[
  {
    "path": "README.md",
    "content": "经过两周左右时间的学习，Flowable基础知识自认为学习完毕，简单构思设计之后，开始上手实践了。由于Flowable官方已经提供了丰富的REST包（和Activiti差不多），基本功能已经满足我们的要求了，个别接口不适用的可自行重写稍作调整即可。<!--more-->\n\nFlowable官方提供的五个war包\n\n<table>\n\t<thead>\n\t\t<tr><th width=\"22%\">starter</th><th>描述</th><th width=\"20%\">在线体验</th></tr>\n\t</thead>\n\t<tbody>\n\t\t<tr><td style=\"color:orange\">flowable-modeler</td><td>让具有建模权限的用户可以创建流程模型、表单、选择表与应用定义。</td><td><a target=\"_blank\" href=\"http://suo.im/6h2yO8\">https://t.cn/A6cjNwAj</a></td></tr>\n    <tr><td style=\"color:orange\">flowable-idm</td><td>身份管理应用。为所有Flowable UI应用提供单点登录认证功能，并且为拥有IDM管理员权限的用户提供了管理用户、组与权限的功能</td><td><a target=\"_blank\" href=\"http://suo.im/5UukYT\">https://t.cn/A6cjCFHc</a></td></tr>\n    <tr><td style=\"color:orange\">flowable-task</td><td>运行时任务应用。提供了启动流程实例、编辑任务表单、完成任务，以及查询流程实例与任务的功能。</td><td><a target=\"_blank\" href=\"http://suo.im/5EHlJk\">https://t.cn/A6cjNLWv</a></td></tr>\n    <tr><td style=\"color:orange\">flowable-admin</td><td>管理应用。让具有管理员权限的用户可以查询BPMN、DMN、Form及Content引擎，并提供了许多选项用于修改流程实例、任务、作业等。管理应用通过REST API连接至引擎，并与Flowable Task应用及Flowable REST应用一同部署。</td><td><a target=\"_blank\" href=\"http://suo.im/620z1q\">https://t.cn/A6cjN4uq</a></td></tr>\n    <tr><td style=\"color:orange\">flowable-rest</td><td>Flowable页面包含的常用REST API</td><td></td></tr>\n\t</tbody>\n</table>\n\n在线体验账号：**admin/123** (<font color=\"red\">个人服务器，配置较低，仅供体验，请勿对应用进行压测</font>)\n\n**先访问idm，使用体验账号登录后，再去访问modeler，task，admin其他模块**\n\n以官方提供的war包为基准，集成以上四个默认页面对应的REST接口。\n\n### 开始集成\n\n#### 后端集成\n\n- maven\n\n~~~xml\n<dependency>\n  <groupId>org.flowable</groupId>\n  <artifactId>flowable-spring-boot-starter-rest</artifactId>\n  <version>${flowable.version}</version>\n</dependency>\n<!-- flowable UI集成 -->\n<dependency>\n  <groupId>org.flowable</groupId>\n  <artifactId>flowable-ui-modeler-conf</artifactId>\n  <version>${flowable.version}</version>\n</dependency>\n<dependency>\n  <groupId>org.flowable</groupId>\n  <artifactId>flowable-ui-task-conf</artifactId>\n  <version>${flowable.version}</version>\n</dependency>\n<dependency>\n  <groupId>org.flowable</groupId>\n  <artifactId>flowable-ui-admin-conf</artifactId>\n  <version>${flowable.version}</version>\n</dependency>\n<dependency>\n  <groupId>org.flowable</groupId>\n  <artifactId>flowable-ui-idm-conf</artifactId>\n  <version>${flowable.version}</version>\n</dependency>\n~~~\n\n- gradle\n\n~~~groovy\ncompile group: 'org.flowable', name: 'flowable-spring-boot-starter-rest', version:'6.4.1'\ncompile group: 'org.flowable', name: 'flowable-ui-modeler-conf', version:'6.4.1'\ncompile group: 'org.flowable', name: 'flowable-ui-task-conf', version:'6.4.1'\ncompile group: 'org.flowable', name: 'flowable-ui-admin-conf', version:'6.4.1'\ncompile group: 'org.flowable', name: 'flowable-ui-idm-conf', version:'6.4.1'\n~~~\n\n**注：** \n\n> flowable-ui-xxx-conf: UI独立于业务外的配置\n> flowable-ui-xxx-logic: UI的业务逻辑\n> flowable-ui-xxx-rest: 提供常用的操作REST API\n\n以上就是集成Flowable UI的基础包了。\n\n由于flowable-ui-xxx-conf中包中，每个中都有对应自己的如`ApplicationConfiguration`等配置类，所以如果用默认配置会出现\n\n~~~\nconflicts with existing, non-compatible bean definition of same name and class\n~~~\n\n类似的错误信息，提示在Spring容器中存在两个相同名称的Bean。\n\n所以不能使用默认的配置类，只能自己去编写配置类，完成flowable-ui-xxx-conf的配置。\n\n- AppDispatcherServletConfiguration\n\n```java\n@Configuration\n@ComponentScan(value = {\n        \"org.flowable.ui.admin.rest\",\n        \"org.flowable.ui.task.rest.runtime\",\n        \"org.flowable.ui.idm.rest.app\",\n        \"org.flowable.ui.common.rest.exception\",\n        \"org.flowable.ui.modeler.rest.app\",\n        \"org.flowable.ui.common.rest\"},\n        excludeFilters = {\n                @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, value = RemoteAccountResource.class),\n                @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, value = StencilSetResource.class),\n                @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, value = EditorUsersResource.class),\n                @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, value = EditorGroupsResource.class)\n        })\n@EnableAsync\npublic class AppDispatcherServletConfiguration implements WebMvcRegistrations\n// 下面类内容省略，可参考org.flowable.ui.xxx.servlet.AppDispatcherServletConfiguration类\n```\n\n<font color=\"red\">**注:**</font> 通过`StencilSetResource`类汉化流程设计器(其实没必要重写类，只需要将stencilset_bpmn.json文件内容汉化即可，重写的目的是以后可以通过此处兼容国际化)\n\n- ApplicationConfiguration\n\n~~~java\n@Configuration\n@EnableConfigurationProperties({FlowableIdmAppProperties.class, FlowableModelerAppProperties.class, FlowableAdminAppProperties.class})\n@ComponentScan(\n    basePackages = {\n        \"org.flowable.ui.admin.repository\",\n        \"org.flowable.ui.admin.service\",\n        \"org.flowable.ui.task.model.component\",\n        \"org.flowable.ui.task.service.runtime\",\n        \"org.flowable.ui.task.service.debugger\",\n        \"org.flowable.ui.idm.conf\",\n        \"org.flowable.ui.idm.security\",\n        \"org.flowable.ui.idm.service\",\n        \"org.flowable.ui.modeler.repository\",\n        \"org.flowable.ui.modeler.service\",\n        \"org.flowable.ui.common.filter\",\n        \"org.flowable.ui.common.service\",\n        \"org.flowable.ui.common.repository\",\n        \"org.flowable.ui.common.security\",\n        \"org.flowable.ui.common.tenant\"\n    },\n    excludeFilters = {\n        @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, value = org.flowable.ui.idm.conf.ApplicationConfiguration.class)\n    }\n)\n~~~\n\n<font color=\"red\">**注:**</font> 通过@ComponentScan注解，扫描需要的包及其接口。\n\n- DatabaseConfiguration\n\n~~~java\n/**\n * 重写flowable-ui-xxx-conf 中的 DatabaseConfiguration 类,\n * 包括:flowable-ui-modeler-conf和flowable-ui-admin-conf 的DatabaseConfiguration\n */\n@Configuration\n@EnableTransactionManagement\npublic class DatabaseConfiguration {\n    private static final Logger LOGGER = LoggerFactory.getLogger(DatabaseConfiguration.class);\n    @Bean\n    public Liquibase modelerLiquibase(DataSource dataSource) {\n        Liquibase liquibase = null;\n        try {\n            DatabaseConnection connection = new JdbcConnection(dataSource.getConnection());\n            Database database = DatabaseFactory.getInstance().findCorrectDatabaseImplementation(connection);\n            database.setDatabaseChangeLogTableName(\"ACT_DE_\" + database.getDatabaseChangeLogTableName());\n            database.setDatabaseChangeLogLockTableName(\"ACT_DE_\" + database.getDatabaseChangeLogLockTableName());\n            liquibase = new Liquibase(\"META-INF/liquibase/flowable-modeler-app-db-changelog.xml\", new ClassLoaderResourceAccessor(), database);\n            liquibase.update(\"flowable\");\n            return liquibase;\n        } catch (Exception e) {\n            throw new InternalServerErrorException(\"Error creating liquibase database\", e);\n        } finally {\n            closeDatabase(liquibase);\n        }\n    }\n    @Bean\n    public Liquibase adminLiquibase(DataSource dataSource) {\n        LOGGER.debug(\"Configuring Liquibase\");\n        Liquibase liquibase = null;\n        try {\n            DatabaseConnection connection = new JdbcConnection(dataSource.getConnection());\n            Database database = DatabaseFactory.getInstance().findCorrectDatabaseImplementation(connection);\n            database.setDatabaseChangeLogTableName(\"ACT_ADM_\" + database.getDatabaseChangeLogTableName());\n            database.setDatabaseChangeLogLockTableName(\"ACT_ADM_\" + database.getDatabaseChangeLogLockTableName());\n            liquibase = new Liquibase(\"META-INF/liquibase/flowable-admin-app-db-changelog.xml\", new ClassLoaderResourceAccessor(), database);\n            liquibase.update(\"flowable\");\n            return liquibase;\n        } catch (Exception e) {\n            throw new InternalServerErrorException(\"Error creating liquibase database\");\n        } finally {\n            closeDatabase(liquibase);\n        }\n    }\n    private void closeDatabase(Liquibase liquibase) {\n        if (liquibase != null) {\n            Database database = liquibase.getDatabase();\n            if (database != null) {\n                try {\n                    database.close();\n                } catch (DatabaseException e) {\n                    LOGGER.warn(\"Error closing database\", e);\n                }\n            }\n        }\n    }\n}\n~~~\n\n<font color=\"red\">**注:**</font> 创建Modeler的模型存储表和Admin首页的服务配置表。\n\n- TaskUserCacheImpl\n\n~~~java\n/**\n * 重写 {@link org.flowable.ui.task.service.idm.UserCacheImpl} 类,避免启动时和 {@link org.flowable.ui.idm.service.UserCacheImpl} 命名冲突\n * Cache containing User objects to prevent too much DB-traffic (users exist separately from the Flowable tables, they need to be fetched afterward one by one to join with those entities).\n * <p>\n *\n * @author Frederik Heremans\n * @author Joram Barrez\n * @author Filip Hrisafov\n */\n@Service\npublic class TaskUserCacheImpl implements UserCache \n~~~\n\n<font color=\"red\">**注:**</font> 重写 {@link org.flowable.ui.task.service.idm.UserCacheImpl} 类,避免启动时和 {@link org.flowable.ui.idm.service.UserCacheImpl} 命名冲突\n\n- org.flowable.ui.admin.service.engine.CmmnTaskService\n\n~~~java\npackage org.flowable.ui.admin.service.engine;\n/**\n * 覆盖jar包中的CmmnTaskService的定义，修改Bean的定义名称,避免和org.flowable.cmmn.api.CmmnTaskService命名冲突\n * Service for invoking Flowable REST services.\n */\n@Service(\"adminCmmnTaskService\")\npublic class CmmnTaskService \n~~~\n\n由于flowable官方提供的jar包导致的冲突问题解决完毕之后，以下是application.yml中需要对Flowable做的配置，其他如数据源相关配置省略，此处不再累述。\n\n~~~yml\nflowable:\n  labelFontName: 宋体\n  activityFontName: 宋体\n  annotationFontName: 宋体\n  rest:\n    app:\n      authentication-mode: verify-privilege\n  process:\n    definition-cache-limit: 1\n  idm:\n    app:\n      admin:\n        password: test\n        user-id: admin\n        first-name: admin\n        last-name: admin\n  common:\n    app:\n      role-prefix:\n      idm-url: http://localhost:${server.port}/${spring.application.name}/idm\n  xml:\n    encoding: UTF-8\n  modeler:\n    app:\n      rest-enabled: true\n  admin:\n    app:\n      security:\n        encryption:\n          credentials-secret-spec: 9FGl73ngxcOoJvmL\n          credentials-i-v-spec: j8kdO2hejA9lKmm6\n      server-config:\n        app:\n          context-root: ${spring.application.name}\n          password: test\n          server-address: http://localhost\n          user-name: admin\n          port: ${server.port}\n          rest-root: app-api\n          name: Flowable App app\n          description: Flowable App REST config\n        process:\n          context-root: ${spring.application.name}\n          server-address: http://localhost\n          password: test\n          user-name: admin\n          rest-root: process-api\n          port: ${server.port}\n          name: Flowable Process app\n          description: Flowable Process REST config\n        form:\n          context-root: ${spring.application.name}\n          server-address: http://localhost\n          password: test\n          user-name: admin\n          port: ${server.port}\n          rest-root: form-api\n          name: Flowable Form app\n          description: Flowable Form REST config\n        dmn:\n          context-root: ${spring.application.name}\n          server-address: http://localhost\n          password: test\n          user-name: admin\n          port: ${server.port}\n          rest-root: dmn-api\n          name: Flowable DMN app\n          description: Flowable DMN REST config\n        cmmn:\n          context-root: ${spring.application.name}\n          password: test\n          server-address: http://localhost\n          user-name: admin\n          port: ${server.port}\n          rest-root: cmmn-api\n          name: Flowable CMMN app\n          description: Flowable CMMN REST config\n        content:\n          context-root: ${spring.application.name}\n          server-address: http://localhost\n          password: test\n          user-name: admin\n          rest-root: content-api\n          port: ${server.port}\n          name: Flowable Content app\n          description: Flowable Content REST config\n  database-schema-update: true\nmanagement:\n  endpoint:\n    health:\n      roles: access-admin\n      show-details: when_authorized\n  endpoints:\n    jmx:\n      unique-names: true\n# MyBatis配置比较重要，手动去扫描Flowable默认的Mapper.xml，以及设置字段类型\nmybatis:\n  mapper-locations:\n    - classpath:/META-INF/admin-mybatis-mappings/*.xml\n    - classpath:/META-INF/modeler-mybatis-mappings/*.xml\n  configuration-properties:\n    prefix:\n    boolValue: TRUE\n    blobType: BLOB\n~~~\n\n至此后端集成完毕。\n\n#### 集成思路出现偏差\n\n一开始准备将官方提供的页面集成到后端工程来，但是由于modeler页面我是直接放到static目录下的，而其他三个页面只能自己建目录存放（idm, admin, task），导致访问modeler时是以后端项目请求路径为根访问路径的，在modeler请求后端接口时，请求路径没有问题；可访问idm、admin、task时，则必须加上idm/路径，导致请求后端接口时，不管将前端请求后端的路径改为相对路径还是绝对路径，最终请求路径都存在问题。此处花费时间较多。下面会讲讲新的页面集成方式。\n\n#### Flowable与SpringBoot版本坑\n\n`flowable-ui-modeler-conf`中`AppDispatcherServletConfiguration`配置类，实现了`WebMvcRegistrations`接口，SpringBoot1.x中，WebMvcRegistrations在`spring-boot-autoconfigure`中的web包下，而在SpringBoot2.x中，WebMvcRegistrations被移到web.servlet下了，所以在使用默认类时，SpringBoot版本必须是2.x。\n\n#### Flowable官方包冲突\n\n由于是根据flowable-modeler、flowable-idm、flowable-task、flowable-admin来集成的，所以后端基础包也是需要这对应的四个，故直接集成了flowable-ui-modeler-conf、flowable-ui-idm-conf、flowable-ui-task-conf、flowable-ui-admin-conf，但是由于这四个包中存在各自的自动配置类，而且在modeler和admin中，自动配置类又和他自己的业务逻辑有关联，而且存在多个类命名相同的Spring Bean，导致Spring上下文由于出现相同名称的Bean而初始化失败，但是默认配置有些又不能不用，最终的解决办法就是去除原来所有的默认配置，将冲突的通过@ComponentScan的excludeFilters属性移除掉，然后自己去自定义配置。\n\n#### 登录权限问题\n\nflowable-ui-modeler-conf、flowable-ui-idm-conf、flowable-ui-task-conf、flowable-ui-admin-conf这四个包中都存在SecurityConfiguration配置类，顾名思义是安全配置，但是在集成的过程中，modeler-conf其实我们希望的是以idm的登录为主，其他模块自己的安全校验配置不需要，但是实际上由于其他模块存在安全配置以及默认的拦截器，导致idm自己的安全验证不能通过。解决方式和上面一样，通过包扫描路径，只扫描自己需要的包路径，而有影响的包要么移除掉，要么自己去实现其中的配置。\n\n### 页面集成\n\n页面集成一开始采用的是集成到后端工程，以后开发自己的页面时，也可直接调用集成好的流程设计器，但是由于其他模块的页面存在问题，故暂时放弃掉这种集成方式，采用Nginx来部署前端，正好满足前后端分离架构。\n\n- Nginx配置\n\n~~~\nserver {\n        listen 8081;\n        server_name flowable_ui;\n        location / {\n            root /user/local/nginx/flowable-ui;\n            index index.html index.htm;\n        }\n        location /flowable_idm {\n            proxy_pass http://localhost:8080/flowable;\n            proxy_cookie_path  /flowable  /flowable_idm;\n        }\n        location /flowable_task {\n            proxy_pass http://localhost:8080/flowable;\n            proxy_cookie_path  /flowable  /flowable_task;\n        }\n        location /flowable_admin {\n            proxy_pass http://localhost:8080/flowable;\n            proxy_cookie_path  /flowable  /flowable_admin;\n        }\n        location /flowable_modeler {\n            proxy_pass http://localhost:8080/flowable;\n            proxy_cookie_path  /flowable  /flowable_modeler;\n        }\n}\n~~~\n\n<font color=\"red\">**注:**</font> 其实可以通过Nginx将静态资源和动态资源分开解析处理即可，但是我这边尝试的过程中有问题，只能采用简单粗暴的方式了。\n\n然后在flowable-ui目录下新建modeler、idm、task、admin目录，将flowable-modeler.war、flowable-idm.war、flowable-task.war、flowable-admin.war中的flowable-xxx/WEB-INF/classes/static下的内容分别复制到对应目录下，此时通过http://localhost:8086/modeler...可看到对应的页面，但是由于动静资源路径一致，导致请求不能转发到后端，所以需要对动态请求和静态资源请求做区分，则需要修改官方页面源码，增加统一的请求路径前缀。\n\n![flowable-ui](https://upload-images.jianshu.io/upload_images/5688362-85e60b8de37aca10.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)\n\n统一请求路径修改：\n\n在modeler/scripts/app-cfg.js文件中，修改contextRoot为flowable_modeler，与静态资源访问路径区分开。\n\n~~~js\n'use strict';\nvar FLOWABLE = FLOWABLE || {};\nvar pathname = window.location.pathname.replace(/^(\\/[^\\/]*)(\\/.*)?$/, '$1').replace(/\\/$/, '');\nFLOWABLE.CONFIG = {\n\t'onPremise' : true,\n\t'contextRoot' : \"/flowable_modeler\",\n\t'webContextRoot' : pathname,\n\t'datesLocalization' : false\n};\n~~~\n\n在idm/scripts/app-cfg.js文件中，修改contextRoot为flowable_idm，与静态资源访问路径区分开。\n\n```js\n'use strict';\nvar FLOWABLE = FLOWABLE || {};\nvar pathname = window.location.pathname.replace(/^(\\/[^\\/]*)(\\/.*)?$/, '$1').replace(/\\/$/, '');\nFLOWABLE.CONFIG = {\n\t'onPremise' : true,\n\t'contextRoot' : \"/flowable_idm\",\n\t'webContextRoot' : pathname,\n\t'datesLocalization' : false\n};\n```\n\n在task/scripts/app-cfg.js文件中，修改contextRoot为flowable_task，与静态资源访问路径区分开。\n\n```js\n'use strict';\nvar FLOWABLE = FLOWABLE || {};\nvar pathname = window.location.pathname.replace(/^(\\/[^\\/]*)(\\/.*)?$/, '$1').replace(/\\/$/, '');\nFLOWABLE.CONFIG = {\n\t'onPremise' : true,\n\t'contextRoot' : \"/flowable_task\",\n\t'webContextRoot' : pathname,\n\t'datesLocalization' : false\n};\n```\n\nadmin和其他的不一样，所以我作为一个后端人员修改前端，采取的方式是在admin/scripts/config.js文件中，增加上面类似配置。\n\n~~~js\nFlowableAdmin.webContextRoot = '/flowable_admin';\n~~~\n\n然后通过开发工具，给所有的REST请求的增加`FlowableAdmin.webContextRoot + `前缀。\n\n如：\n\n~~~js\nurl: '/app/\n~~~\n\n替换为\n\n~~~js\nurl: FlowableAdmin.webContextRoot + '/app/\n~~~\n\n其他非这种格式的URL，可自行手动修改。\n\n至此前后端基本集成完毕。\n\n执行后端SpringBoot启动类，启动后端服务。\n\n启动Nginx。\n\n此时通过以下四个链接，即可访问Flowable官方提供的四个操作页面，不过在第一次访问时，由于没有登录，会跳转到登录页面，在后端工程初次启动时，会初始化两个账号，可通过`ACT_ID_USER`表查询用户名密码。\n\n> http://localhost:8081/idm/\n\n![flowable_idm](https://artislong.oss-cn-hangzhou.aliyuncs.com/images/flowable/flowable_idm.png)\n\n> http://localhost:8081/modeler/\n\n![flowable_modeler](https://artislong.oss-cn-hangzhou.aliyuncs.com/images/flowable/flowable_modeler.png)\n\n> http://localhost:8081/task/\n\n![flowable_task](https://artislong.oss-cn-hangzhou.aliyuncs.com/images/flowable/flowable_task.png)\n\n> http://localhost:8081/admin/\n\n![flowable_admin](https://artislong.oss-cn-hangzhou.aliyuncs.com/images/flowable/flowable_admin.png)\n\n------\n\n关注我的微信公众号：FramePower\n我会不定期发布相关技术积累，欢迎对技术有追求、志同道合的朋友加入，一起学习成长！\n\n------\n\n![微信公众号1](https://artislong.oss-cn-hangzhou.aliyuncs.com/images/%E5%BE%AE%E4%BF%A1%E5%85%AC%E4%BC%97%E5%8F%B7/%E5%BE%AE%E4%BF%A1%E5%85%AC%E4%BC%97%E5%8F%B71.png)\n\n"
  },
  {
    "path": "SECURITY.md",
    "content": "# Security Policy\n\n## Supported Versions\n\nUse this section to tell people about which versions of your project are\ncurrently being supported with security updates.\n\n| Version | Supported          |\n| ------- | ------------------ |\n| 5.1.x   | :white_check_mark: |\n| 5.0.x   | :x:                |\n| 4.0.x   | :white_check_mark: |\n| < 4.0   | :x:                |\n\n## Reporting a Vulnerability\n\nUse this section to tell people how to report a vulnerability.\n\nTell them where to go, how often they can expect to get an update on a\nreported vulnerability, what to expect if the vulnerability is accepted or\ndeclined, etc.\n"
  },
  {
    "path": "flowable-ui/.gitignore",
    "content": "# Created by .ignore support plugin (hsz.mobi)\r"
  },
  {
    "path": "flowable-ui/.gradle/4.10.3/gc.properties",
    "content": ""
  },
  {
    "path": "flowable-ui/.gradle/buildOutputCleanup/cache.properties",
    "content": "#Thu Jun 27 00:31:13 CST 2019\ngradle.version=4.10.3\n"
  },
  {
    "path": "flowable-ui/README.md",
    "content": ""
  },
  {
    "path": "flowable-ui/build.gradle",
    "content": "apply plugin: 'java'\napply plugin: 'maven'\n\ngroup = 'flowable-modeler-study'\nversion = '1.0-SNAPSHOT'\n\ndescription = \"\"\"\"\"\"\n\nsourceCompatibility = 1.5\ntargetCompatibility = 1.5\ntasks.withType(JavaCompile) {\n\toptions.encoding = 'UTF-8'\n}\n\n\n\nrepositories {\n        \n     maven { url \"http://maven.aliyun.com/nexus/content/groups/public\" }\n}\ndependencies {\n    compile group: 'org.flowable', name: 'flowable-spring-boot-starter-rest', version:'6.4.1'\n    compile group: 'org.springframework.boot', name: 'spring-boot-starter-web', version:'2.1.3.RELEASE'\n    compile group: 'org.mybatis.spring.boot', name: 'mybatis-spring-boot-starter', version:'1.3.1'\n    compile group: 'log4j', name: 'log4j', version:'1.2.17'\n    compile group: 'com.alibaba', name: 'fastjson', version:'1.2.46'\n    compile(group: 'mysql', name: 'mysql-connector-java', version:'5.1.47') {\nexclude(module: 'protobuf-java')\n    }\n    compile group: 'com.alibaba', name: 'druid-spring-boot-starter', version:'1.1.10'\n    compile group: 'org.flowable', name: 'flowable-ui-modeler-conf', version:'6.4.1'\n    compile group: 'org.flowable', name: 'flowable-ui-task-conf', version:'6.4.1'\n    compile group: 'org.flowable', name: 'flowable-ui-admin-conf', version:'6.4.1'\n    compile group: 'org.flowable', name: 'flowable-ui-idm-conf', version:'6.4.1'\n    compile group: 'com.spring4all', name: 'swagger-spring-boot-starter', version:'1.9.0.RELEASE'\n    compile group: 'org.projectlombok', name: 'lombok', version:'1.18.6'\n    testCompile group: 'org.springframework.boot', name: 'spring-boot-starter-test', version:'2.1.3.RELEASE'\n}\n"
  },
  {
    "path": "flowable-ui/gradle/wrapper/gradle-wrapper.properties",
    "content": "distributionBase=GRADLE_USER_HOME\ndistributionPath=wrapper/dists\ndistributionUrl=https\\://services.gradle.org/distributions/gradle-4.10.3-bin.zip\nzipStoreBase=GRADLE_USER_HOME\nzipStorePath=wrapper/dists\n"
  },
  {
    "path": "flowable-ui/gradlew",
    "content": "#!/usr/bin/env sh\n\n##############################################################################\n##\n##  Gradle start up script for UN*X\n##\n##############################################################################\n\n# Attempt to set APP_HOME\n# Resolve links: $0 may be a link\nPRG=\"$0\"\n# Need this for relative symlinks.\nwhile [ -h \"$PRG\" ] ; do\n    ls=`ls -ld \"$PRG\"`\n    link=`expr \"$ls\" : '.*-> \\(.*\\)$'`\n    if expr \"$link\" : '/.*' > /dev/null; then\n        PRG=\"$link\"\n    else\n        PRG=`dirname \"$PRG\"`\"/$link\"\n    fi\ndone\nSAVED=\"`pwd`\"\ncd \"`dirname \\\"$PRG\\\"`/\" >/dev/null\nAPP_HOME=\"`pwd -P`\"\ncd \"$SAVED\" >/dev/null\n\nAPP_NAME=\"Gradle\"\nAPP_BASE_NAME=`basename \"$0\"`\n\n# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.\nDEFAULT_JVM_OPTS=\"\"\n\n# Use the maximum available, or set MAX_FD != -1 to use that value.\nMAX_FD=\"maximum\"\n\nwarn () {\n    echo \"$*\"\n}\n\ndie () {\n    echo\n    echo \"$*\"\n    echo\n    exit 1\n}\n\n# OS specific support (must be 'true' or 'false').\ncygwin=false\nmsys=false\ndarwin=false\nnonstop=false\ncase \"`uname`\" in\n  CYGWIN* )\n    cygwin=true\n    ;;\n  Darwin* )\n    darwin=true\n    ;;\n  MINGW* )\n    msys=true\n    ;;\n  NONSTOP* )\n    nonstop=true\n    ;;\nesac\n\nCLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar\n\n# Determine the Java command to use to start the JVM.\nif [ -n \"$JAVA_HOME\" ] ; then\n    if [ -x \"$JAVA_HOME/jre/sh/java\" ] ; then\n        # IBM's JDK on AIX uses strange locations for the executables\n        JAVACMD=\"$JAVA_HOME/jre/sh/java\"\n    else\n        JAVACMD=\"$JAVA_HOME/bin/java\"\n    fi\n    if [ ! -x \"$JAVACMD\" ] ; then\n        die \"ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME\n\nPlease set the JAVA_HOME variable in your environment to match the\nlocation of your Java installation.\"\n    fi\nelse\n    JAVACMD=\"java\"\n    which java >/dev/null 2>&1 || die \"ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.\n\nPlease set the JAVA_HOME variable in your environment to match the\nlocation of your Java installation.\"\nfi\n\n# Increase the maximum file descriptors if we can.\nif [ \"$cygwin\" = \"false\" -a \"$darwin\" = \"false\" -a \"$nonstop\" = \"false\" ] ; then\n    MAX_FD_LIMIT=`ulimit -H -n`\n    if [ $? -eq 0 ] ; then\n        if [ \"$MAX_FD\" = \"maximum\" -o \"$MAX_FD\" = \"max\" ] ; then\n            MAX_FD=\"$MAX_FD_LIMIT\"\n        fi\n        ulimit -n $MAX_FD\n        if [ $? -ne 0 ] ; then\n            warn \"Could not set maximum file descriptor limit: $MAX_FD\"\n        fi\n    else\n        warn \"Could not query maximum file descriptor limit: $MAX_FD_LIMIT\"\n    fi\nfi\n\n# For Darwin, add options to specify how the application appears in the dock\nif $darwin; then\n    GRADLE_OPTS=\"$GRADLE_OPTS \\\"-Xdock:name=$APP_NAME\\\" \\\"-Xdock:icon=$APP_HOME/media/gradle.icns\\\"\"\nfi\n\n# For Cygwin, switch paths to Windows format before running java\nif $cygwin ; then\n    APP_HOME=`cygpath --path --mixed \"$APP_HOME\"`\n    CLASSPATH=`cygpath --path --mixed \"$CLASSPATH\"`\n    JAVACMD=`cygpath --unix \"$JAVACMD\"`\n\n    # We build the pattern for arguments to be converted via cygpath\n    ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`\n    SEP=\"\"\n    for dir in $ROOTDIRSRAW ; do\n        ROOTDIRS=\"$ROOTDIRS$SEP$dir\"\n        SEP=\"|\"\n    done\n    OURCYGPATTERN=\"(^($ROOTDIRS))\"\n    # Add a user-defined pattern to the cygpath arguments\n    if [ \"$GRADLE_CYGPATTERN\" != \"\" ] ; then\n        OURCYGPATTERN=\"$OURCYGPATTERN|($GRADLE_CYGPATTERN)\"\n    fi\n    # Now convert the arguments - kludge to limit ourselves to /bin/sh\n    i=0\n    for arg in \"$@\" ; do\n        CHECK=`echo \"$arg\"|egrep -c \"$OURCYGPATTERN\" -`\n        CHECK2=`echo \"$arg\"|egrep -c \"^-\"`                                 ### Determine if an option\n\n        if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then                    ### Added a condition\n            eval `echo args$i`=`cygpath --path --ignore --mixed \"$arg\"`\n        else\n            eval `echo args$i`=\"\\\"$arg\\\"\"\n        fi\n        i=$((i+1))\n    done\n    case $i in\n        (0) set -- ;;\n        (1) set -- \"$args0\" ;;\n        (2) set -- \"$args0\" \"$args1\" ;;\n        (3) set -- \"$args0\" \"$args1\" \"$args2\" ;;\n        (4) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" ;;\n        (5) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" ;;\n        (6) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" ;;\n        (7) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" \"$args6\" ;;\n        (8) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" \"$args6\" \"$args7\" ;;\n        (9) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" \"$args6\" \"$args7\" \"$args8\" ;;\n    esac\nfi\n\n# Escape application args\nsave () {\n    for i do printf %s\\\\n \"$i\" | sed \"s/'/'\\\\\\\\''/g;1s/^/'/;\\$s/\\$/' \\\\\\\\/\" ; done\n    echo \" \"\n}\nAPP_ARGS=$(save \"$@\")\n\n# Collect all arguments for the java command, following the shell quoting and substitution rules\neval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS \"\\\"-Dorg.gradle.appname=$APP_BASE_NAME\\\"\" -classpath \"\\\"$CLASSPATH\\\"\" org.gradle.wrapper.GradleWrapperMain \"$APP_ARGS\"\n\n# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong\nif [ \"$(uname)\" = \"Darwin\" ] && [ \"$HOME\" = \"$PWD\" ]; then\n  cd \"$(dirname \"$0\")\"\nfi\n\nexec \"$JAVACMD\" \"$@\"\n"
  },
  {
    "path": "flowable-ui/gradlew.bat",
    "content": "@if \"%DEBUG%\" == \"\" @echo off\n@rem ##########################################################################\n@rem\n@rem  Gradle startup script for Windows\n@rem\n@rem ##########################################################################\n\n@rem Set local scope for the variables with windows NT shell\nif \"%OS%\"==\"Windows_NT\" setlocal\n\nset DIRNAME=%~dp0\nif \"%DIRNAME%\" == \"\" set DIRNAME=.\nset APP_BASE_NAME=%~n0\nset APP_HOME=%DIRNAME%\n\n@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.\nset DEFAULT_JVM_OPTS=\n\n@rem Find java.exe\nif defined JAVA_HOME goto findJavaFromJavaHome\n\nset JAVA_EXE=java.exe\n%JAVA_EXE% -version >NUL 2>&1\nif \"%ERRORLEVEL%\" == \"0\" goto init\n\necho.\necho ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.\necho.\necho Please set the JAVA_HOME variable in your environment to match the\necho location of your Java installation.\n\ngoto fail\n\n:findJavaFromJavaHome\nset JAVA_HOME=%JAVA_HOME:\"=%\nset JAVA_EXE=%JAVA_HOME%/bin/java.exe\n\nif exist \"%JAVA_EXE%\" goto init\n\necho.\necho ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%\necho.\necho Please set the JAVA_HOME variable in your environment to match the\necho location of your Java installation.\n\ngoto fail\n\n:init\n@rem Get command-line arguments, handling Windows variants\n\nif not \"%OS%\" == \"Windows_NT\" goto win9xME_args\n\n:win9xME_args\n@rem Slurp the command line arguments.\nset CMD_LINE_ARGS=\nset _SKIP=2\n\n:win9xME_args_slurp\nif \"x%~1\" == \"x\" goto execute\n\nset CMD_LINE_ARGS=%*\n\n:execute\n@rem Setup the command line\n\nset CLASSPATH=%APP_HOME%\\gradle\\wrapper\\gradle-wrapper.jar\n\n@rem Execute Gradle\n\"%JAVA_EXE%\" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% \"-Dorg.gradle.appname=%APP_BASE_NAME%\" -classpath \"%CLASSPATH%\" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%\n\n:end\n@rem End local scope for the variables with windows NT shell\nif \"%ERRORLEVEL%\"==\"0\" goto mainEnd\n\n:fail\nrem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of\nrem the _cmd.exe /c_ return code!\nif  not \"\" == \"%GRADLE_EXIT_CONSOLE%\" exit 1\nexit /b 1\n\n:mainEnd\nif \"%OS%\"==\"Windows_NT\" endlocal\n\n:omega\n"
  },
  {
    "path": "flowable-ui/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\"\n         xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n    <modelVersion>4.0.0</modelVersion>\n    <parent>\n        <groupId>org.springframework.boot</groupId>\n        <artifactId>spring-boot-starter-parent</artifactId>\n        <version>2.1.3.RELEASE</version>\n    </parent>\n    <groupId>com.github.flowable</groupId>\n    <artifactId>flowable-ui</artifactId>\n    <version>1.0-SNAPSHOT</version>\n    <properties>\n        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>\n        <java.version>1.8</java.version>\n        <mysql.version>8.0.16</mysql.version>\n        <druid.springboot.version>1.1.10</druid.springboot.version>\n        <mybatis-spring-boot>1.3.1</mybatis-spring-boot>\n        <flowable.version>6.4.1</flowable.version>\n    </properties>\n    <dependencies>\n        <dependency>\n            <groupId>org.flowable</groupId>\n            <artifactId>flowable-spring-boot-starter-rest</artifactId>\n            <version>${flowable.version}</version>\n        </dependency>\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-web</artifactId>\n        </dependency>\n        <!-- Spring Boot Test 依赖 -->\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-test</artifactId>\n            <scope>test</scope>\n        </dependency>\n        <!-- Spring Boot Mybatis 依赖 -->\n        <dependency>\n            <groupId>org.mybatis.spring.boot</groupId>\n            <artifactId>mybatis-spring-boot-starter</artifactId>\n            <version>${mybatis-spring-boot}</version>\n        </dependency>\n        <dependency>\n            <groupId>log4j</groupId>\n            <artifactId>log4j</artifactId>\n            <version>1.2.17</version>\n        </dependency>\n        <dependency>\n            <groupId>com.alibaba</groupId>\n            <artifactId>fastjson</artifactId>\n            <version>1.2.46</version>\n        </dependency>\n        <dependency>\n            <groupId>mysql</groupId>\n            <artifactId>mysql-connector-java</artifactId>\n            <version>${mysql.version}</version>\n        </dependency>\n        <!-- 数据源配置 -->\n        <dependency>\n            <groupId>com.alibaba</groupId>\n            <artifactId>druid-spring-boot-starter</artifactId>\n            <version>1.1.10</version>\n        </dependency>\n        <!-- flowable UI集成 -->\n        <dependency>\n            <groupId>org.flowable</groupId>\n            <artifactId>flowable-ui-modeler-conf</artifactId>\n            <version>${flowable.version}</version>\n        </dependency>\n        <dependency>\n            <groupId>org.flowable</groupId>\n            <artifactId>flowable-ui-task-conf</artifactId>\n            <version>${flowable.version}</version>\n        </dependency>\n        <dependency>\n            <groupId>org.flowable</groupId>\n            <artifactId>flowable-ui-admin-conf</artifactId>\n            <version>${flowable.version}</version>\n        </dependency>\n        <dependency>\n            <groupId>org.flowable</groupId>\n            <artifactId>flowable-ui-idm-conf</artifactId>\n            <version>${flowable.version}</version>\n        </dependency>\n\n\n        <dependency>\n            <groupId>com.spring4all</groupId>\n            <artifactId>swagger-spring-boot-starter</artifactId>\n            <version>1.9.0.RELEASE</version>\n        </dependency>\n        <dependency>\n            <groupId>org.projectlombok</groupId>\n            <artifactId>lombok</artifactId>\n        </dependency>\n    </dependencies>\n    <build>\n        <finalName>flowable</finalName>\n        <resources>\n            <resource>\n                <directory>${project.basedir}/src/main/java</directory>\n                <includes>\n                    <include>**/*.xml</include>\n                    <include>**/*.ftl</include>\n                </includes>\n            </resource>\n            <resource>\n                <directory>${project.basedir}/src/main/resources</directory>\n            </resource>\n        </resources>\n        <plugins>\n            <plugin>\n                <groupId>org.springframework.boot</groupId>\n                <artifactId>spring-boot-maven-plugin</artifactId>\n            </plugin>\n            <plugin>\n                <artifactId>maven-resources-plugin</artifactId>\n                <configuration>\n                    <encoding>utf-8</encoding>\n                    <useDefaultDelimiters>true</useDefaultDelimiters>\n                </configuration>\n            </plugin>\n        </plugins>\n    </build>\n</project>"
  },
  {
    "path": "flowable-ui/settings.gradle",
    "content": "rootProject.name = 'flowable-modeler-study'\n"
  },
  {
    "path": "flowable-ui/src/main/java/com/github/flowable/FlowableApplication.java",
    "content": "package com.github.flowable;\n\nimport com.spring4all.swagger.EnableSwagger2Doc;\nimport org.flowable.spring.boot.app.AppEngineRestConfiguration;\nimport org.springframework.beans.factory.config.BeanDefinition;\nimport org.springframework.beans.factory.support.BeanDefinitionRegistry;\nimport org.springframework.beans.factory.support.BeanNameGenerator;\nimport org.springframework.beans.factory.support.DefaultBeanNameGenerator;\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\nimport org.springframework.context.annotation.ComponentScan;\nimport org.springframework.context.annotation.Import;\n\n/**\n * @Description:\n * @Author: Bruce.liu\n * @Since:9:18 2019/1/19\n */\n@EnableSwagger2Doc\n@SpringBootApplication\n@ComponentScan(nameGenerator = DefaultBeanNameGenerator.class)\npublic class FlowableApplication {\n\n    public static void main(String[] args) {\n        SpringApplication.run(FlowableApplication.class, args);\n    }\n\n    public static class SpringBeanNameGenerator implements BeanNameGenerator {\n        @Override\n        public String generateBeanName(BeanDefinition definition, BeanDefinitionRegistry registry) {\n            return null;\n        }\n    }\n}\n"
  },
  {
    "path": "flowable-ui/src/main/java/com/github/flowable/config/AppDispatcherServletConfiguration.java",
    "content": "package com.github.flowable.config;\n\nimport org.flowable.ui.common.rest.idm.remote.RemoteAccountResource;\nimport org.flowable.ui.modeler.rest.app.EditorGroupsResource;\nimport org.flowable.ui.modeler.rest.app.EditorUsersResource;\nimport org.flowable.ui.modeler.rest.app.StencilSetResource;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.boot.autoconfigure.web.servlet.WebMvcRegistrations;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.ComponentScan;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.context.annotation.FilterType;\nimport org.springframework.scheduling.annotation.EnableAsync;\nimport org.springframework.web.servlet.i18n.LocaleChangeInterceptor;\nimport org.springframework.web.servlet.i18n.SessionLocaleResolver;\nimport org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;\n\n/**\n * 重写flowable-ui-xxx-conf 中的rest配置类\n */\n@Configuration\n@ComponentScan(value = {\n        \"org.flowable.app.rest\",\n        \"org.flowable.ui.admin.rest\",\n        \"org.flowable.ui.task.rest.runtime\",\n        \"org.flowable.ui.idm.rest.app\",\n        \"org.flowable.ui.common.rest.exception\",\n        \"org.flowable.ui.modeler.rest.app\",\n        \"org.flowable.ui.common.rest\"},\n        excludeFilters = {\n                @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, value = RemoteAccountResource.class),\n                @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, value = StencilSetResource.class),\n                @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, value = EditorUsersResource.class),\n                @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, value = EditorGroupsResource.class)\n        })\n@EnableAsync\npublic class AppDispatcherServletConfiguration implements WebMvcRegistrations{\n\n    private static final Logger LOGGER = LoggerFactory.getLogger(AppDispatcherServletConfiguration.class);\n\n    @Bean\n    public SessionLocaleResolver localeResolver() {\n        return new SessionLocaleResolver();\n    }\n\n    @Bean\n    public LocaleChangeInterceptor localeChangeInterceptor() {\n        LOGGER.debug(\"Configuring localeChangeInterceptor\");\n        LocaleChangeInterceptor localeChangeInterceptor = new LocaleChangeInterceptor();\n        localeChangeInterceptor.setParamName(\"language\");\n        return localeChangeInterceptor;\n    }\n\n    @Override\n    public RequestMappingHandlerMapping getRequestMappingHandlerMapping() {\n        LOGGER.debug(\"Creating requestMappingHandlerMapping\");\n        RequestMappingHandlerMapping requestMappingHandlerMapping = new RequestMappingHandlerMapping();\n        requestMappingHandlerMapping.setUseSuffixPatternMatch(false);\n        requestMappingHandlerMapping.setRemoveSemicolonContent(false);\n        Object[] interceptors = {localeChangeInterceptor()};\n        requestMappingHandlerMapping.setInterceptors(interceptors);\n        return requestMappingHandlerMapping;\n    }\n\n}\n"
  },
  {
    "path": "flowable-ui/src/main/java/com/github/flowable/config/ApplicationConfiguration.java",
    "content": "package com.github.flowable.config;\n\nimport org.flowable.app.rest.AppRestResponseFactory;\nimport org.flowable.ui.admin.properties.FlowableAdminAppProperties;\nimport org.flowable.ui.idm.properties.FlowableIdmAppProperties;\nimport org.flowable.ui.idm.servlet.ApiDispatcherServletConfiguration;\nimport org.flowable.ui.modeler.properties.FlowableModelerAppProperties;\nimport org.springframework.boot.context.properties.EnableConfigurationProperties;\nimport org.springframework.boot.web.servlet.ServletRegistrationBean;\nimport org.springframework.context.ApplicationContext;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.ComponentScan;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.context.annotation.FilterType;\nimport org.springframework.web.context.support.AnnotationConfigWebApplicationContext;\nimport org.springframework.web.servlet.DispatcherServlet;\n\n\n/**\n * 重写flowable-ui-xxx-conf 中的rest基础服务配置类\n */\n@Configuration\n@EnableConfigurationProperties({FlowableIdmAppProperties.class, FlowableModelerAppProperties.class, FlowableAdminAppProperties.class})\n@ComponentScan(\n    basePackages = {\n        \"org.flowable.ui.admin.repository\",\n        \"org.flowable.ui.admin.service\",\n        \"org.flowable.ui.task.model.component\",\n        \"org.flowable.ui.task.service.runtime\",\n        \"org.flowable.ui.task.service.debugger\",\n        \"org.flowable.ui.idm.conf\",\n        \"org.flowable.ui.idm.security\",\n        \"org.flowable.ui.idm.service\",\n        \"org.flowable.ui.modeler.repository\",\n        \"org.flowable.ui.modeler.service\",\n        \"org.flowable.ui.common.filter\",\n        \"org.flowable.ui.common.service\",\n        \"org.flowable.ui.common.repository\",\n        \"org.flowable.ui.common.security\",\n        \"org.flowable.ui.common.tenant\"\n    },\n    excludeFilters = {\n        @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, value = org.flowable.ui.idm.conf.ApplicationConfiguration.class)\n    }\n)\npublic class ApplicationConfiguration {\n\n\n    @Bean\n    public ServletRegistrationBean apiServlet(ApplicationContext applicationContext) {\n        AnnotationConfigWebApplicationContext dispatcherServletConfiguration = new AnnotationConfigWebApplicationContext();\n        dispatcherServletConfiguration.setParent(applicationContext);\n        dispatcherServletConfiguration.register(ApiDispatcherServletConfiguration.class);\n        DispatcherServlet servlet = new DispatcherServlet(dispatcherServletConfiguration);\n        ServletRegistrationBean registrationBean = new ServletRegistrationBean(servlet, \"/api/*\");\n        registrationBean.setName(\"Flowable IDM App API Servlet\");\n        registrationBean.setLoadOnStartup(1);\n        registrationBean.setAsyncSupported(true);\n        return registrationBean;\n    }\n\n    @Bean\n    public AppRestResponseFactory appRestResponseFactory() {\n        return new AppRestResponseFactory();\n    }\n}\n"
  },
  {
    "path": "flowable-ui/src/main/java/com/github/flowable/config/DatabaseConfiguration.java",
    "content": "/* Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.github.flowable.config;\n\nimport liquibase.Liquibase;\nimport liquibase.database.Database;\nimport liquibase.database.DatabaseConnection;\nimport liquibase.database.DatabaseFactory;\nimport liquibase.database.jvm.JdbcConnection;\nimport liquibase.exception.DatabaseException;\nimport liquibase.resource.ClassLoaderResourceAccessor;\nimport org.flowable.ui.common.service.exception.InternalServerErrorException;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.transaction.annotation.EnableTransactionManagement;\n\nimport javax.sql.DataSource;\n\n\n/**\n * 重写flowable-ui-xxx-conf 中的 DatabaseConfiguration 类,\n * 包括:flowable-ui-modeler-conf和flowable-ui-admin-conf 的DatabaseConfiguration\n */\n@Configuration\n@EnableTransactionManagement\npublic class DatabaseConfiguration {\n\n    private static final Logger LOGGER = LoggerFactory.getLogger(DatabaseConfiguration.class);\n\n    @Bean\n    public Liquibase modelerLiquibase(DataSource dataSource) {\n        Liquibase liquibase = null;\n        try {\n            DatabaseConnection connection = new JdbcConnection(dataSource.getConnection());\n            Database database = DatabaseFactory.getInstance().findCorrectDatabaseImplementation(connection);\n            database.setDatabaseChangeLogTableName(\"ACT_DE_\" + database.getDatabaseChangeLogTableName());\n            database.setDatabaseChangeLogLockTableName(\"ACT_DE_\" + database.getDatabaseChangeLogLockTableName());\n\n            liquibase = new Liquibase(\"META-INF/liquibase/flowable-modeler-app-db-changelog.xml\", new ClassLoaderResourceAccessor(), database);\n            liquibase.update(\"flowable\");\n            return liquibase;\n        } catch (Exception e) {\n            throw new InternalServerErrorException(\"Error creating liquibase database\", e);\n        } finally {\n            closeDatabase(liquibase);\n        }\n    }\n\n    @Bean\n    public Liquibase adminLiquibase(DataSource dataSource) {\n        LOGGER.debug(\"Configuring Liquibase\");\n\n        Liquibase liquibase = null;\n        try {\n\n            DatabaseConnection connection = new JdbcConnection(dataSource.getConnection());\n            Database database = DatabaseFactory.getInstance().findCorrectDatabaseImplementation(connection);\n            database.setDatabaseChangeLogTableName(\"ACT_ADM_\" + database.getDatabaseChangeLogTableName());\n            database.setDatabaseChangeLogLockTableName(\"ACT_ADM_\" + database.getDatabaseChangeLogLockTableName());\n\n            liquibase = new Liquibase(\"META-INF/liquibase/flowable-admin-app-db-changelog.xml\", new ClassLoaderResourceAccessor(), database);\n            liquibase.update(\"flowable\");\n            return liquibase;\n\n        } catch (Exception e) {\n            throw new InternalServerErrorException(\"Error creating liquibase database\");\n        } finally {\n            closeDatabase(liquibase);\n        }\n    }\n\n    private void closeDatabase(Liquibase liquibase) {\n        if (liquibase != null) {\n            Database database = liquibase.getDatabase();\n            if (database != null) {\n                try {\n                    database.close();\n                } catch (DatabaseException e) {\n                    LOGGER.warn(\"Error closing database\", e);\n                }\n            }\n        }\n    }\n\n}\n"
  },
  {
    "path": "flowable-ui/src/main/java/com/github/flowable/config/TaskUserCacheImpl.java",
    "content": "/**\r * $Id: TaskUserCacheImpl.java,v 1.0 2019-06-25 16:12 chenmin Exp $\r */\rpackage com.github.flowable.config;\r\rimport com.google.common.cache.CacheBuilder;\rimport com.google.common.cache.CacheLoader;\rimport com.google.common.cache.LoadingCache;\rimport com.google.common.util.concurrent.UncheckedExecutionException;\r\rimport java.util.ArrayList;\rimport java.util.Collection;\rimport java.util.concurrent.ExecutionException;\rimport java.util.concurrent.TimeUnit;\r\rimport javax.annotation.PostConstruct;\r\rimport org.flowable.idm.api.User;\rimport org.flowable.ui.common.properties.FlowableCommonAppProperties;\rimport org.flowable.ui.common.service.idm.RemoteIdmService;\rimport org.flowable.ui.task.service.api.UserCache;\rimport org.springframework.beans.factory.annotation.Autowired;\rimport org.springframework.security.authentication.LockedException;\rimport org.springframework.security.core.GrantedAuthority;\rimport org.springframework.security.core.userdetails.UsernameNotFoundException;\rimport org.springframework.stereotype.Service;\r\r/**\r * 重写 {@link org.flowable.ui.task.service.idm.UserCacheImpl} 类,避免启动时和 {@link org.flowable.ui.idm.service.UserCacheImpl} 命名冲突\r * Cache containing User objects to prevent too much DB-traffic (users exist separately from the Flowable tables, they need to be fetched afterward one by one to join with those entities).\r * <p>\r *\r * @author Frederik Heremans\r * @author Joram Barrez\r * @author Filip Hrisafov\r */\r@Service\rpublic class TaskUserCacheImpl implements UserCache {\r\r    @Autowired\r    protected FlowableCommonAppProperties properties;\r\r    @Autowired\r    protected RemoteIdmService remoteIdmService;\r\r    protected LoadingCache<String, CachedUser> userCache;\r\r    @PostConstruct\r    protected void initCache() {\r        FlowableCommonAppProperties.Cache cache = properties.getCacheUsers();\r        long userCacheMaxSize = cache.getMaxSize();\r        long userCacheMaxAge = cache.getMaxAge();\r\r        userCache = CacheBuilder.newBuilder().maximumSize(userCacheMaxSize)\r                .expireAfterAccess(userCacheMaxAge, TimeUnit.SECONDS).recordStats().build(new CacheLoader<String, CachedUser>() {\r\r                    public CachedUser load(final String userId) throws Exception {\r                        User user = remoteIdmService.getUser(userId);\r                        if (user == null) {\r                            throw new UsernameNotFoundException(\"User \" + userId + \" was not found in the database\");\r                        }\r\r                        Collection<GrantedAuthority> grantedAuthorities = new ArrayList<>();\r\r                        return new CachedUser(user, grantedAuthorities);\r                    }\r\r                });\r    }\r\r    @Override\r    public void putUser(String userId, CachedUser cachedUser) {\r        userCache.put(userId, cachedUser);\r    }\r\r    @Override\r    public CachedUser getUser(String userId) {\r        return getUser(userId, false, false, true); // always check validity by default\r    }\r\r    @Override\r    public CachedUser getUser(String userId, boolean throwExceptionOnNotFound, boolean throwExceptionOnInactive, boolean checkValidity) {\r        try {\r            // The cache is a LoadingCache and will fetch the value itself\r            CachedUser cachedUser = userCache.get(userId);\r            return cachedUser;\r\r        } catch (ExecutionException e) {\r            return null;\r        } catch (UncheckedExecutionException uee) {\r\r            // Some magic with the exceptions is needed:\r            // the exceptions like UserNameNotFound and Locked cannot\r            // bubble up, since Spring security will react on them otherwise\r            if (uee.getCause() instanceof RuntimeException) {\r                RuntimeException runtimeException = (RuntimeException) uee.getCause();\r\r                if (runtimeException instanceof UsernameNotFoundException) {\r                    if (throwExceptionOnNotFound) {\r                        throw runtimeException;\r                    } else {\r                        return null;\r                    }\r                }\r\r                if (runtimeException instanceof LockedException) {\r                    if (throwExceptionOnNotFound) {\r                        throw runtimeException;\r                    } else {\r                        return null;\r                    }\r                }\r\r            }\r            throw uee;\r        }\r    }\r\r    @Override\r    public void invalidate(String userId) {\r        userCache.invalidate(userId);\r    }\r}\r"
  },
  {
    "path": "flowable-ui/src/main/java/com/github/flowable/config/WebMvcConfiguration.java",
    "content": "package com.github.flowable.config;\n\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.web.cors.CorsConfiguration;\nimport org.springframework.web.cors.UrlBasedCorsConfigurationSource;\nimport org.springframework.web.filter.CorsFilter;\nimport org.springframework.web.servlet.config.annotation.CorsRegistry;\nimport org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;\nimport org.springframework.web.servlet.config.annotation.WebMvcConfigurer;\n\n@Configuration\npublic class WebMvcConfiguration implements WebMvcConfigurer {\n\n    //跨域配置\n    @Override\n    public void addCorsMappings(CorsRegistry registry) {\n        registry.addMapping(\"/**\")\n                .allowedMethods(\"*\")\n                .allowedOrigins(\"*\")\n                .allowedHeaders(\"*\")\n                .allowCredentials(true);\n    }\n\n    private CorsConfiguration buildConfig() {\n        CorsConfiguration corsConfiguration = new CorsConfiguration();\n        corsConfiguration.addAllowedOrigin(\"*\");\n        corsConfiguration.setAllowCredentials(true);\n        corsConfiguration.addAllowedHeader(\"*\");\n        corsConfiguration.addAllowedMethod(\"*\");\n\n        return corsConfiguration;\n    }\n\n\n    /**\n     * 跨域过滤器\n     *\n     * @return\n     */\n    @Bean\n    public CorsFilter corsFilter() {\n        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();\n        source.registerCorsConfiguration(\"/**\", buildConfig()); // 4\n        return new CorsFilter(source);\n    }\n}\n"
  },
  {
    "path": "flowable-ui/src/main/java/com/github/flowable/rest/ext/EditorGroupsResource.java",
    "content": "/* Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.github.flowable.rest.ext;\n\nimport org.flowable.idm.api.Group;\nimport org.flowable.idm.api.IdmIdentityService;\nimport org.flowable.ui.common.model.GroupRepresentation;\nimport org.flowable.ui.common.model.ResultListDataRepresentation;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.util.StringUtils;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RequestMethod;\nimport org.springframework.web.bind.annotation.RequestParam;\nimport org.springframework.web.bind.annotation.RestController;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\n/**\n * 重写 {@link org.flowable.ui.modeler.rest.app.EditorGroupsResource} 类,直接查库获取用户组列表\n * @author 陈敏\n * @version $Id: EditorGroupsResource.java,v 1.1 2019-06-20 15:00 chenmin Exp $\n * Created on 2019-06-20 15:00\n * My blog： https://www.chenmin.info\n */\n@RestController\n@RequestMapping(\"/app\")\npublic class EditorGroupsResource {\n\n    @Autowired\n    protected IdmIdentityService idmIdentityService;\n\n    @RequestMapping(value = \"/rest/editor-groups\", method = RequestMethod.GET)\n    public ResultListDataRepresentation getGroups(@RequestParam(required = false, value = \"filter\") String filter) {\n        if(!StringUtils.isEmpty(filter)){\n            filter = filter.trim();\n            String sql = \"select * from act_id_group where NAME_ like #{name} limit 10\";\n            filter = \"%\"+filter+\"%\";\n            List<Group> groups = idmIdentityService.createNativeGroupQuery().sql(sql).parameter(\"name\",filter).list();\n            List<GroupRepresentation> result = new ArrayList<>();\n            for (Group group : groups) {\n                result.add(new GroupRepresentation(group));\n            }\n            return new ResultListDataRepresentation(result);\n        }\n        return null;\n    }\n}\n"
  },
  {
    "path": "flowable-ui/src/main/java/com/github/flowable/rest/ext/EditorUsersResource.java",
    "content": "/* Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.github.flowable.rest.ext;\n\nimport org.flowable.engine.ManagementService;\nimport org.flowable.idm.api.IdmIdentityService;\nimport org.flowable.idm.api.User;\nimport org.flowable.ui.common.model.ResultListDataRepresentation;\nimport org.flowable.ui.common.model.UserRepresentation;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.util.StringUtils;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RequestMethod;\nimport org.springframework.web.bind.annotation.RequestParam;\nimport org.springframework.web.bind.annotation.RestController;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\n/**\n * 重写 {@link org.flowable.ui.modeler.rest.app.EditorUsersResource} 类,直接查库获取用户列表\n * @author 陈敏\n * @version $Id: EditorUsersResource.java,v 1.1 2019-06-20 15:01 chenmin Exp $\n * Created on 2019-06-20 15:01\n * My blog： https://www.chenmin.info\n */\n@RestController\n@RequestMapping(\"/app\")\npublic class EditorUsersResource {\n\n    @Autowired\n    protected IdmIdentityService idmIdentityService;\n    @Autowired\n    protected ManagementService managementService;\n\n    @RequestMapping(value = \"/rest/editor-users\", method = RequestMethod.GET)\n    public ResultListDataRepresentation getUsers(@RequestParam(value = \"filter\", required = false) String filter) {\n        if (!StringUtils.isEmpty(filter)) {\n            filter = filter.trim();\n            String sql = \"select * from act_id_user where ID_ like #{id} or LAST_ like #{name} limit 10\";\n            filter = \"%\"+filter+\"%\";\n            List<User> matchingUsers = idmIdentityService.createNativeUserQuery().sql(sql).parameter(\"id\",filter).parameter(\"name\",filter).list();\n            List<UserRepresentation> userRepresentations = new ArrayList<>(matchingUsers.size());\n            for (User user : matchingUsers) {\n                userRepresentations.add(new UserRepresentation(user));\n            }\n            return new ResultListDataRepresentation(userRepresentations);\n        }\n       return null;\n    }\n\n}\n"
  },
  {
    "path": "flowable-ui/src/main/java/com/github/flowable/rest/ext/FlowStencilSetResource.java",
    "content": "package com.github.flowable.rest.ext;\n\nimport com.fasterxml.jackson.databind.JsonNode;\nimport com.fasterxml.jackson.databind.ObjectMapper;\nimport lombok.extern.slf4j.Slf4j;\nimport org.flowable.ui.common.service.exception.InternalServerErrorException;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RequestMethod;\nimport org.springframework.web.bind.annotation.RestController;\n\n/**\n * 扩展流程图在线设计器(汉化) {@link org.flowable.ui.modeler.rest.app.StencilSetResource}\n * @author 陈敏\n * @version $Id: FlowStencilSetResource.java,v 1.1 2019-06-20 15:02 chenmin Exp $\n * Created on 2019-06-20 15:02\n * My blog： https://www.chenmin.info\n */\n@Slf4j\n@RestController\n@RequestMapping(\"/app\")\npublic class FlowStencilSetResource {\n\n    @Autowired\n    protected ObjectMapper objectMapper;\n\n    /**\n     * 汉化流程设计器编辑数据(后续可支持国际化改造)\n     * @return\n     */\n    @RequestMapping(value = \"/rest/stencil-sets/editor\", method = RequestMethod.GET, produces = \"application/json\")\n    public JsonNode getStencilSetForEditor() {\n        try {\n            JsonNode stencilNode = objectMapper.readTree(this.getClass().getClassLoader().getResourceAsStream(\"stencilset/zh/stencilset_bpmn.json\"));\n            return stencilNode;\n        } catch (Exception e) {\n            log.error(\"Error reading bpmn stencil set json\", e);\n            throw new InternalServerErrorException(\"Error reading bpmn stencil set json\");\n        }\n    }\n\n    /**\n     * 汉化流程设计器编辑数据(后续可支持国际化改造)\n     * @return\n     */\n    @RequestMapping(value = \"/rest/stencil-sets/cmmneditor\", method = RequestMethod.GET, produces = \"application/json\")\n    public JsonNode getCmmnStencilSetForEditor() {\n        try {\n            JsonNode stencilNode = objectMapper.readTree(this.getClass().getClassLoader().getResourceAsStream(\"stencilset/zh/stencilset_cmmn.json\"));\n            return stencilNode;\n        } catch (Exception e) {\n            log.error(\"Error reading bpmn stencil set json\", e);\n            throw new InternalServerErrorException(\"Error reading bpmn stencil set json\");\n        }\n    }\n}\n"
  },
  {
    "path": "flowable-ui/src/main/java/org/flowable/ui/admin/service/engine/CmmnTaskService.java",
    "content": "/* Licensed under the Apache License, Version 2.0 (the \"License\");\r * you may not use this file except in compliance with the License.\r * You may obtain a copy of the License at\r *\r *      http://www.apache.org/licenses/LICENSE-2.0\r *\r * Unless required by applicable law or agreed to in writing, software\r * distributed under the License is distributed on an \"AS IS\" BASIS,\r * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r * See the License for the specific language governing permissions and\r * limitations under the License.\r */\rpackage org.flowable.ui.admin.service.engine;\r\rimport java.text.MessageFormat;\r\rimport org.apache.commons.lang3.StringUtils;\rimport org.apache.http.HttpStatus;\rimport org.apache.http.client.methods.HttpDelete;\rimport org.apache.http.client.methods.HttpGet;\rimport org.apache.http.client.methods.HttpPost;\rimport org.apache.http.client.methods.HttpPut;\rimport org.apache.http.client.utils.URIBuilder;\rimport org.flowable.ui.admin.domain.ServerConfig;\rimport org.flowable.ui.admin.service.engine.exception.FlowableServiceException;\rimport org.springframework.beans.factory.annotation.Autowired;\rimport org.springframework.stereotype.Service;\r\rimport com.fasterxml.jackson.databind.JsonNode;\rimport com.fasterxml.jackson.databind.ObjectMapper;\rimport com.fasterxml.jackson.databind.node.ObjectNode;\r\r/**\r * Service for invoking Flowable REST services.\r */\r@Service(\"adminCmmnTaskService\")\rpublic class CmmnTaskService {\r\r    public static final String HISTORIC_TASK_LIST_URL = \"cmmn-history/historic-task-instances\";\r    public static final String HISTORIC_TASK_QUERY_URL = \"cmmn-query/historic-task-instances\";\r    public static final String HISTORIC_TASK_URL = \"cmmn-history/historic-task-instances/{0}\";\r    public static final String RUNTIME_TASK_URL = \"cmmn-runtime/tasks/{0}\";\r    public static final String HISTORIC_VARIABLE_INSTANCE_LIST_URL = \"cmmn-history/historic-variable-instances\";\r    public static final String HISTORIC_TASK_IDENTITY_LINK_LIST_URL = \"cmmn-history/historic-task-instances/{0}/identitylinks\";\r\r    public static final String[] TASK_FILTERS = new String[] { \"taskNameLike\", \"taskAssigneeLike\", \"taskOwner\", \"finished\",\r            \"dueDateAfter\", \"dueDateBefore\", \"taskCompletedAfter\", \"taskCompletedBefore\", \"taskCreatedAfter\", \"taskCreatedBefore\", \"parentTaskId\", \"caseInstanceId\" };\r\r    private static final String DEFAULT_SUBTASK_RESULT_SIZE = \"1024\";\r    private static final String DEFAULT_VARIABLE_RESULT_SIZE = \"1024\";\r\r    @Autowired\r    protected FlowableClientService clientUtil;\r\r    @Autowired\r    protected ObjectMapper objectMapper;\r\r    public JsonNode listTasks(ServerConfig serverConfig, ObjectNode bodyNode) {\r\r        JsonNode resultNode = null;\r        try {\r            URIBuilder builder = clientUtil.createUriBuilder(HISTORIC_TASK_QUERY_URL);\r\r            String uri = clientUtil.getUriWithPagingAndOrderParameters(builder, bodyNode);\r            HttpPost post = clientUtil.createPost(uri, serverConfig);\r\r            post.setEntity(clientUtil.createStringEntity(bodyNode.toString()));\r            resultNode = clientUtil.executeRequest(post, serverConfig);\r        } catch (Exception e) {\r            throw new FlowableServiceException(e.getMessage(), e);\r        }\r        return resultNode;\r    }\r\r    public JsonNode getTask(ServerConfig serverConfig, String taskId, boolean runtime) {\r        if (taskId == null) {\r            throw new IllegalArgumentException(\"Task id is required\");\r        }\r\r        URIBuilder builder = null;\r        if (runtime) {\r            builder = clientUtil.createUriBuilder(MessageFormat.format(RUNTIME_TASK_URL, taskId));\r        } else {\r            builder = clientUtil.createUriBuilder(MessageFormat.format(HISTORIC_TASK_URL, taskId));\r        }\r\r        HttpGet get = new HttpGet(clientUtil.getServerUrl(serverConfig, builder));\r        return clientUtil.executeRequest(get, serverConfig);\r    }\r\r    /**\r     * Delete a task.\r     */\r    public void deleteTask(ServerConfig serverConfig, String taskId) {\r        if (taskId == null) {\r            throw new IllegalArgumentException(\"Task id is required\");\r        }\r\r        JsonNode taskNode = getTask(serverConfig, taskId, false);\r        if (taskNode.has(\"endTime\")) {\r\r            JsonNode endTimeNode = taskNode.get(\"endTime\");\r            if (endTimeNode != null && !endTimeNode.isNull() && StringUtils.isNotEmpty(endTimeNode.asText())) {\r\r                // Completed task\r                URIBuilder builder = clientUtil.createUriBuilder(MessageFormat.format(HISTORIC_TASK_URL, taskId));\r                HttpDelete delete = new HttpDelete(clientUtil.getServerUrl(serverConfig, builder));\r                clientUtil.executeRequestNoResponseBody(delete, serverConfig, HttpStatus.SC_NO_CONTENT);\r\r            } else {\r\r                // Not completed task\r                URIBuilder builder = clientUtil.createUriBuilder(MessageFormat.format(RUNTIME_TASK_URL, taskId) + \"?cascadeHistory=true\");\r                HttpDelete delete = new HttpDelete(clientUtil.getServerUrl(serverConfig, builder));\r                clientUtil.executeRequestNoResponseBody(delete, serverConfig, HttpStatus.SC_NO_CONTENT);\r\r            }\r        }\r    }\r\r    public void executeTaskAction(ServerConfig serverConfig, String taskId, JsonNode actionRequest) {\r        if (taskId == null) {\r            throw new IllegalArgumentException(\"Task id is required\");\r        }\r\r        URIBuilder builder = clientUtil.createUriBuilder(MessageFormat.format(RUNTIME_TASK_URL, taskId));\r        HttpPost post = clientUtil.createPost(builder, serverConfig);\r\r        post.setEntity(clientUtil.createStringEntity(actionRequest));\r        clientUtil.executeRequestNoResponseBody(post, serverConfig, HttpStatus.SC_OK);\r    }\r\r    public void updateTask(ServerConfig serverConfig, String taskId, JsonNode actionRequest) {\r        if (taskId == null) {\r            throw new IllegalArgumentException(\"Task id is required\");\r        }\r        URIBuilder builder = clientUtil.createUriBuilder(MessageFormat.format(RUNTIME_TASK_URL, taskId));\r        HttpPut put = clientUtil.createPut(builder, serverConfig);\r        put.setEntity(clientUtil.createStringEntity(actionRequest));\r        clientUtil.executeRequestNoResponseBody(put, serverConfig, HttpStatus.SC_OK);\r    }\r\r    public JsonNode getSubTasks(ServerConfig serverConfig, String taskId) {\r        URIBuilder builder = clientUtil.createUriBuilder(HISTORIC_TASK_LIST_URL);\r        builder.addParameter(\"parentTaskId\", taskId);\r        builder.addParameter(\"size\", DEFAULT_SUBTASK_RESULT_SIZE);\r\r        HttpGet get = new HttpGet(clientUtil.getServerUrl(serverConfig, builder));\r        return clientUtil.executeRequest(get, serverConfig);\r    }\r\r    public JsonNode getVariables(ServerConfig serverConfig, String taskId) {\r        URIBuilder builder = clientUtil.createUriBuilder(HISTORIC_VARIABLE_INSTANCE_LIST_URL);\r        builder.addParameter(\"taskId\", taskId);\r        builder.addParameter(\"size\", DEFAULT_VARIABLE_RESULT_SIZE);\r        builder.addParameter(\"sort\", \"variableName\");\r\r        HttpGet get = new HttpGet(clientUtil.getServerUrl(serverConfig, builder));\r        return clientUtil.executeRequest(get, serverConfig);\r    }\r\r    public JsonNode getIdentityLinks(ServerConfig serverConfig, String taskId) {\r        URIBuilder builder = clientUtil.createUriBuilder(MessageFormat.format(HISTORIC_TASK_IDENTITY_LINK_LIST_URL, taskId));\r\r        HttpGet get = new HttpGet(clientUtil.getServerUrl(serverConfig, builder));\r        return clientUtil.executeRequest(get, serverConfig);\r    }\r}\r"
  },
  {
    "path": "flowable-ui/src/main/java/org/flowable/ui/modeler/rest/app/AppDefinitionResource.java",
    "content": "/* Licensed under the Apache License, Version 2.0 (the \"License\");\r * you may not use this file except in compliance with the License.\r * You may obtain a copy of the License at\r *\r *      http://www.apache.org/licenses/LICENSE-2.0\r *\r * Unless required by applicable law or agreed to in writing, software\r * distributed under the License is distributed on an \"AS IS\" BASIS,\r * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r * See the License for the specific language governing permissions and\r * limitations under the License.\r */\rpackage org.flowable.ui.modeler.rest.app;\r\rimport com.fasterxml.jackson.databind.ObjectMapper;\rimport org.flowable.ui.common.service.exception.InternalServerErrorException;\rimport org.flowable.ui.modeler.model.AppDefinitionPublishRepresentation;\rimport org.flowable.ui.modeler.model.AppDefinitionRepresentation;\rimport org.flowable.ui.modeler.model.AppDefinitionSaveRepresentation;\rimport org.flowable.ui.modeler.model.AppDefinitionUpdateResultRepresentation;\rimport org.flowable.ui.modeler.service.AppDefinitionExportService;\rimport org.flowable.ui.modeler.service.AppDefinitionImportService;\rimport org.flowable.ui.modeler.serviceapi.AppDefinitionService;\rimport org.flowable.ui.modeler.serviceapi.ModelService;\rimport org.slf4j.Logger;\rimport org.slf4j.LoggerFactory;\rimport org.springframework.beans.factory.annotation.Autowired;\rimport org.springframework.transaction.annotation.Transactional;\rimport org.springframework.web.bind.annotation.*;\rimport org.springframework.web.multipart.MultipartFile;\r\rimport javax.servlet.http.HttpServletRequest;\rimport javax.servlet.http.HttpServletResponse;\rimport java.io.IOException;\r\r@RestController(\"modelerAppDefinitionResource\")\r@RequestMapping(\"/app\")\rpublic class AppDefinitionResource {\r\r    @Autowired\r    protected AppDefinitionService appDefinitionService;\r\r    @Autowired\r    protected AppDefinitionExportService appDefinitionExportService;\r\r    @Autowired\r    protected AppDefinitionImportService appDefinitionImportService;\r\r    @Autowired\r    protected ModelService modelService;\r\r    @Autowired\r    protected ObjectMapper objectMapper;\r\r    private static final Logger LOGGER = LoggerFactory.getLogger(AppDefinitionResource.class);\r\r    @RequestMapping(value = \"/rest/app-definitions/{modelId}\", method = RequestMethod.GET, produces = \"application/json\")\r    public AppDefinitionRepresentation getAppDefinition(@PathVariable(\"modelId\") String modelId) {\r        return appDefinitionService.getAppDefinition(modelId);\r    }\r\r    @RequestMapping(value = \"/rest/app-definitions/{modelId}/history/{modelHistoryId}\", method = RequestMethod.GET, produces = \"application/json\")\r    public AppDefinitionRepresentation getAppDefinitionHistory(@PathVariable String modelId, @PathVariable String modelHistoryId) {\r        return appDefinitionService.getAppDefinitionHistory(modelId, modelHistoryId);\r    }\r\r    @RequestMapping(value = \"/rest/app-definitions/{modelId}\", method = RequestMethod.PUT, produces = \"application/json\")\r    public AppDefinitionUpdateResultRepresentation updateAppDefinition(@PathVariable(\"modelId\") String modelId, @RequestBody AppDefinitionSaveRepresentation updatedModel) {\r        AppDefinitionUpdateResultRepresentation resultRepresentation = null;\r        try {\r            resultRepresentation = appDefinitionService.updateAppDefinition(modelId, updatedModel);\r        } catch (Exception ex) {\r            resultRepresentation = new AppDefinitionUpdateResultRepresentation();\r            resultRepresentation.setError(true);\r            resultRepresentation.setErrorDescription(ex.getMessage());\r        }\r        return resultRepresentation;\r    }\r\r    @RequestMapping(value = \"/rest/app-definitions/{modelId}/publish\", method = RequestMethod.POST, produces = \"application/json\")\r    public AppDefinitionUpdateResultRepresentation publishAppDefinition(@PathVariable(\"modelId\") String modelId, @RequestBody AppDefinitionPublishRepresentation publishModel) {\r        AppDefinitionUpdateResultRepresentation resultRepresentation = null;\r        try {\r            resultRepresentation = appDefinitionImportService.publishAppDefinition(modelId, publishModel);\r        } catch (Exception ex) {\r            resultRepresentation = new AppDefinitionUpdateResultRepresentation();\r            resultRepresentation.setError(true);\r            resultRepresentation.setErrorDescription(ex.getMessage());\r        }\r        return resultRepresentation;\r    }\r\r    @RequestMapping(value = \"/rest/app-definitions/{modelId}/export\", method = RequestMethod.GET)\r    public void exportAppDefinition(HttpServletResponse response, @PathVariable String modelId) throws IOException {\r        appDefinitionExportService.exportAppDefinition(response, modelId);\r    }\r\r    @RequestMapping(value = \"/rest/app-definitions/{modelId}/export-bar\", method = RequestMethod.GET)\r    public void exportDeployableAppDefinition(HttpServletResponse response, @PathVariable String modelId) throws IOException {\r        appDefinitionExportService.exportDeployableAppDefinition(response, modelId);\r    }\r\r    @Transactional\r    @RequestMapping(value = \"/rest/app-definitions/{modelId}/import\", method = RequestMethod.POST, produces = \"application/json\")\r    public AppDefinitionRepresentation importAppDefinition(HttpServletRequest request, @PathVariable String modelId, @RequestParam(\"file\") MultipartFile file) {\r        return appDefinitionImportService.importAppDefinitionNewVersion(request, file, modelId);\r    }\r\r    @Transactional\r    @RequestMapping(value = \"/rest/app-definitions/{modelId}/text/import\", method = RequestMethod.POST)\r    public String importAppDefinitionText(HttpServletRequest request, @PathVariable String modelId, @RequestParam(\"file\") MultipartFile file) {\r\r        AppDefinitionRepresentation appDefinitionRepresentation = appDefinitionImportService.importAppDefinitionNewVersion(request, file, modelId);\r        String appDefinitionRepresentationJson = null;\r        try {\r            appDefinitionRepresentationJson = objectMapper.writeValueAsString(appDefinitionRepresentation);\r        } catch (Exception e) {\r            LOGGER.error(\"Error while App Definition representation json\", e);\r            throw new InternalServerErrorException(\"App definition could not be saved\");\r        }\r\r        return appDefinitionRepresentationJson;\r    }\r\r    @Transactional\r    @RequestMapping(value = \"/rest/app-definitions/import\", method = RequestMethod.POST, produces = \"application/json\")\r    public AppDefinitionRepresentation importAppDefinition(HttpServletRequest request, @RequestParam(\"file\") MultipartFile file) {\r        return appDefinitionImportService.importAppDefinition(request, file);\r    }\r\r    @Transactional\r    @RequestMapping(value = \"/rest/app-definitions/text/import\", method = RequestMethod.POST)\r    public String importAppDefinitionText(HttpServletRequest request, @RequestParam(\"file\") MultipartFile file) {\r        AppDefinitionRepresentation appDefinitionRepresentation = appDefinitionImportService.importAppDefinition(request, file);\r        String appDefinitionRepresentationJson = null;\r        try {\r            appDefinitionRepresentationJson = objectMapper.writeValueAsString(appDefinitionRepresentation);\r        } catch (Exception e) {\r            LOGGER.error(\"Error while App Definition representation json\", e);\r            throw new InternalServerErrorException(\"App definition could not be saved\");\r        }\r\r        return appDefinitionRepresentationJson;\r    }\r}\r"
  },
  {
    "path": "flowable-ui/src/main/resources/application-dev.yml",
    "content": "spring:\r  datasource:\r    druid:\r      driver-class-name: com.mysql.jdbc.Driver\r      url: jdbc:mysql://127.0.0.1:3306/workFlow?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&allowMultiQueries=true\r      password: root\r      username: root\r"
  },
  {
    "path": "flowable-ui/src/main/resources/application.yml",
    "content": "spring:\r  profiles:\r    active: dev\r  security:\r    filter:\r      dispatcher-types: REQUEST,FORWARD,ASYNC\r  aop:\r    proxy-target-class: false\r    auto: false\r  jackson:\r    date-format: yyyy-MM-dd HH:mm:ss\r    time-zone: GMT+8\r  application:\r    name: flowable\r  jmx:\r    default-domain: ${spring.application.name}\r  servlet:\r    multipart:\r      max-request-size: 100MB\r      max-file-size: 100MB\r  http:\r    encoding:\r      charset: UTF-8\r      force: true\r      enabled: true\r  banner:\r    location: classpath:/org/flowable/spring/boot/flowable-banner.txt\r  mvc:\r    favicon:\r      enabled: false\r  liquibase:\r    enabled: false\r  datasource:\r    druid:\r      min-idle: 5\r      max-pool-prepared-statement-per-connection-size: 20\r      test-while-idle: true\r      time-between-eviction-runs-millis: 60000\r      max-active: 40\r      validation-query: SELECT 'x'\r      max-wait: 60000\r      test-on-borrow: false\r      pool-prepared-statements: true\r      initial-size: 10\r      min-evictable-idle-time-millis: 300000\r      test-on-return: false\rserver:\r  tomcat:\r    uri-encoding: UTF-8\r  port: 8080\r  servlet:\r    context-path: /${spring.application.name}\r  compression:\r    mime-types: application/json,application/xml,text/html,text/xml,text/plain\r    enabled: true\r    min-response-size: 4096\rflowable:\r  rest:\r    app:\r      authentication-mode: verify-privilege\r  process:\r    definition-cache-limit: 1\r  idm:\r    app:\r      admin:\r        password: test\r        user-id: admin\r        first-name: admin\r        last-name: admin\r  labelFontName: 宋体\r  common:\r    app:\r      role-prefix:\r      idm-url: http://localhost:${server.port}/${spring.application.name}/idm\r  xml:\r    encoding: UTF-8\r  activityFontName: 宋体\r  modeler:\r    app:\r      rest-enabled: true\r      deployment-api-url: http://localhost:${server.port}/${spring.application.name}/app-api\r  rest-api-enabled: true\r  admin:\r    app:\r      security:\r        encryption:\r          credentials-secret-spec: 9FGl73ngxcOoJvmL\r          credentials-i-v-spec: j8kdO2hejA9lKmm6\r      server-config:\r        app:\r          context-root: ${spring.application.name}\r          password: test\r          server-address: http://localhost\r          user-name: admin\r          port: ${server.port}\r          rest-root: app-api\r          name: Flowable App app\r          description: Flowable App REST config\r        process:\r          context-root: ${spring.application.name}\r          server-address: http://localhost\r          password: test\r          user-name: admin\r          rest-root: process-api\r          port: ${server.port}\r          name: Flowable Process app\r          description: Flowable Process REST config\r        form:\r          context-root: ${spring.application.name}\r          server-address: http://localhost\r          password: test\r          user-name: admin\r          port: ${server.port}\r          rest-root: form-api\r          name: Flowable Form app\r          description: Flowable Form REST config\r        dmn:\r          context-root: ${spring.application.name}\r          server-address: http://localhost\r          password: test\r          user-name: admin\r          port: ${server.port}\r          rest-root: dmn-api\r          name: Flowable DMN app\r          description: Flowable DMN REST config\r        cmmn:\r          context-root: ${spring.application.name}\r          password: test\r          server-address: http://localhost\r          user-name: admin\r          port: ${server.port}\r          rest-root: cmmn-api\r          name: Flowable CMMN app\r          description: Flowable CMMN REST config\r        content:\r          context-root: ${spring.application.name}\r          server-address: http://localhost\r          password: test\r          user-name: admin\r          rest-root: content-api\r          port: ${server.port}\r          name: Flowable Content app\r          description: Flowable Content REST config\r  database-schema-update: true\r  annotationFontName: 宋体\rmanagement:\r  endpoint:\r    health:\r      roles: access-admin\r      show-details: when_authorized\r  endpoints:\r    jmx:\r      unique-names: true\rmybatis:\r  mapper-locations:\r    - classpath:/META-INF/admin-mybatis-mappings/*.xml\r    - classpath:/META-INF/modeler-mybatis-mappings/*.xml\r  configuration-properties:\r    prefix:\r    boolValue: TRUE\r    blobType: BLOB\rswagger:\r  docket:\r    system:\r      title: 系统内置工作流API\r      description: 工作流\r      version: 1.0.RELEASE\r      license: Apache License, Version 2.0\r      license-url: https://www.apache.org/licenses/LICENSE-2.0.html\r      terms-of-service-url: https://github.com/SpringForAll/spring-boot-starter-swagger\r      base-packages: org.flowable\r      base-path: /**\r      exclude-path: /error, /ops/**\r    own:\r      title: 自定义工作流API\r      description: 工作流\r      version: 1.0.RELEASE\r      license: Apache License, Version 2.0\r      license-url: https://www.apache.org/licenses/LICENSE-2.0.html\r      terms-of-service-url: https://github.com/SpringForAll/spring-boot-starter-swagger\r      base-packages: com.github.flowable\r      base-path: /**\r      exclude-path: /error, /ops/**\r"
  },
  {
    "path": "flowable-ui/src/main/resources/flow-manager.sh",
    "content": "#!/bin/bash\n#这里可替换为你自己的执行程序，其他代码无需更改\nAPP_NAME=flow-manager.jar\nENVIRONMENT=dev\nPROPERTIES=classpath:/application.properties,classpath:/application-dev.properties\nDEBUG_MODE=0\n\n#使用说明，用来提示输入参数\nusage() {\n    echo \"Usage: sh 执行脚本.sh [start|stop|restart|status] [dev|test|prod](default:dev) debug\"\n    exit 1\n}\n\n#检查程序是否在运行\nis_exist(){\n  pid=`ps -ef|grep $APP_NAME|grep -v grep|awk '{print $2}' `\n  #如果不存在返回1，存在返回0\n  if [ -z \"${pid}\" ]; then\n   return 1\n  else\n    return 0\n  fi\n}\n\n#启动方法\n start(){\n   is_exist\n   if [ $? -eq \"0\" ]; then\n     echo \"${APP_NAME} is already running. pid=${pid} .\"\n   else\n    echo \"now Profiles:${ENVIRONMENT}\"\n    if [ ${DEBUG_MODE} -eq \"1\" ]; then\n      nohup java -jar -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5007 $APP_NAME --spring.profiles.active=$ENVIRONMENT  --spring.config.location=$PROPERTIES > /dev/null 2>&1 &\n    else\n      nohup java -jar $APP_NAME --spring.profiles.active=$ENVIRONMENT  --spring.config.location=$PROPERTIES > /dev/null 2>&1 &\n    fi\n   fi\n }\n\n#停止方法\nstop(){\n  is_exist\n  if [ $? -eq \"0\" ]; then\n    kill -9 $pid\n  else\n    echo \"${APP_NAME} is not running\"\n  fi\n}\n\n#输出运行状态\nstatus(){\n  is_exist\n  if [ $? -eq \"0\" ]; then\n    echo \"${APP_NAME} is running. Pid is ${pid}\"\n  else\n    echo \"${APP_NAME} is NOT running.\"\n  fi\n}\n\n#重启\nrestart(){\n  stop\n  start\n}\n\ncase \"$3\" in\n  \"debug\")\n    DEBUG_MODE=1\n    ;;\n  *)\n    ;;\nesac\n\n#根据第二个参数设置编译环境默认为dev\ncase \"$2\" in\n  \"dev\")\n    ENVIRONMENT=dev\n    PROPERTIES=classpath:/application.properties,classpath:/application-dev.properties\n    ;;\n  \"test\")\n    ENVIRONMENT=test\n    PROPERTIES=classpath:/application.properties,/etc/config/flow/application-test.properties\n    ;;\n  \"prod\")\n    ENVIRONMENT=prod\n    PROPERTIES=classpath:/application.properties,/etc/config/flow/application-prod.properties\n    ;;\n  *)\n    if [[ -n $2 ]]; then\n      echo \"Profiles set error ! please check again!\"\n      exit 1\n    fi\n    ;;\nesac\n\n#根据输入参数，选择执行对应方法，不输入则执行使用说明\ncase \"$1\" in\n  \"start\")\n    start\n    ;;\n  \"stop\")\n    stop\n    ;;\n  \"status\")\n    status\n    ;;\n  \"restart\")\n    restart\n    ;;\n  *)\n    usage\n    ;;\nesac"
  },
  {
    "path": "flowable-ui/src/main/resources/mybatisGenerator.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r<!DOCTYPE generatorConfiguration\r        PUBLIC \"-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN\"\r        \"http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd\">\r\r<generatorConfiguration>\r    <context id=\"workflow\" targetRuntime=\"MyBatis3\"\r             defaultModelType=\"flat\">\r\r        <property name=\"javaFileEncoding\" value=\"UTF-8\"/>\r        <!--配置是否使用通用 Mapper 自带的注释扩展，默认 true-->\r        <!--<property name=\"useMapperCommentGenerator\" value=\"false\"/>-->\r\r        <plugin type=\"tk.mybatis.mapper.generator.MapperPlugin\">\r            <property name=\"mappers\" value=\"com.huazhu.workflow.common.mybatis.CommonMapper\" />\r            <!--caseSensitive默认false，当数据库表名区分大小写时，可以将该属性设置为true-->\r            <property name=\"caseSensitive\" value=\"true\"/>\r            <property name=\"forceAnnotation\" value=\"true\"/>\r            <property name=\"beginningDelimiter\" value=\"`\"/>\r            <property name=\"endingDelimiter\" value=\"`\"/>\r            <!--配置是否启用lombok, 支持如下6种注解-->\r            <!--当配置 Data 后，Getter Setter ToString EqualsAndHashCode 会被忽略-->\r            <property name=\"lombok\" value=\"Getter,Setter,Data,ToString,Accessors,EqualsAndHashCode\"/>\r        </plugin>\r        <!-- 生成 JavaBean 对象继承 Serializable 类 -->\r        <plugin type=\"org.mybatis.generator.plugins.SerializablePlugin\" />\r\r        <commentGenerator>\r            <property name=\"suppressDate\" value=\"true\" />\r            <!-- 取消注释 -->\r            <property name=\"suppressAllComments\" value=\"false\" />\r        </commentGenerator>\r\r        <jdbcConnection driverClass=\"com.mysql.jdbc.Driver\"\r                        connectionURL=\"jdbc:mysql://localhost:3306/workFlow\" userId=\"root\"\r                        password=\"root\">\r        </jdbcConnection>\r\r        <!-- 配置表、Java属性的对应关系 -->\r        <javaTypeResolver >\r            <property name=\"forceBigDecimals\" value=\"false\" />\r        </javaTypeResolver>\r\r        <!-- 配置生成文件的位置 -->\r        <javaModelGenerator targetPackage=\"com.huazhu.workflow.common.entity\" targetProject=\"src/main/java\">\r            <property name=\"enableSubPackages\" value=\"true\" />\r            <property name=\"trimStrings\" value=\"true\" />\r        </javaModelGenerator>\r\r        <!-- xml生成器 -->\r        <sqlMapGenerator targetPackage=\"mapper\" targetProject=\"src/main/resources\">\r            <property name=\"enableSubPackages\" value=\"true\" />\r        </sqlMapGenerator>\r\r        <!-- 生成dao -->\r        <javaClientGenerator type=\"XMLMAPPER\"\r                             targetPackage=\"com.huazhu.workflow.common.mapper\" targetProject=\"src/main/java\">\r            <property name=\"enableSubPackages\" value=\"true\" />\r        </javaClientGenerator>\r\r        <!-- 配置需要哪些表需要生成 全部生成-->\r        <!--<table tableName=\"APM_%\">\r            &lt;!&ndash;<generatedKey column=\"id\" sqlStatement=\"oracle\" />&ndash;&gt;\r        </table>-->\r\r        <!-- 单独设置一张表的自动代码生成 -->\r        <table tableName=\"WF_DICT_TYPE\" domainObjectName=\"WfDictType\"\r               enableCountByExample=\"false\"\r               enableDeleteByExample=\"false\"\r               enableSelectByExample=\"false\"\r               enableUpdateByExample=\"false\"\r               selectByExampleQueryId=\"false\">\r            <!-- 配置插入一条记录后 获取到插入后的主键ID-->\r            <generatedKey column=\"ID\" sqlStatement=\"mysql\" type=\"post\" identity=\"true\"/>\r        </table>\r    </context>\r\r</generatorConfiguration>"
  },
  {
    "path": "flowable-ui/src/main/resources/stencilset/en/stencilset_bpmn.json",
    "content": "{\n  \"title\" : \"Process editor\",\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\" : \"Process identifier\",\n      \"value\" : \"process\",\n      \"description\" : \"Unique identifier of the process definition.\",\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\" : \"Name\",\n      \"value\" : \"\",\n      \"description\" : \"The descriptive name of the BPMN element.\",\n      \"popular\" : true,\n      \"refToView\" : \"text_name\"\n    } ]\n  }, {\n    \"name\" : \"documentationpackage\",\n    \"properties\" : [ {\n      \"id\" : \"documentation\",\n      \"type\" : \"Text\",\n      \"title\" : \"Documentation\",\n      \"value\" : \"\",\n      \"description\" : \"The descriptive name of the BPMN element.\",\n      \"popular\" : true\n    } ]\n  }, {\n    \"name\" : \"categorypackage\",\n    \"properties\" : [ {\n      \"id\" : \"categorydefinition\",\n      \"type\" : \"String\",\n      \"title\" : \"Category\",\n      \"value\" : \"\",\n      \"description\" : \"Category of the BPMN element.\",\n      \"popular\" : true\n    } ]\n  }, {\n    \"name\" : \"process_authorpackage\",\n    \"properties\" : [ {\n      \"id\" : \"process_author\",\n      \"type\" : \"String\",\n      \"title\" : \"Process author\",\n      \"value\" : \"\",\n      \"description\" : \"Author of the process definition.\",\n      \"popular\" : true\n    } ]\n  }, {\n    \"name\" : \"process_versionpackage\",\n    \"properties\" : [ {\n      \"id\" : \"process_version\",\n      \"type\" : \"String\",\n      \"title\" : \"Process version string (documentation only)\",\n      \"value\" : \"\",\n      \"description\" : \"Version identifier for documentation purpose.\",\n      \"popular\" : true\n    } ]\n  }, {\n    \"name\" : \"process_historylevelpackage\",\n    \"properties\" : [ {\n      \"id\" : \"process_historylevel\",\n      \"type\" : \"flowable-processhistorylevel\",\n      \"title\" : \"Set a specific history level for this process definition\",\n      \"value\" : \"\",\n      \"description\" : \"Set a specific history level for this process definition\",\n      \"popular\" : true\n    } ]\n  }, {\n    \"name\" : \"isexecutablepackage\",\n    \"properties\" : [ {\n      \"id\" : \"isexecutable\",\n      \"type\" : \"Boolean\",\n      \"title\" : \"Is executable\",\n      \"value\" : \"true\",\n      \"description\" : \"Is the process executable?\",\n      \"popular\" : true\n    } ]\n  }, {\n    \"name\" : \"process_potentialstarteruserpackage\",\n    \"properties\" : [ {\n      \"id\" : \"process_potentialstarteruser\",\n      \"type\" : \"String\",\n      \"title\" : \"Potential starter user\",\n      \"value\" : \"\",\n      \"description\" : \"Which user, can start the process?\",\n      \"popular\" : true\n    } ]\n  }, {\n    \"name\" : \"process_potentialstartergrouppackage\",\n    \"properties\" : [ {\n      \"id\" : \"process_potentialstartergroup\",\n      \"type\" : \"String\",\n      \"title\" : \"Potential starter group\",\n      \"value\" : \"\",\n      \"description\" : \"Which group, can start the process?\",\n      \"popular\" : true\n    } ]\n  }, {\n    \"name\" : \"process_namespacepackage\",\n    \"properties\" : [ {\n      \"id\" : \"process_namespace\",\n      \"type\" : \"String\",\n      \"title\" : \"Target namespace\",\n      \"value\" : \"http://www.flowable.org/processdef\",\n      \"description\" : \"Target namespace for the process definition.\",\n      \"popular\" : true\n    } ]\n  }, {\n    \"name\" : \"process_iseagerexecutionfetchpackage\",\n    \"properties\" : [ {\n      \"id\" : \"iseagerexecutionfetch\",\n      \"type\" : \"Boolean\",\n      \"title\" : \"Eager execution fetching\",\n      \"value\" : \"false\",\n      \"description\" : \"Enable eager execution fetching for this process definition?\",\n      \"popular\" : true\n    } ]\n  }, {\n    \"name\" : \"asynchronousdefinitionpackage\",\n    \"properties\" : [ {\n      \"id\" : \"asynchronousdefinition\",\n      \"type\" : \"Boolean\",\n      \"title\" : \"Asynchronous\",\n      \"value\" : \"false\",\n      \"description\" : \"Define the activity as asynchronous.\",\n      \"popular\" : true\n    } ]\n  }, {\n    \"name\" : \"datapropertiespackage\",\n    \"properties\" : [ {\n      \"id\" : \"dataproperties\",\n      \"type\" : \"Complex\",\n      \"title\" : \"Data Objects\",\n      \"value\" : \"\",\n      \"description\" : \"Definition of the data object properties\",\n      \"popular\" : true\n    } ]\n  }, {\n    \"name\" : \"exclusivedefinitionpackage\",\n    \"properties\" : [ {\n      \"id\" : \"exclusivedefinition\",\n      \"type\" : \"Boolean\",\n      \"title\" : \"Exclusive\",\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\" : \"Execution listeners\",\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\" : \"Task listeners\",\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\" : \"Event listeners\",\n      \"value\" : \"\",\n      \"description\" : \"Listeners for any event happening in the Flowable 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\" : \"Assignments\",\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\" : \"Form properties\",\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\" : \"Form key\",\n      \"value\" : \"\",\n      \"description\" : \"Form key that provides a reference to a form.\",\n      \"popular\" : true\n    } ]\n  }, {\n    \"name\" : \"duedatedefinitionpackage\",\n    \"properties\" : [ {\n      \"id\" : \"duedatedefinition\",\n      \"type\" : \"String\",\n      \"title\" : \"Due date\",\n      \"value\" : \"\",\n      \"description\" : \"Due date of the user task.\",\n      \"popular\" : true\n    } ]\n  }, {\n    \"name\" : \"prioritydefinitionpackage\",\n    \"properties\" : [ {\n      \"id\" : \"prioritydefinition\",\n      \"type\" : \"String\",\n      \"title\" : \"Priority\",\n      \"value\" : \"\",\n      \"description\" : \"Priority of the user task.\",\n      \"popular\" : true\n    } ]\n  }, {\n    \"name\" : \"servicetaskclasspackage\",\n    \"properties\" : [ {\n      \"id\" : \"servicetaskclass\",\n      \"type\" : \"String\",\n      \"title\" : \"Class\",\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\" : \"Text\",\n      \"title\" : \"Expression\",\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\" : \"Text\",\n      \"title\" : \"Delegate expression\",\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\" : \"Class fields\",\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\" : \"servicetaskresultvariablepackage\",\n    \"properties\" : [ {\n      \"id\" : \"servicetaskUseLocalScopeForResultVariable\",\n      \"type\" : \"Boolean\",\n      \"title\" : \"Use local scope for result variable\",\n      \"value\" : \"false\",\n      \"description\" : \"Flag that marks that the used resultVariable needs to be saved as a local variable\",\n      \"popular\" : true\n    } ]\n  }, {\n    \"name\" : \"servicetasktriggerablepackage\",\n    \"properties\" : [ {\n      \"id\" : \"servicetasktriggerable\",\n      \"type\" : \"Boolean\",\n      \"title\" : \"Set service task to be triggerable\",\n      \"value\" : \"false\",\n      \"description\" : \"Sets the service task to be triggerable\",\n      \"popular\" : true\n    } ]\n  }, {\n    \"name\": \"scriptformatpackage\",\n    \"properties\" : [ {\n      \"id\": \"scriptformat\",\n      \"type\": \"String\",\n      \"title\": \"Script format\",\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\": \"Script\",\n      \"value\": \"\",\n      \"description\": \"Script text of the script task.\",\n      \"popular\": true\n    }\n    ]\n  }, {\n    \"name\": \"scriptautostorevariablespackage\",\n    \"properties\": [{\n      \"id\": \"scriptautostorevariables\",\n      \"type\": \"Boolean\",\n      \"title\": \"Auto Store Variables\",\n      \"value\": \"false\",\n      \"description\": \"Automatically store all script variables to the process.\",\n      \"popular\": true\n    }]\n  }, {\n    \"name\" : \"shellcommandpackage\",\n    \"properties\" : [ {\n      \"id\" : \"shellcommand\",\n      \"type\" : \"String\",\n      \"title\" : \"Command\",\n      \"value\" : \"\",\n      \"description\" : \"Shell task command\",\n      \"popular\" : true\n    } ]\n  }, {\n    \"name\" : \"shellarg1package\",\n    \"properties\" : [ {\n      \"id\" : \"shellarg1\",\n      \"type\" : \"Text\",\n      \"title\" : \"Argument 1\",\n      \"value\" : \"\",\n      \"description\" : \"Shell commnad arg 1\",\n      \"popular\" : true\n    } ]\n  }, {\n    \"name\" : \"shellarg2package\",\n    \"properties\" : [ {\n      \"id\" : \"shellarg2\",\n      \"type\" : \"Text\",\n      \"title\" : \"Argument 2\",\n      \"value\" : \"\",\n      \"description\" : \"Shell commnad arg 2\",\n      \"popular\" : true\n    } ]\n  }, {\n    \"name\" : \"shellarg3package\",\n    \"properties\" : [ {\n      \"id\" : \"shellarg3\",\n      \"type\" : \"Text\",\n      \"title\" : \"Argument 3\",\n      \"value\" : \"\",\n      \"description\" : \"Shell commnad arg 3\",\n      \"popular\" : true\n    } ]\n  }, {\n    \"name\" : \"shellarg4package\",\n    \"properties\" : [ {\n      \"id\" : \"shellarg4\",\n      \"type\" : \"Text\",\n      \"title\" : \"Argument 4\",\n      \"value\" : \"\",\n      \"description\" : \"Shell commnad arg 4\",\n      \"popular\" : true\n    } ]\n  }, {\n    \"name\" : \"shellarg5package\",\n    \"properties\" : [ {\n      \"id\" : \"shellarg5\",\n      \"type\" : \"Text\",\n      \"title\" : \"Argument 5\",\n      \"value\" : \"\",\n      \"description\" : \"Shell commnad arg 5\",\n      \"popular\" : true\n    } ]\n  }, {\n    \"name\" : \"shellwaitpackage\",\n    \"properties\" : [ {\n      \"id\" : \"shellwait\",\n      \"type\" : \"Text\",\n      \"title\" : \"Wait\",\n      \"value\" : \"\",\n      \"description\" : \"Flag to wait for shell command execution end\",\n      \"popular\" : true\n    } ]\n  }, {\n    \"name\" : \"shelloutputvariablepackage\",\n    \"properties\" : [ {\n      \"id\" : \"shelloutputvariable\",\n      \"type\" : \"Text\",\n      \"title\" : \"Output variable\",\n      \"value\" : \"\",\n      \"description\" : \"Variable to store shell commnad output\",\n      \"popular\" : true\n    } ]\n  }, {\n    \"name\" : \"shellerrorcodevariablepackage\",\n    \"properties\" : [ {\n      \"id\" : \"shellerrorcodevariable\",\n      \"type\" : \"Text\",\n      \"title\" : \"Error code variable\",\n      \"value\" : \"\",\n      \"description\" : \"Variable to store shell commnad error code\",\n      \"popular\" : true\n    } ]\n  }, {\n    \"name\" : \"shellredirecterrorpackage\",\n    \"properties\" : [ {\n      \"id\" : \"shellredirecterror\",\n      \"type\" : \"Text\",\n      \"title\" : \"Redirect error\",\n      \"value\" : \"\",\n      \"description\" : \"If true merge error output with standard output\",\n      \"popular\" : true\n    } ]\n  }, {\n    \"name\" : \"shellcleanenvpackage\",\n    \"properties\" : [ {\n      \"id\" : \"shellcleanenv\",\n      \"type\" : \"Text\",\n      \"title\" : \"Clean env\",\n      \"value\" : \"\",\n      \"description\" : \"Clean shell execution environment\",\n      \"popular\" : true\n    } ]\n  }, {\n    \"name\" : \"shelldirectorypackage\",\n    \"properties\" : [ {\n      \"id\" : \"shelldirectory\",\n      \"type\" : \"Text\",\n      \"title\" : \"Directory\",\n      \"value\" : \"\",\n      \"description\" : \"Shell process working directory\",\n      \"popular\" : true\n    } ]\n  }, {\n    \"name\" : \"ruletask_rulespackage\",\n    \"properties\" : [ {\n      \"id\" : \"ruletask_rules\",\n      \"type\" : \"String\",\n      \"title\" : \"Rules\",\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\" : \"Input variables\",\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\" : \"Exclude\",\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\" : \"Result variable\",\n      \"value\" : \"\",\n      \"description\" : \"Result variable of the rule task.\",\n      \"popular\" : true\n    } ]\n  }, {\n    \"name\" : \"mailtaskheaderspackage\",\n    \"properties\" : [ {\n      \"id\" : \"mailtaskheaders\",\n      \"type\" : \"Text\",\n      \"title\" : \"Headers\",\n      \"value\" : \"\",\n      \"description\" : \"Line separated Mail headers (For example - X-Attribute: value).\",\n      \"popular\" : true\n    } ]\n  }, {\n    \"name\" : \"mailtasktopackage\",\n    \"properties\" : [ {\n      \"id\" : \"mailtaskto\",\n      \"type\" : \"Text\",\n      \"title\" : \"To\",\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\" : \"From\",\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\" : \"Subject\",\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\" : \"Cc\",\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\" : \"Bcc\",\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\" : \"Text\",\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\" : \"httptaskrequestmethodpackage\",\n    \"properties\" : [ {\n      \"id\" : \"httptaskrequestmethod\",\n      \"type\" : \"flowable-http-request-method\",\n      \"title\" : \"Request method\",\n      \"value\" : \"\",\n      \"description\" : \"Request method (For example - GET,POST,PUT etc).\",\n      \"popular\" : true\n    } ]\n  }, {\n    \"name\" : \"httptaskrequesturlpackage\",\n    \"properties\" : [ {\n      \"id\" : \"httptaskrequesturl\",\n      \"type\" : \"Text\",\n      \"title\" : \"Request URL\",\n      \"value\" : \"\",\n      \"description\" : \"Request URL (For example - http://flowable.org).\",\n      \"popular\" : true\n    } ]\n  }, {\n    \"name\" : \"httptaskrequestheaderspackage\",\n    \"properties\" : [ {\n      \"id\" : \"httptaskrequestheaders\",\n      \"type\" : \"Text\",\n      \"title\" : \"Request headers\",\n      \"value\" : \"\",\n      \"description\" : \"Line separated HTTP request headers (For example - Content-Type: application/json).\",\n      \"popular\" : true\n    } ]\n  }, {\n    \"name\" : \"httptaskrequestbodypackage\",\n    \"properties\" : [ {\n      \"id\" : \"httptaskrequestbody\",\n      \"type\" : \"Text\",\n      \"title\" : \"Request body\",\n      \"value\" : \"\",\n      \"description\" : \"Request body (For example- ${sampleBody}).\",\n      \"popular\" : true\n    } ]\n  }, {\n    \"name\" : \"httptaskrequestbodyencodingpackage\",\n    \"properties\" : [ {\n      \"id\" : \"httptaskrequestbodyencoding\",\n      \"type\" : \"Text\",\n      \"title\" : \"Request body encoding\",\n      \"value\" : \"\",\n      \"description\" : \"Request body encoding (For example- UTF-8).\",\n      \"popular\" : true\n    } ]\n  }, {\n    \"name\" : \"httptaskrequesttimeoutpackage\",\n    \"properties\" : [ {\n      \"id\" : \"httptaskrequesttimeout\",\n      \"type\" : \"String\",\n      \"title\" : \"Request timeout\",\n      \"value\" : \"\",\n      \"description\" : \"Timeout in milliseconds for the request (For example - 5000).\",\n      \"popular\" : true\n    } ]\n  }, {\n    \"name\" : \"httptaskdisallowredirectspackage\",\n    \"properties\" : [ {\n      \"id\" : \"httptaskdisallowredirects\",\n      \"type\" : \"String\",\n      \"title\" : \"Disallow redirects\",\n      \"value\" : \"\",\n      \"description\" : \"Flag to disallow HTTP redirects.\",\n      \"popular\" : true\n    } ]\n  }, {\n    \"name\" : \"httptaskfailstatuscodespackage\",\n    \"properties\" : [ {\n      \"id\" : \"httptaskfailstatuscodes\",\n      \"type\" : \"String\",\n      \"title\" : \"Fail status codes\",\n      \"value\" : \"\",\n      \"description\" : \"Comma separated list of HTTP response status codes to retry, for example 400,5XX.\",\n      \"popular\" : true\n    } ]\n  }, {\n    \"name\" : \"httptaskhandlestatuscodespackage\",\n    \"properties\" : [ {\n      \"id\" : \"httptaskhandlestatuscodes\",\n      \"type\" : \"String\",\n      \"title\" : \"Handle status codes\",\n      \"value\" : \"\",\n      \"description\" : \"Comma separated list of HTTP response status codes to ignore, for example 404,3XX.\",\n      \"popular\" : true\n    } ]\n  }, {\n    \"name\" : \"httptaskignoreexceptionpackage\",\n    \"properties\" : [ {\n      \"id\" : \"httptaskignoreexception\",\n      \"type\" : \"String\",\n      \"title\" : \"Ignore exception\",\n      \"value\" : \"\",\n      \"description\" : \"Flag to ignore exceptions.\",\n      \"popular\" : true\n    } ]\n  },\n    {\n      \"name\" : \"httptasksaveresponseparameterstransientpackage\",\n      \"properties\" : [ {\n        \"id\" : \"httptasksaveresponseparameterstransient\",\n        \"type\" : \"String\",\n        \"title\" : \"Save response as a transient variable\",\n        \"value\" : \"\",\n        \"description\" : \"Flag indicating to store the response variable(s) transient\",\n        \"popular\" : true\n      } ]\n    },\n    {\n      \"name\" : \"httptasksaveresponseasjsonpackage\",\n      \"properties\" : [ {\n        \"id\" : \"httptasksaveresponseasjson\",\n        \"type\" : \"String\",\n        \"title\" : \"Save response as JSON\",\n        \"value\" : \"\",\n        \"description\" : \"Flag indicating to store the response variable as a JSON variable instead of a String\",\n        \"popular\" : true\n      } ]\n    },\n    {\n      \"name\": \"skipexpressionpackage\",\n      \"properties\": [\n        {\n          \"id\": \"skipexpression\",\n          \"type\": \"String\",\n          \"title\": \"Skip expression\",\n          \"value\": \"\",\n          \"description\": \"Skip an expression execution associated with task or association or not.\",\n          \"popular\": true\n        }\n      ]\n    },\n    {\n      \"name\" : \"httptaskresponsevariablenamepackage\",\n      \"properties\" : [ {\n        \"id\" : \"httptaskresponsevariablename\",\n        \"type\" : \"String\",\n        \"title\" : \"Response variable name\",\n        \"value\" : \"\",\n        \"description\" : \"Define the variable name to store the http response.\",\n        \"popular\" : true\n      } ]\n    }, {\n      \"name\" : \"httptasksaverequestvariablespackage\",\n      \"properties\" : [ {\n        \"id\" : \"httptasksaverequestvariables\",\n        \"type\" : \"String\",\n        \"title\" : \"Save request variables\",\n        \"value\" : \"\",\n        \"description\" : \"Flag to save request variables.\",\n        \"popular\" : true\n      } ]\n    }, {\n      \"name\" : \"httptasksaveresponseparameterspackage\",\n      \"properties\" : [ {\n        \"id\" : \"httptasksaveresponseparameters\",\n        \"type\" : \"String\",\n        \"title\" : \"Save response status, headers\",\n        \"value\" : \"\",\n        \"description\" : \"Flag to save response status, headers etc.\",\n        \"popular\" : true\n      } ]\n    }, {\n      \"name\" : \"httptaskresultvariableprefixpackage\",\n      \"properties\" : [ {\n        \"id\" : \"httptaskresultvariableprefix\",\n        \"type\" : \"String\",\n        \"title\" : \"Result variable prefix\",\n        \"value\" : \"\",\n        \"description\" : \"Prefix for the execution variable names.\",\n        \"popular\" : true\n      } ]\n    }, {\n      \"name\" : \"callactivitycalledelementpackage\",\n      \"properties\" : [ {\n        \"id\" : \"callactivitycalledelement\",\n        \"type\" : \"String\",\n        \"title\" : \"Called element\",\n        \"value\" : \"\",\n        \"description\" : \"Process reference.\",\n        \"popular\" : true\n      } ]\n    }, {\n      \"name\" : \"callactivitycalledelementtypepackage\",\n      \"properties\" : [ {\n        \"id\" : \"callactivitycalledelementtype\",\n        \"type\" : \"flowable-calledelementtype\",\n        \"title\" : \"Called element type\",\n        \"value\" : \"key\",\n        \"description\" : \"Type of the used process reference.\",\n        \"popular\" : true\n      } ]\n    }, {\n      \"name\" : \"callactivityinparameterspackage\",\n      \"properties\" : [ {\n        \"id\" : \"callactivityinparameters\",\n        \"type\" : \"Complex\",\n        \"title\" : \"In parameters\",\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\" : \"Out parameters\",\n        \"value\" : \"\",\n        \"description\" : \"Definition of the output parameters\",\n        \"popular\" : true\n      } ]\n    }, {\n      \"name\" : \"callactivityinheritvariablespackage\",\n      \"properties\" : [ {\n        \"id\" : \"callactivityinheritvariables\",\n        \"type\" : \"Boolean\",\n        \"title\" : \"Inherit variables in sub process\",\n        \"value\" : \"false\",\n        \"description\" : \"Inherit parent process variables in the sub process.\",\n        \"popular\" : true\n      } ]\n    }, {\n      \"name\" : \"callactivitysamedeploymentpackage\",\n      \"properties\" : [ {\n        \"id\" : \"callactivitysamedeployment\",\n        \"type\" : \"Boolean\",\n        \"title\" : \"Start the referenced process from the same deployment.\",\n        \"value\" : \"false\",\n        \"description\" : \"Use the referenced process from the same deployment.\",\n        \"popular\" : true\n      } ]\n    }, {\n      \"name\" : \"callactivityfallbacktodefaulttenantpackage\",\n      \"properties\" : [ {\n        \"id\" : \"callactivityfallbacktodefaulttenant\",\n        \"type\" : \"Boolean\",\n        \"title\" : \"Fallback to default tenant\",\n        \"value\" : \"false\",\n        \"description\" : \"Look for the definition by key in the default tenant when current tenant search fails.\",\n        \"popular\" : true\n      } ]\n    }, {\n      \"name\" : \"callactivityprocessinstancenamepackage\",\n      \"properties\" : [ {\n        \"id\" : \"callactivityprocessinstancename\",\n        \"type\" : \"String\",\n        \"title\" : \"Process instance name\",\n        \"value\" : \"\",\n        \"description\" : \"An expression that resolves to the name of the child process instance\",\n        \"popular\" : true\n      } ]\n    }, {\n      \"name\" : \"callactivityinheritbusinesskeypackage\",\n      \"properties\" : [ {\n        \"id\" : \"callactivityinheritbusinesskey\",\n        \"type\" : \"Boolean\",\n        \"title\" : \"Inherit business key\",\n        \"value\" : \"false\",\n        \"description\" : \"Inherit the business key from the parent process.\",\n        \"popular\" : true\n      } ]\n    }, {\n      \"name\" : \"callactivityuselocalscopeforoutparameterspackage\",\n      \"properties\" : [ {\n        \"id\" : \"callactivityuselocalscopeforoutparameters\",\n        \"type\" : \"Boolean\",\n        \"title\" : \"Use local scope for out parameters\",\n        \"value\" : \"false\",\n        \"description\" : \"Use local variable scope for out parameters.\",\n        \"popular\" : true\n      } ]\n    }, {\n      \"name\" : \"callactivitybusinesskeypackage\",\n      \"properties\" : [ {\n        \"id\" : \"callactivitybusinesskey\",\n        \"type\" : \"String\",\n        \"title\" : \"Business key expression\",\n        \"value\" : \"\",\n        \"description\" : \"An expression that resolves to a business key for the child process instance\",\n        \"popular\" : true\n      } ]\n    }, {\n      \"name\" : \"callactivitycompleteasyncpackage\",\n      \"properties\" : [ {\n        \"id\" : \"callactivitycompleteasync\",\n        \"type\" : \"Boolean\",\n        \"title\" : \"Complete asynchronously\",\n        \"value\" : \"\",\n        \"description\" : \"If set, the child process ending and completing the call activity is done asynchronously. Useful when using parallel multi instance with a called process definition that has async tasks.\",\n        \"popular\" : true\n      } ]\n    }, {\n      \"name\" : \"cameltaskcamelcontextpackage\",\n      \"properties\" : [ {\n        \"id\" : \"cameltaskcamelcontext\",\n        \"type\" : \"String\",\n        \"title\" : \"Camel context\",\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\" : \"Endpoint 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\" : \"Language\",\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\" : \"Text\",\n        \"title\" : \"Payload expression\",\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\" : \"Result variable\",\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\" : \"Flow condition\",\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\" : \"Default flow\",\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\" : \"Time cycle (e.g. 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\" : \"Time date in 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\" : \"Time duration (e.g. 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\" : \"Time End Date in 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\" : \"Message reference\",\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\" : \"Signal reference\",\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\" : \"Error reference\",\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\" : \"Cancel activity\",\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\" : \"Initiator\",\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\" : \"flowable-multiinstance\",\n        \"title\" : \"Multi-instance type\",\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\" : \"Cardinality (Multi-instance)\",\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\" : \"Collection (Multi-instance)\",\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\" : \"Element variable (Multi-instance)\",\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\" : \"Completion condition (Multi-instance)\",\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\" : \"Is for compensation\",\n        \"value\" : \"false\",\n        \"description\" : \"A flag that identifies whether this activity is intended for the purposes of compensation.\",\n        \"popular\" : true,\n        \"refToView\" : \"compensation\"\n      } ]\n    }, {\n      \"name\" : \"sequencefloworderpackage\",\n      \"properties\" : [ {\n        \"id\" : \"sequencefloworder\",\n        \"type\" : \"Complex\",\n        \"title\" : \"Flow order\",\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\" : \"Signal definitions\",\n        \"value\" : \"\",\n        \"description\" : \"Signal definitions\",\n        \"popular\" : true\n      } ]\n    }, {\n      \"name\" : \"messagedefinitionspackage\",\n      \"properties\" : [ {\n        \"id\" : \"messagedefinitions\",\n        \"type\" : \"multiplecomplex\",\n        \"title\" : \"Message definitions\",\n        \"value\" : \"\",\n        \"description\" : \"Message definitions\",\n        \"popular\" : true\n      } ]\n    }, {\n      \"name\" : \"istransactionpackage\",\n      \"properties\" : [ {\n        \"id\" : \"istransaction\",\n        \"type\" : \"Boolean\",\n        \"title\" : \"Is a transaction sub process\",\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\" : \"formreferencepackage\",\n      \"properties\" : [ {\n        \"id\" : \"formreference\",\n        \"type\" : \"Complex\",\n        \"title\" : \"Form reference\",\n        \"value\" : \"\",\n        \"description\" : \"Reference to a form\",\n        \"popular\" : true\n      } ]\n    }, {\n      \"name\" : \"terminateAllpackage\",\n      \"properties\" : [ {\n        \"id\" : \"terminateAll\",\n        \"type\" : \"Boolean\",\n        \"title\" : \"Terminate all\",\n        \"value\" : \"false\",\n        \"description\" : \"Enable to terminate the process instance\",\n        \"popular\" : true\n      } ]\n    }, {\n      \"name\" : \"decisiontaskdecisiontablereferencepackage\",\n      \"properties\" : [ {\n        \"id\" : \"decisiontaskdecisiontablereference\",\n        \"type\" : \"Complex\",\n        \"title\" : \"Decision table reference\",\n        \"value\" : \"\",\n        \"description\" : \"Set the decision table reference\",\n        \"popular\" : true\n      } ]\n    }, {\n      \"name\" : \"decisiontaskthrowerroronnohitspackage\",\n      \"properties\" : [ {\n        \"id\" : \"decisiontaskthrowerroronnohits\",\n        \"type\" : \"Boolean\",\n        \"title\" : \"Throw error if no rules were hit\",\n        \"value\" : \"false\",\n        \"description\" : \"Should an error be thrown if no rules of the decision table were hit and consequently no result was found.\",\n        \"popular\" : true\n      } ]\n    }, {\n      \"name\" : \"decisiontaskfallbacktodefaulttenantpackage\",\n      \"properties\" : [ {\n        \"id\" : \"decisiontaskfallbacktodefaulttenant\",\n        \"type\" : \"Boolean\",\n        \"title\" : \"Fallback to default tenant\",\n        \"value\" : \"false\",\n        \"description\" : \"Find decision definition without tenant when previous attemps to find it with tenant failed.\",\n        \"popular\" : true\n      } ]\n    }, {\n      \"name\" : \"interruptingpackage\",\n      \"properties\" : [ {\n        \"id\" : \"interrupting\",\n        \"type\" : \"Boolean\",\n        \"title\" : \"Interrupting\",\n        \"value\" : \"true\",\n        \"description\" : \"Should all parent executions be terminated?\",\n        \"popular\" : true,\n        \"refToView\" : [ \"frame\" ]\n      } ]\n    }, {\n      \"name\" : \"completionconditionpackage\",\n      \"properties\" : [ {\n        \"id\" : \"completioncondition\",\n        \"type\" : \"String\",\n        \"title\" : \"Completion condition\",\n        \"value\" : \"\",\n        \"description\" : \"The completion condition for the adhoc sub process\",\n        \"popular\" : true\n      } ]\n    }, {\n      \"name\" : \"orderingpackage\",\n      \"properties\" : [ {\n        \"id\" : \"ordering\",\n        \"type\" : \"flowable-ordering\",\n        \"title\" : \"Ordering\",\n        \"value\" : \"Parallel\",\n        \"description\" : \"The ordering for the adhoc sub process\",\n        \"popular\" : true\n      } ]\n    }, {\n      \"name\" : \"cancelremaininginstancespackage\",\n      \"properties\" : [ {\n        \"id\" : \"cancelremaininginstances\",\n        \"type\" : \"Boolean\",\n        \"title\" : \"Cancel remaining instances\",\n        \"value\" : \"true\",\n        \"description\" : \"Cancel the remaining instances for the adhoc sub process?\",\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\", \"process_historylevelpackage\", \"isexecutablepackage\", \"datapropertiespackage\", \"executionlistenerspackage\", \"eventlistenerspackage\", \"signaldefinitionspackage\", \"messagedefinitionspackage\", \"process_potentialstarteruserpackage\",\"process_potentialstartergrouppackage\", \"process_iseagerexecutionfetchpackage\" ],\n    \"hiddenPropertyPackages\" : [ ],\n    \"roles\" : [ ]\n  }, {\n    \"type\" : \"node\",\n    \"id\" : \"StartNoneEvent\",\n    \"title\" : \"Start event\",\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\" : [ \"Start Events\" ],\n    \"propertyPackages\" : [ \"overrideidpackage\", \"namepackage\", \"documentationpackage\", \"executionlistenerspackage\", \"initiatorpackage\", \"formkeydefinitionpackage\", \"formreferencepackage\", \"formpropertiespackage\" ],\n    \"hiddenPropertyPackages\" : [ ],\n    \"roles\" : [ \"sequence_start\", \"Startevents_all\", \"StartEventsMorph\", \"all\" ]\n  }, {\n    \"type\" : \"node\",\n    \"id\" : \"StartTimerEvent\",\n    \"title\" : \"Start timer event\",\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\" : [ \"Start Events\" ],\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\" : \"Start signal event\",\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\" : [ \"Start Events\" ],\n    \"propertyPackages\" : [ \"overrideidpackage\", \"namepackage\", \"documentationpackage\", \"executionlistenerspackage\", \"signalrefpackage\", \"interruptingpackage\" ],\n    \"hiddenPropertyPackages\" : [ ],\n    \"roles\" : [ \"sequence_start\", \"Startevents_all\", \"StartEventsMorph\", \"all\" ]\n  }, {\n    \"type\" : \"node\",\n    \"id\" : \"StartMessageEvent\",\n    \"title\" : \"Start message event\",\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\" : [ \"Start Events\" ],\n    \"propertyPackages\" : [ \"overrideidpackage\", \"namepackage\", \"documentationpackage\", \"executionlistenerspackage\", \"messagerefpackage\", \"interruptingpackage\" ],\n    \"hiddenPropertyPackages\" : [ ],\n    \"roles\" : [ \"sequence_start\", \"Startevents_all\", \"StartEventsMorph\", \"all\" ]\n  }, {\n    \"type\" : \"node\",\n    \"id\" : \"StartErrorEvent\",\n    \"title\" : \"Start error event\",\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\" : [ \"Start Events\" ],\n    \"propertyPackages\" : [ \"overrideidpackage\", \"namepackage\", \"documentationpackage\", \"executionlistenerspackage\", \"errorrefpackage\", \"interruptingpackage\" ],\n    \"hiddenPropertyPackages\" : [ ],\n    \"roles\" : [ \"sequence_start\", \"Startevents_all\", \"StartEventsMorph\", \"all\" ]\n  }, {\n    \"type\" : \"node\",\n    \"id\" : \"UserTask\",\n    \"title\" : \"User task\",\n    \"description\" : \"A manual task assigned to a specific person\",\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\" : [ \"Activities\" ],\n    \"propertyPackages\" : [ \"overrideidpackage\", \"namepackage\", \"documentationpackage\", \"asynchronousdefinitionpackage\", \"exclusivedefinitionpackage\", \"executionlistenerspackage\", \"multiinstance_typepackage\", \"multiinstance_cardinalitypackage\", \"multiinstance_collectionpackage\", \"multiinstance_variablepackage\", \"multiinstance_conditionpackage\", \"isforcompensationpackage\", \"usertaskassignmentpackage\", \"formkeydefinitionpackage\", \"formreferencepackage\", \"duedatedefinitionpackage\", \"prioritydefinitionpackage\", \"formpropertiespackage\", \"tasklistenerspackage\", \"skipexpressionpackage\", \"categorypackage\" ],\n    \"hiddenPropertyPackages\" : [ ],\n    \"roles\" : [ \"Activity\", \"sequence_start\", \"sequence_end\", \"ActivitiesMorph\", \"all\" ]\n  }, {\n    \"type\" : \"node\",\n    \"id\" : \"ServiceTask\",\n    \"title\" : \"Service task\",\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\" : [ \"Activities\" ],\n    \"propertyPackages\" : [ \"overrideidpackage\", \"namepackage\", \"documentationpackage\", \"asynchronousdefinitionpackage\", \"exclusivedefinitionpackage\", \"servicetasktriggerablepackage\", \"executionlistenerspackage\", \"multiinstance_typepackage\", \"multiinstance_cardinalitypackage\", \"multiinstance_collectionpackage\", \"multiinstance_variablepackage\", \"multiinstance_conditionpackage\", \"isforcompensationpackage\", \"servicetaskclasspackage\", \"servicetaskexpressionpackage\", \"servicetaskdelegateexpressionpackage\", \"servicetaskfieldspackage\", \"servicetaskresultvariablepackage\", \"skipexpressionpackage\" ],\n    \"hiddenPropertyPackages\" : [ ],\n    \"roles\" : [ \"Activity\", \"sequence_start\", \"sequence_end\", \"ActivitiesMorph\", \"all\" ]\n  }, {\n    \"type\" : \"node\",\n    \"id\" : \"ScriptTask\",\n    \"title\" : \"Script task\",\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\" : [ \"Activities\" ],\n    \"propertyPackages\" : [ \"scriptformatpackage\", \"scripttextpackage\", \"overrideidpackage\", \"namepackage\", \"documentationpackage\", \"asynchronousdefinitionpackage\", \"exclusivedefinitionpackage\", \"executionlistenerspackage\", \"multiinstance_typepackage\", \"multiinstance_cardinalitypackage\", \"multiinstance_collectionpackage\", \"multiinstance_variablepackage\", \"multiinstance_conditionpackage\", \"isforcompensationpackage\", \"scriptautostorevariablespackage\" ],\n    \"hiddenPropertyPackages\" : [ ],\n    \"roles\" : [ \"Activity\", \"sequence_start\", \"sequence_end\", \"ActivitiesMorph\", \"all\" ]\n  }, {\n    \"type\" : \"node\",\n    \"id\" : \"BusinessRule\",\n    \"title\" : \"Business rule task\",\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\" : [ \"Activities\" ],\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\" : \"Receive task\",\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\" : [ \"Activities\" ],\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\" : \"Manual task\",\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\" : [ \"Activities\" ],\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\" : \"Mail task\",\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\" : [ \"Activities\" ],\n    \"propertyPackages\" : [ \"overrideidpackage\", \"namepackage\", \"documentationpackage\", \"asynchronousdefinitionpackage\", \"exclusivedefinitionpackage\", \"executionlistenerspackage\", \"multiinstance_typepackage\", \"multiinstance_cardinalitypackage\", \"multiinstance_collectionpackage\", \"multiinstance_variablepackage\", \"multiinstance_conditionpackage\", \"isforcompensationpackage\", \"mailtaskheaderspackage\", \"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 task\",\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\" : [ \"Activities\" ],\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\" : \"HttpTask\",\n    \"title\" : \"Http task\",\n    \"description\" : \"A HTTP 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 16.704699,5.9229055 q 0.358098,0 0.608767,0.2506681 0.250669,0.250668 0.250669,0.6087677 0,0.3580997 -0.250669,0.6087677 -0.250669,0.2506679 -0.608767,0.2506679 -0.358098,0 -0.608767,-0.2506679 -0.250669,-0.250668 -0.250669,-0.6087677 0,-0.3580997 0.250669,-0.6087677 0.250669,-0.2506681 0.608767,-0.2506681 z m 2.578308,-2.0053502 q -2.229162,0 -3.854034,0.6759125 -1.624871,0.6759067 -3.227361,2.2694472 -0.716197,0.725146 -1.575633,1.7457293 L 7.2329969,8.7876913 Q 7.0897576,8.8055849 7.000233,8.9309334 L 4.9948821,12.368677 q -0.035811,0.06267 -0.035811,0.143242 0,0.107426 0.080572,0.205905 l 0.5729577,0.572957 q 0.125334,0.116384 0.2864786,0.07162 l 2.4708789,-0.760963 2.5156417,2.515645 -0.76096,2.470876 q -0.009,0.02687 -0.009,0.08057 0,0.125338 0.08058,0.205905 l 0.572957,0.572958 q 0.170096,0.152194 0.349146,0.04476 l 3.437744,-2.005351 q 0.125335,-0.08953 0.143239,-0.232763 l 0.17905,-3.392986 q 1.02058,-0.859435 1.745729,-1.575629 1.67411,-1.6830612 2.309735,-3.2049805 0.635625,-1.5219191 0.635625,-3.8585111 0,-0.1253369 -0.08505,-0.2148575 -0.08505,-0.089526 -0.201431,-0.089526 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.http.png\",\n    \"groups\" : [ \"Activities\" ],\n    \"propertyPackages\" : [ \"overrideidpackage\", \"namepackage\", \"documentationpackage\", \"asynchronousdefinitionpackage\", \"exclusivedefinitionpackage\", \"executionlistenerspackage\", \"multiinstance_typepackage\", \"multiinstance_cardinalitypackage\", \"multiinstance_collectionpackage\", \"multiinstance_variablepackage\", \"multiinstance_conditionpackage\", \"isforcompensationpackage\", \"httptaskrequestmethodpackage\", \"httptaskrequesturlpackage\", \"httptaskrequestheaderspackage\", \"httptaskrequestbodypackage\", \"httptaskrequestbodyencodingpackage\", \"httptaskrequesttimeoutpackage\", \"httptaskdisallowredirectspackage\", \"httptaskfailstatuscodespackage\", \"httptaskhandlestatuscodespackage\", \"httptaskignoreexceptionpackage\", \"httptaskresponsevariablenamepackage\", \"httptasksaverequestvariablespackage\", \"httptasksaveresponseparameterspackage\", \"httptaskresultvariableprefixpackage\", \"httptasksaveresponseparameterstransientpackage\", \"httptasksaveresponseasjsonpackage\" ],\n    \"hiddenPropertyPackages\" : [ ],\n    \"roles\" : [ \"Activity\", \"sequence_start\", \"sequence_end\", \"ActivitiesMorph\", \"all\" ]\n  }, {\n    \"type\" : \"node\",\n    \"id\" : \"MuleTask\",\n    \"title\" : \"Mule task\",\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\" : [ \"Activities\" ],\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\" : [ \"Activities\" ],\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\" : \"DecisionTask\",\n    \"title\" : \"Decision task\",\n    \"description\" : \"Task to use the Flowable DMN rule engine\",\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=\\\"decisionTask\\\" 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.9,2.4000386 3.7,0 0,2.7999224 -3.7,0 z m 4.36364,0 3.7,0 0,2.7999224 -3.7,0 z m 4.36364,0 3.7,0 0,2.7999224 -3.7,0 z m -8.67364,3.9 3.7,0 0,2.7999224 -3.7,0 z m 4.36364,0 3.7,0 0,2.7999224 -3.7,0 z m 4.36364,0 3.7,0 0,2.7999224 -3.7,0 z m -8.67364,3.9 3.7,0 0,2.7999224 -3.7,0 z m 4.36364,0 3.7,0 0,2.7999224 -3.7,0 z m 4.36364,0 3.7,0 0,2.7999224 -3.7,0 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\\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.decision.png\",\n    \"groups\" : [ \"Activities\" ],\n    \"propertyPackages\" : [ \"overrideidpackage\", \"namepackage\", \"documentationpackage\", \"asynchronousdefinitionpackage\", \"exclusivedefinitionpackage\", \"executionlistenerspackage\", \"multiinstance_typepackage\", \"multiinstance_cardinalitypackage\", \"multiinstance_collectionpackage\", \"multiinstance_variablepackage\", \"multiinstance_conditionpackage\", \"isforcompensationpackage\", \"decisiontaskdecisiontablereferencepackage\", \"decisiontaskthrowerroronnohitspackage\", \"decisiontaskfallbacktodefaulttenantpackage\" ],\n    \"hiddenPropertyPackages\" : [ ],\n    \"roles\" : [ \"Activity\", \"sequence_start\", \"sequence_end\", \"ActivitiesMorph\", \"all\" ]\n  },\n    {\n      \"type\": \"node\",\n      \"id\": \"ShellTask\",\n      \"title\": \"Shell task\",\n      \"description\": \"An automatic task with shell batch 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=\\\"shellTask\\\" transform=\\\"translate(2,2)\\\">\\n\\t\\t<path oryx:anchors=\\\"top left\\\"\\n\\t\\t\\td=\\\"m 1,2 0,14 16,0 0,-14 z m 1.4,3 12.7,0 0,10 -12.7,0 z\\\"\\n     \\t\\tstyle=\\\"fill:#72a7d0;stroke:none\\\"\\n\\t\\t/><text x='3' y='9' style='fill:#72a7d0;font-size:5px;'><![CDATA[>_]]></text>\\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.shell.png\",\n      \"groups\": [\n        \"Activities\"\n      ],\n      \"propertyPackages\": [\n        \"overrideidpackage\",\n        \"namepackage\",\n        \"documentationpackage\",\n        \"asynchronousdefinitionpackage\",\n        \"shellcommandpackage\",\n        \"shellarg1package\",\n        \"shellarg2package\",\n        \"shellarg3package\",\n        \"shellarg4package\",\n        \"shellarg5package\",\n        \"shellwaitpackage\",\n        \"shelloutputvariablepackage\",\n        \"shellerrorcodevariablepackage\",\n        \"shellredirecterrorpackage\",\n        \"shellcleanenvpackage\",\n        \"shelldirectorypackage\",\n        \"exclusivedefinitionpackage\",\n        \"executionlistenerspackage\",\n        \"multiinstance_typepackage\",\n        \"multiinstance_cardinalitypackage\",\n        \"multiinstance_collectionpackage\",\n        \"multiinstance_variablepackage\",\n        \"multiinstance_conditionpackage\",\n        \"isforcompensationpackage\"\n      ],\n      \"hiddenPropertyPackages\": [],\n      \"roles\": [\n        \"Activity\",\n        \"sequence_start\",\n        \"sequence_end\",\n        \"ActivitiesMorph\",\n        \"all\"\n      ]\n    },{\n      \"type\" : \"node\",\n      \"id\" : \"SubProcess\",\n      \"title\" : \"Sub process\",\n      \"description\" : \"A sub process scope\",\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\" : [ \"Structural\" ],\n      \"propertyPackages\" : [ \"overrideidpackage\", \"namepackage\", \"documentationpackage\", \"asynchronousdefinitionpackage\", \"exclusivedefinitionpackage\", \"datapropertiespackage\", \"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\" : \"CollapsedSubProcess\",\n      \"title\" : \"Collapsed Sub process\",\n      \"description\" : \"A sub process scope\",\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=\\\"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<g id=\\\"subprocess\\\">\\n\\t\\t<rect height=\\\"10\\\" width=\\\"10\\\" x=\\\"45\\\" y=\\\"65\\\" stroke=\\\"#bbbbbb\\\" fill=\\\"none\\\" />\\n\\t\\t<path d=\\\"M50 65 L50 75\\\" stroke=\\\"black\\\" />\\n\\t\\t<path d=\\\"M45 70 L55 70\\\" stroke=\\\"black\\\" />\\n\\t</g>\\n  </g>\\n</svg>\",\n      \"icon\" : \"activity/subprocess.png\",\n      \"groups\" : [ \"Structural\" ],\n      \"propertyPackages\" : [ \"overrideidpackage\", \"namepackage\", \"documentationpackage\", \"asynchronousdefinitionpackage\", \"exclusivedefinitionpackage\", \"datapropertiespackage\", \"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\" : \"Event sub process\",\n      \"description\" : \"A event sub process scope\",\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\" : [ \"Structural\" ],\n      \"propertyPackages\" : [ \"overrideidpackage\", \"namepackage\", \"documentationpackage\", \"asynchronousdefinitionpackage\", \"exclusivedefinitionpackage\", \"executionlistenerspackage\" ],\n      \"hiddenPropertyPackages\" : [ ],\n      \"roles\" : [ \"Activity\", \"all\", \"EventSubProcess\" ]\n    }, {\n      \"type\" : \"node\",\n      \"id\" : \"CallActivity\",\n      \"title\" : \"Call activity\",\n      \"description\" : \"A call activity\",\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\" : [ \"Structural\" ],\n      \"propertyPackages\" : [ \"overrideidpackage\", \"namepackage\", \"documentationpackage\", \"asynchronousdefinitionpackage\", \"exclusivedefinitionpackage\", \"callactivitycompleteasyncpackage\", \"executionlistenerspackage\", \"callactivitycalledelementpackage\", \"callactivitycalledelementtypepackage\", \"callactivityinparameterspackage\", \"callactivityoutparameterspackage\", \"callactivityinheritvariablespackage\", \"callactivitysamedeploymentpackage\", \"callactivityfallbacktodefaulttenantpackage\", \"callactivityprocessinstancenamepackage\", \"callactivityinheritbusinesskeypackage\", \"callactivitybusinesskeypackage\", \"callactivityuselocalscopeforoutparameterspackage\", \"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\" : \"Exclusive gateway\",\n      \"description\" : \"A choice gateway\",\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\" : [ \"Gateways\" ],\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\" : \"Parallel gateway\",\n      \"description\" : \"A parallel gateway\",\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\" : [ \"Gateways\" ],\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\" : \"Inclusive gateway\",\n      \"description\" : \"An inclusive gateway\",\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\" : [ \"Gateways\" ],\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\" : \"Event gateway\",\n      \"description\" : \"An event gateway\",\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     id=\\\"g1027\\\">\\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       id=\\\"circle\\\"\\n       cx=\\\"16\\\"\\n       cy=\\\"16\\\"\\n       r=\\\"10.4\\\"\\n       stroke=\\\"#585858\\\"\\n       style=\\\"fill:none;stroke-width:0.5\\\" />\\n    <circle\\n       id=\\\"circle2\\\"\\n       cx=\\\"16\\\"\\n       cy=\\\"16\\\"\\n       r=\\\"11.7\\\"\\n       stroke=\\\"#585858\\\"\\n       style=\\\"fill:none;stroke-width:0.5\\\" />\\n    <path\\n       d=\\\"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       id=\\\"middlePolygon\\\"\\n       stroke=\\\"#585858\\\"\\n       style=\\\"fill:none;fill-opacity:1;stroke-width:1.39999998;stroke-linejoin:bevel;stroke-opacity:1\\\" />\\n    <g\\n       id=\\\"instantiate\\\">\\n      <path\\n         d=\\\"M -4.5,16 L 16,-4.5 L 35.5,16 L 16,35.5z\\\"\\n         id=\\\"bg_frame2\\\"\\n         fill=\\\"#ffffff\\\"\\n         stroke=\\\"#585858\\\"\\n         style=\\\"stroke-width:1\\\" />\\n      <circle\\n         id=\\\"circle3\\\"\\n         cx=\\\"16\\\"\\n         cy=\\\"16\\\"\\n         r=\\\"11\\\"\\n         stroke=\\\"#585858\\\"\\n         style=\\\"fill:none;stroke-width:1\\\" />\\n      <path\\n         d=\\\"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         id=\\\"middlePolygon2\\\"\\n         stroke=\\\"#585858\\\"\\n         style=\\\"fill:none;fill-opacity:1;stroke-width:1.39999998;stroke-linejoin:bevel;stroke-opacity:1\\\" />\\n      <g\\n         id=\\\"parallel\\\">\\n        <path\\n           d=\\\"M -4.5,16 L 16,-4.5 L 35.5,16 L 16,35.5z\\\"\\n           id=\\\"bg_frame3\\\"\\n           style=\\\"stroke-width:1\\\"\\n           stroke=\\\"#585858\\\"\\n           fill=\\\"#ffffff\\\" />\\n\\n        <path\\n           style=\\\"fill:none;stroke-width:1.5\\\"\\n           stroke=\\\"#585858\\\"\\n           d=\\\"m 16.128163,8.1671486 7.721331,5.6098764 -2.949286,9.076969 -9.544091,0 -2.9492862,-9.07697 z\\\"/>\\n        <circle     \\n           cx=\\\"16\\\"\\n           cy=\\\"16\\\"\\n           r=\\\"11.5\\\"\\n           stroke=\\\"#585858\\\"\\n           style=\\\"fill:none;stroke:#000000;stroke-width:0.4;\\\"\\n           />\\n        <circle \\n           cx=\\\"16\\\"\\n           cy=\\\"16\\\"\\n           r=\\\"10.5\\\"\\n           stroke=\\\"#585858\\\"\\n           style=\\\"fill:none;stroke-width:0.4;\\\" />\\n      </g>\\n    </g>\\n    <text\\n       id=\\\"text_name\\\"\\n       x=\\\"26\\\"\\n       y=\\\"26\\\"\\n       oryx:align=\\\"left top\\\" />\\n  </g>\\n\\n</svg>\\n\",\n      \"icon\" : \"gateway/eventbased.png\",\n      \"groups\" : [ \"Gateways\" ],\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\" : \"Boundary error event\",\n      \"description\" : \"A boundary event that catches a 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    <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\" : [ \"Boundary Events\" ],\n      \"propertyPackages\" : [ \"overrideidpackage\", \"namepackage\", \"documentationpackage\", \"errorrefpackage\" ],\n      \"hiddenPropertyPackages\" : [ ],\n      \"roles\" : [ \"sequence_start\", \"BoundaryEventsMorph\", \"IntermediateEventOnActivityBoundary\" ]\n    }, {\n      \"type\" : \"node\",\n      \"id\" : \"BoundaryTimerEvent\",\n      \"title\" : \"Boundary timer event\",\n      \"description\" : \"A boundary 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  <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\" : [ \"Boundary Events\" ],\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\" : \"Boundary signal event\",\n      \"description\" : \"A boundary 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  <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\" : [ \"Boundary Events\" ],\n      \"propertyPackages\" : [ \"overrideidpackage\", \"namepackage\", \"documentationpackage\", \"signalrefpackage\", \"cancelactivitypackage\" ],\n      \"hiddenPropertyPackages\" : [ ],\n      \"roles\" : [ \"sequence_start\", \"BoundaryEventsMorph\", \"IntermediateEventOnActivityBoundary\" ]\n    }, {\n      \"type\" : \"node\",\n      \"id\" : \"BoundaryMessageEvent\",\n      \"title\" : \"Boundary message event\",\n      \"description\" : \"A boundary 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  <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\" : [ \"Boundary Events\" ],\n      \"propertyPackages\" : [ \"overrideidpackage\", \"namepackage\", \"documentationpackage\", \"messagerefpackage\", \"cancelactivitypackage\" ],\n      \"hiddenPropertyPackages\" : [ ],\n      \"roles\" : [ \"sequence_start\", \"BoundaryEventsMorph\", \"IntermediateEventOnActivityBoundary\" ]\n    }, {\n      \"type\" : \"node\",\n      \"id\" : \"BoundaryCancelEvent\",\n      \"title\" : \"Boundary cancel event\",\n      \"description\" : \"A boundary cancel 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  \\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\" : [ \"Boundary Events\" ],\n      \"propertyPackages\" : [ \"overrideidpackage\", \"namepackage\", \"documentationpackage\" ],\n      \"hiddenPropertyPackages\" : [ ],\n      \"roles\" : [ \"sequence_start\", \"BoundaryEventsMorph\", \"IntermediateEventOnActivityBoundary\" ]\n    }, {\n      \"type\" : \"node\",\n      \"id\" : \"BoundaryCompensationEvent\",\n      \"title\" : \"Boundary compensation event\",\n      \"description\" : \"A boundary compensation 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\\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\" : [ \"Boundary Events\" ],\n      \"propertyPackages\" : [ \"overrideidpackage\", \"namepackage\", \"documentationpackage\" ],\n      \"hiddenPropertyPackages\" : [ ],\n      \"roles\" : [ \"BoundaryEventsMorph\", \"IntermediateEventOnActivityBoundary\", \"all\" ]\n    }, {\n      \"type\" : \"node\",\n      \"id\" : \"CatchTimerEvent\",\n      \"title\" : \"Intermediate timer catching event\",\n      \"description\" : \"An intermediate catching 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  <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\" : [ \"Intermediate Catching Events\" ],\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\" : \"Intermediate signal catching event\",\n      \"description\" : \"An intermediate catching 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  <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\" : [ \"Intermediate Catching Events\" ],\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\" : \"Intermediate message catching event\",\n      \"description\" : \"An intermediate catching 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  <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=\\\"#585858\\\" fill=\\\"none\\\" 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\" : [ \"Intermediate Catching Events\" ],\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\" : \"Intermediate none throwing event\",\n      \"description\" : \"An intermediate 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  <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\" : [ \"Intermediate Throwing Events\" ],\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\" : \"Intermediate signal throwing event\",\n      \"description\" : \"An intermediate 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  <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\" : [ \"Intermediate Throwing Events\" ],\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\" : \"End event\",\n      \"description\" : \"An end 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=\\\"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\" : [ \"End Events\" ],\n      \"propertyPackages\" : [ \"overrideidpackage\", \"namepackage\", \"documentationpackage\", \"executionlistenerspackage\" ],\n      \"hiddenPropertyPackages\" : [ ],\n      \"roles\" : [ \"EndEventsMorph\", \"sequence_end\", \"all\" ]\n    }, {\n      \"type\" : \"node\",\n      \"id\" : \"EndErrorEvent\",\n      \"title\" : \"End error event\",\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\" : [ \"End Events\" ],\n      \"propertyPackages\" : [ \"overrideidpackage\", \"namepackage\", \"documentationpackage\", \"executionlistenerspackage\", \"errorrefpackage\" ],\n      \"hiddenPropertyPackages\" : [ ],\n      \"roles\" : [ \"EndEventsMorph\", \"sequence_end\", \"all\" ]\n    }, {\n      \"type\" : \"node\",\n      \"id\" : \"EndCancelEvent\",\n      \"title\" : \"End cancel event\",\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\" : [ \"End Events\" ],\n      \"propertyPackages\" : [ \"overrideidpackage\", \"namepackage\", \"documentationpackage\", \"executionlistenerspackage\" ],\n      \"hiddenPropertyPackages\" : [ ],\n      \"roles\" : [ \"EndEventsMorph\", \"sequence_end\", \"all\" ]\n    }, {\n      \"type\" : \"node\",\n      \"id\" : \"EndTerminateEvent\",\n      \"title\" : \"End terminate event\",\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\" : [ \"End Events\" ],\n      \"propertyPackages\" : [ \"overrideidpackage\", \"namepackage\", \"documentationpackage\", \"executionlistenerspackage\", \"terminateAllpackage\" ],\n      \"hiddenPropertyPackages\" : [ ],\n      \"roles\" : [ \"EndEventsMorph\", \"sequence_end\", \"all\" ]\n    }, {\n      \"type\" : \"node\",\n      \"id\" : \"Pool\",\n      \"title\" : \"Pool\",\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\" : [ \"Swimlanes\" ],\n      \"layout\" : [ {\n        \"type\" : \"layout.bpmn2_0.pool\"\n      } ],\n      \"propertyPackages\" : [ \"overrideidpackage\", \"namepackage\", \"documentationpackage\", \"process_idpackage\", \"isexecutablepackage\" ],\n      \"hiddenPropertyPackages\" : [ ],\n      \"roles\" : [ \"canContainArtifacts\", \"all\" ]\n    }, {\n      \"type\" : \"node\",\n      \"id\" : \"Lane\",\n      \"title\" : \"Lane\",\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\" : [ \"Swimlanes\" ],\n      \"propertyPackages\" : [ \"overrideidpackage\", \"namepackage\", \"documentationpackage\" ],\n      \"hiddenPropertyPackages\" : [ ],\n      \"roles\" : [ \"PoolChild\", \"canContainArtifacts\", \"all\" ]\n    }, {\n      \"type\" : \"edge\",\n      \"id\" : \"SequenceFlow\",\n      \"title\" : \"Sequence flow\",\n      \"description\" : \"Sequence flow defines the execution order of activities.\",\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\" : [ \"Connecting Objects\" ],\n      \"layout\" : [ {\n        \"type\" : \"layout.bpmn2_0.sequenceflow\"\n      } ],\n      \"propertyPackages\" : [ \"overrideidpackage\", \"namepackage\", \"documentationpackage\", \"conditionsequenceflowpackage\", \"executionlistenerspackage\", \"defaultflowpackage\", \"skipexpressionpackage\" ],\n      \"hiddenPropertyPackages\" : [ ],\n      \"roles\" : [ \"ConnectingObjectsMorph\", \"all\" ]\n    }, {\n      \"type\" : \"edge\",\n      \"id\" : \"MessageFlow\",\n      \"title\" : \"Message flow\",\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\" : [ \"Connecting Objects\" ],\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\" : \"Association\",\n      \"description\" : \"Associates a text annotation with an element.\",\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\" : [ \"Connecting Objects\" ],\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\" : \"DataAssociation\",\n      \"description\" : \"Associates a data element with an activity.\",\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\" : [ \"Connecting Objects\" ],\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\" : \"Text annotation\",\n      \"description\" : \"Annotates elements with description text.\",\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\" : [ \"Artifacts\" ],\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      \"type\" : \"node\",\n      \"id\" : \"AdhocSubProcess\",\n      \"title\" : \"Adhoc sub process\",\n      \"description\" : \"An adhoc sub process\",\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<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<text \\n\\t\\toryx:anchors=\\\"bottom\\\"\\n\\t\\tx=\\\"101\\\"\\n\\t\\ty=\\\"157\\\"\\n\\t\\tfont-size=\\\"20\\\"\\n\\t\\ttransform=\\\"translate(8,0)\\\"\\n\\t>~</text>\\n  </g>\\n</svg>\",\n      \"icon\" : \"activity/adhoc.subprocess.png\",\n      \"groups\" : [ \"Structural\" ],\n      \"propertyPackages\" : [ \"overrideidpackage\", \"namepackage\", \"documentationpackage\", \"completionconditionpackage\", \"orderingpackage\", \"cancelremaininginstancespackage\" ],\n      \"hiddenPropertyPackages\" : [ ],\n      \"roles\" : [ \"Activity\", \"sequence_start\", \"sequence_end\", \"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\" : \"AdhocSubProcess\",\n      \"contains\" : [ \"sequence_start\", \"sequence_end\", \"from_task_event\", \"to_task_event\", \"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": "flowable-ui/src/main/resources/stencilset/en/stencilset_cmmn.json",
    "content": "{\n  \"title\" : \"CMMN editor\",\n  \"namespace\" : \"http://b3mn.org/stencilset/cmmn1.1#\",\n  \"description\" : \"CMMN case editor\",\n  \"propertyPackages\" : [ {\n    \"name\" : \"case_idpackage\",\n    \"properties\" : [ {\n      \"id\" : \"case_id\",\n      \"type\" : \"String\",\n      \"title\" : \"Case identifier\",\n      \"value\" : \"caseModel\",\n      \"description\" : \"Unique identifier of the case definition.\",\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\" : \"Name\",\n      \"value\" : \"\",\n      \"description\" : \"The descriptive name of the CMMN element.\",\n      \"popular\" : true,\n      \"refToView\" : \"text_name\"\n    } ]\n  }, {\n    \"name\" : \"documentationpackage\",\n    \"properties\" : [ {\n      \"id\" : \"documentation\",\n      \"type\" : \"Text\",\n      \"title\" : \"Documentation\",\n      \"value\" : \"\",\n      \"description\" : \"The descriptive name of the CMMN element.\",\n      \"popular\" : true\n    } ]\n  }, {\n    \"name\" : \"blockingpackage\",\n    \"properties\" : [ {\n      \"id\" : \"isblocking\",\n      \"type\" : \"Boolean\",\n      \"title\" : \"Blocking\",\n      \"value\" : \"true\",\n      \"description\" : \"Boolean property, default true. If false the task will automatically complete the task after executing any associated logic\",\n      \"popular\" : true\n    },\n    {\n      \"id\" : \"isblockingexpression\",\n      \"type\" : \"String\",\n      \"title\" : \"Blocking expression\",\n      \"value\" : \"\",\n      \"description\" : \"An expression to control at runtime whether this task is blocking or not. When set, the value of the blocking property is ignored.\",\n      \"popular\" : true\n    } ]\n  }, {\n    \"name\" : \"case_initiatorvariablenamepackage\",\n    \"properties\" : [ {\n      \"id\" : \"case_initiatorvariablename\",\n      \"type\" : \"String\",\n      \"title\" : \"Initiator variable name\",\n      \"value\" : \"\",\n      \"description\" : \"Sets the variable name to be used for the case initiator value.\",\n      \"popular\" : true\n    } ]\n  }, {\n    \"name\" : \"case_authorpackage\",\n    \"properties\" : [ {\n      \"id\" : \"case_author\",\n      \"type\" : \"String\",\n      \"title\" : \"Case author\",\n      \"value\" : \"\",\n      \"description\" : \"Author of the case definition.\",\n      \"popular\" : true\n    } ]\n  }, {\n    \"name\" : \"case_versionpackage\",\n    \"properties\" : [ {\n      \"id\" : \"case_version\",\n      \"type\" : \"String\",\n      \"title\" : \"Case version string (documentation only)\",\n      \"value\" : \"\",\n      \"description\" : \"Version identifier for documentation purpose.\",\n      \"popular\" : true\n    } ]\n  }, {\n    \"name\" : \"case_namespacepackage\",\n    \"properties\" : [ {\n      \"id\" : \"case_namespace\",\n      \"type\" : \"String\",\n      \"title\" : \"Target namespace\",\n      \"value\" : \"http://www.flowable.org/casedef\",\n      \"description\" : \"Target namespace for the case definition.\",\n      \"popular\" : true\n    } ]\n  }, {\n    \"name\" : \"usertaskassignmentpackage\",\n    \"properties\" : [ {\n      \"id\" : \"usertaskassignment\",\n      \"type\" : \"Complex\",\n      \"title\" : \"Assignments\",\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\" : \"Form properties\",\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\" : \"Form key\",\n      \"value\" : \"\",\n      \"description\" : \"Form key that provides a reference to a form.\",\n      \"popular\" : true\n    } ]\n  }, {\n    \"name\" : \"duedatedefinitionpackage\",\n    \"properties\" : [ {\n      \"id\" : \"duedatedefinition\",\n      \"type\" : \"String\",\n      \"title\" : \"Due date\",\n      \"value\" : \"\",\n      \"description\" : \"Due date of the user task.\",\n      \"popular\" : true\n    } ]\n  }, {\n    \"name\" : \"prioritydefinitionpackage\",\n    \"properties\" : [ {\n      \"id\" : \"prioritydefinition\",\n      \"type\" : \"String\",\n      \"title\" : \"Priority\",\n      \"value\" : \"\",\n      \"description\" : \"Priority of the user task.\",\n      \"popular\" : true\n    } ]\n  }, {\n    \"name\" : \"servicetaskclasspackage\",\n    \"properties\" : [ {\n      \"id\" : \"servicetaskclass\",\n      \"type\" : \"String\",\n      \"title\" : \"Class\",\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\" : \"Text\",\n      \"title\" : \"Expression\",\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\" : \"Text\",\n      \"title\" : \"Delegate expression\",\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\" : \"Class fields\",\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\" : \"Script format\",\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\" : \"Script\",\n      \"value\" : \"\",\n      \"description\" : \"Script text of the script task.\",\n      \"popular\" : true\n    } ]\n  }, {\n    \"name\" : \"asyncpackage\",\n    \"properties\" : [ {\n      \"id\" : \"isasync\",\n      \"type\" : \"Boolean\",\n      \"title\" : \"Asynchronous\",\n      \"value\" : \"\",\n      \"description\" : \"Indicates if the task needs to be executed asynchronously.\",\n      \"popular\" : true\n    }, {\n      \"id\" : \"isexclusive\",\n      \"type\" : \"Boolean\",\n      \"title\" : \"Exclusive\",\n      \"value\" : \"\",\n      \"description\" : \"Indicates if an asynchronous task must be executed exclusively\",\n      \"popular\" : true\n    } ]\n  }, {\n    \"name\" : \"mailtasktopackage\",\n    \"properties\" : [ {\n      \"id\" : \"mailtaskto\",\n      \"type\" : \"Text\",\n      \"title\" : \"To\",\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\" : \"From\",\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\" : \"Subject\",\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\" : \"Cc\",\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\" : \"Bcc\",\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\" : \"Text\",\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\" : \"httptaskrequestmethodpackage\",\n    \"properties\" : [ {\n      \"id\" : \"httptaskrequestmethod\",\n      \"type\" : \"String\",\n      \"title\" : \"Request method\",\n      \"value\" : \"\",\n      \"description\" : \"Request method (For example - GET,POST,PUT etc).\",\n      \"popular\" : true\n    } ]\n  }, {\n    \"name\" : \"httptaskrequesturlpackage\",\n    \"properties\" : [ {\n      \"id\" : \"httptaskrequesturl\",\n      \"type\" : \"Text\",\n      \"title\" : \"Request URL\",\n      \"value\" : \"\",\n      \"description\" : \"Request URL (For example - http://flowable.org).\",\n      \"popular\" : true\n    } ]\n  }, {\n    \"name\" : \"httptaskrequestheaderspackage\",\n    \"properties\" : [ {\n      \"id\" : \"httptaskrequestheaders\",\n      \"type\" : \"Text\",\n      \"title\" : \"Request headers\",\n      \"value\" : \"\",\n      \"description\" : \"Line separated HTTP request headers (For example - Content-Type: application/json).\",\n      \"popular\" : true\n    } ]\n  }, {\n    \"name\" : \"httptaskrequestbodypackage\",\n    \"properties\" : [ {\n      \"id\" : \"httptaskrequestbody\",\n      \"type\" : \"Text\",\n      \"title\" : \"Request body\",\n      \"value\" : \"\",\n      \"description\" : \"Request body (For example- ${sampleBody}).\",\n      \"popular\" : true\n    } ]\n  }, {\n    \"name\" : \"httptaskrequesttimeoutpackage\",\n    \"properties\" : [ {\n      \"id\" : \"httptaskrequesttimeout\",\n      \"type\" : \"String\",\n      \"title\" : \"Request timeout\",\n      \"value\" : \"\",\n      \"description\" : \"Timeout in milliseconds for the request (For example - 5000).\",\n      \"popular\" : true\n    } ]\n  }, {\n    \"name\" : \"httptaskdisallowredirectspackage\",\n    \"properties\" : [ {\n      \"id\" : \"httptaskdisallowredirects\",\n      \"type\" : \"String\",\n      \"title\" : \"Disallow redirects\",\n      \"value\" : \"\",\n      \"description\" : \"Flag to disallow HTTP redirects.\",\n      \"popular\" : true\n    } ]\n  }, {\n    \"name\" : \"httptaskfailstatuscodespackage\",\n    \"properties\" : [ {\n      \"id\" : \"httptaskfailstatuscodes\",\n      \"type\" : \"String\",\n      \"title\" : \"Fail status codes\",\n      \"value\" : \"\",\n      \"description\" : \"Comma separated list of HTTP response status codes to retry, for example 400,5XX.\",\n      \"popular\" : true\n    } ]\n  }, {\n    \"name\" : \"httptaskhandlestatuscodespackage\",\n    \"properties\" : [ {\n      \"id\" : \"httptaskhandlestatuscodes\",\n      \"type\" : \"String\",\n      \"title\" : \"Handle status codes\",\n      \"value\" : \"\",\n      \"description\" : \"Comma separated list of HTTP response status codes to ignore, for example 404,3XX.\",\n      \"popular\" : true\n    } ]\n  }, {\n    \"name\" : \"httptaskignoreexceptionpackage\",\n    \"properties\" : [ {\n      \"id\" : \"httptaskignoreexception\",\n      \"type\" : \"String\",\n      \"title\" : \"Ignore exception\",\n      \"value\" : \"\",\n      \"description\" : \"Flag to ignore exceptions.\",\n      \"popular\" : true\n    } ]\n  }, {\n    \"name\" : \"httptaskresponsevariablenamepackage\",\n    \"properties\" : [ {\n      \"id\" : \"httptaskresponsevariablename\",\n      \"type\" : \"String\",\n      \"title\" : \"Response variable name\",\n      \"value\" : \"\",\n      \"description\" : \"Define the variable name to store the http response.\",\n      \"popular\" : true\n    } ]\n  }, {\n    \"name\" : \"httptasksaverequestvariablespackage\",\n    \"properties\" : [ {\n      \"id\" : \"httptasksaverequestvariables\",\n      \"type\" : \"String\",\n      \"title\" : \"Save request variables\",\n      \"value\" : \"\",\n      \"description\" : \"Flag to save request variables.\",\n      \"popular\" : true\n    } ]\n  }, {\n    \"name\" : \"httptasksaveresponseparameterspackage\",\n    \"properties\" : [ {\n      \"id\" : \"httptasksaveresponseparameters\",\n      \"type\" : \"String\",\n      \"title\" : \"Save response status, headers\",\n      \"value\" : \"\",\n      \"description\" : \"Flag to save response status, headers etc.\",\n      \"popular\" : true\n    } ]\n  }, {\n    \"name\" : \"httptaskresultvariableprefixpackage\",\n    \"properties\" : [ {\n      \"id\" : \"httptaskresultvariableprefix\",\n      \"type\" : \"String\",\n      \"title\" : \"Result variable prefix\",\n      \"value\" : \"\",\n      \"description\" : \"Prefix for the execution variable names.\",\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\" : \"formreferencepackage\",\n    \"properties\" : [ {\n      \"id\" : \"formreference\",\n      \"type\" : \"Complex\",\n      \"title\" : \"Form reference\",\n      \"value\" : \"\",\n      \"description\" : \"Reference to a form\",\n      \"popular\" : true\n    } ]\n  }, {\n    \"name\" : \"decisiontaskdecisiontablereferencepackage\",\n    \"properties\" : [ {\n      \"id\" : \"decisiontaskdecisiontablereference\",\n      \"type\" : \"Complex\",\n      \"title\" : \"Decision table reference\",\n      \"value\" : \"\",\n      \"description\" : \"Set the decision table reference\",\n      \"popular\" : true\n    } ]\n  }, {\n    \"name\" : \"decisiontaskthrowerroronnohitspackage\",\n    \"properties\" : [ {\n      \"id\" : \"decisiontaskthrowerroronnohits\",\n      \"type\" : \"Boolean\",\n      \"title\" : \"Throw error if no rules were hit\",\n      \"value\" : \"false\",\n      \"description\" : \"Should an error be thrown if no rules of the decision table were hit and consequently no result was found.\",\n      \"popular\" : true\n    } ]\n  }, {\n      \"name\": \"httptaskrequestmethodpackage\",\n      \"properties\": [\n        {\n          \"id\": \"httptaskrequestmethod\",\n          \"type\": \"String\",\n          \"title\": \"Request method\",\n          \"value\": \"\",\n          \"description\": \"Request method (For example - GET,POST,PUT etc).\",\n          \"popular\": true\n        }\n      ]\n    },\n    {\n      \"name\": \"httptaskrequesturlpackage\",\n      \"properties\": [\n        {\n          \"id\": \"httptaskrequesturl\",\n          \"type\": \"Text\",\n          \"title\": \"Request URL\",\n          \"value\": \"\",\n          \"description\": \"Request URL (For example - http://flowable.org).\",\n          \"popular\": true\n        }\n      ]\n    },\n    {\n      \"name\": \"httptaskrequestheaderspackage\",\n      \"properties\": [\n        {\n          \"id\": \"httptaskrequestheaders\",\n          \"type\": \"Text\",\n          \"title\": \"Request headers\",\n          \"value\": \"\",\n          \"description\": \"Line separated HTTP request headers (For example - Content-Type: application/json).\",\n          \"popular\": true\n        }\n      ]\n    },\n    {\n      \"name\": \"httptaskrequestbodypackage\",\n      \"properties\": [\n        {\n          \"id\": \"httptaskrequestbody\",\n          \"type\": \"Text\",\n          \"title\": \"Request body\",\n          \"value\": \"\",\n          \"description\": \"Request body (For example- ${sampleBody}).\",\n          \"popular\": true\n        }\n      ]\n    },\n    {\n      \"name\": \"httptaskrequesttimeoutpackage\",\n      \"properties\": [\n        {\n          \"id\": \"httptaskrequesttimeout\",\n          \"type\": \"String\",\n          \"title\": \"Request timeout\",\n          \"value\": \"\",\n          \"description\": \"Timeout in milliseconds for the request (For example - 5000).\",\n          \"popular\": true\n        }\n      ]\n    },\n    {\n      \"name\": \"httptaskdisallowredirectspackage\",\n      \"properties\": [\n        {\n          \"id\": \"httptaskdisallowredirects\",\n          \"type\": \"String\",\n          \"title\": \"Disallow redirects\",\n          \"value\": \"\",\n          \"description\": \"Flag to disallow HTTP redirects.\",\n          \"popular\": true\n        }\n      ]\n    },\n    {\n      \"name\": \"httptaskfailstatuscodespackage\",\n      \"properties\": [\n        {\n          \"id\": \"httptaskfailstatuscodes\",\n          \"type\": \"String\",\n          \"title\": \"Fail status codes\",\n          \"value\": \"\",\n          \"description\": \"Comma separated list of HTTP response status codes to retry, for example 400,5XX.\",\n          \"popular\": true\n        }\n      ]\n    },\n    {\n      \"name\": \"httptaskhandlestatuscodespackage\",\n      \"properties\": [\n        {\n          \"id\": \"httptaskhandlestatuscodes\",\n          \"type\": \"String\",\n          \"title\": \"Handle status codes\",\n          \"value\": \"\",\n          \"description\": \"Comma separated list of HTTP response status codes to ignore, for example 404,3XX.\",\n          \"popular\": true\n        }\n      ]\n    },\n    {\n      \"name\": \"httptaskignoreexceptionpackage\",\n      \"properties\": [\n        {\n          \"id\": \"httptaskignoreexception\",\n          \"type\": \"String\",\n          \"title\": \"Ignore exception\",\n          \"value\": \"\",\n          \"description\": \"Flag to ignore exceptions.\",\n          \"popular\": true\n        }\n      ]\n    },\n    {\n      \"name\": \"httptaskresponsevariablenamepackage\",\n      \"properties\": [\n        {\n          \"id\": \"httptaskresponsevariablename\",\n          \"type\": \"String\",\n          \"title\": \"Response variable name\",\n          \"value\": \"\",\n          \"description\": \"Define the variable name to store the http response.\",\n          \"popular\": true\n        }\n      ]\n    },\n    {\n      \"name\": \"httptasksaverequestvariablespackage\",\n      \"properties\": [\n        {\n          \"id\": \"httptasksaverequestvariables\",\n          \"type\": \"String\",\n          \"title\": \"Save request variables\",\n          \"value\": \"\",\n          \"description\": \"Flag to save request variables.\",\n          \"popular\": true\n        }\n      ]\n    },\n    {\n      \"name\": \"httptasksaveresponseparameterspackage\",\n      \"properties\": [\n        {\n          \"id\": \"httptasksaveresponseparameters\",\n          \"type\": \"String\",\n          \"title\": \"Save response status, headers\",\n          \"value\": \"\",\n          \"description\": \"Flag to save response status, headers etc.\",\n          \"popular\": true\n        }\n      ]\n    },\n    {\n      \"name\": \"httptaskresultvariableprefixpackage\",\n      \"properties\": [\n        {\n          \"id\": \"httptaskresultvariableprefix\",\n          \"type\": \"String\",\n          \"title\": \"Result variable prefix\",\n          \"value\": \"\",\n          \"description\": \"Prefix for the execution variable names.\",\n          \"popular\": true\n        }\n      ]\n    },\n    {\n      \"name\" : \"httptasksaveresponseparameterstransientpackage\",\n      \"properties\" : [ {\n        \"id\" : \"httptasksaveresponseparameterstransient\",\n        \"type\" : \"String\",\n        \"title\" : \"Save response as a transient variable\",\n        \"value\" : \"\",\n        \"description\" : \"Flag indicating to store the response variable(s) transient\",\n        \"popular\" : true\n      } ]\n    },\n    {\n      \"name\" : \"httptasksaveresponseasjsonpackage\",\n      \"properties\" : [ {\n        \"id\" : \"httptasksaveresponseasjson\",\n        \"type\" : \"String\",\n        \"title\" : \"Save response as JSON\",\n        \"value\" : \"\",\n        \"description\" : \"Flag indicating to store the response variable as a JSON variable instead of a String\",\n        \"popular\" : true\n      } ]\n    },\n    {\n    \"name\" : \"casetaskcasereferencepackage\",\n    \"properties\" : [ {\n      \"id\" : \"casetaskcasereference\",\n      \"type\" : \"Complex\",\n      \"title\" : \"Case reference\",\n      \"value\" : \"\",\n      \"description\" : \"Set the case reference\",\n      \"popular\" : true\n    } ]\n  }, {\n    \"name\" : \"processtaskprocessreferencepackage\",\n    \"properties\" : [ {\n      \"id\" : \"processtaskprocessreference\",\n      \"type\" : \"Complex\",\n      \"title\" : \"Process reference\",\n      \"value\" : \"\",\n      \"description\" : \"Set the process reference\",\n      \"popular\" : true\n    } ]\n  }, {\n    \"name\" : \"timerexpressionpackage\",\n    \"properties\" : [ {\n      \"id\" : \"timerexpression\",\n      \"type\" : \"String\",\n      \"title\" : \"Timer Expression\",\n      \"value\" : \"\",\n      \"description\" : \"An ISO-8601 string or an expression that resolves to either an ISO-8601 string or a java.util.Date\",\n      \"popular\" : true\n    } ]\n  },  {\n    \"name\" : \"timerstarttriggerpackage\",\n    \"properties\" : [ {\n      \"id\" : \"timerstarttriggersourceref\",\n      \"type\" : \"flowable-planitem-dropdown\",\n      \"title\" : \"Start trigger plan item\",\n      \"value\" : \"\",\n      \"description\" : \"A reference to the plan item for which the configured standard event needs to happen to start the timer (optional)\",\n      \"popular\" : true\n    },\n    {\n      \"id\" : \"transitionevent\",\n      \"type\" : \"flowable-transitionevent\",\n      \"title\" : \"Start trigger transition event\",\n      \"value\" : \"complete\",\n      \"description\" : \"The type of the transition event. Only used when the start trigger plan item is set\",\n      \"popular\" : true\n    } ]\n  }, {\n      \"name\": \"decisiontaskdecisionreferencepackage\",\n      \"properties\": [\n        {\n          \"id\": \"decisiontaskdecisionreference\",\n          \"type\": \"Complex\",\n          \"title\": \"Decision reference\",\n          \"value\": \"\",\n          \"description\": \"Set the decision reference\",\n          \"popular\": true\n        }\n      ]\n    }, {\n    \"name\" : \"ifpartconditionpackage\",\n    \"properties\" : [ {\n      \"id\" : \"ifpartcondition\",\n      \"type\" : \"String\",\n      \"title\" : \"Condition\",\n      \"value\" : \"\",\n      \"description\" : \"An expression that must be true to satisfy the sentry\",\n      \"popular\" : true\n    } ]\n  }, {\n    \"name\" : \"autocompletepackage\",\n    \"properties\" : [ {\n      \"id\" : \"autocompleteenabled\",\n      \"type\" : \"Boolean\",\n      \"title\" : \"Auto complete\",\n      \"value\" : \"\",\n      \"description\" : \"Flag indicating that the stage will automatically complete, once all required children are in an end state and no other children are active.\",\n      \"popular\" : true,\n      \"refToView\" : \"autoComplete\"\n    }, {\n      \"id\" : \"autocompletecondition\",\n      \"type\" : \"String\",\n      \"title\" : \"Auto complete condition\",\n      \"value\" : \"\",\n      \"description\" : \"An expression that is resolved to if the stage can automatically complere.\",\n      \"popular\" : true\n    }]\n  }, {\n    \"name\" : \"requiredrulepackage\",\n    \"properties\" : [ {\n      \"id\" : \"requiredenabled\",\n      \"type\" : \"Boolean\",\n      \"title\" : \"Required\",\n      \"value\" : \"\",\n      \"description\" : \"Flag indicating if the stage, task or milestone is required when determining the parent stage completion. By default false.\",\n      \"popular\" : true,\n      \"refToView\" : \"required\"\n    }, {\n      \"id\" : \"requiredrulecondition\",\n      \"type\" : \"String\",\n      \"title\" : \"Required Rule\",\n      \"value\" : \"\",\n      \"description\" : \"An expression that is resolved to determine if the stage, task or milestone is required when determining the parent stage completion.\",\n      \"popular\" : true\n    }]\n  }, {\n    \"name\" : \"repetitionrulepackage\",\n    \"properties\" : [ {\n      \"id\" : \"repetitionenabled\",\n      \"type\" : \"Boolean\",\n      \"title\" : \"Repetition\",\n      \"value\" : \"\",\n      \"description\" : \"Flag indicating if repetition is enabled\",\n      \"popular\" : true,\n      \"refToView\" : \"repetition\"\n    }, {\n      \"id\" : \"repetitionrulecondition\",\n      \"type\" : \"String\",\n      \"title\" : \"Repetition Rule\",\n      \"value\" : \"\",\n      \"description\" : \"An expression that is resolved to determine if new instances of the planitem need to be created\",\n      \"popular\" : true\n    },\n    {\n      \"id\" : \"repetitioncountervariablename\",\n      \"type\" : \"String\",\n      \"title\" : \"Repetition counter variable\",\n      \"value\" : \"\",\n      \"description\" : \"The name of the local variable which stores the instance counter of the repetition. Default value is 'repetitionCounter'.\",\n      \"popular\" : true\n    } ]\n  }, {\n    \"name\" : \"manualactivationrulepackage\",\n    \"properties\" : [ {\n      \"id\" : \"manualactivationenabled\",\n      \"type\" : \"Boolean\",\n      \"title\" : \"Manual activation\",\n      \"value\" : \"\",\n      \"description\" : \"Flag indicating if the task or stage needs to be manually activated. False by default.\",\n      \"popular\" : true,\n      \"refToView\" : \"manualActivation\"\n    }, {\n      \"id\" : \"manualactivationrulecondition\",\n      \"type\" : \"String\",\n      \"title\" : \"Manual activation Rule\",\n      \"value\" : \"\",\n      \"description\" : \"An expression that is resolved to determine if the stage or task needs to be manually activated.\",\n      \"popular\" : true\n    }]\n  }, {\n    \"name\" : \"completionneutralrulepackage\",\n    \"properties\" : [ {\n      \"id\" : \"completionneutralenabled\",\n      \"type\" : \"Boolean\",\n      \"title\" : \"Completion neutral\",\n      \"value\" : \"\",\n      \"description\" : \"Flag indicating if the plan item is completion neutral. False by default.\",\n      \"popular\" : true\n    }, {\n      \"id\" : \"completionneutralrulecondition\",\n      \"type\" : \"String\",\n      \"title\" : \"Completion neutral Rule\",\n      \"value\" : \"\",\n      \"description\" : \"An expression that is resolved to determine if the plan item is completion neutral.\",\n      \"popular\" : true\n    }]\n  }, {\n    \"name\": \"scriptformatpackage\",\n    \"properties\" : [ {\n        \"id\": \"scriptformat\",\n        \"type\": \"String\",\n        \"title\": \"Script format\",\n        \"value\": \"\",\n        \"description\": \"Script format of the script task (JavaScript, groovy, etc).\",\n        \"popular\": true\n  } ]\n  }, {\n    \"name\": \"scripttextpackage\",\n    \"properties\" : [ {\n        \"id\": \"scripttext\",\n        \"type\": \"Text\",\n        \"title\": \"Script\",\n        \"value\": \"\",\n        \"description\": \"Script text of the script task.\",\n        \"popular\": true\n      }\n    ]\n  }, {\n    \"name\" : \"transitioneventpackage\",\n    \"properties\" : [ {\n      \"id\" : \"transitionevent\",\n      \"type\" : \"flowable-transitionevent\",\n      \"title\" : \"Transition event type\",\n      \"value\" : \"complete\",\n      \"description\" : \"The type of the transition event\",\n      \"popular\" : true\n    } ]\n  } ],\n  \"stencils\" : [ {\n    \"type\" : \"node\",\n    \"id\" : \"CMMNDiagram\",\n    \"title\" : \"CMMN-Diagram\",\n    \"description\" : \"A CMMN 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\" : [ \"case_idpackage\", \"namepackage\", \"documentationpackage\", \"case_initiatorvariablenamepackage\", \"case_authorpackage\", \"case_versionpackage\", \"case_namespacepackage\"],\n    \"hiddenPropertyPackages\" : [ ],\n    \"roles\" : [ ]\n  }, {\n    \"type\" : \"node\",\n    \"id\" : \"CasePlanModel\",\n    \"title\" : \"Case plan model\",\n    \"description\" : \"A case plan model\",\n    \"view\" : \"<?xml version=\\\"1.0\\\" encoding=\\\"UTF-8\\\" standalone=\\\"no\\\"?> <svg xmlns=\\\"http://www.w3.org/2000/svg\\\" xmlns:svg=\\\"http://www.w3.org/2000/svg\\\" xmlns:oryx=\\\"http://www.b3mn.org/oryx\\\" xmlns:xlink=\\\"http://www.w3.org/1999/xlink\\\" version=\\\"1.0\\\" width=\\\"580\\\" height=\\\"720\\\"> <g pointer-events=\\\"fill\\\" oryx:minimumSize=\\\"580 254\\\"> <defs> <radialGradient id=\\\"background\\\" cx=\\\"10%\\\" cy=\\\"10%\\\" r=\\\"100%\\\" fx=\\\"10%\\\" fy=\\\"10%\\\"> <stop offset=\\\"0%\\\" stop-color=\\\"#ffffff\\\" stop-opacity=\\\"1\\\"/> <stop id=\\\"fill_el\\\" offset=\\\"100%\\\" stop-color=\\\"#ffffff\\\" stop-opacity=\\\"1\\\"/> </radialGradient> </defs> <path id=\\\"input_dependent\\\" oryx:resize=\\\"vertical horizontal\\\" d=\\\"M7,30 L600 30 L600 754 L7 754 L7 30Z\\\" stroke=\\\"black\\\" fill=\\\"url(#background) #ffffff\\\" /> <path id=\\\"text_path\\\" d=\\\"M20 55 L37 34 L275 34 L291 55\\\" stroke=\\\"black\\\" fill=\\\"url(#background) #ffffff\\\" transform=\\\"translate(0,-25)\\\" oryx:anchors=\\\"top left\\\"/> <text id=\\\"text_name\\\" font-size=\\\"12\\\" x=\\\"150\\\" y=\\\"18\\\" oryx:fittoelem=\\\"text_path\\\" oryx:anchors=\\\"top left\\\" oryx:align=\\\"middle center\\\" stroke=\\\"black\\\"> </text> <g id=\\\"autoComplete\\\" display=\\\"inherit\\\" stroke=\\\"#000000\\\" oryx:anchors=\\\"bottom center\\\"><path d=\\\" M284 730  L300 730  L300 746  L284 746  z\\\" oryx:anchors=\\\"bottom center\\\"></path></g>  </g> </svg>\",\n    \"icon\" : \"containers/caseplanmodel.png\",\n    \"groups\" : [ \"Containers\" ],\n    \"hide\" : true,\n    \"propertyPackages\" : [\n      \"overrideidpackage\",\n      \"namepackage\",\n      \"documentationpackage\",\n      \"formkeydefinitionpackage\",\n      \"formreferencepackage\",\n      \"autocompletepackage\"\n     ],\n    \"hiddenPropertyPackages\" : [ ],\n    \"roles\" : [ \"StageModelActivity\" ]\n  }, {\n    \"type\" : \"node\",\n    \"id\" : \"Stage\",\n    \"title\" : \"Stage\",\n    \"description\" : \"A stage\",\n    \"view\" : \"<?xml version=\\\"1.0\\\" encoding=\\\"UTF-8\\\" standalone=\\\"no\\\"?> <svg xmlns=\\\"http://www.w3.org/2000/svg\\\" xmlns:svg=\\\"http://www.w3.org/2000/svg\\\" xmlns:oryx=\\\"http://www.b3mn.org/oryx\\\" xmlns:xlink=\\\"http://www.w3.org/1999/xlink\\\" width=\\\"371\\\" height=\\\"171\\\" version=\\\"1.0\\\"> <oryx:magnets> <oryx:magnet oryx:cx=\\\"1\\\" oryx:cy=\\\"42\\\" oryx:anchors=\\\"left\\\" /> <oryx:magnet oryx:cx=\\\"1\\\" oryx:cy=\\\"84\\\" oryx:anchors=\\\"left\\\" /> <oryx:magnet oryx:cx=\\\"1\\\" oryx:cy=\\\"126\\\" oryx:anchors=\\\"left\\\" /><oryx:magnet oryx:cx=\\\"92\\\" oryx:cy=\\\"170\\\" oryx:anchors=\\\"bottom\\\" /> <oryx:magnet oryx:cx=\\\"184\\\" oryx:cy=\\\"170\\\" oryx:anchors=\\\"bottom\\\" /> <oryx:magnet oryx:cx=\\\"276\\\" oryx:cy=\\\"170\\\" oryx:anchors=\\\"bottom\\\" /><oryx:magnet oryx:cx=\\\"370\\\" oryx:cy=\\\"42\\\" oryx:anchors=\\\"right\\\" /> <oryx:magnet oryx:cx=\\\"370\\\" oryx:cy=\\\"84\\\" oryx:anchors=\\\"right\\\" /> <oryx:magnet oryx:cx=\\\"370\\\" oryx:cy=\\\"126\\\" oryx:anchors=\\\"right\\\" /><oryx:magnet oryx:cx=\\\"92\\\" oryx:cy=\\\"1\\\" oryx:anchors=\\\"top\\\" /> <oryx:magnet oryx:cx=\\\"184\\\" oryx:cy=\\\"1\\\" oryx:anchors=\\\"top\\\" /> <oryx:magnet oryx:cx=\\\"276\\\" oryx:cy=\\\"1\\\" oryx:anchors=\\\"top\\\" /><oryx:magnet oryx:cx=\\\"185\\\" oryx:cy=\\\"85\\\" oryx:default=\\\"yes\\\" /> </oryx:magnets> <g pointer-events=\\\"fill\\\" oryx:minimumSize=\\\"160 93\\\"> <polygon id=\\\"bg_frame\\\" points=\\\"10 0 360 0 370 10 370 160 360 170 10 170 0 160 0 10 10 0\\\" oryx:resize=\\\"vertical horizontal\\\" stroke=\\\"black\\\" fill=\\\"#ffffff\\\"/> <text font-size=\\\"12\\\" id=\\\"text_name\\\" x=\\\"13\\\" y=\\\"2\\\" oryx:align=\\\"top left\\\" oryx:fittoelem=\\\"bg_frame\\\" stroke=\\\"black\\\"> </text> <g id=\\\"required\\\" display=\\\"inherit\\\" stroke=\\\"#000000\\\"><path fill=\\\"none\\\" oryx:anchors=\\\"bottom\\\" d=\\\"M183 154 L183 164 M183 166 L183 168\\\" transform=\\\"translate(-4,0)\\\"></path></g> <g id=\\\"repetition\\\" oryx:anchors=\\\"bottom\\\"><path oryx:anchors=\\\"bottom\\\" fill=\\\"none\\\" stroke=\\\"#bbbbbb\\\" stroke-width=\\\"2\\\" d=\\\"M180 156 v12 M183 156 v12 M186 156 v12\\\" transform=\\\"translate(-30,0)\\\"/></g><g id=\\\"manualActivation\\\" display=\\\"inherit\\\" stroke=\\\"#000000\\\"><path d=\\\" M198.88108108108108 162  L188.88108108108108 155  L188.88108108108108 155  L188.88108108108108 167  z\\\" fill=\\\"none\\\" oryx:anchors=\\\"bottom\\\" transform=\\\"translate(-2,0)\\\"></path></g> <g id=\\\"autoComplete\\\" display=\\\"inherit\\\" stroke=\\\"#000000\\\"><path d=\\\"M180 155 L189 155 L189 167 L180 167 L180 167z\\\" oryx:anchors=\\\"bottom\\\" transform=\\\"translate(-16,0)\\\"></path></g> </g></svg>\",\n    \"icon\" : \"containers/expanded.stage.png\",\n    \"groups\" : [ \"Containers\" ],\n    \"hide\" : true,\n    \"propertyPackages\" : [\n      \"overrideidpackage\",\n      \"namepackage\",\n      \"documentationpackage\",\n      \"autocompletepackage\",\n      \"requiredrulepackage\",\n      \"repetitionrulepackage\",\n      \"manualactivationrulepackage\",\n      \"completionneutralrulepackage\"\n    ],\n    \"hiddenPropertyPackages\" : [ ],\n    \"roles\" : [ \"StageActivity\", \"all\", \"association_start\", \"association_end\" ]\n  }, {\n    \"type\" : \"node\",\n    \"id\" : \"Task\",\n    \"title\" : \"Task\",\n    \"description\" : \"A manual task\",\n    \"view\" : \"<?xml version=\\\"1.0\\\" encoding=\\\"UTF-8\\\" standalone=\\\"no\\\"?><svg xmlns=\\\"http://www.w3.org/2000/svg\\\" xmlns:svg=\\\"http://www.w3.org/2000/svg\\\" xmlns:oryx=\\\"http://www.b3mn.org/oryx\\\" xmlns:xlink=\\\"http://www.w3.org/1999/xlink\\\" width=\\\"102\\\" height=\\\"82\\\" version=\\\"1.0\\\"><defs></defs><oryx:magnets><oryx:magnet oryx:cx=\\\"1\\\" oryx:cy=\\\"20\\\" oryx:anchors=\\\"left\\\" /><oryx:magnet oryx:cx=\\\"1\\\" oryx:cy=\\\"40\\\" oryx:anchors=\\\"left\\\" /><oryx:magnet oryx:cx=\\\"1\\\" oryx:cy=\\\"60\\\" oryx:anchors=\\\"left\\\" /><oryx:magnet oryx:cx=\\\"25\\\" oryx:cy=\\\"79\\\" oryx:anchors=\\\"bottom\\\" /><oryx:magnet oryx:cx=\\\"50\\\" oryx:cy=\\\"79\\\" oryx:anchors=\\\"bottom\\\" /><oryx:magnet oryx:cx=\\\"75\\\" oryx:cy=\\\"79\\\" oryx:anchors=\\\"bottom\\\" /><oryx:magnet oryx:cx=\\\"99\\\" oryx:cy=\\\"20\\\" oryx:anchors=\\\"right\\\" /><oryx:magnet oryx:cx=\\\"99\\\" oryx:cy=\\\"40\\\" oryx:anchors=\\\"right\\\" /><oryx:magnet oryx:cx=\\\"99\\\" oryx:cy=\\\"60\\\" oryx:anchors=\\\"right\\\" /><oryx:magnet oryx:cx=\\\"25\\\" oryx:cy=\\\"1\\\" oryx:anchors=\\\"top\\\" /><oryx:magnet oryx:cx=\\\"50\\\" oryx:cy=\\\"1\\\" oryx:anchors=\\\"top\\\" /><oryx:magnet oryx:cx=\\\"75\\\" oryx:cy=\\\"1\\\" oryx:anchors=\\\"top\\\" /><oryx:magnet oryx:cx=\\\"50\\\" oryx:cy=\\\"40\\\" oryx:default=\\\"yes\\\" /></oryx:magnets><g pointer-events=\\\"fill\\\" oryx:minimumSize=\\\"50 40\\\"><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\\\" /><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\\\" /><text font-size=\\\"12\\\" id=\\\"text_name\\\" x=\\\"50\\\" y=\\\"40\\\" oryx:align=\\\"middle center\\\" oryx:fittoelem=\\\"text_frame\\\" stroke=\\\"#373e48\\\"></text><g id=\\\"required\\\" display=\\\"inherit\\\" stroke=\\\"#000000\\\"><g oryx:anchors=\\\"bottom\\\"><path fill=\\\"none\\\" oryx:anchors=\\\"bottom\\\" d=\\\"M49 67 L49 74 M49 76 L49 78\\\" transform=\\\"translate(-11,0)\\\"></path></g></g><g id=\\\"repetition\\\" oryx:anchors=\\\"bottom\\\"><path oryx:anchors=\\\"bottom\\\" fill=\\\"none\\\" stroke=\\\"#bbbbbb\\\" stroke-width=\\\"2\\\" d=\\\"M47 68 v10 M50 68 v10 M53 68 v10\\\" transform=\\\"translate(10,0)\\\"/></g><g id=\\\"manualActivation\\\" display=\\\"inherit\\\" stroke=\\\"#000000\\\" oryx:anchors=\\\"bottom\\\"><path oryx:anchors=\\\"bottom\\\" fill=\\\"none\\\" d=\\\"M45.5 68 L54 73 L45.5 77 L45.5 69z\\\" transform=\\\"translate(-2,0)\\\"></path></g></g></svg>\",\n    \"icon\" : \"activity/task.png\",\n    \"groups\" : [ \"Activities\" ],\n    \"propertyPackages\" : [\n      \"overrideidpackage\",\n      \"namepackage\",\n      \"documentationpackage\",\n      \"blockingpackage\",\n      \"asyncpackage\",\n      \"requiredrulepackage\",\n      \"repetitionrulepackage\",\n      \"manualactivationrulepackage\",\n      \"completionneutralrulepackage\"],\n    \"hiddenPropertyPackages\" : [ ],\n    \"roles\" : [ \"Activity\", \"association_start\", \"association_end\", \"ActivitiesMorph\", \"all\" ]\n  }, {\n    \"type\" : \"node\",\n    \"id\" : \"HumanTask\",\n    \"title\" : \"Human task\",\n    \"description\" : \"A manual task assigned to a specific person\",\n    \"view\" : \"<?xml version=\\\"1.0\\\" encoding=\\\"UTF-8\\\" standalone=\\\"no\\\"?><svg xmlns=\\\"http://www.w3.org/2000/svg\\\" xmlns:svg=\\\"http://www.w3.org/2000/svg\\\" xmlns:oryx=\\\"http://www.b3mn.org/oryx\\\" xmlns:xlink=\\\"http://www.w3.org/1999/xlink\\\" width=\\\"102\\\" height=\\\"82\\\" version=\\\"1.0\\\"> <defs></defs>  <oryx:magnets>  <oryx:magnet oryx:cx=\\\"1\\\" oryx:cy=\\\"20\\\" oryx:anchors=\\\"left\\\" />  <oryx:magnet oryx:cx=\\\"1\\\" oryx:cy=\\\"40\\\" oryx:anchors=\\\"left\\\" />  <oryx:magnet oryx:cx=\\\"1\\\" oryx:cy=\\\"60\\\" oryx:anchors=\\\"left\\\" /> <oryx:magnet oryx:cx=\\\"25\\\" oryx:cy=\\\"79\\\" oryx:anchors=\\\"bottom\\\" />  <oryx:magnet oryx:cx=\\\"50\\\" oryx:cy=\\\"79\\\" oryx:anchors=\\\"bottom\\\" /> <oryx:magnet oryx:cx=\\\"75\\\" oryx:cy=\\\"79\\\" oryx:anchors=\\\"bottom\\\" /> <oryx:magnet oryx:cx=\\\"99\\\" oryx:cy=\\\"20\\\" oryx:anchors=\\\"right\\\" /> <oryx:magnet oryx:cx=\\\"99\\\" oryx:cy=\\\"40\\\" oryx:anchors=\\\"right\\\" /> <oryx:magnet oryx:cx=\\\"99\\\" oryx:cy=\\\"60\\\" oryx:anchors=\\\"right\\\" /> <oryx:magnet oryx:cx=\\\"25\\\" oryx:cy=\\\"1\\\" oryx:anchors=\\\"top\\\" /> <oryx:magnet oryx:cx=\\\"50\\\" oryx:cy=\\\"1\\\" oryx:anchors=\\\"top\\\" /> <oryx:magnet oryx:cx=\\\"75\\\" oryx:cy=\\\"1\\\" oryx:anchors=\\\"top\\\" /> <oryx:magnet oryx:cx=\\\"50\\\" oryx:cy=\\\"40\\\" oryx:default=\\\"yes\\\" /> </oryx:magnets> <g pointer-events=\\\"fill\\\" oryx:minimumSize=\\\"50 40\\\"> <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\\\" /> <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\\\" /> <text font-size=\\\"12\\\" id=\\\"text_name\\\" x=\\\"50\\\" y=\\\"40\\\" oryx:align=\\\"middle center\\\" oryx:fittoelem=\\\"text_frame\\\" stroke=\\\"#373e48\\\"></text><g id=\\\"userTask\\\" transform=\\\"translate(3,3)\\\"><path oryx:anchors=\\\"top left\\\" style=\\\"fill:#d1b575;stroke:none;\\\" 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\\\" /></g><g id=\\\"required\\\" display=\\\"inherit\\\" stroke=\\\"#000000\\\"><g oryx:anchors=\\\"bottom\\\"><path fill=\\\"none\\\" oryx:anchors=\\\"bottom\\\" d=\\\"M49 67 L49 74 M49 76 L49 78\\\" transform=\\\"translate(-11,0)\\\"></path></g></g><g id=\\\"repetition\\\" oryx:anchors=\\\"bottom\\\"><path oryx:anchors=\\\"bottom\\\" fill=\\\"none\\\" stroke=\\\"#bbbbbb\\\" stroke-width=\\\"2\\\" d=\\\"M47 68 v10 M50 68 v10 M53 68 v10\\\" transform=\\\"translate(10,0)\\\"/></g><g id=\\\"manualActivation\\\" display=\\\"inherit\\\" stroke=\\\"#000000\\\" oryx:anchors=\\\"bottom\\\"><path oryx:anchors=\\\"bottom\\\" fill=\\\"none\\\" d=\\\"M45.5 68 L54 73 L45.5 77 L45.5 69z\\\" transform=\\\"translate(-2,0)\\\"></path></g></g></svg>\",\n    \"icon\" : \"activity/humantask.png\",\n    \"groups\" : [ \"Activities\" ],\n    \"propertyPackages\" : [\n      \"overrideidpackage\",\n      \"namepackage\",\n      \"documentationpackage\",\n      \"blockingpackage\",\n      \"usertaskassignmentpackage\",\n      \"formkeydefinitionpackage\",\n      \"formreferencepackage\",\n      \"duedatedefinitionpackage\",\n      \"prioritydefinitionpackage\",\n      \"asyncpackage\",\n      \"requiredrulepackage\",\n      \"repetitionrulepackage\",\n      \"manualactivationrulepackage\",\n      \"completionneutralrulepackage\" ],\n    \"hiddenPropertyPackages\" : [ ],\n    \"roles\" : [ \"Activity\", \"association_start\", \"association_end\", \"ActivitiesMorph\", \"all\" ]\n  }, {\n    \"type\" : \"node\",\n    \"id\" : \"ServiceTask\",\n    \"title\" : \"Service task\",\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\\\" /></g><g id=\\\"required\\\" display=\\\"inherit\\\" stroke=\\\"#000000\\\"><g oryx:anchors=\\\"bottom\\\"><path fill=\\\"none\\\" oryx:anchors=\\\"bottom\\\" d=\\\"M49 67 L49 74 M49 76 L49 78\\\" transform=\\\"translate(-11,0)\\\"></path></g></g><g id=\\\"repetition\\\" oryx:anchors=\\\"bottom\\\"><path oryx:anchors=\\\"bottom\\\" fill=\\\"none\\\" stroke=\\\"#bbbbbb\\\" stroke-width=\\\"2\\\" d=\\\"M47 68 v10 M50 68 v10 M53 68 v10\\\" transform=\\\"translate(10,0)\\\"/></g><g id=\\\"manualActivation\\\" display=\\\"inherit\\\" stroke=\\\"#000000\\\" oryx:anchors=\\\"bottom\\\"><path oryx:anchors=\\\"bottom\\\" fill=\\\"none\\\" d=\\\"M45.5 68 L54 73 L45.5 77 L45.5 69z\\\" transform=\\\"translate(-2,0)\\\"></path></g></g></svg>\",\n    \"icon\" : \"activity/servicetask.png\",\n    \"groups\" : [ \"Activities\" ],\n    \"propertyPackages\" : [\n      \"overrideidpackage\",\n      \"namepackage\",\n      \"documentationpackage\",\n      \"servicetaskclasspackage\",\n      \"servicetaskexpressionpackage\",\n      \"servicetaskdelegateexpressionpackage\",\n      \"servicetaskfieldspackage\",\n      \"servicetaskresultvariablepackage\",\n      \"asyncpackage\",\n      \"requiredrulepackage\",\n      \"repetitionrulepackage\",\n      \"manualactivationrulepackage\",\n      \"completionneutralrulepackage\" ],\n    \"hiddenPropertyPackages\" : [ ],\n    \"roles\" : [ \"Activity\", \"association_start\", \"association_end\", \"ActivitiesMorph\", \"all\" ]\n  },\n    {\n      \"type\": \"node\",\n      \"id\": \"DecisionTask\",\n      \"title\": \"Decision task\",\n      \"description\": \"Task to invoke a DMN decision\",\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=\\\"decisionTask\\\" 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\\\" style=\\\"fill:#72a7d0;stroke:none\\\" /></g><g id=\\\"required\\\" display=\\\"inherit\\\" stroke=\\\"#000000\\\"><g oryx:anchors=\\\"bottom\\\"><path fill=\\\"none\\\" oryx:anchors=\\\"bottom\\\" d=\\\"M49 67 L49 74 M49 76 L49 78\\\" transform=\\\"translate(-11,0)\\\"></path></g></g><g id=\\\"repetition\\\" oryx:anchors=\\\"bottom\\\"><path oryx:anchors=\\\"bottom\\\" fill=\\\"none\\\" stroke=\\\"#bbbbbb\\\" stroke-width=\\\"2\\\" d=\\\"M47 68 v10 M50 68 v10 M53 68 v10\\\" transform=\\\"translate(10,0)\\\"/></g><g id=\\\"manualActivation\\\" display=\\\"inherit\\\" stroke=\\\"#000000\\\" oryx:anchors=\\\"bottom\\\"><path oryx:anchors=\\\"bottom\\\" fill=\\\"none\\\" d=\\\"M45.5 68 L54 73 L45.5 77 L45.5 69z\\\" transform=\\\"translate(-2,0)\\\"></path></g></g></svg>\",\n      \"icon\": \"activity/decisiontask.png\",\n      \"groups\": [\n        \"Activities\"\n      ],\n      \"propertyPackages\": [\n        \"overrideidpackage\",\n        \"namepackage\",\n        \"documentationpackage\",\n        \"decisiontaskdecisiontablereferencepackage\",\n        \"decisiontaskthrowerroronnohitspackage\",\n        \"asyncpackage\",\n        \"requiredrulepackage\",\n        \"repetitionrulepackage\",\n        \"manualactivationrulepackage\",\n        \"completionneutralrulepackage\"\n      ],\n      \"hiddenPropertyPackages\": [],\n      \"roles\": [\n        \"Activity\",\n        \"association_start\",\n        \"association_end\",\n        \"ActivitiesMorph\",\n        \"all\"\n      ]\n    }, {\n      \"type\": \"node\",\n      \"id\": \"HttpTask\",\n      \"title\": \"Http task\",\n      \"description\": \"A HTTP 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 16.704699,5.9229055 q 0.358098,0 0.608767,0.2506681 0.250669,0.250668 0.250669,0.6087677 0,0.3580997 -0.250669,0.6087677 -0.250669,0.2506679 -0.608767,0.2506679 -0.358098,0 -0.608767,-0.2506679 -0.250669,-0.250668 -0.250669,-0.6087677 0,-0.3580997 0.250669,-0.6087677 0.250669,-0.2506681 0.608767,-0.2506681 z m 2.578308,-2.0053502 q -2.229162,0 -3.854034,0.6759125 -1.624871,0.6759067 -3.227361,2.2694472 -0.716197,0.725146 -1.575633,1.7457293 L 7.2329969,8.7876913 Q 7.0897576,8.8055849 7.000233,8.9309334 L 4.9948821,12.368677 q -0.035811,0.06267 -0.035811,0.143242 0,0.107426 0.080572,0.205905 l 0.5729577,0.572957 q 0.125334,0.116384 0.2864786,0.07162 l 2.4708789,-0.760963 2.5156417,2.515645 -0.76096,2.470876 q -0.009,0.02687 -0.009,0.08057 0,0.125338 0.08058,0.205905 l 0.572957,0.572958 q 0.170096,0.152194 0.349146,0.04476 l 3.437744,-2.005351 q 0.125335,-0.08953 0.143239,-0.232763 l 0.17905,-3.392986 q 1.02058,-0.859435 1.745729,-1.575629 1.67411,-1.6830612 2.309735,-3.2049805 0.635625,-1.5219191 0.635625,-3.8585111 0,-0.1253369 -0.08505,-0.2148575 -0.08505,-0.089526 -0.201431,-0.089526 z \\\" /></g><g id=\\\"required\\\" display=\\\"inherit\\\" stroke=\\\"#000000\\\"><g oryx:anchors=\\\"bottom\\\"><path fill=\\\"none\\\" oryx:anchors=\\\"bottom\\\" d=\\\"M49 67 L49 74 M49 76 L49 78\\\" transform=\\\"translate(-11,0)\\\"></path></g></g><g id=\\\"repetition\\\" oryx:anchors=\\\"bottom\\\"><path oryx:anchors=\\\"bottom\\\" fill=\\\"none\\\" stroke=\\\"#bbbbbb\\\" stroke-width=\\\"2\\\" d=\\\"M47 68 v10 M50 68 v10 M53 68 v10\\\" transform=\\\"translate(10,0)\\\"/></g><g id=\\\"manualActivation\\\" display=\\\"inherit\\\" stroke=\\\"#000000\\\" oryx:anchors=\\\"bottom\\\"><path oryx:anchors=\\\"bottom\\\" fill=\\\"none\\\" d=\\\"M45.5 68 L54 73 L45.5 77 L45.5 69z\\\" transform=\\\"translate(-2,0)\\\"></path></g></g></svg>\",\n      \"icon\": \"activity/httptask.png\",\n      \"groups\": [\n        \"Activities\"\n      ],\n      \"propertyPackages\": [\n        \"overrideidpackage\",\n        \"namepackage\",\n        \"documentationpackage\",\n        \"servicetaskclasspackage\",\n        \"asyncpackage\",\n        \"requiredrulepackage\",\n        \"repetitionrulepackage\",\n        \"manualactivationrulepackage\",\n        \"completionneutralrulepackage\",\n        \"httptaskrequestmethodpackage\",\n        \"httptaskrequesturlpackage\",\n        \"httptaskrequestheaderspackage\",\n        \"httptaskrequestbodypackage\",\n        \"httptaskrequesttimeoutpackage\",\n        \"httptaskdisallowredirectspackage\",\n        \"httptaskfailstatuscodespackage\",\n        \"httptaskhandlestatuscodespackage\",\n        \"httptaskignoreexceptionpackage\",\n        \"httptaskresponsevariablenamepackage\",\n        \"httptasksaverequestvariablespackage\",\n        \"httptasksaveresponseparameterspackage\",\n        \"httptaskresultvariableprefixpackage\",\n        \"httptasksaveresponseparameterstransientpackage\",\n        \"httptasksaveresponseasjsonpackage\"\n      ],\n      \"hiddenPropertyPackages\": [],\n      \"roles\": [\n        \"Activity\",\n        \"sequence_start\",\n        \"sequence_end\",\n        \"ActivitiesMorph\",\n        \"all\"\n      ]\n    }, {\n      \"type\" : \"node\",\n      \"id\" : \"ScriptTask\",\n      \"title\" : \"Script task\",\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><g id=\\\"required\\\" display=\\\"inherit\\\" stroke=\\\"#000000\\\"><g oryx:anchors=\\\"bottom\\\"><path fill=\\\"none\\\" oryx:anchors=\\\"bottom\\\" d=\\\"M49 67 L49 74 M49 76 L49 78\\\" transform=\\\"translate(-11,0)\\\"></path></g></g><g id=\\\"repetition\\\" oryx:anchors=\\\"bottom\\\"><path oryx:anchors=\\\"bottom\\\" fill=\\\"none\\\" stroke=\\\"#bbbbbb\\\" stroke-width=\\\"2\\\" d=\\\"M47 68 v10 M50 68 v10 M53 68 v10\\\" transform=\\\"translate(10,0)\\\"/></g><g id=\\\"manualActivation\\\" display=\\\"inherit\\\" stroke=\\\"#000000\\\" oryx:anchors=\\\"bottom\\\"><path oryx:anchors=\\\"bottom\\\" fill=\\\"none\\\" d=\\\"M45.5 68 L54 73 L45.5 77 L45.5 69z\\\" transform=\\\"translate(-2,0)\\\"></path></g></g></svg>\",\n      \"icon\" : \"activity/scripttask.png\",\n      \"groups\" : [ \"Activities\" ],\n      \"propertyPackages\" : [\n        \"overrideidpackage\",\n        \"namepackage\",\n        \"documentationpackage\",\n        \"servicetaskclasspackage\",\n        \"asyncpackage\",\n        \"requiredrulepackage\",\n        \"repetitionrulepackage\",\n        \"manualactivationrulepackage\",\n        \"completionneutralrulepackage\",\n        \"scriptformatpackage\",\n        \"scripttextpackage\",\n        \"servicetaskresultvariablepackage\"\n      ],\n      \"hiddenPropertyPackages\" : [ ],\n      \"roles\" : [ \"Activity\", \"association_start\", \"association_end\", \"ActivitiesMorph\", \"all\" ]\n    }, {\n    \"type\" : \"node\",\n    \"id\" : \"Milestone\",\n    \"title\" : \"Milestone\",\n    \"description\" : \"A milestone\",\n    \"view\" : \"<?xml version=\\\"1.0\\\" encoding=\\\"UTF-8\\\" standalone=\\\"no\\\"?> <svg xmlns=\\\"http://www.w3.org/2000/svg\\\" xmlns:oryx=\\\"http://www.b3mn.org/oryx\\\" width=\\\"146\\\" height=\\\"54\\\" version=\\\"1.0\\\"> <oryx:magnets> <oryx:magnet oryx:cx=\\\"1\\\" oryx:cy=\\\"27\\\" oryx:anchors=\\\"left\\\" /> <oryx:magnet oryx:cx=\\\"36\\\" oryx:cy=\\\"53\\\" oryx:anchors=\\\"bottom\\\" /> <oryx:magnet oryx:cx=\\\"72\\\" oryx:cy=\\\"53\\\" oryx:anchors=\\\"bottom\\\" /> <oryx:magnet oryx:cx=\\\"108\\\" oryx:cy=\\\"53\\\" oryx:anchors=\\\"bottom\\\" /> <oryx:magnet oryx:cx=\\\"145\\\" oryx:cy=\\\"27\\\" oryx:anchors=\\\"right\\\" /> <oryx:magnet oryx:cx=\\\"36\\\" oryx:cy=\\\"1\\\" oryx:anchors=\\\"top\\\" /> <oryx:magnet oryx:cx=\\\"72\\\" oryx:cy=\\\"1\\\" oryx:anchors=\\\"top\\\" /> <oryx:magnet oryx:cx=\\\"108\\\" oryx:cy=\\\"1\\\" oryx:anchors=\\\"top\\\" /> <oryx:magnet oryx:cx=\\\"72\\\" oryx:cy=\\\"27\\\" oryx:default=\\\"yes\\\" /> </oryx:magnets> <g pointer-events=\\\"fill\\\" oryx:minimumSize=\\\"146 54\\\" oryx:maximumSize=\\\"400 54\\\"> <rect id=\\\"mileStone\\\" oryx:resize=\\\"horizontal\\\" x=\\\"0\\\" y=\\\"0\\\" width=\\\"146\\\" height=\\\"54\\\" rx=\\\"24\\\" ry=\\\"30\\\" stroke=\\\"black\\\" fill=\\\"#ffffff\\\"/> <text font-size=\\\"12\\\" id=\\\"text_name\\\" x=\\\"73\\\" y=\\\"26\\\" oryx:align=\\\"middle center\\\" oryx:fittoelem=\\\"mileStone\\\" stroke=\\\"black\\\"> </text> <g id=\\\"required\\\" stroke=\\\"#000000\\\"> <path d=\\\"M68 40 L68 47 M68 49 L68 51 \\\" fill=\\\"none\\\" oryx:anchors=\\\"bottom\\\"/> </g> <g id=\\\"repetition\\\" oryx:anchors=\\\"bottom\\\"><path oryx:anchors=\\\"bottom\\\" fill=\\\"none\\\" stroke=\\\"#bbbbbb\\\" stroke-width=\\\"2\\\" d=\\\"M64 40 v11 M67 40 v11 M70 40 v11\\\" transform=\\\"translate(13,0)\\\"/></g></g> </svg>\",\n    \"icon\" : \"activity/milestone.png\",\n    \"groups\" : [ \"Activities\" ],\n    \"propertyPackages\" : [\n      \"overrideidpackage\",\n      \"namepackage\",\n      \"documentationpackage\",\n      \"requiredrulepackage\",\n      \"repetitionrulepackage\",\n      \"completionneutralrulepackage\" ],\n    \"hiddenPropertyPackages\" : [ ],\n    \"roles\" : [ \"Activity\", \"association_start\", \"association_end\", \"ActivitiesMorph\", \"all\" ]\n  }, {\n    \"type\" : \"node\",\n    \"id\" : \"CaseTask\",\n    \"title\" : \"Case task\",\n    \"description\" : \"A reference to a case definition to start a new instance\",\n    \"view\" : \"<?xml version=\\\"1.0\\\" encoding=\\\"UTF-8\\\" standalone=\\\"no\\\"?> <svg xmlns=\\\"http://www.w3.org/2000/svg\\\" xmlns:svg=\\\"http://www.w3.org/2000/svg\\\" xmlns:oryx=\\\"http://www.b3mn.org/oryx\\\" xmlns:xlink=\\\"http://www.w3.org/1999/xlink\\\" width=\\\"102\\\" height=\\\"82\\\" version=\\\"1.0\\\"> <defs></defs> <oryx:magnets> <oryx:magnet oryx:cx=\\\"1\\\" oryx:cy=\\\"20\\\" oryx:anchors=\\\"left\\\" /> <oryx:magnet oryx:cx=\\\"1\\\" oryx:cy=\\\"40\\\" oryx:anchors=\\\"left\\\" /> <oryx:magnet oryx:cx=\\\"1\\\" oryx:cy=\\\"60\\\" oryx:anchors=\\\"left\\\" /> <oryx:magnet oryx:cx=\\\"25\\\" oryx:cy=\\\"79\\\" oryx:anchors=\\\"bottom\\\" /> <oryx:magnet oryx:cx=\\\"50\\\" oryx:cy=\\\"79\\\" oryx:anchors=\\\"bottom\\\" /> <oryx:magnet oryx:cx=\\\"75\\\" oryx:cy=\\\"79\\\" oryx:anchors=\\\"bottom\\\" /> <oryx:magnet oryx:cx=\\\"99\\\" oryx:cy=\\\"20\\\" oryx:anchors=\\\"right\\\" /> <oryx:magnet oryx:cx=\\\"99\\\" oryx:cy=\\\"40\\\" oryx:anchors=\\\"right\\\" /> <oryx:magnet oryx:cx=\\\"99\\\" oryx:cy=\\\"60\\\" oryx:anchors=\\\"right\\\" /> <oryx:magnet oryx:cx=\\\"25\\\" oryx:cy=\\\"1\\\" oryx:anchors=\\\"top\\\" /> <oryx:magnet oryx:cx=\\\"50\\\" oryx:cy=\\\"1\\\" oryx:anchors=\\\"top\\\" /> <oryx:magnet oryx:cx=\\\"75\\\" oryx:cy=\\\"1\\\" oryx:anchors=\\\"top\\\" /> <oryx:magnet oryx:cx=\\\"50\\\" oryx:cy=\\\"40\\\" oryx:default=\\\"yes\\\" /> </oryx:magnets> <g pointer-events=\\\"fill\\\" oryx:minimumSize=\\\"50 40\\\"> <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\\\" /> <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\\\" /> <text font-size=\\\"12\\\" id=\\\"text_name\\\" x=\\\"50\\\" y=\\\"40\\\" oryx:align=\\\"middle center\\\" oryx:fittoelem=\\\"text_frame\\\" stroke=\\\"#373e48\\\"> </text> <g id=\\\"caseTask\\\" transform=\\\"scale(0.7,0.7) translate(8,8)\\\"> <path oryx:anchors=\\\"top left\\\" style=\\\"opacity:1;fill:#000000;stroke:#000000\\\" d=\\\"M5 4 L9 0 L18 0 L 21 3z\\\"/> <path oryx:anchors=\\\"top left\\\" style=\\\"opacity:1;fill:#F4F6F7;stroke:#000000\\\" d=\\\"M1 23 L1 4 L30 4 L30 23z\\\"/> </g> <g id=\\\"required\\\" display=\\\"inherit\\\" stroke=\\\"#000000\\\"><g oryx:anchors=\\\"bottom\\\"><path fill=\\\"none\\\" oryx:anchors=\\\"bottom\\\" d=\\\"M49 67 L49 74 M49 76 L49 78\\\" transform=\\\"translate(-11,0)\\\"></path></g></g> <g id=\\\"repetition\\\" oryx:anchors=\\\"bottom\\\"><path oryx:anchors=\\\"bottom\\\" fill=\\\"none\\\" stroke=\\\"#bbbbbb\\\" stroke-width=\\\"2\\\" d=\\\"M47 68 v10 M50 68 v10 M53 68 v10\\\" transform=\\\"translate(10,0)\\\"/></g><g id=\\\"manualActivation\\\" display=\\\"inherit\\\" stroke=\\\"#000000\\\" oryx:anchors=\\\"bottom\\\"><path oryx:anchors=\\\"bottom\\\" fill=\\\"none\\\" d=\\\"M45.5 68 L54 73 L45.5 77 L45.5 69z\\\" transform=\\\"translate(-2,0)\\\"></path></g></g></svg>\",\n    \"icon\" : \"activity/casetask.png\",\n    \"groups\" : [ \"Activities\" ],\n    \"propertyPackages\" : [\n      \"overrideidpackage\",\n      \"namepackage\",\n      \"documentationpackage\",\n      \"blockingpackage\",\n      \"casetaskcasereferencepackage\",\n      \"asyncpackage\",\n      \"requiredrulepackage\",\n      \"repetitionrulepackage\",\n      \"manualactivationrulepackage\",\n      \"completionneutralrulepackage\"],\n    \"hiddenPropertyPackages\" : [ ],\n    \"roles\" : [ \"Activity\", \"association_start\", \"association_end\", \"ActivitiesMorph\", \"all\" ]\n  }, {\n    \"type\" : \"node\",\n    \"id\" : \"ProcessTask\",\n    \"title\" : \"Process task\",\n    \"description\" : \"A reference to a process definition to start a new instance\",\n    \"view\" : \"<?xml version=\\\"1.0\\\" encoding=\\\"UTF-8\\\" standalone=\\\"no\\\"?> <svg xmlns=\\\"http://www.w3.org/2000/svg\\\" xmlns:svg=\\\"http://www.w3.org/2000/svg\\\" xmlns:oryx=\\\"http://www.b3mn.org/oryx\\\" xmlns:xlink=\\\"http://www.w3.org/1999/xlink\\\" width=\\\"102\\\" height=\\\"82\\\" version=\\\"1.0\\\"> <defs></defs> <oryx:magnets> <oryx:magnet oryx:cx=\\\"1\\\" oryx:cy=\\\"20\\\" oryx:anchors=\\\"left\\\" /> <oryx:magnet oryx:cx=\\\"1\\\" oryx:cy=\\\"40\\\" oryx:anchors=\\\"left\\\" /> <oryx:magnet oryx:cx=\\\"1\\\" oryx:cy=\\\"60\\\" oryx:anchors=\\\"left\\\" /> <oryx:magnet oryx:cx=\\\"25\\\" oryx:cy=\\\"79\\\" oryx:anchors=\\\"bottom\\\" /> <oryx:magnet oryx:cx=\\\"50\\\" oryx:cy=\\\"79\\\" oryx:anchors=\\\"bottom\\\" /> <oryx:magnet oryx:cx=\\\"75\\\" oryx:cy=\\\"79\\\" oryx:anchors=\\\"bottom\\\" /> <oryx:magnet oryx:cx=\\\"99\\\" oryx:cy=\\\"20\\\" oryx:anchors=\\\"right\\\" /> <oryx:magnet oryx:cx=\\\"99\\\" oryx:cy=\\\"40\\\" oryx:anchors=\\\"right\\\" /> <oryx:magnet oryx:cx=\\\"99\\\" oryx:cy=\\\"60\\\" oryx:anchors=\\\"right\\\" /> <oryx:magnet oryx:cx=\\\"25\\\" oryx:cy=\\\"1\\\" oryx:anchors=\\\"top\\\" /> <oryx:magnet oryx:cx=\\\"50\\\" oryx:cy=\\\"1\\\" oryx:anchors=\\\"top\\\" /> <oryx:magnet oryx:cx=\\\"75\\\" oryx:cy=\\\"1\\\" oryx:anchors=\\\"top\\\" /> <oryx:magnet oryx:cx=\\\"50\\\" oryx:cy=\\\"40\\\" oryx:default=\\\"yes\\\" /> </oryx:magnets> <g pointer-events=\\\"fill\\\" oryx:minimumSize=\\\"50 40\\\"> <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\\\" /> <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\\\" /> <text font-size=\\\"12\\\" id=\\\"text_name\\\" x=\\\"50\\\" y=\\\"40\\\" oryx:align=\\\"middle center\\\" oryx:fittoelem=\\\"text_frame\\\" stroke=\\\"#373e48\\\"> </text> <g id=\\\"processTask\\\" transform=\\\"scale(0.7,0.7) translate(8,8)\\\"> <path oryx:anchors=\\\"top left\\\" style=\\\"opacity:1;fill:#F4F6F7;stroke:#000000\\\" d=\\\"M1 23 L7 11 L1 0 L30 0 L 35 11 L 30 23z\\\"/> </g> <g id=\\\"required\\\" display=\\\"inherit\\\" stroke=\\\"#000000\\\"><g oryx:anchors=\\\"bottom\\\"><path fill=\\\"none\\\" oryx:anchors=\\\"bottom\\\" d=\\\"M49 67 L49 74 M49 76 L49 78\\\" transform=\\\"translate(-11,0)\\\"></path></g></g> <g id=\\\"repetition\\\" oryx:anchors=\\\"bottom\\\"><path oryx:anchors=\\\"bottom\\\" fill=\\\"none\\\" stroke=\\\"#bbbbbb\\\" stroke-width=\\\"2\\\" d=\\\"M47 68 v10 M50 68 v10 M53 68 v10\\\" transform=\\\"translate(10,0)\\\"/></g><g id=\\\"manualActivation\\\" display=\\\"inherit\\\" stroke=\\\"#000000\\\" oryx:anchors=\\\"bottom\\\"><path oryx:anchors=\\\"bottom\\\" fill=\\\"none\\\" d=\\\"M45.5 68 L54 73 L45.5 77 L45.5 69z\\\" transform=\\\"translate(-2,0)\\\"></path></g></g></svg>\",\n    \"icon\" : \"activity/processtask.png\",\n    \"groups\" : [ \"Activities\" ],\n    \"propertyPackages\" : [\n      \"overrideidpackage\",\n      \"namepackage\",\n      \"documentationpackage\",\n      \"blockingpackage\",\n      \"processtaskprocessreferencepackage\",\n      \"asyncpackage\",\n      \"requiredrulepackage\",\n      \"repetitionrulepackage\",\n      \"manualactivationrulepackage\",\n      \"completionneutralrulepackage\"],\n    \"hiddenPropertyPackages\" : [ ],\n    \"roles\" : [ \"Activity\", \"association_start\", \"association_end\", \"ActivitiesMorph\", \"all\" ]\n  }, {\n    \"type\" : \"node\",\n    \"id\" : \"TimerEventListener\",\n    \"title\" : \"Timer event listener\",\n    \"description\" : \"An eventlistener 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\" : \"activity/timereventlistener.png\",\n    \"groups\" : [ \"Event Listeners\" ],\n    \"propertyPackages\" : [\n      \"overrideidpackage\",\n      \"namepackage\",\n      \"documentationpackage\",\n      \"timerexpressionpackage\",\n      \"timerstarttriggerpackage\",\n      \"completionneutralrulepackage\"],\n    \"hiddenPropertyPackages\" : [ ],\n    \"roles\" : [ \"Activity\", \"association_start\", \"association_end\", \"ActivitiesMorph\", \"all\" ]\n  }, {\n      \"type\" : \"node\",\n      \"id\" : \"UserEventListener\",\n      \"title\" : \"User event listener\",\n      \"description\" : \"An listener for user events\",\n      \"view\" : \"<?xml version=\\\"1.0\\\" encoding=\\\"UTF-8\\\" standalone=\\\"no\\\"?><svg xmlns=\\\"http://www.w3.org/2000/svg\\\" xmlns:oryx=\\\"http://www.b3mn.org/oryx\\\" width=\\\"40\\\" height=\\\"40\\\" version=\\\"1.0\\\"> <defs></defs> <oryx:magnets> <oryx:magnet oryx:cx=\\\"16\\\" oryx:cy=\\\"16\\\" oryx:default=\\\"yes\\\" /> </oryx:magnets> <oryx:docker oryx:cx=\\\"16\\\" oryx:cy=\\\"16\\\" /> <g pointer-events=\\\"fill\\\"> <defs> <radialGradient id=\\\"background\\\" cx=\\\"10%\\\" cy=\\\"10%\\\" r=\\\"100%\\\" fx=\\\"10%\\\" fy=\\\"10%\\\"> <stop offset=\\\"0%\\\" stop-color=\\\"#ffffff\\\" stop-opacity=\\\"1\\\"/> <stop id=\\\"fill_el\\\" offset=\\\"100%\\\" stop-color=\\\"#ffffff\\\" stop-opacity=\\\"1\\\"/> </radialGradient> </defs> <circle id=\\\"bg_frame\\\" cx=\\\"16\\\" cy=\\\"16\\\" r=\\\"15\\\" stroke=\\\"black\\\" fill=\\\"url(#background) white\\\" stroke-width=\\\"1\\\"/> <circle id=\\\"frame\\\" cx=\\\"16\\\" cy=\\\"16\\\" r=\\\"12\\\" stroke=\\\"black\\\" fill=\\\"none\\\" stroke-width=\\\"1\\\"/> <g id=\\\"humanTaskBlock\\\" transform=\\\"scale(0.8,0.8) translate(7.5,7)\\\" display=\\\"inherit\\\"> <path oryx:anchors=\\\"top left\\\" style=\\\"opacity:1;fill:#F4F6F7\\\" d=\\\"M0.585,24.167h24.083v-7.833c0,0-2.333-3.917-7.083-5.167h-9.25 c-4.417,1.333-7.833,5.75-7.833,5.75L0.585,24.167z\\\"/> <path oryx:anchors=\\\"top left\\\" style=\\\"opacity:1;fill:none\\\" d=\\\"M 6 20 L 6 24\\\" /> <path oryx:anchors=\\\"top left\\\" style=\\\"opacity:1;fill:none\\\" d=\\\"M 20 20 L 20 24\\\" /> <circle oryx:anchors=\\\"top left\\\" fill=\\\"#000000\\\" cx=\\\"13.002\\\" cy=\\\"5.916\\\" r=\\\"5.417\\\"/> <path oryx:anchors=\\\"top left\\\" style=\\\"opacity:1;fill:#F0EFF0\\\" d=\\\"M8.043,7.083c0,0,2.814-2.426,5.376-1.807s4.624-0.693,4.624-0.693 c0.25,1.688,0.042,3.75-1.458,5.584c0,0,1.083,0.75,1.083,1.5s0.125,1.875-1,3s-5.5,1.25-6.75,0S8.668,12.834,8.668,12 s0.583-1.25,1.25-1.917C8.835,9.5,7.419,7.708,8.043,7.083z\\\"/> </g> <text font-size=\\\"11\\\" id=\\\"text_name\\\" x=\\\"16\\\" y=\\\"33\\\" oryx:align=\\\"top center\\\" stroke=\\\"black\\\" ></text> </g></svg>\",\n      \"icon\" : \"event/userlistener.png\",\n      \"groups\" : [ \"Event Listeners\" ],\n      \"propertyPackages\" : [\n        \"overrideidpackage\",\n        \"namepackage\",\n        \"documentationpackage\",\n        \"completionneutralrulepackage\"],\n      \"hiddenPropertyPackages\" : [ ],\n      \"roles\" : [ \"Activity\", \"association_start\", \"association_end\", \"ActivitiesMorph\", \"all\" ]\n  }, {\n    \"type\" : \"node\",\n    \"id\" : \"EntryCriterion\",\n    \"title\" : \"Entry criterion\",\n    \"description\" : \"A sentry that defines an entry criterion\",\n    \"view\" : \"<?xml version=\\\"1.0\\\" encoding=\\\"utf-8\\\" standalone=\\\"no\\\" ?><svg xmlns=\\\"http://www.w3.org/2000/svg\\\" xmlns:svg=\\\"http://www.w3.org/2000/svg\\\" xmlns:oryx=\\\"http://www.b3mn.org/oryx\\\" xmlns:xlink=\\\"http://www.w3.org/1999/xlink\\\" width=\\\"14\\\"  height=\\\"22\\\" version=\\\"1.0\\\"> <oryx:magnets><oryx:magnet oryx:cx=\\\"8\\\" oryx:cy=\\\"10\\\" oryx:default=\\\"yes\\\" /></oryx:magnets><oryx:docker oryx:cx=\\\"16\\\" oryx:cy=\\\"16\\\" /><g pointer-events=\\\"fill\\\"><defs><radialGradient id=\\\"background\\\" cx=\\\"10%\\\" cy=\\\"10%\\\" r=\\\"100%\\\" fx=\\\"10%\\\" fy=\\\"10%\\\"><stop offset=\\\"0%\\\" stop-color=\\\"#ffffff\\\" stop-opacity=\\\"1\\\"/><stop id=\\\"fill_el\\\" offset=\\\"100%\\\" stop-color=\\\"#ffffff\\\" stop-opacity=\\\"1\\\"/></radialGradient></defs><polygon id=\\\"bg_frame\\\" points=\\\"7 0  14 11  7 22 0 11\\\" fill=\\\"url(#background) #ffffff\\\" stroke=\\\"#000000\\\"/></g></svg>\",\n    \"icon\" : \"sentry/entry.png\",\n    \"groups\" : [ \"Sentries\" ],\n    \"propertyPackages\" : [\n      \"overrideidpackage\",\n      \"namepackage\",\n      \"documentationpackage\",\n      \"ifpartconditionpackage\" ],\n    \"hiddenPropertyPackages\" : [ ],\n    \"roles\" : [ \"association_start\", \"association_end\", \"SentriesMorph\", \"EntryCriterionOnItemBoundary\" ]\n  }, {\n    \"type\" : \"node\",\n    \"id\" : \"ExitCriterion\",\n    \"title\" : \"Exit criterion\",\n    \"description\" : \"A sentry that defines an exit criterion\",\n    \"view\" : \"<?xml version=\\\"1.0\\\" encoding=\\\"utf-8\\\" standalone=\\\"no\\\" ?><svg xmlns=\\\"http://www.w3.org/2000/svg\\\" xmlns:svg=\\\"http://www.w3.org/2000/svg\\\" xmlns:oryx=\\\"http://www.b3mn.org/oryx\\\" xmlns:xlink=\\\"http://www.w3.org/1999/xlink\\\" width=\\\"14\\\"  height=\\\"22\\\" version=\\\"1.0\\\"> <oryx:magnets><oryx:magnet oryx:cx=\\\"8\\\" oryx:cy=\\\"10\\\" oryx:default=\\\"yes\\\" /></oryx:magnets><oryx:docker oryx:cx=\\\"16\\\" oryx:cy=\\\"16\\\" /><g pointer-events=\\\"fill\\\"><defs><radialGradient id=\\\"background\\\" cx=\\\"10%\\\" cy=\\\"10%\\\" r=\\\"100%\\\" fx=\\\"10%\\\" fy=\\\"10%\\\"><stop offset=\\\"0%\\\" stop-color=\\\"#ffffff\\\" stop-opacity=\\\"1\\\"/><stop id=\\\"fill_el\\\" offset=\\\"100%\\\" stop-color=\\\"#000000\\\" stop-opacity=\\\"1\\\"/></radialGradient></defs><polygon id=\\\"bg_frame\\\" points=\\\"7 0  14 11  7 22 0 11\\\" fill=\\\"url(#background) #000000\\\" /></g></svg>\",\n    \"icon\" : \"sentry/exit.png\",\n    \"groups\" : [ \"Sentries\" ],\n    \"propertyPackages\" : [\n      \"overrideidpackage\",\n      \"namepackage\",\n      \"documentationpackage\",\n      \"ifpartconditionpackage\" ],\n    \"hiddenPropertyPackages\" : [ ],\n    \"roles\" : [ \"association_start\", \"SentriesMorph\", \"ExitCriterionOnItemBoundary\" ]\n  }, {\n    \"type\" : \"edge\",\n    \"id\" : \"Association\",\n    \"title\" : \"Association\",\n    \"description\" : \"Associates a sentry with a plan item.\",\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\" : \"connection/connector.png\",\n    \"groups\" : [ \"Connectors\" ],\n    \"layout\" : [ {\n      \"type\" : \"layout.bpmn2_0.sequenceflow\"\n    } ],\n    \"propertyPackages\" : [\n      \"overrideidpackage\",\n      \"namepackage\",\n      \"documentationpackage\",\n      \"transitioneventpackage\" ],\n    \"hiddenPropertyPackages\" : [ ],\n    \"roles\" : [ \"ConnectingObjectsMorph\", \"all\" ]\n  }],\n  \"rules\" : {\n    \"cardinalityRules\" : [ {\n      \"role\" : \"Startevents_all\",\n      \"incomingEdges\" : [ {\n        \"role\" : \"Association\",\n        \"maximum\" : 0\n      } ]\n    }, {\n      \"role\" : \"Endevents_all\",\n      \"outgoingEdges\" : [ {\n        \"role\" : \"Association\",\n        \"maximum\" : 0\n      } ]\n    }],\n    \"connectionRules\" : [ {\n      \"role\" : \"Association\",\n      \"connects\" : [ {\n        \"from\" : \"association_start\",\n        \"to\" : [ \"association_end\" ]\n      }]\n    }, {\n      \"role\" : \"EntryCriterionOnItemBoundary\",\n      \"connects\" : [ {\n        \"from\" : \"Activity\",\n        \"to\" : [ \"EntryCriterionOnItemBoundary\"]\n      }, {\n        \"from\" : \"StageActivity\",\n        \"to\" : [ \"EntryCriterionOnItemBoundary\"]\n      }]\n    }, {\n        \"role\" : \"ExitCriterionOnItemBoundary\",\n        \"connects\" : [ {\n          \"from\" : \"Activity\",\n          \"to\" : [ \"ExitCriterionOnItemBoundary\" ]\n        }, {\n          \"from\" : \"StageActivity\",\n          \"to\" : [ \"ExitCriterionOnItemBoundary\"]\n        }, {\n          \"from\" : \"StageModelActivity\",\n          \"to\" : [ \"ExitCriterionOnItemBoundary\"]\n        }\n      ]}\n    ],\n    \"containmentRules\" : [ {\n      \"role\" : \"CaseDiagram\",\n      \"contains\" : [ \"CasePlanModel\", \"ExitCriterion\" ]\n    }, {\n      \"role\" : \"CasePlanModel\",\n      \"contains\" : [ \"all\" ]\n    }, {\n      \"role\" : \"Stage\",\n      \"contains\" : [ \"all\" ]\n    }],\n    \"morphingRules\" : [ {\n      \"role\" : \"ActivitiesMorph\",\n      \"baseMorphs\" : [ \"CaseTask\" ],\n      \"preserveBounds\" : true\n    }, {\n      \"role\" : \"SentriesMorph\",\n      \"baseMorphs\" : [ \"EntryCriterion\" ],\n      \"preserveBounds\" : true\n    }]\n  }\n}\n"
  },
  {
    "path": "flowable-ui/src/main/resources/stencilset/zh/stencilset_bpmn.json",
    "content": "{\n  \"title\" : \"流程编辑器\",\n  \"namespace\" : \"http://b3mn.org/stencilset/bpmn2.0#\",\n  \"description\" : \"BPMN 流程编辑器\",\n  \"propertyPackages\" : [ {\n    \"name\" : \"process_idpackage\",\n    \"properties\" : [ {\n      \"id\" : \"process_id\",\n      \"type\" : \"String\",\n      \"title\" : \"流程标识(ID)\",\n      \"value\" : \"process\",\n      \"description\" : \"流程定义唯一标识ID.\",\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\" : \"BPMN元素名称.\",\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\" : \"BPMN元素描述.\",\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_historylevelpackage\",\n    \"properties\" : [ {\n      \"id\" : \"process_historylevel\",\n      \"type\" : \"flowable-processhistorylevel\",\n      \"title\" : \"Set a specific history level for this process definition\",\n      \"value\" : \"\",\n      \"description\" : \"Set a specific history level for this process definition\",\n      \"popular\" : true\n    } ]\n  }, {\n    \"name\" : \"isexecutablepackage\",\n    \"properties\" : [ {\n      \"id\" : \"isexecutable\",\n      \"type\" : \"Boolean\",\n      \"title\" : \"Is executable\",\n      \"value\" : \"true\",\n      \"description\" : \"Is the process executable?\",\n      \"popular\" : true\n    } ]\n  }, {\n\t\"name\" : \"process_potentialstarteruserpackage\",\n\t\"properties\" : [ {\n\t\t\"id\" : \"process_potentialstarteruser\",\n\t\t\"type\" : \"String\",\n\t\t\"title\" : \"流程启动人\",\n\t\t\"value\" : \"\",\n\t\t\"description\" : \"哪一个用户，可以启动流程?\",\n\t\t\"popular\" : true\n\t\t} ]\n  }, {\n\t\"name\" : \"process_potentialstartergrouppackage\",\n\t\"properties\" : [ {\n\t\t\"id\" : \"process_potentialstartergroup\",\n\t\t\"type\" : \"String\",\n\t\t\"title\" : \"流程启动组\",\n\t\t\"value\" : \"\",\n\t\t\"description\" : \"那一个组，可以启动流程?\",\n\t\t\"popular\" : true\n\t} ]\n  }, {\n    \"name\" : \"process_namespacepackage\",\n    \"properties\" : [ {\n      \"id\" : \"process_namespace\",\n      \"type\" : \"String\",\n      \"title\" : \"命名空间\",\n      \"value\" : \"http://www.flowable.org/processdef\",\n      \"description\" : \"流程定义命名空间.\",\n      \"popular\" : true\n    } ]\n  }, {\n    \"name\" : \"process_iseagerexecutionfetchpackage\",\n    \"properties\" : [ {\n      \"id\" : \"iseagerexecutionfetch\",\n      \"type\" : \"Boolean\",\n      \"title\" : \"Eager execution fetching\",\n      \"value\" : \"false\",\n      \"description\" : \"Enable eager execution fetching for this process definition?\",\n      \"popular\" : true\n    } ]\n  }, {\n    \"name\" : \"asynchronousdefinitionpackage\",\n    \"properties\" : [ {\n      \"id\" : \"asynchronousdefinition\",\n      \"type\" : \"Boolean\",\n      \"title\" : \"异步\",\n      \"value\" : \"false\",\n      \"description\" : \"定义为一个异步活动.\",\n      \"popular\" : true\n    } ]\n  }, {\n    \"name\" : \"datapropertiespackage\",\n    \"properties\" : [ {\n      \"id\" : \"dataproperties\",\n      \"type\" : \"Complex\",\n      \"title\" : \"Data Objects\",\n      \"value\" : \"\",\n      \"description\" : \"Definition of the data object properties\",\n      \"popular\" : true\n    } ]\n  }, {\n    \"name\" : \"exclusivedefinitionpackage\",\n    \"properties\" : [ {\n      \"id\" : \"exclusivedefinition\",\n      \"type\" : \"Boolean\",\n      \"title\" : \"独占任务\",\n      \"value\" : \"false\",\n      \"description\" : \"定义为一个独占任务.\",\n      \"popular\" : true\n    } ]\n  }, {\n    \"name\" : \"executionlistenerspackage\",\n    \"properties\" : [ {\n      \"id\" : \"executionlisteners\",\n      \"type\" : \"multiplecomplex\",\n      \"title\" : \"执行监听器\",\n      \"value\" : \"\",\n      \"description\" : \"监听activity, process, sequence flow 启动和结束事件.\",\n      \"popular\" : true\n    } ]\n  }, {\n    \"name\" : \"tasklistenerspackage\",\n    \"properties\" : [ {\n      \"id\" : \"tasklisteners\",\n      \"type\" : \"multiplecomplex\",\n      \"title\" : \"任务监听器\",\n      \"value\" : \"\",\n      \"description\" : \"任务监听器\",\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 Flowable 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\" : \"分配任务给用户\",\n      \"popular\" : true\n    } ]\n  }, {\n    \"name\" : \"formpropertiespackage\",\n    \"properties\" : [ {\n      \"id\" : \"formproperties\",\n      \"type\" : \"Complex\",\n      \"title\" : \"表单属性\",\n      \"value\" : \"\",\n      \"description\" : \"定义表单属性\",\n      \"popular\" : true\n    } ]\n  }, {\n    \"name\" : \"formkeydefinitionpackage\",\n    \"properties\" : [ {\n      \"id\" : \"formkeydefinition\",\n      \"type\" : \"String\",\n      \"title\" : \"表单key\",\n      \"value\" : \"\",\n      \"description\" : \"表单key，提供一个表单的引用.\",\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\" : \"到期时间.\",\n      \"popular\" : true\n    } ]\n  }, {\n    \"name\" : \"servicetaskclasspackage\",\n    \"properties\" : [ {\n      \"id\" : \"servicetaskclass\",\n      \"type\" : \"String\",\n      \"title\" : \"类\",\n      \"value\" : \"\",\n      \"description\" : \"实现 service task logic 的类.\",\n      \"popular\" : true\n    } ]\n  }, {\n    \"name\" : \"servicetaskexpressionpackage\",\n    \"properties\" : [ {\n      \"id\" : \"servicetaskexpression\",\n      \"type\" : \"Text\",\n      \"title\" : \"表达式\",\n      \"value\" : \"\",\n      \"description\" : \"表达式定义的Service task logic.\",\n      \"popular\" : true\n    } ]\n  }, {\n    \"name\" : \"servicetaskdelegateexpressionpackage\",\n    \"properties\" : [ {\n      \"id\" : \"servicetaskdelegateexpression\",\n      \"type\" : \"Text\",\n      \"title\" : \"委托表达式\",\n      \"value\" : \"\",\n      \"description\" : \"委托表达式定义的Service task logic..\",\n      \"popular\" : true\n    } ]\n  }, {\n    \"name\" : \"servicetaskfieldspackage\",\n    \"properties\" : [ {\n      \"id\" : \"servicetaskfields\",\n      \"type\" : \"Complex\",\n      \"title\" : \"类字段\",\n      \"value\" : \"\",\n      \"description\" : \"类字段\",\n      \"popular\" : true\n    } ]\n  }, {\n    \"name\" : \"servicetaskresultvariablepackage\",\n    \"properties\" : [ {\n      \"id\" : \"servicetaskresultvariable\",\n      \"type\" : \"String\",\n      \"title\" : \"结果变量名\",\n      \"value\" : \"\",\n      \"description\" : \"Process variable name to store the service task result.\",\n      \"popular\" : true\n    } ]\n  }, {\n    \"name\" : \"servicetaskresultvariablepackage\",\n    \"properties\" : [ {\n      \"id\" : \"servicetaskUseLocalScopeForResultVariable\",\n      \"type\" : \"Boolean\",\n      \"title\" : \"Use local scope for result variable\",\n      \"value\" : \"false\",\n      \"description\" : \"Flag that marks that the used resultVariable needs to be saved as a local variable\",\n      \"popular\" : true\n    } ]\n  }, {\n    \"name\" : \"servicetasktriggerablepackage\",\n    \"properties\" : [ {\n      \"id\" : \"servicetasktriggerable\",\n      \"type\" : \"Boolean\",\n      \"title\" : \"Set service task to be triggerable\",\n      \"value\" : \"false\",\n      \"description\" : \"Sets the service task to be triggerable\",\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    }, {\n    \"name\" : \"shellcommandpackage\",\n    \"properties\" : [ {\n      \"id\" : \"shellcommand\",\n      \"type\" : \"String\",\n      \"title\" : \"命令、指令\",\n      \"value\" : \"\",\n      \"description\" : \"任务的shell指令\",\n      \"popular\" : true\n    } ]\n  }, {\n    \"name\" : \"shellarg1package\",\n    \"properties\" : [ {\n      \"id\" : \"shellarg1\",\n      \"type\" : \"Text\",\n      \"title\" : \"参数1\",\n      \"value\" : \"\",\n      \"description\" : \"shell指令的 参数1\",\n      \"popular\" : true\n    } ]\n  }, {\n    \"name\" : \"shellarg2package\",\n    \"properties\" : [ {\n      \"id\" : \"shellarg2\",\n      \"type\" : \"Text\",\n      \"title\" : \"参数2\",\n      \"value\" : \"\",\n      \"description\" : \"shell指令的 参数2\",\n      \"popular\" : true\n    } ]\n  }, {\n    \"name\" : \"shellarg3package\",\n    \"properties\" : [ {\n      \"id\" : \"shellarg3\",\n      \"type\" : \"Text\",\n      \"title\" : \"参数3\",\n      \"value\" : \"\",\n      \"description\" : \"shell指令的 参数3\",\n      \"popular\" : true\n    } ]\n  }, {\n    \"name\" : \"shellarg4package\",\n    \"properties\" : [ {\n      \"id\" : \"shellarg4\",\n      \"type\" : \"Text\",\n      \"title\" : \"参数4\",\n      \"value\" : \"\",\n      \"description\" : \"shell指令的 参数4\",\n      \"popular\" : true\n    } ]\n  }, {\n    \"name\" : \"shellarg5package\",\n    \"properties\" : [ {\n      \"id\" : \"shellarg5\",\n      \"type\" : \"Text\",\n      \"title\" : \"参数5\",\n      \"value\" : \"\",\n      \"description\" : \"shell指令的 参数5\",\n      \"popular\" : true\n    } ]\n  }, {\n    \"name\" : \"shellwaitpackage\",\n    \"properties\" : [ {\n      \"id\" : \"shellwait\",\n      \"type\" : \"Text\",\n      \"title\" : \"等待(Flag)\",\n      \"value\" : \"\",\n      \"description\" : \"等待shell指令执行结束的Flag标记.(Flag to wait for shell command execution end)\",\n      \"popular\" : true\n    } ]\n  }, {\n    \"name\" : \"shelloutputvariablepackage\",\n    \"properties\" : [ {\n      \"id\" : \"shelloutputvariable\",\n      \"type\" : \"Text\",\n      \"title\" : \"输出变量\",\n      \"value\" : \"\",\n      \"description\" : \"存储shell指令输出的变量\",\n      \"popular\" : true\n    } ]\n  }, {\n    \"name\" : \"shellerrorcodevariablepackage\",\n    \"properties\" : [ {\n      \"id\" : \"shellerrorcodevariable\",\n      \"type\" : \"Text\",\n      \"title\" : \"错误码变量\",\n      \"value\" : \"\",\n      \"description\" : \"存储shell指令错误码的变量\",\n      \"popular\" : true\n    } ]\n  }, {\n    \"name\" : \"shellredirecterrorpackage\",\n    \"properties\" : [ {\n      \"id\" : \"shellredirecterror\",\n      \"type\" : \"Text\",\n      \"title\" : \"重定向错误\",\n      \"value\" : \"\",\n      \"description\" : \"(Redirect error)If true merge error output with standard output\",\n      \"popular\" : true\n    } ]\n  }, {\n    \"name\" : \"shellcleanenvpackage\",\n    \"properties\" : [ {\n      \"id\" : \"shellcleanenv\",\n      \"type\" : \"Text\",\n      \"title\" : \"清理环境\",\n      \"value\" : \"\",\n      \"description\" : \"清理shell执行环境.Clean shell execution environment\",\n      \"popular\" : true\n    } ]\n  }, {\n    \"name\" : \"shelldirectorypackage\",\n    \"properties\" : [ {\n      \"id\" : \"shelldirectory\",\n      \"type\" : \"Text\",\n      \"title\" : \"目录\",\n      \"value\" : \"\",\n      \"description\" : \"shell进程工作目录.Shell process working directory\",\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\" : \"From\",\n      \"value\" : \"\",\n      \"description\" : \"Email的发件地址.没有提供的话就是用默认配置.\",\n      \"popular\" : true\n    } ]\n  }, {\n    \"name\" : \"mailtasksubjectpackage\",\n    \"properties\" : [ {\n      \"id\" : \"mailtasksubject\",\n      \"type\" : \"Text\",\n      \"title\" : \"主题\",\n      \"value\" : \"\",\n      \"description\" : \"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\" : \"字符集(编码格式)\",\n      \"value\" : \"\",\n      \"description\" : \"允许修改邮件字符集，是许多除英语之外的语言所必须的. \",\n      \"popular\" : true\n    } ]\n  }, {\n    \"name\" : \"httptaskrequestmethodpackage\",\n    \"properties\" : [ {\n      \"id\" : \"httptaskrequestmethod\",\n      \"type\" : \"flowable-http-request-method\",\n      \"title\" : \"请求方法\",\n      \"value\" : \"\",\n      \"description\" : \"Request method (For example - GET,POST,PUT etc).\",\n      \"popular\" : true\n    } ]\n  }, {\n    \"name\" : \"httptaskrequesturlpackage\",\n    \"properties\" : [ {\n      \"id\" : \"httptaskrequesturl\",\n      \"type\" : \"Text\",\n      \"title\" : \"请求 URL\",\n      \"value\" : \"\",\n      \"description\" : \"Request URL (For example - http://flowable.org).\",\n      \"popular\" : true\n    } ]\n  }, {\n    \"name\" : \"httptaskrequestheaderspackage\",\n    \"properties\" : [ {\n      \"id\" : \"httptaskrequestheaders\",\n      \"type\" : \"Text\",\n      \"title\" : \"请求头\",\n      \"value\" : \"\",\n      \"description\" : \"Line separated HTTP request headers (For example - Content-Type: application/json).\",\n      \"popular\" : true\n    } ]\n  }, {\n    \"name\" : \"httptaskrequestbodypackage\",\n    \"properties\" : [ {\n      \"id\" : \"httptaskrequestbody\",\n      \"type\" : \"Text\",\n      \"title\" : \"请求体\",\n      \"value\" : \"\",\n      \"description\" : \"Request body (For example- ${sampleBody}).\",\n      \"popular\" : true\n    } ]\n  }, {\n    \"name\" : \"httptaskrequesttimeoutpackage\",\n    \"properties\" : [ {\n      \"id\" : \"httptaskrequesttimeout\",\n      \"type\" : \"String\",\n      \"title\" : \"请求超时时间\",\n      \"value\" : \"\",\n      \"description\" : \"Timeout in milliseconds for the request (For example - 5000).\",\n      \"popular\" : true\n    } ]\n  }, {\n    \"name\" : \"httptaskdisallowredirectspackage\",\n    \"properties\" : [ {\n      \"id\" : \"httptaskdisallowredirects\",\n      \"type\" : \"String\",\n      \"title\" : \"不允许重定向\",\n      \"value\" : \"\",\n      \"description\" : \"Flag to disallow HTTP redirects.\",\n      \"popular\" : true\n    } ]\n  }, {\n    \"name\" : \"httptaskfailstatuscodespackage\",\n    \"properties\" : [ {\n      \"id\" : \"httptaskfailstatuscodes\",\n      \"type\" : \"String\",\n      \"title\" : \"失败的状态码\",\n      \"value\" : \"\",\n      \"description\" : \"Comma separated list of HTTP response status codes to retry, for example 400,5XX.\",\n      \"popular\" : true\n    } ]\n  }, {\n    \"name\" : \"httptaskhandlestatuscodespackage\",\n    \"properties\" : [ {\n      \"id\" : \"httptaskhandlestatuscodes\",\n      \"type\" : \"String\",\n      \"title\" : \"处理状态码\",\n      \"value\" : \"\",\n      \"description\" : \"Comma separated list of HTTP response status codes to ignore, for example 404,3XX.\",\n      \"popular\" : true\n    } ]\n  }, {\n    \"name\" : \"httptaskignoreexceptionpackage\",\n    \"properties\" : [ {\n      \"id\" : \"httptaskignoreexception\",\n      \"type\" : \"String\",\n      \"title\" : \"忽略异常\",\n      \"value\" : \"\",\n      \"description\" : \"Flag to ignore exceptions.\",\n      \"popular\" : true\n    } ]\n  }, \n  {\n    \"name\" : \"httptasksaveresponseparameterstransientpackage\",\n    \"properties\" : [ {\n      \"id\" : \"httptasksaveresponseparameterstransient\",\n      \"type\" : \"String\",\n      \"title\" : \"以 transient variable 的形式保存返回变量、数据\",\n      \"value\" : \"\",\n      \"description\" : \"Flag indicating to store the response variable(s) transient\",\n      \"popular\" : true\n    } ]\n  }, \n  {\n    \"name\" : \"httptasksaveresponseasjsonpackage\",\n    \"properties\" : [ {\n      \"id\" : \"httptasksaveresponseasjson\",\n      \"type\" : \"String\",\n      \"title\" : \"以JSON格式保存返回变量、数据\",\n      \"value\" : \"\",\n      \"description\" : \"Flag indicating to store the response variable as a JSON variable instead of a String\",\n      \"popular\" : true\n    } ]\n  },\n  {\n      \"name\": \"skipexpressionpackage\",\n      \"properties\": [\n        {\n          \"id\": \"skipexpression\",\n          \"type\": \"String\",\n          \"title\": \"Skip expression\",\n          \"value\": \"\",\n          \"description\": \"Skip an expression execution associated with task or association or not.\",\n          \"popular\": true\n        }\n      ]\n    },\n    {\n    \"name\" : \"httptaskresponsevariablenamepackage\",\n    \"properties\" : [ {\n      \"id\" : \"httptaskresponsevariablename\",\n      \"type\" : \"String\",\n      \"title\" : \"响应变量名\",\n      \"value\" : \"\",\n      \"description\" : \"Define the variable name to store the http response.\",\n      \"popular\" : true\n    } ]\n  }, {\n    \"name\" : \"httptasksaverequestvariablespackage\",\n    \"properties\" : [ {\n      \"id\" : \"httptasksaverequestvariables\",\n      \"type\" : \"String\",\n      \"title\" : \"保存请求变量\",\n      \"value\" : \"\",\n      \"description\" : \"Flag to save request variables.\",\n      \"popular\" : true\n    } ]\n  }, {\n    \"name\" : \"httptasksaveresponseparameterspackage\",\n    \"properties\" : [ {\n      \"id\" : \"httptasksaveresponseparameters\",\n      \"type\" : \"String\",\n      \"title\" : \"保存响应状态,头\",\n      \"value\" : \"\",\n      \"description\" : \"Flag to save response status, headers etc.\",\n      \"popular\" : true\n    } ]\n  }, {\n    \"name\" : \"httptaskresultvariableprefixpackage\",\n    \"properties\" : [ {\n      \"id\" : \"httptaskresultvariableprefix\",\n      \"type\" : \"String\",\n      \"title\" : \"结果变量的前缀\",\n      \"value\" : \"\",\n      \"description\" : \"Prefix for the execution variable names.\",\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\" : \"callactivityinheritvariablespackage\",\n    \"properties\" : [ {\n      \"id\" : \"callactivityinheritvariables\",\n      \"type\" : \"Boolean\",\n      \"title\" : \"Inherit variables in sub process\",\n      \"value\" : \"false\",\n      \"description\" : \"Inherit parent process variables in the sub process.\",\n      \"popular\" : true\n    } ]\n  }, {\n    \"name\" : \"callactivitysamedeploymentpackage\",\n    \"properties\" : [ {\n      \"id\" : \"callactivitysamedeployment\",\n      \"type\" : \"Boolean\",\n      \"title\" : \"Start the referenced process from the same deployment.\",\n      \"value\" : \"false\",\n      \"description\" : \"Use the referenced process from the same deployment.\",\n      \"popular\" : true\n    } ]\n  }, {\n    \"name\" : \"callactivityprocessinstancenamepackage\",\n    \"properties\" : [ {\n      \"id\" : \"callactivityprocessinstancename\",\n      \"type\" : \"String\",\n      \"title\" : \"Process instance name\",\n      \"value\" : \"\",\n      \"description\" : \"An expression that resolves to the name of the child process instance\",\n      \"popular\" : true\n    } ]\n  }, {\n    \"name\" : \"callactivityinheritbusinesskeypackage\",\n    \"properties\" : [ {\n      \"id\" : \"callactivityinheritbusinesskey\",\n      \"type\" : \"Boolean\",\n      \"title\" : \"Inherit business key\",\n      \"value\" : \"false\",\n      \"description\" : \"Inherit the business key from the parent process.\",\n      \"popular\" : true\n    } ]\n  }, {\n    \"name\" : \"callactivityuselocalscopeforoutparameterspackage\",\n    \"properties\" : [ {\n      \"id\" : \"callactivityuselocalscopeforoutparameters\",\n      \"type\" : \"Boolean\",\n      \"title\" : \"Use local scope for out parameters\",\n      \"value\" : \"false\",\n      \"description\" : \"Use local variable scope for out parameters.\",\n      \"popular\" : true\n    } ]\n  }, {\n    \"name\" : \"callactivitybusinesskeypackage\",\n    \"properties\" : [ {\n      \"id\" : \"callactivitybusinesskey\",\n      \"type\" : \"String\",\n      \"title\" : \"Business key expression\",\n      \"value\" : \"\",\n      \"description\" : \"An expression that resolves to a business key for the child process instance\",\n      \"popular\" : true\n    } ]\n  }, {\n    \"name\" : \"cameltaskcamelcontextpackage\",\n    \"properties\" : [ {\n      \"id\" : \"cameltaskcamelcontext\",\n      \"type\" : \"String\",\n      \"title\" : \"Camel context\",\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\" : \"Endpoint 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\" : \"Text\",\n      \"title\" : \"Payload expression\",\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\" : \"Result variable\",\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\" : \"条件流\",\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\" : \"时间周期(e.g. 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\" : \"持续时间(e.g. 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\" : \"Time End Date in 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\" : \"定义信号名称.\",\n      \"popular\" : true\n    } ]\n  }, {\n    \"name\" : \"errorrefpackage\",\n    \"properties\" : [ {\n      \"id\" : \"errorref\",\n      \"type\" : \"String\",\n      \"title\" : \"错误引用\",\n      \"value\" : \"\",\n      \"description\" : \"定义错误名称.\",\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\" : \"该流程的发起者.\",\n      \"popular\" : true\n    } ]\n  }, {\n    \"name\" : \"textpackage\",\n    \"properties\" : [ {\n      \"id\" : \"text\",\n      \"type\" : \"String\",\n      \"title\" : \"文本\",\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\" : \"flowable-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\" : \"A flag that identifies whether this activity is intended for the purposes of compensation.\",\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\" : \"Is a transaction sub process\",\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\" : \"formreferencepackage\",\n    \"properties\" : [ {\n      \"id\" : \"formreference\",\n      \"type\" : \"Complex\",\n      \"title\" : \"表单引用\",\n      \"value\" : \"\",\n      \"description\" : \"Reference to a form\",\n      \"popular\" : true\n    } ]\n  }, {\n    \"name\" : \"terminateAllpackage\",\n    \"properties\" : [ {\n      \"id\" : \"terminateAll\",\n      \"type\" : \"Boolean\",\n      \"title\" : \"Terminate all\",\n      \"value\" : \"false\",\n      \"description\" : \"Enable to terminate the process instance\",\n      \"popular\" : true\n    } ]\n  }, {\n    \"name\" : \"decisiontaskdecisiontablereferencepackage\",\n    \"properties\" : [ {\n      \"id\" : \"decisiontaskdecisiontablereference\",\n      \"type\" : \"Complex\",\n      \"title\" : \"Decision table reference\",\n      \"value\" : \"\",\n      \"description\" : \"Set the decision table reference\",\n      \"popular\" : true\n    } ]\n  }, {\n    \"name\" : \"decisiontaskthrowerroronnohitspackage\",\n    \"properties\" : [ {\n      \"id\" : \"decisiontaskthrowerroronnohits\",\n      \"type\" : \"Boolean\",\n      \"title\" : \"Throw error if no rules were hit\",\n      \"value\" : \"false\",\n      \"description\" : \"Should an error be thrown if no rules of the decision table were hit and consequently no result was found.\",\n      \"popular\" : true\n    } ]\n  }, {\n    \"name\" : \"interruptingpackage\",\n    \"properties\" : [ {\n      \"id\" : \"interrupting\",\n      \"type\" : \"Boolean\",\n      \"title\" : \"Interrupting\",\n      \"value\" : \"true\",\n      \"description\" : \"Should all parent executions be terminated?\",\n      \"popular\" : true,\n      \"refToView\" : [ \"frame\" ]\n    } ]\n  }, {\n    \"name\" : \"completionconditionpackage\",\n    \"properties\" : [ {\n      \"id\" : \"completioncondition\",\n      \"type\" : \"String\",\n      \"title\" : \"Completion condition\",\n      \"value\" : \"\",\n      \"description\" : \"The completion condition for the adhoc sub process\",\n      \"popular\" : true\n    } ]\n  }, {\n    \"name\" : \"orderingpackage\",\n    \"properties\" : [ {\n      \"id\" : \"ordering\",\n      \"type\" : \"flowable-ordering\",\n      \"title\" : \"Ordering\",\n      \"value\" : \"Parallel\",\n      \"description\" : \"The ordering for the adhoc sub process\",\n      \"popular\" : true\n    } ]\n  }, {\n    \"name\" : \"cancelremaininginstancespackage\",\n    \"properties\" : [ {\n      \"id\" : \"cancelremaininginstances\",\n      \"type\" : \"Boolean\",\n      \"title\" : \"Cancel remaining instances\",\n      \"value\" : \"true\",\n      \"description\" : \"Cancel the remaining instances for the adhoc sub process?\",\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\", \"process_historylevelpackage\", \"isexecutablepackage\", \"datapropertiespackage\", \"executionlistenerspackage\", \"eventlistenerspackage\", \"signaldefinitionspackage\", \"messagedefinitionspackage\", \"process_potentialstarteruserpackage\",\"process_potentialstartergrouppackage\", \"process_iseagerexecutionfetchpackage\" ],\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\", \"formreferencepackage\", \"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\", \"interruptingpackage\" ],\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\", \"interruptingpackage\" ],\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\", \"interruptingpackage\" ],\n    \"hiddenPropertyPackages\" : [ ],\n    \"roles\" : [ \"sequence_start\", \"Startevents_all\", \"StartEventsMorph\", \"all\" ]\n  }, {\n    \"type\" : \"node\",\n    \"id\" : \"UserTask\",\n    \"title\" : \"用户任务\",\n    \"description\" : \"A manual task assigned to a specific person\",\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\", \"formreferencepackage\", \"duedatedefinitionpackage\", \"prioritydefinitionpackage\", \"formpropertiespackage\", \"tasklistenerspackage\", \"skipexpressionpackage\" ],\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\", \"servicetasktriggerablepackage\", \"executionlistenerspackage\", \"multiinstance_typepackage\", \"multiinstance_cardinalitypackage\", \"multiinstance_collectionpackage\", \"multiinstance_variablepackage\", \"multiinstance_conditionpackage\", \"isforcompensationpackage\", \"servicetaskclasspackage\", \"servicetaskexpressionpackage\", \"servicetaskdelegateexpressionpackage\", \"servicetaskfieldspackage\", \"servicetaskresultvariablepackage\", \"skipexpressionpackage\" ],\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 task\",\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\" : \"HttpTask\",\n    \"title\" : \"调用任务\",\n    \"description\" : \"A HTTP 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 16.704699,5.9229055 q 0.358098,0 0.608767,0.2506681 0.250669,0.250668 0.250669,0.6087677 0,0.3580997 -0.250669,0.6087677 -0.250669,0.2506679 -0.608767,0.2506679 -0.358098,0 -0.608767,-0.2506679 -0.250669,-0.250668 -0.250669,-0.6087677 0,-0.3580997 0.250669,-0.6087677 0.250669,-0.2506681 0.608767,-0.2506681 z m 2.578308,-2.0053502 q -2.229162,0 -3.854034,0.6759125 -1.624871,0.6759067 -3.227361,2.2694472 -0.716197,0.725146 -1.575633,1.7457293 L 7.2329969,8.7876913 Q 7.0897576,8.8055849 7.000233,8.9309334 L 4.9948821,12.368677 q -0.035811,0.06267 -0.035811,0.143242 0,0.107426 0.080572,0.205905 l 0.5729577,0.572957 q 0.125334,0.116384 0.2864786,0.07162 l 2.4708789,-0.760963 2.5156417,2.515645 -0.76096,2.470876 q -0.009,0.02687 -0.009,0.08057 0,0.125338 0.08058,0.205905 l 0.572957,0.572958 q 0.170096,0.152194 0.349146,0.04476 l 3.437744,-2.005351 q 0.125335,-0.08953 0.143239,-0.232763 l 0.17905,-3.392986 q 1.02058,-0.859435 1.745729,-1.575629 1.67411,-1.6830612 2.309735,-3.2049805 0.635625,-1.5219191 0.635625,-3.8585111 0,-0.1253369 -0.08505,-0.2148575 -0.08505,-0.089526 -0.201431,-0.089526 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.http.png\",\n    \"groups\" : [ \"活动\" ],\n    \"propertyPackages\" : [ \"overrideidpackage\", \"namepackage\", \"documentationpackage\", \"asynchronousdefinitionpackage\", \"exclusivedefinitionpackage\", \"executionlistenerspackage\", \"multiinstance_typepackage\", \"multiinstance_cardinalitypackage\", \"multiinstance_collectionpackage\", \"multiinstance_variablepackage\", \"multiinstance_conditionpackage\", \"isforcompensationpackage\", \"httptaskrequestmethodpackage\", \"httptaskrequesturlpackage\", \"httptaskrequestheaderspackage\", \"httptaskrequestbodypackage\", \"httptaskrequesttimeoutpackage\", \"httptaskdisallowredirectspackage\", \"httptaskfailstatuscodespackage\", \"httptaskhandlestatuscodespackage\", \"httptaskignoreexceptionpackage\", \"httptaskresponsevariablenamepackage\", \"httptasksaverequestvariablespackage\", \"httptasksaveresponseparameterspackage\", \"httptaskresultvariableprefixpackage\", \"httptasksaveresponseparameterstransientpackage\", \"httptasksaveresponseasjsonpackage\" ],\n    \"hiddenPropertyPackages\" : [ ],\n    \"roles\" : [ \"Activity\", \"sequence_start\", \"sequence_end\", \"ActivitiesMorph\", \"all\" ]\n  }, {\n    \"type\" : \"node\",\n    \"id\" : \"MuleTask\",\n    \"title\" : \"任务(Mule task)\",\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\" : \"发送任务\",\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\" : \"DecisionTask\",\n    \"title\" : \"决策任务\",\n    \"description\" : \"Task to use the Flowable DMN rule engine\",\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=\\\"decisionTask\\\" 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.9,2.4000386 3.7,0 0,2.7999224 -3.7,0 z m 4.36364,0 3.7,0 0,2.7999224 -3.7,0 z m 4.36364,0 3.7,0 0,2.7999224 -3.7,0 z m -8.67364,3.9 3.7,0 0,2.7999224 -3.7,0 z m 4.36364,0 3.7,0 0,2.7999224 -3.7,0 z m 4.36364,0 3.7,0 0,2.7999224 -3.7,0 z m -8.67364,3.9 3.7,0 0,2.7999224 -3.7,0 z m 4.36364,0 3.7,0 0,2.7999224 -3.7,0 z m 4.36364,0 3.7,0 0,2.7999224 -3.7,0 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\\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.decision.png\",\n    \"groups\" : [ \"活动\" ],\n    \"propertyPackages\" : [ \"overrideidpackage\", \"namepackage\", \"documentationpackage\", \"asynchronousdefinitionpackage\", \"exclusivedefinitionpackage\", \"executionlistenerspackage\", \"multiinstance_typepackage\", \"multiinstance_cardinalitypackage\", \"multiinstance_collectionpackage\", \"multiinstance_variablepackage\", \"multiinstance_conditionpackage\", \"isforcompensationpackage\", \"decisiontaskdecisiontablereferencepackage\", \"decisiontaskthrowerroronnohitspackage\" ],\n    \"hiddenPropertyPackages\" : [ ],\n    \"roles\" : [ \"Activity\", \"sequence_start\", \"sequence_end\", \"ActivitiesMorph\", \"all\" ]\n  },\n    {\n      \"type\": \"node\",\n      \"id\": \"ShellTask\",\n      \"title\": \"Shell 任务\",\n      \"description\": \"An automatic task with shell batch 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=\\\"shellTask\\\" transform=\\\"translate(2,2)\\\">\\n\\t\\t<path oryx:anchors=\\\"top left\\\"\\n\\t\\t\\td=\\\"m 1,2 0,14 16,0 0,-14 z m 1.4,3 12.7,0 0,10 -12.7,0 z\\\"\\n     \\t\\tstyle=\\\"fill:#72a7d0;stroke:none\\\"\\n\\t\\t/><text x='3' y='9' style='fill:#72a7d0;font-size:5px;'><![CDATA[>_]]></text>\\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.shell.png\",\n      \"groups\": [\n        \"活动\"\n      ],\n      \"propertyPackages\": [\n        \"overrideidpackage\",\n        \"namepackage\",\n        \"documentationpackage\",\n        \"asynchronousdefinitionpackage\",\n        \"shellcommandpackage\",\n        \"shellarg1package\",\n        \"shellarg2package\",\n        \"shellarg3package\",\n        \"shellarg4package\",\n        \"shellarg5package\",\n        \"shellwaitpackage\",\n        \"shelloutputvariablepackage\",\n        \"shellerrorcodevariablepackage\",\n        \"shellredirecterrorpackage\",\n        \"shellcleanenvpackage\",\n        \"shelldirectorypackage\",\n        \"exclusivedefinitionpackage\",\n        \"executionlistenerspackage\",\n        \"multiinstance_typepackage\",\n        \"multiinstance_cardinalitypackage\",\n        \"multiinstance_collectionpackage\",\n        \"multiinstance_variablepackage\",\n        \"multiinstance_conditionpackage\",\n        \"isforcompensationpackage\"\n      ],\n      \"hiddenPropertyPackages\": [],\n      \"roles\": [\n        \"Activity\",\n        \"sequence_start\",\n        \"sequence_end\",\n        \"ActivitiesMorph\",\n        \"all\"\n      ]\n    },{\n    \"type\" : \"node\",\n    \"id\" : \"SubProcess\",\n    \"title\" : \"子流程\",\n    \"description\" : \"A sub process scope\",\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\", \"datapropertiespackage\", \"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\" : \"CollapsedSubProcess\",\n    \"title\" : \"可折叠子流程\",\n    \"description\" : \"A sub process scope\",\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=\\\"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<g id=\\\"subprocess\\\">\\n\\t\\t<rect height=\\\"10\\\" width=\\\"10\\\" x=\\\"45\\\" y=\\\"65\\\" stroke=\\\"#bbbbbb\\\" fill=\\\"none\\\" />\\n\\t\\t<path d=\\\"M50 65 L50 75\\\" stroke=\\\"black\\\" />\\n\\t\\t<path d=\\\"M45 70 L55 70\\\" stroke=\\\"black\\\" />\\n\\t</g>\\n  </g>\\n</svg>\",\n    \"icon\" : \"activity/subprocess.png\",\n    \"groups\" : [ \"结构\" ],\n    \"propertyPackages\" : [ \"overrideidpackage\", \"namepackage\", \"documentationpackage\", \"asynchronousdefinitionpackage\", \"exclusivedefinitionpackage\", \"datapropertiespackage\", \"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\" : \"A event sub process scope\",\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\", \"EventSubProcess\" ]\n  }, {\n    \"type\" : \"node\",\n    \"id\" : \"CallActivity\",\n    \"title\" : \"引用流程\",\n    \"description\" : \"A call activity\",\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\", \"callactivityinheritvariablespackage\", \"callactivitysamedeploymentpackage\", \"callactivityprocessinstancenamepackage\", \"callactivityinheritbusinesskeypackage\", \"callactivitybusinesskeypackage\", \"callactivityuselocalscopeforoutparameterspackage\", \"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\" : \"A choice gateway\",\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\" : \"A parallel gateway\",\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\" : \"An inclusive gateway\",\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\" : \"An event gateway\",\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     id=\\\"g1027\\\">\\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       id=\\\"circle\\\"\\n       cx=\\\"16\\\"\\n       cy=\\\"16\\\"\\n       r=\\\"10.4\\\"\\n       stroke=\\\"#585858\\\"\\n       style=\\\"fill:none;stroke-width:0.5\\\" />\\n    <circle\\n       id=\\\"circle2\\\"\\n       cx=\\\"16\\\"\\n       cy=\\\"16\\\"\\n       r=\\\"11.7\\\"\\n       stroke=\\\"#585858\\\"\\n       style=\\\"fill:none;stroke-width:0.5\\\" />\\n    <path\\n       d=\\\"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       id=\\\"middlePolygon\\\"\\n       stroke=\\\"#585858\\\"\\n       style=\\\"fill:none;fill-opacity:1;stroke-width:1.39999998;stroke-linejoin:bevel;stroke-opacity:1\\\" />\\n    <g\\n       id=\\\"instantiate\\\">\\n      <path\\n         d=\\\"M -4.5,16 L 16,-4.5 L 35.5,16 L 16,35.5z\\\"\\n         id=\\\"bg_frame2\\\"\\n         fill=\\\"#ffffff\\\"\\n         stroke=\\\"#585858\\\"\\n         style=\\\"stroke-width:1\\\" />\\n      <circle\\n         id=\\\"circle3\\\"\\n         cx=\\\"16\\\"\\n         cy=\\\"16\\\"\\n         r=\\\"11\\\"\\n         stroke=\\\"#585858\\\"\\n         style=\\\"fill:none;stroke-width:1\\\" />\\n      <path\\n         d=\\\"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         id=\\\"middlePolygon2\\\"\\n         stroke=\\\"#585858\\\"\\n         style=\\\"fill:none;fill-opacity:1;stroke-width:1.39999998;stroke-linejoin:bevel;stroke-opacity:1\\\" />\\n      <g\\n         id=\\\"parallel\\\">\\n        <path\\n           d=\\\"M -4.5,16 L 16,-4.5 L 35.5,16 L 16,35.5z\\\"\\n           id=\\\"bg_frame3\\\"\\n           style=\\\"stroke-width:1\\\"\\n           stroke=\\\"#585858\\\"\\n           fill=\\\"#ffffff\\\" />\\n\\n        <path\\n           style=\\\"fill:none;stroke-width:1.5\\\"\\n           stroke=\\\"#585858\\\"\\n           d=\\\"m 16.128163,8.1671486 7.721331,5.6098764 -2.949286,9.076969 -9.544091,0 -2.9492862,-9.07697 z\\\"/>\\n        <circle     \\n           cx=\\\"16\\\"\\n           cy=\\\"16\\\"\\n           r=\\\"11.5\\\"\\n           stroke=\\\"#585858\\\"\\n           style=\\\"fill:none;stroke:#000000;stroke-width:0.4;\\\"\\n           />\\n        <circle \\n           cx=\\\"16\\\"\\n           cy=\\\"16\\\"\\n           r=\\\"10.5\\\"\\n           stroke=\\\"#585858\\\"\\n           style=\\\"fill:none;stroke-width:0.4;\\\" />\\n      </g>\\n    </g>\\n    <text\\n       id=\\\"text_name\\\"\\n       x=\\\"26\\\"\\n       y=\\\"26\\\"\\n       oryx:align=\\\"left top\\\" />\\n  </g>\\n\\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\" : \"A boundary event that catches a 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    <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\" : \"A boundary 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  <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\" : \"A boundary 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  <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\" : \"A boundary 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  <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\" : \"A boundary cancel 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  \\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\" : \"A boundary compensation 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\\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=\\\"#585858\\\" fill=\\\"none\\\" 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\" : \"抛出错误事件的结束事件\",\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\" : \"结束取消事件\",\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\" : \"结束终止事件\",\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\" : \"用于构造流程定义的池\",\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\", \"isexecutablepackage\" ],\n    \"hiddenPropertyPackages\" : [ ],\n    \"roles\" : [ \"canContainArtifacts\", \"all\" ]\n  }, {\n    \"type\" : \"node\",\n    \"id\" : \"Lane\",\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=\\\"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\", \"skipexpressionpackage\" ],\n    \"hiddenPropertyPackages\" : [ ],\n    \"roles\" : [ \"ConnectingObjectsMorph\", \"all\" ]\n  }, {\n    \"type\" : \"edge\",\n    \"id\" : \"MessageFlow\",\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\\\" 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\" : \"文本关联(Association)\",\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\" : \"数据关联(DataAssociation)\",\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\" : [ \"Artifacts\" ],\n    \"propertyPackages\" : [ \"overrideidpackage\", \"namepackage\", \"documentationpackage\", \"textpackage\" ],\n    \"hiddenPropertyPackages\" : [ ],\n    \"roles\" : [ \"all\" ]\n  }, {\n    \"type\" : \"node\",\n    \"id\" : \"DataStore\",\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: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    \"type\" : \"node\",\n    \"id\" : \"AdhocSubProcess\",\n    \"title\" : \"adhoc子流程\",\n    \"description\" : \"adhoc子流程\",\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<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<text \\n\\t\\toryx:anchors=\\\"bottom\\\"\\n\\t\\tx=\\\"101\\\"\\n\\t\\ty=\\\"157\\\"\\n\\t\\tfont-size=\\\"20\\\"\\n\\t\\ttransform=\\\"translate(8,0)\\\"\\n\\t>~</text>\\n  </g>\\n</svg>\",\n    \"icon\" : \"activity/adhoc.subprocess.png\",\n    \"groups\" : [ \"结构\" ],\n    \"propertyPackages\" : [ \"overrideidpackage\", \"namepackage\", \"documentationpackage\", \"completionconditionpackage\", \"orderingpackage\", \"cancelremaininginstancespackage\" ],\n    \"hiddenPropertyPackages\" : [ ],\n    \"roles\" : [ \"Activity\", \"sequence_start\", \"sequence_end\", \"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\" : \"AdhocSubProcess\",\n      \"contains\" : [ \"sequence_start\", \"sequence_end\", \"from_task_event\", \"to_task_event\", \"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": "flowable-ui/src/main/resources/stencilset/zh/stencilset_cmmn.json",
    "content": "{\n  \"title\" : \"CMMN editor\",\n  \"namespace\" : \"http://b3mn.org/stencilset/cmmn1.1#\",\n  \"description\" : \"CMMN案例编辑器\",\n  \"propertyPackages\" : [ {\n    \"name\" : \"case_idpackage\",\n    \"properties\" : [ {\n      \"id\" : \"case_id\",\n      \"type\" : \"String\",\n      \"title\" : \"案例鉴别\",\n      \"value\" : \"caseModel\",\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\" : \"Name\",\n      \"value\" : \"\",\n      \"description\" : \"The descriptive name of the CMMN element.\",\n      \"popular\" : true,\n      \"refToView\" : \"text_name\"\n    } ]\n  }, {\n    \"name\" : \"documentationpackage\",\n    \"properties\" : [ {\n      \"id\" : \"documentation\",\n      \"type\" : \"Text\",\n      \"title\" : \"Documentation\",\n      \"value\" : \"\",\n      \"description\" : \"The descriptive name of the CMMN element.\",\n      \"popular\" : true\n    } ]\n  }, {\n    \"name\" : \"blockingpackage\",\n    \"properties\" : [ {\n      \"id\" : \"isblocking\",\n      \"type\" : \"Boolean\",\n      \"title\" : \"Blocking\",\n      \"value\" : \"true\",\n      \"description\" : \"Boolean property, default true. If false the task will automatically complete the task after executing any associated logic\",\n      \"popular\" : true\n    },\n    {\n      \"id\" : \"isblockingexpression\",\n      \"type\" : \"String\",\n      \"title\" : \"Blocking expression\",\n      \"value\" : \"\",\n      \"description\" : \"An expression to control at runtime whether this task is blocking or not. When set, the value of the blocking property is ignored.\",\n      \"popular\" : true\n    } ]\n  }, {\n    \"name\" : \"case_initiatorvariablenamepackage\",\n    \"properties\" : [ {\n      \"id\" : \"case_initiatorvariablename\",\n      \"type\" : \"String\",\n      \"title\" : \"Initiator variable name\",\n      \"value\" : \"\",\n      \"description\" : \"Sets the variable name to be used for the case initiator value.\",\n      \"popular\" : true\n    } ]\n  }, {\n    \"name\" : \"case_authorpackage\",\n    \"properties\" : [ {\n      \"id\" : \"case_author\",\n      \"type\" : \"String\",\n      \"title\" : \"Case author\",\n      \"value\" : \"\",\n      \"description\" : \"Author of the case definition.\",\n      \"popular\" : true\n    } ]\n  }, {\n    \"name\" : \"case_versionpackage\",\n    \"properties\" : [ {\n      \"id\" : \"case_version\",\n      \"type\" : \"String\",\n      \"title\" : \"Case version string (documentation only)\",\n      \"value\" : \"\",\n      \"description\" : \"Version identifier for documentation purpose.\",\n      \"popular\" : true\n    } ]\n  }, {\n    \"name\" : \"case_namespacepackage\",\n    \"properties\" : [ {\n      \"id\" : \"case_namespace\",\n      \"type\" : \"String\",\n      \"title\" : \"Target namespace\",\n      \"value\" : \"http://www.flowable.org/casedef\",\n      \"description\" : \"Target namespace for the case definition.\",\n      \"popular\" : true\n    } ]\n  }, {\n    \"name\" : \"usertaskassignmentpackage\",\n    \"properties\" : [ {\n      \"id\" : \"usertaskassignment\",\n      \"type\" : \"Complex\",\n      \"title\" : \"Assignments\",\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\" : \"Form properties\",\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\" : \"Form key\",\n      \"value\" : \"\",\n      \"description\" : \"Form key that provides a reference to a form.\",\n      \"popular\" : true\n    } ]\n  }, {\n    \"name\" : \"duedatedefinitionpackage\",\n    \"properties\" : [ {\n      \"id\" : \"duedatedefinition\",\n      \"type\" : \"String\",\n      \"title\" : \"Due date\",\n      \"value\" : \"\",\n      \"description\" : \"Due date of the user task.\",\n      \"popular\" : true\n    } ]\n  }, {\n    \"name\" : \"prioritydefinitionpackage\",\n    \"properties\" : [ {\n      \"id\" : \"prioritydefinition\",\n      \"type\" : \"String\",\n      \"title\" : \"Priority\",\n      \"value\" : \"\",\n      \"description\" : \"Priority of the user task.\",\n      \"popular\" : true\n    } ]\n  }, {\n    \"name\" : \"servicetaskclasspackage\",\n    \"properties\" : [ {\n      \"id\" : \"servicetaskclass\",\n      \"type\" : \"String\",\n      \"title\" : \"Class\",\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\" : \"Text\",\n      \"title\" : \"Expression\",\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\" : \"Text\",\n      \"title\" : \"Delegate expression\",\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\" : \"Class fields\",\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\" : \"Script format\",\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\" : \"Script\",\n      \"value\" : \"\",\n      \"description\" : \"Script text of the script task.\",\n      \"popular\" : true\n    } ]\n  }, {\n    \"name\" : \"asyncpackage\",\n    \"properties\" : [ {\n      \"id\" : \"isasync\",\n      \"type\" : \"Boolean\",\n      \"title\" : \"Asynchronous\",\n      \"value\" : \"\",\n      \"description\" : \"Indicates if the task needs to be executed asynchronously.\",\n      \"popular\" : true\n    }, {\n      \"id\" : \"isexclusive\",\n      \"type\" : \"Boolean\",\n      \"title\" : \"Exclusive\",\n      \"value\" : \"\",\n      \"description\" : \"Indicates if an asynchronous task must be executed exclusively\",\n      \"popular\" : true\n    } ]\n  }, {\n    \"name\" : \"mailtasktopackage\",\n    \"properties\" : [ {\n      \"id\" : \"mailtaskto\",\n      \"type\" : \"Text\",\n      \"title\" : \"To\",\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\" : \"From\",\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\" : \"Subject\",\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\" : \"Cc\",\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\" : \"Bcc\",\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\" : \"Text\",\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\" : \"httptaskrequestmethodpackage\",\n    \"properties\" : [ {\n      \"id\" : \"httptaskrequestmethod\",\n      \"type\" : \"String\",\n      \"title\" : \"Request method\",\n      \"value\" : \"\",\n      \"description\" : \"Request method (For example - GET,POST,PUT etc).\",\n      \"popular\" : true\n    } ]\n  }, {\n    \"name\" : \"httptaskrequesturlpackage\",\n    \"properties\" : [ {\n      \"id\" : \"httptaskrequesturl\",\n      \"type\" : \"Text\",\n      \"title\" : \"Request URL\",\n      \"value\" : \"\",\n      \"description\" : \"Request URL (For example - http://flowable.org).\",\n      \"popular\" : true\n    } ]\n  }, {\n    \"name\" : \"httptaskrequestheaderspackage\",\n    \"properties\" : [ {\n      \"id\" : \"httptaskrequestheaders\",\n      \"type\" : \"Text\",\n      \"title\" : \"Request headers\",\n      \"value\" : \"\",\n      \"description\" : \"Line separated HTTP request headers (For example - Content-Type: application/json).\",\n      \"popular\" : true\n    } ]\n  }, {\n    \"name\" : \"httptaskrequestbodypackage\",\n    \"properties\" : [ {\n      \"id\" : \"httptaskrequestbody\",\n      \"type\" : \"Text\",\n      \"title\" : \"Request body\",\n      \"value\" : \"\",\n      \"description\" : \"Request body (For example- ${sampleBody}).\",\n      \"popular\" : true\n    } ]\n  }, {\n    \"name\" : \"httptaskrequesttimeoutpackage\",\n    \"properties\" : [ {\n      \"id\" : \"httptaskrequesttimeout\",\n      \"type\" : \"String\",\n      \"title\" : \"Request timeout\",\n      \"value\" : \"\",\n      \"description\" : \"Timeout in milliseconds for the request (For example - 5000).\",\n      \"popular\" : true\n    } ]\n  }, {\n    \"name\" : \"httptaskdisallowredirectspackage\",\n    \"properties\" : [ {\n      \"id\" : \"httptaskdisallowredirects\",\n      \"type\" : \"String\",\n      \"title\" : \"Disallow redirects\",\n      \"value\" : \"\",\n      \"description\" : \"Flag to disallow HTTP redirects.\",\n      \"popular\" : true\n    } ]\n  }, {\n    \"name\" : \"httptaskfailstatuscodespackage\",\n    \"properties\" : [ {\n      \"id\" : \"httptaskfailstatuscodes\",\n      \"type\" : \"String\",\n      \"title\" : \"Fail status codes\",\n      \"value\" : \"\",\n      \"description\" : \"Comma separated list of HTTP response status codes to retry, for example 400,5XX.\",\n      \"popular\" : true\n    } ]\n  }, {\n    \"name\" : \"httptaskhandlestatuscodespackage\",\n    \"properties\" : [ {\n      \"id\" : \"httptaskhandlestatuscodes\",\n      \"type\" : \"String\",\n      \"title\" : \"Handle status codes\",\n      \"value\" : \"\",\n      \"description\" : \"Comma separated list of HTTP response status codes to ignore, for example 404,3XX.\",\n      \"popular\" : true\n    } ]\n  }, {\n    \"name\" : \"httptaskignoreexceptionpackage\",\n    \"properties\" : [ {\n      \"id\" : \"httptaskignoreexception\",\n      \"type\" : \"String\",\n      \"title\" : \"Ignore exception\",\n      \"value\" : \"\",\n      \"description\" : \"Flag to ignore exceptions.\",\n      \"popular\" : true\n    } ]\n  }, {\n    \"name\" : \"httptaskresponsevariablenamepackage\",\n    \"properties\" : [ {\n      \"id\" : \"httptaskresponsevariablename\",\n      \"type\" : \"String\",\n      \"title\" : \"Response variable name\",\n      \"value\" : \"\",\n      \"description\" : \"Define the variable name to store the http response.\",\n      \"popular\" : true\n    } ]\n  }, {\n    \"name\" : \"httptasksaverequestvariablespackage\",\n    \"properties\" : [ {\n      \"id\" : \"httptasksaverequestvariables\",\n      \"type\" : \"String\",\n      \"title\" : \"Save request variables\",\n      \"value\" : \"\",\n      \"description\" : \"Flag to save request variables.\",\n      \"popular\" : true\n    } ]\n  }, {\n    \"name\" : \"httptasksaveresponseparameterspackage\",\n    \"properties\" : [ {\n      \"id\" : \"httptasksaveresponseparameters\",\n      \"type\" : \"String\",\n      \"title\" : \"Save response status, headers\",\n      \"value\" : \"\",\n      \"description\" : \"Flag to save response status, headers etc.\",\n      \"popular\" : true\n    } ]\n  }, {\n    \"name\" : \"httptaskresultvariableprefixpackage\",\n    \"properties\" : [ {\n      \"id\" : \"httptaskresultvariableprefix\",\n      \"type\" : \"String\",\n      \"title\" : \"Result variable prefix\",\n      \"value\" : \"\",\n      \"description\" : \"Prefix for the execution variable names.\",\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\" : \"formreferencepackage\",\n    \"properties\" : [ {\n      \"id\" : \"formreference\",\n      \"type\" : \"Complex\",\n      \"title\" : \"Form reference\",\n      \"value\" : \"\",\n      \"description\" : \"Reference to a form\",\n      \"popular\" : true\n    } ]\n  }, {\n    \"name\" : \"decisiontaskdecisiontablereferencepackage\",\n    \"properties\" : [ {\n      \"id\" : \"decisiontaskdecisiontablereference\",\n      \"type\" : \"Complex\",\n      \"title\" : \"Decision table reference\",\n      \"value\" : \"\",\n      \"description\" : \"Set the decision table reference\",\n      \"popular\" : true\n    } ]\n  }, {\n    \"name\" : \"decisiontaskthrowerroronnohitspackage\",\n    \"properties\" : [ {\n      \"id\" : \"decisiontaskthrowerroronnohits\",\n      \"type\" : \"Boolean\",\n      \"title\" : \"Throw error if no rules were hit\",\n      \"value\" : \"false\",\n      \"description\" : \"Should an error be thrown if no rules of the decision table were hit and consequently no result was found.\",\n      \"popular\" : true\n    } ]\n  }, {\n      \"name\": \"httptaskrequestmethodpackage\",\n      \"properties\": [\n        {\n          \"id\": \"httptaskrequestmethod\",\n          \"type\": \"String\",\n          \"title\": \"Request method\",\n          \"value\": \"\",\n          \"description\": \"Request method (For example - GET,POST,PUT etc).\",\n          \"popular\": true\n        }\n      ]\n    },\n    {\n      \"name\": \"httptaskrequesturlpackage\",\n      \"properties\": [\n        {\n          \"id\": \"httptaskrequesturl\",\n          \"type\": \"Text\",\n          \"title\": \"Request URL\",\n          \"value\": \"\",\n          \"description\": \"Request URL (For example - http://flowable.org).\",\n          \"popular\": true\n        }\n      ]\n    },\n    {\n      \"name\": \"httptaskrequestheaderspackage\",\n      \"properties\": [\n        {\n          \"id\": \"httptaskrequestheaders\",\n          \"type\": \"Text\",\n          \"title\": \"Request headers\",\n          \"value\": \"\",\n          \"description\": \"Line separated HTTP request headers (For example - Content-Type: application/json).\",\n          \"popular\": true\n        }\n      ]\n    },\n    {\n      \"name\": \"httptaskrequestbodypackage\",\n      \"properties\": [\n        {\n          \"id\": \"httptaskrequestbody\",\n          \"type\": \"Text\",\n          \"title\": \"Request body\",\n          \"value\": \"\",\n          \"description\": \"Request body (For example- ${sampleBody}).\",\n          \"popular\": true\n        }\n      ]\n    },\n    {\n      \"name\": \"httptaskrequesttimeoutpackage\",\n      \"properties\": [\n        {\n          \"id\": \"httptaskrequesttimeout\",\n          \"type\": \"String\",\n          \"title\": \"Request timeout\",\n          \"value\": \"\",\n          \"description\": \"Timeout in milliseconds for the request (For example - 5000).\",\n          \"popular\": true\n        }\n      ]\n    },\n    {\n      \"name\": \"httptaskdisallowredirectspackage\",\n      \"properties\": [\n        {\n          \"id\": \"httptaskdisallowredirects\",\n          \"type\": \"String\",\n          \"title\": \"Disallow redirects\",\n          \"value\": \"\",\n          \"description\": \"Flag to disallow HTTP redirects.\",\n          \"popular\": true\n        }\n      ]\n    },\n    {\n      \"name\": \"httptaskfailstatuscodespackage\",\n      \"properties\": [\n        {\n          \"id\": \"httptaskfailstatuscodes\",\n          \"type\": \"String\",\n          \"title\": \"Fail status codes\",\n          \"value\": \"\",\n          \"description\": \"Comma separated list of HTTP response status codes to retry, for example 400,5XX.\",\n          \"popular\": true\n        }\n      ]\n    },\n    {\n      \"name\": \"httptaskhandlestatuscodespackage\",\n      \"properties\": [\n        {\n          \"id\": \"httptaskhandlestatuscodes\",\n          \"type\": \"String\",\n          \"title\": \"Handle status codes\",\n          \"value\": \"\",\n          \"description\": \"Comma separated list of HTTP response status codes to ignore, for example 404,3XX.\",\n          \"popular\": true\n        }\n      ]\n    },\n    {\n      \"name\": \"httptaskignoreexceptionpackage\",\n      \"properties\": [\n        {\n          \"id\": \"httptaskignoreexception\",\n          \"type\": \"String\",\n          \"title\": \"Ignore exception\",\n          \"value\": \"\",\n          \"description\": \"Flag to ignore exceptions.\",\n          \"popular\": true\n        }\n      ]\n    },\n    {\n      \"name\": \"httptaskresponsevariablenamepackage\",\n      \"properties\": [\n        {\n          \"id\": \"httptaskresponsevariablename\",\n          \"type\": \"String\",\n          \"title\": \"Response variable name\",\n          \"value\": \"\",\n          \"description\": \"Define the variable name to store the http response.\",\n          \"popular\": true\n        }\n      ]\n    },\n    {\n      \"name\": \"httptasksaverequestvariablespackage\",\n      \"properties\": [\n        {\n          \"id\": \"httptasksaverequestvariables\",\n          \"type\": \"String\",\n          \"title\": \"Save request variables\",\n          \"value\": \"\",\n          \"description\": \"Flag to save request variables.\",\n          \"popular\": true\n        }\n      ]\n    },\n    {\n      \"name\": \"httptasksaveresponseparameterspackage\",\n      \"properties\": [\n        {\n          \"id\": \"httptasksaveresponseparameters\",\n          \"type\": \"String\",\n          \"title\": \"Save response status, headers\",\n          \"value\": \"\",\n          \"description\": \"Flag to save response status, headers etc.\",\n          \"popular\": true\n        }\n      ]\n    },\n    {\n      \"name\": \"httptaskresultvariableprefixpackage\",\n      \"properties\": [\n        {\n          \"id\": \"httptaskresultvariableprefix\",\n          \"type\": \"String\",\n          \"title\": \"Result variable prefix\",\n          \"value\": \"\",\n          \"description\": \"Prefix for the execution variable names.\",\n          \"popular\": true\n        }\n      ]\n    },\n    {\n      \"name\" : \"httptasksaveresponseparameterstransientpackage\",\n      \"properties\" : [ {\n        \"id\" : \"httptasksaveresponseparameterstransient\",\n        \"type\" : \"String\",\n        \"title\" : \"Save response as a transient variable\",\n        \"value\" : \"\",\n        \"description\" : \"Flag indicating to store the response variable(s) transient\",\n        \"popular\" : true\n      } ]\n    }, \n    {\n      \"name\" : \"httptasksaveresponseasjsonpackage\",\n      \"properties\" : [ {\n        \"id\" : \"httptasksaveresponseasjson\",\n        \"type\" : \"String\",\n        \"title\" : \"Save response as JSON\",\n        \"value\" : \"\",\n        \"description\" : \"Flag indicating to store the response variable as a JSON variable instead of a String\",\n        \"popular\" : true\n      } ]\n    },\n    {\n    \"name\" : \"casetaskcasereferencepackage\",\n    \"properties\" : [ {\n      \"id\" : \"casetaskcasereference\",\n      \"type\" : \"Complex\",\n      \"title\" : \"Case reference\",\n      \"value\" : \"\",\n      \"description\" : \"Set the case reference\",\n      \"popular\" : true\n    } ]\n  }, {\n    \"name\" : \"processtaskprocessreferencepackage\",\n    \"properties\" : [ {\n      \"id\" : \"processtaskprocessreference\",\n      \"type\" : \"Complex\",\n      \"title\" : \"Process reference\",\n      \"value\" : \"\",\n      \"description\" : \"Set the process reference\",\n      \"popular\" : true\n    } ]\n  }, {\n    \"name\" : \"timerexpressionpackage\",\n    \"properties\" : [ {\n      \"id\" : \"timerexpression\",\n      \"type\" : \"String\",\n      \"title\" : \"Timer Expression\",\n      \"value\" : \"\",\n      \"description\" : \"An ISO-8601 string or an expression that resolves to either an ISO-8601 string or a java.util.Date\",\n      \"popular\" : true\n    } ]\n  },  {\n    \"name\" : \"timerstarttriggerpackage\",\n    \"properties\" : [ {\n      \"id\" : \"timerstarttriggersourceref\",\n      \"type\" : \"flowable-planitem-dropdown\",\n      \"title\" : \"Start trigger plan item\",\n      \"value\" : \"\",\n      \"description\" : \"A reference to the plan item for which the configured standard event needs to happen to start the timer (optional)\",\n      \"popular\" : true\n    },\n    {\n      \"id\" : \"transitionevent\",\n      \"type\" : \"flowable-transitionevent\",\n      \"title\" : \"Start trigger transition event\",\n      \"value\" : \"complete\",\n      \"description\" : \"The type of the transition event. Only used when the start trigger plan item is set\",\n      \"popular\" : true\n    } ]\n  }, {\n      \"name\": \"decisiontaskdecisionreferencepackage\",\n      \"properties\": [\n        {\n          \"id\": \"decisiontaskdecisionreference\",\n          \"type\": \"Complex\",\n          \"title\": \"Decision reference\",\n          \"value\": \"\",\n          \"description\": \"Set the decision reference\",\n          \"popular\": true\n        }\n      ]\n    }, {\n    \"name\" : \"ifpartconditionpackage\",\n    \"properties\" : [ {\n      \"id\" : \"ifpartcondition\",\n      \"type\" : \"String\",\n      \"title\" : \"Condition\",\n      \"value\" : \"\",\n      \"description\" : \"An expression that must be true to satisfy the sentry\",\n      \"popular\" : true\n    } ]\n  }, {\n    \"name\" : \"autocompletepackage\",\n    \"properties\" : [ {\n      \"id\" : \"autocompleteenabled\",\n      \"type\" : \"Boolean\",\n      \"title\" : \"Auto complete\",\n      \"value\" : \"\",\n      \"description\" : \"Flag indicating that the stage will automatically complete, once all required children are in an end state and no other children are active.\",\n      \"popular\" : true,\n      \"refToView\" : \"autoComplete\"\n    }, {\n      \"id\" : \"autocompletecondition\",\n      \"type\" : \"String\",\n      \"title\" : \"Auto complete condition\",\n      \"value\" : \"\",\n      \"description\" : \"An expression that is resolved to if the stage can automatically complere.\",\n      \"popular\" : true\n    }]\n  }, {\n    \"name\" : \"requiredrulepackage\",\n    \"properties\" : [ {\n      \"id\" : \"requiredenabled\",\n      \"type\" : \"Boolean\",\n      \"title\" : \"Required\",\n      \"value\" : \"\",\n      \"description\" : \"Flag indicating if the stage, task or milestone is required when determining the parent stage completion. By default false.\",\n      \"popular\" : true,\n      \"refToView\" : \"required\"\n    }, {\n      \"id\" : \"requiredrulecondition\",\n      \"type\" : \"String\",\n      \"title\" : \"Required Rule\",\n      \"value\" : \"\",\n      \"description\" : \"An expression that is resolved to determine if the stage, task or milestone is required when determining the parent stage completion.\",\n      \"popular\" : true\n    }]\n  }, {\n    \"name\" : \"repetitionrulepackage\",\n    \"properties\" : [ {\n      \"id\" : \"repetitionenabled\",\n      \"type\" : \"Boolean\",\n      \"title\" : \"Repetition\",\n      \"value\" : \"\",\n      \"description\" : \"Flag indicating if repetition is enabled\",\n      \"popular\" : true,\n      \"refToView\" : \"repetition\"\n    }, {\n      \"id\" : \"repetitionrulecondition\",\n      \"type\" : \"String\",\n      \"title\" : \"Repetition Rule\",\n      \"value\" : \"\",\n      \"description\" : \"An expression that is resolved to determine if new instances of the planitem need to be created\",\n      \"popular\" : true\n    },\n    {\n      \"id\" : \"repetitioncountervariablename\",\n      \"type\" : \"String\",\n      \"title\" : \"Repetition counter variable\",\n      \"value\" : \"\",\n      \"description\" : \"The name of the local variable which stores the instance counter of the repetition. Default value is 'repetitionCounter'.\",\n      \"popular\" : true\n    } ]\n  }, {\n    \"name\" : \"manualactivationrulepackage\",\n    \"properties\" : [ {\n      \"id\" : \"manualactivationenabled\",\n      \"type\" : \"Boolean\",\n      \"title\" : \"Manual activation\",\n      \"value\" : \"\",\n      \"description\" : \"Flag indicating if the task or stage needs to be manually activated. False by default.\",\n      \"popular\" : true,\n      \"refToView\" : \"manualActivation\"\n    }, {\n      \"id\" : \"manualactivationrulecondition\",\n      \"type\" : \"String\",\n      \"title\" : \"Manual activation Rule\",\n      \"value\" : \"\",\n      \"description\" : \"An expression that is resolved to determine if the stage or task needs to be manually activated.\",\n      \"popular\" : true\n    }]\n  }, {\n    \"name\" : \"completionneutralrulepackage\",\n    \"properties\" : [ {\n      \"id\" : \"completionneutralenabled\",\n      \"type\" : \"Boolean\",\n      \"title\" : \"Completion neutral\",\n      \"value\" : \"\",\n      \"description\" : \"Flag indicating if the plan item is completion neutral. False by default.\",\n      \"popular\" : true\n    }, {\n      \"id\" : \"completionneutralrulecondition\",\n      \"type\" : \"String\",\n      \"title\" : \"Completion neutral Rule\",\n      \"value\" : \"\",\n      \"description\" : \"An expression that is resolved to determine if the plan item is completion neutral.\",\n      \"popular\" : true\n    }]\n  }, {\n    \"name\": \"scriptformatpackage\",\n    \"properties\" : [ {\n        \"id\": \"scriptformat\",\n        \"type\": \"String\",\n        \"title\": \"Script format\",\n        \"value\": \"\",\n        \"description\": \"Script format of the script task (JavaScript, groovy, etc).\",\n        \"popular\": true\n  } ]\n  }, {\n    \"name\": \"scripttextpackage\",\n    \"properties\" : [ {\n        \"id\": \"scripttext\",\n        \"type\": \"Text\",\n        \"title\": \"Script\",\n        \"value\": \"\",\n        \"description\": \"Script text of the script task.\",\n        \"popular\": true\n      }\n    ]\n  }, {\n    \"name\" : \"transitioneventpackage\",\n    \"properties\" : [ {\n      \"id\" : \"transitionevent\",\n      \"type\" : \"flowable-transitionevent\",\n      \"title\" : \"Transition event type\",\n      \"value\" : \"complete\",\n      \"description\" : \"The type of the transition event\",\n      \"popular\" : true\n    } ]\n  } ],\n  \"stencils\" : [ {\n    \"type\" : \"node\",\n    \"id\" : \"CMMNDiagram\",\n    \"title\" : \"CMMN-Diagram\",\n    \"description\" : \"A CMMN 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\" : [ \"case_idpackage\", \"namepackage\", \"documentationpackage\", \"case_initiatorvariablenamepackage\", \"case_authorpackage\", \"case_versionpackage\", \"case_namespacepackage\"],\n    \"hiddenPropertyPackages\" : [ ],\n    \"roles\" : [ ]\n  }, {\n    \"type\" : \"node\",\n    \"id\" : \"CasePlanModel\",\n    \"title\" : \"Case plan model\",\n    \"description\" : \"A case plan model\",\n    \"view\" : \"<?xml version=\\\"1.0\\\" encoding=\\\"UTF-8\\\" standalone=\\\"no\\\"?> <svg xmlns=\\\"http://www.w3.org/2000/svg\\\" xmlns:svg=\\\"http://www.w3.org/2000/svg\\\" xmlns:oryx=\\\"http://www.b3mn.org/oryx\\\" xmlns:xlink=\\\"http://www.w3.org/1999/xlink\\\" version=\\\"1.0\\\" width=\\\"580\\\" height=\\\"720\\\"> <g pointer-events=\\\"fill\\\" oryx:minimumSize=\\\"580 254\\\"> <defs> <radialGradient id=\\\"background\\\" cx=\\\"10%\\\" cy=\\\"10%\\\" r=\\\"100%\\\" fx=\\\"10%\\\" fy=\\\"10%\\\"> <stop offset=\\\"0%\\\" stop-color=\\\"#ffffff\\\" stop-opacity=\\\"1\\\"/> <stop id=\\\"fill_el\\\" offset=\\\"100%\\\" stop-color=\\\"#ffffff\\\" stop-opacity=\\\"1\\\"/> </radialGradient> </defs> <path id=\\\"input_dependent\\\" oryx:resize=\\\"vertical horizontal\\\" d=\\\"M7,30 L600 30 L600 754 L7 754 L7 30Z\\\" stroke=\\\"black\\\" fill=\\\"url(#background) #ffffff\\\" /> <path id=\\\"text_path\\\" d=\\\"M20 55 L37 34 L275 34 L291 55\\\" stroke=\\\"black\\\" fill=\\\"url(#background) #ffffff\\\" transform=\\\"translate(0,-25)\\\" oryx:anchors=\\\"top left\\\"/> <text id=\\\"text_name\\\" font-size=\\\"12\\\" x=\\\"150\\\" y=\\\"18\\\" oryx:fittoelem=\\\"text_path\\\" oryx:anchors=\\\"top left\\\" oryx:align=\\\"middle center\\\" stroke=\\\"black\\\"> </text> <g id=\\\"autoComplete\\\" display=\\\"inherit\\\" stroke=\\\"#000000\\\" oryx:anchors=\\\"bottom center\\\"><path d=\\\" M284 730  L300 730  L300 746  L284 746  z\\\" oryx:anchors=\\\"bottom center\\\"></path></g>  </g> </svg>\",\n    \"icon\" : \"containers/caseplanmodel.png\",\n    \"groups\" : [ \"Containers\" ],\n    \"hide\" : true,\n    \"propertyPackages\" : [\n      \"overrideidpackage\",\n      \"namepackage\",\n      \"documentationpackage\",\n      \"formkeydefinitionpackage\",\n      \"formreferencepackage\",\n      \"autocompletepackage\"\n     ],\n    \"hiddenPropertyPackages\" : [ ],\n    \"roles\" : [ \"StageModelActivity\" ]\n  }, {\n    \"type\" : \"node\",\n    \"id\" : \"Stage\",\n    \"title\" : \"Stage\",\n    \"description\" : \"A stage\",\n    \"view\" : \"<?xml version=\\\"1.0\\\" encoding=\\\"UTF-8\\\" standalone=\\\"no\\\"?> <svg xmlns=\\\"http://www.w3.org/2000/svg\\\" xmlns:svg=\\\"http://www.w3.org/2000/svg\\\" xmlns:oryx=\\\"http://www.b3mn.org/oryx\\\" xmlns:xlink=\\\"http://www.w3.org/1999/xlink\\\" width=\\\"371\\\" height=\\\"171\\\" version=\\\"1.0\\\"> <oryx:magnets> <oryx:magnet oryx:cx=\\\"1\\\" oryx:cy=\\\"42\\\" oryx:anchors=\\\"left\\\" /> <oryx:magnet oryx:cx=\\\"1\\\" oryx:cy=\\\"84\\\" oryx:anchors=\\\"left\\\" /> <oryx:magnet oryx:cx=\\\"1\\\" oryx:cy=\\\"126\\\" oryx:anchors=\\\"left\\\" /><oryx:magnet oryx:cx=\\\"92\\\" oryx:cy=\\\"170\\\" oryx:anchors=\\\"bottom\\\" /> <oryx:magnet oryx:cx=\\\"184\\\" oryx:cy=\\\"170\\\" oryx:anchors=\\\"bottom\\\" /> <oryx:magnet oryx:cx=\\\"276\\\" oryx:cy=\\\"170\\\" oryx:anchors=\\\"bottom\\\" /><oryx:magnet oryx:cx=\\\"370\\\" oryx:cy=\\\"42\\\" oryx:anchors=\\\"right\\\" /> <oryx:magnet oryx:cx=\\\"370\\\" oryx:cy=\\\"84\\\" oryx:anchors=\\\"right\\\" /> <oryx:magnet oryx:cx=\\\"370\\\" oryx:cy=\\\"126\\\" oryx:anchors=\\\"right\\\" /><oryx:magnet oryx:cx=\\\"92\\\" oryx:cy=\\\"1\\\" oryx:anchors=\\\"top\\\" /> <oryx:magnet oryx:cx=\\\"184\\\" oryx:cy=\\\"1\\\" oryx:anchors=\\\"top\\\" /> <oryx:magnet oryx:cx=\\\"276\\\" oryx:cy=\\\"1\\\" oryx:anchors=\\\"top\\\" /><oryx:magnet oryx:cx=\\\"185\\\" oryx:cy=\\\"85\\\" oryx:default=\\\"yes\\\" /> </oryx:magnets> <g pointer-events=\\\"fill\\\" oryx:minimumSize=\\\"160 93\\\"> <polygon id=\\\"bg_frame\\\" points=\\\"10 0 360 0 370 10 370 160 360 170 10 170 0 160 0 10 10 0\\\" oryx:resize=\\\"vertical horizontal\\\" stroke=\\\"black\\\" fill=\\\"#ffffff\\\"/> <text font-size=\\\"12\\\" id=\\\"text_name\\\" x=\\\"13\\\" y=\\\"2\\\" oryx:align=\\\"top left\\\" oryx:fittoelem=\\\"bg_frame\\\" stroke=\\\"black\\\"> </text> <g id=\\\"required\\\" display=\\\"inherit\\\" stroke=\\\"#000000\\\"><path fill=\\\"none\\\" oryx:anchors=\\\"bottom\\\" d=\\\"M183 154 L183 164 M183 166 L183 168\\\" transform=\\\"translate(-4,0)\\\"></path></g> <g id=\\\"repetition\\\" oryx:anchors=\\\"bottom\\\"><path oryx:anchors=\\\"bottom\\\" fill=\\\"none\\\" stroke=\\\"#bbbbbb\\\" stroke-width=\\\"2\\\" d=\\\"M180 156 v12 M183 156 v12 M186 156 v12\\\" transform=\\\"translate(-30,0)\\\"/></g><g id=\\\"manualActivation\\\" display=\\\"inherit\\\" stroke=\\\"#000000\\\"><path d=\\\" M198.88108108108108 162  L188.88108108108108 155  L188.88108108108108 155  L188.88108108108108 167  z\\\" fill=\\\"none\\\" oryx:anchors=\\\"bottom\\\" transform=\\\"translate(-2,0)\\\"></path></g> <g id=\\\"autoComplete\\\" display=\\\"inherit\\\" stroke=\\\"#000000\\\"><path d=\\\"M180 155 L189 155 L189 167 L180 167 L180 167z\\\" oryx:anchors=\\\"bottom\\\" transform=\\\"translate(-16,0)\\\"></path></g> </g></svg>\",\n    \"icon\" : \"containers/expanded.stage.png\",\n    \"groups\" : [ \"Containers\" ],\n    \"hide\" : true,\n    \"propertyPackages\" : [\n      \"overrideidpackage\",\n      \"namepackage\",\n      \"documentationpackage\",\n      \"autocompletepackage\",\n      \"requiredrulepackage\",\n      \"repetitionrulepackage\",\n      \"manualactivationrulepackage\",\n      \"completionneutralrulepackage\"\n    ],\n    \"hiddenPropertyPackages\" : [ ],\n    \"roles\" : [ \"StageActivity\", \"all\", \"association_start\", \"association_end\" ]\n  }, {\n    \"type\" : \"node\",\n    \"id\" : \"Task\",\n    \"title\" : \"Task\",\n    \"description\" : \"A manual task\",\n    \"view\" : \"<?xml version=\\\"1.0\\\" encoding=\\\"UTF-8\\\" standalone=\\\"no\\\"?><svg xmlns=\\\"http://www.w3.org/2000/svg\\\" xmlns:svg=\\\"http://www.w3.org/2000/svg\\\" xmlns:oryx=\\\"http://www.b3mn.org/oryx\\\" xmlns:xlink=\\\"http://www.w3.org/1999/xlink\\\" width=\\\"102\\\" height=\\\"82\\\" version=\\\"1.0\\\"><defs></defs><oryx:magnets><oryx:magnet oryx:cx=\\\"1\\\" oryx:cy=\\\"20\\\" oryx:anchors=\\\"left\\\" /><oryx:magnet oryx:cx=\\\"1\\\" oryx:cy=\\\"40\\\" oryx:anchors=\\\"left\\\" /><oryx:magnet oryx:cx=\\\"1\\\" oryx:cy=\\\"60\\\" oryx:anchors=\\\"left\\\" /><oryx:magnet oryx:cx=\\\"25\\\" oryx:cy=\\\"79\\\" oryx:anchors=\\\"bottom\\\" /><oryx:magnet oryx:cx=\\\"50\\\" oryx:cy=\\\"79\\\" oryx:anchors=\\\"bottom\\\" /><oryx:magnet oryx:cx=\\\"75\\\" oryx:cy=\\\"79\\\" oryx:anchors=\\\"bottom\\\" /><oryx:magnet oryx:cx=\\\"99\\\" oryx:cy=\\\"20\\\" oryx:anchors=\\\"right\\\" /><oryx:magnet oryx:cx=\\\"99\\\" oryx:cy=\\\"40\\\" oryx:anchors=\\\"right\\\" /><oryx:magnet oryx:cx=\\\"99\\\" oryx:cy=\\\"60\\\" oryx:anchors=\\\"right\\\" /><oryx:magnet oryx:cx=\\\"25\\\" oryx:cy=\\\"1\\\" oryx:anchors=\\\"top\\\" /><oryx:magnet oryx:cx=\\\"50\\\" oryx:cy=\\\"1\\\" oryx:anchors=\\\"top\\\" /><oryx:magnet oryx:cx=\\\"75\\\" oryx:cy=\\\"1\\\" oryx:anchors=\\\"top\\\" /><oryx:magnet oryx:cx=\\\"50\\\" oryx:cy=\\\"40\\\" oryx:default=\\\"yes\\\" /></oryx:magnets><g pointer-events=\\\"fill\\\" oryx:minimumSize=\\\"50 40\\\"><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\\\" /><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\\\" /><text font-size=\\\"12\\\" id=\\\"text_name\\\" x=\\\"50\\\" y=\\\"40\\\" oryx:align=\\\"middle center\\\" oryx:fittoelem=\\\"text_frame\\\" stroke=\\\"#373e48\\\"></text><g id=\\\"required\\\" display=\\\"inherit\\\" stroke=\\\"#000000\\\"><g oryx:anchors=\\\"bottom\\\"><path fill=\\\"none\\\" oryx:anchors=\\\"bottom\\\" d=\\\"M49 67 L49 74 M49 76 L49 78\\\" transform=\\\"translate(-11,0)\\\"></path></g></g><g id=\\\"repetition\\\" oryx:anchors=\\\"bottom\\\"><path oryx:anchors=\\\"bottom\\\" fill=\\\"none\\\" stroke=\\\"#bbbbbb\\\" stroke-width=\\\"2\\\" d=\\\"M47 68 v10 M50 68 v10 M53 68 v10\\\" transform=\\\"translate(10,0)\\\"/></g><g id=\\\"manualActivation\\\" display=\\\"inherit\\\" stroke=\\\"#000000\\\" oryx:anchors=\\\"bottom\\\"><path oryx:anchors=\\\"bottom\\\" fill=\\\"none\\\" d=\\\"M45.5 68 L54 73 L45.5 77 L45.5 69z\\\" transform=\\\"translate(-2,0)\\\"></path></g></g></svg>\",\n    \"icon\" : \"activity/task.png\",\n    \"groups\" : [ \"Activities\" ],\n    \"propertyPackages\" : [\n      \"overrideidpackage\",\n      \"namepackage\",\n      \"documentationpackage\",\n      \"blockingpackage\",\n      \"asyncpackage\",\n      \"requiredrulepackage\",\n      \"repetitionrulepackage\",\n      \"manualactivationrulepackage\",\n      \"completionneutralrulepackage\"],\n    \"hiddenPropertyPackages\" : [ ],\n    \"roles\" : [ \"Activity\", \"association_start\", \"association_end\", \"ActivitiesMorph\", \"all\" ]\n  }, {\n    \"type\" : \"node\",\n    \"id\" : \"HumanTask\",\n    \"title\" : \"Human task\",\n    \"description\" : \"A manual task assigned to a specific person\",\n    \"view\" : \"<?xml version=\\\"1.0\\\" encoding=\\\"UTF-8\\\" standalone=\\\"no\\\"?><svg xmlns=\\\"http://www.w3.org/2000/svg\\\" xmlns:svg=\\\"http://www.w3.org/2000/svg\\\" xmlns:oryx=\\\"http://www.b3mn.org/oryx\\\" xmlns:xlink=\\\"http://www.w3.org/1999/xlink\\\" width=\\\"102\\\" height=\\\"82\\\" version=\\\"1.0\\\"> <defs></defs>  <oryx:magnets>  <oryx:magnet oryx:cx=\\\"1\\\" oryx:cy=\\\"20\\\" oryx:anchors=\\\"left\\\" />  <oryx:magnet oryx:cx=\\\"1\\\" oryx:cy=\\\"40\\\" oryx:anchors=\\\"left\\\" />  <oryx:magnet oryx:cx=\\\"1\\\" oryx:cy=\\\"60\\\" oryx:anchors=\\\"left\\\" /> <oryx:magnet oryx:cx=\\\"25\\\" oryx:cy=\\\"79\\\" oryx:anchors=\\\"bottom\\\" />  <oryx:magnet oryx:cx=\\\"50\\\" oryx:cy=\\\"79\\\" oryx:anchors=\\\"bottom\\\" /> <oryx:magnet oryx:cx=\\\"75\\\" oryx:cy=\\\"79\\\" oryx:anchors=\\\"bottom\\\" /> <oryx:magnet oryx:cx=\\\"99\\\" oryx:cy=\\\"20\\\" oryx:anchors=\\\"right\\\" /> <oryx:magnet oryx:cx=\\\"99\\\" oryx:cy=\\\"40\\\" oryx:anchors=\\\"right\\\" /> <oryx:magnet oryx:cx=\\\"99\\\" oryx:cy=\\\"60\\\" oryx:anchors=\\\"right\\\" /> <oryx:magnet oryx:cx=\\\"25\\\" oryx:cy=\\\"1\\\" oryx:anchors=\\\"top\\\" /> <oryx:magnet oryx:cx=\\\"50\\\" oryx:cy=\\\"1\\\" oryx:anchors=\\\"top\\\" /> <oryx:magnet oryx:cx=\\\"75\\\" oryx:cy=\\\"1\\\" oryx:anchors=\\\"top\\\" /> <oryx:magnet oryx:cx=\\\"50\\\" oryx:cy=\\\"40\\\" oryx:default=\\\"yes\\\" /> </oryx:magnets> <g pointer-events=\\\"fill\\\" oryx:minimumSize=\\\"50 40\\\"> <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\\\" /> <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\\\" /> <text font-size=\\\"12\\\" id=\\\"text_name\\\" x=\\\"50\\\" y=\\\"40\\\" oryx:align=\\\"middle center\\\" oryx:fittoelem=\\\"text_frame\\\" stroke=\\\"#373e48\\\"></text><g id=\\\"userTask\\\" transform=\\\"translate(3,3)\\\"><path oryx:anchors=\\\"top left\\\" style=\\\"fill:#d1b575;stroke:none;\\\" 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\\\" /></g><g id=\\\"required\\\" display=\\\"inherit\\\" stroke=\\\"#000000\\\"><g oryx:anchors=\\\"bottom\\\"><path fill=\\\"none\\\" oryx:anchors=\\\"bottom\\\" d=\\\"M49 67 L49 74 M49 76 L49 78\\\" transform=\\\"translate(-11,0)\\\"></path></g></g><g id=\\\"repetition\\\" oryx:anchors=\\\"bottom\\\"><path oryx:anchors=\\\"bottom\\\" fill=\\\"none\\\" stroke=\\\"#bbbbbb\\\" stroke-width=\\\"2\\\" d=\\\"M47 68 v10 M50 68 v10 M53 68 v10\\\" transform=\\\"translate(10,0)\\\"/></g><g id=\\\"manualActivation\\\" display=\\\"inherit\\\" stroke=\\\"#000000\\\" oryx:anchors=\\\"bottom\\\"><path oryx:anchors=\\\"bottom\\\" fill=\\\"none\\\" d=\\\"M45.5 68 L54 73 L45.5 77 L45.5 69z\\\" transform=\\\"translate(-2,0)\\\"></path></g></g></svg>\",\n    \"icon\" : \"activity/humantask.png\",\n    \"groups\" : [ \"Activities\" ],\n    \"propertyPackages\" : [\n      \"overrideidpackage\",\n      \"namepackage\",\n      \"documentationpackage\",\n      \"blockingpackage\",\n      \"usertaskassignmentpackage\",\n      \"formkeydefinitionpackage\",\n      \"formreferencepackage\",\n      \"duedatedefinitionpackage\",\n      \"prioritydefinitionpackage\",\n      \"asyncpackage\",\n      \"requiredrulepackage\",\n      \"repetitionrulepackage\",\n      \"manualactivationrulepackage\",\n      \"completionneutralrulepackage\" ],\n    \"hiddenPropertyPackages\" : [ ],\n    \"roles\" : [ \"Activity\", \"association_start\", \"association_end\", \"ActivitiesMorph\", \"all\" ]\n  }, {\n    \"type\" : \"node\",\n    \"id\" : \"ServiceTask\",\n    \"title\" : \"Service task\",\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\\\" /></g><g id=\\\"required\\\" display=\\\"inherit\\\" stroke=\\\"#000000\\\"><g oryx:anchors=\\\"bottom\\\"><path fill=\\\"none\\\" oryx:anchors=\\\"bottom\\\" d=\\\"M49 67 L49 74 M49 76 L49 78\\\" transform=\\\"translate(-11,0)\\\"></path></g></g><g id=\\\"repetition\\\" oryx:anchors=\\\"bottom\\\"><path oryx:anchors=\\\"bottom\\\" fill=\\\"none\\\" stroke=\\\"#bbbbbb\\\" stroke-width=\\\"2\\\" d=\\\"M47 68 v10 M50 68 v10 M53 68 v10\\\" transform=\\\"translate(10,0)\\\"/></g><g id=\\\"manualActivation\\\" display=\\\"inherit\\\" stroke=\\\"#000000\\\" oryx:anchors=\\\"bottom\\\"><path oryx:anchors=\\\"bottom\\\" fill=\\\"none\\\" d=\\\"M45.5 68 L54 73 L45.5 77 L45.5 69z\\\" transform=\\\"translate(-2,0)\\\"></path></g></g></svg>\",\n    \"icon\" : \"activity/servicetask.png\",\n    \"groups\" : [ \"Activities\" ],\n    \"propertyPackages\" : [\n      \"overrideidpackage\",\n      \"namepackage\",\n      \"documentationpackage\",\n      \"servicetaskclasspackage\",\n      \"servicetaskexpressionpackage\",\n      \"servicetaskdelegateexpressionpackage\",\n      \"servicetaskfieldspackage\",\n      \"servicetaskresultvariablepackage\",\n      \"asyncpackage\",\n      \"requiredrulepackage\",\n      \"repetitionrulepackage\",\n      \"manualactivationrulepackage\",\n      \"completionneutralrulepackage\" ],\n    \"hiddenPropertyPackages\" : [ ],\n    \"roles\" : [ \"Activity\", \"association_start\", \"association_end\", \"ActivitiesMorph\", \"all\" ]\n  },\n    {\n      \"type\": \"node\",\n      \"id\": \"DecisionTask\",\n      \"title\": \"Decision task\",\n      \"description\": \"Task to invoke a DMN decision\",\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=\\\"decisionTask\\\" 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\\\" style=\\\"fill:#72a7d0;stroke:none\\\" /></g><g id=\\\"required\\\" display=\\\"inherit\\\" stroke=\\\"#000000\\\"><g oryx:anchors=\\\"bottom\\\"><path fill=\\\"none\\\" oryx:anchors=\\\"bottom\\\" d=\\\"M49 67 L49 74 M49 76 L49 78\\\" transform=\\\"translate(-11,0)\\\"></path></g></g><g id=\\\"repetition\\\" oryx:anchors=\\\"bottom\\\"><path oryx:anchors=\\\"bottom\\\" fill=\\\"none\\\" stroke=\\\"#bbbbbb\\\" stroke-width=\\\"2\\\" d=\\\"M47 68 v10 M50 68 v10 M53 68 v10\\\" transform=\\\"translate(10,0)\\\"/></g><g id=\\\"manualActivation\\\" display=\\\"inherit\\\" stroke=\\\"#000000\\\" oryx:anchors=\\\"bottom\\\"><path oryx:anchors=\\\"bottom\\\" fill=\\\"none\\\" d=\\\"M45.5 68 L54 73 L45.5 77 L45.5 69z\\\" transform=\\\"translate(-2,0)\\\"></path></g></g></svg>\",\n      \"icon\": \"activity/decisiontask.png\",\n      \"groups\": [\n        \"Activities\"\n      ],\n      \"propertyPackages\": [\n        \"overrideidpackage\",\n        \"namepackage\",\n        \"documentationpackage\",\n        \"decisiontaskdecisiontablereferencepackage\",\n        \"decisiontaskthrowerroronnohitspackage\",\n        \"asyncpackage\",\n        \"requiredrulepackage\",\n        \"repetitionrulepackage\",\n        \"manualactivationrulepackage\",\n        \"completionneutralrulepackage\"\n      ],\n      \"hiddenPropertyPackages\": [],\n      \"roles\": [\n        \"Activity\",\n        \"association_start\",\n        \"association_end\",\n        \"ActivitiesMorph\",\n        \"all\"\n      ]\n    }, {\n      \"type\": \"node\",\n      \"id\": \"HttpTask\",\n      \"title\": \"Http task\",\n      \"description\": \"A HTTP 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 16.704699,5.9229055 q 0.358098,0 0.608767,0.2506681 0.250669,0.250668 0.250669,0.6087677 0,0.3580997 -0.250669,0.6087677 -0.250669,0.2506679 -0.608767,0.2506679 -0.358098,0 -0.608767,-0.2506679 -0.250669,-0.250668 -0.250669,-0.6087677 0,-0.3580997 0.250669,-0.6087677 0.250669,-0.2506681 0.608767,-0.2506681 z m 2.578308,-2.0053502 q -2.229162,0 -3.854034,0.6759125 -1.624871,0.6759067 -3.227361,2.2694472 -0.716197,0.725146 -1.575633,1.7457293 L 7.2329969,8.7876913 Q 7.0897576,8.8055849 7.000233,8.9309334 L 4.9948821,12.368677 q -0.035811,0.06267 -0.035811,0.143242 0,0.107426 0.080572,0.205905 l 0.5729577,0.572957 q 0.125334,0.116384 0.2864786,0.07162 l 2.4708789,-0.760963 2.5156417,2.515645 -0.76096,2.470876 q -0.009,0.02687 -0.009,0.08057 0,0.125338 0.08058,0.205905 l 0.572957,0.572958 q 0.170096,0.152194 0.349146,0.04476 l 3.437744,-2.005351 q 0.125335,-0.08953 0.143239,-0.232763 l 0.17905,-3.392986 q 1.02058,-0.859435 1.745729,-1.575629 1.67411,-1.6830612 2.309735,-3.2049805 0.635625,-1.5219191 0.635625,-3.8585111 0,-0.1253369 -0.08505,-0.2148575 -0.08505,-0.089526 -0.201431,-0.089526 z \\\" /></g><g id=\\\"required\\\" display=\\\"inherit\\\" stroke=\\\"#000000\\\"><g oryx:anchors=\\\"bottom\\\"><path fill=\\\"none\\\" oryx:anchors=\\\"bottom\\\" d=\\\"M49 67 L49 74 M49 76 L49 78\\\" transform=\\\"translate(-11,0)\\\"></path></g></g><g id=\\\"repetition\\\" oryx:anchors=\\\"bottom\\\"><path oryx:anchors=\\\"bottom\\\" fill=\\\"none\\\" stroke=\\\"#bbbbbb\\\" stroke-width=\\\"2\\\" d=\\\"M47 68 v10 M50 68 v10 M53 68 v10\\\" transform=\\\"translate(10,0)\\\"/></g><g id=\\\"manualActivation\\\" display=\\\"inherit\\\" stroke=\\\"#000000\\\" oryx:anchors=\\\"bottom\\\"><path oryx:anchors=\\\"bottom\\\" fill=\\\"none\\\" d=\\\"M45.5 68 L54 73 L45.5 77 L45.5 69z\\\" transform=\\\"translate(-2,0)\\\"></path></g></g></svg>\",\n      \"icon\": \"activity/httptask.png\",\n      \"groups\": [\n        \"Activities\"\n      ],\n      \"propertyPackages\": [\n        \"overrideidpackage\",\n        \"namepackage\",\n        \"documentationpackage\",\n        \"servicetaskclasspackage\",\n        \"asyncpackage\",\n        \"requiredrulepackage\",\n        \"repetitionrulepackage\",\n        \"manualactivationrulepackage\",\n        \"completionneutralrulepackage\",\n        \"httptaskrequestmethodpackage\",\n        \"httptaskrequesturlpackage\",\n        \"httptaskrequestheaderspackage\",\n        \"httptaskrequestbodypackage\",\n        \"httptaskrequesttimeoutpackage\",\n        \"httptaskdisallowredirectspackage\",\n        \"httptaskfailstatuscodespackage\",\n        \"httptaskhandlestatuscodespackage\",\n        \"httptaskignoreexceptionpackage\",\n        \"httptaskresponsevariablenamepackage\",\n        \"httptasksaverequestvariablespackage\",\n        \"httptasksaveresponseparameterspackage\",\n        \"httptaskresultvariableprefixpackage\",\n        \"httptasksaveresponseparameterstransientpackage\",\n        \"httptasksaveresponseasjsonpackage\"\n      ],\n      \"hiddenPropertyPackages\": [],\n      \"roles\": [\n        \"Activity\",\n        \"sequence_start\",\n        \"sequence_end\",\n        \"ActivitiesMorph\",\n        \"all\"\n      ]\n    }, {\n      \"type\" : \"node\",\n      \"id\" : \"ScriptTask\",\n      \"title\" : \"Script task\",\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><g id=\\\"required\\\" display=\\\"inherit\\\" stroke=\\\"#000000\\\"><g oryx:anchors=\\\"bottom\\\"><path fill=\\\"none\\\" oryx:anchors=\\\"bottom\\\" d=\\\"M49 67 L49 74 M49 76 L49 78\\\" transform=\\\"translate(-11,0)\\\"></path></g></g><g id=\\\"repetition\\\" oryx:anchors=\\\"bottom\\\"><path oryx:anchors=\\\"bottom\\\" fill=\\\"none\\\" stroke=\\\"#bbbbbb\\\" stroke-width=\\\"2\\\" d=\\\"M47 68 v10 M50 68 v10 M53 68 v10\\\" transform=\\\"translate(10,0)\\\"/></g><g id=\\\"manualActivation\\\" display=\\\"inherit\\\" stroke=\\\"#000000\\\" oryx:anchors=\\\"bottom\\\"><path oryx:anchors=\\\"bottom\\\" fill=\\\"none\\\" d=\\\"M45.5 68 L54 73 L45.5 77 L45.5 69z\\\" transform=\\\"translate(-2,0)\\\"></path></g></g></svg>\",\n      \"icon\" : \"activity/scripttask.png\",\n      \"groups\" : [ \"Activities\" ],\n      \"propertyPackages\" : [  \n        \"overrideidpackage\",\n        \"namepackage\",\n        \"documentationpackage\",\n        \"servicetaskclasspackage\",\n        \"asyncpackage\",\n        \"requiredrulepackage\",\n        \"repetitionrulepackage\",\n        \"manualactivationrulepackage\",\n        \"completionneutralrulepackage\",\n        \"scriptformatpackage\", \n        \"scripttextpackage\",\n        \"servicetaskresultvariablepackage\"\n      ],\n      \"hiddenPropertyPackages\" : [ ],\n      \"roles\" : [ \"Activity\", \"association_start\", \"association_end\", \"ActivitiesMorph\", \"all\" ]\n    }, {\n    \"type\" : \"node\",\n    \"id\" : \"Milestone\",\n    \"title\" : \"Milestone\",\n    \"description\" : \"A milestone\",\n    \"view\" : \"<?xml version=\\\"1.0\\\" encoding=\\\"UTF-8\\\" standalone=\\\"no\\\"?> <svg xmlns=\\\"http://www.w3.org/2000/svg\\\" xmlns:oryx=\\\"http://www.b3mn.org/oryx\\\" width=\\\"146\\\" height=\\\"54\\\" version=\\\"1.0\\\"> <oryx:magnets> <oryx:magnet oryx:cx=\\\"1\\\" oryx:cy=\\\"27\\\" oryx:anchors=\\\"left\\\" /> <oryx:magnet oryx:cx=\\\"36\\\" oryx:cy=\\\"53\\\" oryx:anchors=\\\"bottom\\\" /> <oryx:magnet oryx:cx=\\\"72\\\" oryx:cy=\\\"53\\\" oryx:anchors=\\\"bottom\\\" /> <oryx:magnet oryx:cx=\\\"108\\\" oryx:cy=\\\"53\\\" oryx:anchors=\\\"bottom\\\" /> <oryx:magnet oryx:cx=\\\"145\\\" oryx:cy=\\\"27\\\" oryx:anchors=\\\"right\\\" /> <oryx:magnet oryx:cx=\\\"36\\\" oryx:cy=\\\"1\\\" oryx:anchors=\\\"top\\\" /> <oryx:magnet oryx:cx=\\\"72\\\" oryx:cy=\\\"1\\\" oryx:anchors=\\\"top\\\" /> <oryx:magnet oryx:cx=\\\"108\\\" oryx:cy=\\\"1\\\" oryx:anchors=\\\"top\\\" /> <oryx:magnet oryx:cx=\\\"72\\\" oryx:cy=\\\"27\\\" oryx:default=\\\"yes\\\" /> </oryx:magnets> <g pointer-events=\\\"fill\\\" oryx:minimumSize=\\\"146 54\\\" oryx:maximumSize=\\\"400 54\\\"> <rect id=\\\"mileStone\\\" oryx:resize=\\\"horizontal\\\" x=\\\"0\\\" y=\\\"0\\\" width=\\\"146\\\" height=\\\"54\\\" rx=\\\"24\\\" ry=\\\"30\\\" stroke=\\\"black\\\" fill=\\\"#ffffff\\\"/> <text font-size=\\\"12\\\" id=\\\"text_name\\\" x=\\\"73\\\" y=\\\"26\\\" oryx:align=\\\"middle center\\\" oryx:fittoelem=\\\"mileStone\\\" stroke=\\\"black\\\"> </text> <g id=\\\"required\\\" stroke=\\\"#000000\\\"> <path d=\\\"M68 40 L68 47 M68 49 L68 51 \\\" fill=\\\"none\\\" oryx:anchors=\\\"bottom\\\"/> </g> <g id=\\\"repetition\\\" oryx:anchors=\\\"bottom\\\"><path oryx:anchors=\\\"bottom\\\" fill=\\\"none\\\" stroke=\\\"#bbbbbb\\\" stroke-width=\\\"2\\\" d=\\\"M64 40 v11 M67 40 v11 M70 40 v11\\\" transform=\\\"translate(13,0)\\\"/></g></g> </svg>\",\n    \"icon\" : \"activity/milestone.png\",\n    \"groups\" : [ \"Activities\" ],\n    \"propertyPackages\" : [\n      \"overrideidpackage\",\n      \"namepackage\",\n      \"documentationpackage\",\n      \"requiredrulepackage\",\n      \"repetitionrulepackage\",\n      \"completionneutralrulepackage\" ],\n    \"hiddenPropertyPackages\" : [ ],\n    \"roles\" : [ \"Activity\", \"association_start\", \"association_end\", \"ActivitiesMorph\", \"all\" ]\n  }, {\n    \"type\" : \"node\",\n    \"id\" : \"CaseTask\",\n    \"title\" : \"Case task\",\n    \"description\" : \"A reference to a case definition to start a new instance\",\n    \"view\" : \"<?xml version=\\\"1.0\\\" encoding=\\\"UTF-8\\\" standalone=\\\"no\\\"?> <svg xmlns=\\\"http://www.w3.org/2000/svg\\\" xmlns:svg=\\\"http://www.w3.org/2000/svg\\\" xmlns:oryx=\\\"http://www.b3mn.org/oryx\\\" xmlns:xlink=\\\"http://www.w3.org/1999/xlink\\\" width=\\\"102\\\" height=\\\"82\\\" version=\\\"1.0\\\"> <defs></defs> <oryx:magnets> <oryx:magnet oryx:cx=\\\"1\\\" oryx:cy=\\\"20\\\" oryx:anchors=\\\"left\\\" /> <oryx:magnet oryx:cx=\\\"1\\\" oryx:cy=\\\"40\\\" oryx:anchors=\\\"left\\\" /> <oryx:magnet oryx:cx=\\\"1\\\" oryx:cy=\\\"60\\\" oryx:anchors=\\\"left\\\" /> <oryx:magnet oryx:cx=\\\"25\\\" oryx:cy=\\\"79\\\" oryx:anchors=\\\"bottom\\\" /> <oryx:magnet oryx:cx=\\\"50\\\" oryx:cy=\\\"79\\\" oryx:anchors=\\\"bottom\\\" /> <oryx:magnet oryx:cx=\\\"75\\\" oryx:cy=\\\"79\\\" oryx:anchors=\\\"bottom\\\" /> <oryx:magnet oryx:cx=\\\"99\\\" oryx:cy=\\\"20\\\" oryx:anchors=\\\"right\\\" /> <oryx:magnet oryx:cx=\\\"99\\\" oryx:cy=\\\"40\\\" oryx:anchors=\\\"right\\\" /> <oryx:magnet oryx:cx=\\\"99\\\" oryx:cy=\\\"60\\\" oryx:anchors=\\\"right\\\" /> <oryx:magnet oryx:cx=\\\"25\\\" oryx:cy=\\\"1\\\" oryx:anchors=\\\"top\\\" /> <oryx:magnet oryx:cx=\\\"50\\\" oryx:cy=\\\"1\\\" oryx:anchors=\\\"top\\\" /> <oryx:magnet oryx:cx=\\\"75\\\" oryx:cy=\\\"1\\\" oryx:anchors=\\\"top\\\" /> <oryx:magnet oryx:cx=\\\"50\\\" oryx:cy=\\\"40\\\" oryx:default=\\\"yes\\\" /> </oryx:magnets> <g pointer-events=\\\"fill\\\" oryx:minimumSize=\\\"50 40\\\"> <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\\\" /> <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\\\" /> <text font-size=\\\"12\\\" id=\\\"text_name\\\" x=\\\"50\\\" y=\\\"40\\\" oryx:align=\\\"middle center\\\" oryx:fittoelem=\\\"text_frame\\\" stroke=\\\"#373e48\\\"> </text> <g id=\\\"caseTask\\\" transform=\\\"scale(0.7,0.7) translate(8,8)\\\"> <path oryx:anchors=\\\"top left\\\" style=\\\"opacity:1;fill:#000000;stroke:#000000\\\" d=\\\"M5 4 L9 0 L18 0 L 21 3z\\\"/> <path oryx:anchors=\\\"top left\\\" style=\\\"opacity:1;fill:#F4F6F7;stroke:#000000\\\" d=\\\"M1 23 L1 4 L30 4 L30 23z\\\"/> </g> <g id=\\\"required\\\" display=\\\"inherit\\\" stroke=\\\"#000000\\\"><g oryx:anchors=\\\"bottom\\\"><path fill=\\\"none\\\" oryx:anchors=\\\"bottom\\\" d=\\\"M49 67 L49 74 M49 76 L49 78\\\" transform=\\\"translate(-11,0)\\\"></path></g></g> <g id=\\\"repetition\\\" oryx:anchors=\\\"bottom\\\"><path oryx:anchors=\\\"bottom\\\" fill=\\\"none\\\" stroke=\\\"#bbbbbb\\\" stroke-width=\\\"2\\\" d=\\\"M47 68 v10 M50 68 v10 M53 68 v10\\\" transform=\\\"translate(10,0)\\\"/></g><g id=\\\"manualActivation\\\" display=\\\"inherit\\\" stroke=\\\"#000000\\\" oryx:anchors=\\\"bottom\\\"><path oryx:anchors=\\\"bottom\\\" fill=\\\"none\\\" d=\\\"M45.5 68 L54 73 L45.5 77 L45.5 69z\\\" transform=\\\"translate(-2,0)\\\"></path></g></g></svg>\",\n    \"icon\" : \"activity/casetask.png\",\n    \"groups\" : [ \"Activities\" ],\n    \"propertyPackages\" : [\n      \"overrideidpackage\",\n      \"namepackage\",\n      \"documentationpackage\",\n      \"blockingpackage\",\n      \"casetaskcasereferencepackage\",\n      \"asyncpackage\",\n      \"requiredrulepackage\",\n      \"repetitionrulepackage\",\n      \"manualactivationrulepackage\",\n      \"completionneutralrulepackage\"],\n    \"hiddenPropertyPackages\" : [ ],\n    \"roles\" : [ \"Activity\", \"association_start\", \"association_end\", \"ActivitiesMorph\", \"all\" ]\n  }, {\n    \"type\" : \"node\",\n    \"id\" : \"ProcessTask\",\n    \"title\" : \"Process task\",\n    \"description\" : \"A reference to a process definition to start a new instance\",\n    \"view\" : \"<?xml version=\\\"1.0\\\" encoding=\\\"UTF-8\\\" standalone=\\\"no\\\"?> <svg xmlns=\\\"http://www.w3.org/2000/svg\\\" xmlns:svg=\\\"http://www.w3.org/2000/svg\\\" xmlns:oryx=\\\"http://www.b3mn.org/oryx\\\" xmlns:xlink=\\\"http://www.w3.org/1999/xlink\\\" width=\\\"102\\\" height=\\\"82\\\" version=\\\"1.0\\\"> <defs></defs> <oryx:magnets> <oryx:magnet oryx:cx=\\\"1\\\" oryx:cy=\\\"20\\\" oryx:anchors=\\\"left\\\" /> <oryx:magnet oryx:cx=\\\"1\\\" oryx:cy=\\\"40\\\" oryx:anchors=\\\"left\\\" /> <oryx:magnet oryx:cx=\\\"1\\\" oryx:cy=\\\"60\\\" oryx:anchors=\\\"left\\\" /> <oryx:magnet oryx:cx=\\\"25\\\" oryx:cy=\\\"79\\\" oryx:anchors=\\\"bottom\\\" /> <oryx:magnet oryx:cx=\\\"50\\\" oryx:cy=\\\"79\\\" oryx:anchors=\\\"bottom\\\" /> <oryx:magnet oryx:cx=\\\"75\\\" oryx:cy=\\\"79\\\" oryx:anchors=\\\"bottom\\\" /> <oryx:magnet oryx:cx=\\\"99\\\" oryx:cy=\\\"20\\\" oryx:anchors=\\\"right\\\" /> <oryx:magnet oryx:cx=\\\"99\\\" oryx:cy=\\\"40\\\" oryx:anchors=\\\"right\\\" /> <oryx:magnet oryx:cx=\\\"99\\\" oryx:cy=\\\"60\\\" oryx:anchors=\\\"right\\\" /> <oryx:magnet oryx:cx=\\\"25\\\" oryx:cy=\\\"1\\\" oryx:anchors=\\\"top\\\" /> <oryx:magnet oryx:cx=\\\"50\\\" oryx:cy=\\\"1\\\" oryx:anchors=\\\"top\\\" /> <oryx:magnet oryx:cx=\\\"75\\\" oryx:cy=\\\"1\\\" oryx:anchors=\\\"top\\\" /> <oryx:magnet oryx:cx=\\\"50\\\" oryx:cy=\\\"40\\\" oryx:default=\\\"yes\\\" /> </oryx:magnets> <g pointer-events=\\\"fill\\\" oryx:minimumSize=\\\"50 40\\\"> <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\\\" /> <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\\\" /> <text font-size=\\\"12\\\" id=\\\"text_name\\\" x=\\\"50\\\" y=\\\"40\\\" oryx:align=\\\"middle center\\\" oryx:fittoelem=\\\"text_frame\\\" stroke=\\\"#373e48\\\"> </text> <g id=\\\"processTask\\\" transform=\\\"scale(0.7,0.7) translate(8,8)\\\"> <path oryx:anchors=\\\"top left\\\" style=\\\"opacity:1;fill:#F4F6F7;stroke:#000000\\\" d=\\\"M1 23 L7 11 L1 0 L30 0 L 35 11 L 30 23z\\\"/> </g> <g id=\\\"required\\\" display=\\\"inherit\\\" stroke=\\\"#000000\\\"><g oryx:anchors=\\\"bottom\\\"><path fill=\\\"none\\\" oryx:anchors=\\\"bottom\\\" d=\\\"M49 67 L49 74 M49 76 L49 78\\\" transform=\\\"translate(-11,0)\\\"></path></g></g> <g id=\\\"repetition\\\" oryx:anchors=\\\"bottom\\\"><path oryx:anchors=\\\"bottom\\\" fill=\\\"none\\\" stroke=\\\"#bbbbbb\\\" stroke-width=\\\"2\\\" d=\\\"M47 68 v10 M50 68 v10 M53 68 v10\\\" transform=\\\"translate(10,0)\\\"/></g><g id=\\\"manualActivation\\\" display=\\\"inherit\\\" stroke=\\\"#000000\\\" oryx:anchors=\\\"bottom\\\"><path oryx:anchors=\\\"bottom\\\" fill=\\\"none\\\" d=\\\"M45.5 68 L54 73 L45.5 77 L45.5 69z\\\" transform=\\\"translate(-2,0)\\\"></path></g></g></svg>\",\n    \"icon\" : \"activity/processtask.png\",\n    \"groups\" : [ \"Activities\" ],\n    \"propertyPackages\" : [\n      \"overrideidpackage\",\n      \"namepackage\",\n      \"documentationpackage\",\n      \"blockingpackage\",\n      \"processtaskprocessreferencepackage\",\n      \"asyncpackage\",\n      \"requiredrulepackage\",\n      \"repetitionrulepackage\",\n      \"manualactivationrulepackage\",\n      \"completionneutralrulepackage\"],\n    \"hiddenPropertyPackages\" : [ ],\n    \"roles\" : [ \"Activity\", \"association_start\", \"association_end\", \"ActivitiesMorph\", \"all\" ]\n  }, {\n    \"type\" : \"node\",\n    \"id\" : \"TimerEventListener\",\n    \"title\" : \"Timer event listener\",\n    \"description\" : \"An eventlistener 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\" : \"activity/timereventlistener.png\",\n    \"groups\" : [ \"Event Listeners\" ],\n    \"propertyPackages\" : [\n      \"overrideidpackage\",\n      \"namepackage\",\n      \"documentationpackage\",\n      \"timerexpressionpackage\",\n      \"timerstarttriggerpackage\",\n      \"completionneutralrulepackage\"],\n    \"hiddenPropertyPackages\" : [ ],\n    \"roles\" : [ \"Activity\", \"association_start\", \"association_end\", \"ActivitiesMorph\", \"all\" ]\n  }, {\n      \"type\" : \"node\",\n      \"id\" : \"UserEventListener\",\n      \"title\" : \"User event listener\",\n      \"description\" : \"An listener for user events\",\n      \"view\" : \"<?xml version=\\\"1.0\\\" encoding=\\\"UTF-8\\\" standalone=\\\"no\\\"?><svg xmlns=\\\"http://www.w3.org/2000/svg\\\" xmlns:oryx=\\\"http://www.b3mn.org/oryx\\\" width=\\\"40\\\" height=\\\"40\\\" version=\\\"1.0\\\"> <defs></defs> <oryx:magnets> <oryx:magnet oryx:cx=\\\"16\\\" oryx:cy=\\\"16\\\" oryx:default=\\\"yes\\\" /> </oryx:magnets> <oryx:docker oryx:cx=\\\"16\\\" oryx:cy=\\\"16\\\" /> <g pointer-events=\\\"fill\\\"> <defs> <radialGradient id=\\\"background\\\" cx=\\\"10%\\\" cy=\\\"10%\\\" r=\\\"100%\\\" fx=\\\"10%\\\" fy=\\\"10%\\\"> <stop offset=\\\"0%\\\" stop-color=\\\"#ffffff\\\" stop-opacity=\\\"1\\\"/> <stop id=\\\"fill_el\\\" offset=\\\"100%\\\" stop-color=\\\"#ffffff\\\" stop-opacity=\\\"1\\\"/> </radialGradient> </defs> <circle id=\\\"bg_frame\\\" cx=\\\"16\\\" cy=\\\"16\\\" r=\\\"15\\\" stroke=\\\"black\\\" fill=\\\"url(#background) white\\\" stroke-width=\\\"1\\\"/> <circle id=\\\"frame\\\" cx=\\\"16\\\" cy=\\\"16\\\" r=\\\"12\\\" stroke=\\\"black\\\" fill=\\\"none\\\" stroke-width=\\\"1\\\"/> <g id=\\\"humanTaskBlock\\\" transform=\\\"scale(0.8,0.8) translate(7.5,7)\\\" display=\\\"inherit\\\"> <path oryx:anchors=\\\"top left\\\" style=\\\"opacity:1;fill:#F4F6F7\\\" d=\\\"M0.585,24.167h24.083v-7.833c0,0-2.333-3.917-7.083-5.167h-9.25 c-4.417,1.333-7.833,5.75-7.833,5.75L0.585,24.167z\\\"/> <path oryx:anchors=\\\"top left\\\" style=\\\"opacity:1;fill:none\\\" d=\\\"M 6 20 L 6 24\\\" /> <path oryx:anchors=\\\"top left\\\" style=\\\"opacity:1;fill:none\\\" d=\\\"M 20 20 L 20 24\\\" /> <circle oryx:anchors=\\\"top left\\\" fill=\\\"#000000\\\" cx=\\\"13.002\\\" cy=\\\"5.916\\\" r=\\\"5.417\\\"/> <path oryx:anchors=\\\"top left\\\" style=\\\"opacity:1;fill:#F0EFF0\\\" d=\\\"M8.043,7.083c0,0,2.814-2.426,5.376-1.807s4.624-0.693,4.624-0.693 c0.25,1.688,0.042,3.75-1.458,5.584c0,0,1.083,0.75,1.083,1.5s0.125,1.875-1,3s-5.5,1.25-6.75,0S8.668,12.834,8.668,12 s0.583-1.25,1.25-1.917C8.835,9.5,7.419,7.708,8.043,7.083z\\\"/> </g> <text font-size=\\\"11\\\" id=\\\"text_name\\\" x=\\\"16\\\" y=\\\"33\\\" oryx:align=\\\"top center\\\" stroke=\\\"black\\\" ></text> </g></svg>\",\n      \"icon\" : \"event/userlistener.png\",\n      \"groups\" : [ \"Event Listeners\" ],\n      \"propertyPackages\" : [\n        \"overrideidpackage\",\n        \"namepackage\",\n        \"documentationpackage\",\n        \"completionneutralrulepackage\"],\n      \"hiddenPropertyPackages\" : [ ],\n      \"roles\" : [ \"Activity\", \"association_start\", \"association_end\", \"ActivitiesMorph\", \"all\" ]\n  }, {\n    \"type\" : \"node\",\n    \"id\" : \"EntryCriterion\",\n    \"title\" : \"Entry criterion\",\n    \"description\" : \"A sentry that defines an entry criterion\",\n    \"view\" : \"<?xml version=\\\"1.0\\\" encoding=\\\"utf-8\\\" standalone=\\\"no\\\" ?><svg xmlns=\\\"http://www.w3.org/2000/svg\\\" xmlns:svg=\\\"http://www.w3.org/2000/svg\\\" xmlns:oryx=\\\"http://www.b3mn.org/oryx\\\" xmlns:xlink=\\\"http://www.w3.org/1999/xlink\\\" width=\\\"14\\\"  height=\\\"22\\\" version=\\\"1.0\\\"> <oryx:magnets><oryx:magnet oryx:cx=\\\"8\\\" oryx:cy=\\\"10\\\" oryx:default=\\\"yes\\\" /></oryx:magnets><oryx:docker oryx:cx=\\\"16\\\" oryx:cy=\\\"16\\\" /><g pointer-events=\\\"fill\\\"><defs><radialGradient id=\\\"background\\\" cx=\\\"10%\\\" cy=\\\"10%\\\" r=\\\"100%\\\" fx=\\\"10%\\\" fy=\\\"10%\\\"><stop offset=\\\"0%\\\" stop-color=\\\"#ffffff\\\" stop-opacity=\\\"1\\\"/><stop id=\\\"fill_el\\\" offset=\\\"100%\\\" stop-color=\\\"#ffffff\\\" stop-opacity=\\\"1\\\"/></radialGradient></defs><polygon id=\\\"bg_frame\\\" points=\\\"7 0  14 11  7 22 0 11\\\" fill=\\\"url(#background) #ffffff\\\" stroke=\\\"#000000\\\"/></g></svg>\",\n    \"icon\" : \"sentry/entry.png\",\n    \"groups\" : [ \"Sentries\" ],\n    \"propertyPackages\" : [\n      \"overrideidpackage\",\n      \"namepackage\",\n      \"documentationpackage\",\n      \"ifpartconditionpackage\" ],\n    \"hiddenPropertyPackages\" : [ ],\n    \"roles\" : [ \"association_start\", \"association_end\", \"SentriesMorph\", \"EntryCriterionOnItemBoundary\" ]\n  }, {\n    \"type\" : \"node\",\n    \"id\" : \"ExitCriterion\",\n    \"title\" : \"Exit criterion\",\n    \"description\" : \"A sentry that defines an exit criterion\",\n    \"view\" : \"<?xml version=\\\"1.0\\\" encoding=\\\"utf-8\\\" standalone=\\\"no\\\" ?><svg xmlns=\\\"http://www.w3.org/2000/svg\\\" xmlns:svg=\\\"http://www.w3.org/2000/svg\\\" xmlns:oryx=\\\"http://www.b3mn.org/oryx\\\" xmlns:xlink=\\\"http://www.w3.org/1999/xlink\\\" width=\\\"14\\\"  height=\\\"22\\\" version=\\\"1.0\\\"> <oryx:magnets><oryx:magnet oryx:cx=\\\"8\\\" oryx:cy=\\\"10\\\" oryx:default=\\\"yes\\\" /></oryx:magnets><oryx:docker oryx:cx=\\\"16\\\" oryx:cy=\\\"16\\\" /><g pointer-events=\\\"fill\\\"><defs><radialGradient id=\\\"background\\\" cx=\\\"10%\\\" cy=\\\"10%\\\" r=\\\"100%\\\" fx=\\\"10%\\\" fy=\\\"10%\\\"><stop offset=\\\"0%\\\" stop-color=\\\"#ffffff\\\" stop-opacity=\\\"1\\\"/><stop id=\\\"fill_el\\\" offset=\\\"100%\\\" stop-color=\\\"#000000\\\" stop-opacity=\\\"1\\\"/></radialGradient></defs><polygon id=\\\"bg_frame\\\" points=\\\"7 0  14 11  7 22 0 11\\\" fill=\\\"url(#background) #000000\\\" /></g></svg>\",\n    \"icon\" : \"sentry/exit.png\",\n    \"groups\" : [ \"Sentries\" ],\n    \"propertyPackages\" : [\n      \"overrideidpackage\",\n      \"namepackage\",\n      \"documentationpackage\",\n      \"ifpartconditionpackage\" ],\n    \"hiddenPropertyPackages\" : [ ],\n    \"roles\" : [ \"association_start\", \"SentriesMorph\", \"ExitCriterionOnItemBoundary\" ]\n  }, {\n    \"type\" : \"edge\",\n    \"id\" : \"Association\",\n    \"title\" : \"Association\",\n    \"description\" : \"Associates a sentry with a plan item.\",\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\" : \"connection/connector.png\",\n    \"groups\" : [ \"Connectors\" ],\n    \"layout\" : [ {\n      \"type\" : \"layout.bpmn2_0.sequenceflow\"\n    } ],\n    \"propertyPackages\" : [\n      \"overrideidpackage\",\n      \"namepackage\",\n      \"documentationpackage\",\n      \"transitioneventpackage\" ],\n    \"hiddenPropertyPackages\" : [ ],\n    \"roles\" : [ \"ConnectingObjectsMorph\", \"all\" ]\n  }],\n  \"rules\" : {\n    \"cardinalityRules\" : [ {\n      \"role\" : \"Startevents_all\",\n      \"incomingEdges\" : [ {\n        \"role\" : \"Association\",\n        \"maximum\" : 0\n      } ]\n    }, {\n      \"role\" : \"Endevents_all\",\n      \"outgoingEdges\" : [ {\n        \"role\" : \"Association\",\n        \"maximum\" : 0\n      } ]\n    }],\n    \"connectionRules\" : [ {\n      \"role\" : \"Association\",\n      \"connects\" : [ {\n        \"from\" : \"association_start\",\n        \"to\" : [ \"association_end\" ]\n      }]\n    }, {\n      \"role\" : \"EntryCriterionOnItemBoundary\",\n      \"connects\" : [ {\n        \"from\" : \"Activity\",\n        \"to\" : [ \"EntryCriterionOnItemBoundary\"]\n      }, {\n        \"from\" : \"StageActivity\",\n        \"to\" : [ \"EntryCriterionOnItemBoundary\"]\n      }]\n    }, {\n        \"role\" : \"ExitCriterionOnItemBoundary\",\n        \"connects\" : [ {\n          \"from\" : \"Activity\",\n          \"to\" : [ \"ExitCriterionOnItemBoundary\" ]\n        }, {\n          \"from\" : \"StageActivity\",\n          \"to\" : [ \"ExitCriterionOnItemBoundary\"]\n        }, {\n          \"from\" : \"StageModelActivity\",\n          \"to\" : [ \"ExitCriterionOnItemBoundary\"]\n        }\n      ]}\n    ],\n    \"containmentRules\" : [ {\n      \"role\" : \"CaseDiagram\",\n      \"contains\" : [ \"CasePlanModel\", \"ExitCriterion\" ]\n    }, {\n      \"role\" : \"CasePlanModel\",\n      \"contains\" : [ \"all\" ]\n    }, {\n      \"role\" : \"Stage\",\n      \"contains\" : [ \"all\" ]\n    }],\n    \"morphingRules\" : [ {\n      \"role\" : \"ActivitiesMorph\",\n      \"baseMorphs\" : [ \"CaseTask\" ],\n      \"preserveBounds\" : true\n    }, {\n      \"role\" : \"SentriesMorph\",\n      \"baseMorphs\" : [ \"EntryCriterion\" ],\n      \"preserveBounds\" : true\n    }]\n  }\n}\n"
  },
  {
    "path": "flowable-ui-web/admin/additional_components/angular-ui-select2/angular-ui-select2.js",
    "content": "/**\n * Enhanced Select2 Dropmenus\n *\n * @AJAX Mode - When in this mode, your value will be an object (or array of objects) of the data used by Select2\n *     This change is so that you do not have to do an additional query yourself on top of Select2's own query\n * @params [options] {object} The configuration options passed to $.fn.select2(). Refer to the documentation\n */\nangular.module('ui.select2', []).value('uiSelect2Config', {}).directive('uiSelect2', ['uiSelect2Config', '$timeout', function (uiSelect2Config, $timeout) {\n  var options = {};\n  if (uiSelect2Config) {\n    angular.extend(options, uiSelect2Config);\n  }\n  return {\n    require: 'ngModel',\n    priority: 1,\n    compile: function (tElm, tAttrs) {\n      var watch,\n        repeatOption,\n        repeatAttr,\n        isSelect = tElm.is('select'),\n        isMultiple = angular.isDefined(tAttrs.multiple);\n\n      // Enable watching of the options dataset if in use\n      if (tElm.is('select')) {\n        repeatOption = tElm.find('option[ng-repeat], option[data-ng-repeat]');\n\n        if (repeatOption.length) {\n          repeatAttr = repeatOption.attr('ng-repeat') || repeatOption.attr('data-ng-repeat');\n          watch = jQuery.trim(repeatAttr.split('|')[0]).split(' ').pop();\n        }\n      }\n\n      return function (scope, elm, attrs, controller) {\n        // instance-specific options\n        var opts = angular.extend({}, options, scope.$eval(attrs.uiSelect2));\n\n        /*\n        Convert from Select2 view-model to Angular view-model.\n        */\n        var convertToAngularModel = function(select2_data) {\n          var model;\n          if (opts.simple_tags) {\n            model = [];\n            angular.forEach(select2_data, function(value, index) {\n              model.push(value.id);\n            });\n          } else {\n            model = select2_data;\n          }\n          return model;\n        };\n\n        /*\n        Convert from Angular view-model to Select2 view-model.\n        */\n        var convertToSelect2Model = function(angular_data) {\n          var model = [];\n          if (!angular_data) {\n            return model;\n          }\n\n          if (opts.simple_tags) {\n            model = [];\n            angular.forEach(\n              angular_data,\n              function(value, index) {\n                model.push({'id': value, 'text': value});\n              });\n          } else {\n            model = angular_data;\n          }\n          return model;\n        };\n\n        if (isSelect) {\n          // Use <select multiple> instead\n          delete opts.multiple;\n          delete opts.initSelection;\n        } else if (isMultiple) {\n          opts.multiple = true;\n        }\n\n        if (controller) {\n          // Watch the model for programmatic changes\n           scope.$watch(tAttrs.ngModel, function(current, old) {\n            if (!current) {\n              return;\n            }\n            if (current === old) {\n              return;\n            }\n            controller.$render();\n          }, true);\n          controller.$render = function () {\n            if (isSelect) {\n              elm.select2('val', controller.$viewValue);\n            } else {\n              if (opts.multiple) {\n                var viewValue = controller.$viewValue;\n                if (angular.isString(viewValue)) {\n                  viewValue = viewValue.split(',');\n                }\n                elm.select2(\n                  'data', convertToSelect2Model(viewValue));\n              } else {\n                if (angular.isObject(controller.$viewValue)) {\n                  elm.select2('data', controller.$viewValue);\n                } else if (!controller.$viewValue) {\n                  elm.select2('data', null);\n                } else {\n                  elm.select2('val', controller.$viewValue);\n                }\n              }\n            }\n          };\n\n          // Watch the options dataset for changes\n          if (watch) {\n            scope.$watch(watch, function (newVal, oldVal, scope) {\n              if (angular.equals(newVal, oldVal)) {\n                return;\n              }\n              // Delayed so that the options have time to be rendered\n              $timeout(function () {\n                elm.select2('val', controller.$viewValue);\n                // Refresh angular to remove the superfluous option\n                elm.trigger('change');\n                if(newVal && !oldVal && controller.$setPristine) {\n                  controller.$setPristine(true);\n                }\n              });\n            });\n          }\n\n          // Update valid and dirty statuses\n          controller.$parsers.push(function (value) {\n            var div = elm.prev();\n            div\n              .toggleClass('ng-invalid', !controller.$valid)\n              .toggleClass('ng-valid', controller.$valid)\n              .toggleClass('ng-invalid-required', !controller.$valid)\n              .toggleClass('ng-valid-required', controller.$valid)\n              .toggleClass('ng-dirty', controller.$dirty)\n              .toggleClass('ng-pristine', controller.$pristine);\n            return value;\n          });\n\n          if (!isSelect) {\n            // Set the view and model value and update the angular template manually for the ajax/multiple select2.\n            elm.bind(\"change\", function (e) {\n              e.stopImmediatePropagation();\n              \n              if (scope.$$phase || scope.$root.$$phase) {\n                return;\n              }\n              scope.$apply(function () {\n                controller.$setViewValue(\n                  convertToAngularModel(elm.select2('data')));\n              });\n            });\n\n            if (opts.initSelection) {\n              var initSelection = opts.initSelection;\n              opts.initSelection = function (element, callback) {\n                initSelection(element, function (value) {\n                  controller.$setViewValue(convertToAngularModel(value));\n                  callback(value);\n                });\n              };\n            }\n          }\n        }\n\n        elm.bind(\"$destroy\", function() {\n          elm.select2(\"destroy\");\n        });\n\n        attrs.$observe('disabled', function (value) {\n          elm.select2('enable', !value);\n        });\n\n        attrs.$observe('readonly', function (value) {\n          elm.select2('readonly', !!value);\n        });\n\n        if (attrs.ngMultiple) {\n          scope.$watch(attrs.ngMultiple, function(newVal) {\n            attrs.$set('multiple', !!newVal);\n            elm.select2(opts);\n          });\n        }\n\n        // Initialize the plugin late so that the injected DOM does not disrupt the template compiler\n        $timeout(function () {\n          elm.select2(opts);\n\n          // Set initial value - I'm not sure about this but it seems to need to be there\n          elm.val(controller.$viewValue);\n          // important!\n          controller.$render();\n\n          // Not sure if I should just check for !isSelect OR if I should check for 'tags' key\n          if (!opts.initSelection && !isSelect) {\n            controller.$setViewValue(\n              convertToAngularModel(elm.select2('data'))\n            );\n          }\n        });\n      };\n    }\n  };\n}]);\n"
  },
  {
    "path": "flowable-ui-web/admin/additional_components/angular-ui-select2/select2.css",
    "content": "/*\nVersion: 3.4.5 Timestamp: Mon Nov  4 08:22:42 PST 2013\n*/\n.select2-container {\n    margin: 0;\n    position: relative;\n    display: inline-block;\n    /* inline-block for ie7 */\n    zoom: 1;\n    *display: inline;\n    vertical-align: middle;\n}\n\n.select2-container,\n.select2-drop,\n.select2-search,\n.select2-search input {\n  /*\n    Force border-box so that % widths fit the parent\n    container without overlap because of margin/padding.\n\n    More Info : http://www.quirksmode.org/css/box.html\n  */\n  -webkit-box-sizing: border-box; /* webkit */\n     -moz-box-sizing: border-box; /* firefox */\n          box-sizing: border-box; /* css3 */\n}\n\n.select2-container .select2-choice {\n    display: block;\n    height: 26px;\n    padding: 0 0 0 8px;\n    overflow: hidden;\n    position: relative;\n\n    border: 1px solid #aaa;\n    white-space: nowrap;\n    line-height: 26px;\n    color: #444;\n    text-decoration: none;\n\n    border-radius: 4px;\n\n    background-clip: padding-box;\n\n    -webkit-touch-callout: none;\n      -webkit-user-select: none;\n         -moz-user-select: none;\n          -ms-user-select: none;\n              user-select: none;\n\n    background-color: #fff;\n    background-image: -webkit-gradient(linear, left bottom, left top, color-stop(0, #eee), color-stop(0.5, #fff));\n    background-image: -webkit-linear-gradient(center bottom, #eee 0%, #fff 50%);\n    background-image: -moz-linear-gradient(center bottom, #eee 0%, #fff 50%);\n    filter: progid:DXImageTransform.Microsoft.gradient(startColorstr = '#ffffff', endColorstr = '#eeeeee', GradientType = 0);\n    background-image: linear-gradient(top, #fff 0%, #eee 50%);\n}\n\n.select2-container.select2-drop-above .select2-choice {\n    border-bottom-color: #aaa;\n\n    border-radius: 0 0 4px 4px;\n\n    background-image: -webkit-gradient(linear, left bottom, left top, color-stop(0, #eee), color-stop(0.9, #fff));\n    background-image: -webkit-linear-gradient(center bottom, #eee 0%, #fff 90%);\n    background-image: -moz-linear-gradient(center bottom, #eee 0%, #fff 90%);\n    filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#eeeeee', GradientType=0);\n    background-image: linear-gradient(top, #eee 0%, #fff 90%);\n}\n\n.select2-container.select2-allowclear .select2-choice .select2-chosen {\n    margin-right: 42px;\n}\n\n.select2-container .select2-choice > .select2-chosen {\n    margin-right: 26px;\n    display: block;\n    overflow: hidden;\n\n    white-space: nowrap;\n\n    text-overflow: ellipsis;\n}\n\n.select2-container .select2-choice abbr {\n    display: none;\n    width: 12px;\n    height: 12px;\n    position: absolute;\n    right: 24px;\n    top: 8px;\n\n    font-size: 1px;\n    text-decoration: none;\n\n    border: 0;\n    background: url('select2.png') right top no-repeat;\n    cursor: pointer;\n    outline: 0;\n}\n\n.select2-container.select2-allowclear .select2-choice abbr {\n    display: inline-block;\n}\n\n.select2-container .select2-choice abbr:hover {\n    background-position: right -11px;\n    cursor: pointer;\n}\n\n.select2-drop-mask {\n    border: 0;\n    margin: 0;\n    padding: 0;\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: 9998;\n    /* styles required for IE to work */\n    background-color: #fff;\n    filter: alpha(opacity=0);\n}\n\n.select2-drop {\n    width: 100%;\n    margin-top: -1px;\n    position: absolute;\n    z-index: 9999;\n    top: 100%;\n\n    background: #fff;\n    color: #000;\n    border: 1px solid #aaa;\n    border-top: 0;\n\n    border-radius: 0 0 4px 4px;\n\n    -webkit-box-shadow: 0 4px 5px rgba(0, 0, 0, .15);\n            box-shadow: 0 4px 5px rgba(0, 0, 0, .15);\n}\n\n.select2-drop-auto-width {\n    border-top: 1px solid #aaa;\n    width: auto;\n}\n\n.select2-drop-auto-width .select2-search {\n    padding-top: 4px;\n}\n\n.select2-drop.select2-drop-above {\n    margin-top: 1px;\n    border-top: 1px solid #aaa;\n    border-bottom: 0;\n\n    border-radius: 4px 4px 0 0;\n\n    -webkit-box-shadow: 0 -4px 5px rgba(0, 0, 0, .15);\n            box-shadow: 0 -4px 5px rgba(0, 0, 0, .15);\n}\n\n.select2-drop-active {\n    border: 1px solid #5897fb;\n    border-top: none;\n}\n\n.select2-drop.select2-drop-above.select2-drop-active {\n    border-top: 1px solid #5897fb;\n}\n\n.select2-container .select2-choice .select2-arrow {\n    display: inline-block;\n    width: 18px;\n    height: 100%;\n    position: absolute;\n    right: 0;\n    top: 0;\n\n    border-left: 1px solid #aaa;\n    border-radius: 0 4px 4px 0;\n\n    background-clip: padding-box;\n\n    background: #ccc;\n    background-image: -webkit-gradient(linear, left bottom, left top, color-stop(0, #ccc), color-stop(0.6, #eee));\n    background-image: -webkit-linear-gradient(center bottom, #ccc 0%, #eee 60%);\n    background-image: -moz-linear-gradient(center bottom, #ccc 0%, #eee 60%);\n    filter: progid:DXImageTransform.Microsoft.gradient(startColorstr = '#eeeeee', endColorstr = '#cccccc', GradientType = 0);\n    background-image: linear-gradient(top, #ccc 0%, #eee 60%);\n}\n\n.select2-container .select2-choice .select2-arrow b {\n    display: block;\n    width: 100%;\n    height: 100%;\n    background: url('select2.png') no-repeat 0 1px;\n}\n\n.select2-search {\n    display: inline-block;\n    width: 100%;\n    min-height: 26px;\n    margin: 0;\n    padding-left: 4px;\n    padding-right: 4px;\n\n    position: relative;\n    z-index: 10000;\n\n    white-space: nowrap;\n}\n\n.select2-search input {\n    width: 100%;\n    height: auto !important;\n    min-height: 26px;\n    padding: 4px 20px 4px 5px;\n    margin: 0;\n\n    outline: 0;\n    font-family: sans-serif;\n    font-size: 1em;\n\n    border: 1px solid #aaa;\n    border-radius: 0;\n\n    -webkit-box-shadow: none;\n            box-shadow: none;\n\n    background: #fff url('select2.png') no-repeat 100% -22px;\n    background: url('select2.png') no-repeat 100% -22px, -webkit-gradient(linear, left bottom, left top, color-stop(0.85, #fff), color-stop(0.99, #eee));\n    background: url('select2.png') no-repeat 100% -22px, -webkit-linear-gradient(center bottom, #fff 85%, #eee 99%);\n    background: url('select2.png') no-repeat 100% -22px, -moz-linear-gradient(center bottom, #fff 85%, #eee 99%);\n    background: url('select2.png') no-repeat 100% -22px, linear-gradient(top, #fff 85%, #eee 99%);\n}\n\n.select2-drop.select2-drop-above .select2-search input {\n    margin-top: 4px;\n}\n\n.select2-search input.select2-active {\n    background: #fff url('select2-spinner.gif') no-repeat 100%;\n    background: url('select2-spinner.gif') no-repeat 100%, -webkit-gradient(linear, left bottom, left top, color-stop(0.85, #fff), color-stop(0.99, #eee));\n    background: url('select2-spinner.gif') no-repeat 100%, -webkit-linear-gradient(center bottom, #fff 85%, #eee 99%);\n    background: url('select2-spinner.gif') no-repeat 100%, -moz-linear-gradient(center bottom, #fff 85%, #eee 99%);\n    background: url('select2-spinner.gif') no-repeat 100%, linear-gradient(top, #fff 85%, #eee 99%);\n}\n\n.select2-container-active .select2-choice,\n.select2-container-active .select2-choices {\n    border: 1px solid #5897fb;\n    outline: none;\n\n    -webkit-box-shadow: 0 0 5px rgba(0, 0, 0, .3);\n            box-shadow: 0 0 5px rgba(0, 0, 0, .3);\n}\n\n.select2-dropdown-open .select2-choice {\n    border-bottom-color: transparent;\n    -webkit-box-shadow: 0 1px 0 #fff inset;\n            box-shadow: 0 1px 0 #fff inset;\n\n    border-bottom-left-radius: 0;\n    border-bottom-right-radius: 0;\n\n    background-color: #eee;\n    background-image: -webkit-gradient(linear, left bottom, left top, color-stop(0, #fff), color-stop(0.5, #eee));\n    background-image: -webkit-linear-gradient(center bottom, #fff 0%, #eee 50%);\n    background-image: -moz-linear-gradient(center bottom, #fff 0%, #eee 50%);\n    filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#eeeeee', endColorstr='#ffffff', GradientType=0);\n    background-image: linear-gradient(top, #fff 0%, #eee 50%);\n}\n\n.select2-dropdown-open.select2-drop-above .select2-choice,\n.select2-dropdown-open.select2-drop-above .select2-choices {\n    border: 1px solid #5897fb;\n    border-top-color: transparent;\n\n    background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0, #fff), color-stop(0.5, #eee));\n    background-image: -webkit-linear-gradient(center top, #fff 0%, #eee 50%);\n    background-image: -moz-linear-gradient(center top, #fff 0%, #eee 50%);\n    filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#eeeeee', endColorstr='#ffffff', GradientType=0);\n    background-image: linear-gradient(bottom, #fff 0%, #eee 50%);\n}\n\n.select2-dropdown-open .select2-choice .select2-arrow {\n    background: transparent;\n    border-left: none;\n    filter: none;\n}\n.select2-dropdown-open .select2-choice .select2-arrow b {\n    background-position: -18px 1px;\n}\n\n/* results */\n.select2-results {\n    max-height: 200px;\n    padding: 0 0 0 4px;\n    margin: 4px 4px 4px 0;\n    position: relative;\n    overflow-x: hidden;\n    overflow-y: auto;\n    -webkit-tap-highlight-color: rgba(0, 0, 0, 0);\n}\n\n.select2-results ul.select2-result-sub {\n    margin: 0;\n    padding-left: 0;\n}\n\n.select2-results ul.select2-result-sub > li .select2-result-label { padding-left: 20px }\n.select2-results ul.select2-result-sub ul.select2-result-sub > li .select2-result-label { padding-left: 40px }\n.select2-results ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub > li .select2-result-label { padding-left: 60px }\n.select2-results ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub > li .select2-result-label { padding-left: 80px }\n.select2-results ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub > li .select2-result-label { padding-left: 100px }\n.select2-results ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub > li .select2-result-label { padding-left: 110px }\n.select2-results ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub > li .select2-result-label { padding-left: 120px }\n\n.select2-results li {\n    list-style: none;\n    display: list-item;\n    background-image: none;\n}\n\n.select2-results li.select2-result-with-children > .select2-result-label {\n    font-weight: bold;\n}\n\n.select2-results .select2-result-label {\n    padding: 3px 7px 4px;\n    margin: 0;\n    cursor: pointer;\n\n    min-height: 1em;\n\n    -webkit-touch-callout: none;\n      -webkit-user-select: none;\n         -moz-user-select: none;\n          -ms-user-select: none;\n              user-select: none;\n}\n\n.select2-results .select2-highlighted {\n    background: #3875d7;\n    color: #fff;\n}\n\n.select2-results li em {\n    background: #feffde;\n    font-style: normal;\n}\n\n.select2-results .select2-highlighted em {\n    background: transparent;\n}\n\n.select2-results .select2-highlighted ul {\n    background: #fff;\n    color: #000;\n}\n\n\n.select2-results .select2-no-results,\n.select2-results .select2-searching,\n.select2-results .select2-selection-limit {\n    background: #f4f4f4;\n    display: list-item;\n}\n\n/*\ndisabled look for disabled choices in the results dropdown\n*/\n.select2-results .select2-disabled.select2-highlighted {\n    color: #666;\n    background: #f4f4f4;\n    display: list-item;\n    cursor: default;\n}\n.select2-results .select2-disabled {\n  background: #f4f4f4;\n  display: list-item;\n  cursor: default;\n}\n\n.select2-results .select2-selected {\n    display: none;\n}\n\n.select2-more-results.select2-active {\n    background: #f4f4f4 url('select2-spinner.gif') no-repeat 100%;\n}\n\n.select2-more-results {\n    background: #f4f4f4;\n    display: list-item;\n}\n\n/* disabled styles */\n\n.select2-container.select2-container-disabled .select2-choice {\n    background-color: #f4f4f4;\n    background-image: none;\n    border: 1px solid #ddd;\n    cursor: default;\n}\n\n.select2-container.select2-container-disabled .select2-choice .select2-arrow {\n    background-color: #f4f4f4;\n    background-image: none;\n    border-left: 0;\n}\n\n.select2-container.select2-container-disabled .select2-choice abbr {\n    display: none;\n}\n\n\n/* multiselect */\n\n.select2-container-multi .select2-choices {\n    height: auto !important;\n    height: 1%;\n    margin: 0;\n    padding: 0;\n    position: relative;\n\n    border: 1px solid #aaa;\n    cursor: text;\n    overflow: hidden;\n\n    background-color: #fff;\n    background-image: -webkit-gradient(linear, 0% 0%, 0% 100%, color-stop(1%, #eee), color-stop(15%, #fff));\n    background-image: -webkit-linear-gradient(top, #eee 1%, #fff 15%);\n    background-image: -moz-linear-gradient(top, #eee 1%, #fff 15%);\n    background-image: linear-gradient(top, #eee 1%, #fff 15%);\n}\n\n.select2-locked {\n  padding: 3px 5px 3px 5px !important;\n}\n\n.select2-container-multi .select2-choices {\n    min-height: 26px;\n}\n\n.select2-container-multi.select2-container-active .select2-choices {\n    border: 1px solid #5897fb;\n    outline: none;\n\n    -webkit-box-shadow: 0 0 5px rgba(0, 0, 0, .3);\n            box-shadow: 0 0 5px rgba(0, 0, 0, .3);\n}\n.select2-container-multi .select2-choices li {\n    float: left;\n    list-style: none;\n}\n.select2-container-multi .select2-choices .select2-search-field {\n    margin: 0;\n    padding: 0;\n    white-space: nowrap;\n}\n\n.select2-container-multi .select2-choices .select2-search-field input {\n    padding: 5px;\n    margin: 1px 0;\n\n    font-family: sans-serif;\n    font-size: 100%;\n    color: #666;\n    outline: 0;\n    border: 0;\n    -webkit-box-shadow: none;\n            box-shadow: none;\n    background: transparent !important;\n}\n\n.select2-container-multi .select2-choices .select2-search-field input.select2-active {\n    background: #fff url('select2-spinner.gif') no-repeat 100% !important;\n}\n\n.select2-default {\n    color: #999 !important;\n}\n\n.select2-container-multi .select2-choices .select2-search-choice {\n    padding: 3px 5px 3px 18px;\n    margin: 3px 0 3px 5px;\n    position: relative;\n\n    line-height: 13px;\n    color: #333;\n    cursor: default;\n    border: 1px solid #aaaaaa;\n\n    border-radius: 3px;\n\n    -webkit-box-shadow: 0 0 2px #fff inset, 0 1px 0 rgba(0, 0, 0, 0.05);\n            box-shadow: 0 0 2px #fff inset, 0 1px 0 rgba(0, 0, 0, 0.05);\n\n    background-clip: padding-box;\n\n    -webkit-touch-callout: none;\n      -webkit-user-select: none;\n         -moz-user-select: none;\n          -ms-user-select: none;\n              user-select: none;\n\n    background-color: #e4e4e4;\n    filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#eeeeee', endColorstr='#f4f4f4', GradientType=0);\n    background-image: -webkit-gradient(linear, 0% 0%, 0% 100%, color-stop(20%, #f4f4f4), color-stop(50%, #f0f0f0), color-stop(52%, #e8e8e8), color-stop(100%, #eee));\n    background-image: -webkit-linear-gradient(top, #f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eee 100%);\n    background-image: -moz-linear-gradient(top, #f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eee 100%);\n    background-image: linear-gradient(top, #f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eee 100%);\n}\n.select2-container-multi .select2-choices .select2-search-choice .select2-chosen {\n    cursor: default;\n}\n.select2-container-multi .select2-choices .select2-search-choice-focus {\n    background: #d4d4d4;\n}\n\n.select2-search-choice-close {\n    display: block;\n    width: 12px;\n    height: 13px;\n    position: absolute;\n    right: 3px;\n    top: 4px;\n\n    font-size: 1px;\n    outline: none;\n    background: url('select2.png') right top no-repeat;\n}\n\n.select2-container-multi .select2-search-choice-close {\n    left: 3px;\n}\n\n.select2-container-multi .select2-choices .select2-search-choice .select2-search-choice-close:hover {\n  background-position: right -11px;\n}\n.select2-container-multi .select2-choices .select2-search-choice-focus .select2-search-choice-close {\n    background-position: right -11px;\n}\n\n/* disabled styles */\n.select2-container-multi.select2-container-disabled .select2-choices {\n    background-color: #f4f4f4;\n    background-image: none;\n    border: 1px solid #ddd;\n    cursor: default;\n}\n\n.select2-container-multi.select2-container-disabled .select2-choices .select2-search-choice {\n    padding: 3px 5px 3px 5px;\n    border: 1px solid #ddd;\n    background-image: none;\n    background-color: #f4f4f4;\n}\n\n.select2-container-multi.select2-container-disabled .select2-choices .select2-search-choice .select2-search-choice-close {    display: none;\n    background: none;\n}\n/* end multiselect */\n\n\n.select2-result-selectable .select2-match,\n.select2-result-unselectable .select2-match {\n    text-decoration: underline;\n}\n\n.select2-offscreen, .select2-offscreen:focus {\n    clip: rect(0 0 0 0) !important;\n    width: 1px !important;\n    height: 1px !important;\n    border: 0 !important;\n    margin: 0 !important;\n    padding: 0 !important;\n    overflow: hidden !important;\n    position: absolute !important;\n    outline: 0 !important;\n    left: 0px !important;\n    top: 0px !important;\n}\n\n.select2-display-none {\n    display: none;\n}\n\n.select2-measure-scrollbar {\n    position: absolute;\n    top: -10000px;\n    left: -10000px;\n    width: 100px;\n    height: 100px;\n    overflow: scroll;\n}\n/* Retina-ize icons */\n\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5), only screen and (min-resolution: 144dpi)  {\n  .select2-search input, .select2-search-choice-close, .select2-container .select2-choice abbr, .select2-container .select2-choice .select2-arrow b {\n      background-image: url('select2x2.png') !important;\n      background-repeat: no-repeat !important;\n      background-size: 60px 40px !important;\n  }\n  .select2-search input {\n      background-position: 100% -21px !important;\n  }\n}\n"
  },
  {
    "path": "flowable-ui-web/admin/additional_components/ui-grid/ui-grid.css",
    "content": "/*!\n * ui-grid - v3.0.4 - 2015-08-13\n * Copyright (c) 2015 ; License: MIT \n */\n#ui-grid-twbs #ui-grid-twbs .form-horizontal .form-group:before,\n#ui-grid-twbs #ui-grid-twbs .form-horizontal .form-group:after,\n#ui-grid-twbs #ui-grid-twbs .btn-toolbar:before,\n#ui-grid-twbs #ui-grid-twbs .btn-toolbar:after,\n#ui-grid-twbs #ui-grid-twbs .btn-group-vertical > .btn-group:before,\n#ui-grid-twbs #ui-grid-twbs .btn-group-vertical > .btn-group:after {\n  content: \" \";\n  display: table;\n}\n#ui-grid-twbs #ui-grid-twbs .form-horizontal .form-group:after,\n#ui-grid-twbs #ui-grid-twbs .btn-toolbar:after,\n#ui-grid-twbs #ui-grid-twbs .btn-group-vertical > .btn-group:after {\n  clear: both;\n}\n.ui-grid {\n  border: 1px solid #d4d4d4;\n  box-sizing: content-box;\n  -webkit-border-radius: 0px;\n  -moz-border-radius: 0px;\n  border-radius: 0px;\n  -webkit-transform: translateZ(0);\n  -moz-transform: translateZ(0);\n  -o-transform: translateZ(0);\n  -ms-transform: translateZ(0);\n  transform: translateZ(0);\n}\n.ui-grid-vertical-bar {\n  position: absolute;\n  right: 0;\n  width: 0;\n}\n.ui-grid-header-cell:not(:last-child) .ui-grid-vertical-bar,\n.ui-grid-cell:not(:last-child) .ui-grid-vertical-bar {\n  width: 1px;\n}\n.ui-grid-scrollbar-placeholder {\n  background-color: transparent;\n}\n.ui-grid-header-cell:not(:last-child) .ui-grid-vertical-bar {\n  background-color: #d4d4d4;\n}\n.ui-grid-cell:not(:last-child) .ui-grid-vertical-bar {\n  background-color: #d4d4d4;\n}\n.ui-grid-header-cell:last-child .ui-grid-vertical-bar {\n  right: -1px;\n  width: 1px;\n  background-color: #d4d4d4;\n}\n.ui-grid-clearfix:before,\n.ui-grid-clearfix:after {\n  content: \"\";\n  display: table;\n}\n.ui-grid-clearfix:after {\n  clear: both;\n}\n.ui-grid-invisible {\n  visibility: hidden;\n}\n.ui-grid-contents-wrapper {\n  position: relative;\n  height: 100%;\n  width: 100%;\n}\n.ui-grid-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.ui-grid-top-panel-background {\n  background: #f3f3f3;\n  background: -webkit-gradient(linear, left bottom, left top, color-stop(0, #eeeeee), color-stop(1, #ffffff));\n  background: -ms-linear-gradient(bottom, #eeeeee, #ffffff);\n  background: -moz-linear-gradient(center bottom, #eeeeee 0%, #ffffff 100%);\n  background: -o-linear-gradient(#ffffff, #eeeeee);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#eeeeee', GradientType=0);\n}\n.ui-grid-header {\n  border-bottom: 1px solid #d4d4d4;\n  box-sizing: border-box;\n}\n.ui-grid-top-panel {\n  position: relative;\n  overflow: hidden;\n  font-weight: bold;\n  background: #f3f3f3;\n  background: -webkit-gradient(linear, left bottom, left top, color-stop(0, #eeeeee), color-stop(1, #ffffff));\n  background: -ms-linear-gradient(bottom, #eeeeee, #ffffff);\n  background: -moz-linear-gradient(center bottom, #eeeeee 0%, #ffffff 100%);\n  background: -o-linear-gradient(#ffffff, #eeeeee);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#eeeeee', GradientType=0);\n  -webkit-border-top-right-radius: -1px;\n  -webkit-border-bottom-right-radius: 0;\n  -webkit-border-bottom-left-radius: 0;\n  -webkit-border-top-left-radius: -1px;\n  -moz-border-radius-topright: -1px;\n  -moz-border-radius-bottomright: 0;\n  -moz-border-radius-bottomleft: 0;\n  -moz-border-radius-topleft: -1px;\n  border-top-right-radius: -1px;\n  border-bottom-right-radius: 0;\n  border-bottom-left-radius: 0;\n  border-top-left-radius: -1px;\n  -moz-background-clip: padding-box;\n  -webkit-background-clip: padding-box;\n  background-clip: padding-box;\n}\n.ui-grid-header-viewport {\n  overflow: hidden;\n}\n.ui-grid-header-canvas:before,\n.ui-grid-header-canvas:after {\n  content: \"\";\n  display: table;\n  line-height: 0;\n}\n.ui-grid-header-canvas:after {\n  clear: both;\n}\n.ui-grid-header-cell-wrapper {\n  position: relative;\n  display: table;\n  box-sizing: border-box;\n  height: 100%;\n}\n.ui-grid-header-cell-row {\n  display: table-row;\n  position: relative;\n}\n.ui-grid-header-cell {\n  position: relative;\n  box-sizing: border-box;\n  background-color: inherit;\n  border-right: 1px solid;\n  border-color: #d4d4d4;\n  display: table-cell;\n  -webkit-user-select: none;\n  -moz-user-select: none;\n  -ms-user-select: none;\n  user-select: none;\n  width: 0;\n}\n.ui-grid-header-cell:last-child {\n  border-right: 0;\n}\n.ui-grid-header-cell .sortable {\n  cursor: pointer;\n}\n.ui-grid-header .ui-grid-vertical-bar {\n  top: 0;\n  bottom: 0;\n}\n.ui-grid-column-menu-button {\n  position: absolute;\n  right: 1px;\n  top: 0;\n}\n.ui-grid-column-menu-button .ui-grid-icon-angle-down {\n  vertical-align: sub;\n}\n.ui-grid-column-menu-button-last-col {\n  margin-right: 25px;\n}\n.ui-grid-column-menu {\n  position: absolute;\n}\n/* Slide up/down animations */\n.ui-grid-column-menu .ui-grid-menu .ui-grid-menu-mid.ng-hide-add,\n.ui-grid-column-menu .ui-grid-menu .ui-grid-menu-mid.ng-hide-remove {\n  -webkit-transition: all 0.05s linear;\n  -moz-transition: all 0.05s linear;\n  -o-transition: all 0.05s linear;\n  transition: all 0.05s linear;\n  display: block !important;\n}\n.ui-grid-column-menu .ui-grid-menu .ui-grid-menu-mid.ng-hide-add.ng-hide-add-active,\n.ui-grid-column-menu .ui-grid-menu .ui-grid-menu-mid.ng-hide-remove {\n  -webkit-transform: translateY(-100%);\n  -moz-transform: translateY(-100%);\n  -o-transform: translateY(-100%);\n  -ms-transform: translateY(-100%);\n  transform: translateY(-100%);\n}\n.ui-grid-column-menu .ui-grid-menu .ui-grid-menu-mid.ng-hide-add,\n.ui-grid-column-menu .ui-grid-menu .ui-grid-menu-mid.ng-hide-remove.ng-hide-remove-active {\n  -webkit-transform: translateY(0);\n  -moz-transform: translateY(0);\n  -o-transform: translateY(0);\n  -ms-transform: translateY(0);\n  transform: translateY(0);\n}\n/* Slide up/down animations */\n.ui-grid-menu-button .ui-grid-menu .ui-grid-menu-mid.ng-hide-add,\n.ui-grid-menu-button .ui-grid-menu .ui-grid-menu-mid.ng-hide-remove {\n  -webkit-transition: all 0.05s linear;\n  -moz-transition: all 0.05s linear;\n  -o-transition: all 0.05s linear;\n  transition: all 0.05s linear;\n  display: block !important;\n}\n.ui-grid-menu-button .ui-grid-menu .ui-grid-menu-mid.ng-hide-add.ng-hide-add-active,\n.ui-grid-menu-button .ui-grid-menu .ui-grid-menu-mid.ng-hide-remove {\n  -webkit-transform: translateY(-100%);\n  -moz-transform: translateY(-100%);\n  -o-transform: translateY(-100%);\n  -ms-transform: translateY(-100%);\n  transform: translateY(-100%);\n}\n.ui-grid-menu-button .ui-grid-menu .ui-grid-menu-mid.ng-hide-add,\n.ui-grid-menu-button .ui-grid-menu .ui-grid-menu-mid.ng-hide-remove.ng-hide-remove-active {\n  -webkit-transform: translateY(0);\n  -moz-transform: translateY(0);\n  -o-transform: translateY(0);\n  -ms-transform: translateY(0);\n  transform: translateY(0);\n}\n.ui-grid-filter-container {\n  padding: 4px 10px;\n  position: relative;\n}\n.ui-grid-filter-container .ui-grid-filter-button {\n  position: absolute;\n  top: 0;\n  bottom: 0;\n  right: 0;\n}\n.ui-grid-filter-container .ui-grid-filter-button [class^=\"ui-grid-icon\"] {\n  position: absolute;\n  top: 50%;\n  line-height: 32px;\n  margin-top: -16px;\n  right: 10px;\n  opacity: 0.66;\n}\n.ui-grid-filter-container .ui-grid-filter-button [class^=\"ui-grid-icon\"]:hover {\n  opacity: 1;\n}\n.ui-grid-filter-container .ui-grid-filter-button-select {\n  position: absolute;\n  top: 0;\n  bottom: 0;\n  right: 0;\n}\n.ui-grid-filter-container .ui-grid-filter-button-select [class^=\"ui-grid-icon\"] {\n  position: absolute;\n  top: 50%;\n  line-height: 32px;\n  margin-top: -16px;\n  right: 0px;\n  opacity: 0.66;\n}\n.ui-grid-filter-container .ui-grid-filter-button-select [class^=\"ui-grid-icon\"]:hover {\n  opacity: 1;\n}\ninput[type=\"text\"].ui-grid-filter-input {\n  padding: 0;\n  margin: 0;\n  border: 0;\n  width: 100%;\n  border: 1px solid #d4d4d4;\n  -webkit-border-top-right-radius: 0px;\n  -webkit-border-bottom-right-radius: 0;\n  -webkit-border-bottom-left-radius: 0;\n  -webkit-border-top-left-radius: 0;\n  -moz-border-radius-topright: 0px;\n  -moz-border-radius-bottomright: 0;\n  -moz-border-radius-bottomleft: 0;\n  -moz-border-radius-topleft: 0;\n  border-top-right-radius: 0px;\n  border-bottom-right-radius: 0;\n  border-bottom-left-radius: 0;\n  border-top-left-radius: 0;\n  -moz-background-clip: padding-box;\n  -webkit-background-clip: padding-box;\n  background-clip: padding-box;\n}\ninput[type=\"text\"].ui-grid-filter-input:hover {\n  border: 1px solid #d4d4d4;\n}\nselect.ui-grid-filter-select {\n  padding: 0;\n  margin: 0;\n  border: 0;\n  width: 90%;\n  border: 1px solid #d4d4d4;\n  -webkit-border-top-right-radius: 0px;\n  -webkit-border-bottom-right-radius: 0;\n  -webkit-border-bottom-left-radius: 0;\n  -webkit-border-top-left-radius: 0;\n  -moz-border-radius-topright: 0px;\n  -moz-border-radius-bottomright: 0;\n  -moz-border-radius-bottomleft: 0;\n  -moz-border-radius-topleft: 0;\n  border-top-right-radius: 0px;\n  border-bottom-right-radius: 0;\n  border-bottom-left-radius: 0;\n  border-top-left-radius: 0;\n  -moz-background-clip: padding-box;\n  -webkit-background-clip: padding-box;\n  background-clip: padding-box;\n}\nselect.ui-grid-filter-select:hover {\n  border: 1px solid #d4d4d4;\n}\n.ui-grid-filter-cancel-button-hidden select.ui-grid-filter-select {\n  width: 100%;\n}\n.ui-grid-render-container {\n  position: inherit;\n  -webkit-border-top-right-radius: 0;\n  -webkit-border-bottom-right-radius: 0px;\n  -webkit-border-bottom-left-radius: 0px;\n  -webkit-border-top-left-radius: 0;\n  -moz-border-radius-topright: 0;\n  -moz-border-radius-bottomright: 0px;\n  -moz-border-radius-bottomleft: 0px;\n  -moz-border-radius-topleft: 0;\n  border-top-right-radius: 0;\n  border-bottom-right-radius: 0px;\n  border-bottom-left-radius: 0px;\n  border-top-left-radius: 0;\n  -moz-background-clip: padding-box;\n  -webkit-background-clip: padding-box;\n  background-clip: padding-box;\n}\n.ui-grid-render-container:focus {\n  outline: none;\n}\n.ui-grid-viewport {\n  min-height: 20px;\n  position: relative;\n  overflow-y: scroll;\n  -webkit-overflow-scrolling: touch;\n}\n.ui-grid-viewport:focus {\n  outline: none !important;\n}\n.ui-grid-canvas {\n  position: relative;\n  padding-top: 1px;\n}\n.ui-grid-row:nth-child(odd) .ui-grid-cell {\n  background-color: #fdfdfd;\n}\n.ui-grid-row:nth-child(even) .ui-grid-cell {\n  background-color: #f3f3f3;\n}\n.ui-grid-row:last-child .ui-grid-cell {\n  border-bottom-color: #d4d4d4;\n  border-bottom-style: solid;\n}\n.ui-grid-no-row-overlay {\n  position: absolute;\n  top: 0;\n  bottom: 0;\n  left: 0;\n  right: 0;\n  margin: 10%;\n  background: #f3f3f3;\n  background: -webkit-gradient(linear, left bottom, left top, color-stop(0, #eeeeee), color-stop(1, #ffffff));\n  background: -ms-linear-gradient(bottom, #eeeeee, #ffffff);\n  background: -moz-linear-gradient(center bottom, #eeeeee 0%, #ffffff 100%);\n  background: -o-linear-gradient(#ffffff, #eeeeee);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#eeeeee', GradientType=0);\n  -webkit-border-top-right-radius: 0px;\n  -webkit-border-bottom-right-radius: 0;\n  -webkit-border-bottom-left-radius: 0;\n  -webkit-border-top-left-radius: 0;\n  -moz-border-radius-topright: 0px;\n  -moz-border-radius-bottomright: 0;\n  -moz-border-radius-bottomleft: 0;\n  -moz-border-radius-topleft: 0;\n  border-top-right-radius: 0px;\n  border-bottom-right-radius: 0;\n  border-bottom-left-radius: 0;\n  border-top-left-radius: 0;\n  -moz-background-clip: padding-box;\n  -webkit-background-clip: padding-box;\n  background-clip: padding-box;\n  border: 1px solid #d4d4d4;\n  font-size: 2em;\n  text-align: center;\n}\n.ui-grid-no-row-overlay > * {\n  position: absolute;\n  display: table;\n  margin: auto 0;\n  width: 100%;\n  top: 0;\n  bottom: 0;\n  left: 0;\n  right: 0;\n  opacity: 0.66;\n}\n.ui-grid-cell {\n  overflow: hidden;\n  float: left;\n  background-color: inherit;\n  border-right: 1px solid;\n  border-color: #d4d4d4;\n  box-sizing: border-box;\n}\n.ui-grid-cell:last-child {\n  border-right: 0;\n}\n.ui-grid-cell-contents {\n  padding: 5px;\n  -moz-box-sizing: border-box;\n  -webkit-box-sizing: border-box;\n  box-sizing: border-box;\n  white-space: nowrap;\n  -ms-text-overflow: ellipsis;\n  -o-text-overflow: ellipsis;\n  text-overflow: ellipsis;\n  overflow: hidden;\n  height: 100%;\n}\n.ui-grid-cell-contents-hidden {\n  visibility: hidden;\n  width: 0;\n  height: 0;\n  display: none;\n}\n.ui-grid-row .ui-grid-cell.ui-grid-row-header-cell {\n  background-color: #f0f0ee;\n  border-bottom: solid 1px #d4d4d4;\n}\n.ui-grid-footer-panel-background {\n  background: #f3f3f3;\n  background: -webkit-gradient(linear, left bottom, left top, color-stop(0, #eeeeee), color-stop(1, #ffffff));\n  background: -ms-linear-gradient(bottom, #eeeeee, #ffffff);\n  background: -moz-linear-gradient(center bottom, #eeeeee 0%, #ffffff 100%);\n  background: -o-linear-gradient(#ffffff, #eeeeee);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#eeeeee', GradientType=0);\n}\n.ui-grid-footer-panel {\n  position: relative;\n  border-bottom: 1px solid #d4d4d4;\n  border-top: 1px solid #d4d4d4;\n  overflow: hidden;\n  font-weight: bold;\n  background: #f3f3f3;\n  background: -webkit-gradient(linear, left bottom, left top, color-stop(0, #eeeeee), color-stop(1, #ffffff));\n  background: -ms-linear-gradient(bottom, #eeeeee, #ffffff);\n  background: -moz-linear-gradient(center bottom, #eeeeee 0%, #ffffff 100%);\n  background: -o-linear-gradient(#ffffff, #eeeeee);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#eeeeee', GradientType=0);\n  -webkit-border-top-right-radius: -1px;\n  -webkit-border-bottom-right-radius: 0;\n  -webkit-border-bottom-left-radius: 0;\n  -webkit-border-top-left-radius: -1px;\n  -moz-border-radius-topright: -1px;\n  -moz-border-radius-bottomright: 0;\n  -moz-border-radius-bottomleft: 0;\n  -moz-border-radius-topleft: -1px;\n  border-top-right-radius: -1px;\n  border-bottom-right-radius: 0;\n  border-bottom-left-radius: 0;\n  border-top-left-radius: -1px;\n  -moz-background-clip: padding-box;\n  -webkit-background-clip: padding-box;\n  background-clip: padding-box;\n}\n.ui-grid-grid-footer {\n  float: left;\n  width: 100%;\n}\n.ui-grid-footer-viewport {\n  overflow: hidden;\n}\n.ui-grid-footer-canvas {\n  position: relative;\n}\n.ui-grid-footer-canvas:before,\n.ui-grid-footer-canvas:after {\n  content: \"\";\n  display: table;\n  line-height: 0;\n}\n.ui-grid-footer-canvas:after {\n  clear: both;\n}\n.ui-grid-footer-cell-wrapper {\n  position: relative;\n  display: table;\n  box-sizing: border-box;\n  height: 100%;\n}\n.ui-grid-footer-cell-row {\n  display: table-row;\n}\n.ui-grid-footer-cell {\n  overflow: hidden;\n  background-color: inherit;\n  border-right: 1px solid;\n  border-color: #d4d4d4;\n  box-sizing: border-box;\n  display: table-cell;\n}\n.ui-grid-footer-cell:last-child {\n  border-right: 0;\n}\ninput[type=\"text\"].ui-grid-filter-input {\n  padding: 0;\n  margin: 0;\n  border: 0;\n  width: 100%;\n  border: 1px solid #d4d4d4;\n  -webkit-border-top-right-radius: 0px;\n  -webkit-border-bottom-right-radius: 0;\n  -webkit-border-bottom-left-radius: 0;\n  -webkit-border-top-left-radius: 0;\n  -moz-border-radius-topright: 0px;\n  -moz-border-radius-bottomright: 0;\n  -moz-border-radius-bottomleft: 0;\n  -moz-border-radius-topleft: 0;\n  border-top-right-radius: 0px;\n  border-bottom-right-radius: 0;\n  border-bottom-left-radius: 0;\n  border-top-left-radius: 0;\n  -moz-background-clip: padding-box;\n  -webkit-background-clip: padding-box;\n  background-clip: padding-box;\n}\ninput[type=\"text\"].ui-grid-filter-input:hover {\n  border: 1px solid #d4d4d4;\n}\n.ui-grid-menu-button {\n  z-index: 2;\n  position: absolute;\n  right: 0;\n  top: 0;\n  background: #f3f3f3;\n  border: 1px solid #d4d4d4;\n  cursor: pointer;\n  height: 31px;\n  font-weight: normal;\n}\n.ui-grid-menu-button .ui-grid-icon-container {\n  margin-top: 3px;\n}\n.ui-grid-menu-button .ui-grid-menu {\n  right: 0;\n}\n.ui-grid-menu-button .ui-grid-menu .ui-grid-menu-mid {\n  overflow: scroll;\n  max-height: 300px;\n  border: 1px solid #d4d4d4;\n}\n.ui-grid-menu {\n  z-index: 2;\n  position: absolute;\n  padding: 0 10px 20px 10px;\n  cursor: pointer;\n  box-sizing: border-box;\n}\n.ui-grid-menu .ui-grid-menu-inner {\n  background: #f3f3f3;\n  border: 1px solid #d4d4d4;\n  position: relative;\n  white-space: nowrap;\n  -webkit-border-radius: 0px;\n  -moz-border-radius: 0px;\n  border-radius: 0px;\n  -webkit-box-shadow: 0 10px 20px rgba(0, 0, 0, 0.2), inset 0 12px 12px -14px rgba(0, 0, 0, 0.2);\n  -moz-box-shadow: 0 10px 20px rgba(0, 0, 0, 0.2), inset 0 12px 12px -14px rgba(0, 0, 0, 0.2);\n  box-shadow: 0 10px 20px rgba(0, 0, 0, 0.2), inset 0 12px 12px -14px rgba(0, 0, 0, 0.2);\n}\n.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button {\n  position: absolute;\n  right: 0px;\n  top: 0px;\n  display: inline-block;\n  margin-bottom: 0;\n  font-weight: normal;\n  text-align: center;\n  vertical-align: middle;\n  touch-action: manipulation;\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.42857143;\n  border-radius: 4px;\n  -webkit-user-select: none;\n  -moz-user-select: none;\n  -ms-user-select: none;\n  user-select: none;\n  padding: 1px 1px;\n  font-size: 10px;\n  line-height: 1;\n  border-radius: 2px;\n  color: transparent;\n  background-color: transparent;\n  border-color: transparent;\n}\n.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button:focus,\n.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button:active:focus,\n.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button.active:focus,\n.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button.focus,\n.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button:active.focus,\n.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button.active.focus {\n  outline: thin dotted;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button:hover,\n.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button:focus,\n.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button.focus {\n  color: #333333;\n  text-decoration: none;\n}\n.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button:active,\n.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button.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.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button.disabled,\n.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button[disabled],\nfieldset[disabled] .ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button {\n  cursor: not-allowed;\n  opacity: 0.65;\n  filter: alpha(opacity=65);\n  -webkit-box-shadow: none;\n  box-shadow: none;\n}\na.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button.disabled,\nfieldset[disabled] a.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button {\n  pointer-events: none;\n}\n.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button:focus,\n.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button.focus {\n  color: transparent;\n  background-color: rgba(0, 0, 0, 0);\n  border-color: rgba(0, 0, 0, 0);\n}\n.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button:hover {\n  color: transparent;\n  background-color: rgba(0, 0, 0, 0);\n  border-color: rgba(0, 0, 0, 0);\n}\n.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button:active,\n.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button.active,\n.open > .dropdown-toggle.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button {\n  color: transparent;\n  background-color: rgba(0, 0, 0, 0);\n  border-color: rgba(0, 0, 0, 0);\n}\n.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button:active:hover,\n.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button.active:hover,\n.open > .dropdown-toggle.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button:hover,\n.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button:active:focus,\n.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button.active:focus,\n.open > .dropdown-toggle.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button:focus,\n.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button:active.focus,\n.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button.active.focus,\n.open > .dropdown-toggle.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button.focus {\n  color: transparent;\n  background-color: rgba(0, 0, 0, 0);\n  border-color: rgba(0, 0, 0, 0);\n}\n.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button:active,\n.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button.active,\n.open > .dropdown-toggle.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button {\n  background-image: none;\n}\n.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button.disabled,\n.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button[disabled],\nfieldset[disabled] .ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button,\n.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button.disabled:hover,\n.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button[disabled]:hover,\nfieldset[disabled] .ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button:hover,\n.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button.disabled:focus,\n.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button[disabled]:focus,\nfieldset[disabled] .ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button:focus,\n.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button.disabled.focus,\n.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button[disabled].focus,\nfieldset[disabled] .ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button.focus,\n.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button.disabled:active,\n.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button[disabled]:active,\nfieldset[disabled] .ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button:active,\n.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button.disabled.active,\n.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button[disabled].active,\nfieldset[disabled] .ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button.active {\n  background-color: transparent;\n  border-color: transparent;\n}\n.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button .badge {\n  color: transparent;\n  background-color: transparent;\n}\n.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button > i {\n  opacity: 0.75;\n  color: black;\n}\n.ui-grid-menu .ui-grid-menu-inner ul {\n  margin: 0;\n  padding: 0;\n  list-style-type: none;\n}\n.ui-grid-menu .ui-grid-menu-inner ul li {\n  padding: 0px;\n}\n.ui-grid-menu .ui-grid-menu-inner ul li button {\n  min-width: 100%;\n  padding: 8px;\n  text-align: left;\n  background: transparent;\n  border: none;\n}\n.ui-grid-menu .ui-grid-menu-inner ul li button:hover,\n.ui-grid-menu .ui-grid-menu-inner ul li button:focus {\n  -webkit-box-shadow: inset 0 0 14px rgba(0, 0, 0, 0.2);\n  -moz-box-shadow: inset 0 0 14px rgba(0, 0, 0, 0.2);\n  box-shadow: inset 0 0 14px rgba(0, 0, 0, 0.2);\n}\n.ui-grid-menu .ui-grid-menu-inner ul li button.ui-grid-menu-item-active {\n  -webkit-box-shadow: inset 0 0 14px rgba(0, 0, 0, 0.2);\n  -moz-box-shadow: inset 0 0 14px rgba(0, 0, 0, 0.2);\n  box-shadow: inset 0 0 14px rgba(0, 0, 0, 0.2);\n  background-color: #cecece;\n}\n.ui-grid-menu .ui-grid-menu-inner ul li:not(:last-child) > button {\n  border-bottom: 1px solid #d4d4d4;\n}\n.ui-grid-sortarrow {\n  right: 5px;\n  position: absolute;\n  width: 20px;\n  top: 0;\n  bottom: 0;\n  background-position: center;\n}\n.ui-grid-sortarrow.down {\n  -webkit-transform: rotate(180deg);\n  -moz-transform: rotate(180deg);\n  -o-transform: rotate(180deg);\n  -ms-transform: rotate(180deg);\n  transform: rotate(180deg);\n}\n@font-face {\n  font-family: 'ui-grid';\n  src: url('ui-grid.eot');\n  src: url('ui-grid.eot#iefix') format('embedded-opentype'), url('ui-grid.woff') format('woff'), url('ui-grid.ttf') format('truetype'), url('ui-grid.svg?#ui-grid') format('svg');\n  font-weight: normal;\n  font-style: normal;\n}\n/* Chrome hack: SVG is rendered more smooth in Windozze. 100% magic, uncomment if you need it. */\n/* Note, that will break hinting! In other OS-es font will be not as sharp as it could be */\n/*\n@media screen and (-webkit-min-device-pixel-ratio:0) {\n  @font-face {\n    font-family: 'ui-grid';\n    src: url('../font/ui-grid.svg?12312827#ui-grid') format('svg');\n  }\n}\n*/\n[class^=\"ui-grid-icon\"]:before,\n[class*=\" ui-grid-icon\"]:before {\n  font-family: \"ui-grid\";\n  font-style: normal;\n  font-weight: normal;\n  speak: none;\n  display: inline-block;\n  text-decoration: inherit;\n  width: 1em;\n  margin-right: .2em;\n  text-align: center;\n  /* opacity: .8; */\n  /* For safety - reset parent styles, that can break glyph codes*/\n  font-variant: normal;\n  text-transform: none;\n  /* fix buttons height, for twitter bootstrap */\n  line-height: 1em;\n  /* Animation center compensation - margins should be symmetric */\n  /* remove if not needed */\n  margin-left: .2em;\n  /* you can be more comfortable with increased icons size */\n  /* font-size: 120%; */\n  /* Uncomment for 3D effect */\n  /* text-shadow: 1px 1px 1px rgba(127, 127, 127, 0.3); */\n}\n.ui-grid-icon-blank::before {\n  width: 1em;\n  content: ' ';\n}\n/*\n* RTL Styles\n*/\n.ui-grid[dir=rtl] .ui-grid-header-cell,\n.ui-grid[dir=rtl] .ui-grid-footer-cell,\n.ui-grid[dir=rtl] .ui-grid-cell {\n  float: right !important;\n}\n.ui-grid[dir=rtl] .ui-grid-column-menu-button {\n  position: absolute;\n  left: 1px;\n  top: 0;\n  right: inherit;\n}\n.ui-grid[dir=rtl] .ui-grid-cell:first-child,\n.ui-grid[dir=rtl] .ui-grid-header-cell:first-child,\n.ui-grid[dir=rtl] .ui-grid-footer-cell:first-child {\n  border-right: 0;\n}\n.ui-grid[dir=rtl] .ui-grid-cell:last-child,\n.ui-grid[dir=rtl] .ui-grid-header-cell:last-child {\n  border-right: 1px solid #d4d4d4;\n  border-left: 0;\n}\n.ui-grid[dir=rtl] .ui-grid-header-cell:first-child .ui-grid-vertical-bar,\n.ui-grid[dir=rtl] .ui-grid-footer-cell:first-child .ui-grid-vertical-bar,\n.ui-grid[dir=rtl] .ui-grid-cell:first-child .ui-grid-vertical-bar {\n  width: 0;\n}\n.ui-grid[dir=rtl] .ui-grid-menu-button {\n  z-index: 2;\n  position: absolute;\n  left: 0;\n  right: auto;\n  background: #f3f3f3;\n  border: 1px solid #d4d4d4;\n  cursor: pointer;\n  min-height: 27px;\n  font-weight: normal;\n}\n.ui-grid[dir=rtl] .ui-grid-menu-button .ui-grid-menu {\n  left: 0;\n  right: auto;\n}\n.ui-grid[dir=rtl] .ui-grid-filter-container .ui-grid-filter-button {\n  right: initial;\n  left: 0;\n}\n.ui-grid[dir=rtl] .ui-grid-filter-container .ui-grid-filter-button [class^=\"ui-grid-icon\"] {\n  right: initial;\n  left: 10px;\n}\n/*\n   Animation example, for spinners\n*/\n.ui-grid-animate-spin {\n  -moz-animation: ui-grid-spin 2s infinite linear;\n  -o-animation: ui-grid-spin 2s infinite linear;\n  -webkit-animation: ui-grid-spin 2s infinite linear;\n  animation: ui-grid-spin 2s infinite linear;\n  display: inline-block;\n}\n@-moz-keyframes ui-grid-spin {\n  0% {\n    -moz-transform: rotate(0deg);\n    -o-transform: rotate(0deg);\n    -webkit-transform: rotate(0deg);\n    transform: rotate(0deg);\n  }\n  100% {\n    -moz-transform: rotate(359deg);\n    -o-transform: rotate(359deg);\n    -webkit-transform: rotate(359deg);\n    transform: rotate(359deg);\n  }\n}\n@-webkit-keyframes ui-grid-spin {\n  0% {\n    -moz-transform: rotate(0deg);\n    -o-transform: rotate(0deg);\n    -webkit-transform: rotate(0deg);\n    transform: rotate(0deg);\n  }\n  100% {\n    -moz-transform: rotate(359deg);\n    -o-transform: rotate(359deg);\n    -webkit-transform: rotate(359deg);\n    transform: rotate(359deg);\n  }\n}\n@-o-keyframes ui-grid-spin {\n  0% {\n    -moz-transform: rotate(0deg);\n    -o-transform: rotate(0deg);\n    -webkit-transform: rotate(0deg);\n    transform: rotate(0deg);\n  }\n  100% {\n    -moz-transform: rotate(359deg);\n    -o-transform: rotate(359deg);\n    -webkit-transform: rotate(359deg);\n    transform: rotate(359deg);\n  }\n}\n@-ms-keyframes ui-grid-spin {\n  0% {\n    -moz-transform: rotate(0deg);\n    -o-transform: rotate(0deg);\n    -webkit-transform: rotate(0deg);\n    transform: rotate(0deg);\n  }\n  100% {\n    -moz-transform: rotate(359deg);\n    -o-transform: rotate(359deg);\n    -webkit-transform: rotate(359deg);\n    transform: rotate(359deg);\n  }\n}\n@keyframes ui-grid-spin {\n  0% {\n    -moz-transform: rotate(0deg);\n    -o-transform: rotate(0deg);\n    -webkit-transform: rotate(0deg);\n    transform: rotate(0deg);\n  }\n  100% {\n    -moz-transform: rotate(359deg);\n    -o-transform: rotate(359deg);\n    -webkit-transform: rotate(359deg);\n    transform: rotate(359deg);\n  }\n}\n/*---------------------------------------------------\n    LESS Elements 0.9\n  ---------------------------------------------------\n    A set of useful LESS mixins\n    More info at: http://lesselements.com\n  ---------------------------------------------------*/\n/* This file contains variable declarations (do not remove this line) */\n/*-- VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/\n/**\n* @section Grid styles\n*/\n/**\n* @section Header styles\n*/\n/** @description Colors for header gradient */\n/**\n* @section Grid body styles\n*/\n/** @description Colors used for row alternation */\n/**\n* @section Sort arrow colors\n*/\n/**\n* @section Scrollbar styles\n*/\n/**\n* @section font library path\n*/\n/*-- END VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/\n\n/* This file contains variable declarations (do not remove this line) */\n/*-- VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/\n/**\n* @section Grid styles\n*/\n/**\n* @section Header styles\n*/\n/** @description Colors for header gradient */\n/**\n* @section Grid body styles\n*/\n/** @description Colors used for row alternation */\n/**\n* @section Sort arrow colors\n*/\n/**\n* @section Scrollbar styles\n*/\n/**\n* @section font library path\n*/\n/*-- END VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/\n#ui-grid-twbs #ui-grid-twbs .form-horizontal .form-group:before,\n#ui-grid-twbs #ui-grid-twbs .form-horizontal .form-group:after,\n#ui-grid-twbs #ui-grid-twbs .btn-toolbar:before,\n#ui-grid-twbs #ui-grid-twbs .btn-toolbar:after,\n#ui-grid-twbs #ui-grid-twbs .btn-group-vertical > .btn-group:before,\n#ui-grid-twbs #ui-grid-twbs .btn-group-vertical > .btn-group:after {\n  content: \" \";\n  display: table;\n}\n#ui-grid-twbs #ui-grid-twbs .form-horizontal .form-group:after,\n#ui-grid-twbs #ui-grid-twbs .btn-toolbar:after,\n#ui-grid-twbs #ui-grid-twbs .btn-group-vertical > .btn-group:after {\n  clear: both;\n}\n.ui-grid-cell-focus {\n  outline: 0;\n  background-color: #b3c4c7;\n}\n.ui-grid-focuser {\n  position: absolute;\n  left: 0px;\n  top: 0px;\n  z-index: -1;\n  width: 100%;\n  height: 100%;\n}\n.ui-grid-focuser: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.ui-grid-offscreen {\n  display: block;\n  position: absolute;\n  left: -10000px;\n  top: -10000px;\n  clip: rect(0px, 0px, 0px, 0px);\n}\n\n/* This file contains variable declarations (do not remove this line) */\n/*-- VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/\n/**\n* @section Grid styles\n*/\n/**\n* @section Header styles\n*/\n/** @description Colors for header gradient */\n/**\n* @section Grid body styles\n*/\n/** @description Colors used for row alternation */\n/**\n* @section Sort arrow colors\n*/\n/**\n* @section Scrollbar styles\n*/\n/**\n* @section font library path\n*/\n/*-- END VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/\ndiv.ui-grid-cell input {\n  border-radius: inherit;\n  padding: 0;\n  width: 100%;\n  color: inherit;\n  height: auto;\n  font: inherit;\n  outline: none;\n}\ndiv.ui-grid-cell input:focus {\n  color: inherit;\n  outline: none;\n}\ndiv.ui-grid-cell input[type=\"checkbox\"] {\n  margin: 9px 0 0 6px;\n  width: auto;\n}\ndiv.ui-grid-cell input.ng-invalid {\n  border: 1px solid #fc8f8f;\n}\ndiv.ui-grid-cell input.ng-valid {\n  border: 1px solid #d4d4d4;\n}\n\n/* This file contains variable declarations (do not remove this line) */\n/*-- VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/\n/**\n* @section Grid styles\n*/\n/**\n* @section Header styles\n*/\n/** @description Colors for header gradient */\n/**\n* @section Grid body styles\n*/\n/** @description Colors used for row alternation */\n/**\n* @section Sort arrow colors\n*/\n/**\n* @section Scrollbar styles\n*/\n/**\n* @section font library path\n*/\n/*-- END VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/\n.expandableRow .ui-grid-row:nth-child(odd) .ui-grid-cell {\n  background-color: #fdfdfd;\n}\n.expandableRow .ui-grid-row:nth-child(even) .ui-grid-cell {\n  background-color: #f3f3f3;\n}\n.scrollFiller {\n  float: left;\n  border: 1px solid #d4d4d4;\n}\n\n/* This file contains variable declarations (do not remove this line) */\n/*-- VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/\n/**\n* @section Grid styles\n*/\n/**\n* @section Header styles\n*/\n/** @description Colors for header gradient */\n/**\n* @section Grid body styles\n*/\n/** @description Colors used for row alternation */\n/**\n* @section Sort arrow colors\n*/\n/**\n* @section Scrollbar styles\n*/\n/**\n* @section font library path\n*/\n/*-- END VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/\n\n/* This file contains variable declarations (do not remove this line) */\n/*-- VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/\n/**\n* @section Grid styles\n*/\n/**\n* @section Header styles\n*/\n/** @description Colors for header gradient */\n/**\n* @section Grid body styles\n*/\n/** @description Colors used for row alternation */\n/**\n* @section Sort arrow colors\n*/\n/**\n* @section Scrollbar styles\n*/\n/**\n* @section font library path\n*/\n/*-- END VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/\n.ui-grid-tree-header-row {\n  font-weight: bold !important;\n}\n\n/* This file contains variable declarations (do not remove this line) */\n/*-- VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/\n/**\n* @section Grid styles\n*/\n/**\n* @section Header styles\n*/\n/** @description Colors for header gradient */\n/**\n* @section Grid body styles\n*/\n/** @description Colors used for row alternation */\n/**\n* @section Sort arrow colors\n*/\n/**\n* @section Scrollbar styles\n*/\n/**\n* @section font library path\n*/\n/*-- END VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/\n\n/* This file contains variable declarations (do not remove this line) */\n/*-- VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/\n/**\n* @section Grid styles\n*/\n/**\n* @section Header styles\n*/\n/** @description Colors for header gradient */\n/**\n* @section Grid body styles\n*/\n/** @description Colors used for row alternation */\n/**\n* @section Sort arrow colors\n*/\n/**\n* @section Scrollbar styles\n*/\n/**\n* @section font library path\n*/\n/*-- END VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/\n.movingColumn {\n  position: absolute;\n  top: 0;\n  border: 1px solid #d4d4d4;\n  box-shadow: inset 0 0 14px rgba(0, 0, 0, 0.2);\n}\n.movingColumn .ui-grid-icon-angle-down {\n  display: none;\n}\n\n/* This file contains variable declarations (do not remove this line) */\n/*-- VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/\n/**\n* @section Grid styles\n*/\n/**\n* @section Header styles\n*/\n/** @description Colors for header gradient */\n/**\n* @section Grid body styles\n*/\n/** @description Colors used for row alternation */\n/**\n* @section Sort arrow colors\n*/\n/**\n* @section Scrollbar styles\n*/\n/**\n* @section font library path\n*/\n/*-- END VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/\n/*---------------------------------------------------\n    LESS Elements 0.9\n  ---------------------------------------------------\n    A set of useful LESS mixins\n    More info at: http://lesselements.com\n  ---------------------------------------------------*/\n#ui-grid-twbs #ui-grid-twbs .form-horizontal .form-group:before,\n#ui-grid-twbs #ui-grid-twbs .form-horizontal .form-group:after,\n#ui-grid-twbs #ui-grid-twbs .btn-toolbar:before,\n#ui-grid-twbs #ui-grid-twbs .btn-toolbar:after,\n#ui-grid-twbs #ui-grid-twbs .btn-group-vertical > .btn-group:before,\n#ui-grid-twbs #ui-grid-twbs .btn-group-vertical > .btn-group:after {\n  content: \" \";\n  display: table;\n}\n#ui-grid-twbs #ui-grid-twbs .form-horizontal .form-group:after,\n#ui-grid-twbs #ui-grid-twbs .btn-toolbar:after,\n#ui-grid-twbs #ui-grid-twbs .btn-group-vertical > .btn-group:after {\n  clear: both;\n}\n.ui-grid-pager-panel {\n  position: absolute;\n  left: 0;\n  bottom: 0;\n  width: 100%;\n  padding-top: 3px;\n  padding-bottom: 3px;\n}\n.ui-grid-pager-container {\n  float: left;\n}\n.ui-grid-pager-control {\n  margin-right: 10px;\n  margin-left: 10px;\n  min-width: 135px;\n  float: left;\n}\n.ui-grid-pager-control button {\n  height: 25px;\n  min-width: 26px;\n  display: inline-block;\n  margin-bottom: 0;\n  font-weight: normal;\n  text-align: center;\n  vertical-align: middle;\n  touch-action: manipulation;\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.42857143;\n  border-radius: 4px;\n  -webkit-user-select: none;\n  -moz-user-select: none;\n  -ms-user-select: none;\n  user-select: none;\n  color: #eeeeee;\n  background-color: #f3f3f3;\n  border-color: #cccccc;\n}\n.ui-grid-pager-control button:focus,\n.ui-grid-pager-control button:active:focus,\n.ui-grid-pager-control button.active:focus,\n.ui-grid-pager-control button.focus,\n.ui-grid-pager-control button:active.focus,\n.ui-grid-pager-control button.active.focus {\n  outline: thin dotted;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n.ui-grid-pager-control button:hover,\n.ui-grid-pager-control button:focus,\n.ui-grid-pager-control button.focus {\n  color: #333333;\n  text-decoration: none;\n}\n.ui-grid-pager-control button:active,\n.ui-grid-pager-control button.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.ui-grid-pager-control button.disabled,\n.ui-grid-pager-control button[disabled],\nfieldset[disabled] .ui-grid-pager-control button {\n  cursor: not-allowed;\n  opacity: 0.65;\n  filter: alpha(opacity=65);\n  -webkit-box-shadow: none;\n  box-shadow: none;\n}\na.ui-grid-pager-control button.disabled,\nfieldset[disabled] a.ui-grid-pager-control button {\n  pointer-events: none;\n}\n.ui-grid-pager-control button:focus,\n.ui-grid-pager-control button.focus {\n  color: #eeeeee;\n  background-color: #dadada;\n  border-color: #8c8c8c;\n}\n.ui-grid-pager-control button:hover {\n  color: #eeeeee;\n  background-color: #dadada;\n  border-color: #adadad;\n}\n.ui-grid-pager-control button:active,\n.ui-grid-pager-control button.active,\n.open > .dropdown-toggle.ui-grid-pager-control button {\n  color: #eeeeee;\n  background-color: #dadada;\n  border-color: #adadad;\n}\n.ui-grid-pager-control button:active:hover,\n.ui-grid-pager-control button.active:hover,\n.open > .dropdown-toggle.ui-grid-pager-control button:hover,\n.ui-grid-pager-control button:active:focus,\n.ui-grid-pager-control button.active:focus,\n.open > .dropdown-toggle.ui-grid-pager-control button:focus,\n.ui-grid-pager-control button:active.focus,\n.ui-grid-pager-control button.active.focus,\n.open > .dropdown-toggle.ui-grid-pager-control button.focus {\n  color: #eeeeee;\n  background-color: #c8c8c8;\n  border-color: #8c8c8c;\n}\n.ui-grid-pager-control button:active,\n.ui-grid-pager-control button.active,\n.open > .dropdown-toggle.ui-grid-pager-control button {\n  background-image: none;\n}\n.ui-grid-pager-control button.disabled,\n.ui-grid-pager-control button[disabled],\nfieldset[disabled] .ui-grid-pager-control button,\n.ui-grid-pager-control button.disabled:hover,\n.ui-grid-pager-control button[disabled]:hover,\nfieldset[disabled] .ui-grid-pager-control button:hover,\n.ui-grid-pager-control button.disabled:focus,\n.ui-grid-pager-control button[disabled]:focus,\nfieldset[disabled] .ui-grid-pager-control button:focus,\n.ui-grid-pager-control button.disabled.focus,\n.ui-grid-pager-control button[disabled].focus,\nfieldset[disabled] .ui-grid-pager-control button.focus,\n.ui-grid-pager-control button.disabled:active,\n.ui-grid-pager-control button[disabled]:active,\nfieldset[disabled] .ui-grid-pager-control button:active,\n.ui-grid-pager-control button.disabled.active,\n.ui-grid-pager-control button[disabled].active,\nfieldset[disabled] .ui-grid-pager-control button.active {\n  background-color: #f3f3f3;\n  border-color: #cccccc;\n}\n.ui-grid-pager-control button .badge {\n  color: #f3f3f3;\n  background-color: #eeeeee;\n}\n.ui-grid-pager-control input {\n  display: block;\n  width: 100%;\n  height: 34px;\n  padding: 6px 12px;\n  font-size: 14px;\n  line-height: 1.42857143;\n  color: #555555;\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  -o-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  height: 30px;\n  padding: 5px 10px;\n  font-size: 12px;\n  line-height: 1.5;\n  border-radius: 3px;\n  display: inline;\n  height: 26px;\n  width: 50px;\n  vertical-align: top;\n}\n.ui-grid-pager-control input: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.ui-grid-pager-control input::-moz-placeholder {\n  color: #999999;\n  opacity: 1;\n}\n.ui-grid-pager-control input:-ms-input-placeholder {\n  color: #999999;\n}\n.ui-grid-pager-control input::-webkit-input-placeholder {\n  color: #999999;\n}\n.ui-grid-pager-control input[disabled],\n.ui-grid-pager-control input[readonly],\nfieldset[disabled] .ui-grid-pager-control input {\n  background-color: #eeeeee;\n  opacity: 1;\n}\n.ui-grid-pager-control input[disabled],\nfieldset[disabled] .ui-grid-pager-control input {\n  cursor: not-allowed;\n}\ntextarea.ui-grid-pager-control input {\n  height: auto;\n}\nselect.ui-grid-pager-control input {\n  height: 30px;\n  line-height: 30px;\n}\ntextarea.ui-grid-pager-control input,\nselect[multiple].ui-grid-pager-control input {\n  height: auto;\n}\n.ui-grid-pager-control .ui-grid-pager-max-pages-number {\n  vertical-align: bottom;\n}\n.ui-grid-pager-control .ui-grid-pager-max-pages-number > * {\n  vertical-align: middle;\n}\n.ui-grid-pager-control .first-bar {\n  width: 10px;\n  border-left: 2px solid #4d4d4d;\n  margin-top: -6px;\n  height: 12px;\n  margin-left: -3px;\n}\n.ui-grid-pager-control .first-triangle {\n  width: 0;\n  height: 0;\n  border-style: solid;\n  border-width: 5px 8.7px 5px 0;\n  border-color: transparent #4d4d4d transparent transparent;\n  margin-left: 2px;\n}\n.ui-grid-pager-control .next-triangle {\n  margin-left: 1px;\n}\n.ui-grid-pager-control .prev-triangle {\n  margin-left: 0;\n}\n.ui-grid-pager-control .last-triangle {\n  width: 0;\n  height: 0;\n  border-style: solid;\n  border-width: 5px 0 5px 8.7px;\n  border-color: transparent transparent transparent #4d4d4d;\n  margin-left: -1px;\n}\n.ui-grid-pager-control .last-bar {\n  width: 10px;\n  border-left: 2px solid #4d4d4d;\n  margin-top: -6px;\n  height: 12px;\n  margin-left: 1px;\n}\n.ui-grid-pager-row-count-picker {\n  float: left;\n}\n.ui-grid-pager-row-count-picker select {\n  display: block;\n  width: 100%;\n  height: 34px;\n  padding: 6px 12px;\n  font-size: 14px;\n  line-height: 1.42857143;\n  color: #555555;\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  -o-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  height: 30px;\n  padding: 5px 10px;\n  font-size: 12px;\n  line-height: 1.5;\n  border-radius: 3px;\n  height: 26px;\n  width: 60px;\n  display: inline;\n}\n.ui-grid-pager-row-count-picker select: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.ui-grid-pager-row-count-picker select::-moz-placeholder {\n  color: #999999;\n  opacity: 1;\n}\n.ui-grid-pager-row-count-picker select:-ms-input-placeholder {\n  color: #999999;\n}\n.ui-grid-pager-row-count-picker select::-webkit-input-placeholder {\n  color: #999999;\n}\n.ui-grid-pager-row-count-picker select[disabled],\n.ui-grid-pager-row-count-picker select[readonly],\nfieldset[disabled] .ui-grid-pager-row-count-picker select {\n  background-color: #eeeeee;\n  opacity: 1;\n}\n.ui-grid-pager-row-count-picker select[disabled],\nfieldset[disabled] .ui-grid-pager-row-count-picker select {\n  cursor: not-allowed;\n}\ntextarea.ui-grid-pager-row-count-picker select {\n  height: auto;\n}\nselect.ui-grid-pager-row-count-picker select {\n  height: 30px;\n  line-height: 30px;\n}\ntextarea.ui-grid-pager-row-count-picker select,\nselect[multiple].ui-grid-pager-row-count-picker select {\n  height: auto;\n}\n.ui-grid-pager-row-count-picker .ui-grid-pager-row-count-label {\n  margin-top: 3px;\n}\n.ui-grid-pager-count-container {\n  float: right;\n  margin-top: 4px;\n  min-width: 50px;\n}\n.ui-grid-pager-count-container .ui-grid-pager-count {\n  margin-right: 10px;\n  margin-left: 10px;\n  float: right;\n}\n\n/* This file contains variable declarations (do not remove this line) */\n/*-- VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/\n/**\n* @section Grid styles\n*/\n/**\n* @section Header styles\n*/\n/** @description Colors for header gradient */\n/**\n* @section Grid body styles\n*/\n/** @description Colors used for row alternation */\n/**\n* @section Sort arrow colors\n*/\n/**\n* @section Scrollbar styles\n*/\n/**\n* @section font library path\n*/\n/*-- END VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/\n.ui-grid-pinned-container {\n  position: absolute;\n  display: inline;\n  top: 0;\n}\n.ui-grid-pinned-container.ui-grid-pinned-container-left {\n  float: left;\n  left: 0;\n}\n.ui-grid-pinned-container.ui-grid-pinned-container-right {\n  float: right;\n  right: 0;\n}\n.ui-grid-pinned-container.ui-grid-pinned-container-left .ui-grid-header-cell:last-child {\n  box-sizing: border-box;\n  border-right: 1px solid;\n  border-width: 1px;\n  border-right-color: #aeaeae;\n}\n.ui-grid-pinned-container.ui-grid-pinned-container-left .ui-grid-cell:last-child {\n  box-sizing: border-box;\n  border-right: 1px solid;\n  border-width: 1px;\n  border-right-color: #aeaeae;\n}\n.ui-grid-pinned-container.ui-grid-pinned-container-left .ui-grid-header-cell:not(:last-child) .ui-grid-vertical-bar,\n.ui-grid-pinned-container .ui-grid-cell:not(:last-child) .ui-grid-vertical-bar {\n  width: 1px;\n}\n.ui-grid-pinned-container.ui-grid-pinned-container-left .ui-grid-header-cell:not(:last-child) .ui-grid-vertical-bar {\n  background-color: #d4d4d4;\n}\n.ui-grid-pinned-container.ui-grid-pinned-container-left .ui-grid-cell:not(:last-child) .ui-grid-vertical-bar {\n  background-color: #aeaeae;\n}\n.ui-grid-pinned-container.ui-grid-pinned-container-left .ui-grid-header-cell:last-child .ui-grid-vertical-bar {\n  right: -1px;\n  width: 1px;\n  background-color: #aeaeae;\n}\n.ui-grid-pinned-container.ui-grid-pinned-container-right .ui-grid-header-cell:first-child {\n  box-sizing: border-box;\n  border-left: 1px solid;\n  border-width: 1px;\n  border-left-color: #aeaeae;\n}\n.ui-grid-pinned-container.ui-grid-pinned-container-right .ui-grid-cell:first-child {\n  box-sizing: border-box;\n  border-left: 1px solid;\n  border-width: 1px;\n  border-left-color: #aeaeae;\n}\n.ui-grid-pinned-container.ui-grid-pinned-container-right .ui-grid-header-cell:not(:first-child) .ui-grid-vertical-bar,\n.ui-grid-pinned-container .ui-grid-cell:not(:first-child) .ui-grid-vertical-bar {\n  width: 1px;\n}\n.ui-grid-pinned-container.ui-grid-pinned-container-right .ui-grid-header-cell:not(:first-child) .ui-grid-vertical-bar {\n  background-color: #d4d4d4;\n}\n.ui-grid-pinned-container.ui-grid-pinned-container-right .ui-grid-cell:not(:last-child) .ui-grid-vertical-bar {\n  background-color: #aeaeae;\n}\n.ui-grid-pinned-container.ui-grid-pinned-container-first .ui-grid-header-cell:first-child .ui-grid-vertical-bar {\n  left: -1px;\n  width: 1px;\n  background-color: #aeaeae;\n}\n\n/* This file contains variable declarations (do not remove this line) */\n/*-- VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/\n/**\n* @section Grid styles\n*/\n/**\n* @section Header styles\n*/\n/** @description Colors for header gradient */\n/**\n* @section Grid body styles\n*/\n/** @description Colors used for row alternation */\n/**\n* @section Sort arrow colors\n*/\n/**\n* @section Scrollbar styles\n*/\n/**\n* @section font library path\n*/\n/*-- END VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/\n.ui-grid-column-resizer {\n  top: 0;\n  bottom: 0;\n  width: 5px;\n  position: absolute;\n  cursor: col-resize;\n}\n.ui-grid-column-resizer.left {\n  left: 0;\n}\n.ui-grid-column-resizer.right {\n  right: 0;\n}\n.ui-grid-header-cell:last-child .ui-grid-column-resizer.right {\n  border-right: 1px solid #d4d4d4;\n}\n.ui-grid[dir=rtl] .ui-grid-header-cell:last-child .ui-grid-column-resizer.right {\n  border-right: 0;\n}\n.ui-grid[dir=rtl] .ui-grid-header-cell:last-child .ui-grid-column-resizer.left {\n  border-left: 1px solid #d4d4d4;\n}\n.ui-grid.column-resizing {\n  cursor: col-resize;\n}\n.ui-grid.column-resizing .ui-grid-resize-overlay {\n  position: absolute;\n  top: 0;\n  height: 100%;\n  width: 1px;\n  background-color: #aeaeae;\n}\n\n/* This file contains variable declarations (do not remove this line) */\n/*-- VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/\n/**\n* @section Grid styles\n*/\n/**\n* @section Header styles\n*/\n/** @description Colors for header gradient */\n/**\n* @section Grid body styles\n*/\n/** @description Colors used for row alternation */\n/**\n* @section Sort arrow colors\n*/\n/**\n* @section Scrollbar styles\n*/\n/**\n* @section font library path\n*/\n/*-- END VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/\n.ui-grid-row-saving .ui-grid-cell {\n  color: #848484 !important;\n}\n.ui-grid-row-dirty .ui-grid-cell {\n  color: #610b38;\n}\n.ui-grid-row-error .ui-grid-cell {\n  color: #ff0000 !important;\n}\n\n/* This file contains variable declarations (do not remove this line) */\n/*-- VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/\n/**\n* @section Grid styles\n*/\n/**\n* @section Header styles\n*/\n/** @description Colors for header gradient */\n/**\n* @section Grid body styles\n*/\n/** @description Colors used for row alternation */\n/**\n* @section Sort arrow colors\n*/\n/**\n* @section Scrollbar styles\n*/\n/**\n* @section font library path\n*/\n/*-- END VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/\n.ui-grid-row.ui-grid-row-selected > [ui-grid-row] > .ui-grid-cell {\n  background-color: #c9dde1;\n}\n.ui-grid-disable-selection {\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  cursor: default;\n}\n.ui-grid-selection-row-header-buttons {\n  cursor: pointer;\n  opacity: 0.1;\n}\n.ui-grid-selection-row-header-buttons.ui-grid-row-selected {\n  opacity: 1;\n}\n.ui-grid-selection-row-header-buttons.ui-grid-all-selected {\n  opacity: 1;\n}\n\n/* This file contains variable declarations (do not remove this line) */\n/*-- VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/\n/**\n* @section Grid styles\n*/\n/**\n* @section Header styles\n*/\n/** @description Colors for header gradient */\n/**\n* @section Grid body styles\n*/\n/** @description Colors used for row alternation */\n/**\n* @section Sort arrow colors\n*/\n/**\n* @section Scrollbar styles\n*/\n/**\n* @section font library path\n*/\n/*-- END VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/\n.ui-grid-tree-row-header-buttons.ui-grid-tree-header {\n  cursor: pointer;\n  opacity: 1;\n}\n\n/* This file contains variable declarations (do not remove this line) */\n/*-- VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/\n/**\n* @section Grid styles\n*/\n/**\n* @section Header styles\n*/\n/** @description Colors for header gradient */\n/**\n* @section Grid body styles\n*/\n/** @description Colors used for row alternation */\n/**\n* @section Sort arrow colors\n*/\n/**\n* @section Scrollbar styles\n*/\n/**\n* @section font library path\n*/\n/*-- END VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/\n.ui-grid-tree-header-row {\n  font-weight: bold !important;\n}\n\n.ui-grid-icon-plus-squared:before {\n  content: '\\c350';\n}\n/* '썐' */\n.ui-grid-icon-minus-squared:before {\n  content: '\\c351';\n}\n/* '썑' */\n.ui-grid-icon-search:before {\n  content: '\\c352';\n}\n/* '썒' */\n.ui-grid-icon-cancel:before {\n  content: '\\c353';\n}\n/* '썓' */\n.ui-grid-icon-info-circled:before {\n  content: '\\c354';\n}\n/* '썔' */\n.ui-grid-icon-lock:before {\n  content: '\\c355';\n}\n/* '썕' */\n.ui-grid-icon-lock-open:before {\n  content: '\\c356';\n}\n/* '썖' */\n.ui-grid-icon-pencil:before {\n  content: '\\c357';\n}\n/* '썗' */\n.ui-grid-icon-down-dir:before {\n  content: '\\c358';\n}\n/* '썘' */\n.ui-grid-icon-up-dir:before {\n  content: '\\c359';\n}\n/* '썙' */\n.ui-grid-icon-left-dir:before {\n  content: '\\c35a';\n}\n/* '썚' */\n.ui-grid-icon-right-dir:before {\n  content: '\\c35b';\n}\n/* '썛' */\n.ui-grid-icon-left-open:before {\n  content: '\\c35c';\n}\n/* '썜' */\n.ui-grid-icon-right-open:before {\n  content: '\\c35d';\n}\n/* '썝' */\n.ui-grid-icon-angle-down:before {\n  content: '\\c35e';\n}\n/* '썞' */\n.ui-grid-icon-filter:before {\n  content: '\\c35f';\n}\n/* '썟' */\n.ui-grid-icon-sort-alt-up:before {\n  content: '\\c360';\n}\n/* '썠' */\n.ui-grid-icon-sort-alt-down:before {\n  content: '\\c361';\n}\n/* '썡' */\n.ui-grid-icon-ok:before {\n  content: '\\c362';\n}\n/* '썢' */\n.ui-grid-icon-menu:before {\n  content: '\\c363';\n}\n/* '썣' */\n.ui-grid-icon-indent-left:before {\n  content: '\\e800';\n}\n/* '' */\n.ui-grid-icon-indent-right:before {\n  content: '\\e801';\n}\n/* '' */\n.ui-grid-icon-spin5:before {\n  content: '\\ea61';\n}\n/* '' */\n"
  },
  {
    "path": "flowable-ui-web/admin/additional_components/ui-grid/ui-grid.js",
    "content": "/*!\n * ui-grid - v3.0.4 - 2015-08-13\n * Copyright (c) 2015 ; License: MIT \n */\n\n(function () {\n  'use strict';\n  angular.module('ui.grid.i18n', []);\n  angular.module('ui.grid', ['ui.grid.i18n']);\n})();\n(function () {\n  'use strict';\n  angular.module('ui.grid').constant('uiGridConstants', {\n    LOG_DEBUG_MESSAGES: true,\n    LOG_WARN_MESSAGES: true,\n    LOG_ERROR_MESSAGES: true,\n    CUSTOM_FILTERS: /CUSTOM_FILTERS/g,\n    COL_FIELD: /COL_FIELD/g,\n    MODEL_COL_FIELD: /MODEL_COL_FIELD/g,\n    TOOLTIP: /title=\\\"TOOLTIP\\\"/g,\n    DISPLAY_CELL_TEMPLATE: /DISPLAY_CELL_TEMPLATE/g,\n    TEMPLATE_REGEXP: /<.+>/,\n    FUNC_REGEXP: /(\\([^)]*\\))?$/,\n    DOT_REGEXP: /\\./g,\n    APOS_REGEXP: /'/g,\n    BRACKET_REGEXP: /^(.*)((?:\\s*\\[\\s*\\d+\\s*\\]\\s*)|(?:\\s*\\[\\s*\"(?:[^\"\\\\]|\\\\.)*\"\\s*\\]\\s*)|(?:\\s*\\[\\s*'(?:[^'\\\\]|\\\\.)*'\\s*\\]\\s*))(.*)$/,\n    COL_CLASS_PREFIX: 'ui-grid-col',\n    events: {\n      GRID_SCROLL: 'uiGridScroll',\n      COLUMN_MENU_SHOWN: 'uiGridColMenuShown',\n      ITEM_DRAGGING: 'uiGridItemDragStart', // For any item being dragged\n      COLUMN_HEADER_CLICK: 'uiGridColumnHeaderClick'\n    },\n    // copied from http://www.lsauer.com/2011/08/javascript-keymap-keycodes-in-json.html\n    keymap: {\n      TAB: 9,\n      STRG: 17,\n      CAPSLOCK: 20,\n      CTRL: 17,\n      CTRLRIGHT: 18,\n      CTRLR: 18,\n      SHIFT: 16,\n      RETURN: 13,\n      ENTER: 13,\n      BACKSPACE: 8,\n      BCKSP: 8,\n      ALT: 18,\n      ALTR: 17,\n      ALTRIGHT: 17,\n      SPACE: 32,\n      WIN: 91,\n      MAC: 91,\n      FN: null,\n      PG_UP: 33,\n      PG_DOWN: 34,\n      UP: 38,\n      DOWN: 40,\n      LEFT: 37,\n      RIGHT: 39,\n      ESC: 27,\n      DEL: 46,\n      F1: 112,\n      F2: 113,\n      F3: 114,\n      F4: 115,\n      F5: 116,\n      F6: 117,\n      F7: 118,\n      F8: 119,\n      F9: 120,\n      F10: 121,\n      F11: 122,\n      F12: 123\n    },\n    ASC: 'asc',\n    DESC: 'desc',\n    filter: {\n      STARTS_WITH: 2,\n      ENDS_WITH: 4,\n      EXACT: 8,\n      CONTAINS: 16,\n      GREATER_THAN: 32,\n      GREATER_THAN_OR_EQUAL: 64,\n      LESS_THAN: 128,\n      LESS_THAN_OR_EQUAL: 256,\n      NOT_EQUAL: 512,\n      SELECT: 'select',\n      INPUT: 'input'\n    },\n\n    aggregationTypes: {\n      sum: 2,\n      count: 4,\n      avg: 8,\n      min: 16,\n      max: 32\n    },\n\n    // TODO(c0bra): Create full list of these somehow. NOTE: do any allow a space before or after them?\n    CURRENCY_SYMBOLS: ['ƒ', '$', '£', '$', '¤', '¥', '៛', '₩', '₱', '฿', '₫'],\n\n    scrollDirection: {\n      UP: 'up',\n      DOWN: 'down',\n      LEFT: 'left',\n      RIGHT: 'right',\n      NONE: 'none'\n\n    },\n\n    dataChange: {\n      ALL: 'all',\n      EDIT: 'edit',\n      ROW: 'row',\n      COLUMN: 'column',\n      OPTIONS: 'options'\n    },\n    scrollbars: {\n      NEVER: 0,\n      ALWAYS: 1\n      //WHEN_NEEDED: 2\n    }\n  });\n\n})();\nangular.module('ui.grid').directive('uiGridCell', ['$compile', '$parse', 'gridUtil', 'uiGridConstants', function ($compile, $parse, gridUtil, uiGridConstants) {\n  var uiGridCell = {\n    priority: 0,\n    scope: false,\n    require: '?^uiGrid',\n    compile: function() {\n      return {\n        pre: function($scope, $elm, $attrs, uiGridCtrl) {\n          function compileTemplate() {\n            var compiledElementFn = $scope.col.compiledElementFn;\n\n            compiledElementFn($scope, function(clonedElement, scope) {\n              $elm.append(clonedElement);\n            });\n          }\n\n          // If the grid controller is present, use it to get the compiled cell template function\n          if (uiGridCtrl && $scope.col.compiledElementFn) {\n             compileTemplate();\n          }\n          // No controller, compile the element manually (for unit tests)\n          else {\n            if ( uiGridCtrl && !$scope.col.compiledElementFn ){\n              // gridUtil.logError('Render has been called before precompile.  Please log a ui-grid issue');  \n\n              $scope.col.getCompiledElementFn()\n                .then(function (compiledElementFn) {\n                  compiledElementFn($scope, function(clonedElement, scope) {\n                    $elm.append(clonedElement);\n                  });\n                });\n            }\n            else {\n              var html = $scope.col.cellTemplate\n                .replace(uiGridConstants.MODEL_COL_FIELD, 'row.entity.' + gridUtil.preEval($scope.col.field))\n                .replace(uiGridConstants.COL_FIELD, 'grid.getCellValue(row, col)');\n\n              var cellElement = $compile(html)($scope);\n              $elm.append(cellElement);\n            }\n          }\n        },\n        post: function($scope, $elm, $attrs, uiGridCtrl) {\n          var initColClass = $scope.col.getColClass(false);\n          $elm.addClass(initColClass);\n\n          var classAdded;\n          var updateClass = function( grid ){\n            var contents = $elm;\n            if ( classAdded ){\n              contents.removeClass( classAdded );\n              classAdded = null;\n            }\n\n            if (angular.isFunction($scope.col.cellClass)) {\n              classAdded = $scope.col.cellClass($scope.grid, $scope.row, $scope.col, $scope.rowRenderIndex, $scope.colRenderIndex);\n            }\n            else {\n              classAdded = $scope.col.cellClass;\n            }\n            contents.addClass(classAdded);\n          };\n\n          if ($scope.col.cellClass) {\n            updateClass();\n          }\n          \n          // Register a data change watch that would get triggered whenever someone edits a cell or modifies column defs\n          var dataChangeDereg = $scope.grid.registerDataChangeCallback( updateClass, [uiGridConstants.dataChange.COLUMN, uiGridConstants.dataChange.EDIT]);\n          \n          // watch the col and row to see if they change - which would indicate that we've scrolled or sorted or otherwise\n          // changed the row/col that this cell relates to, and we need to re-evaluate cell classes and maybe other things\n          var cellChangeFunction = function( n, o ){\n            if ( n !== o ) {\n              if ( classAdded || $scope.col.cellClass ){\n                updateClass();\n              }\n\n              // See if the column's internal class has changed\n              var newColClass = $scope.col.getColClass(false);\n              if (newColClass !== initColClass) {\n                $elm.removeClass(initColClass);\n                $elm.addClass(newColClass);\n                initColClass = newColClass;\n              }\n            }\n          };\n\n          // TODO(c0bra): Turn this into a deep array watch\n/*        shouldn't be needed any more given track by col.name\n          var colWatchDereg = $scope.$watch( 'col', cellChangeFunction );\n*/\n          var rowWatchDereg = $scope.$watch( 'row', cellChangeFunction );\n          \n          \n          var deregisterFunction = function() {\n            dataChangeDereg();\n//            colWatchDereg();\n            rowWatchDereg(); \n          };\n          \n          $scope.$on( '$destroy', deregisterFunction );\n          $elm.on( '$destroy', deregisterFunction );\n        }\n      };\n    }\n  };\n\n  return uiGridCell;\n}]);\n\n\n(function(){\n\nangular.module('ui.grid')\n.service('uiGridColumnMenuService', [ 'i18nService', 'uiGridConstants', 'gridUtil',\nfunction ( i18nService, uiGridConstants, gridUtil ) {\n/**\n *  @ngdoc service\n *  @name ui.grid.service:uiGridColumnMenuService\n *\n *  @description Services for working with column menus, factored out\n *  to make the code easier to understand\n */\n\n  var service = {\n    /**\n     * @ngdoc method\n     * @methodOf ui.grid.service:uiGridColumnMenuService\n     * @name initialize\n     * @description  Sets defaults, puts a reference to the $scope on\n     * the uiGridController\n     * @param {$scope} $scope the $scope from the uiGridColumnMenu\n     * @param {controller} uiGridCtrl the uiGridController for the grid\n     * we're on\n     *\n     */\n    initialize: function( $scope, uiGridCtrl ){\n      $scope.grid = uiGridCtrl.grid;\n\n      // Store a reference to this link/controller in the main uiGrid controller\n      // to allow showMenu later\n      uiGridCtrl.columnMenuScope = $scope;\n\n      // Save whether we're shown or not so the columns can check\n      $scope.menuShown = false;\n    },\n\n\n    /**\n     * @ngdoc method\n     * @methodOf ui.grid.service:uiGridColumnMenuService\n     * @name setColMenuItemWatch\n     * @description  Setup a watch on $scope.col.menuItems, and update\n     * menuItems based on this.  $scope.col needs to be set by the column\n     * before calling the menu.\n     * @param {$scope} $scope the $scope from the uiGridColumnMenu\n     * @param {controller} uiGridCtrl the uiGridController for the grid\n     * we're on\n     *\n     */\n    setColMenuItemWatch: function ( $scope ){\n      var deregFunction = $scope.$watch('col.menuItems', function (n, o) {\n        if (typeof(n) !== 'undefined' && n && angular.isArray(n)) {\n          n.forEach(function (item) {\n            if (typeof(item.context) === 'undefined' || !item.context) {\n              item.context = {};\n            }\n            item.context.col = $scope.col;\n          });\n\n          $scope.menuItems = $scope.defaultMenuItems.concat(n);\n        }\n        else {\n          $scope.menuItems = $scope.defaultMenuItems;\n        }\n      });\n\n      $scope.$on( '$destroy', deregFunction );\n    },\n\n\n    /**\n     * @ngdoc boolean\n     * @name enableSorting\n     * @propertyOf ui.grid.class:GridOptions.columnDef\n     * @description (optional) True by default. When enabled, this setting adds sort\n     * widgets to the column header, allowing sorting of the data in the individual column.\n     */\n    /**\n     * @ngdoc method\n     * @methodOf ui.grid.service:uiGridColumnMenuService\n     * @name sortable\n     * @description  determines whether this column is sortable\n     * @param {$scope} $scope the $scope from the uiGridColumnMenu\n     *\n     */\n    sortable: function( $scope ) {\n      if ( $scope.grid.options.enableSorting && typeof($scope.col) !== 'undefined' && $scope.col && $scope.col.enableSorting) {\n        return true;\n      }\n      else {\n        return false;\n      }\n    },\n\n    /**\n     * @ngdoc method\n     * @methodOf ui.grid.service:uiGridColumnMenuService\n     * @name isActiveSort\n     * @description  determines whether the requested sort direction is current active, to\n     * allow highlighting in the menu\n     * @param {$scope} $scope the $scope from the uiGridColumnMenu\n     * @param {string} direction the direction that we'd have selected for us to be active\n     *\n     */\n    isActiveSort: function( $scope, direction ){\n      return (typeof($scope.col) !== 'undefined' && typeof($scope.col.sort) !== 'undefined' &&\n              typeof($scope.col.sort.direction) !== 'undefined' && $scope.col.sort.direction === direction);\n\n    },\n\n    /**\n     * @ngdoc method\n     * @methodOf ui.grid.service:uiGridColumnMenuService\n     * @name suppressRemoveSort\n     * @description  determines whether we should suppress the removeSort option\n     * @param {$scope} $scope the $scope from the uiGridColumnMenu\n     *\n     */\n    suppressRemoveSort: function( $scope ) {\n      if ($scope.col && $scope.col.suppressRemoveSort) {\n        return true;\n      }\n      else {\n        return false;\n      }\n    },\n\n\n    /**\n     * @ngdoc boolean\n     * @name enableHiding\n     * @propertyOf ui.grid.class:GridOptions.columnDef\n     * @description (optional) True by default. When set to false, this setting prevents a user from hiding the column\n     * using the column menu or the grid menu.\n     */\n    /**\n     * @ngdoc method\n     * @methodOf ui.grid.service:uiGridColumnMenuService\n     * @name hideable\n     * @description  determines whether a column can be hidden, by checking the enableHiding columnDef option\n     * @param {$scope} $scope the $scope from the uiGridColumnMenu\n     *\n     */\n    hideable: function( $scope ) {\n      if (typeof($scope.col) !== 'undefined' && $scope.col && $scope.col.colDef && $scope.col.colDef.enableHiding === false ) {\n        return false;\n      }\n      else {\n        return true;\n      }\n    },\n\n\n    /**\n     * @ngdoc method\n     * @methodOf ui.grid.service:uiGridColumnMenuService\n     * @name getDefaultMenuItems\n     * @description  returns the default menu items for a column menu\n     * @param {$scope} $scope the $scope from the uiGridColumnMenu\n     *\n     */\n    getDefaultMenuItems: function( $scope ){\n      return [\n        {\n          title: i18nService.getSafeText('sort.ascending'),\n          icon: 'ui-grid-icon-sort-alt-up',\n          action: function($event) {\n            $event.stopPropagation();\n            $scope.sortColumn($event, uiGridConstants.ASC);\n          },\n          shown: function () {\n            return service.sortable( $scope );\n          },\n          active: function() {\n            return service.isActiveSort( $scope, uiGridConstants.ASC);\n          }\n        },\n        {\n          title: i18nService.getSafeText('sort.descending'),\n          icon: 'ui-grid-icon-sort-alt-down',\n          action: function($event) {\n            $event.stopPropagation();\n            $scope.sortColumn($event, uiGridConstants.DESC);\n          },\n          shown: function() {\n            return service.sortable( $scope );\n          },\n          active: function() {\n            return service.isActiveSort( $scope, uiGridConstants.DESC);\n          }\n        },\n        {\n          title: i18nService.getSafeText('sort.remove'),\n          icon: 'ui-grid-icon-cancel',\n          action: function ($event) {\n            $event.stopPropagation();\n            $scope.unsortColumn();\n          },\n          shown: function() {\n            return service.sortable( $scope ) &&\n                   typeof($scope.col) !== 'undefined' && (typeof($scope.col.sort) !== 'undefined' &&\n                   typeof($scope.col.sort.direction) !== 'undefined') && $scope.col.sort.direction !== null &&\n                  !service.suppressRemoveSort( $scope );\n          }\n        },\n        {\n          title: i18nService.getSafeText('column.hide'),\n          icon: 'ui-grid-icon-cancel',\n          shown: function() {\n            return service.hideable( $scope );\n          },\n          action: function ($event) {\n            $event.stopPropagation();\n            $scope.hideColumn();\n          }\n        },\n        {\n          title: i18nService.getSafeText('columnMenu.close'),\n          screenReaderOnly: true,\n          shown: function(){\n            return true;\n          },\n          action: function($event){\n            $event.stopPropagation();\n          }\n        }\n      ];\n    },\n\n\n    /**\n     * @ngdoc method\n     * @methodOf ui.grid.service:uiGridColumnMenuService\n     * @name getColumnElementPosition\n     * @description  gets the position information needed to place the column\n     * menu below the column header\n     * @param {$scope} $scope the $scope from the uiGridColumnMenu\n     * @param {GridCol} column the column we want to position below\n     * @param {element} $columnElement the column element we want to position below\n     * @returns {hash} containing left, top, offset, height, width\n     *\n     */\n    getColumnElementPosition: function( $scope, column, $columnElement ){\n      var positionData = {};\n      positionData.left = $columnElement[0].offsetLeft;\n      positionData.top = $columnElement[0].offsetTop;\n      positionData.parentLeft = $columnElement[0].offsetParent.offsetLeft;\n\n      // Get the grid scrollLeft\n      positionData.offset = 0;\n      if (column.grid.options.offsetLeft) {\n        positionData.offset = column.grid.options.offsetLeft;\n      }\n\n      positionData.height = gridUtil.elementHeight($columnElement, true);\n      positionData.width = gridUtil.elementWidth($columnElement, true);\n\n      return positionData;\n    },\n\n\n    /**\n     * @ngdoc method\n     * @methodOf ui.grid.service:uiGridColumnMenuService\n     * @name repositionMenu\n     * @description  Reposition the menu below the new column.  If the menu has no child nodes\n     * (i.e. it's not currently visible) then we guess it's width at 100, we'll be called again\n     * later to fix it\n     * @param {$scope} $scope the $scope from the uiGridColumnMenu\n     * @param {GridCol} column the column we want to position below\n     * @param {hash} positionData a hash containing left, top, offset, height, width\n     * @param {element} $elm the column menu element that we want to reposition\n     * @param {element} $columnElement the column element that we want to reposition underneath\n     *\n     */\n    repositionMenu: function( $scope, column, positionData, $elm, $columnElement ) {\n      var menu = $elm[0].querySelectorAll('.ui-grid-menu');\n      var containerId = column.renderContainer ? column.renderContainer : 'body';\n      var renderContainer = column.grid.renderContainers[containerId];\n\n      // It's possible that the render container of the column we're attaching to is\n      // offset from the grid (i.e. pinned containers), we need to get the difference in the offsetLeft\n      // between the render container and the grid\n      var renderContainerElm = gridUtil.closestElm($columnElement, '.ui-grid-render-container');\n      var renderContainerOffset = renderContainerElm.getBoundingClientRect().left - $scope.grid.element[0].getBoundingClientRect().left;\n\n      var containerScrollLeft = renderContainerElm.querySelectorAll('.ui-grid-viewport')[0].scrollLeft;\n\n      // default value the last width for _this_ column, otherwise last width for _any_ column, otherwise default to 170\n      var myWidth = column.lastMenuWidth ? column.lastMenuWidth : ( $scope.lastMenuWidth ? $scope.lastMenuWidth : 170);\n      var paddingRight = column.lastMenuPaddingRight ? column.lastMenuPaddingRight : ( $scope.lastMenuPaddingRight ? $scope.lastMenuPaddingRight : 10);\n\n      if ( menu.length !== 0 ){\n        var mid = menu[0].querySelectorAll('.ui-grid-menu-mid');\n        if ( mid.length !== 0 && !angular.element(mid).hasClass('ng-hide') ) {\n          myWidth = gridUtil.elementWidth(menu, true);\n          $scope.lastMenuWidth = myWidth;\n          column.lastMenuWidth = myWidth;\n\n          // TODO(c0bra): use padding-left/padding-right based on document direction (ltr/rtl), place menu on proper side\n          // Get the column menu right padding\n          paddingRight = parseInt(gridUtil.getStyles(angular.element(menu)[0])['paddingRight'], 10);\n          $scope.lastMenuPaddingRight = paddingRight;\n          column.lastMenuPaddingRight = paddingRight;\n        }\n      }\n\n      var left = positionData.left + renderContainerOffset - containerScrollLeft + positionData.parentLeft + positionData.width - myWidth + paddingRight;\n      if (left < positionData.offset){\n        left = positionData.offset;\n      }\n\n      $elm.css('left', left + 'px');\n      $elm.css('top', (positionData.top + positionData.height) + 'px');\n    }\n\n  };\n\n  return service;\n}])\n\n\n.directive('uiGridColumnMenu', ['$timeout', 'gridUtil', 'uiGridConstants', 'uiGridColumnMenuService', '$document',\nfunction ($timeout, gridUtil, uiGridConstants, uiGridColumnMenuService, $document) {\n/**\n * @ngdoc directive\n * @name ui.grid.directive:uiGridColumnMenu\n * @description  Provides the column menu framework, leverages uiGridMenu underneath\n *\n */\n\n  var uiGridColumnMenu = {\n    priority: 0,\n    scope: true,\n    require: '^uiGrid',\n    templateUrl: 'ui-grid/uiGridColumnMenu',\n    replace: true,\n    link: function ($scope, $elm, $attrs, uiGridCtrl) {\n      var self = this;\n\n      uiGridColumnMenuService.initialize( $scope, uiGridCtrl );\n\n      $scope.defaultMenuItems = uiGridColumnMenuService.getDefaultMenuItems( $scope );\n\n      // Set the menu items for use with the column menu. The user can later add additional items via the watch\n      $scope.menuItems = $scope.defaultMenuItems;\n      uiGridColumnMenuService.setColMenuItemWatch( $scope );\n\n\n      /**\n       * @ngdoc method\n       * @methodOf ui.grid.directive:uiGridColumnMenu\n       * @name showMenu\n       * @description Shows the column menu.  If the menu is already displayed it\n       * calls the menu to ask it to hide (it will animate), then it repositions the menu\n       * to the right place whilst hidden (it will make an assumption on menu width),\n       * then it asks the menu to show (it will animate), then it repositions the menu again\n       * once we can calculate it's size.\n       * @param {GridCol} column the column we want to position below\n       * @param {element} $columnElement the column element we want to position below\n       */\n      $scope.showMenu = function(column, $columnElement, event) {\n        // Swap to this column\n        $scope.col = column;\n\n        // Get the position information for the column element\n        var colElementPosition = uiGridColumnMenuService.getColumnElementPosition( $scope, column, $columnElement );\n\n        if ($scope.menuShown) {\n          // we want to hide, then reposition, then show, but we want to wait for animations\n          // we set a variable, and then rely on the menu-hidden event to call the reposition and show\n          $scope.colElement = $columnElement;\n          $scope.colElementPosition = colElementPosition;\n          $scope.hideThenShow = true;\n\n          $scope.$broadcast('hide-menu', { originalEvent: event });\n        } else {\n          self.shown = $scope.menuShown = true;\n          uiGridColumnMenuService.repositionMenu( $scope, column, colElementPosition, $elm, $columnElement );\n\n          $scope.colElement = $columnElement;\n          $scope.colElementPosition = colElementPosition;\n          $scope.$broadcast('show-menu', { originalEvent: event });\n        }\n      };\n\n\n      /**\n       * @ngdoc method\n       * @methodOf ui.grid.directive:uiGridColumnMenu\n       * @name hideMenu\n       * @description Hides the column menu.\n       * @param {boolean} broadcastTrigger true if we were triggered by a broadcast\n       * from the menu itself - in which case don't broadcast again as we'll get\n       * an infinite loop\n       */\n      $scope.hideMenu = function( broadcastTrigger ) {\n        $scope.menuShown = false;\n        if ( !broadcastTrigger ){\n          $scope.$broadcast('hide-menu');\n        }\n      };\n\n\n      $scope.$on('menu-hidden', function() {\n        if ( $scope.hideThenShow ){\n          delete $scope.hideThenShow;\n\n          uiGridColumnMenuService.repositionMenu( $scope, $scope.col, $scope.colElementPosition, $elm, $scope.colElement );\n          $scope.$broadcast('show-menu');\n\n          $scope.menuShown = true;\n        } else {\n          $scope.hideMenu( true );\n\n          if ($scope.col) {\n            //Focus on the menu button\n            gridUtil.focus.bySelector($document, '.ui-grid-header-cell.' + $scope.col.getColClass()+ ' .ui-grid-column-menu-button', $scope.col.grid, false);\n          }\n        }\n      });\n\n      $scope.$on('menu-shown', function() {\n        $timeout( function() {\n          uiGridColumnMenuService.repositionMenu( $scope, $scope.col, $scope.colElementPosition, $elm, $scope.colElement );\n          delete $scope.colElementPosition;\n          delete $scope.columnElement;\n        }, 200);\n      });\n\n\n      /* Column methods */\n      $scope.sortColumn = function (event, dir) {\n        event.stopPropagation();\n\n        $scope.grid.sortColumn($scope.col, dir, true)\n          .then(function () {\n            $scope.grid.refresh();\n            $scope.hideMenu();\n          });\n      };\n\n      $scope.unsortColumn = function () {\n        $scope.col.unsort();\n\n        $scope.grid.refresh();\n        $scope.hideMenu();\n      };\n\n      //Since we are hiding this column the default hide action will fail so we need to focus somewhere else.\n      var setFocusOnHideColumn = function(){\n        $timeout(function(){\n          // Get the UID of the first\n          var focusToGridMenu = function(){\n            return gridUtil.focus.byId('grid-menu', $scope.grid);\n          };\n\n          var thisIndex;\n          $scope.grid.columns.some(function(element, index){\n            if (angular.equals(element, $scope.col)) {\n              thisIndex = index;\n              return true;\n            }\n          });\n\n          var previousVisibleCol;\n          // Try and find the next lower or nearest column to focus on\n          $scope.grid.columns.some(function(element, index){\n            if (!element.visible){\n              return false;\n            } // This columns index is below the current column index\n            else if ( index < thisIndex){\n              previousVisibleCol = element;\n            } // This elements index is above this column index and we haven't found one that is lower\n            else if ( index > thisIndex && !previousVisibleCol) {\n              // This is the next best thing\n              previousVisibleCol = element;\n              // We've found one so use it.\n              return true;\n            } // We've reached an element with an index above this column and the previousVisibleCol variable has been set\n            else if (index > thisIndex && previousVisibleCol) {\n              // We are done.\n              return true;\n            }\n          });\n          // If found then focus on it\n          if (previousVisibleCol){\n            var colClass = previousVisibleCol.getColClass();\n            gridUtil.focus.bySelector($document, '.ui-grid-header-cell.' + colClass+ ' .ui-grid-header-cell-primary-focus', true).then(angular.noop, function(reason){\n              if (reason !== 'canceled'){ // If this is canceled then don't perform the action\n                //The fallback action is to focus on the grid menu\n                return focusToGridMenu();\n              }\n            });\n          } else {\n            // Fallback action to focus on the grid menu\n            focusToGridMenu();\n          }\n        });\n      };\n\n      $scope.hideColumn = function () {\n        $scope.col.colDef.visible = false;\n        $scope.col.visible = false;\n\n        $scope.grid.queueGridRefresh();\n        $scope.hideMenu();\n        $scope.grid.api.core.notifyDataChange( uiGridConstants.dataChange.COLUMN );\n        $scope.grid.api.core.raise.columnVisibilityChanged( $scope.col );\n\n        // We are hiding so the default action of focusing on the button that opened this menu will fail.\n        setFocusOnHideColumn();\n      };\n    },\n\n\n\n    controller: ['$scope', function ($scope) {\n      var self = this;\n\n      $scope.$watch('menuItems', function (n, o) {\n        self.menuItems = n;\n      });\n    }]\n  };\n\n  return uiGridColumnMenu;\n\n}]);\n\n})();\n\n(function(){\n  'use strict';\n\n  angular.module('ui.grid').directive('uiGridFilter', ['$compile', '$templateCache', 'i18nService', 'gridUtil', function ($compile, $templateCache, i18nService, gridUtil) {\n\n    return {\n      compile: function() {\n        return {\n          pre: function ($scope, $elm, $attrs, controllers) {\n            $scope.col.updateFilters = function( filterable ){\n              $elm.children().remove();\n              if ( filterable ){\n                var template = $scope.col.filterHeaderTemplate;\n\n                $elm.append($compile(template)($scope));\n              }\n            };\n\n            $scope.$on( '$destroy', function() {\n              delete $scope.col.updateFilters;\n            });\n          },\n          post: function ($scope, $elm, $attrs, controllers){\n            $scope.aria = i18nService.getSafeText('headerCell.aria');\n            $scope.removeFilter = function(colFilter, index){\n              colFilter.term = null;\n              //Set the focus to the filter input after the action disables the button\n              gridUtil.focus.bySelector($elm, '.ui-grid-filter-input-' + index);\n            };\n          }\n        };\n      }\n    };\n  }]);\n})();\n\n(function () {\n  'use strict';\n\n  angular.module('ui.grid').directive('uiGridFooterCell', ['$timeout', 'gridUtil', 'uiGridConstants', '$compile',\n  function ($timeout, gridUtil, uiGridConstants, $compile) {\n    var uiGridFooterCell = {\n      priority: 0,\n      scope: {\n        col: '=',\n        row: '=',\n        renderIndex: '='\n      },\n      replace: true,\n      require: '^uiGrid',\n      compile: function compile(tElement, tAttrs, transclude) {\n        return {\n          pre: function ($scope, $elm, $attrs, uiGridCtrl) {\n            var cellFooter = $compile($scope.col.footerCellTemplate)($scope);\n            $elm.append(cellFooter);\n          },\n          post: function ($scope, $elm, $attrs, uiGridCtrl) {\n            //$elm.addClass($scope.col.getColClass(false));\n            $scope.grid = uiGridCtrl.grid;\n\n            var initColClass = $scope.col.getColClass(false);\n            $elm.addClass(initColClass);\n\n            // apply any footerCellClass\n            var classAdded;\n            var updateClass = function( grid ){\n              var contents = $elm;\n              if ( classAdded ){\n                contents.removeClass( classAdded );\n                classAdded = null;\n              }\n  \n              if (angular.isFunction($scope.col.footerCellClass)) {\n                classAdded = $scope.col.footerCellClass($scope.grid, $scope.row, $scope.col, $scope.rowRenderIndex, $scope.colRenderIndex);\n              }\n              else {\n                classAdded = $scope.col.footerCellClass;\n              }\n              contents.addClass(classAdded);\n            };\n  \n            if ($scope.col.footerCellClass) {\n              updateClass();\n            }\n\n            $scope.col.updateAggregationValue();\n\n            // Watch for column changes so we can alter the col cell class properly\n/* shouldn't be needed any more, given track by col.name\n            $scope.$watch('col', function (n, o) {\n              if (n !== o) {\n                // See if the column's internal class has changed\n                var newColClass = $scope.col.getColClass(false);\n                if (newColClass !== initColClass) {\n                  $elm.removeClass(initColClass);\n                  $elm.addClass(newColClass);\n                  initColClass = newColClass;\n                }\n              }\n            });\n*/\n\n\n            // Register a data change watch that would get triggered whenever someone edits a cell or modifies column defs\n            var dataChangeDereg = $scope.grid.registerDataChangeCallback( updateClass, [uiGridConstants.dataChange.COLUMN]);\n            // listen for visible rows change and update aggregation values\n            $scope.grid.api.core.on.rowsRendered( $scope, $scope.col.updateAggregationValue );\n            $scope.grid.api.core.on.rowsRendered( $scope, updateClass );\n            $scope.$on( '$destroy', dataChangeDereg );\n          }\n        };\n      }\n    };\n\n    return uiGridFooterCell;\n  }]);\n\n})();\n\n(function () {\n  'use strict';\n\n  angular.module('ui.grid').directive('uiGridFooter', ['$templateCache', '$compile', 'uiGridConstants', 'gridUtil', '$timeout', function ($templateCache, $compile, uiGridConstants, gridUtil, $timeout) {\n\n    return {\n      restrict: 'EA',\n      replace: true,\n      // priority: 1000,\n      require: ['^uiGrid', '^uiGridRenderContainer'],\n      scope: true,\n      compile: function ($elm, $attrs) {\n        return {\n          pre: function ($scope, $elm, $attrs, controllers) {\n            var uiGridCtrl = controllers[0];\n            var containerCtrl = controllers[1];\n\n            $scope.grid = uiGridCtrl.grid;\n            $scope.colContainer = containerCtrl.colContainer;\n\n            containerCtrl.footer = $elm;\n\n            var footerTemplate = $scope.grid.options.footerTemplate;\n            gridUtil.getTemplate(footerTemplate)\n              .then(function (contents) {\n                var template = angular.element(contents);\n\n                var newElm = $compile(template)($scope);\n                $elm.append(newElm);\n\n                if (containerCtrl) {\n                  // Inject a reference to the footer viewport (if it exists) into the grid controller for use in the horizontal scroll handler below\n                  var footerViewport = $elm[0].getElementsByClassName('ui-grid-footer-viewport')[0];\n\n                  if (footerViewport) {\n                    containerCtrl.footerViewport = footerViewport;\n                  }\n                }\n              });\n          },\n\n          post: function ($scope, $elm, $attrs, controllers) {\n            var uiGridCtrl = controllers[0];\n            var containerCtrl = controllers[1];\n\n            // gridUtil.logDebug('ui-grid-footer link');\n\n            var grid = uiGridCtrl.grid;\n\n            // Don't animate footer cells\n            gridUtil.disableAnimations($elm);\n\n            containerCtrl.footer = $elm;\n\n            var footerViewport = $elm[0].getElementsByClassName('ui-grid-footer-viewport')[0];\n            if (footerViewport) {\n              containerCtrl.footerViewport = footerViewport;\n            }\n          }\n        };\n      }\n    };\n  }]);\n\n})();\n(function () {\n  'use strict';\n\n  angular.module('ui.grid').directive('uiGridGridFooter', ['$templateCache', '$compile', 'uiGridConstants', 'gridUtil', '$timeout', function ($templateCache, $compile, uiGridConstants, gridUtil, $timeout) {\n\n    return {\n      restrict: 'EA',\n      replace: true,\n      // priority: 1000,\n      require: '^uiGrid',\n      scope: true,\n      compile: function ($elm, $attrs) {\n        return {\n          pre: function ($scope, $elm, $attrs, uiGridCtrl) {\n\n            $scope.grid = uiGridCtrl.grid;\n\n\n\n            var footerTemplate = $scope.grid.options.gridFooterTemplate;\n            gridUtil.getTemplate(footerTemplate)\n              .then(function (contents) {\n                var template = angular.element(contents);\n\n                var newElm = $compile(template)($scope);\n                $elm.append(newElm);\n              });\n          },\n\n          post: function ($scope, $elm, $attrs, controllers) {\n\n          }\n        };\n      }\n    };\n  }]);\n\n})();\n(function(){\n  'use strict';\n\n  angular.module('ui.grid').directive('uiGridGroupPanel', [\"$compile\", \"uiGridConstants\", \"gridUtil\", function($compile, uiGridConstants, gridUtil) {\n    var defaultTemplate = 'ui-grid/ui-grid-group-panel';\n\n    return {\n      restrict: 'EA',\n      replace: true,\n      require: '?^uiGrid',\n      scope: false,\n      compile: function($elm, $attrs) {\n        return {\n          pre: function ($scope, $elm, $attrs, uiGridCtrl) {\n            var groupPanelTemplate = $scope.grid.options.groupPanelTemplate  || defaultTemplate;\n\n             gridUtil.getTemplate(groupPanelTemplate)\n              .then(function (contents) {\n                var template = angular.element(contents);\n                \n                var newElm = $compile(template)($scope);\n                $elm.append(newElm);\n              });\n          },\n\n          post: function ($scope, $elm, $attrs, uiGridCtrl) {\n            $elm.bind('$destroy', function() {\n              // scrollUnbinder();\n            });\n          }\n        };\n      }\n    };\n  }]);\n\n})();\n(function(){\n  'use strict';\n\n  angular.module('ui.grid').directive('uiGridHeaderCell', ['$compile', '$timeout', '$window', '$document', 'gridUtil', 'uiGridConstants', 'ScrollEvent', 'i18nService',\n  function ($compile, $timeout, $window, $document, gridUtil, uiGridConstants, ScrollEvent, i18nService) {\n    // Do stuff after mouse has been down this many ms on the header cell\n    var mousedownTimeout = 500;\n    var changeModeTimeout = 500;    // length of time between a touch event and a mouse event being recognised again, and vice versa\n\n    var uiGridHeaderCell = {\n      priority: 0,\n      scope: {\n        col: '=',\n        row: '=',\n        renderIndex: '='\n      },\n      require: ['^uiGrid', '^uiGridRenderContainer'],\n      replace: true,\n      compile: function() {\n        return {\n          pre: function ($scope, $elm, $attrs) {\n            var cellHeader = $compile($scope.col.headerCellTemplate)($scope);\n            $elm.append(cellHeader);\n          },\n\n          post: function ($scope, $elm, $attrs, controllers) {\n            var uiGridCtrl = controllers[0];\n            var renderContainerCtrl = controllers[1];\n\n            $scope.i18n = {\n              headerCell: i18nService.getSafeText('headerCell'),\n              sort: i18nService.getSafeText('sort')\n            };\n            $scope.getSortDirectionAriaLabel = function(){\n              var col = $scope.col;\n              //Trying to recreate this sort of thing but it was getting messy having it in the template.\n              //Sort direction {{col.sort.direction == asc ? 'ascending' : ( col.sort.direction == desc ? 'descending':'none')}}. {{col.sort.priority ? {{columnPriorityText}} {{col.sort.priority}} : ''}\n              var sortDirectionText = col.sort.direction === uiGridConstants.ASC ? $scope.i18n.sort.ascending : ( col.sort.direction === uiGridConstants.DESC ? $scope.i18n.sort.descending : $scope.i18n.sort.none);\n              var label = sortDirectionText;\n              //Append the priority if it exists\n              if (col.sort.priority) {\n                label = label + '. ' + $scope.i18n.headerCell.priority + ' ' + col.sort.priority;\n              }\n              return label;\n            };\n\n            $scope.grid = uiGridCtrl.grid;\n\n            $scope.renderContainer = uiGridCtrl.grid.renderContainers[renderContainerCtrl.containerId];\n\n            var initColClass = $scope.col.getColClass(false);\n            $elm.addClass(initColClass);\n\n            // Hide the menu by default\n            $scope.menuShown = false;\n\n            // Put asc and desc sort directions in scope\n            $scope.asc = uiGridConstants.ASC;\n            $scope.desc = uiGridConstants.DESC;\n\n            // Store a reference to menu element\n            var $colMenu = angular.element( $elm[0].querySelectorAll('.ui-grid-header-cell-menu') );\n\n            var $contentsElm = angular.element( $elm[0].querySelectorAll('.ui-grid-cell-contents') );\n\n\n            // apply any headerCellClass\n            var classAdded;\n            var previousMouseX;\n\n            // filter watchers\n            var filterDeregisters = [];\n\n\n            /*\n             * Our basic approach here for event handlers is that we listen for a down event (mousedown or touchstart).\n             * Once we have a down event, we need to work out whether we have a click, a drag, or a\n             * hold.  A click would sort the grid (if sortable).  A drag would be used by moveable, so\n             * we ignore it.  A hold would open the menu.\n             *\n             * So, on down event, we put in place handlers for move and up events, and a timer.  If the\n             * timer expires before we see a move or up, then we have a long press and hence a column menu open.\n             * If the up happens before the timer, then we have a click, and we sort if the column is sortable.\n             * If a move happens before the timer, then we are doing column move, so we do nothing, the moveable feature\n             * will handle it.\n             *\n             * To deal with touch enabled devices that also have mice, we only create our handlers when\n             * we get the down event, and we create the corresponding handlers - if we're touchstart then\n             * we get touchmove and touchend, if we're mousedown then we get mousemove and mouseup.\n             *\n             * We also suppress the click action whilst this is happening - otherwise after the mouseup there\n             * will be a click event and that can cause the column menu to close\n             *\n             */\n\n            $scope.downFn = function( event ){\n              event.stopPropagation();\n\n              if (typeof(event.originalEvent) !== 'undefined' && event.originalEvent !== undefined) {\n                event = event.originalEvent;\n              }\n\n              // Don't show the menu if it's not the left button\n              if (event.button && event.button !== 0) {\n                return;\n              }\n              previousMouseX = event.pageX;\n\n              $scope.mousedownStartTime = (new Date()).getTime();\n              $scope.mousedownTimeout = $timeout(function() { }, mousedownTimeout);\n\n              $scope.mousedownTimeout.then(function () {\n                if ( $scope.colMenu ) {\n                  uiGridCtrl.columnMenuScope.showMenu($scope.col, $elm, event);\n                }\n              });\n\n              uiGridCtrl.fireEvent(uiGridConstants.events.COLUMN_HEADER_CLICK, {event: event, columnName: $scope.col.colDef.name});\n\n              $scope.offAllEvents();\n              if ( event.type === 'touchstart'){\n                $document.on('touchend', $scope.upFn);\n                $document.on('touchmove', $scope.moveFn);\n              } else if ( event.type === 'mousedown' ){\n                $document.on('mouseup', $scope.upFn);\n                $document.on('mousemove', $scope.moveFn);\n              }\n            };\n\n            $scope.upFn = function( event ){\n              event.stopPropagation();\n              $timeout.cancel($scope.mousedownTimeout);\n              $scope.offAllEvents();\n              $scope.onDownEvents(event.type);\n\n              var mousedownEndTime = (new Date()).getTime();\n              var mousedownTime = mousedownEndTime - $scope.mousedownStartTime;\n\n              if (mousedownTime > mousedownTimeout) {\n                // long click, handled above with mousedown\n              }\n              else {\n                // short click\n                if ( $scope.sortable ){\n                  $scope.handleClick(event);\n                }\n              }\n            };\n\n            $scope.moveFn = function( event ){\n              // Chrome is known to fire some bogus move events.\n              var changeValue = event.pageX - previousMouseX;\n              if ( changeValue === 0 ){ return; }\n\n              // we're a move, so do nothing and leave for column move (if enabled) to take over\n              $timeout.cancel($scope.mousedownTimeout);\n              $scope.offAllEvents();\n              $scope.onDownEvents(event.type);\n            };\n\n            $scope.clickFn = function ( event ){\n              event.stopPropagation();\n              $contentsElm.off('click', $scope.clickFn);\n            };\n\n\n            $scope.offAllEvents = function(){\n              $contentsElm.off('touchstart', $scope.downFn);\n              $contentsElm.off('mousedown', $scope.downFn);\n\n              $document.off('touchend', $scope.upFn);\n              $document.off('mouseup', $scope.upFn);\n\n              $document.off('touchmove', $scope.moveFn);\n              $document.off('mousemove', $scope.moveFn);\n\n              $contentsElm.off('click', $scope.clickFn);\n            };\n\n            $scope.onDownEvents = function( type ){\n              // If there is a previous event, then wait a while before\n              // activating the other mode - i.e. if the last event was a touch event then\n              // don't enable mouse events for a wee while (500ms or so)\n              // Avoids problems with devices that emulate mouse events when you have touch events\n\n              switch (type){\n                case 'touchmove':\n                case 'touchend':\n                  $contentsElm.on('click', $scope.clickFn);\n                  $contentsElm.on('touchstart', $scope.downFn);\n                  $timeout(function(){\n                    $contentsElm.on('mousedown', $scope.downFn);\n                  }, changeModeTimeout);\n                  break;\n                case 'mousemove':\n                case 'mouseup':\n                  $contentsElm.on('click', $scope.clickFn);\n                  $contentsElm.on('mousedown', $scope.downFn);\n                  $timeout(function(){\n                    $contentsElm.on('touchstart', $scope.downFn);\n                  }, changeModeTimeout);\n                  break;\n                default:\n                  $contentsElm.on('click', $scope.clickFn);\n                  $contentsElm.on('touchstart', $scope.downFn);\n                  $contentsElm.on('mousedown', $scope.downFn);\n              }\n            };\n\n\n            var updateHeaderOptions = function( grid ){\n              var contents = $elm;\n              if ( classAdded ){\n                contents.removeClass( classAdded );\n                classAdded = null;\n              }\n\n              if (angular.isFunction($scope.col.headerCellClass)) {\n                classAdded = $scope.col.headerCellClass($scope.grid, $scope.row, $scope.col, $scope.rowRenderIndex, $scope.colRenderIndex);\n              }\n              else {\n                classAdded = $scope.col.headerCellClass;\n              }\n              contents.addClass(classAdded);\n\n              var rightMostContainer = $scope.grid.renderContainers['right'] ? $scope.grid.renderContainers['right'] : $scope.grid.renderContainers['body'];\n              $scope.isLastCol = ( $scope.col === rightMostContainer.visibleColumnCache[ rightMostContainer.visibleColumnCache.length - 1 ] );\n\n              // Figure out whether this column is sortable or not\n              if (uiGridCtrl.grid.options.enableSorting && $scope.col.enableSorting) {\n                $scope.sortable = true;\n              }\n              else {\n                $scope.sortable = false;\n              }\n\n              // Figure out whether this column is filterable or not\n              var oldFilterable = $scope.filterable;\n              if (uiGridCtrl.grid.options.enableFiltering && $scope.col.enableFiltering) {\n                $scope.filterable = true;\n              }\n              else {\n                $scope.filterable = false;\n              }\n\n              if ( oldFilterable !== $scope.filterable){\n                if ( typeof($scope.col.updateFilters) !== 'undefined' ){\n                  $scope.col.updateFilters($scope.filterable);\n                }\n\n                // if column is filterable add a filter watcher\n                if ($scope.filterable) {\n                  $scope.col.filters.forEach( function(filter, i) {\n                    filterDeregisters.push($scope.$watch('col.filters[' + i + '].term', function(n, o) {\n                      if (n !== o) {\n                        uiGridCtrl.grid.api.core.raise.filterChanged();\n                        uiGridCtrl.grid.api.core.notifyDataChange( uiGridConstants.dataChange.COLUMN );\n                        uiGridCtrl.grid.queueGridRefresh();\n                      }\n                    }));\n                  });\n                  $scope.$on('$destroy', function() {\n                    filterDeregisters.forEach( function(filterDeregister) {\n                      filterDeregister();\n                    });\n                  });\n                } else {\n                  filterDeregisters.forEach( function(filterDeregister) {\n                    filterDeregister();\n                  });\n                }\n\n              }\n\n              // figure out whether we support column menus\n              if ($scope.col.grid.options && $scope.col.grid.options.enableColumnMenus !== false &&\n                      $scope.col.colDef && $scope.col.colDef.enableColumnMenu !== false){\n                $scope.colMenu = true;\n              } else {\n                $scope.colMenu = false;\n              }\n\n              /**\n              * @ngdoc property\n              * @name enableColumnMenu\n              * @propertyOf ui.grid.class:GridOptions.columnDef\n              * @description if column menus are enabled, controls the column menus for this specific\n              * column (i.e. if gridOptions.enableColumnMenus, then you can control column menus\n              * using this option. If gridOptions.enableColumnMenus === false then you get no column\n              * menus irrespective of the value of this option ).  Defaults to true.\n              *\n              */\n              /**\n              * @ngdoc property\n              * @name enableColumnMenus\n              * @propertyOf ui.grid.class:GridOptions.columnDef\n              * @description Override for column menus everywhere - if set to false then you get no\n              * column menus.  Defaults to true.\n              *\n              */\n\n              $scope.offAllEvents();\n\n              if ($scope.sortable || $scope.colMenu) {\n                $scope.onDownEvents();\n\n                $scope.$on('$destroy', function () {\n                  $scope.offAllEvents();\n                });\n              }\n            };\n\n/*\n            $scope.$watch('col', function (n, o) {\n              if (n !== o) {\n                // See if the column's internal class has changed\n                var newColClass = $scope.col.getColClass(false);\n                if (newColClass !== initColClass) {\n                  $elm.removeClass(initColClass);\n                  $elm.addClass(newColClass);\n                  initColClass = newColClass;\n                }\n              }\n            });\n*/\n            updateHeaderOptions();\n\n            // Register a data change watch that would get triggered whenever someone edits a cell or modifies column defs\n            var dataChangeDereg = $scope.grid.registerDataChangeCallback( updateHeaderOptions, [uiGridConstants.dataChange.COLUMN]);\n\n            $scope.$on( '$destroy', dataChangeDereg );\n\n            $scope.handleClick = function(event) {\n              // If the shift key is being held down, add this column to the sort\n              var add = false;\n              if (event.shiftKey) {\n                add = true;\n              }\n\n              // Sort this column then rebuild the grid's rows\n              uiGridCtrl.grid.sortColumn($scope.col, add)\n                .then(function () {\n                  if (uiGridCtrl.columnMenuScope) { uiGridCtrl.columnMenuScope.hideMenu(); }\n                  uiGridCtrl.grid.refresh();\n                });\n            };\n\n\n            $scope.toggleMenu = function(event) {\n              event.stopPropagation();\n\n              // If the menu is already showing...\n              if (uiGridCtrl.columnMenuScope.menuShown) {\n                // ... and we're the column the menu is on...\n                if (uiGridCtrl.columnMenuScope.col === $scope.col) {\n                  // ... hide it\n                  uiGridCtrl.columnMenuScope.hideMenu();\n                }\n                // ... and we're NOT the column the menu is on\n                else {\n                  // ... move the menu to our column\n                  uiGridCtrl.columnMenuScope.showMenu($scope.col, $elm);\n                }\n              }\n              // If the menu is NOT showing\n              else {\n                // ... show it on our column\n                uiGridCtrl.columnMenuScope.showMenu($scope.col, $elm);\n              }\n            };\n          }\n        };\n      }\n    };\n\n    return uiGridHeaderCell;\n  }]);\n\n})();\n\n(function(){\n  'use strict';\n\n  angular.module('ui.grid').directive('uiGridHeader', ['$templateCache', '$compile', 'uiGridConstants', 'gridUtil', '$timeout', 'ScrollEvent',\n    function($templateCache, $compile, uiGridConstants, gridUtil, $timeout, ScrollEvent) {\n    var defaultTemplate = 'ui-grid/ui-grid-header';\n    var emptyTemplate = 'ui-grid/ui-grid-no-header';\n\n    return {\n      restrict: 'EA',\n      // templateUrl: 'ui-grid/ui-grid-header',\n      replace: true,\n      // priority: 1000,\n      require: ['^uiGrid', '^uiGridRenderContainer'],\n      scope: true,\n      compile: function($elm, $attrs) {\n        return {\n          pre: function ($scope, $elm, $attrs, controllers) {\n            var uiGridCtrl = controllers[0];\n            var containerCtrl = controllers[1];\n\n            $scope.grid = uiGridCtrl.grid;\n            $scope.colContainer = containerCtrl.colContainer;\n\n            updateHeaderReferences();\n            \n            var headerTemplate;\n            if (!$scope.grid.options.showHeader) {\n              headerTemplate = emptyTemplate;\n            }\n            else {\n              headerTemplate = ($scope.grid.options.headerTemplate) ? $scope.grid.options.headerTemplate : defaultTemplate;            \n            }\n\n            gridUtil.getTemplate(headerTemplate)\n              .then(function (contents) {\n                var template = angular.element(contents);\n                \n                var newElm = $compile(template)($scope);\n                $elm.replaceWith(newElm);\n\n                // And update $elm to be the new element\n                $elm = newElm;\n\n                updateHeaderReferences();\n\n                if (containerCtrl) {\n                  // Inject a reference to the header viewport (if it exists) into the grid controller for use in the horizontal scroll handler below\n                  var headerViewport = $elm[0].getElementsByClassName('ui-grid-header-viewport')[0];\n\n\n                  if (headerViewport) {\n                    containerCtrl.headerViewport = headerViewport;\n                    angular.element(headerViewport).on('scroll', scrollHandler);\n                    $scope.$on('$destroy', function () {\n                      angular.element(headerViewport).off('scroll', scrollHandler);\n                    });\n                  }\n                }\n\n                $scope.grid.queueRefresh();\n              });\n\n            function updateHeaderReferences() {\n              containerCtrl.header = containerCtrl.colContainer.header = $elm;\n\n              var headerCanvases = $elm[0].getElementsByClassName('ui-grid-header-canvas');\n\n              if (headerCanvases.length > 0) {\n                containerCtrl.headerCanvas = containerCtrl.colContainer.headerCanvas = headerCanvases[0];\n              }\n              else {\n                containerCtrl.headerCanvas = null;\n              }\n            }\n\n            function scrollHandler(evt) {\n              if (uiGridCtrl.grid.isScrollingHorizontally) {\n                return;\n              }\n              var newScrollLeft = gridUtil.normalizeScrollLeft(containerCtrl.headerViewport, uiGridCtrl.grid);\n              var horizScrollPercentage = containerCtrl.colContainer.scrollHorizontal(newScrollLeft);\n\n              var scrollEvent = new ScrollEvent(uiGridCtrl.grid, null, containerCtrl.colContainer, ScrollEvent.Sources.ViewPortScroll);\n              scrollEvent.newScrollLeft = newScrollLeft;\n              if ( horizScrollPercentage > -1 ){\n                scrollEvent.x = { percentage: horizScrollPercentage };\n              }\n\n              uiGridCtrl.grid.scrollContainers(null, scrollEvent);\n            }\n          },\n\n          post: function ($scope, $elm, $attrs, controllers) {\n            var uiGridCtrl = controllers[0];\n            var containerCtrl = controllers[1];\n\n            // gridUtil.logDebug('ui-grid-header link');\n\n            var grid = uiGridCtrl.grid;\n\n            // Don't animate header cells\n            gridUtil.disableAnimations($elm);\n\n            function updateColumnWidths() {\n              // this styleBuilder always runs after the renderContainer, so we can rely on the column widths\n              // already being populated correctly\n\n              var columnCache = containerCtrl.colContainer.visibleColumnCache;\n              \n              // Build the CSS\n              // uiGridCtrl.grid.columns.forEach(function (column) {\n              var ret = '';\n              var canvasWidth = 0;\n              columnCache.forEach(function (column) {\n                ret = ret + column.getColClassDefinition();\n                canvasWidth += column.drawnWidth;\n              });\n\n              containerCtrl.colContainer.canvasWidth = canvasWidth;\n              \n              // Return the styles back to buildStyles which pops them into the `customStyles` scope variable\n              return ret;\n            }\n            \n            containerCtrl.header = $elm;\n            \n            var headerViewport = $elm[0].getElementsByClassName('ui-grid-header-viewport')[0];\n            if (headerViewport) {\n              containerCtrl.headerViewport = headerViewport;\n            }\n\n            //todo: remove this if by injecting gridCtrl into unit tests\n            if (uiGridCtrl) {\n              uiGridCtrl.grid.registerStyleComputation({\n                priority: 15,\n                func: updateColumnWidths\n              });\n            }\n          }\n        };\n      }\n    };\n  }]);\n\n})();\n\n(function(){\n\nangular.module('ui.grid')\n.service('uiGridGridMenuService', [ 'gridUtil', 'i18nService', 'uiGridConstants', function( gridUtil, i18nService, uiGridConstants ) {\n  /**\n   *  @ngdoc service\n   *  @name ui.grid.gridMenuService\n   *\n   *  @description Methods for working with the grid menu\n   */\n\n  var service = {\n    /**\n     * @ngdoc method\n     * @methodOf ui.grid.gridMenuService\n     * @name initialize\n     * @description Sets up the gridMenu. Most importantly, sets our\n     * scope onto the grid object as grid.gridMenuScope, allowing us\n     * to operate when passed only the grid.  Second most importantly,\n     * we register the 'addToGridMenu' and 'removeFromGridMenu' methods\n     * on the core api.\n     * @param {$scope} $scope the scope of this gridMenu\n     * @param {Grid} grid the grid to which this gridMenu is associated\n     */\n    initialize: function( $scope, grid ){\n      grid.gridMenuScope = $scope;\n      $scope.grid = grid;\n      $scope.registeredMenuItems = [];\n\n      // not certain this is needed, but would be bad to create a memory leak\n      $scope.$on('$destroy', function() {\n        if ( $scope.grid && $scope.grid.gridMenuScope ){\n          $scope.grid.gridMenuScope = null;\n        }\n        if ( $scope.grid ){\n          $scope.grid = null;\n        }\n        if ( $scope.registeredMenuItems ){\n          $scope.registeredMenuItems = null;\n        }\n      });\n\n      $scope.registeredMenuItems = [];\n\n      /**\n       * @ngdoc function\n       * @name addToGridMenu\n       * @methodOf ui.grid.core.api:PublicApi\n       * @description add items to the grid menu.  Used by features\n       * to add their menu items if they are enabled, can also be used by\n       * end users to add menu items.  This method has the advantage of allowing\n       * remove again, which can simplify management of which items are included\n       * in the menu when.  (Noting that in most cases the shown and active functions\n       * provide a better way to handle visibility of menu items)\n       * @param {Grid} grid the grid on which we are acting\n       * @param {array} items menu items in the format as described in the tutorial, with\n       * the added note that if you want to use remove you must also specify an `id` field,\n       * which is provided when you want to remove an item.  The id should be unique.\n       *\n       */\n      grid.api.registerMethod( 'core', 'addToGridMenu', service.addToGridMenu );\n\n      /**\n       * @ngdoc function\n       * @name removeFromGridMenu\n       * @methodOf ui.grid.core.api:PublicApi\n       * @description Remove an item from the grid menu based on a provided id. Assumes\n       * that the id is unique, removes only the last instance of that id. Does nothing if\n       * the specified id is not found\n       * @param {Grid} grid the grid on which we are acting\n       * @param {string} id the id we'd like to remove from the menu\n       *\n       */\n      grid.api.registerMethod( 'core', 'removeFromGridMenu', service.removeFromGridMenu );\n    },\n\n\n    /**\n     * @ngdoc function\n     * @name addToGridMenu\n     * @propertyOf ui.grid.gridMenuService\n     * @description add items to the grid menu.  Used by features\n     * to add their menu items if they are enabled, can also be used by\n     * end users to add menu items.  This method has the advantage of allowing\n     * remove again, which can simplify management of which items are included\n     * in the menu when.  (Noting that in most cases the shown and active functions\n     * provide a better way to handle visibility of menu items)\n     * @param {Grid} grid the grid on which we are acting\n     * @param {array} items menu items in the format as described in the tutorial, with\n     * the added note that if you want to use remove you must also specify an `id` field,\n     * which is provided when you want to remove an item.  The id should be unique.\n     *\n     */\n    addToGridMenu: function( grid, menuItems ) {\n      if ( !angular.isArray( menuItems ) ) {\n        gridUtil.logError( 'addToGridMenu: menuItems must be an array, and is not, not adding any items');\n      } else {\n        if ( grid.gridMenuScope ){\n          grid.gridMenuScope.registeredMenuItems = grid.gridMenuScope.registeredMenuItems ? grid.gridMenuScope.registeredMenuItems : [];\n          grid.gridMenuScope.registeredMenuItems = grid.gridMenuScope.registeredMenuItems.concat( menuItems );\n        } else {\n          gridUtil.logError( 'Asked to addToGridMenu, but gridMenuScope not present.  Timing issue?  Please log issue with ui-grid');\n        }\n      }\n    },\n\n\n    /**\n     * @ngdoc function\n     * @name removeFromGridMenu\n     * @methodOf ui.grid.gridMenuService\n     * @description Remove an item from the grid menu based on a provided id.  Assumes\n     * that the id is unique, removes only the last instance of that id.  Does nothing if\n     * the specified id is not found.  If there is no gridMenuScope or registeredMenuItems\n     * then do nothing silently - the desired result is those menu items not be present and they\n     * aren't.\n     * @param {Grid} grid the grid on which we are acting\n     * @param {string} id the id we'd like to remove from the menu\n     *\n     */\n    removeFromGridMenu: function( grid, id ){\n      var foundIndex = -1;\n\n      if ( grid && grid.gridMenuScope ){\n        grid.gridMenuScope.registeredMenuItems.forEach( function( value, index ) {\n          if ( value.id === id ){\n            if (foundIndex > -1) {\n              gridUtil.logError( 'removeFromGridMenu: found multiple items with the same id, removing only the last' );\n            } else {\n\n              foundIndex = index;\n            }\n          }\n        });\n      }\n\n      if ( foundIndex > -1 ){\n        grid.gridMenuScope.registeredMenuItems.splice( foundIndex, 1 );\n      }\n    },\n\n\n    /**\n     * @ngdoc array\n     * @name gridMenuCustomItems\n     * @propertyOf ui.grid.class:GridOptions\n     * @description (optional) An array of menu items that should be added to\n     * the gridMenu.  Follow the format documented in the tutorial for column\n     * menu customisation.  The context provided to the action function will\n     * include context.grid.  An alternative if working with dynamic menus is to use the\n     * provided api - core.addToGridMenu and core.removeFromGridMenu, which handles\n     * some of the management of items for you.\n     *\n     */\n    /**\n     * @ngdoc boolean\n     * @name gridMenuShowHideColumns\n     * @propertyOf ui.grid.class:GridOptions\n     * @description true by default, whether the grid menu should allow hide/show\n     * of columns\n     *\n     */\n    /**\n     * @ngdoc method\n     * @methodOf ui.grid.gridMenuService\n     * @name getMenuItems\n     * @description Decides the menu items to show in the menu.  This is a\n     * combination of:\n     *\n     * - the default menu items that are always included,\n     * - any menu items that have been provided through the addMenuItem api. These\n     *   are typically added by features within the grid\n     * - any menu items included in grid.options.gridMenuCustomItems.  These can be\n     *   changed dynamically, as they're always recalculated whenever we show the\n     *   menu\n     * @param {$scope} $scope the scope of this gridMenu, from which we can find all\n     * the information that we need\n     * @returns {array} an array of menu items that can be shown\n     */\n    getMenuItems: function( $scope ) {\n      var menuItems = [\n        // this is where we add any menu items we want to always include\n      ];\n\n      if ( $scope.grid.options.gridMenuCustomItems ){\n        if ( !angular.isArray( $scope.grid.options.gridMenuCustomItems ) ){\n          gridUtil.logError( 'gridOptions.gridMenuCustomItems must be an array, and is not');\n        } else {\n          menuItems = menuItems.concat( $scope.grid.options.gridMenuCustomItems );\n        }\n      }\n\n      menuItems = menuItems.concat( $scope.registeredMenuItems );\n\n      if ( $scope.grid.options.gridMenuShowHideColumns !== false ){\n        menuItems = menuItems.concat( service.showHideColumns( $scope ) );\n      }\n\n      menuItems.sort(function(a, b){\n        return a.order - b.order;\n      });\n\n      return menuItems;\n    },\n\n\n    /**\n     * @ngdoc array\n     * @name gridMenuTitleFilter\n     * @propertyOf ui.grid.class:GridOptions\n     * @description (optional) A function that takes a title string\n     * (usually the col.displayName), and converts it into a display value.  The function\n     * must return either a string or a promise.\n     *\n     * Used for internationalization of the grid menu column names - for angular-translate\n     * you can pass $translate as the function, for i18nService you can pass getSafeText as the\n     * function\n     * @example\n     * <pre>\n     *   gridOptions = {\n     *     gridMenuTitleFilter: $translate\n     *   }\n     * </pre>\n     */\n    /**\n     * @ngdoc method\n     * @methodOf ui.grid.gridMenuService\n     * @name showHideColumns\n     * @description Adds two menu items for each of the columns in columnDefs.  One\n     * menu item for hide, one menu item for show.  Each is visible when appropriate\n     * (show when column is not visible, hide when column is visible).  Each toggles\n     * the visible property on the columnDef using toggleColumnVisibility\n     * @param {$scope} $scope of a gridMenu, which contains a reference to the grid\n     */\n    showHideColumns: function( $scope ){\n      var showHideColumns = [];\n      if ( !$scope.grid.options.columnDefs || $scope.grid.options.columnDefs.length === 0 || $scope.grid.columns.length === 0 ) {\n        return showHideColumns;\n      }\n\n      // add header for columns\n      showHideColumns.push({\n        title: i18nService.getSafeText('gridMenu.columns'),\n        order: 300\n      });\n\n      $scope.grid.options.gridMenuTitleFilter = $scope.grid.options.gridMenuTitleFilter ? $scope.grid.options.gridMenuTitleFilter : function( title ) { return title; };\n\n      $scope.grid.options.columnDefs.forEach( function( colDef, index ){\n        if ( colDef.enableHiding !== false ){\n          // add hide menu item - shows an OK icon as we only show when column is already visible\n          var menuItem = {\n            icon: 'ui-grid-icon-ok',\n            action: function($event) {\n              $event.stopPropagation();\n              service.toggleColumnVisibility( this.context.gridCol );\n            },\n            shown: function() {\n              return this.context.gridCol.colDef.visible === true || this.context.gridCol.colDef.visible === undefined;\n            },\n            context: { gridCol: $scope.grid.getColumn(colDef.name || colDef.field) },\n            leaveOpen: true,\n            order: 301 + index * 2\n          };\n          service.setMenuItemTitle( menuItem, colDef, $scope.grid );\n          showHideColumns.push( menuItem );\n\n          // add show menu item - shows no icon as we only show when column is invisible\n          menuItem = {\n            icon: 'ui-grid-icon-cancel',\n            action: function($event) {\n              $event.stopPropagation();\n              service.toggleColumnVisibility( this.context.gridCol );\n            },\n            shown: function() {\n              return !(this.context.gridCol.colDef.visible === true || this.context.gridCol.colDef.visible === undefined);\n            },\n            context: { gridCol: $scope.grid.getColumn(colDef.name || colDef.field) },\n            leaveOpen: true,\n            order: 301 + index * 2 + 1\n          };\n          service.setMenuItemTitle( menuItem, colDef, $scope.grid );\n          showHideColumns.push( menuItem );\n        }\n      });\n      return showHideColumns;\n    },\n\n\n    /**\n     * @ngdoc method\n     * @methodOf ui.grid.gridMenuService\n     * @name setMenuItemTitle\n     * @description Handles the response from gridMenuTitleFilter, adding it directly to the menu\n     * item if it returns a string, otherwise waiting for the promise to resolve or reject then\n     * putting the result into the title\n     * @param {object} menuItem the menuItem we want to put the title on\n     * @param {object} colDef the colDef from which we can get displayName, name or field\n     * @param {Grid} grid the grid, from which we can get the options.gridMenuTitleFilter\n     *\n     */\n    setMenuItemTitle: function( menuItem, colDef, grid ){\n      var title = grid.options.gridMenuTitleFilter( colDef.displayName || gridUtil.readableColumnName(colDef.name) || colDef.field );\n\n      if ( typeof(title) === 'string' ){\n        menuItem.title = title;\n      } else if ( title.then ){\n        // must be a promise\n        menuItem.title = \"\";\n        title.then( function( successValue ) {\n          menuItem.title = successValue;\n        }, function( errorValue ) {\n          menuItem.title = errorValue;\n        });\n      } else {\n        gridUtil.logError('Expected gridMenuTitleFilter to return a string or a promise, it has returned neither, bad config');\n        menuItem.title = 'badconfig';\n      }\n    },\n\n    /**\n     * @ngdoc method\n     * @methodOf ui.grid.gridMenuService\n     * @name toggleColumnVisibility\n     * @description Toggles the visibility of an individual column.  Expects to be\n     * provided a context that has on it a gridColumn, which is the column that\n     * we'll operate upon.  We change the visibility, and refresh the grid as appropriate\n     * @param {GridCol} gridCol the column that we want to toggle\n     *\n     */\n    toggleColumnVisibility: function( gridCol ) {\n      gridCol.colDef.visible = !( gridCol.colDef.visible === true || gridCol.colDef.visible === undefined );\n\n      gridCol.grid.refresh();\n      gridCol.grid.api.core.notifyDataChange( uiGridConstants.dataChange.COLUMN );\n      gridCol.grid.api.core.raise.columnVisibilityChanged( gridCol );\n    }\n  };\n\n  return service;\n}])\n\n\n\n.directive('uiGridMenuButton', ['gridUtil', 'uiGridConstants', 'uiGridGridMenuService', 'i18nService',\nfunction (gridUtil, uiGridConstants, uiGridGridMenuService, i18nService) {\n\n  return {\n    priority: 0,\n    scope: true,\n    require: ['^uiGrid'],\n    templateUrl: 'ui-grid/ui-grid-menu-button',\n    replace: true,\n\n    link: function ($scope, $elm, $attrs, controllers) {\n      var uiGridCtrl = controllers[0];\n\n      // For the aria label\n      $scope.i18n = {\n        aria: i18nService.getSafeText('gridMenu.aria')\n      };\n\n      uiGridGridMenuService.initialize($scope, uiGridCtrl.grid);\n\n      $scope.shown = false;\n\n      $scope.toggleMenu = function () {\n        if ( $scope.shown ){\n          $scope.$broadcast('hide-menu');\n          $scope.shown = false;\n        } else {\n          $scope.menuItems = uiGridGridMenuService.getMenuItems( $scope );\n          $scope.$broadcast('show-menu');\n          $scope.shown = true;\n        }\n      };\n\n      $scope.$on('menu-hidden', function() {\n        $scope.shown = false;\n        gridUtil.focus.bySelector($elm, '.ui-grid-icon-container');\n      });\n    }\n  };\n\n}]);\n\n})();\n\n(function(){\n\n/**\n * @ngdoc directive\n * @name ui.grid.directive:uiGridMenu\n * @element style\n * @restrict A\n *\n * @description\n * Allows us to interpolate expressions in `<style>` elements. Angular doesn't do this by default as it can/will/might? break in IE8.\n *\n * @example\n <doc:example module=\"app\">\n <doc:source>\n <script>\n var app = angular.module('app', ['ui.grid']);\n\n app.controller('MainCtrl', ['$scope', function ($scope) {\n\n }]);\n </script>\n\n <div ng-controller=\"MainCtrl\">\n   <div ui-grid-menu shown=\"true\"  ></div>\n </div>\n </doc:source>\n <doc:scenario>\n </doc:scenario>\n </doc:example>\n */\nangular.module('ui.grid')\n\n.directive('uiGridMenu', ['$compile', '$timeout', '$window', '$document', 'gridUtil', 'uiGridConstants', 'i18nService',\nfunction ($compile, $timeout, $window, $document, gridUtil, uiGridConstants, i18nService) {\n  var uiGridMenu = {\n    priority: 0,\n    scope: {\n      // shown: '&',\n      menuItems: '=',\n      autoHide: '=?'\n    },\n    require: '?^uiGrid',\n    templateUrl: 'ui-grid/uiGridMenu',\n    replace: false,\n    link: function ($scope, $elm, $attrs, uiGridCtrl) {\n      var self = this;\n      var menuMid;\n      var $animate;\n\n      $scope.i18n = {\n        close: i18nService.getSafeText('columnMenu.close')\n      };\n\n    // *** Show/Hide functions ******\n      self.showMenu = $scope.showMenu = function(event, args) {\n        if ( !$scope.shown ){\n\n          /*\n           * In order to animate cleanly we remove the ng-if, wait a digest cycle, then\n           * animate the removal of the ng-hide.  We can't successfully (so far as I can tell)\n           * animate removal of the ng-if, as the menu items aren't there yet.  And we don't want\n           * to rely on ng-show only, as that leaves elements in the DOM that are needlessly evaluated\n           * on scroll events.\n           *\n           * Note when testing animation that animations don't run on the tutorials.  When debugging it looks\n           * like they do, but angular has a default $animate provider that is just a stub, and that's what's\n           * being called.  ALso don't be fooled by the fact that your browser has actually loaded the\n           * angular-translate.js, it's not using it.  You need to test animations in an external application.\n           */\n          $scope.shown = true;\n\n          $timeout( function() {\n            $scope.shownMid = true;\n            $scope.$emit('menu-shown');\n          });\n        } else if ( !$scope.shownMid ) {\n          // we're probably doing a hide then show, so we don't need to wait for ng-if\n          $scope.shownMid = true;\n          $scope.$emit('menu-shown');\n        }\n\n        var docEventType = 'click';\n        if (args && args.originalEvent && args.originalEvent.type && args.originalEvent.type === 'touchstart') {\n          docEventType = args.originalEvent.type;\n        }\n\n        // Turn off an existing document click handler\n        angular.element(document).off('click touchstart', applyHideMenu);\n\n        // Turn on the document click handler, but in a timeout so it doesn't apply to THIS click if there is one\n        $timeout(function() {\n          angular.element(document).on(docEventType, applyHideMenu);\n        });\n        //automatically set the focus to the first button element in the now open menu.\n        gridUtil.focus.bySelector($elm, 'button[type=button]', true);\n      };\n\n\n      self.hideMenu = $scope.hideMenu = function(event, args) {\n        if ( $scope.shown ){\n          /*\n           * In order to animate cleanly we animate the addition of ng-hide, then use a $timeout to\n           * set the ng-if (shown = false) after the animation runs.  In theory we can cascade off the\n           * callback on the addClass method, but it is very unreliable with unit tests for no discernable reason.\n           *\n           * The user may have clicked on the menu again whilst\n           * we're waiting, so we check that the mid isn't shown before applying the ng-if.\n           */\n          $scope.shownMid = false;\n          $timeout( function() {\n            if ( !$scope.shownMid ){\n              $scope.shown = false;\n              $scope.$emit('menu-hidden');\n            }\n          }, 200);\n        }\n\n        angular.element(document).off('click touchstart', applyHideMenu);\n      };\n\n      $scope.$on('hide-menu', function (event, args) {\n        $scope.hideMenu(event, args);\n      });\n\n      $scope.$on('show-menu', function (event, args) {\n        $scope.showMenu(event, args);\n      });\n\n\n    // *** Auto hide when click elsewhere ******\n      var applyHideMenu = function(){\n        if ($scope.shown) {\n          $scope.$apply(function () {\n            $scope.hideMenu();\n          });\n        }\n      };\n\n      if (typeof($scope.autoHide) === 'undefined' || $scope.autoHide === undefined) {\n        $scope.autoHide = true;\n      }\n\n      if ($scope.autoHide) {\n        angular.element($window).on('resize', applyHideMenu);\n      }\n\n      $scope.$on('$destroy', function () {\n        angular.element(document).off('click touchstart', applyHideMenu);\n      });\n\n\n      $scope.$on('$destroy', function() {\n        angular.element($window).off('resize', applyHideMenu);\n      });\n\n      if (uiGridCtrl) {\n       $scope.$on('$destroy', uiGridCtrl.grid.api.core.on.scrollBegin($scope, applyHideMenu ));\n      }\n\n      $scope.$on('$destroy', $scope.$on(uiGridConstants.events.ITEM_DRAGGING, applyHideMenu ));\n    },\n\n\n    controller: ['$scope', '$element', '$attrs', function ($scope, $element, $attrs) {\n      var self = this;\n    }]\n  };\n\n  return uiGridMenu;\n}])\n\n.directive('uiGridMenuItem', ['gridUtil', '$compile', 'i18nService', function (gridUtil, $compile, i18nService) {\n  var uiGridMenuItem = {\n    priority: 0,\n    scope: {\n      name: '=',\n      active: '=',\n      action: '=',\n      icon: '=',\n      shown: '=',\n      context: '=',\n      templateUrl: '=',\n      leaveOpen: '=',\n      screenReaderOnly: '='\n    },\n    require: ['?^uiGrid', '^uiGridMenu'],\n    templateUrl: 'ui-grid/uiGridMenuItem',\n    replace: false,\n    compile: function($elm, $attrs) {\n      return {\n        pre: function ($scope, $elm, $attrs, controllers) {\n          var uiGridCtrl = controllers[0],\n              uiGridMenuCtrl = controllers[1];\n\n          if ($scope.templateUrl) {\n            gridUtil.getTemplate($scope.templateUrl)\n                .then(function (contents) {\n                  var template = angular.element(contents);\n\n                  var newElm = $compile(template)($scope);\n                  $elm.replaceWith(newElm);\n                });\n          }\n        },\n        post: function ($scope, $elm, $attrs, controllers) {\n          var uiGridCtrl = controllers[0],\n              uiGridMenuCtrl = controllers[1];\n\n          // TODO(c0bra): validate that shown and active are functions if they're defined. An exception is already thrown above this though\n          // if (typeof($scope.shown) !== 'undefined' && $scope.shown && typeof($scope.shown) !== 'function') {\n          //   throw new TypeError(\"$scope.shown is defined but not a function\");\n          // }\n          if (typeof($scope.shown) === 'undefined' || $scope.shown === null) {\n            $scope.shown = function() { return true; };\n          }\n\n          $scope.itemShown = function () {\n            var context = {};\n            if ($scope.context) {\n              context.context = $scope.context;\n            }\n\n            if (typeof(uiGridCtrl) !== 'undefined' && uiGridCtrl) {\n              context.grid = uiGridCtrl.grid;\n            }\n\n            return $scope.shown.call(context);\n          };\n\n          $scope.itemAction = function($event,title) {\n            gridUtil.logDebug('itemAction');\n            $event.stopPropagation();\n\n            if (typeof($scope.action) === 'function') {\n              var context = {};\n\n              if ($scope.context) {\n                context.context = $scope.context;\n              }\n\n              // Add the grid to the function call context if the uiGrid controller is present\n              if (typeof(uiGridCtrl) !== 'undefined' && uiGridCtrl) {\n                context.grid = uiGridCtrl.grid;\n              }\n\n              $scope.action.call(context, $event, title);\n\n              if ( !$scope.leaveOpen ){\n                $scope.$emit('hide-menu');\n              } else {\n                /*\n                 * XXX: Fix after column refactor\n                 * Ideally the focus would remain on the item.\n                 * However, since there are two menu items that have their 'show' property toggled instead. This is a quick fix.\n                 */\n                gridUtil.focus.bySelector(angular.element(gridUtil.closestElm($elm, \".ui-grid-menu-items\")), 'button[type=button]', true);\n              }\n            }\n          };\n\n          $scope.i18n = i18nService.get();\n        }\n      };\n    }\n  };\n\n  return uiGridMenuItem;\n}]);\n\n})();\n\n(function(){\n  'use strict';\n  /**\n   * @ngdoc overview\n   * @name ui.grid.directive:uiGridOneBind\n   * @summary A group of directives that provide a one time bind to a dom element.\n   * @description A group of directives that provide a one time bind to a dom element.\n   * As one time bindings are not supported in Angular 1.2.* this directive provdes this capability.\n   * This is done to reduce the number of watchers on the dom.\n   * <br/>\n   * <h2>Short Example ({@link ui.grid.directive:uiGridOneBindSrc ui-grid-one-bind-src})</h2>\n   * <pre>\n        <div ng-init=\"imageName = 'myImageDir.jpg'\">\n          <img ui-grid-one-bind-src=\"imageName\"></img>\n        </div>\n     </pre>\n   * Will become:\n   * <pre>\n       <div ng-init=\"imageName = 'myImageDir.jpg'\">\n         <img ui-grid-one-bind-src=\"imageName\" src=\"myImageDir.jpg\"></img>\n       </div>\n     </pre>\n     </br>\n     <h2>Short Example ({@link ui.grid.directive:uiGridOneBindText ui-grid-one-bind-text})</h2>\n   * <pre>\n        <div ng-init=\"text='Add this text'\" ui-grid-one-bind-text=\"text\"></div>\n     </pre>\n   * Will become:\n   * <pre>\n   <div ng-init=\"text='Add this text'\" ui-grid-one-bind-text=\"text\">Add this text</div>\n     </pre>\n     </br>\n   * <b>Note:</b> This behavior is slightly different for the {@link ui.grid.directive:uiGridOneBindIdGrid uiGridOneBindIdGrid}\n   * and {@link ui.grid.directive:uiGridOneBindAriaLabelledbyGrid uiGridOneBindAriaLabelledbyGrid} directives.\n   *\n   */\n  //https://github.com/joshkurz/Black-Belt-AngularJS-Directives/blob/master/directives/Optimization/oneBind.js\n  var oneBinders = angular.module('ui.grid');\n  angular.forEach([\n      /**\n       * @ngdoc directive\n       * @name ui.grid.directive:uiGridOneBindSrc\n       * @memberof ui.grid.directive:uiGridOneBind\n       * @element img\n       * @restrict A\n       * @param {String} uiGridOneBindSrc The angular string you want to bind. Does not support interpolation. Don't use <code>{{scopeElt}}</code> instead use <code>scopeElt</code>.\n       * @description One time binding for the src dom tag.\n       *\n       */\n      {tag: 'Src', method: 'attr'},\n      /**\n       * @ngdoc directive\n       * @name ui.grid.directive:uiGridOneBindText\n       * @element div\n       * @restrict A\n       * @param {String} uiGridOneBindText The angular string you want to bind. Does not support interpolation. Don't use <code>{{scopeElt}}</code> instead use <code>scopeElt</code>.\n       * @description One time binding for the text dom tag.\n       */\n      {tag: 'Text', method: 'text'},\n      /**\n       * @ngdoc directive\n       * @name ui.grid.directive:uiGridOneBindHref\n       * @element div\n       * @restrict A\n       * @param {String} uiGridOneBindHref The angular string you want to bind. Does not support interpolation. Don't use <code>{{scopeElt}}</code> instead use <code>scopeElt</code>.\n       * @description One time binding for the href dom tag. For more information see {@link ui.grid.directive:uiGridOneBind}.\n       */\n      {tag: 'Href', method: 'attr'},\n      /**\n       * @ngdoc directive\n       * @name ui.grid.directive:uiGridOneBindClass\n       * @element div\n       * @restrict A\n       * @param {String} uiGridOneBindClass The angular string you want to bind. Does not support interpolation. Don't use <code>{{scopeElt}}</code> instead use <code>scopeElt</code>.\n       * @param {Object} uiGridOneBindClass The object that you want to bind. At least one of the values in the object must be something other than null or undefined for the watcher to be removed.\n       *                                    this is to prevent the watcher from being removed before the scope is initialized.\n       * @param {Array} uiGridOneBindClass An array of classes to bind to this element.\n       * @description One time binding for the class dom tag. For more information see {@link ui.grid.directive:uiGridOneBind}.\n       */\n      {tag: 'Class', method: 'addClass'},\n      /**\n       * @ngdoc directive\n       * @name ui.grid.directive:uiGridOneBindHtml\n       * @element div\n       * @restrict A\n       * @param {String} uiGridOneBindHtml The angular string you want to bind. Does not support interpolation. Don't use <code>{{scopeElt}}</code> instead use <code>scopeElt</code>.\n       * @description One time binding for the html method on a dom element. For more information see {@link ui.grid.directive:uiGridOneBind}.\n       */\n      {tag: 'Html', method: 'html'},\n      /**\n       * @ngdoc directive\n       * @name ui.grid.directive:uiGridOneBindAlt\n       * @element div\n       * @restrict A\n       * @param {String} uiGridOneBindAlt The angular string you want to bind. Does not support interpolation. Don't use <code>{{scopeElt}}</code> instead use <code>scopeElt</code>.\n       * @description One time binding for the alt dom tag. For more information see {@link ui.grid.directive:uiGridOneBind}.\n       */\n      {tag: 'Alt', method: 'attr'},\n      /**\n       * @ngdoc directive\n       * @name ui.grid.directive:uiGridOneBindStyle\n       * @element div\n       * @restrict A\n       * @param {String} uiGridOneBindStyle The angular string you want to bind. Does not support interpolation. Don't use <code>{{scopeElt}}</code> instead use <code>scopeElt</code>.\n       * @description One time binding for the style dom tag. For more information see {@link ui.grid.directive:uiGridOneBind}.\n       */\n      {tag: 'Style', method: 'css'},\n      /**\n       * @ngdoc directive\n       * @name ui.grid.directive:uiGridOneBindValue\n       * @element div\n       * @restrict A\n       * @param {String} uiGridOneBindValue The angular string you want to bind. Does not support interpolation. Don't use <code>{{scopeElt}}</code> instead use <code>scopeElt</code>.\n       * @description One time binding for the value dom tag. For more information see {@link ui.grid.directive:uiGridOneBind}.\n       */\n      {tag: 'Value', method: 'attr'},\n      /**\n       * @ngdoc directive\n       * @name ui.grid.directive:uiGridOneBindId\n       * @element div\n       * @restrict A\n       * @param {String} uiGridOneBindId The angular string you want to bind. Does not support interpolation. Don't use <code>{{scopeElt}}</code> instead use <code>scopeElt</code>.\n       * @description One time binding for the value dom tag. For more information see {@link ui.grid.directive:uiGridOneBind}.\n       */\n      {tag: 'Id', method: 'attr'},\n      /**\n       * @ngdoc directive\n       * @name ui.grid.directive:uiGridOneBindIdGrid\n       * @element div\n       * @restrict A\n       * @param {String} uiGridOneBindIdGrid The angular string you want to bind. Does not support interpolation. Don't use <code>{{scopeElt}}</code> instead use <code>scopeElt</code>.\n       * @description One time binding for the id dom tag.\n       * <h1>Important Note!</h1>\n       * If the id tag passed as a parameter does <b>not</b> contain the grid id as a substring\n       * then the directive will search the scope and the parent controller (if it is a uiGridController) for the grid.id value.\n       * If this value is found then it is appended to the begining of the id tag. If the grid is not found then the directive throws an error.\n       * This is done in order to ensure uniqueness of id tags across the grid.\n       * This is to prevent two grids in the same document having duplicate id tags.\n       */\n      {tag: 'Id', directiveName:'IdGrid', method: 'attr', appendGridId: true},\n      /**\n       * @ngdoc directive\n       * @name ui.grid.directive:uiGridOneBindTitle\n       * @element div\n       * @restrict A\n       * @param {String} uiGridOneBindTitle The angular string you want to bind. Does not support interpolation. Don't use <code>{{scopeElt}}</code> instead use <code>scopeElt</code>.\n       * @description One time binding for the title dom tag. For more information see {@link ui.grid.directive:uiGridOneBind}.\n       */\n      {tag: 'Title', method: 'attr'},\n      /**\n       * @ngdoc directive\n       * @name ui.grid.directive:uiGridOneBindAriaLabel\n       * @element div\n       * @restrict A\n       * @param {String} uiGridOneBindAriaLabel The angular string you want to bind. Does not support interpolation. Don't use <code>{{scopeElt}}</code> instead use <code>scopeElt</code>.\n       * @description One time binding for the aria-label dom tag. For more information see {@link ui.grid.directive:uiGridOneBind}.\n       *<br/>\n       * <pre>\n            <div ng-init=\"text='Add this text'\" ui-grid-one-bind-aria-label=\"text\"></div>\n         </pre>\n       * Will become:\n       * <pre>\n            <div ng-init=\"text='Add this text'\" ui-grid-one-bind-aria-label=\"text\" aria-label=\"Add this text\"></div>\n         </pre>\n       */\n      {tag: 'Label', method: 'attr', aria:true},\n      /**\n       * @ngdoc directive\n       * @name ui.grid.directive:uiGridOneBindAriaLabelledby\n       * @element div\n       * @restrict A\n       * @param {String} uiGridOneBindAriaLabelledby The angular string you want to bind. Does not support interpolation. Don't use <code>{{scopeElt}}</code> instead use <code>scopeElt</code>.\n       * @description One time binding for the aria-labelledby dom tag. For more information see {@link ui.grid.directive:uiGridOneBind}.\n       *<br/>\n       * <pre>\n            <div ng-init=\"anId = 'gridID32'\" ui-grid-one-bind-aria-labelledby=\"anId\"></div>\n         </pre>\n       * Will become:\n       * <pre>\n            <div ng-init=\"anId = 'gridID32'\" ui-grid-one-bind-aria-labelledby=\"anId\" aria-labelledby=\"gridID32\"></div>\n         </pre>\n       */\n      {tag: 'Labelledby', method: 'attr', aria:true},\n      /**\n       * @ngdoc directive\n       * @name ui.grid.directive:uiGridOneBindAriaLabelledbyGrid\n       * @element div\n       * @restrict A\n       * @param {String} uiGridOneBindAriaLabelledbyGrid The angular string you want to bind. Does not support interpolation. Don't use <code>{{scopeElt}}</code> instead use <code>scopeElt</code>.\n       * @description One time binding for the aria-labelledby dom tag. For more information see {@link ui.grid.directive:uiGridOneBind}.\n       * Works somewhat like {@link ui.grid.directive:uiGridOneBindIdGrid} however this one supports a list of ids (seperated by a space) and will dynamically add the\n       * grid id to each one.\n       *<br/>\n       * <pre>\n            <div ng-init=\"anId = 'gridID32'\" ui-grid-one-bind-aria-labelledby-grid=\"anId\"></div>\n         </pre>\n       * Will become ([grid.id] will be replaced by the actual grid id):\n       * <pre>\n            <div ng-init=\"anId = 'gridID32'\" ui-grid-one-bind-aria-labelledby-grid=\"anId\" aria-labelledby-Grid=\"[grid.id]-gridID32\"></div>\n         </pre>\n       */\n      {tag: 'Labelledby', directiveName:'LabelledbyGrid', appendGridId:true, method: 'attr', aria:true},\n      /**\n       * @ngdoc directive\n       * @name ui.grid.directive:uiGridOneBindAriaDescribedby\n       * @element ANY\n       * @restrict A\n       * @param {String} uiGridOneBindAriaDescribedby The angular string you want to bind. Does not support interpolation. Don't use <code>{{scopeElt}}</code> instead use <code>scopeElt</code>.\n       * @description One time binding for the aria-describedby dom tag. For more information see {@link ui.grid.directive:uiGridOneBind}.\n       *<br/>\n       * <pre>\n            <div ng-init=\"anId = 'gridID32'\" ui-grid-one-bind-aria-describedby=\"anId\"></div>\n         </pre>\n       * Will become:\n       * <pre>\n            <div ng-init=\"anId = 'gridID32'\" ui-grid-one-bind-aria-describedby=\"anId\" aria-describedby=\"gridID32\"></div>\n         </pre>\n       */\n      {tag: 'Describedby', method: 'attr', aria:true},\n      /**\n       * @ngdoc directive\n       * @name ui.grid.directive:uiGridOneBindAriaDescribedbyGrid\n       * @element ANY\n       * @restrict A\n       * @param {String} uiGridOneBindAriaDescribedbyGrid The angular string you want to bind. Does not support interpolation. Don't use <code>{{scopeElt}}</code> instead use <code>scopeElt</code>.\n       * @description One time binding for the aria-labelledby dom tag. For more information see {@link ui.grid.directive:uiGridOneBind}.\n       * Works somewhat like {@link ui.grid.directive:uiGridOneBindIdGrid} however this one supports a list of ids (seperated by a space) and will dynamically add the\n       * grid id to each one.\n       *<br/>\n       * <pre>\n            <div ng-init=\"anId = 'gridID32'\" ui-grid-one-bind-aria-describedby-grid=\"anId\"></div>\n         </pre>\n       * Will become ([grid.id] will be replaced by the actual grid id):\n       * <pre>\n            <div ng-init=\"anId = 'gridID32'\" ui-grid-one-bind-aria-describedby-grid=\"anId\" aria-describedby=\"[grid.id]-gridID32\"></div>\n         </pre>\n       */\n      {tag: 'Describedby', directiveName:'DescribedbyGrid', appendGridId:true, method: 'attr', aria:true}],\n    function(v){\n\n      var baseDirectiveName = 'uiGridOneBind';\n      //If it is an aria tag then append the aria label seperately\n      //This is done because the aria tags are formatted aria-* and the directive name can't have a '-' character in it.\n      //If the diretiveName has to be overridden then it does so here. This is because the tag being modified and the directive sometimes don't match up.\n      var directiveName = (v.aria ? baseDirectiveName + 'Aria' : baseDirectiveName) + (v.directiveName ? v.directiveName : v.tag);\n      oneBinders.directive(directiveName, ['gridUtil', function(gridUtil){\n        return {\n          restrict: 'A',\n          require: ['?uiGrid','?^uiGrid'],\n          link: function(scope, iElement, iAttrs, controllers){\n            /* Appends the grid id to the beginnig of the value. */\n            var appendGridId = function(val){\n              var grid; //Get an instance of the grid if its available\n              //If its available in the scope then we don't need to try to find it elsewhere\n              if (scope.grid) {\n                grid = scope.grid;\n              }\n              //Another possible location to try to find the grid\n              else if (scope.col && scope.col.grid){\n                grid = scope.col.grid;\n              }\n              //Last ditch effort: Search through the provided controllers.\n              else if (!controllers.some( //Go through the controllers till one has the element we need\n                function(controller){\n                  if (controller && controller.grid) {\n                    grid = controller.grid;\n                    return true; //We've found the grid\n                  }\n              })){\n                //We tried our best to find it for you\n                gridUtil.logError(\"[\"+directiveName+\"] A valid grid could not be found to bind id. Are you using this directive \" +\n                                 \"within the correct scope? Trying to generate id: [gridID]-\" + val);\n                throw new Error(\"No valid grid could be found\");\n              }\n\n              if (grid){\n                var idRegex = new RegExp(grid.id.toString());\n                //If the grid id hasn't been appended already in the template declaration\n                if (!idRegex.test(val)){\n                  val = grid.id.toString() + '-' + val;\n                }\n              }\n              return val;\n            };\n\n            // The watch returns a function to remove itself.\n            var rmWatcher = scope.$watch(iAttrs[directiveName], function(newV){\n              if (newV){\n                //If we are trying to add an id element then we also apply the grid id if it isn't already there\n                if (v.appendGridId) {\n                  var newIdString = null;\n                  //Append the id to all of the new ids.\n                  angular.forEach( newV.split(' '), function(s){\n                    newIdString = (newIdString ? (newIdString + ' ') : '') +  appendGridId(s);\n                  });\n                  newV = newIdString;\n                }\n\n                // Append this newValue to the dom element.\n                switch (v.method) {\n                  case 'attr': //The attr method takes two paraams the tag and the value\n                    if (v.aria) {\n                      //If it is an aria element then append the aria prefix\n                      iElement[v.method]('aria-' + v.tag.toLowerCase(),newV);\n                    } else {\n                      iElement[v.method](v.tag.toLowerCase(),newV);\n                    }\n                    break;\n                  case 'addClass':\n                    //Pulled from https://github.com/Pasvaz/bindonce/blob/master/bindonce.js\n                    if (angular.isObject(newV) && !angular.isArray(newV)) {\n                      var results = [];\n                      var nonNullFound = false; //We don't want to remove the binding unless the key is actually defined\n                      angular.forEach(newV, function (value, index) {\n                        if (value !== null && typeof(value) !== \"undefined\"){\n                          nonNullFound = true; //A non null value for a key was found so the object must have been initialized\n                          if (value) {results.push(index);}\n                        }\n                      });\n                      //A non null value for a key wasn't found so assume that the scope values haven't been fully initialized\n                      if (!nonNullFound){\n                        return; // If not initialized then the watcher should not be removed yet.\n                      }\n                      newV = results;\n                    }\n\n                    if (newV) {\n                      iElement.addClass(angular.isArray(newV) ? newV.join(' ') : newV);\n                    } else {\n                      return;\n                    }\n                    break;\n                  default:\n                    iElement[v.method](newV);\n                    break;\n                }\n\n                //Removes the watcher on itself after the bind\n                rmWatcher();\n              }\n            // True ensures that equality is determined using angular.equals instead of ===\n            }, true); //End rm watchers\n          } //End compile function\n        }; //End directive return\n      } // End directive function\n    ]); //End directive\n  }); // End angular foreach\n})();\n\n(function () {\n  'use strict';\n\n  var module = angular.module('ui.grid');\n\n  module.directive('uiGridRenderContainer', ['$timeout', '$document', 'uiGridConstants', 'gridUtil', 'ScrollEvent',\n    function($timeout, $document, uiGridConstants, gridUtil, ScrollEvent) {\n    return {\n      replace: true,\n      transclude: true,\n      templateUrl: 'ui-grid/uiGridRenderContainer',\n      require: ['^uiGrid', 'uiGridRenderContainer'],\n      scope: {\n        containerId: '=',\n        rowContainerName: '=',\n        colContainerName: '=',\n        bindScrollHorizontal: '=',\n        bindScrollVertical: '=',\n        enableVerticalScrollbar: '=',\n        enableHorizontalScrollbar: '='\n      },\n      controller: 'uiGridRenderContainer as RenderContainer',\n      compile: function () {\n        return {\n          pre: function prelink($scope, $elm, $attrs, controllers) {\n\n            var uiGridCtrl = controllers[0];\n            var containerCtrl = controllers[1];\n            var grid = $scope.grid = uiGridCtrl.grid;\n\n            // Verify that the render container for this element exists\n            if (!$scope.rowContainerName) {\n              throw \"No row render container name specified\";\n            }\n            if (!$scope.colContainerName) {\n              throw \"No column render container name specified\";\n            }\n\n            if (!grid.renderContainers[$scope.rowContainerName]) {\n              throw \"Row render container '\" + $scope.rowContainerName + \"' is not registered.\";\n            }\n            if (!grid.renderContainers[$scope.colContainerName]) {\n              throw \"Column render container '\" + $scope.colContainerName + \"' is not registered.\";\n            }\n\n            var rowContainer = $scope.rowContainer = grid.renderContainers[$scope.rowContainerName];\n            var colContainer = $scope.colContainer = grid.renderContainers[$scope.colContainerName];\n\n            containerCtrl.containerId = $scope.containerId;\n            containerCtrl.rowContainer = rowContainer;\n            containerCtrl.colContainer = colContainer;\n          },\n          post: function postlink($scope, $elm, $attrs, controllers) {\n\n            var uiGridCtrl = controllers[0];\n            var containerCtrl = controllers[1];\n\n            var grid = uiGridCtrl.grid;\n            var rowContainer = containerCtrl.rowContainer;\n            var colContainer = containerCtrl.colContainer;\n            var scrollTop = null;\n            var scrollLeft = null;\n\n\n            var renderContainer = grid.renderContainers[$scope.containerId];\n\n            // Put the container name on this element as a class\n            $elm.addClass('ui-grid-render-container-' + $scope.containerId);\n\n            // Scroll the render container viewport when the mousewheel is used\n            gridUtil.on.mousewheel($elm, function (event) {\n              var scrollEvent = new ScrollEvent(grid, rowContainer, colContainer, ScrollEvent.Sources.RenderContainerMouseWheel);\n              if (event.deltaY !== 0) {\n                var scrollYAmount = event.deltaY * -1 * event.deltaFactor;\n\n                scrollTop = containerCtrl.viewport[0].scrollTop;\n\n                // Get the scroll percentage\n                scrollEvent.verticalScrollLength = rowContainer.getVerticalScrollLength();\n                var scrollYPercentage = (scrollTop + scrollYAmount) / scrollEvent.verticalScrollLength;\n\n                // If we should be scrolled 100%, make sure the scrollTop matches the maximum scroll length\n                //   Viewports that have \"overflow: hidden\" don't let the mousewheel scroll all the way to the bottom without this check\n                if (scrollYPercentage >= 1 && scrollTop < scrollEvent.verticalScrollLength) {\n                  containerCtrl.viewport[0].scrollTop = scrollEvent.verticalScrollLength;\n                }\n\n                // Keep scrollPercentage within the range 0-1.\n                if (scrollYPercentage < 0) { scrollYPercentage = 0; }\n                else if (scrollYPercentage > 1) { scrollYPercentage = 1; }\n\n                scrollEvent.y = { percentage: scrollYPercentage, pixels: scrollYAmount };\n              }\n              if (event.deltaX !== 0) {\n                var scrollXAmount = event.deltaX * event.deltaFactor;\n\n                // Get the scroll percentage\n                scrollLeft = gridUtil.normalizeScrollLeft(containerCtrl.viewport, grid);\n                scrollEvent.horizontalScrollLength = (colContainer.getCanvasWidth() - colContainer.getViewportWidth());\n                var scrollXPercentage = (scrollLeft + scrollXAmount) / scrollEvent.horizontalScrollLength;\n\n                // Keep scrollPercentage within the range 0-1.\n                if (scrollXPercentage < 0) { scrollXPercentage = 0; }\n                else if (scrollXPercentage > 1) { scrollXPercentage = 1; }\n\n                scrollEvent.x = { percentage: scrollXPercentage, pixels: scrollXAmount };\n              }\n\n              // Let the parent container scroll if the grid is already at the top/bottom\n              if ((event.deltaY !== 0 && (scrollEvent.atTop(scrollTop) || scrollEvent.atBottom(scrollTop))) ||\n                  (event.deltaX !== 0 && (scrollEvent.atLeft(scrollLeft) || scrollEvent.atRight(scrollLeft)))) {\n                //parent controller scrolls\n              }\n              else {\n                event.preventDefault();\n                scrollEvent.fireThrottledScrollingEvent('', scrollEvent);\n              }\n\n            });\n\n            $elm.bind('$destroy', function() {\n              $elm.unbind('keydown');\n\n              ['touchstart', 'touchmove', 'touchend','keydown', 'wheel', 'mousewheel', 'DomMouseScroll', 'MozMousePixelScroll'].forEach(function (eventName) {\n                $elm.unbind(eventName);\n              });\n            });\n\n            // TODO(c0bra): Handle resizing the inner canvas based on the number of elements\n            function update() {\n              var ret = '';\n\n              var canvasWidth = colContainer.canvasWidth;\n              var viewportWidth = colContainer.getViewportWidth();\n\n              var canvasHeight = rowContainer.getCanvasHeight();\n\n              //add additional height for scrollbar on left and right container\n              //if ($scope.containerId !== 'body') {\n              //  canvasHeight -= grid.scrollbarHeight;\n              //}\n\n              var viewportHeight = rowContainer.getViewportHeight();\n              //shorten the height to make room for a scrollbar placeholder\n              if (colContainer.needsHScrollbarPlaceholder()) {\n                viewportHeight -= grid.scrollbarHeight;\n              }\n\n              var headerViewportWidth,\n                  footerViewportWidth;\n              headerViewportWidth = footerViewportWidth = colContainer.getHeaderViewportWidth();\n\n              // Set canvas dimensions\n              ret += '\\n .grid' + uiGridCtrl.grid.id + ' .ui-grid-render-container-' + $scope.containerId + ' .ui-grid-canvas { width: ' + canvasWidth + 'px; height: ' + canvasHeight + 'px; }';\n\n              ret += '\\n .grid' + uiGridCtrl.grid.id + ' .ui-grid-render-container-' + $scope.containerId + ' .ui-grid-header-canvas { width: ' + (canvasWidth + grid.scrollbarWidth) + 'px; }';\n\n              if (renderContainer.explicitHeaderCanvasHeight) {\n                ret += '\\n .grid' + uiGridCtrl.grid.id + ' .ui-grid-render-container-' + $scope.containerId + ' .ui-grid-header-canvas { height: ' + renderContainer.explicitHeaderCanvasHeight + 'px; }';\n              }\n              else {\n                ret += '\\n .grid' + uiGridCtrl.grid.id + ' .ui-grid-render-container-' + $scope.containerId + ' .ui-grid-header-canvas { height: inherit; }';\n              }\n\n              ret += '\\n .grid' + uiGridCtrl.grid.id + ' .ui-grid-render-container-' + $scope.containerId + ' .ui-grid-viewport { width: ' + viewportWidth + 'px; height: ' + viewportHeight + 'px; }';\n              ret += '\\n .grid' + uiGridCtrl.grid.id + ' .ui-grid-render-container-' + $scope.containerId + ' .ui-grid-header-viewport { width: ' + headerViewportWidth + 'px; }';\n\n              ret += '\\n .grid' + uiGridCtrl.grid.id + ' .ui-grid-render-container-' + $scope.containerId + ' .ui-grid-footer-canvas { width: ' + (canvasWidth + grid.scrollbarWidth) + 'px; }';\n              ret += '\\n .grid' + uiGridCtrl.grid.id + ' .ui-grid-render-container-' + $scope.containerId + ' .ui-grid-footer-viewport { width: ' + footerViewportWidth + 'px; }';\n\n              return ret;\n            }\n\n            uiGridCtrl.grid.registerStyleComputation({\n              priority: 6,\n              func: update\n            });\n          }\n        };\n      }\n    };\n\n  }]);\n\n  module.controller('uiGridRenderContainer', ['$scope', 'gridUtil', function ($scope, gridUtil) {\n\n  }]);\n\n})();\n\n(function(){\n  'use strict';\n\n  angular.module('ui.grid').directive('uiGridRow', ['gridUtil', function(gridUtil) {\n    return {\n      replace: true,\n      // priority: 2001,\n      // templateUrl: 'ui-grid/ui-grid-row',\n      require: ['^uiGrid', '^uiGridRenderContainer'],\n      scope: {\n         row: '=uiGridRow',\n         //rowRenderIndex is added to scope to give the true visual index of the row to any directives that need it\n         rowRenderIndex: '='\n      },\n      compile: function() {\n        return {\n          pre: function($scope, $elm, $attrs, controllers) {\n            var uiGridCtrl = controllers[0];\n            var containerCtrl = controllers[1];\n\n            var grid = uiGridCtrl.grid;\n\n            $scope.grid = uiGridCtrl.grid;\n            $scope.colContainer = containerCtrl.colContainer;\n\n            // Function for attaching the template to this scope\n            var clonedElement, cloneScope;\n            function compileTemplate() {\n              $scope.row.getRowTemplateFn.then(function (compiledElementFn) {\n                // var compiledElementFn = $scope.row.compiledElementFn;\n\n                // Create a new scope for the contents of this row, so we can destroy it later if need be\n                var newScope = $scope.$new();\n\n                compiledElementFn(newScope, function (newElm, scope) {\n                  // If we already have a cloned element, we need to remove it and destroy its scope\n                  if (clonedElement) {\n                    clonedElement.remove();\n                    cloneScope.$destroy();\n                  }\n\n                  // Empty the row and append the new element\n                  $elm.empty().append(newElm);\n\n                  // Save the new cloned element and scope\n                  clonedElement = newElm;\n                  cloneScope = newScope;\n                });\n              });\n            }\n\n            // Initially attach the compiled template to this scope\n            compileTemplate();\n\n            // If the row's compiled element function changes, we need to replace this element's contents with the new compiled template\n            $scope.$watch('row.getRowTemplateFn', function (newFunc, oldFunc) {\n              if (newFunc !== oldFunc) {\n                compileTemplate();\n              }\n            });\n          },\n          post: function($scope, $elm, $attrs, controllers) {\n\n          }\n        };\n      }\n    };\n  }]);\n\n})();\n(function(){\n// 'use strict';\n\n  /**\n   * @ngdoc directive\n   * @name ui.grid.directive:uiGridStyle\n   * @element style\n   * @restrict A\n   *\n   * @description\n   * Allows us to interpolate expressions in `<style>` elements. Angular doesn't do this by default as it can/will/might? break in IE8.\n   *\n   * @example\n   <doc:example module=\"app\">\n   <doc:source>\n   <script>\n   var app = angular.module('app', ['ui.grid']);\n\n   app.controller('MainCtrl', ['$scope', function ($scope) {\n          $scope.myStyle = '.blah { border: 1px solid }';\n        }]);\n   </script>\n\n   <div ng-controller=\"MainCtrl\">\n   <style ui-grid-style>{{ myStyle }}</style>\n   <span class=\"blah\">I am in a box.</span>\n   </div>\n   </doc:source>\n   <doc:scenario>\n      it('should apply the right class to the element', function () {\n        element(by.css('.blah')).getCssValue('border-top-width')\n          .then(function(c) {\n            expect(c).toContain('1px');\n          });\n      });\n   </doc:scenario>\n   </doc:example>\n   */\n\n\n  angular.module('ui.grid').directive('uiGridStyle', ['gridUtil', '$interpolate', function(gridUtil, $interpolate) {\n    return {\n      // restrict: 'A',\n      // priority: 1000,\n      // require: '?^uiGrid',\n      link: function($scope, $elm, $attrs, uiGridCtrl) {\n        // gridUtil.logDebug('ui-grid-style link');\n        // if (uiGridCtrl === undefined) {\n        //    gridUtil.logWarn('[ui-grid-style link] uiGridCtrl is undefined!');\n        // }\n\n        var interpolateFn = $interpolate($elm.text(), true);\n\n        if (interpolateFn) {\n          $scope.$watch(interpolateFn, function(value) {\n            $elm.text(value);\n          });\n        }\n\n          // uiGridCtrl.recalcRowStyles = function() {\n          //   var offset = (scope.options.offsetTop || 0) - (scope.options.excessRows * scope.options.rowHeight);\n          //   var rowHeight = scope.options.rowHeight;\n\n          //   var ret = '';\n          //   var rowStyleCount = uiGridCtrl.minRowsToRender() + (scope.options.excessRows * 2);\n          //   for (var i = 1; i <= rowStyleCount; i++) {\n          //     ret = ret + ' .grid' + scope.gridId + ' .ui-grid-row:nth-child(' + i + ') { top: ' + offset + 'px; }';\n          //     offset = offset + rowHeight;\n          //   }\n\n          //   scope.rowStyles = ret;\n          // };\n\n          // uiGridCtrl.styleComputions.push(uiGridCtrl.recalcRowStyles);\n\n      }\n    };\n  }]);\n\n})();\n\n(function(){\n  'use strict';\n\n  angular.module('ui.grid').directive('uiGridViewport', ['gridUtil','ScrollEvent','uiGridConstants', '$log',\n    function(gridUtil, ScrollEvent, uiGridConstants, $log) {\n      return {\n        replace: true,\n        scope: {},\n        controllerAs: 'Viewport',\n        templateUrl: 'ui-grid/uiGridViewport',\n        require: ['^uiGrid', '^uiGridRenderContainer'],\n        link: function($scope, $elm, $attrs, controllers) {\n          // gridUtil.logDebug('viewport post-link');\n\n          var uiGridCtrl = controllers[0];\n          var containerCtrl = controllers[1];\n\n          $scope.containerCtrl = containerCtrl;\n\n          var rowContainer = containerCtrl.rowContainer;\n          var colContainer = containerCtrl.colContainer;\n\n          var grid = uiGridCtrl.grid;\n\n          $scope.grid = uiGridCtrl.grid;\n\n          // Put the containers in scope so we can get rows and columns from them\n          $scope.rowContainer = containerCtrl.rowContainer;\n          $scope.colContainer = containerCtrl.colContainer;\n\n          // Register this viewport with its container\n          containerCtrl.viewport = $elm;\n\n\n          $elm.on('scroll', scrollHandler);\n\n          var ignoreScroll = false;\n\n          function scrollHandler(evt) {\n            //Leaving in this commented code in case it can someday be used\n            //It does improve performance, but because the horizontal scroll is normalized,\n            //  using this code will lead to the column header getting slightly out of line with columns\n            //\n            //if (ignoreScroll && (grid.isScrollingHorizontally || grid.isScrollingHorizontally)) {\n            //  //don't ask for scrollTop if we just set it\n            //  ignoreScroll = false;\n            //  return;\n            //}\n            //ignoreScroll = true;\n\n            var newScrollTop = $elm[0].scrollTop;\n            var newScrollLeft = gridUtil.normalizeScrollLeft($elm, grid);\n\n            var vertScrollPercentage = rowContainer.scrollVertical(newScrollTop);\n            var horizScrollPercentage = colContainer.scrollHorizontal(newScrollLeft);\n\n            var scrollEvent = new ScrollEvent(grid, rowContainer, colContainer, ScrollEvent.Sources.ViewPortScroll);\n            scrollEvent.newScrollLeft = newScrollLeft;\n            scrollEvent.newScrollTop = newScrollTop;\n            if ( horizScrollPercentage > -1 ){\n              scrollEvent.x = { percentage: horizScrollPercentage };\n            }\n\n            if ( vertScrollPercentage > -1 ){\n              scrollEvent.y = { percentage: vertScrollPercentage };\n            }\n\n            grid.scrollContainers($scope.$parent.containerId, scrollEvent);\n          }\n\n          if ($scope.$parent.bindScrollVertical) {\n            grid.addVerticalScrollSync($scope.$parent.containerId, syncVerticalScroll);\n          }\n\n          if ($scope.$parent.bindScrollHorizontal) {\n            grid.addHorizontalScrollSync($scope.$parent.containerId, syncHorizontalScroll);\n            grid.addHorizontalScrollSync($scope.$parent.containerId + 'header', syncHorizontalHeader);\n            grid.addHorizontalScrollSync($scope.$parent.containerId + 'footer', syncHorizontalFooter);\n          }\n\n          function syncVerticalScroll(scrollEvent){\n            containerCtrl.prevScrollArgs = scrollEvent;\n            var newScrollTop = scrollEvent.getNewScrollTop(rowContainer,containerCtrl.viewport);\n            $elm[0].scrollTop = newScrollTop;\n\n          }\n\n          function syncHorizontalScroll(scrollEvent){\n            containerCtrl.prevScrollArgs = scrollEvent;\n            var newScrollLeft = scrollEvent.getNewScrollLeft(colContainer, containerCtrl.viewport);\n            $elm[0].scrollLeft =  gridUtil.denormalizeScrollLeft(containerCtrl.viewport,newScrollLeft, grid);\n          }\n\n          function syncHorizontalHeader(scrollEvent){\n            var newScrollLeft = scrollEvent.getNewScrollLeft(colContainer, containerCtrl.viewport);\n            if (containerCtrl.headerViewport) {\n              containerCtrl.headerViewport.scrollLeft = gridUtil.denormalizeScrollLeft(containerCtrl.viewport,newScrollLeft, grid);\n            }\n          }\n\n          function syncHorizontalFooter(scrollEvent){\n            var newScrollLeft = scrollEvent.getNewScrollLeft(colContainer, containerCtrl.viewport);\n            if (containerCtrl.footerViewport) {\n              containerCtrl.footerViewport.scrollLeft =  gridUtil.denormalizeScrollLeft(containerCtrl.viewport,newScrollLeft, grid);\n            }\n          }\n\n\n        },\n        controller: ['$scope', function ($scope) {\n          this.rowStyle = function (index) {\n            var rowContainer = $scope.rowContainer;\n            var colContainer = $scope.colContainer;\n\n            var styles = {};\n\n            if (index === 0 && rowContainer.currentTopRow !== 0) {\n              // The row offset-top is just the height of the rows above the current top-most row, which are no longer rendered\n              var hiddenRowWidth = (rowContainer.currentTopRow) * rowContainer.grid.options.rowHeight;\n\n              // return { 'margin-top': hiddenRowWidth + 'px' };\n              styles['margin-top'] = hiddenRowWidth + 'px';\n            }\n\n            if (colContainer.currentFirstColumn !== 0) {\n              if (colContainer.grid.isRTL()) {\n                styles['margin-right'] = colContainer.columnOffset + 'px';\n              }\n              else {\n                styles['margin-left'] = colContainer.columnOffset + 'px';\n              }\n            }\n\n            return styles;\n          };\n        }]\n      };\n    }\n  ]);\n\n})();\n\n(function() {\n\nangular.module('ui.grid')\n.directive('uiGridVisible', function uiGridVisibleAction() {\n  return function ($scope, $elm, $attr) {\n    $scope.$watch($attr.uiGridVisible, function (visible) {\n        // $elm.css('visibility', visible ? 'visible' : 'hidden');\n        $elm[visible ? 'removeClass' : 'addClass']('ui-grid-invisible');\n    });\n  };\n});\n\n})();\n(function () {\n  'use strict';\n\n  angular.module('ui.grid').controller('uiGridController', ['$scope', '$element', '$attrs', 'gridUtil', '$q', 'uiGridConstants',\n                    '$templateCache', 'gridClassFactory', '$timeout', '$parse', '$compile',\n    function ($scope, $elm, $attrs, gridUtil, $q, uiGridConstants,\n              $templateCache, gridClassFactory, $timeout, $parse, $compile) {\n      // gridUtil.logDebug('ui-grid controller');\n\n      var self = this;\n\n      self.grid = gridClassFactory.createGrid($scope.uiGrid);\n\n      //assign $scope.$parent if appScope not already assigned\n      self.grid.appScope = self.grid.appScope || $scope.$parent;\n\n      $elm.addClass('grid' + self.grid.id);\n      self.grid.rtl = gridUtil.getStyles($elm[0])['direction'] === 'rtl';\n\n\n      // angular.extend(self.grid.options, );\n\n      //all properties of grid are available on scope\n      $scope.grid = self.grid;\n\n      if ($attrs.uiGridColumns) {\n        $attrs.$observe('uiGridColumns', function(value) {\n          self.grid.options.columnDefs = value;\n          self.grid.buildColumns()\n            .then(function(){\n              self.grid.preCompileCellTemplates();\n\n              self.grid.refreshCanvas(true);\n            });\n        });\n      }\n\n\n      // if fastWatch is set we watch only the length and the reference, not every individual object\n      var deregFunctions = [];\n      if (self.grid.options.fastWatch) {\n        self.uiGrid = $scope.uiGrid;\n        if (angular.isString($scope.uiGrid.data)) {\n          deregFunctions.push( $scope.$parent.$watch($scope.uiGrid.data, dataWatchFunction) );\n          deregFunctions.push( $scope.$parent.$watch(function() {\n            if ( self.grid.appScope[$scope.uiGrid.data] ){\n              return self.grid.appScope[$scope.uiGrid.data].length; \n            } else {\n              return undefined;\n            } \n          }, dataWatchFunction) );\n        } else {\n          deregFunctions.push( $scope.$parent.$watch(function() { return $scope.uiGrid.data; }, dataWatchFunction) );\n          deregFunctions.push( $scope.$parent.$watch(function() { return $scope.uiGrid.data.length; }, dataWatchFunction) );\n        }\n        deregFunctions.push( $scope.$parent.$watch(function() { return $scope.uiGrid.columnDefs; }, columnDefsWatchFunction) );\n        deregFunctions.push( $scope.$parent.$watch(function() { return $scope.uiGrid.columnDefs.length; }, columnDefsWatchFunction) );\n      } else {\n        if (angular.isString($scope.uiGrid.data)) {\n          deregFunctions.push( $scope.$parent.$watchCollection($scope.uiGrid.data, dataWatchFunction) );\n        } else {\n          deregFunctions.push( $scope.$parent.$watchCollection(function() { return $scope.uiGrid.data; }, dataWatchFunction) );\n        }\n        deregFunctions.push( $scope.$parent.$watchCollection(function() { return $scope.uiGrid.columnDefs; }, columnDefsWatchFunction) );\n      }\n      \n\n      function columnDefsWatchFunction(n, o) {\n        if (n && n !== o) {\n          self.grid.options.columnDefs = n;\n          self.grid.buildColumns({ orderByColumnDefs: true })\n            .then(function(){\n\n              self.grid.preCompileCellTemplates();\n\n              self.grid.callDataChangeCallbacks(uiGridConstants.dataChange.COLUMN);\n            });\n        }\n      }\n\n      function dataWatchFunction(newData) {\n        // gridUtil.logDebug('dataWatch fired');\n        var promises = [];\n        \n        if ( self.grid.options.fastWatch ){\n          if (angular.isString($scope.uiGrid.data)) {\n            newData = self.grid.appScope[$scope.uiGrid.data];\n          } else {\n            newData = $scope.uiGrid.data;\n          }\n        }\n        \n        if (newData) {\n          if (\n            // If we have no columns (i.e. columns length is either 0 or equal to the number of row header columns, which don't count because they're created automatically)\n            self.grid.columns.length === (self.grid.rowHeaderColumns ? self.grid.rowHeaderColumns.length : 0) &&\n            // ... and we don't have a ui-grid-columns attribute, which would define columns for us\n            !$attrs.uiGridColumns &&\n            // ... and we have no pre-defined columns\n            self.grid.options.columnDefs.length === 0 &&\n            // ... but we DO have data\n            newData.length > 0\n          ) {\n            // ... then build the column definitions from the data that we have\n            self.grid.buildColumnDefsFromData(newData);\n          }\n\n          // If we either have some columns defined, or some data defined\n          if (self.grid.options.columnDefs.length > 0 || newData.length > 0) {\n            // Build the column set, then pre-compile the column cell templates\n            promises.push(self.grid.buildColumns()\n              .then(function() {\n                self.grid.preCompileCellTemplates();\n              }));\n          }\n\n          $q.all(promises).then(function() {\n            self.grid.modifyRows(newData)\n              .then(function () {\n                // if (self.viewport) {\n                  self.grid.redrawInPlace(true);\n                // }\n\n                $scope.$evalAsync(function() {\n                  self.grid.refreshCanvas(true);\n                  self.grid.callDataChangeCallbacks(uiGridConstants.dataChange.ROW);\n                });\n              });\n          });\n        }\n      }\n\n      var styleWatchDereg = $scope.$watch(function () { return self.grid.styleComputations; }, function() {\n        self.grid.refreshCanvas(true);\n      });\n\n      $scope.$on('$destroy', function() {\n        deregFunctions.forEach( function( deregFn ){ deregFn(); });\n        styleWatchDereg();\n      });\n\n      self.fireEvent = function(eventName, args) {\n        // Add the grid to the event arguments if it's not there\n        if (typeof(args) === 'undefined' || args === undefined) {\n          args = {};\n        }\n\n        if (typeof(args.grid) === 'undefined' || args.grid === undefined) {\n          args.grid = self.grid;\n        }\n\n        $scope.$broadcast(eventName, args);\n      };\n\n      self.innerCompile = function innerCompile(elm) {\n        $compile(elm)($scope);\n      };\n\n    }]);\n\n/**\n *  @ngdoc directive\n *  @name ui.grid.directive:uiGrid\n *  @element div\n *  @restrict EA\n *  @param {Object} uiGrid Options for the grid to use\n *\n *  @description Create a very basic grid.\n *\n *  @example\n    <example module=\"app\">\n      <file name=\"app.js\">\n        var app = angular.module('app', ['ui.grid']);\n\n        app.controller('MainCtrl', ['$scope', function ($scope) {\n          $scope.data = [\n            { name: 'Bob', title: 'CEO' },\n            { name: 'Frank', title: 'Lowly Developer' }\n          ];\n        }]);\n      </file>\n      <file name=\"index.html\">\n        <div ng-controller=\"MainCtrl\">\n          <div ui-grid=\"{ data: data }\"></div>\n        </div>\n      </file>\n    </example>\n */\nangular.module('ui.grid').directive('uiGrid', uiGridDirective);\n\nuiGridDirective.$inject = ['$compile', '$templateCache', '$timeout', '$window', 'gridUtil', 'uiGridConstants'];\nfunction uiGridDirective($compile, $templateCache, $timeout, $window, gridUtil, uiGridConstants) {\n  return {\n    templateUrl: 'ui-grid/ui-grid',\n    scope: {\n      uiGrid: '='\n    },\n    replace: true,\n    transclude: true,\n    controller: 'uiGridController',\n    compile: function () {\n      return {\n        post: function ($scope, $elm, $attrs, uiGridCtrl) {\n          var grid = uiGridCtrl.grid;\n          // Initialize scrollbars (TODO: move to controller??)\n          uiGridCtrl.scrollbars = [];\n          grid.element = $elm;\n\n\n          // See if the grid has a rendered width, if not, wait a bit and try again\n          var sizeCheckInterval = 100; // ms\n          var maxSizeChecks = 20; // 2 seconds total\n          var sizeChecks = 0;\n\n          // Setup (event listeners) the grid\n          setup();\n\n          // And initialize it\n          init();\n\n          // Mark rendering complete so API events can happen\n          grid.renderingComplete();\n\n          // If the grid doesn't have size currently, wait for a bit to see if it gets size\n          checkSize();\n\n          /*-- Methods --*/\n\n          function checkSize() {\n            // If the grid has no width and we haven't checked more than <maxSizeChecks> times, check again in <sizeCheckInterval> milliseconds\n            if ($elm[0].offsetWidth <= 0 && sizeChecks < maxSizeChecks) {\n              setTimeout(checkSize, sizeCheckInterval);\n              sizeChecks++;\n            }\n            else {\n              $timeout(init);\n            }\n          }\n\n          // Setup event listeners and watchers\n          function setup() {\n            // Bind to window resize events\n            angular.element($window).on('resize', gridResize);\n\n            // Unbind from window resize events when the grid is destroyed\n            $elm.on('$destroy', function () {\n              angular.element($window).off('resize', gridResize);\n            });\n\n            // If we add a left container after render, we need to watch and react\n            $scope.$watch(function () { return grid.hasLeftContainer();}, function (newValue, oldValue) {\n              if (newValue === oldValue) {\n                return;\n              }\n              grid.refreshCanvas(true);\n            });\n\n            // If we add a right container after render, we need to watch and react\n            $scope.$watch(function () { return grid.hasRightContainer();}, function (newValue, oldValue) {\n              if (newValue === oldValue) {\n                return;\n              }\n              grid.refreshCanvas(true);\n            });\n          }\n\n          // Initialize the directive\n          function init() {\n            grid.gridWidth = $scope.gridWidth = gridUtil.elementWidth($elm);\n\n            // Default canvasWidth to the grid width, in case we don't get any column definitions to calculate it from\n            grid.canvasWidth = uiGridCtrl.grid.gridWidth;\n\n            grid.gridHeight = $scope.gridHeight = gridUtil.elementHeight($elm);\n\n            // If the grid isn't tall enough to fit a single row, it's kind of useless. Resize it to fit a minimum number of rows\n            if (grid.gridHeight < grid.options.rowHeight && grid.options.enableMinHeightCheck) {\n              autoAdjustHeight();\n            }\n\n            // Run initial canvas refresh\n            grid.refreshCanvas(true);\n          }\n\n          // Set the grid's height ourselves in the case that its height would be unusably small\n          function autoAdjustHeight() {\n            // Figure out the new height\n            var contentHeight = grid.options.minRowsToShow * grid.options.rowHeight;\n            var headerHeight = grid.options.showHeader ? grid.options.headerRowHeight : 0;\n            var footerHeight = grid.calcFooterHeight();\n            \n            var scrollbarHeight = 0;\n            if (grid.options.enableHorizontalScrollbar === uiGridConstants.scrollbars.ALWAYS) {\n              scrollbarHeight = gridUtil.getScrollbarWidth();\n            }\n\n            var maxNumberOfFilters = 0;\n            // Calculates the maximum number of filters in the columns\n            angular.forEach(grid.options.columnDefs, function(col) {\n              if (col.hasOwnProperty('filter')) {\n                if (maxNumberOfFilters < 1) {\n                    maxNumberOfFilters = 1;\n                }\n              }\n              else if (col.hasOwnProperty('filters')) {\n                if (maxNumberOfFilters < col.filters.length) {\n                    maxNumberOfFilters = col.filters.length;\n                }\n              }\n            });\n\n            if (grid.options.enableFiltering) {\n              var allColumnsHaveFilteringTurnedOff = grid.options.columnDefs.every(function(col) {\n                return col.enableFiltering === false;\n              });\n\n              if (!allColumnsHaveFilteringTurnedOff) {\n                maxNumberOfFilters++;\n              }\n            }\n\n            var filterHeight = maxNumberOfFilters * headerHeight;\n\n            var newHeight = headerHeight + contentHeight + footerHeight + scrollbarHeight + filterHeight;\n\n            $elm.css('height', newHeight + 'px');\n\n            grid.gridHeight = $scope.gridHeight = gridUtil.elementHeight($elm);\n          }\n\n          // Resize the grid on window resize events\n          function gridResize($event) {\n            grid.gridWidth = $scope.gridWidth = gridUtil.elementWidth($elm);\n            grid.gridHeight = $scope.gridHeight = gridUtil.elementHeight($elm);\n\n            grid.refreshCanvas(true);\n          }\n        }\n      };\n    }\n  };\n}\n\n})();\n\n(function(){\n  'use strict';\n\n  // TODO: rename this file to ui-grid-pinned-container.js\n\n  angular.module('ui.grid').directive('uiGridPinnedContainer', ['gridUtil', function (gridUtil) {\n    return {\n      restrict: 'EA',\n      replace: true,\n      template: '<div class=\"ui-grid-pinned-container\"><div ui-grid-render-container container-id=\"side\" row-container-name=\"\\'body\\'\" col-container-name=\"side\" bind-scroll-vertical=\"true\" class=\"{{ side }} ui-grid-render-container-{{ side }}\"></div></div>',\n      scope: {\n        side: '=uiGridPinnedContainer'\n      },\n      require: '^uiGrid',\n      compile: function compile() {\n        return {\n          post: function ($scope, $elm, $attrs, uiGridCtrl) {\n            // gridUtil.logDebug('ui-grid-pinned-container ' + $scope.side + ' link');\n\n            var grid = uiGridCtrl.grid;\n\n            var myWidth = 0;\n\n            $elm.addClass('ui-grid-pinned-container-' + $scope.side);\n\n            // Monkey-patch the viewport width function\n            if ($scope.side === 'left' || $scope.side === 'right') {\n              grid.renderContainers[$scope.side].getViewportWidth = monkeyPatchedGetViewportWidth;\n            }\n\n            function monkeyPatchedGetViewportWidth() {\n              /*jshint validthis: true */\n              var self = this;\n\n              var viewportWidth = 0;\n              self.visibleColumnCache.forEach(function (column) {\n                viewportWidth += column.drawnWidth;\n              });\n\n              var adjustment = self.getViewportAdjustment();\n\n              viewportWidth = viewportWidth + adjustment.width;\n\n              return viewportWidth;\n            }\n\n            function updateContainerWidth() {\n              if ($scope.side === 'left' || $scope.side === 'right') {\n                var cols = grid.renderContainers[$scope.side].visibleColumnCache;\n                var width = 0;\n                for (var i = 0; i < cols.length; i++) {\n                  var col = cols[i];\n                  width += col.drawnWidth || col.width || 0;\n                }\n\n                return width;\n              }\n            }\n\n            function updateContainerDimensions() {\n              var ret = '';\n\n              // Column containers\n              if ($scope.side === 'left' || $scope.side === 'right') {\n                myWidth = updateContainerWidth();\n\n                // gridUtil.logDebug('myWidth', myWidth);\n\n                // TODO(c0bra): Subtract sum of col widths from grid viewport width and update it\n                $elm.attr('style', null);\n\n             //   var myHeight = grid.renderContainers.body.getViewportHeight(); // + grid.horizontalScrollbarHeight;\n\n                ret += '.grid' + grid.id + ' .ui-grid-pinned-container-' + $scope.side + ', .grid' + grid.id + ' .ui-grid-pinned-container-' + $scope.side + ' .ui-grid-render-container-' + $scope.side + ' .ui-grid-viewport { width: ' + myWidth + 'px; } ';\n              }\n\n              return ret;\n            }\n\n            grid.renderContainers.body.registerViewportAdjuster(function (adjustment) {\n              myWidth = updateContainerWidth();\n\n              // Subtract our own width\n              adjustment.width -= myWidth;\n              adjustment.side = $scope.side;\n\n              return adjustment;\n            });\n\n            // Register style computation to adjust for columns in `side`'s render container\n            grid.registerStyleComputation({\n              priority: 15,\n              func: updateContainerDimensions\n            });\n          }\n        };\n      }\n    };\n  }]);\n})();\n\n(function(){\n\nangular.module('ui.grid')\n.factory('Grid', ['$q', '$compile', '$parse', 'gridUtil', 'uiGridConstants', 'GridOptions', 'GridColumn', 'GridRow', 'GridApi', 'rowSorter', 'rowSearcher', 'GridRenderContainer', '$timeout','ScrollEvent',\n    function($q, $compile, $parse, gridUtil, uiGridConstants, GridOptions, GridColumn, GridRow, GridApi, rowSorter, rowSearcher, GridRenderContainer, $timeout, ScrollEvent) {\n\n  /**\n   * @ngdoc object\n   * @name ui.grid.core.api:PublicApi\n   * @description Public Api for the core grid features\n   *\n   */\n\n  /**\n   * @ngdoc function\n   * @name ui.grid.class:Grid\n   * @description Grid is the main viewModel.  Any properties or methods needed to maintain state are defined in\n   * this prototype.  One instance of Grid is created per Grid directive instance.\n   * @param {object} options Object map of options to pass into the grid. An 'id' property is expected.\n   */\n  var Grid = function Grid(options) {\n    var self = this;\n    // Get the id out of the options, then remove it\n    if (options !== undefined && typeof(options.id) !== 'undefined' && options.id) {\n      if (!/^[_a-zA-Z0-9-]+$/.test(options.id)) {\n        throw new Error(\"Grid id '\" + options.id + '\" is invalid. It must follow CSS selector syntax rules.');\n      }\n    }\n    else {\n      throw new Error('No ID provided. An ID must be given when creating a grid.');\n    }\n\n    self.id = options.id;\n    delete options.id;\n\n    // Get default options\n    self.options = GridOptions.initialize( options );\n\n    /**\n     * @ngdoc object\n     * @name appScope\n     * @propertyOf ui.grid.class:Grid\n     * @description reference to the application scope (the parent scope of the ui-grid element).  Assigned in ui-grid controller\n     * <br/>\n     * use gridOptions.appScopeProvider to override the default assignment of $scope.$parent with any reference\n     */\n    self.appScope = self.options.appScopeProvider;\n\n    self.headerHeight = self.options.headerRowHeight;\n\n\n    /**\n     * @ngdoc object\n     * @name footerHeight\n     * @propertyOf ui.grid.class:Grid\n     * @description returns the total footer height gridFooter + columnFooter\n     */\n    self.footerHeight = self.calcFooterHeight();\n\n\n    /**\n     * @ngdoc object\n     * @name columnFooterHeight\n     * @propertyOf ui.grid.class:Grid\n     * @description returns the total column footer height\n     */\n    self.columnFooterHeight = self.calcColumnFooterHeight();\n\n    self.rtl = false;\n    self.gridHeight = 0;\n    self.gridWidth = 0;\n    self.columnBuilders = [];\n    self.rowBuilders = [];\n    self.rowsProcessors = [];\n    self.columnsProcessors = [];\n    self.styleComputations = [];\n    self.viewportAdjusters = [];\n    self.rowHeaderColumns = [];\n    self.dataChangeCallbacks = {};\n    self.verticalScrollSyncCallBackFns = {};\n    self.horizontalScrollSyncCallBackFns = {};\n\n    // self.visibleRowCache = [];\n\n    // Set of 'render' containers for self grid, which can render sets of rows\n    self.renderContainers = {};\n\n    // Create a\n    self.renderContainers.body = new GridRenderContainer('body', self);\n\n    self.cellValueGetterCache = {};\n\n    // Cached function to use with custom row templates\n    self.getRowTemplateFn = null;\n\n\n    //representation of the rows on the grid.\n    //these are wrapped references to the actual data rows (options.data)\n    self.rows = [];\n\n    //represents the columns on the grid\n    self.columns = [];\n\n    /**\n     * @ngdoc boolean\n     * @name isScrollingVertically\n     * @propertyOf ui.grid.class:Grid\n     * @description set to true when Grid is scrolling vertically. Set to false via debounced method\n     */\n    self.isScrollingVertically = false;\n\n    /**\n     * @ngdoc boolean\n     * @name isScrollingHorizontally\n     * @propertyOf ui.grid.class:Grid\n     * @description set to true when Grid is scrolling horizontally. Set to false via debounced method\n     */\n    self.isScrollingHorizontally = false;\n\n    /**\n     * @ngdoc property\n     * @name scrollDirection\n     * @propertyOf ui.grid.class:Grid\n     * @description set one of the uiGridConstants.scrollDirection values (UP, DOWN, LEFT, RIGHT, NONE), which tells\n     * us which direction we are scrolling. Set to NONE via debounced method\n     */\n    self.scrollDirection = uiGridConstants.scrollDirection.NONE;\n\n    //if true, grid will not respond to any scroll events\n    self.disableScrolling = false;\n\n\n    function vertical (scrollEvent) {\n      self.isScrollingVertically = false;\n      self.api.core.raise.scrollEnd(scrollEvent);\n      self.scrollDirection = uiGridConstants.scrollDirection.NONE;\n    }\n\n    var debouncedVertical = gridUtil.debounce(vertical, self.options.scrollDebounce);\n    var debouncedVerticalMinDelay = gridUtil.debounce(vertical, 0);\n\n    function horizontal (scrollEvent) {\n      self.isScrollingHorizontally = false;\n      self.api.core.raise.scrollEnd(scrollEvent);\n      self.scrollDirection = uiGridConstants.scrollDirection.NONE;\n    }\n\n    var debouncedHorizontal = gridUtil.debounce(horizontal, self.options.scrollDebounce);\n    var debouncedHorizontalMinDelay = gridUtil.debounce(horizontal, 0);\n\n\n    /**\n     * @ngdoc function\n     * @name flagScrollingVertically\n     * @methodOf ui.grid.class:Grid\n     * @description sets isScrollingVertically to true and sets it to false in a debounced function\n     */\n    self.flagScrollingVertically = function(scrollEvent) {\n      if (!self.isScrollingVertically && !self.isScrollingHorizontally) {\n        self.api.core.raise.scrollBegin(scrollEvent);\n      }\n      self.isScrollingVertically = true;\n      if (self.options.scrollDebounce === 0 || !scrollEvent.withDelay) {\n        debouncedVerticalMinDelay(scrollEvent);\n      }\n      else {\n        debouncedVertical(scrollEvent);\n      }\n    };\n\n    /**\n     * @ngdoc function\n     * @name flagScrollingHorizontally\n     * @methodOf ui.grid.class:Grid\n     * @description sets isScrollingHorizontally to true and sets it to false in a debounced function\n     */\n    self.flagScrollingHorizontally = function(scrollEvent) {\n      if (!self.isScrollingVertically && !self.isScrollingHorizontally) {\n        self.api.core.raise.scrollBegin(scrollEvent);\n      }\n      self.isScrollingHorizontally = true;\n      if (self.options.scrollDebounce === 0 || !scrollEvent.withDelay) {\n        debouncedHorizontalMinDelay(scrollEvent);\n      }\n      else {\n        debouncedHorizontal(scrollEvent);\n      }\n    };\n\n    self.scrollbarHeight = 0;\n    self.scrollbarWidth = 0;\n    if (self.options.enableHorizontalScrollbar === uiGridConstants.scrollbars.ALWAYS) {\n      self.scrollbarHeight = gridUtil.getScrollbarWidth();\n    }\n\n    if (self.options.enableVerticalScrollbar === uiGridConstants.scrollbars.ALWAYS) {\n      self.scrollbarWidth = gridUtil.getScrollbarWidth();\n    }\n\n\n\n    self.api = new GridApi(self);\n\n    /**\n     * @ngdoc function\n     * @name refresh\n     * @methodOf ui.grid.core.api:PublicApi\n     * @description Refresh the rendered grid on screen.\n     * The refresh method re-runs both the columnProcessors and the\n     * rowProcessors, as well as calling refreshCanvas to update all\n     * the grid sizing.  In general you should prefer to use queueGridRefresh\n     * instead, which is basically a debounced version of refresh.\n     *\n     * If you only want to resize the grid, not regenerate all the rows\n     * and columns, you should consider directly calling refreshCanvas instead.\n     *\n     */\n    self.api.registerMethod( 'core', 'refresh', this.refresh );\n\n    /**\n     * @ngdoc function\n     * @name queueGridRefresh\n     * @methodOf ui.grid.core.api:PublicApi\n     * @description Request a refresh of the rendered grid on screen, if multiple\n     * calls to queueGridRefresh are made within a digest cycle only one will execute.\n     * The refresh method re-runs both the columnProcessors and the\n     * rowProcessors, as well as calling refreshCanvas to update all\n     * the grid sizing.  In general you should prefer to use queueGridRefresh\n     * instead, which is basically a debounced version of refresh.\n     *\n     */\n    self.api.registerMethod( 'core', 'queueGridRefresh', this.queueGridRefresh );\n\n    /**\n     * @ngdoc function\n     * @name refreshRows\n     * @methodOf ui.grid.core.api:PublicApi\n     * @description Runs only the rowProcessors, columns remain as they were.\n     * It then calls redrawInPlace and refreshCanvas, which adjust the grid sizing.\n     * @returns {promise} promise that is resolved when render completes?\n     *\n     */\n    self.api.registerMethod( 'core', 'refreshRows', this.refreshRows );\n\n    /**\n     * @ngdoc function\n     * @name queueRefresh\n     * @methodOf ui.grid.core.api:PublicApi\n     * @description Requests execution of refreshCanvas, if multiple requests are made\n     * during a digest cycle only one will run.  RefreshCanvas updates the grid sizing.\n     * @returns {promise} promise that is resolved when render completes?\n     *\n     */\n    self.api.registerMethod( 'core', 'queueRefresh', this.queueRefresh );\n\n    /**\n     * @ngdoc function\n     * @name handleWindowResize\n     * @methodOf ui.grid.core.api:PublicApi\n     * @description Trigger a grid resize, normally this would be picked\n     * up by a watch on window size, but in some circumstances it is necessary\n     * to call this manually\n     * @returns {promise} promise that is resolved when render completes?\n     *\n     */\n    self.api.registerMethod( 'core', 'handleWindowResize', this.handleWindowResize );\n\n\n    /**\n     * @ngdoc function\n     * @name addRowHeaderColumn\n     * @methodOf ui.grid.core.api:PublicApi\n     * @description adds a row header column to the grid\n     * @param {object} column def\n     *\n     */\n    self.api.registerMethod( 'core', 'addRowHeaderColumn', this.addRowHeaderColumn );\n\n    /**\n     * @ngdoc function\n     * @name scrollToIfNecessary\n     * @methodOf ui.grid.core.api:PublicApi\n     * @description Scrolls the grid to make a certain row and column combo visible,\n     *   in the case that it is not completely visible on the screen already.\n     * @param {GridRow} gridRow row to make visible\n     * @param {GridCol} gridCol column to make visible\n     * @returns {promise} a promise that is resolved when scrolling is complete\n     *\n     */\n    self.api.registerMethod( 'core', 'scrollToIfNecessary', function(gridRow, gridCol) { return self.scrollToIfNecessary(gridRow, gridCol);} );\n\n    /**\n     * @ngdoc function\n     * @name scrollTo\n     * @methodOf ui.grid.core.api:PublicApi\n     * @description Scroll the grid such that the specified\n     * row and column is in view\n     * @param {object} rowEntity gridOptions.data[] array instance to make visible\n     * @param {object} colDef to make visible\n     * @returns {promise} a promise that is resolved after any scrolling is finished\n     */\n    self.api.registerMethod( 'core', 'scrollTo', function (rowEntity, colDef) { return self.scrollTo(rowEntity, colDef);}  );\n\n    /**\n     * @ngdoc function\n     * @name registerRowsProcessor\n     * @methodOf ui.grid.core.api:PublicApi\n     * @description\n     * Register a \"rows processor\" function. When the rows are updated,\n     * the grid calls each registered \"rows processor\", which has a chance\n     * to alter the set of rows (sorting, etc) as long as the count is not\n     * modified.\n     *\n     * @param {function(renderedRowsToProcess, columns )} processorFunction rows processor function, which\n     * is run in the context of the grid (i.e. this for the function will be the grid), and must\n     * return the updated rows list, which is passed to the next processor in the chain\n     * @param {number} priority the priority of this processor.  In general we try to do them in 100s to leave room\n     * for other people to inject rows processors at intermediate priorities.  Lower priority rowsProcessors run earlier.\n     *\n     * At present allRowsVisible is running at 50, sort manipulations running at 60-65, filter is running at 100,\n     * sort is at 200, grouping and treeview at 400-410, selectable rows at 500, pagination at 900 (pagination will generally want to be last)\n     */\n    self.api.registerMethod( 'core', 'registerRowsProcessor', this.registerRowsProcessor  );\n\n    /**\n     * @ngdoc function\n     * @name registerColumnsProcessor\n     * @methodOf ui.grid.core.api:PublicApi\n     * @description\n     * Register a \"columns processor\" function. When the columns are updated,\n     * the grid calls each registered \"columns processor\", which has a chance\n     * to alter the set of columns as long as the count is not\n     * modified.\n     *\n     * @param {function(renderedColumnsToProcess, rows )} processorFunction columns processor function, which\n     * is run in the context of the grid (i.e. this for the function will be the grid), and must\n     * return the updated columns list, which is passed to the next processor in the chain\n     * @param {number} priority the priority of this processor.  In general we try to do them in 100s to leave room\n     * for other people to inject columns processors at intermediate priorities.  Lower priority columnsProcessors run earlier.\n     *\n     * At present allRowsVisible is running at 50, filter is running at 100, sort is at 200, grouping at 400, selectable rows at 500, pagination at 900 (pagination will generally want to be last)\n     */\n    self.api.registerMethod( 'core', 'registerColumnsProcessor', this.registerColumnsProcessor  );\n\n\n\n    /**\n     * @ngdoc function\n     * @name sortHandleNulls\n     * @methodOf ui.grid.core.api:PublicApi\n     * @description A null handling method that can be used when building custom sort\n     * functions\n     * @example\n     * <pre>\n     *   mySortFn = function(a, b) {\n     *   var nulls = $scope.gridApi.core.sortHandleNulls(a, b);\n     *   if ( nulls !== null ){\n     *     return nulls;\n     *   } else {\n     *     // your code for sorting here\n     *   };\n     * </pre>\n     * @param {object} a sort value a\n     * @param {object} b sort value b\n     * @returns {number} null if there were no nulls/undefineds, otherwise returns\n     * a sort value that should be passed back from the sort function\n     *\n     */\n    self.api.registerMethod( 'core', 'sortHandleNulls', rowSorter.handleNulls );\n\n\n    /**\n     * @ngdoc function\n     * @name sortChanged\n     * @methodOf  ui.grid.core.api:PublicApi\n     * @description The sort criteria on one or more columns has\n     * changed.  Provides as parameters the grid and the output of\n     * getColumnSorting, which is an array of gridColumns\n     * that have sorting on them, sorted in priority order.\n     *\n     * @param {$scope} scope The scope of the controller. This is used to deregister this event when the scope is destroyed.\n     * @param {Function} callBack Will be called when the event is emited. The function passes back an array of columns with\n     * sorts on them, in priority order.\n     *\n     * @example\n     * <pre>\n     *      gridApi.core.on.sortChanged( $scope, function(sortColumns){\n     *        // do something\n     *      });\n     * </pre>\n     */\n    self.api.registerEvent( 'core', 'sortChanged' );\n\n      /**\n     * @ngdoc function\n     * @name columnVisibilityChanged\n     * @methodOf  ui.grid.core.api:PublicApi\n     * @description The visibility of a column has changed,\n     * the column itself is passed out as a parameter of the event.\n     * \n     * @param {$scope} scope The scope of the controller. This is used to deregister this event when the scope is destroyed.\n     * @param {Function} callBack Will be called when the event is emited. The function passes back the GridCol that has changed.\n     *\n     * @example\n     * <pre>\n     *      gridApi.core.on.columnVisibilityChanged( $scope, function (column) {\n     *        // do something\n     *      } );\n     * </pre>\n     */\n    self.api.registerEvent( 'core', 'columnVisibilityChanged' );\n\n    /**\n     * @ngdoc method\n     * @name notifyDataChange\n     * @methodOf ui.grid.core.api:PublicApi\n     * @description Notify the grid that a data or config change has occurred,\n     * where that change isn't something the grid was otherwise noticing.  This\n     * might be particularly relevant where you've changed values within the data\n     * and you'd like cell classes to be re-evaluated, or changed config within\n     * the columnDef and you'd like headerCellClasses to be re-evaluated.\n     * @param {string} type one of the\n     * uiGridConstants.dataChange values (ALL, ROW, EDIT, COLUMN), which tells\n     * us which refreshes to fire.\n     *\n     */\n    self.api.registerMethod( 'core', 'notifyDataChange', this.notifyDataChange );\n\n    /**\n     * @ngdoc method\n     * @name clearAllFilters\n     * @methodOf ui.grid.core.api:PublicApi\n     * @description Clears all filters and optionally refreshes the visible rows.\n     * @param {object} refreshRows Defaults to true.\n     * @param {object} clearConditions Defaults to false.\n     * @param {object} clearFlags Defaults to false.\n     * @returns {promise} If `refreshRows` is true, returns a promise of the rows refreshing.\n     */\n    self.api.registerMethod('core', 'clearAllFilters', this.clearAllFilters);\n\n    self.registerDataChangeCallback( self.columnRefreshCallback, [uiGridConstants.dataChange.COLUMN]);\n    self.registerDataChangeCallback( self.processRowsCallback, [uiGridConstants.dataChange.EDIT]);\n    self.registerDataChangeCallback( self.updateFooterHeightCallback, [uiGridConstants.dataChange.OPTIONS]);\n\n    self.registerStyleComputation({\n      priority: 10,\n      func: self.getFooterStyles\n    });\n  };\n\n   Grid.prototype.calcFooterHeight = function () {\n     if (!this.hasFooter()) {\n       return 0;\n     }\n\n     var height = 0;\n     if (this.options.showGridFooter) {\n       height += this.options.gridFooterHeight;\n     }\n\n     height += this.calcColumnFooterHeight();\n\n     return height;\n   };\n\n   Grid.prototype.calcColumnFooterHeight = function () {\n     var height = 0;\n\n     if (this.options.showColumnFooter) {\n       height += this.options.columnFooterHeight;\n     }\n\n     return height;\n   };\n\n   Grid.prototype.getFooterStyles = function () {\n     var style = '.grid' + this.id + ' .ui-grid-footer-aggregates-row { height: ' + this.options.columnFooterHeight + 'px; }';\n     style += ' .grid' + this.id + ' .ui-grid-footer-info { height: ' + this.options.gridFooterHeight + 'px; }';\n     return style;\n   };\n\n  Grid.prototype.hasFooter = function () {\n   return this.options.showGridFooter || this.options.showColumnFooter;\n  };\n\n  /**\n   * @ngdoc function\n   * @name isRTL\n   * @methodOf ui.grid.class:Grid\n   * @description Returns true if grid is RightToLeft\n   */\n  Grid.prototype.isRTL = function () {\n    return this.rtl;\n  };\n\n\n  /**\n   * @ngdoc function\n   * @name registerColumnBuilder\n   * @methodOf ui.grid.class:Grid\n   * @description When the build creates columns from column definitions, the columnbuilders will be called to add\n   * additional properties to the column.\n   * @param {function(colDef, col, gridOptions)} columnBuilder function to be called\n   */\n  Grid.prototype.registerColumnBuilder = function registerColumnBuilder(columnBuilder) {\n    this.columnBuilders.push(columnBuilder);\n  };\n\n  /**\n   * @ngdoc function\n   * @name buildColumnDefsFromData\n   * @methodOf ui.grid.class:Grid\n   * @description Populates columnDefs from the provided data\n   * @param {function(colDef, col, gridOptions)} rowBuilder function to be called\n   */\n  Grid.prototype.buildColumnDefsFromData = function (dataRows){\n    this.options.columnDefs =  gridUtil.getColumnsFromData(dataRows, this.options.excludeProperties);\n  };\n\n  /**\n   * @ngdoc function\n   * @name registerRowBuilder\n   * @methodOf ui.grid.class:Grid\n   * @description When the build creates rows from gridOptions.data, the rowBuilders will be called to add\n   * additional properties to the row.\n   * @param {function(row, gridOptions)} rowBuilder function to be called\n   */\n  Grid.prototype.registerRowBuilder = function registerRowBuilder(rowBuilder) {\n    this.rowBuilders.push(rowBuilder);\n  };\n\n\n  /**\n   * @ngdoc function\n   * @name registerDataChangeCallback\n   * @methodOf ui.grid.class:Grid\n   * @description When a data change occurs, the data change callbacks of the specified type\n   * will be called.  The rules are:\n   *\n   * - when the data watch fires, that is considered a ROW change (the data watch only notices\n   *   added or removed rows)\n   * - when the api is called to inform us of a change, the declared type of that change is used\n   * - when a cell edit completes, the EDIT callbacks are triggered\n   * - when the columnDef watch fires, the COLUMN callbacks are triggered\n   * - when the options watch fires, the OPTIONS callbacks are triggered\n   *\n   * For a given event:\n   * - ALL calls ROW, EDIT, COLUMN, OPTIONS and ALL callbacks\n   * - ROW calls ROW and ALL callbacks\n   * - EDIT calls EDIT and ALL callbacks\n   * - COLUMN calls COLUMN and ALL callbacks\n   * - OPTIONS calls OPTIONS and ALL callbacks\n   *\n   * @param {function(grid)} callback function to be called\n   * @param {array} types the types of data change you want to be informed of.  Values from\n   * the uiGridConstants.dataChange values ( ALL, EDIT, ROW, COLUMN, OPTIONS ).  Optional and defaults to\n   * ALL\n   * @returns {function} deregister function - a function that can be called to deregister this callback\n   */\n  Grid.prototype.registerDataChangeCallback = function registerDataChangeCallback(callback, types, _this) {\n    var uid = gridUtil.nextUid();\n    if ( !types ){\n      types = [uiGridConstants.dataChange.ALL];\n    }\n    if ( !Array.isArray(types)){\n      gridUtil.logError(\"Expected types to be an array or null in registerDataChangeCallback, value passed was: \" + types );\n    }\n    this.dataChangeCallbacks[uid] = { callback: callback, types: types, _this:_this };\n\n    var self = this;\n    var deregisterFunction = function() {\n      delete self.dataChangeCallbacks[uid];\n    };\n    return deregisterFunction;\n  };\n\n  /**\n   * @ngdoc function\n   * @name callDataChangeCallbacks\n   * @methodOf ui.grid.class:Grid\n   * @description Calls the callbacks based on the type of data change that\n   * has occurred. Always calls the ALL callbacks, calls the ROW, EDIT, COLUMN and OPTIONS callbacks if the\n   * event type is matching, or if the type is ALL.\n   * @param {number} type the type of event that occurred - one of the\n   * uiGridConstants.dataChange values (ALL, ROW, EDIT, COLUMN, OPTIONS)\n   */\n  Grid.prototype.callDataChangeCallbacks = function callDataChangeCallbacks(type, options) {\n    angular.forEach( this.dataChangeCallbacks, function( callback, uid ){\n      if ( callback.types.indexOf( uiGridConstants.dataChange.ALL ) !== -1 ||\n           callback.types.indexOf( type ) !== -1 ||\n           type === uiGridConstants.dataChange.ALL ) {\n        if (callback._this) {\n           callback.callback.apply(callback._this,this);\n        }\n        else {\n          callback.callback( this );\n        }\n      }\n    }, this);\n  };\n\n  /**\n   * @ngdoc function\n   * @name notifyDataChange\n   * @methodOf ui.grid.class:Grid\n   * @description Notifies us that a data change has occurred, used in the public\n   * api for users to tell us when they've changed data or some other event that\n   * our watches cannot pick up\n   * @param {string} type the type of event that occurred - one of the\n   * uiGridConstants.dataChange values (ALL, ROW, EDIT, COLUMN)\n   */\n  Grid.prototype.notifyDataChange = function notifyDataChange(type) {\n    var constants = uiGridConstants.dataChange;\n    if ( type === constants.ALL ||\n         type === constants.COLUMN ||\n         type === constants.EDIT ||\n         type === constants.ROW ||\n         type === constants.OPTIONS ){\n      this.callDataChangeCallbacks( type );\n    } else {\n      gridUtil.logError(\"Notified of a data change, but the type was not recognised, so no action taken, type was: \" + type);\n    }\n  };\n\n\n  /**\n   * @ngdoc function\n   * @name columnRefreshCallback\n   * @methodOf ui.grid.class:Grid\n   * @description refreshes the grid when a column refresh\n   * is notified, which triggers handling of the visible flag.\n   * This is called on uiGridConstants.dataChange.COLUMN, and is\n   * registered as a dataChangeCallback in grid.js\n   * @param {string} name column name\n   */\n  Grid.prototype.columnRefreshCallback = function columnRefreshCallback( grid ){\n    grid.buildColumns();\n    grid.queueGridRefresh();\n  };\n\n\n  /**\n   * @ngdoc function\n   * @name processRowsCallback\n   * @methodOf ui.grid.class:Grid\n   * @description calls the row processors, specifically\n   * intended to reset the sorting when an edit is called,\n   * registered as a dataChangeCallback on uiGridConstants.dataChange.EDIT\n   * @param {string} name column name\n   */\n  Grid.prototype.processRowsCallback = function processRowsCallback( grid ){\n    grid.queueGridRefresh();\n  };\n\n\n  /**\n   * @ngdoc function\n   * @name updateFooterHeightCallback\n   * @methodOf ui.grid.class:Grid\n   * @description recalculates the footer height,\n   * registered as a dataChangeCallback on uiGridConstants.dataChange.OPTIONS\n   * @param {string} name column name\n   */\n  Grid.prototype.updateFooterHeightCallback = function updateFooterHeightCallback( grid ){\n    grid.footerHeight = grid.calcFooterHeight();\n    grid.columnFooterHeight = grid.calcColumnFooterHeight();\n  };\n\n\n  /**\n   * @ngdoc function\n   * @name getColumn\n   * @methodOf ui.grid.class:Grid\n   * @description returns a grid column for the column name\n   * @param {string} name column name\n   */\n  Grid.prototype.getColumn = function getColumn(name) {\n    var columns = this.columns.filter(function (column) {\n      return column.colDef.name === name;\n    });\n    return columns.length > 0 ? columns[0] : null;\n  };\n\n  /**\n   * @ngdoc function\n   * @name getColDef\n   * @methodOf ui.grid.class:Grid\n   * @description returns a grid colDef for the column name\n   * @param {string} name column.field\n   */\n  Grid.prototype.getColDef = function getColDef(name) {\n    var colDefs = this.options.columnDefs.filter(function (colDef) {\n      return colDef.name === name;\n    });\n    return colDefs.length > 0 ? colDefs[0] : null;\n  };\n\n  /**\n   * @ngdoc function\n   * @name assignTypes\n   * @methodOf ui.grid.class:Grid\n   * @description uses the first row of data to assign colDef.type for any types not defined.\n   */\n  /**\n   * @ngdoc property\n   * @name type\n   * @propertyOf ui.grid.class:GridOptions.columnDef\n   * @description the type of the column, used in sorting.  If not provided then the\n   * grid will guess the type.  Add this only if the grid guessing is not to your\n   * satisfaction.  One of:\n   * - 'string'\n   * - 'boolean'\n   * - 'number'\n   * - 'date'\n   * - 'object'\n   * - 'numberStr'\n   * Note that if you choose date, your dates should be in a javascript date type\n   *\n   */\n  Grid.prototype.assignTypes = function(){\n    var self = this;\n    self.options.columnDefs.forEach(function (colDef, index) {\n\n      //Assign colDef type if not specified\n      if (!colDef.type) {\n        var col = new GridColumn(colDef, index, self);\n        var firstRow = self.rows.length > 0 ? self.rows[0] : null;\n        if (firstRow) {\n          colDef.type = gridUtil.guessType(self.getCellValue(firstRow, col));\n        }\n        else {\n          colDef.type = 'string';\n        }\n      }\n    });\n  };\n\n\n  /**\n   * @ngdoc function\n   * @name isRowHeaderColumn\n   * @methodOf ui.grid.class:Grid\n   * @description returns true if the column is a row Header\n   * @param {object} column column\n   */\n  Grid.prototype.isRowHeaderColumn = function isRowHeaderColumn(column) {\n    return this.rowHeaderColumns.indexOf(column) !== -1;\n  };\n\n  /**\n  * @ngdoc function\n  * @name addRowHeaderColumn\n  * @methodOf ui.grid.class:Grid\n  * @description adds a row header column to the grid\n  * @param {object} column def\n  */\n  Grid.prototype.addRowHeaderColumn = function addRowHeaderColumn(colDef) {\n    var self = this;\n    var rowHeaderCol = new GridColumn(colDef, gridUtil.nextUid(), self);\n    rowHeaderCol.isRowHeader = true;\n    if (self.isRTL()) {\n      self.createRightContainer();\n      rowHeaderCol.renderContainer = 'right';\n    }\n    else {\n      self.createLeftContainer();\n      rowHeaderCol.renderContainer = 'left';\n    }\n\n    // relies on the default column builder being first in array, as it is instantiated\n    // as part of grid creation\n    self.columnBuilders[0](colDef,rowHeaderCol,self.options)\n      .then(function(){\n        rowHeaderCol.enableFiltering = false;\n        rowHeaderCol.enableSorting = false;\n        rowHeaderCol.enableHiding = false;\n        self.rowHeaderColumns.push(rowHeaderCol);\n        self.buildColumns()\n          .then( function() {\n            self.preCompileCellTemplates();\n            self.queueGridRefresh();\n          });\n      });\n  };\n\n  /**\n   * @ngdoc function\n   * @name getOnlyDataColumns\n   * @methodOf ui.grid.class:Grid\n   * @description returns all columns except for rowHeader columns\n   */\n  Grid.prototype.getOnlyDataColumns = function getOnlyDataColumns() {\n    var self = this;\n    var cols = [];\n    self.columns.forEach(function (col) {\n      if (self.rowHeaderColumns.indexOf(col) === -1) {\n        cols.push(col);\n      }\n    });\n    return cols;\n  };\n\n  /**\n   * @ngdoc function\n   * @name buildColumns\n   * @methodOf ui.grid.class:Grid\n   * @description creates GridColumn objects from the columnDefinition.  Calls each registered\n   * columnBuilder to further process the column\n   * @param {object} options  An object contains options to use when building columns\n   *\n   * * **orderByColumnDefs**: defaults to **false**. When true, `buildColumns` will reorder existing columns according to the order within the column definitions.\n   *\n   * @returns {Promise} a promise to load any needed column resources\n   */\n  Grid.prototype.buildColumns = function buildColumns(opts) {\n    var options = {\n      orderByColumnDefs: false\n    };\n\n    angular.extend(options, opts);\n\n    // gridUtil.logDebug('buildColumns');\n    var self = this;\n    var builderPromises = [];\n    var headerOffset = self.rowHeaderColumns.length;\n    var i;\n\n    // Remove any columns for which a columnDef cannot be found\n    // Deliberately don't use forEach, as it doesn't like splice being called in the middle\n    // Also don't cache columns.length, as it will change during this operation\n    for (i = 0; i < self.columns.length; i++){\n      if (!self.getColDef(self.columns[i].name)) {\n        self.columns.splice(i, 1);\n        i--;\n      }\n    }\n\n    //add row header columns to the grid columns array _after_ columns without columnDefs have been removed\n    self.rowHeaderColumns.forEach(function (rowHeaderColumn) {\n      self.columns.unshift(rowHeaderColumn);\n    });\n\n\n    // look at each column def, and update column properties to match.  If the column def\n    // doesn't have a column, then splice in a new gridCol\n    self.options.columnDefs.forEach(function (colDef, index) {\n      self.preprocessColDef(colDef);\n      var col = self.getColumn(colDef.name);\n\n      if (!col) {\n        col = new GridColumn(colDef, gridUtil.nextUid(), self);\n        self.columns.splice(index + headerOffset, 0, col);\n      }\n      else {\n        // tell updateColumnDef that the column was pre-existing\n        col.updateColumnDef(colDef, false);\n      }\n\n      self.columnBuilders.forEach(function (builder) {\n        builderPromises.push(builder.call(self, colDef, col, self.options));\n      });\n    });\n\n    /*** Reorder columns if necessary ***/\n    if (!!options.orderByColumnDefs) {\n      // Create a shallow copy of the columns as a cache\n      var columnCache = self.columns.slice(0);\n\n      // We need to allow for the \"row headers\" when mapping from the column defs array to the columns array\n      //   If we have a row header in columns[0] and don't account for it   we'll overwrite it with the column in columnDefs[0]\n\n      // Go through all the column defs, use the shorter of columns length and colDefs.length because if a user has given two columns the same name then\n      // columns will be shorter than columnDefs.  In this situation we'll avoid an error, but the user will still get an unexpected result\n      var len = Math.min(self.options.columnDefs.length, self.columns.length);\n      for (i = 0; i < len; i++) {\n        // If the column at this index has a different name than the column at the same index in the column defs...\n        if (self.columns[i + headerOffset].name !== self.options.columnDefs[i].name) {\n          // Replace the one in the cache with the appropriate column\n          columnCache[i + headerOffset] = self.getColumn(self.options.columnDefs[i].name);\n        }\n        else {\n          // Otherwise just copy over the one from the initial columns\n          columnCache[i + headerOffset] = self.columns[i + headerOffset];\n        }\n      }\n\n      // Empty out the columns array, non-destructively\n      self.columns.length = 0;\n\n      // And splice in the updated, ordered columns from the cache\n      Array.prototype.splice.apply(self.columns, [0, 0].concat(columnCache));\n    }\n\n    return $q.all(builderPromises).then(function(){\n      if (self.rows.length > 0){\n        self.assignTypes();\n      }\n    });\n  };\n\n/**\n * @ngdoc function\n * @name preCompileCellTemplates\n * @methodOf ui.grid.class:Grid\n * @description precompiles all cell templates\n */\n  Grid.prototype.preCompileCellTemplates = function() {\n    var self = this;\n\n    var preCompileTemplate = function( col ) {\n      var html = col.cellTemplate.replace(uiGridConstants.MODEL_COL_FIELD, self.getQualifiedColField(col));\n      html = html.replace(uiGridConstants.COL_FIELD, 'grid.getCellValue(row, col)');\n\n      var compiledElementFn = $compile(html);\n      col.compiledElementFn = compiledElementFn;\n\n      if (col.compiledElementFnDefer) {\n        col.compiledElementFnDefer.resolve(col.compiledElementFn);\n      }\n    };\n\n    this.columns.forEach(function (col) {\n      if ( col.cellTemplate ){\n        preCompileTemplate( col );\n      } else if ( col.cellTemplatePromise ){\n        col.cellTemplatePromise.then( function() {\n          preCompileTemplate( col );\n        });\n      }\n    });\n  };\n\n  /**\n   * @ngdoc function\n   * @name getGridQualifiedColField\n   * @methodOf ui.grid.class:Grid\n   * @description Returns the $parse-able accessor for a column within its $scope\n   * @param {GridColumn} col col object\n   */\n  Grid.prototype.getQualifiedColField = function (col) {\n    return 'row.entity.' + gridUtil.preEval(col.field);\n  };\n\n  /**\n   * @ngdoc function\n   * @name createLeftContainer\n   * @methodOf ui.grid.class:Grid\n   * @description creates the left render container if it doesn't already exist\n   */\n  Grid.prototype.createLeftContainer = function() {\n    if (!this.hasLeftContainer()) {\n      this.renderContainers.left = new GridRenderContainer('left', this, { disableColumnOffset: true });\n    }\n  };\n\n  /**\n   * @ngdoc function\n   * @name createRightContainer\n   * @methodOf ui.grid.class:Grid\n   * @description creates the right render container if it doesn't already exist\n   */\n  Grid.prototype.createRightContainer = function() {\n    if (!this.hasRightContainer()) {\n      this.renderContainers.right = new GridRenderContainer('right', this, { disableColumnOffset: true });\n    }\n  };\n\n  /**\n   * @ngdoc function\n   * @name hasLeftContainer\n   * @methodOf ui.grid.class:Grid\n   * @description returns true if leftContainer exists\n   */\n  Grid.prototype.hasLeftContainer = function() {\n    return this.renderContainers.left !== undefined;\n  };\n\n  /**\n   * @ngdoc function\n   * @name hasRightContainer\n   * @methodOf ui.grid.class:Grid\n   * @description returns true if rightContainer exists\n   */\n  Grid.prototype.hasRightContainer = function() {\n    return this.renderContainers.right !== undefined;\n  };\n\n\n      /**\n   * undocumented function\n   * @name preprocessColDef\n   * @methodOf ui.grid.class:Grid\n   * @description defaults the name property from field to maintain backwards compatibility with 2.x\n   * validates that name or field is present\n   */\n  Grid.prototype.preprocessColDef = function preprocessColDef(colDef) {\n    var self = this;\n\n    if (!colDef.field && !colDef.name) {\n      throw new Error('colDef.name or colDef.field property is required');\n    }\n\n    //maintain backwards compatibility with 2.x\n    //field was required in 2.x.  now name is required\n    if (colDef.name === undefined && colDef.field !== undefined) {\n      // See if the column name already exists:\n      var newName = colDef.field,\n        counter = 2;\n      while (self.getColumn(newName)) {\n        newName = colDef.field + counter.toString();\n        counter++;\n      }\n      colDef.name = newName;\n    }\n  };\n\n  // Return a list of items that exist in the `n` array but not the `o` array. Uses optional property accessors passed as third & fourth parameters\n  Grid.prototype.newInN = function newInN(o, n, oAccessor, nAccessor) {\n    var self = this;\n\n    var t = [];\n    for (var i = 0; i < n.length; i++) {\n      var nV = nAccessor ? n[i][nAccessor] : n[i];\n\n      var found = false;\n      for (var j = 0; j < o.length; j++) {\n        var oV = oAccessor ? o[j][oAccessor] : o[j];\n        if (self.options.rowEquality(nV, oV)) {\n          found = true;\n          break;\n        }\n      }\n      if (!found) {\n        t.push(nV);\n      }\n    }\n\n    return t;\n  };\n\n  /**\n   * @ngdoc function\n   * @name getRow\n   * @methodOf ui.grid.class:Grid\n   * @description returns the GridRow that contains the rowEntity\n   * @param {object} rowEntity the gridOptions.data array element instance\n   * @param {array} rows [optional] the rows to look in - if not provided then\n   * looks in grid.rows\n   */\n  Grid.prototype.getRow = function getRow(rowEntity, lookInRows) {\n    var self = this;\n\n    lookInRows = typeof(lookInRows) === 'undefined' ? self.rows : lookInRows;\n\n    var rows = lookInRows.filter(function (row) {\n      return self.options.rowEquality(row.entity, rowEntity);\n    });\n    return rows.length > 0 ? rows[0] : null;\n  };\n\n\n  /**\n   * @ngdoc function\n   * @name modifyRows\n   * @methodOf ui.grid.class:Grid\n   * @description creates or removes GridRow objects from the newRawData array.  Calls each registered\n   * rowBuilder to further process the row\n   *\n   * This method aims to achieve three things:\n   * 1. the resulting rows array is in the same order as the newRawData, we'll call\n   * rowsProcessors immediately after to sort the data anyway\n   * 2. if we have row hashing available, we try to use the rowHash to find the row\n   * 3. no memory leaks - rows that are no longer in newRawData need to be garbage collected\n   *\n   * The basic logic flow makes use of the newRawData, oldRows and oldHash, and creates\n   * the newRows and newHash\n   *\n   * ```\n   * newRawData.forEach newEntity\n   *   if (hashing enabled)\n   *     check oldHash for newEntity\n   *   else\n   *     look for old row directly in oldRows\n   *   if !oldRowFound     // must be a new row\n   *     create newRow\n   *   append to the newRows and add to newHash\n   *   run the processors\n   *\n   * Rows are identified using the hashKey if configured.  If not configured, then rows\n   * are identified using the gridOptions.rowEquality function\n   */\n  Grid.prototype.modifyRows = function modifyRows(newRawData) {\n    var self = this;\n    var oldRows = self.rows.slice(0);\n    var oldRowHash = self.rowHashMap || self.createRowHashMap();\n    self.rowHashMap = self.createRowHashMap();\n    self.rows.length = 0;\n\n    newRawData.forEach( function( newEntity, i ) {\n      var newRow;\n      if ( self.options.enableRowHashing ){\n        // if hashing is enabled, then this row will be in the hash if we already know about it\n        newRow = oldRowHash.get( newEntity );\n      } else {\n        // otherwise, manually search the oldRows to see if we can find this row\n        newRow = self.getRow(newEntity, oldRows);\n      }\n\n      // if we didn't find the row, it must be new, so create it\n      if ( !newRow ){\n        newRow = self.processRowBuilders(new GridRow(newEntity, i, self));\n      }\n\n      self.rows.push( newRow );\n      self.rowHashMap.put( newEntity, newRow );\n    });\n\n    self.assignTypes();\n\n    var p1 = $q.when(self.processRowsProcessors(self.rows))\n      .then(function (renderableRows) {\n        return self.setVisibleRows(renderableRows);\n      });\n\n    var p2 = $q.when(self.processColumnsProcessors(self.columns))\n      .then(function (renderableColumns) {\n        return self.setVisibleColumns(renderableColumns);\n      });\n\n    return $q.all([p1, p2]);\n  };\n\n\n  /**\n   * Private Undocumented Method\n   * @name addRows\n   * @methodOf ui.grid.class:Grid\n   * @description adds the newRawData array of rows to the grid and calls all registered\n   * rowBuilders. this keyword will reference the grid\n   */\n  Grid.prototype.addRows = function addRows(newRawData) {\n    var self = this;\n\n    var existingRowCount = self.rows.length;\n    for (var i = 0; i < newRawData.length; i++) {\n      var newRow = self.processRowBuilders(new GridRow(newRawData[i], i + existingRowCount, self));\n\n      if (self.options.enableRowHashing) {\n        var found = self.rowHashMap.get(newRow.entity);\n        if (found) {\n          found.row = newRow;\n        }\n      }\n\n      self.rows.push(newRow);\n    }\n  };\n\n  /**\n   * @ngdoc function\n   * @name processRowBuilders\n   * @methodOf ui.grid.class:Grid\n   * @description processes all RowBuilders for the gridRow\n   * @param {GridRow} gridRow reference to gridRow\n   * @returns {GridRow} the gridRow with all additional behavior added\n   */\n  Grid.prototype.processRowBuilders = function processRowBuilders(gridRow) {\n    var self = this;\n\n    self.rowBuilders.forEach(function (builder) {\n      builder.call(self, gridRow, self.options);\n    });\n\n    return gridRow;\n  };\n\n  /**\n   * @ngdoc function\n   * @name registerStyleComputation\n   * @methodOf ui.grid.class:Grid\n   * @description registered a styleComputation function\n   *\n   * If the function returns a value it will be appended into the grid's `<style>` block\n   * @param {function($scope)} styleComputation function\n   */\n  Grid.prototype.registerStyleComputation = function registerStyleComputation(styleComputationInfo) {\n    this.styleComputations.push(styleComputationInfo);\n  };\n\n\n  // NOTE (c0bra): We already have rowBuilders. I think these do exactly the same thing...\n  // Grid.prototype.registerRowFilter = function(filter) {\n  //   // TODO(c0bra): validate filter?\n\n  //   this.rowFilters.push(filter);\n  // };\n\n  // Grid.prototype.removeRowFilter = function(filter) {\n  //   var idx = this.rowFilters.indexOf(filter);\n\n  //   if (typeof(idx) !== 'undefined' && idx !== undefined) {\n  //     this.rowFilters.slice(idx, 1);\n  //   }\n  // };\n\n  // Grid.prototype.processRowFilters = function(rows) {\n  //   var self = this;\n  //   self.rowFilters.forEach(function (filter) {\n  //     filter.call(self, rows);\n  //   });\n  // };\n\n\n  /**\n   * @ngdoc function\n   * @name registerRowsProcessor\n   * @methodOf ui.grid.class:Grid\n   * @description\n   *\n   * Register a \"rows processor\" function. When the rows are updated,\n   * the grid calls each registered \"rows processor\", which has a chance\n   * to alter the set of rows (sorting, etc) as long as the count is not\n   * modified.\n   *\n   * @param {function(renderedRowsToProcess, columns )} processorFunction rows processor function, which\n   * is run in the context of the grid (i.e. this for the function will be the grid), and must\n   * return the updated rows list, which is passed to the next processor in the chain\n   * @param {number} priority the priority of this processor.  In general we try to do them in 100s to leave room\n   * for other people to inject rows processors at intermediate priorities.  Lower priority rowsProcessors run earlier.\n   *\n   * At present all rows visible is running at 50, filter is running at 100, sort is at 200, grouping at 400, selectable rows at 500, pagination at 900 (pagination will generally want to be last)\n   *\n   */\n  Grid.prototype.registerRowsProcessor = function registerRowsProcessor(processor, priority) {\n    if (!angular.isFunction(processor)) {\n      throw 'Attempt to register non-function rows processor: ' + processor;\n    }\n\n    this.rowsProcessors.push({processor: processor, priority: priority});\n    this.rowsProcessors.sort(function sortByPriority( a, b ){\n      return a.priority - b.priority;\n    });\n  };\n\n  /**\n   * @ngdoc function\n   * @name removeRowsProcessor\n   * @methodOf ui.grid.class:Grid\n   * @param {function(renderableRows)} rows processor function\n   * @description Remove a registered rows processor\n   */\n  Grid.prototype.removeRowsProcessor = function removeRowsProcessor(processor) {\n    var idx = -1;\n    this.rowsProcessors.forEach(function(rowsProcessor, index){\n      if ( rowsProcessor.processor === processor ){\n        idx = index;\n      }\n    });\n\n    if ( idx !== -1 ) {\n      this.rowsProcessors.splice(idx, 1);\n    }\n  };\n\n  /**\n   * Private Undocumented Method\n   * @name processRowsProcessors\n   * @methodOf ui.grid.class:Grid\n   * @param {Array[GridRow]} The array of \"renderable\" rows\n   * @param {Array[GridColumn]} The array of columns\n   * @description Run all the registered rows processors on the array of renderable rows\n   */\n  Grid.prototype.processRowsProcessors = function processRowsProcessors(renderableRows) {\n    var self = this;\n\n    // Create a shallow copy of the rows so that we can safely sort them without altering the original grid.rows sort order\n    var myRenderableRows = renderableRows.slice(0);\n\n    // Return myRenderableRows with no processing if we have no rows processors\n    if (self.rowsProcessors.length === 0) {\n      return $q.when(myRenderableRows);\n    }\n\n    // Counter for iterating through rows processors\n    var i = 0;\n\n    // Promise for when we're done with all the processors\n    var finished = $q.defer();\n\n    // This function will call the processor in self.rowsProcessors at index 'i', and then\n    //   when done will call the next processor in the list, using the output from the processor\n    //   at i as the argument for 'renderedRowsToProcess' on the next iteration.\n    //\n    //   If we're at the end of the list of processors, we resolve our 'finished' callback with\n    //   the result.\n    function startProcessor(i, renderedRowsToProcess) {\n      // Get the processor at 'i'\n      var processor = self.rowsProcessors[i].processor;\n\n      // Call the processor, passing in the rows to process and the current columns\n      //   (note: it's wrapped in $q.when() in case the processor does not return a promise)\n      return $q.when( processor.call(self, renderedRowsToProcess, self.columns) )\n        .then(function handleProcessedRows(processedRows) {\n          // Check for errors\n          if (!processedRows) {\n            throw \"Processor at index \" + i + \" did not return a set of renderable rows\";\n          }\n\n          if (!angular.isArray(processedRows)) {\n            throw \"Processor at index \" + i + \" did not return an array\";\n          }\n\n          // Processor is done, increment the counter\n          i++;\n\n          // If we're not done with the processors, call the next one\n          if (i <= self.rowsProcessors.length - 1) {\n            return startProcessor(i, processedRows);\n          }\n          // We're done! Resolve the 'finished' promise\n          else {\n            finished.resolve(processedRows);\n          }\n        });\n    }\n\n    // Start on the first processor\n    startProcessor(0, myRenderableRows);\n\n    return finished.promise;\n  };\n\n  Grid.prototype.setVisibleRows = function setVisibleRows(rows) {\n    var self = this;\n\n    // Reset all the render container row caches\n    for (var i in self.renderContainers) {\n      var container = self.renderContainers[i];\n\n      container.canvasHeightShouldUpdate = true;\n\n      if ( typeof(container.visibleRowCache) === 'undefined' ){\n        container.visibleRowCache = [];\n      } else {\n        container.visibleRowCache.length = 0;\n      }\n    }\n\n    // rows.forEach(function (row) {\n    for (var ri = 0; ri < rows.length; ri++) {\n      var row = rows[ri];\n\n      var targetContainer = (typeof(row.renderContainer) !== 'undefined' && row.renderContainer) ? row.renderContainer : 'body';\n\n      // If the row is visible\n      if (row.visible) {\n        self.renderContainers[targetContainer].visibleRowCache.push(row);\n      }\n    }\n    self.api.core.raise.rowsRendered(this.api);\n  };\n\n  /**\n   * @ngdoc function\n   * @name registerColumnsProcessor\n   * @methodOf ui.grid.class:Grid\n   * @param {function(renderedColumnsToProcess, rows)} columnProcessor column processor function, which\n   * is run in the context of the grid (i.e. this for the function will be the grid), and\n   * which must return an updated renderedColumnsToProcess which can be passed to the next processor\n   * in the chain\n   * @param {number} priority the priority of this processor.  In general we try to do them in 100s to leave room\n   * for other people to inject columns processors at intermediate priorities.  Lower priority columnsProcessors run earlier.\n   *\n   * At present all rows visible is running at 50, filter is running at 100, sort is at 200, grouping at 400, selectable rows at 500, pagination at 900 (pagination will generally want to be last)\n   * @description\n\n     Register a \"columns processor\" function. When the columns are updated,\n     the grid calls each registered \"columns processor\", which has a chance\n     to alter the set of columns, as long as the count is not modified.\n   */\n  Grid.prototype.registerColumnsProcessor = function registerColumnsProcessor(processor, priority) {\n    if (!angular.isFunction(processor)) {\n      throw 'Attempt to register non-function rows processor: ' + processor;\n    }\n\n    this.columnsProcessors.push({processor: processor, priority: priority});\n    this.columnsProcessors.sort(function sortByPriority( a, b ){\n      return a.priority - b.priority;\n    });\n  };\n\n  Grid.prototype.removeColumnsProcessor = function removeColumnsProcessor(processor) {\n    var idx = this.columnsProcessors.indexOf(processor);\n\n    if (typeof(idx) !== 'undefined' && idx !== undefined) {\n      this.columnsProcessors.splice(idx, 1);\n    }\n  };\n\n  Grid.prototype.processColumnsProcessors = function processColumnsProcessors(renderableColumns) {\n    var self = this;\n\n    // Create a shallow copy of the rows so that we can safely sort them without altering the original grid.rows sort order\n    var myRenderableColumns = renderableColumns.slice(0);\n\n    // Return myRenderableRows with no processing if we have no rows processors\n    if (self.columnsProcessors.length === 0) {\n      return $q.when(myRenderableColumns);\n    }\n\n    // Counter for iterating through rows processors\n    var i = 0;\n\n    // Promise for when we're done with all the processors\n    var finished = $q.defer();\n\n    // This function will call the processor in self.rowsProcessors at index 'i', and then\n    //   when done will call the next processor in the list, using the output from the processor\n    //   at i as the argument for 'renderedRowsToProcess' on the next iteration.\n    //\n    //   If we're at the end of the list of processors, we resolve our 'finished' callback with\n    //   the result.\n    function startProcessor(i, renderedColumnsToProcess) {\n      // Get the processor at 'i'\n      var processor = self.columnsProcessors[i].processor;\n\n      // Call the processor, passing in the rows to process and the current columns\n      //   (note: it's wrapped in $q.when() in case the processor does not return a promise)\n      return $q.when( processor.call(self, renderedColumnsToProcess, self.rows) )\n        .then(function handleProcessedRows(processedColumns) {\n          // Check for errors\n          if (!processedColumns) {\n            throw \"Processor at index \" + i + \" did not return a set of renderable rows\";\n          }\n\n          if (!angular.isArray(processedColumns)) {\n            throw \"Processor at index \" + i + \" did not return an array\";\n          }\n\n          // Processor is done, increment the counter\n          i++;\n\n          // If we're not done with the processors, call the next one\n          if (i <= self.columnsProcessors.length - 1) {\n            return startProcessor(i, myRenderableColumns);\n          }\n          // We're done! Resolve the 'finished' promise\n          else {\n            finished.resolve(myRenderableColumns);\n          }\n        });\n    }\n\n    // Start on the first processor\n    startProcessor(0, myRenderableColumns);\n\n    return finished.promise;\n  };\n\n  Grid.prototype.setVisibleColumns = function setVisibleColumns(columns) {\n    // gridUtil.logDebug('setVisibleColumns');\n\n    var self = this;\n\n    // Reset all the render container row caches\n    for (var i in self.renderContainers) {\n      var container = self.renderContainers[i];\n\n      container.visibleColumnCache.length = 0;\n    }\n\n    for (var ci = 0; ci < columns.length; ci++) {\n      var column = columns[ci];\n\n      // If the column is visible\n      if (column.visible) {\n        // If the column has a container specified\n        if (typeof(column.renderContainer) !== 'undefined' && column.renderContainer) {\n          self.renderContainers[column.renderContainer].visibleColumnCache.push(column);\n        }\n        // If not, put it into the body container\n        else {\n          self.renderContainers.body.visibleColumnCache.push(column);\n        }\n      }\n    }\n  };\n\n  /**\n   * @ngdoc function\n   * @name handleWindowResize\n   * @methodOf ui.grid.class:Grid\n   * @description Triggered when the browser window resizes; automatically resizes the grid\n   */\n  Grid.prototype.handleWindowResize = function handleWindowResize($event) {\n    var self = this;\n\n    self.gridWidth = gridUtil.elementWidth(self.element);\n    self.gridHeight = gridUtil.elementHeight(self.element);\n\n    self.queueRefresh();\n  };\n\n  /**\n   * @ngdoc function\n   * @name queueRefresh\n   * @methodOf ui.grid.class:Grid\n   * @description queues a grid refreshCanvas, a way of debouncing all the refreshes we might otherwise issue\n   */\n  Grid.prototype.queueRefresh = function queueRefresh() {\n    var self = this;\n\n    if (self.refreshCanceller) {\n      $timeout.cancel(self.refreshCanceller);\n    }\n\n    self.refreshCanceller = $timeout(function () {\n      self.refreshCanvas(true);\n    });\n\n    self.refreshCanceller.then(function () {\n      self.refreshCanceller = null;\n    });\n\n    return self.refreshCanceller;\n  };\n\n\n  /**\n   * @ngdoc function\n   * @name queueGridRefresh\n   * @methodOf ui.grid.class:Grid\n   * @description queues a grid refresh, a way of debouncing all the refreshes we might otherwise issue\n   */\n  Grid.prototype.queueGridRefresh = function queueGridRefresh() {\n    var self = this;\n\n    if (self.gridRefreshCanceller) {\n      $timeout.cancel(self.gridRefreshCanceller);\n    }\n\n    self.gridRefreshCanceller = $timeout(function () {\n      self.refresh(true);\n    });\n\n    self.gridRefreshCanceller.then(function () {\n      self.gridRefreshCanceller = null;\n    });\n\n    return self.gridRefreshCanceller;\n  };\n\n\n  /**\n   * @ngdoc function\n   * @name updateCanvasHeight\n   * @methodOf ui.grid.class:Grid\n   * @description flags all render containers to update their canvas height\n   */\n  Grid.prototype.updateCanvasHeight = function updateCanvasHeight() {\n    var self = this;\n\n    for (var containerId in self.renderContainers) {\n      if (self.renderContainers.hasOwnProperty(containerId)) {\n        var container = self.renderContainers[containerId];\n        container.canvasHeightShouldUpdate = true;\n      }\n    }\n  };\n\n  /**\n   * @ngdoc function\n   * @name buildStyles\n   * @methodOf ui.grid.class:Grid\n   * @description calls each styleComputation function\n   */\n  // TODO: this used to take $scope, but couldn't see that it was used\n  Grid.prototype.buildStyles = function buildStyles() {\n    // gridUtil.logDebug('buildStyles');\n\n    var self = this;\n\n    self.customStyles = '';\n\n    self.styleComputations\n      .sort(function(a, b) {\n        if (a.priority === null) { return 1; }\n        if (b.priority === null) { return -1; }\n        if (a.priority === null && b.priority === null) { return 0; }\n        return a.priority - b.priority;\n      })\n      .forEach(function (compInfo) {\n        // this used to provide $scope as a second parameter, but I couldn't find any\n        // style builders that used it, so removed it as part of moving to grid from controller\n        var ret = compInfo.func.call(self);\n\n        if (angular.isString(ret)) {\n          self.customStyles += '\\n' + ret;\n        }\n      });\n  };\n\n\n  Grid.prototype.minColumnsToRender = function minColumnsToRender() {\n    var self = this;\n    var viewport = this.getViewportWidth();\n\n    var min = 0;\n    var totalWidth = 0;\n    self.columns.forEach(function(col, i) {\n      if (totalWidth < viewport) {\n        totalWidth += col.drawnWidth;\n        min++;\n      }\n      else {\n        var currWidth = 0;\n        for (var j = i; j >= i - min; j--) {\n          currWidth += self.columns[j].drawnWidth;\n        }\n        if (currWidth < viewport) {\n          min++;\n        }\n      }\n    });\n\n    return min;\n  };\n\n  Grid.prototype.getBodyHeight = function getBodyHeight() {\n    // Start with the viewportHeight\n    var bodyHeight = this.getViewportHeight();\n\n    // Add the horizontal scrollbar height if there is one\n    //if (typeof(this.horizontalScrollbarHeight) !== 'undefined' && this.horizontalScrollbarHeight !== undefined && this.horizontalScrollbarHeight > 0) {\n    //  bodyHeight = bodyHeight + this.horizontalScrollbarHeight;\n    //}\n\n    return bodyHeight;\n  };\n\n  // NOTE: viewport drawable height is the height of the grid minus the header row height (including any border)\n  // TODO(c0bra): account for footer height\n  Grid.prototype.getViewportHeight = function getViewportHeight() {\n    var self = this;\n\n    var viewPortHeight = this.gridHeight - this.headerHeight - this.footerHeight;\n\n    // Account for native horizontal scrollbar, if present\n    //if (typeof(this.horizontalScrollbarHeight) !== 'undefined' && this.horizontalScrollbarHeight !== undefined && this.horizontalScrollbarHeight > 0) {\n    //  viewPortHeight = viewPortHeight - this.horizontalScrollbarHeight;\n    //}\n\n    var adjustment = self.getViewportAdjustment();\n\n    viewPortHeight = viewPortHeight + adjustment.height;\n\n    //gridUtil.logDebug('viewPortHeight', viewPortHeight);\n\n    return viewPortHeight;\n  };\n\n  Grid.prototype.getViewportWidth = function getViewportWidth() {\n    var self = this;\n\n    var viewPortWidth = this.gridWidth;\n\n    //if (typeof(this.verticalScrollbarWidth) !== 'undefined' && this.verticalScrollbarWidth !== undefined && this.verticalScrollbarWidth > 0) {\n    //  viewPortWidth = viewPortWidth - this.verticalScrollbarWidth;\n    //}\n\n    var adjustment = self.getViewportAdjustment();\n\n    viewPortWidth = viewPortWidth + adjustment.width;\n\n    //gridUtil.logDebug('getviewPortWidth', viewPortWidth);\n\n    return viewPortWidth;\n  };\n\n  Grid.prototype.getHeaderViewportWidth = function getHeaderViewportWidth() {\n    var viewPortWidth = this.getViewportWidth();\n\n    //if (typeof(this.verticalScrollbarWidth) !== 'undefined' && this.verticalScrollbarWidth !== undefined && this.verticalScrollbarWidth > 0) {\n    //  viewPortWidth = viewPortWidth + this.verticalScrollbarWidth;\n    //}\n\n    return viewPortWidth;\n  };\n\n  Grid.prototype.addVerticalScrollSync = function (containerId, callBackFn) {\n    this.verticalScrollSyncCallBackFns[containerId] = callBackFn;\n  };\n\n  Grid.prototype.addHorizontalScrollSync = function (containerId, callBackFn) {\n    this.horizontalScrollSyncCallBackFns[containerId] = callBackFn;\n  };\n\n/**\n * Scroll needed containers by calling their ScrollSyncs\n * @param sourceContainerId the containerId that has already set it's top/left.\n *         can be empty string which means all containers need to set top/left\n * @param scrollEvent\n */\n  Grid.prototype.scrollContainers = function (sourceContainerId, scrollEvent) {\n\n    if (scrollEvent.y) {\n      //default for no container Id (ex. mousewheel means that all containers must set scrollTop/Left)\n      var verts = ['body','left', 'right'];\n\n      this.flagScrollingVertically(scrollEvent);\n\n      if (sourceContainerId === 'body') {\n        verts = ['left', 'right'];\n      }\n      else if (sourceContainerId === 'left') {\n        verts = ['body', 'right'];\n      }\n      else if (sourceContainerId === 'right') {\n        verts = ['body', 'left'];\n      }\n\n      for (var i = 0; i < verts.length; i++) {\n        var id = verts[i];\n        if (this.verticalScrollSyncCallBackFns[id]) {\n          this.verticalScrollSyncCallBackFns[id](scrollEvent);\n        }\n      }\n\n    }\n\n    if (scrollEvent.x) {\n      //default for no container Id (ex. mousewheel means that all containers must set scrollTop/Left)\n      var horizs = ['body','bodyheader', 'bodyfooter'];\n\n      this.flagScrollingHorizontally(scrollEvent);\n      if (sourceContainerId === 'body') {\n        horizs = ['bodyheader', 'bodyfooter'];\n      }\n\n      for (var j = 0; j < horizs.length; j++) {\n        var idh = horizs[j];\n        if (this.horizontalScrollSyncCallBackFns[idh]) {\n          this.horizontalScrollSyncCallBackFns[idh](scrollEvent);\n        }\n      }\n\n    }\n\n  };\n\n  Grid.prototype.registerViewportAdjuster = function registerViewportAdjuster(func) {\n    this.viewportAdjusters.push(func);\n  };\n\n  Grid.prototype.removeViewportAdjuster = function registerViewportAdjuster(func) {\n    var idx = this.viewportAdjusters.indexOf(func);\n\n    if (typeof(idx) !== 'undefined' && idx !== undefined) {\n      this.viewportAdjusters.splice(idx, 1);\n    }\n  };\n\n  Grid.prototype.getViewportAdjustment = function getViewportAdjustment() {\n    var self = this;\n\n    var adjustment = { height: 0, width: 0 };\n\n    self.viewportAdjusters.forEach(function (func) {\n      adjustment = func.call(this, adjustment);\n    });\n\n    return adjustment;\n  };\n\n  Grid.prototype.getVisibleRowCount = function getVisibleRowCount() {\n    // var count = 0;\n\n    // this.rows.forEach(function (row) {\n    //   if (row.visible) {\n    //     count++;\n    //   }\n    // });\n\n    // return this.visibleRowCache.length;\n    return this.renderContainers.body.visibleRowCache.length;\n  };\n\n   Grid.prototype.getVisibleRows = function getVisibleRows() {\n    return this.renderContainers.body.visibleRowCache;\n   };\n\n  Grid.prototype.getVisibleColumnCount = function getVisibleColumnCount() {\n    // var count = 0;\n\n    // this.rows.forEach(function (row) {\n    //   if (row.visible) {\n    //     count++;\n    //   }\n    // });\n\n    // return this.visibleRowCache.length;\n    return this.renderContainers.body.visibleColumnCache.length;\n  };\n\n\n  Grid.prototype.searchRows = function searchRows(renderableRows) {\n    return rowSearcher.search(this, renderableRows, this.columns);\n  };\n\n  Grid.prototype.sortByColumn = function sortByColumn(renderableRows) {\n    return rowSorter.sort(this, renderableRows, this.columns);\n  };\n\n  /**\n   * @ngdoc function\n   * @name getCellValue\n   * @methodOf ui.grid.class:Grid\n   * @description Gets the value of a cell for a particular row and column\n   * @param {GridRow} row Row to access\n   * @param {GridColumn} col Column to access\n   */\n  Grid.prototype.getCellValue = function getCellValue(row, col){\n    if ( typeof(row.entity[ '$$' + col.uid ]) !== 'undefined' ) {\n      return row.entity[ '$$' + col.uid].rendered;\n    } else if (this.options.flatEntityAccess && typeof(col.field) !== 'undefined' ){\n      return row.entity[col.field];\n    } else {\n      if (!col.cellValueGetterCache) {\n        col.cellValueGetterCache = $parse(row.getEntityQualifiedColField(col));\n      }\n\n      return col.cellValueGetterCache(row);\n    }\n  };\n\n  /**\n   * @ngdoc function\n   * @name getCellDisplayValue\n   * @methodOf ui.grid.class:Grid\n   * @description Gets the displayed value of a cell after applying any the `cellFilter`\n   * @param {GridRow} row Row to access\n   * @param {GridColumn} col Column to access\n   */\n  Grid.prototype.getCellDisplayValue = function getCellDisplayValue(row, col) {\n    if ( !col.cellDisplayGetterCache ) {\n      var custom_filter = col.cellFilter ? \" | \" + col.cellFilter : \"\";\n\n      if (typeof(row.entity['$$' + col.uid]) !== 'undefined') {\n        col.cellDisplayGetterCache = $parse(row.entity['$$' + col.uid].rendered + custom_filter);\n      } else if (this.options.flatEntityAccess && typeof(col.field) !== 'undefined') {\n        col.cellDisplayGetterCache = $parse(row.entity[col.field] + custom_filter);\n      } else {\n        col.cellDisplayGetterCache = $parse(row.getEntityQualifiedColField(col) + custom_filter);\n      }\n    }\n\n    return col.cellDisplayGetterCache(row);\n  };\n\n\n  Grid.prototype.getNextColumnSortPriority = function getNextColumnSortPriority() {\n    var self = this,\n        p = 0;\n\n    self.columns.forEach(function (col) {\n      if (col.sort && col.sort.priority && col.sort.priority > p) {\n        p = col.sort.priority;\n      }\n    });\n\n    return p + 1;\n  };\n\n  /**\n   * @ngdoc function\n   * @name resetColumnSorting\n   * @methodOf ui.grid.class:Grid\n   * @description Return the columns that the grid is currently being sorted by\n   * @param {GridColumn} [excludedColumn] Optional GridColumn to exclude from having its sorting reset\n   */\n  Grid.prototype.resetColumnSorting = function resetColumnSorting(excludeCol) {\n    var self = this;\n\n    self.columns.forEach(function (col) {\n      if (col !== excludeCol && !col.suppressRemoveSort) {\n        col.sort = {};\n      }\n    });\n  };\n\n  /**\n   * @ngdoc function\n   * @name getColumnSorting\n   * @methodOf ui.grid.class:Grid\n   * @description Return the columns that the grid is currently being sorted by\n   * @returns {Array[GridColumn]} An array of GridColumn objects\n   */\n  Grid.prototype.getColumnSorting = function getColumnSorting() {\n    var self = this;\n\n    var sortedCols = [], myCols;\n\n    // Iterate through all the columns, sorted by priority\n    // Make local copy of column list, because sorting is in-place and we do not want to\n    // change the original sequence of columns\n    myCols = self.columns.slice(0);\n    myCols.sort(rowSorter.prioritySort).forEach(function (col) {\n      if (col.sort && typeof(col.sort.direction) !== 'undefined' && col.sort.direction && (col.sort.direction === uiGridConstants.ASC || col.sort.direction === uiGridConstants.DESC)) {\n        sortedCols.push(col);\n      }\n    });\n\n    return sortedCols;\n  };\n\n  /**\n   * @ngdoc function\n   * @name sortColumn\n   * @methodOf ui.grid.class:Grid\n   * @description Set the sorting on a given column, optionally resetting any existing sorting on the Grid.\n   * Emits the sortChanged event whenever the sort criteria are changed.\n   * @param {GridColumn} column Column to set the sorting on\n   * @param {uiGridConstants.ASC|uiGridConstants.DESC} [direction] Direction to sort by, either descending or ascending.\n   *   If not provided, the column will iterate through the sort directions: ascending, descending, unsorted.\n   * @param {boolean} [add] Add this column to the sorting. If not provided or set to `false`, the Grid will reset any existing sorting and sort\n   *   by this column only\n   * @returns {Promise} A resolved promise that supplies the column.\n   */\n\n  Grid.prototype.sortColumn = function sortColumn(column, directionOrAdd, add) {\n    var self = this,\n        direction = null;\n\n    if (typeof(column) === 'undefined' || !column) {\n      throw new Error('No column parameter provided');\n    }\n\n    // Second argument can either be a direction or whether to add this column to the existing sort.\n    //   If it's a boolean, it's an add, otherwise, it's a direction\n    if (typeof(directionOrAdd) === 'boolean') {\n      add = directionOrAdd;\n    }\n    else {\n      direction = directionOrAdd;\n    }\n\n    if (!add) {\n      self.resetColumnSorting(column);\n      column.sort.priority = 0;\n      // Get the actual priority since there may be columns which have suppressRemoveSort set\n      column.sort.priority = self.getNextColumnSortPriority();\n    }\n    else if (!column.sort.priority){\n      column.sort.priority = self.getNextColumnSortPriority();\n    }\n\n    if (!direction) {\n      // Figure out the sort direction\n      if (column.sort.direction && column.sort.direction === uiGridConstants.ASC) {\n        column.sort.direction = uiGridConstants.DESC;\n      }\n      else if (column.sort.direction && column.sort.direction === uiGridConstants.DESC) {\n        if ( column.colDef && column.suppressRemoveSort ){\n          column.sort.direction = uiGridConstants.ASC;\n        } else {\n          column.sort = {};\n        }\n      }\n      else {\n        column.sort.direction = uiGridConstants.ASC;\n      }\n    }\n    else {\n      column.sort.direction = direction;\n    }\n\n    self.api.core.raise.sortChanged( self, self.getColumnSorting() );\n\n    return $q.when(column);\n  };\n\n  /**\n   * communicate to outside world that we are done with initial rendering\n   */\n  Grid.prototype.renderingComplete = function(){\n    if (angular.isFunction(this.options.onRegisterApi)) {\n      this.options.onRegisterApi(this.api);\n    }\n    this.api.core.raise.renderingComplete( this.api );\n  };\n\n  Grid.prototype.createRowHashMap = function createRowHashMap() {\n    var self = this;\n\n    var hashMap = new RowHashMap();\n    hashMap.grid = self;\n\n    return hashMap;\n  };\n\n\n  /**\n   * @ngdoc function\n   * @name refresh\n   * @methodOf ui.grid.class:Grid\n   * @description Refresh the rendered grid on screen.\n   * @param {boolean} [rowsAltered] Optional flag for refreshing when the number of rows has changed.\n   */\n  Grid.prototype.refresh = function refresh(rowsAltered) {\n    var self = this;\n\n    var p1 = self.processRowsProcessors(self.rows).then(function (renderableRows) {\n      self.setVisibleRows(renderableRows);\n    });\n\n    var p2 = self.processColumnsProcessors(self.columns).then(function (renderableColumns) {\n      self.setVisibleColumns(renderableColumns);\n    });\n\n    return $q.all([p1, p2]).then(function () {\n      self.redrawInPlace(rowsAltered);\n\n      self.refreshCanvas(true);\n    });\n  };\n\n  /**\n   * @ngdoc function\n   * @name refreshRows\n   * @methodOf ui.grid.class:Grid\n   * @description Refresh the rendered rows on screen?  Note: not functional at present\n   * @returns {promise} promise that is resolved when render completes?\n   *\n   */\n  Grid.prototype.refreshRows = function refreshRows() {\n    var self = this;\n\n    return self.processRowsProcessors(self.rows)\n      .then(function (renderableRows) {\n        self.setVisibleRows(renderableRows);\n\n        self.redrawInPlace();\n\n        self.refreshCanvas( true );\n      });\n  };\n\n  /**\n   * @ngdoc function\n   * @name refreshCanvas\n   * @methodOf ui.grid.class:Grid\n   * @description Builds all styles and recalculates much of the grid sizing\n   * @param {object} buildStyles optional parameter.  Use TBD\n   * @returns {promise} promise that is resolved when the canvas\n   * has been refreshed\n   *\n   */\n  Grid.prototype.refreshCanvas = function(buildStyles) {\n    var self = this;\n\n    if (buildStyles) {\n      self.buildStyles();\n    }\n\n    var p = $q.defer();\n\n    // Get all the header heights\n    var containerHeadersToRecalc = [];\n    for (var containerId in self.renderContainers) {\n      if (self.renderContainers.hasOwnProperty(containerId)) {\n        var container = self.renderContainers[containerId];\n\n        // Skip containers that have no canvasWidth set yet\n        if (container.canvasWidth === null || isNaN(container.canvasWidth)) {\n          continue;\n        }\n\n        if (container.header || container.headerCanvas) {\n          container.explicitHeaderHeight = container.explicitHeaderHeight || null;\n          container.explicitHeaderCanvasHeight = container.explicitHeaderCanvasHeight || null;\n\n          containerHeadersToRecalc.push(container);\n        }\n      }\n    }\n\n    /*\n     *\n     * Here we loop through the headers, measuring each element as well as any header \"canvas\" it has within it.\n     *\n     * If any header is less than the largest header height, it will be resized to that so that we don't have headers\n     * with different heights, which looks like a rendering problem\n     *\n     * We'll do the same thing with the header canvases, and give the header CELLS an explicit height if their canvas\n     * is smaller than the largest canvas height. That was header cells without extra controls like filtering don't\n     * appear shorter than other cells.\n     *\n     */\n    if (containerHeadersToRecalc.length > 0) {\n      // Build the styles without the explicit header heights\n      if (buildStyles) {\n        self.buildStyles();\n      }\n\n      // Putting in a timeout as it's not calculating after the grid element is rendered and filled out\n      $timeout(function() {\n        // var oldHeaderHeight = self.grid.headerHeight;\n        // self.grid.headerHeight = gridUtil.outerElementHeight(self.header);\n\n        var rebuildStyles = false;\n\n        // Get all the header heights\n        var maxHeaderHeight = 0;\n        var maxHeaderCanvasHeight = 0;\n        var i, container;\n        var getHeight = function(oldVal, newVal){\n          if ( oldVal !== newVal){\n            rebuildStyles = true;\n          }\n          return newVal;\n        };\n        for (i = 0; i < containerHeadersToRecalc.length; i++) {\n          container = containerHeadersToRecalc[i];\n\n          // Skip containers that have no canvasWidth set yet\n          if (container.canvasWidth === null || isNaN(container.canvasWidth)) {\n            continue;\n          }\n\n          if (container.header) {\n            var headerHeight = container.headerHeight = getHeight(container.headerHeight, parseInt(gridUtil.outerElementHeight(container.header), 10));\n\n            // Get the \"inner\" header height, that is the height minus the top and bottom borders, if present. We'll use it to make sure all the headers have a consistent height\n            var topBorder = gridUtil.getBorderSize(container.header, 'top');\n            var bottomBorder = gridUtil.getBorderSize(container.header, 'bottom');\n            var innerHeaderHeight = parseInt(headerHeight - topBorder - bottomBorder, 10);\n\n            innerHeaderHeight  = innerHeaderHeight < 0 ? 0 : innerHeaderHeight;\n\n            container.innerHeaderHeight = innerHeaderHeight;\n\n            // If the header doesn't have an explicit height set, save the largest header height for use later\n            //   Explicit header heights are based off of the max we are calculating here. We never want to base the max on something we're setting explicitly\n            if (!container.explicitHeaderHeight && innerHeaderHeight > maxHeaderHeight) {\n              maxHeaderHeight = innerHeaderHeight;\n            }\n          }\n\n          if (container.headerCanvas) {\n            var headerCanvasHeight = container.headerCanvasHeight = getHeight(container.headerCanvasHeight, parseInt(gridUtil.outerElementHeight(container.headerCanvas), 10));\n\n\n            // If the header doesn't have an explicit canvas height, save the largest header canvas height for use later\n            //   Explicit header heights are based off of the max we are calculating here. We never want to base the max on something we're setting explicitly\n            if (!container.explicitHeaderCanvasHeight && headerCanvasHeight > maxHeaderCanvasHeight) {\n              maxHeaderCanvasHeight = headerCanvasHeight;\n            }\n          }\n        }\n\n        // Go through all the headers\n        for (i = 0; i < containerHeadersToRecalc.length; i++) {\n          container = containerHeadersToRecalc[i];\n\n          /* If:\n              1. We have a max header height\n              2. This container has a header height defined\n              3. And either this container has an explicit header height set, OR its header height is less than the max\n\n              then:\n\n              Give this container's header an explicit height so it will line up with the tallest header\n          */\n          if (\n            maxHeaderHeight > 0 && typeof(container.headerHeight) !== 'undefined' && container.headerHeight !== null &&\n            (container.explicitHeaderHeight || container.headerHeight < maxHeaderHeight)\n          ) {\n            container.explicitHeaderHeight = getHeight(container.explicitHeaderHeight, maxHeaderHeight);\n          }\n\n          // Do the same as above except for the header canvas\n          if (\n            maxHeaderCanvasHeight > 0 && typeof(container.headerCanvasHeight) !== 'undefined' && container.headerCanvasHeight !== null &&\n            (container.explicitHeaderCanvasHeight || container.headerCanvasHeight < maxHeaderCanvasHeight)\n          ) {\n            container.explicitHeaderCanvasHeight = getHeight(container.explicitHeaderCanvasHeight, maxHeaderCanvasHeight);\n          }\n        }\n\n        // Rebuild styles if the header height has changed\n        //   The header height is used in body/viewport calculations and those are then used in other styles so we need it to be available\n        if (buildStyles && rebuildStyles) {\n          self.buildStyles();\n        }\n\n        p.resolve();\n      });\n    }\n    else {\n      // Timeout still needs to be here to trigger digest after styles have been rebuilt\n      $timeout(function() {\n        p.resolve();\n      });\n    }\n\n    return p.promise;\n  };\n\n\n  /**\n   * @ngdoc function\n   * @name redrawCanvas\n   * @methodOf ui.grid.class:Grid\n   * @description Redraw the rows and columns based on our current scroll position\n   * @param {boolean} [rowsAdded] Optional to indicate rows are added and the scroll percentage must be recalculated\n   *\n   */\n  Grid.prototype.redrawInPlace = function redrawInPlace(rowsAdded) {\n    // gridUtil.logDebug('redrawInPlace');\n\n    var self = this;\n\n    for (var i in self.renderContainers) {\n      var container = self.renderContainers[i];\n\n      // gridUtil.logDebug('redrawing container', i);\n\n      if (rowsAdded) {\n        container.adjustRows(container.prevScrollTop, null);\n        container.adjustColumns(container.prevScrollLeft, null);\n      }\n      else {\n        container.adjustRows(null, container.prevScrolltopPercentage);\n        container.adjustColumns(null, container.prevScrollleftPercentage);\n      }\n    }\n  };\n\n    /**\n     * @ngdoc function\n     * @name hasLeftContainerColumns\n     * @methodOf ui.grid.class:Grid\n     * @description returns true if leftContainer has columns\n     */\n    Grid.prototype.hasLeftContainerColumns = function () {\n      return this.hasLeftContainer() && this.renderContainers.left.renderedColumns.length > 0;\n    };\n\n    /**\n     * @ngdoc function\n     * @name hasRightContainerColumns\n     * @methodOf ui.grid.class:Grid\n     * @description returns true if rightContainer has columns\n     */\n    Grid.prototype.hasRightContainerColumns = function () {\n      return this.hasRightContainer() && this.renderContainers.right.renderedColumns.length > 0;\n    };\n\n    /**\n     * @ngdoc method\n     * @methodOf  ui.grid.class:Grid\n     * @name scrollToIfNecessary\n     * @description Scrolls the grid to make a certain row and column combo visible,\n     *   in the case that it is not completely visible on the screen already.\n     * @param {GridRow} gridRow row to make visible\n     * @param {GridCol} gridCol column to make visible\n     * @returns {promise} a promise that is resolved when scrolling is complete\n     */\n    Grid.prototype.scrollToIfNecessary = function (gridRow, gridCol) {\n      var self = this;\n\n      var scrollEvent = new ScrollEvent(self, 'uiGrid.scrollToIfNecessary');\n\n      // Alias the visible row and column caches\n      var visRowCache = self.renderContainers.body.visibleRowCache;\n      var visColCache = self.renderContainers.body.visibleColumnCache;\n\n      /*-- Get the top, left, right, and bottom \"scrolled\" edges of the grid --*/\n\n      // The top boundary is the current Y scroll position PLUS the header height, because the header can obscure rows when the grid is scrolled downwards\n      var topBound = self.renderContainers.body.prevScrollTop + self.headerHeight;\n\n      // Don't the let top boundary be less than 0\n      topBound = (topBound < 0) ? 0 : topBound;\n\n      // The left boundary is the current X scroll position\n      var leftBound = self.renderContainers.body.prevScrollLeft;\n\n      // The bottom boundary is the current Y scroll position, plus the height of the grid, but minus the header height.\n      //   Basically this is the viewport height added on to the scroll position\n      var bottomBound = self.renderContainers.body.prevScrollTop + self.gridHeight - self.renderContainers.body.headerHeight - self.footerHeight -  self.scrollbarWidth;\n\n      // If there's a horizontal scrollbar, remove its height from the bottom boundary, otherwise we'll be letting it obscure rows\n      //if (self.horizontalScrollbarHeight) {\n      //  bottomBound = bottomBound - self.horizontalScrollbarHeight;\n      //}\n\n      // The right position is the current X scroll position minus the grid width\n      var rightBound = self.renderContainers.body.prevScrollLeft + Math.ceil(self.gridWidth);\n\n      // If there's a vertical scrollbar, subtract it from the right boundary or we'll allow it to obscure cells\n      //if (self.verticalScrollbarWidth) {\n      //  rightBound = rightBound - self.verticalScrollbarWidth;\n      //}\n\n      // We were given a row to scroll to\n      if (gridRow !== null) {\n        // This is the index of the row we want to scroll to, within the list of rows that can be visible\n        var seekRowIndex = visRowCache.indexOf(gridRow);\n\n        // Total vertical scroll length of the grid\n        var scrollLength = (self.renderContainers.body.getCanvasHeight() - self.renderContainers.body.getViewportHeight());\n\n        // Add the height of the native horizontal scrollbar to the scroll length, if it's there. Otherwise it will mask over the final row\n        //if (self.horizontalScrollbarHeight && self.horizontalScrollbarHeight > 0) {\n        //  scrollLength = scrollLength + self.horizontalScrollbarHeight;\n        //}\n\n        // This is the minimum amount of pixels we need to scroll vertical in order to see this row.\n        var pixelsToSeeRow = ((seekRowIndex + 1) * self.options.rowHeight);\n\n        // Don't let the pixels required to see the row be less than zero\n        pixelsToSeeRow = (pixelsToSeeRow < 0) ? 0 : pixelsToSeeRow;\n\n        var scrollPixels, percentage;\n\n        // If the scroll position we need to see the row is LESS than the top boundary, i.e. obscured above the top of the self...\n        if (pixelsToSeeRow < topBound) {\n          // Get the different between the top boundary and the required scroll position and subtract it from the current scroll position\\\n          //   to get the full position we need\n          scrollPixels = self.renderContainers.body.prevScrollTop - (topBound - pixelsToSeeRow);\n\n          // Turn the scroll position into a percentage and make it an argument for a scroll event\n          percentage = scrollPixels / scrollLength;\n          scrollEvent.y = { percentage: percentage  };\n        }\n        // Otherwise if the scroll position we need to see the row is MORE than the bottom boundary, i.e. obscured below the bottom of the self...\n        else if (pixelsToSeeRow > bottomBound) {\n          // Get the different between the bottom boundary and the required scroll position and add it to the current scroll position\n          //   to get the full position we need\n          scrollPixels = pixelsToSeeRow - bottomBound + self.renderContainers.body.prevScrollTop;\n\n          // Turn the scroll position into a percentage and make it an argument for a scroll event\n          percentage = scrollPixels / scrollLength;\n          scrollEvent.y = { percentage: percentage  };\n        }\n      }\n\n      // We were given a column to scroll to\n      if (gridCol !== null) {\n        // This is the index of the row we want to scroll to, within the list of rows that can be visible\n        var seekColumnIndex = visColCache.indexOf(gridCol);\n\n        // Total vertical scroll length of the grid\n        var horizScrollLength = (self.renderContainers.body.getCanvasWidth() - self.renderContainers.body.getViewportWidth());\n\n        // Add the height of the native horizontal scrollbar to the scroll length, if it's there. Otherwise it will mask over the final row\n        // if (self.verticalScrollbarWidth && self.verticalScrollbarWidth > 0) {\n        //   horizScrollLength = horizScrollLength + self.verticalScrollbarWidth;\n        // }\n\n        // This is the minimum amount of pixels we need to scroll vertical in order to see this column\n        var columnLeftEdge = 0;\n        for (var i = 0; i < seekColumnIndex; i++) {\n          var col = visColCache[i];\n          columnLeftEdge += col.drawnWidth;\n        }\n        columnLeftEdge = (columnLeftEdge < 0) ? 0 : columnLeftEdge;\n\n        var columnRightEdge = columnLeftEdge + gridCol.drawnWidth;\n\n        // Don't let the pixels required to see the column be less than zero\n        columnRightEdge = (columnRightEdge < 0) ? 0 : columnRightEdge;\n\n        var horizScrollPixels, horizPercentage;\n\n        // If the scroll position we need to see the row is LESS than the top boundary, i.e. obscured above the top of the self...\n        if (columnLeftEdge < leftBound) {\n          // Get the different between the top boundary and the required scroll position and subtract it from the current scroll position\\\n          //   to get the full position we need\n          horizScrollPixels = self.renderContainers.body.prevScrollLeft - (leftBound - columnLeftEdge);\n\n          // Turn the scroll position into a percentage and make it an argument for a scroll event\n          horizPercentage = horizScrollPixels / horizScrollLength;\n          horizPercentage = (horizPercentage > 1) ? 1 : horizPercentage;\n          scrollEvent.x = { percentage: horizPercentage  };\n        }\n        // Otherwise if the scroll position we need to see the row is MORE than the bottom boundary, i.e. obscured below the bottom of the self...\n        else if (columnRightEdge > rightBound) {\n          // Get the different between the bottom boundary and the required scroll position and add it to the current scroll position\n          //   to get the full position we need\n          horizScrollPixels = columnRightEdge - rightBound + self.renderContainers.body.prevScrollLeft;\n\n          // Turn the scroll position into a percentage and make it an argument for a scroll event\n          horizPercentage = horizScrollPixels / horizScrollLength;\n          horizPercentage = (horizPercentage > 1) ? 1 : horizPercentage;\n          scrollEvent.x = { percentage: horizPercentage  };\n        }\n      }\n\n      var deferred = $q.defer();\n\n      // If we need to scroll on either the x or y axes, fire a scroll event\n      if (scrollEvent.y || scrollEvent.x) {\n        scrollEvent.withDelay = false;\n        self.scrollContainers('',scrollEvent);\n        var dereg = self.api.core.on.scrollEnd(null,function() {\n          deferred.resolve(scrollEvent);\n          dereg();\n        });\n      }\n      else {\n        deferred.resolve();\n      }\n\n      return deferred.promise;\n    };\n\n    /**\n     * @ngdoc method\n     * @methodOf ui.grid.class:Grid\n     * @name scrollTo\n     * @description Scroll the grid such that the specified\n     * row and column is in view\n     * @param {object} rowEntity gridOptions.data[] array instance to make visible\n     * @param {object} colDef to make visible\n     * @returns {promise} a promise that is resolved after any scrolling is finished\n     */\n    Grid.prototype.scrollTo = function (rowEntity, colDef) {\n      var gridRow = null, gridCol = null;\n\n      if (rowEntity !== null && typeof(rowEntity) !== 'undefined' ) {\n        gridRow = this.getRow(rowEntity);\n      }\n\n      if (colDef !== null && typeof(colDef) !== 'undefined' ) {\n        gridCol = this.getColumn(colDef.name ? colDef.name : colDef.field);\n      }\n      return this.scrollToIfNecessary(gridRow, gridCol);\n    };\n\n  /**\n   * @ngdoc function\n   * @name clearAllFilters\n   * @methodOf ui.grid.class:Grid\n   * @description Clears all filters and optionally refreshes the visible rows.\n   * @param {object} refreshRows Defaults to true.\n   * @param {object} clearConditions Defaults to false.\n   * @param {object} clearFlags Defaults to false.\n   * @returns {promise} If `refreshRows` is true, returns a promise of the rows refreshing.\n   */\n  Grid.prototype.clearAllFilters = function clearAllFilters(refreshRows, clearConditions, clearFlags) {\n    // Default `refreshRows` to true because it will be the most commonly desired behaviour.\n    if (refreshRows === undefined) {\n      refreshRows = true;\n    }\n    if (clearConditions === undefined) {\n      clearConditions = false;\n    }\n    if (clearFlags === undefined) {\n      clearFlags = false;\n    }\n\n    this.columns.forEach(function(column) {\n      column.filters.forEach(function(filter) {\n        filter.term = undefined;\n\n        if (clearConditions) {\n          filter.condition = undefined;\n        }\n\n        if (clearFlags) {\n          filter.flags = undefined;\n        }\n      });\n    });\n\n    if (refreshRows) {\n      return this.refreshRows();\n    }\n  };\n\n\n      // Blatantly stolen from Angular as it isn't exposed (yet? 2.0?)\n  function RowHashMap() {}\n\n  RowHashMap.prototype = {\n    /**\n     * Store key value pair\n     * @param key key to store can be any type\n     * @param value value to store can be any type\n     */\n    put: function(key, value) {\n      this[this.grid.options.rowIdentity(key)] = value;\n    },\n\n    /**\n     * @param key\n     * @returns {Object} the value for the key\n     */\n    get: function(key) {\n      return this[this.grid.options.rowIdentity(key)];\n    },\n\n    /**\n     * Remove the key/value pair\n     * @param key\n     */\n    remove: function(key) {\n      var value = this[key = this.grid.options.rowIdentity(key)];\n      delete this[key];\n      return value;\n    }\n  };\n\n\n\n  return Grid;\n\n}]);\n\n})();\n\n(function () {\n\n  angular.module('ui.grid')\n    .factory('GridApi', ['$q', '$rootScope', 'gridUtil', 'uiGridConstants', 'GridRow', 'uiGridGridMenuService',\n      function ($q, $rootScope, gridUtil, uiGridConstants, GridRow, uiGridGridMenuService) {\n        /**\n         * @ngdoc function\n         * @name ui.grid.class:GridApi\n         * @description GridApi provides the ability to register public methods events inside the grid and allow\n         * for other components to use the api via featureName.raise.methodName and featureName.on.eventName(function(args){}.\n         * <br/>\n         * To listen to events, you must add a callback to gridOptions.onRegisterApi\n         * <pre>\n         *   $scope.gridOptions.onRegisterApi = function(gridApi){\n         *      gridApi.cellNav.on.navigate($scope,function(newRowCol, oldRowCol){\n         *          $log.log('navigation event');\n         *      });\n         *   };\n         * </pre>\n         * @param {object} grid grid that owns api\n         */\n        var GridApi = function GridApi(grid) {\n          this.grid = grid;\n          this.listeners = [];\n          \n          /**\n           * @ngdoc function\n           * @name renderingComplete\n           * @methodOf  ui.grid.core.api:PublicApi\n           * @description Rendering is complete, called at the same\n           * time as `onRegisterApi`, but provides a way to obtain\n           * that same event within features without stopping end\n           * users from getting at the onRegisterApi method.\n           * \n           * Included in gridApi so that it's always there - otherwise\n           * there is still a timing problem with when a feature can\n           * call this. \n           * \n           * @param {GridApi} gridApi the grid api, as normally \n           * returned in the onRegisterApi method\n           * \n           * @example\n           * <pre>\n           *      gridApi.core.on.renderingComplete( grid );\n           * </pre>\n           */\n          this.registerEvent( 'core', 'renderingComplete' );\n\n          /**\n           * @ngdoc event\n           * @name filterChanged\n           * @eventOf  ui.grid.core.api:PublicApi\n           * @description  is raised after the filter is changed.  The nature\n           * of the watch expression doesn't allow notification of what changed,\n           * so the receiver of this event will need to re-extract the filter \n           * conditions from the columns.\n           * \n           */\n          this.registerEvent( 'core', 'filterChanged' );\n\n          /**\n           * @ngdoc function\n           * @name setRowInvisible\n           * @methodOf  ui.grid.core.api:PublicApi\n           * @description Sets an override on the row to make it always invisible,\n           * which will override any filtering or other visibility calculations.  \n           * If the row is currently visible then sets it to invisible and calls\n           * both grid refresh and emits the rowsVisibleChanged event\n           * @param {object} rowEntity gridOptions.data[] array instance\n           */\n          this.registerMethod( 'core', 'setRowInvisible', GridRow.prototype.setRowInvisible );\n      \n          /**\n           * @ngdoc function\n           * @name clearRowInvisible\n           * @methodOf  ui.grid.core.api:PublicApi\n           * @description Clears any override on visibility for the row so that it returns to \n           * using normal filtering and other visibility calculations.  \n           * If the row is currently invisible then sets it to visible and calls\n           * both grid refresh and emits the rowsVisibleChanged event\n           * TODO: if a filter is active then we can't just set it to visible?\n           * @param {object} rowEntity gridOptions.data[] array instance\n           */\n          this.registerMethod( 'core', 'clearRowInvisible', GridRow.prototype.clearRowInvisible );\n      \n          /**\n           * @ngdoc function\n           * @name getVisibleRows\n           * @methodOf  ui.grid.core.api:PublicApi\n           * @description Returns all visible rows\n           * @param {Grid} grid the grid you want to get visible rows from\n           * @returns {array} an array of gridRow\n           */\n          this.registerMethod( 'core', 'getVisibleRows', this.grid.getVisibleRows );\n          \n          /**\n           * @ngdoc event\n           * @name rowsVisibleChanged\n           * @eventOf  ui.grid.core.api:PublicApi\n           * @description  is raised after the rows that are visible\n           * change.  The filtering is zero-based, so it isn't possible\n           * to say which rows changed (unlike in the selection feature).\n           * We can plausibly know which row was changed when setRowInvisible\n           * is called, but in that situation the user already knows which row\n           * they changed.  When a filter runs we don't know what changed,\n           * and that is the one that would have been useful.\n           *\n           */\n          this.registerEvent( 'core', 'rowsVisibleChanged' );\n\n          /**\n           * @ngdoc event\n           * @name rowsRendered\n           * @eventOf  ui.grid.core.api:PublicApi\n           * @description  is raised after the cache of visible rows is changed.\n           */\n          this.registerEvent( 'core', 'rowsRendered' );\n\n\n          /**\n           * @ngdoc event\n           * @name scrollBegin\n           * @eventOf  ui.grid.core.api:PublicApi\n           * @description  is raised when scroll begins.  Is throttled, so won't be raised too frequently\n           */\n          this.registerEvent( 'core', 'scrollBegin' );\n\n          /**\n           * @ngdoc event\n           * @name scrollEnd\n           * @eventOf  ui.grid.core.api:PublicApi\n           * @description  is raised when scroll has finished.  Is throttled, so won't be raised too frequently\n           */\n          this.registerEvent( 'core', 'scrollEnd' );\n\n          /**\n           * @ngdoc event\n           * @name canvasHeightChanged\n           * @eventOf  ui.grid.core.api:PublicApi\n           * @description  is raised when the canvas height has changed\n           * <br/>\n           * arguments: oldHeight, newHeight\n           */\n          this.registerEvent( 'core', 'canvasHeightChanged');\n        };\n\n        /**\n         * @ngdoc function\n         * @name ui.grid.class:suppressEvents\n         * @methodOf ui.grid.class:GridApi\n         * @description Used to execute a function while disabling the specified event listeners.\n         * Disables the listenerFunctions, executes the callbackFn, and then enables\n         * the listenerFunctions again\n         * @param {object} listenerFuncs listenerFunc or array of listenerFuncs to suppress. These must be the same\n         * functions that were used in the .on.eventName method\n         * @param {object} callBackFn function to execute\n         * @example\n         * <pre>\n         *    var navigate = function (newRowCol, oldRowCol){\n         *       //do something on navigate\n         *    }\n         *\n         *    gridApi.cellNav.on.navigate(scope,navigate);\n         *\n         *\n         *    //call the scrollTo event and suppress our navigate listener\n         *    //scrollTo will still raise the event for other listeners\n         *    gridApi.suppressEvents(navigate, function(){\n         *       gridApi.cellNav.scrollTo(aRow, aCol);\n         *    });\n         *\n         * </pre>\n         */\n        GridApi.prototype.suppressEvents = function (listenerFuncs, callBackFn) {\n          var self = this;\n          var listeners = angular.isArray(listenerFuncs) ? listenerFuncs : [listenerFuncs];\n\n          //find all registered listeners\n          var foundListeners = self.listeners.filter(function(listener) {\n            return listeners.some(function(l) {\n              return listener.handler === l;\n            });\n          });\n\n          //deregister all the listeners\n          foundListeners.forEach(function(l){\n            l.dereg();\n          });\n\n          callBackFn();\n\n          //reregister all the listeners\n          foundListeners.forEach(function(l){\n              l.dereg = registerEventWithAngular(l.eventId, l.handler, self.grid, l._this);\n          });\n\n        };\n\n        /**\n         * @ngdoc function\n         * @name registerEvent\n         * @methodOf ui.grid.class:GridApi\n         * @description Registers a new event for the given feature.  The event will get a\n         * .raise and .on prepended to it\n         * <br>\n         * .raise.eventName() - takes no arguments\n         * <br/>\n         * <br/>\n         * .on.eventName(scope, callBackFn, _this)\n         * <br/>\n         * scope - a scope reference to add a deregister call to the scopes .$on('destroy').  Scope is optional and can be a null value,\n         * but in this case you must deregister it yourself via the returned deregister function\n         * <br/>\n         * callBackFn - The function to call\n         * <br/>\n         * _this - optional this context variable for callbackFn. If omitted, grid.api will be used for the context\n         * <br/>\n         * .on.eventName returns a dereg funtion that will remove the listener.  It's not necessary to use it as the listener\n         * will be removed when the scope is destroyed.\n         * @param {string} featureName name of the feature that raises the event\n         * @param {string} eventName  name of the event\n         */\n        GridApi.prototype.registerEvent = function (featureName, eventName) {\n          var self = this;\n          if (!self[featureName]) {\n            self[featureName] = {};\n          }\n\n          var feature = self[featureName];\n          if (!feature.on) {\n            feature.on = {};\n            feature.raise = {};\n          }\n\n          var eventId = self.grid.id + featureName + eventName;\n\n          // gridUtil.logDebug('Creating raise event method ' + featureName + '.raise.' + eventName);\n          feature.raise[eventName] = function () {\n            $rootScope.$emit.apply($rootScope, [eventId].concat(Array.prototype.slice.call(arguments)));\n          };\n\n          // gridUtil.logDebug('Creating on event method ' + featureName + '.on.' + eventName);\n          feature.on[eventName] = function (scope, handler, _this) {\n            if ( scope !== null && typeof(scope.$on) === 'undefined' ){\n              gridUtil.logError('asked to listen on ' + featureName + '.on.' + eventName + ' but scope wasn\\'t passed in the input parameters.  It is legitimate to pass null, but you\\'ve passed something else, so you probably forgot to provide scope rather than did it deliberately, not registering');\n              return;\n            }\n            var deregAngularOn = registerEventWithAngular(eventId, handler, self.grid, _this);\n\n            //track our listener so we can turn off and on\n            var listener = {handler: handler, dereg: deregAngularOn, eventId: eventId, scope: scope, _this:_this};\n            self.listeners.push(listener);\n\n            var removeListener = function(){\n              listener.dereg();\n              var index = self.listeners.indexOf(listener);\n              self.listeners.splice(index,1);\n            };\n\n            //destroy tracking when scope is destroyed\n            if (scope) {\n              scope.$on('$destroy', function() {\n                removeListener();\n              });\n            }\n\n\n            return removeListener;\n          };\n        };\n\n        function registerEventWithAngular(eventId, handler, grid, _this) {\n          return $rootScope.$on(eventId, function (event) {\n            var args = Array.prototype.slice.call(arguments);\n            args.splice(0, 1); //remove evt argument\n            handler.apply(_this ? _this : grid.api, args);\n          });\n        }\n\n        /**\n         * @ngdoc function\n         * @name registerEventsFromObject\n         * @methodOf ui.grid.class:GridApi\n         * @description Registers features and events from a simple objectMap.\n         * eventObjectMap must be in this format (multiple features allowed)\n         * <pre>\n         * {featureName:\n         *        {\n         *          eventNameOne:function(args){},\n         *          eventNameTwo:function(args){}\n         *        }\n         *  }\n         * </pre>\n         * @param {object} eventObjectMap map of feature/event names\n         */\n        GridApi.prototype.registerEventsFromObject = function (eventObjectMap) {\n          var self = this;\n          var features = [];\n          angular.forEach(eventObjectMap, function (featProp, featPropName) {\n            var feature = {name: featPropName, events: []};\n            angular.forEach(featProp, function (prop, propName) {\n              feature.events.push(propName);\n            });\n            features.push(feature);\n          });\n\n          features.forEach(function (feature) {\n            feature.events.forEach(function (event) {\n              self.registerEvent(feature.name, event);\n            });\n          });\n\n        };\n\n        /**\n         * @ngdoc function\n         * @name registerMethod\n         * @methodOf ui.grid.class:GridApi\n         * @description Registers a new event for the given feature\n         * @param {string} featureName name of the feature\n         * @param {string} methodName  name of the method\n         * @param {object} callBackFn function to execute\n         * @param {object} _this binds callBackFn 'this' to _this.  Defaults to gridApi.grid\n         */\n        GridApi.prototype.registerMethod = function (featureName, methodName, callBackFn, _this) {\n          if (!this[featureName]) {\n            this[featureName] = {};\n          }\n\n          var feature = this[featureName];\n\n          feature[methodName] = gridUtil.createBoundedWrapper(_this || this.grid, callBackFn);\n        };\n\n        /**\n         * @ngdoc function\n         * @name registerMethodsFromObject\n         * @methodOf ui.grid.class:GridApi\n         * @description Registers features and methods from a simple objectMap.\n         * eventObjectMap must be in this format (multiple features allowed)\n         * <br>\n         * {featureName:\n         *        {\n         *          methodNameOne:function(args){},\n         *          methodNameTwo:function(args){}\n         *        }\n         * @param {object} eventObjectMap map of feature/event names\n         * @param {object} _this binds this to _this for all functions.  Defaults to gridApi.grid\n         */\n        GridApi.prototype.registerMethodsFromObject = function (methodMap, _this) {\n          var self = this;\n          var features = [];\n          angular.forEach(methodMap, function (featProp, featPropName) {\n            var feature = {name: featPropName, methods: []};\n            angular.forEach(featProp, function (prop, propName) {\n              feature.methods.push({name: propName, fn: prop});\n            });\n            features.push(feature);\n          });\n\n          features.forEach(function (feature) {\n            feature.methods.forEach(function (method) {\n              self.registerMethod(feature.name, method.name, method.fn, _this);\n            });\n          });\n\n        };\n        \n        return GridApi;\n\n      }]);\n\n})();\n\n(function(){\n\nangular.module('ui.grid')\n.factory('GridColumn', ['gridUtil', 'uiGridConstants', 'i18nService', function(gridUtil, uiGridConstants, i18nService) {\n\n  /**\n   * ******************************************************************************************\n   * PaulL1: Ugly hack here in documentation.  These properties are clearly properties of GridColumn,\n   * and need to be noted as such for those extending and building ui-grid itself.\n   * However, from an end-developer perspective, they interact with all these through columnDefs,\n   * and they really need to be documented there.  I feel like they're relatively static, and\n   * I can't find an elegant way for ngDoc to reference to both....so I've duplicated each\n   * comment block.  Ugh.\n   *\n   */\n\n  /**\n   * @ngdoc property\n   * @name name\n   * @propertyOf ui.grid.class:GridColumn\n   * @description (mandatory) each column should have a name, although for backward\n   * compatibility with 2.x name can be omitted if field is present\n   *\n   */\n\n  /**\n   * @ngdoc property\n   * @name name\n   * @propertyOf ui.grid.class:GridOptions.columnDef\n   * @description (mandatory) each column should have a name, although for backward\n   * compatibility with 2.x name can be omitted if field is present\n   *\n   */\n\n  /**\n   * @ngdoc property\n   * @name displayName\n   * @propertyOf ui.grid.class:GridColumn\n   * @description Column name that will be shown in the header.  If displayName is not\n   * provided then one is generated using the name.\n   *\n   */\n\n  /**\n   * @ngdoc property\n   * @name displayName\n   * @propertyOf ui.grid.class:GridOptions.columnDef\n   * @description Column name that will be shown in the header.  If displayName is not\n   * provided then one is generated using the name.\n   *\n   */\n\n  /**\n   * @ngdoc property\n   * @name field\n   * @propertyOf ui.grid.class:GridColumn\n   * @description field must be provided if you wish to bind to a\n   * property in the data source.  Should be an angular expression that evaluates against grid.options.data\n   * array element.  Can be a complex expression: <code>employee.address.city</code>, or can be a function: <code>employee.getFullAddress()</code>.\n   * See the angular docs on binding expressions.\n   *\n   */\n\n  /**\n   * @ngdoc property\n   * @name field\n   * @propertyOf ui.grid.class:GridOptions.columnDef\n   * @description field must be provided if you wish to bind to a\n   * property in the data source.  Should be an angular expression that evaluates against grid.options.data\n   * array element.  Can be a complex expression: <code>employee.address.city</code>, or can be a function: <code>employee.getFullAddress()</code>.    * See the angular docs on binding expressions.    *\n   */\n\n  /**\n   * @ngdoc property\n   * @name filter\n   * @propertyOf ui.grid.class:GridColumn\n   * @description Filter on this column.\n   * @example\n   * <pre>{ term: 'text', condition: uiGridConstants.filter.STARTS_WITH, placeholder: 'type to filter...', ariaLabel: 'Filter for text, flags: { caseSensitive: false }, type: uiGridConstants.filter.SELECT, [ { value: 1, label: 'male' }, { value: 2, label: 'female' } ] }</pre>\n   *\n   */\n\n  /**\n   * @ngdoc object\n   * @name ui.grid.class:GridColumn\n   * @description Represents the viewModel for each column.  Any state or methods needed for a Grid Column\n   * are defined on this prototype\n   * @param {ColumnDef} colDef the column def to associate with this column\n   * @param {number} uid the unique and immutable uid we'd like to allocate to this column\n   * @param {Grid} grid the grid we'd like to create this column in\n   */\n  function GridColumn(colDef, uid, grid) {\n    var self = this;\n\n    self.grid = grid;\n    self.uid = uid;\n\n    self.updateColumnDef(colDef, true);\n\n    /**\n     * @ngdoc function\n     * @name hideColumn\n     * @methodOf ui.grid.class:GridColumn\n     * @description Hides the column by setting colDef.visible = false\n     */\n    GridColumn.prototype.hideColumn = function() {\n      this.colDef.visible = false;\n    };\n\n    self.aggregationValue = undefined;\n\n    // The footer cell registers to listen for the rowsRendered event, and calls this.  Needed to be\n    // in something with a scope so that the dereg would get called\n    self.updateAggregationValue = function() {\n\n     // gridUtil.logDebug('getAggregationValue for Column ' + self.colDef.name);\n\n      /**\n       * @ngdoc property\n       * @name aggregationType\n       * @propertyOf ui.grid.class:GridOptions.columnDef\n       * @description The aggregation that you'd like to show in the columnFooter for this\n       * column.  Valid values are in uiGridConstants, and currently include `uiGridConstants.aggregationTypes.count`,\n       * `uiGridConstants.aggregationTypes.sum`, `uiGridConstants.aggregationTypes.avg`, `uiGridConstants.aggregationTypes.min`,\n       * `uiGridConstants.aggregationTypes.max`.\n       *\n       * You can also provide a function as the aggregation type, in this case your function needs to accept the full\n       * set of visible rows, and return a value that should be shown\n       */\n      if (!self.aggregationType) {\n        self.aggregationValue = undefined;\n        return;\n      }\n\n      var result = 0;\n      var visibleRows = self.grid.getVisibleRows();\n\n      var cellValues = function(){\n        var values = [];\n        visibleRows.forEach(function (row) {\n          var cellValue = self.grid.getCellValue(row, self);\n          var cellNumber = Number(cellValue);\n          if (!isNaN(cellNumber)) {\n            values.push(cellNumber);\n          }\n        });\n        return values;\n      };\n\n      if (angular.isFunction(self.aggregationType)) {\n        self.aggregationValue = self.aggregationType(visibleRows, self);\n      }\n      else if (self.aggregationType === uiGridConstants.aggregationTypes.count) {\n        self.aggregationValue = self.grid.getVisibleRowCount();\n      }\n      else if (self.aggregationType === uiGridConstants.aggregationTypes.sum) {\n        cellValues().forEach(function (value) {\n          result += value;\n        });\n        self.aggregationValue = result;\n      }\n      else if (self.aggregationType === uiGridConstants.aggregationTypes.avg) {\n        cellValues().forEach(function (value) {\n          result += value;\n        });\n        result = result / cellValues().length;\n        self.aggregationValue = result;\n      }\n      else if (self.aggregationType === uiGridConstants.aggregationTypes.min) {\n        self.aggregationValue = Math.min.apply(null, cellValues());\n      }\n      else if (self.aggregationType === uiGridConstants.aggregationTypes.max) {\n        self.aggregationValue = Math.max.apply(null, cellValues());\n      }\n      else {\n        self.aggregationValue = '\\u00A0';\n      }\n    };\n\n//     var throttledUpdateAggregationValue = gridUtil.throttle(updateAggregationValue, self.grid.options.aggregationCalcThrottle, { trailing: true, context: self.name });\n\n    /**\n     * @ngdoc function\n     * @name getAggregationValue\n     * @methodOf ui.grid.class:GridColumn\n     * @description gets the aggregation value based on the aggregation type for this column.\n     * Debounced using scrollDebounce option setting\n     */\n    this.getAggregationValue =  function() {\n//      if (!self.grid.isScrollingVertically && !self.grid.isScrollingHorizontally) {\n//        throttledUpdateAggregationValue();\n//      }\n\n      return self.aggregationValue;\n    };\n  }\n\n\n  /**\n   * @ngdoc method\n   * @methodOf ui.grid.class:GridColumn\n   * @name setPropertyOrDefault\n   * @description Sets a property on the column using the passed in columnDef, and\n   * setting the defaultValue if the value cannot be found on the colDef\n   * @param {ColumnDef} colDef the column def to look in for the property value\n   * @param {string} propName the property name we'd like to set\n   * @param {object} defaultValue the value to use if the colDef doesn't provide the setting\n   */\n  GridColumn.prototype.setPropertyOrDefault = function (colDef, propName, defaultValue) {\n    var self = this;\n\n    // Use the column definition filter if we were passed it\n    if (typeof(colDef[propName]) !== 'undefined' && colDef[propName]) {\n      self[propName] = colDef[propName];\n    }\n    // Otherwise use our own if it's set\n    else if (typeof(self[propName]) !== 'undefined') {\n      self[propName] = self[propName];\n    }\n    // Default to empty object for the filter\n    else {\n      self[propName] = defaultValue ? defaultValue : {};\n    }\n  };\n\n\n\n  /**\n   * @ngdoc property\n   * @name width\n   * @propertyOf ui.grid.class:GridOptions.columnDef\n   * @description sets the column width.  Can be either\n   * a number or a percentage, or an * for auto.\n   * @example\n   * <pre>  $scope.gridOptions.columnDefs = [ { field: 'field1', width: 100},\n   *                                          { field: 'field2', width: '20%'},\n   *                                          { field: 'field3', width: '*' }]; </pre>\n   *\n   */\n\n  /**\n   * @ngdoc property\n   * @name minWidth\n   * @propertyOf ui.grid.class:GridOptions.columnDef\n   * @description sets the minimum column width.  Should be a number.\n   * @example\n   * <pre>  $scope.gridOptions.columnDefs = [ { field: 'field1', minWidth: 100}]; </pre>\n   *\n   */\n\n  /**\n   * @ngdoc property\n   * @name maxWidth\n   * @propertyOf ui.grid.class:GridOptions.columnDef\n   * @description sets the maximum column width.  Should be a number.\n   * @example\n   * <pre>  $scope.gridOptions.columnDefs = [ { field: 'field1', maxWidth: 100}]; </pre>\n   *\n   */\n\n  /**\n   * @ngdoc property\n   * @name visible\n   * @propertyOf ui.grid.class:GridOptions.columnDef\n   * @description sets whether or not the column is visible\n   * </br>Default is true\n   * @example\n   * <pre>  $scope.gridOptions.columnDefs = [\n   *     { field: 'field1', visible: true},\n   *     { field: 'field2', visible: false }\n   *   ]; </pre>\n   *\n   */\n\n    /**\n  * @ngdoc property\n  * @name sort\n  * @propertyOf ui.grid.class:GridOptions.columnDef\n  * @description An object of sort information, attributes are:\n  *\n  * - direction: values are uiGridConstants.ASC or uiGridConstants.DESC\n  * - ignoreSort: if set to true this sort is ignored (used by tree to manipulate the sort functionality)\n  * - priority: says what order to sort the columns in (lower priority gets sorted first).\n  * @example\n  * <pre>\n  *   $scope.gridOptions.columnDefs = [{\n  *     field: 'field1',\n  *     sort: {\n  *       direction: uiGridConstants.ASC,\n  *       ignoreSort: true,\n  *       priority: 0\n  *      }\n  *   }];\n  * </pre>\n  */\n\n\n  /**\n   * @ngdoc property\n   * @name sortingAlgorithm\n   * @propertyOf ui.grid.class:GridColumn\n   * @description Algorithm to use for sorting this column. Takes 'a' and 'b' parameters\n   * like any normal sorting function.\n   *\n   */\n\n  /**\n   * @ngdoc property\n   * @name sortingAlgorithm\n   * @propertyOf ui.grid.class:GridOptions.columnDef\n   * @description Algorithm to use for sorting this column. Takes 'a' and 'b' parameters\n   * like any normal sorting function.\n   *\n   */\n\n  /**\n   * @ngdoc array\n   * @name filters\n   * @propertyOf ui.grid.class:GridOptions.columnDef\n   * @description Specify multiple filter fields.\n   * @example\n   * <pre>$scope.gridOptions.columnDefs = [\n   *   {\n   *     field: 'field1', filters: [\n   *       {\n   *         term: 'aa',\n   *         condition: uiGridConstants.filter.STARTS_WITH,\n   *         placeholder: 'starts with...',\n   *         ariaLabel: 'Filter for field1',\n   *         flags: { caseSensitive: false },\n   *         type: uiGridConstants.filter.SELECT,\n   *         selectOptions: [ { value: 1, label: 'male' }, { value: 2, label: 'female' } ]\n   *       },\n   *       {\n   *         condition: uiGridConstants.filter.ENDS_WITH,\n   *         placeholder: 'ends with...'\n   *       }\n   *     ]\n   *   }\n   * ]; </pre>\n   *\n   *\n   */\n\n  /**\n   * @ngdoc array\n   * @name filters\n   * @propertyOf ui.grid.class:GridColumn\n   * @description Filters for this column. Includes 'term' property bound to filter input elements.\n   * @example\n   * <pre>[\n   *   {\n   *     term: 'foo', // ngModel for <input>\n   *     condition: uiGridConstants.filter.STARTS_WITH,\n   *     placeholder: 'starts with...',\n   *     ariaLabel: 'Filter for foo',\n   *     flags: { caseSensitive: false },\n   *     type: uiGridConstants.filter.SELECT,\n   *     selectOptions: [ { value: 1, label: 'male' }, { value: 2, label: 'female' } ]\n   *   },\n   *   {\n   *     term: 'baz',\n   *     condition: uiGridConstants.filter.ENDS_WITH,\n   *     placeholder: 'ends with...'\n   *   }\n   * ] </pre>\n   *\n   *\n   */\n\n  /**\n   * @ngdoc array\n   * @name menuItems\n   * @propertyOf ui.grid.class:GridOptions.columnDef\n   * @description used to add menu items to a column.  Refer to the tutorial on this\n   * functionality.  A number of settings are supported:\n   *\n   * - title: controls the title that is displayed in the menu\n   * - icon: the icon shown alongside that title\n   * - action: the method to call when the menu is clicked\n   * - shown: a function to evaluate to determine whether or not to show the item\n   * - active: a function to evaluate to determine whether or not the item is currently selected\n   * - context: context to pass to the action function, available in this.context in your handler\n   * - leaveOpen: if set to true, the menu should stay open after the action, defaults to false\n   * @example\n   * <pre>  $scope.gridOptions.columnDefs = [\n   *   { field: 'field1', menuItems: [\n   *     {\n   *       title: 'Outer Scope Alert',\n   *       icon: 'ui-grid-icon-info-circled',\n   *       action: function($event) {\n   *         this.context.blargh(); // $scope.blargh() would work too, this is just an example\n   *       },\n   *       shown: function() { return true; },\n   *       active: function() { return true; },\n   *       context: $scope\n   *     },\n   *     {\n   *       title: 'Grid ID',\n   *       action: function() {\n   *         alert('Grid ID: ' + this.grid.id);\n   *       }\n   *     }\n   *   ] }]; </pre>\n   *\n   */\n\n  /**\n   * @ngdoc method\n   * @methodOf ui.grid.class:GridColumn\n   * @name updateColumnDef\n   * @description Moves settings from the columnDef down onto the column,\n   * and sets properties as appropriate\n   * @param {ColumnDef} colDef the column def to look in for the property value\n   * @param {boolean} isNew whether the column is being newly created, if not\n   * we're updating an existing column, and some items such as the sort shouldn't\n   * be copied down\n   */\n  GridColumn.prototype.updateColumnDef = function(colDef, isNew) {\n    var self = this;\n\n    self.colDef = colDef;\n\n    if (colDef.name === undefined) {\n      throw new Error('colDef.name is required for column at index ' + self.grid.options.columnDefs.indexOf(colDef));\n    }\n\n    self.displayName = (colDef.displayName === undefined) ? gridUtil.readableColumnName(colDef.name) : colDef.displayName;\n\n    var colDefWidth = colDef.width;\n    var parseErrorMsg = \"Cannot parse column width '\" + colDefWidth + \"' for column named '\" + colDef.name + \"'\";\n\n    if (!angular.isString(colDefWidth) && !angular.isNumber(colDefWidth)) {\n      self.width = '*';\n    } else if (angular.isString(colDefWidth)) {\n      // See if it ends with a percent\n      if (gridUtil.endsWith(colDefWidth, '%')) {\n        // If so we should be able to parse the non-percent-sign part to a number\n        var percentStr = colDefWidth.replace(/%/g, '');\n        var percent = parseInt(percentStr, 10);\n        if (isNaN(percent)) {\n          throw new Error(parseErrorMsg);\n        }\n        self.width = colDefWidth;\n      }\n      // And see if it's a number string\n      else if (colDefWidth.match(/^(\\d+)$/)) {\n        self.width = parseInt(colDefWidth.match(/^(\\d+)$/)[1], 10);\n      }\n      // Otherwise it should be a string of asterisks\n      else if (colDefWidth.match(/^\\*+$/)) {\n        self.width = colDefWidth;\n      }\n      // No idea, throw an Error\n      else {\n        throw new Error(parseErrorMsg);\n      }\n    }\n    // Is a number, use it as the width\n    else {\n      self.width = colDefWidth;\n    }\n\n    self.minWidth = !colDef.minWidth ? 30 : colDef.minWidth;\n    self.maxWidth = !colDef.maxWidth ? 9000 : colDef.maxWidth;\n\n    //use field if it is defined; name if it is not\n    self.field = (colDef.field === undefined) ? colDef.name : colDef.field;\n\n    if ( typeof( self.field ) !== 'string' ){\n      gridUtil.logError( 'Field is not a string, this is likely to break the code, Field is: ' + self.field );\n    }\n\n    self.name = colDef.name;\n\n    // Use colDef.displayName as long as it's not undefined, otherwise default to the field name\n    self.displayName = (colDef.displayName === undefined) ? gridUtil.readableColumnName(colDef.name) : colDef.displayName;\n\n    //self.originalIndex = index;\n\n    self.aggregationType = angular.isDefined(colDef.aggregationType) ? colDef.aggregationType : null;\n    self.footerCellTemplate = angular.isDefined(colDef.footerCellTemplate) ? colDef.footerCellTemplate : null;\n\n    /**\n     * @ngdoc property\n     * @name cellTooltip\n     * @propertyOf ui.grid.class:GridOptions.columnDef\n     * @description Whether or not to show a tooltip when a user hovers over the cell.\n     * If set to false, no tooltip.  If true, the cell value is shown in the tooltip (useful\n     * if you have long values in your cells), if a function then that function is called\n     * passing in the row and the col `cellTooltip( row, col )`, and the return value is shown in the tooltip,\n     * if it is a static string then displays that static string.\n     *\n     * Defaults to false\n     *\n     */\n    if ( typeof(colDef.cellTooltip) === 'undefined' || colDef.cellTooltip === false ) {\n      self.cellTooltip = false;\n    } else if ( colDef.cellTooltip === true ){\n      self.cellTooltip = function(row, col) {\n        return self.grid.getCellValue( row, col );\n      };\n    } else if (typeof(colDef.cellTooltip) === 'function' ){\n      self.cellTooltip = colDef.cellTooltip;\n    } else {\n      self.cellTooltip = function ( row, col ){\n        return col.colDef.cellTooltip;\n      };\n    }\n\n    /**\n     * @ngdoc property\n     * @name headerTooltip\n     * @propertyOf ui.grid.class:GridOptions.columnDef\n     * @description Whether or not to show a tooltip when a user hovers over the header cell.\n     * If set to false, no tooltip.  If true, the displayName is shown in the tooltip (useful\n     * if you have long values in your headers), if a function then that function is called\n     * passing in the row and the col `headerTooltip( col )`, and the return value is shown in the tooltip,\n     * if a static string then shows that static string.\n     *\n     * Defaults to false\n     *\n     */\n    if ( typeof(colDef.headerTooltip) === 'undefined' || colDef.headerTooltip === false ) {\n      self.headerTooltip = false;\n    } else if ( colDef.headerTooltip === true ){\n      self.headerTooltip = function(col) {\n        return col.displayName;\n      };\n    } else if (typeof(colDef.headerTooltip) === 'function' ){\n      self.headerTooltip = colDef.headerTooltip;\n    } else {\n      self.headerTooltip = function ( col ) {\n        return col.colDef.headerTooltip;\n      };\n    }\n\n\n    /**\n     * @ngdoc property\n     * @name footerCellClass\n     * @propertyOf ui.grid.class:GridOptions.columnDef\n     * @description footerCellClass can be a string specifying the class to append to a cell\n     * or it can be a function(row,rowRenderIndex, col, colRenderIndex) that returns a class name\n     *\n     */\n    self.footerCellClass = colDef.footerCellClass;\n\n    /**\n     * @ngdoc property\n     * @name cellClass\n     * @propertyOf ui.grid.class:GridOptions.columnDef\n     * @description cellClass can be a string specifying the class to append to a cell\n     * or it can be a function(row,rowRenderIndex, col, colRenderIndex) that returns a class name\n     *\n     */\n    self.cellClass = colDef.cellClass;\n\n    /**\n     * @ngdoc property\n     * @name headerCellClass\n     * @propertyOf ui.grid.class:GridOptions.columnDef\n     * @description headerCellClass can be a string specifying the class to append to a cell\n     * or it can be a function(row,rowRenderIndex, col, colRenderIndex) that returns a class name\n     *\n     */\n    self.headerCellClass = colDef.headerCellClass;\n\n    /**\n     * @ngdoc property\n     * @name cellFilter\n     * @propertyOf ui.grid.class:GridOptions.columnDef\n     * @description cellFilter is a filter to apply to the content of each cell\n     * @example\n     * <pre>\n     *   gridOptions.columnDefs[0].cellFilter = 'date'\n     *\n     */\n    self.cellFilter = colDef.cellFilter ? colDef.cellFilter : \"\";\n\n    /**\n     * @ngdoc boolean\n     * @name sortCellFiltered\n     * @propertyOf ui.grid.class:GridOptions.columnDef\n     * @description (optional) False by default. When `true` uiGrid will apply the cellFilter before\n     * sorting the data. Note that when using this option uiGrid will assume that the displayed value is\n     * a string, and use the {@link ui.grid.class:RowSorter#sortAlpha sortAlpha} `sortFn`. It is possible\n     * to return a non-string value from an angularjs filter, in which case you should define a {@link ui.grid.class:GridOptions.columnDef#sortingAlgorithm sortingAlgorithm}\n     * for the column which hanldes the returned type. You may specify one of the `sortingAlgorithms`\n     * found in the {@link ui.grid.RowSorter rowSorter} service.\n     */\n    self.sortCellFiltered = colDef.sortCellFiltered ? true : false;\n\n    /**\n     * @ngdoc boolean\n     * @name filterCellFiltered\n     * @propertyOf ui.grid.class:GridOptions.columnDef\n     * @description (optional) False by default. When `true` uiGrid will apply the cellFilter before\n     * applying \"search\" `filters`.\n     */\n    self.filterCellFiltered = colDef.filterCellFiltered ? true : false;\n\n    /**\n     * @ngdoc property\n     * @name headerCellFilter\n     * @propertyOf ui.grid.class:GridOptions.columnDef\n     * @description headerCellFilter is a filter to apply to the content of the column header\n     * @example\n     * <pre>\n     *   gridOptions.columnDefs[0].headerCellFilter = 'translate'\n     *\n     */\n    self.headerCellFilter = colDef.headerCellFilter ? colDef.headerCellFilter : \"\";\n\n    /**\n     * @ngdoc property\n     * @name footerCellFilter\n     * @propertyOf ui.grid.class:GridOptions.columnDef\n     * @description footerCellFilter is a filter to apply to the content of the column footer\n     * @example\n     * <pre>\n     *   gridOptions.columnDefs[0].footerCellFilter = 'date'\n     *\n     */\n    self.footerCellFilter = colDef.footerCellFilter ? colDef.footerCellFilter : \"\";\n\n    self.visible = gridUtil.isNullOrUndefined(colDef.visible) || colDef.visible;\n\n    self.headerClass = colDef.headerClass;\n    //self.cursor = self.sortable ? 'pointer' : 'default';\n\n    // Turn on sorting by default\n    self.enableSorting = typeof(colDef.enableSorting) !== 'undefined' ? colDef.enableSorting : true;\n    self.sortingAlgorithm = colDef.sortingAlgorithm;\n\n    /**\n     * @ngdoc boolean\n     * @name suppressRemoveSort\n     * @propertyOf ui.grid.class:GridOptions.columnDef\n     * @description (optional) False by default. When enabled, this setting hides the removeSort option\n     * in the menu, and prevents users from manually removing the sort\n     */\n    if ( typeof(self.suppressRemoveSort) === 'undefined'){\n      self.suppressRemoveSort = typeof(colDef.suppressRemoveSort) !== 'undefined' ? colDef.suppressRemoveSort : false;\n    }\n\n    /**\n     * @ngdoc property\n     * @name enableFiltering\n     * @propertyOf ui.grid.class:GridOptions.columnDef\n     * @description turn off filtering for an individual column, where\n     * you've turned on filtering for the overall grid\n     * @example\n     * <pre>\n     *   gridOptions.columnDefs[0].enableFiltering = false;\n     *\n     */\n    // Turn on filtering by default (it's disabled by default at the Grid level)\n    self.enableFiltering = typeof(colDef.enableFiltering) !== 'undefined' ? colDef.enableFiltering : true;\n\n    // self.menuItems = colDef.menuItems;\n    self.setPropertyOrDefault(colDef, 'menuItems', []);\n\n    // Use the column definition sort if we were passed it, but only if this is a newly added column\n    if ( isNew ){\n      self.setPropertyOrDefault(colDef, 'sort');\n    }\n\n    // Set up default filters array for when one is not provided.\n    //   In other words, this (in column def):\n    //\n    //       filter: { term: 'something', flags: {}, condition: [CONDITION] }\n    //\n    //   is just shorthand for this:\n    //\n    //       filters: [{ term: 'something', flags: {}, condition: [CONDITION] }]\n    //\n    var defaultFilters = [];\n    if (colDef.filter) {\n      defaultFilters.push(colDef.filter);\n    }\n    else if ( colDef.filters ){\n      defaultFilters = colDef.filters;\n    } else {\n      // Add an empty filter definition object, which will\n      // translate to a guessed condition and no pre-populated\n      // value for the filter <input>.\n      defaultFilters.push({});\n    }\n\n    /**\n     * @ngdoc property\n     * @name filter\n     * @propertyOf ui.grid.class:GridOptions.columnDef\n     * @description Specify a single filter field on this column.\n     *\n     * A filter consists of a condition, a term, and a placeholder:\n     *\n     * - condition defines how rows are chosen as matching the filter term. This can be set to\n     * one of the constants in uiGridConstants.filter, or you can supply a custom filter function\n     * that gets passed the following arguments: [searchTerm, cellValue, row, column].\n     * - term: If set, the filter field will be pre-populated\n     * with this value.\n     * - placeholder: String that will be set to the `<input>.placeholder` attribute.\n     * - ariaLabel: String that will be set to the `<input>.ariaLabel` attribute. This is what is read as a label to screen reader users.\n     * - noTerm: set this to true if you have defined a custom function in condition, and\n     * your custom function doesn't require a term (so it can run even when the term is null)\n     * - flags: only flag currently available is `caseSensitive`, set to false if you don't want\n     * case sensitive matching\n     * - type: defaults to uiGridConstants.filter.INPUT, which gives a text box.  If set to uiGridConstants.filter.SELECT\n     * then a select box will be shown with options selectOptions\n     * - selectOptions: options in the format `[ { value: 1, label: 'male' }]`.  No i18n filter is provided, you need\n     * to perform the i18n on the values before you provide them\n     * - disableCancelFilterButton: defaults to false. If set to true then the 'x' button that cancels/clears the filter\n     * will not be shown.\n     * @example\n     * <pre>$scope.gridOptions.columnDefs = [\n     *   {\n     *     field: 'field1',\n     *     filter: {\n     *       term: 'xx',\n     *       condition: uiGridConstants.filter.STARTS_WITH,\n     *       placeholder: 'starts with...',\n     *       ariaLabel: 'Starts with filter for field1',\n     *       flags: { caseSensitive: false },\n     *       type: uiGridConstants.filter.SELECT,\n     *       selectOptions: [ { value: 1, label: 'male' }, { value: 2, label: 'female' } ],\n     *       disableCancelFilterButton: true\n     *     }\n     *   }\n     * ]; </pre>\n     *\n     */\n\n    /*\n\n\n    /*\n\n      self.filters = [\n        {\n          term: 'search term'\n          condition: uiGridConstants.filter.CONTAINS,\n          placeholder: 'my placeholder',\n          ariaLabel: 'Starts with filter for field1',\n          flags: {\n            caseSensitive: true\n          }\n        }\n      ]\n\n    */\n\n    // Only set filter if this is a newly added column, if we're updating an existing\n    // column then we don't want to put the default filter back if the user may have already\n    // removed it.\n    // However, we do want to keep the settings if they change, just not the term\n    if ( isNew ) {\n      self.setPropertyOrDefault(colDef, 'filter');\n      self.setPropertyOrDefault(colDef, 'filters', defaultFilters);\n    } else if ( self.filters.length === defaultFilters.length ) {\n      self.filters.forEach( function( filter, index ){\n        if (typeof(defaultFilters[index].placeholder) !== 'undefined') {\n          filter.placeholder = defaultFilters[index].placeholder;\n        }\n        if (typeof(defaultFilters[index].ariaLabel) !== 'undefined') {\n          filter.ariaLabel = defaultFilters[index].ariaLabel;\n        }\n        if (typeof(defaultFilters[index].flags) !== 'undefined') {\n          filter.flags = defaultFilters[index].flags;\n        }\n        if (typeof(defaultFilters[index].type) !== 'undefined') {\n          filter.type = defaultFilters[index].type;\n        }\n        if (typeof(defaultFilters[index].selectOptions) !== 'undefined') {\n          filter.selectOptions = defaultFilters[index].selectOptions;\n        }\n      });\n    }\n\n    // Remove this column from the grid sorting, include inside build columns so has\n    // access to self - all seems a bit dodgy but doesn't work otherwise so have left\n    // as is\n    GridColumn.prototype.unsort = function () {\n      this.sort = {};\n      self.grid.api.core.raise.sortChanged( self.grid, self.grid.getColumnSorting() );\n    };\n\n  };\n\n\n  /**\n   * @ngdoc function\n   * @name getColClass\n   * @methodOf ui.grid.class:GridColumn\n   * @description Returns the class name for the column\n   * @param {bool} prefixDot  if true, will return .className instead of className\n   */\n  GridColumn.prototype.getColClass = function (prefixDot) {\n    var cls = uiGridConstants.COL_CLASS_PREFIX + this.uid;\n\n    return prefixDot ? '.' + cls : cls;\n  };\n\n    /**\n     * @ngdoc function\n     * @name isPinnedLeft\n     * @methodOf ui.grid.class:GridColumn\n     * @description Returns true if column is in the left render container\n     */\n    GridColumn.prototype.isPinnedLeft = function () {\n      return this.renderContainer === 'left';\n    };\n\n    /**\n     * @ngdoc function\n     * @name isPinnedRight\n     * @methodOf ui.grid.class:GridColumn\n     * @description Returns true if column is in the right render container\n     */\n    GridColumn.prototype.isPinnedRight = function () {\n      return this.renderContainer === 'right';\n    };\n\n\n    /**\n   * @ngdoc function\n   * @name getColClassDefinition\n   * @methodOf ui.grid.class:GridColumn\n   * @description Returns the class definition for th column\n   */\n  GridColumn.prototype.getColClassDefinition = function () {\n    return ' .grid' + this.grid.id + ' ' + this.getColClass(true) + ' { min-width: ' + this.drawnWidth + 'px; max-width: ' + this.drawnWidth + 'px; }';\n  };\n\n  /**\n   * @ngdoc function\n   * @name getRenderContainer\n   * @methodOf ui.grid.class:GridColumn\n   * @description Returns the render container object that this column belongs to.\n   *\n   * Columns will be default be in the `body` render container if they aren't allocated to one specifically.\n   */\n  GridColumn.prototype.getRenderContainer = function getRenderContainer() {\n    var self = this;\n\n    var containerId = self.renderContainer;\n\n    if (containerId === null || containerId === '' || containerId === undefined) {\n      containerId = 'body';\n    }\n\n    return self.grid.renderContainers[containerId];\n  };\n\n  /**\n   * @ngdoc function\n   * @name showColumn\n   * @methodOf ui.grid.class:GridColumn\n   * @description Makes the column visible by setting colDef.visible = true\n   */\n  GridColumn.prototype.showColumn = function() {\n      this.colDef.visible = true;\n  };\n\n\n  /**\n   * @ngdoc property\n   * @name aggregationHideLabel\n   * @propertyOf ui.grid.class:GridOptions.columnDef\n   * @description defaults to false, if set to true hides the label text\n   * in the aggregation footer, so only the value is displayed.\n   *\n   */\n  /**\n   * @ngdoc function\n   * @name getAggregationText\n   * @methodOf ui.grid.class:GridColumn\n   * @description Gets the aggregation label from colDef.aggregationLabel if\n   * specified or by using i18n, including deciding whether or not to display\n   * based on colDef.aggregationHideLabel.\n   *\n   * @param {string} label the i18n lookup value to use for the column label\n   *\n   */\n  GridColumn.prototype.getAggregationText = function () {\n    var self = this;\n    if ( self.colDef.aggregationHideLabel ){\n      return '';\n    }\n    else if ( self.colDef.aggregationLabel ) {\n      return self.colDef.aggregationLabel;\n    }\n    else {\n      switch ( self.colDef.aggregationType ){\n        case uiGridConstants.aggregationTypes.count:\n          return i18nService.getSafeText('aggregation.count');\n        case uiGridConstants.aggregationTypes.sum:\n          return i18nService.getSafeText('aggregation.sum');\n        case uiGridConstants.aggregationTypes.avg:\n          return i18nService.getSafeText('aggregation.avg');\n        case uiGridConstants.aggregationTypes.min:\n          return i18nService.getSafeText('aggregation.min');\n        case uiGridConstants.aggregationTypes.max:\n          return i18nService.getSafeText('aggregation.max');\n        default:\n          return '';\n      }\n    }\n  };\n\n  GridColumn.prototype.getCellTemplate = function () {\n    var self = this;\n\n    return self.cellTemplatePromise;\n  };\n\n  GridColumn.prototype.getCompiledElementFn = function () {\n    var self = this;\n\n    return self.compiledElementFnDefer.promise;\n  };\n\n  return GridColumn;\n}]);\n\n})();\n\n  (function(){\n\nangular.module('ui.grid')\n.factory('GridOptions', ['gridUtil','uiGridConstants', function(gridUtil,uiGridConstants) {\n\n  /**\n   * @ngdoc function\n   * @name ui.grid.class:GridOptions\n   * @description Default GridOptions class.  GridOptions are defined by the application developer and overlaid\n   * over this object.  Setting gridOptions within your controller is the most common method for an application\n   * developer to configure the behaviour of their ui-grid\n   *\n   * @example To define your gridOptions within your controller:\n   * <pre>$scope.gridOptions = {\n   *   data: $scope.myData,\n   *   columnDefs: [\n   *     { name: 'field1', displayName: 'pretty display name' },\n   *     { name: 'field2', visible: false }\n   *  ]\n   * };</pre>\n   *\n   * You can then use this within your html template, when you define your grid:\n   * <pre>&lt;div ui-grid=\"gridOptions\"&gt;&lt;/div&gt;</pre>\n   *\n   * To provide default options for all of the grids within your application, use an angular\n   * decorator to modify the GridOptions factory.\n   * <pre>\n   * app.config(function($provide){\n   *   $provide.decorator('GridOptions',function($delegate){\n   *     var gridOptions;\n   *     gridOptions = angular.copy($delegate);\n   *     gridOptions.initialize = function(options) {\n   *       var initOptions;\n   *       initOptions = $delegate.initialize(options);\n   *       initOptions.enableColumnMenus = false;\n   *       return initOptions;\n   *     };\n   *     return gridOptions;\n   *   });\n   * });\n   * </pre>\n   */\n  return {\n    initialize: function( baseOptions ){\n      /**\n       * @ngdoc function\n       * @name onRegisterApi\n       * @propertyOf ui.grid.class:GridOptions\n       * @description A callback that returns the gridApi once the grid is instantiated, which is\n       * then used to interact with the grid programatically.\n       *\n       * Note that the gridApi.core.renderingComplete event is identical to this\n       * callback, but has the advantage that it can be called from multiple places\n       * if needed\n       *\n       * @example\n       * <pre>\n       *   $scope.gridOptions.onRegisterApi = function ( gridApi ) {\n       *     $scope.gridApi = gridApi;\n       *     $scope.gridApi.selection.selectAllRows( $scope.gridApi.grid );\n       *   };\n       * </pre>\n       *\n       */\n      baseOptions.onRegisterApi = baseOptions.onRegisterApi || angular.noop();\n\n      /**\n       * @ngdoc object\n       * @name data\n       * @propertyOf ui.grid.class:GridOptions\n       * @description (mandatory) Array of data to be rendered into the grid, providing the data source or data binding for\n       * the grid.\n       *\n       * Most commonly the data is an array of objects, where each object has a number of attributes.\n       * Each attribute automatically becomes a column in your grid.  This array could, for example, be sourced from\n       * an angularJS $resource query request.  The array can also contain complex objects, refer the binding tutorial\n       * for examples of that.\n       *\n       * The most flexible usage is to set your data on $scope:\n       *\n       * `$scope.data = data;`\n       *\n       * And then direct the grid to resolve whatever is in $scope.data:\n       *\n       * `$scope.gridOptions.data = 'data';`\n       *\n       * This is the most flexible approach as it allows you to replace $scope.data whenever you feel like it without\n       * getting pointer issues.\n       *\n       * Alternatively you can directly set the data array:\n       *\n       * `$scope.gridOptions.data = [ ];`\n       * or\n       *\n       * `$http.get('/data/100.json')\n       * .success(function(data) {\n       *   $scope.myData = data;\n       *   $scope.gridOptions.data = $scope.myData;\n       *  });`\n       *\n       * Where you do this, you need to take care in updating the data - you can't just update `$scope.myData` to some other\n       * array, you need to update $scope.gridOptions.data to point to that new array as well.\n       *\n       */\n      baseOptions.data = baseOptions.data || [];\n\n      /**\n       * @ngdoc array\n       * @name columnDefs\n       * @propertyOf  ui.grid.class:GridOptions\n       * @description Array of columnDef objects.  Only required property is name.\n       * The individual options available in columnDefs are documented in the\n       * {@link ui.grid.class:GridOptions.columnDef columnDef} section\n       * </br>_field property can be used in place of name for backwards compatibility with 2.x_\n       *  @example\n       *\n       * <pre>var columnDefs = [{name:'field1'}, {name:'field2'}];</pre>\n       *\n       */\n      baseOptions.columnDefs = baseOptions.columnDefs || [];\n\n      /**\n       * @ngdoc object\n       * @name ui.grid.class:GridOptions.columnDef\n       * @description Definition / configuration of an individual column, which would typically be\n       * one of many column definitions within the gridOptions.columnDefs array\n       * @example\n       * <pre>{name:'field1', field: 'field1', filter: { term: 'xxx' }}</pre>\n       *\n       */\n\n\n      /**\n       * @ngdoc array\n       * @name excludeProperties\n       * @propertyOf  ui.grid.class:GridOptions\n       * @description Array of property names in data to ignore when auto-generating column names.  Provides the\n       * inverse of columnDefs - columnDefs is a list of columns to include, excludeProperties is a list of columns\n       * to exclude.\n       *\n       * If columnDefs is defined, this will be ignored.\n       *\n       * Defaults to ['$$hashKey']\n       */\n\n      baseOptions.excludeProperties = baseOptions.excludeProperties || ['$$hashKey'];\n\n      /**\n       * @ngdoc boolean\n       * @name enableRowHashing\n       * @propertyOf ui.grid.class:GridOptions\n       * @description True by default. When enabled, this setting allows uiGrid to add\n       * `$$hashKey`-type properties (similar to Angular) to elements in the `data` array. This allows\n       * the grid to maintain state while vastly speeding up the process of altering `data` by adding/moving/removing rows.\n       *\n       * Note that this DOES add properties to your data that you may not want, but they are stripped out when using `angular.toJson()`. IF\n       * you do not want this at all you can disable this setting but you will take a performance hit if you are using large numbers of rows\n       * and are altering the data set often.\n       */\n      baseOptions.enableRowHashing = baseOptions.enableRowHashing !== false;\n\n      /**\n       * @ngdoc function\n       * @name rowIdentity\n       * @methodOf ui.grid.class:GridOptions\n       * @description This function is used to get and, if necessary, set the value uniquely identifying this row (i.e. if an identity is not present it will set one).\n       *\n       * By default it returns the `$$hashKey` property if it exists. If it doesn't it uses gridUtil.nextUid() to generate one\n       */\n      baseOptions.rowIdentity = baseOptions.rowIdentity || function rowIdentity(row) {\n        return gridUtil.hashKey(row);\n      };\n\n      /**\n       * @ngdoc function\n       * @name getRowIdentity\n       * @methodOf ui.grid.class:GridOptions\n       * @description This function returns the identity value uniquely identifying this row, if one is not present it does not set it.\n       *\n       * By default it returns the `$$hashKey` property but can be overridden to use any property or set of properties you want.\n       */\n      baseOptions.getRowIdentity = baseOptions.getRowIdentity || function getRowIdentity(row) {\n        return row.$$hashKey;\n      };\n\n      /**\n       * @ngdoc property\n       * @name flatEntityAccess\n       * @propertyOf ui.grid.class:GridOptions\n       * @description Set to true if your columns are all related directly to fields in a flat object structure - i.e.\n       * each of your columns associate directly with a propery one each of the entities in your data array.\n       *\n       * In that situation we can avoid all the logic associated with complex binding to functions or to properties of sub-objects,\n       * which can provide a significant speed improvement with large data sets, with filtering and with sorting.\n       *\n       * By default false\n       */\n      baseOptions.flatEntityAccess = baseOptions.flatEntityAccess === true;\n\n      /**\n       * @ngdoc property\n       * @name showHeader\n       * @propertyOf ui.grid.class:GridOptions\n       * @description True by default. When set to false, this setting will replace the\n       * standard header template with '<div></div>', resulting in no header being shown.\n       */\n      baseOptions.showHeader = typeof(baseOptions.showHeader) !== \"undefined\" ? baseOptions.showHeader : true;\n\n      /* (NOTE): Don't show this in the docs. We only use it internally\n       * @ngdoc property\n       * @name headerRowHeight\n       * @propertyOf ui.grid.class:GridOptions\n       * @description The height of the header in pixels, defaults to 30\n       *\n       */\n      if (!baseOptions.showHeader) {\n        baseOptions.headerRowHeight = 0;\n      }\n      else {\n        baseOptions.headerRowHeight = typeof(baseOptions.headerRowHeight) !== \"undefined\" ? baseOptions.headerRowHeight : 30;\n      }\n\n      /**\n       * @ngdoc property\n       * @name rowHeight\n       * @propertyOf ui.grid.class:GridOptions\n       * @description The height of the row in pixels, defaults to 30\n       *\n       */\n      baseOptions.rowHeight = baseOptions.rowHeight || 30;\n\n      /**\n       * @ngdoc integer\n       * @name minRowsToShow\n       * @propertyOf ui.grid.class:GridOptions\n       * @description Minimum number of rows to show when the grid doesn't have a defined height. Defaults to \"10\".\n       */\n      baseOptions.minRowsToShow = typeof(baseOptions.minRowsToShow) !== \"undefined\" ? baseOptions.minRowsToShow : 10;\n\n      /**\n       * @ngdoc property\n       * @name showGridFooter\n       * @propertyOf ui.grid.class:GridOptions\n       * @description Whether or not to show the footer, defaults to false\n       * The footer display Total Rows and Visible Rows (filtered rows)\n       */\n      baseOptions.showGridFooter = baseOptions.showGridFooter === true;\n\n      /**\n       * @ngdoc property\n       * @name showColumnFooter\n       * @propertyOf ui.grid.class:GridOptions\n       * @description Whether or not to show the column footer, defaults to false\n       * The column footer displays column aggregates\n       */\n      baseOptions.showColumnFooter = baseOptions.showColumnFooter === true;\n\n      /**\n       * @ngdoc property\n       * @name columnFooterHeight\n       * @propertyOf ui.grid.class:GridOptions\n       * @description The height of the footer rows (column footer and grid footer) in pixels\n       *\n       */\n      baseOptions.columnFooterHeight = typeof(baseOptions.columnFooterHeight) !== \"undefined\" ? baseOptions.columnFooterHeight : 30;\n      baseOptions.gridFooterHeight = typeof(baseOptions.gridFooterHeight) !== \"undefined\" ? baseOptions.gridFooterHeight : 30;\n\n      baseOptions.columnWidth = typeof(baseOptions.columnWidth) !== \"undefined\" ? baseOptions.columnWidth : 50;\n\n      /**\n       * @ngdoc property\n       * @name maxVisibleColumnCount\n       * @propertyOf ui.grid.class:GridOptions\n       * @description Defaults to 200\n       *\n       */\n      baseOptions.maxVisibleColumnCount = typeof(baseOptions.maxVisibleColumnCount) !== \"undefined\" ? baseOptions.maxVisibleColumnCount : 200;\n\n      /**\n       * @ngdoc property\n       * @name virtualizationThreshold\n       * @propertyOf ui.grid.class:GridOptions\n       * @description Turn virtualization on when number of data elements goes over this number, defaults to 20\n       */\n      baseOptions.virtualizationThreshold = typeof(baseOptions.virtualizationThreshold) !== \"undefined\" ? baseOptions.virtualizationThreshold : 20;\n\n      /**\n       * @ngdoc property\n       * @name columnVirtualizationThreshold\n       * @propertyOf ui.grid.class:GridOptions\n       * @description Turn virtualization on when number of columns goes over this number, defaults to 10\n       */\n      baseOptions.columnVirtualizationThreshold = typeof(baseOptions.columnVirtualizationThreshold) !== \"undefined\" ? baseOptions.columnVirtualizationThreshold : 10;\n\n      /**\n       * @ngdoc property\n       * @name excessRows\n       * @propertyOf ui.grid.class:GridOptions\n       * @description Extra rows to to render outside of the viewport, which helps with smoothness of scrolling.\n       * Defaults to 4\n       */\n      baseOptions.excessRows = typeof(baseOptions.excessRows) !== \"undefined\" ? baseOptions.excessRows : 4;\n      /**\n       * @ngdoc property\n       * @name scrollThreshold\n       * @propertyOf ui.grid.class:GridOptions\n       * @description Defaults to 4\n       */\n      baseOptions.scrollThreshold = typeof(baseOptions.scrollThreshold) !== \"undefined\" ? baseOptions.scrollThreshold : 4;\n\n      /**\n       * @ngdoc property\n       * @name excessColumns\n       * @propertyOf ui.grid.class:GridOptions\n       * @description Extra columns to to render outside of the viewport, which helps with smoothness of scrolling.\n       * Defaults to 4\n       */\n      baseOptions.excessColumns = typeof(baseOptions.excessColumns) !== \"undefined\" ? baseOptions.excessColumns : 4;\n      /**\n       * @ngdoc property\n       * @name horizontalScrollThreshold\n       * @propertyOf ui.grid.class:GridOptions\n       * @description Defaults to 4\n       */\n      baseOptions.horizontalScrollThreshold = typeof(baseOptions.horizontalScrollThreshold) !== \"undefined\" ? baseOptions.horizontalScrollThreshold : 2;\n\n\n      /**\n       * @ngdoc property\n       * @name aggregationCalcThrottle\n       * @propertyOf ui.grid.class:GridOptions\n       * @description Default time in milliseconds to throttle aggregation calcuations, defaults to 500ms\n       */\n      baseOptions.aggregationCalcThrottle = typeof(baseOptions.aggregationCalcThrottle) !== \"undefined\" ? baseOptions.aggregationCalcThrottle : 500;\n\n      /**\n       * @ngdoc property\n       * @name wheelScrollThrottle\n       * @propertyOf ui.grid.class:GridOptions\n       * @description Default time in milliseconds to throttle scroll events to, defaults to 70ms\n       */\n      baseOptions.wheelScrollThrottle = typeof(baseOptions.wheelScrollThrottle) !== \"undefined\" ? baseOptions.wheelScrollThrottle : 70;\n\n\n      /**\n       * @ngdoc property\n       * @name scrollDebounce\n       * @propertyOf ui.grid.class:GridOptions\n       * @description Default time in milliseconds to debounce scroll events, defaults to 300ms\n       */\n      baseOptions.scrollDebounce = typeof(baseOptions.scrollDebounce) !== \"undefined\" ? baseOptions.scrollDebounce : 300;\n\n      /**\n       * @ngdoc boolean\n       * @name enableSorting\n       * @propertyOf ui.grid.class:GridOptions\n       * @description True by default. When enabled, this setting adds sort\n       * widgets to the column headers, allowing sorting of the data for the entire grid.\n       * Sorting can then be disabled on individual columns using the columnDefs.\n       */\n      baseOptions.enableSorting = baseOptions.enableSorting !== false;\n\n      /**\n       * @ngdoc boolean\n       * @name enableFiltering\n       * @propertyOf ui.grid.class:GridOptions\n       * @description False by default. When enabled, this setting adds filter\n       * boxes to each column header, allowing filtering within the column for the entire grid.\n       * Filtering can then be disabled on individual columns using the columnDefs.\n       */\n      baseOptions.enableFiltering = baseOptions.enableFiltering === true;\n\n      /**\n       * @ngdoc boolean\n       * @name enableColumnMenus\n       * @propertyOf ui.grid.class:GridOptions\n       * @description True by default. When enabled, this setting displays a column\n       * menu within each column.\n       */\n      baseOptions.enableColumnMenus = baseOptions.enableColumnMenus !== false;\n\n      /**\n       * @ngdoc boolean\n       * @name enableVerticalScrollbar\n       * @propertyOf ui.grid.class:GridOptions\n       * @description uiGridConstants.scrollbars.ALWAYS by default. This settings controls the vertical scrollbar for the grid.\n       * Supported values: uiGridConstants.scrollbars.ALWAYS, uiGridConstants.scrollbars.NEVER\n       */\n      baseOptions.enableVerticalScrollbar = typeof(baseOptions.enableVerticalScrollbar) !== \"undefined\" ? baseOptions.enableVerticalScrollbar : uiGridConstants.scrollbars.ALWAYS;\n\n      /**\n       * @ngdoc boolean\n       * @name enableHorizontalScrollbar\n       * @propertyOf ui.grid.class:GridOptions\n       * @description uiGridConstants.scrollbars.ALWAYS by default. This settings controls the horizontal scrollbar for the grid.\n       * Supported values: uiGridConstants.scrollbars.ALWAYS, uiGridConstants.scrollbars.NEVER\n       */\n      baseOptions.enableHorizontalScrollbar = typeof(baseOptions.enableHorizontalScrollbar) !== \"undefined\" ? baseOptions.enableHorizontalScrollbar : uiGridConstants.scrollbars.ALWAYS;\n\n      /**\n       * @ngdoc boolean\n       * @name enableMinHeightCheck\n       * @propertyOf ui.grid.class:GridOptions\n       * @description True by default. When enabled, a newly initialized grid will check to see if it is tall enough to display\n       * at least one row of data.  If the grid is not tall enough, it will resize the DOM element to display minRowsToShow number\n       * of rows.\n       */\n       baseOptions.enableMinHeightCheck = baseOptions.enableMinHeightCheck !== false;\n\n      /**\n       * @ngdoc boolean\n       * @name minimumColumnSize\n       * @propertyOf ui.grid.class:GridOptions\n       * @description Columns can't be smaller than this, defaults to 10 pixels\n       */\n      baseOptions.minimumColumnSize = typeof(baseOptions.minimumColumnSize) !== \"undefined\" ? baseOptions.minimumColumnSize : 10;\n\n      /**\n       * @ngdoc function\n       * @name rowEquality\n       * @methodOf ui.grid.class:GridOptions\n       * @description By default, rows are compared using object equality.  This option can be overridden\n       * to compare on any data item property or function\n       * @param {object} entityA First Data Item to compare\n       * @param {object} entityB Second Data Item to compare\n       */\n      baseOptions.rowEquality = baseOptions.rowEquality || function(entityA, entityB) {\n        return entityA === entityB;\n      };\n\n      /**\n       * @ngdoc string\n       * @name headerTemplate\n       * @propertyOf ui.grid.class:GridOptions\n       * @description Null by default. When provided, this setting uses a custom header\n       * template, rather than the default template. Can be set to either the name of a template file:\n       * <pre>  $scope.gridOptions.headerTemplate = 'header_template.html';</pre>\n       * inline html\n       * <pre>  $scope.gridOptions.headerTemplate = '<div class=\"ui-grid-top-panel\" style=\"text-align: center\">I am a Custom Grid Header</div>'</pre>\n       * or the id of a precompiled template (TBD how to use this).\n       * </br>Refer to the custom header tutorial for more information.\n       * If you want no header at all, you can set to an empty div:\n       * <pre>  $scope.gridOptions.headerTemplate = '<div></div>';</pre>\n       *\n       * If you want to only have a static header, then you can set to static content.  If\n       * you want to tailor the existing column headers, then you should look at the\n       * current 'ui-grid-header.html' template in github as your starting point.\n       *\n       */\n      baseOptions.headerTemplate = baseOptions.headerTemplate || null;\n\n      /**\n       * @ngdoc string\n       * @name footerTemplate\n       * @propertyOf ui.grid.class:GridOptions\n       * @description (optional) ui-grid/ui-grid-footer by default.  This footer shows the per-column\n       * aggregation totals.\n       * When provided, this setting uses a custom footer template. Can be set to either the name of a template file 'footer_template.html', inline html\n       * <pre>'<div class=\"ui-grid-bottom-panel\" style=\"text-align: center\">I am a Custom Grid Footer</div>'</pre>, or the id\n       * of a precompiled template (TBD how to use this).  Refer to the custom footer tutorial for more information.\n       */\n      baseOptions.footerTemplate = baseOptions.footerTemplate || 'ui-grid/ui-grid-footer';\n\n      /**\n       * @ngdoc string\n       * @name gridFooterTemplate\n       * @propertyOf ui.grid.class:GridOptions\n       * @description (optional) ui-grid/ui-grid-grid-footer by default. This template by default shows the\n       * total items at the bottom of the grid, and the selected items if selection is enabled.\n       */\n      baseOptions.gridFooterTemplate = baseOptions.gridFooterTemplate || 'ui-grid/ui-grid-grid-footer';\n\n      /**\n       * @ngdoc string\n       * @name rowTemplate\n       * @propertyOf ui.grid.class:GridOptions\n       * @description 'ui-grid/ui-grid-row' by default. When provided, this setting uses a\n       * custom row template.  Can be set to either the name of a template file:\n       * <pre> $scope.gridOptions.rowTemplate = 'row_template.html';</pre>\n       * inline html\n       * <pre>  $scope.gridOptions.rowTemplate = '<div style=\"background-color: aquamarine\" ng-click=\"grid.appScope.fnOne(row)\" ng-repeat=\"col in colContainer.renderedColumns track by col.colDef.name\" class=\"ui-grid-cell\" ui-grid-cell></div>';</pre>\n       * or the id of a precompiled template (TBD how to use this) can be provided.\n       * </br>Refer to the custom row template tutorial for more information.\n       */\n      baseOptions.rowTemplate = baseOptions.rowTemplate || 'ui-grid/ui-grid-row';\n\n      /**\n       * @ngdoc object\n       * @name appScopeProvider\n       * @propertyOf ui.grid.class:GridOptions\n       * @description by default, the parent scope of the ui-grid element will be assigned to grid.appScope\n       * this property allows you to assign any reference you want to grid.appScope\n       */\n      baseOptions.appScopeProvider = baseOptions.appScopeProvider || null;\n\n      return baseOptions;\n    }\n  };\n\n\n}]);\n\n})();\n\n(function(){\n\nangular.module('ui.grid')\n\n  /**\n   * @ngdoc function\n   * @name ui.grid.class:GridRenderContainer\n   * @description The grid has render containers, allowing the ability to have pinned columns.  If the grid\n   * is right-to-left then there may be a right render container, if left-to-right then there may\n   * be a left render container.  There is always a body render container.\n   * @param {string} name The name of the render container ('body', 'left', or 'right')\n   * @param {Grid} grid the grid the render container is in\n   * @param {object} options the render container options\n   */\n.factory('GridRenderContainer', ['gridUtil', 'uiGridConstants', function(gridUtil, uiGridConstants) {\n  function GridRenderContainer(name, grid, options) {\n    var self = this;\n\n    // if (gridUtil.type(grid) !== 'Grid') {\n    //   throw new Error('Grid argument is not a Grid object');\n    // }\n\n    self.name = name;\n\n    self.grid = grid;\n\n    // self.rowCache = [];\n    // self.columnCache = [];\n\n    self.visibleRowCache = [];\n    self.visibleColumnCache = [];\n\n    self.renderedRows = [];\n    self.renderedColumns = [];\n\n    self.prevScrollTop = 0;\n    self.prevScrolltopPercentage = 0;\n    self.prevRowScrollIndex = 0;\n\n    self.prevScrollLeft = 0;\n    self.prevScrollleftPercentage = 0;\n    self.prevColumnScrollIndex = 0;\n\n    self.columnStyles = \"\";\n\n    self.viewportAdjusters = [];\n\n    /**\n     *  @ngdoc boolean\n     *  @name hasHScrollbar\n     *  @propertyOf  ui.grid.class:GridRenderContainer\n     *  @description flag to signal that container has a horizontal scrollbar\n     */\n    self.hasHScrollbar = false;\n\n    /**\n     *  @ngdoc boolean\n     *  @name hasHScrollbar\n     *  @propertyOf  ui.grid.class:GridRenderContainer\n     *  @description flag to signal that container has a vertical scrollbar\n     */\n    self.hasVScrollbar = false;\n\n    /**\n     *  @ngdoc boolean\n     *  @name canvasHeightShouldUpdate\n     *  @propertyOf  ui.grid.class:GridRenderContainer\n     *  @description flag to signal that container should recalculate the canvas size\n     */\n    self.canvasHeightShouldUpdate = true;\n\n    /**\n     *  @ngdoc boolean\n     *  @name canvasHeight\n     *  @propertyOf  ui.grid.class:GridRenderContainer\n     *  @description last calculated canvas height value\n     */\n    self.$$canvasHeight = 0;\n\n    if (options && angular.isObject(options)) {\n      angular.extend(self, options);\n    }\n\n    grid.registerStyleComputation({\n      priority: 5,\n      func: function () {\n        self.updateColumnWidths();\n        return self.columnStyles;\n      }\n    });\n  }\n\n\n  GridRenderContainer.prototype.reset = function reset() {\n    // this.rowCache.length = 0;\n    // this.columnCache.length = 0;\n\n    this.visibleColumnCache.length = 0;\n    this.visibleRowCache.length = 0;\n\n    this.renderedRows.length = 0;\n    this.renderedColumns.length = 0;\n  };\n\n  // TODO(c0bra): calculate size?? Should this be in a stackable directive?\n\n\n  GridRenderContainer.prototype.containsColumn = function (col) {\n     return this.visibleColumnCache.indexOf(col) !== -1;\n  };\n\n  GridRenderContainer.prototype.minRowsToRender = function minRowsToRender() {\n    var self = this;\n    var minRows = 0;\n    var rowAddedHeight = 0;\n    var viewPortHeight = self.getViewportHeight();\n    for (var i = self.visibleRowCache.length - 1; rowAddedHeight < viewPortHeight && i >= 0; i--) {\n      rowAddedHeight += self.visibleRowCache[i].height;\n      minRows++;\n    }\n    return minRows;\n  };\n\n  GridRenderContainer.prototype.minColumnsToRender = function minColumnsToRender() {\n    var self = this;\n    var viewportWidth = this.getViewportWidth();\n\n    var min = 0;\n    var totalWidth = 0;\n    // self.columns.forEach(function(col, i) {\n    for (var i = 0; i < self.visibleColumnCache.length; i++) {\n      var col = self.visibleColumnCache[i];\n\n      if (totalWidth < viewportWidth) {\n        totalWidth += col.drawnWidth ? col.drawnWidth : 0;\n        min++;\n      }\n      else {\n        var currWidth = 0;\n        for (var j = i; j >= i - min; j--) {\n          currWidth += self.visibleColumnCache[j].drawnWidth ? self.visibleColumnCache[j].drawnWidth : 0;\n        }\n        if (currWidth < viewportWidth) {\n          min++;\n        }\n      }\n    }\n\n    return min;\n  };\n\n  GridRenderContainer.prototype.getVisibleRowCount = function getVisibleRowCount() {\n    return this.visibleRowCache.length;\n  };\n\n  /**\n   * @ngdoc function\n   * @name registerViewportAdjuster\n   * @methodOf ui.grid.class:GridRenderContainer\n   * @description Registers an adjuster to the render container's available width or height.  Adjusters are used\n   * to tell the render container that there is something else consuming space, and to adjust it's size\n   * appropriately.\n   * @param {function} func the adjuster function we want to register\n   */\n\n  GridRenderContainer.prototype.registerViewportAdjuster = function registerViewportAdjuster(func) {\n    this.viewportAdjusters.push(func);\n  };\n\n  /**\n   * @ngdoc function\n   * @name removeViewportAdjuster\n   * @methodOf ui.grid.class:GridRenderContainer\n   * @description Removes an adjuster, should be used when your element is destroyed\n   * @param {function} func the adjuster function we want to remove\n   */\n  GridRenderContainer.prototype.removeViewportAdjuster = function removeViewportAdjuster(func) {\n    var idx = this.viewportAdjusters.indexOf(func);\n\n    if (idx > -1) {\n      this.viewportAdjusters.splice(idx, 1);\n    }\n  };\n\n  /**\n   * @ngdoc function\n   * @name getViewportAdjustment\n   * @methodOf ui.grid.class:GridRenderContainer\n   * @description Gets the adjustment based on the viewportAdjusters.\n   * @returns {object} a hash of { height: x, width: y }.  Usually the values will be negative\n   */\n  GridRenderContainer.prototype.getViewportAdjustment = function getViewportAdjustment() {\n    var self = this;\n\n    var adjustment = { height: 0, width: 0 };\n\n    self.viewportAdjusters.forEach(function (func) {\n      adjustment = func.call(this, adjustment);\n    });\n\n    return adjustment;\n  };\n\n  GridRenderContainer.prototype.getMargin = function getMargin(side) {\n    var self = this;\n\n    var amount = 0;\n\n    self.viewportAdjusters.forEach(function (func) {\n      var adjustment = func.call(this, { height: 0, width: 0 });\n\n      if (adjustment.side && adjustment.side === side) {\n        amount += adjustment.width * -1;\n      }\n    });\n\n    return amount;\n  };\n\n  GridRenderContainer.prototype.getViewportHeight = function getViewportHeight() {\n    var self = this;\n\n    var headerHeight = (self.headerHeight) ? self.headerHeight : self.grid.headerHeight;\n\n    var viewPortHeight = self.grid.gridHeight - headerHeight - self.grid.footerHeight;\n\n\n    var adjustment = self.getViewportAdjustment();\n\n    viewPortHeight = viewPortHeight + adjustment.height;\n\n    return viewPortHeight;\n  };\n\n  GridRenderContainer.prototype.getViewportWidth = function getViewportWidth() {\n    var self = this;\n\n    var viewportWidth = self.grid.gridWidth;\n\n    //if (typeof(self.grid.verticalScrollbarWidth) !== 'undefined' && self.grid.verticalScrollbarWidth !== undefined && self.grid.verticalScrollbarWidth > 0) {\n    //  viewPortWidth = viewPortWidth - self.grid.verticalScrollbarWidth;\n    //}\n\n    // var viewportWidth = 0;\\\n    // self.visibleColumnCache.forEach(function (column) {\n    //   viewportWidth += column.drawnWidth;\n    // });\n\n    var adjustment = self.getViewportAdjustment();\n\n    viewportWidth = viewportWidth + adjustment.width;\n\n    return viewportWidth;\n  };\n\n  GridRenderContainer.prototype.getHeaderViewportWidth = function getHeaderViewportWidth() {\n    var self = this;\n\n    var viewportWidth = this.getViewportWidth();\n\n    //if (typeof(self.grid.verticalScrollbarWidth) !== 'undefined' && self.grid.verticalScrollbarWidth !== undefined && self.grid.verticalScrollbarWidth > 0) {\n    //  viewPortWidth = viewPortWidth + self.grid.verticalScrollbarWidth;\n    //}\n\n    // var adjustment = self.getViewportAdjustment();\n    // viewPortWidth = viewPortWidth + adjustment.width;\n\n    return viewportWidth;\n  };\n\n\n  /**\n   * @ngdoc function\n   * @name getCanvasHeight\n   * @methodOf ui.grid.class:GridRenderContainer\n   * @description Returns the total canvas height.   Only recalculates if canvasHeightShouldUpdate = false\n   * @returns {number} total height of all the visible rows in the container\n   */\n  GridRenderContainer.prototype.getCanvasHeight = function getCanvasHeight() {\n    var self = this;\n\n    if (!self.canvasHeightShouldUpdate) {\n      return self.$$canvasHeight;\n    }\n\n    var oldCanvasHeight = self.$$canvasHeight;\n\n    self.$$canvasHeight =  0;\n\n    self.visibleRowCache.forEach(function(row){\n      self.$$canvasHeight += row.height;\n    });\n\n\n    self.canvasHeightShouldUpdate = false;\n\n    self.grid.api.core.raise.canvasHeightChanged(oldCanvasHeight, self.$$canvasHeight);\n\n    return self.$$canvasHeight;\n  };\n\n  GridRenderContainer.prototype.getVerticalScrollLength = function getVerticalScrollLength() {\n    return this.getCanvasHeight() - this.getViewportHeight() + this.grid.scrollbarHeight;\n  };\n\n  GridRenderContainer.prototype.getCanvasWidth = function getCanvasWidth() {\n    var self = this;\n\n    var ret = self.canvasWidth;\n\n    return ret;\n  };\n\n  GridRenderContainer.prototype.setRenderedRows = function setRenderedRows(newRows) {\n    this.renderedRows.length = newRows.length;\n    for (var i = 0; i < newRows.length; i++) {\n      this.renderedRows[i] = newRows[i];\n    }\n  };\n\n  GridRenderContainer.prototype.setRenderedColumns = function setRenderedColumns(newColumns) {\n    var self = this;\n\n    // OLD:\n    this.renderedColumns.length = newColumns.length;\n    for (var i = 0; i < newColumns.length; i++) {\n      this.renderedColumns[i] = newColumns[i];\n    }\n\n    this.updateColumnOffset();\n  };\n\n  GridRenderContainer.prototype.updateColumnOffset = function updateColumnOffset() {\n    // Calculate the width of the columns on the left side that are no longer rendered.\n    //  That will be the offset for the columns as we scroll horizontally.\n    var hiddenColumnsWidth = 0;\n    for (var i = 0; i < this.currentFirstColumn; i++) {\n      hiddenColumnsWidth += this.visibleColumnCache[i].drawnWidth;\n    }\n\n    this.columnOffset = hiddenColumnsWidth;\n  };\n\n  GridRenderContainer.prototype.scrollVertical = function (newScrollTop) {\n    var vertScrollPercentage = -1;\n\n    if (newScrollTop !== this.prevScrollTop) {\n      var yDiff = newScrollTop - this.prevScrollTop;\n\n      if (yDiff > 0 ) { this.grid.scrollDirection = uiGridConstants.scrollDirection.DOWN; }\n      if (yDiff < 0 ) { this.grid.scrollDirection = uiGridConstants.scrollDirection.UP; }\n\n      var vertScrollLength = this.getVerticalScrollLength();\n\n      vertScrollPercentage = newScrollTop / vertScrollLength;\n\n      // console.log('vert', vertScrollPercentage, newScrollTop, vertScrollLength);\n\n      if (vertScrollPercentage > 1) { vertScrollPercentage = 1; }\n      if (vertScrollPercentage < 0) { vertScrollPercentage = 0; }\n\n      this.adjustScrollVertical(newScrollTop, vertScrollPercentage);\n      return vertScrollPercentage;\n    }\n  };\n\n  GridRenderContainer.prototype.scrollHorizontal = function(newScrollLeft){\n    var horizScrollPercentage = -1;\n\n    // Handle RTL here\n\n    if (newScrollLeft !== this.prevScrollLeft) {\n      var xDiff = newScrollLeft - this.prevScrollLeft;\n\n      if (xDiff > 0) { this.grid.scrollDirection = uiGridConstants.scrollDirection.RIGHT; }\n      if (xDiff < 0) { this.grid.scrollDirection = uiGridConstants.scrollDirection.LEFT; }\n\n      var horizScrollLength = (this.canvasWidth - this.getViewportWidth());\n      if (horizScrollLength !== 0) {\n        horizScrollPercentage = newScrollLeft / horizScrollLength;\n      }\n      else {\n        horizScrollPercentage = 0;\n      }\n\n      this.adjustScrollHorizontal(newScrollLeft, horizScrollPercentage);\n      return horizScrollPercentage;\n    }\n  };\n\n  GridRenderContainer.prototype.adjustScrollVertical = function adjustScrollVertical(scrollTop, scrollPercentage, force) {\n    if (this.prevScrollTop === scrollTop && !force) {\n      return;\n    }\n\n    if (typeof(scrollTop) === 'undefined' || scrollTop === undefined || scrollTop === null) {\n      scrollTop = (this.getCanvasHeight() - this.getViewportHeight()) * scrollPercentage;\n    }\n\n    this.adjustRows(scrollTop, scrollPercentage, false);\n\n    this.prevScrollTop = scrollTop;\n    this.prevScrolltopPercentage = scrollPercentage;\n\n    this.grid.queueRefresh();\n  };\n\n  GridRenderContainer.prototype.adjustScrollHorizontal = function adjustScrollHorizontal(scrollLeft, scrollPercentage, force) {\n    if (this.prevScrollLeft === scrollLeft && !force) {\n      return;\n    }\n\n    if (typeof(scrollLeft) === 'undefined' || scrollLeft === undefined || scrollLeft === null) {\n      scrollLeft = (this.getCanvasWidth() - this.getViewportWidth()) * scrollPercentage;\n    }\n\n    this.adjustColumns(scrollLeft, scrollPercentage);\n\n    this.prevScrollLeft = scrollLeft;\n    this.prevScrollleftPercentage = scrollPercentage;\n\n    this.grid.queueRefresh();\n  };\n\n  GridRenderContainer.prototype.adjustRows = function adjustRows(scrollTop, scrollPercentage, postDataLoaded) {\n    var self = this;\n\n    var minRows = self.minRowsToRender();\n\n    var rowCache = self.visibleRowCache;\n\n    var maxRowIndex = rowCache.length - minRows;\n\n    // console.log('scroll%1', scrollPercentage);\n\n    // Calculate the scroll percentage according to the scrollTop location, if no percentage was provided\n    if ((typeof(scrollPercentage) === 'undefined' || scrollPercentage === null) && scrollTop) {\n      scrollPercentage = scrollTop / self.getVerticalScrollLength();\n    }\n\n    var rowIndex = Math.ceil(Math.min(maxRowIndex, maxRowIndex * scrollPercentage));\n\n    // console.log('maxRowIndex / scroll%', maxRowIndex, scrollPercentage, rowIndex);\n\n    // Define a max row index that we can't scroll past\n    if (rowIndex > maxRowIndex) {\n      rowIndex = maxRowIndex;\n    }\n\n    var newRange = [];\n    if (rowCache.length > self.grid.options.virtualizationThreshold) {\n      if (!(typeof(scrollTop) === 'undefined' || scrollTop === null)) {\n        // Have we hit the threshold going down?\n        if ( !self.grid.suppressParentScrollDown && self.prevScrollTop < scrollTop && rowIndex < self.prevRowScrollIndex + self.grid.options.scrollThreshold && rowIndex < maxRowIndex) {\n          return;\n        }\n        //Have we hit the threshold going up?\n        if ( !self.grid.suppressParentScrollUp && self.prevScrollTop > scrollTop && rowIndex > self.prevRowScrollIndex - self.grid.options.scrollThreshold && rowIndex < maxRowIndex) {\n          return;\n        }\n      }\n      var rangeStart = {};\n      var rangeEnd = {};\n\n      rangeStart = Math.max(0, rowIndex - self.grid.options.excessRows);\n      rangeEnd = Math.min(rowCache.length, rowIndex + minRows + self.grid.options.excessRows);\n\n      newRange = [rangeStart, rangeEnd];\n    }\n    else {\n      var maxLen = self.visibleRowCache.length;\n      newRange = [0, Math.max(maxLen, minRows + self.grid.options.excessRows)];\n    }\n\n    self.updateViewableRowRange(newRange);\n\n    self.prevRowScrollIndex = rowIndex;\n  };\n\n  GridRenderContainer.prototype.adjustColumns = function adjustColumns(scrollLeft, scrollPercentage) {\n    var self = this;\n\n    var minCols = self.minColumnsToRender();\n\n    var columnCache = self.visibleColumnCache;\n    var maxColumnIndex = columnCache.length - minCols;\n\n    // Calculate the scroll percentage according to the scrollLeft location, if no percentage was provided\n    if ((typeof(scrollPercentage) === 'undefined' || scrollPercentage === null) && scrollLeft) {\n      var horizScrollLength = (self.getCanvasWidth() - self.getViewportWidth());\n      scrollPercentage = scrollLeft / horizScrollLength;\n    }\n\n    var colIndex = Math.ceil(Math.min(maxColumnIndex, maxColumnIndex * scrollPercentage));\n\n    // Define a max row index that we can't scroll past\n    if (colIndex > maxColumnIndex) {\n      colIndex = maxColumnIndex;\n    }\n\n    var newRange = [];\n    if (columnCache.length > self.grid.options.columnVirtualizationThreshold && self.getCanvasWidth() > self.getViewportWidth()) {\n      /* Commented the following lines because otherwise the moved column wasn't visible immediately on the new position\n       * in the case of many columns with horizontal scroll, one had to scroll left or right and then return in order to see it\n      // Have we hit the threshold going down?\n      if (self.prevScrollLeft < scrollLeft && colIndex < self.prevColumnScrollIndex + self.grid.options.horizontalScrollThreshold && colIndex < maxColumnIndex) {\n        return;\n      }\n      //Have we hit the threshold going up?\n      if (self.prevScrollLeft > scrollLeft && colIndex > self.prevColumnScrollIndex - self.grid.options.horizontalScrollThreshold && colIndex < maxColumnIndex) {\n        return;\n      }*/\n\n      var rangeStart = Math.max(0, colIndex - self.grid.options.excessColumns);\n      var rangeEnd = Math.min(columnCache.length, colIndex + minCols + self.grid.options.excessColumns);\n\n      newRange = [rangeStart, rangeEnd];\n    }\n    else {\n      var maxLen = self.visibleColumnCache.length;\n\n      newRange = [0, Math.max(maxLen, minCols + self.grid.options.excessColumns)];\n    }\n\n    self.updateViewableColumnRange(newRange);\n\n    self.prevColumnScrollIndex = colIndex;\n  };\n\n  // Method for updating the visible rows\n  GridRenderContainer.prototype.updateViewableRowRange = function updateViewableRowRange(renderedRange) {\n    // Slice out the range of rows from the data\n    // var rowArr = uiGridCtrl.grid.rows.slice(renderedRange[0], renderedRange[1]);\n    var rowArr = this.visibleRowCache.slice(renderedRange[0], renderedRange[1]);\n\n    // Define the top-most rendered row\n    this.currentTopRow = renderedRange[0];\n\n    this.setRenderedRows(rowArr);\n  };\n\n  // Method for updating the visible columns\n  GridRenderContainer.prototype.updateViewableColumnRange = function updateViewableColumnRange(renderedRange) {\n    // Slice out the range of rows from the data\n    // var columnArr = uiGridCtrl.grid.columns.slice(renderedRange[0], renderedRange[1]);\n    var columnArr = this.visibleColumnCache.slice(renderedRange[0], renderedRange[1]);\n\n    // Define the left-most rendered columns\n    this.currentFirstColumn = renderedRange[0];\n\n    this.setRenderedColumns(columnArr);\n  };\n\n  GridRenderContainer.prototype.headerCellWrapperStyle = function () {\n    var self = this;\n\n    if (self.currentFirstColumn !== 0) {\n      var offset = self.columnOffset;\n\n      if (self.grid.isRTL()) {\n        return { 'margin-right': offset + 'px' };\n      }\n      else {\n        return { 'margin-left': offset + 'px' };\n      }\n    }\n\n    return null;\n  };\n\n    /**\n     *  @ngdoc boolean\n     *  @name updateColumnWidths\n     *  @propertyOf  ui.grid.class:GridRenderContainer\n     *  @description Determine the appropriate column width of each column across all render containers.\n     *\n     *  Column width is easy when each column has a specified width.  When columns are variable width (i.e.\n     *  have an * or % of the viewport) then we try to calculate so that things fit in.  The problem is that\n     *  we have multiple render containers, and we don't want one render container to just take the whole viewport\n     *  when it doesn't need to - we want things to balance out across the render containers.\n     *\n     *  To do this, we use this method to calculate all the renderContainers, recognising that in a given render\n     *  cycle it'll get called once per render container, so it needs to return the same values each time.\n     *\n     *  The constraints on this method are therefore:\n     *  - must return the same value when called multiple times, to do this it needs to rely on properties of the\n     *    columns, but not properties that change when this is called (so it shouldn't rely on drawnWidth)\n     *\n     *  The general logic of this method is:\n     *  - calculate our total available width\n     *  - look at all the columns across all render containers, and work out which have widths and which have\n     *    constraints such as % or * or something else\n     *  - for those with *, count the total number of * we see and add it onto a running total, add this column to an * array\n     *  - for those with a %, allocate the % as a percentage of the viewport, having consideration of min and max\n     *  - for those with manual width (in pixels) we set the drawnWidth to the specified width\n     *  - we end up with an asterisks array still to process\n     *  - we look at our remaining width.  If it's greater than zero, we divide it up among the asterisk columns, then process\n     *    them for min and max width constraints\n     *  - if it's zero or less, we set the asterisk columns to their minimum widths\n     *  - we use parseInt quite a bit, as we try to make all our column widths integers\n     */\n  GridRenderContainer.prototype.updateColumnWidths = function () {\n    var self = this;\n\n    var asterisksArray = [],\n        asteriskNum = 0,\n        usedWidthSum = 0,\n        ret = '';\n\n    // Get the width of the viewport\n    var availableWidth = self.grid.getViewportWidth() - self.grid.scrollbarWidth;\n\n    // get all the columns across all render containers, we have to calculate them all or one render container\n    // could consume the whole viewport\n    var columnCache = [];\n    angular.forEach(self.grid.renderContainers, function( container, name){\n      columnCache = columnCache.concat(container.visibleColumnCache);\n    });\n\n    // look at each column, process any manual values or %, put the * into an array to look at later\n    columnCache.forEach(function(column, i) {\n      var width = 0;\n      // Skip hidden columns\n      if (!column.visible) { return; }\n\n      if (angular.isNumber(column.width)) {\n        // pixel width, set to this value\n        width = parseInt(column.width, 10);\n        usedWidthSum = usedWidthSum + width;\n        column.drawnWidth = width;\n\n      } else if (gridUtil.endsWith(column.width, \"%\")) {\n        // percentage width, set to percentage of the viewport\n        width = parseInt(parseInt(column.width.replace(/%/g, ''), 10) / 100 * availableWidth);\n\n        if ( width > column.maxWidth ){\n          width = column.maxWidth;\n        }\n\n        if ( width < column.minWidth ){\n          width = column.minWidth;\n        }\n\n        usedWidthSum = usedWidthSum + width;\n        column.drawnWidth = width;\n      } else if (angular.isString(column.width) && column.width.indexOf('*') !== -1) {\n        // is an asterisk column, the gridColumn already checked the string consists only of '****'\n        asteriskNum = asteriskNum + column.width.length;\n        asterisksArray.push(column);\n      }\n    });\n\n    // Get the remaining width (available width subtracted by the used widths sum)\n    var remainingWidth = availableWidth - usedWidthSum;\n\n    var i, column, colWidth;\n\n    if (asterisksArray.length > 0) {\n      // the width that each asterisk value would be assigned (this can be negative)\n      var asteriskVal = remainingWidth / asteriskNum;\n\n      asterisksArray.forEach(function( column ){\n        var width = parseInt(column.width.length * asteriskVal, 10);\n\n        if ( width > column.maxWidth ){\n          width = column.maxWidth;\n        }\n\n        if ( width < column.minWidth ){\n          width = column.minWidth;\n        }\n\n        usedWidthSum = usedWidthSum + width;\n        column.drawnWidth = width;\n      });\n    }\n\n    // If the grid width didn't divide evenly into the column widths and we have pixels left over, or our\n    // calculated widths would have the grid narrower than the available space,\n    // dole the remainder out one by one to make everything fit\n    var processColumnUpwards = function(column){\n      if ( column.drawnWidth < column.maxWidth && leftoverWidth > 0) {\n        column.drawnWidth++;\n        usedWidthSum++;\n        leftoverWidth--;\n        columnsToChange = true;\n      }\n    };\n\n    var leftoverWidth = availableWidth - usedWidthSum;\n    var columnsToChange = true;\n\n    while (leftoverWidth > 0 && columnsToChange) {\n      columnsToChange = false;\n      asterisksArray.forEach(processColumnUpwards);\n    }\n\n    // We can end up with too much width even though some columns aren't at their max width, in this situation\n    // we can trim the columns a little\n    var processColumnDownwards = function(column){\n      if ( column.drawnWidth > column.minWidth && excessWidth > 0) {\n        column.drawnWidth--;\n        usedWidthSum--;\n        excessWidth--;\n        columnsToChange = true;\n      }\n    };\n\n    var excessWidth =  usedWidthSum - availableWidth;\n    columnsToChange = true;\n\n    while (excessWidth > 0 && columnsToChange) {\n      columnsToChange = false;\n      asterisksArray.forEach(processColumnDownwards);\n    }\n\n\n    // all that was across all the renderContainers, now we need to work out what that calculation decided for\n    // our renderContainer\n    var canvasWidth = 0;\n    self.visibleColumnCache.forEach(function(column){\n      if ( column.visible ){\n        canvasWidth = canvasWidth + column.drawnWidth;\n      }\n    });\n\n    // Build the CSS\n    columnCache.forEach(function (column) {\n      ret = ret + column.getColClassDefinition();\n    });\n\n    self.canvasWidth = canvasWidth;\n\n    // Return the styles back to buildStyles which pops them into the `customStyles` scope variable\n    // return ret;\n\n    // Set this render container's column styles so they can be used in style computation\n    this.columnStyles = ret;\n  };\n\n  GridRenderContainer.prototype.needsHScrollbarPlaceholder = function () {\n    return this.grid.options.enableHorizontalScrollbar && !this.hasHScrollbar;\n  };\n\n  GridRenderContainer.prototype.getViewportStyle = function () {\n    var self = this;\n    var styles = {};\n\n    self.hasHScrollbar = false;\n    self.hasVScrollbar = false;\n\n    if (self.grid.disableScrolling) {\n      styles['overflow-x'] = 'hidden';\n      styles['overflow-y'] = 'hidden';\n      return styles;\n    }\n\n    if (self.name === 'body') {\n      self.hasHScrollbar = self.grid.options.enableHorizontalScrollbar !== uiGridConstants.scrollbars.NEVER;\n      if (!self.grid.isRTL()) {\n        if (!self.grid.hasRightContainerColumns()) {\n          self.hasVScrollbar = self.grid.options.enableVerticalScrollbar !== uiGridConstants.scrollbars.NEVER;\n        }\n      }\n      else {\n        if (!self.grid.hasLeftContainerColumns()) {\n          self.hasVScrollbar = self.grid.options.enableVerticalScrollbar !== uiGridConstants.scrollbars.NEVER;\n        }\n      }\n    }\n    else if (self.name === 'left') {\n      self.hasVScrollbar = self.grid.isRTL() ? self.grid.options.enableVerticalScrollbar !== uiGridConstants.scrollbars.NEVER : false;\n    }\n    else {\n      self.hasVScrollbar = !self.grid.isRTL() ? self.grid.options.enableVerticalScrollbar !== uiGridConstants.scrollbars.NEVER : false;\n    }\n\n    styles['overflow-x'] = self.hasHScrollbar ? 'scroll' : 'hidden';\n    styles['overflow-y'] = self.hasVScrollbar ? 'scroll' : 'hidden';\n\n\n    return styles;\n\n\n  };\n\n  return GridRenderContainer;\n}]);\n\n})();\n\n(function(){\n\nangular.module('ui.grid')\n.factory('GridRow', ['gridUtil', function(gridUtil) {\n\n   /**\n   * @ngdoc function\n   * @name ui.grid.class:GridRow\n   * @description GridRow is the viewModel for one logical row on the grid.  A grid Row is not necessarily a one-to-one\n   * relation to gridOptions.data.\n   * @param {object} entity the array item from GridOptions.data\n   * @param {number} index the current position of the row in the array\n   * @param {Grid} reference to the parent grid\n   */\n  function GridRow(entity, index, grid) {\n\n     /**\n      *  @ngdoc object\n      *  @name grid\n      *  @propertyOf  ui.grid.class:GridRow\n      *  @description A reference back to the grid\n      */\n     this.grid = grid;\n\n     /**\n      *  @ngdoc object\n      *  @name entity\n      *  @propertyOf  ui.grid.class:GridRow\n      *  @description A reference to an item in gridOptions.data[]\n      */\n    this.entity = entity;\n\n     /**\n      *  @ngdoc object\n      *  @name uid\n      *  @propertyOf  ui.grid.class:GridRow\n      *  @description  UniqueId of row\n      */\n     this.uid = gridUtil.nextUid();\n\n     /**\n      *  @ngdoc object\n      *  @name visible\n      *  @propertyOf  ui.grid.class:GridRow\n      *  @description If true, the row will be rendered\n      */\n    // Default to true\n    this.visible = true;\n\n\n    this.$$height = grid.options.rowHeight;\n\n  }\n\n    /**\n     *  @ngdoc object\n     *  @name height\n     *  @propertyOf  ui.grid.class:GridRow\n     *  @description height of each individual row. changing the height will flag all\n     *  row renderContainers to recalculate their canvas height\n     */\n    Object.defineProperty(GridRow.prototype, 'height', {\n      get: function() {\n        return this.$$height;\n      },\n      set: function(height) {\n        if (height !== this.$$height) {\n          this.grid.updateCanvasHeight();\n          this.$$height = height;\n        }\n      }\n    });\n\n  /**\n   * @ngdoc function\n   * @name getQualifiedColField\n   * @methodOf ui.grid.class:GridRow\n   * @description returns the qualified field name as it exists on scope\n   * ie: row.entity.fieldA\n   * @param {GridCol} col column instance\n   * @returns {string} resulting name that can be evaluated on scope\n   */\n    GridRow.prototype.getQualifiedColField = function(col) {\n      return 'row.' + this.getEntityQualifiedColField(col);\n    };\n\n    /**\n     * @ngdoc function\n     * @name getEntityQualifiedColField\n     * @methodOf ui.grid.class:GridRow\n     * @description returns the qualified field name minus the row path\n     * ie: entity.fieldA\n     * @param {GridCol} col column instance\n     * @returns {string} resulting name that can be evaluated against a row\n     */\n  GridRow.prototype.getEntityQualifiedColField = function(col) {\n    return gridUtil.preEval('entity.' + col.field);\n  };\n  \n  \n  /**\n   * @ngdoc function\n   * @name setRowInvisible\n   * @methodOf  ui.grid.class:GridRow\n   * @description Sets an override on the row that forces it to always\n   * be invisible. Emits the rowsVisibleChanged event if it changed the row visibility.\n   * \n   * This method can be called from the api, passing in the gridRow we want\n   * altered.  It should really work by calling gridRow.setRowInvisible, but that's\n   * not the way I coded it, and too late to change now.  Changed to just call\n   * the internal function row.setThisRowInvisible().\n   * \n   * @param {GridRow} row the row we want to set to invisible\n   * \n   */\n  GridRow.prototype.setRowInvisible = function ( row ) {\n    if (row && row.setThisRowInvisible){\n      row.setThisRowInvisible( 'user' );\n    }\n  };\n  \n  \n  /**\n   * @ngdoc function\n   * @name clearRowInvisible\n   * @methodOf  ui.grid.class:GridRow\n   * @description Clears an override on the row that forces it to always\n   * be invisible. Emits the rowsVisibleChanged event if it changed the row visibility.\n   * \n   * This method can be called from the api, passing in the gridRow we want\n   * altered.  It should really work by calling gridRow.clearRowInvisible, but that's\n   * not the way I coded it, and too late to change now.  Changed to just call\n   * the internal function row.clearThisRowInvisible().\n   * \n   * @param {GridRow} row the row we want to clear the invisible flag\n   * \n   */\n  GridRow.prototype.clearRowInvisible = function ( row ) {\n    if (row && row.clearThisRowInvisible){\n      row.clearThisRowInvisible( 'user' );\n    }\n  };\n  \n  \n  /**\n   * @ngdoc function\n   * @name setThisRowInvisible\n   * @methodOf  ui.grid.class:GridRow\n   * @description Sets an override on the row that forces it to always\n   * be invisible. Emits the rowsVisibleChanged event if it changed the row visibility\n   *\n   * @param {string} reason the reason (usually the module) for the row to be invisible.\n   * E.g. grouping, user, filter\n   * @param {boolean} fromRowsProcessor whether we were called from a rowsProcessor, passed through to evaluateRowVisibility\n   */\n  GridRow.prototype.setThisRowInvisible = function ( reason, fromRowsProcessor ) {\n    if ( !this.invisibleReason ){\n      this.invisibleReason = {};\n    }\n    this.invisibleReason[reason] = true;\n    this.evaluateRowVisibility( fromRowsProcessor);\n  };\n\n\n  /**\n   * @ngdoc function\n   * @name clearRowInvisible\n   * @methodOf ui.grid.class:GridRow\n   * @description Clears any override on the row visibility, returning it \n   * to normal visibility calculations.  Emits the rowsVisibleChanged\n   * event\n   * \n   * @param {string} reason the reason (usually the module) for the row to be invisible.\n   * E.g. grouping, user, filter\n   * @param {boolean} fromRowsProcessor whether we were called from a rowsProcessor, passed through to evaluateRowVisibility\n   */\n  GridRow.prototype.clearThisRowInvisible = function ( reason, fromRowsProcessor ) {\n    if (typeof(this.invisibleReason) !== 'undefined' ) {\n      delete this.invisibleReason[reason];\n    }\n    this.evaluateRowVisibility( fromRowsProcessor );\n  };\n\n\n  /**\n   * @ngdoc function\n   * @name evaluateRowVisibility\n   * @methodOf ui.grid.class:GridRow\n   * @description Determines whether the row should be visible based on invisibleReason, \n   * and if it changes the row visibility, then emits the rowsVisibleChanged event.\n   * \n   * Queues a grid refresh, but doesn't call it directly to avoid hitting lots of grid refreshes.\n   * @param {boolean} fromRowProcessor if true, then it won't raise events or queue the refresh, the\n   * row processor does that already\n   */\n  GridRow.prototype.evaluateRowVisibility = function ( fromRowProcessor ) {\n    var newVisibility = true;\n    if ( typeof(this.invisibleReason) !== 'undefined' ){\n      angular.forEach(this.invisibleReason, function( value, key ){\n        if ( value ){\n          newVisibility = false;\n        }\n      });\n    }\n    \n    if ( typeof(this.visible) === 'undefined' || this.visible !== newVisibility ){\n      this.visible = newVisibility;\n      if ( !fromRowProcessor ){\n        this.grid.queueGridRefresh();\n        this.grid.api.core.raise.rowsVisibleChanged(this);\n      }\n    }\n  };\n  \n\n  return GridRow;\n}]);\n\n})();\n\n(function () {\n  angular.module('ui.grid')\n    .factory('ScrollEvent', ['gridUtil', function (gridUtil) {\n\n      /**\n       * @ngdoc function\n       * @name ui.grid.class:ScrollEvent\n       * @description Model for all scrollEvents\n       * @param {Grid} grid that owns the scroll event\n       * @param {GridRenderContainer} sourceRowContainer that owns the scroll event. Can be null\n       * @param {GridRenderContainer} sourceColContainer that owns the scroll event. Can be null\n       * @param {string} source the source of the event - from uiGridConstants.scrollEventSources or a string value of directive/service/factory.functionName\n       */\n      function ScrollEvent(grid, sourceRowContainer, sourceColContainer, source) {\n        var self = this;\n        if (!grid) {\n          throw new Error(\"grid argument is required\");\n        }\n\n        /**\n         *  @ngdoc object\n         *  @name grid\n         *  @propertyOf  ui.grid.class:ScrollEvent\n         *  @description A reference back to the grid\n         */\n         self.grid = grid;\n\n\n\n        /**\n         *  @ngdoc object\n         *  @name source\n         *  @propertyOf  ui.grid.class:ScrollEvent\n         *  @description the source of the scroll event. limited to values from uiGridConstants.scrollEventSources\n         */\n        self.source = source;\n\n\n        /**\n         *  @ngdoc object\n         *  @name noDelay\n         *  @propertyOf  ui.grid.class:ScrollEvent\n         *  @description most scroll events from the mouse or trackpad require delay to operate properly\n         *  set to false to eliminate delay.  Useful for scroll events that the grid causes, such as scrolling to make a row visible.\n         */\n        self.withDelay = true;\n\n        self.sourceRowContainer = sourceRowContainer;\n        self.sourceColContainer = sourceColContainer;\n\n        self.newScrollLeft = null;\n        self.newScrollTop = null;\n        self.x = null;\n        self.y = null;\n\n        self.verticalScrollLength = -9999999;\n        self.horizontalScrollLength = -999999;\n\n\n        /**\n         *  @ngdoc function\n         *  @name fireThrottledScrollingEvent\n         *  @methodOf  ui.grid.class:ScrollEvent\n         *  @description fires a throttled event using grid.api.core.raise.scrollEvent\n         */\n        self.fireThrottledScrollingEvent = gridUtil.throttle(function(sourceContainerId) {\n          self.grid.scrollContainers(sourceContainerId, self);\n        }, self.grid.options.wheelScrollThrottle, {trailing: true});\n\n      }\n\n\n      /**\n       *  @ngdoc function\n       *  @name getNewScrollLeft\n       *  @methodOf  ui.grid.class:ScrollEvent\n       *  @description returns newScrollLeft property if available; calculates a new value if it isn't\n       */\n      ScrollEvent.prototype.getNewScrollLeft = function(colContainer, viewport){\n        var self = this;\n\n        if (!self.newScrollLeft){\n          var scrollWidth = (colContainer.getCanvasWidth() - colContainer.getViewportWidth());\n\n          var oldScrollLeft = gridUtil.normalizeScrollLeft(viewport, self.grid);\n\n          var scrollXPercentage;\n          if (typeof(self.x.percentage) !== 'undefined' && self.x.percentage !== undefined) {\n            scrollXPercentage = self.x.percentage;\n          }\n          else if (typeof(self.x.pixels) !== 'undefined' && self.x.pixels !== undefined) {\n            scrollXPercentage = self.x.percentage = (oldScrollLeft + self.x.pixels) / scrollWidth;\n          }\n          else {\n            throw new Error(\"No percentage or pixel value provided for scroll event X axis\");\n          }\n\n          return Math.max(0, scrollXPercentage * scrollWidth);\n        }\n\n        return self.newScrollLeft;\n      };\n\n\n      /**\n       *  @ngdoc function\n       *  @name getNewScrollTop\n       *  @methodOf  ui.grid.class:ScrollEvent\n       *  @description returns newScrollTop property if available; calculates a new value if it isn't\n       */\n      ScrollEvent.prototype.getNewScrollTop = function(rowContainer, viewport){\n        var self = this;\n\n\n        if (!self.newScrollTop){\n          var scrollLength = rowContainer.getVerticalScrollLength();\n\n          var oldScrollTop = viewport[0].scrollTop;\n\n          var scrollYPercentage;\n          if (typeof(self.y.percentage) !== 'undefined' && self.y.percentage !== undefined) {\n            scrollYPercentage = self.y.percentage;\n          }\n          else if (typeof(self.y.pixels) !== 'undefined' && self.y.pixels !== undefined) {\n            scrollYPercentage = self.y.percentage = (oldScrollTop + self.y.pixels) / scrollLength;\n          }\n          else {\n            throw new Error(\"No percentage or pixel value provided for scroll event Y axis\");\n          }\n\n          return Math.max(0, scrollYPercentage * scrollLength);\n        }\n\n        return self.newScrollTop;\n      };\n\n      ScrollEvent.prototype.atTop = function(scrollTop) {\n        return (this.y && (this.y.percentage === 0 || this.verticalScrollLength < 0) && scrollTop === 0);\n      };\n\n      ScrollEvent.prototype.atBottom = function(scrollTop) {\n        return (this.y && (this.y.percentage === 1 || this.verticalScrollLength === 0) && scrollTop > 0);\n      };\n\n      ScrollEvent.prototype.atLeft = function(scrollLeft) {\n        return (this.x && (this.x.percentage === 0 || this.horizontalScrollLength < 0) && scrollLeft === 0);\n      };\n\n      ScrollEvent.prototype.atRight = function(scrollLeft) {\n        return (this.x && (this.x.percentage === 1 || this.horizontalScrollLength ===0) && scrollLeft > 0);\n      };\n\n\n      ScrollEvent.Sources = {\n        ViewPortScroll: 'ViewPortScroll',\n        RenderContainerMouseWheel: 'RenderContainerMouseWheel',\n        RenderContainerTouchMove: 'RenderContainerTouchMove',\n        Other: 99\n      };\n\n      return ScrollEvent;\n    }]);\n\n\n\n})();\n\n(function () {\n  'use strict';\n  /**\n   *  @ngdoc object\n   *  @name ui.grid.service:gridClassFactory\n   *\n   *  @description factory to return dom specific instances of a grid\n   *\n   */\n  angular.module('ui.grid').service('gridClassFactory', ['gridUtil', '$q', '$compile', '$templateCache', 'uiGridConstants', 'Grid', 'GridColumn', 'GridRow',\n    function (gridUtil, $q, $compile, $templateCache, uiGridConstants, Grid, GridColumn, GridRow) {\n\n      var service = {\n        /**\n         * @ngdoc method\n         * @name createGrid\n         * @methodOf ui.grid.service:gridClassFactory\n         * @description Creates a new grid instance. Each instance will have a unique id\n         * @param {object} options An object map of options to pass into the created grid instance.\n         * @returns {Grid} grid\n         */\n        createGrid : function(options) {\n          options = (typeof(options) !== 'undefined') ? options : {};\n          options.id = gridUtil.newId();\n          var grid = new Grid(options);\n\n          // NOTE/TODO: rowTemplate should always be defined...\n          if (grid.options.rowTemplate) {\n            var rowTemplateFnPromise = $q.defer();\n            grid.getRowTemplateFn = rowTemplateFnPromise.promise;\n            \n            gridUtil.getTemplate(grid.options.rowTemplate)\n              .then(\n                function (template) {\n                  var rowTemplateFn = $compile(template);\n                  rowTemplateFnPromise.resolve(rowTemplateFn);\n                },\n                function (res) {\n                  // Todo handle response error here?\n                  throw new Error(\"Couldn't fetch/use row template '\" + grid.options.rowTemplate + \"'\");\n                });\n          }\n\n          grid.registerColumnBuilder(service.defaultColumnBuilder);\n\n          // Row builder for custom row templates\n          grid.registerRowBuilder(service.rowTemplateAssigner);\n\n          // Reset all rows to visible initially\n          grid.registerRowsProcessor(function allRowsVisible(rows) {\n            rows.forEach(function (row) {\n              row.evaluateRowVisibility( true );\n            }, 50);\n\n            return rows;\n          });\n\n          grid.registerColumnsProcessor(function allColumnsVisible(columns) {\n            columns.forEach(function (column) {\n              column.visible = true;\n            });\n\n            return columns;\n          }, 50);\n\n          grid.registerColumnsProcessor(function(renderableColumns) {\n              renderableColumns.forEach(function (column) {\n                  if (column.colDef.visible === false) {\n                      column.visible = false;\n                  }\n              });\n\n              return renderableColumns;\n          }, 50);\n\n\n          grid.registerRowsProcessor(grid.searchRows, 100);\n\n          // Register the default row processor, it sorts rows by selected columns\n          if (grid.options.externalSort && angular.isFunction(grid.options.externalSort)) {\n            grid.registerRowsProcessor(grid.options.externalSort, 200);\n          }\n          else {\n            grid.registerRowsProcessor(grid.sortByColumn, 200);\n          }\n\n          return grid;\n        },\n\n        /**\n         * @ngdoc function\n         * @name defaultColumnBuilder\n         * @methodOf ui.grid.service:gridClassFactory\n         * @description Processes designTime column definitions and applies them to col for the\n         *              core grid features\n         * @param {object} colDef reference to column definition\n         * @param {GridColumn} col reference to gridCol\n         * @param {object} gridOptions reference to grid options\n         */\n        defaultColumnBuilder: function (colDef, col, gridOptions) {\n\n          var templateGetPromises = [];\n\n          // Abstracts the standard template processing we do for every template type.\n          var processTemplate = function( templateType, providedType, defaultTemplate, filterType, tooltipType ) {\n            if ( !colDef[templateType] ){\n              col[providedType] = defaultTemplate;\n            } else {\n              col[providedType] = colDef[templateType];\n            }\n \n             templateGetPromises.push(gridUtil.getTemplate(col[providedType])\n                .then(\n                function (template) {\n                  var tooltipCall = ( tooltipType === 'cellTooltip' ) ? 'col.cellTooltip(row,col)' : 'col.headerTooltip(col)';\n                  if ( tooltipType && col[tooltipType] === false ){\n                    template = template.replace(uiGridConstants.TOOLTIP, '');\n                  } else if ( tooltipType && col[tooltipType] ){\n                    template = template.replace(uiGridConstants.TOOLTIP, 'title=\"{{' + tooltipCall + ' CUSTOM_FILTERS }}\"');\n                  }\n\n                  if ( filterType ){\n                    col[templateType] = template.replace(uiGridConstants.CUSTOM_FILTERS, function() {\n                      return col[filterType] ? \"|\" + col[filterType] : \"\";\n                    });\n                  } else {\n                    col[templateType] = template;\n                  }\n                },\n                function (res) {\n                  throw new Error(\"Couldn't fetch/use colDef.\" + templateType + \" '\" + colDef[templateType] + \"'\");\n                })\n            );\n\n          };\n\n\n          /**\n           * @ngdoc property\n           * @name cellTemplate\n           * @propertyOf ui.grid.class:GridOptions.columnDef\n           * @description a custom template for each cell in this column.  The default\n           * is ui-grid/uiGridCell.  If you are using the cellNav feature, this template\n           * must contain a div that can receive focus.\n           *\n           */\n          processTemplate( 'cellTemplate', 'providedCellTemplate', 'ui-grid/uiGridCell', 'cellFilter', 'cellTooltip' );\n          col.cellTemplatePromise = templateGetPromises[0];\n\n          /**\n           * @ngdoc property\n           * @name headerCellTemplate\n           * @propertyOf ui.grid.class:GridOptions.columnDef\n           * @description a custom template for the header for this column.  The default\n           * is ui-grid/uiGridHeaderCell\n           *\n           */\n          processTemplate( 'headerCellTemplate', 'providedHeaderCellTemplate', 'ui-grid/uiGridHeaderCell', 'headerCellFilter', 'headerTooltip' );\n\n          /**\n           * @ngdoc property\n           * @name footerCellTemplate\n           * @propertyOf ui.grid.class:GridOptions.columnDef\n           * @description a custom template for the footer for this column.  The default\n           * is ui-grid/uiGridFooterCell\n           *\n           */\n          processTemplate( 'footerCellTemplate', 'providedFooterCellTemplate', 'ui-grid/uiGridFooterCell', 'footerCellFilter' );\n\n          /**\n           * @ngdoc property\n           * @name filterHeaderTemplate\n           * @propertyOf ui.grid.class:GridOptions.columnDef\n           * @description a custom template for the filter input.  The default is ui-grid/ui-grid-filter\n           *\n           */\n          processTemplate( 'filterHeaderTemplate', 'providedFilterHeaderTemplate', 'ui-grid/ui-grid-filter' );\n\n          // Create a promise for the compiled element function\n          col.compiledElementFnDefer = $q.defer();\n\n          return $q.all(templateGetPromises);\n        },\n        \n\n        rowTemplateAssigner: function rowTemplateAssigner(row) {\n          var grid = this;\n\n          // Row has no template assigned to it\n          if (!row.rowTemplate) {\n            // Use the default row template from the grid\n            row.rowTemplate = grid.options.rowTemplate;\n\n            // Use the grid's function for fetching the compiled row template function\n            row.getRowTemplateFn = grid.getRowTemplateFn;\n          }\n          // Row has its own template assigned\n          else {\n            // Create a promise for the compiled row template function\n            var perRowTemplateFnPromise = $q.defer();\n            row.getRowTemplateFn = perRowTemplateFnPromise.promise;\n\n            // Get the row template\n            gridUtil.getTemplate(row.rowTemplate)\n              .then(function (template) {\n                // Compile the template\n                var rowTemplateFn = $compile(template);\n                \n                // Resolve the compiled template function promise\n                perRowTemplateFnPromise.resolve(rowTemplateFn);\n              },\n              function (res) {\n                // Todo handle response error here?\n                throw new Error(\"Couldn't fetch/use row template '\" + row.rowTemplate + \"'\");\n              });\n          }\n\n          return row.getRowTemplateFn;\n        }\n      };\n\n      //class definitions (moved to separate factories)\n\n      return service;\n    }]);\n\n})();\n(function() {\n\nvar module = angular.module('ui.grid');\n\nfunction escapeRegExp(str) {\n  return str.replace(/[\\-\\[\\]\\/\\{\\}\\(\\)\\*\\+\\?\\.\\\\\\^\\$\\|]/g, \"\\\\$&\");\n}\n\n\n/**\n *  @ngdoc service\n *  @name ui.grid.service:rowSearcher\n *\n *  @description Service for searching/filtering rows based on column value conditions.\n */\nmodule.service('rowSearcher', ['gridUtil', 'uiGridConstants', function (gridUtil, uiGridConstants) {\n  var defaultCondition = uiGridConstants.filter.CONTAINS;\n\n  var rowSearcher = {};\n\n  /**\n   * @ngdoc function\n   * @name getTerm\n   * @methodOf ui.grid.service:rowSearcher\n   * @description Get the term from a filter\n   * Trims leading and trailing whitespace\n   * @param {object} filter object to use\n   * @returns {object} Parsed term\n   */\n  rowSearcher.getTerm = function getTerm(filter) {\n    if (typeof(filter.term) === 'undefined') { return filter.term; }\n    \n    var term = filter.term;\n\n    // Strip leading and trailing whitespace if the term is a string\n    if (typeof(term) === 'string') {\n      term = term.trim();\n    }\n\n    return term;\n  };\n\n  /**\n   * @ngdoc function\n   * @name stripTerm\n   * @methodOf ui.grid.service:rowSearcher\n   * @description Remove leading and trailing asterisk (*) from the filter's term\n   * @param {object} filter object to use\n   * @returns {uiGridConstants.filter<int>} Value representing the condition constant value\n   */\n  rowSearcher.stripTerm = function stripTerm(filter) {\n    var term = rowSearcher.getTerm(filter);\n\n    if (typeof(term) === 'string') {\n      return escapeRegExp(term.replace(/(^\\*|\\*$)/g, ''));\n    }\n    else {\n      return term;\n    }\n  };\n  \n\n  /**\n   * @ngdoc function\n   * @name guessCondition\n   * @methodOf ui.grid.service:rowSearcher\n   * @description Guess the condition for a filter based on its term\n   * <br>\n   * Defaults to STARTS_WITH. Uses CONTAINS for strings beginning and ending with *s (*bob*).\n   * Uses STARTS_WITH for strings ending with * (bo*). Uses ENDS_WITH for strings starting with * (*ob).\n   * @param {object} filter object to use\n   * @returns {uiGridConstants.filter<int>} Value representing the condition constant value\n   */\n  rowSearcher.guessCondition = function guessCondition(filter) {\n    if (typeof(filter.term) === 'undefined' || !filter.term) {\n      return defaultCondition;\n    }\n\n    var term = rowSearcher.getTerm(filter);\n    \n    if (/\\*/.test(term)) {\n      var regexpFlags = '';\n      if (!filter.flags || !filter.flags.caseSensitive) {\n        regexpFlags += 'i';\n      }\n\n      var reText = term.replace(/(\\\\)?\\*/g, function ($0, $1) { return $1 ? $0 : '[\\\\s\\\\S]*?'; });\n      return new RegExp('^' + reText + '$', regexpFlags);\n    }\n    // Otherwise default to default condition\n    else {\n      return defaultCondition;\n    }\n  };\n  \n  \n  /**\n   * @ngdoc function\n   * @name setupFilters\n   * @methodOf ui.grid.service:rowSearcher\n   * @description For a given columns filters (either col.filters, or [col.filter] can be passed in),\n   * do all the parsing and pre-processing and store that data into a new filters object.  The object\n   * has the condition, the flags, the stripped term, and a parsed reg exp if there was one.\n   * \n   * We could use a forEach in here, since it's much less performance sensitive, but since we're using \n   * for loops everywhere else in this module...\n   * \n   * @param {array} filters the filters from the column (col.filters or [col.filter])\n   * @returns {array} An array of parsed/preprocessed filters\n   */\n  rowSearcher.setupFilters = function setupFilters( filters ){\n    var newFilters = [];\n    \n    var filtersLength = filters.length;\n    for ( var i = 0; i < filtersLength; i++ ){\n      var filter = filters[i];\n      \n      if ( filter.noTerm || !gridUtil.isNullOrUndefined(filter.term) ){\n        var newFilter = {};\n        \n        var regexpFlags = '';\n        if (!filter.flags || !filter.flags.caseSensitive) {\n          regexpFlags += 'i';\n        }\n    \n        if ( !gridUtil.isNullOrUndefined(filter.term) ){\n          // it is possible to have noTerm.  We don't need to copy that across, it was just a flag to avoid\n          // getting the filter ignored if the filter was a function that didn't use a term\n          newFilter.term = rowSearcher.stripTerm(filter);\n        }\n        \n        if ( filter.condition ){\n          newFilter.condition = filter.condition;\n        } else {\n          newFilter.condition = rowSearcher.guessCondition(filter);\n        }\n\n        newFilter.flags = angular.extend( { caseSensitive: false, date: false }, filter.flags );\n\n        if (newFilter.condition === uiGridConstants.filter.STARTS_WITH) {\n          newFilter.startswithRE = new RegExp('^' + newFilter.term, regexpFlags);\n        }\n        \n         if (newFilter.condition === uiGridConstants.filter.ENDS_WITH) {\n          newFilter.endswithRE = new RegExp(newFilter.term + '$', regexpFlags);\n        }\n\n        if (newFilter.condition === uiGridConstants.filter.CONTAINS) {\n          newFilter.containsRE = new RegExp(newFilter.term, regexpFlags);\n        }\n\n        if (newFilter.condition === uiGridConstants.filter.EXACT) {\n          newFilter.exactRE = new RegExp('^' + newFilter.term + '$', regexpFlags);\n        }\n        \n        newFilters.push(newFilter);\n      }\n    }\n    return newFilters;\n  };\n  \n\n  /**\n   * @ngdoc function\n   * @name runColumnFilter\n   * @methodOf ui.grid.service:rowSearcher\n   * @description Runs a single pre-parsed filter against a cell, returning true\n   * if the cell matches that one filter.\n   * \n   * @param {Grid} grid the grid we're working against\n   * @param {GridRow} row the row we're matching against\n   * @param {GridCol} column the column that we're working against\n   * @param {object} filter the specific, preparsed, filter that we want to test\n   * @returns {boolean} true if we match (row stays visible)\n   */\n  rowSearcher.runColumnFilter = function runColumnFilter(grid, row, column, filter) {\n    // Cache typeof condition\n    var conditionType = typeof(filter.condition);\n\n    // Term to search for.\n    var term = filter.term;\n\n    // Get the column value for this row\n    var value;\n    if ( column.filterCellFiltered ){\n      value = grid.getCellDisplayValue(row, column);\n    } else {\n      value = grid.getCellValue(row, column);\n    }\n\n\n    // If the filter's condition is a RegExp, then use it\n    if (filter.condition instanceof RegExp) {\n      return filter.condition.test(value);\n    }\n\n    // If the filter's condition is a function, run it\n    if (conditionType === 'function') {\n      return filter.condition(term, value, row, column);\n    }\n\n    if (filter.startswithRE) {\n      return filter.startswithRE.test(value);\n    }\n\n    if (filter.endswithRE) {\n      return filter.endswithRE.test(value);\n    }\n\n    if (filter.containsRE) {\n      return filter.containsRE.test(value);\n    }\n\n    if (filter.exactRE) {\n      return filter.exactRE.test(value);\n    }\n\n    if (filter.condition === uiGridConstants.filter.NOT_EQUAL) {\n      var regex = new RegExp('^' + term + '$');\n      return !regex.exec(value);\n    }\n\n    if (typeof(value) === 'number' && typeof(term) === 'string' ){\n      // if the term has a decimal in it, it comes through as '9\\.4', we need to take out the \\\n      // the same for negative numbers\n      // TODO: I suspect the right answer is to look at escapeRegExp at the top of this code file, maybe it's not needed?\n      var tempFloat = parseFloat(term.replace(/\\\\\\./,'.').replace(/\\\\\\-/,'-'));\n      if (!isNaN(tempFloat)) {\n        term = tempFloat;\n      }\n    }\n\n    if (filter.flags.date === true) {\n      value = new Date(value);\n      // If the term has a dash in it, it comes through as '\\-' -- we need to take out the '\\'.\n      term = new Date(term.replace(/\\\\/g, ''));\n    }\n\n    if (filter.condition === uiGridConstants.filter.GREATER_THAN) {\n      return (value > term);\n    }\n\n    if (filter.condition === uiGridConstants.filter.GREATER_THAN_OR_EQUAL) {\n      return (value >= term);\n    }\n\n    if (filter.condition === uiGridConstants.filter.LESS_THAN) {\n      return (value < term);\n    }\n\n    if (filter.condition === uiGridConstants.filter.LESS_THAN_OR_EQUAL) {\n      return (value <= term);\n    }\n\n    return true;\n  };\n\n\n  /**\n   * @ngdoc boolean\n   * @name useExternalFiltering\n   * @propertyOf ui.grid.class:GridOptions\n   * @description False by default. When enabled, this setting suppresses the internal filtering.\n   * All UI logic will still operate, allowing filter conditions to be set and modified.\n   * \n   * The external filter logic can listen for the `filterChange` event, which fires whenever\n   * a filter has been adjusted.\n   */\n  /**\n   * @ngdoc function\n   * @name searchColumn\n   * @methodOf ui.grid.service:rowSearcher\n   * @description Process provided filters on provided column against a given row. If the row meets \n   * the conditions on all the filters, return true.\n   * @param {Grid} grid Grid to search in\n   * @param {GridRow} row Row to search on\n   * @param {GridCol} column Column with the filters to use\n   * @param {array} filters array of pre-parsed/preprocessed filters to apply\n   * @returns {boolean} Whether the column matches or not.\n   */\n  rowSearcher.searchColumn = function searchColumn(grid, row, column, filters) {\n    if (grid.options.useExternalFiltering) {\n      return true;\n    }\n\n    var filtersLength = filters.length;\n    for (var i = 0; i < filtersLength; i++) {\n      var filter = filters[i];\n\n      var ret = rowSearcher.runColumnFilter(grid, row, column, filter);\n      if (!ret) {\n        return false;\n      }\n    }\n\n    return true;\n  };\n\n\n  /**\n   * @ngdoc function\n   * @name search\n   * @methodOf ui.grid.service:rowSearcher\n   * @description Run a search across the given rows and columns, marking any rows that don't \n   * match the stored col.filters or col.filter as invisible.\n   * @param {Grid} grid Grid instance to search inside\n   * @param {Array[GridRow]} rows GridRows to filter\n   * @param {Array[GridColumn]} columns GridColumns with filters to process\n   */\n  rowSearcher.search = function search(grid, rows, columns) {\n    /*\n     * Added performance optimisations into this code base, as this logic creates deeply nested\n     * loops and is therefore very performance sensitive.  In particular, avoiding forEach as\n     * this impacts some browser optimisers (particularly Chrome), using iterators instead\n     */\n\n    // Don't do anything if we weren't passed any rows\n    if (!rows) {\n      return;\n    }\n\n    // don't filter if filtering currently disabled\n    if (!grid.options.enableFiltering){\n      return rows;\n    }\n\n    // Build list of filters to apply\n    var filterData = [];\n\n    var colsLength = columns.length;\n\n    var hasTerm = function( filters ) {\n      var hasTerm = false;\n\n      filters.forEach( function (filter) {\n        if ( !gridUtil.isNullOrUndefined(filter.term) && filter.term !== '' || filter.noTerm ){\n          hasTerm = true;\n        }\n      });\n\n      return hasTerm;\n    };\n\n    for (var i = 0; i < colsLength; i++) {\n      var col = columns[i];\n\n      if (typeof(col.filters) !== 'undefined' && hasTerm(col.filters) ) {\n        filterData.push( { col: col, filters: rowSearcher.setupFilters(col.filters) } );\n      }\n    }\n\n    if (filterData.length > 0) {\n      // define functions outside the loop, performance optimisation\n      var foreachRow = function(grid, row, col, filters){\n        if ( row.visible && !rowSearcher.searchColumn(grid, row, col, filters) ) {\n          row.visible = false;\n        }\n      };\n\n      var foreachFilterCol = function(grid, filterData){\n        var rowsLength = rows.length;\n        for ( var i = 0; i < rowsLength; i++){\n          foreachRow(grid, rows[i], filterData.col, filterData.filters);  \n        }\n      };\n\n      // nested loop itself - foreachFilterCol, which in turn calls foreachRow\n      var filterDataLength = filterData.length;\n      for ( var j = 0; j < filterDataLength; j++){\n        foreachFilterCol( grid, filterData[j] );  \n      }\n\n      if (grid.api.core.raise.rowsVisibleChanged) {\n        grid.api.core.raise.rowsVisibleChanged();\n      }\n\n      // drop any invisible rows\n      // keeping these, as needed with filtering for trees - we have to come back and make parent nodes visible if child nodes are selected in the filter\n      // rows = rows.filter(function(row){ return row.visible; });\n\n    }\n\n    return rows;\n  };\n\n  return rowSearcher;\n}]);\n\n})();\n\n(function() {\n\nvar module = angular.module('ui.grid');\n\n/**\n * @ngdoc object\n * @name ui.grid.class:RowSorter\n * @description RowSorter provides the default sorting mechanisms, \n * including guessing column types and applying appropriate sort \n * algorithms\n * \n */ \n\nmodule.service('rowSorter', ['$parse', 'uiGridConstants', function ($parse, uiGridConstants) {\n  var currencyRegexStr = \n    '(' +\n    uiGridConstants.CURRENCY_SYMBOLS\n      .map(function (a) { return '\\\\' + a; }) // Escape all the currency symbols ($ at least will jack up this regex)\n      .join('|') + // Join all the symbols together with |s\n    ')?';\n\n  // /^[-+]?[£$¤¥]?[\\d,.]+%?$/\n  var numberStrRegex = new RegExp('^[-+]?' + currencyRegexStr + '[\\\\d,.]+' + currencyRegexStr + '%?$');\n\n  var rowSorter = {\n    // Cache of sorting functions. Once we create them, we don't want to keep re-doing it\n    //   this takes a piece of data from the cell and tries to determine its type and what sorting\n    //   function to use for it\n    colSortFnCache: {}\n  };\n\n\n  /**\n   * @ngdoc method\n   * @methodOf ui.grid.class:RowSorter\n   * @name guessSortFn\n   * @description Assigns a sort function to use based on the itemType in the column\n   * @param {string} itemType one of 'number', 'boolean', 'string', 'date', 'object'.  And\n   * error will be thrown for any other type.\n   * @returns {function} a sort function that will sort that type\n   */\n  rowSorter.guessSortFn = function guessSortFn(itemType) {\n    switch (itemType) {\n      case \"number\":\n        return rowSorter.sortNumber;\n      case \"numberStr\":\n        return rowSorter.sortNumberStr;\n      case \"boolean\":\n        return rowSorter.sortBool;\n      case \"string\":\n        return rowSorter.sortAlpha;\n      case \"date\":\n        return rowSorter.sortDate;\n      case \"object\":\n        return rowSorter.basicSort;\n      default:\n        throw new Error('No sorting function found for type:' + itemType);\n    }\n  };\n\n\n  /**\n   * @ngdoc method\n   * @methodOf ui.grid.class:RowSorter\n   * @name handleNulls\n   * @description Sorts nulls and undefined to the bottom (top when\n   * descending).  Called by each of the internal sorters before\n   * attempting to sort.  Note that this method is available on the core api\n   * via gridApi.core.sortHandleNulls\n   * @param {object} a sort value a\n   * @param {object} b sort value b\n   * @returns {number} null if there were no nulls/undefineds, otherwise returns\n   * a sort value that should be passed back from the sort function\n   */\n  rowSorter.handleNulls = function handleNulls(a, b) {\n    // We want to allow zero values and false values to be evaluated in the sort function\n    if ((!a && a !== 0 && a !== false) || (!b && b !== 0 && b !== false)) {\n      // We want to force nulls and such to the bottom when we sort... which effectively is \"greater than\"\n      if ((!a && a !== 0 && a !== false) && (!b && b !== 0 && b !== false)) {\n        return 0;\n      }\n      else if (!a && a !== 0 && a !== false) {\n        return 1;\n      }\n      else if (!b && b !== 0 && b !== false) {\n        return -1;\n      }\n    }\n    return null;\n  };\n\n\n  /**\n   * @ngdoc method\n   * @methodOf ui.grid.class:RowSorter\n   * @name basicSort\n   * @description Sorts any values that provide the < method, including strings\n   * or numbers.  Handles nulls and undefined through calling handleNulls \n   * @param {object} a sort value a\n   * @param {object} b sort value b\n   * @returns {number} normal sort function, returns -ve, 0, +ve\n   */\n  rowSorter.basicSort = function basicSort(a, b) {\n    var nulls = rowSorter.handleNulls(a, b);\n    if ( nulls !== null ){\n      return nulls;\n    } else {\n      if (a === b) {\n        return 0;\n      }\n      if (a < b) {\n        return -1;\n      }\n      return 1;\n    }\n  };\n\n\n  /**\n   * @ngdoc method\n   * @methodOf ui.grid.class:RowSorter\n   * @name sortNumber\n   * @description Sorts numerical values.  Handles nulls and undefined through calling handleNulls \n   * @param {object} a sort value a\n   * @param {object} b sort value b\n   * @returns {number} normal sort function, returns -ve, 0, +ve\n   */\n  rowSorter.sortNumber = function sortNumber(a, b) {\n    var nulls = rowSorter.handleNulls(a, b);\n    if ( nulls !== null ){\n      return nulls;\n    } else {\n      return a - b;\n    }\n  };\n\n\n  /**\n   * @ngdoc method\n   * @methodOf ui.grid.class:RowSorter\n   * @name sortNumberStr\n   * @description Sorts numerical values that are stored in a string (i.e. parses them to numbers first).  \n   * Handles nulls and undefined through calling handleNulls \n   * @param {object} a sort value a\n   * @param {object} b sort value b\n   * @returns {number} normal sort function, returns -ve, 0, +ve\n   */\n  rowSorter.sortNumberStr = function sortNumberStr(a, b) {\n    var nulls = rowSorter.handleNulls(a, b);\n    if ( nulls !== null ){\n      return nulls;\n    } else {\n      var numA, // The parsed number form of 'a'\n          numB, // The parsed number form of 'b'\n          badA = false,\n          badB = false;\n  \n      // Try to parse 'a' to a float\n      numA = parseFloat(a.replace(/[^0-9.-]/g, ''));\n  \n      // If 'a' couldn't be parsed to float, flag it as bad\n      if (isNaN(numA)) {\n          badA = true;\n      }\n  \n      // Try to parse 'b' to a float\n      numB = parseFloat(b.replace(/[^0-9.-]/g, ''));\n  \n      // If 'b' couldn't be parsed to float, flag it as bad\n      if (isNaN(numB)) {\n          badB = true;\n      }\n  \n      // We want bad ones to get pushed to the bottom... which effectively is \"greater than\"\n      if (badA && badB) {\n          return 0;\n      }\n  \n      if (badA) {\n          return 1;\n      }\n  \n      if (badB) {\n          return -1;\n      }\n  \n      return numA - numB;\n    }\n  };\n\n\n  /**\n   * @ngdoc method\n   * @methodOf ui.grid.class:RowSorter\n   * @name sortAlpha\n   * @description Sorts string values. Handles nulls and undefined through calling handleNulls \n   * @param {object} a sort value a\n   * @param {object} b sort value b\n   * @returns {number} normal sort function, returns -ve, 0, +ve\n   */\n  rowSorter.sortAlpha = function sortAlpha(a, b) {\n    var nulls = rowSorter.handleNulls(a, b);\n    if ( nulls !== null ){\n      return nulls;\n    } else {\n      var strA = a.toString().toLowerCase(),\n          strB = b.toString().toLowerCase();\n  \n      return strA === strB ? 0 : (strA < strB ? -1 : 1);\n    }\n  };\n\n\n  /**\n   * @ngdoc method\n   * @methodOf ui.grid.class:RowSorter\n   * @name sortDate\n   * @description Sorts date values. Handles nulls and undefined through calling handleNulls.\n   * Handles date strings by converting to Date object if not already an instance of Date\n   * @param {object} a sort value a\n   * @param {object} b sort value b\n   * @returns {number} normal sort function, returns -ve, 0, +ve\n   */\n  rowSorter.sortDate = function sortDate(a, b) {\n    var nulls = rowSorter.handleNulls(a, b);\n    if ( nulls !== null ){\n      return nulls;\n    } else {\n      if (!(a instanceof Date)) {\n        a = new Date(a);\n      }\n      if (!(b instanceof Date)){\n        b = new Date(b);\n      }\n      var timeA = a.getTime(),\n          timeB = b.getTime();\n  \n      return timeA === timeB ? 0 : (timeA < timeB ? -1 : 1);\n    }\n  };\n\n\n  /**\n   * @ngdoc method\n   * @methodOf ui.grid.class:RowSorter\n   * @name sortBool\n   * @description Sorts boolean values, true is considered larger than false. \n   * Handles nulls and undefined through calling handleNulls \n   * @param {object} a sort value a\n   * @param {object} b sort value b\n   * @returns {number} normal sort function, returns -ve, 0, +ve\n   */\n  rowSorter.sortBool = function sortBool(a, b) {\n    var nulls = rowSorter.handleNulls(a, b);\n    if ( nulls !== null ){\n      return nulls;\n    } else {\n      if (a && b) {\n        return 0;\n      }\n  \n      if (!a && !b) {\n        return 0;\n      }\n      else {\n        return a ? 1 : -1;\n      }\n    }\n  };\n\n\n  /**\n   * @ngdoc method\n   * @methodOf ui.grid.class:RowSorter\n   * @name getSortFn\n   * @description Get the sort function for the column.  Looks first in \n   * rowSorter.colSortFnCache using the column name, failing that it\n   * looks at col.sortingAlgorithm (and puts it in the cache), failing that\n   * it guesses the sort algorithm based on the data type.\n   * \n   * The cache currently seems a bit pointless, as none of the work we do is\n   * processor intensive enough to need caching.  Presumably in future we might\n   * inspect the row data itself to guess the sort function, and in that case\n   * it would make sense to have a cache, the infrastructure is in place to allow\n   * that.\n   * \n   * @param {Grid} grid the grid to consider\n   * @param {GridCol} col the column to find a function for\n   * @param {array} rows an array of grid rows.  Currently unused, but presumably in future\n   * we might inspect the rows themselves to decide what sort of data might be there\n   * @returns {function} the sort function chosen for the column\n   */\n  rowSorter.getSortFn = function getSortFn(grid, col, rows) {\n    var sortFn, item;\n\n    // See if we already figured out what to use to sort the column and have it in the cache\n    if (rowSorter.colSortFnCache[col.colDef.name]) {\n      sortFn = rowSorter.colSortFnCache[col.colDef.name];\n    }\n    // If the column has its OWN sorting algorithm, use that\n    else if (col.sortingAlgorithm !== undefined) {\n      sortFn = col.sortingAlgorithm;\n      rowSorter.colSortFnCache[col.colDef.name] = col.sortingAlgorithm;\n    }\n    // Always default to sortAlpha when sorting after a cellFilter\n    else if ( col.sortCellFiltered && col.cellFilter ){\n      sortFn = rowSorter.sortAlpha;\n      rowSorter.colSortFnCache[col.colDef.name] = sortFn;\n    }\n    // Try and guess what sort function to use\n    else {\n      // Guess the sort function\n      sortFn = rowSorter.guessSortFn(col.colDef.type);\n\n      // If we found a sort function, cache it\n      if (sortFn) {\n        rowSorter.colSortFnCache[col.colDef.name] = sortFn;\n      }\n      else {\n        // We assign the alpha sort because anything that is null/undefined will never get passed to\n        // the actual sorting function. It will get caught in our null check and returned to be sorted\n        // down to the bottom\n        sortFn = rowSorter.sortAlpha;\n      }\n    }\n\n    return sortFn;\n  };\n\n\n\n  /**\n   * @ngdoc method\n   * @methodOf ui.grid.class:RowSorter\n   * @name prioritySort\n   * @description Used where multiple columns are present in the sort criteria,\n   * we determine which column should take precedence in the sort by sorting\n   * the columns based on their sort.priority\n   * \n   * @param {gridColumn} a column a\n   * @param {gridColumn} b column b\n   * @returns {number} normal sort function, returns -ve, 0, +ve\n   */\n  rowSorter.prioritySort = function (a, b) {\n    // Both columns have a sort priority\n    if (a.sort.priority !== undefined && b.sort.priority !== undefined) {\n      // A is higher priority\n      if (a.sort.priority < b.sort.priority) {\n        return -1;\n      }\n      // Equal\n      else if (a.sort.priority === b.sort.priority) {\n        return 0;\n      }\n      // B is higher\n      else {\n        return 1;\n      }\n    }\n    // Only A has a priority\n    else if (a.sort.priority || a.sort.priority === 0) {\n      return -1;\n    }\n    // Only B has a priority\n    else if (b.sort.priority || b.sort.priority === 0) {\n      return 1;\n    }\n    // Neither has a priority\n    else {\n      return 0;\n    }\n  };\n\n\n  /**\n   * @ngdoc object\n   * @name useExternalSorting\n   * @propertyOf ui.grid.class:GridOptions\n   * @description Prevents the internal sorting from executing.  Events will\n   * still be fired when the sort changes, and the sort information on\n   * the columns will be updated, allowing an external sorter (for example,\n   * server sorting) to be implemented.  Defaults to false. \n   * \n   */\n  /**\n   * @ngdoc method\n   * @methodOf ui.grid.class:RowSorter\n   * @name sort\n   * @description sorts the grid \n   * @param {Object} grid the grid itself\n   * @param {array} rows the rows to be sorted\n   * @param {array} columns the columns in which to look\n   * for sort criteria\n   * @returns {array} sorted rows\n   */\n  rowSorter.sort = function rowSorterSort(grid, rows, columns) {\n    // first make sure we are even supposed to do work\n    if (!rows) {\n      return;\n    }\n    \n    if (grid.options.useExternalSorting){\n      return rows;\n    }\n\n    // Build the list of columns to sort by\n    var sortCols = [];\n    columns.forEach(function (col) {\n      if (col.sort && !col.sort.ignoreSort && col.sort.direction && (col.sort.direction === uiGridConstants.ASC || col.sort.direction === uiGridConstants.DESC)) {\n        sortCols.push(col);\n      }\n    });\n\n    // Sort the \"sort columns\" by their sort priority\n    sortCols = sortCols.sort(rowSorter.prioritySort);\n\n    // Now rows to sort by, maintain original order\n    if (sortCols.length === 0) {\n      return rows;\n    }\n    \n    // Re-usable variables\n    var col, direction;\n\n    // put a custom index field on each row, used to make a stable sort out of unstable sorts (e.g. Chrome)\n    var setIndex = function( row, idx ){\n      row.entity.$$uiGridIndex = idx;\n    };\n    rows.forEach(setIndex);\n\n    // IE9-11 HACK.... the 'rows' variable would be empty where we call rowSorter.getSortFn(...) below. We have to use a separate reference\n    // var d = data.slice(0);\n    var r = rows.slice(0);\n\n    // Now actually sort the data\n    var rowSortFn = function (rowA, rowB) {\n      var tem = 0,\n          idx = 0,\n          sortFn;\n\n      while (tem === 0 && idx < sortCols.length) {\n        // grab the metadata for the rest of the logic\n        col = sortCols[idx];\n        direction = sortCols[idx].sort.direction;\n\n        sortFn = rowSorter.getSortFn(grid, col, r);\n        \n        var propA, propB;\n\n        if ( col.sortCellFiltered ){\n          propA = grid.getCellDisplayValue(rowA, col);\n          propB = grid.getCellDisplayValue(rowB, col);\n        } else {\n          propA = grid.getCellValue(rowA, col);\n          propB = grid.getCellValue(rowB, col);\n        }\n\n        tem = sortFn(propA, propB);\n\n        idx++;\n      }\n\n      // Chrome doesn't implement a stable sort function.  If our sort returns 0 \n      // (i.e. the items are equal), and we're at the last sort column in the list,\n      // then return the previous order using our custom\n      // index variable\n      if (tem === 0 ) {\n        return rowA.entity.$$uiGridIndex - rowB.entity.$$uiGridIndex;\n      }\n      \n      // Made it this far, we don't have to worry about null & undefined\n      if (direction === uiGridConstants.ASC) {\n        return tem;\n      } else {\n        return 0 - tem;\n      }\n    };\n\n    var newRows = rows.sort(rowSortFn);\n    \n    // remove the custom index field on each row, used to make a stable sort out of unstable sorts (e.g. Chrome)\n    var clearIndex = function( row, idx ){\n       delete row.entity.$$uiGridIndex;\n    };\n    rows.forEach(clearIndex);\n    \n    return newRows;\n  };\n\n  return rowSorter;\n}]);\n\n})();\n\n(function() {\n\nvar module = angular.module('ui.grid');\n\nvar bindPolyfill;\nif (typeof Function.prototype.bind !== \"function\") {\n  bindPolyfill = function() {\n    var slice = Array.prototype.slice;\n    return function(context) {\n      var fn = this,\n        args = slice.call(arguments, 1);\n      if (args.length) {\n        return function() {\n          return arguments.length ? fn.apply(context, args.concat(slice.call(arguments))) : fn.apply(context, args);\n        };\n      }\n      return function() {\n        return arguments.length ? fn.apply(context, arguments) : fn.call(context);\n      };\n    };\n  };\n}\n\nfunction getStyles (elem) {\n  var e = elem;\n  if (typeof(e.length) !== 'undefined' && e.length) {\n    e = elem[0];\n  }\n\n  return e.ownerDocument.defaultView.getComputedStyle(e, null);\n}\n\nvar rnumnonpx = new RegExp( \"^(\" + (/[+-]?(?:\\d*\\.|)\\d+(?:[eE][+-]?\\d+|)/).source + \")(?!px)[a-z%]+$\", \"i\" ),\n    // swappable if display is none or starts with table except \"table\", \"table-cell\", or \"table-caption\"\n    // see here for display values: https://developer.mozilla.org/en-US/docs/CSS/display\n    rdisplayswap = /^(block|none|table(?!-c[ea]).+)/,\n    cssShow = { position: \"absolute\", visibility: \"hidden\", display: \"block\" };\n\nfunction augmentWidthOrHeight( elem, name, extra, isBorderBox, styles ) {\n  var i = extra === ( isBorderBox ? 'border' : 'content' ) ?\n          // If we already have the right measurement, avoid augmentation\n          4 :\n          // Otherwise initialize for horizontal or vertical properties\n          name === 'width' ? 1 : 0,\n\n          val = 0;\n\n  var sides = ['Top', 'Right', 'Bottom', 'Left'];\n\n  for ( ; i < 4; i += 2 ) {\n    var side = sides[i];\n    // dump('side', side);\n\n    // both box models exclude margin, so add it if we want it\n    if ( extra === 'margin' ) {\n      var marg = parseFloat(styles[extra + side]);\n      if (!isNaN(marg)) {\n        val += marg;\n      }\n    }\n    // dump('val1', val);\n\n    if ( isBorderBox ) {\n      // border-box includes padding, so remove it if we want content\n      if ( extra === 'content' ) {\n        var padd = parseFloat(styles['padding' + side]);\n        if (!isNaN(padd)) {\n          val -= padd;\n          // dump('val2', val);\n        }\n      }\n\n      // at this point, extra isn't border nor margin, so remove border\n      if ( extra !== 'margin' ) {\n        var bordermarg = parseFloat(styles['border' + side + 'Width']);\n        if (!isNaN(bordermarg)) {\n          val -= bordermarg;\n          // dump('val3', val);\n        }\n      }\n    }\n    else {\n      // at this point, extra isn't content, so add padding\n      var nocontentPad = parseFloat(styles['padding' + side]);\n      if (!isNaN(nocontentPad)) {\n        val += nocontentPad;\n        // dump('val4', val);\n      }\n\n      // at this point, extra isn't content nor padding, so add border\n      if ( extra !== 'padding') {\n        var nocontentnopad = parseFloat(styles['border' + side + 'Width']);\n        if (!isNaN(nocontentnopad)) {\n          val += nocontentnopad;\n          // dump('val5', val);\n        }\n      }\n    }\n  }\n\n  // dump('augVal', val);\n\n  return val;\n}\n\nfunction getWidthOrHeight( elem, name, extra ) {\n  // Start with offset property, which is equivalent to the border-box value\n  var valueIsBorderBox = true,\n          val, // = name === 'width' ? elem.offsetWidth : elem.offsetHeight,\n          styles = getStyles(elem),\n          isBorderBox = styles['boxSizing'] === 'border-box';\n\n  // some non-html elements return undefined for offsetWidth, so check for null/undefined\n  // svg - https://bugzilla.mozilla.org/show_bug.cgi?id=649285\n  // MathML - https://bugzilla.mozilla.org/show_bug.cgi?id=491668\n  if ( val <= 0 || val == null ) {\n    // Fall back to computed then uncomputed css if necessary\n    val = styles[name];\n    if ( val < 0 || val == null ) {\n      val = elem.style[ name ];\n    }\n\n    // Computed unit is not pixels. Stop here and return.\n    if ( rnumnonpx.test(val) ) {\n      return val;\n    }\n\n    // we need the check for style in case a browser which returns unreliable values\n    // for getComputedStyle silently falls back to the reliable elem.style\n    valueIsBorderBox = isBorderBox &&\n            ( true || val === elem.style[ name ] ); // use 'true' instead of 'support.boxSizingReliable()'\n\n    // Normalize \"\", auto, and prepare for extra\n    val = parseFloat( val ) || 0;\n  }\n\n  // use the active box-sizing model to add/subtract irrelevant styles\n  var ret = ( val +\n    augmentWidthOrHeight(\n      elem,\n      name,\n      extra || ( isBorderBox ? \"border\" : \"content\" ),\n      valueIsBorderBox,\n      styles\n    )\n  );\n\n  // dump('ret', ret, val);\n  return ret;\n}\n\nfunction getLineHeight(elm) {\n  elm = angular.element(elm)[0];\n  var parent = elm.parentElement;\n\n  if (!parent) {\n    parent = document.getElementsByTagName('body')[0];\n  }\n\n  return parseInt( getStyles(parent).fontSize ) || parseInt( getStyles(elm).fontSize ) || 16;\n}\n\nvar uid = ['0', '0', '0', '0'];\nvar uidPrefix = 'uiGrid-';\n\n/**\n *  @ngdoc service\n *  @name ui.grid.service:GridUtil\n *\n *  @description Grid utility functions\n */\nmodule.service('gridUtil', ['$log', '$window', '$document', '$http', '$templateCache', '$timeout', '$interval', '$injector', '$q', '$interpolate', 'uiGridConstants',\n  function ($log, $window, $document, $http, $templateCache, $timeout, $interval, $injector, $q, $interpolate, uiGridConstants) {\n  var s = {\n\n    augmentWidthOrHeight: augmentWidthOrHeight,\n\n    getStyles: getStyles,\n\n    /**\n     * @ngdoc method\n     * @name createBoundedWrapper\n     * @methodOf ui.grid.service:GridUtil\n     *\n     * @param {object} Object to bind 'this' to\n     * @param {method} Method to bind\n     * @returns {Function} The wrapper that performs the binding\n     *\n     * @description\n     * Binds given method to given object.\n     *\n     * By means of a wrapper, ensures that ``method`` is always bound to\n     * ``object`` regardless of its calling environment.\n     * Iow, inside ``method``, ``this`` always points to ``object``.\n     *\n     * See http://alistapart.com/article/getoutbindingsituations\n     *\n     */\n    createBoundedWrapper: function(object, method) {\n        return function() {\n            return method.apply(object, arguments);\n        };\n    },\n\n\n    /**\n     * @ngdoc method\n     * @name readableColumnName\n     * @methodOf ui.grid.service:GridUtil\n     *\n     * @param {string} columnName Column name as a string\n     * @returns {string} Column name appropriately capitalized and split apart\n     *\n       @example\n       <example module=\"app\">\n        <file name=\"app.js\">\n          var app = angular.module('app', ['ui.grid']);\n\n          app.controller('MainCtrl', ['$scope', 'gridUtil', function ($scope, gridUtil) {\n            $scope.name = 'firstName';\n            $scope.columnName = function(name) {\n              return gridUtil.readableColumnName(name);\n            };\n          }]);\n        </file>\n        <file name=\"index.html\">\n          <div ng-controller=\"MainCtrl\">\n            <strong>Column name:</strong> <input ng-model=\"name\" />\n            <br>\n            <strong>Output:</strong> <span ng-bind=\"columnName(name)\"></span>\n          </div>\n        </file>\n      </example>\n     */\n    readableColumnName: function (columnName) {\n      // Convert underscores to spaces\n      if (typeof(columnName) === 'undefined' || columnName === undefined || columnName === null) { return columnName; }\n\n      if (typeof(columnName) !== 'string') {\n        columnName = String(columnName);\n      }\n\n      return columnName.replace(/_+/g, ' ')\n        // Replace a completely all-capsed word with a first-letter-capitalized version\n        .replace(/^[A-Z]+$/, function (match) {\n          return angular.lowercase(angular.uppercase(match.charAt(0)) + match.slice(1));\n        })\n        // Capitalize the first letter of words\n        .replace(/([\\w\\u00C0-\\u017F]+)/g, function (match) {\n          return angular.uppercase(match.charAt(0)) + match.slice(1);\n        })\n        // Put a space in between words that have partial capilizations (i.e. 'firstName' becomes 'First Name')\n        // .replace(/([A-Z]|[A-Z]\\w+)([A-Z])/g, \"$1 $2\");\n        // .replace(/(\\w+?|\\w)([A-Z])/g, \"$1 $2\");\n        .replace(/(\\w+?(?=[A-Z]))/g, '$1 ');\n    },\n\n    /**\n     * @ngdoc method\n     * @name getColumnsFromData\n     * @methodOf ui.grid.service:GridUtil\n     * @description Return a list of column names, given a data set\n     *\n     * @param {string} data Data array for grid\n     * @returns {Object} Column definitions with field accessor and column name\n     *\n     * @example\n       <pre>\n         var data = [\n           { firstName: 'Bob', lastName: 'Jones' },\n           { firstName: 'Frank', lastName: 'Smith' }\n         ];\n\n         var columnDefs = GridUtil.getColumnsFromData(data, excludeProperties);\n\n         columnDefs == [\n          {\n            field: 'firstName',\n            name: 'First Name'\n          },\n          {\n            field: 'lastName',\n            name: 'Last Name'\n          }\n         ];\n       </pre>\n     */\n    getColumnsFromData: function (data, excludeProperties) {\n      var columnDefs = [];\n\n      if (!data || typeof(data[0]) === 'undefined' || data[0] === undefined) { return []; }\n      if (angular.isUndefined(excludeProperties)) { excludeProperties = []; }\n\n      var item = data[0];\n\n      angular.forEach(item,function (prop, propName) {\n        if ( excludeProperties.indexOf(propName) === -1){\n          columnDefs.push({\n            name: propName\n          });\n        }\n      });\n\n      return columnDefs;\n    },\n\n    /**\n     * @ngdoc method\n     * @name newId\n     * @methodOf ui.grid.service:GridUtil\n     * @description Return a unique ID string\n     *\n     * @returns {string} Unique string\n     *\n     * @example\n       <pre>\n        var id = GridUtil.newId();\n\n        # 1387305700482;\n       </pre>\n     */\n    newId: (function() {\n      var seedId = new Date().getTime();\n      return function() {\n          return seedId += 1;\n      };\n    })(),\n\n\n    /**\n     * @ngdoc method\n     * @name getTemplate\n     * @methodOf ui.grid.service:GridUtil\n     * @description Get's template from cache / element / url\n     *\n     * @param {string|element|promise} Either a string representing the template id, a string representing the template url,\n     *   an jQuery/Angualr element, or a promise that returns the template contents to use.\n     * @returns {object} a promise resolving to template contents\n     *\n     * @example\n     <pre>\n     GridUtil.getTemplate(url).then(function (contents) {\n          alert(contents);\n        })\n     </pre>\n     */\n    getTemplate: function (template) {\n      // Try to fetch the template out of the templateCache\n      if ($templateCache.get(template)) {\n        return s.postProcessTemplate($templateCache.get(template));\n      }\n\n      // See if the template is itself a promise\n      if (template.hasOwnProperty('then')) {\n        return template.then(s.postProcessTemplate);\n      }\n\n      // If the template is an element, return the element\n      try {\n        if (angular.element(template).length > 0) {\n          return $q.when(template).then(s.postProcessTemplate);\n        }\n      }\n      catch (err){\n        //do nothing; not valid html\n      }\n\n      s.logDebug('fetching url', template);\n\n      // Default to trying to fetch the template as a url with $http\n      return $http({ method: 'GET', url: template})\n        .then(\n          function (result) {\n            var templateHtml = result.data.trim();\n            //put in templateCache for next call\n            $templateCache.put(template, templateHtml);\n            return templateHtml;\n          },\n          function (err) {\n            throw new Error(\"Could not get template \" + template + \": \" + err);\n          }\n        )\n        .then(s.postProcessTemplate);\n    },\n\n    //\n    postProcessTemplate: function (template) {\n      var startSym = $interpolate.startSymbol(),\n          endSym = $interpolate.endSymbol();\n\n      // If either of the interpolation symbols have been changed, we need to alter this template\n      if (startSym !== '{{' || endSym !== '}}') {\n        template = template.replace(/\\{\\{/g, startSym);\n        template = template.replace(/\\}\\}/g, endSym);\n      }\n\n      return $q.when(template);\n    },\n\n    /**\n     * @ngdoc method\n     * @name guessType\n     * @methodOf ui.grid.service:GridUtil\n     * @description guesses the type of an argument\n     *\n     * @param {string/number/bool/object} item variable to examine\n     * @returns {string} one of the following\n     * - 'string'\n     * - 'boolean'\n     * - 'number'\n     * - 'date'\n     * - 'object'\n     */\n    guessType : function (item) {\n      var itemType = typeof(item);\n\n      // Check for numbers and booleans\n      switch (itemType) {\n        case \"number\":\n        case \"boolean\":\n        case \"string\":\n          return itemType;\n        default:\n          if (angular.isDate(item)) {\n            return \"date\";\n          }\n          return \"object\";\n      }\n    },\n\n\n  /**\n    * @ngdoc method\n    * @name elementWidth\n    * @methodOf ui.grid.service:GridUtil\n    *\n    * @param {element} element DOM element\n    * @param {string} [extra] Optional modifier for calculation. Use 'margin' to account for margins on element\n    *\n    * @returns {number} Element width in pixels, accounting for any borders, etc.\n    */\n    elementWidth: function (elem) {\n\n    },\n\n    /**\n    * @ngdoc method\n    * @name elementHeight\n    * @methodOf ui.grid.service:GridUtil\n    *\n    * @param {element} element DOM element\n    * @param {string} [extra] Optional modifier for calculation. Use 'margin' to account for margins on element\n    *\n    * @returns {number} Element height in pixels, accounting for any borders, etc.\n    */\n    elementHeight: function (elem) {\n\n    },\n\n    // Thanks to http://stackoverflow.com/a/13382873/888165\n    getScrollbarWidth: function() {\n        var outer = document.createElement(\"div\");\n        outer.style.visibility = \"hidden\";\n        outer.style.width = \"100px\";\n        outer.style.msOverflowStyle = \"scrollbar\"; // needed for WinJS apps\n\n        document.body.appendChild(outer);\n\n        var widthNoScroll = outer.offsetWidth;\n        // force scrollbars\n        outer.style.overflow = \"scroll\";\n\n        // add innerdiv\n        var inner = document.createElement(\"div\");\n        inner.style.width = \"100%\";\n        outer.appendChild(inner);\n\n        var widthWithScroll = inner.offsetWidth;\n\n        // remove divs\n        outer.parentNode.removeChild(outer);\n\n        return widthNoScroll - widthWithScroll;\n    },\n\n    swap: function( elem, options, callback, args ) {\n      var ret, name,\n              old = {};\n\n      // Remember the old values, and insert the new ones\n      for ( name in options ) {\n        old[ name ] = elem.style[ name ];\n        elem.style[ name ] = options[ name ];\n      }\n\n      ret = callback.apply( elem, args || [] );\n\n      // Revert the old values\n      for ( name in options ) {\n        elem.style[ name ] = old[ name ];\n      }\n\n      return ret;\n    },\n\n    fakeElement: function( elem, options, callback, args ) {\n      var ret, name,\n          newElement = angular.element(elem).clone()[0];\n\n      for ( name in options ) {\n        newElement.style[ name ] = options[ name ];\n      }\n\n      angular.element(document.body).append(newElement);\n\n      ret = callback.call( newElement, newElement );\n\n      angular.element(newElement).remove();\n\n      return ret;\n    },\n\n    /**\n    * @ngdoc method\n    * @name normalizeWheelEvent\n    * @methodOf ui.grid.service:GridUtil\n    *\n    * @param {event} event A mouse wheel event\n    *\n    * @returns {event} A normalized event\n    *\n    * @description\n    * Given an event from this list:\n    *\n    * `wheel, mousewheel, DomMouseScroll, MozMousePixelScroll`\n    *\n    * \"normalize\" it\n    * so that it stays consistent no matter what browser it comes from (i.e. scale it correctly and make sure the direction is right.)\n    */\n    normalizeWheelEvent: function (event) {\n      // var toFix = ['wheel', 'mousewheel', 'DOMMouseScroll', 'MozMousePixelScroll'];\n      // var toBind = 'onwheel' in document || document.documentMode >= 9 ? ['wheel'] : ['mousewheel', 'DomMouseScroll', 'MozMousePixelScroll'];\n      var lowestDelta, lowestDeltaXY;\n\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          absDeltaXY = 0,\n          fn;\n\n      // event = $.event.fix(orgEvent);\n      // event.type = 'mousewheel';\n\n      // NOTE: jQuery masks the event and stores it in the event as originalEvent\n      if (orgEvent.originalEvent) {\n        orgEvent = orgEvent.originalEvent;\n      }\n\n      // Old school scrollwheel delta\n      if ( orgEvent.wheelDelta ) { delta = orgEvent.wheelDelta; }\n      if ( orgEvent.detail )     { delta = orgEvent.detail * -1; }\n\n      // At a minimum, setup the deltaY to be delta\n      deltaY = delta;\n\n      // Firefox < 17 related to DOMMouseScroll event\n      if ( orgEvent.axis !== undefined && orgEvent.axis === orgEvent.HORIZONTAL_AXIS ) {\n          deltaY = 0;\n          deltaX = delta * -1;\n      }\n\n      // New school wheel delta (wheel event)\n      if ( orgEvent.deltaY ) {\n          deltaY = orgEvent.deltaY * -1;\n          delta  = deltaY;\n      }\n      if ( orgEvent.deltaX ) {\n          deltaX = orgEvent.deltaX;\n          delta  = deltaX * -1;\n      }\n\n      // Webkit\n      if ( orgEvent.wheelDeltaY !== undefined ) { deltaY = orgEvent.wheelDeltaY; }\n      if ( orgEvent.wheelDeltaX !== undefined ) { deltaX = orgEvent.wheelDeltaX; }\n\n      // Look for lowest delta to normalize the delta values\n      absDelta = Math.abs(delta);\n      if ( !lowestDelta || absDelta < lowestDelta ) { lowestDelta = absDelta; }\n      absDeltaXY = Math.max(Math.abs(deltaY), Math.abs(deltaX));\n      if ( !lowestDeltaXY || absDeltaXY < lowestDeltaXY ) { lowestDeltaXY = absDeltaXY; }\n\n      // Get a whole value for the deltas\n      fn     = delta > 0 ? 'floor' : 'ceil';\n      delta  = Math[fn](delta  / lowestDelta);\n      deltaX = Math[fn](deltaX / lowestDeltaXY);\n      deltaY = Math[fn](deltaY / lowestDeltaXY);\n\n      return {\n        delta: delta,\n        deltaX: deltaX,\n        deltaY: deltaY\n      };\n    },\n\n    // Stolen from Modernizr\n    // TODO: make this, and everythign that flows from it, robust\n    //http://www.stucox.com/blog/you-cant-detect-a-touchscreen/\n    isTouchEnabled: function() {\n      var bool;\n\n      if (('ontouchstart' in $window) || $window.DocumentTouch && $document instanceof DocumentTouch) {\n        bool = true;\n      }\n\n      return bool;\n    },\n\n    isNullOrUndefined: function(obj) {\n      if (obj === undefined || obj === null) {\n        return true;\n      }\n      return false;\n    },\n\n    endsWith: function(str, suffix) {\n      if (!str || !suffix || typeof str !== \"string\") {\n        return false;\n      }\n      return str.indexOf(suffix, str.length - suffix.length) !== -1;\n    },\n\n    arrayContainsObjectWithProperty: function(array, propertyName, propertyValue) {\n        var found = false;\n        angular.forEach(array, function (object) {\n            if (object[propertyName] === propertyValue) {\n                found = true;\n            }\n        });\n        return found;\n    },\n\n    //// Shim requestAnimationFrame\n    //requestAnimationFrame: $window.requestAnimationFrame && $window.requestAnimationFrame.bind($window) ||\n    //                       $window.webkitRequestAnimationFrame && $window.webkitRequestAnimationFrame.bind($window) ||\n    //                       function(fn) {\n    //                         return $timeout(fn, 10, false);\n    //                       },\n\n    numericAndNullSort: function (a, b) {\n      if (a === null) { return 1; }\n      if (b === null) { return -1; }\n      if (a === null && b === null) { return 0; }\n      return a - b;\n    },\n\n    // Disable ngAnimate animations on an element\n    disableAnimations: function (element) {\n      var $animate;\n      try {\n        $animate = $injector.get('$animate');\n        // See: http://brianhann.com/angular-1-4-breaking-changes-to-be-aware-of/#animate\n        if (angular.version.major > 1 || (angular.version.major === 1 && angular.version.minor >= 4)) {\n          $animate.enabled(element, false);\n        } else {\n          $animate.enabled(false, element);\n        }\n      }\n      catch (e) {}\n    },\n\n    enableAnimations: function (element) {\n      var $animate;\n      try {\n        $animate = $injector.get('$animate');\n        // See: http://brianhann.com/angular-1-4-breaking-changes-to-be-aware-of/#animate\n        if (angular.version.major > 1 || (angular.version.major === 1 && angular.version.minor >= 4)) {\n          $animate.enabled(element, true);\n        } else {\n          $animate.enabled(true, element);\n        }\n        return $animate;\n      }\n      catch (e) {}\n    },\n\n    // Blatantly stolen from Angular as it isn't exposed (yet. 2.0 maybe?)\n    nextUid: function nextUid() {\n      var index = uid.length;\n      var digit;\n\n      while (index) {\n        index--;\n        digit = uid[index].charCodeAt(0);\n        if (digit === 57 /*'9'*/) {\n          uid[index] = 'A';\n          return uidPrefix + uid.join('');\n        }\n        if (digit === 90  /*'Z'*/) {\n          uid[index] = '0';\n        } else {\n          uid[index] = String.fromCharCode(digit + 1);\n          return uidPrefix + uid.join('');\n        }\n      }\n      uid.unshift('0');\n\n      return uidPrefix + uid.join('');\n    },\n\n    // Blatantly stolen from Angular as it isn't exposed (yet. 2.0 maybe?)\n    hashKey: function hashKey(obj) {\n      var objType = typeof obj,\n          key;\n\n      if (objType === 'object' && obj !== null) {\n        if (typeof (key = obj.$$hashKey) === 'function') {\n          // must invoke on object to keep the right this\n          key = obj.$$hashKey();\n        }\n        else if (typeof(obj.$$hashKey) !== 'undefined' && obj.$$hashKey) {\n          key = obj.$$hashKey;\n        }\n        else if (key === undefined) {\n          key = obj.$$hashKey = s.nextUid();\n        }\n      }\n      else {\n        key = obj;\n      }\n\n      return objType + ':' + key;\n    },\n\n    resetUids: function () {\n      uid = ['0', '0', '0'];\n    },\n\n    /**\n     * @ngdoc method\n     * @methodOf ui.grid.service:GridUtil\n     * @name logError\n     * @description wraps the $log method, allowing us to choose different\n     * treatment within ui-grid if we so desired.  At present we only log\n     * error messages if uiGridConstants.LOG_ERROR_MESSAGES is set to true\n     * @param {string} logMessage message to be logged to the console\n     *\n     */\n    logError: function( logMessage ){\n      if ( uiGridConstants.LOG_ERROR_MESSAGES ){\n        $log.error( logMessage );\n      }\n    },\n\n    /**\n     * @ngdoc method\n     * @methodOf ui.grid.service:GridUtil\n     * @name logWarn\n     * @description wraps the $log method, allowing us to choose different\n     * treatment within ui-grid if we so desired.  At present we only log\n     * warning messages if uiGridConstants.LOG_WARN_MESSAGES is set to true\n     * @param {string} logMessage message to be logged to the console\n     *\n     */\n    logWarn: function( logMessage ){\n      if ( uiGridConstants.LOG_WARN_MESSAGES ){\n        $log.warn( logMessage );\n      }\n    },\n\n    /**\n     * @ngdoc method\n     * @methodOf ui.grid.service:GridUtil\n     * @name logDebug\n     * @description wraps the $log method, allowing us to choose different\n     * treatment within ui-grid if we so desired.  At present we only log\n     * debug messages if uiGridConstants.LOG_DEBUG_MESSAGES is set to true\n     *\n     */\n    logDebug: function() {\n      if ( uiGridConstants.LOG_DEBUG_MESSAGES ){\n        $log.debug.apply($log, arguments);\n      }\n    }\n\n  };\n\n  /**\n   * @ngdoc object\n   * @name focus\n   * @propertyOf ui.grid.service:GridUtil\n   * @description Provies a set of methods to set the document focus inside the grid.\n   * See {@link ui.grid.service:GridUtil.focus} for more information.\n   */\n\n  /**\n   * @ngdoc object\n   * @name ui.grid.service:GridUtil.focus\n   * @description Provies a set of methods to set the document focus inside the grid.\n   * Timeouts are utilized to ensure that the focus is invoked after any other event has been triggered.\n   * e.g. click events that need to run before the focus or\n   * inputs elements that are in a disabled state but are enabled when those events\n   * are triggered.\n   */\n  s.focus = {\n    queue: [],\n    //http://stackoverflow.com/questions/25596399/set-element-focus-in-angular-way\n    /**\n     * @ngdoc method\n     * @methodOf ui.grid.service:GridUtil.focus\n     * @name byId\n     * @description Sets the focus of the document to the given id value.\n     * If provided with the grid object it will automatically append the grid id.\n     * This is done to encourage unique dom id's as it allows for multiple grids on a\n     * page.\n     * @param {String} id the id of the dom element to set the focus on\n     * @param {Object=} Grid the grid object for this grid instance. See: {@link ui.grid.class:Grid}\n     * @param {Number} Grid.id the unique id for this grid. Already set on an initialized grid object.\n     * @returns {Promise} The `$timeout` promise that will be resolved once focus is set. If another focus is requested before this request is evaluated.\n     * then the promise will fail with the `'canceled'` reason.\n     */\n    byId: function (id, Grid) {\n      this._purgeQueue();\n      var promise = $timeout(function() {\n        var elementID = (Grid && Grid.id ? Grid.id + '-' : '') + id;\n        var element = $window.document.getElementById(elementID);\n        if (element) {\n          element.focus();\n        } else {\n          s.logWarn('[focus.byId] Element id ' + elementID + ' was not found.');\n        }\n      });\n      this.queue.push(promise);\n      return promise;\n    },\n\n    /**\n     * @ngdoc method\n     * @methodOf ui.grid.service:GridUtil.focus\n     * @name byElement\n     * @description Sets the focus of the document to the given dom element.\n     * @param {(element|angular.element)} element the DOM element to set the focus on\n     * @returns {Promise} The `$timeout` promise that will be resolved once focus is set. If another focus is requested before this request is evaluated.\n     * then the promise will fail with the `'canceled'` reason.\n     */\n    byElement: function(element){\n      if (!angular.isElement(element)){\n        s.logWarn(\"Trying to focus on an element that isn\\'t an element.\");\n        return $q.reject('not-element');\n      }\n      element = angular.element(element);\n      this._purgeQueue();\n      var promise = $timeout(function(){\n        if (element){\n          element[0].focus();\n        }\n      });\n      this.queue.push(promise);\n      return promise;\n    },\n    /**\n     * @ngdoc method\n     * @methodOf ui.grid.service:GridUtil.focus\n     * @name bySelector\n     * @description Sets the focus of the document to the given dom element.\n     * @param {(element|angular.element)} parentElement the parent/ancestor of the dom element that you are selecting using the query selector\n     * @param {String} querySelector finds the dom element using the {@link http://www.w3schools.com/jsref/met_document_queryselector.asp querySelector}\n     * @param {boolean} [aSync=false] If true then the selector will be querried inside of a timeout. Otherwise the selector will be querried imidately\n     * then the focus will be called.\n     * @returns {Promise} The `$timeout` promise that will be resolved once focus is set. If another focus is requested before this request is evaluated.\n     * then the promise will fail with the `'canceled'` reason.\n     */\n    bySelector: function(parentElement, querySelector, aSync){\n      var self = this;\n      if (!angular.isElement(parentElement)){\n        throw new Error(\"The parent element is not an element.\");\n      }\n      // Ensure that this is an angular element.\n      // It is fine if this is already an angular element.\n      parentElement = angular.element(parentElement);\n      var focusBySelector = function(){\n        var element = parentElement[0].querySelector(querySelector);\n        return self.byElement(element);\n      };\n      this._purgeQueue();\n      if (aSync){ //Do this asynchronysly\n        var promise = $timeout(focusBySelector);\n        this.queue.push($timeout(focusBySelector));\n        return promise;\n      } else {\n        return focusBySelector();\n      }\n    },\n    _purgeQueue: function(){\n      this.queue.forEach(function(element){\n        $timeout.cancel(element);\n      });\n      this.queue = [];\n    }\n  };\n\n\n  ['width', 'height'].forEach(function (name) {\n    var capsName = angular.uppercase(name.charAt(0)) + name.substr(1);\n    s['element' + capsName] = function (elem, extra) {\n      var e = elem;\n      if (e && typeof(e.length) !== 'undefined' && e.length) {\n        e = elem[0];\n      }\n\n      if (e) {\n        var styles = getStyles(e);\n        return e.offsetWidth === 0 && rdisplayswap.test(styles.display) ?\n                  s.swap(e, cssShow, function() {\n                    return getWidthOrHeight(e, name, extra );\n                  }) :\n                  getWidthOrHeight( e, name, extra );\n      }\n      else {\n        return null;\n      }\n    };\n\n    s['outerElement' + capsName] = function (elem, margin) {\n      return elem ? s['element' + capsName].call(this, elem, margin ? 'margin' : 'border') : null;\n    };\n  });\n\n  // http://stackoverflow.com/a/24107550/888165\n  s.closestElm = function closestElm(el, selector) {\n    if (typeof(el.length) !== 'undefined' && el.length) {\n      el = el[0];\n    }\n\n    var matchesFn;\n\n    // find vendor prefix\n    ['matches','webkitMatchesSelector','mozMatchesSelector','msMatchesSelector','oMatchesSelector'].some(function(fn) {\n        if (typeof document.body[fn] === 'function') {\n            matchesFn = fn;\n            return true;\n        }\n        return false;\n    });\n\n    // traverse parents\n    var parent;\n    while (el !== null) {\n      parent = el.parentElement;\n      if (parent !== null && parent[matchesFn](selector)) {\n          return parent;\n      }\n      el = parent;\n    }\n\n    return null;\n  };\n\n  s.type = function (obj) {\n    var text = Function.prototype.toString.call(obj.constructor);\n    return text.match(/function (.*?)\\(/)[1];\n  };\n\n  s.getBorderSize = function getBorderSize(elem, borderType) {\n    if (typeof(elem.length) !== 'undefined' && elem.length) {\n      elem = elem[0];\n    }\n\n    var styles = getStyles(elem);\n\n    // If a specific border is supplied, like 'top', read the 'borderTop' style property\n    if (borderType) {\n      borderType = 'border' + borderType.charAt(0).toUpperCase() + borderType.slice(1);\n    }\n    else {\n      borderType = 'border';\n    }\n\n    borderType += 'Width';\n\n    var val = parseInt(styles[borderType], 10);\n\n    if (isNaN(val)) {\n      return 0;\n    }\n    else {\n      return val;\n    }\n  };\n\n  // http://stackoverflow.com/a/22948274/888165\n  // TODO: Opera? Mobile?\n  s.detectBrowser = function detectBrowser() {\n    var userAgent = $window.navigator.userAgent;\n\n    var browsers = {chrome: /chrome/i, safari: /safari/i, firefox: /firefox/i, ie: /internet explorer|trident\\//i};\n\n    for (var key in browsers) {\n      if (browsers[key].test(userAgent)) {\n        return key;\n      }\n    }\n\n    return 'unknown';\n  };\n\n  // Borrowed from https://github.com/othree/jquery.rtl-scroll-type\n  // Determine the scroll \"type\" this browser is using for RTL\n  s.rtlScrollType = function rtlScrollType() {\n    if (rtlScrollType.type) {\n      return rtlScrollType.type;\n    }\n\n    var definer = angular.element('<div dir=\"rtl\" style=\"font-size: 14px; width: 1px; height: 1px; position: absolute; top: -1000px; overflow: scroll\">A</div>')[0],\n        type = 'reverse';\n\n    document.body.appendChild(definer);\n\n    if (definer.scrollLeft > 0) {\n      type = 'default';\n    }\n    else {\n      definer.scrollLeft = 1;\n      if (definer.scrollLeft === 0) {\n        type = 'negative';\n      }\n    }\n\n    angular.element(definer).remove();\n    rtlScrollType.type = type;\n\n    return type;\n  };\n\n    /**\n     * @ngdoc method\n     * @name normalizeScrollLeft\n     * @methodOf ui.grid.service:GridUtil\n     *\n     * @param {element} element The element to get the `scrollLeft` from.\n     * @param {grid} grid -  grid used to normalize (uses the rtl property)\n     *\n     * @returns {number} A normalized scrollLeft value for the current browser.\n     *\n     * @description\n     * Browsers currently handle RTL in different ways, resulting in inconsistent scrollLeft values. This method normalizes them\n     */\n  s.normalizeScrollLeft = function normalizeScrollLeft(element, grid) {\n    if (typeof(element.length) !== 'undefined' && element.length) {\n      element = element[0];\n    }\n\n    var scrollLeft = element.scrollLeft;\n\n    if (grid.isRTL()) {\n      switch (s.rtlScrollType()) {\n        case 'default':\n          return element.scrollWidth - scrollLeft - element.clientWidth;\n        case 'negative':\n          return Math.abs(scrollLeft);\n        case 'reverse':\n          return scrollLeft;\n      }\n    }\n\n    return scrollLeft;\n  };\n\n  /**\n  * @ngdoc method\n  * @name denormalizeScrollLeft\n  * @methodOf ui.grid.service:GridUtil\n  *\n  * @param {element} element The element to normalize the `scrollLeft` value for\n  * @param {number} scrollLeft The `scrollLeft` value to denormalize.\n  * @param {grid} grid The grid that owns the scroll event.\n  *\n  * @returns {number} A normalized scrollLeft value for the current browser.\n  *\n  * @description\n  * Browsers currently handle RTL in different ways, resulting in inconsistent scrollLeft values. This method denormalizes a value for the current browser.\n  */\n  s.denormalizeScrollLeft = function denormalizeScrollLeft(element, scrollLeft, grid) {\n    if (typeof(element.length) !== 'undefined' && element.length) {\n      element = element[0];\n    }\n\n    if (grid.isRTL()) {\n      switch (s.rtlScrollType()) {\n        case 'default':\n          // Get the max scroll for the element\n          var maxScrollLeft = element.scrollWidth - element.clientWidth;\n\n          // Subtract the current scroll amount from the max scroll\n          return maxScrollLeft - scrollLeft;\n        case 'negative':\n          return scrollLeft * -1;\n        case 'reverse':\n          return scrollLeft;\n      }\n    }\n\n    return scrollLeft;\n  };\n\n    /**\n     * @ngdoc method\n     * @name preEval\n     * @methodOf ui.grid.service:GridUtil\n     *\n     * @param {string} path Path to evaluate\n     *\n     * @returns {string} A path that is normalized.\n     *\n     * @description\n     * Takes a field path and converts it to bracket notation to allow for special characters in path\n     * @example\n     * <pre>\n     * gridUtil.preEval('property') == 'property'\n     * gridUtil.preEval('nested.deep.prop-erty') = \"nested['deep']['prop-erty']\"\n     * </pre>\n     */\n  s.preEval = function (path) {\n    var m = uiGridConstants.BRACKET_REGEXP.exec(path);\n    if (m) {\n      return (m[1] ? s.preEval(m[1]) : m[1]) + m[2] + (m[3] ? s.preEval(m[3]) : m[3]);\n    } else {\n      path = path.replace(uiGridConstants.APOS_REGEXP, '\\\\\\'');\n      var parts = path.split(uiGridConstants.DOT_REGEXP);\n      var preparsed = [parts.shift()];    // first item must be var notation, thus skip\n      angular.forEach(parts, function (part) {\n        preparsed.push(part.replace(uiGridConstants.FUNC_REGEXP, '\\']$1'));\n      });\n      return preparsed.join('[\\'');\n    }\n  };\n\n  /**\n   * @ngdoc method\n   * @name debounce\n   * @methodOf ui.grid.service:GridUtil\n   *\n   * @param {function} func function to debounce\n   * @param {number} wait milliseconds to delay\n   * @param {boolean} immediate execute before delay\n   *\n   * @returns {function} A function that can be executed as debounced function\n   *\n   * @description\n   * Copied from https://github.com/shahata/angular-debounce\n   * Takes a function, decorates it to execute only 1 time after multiple calls, and returns the decorated function\n   * @example\n   * <pre>\n   * var debouncedFunc =  gridUtil.debounce(function(){alert('debounced');}, 500);\n   * debouncedFunc();\n   * debouncedFunc();\n   * debouncedFunc();\n   * </pre>\n   */\n  s.debounce =  function (func, wait, immediate) {\n    var timeout, args, context, result;\n    function debounce() {\n      /* jshint validthis:true */\n      context = this;\n      args = arguments;\n      var later = function () {\n        timeout = null;\n        if (!immediate) {\n          result = func.apply(context, args);\n        }\n      };\n      var callNow = immediate && !timeout;\n      if (timeout) {\n        $timeout.cancel(timeout);\n      }\n      timeout = $timeout(later, wait);\n      if (callNow) {\n        result = func.apply(context, args);\n      }\n      return result;\n    }\n    debounce.cancel = function () {\n      $timeout.cancel(timeout);\n      timeout = null;\n    };\n    return debounce;\n  };\n\n  /**\n   * @ngdoc method\n   * @name throttle\n   * @methodOf ui.grid.service:GridUtil\n   *\n   * @param {function} func function to throttle\n   * @param {number} wait milliseconds to delay after first trigger\n   * @param {Object} params to use in throttle.\n   *\n   * @returns {function} A function that can be executed as throttled function\n   *\n   * @description\n   * Adapted from debounce function (above)\n   * Potential keys for Params Object are:\n   *    trailing (bool) - whether to trigger after throttle time ends if called multiple times\n   * Updated to use $interval rather than $timeout, as protractor (e2e tests) is able to work with $interval,\n   * but not with $timeout\n   *\n   * Note that when using throttle, you need to use throttle to create a new function upfront, then use the function\n   * return from that call each time you need to call throttle.  If you call throttle itself repeatedly, the lastCall\n   * variable will get overwritten and the throttling won't work\n   *\n   * @example\n   * <pre>\n   * var throttledFunc =  gridUtil.throttle(function(){console.log('throttled');}, 500, {trailing: true});\n   * throttledFunc(); //=> logs throttled\n   * throttledFunc(); //=> queues attempt to log throttled for ~500ms (since trailing param is truthy)\n   * throttledFunc(); //=> updates arguments to keep most-recent request, but does not do anything else.\n   * </pre>\n   */\n  s.throttle = function(func, wait, options){\n    options = options || {};\n    var lastCall = 0, queued = null, context, args;\n\n    function runFunc(endDate){\n      lastCall = +new Date();\n      func.apply(context, args);\n      $interval(function(){ queued = null; }, 0, 1);\n    }\n\n    return function(){\n      /* jshint validthis:true */\n      context = this;\n      args = arguments;\n      if (queued === null){\n        var sinceLast = +new Date() - lastCall;\n        if (sinceLast > wait){\n          runFunc();\n        }\n        else if (options.trailing){\n          queued = $interval(runFunc, wait - sinceLast, 1);\n        }\n      }\n    };\n  };\n\n  s.on = {};\n  s.off = {};\n  s._events = {};\n\n  s.addOff = function (eventName) {\n    s.off[eventName] = function (elm, fn) {\n      var idx = s._events[eventName].indexOf(fn);\n      if (idx > 0) {\n        s._events[eventName].removeAt(idx);\n      }\n    };\n  };\n\n  var mouseWheeltoBind = ( 'onwheel' in document || document.documentMode >= 9 ) ? ['wheel'] : ['mousewheel', 'DomMouseScroll', 'MozMousePixelScroll'],\n      nullLowestDeltaTimeout,\n      lowestDelta;\n\n  s.on.mousewheel = function (elm, fn) {\n    if (!elm || !fn) { return; }\n\n    var $elm = angular.element(elm);\n\n    // Store the line height and page height for this particular element\n    $elm.data('mousewheel-line-height', getLineHeight($elm));\n    $elm.data('mousewheel-page-height', s.elementHeight($elm));\n    if (!$elm.data('mousewheel-callbacks')) { $elm.data('mousewheel-callbacks', {}); }\n\n    var cbs = $elm.data('mousewheel-callbacks');\n    cbs[fn] = (Function.prototype.bind || bindPolyfill).call(mousewheelHandler, $elm[0], fn);\n\n    // Bind all the mousew heel events\n    for ( var i = mouseWheeltoBind.length; i; ) {\n      $elm.on(mouseWheeltoBind[--i], cbs[fn]);\n    }\n  };\n  s.off.mousewheel = function (elm, fn) {\n    var $elm = angular.element(this);\n\n    var cbs = $elm.data('mousewheel-callbacks');\n    var handler = cbs[fn];\n\n    if (handler) {\n      for ( var i = mouseWheeltoBind.length; i; ) {\n        $elm.off(mouseWheeltoBind[--i], handler);\n      }\n    }\n\n    delete cbs[fn];\n\n    if (Object.keys(cbs).length === 0) {\n      $elm.removeData('mousewheel-line-height');\n      $elm.removeData('mousewheel-page-height');\n      $elm.removeData('mousewheel-callbacks');\n    }\n  };\n\n  function mousewheelHandler(fn, event) {\n    var $elm = angular.element(this);\n\n    var delta      = 0,\n        deltaX     = 0,\n        deltaY     = 0,\n        absDelta   = 0,\n        offsetX    = 0,\n        offsetY    = 0;\n\n    // jQuery masks events\n    if (event.originalEvent) { event = event.originalEvent; }\n\n    if ( 'detail'      in event ) { deltaY = event.detail * -1;      }\n    if ( 'wheelDelta'  in event ) { deltaY = event.wheelDelta;       }\n    if ( 'wheelDeltaY' in event ) { deltaY = event.wheelDeltaY;      }\n    if ( 'wheelDeltaX' in event ) { deltaX = event.wheelDeltaX * -1; }\n\n    // Firefox < 17 horizontal scrolling related to DOMMouseScroll event\n    if ( 'axis' in event && event.axis === event.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 event ) {\n      deltaY = event.deltaY * -1;\n      delta  = deltaY;\n    }\n    if ( 'deltaX' in event ) {\n      deltaX = event.deltaX;\n      if ( deltaY === 0 ) { delta  = deltaX * -1; }\n    }\n\n    // No change actually happened, no reason to go any further\n    if ( deltaY === 0 && deltaX === 0 ) { return; }\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 ( event.deltaMode === 1 ) {\n        var lineHeight = $elm.data('mousewheel-line-height');\n        delta  *= lineHeight;\n        deltaY *= lineHeight;\n        deltaX *= lineHeight;\n    }\n    else if ( event.deltaMode === 2 ) {\n        var pageHeight = $elm.data('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(event, absDelta) ) {\n        lowestDelta /= 40;\n      }\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    event.deltaMode = 0;\n\n    // Normalise offsetX and offsetY properties\n    // if ($elm[0].getBoundingClientRect ) {\n    //   var boundingRect = $(elm)[0].getBoundingClientRect();\n    //   offsetX = event.clientX - boundingRect.left;\n    //   offsetY = event.clientY - boundingRect.top;\n    // }\n\n    // event.deltaX = deltaX;\n    // event.deltaY = deltaY;\n    // event.deltaFactor = lowestDelta;\n\n    var newEvent = {\n      originalEvent: event,\n      deltaX: deltaX,\n      deltaY: deltaY,\n      deltaFactor: lowestDelta,\n      preventDefault: function () { event.preventDefault(); }\n    };\n\n    // Clearout lowestDelta after sometime to better\n    // handle multiple device types that give\n    // a different lowestDelta\n    // Ex: trackpad = 3 and mouse wheel = 120\n    if (nullLowestDeltaTimeout) { clearTimeout(nullLowestDeltaTimeout); }\n    nullLowestDeltaTimeout = setTimeout(nullLowestDelta, 200);\n\n    fn.call($elm[0], newEvent);\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 orgEvent.type === 'mousewheel' && absDelta % 120 === 0;\n  }\n\n  return s;\n}]);\n\n// Add 'px' to the end of a number string if it doesn't have it already\nmodule.filter('px', function() {\n  return function(str) {\n    if (str.match(/^[\\d\\.]+$/)) {\n      return str + 'px';\n    }\n    else {\n      return str;\n    }\n  };\n});\n\n})();\n\n(function () {\n  angular.module('ui.grid').config(['$provide', function($provide) {\n    $provide.decorator('i18nService', ['$delegate', function($delegate) {\n      var lang = {\n              aggregate: {\n                  label: 'položky'\n              },\n              groupPanel: {\n                  description: 'Přesuntě záhlaví zde pro vytvoření skupiny dle sloupce.'\n              },\n              search: {\n                  placeholder: 'Hledat...',\n                  showingItems: 'Zobrazuji položky:',\n                  selectedItems: 'Vybrané položky:',\n                  totalItems: 'Celkem položek:',\n                  size: 'Velikost strany:',\n                  first: 'První strana',\n                  next: 'Další strana',\n                  previous: 'Předchozí strana',\n                  last: 'Poslední strana'\n              },\n              menu: {\n                  text: 'Vyberte sloupec:'\n              },\n              sort: {\n                  ascending: 'Seřadit od A-Z',\n                  descending: 'Seřadit od Z-A',\n                  remove: 'Odebrat seřazení'\n              },\n              column: {\n                  hide: 'Schovat sloupec'\n              },\n              aggregation: {\n                  count: 'celkem řádků: ',\n                  sum: 'celkem: ',\n                  avg: 'avg: ',\n                  min: 'min.: ',\n                  max: 'max.: '\n              },\n              pinning: {\n                  pinLeft: 'Zamknout v levo',\n                  pinRight: 'Zamknout v pravo',\n                  unpin: 'Odemknout'\n              },\n              gridMenu: {\n                  columns: 'Sloupce:',\n                  importerTitle: 'Importovat soubor',\n                  exporterAllAsCsv: 'Exportovat všechny data do csv',\n                  exporterVisibleAsCsv: 'Exportovat viditelné data do csv',\n                  exporterSelectedAsCsv: 'Exportovat vybranné data do csv',\n                  exporterAllAsPdf: 'Exportovat všechny data do pdf',\n                  exporterVisibleAsPdf: 'Exportovat viditelné data do pdf',\n                  exporterSelectedAsPdf: 'Exportovat vybranné data do pdf'\n              },\n              importer: {\n                  noHeaders: 'Názvy sloupců se nepodařilo získat, obsahuje soubor záhlaví?',\n                  noObjects: 'Data se nepodařilo zpracovat, obsahuje soubor řádky mimo záhlaví?',\n                  invalidCsv: 'Soubor nelze zpracovat, jedná se CSV?',\n                  invalidJson: 'Soubor nelze zpracovat, je to JSON?',\n                  jsonNotArray: 'Soubor musí obsahovat json. Ukončuji..'\n              },\n              pagination: {\n                  sizes: 'položek na stránku',\n                  totalItems: 'položek'\n              },\n              grouping: {\n                  group: 'Seskupit',\n                  ungroup: 'Odebrat seskupení',\n                  aggregate_count: 'Agregace: Count',\n                  aggregate_sum: 'Agregace: Sum',\n                  aggregate_max: 'Agregace: Max',\n                  aggregate_min: 'Agregace: Min',\n                  aggregate_avg: 'Agregace: Avg',\n                  aggregate_remove: 'Agregace: Odebrat'\n              }\n          };\n\n          // support varianty of different czech keys.\n          $delegate.add('cs', lang);\n          $delegate.add('cz', lang);\n          $delegate.add('cs-cz', lang);\n          $delegate.add('cs-CZ', lang);\n      return $delegate;\n    }]);\n  }]);\n})();\n\n(function(){\n  angular.module('ui.grid').config(['$provide', function($provide) {\n    $provide.decorator('i18nService', ['$delegate', function($delegate) {\n      $delegate.add('da', {\n        aggregate:{\n          label: 'artikler'\n        },\n        groupPanel:{\n          description: 'Grupér rækker udfra en kolonne ved at trække dens overskift hertil.'\n        },\n        search:{\n          placeholder: 'Søg...',\n          showingItems: 'Viste rækker:',\n          selectedItems: 'Valgte rækker:',\n          totalItems: 'Rækker totalt:',\n          size: 'Side størrelse:',\n          first: 'Første side',\n          next: 'Næste side',\n          previous: 'Forrige side',\n          last: 'Sidste side'\n        },\n        menu:{\n          text: 'Vælg kolonner:'\n        },\n        column: {\n          hide: 'Skjul kolonne'\n        },\n        aggregation: {\n          count: 'samlede rækker: ',\n          sum: 'smalede: ',\n          avg: 'gns: ',\n          min: 'min: ',\n          max: 'max: '\n        },\n        gridMenu: {\n          columns: 'Columns:',\n          importerTitle: 'Import file',\n          exporterAllAsCsv: 'Export all data as csv',\n          exporterVisibleAsCsv: 'Export visible data as csv',\n          exporterSelectedAsCsv: 'Export selected data as csv',\n          exporterAllAsPdf: 'Export all data as pdf',\n          exporterVisibleAsPdf: 'Export visible data as pdf',\n          exporterSelectedAsPdf: 'Export selected data as pdf'\n        },\n        importer: {\n          noHeaders: 'Column names were unable to be derived, does the file have a header?',\n          noObjects: 'Objects were not able to be derived, was there data in the file other than headers?',\n          invalidCsv: 'File was unable to be processed, is it valid CSV?',\n          invalidJson: 'File was unable to be processed, is it valid Json?',\n          jsonNotArray: 'Imported json file must contain an array, aborting.'\n        }\n      });\n      return $delegate;\n    }]);\n  }]);\n})();\n(function () {\n  angular.module('ui.grid').config(['$provide', function ($provide) {\n    $provide.decorator('i18nService', ['$delegate', function ($delegate) {\n      $delegate.add('de', {\n        aggregate: {\n          label: 'Eintrag'\n        },\n        groupPanel: {\n          description: 'Ziehen Sie eine Spaltenüberschrift hierhin, um nach dieser Spalte zu gruppieren.'\n        },\n        search: {\n          placeholder: 'Suche...',\n          showingItems: 'Zeige Einträge:',\n          selectedItems: 'Ausgewählte Einträge:',\n          totalItems: 'Einträge gesamt:',\n          size: 'Einträge pro Seite:',\n          first: 'Erste Seite',\n          next: 'Nächste Seite',\n          previous: 'Vorherige Seite',\n          last: 'Letzte Seite'\n        },\n        menu: {\n          text: 'Spalten auswählen:'\n        },\n        sort: {\n          ascending: 'aufsteigend sortieren',\n          descending: 'absteigend sortieren',\n          remove: 'Sortierung zurücksetzen'\n        },\n        column: {\n          hide: 'Spalte ausblenden'\n        },\n        aggregation: {\n          count: 'Zeilen insgesamt: ',\n          sum: 'gesamt: ',\n          avg: 'Durchschnitt: ',\n          min: 'min: ',\n          max: 'max: '\n        },\n        pinning: {\n            pinLeft: 'Links anheften',\n            pinRight: 'Rechts anheften',\n            unpin: 'Lösen'\n        },\n        gridMenu: {\n          columns: 'Spalten:',\n          importerTitle: 'Datei importieren',\n          exporterAllAsCsv: 'Alle Daten als CSV exportieren',\n          exporterVisibleAsCsv: 'sichtbare Daten als CSV exportieren',\n          exporterSelectedAsCsv: 'markierte Daten als CSV exportieren',\n          exporterAllAsPdf: 'Alle Daten als PDF exportieren',\n          exporterVisibleAsPdf: 'sichtbare Daten als PDF exportieren',\n          exporterSelectedAsPdf: 'markierte Daten als CSV exportieren'\n        },\n        importer: {\n          noHeaders: 'Es konnten keine Spaltennamen ermittelt werden. Sind in der Datei Spaltendefinitionen enthalten?',\n          noObjects: 'Es konnten keine Zeileninformationen gelesen werden, Sind in der Datei außer den Spaltendefinitionen auch Daten enthalten?',\n          invalidCsv: 'Die Datei konnte nicht eingelesen werden, ist es eine gültige CSV-Datei?',\n          invalidJson: 'Die Datei konnte nicht eingelesen werden. Enthält sie gültiges JSON?',\n          jsonNotArray: 'Die importierte JSON-Datei muß ein Array enthalten. Breche Import ab.'\n        },\n        pagination: {\n            sizes: 'Einträge pro Seite',\n            totalItems: 'Einträge'\n        },\n        grouping: {\n            group: 'Gruppieren',\n            ungroup: 'Gruppierung aufheben',\n            aggregate_count: 'Agg: Anzahl',\n            aggregate_sum: 'Agg: Summe',\n            aggregate_max: 'Agg: Maximum',\n            aggregate_min: 'Agg: Minimum',\n            aggregate_avg: 'Agg: Mittelwert',\n            aggregate_remove: 'Aggregation entfernen'\n        }\n      });\n      return $delegate;\n    }]);\n  }]);\n})();\n\n(function () {\n  angular.module('ui.grid').config(['$provide', function($provide) {\n    $provide.decorator('i18nService', ['$delegate', function($delegate) {\n      $delegate.add('en', {\n        headerCell: {\n          aria: {\n            defaultFilterLabel: 'Filter for column',\n            removeFilter: 'Remove Filter',\n            columnMenuButtonLabel: 'Column Menu'\n          },\n          priority: 'Priority:',\n          filterLabel: \"Filter for column: \"\n        },\n        aggregate: {\n          label: 'items'\n        },\n        groupPanel: {\n          description: 'Drag a column header here and drop it to group by that column.'\n        },\n        search: {\n          placeholder: 'Search...',\n          showingItems: 'Showing Items:',\n          selectedItems: 'Selected Items:',\n          totalItems: 'Total Items:',\n          size: 'Page Size:',\n          first: 'First Page',\n          next: 'Next Page',\n          previous: 'Previous Page',\n          last: 'Last Page'\n        },\n        menu: {\n          text: 'Choose Columns:'\n        },\n        sort: {\n          ascending: 'Sort Ascending',\n          descending: 'Sort Descending',\n          none: 'Sort None',\n          remove: 'Remove Sort'\n        },\n        column: {\n          hide: 'Hide Column'\n        },\n        aggregation: {\n          count: 'total rows: ',\n          sum: 'total: ',\n          avg: 'avg: ',\n          min: 'min: ',\n          max: 'max: '\n        },\n        pinning: {\n          pinLeft: 'Pin Left',\n          pinRight: 'Pin Right',\n          unpin: 'Unpin'\n        },\n        columnMenu: {\n          close: 'Close'\n        },\n        gridMenu: {\n          aria: {\n            buttonLabel: 'Grid Menu'\n          },\n          columns: 'Columns:',\n          importerTitle: 'Import file',\n          exporterAllAsCsv: 'Export all data as csv',\n          exporterVisibleAsCsv: 'Export visible data as csv',\n          exporterSelectedAsCsv: 'Export selected data as csv',\n          exporterAllAsPdf: 'Export all data as pdf',\n          exporterVisibleAsPdf: 'Export visible data as pdf',\n          exporterSelectedAsPdf: 'Export selected data as pdf'\n        },\n        importer: {\n          noHeaders: 'Column names were unable to be derived, does the file have a header?',\n          noObjects: 'Objects were not able to be derived, was there data in the file other than headers?',\n          invalidCsv: 'File was unable to be processed, is it valid CSV?',\n          invalidJson: 'File was unable to be processed, is it valid Json?',\n          jsonNotArray: 'Imported json file must contain an array, aborting.'\n        },\n        pagination: {\n          aria: {\n            pageToFirst: 'Page to first',\n            pageBack: 'Page back',\n            pageSelected: 'Selected page',\n            pageForward: 'Page forward',\n            pageToLast: 'Page to last'\n          },\n          sizes: 'items per page',\n          totalItems: 'items',\n          through: 'through',\n          of: 'of'\n        },\n        grouping: {\n          group: 'Group',\n          ungroup: 'Ungroup',\n          aggregate_count: 'Agg: Count',\n          aggregate_sum: 'Agg: Sum',\n          aggregate_max: 'Agg: Max',\n          aggregate_min: 'Agg: Min',\n          aggregate_avg: 'Agg: Avg',\n          aggregate_remove: 'Agg: Remove'\n        }\n      });\n      return $delegate;\n    }]);\n  }]);\n})();\n\n(function () {\n  angular.module('ui.grid').config(['$provide', function($provide) {\n    $provide.decorator('i18nService', ['$delegate', function($delegate) {\n      $delegate.add('es', {\n        aggregate: {\n          label: 'Artículos'\n        },\n        groupPanel: {\n          description: 'Arrastre un encabezado de columna aquí y suéltelo para agrupar por esa columna.'\n        },\n        search: {\n          placeholder: 'Buscar...',\n          showingItems: 'Artículos Mostrados:',\n          selectedItems: 'Artículos Seleccionados:',\n          totalItems: 'Artículos Totales:',\n          size: 'Tamaño de Página:',\n          first: 'Primera Página',\n          next: 'Página Siguiente',\n          previous: 'Página Anterior',\n          last: 'Última Página'\n        },\n        menu: {\n          text: 'Elegir columnas:'\n        },\n        sort: {\n          ascending: 'Orden Ascendente',\n          descending: 'Orden Descendente',\n          remove: 'Sin Ordenar'\n        },\n        column: {\n          hide: 'Ocultar la columna'\n        },\n        aggregation: {\n          count: 'filas totales: ',\n          sum: 'total: ',\n          avg: 'media: ',\n          min: 'min: ',\n          max: 'max: '\n        },\n        pinning: {\n          pinLeft: 'Fijar a la Izquierda',\n          pinRight: 'Fijar a la Derecha',\n          unpin: 'Quitar Fijación'\n        },\n        gridMenu: {\n          columns: 'Columnas:',\n          importerTitle: 'Importar archivo',\n          exporterAllAsCsv: 'Exportar todo como csv',\n          exporterVisibleAsCsv: 'Exportar vista como csv',\n          exporterSelectedAsCsv: 'Exportar selección como csv',\n          exporterAllAsPdf: 'Exportar todo como pdf',\n          exporterVisibleAsPdf: 'Exportar vista como pdf',\n          exporterSelectedAsPdf: 'Exportar selección como pdf'\n        },\n        importer: {\n          noHeaders: 'No fue posible derivar los nombres de las columnas, ¿tiene encabezados el archivo?',\n          noObjects: 'No fue posible obtener registros, ¿contiene datos el archivo, aparte de los encabezados?',\n          invalidCsv: 'No fue posible procesar el archivo, ¿es un CSV válido?',\n          invalidJson: 'No fue posible procesar el archivo, ¿es un Json válido?',\n          jsonNotArray: 'El archivo json importado debe contener un array, abortando.'\n        },\n        pagination: {\n          sizes: 'registros por página',\n          totalItems: 'registros',\n          of: 'de'\n        },\n        grouping: {\n          group: 'Agrupar',\n          ungroup: 'Desagrupar',\n          aggregate_count: 'Agr: Cont',\n          aggregate_sum: 'Agr: Sum',\n          aggregate_max: 'Agr: Máx',\n          aggregate_min: 'Agr: Min',\n          aggregate_avg: 'Agr: Prom',\n          aggregate_remove: 'Agr: Quitar'\n        }\n      });\n      return $delegate;\n    }]);\n}]);\n})();\n\n/**\n * Translated by: R. Salarmehr\n *                M. Hosseynzade\n *                Using Vajje.com online dictionary.\n */\n(function () {\n  angular.module('ui.grid').config(['$provide', function ($provide) {\n    $provide.decorator('i18nService', ['$delegate', function ($delegate) {\n      $delegate.add('fa', {\n        aggregate: {\n          label: 'قلم'\n        },\n        groupPanel: {\n          description: 'عنوان یک ستون را بگیر و به گروهی از آن ستون رها کن.'\n        },\n        search: {\n          placeholder: 'جستجو...',\n          showingItems: 'نمایش اقلام:',\n          selectedItems: 'قلم\\u200cهای انتخاب شده:',\n          totalItems: 'مجموع اقلام:',\n          size: 'اندازه\\u200cی صفحه:',\n          first: 'اولین صفحه',\n          next: 'صفحه\\u200cی\\u200cبعدی',\n          previous: 'صفحه\\u200cی\\u200c قبلی',\n          last: 'آخرین صفحه'\n        },\n        menu: {\n          text: 'ستون\\u200cهای انتخابی:'\n        },\n        sort: {\n          ascending: 'ترتیب صعودی',\n          descending: 'ترتیب نزولی',\n          remove: 'حذف مرتب کردن'\n        },\n        column: {\n          hide: 'پنهان\\u200cکردن ستون'\n        },\n        aggregation: {\n          count: 'تعداد: ',\n          sum: 'مجموع: ',\n          avg: 'میانگین: ',\n          min: 'کمترین: ',\n          max: 'بیشترین: '\n        },\n        pinning: {\n          pinLeft: 'پین کردن سمت چپ',\n          pinRight: 'پین کردن سمت راست',\n          unpin: 'حذف پین'\n        },\n        gridMenu: {\n          columns: 'ستون\\u200cها:',\n          importerTitle: 'وارد کردن فایل',\n          exporterAllAsCsv: 'خروجی تمام داده\\u200cها در فایل csv',\n          exporterVisibleAsCsv: 'خروجی داده\\u200cهای قابل مشاهده در فایل csv',\n          exporterSelectedAsCsv: 'خروجی داده\\u200cهای انتخاب\\u200cشده در فایل csv',\n          exporterAllAsPdf: 'خروجی تمام داده\\u200cها در فایل pdf',\n          exporterVisibleAsPdf: 'خروجی داده\\u200cهای قابل مشاهده در فایل pdf',\n          exporterSelectedAsPdf: 'خروجی داده\\u200cهای انتخاب\\u200cشده در فایل pdf'\n        },\n        importer: {\n          noHeaders: 'نام ستون قابل استخراج نیست. آیا فایل عنوان دارد؟',\n          noObjects: 'اشیا قابل استخراج نیستند. آیا به جز عنوان\\u200cها در فایل داده وجود دارد؟',\n          invalidCsv: 'فایل قابل پردازش نیست. آیا فرمت  csv  معتبر است؟',\n          invalidJson: 'فایل قابل پردازش نیست. آیا فرمت json   معتبر است؟',\n          jsonNotArray: 'فایل json وارد شده باید حاوی آرایه باشد. عملیات ساقط شد.'\n        },\n        pagination: {\n          sizes: 'اقلام در هر صفحه',\n          totalItems: 'اقلام',\n          of: 'از'\n        },\n        grouping: {\n          group: 'گروه\\u200cبندی',\n          ungroup: 'حذف گروه\\u200cبندی',\n          aggregate_count: 'Agg: تعداد',\n          aggregate_sum: 'Agg: جمع',\n          aggregate_max: 'Agg: بیشینه',\n          aggregate_min: 'Agg: کمینه',\n          aggregate_avg: 'Agg: میانگین',\n          aggregate_remove: 'Agg: حذف'\n        }\n      });\n      return $delegate;\n    }]);\n  }]);\n})();\n\n(function () {\n  angular.module('ui.grid').config(['$provide', function($provide) {\n    $provide.decorator('i18nService', ['$delegate', function($delegate) {\n      $delegate.add('fi', {\n        aggregate: {\n          label: 'rivit'\n        },\n        groupPanel: {\n          description: 'Raahaa ja pudota otsikko tähän ryhmittääksesi sarakkeen mukaan.'\n        },\n        search: {\n          placeholder: 'Hae...',\n          showingItems: 'Näytetään rivejä:',\n          selectedItems: 'Valitut rivit:',\n          totalItems: 'Rivejä yht.:',\n          size: 'Näytä:',\n          first: 'Ensimmäinen sivu',\n          next: 'Seuraava sivu',\n          previous: 'Edellinen sivu',\n          last: 'Viimeinen sivu'\n        },\n        menu: {\n          text: 'Valitse sarakkeet:'\n        },\n        sort: {\n          ascending: 'Järjestä nouseva',\n          descending: 'Järjestä laskeva',\n          remove: 'Poista järjestys'\n        },\n        column: {\n          hide: 'Piilota sarake'\n        },\n        aggregation: {\n          count: 'Rivejä yht.: ',\n          sum: 'Summa: ',\n          avg: 'K.a.: ',\n          min: 'Min: ',\n          max: 'Max: '\n        },\n        pinning: {\n         pinLeft: 'Lukitse vasemmalle',\n          pinRight: 'Lukitse oikealle',\n          unpin: 'Poista lukitus'\n        },\n        gridMenu: {\n          columns: 'Sarakkeet:',\n          importerTitle: 'Tuo tiedosto',\n          exporterAllAsCsv: 'Vie tiedot csv-muodossa',\n          exporterVisibleAsCsv: 'Vie näkyvä tieto csv-muodossa',\n          exporterSelectedAsCsv: 'Vie valittu tieto csv-muodossa',\n          exporterAllAsPdf: 'Vie tiedot pdf-muodossa',\n          exporterVisibleAsPdf: 'Vie näkyvä tieto pdf-muodossa',\n          exporterSelectedAsPdf: 'Vie valittu tieto pdf-muodossa'\n        },\n        importer: {\n          noHeaders: 'Sarakkeen nimiä ei voitu päätellä, onko tiedostossa otsikkoriviä?',\n          noObjects: 'Tietoja ei voitu lukea, onko tiedostossa muuta kuin otsikkot?',\n          invalidCsv: 'Tiedostoa ei voitu käsitellä, oliko se CSV-muodossa?',\n          invalidJson: 'Tiedostoa ei voitu käsitellä, oliko se JSON-muodossa?',\n          jsonNotArray: 'Tiedosto ei sisältänyt taulukkoa, lopetetaan.'\n        }\n      });\n      return $delegate;\n    }]);\n  }]);\n})();\n\n(function () {\n  angular.module('ui.grid').config(['$provide', function($provide) {\n    $provide.decorator('i18nService', ['$delegate', function($delegate) {\n      $delegate.add('fr', {\n        aggregate: {\n          label: 'éléments'\n        },\n        groupPanel: {\n          description: 'Faites glisser une en-tête de colonne ici pour créer un groupe de colonnes.'\n        },\n        search: {\n          placeholder: 'Recherche...',\n          showingItems: 'Affichage des éléments :',\n          selectedItems: 'Éléments sélectionnés :',\n          totalItems: 'Nombre total d\\'éléments:',\n          size: 'Taille de page:',\n          first: 'Première page',\n          next: 'Page Suivante',\n          previous: 'Page précédente',\n          last: 'Dernière page'\n        },\n        menu: {\n          text: 'Choisir des colonnes :'\n        },\n        sort: {\n          ascending: 'Trier par ordre croissant',\n          descending: 'Trier par ordre décroissant',\n          remove: 'Enlever le tri'\n        },\n        column: {\n          hide: 'Cacher la colonne'\n        },\n        aggregation: {\n          count: 'lignes totales: ',\n          sum: 'total: ',\n          avg: 'moy: ',\n          min: 'min: ',\n          max: 'max: '\n        },\n        pinning: {\n          pinLeft: 'Épingler à gauche',\n          pinRight: 'Épingler à droite',\n          unpin: 'Détacher'\n        },\n        gridMenu: {\n          columns: 'Colonnes:',\n          importerTitle: 'Importer un fichier',\n          exporterAllAsCsv: 'Exporter toutes les données en CSV',\n          exporterVisibleAsCsv: 'Exporter les données visibles en CSV',\n          exporterSelectedAsCsv: 'Exporter les données sélectionnées en CSV',\n          exporterAllAsPdf: 'Exporter toutes les données en PDF',\n          exporterVisibleAsPdf: 'Exporter les données visibles en PDF',\n          exporterSelectedAsPdf: 'Exporter les données sélectionnées en PDF'\n        },\n        importer: {\n          noHeaders: 'Impossible de déterminer le nom des colonnes, le fichier possède-t-il une en-tête ?',\n          noObjects: 'Aucun objet trouvé, le fichier possède-t-il des données autres que l\\'en-tête ?',\n          invalidCsv: 'Le fichier n\\'a pas pu être traité, le CSV est-il valide ?',\n          invalidJson: 'Le fichier n\\'a pas pu être traité, le JSON est-il valide ?',\n          jsonNotArray: 'Le fichier JSON importé doit contenir un tableau, abandon.'\n        },\n        pagination: {\n          sizes: 'éléments par page',\n          totalItems: 'éléments',\n          of: 'sur'\n        },\n        grouping: {\n          group: 'Grouper',\n          ungroup: 'Dégrouper',\n          aggregate_count: 'Agg: Compte',\n          aggregate_sum: 'Agg: Somme',\n          aggregate_max: 'Agg: Max',\n          aggregate_min: 'Agg: Min',\n          aggregate_avg: 'Agg: Moy',\n          aggregate_remove: 'Agg: Retirer'\n        }\n      });\n      return $delegate;\n    }]);\n  }]);\n})();\n(function () {\n  angular.module('ui.grid').config(['$provide', function ($provide) {\n    $provide.decorator('i18nService', ['$delegate', function ($delegate) {\n      $delegate.add('he', {\n        aggregate: {\n          label: 'items'\n        },\n        groupPanel: {\n          description: 'גרור עמודה לכאן ושחרר בכדי לקבץ עמודה זו.'\n        },\n        search: {\n          placeholder: 'חפש...',\n          showingItems: 'מציג:',\n          selectedItems: 'סה\"כ נבחרו:',\n          totalItems: 'סה\"כ רשומות:',\n          size: 'תוצאות בדף:',\n          first: 'דף ראשון',\n          next: 'דף הבא',\n          previous: 'דף קודם',\n          last: 'דף אחרון'\n        },\n        menu: {\n          text: 'בחר עמודות:'\n        },\n        sort: {\n          ascending: 'סדר עולה',\n          descending: 'סדר יורד',\n          remove: 'בטל'\n        },\n        column: {\n          hide: 'טור הסתר'\n        },\n        aggregation: {\n          count: 'total rows: ',\n          sum: 'total: ',\n          avg: 'avg: ',\n          min: 'min: ',\n          max: 'max: '\n        },\n        gridMenu: {\n          columns: 'Columns:',\n          importerTitle: 'Import file',\n          exporterAllAsCsv: 'Export all data as csv',\n          exporterVisibleAsCsv: 'Export visible data as csv',\n          exporterSelectedAsCsv: 'Export selected data as csv',\n          exporterAllAsPdf: 'Export all data as pdf',\n          exporterVisibleAsPdf: 'Export visible data as pdf',\n          exporterSelectedAsPdf: 'Export selected data as pdf'\n        },\n        importer: {\n          noHeaders: 'Column names were unable to be derived, does the file have a header?',\n          noObjects: 'Objects were not able to be derived, was there data in the file other than headers?',\n          invalidCsv: 'File was unable to be processed, is it valid CSV?',\n          invalidJson: 'File was unable to be processed, is it valid Json?',\n          jsonNotArray: 'Imported json file must contain an array, aborting.'\n        }\n      });\n      return $delegate;\n    }]);\n  }]);\n})();\n(function () {\n  angular.module('ui.grid').config(['$provide', function($provide) {\n    $provide.decorator('i18nService', ['$delegate', function($delegate) {\n      $delegate.add('hy', {\n        aggregate: {\n          label: 'տվյալներ'\n        },\n        groupPanel: {\n          description: 'Ըստ սյան խմբավորելու համար քաշեք և գցեք վերնագիրն այստեղ։'\n        },\n        search: {\n          placeholder: 'Փնտրում...',\n          showingItems: 'Ցուցադրված տվյալներ՝',\n          selectedItems: 'Ընտրված:',\n          totalItems: 'Ընդամենը՝',\n          size: 'Տողերի քանակը էջում՝',\n          first: 'Առաջին էջ',\n          next: 'Հաջորդ էջ',\n          previous: 'Նախորդ էջ',\n          last: 'Վերջին էջ'\n        },\n        menu: {\n          text: 'Ընտրել սյուները:'\n        },\n        sort: {\n          ascending: 'Աճման կարգով',\n          descending: 'Նվազման կարգով',\n          remove: 'Հանել '\n        },\n        column: {\n          hide: 'Թաքցնել սյունը'\n        },\n        aggregation: {\n          count: 'ընդամենը տող՝ ',\n          sum: 'ընդամենը՝ ',\n          avg: 'միջին՝ ',\n          min: 'մին՝ ',\n          max: 'մաքս՝ '\n        },\n        pinning: {\n          pinLeft: 'Կպցնել ձախ կողմում',\n          pinRight: 'Կպցնել աջ կողմում',\n          unpin: 'Արձակել'\n        },\n        gridMenu: {\n          columns: 'Սյուներ:',\n          importerTitle: 'Ներմուծել ֆայլ',\n          exporterAllAsCsv: 'Արտահանել ամբողջը CSV',\n          exporterVisibleAsCsv: 'Արտահանել երևացող տվյալները CSV',\n          exporterSelectedAsCsv: 'Արտահանել ընտրված տվյալները CSV',\n          exporterAllAsPdf: 'Արտահանել PDF',\n          exporterVisibleAsPdf: 'Արտահանել երևացող տվյալները PDF',\n          exporterSelectedAsPdf: 'Արտահանել ընտրված տվյալները PDF'\n        },\n        importer: {\n          noHeaders: 'Հնարավոր չեղավ որոշել սյան վերնագրերը։ Արդյո՞ք ֆայլը ունի վերնագրեր։',\n          noObjects: 'Հնարավոր չեղավ կարդալ տվյալները։ Արդյո՞ք ֆայլում կան տվյալներ։',\n          invalidCsv: 'Հնարավոր չեղավ մշակել ֆայլը։ Արդյո՞ք այն վավեր CSV է։',\n          invalidJson: 'Հնարավոր չեղավ մշակել ֆայլը։ Արդյո՞ք այն վավեր Json է։',\n          jsonNotArray: 'Ներմուծված json ֆայլը պետք է պարունակի զանգված, կասեցվում է։'\n        }\n      });\n      return $delegate;\n    }]);\n  }]);\n})();\n\n(function () {\n  angular.module('ui.grid').config(['$provide', function($provide) {\n    $provide.decorator('i18nService', ['$delegate', function($delegate) {\n      $delegate.add('it', {\n        aggregate: {\n          label: 'elementi'\n        },\n        groupPanel: {\n          description: 'Trascina un\\'intestazione all\\'interno del gruppo della colonna.'\n        },\n        search: {\n          placeholder: 'Ricerca...',\n          showingItems: 'Mostra:',\n          selectedItems: 'Selezionati:',\n          totalItems: 'Totali:',\n          size: 'Tot Pagine:',\n          first: 'Prima',\n          next: 'Prossima',\n          previous: 'Precedente',\n          last: 'Ultima'\n        },\n        menu: {\n          text: 'Scegli le colonne:'\n        },\n        sort: {\n          ascending: 'Asc.',\n          descending: 'Desc.',\n          remove: 'Annulla ordinamento'\n        },\n        column: {\n          hide: 'Nascondi'\n        },\n        aggregation: {\n          count: 'righe totali: ',\n          sum: 'tot: ',\n          avg: 'media: ',\n          min: 'minimo: ',\n          max: 'massimo: '\n        },\n        pinning: {\n         pinLeft: 'Blocca a sx',\n          pinRight: 'Blocca a dx',\n          unpin: 'Blocca in alto'\n        },\n        gridMenu: {\n          columns: 'Colonne:',\n          importerTitle: 'Importa',\n          exporterAllAsCsv: 'Esporta tutti i dati in CSV',\n          exporterVisibleAsCsv: 'Esporta i dati visibili in CSV',\n          exporterSelectedAsCsv: 'Esporta i dati selezionati in CSV',\n          exporterAllAsPdf: 'Esporta tutti i dati in PDF',\n          exporterVisibleAsPdf: 'Esporta i dati visibili in PDF',\n          exporterSelectedAsPdf: 'Esporta i dati selezionati in PDF'\n        },\n        importer: {\n          noHeaders: 'Impossibile reperire i nomi delle colonne, sicuro che siano indicati all\\'interno del file?',\n          noObjects: 'Impossibile reperire gli oggetti, sicuro che siano indicati all\\'interno del file?',\n          invalidCsv: 'Impossibile elaborare il file, sicuro che sia un CSV?',\n          invalidJson: 'Impossibile elaborare il file, sicuro che sia un JSON valido?',\n          jsonNotArray: 'Errore! Il file JSON da importare deve contenere un array.'\n        },\n        grouping: {\n          group: 'Raggruppa',\n          ungroup: 'Separa',\n          aggregate_count: 'Agg: N. Elem.',\n          aggregate_sum: 'Agg: Somma',\n          aggregate_max: 'Agg: Massimo',\n          aggregate_min: 'Agg: Minimo',\n          aggregate_avg: 'Agg: Media',\n          aggregate_remove: 'Agg: Rimuovi'\n        }\n      });\n      return $delegate;\n    }]);\n  }]);\n})();\n\n(function() {\n  angular.module('ui.grid').config(['$provide', function($provide) {\n    $provide.decorator('i18nService', ['$delegate', function($delegate) {\n      $delegate.add('ja', {\n        aggregate: {\n          label: '項目'\n        },\n        groupPanel: {\n          description: 'ここに列ヘッダをドラッグアンドドロップして、その列でグループ化します。'\n        },\n        search: {\n          placeholder: '検索...',\n          showingItems: '表示中の項目:',\n          selectedItems: '選択した項目:',\n          totalItems: '項目の総数:',\n          size: 'ページサイズ:',\n          first: '最初のページ',\n          next: '次のページ',\n          previous: '前のページ',\n          last: '前のページ'\n        },\n        menu: {\n          text: '列の選択:'\n        },\n        sort: {\n          ascending: '昇順に並べ替え',\n          descending: '降順に並べ替え',\n          remove: '並べ替えの解除'\n        },\n        column: {\n          hide: '列の非表示'\n        },\n        aggregation: {\n          count: '合計行数: ',\n          sum: '合計: ',\n          avg: '平均: ',\n          min: '最小: ',\n          max: '最大: '\n        },\n        pinning: {\n          pinLeft: '左に固定',\n          pinRight: '右に固定',\n          unpin: '固定解除'\n        },\n        gridMenu: {\n          columns: '列:',\n          importerTitle: 'ファイルのインポート',\n          exporterAllAsCsv: 'すべてのデータをCSV形式でエクスポート',\n          exporterVisibleAsCsv: '表示中のデータをCSV形式でエクスポート',\n          exporterSelectedAsCsv: '選択したデータをCSV形式でエクスポート',\n          exporterAllAsPdf: 'すべてのデータをPDF形式でエクスポート',\n          exporterVisibleAsPdf: '表示中のデータをPDF形式でエクスポート',\n          exporterSelectedAsPdf: '選択したデータをPDF形式でエクスポート'\n        },\n        importer: {\n          noHeaders: '列名を取得できません。ファイルにヘッダが含まれていることを確認してください。',\n          noObjects: 'オブジェクトを取得できません。ファイルにヘッダ以外のデータが含まれていることを確認してください。',\n          invalidCsv: 'ファイルを処理できません。ファイルが有効なCSV形式であることを確認してください。',\n          invalidJson: 'ファイルを処理できません。ファイルが有効なJSON形式であることを確認してください。',\n          jsonNotArray: 'インポートしたJSONファイルには配列が含まれている必要があります。処理を中止します。'\n        },\n        pagination: {\n          sizes: '項目/ページ',\n          totalItems: '項目'\n        }\n      });\n      return $delegate;\n    }]);\n  }]);\n})();\n\n(function () {\n  angular.module('ui.grid').config(['$provide', function($provide) {\n    $provide.decorator('i18nService', ['$delegate', function($delegate) {\n      $delegate.add('ko', {\n        aggregate: {\n          label: '아이템'\n        },\n        groupPanel: {\n          description: '컬럼으로 그룹핑하기 위해서는 컬럼 헤더를 끌어 떨어뜨려 주세요.'\n        },\n        search: {\n          placeholder: '검색...',\n          showingItems: '항목 보여주기:',\n          selectedItems: '선택 항목:',\n          totalItems: '전체 항목:',\n          size: '페이지 크기:',\n          first: '첫번째 페이지',\n          next: '다음 페이지',\n          previous: '이전 페이지',\n          last: '마지막 페이지'\n        },\n        menu: {\n          text: '컬럼을 선택하세요:'\n        },\n        sort: {\n          ascending: '오름차순 정렬',\n          descending: '내림차순 정렬',\n          remove: '소팅 제거'\n        },\n        column: {\n          hide: '컬럼 제거'\n        },\n        aggregation: {\n          count: '전체 갯수: ',\n          sum: '전체: ',\n          avg: '평균: ',\n          min: '최소: ',\n          max: '최대: '\n        },\n        pinning: {\n         pinLeft: '왼쪽 핀',\n          pinRight: '오른쪽 핀',\n          unpin: '핀 제거'\n        },\n        gridMenu: {\n          columns: '컬럼:',\n          importerTitle: '파일 가져오기',\n          exporterAllAsCsv: 'csv로 모든 데이터 내보내기',\n          exporterVisibleAsCsv: 'csv로 보이는 데이터 내보내기',\n          exporterSelectedAsCsv: 'csv로 선택된 데이터 내보내기',\n          exporterAllAsPdf: 'pdf로 모든 데이터 내보내기',\n          exporterVisibleAsPdf: 'pdf로 보이는 데이터 내보내기',\n          exporterSelectedAsPdf: 'pdf로 선택 데이터 내보내기'\n        },\n        importer: {\n          noHeaders: '컬럼명이 지정되어 있지 않습니다. 파일에 헤더가 명시되어 있는지 확인해 주세요.',\n          noObjects: '데이터가 지정되어 있지 않습니다. 데이터가 파일에 있는지 확인해 주세요.',\n          invalidCsv: '파일을 처리할 수 없습니다. 올바른 csv인지 확인해 주세요.',\n          invalidJson: '파일을 처리할 수 없습니다. 올바른 json인지 확인해 주세요.',\n          jsonNotArray: 'json 파일은 배열을 포함해야 합니다.'\n        },\n        pagination: {\n          sizes: '페이지당 항목',\n          totalItems: '전체 항목'\n        }\n      });\n      return $delegate;\n    }]);\n  }]);\n})();\n\n(function () {\n  angular.module('ui.grid').config(['$provide', function($provide) {\n    $provide.decorator('i18nService', ['$delegate', function($delegate) {\n      $delegate.add('nl', {\n        aggregate: {\n          label: 'items'\n        },\n        groupPanel: {\n          description: 'Sleep hier een kolomnaam heen om op te groeperen.'\n        },\n        search: {\n          placeholder: 'Zoeken...',\n          showingItems: 'Getoonde items:',\n          selectedItems: 'Geselecteerde items:',\n          totalItems: 'Totaal aantal items:',\n          size: 'Items per pagina:',\n          first: 'Eerste pagina',\n          next: 'Volgende pagina',\n          previous: 'Vorige pagina',\n          last: 'Laatste pagina'\n        },\n        menu: {\n          text: 'Kies kolommen:'\n        },\n        sort: {\n          ascending: 'Sorteer oplopend',\n          descending: 'Sorteer aflopend',\n          remove: 'Verwijder sortering'\n        },\n        column: {\n          hide: 'Verberg kolom'\n        },\n        aggregation: {\n          count: 'Aantal rijen: ',\n          sum: 'Som: ',\n          avg: 'Gemiddelde: ',\n          min: 'Min: ',\n          max: 'Max: '\n        },\n        pinning: {\n          pinLeft: 'Zet links vast',\n          pinRight: 'Zet rechts vast',\n          unpin: 'Maak los'\n        },\n        gridMenu: {\n          columns: 'Kolommen:',\n          importerTitle: 'Importeer bestand',\n          exporterAllAsCsv: 'Exporteer alle data als csv',\n          exporterVisibleAsCsv: 'Exporteer zichtbare data als csv',\n          exporterSelectedAsCsv: 'Exporteer geselecteerde data als csv',\n          exporterAllAsPdf: 'Exporteer alle data als pdf',\n          exporterVisibleAsPdf: 'Exporteer zichtbare data als pdf',\n          exporterSelectedAsPdf: 'Exporteer geselecteerde data als pdf'\n        },\n        importer: {\n          noHeaders: 'Kolomnamen kunnen niet worden afgeleid. Heeft het bestand een header?',\n          noObjects: 'Objecten kunnen niet worden afgeleid. Bevat het bestand data naast de headers?',\n          invalidCsv: 'Het bestand kan niet verwerkt worden. Is het een valide csv bestand?',\n          invalidJson: 'Het bestand kan niet verwerkt worden. Is het valide json?',\n          jsonNotArray: 'Het json bestand moet een array bevatten. De actie wordt geannuleerd.'\n        },\n        pagination: {\n            sizes: 'items per pagina',\n            totalItems: 'items'\n        },\n        grouping: {\n            group: 'Groepeer',\n            ungroup: 'Groepering opheffen',\n            aggregate_count: 'Agg: Aantal',\n            aggregate_sum: 'Agg: Som',\n            aggregate_max: 'Agg: Max',\n            aggregate_min: 'Agg: Min',\n            aggregate_avg: 'Agg: Gem',\n            aggregate_remove: 'Agg: Verwijder'\n        }\n      });\n      return $delegate;\n    }]);\n  }]);\n})();\n\n(function () {\n  angular.module('ui.grid').config(['$provide', function($provide) {\n    $provide.decorator('i18nService', ['$delegate', function($delegate) {\n      $delegate.add('pt-br', {\n        aggregate: {\n          label: 'itens'\n        },\n        groupPanel: {\n          description: 'Arraste e solte uma coluna aqui para agrupar por essa coluna'\n        },\n        search: {\n          placeholder: 'Procurar...',\n          showingItems: 'Mostrando os Itens:',\n          selectedItems: 'Items Selecionados:',\n          totalItems: 'Total de Itens:',\n          size: 'Tamanho da Página:',\n          first: 'Primeira Página',\n          next: 'Próxima Página',\n          previous: 'Página Anterior',\n          last: 'Última Página'\n        },\n        menu: {\n          text: 'Selecione as colunas:'\n        },\n        sort: {\n          ascending: 'Ordenar Ascendente',\n          descending: 'Ordenar Descendente',\n          remove: 'Remover Ordenação'\n        },\n        column: {\n          hide: 'Esconder coluna'\n        },\n        aggregation: {\n          count: 'total de linhas: ',\n          sum: 'total: ',\n          avg: 'med: ',\n          min: 'min: ',\n          max: 'max: '\n        },\n        pinning: {\n          pinLeft: 'Fixar Esquerda',\n          pinRight: 'Fixar Direita',\n          unpin: 'Desprender'\n        },\n        gridMenu: {\n          columns: 'Colunas:',\n          importerTitle: 'Importar arquivo',\n          exporterAllAsCsv: 'Exportar todos os dados como csv',\n          exporterVisibleAsCsv: 'Exportar dados visíveis como csv',\n          exporterSelectedAsCsv: 'Exportar dados selecionados como csv',\n          exporterAllAsPdf: 'Exportar todos os dados como pdf',\n          exporterVisibleAsPdf: 'Exportar dados visíveis como pdf',\n          exporterSelectedAsPdf: 'Exportar dados selecionados como pdf'\n        },\n        importer: {\n          noHeaders: 'Nomes de colunas não puderam ser derivados. O arquivo tem um cabeçalho?',\n          noObjects: 'Objetos não puderam ser derivados. Havia dados no arquivo, além dos cabeçalhos?',\n          invalidCsv: 'Arquivo não pode ser processado. É um CSV válido?',\n          invalidJson: 'Arquivo não pode ser processado. É um Json válido?',\n          jsonNotArray: 'Arquivo json importado tem que conter um array. Abortando.'\n        },\n        pagination: {\n          sizes: 'itens por página',\n          totalItems: 'itens'\n        },\n        grouping: {\n          group: 'Agrupar',\n          ungroup: 'Desagrupar',\n          aggregate_count: 'Agr: Contar',\n          aggregate_sum: 'Agr: Soma',\n          aggregate_max: 'Agr: Max',\n          aggregate_min: 'Agr: Min',\n          aggregate_avg: 'Agr: Med',\n          aggregate_remove: 'Agr: Remover'\n        }\n      });\n      return $delegate;\n    }]);\n}]);\n})();\n\n(function () {\n  angular.module('ui.grid').config(['$provide', function($provide) {\n    $provide.decorator('i18nService', ['$delegate', function($delegate) {\n      $delegate.add('pt', {\n        aggregate: {\n          label: 'itens'\n        },\n        groupPanel: {\n          description: 'Arraste e solte uma coluna aqui para agrupar por essa coluna'\n        },\n        search: {\n          placeholder: 'Procurar...',\n          showingItems: 'Mostrando os Itens:',\n          selectedItems: 'Itens Selecionados:',\n          totalItems: 'Total de Itens:',\n          size: 'Tamanho da Página:',\n          first: 'Primeira Página',\n          next: 'Próxima Página',\n          previous: 'Página Anterior',\n          last: 'Última Página'\n        },\n        menu: {\n          text: 'Selecione as colunas:'\n        },\n        sort: {\n          ascending: 'Ordenar Ascendente',\n          descending: 'Ordenar Descendente',\n          remove: 'Remover Ordenação'\n        },\n        column: {\n          hide: 'Esconder coluna'\n        },\n        aggregation: {\n          count: 'total de linhas: ',\n          sum: 'total: ',\n          avg: 'med: ',\n          min: 'min: ',\n          max: 'max: '\n        },\n        pinning: {\n          pinLeft: 'Fixar Esquerda',\n          pinRight: 'Fixar Direita',\n          unpin: 'Desprender'\n        },\n        gridMenu: {\n          columns: 'Colunas:',\n          importerTitle: 'Importar ficheiro',\n          exporterAllAsCsv: 'Exportar todos os dados como csv',\n          exporterVisibleAsCsv: 'Exportar dados visíveis como csv',\n          exporterSelectedAsCsv: 'Exportar dados selecionados como csv',\n          exporterAllAsPdf: 'Exportar todos os dados como pdf',\n          exporterVisibleAsPdf: 'Exportar dados visíveis como pdf',\n          exporterSelectedAsPdf: 'Exportar dados selecionados como pdf'\n        },\n        importer: {\n          noHeaders: 'Nomes de colunas não puderam ser derivados. O ficheiro tem um cabeçalho?',\n          noObjects: 'Objetos não puderam ser derivados. Havia dados no ficheiro, além dos cabeçalhos?',\n          invalidCsv: 'Ficheiro não pode ser processado. É um CSV válido?',\n          invalidJson: 'Ficheiro não pode ser processado. É um Json válido?',\n          jsonNotArray: 'Ficheiro json importado tem que conter um array. Interrompendo.'\n        },\n        pagination: {\n          sizes: 'itens por página',\n          totalItems: 'itens',\n          of: 'de'\n        },\n        grouping: {\n          group: 'Agrupar',\n          ungroup: 'Desagrupar',\n          aggregate_count: 'Agr: Contar',\n          aggregate_sum: 'Agr: Soma',\n          aggregate_max: 'Agr: Max',\n          aggregate_min: 'Agr: Min',\n          aggregate_avg: 'Agr: Med',\n          aggregate_remove: 'Agr: Remover'\n        }        \n      });\n      return $delegate;\n    }]);\n}]);\n})();\n\n(function () {\n  angular.module('ui.grid').config(['$provide', function($provide) {\n    $provide.decorator('i18nService', ['$delegate', function($delegate) {\n      $delegate.add('ru', {\n        aggregate: {\n          label: 'элементы'\n        },\n        groupPanel: {\n          description: 'Для группировки по столбцу перетащите сюда его название.'\n        },\n        search: {\n          placeholder: 'Поиск...',\n          showingItems: 'Показать элементы:',\n          selectedItems: 'Выбранные элементы:',\n          totalItems: 'Всего элементов:',\n          size: 'Размер страницы:',\n          first: 'Первая страница',\n          next: 'Следующая страница',\n          previous: 'Предыдущая страница',\n          last: 'Последняя страница'\n        },\n        menu: {\n          text: 'Выбрать столбцы:'\n        },\n        sort: {\n          ascending: 'По возрастанию',\n          descending: 'По убыванию',\n          remove: 'Убрать сортировку'\n        },\n        column: {\n          hide: 'спрятать столбец'\n        },\n        aggregation: {\n          count: 'всего строк: ',\n          sum: 'итого: ',\n          avg: 'среднее: ',\n          min: 'мин: ',\n          max: 'макс: '\n        },\n        gridMenu: {\n          columns: 'Столбцы:',\n          importerTitle: 'Import file',\n          exporterAllAsCsv: 'Экспортировать всё в CSV',\n          exporterVisibleAsCsv: 'Экспортировать видимые данные в CSV',\n          exporterSelectedAsCsv: 'Экспортировать выбранные данные в CSV',\n          exporterAllAsPdf: 'Экспортировать всё в PDF',\n          exporterVisibleAsPdf: 'Экспортировать видимые данные в PDF',\n          exporterSelectedAsPdf: 'Экспортировать выбранные данные в PDF'\n        },\n        importer: {\n          noHeaders: 'Column names were unable to be derived, does the file have a header?',\n          noObjects: 'Objects were not able to be derived, was there data in the file other than headers?',\n          invalidCsv: 'File was unable to be processed, is it valid CSV?',\n          invalidJson: 'File was unable to be processed, is it valid Json?',\n          jsonNotArray: 'Imported json file must contain an array, aborting.'\n        }\n      });\n      return $delegate;\n    }]);\n  }]);\n})();\n\n(function () {\n  angular.module('ui.grid').config(['$provide', function($provide) {\n    $provide.decorator('i18nService', ['$delegate', function($delegate) {\n      $delegate.add('sk', {\n        aggregate: {\n          label: 'items'\n        },\n        groupPanel: {\n          description: 'Pretiahni sem názov stĺpca pre zoskupenie podľa toho stĺpca.'\n        },\n        search: {\n          placeholder: 'Hľadaj...',\n          showingItems: 'Zobrazujem položky:',\n          selectedItems: 'Vybraté položky:',\n          totalItems: 'Počet položiek:',\n          size: 'Počet:',\n          first: 'Prvá strana',\n          next: 'Ďalšia strana',\n          previous: 'Predchádzajúca strana',\n          last: 'Posledná strana'\n        },\n        menu: {\n          text: 'Vyberte stĺpce:'\n        },\n        sort: {\n          ascending: 'Zotriediť vzostupne',\n          descending: 'Zotriediť zostupne',\n          remove: 'Vymazať triedenie'\n        },\n        aggregation: {\n          count: 'total rows: ',\n          sum: 'total: ',\n          avg: 'avg: ',\n          min: 'min: ',\n          max: 'max: '\n        },\n        gridMenu: {\n          columns: 'Columns:',\n          importerTitle: 'Import file',\n          exporterAllAsCsv: 'Export all data as csv',\n          exporterVisibleAsCsv: 'Export visible data as csv',\n          exporterSelectedAsCsv: 'Export selected data as csv',\n          exporterAllAsPdf: 'Export all data as pdf',\n          exporterVisibleAsPdf: 'Export visible data as pdf',\n          exporterSelectedAsPdf: 'Export selected data as pdf'\n        },\n        importer: {\n          noHeaders: 'Column names were unable to be derived, does the file have a header?',\n          noObjects: 'Objects were not able to be derived, was there data in the file other than headers?',\n          invalidCsv: 'File was unable to be processed, is it valid CSV?',\n          invalidJson: 'File was unable to be processed, is it valid Json?',\n          jsonNotArray: 'Imported json file must contain an array, aborting.'\n        }\n      });\n      return $delegate;\n    }]);\n  }]);\n})();\n\n(function () {\n  angular.module('ui.grid').config(['$provide', function($provide) {\n    $provide.decorator('i18nService', ['$delegate', function($delegate) {\n      $delegate.add('sv', {\n        aggregate: {\n          label: 'Artiklar'\n        },\n        groupPanel: {\n          description: 'Dra en kolumnrubrik hit och släpp den för att gruppera efter den kolumnen.'\n        },\n        search: {\n          placeholder: 'Sök...',\n          showingItems: 'Visar artiklar:',\n          selectedItems: 'Valda artiklar:',\n          totalItems: 'Antal artiklar:',\n          size: 'Sidstorlek:',\n          first: 'Första sidan',\n          next: 'Nästa sida',\n          previous: 'Föregående sida',\n          last: 'Sista sidan'\n        },\n        menu: {\n          text: 'Välj kolumner:'\n        },\n        sort: {\n          ascending: 'Sortera stigande',\n          descending: 'Sortera fallande',\n          remove: 'Inaktivera sortering'\n        },\n        column: {\n          hide: 'Göm kolumn'\n        },\n        aggregation: {\n          count: 'Antal rader: ',\n          sum: 'Summa: ',\n          avg: 'Genomsnitt: ',\n          min: 'Min: ',\n          max: 'Max: '\n        },\n        pinning: {\n          pinLeft: 'Fäst vänster',\n          pinRight: 'Fäst höger',\n          unpin: 'Lösgör'\n        },\n        gridMenu: {\n          columns: 'Kolumner:',\n          importerTitle: 'Importera fil',\n          exporterAllAsCsv: 'Exportera all data som CSV',\n          exporterVisibleAsCsv: 'Exportera synlig data som CSV',\n          exporterSelectedAsCsv: 'Exportera markerad data som CSV',\n          exporterAllAsPdf: 'Exportera all data som PDF',\n          exporterVisibleAsPdf: 'Exportera synlig data som PDF',\n          exporterSelectedAsPdf: 'Exportera markerad data som PDF'\n        },\n        importer: {\n          noHeaders: 'Kolumnnamn kunde inte härledas. Har filen ett sidhuvud?',\n          noObjects: 'Objekt kunde inte härledas. Har filen data undantaget sidhuvud?',\n          invalidCsv: 'Filen kunde inte behandlas, är den en giltig CSV?',\n          invalidJson: 'Filen kunde inte behandlas, är den en giltig JSON?',\n          jsonNotArray: 'Importerad JSON-fil måste innehålla ett fält. Import avbruten.'\n        },\n        pagination: {\n          sizes: 'Artiklar per sida',\n          totalItems: 'Artiklar'\n        }\n      });\n      return $delegate;\n    }]);\n  }]);\n})();\n\n(function () {\n  angular.module('ui.grid').config(['$provide', function($provide) {\n    $provide.decorator('i18nService', ['$delegate', function($delegate) {\n      $delegate.add('ta', {\n        aggregate: {\n          label: 'உருப்படிகள்'\n        },\n        groupPanel: {\n          description: 'ஒரு பத்தியை குழுவாக அமைக்க அப்பத்தியின் தலைப்பை இங்கே  இழுத்து வரவும் '\n        },\n        search: {\n          placeholder: 'தேடல் ...',\n          showingItems: 'உருப்படிகளை காண்பித்தல்:',\n          selectedItems: 'தேர்ந்தெடுக்கப்பட்ட  உருப்படிகள்:',\n          totalItems: 'மொத்த உருப்படிகள்:',\n          size: 'பக்க அளவு: ',\n          first: 'முதல் பக்கம்',\n          next: 'அடுத்த பக்கம்',\n          previous: 'முந்தைய பக்கம் ',\n          last: 'இறுதி பக்கம்'\n        },\n        menu: {\n          text: 'பத்திகளை தேர்ந்தெடு:'\n        },\n        sort: {\n          ascending: 'மேலிருந்து கீழாக',\n          descending: 'கீழிருந்து மேலாக',\n          remove: 'வரிசையை நீக்கு'\n        },\n        column: {\n          hide: 'பத்தியை மறைத்து வை '\n        },\n        aggregation: {\n          count: 'மொத்த வரிகள்:',\n          sum: 'மொத்தம்: ',\n          avg: 'சராசரி: ',\n          min: 'குறைந்தபட்ச: ',\n          max: 'அதிகபட்ச: '\n        },\n        pinning: {\n         pinLeft: 'இடதுபுறமாக தைக்க ',\n          pinRight: 'வலதுபுறமாக தைக்க',\n          unpin: 'பிரி'\n        },\n        gridMenu: {\n          columns: 'பத்திகள்:',\n          importerTitle: 'கோப்பு : படித்தல்',\n          exporterAllAsCsv: 'எல்லா தரவுகளையும் கோப்பாக்கு: csv',\n          exporterVisibleAsCsv: 'இருக்கும் தரவுகளை கோப்பாக்கு: csv',\n          exporterSelectedAsCsv: 'தேர்ந்தெடுத்த தரவுகளை கோப்பாக்கு: csv',\n          exporterAllAsPdf: 'எல்லா தரவுகளையும் கோப்பாக்கு: pdf',\n          exporterVisibleAsPdf: 'இருக்கும் தரவுகளை கோப்பாக்கு: pdf',\n          exporterSelectedAsPdf: 'தேர்ந்தெடுத்த தரவுகளை கோப்பாக்கு: pdf'\n        },\n        importer: {\n          noHeaders: 'பத்தியின் தலைப்புகளை பெற இயலவில்லை, கோப்பிற்கு தலைப்பு உள்ளதா?',\n          noObjects: 'இலக்குகளை உருவாக்க முடியவில்லை, கோப்பில் தலைப்புகளை தவிர தரவு ஏதேனும் உள்ளதா? ',\n          invalidCsv:\t'சரிவர நடைமுறை படுத்த இயலவில்லை, கோப்பு சரிதானா? - csv',\n          invalidJson: 'சரிவர நடைமுறை படுத்த இயலவில்லை, கோப்பு சரிதானா? - json',\n          jsonNotArray: 'படித்த கோப்பில் வரிசைகள் உள்ளது, நடைமுறை ரத்து செய் : json'\n        },\n        pagination: {\n          sizes\t\t: 'உருப்படிகள் / பக்கம்',\n          totalItems\t: 'உருப்படிகள் '\n        },\n        grouping: {\n          group\t: 'குழு',\n          ungroup : 'பிரி',\n          aggregate_count\t: 'மதிப்பீட்டு : எண்ணு',\n          aggregate_sum : 'மதிப்பீட்டு : கூட்டல்',\n          aggregate_max\t: 'மதிப்பீட்டு : அதிகபட்சம்',\n          aggregate_min\t: 'மதிப்பீட்டு : குறைந்தபட்சம்',\n          aggregate_avg\t: 'மதிப்பீட்டு : சராசரி',\n          aggregate_remove : 'மதிப்பீட்டு : நீக்கு'\n        }\n      });\n      return $delegate;\n    }]);\n  }]);\n})();\n\n/**\n * @ngdoc overview\n * @name ui.grid.i18n\n * @description\n *\n *  # ui.grid.i18n\n * This module provides i18n functions to ui.grid and any application that wants to use it\n\n *\n * <div doc-module-components=\"ui.grid.i18n\"></div>\n */\n\n(function () {\n  var DIRECTIVE_ALIASES = ['uiT', 'uiTranslate'];\n  var FILTER_ALIASES = ['t', 'uiTranslate'];\n\n  var module = angular.module('ui.grid.i18n');\n\n\n  /**\n   *  @ngdoc object\n   *  @name ui.grid.i18n.constant:i18nConstants\n   *\n   *  @description constants available in i18n module\n   */\n  module.constant('i18nConstants', {\n    MISSING: '[MISSING]',\n    UPDATE_EVENT: '$uiI18n',\n\n    LOCALE_DIRECTIVE_ALIAS: 'uiI18n',\n    // default to english\n    DEFAULT_LANG: 'en'\n  });\n\n//    module.config(['$provide', function($provide) {\n//        $provide.decorator('i18nService', ['$delegate', function($delegate) {}])}]);\n\n  /**\n   *  @ngdoc service\n   *  @name ui.grid.i18n.service:i18nService\n   *\n   *  @description Services for i18n\n   */\n  module.service('i18nService', ['$log', 'i18nConstants', '$rootScope',\n    function ($log, i18nConstants, $rootScope) {\n\n      var langCache = {\n        _langs: {},\n        current: null,\n        get: function (lang) {\n          return this._langs[lang.toLowerCase()];\n        },\n        add: function (lang, strings) {\n          var lower = lang.toLowerCase();\n          if (!this._langs[lower]) {\n            this._langs[lower] = {};\n          }\n          angular.extend(this._langs[lower], strings);\n        },\n        getAllLangs: function () {\n          var langs = [];\n          if (!this._langs) {\n            return langs;\n          }\n\n          for (var key in this._langs) {\n            langs.push(key);\n          }\n\n          return langs;\n        },\n        setCurrent: function (lang) {\n          this.current = lang.toLowerCase();\n        },\n        getCurrentLang: function () {\n          return this.current;\n        }\n      };\n\n      var service = {\n\n        /**\n         * @ngdoc service\n         * @name add\n         * @methodOf ui.grid.i18n.service:i18nService\n         * @description  Adds the languages and strings to the cache. Decorate this service to\n         * add more translation strings\n         * @param {string} lang language to add\n         * @param {object} stringMaps of strings to add grouped by property names\n         * @example\n         * <pre>\n         *      i18nService.add('en', {\n         *         aggregate: {\n         *                 label1: 'items',\n         *                 label2: 'some more items'\n         *                 }\n         *         },\n         *         groupPanel: {\n         *              description: 'Drag a column header here and drop it to group by that column.'\n         *           }\n         *      }\n         * </pre>\n         */\n        add: function (langs, stringMaps) {\n          if (typeof(langs) === 'object') {\n            angular.forEach(langs, function (lang) {\n              if (lang) {\n                langCache.add(lang, stringMaps);\n              }\n            });\n          } else {\n            langCache.add(langs, stringMaps);\n          }\n        },\n\n        /**\n         * @ngdoc service\n         * @name getAllLangs\n         * @methodOf ui.grid.i18n.service:i18nService\n         * @description  return all currently loaded languages\n         * @returns {array} string\n         */\n        getAllLangs: function () {\n          return langCache.getAllLangs();\n        },\n\n        /**\n         * @ngdoc service\n         * @name get\n         * @methodOf ui.grid.i18n.service:i18nService\n         * @description  return all currently loaded languages\n         * @param {string} lang to return.  If not specified, returns current language\n         * @returns {object} the translation string maps for the language\n         */\n        get: function (lang) {\n          var language = lang ? lang : service.getCurrentLang();\n          return langCache.get(language);\n        },\n\n        /**\n         * @ngdoc service\n         * @name getSafeText\n         * @methodOf ui.grid.i18n.service:i18nService\n         * @description  returns the text specified in the path or a Missing text if text is not found\n         * @param {string} path property path to use for retrieving text from string map\n         * @param {string} lang to return.  If not specified, returns current language\n         * @returns {object} the translation for the path\n         * @example\n         * <pre>\n         * i18nService.getSafeText('sort.ascending')\n         * </pre>\n         */\n        getSafeText: function (path, lang) {\n          var language = lang ? lang : service.getCurrentLang();\n          var trans = langCache.get(language);\n\n          if (!trans) {\n            return i18nConstants.MISSING;\n          }\n\n          var paths = path.split('.');\n          var current = trans;\n\n          for (var i = 0; i < paths.length; ++i) {\n            if (current[paths[i]] === undefined || current[paths[i]] === null) {\n              return i18nConstants.MISSING;\n            } else {\n              current = current[paths[i]];\n            }\n          }\n\n          return current;\n\n        },\n\n        /**\n         * @ngdoc service\n         * @name setCurrentLang\n         * @methodOf ui.grid.i18n.service:i18nService\n         * @description sets the current language to use in the application\n         * $broadcasts the Update_Event on the $rootScope\n         * @param {string} lang to set\n         * @example\n         * <pre>\n         * i18nService.setCurrentLang('fr');\n         * </pre>\n         */\n\n        setCurrentLang: function (lang) {\n          if (lang) {\n            langCache.setCurrent(lang);\n            $rootScope.$broadcast(i18nConstants.UPDATE_EVENT);\n          }\n        },\n\n        /**\n         * @ngdoc service\n         * @name getCurrentLang\n         * @methodOf ui.grid.i18n.service:i18nService\n         * @description returns the current language used in the application\n         */\n        getCurrentLang: function () {\n          var lang = langCache.getCurrentLang();\n          if (!lang) {\n            lang = i18nConstants.DEFAULT_LANG;\n            langCache.setCurrent(lang);\n          }\n          return lang;\n        }\n\n      };\n\n      return service;\n\n    }]);\n\n  var localeDirective = function (i18nService, i18nConstants) {\n    return {\n      compile: function () {\n        return {\n          pre: function ($scope, $elm, $attrs) {\n            var alias = i18nConstants.LOCALE_DIRECTIVE_ALIAS;\n            // check for watchable property\n            var lang = $scope.$eval($attrs[alias]);\n            if (lang) {\n              $scope.$watch($attrs[alias], function () {\n                i18nService.setCurrentLang(lang);\n              });\n            } else if ($attrs.$$observers) {\n              $attrs.$observe(alias, function () {\n                i18nService.setCurrentLang($attrs[alias] || i18nConstants.DEFAULT_LANG);\n              });\n            }\n          }\n        };\n      }\n    };\n  };\n\n  module.directive('uiI18n', ['i18nService', 'i18nConstants', localeDirective]);\n\n  // directive syntax\n  var uitDirective = function ($parse, i18nService, i18nConstants) {\n    return {\n      restrict: 'EA',\n      compile: function () {\n        return {\n          pre: function ($scope, $elm, $attrs) {\n            var alias1 = DIRECTIVE_ALIASES[0],\n              alias2 = DIRECTIVE_ALIASES[1];\n            var token = $attrs[alias1] || $attrs[alias2] || $elm.html();\n            var missing = i18nConstants.MISSING + token;\n            var observer;\n            if ($attrs.$$observers) {\n              var prop = $attrs[alias1] ? alias1 : alias2;\n              observer = $attrs.$observe(prop, function (result) {\n                if (result) {\n                  $elm.html($parse(result)(i18nService.getCurrentLang()) || missing);\n                }\n              });\n            }\n            var getter = $parse(token);\n            var listener = $scope.$on(i18nConstants.UPDATE_EVENT, function (evt) {\n              if (observer) {\n                observer($attrs[alias1] || $attrs[alias2]);\n              } else {\n                // set text based on i18n current language\n                $elm.html(getter(i18nService.get()) || missing);\n              }\n            });\n            $scope.$on('$destroy', listener);\n\n            $elm.html(getter(i18nService.get()) || missing);\n          }\n        };\n      }\n    };\n  };\n\n  angular.forEach( DIRECTIVE_ALIASES, function ( alias ) {\n    module.directive( alias, ['$parse', 'i18nService', 'i18nConstants', uitDirective] );\n  } );\n\n  // optional filter syntax\n  var uitFilter = function ($parse, i18nService, i18nConstants) {\n    return function (data) {\n      var getter = $parse(data);\n      // set text based on i18n current language\n      return getter(i18nService.get()) || i18nConstants.MISSING + data;\n    };\n  };\n\n  angular.forEach( FILTER_ALIASES, function ( alias ) {\n    module.filter( alias, ['$parse', 'i18nService', 'i18nConstants', uitFilter] );\n  } );\n\n\n})();\n(function() {\n  angular.module('ui.grid').config(['$provide', function($provide) {\n    $provide.decorator('i18nService', ['$delegate', function($delegate) {\n      $delegate.add('zh-cn', {\n        aggregate: {\n          label: '行'\n        },\n        groupPanel: {\n          description: '拖曳表头到此处进行分组'\n        },\n        search: {\n          placeholder: '查找',\n          showingItems: '已显示行数：',\n          selectedItems: '已选择行数：',\n          totalItems: '总行数：',\n          size: '每页显示行数：',\n          first: '首页',\n          next: '下一页',\n          previous: '上一页',\n          last: '末页'\n        },\n        menu: {\n          text: '选择列：'\n        },\n        sort: {\n          ascending: '升序',\n          descending: '降序',\n          remove: '取消排序'\n        },\n        column: {\n          hide: '隐藏列'\n        },\n        aggregation: {\n          count: '计数：',\n          sum: '求和：',\n          avg: '均值：',\n          min: '最小值：',\n          max: '最大值：'\n        },\n        pinning: {\n          pinLeft: '左侧固定',\n          pinRight: '右侧固定',\n          unpin: '取消固定'\n        },\n        gridMenu: {\n          columns: '列：',\n          importerTitle: '导入文件',\n          exporterAllAsCsv: '导出全部数据到CSV',\n          exporterVisibleAsCsv: '导出可见数据到CSV',\n          exporterSelectedAsCsv: '导出已选数据到CSV',\n          exporterAllAsPdf: '导出全部数据到PDF',\n          exporterVisibleAsPdf: '导出可见数据到PDF',\n          exporterSelectedAsPdf: '导出已选数据到PDF'\n        },\n        importer: {\n          noHeaders: '无法获取列名，确定文件包含表头？',\n          noObjects: '无法获取数据，确定文件包含数据？',\n          invalidCsv: '无法处理文件，确定是合法的CSV文件？',\n          invalidJson: '无法处理文件，确定是合法的JSON文件？',\n          jsonNotArray: '导入的文件不是JSON数组！'\n        },\n        pagination: {\n          sizes: '行每页',\n          totalItems: '行'\n        }\n      });\n      return $delegate;\n    }]);\n  }]);\n})();\n\n(function() {\n  angular.module('ui.grid').config(['$provide', function($provide) {\n    $provide.decorator('i18nService', ['$delegate', function($delegate) {\n      $delegate.add('zh-tw', {\n        aggregate: {\n          label: '行'\n        },\n        groupPanel: {\n          description: '拖曳表頭到此處進行分組'\n        },\n        search: {\n          placeholder: '查找',\n          showingItems: '已顯示行數：',\n          selectedItems: '已選擇行數：',\n          totalItems: '總行數：',\n          size: '每頁顯示行數：',\n          first: '首頁',\n          next: '下壹頁',\n          previous: '上壹頁',\n          last: '末頁'\n        },\n        menu: {\n          text: '選擇列：'\n        },\n        sort: {\n          ascending: '升序',\n          descending: '降序',\n          remove: '取消排序'\n        },\n        column: {\n          hide: '隱藏列'\n        },\n        aggregation: {\n          count: '計數：',\n          sum: '求和：',\n          avg: '均值：',\n          min: '最小值：',\n          max: '最大值：'\n        },\n        pinning: {\n          pinLeft: '左側固定',\n          pinRight: '右側固定',\n          unpin: '取消固定'\n        },\n        gridMenu: {\n          columns: '列：',\n          importerTitle: '導入文件',\n          exporterAllAsCsv: '導出全部數據到CSV',\n          exporterVisibleAsCsv: '導出可見數據到CSV',\n          exporterSelectedAsCsv: '導出已選數據到CSV',\n          exporterAllAsPdf: '導出全部數據到PDF',\n          exporterVisibleAsPdf: '導出可見數據到PDF',\n          exporterSelectedAsPdf: '導出已選數據到PDF'\n        },\n        importer: {\n          noHeaders: '無法獲取列名，確定文件包含表頭？',\n          noObjects: '無法獲取數據，確定文件包含數據？',\n          invalidCsv: '無法處理文件，確定是合法的CSV文件？',\n          invalidJson: '無法處理文件，確定是合法的JSON文件？',\n          jsonNotArray: '導入的文件不是JSON數組！'\n        },\n        pagination: {\n          sizes: '行每頁',\n          totalItems: '行'\n        }\n      });\n      return $delegate;\n    }]);\n  }]);\n})();\n\n(function() {\n  'use strict';\n  /**\n   *  @ngdoc overview\n   *  @name ui.grid.autoResize\n   *\n   *  @description\n   *\n   *  #ui.grid.autoResize\n   *\n   *  <div class=\"alert alert-warning\" role=\"alert\"><strong>Beta</strong> This feature is ready for testing, but it either hasn't seen a lot of use or has some known bugs.</div>\n   *\n   *  This module provides auto-resizing functionality to UI-Grid.\n   */\n  var module = angular.module('ui.grid.autoResize', ['ui.grid']);\n\n\n  module.directive('uiGridAutoResize', ['$timeout', 'gridUtil', function ($timeout, gridUtil) {\n    return {\n      require: 'uiGrid',\n      scope: false,\n      link: function ($scope, $elm, $attrs, uiGridCtrl) {\n        var prevGridWidth, prevGridHeight;\n\n        function getDimensions() {\n          prevGridHeight = gridUtil.elementHeight($elm);\n          prevGridWidth = gridUtil.elementWidth($elm);\n        }\n\n        // Initialize the dimensions\n        getDimensions();\n\n        var resizeTimeoutId;\n        function startTimeout() {\n          clearTimeout(resizeTimeoutId);\n\n          resizeTimeoutId = setTimeout(function () {\n            var newGridHeight = gridUtil.elementHeight($elm);\n            var newGridWidth = gridUtil.elementWidth($elm);\n\n            if (newGridHeight !== prevGridHeight || newGridWidth !== prevGridWidth) {\n              uiGridCtrl.grid.gridHeight = newGridHeight;\n              uiGridCtrl.grid.gridWidth = newGridWidth;\n\n              $scope.$apply(function () {\n                uiGridCtrl.grid.refresh()\n                  .then(function () {\n                    getDimensions();\n\n                    startTimeout();\n                  });\n              });\n            }\n            else {\n              startTimeout();\n            }\n          }, 250);\n        }\n\n        startTimeout();\n\n        $scope.$on('$destroy', function() {\n          clearTimeout(resizeTimeoutId);\n        });\n      }\n    };\n  }]);\n})();\n\n(function () {\n  'use strict';\n\n  /**\n   *  @ngdoc overview\n   *  @name ui.grid.cellNav\n   *\n   *  @description\n\n      #ui.grid.cellNav\n\n      <div class=\"alert alert-success\" role=\"alert\"><strong>Stable</strong> This feature is stable. There should no longer be breaking api changes without a deprecation warning.</div>\n\n      This module provides auto-resizing functionality to UI-Grid.\n   */\n  var module = angular.module('ui.grid.cellNav', ['ui.grid']);\n\n  /**\n   *  @ngdoc object\n   *  @name ui.grid.cellNav.constant:uiGridCellNavConstants\n   *\n   *  @description constants available in cellNav\n   */\n  module.constant('uiGridCellNavConstants', {\n    FEATURE_NAME: 'gridCellNav',\n    CELL_NAV_EVENT: 'cellNav',\n    direction: {LEFT: 0, RIGHT: 1, UP: 2, DOWN: 3, PG_UP: 4, PG_DOWN: 5},\n    EVENT_TYPE: {\n      KEYDOWN: 0,\n      CLICK: 1,\n      CLEAR: 2\n    }\n  });\n\n  /**\n   * @ngdoc object\n   * @name ui.grid.cellNav.object:RowCol\n   * @param {GridRow} row The row for this pair\n   * @param {GridColumn} column The column for this pair\n   * @description A row and column pair that represents the intersection of these two entities.\n   */\n  module.factory('RowColFactory', ['$parse', '$filter',\n    function($parse, $filter){\n      var RowCol = function RowCol(row, col) {\n        /**\n         * @ngdoc object\n         * @name row\n         * @propertyOf ui.grid.cellNav.object:RowCol\n         * @description {@link ui.grid.class:GridRow }\n         */\n        this.row = row;\n        /**\n         * @ngdoc object\n         * @name col\n         * @propertyOf ui.grid.cellNav.object:RowCol\n         * @description {@link ui.grid.class:GridColumn }\n         */\n        this.col = col;\n      };\n\n      /**\n       * @ngdoc function\n       * @name getIntersectionValueRaw\n       * @methodOf ui.grid.cellNav.object:RowCol\n       * @description Gets the intersection of where the row and column meet.\n       * @returns {String|Number|Object} The value from the grid data that this RowCol points too.\n       *          If the column has a cellFilter this will NOT return the filtered value.\n       */\n      RowCol.prototype.getIntersectionValueRaw = function(){\n        var getter = $parse(this.col.field);\n        var context = this.row.entity;\n        return getter(context);\n      };\n      /**\n       * @ngdoc function\n       * @name getIntersectionValueFiltered\n       * @methodOf ui.grid.cellNav.object:RowCol\n       * @description Gets the intersection of where the row and column meet.\n       * @returns {String|Number|Object} The value from the grid data that this RowCol points too.\n       *          If the column has a cellFilter this will also apply the filter to it and return the value that the filter displays.\n       */\n      RowCol.prototype.getIntersectionValueFiltered = function(){\n        var value = this.getIntersectionValueRaw();\n        if (this.col.cellFilter && this.col.cellFilter !== ''){\n          var getFilterIfExists = function(filterName){\n            try {\n              return $filter(filterName);\n            } catch (e){\n              return null;\n            }\n          };\n          var filter = getFilterIfExists(this.col.cellFilter);\n          if (filter) { // Check if this is filter name or a filter string\n            value = filter(value);\n          } else { // We have the template version of a filter so we need to parse it apart\n            // Get the filter params out using a regex\n            // Test out this regex here https://regex101.com/r/rC5eR5/2\n            var re = /([^:]*):([^:]*):?([\\s\\S]+)?/;\n            var matches;\n            if ((matches = re.exec(this.col.cellFilter)) !== null) {\n                // View your result using the matches-variable.\n                // eg matches[0] etc.\n                value = $filter(matches[1])(value, matches[2], matches[3]);\n            }\n          }\n        }\n        return value;\n      };\n      return RowCol;\n    }]);\n\n\n  module.factory('uiGridCellNavFactory', ['gridUtil', 'uiGridConstants', 'uiGridCellNavConstants', 'RowColFactory', '$q',\n    function (gridUtil, uiGridConstants, uiGridCellNavConstants, RowCol, $q) {\n      /**\n       *  @ngdoc object\n       *  @name ui.grid.cellNav.object:CellNav\n       *  @description returns a CellNav prototype function\n       *  @param {object} rowContainer container for rows\n       *  @param {object} colContainer parent column container\n       *  @param {object} leftColContainer column container to the left of parent\n       *  @param {object} rightColContainer column container to the right of parent\n       */\n      var UiGridCellNav = function UiGridCellNav(rowContainer, colContainer, leftColContainer, rightColContainer) {\n        this.rows = rowContainer.visibleRowCache;\n        this.columns = colContainer.visibleColumnCache;\n        this.leftColumns = leftColContainer ? leftColContainer.visibleColumnCache : [];\n        this.rightColumns = rightColContainer ? rightColContainer.visibleColumnCache : [];\n        this.bodyContainer = rowContainer;\n      };\n\n      /** returns focusable columns of all containers */\n      UiGridCellNav.prototype.getFocusableCols = function () {\n        var allColumns = this.leftColumns.concat(this.columns, this.rightColumns);\n\n        return allColumns.filter(function (col) {\n          return col.colDef.allowCellFocus;\n        });\n      };\n\n      /**\n       *  @ngdoc object\n       *  @name ui.grid.cellNav.api:GridRow\n       *\n       *  @description GridRow settings for cellNav feature, these are available to be\n       *  set only internally (for example, by other features)\n       */\n\n      /**\n       *  @ngdoc object\n       *  @name allowCellFocus\n       *  @propertyOf  ui.grid.cellNav.api:GridRow\n       *  @description Enable focus on a cell within this row.  If set to false then no cells\n       *  in this row can be focused - group header rows as an example would set this to false.\n       *  <br/>Defaults to true\n       */\n      /** returns focusable rows */\n      UiGridCellNav.prototype.getFocusableRows = function () {\n        return this.rows.filter(function(row) {\n          return row.allowCellFocus !== false;\n        });\n      };\n\n      UiGridCellNav.prototype.getNextRowCol = function (direction, curRow, curCol) {\n        switch (direction) {\n          case uiGridCellNavConstants.direction.LEFT:\n            return this.getRowColLeft(curRow, curCol);\n          case uiGridCellNavConstants.direction.RIGHT:\n            return this.getRowColRight(curRow, curCol);\n          case uiGridCellNavConstants.direction.UP:\n            return this.getRowColUp(curRow, curCol);\n          case uiGridCellNavConstants.direction.DOWN:\n            return this.getRowColDown(curRow, curCol);\n          case uiGridCellNavConstants.direction.PG_UP:\n            return this.getRowColPageUp(curRow, curCol);\n          case uiGridCellNavConstants.direction.PG_DOWN:\n            return this.getRowColPageDown(curRow, curCol);\n        }\n\n      };\n\n      UiGridCellNav.prototype.initializeSelection = function () {\n        var focusableCols = this.getFocusableCols();\n        var focusableRows = this.getFocusableRows();\n        if (focusableCols.length === 0 || focusableRows.length === 0) {\n          return null;\n        }\n\n        var curRowIndex = 0;\n        var curColIndex = 0;\n        return new RowCol(focusableRows[0], focusableCols[0]); //return same row\n      };\n\n      UiGridCellNav.prototype.getRowColLeft = function (curRow, curCol) {\n        var focusableCols = this.getFocusableCols();\n        var focusableRows = this.getFocusableRows();\n        var curColIndex = focusableCols.indexOf(curCol);\n        var curRowIndex = focusableRows.indexOf(curRow);\n\n        //could not find column in focusable Columns so set it to 1\n        if (curColIndex === -1) {\n          curColIndex = 1;\n        }\n\n        var nextColIndex = curColIndex === 0 ? focusableCols.length - 1 : curColIndex - 1;\n\n        //get column to left\n        if (nextColIndex > curColIndex) {\n          // On the first row\n          // if (curRowIndex === 0 && curColIndex === 0) {\n          //   return null;\n          // }\n          if (curRowIndex === 0) {\n            return new RowCol(curRow, focusableCols[nextColIndex]); //return same row\n          }\n          else {\n            //up one row and far right column\n            return new RowCol(focusableRows[curRowIndex - 1], focusableCols[nextColIndex]);\n          }\n        }\n        else {\n          return new RowCol(curRow, focusableCols[nextColIndex]);\n        }\n      };\n\n\n\n      UiGridCellNav.prototype.getRowColRight = function (curRow, curCol) {\n        var focusableCols = this.getFocusableCols();\n        var focusableRows = this.getFocusableRows();\n        var curColIndex = focusableCols.indexOf(curCol);\n        var curRowIndex = focusableRows.indexOf(curRow);\n\n        //could not find column in focusable Columns so set it to 0\n        if (curColIndex === -1) {\n          curColIndex = 0;\n        }\n        var nextColIndex = curColIndex === focusableCols.length - 1 ? 0 : curColIndex + 1;\n\n        if (nextColIndex < curColIndex) {\n          if (curRowIndex === focusableRows.length - 1) {\n            return new RowCol(curRow, focusableCols[nextColIndex]); //return same row\n          }\n          else {\n            //down one row and far left column\n            return new RowCol(focusableRows[curRowIndex + 1], focusableCols[nextColIndex]);\n          }\n        }\n        else {\n          return new RowCol(curRow, focusableCols[nextColIndex]);\n        }\n      };\n\n      UiGridCellNav.prototype.getRowColDown = function (curRow, curCol) {\n        var focusableCols = this.getFocusableCols();\n        var focusableRows = this.getFocusableRows();\n        var curColIndex = focusableCols.indexOf(curCol);\n        var curRowIndex = focusableRows.indexOf(curRow);\n\n        //could not find column in focusable Columns so set it to 0\n        if (curColIndex === -1) {\n          curColIndex = 0;\n        }\n\n        if (curRowIndex === focusableRows.length - 1) {\n          return new RowCol(curRow, focusableCols[curColIndex]); //return same row\n        }\n        else {\n          //down one row\n          return new RowCol(focusableRows[curRowIndex + 1], focusableCols[curColIndex]);\n        }\n      };\n\n      UiGridCellNav.prototype.getRowColPageDown = function (curRow, curCol) {\n        var focusableCols = this.getFocusableCols();\n        var focusableRows = this.getFocusableRows();\n        var curColIndex = focusableCols.indexOf(curCol);\n        var curRowIndex = focusableRows.indexOf(curRow);\n\n        //could not find column in focusable Columns so set it to 0\n        if (curColIndex === -1) {\n          curColIndex = 0;\n        }\n\n        var pageSize = this.bodyContainer.minRowsToRender();\n        if (curRowIndex >= focusableRows.length - pageSize) {\n          return new RowCol(focusableRows[focusableRows.length - 1], focusableCols[curColIndex]); //return last row\n        }\n        else {\n          //down one page\n          return new RowCol(focusableRows[curRowIndex + pageSize], focusableCols[curColIndex]);\n        }\n      };\n\n      UiGridCellNav.prototype.getRowColUp = function (curRow, curCol) {\n        var focusableCols = this.getFocusableCols();\n        var focusableRows = this.getFocusableRows();\n        var curColIndex = focusableCols.indexOf(curCol);\n        var curRowIndex = focusableRows.indexOf(curRow);\n\n        //could not find column in focusable Columns so set it to 0\n        if (curColIndex === -1) {\n          curColIndex = 0;\n        }\n\n        if (curRowIndex === 0) {\n          return new RowCol(curRow, focusableCols[curColIndex]); //return same row\n        }\n        else {\n          //up one row\n          return new RowCol(focusableRows[curRowIndex - 1], focusableCols[curColIndex]);\n        }\n      };\n\n      UiGridCellNav.prototype.getRowColPageUp = function (curRow, curCol) {\n        var focusableCols = this.getFocusableCols();\n        var focusableRows = this.getFocusableRows();\n        var curColIndex = focusableCols.indexOf(curCol);\n        var curRowIndex = focusableRows.indexOf(curRow);\n\n        //could not find column in focusable Columns so set it to 0\n        if (curColIndex === -1) {\n          curColIndex = 0;\n        }\n\n        var pageSize = this.bodyContainer.minRowsToRender();\n        if (curRowIndex - pageSize < 0) {\n          return new RowCol(focusableRows[0], focusableCols[curColIndex]); //return first row\n        }\n        else {\n          //up one page\n          return new RowCol(focusableRows[curRowIndex - pageSize], focusableCols[curColIndex]);\n        }\n      };\n      return UiGridCellNav;\n    }]);\n\n  /**\n   *  @ngdoc service\n   *  @name ui.grid.cellNav.service:uiGridCellNavService\n   *\n   *  @description Services for cell navigation features. If you don't like the key maps we use,\n   *  or the direction cells navigation, override with a service decorator (see angular docs)\n   */\n  module.service('uiGridCellNavService', ['gridUtil', 'uiGridConstants', 'uiGridCellNavConstants', '$q', 'uiGridCellNavFactory', 'RowColFactory', 'ScrollEvent',\n    function (gridUtil, uiGridConstants, uiGridCellNavConstants, $q, UiGridCellNav, RowCol, ScrollEvent) {\n\n      var service = {\n\n        initializeGrid: function (grid) {\n          grid.registerColumnBuilder(service.cellNavColumnBuilder);\n\n\n          /**\n           *  @ngdoc object\n           *  @name ui.grid.cellNav:Grid.cellNav\n           * @description cellNav properties added to grid class\n           */\n          grid.cellNav = {};\n          grid.cellNav.lastRowCol = null;\n          grid.cellNav.focusedCells = [];\n\n          service.defaultGridOptions(grid.options);\n\n          /**\n           *  @ngdoc object\n           *  @name ui.grid.cellNav.api:PublicApi\n           *\n           *  @description Public Api for cellNav feature\n           */\n          var publicApi = {\n            events: {\n              cellNav: {\n                /**\n                 * @ngdoc event\n                 * @name navigate\n                 * @eventOf  ui.grid.cellNav.api:PublicApi\n                 * @description raised when the active cell is changed\n                 * <pre>\n                 *      gridApi.cellNav.on.navigate(scope,function(newRowcol, oldRowCol){})\n                 * </pre>\n                 * @param {object} newRowCol new position\n                 * @param {object} oldRowCol old position\n                 */\n                navigate: function (newRowCol, oldRowCol) {},\n                /**\n                 * @ngdoc event\n                 * @name viewPortKeyDown\n                 * @eventOf  ui.grid.cellNav.api:PublicApi\n                 * @description  is raised when the viewPort receives a keyDown event. Cells never get focus in uiGrid\n                 * due to the difficulties of setting focus on a cell that is not visible in the viewport.  Use this\n                 * event whenever you need a keydown event on a cell\n                 * <br/>\n                 * @param {object} event keydown event\n                 * @param {object} rowCol current rowCol position\n                 */\n                viewPortKeyDown: function (event, rowCol) {},\n\n                /**\n                 * @ngdoc event\n                 * @name viewPortKeyPress\n                 * @eventOf  ui.grid.cellNav.api:PublicApi\n                 * @description  is raised when the viewPort receives a keyPress event. Cells never get focus in uiGrid\n                 * due to the difficulties of setting focus on a cell that is not visible in the viewport.  Use this\n                 * event whenever you need a keypress event on a cell\n                 * <br/>\n                 * @param {object} event keypress event\n                 * @param {object} rowCol current rowCol position\n                 */\n                viewPortKeyPress: function (event, rowCol) {}\n              }\n            },\n            methods: {\n              cellNav: {\n                /**\n                 * @ngdoc function\n                 * @name scrollToFocus\n                 * @methodOf  ui.grid.cellNav.api:PublicApi\n                 * @description brings the specified row and column into view, and sets focus\n                 * to that cell\n                 * @param {object} rowEntity gridOptions.data[] array instance to make visible and set focus\n                 * @param {object} colDef to make visible and set focus\n                 * @returns {promise} a promise that is resolved after any scrolling is finished\n                 */\n                scrollToFocus: function (rowEntity, colDef) {\n                  return service.scrollToFocus(grid, rowEntity, colDef);\n                },\n\n                /**\n                 * @ngdoc function\n                 * @name getFocusedCell\n                 * @methodOf  ui.grid.cellNav.api:PublicApi\n                 * @description returns the current (or last if Grid does not have focus) focused row and column\n                 * <br> value is null if no selection has occurred\n                 */\n                getFocusedCell: function () {\n                  return grid.cellNav.lastRowCol;\n                },\n\n                /**\n                 * @ngdoc function\n                 * @name getCurrentSelection\n                 * @methodOf  ui.grid.cellNav.api:PublicApi\n                 * @description returns an array containing the current selection\n                 * <br> array is empty if no selection has occurred\n                 */\n                getCurrentSelection: function () {\n                  return grid.cellNav.focusedCells;\n                },\n\n                /**\n                 * @ngdoc function\n                 * @name rowColSelectIndex\n                 * @methodOf  ui.grid.cellNav.api:PublicApi\n                 * @description returns the index in the order in which the RowCol was selected, returns -1 if the RowCol\n                 * isn't selected\n                 * @param {object} rowCol the rowCol to evaluate\n                 */\n                rowColSelectIndex: function (rowCol) {\n                  //return gridUtil.arrayContainsObjectWithProperty(grid.cellNav.focusedCells, 'col.uid', rowCol.col.uid) &&\n                  var index = -1;\n                  for (var i = 0; i < grid.cellNav.focusedCells.length; i++) {\n                    if (grid.cellNav.focusedCells[i].col.uid === rowCol.col.uid &&\n                      grid.cellNav.focusedCells[i].row.uid === rowCol.row.uid) {\n                      index = i;\n                      break;\n                    }\n                  }\n                  return index;\n                }\n              }\n            }\n          };\n\n          grid.api.registerEventsFromObject(publicApi.events);\n\n          grid.api.registerMethodsFromObject(publicApi.methods);\n\n        },\n\n        defaultGridOptions: function (gridOptions) {\n          /**\n           *  @ngdoc object\n           *  @name ui.grid.cellNav.api:GridOptions\n           *\n           *  @description GridOptions for cellNav feature, these are available to be\n           *  set using the ui-grid {@link ui.grid.class:GridOptions gridOptions}\n           */\n\n          /**\n           *  @ngdoc object\n           *  @name modifierKeysToMultiSelectCells\n           *  @propertyOf  ui.grid.cellNav.api:GridOptions\n           *  @description Enable multiple cell selection only when using the ctrlKey or shiftKey.\n           *  <br/>Defaults to false\n           */\n          gridOptions.modifierKeysToMultiSelectCells = gridOptions.modifierKeysToMultiSelectCells === true;\n\n        },\n\n        /**\n         * @ngdoc service\n         * @name decorateRenderContainers\n         * @methodOf ui.grid.cellNav.service:uiGridCellNavService\n         * @description  decorates grid renderContainers with cellNav functions\n         */\n        decorateRenderContainers: function (grid) {\n\n          var rightContainer = grid.hasRightContainer() ? grid.renderContainers.right : null;\n          var leftContainer = grid.hasLeftContainer() ? grid.renderContainers.left : null;\n\n          if (leftContainer !== null) {\n            grid.renderContainers.left.cellNav = new UiGridCellNav(grid.renderContainers.body, leftContainer, rightContainer, grid.renderContainers.body);\n          }\n          if (rightContainer !== null) {\n            grid.renderContainers.right.cellNav = new UiGridCellNav(grid.renderContainers.body, rightContainer, grid.renderContainers.body, leftContainer);\n          }\n\n          grid.renderContainers.body.cellNav = new UiGridCellNav(grid.renderContainers.body, grid.renderContainers.body, leftContainer, rightContainer);\n        },\n\n        /**\n         * @ngdoc service\n         * @name getDirection\n         * @methodOf ui.grid.cellNav.service:uiGridCellNavService\n         * @description  determines which direction to for a given keyDown event\n         * @returns {uiGridCellNavConstants.direction} direction\n         */\n        getDirection: function (evt) {\n          if (evt.keyCode === uiGridConstants.keymap.LEFT ||\n            (evt.keyCode === uiGridConstants.keymap.TAB && evt.shiftKey)) {\n            return uiGridCellNavConstants.direction.LEFT;\n          }\n          if (evt.keyCode === uiGridConstants.keymap.RIGHT ||\n            evt.keyCode === uiGridConstants.keymap.TAB) {\n            return uiGridCellNavConstants.direction.RIGHT;\n          }\n\n          if (evt.keyCode === uiGridConstants.keymap.UP ||\n            (evt.keyCode === uiGridConstants.keymap.ENTER && evt.shiftKey) ) {\n            return uiGridCellNavConstants.direction.UP;\n          }\n\n          if (evt.keyCode === uiGridConstants.keymap.PG_UP){\n            return uiGridCellNavConstants.direction.PG_UP;\n          }\n\n          if (evt.keyCode === uiGridConstants.keymap.DOWN ||\n            evt.keyCode === uiGridConstants.keymap.ENTER && !(evt.ctrlKey || evt.altKey)) {\n            return uiGridCellNavConstants.direction.DOWN;\n          }\n\n          if (evt.keyCode === uiGridConstants.keymap.PG_DOWN){\n            return uiGridCellNavConstants.direction.PG_DOWN;\n          }\n\n          return null;\n        },\n\n        /**\n         * @ngdoc service\n         * @name cellNavColumnBuilder\n         * @methodOf ui.grid.cellNav.service:uiGridCellNavService\n         * @description columnBuilder function that adds cell navigation properties to grid column\n         * @returns {promise} promise that will load any needed templates when resolved\n         */\n        cellNavColumnBuilder: function (colDef, col, gridOptions) {\n          var promises = [];\n\n          /**\n           *  @ngdoc object\n           *  @name ui.grid.cellNav.api:ColumnDef\n           *\n           *  @description Column Definitions for cellNav feature, these are available to be\n           *  set using the ui-grid {@link ui.grid.class:GridOptions.columnDef gridOptions.columnDefs}\n           */\n\n          /**\n           *  @ngdoc object\n           *  @name allowCellFocus\n           *  @propertyOf  ui.grid.cellNav.api:ColumnDef\n           *  @description Enable focus on a cell within this column.\n           *  <br/>Defaults to true\n           */\n          colDef.allowCellFocus = colDef.allowCellFocus === undefined ? true : colDef.allowCellFocus;\n\n          return $q.all(promises);\n        },\n\n        /**\n         * @ngdoc method\n         * @methodOf ui.grid.cellNav.service:uiGridCellNavService\n         * @name scrollToFocus\n         * @description Scroll the grid such that the specified\n         * row and column is in view, and set focus to the cell in that row and column\n         * @param {Grid} grid the grid you'd like to act upon, usually available\n         * from gridApi.grid\n         * @param {object} rowEntity gridOptions.data[] array instance to make visible and set focus to\n         * @param {object} colDef to make visible and set focus to\n         * @returns {promise} a promise that is resolved after any scrolling is finished\n         */\n        scrollToFocus: function (grid, rowEntity, colDef) {\n          var gridRow = null, gridCol = null;\n\n          if (typeof(rowEntity) !== 'undefined' && rowEntity !== null) {\n            gridRow = grid.getRow(rowEntity);\n          }\n\n          if (typeof(colDef) !== 'undefined' && colDef !== null) {\n            gridCol = grid.getColumn(colDef.name ? colDef.name : colDef.field);\n          }\n          return grid.api.core.scrollToIfNecessary(gridRow, gridCol).then(function () {\n            var rowCol = { row: gridRow, col: gridCol };\n\n            // Broadcast the navigation\n            if (gridRow !== null && gridCol !== null) {\n              grid.cellNav.broadcastCellNav(rowCol);\n            }\n          });\n\n\n\n        },\n\n\n        /**\n         * @ngdoc method\n         * @methodOf ui.grid.cellNav.service:uiGridCellNavService\n         * @name getLeftWidth\n         * @description Get the current drawn width of the columns in the\n         * grid up to the numbered column, and add an apportionment for the\n         * column that we're on.  So if we are on column 0, we want to scroll\n         * 0% (i.e. exclude this column from calc).  If we're on the last column\n         * we want to scroll to 100% (i.e. include this column in the calc). So\n         * we include (thisColIndex / totalNumberCols) % of this column width\n         * @param {Grid} grid the grid you'd like to act upon, usually available\n         * from gridApi.grid\n         * @param {gridCol} upToCol the column to total up to and including\n         */\n        getLeftWidth: function (grid, upToCol) {\n          var width = 0;\n\n          if (!upToCol) {\n            return width;\n          }\n\n          var lastIndex = grid.renderContainers.body.visibleColumnCache.indexOf( upToCol );\n\n          // total column widths up-to but not including the passed in column\n          grid.renderContainers.body.visibleColumnCache.forEach( function( col, index ) {\n            if ( index < lastIndex ){\n              width += col.drawnWidth;\n            }\n          });\n\n          // pro-rata the final column based on % of total columns.\n          var percentage = lastIndex === 0 ? 0 : (lastIndex + 1) / grid.renderContainers.body.visibleColumnCache.length;\n          width += upToCol.drawnWidth * percentage;\n\n          return width;\n        }\n      };\n\n      return service;\n    }]);\n\n  /**\n   *  @ngdoc directive\n   *  @name ui.grid.cellNav.directive:uiCellNav\n   *  @element div\n   *  @restrict EA\n   *\n   *  @description Adds cell navigation features to the grid columns\n   *\n   *  @example\n   <example module=\"app\">\n   <file name=\"app.js\">\n   var app = angular.module('app', ['ui.grid', 'ui.grid.cellNav']);\n\n   app.controller('MainCtrl', ['$scope', function ($scope) {\n      $scope.data = [\n        { name: 'Bob', title: 'CEO' },\n            { name: 'Frank', title: 'Lowly Developer' }\n      ];\n\n      $scope.columnDefs = [\n        {name: 'name'},\n        {name: 'title'}\n      ];\n    }]);\n   </file>\n   <file name=\"index.html\">\n   <div ng-controller=\"MainCtrl\">\n   <div ui-grid=\"{ data: data, columnDefs: columnDefs }\" ui-grid-cellnav></div>\n   </div>\n   </file>\n   </example>\n   */\n  module.directive('uiGridCellnav', ['gridUtil', 'uiGridCellNavService', 'uiGridCellNavConstants', 'uiGridConstants', 'RowColFactory', '$timeout', '$compile',\n    function (gridUtil, uiGridCellNavService, uiGridCellNavConstants, uiGridConstants, RowCol, $timeout, $compile) {\n      return {\n        replace: true,\n        priority: -150,\n        require: '^uiGrid',\n        scope: false,\n        controller: function () {},\n        compile: function () {\n          return {\n            pre: function ($scope, $elm, $attrs, uiGridCtrl) {\n              var _scope = $scope;\n\n              var grid = uiGridCtrl.grid;\n              uiGridCellNavService.initializeGrid(grid);\n\n              uiGridCtrl.cellNav = {};\n\n              //Ensure that the object has all of the methods we expect it to\n              uiGridCtrl.cellNav.makeRowCol = function (obj) {\n                if (!(obj instanceof RowCol)) {\n                  obj = new RowCol(obj.row, obj.col);\n                }\n                return obj;\n              };\n\n              uiGridCtrl.cellNav.getActiveCell = function () {\n                var elms = $elm[0].getElementsByClassName('ui-grid-cell-focus');\n                if (elms.length > 0){\n                  return elms[0];\n                }\n\n                return undefined;\n              };\n\n              uiGridCtrl.cellNav.broadcastCellNav = grid.cellNav.broadcastCellNav = function (newRowCol, modifierDown, originEvt) {\n                modifierDown = !(modifierDown === undefined || !modifierDown);\n\n                newRowCol = uiGridCtrl.cellNav.makeRowCol(newRowCol);\n\n                uiGridCtrl.cellNav.broadcastFocus(newRowCol, modifierDown, originEvt);\n                _scope.$broadcast(uiGridCellNavConstants.CELL_NAV_EVENT, newRowCol, modifierDown, originEvt);\n              };\n\n              uiGridCtrl.cellNav.clearFocus = grid.cellNav.clearFocus = function () {\n                grid.cellNav.focusedCells = [];\n                _scope.$broadcast(uiGridCellNavConstants.CELL_NAV_EVENT);\n              };\n\n              uiGridCtrl.cellNav.broadcastFocus = function (rowCol, modifierDown, originEvt) {\n                modifierDown = !(modifierDown === undefined || !modifierDown);\n\n                rowCol = uiGridCtrl.cellNav.makeRowCol(rowCol);\n\n                var row = rowCol.row,\n                  col = rowCol.col;\n\n                var rowColSelectIndex = uiGridCtrl.grid.api.cellNav.rowColSelectIndex(rowCol);\n\n                if (grid.cellNav.lastRowCol === null || rowColSelectIndex === -1) {\n                  var newRowCol = new RowCol(row, col);\n\n                  grid.api.cellNav.raise.navigate(newRowCol, grid.cellNav.lastRowCol);\n                  grid.cellNav.lastRowCol = newRowCol;\n                  if (uiGridCtrl.grid.options.modifierKeysToMultiSelectCells && modifierDown) {\n                    grid.cellNav.focusedCells.push(rowCol);\n                  } else {\n                    grid.cellNav.focusedCells = [rowCol];\n                  }\n                } else if (grid.options.modifierKeysToMultiSelectCells && modifierDown &&\n                  rowColSelectIndex >= 0) {\n\n                  grid.cellNav.focusedCells.splice(rowColSelectIndex, 1);\n                }\n              };\n\n              uiGridCtrl.cellNav.handleKeyDown = function (evt) {\n                var direction = uiGridCellNavService.getDirection(evt);\n                if (direction === null) {\n                  return null;\n                }\n\n                var containerId = 'body';\n                if (evt.uiGridTargetRenderContainerId) {\n                  containerId = evt.uiGridTargetRenderContainerId;\n                }\n\n                // Get the last-focused row+col combo\n                var lastRowCol = uiGridCtrl.grid.api.cellNav.getFocusedCell();\n                if (lastRowCol) {\n                  // Figure out which new row+combo we're navigating to\n                  var rowCol = uiGridCtrl.grid.renderContainers[containerId].cellNav.getNextRowCol(direction, lastRowCol.row, lastRowCol.col);\n                  var focusableCols = uiGridCtrl.grid.renderContainers[containerId].cellNav.getFocusableCols();\n                  var rowColSelectIndex = uiGridCtrl.grid.api.cellNav.rowColSelectIndex(rowCol);\n                  // Shift+tab on top-left cell should exit cellnav on render container\n                  if (\n                    // Navigating left\n                    direction === uiGridCellNavConstants.direction.LEFT &&\n                    // New col is last col (i.e. wrap around)\n                    rowCol.col === focusableCols[focusableCols.length - 1] &&\n                    // Staying on same row, which means we're at first row\n                    rowCol.row === lastRowCol.row &&\n                    evt.keyCode === uiGridConstants.keymap.TAB &&\n                    evt.shiftKey\n                  ) {\n                    grid.cellNav.focusedCells.splice(rowColSelectIndex, 1);\n                    uiGridCtrl.cellNav.clearFocus();\n                    return true;\n                  }\n                  // Tab on bottom-right cell should exit cellnav on render container\n                  else if (\n                    direction === uiGridCellNavConstants.direction.RIGHT &&\n                    // New col is first col (i.e. wrap around)\n                    rowCol.col === focusableCols[0] &&\n                    // Staying on same row, which means we're at first row\n                    rowCol.row === lastRowCol.row &&\n                    evt.keyCode === uiGridConstants.keymap.TAB &&\n                    !evt.shiftKey\n                  ) {\n                    grid.cellNav.focusedCells.splice(rowColSelectIndex, 1);\n                    uiGridCtrl.cellNav.clearFocus();\n                    return true;\n                  }\n\n                  // Scroll to the new cell, if it's not completely visible within the render container's viewport\n                  grid.scrollToIfNecessary(rowCol.row, rowCol.col).then(function () {\n                    uiGridCtrl.cellNav.broadcastCellNav(rowCol);\n                  });\n\n\n                  evt.stopPropagation();\n                  evt.preventDefault();\n\n                  return false;\n                }\n              };\n            },\n            post: function ($scope, $elm, $attrs, uiGridCtrl) {\n              var _scope = $scope;\n              var grid = uiGridCtrl.grid;\n\n              function addAriaLiveRegion(){\n                // Thanks to google docs for the inspiration behind how to do this\n                // XXX: Why is this entire mess nessasary?\n                // Because browsers take a lot of coercing to get them to read out live regions\n                //http://www.paciellogroup.com/blog/2012/06/html5-accessibility-chops-aria-rolealert-browser-support/\n                var ariaNotifierDomElt = '<div ' +\n                                           'id=\"' + grid.id +'-aria-speakable\" ' +\n                                           'class=\"ui-grid-a11y-ariascreenreader-speakable ui-grid-offscreen\" ' +\n                                           'aria-live=\"assertive\" ' +\n                                           'role=\"region\" ' +\n                                           'aria-atomic=\"true\" ' +\n                                           'aria-hidden=\"false\" ' +\n                                           'aria-relevant=\"additions\" ' +\n                                           '>' +\n                                           '&nbsp;' +\n                                         '</div>';\n\n                var ariaNotifier = $compile(ariaNotifierDomElt)($scope);\n                $elm.prepend(ariaNotifier);\n                $scope.$on(uiGridCellNavConstants.CELL_NAV_EVENT, function (evt, rowCol, modifierDown, originEvt) {\n                  /*\n                   * If the cell nav event was because of a focus event then we don't want to\n                   * change the notifier text.\n                   * Reasoning: Voice Over fires a focus events when moving arround the grid.\n                   * If the screen reader is handing the grid nav properly then we don't need to\n                   * use the alert to notify the user of the movement.\n                   * In all other cases we do want a notification event.\n                   */\n                  if (originEvt && originEvt.type === 'focus'){return;}\n\n                  function setNotifyText(text){\n                    if (text === ariaNotifier.text()){return;}\n                    ariaNotifier[0].style.clip = 'rect(0px,0px,0px,0px)';\n                    /*\n                     * This is how google docs handles clearing the div. Seems to work better than setting the text of the div to ''\n                     */\n                    ariaNotifier[0].innerHTML = \"\";\n                    ariaNotifier[0].style.visibility = 'hidden';\n                    ariaNotifier[0].style.visibility = 'visible';\n                    if (text !== ''){\n                      ariaNotifier[0].style.clip = 'auto';\n                      /*\n                       * The space after the text is something that google docs does.\n                       */\n                      ariaNotifier[0].appendChild(document.createTextNode(text + \" \"));\n                      ariaNotifier[0].style.visibility = 'hidden';\n                      ariaNotifier[0].style.visibility = 'visible';\n                    }\n                  }\n\n                  var values = [];\n                  var currentSelection = grid.api.cellNav.getCurrentSelection();\n                  for (var i = 0; i < currentSelection.length; i++) {\n                    values.push(currentSelection[i].getIntersectionValueFiltered());\n                  }\n                  var cellText = values.toString();\n                  setNotifyText(cellText);\n\n                });\n              }\n              addAriaLiveRegion();\n            }\n          };\n        }\n      };\n    }]);\n\n  module.directive('uiGridRenderContainer', ['$timeout', '$document', 'gridUtil', 'uiGridConstants', 'uiGridCellNavService', '$compile','uiGridCellNavConstants',\n    function ($timeout, $document, gridUtil, uiGridConstants, uiGridCellNavService, $compile, uiGridCellNavConstants) {\n      return {\n        replace: true,\n        priority: -99999, //this needs to run very last\n        require: ['^uiGrid', 'uiGridRenderContainer', '?^uiGridCellnav'],\n        scope: false,\n        compile: function () {\n          return {\n            post: function ($scope, $elm, $attrs, controllers) {\n              var uiGridCtrl = controllers[0],\n                 renderContainerCtrl = controllers[1],\n                 uiGridCellnavCtrl = controllers[2];\n\n              // Skip attaching cell-nav specific logic if the directive is not attached above us\n              if (!uiGridCtrl.grid.api.cellNav) { return; }\n\n              var containerId = renderContainerCtrl.containerId;\n\n              var grid = uiGridCtrl.grid;\n\n              //run each time a render container is created\n              uiGridCellNavService.decorateRenderContainers(grid);\n\n              // focusser only created for body\n              if (containerId !== 'body') {\n                return;\n              }\n\n\n\n              if (uiGridCtrl.grid.options.modifierKeysToMultiSelectCells){\n                $elm.attr('aria-multiselectable', true);\n              } else {\n                $elm.attr('aria-multiselectable', false);\n              }\n\n              //add an element with no dimensions that can be used to set focus and capture keystrokes\n              var focuser = $compile('<div class=\"ui-grid-focuser\" role=\"region\" aria-live=\"assertive\" aria-atomic=\"false\" tabindex=\"0\" aria-controls=\"' + grid.id +'-aria-speakable '+ grid.id + '-grid-container' +'\" aria-owns=\"' + grid.id + '-grid-container' + '\"></div>')($scope);\n              $elm.append(focuser);\n\n              focuser.on('focus', function (evt) {\n                evt.uiGridTargetRenderContainerId = containerId;\n                var rowCol = uiGridCtrl.grid.api.cellNav.getFocusedCell();\n                if (rowCol === null) {\n                  rowCol = uiGridCtrl.grid.renderContainers[containerId].cellNav.getNextRowCol(uiGridCellNavConstants.direction.DOWN, null, null);\n                  if (rowCol.row && rowCol.col) {\n                    uiGridCtrl.cellNav.broadcastCellNav(rowCol);\n                  }\n                }\n              });\n\n              uiGridCellnavCtrl.setAriaActivedescendant = function(id){\n                $elm.attr('aria-activedescendant', id);\n              };\n\n              uiGridCellnavCtrl.removeAriaActivedescendant = function(id){\n                if ($elm.attr('aria-activedescendant') === id){\n                  $elm.attr('aria-activedescendant', '');\n                }\n              };\n\n\n              uiGridCtrl.focus = function () {\n                gridUtil.focus.byElement(focuser[0]);\n                //allow for first time grid focus\n              };\n\n              var viewPortKeyDownWasRaisedForRowCol = null;\n              // Bind to keydown events in the render container\n              focuser.on('keydown', function (evt) {\n                evt.uiGridTargetRenderContainerId = containerId;\n                var rowCol = uiGridCtrl.grid.api.cellNav.getFocusedCell();\n                var result = uiGridCtrl.cellNav.handleKeyDown(evt);\n                if (result === null) {\n                  uiGridCtrl.grid.api.cellNav.raise.viewPortKeyDown(evt, rowCol);\n                  viewPortKeyDownWasRaisedForRowCol = rowCol;\n                }\n              });\n              //Bind to keypress events in the render container\n              //keypress events are needed by edit function so the key press\n              //that initiated an edit is not lost\n              //must fire the event in a timeout so the editor can\n              //initialize and subscribe to the event on another event loop\n              focuser.on('keypress', function (evt) {\n                if (viewPortKeyDownWasRaisedForRowCol) {\n                  $timeout(function () {\n                    uiGridCtrl.grid.api.cellNav.raise.viewPortKeyPress(evt, viewPortKeyDownWasRaisedForRowCol);\n                  },4);\n\n                  viewPortKeyDownWasRaisedForRowCol = null;\n                }\n              });\n\n              $scope.$on('$destroy', function(){\n                //Remove all event handlers associated with this focuser.\n                focuser.off();\n              });\n\n            }\n          };\n        }\n      };\n    }]);\n\n  module.directive('uiGridViewport', ['$timeout', '$document', 'gridUtil', 'uiGridConstants', 'uiGridCellNavService', 'uiGridCellNavConstants','$log','$compile',\n    function ($timeout, $document, gridUtil, uiGridConstants, uiGridCellNavService, uiGridCellNavConstants, $log, $compile) {\n      return {\n        replace: true,\n        priority: -99999, //this needs to run very last\n        require: ['^uiGrid', '^uiGridRenderContainer', '?^uiGridCellnav'],\n        scope: false,\n        compile: function () {\n          return {\n            pre: function ($scope, $elm, $attrs, uiGridCtrl) {\n            },\n            post: function ($scope, $elm, $attrs, controllers) {\n              var uiGridCtrl = controllers[0],\n                renderContainerCtrl = controllers[1];\n\n              // Skip attaching cell-nav specific logic if the directive is not attached above us\n              if (!uiGridCtrl.grid.api.cellNav) { return; }\n\n              var containerId = renderContainerCtrl.containerId;\n              //no need to process for other containers\n              if (containerId !== 'body') {\n                return;\n              }\n\n              var grid = uiGridCtrl.grid;\n\n              grid.api.core.on.scrollBegin($scope, function (args) {\n\n                // Skip if there's no currently-focused cell\n                var lastRowCol = uiGridCtrl.grid.api.cellNav.getFocusedCell();\n                if (lastRowCol === null) {\n                  return;\n                }\n\n                //if not in my container, move on\n                //todo: worry about horiz scroll\n                if (!renderContainerCtrl.colContainer.containsColumn(lastRowCol.col)) {\n                  return;\n                }\n\n                uiGridCtrl.cellNav.clearFocus();\n\n              });\n\n              grid.api.core.on.scrollEnd($scope, function (args) {\n                // Skip if there's no currently-focused cell\n                var lastRowCol = uiGridCtrl.grid.api.cellNav.getFocusedCell();\n                if (lastRowCol === null) {\n                  return;\n                }\n\n                //if not in my container, move on\n                //todo: worry about horiz scroll\n                if (!renderContainerCtrl.colContainer.containsColumn(lastRowCol.col)) {\n                  return;\n                }\n\n                uiGridCtrl.cellNav.broadcastCellNav(lastRowCol);\n\n              });\n\n              grid.api.cellNav.on.navigate($scope, function () {\n                //focus again because it can be lost\n                 uiGridCtrl.focus();\n              });\n\n            }\n          };\n        }\n      };\n    }]);\n\n  /**\n   *  @ngdoc directive\n   *  @name ui.grid.cellNav.directive:uiGridCell\n   *  @element div\n   *  @restrict A\n   *  @description Stacks on top of ui.grid.uiGridCell to provide cell navigation\n   */\n  module.directive('uiGridCell', ['$timeout', '$document', 'uiGridCellNavService', 'gridUtil', 'uiGridCellNavConstants', 'uiGridConstants', 'RowColFactory',\n    function ($timeout, $document, uiGridCellNavService, gridUtil, uiGridCellNavConstants, uiGridConstants, RowCol) {\n      return {\n        priority: -150, // run after default uiGridCell directive and ui.grid.edit uiGridCell\n        restrict: 'A',\n        require: ['^uiGrid', '?^uiGridCellnav'],\n        scope: false,\n        link: function ($scope, $elm, $attrs, controllers) {\n          var uiGridCtrl = controllers[0],\n              uiGridCellnavCtrl = controllers[1];\n          // Skip attaching cell-nav specific logic if the directive is not attached above us\n          if (!uiGridCtrl.grid.api.cellNav) { return; }\n\n          if (!$scope.col.colDef.allowCellFocus) {\n            return;\n          }\n\n          //Convinience local variables\n          var grid = uiGridCtrl.grid;\n          $scope.focused = false;\n\n          // Make this cell focusable but only with javascript/a mouse click\n          $elm.attr('tabindex', -1);\n\n          // When a cell is clicked, broadcast a cellNav event saying that this row+col combo is now focused\n          $elm.find('div').on('click', function (evt) {\n            uiGridCtrl.cellNav.broadcastCellNav(new RowCol($scope.row, $scope.col), evt.ctrlKey || evt.metaKey, evt);\n\n            evt.stopPropagation();\n            $scope.$apply();\n          });\n\n\n          /*\n           * XXX Hack for screen readers.\n           * This allows the grid to focus using only the screen reader cursor.\n           * Since the focus event doesn't include key press information we can't use it\n           * as our primary source of the event.\n           */\n          $elm.on('mousedown', preventMouseDown);\n\n          //turn on and off for edit events\n          if (uiGridCtrl.grid.api.edit) {\n            uiGridCtrl.grid.api.edit.on.beginCellEdit($scope, function () {\n              $elm.off('mousedown', preventMouseDown);\n            });\n\n            uiGridCtrl.grid.api.edit.on.afterCellEdit($scope, function () {\n              $elm.on('mousedown', preventMouseDown);\n            });\n\n            uiGridCtrl.grid.api.edit.on.cancelCellEdit($scope, function () {\n              $elm.on('mousedown', preventMouseDown);\n            });\n          }\n\n          function preventMouseDown(evt) {\n            //Prevents the foucus event from firing if the click event is already going to fire.\n            //If both events fire it will cause bouncing behavior.\n            evt.preventDefault();\n          }\n\n          //You can only focus on elements with a tabindex value\n          $elm.on('focus', function (evt) {\n            uiGridCtrl.cellNav.broadcastCellNav(new RowCol($scope.row, $scope.col), false, evt);\n            evt.stopPropagation();\n            $scope.$apply();\n          });\n\n          // This event is fired for all cells.  If the cell matches, then focus is set\n          $scope.$on(uiGridCellNavConstants.CELL_NAV_EVENT, function (evt, rowCol, modifierDown) {\n            var isFocused = grid.cellNav.focusedCells.some(function(focusedRowCol, index){\n              return (focusedRowCol.row === $scope.row && focusedRowCol.col === $scope.col);\n            });\n            if (isFocused){\n              setFocused();\n            } else {\n              clearFocus();\n            }\n          });\n\n          function setFocused() {\n            if (!$scope.focused){\n              var div = $elm.find('div');\n              div.addClass('ui-grid-cell-focus');\n              $elm.attr('aria-selected', true);\n              uiGridCellnavCtrl.setAriaActivedescendant($elm.attr('id'));\n              $scope.focused = true;\n            }\n          }\n\n          function clearFocus() {\n            if ($scope.focused){\n              var div = $elm.find('div');\n              div.removeClass('ui-grid-cell-focus');\n              $elm.attr('aria-selected', false);\n              uiGridCellnavCtrl.removeAriaActivedescendant($elm.attr('id'));\n              $scope.focused = false;\n            }\n          }\n\n          $scope.$on('$destroy', function () {\n            //.off withouth paramaters removes all handlers\n            $elm.find('div').off();\n            $elm.off();\n          });\n        }\n      };\n    }]);\n\n})();\n\n(function () {\n  'use strict';\n\n  /**\n   * @ngdoc overview\n   * @name ui.grid.edit\n   * @description\n   *\n   * # ui.grid.edit\n   *\n   * <div class=\"alert alert-success\" role=\"alert\"><strong>Stable</strong> This feature is stable. There should no longer be breaking api changes without a deprecation warning.</div>\n   *\n   * This module provides cell editing capability to ui.grid. The goal was to emulate keying data in a spreadsheet via\n   * a keyboard.\n   * <br/>\n   * <br/>\n   * To really get the full spreadsheet-like data entry, the ui.grid.cellNav module should be used. This will allow the\n   * user to key data and then tab, arrow, or enter to the cells beside or below.\n   *\n   * <div doc-module-components=\"ui.grid.edit\"></div>\n   */\n\n  var module = angular.module('ui.grid.edit', ['ui.grid']);\n\n  /**\n   *  @ngdoc object\n   *  @name ui.grid.edit.constant:uiGridEditConstants\n   *\n   *  @description constants available in edit module\n   */\n  module.constant('uiGridEditConstants', {\n    EDITABLE_CELL_TEMPLATE: /EDITABLE_CELL_TEMPLATE/g,\n    //must be lowercase because template bulder converts to lower\n    EDITABLE_CELL_DIRECTIVE: /editable_cell_directive/g,\n    events: {\n      BEGIN_CELL_EDIT: 'uiGridEventBeginCellEdit',\n      END_CELL_EDIT: 'uiGridEventEndCellEdit',\n      CANCEL_CELL_EDIT: 'uiGridEventCancelCellEdit'\n    }\n  });\n\n  /**\n   *  @ngdoc service\n   *  @name ui.grid.edit.service:uiGridEditService\n   *\n   *  @description Services for editing features\n   */\n  module.service('uiGridEditService', ['$q', 'uiGridConstants', 'gridUtil',\n    function ($q, uiGridConstants, gridUtil) {\n\n      var service = {\n\n        initializeGrid: function (grid) {\n\n          service.defaultGridOptions(grid.options);\n\n          grid.registerColumnBuilder(service.editColumnBuilder);\n          grid.edit = {};\n\n          /**\n           *  @ngdoc object\n           *  @name ui.grid.edit.api:PublicApi\n           *\n           *  @description Public Api for edit feature\n           */\n          var publicApi = {\n            events: {\n              edit: {\n                /**\n                 * @ngdoc event\n                 * @name afterCellEdit\n                 * @eventOf  ui.grid.edit.api:PublicApi\n                 * @description raised when cell editing is complete\n                 * <pre>\n                 *      gridApi.edit.on.afterCellEdit(scope,function(rowEntity, colDef){})\n                 * </pre>\n                 * @param {object} rowEntity the options.data element that was edited\n                 * @param {object} colDef the column that was edited\n                 * @param {object} newValue new value\n                 * @param {object} oldValue old value\n                 */\n                afterCellEdit: function (rowEntity, colDef, newValue, oldValue) {\n                },\n                /**\n                 * @ngdoc event\n                 * @name beginCellEdit\n                 * @eventOf  ui.grid.edit.api:PublicApi\n                 * @description raised when cell editing starts on a cell\n                 * <pre>\n                 *      gridApi.edit.on.beginCellEdit(scope,function(rowEntity, colDef){})\n                 * </pre>\n                 * @param {object} rowEntity the options.data element that was edited\n                 * @param {object} colDef the column that was edited\n                 * @param {object} triggerEvent the event that triggered the edit.  Useful to prevent losing keystrokes on some\n                 *                 complex editors\n                 */\n                beginCellEdit: function (rowEntity, colDef, triggerEvent) {\n                },\n                /**\n                 * @ngdoc event\n                 * @name cancelCellEdit\n                 * @eventOf  ui.grid.edit.api:PublicApi\n                 * @description raised when cell editing is cancelled on a cell\n                 * <pre>\n                 *      gridApi.edit.on.cancelCellEdit(scope,function(rowEntity, colDef){})\n                 * </pre>\n                 * @param {object} rowEntity the options.data element that was edited\n                 * @param {object} colDef the column that was edited\n                 */\n                cancelCellEdit: function (rowEntity, colDef) {\n                }\n              }\n            },\n            methods: {\n              edit: { }\n            }\n          };\n\n          grid.api.registerEventsFromObject(publicApi.events);\n          //grid.api.registerMethodsFromObject(publicApi.methods);\n\n        },\n\n        defaultGridOptions: function (gridOptions) {\n\n          /**\n           *  @ngdoc object\n           *  @name ui.grid.edit.api:GridOptions\n           *\n           *  @description Options for configuring the edit feature, these are available to be\n           *  set using the ui-grid {@link ui.grid.class:GridOptions gridOptions}\n           */\n\n          /**\n           *  @ngdoc object\n           *  @name enableCellEdit\n           *  @propertyOf  ui.grid.edit.api:GridOptions\n           *  @description If defined, sets the default value for the editable flag on each individual colDefs\n           *  if their individual enableCellEdit configuration is not defined. Defaults to undefined.\n           */\n\n          /**\n           *  @ngdoc object\n           *  @name cellEditableCondition\n           *  @propertyOf  ui.grid.edit.api:GridOptions\n           *  @description If specified, either a value or function to be used by all columns before editing.\n           *  If falsy, then editing of cell is not allowed.\n           *  @example\n           *  <pre>\n           *  function($scope){\n           *    //use $scope.row.entity and $scope.col.colDef to determine if editing is allowed\n           *    return true;\n           *  }\n           *  </pre>\n           */\n          gridOptions.cellEditableCondition = gridOptions.cellEditableCondition === undefined ? true : gridOptions.cellEditableCondition;\n\n          /**\n           *  @ngdoc object\n           *  @name editableCellTemplate\n           *  @propertyOf  ui.grid.edit.api:GridOptions\n           *  @description If specified, cellTemplate to use as the editor for all columns.\n           *  <br/> defaults to 'ui-grid/cellTextEditor'\n           */\n\n          /**\n           *  @ngdoc object\n           *  @name enableCellEditOnFocus\n           *  @propertyOf  ui.grid.edit.api:GridOptions\n           *  @description If true, then editor is invoked as soon as cell receives focus. Default false.\n           *  <br/>_requires cellNav feature and the edit feature to be enabled_\n           */\n            //enableCellEditOnFocus can only be used if cellnav module is used\n          gridOptions.enableCellEditOnFocus = gridOptions.enableCellEditOnFocus === undefined ? false : gridOptions.enableCellEditOnFocus;\n        },\n\n        /**\n         * @ngdoc service\n         * @name editColumnBuilder\n         * @methodOf ui.grid.edit.service:uiGridEditService\n         * @description columnBuilder function that adds edit properties to grid column\n         * @returns {promise} promise that will load any needed templates when resolved\n         */\n        editColumnBuilder: function (colDef, col, gridOptions) {\n\n          var promises = [];\n\n          /**\n           *  @ngdoc object\n           *  @name ui.grid.edit.api:ColumnDef\n           *\n           *  @description Column Definition for edit feature, these are available to be\n           *  set using the ui-grid {@link ui.grid.class:GridOptions.columnDef gridOptions.columnDefs}\n           */\n\n          /**\n           *  @ngdoc object\n           *  @name enableCellEdit\n           *  @propertyOf  ui.grid.edit.api:ColumnDef\n           *  @description enable editing on column\n           */\n          colDef.enableCellEdit = colDef.enableCellEdit === undefined ? (gridOptions.enableCellEdit === undefined ?\n            (colDef.type !== 'object') : gridOptions.enableCellEdit) : colDef.enableCellEdit;\n\n          /**\n           *  @ngdoc object\n           *  @name cellEditableCondition\n           *  @propertyOf  ui.grid.edit.api:ColumnDef\n           *  @description If specified, either a value or function evaluated before editing cell.  If falsy, then editing of cell is not allowed.\n           *  @example\n           *  <pre>\n           *  function($scope){\n           *    //use $scope.row.entity and $scope.col.colDef to determine if editing is allowed\n           *    return true;\n           *  }\n           *  </pre>\n           */\n          colDef.cellEditableCondition = colDef.cellEditableCondition === undefined ? gridOptions.cellEditableCondition :  colDef.cellEditableCondition;\n\n          /**\n           *  @ngdoc object\n           *  @name editableCellTemplate\n           *  @propertyOf  ui.grid.edit.api:ColumnDef\n           *  @description cell template to be used when editing this column. Can be Url or text template\n           *  <br/>Defaults to gridOptions.editableCellTemplate\n           */\n          if (colDef.enableCellEdit) {\n            colDef.editableCellTemplate = colDef.editableCellTemplate || gridOptions.editableCellTemplate || 'ui-grid/cellEditor';\n\n            promises.push(gridUtil.getTemplate(colDef.editableCellTemplate)\n              .then(\n              function (template) {\n                col.editableCellTemplate = template;\n              },\n              function (res) {\n                // Todo handle response error here?\n                throw new Error(\"Couldn't fetch/use colDef.editableCellTemplate '\" + colDef.editableCellTemplate + \"'\");\n              }));\n          }\n\n          /**\n           *  @ngdoc object\n           *  @name enableCellEditOnFocus\n           *  @propertyOf  ui.grid.edit.api:ColumnDef\n           *  @requires ui.grid.cellNav\n           *  @description If true, then editor is invoked as soon as cell receives focus. Default false.\n           *  <br>_requires both the cellNav feature and the edit feature to be enabled_\n           */\n            //enableCellEditOnFocus can only be used if cellnav module is used\n          colDef.enableCellEditOnFocus = colDef.enableCellEditOnFocus === undefined ? gridOptions.enableCellEditOnFocus : colDef.enableCellEditOnFocus;\n\n\n          /**\n           *  @ngdoc string\n           *  @name editModelField\n           *  @propertyOf  ui.grid.edit.api:ColumnDef\n           *  @description a bindable string value that is used when binding to edit controls instead of colDef.field\n           *  <br/> example: You have a complex property on and object like state:{abbrev:'MS',name:'Mississippi'}.  The\n           *  grid should display state.name in the cell and sort/filter based on the state.name property but the editor\n           *  requires the full state object.\n           *  <br/>colDef.field = 'state.name'\n           *  <br/>colDef.editModelField = 'state'\n           */\n          //colDef.editModelField\n\n          return $q.all(promises);\n        },\n\n        /**\n         * @ngdoc service\n         * @name isStartEditKey\n         * @methodOf ui.grid.edit.service:uiGridEditService\n         * @description  Determines if a keypress should start editing.  Decorate this service to override with your\n         * own key events.  See service decorator in angular docs.\n         * @param {Event} evt keydown event\n         * @returns {boolean} true if an edit should start\n         */\n        isStartEditKey: function (evt) {\n          if (evt.metaKey ||\n              evt.keyCode === uiGridConstants.keymap.ESC ||\n              evt.keyCode === uiGridConstants.keymap.SHIFT ||\n              evt.keyCode === uiGridConstants.keymap.CTRL ||\n              evt.keyCode === uiGridConstants.keymap.ALT ||\n              evt.keyCode === uiGridConstants.keymap.WIN ||\n              evt.keyCode === uiGridConstants.keymap.CAPSLOCK ||\n\n             evt.keyCode === uiGridConstants.keymap.LEFT ||\n            (evt.keyCode === uiGridConstants.keymap.TAB && evt.shiftKey) ||\n\n            evt.keyCode === uiGridConstants.keymap.RIGHT ||\n            evt.keyCode === uiGridConstants.keymap.TAB ||\n\n            evt.keyCode === uiGridConstants.keymap.UP ||\n            (evt.keyCode === uiGridConstants.keymap.ENTER && evt.shiftKey) ||\n\n            evt.keyCode === uiGridConstants.keymap.DOWN ||\n            evt.keyCode === uiGridConstants.keymap.ENTER) {\n            return false;\n\n          }\n          return true;\n        }\n\n\n      };\n\n      return service;\n\n    }]);\n\n  /**\n   *  @ngdoc directive\n   *  @name ui.grid.edit.directive:uiGridEdit\n   *  @element div\n   *  @restrict A\n   *\n   *  @description Adds editing features to the ui-grid directive.\n   *\n   *  @example\n   <example module=\"app\">\n   <file name=\"app.js\">\n   var app = angular.module('app', ['ui.grid', 'ui.grid.edit']);\n\n   app.controller('MainCtrl', ['$scope', function ($scope) {\n      $scope.data = [\n        { name: 'Bob', title: 'CEO' },\n            { name: 'Frank', title: 'Lowly Developer' }\n      ];\n\n      $scope.columnDefs = [\n        {name: 'name', enableCellEdit: true},\n        {name: 'title', enableCellEdit: true}\n      ];\n    }]);\n   </file>\n   <file name=\"index.html\">\n   <div ng-controller=\"MainCtrl\">\n   <div ui-grid=\"{ data: data, columnDefs: columnDefs }\" ui-grid-edit></div>\n   </div>\n   </file>\n   </example>\n   */\n  module.directive('uiGridEdit', ['gridUtil', 'uiGridEditService', function (gridUtil, uiGridEditService) {\n    return {\n      replace: true,\n      priority: 0,\n      require: '^uiGrid',\n      scope: false,\n      compile: function () {\n        return {\n          pre: function ($scope, $elm, $attrs, uiGridCtrl) {\n            uiGridEditService.initializeGrid(uiGridCtrl.grid);\n          },\n          post: function ($scope, $elm, $attrs, uiGridCtrl) {\n          }\n        };\n      }\n    };\n  }]);\n\n  /**\n   *  @ngdoc directive\n   *  @name ui.grid.edit.directive:uiGridRenderContainer\n   *  @element div\n   *  @restrict A\n   *\n   *  @description Adds keydown listeners to renderContainer element so we can capture when to begin edits\n   *\n   */\n  module.directive('uiGridViewport', [ 'uiGridEditConstants',\n    function ( uiGridEditConstants) {\n      return {\n        replace: true,\n        priority: -99998, //run before cellNav\n        require: ['^uiGrid', '^uiGridRenderContainer'],\n        scope: false,\n        compile: function () {\n          return {\n            post: function ($scope, $elm, $attrs, controllers) {\n              var uiGridCtrl = controllers[0];\n\n              // Skip attaching if edit and cellNav is not enabled\n              if (!uiGridCtrl.grid.api.edit || !uiGridCtrl.grid.api.cellNav) { return; }\n\n              var containerId =  controllers[1].containerId;\n              //no need to process for other containers\n              if (containerId !== 'body') {\n                return;\n              }\n\n              //refocus on the grid\n              $scope.$on(uiGridEditConstants.events.CANCEL_CELL_EDIT, function () {\n                uiGridCtrl.focus();\n              });\n              $scope.$on(uiGridEditConstants.events.END_CELL_EDIT, function () {\n                uiGridCtrl.focus();\n              });\n\n            }\n          };\n        }\n      };\n    }]);\n\n  /**\n   *  @ngdoc directive\n   *  @name ui.grid.edit.directive:uiGridCell\n   *  @element div\n   *  @restrict A\n   *\n   *  @description Stacks on top of ui.grid.uiGridCell to provide in-line editing capabilities to the cell\n   *  Editing Actions.\n   *\n   *  Binds edit start events to the uiGridCell element.  When the events fire, the gridCell element is appended\n   *  with the columnDef.editableCellTemplate element ('cellEditor.html' by default).\n   *\n   *  The editableCellTemplate should respond to uiGridEditConstants.events.BEGIN\\_CELL\\_EDIT angular event\n   *  and do the initial steps needed to edit the cell (setfocus on input element, etc).\n   *\n   *  When the editableCellTemplate recognizes that the editing is ended (blur event, Enter key, etc.)\n   *  it should emit the uiGridEditConstants.events.END\\_CELL\\_EDIT event.\n   *\n   *  If editableCellTemplate recognizes that the editing has been cancelled (esc key)\n   *  it should emit the uiGridEditConstants.events.CANCEL\\_CELL\\_EDIT event.  The original value\n   *  will be set back on the model by the uiGridCell directive.\n   *\n   *  Events that invoke editing:\n   *    - dblclick\n   *    - F2 keydown (when using cell selection)\n   *\n   *  Events that end editing:\n   *    - Dependent on the specific editableCellTemplate\n   *    - Standards should be blur and enter keydown\n   *\n   *  Events that cancel editing:\n   *    - Dependent on the specific editableCellTemplate\n   *    - Standards should be Esc keydown\n   *\n   *  Grid Events that end editing:\n   *    - uiGridConstants.events.GRID_SCROLL\n   *\n   */\n\n  /**\n   *  @ngdoc object\n   *  @name ui.grid.edit.api:GridRow\n   *\n   *  @description GridRow options for edit feature, these are available to be\n   *  set internally only, by other features\n   */\n\n  /**\n   *  @ngdoc object\n   *  @name enableCellEdit\n   *  @propertyOf  ui.grid.edit.api:GridRow\n   *  @description enable editing on row, grouping for example might disable editing on group header rows\n   */\n\n  module.directive('uiGridCell',\n    ['$compile', '$injector', '$timeout', 'uiGridConstants', 'uiGridEditConstants', 'gridUtil', '$parse', 'uiGridEditService', '$rootScope',\n      function ($compile, $injector, $timeout, uiGridConstants, uiGridEditConstants, gridUtil, $parse, uiGridEditService, $rootScope) {\n        var touchstartTimeout = 500;\n        if ($injector.has('uiGridCellNavService')) {\n          var uiGridCellNavService = $injector.get('uiGridCellNavService');\n        }\n\n        return {\n          priority: -100, // run after default uiGridCell directive\n          restrict: 'A',\n          scope: false,\n          require: '?^uiGrid',\n          link: function ($scope, $elm, $attrs, uiGridCtrl) {\n            var html;\n            var origCellValue;\n            var inEdit = false;\n            var cellModel;\n            var cancelTouchstartTimeout;\n\n            var editCellScope;\n\n            if (!$scope.col.colDef.enableCellEdit) {\n              return;\n            }\n\n            var cellNavNavigateDereg = function() {};\n\n            // Bind to keydown events in the render container\n            if (uiGridCtrl && uiGridCtrl.grid.api.cellNav) {\n\n              uiGridCtrl.grid.api.cellNav.on.viewPortKeyDown($scope, function (evt, rowCol) {\n                if (rowCol === null) {\n                  return;\n                }\n\n                if (rowCol.row === $scope.row && rowCol.col === $scope.col && !$scope.col.colDef.enableCellEditOnFocus) {\n                  //important to do this before scrollToIfNecessary\n                  beginEditKeyDown(evt);\n                 // uiGridCtrl.grid.api.core.scrollToIfNecessary(rowCol.row, rowCol.col);\n                }\n\n              });\n            }\n\n            var setEditable = function() {\n              if ($scope.col.colDef.enableCellEdit && $scope.row.enableCellEdit !== false) {\n                registerBeginEditEvents();\n              } else {\n                cancelBeginEditEvents();\n              }\n            };\n\n            setEditable();\n\n            var rowWatchDereg = $scope.$watch( 'row', setEditable );\n            $scope.$on( '$destroy', rowWatchDereg );\n\n            function registerBeginEditEvents() {\n              $elm.on('dblclick', beginEdit);\n\n              // Add touchstart handling. If the users starts a touch and it doesn't end after X milliseconds, then start the edit\n              $elm.on('touchstart', touchStart);\n\n              if (uiGridCtrl && uiGridCtrl.grid.api.cellNav) {\n                cellNavNavigateDereg = uiGridCtrl.grid.api.cellNav.on.navigate($scope, function (newRowCol, oldRowCol) {\n                  if ($scope.col.colDef.enableCellEditOnFocus) {\n                    if (newRowCol.row === $scope.row && newRowCol.col === $scope.col) {\n                      $timeout(function () {\n                        beginEdit();\n                      });\n                    }\n                  }\n                });\n              }\n\n\n\n            }\n\n            function touchStart(event) {\n              // jQuery masks events\n              if (typeof(event.originalEvent) !== 'undefined' && event.originalEvent !== undefined) {\n                event = event.originalEvent;\n              }\n\n              // Bind touchend handler\n              $elm.on('touchend', touchEnd);\n\n              // Start a timeout\n              cancelTouchstartTimeout = $timeout(function() { }, touchstartTimeout);\n\n              // Timeout's done! Start the edit\n              cancelTouchstartTimeout.then(function () {\n                // Use setTimeout to start the edit because beginEdit expects to be outside of $digest\n                setTimeout(beginEdit, 0);\n\n                // Undbind the touchend handler, we don't need it anymore\n                $elm.off('touchend', touchEnd);\n              });\n            }\n\n            // Cancel any touchstart timeout\n            function touchEnd(event) {\n              $timeout.cancel(cancelTouchstartTimeout);\n              $elm.off('touchend', touchEnd);\n            }\n\n            function cancelBeginEditEvents() {\n              $elm.off('dblclick', beginEdit);\n              $elm.off('keydown', beginEditKeyDown);\n              $elm.off('touchstart', touchStart);\n              cellNavNavigateDereg();\n            }\n\n            function beginEditKeyDown(evt) {\n              if (uiGridEditService.isStartEditKey(evt)) {\n                beginEdit(evt);\n              }\n            }\n\n            function shouldEdit(col, row) {\n              return !row.isSaving &&\n                ( angular.isFunction(col.colDef.cellEditableCondition) ?\n                    col.colDef.cellEditableCondition($scope) :\n                    col.colDef.cellEditableCondition );\n            }\n\n\n            function beginEdit(triggerEvent) {\n              //we need to scroll the cell into focus before invoking the editor\n              $scope.grid.api.core.scrollToIfNecessary($scope.row, $scope.col)\n                .then(function () {\n                  beginEditAfterScroll(triggerEvent);\n                });\n            }\n\n            /**\n             *  @ngdoc property\n             *  @name editDropdownOptionsArray\n             *  @propertyOf ui.grid.edit.api:ColumnDef\n             *  @description an array of values in the format\n             *  [ {id: xxx, value: xxx} ], which is populated\n             *  into the edit dropdown\n             *\n             */\n            /**\n             *  @ngdoc property\n             *  @name editDropdownIdLabel\n             *  @propertyOf ui.grid.edit.api:ColumnDef\n             *  @description the label for the \"id\" field\n             *  in the editDropdownOptionsArray.  Defaults\n             *  to 'id'\n             *  @example\n             *  <pre>\n             *    $scope.gridOptions = {\n             *      columnDefs: [\n             *        {name: 'status', editableCellTemplate: 'ui-grid/dropdownEditor',\n             *          editDropdownOptionsArray: [{code: 1, status: 'active'}, {code: 2, status: 'inactive'}],\n             *          editDropdownIdLabel: 'code', editDropdownValueLabel: 'status' }\n             *      ],\n             *  </pre>\n             *\n             */\n            /**\n             *  @ngdoc property\n             *  @name editDropdownRowEntityOptionsArrayPath\n             *  @propertyOf ui.grid.edit.api:ColumnDef\n             *  @description a path to a property on row.entity containing an\n             *  array of values in the format\n             *  [ {id: xxx, value: xxx} ], which will be used to populate\n             *  the edit dropdown.  This can be used when the dropdown values are dependent on\n             *  the backing row entity.\n             *  If this property is set then editDropdownOptionsArray will be ignored.\n             *  @example\n             *  <pre>\n             *    $scope.gridOptions = {\n             *      columnDefs: [\n             *        {name: 'status', editableCellTemplate: 'ui-grid/dropdownEditor',\n             *          editDropdownRowEntityOptionsArrayPath: 'foo.bars[0].baz',\n             *          editDropdownIdLabel: 'code', editDropdownValueLabel: 'status' }\n             *      ],\n             *  </pre>\n             *\n             */\n            /**\n             *  @ngdoc property\n             *  @name editDropdownValueLabel\n             *  @propertyOf ui.grid.edit.api:ColumnDef\n             *  @description the label for the \"value\" field\n             *  in the editDropdownOptionsArray.  Defaults\n             *  to 'value'\n             *  @example\n             *  <pre>\n             *    $scope.gridOptions = {\n             *      columnDefs: [\n             *        {name: 'status', editableCellTemplate: 'ui-grid/dropdownEditor',\n             *          editDropdownOptionsArray: [{code: 1, status: 'active'}, {code: 2, status: 'inactive'}],\n             *          editDropdownIdLabel: 'code', editDropdownValueLabel: 'status' }\n             *      ],\n             *  </pre>\n             *\n             */\n            /**\n             *  @ngdoc property\n             *  @name editDropdownFilter\n             *  @propertyOf ui.grid.edit.api:ColumnDef\n             *  @description A filter that you would like to apply to the values in the options list\n             *  of the dropdown.  For example if you were using angular-translate you might set this\n             *  to `'translate'`\n             *  @example\n             *  <pre>\n             *    $scope.gridOptions = {\n             *      columnDefs: [\n             *        {name: 'status', editableCellTemplate: 'ui-grid/dropdownEditor',\n             *          editDropdownOptionsArray: [{code: 1, status: 'active'}, {code: 2, status: 'inactive'}],\n             *          editDropdownIdLabel: 'code', editDropdownValueLabel: 'status', editDropdownFilter: 'translate' }\n             *      ],\n             *  </pre>\n             *\n             */\n            function beginEditAfterScroll(triggerEvent) {\n              // If we are already editing, then just skip this so we don't try editing twice...\n              if (inEdit) {\n                return;\n              }\n\n              if (!shouldEdit($scope.col, $scope.row)) {\n                return;\n              }\n\n\n              cellModel = $parse($scope.row.getQualifiedColField($scope.col));\n              //get original value from the cell\n              origCellValue = cellModel($scope);\n\n              html = $scope.col.editableCellTemplate;\n\n              if ($scope.col.colDef.editModelField) {\n                html = html.replace(uiGridConstants.MODEL_COL_FIELD, gridUtil.preEval('row.entity.' + $scope.col.colDef.editModelField));\n              }\n              else {\n                html = html.replace(uiGridConstants.MODEL_COL_FIELD, $scope.row.getQualifiedColField($scope.col));\n              }\n\n              html = html.replace(uiGridConstants.COL_FIELD, 'grid.getCellValue(row, col)');\n\n              var optionFilter = $scope.col.colDef.editDropdownFilter ? '|' + $scope.col.colDef.editDropdownFilter : '';\n              html = html.replace(uiGridConstants.CUSTOM_FILTERS, optionFilter);\n\n              var inputType = 'text';\n              switch ($scope.col.colDef.type){\n                case 'boolean':\n                  inputType = 'checkbox';\n                  break;\n                case 'number':\n                  inputType = 'number';\n                  break;\n                case 'date':\n                  inputType = 'date';\n                  break;\n              }\n              html = html.replace('INPUT_TYPE', inputType);\n\n              var editDropdownRowEntityOptionsArrayPath = $scope.col.colDef.editDropdownRowEntityOptionsArrayPath;\n              if (editDropdownRowEntityOptionsArrayPath) {\n                $scope.editDropdownOptionsArray =  resolveObjectFromPath($scope.row.entity, editDropdownRowEntityOptionsArrayPath);\n              }\n              else {\n                $scope.editDropdownOptionsArray = $scope.col.colDef.editDropdownOptionsArray;\n              }\n              $scope.editDropdownIdLabel = $scope.col.colDef.editDropdownIdLabel ? $scope.col.colDef.editDropdownIdLabel : 'id';\n              $scope.editDropdownValueLabel = $scope.col.colDef.editDropdownValueLabel ? $scope.col.colDef.editDropdownValueLabel : 'value';\n\n              var cellElement;\n              var createEditor = function(){\n                inEdit = true;\n                cancelBeginEditEvents();\n                var cellElement = angular.element(html);\n                $elm.append(cellElement);\n                editCellScope = $scope.$new();\n                $compile(cellElement)(editCellScope);\n                var gridCellContentsEl = angular.element($elm.children()[0]);\n                gridCellContentsEl.addClass('ui-grid-cell-contents-hidden');\n              };\n              if (!$rootScope.$$phase) {\n                $scope.$apply(createEditor);\n              } else {\n                createEditor();\n              }\n\n              //stop editing when grid is scrolled\n              var deregOnGridScroll = $scope.col.grid.api.core.on.scrollBegin($scope, function () {\n                endEdit();\n                $scope.grid.api.edit.raise.afterCellEdit($scope.row.entity, $scope.col.colDef, cellModel($scope), origCellValue);\n                deregOnGridScroll();\n                deregOnEndCellEdit();\n                deregOnCancelCellEdit();\n              });\n\n              //end editing\n              var deregOnEndCellEdit = $scope.$on(uiGridEditConstants.events.END_CELL_EDIT, function () {\n                endEdit();\n                $scope.grid.api.edit.raise.afterCellEdit($scope.row.entity, $scope.col.colDef, cellModel($scope), origCellValue);\n                deregOnEndCellEdit();\n                deregOnGridScroll();\n                deregOnCancelCellEdit();\n              });\n\n              //cancel editing\n              var deregOnCancelCellEdit = $scope.$on(uiGridEditConstants.events.CANCEL_CELL_EDIT, function () {\n                cancelEdit();\n                deregOnCancelCellEdit();\n                deregOnGridScroll();\n                deregOnEndCellEdit();\n              });\n\n              $scope.$broadcast(uiGridEditConstants.events.BEGIN_CELL_EDIT, triggerEvent);\n              $timeout(function () {\n                //execute in a timeout to give any complex editor templates a cycle to completely render\n                $scope.grid.api.edit.raise.beginCellEdit($scope.row.entity, $scope.col.colDef, triggerEvent);\n              });\n            }\n\n            function endEdit() {\n              $scope.grid.disableScrolling = false;\n              if (!inEdit) {\n                return;\n              }\n\n              //sometimes the events can't keep up with the keyboard and grid focus is lost, so always focus\n              //back to grid here. The focus call needs to be before the $destroy and removal of the control,\n              //otherwise ng-model-options of UpdateOn: 'blur' will not work.\n              if (uiGridCtrl && uiGridCtrl.grid.api.cellNav) {\n                uiGridCtrl.focus();\n              }\n\n              var gridCellContentsEl = angular.element($elm.children()[0]);\n              //remove edit element\n              editCellScope.$destroy();\n              angular.element($elm.children()[1]).remove();\n              gridCellContentsEl.removeClass('ui-grid-cell-contents-hidden');\n              inEdit = false;\n              registerBeginEditEvents();\n              $scope.grid.api.core.notifyDataChange( uiGridConstants.dataChange.EDIT );\n            }\n\n            function cancelEdit() {\n              $scope.grid.disableScrolling = false;\n              if (!inEdit) {\n                return;\n              }\n              cellModel.assign($scope, origCellValue);\n              $scope.$apply();\n\n              $scope.grid.api.edit.raise.cancelCellEdit($scope.row.entity, $scope.col.colDef);\n              endEdit();\n            }\n\n            // resolves a string path against the given object\n            // shamelessly borrowed from\n            // http://stackoverflow.com/questions/6491463/accessing-nested-javascript-objects-with-string-key\n            function resolveObjectFromPath(object, path) {\n              path = path.replace(/\\[(\\w+)\\]/g, '.$1'); // convert indexes to properties\n              path = path.replace(/^\\./, '');           // strip a leading dot\n              var a = path.split('.');\n              while (a.length) {\n                  var n = a.shift();\n                  if (n in object) {\n                      object = object[n];\n                  } else {\n                      return;\n                  }\n              }\n              return object;\n            }\n\n          }\n        };\n      }]);\n\n  /**\n   *  @ngdoc directive\n   *  @name ui.grid.edit.directive:uiGridEditor\n   *  @element div\n   *  @restrict A\n   *\n   *  @description input editor directive for editable fields.\n   *  Provides EndEdit and CancelEdit events\n   *\n   *  Events that end editing:\n   *     blur and enter keydown\n   *\n   *  Events that cancel editing:\n   *    - Esc keydown\n   *\n   */\n  module.directive('uiGridEditor',\n    ['gridUtil', 'uiGridConstants', 'uiGridEditConstants','$timeout', 'uiGridEditService',\n      function (gridUtil, uiGridConstants, uiGridEditConstants, $timeout, uiGridEditService) {\n        return {\n          scope: true,\n          require: ['?^uiGrid', '?^uiGridRenderContainer', 'ngModel'],\n          compile: function () {\n            return {\n              pre: function ($scope, $elm, $attrs) {\n\n              },\n              post: function ($scope, $elm, $attrs, controllers) {\n                var uiGridCtrl, renderContainerCtrl, ngModel;\n                if (controllers[0]) { uiGridCtrl = controllers[0]; }\n                if (controllers[1]) { renderContainerCtrl = controllers[1]; }\n                if (controllers[2]) { ngModel = controllers[2]; }\n\n                //set focus at start of edit\n                $scope.$on(uiGridEditConstants.events.BEGIN_CELL_EDIT, function (evt,triggerEvent) {\n                  $timeout(function () {\n                    $elm[0].focus();\n                    //only select text if it is not being replaced below in the cellNav viewPortKeyPress\n                    if ($scope.col.colDef.enableCellEditOnFocus || !(uiGridCtrl && uiGridCtrl.grid.api.cellNav)) {\n                      $elm[0].select();\n                    }\n                    else {\n                      //some browsers (Chrome) stupidly, imo, support the w3 standard that number, email, ...\n                      //fields should not allow setSelectionRange.  We ignore the error for those browsers\n                      //https://www.w3.org/Bugs/Public/show_bug.cgi?id=24796\n                      try {\n                        $elm[0].setSelectionRange($elm[0].value.length, $elm[0].value.length);\n                      }\n                      catch (ex) {\n                        //ignore\n                      }\n                    }\n                  });\n\n                  //set the keystroke that started the edit event\n                  //we must do this because the BeginEdit is done in a different event loop than the intitial\n                  //keydown event\n                  //fire this event for the keypress that is received\n                  if (uiGridCtrl && uiGridCtrl.grid.api.cellNav) {\n                    var viewPortKeyDownUnregister = uiGridCtrl.grid.api.cellNav.on.viewPortKeyPress($scope, function (evt, rowCol) {\n                      if (uiGridEditService.isStartEditKey(evt)) {\n                        ngModel.$setViewValue(String.fromCharCode(evt.keyCode), evt);\n                        ngModel.$render();\n                      }\n                      viewPortKeyDownUnregister();\n                    });\n                  }\n\n                  $elm.on('blur', function (evt) {\n                    $scope.stopEdit(evt);\n                  });\n                });\n\n\n                $scope.deepEdit = false;\n\n                $scope.stopEdit = function (evt) {\n                  if ($scope.inputForm && !$scope.inputForm.$valid) {\n                    evt.stopPropagation();\n                    $scope.$emit(uiGridEditConstants.events.CANCEL_CELL_EDIT);\n                  }\n                  else {\n                    $scope.$emit(uiGridEditConstants.events.END_CELL_EDIT);\n                  }\n                  $scope.deepEdit = false;\n                };\n\n\n                $elm.on('click', function (evt) {\n                  if ($elm[0].type !== 'checkbox') {\n                    $scope.deepEdit = true;\n                    $timeout(function () {\n                      $scope.grid.disableScrolling = true;\n                    });\n                  }\n                });\n\n                $elm.on('keydown', function (evt) {\n                  switch (evt.keyCode) {\n                    case uiGridConstants.keymap.ESC:\n                      evt.stopPropagation();\n                      $scope.$emit(uiGridEditConstants.events.CANCEL_CELL_EDIT);\n                      break;\n                  }\n\n                  if ($scope.deepEdit &&\n                    (evt.keyCode === uiGridConstants.keymap.LEFT ||\n                     evt.keyCode === uiGridConstants.keymap.RIGHT ||\n                     evt.keyCode === uiGridConstants.keymap.UP ||\n                     evt.keyCode === uiGridConstants.keymap.DOWN)) {\n                    evt.stopPropagation();\n                  }\n                  // Pass the keydown event off to the cellNav service, if it exists\n                  else if (uiGridCtrl && uiGridCtrl.grid.api.cellNav) {\n                    evt.uiGridTargetRenderContainerId = renderContainerCtrl.containerId;\n                    if (uiGridCtrl.cellNav.handleKeyDown(evt) !== null) {\n                      $scope.stopEdit(evt);\n                    }\n                  }\n                  else {\n                    //handle enter and tab for editing not using cellNav\n                    switch (evt.keyCode) {\n                      case uiGridConstants.keymap.ENTER: // Enter (Leave Field)\n                      case uiGridConstants.keymap.TAB:\n                        evt.stopPropagation();\n                        evt.preventDefault();\n                        $scope.stopEdit(evt);\n                        break;\n                    }\n                  }\n\n                  return true;\n                });\n              }\n            };\n          }\n        };\n      }]);\n\n  /**\n   *  @ngdoc directive\n   *  @name ui.grid.edit.directive:input\n   *  @element input\n   *  @restrict E\n   *\n   *  @description directive to provide binding between input[date] value and ng-model for angular 1.2\n   *  It is similar to input[date] directive of angular 1.3\n   *\n   *  Supported date format for input is 'yyyy-MM-dd'\n   *  The directive will set the $valid property of input element and the enclosing form to false if\n   *  model is invalid date or value of input is entered wrong.\n   *\n   */\n    module.directive('uiGridEditor', ['$filter', function ($filter) {\n      function parseDateString(dateString) {\n        if (typeof(dateString) === 'undefined' || dateString === '') {\n          return null;\n        }\n        var parts = dateString.split('-');\n        if (parts.length !== 3) {\n          return null;\n        }\n        var year = parseInt(parts[0], 10);\n        var month = parseInt(parts[1], 10);\n        var day = parseInt(parts[2], 10);\n\n        if (month < 1 || year < 1 || day < 1) {\n          return null;\n        }\n        return new Date(year, (month - 1), day);\n      }\n      return {\n        priority: -100, // run after default uiGridEditor directive\n        require: '?ngModel',\n        link: function (scope, element, attrs, ngModel) {\n\n          if (angular.version.minor === 2 && attrs.type && attrs.type === 'date' && ngModel) {\n\n            ngModel.$formatters.push(function (modelValue) {\n              ngModel.$setValidity(null,(!modelValue || !isNaN(modelValue.getTime())));\n              return $filter('date')(modelValue, 'yyyy-MM-dd');\n            });\n\n            ngModel.$parsers.push(function (viewValue) {\n              if (viewValue && viewValue.length > 0) {\n                var dateValue = parseDateString(viewValue);\n                ngModel.$setValidity(null, (dateValue && !isNaN(dateValue.getTime())));\n                return dateValue;\n              }\n              else {\n                ngModel.$setValidity(null, true);\n                return null;\n              }\n            });\n          }\n        }\n      };\n    }]);\n\n\n  /**\n   *  @ngdoc directive\n   *  @name ui.grid.edit.directive:uiGridEditDropdown\n   *  @element div\n   *  @restrict A\n   *\n   *  @description dropdown editor for editable fields.\n   *  Provides EndEdit and CancelEdit events\n   *\n   *  Events that end editing:\n   *     blur and enter keydown, and any left/right nav\n   *\n   *  Events that cancel editing:\n   *    - Esc keydown\n   *\n   */\n  module.directive('uiGridEditDropdown',\n    ['uiGridConstants', 'uiGridEditConstants',\n      function (uiGridConstants, uiGridEditConstants) {\n        return {\n          require: ['?^uiGrid', '?^uiGridRenderContainer'],\n          scope: true,\n          compile: function () {\n            return {\n              pre: function ($scope, $elm, $attrs) {\n\n              },\n              post: function ($scope, $elm, $attrs, controllers) {\n                var uiGridCtrl = controllers[0];\n                var renderContainerCtrl = controllers[1];\n\n                //set focus at start of edit\n                $scope.$on(uiGridEditConstants.events.BEGIN_CELL_EDIT, function () {\n                  $elm[0].focus();\n                  $elm[0].style.width = ($elm[0].parentElement.offsetWidth - 1) + 'px';\n                  $elm.on('blur', function (evt) {\n                    $scope.stopEdit(evt);\n                  });\n                });\n\n\n                $scope.stopEdit = function (evt) {\n                  // no need to validate a dropdown - invalid values shouldn't be\n                  // available in the list\n                  $scope.$emit(uiGridEditConstants.events.END_CELL_EDIT);\n                };\n\n                $elm.on('keydown', function (evt) {\n                  switch (evt.keyCode) {\n                    case uiGridConstants.keymap.ESC:\n                      evt.stopPropagation();\n                      $scope.$emit(uiGridEditConstants.events.CANCEL_CELL_EDIT);\n                      break;\n                  }\n                  if (uiGridCtrl && uiGridCtrl.grid.api.cellNav) {\n                    evt.uiGridTargetRenderContainerId = renderContainerCtrl.containerId;\n                    if (uiGridCtrl.cellNav.handleKeyDown(evt) !== null) {\n                      $scope.stopEdit(evt);\n                    }\n                  }\n                  else {\n                    //handle enter and tab for editing not using cellNav\n                    switch (evt.keyCode) {\n                      case uiGridConstants.keymap.ENTER: // Enter (Leave Field)\n                      case uiGridConstants.keymap.TAB:\n                        evt.stopPropagation();\n                        evt.preventDefault();\n                        $scope.stopEdit(evt);\n                        break;\n                    }\n                  }\n                  return true;\n                });\n              }\n            };\n          }\n        };\n      }]);\n\n  /**\n   *  @ngdoc directive\n   *  @name ui.grid.edit.directive:uiGridEditFileChooser\n   *  @element div\n   *  @restrict A\n   *\n   *  @description input editor directive for editable fields.\n   *  Provides EndEdit and CancelEdit events\n   *\n   *  Events that end editing:\n   *     blur and enter keydown\n   *\n   *  Events that cancel editing:\n   *    - Esc keydown\n   *\n   */\n  module.directive('uiGridEditFileChooser',\n    ['gridUtil', 'uiGridConstants', 'uiGridEditConstants','$timeout',\n      function (gridUtil, uiGridConstants, uiGridEditConstants, $timeout) {\n        return {\n          scope: true,\n          require: ['?^uiGrid', '?^uiGridRenderContainer'],\n          compile: function () {\n            return {\n              pre: function ($scope, $elm, $attrs) {\n\n              },\n              post: function ($scope, $elm, $attrs, controllers) {\n                var uiGridCtrl, renderContainerCtrl;\n                if (controllers[0]) { uiGridCtrl = controllers[0]; }\n                if (controllers[1]) { renderContainerCtrl = controllers[1]; }\n                var grid = uiGridCtrl.grid;\n\n                var handleFileSelect = function( event ){\n                  var target = event.srcElement || event.target;\n\n                  if (target && target.files && target.files.length > 0) {\n                    /**\n                     *  @ngdoc property\n                     *  @name editFileChooserCallback\n                     *  @propertyOf  ui.grid.edit.api:ColumnDef\n                     *  @description A function that should be called when any files have been chosen\n                     *  by the user.  You should use this to process the files appropriately for your\n                     *  application.\n                     *\n                     *  It passes the gridCol, the gridRow (from which you can get gridRow.entity),\n                     *  and the files.  The files are in the format as returned from the file chooser,\n                     *  an array of files, with each having useful information such as:\n                     *  - `files[0].lastModifiedDate`\n                     *  - `files[0].name`\n                     *  - `files[0].size`  (appears to be in bytes)\n                     *  - `files[0].type`  (MIME type by the looks)\n                     *\n                     *  Typically you would do something with these files - most commonly you would\n                     *  use the filename or read the file itself in.  The example function does both.\n                     *\n                     *  @example\n                     *  <pre>\n                     *  editFileChooserCallBack: function(gridRow, gridCol, files ){\n                     *    // ignore all but the first file, it can only choose one anyway\n                     *    // set the filename into this column\n                     *    gridRow.entity.filename = file[0].name;\n                     *\n                     *    // read the file and set it into a hidden column, which we may do stuff with later\n                     *    var setFile = function(fileContent){\n                     *      gridRow.entity.file = fileContent.currentTarget.result;\n                     *    };\n                     *    var reader = new FileReader();\n                     *    reader.onload = setFile;\n                     *    reader.readAsText( files[0] );\n                     *  }\n                     *  </pre>\n                     */\n                    if ( typeof($scope.col.colDef.editFileChooserCallback) === 'function' ) {\n                      $scope.col.colDef.editFileChooserCallback($scope.row, $scope.col, target.files);\n                    } else {\n                      gridUtil.logError('You need to set colDef.editFileChooserCallback to use the file chooser');\n                    }\n\n                    target.form.reset();\n                    $scope.$emit(uiGridEditConstants.events.END_CELL_EDIT);\n                  } else {\n                    $scope.$emit(uiGridEditConstants.events.CANCEL_CELL_EDIT);\n                  }\n                };\n\n                $elm[0].addEventListener('change', handleFileSelect, false);  // TODO: why the false on the end?  Google\n\n                $scope.$on(uiGridEditConstants.events.BEGIN_CELL_EDIT, function () {\n                  $elm[0].focus();\n                  $elm[0].select();\n\n                  $elm.on('blur', function (evt) {\n                    $scope.$emit(uiGridEditConstants.events.END_CELL_EDIT);\n                  });\n                });\n              }\n            };\n          }\n        };\n      }]);\n\n\n})();\n\n(function () {\n  'use strict';\n\n  /**\n   * @ngdoc overview\n   * @name ui.grid.expandable\n   * @description\n   *\n   * # ui.grid.expandable\n   *\n   * <div class=\"alert alert-warning\" role=\"alert\"><strong>Alpha</strong> This feature is in development. There will almost certainly be breaking api changes, or there are major outstanding bugs.</div>\n   *\n   * This module provides the ability to create subgrids with the ability to expand a row\n   * to show the subgrid.\n   *\n   * <div doc-module-components=\"ui.grid.expandable\"></div>\n   */\n  var module = angular.module('ui.grid.expandable', ['ui.grid']);\n\n  /**\n   *  @ngdoc service\n   *  @name ui.grid.expandable.service:uiGridExpandableService\n   *\n   *  @description Services for the expandable grid\n   */\n  module.service('uiGridExpandableService', ['gridUtil', '$compile', function (gridUtil, $compile) {\n    var service = {\n      initializeGrid: function (grid) {\n\n        grid.expandable = {};\n        grid.expandable.expandedAll = false;\n\n        /**\n         *  @ngdoc object\n         *  @name enableExpandable\n         *  @propertyOf  ui.grid.expandable.api:GridOptions\n         *  @description Whether or not to use expandable feature, allows you to turn off expandable on specific grids\n         *  within your application, or in specific modes on _this_ grid. Defaults to true.\n         *  @example\n         *  <pre>\n         *    $scope.gridOptions = {\n         *      enableExpandable: false\n         *    }\n         *  </pre>\n         */\n        grid.options.enableExpandable = grid.options.enableExpandable !== false;\n\n        /**\n         *  @ngdoc object\n         *  @name expandableRowHeight\n         *  @propertyOf  ui.grid.expandable.api:GridOptions\n         *  @description Height in pixels of the expanded subgrid.  Defaults to\n         *  150\n         *  @example\n         *  <pre>\n         *    $scope.gridOptions = {\n         *      expandableRowHeight: 150\n         *    }\n         *  </pre>\n         */\n        grid.options.expandableRowHeight = grid.options.expandableRowHeight || 150;\n\n        /**\n         *  @ngdoc object\n         *  @name\n         *  @propertyOf  ui.grid.expandable.api:GridOptions\n         *  @description Width in pixels of the expandable column. Defaults to 40\n         *  @example\n         *  <pre>\n         *    $scope.gridOptions = {\n         *      expandableRowHeaderWidth: 40\n         *    }\n         *  </pre>\n         */\n        grid.options.expandableRowHeaderWidth = grid.options.expandableRowHeaderWidth || 40;\n\n        /**\n         *  @ngdoc object\n         *  @name expandableRowTemplate\n         *  @propertyOf  ui.grid.expandable.api:GridOptions\n         *  @description Mandatory. The template for your expanded row\n         *  @example\n         *  <pre>\n         *    $scope.gridOptions = {\n         *      expandableRowTemplate: 'expandableRowTemplate.html'\n         *    }\n         *  </pre>\n         */\n        if ( grid.options.enableExpandable && !grid.options.expandableRowTemplate ){\n          gridUtil.logError( 'You have not set the expandableRowTemplate, disabling expandable module' );\n          grid.options.enableExpandable = false;\n        }\n\n        /**\n         *  @ngdoc object\n         *  @name ui.grid.expandable.api:PublicApi\n         *\n         *  @description Public Api for expandable feature\n         */\n        /**\n         *  @ngdoc object\n         *  @name ui.grid.expandable.api:GridOptions\n         *\n         *  @description Options for configuring the expandable feature, these are available to be\n         *  set using the ui-grid {@link ui.grid.class:GridOptions gridOptions}\n         */\n        var publicApi = {\n          events: {\n            expandable: {\n              /**\n               * @ngdoc event\n               * @name rowExpandedStateChanged\n               * @eventOf  ui.grid.expandable.api:PublicApi\n               * @description raised when cell editing is complete\n               * <pre>\n               *      gridApi.expandable.on.rowExpandedStateChanged(scope,function(row){})\n               * </pre>\n               * @param {GridRow} row the row that was expanded\n               */\n              rowExpandedStateChanged: function (scope, row) {\n              }\n            }\n          },\n\n          methods: {\n            expandable: {\n              /**\n               * @ngdoc method\n               * @name toggleRowExpansion\n               * @methodOf  ui.grid.expandable.api:PublicApi\n               * @description Toggle a specific row\n               * <pre>\n               *      gridApi.expandable.toggleRowExpansion(rowEntity);\n               * </pre>\n               * @param {object} rowEntity the data entity for the row you want to expand\n               */\n              toggleRowExpansion: function (rowEntity) {\n                var row = grid.getRow(rowEntity);\n                if (row !== null) {\n                  service.toggleRowExpansion(grid, row);\n                }\n              },\n\n              /**\n               * @ngdoc method\n               * @name expandAllRows\n               * @methodOf  ui.grid.expandable.api:PublicApi\n               * @description Expand all subgrids.\n               * <pre>\n               *      gridApi.expandable.expandAllRows();\n               * </pre>\n               */\n              expandAllRows: function() {\n                service.expandAllRows(grid);\n              },\n\n              /**\n               * @ngdoc method\n               * @name collapseAllRows\n               * @methodOf  ui.grid.expandable.api:PublicApi\n               * @description Collapse all subgrids.\n               * <pre>\n               *      gridApi.expandable.collapseAllRows();\n               * </pre>\n               */\n              collapseAllRows: function() {\n                service.collapseAllRows(grid);\n              },\n\n              /**\n               * @ngdoc method\n               * @name toggleAllRows\n               * @methodOf  ui.grid.expandable.api:PublicApi\n               * @description Toggle all subgrids.\n               * <pre>\n               *      gridApi.expandable.toggleAllRows();\n               * </pre>\n               */\n              toggleAllRows: function() {\n                service.toggleAllRows(grid);\n              }\n            }\n          }\n        };\n        grid.api.registerEventsFromObject(publicApi.events);\n        grid.api.registerMethodsFromObject(publicApi.methods);\n      },\n\n      toggleRowExpansion: function (grid, row) {\n        row.isExpanded = !row.isExpanded;\n        if (row.isExpanded) {\n          row.height = row.grid.options.rowHeight + grid.options.expandableRowHeight;\n        }\n        else {\n          row.height = row.grid.options.rowHeight;\n          grid.expandable.expandedAll = false;\n        }\n        grid.api.expandable.raise.rowExpandedStateChanged(row);\n      },\n\n      expandAllRows: function(grid, $scope) {\n        grid.renderContainers.body.visibleRowCache.forEach( function(row) {\n          if (!row.isExpanded) {\n            service.toggleRowExpansion(grid, row);\n          }\n        });\n        grid.expandable.expandedAll = true;\n        grid.queueGridRefresh();\n      },\n\n      collapseAllRows: function(grid) {\n        grid.renderContainers.body.visibleRowCache.forEach( function(row) {\n          if (row.isExpanded) {\n            service.toggleRowExpansion(grid, row);\n          }\n        });\n        grid.expandable.expandedAll = false;\n        grid.queueGridRefresh();\n      },\n\n      toggleAllRows: function(grid) {\n        if (grid.expandable.expandedAll) {\n          service.collapseAllRows(grid);\n        }\n        else {\n          service.expandAllRows(grid);\n        }\n      }\n    };\n    return service;\n  }]);\n\n  /**\n   *  @ngdoc object\n   *  @name enableExpandableRowHeader\n   *  @propertyOf  ui.grid.expandable.api:GridOptions\n   *  @description Show a rowHeader to provide the expandable buttons.  If set to false then implies\n   *  you're going to use a custom method for expanding and collapsing the subgrids. Defaults to true.\n   *  @example\n   *  <pre>\n   *    $scope.gridOptions = {\n   *      enableExpandableRowHeader: false\n   *    }\n   *  </pre>\n   */\n  module.directive('uiGridExpandable', ['uiGridExpandableService', '$templateCache',\n    function (uiGridExpandableService, $templateCache) {\n      return {\n        replace: true,\n        priority: 0,\n        require: '^uiGrid',\n        scope: false,\n        compile: function () {\n          return {\n            pre: function ($scope, $elm, $attrs, uiGridCtrl) {\n              if ( uiGridCtrl.grid.options.enableExpandableRowHeader !== false ) {\n                var expandableRowHeaderColDef = {\n                  name: 'expandableButtons',\n                  displayName: '',\n                  exporterSuppressExport: true,\n                  enableColumnResizing: false,\n                  enableColumnMenu: false,\n                  width: uiGridCtrl.grid.options.expandableRowHeaderWidth || 40\n                };\n                expandableRowHeaderColDef.cellTemplate = $templateCache.get('ui-grid/expandableRowHeader');\n                expandableRowHeaderColDef.headerCellTemplate = $templateCache.get('ui-grid/expandableTopRowHeader');\n                uiGridCtrl.grid.addRowHeaderColumn(expandableRowHeaderColDef);\n              }\n              uiGridExpandableService.initializeGrid(uiGridCtrl.grid);\n            },\n            post: function ($scope, $elm, $attrs, uiGridCtrl) {\n            }\n          };\n        }\n      };\n    }]);\n\n  /**\n   *  @ngdoc directive\n   *  @name ui.grid.expandable.directive:uiGrid\n   *  @description stacks on the uiGrid directive to register child grid with parent row when child is created\n   */\n  module.directive('uiGrid', ['uiGridExpandableService', '$templateCache',\n    function (uiGridExpandableService, $templateCache) {\n      return {\n        replace: true,\n        priority: 599,\n        require: '^uiGrid',\n        scope: false,\n        compile: function () {\n          return {\n            pre: function ($scope, $elm, $attrs, uiGridCtrl) {\n\n              uiGridCtrl.grid.api.core.on.renderingComplete($scope, function() {\n                //if a parent grid row is on the scope, then add the parentRow property to this childGrid\n                if ($scope.row && $scope.row.grid && $scope.row.grid.options && $scope.row.grid.options.enableExpandable) {\n\n                  /**\n                   *  @ngdoc directive\n                   *  @name ui.grid.expandable.class:Grid\n                   *  @description Additional Grid properties added by expandable module\n                   */\n\n                  /**\n                   *  @ngdoc object\n                   *  @name parentRow\n                   *  @propertyOf ui.grid.expandable.class:Grid\n                   *  @description reference to the expanded parent row that owns this grid\n                   */\n                  uiGridCtrl.grid.parentRow = $scope.row;\n\n                  //todo: adjust height on parent row when child grid height changes. we need some sort of gridHeightChanged event\n                 // uiGridCtrl.grid.core.on.canvasHeightChanged($scope, function(oldHeight, newHeight) {\n                 //   uiGridCtrl.grid.parentRow = newHeight;\n                 // });\n                }\n\n              });\n            },\n            post: function ($scope, $elm, $attrs, uiGridCtrl) {\n\n            }\n          };\n        }\n      };\n    }]);\n\n  /**\n   *  @ngdoc directive\n   *  @name ui.grid.expandable.directive:uiGridExpandableRow\n   *  @description directive to render the expandable row template\n   */\n  module.directive('uiGridExpandableRow',\n  ['uiGridExpandableService', '$timeout', '$compile', 'uiGridConstants','gridUtil','$interval', '$log',\n    function (uiGridExpandableService, $timeout, $compile, uiGridConstants, gridUtil, $interval, $log) {\n\n      return {\n        replace: false,\n        priority: 0,\n        scope: false,\n\n        compile: function () {\n          return {\n            pre: function ($scope, $elm, $attrs, uiGridCtrl) {\n              gridUtil.getTemplate($scope.grid.options.expandableRowTemplate).then(\n                function (template) {\n                  if ($scope.grid.options.expandableRowScope) {\n                    var expandableRowScope = $scope.grid.options.expandableRowScope;\n                    for (var property in expandableRowScope) {\n                      if (expandableRowScope.hasOwnProperty(property)) {\n                        $scope[property] = expandableRowScope[property];\n                      }\n                    }\n                  }\n                  var expandedRowElement = $compile(template)($scope);\n                  $elm.append(expandedRowElement);\n                  $scope.row.expandedRendered = true;\n              });\n            },\n\n            post: function ($scope, $elm, $attrs, uiGridCtrl) {\n              $scope.$on('$destroy', function() {\n                $scope.row.expandedRendered = false;\n              });\n            }\n          };\n        }\n      };\n    }]);\n\n  /**\n   *  @ngdoc directive\n   *  @name ui.grid.expandable.directive:uiGridRow\n   *  @description stacks on the uiGridRow directive to add support for expandable rows\n   */\n  module.directive('uiGridRow',\n    ['$compile', 'gridUtil', '$templateCache',\n      function ($compile, gridUtil, $templateCache) {\n        return {\n          priority: -200,\n          scope: false,\n          compile: function ($elm, $attrs) {\n            return {\n              pre: function ($scope, $elm, $attrs, controllers) {\n\n                $scope.expandableRow = {};\n\n                $scope.expandableRow.shouldRenderExpand = function () {\n                  var ret = $scope.colContainer.name === 'body' &&  $scope.grid.options.enableExpandable !== false && $scope.row.isExpanded && (!$scope.grid.isScrollingVertically || $scope.row.expandedRendered);\n                  return ret;\n                };\n\n                $scope.expandableRow.shouldRenderFiller = function () {\n                  var ret = $scope.row.isExpanded && ( $scope.colContainer.name !== 'body' || ($scope.grid.isScrollingVertically && !$scope.row.expandedRendered));\n                  return ret;\n                };\n\n /*\n  * Commented out @PaulL1.  This has no purpose that I can see, and causes #2964.  If this code needs to be reinstated for some\n  * reason it needs to use drawnWidth, not width, and needs to check column visibility.  It should really use render container\n  * visible column cache also instead of checking column.renderContainer.\n                  function updateRowContainerWidth() {\n                      var grid = $scope.grid;\n                      var colWidth = 0;\n                      grid.columns.forEach( function (column) {\n                          if (column.renderContainer === 'left') {\n                            colWidth += column.width;\n                          }\n                      });\n                      colWidth = Math.floor(colWidth);\n                      return '.grid' + grid.id + ' .ui-grid-pinned-container-' + $scope.colContainer.name + ', .grid' + grid.id +\n                          ' .ui-grid-pinned-container-' + $scope.colContainer.name + ' .ui-grid-render-container-' + $scope.colContainer.name +\n                          ' .ui-grid-viewport .ui-grid-canvas .ui-grid-row { width: ' + colWidth + 'px; }';\n                  }\n\n                  if ($scope.colContainer.name === 'left') {\n                      $scope.grid.registerStyleComputation({\n                          priority: 15,\n                          func: updateRowContainerWidth\n                      });\n                  }*/\n\n              },\n              post: function ($scope, $elm, $attrs, controllers) {\n              }\n            };\n          }\n        };\n      }]);\n\n  /**\n   *  @ngdoc directive\n   *  @name ui.grid.expandable.directive:uiGridViewport\n   *  @description stacks on the uiGridViewport directive to append the expandable row html elements to the\n   *  default gridRow template\n   */\n  module.directive('uiGridViewport',\n    ['$compile', 'gridUtil', '$templateCache',\n      function ($compile, gridUtil, $templateCache) {\n        return {\n          priority: -200,\n          scope: false,\n          compile: function ($elm, $attrs) {\n            var rowRepeatDiv = angular.element($elm.children().children()[0]);\n            var expandedRowFillerElement = $templateCache.get('ui-grid/expandableScrollFiller');\n            var expandedRowElement = $templateCache.get('ui-grid/expandableRow');\n            rowRepeatDiv.append(expandedRowElement);\n            rowRepeatDiv.append(expandedRowFillerElement);\n            return {\n              pre: function ($scope, $elm, $attrs, controllers) {\n              },\n              post: function ($scope, $elm, $attrs, controllers) {\n              }\n            };\n          }\n        };\n      }]);\n\n})();\n\n/* global console */\n\n(function () {\n  'use strict';\n\n  /**\n   * @ngdoc overview\n   * @name ui.grid.exporter\n   * @description\n   *\n   * # ui.grid.exporter\n   *\n   * <div class=\"alert alert-success\" role=\"alert\"><strong>Stable</strong> This feature is stable. There should no longer be breaking api changes without a deprecation warning.</div>\n   *\n   * This module provides the ability to exporter data from the grid.\n   *\n   * Data can be exported in a range of formats, and all data, visible\n   * data, or selected rows can be exported, with all columns or visible\n   * columns.\n   *\n   * No UI is provided, the caller should provide their own UI/buttons\n   * as appropriate, or enable the gridMenu\n   *\n   * <br/>\n   * <br/>\n   *\n   * <div doc-module-components=\"ui.grid.exporter\"></div>\n   */\n\n  var module = angular.module('ui.grid.exporter', ['ui.grid']);\n\n  /**\n   *  @ngdoc object\n   *  @name ui.grid.exporter.constant:uiGridExporterConstants\n   *\n   *  @description constants available in exporter module\n   */\n  /**\n   * @ngdoc property\n   * @propertyOf ui.grid.exporter.constant:uiGridExporterConstants\n   * @name ALL\n   * @description export all data, including data not visible.  Can\n   * be set for either rowTypes or colTypes\n   */\n  /**\n   * @ngdoc property\n   * @propertyOf ui.grid.exporter.constant:uiGridExporterConstants\n   * @name VISIBLE\n   * @description export only visible data, including data not visible.  Can\n   * be set for either rowTypes or colTypes\n   */\n  /**\n   * @ngdoc property\n   * @propertyOf ui.grid.exporter.constant:uiGridExporterConstants\n   * @name SELECTED\n   * @description export all data, including data not visible.  Can\n   * be set only for rowTypes, selection of only some columns is\n   * not supported\n   */\n  module.constant('uiGridExporterConstants', {\n    featureName: 'exporter',\n    ALL: 'all',\n    VISIBLE: 'visible',\n    SELECTED: 'selected',\n    CSV_CONTENT: 'CSV_CONTENT',\n    BUTTON_LABEL: 'BUTTON_LABEL',\n    FILE_NAME: 'FILE_NAME'\n  });\n\n  /**\n   *  @ngdoc service\n   *  @name ui.grid.exporter.service:uiGridExporterService\n   *\n   *  @description Services for exporter feature\n   */\n  module.service('uiGridExporterService', ['$q', 'uiGridExporterConstants', 'gridUtil', '$compile', '$interval', 'i18nService',\n    function ($q, uiGridExporterConstants, gridUtil, $compile, $interval, i18nService) {\n\n      var service = {\n\n        delay: 100,\n\n        initializeGrid: function (grid) {\n\n          //add feature namespace and any properties to grid for needed state\n          grid.exporter = {};\n          this.defaultGridOptions(grid.options);\n\n          /**\n           *  @ngdoc object\n           *  @name ui.grid.exporter.api:PublicApi\n           *\n           *  @description Public Api for exporter feature\n           */\n          var publicApi = {\n            events: {\n              exporter: {\n              }\n            },\n            methods: {\n              exporter: {\n                /**\n                 * @ngdoc function\n                 * @name csvExport\n                 * @methodOf  ui.grid.exporter.api:PublicApi\n                 * @description Exports rows from the grid in csv format,\n                 * the data exported is selected based on the provided options\n                 * @param {string} rowTypes which rows to export, valid values are\n                 * uiGridExporterConstants.ALL, uiGridExporterConstants.VISIBLE,\n                 * uiGridExporterConstants.SELECTED\n                 * @param {string} colTypes which columns to export, valid values are\n                 * uiGridExporterConstants.ALL, uiGridExporterConstants.VISIBLE\n                 */\n                csvExport: function (rowTypes, colTypes) {\n                  service.csvExport(grid, rowTypes, colTypes);\n                },\n                /**\n                 * @ngdoc function\n                 * @name pdfExport\n                 * @methodOf  ui.grid.exporter.api:PublicApi\n                 * @description Exports rows from the grid in pdf format,\n                 * the data exported is selected based on the provided options\n                 * Note that this function has a dependency on pdfMake, all\n                 * going well this has been installed for you.\n                 * The resulting pdf opens in a new browser window.\n                 * @param {string} rowTypes which rows to export, valid values are\n                 * uiGridExporterConstants.ALL, uiGridExporterConstants.VISIBLE,\n                 * uiGridExporterConstants.SELECTED\n                 * @param {string} colTypes which columns to export, valid values are\n                 * uiGridExporterConstants.ALL, uiGridExporterConstants.VISIBLE\n                 */\n                pdfExport: function (rowTypes, colTypes) {\n                  service.pdfExport(grid, rowTypes, colTypes);\n                }\n              }\n            }\n          };\n\n          grid.api.registerEventsFromObject(publicApi.events);\n\n          grid.api.registerMethodsFromObject(publicApi.methods);\n\n          if (grid.api.core.addToGridMenu){\n            service.addToMenu( grid );\n          } else {\n            // order of registration is not guaranteed, register in a little while\n            $interval( function() {\n              if (grid.api.core.addToGridMenu){\n                service.addToMenu( grid );\n              }\n            }, this.delay, 1);\n          }\n\n        },\n\n        defaultGridOptions: function (gridOptions) {\n          //default option to true unless it was explicitly set to false\n          /**\n           * @ngdoc object\n           * @name ui.grid.exporter.api:GridOptions\n           *\n           * @description GridOptions for exporter feature, these are available to be\n           * set using the ui-grid {@link ui.grid.class:GridOptions gridOptions}\n           */\n          /**\n           * @ngdoc object\n           * @name ui.grid.exporter.api:ColumnDef\n           * @description ColumnDef settings for exporter\n           */\n          /**\n           * @ngdoc object\n           * @name exporterSuppressMenu\n           * @propertyOf  ui.grid.exporter.api:GridOptions\n           * @description Don't show the export menu button, implying the user\n           * will roll their own UI for calling the exporter\n           * <br/>Defaults to false\n           */\n          gridOptions.exporterSuppressMenu = gridOptions.exporterSuppressMenu === true;\n          /**\n           * @ngdoc object\n           * @name exporterMenuLabel\n           * @propertyOf  ui.grid.exporter.api:GridOptions\n           * @description The text to show on the exporter menu button\n           * link\n           * <br/>Defaults to 'Export'\n           */\n          gridOptions.exporterMenuLabel = gridOptions.exporterMenuLabel ? gridOptions.exporterMenuLabel : 'Export';\n          /**\n           * @ngdoc object\n           * @name exporterSuppressColumns\n           * @propertyOf  ui.grid.exporter.api:GridOptions\n           * @description Columns that should not be exported.  The selectionRowHeader is already automatically\n           * suppressed, but if you had a button column or some other \"system\" column that shouldn't be shown in the\n           * output then add it in this list.  You should provide an array of column names.\n           * <br/>Defaults to: []\n           * <pre>\n           *   gridOptions.exporterSuppressColumns = [ 'buttons' ];\n           * </pre>\n           */\n          gridOptions.exporterSuppressColumns = gridOptions.exporterSuppressColumns ? gridOptions.exporterSuppressColumns : [];\n          /**\n           * @ngdoc object\n           * @name exporterCsvColumnSeparator\n           * @propertyOf  ui.grid.exporter.api:GridOptions\n           * @description The character to use as column separator\n           * link\n           * <br/>Defaults to ','\n           */\n          gridOptions.exporterCsvColumnSeparator = gridOptions.exporterCsvColumnSeparator ? gridOptions.exporterCsvColumnSeparator : ',';\n          /**\n           * @ngdoc object\n           * @name exporterCsvFilename\n           * @propertyOf  ui.grid.exporter.api:GridOptions\n           * @description The default filename to use when saving the downloaded csv.\n           * This will only work in some browsers.\n           * <br/>Defaults to 'download.csv'\n           */\n          gridOptions.exporterCsvFilename = gridOptions.exporterCsvFilename ? gridOptions.exporterCsvFilename : 'download.csv';\n          /**\n           * @ngdoc object\n           * @name exporterPdfFilename\n           * @propertyOf  ui.grid.exporter.api:GridOptions\n           * @description The default filename to use when saving the downloaded pdf, only used in IE (other browsers open pdfs in a new window)\n           * <br/>Defaults to 'download.pdf'\n           */\n          gridOptions.exporterPdfFilename = gridOptions.exporterPdfFilename ? gridOptions.exporterPdfFilename : 'download.pdf';\n          /**\n           * @ngdoc object\n           * @name exporterOlderExcelCompatibility\n           * @propertyOf  ui.grid.exporter.api:GridOptions\n           * @description Some versions of excel don't like the utf-16 BOM on the front, and it comes\n           * through as ï»¿ in the first column header.  Setting this option to false will suppress this, at the\n           * expense of proper utf-16 handling in applications that do recognise the BOM\n           * <br/>Defaults to false\n           */\n          gridOptions.exporterOlderExcelCompatibility = gridOptions.exporterOlderExcelCompatibility === true;\n          /**\n           * @ngdoc object\n           * @name exporterPdfDefaultStyle\n           * @propertyOf  ui.grid.exporter.api:GridOptions\n           * @description The default style in pdfMake format\n           * <br/>Defaults to:\n           * <pre>\n           *   {\n           *     fontSize: 11\n           *   }\n           * </pre>\n           */\n          gridOptions.exporterPdfDefaultStyle = gridOptions.exporterPdfDefaultStyle ? gridOptions.exporterPdfDefaultStyle : { fontSize: 11 };\n          /**\n           * @ngdoc object\n           * @name exporterPdfTableStyle\n           * @propertyOf  ui.grid.exporter.api:GridOptions\n           * @description The table style in pdfMake format\n           * <br/>Defaults to:\n           * <pre>\n           *   {\n           *     margin: [0, 5, 0, 15]\n           *   }\n           * </pre>\n           */\n          gridOptions.exporterPdfTableStyle = gridOptions.exporterPdfTableStyle ? gridOptions.exporterPdfTableStyle : { margin: [0, 5, 0, 15] };\n          /**\n           * @ngdoc object\n           * @name exporterPdfTableHeaderStyle\n           * @propertyOf  ui.grid.exporter.api:GridOptions\n           * @description The tableHeader style in pdfMake format\n           * <br/>Defaults to:\n           * <pre>\n           *   {\n           *     bold: true,\n           *     fontSize: 12,\n           *     color: 'black'\n           *   }\n           * </pre>\n           */\n          gridOptions.exporterPdfTableHeaderStyle = gridOptions.exporterPdfTableHeaderStyle ? gridOptions.exporterPdfTableHeaderStyle : { bold: true, fontSize: 12, color: 'black' };\n          /**\n           * @ngdoc object\n           * @name exporterPdfHeader\n           * @propertyOf  ui.grid.exporter.api:GridOptions\n           * @description The header section for pdf exports.  Can be\n           * simple text:\n           * <pre>\n           *   gridOptions.exporterPdfHeader = 'My Header';\n           * </pre>\n           * Can be a more complex object in pdfMake format:\n           * <pre>\n           *   gridOptions.exporterPdfHeader = {\n           *     columns: [\n           *       'Left part',\n           *       { text: 'Right part', alignment: 'right' }\n           *     ]\n           *   };\n           * </pre>\n           * Or can be a function, allowing page numbers and the like\n           * <pre>\n           *   gridOptions.exporterPdfHeader: function(currentPage, pageCount) { return currentPage.toString() + ' of ' + pageCount; };\n           * </pre>\n           */\n          gridOptions.exporterPdfHeader = gridOptions.exporterPdfHeader ? gridOptions.exporterPdfHeader : null;\n          /**\n           * @ngdoc object\n           * @name exporterPdfFooter\n           * @propertyOf  ui.grid.exporter.api:GridOptions\n           * @description The header section for pdf exports.  Can be\n           * simple text:\n           * <pre>\n           *   gridOptions.exporterPdfFooter = 'My Footer';\n           * </pre>\n           * Can be a more complex object in pdfMake format:\n           * <pre>\n           *   gridOptions.exporterPdfFooter = {\n           *     columns: [\n           *       'Left part',\n           *       { text: 'Right part', alignment: 'right' }\n           *     ]\n           *   };\n           * </pre>\n           * Or can be a function, allowing page numbers and the like\n           * <pre>\n           *   gridOptions.exporterPdfFooter: function(currentPage, pageCount) { return currentPage.toString() + ' of ' + pageCount; };\n           * </pre>\n           */\n          gridOptions.exporterPdfFooter = gridOptions.exporterPdfFooter ? gridOptions.exporterPdfFooter : null;\n          /**\n           * @ngdoc object\n           * @name exporterPdfOrientation\n           * @propertyOf  ui.grid.exporter.api:GridOptions\n           * @description The orientation, should be a valid pdfMake value,\n           * 'landscape' or 'portrait'\n           * <br/>Defaults to landscape\n           */\n          gridOptions.exporterPdfOrientation = gridOptions.exporterPdfOrientation ? gridOptions.exporterPdfOrientation : 'landscape';\n          /**\n           * @ngdoc object\n           * @name exporterPdfPageSize\n           * @propertyOf  ui.grid.exporter.api:GridOptions\n           * @description The orientation, should be a valid pdfMake\n           * paper size, usually 'A4' or 'LETTER'\n           * {@link https://github.com/bpampuch/pdfmake/blob/master/src/standardPageSizes.js pdfMake page sizes}\n           * <br/>Defaults to A4\n           */\n          gridOptions.exporterPdfPageSize = gridOptions.exporterPdfPageSize ? gridOptions.exporterPdfPageSize : 'A4';\n          /**\n           * @ngdoc object\n           * @name exporterPdfMaxGridWidth\n           * @propertyOf  ui.grid.exporter.api:GridOptions\n           * @description The maxium grid width - the current grid width\n           * will be scaled to match this, with any fixed width columns\n           * being adjusted accordingly.\n           * <br/>Defaults to 720 (for A4 landscape), use 670 for LETTER\n           */\n          gridOptions.exporterPdfMaxGridWidth = gridOptions.exporterPdfMaxGridWidth ? gridOptions.exporterPdfMaxGridWidth : 720;\n          /**\n           * @ngdoc object\n           * @name exporterPdfTableLayout\n           * @propertyOf  ui.grid.exporter.api:GridOptions\n           * @description A tableLayout in pdfMake format,\n           * controls gridlines and the like.  We use the default\n           * layout usually.\n           * <br/>Defaults to null, which means no layout\n           */\n\n          /**\n           * @ngdoc object\n           * @name exporterMenuAllData\n           * @porpertyOf  ui.grid.exporter.api:GridOptions\n           * @description Add export all data as cvs/pdf menu items to the ui-grid grid menu, if it's present.  Defaults to true.\n           */\n          gridOptions.exporterMenuAllData = gridOptions.exporterMenuAllData !== undefined ? gridOptions.exporterMenuAllData : true;\n\n          /**\n           * @ngdoc object\n           * @name exporterMenuCsv\n           * @propertyOf  ui.grid.exporter.api:GridOptions\n           * @description Add csv export menu items to the ui-grid grid menu, if it's present.  Defaults to true.\n           */\n          gridOptions.exporterMenuCsv = gridOptions.exporterMenuCsv !== undefined ? gridOptions.exporterMenuCsv : true;\n\n          /**\n           * @ngdoc object\n           * @name exporterMenuPdf\n           * @propertyOf  ui.grid.exporter.api:GridOptions\n           * @description Add pdf export menu items to the ui-grid grid menu, if it's present.  Defaults to true.\n           */\n          gridOptions.exporterMenuPdf = gridOptions.exporterMenuPdf !== undefined ? gridOptions.exporterMenuPdf : true;\n\n          /**\n           * @ngdoc object\n           * @name exporterPdfCustomFormatter\n           * @propertyOf  ui.grid.exporter.api:GridOptions\n           * @description A custom callback routine that changes the pdf document, adding any\n           * custom styling or content that is supported by pdfMake.  Takes in the complete docDefinition, and\n           * must return an updated docDefinition ready for pdfMake.\n           * @example\n           * In this example we add a style to the style array, so that we can use it in our\n           * footer definition.\n           * <pre>\n           *   gridOptions.exporterPdfCustomFormatter = function ( docDefinition ) {\n           *     docDefinition.styles.footerStyle = { bold: true, fontSize: 10 };\n           *     return docDefinition;\n           *   }\n           *\n           *   gridOptions.exporterPdfFooter = { text: 'My footer', style: 'footerStyle' }\n           * </pre>\n           */\n          gridOptions.exporterPdfCustomFormatter = ( gridOptions.exporterPdfCustomFormatter && typeof( gridOptions.exporterPdfCustomFormatter ) === 'function' ) ? gridOptions.exporterPdfCustomFormatter : function ( docDef ) { return docDef; };\n\n          /**\n           * @ngdoc object\n           * @name exporterHeaderFilterUseName\n           * @propertyOf  ui.grid.exporter.api:GridOptions\n           * @description Defaults to false, which leads to `displayName` being passed into the headerFilter.\n           * If set to true, then will pass `name` instead.\n           *\n           *\n           * @example\n           * <pre>\n           *   gridOptions.exporterHeaderFilterUseName = true;\n           * </pre>\n           */\n          gridOptions.exporterHeaderFilterUseName = gridOptions.exporterHeaderFilterUseName === true;\n\n          /**\n           * @ngdoc object\n           * @name exporterHeaderFilter\n           * @propertyOf  ui.grid.exporter.api:GridOptions\n           * @description A function to apply to the header displayNames before exporting.  Useful for internationalisation,\n           * for example if you were using angular-translate you'd set this to `$translate.instant`.  Note that this\n           * call must be synchronous, it cannot be a call that returns a promise.\n           *\n           * Behaviour can be changed to pass in `name` instead of `displayName` through use of `exporterHeaderFilterUseName: true`.\n           *\n           * @example\n           * <pre>\n           *   gridOptions.exporterHeaderFilter = function( displayName ){ return 'col: ' + name; };\n           * </pre>\n           * OR\n           * <pre>\n           *   gridOptions.exporterHeaderFilter = $translate.instant;\n           * </pre>\n           */\n\n          /**\n           * @ngdoc function\n           * @name exporterFieldCallback\n           * @propertyOf  ui.grid.exporter.api:GridOptions\n           * @description A function to call for each field before exporting it.  Allows\n           * massaging of raw data into a display format, for example if you have applied\n           * filters to convert codes into decodes, or you require\n           * a specific date format in the exported content.\n           *\n           * The method is called once for each field exported, and provides the grid, the\n           * gridCol and the GridRow for you to use as context in massaging the data.\n           *\n           * @param {Grid} grid provides the grid in case you have need of it\n           * @param {GridRow} row the row from which the data comes\n           * @param {GridCol} col the column from which the data comes\n           * @param {object} value the value for your massaging\n           * @returns {object} you must return the massaged value ready for exporting\n           *\n           * @example\n           * <pre>\n           *   gridOptions.exporterFieldCallback = function ( grid, row, col, value ){\n           *     if ( col.name === 'status' ){\n           *       value = decodeStatus( value );\n           *     }\n           *     return value;\n           *   }\n           * </pre>\n           */\n          gridOptions.exporterFieldCallback = gridOptions.exporterFieldCallback ? gridOptions.exporterFieldCallback : function( grid, row, col, value ) { return value; };\n\n          /**\n           * @ngdoc function\n           * @name exporterAllDataFn\n           * @propertyOf  ui.grid.exporter.api:GridOptions\n           * @description This promise is needed when exporting all rows,\n           * and the data need to be provided by server side. Default is null.\n           * @returns {Promise} a promise to load all data from server\n           *\n           * @example\n           * <pre>\n           *   gridOptions.exporterAllDataFn = function () {\n           *     return $http.get('/data/100.json')\n           *   }\n           * </pre>\n           */\n          gridOptions.exporterAllDataFn = gridOptions.exporterAllDataFn ? gridOptions.exporterAllDataFn : null;\n\n          /**\n           * @ngdoc function\n           * @name exporterAllDataPromise\n           * @propertyOf  ui.grid.exporter.api:GridOptions\n           * @description DEPRECATED - exporterAllDataFn used to be\n           * called this, but it wasn't a promise, it was a function that returned\n           * a promise.  Deprecated, but supported for backward compatibility, use\n           * exporterAllDataFn instead.\n           * @returns {Promise} a promise to load all data from server\n           *\n           * @example\n           * <pre>\n           *   gridOptions.exporterAllDataFn = function () {\n           *     return $http.get('/data/100.json')\n           *   }\n           * </pre>\n           */\n          if ( gridOptions.exporterAllDataFn == null && gridOptions.exporterAllDataPromise ) {\n            gridOptions.exporterAllDataFn = gridOptions.exporterAllDataPromise;\n          }\n        },\n\n\n        /**\n         * @ngdoc function\n         * @name addToMenu\n         * @methodOf  ui.grid.exporter.service:uiGridExporterService\n         * @description Adds export items to the grid menu,\n         * allowing the user to select export options\n         * @param {Grid} grid the grid from which data should be exported\n         */\n        addToMenu: function ( grid ) {\n          grid.api.core.addToGridMenu( grid, [\n            {\n              title: i18nService.getSafeText('gridMenu.exporterAllAsCsv'),\n              action: function ($event) {\n                this.grid.api.exporter.csvExport( uiGridExporterConstants.ALL, uiGridExporterConstants.ALL );\n              },\n              shown: function() {\n                return this.grid.options.exporterMenuCsv && this.grid.options.exporterMenuAllData;\n              },\n              order: 200\n            },\n            {\n              title: i18nService.getSafeText('gridMenu.exporterVisibleAsCsv'),\n              action: function ($event) {\n                this.grid.api.exporter.csvExport( uiGridExporterConstants.VISIBLE, uiGridExporterConstants.VISIBLE );\n              },\n              shown: function() {\n                return this.grid.options.exporterMenuCsv;\n              },\n              order: 201\n            },\n            {\n              title: i18nService.getSafeText('gridMenu.exporterSelectedAsCsv'),\n              action: function ($event) {\n                this.grid.api.exporter.csvExport( uiGridExporterConstants.SELECTED, uiGridExporterConstants.VISIBLE );\n              },\n              shown: function() {\n                return this.grid.options.exporterMenuCsv &&\n                       ( this.grid.api.selection && this.grid.api.selection.getSelectedRows().length > 0 );\n              },\n              order: 202\n            },\n            {\n              title: i18nService.getSafeText('gridMenu.exporterAllAsPdf'),\n              action: function ($event) {\n                this.grid.api.exporter.pdfExport( uiGridExporterConstants.ALL, uiGridExporterConstants.ALL );\n              },\n              shown: function() {\n                return this.grid.options.exporterMenuPdf && this.grid.options.exporterMenuAllData;\n              },\n              order: 203\n            },\n            {\n              title: i18nService.getSafeText('gridMenu.exporterVisibleAsPdf'),\n              action: function ($event) {\n                this.grid.api.exporter.pdfExport( uiGridExporterConstants.VISIBLE, uiGridExporterConstants.VISIBLE );\n              },\n              shown: function() {\n                return this.grid.options.exporterMenuPdf;\n              },\n              order: 204\n            },\n            {\n              title: i18nService.getSafeText('gridMenu.exporterSelectedAsPdf'),\n              action: function ($event) {\n                this.grid.api.exporter.pdfExport( uiGridExporterConstants.SELECTED, uiGridExporterConstants.VISIBLE );\n              },\n              shown: function() {\n                return this.grid.options.exporterMenuPdf &&\n                       ( this.grid.api.selection && this.grid.api.selection.getSelectedRows().length > 0 );\n              },\n              order: 205\n            }\n          ]);\n        },\n\n\n        /**\n         * @ngdoc function\n         * @name csvExport\n         * @methodOf  ui.grid.exporter.service:uiGridExporterService\n         * @description Exports rows from the grid in csv format,\n         * the data exported is selected based on the provided options\n         * @param {Grid} grid the grid from which data should be exported\n         * @param {string} rowTypes which rows to export, valid values are\n         * uiGridExporterConstants.ALL, uiGridExporterConstants.VISIBLE,\n         * uiGridExporterConstants.SELECTED\n         * @param {string} colTypes which columns to export, valid values are\n         * uiGridExporterConstants.ALL, uiGridExporterConstants.VISIBLE,\n         * uiGridExporterConstants.SELECTED\n         */\n        csvExport: function (grid, rowTypes, colTypes) {\n          var self = this;\n          this.loadAllDataIfNeeded(grid, rowTypes, colTypes).then(function() {\n            var exportColumnHeaders = self.getColumnHeaders(grid, colTypes);\n            var exportData = self.getData(grid, rowTypes, colTypes);\n            var csvContent = self.formatAsCsv(exportColumnHeaders, exportData, grid.options.exporterCsvColumnSeparator);\n\n            self.downloadFile (grid.options.exporterCsvFilename, csvContent, grid.options.exporterOlderExcelCompatibility);\n          });\n        },\n\n        /**\n         * @ngdoc function\n         * @name loadAllDataIfNeeded\n         * @methodOf  ui.grid.exporter.service:uiGridExporterService\n         * @description When using server side pagination, use exporterAllDataFn to\n         * load all data before continuing processing.\n         * When using client side pagination, return a resolved promise so processing\n         * continues immediately\n         * @param {Grid} grid the grid from which data should be exported\n         * @param {string} rowTypes which rows to export, valid values are\n         * uiGridExporterConstants.ALL, uiGridExporterConstants.VISIBLE,\n         * uiGridExporterConstants.SELECTED\n         * @param {string} colTypes which columns to export, valid values are\n         * uiGridExporterConstants.ALL, uiGridExporterConstants.VISIBLE,\n         * uiGridExporterConstants.SELECTED\n         */\n        loadAllDataIfNeeded: function (grid, rowTypes, colTypes) {\n          if ( rowTypes === uiGridExporterConstants.ALL && grid.rows.length !== grid.options.totalItems && grid.options.exporterAllDataFn) {\n            return grid.options.exporterAllDataFn()\n              .then(function() {\n                grid.modifyRows(grid.options.data);\n              });\n          } else {\n            var deferred = $q.defer();\n            deferred.resolve();\n            return deferred.promise;\n          }\n        },\n\n        /**\n         * @ngdoc property\n         * @propertyOf ui.grid.exporter.api:ColumnDef\n         * @name exporterSuppressExport\n         * @description Suppresses export for this column.  Used by selection and expandable.\n         */\n\n        /**\n         * @ngdoc function\n         * @name getColumnHeaders\n         * @methodOf  ui.grid.exporter.service:uiGridExporterService\n         * @description Gets the column headers from the grid to use\n         * as a title row for the exported file, all headers have\n         * headerCellFilters applied as appropriate.\n         *\n         * Column headers are an array of objects, each object has\n         * name, displayName, width and align attributes.  Only name is\n         * used for csv, all attributes are used for pdf.\n         *\n         * @param {Grid} grid the grid from which data should be exported\n         * @param {string} colTypes which columns to export, valid values are\n         * uiGridExporterConstants.ALL, uiGridExporterConstants.VISIBLE,\n         * uiGridExporterConstants.SELECTED\n         */\n        getColumnHeaders: function (grid, colTypes) {\n          var headers = [];\n          var columns;\n\n          if ( colTypes === uiGridExporterConstants.ALL ){\n            columns = grid.columns;\n          } else {\n            columns = grid.renderContainers.body.visibleColumnCache.filter( function( column ){ return column.visible; } );\n          }\n\n          columns.forEach( function( gridCol, index ) {\n            if ( gridCol.colDef.exporterSuppressExport !== true &&\n                 grid.options.exporterSuppressColumns.indexOf( gridCol.name ) === -1 ){\n              headers.push({\n                name: gridCol.field,\n                displayName: grid.options.exporterHeaderFilter ? ( grid.options.exporterHeaderFilterUseName ? grid.options.exporterHeaderFilter(gridCol.name) : grid.options.exporterHeaderFilter(gridCol.displayName) ) : gridCol.displayName,\n                width: gridCol.drawnWidth ? gridCol.drawnWidth : gridCol.width,\n                align: gridCol.colDef.type === 'number' ? 'right' : 'left'\n              });\n            }\n          });\n\n          return headers;\n        },\n\n\n        /**\n         * @ngdoc property\n         * @propertyOf ui.grid.exporter.api:ColumnDef\n         * @name exporterPdfAlign\n         * @description the alignment you'd like for this specific column when\n         * exported into a pdf.  Can be 'left', 'right', 'center' or any other\n         * valid pdfMake alignment option.\n         */\n\n\n        /**\n         * @ngdoc object\n         * @name ui.grid.exporter.api:GridRow\n         * @description GridRow settings for exporter\n         */\n        /**\n         * @ngdoc object\n         * @name exporterEnableExporting\n         * @propertyOf  ui.grid.exporter.api:GridRow\n         * @description If set to false, then don't export this row, notwithstanding visible or\n         * other settings\n         * <br/>Defaults to true\n         */\n\n        /**\n         * @ngdoc function\n         * @name getData\n         * @methodOf  ui.grid.exporter.service:uiGridExporterService\n         * @description Gets data from the grid based on the provided options,\n         * all cells have cellFilters applied as appropriate.  Any rows marked\n         * `exporterEnableExporting: false` will not be exported\n         * @param {Grid} grid the grid from which data should be exported\n         * @param {string} rowTypes which rows to export, valid values are\n         * uiGridExporterConstants.ALL, uiGridExporterConstants.VISIBLE,\n         * uiGridExporterConstants.SELECTED\n         * @param {string} colTypes which columns to export, valid values are\n         * uiGridExporterConstants.ALL, uiGridExporterConstants.VISIBLE,\n         * uiGridExporterConstants.SELECTED\n         */\n        getData: function (grid, rowTypes, colTypes) {\n          var data = [];\n          var rows;\n          var columns;\n\n          switch ( rowTypes ) {\n            case uiGridExporterConstants.ALL:\n              rows = grid.rows;\n              break;\n            case uiGridExporterConstants.VISIBLE:\n              rows = grid.getVisibleRows();\n              break;\n            case uiGridExporterConstants.SELECTED:\n              if ( grid.api.selection ){\n                rows = grid.api.selection.getSelectedGridRows();\n              } else {\n                gridUtil.logError('selection feature must be enabled to allow selected rows to be exported');\n              }\n              break;\n          }\n\n          if ( colTypes === uiGridExporterConstants.ALL ){\n            columns = grid.columns;\n          } else {\n            columns = grid.renderContainers.body.visibleColumnCache.filter( function( column ){ return column.visible; } );\n          }\n\n          rows.forEach( function( row, index ) {\n\n            if (row.exporterEnableExporting !== false) {\n              var extractedRow = [];\n\n\n              columns.forEach( function( gridCol, index ) {\n              if ( (gridCol.visible || colTypes === uiGridExporterConstants.ALL ) &&\n                   gridCol.colDef.exporterSuppressExport !== true &&\n                   grid.options.exporterSuppressColumns.indexOf( gridCol.name ) === -1 ){\n                  var extractedField = { value: grid.options.exporterFieldCallback( grid, row, gridCol, grid.getCellValue( row, gridCol ) ) };\n                  if ( gridCol.colDef.exporterPdfAlign ) {\n                    extractedField.alignment = gridCol.colDef.exporterPdfAlign;\n                  }\n                  extractedRow.push(extractedField);\n                }\n              });\n\n              data.push(extractedRow);\n            }\n          });\n\n          return data;\n        },\n\n\n        /**\n         * @ngdoc function\n         * @name formatAsCSV\n         * @methodOf  ui.grid.exporter.service:uiGridExporterService\n         * @description Formats the column headers and data as a CSV,\n         * and sends that data to the user\n         * @param {array} exportColumnHeaders an array of column headers,\n         * where each header is an object with name, width and maybe alignment\n         * @param {array} exportData an array of rows, where each row is\n         * an array of column data\n         * @returns {string} csv the formatted csv as a string\n         */\n        formatAsCsv: function (exportColumnHeaders, exportData, separator) {\n          var self = this;\n\n          var bareHeaders = exportColumnHeaders.map(function(header){return { value: header.displayName };});\n\n          var csv = self.formatRowAsCsv(this, separator)(bareHeaders) + '\\n';\n\n          csv += exportData.map(this.formatRowAsCsv(this, separator)).join('\\n');\n\n          return csv;\n        },\n\n        /**\n         * @ngdoc function\n         * @name formatRowAsCsv\n         * @methodOf  ui.grid.exporter.service:uiGridExporterService\n         * @description Renders a single field as a csv field, including\n         * quotes around the value\n         * @param {exporterService} exporter pass in exporter\n         * @param {array} row the row to be turned into a csv string\n         * @returns {string} a csv-ified version of the row\n         */\n        formatRowAsCsv: function (exporter, separator) {\n          return function (row) {\n            return row.map(exporter.formatFieldAsCsv).join(separator);\n          };\n        },\n\n        /**\n         * @ngdoc function\n         * @name formatFieldAsCsv\n         * @methodOf  ui.grid.exporter.service:uiGridExporterService\n         * @description Renders a single field as a csv field, including\n         * quotes around the value\n         * @param {field} field the field to be turned into a csv string,\n         * may be of any type\n         * @returns {string} a csv-ified version of the field\n         */\n        formatFieldAsCsv: function (field) {\n          if (field.value == null) { // we want to catch anything null-ish, hence just == not ===\n            return '';\n          }\n          if (typeof(field.value) === 'number') {\n            return field.value;\n          }\n          if (typeof(field.value) === 'boolean') {\n            return (field.value ? 'TRUE' : 'FALSE') ;\n          }\n          if (typeof(field.value) === 'string') {\n            return '\"' + field.value.replace(/\"/g,'\"\"') + '\"';\n          }\n\n          return JSON.stringify(field.value);\n        },\n\n\n        /**\n         * @ngdoc function\n         * @name isIE\n         * @methodOf  ui.grid.exporter.service:uiGridExporterService\n         * @description Checks whether current browser is IE and returns it's version if it is\n        */\n        isIE: function () {\n          var match = navigator.userAgent.match(/(?:MSIE |Trident\\/.*; rv:)(\\d+)/);\n          return match ? parseInt(match[1]) : false;\n        },\n\n\n        /**\n         * @ngdoc function\n         * @name downloadFile\n         * @methodOf  ui.grid.exporter.service:uiGridExporterService\n         * @description Triggers download of a csv file.  Logic provided\n         * by @cssensei (from his colleagues at https://github.com/ifeelgoods) in issue #2391\n         * @param {string} fileName the filename we'd like our file to be\n         * given\n         * @param {string} csvContent the csv content that we'd like to\n         * download as a file\n         * @param {boolean} exporterOlderExcelCompatibility whether or not we put a utf-16 BOM on the from (\\uFEFF)\n         */\n        downloadFile: function (fileName, csvContent, exporterOlderExcelCompatibility) {\n          var D = document;\n          var a = D.createElement('a');\n          var strMimeType = 'application/octet-stream;charset=utf-8';\n          var rawFile;\n          var ieVersion;\n\n          ieVersion = this.isIE();\n          if (ieVersion && ieVersion < 10) {\n            var frame = D.createElement('iframe');\n            document.body.appendChild(frame);\n\n            frame.contentWindow.document.open(\"text/html\", \"replace\");\n            frame.contentWindow.document.write('sep=,\\r\\n' + csvContent);\n            frame.contentWindow.document.close();\n            frame.contentWindow.focus();\n            frame.contentWindow.document.execCommand('SaveAs', true, fileName);\n\n            document.body.removeChild(frame);\n            return true;\n          }\n\n          // IE10+\n          if (navigator.msSaveBlob) {\n            return navigator.msSaveBlob(\n              new Blob(\n                [exporterOlderExcelCompatibility ? \"\\uFEFF\" : '', csvContent],\n                { type: strMimeType } ),\n              fileName\n            );\n          }\n\n          //html5 A[download]\n          if ('download' in a) {\n            var blob = new Blob(\n              [exporterOlderExcelCompatibility ? \"\\uFEFF\" : '', csvContent],\n              { type: strMimeType }\n            );\n            rawFile = URL.createObjectURL(blob);\n            a.setAttribute('download', fileName);\n          } else {\n            rawFile = 'data:' + strMimeType + ',' + encodeURIComponent(csvContent);\n            a.setAttribute('target', '_blank');\n          }\n\n          a.href = rawFile;\n          a.setAttribute('style', 'display:none;');\n          D.body.appendChild(a);\n          setTimeout(function() {\n            if (a.click) {\n              a.click();\n              // Workaround for Safari 5\n            } else if (document.createEvent) {\n              var eventObj = document.createEvent('MouseEvents');\n              eventObj.initEvent('click', true, true);\n              a.dispatchEvent(eventObj);\n            }\n            D.body.removeChild(a);\n\n          }, this.delay);\n        },\n\n        /**\n         * @ngdoc function\n         * @name pdfExport\n         * @methodOf  ui.grid.exporter.service:uiGridExporterService\n         * @description Exports rows from the grid in pdf format,\n         * the data exported is selected based on the provided options.\n         * Note that this function has a dependency on pdfMake, which must\n         * be installed.  The resulting pdf opens in a new\n         * browser window.\n         * @param {Grid} grid the grid from which data should be exported\n         * @param {string} rowTypes which rows to export, valid values are\n         * uiGridExporterConstants.ALL, uiGridExporterConstants.VISIBLE,\n         * uiGridExporterConstants.SELECTED\n         * @param {string} colTypes which columns to export, valid values are\n         * uiGridExporterConstants.ALL, uiGridExporterConstants.VISIBLE,\n         * uiGridExporterConstants.SELECTED\n         */\n        pdfExport: function (grid, rowTypes, colTypes) {\n          var self = this;\n          this.loadAllDataIfNeeded(grid, rowTypes, colTypes).then(function () {\n            var exportColumnHeaders = self.getColumnHeaders(grid, colTypes);\n            var exportData = self.getData(grid, rowTypes, colTypes);\n            var docDefinition = self.prepareAsPdf(grid, exportColumnHeaders, exportData);\n\n            if (self.isIE()) {\n              self.downloadPDF(grid.options.exporterPdfFilename, docDefinition);\n            } else {\n              pdfMake.createPdf(docDefinition).open();\n            }\n          });\n        },\n\n\n        /**\n         * @ngdoc function\n         * @name downloadPdf\n         * @methodOf  ui.grid.exporter.service:uiGridExporterService\n         * @description Generates and retrieves the pdf as a blob, then downloads\n         * it as a file.  Only used in IE, in all other browsers we use the native\n         * pdfMake.open function to just open the PDF\n         * @param {string} fileName the filename to give to the pdf, can be set\n         * through exporterPdfFilename\n         * @param {object} docDefinition a pdf docDefinition that we can generate\n         * and get a blob from\n         */\n        downloadPDF: function (fileName, docDefinition) {\n          var D = document;\n          var a = D.createElement('a');\n          var strMimeType = 'application/octet-stream;charset=utf-8';\n          var rawFile;\n          var ieVersion;\n\n          ieVersion = this.isIE();\n          var doc = pdfMake.createPdf(docDefinition);\n          var blob;\n\n          doc.getBuffer( function (buffer) {\n            blob = new Blob([buffer]);\n\n            if (ieVersion && ieVersion < 10) {\n              var frame = D.createElement('iframe');\n              document.body.appendChild(frame);\n\n              frame.contentWindow.document.open(\"text/html\", \"replace\");\n              frame.contentWindow.document.write(blob);\n              frame.contentWindow.document.close();\n              frame.contentWindow.focus();\n              frame.contentWindow.document.execCommand('SaveAs', true, fileName);\n\n              document.body.removeChild(frame);\n              return true;\n            }\n\n            // IE10+\n            if (navigator.msSaveBlob) {\n              return navigator.msSaveBlob(\n                blob, fileName\n              );\n            }\n          });\n        },\n\n\n        /**\n         * @ngdoc function\n         * @name renderAsPdf\n         * @methodOf  ui.grid.exporter.service:uiGridExporterService\n         * @description Renders the data into a pdf, and opens that pdf.\n         *\n         * @param {Grid} grid the grid from which data should be exported\n         * @param {array} exportColumnHeaders an array of column headers,\n         * where each header is an object with name, width and maybe alignment\n         * @param {array} exportData an array of rows, where each row is\n         * an array of column data\n         * @returns {object} a pdfMake format document definition, ready\n         * for generation\n         */\n        prepareAsPdf: function(grid, exportColumnHeaders, exportData) {\n          var headerWidths = this.calculatePdfHeaderWidths( grid, exportColumnHeaders );\n\n          var headerColumns = exportColumnHeaders.map( function( header ) {\n            return { text: header.displayName, style: 'tableHeader' };\n          });\n\n          var stringData = exportData.map(this.formatRowAsPdf(this));\n\n          var allData = [headerColumns].concat(stringData);\n\n          var docDefinition = {\n            pageOrientation: grid.options.exporterPdfOrientation,\n            pageSize: grid.options.exporterPdfPageSize,\n            content: [{\n              style: 'tableStyle',\n              table: {\n                headerRows: 1,\n                widths: headerWidths,\n                body: allData\n              }\n            }],\n            styles: {\n              tableStyle: grid.options.exporterPdfTableStyle,\n              tableHeader: grid.options.exporterPdfTableHeaderStyle\n            },\n            defaultStyle: grid.options.exporterPdfDefaultStyle\n          };\n\n          if ( grid.options.exporterPdfLayout ){\n            docDefinition.layout = grid.options.exporterPdfLayout;\n          }\n\n          if ( grid.options.exporterPdfHeader ){\n            docDefinition.header = grid.options.exporterPdfHeader;\n          }\n\n          if ( grid.options.exporterPdfFooter ){\n            docDefinition.footer = grid.options.exporterPdfFooter;\n          }\n\n          if ( grid.options.exporterPdfCustomFormatter ){\n            docDefinition = grid.options.exporterPdfCustomFormatter( docDefinition );\n          }\n          return docDefinition;\n\n        },\n\n\n        /**\n         * @ngdoc function\n         * @name calculatePdfHeaderWidths\n         * @methodOf  ui.grid.exporter.service:uiGridExporterService\n         * @description Determines the column widths base on the\n         * widths we got from the grid.  If the column is drawn\n         * then we have a drawnWidth.  If the column is not visible\n         * then we have '*', 'x%' or a width.  When columns are\n         * not visible they don't contribute to the overall gridWidth,\n         * so we need to adjust to allow for extra columns\n         *\n         * Our basic heuristic is to take the current gridWidth, plus\n         * numeric columns and call this the base gridwidth.\n         *\n         * To that we add 100 for any '*' column, and x% of the base gridWidth\n         * for any column that is a %\n         *\n         * @param {Grid} grid the grid from which data should be exported\n         * @param {array} exportHeaders array of header information\n         * @returns {object} an array of header widths\n         */\n        calculatePdfHeaderWidths: function ( grid, exportHeaders ) {\n          var baseGridWidth = 0;\n          exportHeaders.forEach( function(value){\n            if (typeof(value.width) === 'number'){\n              baseGridWidth += value.width;\n            }\n          });\n\n          var extraColumns = 0;\n          exportHeaders.forEach( function(value){\n            if (value.width === '*'){\n              extraColumns += 100;\n            }\n            if (typeof(value.width) === 'string' && value.width.match(/(\\d)*%/)) {\n              var percent = parseInt(value.width.match(/(\\d)*%/)[0]);\n\n              value.width = baseGridWidth * percent / 100;\n              extraColumns += value.width;\n            }\n          });\n\n          var gridWidth = baseGridWidth + extraColumns;\n\n          return exportHeaders.map(function( header ) {\n            return header.width === '*' ? header.width : header.width * grid.options.exporterPdfMaxGridWidth / gridWidth;\n          });\n\n        },\n\n        /**\n         * @ngdoc function\n         * @name formatRowAsPdf\n         * @methodOf  ui.grid.exporter.service:uiGridExporterService\n         * @description Renders a row in a format consumable by PDF,\n         * mainly meaning casting everything to a string\n         * @param {exporterService} exporter pass in exporter\n         * @param {array} row the row to be turned into a csv string\n         * @returns {string} a csv-ified version of the row\n         */\n        formatRowAsPdf: function ( exporter ) {\n          return function( row ) {\n            return row.map(exporter.formatFieldAsPdfString);\n          };\n        },\n\n\n        /**\n         * @ngdoc function\n         * @name formatFieldAsCsv\n         * @methodOf  ui.grid.exporter.service:uiGridExporterService\n         * @description Renders a single field as a pdf-able field, which\n         * is different from a csv field only in that strings don't have quotes\n         * around them\n         * @param {field} field the field to be turned into a pdf string,\n         * may be of any type\n         * @returns {string} a string-ified version of the field\n         */\n        formatFieldAsPdfString: function (field) {\n          var returnVal;\n          if (field.value == null) { // we want to catch anything null-ish, hence just == not ===\n            returnVal = '';\n          } else if (typeof(field.value) === 'number') {\n            returnVal = field.value.toString();\n          } else if (typeof(field.value) === 'boolean') {\n            returnVal = (field.value ? 'TRUE' : 'FALSE') ;\n          } else if (typeof(field.value) === 'string') {\n            returnVal = field.value.replace(/\"/g,'\"\"');\n          } else {\n            returnVal = JSON.stringify(field.value).replace(/^\"/,'').replace(/\"$/,'');\n          }\n\n          if (field.alignment && typeof(field.alignment) === 'string' ){\n            returnVal = { text: returnVal, alignment: field.alignment };\n          }\n\n          return returnVal;\n        }\n      };\n\n      return service;\n\n    }\n  ]);\n\n  /**\n   *  @ngdoc directive\n   *  @name ui.grid.exporter.directive:uiGridExporter\n   *  @element div\n   *  @restrict A\n   *\n   *  @description Adds exporter features to grid\n   *\n   *  @example\n   <example module=\"app\">\n   <file name=\"app.js\">\n   var app = angular.module('app', ['ui.grid', 'ui.grid.exporter']);\n\n   app.controller('MainCtrl', ['$scope', function ($scope) {\n      $scope.data = [\n        { name: 'Bob', title: 'CEO' },\n            { name: 'Frank', title: 'Lowly Developer' }\n      ];\n\n      $scope.gridOptions = {\n        enableGridMenu: true,\n        exporterMenuCsv: false,\n        columnDefs: [\n          {name: 'name', enableCellEdit: true},\n          {name: 'title', enableCellEdit: true}\n        ],\n        data: $scope.data\n      };\n    }]);\n   </file>\n   <file name=\"index.html\">\n   <div ng-controller=\"MainCtrl\">\n   <div ui-grid=\"gridOptions\" ui-grid-exporter></div>\n   </div>\n   </file>\n   </example>\n   */\n  module.directive('uiGridExporter', ['uiGridExporterConstants', 'uiGridExporterService', 'gridUtil', '$compile',\n    function (uiGridExporterConstants, uiGridExporterService, gridUtil, $compile) {\n      return {\n        replace: true,\n        priority: 0,\n        require: '^uiGrid',\n        scope: false,\n        link: function ($scope, $elm, $attrs, uiGridCtrl) {\n          uiGridExporterService.initializeGrid(uiGridCtrl.grid);\n          uiGridCtrl.grid.exporter.$scope = $scope;\n        }\n      };\n    }\n  ]);\n})();\n\n(function () {\n  'use strict';\n\n  /**\n   * @ngdoc overview\n   * @name ui.grid.grouping\n   * @description\n   *\n   * # ui.grid.grouping\n   *\n   * <div class=\"alert alert-warning\" role=\"alert\"><strong>Beta</strong> This feature is ready for testing, but it either hasn't seen a lot of use or has some known bugs.</div>\n   *\n   * This module provides grouping of rows based on the data in them, similar\n   * in concept to excel grouping.  You can group multiple columns, resulting in\n   * nested grouping.\n   *\n   * In concept this feature is similar to sorting + grid footer/aggregation, it\n   * sorts the data based on the grouped columns, then creates group rows that\n   * reflect a break in the data.  Each of those group rows can have aggregations for\n   * the data within that group.\n   *\n   * This feature leverages treeBase to provide the tree functionality itself,\n   * the key thing this feature does therefore is to set treeLevels on the rows\n   * and insert the group headers.\n   *\n   * Design information:\n   * -------------------\n   *\n   * Each column will get new menu items - group by, and aggregate by.  Group by\n   * will cause this column to be sorted (if not already), and will move this column\n   * to the front of the sorted columns (i.e. grouped columns take precedence over\n   * sorted columns).  It will respect the sort order already set if there is one,\n   * and it will allow the sorting logic to change that sort order, it just forces\n   * the column to the front of the sorting.  You can group by multiple columns, the\n   * logic will add this column to the sorting after any already grouped columns.\n   *\n   * Once a grouping is defined, grouping logic is added to the rowsProcessors.  This\n   * will process the rows, identifying a break in the data value, and inserting a grouping row.\n   * Grouping rows have specific attributes on them:\n   *\n   *  - internalRow = true: tells us that this isn't a real row, so we can ignore it\n   *    from any processing that it looking at core data rows.  This is used by the core\n   *    logic (or will be one day), as it's not grouping specific\n   *  - groupHeader = true: tells us this is a groupHeader.  This is used by the grouping logic\n   *    to know if this is a groupHeader row or not\n   *\n   * Since the logic is baked into the rowsProcessors, it should get triggered whenever\n   * row order or filtering or anything like that is changed.  In order to avoid the row instantiation\n   * time, and to preserve state across invocations, we hold a cache of the rows that we created\n   * last time, and we use them again this time if we can.\n   *\n   * By default rows are collapsed, which means all data rows have their visible property\n   * set to false, and only level 0 group rows are set to visible.\n   *\n   * <br/>\n   * <br/>\n   *\n   * <div doc-module-components=\"ui.grid.grouping\"></div>\n   */\n\n  var module = angular.module('ui.grid.grouping', ['ui.grid', 'ui.grid.treeBase']);\n\n  /**\n   *  @ngdoc object\n   *  @name ui.grid.grouping.constant:uiGridGroupingConstants\n   *\n   *  @description constants available in grouping module, this includes\n   *  all the constants declared in the treeBase module (these are manually copied\n   *  as there isn't an easy way to include constants in another constants file, and\n   *  we don't want to make users include treeBase)\n   *\n   */\n  module.constant('uiGridGroupingConstants', {\n    featureName: \"grouping\",\n    rowHeaderColName: 'treeBaseRowHeaderCol',\n    EXPANDED: 'expanded',\n    COLLAPSED: 'collapsed',\n    aggregation: {\n      COUNT: 'count',\n      SUM: 'sum',\n      MAX: 'max',\n      MIN: 'min',\n      AVG: 'avg'\n    }\n  });\n\n  /**\n   *  @ngdoc service\n   *  @name ui.grid.grouping.service:uiGridGroupingService\n   *\n   *  @description Services for grouping features\n   */\n  module.service('uiGridGroupingService', ['$q', 'uiGridGroupingConstants', 'gridUtil', 'rowSorter', 'GridRow', 'gridClassFactory', 'i18nService', 'uiGridConstants', 'uiGridTreeBaseService',\n  function ($q, uiGridGroupingConstants, gridUtil, rowSorter, GridRow, gridClassFactory, i18nService, uiGridConstants, uiGridTreeBaseService) {\n\n    var service = {\n\n      initializeGrid: function (grid, $scope) {\n        uiGridTreeBaseService.initializeGrid( grid, $scope );\n\n        //add feature namespace and any properties to grid for needed\n        /**\n         *  @ngdoc object\n         *  @name ui.grid.grouping.grid:grouping\n         *\n         *  @description Grid properties and functions added for grouping\n         */\n        grid.grouping = {};\n\n        /**\n         *  @ngdoc property\n         *  @propertyOf ui.grid.grouping.grid:grouping\n         *  @name groupHeaderCache\n         *\n         *  @description Cache that holds the group header rows we created last time, we'll\n         *  reuse these next time, not least because they hold our expanded states.\n         *\n         *  We need to take care with these that they don't become a memory leak, we\n         *  create a new cache each time using the values from the old cache.  This works\n         *  so long as we're creating group rows for invisible rows as well.\n         *\n         *  The cache is a nested hash, indexed on the value we grouped by.  So if we\n         *  grouped by gender then age, we'd maybe have something like:\n         *  ```\n         *    {\n         *      male: {\n         *        row: <pointer to the old row>,\n         *        children: {\n         *          22: { row: <pointer to the old row> },\n         *          31: { row: <pointer to the old row> }\n         *      },\n         *      female: {\n         *        row: <pointer to the old row>,\n         *        children: {\n         *          28: { row: <pointer to the old row> },\n         *          55: { row: <pointer to the old row> }\n         *      }\n         *    }\n         *  ```\n         *\n         *  We create new rows for any missing rows, this means that they come in as collapsed.\n         *\n         */\n        grid.grouping.groupHeaderCache = {};\n\n        service.defaultGridOptions(grid.options);\n\n        grid.registerRowsProcessor(service.groupRows, 400);\n\n        grid.registerColumnBuilder( service.groupingColumnBuilder);\n\n        grid.registerColumnsProcessor(service.groupingColumnProcessor, 400);\n\n        /**\n         *  @ngdoc object\n         *  @name ui.grid.grouping.api:PublicApi\n         *\n         *  @description Public Api for grouping feature\n         */\n        var publicApi = {\n          events: {\n            grouping: {\n              /**\n               * @ngdoc event\n               * @eventOf ui.grid.grouping.api:PublicApi\n               * @name aggregationChanged\n               * @description raised whenever aggregation is changed, added or removed from a column\n               *\n               * <pre>\n               *      gridApi.grouping.on.aggregationChanged(scope,function(col){})\n               * </pre>\n               * @param {gridCol} col the column which on which aggregation changed. The aggregation\n               * type is available as `col.treeAggregation.type`\n               */\n              aggregationChanged: {},\n              /**\n               * @ngdoc event\n               * @eventOf ui.grid.grouping.api:PublicApi\n               * @name groupingChanged\n               * @description raised whenever the grouped columns changes\n               *\n               * <pre>\n               *      gridApi.grouping.on.groupingChanged(scope,function(col){})\n               * </pre>\n               * @param {gridCol} col the column which on which grouping changed. The new grouping is\n               * available as `col.grouping`\n               */\n              groupingChanged: {}\n            }\n          },\n          methods: {\n            grouping: {\n              /**\n               * @ngdoc function\n               * @name getGrouping\n               * @methodOf  ui.grid.grouping.api:PublicApi\n               * @description Get the grouping configuration for this grid,\n               * used by the saveState feature.  Adds expandedState to the information\n               * provided by the internal getGrouping, and removes any aggregations that have a source\n               * of grouping (i.e. will be automatically reapplied when we regroup the column)\n               * Returned grouping is an object\n               *   `{ grouping: groupArray, treeAggregations: aggregateArray, expandedState: hash }`\n               * where grouping contains an array of objects:\n               *   `{ field: column.field, colName: column.name, groupPriority: column.grouping.groupPriority }`\n               * and aggregations contains an array of objects:\n               *   `{ field: column.field, colName: column.name, aggregation: column.grouping.aggregation }`\n               * and expandedState is a hash of the currently expanded nodes\n               *\n               * The groupArray will be sorted by groupPriority.\n               *\n               * @param {boolean} getExpanded whether or not to return the expanded state\n               * @returns {object} grouping configuration\n               */\n              getGrouping: function ( getExpanded ) {\n                var grouping = service.getGrouping(grid);\n\n                grouping.grouping.forEach( function( group ) {\n                  group.colName = group.col.name;\n                  delete group.col;\n                });\n\n                grouping.aggregations.forEach( function( aggregation ) {\n                  aggregation.colName = aggregation.col.name;\n                  delete aggregation.col;\n                });\n\n                grouping.aggregations = grouping.aggregations.filter( function( aggregation ){\n                  return !aggregation.aggregation.source || aggregation.aggregation.source !== 'grouping';\n                });\n\n                if ( getExpanded ){\n                  grouping.rowExpandedStates = service.getRowExpandedStates( grid.grouping.groupingHeaderCache );\n                }\n\n                return grouping;\n              },\n\n              /**\n               * @ngdoc function\n               * @name setGrouping\n               * @methodOf  ui.grid.grouping.api:PublicApi\n               * @description Set the grouping configuration for this grid,\n               * used by the saveState feature, but can also be used by any\n               * user to specify a combined grouping and aggregation configuration\n               * @param {object} config the config you want to apply, in the format\n               * provided out by getGrouping\n               */\n              setGrouping: function ( config ) {\n                service.setGrouping(grid, config);\n              },\n\n              /**\n               * @ngdoc function\n               * @name groupColumn\n               * @methodOf  ui.grid.grouping.api:PublicApi\n               * @description Adds this column to the existing grouping, at the end of the priority order.\n               * If the column doesn't have a sort, adds one, by default ASC\n               *\n               * This column will move to the left of any non-group columns, the\n               * move is handled in a columnProcessor, so gets called as part of refresh\n               *\n               * @param {string} columnName the name of the column we want to group\n               */\n              groupColumn: function( columnName ) {\n                var column = grid.getColumn(columnName);\n                service.groupColumn(grid, column);\n              },\n\n              /**\n               * @ngdoc function\n               * @name ungroupColumn\n               * @methodOf  ui.grid.grouping.api:PublicApi\n               * @description Removes the groupPriority from this column.  If the\n               * column was previously aggregated the aggregation will come back.\n               * The sort will remain.\n               *\n               * This column will move to the right of any other group columns, the\n               * move is handled in a columnProcessor, so gets called as part of refresh\n               *\n               * @param {string} columnName the name of the column we want to ungroup\n               */\n              ungroupColumn: function( columnName ) {\n                var column = grid.getColumn(columnName);\n                service.ungroupColumn(grid, column);\n              },\n\n              /**\n               * @ngdoc function\n               * @name clearGrouping\n               * @methodOf  ui.grid.grouping.api:PublicApi\n               * @description Clear any grouped columns and any aggregations.  Doesn't remove sorting,\n               * as we don't know whether that sorting was added by grouping or was there beforehand\n               *\n               */\n              clearGrouping: function() {\n                service.clearGrouping(grid);\n              },\n\n              /**\n               * @ngdoc function\n               * @name aggregateColumn\n               * @methodOf  ui.grid.grouping.api:PublicApi\n               * @description Sets the aggregation type on a column, if the\n               * column is currently grouped then it removes the grouping first.\n               * If the aggregationDef is null then will result in the aggregation\n               * being removed\n               *\n               * @param {string} columnName the column we want to aggregate\n               * @param {string} or {function} aggregationDef one of the recognised types\n               * from uiGridGroupingConstants or a custom aggregation function.\n               * @param {string} aggregationLabel (optional) The label to use for this aggregation.\n               */\n              aggregateColumn: function( columnName, aggregationDef, aggregationLabel){\n                var column = grid.getColumn(columnName);\n                service.aggregateColumn( grid, column, aggregationDef, aggregationLabel);\n              }\n\n            }\n          }\n        };\n\n        grid.api.registerEventsFromObject(publicApi.events);\n\n        grid.api.registerMethodsFromObject(publicApi.methods);\n\n        grid.api.core.on.sortChanged( $scope, service.tidyPriorities);\n\n      },\n\n      defaultGridOptions: function (gridOptions) {\n        //default option to true unless it was explicitly set to false\n        /**\n         *  @ngdoc object\n         *  @name ui.grid.grouping.api:GridOptions\n         *\n         *  @description GridOptions for grouping feature, these are available to be\n         *  set using the ui-grid {@link ui.grid.class:GridOptions gridOptions}\n         */\n\n        /**\n         *  @ngdoc object\n         *  @name enableGrouping\n         *  @propertyOf  ui.grid.grouping.api:GridOptions\n         *  @description Enable row grouping for entire grid.\n         *  <br/>Defaults to true\n         */\n        gridOptions.enableGrouping = gridOptions.enableGrouping !== false;\n\n        /**\n         *  @ngdoc object\n         *  @name groupingShowCounts\n         *  @propertyOf  ui.grid.grouping.api:GridOptions\n         *  @description shows counts on the groupHeader rows. Not that if you are using a cellFilter or a\n         *  sortingAlgorithm which relies on a specific format or data type, showing counts may cause that\n         *  to break, since the group header rows will always be a string with groupingShowCounts enabled.\n         *  <br/>Defaults to true except on columns of type 'date'\n         */\n        gridOptions.groupingShowCounts = gridOptions.groupingShowCounts !== false;\n\n        /**\n         *  @ngdoc object\n         *  @name groupingNullLabel\n         *  @propertyOf  ui.grid.grouping.api:GridOptions\n         *  @description The string to use for the grouping header row label on rows which contain a null or undefined value in the grouped column.\n         *  <br/>Defaults to \"Null\"\n         */\n        gridOptions.groupingNullLabel = typeof(gridOptions.groupingNullLabel) === 'undefined' ? 'Null' : gridOptions.groupingNullLabel;\n\n        /**\n         *  @ngdoc object\n         *  @name enableGroupHeaderSelection\n         *  @propertyOf  ui.grid.grouping.api:GridOptions\n         *  @description Allows group header rows to be selected.\n         *  <br/>Defaults to false\n         */\n        gridOptions.enableGroupHeaderSelection = gridOptions.enableGroupHeaderSelection === true;\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name groupingColumnBuilder\n       * @methodOf  ui.grid.grouping.service:uiGridGroupingService\n       * @description Sets the grouping defaults based on the columnDefs\n       *\n       * @param {object} colDef columnDef we're basing on\n       * @param {GridCol} col the column we're to update\n       * @param {object} gridOptions the options we should use\n       * @returns {promise} promise for the builder - actually we do it all inline so it's immediately resolved\n       */\n      groupingColumnBuilder: function (colDef, col, gridOptions) {\n        /**\n         *  @ngdoc object\n         *  @name ui.grid.grouping.api:ColumnDef\n         *\n         *  @description ColumnDef for grouping feature, these are available to be\n         *  set using the ui-grid {@link ui.grid.class:GridOptions.columnDef gridOptions.columnDefs}\n         */\n\n        /**\n         *  @ngdoc object\n         *  @name enableGrouping\n         *  @propertyOf  ui.grid.grouping.api:ColumnDef\n         *  @description Enable grouping on this column\n         *  <br/>Defaults to true.\n         */\n        if (colDef.enableGrouping === false){\n          return;\n        }\n\n        /**\n         *  @ngdoc object\n         *  @name grouping\n         *  @propertyOf  ui.grid.grouping.api:ColumnDef\n         *  @description Set the grouping for a column.  Format is:\n         *  ```\n         *    {\n         *      groupPriority: <number, starts at 0, if less than 0 or undefined then we're aggregating in this column>\n         *    }\n         *  ```\n         *\n         *  **Note that aggregation used to be included in grouping, but is now separately set on the column via treeAggregation\n         *  setting in treeBase**\n         *\n         *  We group in the priority order given, this will also put these columns to the high order of the sort irrespective\n         *  of the sort priority given them.  If there is no sort defined then we sort ascending, if there is a sort defined then\n         *  we use that sort.\n         *\n         *  If the groupPriority is undefined or less than 0, then we expect to be aggregating, and we look at the\n         *  aggregation types to determine what sort of aggregation we can do.  Values are in the constants file, but\n         *  include SUM, COUNT, MAX, MIN\n         *\n         *  groupPriorities should generally be sequential, if they're not then the next time getGrouping is called\n         *  we'll renumber them to be sequential.\n         *  <br/>Defaults to undefined.\n         */\n\n        if ( typeof(col.grouping) === 'undefined' && typeof(colDef.grouping) !== 'undefined') {\n          col.grouping = angular.copy(colDef.grouping);\n          if ( typeof(col.grouping.groupPriority) !== 'undefined' && col.grouping.groupPriority > -1 ){\n            col.treeAggregationFn = uiGridTreeBaseService.nativeAggregations()[uiGridGroupingConstants.aggregation.COUNT].aggregationFn;\n            col.treeAggregationFinalizerFn = service.groupedFinalizerFn;\n          }\n        } else if (typeof(col.grouping) === 'undefined'){\n          col.grouping = {};\n        }\n\n        if (typeof(col.grouping) !== 'undefined' && typeof(col.grouping.groupPriority) !== 'undefined' && col.grouping.groupPriority >= 0){\n          col.suppressRemoveSort = true;\n        }\n\n        var groupColumn = {\n          name: 'ui.grid.grouping.group',\n          title: i18nService.get().grouping.group,\n          icon: 'ui-grid-icon-indent-right',\n          shown: function () {\n            return typeof(this.context.col.grouping) === 'undefined' ||\n                   typeof(this.context.col.grouping.groupPriority) === 'undefined' ||\n                   this.context.col.grouping.groupPriority < 0;\n          },\n          action: function () {\n            service.groupColumn( this.context.col.grid, this.context.col );\n          }\n        };\n\n        var ungroupColumn = {\n          name: 'ui.grid.grouping.ungroup',\n          title: i18nService.get().grouping.ungroup,\n          icon: 'ui-grid-icon-indent-left',\n          shown: function () {\n            return typeof(this.context.col.grouping) !== 'undefined' &&\n                   typeof(this.context.col.grouping.groupPriority) !== 'undefined' &&\n                   this.context.col.grouping.groupPriority >= 0;\n          },\n          action: function () {\n            service.ungroupColumn( this.context.col.grid, this.context.col );\n          }\n        };\n\n        var aggregateRemove = {\n          name: 'ui.grid.grouping.aggregateRemove',\n          title: i18nService.get().grouping.aggregate_remove,\n          shown: function () {\n            return typeof(this.context.col.treeAggregationFn) !== 'undefined';\n          },\n          action: function () {\n            service.aggregateColumn( this.context.col.grid, this.context.col, null);\n          }\n        };\n\n        // generic adder for the aggregation menus, which follow a pattern\n        var addAggregationMenu = function(type, title){\n          title = title || i18nService.get().grouping['aggregate_' + type] || type;\n          var menuItem = {\n            name: 'ui.grid.grouping.aggregate' + type,\n            title: title,\n            shown: function () {\n              return typeof(this.context.col.treeAggregation) === 'undefined' ||\n                     typeof(this.context.col.treeAggregation.type) === 'undefined' ||\n                     this.context.col.treeAggregation.type !== type;\n            },\n            action: function () {\n              service.aggregateColumn( this.context.col.grid, this.context.col, type);\n            }\n          };\n\n          if (!gridUtil.arrayContainsObjectWithProperty(col.menuItems, 'name', 'ui.grid.grouping.aggregate' + type)) {\n            col.menuItems.push(menuItem);\n          }\n        };\n\n        /**\n         *  @ngdoc object\n         *  @name groupingShowGroupingMenu\n         *  @propertyOf  ui.grid.grouping.api:ColumnDef\n         *  @description Show the grouping (group and ungroup items) menu on this column\n         *  <br/>Defaults to true.\n         */\n        if ( col.colDef.groupingShowGroupingMenu !== false ){\n          if (!gridUtil.arrayContainsObjectWithProperty(col.menuItems, 'name', 'ui.grid.grouping.group')) {\n            col.menuItems.push(groupColumn);\n          }\n\n          if (!gridUtil.arrayContainsObjectWithProperty(col.menuItems, 'name', 'ui.grid.grouping.ungroup')) {\n            col.menuItems.push(ungroupColumn);\n          }\n        }\n\n\n        /**\n         *  @ngdoc object\n         *  @name groupingShowAggregationMenu\n         *  @propertyOf  ui.grid.grouping.api:ColumnDef\n         *  @description Show the aggregation menu on this column\n         *  <br/>Defaults to true.\n         */\n        if ( col.colDef.groupingShowAggregationMenu !== false ){\n          angular.forEach(uiGridTreeBaseService.nativeAggregations(), function(aggregationDef, name){\n            addAggregationMenu(name);\n          });\n          angular.forEach(gridOptions.treeCustomAggregations, function(aggregationDef, name){\n            addAggregationMenu(name, aggregationDef.menuTitle);\n          });\n\n          if (!gridUtil.arrayContainsObjectWithProperty(col.menuItems, 'name', 'ui.grid.grouping.aggregateRemove')) {\n            col.menuItems.push(aggregateRemove);\n          }\n        }\n      },\n\n\n\n\n      /**\n       * @ngdoc function\n       * @name groupingColumnProcessor\n       * @methodOf  ui.grid.grouping.service:uiGridGroupingService\n       * @description Moves the columns around based on which are grouped\n       *\n       * @param {array} columns the columns to consider rendering\n       * @param {array} rows the grid rows, which we don't use but are passed to us\n       * @returns {array} updated columns array\n       */\n      groupingColumnProcessor: function( columns, rows ) {\n        var grid = this;\n\n        columns = service.moveGroupColumns(this, columns, rows);\n        return columns;\n      },\n\n      /**\n       * @ngdoc function\n       * @name groupedFinalizerFn\n       * @methodOf  ui.grid.grouping.service:uiGridGroupingService\n       * @description Used on group columns to display the rendered value and optionally\n       * display the count of rows.\n       *\n       * @param {aggregation} the aggregation entity for a grouped column\n       */\n      groupedFinalizerFn: function( aggregation ){\n        var col = this;\n\n        if ( typeof(aggregation.groupVal) !== 'undefined') {\n          aggregation.rendered = aggregation.groupVal;\n          if ( col.grid.options.groupingShowCounts && col.colDef.type !== 'date' ){\n            aggregation.rendered += (' (' + aggregation.value + ')');\n          }\n        } else {\n          aggregation.rendered = null;\n        }\n      },\n\n      /**\n       * @ngdoc function\n       * @name moveGroupColumns\n       * @methodOf  ui.grid.grouping.service:uiGridGroupingService\n       * @description Moves the column order so that the grouped columns are lined up\n       * to the left (well, unless you're RTL, then it's the right).  By doing this in\n       * the columnsProcessor, we make it transient - when the column is ungrouped it'll\n       * go back to where it was.\n       *\n       * Does nothing if the option `moveGroupColumns` is set to false.\n       *\n       * @param {Grid} grid grid object\n       * @param {array} columns the columns that we should process/move\n       * @param {array} rows the grid rows\n       * @returns {array} updated columns\n       */\n      moveGroupColumns: function( grid, columns, rows ){\n        if ( grid.options.moveGroupColumns === false){\n          return;\n        }\n\n        columns.forEach( function(column, index){\n          // position used to make stable sort in moveGroupColumns\n          column.groupingPosition = index;\n        });\n\n        columns.sort(function(a, b){\n          var a_group, b_group;\n          if (a.isRowHeader){\n            a_group = -1000;\n          }\n          else if ( typeof(a.grouping) === 'undefined' || typeof(a.grouping.groupPriority) === 'undefined' || a.grouping.groupPriority < 0){\n            a_group = null;\n          } else {\n            a_group = a.grouping.groupPriority;\n          }\n\n          if (b.isRowHeader){\n            b_group = -1000;\n          }\n          else if ( typeof(b.grouping) === 'undefined' || typeof(b.grouping.groupPriority) === 'undefined' || b.grouping.groupPriority < 0){\n            b_group = null;\n          } else {\n            b_group = b.grouping.groupPriority;\n          }\n\n          // groups get sorted to the top\n          if ( a_group !== null && b_group === null) { return -1; }\n          if ( b_group !== null && a_group === null) { return 1; }\n          if ( a_group !== null && b_group !== null) {return a_group - b_group; }\n\n          return a.groupingPosition - b.groupingPosition;\n        });\n\n        columns.forEach( function(column, index) {\n          delete column.groupingPosition;\n        });\n\n        return columns;\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name groupColumn\n       * @methodOf  ui.grid.grouping.service:uiGridGroupingService\n       * @description Adds this column to the existing grouping, at the end of the priority order.\n       * If the column doesn't have a sort, adds one, by default ASC\n       *\n       * This column will move to the left of any non-group columns, the\n       * move is handled in a columnProcessor, so gets called as part of refresh\n       *\n       * @param {Grid} grid grid object\n       * @param {GridCol} column the column we want to group\n       */\n      groupColumn: function( grid, column){\n        if ( typeof(column.grouping) === 'undefined' ){\n          column.grouping = {};\n        }\n\n        // set the group priority to the next number in the hierarchy\n        var existingGrouping = service.getGrouping( grid );\n        column.grouping.groupPriority = existingGrouping.grouping.length;\n\n        // add sort if not present\n        if ( !column.sort ){\n          column.sort = { direction: uiGridConstants.ASC };\n        } else if ( typeof(column.sort.direction) === 'undefined' || column.sort.direction === null ){\n          column.sort.direction = uiGridConstants.ASC;\n        }\n\n        column.treeAggregation = { type: uiGridGroupingConstants.aggregation.COUNT, source: 'grouping' };\n        column.treeAggregationFn = uiGridTreeBaseService.nativeAggregations()[uiGridGroupingConstants.aggregation.COUNT].aggregationFn;\n        column.treeAggregationFinalizerFn = service.groupedFinalizerFn;\n\n        grid.api.grouping.raise.groupingChanged(column);\n        // This indirectly calls service.tidyPriorities( grid );\n        grid.api.core.raise.sortChanged(grid, grid.getColumnSorting());\n\n        grid.queueGridRefresh();\n      },\n\n\n       /**\n       * @ngdoc function\n       * @name ungroupColumn\n       * @methodOf  ui.grid.grouping.service:uiGridGroupingService\n       * @description Removes the groupPriority from this column.  If the\n       * column was previously aggregated the aggregation will come back.\n       * The sort will remain.\n       *\n       * This column will move to the right of any other group columns, the\n       * move is handled in a columnProcessor, so gets called as part of refresh\n       *\n       * @param {Grid} grid grid object\n       * @param {GridCol} column the column we want to ungroup\n       */\n      ungroupColumn: function( grid, column){\n        if ( typeof(column.grouping) === 'undefined' ){\n          return;\n        }\n\n        delete column.grouping.groupPriority;\n        delete column.treeAggregation;\n        delete column.customTreeAggregationFinalizer;\n\n        service.tidyPriorities( grid );\n\n        grid.api.grouping.raise.groupingChanged(column);\n\n        grid.queueGridRefresh();\n      },\n\n      /**\n       * @ngdoc function\n       * @name aggregateColumn\n       * @methodOf  ui.grid.grouping.service:uiGridGroupingService\n       * @description Sets the aggregation type on a column, if the\n       * column is currently grouped then it removes the grouping first.\n       *\n       * @param {Grid} grid grid object\n       * @param {GridCol} column the column we want to aggregate\n       * @param {string} one of the recognised types from uiGridGroupingConstants or one of the custom aggregations from gridOptions\n       */\n      aggregateColumn: function( grid, column, aggregationType){\n\n        if (typeof(column.grouping) !== 'undefined' && typeof(column.grouping.groupPriority) !== 'undefined' && column.grouping.groupPriority >= 0){\n          service.ungroupColumn( grid, column );\n        }\n\n        var aggregationDef = {};\n        if ( typeof(grid.options.treeCustomAggregations[aggregationType]) !== 'undefined' ){\n          aggregationDef = grid.options.treeCustomAggregations[aggregationType];\n        } else if ( typeof(uiGridTreeBaseService.nativeAggregations()[aggregationType]) !== 'undefined' ){\n          aggregationDef = uiGridTreeBaseService.nativeAggregations()[aggregationType];\n        }\n\n        column.treeAggregation = { type: aggregationType, label:  i18nService.get().aggregation[aggregationDef.label] || aggregationDef.label };\n        column.treeAggregationFn = aggregationDef.aggregationFn;\n        column.treeAggregationFinalizerFn = aggregationDef.finalizerFn;\n\n        grid.api.grouping.raise.aggregationChanged(column);\n\n        grid.queueGridRefresh();\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name setGrouping\n       * @methodOf  ui.grid.grouping.service:uiGridGroupingService\n       * @description Set the grouping based on a config object, used by the save state feature\n       * (more specifically, by the restore function in that feature )\n       *\n       * @param {Grid} grid grid object\n       * @param {object} config the config we want to set, same format as that returned by getGrouping\n       */\n      setGrouping: function ( grid, config ){\n        if ( typeof(config) === 'undefined' ){\n          return;\n        }\n\n        // first remove any existing grouping\n        service.clearGrouping(grid);\n\n        if ( config.grouping && config.grouping.length && config.grouping.length > 0 ){\n          config.grouping.forEach( function( group ) {\n            var col = grid.getColumn(group.colName);\n\n            if ( col ) {\n              service.groupColumn( grid, col );\n            }\n          });\n        }\n\n        if ( config.aggregations && config.aggregations.length ){\n          config.aggregations.forEach( function( aggregation ) {\n            var col = grid.getColumn(aggregation.colName);\n\n            if ( col ) {\n              service.aggregateColumn( grid, col, aggregation.aggregation.type );\n            }\n          });\n        }\n\n        if ( config.rowExpandedStates ){\n          service.applyRowExpandedStates( grid.grouping.groupingHeaderCache, config.rowExpandedStates );\n        }\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name clearGrouping\n       * @methodOf  ui.grid.grouping.service:uiGridGroupingService\n       * @description Clear any grouped columns and any aggregations.  Doesn't remove sorting,\n       * as we don't know whether that sorting was added by grouping or was there beforehand\n       *\n       * @param {Grid} grid grid object\n       */\n      clearGrouping: function( grid ) {\n        var currentGrouping = service.getGrouping(grid);\n\n        if ( currentGrouping.grouping.length > 0 ){\n          currentGrouping.grouping.forEach( function( group ) {\n            if (!group.col){\n              // should have a group.colName if there's no col\n              group.col = grid.getColumn(group.colName);\n            }\n            service.ungroupColumn(grid, group.col);\n          });\n        }\n\n        if ( currentGrouping.aggregations.length > 0 ){\n          currentGrouping.aggregations.forEach( function( aggregation ){\n            if (!aggregation.col){\n              // should have a group.colName if there's no col\n              aggregation.col = grid.getColumn(aggregation.colName);\n            }\n            service.aggregateColumn(grid, aggregation.col, null);\n          });\n        }\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name tidyPriorities\n       * @methodOf  ui.grid.grouping.service:uiGridGroupingService\n       * @description Renumbers groupPriority and sortPriority such that\n       * groupPriority is contiguous, and sortPriority either matches\n       * groupPriority (for group columns), and otherwise is contiguous and\n       * higher than groupPriority.\n       *\n       * @param {Grid} grid grid object\n       */\n      tidyPriorities: function( grid ){\n        // if we're called from sortChanged, grid is in this, not passed as param, the param can be a column or undefined\n        if ( ( typeof(grid) === 'undefined' || typeof(grid.grid) !== 'undefined' ) && typeof(this.grid) !== 'undefined' ) {\n          grid = this.grid;\n        }\n\n        var groupArray = [];\n        var sortArray = [];\n\n        grid.columns.forEach( function(column, index){\n          if ( typeof(column.grouping) !== 'undefined' && typeof(column.grouping.groupPriority) !== 'undefined' && column.grouping.groupPriority >= 0){\n            groupArray.push(column);\n          } else if ( typeof(column.sort) !== 'undefined' && typeof(column.sort.priority) !== 'undefined' && column.sort.priority >= 0){\n            sortArray.push(column);\n          }\n        });\n\n        groupArray.sort(function(a, b){ return a.grouping.groupPriority - b.grouping.groupPriority; });\n        groupArray.forEach( function(column, index){\n          column.grouping.groupPriority = index;\n          column.suppressRemoveSort = true;\n          if ( typeof(column.sort) === 'undefined'){\n            column.sort = {};\n          }\n          column.sort.priority = index;\n        });\n\n        var i = groupArray.length;\n        sortArray.sort(function(a, b){ return a.sort.priority - b.sort.priority; });\n        sortArray.forEach( function(column, index){\n          column.sort.priority = i;\n          column.suppressRemoveSort = column.colDef.suppressRemoveSort;\n          i++;\n        });\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name groupRows\n       * @methodOf  ui.grid.grouping.service:uiGridGroupingService\n       * @description The rowProcessor that creates the groupHeaders (i.e. does\n       * the actual grouping).\n       *\n       * Assumes it is always called after the sorting processor, guaranteed by the priority setting\n       *\n       * Processes all the rows in order, inserting a groupHeader row whenever there is a change\n       * in value of a grouped row, based on the sortAlgorithm used for the column.  The group header row\n       * is looked up in the groupHeaderCache, and used from there if there is one. The entity is reset\n       * to {} if one is found.\n       *\n       * As it processes it maintains a `processingState` array. This records, for each level of grouping we're\n       * working with, the following information:\n       * ```\n       *   {\n       *     fieldName: name,\n       *     col: col,\n       *     initialised: boolean,\n       *     currentValue: value,\n       *     currentRow: gridRow,\n       *   }\n       * ```\n       * We look for changes in the currentValue at any of the levels.  Where we find a change we:\n       *\n       * - create a new groupHeader row in the array\n       *\n       * @param {array} renderableRows the rows we want to process, usually the output from the previous rowProcessor\n       * @returns {array} the updated rows, including our new group rows\n       */\n      groupRows: function( renderableRows ) {\n        if (renderableRows.length === 0){\n          return renderableRows;\n        }\n\n        var grid = this;\n        grid.grouping.oldGroupingHeaderCache = grid.grouping.groupingHeaderCache || {};\n        grid.grouping.groupingHeaderCache = {};\n\n        var processingState = service.initialiseProcessingState( grid );\n\n        // processes each of the fields we are grouping by, checks if the value has changed and inserts a groupHeader\n        // Broken out as shouldn't create functions in a loop.\n        var updateProcessingState = function( groupFieldState, stateIndex ) {\n          var fieldValue = grid.getCellValue(row, groupFieldState.col);\n\n          // look for change of value - and insert a header\n          if ( !groupFieldState.initialised || rowSorter.getSortFn(grid, groupFieldState.col, renderableRows)(fieldValue, groupFieldState.currentValue) !== 0 ){\n            service.insertGroupHeader( grid, renderableRows, i, processingState, stateIndex );\n            i++;\n          }\n        };\n\n        // use a for loop because it's tolerant of the array length changing whilst we go - we can\n        // manipulate the iterator when we insert groupHeader rows\n        for (var i = 0; i < renderableRows.length; i++ ){\n          var row = renderableRows[i];\n\n          if ( row.visible ){\n            processingState.forEach( updateProcessingState );\n          }\n        }\n\n        delete grid.grouping.oldGroupingHeaderCache;\n        return renderableRows;\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name initialiseProcessingState\n       * @methodOf  ui.grid.grouping.service:uiGridGroupingService\n       * @description Creates the processing state array that is used\n       * for groupRows.\n       *\n       * @param {Grid} grid grid object\n       * @returns {array} an array in the format described in the groupRows method,\n       * initialised with blank values\n       */\n      initialiseProcessingState: function( grid ){\n        var processingState = [];\n        var columnSettings = service.getGrouping( grid );\n\n        columnSettings.grouping.forEach( function( groupItem, index){\n          processingState.push({\n            fieldName: groupItem.field,\n            col: groupItem.col,\n            initialised: false,\n            currentValue: null,\n            currentRow: null\n          });\n        });\n\n        return processingState;\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name getGrouping\n       * @methodOf  ui.grid.grouping.service:uiGridGroupingService\n       * @description Get the grouping settings from the columns.  As a side effect\n       * this always renumbers the grouping starting at 0\n       * @param {Grid} grid grid object\n       * @returns {array} an array of the group fields, in order of priority\n       */\n      getGrouping: function( grid ){\n        var groupArray = [];\n        var aggregateArray = [];\n\n        // get all the grouping\n        grid.columns.forEach( function(column, columnIndex){\n          if ( column.grouping ){\n            if ( typeof(column.grouping.groupPriority) !== 'undefined' && column.grouping.groupPriority >= 0){\n              groupArray.push({ field: column.field, col: column, groupPriority: column.grouping.groupPriority, grouping: column.grouping });\n            }\n          }\n          if ( column.treeAggregation && column.treeAggregation.type ){\n            aggregateArray.push({ field: column.field, col: column, aggregation: column.treeAggregation });\n          }\n        });\n\n        // sort grouping into priority order\n        groupArray.sort( function(a, b){\n          return a.groupPriority - b.groupPriority;\n        });\n\n        // renumber the priority in case it was somewhat messed up, then remove the grouping reference\n        groupArray.forEach( function( group, index) {\n          group.grouping.groupPriority = index;\n          group.groupPriority = index;\n          delete group.grouping;\n        });\n\n        return { grouping: groupArray, aggregations: aggregateArray };\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name insertGroupHeader\n       * @methodOf  ui.grid.grouping.service:uiGridGroupingService\n       * @description Create a group header row, and link it to the various configuration\n       * items that we use.\n       *\n       * Look for the row in the oldGroupingHeaderCache, write the row into the new groupingHeaderCache.\n       *\n       * @param {Grid} grid grid object\n       * @param {array} renderableRows the rows that we are processing\n       * @param {number} rowIndex the row we were up to processing\n       * @param {array} processingState the current processing state\n       * @param {number} stateIndex the processing state item that we were on when we triggered a new group header -\n       * i.e. the column that we want to create a header for\n       */\n      insertGroupHeader: function( grid, renderableRows, rowIndex, processingState, stateIndex ) {\n        // set the value that caused the end of a group into the header row and the processing state\n        var fieldName = processingState[stateIndex].fieldName;\n        var col = processingState[stateIndex].col;\n\n        var newValue = grid.getCellValue(renderableRows[rowIndex], col);\n        var newDisplayValue = newValue;\n        if ( typeof(newValue) === 'undefined' || newValue === null ) {\n          newDisplayValue = grid.options.groupingNullLabel;\n        }\n\n        var cacheItem = grid.grouping.oldGroupingHeaderCache;\n        for ( var i = 0; i < stateIndex; i++ ){\n          if ( cacheItem && cacheItem[processingState[i].currentValue] ){\n            cacheItem = cacheItem[processingState[i].currentValue].children;\n          }\n        }\n\n        var headerRow;\n        if ( cacheItem && cacheItem[newValue]){\n          headerRow = cacheItem[newValue].row;\n          headerRow.entity = {};\n        } else {\n          headerRow = new GridRow( {}, null, grid );\n          gridClassFactory.rowTemplateAssigner.call(grid, headerRow);\n        }\n\n        headerRow.entity['$$' + processingState[stateIndex].col.uid] = { groupVal: newDisplayValue };\n        headerRow.treeLevel = stateIndex;\n        headerRow.groupHeader = true;\n        headerRow.internalRow = true;\n        headerRow.enableCellEdit = false;\n        headerRow.enableSelection = grid.options.enableGroupHeaderSelection;\n        processingState[stateIndex].initialised = true;\n        processingState[stateIndex].currentValue = newValue;\n        processingState[stateIndex].currentRow = headerRow;\n\n        // set all processing states below this one to not be initialised - change of this state\n        // means all those need to start again\n        service.finaliseProcessingState( processingState, stateIndex + 1);\n\n        // insert our new header row\n        renderableRows.splice(rowIndex, 0, headerRow);\n\n        // add our new header row to the cache\n        cacheItem = grid.grouping.groupingHeaderCache;\n        for ( i = 0; i < stateIndex; i++ ){\n          cacheItem = cacheItem[processingState[i].currentValue].children;\n        }\n        cacheItem[newValue] = { row: headerRow, children: {} };\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name finaliseProcessingState\n       * @methodOf  ui.grid.grouping.service:uiGridGroupingService\n       * @description Set all processing states lower than the one that had a break in value to\n       * no longer be initialised.  Render the counts into the entity ready for display.\n       *\n       * @param {Grid} grid grid object\n       * @param {array} processingState the current processing state\n       * @param {number} stateIndex the processing state item that we were on when we triggered a new group header, all\n       * processing states after this need to be finalised\n       */\n      finaliseProcessingState: function( processingState, stateIndex ){\n        for ( var i = stateIndex; i < processingState.length; i++){\n          processingState[i].initialised = false;\n          processingState[i].currentRow = null;\n          processingState[i].currentValue = null;\n        }\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name getRowExpandedStates\n       * @methodOf  ui.grid.grouping.service:uiGridGroupingService\n       * @description Extract the groupHeaderCache hash, pulling out only the states.\n       *\n       * The example below shows a grid that is grouped by gender then age\n       *\n       * <pre>\n       *   {\n       *     male: {\n       *       state: 'expanded',\n       *       children: {\n       *         22: { state: 'expanded' },\n       *         30: { state: 'collapsed' }\n       *       }\n       *     },\n       *     female: {\n       *       state: 'expanded',\n       *       children: {\n       *         28: { state: 'expanded' },\n       *         55: { state: 'collapsed' }\n       *       }\n       *     }\n       *   }\n       * </pre>\n       *\n       * @param {Grid} grid grid object\n       * @returns {hash} the expanded states as a hash\n       */\n      getRowExpandedStates: function(treeChildren){\n        if ( typeof(treeChildren) === 'undefined' ){\n          return {};\n        }\n\n        var newChildren = {};\n\n        angular.forEach( treeChildren, function( value, key ){\n          newChildren[key] = { state: value.row.treeNode.state };\n          if ( value.children ){\n            newChildren[key].children = service.getRowExpandedStates( value.children );\n          } else {\n            newChildren[key].children = {};\n          }\n        });\n\n        return newChildren;\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name applyRowExpandedStates\n       * @methodOf  ui.grid.grouping.service:uiGridGroupingService\n       * @description Take a hash in the format as created by getRowExpandedStates,\n       * and apply it to the grid.grouping.groupHeaderCache.\n       *\n       * Takes a treeSubset, and applies to a treeSubset - so can be called\n       * recursively.\n       *\n       * @param {object} currentNode can be grid.grouping.groupHeaderCache, or any of\n       * the children of that hash\n       * @returns {hash} expandedStates can be the full expanded states, or children\n       * of that expanded states (which hopefully matches the subset of the groupHeaderCache)\n       */\n      applyRowExpandedStates: function( currentNode, expandedStates ){\n        if ( typeof(expandedStates) === 'undefined' ){\n          return;\n        }\n\n        angular.forEach(expandedStates, function( value, key ) {\n          if ( currentNode[key] ){\n            currentNode[key].row.treeNode.state = value.state;\n\n            if (value.children && currentNode[key].children){\n              service.applyRowExpandedStates( currentNode[key].children, value.children );\n            }\n          }\n        });\n      }\n\n\n    };\n\n    return service;\n\n  }]);\n\n\n  /**\n   *  @ngdoc directive\n   *  @name ui.grid.grouping.directive:uiGridGrouping\n   *  @element div\n   *  @restrict A\n   *\n   *  @description Adds grouping features to grid\n   *\n   *  @example\n   <example module=\"app\">\n   <file name=\"app.js\">\n   var app = angular.module('app', ['ui.grid', 'ui.grid.grouping']);\n\n   app.controller('MainCtrl', ['$scope', function ($scope) {\n      $scope.data = [\n        { name: 'Bob', title: 'CEO' },\n            { name: 'Frank', title: 'Lowly Developer' }\n      ];\n\n      $scope.columnDefs = [\n        {name: 'name', enableCellEdit: true},\n        {name: 'title', enableCellEdit: true}\n      ];\n\n      $scope.gridOptions = { columnDefs: $scope.columnDefs, data: $scope.data };\n    }]);\n   </file>\n   <file name=\"index.html\">\n   <div ng-controller=\"MainCtrl\">\n   <div ui-grid=\"gridOptions\" ui-grid-grouping></div>\n   </div>\n   </file>\n   </example>\n   */\n  module.directive('uiGridGrouping', ['uiGridGroupingConstants', 'uiGridGroupingService', '$templateCache',\n  function (uiGridGroupingConstants, uiGridGroupingService, $templateCache) {\n    return {\n      replace: true,\n      priority: 0,\n      require: '^uiGrid',\n      scope: false,\n      compile: function () {\n        return {\n          pre: function ($scope, $elm, $attrs, uiGridCtrl) {\n            if (uiGridCtrl.grid.options.enableGrouping !== false){\n              uiGridGroupingService.initializeGrid(uiGridCtrl.grid, $scope);\n            }\n          },\n          post: function ($scope, $elm, $attrs, uiGridCtrl) {\n          }\n        };\n      }\n    };\n  }]);\n\n})();\n\n(function () {\n  'use strict';\n\n  /**\n   * @ngdoc overview\n   * @name ui.grid.importer\n   * @description\n   *\n   * # ui.grid.importer\n   *\n   * <div class=\"alert alert-success\" role=\"alert\"><strong>Stable</strong> This feature is stable. There should no longer be breaking api changes without a deprecation warning.</div>\n   *\n   * This module provides the ability to import data into the grid. It\n   * uses the column defs to work out which data belongs in which column,\n   * and creates entities from a configured class (typically a $resource).\n   *\n   * If the rowEdit feature is enabled, it also calls save on those newly\n   * created objects, and then displays any errors in the imported data.\n   *\n   * Currently the importer imports only CSV and json files, although provision has been\n   * made to process other file formats, and these can be added over time.\n   *\n   * For json files, the properties within each object in the json must match the column names\n   * (to put it another way, the importer doesn't process the json, it just copies the objects\n   * within the json into a new instance of the specified object type)\n   *\n   * For CSV import, the default column identification relies on each column in the\n   * header row matching a column.name or column.displayName. Optionally, a column identification\n   * callback can be used.  This allows matching using other attributes, which is particularly\n   * useful if your application has internationalised column headings (i.e. the headings that\n   * the user sees don't match the column names).\n   *\n   * The importer makes use of the grid menu as the UI for requesting an\n   * import.\n   *\n   * <div ui-grid-importer></div>\n   */\n\n  var module = angular.module('ui.grid.importer', ['ui.grid']);\n\n  /**\n   *  @ngdoc object\n   *  @name ui.grid.importer.constant:uiGridImporterConstants\n   *\n   *  @description constants available in importer module\n   */\n\n  module.constant('uiGridImporterConstants', {\n    featureName: 'importer'\n  });\n\n  /**\n   *  @ngdoc service\n   *  @name ui.grid.importer.service:uiGridImporterService\n   *\n   *  @description Services for importer feature\n   */\n  module.service('uiGridImporterService', ['$q', 'uiGridConstants', 'uiGridImporterConstants', 'gridUtil', '$compile', '$interval', 'i18nService', '$window',\n    function ($q, uiGridConstants, uiGridImporterConstants, gridUtil, $compile, $interval, i18nService, $window) {\n\n      var service = {\n\n        initializeGrid: function ($scope, grid) {\n\n          //add feature namespace and any properties to grid for needed state\n          grid.importer = {\n            $scope: $scope\n          };\n\n          this.defaultGridOptions(grid.options);\n\n          /**\n           *  @ngdoc object\n           *  @name ui.grid.importer.api:PublicApi\n           *\n           *  @description Public Api for importer feature\n           */\n          var publicApi = {\n            events: {\n              importer: {\n              }\n            },\n            methods: {\n              importer: {\n                /**\n                 * @ngdoc function\n                 * @name importFile\n                 * @methodOf  ui.grid.importer.api:PublicApi\n                 * @description Imports a file into the grid using the file object\n                 * provided.  Bypasses the grid menu\n                 * @param {File} fileObject the file we want to import, as a javascript\n                 * File object\n                 */\n                importFile: function ( fileObject ) {\n                  service.importThisFile( grid, fileObject );\n                }\n              }\n            }\n          };\n\n          grid.api.registerEventsFromObject(publicApi.events);\n\n          grid.api.registerMethodsFromObject(publicApi.methods);\n\n          if ( grid.options.enableImporter && grid.options.importerShowMenu ){\n            if ( grid.api.core.addToGridMenu ){\n              service.addToMenu( grid );\n            } else {\n              // order of registration is not guaranteed, register in a little while\n              $interval( function() {\n                if (grid.api.core.addToGridMenu){\n                  service.addToMenu( grid );\n                }\n              }, 100, 1);\n            }\n          }\n        },\n\n\n        defaultGridOptions: function (gridOptions) {\n          //default option to true unless it was explicitly set to false\n          /**\n           * @ngdoc object\n           * @name ui.grid.importer.api:GridOptions\n           *\n           * @description GridOptions for importer feature, these are available to be\n           * set using the ui-grid {@link ui.grid.class:GridOptions gridOptions}\n           */\n\n          /**\n           * @ngdoc property\n           * @propertyOf ui.grid.importer.api:GridOptions\n           * @name enableImporter\n           * @description Whether or not importer is enabled.  Automatically set\n           * to false if the user's browser does not support the required fileApi.\n           * Otherwise defaults to true.\n           *\n           */\n          if (gridOptions.enableImporter  || gridOptions.enableImporter === undefined) {\n            if ( !($window.hasOwnProperty('File') && $window.hasOwnProperty('FileReader') && $window.hasOwnProperty('FileList') && $window.hasOwnProperty('Blob')) ) {\n              gridUtil.logError('The File APIs are not fully supported in this browser, grid importer cannot be used.');\n              gridOptions.enableImporter = false;\n            } else {\n              gridOptions.enableImporter = true;\n            }\n          } else {\n            gridOptions.enableImporter = false;\n          }\n\n          /**\n           * @ngdoc method\n           * @name importerProcessHeaders\n           * @methodOf ui.grid.importer.api:GridOptions\n           * @description A callback function that will process headers using custom\n           * logic.  Set this callback function if the headers that your user will provide in their\n           * import file don't necessarily match the grid header or field names.  This might commonly\n           * occur where your application is internationalised, and therefore the field names\n           * that the user recognises are in a different language than the field names that\n           * ui-grid knows about.\n           *\n           * Defaults to the internal `processHeaders` method, which seeks to match using both\n           * displayName and column.name.  Any non-matching columns are discarded.\n           *\n           * Your callback routine should respond by processing the header array, and returning an array\n           * of matching column names.  A null value in any given position means \"don't import this column\"\n           *\n           * <pre>\n           *      gridOptions.importerProcessHeaders: function( headerArray ) {\n           *        var myHeaderColumns = [];\n           *        var thisCol;\n           *        headerArray.forEach( function( value, index ) {\n           *          thisCol = mySpecialLookupFunction( value );\n           *          myHeaderColumns.push( thisCol.name );\n           *        });\n           *\n           *        return myHeaderCols;\n           *      })\n           * </pre>\n           * @param {Grid} grid the grid we're importing into\n           * @param {array} headerArray an array of the text from the first row of the csv file,\n           * which you need to match to column.names\n           * @returns {array} array of matching column names, in the same order as the headerArray\n           *\n           */\n          gridOptions.importerProcessHeaders = gridOptions.importerProcessHeaders || service.processHeaders;\n\n          /**\n           * @ngdoc method\n           * @name importerHeaderFilter\n           * @methodOf ui.grid.importer.api:GridOptions\n           * @description A callback function that will filter (usually translate) a single\n           * header.  Used when you want to match the passed in column names to the column\n           * displayName after the header filter.\n           *\n           * Your callback routine needs to return the filtered header value.\n           * <pre>\n           *      gridOptions.importerHeaderFilter: function( displayName ) {\n           *        return $translate.instant( displayName );\n           *      })\n           * </pre>\n           *\n           * or:\n           * <pre>\n           *      gridOptions.importerHeaderFilter: $translate.instant\n           * </pre>\n           * @param {string} displayName the displayName that we'd like to translate\n           * @returns {string} the translated name\n           *\n           */\n          gridOptions.importerHeaderFilter = gridOptions.importerHeaderFilter || function( displayName ) { return displayName; };\n\n          /**\n           * @ngdoc method\n           * @name importerErrorCallback\n           * @methodOf ui.grid.importer.api:GridOptions\n           * @description A callback function that provides custom error handling, rather\n           * than the standard grid behaviour of an alert box and a console message.  You\n           * might use this to internationalise the console log messages, or to write to a\n           * custom logging routine that returned errors to the server.\n           *\n           * <pre>\n           *      gridOptions.importerErrorCallback: function( grid, errorKey, consoleMessage, context ) {\n           *        myUserDisplayRoutine( errorKey );\n           *        myLoggingRoutine( consoleMessage, context );\n           *      })\n           * </pre>\n           * @param {Grid} grid the grid we're importing into, may be useful if you're positioning messages\n           * in some way\n           * @param {string} errorKey one of the i18n keys the importer can return - importer.noHeaders,\n           * importer.noObjects, importer.invalidCsv, importer.invalidJson, importer.jsonNotArray\n           * @param {string} consoleMessage the English console message that importer would have written\n           * @param {object} context the context data that importer would have appended to that console message,\n           * often the file content itself or the element that is in error\n           *\n           */\n          if ( !gridOptions.importerErrorCallback ||  typeof(gridOptions.importerErrorCallback) !== 'function' ){\n            delete gridOptions.importerErrorCallback;\n          }\n\n          /**\n           * @ngdoc method\n           * @name importerDataAddCallback\n           * @methodOf ui.grid.importer.api:GridOptions\n           * @description A mandatory callback function that adds data to the source data array.  The grid\n           * generally doesn't add rows to the source data array, it is tidier to handle this through a user\n           * callback.\n           *\n           * <pre>\n           *      gridOptions.importerDataAddCallback: function( grid, newObjects ) {\n           *        $scope.myData = $scope.myData.concat( newObjects );\n           *      })\n           * </pre>\n           * @param {Grid} grid the grid we're importing into, may be useful in some way\n           * @param {array} newObjects an array of new objects that you should add to your data\n           *\n           */\n          if ( gridOptions.enableImporter === true && !gridOptions.importerDataAddCallback ) {\n            gridUtil.logError(\"You have not set an importerDataAddCallback, importer is disabled\");\n            gridOptions.enableImporter = false;\n          }\n\n          /**\n           * @ngdoc object\n           * @name importerNewObject\n           * @propertyOf  ui.grid.importer.api:GridOptions\n           * @description An object on which we call `new` to create each new row before inserting it into\n           * the data array.  Typically this would be a $resource entity, which means that if you're using\n           * the rowEdit feature, you can directly call save on this entity when the save event is triggered.\n           *\n           * Defaults to a vanilla javascript object\n           *\n           * @example\n           * <pre>\n           *   gridOptions.importerNewObject = MyRes;\n           * </pre>\n           *\n           */\n\n          /**\n           * @ngdoc property\n           * @propertyOf ui.grid.importer.api:GridOptions\n           * @name importerShowMenu\n           * @description Whether or not to show an item in the grid menu.  Defaults to true.\n           *\n           */\n          gridOptions.importerShowMenu = gridOptions.importerShowMenu !== false;\n\n          /**\n           * @ngdoc method\n           * @methodOf ui.grid.importer.api:GridOptions\n           * @name importerObjectCallback\n           * @description A callback that massages the data for each object.  For example,\n           * you might have data stored as a code value, but display the decode.  This callback\n           * can be used to change the decoded value back into a code.  Defaults to doing nothing.\n           * @param {Grid} grid in case you need it\n           * @param {object} newObject the new object as importer has created it, modify it\n           * then return the modified version\n           * @returns {object} the modified object\n           * @example\n           * <pre>\n           *   gridOptions.importerObjectCallback = function ( grid, newObject ) {\n           *     switch newObject.status {\n           *       case 'Active':\n           *         newObject.status = 1;\n           *         break;\n           *       case 'Inactive':\n           *         newObject.status = 2;\n           *         break;\n           *     }\n           *     return newObject;\n           *   };\n           * </pre>\n           */\n          gridOptions.importerObjectCallback = gridOptions.importerObjectCallback || function( grid, newObject ) { return newObject; };\n        },\n\n\n        /**\n         * @ngdoc function\n         * @name addToMenu\n         * @methodOf  ui.grid.importer.service:uiGridImporterService\n         * @description Adds import menu item to the grid menu,\n         * allowing the user to request import of a file\n         * @param {Grid} grid the grid into which data should be imported\n         */\n        addToMenu: function ( grid ) {\n          grid.api.core.addToGridMenu( grid, [\n            {\n              title: i18nService.getSafeText('gridMenu.importerTitle'),\n              order: 150\n            },\n            {\n              templateUrl: 'ui-grid/importerMenuItemContainer',\n              action: function ($event) {\n                this.grid.api.importer.importAFile( grid );\n              },\n              order: 151\n            }\n          ]);\n        },\n\n\n        /**\n         * @ngdoc function\n         * @name importThisFile\n         * @methodOf ui.grid.importer.service:uiGridImporterService\n         * @description Imports the provided file into the grid using the file object\n         * provided.  Bypasses the grid menu\n         * @param {Grid} grid the grid we're importing into\n         * @param {File} fileObject the file we want to import, as returned from the File\n         * javascript object\n         */\n        importThisFile: function ( grid, fileObject ) {\n          if (!fileObject){\n            gridUtil.logError( 'No file object provided to importThisFile, should be impossible, aborting');\n            return;\n          }\n\n          var reader = new FileReader();\n\n          switch ( fileObject.type ){\n            case 'application/json':\n              reader.onload = service.importJsonClosure( grid );\n              break;\n            default:\n              reader.onload = service.importCsvClosure( grid );\n              break;\n          }\n\n          reader.readAsText( fileObject );\n        },\n\n\n        /**\n         * @ngdoc function\n         * @name importJson\n         * @methodOf ui.grid.importer.service:uiGridImporterService\n         * @description Creates a function that imports a json file into the grid.\n         * The json data is imported into new objects of type `gridOptions.importerNewObject`,\n         * and if the rowEdit feature is enabled the rows are marked as dirty\n         * @param {Grid} grid the grid we want to import into\n         * @param {FileObject} importFile the file that we want to import, as\n         * a FileObject\n         */\n        importJsonClosure: function( grid ) {\n          return function( importFile ){\n            var newObjects = [];\n            var newObject;\n\n            var importArray = service.parseJson( grid, importFile );\n            if (importArray === null){\n              return;\n            }\n            importArray.forEach(  function( value, index ) {\n              newObject = service.newObject( grid );\n              angular.extend( newObject, value );\n              newObject = grid.options.importerObjectCallback( grid, newObject );\n              newObjects.push( newObject );\n            });\n\n            service.addObjects( grid, newObjects );\n\n          };\n        },\n\n\n        /**\n         * @ngdoc function\n         * @name parseJson\n         * @methodOf ui.grid.importer.service:uiGridImporterService\n         * @description Parses a json file, returns the parsed data.\n         * Displays an error if file doesn't parse\n         * @param {Grid} grid the grid that we want to import into\n         * @param {FileObject} importFile the file that we want to import, as\n         * a FileObject\n         * @returns {array} array of objects from the imported json\n         */\n        parseJson: function( grid, importFile ){\n          var loadedObjects;\n          try {\n            loadedObjects = JSON.parse( importFile.target.result );\n          } catch (e) {\n            service.alertError( grid, 'importer.invalidJson', 'File could not be processed, is it valid json? Content was: ', importFile.target.result );\n            return;\n          }\n\n          if ( !Array.isArray( loadedObjects ) ){\n            service.alertError( grid, 'importer.jsonNotarray', 'Import failed, file is not an array, file was: ', importFile.target.result );\n            return [];\n          } else {\n            return loadedObjects;\n          }\n        },\n\n\n\n        /**\n         * @ngdoc function\n         * @name importCsvClosure\n         * @methodOf ui.grid.importer.service:uiGridImporterService\n         * @description Creates a function that imports a csv file into the grid\n         * (allowing it to be used in the reader.onload event)\n         * @param {Grid} grid the grid that we want to import into\n         * @param {FileObject} importFile the file that we want to import, as\n         * a file object\n         */\n        importCsvClosure: function( grid ) {\n          return function( importFile ){\n            var importArray = service.parseCsv( importFile );\n            if ( !importArray || importArray.length < 1 ){\n              service.alertError( grid, 'importer.invalidCsv', 'File could not be processed, is it valid csv? Content was: ', importFile.target.result );\n              return;\n            }\n\n            var newObjects = service.createCsvObjects( grid, importArray );\n            if ( !newObjects || newObjects.length === 0 ){\n              service.alertError( grid, 'importer.noObjects', 'Objects were not able to be derived, content was: ', importFile.target.result );\n              return;\n            }\n\n            service.addObjects( grid, newObjects );\n          };\n        },\n\n\n        /**\n         * @ngdoc function\n         * @name parseCsv\n         * @methodOf ui.grid.importer.service:uiGridImporterService\n         * @description Parses a csv file into an array of arrays, with the first\n         * array being the headers, and the remaining arrays being the data.\n         * The logic for this comes from https://github.com/thetalecrafter/excel.js/blob/master/src/csv.js,\n         * which is noted as being under the MIT license.  The code is modified to pass the jscs yoda condition\n         * checker\n         * @param {FileObject} importFile the file that we want to import, as a\n         * file object\n         */\n        parseCsv: function( importFile ) {\n          var csv = importFile.target.result;\n\n          // use the CSV-JS library to parse\n          return CSV.parse(csv);\n        },\n\n\n        /**\n         * @ngdoc function\n         * @name createCsvObjects\n         * @methodOf ui.grid.importer.service:uiGridImporterService\n         * @description Converts an array of arrays (representing the csv file)\n         * into a set of objects.  Uses the provided `gridOptions.importerNewObject`\n         * to create the objects, and maps the header row into the individual columns\n         * using either `gridOptions.importerProcessHeaders`, or by using a native method\n         * of matching to either the displayName, column name or column field of\n         * the columns in the column defs.  The resulting objects will have attributes\n         * that are named based on the column.field or column.name, in that order.\n         * @param {Grid} grid the grid that we want to import into\n         * @param {Array} importArray the data that we want to import, as an array\n         */\n        createCsvObjects: function( grid, importArray ){\n          // pull off header row and turn into headers\n          var headerMapping = grid.options.importerProcessHeaders( grid, importArray.shift() );\n          if ( !headerMapping || headerMapping.length === 0 ){\n            service.alertError( grid, 'importer.noHeaders', 'Column names could not be derived, content was: ', importArray );\n            return [];\n          }\n\n          var newObjects = [];\n          var newObject;\n          importArray.forEach( function( row, index ) {\n            newObject = service.newObject( grid );\n            if ( row !== null ){\n              row.forEach( function( field, index ){\n                if ( headerMapping[index] !== null ){\n                  newObject[ headerMapping[index] ] = field;\n                }\n              });\n            }\n            newObject = grid.options.importerObjectCallback( grid, newObject );\n            newObjects.push( newObject );\n          });\n\n          return newObjects;\n        },\n\n\n        /**\n         * @ngdoc function\n         * @name processHeaders\n         * @methodOf ui.grid.importer.service:uiGridImporterService\n         * @description Determines the columns that the header row from\n         * a csv (or other) file represents.\n         * @param {Grid} grid the grid we're importing into\n         * @param {array} headerRow the header row that we wish to match against\n         * the column definitions\n         * @returns {array} an array of the attribute names that should be used\n         * for that column, based on matching the headers or creating the headers\n         *\n         */\n        processHeaders: function( grid, headerRow ) {\n          var headers = [];\n          if ( !grid.options.columnDefs || grid.options.columnDefs.length === 0 ){\n            // we are going to create new columnDefs for all these columns, so just remove\n            // spaces from the names to create fields\n            headerRow.forEach( function( value, index ) {\n              headers.push( value.replace( /[^0-9a-zA-Z\\-_]/g, '_' ) );\n            });\n            return headers;\n          } else {\n            var lookupHash = service.flattenColumnDefs( grid, grid.options.columnDefs );\n            headerRow.forEach(  function( value, index ) {\n              if ( lookupHash[value] ) {\n                headers.push( lookupHash[value] );\n              } else if ( lookupHash[ value.toLowerCase() ] ) {\n                headers.push( lookupHash[ value.toLowerCase() ] );\n              } else {\n                headers.push( null );\n              }\n            });\n            return headers;\n          }\n        },\n\n\n        /**\n         * @name flattenColumnDefs\n         * @methodOf ui.grid.importer.service:uiGridImporterService\n         * @description Runs through the column defs and creates a hash of\n         * the displayName, name and field, and of each of those values forced to lower case,\n         * with each pointing to the field or name\n         * (whichever is present).  Used to lookup column headers and decide what\n         * attribute name to give to the resulting field.\n         * @param {Grid} grid the grid we're importing into\n         * @param {array} columnDefs the columnDefs that we should flatten\n         * @returns {hash} the flattened version of the column def information, allowing\n         * us to look up a value by `flattenedHash[ headerValue ]`\n         */\n        flattenColumnDefs: function( grid, columnDefs ){\n          var flattenedHash = {};\n          columnDefs.forEach(  function( columnDef, index) {\n            if ( columnDef.name ){\n              flattenedHash[ columnDef.name ] = columnDef.field || columnDef.name;\n              flattenedHash[ columnDef.name.toLowerCase() ] = columnDef.field || columnDef.name;\n            }\n\n            if ( columnDef.field ){\n              flattenedHash[ columnDef.field ] = columnDef.field || columnDef.name;\n              flattenedHash[ columnDef.field.toLowerCase() ] = columnDef.field || columnDef.name;\n            }\n\n            if ( columnDef.displayName ){\n              flattenedHash[ columnDef.displayName ] = columnDef.field || columnDef.name;\n              flattenedHash[ columnDef.displayName.toLowerCase() ] = columnDef.field || columnDef.name;\n            }\n\n            if ( columnDef.displayName && grid.options.importerHeaderFilter ){\n              flattenedHash[ grid.options.importerHeaderFilter(columnDef.displayName) ] = columnDef.field || columnDef.name;\n              flattenedHash[ grid.options.importerHeaderFilter(columnDef.displayName).toLowerCase() ] = columnDef.field || columnDef.name;\n            }\n          });\n\n          return flattenedHash;\n        },\n\n\n        /**\n         * @ngdoc function\n         * @name addObjects\n         * @methodOf ui.grid.importer.service:uiGridImporterService\n         * @description Inserts our new objects into the grid data, and\n         * sets the rows to dirty if the rowEdit feature is being used\n         *\n         * Does this by registering a watch on dataChanges, which essentially\n         * is waiting on the result of the grid data watch, and downstream processing.\n         *\n         * When the callback is called, it deregisters itself - we don't want to run\n         * again next time data is added.\n         *\n         * If we never get called, we deregister on destroy.\n         *\n         * @param {Grid} grid the grid we're importing into\n         * @param {array} newObjects the objects we want to insert into the grid data\n         * @returns {object} the new object\n         */\n        addObjects: function( grid, newObjects, $scope ){\n          if ( grid.api.rowEdit ){\n            var dataChangeDereg = grid.registerDataChangeCallback( function() {\n              grid.api.rowEdit.setRowsDirty( newObjects );\n              dataChangeDereg();\n            }, [uiGridConstants.dataChange.ROW] );\n\n            grid.importer.$scope.$on( '$destroy', dataChangeDereg );\n          }\n\n          grid.importer.$scope.$apply( grid.options.importerDataAddCallback( grid, newObjects ) );\n\n        },\n\n\n        /**\n         * @ngdoc function\n         * @name newObject\n         * @methodOf ui.grid.importer.service:uiGridImporterService\n         * @description Makes a new object based on `gridOptions.importerNewObject`,\n         * or based on an empty object if not present\n         * @param {Grid} grid the grid we're importing into\n         * @returns {object} the new object\n         */\n        newObject: function( grid ){\n          if ( typeof(grid.options) !== \"undefined\" && typeof(grid.options.importerNewObject) !== \"undefined\" ){\n            return new grid.options.importerNewObject();\n          } else {\n            return {};\n          }\n        },\n\n\n        /**\n         * @ngdoc function\n         * @name alertError\n         * @methodOf ui.grid.importer.service:uiGridImporterService\n         * @description Provides an internationalised user alert for the failure,\n         * and logs a console message including diagnostic content.\n         * Optionally, if the the `gridOptions.importerErrorCallback` routine\n         * is defined, then calls that instead, allowing user specified error routines\n         * @param {Grid} grid the grid we're importing into\n         * @param {array} headerRow the header row that we wish to match against\n         * the column definitions\n         */\n        alertError: function( grid, alertI18nToken, consoleMessage, context ){\n          if ( grid.options.importerErrorCallback ){\n            grid.options.importerErrorCallback( grid, alertI18nToken, consoleMessage, context );\n          } else {\n            $window.alert(i18nService.getSafeText( alertI18nToken ));\n            gridUtil.logError(consoleMessage + context );\n          }\n        }\n      };\n\n      return service;\n\n    }\n  ]);\n\n  /**\n   *  @ngdoc directive\n   *  @name ui.grid.importer.directive:uiGridImporter\n   *  @element div\n   *  @restrict A\n   *\n   *  @description Adds importer features to grid\n   *\n   */\n  module.directive('uiGridImporter', ['uiGridImporterConstants', 'uiGridImporterService', 'gridUtil', '$compile',\n    function (uiGridImporterConstants, uiGridImporterService, gridUtil, $compile) {\n      return {\n        replace: true,\n        priority: 0,\n        require: '^uiGrid',\n        scope: false,\n        link: function ($scope, $elm, $attrs, uiGridCtrl) {\n          uiGridImporterService.initializeGrid($scope, uiGridCtrl.grid);\n        }\n      };\n    }\n  ]);\n\n  /**\n   *  @ngdoc directive\n   *  @name ui.grid.importer.directive:uiGridImporterMenuItem\n   *  @element div\n   *  @restrict A\n   *\n   *  @description Handles the processing from the importer menu item - once a file is\n   *  selected\n   *\n   */\n  module.directive('uiGridImporterMenuItem', ['uiGridImporterConstants', 'uiGridImporterService', 'gridUtil', '$compile',\n    function (uiGridImporterConstants, uiGridImporterService, gridUtil, $compile) {\n      return {\n        replace: true,\n        priority: 0,\n        require: '^uiGrid',\n        scope: false,\n        templateUrl: 'ui-grid/importerMenuItem',\n        link: function ($scope, $elm, $attrs, uiGridCtrl) {\n          var handleFileSelect = function( event ){\n            var target = event.srcElement || event.target;\n\n            if (target && target.files && target.files.length === 1) {\n              var fileObject = target.files[0];\n              uiGridImporterService.importThisFile( grid, fileObject );\n              target.form.reset();\n            }\n          };\n\n          var fileChooser = $elm[0].querySelectorAll('.ui-grid-importer-file-chooser');\n          var grid = uiGridCtrl.grid;\n\n          if ( fileChooser.length !== 1 ){\n            gridUtil.logError('Found > 1 or < 1 file choosers within the menu item, error, cannot continue');\n          } else {\n            fileChooser[0].addEventListener('change', handleFileSelect, false);  // TODO: why the false on the end?  Google\n          }\n        }\n      };\n    }\n  ]);\n})();\n\n(function() {\n  'use strict';\n  /**\n   *  @ngdoc overview\n   *  @name ui.grid.infiniteScroll\n   *\n   *  @description\n   *\n   * #ui.grid.infiniteScroll\n   *\n   * <div class=\"alert alert-warning\" role=\"alert\"><strong>Beta</strong> This feature is ready for testing, but it either hasn't seen a lot of use or has some known bugs.</div>\n   *\n   * This module provides infinite scroll functionality to ui-grid\n   *\n   */\n  var module = angular.module('ui.grid.infiniteScroll', ['ui.grid']);\n  /**\n   *  @ngdoc service\n   *  @name ui.grid.infiniteScroll.service:uiGridInfiniteScrollService\n   *\n   *  @description Service for infinite scroll features\n   */\n  module.service('uiGridInfiniteScrollService', ['gridUtil', '$compile', '$timeout', 'uiGridConstants', 'ScrollEvent', '$q', function (gridUtil, $compile, $timeout, uiGridConstants, ScrollEvent, $q) {\n\n    var service = {\n\n      /**\n       * @ngdoc function\n       * @name initializeGrid\n       * @methodOf ui.grid.infiniteScroll.service:uiGridInfiniteScrollService\n       * @description This method register events and methods into grid public API\n       */\n\n      initializeGrid: function(grid, $scope) {\n        service.defaultGridOptions(grid.options);\n\n        if (!grid.options.enableInfiniteScroll){\n          return;\n        }\n\n        grid.infiniteScroll = { dataLoading: false };\n        service.setScrollDirections( grid, grid.options.infiniteScrollUp, grid.options.infiniteScrollDown );\n          grid.api.core.on.scrollEnd($scope, service.handleScroll);\n\n        /**\n         *  @ngdoc object\n         *  @name ui.grid.infiniteScroll.api:PublicAPI\n         *\n         *  @description Public API for infinite scroll feature\n         */\n        var publicApi = {\n          events: {\n            infiniteScroll: {\n\n              /**\n               * @ngdoc event\n               * @name needLoadMoreData\n               * @eventOf ui.grid.infiniteScroll.api:PublicAPI\n               * @description This event fires when scroll reaches bottom percentage of grid\n               * and needs to load data\n               */\n\n              needLoadMoreData: function ($scope, fn) {\n              },\n\n              /**\n               * @ngdoc event\n               * @name needLoadMoreDataTop\n               * @eventOf ui.grid.infiniteScroll.api:PublicAPI\n               * @description This event fires when scroll reaches top percentage of grid\n               * and needs to load data\n               */\n\n              needLoadMoreDataTop: function ($scope, fn) {\n              }\n            }\n          },\n          methods: {\n            infiniteScroll: {\n\n              /**\n               * @ngdoc function\n               * @name dataLoaded\n               * @methodOf ui.grid.infiniteScroll.api:PublicAPI\n               * @description Call this function when you have loaded the additional data\n               * requested.  You should set scrollUp and scrollDown to indicate\n               * whether there are still more pages in each direction.\n               *\n               * If you call dataLoaded without first calling `saveScrollPercentage` then we will\n               * scroll the user to the start of the newly loaded data, which usually gives a smooth scroll\n               * experience, but can give a jumpy experience with large `infiniteScrollRowsFromEnd` values, and\n               * on variable speed internet connections.  Using `saveScrollPercentage` as demonstrated in the tutorial\n               * should give a smoother scrolling experience for users.\n               *\n               * See infinite_scroll tutorial for example of usage\n               * @param {boolean} scrollUp if set to false flags that there are no more pages upwards, so don't fire\n               * any more infinite scroll events upward\n               * @param {boolean} scrollDown if set to false flags that there are no more pages downwards, so don't\n               * fire any more infinite scroll events downward\n               * @returns {promise} a promise that is resolved when the grid scrolling is fully adjusted.  If you're\n               * planning to remove pages, you should wait on this promise first, or you'll break the scroll positioning\n               */\n              dataLoaded: function( scrollUp, scrollDown ) {\n                service.setScrollDirections(grid, scrollUp, scrollDown);\n\n                var promise = service.adjustScroll(grid).then(function() {\n                  grid.infiniteScroll.dataLoading = false;\n                });\n\n                return promise;\n              },\n\n              /**\n               * @ngdoc function\n               * @name resetScroll\n               * @methodOf ui.grid.infiniteScroll.api:PublicAPI\n               * @description Call this function when you have taken some action that makes the current\n               * scroll position invalid.  For example, if you're using external sorting and you've resorted\n               * then you might reset the scroll, or if you've otherwise substantially changed the data, perhaps\n               * you've reused an existing grid for a new data set\n               *\n               * You must tell us whether there is data upwards or downwards after the reset\n               *\n               * @param {boolean} scrollUp flag that there are pages upwards, fire\n               * infinite scroll events upward\n               * @param {boolean} scrollDown flag that there are pages downwards, so\n               * fire infinite scroll events downward\n               * @returns {promise} promise that is resolved when the scroll reset is complete\n               */\n              resetScroll: function( scrollUp, scrollDown ) {\n                service.setScrollDirections( grid, scrollUp, scrollDown);\n\n                return service.adjustInfiniteScrollPosition(grid, 0);\n              },\n\n\n              /**\n               * @ngdoc function\n               * @name saveScrollPercentage\n               * @methodOf ui.grid.infiniteScroll.api:PublicAPI\n               * @description Saves the scroll percentage and number of visible rows before you adjust the data,\n               * used if you're subsequently going to call `dataRemovedTop` or `dataRemovedBottom`\n               */\n              saveScrollPercentage: function() {\n                grid.infiniteScroll.prevScrolltopPercentage = grid.renderContainers.body.prevScrolltopPercentage;\n                grid.infiniteScroll.previousVisibleRows = grid.renderContainers.body.visibleRowCache.length;\n              },\n\n\n              /**\n               * @ngdoc function\n               * @name dataRemovedTop\n               * @methodOf ui.grid.infiniteScroll.api:PublicAPI\n               * @description Adjusts the scroll position after you've removed data at the top\n               * @param {boolean} scrollUp flag that there are pages upwards, fire\n               * infinite scroll events upward\n               * @param {boolean} scrollDown flag that there are pages downwards, so\n               * fire infinite scroll events downward\n               */\n              dataRemovedTop: function( scrollUp, scrollDown ) {\n                service.dataRemovedTop( grid, scrollUp, scrollDown );\n              },\n\n              /**\n               * @ngdoc function\n               * @name dataRemovedBottom\n               * @methodOf ui.grid.infiniteScroll.api:PublicAPI\n               * @description Adjusts the scroll position after you've removed data at the bottom\n               * @param {boolean} scrollUp flag that there are pages upwards, fire\n               * infinite scroll events upward\n               * @param {boolean} scrollDown flag that there are pages downwards, so\n               * fire infinite scroll events downward\n               */\n              dataRemovedBottom: function( scrollUp, scrollDown ) {\n                service.dataRemovedBottom( grid, scrollUp, scrollDown );\n              },\n\n              /**\n               * @ngdoc function\n               * @name setScrollDirections\n               * @methodOf ui.grid.infiniteScroll.service:uiGridInfiniteScrollService\n               * @description Sets the scrollUp and scrollDown flags, handling nulls and undefined,\n               * and also sets the grid.suppressParentScroll\n               * @param {boolean} scrollUp whether there are pages available up - defaults to false\n               * @param {boolean} scrollDown whether there are pages available down - defaults to true\n               */\n              setScrollDirections:  function ( scrollUp, scrollDown ) {\n                service.setScrollDirections( grid, scrollUp, scrollDown );\n              }\n\n            }\n          }\n        };\n        grid.api.registerEventsFromObject(publicApi.events);\n        grid.api.registerMethodsFromObject(publicApi.methods);\n      },\n\n\n      defaultGridOptions: function (gridOptions) {\n        //default option to true unless it was explicitly set to false\n        /**\n         *  @ngdoc object\n         *  @name ui.grid.infiniteScroll.api:GridOptions\n         *\n         *  @description GridOptions for infinite scroll feature, these are available to be\n         *  set using the ui-grid {@link ui.grid.class:GridOptions gridOptions}\n         */\n\n        /**\n         *  @ngdoc object\n         *  @name enableInfiniteScroll\n         *  @propertyOf  ui.grid.infiniteScroll.api:GridOptions\n         *  @description Enable infinite scrolling for this grid\n         *  <br/>Defaults to true\n         */\n        gridOptions.enableInfiniteScroll = gridOptions.enableInfiniteScroll !== false;\n\n        /**\n         * @ngdoc property\n         * @name infiniteScrollRowsFromEnd\n         * @propertyOf ui.grid.class:GridOptions\n         * @description This setting controls how close to the end of the dataset a user gets before\n         * more data is requested by the infinite scroll, whether scrolling up or down.  This allows you to\n         * 'prefetch' rows before the user actually runs out of scrolling.\n         *\n         * Note that if you set this value too high it may give jumpy scrolling behaviour, if you're getting\n         * this behaviour you could use the `saveScrollPercentageMethod` right before loading your data, and we'll\n         * preserve that scroll position\n         *\n         * <br> Defaults to 20\n         */\n        gridOptions.infiniteScrollRowsFromEnd = gridOptions.infiniteScrollRowsFromEnd || 20;\n\n        /**\n         * @ngdoc property\n         * @name infiniteScrollUp\n         * @propertyOf ui.grid.class:GridOptions\n         * @description Whether you allow infinite scroll up, implying that the first page of data\n         * you have displayed is in the middle of your data set.  If set to true then we trigger the\n         * needMoreDataTop event when the user hits the top of the scrollbar.\n         * <br> Defaults to false\n         */\n        gridOptions.infiniteScrollUp = gridOptions.infiniteScrollUp === true;\n\n        /**\n         * @ngdoc property\n         * @name infiniteScrollDown\n         * @propertyOf ui.grid.class:GridOptions\n         * @description Whether you allow infinite scroll down, implying that the first page of data\n         * you have displayed is in the middle of your data set.  If set to true then we trigger the\n         * needMoreData event when the user hits the bottom of the scrollbar.\n         * <br> Defaults to true\n         */\n        gridOptions.infiniteScrollDown = gridOptions.infiniteScrollDown !== false;\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name setScrollDirections\n       * @methodOf ui.grid.infiniteScroll.service:uiGridInfiniteScrollService\n       * @description Sets the scrollUp and scrollDown flags, handling nulls and undefined,\n       * and also sets the grid.suppressParentScroll\n       * @param {grid} grid the grid we're operating on\n       * @param {boolean} scrollUp whether there are pages available up - defaults to false\n       * @param {boolean} scrollDown whether there are pages available down - defaults to true\n       */\n      setScrollDirections:  function ( grid, scrollUp, scrollDown ) {\n        grid.infiniteScroll.scrollUp = ( scrollUp === true );\n        grid.suppressParentScrollUp = ( scrollUp === true );\n\n        grid.infiniteScroll.scrollDown = ( scrollDown !== false);\n        grid.suppressParentScrollDown = ( scrollDown !== false);\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name handleScroll\n       * @methodOf ui.grid.infiniteScroll.service:uiGridInfiniteScrollService\n       * @description Called whenever the grid scrolls, determines whether the scroll should\n       * trigger an infinite scroll request for more data\n       * @param {object} args the args from the event\n       */\n      handleScroll:  function (args) {\n        // don't request data if already waiting for data, or if source is coming from ui.grid.adjustInfiniteScrollPosition() function\n        if ( args.grid.infiniteScroll && args.grid.infiniteScroll.dataLoading || args.source === 'ui.grid.adjustInfiniteScrollPosition' ){\n          return;\n        }\n\n        if (args.y) {\n          var percentage;\n          var targetPercentage = args.grid.options.infiniteScrollRowsFromEnd / args.grid.renderContainers.body.visibleRowCache.length;\n          if (args.grid.scrollDirection === uiGridConstants.scrollDirection.UP ) {\n            percentage = args.y.percentage;\n            if (percentage <= targetPercentage){\n              service.loadData(args.grid);\n            }\n          } else if (args.grid.scrollDirection === uiGridConstants.scrollDirection.DOWN) {\n            percentage = 1 - args.y.percentage;\n            if (percentage <= targetPercentage){\n              service.loadData(args.grid);\n            }\n          }\n        }\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name loadData\n       * @methodOf ui.grid.infiniteScroll.service:uiGridInfiniteScrollService\n       * @description This function fires 'needLoadMoreData' or 'needLoadMoreDataTop' event based on scrollDirection\n       * and whether there are more pages upwards or downwards.  It also stores the number of rows that we had previously,\n       * and clears out any saved scroll position so that we know whether or not the user calls `saveScrollPercentage`\n       * @param {Grid} grid the grid we're working on\n       */\n      loadData: function (grid) {\n        // save number of currently visible rows to calculate new scroll position later - we know that we want\n        // to be at approximately the row we're currently at\n        grid.infiniteScroll.previousVisibleRows = grid.renderContainers.body.visibleRowCache.length;\n        grid.infiniteScroll.direction = grid.scrollDirection;\n        delete grid.infiniteScroll.prevScrolltopPercentage;\n\n        if (grid.scrollDirection === uiGridConstants.scrollDirection.UP && grid.infiniteScroll.scrollUp ) {\n          grid.infiniteScroll.dataLoading = true;\n          grid.api.infiniteScroll.raise.needLoadMoreDataTop();\n        } else if (grid.scrollDirection === uiGridConstants.scrollDirection.DOWN && grid.infiniteScroll.scrollDown ) {\n          grid.infiniteScroll.dataLoading = true;\n          grid.api.infiniteScroll.raise.needLoadMoreData();\n        }\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name adjustScroll\n       * @methodOf ui.grid.infiniteScroll.service:uiGridInfiniteScrollService\n       * @description Once we are informed that data has been loaded, adjust the scroll position to account for that\n       * addition and to make things look clean.\n       *\n       * If we're scrolling up we scroll to the first row of the old data set -\n       * so we're assuming that you would have gotten to the top of the grid (from the 20% need more data trigger) by\n       * the time the data comes back.  If we're scrolling down we scoll to the last row of the old data set - so we're\n       * assuming that you would have gotten to the bottom of the grid (from the 80% need more data trigger) by the time\n       * the data comes back.\n       *\n       * Neither of these are good assumptions, but making this a smoother experience really requires\n       * that trigger to not be a percentage, and to be much closer to the end of the data (say, 5 rows off the end).  Even then\n       * it'd be better still to actually run into the end.  But if the data takes a while to come back, they may have scrolled\n       * somewhere else in the mean-time, in which case they'll get a jump back to the new data.  Anyway, this will do for\n       * now, until someone wants to do better.\n       * @param {Grid} grid the grid we're working on\n       * @returns {promise} a promise that is resolved when scrolling has finished\n       */\n      adjustScroll: function(grid){\n        var promise = $q.defer();\n        $timeout(function () {\n          var newPercentage;\n\n          if ( grid.infiniteScroll.direction === undefined ){\n            // called from initialize, tweak our scroll up a little\n            service.adjustInfiniteScrollPosition(grid, 0);\n          }\n\n          var newVisibleRows = grid.renderContainers.body.visibleRowCache.length;\n          var oldPercentage, oldTopRow;\n          var halfViewport = grid.getViewportHeight() / grid.options.rowHeight / 2;\n\n          if ( grid.infiniteScroll.direction === uiGridConstants.scrollDirection.UP ){\n            oldPercentage = grid.infiniteScroll.prevScrolltopPercentage || 0;\n            oldTopRow = oldPercentage * grid.infiniteScroll.previousVisibleRows;\n            newPercentage = ( newVisibleRows - grid.infiniteScroll.previousVisibleRows + oldTopRow + halfViewport ) / newVisibleRows;\n            service.adjustInfiniteScrollPosition(grid, newPercentage);\n            $timeout( function() {\n              promise.resolve();\n            });\n          }\n\n          if ( grid.infiniteScroll.direction === uiGridConstants.scrollDirection.DOWN ){\n            oldPercentage = grid.infiniteScroll.prevScrolltopPercentage || 1;\n            oldTopRow = oldPercentage * grid.infiniteScroll.previousVisibleRows;\n            newPercentage = ( oldTopRow - halfViewport ) / newVisibleRows;\n            service.adjustInfiniteScrollPosition(grid, newPercentage);\n            $timeout( function() {\n              promise.resolve();\n            });\n          }\n        }, 0);\n\n        return promise.promise;\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name adjustInfiniteScrollPosition\n       * @methodOf ui.grid.infiniteScroll.service:uiGridInfiniteScrollService\n       * @description This function fires 'needLoadMoreData' or 'needLoadMoreDataTop' event based on scrollDirection\n       * @param {Grid} grid the grid we're working on\n       * @param {number} percentage the percentage through the grid that we want to scroll to\n       * @returns {promise} a promise that is resolved when the scrolling finishes\n       */\n      adjustInfiniteScrollPosition: function (grid, percentage) {\n        var scrollEvent = new ScrollEvent(grid, null, null, 'ui.grid.adjustInfiniteScrollPosition');\n\n        //for infinite scroll, if there are pages upwards then never allow it to be at the zero position so the up button can be active\n        if ( percentage === 0 && grid.infiniteScroll.scrollUp ) {\n          scrollEvent.y = {pixels: 1};\n        }\n        else {\n          scrollEvent.y = {percentage: percentage};\n        }\n        grid.scrollContainers('', scrollEvent);\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name dataRemovedTop\n       * @methodOf ui.grid.infiniteScroll.api:PublicAPI\n       * @description Adjusts the scroll position after you've removed data at the top. You should\n       * have called `saveScrollPercentage` before you remove the data, and if you're doing this in\n       * response to a `needMoreData` you should wait until the promise from `loadData` has resolved\n       * before you start removing data\n       * @param {Grid} grid the grid we're working on\n       * @param {boolean} scrollUp flag that there are pages upwards, fire\n       * infinite scroll events upward\n       * @param {boolean} scrollDown flag that there are pages downwards, so\n       * fire infinite scroll events downward\n       * @returns {promise} a promise that is resolved when the scrolling finishes\n       */\n      dataRemovedTop: function( grid, scrollUp, scrollDown ) {\n        service.setScrollDirections( grid, scrollUp, scrollDown );\n\n        var newVisibleRows = grid.renderContainers.body.visibleRowCache.length;\n        var oldScrollRow = grid.infiniteScroll.prevScrolltopPercentage * grid.infiniteScroll.previousVisibleRows;\n\n        // since we removed from the top, our new scroll row will be the old scroll row less the number\n        // of rows removed\n        var newScrollRow = oldScrollRow - ( grid.infiniteScroll.previousVisibleRows - newVisibleRows );\n        var newScrollPercent = newScrollRow / newVisibleRows;\n\n        return service.adjustInfiniteScrollPosition( grid, newScrollPercent );\n      },\n\n      /**\n       * @ngdoc function\n       * @name dataRemovedBottom\n       * @methodOf ui.grid.infiniteScroll.api:PublicAPI\n       * @description Adjusts the scroll position after you've removed data at the bottom.  You should\n       * have called `saveScrollPercentage` before you remove the data, and if you're doing this in\n       * response to a `needMoreData` you should wait until the promise from `loadData` has resolved\n       * before you start removing data\n       * @param {Grid} grid the grid we're working on\n       * @param {boolean} scrollUp flag that there are pages upwards, fire\n       * infinite scroll events upward\n       * @param {boolean} scrollDown flag that there are pages downwards, so\n       * fire infinite scroll events downward\n       */\n      dataRemovedBottom: function( grid, scrollUp, scrollDown ) {\n        service.setScrollDirections( grid, scrollUp, scrollDown );\n\n        var newVisibleRows = grid.renderContainers.body.visibleRowCache.length;\n        var oldScrollRow = grid.infiniteScroll.prevScrolltopPercentage * grid.infiniteScroll.previousVisibleRows;\n\n        // since we removed from the bottom, our new scroll row will be same as the old scroll row\n        var newScrollPercent = oldScrollRow / newVisibleRows;\n\n        return service.adjustInfiniteScrollPosition( grid, newScrollPercent );\n      }\n    };\n    return service;\n  }]);\n  /**\n   *  @ngdoc directive\n   *  @name ui.grid.infiniteScroll.directive:uiGridInfiniteScroll\n   *  @element div\n   *  @restrict A\n   *\n   *  @description Adds infinite scroll features to grid\n   *\n   *  @example\n   <example module=\"app\">\n   <file name=\"app.js\">\n   var app = angular.module('app', ['ui.grid', 'ui.grid.infiniteScroll']);\n\n   app.controller('MainCtrl', ['$scope', function ($scope) {\n      $scope.data = [\n        { name: 'Alex', car: 'Toyota' },\n            { name: 'Sam', car: 'Lexus' }\n      ];\n\n      $scope.columnDefs = [\n        {name: 'name'},\n        {name: 'car'}\n      ];\n    }]);\n   </file>\n   <file name=\"index.html\">\n   <div ng-controller=\"MainCtrl\">\n   <div ui-grid=\"{ data: data, columnDefs: columnDefs }\" ui-grid-infinite-scroll=\"20\"></div>\n   </div>\n   </file>\n   </example>\n   */\n\n  module.directive('uiGridInfiniteScroll', ['uiGridInfiniteScrollService',\n    function (uiGridInfiniteScrollService) {\n      return {\n        priority: -200,\n        scope: false,\n        require: '^uiGrid',\n        compile: function($scope, $elm, $attr){\n          return {\n            pre: function($scope, $elm, $attr, uiGridCtrl) {\n              uiGridInfiniteScrollService.initializeGrid(uiGridCtrl.grid, $scope);\n            },\n            post: function($scope, $elm, $attr) {\n            }\n          };\n        }\n      };\n    }]);\n\n})();\n\n(function () {\n  'use strict';\n\n  /**\n   * @ngdoc overview\n   * @name ui.grid.moveColumns\n   * @description\n   *\n   * # ui.grid.moveColumns\n   *\n   * <div class=\"alert alert-warning\" role=\"alert\"><strong>Alpha</strong> This feature is in development. There will almost certainly be breaking api changes, or there are major outstanding bugs.</div>\n   *\n   * This module provides column moving capability to ui.grid. It enables to change the position of columns.\n   * <div doc-module-components=\"ui.grid.moveColumns\"></div>\n   */\n  var module = angular.module('ui.grid.moveColumns', ['ui.grid']);\n\n  /**\n   *  @ngdoc service\n   *  @name ui.grid.moveColumns.service:uiGridMoveColumnService\n   *  @description Service for column moving feature.\n   */\n  module.service('uiGridMoveColumnService', ['$q', '$timeout', '$log', 'ScrollEvent', 'uiGridConstants', 'gridUtil', function ($q, $timeout, $log, ScrollEvent, uiGridConstants, gridUtil) {\n\n    var service = {\n      initializeGrid: function (grid) {\n        var self = this;\n        this.registerPublicApi(grid);\n        this.defaultGridOptions(grid.options);\n        grid.registerColumnBuilder(self.movableColumnBuilder);\n      },\n      registerPublicApi: function (grid) {\n        var self = this;\n        /**\n         *  @ngdoc object\n         *  @name ui.grid.moveColumns.api:PublicApi\n         *  @description Public Api for column moving feature.\n         */\n        var publicApi = {\n          events: {\n            /**\n             * @ngdoc event\n             * @name columnPositionChanged\n             * @eventOf  ui.grid.moveColumns.api:PublicApi\n             * @description raised when column is moved\n             * <pre>\n             *      gridApi.colMovable.on.columnPositionChanged(scope,function(colDef, originalPosition, newPosition){})\n             * </pre>\n             * @param {object} colDef the column that was moved\n             * @param {integer} originalPosition of the column\n             * @param {integer} finalPosition of the column\n             */\n            colMovable: {\n              columnPositionChanged: function (colDef, originalPosition, newPosition) {\n              }\n            }\n          },\n          methods: {\n            /**\n             * @ngdoc method\n             * @name moveColumn\n             * @methodOf  ui.grid.moveColumns.api:PublicApi\n             * @description Method can be used to change column position.\n             * <pre>\n             *      gridApi.colMovable.moveColumn(oldPosition, newPosition)\n             * </pre>\n             * @param {integer} originalPosition of the column\n             * @param {integer} finalPosition of the column\n             */\n            colMovable: {\n              moveColumn: function (originalPosition, finalPosition) {\n                var columns = grid.columns;\n                if (!angular.isNumber(originalPosition) || !angular.isNumber(finalPosition)) {\n                  gridUtil.logError('MoveColumn: Please provide valid values for originalPosition and finalPosition');\n                  return;\n                }\n                var nonMovableColumns = 0;\n                for (var i = 0; i < columns.length; i++) {\n                  if ((angular.isDefined(columns[i].colDef.visible) && columns[i].colDef.visible === false) || columns[i].isRowHeader === true) {\n                    nonMovableColumns++;\n                  }\n                }\n                if (originalPosition >= (columns.length - nonMovableColumns) || finalPosition >= (columns.length - nonMovableColumns)) {\n                  gridUtil.logError('MoveColumn: Invalid values for originalPosition, finalPosition');\n                  return;\n                }\n                var findPositionForRenderIndex = function (index) {\n                  var position = index;\n                  for (var i = 0; i <= position; i++) {\n                    if (angular.isDefined(columns[i]) && ((angular.isDefined(columns[i].colDef.visible) && columns[i].colDef.visible === false) || columns[i].isRowHeader === true)) {\n                      position++;\n                    }\n                  }\n                  return position;\n                };\n                self.redrawColumnAtPosition(grid, findPositionForRenderIndex(originalPosition), findPositionForRenderIndex(finalPosition));\n              }\n            }\n          }\n        };\n        grid.api.registerEventsFromObject(publicApi.events);\n        grid.api.registerMethodsFromObject(publicApi.methods);\n      },\n      defaultGridOptions: function (gridOptions) {\n        /**\n         *  @ngdoc object\n         *  @name ui.grid.moveColumns.api:GridOptions\n         *\n         *  @description Options for configuring the move column feature, these are available to be\n         *  set using the ui-grid {@link ui.grid.class:GridOptions gridOptions}\n         */\n        /**\n         *  @ngdoc object\n         *  @name enableColumnMoving\n         *  @propertyOf  ui.grid.moveColumns.api:GridOptions\n         *  @description If defined, sets the default value for the colMovable flag on each individual colDefs\n         *  if their individual enableColumnMoving configuration is not defined. Defaults to true.\n         */\n        gridOptions.enableColumnMoving = gridOptions.enableColumnMoving !== false;\n      },\n      movableColumnBuilder: function (colDef, col, gridOptions) {\n        var promises = [];\n        /**\n         *  @ngdoc object\n         *  @name ui.grid.moveColumns.api:ColumnDef\n         *\n         *  @description Column Definition for move column feature, these are available to be\n         *  set using the ui-grid {@link ui.grid.class:GridOptions.columnDef gridOptions.columnDefs}\n         */\n        /**\n         *  @ngdoc object\n         *  @name enableColumnMoving\n         *  @propertyOf  ui.grid.moveColumns.api:ColumnDef\n         *  @description Enable column moving for the column.\n         */\n        colDef.enableColumnMoving = colDef.enableColumnMoving === undefined ? gridOptions.enableColumnMoving\n          : colDef.enableColumnMoving;\n        return $q.all(promises);\n      },\n      redrawColumnAtPosition: function (grid, originalPosition, newPosition) {\n\n        var columns = grid.columns;\n\n        var originalColumn = columns[originalPosition];\n        if (originalColumn.colDef.enableColumnMoving) {\n          if (originalPosition > newPosition) {\n            for (var i1 = originalPosition; i1 > newPosition; i1--) {\n              columns[i1] = columns[i1 - 1];\n            }\n          }\n          else if (newPosition > originalPosition) {\n            for (var i2 = originalPosition; i2 < newPosition; i2++) {\n              columns[i2] = columns[i2 + 1];\n            }\n          }\n          columns[newPosition] = originalColumn;\n          grid.queueGridRefresh();\n          $timeout(function () {\n            grid.api.core.notifyDataChange( uiGridConstants.dataChange.COLUMN );\n            grid.api.colMovable.raise.columnPositionChanged(originalColumn.colDef, originalPosition, newPosition);\n          });\n        }\n      }\n    };\n    return service;\n  }]);\n\n  /**\n   *  @ngdoc directive\n   *  @name ui.grid.moveColumns.directive:uiGridMoveColumns\n   *  @element div\n   *  @restrict A\n   *  @description Adds column moving features to the ui-grid directive.\n   *  @example\n   <example module=\"app\">\n   <file name=\"app.js\">\n   var app = angular.module('app', ['ui.grid', 'ui.grid.moveColumns']);\n   app.controller('MainCtrl', ['$scope', function ($scope) {\n        $scope.data = [\n          { name: 'Bob', title: 'CEO', age: 45 },\n          { name: 'Frank', title: 'Lowly Developer', age: 25 },\n          { name: 'Jenny', title: 'Highly Developer', age: 35 }\n        ];\n        $scope.columnDefs = [\n          {name: 'name'},\n          {name: 'title'},\n          {name: 'age'}\n        ];\n      }]);\n   </file>\n   <file name=\"main.css\">\n   .grid {\n      width: 100%;\n      height: 150px;\n    }\n   </file>\n   <file name=\"index.html\">\n   <div ng-controller=\"MainCtrl\">\n   <div class=\"grid\" ui-grid=\"{ data: data, columnDefs: columnDefs }\" ui-grid-move-columns></div>\n   </div>\n   </file>\n   </example>\n   */\n  module.directive('uiGridMoveColumns', ['uiGridMoveColumnService', function (uiGridMoveColumnService) {\n    return {\n      replace: true,\n      priority: 0,\n      require: '^uiGrid',\n      scope: false,\n      compile: function () {\n        return {\n          pre: function ($scope, $elm, $attrs, uiGridCtrl) {\n            uiGridMoveColumnService.initializeGrid(uiGridCtrl.grid);\n          },\n          post: function ($scope, $elm, $attrs, uiGridCtrl) {\n          }\n        };\n      }\n    };\n  }]);\n\n  /**\n   *  @ngdoc directive\n   *  @name ui.grid.moveColumns.directive:uiGridHeaderCell\n   *  @element div\n   *  @restrict A\n   *\n   *  @description Stacks on top of ui.grid.uiGridHeaderCell to provide capability to be able to move it to reposition column.\n   *\n   *  On receiving mouseDown event headerCell is cloned, now as the mouse moves the cloned header cell also moved in the grid.\n   *  In case the moving cloned header cell reaches the left or right extreme of grid, grid scrolling is triggered (if horizontal scroll exists).\n   *  On mouseUp event column is repositioned at position where mouse is released and cloned header cell is removed.\n   *\n   *  Events that invoke cloning of header cell:\n   *    - mousedown\n   *\n   *  Events that invoke movement of cloned header cell:\n   *    - mousemove\n   *\n   *  Events that invoke repositioning of column:\n   *    - mouseup\n   */\n  module.directive('uiGridHeaderCell', ['$q', 'gridUtil', 'uiGridMoveColumnService', '$document', '$log', 'uiGridConstants', 'ScrollEvent',\n    function ($q, gridUtil, uiGridMoveColumnService, $document, $log, uiGridConstants, ScrollEvent) {\n      return {\n        priority: -10,\n        require: '^uiGrid',\n        compile: function () {\n          return {\n            post: function ($scope, $elm, $attrs, uiGridCtrl) {\n\n              if ($scope.col.colDef.enableColumnMoving) {\n\n                /*\n                 * Our general approach to column move is that we listen to a touchstart or mousedown\n                 * event over the column header.  When we hear one, then we wait for a move of the same type\n                 * - if we are a touchstart then we listen for a touchmove, if we are a mousedown we listen for\n                 * a mousemove (i.e. a drag) before we decide that there's a move underway.  If there's never a move,\n                 * and we instead get a mouseup or a touchend, then we just drop out again and do nothing.\n                 *\n                 */\n                var $contentsElm = angular.element( $elm[0].querySelectorAll('.ui-grid-cell-contents') );\n\n                var gridLeft;\n                var previousMouseX;\n                var totalMouseMovement;\n                var rightMoveLimit;\n                var elmCloned = false;\n                var movingElm;\n                var reducedWidth;\n                var moveOccurred = false;\n\n                var downFn = function( event ){\n                  //Setting some variables required for calculations.\n                  gridLeft = $scope.grid.element[0].getBoundingClientRect().left;\n                  if ( $scope.grid.hasLeftContainer() ){\n                    gridLeft += $scope.grid.renderContainers.left.header[0].getBoundingClientRect().width;\n                  }\n\n                  previousMouseX = event.pageX;\n                  totalMouseMovement = 0;\n                  rightMoveLimit = gridLeft + $scope.grid.getViewportWidth();\n\n                  if ( event.type === 'mousedown' ){\n                    $document.on('mousemove', moveFn);\n                    $document.on('mouseup', upFn);\n                  } else if ( event.type === 'touchstart' ){\n                    $document.on('touchmove', moveFn);\n                    $document.on('touchend', upFn);\n                  }\n                };\n\n                var moveFn = function( event ) {\n                  var changeValue = event.pageX - previousMouseX;\n                  if ( changeValue === 0 ){ return; }\n                  //Disable text selection in Chrome during column move\n                  document.onselectstart = function() { return false; };\n\n                  moveOccurred = true;\n\n                  if (!elmCloned) {\n                    cloneElement();\n                  }\n                  else if (elmCloned) {\n                    moveElement(changeValue);\n                    previousMouseX = event.pageX;\n                  }\n                };\n\n                var upFn = function( event ){\n                  //Re-enable text selection after column move\n                  document.onselectstart = null;\n\n                  //Remove the cloned element on mouse up.\n                  if (movingElm) {\n                    movingElm.remove();\n                    elmCloned = false;\n                  }\n\n                  offAllEvents();\n                  onDownEvents();\n\n                  if (!moveOccurred){\n                    return;\n                  }\n\n                  var columns = $scope.grid.columns;\n                  var columnIndex = 0;\n                  for (var i = 0; i < columns.length; i++) {\n                    if (columns[i].colDef.name !== $scope.col.colDef.name) {\n                      columnIndex++;\n                    }\n                    else {\n                      break;\n                    }\n                  }\n\n                  //Case where column should be moved to a position on its left\n                  if (totalMouseMovement < 0) {\n                    var totalColumnsLeftWidth = 0;\n                    for (var il = columnIndex - 1; il >= 0; il--) {\n                      if (angular.isUndefined(columns[il].colDef.visible) || columns[il].colDef.visible === true) {\n                        totalColumnsLeftWidth += columns[il].drawnWidth || columns[il].width || columns[il].colDef.width;\n                        if (totalColumnsLeftWidth > Math.abs(totalMouseMovement)) {\n                          uiGridMoveColumnService.redrawColumnAtPosition\n                          ($scope.grid, columnIndex, il + 1);\n                          break;\n                        }\n                      }\n                    }\n                    //Case where column should be moved to beginning of the grid.\n                    if (totalColumnsLeftWidth < Math.abs(totalMouseMovement)) {\n                      uiGridMoveColumnService.redrawColumnAtPosition\n                      ($scope.grid, columnIndex, 0);\n                    }\n                  }\n\n                  //Case where column should be moved to a position on its right\n                  else if (totalMouseMovement > 0) {\n                    var totalColumnsRightWidth = 0;\n                    for (var ir = columnIndex + 1; ir < columns.length; ir++) {\n                      if (angular.isUndefined(columns[ir].colDef.visible) || columns[ir].colDef.visible === true) {\n                        totalColumnsRightWidth += columns[ir].drawnWidth || columns[ir].width || columns[ir].colDef.width;\n                        if (totalColumnsRightWidth > totalMouseMovement) {\n                          uiGridMoveColumnService.redrawColumnAtPosition\n                          ($scope.grid, columnIndex, ir - 1);\n                          break;\n                        }\n                      }\n                    }\n                    //Case where column should be moved to end of the grid.\n                    if (totalColumnsRightWidth < totalMouseMovement) {\n                      uiGridMoveColumnService.redrawColumnAtPosition\n                      ($scope.grid, columnIndex, columns.length - 1);\n                    }\n                  }\n                };\n\n                var onDownEvents = function(){\n                  $contentsElm.on('touchstart', downFn);\n                  $contentsElm.on('mousedown', downFn);\n                };\n\n                var offAllEvents = function() {\n                  $contentsElm.off('touchstart', downFn);\n                  $contentsElm.off('mousedown', downFn);\n\n                  $document.off('mousemove', moveFn);\n                  $document.off('touchmove', moveFn);\n\n                  $document.off('mouseup', upFn);\n                  $document.off('touchend', upFn);\n                };\n\n                onDownEvents();\n\n\n                var cloneElement = function () {\n                  elmCloned = true;\n\n                  //Cloning header cell and appending to current header cell.\n                  movingElm = $elm.clone();\n                  $elm.parent().append(movingElm);\n\n                  //Left of cloned element should be aligned to original header cell.\n                  movingElm.addClass('movingColumn');\n                  var movingElementStyles = {};\n                  var elmLeft;\n                  if (gridUtil.detectBrowser() === 'safari') {\n                    //Correction for Safari getBoundingClientRect,\n                    //which does not correctly compute when there is an horizontal scroll\n                    elmLeft = $elm[0].offsetLeft + $elm[0].offsetWidth - $elm[0].getBoundingClientRect().width;\n                  }\n                  else {\n                    elmLeft = $elm[0].getBoundingClientRect().left;\n                  }\n                  movingElementStyles.left = (elmLeft - gridLeft) + 'px';\n                  var gridRight = $scope.grid.element[0].getBoundingClientRect().right;\n                  var elmRight = $elm[0].getBoundingClientRect().right;\n                  if (elmRight > gridRight) {\n                    reducedWidth = $scope.col.drawnWidth + (gridRight - elmRight);\n                    movingElementStyles.width = reducedWidth + 'px';\n                  }\n                  movingElm.css(movingElementStyles);\n                };\n\n                var moveElement = function (changeValue) {\n                  //Calculate total column width\n                  var columns = $scope.grid.columns;\n                  var totalColumnWidth = 0;\n                  for (var i = 0; i < columns.length; i++) {\n                    if (angular.isUndefined(columns[i].colDef.visible) || columns[i].colDef.visible === true) {\n                      totalColumnWidth += columns[i].drawnWidth || columns[i].width || columns[i].colDef.width;\n                    }\n                  }\n\n                  //Calculate new position of left of column\n                  var currentElmLeft = movingElm[0].getBoundingClientRect().left - 1;\n                  var currentElmRight = movingElm[0].getBoundingClientRect().right;\n                  var newElementLeft;\n\n                  newElementLeft = currentElmLeft - gridLeft + changeValue;\n                  newElementLeft = newElementLeft < rightMoveLimit ? newElementLeft : rightMoveLimit;\n\n                  //Update css of moving column to adjust to new left value or fire scroll in case column has reached edge of grid\n                  if ((currentElmLeft >= gridLeft || changeValue > 0) && (currentElmRight <= rightMoveLimit || changeValue < 0)) {\n                    movingElm.css({visibility: 'visible', 'left': newElementLeft + 'px'});\n                  }\n                  else if (totalColumnWidth > Math.ceil(uiGridCtrl.grid.gridWidth)) {\n                    changeValue *= 8;\n                    var scrollEvent = new ScrollEvent($scope.col.grid, null, null, 'uiGridHeaderCell.moveElement');\n                    scrollEvent.x = {pixels: changeValue};\n                    scrollEvent.grid.scrollContainers('',scrollEvent);\n                  }\n\n                  //Calculate total width of columns on the left of the moving column and the mouse movement\n                  var totalColumnsLeftWidth = 0;\n                  for (var il = 0; il < columns.length; il++) {\n                    if (angular.isUndefined(columns[il].colDef.visible) || columns[il].colDef.visible === true) {\n                      if (columns[il].colDef.name !== $scope.col.colDef.name) {\n                        totalColumnsLeftWidth += columns[il].drawnWidth || columns[il].width || columns[il].colDef.width;\n                      }\n                      else {\n                        break;\n                      }\n                    }\n                  }\n                  if ($scope.newScrollLeft === undefined) {\n                    totalMouseMovement += changeValue;\n                  }\n                  else {\n                    totalMouseMovement = $scope.newScrollLeft + newElementLeft - totalColumnsLeftWidth;\n                  }\n\n                  //Increase width of moving column, in case the rightmost column was moved and its width was\n                  //decreased because of overflow\n                  if (reducedWidth < $scope.col.drawnWidth) {\n                    reducedWidth += Math.abs(changeValue);\n                    movingElm.css({'width': reducedWidth + 'px'});\n                  }\n                };\n              }\n            }\n          };\n        }\n      };\n    }]);\n})();\n\n(function() {\n  'use strict';\n\n  /**\n   * @ngdoc overview\n   * @name ui.grid.pagination\n   *\n   * @description\n   *\n   * # ui.grid.pagination\n   *\n   * <div class=\"alert alert-warning\" role=\"alert\"><strong>Alpha</strong> This feature is in development. There will almost certainly be breaking api changes, or there are major outstanding bugs.</div>\n   *\n   * This module provides pagination support to ui-grid\n   */\n  var module = angular.module('ui.grid.pagination', ['ng', 'ui.grid']);\n\n  /**\n   * @ngdoc service\n   * @name ui.grid.pagination.service:uiGridPaginationService\n   *\n   * @description Service for the pagination feature\n   */\n  module.service('uiGridPaginationService', ['gridUtil',\n    function (gridUtil) {\n      var service = {\n        /**\n         * @ngdoc method\n         * @name initializeGrid\n         * @methodOf ui.grid.pagination.service:uiGridPaginationService\n         * @description Attaches the service to a certain grid\n         * @param {Grid} grid The grid we want to work with\n         */\n        initializeGrid: function (grid) {\n          service.defaultGridOptions(grid.options);\n\n          /**\n          * @ngdoc object\n          * @name ui.grid.pagination.api:PublicAPI\n          *\n          * @description Public API for the pagination feature\n          */\n          var publicApi = {\n            events: {\n              pagination: {\n              /**\n               * @ngdoc event\n               * @name paginationChanged\n               * @eventOf ui.grid.pagination.api:PublicAPI\n               * @description This event fires when the pageSize or currentPage changes\n               * @param {int} currentPage requested page number\n               * @param {int} pageSize requested page size\n               */\n                paginationChanged: function (currentPage, pageSize) { }\n              }\n            },\n            methods: {\n              pagination: {\n                /**\n                 * @ngdoc method\n                 * @name getPage\n                 * @methodOf ui.grid.pagination.api:PublicAPI\n                 * @description Returns the number of the current page\n                 */\n                getPage: function () {\n                  return grid.options.enablePagination ? grid.options.paginationCurrentPage : null;\n                },\n                /**\n                 * @ngdoc method\n                 * @name getTotalPages\n                 * @methodOf ui.grid.pagination.api:PublicAPI\n                 * @description Returns the total number of pages\n                 */\n                getTotalPages: function () {\n                  if (!grid.options.enablePagination) {\n                    return null;\n                  }\n\n                  return (grid.options.totalItems === 0) ? 1 : Math.ceil(grid.options.totalItems / grid.options.paginationPageSize);\n                },\n                /**\n                 * @ngdoc method\n                 * @name nextPage\n                 * @methodOf ui.grid.pagination.api:PublicAPI\n                 * @description Moves to the next page, if possible\n                 */\n                nextPage: function () {\n                  if (!grid.options.enablePagination) {\n                    return;\n                  }\n\n                  if (grid.options.totalItems > 0) {\n                    grid.options.paginationCurrentPage = Math.min(\n                      grid.options.paginationCurrentPage + 1,\n                      publicApi.methods.pagination.getTotalPages()\n                    );\n                  } else {\n                    grid.options.paginationCurrentPage++;\n                  }\n                },\n                /**\n                 * @ngdoc method\n                 * @name previousPage\n                 * @methodOf ui.grid.pagination.api:PublicAPI\n                 * @description Moves to the previous page, if we're not on the first page\n                 */\n                previousPage: function () {\n                  if (!grid.options.enablePagination) {\n                    return;\n                  }\n\n                  grid.options.paginationCurrentPage = Math.max(grid.options.paginationCurrentPage - 1, 1);\n                },\n                /**\n                 * @ngdoc method\n                 * @name seek\n                 * @methodOf ui.grid.pagination.api:PublicAPI\n                 * @description Moves to the requested page\n                 * @param {int} page The number of the page that should be displayed\n                 */\n                seek: function (page) {\n                  if (!grid.options.enablePagination) {\n                    return;\n                  }\n                  if (!angular.isNumber(page) || page < 1) {\n                    throw 'Invalid page number: ' + page;\n                  }\n\n                  grid.options.paginationCurrentPage = Math.min(page, publicApi.methods.pagination.getTotalPages());\n                }\n              }\n            }\n          };\n\n          grid.api.registerEventsFromObject(publicApi.events);\n          grid.api.registerMethodsFromObject(publicApi.methods);\n\n          var processPagination = function( renderableRows ){\n            if (grid.options.useExternalPagination || !grid.options.enablePagination) {\n              return renderableRows;\n            }\n            //client side pagination\n            var pageSize = parseInt(grid.options.paginationPageSize, 10);\n            var currentPage = parseInt(grid.options.paginationCurrentPage, 10);\n\n            var visibleRows = renderableRows.filter(function (row) { return row.visible; });\n            grid.options.totalItems = visibleRows.length;\n\n            var firstRow = (currentPage - 1) * pageSize;\n            if (firstRow > visibleRows.length) {\n              currentPage = grid.options.paginationCurrentPage = 1;\n              firstRow = (currentPage - 1) * pageSize;\n            }\n            return visibleRows.slice(firstRow, firstRow + pageSize);\n          };\n\n          grid.registerRowsProcessor(processPagination, 900 );\n\n        },\n        defaultGridOptions: function (gridOptions) {\n          /**\n           * @ngdoc object\n           * @name ui.grid.pagination.api:GridOptions\n           *\n           * @description GridOptions for the pagination feature, these are available to be\n           * set using the ui-grid {@link ui.grid.class:GridOptions gridOptions}\n           */\n\n          /**\n           * @ngdoc property\n           * @name enablePagination\n           * @propertyOf ui.grid.pagination.api:GridOptions\n           * @description Enables pagination, defaults to true\n           */\n          gridOptions.enablePagination = gridOptions.enablePagination !== false;\n          /**\n           * @ngdoc property\n           * @name enablePaginationControls\n           * @propertyOf ui.grid.pagination.api:GridOptions\n           * @description Enables the paginator at the bottom of the grid. Turn this off, if you want to implement your\n           *              own controls outside the grid.\n           */\n          gridOptions.enablePaginationControls = gridOptions.enablePaginationControls !== false;\n          /**\n           * @ngdoc property\n           * @name useExternalPagination\n           * @propertyOf ui.grid.pagination.api:GridOptions\n           * @description Disables client side pagination. When true, handle the paginationChanged event and set data\n           *              and totalItems, defaults to `false`\n           */\n          gridOptions.useExternalPagination = gridOptions.useExternalPagination === true;\n          /**\n           * @ngdoc property\n           * @name totalItems\n           * @propertyOf ui.grid.pagination.api:GridOptions\n           * @description Total number of items, set automatically when client side pagination, needs set by user\n           *              for server side pagination\n           */\n          if (gridUtil.isNullOrUndefined(gridOptions.totalItems)) {\n            gridOptions.totalItems = 0;\n          }\n          /**\n           * @ngdoc property\n           * @name paginationPageSizes\n           * @propertyOf ui.grid.pagination.api:GridOptions\n           * @description Array of page sizes, defaults to `[250, 500, 1000]`\n           */\n          if (gridUtil.isNullOrUndefined(gridOptions.paginationPageSizes)) {\n            gridOptions.paginationPageSizes = [250, 500, 1000];\n          }\n          /**\n           * @ngdoc property\n           * @name paginationPageSize\n           * @propertyOf ui.grid.pagination.api:GridOptions\n           * @description Page size, defaults to the first item in paginationPageSizes, or 0 if paginationPageSizes is empty\n           */\n          if (gridUtil.isNullOrUndefined(gridOptions.paginationPageSize)) {\n            if (gridOptions.paginationPageSizes.length > 0) {\n              gridOptions.paginationPageSize = gridOptions.paginationPageSizes[0];\n            } else {\n              gridOptions.paginationPageSize = 0;\n            }\n          }\n          /**\n           * @ngdoc property\n           * @name paginationCurrentPage\n           * @propertyOf ui.grid.pagination.api:GridOptions\n           * @description Current page number, defaults to 1\n           */\n          if (gridUtil.isNullOrUndefined(gridOptions.paginationCurrentPage)) {\n            gridOptions.paginationCurrentPage = 1;\n          }\n\n          /**\n           * @ngdoc property\n           * @name paginationTemplate\n           * @propertyOf ui.grid.pagination.api:GridOptions\n           * @description A custom template for the pager, defaults to `ui-grid/pagination`\n           */\n          if (gridUtil.isNullOrUndefined(gridOptions.paginationTemplate)) {\n            gridOptions.paginationTemplate = 'ui-grid/pagination';\n          }\n        },\n        /**\n         * @ngdoc method\n         * @methodOf ui.grid.pagination.service:uiGridPaginationService\n         * @name uiGridPaginationService\n         * @description  Raises paginationChanged and calls refresh for client side pagination\n         * @param {Grid} grid the grid for which the pagination changed\n         * @param {int} currentPage requested page number\n         * @param {int} pageSize requested page size\n         */\n        onPaginationChanged: function (grid, currentPage, pageSize) {\n            grid.api.pagination.raise.paginationChanged(currentPage, pageSize);\n            if (!grid.options.useExternalPagination) {\n              grid.queueGridRefresh(); //client side pagination\n            }\n        }\n      };\n\n      return service;\n    }\n  ]);\n  /**\n   *  @ngdoc directive\n   *  @name ui.grid.pagination.directive:uiGridPagination\n   *  @element div\n   *  @restrict A\n   *\n   *  @description Adds pagination features to grid\n   *  @example\n   <example module=\"app\">\n   <file name=\"app.js\">\n   var app = angular.module('app', ['ui.grid', 'ui.grid.pagination']);\n\n   app.controller('MainCtrl', ['$scope', function ($scope) {\n      $scope.data = [\n        { name: 'Alex', car: 'Toyota' },\n        { name: 'Sam', car: 'Lexus' },\n        { name: 'Joe', car: 'Dodge' },\n        { name: 'Bob', car: 'Buick' },\n        { name: 'Cindy', car: 'Ford' },\n        { name: 'Brian', car: 'Audi' },\n        { name: 'Malcom', car: 'Mercedes Benz' },\n        { name: 'Dave', car: 'Ford' },\n        { name: 'Stacey', car: 'Audi' },\n        { name: 'Amy', car: 'Acura' },\n        { name: 'Scott', car: 'Toyota' },\n        { name: 'Ryan', car: 'BMW' },\n      ];\n\n      $scope.gridOptions = {\n        data: 'data',\n        paginationPageSizes: [5, 10, 25],\n        paginationPageSize: 5,\n        columnDefs: [\n          {name: 'name'},\n          {name: 'car'}\n        ]\n       }\n    }]);\n   </file>\n   <file name=\"index.html\">\n   <div ng-controller=\"MainCtrl\">\n   <div ui-grid=\"gridOptions\" ui-grid-pagination></div>\n   </div>\n   </file>\n   </example>\n   */\n  module.directive('uiGridPagination', ['gridUtil', 'uiGridPaginationService',\n    function (gridUtil, uiGridPaginationService) {\n      return {\n        priority: -200,\n        scope: false,\n        require: 'uiGrid',\n        link: {\n          pre: function ($scope, $elm, $attr, uiGridCtrl) {\n            uiGridPaginationService.initializeGrid(uiGridCtrl.grid);\n\n            gridUtil.getTemplate(uiGridCtrl.grid.options.paginationTemplate)\n              .then(function (contents) {\n                var template = angular.element(contents);\n                $elm.append(template);\n                uiGridCtrl.innerCompile(template);\n              });\n          }\n        }\n      };\n    }\n  ]);\n\n  /**\n   *  @ngdoc directive\n   *  @name ui.grid.pagination.directive:uiGridPager\n   *  @element div\n   *\n   *  @description Panel for handling pagination\n   */\n  module.directive('uiGridPager', ['uiGridPaginationService', 'uiGridConstants', 'gridUtil', 'i18nService',\n    function (uiGridPaginationService, uiGridConstants, gridUtil, i18nService) {\n      return {\n        priority: -200,\n        scope: true,\n        require: '^uiGrid',\n        link: function ($scope, $elm, $attr, uiGridCtrl) {\n          var defaultFocusElementSelector = '.ui-grid-pager-control-input';\n          $scope.aria = i18nService.getSafeText('pagination.aria'); //Returns an object with all of the aria labels\n\n          $scope.paginationApi = uiGridCtrl.grid.api.pagination;\n          $scope.sizesLabel = i18nService.getSafeText('pagination.sizes');\n          $scope.totalItemsLabel = i18nService.getSafeText('pagination.totalItems');\n          $scope.paginationOf = i18nService.getSafeText('pagination.of');\n          $scope.paginationThrough = i18nService.getSafeText('pagination.through');\n\n          var options = uiGridCtrl.grid.options;\n\n          uiGridCtrl.grid.renderContainers.body.registerViewportAdjuster(function (adjustment) {\n            adjustment.height = adjustment.height - gridUtil.elementHeight($elm);\n            return adjustment;\n          });\n\n          var dataChangeDereg = uiGridCtrl.grid.registerDataChangeCallback(function (grid) {\n            if (!grid.options.useExternalPagination) {\n              grid.options.totalItems = grid.rows.length;\n            }\n          }, [uiGridConstants.dataChange.ROW]);\n\n          $scope.$on('$destroy', dataChangeDereg);\n\n          var setShowing = function () {\n            $scope.showingLow = ((options.paginationCurrentPage - 1) * options.paginationPageSize) + 1;\n            $scope.showingHigh = Math.min(options.paginationCurrentPage * options.paginationPageSize, options.totalItems);\n          };\n\n          var deregT = $scope.$watch('grid.options.totalItems + grid.options.paginationPageSize', setShowing);\n\n          var deregP = $scope.$watch('grid.options.paginationCurrentPage + grid.options.paginationPageSize', function (newValues, oldValues) {\n              if (newValues === oldValues) {\n                return;\n              }\n\n              if (!angular.isNumber(options.paginationCurrentPage) || options.paginationCurrentPage < 1) {\n                options.paginationCurrentPage = 1;\n                return;\n              }\n\n              if (options.totalItems > 0 && options.paginationCurrentPage > $scope.paginationApi.getTotalPages()) {\n                options.paginationCurrentPage = $scope.paginationApi.getTotalPages();\n                return;\n              }\n\n              setShowing();\n              uiGridPaginationService.onPaginationChanged($scope.grid, options.paginationCurrentPage, options.paginationPageSize);\n            }\n          );\n\n          $scope.$on('$destroy', function() {\n            deregT();\n            deregP();\n          });\n\n          $scope.cantPageForward = function () {\n            if (options.totalItems > 0) {\n              return options.paginationCurrentPage >= $scope.paginationApi.getTotalPages();\n            } else {\n              return options.data.length < 1;\n            }\n          };\n\n          $scope.cantPageToLast = function () {\n            if (options.totalItems > 0) {\n              return $scope.cantPageForward();\n            } else {\n              return true;\n            }\n          };\n\n          $scope.cantPageBackward = function () {\n            return options.paginationCurrentPage <= 1;\n          };\n\n          var focusToInputIf = function(condition){\n            if (condition){\n              gridUtil.focus.bySelector($elm, defaultFocusElementSelector);\n            }\n          };\n\n          //Takes care of setting focus to the middle element when focus is lost\n          $scope.pageFirstPageClick = function () {\n            $scope.paginationApi.seek(1);\n            focusToInputIf($scope.cantPageBackward());\n          };\n\n          $scope.pagePreviousPageClick = function () {\n            $scope.paginationApi.previousPage();\n            focusToInputIf($scope.cantPageBackward());\n          };\n\n          $scope.pageNextPageClick = function () {\n            $scope.paginationApi.nextPage();\n            focusToInputIf($scope.cantPageForward());\n          };\n\n          $scope.pageLastPageClick = function () {\n            $scope.paginationApi.seek($scope.paginationApi.getTotalPages());\n            focusToInputIf($scope.cantPageToLast());\n          };\n\n        }\n      };\n    }\n  ]);\n})();\n\n(function () {\n  'use strict';\n\n  /**\n   * @ngdoc overview\n   * @name ui.grid.pinning\n   * @description\n   *\n   * # ui.grid.pinning\n   *\n   * <div class=\"alert alert-success\" role=\"alert\"><strong>Stable</strong> This feature is stable. There should no longer be breaking api changes without a deprecation warning.</div>\n   *\n   * This module provides column pinning to the end user via menu options in the column header\n   *\n   * <div doc-module-components=\"ui.grid.pinning\"></div>\n   */\n\n  var module = angular.module('ui.grid.pinning', ['ui.grid']);\n\n  module.constant('uiGridPinningConstants', {\n    container: {\n      LEFT: 'left',\n      RIGHT: 'right',\n      NONE: ''\n    }\n  });\n\n  module.service('uiGridPinningService', ['gridUtil', 'GridRenderContainer', 'i18nService', 'uiGridPinningConstants', function (gridUtil, GridRenderContainer, i18nService, uiGridPinningConstants) {\n    var service = {\n\n      initializeGrid: function (grid) {\n        service.defaultGridOptions(grid.options);\n\n        // Register a column builder to add new menu items for pinning left and right\n        grid.registerColumnBuilder(service.pinningColumnBuilder);\n\n        /**\n         *  @ngdoc object\n         *  @name ui.grid.pinning.api:PublicApi\n         *\n         *  @description Public Api for pinning feature\n         */\n        var publicApi = {\n          events: {\n            pinning: {\n              /**\n               * @ngdoc event\n               * @name columnPin\n               * @eventOf ui.grid.pinning.api:PublicApi\n               * @description raised when column pin state has changed\n               * <pre>\n               *   gridApi.pinning.on.columnPinned(scope, function(colDef){})\n               * </pre>\n               * @param {object} colDef the column that was changed\n               * @param {string} container the render container the column is in ('left', 'right', '')\n               */\n              columnPinned: function(colDef, container) {\n              }\n            }\n          },\n          methods: {\n            pinning: {\n              /**\n               * @ngdoc function\n               * @name pinColumn\n               * @methodOf ui.grid.pinning.api:PublicApi\n               * @description pin column left, right, or none\n               * <pre>\n               *   gridApi.pinning.pinColumn(col, uiGridPinningConstants.container.LEFT)\n               * </pre>\n               * @param {gridColumn} col the column being pinned\n               * @param {string} container one of the recognised types\n               * from uiGridPinningConstants\n               */\n              pinColumn: function(col, container) {\n                service.pinColumn(grid, col, container);\n              }\n            }\n          }\n        };\n\n        grid.api.registerEventsFromObject(publicApi.events);\n        grid.api.registerMethodsFromObject(publicApi.methods);\n      },\n\n      defaultGridOptions: function (gridOptions) {\n        //default option to true unless it was explicitly set to false\n        /**\n         *  @ngdoc object\n         *  @name ui.grid.pinning.api:GridOptions\n         *\n         *  @description GridOptions for pinning feature, these are available to be\n           *  set using the ui-grid {@link ui.grid.class:GridOptions gridOptions}\n         */\n\n        /**\n         *  @ngdoc object\n         *  @name enablePinning\n         *  @propertyOf  ui.grid.pinning.api:GridOptions\n         *  @description Enable pinning for the entire grid.\n         *  <br/>Defaults to true\n         */\n        gridOptions.enablePinning = gridOptions.enablePinning !== false;\n\n      },\n\n      pinningColumnBuilder: function (colDef, col, gridOptions) {\n        //default to true unless gridOptions or colDef is explicitly false\n\n        /**\n         *  @ngdoc object\n         *  @name ui.grid.pinning.api:ColumnDef\n         *\n         *  @description ColumnDef for pinning feature, these are available to be\n         *  set using the ui-grid {@link ui.grid.class:GridOptions.columnDef gridOptions.columnDefs}\n         */\n\n        /**\n         *  @ngdoc object\n         *  @name enablePinning\n         *  @propertyOf  ui.grid.pinning.api:ColumnDef\n         *  @description Enable pinning for the individual column.\n         *  <br/>Defaults to true\n         */\n        colDef.enablePinning = colDef.enablePinning === undefined ? gridOptions.enablePinning : colDef.enablePinning;\n\n\n        /**\n         *  @ngdoc object\n         *  @name pinnedLeft\n         *  @propertyOf  ui.grid.pinning.api:ColumnDef\n         *  @description Column is pinned left when grid is rendered\n         *  <br/>Defaults to false\n         */\n\n        /**\n         *  @ngdoc object\n         *  @name pinnedRight\n         *  @propertyOf  ui.grid.pinning.api:ColumnDef\n         *  @description Column is pinned right when grid is rendered\n         *  <br/>Defaults to false\n         */\n        if (colDef.pinnedLeft) {\n          col.renderContainer = 'left';\n          col.grid.createLeftContainer();\n        }\n        else if (colDef.pinnedRight) {\n          col.renderContainer = 'right';\n          col.grid.createRightContainer();\n        }\n\n        if (!colDef.enablePinning) {\n          return;\n        }\n\n        var pinColumnLeftAction = {\n          name: 'ui.grid.pinning.pinLeft',\n          title: i18nService.get().pinning.pinLeft,\n          icon: 'ui-grid-icon-left-open',\n          shown: function () {\n            return typeof(this.context.col.renderContainer) === 'undefined' || !this.context.col.renderContainer || this.context.col.renderContainer !== 'left';\n          },\n          action: function () {\n            service.pinColumn(this.context.col.grid, this.context.col, uiGridPinningConstants.container.LEFT);\n          }\n        };\n\n        var pinColumnRightAction = {\n          name: 'ui.grid.pinning.pinRight',\n          title: i18nService.get().pinning.pinRight,\n          icon: 'ui-grid-icon-right-open',\n          shown: function () {\n            return typeof(this.context.col.renderContainer) === 'undefined' || !this.context.col.renderContainer || this.context.col.renderContainer !== 'right';\n          },\n          action: function () {\n            service.pinColumn(this.context.col.grid, this.context.col, uiGridPinningConstants.container.RIGHT);\n          }\n        };\n\n        var removePinAction = {\n          name: 'ui.grid.pinning.unpin',\n          title: i18nService.get().pinning.unpin,\n          icon: 'ui-grid-icon-cancel',\n          shown: function () {\n            return typeof(this.context.col.renderContainer) !== 'undefined' && this.context.col.renderContainer !== null && this.context.col.renderContainer !== 'body';\n          },\n          action: function () {\n            service.pinColumn(this.context.col.grid, this.context.col, uiGridPinningConstants.container.UNPIN);\n          }\n        };\n\n        if (!gridUtil.arrayContainsObjectWithProperty(col.menuItems, 'name', 'ui.grid.pinning.pinLeft')) {\n          col.menuItems.push(pinColumnLeftAction);\n        }\n        if (!gridUtil.arrayContainsObjectWithProperty(col.menuItems, 'name', 'ui.grid.pinning.pinRight')) {\n          col.menuItems.push(pinColumnRightAction);\n        }\n        if (!gridUtil.arrayContainsObjectWithProperty(col.menuItems, 'name', 'ui.grid.pinning.unpin')) {\n          col.menuItems.push(removePinAction);\n        }\n      },\n\n      pinColumn: function(grid, col, container) {\n        if (container === uiGridPinningConstants.container.NONE) {\n          col.renderContainer = null;\n        }\n        else {\n          col.renderContainer = container;\n          if (container === uiGridPinningConstants.container.LEFT) {\n            grid.createLeftContainer();\n          }\n          else if (container === uiGridPinningConstants.container.RIGHT) {\n            grid.createRightContainer();\n          }\n        }\n\n        grid.refresh()\n        .then(function() {\n          grid.api.pinning.raise.columnPinned( col.colDef, container );\n        });\n      }\n    };\n\n    return service;\n  }]);\n\n  module.directive('uiGridPinning', ['gridUtil', 'uiGridPinningService',\n    function (gridUtil, uiGridPinningService) {\n      return {\n        require: 'uiGrid',\n        scope: false,\n        compile: function () {\n          return {\n            pre: function ($scope, $elm, $attrs, uiGridCtrl) {\n              uiGridPinningService.initializeGrid(uiGridCtrl.grid);\n            },\n            post: function ($scope, $elm, $attrs, uiGridCtrl) {\n            }\n          };\n        }\n      };\n    }]);\n\n\n})();\n\n(function(){\n  'use strict';\n\n  /**\n   * @ngdoc overview\n   * @name ui.grid.resizeColumns\n   * @description\n   *\n   * # ui.grid.resizeColumns\n   *\n   * <div class=\"alert alert-success\" role=\"alert\"><strong>Stable</strong> This feature is stable. There should no longer be breaking api changes without a deprecation warning.</div>\n   *\n   * This module allows columns to be resized.\n   */\n  var module = angular.module('ui.grid.resizeColumns', ['ui.grid']);\n\n  module.service('uiGridResizeColumnsService', ['gridUtil', '$q', '$timeout',\n    function (gridUtil, $q, $timeout) {\n\n      var service = {\n        defaultGridOptions: function(gridOptions){\n          //default option to true unless it was explicitly set to false\n          /**\n           *  @ngdoc object\n           *  @name ui.grid.resizeColumns.api:GridOptions\n           *\n           *  @description GridOptions for resizeColumns feature, these are available to be\n           *  set using the ui-grid {@link ui.grid.class:GridOptions gridOptions}\n           */\n\n          /**\n           *  @ngdoc object\n           *  @name enableColumnResizing\n           *  @propertyOf  ui.grid.resizeColumns.api:GridOptions\n           *  @description Enable column resizing on the entire grid\n           *  <br/>Defaults to true\n           */\n          gridOptions.enableColumnResizing = gridOptions.enableColumnResizing !== false;\n\n          //legacy support\n          //use old name if it is explicitly false\n          if (gridOptions.enableColumnResize === false){\n            gridOptions.enableColumnResizing = false;\n          }\n        },\n\n        colResizerColumnBuilder: function (colDef, col, gridOptions) {\n\n          var promises = [];\n          /**\n           *  @ngdoc object\n           *  @name ui.grid.resizeColumns.api:ColumnDef\n           *\n           *  @description ColumnDef for resizeColumns feature, these are available to be\n           *  set using the ui-grid {@link ui.grid.class:GridOptions.columnDef gridOptions.columnDefs}\n           */\n\n          /**\n           *  @ngdoc object\n           *  @name enableColumnResizing\n           *  @propertyOf  ui.grid.resizeColumns.api:ColumnDef\n           *  @description Enable column resizing on an individual column\n           *  <br/>Defaults to GridOptions.enableColumnResizing\n           */\n          //default to true unless gridOptions or colDef is explicitly false\n          colDef.enableColumnResizing = colDef.enableColumnResizing === undefined ? gridOptions.enableColumnResizing : colDef.enableColumnResizing;\n\n\n          //legacy support of old option name\n          if (colDef.enableColumnResize === false){\n            colDef.enableColumnResizing = false;\n          }\n\n          return $q.all(promises);\n        },\n\n        registerPublicApi: function (grid) {\n            /**\n             *  @ngdoc object\n             *  @name ui.grid.resizeColumns.api:PublicApi\n             *  @description Public Api for column resize feature.\n             */\n            var publicApi = {\n              events: {\n                /**\n                 * @ngdoc event\n                 * @name columnSizeChanged\n                 * @eventOf  ui.grid.resizeColumns.api:PublicApi\n                 * @description raised when column is resized\n                 * <pre>\n                 *      gridApi.colResizable.on.columnSizeChanged(scope,function(colDef, deltaChange){})\n                 * </pre>\n                 * @param {object} colDef the column that was resized\n                 * @param {integer} delta of the column size change\n                 */\n                colResizable: {\n                  columnSizeChanged: function (colDef, deltaChange) {\n                  }\n                }\n              }\n            };\n            grid.api.registerEventsFromObject(publicApi.events);\n        },\n\n        fireColumnSizeChanged: function (grid, colDef, deltaChange) {\n          $timeout(function () {\n            if ( grid.api.colResizable ){\n              grid.api.colResizable.raise.columnSizeChanged(colDef, deltaChange);\n            } else {\n              gridUtil.logError(\"The resizeable api is not registered, this may indicate that you've included the module but not added the 'ui-grid-resize-columns' directive to your grid definition.  Cannot raise any events.\");\n            }\n          });\n        },\n\n        // get either this column, or the column next to this column, to resize,\n        // returns the column we're going to resize\n        findTargetCol: function(col, position, rtlMultiplier){\n          var renderContainer = col.getRenderContainer();\n\n          if (position === 'left') {\n            // Get the column to the left of this one\n            var colIndex = renderContainer.visibleColumnCache.indexOf(col);\n            return renderContainer.visibleColumnCache[colIndex - 1 * rtlMultiplier];\n          } else {\n            return col;\n          }\n        }\n\n      };\n\n      return service;\n\n    }]);\n\n\n  /**\n   * @ngdoc directive\n   * @name ui.grid.resizeColumns.directive:uiGridResizeColumns\n   * @element div\n   * @restrict A\n   * @description\n   * Enables resizing for all columns on the grid. If, for some reason, you want to use the ui-grid-resize-columns directive, but not allow column resizing, you can explicitly set the\n   * option to false. This prevents resizing for the entire grid, regardless of individual columnDef options.\n   *\n   * @example\n   <doc:example module=\"app\">\n   <doc:source>\n   <script>\n   var app = angular.module('app', ['ui.grid', 'ui.grid.resizeColumns']);\n\n   app.controller('MainCtrl', ['$scope', function ($scope) {\n          $scope.gridOpts = {\n            data: [\n              { \"name\": \"Ethel Price\", \"gender\": \"female\", \"company\": \"Enersol\" },\n              { \"name\": \"Claudine Neal\", \"gender\": \"female\", \"company\": \"Sealoud\" },\n              { \"name\": \"Beryl Rice\", \"gender\": \"female\", \"company\": \"Velity\" },\n              { \"name\": \"Wilder Gonzales\", \"gender\": \"male\", \"company\": \"Geekko\" }\n            ]\n          };\n        }]);\n   </script>\n\n   <div ng-controller=\"MainCtrl\">\n   <div class=\"testGrid\" ui-grid=\"gridOpts\" ui-grid-resize-columns ></div>\n   </div>\n   </doc:source>\n   <doc:scenario>\n\n   </doc:scenario>\n   </doc:example>\n   */\n  module.directive('uiGridResizeColumns', ['gridUtil', 'uiGridResizeColumnsService', function (gridUtil, uiGridResizeColumnsService) {\n    return {\n      replace: true,\n      priority: 0,\n      require: '^uiGrid',\n      scope: false,\n      compile: function () {\n        return {\n          pre: function ($scope, $elm, $attrs, uiGridCtrl) {\n            uiGridResizeColumnsService.defaultGridOptions(uiGridCtrl.grid.options);\n            uiGridCtrl.grid.registerColumnBuilder( uiGridResizeColumnsService.colResizerColumnBuilder);\n            uiGridResizeColumnsService.registerPublicApi(uiGridCtrl.grid);\n          },\n          post: function ($scope, $elm, $attrs, uiGridCtrl) {\n          }\n        };\n      }\n    };\n  }]);\n\n  // Extend the uiGridHeaderCell directive\n  module.directive('uiGridHeaderCell', ['gridUtil', '$templateCache', '$compile', '$q', 'uiGridResizeColumnsService', 'uiGridConstants', '$timeout', function (gridUtil, $templateCache, $compile, $q, uiGridResizeColumnsService, uiGridConstants, $timeout) {\n    return {\n      // Run after the original uiGridHeaderCell\n      priority: -10,\n      require: '^uiGrid',\n      // scope: false,\n      compile: function() {\n        return {\n          post: function ($scope, $elm, $attrs, uiGridCtrl) {\n            var grid = uiGridCtrl.grid;\n\n            if (grid.options.enableColumnResizing) {\n              var columnResizerElm = $templateCache.get('ui-grid/columnResizer');\n\n              var rtlMultiplier = 1;\n              //when in RTL mode reverse the direction using the rtlMultiplier and change the position to left\n              if (grid.isRTL()) {\n                $scope.position = 'left';\n                rtlMultiplier = -1;\n              }\n\n              var displayResizers = function(){\n\n                // remove any existing resizers.\n                var resizers = $elm[0].getElementsByClassName('ui-grid-column-resizer');\n                for ( var i = 0; i < resizers.length; i++ ){\n                  angular.element(resizers[i]).remove();\n                }\n\n                // get the target column for the left resizer\n                var otherCol = uiGridResizeColumnsService.findTargetCol($scope.col, 'left', rtlMultiplier);\n                var renderContainer = $scope.col.getRenderContainer();\n\n                // Don't append the left resizer if this is the first column or the column to the left of this one has resizing disabled\n                if (otherCol && renderContainer.visibleColumnCache.indexOf($scope.col) !== 0 && otherCol.colDef.enableColumnResizing !== false) {\n                  var resizerLeft = angular.element(columnResizerElm).clone();\n                  resizerLeft.attr('position', 'left');\n\n                  $elm.prepend(resizerLeft);\n                  $compile(resizerLeft)($scope);\n                }\n\n                // Don't append the right resizer if this column has resizing disabled\n                if ($scope.col.colDef.enableColumnResizing !== false) {\n                  var resizerRight = angular.element(columnResizerElm).clone();\n                  resizerRight.attr('position', 'right');\n\n                  $elm.append(resizerRight);\n                  $compile(resizerRight)($scope);\n                }\n              };\n\n              displayResizers();\n\n              var waitDisplay = function(){\n                $timeout(displayResizers);\n              };\n\n              var dataChangeDereg = grid.registerDataChangeCallback( waitDisplay, [uiGridConstants.dataChange.COLUMN] );\n\n              $scope.$on( '$destroy', dataChangeDereg );\n            }\n          }\n        };\n      }\n    };\n  }]);\n\n\n\n  /**\n   * @ngdoc directive\n   * @name ui.grid.resizeColumns.directive:uiGridColumnResizer\n   * @element div\n   * @restrict A\n   *\n   * @description\n   * Draggable handle that controls column resizing.\n   *\n   * @example\n   <doc:example module=\"app\">\n     <doc:source>\n       <script>\n        var app = angular.module('app', ['ui.grid', 'ui.grid.resizeColumns']);\n\n        app.controller('MainCtrl', ['$scope', function ($scope) {\n          $scope.gridOpts = {\n            enableColumnResizing: true,\n            data: [\n              { \"name\": \"Ethel Price\", \"gender\": \"female\", \"company\": \"Enersol\" },\n              { \"name\": \"Claudine Neal\", \"gender\": \"female\", \"company\": \"Sealoud\" },\n              { \"name\": \"Beryl Rice\", \"gender\": \"female\", \"company\": \"Velity\" },\n              { \"name\": \"Wilder Gonzales\", \"gender\": \"male\", \"company\": \"Geekko\" }\n            ]\n          };\n        }]);\n       </script>\n\n       <div ng-controller=\"MainCtrl\">\n        <div class=\"testGrid\" ui-grid=\"gridOpts\"></div>\n       </div>\n     </doc:source>\n     <doc:scenario>\n      // TODO: e2e specs?\n\n      // TODO: post-resize a horizontal scroll event should be fired\n     </doc:scenario>\n   </doc:example>\n   */\n  module.directive('uiGridColumnResizer', ['$document', 'gridUtil', 'uiGridConstants', 'uiGridResizeColumnsService', function ($document, gridUtil, uiGridConstants, uiGridResizeColumnsService) {\n    var resizeOverlay = angular.element('<div class=\"ui-grid-resize-overlay\"></div>');\n\n    var resizer = {\n      priority: 0,\n      scope: {\n        col: '=',\n        position: '@',\n        renderIndex: '='\n      },\n      require: '?^uiGrid',\n      link: function ($scope, $elm, $attrs, uiGridCtrl) {\n        var startX = 0,\n            x = 0,\n            gridLeft = 0,\n            rtlMultiplier = 1;\n\n        //when in RTL mode reverse the direction using the rtlMultiplier and change the position to left\n        if (uiGridCtrl.grid.isRTL()) {\n          $scope.position = 'left';\n          rtlMultiplier = -1;\n        }\n\n        if ($scope.position === 'left') {\n          $elm.addClass('left');\n        }\n        else if ($scope.position === 'right') {\n          $elm.addClass('right');\n        }\n\n        // Refresh the grid canvas\n        //   takes an argument representing the diff along the X-axis that the resize had\n        function refreshCanvas(xDiff) {\n          // Then refresh the grid canvas, rebuilding the styles so that the scrollbar updates its size\n          uiGridCtrl.grid.refreshCanvas(true).then( function() {\n            uiGridCtrl.grid.queueGridRefresh();\n          });\n        }\n\n        // Check that the requested width isn't wider than the maxWidth, or narrower than the minWidth\n        // Returns the new recommended with, after constraints applied\n        function constrainWidth(col, width){\n          var newWidth = width;\n\n          // If the new width would be less than the column's allowably minimum width, don't allow it\n          if (col.minWidth && newWidth < col.minWidth) {\n            newWidth = col.minWidth;\n          }\n          else if (col.maxWidth && newWidth > col.maxWidth) {\n            newWidth = col.maxWidth;\n          }\n\n          return newWidth;\n        }\n\n\n        /*\n         * Our approach to event handling aims to deal with both touch devices and mouse devices\n         * We register down handlers on both touch and mouse.  When a touchstart or mousedown event\n         * occurs, we register the corresponding touchmove/touchend, or mousemove/mouseend events.\n         *\n         * This way we can listen for both without worrying about the fact many touch devices also emulate\n         * mouse events - basically whichever one we hear first is what we'll go with.\n         */\n        function moveFunction(event, args) {\n          if (event.originalEvent) { event = event.originalEvent; }\n          event.preventDefault();\n\n          x = (event.targetTouches ? event.targetTouches[0] : event).clientX - gridLeft;\n\n          if (x < 0) { x = 0; }\n          else if (x > uiGridCtrl.grid.gridWidth) { x = uiGridCtrl.grid.gridWidth; }\n\n          var col = uiGridResizeColumnsService.findTargetCol($scope.col, $scope.position, rtlMultiplier);\n\n          // Don't resize if it's disabled on this column\n          if (col.colDef.enableColumnResizing === false) {\n            return;\n          }\n\n          if (!uiGridCtrl.grid.element.hasClass('column-resizing')) {\n            uiGridCtrl.grid.element.addClass('column-resizing');\n          }\n\n          // Get the diff along the X axis\n          var xDiff = x - startX;\n\n          // Get the width that this mouse would give the column\n          var newWidth = parseInt(col.drawnWidth + xDiff * rtlMultiplier, 10);\n\n          // check we're not outside the allowable bounds for this column\n          x = x + ( constrainWidth(col, newWidth) - newWidth ) * rtlMultiplier;\n\n          resizeOverlay.css({ left: x + 'px' });\n\n          uiGridCtrl.fireEvent(uiGridConstants.events.ITEM_DRAGGING);\n        }\n\n\n        function upFunction(event, args) {\n          if (event.originalEvent) { event = event.originalEvent; }\n          event.preventDefault();\n\n          uiGridCtrl.grid.element.removeClass('column-resizing');\n\n          resizeOverlay.remove();\n\n          // Resize the column\n          x = (event.changedTouches ? event.changedTouches[0] : event).clientX - gridLeft;\n          var xDiff = x - startX;\n\n          if (xDiff === 0) {\n            // no movement, so just reset event handlers, including turning back on both\n            // down events - we turned one off when this event started\n            offAllEvents();\n            onDownEvents();\n            return;\n          }\n\n          var col = uiGridResizeColumnsService.findTargetCol($scope.col, $scope.position, rtlMultiplier);\n\n          // Don't resize if it's disabled on this column\n          if (col.colDef.enableColumnResizing === false) {\n            return;\n          }\n\n          // Get the new width\n          var newWidth = parseInt(col.drawnWidth + xDiff * rtlMultiplier, 10);\n\n          // check we're not outside the allowable bounds for this column\n          col.width = constrainWidth(col, newWidth);\n\n          refreshCanvas(xDiff);\n\n          uiGridResizeColumnsService.fireColumnSizeChanged(uiGridCtrl.grid, col.colDef, xDiff);\n\n          // stop listening of up and move events - wait for next down\n          // reset the down events - we will have turned one off when this event started\n          offAllEvents();\n          onDownEvents();\n        }\n\n\n        var downFunction = function(event, args) {\n          if (event.originalEvent) { event = event.originalEvent; }\n          event.stopPropagation();\n\n          // Get the left offset of the grid\n          // gridLeft = uiGridCtrl.grid.element[0].offsetLeft;\n          gridLeft = uiGridCtrl.grid.element[0].getBoundingClientRect().left;\n\n          // Get the starting X position, which is the X coordinate of the click minus the grid's offset\n          startX = (event.targetTouches ? event.targetTouches[0] : event).clientX - gridLeft;\n\n          // Append the resizer overlay\n          uiGridCtrl.grid.element.append(resizeOverlay);\n\n          // Place the resizer overlay at the start position\n          resizeOverlay.css({ left: startX });\n\n          // Add handlers for move and up events - if we were mousedown then we listen for mousemove and mouseup, if\n          // we were touchdown then we listen for touchmove and touchup.  Also remove the handler for the equivalent\n          // down event - so if we're touchdown, then remove the mousedown handler until this event is over, if we're\n          // mousedown then remove the touchdown handler until this event is over, this avoids processing duplicate events\n          if ( event.type === 'touchstart' ){\n            $document.on('touchend', upFunction);\n            $document.on('touchmove', moveFunction);\n            $elm.off('mousedown', downFunction);\n          } else {\n            $document.on('mouseup', upFunction);\n            $document.on('mousemove', moveFunction);\n            $elm.off('touchstart', downFunction);\n          }\n        };\n\n        var onDownEvents = function() {\n          $elm.on('mousedown', downFunction);\n          $elm.on('touchstart', downFunction);\n        };\n\n        var offAllEvents = function() {\n          $document.off('mouseup', upFunction);\n          $document.off('touchend', upFunction);\n          $document.off('mousemove', moveFunction);\n          $document.off('touchmove', moveFunction);\n          $elm.off('mousedown', downFunction);\n          $elm.off('touchstart', downFunction);\n        };\n\n        onDownEvents();\n\n\n        // On doubleclick, resize to fit all rendered cells\n        var dblClickFn = function(event, args){\n          event.stopPropagation();\n\n          var col = uiGridResizeColumnsService.findTargetCol($scope.col, $scope.position, rtlMultiplier);\n\n          // Don't resize if it's disabled on this column\n          if (col.colDef.enableColumnResizing === false) {\n            return;\n          }\n\n          // Go through the rendered rows and find out the max size for the data in this column\n          var maxWidth = 0;\n          var xDiff = 0;\n\n          // Get the parent render container element\n          var renderContainerElm = gridUtil.closestElm($elm, '.ui-grid-render-container');\n\n          // Get the cell contents so we measure correctly. For the header cell we have to account for the sort icon and the menu buttons, if present\n          var cells = renderContainerElm.querySelectorAll('.' + uiGridConstants.COL_CLASS_PREFIX + col.uid + ' .ui-grid-cell-contents');\n          Array.prototype.forEach.call(cells, function (cell) {\n              // Get the cell width\n              // gridUtil.logDebug('width', gridUtil.elementWidth(cell));\n\n              // Account for the menu button if it exists\n              var menuButton;\n              if (angular.element(cell).parent().hasClass('ui-grid-header-cell')) {\n                menuButton = angular.element(cell).parent()[0].querySelectorAll('.ui-grid-column-menu-button');\n              }\n\n              gridUtil.fakeElement(cell, {}, function(newElm) {\n                // Make the element float since it's a div and can expand to fill its container\n                var e = angular.element(newElm);\n                e.attr('style', 'float: left');\n\n                var width = gridUtil.elementWidth(e);\n\n                if (menuButton) {\n                  var menuButtonWidth = gridUtil.elementWidth(menuButton);\n                  width = width + menuButtonWidth;\n                }\n\n                if (width > maxWidth) {\n                  maxWidth = width;\n                  xDiff = maxWidth - width;\n                }\n              });\n            });\n\n          // check we're not outside the allowable bounds for this column\n          col.width = constrainWidth(col, maxWidth);\n\n          refreshCanvas(xDiff);\n\n          uiGridResizeColumnsService.fireColumnSizeChanged(uiGridCtrl.grid, col.colDef, xDiff);        };\n        $elm.on('dblclick', dblClickFn);\n\n        $elm.on('$destroy', function() {\n          $elm.off('dblclick', dblClickFn);\n          offAllEvents();\n        });\n      }\n    };\n\n    return resizer;\n  }]);\n\n})();\n\n(function () {\n  'use strict';\n\n  /**\n   * @ngdoc overview\n   * @name ui.grid.rowEdit\n   * @description\n   *\n   * # ui.grid.rowEdit\n   *\n   * <div class=\"alert alert-success\" role=\"alert\"><strong>Stable</strong> This feature is stable. There should no longer be breaking api changes without a deprecation warning.</div>\n   *\n   * This module extends the edit feature to provide tracking and saving of rows\n   * of data.  The tutorial provides more information on how this feature is best\n   * used {@link tutorial/205_row_editable here}.\n   * <br/>\n   * This feature depends on usage of the ui-grid-edit feature, and also benefits\n   * from use of ui-grid-cellNav to provide the full spreadsheet-like editing\n   * experience\n   *\n   */\n\n  var module = angular.module('ui.grid.rowEdit', ['ui.grid', 'ui.grid.edit', 'ui.grid.cellNav']);\n\n  /**\n   *  @ngdoc object\n   *  @name ui.grid.rowEdit.constant:uiGridRowEditConstants\n   *\n   *  @description constants available in row edit module\n   */\n  module.constant('uiGridRowEditConstants', {\n  });\n\n  /**\n   *  @ngdoc service\n   *  @name ui.grid.rowEdit.service:uiGridRowEditService\n   *\n   *  @description Services for row editing features\n   */\n  module.service('uiGridRowEditService', ['$interval', '$q', 'uiGridConstants', 'uiGridRowEditConstants', 'gridUtil',\n    function ($interval, $q, uiGridConstants, uiGridRowEditConstants, gridUtil) {\n\n      var service = {\n\n        initializeGrid: function (scope, grid) {\n          /**\n           *  @ngdoc object\n           *  @name ui.grid.rowEdit.api:PublicApi\n           *\n           *  @description Public Api for rowEdit feature\n           */\n\n          grid.rowEdit = {};\n\n          var publicApi = {\n            events: {\n              rowEdit: {\n                /**\n                 * @ngdoc event\n                 * @eventOf ui.grid.rowEdit.api:PublicApi\n                 * @name saveRow\n                 * @description raised when a row is ready for saving.  Once your\n                 * row has saved you may need to use angular.extend to update the\n                 * data entity with any changed data from your save (for example,\n                 * lock version information if you're using optimistic locking,\n                 * or last update time/user information).\n                 *\n                 * Your method should call setSavePromise somewhere in the body before\n                 * returning control.  The feature will then wait, with the gridRow greyed out\n                 * whilst this promise is being resolved.\n                 *\n                 * <pre>\n                 *      gridApi.rowEdit.on.saveRow(scope,function(rowEntity){})\n                 * </pre>\n                 * and somewhere within the event handler:\n                 * <pre>\n                 *      gridApi.rowEdit.setSavePromise( rowEntity, savePromise)\n                 * </pre>\n                 * @param {object} rowEntity the options.data element that was edited\n                 * @returns {promise} Your saveRow method should return a promise, the\n                 * promise should either be resolved (implying successful save), or\n                 * rejected (implying an error).\n                 */\n                saveRow: function (rowEntity) {\n                }\n              }\n            },\n            methods: {\n              rowEdit: {\n                /**\n                 * @ngdoc method\n                 * @methodOf ui.grid.rowEdit.api:PublicApi\n                 * @name setSavePromise\n                 * @description Sets the promise associated with the row save, mandatory that\n                 * the saveRow event handler calls this method somewhere before returning.\n                 * <pre>\n                 *      gridApi.rowEdit.setSavePromise(rowEntity, savePromise)\n                 * </pre>\n                 * @param {object} rowEntity a data row from the grid for which a save has\n                 * been initiated\n                 * @param {promise} savePromise the promise that will be resolved when the\n                 * save is successful, or rejected if the save fails\n                 *\n                 */\n                setSavePromise: function ( rowEntity, savePromise) {\n                  service.setSavePromise(grid, rowEntity, savePromise);\n                },\n                /**\n                 * @ngdoc method\n                 * @methodOf ui.grid.rowEdit.api:PublicApi\n                 * @name getDirtyRows\n                 * @description Returns all currently dirty rows\n                 * <pre>\n                 *      gridApi.rowEdit.getDirtyRows(grid)\n                 * </pre>\n                 * @returns {array} An array of gridRows that are currently dirty\n                 *\n                 */\n                getDirtyRows: function () {\n                  return grid.rowEdit.dirtyRows ? grid.rowEdit.dirtyRows : [];\n                },\n                /**\n                 * @ngdoc method\n                 * @methodOf ui.grid.rowEdit.api:PublicApi\n                 * @name getErrorRows\n                 * @description Returns all currently errored rows\n                 * <pre>\n                 *      gridApi.rowEdit.getErrorRows(grid)\n                 * </pre>\n                 * @returns {array} An array of gridRows that are currently in error\n                 *\n                 */\n                getErrorRows: function () {\n                  return grid.rowEdit.errorRows ? grid.rowEdit.errorRows : [];\n                },\n                /**\n                 * @ngdoc method\n                 * @methodOf ui.grid.rowEdit.api:PublicApi\n                 * @name flushDirtyRows\n                 * @description Triggers a save event for all currently dirty rows, could\n                 * be used where user presses a save button or navigates away from the page\n                 * <pre>\n                 *      gridApi.rowEdit.flushDirtyRows(grid)\n                 * </pre>\n                 * @returns {promise} a promise that represents the aggregate of all\n                 * of the individual save promises - i.e. it will be resolved when all\n                 * the individual save promises have been resolved.\n                 *\n                 */\n                flushDirtyRows: function () {\n                  return service.flushDirtyRows(grid);\n                },\n\n                /**\n                 * @ngdoc method\n                 * @methodOf ui.grid.rowEdit.api:PublicApi\n                 * @name setRowsDirty\n                 * @description Sets each of the rows passed in dataRows\n                 * to be dirty.  note that if you have only just inserted the\n                 * rows into your data you will need to wait for a $digest cycle\n                 * before the gridRows are present - so often you would wrap this\n                 * call in a $interval or $timeout\n                 * <pre>\n                 *      $interval( function() {\n                 *        gridApi.rowEdit.setRowsDirty(myDataRows);\n                 *      }, 0, 1);\n                 * </pre>\n                 * @param {array} dataRows the data entities for which the gridRows\n                 * should be set dirty.\n                 *\n                 */\n                setRowsDirty: function ( dataRows) {\n                  service.setRowsDirty(grid, dataRows);\n                },\n\n                /**\n                 * @ngdoc method\n                 * @methodOf ui.grid.rowEdit.api:PublicApi\n                 * @name setRowsClean\n                 * @description Sets each of the rows passed in dataRows\n                 * to be clean, removing them from the dirty cache and the error cache,\n                 * and clearing the error flag and the dirty flag\n                 * <pre>\n                 *      var gridRows = $scope.gridApi.rowEdit.getDirtyRows();\n                 *      var dataRows = gridRows.map( function( gridRow ) { return gridRow.entity; });\n                 *      $scope.gridApi.rowEdit.setRowsClean( dataRows );\n                 * </pre>\n                 * @param {array} dataRows the data entities for which the gridRows\n                 * should be set clean.\n                 *\n                 */\n                setRowsClean: function ( dataRows) {\n                  service.setRowsClean(grid, dataRows);\n                }\n              }\n            }\n          };\n\n          grid.api.registerEventsFromObject(publicApi.events);\n          grid.api.registerMethodsFromObject(publicApi.methods);\n\n          grid.api.core.on.renderingComplete( scope, function ( gridApi ) {\n            grid.api.edit.on.afterCellEdit( scope, service.endEditCell );\n            grid.api.edit.on.beginCellEdit( scope, service.beginEditCell );\n            grid.api.edit.on.cancelCellEdit( scope, service.cancelEditCell );\n\n            if ( grid.api.cellNav ) {\n              grid.api.cellNav.on.navigate( scope, service.navigate );\n            }\n          });\n\n        },\n\n        defaultGridOptions: function (gridOptions) {\n\n          /**\n           *  @ngdoc object\n           *  @name ui.grid.rowEdit.api:GridOptions\n           *\n           *  @description Options for configuring the rowEdit feature, these are available to be\n           *  set using the ui-grid {@link ui.grid.class:GridOptions gridOptions}\n           */\n\n        },\n\n\n        /**\n         * @ngdoc method\n         * @methodOf ui.grid.rowEdit.service:uiGridRowEditService\n         * @name saveRow\n         * @description  Returns a function that saves the specified row from the grid,\n         * and returns a promise\n         * @param {object} grid the grid for which dirty rows should be flushed\n         * @param {GridRow} gridRow the row that should be saved\n         * @returns {function} the saveRow function returns a function.  That function\n         * in turn, when called, returns a promise relating to the save callback\n         */\n        saveRow: function ( grid, gridRow ) {\n          var self = this;\n\n          return function() {\n            gridRow.isSaving = true;\n\n            if ( gridRow.rowEditSavePromise ){\n              // don't save the row again if it's already saving - that causes stale object exceptions\n              return gridRow.rowEditSavePromise;\n            }\n\n            var promise = grid.api.rowEdit.raise.saveRow( gridRow.entity );\n\n            if ( gridRow.rowEditSavePromise ){\n              gridRow.rowEditSavePromise.then( self.processSuccessPromise( grid, gridRow ), self.processErrorPromise( grid, gridRow ));\n            } else {\n              gridUtil.logError( 'A promise was not returned when saveRow event was raised, either nobody is listening to event, or event handler did not return a promise' );\n            }\n            return promise;\n          };\n        },\n\n\n        /**\n         * @ngdoc method\n         * @methodOf  ui.grid.rowEdit.service:uiGridRowEditService\n         * @name setSavePromise\n         * @description Sets the promise associated with the row save, mandatory that\n         * the saveRow event handler calls this method somewhere before returning.\n         * <pre>\n         *      gridApi.rowEdit.setSavePromise(grid, rowEntity)\n         * </pre>\n         * @param {object} grid the grid for which dirty rows should be returned\n         * @param {object} rowEntity a data row from the grid for which a save has\n         * been initiated\n         * @param {promise} savePromise the promise that will be resolved when the\n         * save is successful, or rejected if the save fails\n         *\n         */\n        setSavePromise: function (grid, rowEntity, savePromise) {\n          var gridRow = grid.getRow( rowEntity );\n          gridRow.rowEditSavePromise = savePromise;\n        },\n\n\n        /**\n         * @ngdoc method\n         * @methodOf ui.grid.rowEdit.service:uiGridRowEditService\n         * @name processSuccessPromise\n         * @description  Returns a function that processes the successful\n         * resolution of a save promise\n         * @param {object} grid the grid for which the promise should be processed\n         * @param {GridRow} gridRow the row that has been saved\n         * @returns {function} the success handling function\n         */\n        processSuccessPromise: function ( grid, gridRow ) {\n          var self = this;\n\n          return function() {\n            delete gridRow.isSaving;\n            delete gridRow.isDirty;\n            delete gridRow.isError;\n            delete gridRow.rowEditSaveTimer;\n            delete gridRow.rowEditSavePromise;\n            self.removeRow( grid.rowEdit.errorRows, gridRow );\n            self.removeRow( grid.rowEdit.dirtyRows, gridRow );\n          };\n        },\n\n\n        /**\n         * @ngdoc method\n         * @methodOf ui.grid.rowEdit.service:uiGridRowEditService\n         * @name processErrorPromise\n         * @description  Returns a function that processes the failed\n         * resolution of a save promise\n         * @param {object} grid the grid for which the promise should be processed\n         * @param {GridRow} gridRow the row that is now in error\n         * @returns {function} the error handling function\n         */\n        processErrorPromise: function ( grid, gridRow ) {\n          return function() {\n            delete gridRow.isSaving;\n            delete gridRow.rowEditSaveTimer;\n            delete gridRow.rowEditSavePromise;\n\n            gridRow.isError = true;\n\n            if (!grid.rowEdit.errorRows){\n              grid.rowEdit.errorRows = [];\n            }\n            if (!service.isRowPresent( grid.rowEdit.errorRows, gridRow ) ){\n              grid.rowEdit.errorRows.push( gridRow );\n            }\n          };\n        },\n\n\n        /**\n         * @ngdoc method\n         * @methodOf ui.grid.rowEdit.service:uiGridRowEditService\n         * @name removeRow\n         * @description  Removes a row from a cache of rows - either\n         * grid.rowEdit.errorRows or grid.rowEdit.dirtyRows.  If the row\n         * is not present silently does nothing.\n         * @param {array} rowArray the array from which to remove the row\n         * @param {GridRow} gridRow the row that should be removed\n         */\n        removeRow: function( rowArray, removeGridRow ){\n          if (typeof(rowArray) === 'undefined' || rowArray === null){\n            return;\n          }\n\n          rowArray.forEach( function( gridRow, index ){\n            if ( gridRow.uid === removeGridRow.uid ){\n              rowArray.splice( index, 1);\n            }\n          });\n        },\n\n\n        /**\n         * @ngdoc method\n         * @methodOf ui.grid.rowEdit.service:uiGridRowEditService\n         * @name isRowPresent\n         * @description  Checks whether a row is already present\n         * in the given array\n         * @param {array} rowArray the array in which to look for the row\n         * @param {GridRow} gridRow the row that should be looked for\n         */\n        isRowPresent: function( rowArray, removeGridRow ){\n          var present = false;\n          rowArray.forEach( function( gridRow, index ){\n            if ( gridRow.uid === removeGridRow.uid ){\n              present = true;\n            }\n          });\n          return present;\n        },\n\n\n        /**\n         * @ngdoc method\n         * @methodOf ui.grid.rowEdit.service:uiGridRowEditService\n         * @name flushDirtyRows\n         * @description Triggers a save event for all currently dirty rows, could\n         * be used where user presses a save button or navigates away from the page\n         * <pre>\n         *      gridApi.rowEdit.flushDirtyRows(grid)\n         * </pre>\n         * @param {object} grid the grid for which dirty rows should be flushed\n         * @returns {promise} a promise that represents the aggregate of all\n         * of the individual save promises - i.e. it will be resolved when all\n         * the individual save promises have been resolved.\n         *\n         */\n        flushDirtyRows: function(grid){\n          var promises = [];\n          grid.api.rowEdit.getDirtyRows().forEach( function( gridRow ){\n            service.saveRow( grid, gridRow )();\n            promises.push( gridRow.rowEditSavePromise );\n          });\n\n          return $q.all( promises );\n        },\n\n\n        /**\n         * @ngdoc method\n         * @methodOf ui.grid.rowEdit.service:uiGridRowEditService\n         * @name endEditCell\n         * @description Receives an afterCellEdit event from the edit function,\n         * and sets flags as appropriate.  Only the rowEntity parameter\n         * is processed, although other params are available.  Grid\n         * is automatically provided by the gridApi.\n         * @param {object} rowEntity the data entity for which the cell\n         * was edited\n         */\n        endEditCell: function( rowEntity, colDef, newValue, previousValue ){\n          var grid = this.grid;\n          var gridRow = grid.getRow( rowEntity );\n          if ( !gridRow ){ gridUtil.logError( 'Unable to find rowEntity in grid data, dirty flag cannot be set' ); return; }\n\n          if ( newValue !== previousValue || gridRow.isDirty ){\n            if ( !grid.rowEdit.dirtyRows ){\n              grid.rowEdit.dirtyRows = [];\n            }\n\n            if ( !gridRow.isDirty ){\n              gridRow.isDirty = true;\n              grid.rowEdit.dirtyRows.push( gridRow );\n            }\n\n            delete gridRow.isError;\n\n            service.considerSetTimer( grid, gridRow );\n          }\n        },\n\n\n        /**\n         * @ngdoc method\n         * @methodOf ui.grid.rowEdit.service:uiGridRowEditService\n         * @name beginEditCell\n         * @description Receives a beginCellEdit event from the edit function,\n         * and cancels any rowEditSaveTimers if present, as the user is still editing\n         * this row.  Only the rowEntity parameter\n         * is processed, although other params are available.  Grid\n         * is automatically provided by the gridApi.\n         * @param {object} rowEntity the data entity for which the cell\n         * editing has commenced\n         */\n        beginEditCell: function( rowEntity, colDef ){\n          var grid = this.grid;\n          var gridRow = grid.getRow( rowEntity );\n          if ( !gridRow ){ gridUtil.logError( 'Unable to find rowEntity in grid data, timer cannot be cancelled' ); return; }\n\n          service.cancelTimer( grid, gridRow );\n        },\n\n\n        /**\n         * @ngdoc method\n         * @methodOf ui.grid.rowEdit.service:uiGridRowEditService\n         * @name cancelEditCell\n         * @description Receives a cancelCellEdit event from the edit function,\n         * and if the row was already dirty, restarts the save timer.  If the row\n         * was not already dirty, then it's not dirty now either and does nothing.\n         *\n         * Only the rowEntity parameter\n         * is processed, although other params are available.  Grid\n         * is automatically provided by the gridApi.\n         *\n         * @param {object} rowEntity the data entity for which the cell\n         * editing was cancelled\n         */\n        cancelEditCell: function( rowEntity, colDef ){\n          var grid = this.grid;\n          var gridRow = grid.getRow( rowEntity );\n          if ( !gridRow ){ gridUtil.logError( 'Unable to find rowEntity in grid data, timer cannot be set' ); return; }\n\n          service.considerSetTimer( grid, gridRow );\n        },\n\n\n        /**\n         * @ngdoc method\n         * @methodOf ui.grid.rowEdit.service:uiGridRowEditService\n         * @name navigate\n         * @description cellNav tells us that the selected cell has changed.  If\n         * the new row had a timer running, then stop it similar to in a beginCellEdit\n         * call.  If the old row is dirty and not the same as the new row, then\n         * start a timer on it.\n         * @param {object} newRowCol the row and column that were selected\n         * @param {object} oldRowCol the row and column that was left\n         *\n         */\n        navigate: function( newRowCol, oldRowCol ){\n          var grid = this.grid;\n          if ( newRowCol.row.rowEditSaveTimer ){\n            service.cancelTimer( grid, newRowCol.row );\n          }\n\n          if ( oldRowCol && oldRowCol.row && oldRowCol.row !== newRowCol.row ){\n            service.considerSetTimer( grid, oldRowCol.row );\n          }\n        },\n\n\n        /**\n         * @ngdoc property\n         * @propertyOf ui.grid.rowEdit.api:GridOptions\n         * @name rowEditWaitInterval\n         * @description How long the grid should wait for another change on this row\n         * before triggering a save (in milliseconds).  If set to -1, then saves are\n         * never triggered by timer (implying that the user will call flushDirtyRows()\n         * manually)\n         *\n         * @example\n         * Setting the wait interval to 4 seconds\n         * <pre>\n         *   $scope.gridOptions = { rowEditWaitInterval: 4000 }\n         * </pre>\n         *\n         */\n        /**\n         * @ngdoc method\n         * @methodOf ui.grid.rowEdit.service:uiGridRowEditService\n         * @name considerSetTimer\n         * @description Consider setting a timer on this row (if it is dirty).  if there is a timer running\n         * on the row and the row isn't currently saving, cancel it, using cancelTimer, then if the row is\n         * dirty and not currently saving then set a new timer\n         * @param {object} grid the grid for which we are processing\n         * @param {GridRow} gridRow the row for which the timer should be adjusted\n         *\n         */\n        considerSetTimer: function( grid, gridRow ){\n          service.cancelTimer( grid, gridRow );\n\n          if ( gridRow.isDirty && !gridRow.isSaving ){\n            if ( grid.options.rowEditWaitInterval !== -1 ){\n              var waitTime = grid.options.rowEditWaitInterval ? grid.options.rowEditWaitInterval : 2000;\n              gridRow.rowEditSaveTimer = $interval( service.saveRow( grid, gridRow ), waitTime, 1);\n            }\n          }\n        },\n\n\n        /**\n         * @ngdoc method\n         * @methodOf ui.grid.rowEdit.service:uiGridRowEditService\n         * @name cancelTimer\n         * @description cancel the $interval for any timer running on this row\n         * then delete the timer itself\n         * @param {object} grid the grid for which we are processing\n         * @param {GridRow} gridRow the row for which the timer should be adjusted\n         *\n         */\n        cancelTimer: function( grid, gridRow ){\n          if ( gridRow.rowEditSaveTimer && !gridRow.isSaving ){\n            $interval.cancel(gridRow.rowEditSaveTimer);\n            delete gridRow.rowEditSaveTimer;\n          }\n        },\n\n\n        /**\n         * @ngdoc method\n         * @methodOf ui.grid.rowEdit.service:uiGridRowEditService\n         * @name setRowsDirty\n         * @description Sets each of the rows passed in dataRows\n         * to be dirty.  note that if you have only just inserted the\n         * rows into your data you will need to wait for a $digest cycle\n         * before the gridRows are present - so often you would wrap this\n         * call in a $interval or $timeout\n         * <pre>\n         *      $interval( function() {\n         *        gridApi.rowEdit.setRowsDirty( myDataRows);\n         *      }, 0, 1);\n         * </pre>\n         * @param {object} grid the grid for which rows should be set dirty\n         * @param {array} dataRows the data entities for which the gridRows\n         * should be set dirty.\n         *\n         */\n        setRowsDirty: function( grid, myDataRows ) {\n          var gridRow;\n          myDataRows.forEach( function( value, index ){\n            gridRow = grid.getRow( value );\n            if ( gridRow ){\n              if ( !grid.rowEdit.dirtyRows ){\n                grid.rowEdit.dirtyRows = [];\n              }\n\n              if ( !gridRow.isDirty ){\n                gridRow.isDirty = true;\n                grid.rowEdit.dirtyRows.push( gridRow );\n              }\n\n              delete gridRow.isError;\n\n              service.considerSetTimer( grid, gridRow );\n            } else {\n              gridUtil.logError( \"requested row not found in rowEdit.setRowsDirty, row was: \" + value );\n            }\n          });\n        },\n\n\n        /**\n         * @ngdoc method\n         * @methodOf ui.grid.rowEdit.service:uiGridRowEditService\n         * @name setRowsClean\n         * @description Sets each of the rows passed in dataRows\n         * to be clean, clearing the dirty flag and the error flag, and removing\n         * the rows from the dirty and error caches.\n         * @param {object} grid the grid for which rows should be set clean\n         * @param {array} dataRows the data entities for which the gridRows\n         * should be set clean.\n         *\n         */\n        setRowsClean: function( grid, myDataRows ) {\n          var gridRow;\n\n          myDataRows.forEach( function( value, index ){\n            gridRow = grid.getRow( value );\n            if ( gridRow ){\n              delete gridRow.isDirty;\n              service.removeRow( grid.rowEdit.dirtyRows, gridRow );\n              service.cancelTimer( grid, gridRow );\n\n              delete gridRow.isError;\n              service.removeRow( grid.rowEdit.errorRows, gridRow );\n            } else {\n              gridUtil.logError( \"requested row not found in rowEdit.setRowsClean, row was: \" + value );\n            }\n          });\n        }\n\n      };\n\n      return service;\n\n    }]);\n\n  /**\n   *  @ngdoc directive\n   *  @name ui.grid.rowEdit.directive:uiGridEdit\n   *  @element div\n   *  @restrict A\n   *\n   *  @description Adds row editing features to the ui-grid-edit directive.\n   *\n   */\n  module.directive('uiGridRowEdit', ['gridUtil', 'uiGridRowEditService', 'uiGridEditConstants',\n  function (gridUtil, uiGridRowEditService, uiGridEditConstants) {\n    return {\n      replace: true,\n      priority: 0,\n      require: '^uiGrid',\n      scope: false,\n      compile: function () {\n        return {\n          pre: function ($scope, $elm, $attrs, uiGridCtrl) {\n            uiGridRowEditService.initializeGrid($scope, uiGridCtrl.grid);\n          },\n          post: function ($scope, $elm, $attrs, uiGridCtrl) {\n          }\n        };\n      }\n    };\n  }]);\n\n\n  /**\n   *  @ngdoc directive\n   *  @name ui.grid.rowEdit.directive:uiGridViewport\n   *  @element div\n   *\n   *  @description Stacks on top of ui.grid.uiGridViewport to alter the attributes used\n   *  for the grid row to allow coloring of saving and error rows\n   */\n  module.directive('uiGridViewport',\n    ['$compile', 'uiGridConstants', 'gridUtil', '$parse',\n      function ($compile, uiGridConstants, gridUtil, $parse) {\n        return {\n          priority: -200, // run after default  directive\n          scope: false,\n          compile: function ($elm, $attrs) {\n            var rowRepeatDiv = angular.element($elm.children().children()[0]);\n\n            var existingNgClass = rowRepeatDiv.attr(\"ng-class\");\n            var newNgClass = '';\n            if ( existingNgClass ) {\n              newNgClass = existingNgClass.slice(0, -1) + \", 'ui-grid-row-dirty': row.isDirty, 'ui-grid-row-saving': row.isSaving, 'ui-grid-row-error': row.isError}\";\n            } else {\n              newNgClass = \"{'ui-grid-row-dirty': row.isDirty, 'ui-grid-row-saving': row.isSaving, 'ui-grid-row-error': row.isError}\";\n            }\n            rowRepeatDiv.attr(\"ng-class\", newNgClass);\n\n            return {\n              pre: function ($scope, $elm, $attrs, controllers) {\n\n              },\n              post: function ($scope, $elm, $attrs, controllers) {\n              }\n            };\n          }\n        };\n      }]);\n\n})();\n\n(function () {\n  'use strict';\n\n  /**\n   * @ngdoc overview\n   * @name ui.grid.saveState\n   * @description\n   *\n   * # ui.grid.saveState\n   *\n   * <div class=\"alert alert-success\" role=\"alert\"><strong>Stable</strong> This feature is stable. There should no longer be breaking api changes without a deprecation warning.</div>\n   *\n   * This module provides the ability to save the grid state, and restore\n   * it when the user returns to the page.\n   *\n   * No UI is provided, the caller should provide their own UI/buttons\n   * as appropriate. Usually the navigate events would be used to save\n   * the grid state and restore it.\n   *\n   * <br/>\n   * <br/>\n   *\n   * <div doc-module-components=\"ui.grid.save-state\"></div>\n   */\n\n  var module = angular.module('ui.grid.saveState', ['ui.grid', 'ui.grid.selection', 'ui.grid.cellNav', 'ui.grid.grouping', 'ui.grid.pinning', 'ui.grid.treeView']);\n\n  /**\n   *  @ngdoc object\n   *  @name ui.grid.saveState.constant:uiGridSaveStateConstants\n   *\n   *  @description constants available in save state module\n   */\n\n  module.constant('uiGridSaveStateConstants', {\n    featureName: 'saveState'\n  });\n\n  /**\n   *  @ngdoc service\n   *  @name ui.grid.saveState.service:uiGridSaveStateService\n   *\n   *  @description Services for saveState feature\n   */\n  module.service('uiGridSaveStateService', ['$q', 'uiGridSaveStateConstants', 'gridUtil', '$compile', '$interval', 'uiGridConstants',\n    function ($q, uiGridSaveStateConstants, gridUtil, $compile, $interval, uiGridConstants ) {\n\n      var service = {\n\n        initializeGrid: function (grid) {\n\n          //add feature namespace and any properties to grid for needed state\n          grid.saveState = {};\n          this.defaultGridOptions(grid.options);\n\n          /**\n           *  @ngdoc object\n           *  @name ui.grid.saveState.api:PublicApi\n           *\n           *  @description Public Api for saveState feature\n           */\n          var publicApi = {\n            events: {\n              saveState: {\n              }\n            },\n            methods: {\n              saveState: {\n                /**\n                 * @ngdoc function\n                 * @name save\n                 * @methodOf  ui.grid.saveState.api:PublicApi\n                 * @description Packages the current state of the grid into\n                 * an object, and provides it to the user for saving\n                 * @returns {object} the state as a javascript object that can be saved\n                 */\n                save: function () {\n                  return service.save(grid);\n                },\n                /**\n                 * @ngdoc function\n                 * @name restore\n                 * @methodOf  ui.grid.saveState.api:PublicApi\n                 * @description Restores the provided state into the grid\n                 * @param {scope} $scope a scope that we can broadcast on\n                 * @param {object} state the state that should be restored into the grid\n                 */\n                restore: function ( $scope, state) {\n                  service.restore(grid, $scope, state);\n                }\n              }\n            }\n          };\n\n          grid.api.registerEventsFromObject(publicApi.events);\n\n          grid.api.registerMethodsFromObject(publicApi.methods);\n\n        },\n\n        defaultGridOptions: function (gridOptions) {\n          //default option to true unless it was explicitly set to false\n          /**\n           * @ngdoc object\n           * @name ui.grid.saveState.api:GridOptions\n           *\n           * @description GridOptions for saveState feature, these are available to be\n           * set using the ui-grid {@link ui.grid.class:GridOptions gridOptions}\n           */\n          /**\n           * @ngdoc object\n           * @name saveWidths\n           * @propertyOf  ui.grid.saveState.api:GridOptions\n           * @description Save the current column widths.  Note that unless\n           * you've provided the user with some way to resize their columns (say\n           * the resize columns feature), then this makes little sense.\n           * <br/>Defaults to true\n           */\n          gridOptions.saveWidths = gridOptions.saveWidths !== false;\n          /**\n           * @ngdoc object\n           * @name saveOrder\n           * @propertyOf  ui.grid.saveState.api:GridOptions\n           * @description Restore the current column order.  Note that unless\n           * you've provided the user with some way to reorder their columns (for\n           * example the move columns feature), this makes little sense.\n           * <br/>Defaults to true\n           */\n          gridOptions.saveOrder = gridOptions.saveOrder !== false;\n          /**\n           * @ngdoc object\n           * @name saveScroll\n           * @propertyOf  ui.grid.saveState.api:GridOptions\n           * @description Save the current scroll position.  Note that this\n           * is saved as the percentage of the grid scrolled - so if your\n           * user returns to a grid with a significantly different number of\n           * rows (perhaps some data has been deleted) then the scroll won't\n           * actually show the same rows as before.  If you want to scroll to\n           * a specific row then you should instead use the saveFocus option, which\n           * is the default.\n           *\n           * Note that this element will only be saved if the cellNav feature is\n           * enabled\n           * <br/>Defaults to false\n           */\n          gridOptions.saveScroll = gridOptions.saveScroll === true;\n          /**\n           * @ngdoc object\n           * @name saveFocus\n           * @propertyOf  ui.grid.saveState.api:GridOptions\n           * @description Save the current focused cell.  On returning\n           * to this focused cell we'll also scroll.  This option is\n           * preferred to the saveScroll option, so is set to true by\n           * default.  If saveScroll is set to true then this option will\n           * be disabled.\n           *\n           * By default this option saves the current row number and column\n           * number, and returns to that row and column.  However, if you define\n           * a saveRowIdentity function, then it will return you to the currently\n           * selected column within that row (in a business sense - so if some\n           * rows have been deleted, it will still find the same data, presuming it\n           * still exists in the list.  If it isn't in the list then it will instead\n           * return to the same row number - i.e. scroll percentage)\n           *\n           * Note that this option will do nothing if the cellNav\n           * feature is not enabled.\n           *\n           * <br/>Defaults to true (unless saveScroll is true)\n           */\n          gridOptions.saveFocus = gridOptions.saveScroll !== true && gridOptions.saveFocus !== false;\n          /**\n           * @ngdoc object\n           * @name saveRowIdentity\n           * @propertyOf  ui.grid.saveState.api:GridOptions\n           * @description A function that can be called, passing in a rowEntity,\n           * and that will return a unique id for that row.  This might simply\n           * return the `id` field from that row (if you have one), or it might\n           * concatenate some fields within the row to make a unique value.\n           *\n           * This value will be used to find the same row again and set the focus\n           * to it, if it exists when we return.\n           *\n           * <br/>Defaults to undefined\n           */\n          /**\n           * @ngdoc object\n           * @name saveVisible\n           * @propertyOf  ui.grid.saveState.api:GridOptions\n           * @description Save whether or not columns are visible.\n           *\n           * <br/>Defaults to true\n           */\n          gridOptions.saveVisible = gridOptions.saveVisible !== false;\n          /**\n           * @ngdoc object\n           * @name saveSort\n           * @propertyOf  ui.grid.saveState.api:GridOptions\n           * @description Save the current sort state for each column\n           *\n           * <br/>Defaults to true\n           */\n          gridOptions.saveSort = gridOptions.saveSort !== false;\n          /**\n           * @ngdoc object\n           * @name saveFilter\n           * @propertyOf  ui.grid.saveState.api:GridOptions\n           * @description Save the current filter state for each column\n           *\n           * <br/>Defaults to true\n           */\n          gridOptions.saveFilter = gridOptions.saveFilter !== false;\n          /**\n           * @ngdoc object\n           * @name saveSelection\n           * @propertyOf  ui.grid.saveState.api:GridOptions\n           * @description Save the currently selected rows.  If the `saveRowIdentity` callback\n           * is defined, then it will save the id of the row and select that.  If not, then\n           * it will attempt to select the rows by row number, which will give the wrong results\n           * if the data set has changed in the mean-time.\n           *\n           * Note that this option only does anything\n           * if the selection feature is enabled.\n           *\n           * <br/>Defaults to true\n           */\n          gridOptions.saveSelection = gridOptions.saveSelection !== false;\n          /**\n           * @ngdoc object\n           * @name saveGrouping\n           * @propertyOf  ui.grid.saveState.api:GridOptions\n           * @description Save the grouping configuration.  If set to true and the\n           * grouping feature is not enabled then does nothing.\n           *\n           * <br/>Defaults to true\n           */\n          gridOptions.saveGrouping = gridOptions.saveGrouping !== false;\n          /**\n           * @ngdoc object\n           * @name saveGroupingExpandedStates\n           * @propertyOf  ui.grid.saveState.api:GridOptions\n           * @description Save the grouping row expanded states.  If set to true and the\n           * grouping feature is not enabled then does nothing.\n           *\n           * This can be quite a bit of data, in many cases you wouldn't want to save this\n           * information.\n           *\n           * <br/>Defaults to false\n           */\n          gridOptions.saveGroupingExpandedStates = gridOptions.saveGroupingExpandedStates === true;\n          /**\n           * @ngdoc object\n           * @name savePinning\n           * @propertyOf ui.grid.saveState.api:GridOptions\n           * @description Save pinning state for columns.\n           *\n           * <br/>Defaults to true\n           */\n          gridOptions.savePinning = gridOptions.savePinning !== false;\n          /**\n           * @ngdoc object\n           * @name saveTreeView\n           * @propertyOf  ui.grid.saveState.api:GridOptions\n           * @description Save the treeView configuration.  If set to true and the\n           * treeView feature is not enabled then does nothing.\n           *\n           * <br/>Defaults to true\n           */\n          gridOptions.saveTreeView = gridOptions.saveTreeView !== false;\n        },\n\n\n\n        /**\n         * @ngdoc function\n         * @name save\n         * @methodOf  ui.grid.saveState.service:uiGridSaveStateService\n         * @description Saves the current grid state into an object, and\n         * passes that object back to the caller\n         * @param {Grid} grid the grid whose state we'd like to save\n         * @returns {object} the state ready to be saved\n         */\n        save: function (grid) {\n          var savedState = {};\n\n          savedState.columns = service.saveColumns( grid );\n          savedState.scrollFocus = service.saveScrollFocus( grid );\n          savedState.selection = service.saveSelection( grid );\n          savedState.grouping = service.saveGrouping( grid );\n          savedState.treeView = service.saveTreeView( grid );\n\n          return savedState;\n        },\n\n\n        /**\n         * @ngdoc function\n         * @name restore\n         * @methodOf  ui.grid.saveState.service:uiGridSaveStateService\n         * @description Applies the provided state to the grid\n         *\n         * @param {Grid} grid the grid whose state we'd like to restore\n         * @param {scope} $scope a scope that we can broadcast on\n         * @param {object} state the state we'd like to restore\n         */\n        restore: function( grid, $scope, state ){\n          if ( state.columns ) {\n            service.restoreColumns( grid, state.columns );\n          }\n\n          if ( state.scrollFocus ){\n            service.restoreScrollFocus( grid, $scope, state.scrollFocus );\n          }\n\n          if ( state.selection ){\n            service.restoreSelection( grid, state.selection );\n          }\n\n          if ( state.grouping ){\n            service.restoreGrouping( grid, state.grouping );\n          }\n\n          if ( state.treeView ){\n            service.restoreTreeView( grid, state.treeView );\n          }\n\n          grid.refresh();\n        },\n\n\n        /**\n         * @ngdoc function\n         * @name saveColumns\n         * @methodOf  ui.grid.saveState.service:uiGridSaveStateService\n         * @description Saves the column setup, including sort, filters, ordering,\n         * pinning and column widths.\n         *\n         * Works through the current columns, storing them in order.  Stores the\n         * column name, then the visible flag, width, sort and filters for each column.\n         *\n         * @param {Grid} grid the grid whose state we'd like to save\n         * @returns {array} the columns state ready to be saved\n         */\n        saveColumns: function( grid ) {\n          var columns = [];\n          grid.getOnlyDataColumns().forEach( function( column ) {\n            var savedColumn = {};\n            savedColumn.name = column.name;\n\n            if ( grid.options.saveVisible ){\n              savedColumn.visible = column.visible;\n            }\n\n            if ( grid.options.saveWidths ){\n              savedColumn.width = column.width;\n            }\n\n            // these two must be copied, not just pointed too - otherwise our saved state is pointing to the same object as current state\n            if ( grid.options.saveSort ){\n              savedColumn.sort = angular.copy( column.sort );\n            }\n\n            if ( grid.options.saveFilter ){\n              savedColumn.filters = [];\n              column.filters.forEach( function( filter ){\n                var copiedFilter = {};\n                angular.forEach( filter, function( value, key) {\n                  if ( key !== 'condition' && key !== '$$hashKey' && key !== 'placeholder'){\n                    copiedFilter[key] = value;\n                  }\n                });\n                savedColumn.filters.push(copiedFilter);\n              });\n            }\n\n            if ( !!grid.api.pinning && grid.options.savePinning ){\n              savedColumn.pinned = column.renderContainer ? column.renderContainer : '';\n            }\n\n            columns.push( savedColumn );\n          });\n\n          return columns;\n        },\n\n\n        /**\n         * @ngdoc function\n         * @name saveScrollFocus\n         * @methodOf  ui.grid.saveState.service:uiGridSaveStateService\n         * @description Saves the currently scroll or focus.\n         *\n         * If cellNav isn't present then does nothing - we can't return\n         * to the scroll position without cellNav anyway.\n         *\n         * If the cellNav module is present, and saveFocus is true, then\n         * it saves the currently focused cell.  If rowIdentity is present\n         * then saves using rowIdentity, otherwise saves visibleRowNum.\n         *\n         * If the cellNav module is not present, and saveScroll is true, then\n         * it approximates the current scroll row and column, and saves that.\n         *\n         * @param {Grid} grid the grid whose state we'd like to save\n         * @returns {object} the selection state ready to be saved\n         */\n        saveScrollFocus: function( grid ){\n          if ( !grid.api.cellNav ){\n            return {};\n          }\n\n          var scrollFocus = {};\n          if ( grid.options.saveFocus ){\n            scrollFocus.focus = true;\n            var rowCol = grid.api.cellNav.getFocusedCell();\n            if ( rowCol !== null ) {\n              if ( rowCol.col !== null ){\n                scrollFocus.colName = rowCol.col.colDef.name;\n              }\n              if ( rowCol.row !== null ){\n                scrollFocus.rowVal = service.getRowVal( grid, rowCol.row );\n              }\n            }\n          }\n\n          if ( grid.options.saveScroll || grid.options.saveFocus && !scrollFocus.colName && !scrollFocus.rowVal ) {\n            scrollFocus.focus = false;\n            if ( grid.renderContainers.body.prevRowScrollIndex ){\n              scrollFocus.rowVal = service.getRowVal( grid, grid.renderContainers.body.visibleRowCache[ grid.renderContainers.body.prevRowScrollIndex ]);\n            }\n\n            if ( grid.renderContainers.body.prevColScrollIndex ){\n              scrollFocus.colName = grid.renderContainers.body.visibleColumnCache[ grid.renderContainers.body.prevColScrollIndex ].name;\n            }\n          }\n\n          return scrollFocus;\n        },\n\n\n        /**\n         * @ngdoc function\n         * @name saveSelection\n         * @methodOf  ui.grid.saveState.service:uiGridSaveStateService\n         * @description Saves the currently selected rows, if the selection feature is enabled\n         * @param {Grid} grid the grid whose state we'd like to save\n         * @returns {array} the selection state ready to be saved\n         */\n        saveSelection: function( grid ){\n          if ( !grid.api.selection || !grid.options.saveSelection ){\n            return [];\n          }\n\n          var selection = grid.api.selection.getSelectedGridRows().map( function( gridRow ) {\n            return service.getRowVal( grid, gridRow );\n          });\n\n          return selection;\n        },\n\n\n        /**\n         * @ngdoc function\n         * @name saveGrouping\n         * @methodOf  ui.grid.saveState.service:uiGridSaveStateService\n         * @description Saves the grouping state, if the grouping feature is enabled\n         * @param {Grid} grid the grid whose state we'd like to save\n         * @returns {object} the grouping state ready to be saved\n         */\n        saveGrouping: function( grid ){\n          if ( !grid.api.grouping || !grid.options.saveGrouping ){\n            return {};\n          }\n\n          return grid.api.grouping.getGrouping( grid.options.saveGroupingExpandedStates );\n        },\n\n\n        /**\n         * @ngdoc function\n         * @name saveTreeView\n         * @methodOf  ui.grid.saveState.service:uiGridSaveStateService\n         * @description Saves the tree view state, if the tree feature is enabled\n         * @param {Grid} grid the grid whose state we'd like to save\n         * @returns {object} the tree view state ready to be saved\n         */\n        saveTreeView: function( grid ){\n          if ( !grid.api.treeView || !grid.options.saveTreeView ){\n            return {};\n          }\n\n          return grid.api.treeView.getTreeView();\n        },\n\n\n        /**\n         * @ngdoc function\n         * @name getRowVal\n         * @methodOf  ui.grid.saveState.service:uiGridSaveStateService\n         * @description Helper function that gets either the rowNum or\n         * the saveRowIdentity, given a gridRow\n         * @param {Grid} grid the grid the row is in\n         * @param {GridRow} gridRow the row we want the rowNum for\n         * @returns {object} an object containing { identity: true/false, row: rowNumber/rowIdentity }\n         *\n         */\n        getRowVal: function( grid, gridRow ){\n          if ( !gridRow ) {\n            return null;\n          }\n\n          var rowVal = {};\n          if ( grid.options.saveRowIdentity ){\n            rowVal.identity = true;\n            rowVal.row = grid.options.saveRowIdentity( gridRow.entity );\n          } else {\n            rowVal.identity = false;\n            rowVal.row = grid.renderContainers.body.visibleRowCache.indexOf( gridRow );\n          }\n          return rowVal;\n        },\n\n\n        /**\n         * @ngdoc function\n         * @name restoreColumns\n         * @methodOf  ui.grid.saveState.service:uiGridSaveStateService\n         * @description Restores the columns, including order, visible, width,\n         * pinning, sort and filters.\n         *\n         * @param {Grid} grid the grid whose state we'd like to restore\n         * @param {object} columnsState the list of columns we had before, with their state\n         */\n        restoreColumns: function( grid, columnsState ){\n          var isSortChanged = false;\n\n          columnsState.forEach( function( columnState, index ) {\n            var currentCol = grid.getColumn( columnState.name );\n\n            if ( currentCol && !grid.isRowHeaderColumn(currentCol) ){\n              if ( grid.options.saveVisible &&\n                   ( currentCol.visible !== columnState.visible ||\n                     currentCol.colDef.visible !== columnState.visible ) ){\n                currentCol.visible = columnState.visible;\n                currentCol.colDef.visible = columnState.visible;\n                grid.api.core.raise.columnVisibilityChanged(currentCol);\n              }\n\n              if ( grid.options.saveWidths ){\n                currentCol.width = columnState.width;\n              }\n\n              if ( grid.options.saveSort &&\n                   !angular.equals(currentCol.sort, columnState.sort) &&\n                   !( currentCol.sort === undefined && angular.isEmpty(columnState.sort) ) ){\n                currentCol.sort = angular.copy( columnState.sort );\n                isSortChanged = true;\n              }\n\n              if ( grid.options.saveFilter &&\n                   !angular.equals(currentCol.filters, columnState.filters ) ){\n                columnState.filters.forEach( function( filter, index ){\n                  angular.extend( currentCol.filters[index], filter );\n                  if ( typeof(filter.term) === 'undefined' || filter.term === null ){\n                    delete currentCol.filters[index].term;\n                  }\n                });\n                grid.api.core.raise.filterChanged();\n              }\n\n              if ( !!grid.api.pinning && grid.options.savePinning && currentCol.renderContainer !== columnState.pinned ){\n                grid.api.pinning.pinColumn(currentCol, columnState.pinned);\n              }\n\n              var currentIndex = grid.getOnlyDataColumns().indexOf( currentCol );\n              if (currentIndex !== -1) {\n                if (grid.options.saveOrder && currentIndex !== index) {\n                  var column = grid.columns.splice(currentIndex + grid.rowHeaderColumns.length, 1)[0];\n                  grid.columns.splice(index + grid.rowHeaderColumns.length, 0, column);\n                }\n              }\n            }\n          });\n\n          if ( isSortChanged ) {\n            grid.api.core.raise.sortChanged( grid, grid.getColumnSorting() );\n          }\n        },\n\n\n        /**\n         * @ngdoc function\n         * @name restoreScrollFocus\n         * @methodOf  ui.grid.saveState.service:uiGridSaveStateService\n         * @description Scrolls to the position that was saved.  If focus is true, then\n         * sets focus to the specified row/col.  If focus is false, then scrolls to the\n         * specified row/col.\n         *\n         * @param {Grid} grid the grid whose state we'd like to restore\n         * @param {scope} $scope a scope that we can broadcast on\n         * @param {object} scrollFocusState the scroll/focus state ready to be restored\n         */\n        restoreScrollFocus: function( grid, $scope, scrollFocusState ){\n          if ( !grid.api.cellNav ){\n            return;\n          }\n\n          var colDef, row;\n          if ( scrollFocusState.colName ){\n            var colDefs = grid.options.columnDefs.filter( function( colDef ) { return colDef.name === scrollFocusState.colName; });\n            if ( colDefs.length > 0 ){\n              colDef = colDefs[0];\n            }\n          }\n\n          if ( scrollFocusState.rowVal && scrollFocusState.rowVal.row ){\n            if ( scrollFocusState.rowVal.identity ){\n              row = service.findRowByIdentity( grid, scrollFocusState.rowVal );\n            } else {\n              row = grid.renderContainers.body.visibleRowCache[ scrollFocusState.rowVal.row ];\n            }\n          }\n\n          var entity = row && row.entity ? row.entity : null ;\n\n          if ( colDef || entity ) {\n            if (scrollFocusState.focus ){\n              grid.api.cellNav.scrollToFocus( entity, colDef );\n            } else {\n              grid.scrollTo( entity, colDef );\n            }\n          }\n        },\n\n\n        /**\n         * @ngdoc function\n         * @name restoreSelection\n         * @methodOf  ui.grid.saveState.service:uiGridSaveStateService\n         * @description Selects the rows that are provided in the selection\n         * state.  If you are using `saveRowIdentity` and more than one row matches the identity\n         * function then only the first is selected.\n         * @param {Grid} grid the grid whose state we'd like to restore\n         * @param {object} selectionState the selection state ready to be restored\n         */\n        restoreSelection: function( grid, selectionState ){\n          if ( !grid.api.selection ){\n            return;\n          }\n\n          grid.api.selection.clearSelectedRows();\n\n          selectionState.forEach(  function( rowVal ) {\n            if ( rowVal.identity ){\n              var foundRow = service.findRowByIdentity( grid, rowVal );\n\n              if ( foundRow ){\n                grid.api.selection.selectRow( foundRow.entity );\n              }\n\n            } else {\n              grid.api.selection.selectRowByVisibleIndex( rowVal.row );\n            }\n          });\n        },\n\n\n        /**\n         * @ngdoc function\n         * @name restoreGrouping\n         * @methodOf  ui.grid.saveState.service:uiGridSaveStateService\n         * @description Restores the grouping configuration, if the grouping feature\n         * is enabled.\n         * @param {Grid} grid the grid whose state we'd like to restore\n         * @param {object} groupingState the grouping state ready to be restored\n         */\n        restoreGrouping: function( grid, groupingState ){\n          if ( !grid.api.grouping || typeof(groupingState) === 'undefined' || groupingState === null || angular.equals(groupingState, {}) ){\n            return;\n          }\n\n          grid.api.grouping.setGrouping( groupingState );\n        },\n\n        /**\n         * @ngdoc function\n         * @name restoreTreeView\n         * @methodOf  ui.grid.saveState.service:uiGridSaveStateService\n         * @description Restores the tree view configuration, if the tree view feature\n         * is enabled.\n         * @param {Grid} grid the grid whose state we'd like to restore\n         * @param {object} treeViewState the tree view state ready to be restored\n         */\n        restoreTreeView: function( grid, treeViewState ){\n          if ( !grid.api.treeView || typeof(treeViewState) === 'undefined' || treeViewState === null || angular.equals(treeViewState, {}) ){\n            return;\n          }\n\n          grid.api.treeView.setTreeView( treeViewState );\n        },\n\n        /**\n         * @ngdoc function\n         * @name findRowByIdentity\n         * @methodOf  ui.grid.saveState.service:uiGridSaveStateService\n         * @description Finds a row given it's identity value, returns the first found row\n         * if any are found, otherwise returns null if no rows are found.\n         * @param {Grid} grid the grid whose state we'd like to restore\n         * @param {object} rowVal the row we'd like to find\n         * @returns {gridRow} the found row, or null if none found\n         */\n        findRowByIdentity: function( grid, rowVal ){\n          if ( !grid.options.saveRowIdentity ){\n            return null;\n          }\n\n          var filteredRows = grid.rows.filter( function( gridRow ) {\n            if ( grid.options.saveRowIdentity( gridRow.entity ) === rowVal.row ){\n              return true;\n            } else {\n              return false;\n            }\n          });\n\n          if ( filteredRows.length > 0 ){\n            return filteredRows[0];\n          } else {\n            return null;\n          }\n        }\n      };\n\n      return service;\n\n    }\n  ]);\n\n  /**\n   *  @ngdoc directive\n   *  @name ui.grid.saveState.directive:uiGridSaveState\n   *  @element div\n   *  @restrict A\n   *\n   *  @description Adds saveState features to grid\n   *\n   *  @example\n   <example module=\"app\">\n   <file name=\"app.js\">\n   var app = angular.module('app', ['ui.grid', 'ui.grid.saveState']);\n\n   app.controller('MainCtrl', ['$scope', function ($scope) {\n      $scope.data = [\n        { name: 'Bob', title: 'CEO' },\n        { name: 'Frank', title: 'Lowly Developer' }\n      ];\n\n      $scope.gridOptions = {\n        columnDefs: [\n          {name: 'name'},\n          {name: 'title', enableCellEdit: true}\n        ],\n        data: $scope.data\n      };\n    }]);\n   </file>\n   <file name=\"index.html\">\n   <div ng-controller=\"MainCtrl\">\n   <div ui-grid=\"gridOptions\" ui-grid-save-state></div>\n   </div>\n   </file>\n   </example>\n   */\n  module.directive('uiGridSaveState', ['uiGridSaveStateConstants', 'uiGridSaveStateService', 'gridUtil', '$compile',\n    function (uiGridSaveStateConstants, uiGridSaveStateService, gridUtil, $compile) {\n      return {\n        replace: true,\n        priority: 0,\n        require: '^uiGrid',\n        scope: false,\n        link: function ($scope, $elm, $attrs, uiGridCtrl) {\n          uiGridSaveStateService.initializeGrid(uiGridCtrl.grid);\n        }\n      };\n    }\n  ]);\n})();\n\n(function () {\n  'use strict';\n\n  /**\n   * @ngdoc overview\n   * @name ui.grid.selection\n   * @description\n   *\n   * # ui.grid.selection\n   * This module provides row selection\n   *\n   * <div class=\"alert alert-success\" role=\"alert\"><strong>Stable</strong> This feature is stable. There should no longer be breaking api changes without a deprecation warning.</div>\n   *\n   * <div doc-module-components=\"ui.grid.selection\"></div>\n   */\n\n  var module = angular.module('ui.grid.selection', ['ui.grid']);\n\n  /**\n   *  @ngdoc object\n   *  @name ui.grid.selection.constant:uiGridSelectionConstants\n   *\n   *  @description constants available in selection module\n   */\n  module.constant('uiGridSelectionConstants', {\n    featureName: \"selection\",\n    selectionRowHeaderColName: 'selectionRowHeaderCol'\n  });\n\n  //add methods to GridRow\n  angular.module('ui.grid').config(['$provide', function($provide) {\n    $provide.decorator('GridRow', ['$delegate', function($delegate) {\n\n      /**\n       *  @ngdoc object\n       *  @name ui.grid.selection.api:GridRow\n       *\n       *  @description GridRow prototype functions added for selection\n       */\n\n      /**\n       *  @ngdoc object\n       *  @name enableSelection\n       *  @propertyOf  ui.grid.selection.api:GridRow\n       *  @description Enable row selection for this row, only settable by internal code.\n       *\n       *  The grouping feature, for example, might set group header rows to not be selectable.\n       *  <br/>Defaults to true\n       */\n\n      /**\n       *  @ngdoc object\n       *  @name isSelected\n       *  @propertyOf  ui.grid.selection.api:GridRow\n       *  @description Selected state of row.  Should be readonly. Make any changes to selected state using setSelected().\n       *  <br/>Defaults to false\n       */\n\n\n        /**\n         * @ngdoc function\n         * @name setSelected\n         * @methodOf ui.grid.selection.api:GridRow\n         * @description Sets the isSelected property and updates the selectedCount\n         * Changes to isSelected state should only be made via this function\n         * @param {bool} selected value to set\n         */\n        $delegate.prototype.setSelected = function(selected) {\n          this.isSelected = selected;\n          if (selected) {\n            this.grid.selection.selectedCount++;\n          }\n          else {\n            this.grid.selection.selectedCount--;\n          }\n        };\n\n      return $delegate;\n    }]);\n  }]);\n\n  /**\n   *  @ngdoc service\n   *  @name ui.grid.selection.service:uiGridSelectionService\n   *\n   *  @description Services for selection features\n   */\n  module.service('uiGridSelectionService', ['$q', '$templateCache', 'uiGridSelectionConstants', 'gridUtil',\n    function ($q, $templateCache, uiGridSelectionConstants, gridUtil) {\n\n      var service = {\n\n        initializeGrid: function (grid) {\n\n          //add feature namespace and any properties to grid for needed\n          /**\n           *  @ngdoc object\n           *  @name ui.grid.selection.grid:selection\n           *\n           *  @description Grid properties and functions added for selection\n           */\n          grid.selection = {};\n          grid.selection.lastSelectedRow = null;\n          grid.selection.selectAll = false;\n\n\n          /**\n           *  @ngdoc object\n           *  @name selectedCount\n           *  @propertyOf  ui.grid.selection.grid:selection\n           *  @description Current count of selected rows\n           *  @example\n           *  var count = grid.selection.selectedCount\n           */\n          grid.selection.selectedCount = 0;\n\n          service.defaultGridOptions(grid.options);\n\n          /**\n           *  @ngdoc object\n           *  @name ui.grid.selection.api:PublicApi\n           *\n           *  @description Public Api for selection feature\n           */\n          var publicApi = {\n            events: {\n              selection: {\n                /**\n                 * @ngdoc event\n                 * @name rowSelectionChanged\n                 * @eventOf  ui.grid.selection.api:PublicApi\n                 * @description  is raised after the row.isSelected state is changed\n                 * @param {GridRow} row the row that was selected/deselected\n                 * @param {Event} event object if raised from an event\n                 */\n                rowSelectionChanged: function (scope, row, evt) {\n                },\n                /**\n                 * @ngdoc event\n                 * @name rowSelectionChangedBatch\n                 * @eventOf  ui.grid.selection.api:PublicApi\n                 * @description  is raised after the row.isSelected state is changed\n                 * in bulk, if the `enableSelectionBatchEvent` option is set to true\n                 * (which it is by default).  This allows more efficient processing\n                 * of bulk events.\n                 * @param {array} rows the rows that were selected/deselected\n                 * @param {Event} event object if raised from an event\n                 */\n                rowSelectionChangedBatch: function (scope, rows, evt) {\n                }\n              }\n            },\n            methods: {\n              selection: {\n                /**\n                 * @ngdoc function\n                 * @name toggleRowSelection\n                 * @methodOf  ui.grid.selection.api:PublicApi\n                 * @description Toggles data row as selected or unselected\n                 * @param {object} rowEntity gridOptions.data[] array instance\n                 * @param {Event} event object if raised from an event\n                 */\n                toggleRowSelection: function (rowEntity, evt) {\n                  var row = grid.getRow(rowEntity);\n                  if (row !== null) {\n                    service.toggleRowSelection(grid, row, evt, grid.options.multiSelect, grid.options.noUnselect);\n                  }\n                },\n                /**\n                 * @ngdoc function\n                 * @name selectRow\n                 * @methodOf  ui.grid.selection.api:PublicApi\n                 * @description Select the data row\n                 * @param {object} rowEntity gridOptions.data[] array instance\n                 * @param {Event} event object if raised from an event\n                 */\n                selectRow: function (rowEntity, evt) {\n                  var row = grid.getRow(rowEntity);\n                  if (row !== null && !row.isSelected) {\n                    service.toggleRowSelection(grid, row, evt, grid.options.multiSelect, grid.options.noUnselect);\n                  }\n                },\n                /**\n                 * @ngdoc function\n                 * @name selectRowByVisibleIndex\n                 * @methodOf  ui.grid.selection.api:PublicApi\n                 * @description Select the specified row by visible index (i.e. if you\n                 * specify row 0 you'll get the first visible row selected).  In this context\n                 * visible means of those rows that are theoretically visible (i.e. not filtered),\n                 * rather than rows currently rendered on the screen.\n                 * @param {number} index index within the rowsVisible array\n                 * @param {Event} event object if raised from an event\n                 */\n                selectRowByVisibleIndex: function ( rowNum, evt ) {\n                  var row = grid.renderContainers.body.visibleRowCache[rowNum];\n                  if (row !== null && typeof(row) !== 'undefined' && !row.isSelected) {\n                    service.toggleRowSelection(grid, row, evt, grid.options.multiSelect, grid.options.noUnselect);\n                  }\n                },\n                /**\n                 * @ngdoc function\n                 * @name unSelectRow\n                 * @methodOf  ui.grid.selection.api:PublicApi\n                 * @description UnSelect the data row\n                 * @param {object} rowEntity gridOptions.data[] array instance\n                 * @param {Event} event object if raised from an event\n                 */\n                unSelectRow: function (rowEntity, evt) {\n                  var row = grid.getRow(rowEntity);\n                  if (row !== null && row.isSelected) {\n                    service.toggleRowSelection(grid, row, evt, grid.options.multiSelect, grid.options.noUnselect);\n                  }\n                },\n                /**\n                 * @ngdoc function\n                 * @name selectAllRows\n                 * @methodOf  ui.grid.selection.api:PublicApi\n                 * @description Selects all rows.  Does nothing if multiSelect = false\n                 * @param {Event} event object if raised from an event\n                 */\n                selectAllRows: function (evt) {\n                  if (grid.options.multiSelect === false) {\n                    return;\n                  }\n\n                  var changedRows = [];\n                  grid.rows.forEach(function (row) {\n                    if ( !row.isSelected && row.enableSelection !== false ){\n                      row.setSelected(true);\n                      service.decideRaiseSelectionEvent( grid, row, changedRows, evt );\n                    }\n                  });\n                  service.decideRaiseSelectionBatchEvent( grid, changedRows, evt );\n                  grid.selection.selectAll = true;\n                },\n                /**\n                 * @ngdoc function\n                 * @name selectAllVisibleRows\n                 * @methodOf  ui.grid.selection.api:PublicApi\n                 * @description Selects all visible rows.  Does nothing if multiSelect = false\n                 * @param {Event} event object if raised from an event\n                 */\n                selectAllVisibleRows: function (evt) {\n                  if (grid.options.multiSelect === false) {\n                    return;\n                  }\n\n                  var changedRows = [];\n                  grid.rows.forEach(function (row) {\n                    if (row.visible) {\n                      if (!row.isSelected && row.enableSelection !== false){\n                        row.setSelected(true);\n                        service.decideRaiseSelectionEvent( grid, row, changedRows, evt );\n                      }\n                    } else {\n                      if (row.isSelected){\n                        row.setSelected(false);\n                        service.decideRaiseSelectionEvent( grid, row, changedRows, evt );\n                      }\n                    }\n                  });\n                  service.decideRaiseSelectionBatchEvent( grid, changedRows, evt );\n                  grid.selection.selectAll = true;\n                },\n                /**\n                 * @ngdoc function\n                 * @name clearSelectedRows\n                 * @methodOf  ui.grid.selection.api:PublicApi\n                 * @description Unselects all rows\n                 * @param {Event} event object if raised from an event\n                 */\n                clearSelectedRows: function (evt) {\n                  service.clearSelectedRows(grid, evt);\n                },\n                /**\n                 * @ngdoc function\n                 * @name getSelectedRows\n                 * @methodOf  ui.grid.selection.api:PublicApi\n                 * @description returns all selectedRow's entity references\n                 */\n                getSelectedRows: function () {\n                  return service.getSelectedRows(grid).map(function (gridRow) {\n                    return gridRow.entity;\n                  });\n                },\n                /**\n                 * @ngdoc function\n                 * @name getSelectedGridRows\n                 * @methodOf  ui.grid.selection.api:PublicApi\n                 * @description returns all selectedRow's as gridRows\n                 */\n                getSelectedGridRows: function () {\n                  return service.getSelectedRows(grid);\n                },\n                /**\n                 * @ngdoc function\n                 * @name setMultiSelect\n                 * @methodOf  ui.grid.selection.api:PublicApi\n                 * @description Sets the current gridOption.multiSelect to true or false\n                 * @param {bool} multiSelect true to allow multiple rows\n                 */\n                setMultiSelect: function (multiSelect) {\n                  grid.options.multiSelect = multiSelect;\n                },\n                /**\n                 * @ngdoc function\n                 * @name setModifierKeysToMultiSelect\n                 * @methodOf  ui.grid.selection.api:PublicApi\n                 * @description Sets the current gridOption.modifierKeysToMultiSelect to true or false\n                 * @param {bool} modifierKeysToMultiSelect true to only allow multiple rows when using ctrlKey or shiftKey is used\n                 */\n                setModifierKeysToMultiSelect: function (modifierKeysToMultiSelect) {\n                  grid.options.modifierKeysToMultiSelect = modifierKeysToMultiSelect;\n                },\n                /**\n                 * @ngdoc function\n                 * @name getSelectAllState\n                 * @methodOf  ui.grid.selection.api:PublicApi\n                 * @description Returns whether or not the selectAll checkbox is currently ticked.  The\n                 * grid doesn't automatically select rows when you add extra data - so when you add data\n                 * you need to explicitly check whether the selectAll is set, and then call setVisible rows\n                 * if it is\n                 */\n                getSelectAllState: function () {\n                  return grid.selection.selectAll;\n                }\n\n              }\n            }\n          };\n\n          grid.api.registerEventsFromObject(publicApi.events);\n\n          grid.api.registerMethodsFromObject(publicApi.methods);\n\n        },\n\n        defaultGridOptions: function (gridOptions) {\n          //default option to true unless it was explicitly set to false\n          /**\n           *  @ngdoc object\n           *  @name ui.grid.selection.api:GridOptions\n           *\n           *  @description GridOptions for selection feature, these are available to be\n           *  set using the ui-grid {@link ui.grid.class:GridOptions gridOptions}\n           */\n\n          /**\n           *  @ngdoc object\n           *  @name enableRowSelection\n           *  @propertyOf  ui.grid.selection.api:GridOptions\n           *  @description Enable row selection for entire grid.\n           *  <br/>Defaults to true\n           */\n          gridOptions.enableRowSelection = gridOptions.enableRowSelection !== false;\n          /**\n           *  @ngdoc object\n           *  @name multiSelect\n           *  @propertyOf  ui.grid.selection.api:GridOptions\n           *  @description Enable multiple row selection for entire grid\n           *  <br/>Defaults to true\n           */\n          gridOptions.multiSelect = gridOptions.multiSelect !== false;\n          /**\n           *  @ngdoc object\n           *  @name noUnselect\n           *  @propertyOf  ui.grid.selection.api:GridOptions\n           *  @description Prevent a row from being unselected.  Works in conjunction\n           *  with `multiselect = false` and `gridApi.selection.selectRow()` to allow\n           *  you to create a single selection only grid - a row is always selected, you\n           *  can only select different rows, you can't unselect the row.\n           *  <br/>Defaults to false\n           */\n          gridOptions.noUnselect = gridOptions.noUnselect === true;\n          /**\n           *  @ngdoc object\n           *  @name modifierKeysToMultiSelect\n           *  @propertyOf  ui.grid.selection.api:GridOptions\n           *  @description Enable multiple row selection only when using the ctrlKey or shiftKey. Requires multiSelect to be true.\n           *  <br/>Defaults to false\n           */\n          gridOptions.modifierKeysToMultiSelect = gridOptions.modifierKeysToMultiSelect === true;\n          /**\n           *  @ngdoc object\n           *  @name enableRowHeaderSelection\n           *  @propertyOf  ui.grid.selection.api:GridOptions\n           *  @description Enable a row header to be used for selection\n           *  <br/>Defaults to true\n           */\n          gridOptions.enableRowHeaderSelection = gridOptions.enableRowHeaderSelection !== false;\n          /**\n           *  @ngdoc object\n           *  @name enableFullRowSelection\n           *  @propertyOf  ui.grid.selection.api:GridOptions\n           *  @description Enable selection by clicking anywhere on the row.  Defaults to\n           *  false if `enableRowHeaderSelection` is true, otherwise defaults to false.\n           */\n          if ( typeof(gridOptions.enableFullRowSelection) === 'undefined' ){\n            gridOptions.enableFullRowSelection = !gridOptions.enableRowHeaderSelection;\n          }\n          /**\n           *  @ngdoc object\n           *  @name enableSelectAll\n           *  @propertyOf  ui.grid.selection.api:GridOptions\n           *  @description Enable the select all checkbox at the top of the selectionRowHeader\n           *  <br/>Defaults to true\n           */\n          gridOptions.enableSelectAll = gridOptions.enableSelectAll !== false;\n          /**\n           *  @ngdoc object\n           *  @name enableSelectionBatchEvent\n           *  @propertyOf  ui.grid.selection.api:GridOptions\n           *  @description If selected rows are changed in bulk, either via the API or\n           *  via the selectAll checkbox, then a separate event is fired.  Setting this\n           *  option to false will cause the rowSelectionChanged event to be called multiple times\n           *  instead\n           *  <br/>Defaults to true\n           */\n          gridOptions.enableSelectionBatchEvent = gridOptions.enableSelectionBatchEvent !== false;\n          /**\n           *  @ngdoc object\n           *  @name selectionRowHeaderWidth\n           *  @propertyOf  ui.grid.selection.api:GridOptions\n           *  @description can be used to set a custom width for the row header selection column\n           *  <br/>Defaults to 30px\n           */\n          gridOptions.selectionRowHeaderWidth = angular.isDefined(gridOptions.selectionRowHeaderWidth) ? gridOptions.selectionRowHeaderWidth : 30;\n\n          /**\n           *  @ngdoc object\n           *  @name enableFooterTotalSelected\n           *  @propertyOf  ui.grid.selection.api:GridOptions\n           *  @description Shows the total number of selected items in footer if true.\n           *  <br/>Defaults to true.\n           *  <br/>GridOptions.showGridFooter must also be set to true.\n           */\n          gridOptions.enableFooterTotalSelected = gridOptions.enableFooterTotalSelected !== false;\n\n          /**\n           *  @ngdoc object\n           *  @name isRowSelectable\n           *  @propertyOf  ui.grid.selection.api:GridOptions\n           *  @description Makes it possible to specify a method that evaluates for each row and sets its \"enableSelection\" property.\n           */\n\n          gridOptions.isRowSelectable = angular.isDefined(gridOptions.isRowSelectable) ? gridOptions.isRowSelectable : angular.noop;\n        },\n\n        /**\n         * @ngdoc function\n         * @name toggleRowSelection\n         * @methodOf  ui.grid.selection.service:uiGridSelectionService\n         * @description Toggles row as selected or unselected\n         * @param {Grid} grid grid object\n         * @param {GridRow} row row to select or deselect\n         * @param {Event} event object if resulting from event\n         * @param {bool} multiSelect if false, only one row at time can be selected\n         * @param {bool} noUnselect if true then rows cannot be unselected\n         */\n        toggleRowSelection: function (grid, row, evt, multiSelect, noUnselect) {\n          var selected = row.isSelected;\n\n          if ( row.enableSelection === false && !selected ){\n            return;\n          }\n\n          if (!multiSelect && !selected) {\n            service.clearSelectedRows(grid, evt);\n          } else if (!multiSelect && selected) {\n            var selectedRows = service.getSelectedRows(grid);\n            if (selectedRows.length > 1) {\n              selected = false; // Enable reselect of the row\n              service.clearSelectedRows(grid, evt);\n            }\n          }\n\n          if (selected && noUnselect){\n            // don't deselect the row\n          } else {\n            row.setSelected(!selected);\n            if (row.isSelected === true) {\n              grid.selection.lastSelectedRow = row;\n            } else {\n              grid.selection.selectAll = false;\n            }\n            grid.api.selection.raise.rowSelectionChanged(row, evt);\n          }\n        },\n        /**\n         * @ngdoc function\n         * @name shiftSelect\n         * @methodOf  ui.grid.selection.service:uiGridSelectionService\n         * @description selects a group of rows from the last selected row using the shift key\n         * @param {Grid} grid grid object\n         * @param {GridRow} clicked row\n         * @param {Event} event object if raised from an event\n         * @param {bool} multiSelect if false, does nothing this is for multiSelect only\n         */\n        shiftSelect: function (grid, row, evt, multiSelect) {\n          if (!multiSelect) {\n            return;\n          }\n          var selectedRows = service.getSelectedRows(grid);\n          var fromRow = selectedRows.length > 0 ? grid.renderContainers.body.visibleRowCache.indexOf(grid.selection.lastSelectedRow) : 0;\n          var toRow = grid.renderContainers.body.visibleRowCache.indexOf(row);\n          //reverse select direction\n          if (fromRow > toRow) {\n            var tmp = fromRow;\n            fromRow = toRow;\n            toRow = tmp;\n          }\n\n          var changedRows = [];\n          for (var i = fromRow; i <= toRow; i++) {\n            var rowToSelect = grid.renderContainers.body.visibleRowCache[i];\n            if (rowToSelect) {\n              if ( !rowToSelect.isSelected && rowToSelect.enableSelection !== false ){\n                rowToSelect.setSelected(true);\n                grid.selection.lastSelectedRow = rowToSelect;\n                service.decideRaiseSelectionEvent( grid, rowToSelect, changedRows, evt );\n              }\n            }\n          }\n          service.decideRaiseSelectionBatchEvent( grid, changedRows, evt );\n        },\n        /**\n         * @ngdoc function\n         * @name getSelectedRows\n         * @methodOf  ui.grid.selection.service:uiGridSelectionService\n         * @description Returns all the selected rows\n         * @param {Grid} grid grid object\n         */\n        getSelectedRows: function (grid) {\n          return grid.rows.filter(function (row) {\n            return row.isSelected;\n          });\n        },\n\n        /**\n         * @ngdoc function\n         * @name clearSelectedRows\n         * @methodOf  ui.grid.selection.service:uiGridSelectionService\n         * @description Clears all selected rows\n         * @param {Grid} grid grid object\n         * @param {Event} event object if raised from an event\n         */\n        clearSelectedRows: function (grid, evt) {\n          var changedRows = [];\n          service.getSelectedRows(grid).forEach(function (row) {\n            if ( row.isSelected ){\n              row.setSelected(false);\n              service.decideRaiseSelectionEvent( grid, row, changedRows, evt );\n            }\n          });\n          service.decideRaiseSelectionBatchEvent( grid, changedRows, evt );\n          grid.selection.selectAll = false;\n        },\n\n        /**\n         * @ngdoc function\n         * @name decideRaiseSelectionEvent\n         * @methodOf  ui.grid.selection.service:uiGridSelectionService\n         * @description Decides whether to raise a single event or a batch event\n         * @param {Grid} grid grid object\n         * @param {GridRow} row row that has changed\n         * @param {array} changedRows an array to which we can append the changed\n         * @param {Event} event object if raised from an event\n         * row if we're doing batch events\n         */\n        decideRaiseSelectionEvent: function( grid, row, changedRows, evt ){\n          if ( !grid.options.enableSelectionBatchEvent ){\n            grid.api.selection.raise.rowSelectionChanged(row, evt);\n          } else {\n            changedRows.push(row);\n          }\n        },\n\n        /**\n         * @ngdoc function\n         * @name raiseSelectionEvent\n         * @methodOf  ui.grid.selection.service:uiGridSelectionService\n         * @description Decides whether we need to raise a batch event, and\n         * raises it if we do.\n         * @param {Grid} grid grid object\n         * @param {array} changedRows an array of changed rows, only populated\n         * @param {Event} event object if raised from an event\n         * if we're doing batch events\n         */\n        decideRaiseSelectionBatchEvent: function( grid, changedRows, evt ){\n          if ( changedRows.length > 0 ){\n            grid.api.selection.raise.rowSelectionChangedBatch(changedRows, evt);\n          }\n        }\n      };\n\n      return service;\n\n    }]);\n\n  /**\n   *  @ngdoc directive\n   *  @name ui.grid.selection.directive:uiGridSelection\n   *  @element div\n   *  @restrict A\n   *\n   *  @description Adds selection features to grid\n   *\n   *  @example\n   <example module=\"app\">\n   <file name=\"app.js\">\n   var app = angular.module('app', ['ui.grid', 'ui.grid.selection']);\n\n   app.controller('MainCtrl', ['$scope', function ($scope) {\n      $scope.data = [\n        { name: 'Bob', title: 'CEO' },\n            { name: 'Frank', title: 'Lowly Developer' }\n      ];\n\n      $scope.columnDefs = [\n        {name: 'name', enableCellEdit: true},\n        {name: 'title', enableCellEdit: true}\n      ];\n    }]);\n   </file>\n   <file name=\"index.html\">\n   <div ng-controller=\"MainCtrl\">\n   <div ui-grid=\"{ data: data, columnDefs: columnDefs }\" ui-grid-selection></div>\n   </div>\n   </file>\n   </example>\n   */\n  module.directive('uiGridSelection', ['uiGridSelectionConstants', 'uiGridSelectionService', '$templateCache', 'uiGridConstants',\n    function (uiGridSelectionConstants, uiGridSelectionService, $templateCache, uiGridConstants) {\n      return {\n        replace: true,\n        priority: 0,\n        require: '^uiGrid',\n        scope: false,\n        compile: function () {\n          return {\n            pre: function ($scope, $elm, $attrs, uiGridCtrl) {\n              uiGridSelectionService.initializeGrid(uiGridCtrl.grid);\n              if (uiGridCtrl.grid.options.enableRowHeaderSelection) {\n                var selectionRowHeaderDef = {\n                  name: uiGridSelectionConstants.selectionRowHeaderColName,\n                  displayName: '',\n                  width:  uiGridCtrl.grid.options.selectionRowHeaderWidth,\n                  minWidth: 10,\n                  cellTemplate: 'ui-grid/selectionRowHeader',\n                  headerCellTemplate: 'ui-grid/selectionHeaderCell',\n                  enableColumnResizing: false,\n                  enableColumnMenu: false,\n                  exporterSuppressExport: true,\n                  allowCellFocus: true\n                };\n\n                uiGridCtrl.grid.addRowHeaderColumn(selectionRowHeaderDef);\n              }\n\n              var processorSet = false;\n\n              var processSelectableRows = function( rows ){\n                rows.forEach(function(row){\n                  row.enableSelection = uiGridCtrl.grid.options.isRowSelectable(row);\n                });\n                return rows;\n              };\n\n              var updateOptions = function(){\n                if (uiGridCtrl.grid.options.isRowSelectable !== angular.noop && processorSet !== true) {\n                  uiGridCtrl.grid.registerRowsProcessor(processSelectableRows, 500);\n                  processorSet = true;\n                }\n              };\n\n              updateOptions();\n\n              var dataChangeDereg = uiGridCtrl.grid.registerDataChangeCallback( updateOptions, [uiGridConstants.dataChange.OPTIONS] );\n\n              $scope.$on( '$destroy', dataChangeDereg);\n            },\n            post: function ($scope, $elm, $attrs, uiGridCtrl) {\n\n            }\n          };\n        }\n      };\n    }]);\n\n  module.directive('uiGridSelectionRowHeaderButtons', ['$templateCache', 'uiGridSelectionService', 'gridUtil',\n    function ($templateCache, uiGridSelectionService, gridUtil) {\n      return {\n        replace: true,\n        restrict: 'E',\n        template: $templateCache.get('ui-grid/selectionRowHeaderButtons'),\n        scope: true,\n        require: '^uiGrid',\n        link: function($scope, $elm, $attrs, uiGridCtrl) {\n          var self = uiGridCtrl.grid;\n          $scope.selectButtonClick = selectButtonClick;\n\n          // On IE, prevent mousedowns on the select button from starting a selection.\n          //   If this is not done and you shift+click on another row, the browser will select a big chunk of text\n          if (gridUtil.detectBrowser() === 'ie') {\n            $elm.on('mousedown', selectButtonMouseDown);\n          }\n\n\n          function selectButtonClick(row, evt) {\n            evt.stopPropagation();\n\n            if (evt.shiftKey) {\n              uiGridSelectionService.shiftSelect(self, row, evt, self.options.multiSelect);\n            }\n            else if (evt.ctrlKey || evt.metaKey) {\n              uiGridSelectionService.toggleRowSelection(self, row, evt, self.options.multiSelect, self.options.noUnselect);\n            }\n            else {\n              uiGridSelectionService.toggleRowSelection(self, row, evt, (self.options.multiSelect && !self.options.modifierKeysToMultiSelect), self.options.noUnselect);\n            }\n          }\n\n          function selectButtonMouseDown(evt) {\n            if (evt.ctrlKey || evt.shiftKey) {\n              evt.target.onselectstart = function () { return false; };\n              window.setTimeout(function () { evt.target.onselectstart = null; }, 0);\n            }\n          }\n        }\n      };\n    }]);\n\n  module.directive('uiGridSelectionSelectAllButtons', ['$templateCache', 'uiGridSelectionService',\n    function ($templateCache, uiGridSelectionService) {\n      return {\n        replace: true,\n        restrict: 'E',\n        template: $templateCache.get('ui-grid/selectionSelectAllButtons'),\n        scope: false,\n        link: function($scope, $elm, $attrs, uiGridCtrl) {\n          var self = $scope.col.grid;\n\n          $scope.headerButtonClick = function(row, evt) {\n            if ( self.selection.selectAll ){\n              uiGridSelectionService.clearSelectedRows(self, evt);\n              if ( self.options.noUnselect ){\n                self.api.selection.selectRowByVisibleIndex(0, evt);\n              }\n              self.selection.selectAll = false;\n            } else {\n              if ( self.options.multiSelect ){\n                self.api.selection.selectAllVisibleRows(evt);\n                self.selection.selectAll = true;\n              }\n            }\n          };\n        }\n      };\n    }]);\n\n  /**\n   *  @ngdoc directive\n   *  @name ui.grid.selection.directive:uiGridViewport\n   *  @element div\n   *\n   *  @description Stacks on top of ui.grid.uiGridViewport to alter the attributes used\n   *  for the grid row\n   */\n  module.directive('uiGridViewport',\n    ['$compile', 'uiGridConstants', 'uiGridSelectionConstants', 'gridUtil', '$parse', 'uiGridSelectionService',\n      function ($compile, uiGridConstants, uiGridSelectionConstants, gridUtil, $parse, uiGridSelectionService) {\n        return {\n          priority: -200, // run after default  directive\n          scope: false,\n          compile: function ($elm, $attrs) {\n            var rowRepeatDiv = angular.element($elm.children().children()[0]);\n\n            var existingNgClass = rowRepeatDiv.attr(\"ng-class\");\n            var newNgClass = '';\n            if ( existingNgClass ) {\n              newNgClass = existingNgClass.slice(0, -1) + \",'ui-grid-row-selected': row.isSelected}\";\n            } else {\n              newNgClass = \"{'ui-grid-row-selected': row.isSelected}\";\n            }\n            rowRepeatDiv.attr(\"ng-class\", newNgClass);\n\n            return {\n              pre: function ($scope, $elm, $attrs, controllers) {\n\n              },\n              post: function ($scope, $elm, $attrs, controllers) {\n              }\n            };\n          }\n        };\n      }]);\n\n  /**\n   *  @ngdoc directive\n   *  @name ui.grid.selection.directive:uiGridCell\n   *  @element div\n   *  @restrict A\n   *\n   *  @description Stacks on top of ui.grid.uiGridCell to provide selection feature\n   */\n  module.directive('uiGridCell',\n    ['$compile', 'uiGridConstants', 'uiGridSelectionConstants', 'gridUtil', '$parse', 'uiGridSelectionService', '$timeout',\n      function ($compile, uiGridConstants, uiGridSelectionConstants, gridUtil, $parse, uiGridSelectionService, $timeout) {\n        return {\n          priority: -200, // run after default uiGridCell directive\n          restrict: 'A',\n          require: '?^uiGrid',\n          scope: false,\n          link: function ($scope, $elm, $attrs, uiGridCtrl) {\n\n            var touchStartTime = 0;\n            var touchTimeout = 300;\n\n            // Bind to keydown events in the render container\n            if (uiGridCtrl.grid.api.cellNav) {\n\n              uiGridCtrl.grid.api.cellNav.on.viewPortKeyDown($scope, function (evt, rowCol) {\n                if (rowCol === null ||\n                  rowCol.row !== $scope.row ||\n                  rowCol.col !== $scope.col) {\n                  return;\n                }\n\n                if (evt.keyCode === 32 && $scope.col.colDef.name === \"selectionRowHeaderCol\") {\n                  uiGridSelectionService.toggleRowSelection($scope.grid, $scope.row, evt, ($scope.grid.options.multiSelect && !$scope.grid.options.modifierKeysToMultiSelect), $scope.grid.options.noUnselect);\n                  $scope.$apply();\n                }\n\n              //  uiGridCellNavService.scrollToIfNecessary(uiGridCtrl.grid, rowCol.row, rowCol.col);\n              });\n            }\n\n            //$elm.bind('keydown', function (evt) {\n            //  if (evt.keyCode === 32 && $scope.col.colDef.name === \"selectionRowHeaderCol\") {\n            //    uiGridSelectionService.toggleRowSelection($scope.grid, $scope.row, evt, ($scope.grid.options.multiSelect && !$scope.grid.options.modifierKeysToMultiSelect), $scope.grid.options.noUnselect);\n            //    $scope.$apply();\n            //  }\n            //});\n\n            var selectCells = function(evt){\n              // if we get a click, then stop listening for touchend\n              $elm.off('touchend', touchEnd);\n\n              if (evt.shiftKey) {\n                uiGridSelectionService.shiftSelect($scope.grid, $scope.row, evt, $scope.grid.options.multiSelect);\n              }\n              else if (evt.ctrlKey || evt.metaKey) {\n                uiGridSelectionService.toggleRowSelection($scope.grid, $scope.row, evt, $scope.grid.options.multiSelect, $scope.grid.options.noUnselect);\n              }\n              else {\n                uiGridSelectionService.toggleRowSelection($scope.grid, $scope.row, evt, ($scope.grid.options.multiSelect && !$scope.grid.options.modifierKeysToMultiSelect), $scope.grid.options.noUnselect);\n              }\n              $scope.$apply();\n\n              // don't re-enable the touchend handler for a little while - some devices generate both, and it will\n              // take a little while to move your hand from the mouse to the screen if you have both modes of input\n              $timeout(function() {\n                $elm.on('touchend', touchEnd);\n              }, touchTimeout);\n            };\n\n            var touchStart = function(evt){\n              touchStartTime = (new Date()).getTime();\n\n              // if we get a touch event, then stop listening for click\n              $elm.off('click', selectCells);\n            };\n\n            var touchEnd = function(evt) {\n              var touchEndTime = (new Date()).getTime();\n              var touchTime = touchEndTime - touchStartTime;\n\n              if (touchTime < touchTimeout ) {\n                // short touch\n                selectCells(evt);\n              }\n\n              // don't re-enable the click handler for a little while - some devices generate both, and it will\n              // take a little while to move your hand from the screen to the mouse if you have both modes of input\n              $timeout(function() {\n                $elm.on('click', selectCells);\n              }, touchTimeout);\n            };\n\n            function registerRowSelectionEvents() {\n              if ($scope.grid.options.enableRowSelection && $scope.grid.options.enableFullRowSelection) {\n                $elm.addClass('ui-grid-disable-selection');\n                $elm.on('touchstart', touchStart);\n                $elm.on('touchend', touchEnd);\n                $elm.on('click', selectCells);\n\n                $scope.registered = true;\n              }\n            }\n\n            function deregisterRowSelectionEvents() {\n              if ($scope.registered){\n                $elm.removeClass('ui-grid-disable-selection');\n\n                $elm.off('touchstart', touchStart);\n                $elm.off('touchend', touchEnd);\n                $elm.off('click', selectCells);\n\n                $scope.registered = false;\n              }\n            }\n\n            registerRowSelectionEvents();\n            // register a dataChange callback so that we can change the selection configuration dynamically\n            // if the user changes the options\n            var dataChangeDereg = $scope.grid.registerDataChangeCallback( function() {\n              if ( $scope.grid.options.enableRowSelection && $scope.grid.options.enableFullRowSelection &&\n                !$scope.registered ){\n                registerRowSelectionEvents();\n              } else if ( ( !$scope.grid.options.enableRowSelection || !$scope.grid.options.enableFullRowSelection ) &&\n                $scope.registered ){\n                deregisterRowSelectionEvents();\n              }\n            }, [uiGridConstants.dataChange.OPTIONS] );\n\n            $elm.on( '$destroy', dataChangeDereg);\n          }\n        };\n      }]);\n\n  module.directive('uiGridGridFooter', ['$compile', 'uiGridConstants', 'gridUtil', function ($compile, uiGridConstants, gridUtil) {\n    return {\n      restrict: 'EA',\n      replace: true,\n      priority: -1000,\n      require: '^uiGrid',\n      scope: true,\n      compile: function ($elm, $attrs) {\n        return {\n          pre: function ($scope, $elm, $attrs, uiGridCtrl) {\n\n            if (!uiGridCtrl.grid.options.showGridFooter) {\n              return;\n            }\n\n\n            gridUtil.getTemplate('ui-grid/gridFooterSelectedItems')\n              .then(function (contents) {\n                var template = angular.element(contents);\n\n                var newElm = $compile(template)($scope);\n\n                angular.element($elm[0].getElementsByClassName('ui-grid-grid-footer')[0]).append(newElm);\n              });\n          },\n\n          post: function ($scope, $elm, $attrs, controllers) {\n\n          }\n        };\n      }\n    };\n  }]);\n\n})();\n\n(function () {\n  'use strict';\n\n  /**\n   * @ngdoc overview\n   * @name ui.grid.treeBase\n   * @description\n   *\n   * # ui.grid.treeBase\n   *\n   * <div class=\"alert alert-warning\" role=\"alert\"><strong>Beta</strong> This feature is ready for testing, but it either hasn't seen a lot of use or has some known bugs.</div>\n   *\n   * This module provides base tree handling functions that are shared by other features, notably grouping\n   * and treeView.  It provides a tree view of the data, with nodes in that\n   * tree and leaves.\n   *\n   * Design information:\n   * -------------------\n   *\n   * The raw data that is provided must come with a $$treeLevel on any non-leaf node.  Grouping will create\n   * these on all the group header rows, treeView will expect these to be set in the raw data by the user.\n   * TreeBase will run a rowsProcessor that:\n   *  - builds `treeBase.tree` out of the provided rows\n   *  - permits a recursive sort of the tree\n   *  - maintains the expand/collapse state of each node\n   *  - provides the expand/collapse all button and the expand/collapse buttons\n   *  - maintains the count of children for each node\n   *\n   * Each row is updated with a link to the tree node that represents it.  Refer {@link ui.grid.treeBase.grid:treeBase.tree tree documentation}\n   * for information.\n   *\n   *  TreeBase adds information to the rows\n   *  - treeLevel: if present and > -1 tells us the level (level 0 is the top level)\n   *  - treeNode: pointer to the node in the grid.treeBase.tree that refers\n   *    to this row, allowing us to manipulate the state\n   *\n   * Since the logic is baked into the rowsProcessors, it should get triggered whenever\n   * row order or filtering or anything like that is changed.  We recall the expanded state\n   * across invocations of the rowsProcessors by the reference to the treeNode on the individual\n   * rows.  We rebuild the tree itself quite frequently, when we do this we use the saved treeNodes to\n   * get the state, but we overwrite the other data in that treeNode.\n   *\n   * By default rows are collapsed, which means all data rows have their visible property\n   * set to false, and only level 0 group rows are set to visible.\n   *\n   * We rely on the rowsProcessors to do the actual expanding and collapsing, so we set the flags we want into\n   * grid.treeBase.tree, then call refresh.  This is because we can't easily change the visible\n   * row cache without calling the processors, and once we've built the logic into the rowProcessors we may as\n   * well use it all the time.\n   *\n   * Tree base provides sorting (on non-grouped columns).\n   *\n   * Sorting works in two passes.  The standard sorting is performed for any columns that are important to building\n   * the tree (for example, any grouped columns).  Then after the tree is built, a recursive tree sort is performed\n   * for the remaining sort columns (including the original sort) - these columns are sorted within each tree level\n   * (so all the level 1 nodes are sorted, then all the level 2 nodes within each level 1 node etc).\n   *\n   * To achieve this we make use of the `ignoreSort` property on the sort configuration.  The parent feature (treeView or grouping)\n   * must provide a rowsProcessor that runs with very low priority (typically in the 60-65 range), and that sets\n   * the `ignoreSort`on any sort that it wants to run on the tree.  TreeBase will clear the ignoreSort on all sorts - so it\n   * will turn on any sorts that haven't run.  It will then call a recursive sort on the tree.\n   *\n   * Tree base provides treeAggregation.  It checks the treeAggregation configuration on each column, and aggregates based on\n   * the logic provided as it builds the tree. Footer aggregation from the uiGrid core should not be used with treeBase aggregation,\n   * since it operates on all visible rows, as opposed to to leaf nodes only. Setting `showColumnFooter: true` will show the\n   * treeAggregations in the column footer.  Aggregation information will be collected in the format:\n   *\n   * ```\n   *   {\n   *     type: 'count',\n   *     value: 4,\n   *     label: 'count: ',\n   *     rendered: 'count: 4'\n   *   }\n   * ```\n   *\n   * A callback is provided to format the value once it is finalised (aka a valueFilter).\n   *\n   * <br/>\n   * <br/>\n   *\n   * <div doc-module-components=\"ui.grid.treeBase\"></div>\n   */\n\n  var module = angular.module('ui.grid.treeBase', ['ui.grid']);\n\n  /**\n   *  @ngdoc object\n   *  @name ui.grid.treeBase.constant:uiGridTreeBaseConstants\n   *\n   *  @description constants available in treeBase module.\n   *\n   *  These constants are manually copied into grouping and treeView,\n   *  as I haven't found a way to simply include them, and it's not worth\n   *  investing time in for something that changes very infrequently.\n   *\n   */\n  module.constant('uiGridTreeBaseConstants', {\n    featureName: \"treeBase\",\n    rowHeaderColName: 'treeBaseRowHeaderCol',\n    EXPANDED: 'expanded',\n    COLLAPSED: 'collapsed',\n    aggregation: {\n      COUNT: 'count',\n      SUM: 'sum',\n      MAX: 'max',\n      MIN: 'min',\n      AVG: 'avg'\n    }\n  });\n\n  /**\n   *  @ngdoc service\n   *  @name ui.grid.treeBase.service:uiGridTreeBaseService\n   *\n   *  @description Services for treeBase feature\n   */\n  /**\n   *  @ngdoc object\n   *  @name ui.grid.treeBase.api:ColumnDef\n   *\n   *  @description ColumnDef for tree feature, these are available to be\n   *  set using the ui-grid {@link ui.grid.class:GridOptions.columnDef gridOptions.columnDefs}\n   */\n\n  module.service('uiGridTreeBaseService', ['$q', 'uiGridTreeBaseConstants', 'gridUtil', 'GridRow', 'gridClassFactory', 'i18nService', 'uiGridConstants', 'rowSorter',\n  function ($q, uiGridTreeBaseConstants, gridUtil, GridRow, gridClassFactory, i18nService, uiGridConstants, rowSorter) {\n\n    var service = {\n\n      initializeGrid: function (grid, $scope) {\n\n        //add feature namespace and any properties to grid for needed\n        /**\n         *  @ngdoc object\n         *  @name ui.grid.treeBase.grid:treeBase\n         *\n         *  @description Grid properties and functions added for treeBase\n         */\n        grid.treeBase = {};\n\n        /**\n         *  @ngdoc property\n         *  @propertyOf ui.grid.treeBase.grid:treeBase\n         *  @name numberLevels\n         *\n         *  @description Total number of tree levels currently used, calculated by the rowsProcessor by\n         *  retaining the highest tree level it sees\n         */\n        grid.treeBase.numberLevels = 0;\n\n        /**\n         *  @ngdoc property\n         *  @propertyOf ui.grid.treeBase.grid:treeBase\n         *  @name expandAll\n         *\n         *  @description Whether or not the expandAll box is selected\n         */\n        grid.treeBase.expandAll = false;\n\n        /**\n         *  @ngdoc property\n         *  @propertyOf ui.grid.treeBase.grid:treeBase\n         *  @name tree\n         *\n         *  @description Tree represented as a nested array that holds the state of each node, along with a\n         *  pointer to the row.  The array order is material - we will display the children in the order\n         *  they are stored in the array\n         *\n         *  Each node stores:\n         *\n         *    - the state of this node\n         *    - an array of children of this node\n         *    - a pointer to the parent of this node (reverse pointer, allowing us to walk up the tree)\n         *    - the number of children of this node\n         *    - aggregation information calculated from the nodes\n         *\n         *  ```\n         *    [{\n         *      state: 'expanded',\n         *      row: <reference to row>,\n         *      parentRow: null,\n         *      aggregations: [{\n         *        type: 'count',\n         *        col: <gridCol>,\n         *        value: 2,\n         *        label: 'count: ',\n         *        rendered: 'count: 2'\n         *      }],\n         *      children: [\n         *        {\n         *          state: 'expanded',\n         *          row: <reference to row>,\n         *          parentRow: <reference to row>,\n         *          aggregations: [{\n         *            type: 'count',\n         *            col: '<gridCol>,\n         *            value: 4,\n         *            label: 'count: ',\n         *            rendered: 'count: 4'\n         *          }],\n         *          children: [\n         *            { state: 'expanded', row: <reference to row>, parentRow: <reference to row> },\n         *            { state: 'collapsed', row: <reference to row>, parentRow: <reference to row> },\n         *            { state: 'expanded', row: <reference to row>, parentRow: <reference to row> },\n         *            { state: 'collapsed', row: <reference to row>, parentRow: <reference to row> }\n         *          ]\n         *        },\n         *        {\n         *          state: 'collapsed',\n         *          row: <reference to row>,\n         *          parentRow: <reference to row>,\n         *          aggregations: [{\n         *            type: 'count',\n         *            col: <gridCol>,\n         *            value: 3,\n         *            label: 'count: ',\n         *            rendered: 'count: 3'\n         *          }],\n         *          children: [\n         *            { state: 'expanded', row: <reference to row>, parentRow: <reference to row> },\n         *            { state: 'collapsed', row: <reference to row>, parentRow: <reference to row> },\n         *            { state: 'expanded', row: <reference to row>, parentRow: <reference to row> }\n         *          ]\n         *        }\n         *      ]\n         *    }, {<another level 0 node maybe>} ]\n         *  ```\n         *  Missing state values are false - meaning they aren't expanded.\n         *\n         *  This is used because the rowProcessors run every time the grid is refreshed, so\n         *  we'd lose the expanded state every time the grid was refreshed.  This instead gives\n         *  us a reliable lookup that persists across rowProcessors.\n         *\n         *  This tree is rebuilt every time we run the rowsProcessors.  Since each row holds a pointer\n         *  to it's tree node we can persist expand/collapse state across calls to rowsProcessor, we discard\n         *  all transient information on the tree (children, childCount) and recalculate it\n         *\n         */\n        grid.treeBase.tree = {};\n\n        service.defaultGridOptions(grid.options);\n\n        grid.registerRowsProcessor(service.treeRows, 410);\n\n        grid.registerColumnBuilder( service.treeBaseColumnBuilder );\n\n        service.createRowHeader( grid );\n\n        /**\n         *  @ngdoc object\n         *  @name ui.grid.treeBase.api:PublicApi\n         *\n         *  @description Public Api for treeBase feature\n         */\n        var publicApi = {\n          events: {\n            treeBase: {\n              /**\n               * @ngdoc event\n               * @eventOf ui.grid.treeBase.api:PublicApi\n               * @name rowExpanded\n               * @description raised whenever a row is expanded.  If you are dynamically\n               * rendering your tree you can listen to this event, and then retrieve\n               * the children of this row and load them into the grid data.\n               *\n               * When the data is loaded the grid will automatically refresh to show these new rows\n               *\n               * <pre>\n               *      gridApi.treeBase.on.rowExpanded(scope,function(row){})\n               * </pre>\n               * @param {gridRow} row the row that was expanded.  You can also\n               * retrieve the grid from this row with row.grid\n               */\n              rowExpanded: {},\n\n              /**\n               * @ngdoc event\n               * @eventOf ui.grid.treeBase.api:PublicApi\n               * @name rowCollapsed\n               * @description raised whenever a row is collapsed.  Doesn't really have\n               * a purpose at the moment, included for symmetry\n               *\n               * <pre>\n               *      gridApi.treeBase.on.rowCollapsed(scope,function(row){})\n               * </pre>\n               * @param {gridRow} row the row that was collapsed.  You can also\n               * retrieve the grid from this row with row.grid\n               */\n              rowCollapsed: {}\n            }\n          },\n\n          methods: {\n            treeBase: {\n              /**\n               * @ngdoc function\n               * @name expandAllRows\n               * @methodOf  ui.grid.treeBase.api:PublicApi\n               * @description Expands all tree rows\n               */\n              expandAllRows: function () {\n                service.expandAllRows(grid);\n              },\n\n              /**\n               * @ngdoc function\n               * @name collapseAllRows\n               * @methodOf  ui.grid.treeBase.api:PublicApi\n               * @description collapse all tree rows\n               */\n              collapseAllRows: function () {\n                service.collapseAllRows(grid);\n              },\n\n              /**\n               * @ngdoc function\n               * @name toggleRowTreeState\n               * @methodOf  ui.grid.treeBase.api:PublicApi\n               * @description  call expand if the row is collapsed, collapse if it is expanded\n               * @param {gridRow} row the row you wish to toggle\n               */\n              toggleRowTreeState: function (row) {\n                service.toggleRowTreeState(grid, row);\n              },\n\n              /**\n               * @ngdoc function\n               * @name expandRow\n               * @methodOf  ui.grid.treeBase.api:PublicApi\n               * @description expand the immediate children of the specified row\n               * @param {gridRow} row the row you wish to expand\n               */\n              expandRow: function (row) {\n                service.expandRow(grid, row);\n              },\n\n              /**\n               * @ngdoc function\n               * @name expandRowChildren\n               * @methodOf  ui.grid.treeBase.api:PublicApi\n               * @description expand all children of the specified row\n               * @param {gridRow} row the row you wish to expand\n               */\n              expandRowChildren: function (row) {\n                service.expandRowChildren(grid, row);\n              },\n\n              /**\n               * @ngdoc function\n               * @name collapseRow\n               * @methodOf  ui.grid.treeBase.api:PublicApi\n               * @description collapse  the specified row.  When\n               * you expand the row again, all grandchildren will retain their state\n               * @param {gridRow} row the row you wish to collapse\n               */\n              collapseRow: function ( row ) {\n                service.collapseRow(grid, row);\n              },\n\n              /**\n               * @ngdoc function\n               * @name collapseRowChildren\n               * @methodOf  ui.grid.treeBase.api:PublicApi\n               * @description collapse all children of the specified row.  When\n               * you expand the row again, all grandchildren will be collapsed\n               * @param {gridRow} row the row you wish to collapse children for\n               */\n              collapseRowChildren: function ( row ) {\n                service.collapseRowChildren(grid, row);\n              },\n\n              /**\n               * @ngdoc function\n               * @name getTreeState\n               * @methodOf  ui.grid.treeBase.api:PublicApi\n               * @description Get the tree state for this grid,\n               * used by the saveState feature\n               * Returned treeState as an object\n               *   `{ expandedState: { uid: 'expanded', uid: 'collapsed' } }`\n               * where expandedState is a hash of row uid and the current expanded state\n               *\n               * @returns {object} tree state\n               *\n               * TODO - this needs work - we need an identifier that persists across instantiations,\n               * not uid.  This really means we need a row identity defined, but that won't work for\n               * grouping.  Perhaps this needs to be moved up to treeView and grouping, rather than\n               * being in base.\n               */\n              getTreeExpandedState: function () {\n                return { expandedState: service.getTreeState(grid) };\n              },\n\n              /**\n               * @ngdoc function\n               * @name setTreeState\n               * @methodOf  ui.grid.treeBase.api:PublicApi\n               * @description Set the expanded states of the tree\n               * @param {object} config the config you want to apply, in the format\n               * provided by getTreeState\n               */\n              setTreeState: function ( config ) {\n                service.setTreeState( grid, config );\n              },\n\n              /**\n               * @ngdoc function\n               * @name getRowChildren\n               * @methodOf  ui.grid.treeBase.api:PublicApi\n               * @description Get the children of the specified row\n               * @param {GridRow} row the row you want the children of\n               * @returns {Array} array of children of this row, the children\n               * are all gridRows\n               */\n              getRowChildren: function ( row ){\n                return row.treeNode.children.map( function( childNode ){\n                  return childNode.row;\n                });\n              }\n            }\n          }\n        };\n\n        grid.api.registerEventsFromObject(publicApi.events);\n\n        grid.api.registerMethodsFromObject(publicApi.methods);\n      },\n\n\n      defaultGridOptions: function (gridOptions) {\n        //default option to true unless it was explicitly set to false\n        /**\n         *  @ngdoc object\n         *  @name ui.grid.treeBase.api:GridOptions\n         *\n         *  @description GridOptions for treeBase feature, these are available to be\n         *  set using the ui-grid {@link ui.grid.class:GridOptions gridOptions}\n         */\n\n        /**\n         *  @ngdoc object\n         *  @name treeRowHeaderBaseWidth\n         *  @propertyOf  ui.grid.treeBase.api:GridOptions\n         *  @description Base width of the tree header, provides for a single level of tree.  This\n         *  is incremented by `treeIndent` for each extra level\n         *  <br/>Defaults to 30\n         */\n        gridOptions.treeRowHeaderBaseWidth = gridOptions.treeRowHeaderBaseWidth || 30;\n\n        /**\n         *  @ngdoc object\n         *  @name treeIndent\n         *  @propertyOf  ui.grid.treeBase.api:GridOptions\n         *  @description Number of pixels of indent for the icon at each tree level, wider indents are visually more pleasing,\n         *  but will make the tree row header wider\n         *  <br/>Defaults to 10\n         */\n        gridOptions.treeIndent = gridOptions.treeIndent || 10;\n\n        /**\n         *  @ngdoc object\n         *  @name showTreeRowHeader\n         *  @propertyOf  ui.grid.treeBase.api:GridOptions\n         *  @description If set to false, don't create the row header.  Youll need to programatically control the expand\n         *  states\n         *  <br/>Defaults to true\n         */\n        gridOptions.showTreeRowHeader = gridOptions.showTreeRowHeader !== false;\n\n        /**\n         *  @ngdoc object\n         *  @name showTreeExpandNoChildren\n         *  @propertyOf  ui.grid.treeBase.api:GridOptions\n         *  @description If set to true, show the expand/collapse button even if there are no\n         *  children of a node.  You'd use this if you're planning to dynamically load the children\n         *\n         *  <br/>Defaults to true, grouping overrides to false\n         */\n        gridOptions.showTreeExpandNoChildren = gridOptions.showTreeExpandNoChildren !== false;\n\n        /**\n         *  @ngdoc object\n         *  @name treeRowHeaderAlwaysVisible\n         *  @propertyOf  ui.grid.treeBase.api:GridOptions\n         *  @description If set to true, row header even if there are no tree nodes\n         *\n         *  <br/>Defaults to true\n         */\n        gridOptions.treeRowHeaderAlwaysVisible = gridOptions.treeRowHeaderAlwaysVisible !== false;\n\n        /**\n         *  @ngdoc object\n         *  @name treeCustomAggregations\n         *  @propertyOf  ui.grid.treeBase.api:GridOptions\n         *  @description Define custom aggregation functions. The properties of this object will be\n         *  aggregation types available for use on columnDef with {@link ui.grid.treeBase.api:ColumnDef treeAggregationType} or through the column menu.\n         *  If a function defined here uses the same name as one of the native aggregations, this one will take precedence.\n         *  The object format is:\n         *\n         *  <pre>\n         *    {\n         *      aggregationName: {\n         *        label: (optional) string,\n         *        aggregationFn: function( aggregation, fieldValue, numValue, row ){...},\n         *        finalizerFn: (optional) function( aggregation ){...}\n       *        },\n         *      mean: {\n         *        label: 'mean',\n         *        aggregationFn: function( aggregation, fieldValue, numValue ){\n       *            aggregation.count = (aggregation.count || 1) + 1;\n         *          aggregation.sum = (aggregation.sum || 0) + numValue;\n         *        },\n         *        finalizerFn: function( aggregation ){\n         *          aggregation.value = aggregation.sum / aggregation.count\n         *        }\n         *      }\n         *    }\n         *  </pre>\n         *\n         *  <br/>The `finalizerFn` may be used to manipulate the value before rendering, or to\n         *  apply a custom rendered value. If `aggregation.rendered` is left undefined, the value will be\n         *  rendered. Note that the native aggregation functions use an `finalizerFn` to concatenate\n         *  the label and the value.\n         *\n         *  <br/>Defaults to {}\n         */\n        gridOptions.treeCustomAggregations = gridOptions.treeCustomAggregations || {};\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name treeBaseColumnBuilder\n       * @methodOf  ui.grid.treeBase.service:uiGridTreeBaseService\n       * @description Sets the tree defaults based on the columnDefs\n       *\n       * @param {object} colDef columnDef we're basing on\n       * @param {GridCol} col the column we're to update\n       * @param {object} gridOptions the options we should use\n       * @returns {promise} promise for the builder - actually we do it all inline so it's immediately resolved\n       */\n      treeBaseColumnBuilder: function (colDef, col, gridOptions) {\n\n\n        /**\n         *  @ngdoc object\n         *  @name customTreeAggregationFn\n         *  @propertyOf  ui.grid.treeBase.api:ColumnDef\n         *  @description A custom function that aggregates rows into some form of\n         *  total.  Aggregations run row-by-row, the function needs to be capable of\n         *  creating a running total.\n         *\n         *  The function will be provided the aggregation item (in which you can store running\n         *  totals), the row value that is to be aggregated, and that same row value converted to\n         *  a number (most aggregations work on numbers)\n         *  @example\n         *  <pre>\n         *    customTreeAggregationFn = function ( aggregation, fieldValue, numValue, row ){\n         *      // calculates the average of the squares of the values\n         *      if ( typeof(aggregation.count) === 'undefined' ){\n         *        aggregation.count = 0;\n         *      }\n         *      aggregation.count++;\n         *\n         *      if ( !isNaN(numValue) ){\n         *        if ( typeof(aggregation.total) === 'undefined' ){\n         *          aggregation.total = 0;\n         *        }\n         *        aggregation.total = aggregation.total + numValue * numValue;\n         *      }\n         *\n         *      aggregation.value = aggregation.total / aggregation.count;\n         *    }\n         *  </pre>\n         *  <br/>Defaults to undefined. May be overwritten by treeAggregationType, the two options should not be used together.\n         */\n        if ( typeof(colDef.customTreeAggregationFn) !== 'undefined' ){\n          col.treeAggregationFn = colDef.customTreeAggregationFn;\n        }\n\n        /**\n         *  @ngdoc object\n         *  @name treeAggregationType\n         *  @propertyOf  ui.grid.treeBase.api:ColumnDef\n         *  @description Use one of the native or grid-level aggregation methods for calculating aggregations on this column.\n         *  Native method are in the constants file and include: SUM, COUNT, MIN, MAX, AVG. This may also be the property the\n         *  name of an aggregation function defined with {@link ui.grid.treeBase.api:GridOptions treeCustomAggregations}.\n         *\n         *  <pre>\n         *      treeAggregationType = uiGridTreeBaseConstants.aggregation.SUM,\n         *    }\n         *  </pre>\n         *\n         *  If you are using aggregations you should either:\n         *\n         *   - also use grouping, in which case the aggregations are displayed in the group header, OR\n         *   - use treeView, in which case you can set `treeAggregationUpdateEntity: true` in the colDef, and\n         *     treeBase will store the aggregation information in the entity, or you can set `treeAggregationUpdateEntity: false`\n         *     in the colDef, and you need to manual retrieve the calculated aggregations from the row.treeNode.aggregations\n         *\n         *  <br/>Takes precendence over a treeAggregationFn, the two options should not be used together.\n         *  <br/>Defaults to undefined.\n         */\n        if ( typeof(colDef.treeAggregationType) !== 'undefined' ){\n          col.treeAggregation = { type: colDef.treeAggregationType };\n          if ( typeof(gridOptions.treeCustomAggregations[colDef.treeAggregationType]) !== 'undefined' ){\n            col.treeAggregationFn = gridOptions.treeCustomAggregations[colDef.treeAggregationType].aggregationFn;\n            col.treeAggregationFinalizerFn = gridOptions.treeCustomAggregations[colDef.treeAggregationType].finalizerFn;\n            col.treeAggregation.label = gridOptions.treeCustomAggregations[colDef.treeAggregationType].label;\n          } else if ( typeof(service.nativeAggregations()[colDef.treeAggregationType]) !== 'undefined' ){\n            col.treeAggregationFn = service.nativeAggregations()[colDef.treeAggregationType].aggregationFn;\n            col.treeAggregation.label = service.nativeAggregations()[colDef.treeAggregationType].label;\n          }\n        }\n\n         /**\n         *  @ngdoc object\n         *  @name treeAggregationLabel\n         *  @propertyOf  ui.grid.treeBase.api:ColumnDef\n         *  @description A custom label to use for this aggregation. If provided we don't use native i18n.\n         */\n        if ( typeof(colDef.treeAggregationLabel) !== 'undefined' ){\n          if (typeof(col.treeAggregation) === 'undefined' ){\n            col.treeAggregation = {};\n          }\n          col.treeAggregation.label = colDef.treeAggregationLabel;\n        }\n\n        /**\n         *  @ngdoc object\n         *  @name treeAggregationUpdateEntity\n         *  @propertyOf  ui.grid.treeBase.api:ColumnDef\n         *  @description Store calculated aggregations into the entity, allowing them\n         *  to be displayed in the grid using a standard cellTemplate.  This defaults to true,\n         *  if you are using grouping then you shouldn't set it to false, as then the aggregations won't\n         *  display.\n         *\n         *  If you are using treeView in most cases you'll want to set this to true.  This will result in\n         *  getCellValue returning the aggregation rather than whatever was stored in the cell attribute on\n         *  the entity.  If you want to render the underlying entity value (and do something else with the aggregation)\n         *  then you could use a custom cellTemplate to display `row.entity.myAttribute`, rather than using getCellValue.\n         *\n         *  <br/>Defaults to true\n         *\n         *  @example\n         *  <pre>\n         *    gridOptions.columns = [{\n         *      name: 'myCol',\n         *      treeAggregation: { type: uiGridTreeBaseConstants.aggregation.SUM },\n         *      treeAggregationUpdateEntity: true\n         *      cellTemplate: '<div>{{row.entity.myCol + \" \" + row.treeNode.aggregations[0].rendered}}</div>'\n         *    }];\n         * </pre>\n         */\n        col.treeAggregationUpdateEntity = colDef.treeAggregationUpdateEntity !== false;\n\n        /**\n         *  @ngdoc object\n         *  @name customTreeAggregationFinalizerFn\n         *  @propertyOf  ui.grid.treeBase.api:ColumnDef\n         *  @description A custom function that populates aggregation.rendered, this is called when\n         *  a particular aggregation has been fully calculated, and we want to render the value.\n         *\n         *  With the native aggregation options we just concatenate `aggregation.label` and\n         *  `aggregation.value`, but if you wanted to apply a filter or otherwise manipulate the label\n         *  or the value, you can do so with this function. This function will be called after the\n         *  the default `finalizerFn`.\n         *\n         *  @example\n         *  <pre>\n         *    customTreeAggregationFinalizerFn = function ( aggregation ){\n         *      aggregation.rendered = aggregation.label + aggregation.value / 100 + '%';\n         *    }\n         *  </pre>\n         *  <br/>Defaults to undefined.\n         */\n        if ( typeof(col.customTreeAggregationFinalizerFn) === 'undefined' ){\n          col.customTreeAggregationFinalizerFn = colDef.customTreeAggregationFinalizerFn;\n        }\n\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name createRowHeader\n       * @methodOf  ui.grid.treeBase.service:uiGridTreeBaseService\n       * @description Create the rowHeader.  If treeRowHeaderAlwaysVisible then\n       * set it to visible, otherwise set it to invisible\n       *\n       * @param {Grid} grid grid object\n       */\n      createRowHeader: function( grid ){\n        var rowHeaderColumnDef = {\n          name: uiGridTreeBaseConstants.rowHeaderColName,\n          displayName: '',\n          width:  grid.options.treeRowHeaderBaseWidth,\n          minWidth: 10,\n          cellTemplate: 'ui-grid/treeBaseRowHeader',\n          headerCellTemplate: 'ui-grid/treeBaseHeaderCell',\n          enableColumnResizing: false,\n          enableColumnMenu: false,\n          exporterSuppressExport: true,\n          allowCellFocus: true\n        };\n\n        rowHeaderColumnDef.visible = grid.options.treeRowHeaderAlwaysVisible;\n        grid.addRowHeaderColumn( rowHeaderColumnDef );\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name expandAllRows\n       * @methodOf  ui.grid.treeBase.service:uiGridTreeBaseService\n       * @description Expands all nodes in the tree\n       *\n       * @param {Grid} grid grid object\n       */\n      expandAllRows: function (grid) {\n        grid.treeBase.tree.forEach( function( node ) {\n          service.setAllNodes( grid, node, uiGridTreeBaseConstants.EXPANDED);\n        });\n        grid.treeBase.expandAll = true;\n        grid.queueGridRefresh();\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name collapseAllRows\n       * @methodOf  ui.grid.treeBase.service:uiGridTreeBaseService\n       * @description Collapses all nodes in the tree\n       *\n       * @param {Grid} grid grid object\n       */\n      collapseAllRows: function (grid) {\n        grid.treeBase.tree.forEach( function( node ) {\n          service.setAllNodes( grid, node, uiGridTreeBaseConstants.COLLAPSED);\n        });\n        grid.treeBase.expandAll = false;\n        grid.queueGridRefresh();\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name setAllNodes\n       * @methodOf  ui.grid.treeBase.service:uiGridTreeBaseService\n       * @description Works through a subset of grid.treeBase.rowExpandedStates, setting\n       * all child nodes (and their descendents) of the provided node to the given state.\n       *\n       * Calls itself recursively on all nodes so as to achieve this.\n       *\n       * @param {Grid} grid the grid we're operating on (so we can raise events)\n       * @param {object} treeNode a node in the tree that we want to update\n       * @param {string} targetState the state we want to set it to\n       */\n      setAllNodes: function (grid, treeNode, targetState) {\n        if ( typeof(treeNode.state) !== 'undefined' && treeNode.state !== targetState ){\n          treeNode.state = targetState;\n\n          if ( targetState === uiGridTreeBaseConstants.EXPANDED ){\n            grid.api.treeBase.raise.rowExpanded(treeNode.row);\n          } else {\n            grid.api.treeBase.raise.rowCollapsed(treeNode.row);\n          }\n        }\n\n        // set all child nodes\n        if ( treeNode.children ){\n          treeNode.children.forEach(function( childNode ){\n            service.setAllNodes(grid, childNode, targetState);\n          });\n        }\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name toggleRowTreeState\n       * @methodOf  ui.grid.treeBase.service:uiGridTreeBaseService\n       * @description Toggles the expand or collapse state of this grouped row, if\n       * it's a parent row\n       *\n       * @param {Grid} grid grid object\n       * @param {GridRow} row the row we want to toggle\n       */\n      toggleRowTreeState: function ( grid, row ){\n        if ( typeof(row.treeLevel) === 'undefined' || row.treeLevel === null || row.treeLevel < 0 ){\n          return;\n        }\n\n        if (row.treeNode.state === uiGridTreeBaseConstants.EXPANDED){\n          service.collapseRow(grid, row);\n        } else {\n          service.expandRow(grid, row);\n        }\n\n        grid.queueGridRefresh();\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name expandRow\n       * @methodOf  ui.grid.treeBase.service:uiGridTreeBaseService\n       * @description Expands this specific row, showing only immediate children.\n       *\n       * @param {Grid} grid grid object\n       * @param {GridRow} row the row we want to expand\n       */\n      expandRow: function ( grid, row ){\n        if ( typeof(row.treeLevel) === 'undefined' || row.treeLevel === null || row.treeLevel < 0 ){\n          return;\n        }\n\n        if ( row.treeNode.state !== uiGridTreeBaseConstants.EXPANDED ){\n          row.treeNode.state = uiGridTreeBaseConstants.EXPANDED;\n          grid.api.treeBase.raise.rowExpanded(row);\n          grid.treeBase.expandAll = service.allExpanded(grid.treeBase.tree);\n          grid.queueGridRefresh();\n        }\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name expandRowChildren\n       * @methodOf  ui.grid.treeBase.service:uiGridTreeBaseService\n       * @description Expands this specific row, showing all children.\n       *\n       * @param {Grid} grid grid object\n       * @param {GridRow} row the row we want to expand\n       */\n      expandRowChildren: function ( grid, row ){\n        if ( typeof(row.treeLevel) === 'undefined' || row.treeLevel === null || row.treeLevel < 0 ){\n          return;\n        }\n\n        service.setAllNodes(grid, row.treeNode, uiGridTreeBaseConstants.EXPANDED);\n        grid.treeBase.expandAll = service.allExpanded(grid.treeBase.tree);\n        grid.queueGridRefresh();\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name collapseRow\n       * @methodOf  ui.grid.treeBase.service:uiGridTreeBaseService\n       * @description Collapses this specific row\n       *\n       * @param {Grid} grid grid object\n       * @param {GridRow} row the row we want to collapse\n       */\n      collapseRow: function( grid, row ){\n        if ( typeof(row.treeLevel) === 'undefined' || row.treeLevel === null || row.treeLevel < 0 ){\n          return;\n        }\n\n        if ( row.treeNode.state !== uiGridTreeBaseConstants.COLLAPSED ){\n          row.treeNode.state = uiGridTreeBaseConstants.COLLAPSED;\n          grid.treeBase.expandAll = false;\n          grid.api.treeBase.raise.rowCollapsed(row);\n          grid.queueGridRefresh();\n        }\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name collapseRowChildren\n       * @methodOf  ui.grid.treeBase.service:uiGridTreeBaseService\n       * @description Collapses this specific row and all children\n       *\n       * @param {Grid} grid grid object\n       * @param {GridRow} row the row we want to collapse\n       */\n      collapseRowChildren: function( grid, row ){\n        if ( typeof(row.treeLevel) === 'undefined' || row.treeLevel === null || row.treeLevel < 0 ){\n          return;\n        }\n\n        service.setAllNodes(grid, row.treeNode, uiGridTreeBaseConstants.COLLAPSED);\n        grid.treeBase.expandAll = false;\n        grid.queueGridRefresh();\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name allExpanded\n       * @methodOf  ui.grid.treeBase.service:uiGridTreeBaseService\n       * @description Returns true if all rows are expanded, false\n       * if they're not.  Walks the tree to determine this.  Used\n       * to set the expandAll state.\n       *\n       * If the node has no children, then return true (it's immaterial\n       * whether it is expanded).  If the node has children, then return\n       * false if this node is collapsed, or if any child node is not all expanded\n       *\n       * @param {object} tree the grid to check\n       * @returns {boolean} whether or not the tree is all expanded\n       */\n      allExpanded: function( tree ){\n        var allExpanded = true;\n        tree.forEach( function( node ){\n          if ( !service.allExpandedInternal( node ) ){\n            allExpanded = false;\n          }\n        });\n        return allExpanded;\n      },\n\n      allExpandedInternal: function( treeNode ){\n        if ( treeNode.children && treeNode.children.length > 0 ){\n          if ( treeNode.state === uiGridTreeBaseConstants.COLLAPSED ){\n            return false;\n          }\n          var allExpanded = true;\n          treeNode.children.forEach( function( node ){\n            if ( !service.allExpandedInternal( node ) ){\n              allExpanded = false;\n            }\n          });\n          return allExpanded;\n        } else {\n          return true;\n        }\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name treeRows\n       * @methodOf  ui.grid.treeBase.service:uiGridTreeBaseService\n       * @description The rowProcessor that adds the nodes to the tree, and sets the visible\n       * state of each row based on it's parent state\n       *\n       * Assumes it is always called after the sorting processor, and the grouping processor if there is one.\n       * Performs any tree sorts itself after having built the tree\n       *\n       * Processes all the rows in order, setting the group level based on the $$treeLevel in the associated\n       * entity, and setting the visible state based on the parent's state.\n       *\n       * Calculates the deepest level of tree whilst it goes, and updates that so that the header column can be correctly\n       * sized.\n       *\n       * Aggregates if necessary along the way.\n       *\n       * @param {array} renderableRows the rows we want to process, usually the output from the previous rowProcessor\n       * @returns {array} the updated rows\n       */\n      treeRows: function( renderableRows ) {\n        if (renderableRows.length === 0){\n          return renderableRows;\n        }\n\n        var grid = this;\n        var currentLevel = 0;\n        var currentState = uiGridTreeBaseConstants.EXPANDED;\n        var parents = [];\n\n        grid.treeBase.tree = service.createTree( grid, renderableRows );\n        service.updateRowHeaderWidth( grid );\n\n        service.sortTree( grid );\n        service.fixFilter( grid );\n\n        return service.renderTree( grid.treeBase.tree );\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name createOrUpdateRowHeaderWidth\n       * @methodOf  ui.grid.treeBase.service:uiGridTreeBaseService\n       * @description Calculates the rowHeader width.\n       *\n       * If rowHeader is always present, updates the width.\n       *\n       * If rowHeader is only sometimes present (`treeRowHeaderAlwaysVisible: false`), determines whether there\n       * should be one, then creates or removes it as appropriate, with the created rowHeader having the\n       * right width.\n       *\n       * If there's never a rowHeader then never creates one: `showTreeRowHeader: false`\n       *\n       * @param {Grid} grid the grid we want to set the row header on\n       */\n      updateRowHeaderWidth: function( grid ){\n        var rowHeader = grid.getColumn(uiGridTreeBaseConstants.rowHeaderColName);\n\n        var newWidth = grid.options.treeRowHeaderBaseWidth + grid.options.treeIndent * Math.max(grid.treeBase.numberLevels - 1, 0);\n        if ( rowHeader && newWidth !== rowHeader.width ){\n          rowHeader.width = newWidth;\n          grid.queueRefresh();\n        }\n\n        var newVisibility = true;\n        if ( grid.options.showTreeRowHeader === false ){\n          newVisibility = false;\n        }\n        if ( grid.options.treeRowHeaderAlwaysVisible === false && grid.treeBase.numberLevels <= 0 ){\n          newVisibility = false;\n        }\n        if ( rowHeader.visible !== newVisibility ) {\n          rowHeader.visible = newVisibility;\n          rowHeader.colDef.visible = newVisibility;\n          grid.queueGridRefresh();\n        }\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name renderTree\n       * @methodOf  ui.grid.treeBase.service:uiGridTreeBaseService\n       * @description Creates an array of rows based on the tree, exporting only\n       * the visible nodes and leaves\n       *\n       * @param {array} nodeList the list of nodes - can be grid.treeBase.tree, or can be node.children when\n       * we're calling recursively\n       * @returns {array} renderable rows\n       */\n      renderTree: function( nodeList ){\n        var renderableRows = [];\n\n        nodeList.forEach( function ( node ){\n          if ( node.row.visible ){\n            renderableRows.push( node.row );\n          }\n          if ( node.state === uiGridTreeBaseConstants.EXPANDED && node.children && node.children.length > 0 ){\n            renderableRows = renderableRows.concat( service.renderTree( node.children ) );\n          }\n        });\n        return renderableRows;\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name createTree\n       * @methodOf  ui.grid.treeBase.service:uiGridTreeBaseService\n       * @description Creates a tree from the renderableRows\n       *\n       * @param {Grid} grid the grid\n       * @param {array} renderableRows the rows we want to create a tree from\n       * @returns {object} the tree we've build\n       */\n      createTree: function( grid, renderableRows ) {\n        var currentLevel = -1;\n        var parents = [];\n        var currentState;\n        grid.treeBase.tree = [];\n        grid.treeBase.numberLevels = 0;\n        var aggregations = service.getAggregations( grid );\n\n        var createNode = function( row ){\n          if ( typeof(row.entity.$$treeLevel) !== 'undefined' && row.treeLevel !== row.entity.$$treeLevel ){\n            row.treeLevel = row.entity.$$treeLevel;\n          }\n\n          if ( row.treeLevel <= currentLevel ){\n            // pop any levels that aren't parents of this level, formatting the aggregation at the same time\n            while ( row.treeLevel <= currentLevel ){\n              var lastParent = parents.pop();\n              service.finaliseAggregations( lastParent );\n              currentLevel--;\n            }\n\n            // reset our current state based on the new parent, set to expanded if this is a level 0 node\n            if ( parents.length > 0 ){\n              currentState = service.setCurrentState(parents);\n            } else {\n              currentState = uiGridTreeBaseConstants.EXPANDED;\n            }\n          }\n\n          // aggregate if this is a leaf node\n          if ( ( typeof(row.treeLevel) === 'undefined' || row.treeLevel === null || row.treeLevel < 0 ) && row.visible  ){\n            service.aggregate( grid, row, parents );\n          }\n\n          // add this node to the tree\n          service.addOrUseNode(grid, row, parents, aggregations);\n\n          if ( typeof(row.treeLevel) !== 'undefined' && row.treeLevel !== null && row.treeLevel >= 0 ){\n            parents.push(row);\n            currentLevel++;\n            currentState = service.setCurrentState(parents);\n          }\n\n          // update the tree number of levels, so we can set header width if we need to\n          if ( grid.treeBase.numberLevels < row.treeLevel + 1){\n            grid.treeBase.numberLevels = row.treeLevel + 1;\n          }\n        };\n\n        renderableRows.forEach( createNode );\n\n        // finalise remaining aggregations\n        while ( parents.length > 0 ){\n          var lastParent = parents.pop();\n          service.finaliseAggregations( lastParent );\n        }\n\n        return grid.treeBase.tree;\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name addOrUseNode\n       * @methodOf  ui.grid.treeBase.service:uiGridTreeBaseService\n       * @description Creates a tree node for this row.  If this row already has a treeNode\n       * recorded against it, preserves the state, but otherwise overwrites the data.\n       *\n       * @param {grid} grid the grid we're operating on\n       * @param {gridRow} row the row we want to set\n       * @param {array} parents an array of the parents this row should have\n       * @param {array} aggregationBase empty aggregation information\n       * @returns {undefined} updates the parents array, updates the row to have a treeNode, and updates the\n       * grid.treeBase.tree\n       */\n      addOrUseNode: function( grid, row, parents, aggregationBase ){\n        var newAggregations = [];\n        aggregationBase.forEach( function(aggregation){\n          newAggregations.push(service.buildAggregationObject(aggregation.col));\n        });\n\n        var newNode = { state: uiGridTreeBaseConstants.COLLAPSED, row: row, parentRow: null, aggregations: newAggregations, children: [] };\n        if ( row.treeNode ){\n          newNode.state = row.treeNode.state;\n        }\n        if ( parents.length > 0 ){\n          newNode.parentRow = parents[parents.length - 1];\n        }\n        row.treeNode = newNode;\n\n        if ( parents.length === 0 ){\n          grid.treeBase.tree.push( newNode );\n        } else {\n          parents[parents.length - 1].treeNode.children.push( newNode );\n        }\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name setCurrentState\n       * @methodOf  ui.grid.treeBase.service:uiGridTreeBaseService\n       * @description Looks at the parents array to determine our current state.\n       * If any node in the hierarchy is collapsed, then return collapsed, otherwise return\n       * expanded.\n       *\n       * @param {array} parents an array of the parents this row should have\n       * @returns {string} the state we should be setting to any nodes we see\n       */\n      setCurrentState: function( parents ){\n        var currentState = uiGridTreeBaseConstants.EXPANDED;\n        parents.forEach( function(parent){\n          if ( parent.treeNode.state === uiGridTreeBaseConstants.COLLAPSED ){\n            currentState = uiGridTreeBaseConstants.COLLAPSED;\n          }\n        });\n        return currentState;\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name sortTree\n       * @methodOf  ui.grid.treeBase.service:uiGridTreeBaseService\n       * @description Performs a recursive sort on the tree nodes, sorting the\n       * children of each node and putting them back into the children array.\n       *\n       * Before doing this it turns back on all the sortIgnore - things that were previously\n       * ignored we process now.  Since we're sorting within the nodes, presumably anything\n       * that was already sorted is how we derived the nodes, we can keep those sorts too.\n       *\n       * We only sort tree nodes that are expanded - no point in wasting effort sorting collapsed\n       * nodes\n       *\n       * @param {Grid} grid the grid to get the aggregation information from\n       * @returns {array} the aggregation information\n       */\n      sortTree: function( grid ){\n        grid.columns.forEach( function( column ) {\n          if ( column.sort && column.sort.ignoreSort ){\n            delete column.sort.ignoreSort;\n          }\n        });\n\n        grid.treeBase.tree = service.sortInternal( grid, grid.treeBase.tree );\n      },\n\n      sortInternal: function( grid, treeList ){\n        var rows = treeList.map( function( node ){\n          return node.row;\n        });\n\n        rows = rowSorter.sort( grid, rows, grid.columns );\n\n        var treeNodes = rows.map( function( row ){\n          return row.treeNode;\n        });\n\n        treeNodes.forEach( function( node ){\n          if ( node.state === uiGridTreeBaseConstants.EXPANDED && node.children && node.children.length > 0 ){\n            node.children = service.sortInternal( grid, node.children );\n          }\n        });\n\n        return treeNodes;\n      },\n\n      /**\n       * @ngdoc function\n       * @name fixFilter\n       * @methodOf  ui.grid.treeBase.service:uiGridTreeBaseService\n       * @description After filtering has run, we need to go back through the tree\n       * and make sure the parent rows are always visible if any of the child rows\n       * are visible (filtering may make a child visible, but the parent may not\n       * match the filter criteria)\n       *\n       * This has a risk of being computationally expensive, we do it by walking\n       * the tree and remembering whether there are any invisible nodes on the\n       * way down.\n       *\n       * @param {Grid} grid the grid to fix filters on\n       */\n      fixFilter: function( grid ){\n        var parentsVisible;\n\n        grid.treeBase.tree.forEach( function( node ){\n          if ( node.children && node.children.length > 0 ){\n            parentsVisible = node.row.visible;\n            service.fixFilterInternal( node.children, parentsVisible );\n          }\n        });\n      },\n\n      fixFilterInternal: function( nodes, parentsVisible) {\n        nodes.forEach( function( node ){\n          if ( node.row.visible && !parentsVisible ){\n            service.setParentsVisible( node );\n            parentsVisible = true;\n          }\n\n          if ( node.children && node.children.length > 0 ){\n            if ( service.fixFilterInternal( node.children, ( parentsVisible && node.row.visible ) ) ) {\n              parentsVisible = true;\n            }\n          }\n        });\n\n        return parentsVisible;\n      },\n\n      setParentsVisible: function( node ){\n        while ( node.parentRow ){\n          node.parentRow.visible = true;\n          node = node.parentRow.treeNode;\n        }\n      },\n\n      /**\n       * @ngdoc function\n       * @name buildAggregationObject\n       * @methodOf  ui.grid.treeBase.service:uiGridTreeBaseService\n       * @description Build the object which is stored on the column for holding meta-data about the aggregation.\n       * This method should only be called with columns which have an aggregation.\n       *\n       * @param {Column} the column which this object relates to\n       * @returns {object} {col: Column object, label: string, type: string (optional)}\n       */\n      buildAggregationObject: function( column ){\n        var newAggregation = { col: column };\n\n        if ( column.treeAggregation && column.treeAggregation.type ){\n          newAggregation.type = column.treeAggregation.type;\n        }\n\n        if ( column.treeAggregation && column.treeAggregation.label ){\n          newAggregation.label = column.treeAggregation.label;\n        }\n\n        return newAggregation;\n      },\n\n      /**\n       * @ngdoc function\n       * @name getAggregations\n       * @methodOf  ui.grid.treeBase.service:uiGridTreeBaseService\n       * @description Looks through the grid columns to find those with aggregations,\n       * and collates the aggregation information into an array, returns that array\n       *\n       * @param {Grid} grid the grid to get the aggregation information from\n       * @returns {array} the aggregation information\n       */\n      getAggregations: function( grid ){\n        var aggregateArray = [];\n\n        grid.columns.forEach( function(column){\n          if ( typeof(column.treeAggregationFn) !== 'undefined' ){\n            aggregateArray.push( service.buildAggregationObject(column) );\n\n            if ( grid.options.showColumnFooter && typeof(column.colDef.aggregationType) === 'undefined' && column.treeAggregation ){\n              // Add aggregation object for footer\n              column.treeFooterAggregation = service.buildAggregationObject(column);\n              column.aggregationType = service.treeFooterAggregationType;\n            }\n          }\n        });\n        return aggregateArray;\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name aggregate\n       * @methodOf  ui.grid.treeBase.service:uiGridTreeBaseService\n       * @description Accumulate the data from this row onto the aggregations for each parent\n       *\n       * Iterate over the parents, then iterate over the aggregations for each of those parents,\n       * and perform the aggregation for each individual aggregation\n       *\n       * @param {Grid} grid grid object\n       * @param {GridRow} row the row we want to set grouping visibility on\n       * @param {array} parents the parents that we would want to aggregate onto\n       */\n      aggregate: function( grid, row, parents ){\n        if ( parents.length === 0 && row.treeNode && row.treeNode.aggregations ){\n          row.treeNode.aggregations.forEach(function(aggregation){\n            // Calculate aggregations for footer even if there are no grouped rows\n            if ( typeof(aggregation.col.treeFooterAggregation) !== 'undefined' ) {\n              var fieldValue = grid.getCellValue(row, aggregation.col);\n              var numValue = Number(fieldValue);\n              aggregation.col.treeAggregationFn(aggregation.col.treeFooterAggregation, fieldValue, numValue, row);\n            }\n          });\n        }\n\n        parents.forEach( function( parent, index ){\n          if ( parent.treeNode.aggregations ){\n            parent.treeNode.aggregations.forEach( function( aggregation ){\n              var fieldValue = grid.getCellValue(row, aggregation.col);\n              var numValue = Number(fieldValue);\n              aggregation.col.treeAggregationFn(aggregation, fieldValue, numValue, row);\n\n              if ( index === 0 && typeof(aggregation.col.treeFooterAggregation) !== 'undefined' ){\n                aggregation.col.treeAggregationFn(aggregation.col.treeFooterAggregation, fieldValue, numValue, row);\n              }\n            });\n          }\n        });\n      },\n\n\n      // Aggregation routines - no doco needed as self evident\n      nativeAggregations: function() {\n        var nativeAggregations = {\n          count: {\n            label: i18nService.get().aggregation.count,\n            menuTitle: i18nService.get().grouping.aggregate_count,\n            aggregationFn: function (aggregation, fieldValue, numValue) {\n              if (typeof(aggregation.value) === 'undefined') {\n                aggregation.value = 1;\n              } else {\n                aggregation.value++;\n              }\n            }\n          },\n\n          sum: {\n            label: i18nService.get().aggregation.sum,\n            menuTitle: i18nService.get().grouping.aggregate_sum,\n            aggregationFn: function( aggregation, fieldValue, numValue ) {\n              if (!isNaN(numValue)) {\n                if (typeof(aggregation.value) === 'undefined') {\n                  aggregation.value = numValue;\n                } else {\n                  aggregation.value += numValue;\n                }\n              }\n            }\n          },\n\n          min: {\n            label: i18nService.get().aggregation.min,\n            menuTitle: i18nService.get().grouping.aggregate_min,\n            aggregationFn: function( aggregation, fieldValue, numValue ) {\n              if (typeof(aggregation.value) === 'undefined') {\n                aggregation.value = fieldValue;\n              } else {\n                if (typeof(fieldValue) !== 'undefined' && fieldValue !== null && (fieldValue < aggregation.value || aggregation.value === null)) {\n                  aggregation.value = fieldValue;\n                }\n              }\n            }\n          },\n\n          max: {\n            label: i18nService.get().aggregation.max,\n            menuTitle: i18nService.get().grouping.aggregate_max,\n            aggregationFn: function( aggregation, fieldValue, numValue ){\n              if ( typeof(aggregation.value) === 'undefined' ){\n                aggregation.value = fieldValue;\n              } else {\n                if ( typeof(fieldValue) !== 'undefined' && fieldValue !== null && (fieldValue > aggregation.value || aggregation.value === null)){\n                  aggregation.value = fieldValue;\n                }\n              }\n            }\n          },\n\n          avg: {\n            label: i18nService.get().aggregation.avg,\n            menuTitle: i18nService.get().grouping.aggregate_avg,\n            aggregationFn: function( aggregation, fieldValue, numValue ){\n              if ( typeof(aggregation.count) === 'undefined' ){\n                aggregation.count = 1;\n              } else {\n                aggregation.count++;\n              }\n\n              if ( isNaN(numValue) ){\n                return;\n              }\n\n              if ( typeof(aggregation.value) === 'undefined' || typeof(aggregation.sum) === 'undefined' ){\n                aggregation.value = numValue;\n                aggregation.sum = numValue;\n              } else {\n                aggregation.sum += numValue;\n                aggregation.value = aggregation.sum / aggregation.count;\n              }\n            }\n          }\n        };\n        return nativeAggregations;\n      },\n\n      /**\n       * @ngdoc function\n       * @name finaliseAggregation\n       * @methodOf  ui.grid.treeBase.service:uiGridTreeBaseService\n       * @description Helper function used to finalize aggregation nodes and footer cells\n       *\n       * @param {gridRow} row the parent we're finalising\n       * @param {aggregation} the aggregation object manipulated by the aggregationFn\n       */\n      finaliseAggregation: function(row, aggregation){\n        if ( aggregation.col.treeAggregationUpdateEntity && typeof(row) !== 'undefined' && typeof(row.entity[ '$$' + aggregation.col.uid ]) !== 'undefined' ){\n          angular.extend( aggregation, row.entity[ '$$' + aggregation.col.uid ]);\n        }\n\n        if ( typeof(aggregation.col.treeAggregationFinalizerFn) === 'function' ){\n          aggregation.col.treeAggregationFinalizerFn( aggregation );\n        }\n        if ( typeof(aggregation.col.customTreeAggregationFinalizerFn) === 'function' ){\n          aggregation.col.customTreeAggregationFinalizerFn( aggregation );\n        }\n        if ( typeof(aggregation.rendered) === 'undefined' ){\n          aggregation.rendered = aggregation.label ? aggregation.label + aggregation.value : aggregation.value;\n        }\n      },\n\n      /**\n       * @ngdoc function\n       * @name finaliseAggregations\n       * @methodOf  ui.grid.treeBase.service:uiGridTreeBaseService\n       * @description Format the data from the aggregation into the rendered text\n       * e.g. if we had label: 'sum: ' and value: 25, we'd create 'sum: 25'.\n       *\n       * As part of this we call any formatting callback routines we've been provided.\n       *\n       * We write our aggregation out to the row.entity if treeAggregationUpdateEntity is\n       * set on the column - we don't overwrite any information that's already there, we append\n       * to it so that grouping can have set the groupVal beforehand without us overwriting it.\n       *\n       * We need to copy the data from the row.entity first before we finalise the aggregation,\n       * we need that information for the finaliserFn\n       *\n       * @param {gridRow} row the parent we're finalising\n       */\n      finaliseAggregations: function( row ){\n        if ( typeof(row.treeNode.aggregations) === 'undefined' ){\n          return;\n        }\n\n        row.treeNode.aggregations.forEach( function( aggregation ) {\n          service.finaliseAggregation(row, aggregation);\n\n          if ( aggregation.col.treeAggregationUpdateEntity ){\n            var aggregationCopy = {};\n            angular.forEach( aggregation, function( value, key ){\n              if ( aggregation.hasOwnProperty(key) && key !== 'col' ){\n                aggregationCopy[key] = value;\n              }\n            });\n\n            row.entity[ '$$' + aggregation.col.uid ] = aggregationCopy;\n          }\n        });\n      },\n\n      /**\n       * @ngdoc function\n       * @name treeFooterAggregationType\n       * @methodOf  ui.grid.treeBase.service:uiGridTreeBaseService\n       * @description Uses the tree aggregation functions and finalizers to set the\n       * column footer aggregations.\n       *\n       * @param {rows} visible rows. not used, but accepted to match signature of GridColumn.aggregationType\n       * @param {gridColumn} the column we are finalizing\n       */\n      treeFooterAggregationType: function( rows, column ) {\n        service.finaliseAggregation(undefined, column.treeFooterAggregation);\n        if ( typeof(column.treeFooterAggregation.value) === 'undefined' || column.treeFooterAggregation.rendered === null ){\n          // The was apparently no aggregation performed (perhaps this is a grouped column\n          return '';\n        }\n        return column.treeFooterAggregation.rendered;\n      }\n    };\n\n    return service;\n\n  }]);\n\n\n  /**\n   *  @ngdoc directive\n   *  @name ui.grid.treeBase.directive:uiGridTreeRowHeaderButtons\n   *  @element div\n   *\n   *  @description Provides the expand/collapse button on rows\n   */\n  module.directive('uiGridTreeBaseRowHeaderButtons', ['$templateCache', 'uiGridTreeBaseService',\n  function ($templateCache, uiGridTreeBaseService) {\n    return {\n      replace: true,\n      restrict: 'E',\n      template: $templateCache.get('ui-grid/treeBaseRowHeaderButtons'),\n      scope: true,\n      require: '^uiGrid',\n      link: function($scope, $elm, $attrs, uiGridCtrl) {\n        var self = uiGridCtrl.grid;\n        $scope.treeButtonClick = function(row, evt) {\n          uiGridTreeBaseService.toggleRowTreeState(self, row, evt);\n        };\n      }\n    };\n  }]);\n\n\n  /**\n   *  @ngdoc directive\n   *  @name ui.grid.treeBase.directive:uiGridTreeBaseExpandAllButtons\n   *  @element div\n   *\n   *  @description Provides the expand/collapse all button\n   */\n  module.directive('uiGridTreeBaseExpandAllButtons', ['$templateCache', 'uiGridTreeBaseService',\n  function ($templateCache, uiGridTreeBaseService) {\n    return {\n      replace: true,\n      restrict: 'E',\n      template: $templateCache.get('ui-grid/treeBaseExpandAllButtons'),\n      scope: false,\n      link: function($scope, $elm, $attrs, uiGridCtrl) {\n        var self = $scope.col.grid;\n\n        $scope.headerButtonClick = function(row, evt) {\n          if ( self.treeBase.expandAll ){\n            uiGridTreeBaseService.collapseAllRows(self, evt);\n          } else {\n            uiGridTreeBaseService.expandAllRows(self, evt);\n          }\n        };\n      }\n    };\n  }]);\n\n\n  /**\n   *  @ngdoc directive\n   *  @name ui.grid.treeBase.directive:uiGridViewport\n   *  @element div\n   *\n   *  @description Stacks on top of ui.grid.uiGridViewport to set formatting on a tree header row\n   */\n  module.directive('uiGridViewport',\n  ['$compile', 'uiGridConstants', 'gridUtil', '$parse',\n    function ($compile, uiGridConstants, gridUtil, $parse) {\n      return {\n        priority: -200, // run after default  directive\n        scope: false,\n        compile: function ($elm, $attrs) {\n          var rowRepeatDiv = angular.element($elm.children().children()[0]);\n\n          var existingNgClass = rowRepeatDiv.attr(\"ng-class\");\n          var newNgClass = '';\n          if ( existingNgClass ) {\n            newNgClass = existingNgClass.slice(0, -1) + \",'ui-grid-tree-header-row': row.treeLevel > -1}\";\n          } else {\n            newNgClass = \"{'ui-grid-tree-header-row': row.treeLevel > -1}\";\n          }\n          rowRepeatDiv.attr(\"ng-class\", newNgClass);\n\n          return {\n            pre: function ($scope, $elm, $attrs, controllers) {\n\n            },\n            post: function ($scope, $elm, $attrs, controllers) {\n            }\n          };\n        }\n      };\n    }]);\n})();\n\n(function () {\n  'use strict';\n\n  /**\n   * @ngdoc overview\n   * @name ui.grid.treeView\n   * @description\n   *\n   * # ui.grid.treeView\n   *\n   * <div class=\"alert alert-warning\" role=\"alert\"><strong>Beta</strong> This feature is ready for testing, but it either hasn't seen a lot of use or has some known bugs.</div>\n   *\n   * This module provides a tree view of the data that it is provided, with nodes in that\n   * tree and leaves.  Unlike grouping, the tree is an inherent property of the data and must\n   * be provided with your data array.\n   *\n   * Design information:\n   * -------------------\n   *\n   * TreeView uses treeBase for the underlying functionality, and is a very thin wrapper around\n   * that logic.  Most of the design information has now moved to treebase.\n   * <br/>\n   * <br/>\n   *\n   * <div doc-module-components=\"ui.grid.treeView\"></div>\n   */\n\n  var module = angular.module('ui.grid.treeView', ['ui.grid', 'ui.grid.treeBase']);\n\n  /**\n   *  @ngdoc object\n   *  @name ui.grid.treeView.constant:uiGridTreeViewConstants\n   *\n   *  @description constants available in treeView module, this includes\n   *  all the constants declared in the treeBase module (these are manually copied\n   *  as there isn't an easy way to include constants in another constants file, and\n   *  we don't want to make users include treeBase)\n   *\n   */\n  module.constant('uiGridTreeViewConstants', {\n    featureName: \"treeView\",\n    rowHeaderColName: 'treeBaseRowHeaderCol',\n    EXPANDED: 'expanded',\n    COLLAPSED: 'collapsed',\n    aggregation: {\n      COUNT: 'count',\n      SUM: 'sum',\n      MAX: 'max',\n      MIN: 'min',\n      AVG: 'avg'\n    }\n  });\n\n  /**\n   *  @ngdoc service\n   *  @name ui.grid.treeView.service:uiGridTreeViewService\n   *\n   *  @description Services for treeView features\n   */\n  module.service('uiGridTreeViewService', ['$q', 'uiGridTreeViewConstants', 'uiGridTreeBaseConstants', 'uiGridTreeBaseService', 'gridUtil', 'GridRow', 'gridClassFactory', 'i18nService', 'uiGridConstants',\n  function ($q, uiGridTreeViewConstants, uiGridTreeBaseConstants, uiGridTreeBaseService, gridUtil, GridRow, gridClassFactory, i18nService, uiGridConstants) {\n\n    var service = {\n\n      initializeGrid: function (grid, $scope) {\n        uiGridTreeBaseService.initializeGrid( grid, $scope );\n\n        /**\n         *  @ngdoc object\n         *  @name ui.grid.treeView.grid:treeView\n         *\n         *  @description Grid properties and functions added for treeView\n         */\n        grid.treeView = {};\n\n        grid.registerRowsProcessor(service.adjustSorting, 60);\n\n        /**\n         *  @ngdoc object\n         *  @name ui.grid.treeView.api:PublicApi\n         *\n         *  @description Public Api for treeView feature\n         */\n        var publicApi = {\n          events: {\n            treeView: {\n            }\n          },\n          methods: {\n            treeView: {\n            }\n          }\n        };\n\n        grid.api.registerEventsFromObject(publicApi.events);\n\n        grid.api.registerMethodsFromObject(publicApi.methods);\n\n      },\n\n      defaultGridOptions: function (gridOptions) {\n        //default option to true unless it was explicitly set to false\n        /**\n         *  @ngdoc object\n         *  @name ui.grid.treeView.api:GridOptions\n         *\n         *  @description GridOptions for treeView feature, these are available to be\n         *  set using the ui-grid {@link ui.grid.class:GridOptions gridOptions}\n         *\n         *  Many tree options are set on treeBase, make sure to look at that feature in\n         *  conjunction with these options.\n         */\n\n        /**\n         *  @ngdoc object\n         *  @name enableTreeView\n         *  @propertyOf  ui.grid.treeView.api:GridOptions\n         *  @description Enable row tree view for entire grid.\n         *  <br/>Defaults to true\n         */\n        gridOptions.enableTreeView = gridOptions.enableTreeView !== false;\n\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name adjustSorting\n       * @methodOf  ui.grid.treeBase.service:uiGridTreeBaseService\n       * @description Trees cannot be sorted the same as flat lists of rows -\n       * trees are sorted recursively within each level - so the children of each\n       * node are sorted, but not the full set of rows.\n       *\n       * To achieve this, we suppress the normal sorting by setting ignoreSort on\n       * each of the sort columns.  When the treeBase rowsProcessor runs it will then\n       * unignore these, and will perform a recursive sort against the tree that it builds.\n       *\n       * @param {array} renderableRows the rows that we need to pass on through\n       * @returns {array} renderableRows that we passed on through\n       */\n      adjustSorting: function( renderableRows ) {\n        var grid = this;\n\n        grid.columns.forEach( function( column ){\n          if ( column.sort ){\n            column.sort.ignoreSort = true;\n          }\n        });\n\n        return renderableRows;\n      }\n\n    };\n\n    return service;\n\n  }]);\n\n  /**\n   *  @ngdoc directive\n   *  @name ui.grid.treeView.directive:uiGridTreeView\n   *  @element div\n   *  @restrict A\n   *\n   *  @description Adds treeView features to grid\n   *\n   *  @example\n   <example module=\"app\">\n   <file name=\"app.js\">\n   var app = angular.module('app', ['ui.grid', 'ui.grid.treeView']);\n\n   app.controller('MainCtrl', ['$scope', function ($scope) {\n      $scope.data = [\n        { name: 'Bob', title: 'CEO' },\n            { name: 'Frank', title: 'Lowly Developer' }\n      ];\n\n      $scope.columnDefs = [\n        {name: 'name', enableCellEdit: true},\n        {name: 'title', enableCellEdit: true}\n      ];\n\n      $scope.gridOptions = { columnDefs: $scope.columnDefs, data: $scope.data };\n    }]);\n   </file>\n   <file name=\"index.html\">\n   <div ng-controller=\"MainCtrl\">\n   <div ui-grid=\"gridOptions\" ui-grid-tree-view></div>\n   </div>\n   </file>\n   </example>\n   */\n  module.directive('uiGridTreeView', ['uiGridTreeViewConstants', 'uiGridTreeViewService', '$templateCache',\n  function (uiGridTreeViewConstants, uiGridTreeViewService, $templateCache) {\n    return {\n      replace: true,\n      priority: 0,\n      require: '^uiGrid',\n      scope: false,\n      compile: function () {\n        return {\n          pre: function ($scope, $elm, $attrs, uiGridCtrl) {\n            if (uiGridCtrl.grid.options.enableTreeView !== false){\n              uiGridTreeViewService.initializeGrid(uiGridCtrl.grid, $scope);\n            }\n          },\n          post: function ($scope, $elm, $attrs, uiGridCtrl) {\n\n          }\n        };\n      }\n    };\n  }]);\n})();\n\nangular.module('ui.grid').run(['$templateCache', function($templateCache) {\n  'use strict';\n\n  $templateCache.put('ui-grid/ui-grid-filter',\n    \"<div class=\\\"ui-grid-filter-container\\\" ng-repeat=\\\"colFilter in col.filters\\\" ng-class=\\\"{'ui-grid-filter-cancel-button-hidden' : colFilter.disableCancelFilterButton === true }\\\"><div ng-if=\\\"colFilter.type !== 'select'\\\"><input type=\\\"text\\\" class=\\\"ui-grid-filter-input ui-grid-filter-input-{{$index}}\\\" ng-model=\\\"colFilter.term\\\" ng-attr-placeholder=\\\"{{colFilter.placeholder || ''}}\\\" aria-label=\\\"{{colFilter.ariaLabel || aria.defaultFilterLabel}}\\\"><div role=\\\"button\\\" class=\\\"ui-grid-filter-button\\\" ng-click=\\\"removeFilter(colFilter, $index)\\\" ng-if=\\\"!colFilter.disableCancelFilterButton\\\" ng-disabled=\\\"colFilter.term === undefined || colFilter.term === null || colFilter.term === ''\\\" ng-show=\\\"colFilter.term !== undefined && colFilter.term !== null && colFilter.term !== ''\\\"><i class=\\\"ui-grid-icon-cancel\\\" ui-grid-one-bind-aria-label=\\\"aria.removeFilter\\\">&nbsp;</i></div></div><div ng-if=\\\"colFilter.type === 'select'\\\"><select class=\\\"ui-grid-filter-select ui-grid-filter-input-{{$index}}\\\" ng-model=\\\"colFilter.term\\\" ng-attr-placeholder=\\\"{{colFilter.placeholder || aria.defaultFilterLabel}}\\\" aria-label=\\\"{{colFilter.ariaLabel || ''}}\\\" ng-options=\\\"option.value as option.label for option in colFilter.selectOptions\\\"><option value=\\\"\\\"></option></select><div role=\\\"button\\\" class=\\\"ui-grid-filter-button-select\\\" ng-click=\\\"removeFilter(colFilter, $index)\\\" ng-if=\\\"!colFilter.disableCancelFilterButton\\\" ng-disabled=\\\"colFilter.term === undefined || colFilter.term === null || colFilter.term === ''\\\" ng-show=\\\"colFilter.term !== undefined && colFilter.term != null\\\"><i class=\\\"ui-grid-icon-cancel\\\" ui-grid-one-bind-aria-label=\\\"aria.removeFilter\\\">&nbsp;</i></div></div></div>\"\n  );\n\n\n  $templateCache.put('ui-grid/ui-grid-footer',\n    \"<div class=\\\"ui-grid-footer-panel ui-grid-footer-aggregates-row\\\"><!-- tfooter --><div class=\\\"ui-grid-footer ui-grid-footer-viewport\\\"><div class=\\\"ui-grid-footer-canvas\\\"><div class=\\\"ui-grid-footer-cell-wrapper\\\" ng-style=\\\"colContainer.headerCellWrapperStyle()\\\"><div role=\\\"row\\\" class=\\\"ui-grid-footer-cell-row\\\"><div ui-grid-footer-cell role=\\\"gridcell\\\" ng-repeat=\\\"col in colContainer.renderedColumns track by col.uid\\\" col=\\\"col\\\" render-index=\\\"$index\\\" class=\\\"ui-grid-footer-cell ui-grid-clearfix\\\"></div></div></div></div></div></div>\"\n  );\n\n\n  $templateCache.put('ui-grid/ui-grid-grid-footer',\n    \"<div class=\\\"ui-grid-footer-info ui-grid-grid-footer\\\"><span>{{'search.totalItems' | t}} {{grid.rows.length}}</span> <span ng-if=\\\"grid.renderContainers.body.visibleRowCache.length !== grid.rows.length\\\" class=\\\"ngLabel\\\">({{\\\"search.showingItems\\\" | t}} {{grid.renderContainers.body.visibleRowCache.length}})</span></div>\"\n  );\n\n\n  $templateCache.put('ui-grid/ui-grid-group-panel',\n    \"<div class=\\\"ui-grid-group-panel\\\"><div ui-t=\\\"groupPanel.description\\\" class=\\\"description\\\" ng-show=\\\"groupings.length == 0\\\"></div><ul ng-show=\\\"groupings.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>\"\n  );\n\n\n  $templateCache.put('ui-grid/ui-grid-header',\n    \"<div role=\\\"rowgroup\\\" class=\\\"ui-grid-header\\\"><!-- theader --><div class=\\\"ui-grid-top-panel\\\"><div class=\\\"ui-grid-header-viewport\\\"><div class=\\\"ui-grid-header-canvas\\\"><div class=\\\"ui-grid-header-cell-wrapper\\\" ng-style=\\\"colContainer.headerCellWrapperStyle()\\\"><div role=\\\"row\\\" class=\\\"ui-grid-header-cell-row\\\"><div class=\\\"ui-grid-header-cell ui-grid-clearfix\\\" ng-repeat=\\\"col in colContainer.renderedColumns track by col.uid\\\" ui-grid-header-cell col=\\\"col\\\" render-index=\\\"$index\\\"></div></div></div></div></div></div></div>\"\n  );\n\n\n  $templateCache.put('ui-grid/ui-grid-menu-button',\n    \"<div class=\\\"ui-grid-menu-button\\\"><div role=\\\"button\\\" ui-grid-one-bind-id-grid=\\\"'grid-menu'\\\" class=\\\"ui-grid-icon-container\\\" ng-click=\\\"toggleMenu()\\\" aria-haspopup=\\\"true\\\"><i class=\\\"ui-grid-icon-menu\\\" ui-grid-one-bind-aria-label=\\\"i18n.aria.buttonLabel\\\">&nbsp;</i></div><div ui-grid-menu menu-items=\\\"menuItems\\\"></div></div>\"\n  );\n\n\n  $templateCache.put('ui-grid/ui-grid-no-header',\n    \"<div class=\\\"ui-grid-top-panel\\\"></div>\"\n  );\n\n\n  $templateCache.put('ui-grid/ui-grid-row',\n    \"<div ng-repeat=\\\"(colRenderIndex, col) in colContainer.renderedColumns track by col.uid\\\" ui-grid-one-bind-id-grid=\\\"rowRenderIndex + '-' + col.uid + '-cell'\\\" class=\\\"ui-grid-cell\\\" ng-class=\\\"{ 'ui-grid-row-header-cell': col.isRowHeader }\\\" role=\\\"{{col.isRowHeader ? 'rowheader' : 'gridcell'}}\\\" ui-grid-cell></div>\"\n  );\n\n\n  $templateCache.put('ui-grid/ui-grid',\n    \"<div ui-i18n=\\\"en\\\" class=\\\"ui-grid\\\"><!-- TODO (c0bra): add \\\"scoped\\\" attr here, eventually? --><style ui-grid-style>.grid{{ grid.id }} {\\n\" +\n    \"      /* Styles for the grid */\\n\" +\n    \"    }\\n\" +\n    \"\\n\" +\n    \"    .grid{{ grid.id }} .ui-grid-row, .grid{{ grid.id }} .ui-grid-cell, .grid{{ grid.id }} .ui-grid-cell .ui-grid-vertical-bar {\\n\" +\n    \"      height: {{ grid.options.rowHeight }}px;\\n\" +\n    \"    }\\n\" +\n    \"\\n\" +\n    \"    .grid{{ grid.id }} .ui-grid-row:last-child .ui-grid-cell {\\n\" +\n    \"      border-bottom-width: {{ ((grid.getTotalRowHeight() < grid.getViewportHeight()) && '1') || '0' }}px;\\n\" +\n    \"    }\\n\" +\n    \"\\n\" +\n    \"    {{ grid.verticalScrollbarStyles }}\\n\" +\n    \"    {{ grid.horizontalScrollbarStyles }}\\n\" +\n    \"\\n\" +\n    \"    /*\\n\" +\n    \"    .ui-grid[dir=rtl] .ui-grid-viewport {\\n\" +\n    \"      padding-left: {{ grid.verticalScrollbarWidth }}px;\\n\" +\n    \"    }\\n\" +\n    \"    */\\n\" +\n    \"\\n\" +\n    \"    {{ grid.customStyles }}</style><div class=\\\"ui-grid-contents-wrapper\\\"><div ui-grid-menu-button ng-if=\\\"grid.options.enableGridMenu\\\"></div><div ng-if=\\\"grid.hasLeftContainer()\\\" style=\\\"width: 0\\\" ui-grid-pinned-container=\\\"'left'\\\"></div><div ui-grid-render-container container-id=\\\"'body'\\\" col-container-name=\\\"'body'\\\" row-container-name=\\\"'body'\\\" bind-scroll-horizontal=\\\"true\\\" bind-scroll-vertical=\\\"true\\\" enable-horizontal-scrollbar=\\\"grid.options.enableHorizontalScrollbar\\\" enable-vertical-scrollbar=\\\"grid.options.enableVerticalScrollbar\\\"></div><div ng-if=\\\"grid.hasRightContainer()\\\" style=\\\"width: 0\\\" ui-grid-pinned-container=\\\"'right'\\\"></div><div ui-grid-grid-footer ng-if=\\\"grid.options.showGridFooter\\\"></div><div ui-grid-column-menu ng-if=\\\"grid.options.enableColumnMenus\\\"></div><div ng-transclude></div></div></div>\"\n  );\n\n\n  $templateCache.put('ui-grid/uiGridCell',\n    \"<div class=\\\"ui-grid-cell-contents\\\" title=\\\"TOOLTIP\\\">{{COL_FIELD CUSTOM_FILTERS}}</div>\"\n  );\n\n\n  $templateCache.put('ui-grid/uiGridColumnMenu',\n    \"<div class=\\\"ui-grid-column-menu\\\"><div ui-grid-menu menu-items=\\\"menuItems\\\"><!-- <div class=\\\"ui-grid-column-menu\\\">\\n\" +\n    \"    <div class=\\\"inner\\\" ng-show=\\\"menuShown\\\">\\n\" +\n    \"      <ul>\\n\" +\n    \"        <div ng-show=\\\"grid.options.enableSorting\\\">\\n\" +\n    \"          <li ng-click=\\\"sortColumn($event, asc)\\\" ng-class=\\\"{ 'selected' : col.sort.direction == asc }\\\"><i class=\\\"ui-grid-icon-sort-alt-up\\\"></i> Sort Ascending</li>\\n\" +\n    \"          <li ng-click=\\\"sortColumn($event, desc)\\\" ng-class=\\\"{ 'selected' : col.sort.direction == desc }\\\"><i class=\\\"ui-grid-icon-sort-alt-down\\\"></i> Sort Descending</li>\\n\" +\n    \"          <li ng-show=\\\"col.sort.direction\\\" ng-click=\\\"unsortColumn()\\\"><i class=\\\"ui-grid-icon-cancel\\\"></i> Remove Sort</li>\\n\" +\n    \"        </div>\\n\" +\n    \"      </ul>\\n\" +\n    \"    </div>\\n\" +\n    \"  </div> --></div></div>\"\n  );\n\n\n  $templateCache.put('ui-grid/uiGridFooterCell',\n    \"<div class=\\\"ui-grid-cell-contents\\\" col-index=\\\"renderIndex\\\"><div>{{ col.getAggregationText() + ( col.getAggregationValue() CUSTOM_FILTERS ) }}</div></div>\"\n  );\n\n\n  $templateCache.put('ui-grid/uiGridHeaderCell',\n    \"<div role=\\\"columnheader\\\" ng-class=\\\"{ 'sortable': sortable }\\\" ui-grid-one-bind-aria-labelledby-grid=\\\"col.uid + '-header-text ' + col.uid + '-sortdir-text'\\\" aria-sort=\\\"{{col.sort.direction == asc ? 'ascending' : ( col.sort.direction == desc ? 'descending' : (!col.sort.direction ? 'none' : 'other'))}}\\\"><div role=\\\"button\\\" tabindex=\\\"0\\\" class=\\\"ui-grid-cell-contents ui-grid-header-cell-primary-focus\\\" col-index=\\\"renderIndex\\\" title=\\\"TOOLTIP\\\"><span ui-grid-one-bind-id-grid=\\\"col.uid + '-header-text'\\\">{{ col.displayName CUSTOM_FILTERS }}</span> <span ui-grid-one-bind-id-grid=\\\"col.uid + '-sortdir-text'\\\" ui-grid-visible=\\\"col.sort.direction\\\" aria-label=\\\"{{getSortDirectionAriaLabel()}}\\\"><i ng-class=\\\"{ 'ui-grid-icon-up-dir': col.sort.direction == asc, 'ui-grid-icon-down-dir': col.sort.direction == desc, 'ui-grid-icon-blank': !col.sort.direction }\\\" title=\\\"{{col.sort.priority ? i18n.headerCell.priority + ' ' + col.sort.priority : null}}\\\" aria-hidden=\\\"true\\\">&nbsp;</i></span></div><div role=\\\"button\\\" tabindex=\\\"0\\\" ui-grid-one-bind-id-grid=\\\"col.uid + '-menu-button'\\\" class=\\\"ui-grid-column-menu-button\\\" ng-if=\\\"grid.options.enableColumnMenus && !col.isRowHeader  && col.colDef.enableColumnMenu !== false\\\" ng-click=\\\"toggleMenu($event)\\\" ng-class=\\\"{'ui-grid-column-menu-button-last-col': isLastCol}\\\" ui-grid-one-bind-aria-label=\\\"i18n.headerCell.aria.columnMenuButtonLabel\\\" aria-haspopup=\\\"true\\\"><i class=\\\"ui-grid-icon-angle-down\\\" aria-hidden=\\\"true\\\">&nbsp;</i></div><div ui-grid-filter></div></div>\"\n  );\n\n\n  $templateCache.put('ui-grid/uiGridMenu',\n    \"<div class=\\\"ui-grid-menu\\\" ng-if=\\\"shown\\\"><div class=\\\"ui-grid-menu-mid\\\" ng-show=\\\"shownMid\\\"><div class=\\\"ui-grid-menu-inner\\\"><button type=\\\"button\\\" ng-focus=\\\"focus=true\\\" ng-blur=\\\"focus=false\\\" class=\\\"ui-grid-menu-close-button\\\" ng-class=\\\"{'ui-grid-sr-only': (!focus)}\\\"><i class=\\\"ui-grid-icon-cancel\\\" ui-grid-one-bind-aria-label=\\\"i18n.close\\\"></i></button><ul role=\\\"menu\\\" class=\\\"ui-grid-menu-items\\\"><li ng-repeat=\\\"item in menuItems\\\" role=\\\"menuitem\\\" ui-grid-menu-item ui-grid-one-bind-id=\\\"'menuitem-'+$index\\\" action=\\\"item.action\\\" name=\\\"item.title\\\" active=\\\"item.active\\\" icon=\\\"item.icon\\\" shown=\\\"item.shown\\\" context=\\\"item.context\\\" template-url=\\\"item.templateUrl\\\" leave-open=\\\"item.leaveOpen\\\" screen-reader-only=\\\"item.screenReaderOnly\\\"></li></ul></div></div></div>\"\n  );\n\n\n  $templateCache.put('ui-grid/uiGridMenuItem',\n    \"<button type=\\\"button\\\" class=\\\"ui-grid-menu-item\\\" ng-click=\\\"itemAction($event, title)\\\" ng-show=\\\"itemShown()\\\" ng-class=\\\"{ 'ui-grid-menu-item-active': active(), 'ui-grid-sr-only': (!focus && screenReaderOnly) }\\\" aria-pressed=\\\"{{active()}}\\\" tabindex=\\\"0\\\" ng-focus=\\\"focus=true\\\" ng-blur=\\\"focus=false\\\"><i ng-class=\\\"icon\\\" aria-hidden=\\\"true\\\">&nbsp;</i> {{ name }}</button>\"\n  );\n\n\n  $templateCache.put('ui-grid/uiGridRenderContainer',\n    \"<div role=\\\"grid\\\" ui-grid-one-bind-id-grid=\\\"'grid-container'\\\" class=\\\"ui-grid-render-container\\\" ng-style=\\\"{ 'margin-left': colContainer.getMargin('left') + 'px', 'margin-right': colContainer.getMargin('right') + 'px' }\\\"><!-- All of these dom elements are replaced in place --><div ui-grid-header></div><div ui-grid-viewport></div><div ng-if=\\\"colContainer.needsHScrollbarPlaceholder()\\\" class=\\\"ui-grid-scrollbar-placeholder\\\" style=\\\"height:{{colContainer.grid.scrollbarHeight}}px\\\"></div><ui-grid-footer ng-if=\\\"grid.options.showColumnFooter\\\"></ui-grid-footer></div>\"\n  );\n\n\n  $templateCache.put('ui-grid/uiGridViewport',\n    \"<div role=\\\"rowgroup\\\" class=\\\"ui-grid-viewport\\\" ng-style=\\\"colContainer.getViewportStyle()\\\"><!-- tbody --><div class=\\\"ui-grid-canvas\\\"><div ng-repeat=\\\"(rowRenderIndex, row) in rowContainer.renderedRows track by $index\\\" class=\\\"ui-grid-row\\\" ng-style=\\\"Viewport.rowStyle(rowRenderIndex)\\\"><div role=\\\"row\\\" ui-grid-row=\\\"row\\\" row-render-index=\\\"rowRenderIndex\\\"></div></div></div></div>\"\n  );\n\n\n  $templateCache.put('ui-grid/cellEditor',\n    \"<div><form name=\\\"inputForm\\\"><input type=\\\"INPUT_TYPE\\\" ng-class=\\\"'colt' + col.uid\\\" ui-grid-editor ng-model=\\\"MODEL_COL_FIELD\\\"></form></div>\"\n  );\n\n\n  $templateCache.put('ui-grid/dropdownEditor',\n    \"<div><form name=\\\"inputForm\\\"><select ng-class=\\\"'colt' + col.uid\\\" ui-grid-edit-dropdown ng-model=\\\"MODEL_COL_FIELD\\\" ng-options=\\\"field[editDropdownIdLabel] as field[editDropdownValueLabel] CUSTOM_FILTERS for field in editDropdownOptionsArray\\\"></select></form></div>\"\n  );\n\n\n  $templateCache.put('ui-grid/fileChooserEditor',\n    \"<div><form name=\\\"inputForm\\\"><input ng-class=\\\"'colt' + col.uid\\\" ui-grid-edit-file-chooser type=\\\"file\\\" id=\\\"files\\\" name=\\\"files[]\\\" ng-model=\\\"MODEL_COL_FIELD\\\"></form></div>\"\n  );\n\n\n  $templateCache.put('ui-grid/expandableRow',\n    \"<div ui-grid-expandable-row ng-if=\\\"expandableRow.shouldRenderExpand()\\\" class=\\\"expandableRow\\\" style=\\\"float:left; margin-top: 1px; margin-bottom: 1px\\\" ng-style=\\\"{width: (grid.renderContainers.body.getCanvasWidth()) + 'px', height: grid.options.expandableRowHeight + 'px'}\\\"></div>\"\n  );\n\n\n  $templateCache.put('ui-grid/expandableRowHeader',\n    \"<div class=\\\"ui-grid-row-header-cell ui-grid-expandable-buttons-cell\\\"><div class=\\\"ui-grid-cell-contents\\\"><i ng-class=\\\"{ 'ui-grid-icon-plus-squared' : !row.isExpanded, 'ui-grid-icon-minus-squared' : row.isExpanded }\\\" ng-click=\\\"grid.api.expandable.toggleRowExpansion(row.entity)\\\"></i></div></div>\"\n  );\n\n\n  $templateCache.put('ui-grid/expandableScrollFiller',\n    \"<div ng-if=\\\"expandableRow.shouldRenderFiller()\\\" ng-class=\\\"{scrollFiller:true, scrollFillerClass:(colContainer.name === 'body')}\\\" ng-style=\\\"{ width: (grid.getViewportWidth()) + 'px', height: grid.options.expandableRowHeight + 2 + 'px', 'margin-left': grid.options.rowHeader.rowHeaderWidth + 'px' }\\\"><i class=\\\"ui-grid-icon-spin5 ui-grid-animate-spin\\\" ng-style=\\\"{'margin-top': ( grid.options.expandableRowHeight/2 - 5) + 'px', 'margin-left' : ((grid.getViewportWidth() - grid.options.rowHeader.rowHeaderWidth)/2 - 5) + 'px'}\\\"></i></div>\"\n  );\n\n\n  $templateCache.put('ui-grid/expandableTopRowHeader',\n    \"<div class=\\\"ui-grid-row-header-cell ui-grid-expandable-buttons-cell\\\"><div class=\\\"ui-grid-cell-contents\\\"><i ng-class=\\\"{ 'ui-grid-icon-plus-squared' : !grid.expandable.expandedAll, 'ui-grid-icon-minus-squared' : grid.expandable.expandedAll }\\\" ng-click=\\\"grid.api.expandable.toggleAllRows()\\\"></i></div></div>\"\n  );\n\n\n  $templateCache.put('ui-grid/csvLink',\n    \"<span class=\\\"ui-grid-exporter-csv-link-span\\\"><a href=\\\"data:text/csv;charset=UTF-8,CSV_CONTENT\\\" download=\\\"FILE_NAME\\\">LINK_LABEL</a></span>\"\n  );\n\n\n  $templateCache.put('ui-grid/importerMenuItem',\n    \"<li class=\\\"ui-grid-menu-item\\\"><form><input class=\\\"ui-grid-importer-file-chooser\\\" type=\\\"file\\\" id=\\\"files\\\" name=\\\"files[]\\\"></form></li>\"\n  );\n\n\n  $templateCache.put('ui-grid/importerMenuItemContainer',\n    \"<div ui-grid-importer-menu-item></div>\"\n  );\n\n\n  $templateCache.put('ui-grid/pagination',\n    \"<div role=\\\"contentinfo\\\" class=\\\"ui-grid-pager-panel\\\" ui-grid-pager ng-show=\\\"grid.options.enablePaginationControls\\\"><div role=\\\"navigation\\\" class=\\\"ui-grid-pager-container\\\"><div role=\\\"menubar\\\" class=\\\"ui-grid-pager-control\\\"><button type=\\\"button\\\" role=\\\"menuitem\\\" class=\\\"ui-grid-pager-first\\\" ui-grid-one-bind-title=\\\"aria.pageToFirst\\\" ui-grid-one-bind-aria-label=\\\"aria.pageToFirst\\\" ng-click=\\\"pageFirstPageClick()\\\" ng-disabled=\\\"cantPageBackward()\\\"><div class=\\\"first-triangle\\\"><div class=\\\"first-bar\\\"></div></div></button> <button type=\\\"button\\\" role=\\\"menuitem\\\" class=\\\"ui-grid-pager-previous\\\" ui-grid-one-bind-title=\\\"aria.pageBack\\\" ui-grid-one-bind-aria-label=\\\"aria.pageBack\\\" ng-click=\\\"pagePreviousPageClick()\\\" ng-disabled=\\\"cantPageBackward()\\\"><div class=\\\"first-triangle prev-triangle\\\"></div></button> <input type=\\\"number\\\" ui-grid-one-bind-title=\\\"aria.pageSelected\\\" ui-grid-one-bind-aria-label=\\\"aria.pageSelected\\\" class=\\\"ui-grid-pager-control-input\\\" ng-model=\\\"grid.options.paginationCurrentPage\\\" min=\\\"1\\\" max=\\\"{{ paginationApi.getTotalPages() }}\\\" required> <span class=\\\"ui-grid-pager-max-pages-number\\\" ng-show=\\\"paginationApi.getTotalPages() > 0\\\"><abbr ui-grid-one-bind-title=\\\"paginationOf\\\">/</abbr> {{ paginationApi.getTotalPages() }}</span> <button type=\\\"button\\\" role=\\\"menuitem\\\" class=\\\"ui-grid-pager-next\\\" ui-grid-one-bind-title=\\\"aria.pageForward\\\" ui-grid-one-bind-aria-label=\\\"aria.pageForward\\\" ng-click=\\\"pageNextPageClick()\\\" ng-disabled=\\\"cantPageForward()\\\"><div class=\\\"last-triangle next-triangle\\\"></div></button> <button type=\\\"button\\\" role=\\\"menuitem\\\" class=\\\"ui-grid-pager-last\\\" ui-grid-one-bind-title=\\\"aria.pageToLast\\\" ui-grid-one-bind-aria-label=\\\"aria.pageToLast\\\" ng-click=\\\"pageLastPageClick()\\\" ng-disabled=\\\"cantPageToLast()\\\"><div class=\\\"last-triangle\\\"><div class=\\\"last-bar\\\"></div></div></button></div><div class=\\\"ui-grid-pager-row-count-picker\\\" ng-if=\\\"grid.options.paginationPageSizes.length > 1\\\"><select ui-grid-one-bind-aria-labelledby-grid=\\\"'items-per-page-label'\\\" ng-model=\\\"grid.options.paginationPageSize\\\" ng-options=\\\"o as o for o in grid.options.paginationPageSizes\\\"></select><span ui-grid-one-bind-id-grid=\\\"'items-per-page-label'\\\" class=\\\"ui-grid-pager-row-count-label\\\">&nbsp;{{sizesLabel}}</span></div><span ng-if=\\\"grid.options.paginationPageSizes.length <= 1\\\" class=\\\"ui-grid-pager-row-count-label\\\">{{grid.options.paginationPageSize}}&nbsp;{{sizesLabel}}</span></div><div class=\\\"ui-grid-pager-count-container\\\"><div class=\\\"ui-grid-pager-count\\\"><span ng-show=\\\"grid.options.totalItems > 0\\\">{{showingLow}} <abbr ui-grid-one-bind-title=\\\"paginationThrough\\\">-</abbr> {{showingHigh}} {{paginationOf}} {{grid.options.totalItems}} {{totalItemsLabel}}</span></div></div></div>\"\n  );\n\n\n  $templateCache.put('ui-grid/columnResizer',\n    \"<div ui-grid-column-resizer ng-if=\\\"grid.options.enableColumnResizing\\\" class=\\\"ui-grid-column-resizer\\\" col=\\\"col\\\" position=\\\"right\\\" render-index=\\\"renderIndex\\\" unselectable=\\\"on\\\"></div>\"\n  );\n\n\n  $templateCache.put('ui-grid/gridFooterSelectedItems',\n    \"<span ng-if=\\\"grid.selection.selectedCount !== 0 && grid.options.enableFooterTotalSelected\\\">({{\\\"search.selectedItems\\\" | t}} {{grid.selection.selectedCount}})</span>\"\n  );\n\n\n  $templateCache.put('ui-grid/selectionHeaderCell',\n    \"<div><!-- <div class=\\\"ui-grid-vertical-bar\\\">&nbsp;</div> --><div class=\\\"ui-grid-cell-contents\\\" col-index=\\\"renderIndex\\\"><ui-grid-selection-select-all-buttons ng-if=\\\"grid.options.enableSelectAll\\\"></ui-grid-selection-select-all-buttons></div></div>\"\n  );\n\n\n  $templateCache.put('ui-grid/selectionRowHeader',\n    \"<div class=\\\"ui-grid-disable-selection\\\"><div class=\\\"ui-grid-cell-contents\\\"><ui-grid-selection-row-header-buttons></ui-grid-selection-row-header-buttons></div></div>\"\n  );\n\n\n  $templateCache.put('ui-grid/selectionRowHeaderButtons',\n    \"<div class=\\\"ui-grid-selection-row-header-buttons ui-grid-icon-ok\\\" ng-class=\\\"{'ui-grid-row-selected': row.isSelected}\\\" ng-click=\\\"selectButtonClick(row, $event)\\\">&nbsp;</div>\"\n  );\n\n\n  $templateCache.put('ui-grid/selectionSelectAllButtons',\n    \"<div class=\\\"ui-grid-selection-row-header-buttons ui-grid-icon-ok\\\" ng-class=\\\"{'ui-grid-all-selected': grid.selection.selectAll}\\\" ng-click=\\\"headerButtonClick($event)\\\"></div>\"\n  );\n\n\n  $templateCache.put('ui-grid/treeBaseExpandAllButtons',\n    \"<div class=\\\"ui-grid-tree-base-row-header-buttons\\\" ng-class=\\\"{'ui-grid-icon-minus-squared': grid.treeBase.numberLevels > 0 && grid.treeBase.expandAll, 'ui-grid-icon-plus-squared': grid.treeBase.numberLevels > 0 && !grid.treeBase.expandAll}\\\" ng-click=\\\"headerButtonClick($event)\\\"></div>\"\n  );\n\n\n  $templateCache.put('ui-grid/treeBaseHeaderCell',\n    \"<div><div class=\\\"ui-grid-cell-contents\\\" col-index=\\\"renderIndex\\\"><ui-grid-tree-base-expand-all-buttons></ui-grid-tree-base-expand-all-buttons></div></div>\"\n  );\n\n\n  $templateCache.put('ui-grid/treeBaseRowHeader',\n    \"<div class=\\\"ui-grid-cell-contents\\\"><ui-grid-tree-base-row-header-buttons></ui-grid-tree-base-row-header-buttons></div>\"\n  );\n\n\n  $templateCache.put('ui-grid/treeBaseRowHeaderButtons',\n    \"<div class=\\\"ui-grid-tree-base-row-header-buttons\\\" ng-class=\\\"{'ui-grid-tree-base-header': row.treeLevel > -1 }\\\" ng-click=\\\"treeButtonClick(row, $event)\\\"><i ng-class=\\\"{'ui-grid-icon-minus-squared': ( ( grid.options.showTreeExpandNoChildren && row.treeLevel > -1 ) || ( row.treeNode.children && row.treeNode.children.length > 0 ) ) && row.treeNode.state === 'expanded', 'ui-grid-icon-plus-squared': ( ( grid.options.showTreeExpandNoChildren && row.treeLevel > -1 ) || ( row.treeNode.children && row.treeNode.children.length > 0 ) ) && row.treeNode.state === 'collapsed'}\\\" ng-style=\\\"{'padding-left': grid.options.treeIndent * row.treeLevel + 'px'}\\\"></i> &nbsp;</div>\"\n  );\n\n}]);\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/angular/.bower.json",
    "content": "{\n  \"name\": \"angular\",\n  \"version\": \"1.3.13\",\n  \"main\": \"./angular.js\",\n  \"ignore\": [],\n  \"dependencies\": {},\n  \"homepage\": \"https://github.com/angular/bower-angular\",\n  \"_release\": \"1.3.13\",\n  \"_resolution\": {\n    \"type\": \"version\",\n    \"tag\": \"v1.3.13\",\n    \"commit\": \"ad68cfecb69ff7cacb27813377ce9d95e072529b\"\n  },\n  \"_source\": \"https://github.com/angular/bower-angular.git\",\n  \"_target\": \"1.3.13\",\n  \"_originalSource\": \"angular\"\n}"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/angular/README.md",
    "content": "# packaged angular\n\nThis repo is for distribution on `npm` and `bower`. The source for this module is in the\n[main AngularJS repo](https://github.com/angular/angular.js).\nPlease file issues and pull requests against that repo.\n\n## Install\n\nYou can install this package either with `npm` or with `bower`.\n\n### npm\n\n```shell\nnpm install angular\n```\n\nThen add a `<script>` to your `index.html`:\n\n```html\n<script src=\"/node_modules/angular/angular.js\"></script>\n```\n\nNote that this package is not in CommonJS format, so doing `require('angular')` will return `undefined`.\nIf you're using [Browserify](https://github.com/substack/node-browserify), you can use\n[exposify](https://github.com/thlorenz/exposify) to have `require('angular')` return the `angular`\nglobal.\n\n### bower\n\n```shell\nbower install angular\n```\n\nThen add a `<script>` to your `index.html`:\n\n```html\n<script src=\"/bower_components/angular/angular.js\"></script>\n```\n\n## Documentation\n\nDocumentation is available on the\n[AngularJS docs site](http://docs.angularjs.org/).\n\n## License\n\nThe MIT License\n\nCopyright (c) 2010-2012 Google, Inc. http://angularjs.org\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies 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 FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/angular/angular-csp.css",
    "content": "/* Include this file in your html if you are using the CSP mode. */\n\n@charset \"UTF-8\";\n\n[ng\\:cloak], [ng-cloak], [data-ng-cloak], [x-ng-cloak],\n.ng-cloak, .x-ng-cloak,\n.ng-hide:not(.ng-hide-animate) {\n  display: none !important;\n}\n\nng\\:form {\n  display: block;\n}\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/angular/angular.js",
    "content": "/**\n * @license AngularJS v1.3.13\n * (c) 2010-2014 Google, Inc. http://angularjs.org\n * License: MIT\n */\n(function(window, document, undefined) {'use strict';\n\n/**\n * @description\n *\n * This object provides a utility for producing rich Error messages within\n * Angular. It can be called as follows:\n *\n * var exampleMinErr = minErr('example');\n * throw exampleMinErr('one', 'This {0} is {1}', foo, bar);\n *\n * The above creates an instance of minErr in the example namespace. The\n * resulting error will have a namespaced error code of example.one.  The\n * resulting error will replace {0} with the value of foo, and {1} with the\n * value of bar. The object is not restricted in the number of arguments it can\n * take.\n *\n * If fewer arguments are specified than necessary for interpolation, the extra\n * interpolation markers will be preserved in the final string.\n *\n * Since data will be parsed statically during a build step, some restrictions\n * are applied with respect to how minErr instances are created and called.\n * Instances should have names of the form namespaceMinErr for a minErr created\n * using minErr('namespace') . Error codes, namespaces and template strings\n * should all be static strings, not variables or general expressions.\n *\n * @param {string} module The namespace to use for the new minErr instance.\n * @param {function} ErrorConstructor Custom error constructor to be instantiated when returning\n *   error from returned function, for cases when a particular type of error is useful.\n * @returns {function(code:string, template:string, ...templateArgs): Error} minErr instance\n */\n\nfunction minErr(module, ErrorConstructor) {\n  ErrorConstructor = ErrorConstructor || Error;\n  return function() {\n    var code = arguments[0],\n      prefix = '[' + (module ? module + ':' : '') + code + '] ',\n      template = arguments[1],\n      templateArgs = arguments,\n\n      message, i;\n\n    message = prefix + template.replace(/\\{\\d+\\}/g, function(match) {\n      var index = +match.slice(1, -1), arg;\n\n      if (index + 2 < templateArgs.length) {\n        return toDebugString(templateArgs[index + 2]);\n      }\n      return match;\n    });\n\n    message = message + '\\nhttp://errors.angularjs.org/1.3.13/' +\n      (module ? module + '/' : '') + code;\n    for (i = 2; i < arguments.length; i++) {\n      message = message + (i == 2 ? '?' : '&') + 'p' + (i - 2) + '=' +\n        encodeURIComponent(toDebugString(arguments[i]));\n    }\n    return new ErrorConstructor(message);\n  };\n}\n\n/* We need to tell jshint what variables are being exported */\n/* global angular: true,\n  msie: true,\n  jqLite: true,\n  jQuery: true,\n  slice: true,\n  splice: true,\n  push: true,\n  toString: true,\n  ngMinErr: true,\n  angularModule: true,\n  uid: true,\n  REGEX_STRING_REGEXP: true,\n  VALIDITY_STATE_PROPERTY: true,\n\n  lowercase: true,\n  uppercase: true,\n  manualLowercase: true,\n  manualUppercase: true,\n  nodeName_: true,\n  isArrayLike: true,\n  forEach: true,\n  sortedKeys: true,\n  forEachSorted: true,\n  reverseParams: true,\n  nextUid: true,\n  setHashKey: true,\n  extend: true,\n  int: true,\n  inherit: true,\n  noop: true,\n  identity: true,\n  valueFn: true,\n  isUndefined: true,\n  isDefined: true,\n  isObject: true,\n  isString: true,\n  isNumber: true,\n  isDate: true,\n  isArray: true,\n  isFunction: true,\n  isRegExp: true,\n  isWindow: true,\n  isScope: true,\n  isFile: true,\n  isFormData: true,\n  isBlob: true,\n  isBoolean: true,\n  isPromiseLike: true,\n  trim: true,\n  escapeForRegexp: true,\n  isElement: true,\n  makeMap: true,\n  includes: true,\n  arrayRemove: true,\n  copy: true,\n  shallowCopy: true,\n  equals: true,\n  csp: true,\n  concat: true,\n  sliceArgs: true,\n  bind: true,\n  toJsonReplacer: true,\n  toJson: true,\n  fromJson: true,\n  startingTag: true,\n  tryDecodeURIComponent: true,\n  parseKeyValue: true,\n  toKeyValue: true,\n  encodeUriSegment: true,\n  encodeUriQuery: true,\n  angularInit: true,\n  bootstrap: true,\n  getTestability: true,\n  snake_case: true,\n  bindJQuery: true,\n  assertArg: true,\n  assertArgFn: true,\n  assertNotHasOwnProperty: true,\n  getter: true,\n  getBlockNodes: true,\n  hasOwnProperty: true,\n  createMap: true,\n\n  NODE_TYPE_ELEMENT: true,\n  NODE_TYPE_TEXT: true,\n  NODE_TYPE_COMMENT: true,\n  NODE_TYPE_DOCUMENT: true,\n  NODE_TYPE_DOCUMENT_FRAGMENT: true,\n*/\n\n////////////////////////////////////\n\n/**\n * @ngdoc module\n * @name ng\n * @module ng\n * @description\n *\n * # ng (core module)\n * The ng module is loaded by default when an AngularJS application is started. The module itself\n * contains the essential components for an AngularJS application to function. The table below\n * lists a high level breakdown of each of the services/factories, filters, directives and testing\n * components available within this core module.\n *\n * <div doc-module-components=\"ng\"></div>\n */\n\nvar REGEX_STRING_REGEXP = /^\\/(.+)\\/([a-z]*)$/;\n\n// The name of a form control's ValidityState property.\n// This is used so that it's possible for internal tests to create mock ValidityStates.\nvar VALIDITY_STATE_PROPERTY = 'validity';\n\n/**\n * @ngdoc function\n * @name angular.lowercase\n * @module ng\n * @kind function\n *\n * @description Converts the specified string to lowercase.\n * @param {string} string String to be converted to lowercase.\n * @returns {string} Lowercased string.\n */\nvar lowercase = function(string) {return isString(string) ? string.toLowerCase() : string;};\nvar hasOwnProperty = Object.prototype.hasOwnProperty;\n\n/**\n * @ngdoc function\n * @name angular.uppercase\n * @module ng\n * @kind function\n *\n * @description Converts the specified string to uppercase.\n * @param {string} string String to be converted to uppercase.\n * @returns {string} Uppercased string.\n */\nvar uppercase = function(string) {return isString(string) ? string.toUpperCase() : string;};\n\n\nvar manualLowercase = function(s) {\n  /* jshint bitwise: false */\n  return isString(s)\n      ? s.replace(/[A-Z]/g, function(ch) {return String.fromCharCode(ch.charCodeAt(0) | 32);})\n      : s;\n};\nvar manualUppercase = function(s) {\n  /* jshint bitwise: false */\n  return isString(s)\n      ? s.replace(/[a-z]/g, function(ch) {return String.fromCharCode(ch.charCodeAt(0) & ~32);})\n      : s;\n};\n\n\n// String#toLowerCase and String#toUpperCase don't produce correct results in browsers with Turkish\n// locale, for this reason we need to detect this case and redefine lowercase/uppercase methods\n// with correct but slower alternatives.\nif ('i' !== 'I'.toLowerCase()) {\n  lowercase = manualLowercase;\n  uppercase = manualUppercase;\n}\n\n\nvar\n    msie,             // holds major version number for IE, or NaN if UA is not IE.\n    jqLite,           // delay binding since jQuery could be loaded after us.\n    jQuery,           // delay binding\n    slice             = [].slice,\n    splice            = [].splice,\n    push              = [].push,\n    toString          = Object.prototype.toString,\n    ngMinErr          = minErr('ng'),\n\n    /** @name angular */\n    angular           = window.angular || (window.angular = {}),\n    angularModule,\n    uid               = 0;\n\n/**\n * documentMode is an IE-only property\n * http://msdn.microsoft.com/en-us/library/ie/cc196988(v=vs.85).aspx\n */\nmsie = document.documentMode;\n\n\n/**\n * @private\n * @param {*} obj\n * @return {boolean} Returns true if `obj` is an array or array-like object (NodeList, Arguments,\n *                   String ...)\n */\nfunction isArrayLike(obj) {\n  if (obj == null || isWindow(obj)) {\n    return false;\n  }\n\n  var length = obj.length;\n\n  if (obj.nodeType === NODE_TYPE_ELEMENT && length) {\n    return true;\n  }\n\n  return isString(obj) || isArray(obj) || length === 0 ||\n         typeof length === 'number' && length > 0 && (length - 1) in obj;\n}\n\n/**\n * @ngdoc function\n * @name angular.forEach\n * @module ng\n * @kind function\n *\n * @description\n * Invokes the `iterator` function once for each item in `obj` collection, which can be either an\n * object or an array. The `iterator` function is invoked with `iterator(value, key, obj)`, where `value`\n * is the value of an object property or an array element, `key` is the object property key or\n * array element index and obj is the `obj` itself. Specifying a `context` for the function is optional.\n *\n * It is worth noting that `.forEach` does not iterate over inherited properties because it filters\n * using the `hasOwnProperty` method.\n *\n * Unlike ES262's\n * [Array.prototype.forEach](http://www.ecma-international.org/ecma-262/5.1/#sec-15.4.4.18),\n * Providing 'undefined' or 'null' values for `obj` will not throw a TypeError, but rather just\n * return the value provided.\n *\n   ```js\n     var values = {name: 'misko', gender: 'male'};\n     var log = [];\n     angular.forEach(values, function(value, key) {\n       this.push(key + ': ' + value);\n     }, log);\n     expect(log).toEqual(['name: misko', 'gender: male']);\n   ```\n *\n * @param {Object|Array} obj Object to iterate over.\n * @param {Function} iterator Iterator function.\n * @param {Object=} context Object to become context (`this`) for the iterator function.\n * @returns {Object|Array} Reference to `obj`.\n */\n\nfunction forEach(obj, iterator, context) {\n  var key, length;\n  if (obj) {\n    if (isFunction(obj)) {\n      for (key in obj) {\n        // Need to check if hasOwnProperty exists,\n        // as on IE8 the result of querySelectorAll is an object without a hasOwnProperty function\n        if (key != 'prototype' && key != 'length' && key != 'name' && (!obj.hasOwnProperty || obj.hasOwnProperty(key))) {\n          iterator.call(context, obj[key], key, obj);\n        }\n      }\n    } else if (isArray(obj) || isArrayLike(obj)) {\n      var isPrimitive = typeof obj !== 'object';\n      for (key = 0, length = obj.length; key < length; key++) {\n        if (isPrimitive || key in obj) {\n          iterator.call(context, obj[key], key, obj);\n        }\n      }\n    } else if (obj.forEach && obj.forEach !== forEach) {\n        obj.forEach(iterator, context, obj);\n    } else {\n      for (key in obj) {\n        if (obj.hasOwnProperty(key)) {\n          iterator.call(context, obj[key], key, obj);\n        }\n      }\n    }\n  }\n  return obj;\n}\n\nfunction sortedKeys(obj) {\n  return Object.keys(obj).sort();\n}\n\nfunction forEachSorted(obj, iterator, context) {\n  var keys = sortedKeys(obj);\n  for (var i = 0; i < keys.length; i++) {\n    iterator.call(context, obj[keys[i]], keys[i]);\n  }\n  return keys;\n}\n\n\n/**\n * when using forEach the params are value, key, but it is often useful to have key, value.\n * @param {function(string, *)} iteratorFn\n * @returns {function(*, string)}\n */\nfunction reverseParams(iteratorFn) {\n  return function(value, key) { iteratorFn(key, value); };\n}\n\n/**\n * A consistent way of creating unique IDs in angular.\n *\n * Using simple numbers allows us to generate 28.6 million unique ids per second for 10 years before\n * we hit number precision issues in JavaScript.\n *\n * Math.pow(2,53) / 60 / 60 / 24 / 365 / 10 = 28.6M\n *\n * @returns {number} an unique alpha-numeric string\n */\nfunction nextUid() {\n  return ++uid;\n}\n\n\n/**\n * Set or clear the hashkey for an object.\n * @param obj object\n * @param h the hashkey (!truthy to delete the hashkey)\n */\nfunction setHashKey(obj, h) {\n  if (h) {\n    obj.$$hashKey = h;\n  } else {\n    delete obj.$$hashKey;\n  }\n}\n\n/**\n * @ngdoc function\n * @name angular.extend\n * @module ng\n * @kind function\n *\n * @description\n * Extends the destination object `dst` by copying own enumerable properties from the `src` object(s)\n * to `dst`. You can specify multiple `src` objects. If you want to preserve original objects, you can do so\n * by passing an empty object as the target: `var object = angular.extend({}, object1, object2)`.\n * Note: Keep in mind that `angular.extend` does not support recursive merge (deep copy).\n *\n * @param {Object} dst Destination object.\n * @param {...Object} src Source object(s).\n * @returns {Object} Reference to `dst`.\n */\nfunction extend(dst) {\n  var h = dst.$$hashKey;\n\n  for (var i = 1, ii = arguments.length; i < ii; i++) {\n    var obj = arguments[i];\n    if (obj) {\n      var keys = Object.keys(obj);\n      for (var j = 0, jj = keys.length; j < jj; j++) {\n        var key = keys[j];\n        dst[key] = obj[key];\n      }\n    }\n  }\n\n  setHashKey(dst, h);\n  return dst;\n}\n\nfunction int(str) {\n  return parseInt(str, 10);\n}\n\n\nfunction inherit(parent, extra) {\n  return extend(Object.create(parent), extra);\n}\n\n/**\n * @ngdoc function\n * @name angular.noop\n * @module ng\n * @kind function\n *\n * @description\n * A function that performs no operations. This function can be useful when writing code in the\n * functional style.\n   ```js\n     function foo(callback) {\n       var result = calculateResult();\n       (callback || angular.noop)(result);\n     }\n   ```\n */\nfunction noop() {}\nnoop.$inject = [];\n\n\n/**\n * @ngdoc function\n * @name angular.identity\n * @module ng\n * @kind function\n *\n * @description\n * A function that returns its first argument. This function is useful when writing code in the\n * functional style.\n *\n   ```js\n     function transformer(transformationFn, value) {\n       return (transformationFn || angular.identity)(value);\n     };\n   ```\n  * @param {*} value to be returned.\n  * @returns {*} the value passed in.\n */\nfunction identity($) {return $;}\nidentity.$inject = [];\n\n\nfunction valueFn(value) {return function() {return value;};}\n\n/**\n * @ngdoc function\n * @name angular.isUndefined\n * @module ng\n * @kind function\n *\n * @description\n * Determines if a reference is undefined.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is undefined.\n */\nfunction isUndefined(value) {return typeof value === 'undefined';}\n\n\n/**\n * @ngdoc function\n * @name angular.isDefined\n * @module ng\n * @kind function\n *\n * @description\n * Determines if a reference is defined.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is defined.\n */\nfunction isDefined(value) {return typeof value !== 'undefined';}\n\n\n/**\n * @ngdoc function\n * @name angular.isObject\n * @module ng\n * @kind function\n *\n * @description\n * Determines if a reference is an `Object`. Unlike `typeof` in JavaScript, `null`s are not\n * considered to be objects. Note that JavaScript arrays are objects.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is an `Object` but not `null`.\n */\nfunction isObject(value) {\n  // http://jsperf.com/isobject4\n  return value !== null && typeof value === 'object';\n}\n\n\n/**\n * @ngdoc function\n * @name angular.isString\n * @module ng\n * @kind function\n *\n * @description\n * Determines if a reference is a `String`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `String`.\n */\nfunction isString(value) {return typeof value === 'string';}\n\n\n/**\n * @ngdoc function\n * @name angular.isNumber\n * @module ng\n * @kind function\n *\n * @description\n * Determines if a reference is a `Number`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Number`.\n */\nfunction isNumber(value) {return typeof value === 'number';}\n\n\n/**\n * @ngdoc function\n * @name angular.isDate\n * @module ng\n * @kind function\n *\n * @description\n * Determines if a value is a date.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Date`.\n */\nfunction isDate(value) {\n  return toString.call(value) === '[object Date]';\n}\n\n\n/**\n * @ngdoc function\n * @name angular.isArray\n * @module ng\n * @kind function\n *\n * @description\n * Determines if a reference is an `Array`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is an `Array`.\n */\nvar isArray = Array.isArray;\n\n/**\n * @ngdoc function\n * @name angular.isFunction\n * @module ng\n * @kind function\n *\n * @description\n * Determines if a reference is a `Function`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Function`.\n */\nfunction isFunction(value) {return typeof value === 'function';}\n\n\n/**\n * Determines if a value is a regular expression object.\n *\n * @private\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `RegExp`.\n */\nfunction isRegExp(value) {\n  return toString.call(value) === '[object RegExp]';\n}\n\n\n/**\n * Checks if `obj` is a window object.\n *\n * @private\n * @param {*} obj Object to check\n * @returns {boolean} True if `obj` is a window obj.\n */\nfunction isWindow(obj) {\n  return obj && obj.window === obj;\n}\n\n\nfunction isScope(obj) {\n  return obj && obj.$evalAsync && obj.$watch;\n}\n\n\nfunction isFile(obj) {\n  return toString.call(obj) === '[object File]';\n}\n\n\nfunction isFormData(obj) {\n  return toString.call(obj) === '[object FormData]';\n}\n\n\nfunction isBlob(obj) {\n  return toString.call(obj) === '[object Blob]';\n}\n\n\nfunction isBoolean(value) {\n  return typeof value === 'boolean';\n}\n\n\nfunction isPromiseLike(obj) {\n  return obj && isFunction(obj.then);\n}\n\n\nvar trim = function(value) {\n  return isString(value) ? value.trim() : value;\n};\n\n// Copied from:\n// http://docs.closure-library.googlecode.com/git/local_closure_goog_string_string.js.source.html#line1021\n// Prereq: s is a string.\nvar escapeForRegexp = function(s) {\n  return s.replace(/([-()\\[\\]{}+?*.$\\^|,:#<!\\\\])/g, '\\\\$1').\n           replace(/\\x08/g, '\\\\x08');\n};\n\n\n/**\n * @ngdoc function\n * @name angular.isElement\n * @module ng\n * @kind function\n *\n * @description\n * Determines if a reference is a DOM element (or wrapped jQuery element).\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a DOM element (or wrapped jQuery element).\n */\nfunction isElement(node) {\n  return !!(node &&\n    (node.nodeName  // we are a direct element\n    || (node.prop && node.attr && node.find)));  // we have an on and find method part of jQuery API\n}\n\n/**\n * @param str 'key1,key2,...'\n * @returns {object} in the form of {key1:true, key2:true, ...}\n */\nfunction makeMap(str) {\n  var obj = {}, items = str.split(\",\"), i;\n  for (i = 0; i < items.length; i++)\n    obj[items[i]] = true;\n  return obj;\n}\n\n\nfunction nodeName_(element) {\n  return lowercase(element.nodeName || (element[0] && element[0].nodeName));\n}\n\nfunction includes(array, obj) {\n  return Array.prototype.indexOf.call(array, obj) != -1;\n}\n\nfunction arrayRemove(array, value) {\n  var index = array.indexOf(value);\n  if (index >= 0)\n    array.splice(index, 1);\n  return value;\n}\n\n/**\n * @ngdoc function\n * @name angular.copy\n * @module ng\n * @kind function\n *\n * @description\n * Creates a deep copy of `source`, which should be an object or an array.\n *\n * * If no destination is supplied, a copy of the object or array is created.\n * * If a destination is provided, all of its elements (for arrays) or properties (for objects)\n *   are deleted and then all elements/properties from the source are copied to it.\n * * If `source` is not an object or array (inc. `null` and `undefined`), `source` is returned.\n * * If `source` is identical to 'destination' an exception will be thrown.\n *\n * @param {*} source The source that will be used to make a copy.\n *                   Can be any type, including primitives, `null`, and `undefined`.\n * @param {(Object|Array)=} destination Destination into which the source is copied. If\n *     provided, must be of the same type as `source`.\n * @returns {*} The copy or updated `destination`, if `destination` was specified.\n *\n * @example\n <example module=\"copyExample\">\n <file name=\"index.html\">\n <div ng-controller=\"ExampleController\">\n <form novalidate class=\"simple-form\">\n Name: <input type=\"text\" ng-model=\"user.name\" /><br />\n E-mail: <input type=\"email\" ng-model=\"user.email\" /><br />\n Gender: <input type=\"radio\" ng-model=\"user.gender\" value=\"male\" />male\n <input type=\"radio\" ng-model=\"user.gender\" value=\"female\" />female<br />\n <button ng-click=\"reset()\">RESET</button>\n <button ng-click=\"update(user)\">SAVE</button>\n </form>\n <pre>form = {{user | json}}</pre>\n <pre>master = {{master | json}}</pre>\n </div>\n\n <script>\n  angular.module('copyExample', [])\n    .controller('ExampleController', ['$scope', function($scope) {\n      $scope.master= {};\n\n      $scope.update = function(user) {\n        // Example with 1 argument\n        $scope.master= angular.copy(user);\n      };\n\n      $scope.reset = function() {\n        // Example with 2 arguments\n        angular.copy($scope.master, $scope.user);\n      };\n\n      $scope.reset();\n    }]);\n </script>\n </file>\n </example>\n */\nfunction copy(source, destination, stackSource, stackDest) {\n  if (isWindow(source) || isScope(source)) {\n    throw ngMinErr('cpws',\n      \"Can't copy! Making copies of Window or Scope instances is not supported.\");\n  }\n\n  if (!destination) {\n    destination = source;\n    if (source) {\n      if (isArray(source)) {\n        destination = copy(source, [], stackSource, stackDest);\n      } else if (isDate(source)) {\n        destination = new Date(source.getTime());\n      } else if (isRegExp(source)) {\n        destination = new RegExp(source.source, source.toString().match(/[^\\/]*$/)[0]);\n        destination.lastIndex = source.lastIndex;\n      } else if (isObject(source)) {\n        var emptyObject = Object.create(Object.getPrototypeOf(source));\n        destination = copy(source, emptyObject, stackSource, stackDest);\n      }\n    }\n  } else {\n    if (source === destination) throw ngMinErr('cpi',\n      \"Can't copy! Source and destination are identical.\");\n\n    stackSource = stackSource || [];\n    stackDest = stackDest || [];\n\n    if (isObject(source)) {\n      var index = stackSource.indexOf(source);\n      if (index !== -1) return stackDest[index];\n\n      stackSource.push(source);\n      stackDest.push(destination);\n    }\n\n    var result;\n    if (isArray(source)) {\n      destination.length = 0;\n      for (var i = 0; i < source.length; i++) {\n        result = copy(source[i], null, stackSource, stackDest);\n        if (isObject(source[i])) {\n          stackSource.push(source[i]);\n          stackDest.push(result);\n        }\n        destination.push(result);\n      }\n    } else {\n      var h = destination.$$hashKey;\n      if (isArray(destination)) {\n        destination.length = 0;\n      } else {\n        forEach(destination, function(value, key) {\n          delete destination[key];\n        });\n      }\n      for (var key in source) {\n        if (source.hasOwnProperty(key)) {\n          result = copy(source[key], null, stackSource, stackDest);\n          if (isObject(source[key])) {\n            stackSource.push(source[key]);\n            stackDest.push(result);\n          }\n          destination[key] = result;\n        }\n      }\n      setHashKey(destination,h);\n    }\n\n  }\n  return destination;\n}\n\n/**\n * Creates a shallow copy of an object, an array or a primitive.\n *\n * Assumes that there are no proto properties for objects.\n */\nfunction shallowCopy(src, dst) {\n  if (isArray(src)) {\n    dst = dst || [];\n\n    for (var i = 0, ii = src.length; i < ii; i++) {\n      dst[i] = src[i];\n    }\n  } else if (isObject(src)) {\n    dst = dst || {};\n\n    for (var key in src) {\n      if (!(key.charAt(0) === '$' && key.charAt(1) === '$')) {\n        dst[key] = src[key];\n      }\n    }\n  }\n\n  return dst || src;\n}\n\n\n/**\n * @ngdoc function\n * @name angular.equals\n * @module ng\n * @kind function\n *\n * @description\n * Determines if two objects or two values are equivalent. Supports value types, regular\n * expressions, arrays and objects.\n *\n * Two objects or values are considered equivalent if at least one of the following is true:\n *\n * * Both objects or values pass `===` comparison.\n * * Both objects or values are of the same type and all of their properties are equal by\n *   comparing them with `angular.equals`.\n * * Both values are NaN. (In JavaScript, NaN == NaN => false. But we consider two NaN as equal)\n * * Both values represent the same regular expression (In JavaScript,\n *   /abc/ == /abc/ => false. But we consider two regular expressions as equal when their textual\n *   representation matches).\n *\n * During a property comparison, properties of `function` type and properties with names\n * that begin with `$` are ignored.\n *\n * Scope and DOMWindow objects are being compared only by identify (`===`).\n *\n * @param {*} o1 Object or value to compare.\n * @param {*} o2 Object or value to compare.\n * @returns {boolean} True if arguments are equal.\n */\nfunction equals(o1, o2) {\n  if (o1 === o2) return true;\n  if (o1 === null || o2 === null) return false;\n  if (o1 !== o1 && o2 !== o2) return true; // NaN === NaN\n  var t1 = typeof o1, t2 = typeof o2, length, key, keySet;\n  if (t1 == t2) {\n    if (t1 == 'object') {\n      if (isArray(o1)) {\n        if (!isArray(o2)) return false;\n        if ((length = o1.length) == o2.length) {\n          for (key = 0; key < length; key++) {\n            if (!equals(o1[key], o2[key])) return false;\n          }\n          return true;\n        }\n      } else if (isDate(o1)) {\n        if (!isDate(o2)) return false;\n        return equals(o1.getTime(), o2.getTime());\n      } else if (isRegExp(o1) && isRegExp(o2)) {\n        return o1.toString() == o2.toString();\n      } else {\n        if (isScope(o1) || isScope(o2) || isWindow(o1) || isWindow(o2) || isArray(o2)) return false;\n        keySet = {};\n        for (key in o1) {\n          if (key.charAt(0) === '$' || isFunction(o1[key])) continue;\n          if (!equals(o1[key], o2[key])) return false;\n          keySet[key] = true;\n        }\n        for (key in o2) {\n          if (!keySet.hasOwnProperty(key) &&\n              key.charAt(0) !== '$' &&\n              o2[key] !== undefined &&\n              !isFunction(o2[key])) return false;\n        }\n        return true;\n      }\n    }\n  }\n  return false;\n}\n\nvar csp = function() {\n  if (isDefined(csp.isActive_)) return csp.isActive_;\n\n  var active = !!(document.querySelector('[ng-csp]') ||\n                  document.querySelector('[data-ng-csp]'));\n\n  if (!active) {\n    try {\n      /* jshint -W031, -W054 */\n      new Function('');\n      /* jshint +W031, +W054 */\n    } catch (e) {\n      active = true;\n    }\n  }\n\n  return (csp.isActive_ = active);\n};\n\n\n\nfunction concat(array1, array2, index) {\n  return array1.concat(slice.call(array2, index));\n}\n\nfunction sliceArgs(args, startIndex) {\n  return slice.call(args, startIndex || 0);\n}\n\n\n/* jshint -W101 */\n/**\n * @ngdoc function\n * @name angular.bind\n * @module ng\n * @kind function\n *\n * @description\n * Returns a function which calls function `fn` bound to `self` (`self` becomes the `this` for\n * `fn`). You can supply optional `args` that are prebound to the function. This feature is also\n * known as [partial application](http://en.wikipedia.org/wiki/Partial_application), as\n * distinguished from [function currying](http://en.wikipedia.org/wiki/Currying#Contrast_with_partial_function_application).\n *\n * @param {Object} self Context which `fn` should be evaluated in.\n * @param {function()} fn Function to be bound.\n * @param {...*} args Optional arguments to be prebound to the `fn` function call.\n * @returns {function()} Function that wraps the `fn` with all the specified bindings.\n */\n/* jshint +W101 */\nfunction bind(self, fn) {\n  var curryArgs = arguments.length > 2 ? sliceArgs(arguments, 2) : [];\n  if (isFunction(fn) && !(fn instanceof RegExp)) {\n    return curryArgs.length\n      ? function() {\n          return arguments.length\n            ? fn.apply(self, concat(curryArgs, arguments, 0))\n            : fn.apply(self, curryArgs);\n        }\n      : function() {\n          return arguments.length\n            ? fn.apply(self, arguments)\n            : fn.call(self);\n        };\n  } else {\n    // in IE, native methods are not functions so they cannot be bound (note: they don't need to be)\n    return fn;\n  }\n}\n\n\nfunction toJsonReplacer(key, value) {\n  var val = value;\n\n  if (typeof key === 'string' && key.charAt(0) === '$' && key.charAt(1) === '$') {\n    val = undefined;\n  } else if (isWindow(value)) {\n    val = '$WINDOW';\n  } else if (value &&  document === value) {\n    val = '$DOCUMENT';\n  } else if (isScope(value)) {\n    val = '$SCOPE';\n  }\n\n  return val;\n}\n\n\n/**\n * @ngdoc function\n * @name angular.toJson\n * @module ng\n * @kind function\n *\n * @description\n * Serializes input into a JSON-formatted string. Properties with leading $$ characters will be\n * stripped since angular uses this notation internally.\n *\n * @param {Object|Array|Date|string|number} obj Input to be serialized into JSON.\n * @param {boolean|number=} pretty If set to true, the JSON output will contain newlines and whitespace.\n *    If set to an integer, the JSON output will contain that many spaces per indentation (the default is 2).\n * @returns {string|undefined} JSON-ified string representing `obj`.\n */\nfunction toJson(obj, pretty) {\n  if (typeof obj === 'undefined') return undefined;\n  if (!isNumber(pretty)) {\n    pretty = pretty ? 2 : null;\n  }\n  return JSON.stringify(obj, toJsonReplacer, pretty);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.fromJson\n * @module ng\n * @kind function\n *\n * @description\n * Deserializes a JSON string.\n *\n * @param {string} json JSON string to deserialize.\n * @returns {Object|Array|string|number} Deserialized JSON string.\n */\nfunction fromJson(json) {\n  return isString(json)\n      ? JSON.parse(json)\n      : json;\n}\n\n\n/**\n * @returns {string} Returns the string representation of the element.\n */\nfunction startingTag(element) {\n  element = jqLite(element).clone();\n  try {\n    // turns out IE does not let you set .html() on elements which\n    // are not allowed to have children. So we just ignore it.\n    element.empty();\n  } catch (e) {}\n  var elemHtml = jqLite('<div>').append(element).html();\n  try {\n    return element[0].nodeType === NODE_TYPE_TEXT ? lowercase(elemHtml) :\n        elemHtml.\n          match(/^(<[^>]+>)/)[1].\n          replace(/^<([\\w\\-]+)/, function(match, nodeName) { return '<' + lowercase(nodeName); });\n  } catch (e) {\n    return lowercase(elemHtml);\n  }\n\n}\n\n\n/////////////////////////////////////////////////\n\n/**\n * Tries to decode the URI component without throwing an exception.\n *\n * @private\n * @param str value potential URI component to check.\n * @returns {boolean} True if `value` can be decoded\n * with the decodeURIComponent function.\n */\nfunction tryDecodeURIComponent(value) {\n  try {\n    return decodeURIComponent(value);\n  } catch (e) {\n    // Ignore any invalid uri component\n  }\n}\n\n\n/**\n * Parses an escaped url query string into key-value pairs.\n * @returns {Object.<string,boolean|Array>}\n */\nfunction parseKeyValue(/**string*/keyValue) {\n  var obj = {}, key_value, key;\n  forEach((keyValue || \"\").split('&'), function(keyValue) {\n    if (keyValue) {\n      key_value = keyValue.replace(/\\+/g,'%20').split('=');\n      key = tryDecodeURIComponent(key_value[0]);\n      if (isDefined(key)) {\n        var val = isDefined(key_value[1]) ? tryDecodeURIComponent(key_value[1]) : true;\n        if (!hasOwnProperty.call(obj, key)) {\n          obj[key] = val;\n        } else if (isArray(obj[key])) {\n          obj[key].push(val);\n        } else {\n          obj[key] = [obj[key],val];\n        }\n      }\n    }\n  });\n  return obj;\n}\n\nfunction toKeyValue(obj) {\n  var parts = [];\n  forEach(obj, function(value, key) {\n    if (isArray(value)) {\n      forEach(value, function(arrayValue) {\n        parts.push(encodeUriQuery(key, true) +\n                   (arrayValue === true ? '' : '=' + encodeUriQuery(arrayValue, true)));\n      });\n    } else {\n    parts.push(encodeUriQuery(key, true) +\n               (value === true ? '' : '=' + encodeUriQuery(value, true)));\n    }\n  });\n  return parts.length ? parts.join('&') : '';\n}\n\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 */\nfunction 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 custom\n * method because encodeURIComponent is too aggressive and encodes stuff that doesn't have to be\n * 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 */\nfunction 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(/%3B/gi, ';').\n             replace(/%20/g, (pctEncodeSpaces ? '%20' : '+'));\n}\n\nvar ngAttrPrefixes = ['ng-', 'data-ng-', 'ng:', 'x-ng-'];\n\nfunction getNgAttribute(element, ngAttr) {\n  var attr, i, ii = ngAttrPrefixes.length;\n  element = jqLite(element);\n  for (i = 0; i < ii; ++i) {\n    attr = ngAttrPrefixes[i] + ngAttr;\n    if (isString(attr = element.attr(attr))) {\n      return attr;\n    }\n  }\n  return null;\n}\n\n/**\n * @ngdoc directive\n * @name ngApp\n * @module ng\n *\n * @element ANY\n * @param {angular.Module} ngApp an optional application\n *   {@link angular.module module} name to load.\n * @param {boolean=} ngStrictDi if this attribute is present on the app element, the injector will be\n *   created in \"strict-di\" mode. This means that the application will fail to invoke functions which\n *   do not use explicit function annotation (and are thus unsuitable for minification), as described\n *   in {@link guide/di the Dependency Injection guide}, and useful debugging info will assist in\n *   tracking down the root of these bugs.\n *\n * @description\n *\n * Use this directive to **auto-bootstrap** an AngularJS application. The `ngApp` directive\n * designates the **root element** of the application and is typically placed near the root element\n * of the page - e.g. on the `<body>` or `<html>` tags.\n *\n * Only one AngularJS application can be auto-bootstrapped per HTML document. The first `ngApp`\n * found in the document will be used to define the root element to auto-bootstrap as an\n * application. To run multiple applications in an HTML document you must manually bootstrap them using\n * {@link angular.bootstrap} instead. AngularJS applications cannot be nested within each other.\n *\n * You can specify an **AngularJS module** to be used as the root module for the application.  This\n * module will be loaded into the {@link auto.$injector} when the application is bootstrapped. It\n * should contain the application code needed or have dependencies on other modules that will\n * contain the code. See {@link angular.module} for more information.\n *\n * In the example below if the `ngApp` directive were not placed on the `html` element then the\n * document would not be compiled, the `AppController` would not be instantiated and the `{{ a+b }}`\n * would not be resolved to `3`.\n *\n * `ngApp` is the easiest, and most common way to bootstrap an application.\n *\n <example module=\"ngAppDemo\">\n   <file name=\"index.html\">\n   <div ng-controller=\"ngAppDemoController\">\n     I can add: {{a}} + {{b}} =  {{ a+b }}\n   </div>\n   </file>\n   <file name=\"script.js\">\n   angular.module('ngAppDemo', []).controller('ngAppDemoController', function($scope) {\n     $scope.a = 1;\n     $scope.b = 2;\n   });\n   </file>\n </example>\n *\n * Using `ngStrictDi`, you would see something like this:\n *\n <example ng-app-included=\"true\">\n   <file name=\"index.html\">\n   <div ng-app=\"ngAppStrictDemo\" ng-strict-di>\n       <div ng-controller=\"GoodController1\">\n           I can add: {{a}} + {{b}} =  {{ a+b }}\n\n           <p>This renders because the controller does not fail to\n              instantiate, by using explicit annotation style (see\n              script.js for details)\n           </p>\n       </div>\n\n       <div ng-controller=\"GoodController2\">\n           Name: <input ng-model=\"name\"><br />\n           Hello, {{name}}!\n\n           <p>This renders because the controller does not fail to\n              instantiate, by using explicit annotation style\n              (see script.js for details)\n           </p>\n       </div>\n\n       <div ng-controller=\"BadController\">\n           I can add: {{a}} + {{b}} =  {{ a+b }}\n\n           <p>The controller could not be instantiated, due to relying\n              on automatic function annotations (which are disabled in\n              strict mode). As such, the content of this section is not\n              interpolated, and there should be an error in your web console.\n           </p>\n       </div>\n   </div>\n   </file>\n   <file name=\"script.js\">\n   angular.module('ngAppStrictDemo', [])\n     // BadController will fail to instantiate, due to relying on automatic function annotation,\n     // rather than an explicit annotation\n     .controller('BadController', function($scope) {\n       $scope.a = 1;\n       $scope.b = 2;\n     })\n     // Unlike BadController, GoodController1 and GoodController2 will not fail to be instantiated,\n     // due to using explicit annotations using the array style and $inject property, respectively.\n     .controller('GoodController1', ['$scope', function($scope) {\n       $scope.a = 1;\n       $scope.b = 2;\n     }])\n     .controller('GoodController2', GoodController2);\n     function GoodController2($scope) {\n       $scope.name = \"World\";\n     }\n     GoodController2.$inject = ['$scope'];\n   </file>\n   <file name=\"style.css\">\n   div[ng-controller] {\n       margin-bottom: 1em;\n       -webkit-border-radius: 4px;\n       border-radius: 4px;\n       border: 1px solid;\n       padding: .5em;\n   }\n   div[ng-controller^=Good] {\n       border-color: #d6e9c6;\n       background-color: #dff0d8;\n       color: #3c763d;\n   }\n   div[ng-controller^=Bad] {\n       border-color: #ebccd1;\n       background-color: #f2dede;\n       color: #a94442;\n       margin-bottom: 0;\n   }\n   </file>\n </example>\n */\nfunction angularInit(element, bootstrap) {\n  var appElement,\n      module,\n      config = {};\n\n  // The element `element` has priority over any other element\n  forEach(ngAttrPrefixes, function(prefix) {\n    var name = prefix + 'app';\n\n    if (!appElement && element.hasAttribute && element.hasAttribute(name)) {\n      appElement = element;\n      module = element.getAttribute(name);\n    }\n  });\n  forEach(ngAttrPrefixes, function(prefix) {\n    var name = prefix + 'app';\n    var candidate;\n\n    if (!appElement && (candidate = element.querySelector('[' + name.replace(':', '\\\\:') + ']'))) {\n      appElement = candidate;\n      module = candidate.getAttribute(name);\n    }\n  });\n  if (appElement) {\n    config.strictDi = getNgAttribute(appElement, \"strict-di\") !== null;\n    bootstrap(appElement, module ? [module] : [], config);\n  }\n}\n\n/**\n * @ngdoc function\n * @name angular.bootstrap\n * @module ng\n * @description\n * Use this function to manually start up angular application.\n *\n * See: {@link guide/bootstrap Bootstrap}\n *\n * Note that Protractor based end-to-end tests cannot use this function to bootstrap manually.\n * They must use {@link ng.directive:ngApp ngApp}.\n *\n * Angular will detect if it has been loaded into the browser more than once and only allow the\n * first loaded script to be bootstrapped and will report a warning to the browser console for\n * each of the subsequent scripts. This prevents strange results in applications, where otherwise\n * multiple instances of Angular try to work on the DOM.\n *\n * ```html\n * <!doctype html>\n * <html>\n * <body>\n * <div ng-controller=\"WelcomeController\">\n *   {{greeting}}\n * </div>\n *\n * <script src=\"angular.js\"></script>\n * <script>\n *   var app = angular.module('demo', [])\n *   .controller('WelcomeController', function($scope) {\n *       $scope.greeting = 'Welcome!';\n *   });\n *   angular.bootstrap(document, ['demo']);\n * </script>\n * </body>\n * </html>\n * ```\n *\n * @param {DOMElement} element DOM element which is the root of angular application.\n * @param {Array<String|Function|Array>=} modules an array of modules to load into the application.\n *     Each item in the array should be the name of a predefined module or a (DI annotated)\n *     function that will be invoked by the injector as a `config` block.\n *     See: {@link angular.module modules}\n * @param {Object=} config an object for defining configuration options for the application. The\n *     following keys are supported:\n *\n * * `strictDi` - disable automatic function annotation for the application. This is meant to\n *   assist in finding bugs which break minified code. Defaults to `false`.\n *\n * @returns {auto.$injector} Returns the newly created injector for this app.\n */\nfunction bootstrap(element, modules, config) {\n  if (!isObject(config)) config = {};\n  var defaultConfig = {\n    strictDi: false\n  };\n  config = extend(defaultConfig, config);\n  var doBootstrap = function() {\n    element = jqLite(element);\n\n    if (element.injector()) {\n      var tag = (element[0] === document) ? 'document' : startingTag(element);\n      //Encode angle brackets to prevent input from being sanitized to empty string #8683\n      throw ngMinErr(\n          'btstrpd',\n          \"App Already Bootstrapped with this Element '{0}'\",\n          tag.replace(/</,'&lt;').replace(/>/,'&gt;'));\n    }\n\n    modules = modules || [];\n    modules.unshift(['$provide', function($provide) {\n      $provide.value('$rootElement', element);\n    }]);\n\n    if (config.debugInfoEnabled) {\n      // Pushing so that this overrides `debugInfoEnabled` setting defined in user's `modules`.\n      modules.push(['$compileProvider', function($compileProvider) {\n        $compileProvider.debugInfoEnabled(true);\n      }]);\n    }\n\n    modules.unshift('ng');\n    var injector = createInjector(modules, config.strictDi);\n    injector.invoke(['$rootScope', '$rootElement', '$compile', '$injector',\n       function bootstrapApply(scope, element, compile, injector) {\n        scope.$apply(function() {\n          element.data('$injector', injector);\n          compile(element)(scope);\n        });\n      }]\n    );\n    return injector;\n  };\n\n  var NG_ENABLE_DEBUG_INFO = /^NG_ENABLE_DEBUG_INFO!/;\n  var NG_DEFER_BOOTSTRAP = /^NG_DEFER_BOOTSTRAP!/;\n\n  if (window && NG_ENABLE_DEBUG_INFO.test(window.name)) {\n    config.debugInfoEnabled = true;\n    window.name = window.name.replace(NG_ENABLE_DEBUG_INFO, '');\n  }\n\n  if (window && !NG_DEFER_BOOTSTRAP.test(window.name)) {\n    return doBootstrap();\n  }\n\n  window.name = window.name.replace(NG_DEFER_BOOTSTRAP, '');\n  angular.resumeBootstrap = function(extraModules) {\n    forEach(extraModules, function(module) {\n      modules.push(module);\n    });\n    return doBootstrap();\n  };\n\n  if (isFunction(angular.resumeDeferredBootstrap)) {\n    angular.resumeDeferredBootstrap();\n  }\n}\n\n/**\n * @ngdoc function\n * @name angular.reloadWithDebugInfo\n * @module ng\n * @description\n * Use this function to reload the current application with debug information turned on.\n * This takes precedence over a call to `$compileProvider.debugInfoEnabled(false)`.\n *\n * See {@link ng.$compileProvider#debugInfoEnabled} for more.\n */\nfunction reloadWithDebugInfo() {\n  window.name = 'NG_ENABLE_DEBUG_INFO!' + window.name;\n  window.location.reload();\n}\n\n/**\n * @name angular.getTestability\n * @module ng\n * @description\n * Get the testability service for the instance of Angular on the given\n * element.\n * @param {DOMElement} element DOM element which is the root of angular application.\n */\nfunction getTestability(rootElement) {\n  var injector = angular.element(rootElement).injector();\n  if (!injector) {\n    throw ngMinErr('test',\n      'no injector found for element argument to getTestability');\n  }\n  return injector.get('$$testability');\n}\n\nvar SNAKE_CASE_REGEXP = /[A-Z]/g;\nfunction snake_case(name, separator) {\n  separator = separator || '_';\n  return name.replace(SNAKE_CASE_REGEXP, function(letter, pos) {\n    return (pos ? separator : '') + letter.toLowerCase();\n  });\n}\n\nvar bindJQueryFired = false;\nvar skipDestroyOnNextJQueryCleanData;\nfunction bindJQuery() {\n  var originalCleanData;\n\n  if (bindJQueryFired) {\n    return;\n  }\n\n  // bind to jQuery if present;\n  jQuery = window.jQuery;\n  // Use jQuery if it exists with proper functionality, otherwise default to us.\n  // Angular 1.2+ requires jQuery 1.7+ for on()/off() support.\n  // Angular 1.3+ technically requires at least jQuery 2.1+ but it may work with older\n  // versions. It will not work for sure with jQuery <1.7, though.\n  if (jQuery && jQuery.fn.on) {\n    jqLite = jQuery;\n    extend(jQuery.fn, {\n      scope: JQLitePrototype.scope,\n      isolateScope: JQLitePrototype.isolateScope,\n      controller: JQLitePrototype.controller,\n      injector: JQLitePrototype.injector,\n      inheritedData: JQLitePrototype.inheritedData\n    });\n\n    // All nodes removed from the DOM via various jQuery APIs like .remove()\n    // are passed through jQuery.cleanData. Monkey-patch this method to fire\n    // the $destroy event on all removed nodes.\n    originalCleanData = jQuery.cleanData;\n    jQuery.cleanData = function(elems) {\n      var events;\n      if (!skipDestroyOnNextJQueryCleanData) {\n        for (var i = 0, elem; (elem = elems[i]) != null; i++) {\n          events = jQuery._data(elem, \"events\");\n          if (events && events.$destroy) {\n            jQuery(elem).triggerHandler('$destroy');\n          }\n        }\n      } else {\n        skipDestroyOnNextJQueryCleanData = false;\n      }\n      originalCleanData(elems);\n    };\n  } else {\n    jqLite = JQLite;\n  }\n\n  angular.element = jqLite;\n\n  // Prevent double-proxying.\n  bindJQueryFired = true;\n}\n\n/**\n * throw error if the argument is falsy.\n */\nfunction assertArg(arg, name, reason) {\n  if (!arg) {\n    throw ngMinErr('areq', \"Argument '{0}' is {1}\", (name || '?'), (reason || \"required\"));\n  }\n  return arg;\n}\n\nfunction assertArgFn(arg, name, acceptArrayAnnotation) {\n  if (acceptArrayAnnotation && isArray(arg)) {\n      arg = arg[arg.length - 1];\n  }\n\n  assertArg(isFunction(arg), name, 'not a function, got ' +\n      (arg && typeof arg === 'object' ? arg.constructor.name || 'Object' : typeof arg));\n  return arg;\n}\n\n/**\n * throw error if the name given is hasOwnProperty\n * @param  {String} name    the name to test\n * @param  {String} context the context in which the name is used, such as module or directive\n */\nfunction assertNotHasOwnProperty(name, context) {\n  if (name === 'hasOwnProperty') {\n    throw ngMinErr('badname', \"hasOwnProperty is not a valid {0} name\", context);\n  }\n}\n\n/**\n * Return the value accessible from the object by path. Any undefined traversals are ignored\n * @param {Object} obj starting object\n * @param {String} path path to traverse\n * @param {boolean} [bindFnToScope=true]\n * @returns {Object} value as accessible by path\n */\n//TODO(misko): this function needs to be removed\nfunction getter(obj, path, bindFnToScope) {\n  if (!path) return obj;\n  var keys = path.split('.');\n  var key;\n  var lastInstance = obj;\n  var len = keys.length;\n\n  for (var i = 0; i < len; i++) {\n    key = keys[i];\n    if (obj) {\n      obj = (lastInstance = obj)[key];\n    }\n  }\n  if (!bindFnToScope && isFunction(obj)) {\n    return bind(lastInstance, obj);\n  }\n  return obj;\n}\n\n/**\n * Return the DOM siblings between the first and last node in the given array.\n * @param {Array} array like object\n * @returns {jqLite} jqLite collection containing the nodes\n */\nfunction getBlockNodes(nodes) {\n  // TODO(perf): just check if all items in `nodes` are siblings and if they are return the original\n  //             collection, otherwise update the original collection.\n  var node = nodes[0];\n  var endNode = nodes[nodes.length - 1];\n  var blockNodes = [node];\n\n  do {\n    node = node.nextSibling;\n    if (!node) break;\n    blockNodes.push(node);\n  } while (node !== endNode);\n\n  return jqLite(blockNodes);\n}\n\n\n/**\n * Creates a new object without a prototype. This object is useful for lookup without having to\n * guard against prototypically inherited properties via hasOwnProperty.\n *\n * Related micro-benchmarks:\n * - http://jsperf.com/object-create2\n * - http://jsperf.com/proto-map-lookup/2\n * - http://jsperf.com/for-in-vs-object-keys2\n *\n * @returns {Object}\n */\nfunction createMap() {\n  return Object.create(null);\n}\n\nvar NODE_TYPE_ELEMENT = 1;\nvar NODE_TYPE_TEXT = 3;\nvar NODE_TYPE_COMMENT = 8;\nvar NODE_TYPE_DOCUMENT = 9;\nvar NODE_TYPE_DOCUMENT_FRAGMENT = 11;\n\n/**\n * @ngdoc type\n * @name angular.Module\n * @module ng\n * @description\n *\n * Interface for configuring angular {@link angular.module modules}.\n */\n\nfunction setupModuleLoader(window) {\n\n  var $injectorMinErr = minErr('$injector');\n  var ngMinErr = minErr('ng');\n\n  function ensure(obj, name, factory) {\n    return obj[name] || (obj[name] = factory());\n  }\n\n  var angular = ensure(window, 'angular', Object);\n\n  // We need to expose `angular.$$minErr` to modules such as `ngResource` that reference it during bootstrap\n  angular.$$minErr = angular.$$minErr || minErr;\n\n  return ensure(angular, 'module', function() {\n    /** @type {Object.<string, angular.Module>} */\n    var modules = {};\n\n    /**\n     * @ngdoc function\n     * @name angular.module\n     * @module ng\n     * @description\n     *\n     * The `angular.module` is a global place for creating, registering and retrieving Angular\n     * modules.\n     * All modules (angular core or 3rd party) that should be available to an application must be\n     * registered using this mechanism.\n     *\n     * When passed two or more arguments, a new module is created.  If passed only one argument, an\n     * existing module (the name passed as the first argument to `module`) is retrieved.\n     *\n     *\n     * # Module\n     *\n     * A module is a collection of services, directives, controllers, filters, and configuration information.\n     * `angular.module` is used to configure the {@link auto.$injector $injector}.\n     *\n     * ```js\n     * // Create a new module\n     * var myModule = angular.module('myModule', []);\n     *\n     * // register a new service\n     * myModule.value('appName', 'MyCoolApp');\n     *\n     * // configure existing services inside initialization blocks.\n     * myModule.config(['$locationProvider', function($locationProvider) {\n     *   // Configure existing providers\n     *   $locationProvider.hashPrefix('!');\n     * }]);\n     * ```\n     *\n     * Then you can create an injector and load your modules like this:\n     *\n     * ```js\n     * var injector = angular.injector(['ng', 'myModule'])\n     * ```\n     *\n     * However it's more likely that you'll just use\n     * {@link ng.directive:ngApp ngApp} or\n     * {@link angular.bootstrap} to simplify this process for you.\n     *\n     * @param {!string} name The name of the module to create or retrieve.\n     * @param {!Array.<string>=} requires If specified then new module is being created. If\n     *        unspecified then the module is being retrieved for further configuration.\n     * @param {Function=} configFn Optional configuration function for the module. Same as\n     *        {@link angular.Module#config Module#config()}.\n     * @returns {module} new module with the {@link angular.Module} api.\n     */\n    return function module(name, requires, configFn) {\n      var assertNotHasOwnProperty = function(name, context) {\n        if (name === 'hasOwnProperty') {\n          throw ngMinErr('badname', 'hasOwnProperty is not a valid {0} name', context);\n        }\n      };\n\n      assertNotHasOwnProperty(name, 'module');\n      if (requires && modules.hasOwnProperty(name)) {\n        modules[name] = null;\n      }\n      return ensure(modules, name, function() {\n        if (!requires) {\n          throw $injectorMinErr('nomod', \"Module '{0}' is not available! You either misspelled \" +\n             \"the module name or forgot to load it. If registering a module ensure that you \" +\n             \"specify the dependencies as the second argument.\", name);\n        }\n\n        /** @type {!Array.<Array.<*>>} */\n        var invokeQueue = [];\n\n        /** @type {!Array.<Function>} */\n        var configBlocks = [];\n\n        /** @type {!Array.<Function>} */\n        var runBlocks = [];\n\n        var config = invokeLater('$injector', 'invoke', 'push', configBlocks);\n\n        /** @type {angular.Module} */\n        var moduleInstance = {\n          // Private state\n          _invokeQueue: invokeQueue,\n          _configBlocks: configBlocks,\n          _runBlocks: runBlocks,\n\n          /**\n           * @ngdoc property\n           * @name angular.Module#requires\n           * @module ng\n           *\n           * @description\n           * Holds the list of modules which the injector will load before the current module is\n           * loaded.\n           */\n          requires: requires,\n\n          /**\n           * @ngdoc property\n           * @name angular.Module#name\n           * @module ng\n           *\n           * @description\n           * Name of the module.\n           */\n          name: name,\n\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#provider\n           * @module ng\n           * @param {string} name service name\n           * @param {Function} providerType Construction function for creating new instance of the\n           *                                service.\n           * @description\n           * See {@link auto.$provide#provider $provide.provider()}.\n           */\n          provider: invokeLater('$provide', 'provider'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#factory\n           * @module ng\n           * @param {string} name service name\n           * @param {Function} providerFunction Function for creating new instance of the service.\n           * @description\n           * See {@link auto.$provide#factory $provide.factory()}.\n           */\n          factory: invokeLater('$provide', 'factory'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#service\n           * @module ng\n           * @param {string} name service name\n           * @param {Function} constructor A constructor function that will be instantiated.\n           * @description\n           * See {@link auto.$provide#service $provide.service()}.\n           */\n          service: invokeLater('$provide', 'service'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#value\n           * @module ng\n           * @param {string} name service name\n           * @param {*} object Service instance object.\n           * @description\n           * See {@link auto.$provide#value $provide.value()}.\n           */\n          value: invokeLater('$provide', 'value'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#constant\n           * @module ng\n           * @param {string} name constant name\n           * @param {*} object Constant value.\n           * @description\n           * Because the constant are fixed, they get applied before other provide methods.\n           * See {@link auto.$provide#constant $provide.constant()}.\n           */\n          constant: invokeLater('$provide', 'constant', 'unshift'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#animation\n           * @module ng\n           * @param {string} name animation name\n           * @param {Function} animationFactory Factory function for creating new instance of an\n           *                                    animation.\n           * @description\n           *\n           * **NOTE**: animations take effect only if the **ngAnimate** module is loaded.\n           *\n           *\n           * Defines an animation hook that can be later used with\n           * {@link ngAnimate.$animate $animate} service and directives that use this service.\n           *\n           * ```js\n           * module.animation('.animation-name', function($inject1, $inject2) {\n           *   return {\n           *     eventName : function(element, done) {\n           *       //code to run the animation\n           *       //once complete, then run done()\n           *       return function cancellationFunction(element) {\n           *         //code to cancel the animation\n           *       }\n           *     }\n           *   }\n           * })\n           * ```\n           *\n           * See {@link ng.$animateProvider#register $animateProvider.register()} and\n           * {@link ngAnimate ngAnimate module} for more information.\n           */\n          animation: invokeLater('$animateProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#filter\n           * @module ng\n           * @param {string} name Filter name.\n           * @param {Function} filterFactory Factory function for creating new instance of filter.\n           * @description\n           * See {@link ng.$filterProvider#register $filterProvider.register()}.\n           */\n          filter: invokeLater('$filterProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#controller\n           * @module ng\n           * @param {string|Object} name Controller name, or an object map of controllers where the\n           *    keys are the names and the values are the constructors.\n           * @param {Function} constructor Controller constructor function.\n           * @description\n           * See {@link ng.$controllerProvider#register $controllerProvider.register()}.\n           */\n          controller: invokeLater('$controllerProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#directive\n           * @module ng\n           * @param {string|Object} name Directive name, or an object map of directives where the\n           *    keys are the names and the values are the factories.\n           * @param {Function} directiveFactory Factory function for creating new instance of\n           * directives.\n           * @description\n           * See {@link ng.$compileProvider#directive $compileProvider.directive()}.\n           */\n          directive: invokeLater('$compileProvider', 'directive'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#config\n           * @module ng\n           * @param {Function} configFn Execute this function on module load. Useful for service\n           *    configuration.\n           * @description\n           * Use this method to register work which needs to be performed on module loading.\n           * For more about how to configure services, see\n           * {@link providers#provider-recipe Provider Recipe}.\n           */\n          config: config,\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#run\n           * @module ng\n           * @param {Function} initializationFn Execute this function after injector creation.\n           *    Useful for application initialization.\n           * @description\n           * Use this method to register work which should be performed when the injector is done\n           * loading all modules.\n           */\n          run: function(block) {\n            runBlocks.push(block);\n            return this;\n          }\n        };\n\n        if (configFn) {\n          config(configFn);\n        }\n\n        return moduleInstance;\n\n        /**\n         * @param {string} provider\n         * @param {string} method\n         * @param {String=} insertMethod\n         * @returns {angular.Module}\n         */\n        function invokeLater(provider, method, insertMethod, queue) {\n          if (!queue) queue = invokeQueue;\n          return function() {\n            queue[insertMethod || 'push']([provider, method, arguments]);\n            return moduleInstance;\n          };\n        }\n      });\n    };\n  });\n\n}\n\n/* global: toDebugString: true */\n\nfunction serializeObject(obj) {\n  var seen = [];\n\n  return JSON.stringify(obj, function(key, val) {\n    val = toJsonReplacer(key, val);\n    if (isObject(val)) {\n\n      if (seen.indexOf(val) >= 0) return '<<already seen>>';\n\n      seen.push(val);\n    }\n    return val;\n  });\n}\n\nfunction toDebugString(obj) {\n  if (typeof obj === 'function') {\n    return obj.toString().replace(/ \\{[\\s\\S]*$/, '');\n  } else if (typeof obj === 'undefined') {\n    return 'undefined';\n  } else if (typeof obj !== 'string') {\n    return serializeObject(obj);\n  }\n  return obj;\n}\n\n/* global angularModule: true,\n  version: true,\n\n  $LocaleProvider,\n  $CompileProvider,\n\n  htmlAnchorDirective,\n  inputDirective,\n  inputDirective,\n  formDirective,\n  scriptDirective,\n  selectDirective,\n  styleDirective,\n  optionDirective,\n  ngBindDirective,\n  ngBindHtmlDirective,\n  ngBindTemplateDirective,\n  ngClassDirective,\n  ngClassEvenDirective,\n  ngClassOddDirective,\n  ngCspDirective,\n  ngCloakDirective,\n  ngControllerDirective,\n  ngFormDirective,\n  ngHideDirective,\n  ngIfDirective,\n  ngIncludeDirective,\n  ngIncludeFillContentDirective,\n  ngInitDirective,\n  ngNonBindableDirective,\n  ngPluralizeDirective,\n  ngRepeatDirective,\n  ngShowDirective,\n  ngStyleDirective,\n  ngSwitchDirective,\n  ngSwitchWhenDirective,\n  ngSwitchDefaultDirective,\n  ngOptionsDirective,\n  ngTranscludeDirective,\n  ngModelDirective,\n  ngListDirective,\n  ngChangeDirective,\n  patternDirective,\n  patternDirective,\n  requiredDirective,\n  requiredDirective,\n  minlengthDirective,\n  minlengthDirective,\n  maxlengthDirective,\n  maxlengthDirective,\n  ngValueDirective,\n  ngModelOptionsDirective,\n  ngAttributeAliasDirectives,\n  ngEventDirectives,\n\n  $AnchorScrollProvider,\n  $AnimateProvider,\n  $BrowserProvider,\n  $CacheFactoryProvider,\n  $ControllerProvider,\n  $DocumentProvider,\n  $ExceptionHandlerProvider,\n  $FilterProvider,\n  $InterpolateProvider,\n  $IntervalProvider,\n  $HttpProvider,\n  $HttpBackendProvider,\n  $LocationProvider,\n  $LogProvider,\n  $ParseProvider,\n  $RootScopeProvider,\n  $QProvider,\n  $$QProvider,\n  $$SanitizeUriProvider,\n  $SceProvider,\n  $SceDelegateProvider,\n  $SnifferProvider,\n  $TemplateCacheProvider,\n  $TemplateRequestProvider,\n  $$TestabilityProvider,\n  $TimeoutProvider,\n  $$RAFProvider,\n  $$AsyncCallbackProvider,\n  $WindowProvider,\n  $$jqLiteProvider\n*/\n\n\n/**\n * @ngdoc object\n * @name angular.version\n * @module ng\n * @description\n * An object that contains information about the current AngularJS version. This object has the\n * following properties:\n *\n * - `full` – `{string}` – Full version string, such as \"0.9.18\".\n * - `major` – `{number}` – Major version number, such as \"0\".\n * - `minor` – `{number}` – Minor version number, such as \"9\".\n * - `dot` – `{number}` – Dot version number, such as \"18\".\n * - `codeName` – `{string}` – Code name of the release, such as \"jiggling-armfat\".\n */\nvar version = {\n  full: '1.3.13',    // all of these placeholder strings will be replaced by grunt's\n  major: 1,    // package task\n  minor: 3,\n  dot: 13,\n  codeName: 'meticulous-riffleshuffle'\n};\n\n\nfunction publishExternalAPI(angular) {\n  extend(angular, {\n    'bootstrap': bootstrap,\n    'copy': copy,\n    'extend': extend,\n    'equals': equals,\n    'element': jqLite,\n    'forEach': forEach,\n    'injector': createInjector,\n    'noop': noop,\n    'bind': bind,\n    'toJson': toJson,\n    'fromJson': fromJson,\n    'identity': identity,\n    'isUndefined': isUndefined,\n    'isDefined': isDefined,\n    'isString': isString,\n    'isFunction': isFunction,\n    'isObject': isObject,\n    'isNumber': isNumber,\n    'isElement': isElement,\n    'isArray': isArray,\n    'version': version,\n    'isDate': isDate,\n    'lowercase': lowercase,\n    'uppercase': uppercase,\n    'callbacks': {counter: 0},\n    'getTestability': getTestability,\n    '$$minErr': minErr,\n    '$$csp': csp,\n    'reloadWithDebugInfo': reloadWithDebugInfo\n  });\n\n  angularModule = setupModuleLoader(window);\n  try {\n    angularModule('ngLocale');\n  } catch (e) {\n    angularModule('ngLocale', []).provider('$locale', $LocaleProvider);\n  }\n\n  angularModule('ng', ['ngLocale'], ['$provide',\n    function ngModule($provide) {\n      // $$sanitizeUriProvider needs to be before $compileProvider as it is used by it.\n      $provide.provider({\n        $$sanitizeUri: $$SanitizeUriProvider\n      });\n      $provide.provider('$compile', $CompileProvider).\n        directive({\n            a: htmlAnchorDirective,\n            input: inputDirective,\n            textarea: inputDirective,\n            form: formDirective,\n            script: scriptDirective,\n            select: selectDirective,\n            style: styleDirective,\n            option: optionDirective,\n            ngBind: ngBindDirective,\n            ngBindHtml: ngBindHtmlDirective,\n            ngBindTemplate: ngBindTemplateDirective,\n            ngClass: ngClassDirective,\n            ngClassEven: ngClassEvenDirective,\n            ngClassOdd: ngClassOddDirective,\n            ngCloak: ngCloakDirective,\n            ngController: ngControllerDirective,\n            ngForm: ngFormDirective,\n            ngHide: ngHideDirective,\n            ngIf: ngIfDirective,\n            ngInclude: ngIncludeDirective,\n            ngInit: ngInitDirective,\n            ngNonBindable: ngNonBindableDirective,\n            ngPluralize: ngPluralizeDirective,\n            ngRepeat: ngRepeatDirective,\n            ngShow: ngShowDirective,\n            ngStyle: ngStyleDirective,\n            ngSwitch: ngSwitchDirective,\n            ngSwitchWhen: ngSwitchWhenDirective,\n            ngSwitchDefault: ngSwitchDefaultDirective,\n            ngOptions: ngOptionsDirective,\n            ngTransclude: ngTranscludeDirective,\n            ngModel: ngModelDirective,\n            ngList: ngListDirective,\n            ngChange: ngChangeDirective,\n            pattern: patternDirective,\n            ngPattern: patternDirective,\n            required: requiredDirective,\n            ngRequired: requiredDirective,\n            minlength: minlengthDirective,\n            ngMinlength: minlengthDirective,\n            maxlength: maxlengthDirective,\n            ngMaxlength: maxlengthDirective,\n            ngValue: ngValueDirective,\n            ngModelOptions: ngModelOptionsDirective\n        }).\n        directive({\n          ngInclude: ngIncludeFillContentDirective\n        }).\n        directive(ngAttributeAliasDirectives).\n        directive(ngEventDirectives);\n      $provide.provider({\n        $anchorScroll: $AnchorScrollProvider,\n        $animate: $AnimateProvider,\n        $browser: $BrowserProvider,\n        $cacheFactory: $CacheFactoryProvider,\n        $controller: $ControllerProvider,\n        $document: $DocumentProvider,\n        $exceptionHandler: $ExceptionHandlerProvider,\n        $filter: $FilterProvider,\n        $interpolate: $InterpolateProvider,\n        $interval: $IntervalProvider,\n        $http: $HttpProvider,\n        $httpBackend: $HttpBackendProvider,\n        $location: $LocationProvider,\n        $log: $LogProvider,\n        $parse: $ParseProvider,\n        $rootScope: $RootScopeProvider,\n        $q: $QProvider,\n        $$q: $$QProvider,\n        $sce: $SceProvider,\n        $sceDelegate: $SceDelegateProvider,\n        $sniffer: $SnifferProvider,\n        $templateCache: $TemplateCacheProvider,\n        $templateRequest: $TemplateRequestProvider,\n        $$testability: $$TestabilityProvider,\n        $timeout: $TimeoutProvider,\n        $window: $WindowProvider,\n        $$rAF: $$RAFProvider,\n        $$asyncCallback: $$AsyncCallbackProvider,\n        $$jqLite: $$jqLiteProvider\n      });\n    }\n  ]);\n}\n\n/* global JQLitePrototype: true,\n  addEventListenerFn: true,\n  removeEventListenerFn: true,\n  BOOLEAN_ATTR: true,\n  ALIASED_ATTR: true,\n*/\n\n//////////////////////////////////\n//JQLite\n//////////////////////////////////\n\n/**\n * @ngdoc function\n * @name angular.element\n * @module ng\n * @kind function\n *\n * @description\n * Wraps a raw DOM element or HTML string as a [jQuery](http://jquery.com) element.\n *\n * If jQuery is available, `angular.element` is an alias for the\n * [jQuery](http://api.jquery.com/jQuery/) function. If jQuery is not available, `angular.element`\n * delegates to Angular's built-in subset of jQuery, called \"jQuery lite\" or \"jqLite.\"\n *\n * <div class=\"alert alert-success\">jqLite is a tiny, API-compatible subset of jQuery that allows\n * Angular to manipulate the DOM in a cross-browser compatible way. **jqLite** implements only the most\n * commonly needed functionality with the goal of having a very small footprint.</div>\n *\n * To use jQuery, simply load it before `DOMContentLoaded` event fired.\n *\n * <div class=\"alert\">**Note:** all element references in Angular are always wrapped with jQuery or\n * jqLite; they are never raw DOM references.</div>\n *\n * ## Angular's jqLite\n * jqLite provides only the following jQuery methods:\n *\n * - [`addClass()`](http://api.jquery.com/addClass/)\n * - [`after()`](http://api.jquery.com/after/)\n * - [`append()`](http://api.jquery.com/append/)\n * - [`attr()`](http://api.jquery.com/attr/) - Does not support functions as parameters\n * - [`bind()`](http://api.jquery.com/bind/) - Does not support namespaces, selectors or eventData\n * - [`children()`](http://api.jquery.com/children/) - Does not support selectors\n * - [`clone()`](http://api.jquery.com/clone/)\n * - [`contents()`](http://api.jquery.com/contents/)\n * - [`css()`](http://api.jquery.com/css/) - Only retrieves inline-styles, does not call `getComputedStyle()`\n * - [`data()`](http://api.jquery.com/data/)\n * - [`detach()`](http://api.jquery.com/detach/)\n * - [`empty()`](http://api.jquery.com/empty/)\n * - [`eq()`](http://api.jquery.com/eq/)\n * - [`find()`](http://api.jquery.com/find/) - Limited to lookups by tag name\n * - [`hasClass()`](http://api.jquery.com/hasClass/)\n * - [`html()`](http://api.jquery.com/html/)\n * - [`next()`](http://api.jquery.com/next/) - Does not support selectors\n * - [`on()`](http://api.jquery.com/on/) - Does not support namespaces, selectors or eventData\n * - [`off()`](http://api.jquery.com/off/) - Does not support namespaces or selectors\n * - [`one()`](http://api.jquery.com/one/) - Does not support namespaces or selectors\n * - [`parent()`](http://api.jquery.com/parent/) - Does not support selectors\n * - [`prepend()`](http://api.jquery.com/prepend/)\n * - [`prop()`](http://api.jquery.com/prop/)\n * - [`ready()`](http://api.jquery.com/ready/)\n * - [`remove()`](http://api.jquery.com/remove/)\n * - [`removeAttr()`](http://api.jquery.com/removeAttr/)\n * - [`removeClass()`](http://api.jquery.com/removeClass/)\n * - [`removeData()`](http://api.jquery.com/removeData/)\n * - [`replaceWith()`](http://api.jquery.com/replaceWith/)\n * - [`text()`](http://api.jquery.com/text/)\n * - [`toggleClass()`](http://api.jquery.com/toggleClass/)\n * - [`triggerHandler()`](http://api.jquery.com/triggerHandler/) - Passes a dummy event object to handlers.\n * - [`unbind()`](http://api.jquery.com/unbind/) - Does not support namespaces\n * - [`val()`](http://api.jquery.com/val/)\n * - [`wrap()`](http://api.jquery.com/wrap/)\n *\n * ## jQuery/jqLite Extras\n * Angular also provides the following additional methods and events to both jQuery and jqLite:\n *\n * ### Events\n * - `$destroy` - AngularJS intercepts all jqLite/jQuery's DOM destruction apis and fires this event\n *    on all DOM nodes being removed.  This can be used to clean up any 3rd party bindings to the DOM\n *    element before it is removed.\n *\n * ### Methods\n * - `controller(name)` - retrieves the controller of the current element or its parent. By default\n *   retrieves controller associated with the `ngController` directive. If `name` is provided as\n *   camelCase directive name, then the controller for this directive will be retrieved (e.g.\n *   `'ngModel'`).\n * - `injector()` - retrieves the injector of the current element or its parent.\n * - `scope()` - retrieves the {@link ng.$rootScope.Scope scope} of the current\n *   element or its parent. Requires {@link guide/production#disabling-debug-data Debug Data} to\n *   be enabled.\n * - `isolateScope()` - retrieves an isolate {@link ng.$rootScope.Scope scope} if one is attached directly to the\n *   current element. This getter should be used only on elements that contain a directive which starts a new isolate\n *   scope. Calling `scope()` on this element always returns the original non-isolate scope.\n *   Requires {@link guide/production#disabling-debug-data Debug Data} to be enabled.\n * - `inheritedData()` - same as `data()`, but walks up the DOM until a value is found or the top\n *   parent element is reached.\n *\n * @param {string|DOMElement} element HTML string or DOMElement to be wrapped into jQuery.\n * @returns {Object} jQuery object.\n */\n\nJQLite.expando = 'ng339';\n\nvar jqCache = JQLite.cache = {},\n    jqId = 1,\n    addEventListenerFn = function(element, type, fn) {\n      element.addEventListener(type, fn, false);\n    },\n    removeEventListenerFn = function(element, type, fn) {\n      element.removeEventListener(type, fn, false);\n    };\n\n/*\n * !!! This is an undocumented \"private\" function !!!\n */\nJQLite._data = function(node) {\n  //jQuery always returns an object on cache miss\n  return this.cache[node[this.expando]] || {};\n};\n\nfunction jqNextId() { return ++jqId; }\n\n\nvar SPECIAL_CHARS_REGEXP = /([\\:\\-\\_]+(.))/g;\nvar MOZ_HACK_REGEXP = /^moz([A-Z])/;\nvar MOUSE_EVENT_MAP= { mouseleave: \"mouseout\", mouseenter: \"mouseover\"};\nvar jqLiteMinErr = minErr('jqLite');\n\n/**\n * Converts snake_case to camelCase.\n * Also there is special case for Moz prefix starting with upper case letter.\n * @param name Name to normalize\n */\nfunction camelCase(name) {\n  return name.\n    replace(SPECIAL_CHARS_REGEXP, function(_, separator, letter, offset) {\n      return offset ? letter.toUpperCase() : letter;\n    }).\n    replace(MOZ_HACK_REGEXP, 'Moz$1');\n}\n\nvar SINGLE_TAG_REGEXP = /^<(\\w+)\\s*\\/?>(?:<\\/\\1>|)$/;\nvar HTML_REGEXP = /<|&#?\\w+;/;\nvar TAG_NAME_REGEXP = /<([\\w:]+)/;\nvar XHTML_TAG_REGEXP = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\\w:]+)[^>]*)\\/>/gi;\n\nvar wrapMap = {\n  'option': [1, '<select multiple=\"multiple\">', '</select>'],\n\n  'thead': [1, '<table>', '</table>'],\n  'col': [2, '<table><colgroup>', '</colgroup></table>'],\n  'tr': [2, '<table><tbody>', '</tbody></table>'],\n  'td': [3, '<table><tbody><tr>', '</tr></tbody></table>'],\n  '_default': [0, \"\", \"\"]\n};\n\nwrapMap.optgroup = wrapMap.option;\nwrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;\nwrapMap.th = wrapMap.td;\n\n\nfunction jqLiteIsTextNode(html) {\n  return !HTML_REGEXP.test(html);\n}\n\nfunction jqLiteAcceptsData(node) {\n  // The window object can accept data but has no nodeType\n  // Otherwise we are only interested in elements (1) and documents (9)\n  var nodeType = node.nodeType;\n  return nodeType === NODE_TYPE_ELEMENT || !nodeType || nodeType === NODE_TYPE_DOCUMENT;\n}\n\nfunction jqLiteBuildFragment(html, context) {\n  var tmp, tag, wrap,\n      fragment = context.createDocumentFragment(),\n      nodes = [], i;\n\n  if (jqLiteIsTextNode(html)) {\n    // Convert non-html into a text node\n    nodes.push(context.createTextNode(html));\n  } else {\n    // Convert html into DOM nodes\n    tmp = tmp || fragment.appendChild(context.createElement(\"div\"));\n    tag = (TAG_NAME_REGEXP.exec(html) || [\"\", \"\"])[1].toLowerCase();\n    wrap = wrapMap[tag] || wrapMap._default;\n    tmp.innerHTML = wrap[1] + html.replace(XHTML_TAG_REGEXP, \"<$1></$2>\") + wrap[2];\n\n    // Descend through wrappers to the right content\n    i = wrap[0];\n    while (i--) {\n      tmp = tmp.lastChild;\n    }\n\n    nodes = concat(nodes, tmp.childNodes);\n\n    tmp = fragment.firstChild;\n    tmp.textContent = \"\";\n  }\n\n  // Remove wrapper from fragment\n  fragment.textContent = \"\";\n  fragment.innerHTML = \"\"; // Clear inner HTML\n  forEach(nodes, function(node) {\n    fragment.appendChild(node);\n  });\n\n  return fragment;\n}\n\nfunction jqLiteParseHTML(html, context) {\n  context = context || document;\n  var parsed;\n\n  if ((parsed = SINGLE_TAG_REGEXP.exec(html))) {\n    return [context.createElement(parsed[1])];\n  }\n\n  if ((parsed = jqLiteBuildFragment(html, context))) {\n    return parsed.childNodes;\n  }\n\n  return [];\n}\n\n/////////////////////////////////////////////\nfunction JQLite(element) {\n  if (element instanceof JQLite) {\n    return element;\n  }\n\n  var argIsString;\n\n  if (isString(element)) {\n    element = trim(element);\n    argIsString = true;\n  }\n  if (!(this instanceof JQLite)) {\n    if (argIsString && element.charAt(0) != '<') {\n      throw jqLiteMinErr('nosel', 'Looking up elements via selectors is not supported by jqLite! See: http://docs.angularjs.org/api/angular.element');\n    }\n    return new JQLite(element);\n  }\n\n  if (argIsString) {\n    jqLiteAddNodes(this, jqLiteParseHTML(element));\n  } else {\n    jqLiteAddNodes(this, element);\n  }\n}\n\nfunction jqLiteClone(element) {\n  return element.cloneNode(true);\n}\n\nfunction jqLiteDealoc(element, onlyDescendants) {\n  if (!onlyDescendants) jqLiteRemoveData(element);\n\n  if (element.querySelectorAll) {\n    var descendants = element.querySelectorAll('*');\n    for (var i = 0, l = descendants.length; i < l; i++) {\n      jqLiteRemoveData(descendants[i]);\n    }\n  }\n}\n\nfunction jqLiteOff(element, type, fn, unsupported) {\n  if (isDefined(unsupported)) throw jqLiteMinErr('offargs', 'jqLite#off() does not support the `selector` argument');\n\n  var expandoStore = jqLiteExpandoStore(element);\n  var events = expandoStore && expandoStore.events;\n  var handle = expandoStore && expandoStore.handle;\n\n  if (!handle) return; //no listeners registered\n\n  if (!type) {\n    for (type in events) {\n      if (type !== '$destroy') {\n        removeEventListenerFn(element, type, handle);\n      }\n      delete events[type];\n    }\n  } else {\n    forEach(type.split(' '), function(type) {\n      if (isDefined(fn)) {\n        var listenerFns = events[type];\n        arrayRemove(listenerFns || [], fn);\n        if (listenerFns && listenerFns.length > 0) {\n          return;\n        }\n      }\n\n      removeEventListenerFn(element, type, handle);\n      delete events[type];\n    });\n  }\n}\n\nfunction jqLiteRemoveData(element, name) {\n  var expandoId = element.ng339;\n  var expandoStore = expandoId && jqCache[expandoId];\n\n  if (expandoStore) {\n    if (name) {\n      delete expandoStore.data[name];\n      return;\n    }\n\n    if (expandoStore.handle) {\n      if (expandoStore.events.$destroy) {\n        expandoStore.handle({}, '$destroy');\n      }\n      jqLiteOff(element);\n    }\n    delete jqCache[expandoId];\n    element.ng339 = undefined; // don't delete DOM expandos. IE and Chrome don't like it\n  }\n}\n\n\nfunction jqLiteExpandoStore(element, createIfNecessary) {\n  var expandoId = element.ng339,\n      expandoStore = expandoId && jqCache[expandoId];\n\n  if (createIfNecessary && !expandoStore) {\n    element.ng339 = expandoId = jqNextId();\n    expandoStore = jqCache[expandoId] = {events: {}, data: {}, handle: undefined};\n  }\n\n  return expandoStore;\n}\n\n\nfunction jqLiteData(element, key, value) {\n  if (jqLiteAcceptsData(element)) {\n\n    var isSimpleSetter = isDefined(value);\n    var isSimpleGetter = !isSimpleSetter && key && !isObject(key);\n    var massGetter = !key;\n    var expandoStore = jqLiteExpandoStore(element, !isSimpleGetter);\n    var data = expandoStore && expandoStore.data;\n\n    if (isSimpleSetter) { // data('key', value)\n      data[key] = value;\n    } else {\n      if (massGetter) {  // data()\n        return data;\n      } else {\n        if (isSimpleGetter) { // data('key')\n          // don't force creation of expandoStore if it doesn't exist yet\n          return data && data[key];\n        } else { // mass-setter: data({key1: val1, key2: val2})\n          extend(data, key);\n        }\n      }\n    }\n  }\n}\n\nfunction jqLiteHasClass(element, selector) {\n  if (!element.getAttribute) return false;\n  return ((\" \" + (element.getAttribute('class') || '') + \" \").replace(/[\\n\\t]/g, \" \").\n      indexOf(\" \" + selector + \" \") > -1);\n}\n\nfunction jqLiteRemoveClass(element, cssClasses) {\n  if (cssClasses && element.setAttribute) {\n    forEach(cssClasses.split(' '), function(cssClass) {\n      element.setAttribute('class', trim(\n          (\" \" + (element.getAttribute('class') || '') + \" \")\n          .replace(/[\\n\\t]/g, \" \")\n          .replace(\" \" + trim(cssClass) + \" \", \" \"))\n      );\n    });\n  }\n}\n\nfunction jqLiteAddClass(element, cssClasses) {\n  if (cssClasses && element.setAttribute) {\n    var existingClasses = (' ' + (element.getAttribute('class') || '') + ' ')\n                            .replace(/[\\n\\t]/g, \" \");\n\n    forEach(cssClasses.split(' '), function(cssClass) {\n      cssClass = trim(cssClass);\n      if (existingClasses.indexOf(' ' + cssClass + ' ') === -1) {\n        existingClasses += cssClass + ' ';\n      }\n    });\n\n    element.setAttribute('class', trim(existingClasses));\n  }\n}\n\n\nfunction jqLiteAddNodes(root, elements) {\n  // THIS CODE IS VERY HOT. Don't make changes without benchmarking.\n\n  if (elements) {\n\n    // if a Node (the most common case)\n    if (elements.nodeType) {\n      root[root.length++] = elements;\n    } else {\n      var length = elements.length;\n\n      // if an Array or NodeList and not a Window\n      if (typeof length === 'number' && elements.window !== elements) {\n        if (length) {\n          for (var i = 0; i < length; i++) {\n            root[root.length++] = elements[i];\n          }\n        }\n      } else {\n        root[root.length++] = elements;\n      }\n    }\n  }\n}\n\n\nfunction jqLiteController(element, name) {\n  return jqLiteInheritedData(element, '$' + (name || 'ngController') + 'Controller');\n}\n\nfunction jqLiteInheritedData(element, name, value) {\n  // if element is the document object work with the html element instead\n  // this makes $(document).scope() possible\n  if (element.nodeType == NODE_TYPE_DOCUMENT) {\n    element = element.documentElement;\n  }\n  var names = isArray(name) ? name : [name];\n\n  while (element) {\n    for (var i = 0, ii = names.length; i < ii; i++) {\n      if ((value = jqLite.data(element, names[i])) !== undefined) return value;\n    }\n\n    // If dealing with a document fragment node with a host element, and no parent, use the host\n    // element as the parent. This enables directives within a Shadow DOM or polyfilled Shadow DOM\n    // to lookup parent controllers.\n    element = element.parentNode || (element.nodeType === NODE_TYPE_DOCUMENT_FRAGMENT && element.host);\n  }\n}\n\nfunction jqLiteEmpty(element) {\n  jqLiteDealoc(element, true);\n  while (element.firstChild) {\n    element.removeChild(element.firstChild);\n  }\n}\n\nfunction jqLiteRemove(element, keepData) {\n  if (!keepData) jqLiteDealoc(element);\n  var parent = element.parentNode;\n  if (parent) parent.removeChild(element);\n}\n\n\nfunction jqLiteDocumentLoaded(action, win) {\n  win = win || window;\n  if (win.document.readyState === 'complete') {\n    // Force the action to be run async for consistent behaviour\n    // from the action's point of view\n    // i.e. it will definitely not be in a $apply\n    win.setTimeout(action);\n  } else {\n    // No need to unbind this handler as load is only ever called once\n    jqLite(win).on('load', action);\n  }\n}\n\n//////////////////////////////////////////\n// Functions which are declared directly.\n//////////////////////////////////////////\nvar JQLitePrototype = JQLite.prototype = {\n  ready: function(fn) {\n    var fired = false;\n\n    function trigger() {\n      if (fired) return;\n      fired = true;\n      fn();\n    }\n\n    // check if document is already loaded\n    if (document.readyState === 'complete') {\n      setTimeout(trigger);\n    } else {\n      this.on('DOMContentLoaded', trigger); // works for modern browsers and IE9\n      // we can not use jqLite since we are not done loading and jQuery could be loaded later.\n      // jshint -W064\n      JQLite(window).on('load', trigger); // fallback to window.onload for others\n      // jshint +W064\n    }\n  },\n  toString: function() {\n    var value = [];\n    forEach(this, function(e) { value.push('' + e);});\n    return '[' + value.join(', ') + ']';\n  },\n\n  eq: function(index) {\n      return (index >= 0) ? jqLite(this[index]) : jqLite(this[this.length + index]);\n  },\n\n  length: 0,\n  push: push,\n  sort: [].sort,\n  splice: [].splice\n};\n\n//////////////////////////////////////////\n// Functions iterating getter/setters.\n// these functions return self on setter and\n// value on get.\n//////////////////////////////////////////\nvar BOOLEAN_ATTR = {};\nforEach('multiple,selected,checked,disabled,readOnly,required,open'.split(','), function(value) {\n  BOOLEAN_ATTR[lowercase(value)] = value;\n});\nvar BOOLEAN_ELEMENTS = {};\nforEach('input,select,option,textarea,button,form,details'.split(','), function(value) {\n  BOOLEAN_ELEMENTS[value] = true;\n});\nvar ALIASED_ATTR = {\n  'ngMinlength': 'minlength',\n  'ngMaxlength': 'maxlength',\n  'ngMin': 'min',\n  'ngMax': 'max',\n  'ngPattern': 'pattern'\n};\n\nfunction getBooleanAttrName(element, name) {\n  // check dom last since we will most likely fail on name\n  var booleanAttr = BOOLEAN_ATTR[name.toLowerCase()];\n\n  // booleanAttr is here twice to minimize DOM access\n  return booleanAttr && BOOLEAN_ELEMENTS[nodeName_(element)] && booleanAttr;\n}\n\nfunction getAliasedAttrName(element, name) {\n  var nodeName = element.nodeName;\n  return (nodeName === 'INPUT' || nodeName === 'TEXTAREA') && ALIASED_ATTR[name];\n}\n\nforEach({\n  data: jqLiteData,\n  removeData: jqLiteRemoveData\n}, function(fn, name) {\n  JQLite[name] = fn;\n});\n\nforEach({\n  data: jqLiteData,\n  inheritedData: jqLiteInheritedData,\n\n  scope: function(element) {\n    // Can't use jqLiteData here directly so we stay compatible with jQuery!\n    return jqLite.data(element, '$scope') || jqLiteInheritedData(element.parentNode || element, ['$isolateScope', '$scope']);\n  },\n\n  isolateScope: function(element) {\n    // Can't use jqLiteData here directly so we stay compatible with jQuery!\n    return jqLite.data(element, '$isolateScope') || jqLite.data(element, '$isolateScopeNoTemplate');\n  },\n\n  controller: jqLiteController,\n\n  injector: function(element) {\n    return jqLiteInheritedData(element, '$injector');\n  },\n\n  removeAttr: function(element, name) {\n    element.removeAttribute(name);\n  },\n\n  hasClass: jqLiteHasClass,\n\n  css: function(element, name, value) {\n    name = camelCase(name);\n\n    if (isDefined(value)) {\n      element.style[name] = value;\n    } else {\n      return element.style[name];\n    }\n  },\n\n  attr: function(element, name, value) {\n    var lowercasedName = lowercase(name);\n    if (BOOLEAN_ATTR[lowercasedName]) {\n      if (isDefined(value)) {\n        if (!!value) {\n          element[name] = true;\n          element.setAttribute(name, lowercasedName);\n        } else {\n          element[name] = false;\n          element.removeAttribute(lowercasedName);\n        }\n      } else {\n        return (element[name] ||\n                 (element.attributes.getNamedItem(name) || noop).specified)\n               ? lowercasedName\n               : undefined;\n      }\n    } else if (isDefined(value)) {\n      element.setAttribute(name, value);\n    } else if (element.getAttribute) {\n      // the extra argument \"2\" is to get the right thing for a.href in IE, see jQuery code\n      // some elements (e.g. Document) don't have get attribute, so return undefined\n      var ret = element.getAttribute(name, 2);\n      // normalize non-existing attributes to undefined (as jQuery)\n      return ret === null ? undefined : ret;\n    }\n  },\n\n  prop: function(element, name, value) {\n    if (isDefined(value)) {\n      element[name] = value;\n    } else {\n      return element[name];\n    }\n  },\n\n  text: (function() {\n    getText.$dv = '';\n    return getText;\n\n    function getText(element, value) {\n      if (isUndefined(value)) {\n        var nodeType = element.nodeType;\n        return (nodeType === NODE_TYPE_ELEMENT || nodeType === NODE_TYPE_TEXT) ? element.textContent : '';\n      }\n      element.textContent = value;\n    }\n  })(),\n\n  val: function(element, value) {\n    if (isUndefined(value)) {\n      if (element.multiple && nodeName_(element) === 'select') {\n        var result = [];\n        forEach(element.options, function(option) {\n          if (option.selected) {\n            result.push(option.value || option.text);\n          }\n        });\n        return result.length === 0 ? null : result;\n      }\n      return element.value;\n    }\n    element.value = value;\n  },\n\n  html: function(element, value) {\n    if (isUndefined(value)) {\n      return element.innerHTML;\n    }\n    jqLiteDealoc(element, true);\n    element.innerHTML = value;\n  },\n\n  empty: jqLiteEmpty\n}, function(fn, name) {\n  /**\n   * Properties: writes return selection, reads return first value\n   */\n  JQLite.prototype[name] = function(arg1, arg2) {\n    var i, key;\n    var nodeCount = this.length;\n\n    // jqLiteHasClass has only two arguments, but is a getter-only fn, so we need to special-case it\n    // in a way that survives minification.\n    // jqLiteEmpty takes no arguments but is a setter.\n    if (fn !== jqLiteEmpty &&\n        (((fn.length == 2 && (fn !== jqLiteHasClass && fn !== jqLiteController)) ? arg1 : arg2) === undefined)) {\n      if (isObject(arg1)) {\n\n        // we are a write, but the object properties are the key/values\n        for (i = 0; i < nodeCount; i++) {\n          if (fn === jqLiteData) {\n            // data() takes the whole object in jQuery\n            fn(this[i], arg1);\n          } else {\n            for (key in arg1) {\n              fn(this[i], key, arg1[key]);\n            }\n          }\n        }\n        // return self for chaining\n        return this;\n      } else {\n        // we are a read, so read the first child.\n        // TODO: do we still need this?\n        var value = fn.$dv;\n        // Only if we have $dv do we iterate over all, otherwise it is just the first element.\n        var jj = (value === undefined) ? Math.min(nodeCount, 1) : nodeCount;\n        for (var j = 0; j < jj; j++) {\n          var nodeValue = fn(this[j], arg1, arg2);\n          value = value ? value + nodeValue : nodeValue;\n        }\n        return value;\n      }\n    } else {\n      // we are a write, so apply to all children\n      for (i = 0; i < nodeCount; i++) {\n        fn(this[i], arg1, arg2);\n      }\n      // return self for chaining\n      return this;\n    }\n  };\n});\n\nfunction createEventHandler(element, events) {\n  var eventHandler = function(event, type) {\n    // jQuery specific api\n    event.isDefaultPrevented = function() {\n      return event.defaultPrevented;\n    };\n\n    var eventFns = events[type || event.type];\n    var eventFnsLength = eventFns ? eventFns.length : 0;\n\n    if (!eventFnsLength) return;\n\n    if (isUndefined(event.immediatePropagationStopped)) {\n      var originalStopImmediatePropagation = event.stopImmediatePropagation;\n      event.stopImmediatePropagation = function() {\n        event.immediatePropagationStopped = true;\n\n        if (event.stopPropagation) {\n          event.stopPropagation();\n        }\n\n        if (originalStopImmediatePropagation) {\n          originalStopImmediatePropagation.call(event);\n        }\n      };\n    }\n\n    event.isImmediatePropagationStopped = function() {\n      return event.immediatePropagationStopped === true;\n    };\n\n    // Copy event handlers in case event handlers array is modified during execution.\n    if ((eventFnsLength > 1)) {\n      eventFns = shallowCopy(eventFns);\n    }\n\n    for (var i = 0; i < eventFnsLength; i++) {\n      if (!event.isImmediatePropagationStopped()) {\n        eventFns[i].call(element, event);\n      }\n    }\n  };\n\n  // TODO: this is a hack for angularMocks/clearDataCache that makes it possible to deregister all\n  //       events on `element`\n  eventHandler.elem = element;\n  return eventHandler;\n}\n\n//////////////////////////////////////////\n// Functions iterating traversal.\n// These functions chain results into a single\n// selector.\n//////////////////////////////////////////\nforEach({\n  removeData: jqLiteRemoveData,\n\n  on: function jqLiteOn(element, type, fn, unsupported) {\n    if (isDefined(unsupported)) throw jqLiteMinErr('onargs', 'jqLite#on() does not support the `selector` or `eventData` parameters');\n\n    // Do not add event handlers to non-elements because they will not be cleaned up.\n    if (!jqLiteAcceptsData(element)) {\n      return;\n    }\n\n    var expandoStore = jqLiteExpandoStore(element, true);\n    var events = expandoStore.events;\n    var handle = expandoStore.handle;\n\n    if (!handle) {\n      handle = expandoStore.handle = createEventHandler(element, events);\n    }\n\n    // http://jsperf.com/string-indexof-vs-split\n    var types = type.indexOf(' ') >= 0 ? type.split(' ') : [type];\n    var i = types.length;\n\n    while (i--) {\n      type = types[i];\n      var eventFns = events[type];\n\n      if (!eventFns) {\n        events[type] = [];\n\n        if (type === 'mouseenter' || type === 'mouseleave') {\n          // Refer to jQuery's implementation of mouseenter & mouseleave\n          // Read about mouseenter and mouseleave:\n          // http://www.quirksmode.org/js/events_mouse.html#link8\n\n          jqLiteOn(element, MOUSE_EVENT_MAP[type], function(event) {\n            var target = this, related = event.relatedTarget;\n            // For mousenter/leave call the handler if related is outside the target.\n            // NB: No relatedTarget if the mouse left/entered the browser window\n            if (!related || (related !== target && !target.contains(related))) {\n              handle(event, type);\n            }\n          });\n\n        } else {\n          if (type !== '$destroy') {\n            addEventListenerFn(element, type, handle);\n          }\n        }\n        eventFns = events[type];\n      }\n      eventFns.push(fn);\n    }\n  },\n\n  off: jqLiteOff,\n\n  one: function(element, type, fn) {\n    element = jqLite(element);\n\n    //add the listener twice so that when it is called\n    //you can remove the original function and still be\n    //able to call element.off(ev, fn) normally\n    element.on(type, function onFn() {\n      element.off(type, fn);\n      element.off(type, onFn);\n    });\n    element.on(type, fn);\n  },\n\n  replaceWith: function(element, replaceNode) {\n    var index, parent = element.parentNode;\n    jqLiteDealoc(element);\n    forEach(new JQLite(replaceNode), function(node) {\n      if (index) {\n        parent.insertBefore(node, index.nextSibling);\n      } else {\n        parent.replaceChild(node, element);\n      }\n      index = node;\n    });\n  },\n\n  children: function(element) {\n    var children = [];\n    forEach(element.childNodes, function(element) {\n      if (element.nodeType === NODE_TYPE_ELEMENT)\n        children.push(element);\n    });\n    return children;\n  },\n\n  contents: function(element) {\n    return element.contentDocument || element.childNodes || [];\n  },\n\n  append: function(element, node) {\n    var nodeType = element.nodeType;\n    if (nodeType !== NODE_TYPE_ELEMENT && nodeType !== NODE_TYPE_DOCUMENT_FRAGMENT) return;\n\n    node = new JQLite(node);\n\n    for (var i = 0, ii = node.length; i < ii; i++) {\n      var child = node[i];\n      element.appendChild(child);\n    }\n  },\n\n  prepend: function(element, node) {\n    if (element.nodeType === NODE_TYPE_ELEMENT) {\n      var index = element.firstChild;\n      forEach(new JQLite(node), function(child) {\n        element.insertBefore(child, index);\n      });\n    }\n  },\n\n  wrap: function(element, wrapNode) {\n    wrapNode = jqLite(wrapNode).eq(0).clone()[0];\n    var parent = element.parentNode;\n    if (parent) {\n      parent.replaceChild(wrapNode, element);\n    }\n    wrapNode.appendChild(element);\n  },\n\n  remove: jqLiteRemove,\n\n  detach: function(element) {\n    jqLiteRemove(element, true);\n  },\n\n  after: function(element, newElement) {\n    var index = element, parent = element.parentNode;\n    newElement = new JQLite(newElement);\n\n    for (var i = 0, ii = newElement.length; i < ii; i++) {\n      var node = newElement[i];\n      parent.insertBefore(node, index.nextSibling);\n      index = node;\n    }\n  },\n\n  addClass: jqLiteAddClass,\n  removeClass: jqLiteRemoveClass,\n\n  toggleClass: function(element, selector, condition) {\n    if (selector) {\n      forEach(selector.split(' '), function(className) {\n        var classCondition = condition;\n        if (isUndefined(classCondition)) {\n          classCondition = !jqLiteHasClass(element, className);\n        }\n        (classCondition ? jqLiteAddClass : jqLiteRemoveClass)(element, className);\n      });\n    }\n  },\n\n  parent: function(element) {\n    var parent = element.parentNode;\n    return parent && parent.nodeType !== NODE_TYPE_DOCUMENT_FRAGMENT ? parent : null;\n  },\n\n  next: function(element) {\n    return element.nextElementSibling;\n  },\n\n  find: function(element, selector) {\n    if (element.getElementsByTagName) {\n      return element.getElementsByTagName(selector);\n    } else {\n      return [];\n    }\n  },\n\n  clone: jqLiteClone,\n\n  triggerHandler: function(element, event, extraParameters) {\n\n    var dummyEvent, eventFnsCopy, handlerArgs;\n    var eventName = event.type || event;\n    var expandoStore = jqLiteExpandoStore(element);\n    var events = expandoStore && expandoStore.events;\n    var eventFns = events && events[eventName];\n\n    if (eventFns) {\n      // Create a dummy event to pass to the handlers\n      dummyEvent = {\n        preventDefault: function() { this.defaultPrevented = true; },\n        isDefaultPrevented: function() { return this.defaultPrevented === true; },\n        stopImmediatePropagation: function() { this.immediatePropagationStopped = true; },\n        isImmediatePropagationStopped: function() { return this.immediatePropagationStopped === true; },\n        stopPropagation: noop,\n        type: eventName,\n        target: element\n      };\n\n      // If a custom event was provided then extend our dummy event with it\n      if (event.type) {\n        dummyEvent = extend(dummyEvent, event);\n      }\n\n      // Copy event handlers in case event handlers array is modified during execution.\n      eventFnsCopy = shallowCopy(eventFns);\n      handlerArgs = extraParameters ? [dummyEvent].concat(extraParameters) : [dummyEvent];\n\n      forEach(eventFnsCopy, function(fn) {\n        if (!dummyEvent.isImmediatePropagationStopped()) {\n          fn.apply(element, handlerArgs);\n        }\n      });\n    }\n  }\n}, function(fn, name) {\n  /**\n   * chaining functions\n   */\n  JQLite.prototype[name] = function(arg1, arg2, arg3) {\n    var value;\n\n    for (var i = 0, ii = this.length; i < ii; i++) {\n      if (isUndefined(value)) {\n        value = fn(this[i], arg1, arg2, arg3);\n        if (isDefined(value)) {\n          // any function which returns a value needs to be wrapped\n          value = jqLite(value);\n        }\n      } else {\n        jqLiteAddNodes(value, fn(this[i], arg1, arg2, arg3));\n      }\n    }\n    return isDefined(value) ? value : this;\n  };\n\n  // bind legacy bind/unbind to on/off\n  JQLite.prototype.bind = JQLite.prototype.on;\n  JQLite.prototype.unbind = JQLite.prototype.off;\n});\n\n\n// Provider for private $$jqLite service\nfunction $$jqLiteProvider() {\n  this.$get = function $$jqLite() {\n    return extend(JQLite, {\n      hasClass: function(node, classes) {\n        if (node.attr) node = node[0];\n        return jqLiteHasClass(node, classes);\n      },\n      addClass: function(node, classes) {\n        if (node.attr) node = node[0];\n        return jqLiteAddClass(node, classes);\n      },\n      removeClass: function(node, classes) {\n        if (node.attr) node = node[0];\n        return jqLiteRemoveClass(node, classes);\n      }\n    });\n  };\n}\n\n/**\n * Computes a hash of an 'obj'.\n * Hash of a:\n *  string is string\n *  number is number as string\n *  object is either result of calling $$hashKey function on the object or uniquely generated id,\n *         that is also assigned to the $$hashKey property of the object.\n *\n * @param obj\n * @returns {string} hash string such that the same input will have the same hash string.\n *         The resulting string key is in 'type:hashKey' format.\n */\nfunction hashKey(obj, nextUidFn) {\n  var key = obj && obj.$$hashKey;\n\n  if (key) {\n    if (typeof key === 'function') {\n      key = obj.$$hashKey();\n    }\n    return key;\n  }\n\n  var objType = typeof obj;\n  if (objType == 'function' || (objType == 'object' && obj !== null)) {\n    key = obj.$$hashKey = objType + ':' + (nextUidFn || nextUid)();\n  } else {\n    key = objType + ':' + obj;\n  }\n\n  return key;\n}\n\n/**\n * HashMap which can use objects as keys\n */\nfunction HashMap(array, isolatedUid) {\n  if (isolatedUid) {\n    var uid = 0;\n    this.nextUid = function() {\n      return ++uid;\n    };\n  }\n  forEach(array, this.put, this);\n}\nHashMap.prototype = {\n  /**\n   * Store key value pair\n   * @param key key to store can be any type\n   * @param value value to store can be any type\n   */\n  put: function(key, value) {\n    this[hashKey(key, this.nextUid)] = value;\n  },\n\n  /**\n   * @param key\n   * @returns {Object} the value for the key\n   */\n  get: function(key) {\n    return this[hashKey(key, this.nextUid)];\n  },\n\n  /**\n   * Remove the key/value pair\n   * @param key\n   */\n  remove: function(key) {\n    var value = this[key = hashKey(key, this.nextUid)];\n    delete this[key];\n    return value;\n  }\n};\n\n/**\n * @ngdoc function\n * @module ng\n * @name angular.injector\n * @kind function\n *\n * @description\n * Creates an injector object that can be used for retrieving services as well as for\n * dependency injection (see {@link guide/di dependency injection}).\n *\n * @param {Array.<string|Function>} modules A list of module functions or their aliases. See\n *     {@link angular.module}. The `ng` module must be explicitly added.\n * @param {boolean=} [strictDi=false] Whether the injector should be in strict mode, which\n *     disallows argument name annotation inference.\n * @returns {injector} Injector object. See {@link auto.$injector $injector}.\n *\n * @example\n * Typical usage\n * ```js\n *   // create an injector\n *   var $injector = angular.injector(['ng']);\n *\n *   // use the injector to kick off your application\n *   // use the type inference to auto inject arguments, or use implicit injection\n *   $injector.invoke(function($rootScope, $compile, $document) {\n *     $compile($document)($rootScope);\n *     $rootScope.$digest();\n *   });\n * ```\n *\n * Sometimes you want to get access to the injector of a currently running Angular app\n * from outside Angular. Perhaps, you want to inject and compile some markup after the\n * application has been bootstrapped. You can do this using the extra `injector()` added\n * to JQuery/jqLite elements. See {@link angular.element}.\n *\n * *This is fairly rare but could be the case if a third party library is injecting the\n * markup.*\n *\n * In the following example a new block of HTML containing a `ng-controller`\n * directive is added to the end of the document body by JQuery. We then compile and link\n * it into the current AngularJS scope.\n *\n * ```js\n * var $div = $('<div ng-controller=\"MyCtrl\">{{content.label}}</div>');\n * $(document.body).append($div);\n *\n * angular.element(document).injector().invoke(function($compile) {\n *   var scope = angular.element($div).scope();\n *   $compile($div)(scope);\n * });\n * ```\n */\n\n\n/**\n * @ngdoc module\n * @name auto\n * @description\n *\n * Implicit module which gets automatically added to each {@link auto.$injector $injector}.\n */\n\nvar FN_ARGS = /^function\\s*[^\\(]*\\(\\s*([^\\)]*)\\)/m;\nvar FN_ARG_SPLIT = /,/;\nvar FN_ARG = /^\\s*(_?)(\\S+?)\\1\\s*$/;\nvar STRIP_COMMENTS = /((\\/\\/.*$)|(\\/\\*[\\s\\S]*?\\*\\/))/mg;\nvar $injectorMinErr = minErr('$injector');\n\nfunction anonFn(fn) {\n  // For anonymous functions, showing at the very least the function signature can help in\n  // debugging.\n  var fnText = fn.toString().replace(STRIP_COMMENTS, ''),\n      args = fnText.match(FN_ARGS);\n  if (args) {\n    return 'function(' + (args[1] || '').replace(/[\\s\\r\\n]+/, ' ') + ')';\n  }\n  return 'fn';\n}\n\nfunction annotate(fn, strictDi, name) {\n  var $inject,\n      fnText,\n      argDecl,\n      last;\n\n  if (typeof fn === 'function') {\n    if (!($inject = fn.$inject)) {\n      $inject = [];\n      if (fn.length) {\n        if (strictDi) {\n          if (!isString(name) || !name) {\n            name = fn.name || anonFn(fn);\n          }\n          throw $injectorMinErr('strictdi',\n            '{0} is not using explicit annotation and cannot be invoked in strict mode', name);\n        }\n        fnText = fn.toString().replace(STRIP_COMMENTS, '');\n        argDecl = fnText.match(FN_ARGS);\n        forEach(argDecl[1].split(FN_ARG_SPLIT), function(arg) {\n          arg.replace(FN_ARG, function(all, underscore, name) {\n            $inject.push(name);\n          });\n        });\n      }\n      fn.$inject = $inject;\n    }\n  } else if (isArray(fn)) {\n    last = fn.length - 1;\n    assertArgFn(fn[last], 'fn');\n    $inject = fn.slice(0, last);\n  } else {\n    assertArgFn(fn, 'fn', true);\n  }\n  return $inject;\n}\n\n///////////////////////////////////////\n\n/**\n * @ngdoc service\n * @name $injector\n *\n * @description\n *\n * `$injector` is used to retrieve object instances as defined by\n * {@link auto.$provide provider}, instantiate types, invoke methods,\n * and load modules.\n *\n * The following always holds true:\n *\n * ```js\n *   var $injector = angular.injector();\n *   expect($injector.get('$injector')).toBe($injector);\n *   expect($injector.invoke(function($injector) {\n *     return $injector;\n *   })).toBe($injector);\n * ```\n *\n * # Injection Function Annotation\n *\n * JavaScript does not have annotations, and annotations are needed for dependency injection. The\n * following are all valid ways of annotating function with injection arguments and are equivalent.\n *\n * ```js\n *   // inferred (only works if code not minified/obfuscated)\n *   $injector.invoke(function(serviceA){});\n *\n *   // annotated\n *   function explicit(serviceA) {};\n *   explicit.$inject = ['serviceA'];\n *   $injector.invoke(explicit);\n *\n *   // inline\n *   $injector.invoke(['serviceA', function(serviceA){}]);\n * ```\n *\n * ## Inference\n *\n * In JavaScript calling `toString()` on a function returns the function definition. The definition\n * can then be parsed and the function arguments can be extracted. This method of discovering\n * annotations is disallowed when the injector is in strict mode.\n * *NOTE:* This does not work with minification, and obfuscation tools since these tools change the\n * argument names.\n *\n * ## `$inject` Annotation\n * By adding an `$inject` property onto a function the injection parameters can be specified.\n *\n * ## Inline\n * As an array of injection names, where the last item in the array is the function to call.\n */\n\n/**\n * @ngdoc method\n * @name $injector#get\n *\n * @description\n * Return an instance of the service.\n *\n * @param {string} name The name of the instance to retrieve.\n * @param {string} caller An optional string to provide the origin of the function call for error messages.\n * @return {*} The instance.\n */\n\n/**\n * @ngdoc method\n * @name $injector#invoke\n *\n * @description\n * Invoke the method and supply the method arguments from the `$injector`.\n *\n * @param {!Function} fn The function to invoke. Function parameters are injected according to the\n *   {@link guide/di $inject Annotation} rules.\n * @param {Object=} self The `this` for the invoked method.\n * @param {Object=} locals Optional object. If preset then any argument names are read from this\n *                         object first, before the `$injector` is consulted.\n * @returns {*} the value returned by the invoked `fn` function.\n */\n\n/**\n * @ngdoc method\n * @name $injector#has\n *\n * @description\n * Allows the user to query if the particular service exists.\n *\n * @param {string} name Name of the service to query.\n * @returns {boolean} `true` if injector has given service.\n */\n\n/**\n * @ngdoc method\n * @name $injector#instantiate\n * @description\n * Create a new instance of JS type. The method takes a constructor function, invokes the new\n * operator, and supplies all of the arguments to the constructor function as specified by the\n * constructor annotation.\n *\n * @param {Function} Type Annotated constructor function.\n * @param {Object=} locals Optional object. If preset then any argument names are read from this\n * object first, before the `$injector` is consulted.\n * @returns {Object} new instance of `Type`.\n */\n\n/**\n * @ngdoc method\n * @name $injector#annotate\n *\n * @description\n * Returns an array of service names which the function is requesting for injection. This API is\n * used by the injector to determine which services need to be injected into the function when the\n * function is invoked. There are three ways in which the function can be annotated with the needed\n * dependencies.\n *\n * # Argument names\n *\n * The simplest form is to extract the dependencies from the arguments of the function. This is done\n * by converting the function into a string using `toString()` method and extracting the argument\n * names.\n * ```js\n *   // Given\n *   function MyController($scope, $route) {\n *     // ...\n *   }\n *\n *   // Then\n *   expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);\n * ```\n *\n * You can disallow this method by using strict injection mode.\n *\n * This method does not work with code minification / obfuscation. For this reason the following\n * annotation strategies are supported.\n *\n * # The `$inject` property\n *\n * If a function has an `$inject` property and its value is an array of strings, then the strings\n * represent names of services to be injected into the function.\n * ```js\n *   // Given\n *   var MyController = function(obfuscatedScope, obfuscatedRoute) {\n *     // ...\n *   }\n *   // Define function dependencies\n *   MyController['$inject'] = ['$scope', '$route'];\n *\n *   // Then\n *   expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);\n * ```\n *\n * # The array notation\n *\n * It is often desirable to inline Injected functions and that's when setting the `$inject` property\n * is very inconvenient. In these situations using the array notation to specify the dependencies in\n * a way that survives minification is a better choice:\n *\n * ```js\n *   // We wish to write this (not minification / obfuscation safe)\n *   injector.invoke(function($compile, $rootScope) {\n *     // ...\n *   });\n *\n *   // We are forced to write break inlining\n *   var tmpFn = function(obfuscatedCompile, obfuscatedRootScope) {\n *     // ...\n *   };\n *   tmpFn.$inject = ['$compile', '$rootScope'];\n *   injector.invoke(tmpFn);\n *\n *   // To better support inline function the inline annotation is supported\n *   injector.invoke(['$compile', '$rootScope', function(obfCompile, obfRootScope) {\n *     // ...\n *   }]);\n *\n *   // Therefore\n *   expect(injector.annotate(\n *      ['$compile', '$rootScope', function(obfus_$compile, obfus_$rootScope) {}])\n *    ).toEqual(['$compile', '$rootScope']);\n * ```\n *\n * @param {Function|Array.<string|Function>} fn Function for which dependent service names need to\n * be retrieved as described above.\n *\n * @param {boolean=} [strictDi=false] Disallow argument name annotation inference.\n *\n * @returns {Array.<string>} The names of the services which the function requires.\n */\n\n\n\n\n/**\n * @ngdoc service\n * @name $provide\n *\n * @description\n *\n * The {@link auto.$provide $provide} service has a number of methods for registering components\n * with the {@link auto.$injector $injector}. Many of these functions are also exposed on\n * {@link angular.Module}.\n *\n * An Angular **service** is a singleton object created by a **service factory**.  These **service\n * factories** are functions which, in turn, are created by a **service provider**.\n * The **service providers** are constructor functions. When instantiated they must contain a\n * property called `$get`, which holds the **service factory** function.\n *\n * When you request a service, the {@link auto.$injector $injector} is responsible for finding the\n * correct **service provider**, instantiating it and then calling its `$get` **service factory**\n * function to get the instance of the **service**.\n *\n * Often services have no configuration options and there is no need to add methods to the service\n * provider.  The provider will be no more than a constructor function with a `$get` property. For\n * these cases the {@link auto.$provide $provide} service has additional helper methods to register\n * services without specifying a provider.\n *\n * * {@link auto.$provide#provider provider(provider)} - registers a **service provider** with the\n *     {@link auto.$injector $injector}\n * * {@link auto.$provide#constant constant(obj)} - registers a value/object that can be accessed by\n *     providers and services.\n * * {@link auto.$provide#value value(obj)} - registers a value/object that can only be accessed by\n *     services, not providers.\n * * {@link auto.$provide#factory factory(fn)} - registers a service **factory function**, `fn`,\n *     that will be wrapped in a **service provider** object, whose `$get` property will contain the\n *     given factory function.\n * * {@link auto.$provide#service service(class)} - registers a **constructor function**, `class`\n *     that will be wrapped in a **service provider** object, whose `$get` property will instantiate\n *      a new object using the given constructor function.\n *\n * See the individual methods for more information and examples.\n */\n\n/**\n * @ngdoc method\n * @name $provide#provider\n * @description\n *\n * Register a **provider function** with the {@link auto.$injector $injector}. Provider functions\n * are constructor functions, whose instances are responsible for \"providing\" a factory for a\n * service.\n *\n * Service provider names start with the name of the service they provide followed by `Provider`.\n * For example, the {@link ng.$log $log} service has a provider called\n * {@link ng.$logProvider $logProvider}.\n *\n * Service provider objects can have additional methods which allow configuration of the provider\n * and its service. Importantly, you can configure what kind of service is created by the `$get`\n * method, or how that service will act. For example, the {@link ng.$logProvider $logProvider} has a\n * method {@link ng.$logProvider#debugEnabled debugEnabled}\n * which lets you specify whether the {@link ng.$log $log} service will log debug messages to the\n * console or not.\n *\n * @param {string} name The name of the instance. NOTE: the provider will be available under `name +\n                        'Provider'` key.\n * @param {(Object|function())} provider If the provider is:\n *\n *   - `Object`: then it should have a `$get` method. The `$get` method will be invoked using\n *     {@link auto.$injector#invoke $injector.invoke()} when an instance needs to be created.\n *   - `Constructor`: a new instance of the provider will be created using\n *     {@link auto.$injector#instantiate $injector.instantiate()}, then treated as `object`.\n *\n * @returns {Object} registered provider instance\n\n * @example\n *\n * The following example shows how to create a simple event tracking service and register it using\n * {@link auto.$provide#provider $provide.provider()}.\n *\n * ```js\n *  // Define the eventTracker provider\n *  function EventTrackerProvider() {\n *    var trackingUrl = '/track';\n *\n *    // A provider method for configuring where the tracked events should been saved\n *    this.setTrackingUrl = function(url) {\n *      trackingUrl = url;\n *    };\n *\n *    // The service factory function\n *    this.$get = ['$http', function($http) {\n *      var trackedEvents = {};\n *      return {\n *        // Call this to track an event\n *        event: function(event) {\n *          var count = trackedEvents[event] || 0;\n *          count += 1;\n *          trackedEvents[event] = count;\n *          return count;\n *        },\n *        // Call this to save the tracked events to the trackingUrl\n *        save: function() {\n *          $http.post(trackingUrl, trackedEvents);\n *        }\n *      };\n *    }];\n *  }\n *\n *  describe('eventTracker', function() {\n *    var postSpy;\n *\n *    beforeEach(module(function($provide) {\n *      // Register the eventTracker provider\n *      $provide.provider('eventTracker', EventTrackerProvider);\n *    }));\n *\n *    beforeEach(module(function(eventTrackerProvider) {\n *      // Configure eventTracker provider\n *      eventTrackerProvider.setTrackingUrl('/custom-track');\n *    }));\n *\n *    it('tracks events', inject(function(eventTracker) {\n *      expect(eventTracker.event('login')).toEqual(1);\n *      expect(eventTracker.event('login')).toEqual(2);\n *    }));\n *\n *    it('saves to the tracking url', inject(function(eventTracker, $http) {\n *      postSpy = spyOn($http, 'post');\n *      eventTracker.event('login');\n *      eventTracker.save();\n *      expect(postSpy).toHaveBeenCalled();\n *      expect(postSpy.mostRecentCall.args[0]).not.toEqual('/track');\n *      expect(postSpy.mostRecentCall.args[0]).toEqual('/custom-track');\n *      expect(postSpy.mostRecentCall.args[1]).toEqual({ 'login': 1 });\n *    }));\n *  });\n * ```\n */\n\n/**\n * @ngdoc method\n * @name $provide#factory\n * @description\n *\n * Register a **service factory**, which will be called to return the service instance.\n * This is short for registering a service where its provider consists of only a `$get` property,\n * which is the given service factory function.\n * You should use {@link auto.$provide#factory $provide.factory(getFn)} if you do not need to\n * configure your service in a provider.\n *\n * @param {string} name The name of the instance.\n * @param {function()} $getFn The $getFn for the instance creation. Internally this is a short hand\n *                            for `$provide.provider(name, {$get: $getFn})`.\n * @returns {Object} registered provider instance\n *\n * @example\n * Here is an example of registering a service\n * ```js\n *   $provide.factory('ping', ['$http', function($http) {\n *     return function ping() {\n *       return $http.send('/ping');\n *     };\n *   }]);\n * ```\n * You would then inject and use this service like this:\n * ```js\n *   someModule.controller('Ctrl', ['ping', function(ping) {\n *     ping();\n *   }]);\n * ```\n */\n\n\n/**\n * @ngdoc method\n * @name $provide#service\n * @description\n *\n * Register a **service constructor**, which will be invoked with `new` to create the service\n * instance.\n * This is short for registering a service where its provider's `$get` property is the service\n * constructor function that will be used to instantiate the service instance.\n *\n * You should use {@link auto.$provide#service $provide.service(class)} if you define your service\n * as a type/class.\n *\n * @param {string} name The name of the instance.\n * @param {Function} constructor A class (constructor function) that will be instantiated.\n * @returns {Object} registered provider instance\n *\n * @example\n * Here is an example of registering a service using\n * {@link auto.$provide#service $provide.service(class)}.\n * ```js\n *   var Ping = function($http) {\n *     this.$http = $http;\n *   };\n *\n *   Ping.$inject = ['$http'];\n *\n *   Ping.prototype.send = function() {\n *     return this.$http.get('/ping');\n *   };\n *   $provide.service('ping', Ping);\n * ```\n * You would then inject and use this service like this:\n * ```js\n *   someModule.controller('Ctrl', ['ping', function(ping) {\n *     ping.send();\n *   }]);\n * ```\n */\n\n\n/**\n * @ngdoc method\n * @name $provide#value\n * @description\n *\n * Register a **value service** with the {@link auto.$injector $injector}, such as a string, a\n * number, an array, an object or a function.  This is short for registering a service where its\n * provider's `$get` property is a factory function that takes no arguments and returns the **value\n * service**.\n *\n * Value services are similar to constant services, except that they cannot be injected into a\n * module configuration function (see {@link angular.Module#config}) but they can be overridden by\n * an Angular\n * {@link auto.$provide#decorator decorator}.\n *\n * @param {string} name The name of the instance.\n * @param {*} value The value.\n * @returns {Object} registered provider instance\n *\n * @example\n * Here are some examples of creating value services.\n * ```js\n *   $provide.value('ADMIN_USER', 'admin');\n *\n *   $provide.value('RoleLookup', { admin: 0, writer: 1, reader: 2 });\n *\n *   $provide.value('halfOf', function(value) {\n *     return value / 2;\n *   });\n * ```\n */\n\n\n/**\n * @ngdoc method\n * @name $provide#constant\n * @description\n *\n * Register a **constant service**, such as a string, a number, an array, an object or a function,\n * with the {@link auto.$injector $injector}. Unlike {@link auto.$provide#value value} it can be\n * injected into a module configuration function (see {@link angular.Module#config}) and it cannot\n * be overridden by an Angular {@link auto.$provide#decorator decorator}.\n *\n * @param {string} name The name of the constant.\n * @param {*} value The constant value.\n * @returns {Object} registered instance\n *\n * @example\n * Here a some examples of creating constants:\n * ```js\n *   $provide.constant('SHARD_HEIGHT', 306);\n *\n *   $provide.constant('MY_COLOURS', ['red', 'blue', 'grey']);\n *\n *   $provide.constant('double', function(value) {\n *     return value * 2;\n *   });\n * ```\n */\n\n\n/**\n * @ngdoc method\n * @name $provide#decorator\n * @description\n *\n * Register a **service decorator** with the {@link auto.$injector $injector}. A service decorator\n * intercepts the creation of a service, allowing it to override or modify the behaviour of the\n * service. The object returned by the decorator may be the original service, or a new service\n * object which replaces or wraps and delegates to the original service.\n *\n * @param {string} name The name of the service to decorate.\n * @param {function()} decorator This function will be invoked when the service needs to be\n *    instantiated and should return the decorated service instance. The function is called using\n *    the {@link auto.$injector#invoke injector.invoke} method and is therefore fully injectable.\n *    Local injection arguments:\n *\n *    * `$delegate` - The original service instance, which can be monkey patched, configured,\n *      decorated or delegated to.\n *\n * @example\n * Here we decorate the {@link ng.$log $log} service to convert warnings to errors by intercepting\n * calls to {@link ng.$log#error $log.warn()}.\n * ```js\n *   $provide.decorator('$log', ['$delegate', function($delegate) {\n *     $delegate.warn = $delegate.error;\n *     return $delegate;\n *   }]);\n * ```\n */\n\n\nfunction createInjector(modulesToLoad, strictDi) {\n  strictDi = (strictDi === true);\n  var INSTANTIATING = {},\n      providerSuffix = 'Provider',\n      path = [],\n      loadedModules = new HashMap([], true),\n      providerCache = {\n        $provide: {\n            provider: supportObject(provider),\n            factory: supportObject(factory),\n            service: supportObject(service),\n            value: supportObject(value),\n            constant: supportObject(constant),\n            decorator: decorator\n          }\n      },\n      providerInjector = (providerCache.$injector =\n          createInternalInjector(providerCache, function(serviceName, caller) {\n            if (angular.isString(caller)) {\n              path.push(caller);\n            }\n            throw $injectorMinErr('unpr', \"Unknown provider: {0}\", path.join(' <- '));\n          })),\n      instanceCache = {},\n      instanceInjector = (instanceCache.$injector =\n          createInternalInjector(instanceCache, function(serviceName, caller) {\n            var provider = providerInjector.get(serviceName + providerSuffix, caller);\n            return instanceInjector.invoke(provider.$get, provider, undefined, serviceName);\n          }));\n\n\n  forEach(loadModules(modulesToLoad), function(fn) { instanceInjector.invoke(fn || noop); });\n\n  return instanceInjector;\n\n  ////////////////////////////////////\n  // $provider\n  ////////////////////////////////////\n\n  function supportObject(delegate) {\n    return function(key, value) {\n      if (isObject(key)) {\n        forEach(key, reverseParams(delegate));\n      } else {\n        return delegate(key, value);\n      }\n    };\n  }\n\n  function provider(name, provider_) {\n    assertNotHasOwnProperty(name, 'service');\n    if (isFunction(provider_) || isArray(provider_)) {\n      provider_ = providerInjector.instantiate(provider_);\n    }\n    if (!provider_.$get) {\n      throw $injectorMinErr('pget', \"Provider '{0}' must define $get factory method.\", name);\n    }\n    return providerCache[name + providerSuffix] = provider_;\n  }\n\n  function enforceReturnValue(name, factory) {\n    return function enforcedReturnValue() {\n      var result = instanceInjector.invoke(factory, this);\n      if (isUndefined(result)) {\n        throw $injectorMinErr('undef', \"Provider '{0}' must return a value from $get factory method.\", name);\n      }\n      return result;\n    };\n  }\n\n  function factory(name, factoryFn, enforce) {\n    return provider(name, {\n      $get: enforce !== false ? enforceReturnValue(name, factoryFn) : factoryFn\n    });\n  }\n\n  function service(name, constructor) {\n    return factory(name, ['$injector', function($injector) {\n      return $injector.instantiate(constructor);\n    }]);\n  }\n\n  function value(name, val) { return factory(name, valueFn(val), false); }\n\n  function constant(name, value) {\n    assertNotHasOwnProperty(name, 'constant');\n    providerCache[name] = value;\n    instanceCache[name] = value;\n  }\n\n  function decorator(serviceName, decorFn) {\n    var origProvider = providerInjector.get(serviceName + providerSuffix),\n        orig$get = origProvider.$get;\n\n    origProvider.$get = function() {\n      var origInstance = instanceInjector.invoke(orig$get, origProvider);\n      return instanceInjector.invoke(decorFn, null, {$delegate: origInstance});\n    };\n  }\n\n  ////////////////////////////////////\n  // Module Loading\n  ////////////////////////////////////\n  function loadModules(modulesToLoad) {\n    var runBlocks = [], moduleFn;\n    forEach(modulesToLoad, function(module) {\n      if (loadedModules.get(module)) return;\n      loadedModules.put(module, true);\n\n      function runInvokeQueue(queue) {\n        var i, ii;\n        for (i = 0, ii = queue.length; i < ii; i++) {\n          var invokeArgs = queue[i],\n              provider = providerInjector.get(invokeArgs[0]);\n\n          provider[invokeArgs[1]].apply(provider, invokeArgs[2]);\n        }\n      }\n\n      try {\n        if (isString(module)) {\n          moduleFn = angularModule(module);\n          runBlocks = runBlocks.concat(loadModules(moduleFn.requires)).concat(moduleFn._runBlocks);\n          runInvokeQueue(moduleFn._invokeQueue);\n          runInvokeQueue(moduleFn._configBlocks);\n        } else if (isFunction(module)) {\n            runBlocks.push(providerInjector.invoke(module));\n        } else if (isArray(module)) {\n            runBlocks.push(providerInjector.invoke(module));\n        } else {\n          assertArgFn(module, 'module');\n        }\n      } catch (e) {\n        if (isArray(module)) {\n          module = module[module.length - 1];\n        }\n        if (e.message && e.stack && e.stack.indexOf(e.message) == -1) {\n          // Safari & FF's stack traces don't contain error.message content\n          // unlike those of Chrome and IE\n          // So if stack doesn't contain message, we create a new string that contains both.\n          // Since error.stack is read-only in Safari, I'm overriding e and not e.stack here.\n          /* jshint -W022 */\n          e = e.message + '\\n' + e.stack;\n        }\n        throw $injectorMinErr('modulerr', \"Failed to instantiate module {0} due to:\\n{1}\",\n                  module, e.stack || e.message || e);\n      }\n    });\n    return runBlocks;\n  }\n\n  ////////////////////////////////////\n  // internal Injector\n  ////////////////////////////////////\n\n  function createInternalInjector(cache, factory) {\n\n    function getService(serviceName, caller) {\n      if (cache.hasOwnProperty(serviceName)) {\n        if (cache[serviceName] === INSTANTIATING) {\n          throw $injectorMinErr('cdep', 'Circular dependency found: {0}',\n                    serviceName + ' <- ' + path.join(' <- '));\n        }\n        return cache[serviceName];\n      } else {\n        try {\n          path.unshift(serviceName);\n          cache[serviceName] = INSTANTIATING;\n          return cache[serviceName] = factory(serviceName, caller);\n        } catch (err) {\n          if (cache[serviceName] === INSTANTIATING) {\n            delete cache[serviceName];\n          }\n          throw err;\n        } finally {\n          path.shift();\n        }\n      }\n    }\n\n    function invoke(fn, self, locals, serviceName) {\n      if (typeof locals === 'string') {\n        serviceName = locals;\n        locals = null;\n      }\n\n      var args = [],\n          $inject = createInjector.$$annotate(fn, strictDi, serviceName),\n          length, i,\n          key;\n\n      for (i = 0, length = $inject.length; i < length; i++) {\n        key = $inject[i];\n        if (typeof key !== 'string') {\n          throw $injectorMinErr('itkn',\n                  'Incorrect injection token! Expected service name as string, got {0}', key);\n        }\n        args.push(\n          locals && locals.hasOwnProperty(key)\n          ? locals[key]\n          : getService(key, serviceName)\n        );\n      }\n      if (isArray(fn)) {\n        fn = fn[length];\n      }\n\n      // http://jsperf.com/angularjs-invoke-apply-vs-switch\n      // #5388\n      return fn.apply(self, args);\n    }\n\n    function instantiate(Type, locals, serviceName) {\n      // Check if Type is annotated and use just the given function at n-1 as parameter\n      // e.g. someModule.factory('greeter', ['$window', function(renamed$window) {}]);\n      // Object creation: http://jsperf.com/create-constructor/2\n      var instance = Object.create((isArray(Type) ? Type[Type.length - 1] : Type).prototype || null);\n      var returnedValue = invoke(Type, instance, locals, serviceName);\n\n      return isObject(returnedValue) || isFunction(returnedValue) ? returnedValue : instance;\n    }\n\n    return {\n      invoke: invoke,\n      instantiate: instantiate,\n      get: getService,\n      annotate: createInjector.$$annotate,\n      has: function(name) {\n        return providerCache.hasOwnProperty(name + providerSuffix) || cache.hasOwnProperty(name);\n      }\n    };\n  }\n}\n\ncreateInjector.$$annotate = annotate;\n\n/**\n * @ngdoc provider\n * @name $anchorScrollProvider\n *\n * @description\n * Use `$anchorScrollProvider` to disable automatic scrolling whenever\n * {@link ng.$location#hash $location.hash()} changes.\n */\nfunction $AnchorScrollProvider() {\n\n  var autoScrollingEnabled = true;\n\n  /**\n   * @ngdoc method\n   * @name $anchorScrollProvider#disableAutoScrolling\n   *\n   * @description\n   * By default, {@link ng.$anchorScroll $anchorScroll()} will automatically detect changes to\n   * {@link ng.$location#hash $location.hash()} and scroll to the element matching the new hash.<br />\n   * Use this method to disable automatic scrolling.\n   *\n   * If automatic scrolling is disabled, one must explicitly call\n   * {@link ng.$anchorScroll $anchorScroll()} in order to scroll to the element related to the\n   * current hash.\n   */\n  this.disableAutoScrolling = function() {\n    autoScrollingEnabled = false;\n  };\n\n  /**\n   * @ngdoc service\n   * @name $anchorScroll\n   * @kind function\n   * @requires $window\n   * @requires $location\n   * @requires $rootScope\n   *\n   * @description\n   * When called, it checks the current value of {@link ng.$location#hash $location.hash()} and\n   * scrolls to the related element, according to the rules specified in the\n   * [Html5 spec](http://dev.w3.org/html5/spec/Overview.html#the-indicated-part-of-the-document).\n   *\n   * It also watches the {@link ng.$location#hash $location.hash()} and automatically scrolls to\n   * match any anchor whenever it changes. This can be disabled by calling\n   * {@link ng.$anchorScrollProvider#disableAutoScrolling $anchorScrollProvider.disableAutoScrolling()}.\n   *\n   * Additionally, you can use its {@link ng.$anchorScroll#yOffset yOffset} property to specify a\n   * vertical scroll-offset (either fixed or dynamic).\n   *\n   * @property {(number|function|jqLite)} yOffset\n   * If set, specifies a vertical scroll-offset. This is often useful when there are fixed\n   * positioned elements at the top of the page, such as navbars, headers etc.\n   *\n   * `yOffset` can be specified in various ways:\n   * - **number**: A fixed number of pixels to be used as offset.<br /><br />\n   * - **function**: A getter function called everytime `$anchorScroll()` is executed. Must return\n   *   a number representing the offset (in pixels).<br /><br />\n   * - **jqLite**: A jqLite/jQuery element to be used for specifying the offset. The distance from\n   *   the top of the page to the element's bottom will be used as offset.<br />\n   *   **Note**: The element will be taken into account only as long as its `position` is set to\n   *   `fixed`. This option is useful, when dealing with responsive navbars/headers that adjust\n   *   their height and/or positioning according to the viewport's size.\n   *\n   * <br />\n   * <div class=\"alert alert-warning\">\n   * In order for `yOffset` to work properly, scrolling should take place on the document's root and\n   * not some child element.\n   * </div>\n   *\n   * @example\n     <example module=\"anchorScrollExample\">\n       <file name=\"index.html\">\n         <div id=\"scrollArea\" ng-controller=\"ScrollController\">\n           <a ng-click=\"gotoBottom()\">Go to bottom</a>\n           <a id=\"bottom\"></a> You're at the bottom!\n         </div>\n       </file>\n       <file name=\"script.js\">\n         angular.module('anchorScrollExample', [])\n           .controller('ScrollController', ['$scope', '$location', '$anchorScroll',\n             function ($scope, $location, $anchorScroll) {\n               $scope.gotoBottom = function() {\n                 // set the location.hash to the id of\n                 // the element you wish to scroll to.\n                 $location.hash('bottom');\n\n                 // call $anchorScroll()\n                 $anchorScroll();\n               };\n             }]);\n       </file>\n       <file name=\"style.css\">\n         #scrollArea {\n           height: 280px;\n           overflow: auto;\n         }\n\n         #bottom {\n           display: block;\n           margin-top: 2000px;\n         }\n       </file>\n     </example>\n   *\n   * <hr />\n   * The example below illustrates the use of a vertical scroll-offset (specified as a fixed value).\n   * See {@link ng.$anchorScroll#yOffset $anchorScroll.yOffset} for more details.\n   *\n   * @example\n     <example module=\"anchorScrollOffsetExample\">\n       <file name=\"index.html\">\n         <div class=\"fixed-header\" ng-controller=\"headerCtrl\">\n           <a href=\"\" ng-click=\"gotoAnchor(x)\" ng-repeat=\"x in [1,2,3,4,5]\">\n             Go to anchor {{x}}\n           </a>\n         </div>\n         <div id=\"anchor{{x}}\" class=\"anchor\" ng-repeat=\"x in [1,2,3,4,5]\">\n           Anchor {{x}} of 5\n         </div>\n       </file>\n       <file name=\"script.js\">\n         angular.module('anchorScrollOffsetExample', [])\n           .run(['$anchorScroll', function($anchorScroll) {\n             $anchorScroll.yOffset = 50;   // always scroll by 50 extra pixels\n           }])\n           .controller('headerCtrl', ['$anchorScroll', '$location', '$scope',\n             function ($anchorScroll, $location, $scope) {\n               $scope.gotoAnchor = function(x) {\n                 var newHash = 'anchor' + x;\n                 if ($location.hash() !== newHash) {\n                   // set the $location.hash to `newHash` and\n                   // $anchorScroll will automatically scroll to it\n                   $location.hash('anchor' + x);\n                 } else {\n                   // call $anchorScroll() explicitly,\n                   // since $location.hash hasn't changed\n                   $anchorScroll();\n                 }\n               };\n             }\n           ]);\n       </file>\n       <file name=\"style.css\">\n         body {\n           padding-top: 50px;\n         }\n\n         .anchor {\n           border: 2px dashed DarkOrchid;\n           padding: 10px 10px 200px 10px;\n         }\n\n         .fixed-header {\n           background-color: rgba(0, 0, 0, 0.2);\n           height: 50px;\n           position: fixed;\n           top: 0; left: 0; right: 0;\n         }\n\n         .fixed-header > a {\n           display: inline-block;\n           margin: 5px 15px;\n         }\n       </file>\n     </example>\n   */\n  this.$get = ['$window', '$location', '$rootScope', function($window, $location, $rootScope) {\n    var document = $window.document;\n\n    // Helper function to get first anchor from a NodeList\n    // (using `Array#some()` instead of `angular#forEach()` since it's more performant\n    //  and working in all supported browsers.)\n    function getFirstAnchor(list) {\n      var result = null;\n      Array.prototype.some.call(list, function(element) {\n        if (nodeName_(element) === 'a') {\n          result = element;\n          return true;\n        }\n      });\n      return result;\n    }\n\n    function getYOffset() {\n\n      var offset = scroll.yOffset;\n\n      if (isFunction(offset)) {\n        offset = offset();\n      } else if (isElement(offset)) {\n        var elem = offset[0];\n        var style = $window.getComputedStyle(elem);\n        if (style.position !== 'fixed') {\n          offset = 0;\n        } else {\n          offset = elem.getBoundingClientRect().bottom;\n        }\n      } else if (!isNumber(offset)) {\n        offset = 0;\n      }\n\n      return offset;\n    }\n\n    function scrollTo(elem) {\n      if (elem) {\n        elem.scrollIntoView();\n\n        var offset = getYOffset();\n\n        if (offset) {\n          // `offset` is the number of pixels we should scroll UP in order to align `elem` properly.\n          // This is true ONLY if the call to `elem.scrollIntoView()` initially aligns `elem` at the\n          // top of the viewport.\n          //\n          // IF the number of pixels from the top of `elem` to the end of the page's content is less\n          // than the height of the viewport, then `elem.scrollIntoView()` will align the `elem` some\n          // way down the page.\n          //\n          // This is often the case for elements near the bottom of the page.\n          //\n          // In such cases we do not need to scroll the whole `offset` up, just the difference between\n          // the top of the element and the offset, which is enough to align the top of `elem` at the\n          // desired position.\n          var elemTop = elem.getBoundingClientRect().top;\n          $window.scrollBy(0, elemTop - offset);\n        }\n      } else {\n        $window.scrollTo(0, 0);\n      }\n    }\n\n    function scroll() {\n      var hash = $location.hash(), elm;\n\n      // empty hash, scroll to the top of the page\n      if (!hash) scrollTo(null);\n\n      // element with given id\n      else if ((elm = document.getElementById(hash))) scrollTo(elm);\n\n      // first anchor with given name :-D\n      else if ((elm = getFirstAnchor(document.getElementsByName(hash)))) scrollTo(elm);\n\n      // no element and hash == 'top', scroll to the top of the page\n      else if (hash === 'top') scrollTo(null);\n    }\n\n    // does not scroll when user clicks on anchor link that is currently on\n    // (no url change, no $location.hash() change), browser native does scroll\n    if (autoScrollingEnabled) {\n      $rootScope.$watch(function autoScrollWatch() {return $location.hash();},\n        function autoScrollWatchAction(newVal, oldVal) {\n          // skip the initial scroll if $location.hash is empty\n          if (newVal === oldVal && newVal === '') return;\n\n          jqLiteDocumentLoaded(function() {\n            $rootScope.$evalAsync(scroll);\n          });\n        });\n    }\n\n    return scroll;\n  }];\n}\n\nvar $animateMinErr = minErr('$animate');\n\n/**\n * @ngdoc provider\n * @name $animateProvider\n *\n * @description\n * Default implementation of $animate that doesn't perform any animations, instead just\n * synchronously performs DOM\n * updates and calls done() callbacks.\n *\n * In order to enable animations the ngAnimate module has to be loaded.\n *\n * To see the functional implementation check out src/ngAnimate/animate.js\n */\nvar $AnimateProvider = ['$provide', function($provide) {\n\n\n  this.$$selectors = {};\n\n\n  /**\n   * @ngdoc method\n   * @name $animateProvider#register\n   *\n   * @description\n   * Registers a new injectable animation factory function. The factory function produces the\n   * animation object which contains callback functions for each event that is expected to be\n   * animated.\n   *\n   *   * `eventFn`: `function(Element, doneFunction)` The element to animate, the `doneFunction`\n   *   must be called once the element animation is complete. If a function is returned then the\n   *   animation service will use this function to cancel the animation whenever a cancel event is\n   *   triggered.\n   *\n   *\n   * ```js\n   *   return {\n     *     eventFn : function(element, done) {\n     *       //code to run the animation\n     *       //once complete, then run done()\n     *       return function cancellationFunction() {\n     *         //code to cancel the animation\n     *       }\n     *     }\n     *   }\n   * ```\n   *\n   * @param {string} name The name of the animation.\n   * @param {Function} factory The factory function that will be executed to return the animation\n   *                           object.\n   */\n  this.register = function(name, factory) {\n    var key = name + '-animation';\n    if (name && name.charAt(0) != '.') throw $animateMinErr('notcsel',\n        \"Expecting class selector starting with '.' got '{0}'.\", name);\n    this.$$selectors[name.substr(1)] = key;\n    $provide.factory(key, factory);\n  };\n\n  /**\n   * @ngdoc method\n   * @name $animateProvider#classNameFilter\n   *\n   * @description\n   * Sets and/or returns the CSS class regular expression that is checked when performing\n   * an animation. Upon bootstrap the classNameFilter value is not set at all and will\n   * therefore enable $animate to attempt to perform an animation on any element.\n   * When setting the classNameFilter value, animations will only be performed on elements\n   * that successfully match the filter expression. This in turn can boost performance\n   * for low-powered devices as well as applications containing a lot of structural operations.\n   * @param {RegExp=} expression The className expression which will be checked against all animations\n   * @return {RegExp} The current CSS className expression value. If null then there is no expression value\n   */\n  this.classNameFilter = function(expression) {\n    if (arguments.length === 1) {\n      this.$$classNameFilter = (expression instanceof RegExp) ? expression : null;\n    }\n    return this.$$classNameFilter;\n  };\n\n  this.$get = ['$$q', '$$asyncCallback', '$rootScope', function($$q, $$asyncCallback, $rootScope) {\n\n    var currentDefer;\n\n    function runAnimationPostDigest(fn) {\n      var cancelFn, defer = $$q.defer();\n      defer.promise.$$cancelFn = function ngAnimateMaybeCancel() {\n        cancelFn && cancelFn();\n      };\n\n      $rootScope.$$postDigest(function ngAnimatePostDigest() {\n        cancelFn = fn(function ngAnimateNotifyComplete() {\n          defer.resolve();\n        });\n      });\n\n      return defer.promise;\n    }\n\n    function resolveElementClasses(element, classes) {\n      var toAdd = [], toRemove = [];\n\n      var hasClasses = createMap();\n      forEach((element.attr('class') || '').split(/\\s+/), function(className) {\n        hasClasses[className] = true;\n      });\n\n      forEach(classes, function(status, className) {\n        var hasClass = hasClasses[className];\n\n        // If the most recent class manipulation (via $animate) was to remove the class, and the\n        // element currently has the class, the class is scheduled for removal. Otherwise, if\n        // the most recent class manipulation (via $animate) was to add the class, and the\n        // element does not currently have the class, the class is scheduled to be added.\n        if (status === false && hasClass) {\n          toRemove.push(className);\n        } else if (status === true && !hasClass) {\n          toAdd.push(className);\n        }\n      });\n\n      return (toAdd.length + toRemove.length) > 0 &&\n        [toAdd.length ? toAdd : null, toRemove.length ? toRemove : null];\n    }\n\n    function cachedClassManipulation(cache, classes, op) {\n      for (var i=0, ii = classes.length; i < ii; ++i) {\n        var className = classes[i];\n        cache[className] = op;\n      }\n    }\n\n    function asyncPromise() {\n      // only serve one instance of a promise in order to save CPU cycles\n      if (!currentDefer) {\n        currentDefer = $$q.defer();\n        $$asyncCallback(function() {\n          currentDefer.resolve();\n          currentDefer = null;\n        });\n      }\n      return currentDefer.promise;\n    }\n\n    function applyStyles(element, options) {\n      if (angular.isObject(options)) {\n        var styles = extend(options.from || {}, options.to || {});\n        element.css(styles);\n      }\n    }\n\n    /**\n     *\n     * @ngdoc service\n     * @name $animate\n     * @description The $animate service provides rudimentary DOM manipulation functions to\n     * insert, remove and move elements within the DOM, as well as adding and removing classes.\n     * This service is the core service used by the ngAnimate $animator service which provides\n     * high-level animation hooks for CSS and JavaScript.\n     *\n     * $animate is available in the AngularJS core, however, the ngAnimate module must be included\n     * to enable full out animation support. Otherwise, $animate will only perform simple DOM\n     * manipulation operations.\n     *\n     * To learn more about enabling animation support, click here to visit the {@link ngAnimate\n     * ngAnimate module page} as well as the {@link ngAnimate.$animate ngAnimate $animate service\n     * page}.\n     */\n    return {\n      animate: function(element, from, to) {\n        applyStyles(element, { from: from, to: to });\n        return asyncPromise();\n      },\n\n      /**\n       *\n       * @ngdoc method\n       * @name $animate#enter\n       * @kind function\n       * @description Inserts the element into the DOM either after the `after` element or\n       * as the first child within the `parent` element. When the function is called a promise\n       * is returned that will be resolved at a later time.\n       * @param {DOMElement} element the element which will be inserted into the DOM\n       * @param {DOMElement} parent the parent element which will append the element as\n       *   a child (if the after element is not present)\n       * @param {DOMElement} after the sibling element which will append the element\n       *   after itself\n       * @param {object=} options an optional collection of styles that will be applied to the element.\n       * @return {Promise} the animation callback promise\n       */\n      enter: function(element, parent, after, options) {\n        applyStyles(element, options);\n        after ? after.after(element)\n              : parent.prepend(element);\n        return asyncPromise();\n      },\n\n      /**\n       *\n       * @ngdoc method\n       * @name $animate#leave\n       * @kind function\n       * @description Removes the element from the DOM. When the function is called a promise\n       * is returned that will be resolved at a later time.\n       * @param {DOMElement} element the element which will be removed from the DOM\n       * @param {object=} options an optional collection of options that will be applied to the element.\n       * @return {Promise} the animation callback promise\n       */\n      leave: function(element, options) {\n        element.remove();\n        return asyncPromise();\n      },\n\n      /**\n       *\n       * @ngdoc method\n       * @name $animate#move\n       * @kind function\n       * @description Moves the position of the provided element within the DOM to be placed\n       * either after the `after` element or inside of the `parent` element. When the function\n       * is called a promise is returned that will be resolved at a later time.\n       *\n       * @param {DOMElement} element the element which will be moved around within the\n       *   DOM\n       * @param {DOMElement} parent the parent element where the element will be\n       *   inserted into (if the after element is not present)\n       * @param {DOMElement} after the sibling element where the element will be\n       *   positioned next to\n       * @param {object=} options an optional collection of options that will be applied to the element.\n       * @return {Promise} the animation callback promise\n       */\n      move: function(element, parent, after, options) {\n        // Do not remove element before insert. Removing will cause data associated with the\n        // element to be dropped. Insert will implicitly do the remove.\n        return this.enter(element, parent, after, options);\n      },\n\n      /**\n       *\n       * @ngdoc method\n       * @name $animate#addClass\n       * @kind function\n       * @description Adds the provided className CSS class value to the provided element.\n       * When the function is called a promise is returned that will be resolved at a later time.\n       * @param {DOMElement} element the element which will have the className value\n       *   added to it\n       * @param {string} className the CSS class which will be added to the element\n       * @param {object=} options an optional collection of options that will be applied to the element.\n       * @return {Promise} the animation callback promise\n       */\n      addClass: function(element, className, options) {\n        return this.setClass(element, className, [], options);\n      },\n\n      $$addClassImmediately: function(element, className, options) {\n        element = jqLite(element);\n        className = !isString(className)\n                        ? (isArray(className) ? className.join(' ') : '')\n                        : className;\n        forEach(element, function(element) {\n          jqLiteAddClass(element, className);\n        });\n        applyStyles(element, options);\n        return asyncPromise();\n      },\n\n      /**\n       *\n       * @ngdoc method\n       * @name $animate#removeClass\n       * @kind function\n       * @description Removes the provided className CSS class value from the provided element.\n       * When the function is called a promise is returned that will be resolved at a later time.\n       * @param {DOMElement} element the element which will have the className value\n       *   removed from it\n       * @param {string} className the CSS class which will be removed from the element\n       * @param {object=} options an optional collection of options that will be applied to the element.\n       * @return {Promise} the animation callback promise\n       */\n      removeClass: function(element, className, options) {\n        return this.setClass(element, [], className, options);\n      },\n\n      $$removeClassImmediately: function(element, className, options) {\n        element = jqLite(element);\n        className = !isString(className)\n                        ? (isArray(className) ? className.join(' ') : '')\n                        : className;\n        forEach(element, function(element) {\n          jqLiteRemoveClass(element, className);\n        });\n        applyStyles(element, options);\n        return asyncPromise();\n      },\n\n      /**\n       *\n       * @ngdoc method\n       * @name $animate#setClass\n       * @kind function\n       * @description Adds and/or removes the given CSS classes to and from the element.\n       * When the function is called a promise is returned that will be resolved at a later time.\n       * @param {DOMElement} element the element which will have its CSS classes changed\n       *   removed from it\n       * @param {string} add the CSS classes which will be added to the element\n       * @param {string} remove the CSS class which will be removed from the element\n       * @param {object=} options an optional collection of options that will be applied to the element.\n       * @return {Promise} the animation callback promise\n       */\n      setClass: function(element, add, remove, options) {\n        var self = this;\n        var STORAGE_KEY = '$$animateClasses';\n        var createdCache = false;\n        element = jqLite(element);\n\n        var cache = element.data(STORAGE_KEY);\n        if (!cache) {\n          cache = {\n            classes: {},\n            options: options\n          };\n          createdCache = true;\n        } else if (options && cache.options) {\n          cache.options = angular.extend(cache.options || {}, options);\n        }\n\n        var classes = cache.classes;\n\n        add = isArray(add) ? add : add.split(' ');\n        remove = isArray(remove) ? remove : remove.split(' ');\n        cachedClassManipulation(classes, add, true);\n        cachedClassManipulation(classes, remove, false);\n\n        if (createdCache) {\n          cache.promise = runAnimationPostDigest(function(done) {\n            var cache = element.data(STORAGE_KEY);\n            element.removeData(STORAGE_KEY);\n\n            // in the event that the element is removed before postDigest\n            // is run then the cache will be undefined and there will be\n            // no need anymore to add or remove and of the element classes\n            if (cache) {\n              var classes = resolveElementClasses(element, cache.classes);\n              if (classes) {\n                self.$$setClassImmediately(element, classes[0], classes[1], cache.options);\n              }\n            }\n\n            done();\n          });\n          element.data(STORAGE_KEY, cache);\n        }\n\n        return cache.promise;\n      },\n\n      $$setClassImmediately: function(element, add, remove, options) {\n        add && this.$$addClassImmediately(element, add);\n        remove && this.$$removeClassImmediately(element, remove);\n        applyStyles(element, options);\n        return asyncPromise();\n      },\n\n      enabled: noop,\n      cancel: noop\n    };\n  }];\n}];\n\nfunction $$AsyncCallbackProvider() {\n  this.$get = ['$$rAF', '$timeout', function($$rAF, $timeout) {\n    return $$rAF.supported\n      ? function(fn) { return $$rAF(fn); }\n      : function(fn) {\n        return $timeout(fn, 0, false);\n      };\n  }];\n}\n\n/* global stripHash: true */\n\n/**\n * ! This is a private undocumented service !\n *\n * @name $browser\n * @requires $log\n * @description\n * This object has two goals:\n *\n * - hide all the global state in the browser caused by the window object\n * - abstract away all the browser specific features and inconsistencies\n *\n * For tests we provide {@link ngMock.$browser mock implementation} of the `$browser`\n * service, which can be used for convenient testing of the application without the interaction with\n * the real browser apis.\n */\n/**\n * @param {object} window The global window object.\n * @param {object} document jQuery wrapped document.\n * @param {object} $log window.console or an object with the same interface.\n * @param {object} $sniffer $sniffer service\n */\nfunction Browser(window, document, $log, $sniffer) {\n  var self = this,\n      rawDocument = document[0],\n      location = window.location,\n      history = window.history,\n      setTimeout = window.setTimeout,\n      clearTimeout = window.clearTimeout,\n      pendingDeferIds = {};\n\n  self.isMock = false;\n\n  var outstandingRequestCount = 0;\n  var outstandingRequestCallbacks = [];\n\n  // TODO(vojta): remove this temporary api\n  self.$$completeOutstandingRequest = completeOutstandingRequest;\n  self.$$incOutstandingRequestCount = function() { outstandingRequestCount++; };\n\n  /**\n   * Executes the `fn` function(supports currying) and decrements the `outstandingRequestCallbacks`\n   * counter. If the counter reaches 0, all the `outstandingRequestCallbacks` are executed.\n   */\n  function completeOutstandingRequest(fn) {\n    try {\n      fn.apply(null, sliceArgs(arguments, 1));\n    } finally {\n      outstandingRequestCount--;\n      if (outstandingRequestCount === 0) {\n        while (outstandingRequestCallbacks.length) {\n          try {\n            outstandingRequestCallbacks.pop()();\n          } catch (e) {\n            $log.error(e);\n          }\n        }\n      }\n    }\n  }\n\n  function getHash(url) {\n    var index = url.indexOf('#');\n    return index === -1 ? '' : url.substr(index + 1);\n  }\n\n  /**\n   * @private\n   * Note: this method is used only by scenario runner\n   * TODO(vojta): prefix this method with $$ ?\n   * @param {function()} callback Function that will be called when no outstanding request\n   */\n  self.notifyWhenNoOutstandingRequests = function(callback) {\n    // force browser to execute all pollFns - this is needed so that cookies and other pollers fire\n    // at some deterministic time in respect to the test runner's actions. Leaving things up to the\n    // regular poller would result in flaky tests.\n    forEach(pollFns, function(pollFn) { pollFn(); });\n\n    if (outstandingRequestCount === 0) {\n      callback();\n    } else {\n      outstandingRequestCallbacks.push(callback);\n    }\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Poll Watcher API\n  //////////////////////////////////////////////////////////////\n  var pollFns = [],\n      pollTimeout;\n\n  /**\n   * @name $browser#addPollFn\n   *\n   * @param {function()} fn Poll function to add\n   *\n   * @description\n   * Adds a function to the list of functions that poller periodically executes,\n   * and starts polling if not started yet.\n   *\n   * @returns {function()} the added function\n   */\n  self.addPollFn = function(fn) {\n    if (isUndefined(pollTimeout)) startPoller(100, setTimeout);\n    pollFns.push(fn);\n    return fn;\n  };\n\n  /**\n   * @param {number} interval How often should browser call poll functions (ms)\n   * @param {function()} setTimeout Reference to a real or fake `setTimeout` function.\n   *\n   * @description\n   * Configures the poller to run in the specified intervals, using the specified\n   * setTimeout fn and kicks it off.\n   */\n  function startPoller(interval, setTimeout) {\n    (function check() {\n      forEach(pollFns, function(pollFn) { pollFn(); });\n      pollTimeout = setTimeout(check, interval);\n    })();\n  }\n\n  //////////////////////////////////////////////////////////////\n  // URL API\n  //////////////////////////////////////////////////////////////\n\n  var cachedState, lastHistoryState,\n      lastBrowserUrl = location.href,\n      baseElement = document.find('base'),\n      reloadLocation = null;\n\n  cacheState();\n  lastHistoryState = cachedState;\n\n  /**\n   * @name $browser#url\n   *\n   * @description\n   * GETTER:\n   * Without any argument, this method just returns current value of location.href.\n   *\n   * SETTER:\n   * With at least one argument, this method sets url to new value.\n   * If html5 history api supported, pushState/replaceState is used, otherwise\n   * location.href/location.replace is used.\n   * Returns its own instance to allow chaining\n   *\n   * NOTE: this api is intended for use only by the $location service. Please use the\n   * {@link ng.$location $location service} to change url.\n   *\n   * @param {string} url New url (when used as setter)\n   * @param {boolean=} replace Should new url replace current history record?\n   * @param {object=} state object to use with pushState/replaceState\n   */\n  self.url = function(url, replace, state) {\n    // In modern browsers `history.state` is `null` by default; treating it separately\n    // from `undefined` would cause `$browser.url('/foo')` to change `history.state`\n    // to undefined via `pushState`. Instead, let's change `undefined` to `null` here.\n    if (isUndefined(state)) {\n      state = null;\n    }\n\n    // Android Browser BFCache causes location, history reference to become stale.\n    if (location !== window.location) location = window.location;\n    if (history !== window.history) history = window.history;\n\n    // setter\n    if (url) {\n      var sameState = lastHistoryState === state;\n\n      // Don't change anything if previous and current URLs and states match. This also prevents\n      // IE<10 from getting into redirect loop when in LocationHashbangInHtml5Url mode.\n      // See https://github.com/angular/angular.js/commit/ffb2701\n      if (lastBrowserUrl === url && (!$sniffer.history || sameState)) {\n        return self;\n      }\n      var sameBase = lastBrowserUrl && stripHash(lastBrowserUrl) === stripHash(url);\n      lastBrowserUrl = url;\n      lastHistoryState = state;\n      // Don't use history API if only the hash changed\n      // due to a bug in IE10/IE11 which leads\n      // to not firing a `hashchange` nor `popstate` event\n      // in some cases (see #9143).\n      if ($sniffer.history && (!sameBase || !sameState)) {\n        history[replace ? 'replaceState' : 'pushState'](state, '', url);\n        cacheState();\n        // Do the assignment again so that those two variables are referentially identical.\n        lastHistoryState = cachedState;\n      } else {\n        if (!sameBase) {\n          reloadLocation = url;\n        }\n        if (replace) {\n          location.replace(url);\n        } else if (!sameBase) {\n          location.href = url;\n        } else {\n          location.hash = getHash(url);\n        }\n      }\n      return self;\n    // getter\n    } else {\n      // - reloadLocation is needed as browsers don't allow to read out\n      //   the new location.href if a reload happened.\n      // - the replacement is a workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=407172\n      return reloadLocation || location.href.replace(/%27/g,\"'\");\n    }\n  };\n\n  /**\n   * @name $browser#state\n   *\n   * @description\n   * This method is a getter.\n   *\n   * Return history.state or null if history.state is undefined.\n   *\n   * @returns {object} state\n   */\n  self.state = function() {\n    return cachedState;\n  };\n\n  var urlChangeListeners = [],\n      urlChangeInit = false;\n\n  function cacheStateAndFireUrlChange() {\n    cacheState();\n    fireUrlChange();\n  }\n\n  // This variable should be used *only* inside the cacheState function.\n  var lastCachedState = null;\n  function cacheState() {\n    // This should be the only place in $browser where `history.state` is read.\n    cachedState = window.history.state;\n    cachedState = isUndefined(cachedState) ? null : cachedState;\n\n    // Prevent callbacks fo fire twice if both hashchange & popstate were fired.\n    if (equals(cachedState, lastCachedState)) {\n      cachedState = lastCachedState;\n    }\n    lastCachedState = cachedState;\n  }\n\n  function fireUrlChange() {\n    if (lastBrowserUrl === self.url() && lastHistoryState === cachedState) {\n      return;\n    }\n\n    lastBrowserUrl = self.url();\n    lastHistoryState = cachedState;\n    forEach(urlChangeListeners, function(listener) {\n      listener(self.url(), cachedState);\n    });\n  }\n\n  /**\n   * @name $browser#onUrlChange\n   *\n   * @description\n   * Register callback function that will be called, when url changes.\n   *\n   * It's only called when the url is changed from outside of angular:\n   * - user types different url into address bar\n   * - user clicks on history (forward/back) button\n   * - user clicks on a link\n   *\n   * It's not called when url is changed by $browser.url() method\n   *\n   * The listener gets called with new url as parameter.\n   *\n   * NOTE: this api is intended for use only by the $location service. Please use the\n   * {@link ng.$location $location service} to monitor url changes in angular apps.\n   *\n   * @param {function(string)} listener Listener function to be called when url changes.\n   * @return {function(string)} Returns the registered listener fn - handy if the fn is anonymous.\n   */\n  self.onUrlChange = function(callback) {\n    // TODO(vojta): refactor to use node's syntax for events\n    if (!urlChangeInit) {\n      // We listen on both (hashchange/popstate) when available, as some browsers (e.g. Opera)\n      // don't fire popstate when user change the address bar and don't fire hashchange when url\n      // changed by push/replaceState\n\n      // html5 history api - popstate event\n      if ($sniffer.history) jqLite(window).on('popstate', cacheStateAndFireUrlChange);\n      // hashchange event\n      jqLite(window).on('hashchange', cacheStateAndFireUrlChange);\n\n      urlChangeInit = true;\n    }\n\n    urlChangeListeners.push(callback);\n    return callback;\n  };\n\n  /**\n   * Checks whether the url has changed outside of Angular.\n   * Needs to be exported to be able to check for changes that have been done in sync,\n   * as hashchange/popstate events fire in async.\n   */\n  self.$$checkUrlChange = fireUrlChange;\n\n  //////////////////////////////////////////////////////////////\n  // Misc API\n  //////////////////////////////////////////////////////////////\n\n  /**\n   * @name $browser#baseHref\n   *\n   * @description\n   * Returns current <base href>\n   * (always relative - without domain)\n   *\n   * @returns {string} The current base href\n   */\n  self.baseHref = function() {\n    var href = baseElement.attr('href');\n    return href ? href.replace(/^(https?\\:)?\\/\\/[^\\/]*/, '') : '';\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Cookies API\n  //////////////////////////////////////////////////////////////\n  var lastCookies = {};\n  var lastCookieString = '';\n  var cookiePath = self.baseHref();\n\n  function safeDecodeURIComponent(str) {\n    try {\n      return decodeURIComponent(str);\n    } catch (e) {\n      return str;\n    }\n  }\n\n  /**\n   * @name $browser#cookies\n   *\n   * @param {string=} name Cookie name\n   * @param {string=} value Cookie value\n   *\n   * @description\n   * The cookies method provides a 'private' low level access to browser cookies.\n   * It is not meant to be used directly, use the $cookie service instead.\n   *\n   * The return values vary depending on the arguments that the method was called with as follows:\n   *\n   * - cookies() -> hash of all cookies, this is NOT a copy of the internal state, so do not modify\n   *   it\n   * - cookies(name, value) -> set name to value, if value is undefined delete the cookie\n   * - cookies(name) -> the same as (name, undefined) == DELETES (no one calls it right now that\n   *   way)\n   *\n   * @returns {Object} Hash of all cookies (if called without any parameter)\n   */\n  self.cookies = function(name, value) {\n    var cookieLength, cookieArray, cookie, i, index;\n\n    if (name) {\n      if (value === undefined) {\n        rawDocument.cookie = encodeURIComponent(name) + \"=;path=\" + cookiePath +\n                                \";expires=Thu, 01 Jan 1970 00:00:00 GMT\";\n      } else {\n        if (isString(value)) {\n          cookieLength = (rawDocument.cookie = encodeURIComponent(name) + '=' + encodeURIComponent(value) +\n                                ';path=' + cookiePath).length + 1;\n\n          // per http://www.ietf.org/rfc/rfc2109.txt browser must allow at minimum:\n          // - 300 cookies\n          // - 20 cookies per unique domain\n          // - 4096 bytes per cookie\n          if (cookieLength > 4096) {\n            $log.warn(\"Cookie '\" + name +\n              \"' possibly not set or overflowed because it was too large (\" +\n              cookieLength + \" > 4096 bytes)!\");\n          }\n        }\n      }\n    } else {\n      if (rawDocument.cookie !== lastCookieString) {\n        lastCookieString = rawDocument.cookie;\n        cookieArray = lastCookieString.split(\"; \");\n        lastCookies = {};\n\n        for (i = 0; i < cookieArray.length; i++) {\n          cookie = cookieArray[i];\n          index = cookie.indexOf('=');\n          if (index > 0) { //ignore nameless cookies\n            name = safeDecodeURIComponent(cookie.substring(0, index));\n            // the first value that is seen for a cookie is the most\n            // specific one.  values for the same cookie name that\n            // follow are for less specific paths.\n            if (lastCookies[name] === undefined) {\n              lastCookies[name] = safeDecodeURIComponent(cookie.substring(index + 1));\n            }\n          }\n        }\n      }\n      return lastCookies;\n    }\n  };\n\n\n  /**\n   * @name $browser#defer\n   * @param {function()} fn A function, who's execution should be deferred.\n   * @param {number=} [delay=0] of milliseconds to defer the function execution.\n   * @returns {*} DeferId that can be used to cancel the task via `$browser.defer.cancel()`.\n   *\n   * @description\n   * Executes a fn asynchronously via `setTimeout(fn, delay)`.\n   *\n   * Unlike when calling `setTimeout` directly, in test this function is mocked and instead of using\n   * `setTimeout` in tests, the fns are queued in an array, which can be programmatically flushed\n   * via `$browser.defer.flush()`.\n   *\n   */\n  self.defer = function(fn, delay) {\n    var timeoutId;\n    outstandingRequestCount++;\n    timeoutId = setTimeout(function() {\n      delete pendingDeferIds[timeoutId];\n      completeOutstandingRequest(fn);\n    }, delay || 0);\n    pendingDeferIds[timeoutId] = true;\n    return timeoutId;\n  };\n\n\n  /**\n   * @name $browser#defer.cancel\n   *\n   * @description\n   * Cancels a deferred task identified with `deferId`.\n   *\n   * @param {*} deferId Token returned by the `$browser.defer` function.\n   * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfully\n   *                    canceled.\n   */\n  self.defer.cancel = function(deferId) {\n    if (pendingDeferIds[deferId]) {\n      delete pendingDeferIds[deferId];\n      clearTimeout(deferId);\n      completeOutstandingRequest(noop);\n      return true;\n    }\n    return false;\n  };\n\n}\n\nfunction $BrowserProvider() {\n  this.$get = ['$window', '$log', '$sniffer', '$document',\n      function($window, $log, $sniffer, $document) {\n        return new Browser($window, $document, $log, $sniffer);\n      }];\n}\n\n/**\n * @ngdoc service\n * @name $cacheFactory\n *\n * @description\n * Factory that constructs {@link $cacheFactory.Cache Cache} objects and gives access to\n * them.\n *\n * ```js\n *\n *  var cache = $cacheFactory('cacheId');\n *  expect($cacheFactory.get('cacheId')).toBe(cache);\n *  expect($cacheFactory.get('noSuchCacheId')).not.toBeDefined();\n *\n *  cache.put(\"key\", \"value\");\n *  cache.put(\"another key\", \"another value\");\n *\n *  // We've specified no options on creation\n *  expect(cache.info()).toEqual({id: 'cacheId', size: 2});\n *\n * ```\n *\n *\n * @param {string} cacheId Name or id of the newly created cache.\n * @param {object=} options Options object that specifies the cache behavior. Properties:\n *\n *   - `{number=}` `capacity` — turns the cache into LRU cache.\n *\n * @returns {object} Newly created cache object with the following set of methods:\n *\n * - `{object}` `info()` — Returns id, size, and options of cache.\n * - `{{*}}` `put({string} key, {*} value)` — Puts a new key-value pair into the cache and returns\n *   it.\n * - `{{*}}` `get({string} key)` — Returns cached value for `key` or undefined for cache miss.\n * - `{void}` `remove({string} key)` — Removes a key-value pair from the cache.\n * - `{void}` `removeAll()` — Removes all cached values.\n * - `{void}` `destroy()` — Removes references to this cache from $cacheFactory.\n *\n * @example\n   <example module=\"cacheExampleApp\">\n     <file name=\"index.html\">\n       <div ng-controller=\"CacheController\">\n         <input ng-model=\"newCacheKey\" placeholder=\"Key\">\n         <input ng-model=\"newCacheValue\" placeholder=\"Value\">\n         <button ng-click=\"put(newCacheKey, newCacheValue)\">Cache</button>\n\n         <p ng-if=\"keys.length\">Cached Values</p>\n         <div ng-repeat=\"key in keys\">\n           <span ng-bind=\"key\"></span>\n           <span>: </span>\n           <b ng-bind=\"cache.get(key)\"></b>\n         </div>\n\n         <p>Cache Info</p>\n         <div ng-repeat=\"(key, value) in cache.info()\">\n           <span ng-bind=\"key\"></span>\n           <span>: </span>\n           <b ng-bind=\"value\"></b>\n         </div>\n       </div>\n     </file>\n     <file name=\"script.js\">\n       angular.module('cacheExampleApp', []).\n         controller('CacheController', ['$scope', '$cacheFactory', function($scope, $cacheFactory) {\n           $scope.keys = [];\n           $scope.cache = $cacheFactory('cacheId');\n           $scope.put = function(key, value) {\n             if ($scope.cache.get(key) === undefined) {\n               $scope.keys.push(key);\n             }\n             $scope.cache.put(key, value === undefined ? null : value);\n           };\n         }]);\n     </file>\n     <file name=\"style.css\">\n       p {\n         margin: 10px 0 3px;\n       }\n     </file>\n   </example>\n */\nfunction $CacheFactoryProvider() {\n\n  this.$get = function() {\n    var caches = {};\n\n    function cacheFactory(cacheId, options) {\n      if (cacheId in caches) {\n        throw minErr('$cacheFactory')('iid', \"CacheId '{0}' is already taken!\", cacheId);\n      }\n\n      var size = 0,\n          stats = extend({}, options, {id: cacheId}),\n          data = {},\n          capacity = (options && options.capacity) || Number.MAX_VALUE,\n          lruHash = {},\n          freshEnd = null,\n          staleEnd = null;\n\n      /**\n       * @ngdoc type\n       * @name $cacheFactory.Cache\n       *\n       * @description\n       * A cache object used to store and retrieve data, primarily used by\n       * {@link $http $http} and the {@link ng.directive:script script} directive to cache\n       * templates and other data.\n       *\n       * ```js\n       *  angular.module('superCache')\n       *    .factory('superCache', ['$cacheFactory', function($cacheFactory) {\n       *      return $cacheFactory('super-cache');\n       *    }]);\n       * ```\n       *\n       * Example test:\n       *\n       * ```js\n       *  it('should behave like a cache', inject(function(superCache) {\n       *    superCache.put('key', 'value');\n       *    superCache.put('another key', 'another value');\n       *\n       *    expect(superCache.info()).toEqual({\n       *      id: 'super-cache',\n       *      size: 2\n       *    });\n       *\n       *    superCache.remove('another key');\n       *    expect(superCache.get('another key')).toBeUndefined();\n       *\n       *    superCache.removeAll();\n       *    expect(superCache.info()).toEqual({\n       *      id: 'super-cache',\n       *      size: 0\n       *    });\n       *  }));\n       * ```\n       */\n      return caches[cacheId] = {\n\n        /**\n         * @ngdoc method\n         * @name $cacheFactory.Cache#put\n         * @kind function\n         *\n         * @description\n         * Inserts a named entry into the {@link $cacheFactory.Cache Cache} object to be\n         * retrieved later, and incrementing the size of the cache if the key was not already\n         * present in the cache. If behaving like an LRU cache, it will also remove stale\n         * entries from the set.\n         *\n         * It will not insert undefined values into the cache.\n         *\n         * @param {string} key the key under which the cached data is stored.\n         * @param {*} value the value to store alongside the key. If it is undefined, the key\n         *    will not be stored.\n         * @returns {*} the value stored.\n         */\n        put: function(key, value) {\n          if (capacity < Number.MAX_VALUE) {\n            var lruEntry = lruHash[key] || (lruHash[key] = {key: key});\n\n            refresh(lruEntry);\n          }\n\n          if (isUndefined(value)) return;\n          if (!(key in data)) size++;\n          data[key] = value;\n\n          if (size > capacity) {\n            this.remove(staleEnd.key);\n          }\n\n          return value;\n        },\n\n        /**\n         * @ngdoc method\n         * @name $cacheFactory.Cache#get\n         * @kind function\n         *\n         * @description\n         * Retrieves named data stored in the {@link $cacheFactory.Cache Cache} object.\n         *\n         * @param {string} key the key of the data to be retrieved\n         * @returns {*} the value stored.\n         */\n        get: function(key) {\n          if (capacity < Number.MAX_VALUE) {\n            var lruEntry = lruHash[key];\n\n            if (!lruEntry) return;\n\n            refresh(lruEntry);\n          }\n\n          return data[key];\n        },\n\n\n        /**\n         * @ngdoc method\n         * @name $cacheFactory.Cache#remove\n         * @kind function\n         *\n         * @description\n         * Removes an entry from the {@link $cacheFactory.Cache Cache} object.\n         *\n         * @param {string} key the key of the entry to be removed\n         */\n        remove: function(key) {\n          if (capacity < Number.MAX_VALUE) {\n            var lruEntry = lruHash[key];\n\n            if (!lruEntry) return;\n\n            if (lruEntry == freshEnd) freshEnd = lruEntry.p;\n            if (lruEntry == staleEnd) staleEnd = lruEntry.n;\n            link(lruEntry.n,lruEntry.p);\n\n            delete lruHash[key];\n          }\n\n          delete data[key];\n          size--;\n        },\n\n\n        /**\n         * @ngdoc method\n         * @name $cacheFactory.Cache#removeAll\n         * @kind function\n         *\n         * @description\n         * Clears the cache object of any entries.\n         */\n        removeAll: function() {\n          data = {};\n          size = 0;\n          lruHash = {};\n          freshEnd = staleEnd = null;\n        },\n\n\n        /**\n         * @ngdoc method\n         * @name $cacheFactory.Cache#destroy\n         * @kind function\n         *\n         * @description\n         * Destroys the {@link $cacheFactory.Cache Cache} object entirely,\n         * removing it from the {@link $cacheFactory $cacheFactory} set.\n         */\n        destroy: function() {\n          data = null;\n          stats = null;\n          lruHash = null;\n          delete caches[cacheId];\n        },\n\n\n        /**\n         * @ngdoc method\n         * @name $cacheFactory.Cache#info\n         * @kind function\n         *\n         * @description\n         * Retrieve information regarding a particular {@link $cacheFactory.Cache Cache}.\n         *\n         * @returns {object} an object with the following properties:\n         *   <ul>\n         *     <li>**id**: the id of the cache instance</li>\n         *     <li>**size**: the number of entries kept in the cache instance</li>\n         *     <li>**...**: any additional properties from the options object when creating the\n         *       cache.</li>\n         *   </ul>\n         */\n        info: function() {\n          return extend({}, stats, {size: size});\n        }\n      };\n\n\n      /**\n       * makes the `entry` the freshEnd of the LRU linked list\n       */\n      function refresh(entry) {\n        if (entry != freshEnd) {\n          if (!staleEnd) {\n            staleEnd = entry;\n          } else if (staleEnd == entry) {\n            staleEnd = entry.n;\n          }\n\n          link(entry.n, entry.p);\n          link(entry, freshEnd);\n          freshEnd = entry;\n          freshEnd.n = null;\n        }\n      }\n\n\n      /**\n       * bidirectionally links two entries of the LRU linked list\n       */\n      function link(nextEntry, prevEntry) {\n        if (nextEntry != prevEntry) {\n          if (nextEntry) nextEntry.p = prevEntry; //p stands for previous, 'prev' didn't minify\n          if (prevEntry) prevEntry.n = nextEntry; //n stands for next, 'next' didn't minify\n        }\n      }\n    }\n\n\n  /**\n   * @ngdoc method\n   * @name $cacheFactory#info\n   *\n   * @description\n   * Get information about all the caches that have been created\n   *\n   * @returns {Object} - key-value map of `cacheId` to the result of calling `cache#info`\n   */\n    cacheFactory.info = function() {\n      var info = {};\n      forEach(caches, function(cache, cacheId) {\n        info[cacheId] = cache.info();\n      });\n      return info;\n    };\n\n\n  /**\n   * @ngdoc method\n   * @name $cacheFactory#get\n   *\n   * @description\n   * Get access to a cache object by the `cacheId` used when it was created.\n   *\n   * @param {string} cacheId Name or id of a cache to access.\n   * @returns {object} Cache object identified by the cacheId or undefined if no such cache.\n   */\n    cacheFactory.get = function(cacheId) {\n      return caches[cacheId];\n    };\n\n\n    return cacheFactory;\n  };\n}\n\n/**\n * @ngdoc service\n * @name $templateCache\n *\n * @description\n * The first time a template is used, it is loaded in the template cache for quick retrieval. You\n * can load templates directly into the cache in a `script` tag, or by consuming the\n * `$templateCache` service directly.\n *\n * Adding via the `script` tag:\n *\n * ```html\n *   <script type=\"text/ng-template\" id=\"templateId.html\">\n *     <p>This is the content of the template</p>\n *   </script>\n * ```\n *\n * **Note:** the `script` tag containing the template does not need to be included in the `head` of\n * the document, but it must be a descendent of the {@link ng.$rootElement $rootElement} (IE,\n * element with ng-app attribute), otherwise the template will be ignored.\n *\n * Adding via the $templateCache service:\n *\n * ```js\n * var myApp = angular.module('myApp', []);\n * myApp.run(function($templateCache) {\n *   $templateCache.put('templateId.html', 'This is the content of the template');\n * });\n * ```\n *\n * To retrieve the template later, simply use it in your HTML:\n * ```html\n * <div ng-include=\" 'templateId.html' \"></div>\n * ```\n *\n * or get it via Javascript:\n * ```js\n * $templateCache.get('templateId.html')\n * ```\n *\n * See {@link ng.$cacheFactory $cacheFactory}.\n *\n */\nfunction $TemplateCacheProvider() {\n  this.$get = ['$cacheFactory', function($cacheFactory) {\n    return $cacheFactory('templates');\n  }];\n}\n\n/* ! VARIABLE/FUNCTION NAMING CONVENTIONS THAT APPLY TO THIS FILE!\n *\n * DOM-related variables:\n *\n * - \"node\" - DOM Node\n * - \"element\" - DOM Element or Node\n * - \"$node\" or \"$element\" - jqLite-wrapped node or element\n *\n *\n * Compiler related stuff:\n *\n * - \"linkFn\" - linking fn of a single directive\n * - \"nodeLinkFn\" - function that aggregates all linking fns for a particular node\n * - \"childLinkFn\" -  function that aggregates all linking fns for child nodes of a particular node\n * - \"compositeLinkFn\" - function that aggregates all linking fns for a compilation root (nodeList)\n */\n\n\n/**\n * @ngdoc service\n * @name $compile\n * @kind function\n *\n * @description\n * Compiles an HTML string or DOM into a template and produces a template function, which\n * can then be used to link {@link ng.$rootScope.Scope `scope`} and the template together.\n *\n * The compilation is a process of walking the DOM tree and matching DOM elements to\n * {@link ng.$compileProvider#directive directives}.\n *\n * <div class=\"alert alert-warning\">\n * **Note:** This document is an in-depth reference of all directive options.\n * For a gentle introduction to directives with examples of common use cases,\n * see the {@link guide/directive directive guide}.\n * </div>\n *\n * ## Comprehensive Directive API\n *\n * There are many different options for a directive.\n *\n * The difference resides in the return value of the factory function.\n * You can either return a \"Directive Definition Object\" (see below) that defines the directive properties,\n * or just the `postLink` function (all other properties will have the default values).\n *\n * <div class=\"alert alert-success\">\n * **Best Practice:** It's recommended to use the \"directive definition object\" form.\n * </div>\n *\n * Here's an example directive declared with a Directive Definition Object:\n *\n * ```js\n *   var myModule = angular.module(...);\n *\n *   myModule.directive('directiveName', function factory(injectables) {\n *     var directiveDefinitionObject = {\n *       priority: 0,\n *       template: '<div></div>', // or // function(tElement, tAttrs) { ... },\n *       // or\n *       // templateUrl: 'directive.html', // or // function(tElement, tAttrs) { ... },\n *       transclude: false,\n *       restrict: 'A',\n *       templateNamespace: 'html',\n *       scope: false,\n *       controller: function($scope, $element, $attrs, $transclude, otherInjectables) { ... },\n *       controllerAs: 'stringAlias',\n *       require: 'siblingDirectiveName', // or // ['^parentDirectiveName', '?optionalDirectiveName', '?^optionalParent'],\n *       compile: function compile(tElement, tAttrs, transclude) {\n *         return {\n *           pre: function preLink(scope, iElement, iAttrs, controller) { ... },\n *           post: function postLink(scope, iElement, iAttrs, controller) { ... }\n *         }\n *         // or\n *         // return function postLink( ... ) { ... }\n *       },\n *       // or\n *       // link: {\n *       //  pre: function preLink(scope, iElement, iAttrs, controller) { ... },\n *       //  post: function postLink(scope, iElement, iAttrs, controller) { ... }\n *       // }\n *       // or\n *       // link: function postLink( ... ) { ... }\n *     };\n *     return directiveDefinitionObject;\n *   });\n * ```\n *\n * <div class=\"alert alert-warning\">\n * **Note:** Any unspecified options will use the default value. You can see the default values below.\n * </div>\n *\n * Therefore the above can be simplified as:\n *\n * ```js\n *   var myModule = angular.module(...);\n *\n *   myModule.directive('directiveName', function factory(injectables) {\n *     var directiveDefinitionObject = {\n *       link: function postLink(scope, iElement, iAttrs) { ... }\n *     };\n *     return directiveDefinitionObject;\n *     // or\n *     // return function postLink(scope, iElement, iAttrs) { ... }\n *   });\n * ```\n *\n *\n *\n * ### Directive Definition Object\n *\n * The directive definition object provides instructions to the {@link ng.$compile\n * compiler}. The attributes are:\n *\n * #### `multiElement`\n * When this property is set to true, the HTML compiler will collect DOM nodes between\n * nodes with the attributes `directive-name-start` and `directive-name-end`, and group them\n * together as the directive elements. It is recommended that this feature be used on directives\n * which are not strictly behavioural (such as {@link ngClick}), and which\n * do not manipulate or replace child nodes (such as {@link ngInclude}).\n *\n * #### `priority`\n * When there are multiple directives defined on a single DOM element, sometimes it\n * is necessary to specify the order in which the directives are applied. The `priority` is used\n * to sort the directives before their `compile` functions get called. Priority is defined as a\n * number. Directives with greater numerical `priority` are compiled first. Pre-link functions\n * are also run in priority order, but post-link functions are run in reverse order. The order\n * of directives with the same priority is undefined. The default priority is `0`.\n *\n * #### `terminal`\n * If set to true then the current `priority` will be the last set of directives\n * which will execute (any directives at the current priority will still execute\n * as the order of execution on same `priority` is undefined). Note that expressions\n * and other directives used in the directive's template will also be excluded from execution.\n *\n * #### `scope`\n * **If set to `true`,** then a new scope will be created for this directive. If multiple directives on the\n * same element request a new scope, only one new scope is created. The new scope rule does not\n * apply for the root of the template since the root of the template always gets a new scope.\n *\n * **If set to `{}` (object hash),** then a new \"isolate\" scope is created. The 'isolate' scope differs from\n * normal scope in that it does not prototypically inherit from the parent scope. This is useful\n * when creating reusable components, which should not accidentally read or modify data in the\n * parent scope.\n *\n * The 'isolate' scope takes an object hash which defines a set of local scope properties\n * derived from the parent scope. These local properties are useful for aliasing values for\n * templates. Locals definition is a hash of local scope property to its source:\n *\n * * `@` or `@attr` - bind a local scope property to the value of DOM attribute. The result is\n *   always a string since DOM attributes are strings. If no `attr` name is specified  then the\n *   attribute name is assumed to be the same as the local name.\n *   Given `<widget my-attr=\"hello {{name}}\">` and widget definition\n *   of `scope: { localName:'@myAttr' }`, then widget scope property `localName` will reflect\n *   the interpolated value of `hello {{name}}`. As the `name` attribute changes so will the\n *   `localName` property on the widget scope. The `name` is read from the parent scope (not\n *   component scope).\n *\n * * `=` or `=attr` - set up bi-directional binding between a local scope property and the\n *   parent scope property of name defined via the value of the `attr` attribute. If no `attr`\n *   name is specified then the attribute name is assumed to be the same as the local name.\n *   Given `<widget my-attr=\"parentModel\">` and widget definition of\n *   `scope: { localModel:'=myAttr' }`, then widget scope property `localModel` will reflect the\n *   value of `parentModel` on the parent scope. Any changes to `parentModel` will be reflected\n *   in `localModel` and any changes in `localModel` will reflect in `parentModel`. If the parent\n *   scope property doesn't exist, it will throw a NON_ASSIGNABLE_MODEL_EXPRESSION exception. You\n *   can avoid this behavior using `=?` or `=?attr` in order to flag the property as optional. If\n *   you want to shallow watch for changes (i.e. $watchCollection instead of $watch) you can use\n *   `=*` or `=*attr` (`=*?` or `=*?attr` if the property is optional).\n *\n * * `&` or `&attr` - provides a way to execute an expression in the context of the parent scope.\n *   If no `attr` name is specified then the attribute name is assumed to be the same as the\n *   local name. Given `<widget my-attr=\"count = count + value\">` and widget definition of\n *   `scope: { localFn:'&myAttr' }`, then isolate scope property `localFn` will point to\n *   a function wrapper for the `count = count + value` expression. Often it's desirable to\n *   pass data from the isolated scope via an expression to the parent scope, this can be\n *   done by passing a map of local variable names and values into the expression wrapper fn.\n *   For example, if the expression is `increment(amount)` then we can specify the amount value\n *   by calling the `localFn` as `localFn({amount: 22})`.\n *\n *\n * #### `bindToController`\n * When an isolate scope is used for a component (see above), and `controllerAs` is used, `bindToController: true` will\n * allow a component to have its properties bound to the controller, rather than to scope. When the controller\n * is instantiated, the initial values of the isolate scope bindings are already available.\n *\n * #### `controller`\n * Controller constructor function. The controller is instantiated before the\n * pre-linking phase and it is shared with other directives (see\n * `require` attribute). This allows the directives to communicate with each other and augment\n * each other's behavior. The controller is injectable (and supports bracket notation) with the following locals:\n *\n * * `$scope` - Current scope associated with the element\n * * `$element` - Current element\n * * `$attrs` - Current attributes object for the element\n * * `$transclude` - A transclude linking function pre-bound to the correct transclusion scope:\n *   `function([scope], cloneLinkingFn, futureParentElement)`.\n *    * `scope`: optional argument to override the scope.\n *    * `cloneLinkingFn`: optional argument to create clones of the original transcluded content.\n *    * `futureParentElement`:\n *        * defines the parent to which the `cloneLinkingFn` will add the cloned elements.\n *        * default: `$element.parent()` resp. `$element` for `transclude:'element'` resp. `transclude:true`.\n *        * only needed for transcludes that are allowed to contain non html elements (e.g. SVG elements)\n *          and when the `cloneLinkinFn` is passed,\n *          as those elements need to created and cloned in a special way when they are defined outside their\n *          usual containers (e.g. like `<svg>`).\n *        * See also the `directive.templateNamespace` property.\n *\n *\n * #### `require`\n * Require another directive and inject its controller as the fourth argument to the linking function. The\n * `require` takes a string name (or array of strings) of the directive(s) to pass in. If an array is used, the\n * injected argument will be an array in corresponding order. If no such directive can be\n * found, or if the directive does not have a controller, then an error is raised. The name can be prefixed with:\n *\n * * (no prefix) - Locate the required controller on the current element. Throw an error if not found.\n * * `?` - Attempt to locate the required controller or pass `null` to the `link` fn if not found.\n * * `^` - Locate the required controller by searching the element and its parents. Throw an error if not found.\n * * `^^` - Locate the required controller by searching the element's parents. Throw an error if not found.\n * * `?^` - Attempt to locate the required controller by searching the element and its parents or pass\n *   `null` to the `link` fn if not found.\n * * `?^^` - Attempt to locate the required controller by searching the element's parents, or pass\n *   `null` to the `link` fn if not found.\n *\n *\n * #### `controllerAs`\n * Controller alias at the directive scope. An alias for the controller so it\n * can be referenced at the directive template. The directive needs to define a scope for this\n * configuration to be used. Useful in the case when directive is used as component.\n *\n *\n * #### `restrict`\n * String of subset of `EACM` which restricts the directive to a specific directive\n * declaration style. If omitted, the defaults (elements and attributes) are used.\n *\n * * `E` - Element name (default): `<my-directive></my-directive>`\n * * `A` - Attribute (default): `<div my-directive=\"exp\"></div>`\n * * `C` - Class: `<div class=\"my-directive: exp;\"></div>`\n * * `M` - Comment: `<!-- directive: my-directive exp -->`\n *\n *\n * #### `templateNamespace`\n * String representing the document type used by the markup in the template.\n * AngularJS needs this information as those elements need to be created and cloned\n * in a special way when they are defined outside their usual containers like `<svg>` and `<math>`.\n *\n * * `html` - All root nodes in the template are HTML. Root nodes may also be\n *   top-level elements such as `<svg>` or `<math>`.\n * * `svg` - The root nodes in the template are SVG elements (excluding `<math>`).\n * * `math` - The root nodes in the template are MathML elements (excluding `<svg>`).\n *\n * If no `templateNamespace` is specified, then the namespace is considered to be `html`.\n *\n * #### `template`\n * HTML markup that may:\n * * Replace the contents of the directive's element (default).\n * * Replace the directive's element itself (if `replace` is true - DEPRECATED).\n * * Wrap the contents of the directive's element (if `transclude` is true).\n *\n * Value may be:\n *\n * * A string. For example `<div red-on-hover>{{delete_str}}</div>`.\n * * A function which takes two arguments `tElement` and `tAttrs` (described in the `compile`\n *   function api below) and returns a string value.\n *\n *\n * #### `templateUrl`\n * This is similar to `template` but the template is loaded from the specified URL, asynchronously.\n *\n * Because template loading is asynchronous the compiler will suspend compilation of directives on that element\n * for later when the template has been resolved.  In the meantime it will continue to compile and link\n * sibling and parent elements as though this element had not contained any directives.\n *\n * The compiler does not suspend the entire compilation to wait for templates to be loaded because this\n * would result in the whole app \"stalling\" until all templates are loaded asynchronously - even in the\n * case when only one deeply nested directive has `templateUrl`.\n *\n * Template loading is asynchronous even if the template has been preloaded into the {@link $templateCache}\n *\n * You can specify `templateUrl` as a string representing the URL or as a function which takes two\n * arguments `tElement` and `tAttrs` (described in the `compile` function api below) and returns\n * a string value representing the url.  In either case, the template URL is passed through {@link\n * $sce#getTrustedResourceUrl $sce.getTrustedResourceUrl}.\n *\n *\n * #### `replace` ([*DEPRECATED*!], will be removed in next major release - i.e. v2.0)\n * specify what the template should replace. Defaults to `false`.\n *\n * * `true` - the template will replace the directive's element.\n * * `false` - the template will replace the contents of the directive's element.\n *\n * The replacement process migrates all of the attributes / classes from the old element to the new\n * one. See the {@link guide/directive#template-expanding-directive\n * Directives Guide} for an example.\n *\n * There are very few scenarios where element replacement is required for the application function,\n * the main one being reusable custom components that are used within SVG contexts\n * (because SVG doesn't work with custom elements in the DOM tree).\n *\n * #### `transclude`\n * Extract the contents of the element where the directive appears and make it available to the directive.\n * The contents are compiled and provided to the directive as a **transclusion function**. See the\n * {@link $compile#transclusion Transclusion} section below.\n *\n * There are two kinds of transclusion depending upon whether you want to transclude just the contents of the\n * directive's element or the entire element:\n *\n * * `true` - transclude the content (i.e. the child nodes) of the directive's element.\n * * `'element'` - transclude the whole of the directive's element including any directives on this\n *   element that defined at a lower priority than this directive. When used, the `template`\n *   property is ignored.\n *\n *\n * #### `compile`\n *\n * ```js\n *   function compile(tElement, tAttrs, transclude) { ... }\n * ```\n *\n * The compile function deals with transforming the template DOM. Since most directives do not do\n * template transformation, it is not used often. The compile function takes the following arguments:\n *\n *   * `tElement` - template element - The element where the directive has been declared. It is\n *     safe to do template transformation on the element and child elements only.\n *\n *   * `tAttrs` - template attributes - Normalized list of attributes declared on this element shared\n *     between all directive compile functions.\n *\n *   * `transclude` -  [*DEPRECATED*!] A transclude linking function: `function(scope, cloneLinkingFn)`\n *\n * <div class=\"alert alert-warning\">\n * **Note:** The template instance and the link instance may be different objects if the template has\n * been cloned. For this reason it is **not** safe to do anything other than DOM transformations that\n * apply to all cloned DOM nodes within the compile function. Specifically, DOM listener registration\n * should be done in a linking function rather than in a compile function.\n * </div>\n\n * <div class=\"alert alert-warning\">\n * **Note:** The compile function cannot handle directives that recursively use themselves in their\n * own templates or compile functions. Compiling these directives results in an infinite loop and a\n * stack overflow errors.\n *\n * This can be avoided by manually using $compile in the postLink function to imperatively compile\n * a directive's template instead of relying on automatic template compilation via `template` or\n * `templateUrl` declaration or manual compilation inside the compile function.\n * </div>\n *\n * <div class=\"alert alert-error\">\n * **Note:** The `transclude` function that is passed to the compile function is deprecated, as it\n *   e.g. does not know about the right outer scope. Please use the transclude function that is passed\n *   to the link function instead.\n * </div>\n\n * A compile function can have a return value which can be either a function or an object.\n *\n * * returning a (post-link) function - is equivalent to registering the linking function via the\n *   `link` property of the config object when the compile function is empty.\n *\n * * returning an object with function(s) registered via `pre` and `post` properties - allows you to\n *   control when a linking function should be called during the linking phase. See info about\n *   pre-linking and post-linking functions below.\n *\n *\n * #### `link`\n * This property is used only if the `compile` property is not defined.\n *\n * ```js\n *   function link(scope, iElement, iAttrs, controller, transcludeFn) { ... }\n * ```\n *\n * The link function is responsible for registering DOM listeners as well as updating the DOM. It is\n * executed after the template has been cloned. This is where most of the directive logic will be\n * put.\n *\n *   * `scope` - {@link ng.$rootScope.Scope Scope} - The scope to be used by the\n *     directive for registering {@link ng.$rootScope.Scope#$watch watches}.\n *\n *   * `iElement` - instance element - The element where the directive is to be used. It is safe to\n *     manipulate the children of the element only in `postLink` function since the children have\n *     already been linked.\n *\n *   * `iAttrs` - instance attributes - Normalized list of attributes declared on this element shared\n *     between all directive linking functions.\n *\n *   * `controller` - a controller instance - A controller instance if at least one directive on the\n *     element defines a controller. The controller is shared among all the directives, which allows\n *     the directives to use the controllers as a communication channel.\n *\n *   * `transcludeFn` - A transclude linking function pre-bound to the correct transclusion scope.\n *     This is the same as the `$transclude`\n *     parameter of directive controllers, see there for details.\n *     `function([scope], cloneLinkingFn, futureParentElement)`.\n *\n * #### Pre-linking function\n *\n * Executed before the child elements are linked. Not safe to do DOM transformation since the\n * compiler linking function will fail to locate the correct elements for linking.\n *\n * #### Post-linking function\n *\n * Executed after the child elements are linked.\n *\n * Note that child elements that contain `templateUrl` directives will not have been compiled\n * and linked since they are waiting for their template to load asynchronously and their own\n * compilation and linking has been suspended until that occurs.\n *\n * It is safe to do DOM transformation in the post-linking function on elements that are not waiting\n * for their async templates to be resolved.\n *\n *\n * ### Transclusion\n *\n * Transclusion is the process of extracting a collection of DOM element from one part of the DOM and\n * copying them to another part of the DOM, while maintaining their connection to the original AngularJS\n * scope from where they were taken.\n *\n * Transclusion is used (often with {@link ngTransclude}) to insert the\n * original contents of a directive's element into a specified place in the template of the directive.\n * The benefit of transclusion, over simply moving the DOM elements manually, is that the transcluded\n * content has access to the properties on the scope from which it was taken, even if the directive\n * has isolated scope.\n * See the {@link guide/directive#creating-a-directive-that-wraps-other-elements Directives Guide}.\n *\n * This makes it possible for the widget to have private state for its template, while the transcluded\n * content has access to its originating scope.\n *\n * <div class=\"alert alert-warning\">\n * **Note:** When testing an element transclude directive you must not place the directive at the root of the\n * DOM fragment that is being compiled. See {@link guide/unit-testing#testing-transclusion-directives\n * Testing Transclusion Directives}.\n * </div>\n *\n * #### Transclusion Functions\n *\n * When a directive requests transclusion, the compiler extracts its contents and provides a **transclusion\n * function** to the directive's `link` function and `controller`. This transclusion function is a special\n * **linking function** that will return the compiled contents linked to a new transclusion scope.\n *\n * <div class=\"alert alert-info\">\n * If you are just using {@link ngTransclude} then you don't need to worry about this function, since\n * ngTransclude will deal with it for us.\n * </div>\n *\n * If you want to manually control the insertion and removal of the transcluded content in your directive\n * then you must use this transclude function. When you call a transclude function it returns a a jqLite/JQuery\n * object that contains the compiled DOM, which is linked to the correct transclusion scope.\n *\n * When you call a transclusion function you can pass in a **clone attach function**. This function accepts\n * two parameters, `function(clone, scope) { ... }`, where the `clone` is a fresh compiled copy of your transcluded\n * content and the `scope` is the newly created transclusion scope, to which the clone is bound.\n *\n * <div class=\"alert alert-info\">\n * **Best Practice**: Always provide a `cloneFn` (clone attach function) when you call a translude function\n * since you then get a fresh clone of the original DOM and also have access to the new transclusion scope.\n * </div>\n *\n * It is normal practice to attach your transcluded content (`clone`) to the DOM inside your **clone\n * attach function**:\n *\n * ```js\n * var transcludedContent, transclusionScope;\n *\n * $transclude(function(clone, scope) {\n *   element.append(clone);\n *   transcludedContent = clone;\n *   transclusionScope = scope;\n * });\n * ```\n *\n * Later, if you want to remove the transcluded content from your DOM then you should also destroy the\n * associated transclusion scope:\n *\n * ```js\n * transcludedContent.remove();\n * transclusionScope.$destroy();\n * ```\n *\n * <div class=\"alert alert-info\">\n * **Best Practice**: if you intend to add and remove transcluded content manually in your directive\n * (by calling the transclude function to get the DOM and and calling `element.remove()` to remove it),\n * then you are also responsible for calling `$destroy` on the transclusion scope.\n * </div>\n *\n * The built-in DOM manipulation directives, such as {@link ngIf}, {@link ngSwitch} and {@link ngRepeat}\n * automatically destroy their transluded clones as necessary so you do not need to worry about this if\n * you are simply using {@link ngTransclude} to inject the transclusion into your directive.\n *\n *\n * #### Transclusion Scopes\n *\n * When you call a transclude function it returns a DOM fragment that is pre-bound to a **transclusion\n * scope**. This scope is special, in that it is a child of the directive's scope (and so gets destroyed\n * when the directive's scope gets destroyed) but it inherits the properties of the scope from which it\n * was taken.\n *\n * For example consider a directive that uses transclusion and isolated scope. The DOM hierarchy might look\n * like this:\n *\n * ```html\n * <div ng-app>\n *   <div isolate>\n *     <div transclusion>\n *     </div>\n *   </div>\n * </div>\n * ```\n *\n * The `$parent` scope hierarchy will look like this:\n *\n * ```\n * - $rootScope\n *   - isolate\n *     - transclusion\n * ```\n *\n * but the scopes will inherit prototypically from different scopes to their `$parent`.\n *\n * ```\n * - $rootScope\n *   - transclusion\n * - isolate\n * ```\n *\n *\n * ### Attributes\n *\n * The {@link ng.$compile.directive.Attributes Attributes} object - passed as a parameter in the\n * `link()` or `compile()` functions. It has a variety of uses.\n *\n * accessing *Normalized attribute names:*\n * Directives like 'ngBind' can be expressed in many ways: 'ng:bind', `data-ng-bind`, or 'x-ng-bind'.\n * the attributes object allows for normalized access to\n *   the attributes.\n *\n * * *Directive inter-communication:* All directives share the same instance of the attributes\n *   object which allows the directives to use the attributes object as inter directive\n *   communication.\n *\n * * *Supports interpolation:* Interpolation attributes are assigned to the attribute object\n *   allowing other directives to read the interpolated value.\n *\n * * *Observing interpolated attributes:* Use `$observe` to observe the value changes of attributes\n *   that contain interpolation (e.g. `src=\"{{bar}}\"`). Not only is this very efficient but it's also\n *   the only way to easily get the actual value because during the linking phase the interpolation\n *   hasn't been evaluated yet and so the value is at this time set to `undefined`.\n *\n * ```js\n * function linkingFn(scope, elm, attrs, ctrl) {\n *   // get the attribute value\n *   console.log(attrs.ngModel);\n *\n *   // change the attribute\n *   attrs.$set('ngModel', 'new value');\n *\n *   // observe changes to interpolated attribute\n *   attrs.$observe('ngModel', function(value) {\n *     console.log('ngModel has changed value to ' + value);\n *   });\n * }\n * ```\n *\n * ## Example\n *\n * <div class=\"alert alert-warning\">\n * **Note**: Typically directives are registered with `module.directive`. The example below is\n * to illustrate how `$compile` works.\n * </div>\n *\n <example module=\"compileExample\">\n   <file name=\"index.html\">\n    <script>\n      angular.module('compileExample', [], function($compileProvider) {\n        // configure new 'compile' directive by passing a directive\n        // factory function. The factory function injects the '$compile'\n        $compileProvider.directive('compile', function($compile) {\n          // directive factory creates a link function\n          return function(scope, element, attrs) {\n            scope.$watch(\n              function(scope) {\n                 // watch the 'compile' expression for changes\n                return scope.$eval(attrs.compile);\n              },\n              function(value) {\n                // when the 'compile' expression changes\n                // assign it into the current DOM\n                element.html(value);\n\n                // compile the new DOM and link it to the current\n                // scope.\n                // NOTE: we only compile .childNodes so that\n                // we don't get into infinite loop compiling ourselves\n                $compile(element.contents())(scope);\n              }\n            );\n          };\n        });\n      })\n      .controller('GreeterController', ['$scope', function($scope) {\n        $scope.name = 'Angular';\n        $scope.html = 'Hello {{name}}';\n      }]);\n    </script>\n    <div ng-controller=\"GreeterController\">\n      <input ng-model=\"name\"> <br>\n      <textarea ng-model=\"html\"></textarea> <br>\n      <div compile=\"html\"></div>\n    </div>\n   </file>\n   <file name=\"protractor.js\" type=\"protractor\">\n     it('should auto compile', function() {\n       var textarea = $('textarea');\n       var output = $('div[compile]');\n       // The initial state reads 'Hello Angular'.\n       expect(output.getText()).toBe('Hello Angular');\n       textarea.clear();\n       textarea.sendKeys('{{name}}!');\n       expect(output.getText()).toBe('Angular!');\n     });\n   </file>\n </example>\n\n *\n *\n * @param {string|DOMElement} element Element or HTML string to compile into a template function.\n * @param {function(angular.Scope, cloneAttachFn=)} transclude function available to directives - DEPRECATED.\n *\n * <div class=\"alert alert-error\">\n * **Note:** Passing a `transclude` function to the $compile function is deprecated, as it\n *   e.g. will not use the right outer scope. Please pass the transclude function as a\n *   `parentBoundTranscludeFn` to the link function instead.\n * </div>\n *\n * @param {number} maxPriority only apply directives lower than given priority (Only effects the\n *                 root element(s), not their children)\n * @returns {function(scope, cloneAttachFn=, options=)} a link function which is used to bind template\n * (a DOM element/tree) to a scope. Where:\n *\n *  * `scope` - A {@link ng.$rootScope.Scope Scope} to bind to.\n *  * `cloneAttachFn` - If `cloneAttachFn` is provided, then the link function will clone the\n *  `template` and call the `cloneAttachFn` function allowing the caller to attach the\n *  cloned elements to the DOM document at the appropriate place. The `cloneAttachFn` is\n *  called as: <br> `cloneAttachFn(clonedElement, scope)` where:\n *\n *      * `clonedElement` - is a clone of the original `element` passed into the compiler.\n *      * `scope` - is the current scope with which the linking function is working with.\n *\n *  * `options` - An optional object hash with linking options. If `options` is provided, then the following\n *  keys may be used to control linking behavior:\n *\n *      * `parentBoundTranscludeFn` - the transclude function made available to\n *        directives; if given, it will be passed through to the link functions of\n *        directives found in `element` during compilation.\n *      * `transcludeControllers` - an object hash with keys that map controller names\n *        to controller instances; if given, it will make the controllers\n *        available to directives.\n *      * `futureParentElement` - defines the parent to which the `cloneAttachFn` will add\n *        the cloned elements; only needed for transcludes that are allowed to contain non html\n *        elements (e.g. SVG elements). See also the directive.controller property.\n *\n * Calling the linking function returns the element of the template. It is either the original\n * element passed in, or the clone of the element if the `cloneAttachFn` is provided.\n *\n * After linking the view is not updated until after a call to $digest which typically is done by\n * Angular automatically.\n *\n * If you need access to the bound view, there are two ways to do it:\n *\n * - If you are not asking the linking function to clone the template, create the DOM element(s)\n *   before you send them to the compiler and keep this reference around.\n *   ```js\n *     var element = $compile('<p>{{total}}</p>')(scope);\n *   ```\n *\n * - if on the other hand, you need the element to be cloned, the view reference from the original\n *   example would not point to the clone, but rather to the original template that was cloned. In\n *   this case, you can access the clone via the cloneAttachFn:\n *   ```js\n *     var templateElement = angular.element('<p>{{total}}</p>'),\n *         scope = ....;\n *\n *     var clonedElement = $compile(templateElement)(scope, function(clonedElement, scope) {\n *       //attach the clone to DOM document at the right place\n *     });\n *\n *     //now we have reference to the cloned DOM via `clonedElement`\n *   ```\n *\n *\n * For information on how the compiler works, see the\n * {@link guide/compiler Angular HTML Compiler} section of the Developer Guide.\n */\n\nvar $compileMinErr = minErr('$compile');\n\n/**\n * @ngdoc provider\n * @name $compileProvider\n *\n * @description\n */\n$CompileProvider.$inject = ['$provide', '$$sanitizeUriProvider'];\nfunction $CompileProvider($provide, $$sanitizeUriProvider) {\n  var hasDirectives = {},\n      Suffix = 'Directive',\n      COMMENT_DIRECTIVE_REGEXP = /^\\s*directive\\:\\s*([\\w\\-]+)\\s+(.*)$/,\n      CLASS_DIRECTIVE_REGEXP = /(([\\w\\-]+)(?:\\:([^;]+))?;?)/,\n      ALL_OR_NOTHING_ATTRS = makeMap('ngSrc,ngSrcset,src,srcset'),\n      REQUIRE_PREFIX_REGEXP = /^(?:(\\^\\^?)?(\\?)?(\\^\\^?)?)?/;\n\n  // Ref: http://developers.whatwg.org/webappapis.html#event-handler-idl-attributes\n  // The assumption is that future DOM event attribute names will begin with\n  // 'on' and be composed of only English letters.\n  var EVENT_HANDLER_ATTR_REGEXP = /^(on[a-z]+|formaction)$/;\n\n  function parseIsolateBindings(scope, directiveName) {\n    var LOCAL_REGEXP = /^\\s*([@&]|=(\\*?))(\\??)\\s*(\\w*)\\s*$/;\n\n    var bindings = {};\n\n    forEach(scope, function(definition, scopeName) {\n      var match = definition.match(LOCAL_REGEXP);\n\n      if (!match) {\n        throw $compileMinErr('iscp',\n            \"Invalid isolate scope definition for directive '{0}'.\" +\n            \" Definition: {... {1}: '{2}' ...}\",\n            directiveName, scopeName, definition);\n      }\n\n      bindings[scopeName] = {\n        mode: match[1][0],\n        collection: match[2] === '*',\n        optional: match[3] === '?',\n        attrName: match[4] || scopeName\n      };\n    });\n\n    return bindings;\n  }\n\n  /**\n   * @ngdoc method\n   * @name $compileProvider#directive\n   * @kind function\n   *\n   * @description\n   * Register a new directive with the compiler.\n   *\n   * @param {string|Object} name Name of the directive in camel-case (i.e. <code>ngBind</code> which\n   *    will match as <code>ng-bind</code>), or an object map of directives where the keys are the\n   *    names and the values are the factories.\n   * @param {Function|Array} directiveFactory An injectable directive factory function. See\n   *    {@link guide/directive} for more info.\n   * @returns {ng.$compileProvider} Self for chaining.\n   */\n   this.directive = function registerDirective(name, directiveFactory) {\n    assertNotHasOwnProperty(name, 'directive');\n    if (isString(name)) {\n      assertArg(directiveFactory, 'directiveFactory');\n      if (!hasDirectives.hasOwnProperty(name)) {\n        hasDirectives[name] = [];\n        $provide.factory(name + Suffix, ['$injector', '$exceptionHandler',\n          function($injector, $exceptionHandler) {\n            var directives = [];\n            forEach(hasDirectives[name], function(directiveFactory, index) {\n              try {\n                var directive = $injector.invoke(directiveFactory);\n                if (isFunction(directive)) {\n                  directive = { compile: valueFn(directive) };\n                } else if (!directive.compile && directive.link) {\n                  directive.compile = valueFn(directive.link);\n                }\n                directive.priority = directive.priority || 0;\n                directive.index = index;\n                directive.name = directive.name || name;\n                directive.require = directive.require || (directive.controller && directive.name);\n                directive.restrict = directive.restrict || 'EA';\n                if (isObject(directive.scope)) {\n                  directive.$$isolateBindings = parseIsolateBindings(directive.scope, directive.name);\n                }\n                directives.push(directive);\n              } catch (e) {\n                $exceptionHandler(e);\n              }\n            });\n            return directives;\n          }]);\n      }\n      hasDirectives[name].push(directiveFactory);\n    } else {\n      forEach(name, reverseParams(registerDirective));\n    }\n    return this;\n  };\n\n\n  /**\n   * @ngdoc method\n   * @name $compileProvider#aHrefSanitizationWhitelist\n   * @kind function\n   *\n   * @description\n   * Retrieves or overrides the default regular expression that is used for whitelisting of safe\n   * urls during a[href] sanitization.\n   *\n   * The sanitization is a security measure aimed at preventing XSS attacks via html links.\n   *\n   * Any url about to be assigned to a[href] via data-binding is first normalized and turned into\n   * an absolute url. Afterwards, the url is matched against the `aHrefSanitizationWhitelist`\n   * regular expression. If a match is found, the original url is written into the dom. Otherwise,\n   * the absolute url is prefixed with `'unsafe:'` string and only then is it written into the DOM.\n   *\n   * @param {RegExp=} regexp New regexp to whitelist urls with.\n   * @returns {RegExp|ng.$compileProvider} Current RegExp if called without value or self for\n   *    chaining otherwise.\n   */\n  this.aHrefSanitizationWhitelist = function(regexp) {\n    if (isDefined(regexp)) {\n      $$sanitizeUriProvider.aHrefSanitizationWhitelist(regexp);\n      return this;\n    } else {\n      return $$sanitizeUriProvider.aHrefSanitizationWhitelist();\n    }\n  };\n\n\n  /**\n   * @ngdoc method\n   * @name $compileProvider#imgSrcSanitizationWhitelist\n   * @kind function\n   *\n   * @description\n   * Retrieves or overrides the default regular expression that is used for whitelisting of safe\n   * urls during img[src] sanitization.\n   *\n   * The sanitization is a security measure aimed at prevent XSS attacks via html links.\n   *\n   * Any url about to be assigned to img[src] via data-binding is first normalized and turned into\n   * an absolute url. Afterwards, the url is matched against the `imgSrcSanitizationWhitelist`\n   * regular expression. If a match is found, the original url is written into the dom. Otherwise,\n   * the absolute url is prefixed with `'unsafe:'` string and only then is it written into the DOM.\n   *\n   * @param {RegExp=} regexp New regexp to whitelist urls with.\n   * @returns {RegExp|ng.$compileProvider} Current RegExp if called without value or self for\n   *    chaining otherwise.\n   */\n  this.imgSrcSanitizationWhitelist = function(regexp) {\n    if (isDefined(regexp)) {\n      $$sanitizeUriProvider.imgSrcSanitizationWhitelist(regexp);\n      return this;\n    } else {\n      return $$sanitizeUriProvider.imgSrcSanitizationWhitelist();\n    }\n  };\n\n  /**\n   * @ngdoc method\n   * @name  $compileProvider#debugInfoEnabled\n   *\n   * @param {boolean=} enabled update the debugInfoEnabled state if provided, otherwise just return the\n   * current debugInfoEnabled state\n   * @returns {*} current value if used as getter or itself (chaining) if used as setter\n   *\n   * @kind function\n   *\n   * @description\n   * Call this method to enable/disable various debug runtime information in the compiler such as adding\n   * binding information and a reference to the current scope on to DOM elements.\n   * If enabled, the compiler will add the following to DOM elements that have been bound to the scope\n   * * `ng-binding` CSS class\n   * * `$binding` data property containing an array of the binding expressions\n   *\n   * You may want to disable this in production for a significant performance boost. See\n   * {@link guide/production#disabling-debug-data Disabling Debug Data} for more.\n   *\n   * The default value is true.\n   */\n  var debugInfoEnabled = true;\n  this.debugInfoEnabled = function(enabled) {\n    if (isDefined(enabled)) {\n      debugInfoEnabled = enabled;\n      return this;\n    }\n    return debugInfoEnabled;\n  };\n\n  this.$get = [\n            '$injector', '$interpolate', '$exceptionHandler', '$templateRequest', '$parse',\n            '$controller', '$rootScope', '$document', '$sce', '$animate', '$$sanitizeUri',\n    function($injector,   $interpolate,   $exceptionHandler,   $templateRequest,   $parse,\n             $controller,   $rootScope,   $document,   $sce,   $animate,   $$sanitizeUri) {\n\n    var Attributes = function(element, attributesToCopy) {\n      if (attributesToCopy) {\n        var keys = Object.keys(attributesToCopy);\n        var i, l, key;\n\n        for (i = 0, l = keys.length; i < l; i++) {\n          key = keys[i];\n          this[key] = attributesToCopy[key];\n        }\n      } else {\n        this.$attr = {};\n      }\n\n      this.$$element = element;\n    };\n\n    Attributes.prototype = {\n      /**\n       * @ngdoc method\n       * @name $compile.directive.Attributes#$normalize\n       * @kind function\n       *\n       * @description\n       * Converts an attribute name (e.g. dash/colon/underscore-delimited string, optionally prefixed with `x-` or\n       * `data-`) to its normalized, camelCase form.\n       *\n       * Also there is special case for Moz prefix starting with upper case letter.\n       *\n       * For further information check out the guide on {@link guide/directive#matching-directives Matching Directives}\n       *\n       * @param {string} name Name to normalize\n       */\n      $normalize: directiveNormalize,\n\n\n      /**\n       * @ngdoc method\n       * @name $compile.directive.Attributes#$addClass\n       * @kind function\n       *\n       * @description\n       * Adds the CSS class value specified by the classVal parameter to the element. If animations\n       * are enabled then an animation will be triggered for the class addition.\n       *\n       * @param {string} classVal The className value that will be added to the element\n       */\n      $addClass: function(classVal) {\n        if (classVal && classVal.length > 0) {\n          $animate.addClass(this.$$element, classVal);\n        }\n      },\n\n      /**\n       * @ngdoc method\n       * @name $compile.directive.Attributes#$removeClass\n       * @kind function\n       *\n       * @description\n       * Removes the CSS class value specified by the classVal parameter from the element. If\n       * animations are enabled then an animation will be triggered for the class removal.\n       *\n       * @param {string} classVal The className value that will be removed from the element\n       */\n      $removeClass: function(classVal) {\n        if (classVal && classVal.length > 0) {\n          $animate.removeClass(this.$$element, classVal);\n        }\n      },\n\n      /**\n       * @ngdoc method\n       * @name $compile.directive.Attributes#$updateClass\n       * @kind function\n       *\n       * @description\n       * Adds and removes the appropriate CSS class values to the element based on the difference\n       * between the new and old CSS class values (specified as newClasses and oldClasses).\n       *\n       * @param {string} newClasses The current CSS className value\n       * @param {string} oldClasses The former CSS className value\n       */\n      $updateClass: function(newClasses, oldClasses) {\n        var toAdd = tokenDifference(newClasses, oldClasses);\n        if (toAdd && toAdd.length) {\n          $animate.addClass(this.$$element, toAdd);\n        }\n\n        var toRemove = tokenDifference(oldClasses, newClasses);\n        if (toRemove && toRemove.length) {\n          $animate.removeClass(this.$$element, toRemove);\n        }\n      },\n\n      /**\n       * Set a normalized attribute on the element in a way such that all directives\n       * can share the attribute. This function properly handles boolean attributes.\n       * @param {string} key Normalized key. (ie ngAttribute)\n       * @param {string|boolean} value The value to set. If `null` attribute will be deleted.\n       * @param {boolean=} writeAttr If false, does not write the value to DOM element attribute.\n       *     Defaults to true.\n       * @param {string=} attrName Optional none normalized name. Defaults to key.\n       */\n      $set: function(key, value, writeAttr, attrName) {\n        // TODO: decide whether or not to throw an error if \"class\"\n        //is set through this function since it may cause $updateClass to\n        //become unstable.\n\n        var node = this.$$element[0],\n            booleanKey = getBooleanAttrName(node, key),\n            aliasedKey = getAliasedAttrName(node, key),\n            observer = key,\n            nodeName;\n\n        if (booleanKey) {\n          this.$$element.prop(key, value);\n          attrName = booleanKey;\n        } else if (aliasedKey) {\n          this[aliasedKey] = value;\n          observer = aliasedKey;\n        }\n\n        this[key] = value;\n\n        // translate normalized key to actual key\n        if (attrName) {\n          this.$attr[key] = attrName;\n        } else {\n          attrName = this.$attr[key];\n          if (!attrName) {\n            this.$attr[key] = attrName = snake_case(key, '-');\n          }\n        }\n\n        nodeName = nodeName_(this.$$element);\n\n        if ((nodeName === 'a' && key === 'href') ||\n            (nodeName === 'img' && key === 'src')) {\n          // sanitize a[href] and img[src] values\n          this[key] = value = $$sanitizeUri(value, key === 'src');\n        } else if (nodeName === 'img' && key === 'srcset') {\n          // sanitize img[srcset] values\n          var result = \"\";\n\n          // first check if there are spaces because it's not the same pattern\n          var trimmedSrcset = trim(value);\n          //                (   999x   ,|   999w   ,|   ,|,   )\n          var srcPattern = /(\\s+\\d+x\\s*,|\\s+\\d+w\\s*,|\\s+,|,\\s+)/;\n          var pattern = /\\s/.test(trimmedSrcset) ? srcPattern : /(,)/;\n\n          // split srcset into tuple of uri and descriptor except for the last item\n          var rawUris = trimmedSrcset.split(pattern);\n\n          // for each tuples\n          var nbrUrisWith2parts = Math.floor(rawUris.length / 2);\n          for (var i = 0; i < nbrUrisWith2parts; i++) {\n            var innerIdx = i * 2;\n            // sanitize the uri\n            result += $$sanitizeUri(trim(rawUris[innerIdx]), true);\n            // add the descriptor\n            result += (\" \" + trim(rawUris[innerIdx + 1]));\n          }\n\n          // split the last item into uri and descriptor\n          var lastTuple = trim(rawUris[i * 2]).split(/\\s/);\n\n          // sanitize the last uri\n          result += $$sanitizeUri(trim(lastTuple[0]), true);\n\n          // and add the last descriptor if any\n          if (lastTuple.length === 2) {\n            result += (\" \" + trim(lastTuple[1]));\n          }\n          this[key] = value = result;\n        }\n\n        if (writeAttr !== false) {\n          if (value === null || value === undefined) {\n            this.$$element.removeAttr(attrName);\n          } else {\n            this.$$element.attr(attrName, value);\n          }\n        }\n\n        // fire observers\n        var $$observers = this.$$observers;\n        $$observers && forEach($$observers[observer], function(fn) {\n          try {\n            fn(value);\n          } catch (e) {\n            $exceptionHandler(e);\n          }\n        });\n      },\n\n\n      /**\n       * @ngdoc method\n       * @name $compile.directive.Attributes#$observe\n       * @kind function\n       *\n       * @description\n       * Observes an interpolated attribute.\n       *\n       * The observer function will be invoked once during the next `$digest` following\n       * compilation. The observer is then invoked whenever the interpolated value\n       * changes.\n       *\n       * @param {string} key Normalized key. (ie ngAttribute) .\n       * @param {function(interpolatedValue)} fn Function that will be called whenever\n                the interpolated value of the attribute changes.\n       *        See the {@link guide/directive#text-and-attribute-bindings Directives} guide for more info.\n       * @returns {function()} Returns a deregistration function for this observer.\n       */\n      $observe: function(key, fn) {\n        var attrs = this,\n            $$observers = (attrs.$$observers || (attrs.$$observers = createMap())),\n            listeners = ($$observers[key] || ($$observers[key] = []));\n\n        listeners.push(fn);\n        $rootScope.$evalAsync(function() {\n          if (!listeners.$$inter && attrs.hasOwnProperty(key)) {\n            // no one registered attribute interpolation function, so lets call it manually\n            fn(attrs[key]);\n          }\n        });\n\n        return function() {\n          arrayRemove(listeners, fn);\n        };\n      }\n    };\n\n\n    function safeAddClass($element, className) {\n      try {\n        $element.addClass(className);\n      } catch (e) {\n        // ignore, since it means that we are trying to set class on\n        // SVG element, where class name is read-only.\n      }\n    }\n\n\n    var startSymbol = $interpolate.startSymbol(),\n        endSymbol = $interpolate.endSymbol(),\n        denormalizeTemplate = (startSymbol == '{{' || endSymbol  == '}}')\n            ? identity\n            : function denormalizeTemplate(template) {\n              return template.replace(/\\{\\{/g, startSymbol).replace(/}}/g, endSymbol);\n        },\n        NG_ATTR_BINDING = /^ngAttr[A-Z]/;\n\n    compile.$$addBindingInfo = debugInfoEnabled ? function $$addBindingInfo($element, binding) {\n      var bindings = $element.data('$binding') || [];\n\n      if (isArray(binding)) {\n        bindings = bindings.concat(binding);\n      } else {\n        bindings.push(binding);\n      }\n\n      $element.data('$binding', bindings);\n    } : noop;\n\n    compile.$$addBindingClass = debugInfoEnabled ? function $$addBindingClass($element) {\n      safeAddClass($element, 'ng-binding');\n    } : noop;\n\n    compile.$$addScopeInfo = debugInfoEnabled ? function $$addScopeInfo($element, scope, isolated, noTemplate) {\n      var dataName = isolated ? (noTemplate ? '$isolateScopeNoTemplate' : '$isolateScope') : '$scope';\n      $element.data(dataName, scope);\n    } : noop;\n\n    compile.$$addScopeClass = debugInfoEnabled ? function $$addScopeClass($element, isolated) {\n      safeAddClass($element, isolated ? 'ng-isolate-scope' : 'ng-scope');\n    } : noop;\n\n    return compile;\n\n    //================================\n\n    function compile($compileNodes, transcludeFn, maxPriority, ignoreDirective,\n                        previousCompileContext) {\n      if (!($compileNodes instanceof jqLite)) {\n        // jquery always rewraps, whereas we need to preserve the original selector so that we can\n        // modify it.\n        $compileNodes = jqLite($compileNodes);\n      }\n      // We can not compile top level text elements since text nodes can be merged and we will\n      // not be able to attach scope data to them, so we will wrap them in <span>\n      forEach($compileNodes, function(node, index) {\n        if (node.nodeType == NODE_TYPE_TEXT && node.nodeValue.match(/\\S+/) /* non-empty */ ) {\n          $compileNodes[index] = jqLite(node).wrap('<span></span>').parent()[0];\n        }\n      });\n      var compositeLinkFn =\n              compileNodes($compileNodes, transcludeFn, $compileNodes,\n                           maxPriority, ignoreDirective, previousCompileContext);\n      compile.$$addScopeClass($compileNodes);\n      var namespace = null;\n      return function publicLinkFn(scope, cloneConnectFn, options) {\n        assertArg(scope, 'scope');\n\n        options = options || {};\n        var parentBoundTranscludeFn = options.parentBoundTranscludeFn,\n          transcludeControllers = options.transcludeControllers,\n          futureParentElement = options.futureParentElement;\n\n        // When `parentBoundTranscludeFn` is passed, it is a\n        // `controllersBoundTransclude` function (it was previously passed\n        // as `transclude` to directive.link) so we must unwrap it to get\n        // its `boundTranscludeFn`\n        if (parentBoundTranscludeFn && parentBoundTranscludeFn.$$boundTransclude) {\n          parentBoundTranscludeFn = parentBoundTranscludeFn.$$boundTransclude;\n        }\n\n        if (!namespace) {\n          namespace = detectNamespaceForChildElements(futureParentElement);\n        }\n        var $linkNode;\n        if (namespace !== 'html') {\n          // When using a directive with replace:true and templateUrl the $compileNodes\n          // (or a child element inside of them)\n          // might change, so we need to recreate the namespace adapted compileNodes\n          // for call to the link function.\n          // Note: This will already clone the nodes...\n          $linkNode = jqLite(\n            wrapTemplate(namespace, jqLite('<div>').append($compileNodes).html())\n          );\n        } else if (cloneConnectFn) {\n          // important!!: we must call our jqLite.clone() since the jQuery one is trying to be smart\n          // and sometimes changes the structure of the DOM.\n          $linkNode = JQLitePrototype.clone.call($compileNodes);\n        } else {\n          $linkNode = $compileNodes;\n        }\n\n        if (transcludeControllers) {\n          for (var controllerName in transcludeControllers) {\n            $linkNode.data('$' + controllerName + 'Controller', transcludeControllers[controllerName].instance);\n          }\n        }\n\n        compile.$$addScopeInfo($linkNode, scope);\n\n        if (cloneConnectFn) cloneConnectFn($linkNode, scope);\n        if (compositeLinkFn) compositeLinkFn(scope, $linkNode, $linkNode, parentBoundTranscludeFn);\n        return $linkNode;\n      };\n    }\n\n    function detectNamespaceForChildElements(parentElement) {\n      // TODO: Make this detect MathML as well...\n      var node = parentElement && parentElement[0];\n      if (!node) {\n        return 'html';\n      } else {\n        return nodeName_(node) !== 'foreignobject' && node.toString().match(/SVG/) ? 'svg' : 'html';\n      }\n    }\n\n    /**\n     * Compile function matches each node in nodeList against the directives. Once all directives\n     * for a particular node are collected their compile functions are executed. The compile\n     * functions return values - the linking functions - are combined into a composite linking\n     * function, which is the a linking function for the node.\n     *\n     * @param {NodeList} nodeList an array of nodes or NodeList to compile\n     * @param {function(angular.Scope, cloneAttachFn=)} transcludeFn A linking function, where the\n     *        scope argument is auto-generated to the new child of the transcluded parent scope.\n     * @param {DOMElement=} $rootElement If the nodeList is the root of the compilation tree then\n     *        the rootElement must be set the jqLite collection of the compile root. This is\n     *        needed so that the jqLite collection items can be replaced with widgets.\n     * @param {number=} maxPriority Max directive priority.\n     * @returns {Function} A composite linking function of all of the matched directives or null.\n     */\n    function compileNodes(nodeList, transcludeFn, $rootElement, maxPriority, ignoreDirective,\n                            previousCompileContext) {\n      var linkFns = [],\n          attrs, directives, nodeLinkFn, childNodes, childLinkFn, linkFnFound, nodeLinkFnFound;\n\n      for (var i = 0; i < nodeList.length; i++) {\n        attrs = new Attributes();\n\n        // we must always refer to nodeList[i] since the nodes can be replaced underneath us.\n        directives = collectDirectives(nodeList[i], [], attrs, i === 0 ? maxPriority : undefined,\n                                        ignoreDirective);\n\n        nodeLinkFn = (directives.length)\n            ? applyDirectivesToNode(directives, nodeList[i], attrs, transcludeFn, $rootElement,\n                                      null, [], [], previousCompileContext)\n            : null;\n\n        if (nodeLinkFn && nodeLinkFn.scope) {\n          compile.$$addScopeClass(attrs.$$element);\n        }\n\n        childLinkFn = (nodeLinkFn && nodeLinkFn.terminal ||\n                      !(childNodes = nodeList[i].childNodes) ||\n                      !childNodes.length)\n            ? null\n            : compileNodes(childNodes,\n                 nodeLinkFn ? (\n                  (nodeLinkFn.transcludeOnThisElement || !nodeLinkFn.templateOnThisElement)\n                     && nodeLinkFn.transclude) : transcludeFn);\n\n        if (nodeLinkFn || childLinkFn) {\n          linkFns.push(i, nodeLinkFn, childLinkFn);\n          linkFnFound = true;\n          nodeLinkFnFound = nodeLinkFnFound || nodeLinkFn;\n        }\n\n        //use the previous context only for the first element in the virtual group\n        previousCompileContext = null;\n      }\n\n      // return a linking function if we have found anything, null otherwise\n      return linkFnFound ? compositeLinkFn : null;\n\n      function compositeLinkFn(scope, nodeList, $rootElement, parentBoundTranscludeFn) {\n        var nodeLinkFn, childLinkFn, node, childScope, i, ii, idx, childBoundTranscludeFn;\n        var stableNodeList;\n\n\n        if (nodeLinkFnFound) {\n          // copy nodeList so that if a nodeLinkFn removes or adds an element at this DOM level our\n          // offsets don't get screwed up\n          var nodeListLength = nodeList.length;\n          stableNodeList = new Array(nodeListLength);\n\n          // create a sparse array by only copying the elements which have a linkFn\n          for (i = 0; i < linkFns.length; i+=3) {\n            idx = linkFns[i];\n            stableNodeList[idx] = nodeList[idx];\n          }\n        } else {\n          stableNodeList = nodeList;\n        }\n\n        for (i = 0, ii = linkFns.length; i < ii;) {\n          node = stableNodeList[linkFns[i++]];\n          nodeLinkFn = linkFns[i++];\n          childLinkFn = linkFns[i++];\n\n          if (nodeLinkFn) {\n            if (nodeLinkFn.scope) {\n              childScope = scope.$new();\n              compile.$$addScopeInfo(jqLite(node), childScope);\n            } else {\n              childScope = scope;\n            }\n\n            if (nodeLinkFn.transcludeOnThisElement) {\n              childBoundTranscludeFn = createBoundTranscludeFn(\n                  scope, nodeLinkFn.transclude, parentBoundTranscludeFn,\n                  nodeLinkFn.elementTranscludeOnThisElement);\n\n            } else if (!nodeLinkFn.templateOnThisElement && parentBoundTranscludeFn) {\n              childBoundTranscludeFn = parentBoundTranscludeFn;\n\n            } else if (!parentBoundTranscludeFn && transcludeFn) {\n              childBoundTranscludeFn = createBoundTranscludeFn(scope, transcludeFn);\n\n            } else {\n              childBoundTranscludeFn = null;\n            }\n\n            nodeLinkFn(childLinkFn, childScope, node, $rootElement, childBoundTranscludeFn);\n\n          } else if (childLinkFn) {\n            childLinkFn(scope, node.childNodes, undefined, parentBoundTranscludeFn);\n          }\n        }\n      }\n    }\n\n    function createBoundTranscludeFn(scope, transcludeFn, previousBoundTranscludeFn, elementTransclusion) {\n\n      var boundTranscludeFn = function(transcludedScope, cloneFn, controllers, futureParentElement, containingScope) {\n\n        if (!transcludedScope) {\n          transcludedScope = scope.$new(false, containingScope);\n          transcludedScope.$$transcluded = true;\n        }\n\n        return transcludeFn(transcludedScope, cloneFn, {\n          parentBoundTranscludeFn: previousBoundTranscludeFn,\n          transcludeControllers: controllers,\n          futureParentElement: futureParentElement\n        });\n      };\n\n      return boundTranscludeFn;\n    }\n\n    /**\n     * Looks for directives on the given node and adds them to the directive collection which is\n     * sorted.\n     *\n     * @param node Node to search.\n     * @param directives An array to which the directives are added to. This array is sorted before\n     *        the function returns.\n     * @param attrs The shared attrs object which is used to populate the normalized attributes.\n     * @param {number=} maxPriority Max directive priority.\n     */\n    function collectDirectives(node, directives, attrs, maxPriority, ignoreDirective) {\n      var nodeType = node.nodeType,\n          attrsMap = attrs.$attr,\n          match,\n          className;\n\n      switch (nodeType) {\n        case NODE_TYPE_ELEMENT: /* Element */\n          // use the node name: <directive>\n          addDirective(directives,\n              directiveNormalize(nodeName_(node)), 'E', maxPriority, ignoreDirective);\n\n          // iterate over the attributes\n          for (var attr, name, nName, ngAttrName, value, isNgAttr, nAttrs = node.attributes,\n                   j = 0, jj = nAttrs && nAttrs.length; j < jj; j++) {\n            var attrStartName = false;\n            var attrEndName = false;\n\n            attr = nAttrs[j];\n            name = attr.name;\n            value = trim(attr.value);\n\n            // support ngAttr attribute binding\n            ngAttrName = directiveNormalize(name);\n            if (isNgAttr = NG_ATTR_BINDING.test(ngAttrName)) {\n              name = name.replace(PREFIX_REGEXP, '')\n                .substr(8).replace(/_(.)/g, function(match, letter) {\n                  return letter.toUpperCase();\n                });\n            }\n\n            var directiveNName = ngAttrName.replace(/(Start|End)$/, '');\n            if (directiveIsMultiElement(directiveNName)) {\n              if (ngAttrName === directiveNName + 'Start') {\n                attrStartName = name;\n                attrEndName = name.substr(0, name.length - 5) + 'end';\n                name = name.substr(0, name.length - 6);\n              }\n            }\n\n            nName = directiveNormalize(name.toLowerCase());\n            attrsMap[nName] = name;\n            if (isNgAttr || !attrs.hasOwnProperty(nName)) {\n                attrs[nName] = value;\n                if (getBooleanAttrName(node, nName)) {\n                  attrs[nName] = true; // presence means true\n                }\n            }\n            addAttrInterpolateDirective(node, directives, value, nName, isNgAttr);\n            addDirective(directives, nName, 'A', maxPriority, ignoreDirective, attrStartName,\n                          attrEndName);\n          }\n\n          // use class as directive\n          className = node.className;\n          if (isObject(className)) {\n              // Maybe SVGAnimatedString\n              className = className.animVal;\n          }\n          if (isString(className) && className !== '') {\n            while (match = CLASS_DIRECTIVE_REGEXP.exec(className)) {\n              nName = directiveNormalize(match[2]);\n              if (addDirective(directives, nName, 'C', maxPriority, ignoreDirective)) {\n                attrs[nName] = trim(match[3]);\n              }\n              className = className.substr(match.index + match[0].length);\n            }\n          }\n          break;\n        case NODE_TYPE_TEXT: /* Text Node */\n          addTextInterpolateDirective(directives, node.nodeValue);\n          break;\n        case NODE_TYPE_COMMENT: /* Comment */\n          try {\n            match = COMMENT_DIRECTIVE_REGEXP.exec(node.nodeValue);\n            if (match) {\n              nName = directiveNormalize(match[1]);\n              if (addDirective(directives, nName, 'M', maxPriority, ignoreDirective)) {\n                attrs[nName] = trim(match[2]);\n              }\n            }\n          } catch (e) {\n            // turns out that under some circumstances IE9 throws errors when one attempts to read\n            // comment's node value.\n            // Just ignore it and continue. (Can't seem to reproduce in test case.)\n          }\n          break;\n      }\n\n      directives.sort(byPriority);\n      return directives;\n    }\n\n    /**\n     * Given a node with an directive-start it collects all of the siblings until it finds\n     * directive-end.\n     * @param node\n     * @param attrStart\n     * @param attrEnd\n     * @returns {*}\n     */\n    function groupScan(node, attrStart, attrEnd) {\n      var nodes = [];\n      var depth = 0;\n      if (attrStart && node.hasAttribute && node.hasAttribute(attrStart)) {\n        do {\n          if (!node) {\n            throw $compileMinErr('uterdir',\n                      \"Unterminated attribute, found '{0}' but no matching '{1}' found.\",\n                      attrStart, attrEnd);\n          }\n          if (node.nodeType == NODE_TYPE_ELEMENT) {\n            if (node.hasAttribute(attrStart)) depth++;\n            if (node.hasAttribute(attrEnd)) depth--;\n          }\n          nodes.push(node);\n          node = node.nextSibling;\n        } while (depth > 0);\n      } else {\n        nodes.push(node);\n      }\n\n      return jqLite(nodes);\n    }\n\n    /**\n     * Wrapper for linking function which converts normal linking function into a grouped\n     * linking function.\n     * @param linkFn\n     * @param attrStart\n     * @param attrEnd\n     * @returns {Function}\n     */\n    function groupElementsLinkFnWrapper(linkFn, attrStart, attrEnd) {\n      return function(scope, element, attrs, controllers, transcludeFn) {\n        element = groupScan(element[0], attrStart, attrEnd);\n        return linkFn(scope, element, attrs, controllers, transcludeFn);\n      };\n    }\n\n    /**\n     * Once the directives have been collected, their compile functions are executed. This method\n     * is responsible for inlining directive templates as well as terminating the application\n     * of the directives if the terminal directive has been reached.\n     *\n     * @param {Array} directives Array of collected directives to execute their compile function.\n     *        this needs to be pre-sorted by priority order.\n     * @param {Node} compileNode The raw DOM node to apply the compile functions to\n     * @param {Object} templateAttrs The shared attribute function\n     * @param {function(angular.Scope, cloneAttachFn=)} transcludeFn A linking function, where the\n     *                                                  scope argument is auto-generated to the new\n     *                                                  child of the transcluded parent scope.\n     * @param {JQLite} jqCollection If we are working on the root of the compile tree then this\n     *                              argument has the root jqLite array so that we can replace nodes\n     *                              on it.\n     * @param {Object=} originalReplaceDirective An optional directive that will be ignored when\n     *                                           compiling the transclusion.\n     * @param {Array.<Function>} preLinkFns\n     * @param {Array.<Function>} postLinkFns\n     * @param {Object} previousCompileContext Context used for previous compilation of the current\n     *                                        node\n     * @returns {Function} linkFn\n     */\n    function applyDirectivesToNode(directives, compileNode, templateAttrs, transcludeFn,\n                                   jqCollection, originalReplaceDirective, preLinkFns, postLinkFns,\n                                   previousCompileContext) {\n      previousCompileContext = previousCompileContext || {};\n\n      var terminalPriority = -Number.MAX_VALUE,\n          newScopeDirective,\n          controllerDirectives = previousCompileContext.controllerDirectives,\n          controllers,\n          newIsolateScopeDirective = previousCompileContext.newIsolateScopeDirective,\n          templateDirective = previousCompileContext.templateDirective,\n          nonTlbTranscludeDirective = previousCompileContext.nonTlbTranscludeDirective,\n          hasTranscludeDirective = false,\n          hasTemplate = false,\n          hasElementTranscludeDirective = previousCompileContext.hasElementTranscludeDirective,\n          $compileNode = templateAttrs.$$element = jqLite(compileNode),\n          directive,\n          directiveName,\n          $template,\n          replaceDirective = originalReplaceDirective,\n          childTranscludeFn = transcludeFn,\n          linkFn,\n          directiveValue;\n\n      // executes all directives on the current element\n      for (var i = 0, ii = directives.length; i < ii; i++) {\n        directive = directives[i];\n        var attrStart = directive.$$start;\n        var attrEnd = directive.$$end;\n\n        // collect multiblock sections\n        if (attrStart) {\n          $compileNode = groupScan(compileNode, attrStart, attrEnd);\n        }\n        $template = undefined;\n\n        if (terminalPriority > directive.priority) {\n          break; // prevent further processing of directives\n        }\n\n        if (directiveValue = directive.scope) {\n\n          // skip the check for directives with async templates, we'll check the derived sync\n          // directive when the template arrives\n          if (!directive.templateUrl) {\n            if (isObject(directiveValue)) {\n              // This directive is trying to add an isolated scope.\n              // Check that there is no scope of any kind already\n              assertNoDuplicate('new/isolated scope', newIsolateScopeDirective || newScopeDirective,\n                                directive, $compileNode);\n              newIsolateScopeDirective = directive;\n            } else {\n              // This directive is trying to add a child scope.\n              // Check that there is no isolated scope already\n              assertNoDuplicate('new/isolated scope', newIsolateScopeDirective, directive,\n                                $compileNode);\n            }\n          }\n\n          newScopeDirective = newScopeDirective || directive;\n        }\n\n        directiveName = directive.name;\n\n        if (!directive.templateUrl && directive.controller) {\n          directiveValue = directive.controller;\n          controllerDirectives = controllerDirectives || {};\n          assertNoDuplicate(\"'\" + directiveName + \"' controller\",\n              controllerDirectives[directiveName], directive, $compileNode);\n          controllerDirectives[directiveName] = directive;\n        }\n\n        if (directiveValue = directive.transclude) {\n          hasTranscludeDirective = true;\n\n          // Special case ngIf and ngRepeat so that we don't complain about duplicate transclusion.\n          // This option should only be used by directives that know how to safely handle element transclusion,\n          // where the transcluded nodes are added or replaced after linking.\n          if (!directive.$$tlb) {\n            assertNoDuplicate('transclusion', nonTlbTranscludeDirective, directive, $compileNode);\n            nonTlbTranscludeDirective = directive;\n          }\n\n          if (directiveValue == 'element') {\n            hasElementTranscludeDirective = true;\n            terminalPriority = directive.priority;\n            $template = $compileNode;\n            $compileNode = templateAttrs.$$element =\n                jqLite(document.createComment(' ' + directiveName + ': ' +\n                                              templateAttrs[directiveName] + ' '));\n            compileNode = $compileNode[0];\n            replaceWith(jqCollection, sliceArgs($template), compileNode);\n\n            childTranscludeFn = compile($template, transcludeFn, terminalPriority,\n                                        replaceDirective && replaceDirective.name, {\n                                          // Don't pass in:\n                                          // - controllerDirectives - otherwise we'll create duplicates controllers\n                                          // - newIsolateScopeDirective or templateDirective - combining templates with\n                                          //   element transclusion doesn't make sense.\n                                          //\n                                          // We need only nonTlbTranscludeDirective so that we prevent putting transclusion\n                                          // on the same element more than once.\n                                          nonTlbTranscludeDirective: nonTlbTranscludeDirective\n                                        });\n          } else {\n            $template = jqLite(jqLiteClone(compileNode)).contents();\n            $compileNode.empty(); // clear contents\n            childTranscludeFn = compile($template, transcludeFn);\n          }\n        }\n\n        if (directive.template) {\n          hasTemplate = true;\n          assertNoDuplicate('template', templateDirective, directive, $compileNode);\n          templateDirective = directive;\n\n          directiveValue = (isFunction(directive.template))\n              ? directive.template($compileNode, templateAttrs)\n              : directive.template;\n\n          directiveValue = denormalizeTemplate(directiveValue);\n\n          if (directive.replace) {\n            replaceDirective = directive;\n            if (jqLiteIsTextNode(directiveValue)) {\n              $template = [];\n            } else {\n              $template = removeComments(wrapTemplate(directive.templateNamespace, trim(directiveValue)));\n            }\n            compileNode = $template[0];\n\n            if ($template.length != 1 || compileNode.nodeType !== NODE_TYPE_ELEMENT) {\n              throw $compileMinErr('tplrt',\n                  \"Template for directive '{0}' must have exactly one root element. {1}\",\n                  directiveName, '');\n            }\n\n            replaceWith(jqCollection, $compileNode, compileNode);\n\n            var newTemplateAttrs = {$attr: {}};\n\n            // combine directives from the original node and from the template:\n            // - take the array of directives for this element\n            // - split it into two parts, those that already applied (processed) and those that weren't (unprocessed)\n            // - collect directives from the template and sort them by priority\n            // - combine directives as: processed + template + unprocessed\n            var templateDirectives = collectDirectives(compileNode, [], newTemplateAttrs);\n            var unprocessedDirectives = directives.splice(i + 1, directives.length - (i + 1));\n\n            if (newIsolateScopeDirective) {\n              markDirectivesAsIsolate(templateDirectives);\n            }\n            directives = directives.concat(templateDirectives).concat(unprocessedDirectives);\n            mergeTemplateAttributes(templateAttrs, newTemplateAttrs);\n\n            ii = directives.length;\n          } else {\n            $compileNode.html(directiveValue);\n          }\n        }\n\n        if (directive.templateUrl) {\n          hasTemplate = true;\n          assertNoDuplicate('template', templateDirective, directive, $compileNode);\n          templateDirective = directive;\n\n          if (directive.replace) {\n            replaceDirective = directive;\n          }\n\n          nodeLinkFn = compileTemplateUrl(directives.splice(i, directives.length - i), $compileNode,\n              templateAttrs, jqCollection, hasTranscludeDirective && childTranscludeFn, preLinkFns, postLinkFns, {\n                controllerDirectives: controllerDirectives,\n                newIsolateScopeDirective: newIsolateScopeDirective,\n                templateDirective: templateDirective,\n                nonTlbTranscludeDirective: nonTlbTranscludeDirective\n              });\n          ii = directives.length;\n        } else if (directive.compile) {\n          try {\n            linkFn = directive.compile($compileNode, templateAttrs, childTranscludeFn);\n            if (isFunction(linkFn)) {\n              addLinkFns(null, linkFn, attrStart, attrEnd);\n            } else if (linkFn) {\n              addLinkFns(linkFn.pre, linkFn.post, attrStart, attrEnd);\n            }\n          } catch (e) {\n            $exceptionHandler(e, startingTag($compileNode));\n          }\n        }\n\n        if (directive.terminal) {\n          nodeLinkFn.terminal = true;\n          terminalPriority = Math.max(terminalPriority, directive.priority);\n        }\n\n      }\n\n      nodeLinkFn.scope = newScopeDirective && newScopeDirective.scope === true;\n      nodeLinkFn.transcludeOnThisElement = hasTranscludeDirective;\n      nodeLinkFn.elementTranscludeOnThisElement = hasElementTranscludeDirective;\n      nodeLinkFn.templateOnThisElement = hasTemplate;\n      nodeLinkFn.transclude = childTranscludeFn;\n\n      previousCompileContext.hasElementTranscludeDirective = hasElementTranscludeDirective;\n\n      // might be normal or delayed nodeLinkFn depending on if templateUrl is present\n      return nodeLinkFn;\n\n      ////////////////////\n\n      function addLinkFns(pre, post, attrStart, attrEnd) {\n        if (pre) {\n          if (attrStart) pre = groupElementsLinkFnWrapper(pre, attrStart, attrEnd);\n          pre.require = directive.require;\n          pre.directiveName = directiveName;\n          if (newIsolateScopeDirective === directive || directive.$$isolateScope) {\n            pre = cloneAndAnnotateFn(pre, {isolateScope: true});\n          }\n          preLinkFns.push(pre);\n        }\n        if (post) {\n          if (attrStart) post = groupElementsLinkFnWrapper(post, attrStart, attrEnd);\n          post.require = directive.require;\n          post.directiveName = directiveName;\n          if (newIsolateScopeDirective === directive || directive.$$isolateScope) {\n            post = cloneAndAnnotateFn(post, {isolateScope: true});\n          }\n          postLinkFns.push(post);\n        }\n      }\n\n\n      function getControllers(directiveName, require, $element, elementControllers) {\n        var value, retrievalMethod = 'data', optional = false;\n        var $searchElement = $element;\n        var match;\n        if (isString(require)) {\n          match = require.match(REQUIRE_PREFIX_REGEXP);\n          require = require.substring(match[0].length);\n\n          if (match[3]) {\n            if (match[1]) match[3] = null;\n            else match[1] = match[3];\n          }\n          if (match[1] === '^') {\n            retrievalMethod = 'inheritedData';\n          } else if (match[1] === '^^') {\n            retrievalMethod = 'inheritedData';\n            $searchElement = $element.parent();\n          }\n          if (match[2] === '?') {\n            optional = true;\n          }\n\n          value = null;\n\n          if (elementControllers && retrievalMethod === 'data') {\n            if (value = elementControllers[require]) {\n              value = value.instance;\n            }\n          }\n          value = value || $searchElement[retrievalMethod]('$' + require + 'Controller');\n\n          if (!value && !optional) {\n            throw $compileMinErr('ctreq',\n                \"Controller '{0}', required by directive '{1}', can't be found!\",\n                require, directiveName);\n          }\n          return value || null;\n        } else if (isArray(require)) {\n          value = [];\n          forEach(require, function(require) {\n            value.push(getControllers(directiveName, require, $element, elementControllers));\n          });\n        }\n        return value;\n      }\n\n\n      function nodeLinkFn(childLinkFn, scope, linkNode, $rootElement, boundTranscludeFn) {\n        var i, ii, linkFn, controller, isolateScope, elementControllers, transcludeFn, $element,\n            attrs;\n\n        if (compileNode === linkNode) {\n          attrs = templateAttrs;\n          $element = templateAttrs.$$element;\n        } else {\n          $element = jqLite(linkNode);\n          attrs = new Attributes($element, templateAttrs);\n        }\n\n        if (newIsolateScopeDirective) {\n          isolateScope = scope.$new(true);\n        }\n\n        if (boundTranscludeFn) {\n          // track `boundTranscludeFn` so it can be unwrapped if `transcludeFn`\n          // is later passed as `parentBoundTranscludeFn` to `publicLinkFn`\n          transcludeFn = controllersBoundTransclude;\n          transcludeFn.$$boundTransclude = boundTranscludeFn;\n        }\n\n        if (controllerDirectives) {\n          // TODO: merge `controllers` and `elementControllers` into single object.\n          controllers = {};\n          elementControllers = {};\n          forEach(controllerDirectives, function(directive) {\n            var locals = {\n              $scope: directive === newIsolateScopeDirective || directive.$$isolateScope ? isolateScope : scope,\n              $element: $element,\n              $attrs: attrs,\n              $transclude: transcludeFn\n            }, controllerInstance;\n\n            controller = directive.controller;\n            if (controller == '@') {\n              controller = attrs[directive.name];\n            }\n\n            controllerInstance = $controller(controller, locals, true, directive.controllerAs);\n\n            // For directives with element transclusion the element is a comment,\n            // but jQuery .data doesn't support attaching data to comment nodes as it's hard to\n            // clean up (http://bugs.jquery.com/ticket/8335).\n            // Instead, we save the controllers for the element in a local hash and attach to .data\n            // later, once we have the actual element.\n            elementControllers[directive.name] = controllerInstance;\n            if (!hasElementTranscludeDirective) {\n              $element.data('$' + directive.name + 'Controller', controllerInstance.instance);\n            }\n\n            controllers[directive.name] = controllerInstance;\n          });\n        }\n\n        if (newIsolateScopeDirective) {\n          compile.$$addScopeInfo($element, isolateScope, true, !(templateDirective && (templateDirective === newIsolateScopeDirective ||\n              templateDirective === newIsolateScopeDirective.$$originalDirective)));\n          compile.$$addScopeClass($element, true);\n\n          var isolateScopeController = controllers && controllers[newIsolateScopeDirective.name];\n          var isolateBindingContext = isolateScope;\n          if (isolateScopeController && isolateScopeController.identifier &&\n              newIsolateScopeDirective.bindToController === true) {\n            isolateBindingContext = isolateScopeController.instance;\n          }\n\n          forEach(isolateScope.$$isolateBindings = newIsolateScopeDirective.$$isolateBindings, function(definition, scopeName) {\n            var attrName = definition.attrName,\n                optional = definition.optional,\n                mode = definition.mode, // @, =, or &\n                lastValue,\n                parentGet, parentSet, compare;\n\n            switch (mode) {\n\n              case '@':\n                attrs.$observe(attrName, function(value) {\n                  isolateBindingContext[scopeName] = value;\n                });\n                attrs.$$observers[attrName].$$scope = scope;\n                if (attrs[attrName]) {\n                  // If the attribute has been provided then we trigger an interpolation to ensure\n                  // the value is there for use in the link fn\n                  isolateBindingContext[scopeName] = $interpolate(attrs[attrName])(scope);\n                }\n                break;\n\n              case '=':\n                if (optional && !attrs[attrName]) {\n                  return;\n                }\n                parentGet = $parse(attrs[attrName]);\n                if (parentGet.literal) {\n                  compare = equals;\n                } else {\n                  compare = function(a, b) { return a === b || (a !== a && b !== b); };\n                }\n                parentSet = parentGet.assign || function() {\n                  // reset the change, or we will throw this exception on every $digest\n                  lastValue = isolateBindingContext[scopeName] = parentGet(scope);\n                  throw $compileMinErr('nonassign',\n                      \"Expression '{0}' used with directive '{1}' is non-assignable!\",\n                      attrs[attrName], newIsolateScopeDirective.name);\n                };\n                lastValue = isolateBindingContext[scopeName] = parentGet(scope);\n                var parentValueWatch = function parentValueWatch(parentValue) {\n                  if (!compare(parentValue, isolateBindingContext[scopeName])) {\n                    // we are out of sync and need to copy\n                    if (!compare(parentValue, lastValue)) {\n                      // parent changed and it has precedence\n                      isolateBindingContext[scopeName] = parentValue;\n                    } else {\n                      // if the parent can be assigned then do so\n                      parentSet(scope, parentValue = isolateBindingContext[scopeName]);\n                    }\n                  }\n                  return lastValue = parentValue;\n                };\n                parentValueWatch.$stateful = true;\n                var unwatch;\n                if (definition.collection) {\n                  unwatch = scope.$watchCollection(attrs[attrName], parentValueWatch);\n                } else {\n                  unwatch = scope.$watch($parse(attrs[attrName], parentValueWatch), null, parentGet.literal);\n                }\n                isolateScope.$on('$destroy', unwatch);\n                break;\n\n              case '&':\n                parentGet = $parse(attrs[attrName]);\n                isolateBindingContext[scopeName] = function(locals) {\n                  return parentGet(scope, locals);\n                };\n                break;\n            }\n          });\n        }\n        if (controllers) {\n          forEach(controllers, function(controller) {\n            controller();\n          });\n          controllers = null;\n        }\n\n        // PRELINKING\n        for (i = 0, ii = preLinkFns.length; i < ii; i++) {\n          linkFn = preLinkFns[i];\n          invokeLinkFn(linkFn,\n              linkFn.isolateScope ? isolateScope : scope,\n              $element,\n              attrs,\n              linkFn.require && getControllers(linkFn.directiveName, linkFn.require, $element, elementControllers),\n              transcludeFn\n          );\n        }\n\n        // RECURSION\n        // We only pass the isolate scope, if the isolate directive has a template,\n        // otherwise the child elements do not belong to the isolate directive.\n        var scopeToChild = scope;\n        if (newIsolateScopeDirective && (newIsolateScopeDirective.template || newIsolateScopeDirective.templateUrl === null)) {\n          scopeToChild = isolateScope;\n        }\n        childLinkFn && childLinkFn(scopeToChild, linkNode.childNodes, undefined, boundTranscludeFn);\n\n        // POSTLINKING\n        for (i = postLinkFns.length - 1; i >= 0; i--) {\n          linkFn = postLinkFns[i];\n          invokeLinkFn(linkFn,\n              linkFn.isolateScope ? isolateScope : scope,\n              $element,\n              attrs,\n              linkFn.require && getControllers(linkFn.directiveName, linkFn.require, $element, elementControllers),\n              transcludeFn\n          );\n        }\n\n        // This is the function that is injected as `$transclude`.\n        // Note: all arguments are optional!\n        function controllersBoundTransclude(scope, cloneAttachFn, futureParentElement) {\n          var transcludeControllers;\n\n          // No scope passed in:\n          if (!isScope(scope)) {\n            futureParentElement = cloneAttachFn;\n            cloneAttachFn = scope;\n            scope = undefined;\n          }\n\n          if (hasElementTranscludeDirective) {\n            transcludeControllers = elementControllers;\n          }\n          if (!futureParentElement) {\n            futureParentElement = hasElementTranscludeDirective ? $element.parent() : $element;\n          }\n          return boundTranscludeFn(scope, cloneAttachFn, transcludeControllers, futureParentElement, scopeToChild);\n        }\n      }\n    }\n\n    function markDirectivesAsIsolate(directives) {\n      // mark all directives as needing isolate scope.\n      for (var j = 0, jj = directives.length; j < jj; j++) {\n        directives[j] = inherit(directives[j], {$$isolateScope: true});\n      }\n    }\n\n    /**\n     * looks up the directive and decorates it with exception handling and proper parameters. We\n     * call this the boundDirective.\n     *\n     * @param {string} name name of the directive to look up.\n     * @param {string} location The directive must be found in specific format.\n     *   String containing any of theses characters:\n     *\n     *   * `E`: element name\n     *   * `A': attribute\n     *   * `C`: class\n     *   * `M`: comment\n     * @returns {boolean} true if directive was added.\n     */\n    function addDirective(tDirectives, name, location, maxPriority, ignoreDirective, startAttrName,\n                          endAttrName) {\n      if (name === ignoreDirective) return null;\n      var match = null;\n      if (hasDirectives.hasOwnProperty(name)) {\n        for (var directive, directives = $injector.get(name + Suffix),\n            i = 0, ii = directives.length; i < ii; i++) {\n          try {\n            directive = directives[i];\n            if ((maxPriority === undefined || maxPriority > directive.priority) &&\n                 directive.restrict.indexOf(location) != -1) {\n              if (startAttrName) {\n                directive = inherit(directive, {$$start: startAttrName, $$end: endAttrName});\n              }\n              tDirectives.push(directive);\n              match = directive;\n            }\n          } catch (e) { $exceptionHandler(e); }\n        }\n      }\n      return match;\n    }\n\n\n    /**\n     * looks up the directive and returns true if it is a multi-element directive,\n     * and therefore requires DOM nodes between -start and -end markers to be grouped\n     * together.\n     *\n     * @param {string} name name of the directive to look up.\n     * @returns true if directive was registered as multi-element.\n     */\n    function directiveIsMultiElement(name) {\n      if (hasDirectives.hasOwnProperty(name)) {\n        for (var directive, directives = $injector.get(name + Suffix),\n            i = 0, ii = directives.length; i < ii; i++) {\n          directive = directives[i];\n          if (directive.multiElement) {\n            return true;\n          }\n        }\n      }\n      return false;\n    }\n\n    /**\n     * When the element is replaced with HTML template then the new attributes\n     * on the template need to be merged with the existing attributes in the DOM.\n     * The desired effect is to have both of the attributes present.\n     *\n     * @param {object} dst destination attributes (original DOM)\n     * @param {object} src source attributes (from the directive template)\n     */\n    function mergeTemplateAttributes(dst, src) {\n      var srcAttr = src.$attr,\n          dstAttr = dst.$attr,\n          $element = dst.$$element;\n\n      // reapply the old attributes to the new element\n      forEach(dst, function(value, key) {\n        if (key.charAt(0) != '$') {\n          if (src[key] && src[key] !== value) {\n            value += (key === 'style' ? ';' : ' ') + src[key];\n          }\n          dst.$set(key, value, true, srcAttr[key]);\n        }\n      });\n\n      // copy the new attributes on the old attrs object\n      forEach(src, function(value, key) {\n        if (key == 'class') {\n          safeAddClass($element, value);\n          dst['class'] = (dst['class'] ? dst['class'] + ' ' : '') + value;\n        } else if (key == 'style') {\n          $element.attr('style', $element.attr('style') + ';' + value);\n          dst['style'] = (dst['style'] ? dst['style'] + ';' : '') + value;\n          // `dst` will never contain hasOwnProperty as DOM parser won't let it.\n          // You will get an \"InvalidCharacterError: DOM Exception 5\" error if you\n          // have an attribute like \"has-own-property\" or \"data-has-own-property\", etc.\n        } else if (key.charAt(0) != '$' && !dst.hasOwnProperty(key)) {\n          dst[key] = value;\n          dstAttr[key] = srcAttr[key];\n        }\n      });\n    }\n\n\n    function compileTemplateUrl(directives, $compileNode, tAttrs,\n        $rootElement, childTranscludeFn, preLinkFns, postLinkFns, previousCompileContext) {\n      var linkQueue = [],\n          afterTemplateNodeLinkFn,\n          afterTemplateChildLinkFn,\n          beforeTemplateCompileNode = $compileNode[0],\n          origAsyncDirective = directives.shift(),\n          derivedSyncDirective = inherit(origAsyncDirective, {\n            templateUrl: null, transclude: null, replace: null, $$originalDirective: origAsyncDirective\n          }),\n          templateUrl = (isFunction(origAsyncDirective.templateUrl))\n              ? origAsyncDirective.templateUrl($compileNode, tAttrs)\n              : origAsyncDirective.templateUrl,\n          templateNamespace = origAsyncDirective.templateNamespace;\n\n      $compileNode.empty();\n\n      $templateRequest($sce.getTrustedResourceUrl(templateUrl))\n        .then(function(content) {\n          var compileNode, tempTemplateAttrs, $template, childBoundTranscludeFn;\n\n          content = denormalizeTemplate(content);\n\n          if (origAsyncDirective.replace) {\n            if (jqLiteIsTextNode(content)) {\n              $template = [];\n            } else {\n              $template = removeComments(wrapTemplate(templateNamespace, trim(content)));\n            }\n            compileNode = $template[0];\n\n            if ($template.length != 1 || compileNode.nodeType !== NODE_TYPE_ELEMENT) {\n              throw $compileMinErr('tplrt',\n                  \"Template for directive '{0}' must have exactly one root element. {1}\",\n                  origAsyncDirective.name, templateUrl);\n            }\n\n            tempTemplateAttrs = {$attr: {}};\n            replaceWith($rootElement, $compileNode, compileNode);\n            var templateDirectives = collectDirectives(compileNode, [], tempTemplateAttrs);\n\n            if (isObject(origAsyncDirective.scope)) {\n              markDirectivesAsIsolate(templateDirectives);\n            }\n            directives = templateDirectives.concat(directives);\n            mergeTemplateAttributes(tAttrs, tempTemplateAttrs);\n          } else {\n            compileNode = beforeTemplateCompileNode;\n            $compileNode.html(content);\n          }\n\n          directives.unshift(derivedSyncDirective);\n\n          afterTemplateNodeLinkFn = applyDirectivesToNode(directives, compileNode, tAttrs,\n              childTranscludeFn, $compileNode, origAsyncDirective, preLinkFns, postLinkFns,\n              previousCompileContext);\n          forEach($rootElement, function(node, i) {\n            if (node == compileNode) {\n              $rootElement[i] = $compileNode[0];\n            }\n          });\n          afterTemplateChildLinkFn = compileNodes($compileNode[0].childNodes, childTranscludeFn);\n\n          while (linkQueue.length) {\n            var scope = linkQueue.shift(),\n                beforeTemplateLinkNode = linkQueue.shift(),\n                linkRootElement = linkQueue.shift(),\n                boundTranscludeFn = linkQueue.shift(),\n                linkNode = $compileNode[0];\n\n            if (scope.$$destroyed) continue;\n\n            if (beforeTemplateLinkNode !== beforeTemplateCompileNode) {\n              var oldClasses = beforeTemplateLinkNode.className;\n\n              if (!(previousCompileContext.hasElementTranscludeDirective &&\n                  origAsyncDirective.replace)) {\n                // it was cloned therefore we have to clone as well.\n                linkNode = jqLiteClone(compileNode);\n              }\n              replaceWith(linkRootElement, jqLite(beforeTemplateLinkNode), linkNode);\n\n              // Copy in CSS classes from original node\n              safeAddClass(jqLite(linkNode), oldClasses);\n            }\n            if (afterTemplateNodeLinkFn.transcludeOnThisElement) {\n              childBoundTranscludeFn = createBoundTranscludeFn(scope, afterTemplateNodeLinkFn.transclude, boundTranscludeFn);\n            } else {\n              childBoundTranscludeFn = boundTranscludeFn;\n            }\n            afterTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, linkNode, $rootElement,\n              childBoundTranscludeFn);\n          }\n          linkQueue = null;\n        });\n\n      return function delayedNodeLinkFn(ignoreChildLinkFn, scope, node, rootElement, boundTranscludeFn) {\n        var childBoundTranscludeFn = boundTranscludeFn;\n        if (scope.$$destroyed) return;\n        if (linkQueue) {\n          linkQueue.push(scope,\n                         node,\n                         rootElement,\n                         childBoundTranscludeFn);\n        } else {\n          if (afterTemplateNodeLinkFn.transcludeOnThisElement) {\n            childBoundTranscludeFn = createBoundTranscludeFn(scope, afterTemplateNodeLinkFn.transclude, boundTranscludeFn);\n          }\n          afterTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, node, rootElement, childBoundTranscludeFn);\n        }\n      };\n    }\n\n\n    /**\n     * Sorting function for bound directives.\n     */\n    function byPriority(a, b) {\n      var diff = b.priority - a.priority;\n      if (diff !== 0) return diff;\n      if (a.name !== b.name) return (a.name < b.name) ? -1 : 1;\n      return a.index - b.index;\n    }\n\n\n    function assertNoDuplicate(what, previousDirective, directive, element) {\n      if (previousDirective) {\n        throw $compileMinErr('multidir', 'Multiple directives [{0}, {1}] asking for {2} on: {3}',\n            previousDirective.name, directive.name, what, startingTag(element));\n      }\n    }\n\n\n    function addTextInterpolateDirective(directives, text) {\n      var interpolateFn = $interpolate(text, true);\n      if (interpolateFn) {\n        directives.push({\n          priority: 0,\n          compile: function textInterpolateCompileFn(templateNode) {\n            var templateNodeParent = templateNode.parent(),\n                hasCompileParent = !!templateNodeParent.length;\n\n            // When transcluding a template that has bindings in the root\n            // we don't have a parent and thus need to add the class during linking fn.\n            if (hasCompileParent) compile.$$addBindingClass(templateNodeParent);\n\n            return function textInterpolateLinkFn(scope, node) {\n              var parent = node.parent();\n              if (!hasCompileParent) compile.$$addBindingClass(parent);\n              compile.$$addBindingInfo(parent, interpolateFn.expressions);\n              scope.$watch(interpolateFn, function interpolateFnWatchAction(value) {\n                node[0].nodeValue = value;\n              });\n            };\n          }\n        });\n      }\n    }\n\n\n    function wrapTemplate(type, template) {\n      type = lowercase(type || 'html');\n      switch (type) {\n      case 'svg':\n      case 'math':\n        var wrapper = document.createElement('div');\n        wrapper.innerHTML = '<' + type + '>' + template + '</' + type + '>';\n        return wrapper.childNodes[0].childNodes;\n      default:\n        return template;\n      }\n    }\n\n\n    function getTrustedContext(node, attrNormalizedName) {\n      if (attrNormalizedName == \"srcdoc\") {\n        return $sce.HTML;\n      }\n      var tag = nodeName_(node);\n      // maction[xlink:href] can source SVG.  It's not limited to <maction>.\n      if (attrNormalizedName == \"xlinkHref\" ||\n          (tag == \"form\" && attrNormalizedName == \"action\") ||\n          (tag != \"img\" && (attrNormalizedName == \"src\" ||\n                            attrNormalizedName == \"ngSrc\"))) {\n        return $sce.RESOURCE_URL;\n      }\n    }\n\n\n    function addAttrInterpolateDirective(node, directives, value, name, allOrNothing) {\n      var trustedContext = getTrustedContext(node, name);\n      allOrNothing = ALL_OR_NOTHING_ATTRS[name] || allOrNothing;\n\n      var interpolateFn = $interpolate(value, true, trustedContext, allOrNothing);\n\n      // no interpolation found -> ignore\n      if (!interpolateFn) return;\n\n\n      if (name === \"multiple\" && nodeName_(node) === \"select\") {\n        throw $compileMinErr(\"selmulti\",\n            \"Binding to the 'multiple' attribute is not supported. Element: {0}\",\n            startingTag(node));\n      }\n\n      directives.push({\n        priority: 100,\n        compile: function() {\n            return {\n              pre: function attrInterpolatePreLinkFn(scope, element, attr) {\n                var $$observers = (attr.$$observers || (attr.$$observers = {}));\n\n                if (EVENT_HANDLER_ATTR_REGEXP.test(name)) {\n                  throw $compileMinErr('nodomevents',\n                      \"Interpolations for HTML DOM event attributes are disallowed.  Please use the \" +\n                          \"ng- versions (such as ng-click instead of onclick) instead.\");\n                }\n\n                // If the attribute has changed since last $interpolate()ed\n                var newValue = attr[name];\n                if (newValue !== value) {\n                  // we need to interpolate again since the attribute value has been updated\n                  // (e.g. by another directive's compile function)\n                  // ensure unset/empty values make interpolateFn falsy\n                  interpolateFn = newValue && $interpolate(newValue, true, trustedContext, allOrNothing);\n                  value = newValue;\n                }\n\n                // if attribute was updated so that there is no interpolation going on we don't want to\n                // register any observers\n                if (!interpolateFn) return;\n\n                // initialize attr object so that it's ready in case we need the value for isolate\n                // scope initialization, otherwise the value would not be available from isolate\n                // directive's linking fn during linking phase\n                attr[name] = interpolateFn(scope);\n\n                ($$observers[name] || ($$observers[name] = [])).$$inter = true;\n                (attr.$$observers && attr.$$observers[name].$$scope || scope).\n                  $watch(interpolateFn, function interpolateFnWatchAction(newValue, oldValue) {\n                    //special case for class attribute addition + removal\n                    //so that class changes can tap into the animation\n                    //hooks provided by the $animate service. Be sure to\n                    //skip animations when the first digest occurs (when\n                    //both the new and the old values are the same) since\n                    //the CSS classes are the non-interpolated values\n                    if (name === 'class' && newValue != oldValue) {\n                      attr.$updateClass(newValue, oldValue);\n                    } else {\n                      attr.$set(name, newValue);\n                    }\n                  });\n              }\n            };\n          }\n      });\n    }\n\n\n    /**\n     * This is a special jqLite.replaceWith, which can replace items which\n     * have no parents, provided that the containing jqLite collection is provided.\n     *\n     * @param {JqLite=} $rootElement The root of the compile tree. Used so that we can replace nodes\n     *                               in the root of the tree.\n     * @param {JqLite} elementsToRemove The jqLite element which we are going to replace. We keep\n     *                                  the shell, but replace its DOM node reference.\n     * @param {Node} newNode The new DOM node.\n     */\n    function replaceWith($rootElement, elementsToRemove, newNode) {\n      var firstElementToRemove = elementsToRemove[0],\n          removeCount = elementsToRemove.length,\n          parent = firstElementToRemove.parentNode,\n          i, ii;\n\n      if ($rootElement) {\n        for (i = 0, ii = $rootElement.length; i < ii; i++) {\n          if ($rootElement[i] == firstElementToRemove) {\n            $rootElement[i++] = newNode;\n            for (var j = i, j2 = j + removeCount - 1,\n                     jj = $rootElement.length;\n                 j < jj; j++, j2++) {\n              if (j2 < jj) {\n                $rootElement[j] = $rootElement[j2];\n              } else {\n                delete $rootElement[j];\n              }\n            }\n            $rootElement.length -= removeCount - 1;\n\n            // If the replaced element is also the jQuery .context then replace it\n            // .context is a deprecated jQuery api, so we should set it only when jQuery set it\n            // http://api.jquery.com/context/\n            if ($rootElement.context === firstElementToRemove) {\n              $rootElement.context = newNode;\n            }\n            break;\n          }\n        }\n      }\n\n      if (parent) {\n        parent.replaceChild(newNode, firstElementToRemove);\n      }\n\n      // TODO(perf): what's this document fragment for? is it needed? can we at least reuse it?\n      var fragment = document.createDocumentFragment();\n      fragment.appendChild(firstElementToRemove);\n\n      // Copy over user data (that includes Angular's $scope etc.). Don't copy private\n      // data here because there's no public interface in jQuery to do that and copying over\n      // event listeners (which is the main use of private data) wouldn't work anyway.\n      jqLite(newNode).data(jqLite(firstElementToRemove).data());\n\n      // Remove data of the replaced element. We cannot just call .remove()\n      // on the element it since that would deallocate scope that is needed\n      // for the new node. Instead, remove the data \"manually\".\n      if (!jQuery) {\n        delete jqLite.cache[firstElementToRemove[jqLite.expando]];\n      } else {\n        // jQuery 2.x doesn't expose the data storage. Use jQuery.cleanData to clean up after\n        // the replaced element. The cleanData version monkey-patched by Angular would cause\n        // the scope to be trashed and we do need the very same scope to work with the new\n        // element. However, we cannot just cache the non-patched version and use it here as\n        // that would break if another library patches the method after Angular does (one\n        // example is jQuery UI). Instead, set a flag indicating scope destroying should be\n        // skipped this one time.\n        skipDestroyOnNextJQueryCleanData = true;\n        jQuery.cleanData([firstElementToRemove]);\n      }\n\n      for (var k = 1, kk = elementsToRemove.length; k < kk; k++) {\n        var element = elementsToRemove[k];\n        jqLite(element).remove(); // must do this way to clean up expando\n        fragment.appendChild(element);\n        delete elementsToRemove[k];\n      }\n\n      elementsToRemove[0] = newNode;\n      elementsToRemove.length = 1;\n    }\n\n\n    function cloneAndAnnotateFn(fn, annotation) {\n      return extend(function() { return fn.apply(null, arguments); }, fn, annotation);\n    }\n\n\n    function invokeLinkFn(linkFn, scope, $element, attrs, controllers, transcludeFn) {\n      try {\n        linkFn(scope, $element, attrs, controllers, transcludeFn);\n      } catch (e) {\n        $exceptionHandler(e, startingTag($element));\n      }\n    }\n  }];\n}\n\nvar PREFIX_REGEXP = /^((?:x|data)[\\:\\-_])/i;\n/**\n * Converts all accepted directives format into proper directive name.\n * @param name Name to normalize\n */\nfunction directiveNormalize(name) {\n  return camelCase(name.replace(PREFIX_REGEXP, ''));\n}\n\n/**\n * @ngdoc type\n * @name $compile.directive.Attributes\n *\n * @description\n * A shared object between directive compile / linking functions which contains normalized DOM\n * element attributes. The values reflect current binding state `{{ }}`. The normalization is\n * needed since all of these are treated as equivalent in Angular:\n *\n * ```\n *    <span ng:bind=\"a\" ng-bind=\"a\" data-ng-bind=\"a\" x-ng-bind=\"a\">\n * ```\n */\n\n/**\n * @ngdoc property\n * @name $compile.directive.Attributes#$attr\n *\n * @description\n * A map of DOM element attribute names to the normalized name. This is\n * needed to do reverse lookup from normalized name back to actual name.\n */\n\n\n/**\n * @ngdoc method\n * @name $compile.directive.Attributes#$set\n * @kind function\n *\n * @description\n * Set DOM element attribute value.\n *\n *\n * @param {string} name Normalized element attribute name of the property to modify. The name is\n *          reverse-translated using the {@link ng.$compile.directive.Attributes#$attr $attr}\n *          property to the original name.\n * @param {string} value Value to set the attribute to. The value can be an interpolated string.\n */\n\n\n\n/**\n * Closure compiler type information\n */\n\nfunction nodesetLinkingFn(\n  /* angular.Scope */ scope,\n  /* NodeList */ nodeList,\n  /* Element */ rootElement,\n  /* function(Function) */ boundTranscludeFn\n) {}\n\nfunction directiveLinkingFn(\n  /* nodesetLinkingFn */ nodesetLinkingFn,\n  /* angular.Scope */ scope,\n  /* Node */ node,\n  /* Element */ rootElement,\n  /* function(Function) */ boundTranscludeFn\n) {}\n\nfunction tokenDifference(str1, str2) {\n  var values = '',\n      tokens1 = str1.split(/\\s+/),\n      tokens2 = str2.split(/\\s+/);\n\n  outer:\n  for (var i = 0; i < tokens1.length; i++) {\n    var token = tokens1[i];\n    for (var j = 0; j < tokens2.length; j++) {\n      if (token == tokens2[j]) continue outer;\n    }\n    values += (values.length > 0 ? ' ' : '') + token;\n  }\n  return values;\n}\n\nfunction removeComments(jqNodes) {\n  jqNodes = jqLite(jqNodes);\n  var i = jqNodes.length;\n\n  if (i <= 1) {\n    return jqNodes;\n  }\n\n  while (i--) {\n    var node = jqNodes[i];\n    if (node.nodeType === NODE_TYPE_COMMENT) {\n      splice.call(jqNodes, i, 1);\n    }\n  }\n  return jqNodes;\n}\n\nvar $controllerMinErr = minErr('$controller');\n\n/**\n * @ngdoc provider\n * @name $controllerProvider\n * @description\n * The {@link ng.$controller $controller service} is used by Angular to create new\n * controllers.\n *\n * This provider allows controller registration via the\n * {@link ng.$controllerProvider#register register} method.\n */\nfunction $ControllerProvider() {\n  var controllers = {},\n      globals = false,\n      CNTRL_REG = /^(\\S+)(\\s+as\\s+(\\w+))?$/;\n\n\n  /**\n   * @ngdoc method\n   * @name $controllerProvider#register\n   * @param {string|Object} name Controller name, or an object map of controllers where the keys are\n   *    the names and the values are the constructors.\n   * @param {Function|Array} constructor Controller constructor fn (optionally decorated with DI\n   *    annotations in the array notation).\n   */\n  this.register = function(name, constructor) {\n    assertNotHasOwnProperty(name, 'controller');\n    if (isObject(name)) {\n      extend(controllers, name);\n    } else {\n      controllers[name] = constructor;\n    }\n  };\n\n  /**\n   * @ngdoc method\n   * @name $controllerProvider#allowGlobals\n   * @description If called, allows `$controller` to find controller constructors on `window`\n   */\n  this.allowGlobals = function() {\n    globals = true;\n  };\n\n\n  this.$get = ['$injector', '$window', function($injector, $window) {\n\n    /**\n     * @ngdoc service\n     * @name $controller\n     * @requires $injector\n     *\n     * @param {Function|string} constructor If called with a function then it's considered to be the\n     *    controller constructor function. Otherwise it's considered to be a string which is used\n     *    to retrieve the controller constructor using the following steps:\n     *\n     *    * check if a controller with given name is registered via `$controllerProvider`\n     *    * check if evaluating the string on the current scope returns a constructor\n     *    * if $controllerProvider#allowGlobals, check `window[constructor]` on the global\n     *      `window` object (not recommended)\n     *\n     *    The string can use the `controller as property` syntax, where the controller instance is published\n     *    as the specified property on the `scope`; the `scope` must be injected into `locals` param for this\n     *    to work correctly.\n     *\n     * @param {Object} locals Injection locals for Controller.\n     * @return {Object} Instance of given controller.\n     *\n     * @description\n     * `$controller` service is responsible for instantiating controllers.\n     *\n     * It's just a simple call to {@link auto.$injector $injector}, but extracted into\n     * a service, so that one can override this service with [BC version](https://gist.github.com/1649788).\n     */\n    return function(expression, locals, later, ident) {\n      // PRIVATE API:\n      //   param `later` --- indicates that the controller's constructor is invoked at a later time.\n      //                     If true, $controller will allocate the object with the correct\n      //                     prototype chain, but will not invoke the controller until a returned\n      //                     callback is invoked.\n      //   param `ident` --- An optional label which overrides the label parsed from the controller\n      //                     expression, if any.\n      var instance, match, constructor, identifier;\n      later = later === true;\n      if (ident && isString(ident)) {\n        identifier = ident;\n      }\n\n      if (isString(expression)) {\n        match = expression.match(CNTRL_REG);\n        if (!match) {\n          throw $controllerMinErr('ctrlfmt',\n            \"Badly formed controller string '{0}'. \" +\n            \"Must match `__name__ as __id__` or `__name__`.\", expression);\n        }\n        constructor = match[1],\n        identifier = identifier || match[3];\n        expression = controllers.hasOwnProperty(constructor)\n            ? controllers[constructor]\n            : getter(locals.$scope, constructor, true) ||\n                (globals ? getter($window, constructor, true) : undefined);\n\n        assertArgFn(expression, constructor, true);\n      }\n\n      if (later) {\n        // Instantiate controller later:\n        // This machinery is used to create an instance of the object before calling the\n        // controller's constructor itself.\n        //\n        // This allows properties to be added to the controller before the constructor is\n        // invoked. Primarily, this is used for isolate scope bindings in $compile.\n        //\n        // This feature is not intended for use by applications, and is thus not documented\n        // publicly.\n        // Object creation: http://jsperf.com/create-constructor/2\n        var controllerPrototype = (isArray(expression) ?\n          expression[expression.length - 1] : expression).prototype;\n        instance = Object.create(controllerPrototype || null);\n\n        if (identifier) {\n          addIdentifier(locals, identifier, instance, constructor || expression.name);\n        }\n\n        return extend(function() {\n          $injector.invoke(expression, instance, locals, constructor);\n          return instance;\n        }, {\n          instance: instance,\n          identifier: identifier\n        });\n      }\n\n      instance = $injector.instantiate(expression, locals, constructor);\n\n      if (identifier) {\n        addIdentifier(locals, identifier, instance, constructor || expression.name);\n      }\n\n      return instance;\n    };\n\n    function addIdentifier(locals, identifier, instance, name) {\n      if (!(locals && isObject(locals.$scope))) {\n        throw minErr('$controller')('noscp',\n          \"Cannot export controller '{0}' as '{1}'! No $scope object provided via `locals`.\",\n          name, identifier);\n      }\n\n      locals.$scope[identifier] = instance;\n    }\n  }];\n}\n\n/**\n * @ngdoc service\n * @name $document\n * @requires $window\n *\n * @description\n * A {@link angular.element jQuery or jqLite} wrapper for the browser's `window.document` object.\n *\n * @example\n   <example module=\"documentExample\">\n     <file name=\"index.html\">\n       <div ng-controller=\"ExampleController\">\n         <p>$document title: <b ng-bind=\"title\"></b></p>\n         <p>window.document title: <b ng-bind=\"windowTitle\"></b></p>\n       </div>\n     </file>\n     <file name=\"script.js\">\n       angular.module('documentExample', [])\n         .controller('ExampleController', ['$scope', '$document', function($scope, $document) {\n           $scope.title = $document[0].title;\n           $scope.windowTitle = angular.element(window.document)[0].title;\n         }]);\n     </file>\n   </example>\n */\nfunction $DocumentProvider() {\n  this.$get = ['$window', function(window) {\n    return jqLite(window.document);\n  }];\n}\n\n/**\n * @ngdoc service\n * @name $exceptionHandler\n * @requires ng.$log\n *\n * @description\n * Any uncaught exception in angular expressions is delegated to this service.\n * The default implementation simply delegates to `$log.error` which logs it into\n * the browser console.\n *\n * In unit tests, if `angular-mocks.js` is loaded, this service is overridden by\n * {@link ngMock.$exceptionHandler mock $exceptionHandler} which aids in testing.\n *\n * ## Example:\n *\n * ```js\n *   angular.module('exceptionOverride', []).factory('$exceptionHandler', function() {\n *     return function(exception, cause) {\n *       exception.message += ' (caused by \"' + cause + '\")';\n *       throw exception;\n *     };\n *   });\n * ```\n *\n * This example will override the normal action of `$exceptionHandler`, to make angular\n * exceptions fail hard when they happen, instead of just logging to the console.\n *\n * <hr />\n * Note, that code executed in event-listeners (even those registered using jqLite's `on`/`bind`\n * methods) does not delegate exceptions to the {@link ng.$exceptionHandler $exceptionHandler}\n * (unless executed during a digest).\n *\n * If you wish, you can manually delegate exceptions, e.g.\n * `try { ... } catch(e) { $exceptionHandler(e); }`\n *\n * @param {Error} exception Exception associated with the error.\n * @param {string=} cause optional information about the context in which\n *       the error was thrown.\n *\n */\nfunction $ExceptionHandlerProvider() {\n  this.$get = ['$log', function($log) {\n    return function(exception, cause) {\n      $log.error.apply($log, arguments);\n    };\n  }];\n}\n\nvar APPLICATION_JSON = 'application/json';\nvar CONTENT_TYPE_APPLICATION_JSON = {'Content-Type': APPLICATION_JSON + ';charset=utf-8'};\nvar JSON_START = /^\\[|^\\{(?!\\{)/;\nvar JSON_ENDS = {\n  '[': /]$/,\n  '{': /}$/\n};\nvar JSON_PROTECTION_PREFIX = /^\\)\\]\\}',?\\n/;\n\nfunction defaultHttpResponseTransform(data, headers) {\n  if (isString(data)) {\n    // Strip json vulnerability protection prefix and trim whitespace\n    var tempData = data.replace(JSON_PROTECTION_PREFIX, '').trim();\n\n    if (tempData) {\n      var contentType = headers('Content-Type');\n      if ((contentType && (contentType.indexOf(APPLICATION_JSON) === 0)) || isJsonLike(tempData)) {\n        data = fromJson(tempData);\n      }\n    }\n  }\n\n  return data;\n}\n\nfunction isJsonLike(str) {\n    var jsonStart = str.match(JSON_START);\n    return jsonStart && JSON_ENDS[jsonStart[0]].test(str);\n}\n\n/**\n * Parse headers into key value object\n *\n * @param {string} headers Raw headers as a string\n * @returns {Object} Parsed headers as key value object\n */\nfunction parseHeaders(headers) {\n  var parsed = createMap(), key, val, i;\n\n  if (!headers) return parsed;\n\n  forEach(headers.split('\\n'), function(line) {\n    i = line.indexOf(':');\n    key = lowercase(trim(line.substr(0, i)));\n    val = trim(line.substr(i + 1));\n\n    if (key) {\n      parsed[key] = parsed[key] ? parsed[key] + ', ' + val : val;\n    }\n  });\n\n  return parsed;\n}\n\n\n/**\n * Returns a function that provides access to parsed headers.\n *\n * Headers are lazy parsed when first requested.\n * @see parseHeaders\n *\n * @param {(string|Object)} headers Headers to provide access to.\n * @returns {function(string=)} Returns a getter function which if called with:\n *\n *   - if called with single an argument returns a single header value or null\n *   - if called with no arguments returns an object containing all headers.\n */\nfunction headersGetter(headers) {\n  var headersObj = isObject(headers) ? headers : undefined;\n\n  return function(name) {\n    if (!headersObj) headersObj =  parseHeaders(headers);\n\n    if (name) {\n      var value = headersObj[lowercase(name)];\n      if (value === void 0) {\n        value = null;\n      }\n      return value;\n    }\n\n    return headersObj;\n  };\n}\n\n\n/**\n * Chain all given functions\n *\n * This function is used for both request and response transforming\n *\n * @param {*} data Data to transform.\n * @param {function(string=)} headers HTTP headers getter fn.\n * @param {number} status HTTP status code of the response.\n * @param {(Function|Array.<Function>)} fns Function or an array of functions.\n * @returns {*} Transformed data.\n */\nfunction transformData(data, headers, status, fns) {\n  if (isFunction(fns))\n    return fns(data, headers, status);\n\n  forEach(fns, function(fn) {\n    data = fn(data, headers, status);\n  });\n\n  return data;\n}\n\n\nfunction isSuccess(status) {\n  return 200 <= status && status < 300;\n}\n\n\n/**\n * @ngdoc provider\n * @name $httpProvider\n * @description\n * Use `$httpProvider` to change the default behavior of the {@link ng.$http $http} service.\n * */\nfunction $HttpProvider() {\n  /**\n   * @ngdoc property\n   * @name $httpProvider#defaults\n   * @description\n   *\n   * Object containing default values for all {@link ng.$http $http} requests.\n   *\n   * - **`defaults.cache`** - {Object} - an object built with {@link ng.$cacheFactory `$cacheFactory`}\n   * that will provide the cache for all requests who set their `cache` property to `true`.\n   * If you set the `default.cache = false` then only requests that specify their own custom\n   * cache object will be cached. See {@link $http#caching $http Caching} for more information.\n   *\n   * - **`defaults.xsrfCookieName`** - {string} - Name of cookie containing the XSRF token.\n   * Defaults value is `'XSRF-TOKEN'`.\n   *\n   * - **`defaults.xsrfHeaderName`** - {string} - Name of HTTP header to populate with the\n   * XSRF token. Defaults value is `'X-XSRF-TOKEN'`.\n   *\n   * - **`defaults.headers`** - {Object} - Default headers for all $http requests.\n   * Refer to {@link ng.$http#setting-http-headers $http} for documentation on\n   * setting default headers.\n   *     - **`defaults.headers.common`**\n   *     - **`defaults.headers.post`**\n   *     - **`defaults.headers.put`**\n   *     - **`defaults.headers.patch`**\n   *\n   **/\n  var defaults = this.defaults = {\n    // transform incoming response data\n    transformResponse: [defaultHttpResponseTransform],\n\n    // transform outgoing request data\n    transformRequest: [function(d) {\n      return isObject(d) && !isFile(d) && !isBlob(d) && !isFormData(d) ? toJson(d) : d;\n    }],\n\n    // default headers\n    headers: {\n      common: {\n        'Accept': 'application/json, text/plain, */*'\n      },\n      post:   shallowCopy(CONTENT_TYPE_APPLICATION_JSON),\n      put:    shallowCopy(CONTENT_TYPE_APPLICATION_JSON),\n      patch:  shallowCopy(CONTENT_TYPE_APPLICATION_JSON)\n    },\n\n    xsrfCookieName: 'XSRF-TOKEN',\n    xsrfHeaderName: 'X-XSRF-TOKEN'\n  };\n\n  var useApplyAsync = false;\n  /**\n   * @ngdoc method\n   * @name $httpProvider#useApplyAsync\n   * @description\n   *\n   * Configure $http service to combine processing of multiple http responses received at around\n   * the same time via {@link ng.$rootScope.Scope#$applyAsync $rootScope.$applyAsync}. This can result in\n   * significant performance improvement for bigger applications that make many HTTP requests\n   * concurrently (common during application bootstrap).\n   *\n   * Defaults to false. If no value is specifed, returns the current configured value.\n   *\n   * @param {boolean=} value If true, when requests are loaded, they will schedule a deferred\n   *    \"apply\" on the next tick, giving time for subsequent requests in a roughly ~10ms window\n   *    to load and share the same digest cycle.\n   *\n   * @returns {boolean|Object} If a value is specified, returns the $httpProvider for chaining.\n   *    otherwise, returns the current configured value.\n   **/\n  this.useApplyAsync = function(value) {\n    if (isDefined(value)) {\n      useApplyAsync = !!value;\n      return this;\n    }\n    return useApplyAsync;\n  };\n\n  /**\n   * @ngdoc property\n   * @name $httpProvider#interceptors\n   * @description\n   *\n   * Array containing service factories for all synchronous or asynchronous {@link ng.$http $http}\n   * pre-processing of request or postprocessing of responses.\n   *\n   * These service factories are ordered by request, i.e. they are applied in the same order as the\n   * array, on request, but reverse order, on response.\n   *\n   * {@link ng.$http#interceptors Interceptors detailed info}\n   **/\n  var interceptorFactories = this.interceptors = [];\n\n  this.$get = ['$httpBackend', '$browser', '$cacheFactory', '$rootScope', '$q', '$injector',\n      function($httpBackend, $browser, $cacheFactory, $rootScope, $q, $injector) {\n\n    var defaultCache = $cacheFactory('$http');\n\n    /**\n     * Interceptors stored in reverse order. Inner interceptors before outer interceptors.\n     * The reversal is needed so that we can build up the interception chain around the\n     * server request.\n     */\n    var reversedInterceptors = [];\n\n    forEach(interceptorFactories, function(interceptorFactory) {\n      reversedInterceptors.unshift(isString(interceptorFactory)\n          ? $injector.get(interceptorFactory) : $injector.invoke(interceptorFactory));\n    });\n\n    /**\n     * @ngdoc service\n     * @kind function\n     * @name $http\n     * @requires ng.$httpBackend\n     * @requires $cacheFactory\n     * @requires $rootScope\n     * @requires $q\n     * @requires $injector\n     *\n     * @description\n     * The `$http` service is a core Angular service that facilitates communication with the remote\n     * HTTP servers via the browser's [XMLHttpRequest](https://developer.mozilla.org/en/xmlhttprequest)\n     * object or via [JSONP](http://en.wikipedia.org/wiki/JSONP).\n     *\n     * For unit testing applications that use `$http` service, see\n     * {@link ngMock.$httpBackend $httpBackend mock}.\n     *\n     * For a higher level of abstraction, please check out the {@link ngResource.$resource\n     * $resource} service.\n     *\n     * The $http API is based on the {@link ng.$q deferred/promise APIs} exposed by\n     * the $q service. While for simple usage patterns this doesn't matter much, for advanced usage\n     * it is important to familiarize yourself with these APIs and the guarantees they provide.\n     *\n     *\n     * ## General usage\n     * The `$http` service is a function which takes a single argument — a configuration object —\n     * that is used to generate an HTTP request and returns  a {@link ng.$q promise}\n     * with two $http specific methods: `success` and `error`.\n     *\n     * ```js\n     *   // Simple GET request example :\n     *   $http.get('/someUrl').\n     *     success(function(data, status, headers, config) {\n     *       // this callback will be called asynchronously\n     *       // when the response is available\n     *     }).\n     *     error(function(data, status, headers, config) {\n     *       // called asynchronously if an error occurs\n     *       // or server returns response with an error status.\n     *     });\n     * ```\n     *\n     * ```js\n     *   // Simple POST request example (passing data) :\n     *   $http.post('/someUrl', {msg:'hello word!'}).\n     *     success(function(data, status, headers, config) {\n     *       // this callback will be called asynchronously\n     *       // when the response is available\n     *     }).\n     *     error(function(data, status, headers, config) {\n     *       // called asynchronously if an error occurs\n     *       // or server returns response with an error status.\n     *     });\n     * ```\n     *\n     *\n     * Since the returned value of calling the $http function is a `promise`, you can also use\n     * the `then` method to register callbacks, and these callbacks will receive a single argument –\n     * an object representing the response. See the API signature and type info below for more\n     * details.\n     *\n     * A response status code between 200 and 299 is considered a success status and\n     * will result in the success callback being called. Note that if the response is a redirect,\n     * XMLHttpRequest will transparently follow it, meaning that the error callback will not be\n     * called for such responses.\n     *\n     * ## Writing Unit Tests that use $http\n     * When unit testing (using {@link ngMock ngMock}), it is necessary to call\n     * {@link ngMock.$httpBackend#flush $httpBackend.flush()} to flush each pending\n     * request using trained responses.\n     *\n     * ```\n     * $httpBackend.expectGET(...);\n     * $http.get(...);\n     * $httpBackend.flush();\n     * ```\n     *\n     * ## Shortcut methods\n     *\n     * Shortcut methods are also available. All shortcut methods require passing in the URL, and\n     * request data must be passed in for POST/PUT requests.\n     *\n     * ```js\n     *   $http.get('/someUrl').success(successCallback);\n     *   $http.post('/someUrl', data).success(successCallback);\n     * ```\n     *\n     * Complete list of shortcut methods:\n     *\n     * - {@link ng.$http#get $http.get}\n     * - {@link ng.$http#head $http.head}\n     * - {@link ng.$http#post $http.post}\n     * - {@link ng.$http#put $http.put}\n     * - {@link ng.$http#delete $http.delete}\n     * - {@link ng.$http#jsonp $http.jsonp}\n     * - {@link ng.$http#patch $http.patch}\n     *\n     *\n     * ## Setting HTTP Headers\n     *\n     * The $http service will automatically add certain HTTP headers to all requests. These defaults\n     * can be fully configured by accessing the `$httpProvider.defaults.headers` configuration\n     * object, which currently contains this default configuration:\n     *\n     * - `$httpProvider.defaults.headers.common` (headers that are common for all requests):\n     *   - `Accept: application/json, text/plain, * / *`\n     * - `$httpProvider.defaults.headers.post`: (header defaults for POST requests)\n     *   - `Content-Type: application/json`\n     * - `$httpProvider.defaults.headers.put` (header defaults for PUT requests)\n     *   - `Content-Type: application/json`\n     *\n     * To add or overwrite these defaults, simply add or remove a property from these configuration\n     * objects. To add headers for an HTTP method other than POST or PUT, simply add a new object\n     * with the lowercased HTTP method name as the key, e.g.\n     * `$httpProvider.defaults.headers.get = { 'My-Header' : 'value' }.\n     *\n     * The defaults can also be set at runtime via the `$http.defaults` object in the same\n     * fashion. For example:\n     *\n     * ```\n     * module.run(function($http) {\n     *   $http.defaults.headers.common.Authorization = 'Basic YmVlcDpib29w'\n     * });\n     * ```\n     *\n     * In addition, you can supply a `headers` property in the config object passed when\n     * calling `$http(config)`, which overrides the defaults without changing them globally.\n     *\n     * To explicitly remove a header automatically added via $httpProvider.defaults.headers on a per request basis,\n     * Use the `headers` property, setting the desired header to `undefined`. For example:\n     *\n     * ```js\n     * var req = {\n     *  method: 'POST',\n     *  url: 'http://example.com',\n     *  headers: {\n     *    'Content-Type': undefined\n     *  },\n     *  data: { test: 'test' },\n     * }\n     *\n     * $http(req).success(function(){...}).error(function(){...});\n     * ```\n     *\n     * ## Transforming Requests and Responses\n     *\n     * Both requests and responses can be transformed using transformation functions: `transformRequest`\n     * and `transformResponse`. These properties can be a single function that returns\n     * the transformed value (`function(data, headersGetter, status)`) or an array of such transformation functions,\n     * which allows you to `push` or `unshift` a new transformation function into the transformation chain.\n     *\n     * ### Default Transformations\n     *\n     * The `$httpProvider` provider and `$http` service expose `defaults.transformRequest` and\n     * `defaults.transformResponse` properties. If a request does not provide its own transformations\n     * then these will be applied.\n     *\n     * You can augment or replace the default transformations by modifying these properties by adding to or\n     * replacing the array.\n     *\n     * Angular provides the following default transformations:\n     *\n     * Request transformations (`$httpProvider.defaults.transformRequest` and `$http.defaults.transformRequest`):\n     *\n     * - If the `data` property of the request configuration object contains an object, serialize it\n     *   into JSON format.\n     *\n     * Response transformations (`$httpProvider.defaults.transformResponse` and `$http.defaults.transformResponse`):\n     *\n     *  - If XSRF prefix is detected, strip it (see Security Considerations section below).\n     *  - If JSON response is detected, deserialize it using a JSON parser.\n     *\n     *\n     * ### Overriding the Default Transformations Per Request\n     *\n     * If you wish override the request/response transformations only for a single request then provide\n     * `transformRequest` and/or `transformResponse` properties on the configuration object passed\n     * into `$http`.\n     *\n     * Note that if you provide these properties on the config object the default transformations will be\n     * overwritten. If you wish to augment the default transformations then you must include them in your\n     * local transformation array.\n     *\n     * The following code demonstrates adding a new response transformation to be run after the default response\n     * transformations have been run.\n     *\n     * ```js\n     * function appendTransform(defaults, transform) {\n     *\n     *   // We can't guarantee that the default transformation is an array\n     *   defaults = angular.isArray(defaults) ? defaults : [defaults];\n     *\n     *   // Append the new transformation to the defaults\n     *   return defaults.concat(transform);\n     * }\n     *\n     * $http({\n     *   url: '...',\n     *   method: 'GET',\n     *   transformResponse: appendTransform($http.defaults.transformResponse, function(value) {\n     *     return doTransform(value);\n     *   })\n     * });\n     * ```\n     *\n     *\n     * ## Caching\n     *\n     * To enable caching, set the request configuration `cache` property to `true` (to use default\n     * cache) or to a custom cache object (built with {@link ng.$cacheFactory `$cacheFactory`}).\n     * When the cache is enabled, `$http` stores the response from the server in the specified\n     * cache. The next time the same request is made, the response is served from the cache without\n     * sending a request to the server.\n     *\n     * Note that even if the response is served from cache, delivery of the data is asynchronous in\n     * the same way that real requests are.\n     *\n     * If there are multiple GET requests for the same URL that should be cached using the same\n     * cache, but the cache is not populated yet, only one request to the server will be made and\n     * the remaining requests will be fulfilled using the response from the first request.\n     *\n     * You can change the default cache to a new object (built with\n     * {@link ng.$cacheFactory `$cacheFactory`}) by updating the\n     * {@link ng.$http#defaults `$http.defaults.cache`} property. All requests who set\n     * their `cache` property to `true` will now use this cache object.\n     *\n     * If you set the default cache to `false` then only requests that specify their own custom\n     * cache object will be cached.\n     *\n     * ## Interceptors\n     *\n     * Before you start creating interceptors, be sure to understand the\n     * {@link ng.$q $q and deferred/promise APIs}.\n     *\n     * For purposes of global error handling, authentication, or any kind of synchronous or\n     * asynchronous pre-processing of request or postprocessing of responses, it is desirable to be\n     * able to intercept requests before they are handed to the server and\n     * responses before they are handed over to the application code that\n     * initiated these requests. The interceptors leverage the {@link ng.$q\n     * promise APIs} to fulfill this need for both synchronous and asynchronous pre-processing.\n     *\n     * The interceptors are service factories that are registered with the `$httpProvider` by\n     * adding them to the `$httpProvider.interceptors` array. The factory is called and\n     * injected with dependencies (if specified) and returns the interceptor.\n     *\n     * There are two kinds of interceptors (and two kinds of rejection interceptors):\n     *\n     *   * `request`: interceptors get called with a http `config` object. The function is free to\n     *     modify the `config` object or create a new one. The function needs to return the `config`\n     *     object directly, or a promise containing the `config` or a new `config` object.\n     *   * `requestError`: interceptor gets called when a previous interceptor threw an error or\n     *     resolved with a rejection.\n     *   * `response`: interceptors get called with http `response` object. The function is free to\n     *     modify the `response` object or create a new one. The function needs to return the `response`\n     *     object directly, or as a promise containing the `response` or a new `response` object.\n     *   * `responseError`: interceptor gets called when a previous interceptor threw an error or\n     *     resolved with a rejection.\n     *\n     *\n     * ```js\n     *   // register the interceptor as a service\n     *   $provide.factory('myHttpInterceptor', function($q, dependency1, dependency2) {\n     *     return {\n     *       // optional method\n     *       'request': function(config) {\n     *         // do something on success\n     *         return config;\n     *       },\n     *\n     *       // optional method\n     *      'requestError': function(rejection) {\n     *         // do something on error\n     *         if (canRecover(rejection)) {\n     *           return responseOrNewPromise\n     *         }\n     *         return $q.reject(rejection);\n     *       },\n     *\n     *\n     *\n     *       // optional method\n     *       'response': function(response) {\n     *         // do something on success\n     *         return response;\n     *       },\n     *\n     *       // optional method\n     *      'responseError': function(rejection) {\n     *         // do something on error\n     *         if (canRecover(rejection)) {\n     *           return responseOrNewPromise\n     *         }\n     *         return $q.reject(rejection);\n     *       }\n     *     };\n     *   });\n     *\n     *   $httpProvider.interceptors.push('myHttpInterceptor');\n     *\n     *\n     *   // alternatively, register the interceptor via an anonymous factory\n     *   $httpProvider.interceptors.push(function($q, dependency1, dependency2) {\n     *     return {\n     *      'request': function(config) {\n     *          // same as above\n     *       },\n     *\n     *       'response': function(response) {\n     *          // same as above\n     *       }\n     *     };\n     *   });\n     * ```\n     *\n     * ## Security Considerations\n     *\n     * When designing web applications, consider security threats from:\n     *\n     * - [JSON vulnerability](http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx)\n     * - [XSRF](http://en.wikipedia.org/wiki/Cross-site_request_forgery)\n     *\n     * Both server and the client must cooperate in order to eliminate these threats. Angular comes\n     * pre-configured with strategies that address these issues, but for this to work backend server\n     * cooperation is required.\n     *\n     * ### JSON Vulnerability Protection\n     *\n     * A [JSON vulnerability](http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx)\n     * allows third party website to turn your JSON resource URL into\n     * [JSONP](http://en.wikipedia.org/wiki/JSONP) request under some conditions. To\n     * counter this your server can prefix all JSON requests with following string `\")]}',\\n\"`.\n     * Angular will automatically strip the prefix before processing it as JSON.\n     *\n     * For example if your server needs to return:\n     * ```js\n     * ['one','two']\n     * ```\n     *\n     * which is vulnerable to attack, your server can return:\n     * ```js\n     * )]}',\n     * ['one','two']\n     * ```\n     *\n     * Angular will strip the prefix, before processing the JSON.\n     *\n     *\n     * ### Cross Site Request Forgery (XSRF) Protection\n     *\n     * [XSRF](http://en.wikipedia.org/wiki/Cross-site_request_forgery) is a technique by which\n     * an unauthorized site can gain your user's private data. Angular provides a mechanism\n     * to counter XSRF. When performing XHR requests, the $http service reads a token from a cookie\n     * (by default, `XSRF-TOKEN`) and sets it as an HTTP header (`X-XSRF-TOKEN`). Since only\n     * JavaScript that runs on your domain could read the cookie, your server can be assured that\n     * the XHR came from JavaScript running on your domain. The header will not be set for\n     * cross-domain requests.\n     *\n     * To take advantage of this, your server needs to set a token in a JavaScript readable session\n     * cookie called `XSRF-TOKEN` on the first HTTP GET request. On subsequent XHR requests the\n     * server can verify that the cookie matches `X-XSRF-TOKEN` HTTP header, and therefore be sure\n     * that only JavaScript running on your domain could have sent the request. The token must be\n     * unique for each user and must be verifiable by the server (to prevent the JavaScript from\n     * making up its own tokens). We recommend that the token is a digest of your site's\n     * authentication cookie with a [salt](https://en.wikipedia.org/wiki/Salt_(cryptography&#41;)\n     * for added security.\n     *\n     * The name of the headers can be specified using the xsrfHeaderName and xsrfCookieName\n     * properties of either $httpProvider.defaults at config-time, $http.defaults at run-time,\n     * or the per-request config object.\n     *\n     *\n     * @param {object} config Object describing the request to be made and how it should be\n     *    processed. The object has following properties:\n     *\n     *    - **method** – `{string}` – HTTP method (e.g. 'GET', 'POST', etc)\n     *    - **url** – `{string}` – Absolute or relative URL of the resource that is being requested.\n     *    - **params** – `{Object.<string|Object>}` – Map of strings or objects which will be turned\n     *      to `?key1=value1&key2=value2` after the url. If the value is not a string, it will be\n     *      JSONified.\n     *    - **data** – `{string|Object}` – Data to be sent as the request message data.\n     *    - **headers** – `{Object}` – Map of strings or functions which return strings representing\n     *      HTTP headers to send to the server. If the return value of a function is null, the\n     *      header will not be sent.\n     *    - **xsrfHeaderName** – `{string}` – Name of HTTP header to populate with the XSRF token.\n     *    - **xsrfCookieName** – `{string}` – Name of cookie containing the XSRF token.\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     *      See {@link ng.$http#overriding-the-default-transformations-per-request\n     *      Overriding the Default Transformations}\n     *    - **transformResponse** –\n     *      `{function(data, headersGetter, status)|Array.<function(data, headersGetter, status)>}` –\n     *      transform function or an array of such functions. The transform function takes the http\n     *      response body, headers and status and returns its transformed (typically deserialized) version.\n     *      See {@link ng.$http#overriding-the-default-transformations-per-request\n     *      Overriding the Default Transformations}\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}\n     *      that should abort the request when resolved.\n     *    - **withCredentials** - `{boolean}` - whether to set the `withCredentials` flag on the\n     *      XHR object. See [requests with credentials](https://developer.mozilla.org/docs/Web/HTTP/Access_control_CORS#Requests_with_credentials)\n     *      for more information.\n     *    - **responseType** - `{string}` - see\n     *      [requestType](https://developer.mozilla.org/en-US/docs/DOM/XMLHttpRequest#responseType).\n     *\n     * @returns {HttpPromise} Returns a {@link ng.$q promise} object with the\n     *   standard `then` method and two http specific methods: `success` and `error`. The `then`\n     *   method takes two arguments a success and an error callback which will be called with a\n     *   response object. The `success` and `error` methods take a single argument - a function that\n     *   will be called when the request succeeds or fails respectively. The arguments passed into\n     *   these functions are destructured representation of the response object passed into the\n     *   `then` method. The response object has these properties:\n     *\n     *   - **data** – `{string|Object}` – The response body transformed with the transform\n     *     functions.\n     *   - **status** – `{number}` – HTTP status code of the response.\n     *   - **headers** – `{function([headerName])}` – Header getter function.\n     *   - **config** – `{Object}` – The configuration object that was used to generate the request.\n     *   - **statusText** – `{string}` – HTTP status text of the response.\n     *\n     * @property {Array.<Object>} pendingRequests Array of config objects for currently pending\n     *   requests. This is primarily meant to be used for debugging purposes.\n     *\n     *\n     * @example\n<example module=\"httpExample\">\n<file name=\"index.html\">\n  <div ng-controller=\"FetchController\">\n    <select ng-model=\"method\">\n      <option>GET</option>\n      <option>JSONP</option>\n    </select>\n    <input type=\"text\" ng-model=\"url\" size=\"80\"/>\n    <button id=\"fetchbtn\" ng-click=\"fetch()\">fetch</button><br>\n    <button id=\"samplegetbtn\" ng-click=\"updateModel('GET', 'http-hello.html')\">Sample GET</button>\n    <button id=\"samplejsonpbtn\"\n      ng-click=\"updateModel('JSONP',\n                    'https://angularjs.org/greet.php?callback=JSON_CALLBACK&name=Super%20Hero')\">\n      Sample JSONP\n    </button>\n    <button id=\"invalidjsonpbtn\"\n      ng-click=\"updateModel('JSONP', 'https://angularjs.org/doesntexist&callback=JSON_CALLBACK')\">\n        Invalid JSONP\n      </button>\n    <pre>http status code: {{status}}</pre>\n    <pre>http response data: {{data}}</pre>\n  </div>\n</file>\n<file name=\"script.js\">\n  angular.module('httpExample', [])\n    .controller('FetchController', ['$scope', '$http', '$templateCache',\n      function($scope, $http, $templateCache) {\n        $scope.method = 'GET';\n        $scope.url = 'http-hello.html';\n\n        $scope.fetch = function() {\n          $scope.code = null;\n          $scope.response = null;\n\n          $http({method: $scope.method, url: $scope.url, cache: $templateCache}).\n            success(function(data, status) {\n              $scope.status = status;\n              $scope.data = data;\n            }).\n            error(function(data, status) {\n              $scope.data = data || \"Request failed\";\n              $scope.status = status;\n          });\n        };\n\n        $scope.updateModel = function(method, url) {\n          $scope.method = method;\n          $scope.url = url;\n        };\n      }]);\n</file>\n<file name=\"http-hello.html\">\n  Hello, $http!\n</file>\n<file name=\"protractor.js\" type=\"protractor\">\n  var status = element(by.binding('status'));\n  var data = element(by.binding('data'));\n  var fetchBtn = element(by.id('fetchbtn'));\n  var sampleGetBtn = element(by.id('samplegetbtn'));\n  var sampleJsonpBtn = element(by.id('samplejsonpbtn'));\n  var invalidJsonpBtn = element(by.id('invalidjsonpbtn'));\n\n  it('should make an xhr GET request', function() {\n    sampleGetBtn.click();\n    fetchBtn.click();\n    expect(status.getText()).toMatch('200');\n    expect(data.getText()).toMatch(/Hello, \\$http!/);\n  });\n\n// Commented out due to flakes. See https://github.com/angular/angular.js/issues/9185\n// it('should make a JSONP request to angularjs.org', function() {\n//   sampleJsonpBtn.click();\n//   fetchBtn.click();\n//   expect(status.getText()).toMatch('200');\n//   expect(data.getText()).toMatch(/Super Hero!/);\n// });\n\n  it('should make JSONP request to invalid URL and invoke the error handler',\n      function() {\n    invalidJsonpBtn.click();\n    fetchBtn.click();\n    expect(status.getText()).toMatch('0');\n    expect(data.getText()).toMatch('Request failed');\n  });\n</file>\n</example>\n     */\n    function $http(requestConfig) {\n\n      if (!angular.isObject(requestConfig)) {\n        throw minErr('$http')('badreq', 'Http request configuration must be an object.  Received: {0}', requestConfig);\n      }\n\n      var config = extend({\n        method: 'get',\n        transformRequest: defaults.transformRequest,\n        transformResponse: defaults.transformResponse\n      }, requestConfig);\n\n      config.headers = mergeHeaders(requestConfig);\n      config.method = uppercase(config.method);\n\n      var serverRequest = function(config) {\n        var headers = config.headers;\n        var reqData = transformData(config.data, headersGetter(headers), undefined, config.transformRequest);\n\n        // strip content-type if data is undefined\n        if (isUndefined(reqData)) {\n          forEach(headers, function(value, header) {\n            if (lowercase(header) === 'content-type') {\n                delete headers[header];\n            }\n          });\n        }\n\n        if (isUndefined(config.withCredentials) && !isUndefined(defaults.withCredentials)) {\n          config.withCredentials = defaults.withCredentials;\n        }\n\n        // send request\n        return sendReq(config, reqData).then(transformResponse, transformResponse);\n      };\n\n      var chain = [serverRequest, undefined];\n      var promise = $q.when(config);\n\n      // apply interceptors\n      forEach(reversedInterceptors, function(interceptor) {\n        if (interceptor.request || interceptor.requestError) {\n          chain.unshift(interceptor.request, interceptor.requestError);\n        }\n        if (interceptor.response || interceptor.responseError) {\n          chain.push(interceptor.response, interceptor.responseError);\n        }\n      });\n\n      while (chain.length) {\n        var thenFn = chain.shift();\n        var rejectFn = chain.shift();\n\n        promise = promise.then(thenFn, rejectFn);\n      }\n\n      promise.success = function(fn) {\n        promise.then(function(response) {\n          fn(response.data, response.status, response.headers, config);\n        });\n        return promise;\n      };\n\n      promise.error = function(fn) {\n        promise.then(null, function(response) {\n          fn(response.data, response.status, response.headers, config);\n        });\n        return promise;\n      };\n\n      return promise;\n\n      function transformResponse(response) {\n        // make a copy since the response must be cacheable\n        var resp = extend({}, response);\n        if (!response.data) {\n          resp.data = response.data;\n        } else {\n          resp.data = transformData(response.data, response.headers, response.status, config.transformResponse);\n        }\n        return (isSuccess(response.status))\n          ? resp\n          : $q.reject(resp);\n      }\n\n      function executeHeaderFns(headers) {\n        var headerContent, processedHeaders = {};\n\n        forEach(headers, function(headerFn, header) {\n          if (isFunction(headerFn)) {\n            headerContent = headerFn();\n            if (headerContent != null) {\n              processedHeaders[header] = headerContent;\n            }\n          } else {\n            processedHeaders[header] = headerFn;\n          }\n        });\n\n        return processedHeaders;\n      }\n\n      function mergeHeaders(config) {\n        var defHeaders = defaults.headers,\n            reqHeaders = extend({}, config.headers),\n            defHeaderName, lowercaseDefHeaderName, reqHeaderName;\n\n        defHeaders = extend({}, defHeaders.common, defHeaders[lowercase(config.method)]);\n\n        // using for-in instead of forEach to avoid unecessary iteration after header has been found\n        defaultHeadersIteration:\n        for (defHeaderName in defHeaders) {\n          lowercaseDefHeaderName = lowercase(defHeaderName);\n\n          for (reqHeaderName in reqHeaders) {\n            if (lowercase(reqHeaderName) === lowercaseDefHeaderName) {\n              continue defaultHeadersIteration;\n            }\n          }\n\n          reqHeaders[defHeaderName] = defHeaders[defHeaderName];\n        }\n\n        // execute if header value is a function for merged headers\n        return executeHeaderFns(reqHeaders);\n      }\n    }\n\n    $http.pendingRequests = [];\n\n    /**\n     * @ngdoc method\n     * @name $http#get\n     *\n     * @description\n     * Shortcut method to perform `GET` request.\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name $http#delete\n     *\n     * @description\n     * Shortcut method to perform `DELETE` request.\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name $http#head\n     *\n     * @description\n     * Shortcut method to perform `HEAD` request.\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name $http#jsonp\n     *\n     * @description\n     * Shortcut method to perform `JSONP` request.\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request.\n     *                     The name of the callback should be the string `JSON_CALLBACK`.\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n    createShortMethods('get', 'delete', 'head', 'jsonp');\n\n    /**\n     * @ngdoc method\n     * @name $http#post\n     *\n     * @description\n     * Shortcut method to perform `POST` request.\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {*} data Request content\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name $http#put\n     *\n     * @description\n     * Shortcut method to perform `PUT` request.\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {*} data Request content\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n     /**\n      * @ngdoc method\n      * @name $http#patch\n      *\n      * @description\n      * Shortcut method to perform `PATCH` request.\n      *\n      * @param {string} url Relative or absolute URL specifying the destination of the request\n      * @param {*} data Request content\n      * @param {Object=} config Optional configuration object\n      * @returns {HttpPromise} Future object\n      */\n    createShortMethodsWithData('post', 'put', 'patch');\n\n        /**\n         * @ngdoc property\n         * @name $http#defaults\n         *\n         * @description\n         * Runtime equivalent of the `$httpProvider.defaults` property. Allows configuration of\n         * default headers, withCredentials as well as request and response transformations.\n         *\n         * See \"Setting HTTP Headers\" and \"Transforming Requests and Responses\" sections above.\n         */\n    $http.defaults = defaults;\n\n\n    return $http;\n\n\n    function createShortMethods(names) {\n      forEach(arguments, function(name) {\n        $http[name] = function(url, config) {\n          return $http(extend(config || {}, {\n            method: name,\n            url: url\n          }));\n        };\n      });\n    }\n\n\n    function createShortMethodsWithData(name) {\n      forEach(arguments, function(name) {\n        $http[name] = function(url, data, config) {\n          return $http(extend(config || {}, {\n            method: name,\n            url: url,\n            data: data\n          }));\n        };\n      });\n    }\n\n\n    /**\n     * Makes the request.\n     *\n     * !!! ACCESSES CLOSURE VARS:\n     * $httpBackend, defaults, $log, $rootScope, defaultCache, $http.pendingRequests\n     */\n    function sendReq(config, reqData) {\n      var deferred = $q.defer(),\n          promise = deferred.promise,\n          cache,\n          cachedResp,\n          reqHeaders = config.headers,\n          url = buildUrl(config.url, config.params);\n\n      $http.pendingRequests.push(config);\n      promise.then(removePendingReq, removePendingReq);\n\n\n      if ((config.cache || defaults.cache) && config.cache !== false &&\n          (config.method === 'GET' || config.method === 'JSONP')) {\n        cache = isObject(config.cache) ? config.cache\n              : isObject(defaults.cache) ? defaults.cache\n              : defaultCache;\n      }\n\n      if (cache) {\n        cachedResp = cache.get(url);\n        if (isDefined(cachedResp)) {\n          if (isPromiseLike(cachedResp)) {\n            // cached request has already been sent, but there is no response yet\n            cachedResp.then(resolvePromiseWithResult, resolvePromiseWithResult);\n          } else {\n            // serving from cache\n            if (isArray(cachedResp)) {\n              resolvePromise(cachedResp[1], cachedResp[0], shallowCopy(cachedResp[2]), cachedResp[3]);\n            } else {\n              resolvePromise(cachedResp, 200, {}, 'OK');\n            }\n          }\n        } else {\n          // put the promise for the non-transformed response into cache as a placeholder\n          cache.put(url, promise);\n        }\n      }\n\n\n      // if we won't have the response in cache, set the xsrf headers and\n      // send the request to the backend\n      if (isUndefined(cachedResp)) {\n        var xsrfValue = urlIsSameOrigin(config.url)\n            ? $browser.cookies()[config.xsrfCookieName || defaults.xsrfCookieName]\n            : undefined;\n        if (xsrfValue) {\n          reqHeaders[(config.xsrfHeaderName || defaults.xsrfHeaderName)] = xsrfValue;\n        }\n\n        $httpBackend(config.method, url, reqData, done, reqHeaders, config.timeout,\n            config.withCredentials, config.responseType);\n      }\n\n      return promise;\n\n\n      /**\n       * Callback registered to $httpBackend():\n       *  - caches the response if desired\n       *  - resolves the raw $http promise\n       *  - calls $apply\n       */\n      function done(status, response, headersString, statusText) {\n        if (cache) {\n          if (isSuccess(status)) {\n            cache.put(url, [status, response, parseHeaders(headersString), statusText]);\n          } else {\n            // remove promise from the cache\n            cache.remove(url);\n          }\n        }\n\n        function resolveHttpPromise() {\n          resolvePromise(response, status, headersString, statusText);\n        }\n\n        if (useApplyAsync) {\n          $rootScope.$applyAsync(resolveHttpPromise);\n        } else {\n          resolveHttpPromise();\n          if (!$rootScope.$$phase) $rootScope.$apply();\n        }\n      }\n\n\n      /**\n       * Resolves the raw $http promise.\n       */\n      function resolvePromise(response, status, headers, statusText) {\n        // normalize internal statuses to 0\n        status = Math.max(status, 0);\n\n        (isSuccess(status) ? deferred.resolve : deferred.reject)({\n          data: response,\n          status: status,\n          headers: headersGetter(headers),\n          config: config,\n          statusText: statusText\n        });\n      }\n\n      function resolvePromiseWithResult(result) {\n        resolvePromise(result.data, result.status, shallowCopy(result.headers()), result.statusText);\n      }\n\n      function removePendingReq() {\n        var idx = $http.pendingRequests.indexOf(config);\n        if (idx !== -1) $http.pendingRequests.splice(idx, 1);\n      }\n    }\n\n\n    function buildUrl(url, params) {\n      if (!params) return url;\n      var parts = [];\n      forEachSorted(params, function(value, key) {\n        if (value === null || isUndefined(value)) return;\n        if (!isArray(value)) value = [value];\n\n        forEach(value, function(v) {\n          if (isObject(v)) {\n            if (isDate(v)) {\n              v = v.toISOString();\n            } else {\n              v = toJson(v);\n            }\n          }\n          parts.push(encodeUriQuery(key) + '=' +\n                     encodeUriQuery(v));\n        });\n      });\n      if (parts.length > 0) {\n        url += ((url.indexOf('?') == -1) ? '?' : '&') + parts.join('&');\n      }\n      return url;\n    }\n  }];\n}\n\nfunction createXhr() {\n    return new window.XMLHttpRequest();\n}\n\n/**\n * @ngdoc service\n * @name $httpBackend\n * @requires $window\n * @requires $document\n *\n * @description\n * HTTP backend used by the {@link ng.$http service} that delegates to\n * XMLHttpRequest object or JSONP and deals with browser incompatibilities.\n *\n * You should never need to use this service directly, instead use the higher-level abstractions:\n * {@link ng.$http $http} or {@link ngResource.$resource $resource}.\n *\n * During testing this implementation is swapped with {@link ngMock.$httpBackend mock\n * $httpBackend} which can be trained with responses.\n */\nfunction $HttpBackendProvider() {\n  this.$get = ['$browser', '$window', '$document', function($browser, $window, $document) {\n    return createHttpBackend($browser, createXhr, $browser.defer, $window.angular.callbacks, $document[0]);\n  }];\n}\n\nfunction createHttpBackend($browser, createXhr, $browserDefer, callbacks, rawDocument) {\n  // TODO(vojta): fix the signature\n  return function(method, url, post, callback, headers, timeout, withCredentials, responseType) {\n    $browser.$$incOutstandingRequestCount();\n    url = url || $browser.url();\n\n    if (lowercase(method) == 'jsonp') {\n      var callbackId = '_' + (callbacks.counter++).toString(36);\n      callbacks[callbackId] = function(data) {\n        callbacks[callbackId].data = data;\n        callbacks[callbackId].called = true;\n      };\n\n      var jsonpDone = jsonpReq(url.replace('JSON_CALLBACK', 'angular.callbacks.' + callbackId),\n          callbackId, function(status, text) {\n        completeRequest(callback, status, callbacks[callbackId].data, \"\", text);\n        callbacks[callbackId] = noop;\n      });\n    } else {\n\n      var xhr = createXhr();\n\n      xhr.open(method, url, true);\n      forEach(headers, function(value, key) {\n        if (isDefined(value)) {\n            xhr.setRequestHeader(key, value);\n        }\n      });\n\n      xhr.onload = function requestLoaded() {\n        var statusText = xhr.statusText || '';\n\n        // responseText is the old-school way of retrieving response (supported by IE8 & 9)\n        // response/responseType properties were introduced in XHR Level2 spec (supported by IE10)\n        var response = ('response' in xhr) ? xhr.response : xhr.responseText;\n\n        // normalize IE9 bug (http://bugs.jquery.com/ticket/1450)\n        var status = xhr.status === 1223 ? 204 : xhr.status;\n\n        // fix status code when it is 0 (0 status is undocumented).\n        // Occurs when accessing file resources or on Android 4.1 stock browser\n        // while retrieving files from application cache.\n        if (status === 0) {\n          status = response ? 200 : urlResolve(url).protocol == 'file' ? 404 : 0;\n        }\n\n        completeRequest(callback,\n            status,\n            response,\n            xhr.getAllResponseHeaders(),\n            statusText);\n      };\n\n      var requestError = function() {\n        // The response is always empty\n        // See https://xhr.spec.whatwg.org/#request-error-steps and https://fetch.spec.whatwg.org/#concept-network-error\n        completeRequest(callback, -1, null, null, '');\n      };\n\n      xhr.onerror = requestError;\n      xhr.onabort = requestError;\n\n      if (withCredentials) {\n        xhr.withCredentials = true;\n      }\n\n      if (responseType) {\n        try {\n          xhr.responseType = responseType;\n        } catch (e) {\n          // WebKit added support for the json responseType value on 09/03/2013\n          // https://bugs.webkit.org/show_bug.cgi?id=73648. Versions of Safari prior to 7 are\n          // known to throw when setting the value \"json\" as the response type. Other older\n          // browsers implementing the responseType\n          //\n          // The json response type can be ignored if not supported, because JSON payloads are\n          // parsed on the client-side regardless.\n          if (responseType !== 'json') {\n            throw e;\n          }\n        }\n      }\n\n      xhr.send(post || null);\n    }\n\n    if (timeout > 0) {\n      var timeoutId = $browserDefer(timeoutRequest, timeout);\n    } else if (isPromiseLike(timeout)) {\n      timeout.then(timeoutRequest);\n    }\n\n\n    function timeoutRequest() {\n      jsonpDone && jsonpDone();\n      xhr && xhr.abort();\n    }\n\n    function completeRequest(callback, status, response, headersString, statusText) {\n      // cancel timeout and subsequent timeout promise resolution\n      if (timeoutId !== undefined) {\n        $browserDefer.cancel(timeoutId);\n      }\n      jsonpDone = xhr = null;\n\n      callback(status, response, headersString, statusText);\n      $browser.$$completeOutstandingRequest(noop);\n    }\n  };\n\n  function jsonpReq(url, callbackId, done) {\n    // we can't use jQuery/jqLite here because jQuery does crazy shit with script elements, e.g.:\n    // - fetches local scripts via XHR and evals them\n    // - adds and immediately removes script elements from the document\n    var script = rawDocument.createElement('script'), callback = null;\n    script.type = \"text/javascript\";\n    script.src = url;\n    script.async = true;\n\n    callback = function(event) {\n      removeEventListenerFn(script, \"load\", callback);\n      removeEventListenerFn(script, \"error\", callback);\n      rawDocument.body.removeChild(script);\n      script = null;\n      var status = -1;\n      var text = \"unknown\";\n\n      if (event) {\n        if (event.type === \"load\" && !callbacks[callbackId].called) {\n          event = { type: \"error\" };\n        }\n        text = event.type;\n        status = event.type === \"error\" ? 404 : 200;\n      }\n\n      if (done) {\n        done(status, text);\n      }\n    };\n\n    addEventListenerFn(script, \"load\", callback);\n    addEventListenerFn(script, \"error\", callback);\n    rawDocument.body.appendChild(script);\n    return callback;\n  }\n}\n\nvar $interpolateMinErr = minErr('$interpolate');\n\n/**\n * @ngdoc provider\n * @name $interpolateProvider\n *\n * @description\n *\n * Used for configuring the interpolation markup. Defaults to `{{` and `}}`.\n *\n * @example\n<example module=\"customInterpolationApp\">\n<file name=\"index.html\">\n<script>\n  var customInterpolationApp = angular.module('customInterpolationApp', []);\n\n  customInterpolationApp.config(function($interpolateProvider) {\n    $interpolateProvider.startSymbol('//');\n    $interpolateProvider.endSymbol('//');\n  });\n\n\n  customInterpolationApp.controller('DemoController', function() {\n      this.label = \"This binding is brought you by // interpolation symbols.\";\n  });\n</script>\n<div ng-app=\"App\" ng-controller=\"DemoController as demo\">\n    //demo.label//\n</div>\n</file>\n<file name=\"protractor.js\" type=\"protractor\">\n  it('should interpolate binding with custom symbols', function() {\n    expect(element(by.binding('demo.label')).getText()).toBe('This binding is brought you by // interpolation symbols.');\n  });\n</file>\n</example>\n */\nfunction $InterpolateProvider() {\n  var startSymbol = '{{';\n  var endSymbol = '}}';\n\n  /**\n   * @ngdoc method\n   * @name $interpolateProvider#startSymbol\n   * @description\n   * Symbol to denote start of expression in the interpolated string. Defaults to `{{`.\n   *\n   * @param {string=} value new value to set the starting symbol to.\n   * @returns {string|self} Returns the symbol when used as getter and self if used as setter.\n   */\n  this.startSymbol = function(value) {\n    if (value) {\n      startSymbol = value;\n      return this;\n    } else {\n      return startSymbol;\n    }\n  };\n\n  /**\n   * @ngdoc method\n   * @name $interpolateProvider#endSymbol\n   * @description\n   * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.\n   *\n   * @param {string=} value new value to set the ending symbol to.\n   * @returns {string|self} Returns the symbol when used as getter and self if used as setter.\n   */\n  this.endSymbol = function(value) {\n    if (value) {\n      endSymbol = value;\n      return this;\n    } else {\n      return endSymbol;\n    }\n  };\n\n\n  this.$get = ['$parse', '$exceptionHandler', '$sce', function($parse, $exceptionHandler, $sce) {\n    var startSymbolLength = startSymbol.length,\n        endSymbolLength = endSymbol.length,\n        escapedStartRegexp = new RegExp(startSymbol.replace(/./g, escape), 'g'),\n        escapedEndRegexp = new RegExp(endSymbol.replace(/./g, escape), 'g');\n\n    function escape(ch) {\n      return '\\\\\\\\\\\\' + ch;\n    }\n\n    /**\n     * @ngdoc service\n     * @name $interpolate\n     * @kind function\n     *\n     * @requires $parse\n     * @requires $sce\n     *\n     * @description\n     *\n     * Compiles a string with markup into an interpolation function. This service is used by the\n     * HTML {@link ng.$compile $compile} service for data binding. See\n     * {@link ng.$interpolateProvider $interpolateProvider} for configuring the\n     * interpolation markup.\n     *\n     *\n     * ```js\n     *   var $interpolate = ...; // injected\n     *   var exp = $interpolate('Hello {{name | uppercase}}!');\n     *   expect(exp({name:'Angular'}).toEqual('Hello ANGULAR!');\n     * ```\n     *\n     * `$interpolate` takes an optional fourth argument, `allOrNothing`. If `allOrNothing` is\n     * `true`, the interpolation function will return `undefined` unless all embedded expressions\n     * evaluate to a value other than `undefined`.\n     *\n     * ```js\n     *   var $interpolate = ...; // injected\n     *   var context = {greeting: 'Hello', name: undefined };\n     *\n     *   // default \"forgiving\" mode\n     *   var exp = $interpolate('{{greeting}} {{name}}!');\n     *   expect(exp(context)).toEqual('Hello !');\n     *\n     *   // \"allOrNothing\" mode\n     *   exp = $interpolate('{{greeting}} {{name}}!', false, null, true);\n     *   expect(exp(context)).toBeUndefined();\n     *   context.name = 'Angular';\n     *   expect(exp(context)).toEqual('Hello Angular!');\n     * ```\n     *\n     * `allOrNothing` is useful for interpolating URLs. `ngSrc` and `ngSrcset` use this behavior.\n     *\n     * ####Escaped Interpolation\n     * $interpolate provides a mechanism for escaping interpolation markers. Start and end markers\n     * can be escaped by preceding each of their characters with a REVERSE SOLIDUS U+005C (backslash).\n     * It will be rendered as a regular start/end marker, and will not be interpreted as an expression\n     * or binding.\n     *\n     * This enables web-servers to prevent script injection attacks and defacing attacks, to some\n     * degree, while also enabling code examples to work without relying on the\n     * {@link ng.directive:ngNonBindable ngNonBindable} directive.\n     *\n     * **For security purposes, it is strongly encouraged that web servers escape user-supplied data,\n     * replacing angle brackets (&lt;, &gt;) with &amp;lt; and &amp;gt; respectively, and replacing all\n     * interpolation start/end markers with their escaped counterparts.**\n     *\n     * Escaped interpolation markers are only replaced with the actual interpolation markers in rendered\n     * output when the $interpolate service processes the text. So, for HTML elements interpolated\n     * by {@link ng.$compile $compile}, or otherwise interpolated with the `mustHaveExpression` parameter\n     * set to `true`, the interpolated text must contain an unescaped interpolation expression. As such,\n     * this is typically useful only when user-data is used in rendering a template from the server, or\n     * when otherwise untrusted data is used by a directive.\n     *\n     * <example>\n     *  <file name=\"index.html\">\n     *    <div ng-init=\"username='A user'\">\n     *      <p ng-init=\"apptitle='Escaping demo'\">{{apptitle}}: \\{\\{ username = \"defaced value\"; \\}\\}\n     *        </p>\n     *      <p><strong>{{username}}</strong> attempts to inject code which will deface the\n     *        application, but fails to accomplish their task, because the server has correctly\n     *        escaped the interpolation start/end markers with REVERSE SOLIDUS U+005C (backslash)\n     *        characters.</p>\n     *      <p>Instead, the result of the attempted script injection is visible, and can be removed\n     *        from the database by an administrator.</p>\n     *    </div>\n     *  </file>\n     * </example>\n     *\n     * @param {string} text The text with markup to interpolate.\n     * @param {boolean=} mustHaveExpression if set to true then the interpolation string must have\n     *    embedded expression in order to return an interpolation function. Strings with no\n     *    embedded expression will return null for the interpolation function.\n     * @param {string=} trustedContext when provided, the returned function passes the interpolated\n     *    result through {@link ng.$sce#getTrusted $sce.getTrusted(interpolatedResult,\n     *    trustedContext)} before returning it.  Refer to the {@link ng.$sce $sce} service that\n     *    provides Strict Contextual Escaping for details.\n     * @param {boolean=} allOrNothing if `true`, then the returned function returns undefined\n     *    unless all embedded expressions evaluate to a value other than `undefined`.\n     * @returns {function(context)} an interpolation function which is used to compute the\n     *    interpolated string. The function has these parameters:\n     *\n     * - `context`: evaluation context for all expressions embedded in the interpolated text\n     */\n    function $interpolate(text, mustHaveExpression, trustedContext, allOrNothing) {\n      allOrNothing = !!allOrNothing;\n      var startIndex,\n          endIndex,\n          index = 0,\n          expressions = [],\n          parseFns = [],\n          textLength = text.length,\n          exp,\n          concat = [],\n          expressionPositions = [];\n\n      while (index < textLength) {\n        if (((startIndex = text.indexOf(startSymbol, index)) != -1) &&\n             ((endIndex = text.indexOf(endSymbol, startIndex + startSymbolLength)) != -1)) {\n          if (index !== startIndex) {\n            concat.push(unescapeText(text.substring(index, startIndex)));\n          }\n          exp = text.substring(startIndex + startSymbolLength, endIndex);\n          expressions.push(exp);\n          parseFns.push($parse(exp, parseStringifyInterceptor));\n          index = endIndex + endSymbolLength;\n          expressionPositions.push(concat.length);\n          concat.push('');\n        } else {\n          // we did not find an interpolation, so we have to add the remainder to the separators array\n          if (index !== textLength) {\n            concat.push(unescapeText(text.substring(index)));\n          }\n          break;\n        }\n      }\n\n      // Concatenating expressions makes it hard to reason about whether some combination of\n      // concatenated values are unsafe to use and could easily lead to XSS.  By requiring that a\n      // single expression be used for iframe[src], object[src], etc., we ensure that the value\n      // that's used is assigned or constructed by some JS code somewhere that is more testable or\n      // make it obvious that you bound the value to some user controlled value.  This helps reduce\n      // the load when auditing for XSS issues.\n      if (trustedContext && concat.length > 1) {\n          throw $interpolateMinErr('noconcat',\n              \"Error while interpolating: {0}\\nStrict Contextual Escaping disallows \" +\n              \"interpolations that concatenate multiple expressions when a trusted value is \" +\n              \"required.  See http://docs.angularjs.org/api/ng.$sce\", text);\n      }\n\n      if (!mustHaveExpression || expressions.length) {\n        var compute = function(values) {\n          for (var i = 0, ii = expressions.length; i < ii; i++) {\n            if (allOrNothing && isUndefined(values[i])) return;\n            concat[expressionPositions[i]] = values[i];\n          }\n          return concat.join('');\n        };\n\n        var getValue = function(value) {\n          return trustedContext ?\n            $sce.getTrusted(trustedContext, value) :\n            $sce.valueOf(value);\n        };\n\n        var stringify = function(value) {\n          if (value == null) { // null || undefined\n            return '';\n          }\n          switch (typeof value) {\n            case 'string':\n              break;\n            case 'number':\n              value = '' + value;\n              break;\n            default:\n              value = toJson(value);\n          }\n\n          return value;\n        };\n\n        return extend(function interpolationFn(context) {\n            var i = 0;\n            var ii = expressions.length;\n            var values = new Array(ii);\n\n            try {\n              for (; i < ii; i++) {\n                values[i] = parseFns[i](context);\n              }\n\n              return compute(values);\n            } catch (err) {\n              var newErr = $interpolateMinErr('interr', \"Can't interpolate: {0}\\n{1}\", text,\n                  err.toString());\n              $exceptionHandler(newErr);\n            }\n\n          }, {\n          // all of these properties are undocumented for now\n          exp: text, //just for compatibility with regular watchers created via $watch\n          expressions: expressions,\n          $$watchDelegate: function(scope, listener, objectEquality) {\n            var lastValue;\n            return scope.$watchGroup(parseFns, function interpolateFnWatcher(values, oldValues) {\n              var currValue = compute(values);\n              if (isFunction(listener)) {\n                listener.call(this, currValue, values !== oldValues ? lastValue : currValue, scope);\n              }\n              lastValue = currValue;\n            }, objectEquality);\n          }\n        });\n      }\n\n      function unescapeText(text) {\n        return text.replace(escapedStartRegexp, startSymbol).\n          replace(escapedEndRegexp, endSymbol);\n      }\n\n      function parseStringifyInterceptor(value) {\n        try {\n          value = getValue(value);\n          return allOrNothing && !isDefined(value) ? value : stringify(value);\n        } catch (err) {\n          var newErr = $interpolateMinErr('interr', \"Can't interpolate: {0}\\n{1}\", text,\n            err.toString());\n          $exceptionHandler(newErr);\n        }\n      }\n    }\n\n\n    /**\n     * @ngdoc method\n     * @name $interpolate#startSymbol\n     * @description\n     * Symbol to denote the start of expression in the interpolated string. Defaults to `{{`.\n     *\n     * Use {@link ng.$interpolateProvider#startSymbol `$interpolateProvider.startSymbol`} to change\n     * the symbol.\n     *\n     * @returns {string} start symbol.\n     */\n    $interpolate.startSymbol = function() {\n      return startSymbol;\n    };\n\n\n    /**\n     * @ngdoc method\n     * @name $interpolate#endSymbol\n     * @description\n     * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.\n     *\n     * Use {@link ng.$interpolateProvider#endSymbol `$interpolateProvider.endSymbol`} to change\n     * the symbol.\n     *\n     * @returns {string} end symbol.\n     */\n    $interpolate.endSymbol = function() {\n      return endSymbol;\n    };\n\n    return $interpolate;\n  }];\n}\n\nfunction $IntervalProvider() {\n  this.$get = ['$rootScope', '$window', '$q', '$$q',\n       function($rootScope,   $window,   $q,   $$q) {\n    var intervals = {};\n\n\n     /**\n      * @ngdoc service\n      * @name $interval\n      *\n      * @description\n      * Angular's wrapper for `window.setInterval`. The `fn` function is executed every `delay`\n      * milliseconds.\n      *\n      * The return value of registering an interval function is a promise. This promise will be\n      * notified upon each tick of the interval, and will be resolved after `count` iterations, or\n      * run indefinitely if `count` is not defined. The value of the notification will be the\n      * number of iterations that have run.\n      * To cancel an interval, call `$interval.cancel(promise)`.\n      *\n      * In tests you can use {@link ngMock.$interval#flush `$interval.flush(millis)`} to\n      * move forward by `millis` milliseconds and trigger any functions scheduled to run in that\n      * time.\n      *\n      * <div class=\"alert alert-warning\">\n      * **Note**: Intervals created by this service must be explicitly destroyed when you are finished\n      * with them.  In particular they are not automatically destroyed when a controller's scope or a\n      * directive's element are destroyed.\n      * You should take this into consideration and make sure to always cancel the interval at the\n      * appropriate moment.  See the example below for more details on how and when to do this.\n      * </div>\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#$apply $apply} block.\n      * @returns {promise} A promise which will be notified on each iteration.\n      *\n      * @example\n      * <example module=\"intervalExample\">\n      * <file name=\"index.html\">\n      *   <script>\n      *     angular.module('intervalExample', [])\n      *       .controller('ExampleController', ['$scope', '$interval',\n      *         function($scope, $interval) {\n      *           $scope.format = 'M/d/yy h:mm:ss a';\n      *           $scope.blood_1 = 100;\n      *           $scope.blood_2 = 120;\n      *\n      *           var stop;\n      *           $scope.fight = function() {\n      *             // Don't start a new fight if we are already fighting\n      *             if ( angular.isDefined(stop) ) return;\n      *\n      *             stop = $interval(function() {\n      *               if ($scope.blood_1 > 0 && $scope.blood_2 > 0) {\n      *                 $scope.blood_1 = $scope.blood_1 - 3;\n      *                 $scope.blood_2 = $scope.blood_2 - 4;\n      *               } else {\n      *                 $scope.stopFight();\n      *               }\n      *             }, 100);\n      *           };\n      *\n      *           $scope.stopFight = function() {\n      *             if (angular.isDefined(stop)) {\n      *               $interval.cancel(stop);\n      *               stop = undefined;\n      *             }\n      *           };\n      *\n      *           $scope.resetFight = function() {\n      *             $scope.blood_1 = 100;\n      *             $scope.blood_2 = 120;\n      *           };\n      *\n      *           $scope.$on('$destroy', function() {\n      *             // Make sure that the interval is destroyed too\n      *             $scope.stopFight();\n      *           });\n      *         }])\n      *       // Register the 'myCurrentTime' directive factory method.\n      *       // We inject $interval and dateFilter service since the factory method is DI.\n      *       .directive('myCurrentTime', ['$interval', 'dateFilter',\n      *         function($interval, dateFilter) {\n      *           // return the directive link function. (compile function not needed)\n      *           return function(scope, element, attrs) {\n      *             var format,  // date format\n      *                 stopTime; // so that we can cancel the time updates\n      *\n      *             // used to update the UI\n      *             function updateTime() {\n      *               element.text(dateFilter(new Date(), format));\n      *             }\n      *\n      *             // watch the expression, and update the UI on change.\n      *             scope.$watch(attrs.myCurrentTime, function(value) {\n      *               format = value;\n      *               updateTime();\n      *             });\n      *\n      *             stopTime = $interval(updateTime, 1000);\n      *\n      *             // listen on DOM destroy (removal) event, and cancel the next UI update\n      *             // to prevent updating time after the DOM element was removed.\n      *             element.on('$destroy', function() {\n      *               $interval.cancel(stopTime);\n      *             });\n      *           }\n      *         }]);\n      *   </script>\n      *\n      *   <div>\n      *     <div ng-controller=\"ExampleController\">\n      *       Date format: <input ng-model=\"format\"> <hr/>\n      *       Current time is: <span my-current-time=\"format\"></span>\n      *       <hr/>\n      *       Blood 1 : <font color='red'>{{blood_1}}</font>\n      *       Blood 2 : <font color='red'>{{blood_2}}</font>\n      *       <button type=\"button\" data-ng-click=\"fight()\">Fight</button>\n      *       <button type=\"button\" data-ng-click=\"stopFight()\">StopFight</button>\n      *       <button type=\"button\" data-ng-click=\"resetFight()\">resetFight</button>\n      *     </div>\n      *   </div>\n      *\n      * </file>\n      * </example>\n      */\n    function interval(fn, delay, count, invokeApply) {\n      var setInterval = $window.setInterval,\n          clearInterval = $window.clearInterval,\n          iteration = 0,\n          skipApply = (isDefined(invokeApply) && !invokeApply),\n          deferred = (skipApply ? $$q : $q).defer(),\n          promise = deferred.promise;\n\n      count = isDefined(count) ? count : 0;\n\n      promise.then(null, null, fn);\n\n      promise.$$intervalId = setInterval(function tick() {\n        deferred.notify(iteration++);\n\n        if (count > 0 && iteration >= count) {\n          deferred.resolve(iteration);\n          clearInterval(promise.$$intervalId);\n          delete intervals[promise.$$intervalId];\n        }\n\n        if (!skipApply) $rootScope.$apply();\n\n      }, delay);\n\n      intervals[promise.$$intervalId] = deferred;\n\n      return promise;\n    }\n\n\n     /**\n      * @ngdoc method\n      * @name $interval#cancel\n      *\n      * @description\n      * Cancels a task associated with the `promise`.\n      *\n      * @param {promise} promise returned by the `$interval` function.\n      * @returns {boolean} Returns `true` if the task was successfully canceled.\n      */\n    interval.cancel = function(promise) {\n      if (promise && promise.$$intervalId in intervals) {\n        intervals[promise.$$intervalId].reject('canceled');\n        $window.clearInterval(promise.$$intervalId);\n        delete intervals[promise.$$intervalId];\n        return true;\n      }\n      return false;\n    };\n\n    return interval;\n  }];\n}\n\n/**\n * @ngdoc service\n * @name $locale\n *\n * @description\n * $locale service provides localization rules for various Angular components. As of right now the\n * only public api is:\n *\n * * `id` – `{string}` – locale id formatted as `languageId-countryId` (e.g. `en-us`)\n */\nfunction $LocaleProvider() {\n  this.$get = function() {\n    return {\n      id: 'en-us',\n\n      NUMBER_FORMATS: {\n        DECIMAL_SEP: '.',\n        GROUP_SEP: ',',\n        PATTERNS: [\n          { // Decimal Pattern\n            minInt: 1,\n            minFrac: 0,\n            maxFrac: 3,\n            posPre: '',\n            posSuf: '',\n            negPre: '-',\n            negSuf: '',\n            gSize: 3,\n            lgSize: 3\n          },{ //Currency Pattern\n            minInt: 1,\n            minFrac: 2,\n            maxFrac: 2,\n            posPre: '\\u00A4',\n            posSuf: '',\n            negPre: '(\\u00A4',\n            negSuf: ')',\n            gSize: 3,\n            lgSize: 3\n          }\n        ],\n        CURRENCY_SYM: '$'\n      },\n\n      DATETIME_FORMATS: {\n        MONTH:\n            'January,February,March,April,May,June,July,August,September,October,November,December'\n            .split(','),\n        SHORTMONTH:  'Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec'.split(','),\n        DAY: 'Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday'.split(','),\n        SHORTDAY: 'Sun,Mon,Tue,Wed,Thu,Fri,Sat'.split(','),\n        AMPMS: ['AM','PM'],\n        medium: 'MMM d, y h:mm:ss a',\n        'short': 'M/d/yy h:mm a',\n        fullDate: 'EEEE, MMMM d, y',\n        longDate: 'MMMM d, y',\n        mediumDate: 'MMM d, y',\n        shortDate: 'M/d/yy',\n        mediumTime: 'h:mm:ss a',\n        shortTime: 'h:mm a'\n      },\n\n      pluralCat: function(num) {\n        if (num === 1) {\n          return 'one';\n        }\n        return 'other';\n      }\n    };\n  };\n}\n\nvar PATH_MATCH = /^([^\\?#]*)(\\?([^#]*))?(#(.*))?$/,\n    DEFAULT_PORTS = {'http': 80, 'https': 443, 'ftp': 21};\nvar $locationMinErr = minErr('$location');\n\n\n/**\n * Encode path using encodeUriSegment, ignoring forward slashes\n *\n * @param {string} path Path to encode\n * @returns {string}\n */\nfunction encodePath(path) {\n  var segments = path.split('/'),\n      i = segments.length;\n\n  while (i--) {\n    segments[i] = encodeUriSegment(segments[i]);\n  }\n\n  return segments.join('/');\n}\n\nfunction parseAbsoluteUrl(absoluteUrl, locationObj) {\n  var parsedUrl = urlResolve(absoluteUrl);\n\n  locationObj.$$protocol = parsedUrl.protocol;\n  locationObj.$$host = parsedUrl.hostname;\n  locationObj.$$port = int(parsedUrl.port) || DEFAULT_PORTS[parsedUrl.protocol] || null;\n}\n\n\nfunction parseAppUrl(relativeUrl, locationObj) {\n  var prefixed = (relativeUrl.charAt(0) !== '/');\n  if (prefixed) {\n    relativeUrl = '/' + relativeUrl;\n  }\n  var match = urlResolve(relativeUrl);\n  locationObj.$$path = decodeURIComponent(prefixed && match.pathname.charAt(0) === '/' ?\n      match.pathname.substring(1) : match.pathname);\n  locationObj.$$search = parseKeyValue(match.search);\n  locationObj.$$hash = decodeURIComponent(match.hash);\n\n  // make sure path starts with '/';\n  if (locationObj.$$path && locationObj.$$path.charAt(0) != '/') {\n    locationObj.$$path = '/' + locationObj.$$path;\n  }\n}\n\n\n/**\n *\n * @param {string} begin\n * @param {string} whole\n * @returns {string} returns text from whole after begin or undefined if it does not begin with\n *                   expected string.\n */\nfunction beginsWith(begin, whole) {\n  if (whole.indexOf(begin) === 0) {\n    return whole.substr(begin.length);\n  }\n}\n\n\nfunction stripHash(url) {\n  var index = url.indexOf('#');\n  return index == -1 ? url : url.substr(0, index);\n}\n\nfunction trimEmptyHash(url) {\n  return url.replace(/(#.+)|#$/, '$1');\n}\n\n\nfunction stripFile(url) {\n  return url.substr(0, stripHash(url).lastIndexOf('/') + 1);\n}\n\n/* return the server only (scheme://host:port) */\nfunction serverBase(url) {\n  return url.substring(0, url.indexOf('/', url.indexOf('//') + 2));\n}\n\n\n/**\n * LocationHtml5Url represents an url\n * This object is exposed as $location service when HTML5 mode is enabled and supported\n *\n * @constructor\n * @param {string} appBase application base URL\n * @param {string} basePrefix url path prefix\n */\nfunction LocationHtml5Url(appBase, basePrefix) {\n  this.$$html5 = true;\n  basePrefix = basePrefix || '';\n  var appBaseNoFile = stripFile(appBase);\n  parseAbsoluteUrl(appBase, this);\n\n\n  /**\n   * Parse given html5 (regular) url string into properties\n   * @param {string} url HTML5 url\n   * @private\n   */\n  this.$$parse = function(url) {\n    var pathUrl = beginsWith(appBaseNoFile, url);\n    if (!isString(pathUrl)) {\n      throw $locationMinErr('ipthprfx', 'Invalid url \"{0}\", missing path prefix \"{1}\".', url,\n          appBaseNoFile);\n    }\n\n    parseAppUrl(pathUrl, this);\n\n    if (!this.$$path) {\n      this.$$path = '/';\n    }\n\n    this.$$compose();\n  };\n\n  /**\n   * Compose url and update `absUrl` property\n   * @private\n   */\n  this.$$compose = function() {\n    var search = toKeyValue(this.$$search),\n        hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';\n\n    this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;\n    this.$$absUrl = appBaseNoFile + this.$$url.substr(1); // first char is always '/'\n  };\n\n  this.$$parseLinkUrl = function(url, relHref) {\n    if (relHref && relHref[0] === '#') {\n      // special case for links to hash fragments:\n      // keep the old url and only replace the hash fragment\n      this.hash(relHref.slice(1));\n      return true;\n    }\n    var appUrl, prevAppUrl;\n    var rewrittenUrl;\n\n    if ((appUrl = beginsWith(appBase, url)) !== undefined) {\n      prevAppUrl = appUrl;\n      if ((appUrl = beginsWith(basePrefix, appUrl)) !== undefined) {\n        rewrittenUrl = appBaseNoFile + (beginsWith('/', appUrl) || appUrl);\n      } else {\n        rewrittenUrl = appBase + prevAppUrl;\n      }\n    } else if ((appUrl = beginsWith(appBaseNoFile, url)) !== undefined) {\n      rewrittenUrl = appBaseNoFile + appUrl;\n    } else if (appBaseNoFile == url + '/') {\n      rewrittenUrl = appBaseNoFile;\n    }\n    if (rewrittenUrl) {\n      this.$$parse(rewrittenUrl);\n    }\n    return !!rewrittenUrl;\n  };\n}\n\n\n/**\n * LocationHashbangUrl represents url\n * This object is exposed as $location service when developer doesn't opt into html5 mode.\n * It also serves as the base class for html5 mode fallback on legacy browsers.\n *\n * @constructor\n * @param {string} appBase application base URL\n * @param {string} hashPrefix hashbang prefix\n */\nfunction LocationHashbangUrl(appBase, hashPrefix) {\n  var appBaseNoFile = stripFile(appBase);\n\n  parseAbsoluteUrl(appBase, this);\n\n\n  /**\n   * Parse given hashbang url into properties\n   * @param {string} url Hashbang url\n   * @private\n   */\n  this.$$parse = function(url) {\n    var withoutBaseUrl = beginsWith(appBase, url) || beginsWith(appBaseNoFile, url);\n    var withoutHashUrl;\n\n    if (withoutBaseUrl.charAt(0) === '#') {\n\n      // The rest of the url starts with a hash so we have\n      // got either a hashbang path or a plain hash fragment\n      withoutHashUrl = beginsWith(hashPrefix, withoutBaseUrl);\n      if (isUndefined(withoutHashUrl)) {\n        // There was no hashbang prefix so we just have a hash fragment\n        withoutHashUrl = withoutBaseUrl;\n      }\n\n    } else {\n      // There was no hashbang path nor hash fragment:\n      // If we are in HTML5 mode we use what is left as the path;\n      // Otherwise we ignore what is left\n      withoutHashUrl = this.$$html5 ? withoutBaseUrl : '';\n    }\n\n    parseAppUrl(withoutHashUrl, this);\n\n    this.$$path = removeWindowsDriveName(this.$$path, withoutHashUrl, appBase);\n\n    this.$$compose();\n\n    /*\n     * In Windows, on an anchor node on documents loaded from\n     * the filesystem, the browser will return a pathname\n     * prefixed with the drive name ('/C:/path') when a\n     * pathname without a drive is set:\n     *  * a.setAttribute('href', '/foo')\n     *   * a.pathname === '/C:/foo' //true\n     *\n     * Inside of Angular, we're always using pathnames that\n     * do not include drive names for routing.\n     */\n    function removeWindowsDriveName(path, url, base) {\n      /*\n      Matches paths for file protocol on windows,\n      such as /C:/foo/bar, and captures only /foo/bar.\n      */\n      var windowsFilePathExp = /^\\/[A-Z]:(\\/.*)/;\n\n      var firstPathSegmentMatch;\n\n      //Get the relative path from the input URL.\n      if (url.indexOf(base) === 0) {\n        url = url.replace(base, '');\n      }\n\n      // The input URL intentionally contains a first path segment that ends with a colon.\n      if (windowsFilePathExp.exec(url)) {\n        return path;\n      }\n\n      firstPathSegmentMatch = windowsFilePathExp.exec(path);\n      return firstPathSegmentMatch ? firstPathSegmentMatch[1] : path;\n    }\n  };\n\n  /**\n   * Compose hashbang url and update `absUrl` property\n   * @private\n   */\n  this.$$compose = function() {\n    var search = toKeyValue(this.$$search),\n        hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';\n\n    this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;\n    this.$$absUrl = appBase + (this.$$url ? hashPrefix + this.$$url : '');\n  };\n\n  this.$$parseLinkUrl = function(url, relHref) {\n    if (stripHash(appBase) == stripHash(url)) {\n      this.$$parse(url);\n      return true;\n    }\n    return false;\n  };\n}\n\n\n/**\n * LocationHashbangUrl represents url\n * This object is exposed as $location service when html5 history api is enabled but the browser\n * does not support it.\n *\n * @constructor\n * @param {string} appBase application base URL\n * @param {string} hashPrefix hashbang prefix\n */\nfunction LocationHashbangInHtml5Url(appBase, hashPrefix) {\n  this.$$html5 = true;\n  LocationHashbangUrl.apply(this, arguments);\n\n  var appBaseNoFile = stripFile(appBase);\n\n  this.$$parseLinkUrl = function(url, relHref) {\n    if (relHref && relHref[0] === '#') {\n      // special case for links to hash fragments:\n      // keep the old url and only replace the hash fragment\n      this.hash(relHref.slice(1));\n      return true;\n    }\n\n    var rewrittenUrl;\n    var appUrl;\n\n    if (appBase == stripHash(url)) {\n      rewrittenUrl = url;\n    } else if ((appUrl = beginsWith(appBaseNoFile, url))) {\n      rewrittenUrl = appBase + hashPrefix + appUrl;\n    } else if (appBaseNoFile === url + '/') {\n      rewrittenUrl = appBaseNoFile;\n    }\n    if (rewrittenUrl) {\n      this.$$parse(rewrittenUrl);\n    }\n    return !!rewrittenUrl;\n  };\n\n  this.$$compose = function() {\n    var search = toKeyValue(this.$$search),\n        hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';\n\n    this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;\n    // include hashPrefix in $$absUrl when $$url is empty so IE8 & 9 do not reload page because of removal of '#'\n    this.$$absUrl = appBase + hashPrefix + this.$$url;\n  };\n\n}\n\n\nvar locationPrototype = {\n\n  /**\n   * Are we in html5 mode?\n   * @private\n   */\n  $$html5: false,\n\n  /**\n   * Has any change been replacing?\n   * @private\n   */\n  $$replace: false,\n\n  /**\n   * @ngdoc method\n   * @name $location#absUrl\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return full url representation with all segments encoded according to rules specified in\n   * [RFC 3986](http://www.ietf.org/rfc/rfc3986.txt).\n   *\n   *\n   * ```js\n   * // given url http://example.com/#/some/path?foo=bar&baz=xoxo\n   * var absUrl = $location.absUrl();\n   * // => \"http://example.com/#/some/path?foo=bar&baz=xoxo\"\n   * ```\n   *\n   * @return {string} full url\n   */\n  absUrl: locationGetter('$$absUrl'),\n\n  /**\n   * @ngdoc method\n   * @name $location#url\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return url (e.g. `/path?a=b#hash`) when called without any parameter.\n   *\n   * Change path, search and hash, when called with parameter and return `$location`.\n   *\n   *\n   * ```js\n   * // given url http://example.com/#/some/path?foo=bar&baz=xoxo\n   * var url = $location.url();\n   * // => \"/some/path?foo=bar&baz=xoxo\"\n   * ```\n   *\n   * @param {string=} url New url without base prefix (e.g. `/path?a=b#hash`)\n   * @return {string} url\n   */\n  url: function(url) {\n    if (isUndefined(url))\n      return this.$$url;\n\n    var match = PATH_MATCH.exec(url);\n    if (match[1] || url === '') this.path(decodeURIComponent(match[1]));\n    if (match[2] || match[1] || url === '') this.search(match[3] || '');\n    this.hash(match[5] || '');\n\n    return this;\n  },\n\n  /**\n   * @ngdoc method\n   * @name $location#protocol\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return protocol of current url.\n   *\n   *\n   * ```js\n   * // given url http://example.com/#/some/path?foo=bar&baz=xoxo\n   * var protocol = $location.protocol();\n   * // => \"http\"\n   * ```\n   *\n   * @return {string} protocol of current url\n   */\n  protocol: locationGetter('$$protocol'),\n\n  /**\n   * @ngdoc method\n   * @name $location#host\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return host of current url.\n   *\n   *\n   * ```js\n   * // given url http://example.com/#/some/path?foo=bar&baz=xoxo\n   * var host = $location.host();\n   * // => \"example.com\"\n   * ```\n   *\n   * @return {string} host of current url.\n   */\n  host: locationGetter('$$host'),\n\n  /**\n   * @ngdoc method\n   * @name $location#port\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return port of current url.\n   *\n   *\n   * ```js\n   * // given url http://example.com/#/some/path?foo=bar&baz=xoxo\n   * var port = $location.port();\n   * // => 80\n   * ```\n   *\n   * @return {Number} port\n   */\n  port: locationGetter('$$port'),\n\n  /**\n   * @ngdoc method\n   * @name $location#path\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return path of current url when called without any parameter.\n   *\n   * Change path when called with parameter and return `$location`.\n   *\n   * Note: Path should always begin with forward slash (/), this method will add the forward slash\n   * if it is missing.\n   *\n   *\n   * ```js\n   * // given url http://example.com/#/some/path?foo=bar&baz=xoxo\n   * var path = $location.path();\n   * // => \"/some/path\"\n   * ```\n   *\n   * @param {(string|number)=} path New path\n   * @return {string} path\n   */\n  path: locationGetterSetter('$$path', function(path) {\n    path = path !== null ? path.toString() : '';\n    return path.charAt(0) == '/' ? path : '/' + path;\n  }),\n\n  /**\n   * @ngdoc method\n   * @name $location#search\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return search part (as object) of current url when called without any parameter.\n   *\n   * Change search part when called with parameter and return `$location`.\n   *\n   *\n   * ```js\n   * // given url http://example.com/#/some/path?foo=bar&baz=xoxo\n   * var searchObject = $location.search();\n   * // => {foo: 'bar', baz: 'xoxo'}\n   *\n   * // set foo to 'yipee'\n   * $location.search('foo', 'yipee');\n   * // $location.search() => {foo: 'yipee', baz: 'xoxo'}\n   * ```\n   *\n   * @param {string|Object.<string>|Object.<Array.<string>>} search New search params - string or\n   * hash object.\n   *\n   * When called with a single argument the method acts as a setter, setting the `search` component\n   * of `$location` to the specified value.\n   *\n   * If the argument is a hash object containing an array of values, these values will be encoded\n   * as duplicate search parameters in the url.\n   *\n   * @param {(string|Number|Array<string>|boolean)=} paramValue If `search` is a string or number, then `paramValue`\n   * will override only a single search property.\n   *\n   * If `paramValue` is an array, it will override the property of the `search` component of\n   * `$location` specified via the first argument.\n   *\n   * If `paramValue` is `null`, the property specified via the first argument will be deleted.\n   *\n   * If `paramValue` is `true`, the property specified via the first argument will be added with no\n   * value nor trailing equal sign.\n   *\n   * @return {Object} If called with no arguments returns the parsed `search` object. If called with\n   * one or more arguments returns `$location` object itself.\n   */\n  search: function(search, paramValue) {\n    switch (arguments.length) {\n      case 0:\n        return this.$$search;\n      case 1:\n        if (isString(search) || isNumber(search)) {\n          search = search.toString();\n          this.$$search = parseKeyValue(search);\n        } else if (isObject(search)) {\n          search = copy(search, {});\n          // remove object undefined or null properties\n          forEach(search, function(value, key) {\n            if (value == null) delete search[key];\n          });\n\n          this.$$search = search;\n        } else {\n          throw $locationMinErr('isrcharg',\n              'The first argument of the `$location#search()` call must be a string or an object.');\n        }\n        break;\n      default:\n        if (isUndefined(paramValue) || paramValue === null) {\n          delete this.$$search[search];\n        } else {\n          this.$$search[search] = paramValue;\n        }\n    }\n\n    this.$$compose();\n    return this;\n  },\n\n  /**\n   * @ngdoc method\n   * @name $location#hash\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return hash fragment when called without any parameter.\n   *\n   * Change hash fragment when called with parameter and return `$location`.\n   *\n   *\n   * ```js\n   * // given url http://example.com/#/some/path?foo=bar&baz=xoxo#hashValue\n   * var hash = $location.hash();\n   * // => \"hashValue\"\n   * ```\n   *\n   * @param {(string|number)=} hash New hash fragment\n   * @return {string} hash\n   */\n  hash: locationGetterSetter('$$hash', function(hash) {\n    return hash !== null ? hash.toString() : '';\n  }),\n\n  /**\n   * @ngdoc method\n   * @name $location#replace\n   *\n   * @description\n   * If called, all changes to $location during current `$digest` will be replacing current history\n   * record, instead of adding new one.\n   */\n  replace: function() {\n    this.$$replace = true;\n    return this;\n  }\n};\n\nforEach([LocationHashbangInHtml5Url, LocationHashbangUrl, LocationHtml5Url], function(Location) {\n  Location.prototype = Object.create(locationPrototype);\n\n  /**\n   * @ngdoc method\n   * @name $location#state\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return the history state object when called without any parameter.\n   *\n   * Change the history state object when called with one parameter and return `$location`.\n   * The state object is later passed to `pushState` or `replaceState`.\n   *\n   * NOTE: This method is supported only in HTML5 mode and only in browsers supporting\n   * the HTML5 History API (i.e. methods `pushState` and `replaceState`). If you need to support\n   * older browsers (like IE9 or Android < 4.0), don't use this method.\n   *\n   * @param {object=} state State object for pushState or replaceState\n   * @return {object} state\n   */\n  Location.prototype.state = function(state) {\n    if (!arguments.length)\n      return this.$$state;\n\n    if (Location !== LocationHtml5Url || !this.$$html5) {\n      throw $locationMinErr('nostate', 'History API state support is available only ' +\n        'in HTML5 mode and only in browsers supporting HTML5 History API');\n    }\n    // The user might modify `stateObject` after invoking `$location.state(stateObject)`\n    // but we're changing the $$state reference to $browser.state() during the $digest\n    // so the modification window is narrow.\n    this.$$state = isUndefined(state) ? null : state;\n\n    return this;\n  };\n});\n\n\nfunction locationGetter(property) {\n  return function() {\n    return this[property];\n  };\n}\n\n\nfunction locationGetterSetter(property, preprocess) {\n  return function(value) {\n    if (isUndefined(value))\n      return this[property];\n\n    this[property] = preprocess(value);\n    this.$$compose();\n\n    return this;\n  };\n}\n\n\n/**\n * @ngdoc service\n * @name $location\n *\n * @requires $rootElement\n *\n * @description\n * The $location service parses the URL in the browser address bar (based on the\n * [window.location](https://developer.mozilla.org/en/window.location)) and makes the URL\n * available to your application. Changes to the URL in the address bar are reflected into\n * $location service and changes to $location are reflected into the browser address bar.\n *\n * **The $location service:**\n *\n * - Exposes the current URL in the browser address bar, so you can\n *   - Watch and observe the URL.\n *   - Change the URL.\n * - Synchronizes the URL with the browser when the user\n *   - Changes the address bar.\n *   - Clicks the back or forward button (or clicks a History link).\n *   - Clicks on a link.\n * - Represents the URL object as a set of methods (protocol, host, port, path, search, hash).\n *\n * For more information see {@link guide/$location Developer Guide: Using $location}\n */\n\n/**\n * @ngdoc provider\n * @name $locationProvider\n * @description\n * Use the `$locationProvider` to configure how the application deep linking paths are stored.\n */\nfunction $LocationProvider() {\n  var hashPrefix = '',\n      html5Mode = {\n        enabled: false,\n        requireBase: true,\n        rewriteLinks: true\n      };\n\n  /**\n   * @ngdoc method\n   * @name $locationProvider#hashPrefix\n   * @description\n   * @param {string=} prefix Prefix for hash part (containing path and search)\n   * @returns {*} current value if used as getter or itself (chaining) if used as setter\n   */\n  this.hashPrefix = function(prefix) {\n    if (isDefined(prefix)) {\n      hashPrefix = prefix;\n      return this;\n    } else {\n      return hashPrefix;\n    }\n  };\n\n  /**\n   * @ngdoc method\n   * @name $locationProvider#html5Mode\n   * @description\n   * @param {(boolean|Object)=} mode If boolean, sets `html5Mode.enabled` to value.\n   *   If object, sets `enabled`, `requireBase` and `rewriteLinks` to respective values. Supported\n   *   properties:\n   *   - **enabled** – `{boolean}` – (default: false) If true, will rely on `history.pushState` to\n   *     change urls where supported. Will fall back to hash-prefixed paths in browsers that do not\n   *     support `pushState`.\n   *   - **requireBase** - `{boolean}` - (default: `true`) When html5Mode is enabled, specifies\n   *     whether or not a <base> tag is required to be present. If `enabled` and `requireBase` are\n   *     true, and a base tag is not present, an error will be thrown when `$location` is injected.\n   *     See the {@link guide/$location $location guide for more information}\n   *   - **rewriteLinks** - `{boolean}` - (default: `true`) When html5Mode is enabled,\n   *     enables/disables url rewriting for relative links.\n   *\n   * @returns {Object} html5Mode object if used as getter or itself (chaining) if used as setter\n   */\n  this.html5Mode = function(mode) {\n    if (isBoolean(mode)) {\n      html5Mode.enabled = mode;\n      return this;\n    } else if (isObject(mode)) {\n\n      if (isBoolean(mode.enabled)) {\n        html5Mode.enabled = mode.enabled;\n      }\n\n      if (isBoolean(mode.requireBase)) {\n        html5Mode.requireBase = mode.requireBase;\n      }\n\n      if (isBoolean(mode.rewriteLinks)) {\n        html5Mode.rewriteLinks = mode.rewriteLinks;\n      }\n\n      return this;\n    } else {\n      return html5Mode;\n    }\n  };\n\n  /**\n   * @ngdoc event\n   * @name $location#$locationChangeStart\n   * @eventType broadcast on root scope\n   * @description\n   * Broadcasted before a URL will change.\n   *\n   * This change can be prevented by calling\n   * `preventDefault` method of the event. See {@link ng.$rootScope.Scope#$on} for more\n   * details about event object. Upon successful change\n   * {@link ng.$location#$locationChangeSuccess $locationChangeSuccess} is fired.\n   *\n   * The `newState` and `oldState` parameters may be defined only in HTML5 mode and when\n   * the browser supports the HTML5 History API.\n   *\n   * @param {Object} angularEvent Synthetic event object.\n   * @param {string} newUrl New URL\n   * @param {string=} oldUrl URL that was before it was changed.\n   * @param {string=} newState New history state object\n   * @param {string=} oldState History state object that was before it was changed.\n   */\n\n  /**\n   * @ngdoc event\n   * @name $location#$locationChangeSuccess\n   * @eventType broadcast on root scope\n   * @description\n   * Broadcasted after a URL was changed.\n   *\n   * The `newState` and `oldState` parameters may be defined only in HTML5 mode and when\n   * the browser supports the HTML5 History API.\n   *\n   * @param {Object} angularEvent Synthetic event object.\n   * @param {string} newUrl New URL\n   * @param {string=} oldUrl URL that was before it was changed.\n   * @param {string=} newState New history state object\n   * @param {string=} oldState History state object that was before it was changed.\n   */\n\n  this.$get = ['$rootScope', '$browser', '$sniffer', '$rootElement', '$window',\n      function($rootScope, $browser, $sniffer, $rootElement, $window) {\n    var $location,\n        LocationMode,\n        baseHref = $browser.baseHref(), // if base[href] is undefined, it defaults to ''\n        initialUrl = $browser.url(),\n        appBase;\n\n    if (html5Mode.enabled) {\n      if (!baseHref && html5Mode.requireBase) {\n        throw $locationMinErr('nobase',\n          \"$location in HTML5 mode requires a <base> tag to be present!\");\n      }\n      appBase = serverBase(initialUrl) + (baseHref || '/');\n      LocationMode = $sniffer.history ? LocationHtml5Url : LocationHashbangInHtml5Url;\n    } else {\n      appBase = stripHash(initialUrl);\n      LocationMode = LocationHashbangUrl;\n    }\n    $location = new LocationMode(appBase, '#' + hashPrefix);\n    $location.$$parseLinkUrl(initialUrl, initialUrl);\n\n    $location.$$state = $browser.state();\n\n    var IGNORE_URI_REGEXP = /^\\s*(javascript|mailto):/i;\n\n    function setBrowserUrlWithFallback(url, replace, state) {\n      var oldUrl = $location.url();\n      var oldState = $location.$$state;\n      try {\n        $browser.url(url, replace, state);\n\n        // Make sure $location.state() returns referentially identical (not just deeply equal)\n        // state object; this makes possible quick checking if the state changed in the digest\n        // loop. Checking deep equality would be too expensive.\n        $location.$$state = $browser.state();\n      } catch (e) {\n        // Restore old values if pushState fails\n        $location.url(oldUrl);\n        $location.$$state = oldState;\n\n        throw e;\n      }\n    }\n\n    $rootElement.on('click', function(event) {\n      // TODO(vojta): rewrite link when opening in new tab/window (in legacy browser)\n      // currently we open nice url link and redirect then\n\n      if (!html5Mode.rewriteLinks || event.ctrlKey || event.metaKey || event.shiftKey || event.which == 2 || event.button == 2) return;\n\n      var elm = jqLite(event.target);\n\n      // traverse the DOM up to find first A tag\n      while (nodeName_(elm[0]) !== 'a') {\n        // ignore rewriting if no A tag (reached root element, or no parent - removed from document)\n        if (elm[0] === $rootElement[0] || !(elm = elm.parent())[0]) return;\n      }\n\n      var absHref = elm.prop('href');\n      // get the actual href attribute - see\n      // http://msdn.microsoft.com/en-us/library/ie/dd347148(v=vs.85).aspx\n      var relHref = elm.attr('href') || elm.attr('xlink:href');\n\n      if (isObject(absHref) && absHref.toString() === '[object SVGAnimatedString]') {\n        // SVGAnimatedString.animVal should be identical to SVGAnimatedString.baseVal, unless during\n        // an animation.\n        absHref = urlResolve(absHref.animVal).href;\n      }\n\n      // Ignore when url is started with javascript: or mailto:\n      if (IGNORE_URI_REGEXP.test(absHref)) return;\n\n      if (absHref && !elm.attr('target') && !event.isDefaultPrevented()) {\n        if ($location.$$parseLinkUrl(absHref, relHref)) {\n          // We do a preventDefault for all urls that are part of the angular application,\n          // in html5mode and also without, so that we are able to abort navigation without\n          // getting double entries in the location history.\n          event.preventDefault();\n          // update location manually\n          if ($location.absUrl() != $browser.url()) {\n            $rootScope.$apply();\n            // hack to work around FF6 bug 684208 when scenario runner clicks on links\n            $window.angular['ff-684208-preventDefault'] = true;\n          }\n        }\n      }\n    });\n\n\n    // rewrite hashbang url <> html5 url\n    if (trimEmptyHash($location.absUrl()) != trimEmptyHash(initialUrl)) {\n      $browser.url($location.absUrl(), true);\n    }\n\n    var initializing = true;\n\n    // update $location when $browser url changes\n    $browser.onUrlChange(function(newUrl, newState) {\n      $rootScope.$evalAsync(function() {\n        var oldUrl = $location.absUrl();\n        var oldState = $location.$$state;\n        var defaultPrevented;\n\n        $location.$$parse(newUrl);\n        $location.$$state = newState;\n\n        defaultPrevented = $rootScope.$broadcast('$locationChangeStart', newUrl, oldUrl,\n            newState, oldState).defaultPrevented;\n\n        // if the location was changed by a `$locationChangeStart` handler then stop\n        // processing this location change\n        if ($location.absUrl() !== newUrl) return;\n\n        if (defaultPrevented) {\n          $location.$$parse(oldUrl);\n          $location.$$state = oldState;\n          setBrowserUrlWithFallback(oldUrl, false, oldState);\n        } else {\n          initializing = false;\n          afterLocationChange(oldUrl, oldState);\n        }\n      });\n      if (!$rootScope.$$phase) $rootScope.$digest();\n    });\n\n    // update browser\n    $rootScope.$watch(function $locationWatch() {\n      var oldUrl = trimEmptyHash($browser.url());\n      var newUrl = trimEmptyHash($location.absUrl());\n      var oldState = $browser.state();\n      var currentReplace = $location.$$replace;\n      var urlOrStateChanged = oldUrl !== newUrl ||\n        ($location.$$html5 && $sniffer.history && oldState !== $location.$$state);\n\n      if (initializing || urlOrStateChanged) {\n        initializing = false;\n\n        $rootScope.$evalAsync(function() {\n          var newUrl = $location.absUrl();\n          var defaultPrevented = $rootScope.$broadcast('$locationChangeStart', newUrl, oldUrl,\n              $location.$$state, oldState).defaultPrevented;\n\n          // if the location was changed by a `$locationChangeStart` handler then stop\n          // processing this location change\n          if ($location.absUrl() !== newUrl) return;\n\n          if (defaultPrevented) {\n            $location.$$parse(oldUrl);\n            $location.$$state = oldState;\n          } else {\n            if (urlOrStateChanged) {\n              setBrowserUrlWithFallback(newUrl, currentReplace,\n                                        oldState === $location.$$state ? null : $location.$$state);\n            }\n            afterLocationChange(oldUrl, oldState);\n          }\n        });\n      }\n\n      $location.$$replace = false;\n\n      // we don't need to return anything because $evalAsync will make the digest loop dirty when\n      // there is a change\n    });\n\n    return $location;\n\n    function afterLocationChange(oldUrl, oldState) {\n      $rootScope.$broadcast('$locationChangeSuccess', $location.absUrl(), oldUrl,\n        $location.$$state, oldState);\n    }\n}];\n}\n\n/**\n * @ngdoc service\n * @name $log\n * @requires $window\n *\n * @description\n * Simple service for logging. Default implementation safely writes the message\n * into the browser's console (if present).\n *\n * The main purpose of this service is to simplify debugging and troubleshooting.\n *\n * The default is to log `debug` messages. You can use\n * {@link ng.$logProvider ng.$logProvider#debugEnabled} to change this.\n *\n * @example\n   <example module=\"logExample\">\n     <file name=\"script.js\">\n       angular.module('logExample', [])\n         .controller('LogController', ['$scope', '$log', function($scope, $log) {\n           $scope.$log = $log;\n           $scope.message = 'Hello World!';\n         }]);\n     </file>\n     <file name=\"index.html\">\n       <div ng-controller=\"LogController\">\n         <p>Reload this page with open console, enter text and hit the log button...</p>\n         Message:\n         <input type=\"text\" ng-model=\"message\"/>\n         <button ng-click=\"$log.log(message)\">log</button>\n         <button ng-click=\"$log.warn(message)\">warn</button>\n         <button ng-click=\"$log.info(message)\">info</button>\n         <button ng-click=\"$log.error(message)\">error</button>\n       </div>\n     </file>\n   </example>\n */\n\n/**\n * @ngdoc provider\n * @name $logProvider\n * @description\n * Use the `$logProvider` to configure how the application logs messages\n */\nfunction $LogProvider() {\n  var debug = true,\n      self = this;\n\n  /**\n   * @ngdoc method\n   * @name $logProvider#debugEnabled\n   * @description\n   * @param {boolean=} flag enable or disable debug level messages\n   * @returns {*} current value if used as getter or itself (chaining) if used as setter\n   */\n  this.debugEnabled = function(flag) {\n    if (isDefined(flag)) {\n      debug = flag;\n    return this;\n    } else {\n      return debug;\n    }\n  };\n\n  this.$get = ['$window', function($window) {\n    return {\n      /**\n       * @ngdoc method\n       * @name $log#log\n       *\n       * @description\n       * Write a log message\n       */\n      log: consoleLog('log'),\n\n      /**\n       * @ngdoc method\n       * @name $log#info\n       *\n       * @description\n       * Write an information message\n       */\n      info: consoleLog('info'),\n\n      /**\n       * @ngdoc method\n       * @name $log#warn\n       *\n       * @description\n       * Write a warning message\n       */\n      warn: consoleLog('warn'),\n\n      /**\n       * @ngdoc method\n       * @name $log#error\n       *\n       * @description\n       * Write an error message\n       */\n      error: consoleLog('error'),\n\n      /**\n       * @ngdoc method\n       * @name $log#debug\n       *\n       * @description\n       * Write a debug message\n       */\n      debug: (function() {\n        var fn = consoleLog('debug');\n\n        return function() {\n          if (debug) {\n            fn.apply(self, arguments);\n          }\n        };\n      }())\n    };\n\n    function formatError(arg) {\n      if (arg instanceof Error) {\n        if (arg.stack) {\n          arg = (arg.message && arg.stack.indexOf(arg.message) === -1)\n              ? 'Error: ' + arg.message + '\\n' + arg.stack\n              : arg.stack;\n        } else if (arg.sourceURL) {\n          arg = arg.message + '\\n' + arg.sourceURL + ':' + arg.line;\n        }\n      }\n      return arg;\n    }\n\n    function consoleLog(type) {\n      var console = $window.console || {},\n          logFn = console[type] || console.log || noop,\n          hasApply = false;\n\n      // Note: reading logFn.apply throws an error in IE11 in IE8 document mode.\n      // The reason behind this is that console.log has type \"object\" in IE8...\n      try {\n        hasApply = !!logFn.apply;\n      } catch (e) {}\n\n      if (hasApply) {\n        return function() {\n          var args = [];\n          forEach(arguments, function(arg) {\n            args.push(formatError(arg));\n          });\n          return logFn.apply(console, args);\n        };\n      }\n\n      // we are IE which either doesn't have window.console => this is noop and we do nothing,\n      // or we are IE where console.log doesn't have apply so we log at least first 2 args\n      return function(arg1, arg2) {\n        logFn(arg1, arg2 == null ? '' : arg2);\n      };\n    }\n  }];\n}\n\nvar $parseMinErr = minErr('$parse');\n\n// Sandboxing Angular Expressions\n// ------------------------------\n// Angular expressions are generally considered safe because these expressions only have direct\n// access to `$scope` and locals. However, one can obtain the ability to execute arbitrary JS code by\n// obtaining a reference to native JS functions such as the Function constructor.\n//\n// As an example, consider the following Angular expression:\n//\n//   {}.toString.constructor('alert(\"evil JS code\")')\n//\n// This sandboxing technique is not perfect and doesn't aim to be. The goal is to prevent exploits\n// against the expression language, but not to prevent exploits that were enabled by exposing\n// sensitive JavaScript or browser APIs on Scope. Exposing such objects on a Scope is never a good\n// practice and therefore we are not even trying to protect against interaction with an object\n// explicitly exposed in this way.\n//\n// In general, it is not possible to access a Window object from an angular expression unless a\n// window or some DOM object that has a reference to window is published onto a Scope.\n// Similarly we prevent invocations of function known to be dangerous, as well as assignments to\n// native objects.\n//\n// See https://docs.angularjs.org/guide/security\n\n\nfunction ensureSafeMemberName(name, fullExpression) {\n  if (name === \"__defineGetter__\" || name === \"__defineSetter__\"\n      || name === \"__lookupGetter__\" || name === \"__lookupSetter__\"\n      || name === \"__proto__\") {\n    throw $parseMinErr('isecfld',\n        'Attempting to access a disallowed field in Angular expressions! '\n        + 'Expression: {0}', fullExpression);\n  }\n  return name;\n}\n\nfunction ensureSafeObject(obj, fullExpression) {\n  // nifty check if obj is Function that is fast and works across iframes and other contexts\n  if (obj) {\n    if (obj.constructor === obj) {\n      throw $parseMinErr('isecfn',\n          'Referencing Function in Angular expressions is disallowed! Expression: {0}',\n          fullExpression);\n    } else if (// isWindow(obj)\n        obj.window === obj) {\n      throw $parseMinErr('isecwindow',\n          'Referencing the Window in Angular expressions is disallowed! Expression: {0}',\n          fullExpression);\n    } else if (// isElement(obj)\n        obj.children && (obj.nodeName || (obj.prop && obj.attr && obj.find))) {\n      throw $parseMinErr('isecdom',\n          'Referencing DOM nodes in Angular expressions is disallowed! Expression: {0}',\n          fullExpression);\n    } else if (// block Object so that we can't get hold of dangerous Object.* methods\n        obj === Object) {\n      throw $parseMinErr('isecobj',\n          'Referencing Object in Angular expressions is disallowed! Expression: {0}',\n          fullExpression);\n    }\n  }\n  return obj;\n}\n\nvar CALL = Function.prototype.call;\nvar APPLY = Function.prototype.apply;\nvar BIND = Function.prototype.bind;\n\nfunction ensureSafeFunction(obj, fullExpression) {\n  if (obj) {\n    if (obj.constructor === obj) {\n      throw $parseMinErr('isecfn',\n        'Referencing Function in Angular expressions is disallowed! Expression: {0}',\n        fullExpression);\n    } else if (obj === CALL || obj === APPLY || obj === BIND) {\n      throw $parseMinErr('isecff',\n        'Referencing call, apply or bind in Angular expressions is disallowed! Expression: {0}',\n        fullExpression);\n    }\n  }\n}\n\n//Keyword constants\nvar CONSTANTS = createMap();\nforEach({\n  'null': function() { return null; },\n  'true': function() { return true; },\n  'false': function() { return false; },\n  'undefined': function() {}\n}, function(constantGetter, name) {\n  constantGetter.constant = constantGetter.literal = constantGetter.sharedGetter = true;\n  CONSTANTS[name] = constantGetter;\n});\n\n//Not quite a constant, but can be lex/parsed the same\nCONSTANTS['this'] = function(self) { return self; };\nCONSTANTS['this'].sharedGetter = true;\n\n\n//Operators - will be wrapped by binaryFn/unaryFn/assignment/filter\nvar OPERATORS = extend(createMap(), {\n    '+':function(self, locals, a, b) {\n      a=a(self, locals); b=b(self, locals);\n      if (isDefined(a)) {\n        if (isDefined(b)) {\n          return a + b;\n        }\n        return a;\n      }\n      return isDefined(b) ? b : undefined;},\n    '-':function(self, locals, a, b) {\n          a=a(self, locals); b=b(self, locals);\n          return (isDefined(a) ? a : 0) - (isDefined(b) ? b : 0);\n        },\n    '*':function(self, locals, a, b) {return a(self, locals) * b(self, locals);},\n    '/':function(self, locals, a, b) {return a(self, locals) / b(self, locals);},\n    '%':function(self, locals, a, b) {return a(self, locals) % b(self, locals);},\n    '===':function(self, locals, a, b) {return a(self, locals) === b(self, locals);},\n    '!==':function(self, locals, a, b) {return a(self, locals) !== b(self, locals);},\n    '==':function(self, locals, a, b) {return a(self, locals) == b(self, locals);},\n    '!=':function(self, locals, a, b) {return a(self, locals) != b(self, locals);},\n    '<':function(self, locals, a, b) {return a(self, locals) < b(self, locals);},\n    '>':function(self, locals, a, b) {return a(self, locals) > b(self, locals);},\n    '<=':function(self, locals, a, b) {return a(self, locals) <= b(self, locals);},\n    '>=':function(self, locals, a, b) {return a(self, locals) >= b(self, locals);},\n    '&&':function(self, locals, a, b) {return a(self, locals) && b(self, locals);},\n    '||':function(self, locals, a, b) {return a(self, locals) || b(self, locals);},\n    '!':function(self, locals, a) {return !a(self, locals);},\n\n    //Tokenized as operators but parsed as assignment/filters\n    '=':true,\n    '|':true\n});\nvar ESCAPE = {\"n\":\"\\n\", \"f\":\"\\f\", \"r\":\"\\r\", \"t\":\"\\t\", \"v\":\"\\v\", \"'\":\"'\", '\"':'\"'};\n\n\n/////////////////////////////////////////\n\n\n/**\n * @constructor\n */\nvar Lexer = function(options) {\n  this.options = options;\n};\n\nLexer.prototype = {\n  constructor: Lexer,\n\n  lex: function(text) {\n    this.text = text;\n    this.index = 0;\n    this.tokens = [];\n\n    while (this.index < this.text.length) {\n      var ch = this.text.charAt(this.index);\n      if (ch === '\"' || ch === \"'\") {\n        this.readString(ch);\n      } else if (this.isNumber(ch) || ch === '.' && this.isNumber(this.peek())) {\n        this.readNumber();\n      } else if (this.isIdent(ch)) {\n        this.readIdent();\n      } else if (this.is(ch, '(){}[].,;:?')) {\n        this.tokens.push({index: this.index, text: ch});\n        this.index++;\n      } else if (this.isWhitespace(ch)) {\n        this.index++;\n      } else {\n        var ch2 = ch + this.peek();\n        var ch3 = ch2 + this.peek(2);\n        var op1 = OPERATORS[ch];\n        var op2 = OPERATORS[ch2];\n        var op3 = OPERATORS[ch3];\n        if (op1 || op2 || op3) {\n          var token = op3 ? ch3 : (op2 ? ch2 : ch);\n          this.tokens.push({index: this.index, text: token, operator: true});\n          this.index += token.length;\n        } else {\n          this.throwError('Unexpected next character ', this.index, this.index + 1);\n        }\n      }\n    }\n    return this.tokens;\n  },\n\n  is: function(ch, chars) {\n    return chars.indexOf(ch) !== -1;\n  },\n\n  peek: function(i) {\n    var num = i || 1;\n    return (this.index + num < this.text.length) ? this.text.charAt(this.index + num) : false;\n  },\n\n  isNumber: function(ch) {\n    return ('0' <= ch && ch <= '9') && typeof ch === \"string\";\n  },\n\n  isWhitespace: function(ch) {\n    // IE treats non-breaking space as \\u00A0\n    return (ch === ' ' || ch === '\\r' || ch === '\\t' ||\n            ch === '\\n' || ch === '\\v' || ch === '\\u00A0');\n  },\n\n  isIdent: function(ch) {\n    return ('a' <= ch && ch <= 'z' ||\n            'A' <= ch && ch <= 'Z' ||\n            '_' === ch || ch === '$');\n  },\n\n  isExpOperator: function(ch) {\n    return (ch === '-' || ch === '+' || this.isNumber(ch));\n  },\n\n  throwError: function(error, start, end) {\n    end = end || this.index;\n    var colStr = (isDefined(start)\n            ? 's ' + start +  '-' + this.index + ' [' + this.text.substring(start, end) + ']'\n            : ' ' + end);\n    throw $parseMinErr('lexerr', 'Lexer Error: {0} at column{1} in expression [{2}].',\n        error, colStr, this.text);\n  },\n\n  readNumber: function() {\n    var number = '';\n    var start = this.index;\n    while (this.index < this.text.length) {\n      var ch = lowercase(this.text.charAt(this.index));\n      if (ch == '.' || this.isNumber(ch)) {\n        number += ch;\n      } else {\n        var peekCh = this.peek();\n        if (ch == 'e' && this.isExpOperator(peekCh)) {\n          number += ch;\n        } else if (this.isExpOperator(ch) &&\n            peekCh && this.isNumber(peekCh) &&\n            number.charAt(number.length - 1) == 'e') {\n          number += ch;\n        } else if (this.isExpOperator(ch) &&\n            (!peekCh || !this.isNumber(peekCh)) &&\n            number.charAt(number.length - 1) == 'e') {\n          this.throwError('Invalid exponent');\n        } else {\n          break;\n        }\n      }\n      this.index++;\n    }\n    this.tokens.push({\n      index: start,\n      text: number,\n      constant: true,\n      value: Number(number)\n    });\n  },\n\n  readIdent: function() {\n    var start = this.index;\n    while (this.index < this.text.length) {\n      var ch = this.text.charAt(this.index);\n      if (!(this.isIdent(ch) || this.isNumber(ch))) {\n        break;\n      }\n      this.index++;\n    }\n    this.tokens.push({\n      index: start,\n      text: this.text.slice(start, this.index),\n      identifier: true\n    });\n  },\n\n  readString: function(quote) {\n    var start = this.index;\n    this.index++;\n    var string = '';\n    var rawString = quote;\n    var escape = false;\n    while (this.index < this.text.length) {\n      var ch = this.text.charAt(this.index);\n      rawString += ch;\n      if (escape) {\n        if (ch === 'u') {\n          var hex = this.text.substring(this.index + 1, this.index + 5);\n          if (!hex.match(/[\\da-f]{4}/i))\n            this.throwError('Invalid unicode escape [\\\\u' + hex + ']');\n          this.index += 4;\n          string += String.fromCharCode(parseInt(hex, 16));\n        } else {\n          var rep = ESCAPE[ch];\n          string = string + (rep || ch);\n        }\n        escape = false;\n      } else if (ch === '\\\\') {\n        escape = true;\n      } else if (ch === quote) {\n        this.index++;\n        this.tokens.push({\n          index: start,\n          text: rawString,\n          constant: true,\n          value: string\n        });\n        return;\n      } else {\n        string += ch;\n      }\n      this.index++;\n    }\n    this.throwError('Unterminated quote', start);\n  }\n};\n\n\nfunction isConstant(exp) {\n  return exp.constant;\n}\n\n/**\n * @constructor\n */\nvar Parser = function(lexer, $filter, options) {\n  this.lexer = lexer;\n  this.$filter = $filter;\n  this.options = options;\n};\n\nParser.ZERO = extend(function() {\n  return 0;\n}, {\n  sharedGetter: true,\n  constant: true\n});\n\nParser.prototype = {\n  constructor: Parser,\n\n  parse: function(text) {\n    this.text = text;\n    this.tokens = this.lexer.lex(text);\n\n    var value = this.statements();\n\n    if (this.tokens.length !== 0) {\n      this.throwError('is an unexpected token', this.tokens[0]);\n    }\n\n    value.literal = !!value.literal;\n    value.constant = !!value.constant;\n\n    return value;\n  },\n\n  primary: function() {\n    var primary;\n    if (this.expect('(')) {\n      primary = this.filterChain();\n      this.consume(')');\n    } else if (this.expect('[')) {\n      primary = this.arrayDeclaration();\n    } else if (this.expect('{')) {\n      primary = this.object();\n    } else if (this.peek().identifier && this.peek().text in CONSTANTS) {\n      primary = CONSTANTS[this.consume().text];\n    } else if (this.peek().identifier) {\n      primary = this.identifier();\n    } else if (this.peek().constant) {\n      primary = this.constant();\n    } else {\n      this.throwError('not a primary expression', this.peek());\n    }\n\n    var next, context;\n    while ((next = this.expect('(', '[', '.'))) {\n      if (next.text === '(') {\n        primary = this.functionCall(primary, context);\n        context = null;\n      } else if (next.text === '[') {\n        context = primary;\n        primary = this.objectIndex(primary);\n      } else if (next.text === '.') {\n        context = primary;\n        primary = this.fieldAccess(primary);\n      } else {\n        this.throwError('IMPOSSIBLE');\n      }\n    }\n    return primary;\n  },\n\n  throwError: function(msg, token) {\n    throw $parseMinErr('syntax',\n        'Syntax Error: Token \\'{0}\\' {1} at column {2} of the expression [{3}] starting at [{4}].',\n          token.text, msg, (token.index + 1), this.text, this.text.substring(token.index));\n  },\n\n  peekToken: function() {\n    if (this.tokens.length === 0)\n      throw $parseMinErr('ueoe', 'Unexpected end of expression: {0}', this.text);\n    return this.tokens[0];\n  },\n\n  peek: function(e1, e2, e3, e4) {\n    return this.peekAhead(0, e1, e2, e3, e4);\n  },\n  peekAhead: function(i, e1, e2, e3, e4) {\n    if (this.tokens.length > i) {\n      var token = this.tokens[i];\n      var t = token.text;\n      if (t === e1 || t === e2 || t === e3 || t === e4 ||\n          (!e1 && !e2 && !e3 && !e4)) {\n        return token;\n      }\n    }\n    return false;\n  },\n\n  expect: function(e1, e2, e3, e4) {\n    var token = this.peek(e1, e2, e3, e4);\n    if (token) {\n      this.tokens.shift();\n      return token;\n    }\n    return false;\n  },\n\n  consume: function(e1) {\n    if (this.tokens.length === 0) {\n      throw $parseMinErr('ueoe', 'Unexpected end of expression: {0}', this.text);\n    }\n\n    var token = this.expect(e1);\n    if (!token) {\n      this.throwError('is unexpected, expecting [' + e1 + ']', this.peek());\n    }\n    return token;\n  },\n\n  unaryFn: function(op, right) {\n    var fn = OPERATORS[op];\n    return extend(function $parseUnaryFn(self, locals) {\n      return fn(self, locals, right);\n    }, {\n      constant:right.constant,\n      inputs: [right]\n    });\n  },\n\n  binaryFn: function(left, op, right, isBranching) {\n    var fn = OPERATORS[op];\n    return extend(function $parseBinaryFn(self, locals) {\n      return fn(self, locals, left, right);\n    }, {\n      constant: left.constant && right.constant,\n      inputs: !isBranching && [left, right]\n    });\n  },\n\n  identifier: function() {\n    var id = this.consume().text;\n\n    //Continue reading each `.identifier` unless it is a method invocation\n    while (this.peek('.') && this.peekAhead(1).identifier && !this.peekAhead(2, '(')) {\n      id += this.consume().text + this.consume().text;\n    }\n\n    return getterFn(id, this.options, this.text);\n  },\n\n  constant: function() {\n    var value = this.consume().value;\n\n    return extend(function $parseConstant() {\n      return value;\n    }, {\n      constant: true,\n      literal: true\n    });\n  },\n\n  statements: function() {\n    var statements = [];\n    while (true) {\n      if (this.tokens.length > 0 && !this.peek('}', ')', ';', ']'))\n        statements.push(this.filterChain());\n      if (!this.expect(';')) {\n        // optimize for the common case where there is only one statement.\n        // TODO(size): maybe we should not support multiple statements?\n        return (statements.length === 1)\n            ? statements[0]\n            : function $parseStatements(self, locals) {\n                var value;\n                for (var i = 0, ii = statements.length; i < ii; i++) {\n                  value = statements[i](self, locals);\n                }\n                return value;\n              };\n      }\n    }\n  },\n\n  filterChain: function() {\n    var left = this.expression();\n    var token;\n    while ((token = this.expect('|'))) {\n      left = this.filter(left);\n    }\n    return left;\n  },\n\n  filter: function(inputFn) {\n    var fn = this.$filter(this.consume().text);\n    var argsFn;\n    var args;\n\n    if (this.peek(':')) {\n      argsFn = [];\n      args = []; // we can safely reuse the array\n      while (this.expect(':')) {\n        argsFn.push(this.expression());\n      }\n    }\n\n    var inputs = [inputFn].concat(argsFn || []);\n\n    return extend(function $parseFilter(self, locals) {\n      var input = inputFn(self, locals);\n      if (args) {\n        args[0] = input;\n\n        var i = argsFn.length;\n        while (i--) {\n          args[i + 1] = argsFn[i](self, locals);\n        }\n\n        return fn.apply(undefined, args);\n      }\n\n      return fn(input);\n    }, {\n      constant: !fn.$stateful && inputs.every(isConstant),\n      inputs: !fn.$stateful && inputs\n    });\n  },\n\n  expression: function() {\n    return this.assignment();\n  },\n\n  assignment: function() {\n    var left = this.ternary();\n    var right;\n    var token;\n    if ((token = this.expect('='))) {\n      if (!left.assign) {\n        this.throwError('implies assignment but [' +\n            this.text.substring(0, token.index) + '] can not be assigned to', token);\n      }\n      right = this.ternary();\n      return extend(function $parseAssignment(scope, locals) {\n        return left.assign(scope, right(scope, locals), locals);\n      }, {\n        inputs: [left, right]\n      });\n    }\n    return left;\n  },\n\n  ternary: function() {\n    var left = this.logicalOR();\n    var middle;\n    var token;\n    if ((token = this.expect('?'))) {\n      middle = this.assignment();\n      if (this.consume(':')) {\n        var right = this.assignment();\n\n        return extend(function $parseTernary(self, locals) {\n          return left(self, locals) ? middle(self, locals) : right(self, locals);\n        }, {\n          constant: left.constant && middle.constant && right.constant\n        });\n      }\n    }\n\n    return left;\n  },\n\n  logicalOR: function() {\n    var left = this.logicalAND();\n    var token;\n    while ((token = this.expect('||'))) {\n      left = this.binaryFn(left, token.text, this.logicalAND(), true);\n    }\n    return left;\n  },\n\n  logicalAND: function() {\n    var left = this.equality();\n    var token;\n    while ((token = this.expect('&&'))) {\n      left = this.binaryFn(left, token.text, this.equality(), true);\n    }\n    return left;\n  },\n\n  equality: function() {\n    var left = this.relational();\n    var token;\n    while ((token = this.expect('==','!=','===','!=='))) {\n      left = this.binaryFn(left, token.text, this.relational());\n    }\n    return left;\n  },\n\n  relational: function() {\n    var left = this.additive();\n    var token;\n    while ((token = this.expect('<', '>', '<=', '>='))) {\n      left = this.binaryFn(left, token.text, this.additive());\n    }\n    return left;\n  },\n\n  additive: function() {\n    var left = this.multiplicative();\n    var token;\n    while ((token = this.expect('+','-'))) {\n      left = this.binaryFn(left, token.text, this.multiplicative());\n    }\n    return left;\n  },\n\n  multiplicative: function() {\n    var left = this.unary();\n    var token;\n    while ((token = this.expect('*','/','%'))) {\n      left = this.binaryFn(left, token.text, this.unary());\n    }\n    return left;\n  },\n\n  unary: function() {\n    var token;\n    if (this.expect('+')) {\n      return this.primary();\n    } else if ((token = this.expect('-'))) {\n      return this.binaryFn(Parser.ZERO, token.text, this.unary());\n    } else if ((token = this.expect('!'))) {\n      return this.unaryFn(token.text, this.unary());\n    } else {\n      return this.primary();\n    }\n  },\n\n  fieldAccess: function(object) {\n    var getter = this.identifier();\n\n    return extend(function $parseFieldAccess(scope, locals, self) {\n      var o = self || object(scope, locals);\n      return (o == null) ? undefined : getter(o);\n    }, {\n      assign: function(scope, value, locals) {\n        var o = object(scope, locals);\n        if (!o) object.assign(scope, o = {}, locals);\n        return getter.assign(o, value);\n      }\n    });\n  },\n\n  objectIndex: function(obj) {\n    var expression = this.text;\n\n    var indexFn = this.expression();\n    this.consume(']');\n\n    return extend(function $parseObjectIndex(self, locals) {\n      var o = obj(self, locals),\n          i = indexFn(self, locals),\n          v;\n\n      ensureSafeMemberName(i, expression);\n      if (!o) return undefined;\n      v = ensureSafeObject(o[i], expression);\n      return v;\n    }, {\n      assign: function(self, value, locals) {\n        var key = ensureSafeMemberName(indexFn(self, locals), expression);\n        // prevent overwriting of Function.constructor which would break ensureSafeObject check\n        var o = ensureSafeObject(obj(self, locals), expression);\n        if (!o) obj.assign(self, o = {}, locals);\n        return o[key] = value;\n      }\n    });\n  },\n\n  functionCall: function(fnGetter, contextGetter) {\n    var argsFn = [];\n    if (this.peekToken().text !== ')') {\n      do {\n        argsFn.push(this.expression());\n      } while (this.expect(','));\n    }\n    this.consume(')');\n\n    var expressionText = this.text;\n    // we can safely reuse the array across invocations\n    var args = argsFn.length ? [] : null;\n\n    return function $parseFunctionCall(scope, locals) {\n      var context = contextGetter ? contextGetter(scope, locals) : isDefined(contextGetter) ? undefined : scope;\n      var fn = fnGetter(scope, locals, context) || noop;\n\n      if (args) {\n        var i = argsFn.length;\n        while (i--) {\n          args[i] = ensureSafeObject(argsFn[i](scope, locals), expressionText);\n        }\n      }\n\n      ensureSafeObject(context, expressionText);\n      ensureSafeFunction(fn, expressionText);\n\n      // IE doesn't have apply for some native functions\n      var v = fn.apply\n            ? fn.apply(context, args)\n            : fn(args[0], args[1], args[2], args[3], args[4]);\n\n      if (args) {\n        // Free-up the memory (arguments of the last function call).\n        args.length = 0;\n      }\n\n      return ensureSafeObject(v, expressionText);\n      };\n  },\n\n  // This is used with json array declaration\n  arrayDeclaration: function() {\n    var elementFns = [];\n    if (this.peekToken().text !== ']') {\n      do {\n        if (this.peek(']')) {\n          // Support trailing commas per ES5.1.\n          break;\n        }\n        elementFns.push(this.expression());\n      } while (this.expect(','));\n    }\n    this.consume(']');\n\n    return extend(function $parseArrayLiteral(self, locals) {\n      var array = [];\n      for (var i = 0, ii = elementFns.length; i < ii; i++) {\n        array.push(elementFns[i](self, locals));\n      }\n      return array;\n    }, {\n      literal: true,\n      constant: elementFns.every(isConstant),\n      inputs: elementFns\n    });\n  },\n\n  object: function() {\n    var keys = [], valueFns = [];\n    if (this.peekToken().text !== '}') {\n      do {\n        if (this.peek('}')) {\n          // Support trailing commas per ES5.1.\n          break;\n        }\n        var token = this.consume();\n        if (token.constant) {\n          keys.push(token.value);\n        } else if (token.identifier) {\n          keys.push(token.text);\n        } else {\n          this.throwError(\"invalid key\", token);\n        }\n        this.consume(':');\n        valueFns.push(this.expression());\n      } while (this.expect(','));\n    }\n    this.consume('}');\n\n    return extend(function $parseObjectLiteral(self, locals) {\n      var object = {};\n      for (var i = 0, ii = valueFns.length; i < ii; i++) {\n        object[keys[i]] = valueFns[i](self, locals);\n      }\n      return object;\n    }, {\n      literal: true,\n      constant: valueFns.every(isConstant),\n      inputs: valueFns\n    });\n  }\n};\n\n\n//////////////////////////////////////////////////\n// Parser helper functions\n//////////////////////////////////////////////////\n\nfunction setter(obj, locals, path, setValue, fullExp) {\n  ensureSafeObject(obj, fullExp);\n  ensureSafeObject(locals, fullExp);\n\n  var element = path.split('.'), key;\n  for (var i = 0; element.length > 1; i++) {\n    key = ensureSafeMemberName(element.shift(), fullExp);\n    var propertyObj = (i === 0 && locals && locals[key]) || obj[key];\n    if (!propertyObj) {\n      propertyObj = {};\n      obj[key] = propertyObj;\n    }\n    obj = ensureSafeObject(propertyObj, fullExp);\n  }\n  key = ensureSafeMemberName(element.shift(), fullExp);\n  ensureSafeObject(obj[key], fullExp);\n  obj[key] = setValue;\n  return setValue;\n}\n\nvar getterFnCacheDefault = createMap();\nvar getterFnCacheExpensive = createMap();\n\nfunction isPossiblyDangerousMemberName(name) {\n  return name == 'constructor';\n}\n\n/**\n * Implementation of the \"Black Hole\" variant from:\n * - http://jsperf.com/angularjs-parse-getter/4\n * - http://jsperf.com/path-evaluation-simplified/7\n */\nfunction cspSafeGetterFn(key0, key1, key2, key3, key4, fullExp, expensiveChecks) {\n  ensureSafeMemberName(key0, fullExp);\n  ensureSafeMemberName(key1, fullExp);\n  ensureSafeMemberName(key2, fullExp);\n  ensureSafeMemberName(key3, fullExp);\n  ensureSafeMemberName(key4, fullExp);\n  var eso = function(o) {\n    return ensureSafeObject(o, fullExp);\n  };\n  var eso0 = (expensiveChecks || isPossiblyDangerousMemberName(key0)) ? eso : identity;\n  var eso1 = (expensiveChecks || isPossiblyDangerousMemberName(key1)) ? eso : identity;\n  var eso2 = (expensiveChecks || isPossiblyDangerousMemberName(key2)) ? eso : identity;\n  var eso3 = (expensiveChecks || isPossiblyDangerousMemberName(key3)) ? eso : identity;\n  var eso4 = (expensiveChecks || isPossiblyDangerousMemberName(key4)) ? eso : identity;\n\n  return function cspSafeGetter(scope, locals) {\n    var pathVal = (locals && locals.hasOwnProperty(key0)) ? locals : scope;\n\n    if (pathVal == null) return pathVal;\n    pathVal = eso0(pathVal[key0]);\n\n    if (!key1) return pathVal;\n    if (pathVal == null) return undefined;\n    pathVal = eso1(pathVal[key1]);\n\n    if (!key2) return pathVal;\n    if (pathVal == null) return undefined;\n    pathVal = eso2(pathVal[key2]);\n\n    if (!key3) return pathVal;\n    if (pathVal == null) return undefined;\n    pathVal = eso3(pathVal[key3]);\n\n    if (!key4) return pathVal;\n    if (pathVal == null) return undefined;\n    pathVal = eso4(pathVal[key4]);\n\n    return pathVal;\n  };\n}\n\nfunction getterFnWithEnsureSafeObject(fn, fullExpression) {\n  return function(s, l) {\n    return fn(s, l, ensureSafeObject, fullExpression);\n  };\n}\n\nfunction getterFn(path, options, fullExp) {\n  var expensiveChecks = options.expensiveChecks;\n  var getterFnCache = (expensiveChecks ? getterFnCacheExpensive : getterFnCacheDefault);\n  var fn = getterFnCache[path];\n  if (fn) return fn;\n\n\n  var pathKeys = path.split('.'),\n      pathKeysLength = pathKeys.length;\n\n  // http://jsperf.com/angularjs-parse-getter/6\n  if (options.csp) {\n    if (pathKeysLength < 6) {\n      fn = cspSafeGetterFn(pathKeys[0], pathKeys[1], pathKeys[2], pathKeys[3], pathKeys[4], fullExp, expensiveChecks);\n    } else {\n      fn = function cspSafeGetter(scope, locals) {\n        var i = 0, val;\n        do {\n          val = cspSafeGetterFn(pathKeys[i++], pathKeys[i++], pathKeys[i++], pathKeys[i++],\n                                pathKeys[i++], fullExp, expensiveChecks)(scope, locals);\n\n          locals = undefined; // clear after first iteration\n          scope = val;\n        } while (i < pathKeysLength);\n        return val;\n      };\n    }\n  } else {\n    var code = '';\n    if (expensiveChecks) {\n      code += 's = eso(s, fe);\\nl = eso(l, fe);\\n';\n    }\n    var needsEnsureSafeObject = expensiveChecks;\n    forEach(pathKeys, function(key, index) {\n      ensureSafeMemberName(key, fullExp);\n      var lookupJs = (index\n                      // we simply dereference 's' on any .dot notation\n                      ? 's'\n                      // but if we are first then we check locals first, and if so read it first\n                      : '((l&&l.hasOwnProperty(\"' + key + '\"))?l:s)') + '.' + key;\n      if (expensiveChecks || isPossiblyDangerousMemberName(key)) {\n        lookupJs = 'eso(' + lookupJs + ', fe)';\n        needsEnsureSafeObject = true;\n      }\n      code += 'if(s == null) return undefined;\\n' +\n              's=' + lookupJs + ';\\n';\n    });\n    code += 'return s;';\n\n    /* jshint -W054 */\n    var evaledFnGetter = new Function('s', 'l', 'eso', 'fe', code); // s=scope, l=locals, eso=ensureSafeObject\n    /* jshint +W054 */\n    evaledFnGetter.toString = valueFn(code);\n    if (needsEnsureSafeObject) {\n      evaledFnGetter = getterFnWithEnsureSafeObject(evaledFnGetter, fullExp);\n    }\n    fn = evaledFnGetter;\n  }\n\n  fn.sharedGetter = true;\n  fn.assign = function(self, value, locals) {\n    return setter(self, locals, path, value, path);\n  };\n  getterFnCache[path] = fn;\n  return fn;\n}\n\nvar objectValueOf = Object.prototype.valueOf;\n\nfunction getValueOf(value) {\n  return isFunction(value.valueOf) ? value.valueOf() : objectValueOf.call(value);\n}\n\n///////////////////////////////////\n\n/**\n * @ngdoc service\n * @name $parse\n * @kind function\n *\n * @description\n *\n * Converts Angular {@link guide/expression expression} into a function.\n *\n * ```js\n *   var getter = $parse('user.name');\n *   var setter = getter.assign;\n *   var context = {user:{name:'angular'}};\n *   var locals = {user:{name:'local'}};\n *\n *   expect(getter(context)).toEqual('angular');\n *   setter(context, 'newValue');\n *   expect(context.user.name).toEqual('newValue');\n *   expect(getter(context, locals)).toEqual('local');\n * ```\n *\n *\n * @param {string} expression String expression to compile.\n * @returns {function(context, locals)} a function which represents the compiled expression:\n *\n *    * `context` – `{object}` – an object against which any expressions embedded in the strings\n *      are evaluated against (typically a scope object).\n *    * `locals` – `{object=}` – local variables context object, useful for overriding values in\n *      `context`.\n *\n *    The returned function also has the following properties:\n *      * `literal` – `{boolean}` – whether the expression's top-level node is a JavaScript\n *        literal.\n *      * `constant` – `{boolean}` – whether the expression is made entirely of JavaScript\n *        constant literals.\n *      * `assign` – `{?function(context, value)}` – if the expression is assignable, this will be\n *        set to a function to change its value on the given context.\n *\n */\n\n\n/**\n * @ngdoc provider\n * @name $parseProvider\n *\n * @description\n * `$parseProvider` can be used for configuring the default behavior of the {@link ng.$parse $parse}\n *  service.\n */\nfunction $ParseProvider() {\n  var cacheDefault = createMap();\n  var cacheExpensive = createMap();\n\n\n\n  this.$get = ['$filter', '$sniffer', function($filter, $sniffer) {\n    var $parseOptions = {\n          csp: $sniffer.csp,\n          expensiveChecks: false\n        },\n        $parseOptionsExpensive = {\n          csp: $sniffer.csp,\n          expensiveChecks: true\n        };\n\n    function wrapSharedExpression(exp) {\n      var wrapped = exp;\n\n      if (exp.sharedGetter) {\n        wrapped = function $parseWrapper(self, locals) {\n          return exp(self, locals);\n        };\n        wrapped.literal = exp.literal;\n        wrapped.constant = exp.constant;\n        wrapped.assign = exp.assign;\n      }\n\n      return wrapped;\n    }\n\n    return function $parse(exp, interceptorFn, expensiveChecks) {\n      var parsedExpression, oneTime, cacheKey;\n\n      switch (typeof exp) {\n        case 'string':\n          cacheKey = exp = exp.trim();\n\n          var cache = (expensiveChecks ? cacheExpensive : cacheDefault);\n          parsedExpression = cache[cacheKey];\n\n          if (!parsedExpression) {\n            if (exp.charAt(0) === ':' && exp.charAt(1) === ':') {\n              oneTime = true;\n              exp = exp.substring(2);\n            }\n\n            var parseOptions = expensiveChecks ? $parseOptionsExpensive : $parseOptions;\n            var lexer = new Lexer(parseOptions);\n            var parser = new Parser(lexer, $filter, parseOptions);\n            parsedExpression = parser.parse(exp);\n\n            if (parsedExpression.constant) {\n              parsedExpression.$$watchDelegate = constantWatchDelegate;\n            } else if (oneTime) {\n              //oneTime is not part of the exp passed to the Parser so we may have to\n              //wrap the parsedExpression before adding a $$watchDelegate\n              parsedExpression = wrapSharedExpression(parsedExpression);\n              parsedExpression.$$watchDelegate = parsedExpression.literal ?\n                oneTimeLiteralWatchDelegate : oneTimeWatchDelegate;\n            } else if (parsedExpression.inputs) {\n              parsedExpression.$$watchDelegate = inputsWatchDelegate;\n            }\n\n            cache[cacheKey] = parsedExpression;\n          }\n          return addInterceptor(parsedExpression, interceptorFn);\n\n        case 'function':\n          return addInterceptor(exp, interceptorFn);\n\n        default:\n          return addInterceptor(noop, interceptorFn);\n      }\n    };\n\n    function collectExpressionInputs(inputs, list) {\n      for (var i = 0, ii = inputs.length; i < ii; i++) {\n        var input = inputs[i];\n        if (!input.constant) {\n          if (input.inputs) {\n            collectExpressionInputs(input.inputs, list);\n          } else if (list.indexOf(input) === -1) { // TODO(perf) can we do better?\n            list.push(input);\n          }\n        }\n      }\n\n      return list;\n    }\n\n    function expressionInputDirtyCheck(newValue, oldValueOfValue) {\n\n      if (newValue == null || oldValueOfValue == null) { // null/undefined\n        return newValue === oldValueOfValue;\n      }\n\n      if (typeof newValue === 'object') {\n\n        // attempt to convert the value to a primitive type\n        // TODO(docs): add a note to docs that by implementing valueOf even objects and arrays can\n        //             be cheaply dirty-checked\n        newValue = getValueOf(newValue);\n\n        if (typeof newValue === 'object') {\n          // objects/arrays are not supported - deep-watching them would be too expensive\n          return false;\n        }\n\n        // fall-through to the primitive equality check\n      }\n\n      //Primitive or NaN\n      return newValue === oldValueOfValue || (newValue !== newValue && oldValueOfValue !== oldValueOfValue);\n    }\n\n    function inputsWatchDelegate(scope, listener, objectEquality, parsedExpression) {\n      var inputExpressions = parsedExpression.$$inputs ||\n                    (parsedExpression.$$inputs = collectExpressionInputs(parsedExpression.inputs, []));\n\n      var lastResult;\n\n      if (inputExpressions.length === 1) {\n        var oldInputValue = expressionInputDirtyCheck; // init to something unique so that equals check fails\n        inputExpressions = inputExpressions[0];\n        return scope.$watch(function expressionInputWatch(scope) {\n          var newInputValue = inputExpressions(scope);\n          if (!expressionInputDirtyCheck(newInputValue, oldInputValue)) {\n            lastResult = parsedExpression(scope);\n            oldInputValue = newInputValue && getValueOf(newInputValue);\n          }\n          return lastResult;\n        }, listener, objectEquality);\n      }\n\n      var oldInputValueOfValues = [];\n      for (var i = 0, ii = inputExpressions.length; i < ii; i++) {\n        oldInputValueOfValues[i] = expressionInputDirtyCheck; // init to something unique so that equals check fails\n      }\n\n      return scope.$watch(function expressionInputsWatch(scope) {\n        var changed = false;\n\n        for (var i = 0, ii = inputExpressions.length; i < ii; i++) {\n          var newInputValue = inputExpressions[i](scope);\n          if (changed || (changed = !expressionInputDirtyCheck(newInputValue, oldInputValueOfValues[i]))) {\n            oldInputValueOfValues[i] = newInputValue && getValueOf(newInputValue);\n          }\n        }\n\n        if (changed) {\n          lastResult = parsedExpression(scope);\n        }\n\n        return lastResult;\n      }, listener, objectEquality);\n    }\n\n    function oneTimeWatchDelegate(scope, listener, objectEquality, parsedExpression) {\n      var unwatch, lastValue;\n      return unwatch = scope.$watch(function oneTimeWatch(scope) {\n        return parsedExpression(scope);\n      }, function oneTimeListener(value, old, scope) {\n        lastValue = value;\n        if (isFunction(listener)) {\n          listener.apply(this, arguments);\n        }\n        if (isDefined(value)) {\n          scope.$$postDigest(function() {\n            if (isDefined(lastValue)) {\n              unwatch();\n            }\n          });\n        }\n      }, objectEquality);\n    }\n\n    function oneTimeLiteralWatchDelegate(scope, listener, objectEquality, parsedExpression) {\n      var unwatch, lastValue;\n      return unwatch = scope.$watch(function oneTimeWatch(scope) {\n        return parsedExpression(scope);\n      }, function oneTimeListener(value, old, scope) {\n        lastValue = value;\n        if (isFunction(listener)) {\n          listener.call(this, value, old, scope);\n        }\n        if (isAllDefined(value)) {\n          scope.$$postDigest(function() {\n            if (isAllDefined(lastValue)) unwatch();\n          });\n        }\n      }, objectEquality);\n\n      function isAllDefined(value) {\n        var allDefined = true;\n        forEach(value, function(val) {\n          if (!isDefined(val)) allDefined = false;\n        });\n        return allDefined;\n      }\n    }\n\n    function constantWatchDelegate(scope, listener, objectEquality, parsedExpression) {\n      var unwatch;\n      return unwatch = scope.$watch(function constantWatch(scope) {\n        return parsedExpression(scope);\n      }, function constantListener(value, old, scope) {\n        if (isFunction(listener)) {\n          listener.apply(this, arguments);\n        }\n        unwatch();\n      }, objectEquality);\n    }\n\n    function addInterceptor(parsedExpression, interceptorFn) {\n      if (!interceptorFn) return parsedExpression;\n      var watchDelegate = parsedExpression.$$watchDelegate;\n\n      var regularWatch =\n          watchDelegate !== oneTimeLiteralWatchDelegate &&\n          watchDelegate !== oneTimeWatchDelegate;\n\n      var fn = regularWatch ? function regularInterceptedExpression(scope, locals) {\n        var value = parsedExpression(scope, locals);\n        return interceptorFn(value, scope, locals);\n      } : function oneTimeInterceptedExpression(scope, locals) {\n        var value = parsedExpression(scope, locals);\n        var result = interceptorFn(value, scope, locals);\n        // we only return the interceptor's result if the\n        // initial value is defined (for bind-once)\n        return isDefined(value) ? result : value;\n      };\n\n      // Propagate $$watchDelegates other then inputsWatchDelegate\n      if (parsedExpression.$$watchDelegate &&\n          parsedExpression.$$watchDelegate !== inputsWatchDelegate) {\n        fn.$$watchDelegate = parsedExpression.$$watchDelegate;\n      } else if (!interceptorFn.$stateful) {\n        // If there is an interceptor, but no watchDelegate then treat the interceptor like\n        // we treat filters - it is assumed to be a pure function unless flagged with $stateful\n        fn.$$watchDelegate = inputsWatchDelegate;\n        fn.inputs = [parsedExpression];\n      }\n\n      return fn;\n    }\n  }];\n}\n\n/**\n * @ngdoc service\n * @name $q\n * @requires $rootScope\n *\n * @description\n * A service that helps you run functions asynchronously, and use their return values (or exceptions)\n * when they are done processing.\n *\n * This is an implementation of promises/deferred objects inspired by\n * [Kris Kowal's Q](https://github.com/kriskowal/q).\n *\n * $q can be used in two fashions --- one which is more similar to Kris Kowal's Q or jQuery's Deferred\n * implementations, and the other which resembles ES6 promises to some degree.\n *\n * # $q constructor\n *\n * The streamlined ES6 style promise is essentially just using $q as a constructor which takes a `resolver`\n * function as the first argument. This is similar to the native Promise implementation from ES6 Harmony,\n * see [MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise).\n *\n * While the constructor-style use is supported, not all of the supporting methods from ES6 Harmony promises are\n * available yet.\n *\n * It can be used like so:\n *\n * ```js\n *   // for the purpose of this example let's assume that variables `$q` and `okToGreet`\n *   // are available in the current lexical scope (they could have been injected or passed in).\n *\n *   function asyncGreet(name) {\n *     // perform some asynchronous operation, resolve or reject the promise when appropriate.\n *     return $q(function(resolve, reject) {\n *       setTimeout(function() {\n *         if (okToGreet(name)) {\n *           resolve('Hello, ' + name + '!');\n *         } else {\n *           reject('Greeting ' + name + ' is not allowed.');\n *         }\n *       }, 1000);\n *     });\n *   }\n *\n *   var promise = asyncGreet('Robin Hood');\n *   promise.then(function(greeting) {\n *     alert('Success: ' + greeting);\n *   }, function(reason) {\n *     alert('Failed: ' + reason);\n *   });\n * ```\n *\n * Note: progress/notify callbacks are not currently supported via the ES6-style interface.\n *\n * However, the more traditional CommonJS-style usage is still available, and documented below.\n *\n * [The CommonJS Promise proposal](http://wiki.commonjs.org/wiki/Promises) describes a promise as an\n * interface for interacting with an object that represents the result of an action that is\n * performed asynchronously, and may or may not be finished at any given point in time.\n *\n * From the perspective of dealing with error handling, deferred and promise APIs are to\n * asynchronous programming what `try`, `catch` and `throw` keywords are to synchronous programming.\n *\n * ```js\n *   // for the purpose of this example let's assume that variables `$q` and `okToGreet`\n *   // are available in the current lexical scope (they could have been injected or passed in).\n *\n *   function asyncGreet(name) {\n *     var deferred = $q.defer();\n *\n *     setTimeout(function() {\n *       deferred.notify('About to greet ' + name + '.');\n *\n *       if (okToGreet(name)) {\n *         deferred.resolve('Hello, ' + name + '!');\n *       } else {\n *         deferred.reject('Greeting ' + name + ' is not allowed.');\n *       }\n *     }, 1000);\n *\n *     return deferred.promise;\n *   }\n *\n *   var promise = asyncGreet('Robin Hood');\n *   promise.then(function(greeting) {\n *     alert('Success: ' + greeting);\n *   }, function(reason) {\n *     alert('Failed: ' + reason);\n *   }, function(update) {\n *     alert('Got notification: ' + update);\n *   });\n * ```\n *\n * At first it might not be obvious why this extra complexity is worth the trouble. The payoff\n * comes in the way of guarantees that promise and deferred APIs make, see\n * https://github.com/kriskowal/uncommonjs/blob/master/promises/specification.md.\n *\n * Additionally the promise api allows for composition that is very hard to do with the\n * traditional callback ([CPS](http://en.wikipedia.org/wiki/Continuation-passing_style)) approach.\n * For more on this please see the [Q documentation](https://github.com/kriskowal/q) especially the\n * section on serial or parallel joining of promises.\n *\n * # The Deferred API\n *\n * A new instance of deferred is constructed by calling `$q.defer()`.\n *\n * The purpose of the deferred object is to expose the associated Promise instance as well as APIs\n * that can be used for signaling the successful or unsuccessful completion, as well as the status\n * of the task.\n *\n * **Methods**\n *\n * - `resolve(value)` – resolves the derived promise with the `value`. If the value is a rejection\n *   constructed via `$q.reject`, the promise will be rejected instead.\n * - `reject(reason)` – rejects the derived promise with the `reason`. This is equivalent to\n *   resolving it with a rejection constructed via `$q.reject`.\n * - `notify(value)` - provides updates on the status of the promise's execution. This may be called\n *   multiple times before the promise is either resolved or rejected.\n *\n * **Properties**\n *\n * - promise – `{Promise}` – promise object associated with this deferred.\n *\n *\n * # The Promise API\n *\n * A new promise instance is created when a deferred instance is created and can be retrieved by\n * calling `deferred.promise`.\n *\n * The purpose of the promise object is to allow for interested parties to get access to the result\n * of the deferred task when it completes.\n *\n * **Methods**\n *\n * - `then(successCallback, errorCallback, notifyCallback)` – regardless of when the promise was or\n *   will be resolved or rejected, `then` calls one of the success or error callbacks asynchronously\n *   as soon as the result is available. The callbacks are called with a single argument: the result\n *   or rejection reason. Additionally, the notify callback may be called zero or more times to\n *   provide a progress indication, before the promise is resolved or rejected.\n *\n *   This method *returns a new promise* which is resolved or rejected via the return value of the\n *   `successCallback`, `errorCallback`. It also notifies via the return value of the\n *   `notifyCallback` method. The promise cannot be resolved or rejected from the notifyCallback\n *   method.\n *\n * - `catch(errorCallback)` – shorthand for `promise.then(null, errorCallback)`\n *\n * - `finally(callback, notifyCallback)` – allows you to observe either the fulfillment or rejection of a promise,\n *   but to do so without modifying the final value. This is useful to release resources or do some\n *   clean-up that needs to be done whether the promise was rejected or resolved. See the [full\n *   specification](https://github.com/kriskowal/q/wiki/API-Reference#promisefinallycallback) for\n *   more information.\n *\n * # Chaining promises\n *\n * Because calling the `then` method of a promise returns a new derived promise, it is easily\n * possible to create a chain of promises:\n *\n * ```js\n *   promiseB = promiseA.then(function(result) {\n *     return result + 1;\n *   });\n *\n *   // promiseB will be resolved immediately after promiseA is resolved and its value\n *   // will be the result of promiseA incremented by 1\n * ```\n *\n * It is possible to create chains of any length and since a promise can be resolved with another\n * promise (which will defer its resolution further), it is possible to pause/defer resolution of\n * the promises at any point in the chain. This makes it possible to implement powerful APIs like\n * $http's response interceptors.\n *\n *\n * # Differences between Kris Kowal's Q and $q\n *\n *  There are two main differences:\n *\n * - $q is integrated with the {@link ng.$rootScope.Scope} Scope model observation\n *   mechanism in angular, which means faster propagation of resolution or rejection into your\n *   models and avoiding unnecessary browser repaints, which would result in flickering UI.\n * - Q has many more features than $q, but that comes at a cost of bytes. $q is tiny, but contains\n *   all the important functionality needed for common async tasks.\n *\n *  # Testing\n *\n *  ```js\n *    it('should simulate promise', inject(function($q, $rootScope) {\n *      var deferred = $q.defer();\n *      var promise = deferred.promise;\n *      var resolvedValue;\n *\n *      promise.then(function(value) { resolvedValue = value; });\n *      expect(resolvedValue).toBeUndefined();\n *\n *      // Simulate resolving of promise\n *      deferred.resolve(123);\n *      // Note that the 'then' function does not get called synchronously.\n *      // This is because we want the promise API to always be async, whether or not\n *      // it got called synchronously or asynchronously.\n *      expect(resolvedValue).toBeUndefined();\n *\n *      // Propagate promise resolution to 'then' functions using $apply().\n *      $rootScope.$apply();\n *      expect(resolvedValue).toEqual(123);\n *    }));\n *  ```\n *\n * @param {function(function, function)} resolver Function which is responsible for resolving or\n *   rejecting the newly created promise. The first parameter is a function which resolves the\n *   promise, the second parameter is a function which rejects the promise.\n *\n * @returns {Promise} The newly created promise.\n */\nfunction $QProvider() {\n\n  this.$get = ['$rootScope', '$exceptionHandler', function($rootScope, $exceptionHandler) {\n    return qFactory(function(callback) {\n      $rootScope.$evalAsync(callback);\n    }, $exceptionHandler);\n  }];\n}\n\nfunction $$QProvider() {\n  this.$get = ['$browser', '$exceptionHandler', function($browser, $exceptionHandler) {\n    return qFactory(function(callback) {\n      $browser.defer(callback);\n    }, $exceptionHandler);\n  }];\n}\n\n/**\n * Constructs a promise manager.\n *\n * @param {function(function)} nextTick Function for executing functions in the next turn.\n * @param {function(...*)} exceptionHandler Function into which unexpected exceptions are passed for\n *     debugging purposes.\n * @returns {object} Promise manager.\n */\nfunction qFactory(nextTick, exceptionHandler) {\n  var $qMinErr = minErr('$q', TypeError);\n  function callOnce(self, resolveFn, rejectFn) {\n    var called = false;\n    function wrap(fn) {\n      return function(value) {\n        if (called) return;\n        called = true;\n        fn.call(self, value);\n      };\n    }\n\n    return [wrap(resolveFn), wrap(rejectFn)];\n  }\n\n  /**\n   * @ngdoc method\n   * @name ng.$q#defer\n   * @kind function\n   *\n   * @description\n   * Creates a `Deferred` object which represents a task which will finish in the future.\n   *\n   * @returns {Deferred} Returns a new instance of deferred.\n   */\n  var defer = function() {\n    return new Deferred();\n  };\n\n  function Promise() {\n    this.$$state = { status: 0 };\n  }\n\n  Promise.prototype = {\n    then: function(onFulfilled, onRejected, progressBack) {\n      var result = new Deferred();\n\n      this.$$state.pending = this.$$state.pending || [];\n      this.$$state.pending.push([result, onFulfilled, onRejected, progressBack]);\n      if (this.$$state.status > 0) scheduleProcessQueue(this.$$state);\n\n      return result.promise;\n    },\n\n    \"catch\": function(callback) {\n      return this.then(null, callback);\n    },\n\n    \"finally\": function(callback, progressBack) {\n      return this.then(function(value) {\n        return handleCallback(value, true, callback);\n      }, function(error) {\n        return handleCallback(error, false, callback);\n      }, progressBack);\n    }\n  };\n\n  //Faster, more basic than angular.bind http://jsperf.com/angular-bind-vs-custom-vs-native\n  function simpleBind(context, fn) {\n    return function(value) {\n      fn.call(context, value);\n    };\n  }\n\n  function processQueue(state) {\n    var fn, promise, pending;\n\n    pending = state.pending;\n    state.processScheduled = false;\n    state.pending = undefined;\n    for (var i = 0, ii = pending.length; i < ii; ++i) {\n      promise = pending[i][0];\n      fn = pending[i][state.status];\n      try {\n        if (isFunction(fn)) {\n          promise.resolve(fn(state.value));\n        } else if (state.status === 1) {\n          promise.resolve(state.value);\n        } else {\n          promise.reject(state.value);\n        }\n      } catch (e) {\n        promise.reject(e);\n        exceptionHandler(e);\n      }\n    }\n  }\n\n  function scheduleProcessQueue(state) {\n    if (state.processScheduled || !state.pending) return;\n    state.processScheduled = true;\n    nextTick(function() { processQueue(state); });\n  }\n\n  function Deferred() {\n    this.promise = new Promise();\n    //Necessary to support unbound execution :/\n    this.resolve = simpleBind(this, this.resolve);\n    this.reject = simpleBind(this, this.reject);\n    this.notify = simpleBind(this, this.notify);\n  }\n\n  Deferred.prototype = {\n    resolve: function(val) {\n      if (this.promise.$$state.status) return;\n      if (val === this.promise) {\n        this.$$reject($qMinErr(\n          'qcycle',\n          \"Expected promise to be resolved with value other than itself '{0}'\",\n          val));\n      } else {\n        this.$$resolve(val);\n      }\n\n    },\n\n    $$resolve: function(val) {\n      var then, fns;\n\n      fns = callOnce(this, this.$$resolve, this.$$reject);\n      try {\n        if ((isObject(val) || isFunction(val))) then = val && val.then;\n        if (isFunction(then)) {\n          this.promise.$$state.status = -1;\n          then.call(val, fns[0], fns[1], this.notify);\n        } else {\n          this.promise.$$state.value = val;\n          this.promise.$$state.status = 1;\n          scheduleProcessQueue(this.promise.$$state);\n        }\n      } catch (e) {\n        fns[1](e);\n        exceptionHandler(e);\n      }\n    },\n\n    reject: function(reason) {\n      if (this.promise.$$state.status) return;\n      this.$$reject(reason);\n    },\n\n    $$reject: function(reason) {\n      this.promise.$$state.value = reason;\n      this.promise.$$state.status = 2;\n      scheduleProcessQueue(this.promise.$$state);\n    },\n\n    notify: function(progress) {\n      var callbacks = this.promise.$$state.pending;\n\n      if ((this.promise.$$state.status <= 0) && callbacks && callbacks.length) {\n        nextTick(function() {\n          var callback, result;\n          for (var i = 0, ii = callbacks.length; i < ii; i++) {\n            result = callbacks[i][0];\n            callback = callbacks[i][3];\n            try {\n              result.notify(isFunction(callback) ? callback(progress) : progress);\n            } catch (e) {\n              exceptionHandler(e);\n            }\n          }\n        });\n      }\n    }\n  };\n\n  /**\n   * @ngdoc method\n   * @name $q#reject\n   * @kind function\n   *\n   * @description\n   * Creates a promise that is resolved as rejected with the specified `reason`. This api should be\n   * used to forward rejection in a chain of promises. If you are dealing with the last promise in\n   * a promise chain, you don't need to worry about it.\n   *\n   * When comparing deferreds/promises to the familiar behavior of try/catch/throw, think of\n   * `reject` as the `throw` keyword in JavaScript. This also means that if you \"catch\" an error via\n   * a promise error callback and you want to forward the error to the promise derived from the\n   * current promise, you have to \"rethrow\" the error by returning a rejection constructed via\n   * `reject`.\n   *\n   * ```js\n   *   promiseB = promiseA.then(function(result) {\n   *     // success: do something and resolve promiseB\n   *     //          with the old or a new result\n   *     return result;\n   *   }, function(reason) {\n   *     // error: handle the error if possible and\n   *     //        resolve promiseB with newPromiseOrValue,\n   *     //        otherwise forward the rejection to promiseB\n   *     if (canHandle(reason)) {\n   *      // handle the error and recover\n   *      return newPromiseOrValue;\n   *     }\n   *     return $q.reject(reason);\n   *   });\n   * ```\n   *\n   * @param {*} reason Constant, message, exception or an object representing the rejection reason.\n   * @returns {Promise} Returns a promise that was already resolved as rejected with the `reason`.\n   */\n  var reject = function(reason) {\n    var result = new Deferred();\n    result.reject(reason);\n    return result.promise;\n  };\n\n  var makePromise = function makePromise(value, resolved) {\n    var result = new Deferred();\n    if (resolved) {\n      result.resolve(value);\n    } else {\n      result.reject(value);\n    }\n    return result.promise;\n  };\n\n  var handleCallback = function handleCallback(value, isResolved, callback) {\n    var callbackOutput = null;\n    try {\n      if (isFunction(callback)) callbackOutput = callback();\n    } catch (e) {\n      return makePromise(e, false);\n    }\n    if (isPromiseLike(callbackOutput)) {\n      return callbackOutput.then(function() {\n        return makePromise(value, isResolved);\n      }, function(error) {\n        return makePromise(error, false);\n      });\n    } else {\n      return makePromise(value, isResolved);\n    }\n  };\n\n  /**\n   * @ngdoc method\n   * @name $q#when\n   * @kind function\n   *\n   * @description\n   * Wraps an object that might be a value or a (3rd party) then-able promise into a $q promise.\n   * This is useful when you are dealing with an object that might or might not be a promise, or if\n   * the promise comes from a source that can't be trusted.\n   *\n   * @param {*} value Value or a promise\n   * @returns {Promise} Returns a promise of the passed value or promise\n   */\n\n\n  var when = function(value, callback, errback, progressBack) {\n    var result = new Deferred();\n    result.resolve(value);\n    return result.promise.then(callback, errback, progressBack);\n  };\n\n  /**\n   * @ngdoc method\n   * @name $q#all\n   * @kind function\n   *\n   * @description\n   * Combines multiple promises into a single promise that is resolved when all of the input\n   * promises are resolved.\n   *\n   * @param {Array.<Promise>|Object.<Promise>} promises An array or hash of promises.\n   * @returns {Promise} Returns a single promise that will be resolved with an array/hash of values,\n   *   each value corresponding to the promise at the same index/key in the `promises` array/hash.\n   *   If any of the promises is resolved with a rejection, this resulting promise will be rejected\n   *   with the same rejection value.\n   */\n\n  function all(promises) {\n    var deferred = new Deferred(),\n        counter = 0,\n        results = isArray(promises) ? [] : {};\n\n    forEach(promises, function(promise, key) {\n      counter++;\n      when(promise).then(function(value) {\n        if (results.hasOwnProperty(key)) return;\n        results[key] = value;\n        if (!(--counter)) deferred.resolve(results);\n      }, function(reason) {\n        if (results.hasOwnProperty(key)) return;\n        deferred.reject(reason);\n      });\n    });\n\n    if (counter === 0) {\n      deferred.resolve(results);\n    }\n\n    return deferred.promise;\n  }\n\n  var $Q = function Q(resolver) {\n    if (!isFunction(resolver)) {\n      throw $qMinErr('norslvr', \"Expected resolverFn, got '{0}'\", resolver);\n    }\n\n    if (!(this instanceof Q)) {\n      // More useful when $Q is the Promise itself.\n      return new Q(resolver);\n    }\n\n    var deferred = new Deferred();\n\n    function resolveFn(value) {\n      deferred.resolve(value);\n    }\n\n    function rejectFn(reason) {\n      deferred.reject(reason);\n    }\n\n    resolver(resolveFn, rejectFn);\n\n    return deferred.promise;\n  };\n\n  $Q.defer = defer;\n  $Q.reject = reject;\n  $Q.when = when;\n  $Q.all = all;\n\n  return $Q;\n}\n\nfunction $$RAFProvider() { //rAF\n  this.$get = ['$window', '$timeout', function($window, $timeout) {\n    var requestAnimationFrame = $window.requestAnimationFrame ||\n                                $window.webkitRequestAnimationFrame;\n\n    var cancelAnimationFrame = $window.cancelAnimationFrame ||\n                               $window.webkitCancelAnimationFrame ||\n                               $window.webkitCancelRequestAnimationFrame;\n\n    var rafSupported = !!requestAnimationFrame;\n    var raf = rafSupported\n      ? function(fn) {\n          var id = requestAnimationFrame(fn);\n          return function() {\n            cancelAnimationFrame(id);\n          };\n        }\n      : function(fn) {\n          var timer = $timeout(fn, 16.66, false); // 1000 / 60 = 16.666\n          return function() {\n            $timeout.cancel(timer);\n          };\n        };\n\n    raf.supported = rafSupported;\n\n    return raf;\n  }];\n}\n\n/**\n * DESIGN NOTES\n *\n * The design decisions behind the scope are heavily favored for speed and memory consumption.\n *\n * The typical use of scope is to watch the expressions, which most of the time return the same\n * value as last time so we optimize the operation.\n *\n * Closures construction is expensive in terms of speed as well as memory:\n *   - No closures, instead use prototypical inheritance for API\n *   - Internal state needs to be stored on scope directly, which means that private state is\n *     exposed as $$____ properties\n *\n * Loop operations are optimized by using while(count--) { ... }\n *   - this means that in order to keep the same order of execution as addition we have to add\n *     items to the array at the beginning (unshift) instead of at the end (push)\n *\n * Child scopes are created and removed often\n *   - Using an array would be slow since inserts in middle are expensive so we use linked list\n *\n * There are few watches then a lot of observers. This is why you don't want the observer to be\n * implemented in the same way as watch. Watch requires return of initialization function which\n * are expensive to construct.\n */\n\n\n/**\n * @ngdoc provider\n * @name $rootScopeProvider\n * @description\n *\n * Provider for the $rootScope service.\n */\n\n/**\n * @ngdoc method\n * @name $rootScopeProvider#digestTtl\n * @description\n *\n * Sets the number of `$digest` iterations the scope should attempt to execute before giving up and\n * assuming that the model is unstable.\n *\n * The current default is 10 iterations.\n *\n * In complex applications it's possible that the dependencies between `$watch`s will result in\n * several digest iterations. However if an application needs more than the default 10 digest\n * iterations for its model to stabilize then you should investigate what is causing the model to\n * continuously change during the digest.\n *\n * Increasing the TTL could have performance implications, so you should not change it without\n * proper justification.\n *\n * @param {number} limit The number of digest iterations.\n */\n\n\n/**\n * @ngdoc service\n * @name $rootScope\n * @description\n *\n * Every application has a single root {@link ng.$rootScope.Scope scope}.\n * All other scopes are descendant scopes of the root scope. Scopes provide separation\n * between the model and the view, via a mechanism for watching the model for changes.\n * They also provide an event emission/broadcast and subscription facility. See the\n * {@link guide/scope developer guide on scopes}.\n */\nfunction $RootScopeProvider() {\n  var TTL = 10;\n  var $rootScopeMinErr = minErr('$rootScope');\n  var lastDirtyWatch = null;\n  var applyAsyncId = null;\n\n  this.digestTtl = function(value) {\n    if (arguments.length) {\n      TTL = value;\n    }\n    return TTL;\n  };\n\n  this.$get = ['$injector', '$exceptionHandler', '$parse', '$browser',\n      function($injector, $exceptionHandler, $parse, $browser) {\n\n    /**\n     * @ngdoc type\n     * @name $rootScope.Scope\n     *\n     * @description\n     * A root scope can be retrieved using the {@link ng.$rootScope $rootScope} key from the\n     * {@link auto.$injector $injector}. Child scopes are created using the\n     * {@link ng.$rootScope.Scope#$new $new()} method. (Most scopes are created automatically when\n     * compiled HTML template is executed.)\n     *\n     * Here is a simple scope snippet to show how you can interact with the scope.\n     * ```html\n     * <file src=\"./test/ng/rootScopeSpec.js\" tag=\"docs1\" />\n     * ```\n     *\n     * # Inheritance\n     * A scope can inherit from a parent scope, as in this example:\n     * ```js\n         var parent = $rootScope;\n         var child = parent.$new();\n\n         parent.salutation = \"Hello\";\n         expect(child.salutation).toEqual('Hello');\n\n         child.salutation = \"Welcome\";\n         expect(child.salutation).toEqual('Welcome');\n         expect(parent.salutation).toEqual('Hello');\n     * ```\n     *\n     * When interacting with `Scope` in tests, additional helper methods are available on the\n     * instances of `Scope` type. See {@link ngMock.$rootScope.Scope ngMock Scope} for additional\n     * details.\n     *\n     *\n     * @param {Object.<string, function()>=} providers Map of service factory which need to be\n     *                                       provided for the current scope. Defaults to {@link ng}.\n     * @param {Object.<string, *>=} instanceCache Provides pre-instantiated services which should\n     *                              append/override services provided by `providers`. This is handy\n     *                              when unit-testing and having the need to override a default\n     *                              service.\n     * @returns {Object} Newly created scope.\n     *\n     */\n    function Scope() {\n      this.$id = nextUid();\n      this.$$phase = this.$parent = this.$$watchers =\n                     this.$$nextSibling = this.$$prevSibling =\n                     this.$$childHead = this.$$childTail = null;\n      this.$root = this;\n      this.$$destroyed = false;\n      this.$$listeners = {};\n      this.$$listenerCount = {};\n      this.$$isolateBindings = null;\n    }\n\n    /**\n     * @ngdoc property\n     * @name $rootScope.Scope#$id\n     *\n     * @description\n     * Unique scope ID (monotonically increasing) useful for debugging.\n     */\n\n     /**\n      * @ngdoc property\n      * @name $rootScope.Scope#$parent\n      *\n      * @description\n      * Reference to the parent scope.\n      */\n\n      /**\n       * @ngdoc property\n       * @name $rootScope.Scope#$root\n       *\n       * @description\n       * Reference to the root scope.\n       */\n\n    Scope.prototype = {\n      constructor: Scope,\n      /**\n       * @ngdoc method\n       * @name $rootScope.Scope#$new\n       * @kind function\n       *\n       * @description\n       * Creates a new child {@link ng.$rootScope.Scope scope}.\n       *\n       * The parent scope will propagate the {@link ng.$rootScope.Scope#$digest $digest()} event.\n       * The scope can be removed from the scope hierarchy using {@link ng.$rootScope.Scope#$destroy $destroy()}.\n       *\n       * {@link ng.$rootScope.Scope#$destroy $destroy()} must be called on a scope when it is\n       * desired for the scope and its child scopes to be permanently detached from the parent and\n       * thus stop participating in model change detection and listener notification by invoking.\n       *\n       * @param {boolean} isolate If true, then the scope does not prototypically inherit from the\n       *         parent scope. The scope is isolated, as it can not see parent scope properties.\n       *         When creating widgets, it is useful for the widget to not accidentally read parent\n       *         state.\n       *\n       * @param {Scope} [parent=this] The {@link ng.$rootScope.Scope `Scope`} that will be the `$parent`\n       *                              of the newly created scope. Defaults to `this` scope if not provided.\n       *                              This is used when creating a transclude scope to correctly place it\n       *                              in the scope hierarchy while maintaining the correct prototypical\n       *                              inheritance.\n       *\n       * @returns {Object} The newly created child scope.\n       *\n       */\n      $new: function(isolate, parent) {\n        var child;\n\n        parent = parent || this;\n\n        if (isolate) {\n          child = new Scope();\n          child.$root = this.$root;\n        } else {\n          // Only create a child scope class if somebody asks for one,\n          // but cache it to allow the VM to optimize lookups.\n          if (!this.$$ChildScope) {\n            this.$$ChildScope = function ChildScope() {\n              this.$$watchers = this.$$nextSibling =\n                  this.$$childHead = this.$$childTail = null;\n              this.$$listeners = {};\n              this.$$listenerCount = {};\n              this.$id = nextUid();\n              this.$$ChildScope = null;\n            };\n            this.$$ChildScope.prototype = this;\n          }\n          child = new this.$$ChildScope();\n        }\n        child.$parent = parent;\n        child.$$prevSibling = parent.$$childTail;\n        if (parent.$$childHead) {\n          parent.$$childTail.$$nextSibling = child;\n          parent.$$childTail = child;\n        } else {\n          parent.$$childHead = parent.$$childTail = child;\n        }\n\n        // When the new scope is not isolated or we inherit from `this`, and\n        // the parent scope is destroyed, the property `$$destroyed` is inherited\n        // prototypically. In all other cases, this property needs to be set\n        // when the parent scope is destroyed.\n        // The listener needs to be added after the parent is set\n        if (isolate || parent != this) child.$on('$destroy', destroyChild);\n\n        return child;\n\n        function destroyChild() {\n          child.$$destroyed = true;\n        }\n      },\n\n      /**\n       * @ngdoc method\n       * @name $rootScope.Scope#$watch\n       * @kind function\n       *\n       * @description\n       * Registers a `listener` callback to be executed whenever the `watchExpression` changes.\n       *\n       * - The `watchExpression` is called on every call to {@link ng.$rootScope.Scope#$digest\n       *   $digest()} and should return the value that will be watched. (Since\n       *   {@link ng.$rootScope.Scope#$digest $digest()} reruns when it detects changes the\n       *   `watchExpression` can execute multiple times per\n       *   {@link ng.$rootScope.Scope#$digest $digest()} and should be idempotent.)\n       * - The `listener` is called only when the value from the current `watchExpression` and the\n       *   previous call to `watchExpression` are not equal (with the exception of the initial run,\n       *   see below). Inequality is determined according to reference inequality,\n       *   [strict comparison](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Comparison_Operators)\n       *    via the `!==` Javascript operator, unless `objectEquality == true`\n       *   (see next point)\n       * - When `objectEquality == true`, inequality of the `watchExpression` is determined\n       *   according to the {@link angular.equals} function. To save the value of the object for\n       *   later comparison, the {@link angular.copy} function is used. This therefore means that\n       *   watching complex objects will have adverse memory and performance implications.\n       * - The watch `listener` may change the model, which may trigger other `listener`s to fire.\n       *   This is achieved by rerunning the watchers until no changes are detected. The rerun\n       *   iteration limit is 10 to prevent an infinite loop deadlock.\n       *\n       *\n       * If you want to be notified whenever {@link ng.$rootScope.Scope#$digest $digest} is called,\n       * you can register a `watchExpression` function with no `listener`. (Since `watchExpression`\n       * can execute multiple times per {@link ng.$rootScope.Scope#$digest $digest} cycle when a\n       * change is detected, be prepared for multiple calls to your listener.)\n       *\n       * After a watcher is registered with the scope, the `listener` fn is called asynchronously\n       * (via {@link ng.$rootScope.Scope#$evalAsync $evalAsync}) to initialize the\n       * watcher. In rare cases, this is undesirable because the listener is called when the result\n       * of `watchExpression` didn't change. To detect this scenario within the `listener` fn, you\n       * can compare the `newVal` and `oldVal`. If these two values are identical (`===`) then the\n       * listener was called due to initialization.\n       *\n       *\n       *\n       * # Example\n       * ```js\n           // let's assume that scope was dependency injected as the $rootScope\n           var scope = $rootScope;\n           scope.name = 'misko';\n           scope.counter = 0;\n\n           expect(scope.counter).toEqual(0);\n           scope.$watch('name', function(newValue, oldValue) {\n             scope.counter = scope.counter + 1;\n           });\n           expect(scope.counter).toEqual(0);\n\n           scope.$digest();\n           // the listener is always called during the first $digest loop after it was registered\n           expect(scope.counter).toEqual(1);\n\n           scope.$digest();\n           // but now it will not be called unless the value changes\n           expect(scope.counter).toEqual(1);\n\n           scope.name = 'adam';\n           scope.$digest();\n           expect(scope.counter).toEqual(2);\n\n\n\n           // Using a function as a watchExpression\n           var food;\n           scope.foodCounter = 0;\n           expect(scope.foodCounter).toEqual(0);\n           scope.$watch(\n             // This function returns the value being watched. It is called for each turn of the $digest loop\n             function() { return food; },\n             // This is the change listener, called when the value returned from the above function changes\n             function(newValue, oldValue) {\n               if ( newValue !== oldValue ) {\n                 // Only increment the counter if the value changed\n                 scope.foodCounter = scope.foodCounter + 1;\n               }\n             }\n           );\n           // No digest has been run so the counter will be zero\n           expect(scope.foodCounter).toEqual(0);\n\n           // Run the digest but since food has not changed count will still be zero\n           scope.$digest();\n           expect(scope.foodCounter).toEqual(0);\n\n           // Update food and run digest.  Now the counter will increment\n           food = 'cheeseburger';\n           scope.$digest();\n           expect(scope.foodCounter).toEqual(1);\n\n       * ```\n       *\n       *\n       *\n       * @param {(function()|string)} watchExpression Expression that is evaluated on each\n       *    {@link ng.$rootScope.Scope#$digest $digest} cycle. A change in the return value triggers\n       *    a call to the `listener`.\n       *\n       *    - `string`: Evaluated as {@link guide/expression expression}\n       *    - `function(scope)`: called with current `scope` as a parameter.\n       * @param {function(newVal, oldVal, scope)} listener Callback called whenever the value\n       *    of `watchExpression` changes.\n       *\n       *    - `newVal` contains the current value of the `watchExpression`\n       *    - `oldVal` contains the previous value of the `watchExpression`\n       *    - `scope` refers to the current scope\n       * @param {boolean=} objectEquality Compare for object equality using {@link angular.equals} instead of\n       *     comparing for reference equality.\n       * @returns {function()} Returns a deregistration function for this listener.\n       */\n      $watch: function(watchExp, listener, objectEquality) {\n        var get = $parse(watchExp);\n\n        if (get.$$watchDelegate) {\n          return get.$$watchDelegate(this, listener, objectEquality, get);\n        }\n        var scope = this,\n            array = scope.$$watchers,\n            watcher = {\n              fn: listener,\n              last: initWatchVal,\n              get: get,\n              exp: watchExp,\n              eq: !!objectEquality\n            };\n\n        lastDirtyWatch = null;\n\n        if (!isFunction(listener)) {\n          watcher.fn = noop;\n        }\n\n        if (!array) {\n          array = scope.$$watchers = [];\n        }\n        // we use unshift since we use a while loop in $digest for speed.\n        // the while loop reads in reverse order.\n        array.unshift(watcher);\n\n        return function deregisterWatch() {\n          arrayRemove(array, watcher);\n          lastDirtyWatch = null;\n        };\n      },\n\n      /**\n       * @ngdoc method\n       * @name $rootScope.Scope#$watchGroup\n       * @kind function\n       *\n       * @description\n       * A variant of {@link ng.$rootScope.Scope#$watch $watch()} where it watches an array of `watchExpressions`.\n       * If any one expression in the collection changes the `listener` is executed.\n       *\n       * - The items in the `watchExpressions` array are observed via standard $watch operation and are examined on every\n       *   call to $digest() to see if any items changes.\n       * - The `listener` is called whenever any expression in the `watchExpressions` array changes.\n       *\n       * @param {Array.<string|Function(scope)>} watchExpressions Array of expressions that will be individually\n       * watched using {@link ng.$rootScope.Scope#$watch $watch()}\n       *\n       * @param {function(newValues, oldValues, scope)} listener Callback called whenever the return value of any\n       *    expression in `watchExpressions` changes\n       *    The `newValues` array contains the current values of the `watchExpressions`, with the indexes matching\n       *    those of `watchExpression`\n       *    and the `oldValues` array contains the previous values of the `watchExpressions`, with the indexes matching\n       *    those of `watchExpression`\n       *    The `scope` refers to the current scope.\n       * @returns {function()} Returns a de-registration function for all listeners.\n       */\n      $watchGroup: function(watchExpressions, listener) {\n        var oldValues = new Array(watchExpressions.length);\n        var newValues = new Array(watchExpressions.length);\n        var deregisterFns = [];\n        var self = this;\n        var changeReactionScheduled = false;\n        var firstRun = true;\n\n        if (!watchExpressions.length) {\n          // No expressions means we call the listener ASAP\n          var shouldCall = true;\n          self.$evalAsync(function() {\n            if (shouldCall) listener(newValues, newValues, self);\n          });\n          return function deregisterWatchGroup() {\n            shouldCall = false;\n          };\n        }\n\n        if (watchExpressions.length === 1) {\n          // Special case size of one\n          return this.$watch(watchExpressions[0], function watchGroupAction(value, oldValue, scope) {\n            newValues[0] = value;\n            oldValues[0] = oldValue;\n            listener(newValues, (value === oldValue) ? newValues : oldValues, scope);\n          });\n        }\n\n        forEach(watchExpressions, function(expr, i) {\n          var unwatchFn = self.$watch(expr, function watchGroupSubAction(value, oldValue) {\n            newValues[i] = value;\n            oldValues[i] = oldValue;\n            if (!changeReactionScheduled) {\n              changeReactionScheduled = true;\n              self.$evalAsync(watchGroupAction);\n            }\n          });\n          deregisterFns.push(unwatchFn);\n        });\n\n        function watchGroupAction() {\n          changeReactionScheduled = false;\n\n          if (firstRun) {\n            firstRun = false;\n            listener(newValues, newValues, self);\n          } else {\n            listener(newValues, oldValues, self);\n          }\n        }\n\n        return function deregisterWatchGroup() {\n          while (deregisterFns.length) {\n            deregisterFns.shift()();\n          }\n        };\n      },\n\n\n      /**\n       * @ngdoc method\n       * @name $rootScope.Scope#$watchCollection\n       * @kind function\n       *\n       * @description\n       * Shallow watches the properties of an object and fires whenever any of the properties change\n       * (for arrays, this implies watching the array items; for object maps, this implies watching\n       * the properties). If a change is detected, the `listener` callback is fired.\n       *\n       * - The `obj` collection is observed via standard $watch operation and is examined on every\n       *   call to $digest() to see if any items have been added, removed, or moved.\n       * - The `listener` is called whenever anything within the `obj` has changed. Examples include\n       *   adding, removing, and moving items belonging to an object or array.\n       *\n       *\n       * # Example\n       * ```js\n          $scope.names = ['igor', 'matias', 'misko', 'james'];\n          $scope.dataCount = 4;\n\n          $scope.$watchCollection('names', function(newNames, oldNames) {\n            $scope.dataCount = newNames.length;\n          });\n\n          expect($scope.dataCount).toEqual(4);\n          $scope.$digest();\n\n          //still at 4 ... no changes\n          expect($scope.dataCount).toEqual(4);\n\n          $scope.names.pop();\n          $scope.$digest();\n\n          //now there's been a change\n          expect($scope.dataCount).toEqual(3);\n       * ```\n       *\n       *\n       * @param {string|function(scope)} obj Evaluated as {@link guide/expression expression}. The\n       *    expression value should evaluate to an object or an array which is observed on each\n       *    {@link ng.$rootScope.Scope#$digest $digest} cycle. Any shallow change within the\n       *    collection will trigger a call to the `listener`.\n       *\n       * @param {function(newCollection, oldCollection, scope)} listener a callback function called\n       *    when a change is detected.\n       *    - The `newCollection` object is the newly modified data obtained from the `obj` expression\n       *    - The `oldCollection` object is a copy of the former collection data.\n       *      Due to performance considerations, the`oldCollection` value is computed only if the\n       *      `listener` function declares two or more arguments.\n       *    - The `scope` argument refers to the current scope.\n       *\n       * @returns {function()} Returns a de-registration function for this listener. When the\n       *    de-registration function is executed, the internal watch operation is terminated.\n       */\n      $watchCollection: function(obj, listener) {\n        $watchCollectionInterceptor.$stateful = true;\n\n        var self = this;\n        // the current value, updated on each dirty-check run\n        var newValue;\n        // a shallow copy of the newValue from the last dirty-check run,\n        // updated to match newValue during dirty-check run\n        var oldValue;\n        // a shallow copy of the newValue from when the last change happened\n        var veryOldValue;\n        // only track veryOldValue if the listener is asking for it\n        var trackVeryOldValue = (listener.length > 1);\n        var changeDetected = 0;\n        var changeDetector = $parse(obj, $watchCollectionInterceptor);\n        var internalArray = [];\n        var internalObject = {};\n        var initRun = true;\n        var oldLength = 0;\n\n        function $watchCollectionInterceptor(_value) {\n          newValue = _value;\n          var newLength, key, bothNaN, newItem, oldItem;\n\n          // If the new value is undefined, then return undefined as the watch may be a one-time watch\n          if (isUndefined(newValue)) return;\n\n          if (!isObject(newValue)) { // if primitive\n            if (oldValue !== newValue) {\n              oldValue = newValue;\n              changeDetected++;\n            }\n          } else if (isArrayLike(newValue)) {\n            if (oldValue !== internalArray) {\n              // we are transitioning from something which was not an array into array.\n              oldValue = internalArray;\n              oldLength = oldValue.length = 0;\n              changeDetected++;\n            }\n\n            newLength = newValue.length;\n\n            if (oldLength !== newLength) {\n              // if lengths do not match we need to trigger change notification\n              changeDetected++;\n              oldValue.length = oldLength = newLength;\n            }\n            // copy the items to oldValue and look for changes.\n            for (var i = 0; i < newLength; i++) {\n              oldItem = oldValue[i];\n              newItem = newValue[i];\n\n              bothNaN = (oldItem !== oldItem) && (newItem !== newItem);\n              if (!bothNaN && (oldItem !== newItem)) {\n                changeDetected++;\n                oldValue[i] = newItem;\n              }\n            }\n          } else {\n            if (oldValue !== internalObject) {\n              // we are transitioning from something which was not an object into object.\n              oldValue = internalObject = {};\n              oldLength = 0;\n              changeDetected++;\n            }\n            // copy the items to oldValue and look for changes.\n            newLength = 0;\n            for (key in newValue) {\n              if (newValue.hasOwnProperty(key)) {\n                newLength++;\n                newItem = newValue[key];\n                oldItem = oldValue[key];\n\n                if (key in oldValue) {\n                  bothNaN = (oldItem !== oldItem) && (newItem !== newItem);\n                  if (!bothNaN && (oldItem !== newItem)) {\n                    changeDetected++;\n                    oldValue[key] = newItem;\n                  }\n                } else {\n                  oldLength++;\n                  oldValue[key] = newItem;\n                  changeDetected++;\n                }\n              }\n            }\n            if (oldLength > newLength) {\n              // we used to have more keys, need to find them and destroy them.\n              changeDetected++;\n              for (key in oldValue) {\n                if (!newValue.hasOwnProperty(key)) {\n                  oldLength--;\n                  delete oldValue[key];\n                }\n              }\n            }\n          }\n          return changeDetected;\n        }\n\n        function $watchCollectionAction() {\n          if (initRun) {\n            initRun = false;\n            listener(newValue, newValue, self);\n          } else {\n            listener(newValue, veryOldValue, self);\n          }\n\n          // make a copy for the next time a collection is changed\n          if (trackVeryOldValue) {\n            if (!isObject(newValue)) {\n              //primitive\n              veryOldValue = newValue;\n            } else if (isArrayLike(newValue)) {\n              veryOldValue = new Array(newValue.length);\n              for (var i = 0; i < newValue.length; i++) {\n                veryOldValue[i] = newValue[i];\n              }\n            } else { // if object\n              veryOldValue = {};\n              for (var key in newValue) {\n                if (hasOwnProperty.call(newValue, key)) {\n                  veryOldValue[key] = newValue[key];\n                }\n              }\n            }\n          }\n        }\n\n        return this.$watch(changeDetector, $watchCollectionAction);\n      },\n\n      /**\n       * @ngdoc method\n       * @name $rootScope.Scope#$digest\n       * @kind function\n       *\n       * @description\n       * Processes all of the {@link ng.$rootScope.Scope#$watch watchers} of the current scope and\n       * its children. Because a {@link ng.$rootScope.Scope#$watch watcher}'s listener can change\n       * the model, the `$digest()` keeps calling the {@link ng.$rootScope.Scope#$watch watchers}\n       * until no more listeners are firing. This means that it is possible to get into an infinite\n       * loop. This function will throw `'Maximum iteration limit exceeded.'` if the number of\n       * iterations exceeds 10.\n       *\n       * Usually, you don't call `$digest()` directly in\n       * {@link ng.directive:ngController controllers} or in\n       * {@link ng.$compileProvider#directive directives}.\n       * Instead, you should call {@link ng.$rootScope.Scope#$apply $apply()} (typically from within\n       * a {@link ng.$compileProvider#directive directive}), which will force a `$digest()`.\n       *\n       * If you want to be notified whenever `$digest()` is called,\n       * you can register a `watchExpression` function with\n       * {@link ng.$rootScope.Scope#$watch $watch()} with no `listener`.\n       *\n       * In unit tests, you may need to call `$digest()` to simulate the scope life cycle.\n       *\n       * # Example\n       * ```js\n           var scope = ...;\n           scope.name = 'misko';\n           scope.counter = 0;\n\n           expect(scope.counter).toEqual(0);\n           scope.$watch('name', function(newValue, oldValue) {\n             scope.counter = scope.counter + 1;\n           });\n           expect(scope.counter).toEqual(0);\n\n           scope.$digest();\n           // the listener is always called during the first $digest loop after it was registered\n           expect(scope.counter).toEqual(1);\n\n           scope.$digest();\n           // but now it will not be called unless the value changes\n           expect(scope.counter).toEqual(1);\n\n           scope.name = 'adam';\n           scope.$digest();\n           expect(scope.counter).toEqual(2);\n       * ```\n       *\n       */\n      $digest: function() {\n        var watch, value, last,\n            watchers,\n            length,\n            dirty, ttl = TTL,\n            next, current, target = this,\n            watchLog = [],\n            logIdx, logMsg, asyncTask;\n\n        beginPhase('$digest');\n        // Check for changes to browser url that happened in sync before the call to $digest\n        $browser.$$checkUrlChange();\n\n        if (this === $rootScope && applyAsyncId !== null) {\n          // If this is the root scope, and $applyAsync has scheduled a deferred $apply(), then\n          // cancel the scheduled $apply and flush the queue of expressions to be evaluated.\n          $browser.defer.cancel(applyAsyncId);\n          flushApplyAsync();\n        }\n\n        lastDirtyWatch = null;\n\n        do { // \"while dirty\" loop\n          dirty = false;\n          current = target;\n\n          while (asyncQueue.length) {\n            try {\n              asyncTask = asyncQueue.shift();\n              asyncTask.scope.$eval(asyncTask.expression, asyncTask.locals);\n            } catch (e) {\n              $exceptionHandler(e);\n            }\n            lastDirtyWatch = null;\n          }\n\n          traverseScopesLoop:\n          do { // \"traverse the scopes\" loop\n            if ((watchers = current.$$watchers)) {\n              // process our watches\n              length = watchers.length;\n              while (length--) {\n                try {\n                  watch = watchers[length];\n                  // Most common watches are on primitives, in which case we can short\n                  // circuit it with === operator, only when === fails do we use .equals\n                  if (watch) {\n                    if ((value = watch.get(current)) !== (last = watch.last) &&\n                        !(watch.eq\n                            ? equals(value, last)\n                            : (typeof value === 'number' && typeof last === 'number'\n                               && isNaN(value) && isNaN(last)))) {\n                      dirty = true;\n                      lastDirtyWatch = watch;\n                      watch.last = watch.eq ? copy(value, null) : value;\n                      watch.fn(value, ((last === initWatchVal) ? value : last), current);\n                      if (ttl < 5) {\n                        logIdx = 4 - ttl;\n                        if (!watchLog[logIdx]) watchLog[logIdx] = [];\n                        watchLog[logIdx].push({\n                          msg: isFunction(watch.exp) ? 'fn: ' + (watch.exp.name || watch.exp.toString()) : watch.exp,\n                          newVal: value,\n                          oldVal: last\n                        });\n                      }\n                    } else if (watch === lastDirtyWatch) {\n                      // If the most recently dirty watcher is now clean, short circuit since the remaining watchers\n                      // have already been tested.\n                      dirty = false;\n                      break traverseScopesLoop;\n                    }\n                  }\n                } catch (e) {\n                  $exceptionHandler(e);\n                }\n              }\n            }\n\n            // Insanity Warning: scope depth-first traversal\n            // yes, this code is a bit crazy, but it works and we have tests to prove it!\n            // this piece should be kept in sync with the traversal in $broadcast\n            if (!(next = (current.$$childHead ||\n                (current !== target && current.$$nextSibling)))) {\n              while (current !== target && !(next = current.$$nextSibling)) {\n                current = current.$parent;\n              }\n            }\n          } while ((current = next));\n\n          // `break traverseScopesLoop;` takes us to here\n\n          if ((dirty || asyncQueue.length) && !(ttl--)) {\n            clearPhase();\n            throw $rootScopeMinErr('infdig',\n                '{0} $digest() iterations reached. Aborting!\\n' +\n                'Watchers fired in the last 5 iterations: {1}',\n                TTL, watchLog);\n          }\n\n        } while (dirty || asyncQueue.length);\n\n        clearPhase();\n\n        while (postDigestQueue.length) {\n          try {\n            postDigestQueue.shift()();\n          } catch (e) {\n            $exceptionHandler(e);\n          }\n        }\n      },\n\n\n      /**\n       * @ngdoc event\n       * @name $rootScope.Scope#$destroy\n       * @eventType broadcast on scope being destroyed\n       *\n       * @description\n       * Broadcasted when a scope and its children are being destroyed.\n       *\n       * Note that, in AngularJS, there is also a `$destroy` jQuery event, which can be used to\n       * clean up DOM bindings before an element is removed from the DOM.\n       */\n\n      /**\n       * @ngdoc method\n       * @name $rootScope.Scope#$destroy\n       * @kind function\n       *\n       * @description\n       * Removes the current scope (and all of its children) from the parent scope. Removal implies\n       * that calls to {@link ng.$rootScope.Scope#$digest $digest()} will no longer\n       * propagate to the current scope and its children. Removal also implies that the current\n       * scope is eligible for garbage collection.\n       *\n       * The `$destroy()` is usually used by directives such as\n       * {@link ng.directive:ngRepeat ngRepeat} for managing the\n       * unrolling of the loop.\n       *\n       * Just before a scope is destroyed, a `$destroy` event is broadcasted on this scope.\n       * Application code can register a `$destroy` event handler that will give it a chance to\n       * perform any necessary cleanup.\n       *\n       * Note that, in AngularJS, there is also a `$destroy` jQuery event, which can be used to\n       * clean up DOM bindings before an element is removed from the DOM.\n       */\n      $destroy: function() {\n        // we can't destroy the root scope or a scope that has been already destroyed\n        if (this.$$destroyed) return;\n        var parent = this.$parent;\n\n        this.$broadcast('$destroy');\n        this.$$destroyed = true;\n        if (this === $rootScope) return;\n\n        for (var eventName in this.$$listenerCount) {\n          decrementListenerCount(this, this.$$listenerCount[eventName], eventName);\n        }\n\n        // sever all the references to parent scopes (after this cleanup, the current scope should\n        // not be retained by any of our references and should be eligible for garbage collection)\n        if (parent.$$childHead == this) parent.$$childHead = this.$$nextSibling;\n        if (parent.$$childTail == this) parent.$$childTail = this.$$prevSibling;\n        if (this.$$prevSibling) this.$$prevSibling.$$nextSibling = this.$$nextSibling;\n        if (this.$$nextSibling) this.$$nextSibling.$$prevSibling = this.$$prevSibling;\n\n        // Disable listeners, watchers and apply/digest methods\n        this.$destroy = this.$digest = this.$apply = this.$evalAsync = this.$applyAsync = noop;\n        this.$on = this.$watch = this.$watchGroup = function() { return noop; };\n        this.$$listeners = {};\n\n        // All of the code below is bogus code that works around V8's memory leak via optimized code\n        // and inline caches.\n        //\n        // see:\n        // - https://code.google.com/p/v8/issues/detail?id=2073#c26\n        // - https://github.com/angular/angular.js/issues/6794#issuecomment-38648909\n        // - https://github.com/angular/angular.js/issues/1313#issuecomment-10378451\n\n        this.$parent = this.$$nextSibling = this.$$prevSibling = this.$$childHead =\n            this.$$childTail = this.$root = this.$$watchers = null;\n      },\n\n      /**\n       * @ngdoc method\n       * @name $rootScope.Scope#$eval\n       * @kind function\n       *\n       * @description\n       * Executes the `expression` on the current scope and returns the result. Any exceptions in\n       * the expression are propagated (uncaught). This is useful when evaluating Angular\n       * expressions.\n       *\n       * # Example\n       * ```js\n           var scope = ng.$rootScope.Scope();\n           scope.a = 1;\n           scope.b = 2;\n\n           expect(scope.$eval('a+b')).toEqual(3);\n           expect(scope.$eval(function(scope){ return scope.a + scope.b; })).toEqual(3);\n       * ```\n       *\n       * @param {(string|function())=} expression An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in  {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with the current `scope` parameter.\n       *\n       * @param {(object)=} locals Local variables object, useful for overriding values in scope.\n       * @returns {*} The result of evaluating the expression.\n       */\n      $eval: function(expr, locals) {\n        return $parse(expr)(this, locals);\n      },\n\n      /**\n       * @ngdoc method\n       * @name $rootScope.Scope#$evalAsync\n       * @kind function\n       *\n       * @description\n       * Executes the expression on the current scope at a later point in time.\n       *\n       * The `$evalAsync` makes no guarantees as to when the `expression` will be executed, only\n       * that:\n       *\n       *   - it will execute after the function that scheduled the evaluation (preferably before DOM\n       *     rendering).\n       *   - at least one {@link ng.$rootScope.Scope#$digest $digest cycle} will be performed after\n       *     `expression` execution.\n       *\n       * Any exceptions from the execution of the expression are forwarded to the\n       * {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * __Note:__ if this function is called outside of a `$digest` cycle, a new `$digest` cycle\n       * will be scheduled. However, it is encouraged to always call code that changes the model\n       * from within an `$apply` call. That includes code evaluated via `$evalAsync`.\n       *\n       * @param {(string|function())=} expression An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with the current `scope` parameter.\n       *\n       * @param {(object)=} locals Local variables object, useful for overriding values in scope.\n       */\n      $evalAsync: function(expr, locals) {\n        // if we are outside of an $digest loop and this is the first time we are scheduling async\n        // task also schedule async auto-flush\n        if (!$rootScope.$$phase && !asyncQueue.length) {\n          $browser.defer(function() {\n            if (asyncQueue.length) {\n              $rootScope.$digest();\n            }\n          });\n        }\n\n        asyncQueue.push({scope: this, expression: expr, locals: locals});\n      },\n\n      $$postDigest: function(fn) {\n        postDigestQueue.push(fn);\n      },\n\n      /**\n       * @ngdoc method\n       * @name $rootScope.Scope#$apply\n       * @kind function\n       *\n       * @description\n       * `$apply()` is used to execute an expression in angular from outside of the angular\n       * framework. (For example from browser DOM events, setTimeout, XHR or third party libraries).\n       * Because we are calling into the angular framework we need to perform proper scope life\n       * cycle of {@link ng.$exceptionHandler exception handling},\n       * {@link ng.$rootScope.Scope#$digest executing watches}.\n       *\n       * ## Life cycle\n       *\n       * # Pseudo-Code of `$apply()`\n       * ```js\n           function $apply(expr) {\n             try {\n               return $eval(expr);\n             } catch (e) {\n               $exceptionHandler(e);\n             } finally {\n               $root.$digest();\n             }\n           }\n       * ```\n       *\n       *\n       * Scope's `$apply()` method transitions through the following stages:\n       *\n       * 1. The {@link guide/expression expression} is executed using the\n       *    {@link ng.$rootScope.Scope#$eval $eval()} method.\n       * 2. Any exceptions from the execution of the expression are forwarded to the\n       *    {@link ng.$exceptionHandler $exceptionHandler} service.\n       * 3. The {@link ng.$rootScope.Scope#$watch watch} listeners are fired immediately after the\n       *    expression was executed using the {@link ng.$rootScope.Scope#$digest $digest()} method.\n       *\n       *\n       * @param {(string|function())=} exp An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with current `scope` parameter.\n       *\n       * @returns {*} The result of evaluating the expression.\n       */\n      $apply: function(expr) {\n        try {\n          beginPhase('$apply');\n          return this.$eval(expr);\n        } catch (e) {\n          $exceptionHandler(e);\n        } finally {\n          clearPhase();\n          try {\n            $rootScope.$digest();\n          } catch (e) {\n            $exceptionHandler(e);\n            throw e;\n          }\n        }\n      },\n\n      /**\n       * @ngdoc method\n       * @name $rootScope.Scope#$applyAsync\n       * @kind function\n       *\n       * @description\n       * Schedule the invocation of $apply to occur at a later time. The actual time difference\n       * varies across browsers, but is typically around ~10 milliseconds.\n       *\n       * This can be used to queue up multiple expressions which need to be evaluated in the same\n       * digest.\n       *\n       * @param {(string|function())=} exp An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with current `scope` parameter.\n       */\n      $applyAsync: function(expr) {\n        var scope = this;\n        expr && applyAsyncQueue.push($applyAsyncExpression);\n        scheduleApplyAsync();\n\n        function $applyAsyncExpression() {\n          scope.$eval(expr);\n        }\n      },\n\n      /**\n       * @ngdoc method\n       * @name $rootScope.Scope#$on\n       * @kind function\n       *\n       * @description\n       * Listens on events of a given type. See {@link ng.$rootScope.Scope#$emit $emit} for\n       * discussion of event life cycle.\n       *\n       * The event listener function format is: `function(event, args...)`. The `event` object\n       * passed into the listener has the following attributes:\n       *\n       *   - `targetScope` - `{Scope}`: the scope on which the event was `$emit`-ed or\n       *     `$broadcast`-ed.\n       *   - `currentScope` - `{Scope}`: the scope that is currently handling the event. Once the\n       *     event propagates through the scope hierarchy, this property is set to null.\n       *   - `name` - `{string}`: name of the event.\n       *   - `stopPropagation` - `{function=}`: calling `stopPropagation` function will cancel\n       *     further event propagation (available only for events that were `$emit`-ed).\n       *   - `preventDefault` - `{function}`: calling `preventDefault` sets `defaultPrevented` flag\n       *     to true.\n       *   - `defaultPrevented` - `{boolean}`: true if `preventDefault` was called.\n       *\n       * @param {string} name Event name to listen on.\n       * @param {function(event, ...args)} listener Function to call when the event is emitted.\n       * @returns {function()} Returns a deregistration function for this listener.\n       */\n      $on: function(name, listener) {\n        var namedListeners = this.$$listeners[name];\n        if (!namedListeners) {\n          this.$$listeners[name] = namedListeners = [];\n        }\n        namedListeners.push(listener);\n\n        var current = this;\n        do {\n          if (!current.$$listenerCount[name]) {\n            current.$$listenerCount[name] = 0;\n          }\n          current.$$listenerCount[name]++;\n        } while ((current = current.$parent));\n\n        var self = this;\n        return function() {\n          var indexOfListener = namedListeners.indexOf(listener);\n          if (indexOfListener !== -1) {\n            namedListeners[indexOfListener] = null;\n            decrementListenerCount(self, 1, name);\n          }\n        };\n      },\n\n\n      /**\n       * @ngdoc method\n       * @name $rootScope.Scope#$emit\n       * @kind function\n       *\n       * @description\n       * Dispatches an event `name` upwards through the scope hierarchy notifying the\n       * registered {@link ng.$rootScope.Scope#$on} listeners.\n       *\n       * The event life cycle starts at the scope on which `$emit` was called. All\n       * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get\n       * notified. Afterwards, the event traverses upwards toward the root scope and calls all\n       * registered listeners along the way. The event will stop propagating if one of the listeners\n       * cancels it.\n       *\n       * Any exception emitted from the {@link ng.$rootScope.Scope#$on listeners} will be passed\n       * onto the {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {string} name Event name to emit.\n       * @param {...*} args Optional one or more arguments which will be passed onto the event listeners.\n       * @return {Object} Event object (see {@link ng.$rootScope.Scope#$on}).\n       */\n      $emit: function(name, args) {\n        var empty = [],\n            namedListeners,\n            scope = this,\n            stopPropagation = false,\n            event = {\n              name: name,\n              targetScope: scope,\n              stopPropagation: function() {stopPropagation = true;},\n              preventDefault: function() {\n                event.defaultPrevented = true;\n              },\n              defaultPrevented: false\n            },\n            listenerArgs = concat([event], arguments, 1),\n            i, length;\n\n        do {\n          namedListeners = scope.$$listeners[name] || empty;\n          event.currentScope = scope;\n          for (i = 0, length = namedListeners.length; i < length; i++) {\n\n            // if listeners were deregistered, defragment the array\n            if (!namedListeners[i]) {\n              namedListeners.splice(i, 1);\n              i--;\n              length--;\n              continue;\n            }\n            try {\n              //allow all listeners attached to the current scope to run\n              namedListeners[i].apply(null, listenerArgs);\n            } catch (e) {\n              $exceptionHandler(e);\n            }\n          }\n          //if any listener on the current scope stops propagation, prevent bubbling\n          if (stopPropagation) {\n            event.currentScope = null;\n            return event;\n          }\n          //traverse upwards\n          scope = scope.$parent;\n        } while (scope);\n\n        event.currentScope = null;\n\n        return event;\n      },\n\n\n      /**\n       * @ngdoc method\n       * @name $rootScope.Scope#$broadcast\n       * @kind function\n       *\n       * @description\n       * Dispatches an event `name` downwards to all child scopes (and their children) notifying the\n       * registered {@link ng.$rootScope.Scope#$on} listeners.\n       *\n       * The event life cycle starts at the scope on which `$broadcast` was called. All\n       * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get\n       * notified. Afterwards, the event propagates to all direct and indirect scopes of the current\n       * scope and calls all registered listeners along the way. The event cannot be canceled.\n       *\n       * Any exception emitted from the {@link ng.$rootScope.Scope#$on listeners} will be passed\n       * onto the {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {string} name Event name to broadcast.\n       * @param {...*} args Optional one or more arguments which will be passed onto the event listeners.\n       * @return {Object} Event object, see {@link ng.$rootScope.Scope#$on}\n       */\n      $broadcast: function(name, args) {\n        var target = this,\n            current = target,\n            next = target,\n            event = {\n              name: name,\n              targetScope: target,\n              preventDefault: function() {\n                event.defaultPrevented = true;\n              },\n              defaultPrevented: false\n            };\n\n        if (!target.$$listenerCount[name]) return event;\n\n        var listenerArgs = concat([event], arguments, 1),\n            listeners, i, length;\n\n        //down while you can, then up and next sibling or up and next sibling until back at root\n        while ((current = next)) {\n          event.currentScope = current;\n          listeners = current.$$listeners[name] || [];\n          for (i = 0, length = listeners.length; i < length; i++) {\n            // if listeners were deregistered, defragment the array\n            if (!listeners[i]) {\n              listeners.splice(i, 1);\n              i--;\n              length--;\n              continue;\n            }\n\n            try {\n              listeners[i].apply(null, listenerArgs);\n            } catch (e) {\n              $exceptionHandler(e);\n            }\n          }\n\n          // Insanity Warning: scope depth-first traversal\n          // yes, this code is a bit crazy, but it works and we have tests to prove it!\n          // this piece should be kept in sync with the traversal in $digest\n          // (though it differs due to having the extra check for $$listenerCount)\n          if (!(next = ((current.$$listenerCount[name] && current.$$childHead) ||\n              (current !== target && current.$$nextSibling)))) {\n            while (current !== target && !(next = current.$$nextSibling)) {\n              current = current.$parent;\n            }\n          }\n        }\n\n        event.currentScope = null;\n        return event;\n      }\n    };\n\n    var $rootScope = new Scope();\n\n    //The internal queues. Expose them on the $rootScope for debugging/testing purposes.\n    var asyncQueue = $rootScope.$$asyncQueue = [];\n    var postDigestQueue = $rootScope.$$postDigestQueue = [];\n    var applyAsyncQueue = $rootScope.$$applyAsyncQueue = [];\n\n    return $rootScope;\n\n\n    function beginPhase(phase) {\n      if ($rootScope.$$phase) {\n        throw $rootScopeMinErr('inprog', '{0} already in progress', $rootScope.$$phase);\n      }\n\n      $rootScope.$$phase = phase;\n    }\n\n    function clearPhase() {\n      $rootScope.$$phase = null;\n    }\n\n\n    function decrementListenerCount(current, count, name) {\n      do {\n        current.$$listenerCount[name] -= count;\n\n        if (current.$$listenerCount[name] === 0) {\n          delete current.$$listenerCount[name];\n        }\n      } while ((current = current.$parent));\n    }\n\n    /**\n     * function used as an initial value for watchers.\n     * because it's unique we can easily tell it apart from other values\n     */\n    function initWatchVal() {}\n\n    function flushApplyAsync() {\n      while (applyAsyncQueue.length) {\n        try {\n          applyAsyncQueue.shift()();\n        } catch (e) {\n          $exceptionHandler(e);\n        }\n      }\n      applyAsyncId = null;\n    }\n\n    function scheduleApplyAsync() {\n      if (applyAsyncId === null) {\n        applyAsyncId = $browser.defer(function() {\n          $rootScope.$apply(flushApplyAsync);\n        });\n      }\n    }\n  }];\n}\n\n/**\n * @description\n * Private service to sanitize uris for links and images. Used by $compile and $sanitize.\n */\nfunction $$SanitizeUriProvider() {\n  var aHrefSanitizationWhitelist = /^\\s*(https?|ftp|mailto|tel|file):/,\n    imgSrcSanitizationWhitelist = /^\\s*((https?|ftp|file|blob):|data:image\\/)/;\n\n  /**\n   * @description\n   * Retrieves or overrides the default regular expression that is used for whitelisting of safe\n   * urls during a[href] sanitization.\n   *\n   * The sanitization is a security measure aimed at prevent XSS attacks via html links.\n   *\n   * Any url about to be assigned to a[href] via data-binding is first normalized and turned into\n   * an absolute url. Afterwards, the url is matched against the `aHrefSanitizationWhitelist`\n   * regular expression. If a match is found, the original url is written into the dom. Otherwise,\n   * the absolute url is prefixed with `'unsafe:'` string and only then is it written into the DOM.\n   *\n   * @param {RegExp=} regexp New regexp to whitelist urls with.\n   * @returns {RegExp|ng.$compileProvider} Current RegExp if called without value or self for\n   *    chaining otherwise.\n   */\n  this.aHrefSanitizationWhitelist = function(regexp) {\n    if (isDefined(regexp)) {\n      aHrefSanitizationWhitelist = regexp;\n      return this;\n    }\n    return aHrefSanitizationWhitelist;\n  };\n\n\n  /**\n   * @description\n   * Retrieves or overrides the default regular expression that is used for whitelisting of safe\n   * urls during img[src] sanitization.\n   *\n   * The sanitization is a security measure aimed at prevent XSS attacks via html links.\n   *\n   * Any url about to be assigned to img[src] via data-binding is first normalized and turned into\n   * an absolute url. Afterwards, the url is matched against the `imgSrcSanitizationWhitelist`\n   * regular expression. If a match is found, the original url is written into the dom. Otherwise,\n   * the absolute url is prefixed with `'unsafe:'` string and only then is it written into the DOM.\n   *\n   * @param {RegExp=} regexp New regexp to whitelist urls with.\n   * @returns {RegExp|ng.$compileProvider} Current RegExp if called without value or self for\n   *    chaining otherwise.\n   */\n  this.imgSrcSanitizationWhitelist = function(regexp) {\n    if (isDefined(regexp)) {\n      imgSrcSanitizationWhitelist = regexp;\n      return this;\n    }\n    return imgSrcSanitizationWhitelist;\n  };\n\n  this.$get = function() {\n    return function sanitizeUri(uri, isImage) {\n      var regex = isImage ? imgSrcSanitizationWhitelist : aHrefSanitizationWhitelist;\n      var normalizedVal;\n      normalizedVal = urlResolve(uri).href;\n      if (normalizedVal !== '' && !normalizedVal.match(regex)) {\n        return 'unsafe:' + normalizedVal;\n      }\n      return uri;\n    };\n  };\n}\n\nvar $sceMinErr = minErr('$sce');\n\nvar SCE_CONTEXTS = {\n  HTML: 'html',\n  CSS: 'css',\n  URL: 'url',\n  // RESOURCE_URL is a subtype of URL used in contexts where a privileged resource is sourced from a\n  // url.  (e.g. ng-include, script src, templateUrl)\n  RESOURCE_URL: 'resourceUrl',\n  JS: 'js'\n};\n\n// Helper functions follow.\n\nfunction adjustMatcher(matcher) {\n  if (matcher === 'self') {\n    return matcher;\n  } else if (isString(matcher)) {\n    // Strings match exactly except for 2 wildcards - '*' and '**'.\n    // '*' matches any character except those from the set ':/.?&'.\n    // '**' matches any character (like .* in a RegExp).\n    // More than 2 *'s raises an error as it's ill defined.\n    if (matcher.indexOf('***') > -1) {\n      throw $sceMinErr('iwcard',\n          'Illegal sequence *** in string matcher.  String: {0}', matcher);\n    }\n    matcher = escapeForRegexp(matcher).\n                  replace('\\\\*\\\\*', '.*').\n                  replace('\\\\*', '[^:/.?&;]*');\n    return new RegExp('^' + matcher + '$');\n  } else if (isRegExp(matcher)) {\n    // The only other type of matcher allowed is a Regexp.\n    // Match entire URL / disallow partial matches.\n    // Flags are reset (i.e. no global, ignoreCase or multiline)\n    return new RegExp('^' + matcher.source + '$');\n  } else {\n    throw $sceMinErr('imatcher',\n        'Matchers may only be \"self\", string patterns or RegExp objects');\n  }\n}\n\n\nfunction adjustMatchers(matchers) {\n  var adjustedMatchers = [];\n  if (isDefined(matchers)) {\n    forEach(matchers, function(matcher) {\n      adjustedMatchers.push(adjustMatcher(matcher));\n    });\n  }\n  return adjustedMatchers;\n}\n\n\n/**\n * @ngdoc service\n * @name $sceDelegate\n * @kind function\n *\n * @description\n *\n * `$sceDelegate` is a service that is used by the `$sce` service to provide {@link ng.$sce Strict\n * Contextual Escaping (SCE)} services to AngularJS.\n *\n * Typically, you would configure or override the {@link ng.$sceDelegate $sceDelegate} instead of\n * the `$sce` service to customize the way Strict Contextual Escaping works in AngularJS.  This is\n * because, while the `$sce` provides numerous shorthand methods, etc., you really only need to\n * override 3 core functions (`trustAs`, `getTrusted` and `valueOf`) to replace the way things\n * work because `$sce` delegates to `$sceDelegate` for these operations.\n *\n * Refer {@link ng.$sceDelegateProvider $sceDelegateProvider} to configure this service.\n *\n * The default instance of `$sceDelegate` should work out of the box with little pain.  While you\n * can override it completely to change the behavior of `$sce`, the common case would\n * involve configuring the {@link ng.$sceDelegateProvider $sceDelegateProvider} instead by setting\n * your own whitelists and blacklists for trusting URLs used for loading AngularJS resources such as\n * templates.  Refer {@link ng.$sceDelegateProvider#resourceUrlWhitelist\n * $sceDelegateProvider.resourceUrlWhitelist} and {@link\n * ng.$sceDelegateProvider#resourceUrlBlacklist $sceDelegateProvider.resourceUrlBlacklist}\n */\n\n/**\n * @ngdoc provider\n * @name $sceDelegateProvider\n * @description\n *\n * The `$sceDelegateProvider` provider allows developers to configure the {@link ng.$sceDelegate\n * $sceDelegate} service.  This allows one to get/set the whitelists and blacklists used to ensure\n * that the URLs used for sourcing Angular templates are safe.  Refer {@link\n * ng.$sceDelegateProvider#resourceUrlWhitelist $sceDelegateProvider.resourceUrlWhitelist} and\n * {@link ng.$sceDelegateProvider#resourceUrlBlacklist $sceDelegateProvider.resourceUrlBlacklist}\n *\n * For the general details about this service in Angular, read the main page for {@link ng.$sce\n * Strict Contextual Escaping (SCE)}.\n *\n * **Example**:  Consider the following case. <a name=\"example\"></a>\n *\n * - your app is hosted at url `http://myapp.example.com/`\n * - but some of your templates are hosted on other domains you control such as\n *   `http://srv01.assets.example.com/`,  `http://srv02.assets.example.com/`, etc.\n * - and you have an open redirect at `http://myapp.example.com/clickThru?...`.\n *\n * Here is what a secure configuration for this scenario might look like:\n *\n * ```\n *  angular.module('myApp', []).config(function($sceDelegateProvider) {\n *    $sceDelegateProvider.resourceUrlWhitelist([\n *      // Allow same origin resource loads.\n *      'self',\n *      // Allow loading from our assets domain.  Notice the difference between * and **.\n *      'http://srv*.assets.example.com/**'\n *    ]);\n *\n *    // The blacklist overrides the whitelist so the open redirect here is blocked.\n *    $sceDelegateProvider.resourceUrlBlacklist([\n *      'http://myapp.example.com/clickThru**'\n *    ]);\n *  });\n * ```\n */\n\nfunction $SceDelegateProvider() {\n  this.SCE_CONTEXTS = SCE_CONTEXTS;\n\n  // Resource URLs can also be trusted by policy.\n  var resourceUrlWhitelist = ['self'],\n      resourceUrlBlacklist = [];\n\n  /**\n   * @ngdoc method\n   * @name $sceDelegateProvider#resourceUrlWhitelist\n   * @kind function\n   *\n   * @param {Array=} whitelist When provided, replaces the resourceUrlWhitelist with the value\n   *     provided.  This must be an array or null.  A snapshot of this array is used so further\n   *     changes to the array are ignored.\n   *\n   *     Follow {@link ng.$sce#resourceUrlPatternItem this link} for a description of the items\n   *     allowed in this array.\n   *\n   *     Note: **an empty whitelist array will block all URLs**!\n   *\n   * @return {Array} the currently set whitelist array.\n   *\n   * The **default value** when no whitelist has been explicitly set is `['self']` allowing only\n   * same origin resource requests.\n   *\n   * @description\n   * Sets/Gets the whitelist of trusted resource URLs.\n   */\n  this.resourceUrlWhitelist = function(value) {\n    if (arguments.length) {\n      resourceUrlWhitelist = adjustMatchers(value);\n    }\n    return resourceUrlWhitelist;\n  };\n\n  /**\n   * @ngdoc method\n   * @name $sceDelegateProvider#resourceUrlBlacklist\n   * @kind function\n   *\n   * @param {Array=} blacklist When provided, replaces the resourceUrlBlacklist with the value\n   *     provided.  This must be an array or null.  A snapshot of this array is used so further\n   *     changes to the array are ignored.\n   *\n   *     Follow {@link ng.$sce#resourceUrlPatternItem this link} for a description of the items\n   *     allowed in this array.\n   *\n   *     The typical usage for the blacklist is to **block\n   *     [open redirects](http://cwe.mitre.org/data/definitions/601.html)** served by your domain as\n   *     these would otherwise be trusted but actually return content from the redirected domain.\n   *\n   *     Finally, **the blacklist overrides the whitelist** and has the final say.\n   *\n   * @return {Array} the currently set blacklist array.\n   *\n   * The **default value** when no whitelist has been explicitly set is the empty array (i.e. there\n   * is no blacklist.)\n   *\n   * @description\n   * Sets/Gets the blacklist of trusted resource URLs.\n   */\n\n  this.resourceUrlBlacklist = function(value) {\n    if (arguments.length) {\n      resourceUrlBlacklist = adjustMatchers(value);\n    }\n    return resourceUrlBlacklist;\n  };\n\n  this.$get = ['$injector', function($injector) {\n\n    var htmlSanitizer = function htmlSanitizer(html) {\n      throw $sceMinErr('unsafe', 'Attempting to use an unsafe value in a safe context.');\n    };\n\n    if ($injector.has('$sanitize')) {\n      htmlSanitizer = $injector.get('$sanitize');\n    }\n\n\n    function matchUrl(matcher, parsedUrl) {\n      if (matcher === 'self') {\n        return urlIsSameOrigin(parsedUrl);\n      } else {\n        // definitely a regex.  See adjustMatchers()\n        return !!matcher.exec(parsedUrl.href);\n      }\n    }\n\n    function isResourceUrlAllowedByPolicy(url) {\n      var parsedUrl = urlResolve(url.toString());\n      var i, n, allowed = false;\n      // Ensure that at least one item from the whitelist allows this url.\n      for (i = 0, n = resourceUrlWhitelist.length; i < n; i++) {\n        if (matchUrl(resourceUrlWhitelist[i], parsedUrl)) {\n          allowed = true;\n          break;\n        }\n      }\n      if (allowed) {\n        // Ensure that no item from the blacklist blocked this url.\n        for (i = 0, n = resourceUrlBlacklist.length; i < n; i++) {\n          if (matchUrl(resourceUrlBlacklist[i], parsedUrl)) {\n            allowed = false;\n            break;\n          }\n        }\n      }\n      return allowed;\n    }\n\n    function generateHolderType(Base) {\n      var holderType = function TrustedValueHolderType(trustedValue) {\n        this.$$unwrapTrustedValue = function() {\n          return trustedValue;\n        };\n      };\n      if (Base) {\n        holderType.prototype = new Base();\n      }\n      holderType.prototype.valueOf = function sceValueOf() {\n        return this.$$unwrapTrustedValue();\n      };\n      holderType.prototype.toString = function sceToString() {\n        return this.$$unwrapTrustedValue().toString();\n      };\n      return holderType;\n    }\n\n    var trustedValueHolderBase = generateHolderType(),\n        byType = {};\n\n    byType[SCE_CONTEXTS.HTML] = generateHolderType(trustedValueHolderBase);\n    byType[SCE_CONTEXTS.CSS] = generateHolderType(trustedValueHolderBase);\n    byType[SCE_CONTEXTS.URL] = generateHolderType(trustedValueHolderBase);\n    byType[SCE_CONTEXTS.JS] = generateHolderType(trustedValueHolderBase);\n    byType[SCE_CONTEXTS.RESOURCE_URL] = generateHolderType(byType[SCE_CONTEXTS.URL]);\n\n    /**\n     * @ngdoc method\n     * @name $sceDelegate#trustAs\n     *\n     * @description\n     * Returns an object that is trusted by angular for use in specified strict\n     * contextual escaping contexts (such as ng-bind-html, ng-include, any src\n     * attribute interpolation, any dom event binding attribute interpolation\n     * such as for onclick,  etc.) that uses the provided value.\n     * See {@link ng.$sce $sce} for enabling strict contextual escaping.\n     *\n     * @param {string} type The kind of context in which this value is safe for use.  e.g. url,\n     *   resourceUrl, html, js and css.\n     * @param {*} value The value that that should be considered trusted/safe.\n     * @returns {*} A value that can be used to stand in for the provided `value` in places\n     * where Angular expects a $sce.trustAs() return value.\n     */\n    function trustAs(type, trustedValue) {\n      var Constructor = (byType.hasOwnProperty(type) ? byType[type] : null);\n      if (!Constructor) {\n        throw $sceMinErr('icontext',\n            'Attempted to trust a value in invalid context. Context: {0}; Value: {1}',\n            type, trustedValue);\n      }\n      if (trustedValue === null || trustedValue === undefined || trustedValue === '') {\n        return trustedValue;\n      }\n      // All the current contexts in SCE_CONTEXTS happen to be strings.  In order to avoid trusting\n      // mutable objects, we ensure here that the value passed in is actually a string.\n      if (typeof trustedValue !== 'string') {\n        throw $sceMinErr('itype',\n            'Attempted to trust a non-string value in a content requiring a string: Context: {0}',\n            type);\n      }\n      return new Constructor(trustedValue);\n    }\n\n    /**\n     * @ngdoc method\n     * @name $sceDelegate#valueOf\n     *\n     * @description\n     * If the passed parameter had been returned by a prior call to {@link ng.$sceDelegate#trustAs\n     * `$sceDelegate.trustAs`}, returns the value that had been passed to {@link\n     * ng.$sceDelegate#trustAs `$sceDelegate.trustAs`}.\n     *\n     * If the passed parameter is not a value that had been returned by {@link\n     * ng.$sceDelegate#trustAs `$sceDelegate.trustAs`}, returns it as-is.\n     *\n     * @param {*} value The result of a prior {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs`}\n     *      call or anything else.\n     * @returns {*} The `value` that was originally provided to {@link ng.$sceDelegate#trustAs\n     *     `$sceDelegate.trustAs`} if `value` is the result of such a call.  Otherwise, returns\n     *     `value` unchanged.\n     */\n    function valueOf(maybeTrusted) {\n      if (maybeTrusted instanceof trustedValueHolderBase) {\n        return maybeTrusted.$$unwrapTrustedValue();\n      } else {\n        return maybeTrusted;\n      }\n    }\n\n    /**\n     * @ngdoc method\n     * @name $sceDelegate#getTrusted\n     *\n     * @description\n     * Takes the result of a {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs`} call and\n     * returns the originally supplied value if the queried context type is a supertype of the\n     * created type.  If this condition isn't satisfied, throws an exception.\n     *\n     * @param {string} type The kind of context in which this value is to be used.\n     * @param {*} maybeTrusted The result of a prior {@link ng.$sceDelegate#trustAs\n     *     `$sceDelegate.trustAs`} call.\n     * @returns {*} The value the was originally provided to {@link ng.$sceDelegate#trustAs\n     *     `$sceDelegate.trustAs`} if valid in this context.  Otherwise, throws an exception.\n     */\n    function getTrusted(type, maybeTrusted) {\n      if (maybeTrusted === null || maybeTrusted === undefined || maybeTrusted === '') {\n        return maybeTrusted;\n      }\n      var constructor = (byType.hasOwnProperty(type) ? byType[type] : null);\n      if (constructor && maybeTrusted instanceof constructor) {\n        return maybeTrusted.$$unwrapTrustedValue();\n      }\n      // If we get here, then we may only take one of two actions.\n      // 1. sanitize the value for the requested type, or\n      // 2. throw an exception.\n      if (type === SCE_CONTEXTS.RESOURCE_URL) {\n        if (isResourceUrlAllowedByPolicy(maybeTrusted)) {\n          return maybeTrusted;\n        } else {\n          throw $sceMinErr('insecurl',\n              'Blocked loading resource from url not allowed by $sceDelegate policy.  URL: {0}',\n              maybeTrusted.toString());\n        }\n      } else if (type === SCE_CONTEXTS.HTML) {\n        return htmlSanitizer(maybeTrusted);\n      }\n      throw $sceMinErr('unsafe', 'Attempting to use an unsafe value in a safe context.');\n    }\n\n    return { trustAs: trustAs,\n             getTrusted: getTrusted,\n             valueOf: valueOf };\n  }];\n}\n\n\n/**\n * @ngdoc provider\n * @name $sceProvider\n * @description\n *\n * The $sceProvider provider allows developers to configure the {@link ng.$sce $sce} service.\n * -   enable/disable Strict Contextual Escaping (SCE) in a module\n * -   override the default implementation with a custom delegate\n *\n * Read more about {@link ng.$sce Strict Contextual Escaping (SCE)}.\n */\n\n/* jshint maxlen: false*/\n\n/**\n * @ngdoc service\n * @name $sce\n * @kind function\n *\n * @description\n *\n * `$sce` is a service that provides Strict Contextual Escaping services to AngularJS.\n *\n * # Strict Contextual Escaping\n *\n * Strict Contextual Escaping (SCE) is a mode in which AngularJS requires bindings in certain\n * contexts to result in a value that is marked as safe to use for that context.  One example of\n * such a context is binding arbitrary html controlled by the user via `ng-bind-html`.  We refer\n * to these contexts as privileged or SCE contexts.\n *\n * As of version 1.2, Angular ships with SCE enabled by default.\n *\n * Note:  When enabled (the default), IE<11 in quirks mode is not supported.  In this mode, IE<11 allow\n * one to execute arbitrary javascript by the use of the expression() syntax.  Refer\n * <http://blogs.msdn.com/b/ie/archive/2008/10/16/ending-expressions.aspx> to learn more about them.\n * You can ensure your document is in standards mode and not quirks mode by adding `<!doctype html>`\n * to the top of your HTML document.\n *\n * SCE assists in writing code in way that (a) is secure by default and (b) makes auditing for\n * security vulnerabilities such as XSS, clickjacking, etc. a lot easier.\n *\n * Here's an example of a binding in a privileged context:\n *\n * ```\n * <input ng-model=\"userHtml\">\n * <div ng-bind-html=\"userHtml\"></div>\n * ```\n *\n * Notice that `ng-bind-html` is bound to `userHtml` controlled by the user.  With SCE\n * disabled, this application allows the user to render arbitrary HTML into the DIV.\n * In a more realistic example, one may be rendering user comments, blog articles, etc. via\n * bindings.  (HTML is just one example of a context where rendering user controlled input creates\n * security vulnerabilities.)\n *\n * For the case of HTML, you might use a library, either on the client side, or on the server side,\n * to sanitize unsafe HTML before binding to the value and rendering it in the document.\n *\n * How would you ensure that every place that used these types of bindings was bound to a value that\n * was sanitized by your library (or returned as safe for rendering by your server?)  How can you\n * ensure that you didn't accidentally delete the line that sanitized the value, or renamed some\n * properties/fields and forgot to update the binding to the sanitized value?\n *\n * To be secure by default, you want to ensure that any such bindings are disallowed unless you can\n * determine that something explicitly says it's safe to use a value for binding in that\n * context.  You can then audit your code (a simple grep would do) to ensure that this is only done\n * for those values that you can easily tell are safe - because they were received from your server,\n * sanitized by your library, etc.  You can organize your codebase to help with this - perhaps\n * allowing only the files in a specific directory to do this.  Ensuring that the internal API\n * exposed by that code doesn't markup arbitrary values as safe then becomes a more manageable task.\n *\n * In the case of AngularJS' SCE service, one uses {@link ng.$sce#trustAs $sce.trustAs}\n * (and shorthand methods such as {@link ng.$sce#trustAsHtml $sce.trustAsHtml}, etc.) to\n * obtain values that will be accepted by SCE / privileged contexts.\n *\n *\n * ## How does it work?\n *\n * In privileged contexts, directives and code will bind to the result of {@link ng.$sce#getTrusted\n * $sce.getTrusted(context, value)} rather than to the value directly.  Directives use {@link\n * ng.$sce#parseAs $sce.parseAs} rather than `$parse` to watch attribute bindings, which performs the\n * {@link ng.$sce#getTrusted $sce.getTrusted} behind the scenes on non-constant literals.\n *\n * As an example, {@link ng.directive:ngBindHtml ngBindHtml} uses {@link\n * ng.$sce#parseAsHtml $sce.parseAsHtml(binding expression)}.  Here's the actual code (slightly\n * simplified):\n *\n * ```\n * var ngBindHtmlDirective = ['$sce', function($sce) {\n *   return function(scope, element, attr) {\n *     scope.$watch($sce.parseAsHtml(attr.ngBindHtml), function(value) {\n *       element.html(value || '');\n *     });\n *   };\n * }];\n * ```\n *\n * ## Impact on loading templates\n *\n * This applies both to the {@link ng.directive:ngInclude `ng-include`} directive as well as\n * `templateUrl`'s specified by {@link guide/directive directives}.\n *\n * By default, Angular only loads templates from the same domain and protocol as the application\n * document.  This is done by calling {@link ng.$sce#getTrustedResourceUrl\n * $sce.getTrustedResourceUrl} on the template URL.  To load templates from other domains and/or\n * protocols, you may either either {@link ng.$sceDelegateProvider#resourceUrlWhitelist whitelist\n * them} or {@link ng.$sce#trustAsResourceUrl wrap it} into a trusted value.\n *\n * *Please note*:\n * The browser's\n * [Same Origin Policy](https://code.google.com/p/browsersec/wiki/Part2#Same-origin_policy_for_XMLHttpRequest)\n * and [Cross-Origin Resource Sharing (CORS)](http://www.w3.org/TR/cors/)\n * policy apply in addition to this and may further restrict whether the template is successfully\n * loaded.  This means that without the right CORS policy, loading templates from a different domain\n * won't work on all browsers.  Also, loading templates from `file://` URL does not work on some\n * browsers.\n *\n * ## This feels like too much overhead\n *\n * It's important to remember that SCE only applies to interpolation expressions.\n *\n * If your expressions are constant literals, they're automatically trusted and you don't need to\n * call `$sce.trustAs` on them (remember to include the `ngSanitize` module) (e.g.\n * `<div ng-bind-html=\"'<b>implicitly trusted</b>'\"></div>`) just works.\n *\n * Additionally, `a[href]` and `img[src]` automatically sanitize their URLs and do not pass them\n * through {@link ng.$sce#getTrusted $sce.getTrusted}.  SCE doesn't play a role here.\n *\n * The included {@link ng.$sceDelegate $sceDelegate} comes with sane defaults to allow you to load\n * templates in `ng-include` from your application's domain without having to even know about SCE.\n * It blocks loading templates from other domains or loading templates over http from an https\n * served document.  You can change these by setting your own custom {@link\n * ng.$sceDelegateProvider#resourceUrlWhitelist whitelists} and {@link\n * ng.$sceDelegateProvider#resourceUrlBlacklist blacklists} for matching such URLs.\n *\n * This significantly reduces the overhead.  It is far easier to pay the small overhead and have an\n * application that's secure and can be audited to verify that with much more ease than bolting\n * security onto an application later.\n *\n * <a name=\"contexts\"></a>\n * ## What trusted context types are supported?\n *\n * | Context             | Notes          |\n * |---------------------|----------------|\n * | `$sce.HTML`         | For HTML that's safe to source into the application.  The {@link ng.directive:ngBindHtml ngBindHtml} directive uses this context for bindings. If an unsafe value is encountered and the {@link ngSanitize $sanitize} module is present this will sanitize the value instead of throwing an error. |\n * | `$sce.CSS`          | For CSS that's safe to source into the application.  Currently unused.  Feel free to use it in your own directives. |\n * | `$sce.URL`          | For URLs that are safe to follow as links.  Currently unused (`<a href=` and `<img src=` sanitize their urls and don't constitute an SCE context. |\n * | `$sce.RESOURCE_URL` | For URLs that are not only safe to follow as links, but whose contents are also safe to include in your application.  Examples include `ng-include`, `src` / `ngSrc` bindings for tags other than `IMG` (e.g. `IFRAME`, `OBJECT`, etc.)  <br><br>Note that `$sce.RESOURCE_URL` makes a stronger statement about the URL than `$sce.URL` does and therefore contexts requiring values trusted for `$sce.RESOURCE_URL` can be used anywhere that values trusted for `$sce.URL` are required. |\n * | `$sce.JS`           | For JavaScript that is safe to execute in your application's context.  Currently unused.  Feel free to use it in your own directives. |\n *\n * ## Format of items in {@link ng.$sceDelegateProvider#resourceUrlWhitelist resourceUrlWhitelist}/{@link ng.$sceDelegateProvider#resourceUrlBlacklist Blacklist} <a name=\"resourceUrlPatternItem\"></a>\n *\n *  Each element in these arrays must be one of the following:\n *\n *  - **'self'**\n *    - The special **string**, `'self'`, can be used to match against all URLs of the **same\n *      domain** as the application document using the **same protocol**.\n *  - **String** (except the special value `'self'`)\n *    - The string is matched against the full *normalized / absolute URL* of the resource\n *      being tested (substring matches are not good enough.)\n *    - There are exactly **two wildcard sequences** - `*` and `**`.  All other characters\n *      match themselves.\n *    - `*`: matches zero or more occurrences of any character other than one of the following 6\n *      characters: '`:`', '`/`', '`.`', '`?`', '`&`' and ';'.  It's a useful wildcard for use\n *      in a whitelist.\n *    - `**`: matches zero or more occurrences of *any* character.  As such, it's not\n *      not appropriate to use in for a scheme, domain, etc. as it would match too much.  (e.g.\n *      http://**.example.com/ would match http://evil.com/?ignore=.example.com/ and that might\n *      not have been the intention.)  Its usage at the very end of the path is ok.  (e.g.\n *      http://foo.example.com/templates/**).\n *  - **RegExp** (*see caveat below*)\n *    - *Caveat*:  While regular expressions are powerful and offer great flexibility,  their syntax\n *      (and all the inevitable escaping) makes them *harder to maintain*.  It's easy to\n *      accidentally introduce a bug when one updates a complex expression (imho, all regexes should\n *      have good test coverage.).  For instance, the use of `.` in the regex is correct only in a\n *      small number of cases.  A `.` character in the regex used when matching the scheme or a\n *      subdomain could be matched against a `:` or literal `.` that was likely not intended.   It\n *      is highly recommended to use the string patterns and only fall back to regular expressions\n *      if they as a last resort.\n *    - The regular expression must be an instance of RegExp (i.e. not a string.)  It is\n *      matched against the **entire** *normalized / absolute URL* of the resource being tested\n *      (even when the RegExp did not have the `^` and `$` codes.)  In addition, any flags\n *      present on the RegExp (such as multiline, global, ignoreCase) are ignored.\n *    - If you are generating your JavaScript from some other templating engine (not\n *      recommended, e.g. in issue [#4006](https://github.com/angular/angular.js/issues/4006)),\n *      remember to escape your regular expression (and be aware that you might need more than\n *      one level of escaping depending on your templating engine and the way you interpolated\n *      the value.)  Do make use of your platform's escaping mechanism as it might be good\n *      enough before coding your own.  e.g. Ruby has\n *      [Regexp.escape(str)](http://www.ruby-doc.org/core-2.0.0/Regexp.html#method-c-escape)\n *      and Python has [re.escape](http://docs.python.org/library/re.html#re.escape).\n *      Javascript lacks a similar built in function for escaping.  Take a look at Google\n *      Closure library's [goog.string.regExpEscape(s)](\n *      http://docs.closure-library.googlecode.com/git/closure_goog_string_string.js.source.html#line962).\n *\n * Refer {@link ng.$sceDelegateProvider $sceDelegateProvider} for an example.\n *\n * ## Show me an example using SCE.\n *\n * <example module=\"mySceApp\" deps=\"angular-sanitize.js\">\n * <file name=\"index.html\">\n *   <div ng-controller=\"AppController as myCtrl\">\n *     <i ng-bind-html=\"myCtrl.explicitlyTrustedHtml\" id=\"explicitlyTrustedHtml\"></i><br><br>\n *     <b>User comments</b><br>\n *     By default, HTML that isn't explicitly trusted (e.g. Alice's comment) is sanitized when\n *     $sanitize is available.  If $sanitize isn't available, this results in an error instead of an\n *     exploit.\n *     <div class=\"well\">\n *       <div ng-repeat=\"userComment in myCtrl.userComments\">\n *         <b>{{userComment.name}}</b>:\n *         <span ng-bind-html=\"userComment.htmlComment\" class=\"htmlComment\"></span>\n *         <br>\n *       </div>\n *     </div>\n *   </div>\n * </file>\n *\n * <file name=\"script.js\">\n *   angular.module('mySceApp', ['ngSanitize'])\n *     .controller('AppController', ['$http', '$templateCache', '$sce',\n *       function($http, $templateCache, $sce) {\n *         var self = this;\n *         $http.get(\"test_data.json\", {cache: $templateCache}).success(function(userComments) {\n *           self.userComments = userComments;\n *         });\n *         self.explicitlyTrustedHtml = $sce.trustAsHtml(\n *             '<span onmouseover=\"this.textContent=&quot;Explicitly trusted HTML bypasses ' +\n *             'sanitization.&quot;\">Hover over this text.</span>');\n *       }]);\n * </file>\n *\n * <file name=\"test_data.json\">\n * [\n *   { \"name\": \"Alice\",\n *     \"htmlComment\":\n *         \"<span onmouseover='this.textContent=\\\"PWN3D!\\\"'>Is <i>anyone</i> reading this?</span>\"\n *   },\n *   { \"name\": \"Bob\",\n *     \"htmlComment\": \"<i>Yes!</i>  Am I the only other one?\"\n *   }\n * ]\n * </file>\n *\n * <file name=\"protractor.js\" type=\"protractor\">\n *   describe('SCE doc demo', function() {\n *     it('should sanitize untrusted values', function() {\n *       expect(element.all(by.css('.htmlComment')).first().getInnerHtml())\n *           .toBe('<span>Is <i>anyone</i> reading this?</span>');\n *     });\n *\n *     it('should NOT sanitize explicitly trusted values', function() {\n *       expect(element(by.id('explicitlyTrustedHtml')).getInnerHtml()).toBe(\n *           '<span onmouseover=\"this.textContent=&quot;Explicitly trusted HTML bypasses ' +\n *           'sanitization.&quot;\">Hover over this text.</span>');\n *     });\n *   });\n * </file>\n * </example>\n *\n *\n *\n * ## Can I disable SCE completely?\n *\n * Yes, you can.  However, this is strongly discouraged.  SCE gives you a lot of security benefits\n * for little coding overhead.  It will be much harder to take an SCE disabled application and\n * either secure it on your own or enable SCE at a later stage.  It might make sense to disable SCE\n * for cases where you have a lot of existing code that was written before SCE was introduced and\n * you're migrating them a module at a time.\n *\n * That said, here's how you can completely disable SCE:\n *\n * ```\n * angular.module('myAppWithSceDisabledmyApp', []).config(function($sceProvider) {\n *   // Completely disable SCE.  For demonstration purposes only!\n *   // Do not use in new projects.\n *   $sceProvider.enabled(false);\n * });\n * ```\n *\n */\n/* jshint maxlen: 100 */\n\nfunction $SceProvider() {\n  var enabled = true;\n\n  /**\n   * @ngdoc method\n   * @name $sceProvider#enabled\n   * @kind function\n   *\n   * @param {boolean=} value If provided, then enables/disables SCE.\n   * @return {boolean} true if SCE is enabled, false otherwise.\n   *\n   * @description\n   * Enables/disables SCE and returns the current value.\n   */\n  this.enabled = function(value) {\n    if (arguments.length) {\n      enabled = !!value;\n    }\n    return enabled;\n  };\n\n\n  /* Design notes on the default implementation for SCE.\n   *\n   * The API contract for the SCE delegate\n   * -------------------------------------\n   * The SCE delegate object must provide the following 3 methods:\n   *\n   * - trustAs(contextEnum, value)\n   *     This method is used to tell the SCE service that the provided value is OK to use in the\n   *     contexts specified by contextEnum.  It must return an object that will be accepted by\n   *     getTrusted() for a compatible contextEnum and return this value.\n   *\n   * - valueOf(value)\n   *     For values that were not produced by trustAs(), return them as is.  For values that were\n   *     produced by trustAs(), return the corresponding input value to trustAs.  Basically, if\n   *     trustAs is wrapping the given values into some type, this operation unwraps it when given\n   *     such a value.\n   *\n   * - getTrusted(contextEnum, value)\n   *     This function should return the a value that is safe to use in the context specified by\n   *     contextEnum or throw and exception otherwise.\n   *\n   * NOTE: This contract deliberately does NOT state that values returned by trustAs() must be\n   * opaque or wrapped in some holder object.  That happens to be an implementation detail.  For\n   * instance, an implementation could maintain a registry of all trusted objects by context.  In\n   * such a case, trustAs() would return the same object that was passed in.  getTrusted() would\n   * return the same object passed in if it was found in the registry under a compatible context or\n   * throw an exception otherwise.  An implementation might only wrap values some of the time based\n   * on some criteria.  getTrusted() might return a value and not throw an exception for special\n   * constants or objects even if not wrapped.  All such implementations fulfill this contract.\n   *\n   *\n   * A note on the inheritance model for SCE contexts\n   * ------------------------------------------------\n   * I've used inheritance and made RESOURCE_URL wrapped types a subtype of URL wrapped types.  This\n   * is purely an implementation details.\n   *\n   * The contract is simply this:\n   *\n   *     getTrusted($sce.RESOURCE_URL, value) succeeding implies that getTrusted($sce.URL, value)\n   *     will also succeed.\n   *\n   * Inheritance happens to capture this in a natural way.  In some future, we\n   * may not use inheritance anymore.  That is OK because no code outside of\n   * sce.js and sceSpecs.js would need to be aware of this detail.\n   */\n\n  this.$get = ['$parse', '$sceDelegate', function(\n                $parse,   $sceDelegate) {\n    // Prereq: Ensure that we're not running in IE<11 quirks mode.  In that mode, IE < 11 allow\n    // the \"expression(javascript expression)\" syntax which is insecure.\n    if (enabled && msie < 8) {\n      throw $sceMinErr('iequirks',\n        'Strict Contextual Escaping does not support Internet Explorer version < 11 in quirks ' +\n        'mode.  You can fix this by adding the text <!doctype html> to the top of your HTML ' +\n        'document.  See http://docs.angularjs.org/api/ng.$sce for more information.');\n    }\n\n    var sce = shallowCopy(SCE_CONTEXTS);\n\n    /**\n     * @ngdoc method\n     * @name $sce#isEnabled\n     * @kind function\n     *\n     * @return {Boolean} true if SCE is enabled, false otherwise.  If you want to set the value, you\n     * have to do it at module config time on {@link ng.$sceProvider $sceProvider}.\n     *\n     * @description\n     * Returns a boolean indicating if SCE is enabled.\n     */\n    sce.isEnabled = function() {\n      return enabled;\n    };\n    sce.trustAs = $sceDelegate.trustAs;\n    sce.getTrusted = $sceDelegate.getTrusted;\n    sce.valueOf = $sceDelegate.valueOf;\n\n    if (!enabled) {\n      sce.trustAs = sce.getTrusted = function(type, value) { return value; };\n      sce.valueOf = identity;\n    }\n\n    /**\n     * @ngdoc method\n     * @name $sce#parseAs\n     *\n     * @description\n     * Converts Angular {@link guide/expression expression} into a function.  This is like {@link\n     * ng.$parse $parse} and is identical when the expression is a literal constant.  Otherwise, it\n     * wraps the expression in a call to {@link ng.$sce#getTrusted $sce.getTrusted(*type*,\n     * *result*)}\n     *\n     * @param {string} type The kind of SCE context in which this result will be used.\n     * @param {string} expression String expression to compile.\n     * @returns {function(context, locals)} a function which represents the compiled expression:\n     *\n     *    * `context` – `{object}` – an object against which any expressions embedded in the strings\n     *      are evaluated against (typically a scope object).\n     *    * `locals` – `{object=}` – local variables context object, useful for overriding values in\n     *      `context`.\n     */\n    sce.parseAs = function sceParseAs(type, expr) {\n      var parsed = $parse(expr);\n      if (parsed.literal && parsed.constant) {\n        return parsed;\n      } else {\n        return $parse(expr, function(value) {\n          return sce.getTrusted(type, value);\n        });\n      }\n    };\n\n    /**\n     * @ngdoc method\n     * @name $sce#trustAs\n     *\n     * @description\n     * Delegates to {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs`}.  As such,\n     * returns an object that is trusted by angular for use in specified strict contextual\n     * escaping contexts (such as ng-bind-html, ng-include, any src attribute\n     * interpolation, any dom event binding attribute interpolation such as for onclick,  etc.)\n     * that uses the provided value.  See * {@link ng.$sce $sce} for enabling strict contextual\n     * escaping.\n     *\n     * @param {string} type The kind of context in which this value is safe for use.  e.g. url,\n     *   resource_url, html, js and css.\n     * @param {*} value The value that that should be considered trusted/safe.\n     * @returns {*} A value that can be used to stand in for the provided `value` in places\n     * where Angular expects a $sce.trustAs() return value.\n     */\n\n    /**\n     * @ngdoc method\n     * @name $sce#trustAsHtml\n     *\n     * @description\n     * Shorthand method.  `$sce.trustAsHtml(value)` →\n     *     {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs($sce.HTML, value)`}\n     *\n     * @param {*} value The value to trustAs.\n     * @returns {*} An object that can be passed to {@link ng.$sce#getTrustedHtml\n     *     $sce.getTrustedHtml(value)} to obtain the original value.  (privileged directives\n     *     only accept expressions that are either literal constants or are the\n     *     return value of {@link ng.$sce#trustAs $sce.trustAs}.)\n     */\n\n    /**\n     * @ngdoc method\n     * @name $sce#trustAsUrl\n     *\n     * @description\n     * Shorthand method.  `$sce.trustAsUrl(value)` →\n     *     {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs($sce.URL, value)`}\n     *\n     * @param {*} value The value to trustAs.\n     * @returns {*} An object that can be passed to {@link ng.$sce#getTrustedUrl\n     *     $sce.getTrustedUrl(value)} to obtain the original value.  (privileged directives\n     *     only accept expressions that are either literal constants or are the\n     *     return value of {@link ng.$sce#trustAs $sce.trustAs}.)\n     */\n\n    /**\n     * @ngdoc method\n     * @name $sce#trustAsResourceUrl\n     *\n     * @description\n     * Shorthand method.  `$sce.trustAsResourceUrl(value)` →\n     *     {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs($sce.RESOURCE_URL, value)`}\n     *\n     * @param {*} value The value to trustAs.\n     * @returns {*} An object that can be passed to {@link ng.$sce#getTrustedResourceUrl\n     *     $sce.getTrustedResourceUrl(value)} to obtain the original value.  (privileged directives\n     *     only accept expressions that are either literal constants or are the return\n     *     value of {@link ng.$sce#trustAs $sce.trustAs}.)\n     */\n\n    /**\n     * @ngdoc method\n     * @name $sce#trustAsJs\n     *\n     * @description\n     * Shorthand method.  `$sce.trustAsJs(value)` →\n     *     {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs($sce.JS, value)`}\n     *\n     * @param {*} value The value to trustAs.\n     * @returns {*} An object that can be passed to {@link ng.$sce#getTrustedJs\n     *     $sce.getTrustedJs(value)} to obtain the original value.  (privileged directives\n     *     only accept expressions that are either literal constants or are the\n     *     return value of {@link ng.$sce#trustAs $sce.trustAs}.)\n     */\n\n    /**\n     * @ngdoc method\n     * @name $sce#getTrusted\n     *\n     * @description\n     * Delegates to {@link ng.$sceDelegate#getTrusted `$sceDelegate.getTrusted`}.  As such,\n     * takes the result of a {@link ng.$sce#trustAs `$sce.trustAs`}() call and returns the\n     * originally supplied value if the queried context type is a supertype of the created type.\n     * If this condition isn't satisfied, throws an exception.\n     *\n     * @param {string} type The kind of context in which this value is to be used.\n     * @param {*} maybeTrusted The result of a prior {@link ng.$sce#trustAs `$sce.trustAs`}\n     *                         call.\n     * @returns {*} The value the was originally provided to\n     *              {@link ng.$sce#trustAs `$sce.trustAs`} if valid in this context.\n     *              Otherwise, throws an exception.\n     */\n\n    /**\n     * @ngdoc method\n     * @name $sce#getTrustedHtml\n     *\n     * @description\n     * Shorthand method.  `$sce.getTrustedHtml(value)` →\n     *     {@link ng.$sceDelegate#getTrusted `$sceDelegate.getTrusted($sce.HTML, value)`}\n     *\n     * @param {*} value The value to pass to `$sce.getTrusted`.\n     * @returns {*} The return value of `$sce.getTrusted($sce.HTML, value)`\n     */\n\n    /**\n     * @ngdoc method\n     * @name $sce#getTrustedCss\n     *\n     * @description\n     * Shorthand method.  `$sce.getTrustedCss(value)` →\n     *     {@link ng.$sceDelegate#getTrusted `$sceDelegate.getTrusted($sce.CSS, value)`}\n     *\n     * @param {*} value The value to pass to `$sce.getTrusted`.\n     * @returns {*} The return value of `$sce.getTrusted($sce.CSS, value)`\n     */\n\n    /**\n     * @ngdoc method\n     * @name $sce#getTrustedUrl\n     *\n     * @description\n     * Shorthand method.  `$sce.getTrustedUrl(value)` →\n     *     {@link ng.$sceDelegate#getTrusted `$sceDelegate.getTrusted($sce.URL, value)`}\n     *\n     * @param {*} value The value to pass to `$sce.getTrusted`.\n     * @returns {*} The return value of `$sce.getTrusted($sce.URL, value)`\n     */\n\n    /**\n     * @ngdoc method\n     * @name $sce#getTrustedResourceUrl\n     *\n     * @description\n     * Shorthand method.  `$sce.getTrustedResourceUrl(value)` →\n     *     {@link ng.$sceDelegate#getTrusted `$sceDelegate.getTrusted($sce.RESOURCE_URL, value)`}\n     *\n     * @param {*} value The value to pass to `$sceDelegate.getTrusted`.\n     * @returns {*} The return value of `$sce.getTrusted($sce.RESOURCE_URL, value)`\n     */\n\n    /**\n     * @ngdoc method\n     * @name $sce#getTrustedJs\n     *\n     * @description\n     * Shorthand method.  `$sce.getTrustedJs(value)` →\n     *     {@link ng.$sceDelegate#getTrusted `$sceDelegate.getTrusted($sce.JS, value)`}\n     *\n     * @param {*} value The value to pass to `$sce.getTrusted`.\n     * @returns {*} The return value of `$sce.getTrusted($sce.JS, value)`\n     */\n\n    /**\n     * @ngdoc method\n     * @name $sce#parseAsHtml\n     *\n     * @description\n     * Shorthand method.  `$sce.parseAsHtml(expression string)` →\n     *     {@link ng.$sce#parseAs `$sce.parseAs($sce.HTML, value)`}\n     *\n     * @param {string} expression String expression to compile.\n     * @returns {function(context, locals)} a function which represents the compiled expression:\n     *\n     *    * `context` – `{object}` – an object against which any expressions embedded in the strings\n     *      are evaluated against (typically a scope object).\n     *    * `locals` – `{object=}` – local variables context object, useful for overriding values in\n     *      `context`.\n     */\n\n    /**\n     * @ngdoc method\n     * @name $sce#parseAsCss\n     *\n     * @description\n     * Shorthand method.  `$sce.parseAsCss(value)` →\n     *     {@link ng.$sce#parseAs `$sce.parseAs($sce.CSS, value)`}\n     *\n     * @param {string} expression String expression to compile.\n     * @returns {function(context, locals)} a function which represents the compiled expression:\n     *\n     *    * `context` – `{object}` – an object against which any expressions embedded in the strings\n     *      are evaluated against (typically a scope object).\n     *    * `locals` – `{object=}` – local variables context object, useful for overriding values in\n     *      `context`.\n     */\n\n    /**\n     * @ngdoc method\n     * @name $sce#parseAsUrl\n     *\n     * @description\n     * Shorthand method.  `$sce.parseAsUrl(value)` →\n     *     {@link ng.$sce#parseAs `$sce.parseAs($sce.URL, value)`}\n     *\n     * @param {string} expression String expression to compile.\n     * @returns {function(context, locals)} a function which represents the compiled expression:\n     *\n     *    * `context` – `{object}` – an object against which any expressions embedded in the strings\n     *      are evaluated against (typically a scope object).\n     *    * `locals` – `{object=}` – local variables context object, useful for overriding values in\n     *      `context`.\n     */\n\n    /**\n     * @ngdoc method\n     * @name $sce#parseAsResourceUrl\n     *\n     * @description\n     * Shorthand method.  `$sce.parseAsResourceUrl(value)` →\n     *     {@link ng.$sce#parseAs `$sce.parseAs($sce.RESOURCE_URL, value)`}\n     *\n     * @param {string} expression String expression to compile.\n     * @returns {function(context, locals)} a function which represents the compiled expression:\n     *\n     *    * `context` – `{object}` – an object against which any expressions embedded in the strings\n     *      are evaluated against (typically a scope object).\n     *    * `locals` – `{object=}` – local variables context object, useful for overriding values in\n     *      `context`.\n     */\n\n    /**\n     * @ngdoc method\n     * @name $sce#parseAsJs\n     *\n     * @description\n     * Shorthand method.  `$sce.parseAsJs(value)` →\n     *     {@link ng.$sce#parseAs `$sce.parseAs($sce.JS, value)`}\n     *\n     * @param {string} expression String expression to compile.\n     * @returns {function(context, locals)} a function which represents the compiled expression:\n     *\n     *    * `context` – `{object}` – an object against which any expressions embedded in the strings\n     *      are evaluated against (typically a scope object).\n     *    * `locals` – `{object=}` – local variables context object, useful for overriding values in\n     *      `context`.\n     */\n\n    // Shorthand delegations.\n    var parse = sce.parseAs,\n        getTrusted = sce.getTrusted,\n        trustAs = sce.trustAs;\n\n    forEach(SCE_CONTEXTS, function(enumValue, name) {\n      var lName = lowercase(name);\n      sce[camelCase(\"parse_as_\" + lName)] = function(expr) {\n        return parse(enumValue, expr);\n      };\n      sce[camelCase(\"get_trusted_\" + lName)] = function(value) {\n        return getTrusted(enumValue, value);\n      };\n      sce[camelCase(\"trust_as_\" + lName)] = function(value) {\n        return trustAs(enumValue, value);\n      };\n    });\n\n    return sce;\n  }];\n}\n\n/**\n * !!! This is an undocumented \"private\" service !!!\n *\n * @name $sniffer\n * @requires $window\n * @requires $document\n *\n * @property {boolean} history Does the browser support html5 history api ?\n * @property {boolean} transitions Does the browser support CSS transition events ?\n * @property {boolean} animations Does the browser support CSS animation events ?\n *\n * @description\n * This is very simple implementation of testing browser's features.\n */\nfunction $SnifferProvider() {\n  this.$get = ['$window', '$document', function($window, $document) {\n    var eventSupport = {},\n        android =\n          int((/android (\\d+)/.exec(lowercase(($window.navigator || {}).userAgent)) || [])[1]),\n        boxee = /Boxee/i.test(($window.navigator || {}).userAgent),\n        document = $document[0] || {},\n        vendorPrefix,\n        vendorRegex = /^(Moz|webkit|ms)(?=[A-Z])/,\n        bodyStyle = document.body && document.body.style,\n        transitions = false,\n        animations = false,\n        match;\n\n    if (bodyStyle) {\n      for (var prop in bodyStyle) {\n        if (match = vendorRegex.exec(prop)) {\n          vendorPrefix = match[0];\n          vendorPrefix = vendorPrefix.substr(0, 1).toUpperCase() + vendorPrefix.substr(1);\n          break;\n        }\n      }\n\n      if (!vendorPrefix) {\n        vendorPrefix = ('WebkitOpacity' in bodyStyle) && 'webkit';\n      }\n\n      transitions = !!(('transition' in bodyStyle) || (vendorPrefix + 'Transition' in bodyStyle));\n      animations  = !!(('animation' in bodyStyle) || (vendorPrefix + 'Animation' in bodyStyle));\n\n      if (android && (!transitions ||  !animations)) {\n        transitions = isString(document.body.style.webkitTransition);\n        animations = isString(document.body.style.webkitAnimation);\n      }\n    }\n\n\n    return {\n      // Android has history.pushState, but it does not update location correctly\n      // so let's not use the history API at all.\n      // http://code.google.com/p/android/issues/detail?id=17471\n      // https://github.com/angular/angular.js/issues/904\n\n      // older webkit browser (533.9) on Boxee box has exactly the same problem as Android has\n      // so let's not use the history API also\n      // We are purposefully using `!(android < 4)` to cover the case when `android` is undefined\n      // jshint -W018\n      history: !!($window.history && $window.history.pushState && !(android < 4) && !boxee),\n      // jshint +W018\n      hasEvent: function(event) {\n        // IE9 implements 'input' event it's so fubared that we rather pretend that it doesn't have\n        // it. In particular the event is not fired when backspace or delete key are pressed or\n        // when cut operation is performed.\n        // IE10+ implements 'input' event but it erroneously fires under various situations,\n        // e.g. when placeholder changes, or a form is focused.\n        if (event === 'input' && msie <= 11) return false;\n\n        if (isUndefined(eventSupport[event])) {\n          var divElm = document.createElement('div');\n          eventSupport[event] = 'on' + event in divElm;\n        }\n\n        return eventSupport[event];\n      },\n      csp: csp(),\n      vendorPrefix: vendorPrefix,\n      transitions: transitions,\n      animations: animations,\n      android: android\n    };\n  }];\n}\n\nvar $compileMinErr = minErr('$compile');\n\n/**\n * @ngdoc service\n * @name $templateRequest\n *\n * @description\n * The `$templateRequest` service downloads the provided template using `$http` and, upon success,\n * stores the contents inside of `$templateCache`. If the HTTP request fails or the response data\n * of the HTTP request is empty, a `$compile` error will be thrown (the exception can be thwarted\n * by setting the 2nd parameter of the function to true).\n *\n * @param {string} tpl The HTTP request template URL\n * @param {boolean=} ignoreRequestError Whether or not to ignore the exception when the request fails or the template is empty\n *\n * @return {Promise} the HTTP Promise for the given.\n *\n * @property {number} totalPendingRequests total amount of pending template requests being downloaded.\n */\nfunction $TemplateRequestProvider() {\n  this.$get = ['$templateCache', '$http', '$q', function($templateCache, $http, $q) {\n    function handleRequestFn(tpl, ignoreRequestError) {\n      handleRequestFn.totalPendingRequests++;\n\n      var transformResponse = $http.defaults && $http.defaults.transformResponse;\n\n      if (isArray(transformResponse)) {\n        transformResponse = transformResponse.filter(function(transformer) {\n          return transformer !== defaultHttpResponseTransform;\n        });\n      } else if (transformResponse === defaultHttpResponseTransform) {\n        transformResponse = null;\n      }\n\n      var httpOptions = {\n        cache: $templateCache,\n        transformResponse: transformResponse\n      };\n\n      return $http.get(tpl, httpOptions)\n        .finally(function() {\n          handleRequestFn.totalPendingRequests--;\n        })\n        .then(function(response) {\n          return response.data;\n        }, handleError);\n\n      function handleError(resp) {\n        if (!ignoreRequestError) {\n          throw $compileMinErr('tpload', 'Failed to load template: {0}', tpl);\n        }\n        return $q.reject(resp);\n      }\n    }\n\n    handleRequestFn.totalPendingRequests = 0;\n\n    return handleRequestFn;\n  }];\n}\n\nfunction $$TestabilityProvider() {\n  this.$get = ['$rootScope', '$browser', '$location',\n       function($rootScope,   $browser,   $location) {\n\n    /**\n     * @name $testability\n     *\n     * @description\n     * The private $$testability service provides a collection of methods for use when debugging\n     * or by automated test and debugging tools.\n     */\n    var testability = {};\n\n    /**\n     * @name $$testability#findBindings\n     *\n     * @description\n     * Returns an array of elements that are bound (via ng-bind or {{}})\n     * to expressions matching the input.\n     *\n     * @param {Element} element The element root to search from.\n     * @param {string} expression The binding expression to match.\n     * @param {boolean} opt_exactMatch If true, only returns exact matches\n     *     for the expression. Filters and whitespace are ignored.\n     */\n    testability.findBindings = function(element, expression, opt_exactMatch) {\n      var bindings = element.getElementsByClassName('ng-binding');\n      var matches = [];\n      forEach(bindings, function(binding) {\n        var dataBinding = angular.element(binding).data('$binding');\n        if (dataBinding) {\n          forEach(dataBinding, function(bindingName) {\n            if (opt_exactMatch) {\n              var matcher = new RegExp('(^|\\\\s)' + escapeForRegexp(expression) + '(\\\\s|\\\\||$)');\n              if (matcher.test(bindingName)) {\n                matches.push(binding);\n              }\n            } else {\n              if (bindingName.indexOf(expression) != -1) {\n                matches.push(binding);\n              }\n            }\n          });\n        }\n      });\n      return matches;\n    };\n\n    /**\n     * @name $$testability#findModels\n     *\n     * @description\n     * Returns an array of elements that are two-way found via ng-model to\n     * expressions matching the input.\n     *\n     * @param {Element} element The element root to search from.\n     * @param {string} expression The model expression to match.\n     * @param {boolean} opt_exactMatch If true, only returns exact matches\n     *     for the expression.\n     */\n    testability.findModels = function(element, expression, opt_exactMatch) {\n      var prefixes = ['ng-', 'data-ng-', 'ng\\\\:'];\n      for (var p = 0; p < prefixes.length; ++p) {\n        var attributeEquals = opt_exactMatch ? '=' : '*=';\n        var selector = '[' + prefixes[p] + 'model' + attributeEquals + '\"' + expression + '\"]';\n        var elements = element.querySelectorAll(selector);\n        if (elements.length) {\n          return elements;\n        }\n      }\n    };\n\n    /**\n     * @name $$testability#getLocation\n     *\n     * @description\n     * Shortcut for getting the location in a browser agnostic way. Returns\n     *     the path, search, and hash. (e.g. /path?a=b#hash)\n     */\n    testability.getLocation = function() {\n      return $location.url();\n    };\n\n    /**\n     * @name $$testability#setLocation\n     *\n     * @description\n     * Shortcut for navigating to a location without doing a full page reload.\n     *\n     * @param {string} url The location url (path, search and hash,\n     *     e.g. /path?a=b#hash) to go to.\n     */\n    testability.setLocation = function(url) {\n      if (url !== $location.url()) {\n        $location.url(url);\n        $rootScope.$digest();\n      }\n    };\n\n    /**\n     * @name $$testability#whenStable\n     *\n     * @description\n     * Calls the callback when $timeout and $http requests are completed.\n     *\n     * @param {function} callback\n     */\n    testability.whenStable = function(callback) {\n      $browser.notifyWhenNoOutstandingRequests(callback);\n    };\n\n    return testability;\n  }];\n}\n\nfunction $TimeoutProvider() {\n  this.$get = ['$rootScope', '$browser', '$q', '$$q', '$exceptionHandler',\n       function($rootScope,   $browser,   $q,   $$q,   $exceptionHandler) {\n    var deferreds = {};\n\n\n     /**\n      * @ngdoc service\n      * @name $timeout\n      *\n      * @description\n      * Angular's wrapper for `window.setTimeout`. The `fn` function is wrapped into a try/catch\n      * block and delegates any exceptions to\n      * {@link ng.$exceptionHandler $exceptionHandler} service.\n      *\n      * The return value of registering a timeout function is a promise, which will be resolved when\n      * the timeout is reached and the timeout function is executed.\n      *\n      * To cancel a timeout request, call `$timeout.cancel(promise)`.\n      *\n      * In tests you can use {@link ngMock.$timeout `$timeout.flush()`} to\n      * synchronously flush the queue of deferred functions.\n      *\n      * @param {function()} fn A function, whose execution should be delayed.\n      * @param {number=} [delay=0] Delay in milliseconds.\n      * @param {boolean=} [invokeApply=true] If set to `false` skips model dirty checking, otherwise\n      *   will invoke `fn` within the {@link ng.$rootScope.Scope#$apply $apply} block.\n      * @returns {Promise} Promise that will be resolved when the timeout is reached. The value this\n      *   promise will be resolved with is the return value of the `fn` function.\n      *\n      */\n    function timeout(fn, delay, invokeApply) {\n      var skipApply = (isDefined(invokeApply) && !invokeApply),\n          deferred = (skipApply ? $$q : $q).defer(),\n          promise = deferred.promise,\n          timeoutId;\n\n      timeoutId = $browser.defer(function() {\n        try {\n          deferred.resolve(fn());\n        } catch (e) {\n          deferred.reject(e);\n          $exceptionHandler(e);\n        }\n        finally {\n          delete deferreds[promise.$$timeoutId];\n        }\n\n        if (!skipApply) $rootScope.$apply();\n      }, delay);\n\n      promise.$$timeoutId = timeoutId;\n      deferreds[timeoutId] = deferred;\n\n      return promise;\n    }\n\n\n     /**\n      * @ngdoc method\n      * @name $timeout#cancel\n      *\n      * @description\n      * Cancels a task associated with the `promise`. As a result of this, the promise will be\n      * resolved with a rejection.\n      *\n      * @param {Promise=} promise Promise returned by the `$timeout` function.\n      * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfully\n      *   canceled.\n      */\n    timeout.cancel = function(promise) {\n      if (promise && promise.$$timeoutId in deferreds) {\n        deferreds[promise.$$timeoutId].reject('canceled');\n        delete deferreds[promise.$$timeoutId];\n        return $browser.defer.cancel(promise.$$timeoutId);\n      }\n      return false;\n    };\n\n    return timeout;\n  }];\n}\n\n// NOTE:  The usage of window and document instead of $window and $document here is\n// deliberate.  This service depends on the specific behavior of anchor nodes created by the\n// browser (resolving and parsing URLs) that is unlikely to be provided by mock objects and\n// cause us to break tests.  In addition, when the browser resolves a URL for XHR, it\n// doesn't know about mocked locations and resolves URLs to the real document - which is\n// exactly the behavior needed here.  There is little value is mocking these out for this\n// service.\nvar urlParsingNode = document.createElement(\"a\");\nvar originUrl = urlResolve(window.location.href);\n\n\n/**\n *\n * Implementation Notes for non-IE browsers\n * ----------------------------------------\n * Assigning a URL to the href property of an anchor DOM node, even one attached to the DOM,\n * results both in the normalizing and parsing of the URL.  Normalizing means that a relative\n * URL will be resolved into an absolute URL in the context of the application document.\n * Parsing means that the anchor node's host, hostname, protocol, port, pathname and related\n * properties are all populated to reflect the normalized URL.  This approach has wide\n * compatibility - Safari 1+, Mozilla 1+, Opera 7+,e etc.  See\n * http://www.aptana.com/reference/html/api/HTMLAnchorElement.html\n *\n * Implementation Notes for IE\n * ---------------------------\n * IE >= 8 and <= 10 normalizes the URL when assigned to the anchor node similar to the other\n * browsers.  However, the parsed components will not be set if the URL assigned did not specify\n * them.  (e.g. if you assign a.href = \"foo\", then a.protocol, a.host, etc. will be empty.)  We\n * work around that by performing the parsing in a 2nd step by taking a previously normalized\n * URL (e.g. by assigning to a.href) and assigning it a.href again.  This correctly populates the\n * properties such as protocol, hostname, port, etc.\n *\n * IE7 does not normalize the URL when assigned to an anchor node.  (Apparently, it does, if one\n * uses the inner HTML approach to assign the URL as part of an HTML snippet -\n * http://stackoverflow.com/a/472729)  However, setting img[src] does normalize the URL.\n * Unfortunately, setting img[src] to something like \"javascript:foo\" on IE throws an exception.\n * Since the primary usage for normalizing URLs is to sanitize such URLs, we can't use that\n * method and IE < 8 is unsupported.\n *\n * References:\n *   http://developer.mozilla.org/en-US/docs/Web/API/HTMLAnchorElement\n *   http://www.aptana.com/reference/html/api/HTMLAnchorElement.html\n *   http://url.spec.whatwg.org/#urlutils\n *   https://github.com/angular/angular.js/pull/2902\n *   http://james.padolsey.com/javascript/parsing-urls-with-the-dom/\n *\n * @kind function\n * @param {string} url The URL to be parsed.\n * @description Normalizes and parses a URL.\n * @returns {object} Returns the normalized URL as a dictionary.\n *\n *   | member name   | Description    |\n *   |---------------|----------------|\n *   | href          | A normalized version of the provided URL if it was not an absolute URL |\n *   | protocol      | The protocol including the trailing colon                              |\n *   | host          | The host and port (if the port is non-default) of the normalizedUrl    |\n *   | search        | The search params, minus the question mark                             |\n *   | hash          | The hash string, minus the hash symbol\n *   | hostname      | The hostname\n *   | port          | The port, without \":\"\n *   | pathname      | The pathname, beginning with \"/\"\n *\n */\nfunction urlResolve(url) {\n  var href = url;\n\n  if (msie) {\n    // Normalize before parse.  Refer Implementation Notes on why this is\n    // done in two steps on IE.\n    urlParsingNode.setAttribute(\"href\", href);\n    href = urlParsingNode.href;\n  }\n\n  urlParsingNode.setAttribute('href', href);\n\n  // urlParsingNode provides the UrlUtils interface - http://url.spec.whatwg.org/#urlutils\n  return {\n    href: urlParsingNode.href,\n    protocol: urlParsingNode.protocol ? urlParsingNode.protocol.replace(/:$/, '') : '',\n    host: urlParsingNode.host,\n    search: urlParsingNode.search ? urlParsingNode.search.replace(/^\\?/, '') : '',\n    hash: urlParsingNode.hash ? urlParsingNode.hash.replace(/^#/, '') : '',\n    hostname: urlParsingNode.hostname,\n    port: urlParsingNode.port,\n    pathname: (urlParsingNode.pathname.charAt(0) === '/')\n      ? urlParsingNode.pathname\n      : '/' + urlParsingNode.pathname\n  };\n}\n\n/**\n * Parse a request URL and determine whether this is a same-origin request as the application document.\n *\n * @param {string|object} requestUrl The url of the request as a string that will be resolved\n * or a parsed URL object.\n * @returns {boolean} Whether the request is for the same origin as the application document.\n */\nfunction urlIsSameOrigin(requestUrl) {\n  var parsed = (isString(requestUrl)) ? urlResolve(requestUrl) : requestUrl;\n  return (parsed.protocol === originUrl.protocol &&\n          parsed.host === originUrl.host);\n}\n\n/**\n * @ngdoc service\n * @name $window\n *\n * @description\n * A reference to the browser's `window` object. While `window`\n * is globally available in JavaScript, it causes testability problems, because\n * it is a global variable. In angular we always refer to it through the\n * `$window` service, so it may be overridden, removed or mocked for testing.\n *\n * Expressions, like the one defined for the `ngClick` directive in the example\n * below, are evaluated with respect to the current scope.  Therefore, there is\n * no risk of inadvertently coding in a dependency on a global value in such an\n * expression.\n *\n * @example\n   <example module=\"windowExample\">\n     <file name=\"index.html\">\n       <script>\n         angular.module('windowExample', [])\n           .controller('ExampleController', ['$scope', '$window', function($scope, $window) {\n             $scope.greeting = 'Hello, World!';\n             $scope.doGreeting = function(greeting) {\n               $window.alert(greeting);\n             };\n           }]);\n       </script>\n       <div ng-controller=\"ExampleController\">\n         <input type=\"text\" ng-model=\"greeting\" />\n         <button ng-click=\"doGreeting(greeting)\">ALERT</button>\n       </div>\n     </file>\n     <file name=\"protractor.js\" type=\"protractor\">\n      it('should display the greeting in the input box', function() {\n       element(by.model('greeting')).sendKeys('Hello, E2E Tests');\n       // If we click the button it will block the test runner\n       // element(':button').click();\n      });\n     </file>\n   </example>\n */\nfunction $WindowProvider() {\n  this.$get = valueFn(window);\n}\n\n/* global currencyFilter: true,\n dateFilter: true,\n filterFilter: true,\n jsonFilter: true,\n limitToFilter: true,\n lowercaseFilter: true,\n numberFilter: true,\n orderByFilter: true,\n uppercaseFilter: true,\n */\n\n/**\n * @ngdoc provider\n * @name $filterProvider\n * @description\n *\n * Filters are just functions which transform input to an output. However filters need to be\n * Dependency Injected. To achieve this a filter definition consists of a factory function which is\n * annotated with dependencies and is responsible for creating a filter function.\n *\n * ```js\n *   // Filter registration\n *   function MyModule($provide, $filterProvider) {\n *     // create a service to demonstrate injection (not always needed)\n *     $provide.value('greet', function(name){\n *       return 'Hello ' + name + '!';\n *     });\n *\n *     // register a filter factory which uses the\n *     // greet service to demonstrate DI.\n *     $filterProvider.register('greet', function(greet){\n *       // return the filter function which uses the greet service\n *       // to generate salutation\n *       return function(text) {\n *         // filters need to be forgiving so check input validity\n *         return text && greet(text) || text;\n *       };\n *     });\n *   }\n * ```\n *\n * The filter function is registered with the `$injector` under the filter name suffix with\n * `Filter`.\n *\n * ```js\n *   it('should be the same instance', inject(\n *     function($filterProvider) {\n *       $filterProvider.register('reverse', function(){\n *         return ...;\n *       });\n *     },\n *     function($filter, reverseFilter) {\n *       expect($filter('reverse')).toBe(reverseFilter);\n *     });\n * ```\n *\n *\n * For more information about how angular filters work, and how to create your own filters, see\n * {@link guide/filter Filters} in the Angular Developer Guide.\n */\n\n/**\n * @ngdoc service\n * @name $filter\n * @kind function\n * @description\n * Filters are used for formatting data displayed to the user.\n *\n * The general syntax in templates is as follows:\n *\n *         {{ expression [| filter_name[:parameter_value] ... ] }}\n *\n * @param {String} name Name of the filter function to retrieve\n * @return {Function} the filter function\n * @example\n   <example name=\"$filter\" module=\"filterExample\">\n     <file name=\"index.html\">\n       <div ng-controller=\"MainCtrl\">\n        <h3>{{ originalText }}</h3>\n        <h3>{{ filteredText }}</h3>\n       </div>\n     </file>\n\n     <file name=\"script.js\">\n      angular.module('filterExample', [])\n      .controller('MainCtrl', function($scope, $filter) {\n        $scope.originalText = 'hello';\n        $scope.filteredText = $filter('uppercase')($scope.originalText);\n      });\n     </file>\n   </example>\n  */\n$FilterProvider.$inject = ['$provide'];\nfunction $FilterProvider($provide) {\n  var suffix = 'Filter';\n\n  /**\n   * @ngdoc method\n   * @name $filterProvider#register\n   * @param {string|Object} name Name of the filter function, or an object map of filters where\n   *    the keys are the filter names and the values are the filter factories.\n   * @returns {Object} Registered filter instance, or if a map of filters was provided then a map\n   *    of the registered filter instances.\n   */\n  function register(name, factory) {\n    if (isObject(name)) {\n      var filters = {};\n      forEach(name, function(filter, key) {\n        filters[key] = register(key, filter);\n      });\n      return filters;\n    } else {\n      return $provide.factory(name + suffix, factory);\n    }\n  }\n  this.register = register;\n\n  this.$get = ['$injector', function($injector) {\n    return function(name) {\n      return $injector.get(name + suffix);\n    };\n  }];\n\n  ////////////////////////////////////////\n\n  /* global\n    currencyFilter: false,\n    dateFilter: false,\n    filterFilter: false,\n    jsonFilter: false,\n    limitToFilter: false,\n    lowercaseFilter: false,\n    numberFilter: false,\n    orderByFilter: false,\n    uppercaseFilter: false,\n  */\n\n  register('currency', currencyFilter);\n  register('date', dateFilter);\n  register('filter', filterFilter);\n  register('json', jsonFilter);\n  register('limitTo', limitToFilter);\n  register('lowercase', lowercaseFilter);\n  register('number', numberFilter);\n  register('orderBy', orderByFilter);\n  register('uppercase', uppercaseFilter);\n}\n\n/**\n * @ngdoc filter\n * @name filter\n * @kind function\n *\n * @description\n * Selects a subset of items from `array` and returns it as a new array.\n *\n * @param {Array} array The source array.\n * @param {string|Object|function()} expression The predicate to be used for selecting items from\n *   `array`.\n *\n *   Can be one of:\n *\n *   - `string`: The string is used for matching against the contents of the `array`. All strings or\n *     objects with string properties in `array` that match this string will be returned. This also\n *     applies to nested object properties.\n *     The predicate can be negated by prefixing the string with `!`.\n *\n *   - `Object`: A pattern object can be used to filter specific properties on objects contained\n *     by `array`. For example `{name:\"M\", phone:\"1\"}` predicate will return an array of items\n *     which have property `name` containing \"M\" and property `phone` containing \"1\". A special\n *     property name `$` can be used (as in `{$:\"text\"}`) to accept a match against any\n *     property of the object or its nested object properties. That's equivalent to the simple\n *     substring match with a `string` as described above. The predicate can be negated by prefixing\n *     the string with `!`.\n *     For example `{name: \"!M\"}` predicate will return an array of items which have property `name`\n *     not containing \"M\".\n *\n *     Note that a named property will match properties on the same level only, while the special\n *     `$` property will match properties on the same level or deeper. E.g. an array item like\n *     `{name: {first: 'John', last: 'Doe'}}` will **not** be matched by `{name: 'John'}`, but\n *     **will** be matched by `{$: 'John'}`.\n *\n *   - `function(value, index)`: A predicate function can be used to write arbitrary filters. The\n *     function is called for each element of `array`. The final result is an array of those\n *     elements that the predicate returned true for.\n *\n * @param {function(actual, expected)|true|undefined} comparator Comparator which is used in\n *     determining if the expected value (from the filter expression) and actual value (from\n *     the object in the array) should be considered a match.\n *\n *   Can be one of:\n *\n *   - `function(actual, expected)`:\n *     The function will be given the object value and the predicate value to compare and\n *     should return true if both values should be considered equal.\n *\n *   - `true`: A shorthand for `function(actual, expected) { return angular.equals(actual, expected)}`.\n *     This is essentially strict comparison of expected and actual.\n *\n *   - `false|undefined`: A short hand for a function which will look for a substring match in case\n *     insensitive way.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n       <div ng-init=\"friends = [{name:'John', phone:'555-1276'},\n                                {name:'Mary', phone:'800-BIG-MARY'},\n                                {name:'Mike', phone:'555-4321'},\n                                {name:'Adam', phone:'555-5678'},\n                                {name:'Julie', phone:'555-8765'},\n                                {name:'Juliette', phone:'555-5678'}]\"></div>\n\n       Search: <input ng-model=\"searchText\">\n       <table id=\"searchTextResults\">\n         <tr><th>Name</th><th>Phone</th></tr>\n         <tr ng-repeat=\"friend in friends | filter:searchText\">\n           <td>{{friend.name}}</td>\n           <td>{{friend.phone}}</td>\n         </tr>\n       </table>\n       <hr>\n       Any: <input ng-model=\"search.$\"> <br>\n       Name only <input ng-model=\"search.name\"><br>\n       Phone only <input ng-model=\"search.phone\"><br>\n       Equality <input type=\"checkbox\" ng-model=\"strict\"><br>\n       <table id=\"searchObjResults\">\n         <tr><th>Name</th><th>Phone</th></tr>\n         <tr ng-repeat=\"friendObj in friends | filter:search:strict\">\n           <td>{{friendObj.name}}</td>\n           <td>{{friendObj.phone}}</td>\n         </tr>\n       </table>\n     </file>\n     <file name=\"protractor.js\" type=\"protractor\">\n       var expectFriendNames = function(expectedNames, key) {\n         element.all(by.repeater(key + ' in friends').column(key + '.name')).then(function(arr) {\n           arr.forEach(function(wd, i) {\n             expect(wd.getText()).toMatch(expectedNames[i]);\n           });\n         });\n       };\n\n       it('should search across all fields when filtering with a string', function() {\n         var searchText = element(by.model('searchText'));\n         searchText.clear();\n         searchText.sendKeys('m');\n         expectFriendNames(['Mary', 'Mike', 'Adam'], 'friend');\n\n         searchText.clear();\n         searchText.sendKeys('76');\n         expectFriendNames(['John', 'Julie'], 'friend');\n       });\n\n       it('should search in specific fields when filtering with a predicate object', function() {\n         var searchAny = element(by.model('search.$'));\n         searchAny.clear();\n         searchAny.sendKeys('i');\n         expectFriendNames(['Mary', 'Mike', 'Julie', 'Juliette'], 'friendObj');\n       });\n       it('should use a equal comparison when comparator is true', function() {\n         var searchName = element(by.model('search.name'));\n         var strict = element(by.model('strict'));\n         searchName.clear();\n         searchName.sendKeys('Julie');\n         strict.click();\n         expectFriendNames(['Julie'], 'friendObj');\n       });\n     </file>\n   </example>\n */\nfunction filterFilter() {\n  return function(array, expression, comparator) {\n    if (!isArray(array)) return array;\n\n    var predicateFn;\n    var matchAgainstAnyProp;\n\n    switch (typeof expression) {\n      case 'function':\n        predicateFn = expression;\n        break;\n      case 'boolean':\n      case 'number':\n      case 'string':\n        matchAgainstAnyProp = true;\n        //jshint -W086\n      case 'object':\n        //jshint +W086\n        predicateFn = createPredicateFn(expression, comparator, matchAgainstAnyProp);\n        break;\n      default:\n        return array;\n    }\n\n    return array.filter(predicateFn);\n  };\n}\n\n// Helper functions for `filterFilter`\nfunction createPredicateFn(expression, comparator, matchAgainstAnyProp) {\n  var shouldMatchPrimitives = isObject(expression) && ('$' in expression);\n  var predicateFn;\n\n  if (comparator === true) {\n    comparator = equals;\n  } else if (!isFunction(comparator)) {\n    comparator = function(actual, expected) {\n      if (isObject(actual) || isObject(expected)) {\n        // Prevent an object to be considered equal to a string like `'[object'`\n        return false;\n      }\n\n      actual = lowercase('' + actual);\n      expected = lowercase('' + expected);\n      return actual.indexOf(expected) !== -1;\n    };\n  }\n\n  predicateFn = function(item) {\n    if (shouldMatchPrimitives && !isObject(item)) {\n      return deepCompare(item, expression.$, comparator, false);\n    }\n    return deepCompare(item, expression, comparator, matchAgainstAnyProp);\n  };\n\n  return predicateFn;\n}\n\nfunction deepCompare(actual, expected, comparator, matchAgainstAnyProp, dontMatchWholeObject) {\n  var actualType = typeof actual;\n  var expectedType = typeof expected;\n\n  if ((expectedType === 'string') && (expected.charAt(0) === '!')) {\n    return !deepCompare(actual, expected.substring(1), comparator, matchAgainstAnyProp);\n  } else if (isArray(actual)) {\n    // In case `actual` is an array, consider it a match\n    // if ANY of it's items matches `expected`\n    return actual.some(function(item) {\n      return deepCompare(item, expected, comparator, matchAgainstAnyProp);\n    });\n  }\n\n  switch (actualType) {\n    case 'object':\n      var key;\n      if (matchAgainstAnyProp) {\n        for (key in actual) {\n          if ((key.charAt(0) !== '$') && deepCompare(actual[key], expected, comparator, true)) {\n            return true;\n          }\n        }\n        return dontMatchWholeObject ? false : deepCompare(actual, expected, comparator, false);\n      } else if (expectedType === 'object') {\n        for (key in expected) {\n          var expectedVal = expected[key];\n          if (isFunction(expectedVal)) {\n            continue;\n          }\n\n          var matchAnyProperty = key === '$';\n          var actualVal = matchAnyProperty ? actual : actual[key];\n          if (!deepCompare(actualVal, expectedVal, comparator, matchAnyProperty, matchAnyProperty)) {\n            return false;\n          }\n        }\n        return true;\n      } else {\n        return comparator(actual, expected);\n      }\n      break;\n    case 'function':\n      return false;\n    default:\n      return comparator(actual, expected);\n  }\n}\n\n/**\n * @ngdoc filter\n * @name currency\n * @kind function\n *\n * @description\n * Formats a number as a currency (ie $1,234.56). When no currency symbol is provided, default\n * symbol for current locale is used.\n *\n * @param {number} amount Input to filter.\n * @param {string=} symbol Currency symbol or identifier to be displayed.\n * @param {number=} fractionSize Number of decimal places to round the amount to, defaults to default max fraction size for current locale\n * @returns {string} Formatted number.\n *\n *\n * @example\n   <example module=\"currencyExample\">\n     <file name=\"index.html\">\n       <script>\n         angular.module('currencyExample', [])\n           .controller('ExampleController', ['$scope', function($scope) {\n             $scope.amount = 1234.56;\n           }]);\n       </script>\n       <div ng-controller=\"ExampleController\">\n         <input type=\"number\" ng-model=\"amount\"> <br>\n         default currency symbol ($): <span id=\"currency-default\">{{amount | currency}}</span><br>\n         custom currency identifier (USD$): <span id=\"currency-custom\">{{amount | currency:\"USD$\"}}</span>\n         no fractions (0): <span id=\"currency-no-fractions\">{{amount | currency:\"USD$\":0}}</span>\n       </div>\n     </file>\n     <file name=\"protractor.js\" type=\"protractor\">\n       it('should init with 1234.56', function() {\n         expect(element(by.id('currency-default')).getText()).toBe('$1,234.56');\n         expect(element(by.id('currency-custom')).getText()).toBe('USD$1,234.56');\n         expect(element(by.id('currency-no-fractions')).getText()).toBe('USD$1,235');\n       });\n       it('should update', function() {\n         if (browser.params.browser == 'safari') {\n           // Safari does not understand the minus key. See\n           // https://github.com/angular/protractor/issues/481\n           return;\n         }\n         element(by.model('amount')).clear();\n         element(by.model('amount')).sendKeys('-1234');\n         expect(element(by.id('currency-default')).getText()).toBe('($1,234.00)');\n         expect(element(by.id('currency-custom')).getText()).toBe('(USD$1,234.00)');\n         expect(element(by.id('currency-no-fractions')).getText()).toBe('(USD$1,234)');\n       });\n     </file>\n   </example>\n */\ncurrencyFilter.$inject = ['$locale'];\nfunction currencyFilter($locale) {\n  var formats = $locale.NUMBER_FORMATS;\n  return function(amount, currencySymbol, fractionSize) {\n    if (isUndefined(currencySymbol)) {\n      currencySymbol = formats.CURRENCY_SYM;\n    }\n\n    if (isUndefined(fractionSize)) {\n      fractionSize = formats.PATTERNS[1].maxFrac;\n    }\n\n    // if null or undefined pass it through\n    return (amount == null)\n        ? amount\n        : formatNumber(amount, formats.PATTERNS[1], formats.GROUP_SEP, formats.DECIMAL_SEP, fractionSize).\n            replace(/\\u00A4/g, currencySymbol);\n  };\n}\n\n/**\n * @ngdoc filter\n * @name number\n * @kind function\n *\n * @description\n * Formats a number as text.\n *\n * If the input is not a number an empty string is returned.\n *\n * @param {number|string} number Number to format.\n * @param {(number|string)=} fractionSize Number of decimal places to round the number to.\n * If this is not provided then the fraction size is computed from the current locale's number\n * formatting pattern. In the case of the default locale, it will be 3.\n * @returns {string} Number rounded to decimalPlaces and places a “,” after each third digit.\n *\n * @example\n   <example module=\"numberFilterExample\">\n     <file name=\"index.html\">\n       <script>\n         angular.module('numberFilterExample', [])\n           .controller('ExampleController', ['$scope', function($scope) {\n             $scope.val = 1234.56789;\n           }]);\n       </script>\n       <div ng-controller=\"ExampleController\">\n         Enter number: <input ng-model='val'><br>\n         Default formatting: <span id='number-default'>{{val | number}}</span><br>\n         No fractions: <span>{{val | number:0}}</span><br>\n         Negative number: <span>{{-val | number:4}}</span>\n       </div>\n     </file>\n     <file name=\"protractor.js\" type=\"protractor\">\n       it('should format numbers', function() {\n         expect(element(by.id('number-default')).getText()).toBe('1,234.568');\n         expect(element(by.binding('val | number:0')).getText()).toBe('1,235');\n         expect(element(by.binding('-val | number:4')).getText()).toBe('-1,234.5679');\n       });\n\n       it('should update', function() {\n         element(by.model('val')).clear();\n         element(by.model('val')).sendKeys('3374.333');\n         expect(element(by.id('number-default')).getText()).toBe('3,374.333');\n         expect(element(by.binding('val | number:0')).getText()).toBe('3,374');\n         expect(element(by.binding('-val | number:4')).getText()).toBe('-3,374.3330');\n      });\n     </file>\n   </example>\n */\n\n\nnumberFilter.$inject = ['$locale'];\nfunction numberFilter($locale) {\n  var formats = $locale.NUMBER_FORMATS;\n  return function(number, fractionSize) {\n\n    // if null or undefined pass it through\n    return (number == null)\n        ? number\n        : formatNumber(number, formats.PATTERNS[0], formats.GROUP_SEP, formats.DECIMAL_SEP,\n                       fractionSize);\n  };\n}\n\nvar DECIMAL_SEP = '.';\nfunction formatNumber(number, pattern, groupSep, decimalSep, fractionSize) {\n  if (!isFinite(number) || isObject(number)) return '';\n\n  var isNegative = number < 0;\n  number = Math.abs(number);\n  var numStr = number + '',\n      formatedText = '',\n      parts = [];\n\n  var hasExponent = false;\n  if (numStr.indexOf('e') !== -1) {\n    var match = numStr.match(/([\\d\\.]+)e(-?)(\\d+)/);\n    if (match && match[2] == '-' && match[3] > fractionSize + 1) {\n      number = 0;\n    } else {\n      formatedText = numStr;\n      hasExponent = true;\n    }\n  }\n\n  if (!hasExponent) {\n    var fractionLen = (numStr.split(DECIMAL_SEP)[1] || '').length;\n\n    // determine fractionSize if it is not specified\n    if (isUndefined(fractionSize)) {\n      fractionSize = Math.min(Math.max(pattern.minFrac, fractionLen), pattern.maxFrac);\n    }\n\n    // safely round numbers in JS without hitting imprecisions of floating-point arithmetics\n    // inspired by:\n    // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/round\n    number = +(Math.round(+(number.toString() + 'e' + fractionSize)).toString() + 'e' + -fractionSize);\n\n    var fraction = ('' + number).split(DECIMAL_SEP);\n    var whole = fraction[0];\n    fraction = fraction[1] || '';\n\n    var i, pos = 0,\n        lgroup = pattern.lgSize,\n        group = pattern.gSize;\n\n    if (whole.length >= (lgroup + group)) {\n      pos = whole.length - lgroup;\n      for (i = 0; i < pos; i++) {\n        if ((pos - i) % group === 0 && i !== 0) {\n          formatedText += groupSep;\n        }\n        formatedText += whole.charAt(i);\n      }\n    }\n\n    for (i = pos; i < whole.length; i++) {\n      if ((whole.length - i) % lgroup === 0 && i !== 0) {\n        formatedText += groupSep;\n      }\n      formatedText += whole.charAt(i);\n    }\n\n    // format fraction part.\n    while (fraction.length < fractionSize) {\n      fraction += '0';\n    }\n\n    if (fractionSize && fractionSize !== \"0\") formatedText += decimalSep + fraction.substr(0, fractionSize);\n  } else {\n    if (fractionSize > 0 && number < 1) {\n      formatedText = number.toFixed(fractionSize);\n      number = parseFloat(formatedText);\n    }\n  }\n\n  if (number === 0) {\n    isNegative = false;\n  }\n\n  parts.push(isNegative ? pattern.negPre : pattern.posPre,\n             formatedText,\n             isNegative ? pattern.negSuf : pattern.posSuf);\n  return parts.join('');\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\nfunction dateGetter(name, size, offset, trim) {\n  offset = offset || 0;\n  return function(date) {\n    var value = date['get' + name]();\n    if (offset > 0 || value > -offset)\n      value += offset;\n    if (value === 0 && offset == -12) value = 12;\n    return padNumber(value, size, trim);\n  };\n}\n\nfunction dateStrGetter(name, shortForm) {\n  return function(date, formats) {\n    var value = date['get' + name]();\n    var get = uppercase(shortForm ? ('SHORT' + name) : name);\n\n    return formats[get][value];\n  };\n}\n\nfunction timeZoneGetter(date) {\n  var zone = -1 * date.getTimezoneOffset();\n  var paddedZone = (zone >= 0) ? \"+\" : \"\";\n\n  paddedZone += padNumber(Math[zone > 0 ? 'floor' : 'ceil'](zone / 60), 2) +\n                padNumber(Math.abs(zone % 60), 2);\n\n  return paddedZone;\n}\n\nfunction getFirstThursdayOfYear(year) {\n    // 0 = index of January\n    var dayOfWeekOnFirst = (new Date(year, 0, 1)).getDay();\n    // 4 = index of Thursday (+1 to account for 1st = 5)\n    // 11 = index of *next* Thursday (+1 account for 1st = 12)\n    return new Date(year, 0, ((dayOfWeekOnFirst <= 4) ? 5 : 12) - dayOfWeekOnFirst);\n}\n\nfunction getThursdayThisWeek(datetime) {\n    return new Date(datetime.getFullYear(), datetime.getMonth(),\n      // 4 = index of Thursday\n      datetime.getDate() + (4 - datetime.getDay()));\n}\n\nfunction weekGetter(size) {\n   return function(date) {\n      var firstThurs = getFirstThursdayOfYear(date.getFullYear()),\n         thisThurs = getThursdayThisWeek(date);\n\n      var diff = +thisThurs - +firstThurs,\n         result = 1 + Math.round(diff / 6.048e8); // 6.048e8 ms per week\n\n      return padNumber(result, size);\n   };\n}\n\nfunction ampmGetter(date, formats) {\n  return date.getHours() < 12 ? formats.AMPMS[0] : formats.AMPMS[1];\n}\n\nvar DATE_FORMATS = {\n  yyyy: dateGetter('FullYear', 4),\n    yy: dateGetter('FullYear', 2, 0, true),\n     y: dateGetter('FullYear', 1),\n  MMMM: dateStrGetter('Month'),\n   MMM: dateStrGetter('Month', true),\n    MM: dateGetter('Month', 2, 1),\n     M: dateGetter('Month', 1, 1),\n    dd: dateGetter('Date', 2),\n     d: dateGetter('Date', 1),\n    HH: dateGetter('Hours', 2),\n     H: dateGetter('Hours', 1),\n    hh: dateGetter('Hours', 2, -12),\n     h: dateGetter('Hours', 1, -12),\n    mm: dateGetter('Minutes', 2),\n     m: dateGetter('Minutes', 1),\n    ss: dateGetter('Seconds', 2),\n     s: dateGetter('Seconds', 1),\n     // while ISO 8601 requires fractions to be prefixed with `.` or `,`\n     // we can be just safely rely on using `sss` since we currently don't support single or two digit fractions\n   sss: dateGetter('Milliseconds', 3),\n  EEEE: dateStrGetter('Day'),\n   EEE: dateStrGetter('Day', true),\n     a: ampmGetter,\n     Z: timeZoneGetter,\n    ww: weekGetter(2),\n     w: weekGetter(1)\n};\n\nvar DATE_FORMATS_SPLIT = /((?:[^yMdHhmsaZEw']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+|H+|h+|m+|s+|a|Z|w+))(.*)/,\n    NUMBER_STRING = /^\\-?\\d+$/;\n\n/**\n * @ngdoc filter\n * @name date\n * @kind function\n *\n * @description\n *   Formats `date` to a string based on the requested `format`.\n *\n *   `format` string can be composed of the following elements:\n *\n *   * `'yyyy'`: 4 digit representation of year (e.g. AD 1 => 0001, AD 2010 => 2010)\n *   * `'yy'`: 2 digit representation of year, padded (00-99). (e.g. AD 2001 => 01, AD 2010 => 10)\n *   * `'y'`: 1 digit representation of year, e.g. (AD 1 => 1, AD 199 => 199)\n *   * `'MMMM'`: Month in year (January-December)\n *   * `'MMM'`: Month in year (Jan-Dec)\n *   * `'MM'`: Month in year, padded (01-12)\n *   * `'M'`: Month in year (1-12)\n *   * `'dd'`: Day in month, padded (01-31)\n *   * `'d'`: Day in month (1-31)\n *   * `'EEEE'`: Day in Week,(Sunday-Saturday)\n *   * `'EEE'`: Day in Week, (Sun-Sat)\n *   * `'HH'`: Hour in day, padded (00-23)\n *   * `'H'`: Hour in day (0-23)\n *   * `'hh'`: Hour in AM/PM, padded (01-12)\n *   * `'h'`: Hour in AM/PM, (1-12)\n *   * `'mm'`: Minute in hour, padded (00-59)\n *   * `'m'`: Minute in hour (0-59)\n *   * `'ss'`: Second in minute, padded (00-59)\n *   * `'s'`: Second in minute (0-59)\n *   * `'sss'`: Millisecond in second, padded (000-999)\n *   * `'a'`: AM/PM marker\n *   * `'Z'`: 4 digit (+sign) representation of the timezone offset (-1200-+1200)\n *   * `'ww'`: Week of year, padded (00-53). Week 01 is the week with the first Thursday of the year\n *   * `'w'`: Week of year (0-53). Week 1 is the week with the first Thursday of the year\n *\n *   `format` string can also be one of the following predefined\n *   {@link guide/i18n localizable formats}:\n *\n *   * `'medium'`: equivalent to `'MMM d, y h:mm:ss a'` for en_US locale\n *     (e.g. Sep 3, 2010 12:05:08 PM)\n *   * `'short'`: equivalent to `'M/d/yy h:mm a'` for en_US  locale (e.g. 9/3/10 12:05 PM)\n *   * `'fullDate'`: equivalent to `'EEEE, MMMM d, y'` for en_US  locale\n *     (e.g. Friday, September 3, 2010)\n *   * `'longDate'`: equivalent to `'MMMM d, y'` for en_US  locale (e.g. September 3, 2010)\n *   * `'mediumDate'`: equivalent to `'MMM d, y'` for en_US  locale (e.g. Sep 3, 2010)\n *   * `'shortDate'`: equivalent to `'M/d/yy'` for en_US locale (e.g. 9/3/10)\n *   * `'mediumTime'`: equivalent to `'h:mm:ss a'` for en_US locale (e.g. 12:05:08 PM)\n *   * `'shortTime'`: equivalent to `'h:mm a'` for en_US locale (e.g. 12:05 PM)\n *\n *   `format` string can contain literal values. These need to be escaped by surrounding with single quotes (e.g.\n *   `\"h 'in the morning'\"`). In order to output a single quote, escape it - i.e., two single quotes in a sequence\n *   (e.g. `\"h 'o''clock'\"`).\n *\n * @param {(Date|number|string)} date Date to format either as Date object, milliseconds (string or\n *    number) or various ISO 8601 datetime string formats (e.g. yyyy-MM-ddTHH:mm:ss.sssZ and its\n *    shorter versions like yyyy-MM-ddTHH:mmZ, yyyy-MM-dd or yyyyMMddTHHmmssZ). If no timezone is\n *    specified in the string input, the time is considered to be in the local timezone.\n * @param {string=} format Formatting rules (see Description). If not specified,\n *    `mediumDate` is used.\n * @param {string=} timezone Timezone to be used for formatting. Right now, only `'UTC'` is supported.\n *    If not specified, the timezone of the browser will be used.\n * @returns {string} Formatted string or the input if input is not recognized as date/millis.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n       <span ng-non-bindable>{{1288323623006 | date:'medium'}}</span>:\n           <span>{{1288323623006 | date:'medium'}}</span><br>\n       <span ng-non-bindable>{{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}</span>:\n          <span>{{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}</span><br>\n       <span ng-non-bindable>{{1288323623006 | date:'MM/dd/yyyy @ h:mma'}}</span>:\n          <span>{{'1288323623006' | date:'MM/dd/yyyy @ h:mma'}}</span><br>\n       <span ng-non-bindable>{{1288323623006 | date:\"MM/dd/yyyy 'at' h:mma\"}}</span>:\n          <span>{{'1288323623006' | date:\"MM/dd/yyyy 'at' h:mma\"}}</span><br>\n     </file>\n     <file name=\"protractor.js\" type=\"protractor\">\n       it('should format date', function() {\n         expect(element(by.binding(\"1288323623006 | date:'medium'\")).getText()).\n            toMatch(/Oct 2\\d, 2010 \\d{1,2}:\\d{2}:\\d{2} (AM|PM)/);\n         expect(element(by.binding(\"1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'\")).getText()).\n            toMatch(/2010\\-10\\-2\\d \\d{2}:\\d{2}:\\d{2} (\\-|\\+)?\\d{4}/);\n         expect(element(by.binding(\"'1288323623006' | date:'MM/dd/yyyy @ h:mma'\")).getText()).\n            toMatch(/10\\/2\\d\\/2010 @ \\d{1,2}:\\d{2}(AM|PM)/);\n         expect(element(by.binding(\"'1288323623006' | date:\\\"MM/dd/yyyy 'at' h:mma\\\"\")).getText()).\n            toMatch(/10\\/2\\d\\/2010 at \\d{1,2}:\\d{2}(AM|PM)/);\n       });\n     </file>\n   </example>\n */\ndateFilter.$inject = ['$locale'];\nfunction dateFilter($locale) {\n\n\n  var R_ISO8601_STR = /^(\\d{4})-?(\\d\\d)-?(\\d\\d)(?:T(\\d\\d)(?::?(\\d\\d)(?::?(\\d\\d)(?:\\.(\\d+))?)?)?(Z|([+-])(\\d\\d):?(\\d\\d))?)?$/;\n                     // 1        2       3         4          5          6          7          8  9     10      11\n  function jsonStringToDate(string) {\n    var match;\n    if (match = string.match(R_ISO8601_STR)) {\n      var date = new Date(0),\n          tzHour = 0,\n          tzMin  = 0,\n          dateSetter = match[8] ? date.setUTCFullYear : date.setFullYear,\n          timeSetter = match[8] ? date.setUTCHours : date.setHours;\n\n      if (match[9]) {\n        tzHour = int(match[9] + match[10]);\n        tzMin = int(match[9] + match[11]);\n      }\n      dateSetter.call(date, int(match[1]), int(match[2]) - 1, int(match[3]));\n      var h = int(match[4] || 0) - tzHour;\n      var m = int(match[5] || 0) - tzMin;\n      var s = int(match[6] || 0);\n      var ms = Math.round(parseFloat('0.' + (match[7] || 0)) * 1000);\n      timeSetter.call(date, h, m, s, ms);\n      return date;\n    }\n    return string;\n  }\n\n\n  return function(date, format, timezone) {\n    var text = '',\n        parts = [],\n        fn, match;\n\n    format = format || 'mediumDate';\n    format = $locale.DATETIME_FORMATS[format] || format;\n    if (isString(date)) {\n      date = NUMBER_STRING.test(date) ? int(date) : jsonStringToDate(date);\n    }\n\n    if (isNumber(date)) {\n      date = new Date(date);\n    }\n\n    if (!isDate(date)) {\n      return date;\n    }\n\n    while (format) {\n      match = DATE_FORMATS_SPLIT.exec(format);\n      if (match) {\n        parts = concat(parts, match, 1);\n        format = parts.pop();\n      } else {\n        parts.push(format);\n        format = null;\n      }\n    }\n\n    if (timezone && timezone === 'UTC') {\n      date = new Date(date.getTime());\n      date.setMinutes(date.getMinutes() + date.getTimezoneOffset());\n    }\n    forEach(parts, function(value) {\n      fn = DATE_FORMATS[value];\n      text += fn ? fn(date, $locale.DATETIME_FORMATS)\n                 : value.replace(/(^'|'$)/g, '').replace(/''/g, \"'\");\n    });\n\n    return text;\n  };\n}\n\n\n/**\n * @ngdoc filter\n * @name json\n * @kind function\n *\n * @description\n *   Allows you to convert a JavaScript object into JSON string.\n *\n *   This filter is mostly useful for debugging. When using the double curly {{value}} notation\n *   the binding is automatically converted to JSON.\n *\n * @param {*} object Any JavaScript object (including arrays and primitive types) to filter.\n * @param {number=} spacing The number of spaces to use per indentation, defaults to 2.\n * @returns {string} JSON string.\n *\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n       <pre id=\"default-spacing\">{{ {'name':'value'} | json }}</pre>\n       <pre id=\"custom-spacing\">{{ {'name':'value'} | json:4 }}</pre>\n     </file>\n     <file name=\"protractor.js\" type=\"protractor\">\n       it('should jsonify filtered objects', function() {\n         expect(element(by.id('default-spacing')).getText()).toMatch(/\\{\\n  \"name\": ?\"value\"\\n}/);\n         expect(element(by.id('custom-spacing')).getText()).toMatch(/\\{\\n    \"name\": ?\"value\"\\n}/);\n       });\n     </file>\n   </example>\n *\n */\nfunction jsonFilter() {\n  return function(object, spacing) {\n    if (isUndefined(spacing)) {\n        spacing = 2;\n    }\n    return toJson(object, spacing);\n  };\n}\n\n\n/**\n * @ngdoc filter\n * @name lowercase\n * @kind function\n * @description\n * Converts string to lowercase.\n * @see angular.lowercase\n */\nvar lowercaseFilter = valueFn(lowercase);\n\n\n/**\n * @ngdoc filter\n * @name uppercase\n * @kind function\n * @description\n * Converts string to uppercase.\n * @see angular.uppercase\n */\nvar uppercaseFilter = valueFn(uppercase);\n\n/**\n * @ngdoc filter\n * @name limitTo\n * @kind function\n *\n * @description\n * Creates a new array or string containing only a specified number of elements. The elements\n * are taken from either the beginning or the end of the source array, string or number, as specified by\n * the value and sign (positive or negative) of `limit`. If a number is used as input, it is\n * converted to a string.\n *\n * @param {Array|string|number} input Source array, string or number to be limited.\n * @param {string|number} limit The length of the returned array or string. If the `limit` number\n *     is positive, `limit` number of items from the beginning of the source array/string are copied.\n *     If the number is negative, `limit` number  of items from the end of the source array/string\n *     are copied. The `limit` will be trimmed if it exceeds `array.length`\n * @returns {Array|string} A new sub-array or substring of length `limit` or less if input array\n *     had less than `limit` elements.\n *\n * @example\n   <example module=\"limitToExample\">\n     <file name=\"index.html\">\n       <script>\n         angular.module('limitToExample', [])\n           .controller('ExampleController', ['$scope', function($scope) {\n             $scope.numbers = [1,2,3,4,5,6,7,8,9];\n             $scope.letters = \"abcdefghi\";\n             $scope.longNumber = 2345432342;\n             $scope.numLimit = 3;\n             $scope.letterLimit = 3;\n             $scope.longNumberLimit = 3;\n           }]);\n       </script>\n       <div ng-controller=\"ExampleController\">\n         Limit {{numbers}} to: <input type=\"number\" step=\"1\" ng-model=\"numLimit\">\n         <p>Output numbers: {{ numbers | limitTo:numLimit }}</p>\n         Limit {{letters}} to: <input type=\"number\" step=\"1\" ng-model=\"letterLimit\">\n         <p>Output letters: {{ letters | limitTo:letterLimit }}</p>\n         Limit {{longNumber}} to: <input type=\"number\" step=\"1\" ng-model=\"longNumberLimit\">\n         <p>Output long number: {{ longNumber | limitTo:longNumberLimit }}</p>\n       </div>\n     </file>\n     <file name=\"protractor.js\" type=\"protractor\">\n       var numLimitInput = element(by.model('numLimit'));\n       var letterLimitInput = element(by.model('letterLimit'));\n       var longNumberLimitInput = element(by.model('longNumberLimit'));\n       var limitedNumbers = element(by.binding('numbers | limitTo:numLimit'));\n       var limitedLetters = element(by.binding('letters | limitTo:letterLimit'));\n       var limitedLongNumber = element(by.binding('longNumber | limitTo:longNumberLimit'));\n\n       it('should limit the number array to first three items', function() {\n         expect(numLimitInput.getAttribute('value')).toBe('3');\n         expect(letterLimitInput.getAttribute('value')).toBe('3');\n         expect(longNumberLimitInput.getAttribute('value')).toBe('3');\n         expect(limitedNumbers.getText()).toEqual('Output numbers: [1,2,3]');\n         expect(limitedLetters.getText()).toEqual('Output letters: abc');\n         expect(limitedLongNumber.getText()).toEqual('Output long number: 234');\n       });\n\n       // There is a bug in safari and protractor that doesn't like the minus key\n       // it('should update the output when -3 is entered', function() {\n       //   numLimitInput.clear();\n       //   numLimitInput.sendKeys('-3');\n       //   letterLimitInput.clear();\n       //   letterLimitInput.sendKeys('-3');\n       //   longNumberLimitInput.clear();\n       //   longNumberLimitInput.sendKeys('-3');\n       //   expect(limitedNumbers.getText()).toEqual('Output numbers: [7,8,9]');\n       //   expect(limitedLetters.getText()).toEqual('Output letters: ghi');\n       //   expect(limitedLongNumber.getText()).toEqual('Output long number: 342');\n       // });\n\n       it('should not exceed the maximum size of input array', function() {\n         numLimitInput.clear();\n         numLimitInput.sendKeys('100');\n         letterLimitInput.clear();\n         letterLimitInput.sendKeys('100');\n         longNumberLimitInput.clear();\n         longNumberLimitInput.sendKeys('100');\n         expect(limitedNumbers.getText()).toEqual('Output numbers: [1,2,3,4,5,6,7,8,9]');\n         expect(limitedLetters.getText()).toEqual('Output letters: abcdefghi');\n         expect(limitedLongNumber.getText()).toEqual('Output long number: 2345432342');\n       });\n     </file>\n   </example>\n*/\nfunction limitToFilter() {\n  return function(input, limit) {\n    if (isNumber(input)) input = input.toString();\n    if (!isArray(input) && !isString(input)) return input;\n\n    if (Math.abs(Number(limit)) === Infinity) {\n      limit = Number(limit);\n    } else {\n      limit = int(limit);\n    }\n\n    //NaN check on limit\n    if (limit) {\n      return limit > 0 ? input.slice(0, limit) : input.slice(limit);\n    } else {\n      return isString(input) ? \"\" : [];\n    }\n  };\n}\n\n/**\n * @ngdoc filter\n * @name orderBy\n * @kind function\n *\n * @description\n * Orders a specified `array` by the `expression` predicate. It is ordered alphabetically\n * for strings and numerically for numbers. Note: if you notice numbers are not being sorted\n * correctly, make sure they are actually being saved as numbers and not strings.\n *\n * @param {Array} array The array to sort.\n * @param {function(*)|string|Array.<(function(*)|string)>=} expression A predicate to be\n *    used by the comparator to determine the order of elements.\n *\n *    Can be one of:\n *\n *    - `function`: Getter function. The result of this function will be sorted using the\n *      `<`, `=`, `>` operator.\n *    - `string`: An Angular expression. The result of this expression is used to compare elements\n *      (for example `name` to sort by a property called `name` or `name.substr(0, 3)` to sort by\n *      3 first characters of a property called `name`). The result of a constant expression\n *      is interpreted as a property name to be used in comparisons (for example `\"special name\"`\n *      to sort object by the value of their `special name` property). An expression can be\n *      optionally prefixed with `+` or `-` to control ascending or descending sort order\n *      (for example, `+name` or `-name`). If no property is provided, (e.g. `'+'`) then the array\n *      element itself is used to compare where sorting.\n *    - `Array`: An array of function or string predicates. The first predicate in the array\n *      is used for sorting, but when two items are equivalent, the next predicate is used.\n *\n *    If the predicate is missing or empty then it defaults to `'+'`.\n *\n * @param {boolean=} reverse Reverse the order of the array.\n * @returns {Array} Sorted copy of the source array.\n *\n * @example\n   <example module=\"orderByExample\">\n     <file name=\"index.html\">\n       <script>\n         angular.module('orderByExample', [])\n           .controller('ExampleController', ['$scope', function($scope) {\n             $scope.friends =\n                 [{name:'John', phone:'555-1212', age:10},\n                  {name:'Mary', phone:'555-9876', age:19},\n                  {name:'Mike', phone:'555-4321', age:21},\n                  {name:'Adam', phone:'555-5678', age:35},\n                  {name:'Julie', phone:'555-8765', age:29}];\n             $scope.predicate = '-age';\n           }]);\n       </script>\n       <div ng-controller=\"ExampleController\">\n         <pre>Sorting predicate = {{predicate}}; reverse = {{reverse}}</pre>\n         <hr/>\n         [ <a href=\"\" ng-click=\"predicate=''\">unsorted</a> ]\n         <table class=\"friend\">\n           <tr>\n             <th><a href=\"\" ng-click=\"predicate = 'name'; reverse=false\">Name</a>\n                 (<a href=\"\" ng-click=\"predicate = '-name'; reverse=false\">^</a>)</th>\n             <th><a href=\"\" ng-click=\"predicate = 'phone'; reverse=!reverse\">Phone Number</a></th>\n             <th><a href=\"\" ng-click=\"predicate = 'age'; reverse=!reverse\">Age</a></th>\n           </tr>\n           <tr ng-repeat=\"friend in friends | orderBy:predicate:reverse\">\n             <td>{{friend.name}}</td>\n             <td>{{friend.phone}}</td>\n             <td>{{friend.age}}</td>\n           </tr>\n         </table>\n       </div>\n     </file>\n   </example>\n *\n * It's also possible to call the orderBy filter manually, by injecting `$filter`, retrieving the\n * filter routine with `$filter('orderBy')`, and calling the returned filter routine with the\n * desired parameters.\n *\n * Example:\n *\n * @example\n  <example module=\"orderByExample\">\n    <file name=\"index.html\">\n      <div ng-controller=\"ExampleController\">\n        <table class=\"friend\">\n          <tr>\n            <th><a href=\"\" ng-click=\"reverse=false;order('name', false)\">Name</a>\n              (<a href=\"\" ng-click=\"order('-name',false)\">^</a>)</th>\n            <th><a href=\"\" ng-click=\"reverse=!reverse;order('phone', reverse)\">Phone Number</a></th>\n            <th><a href=\"\" ng-click=\"reverse=!reverse;order('age',reverse)\">Age</a></th>\n          </tr>\n          <tr ng-repeat=\"friend in friends\">\n            <td>{{friend.name}}</td>\n            <td>{{friend.phone}}</td>\n            <td>{{friend.age}}</td>\n          </tr>\n        </table>\n      </div>\n    </file>\n\n    <file name=\"script.js\">\n      angular.module('orderByExample', [])\n        .controller('ExampleController', ['$scope', '$filter', function($scope, $filter) {\n          var orderBy = $filter('orderBy');\n          $scope.friends = [\n            { name: 'John',    phone: '555-1212',    age: 10 },\n            { name: 'Mary',    phone: '555-9876',    age: 19 },\n            { name: 'Mike',    phone: '555-4321',    age: 21 },\n            { name: 'Adam',    phone: '555-5678',    age: 35 },\n            { name: 'Julie',   phone: '555-8765',    age: 29 }\n          ];\n          $scope.order = function(predicate, reverse) {\n            $scope.friends = orderBy($scope.friends, predicate, reverse);\n          };\n          $scope.order('-age',false);\n        }]);\n    </file>\n</example>\n */\norderByFilter.$inject = ['$parse'];\nfunction orderByFilter($parse) {\n  return function(array, sortPredicate, reverseOrder) {\n    if (!(isArrayLike(array))) return array;\n    sortPredicate = isArray(sortPredicate) ? sortPredicate : [sortPredicate];\n    if (sortPredicate.length === 0) { sortPredicate = ['+']; }\n    sortPredicate = sortPredicate.map(function(predicate) {\n      var descending = false, get = predicate || identity;\n      if (isString(predicate)) {\n        if ((predicate.charAt(0) == '+' || predicate.charAt(0) == '-')) {\n          descending = predicate.charAt(0) == '-';\n          predicate = predicate.substring(1);\n        }\n        if (predicate === '') {\n          // Effectively no predicate was passed so we compare identity\n          return reverseComparator(compare, descending);\n        }\n        get = $parse(predicate);\n        if (get.constant) {\n          var key = get();\n          return reverseComparator(function(a, b) {\n            return compare(a[key], b[key]);\n          }, descending);\n        }\n      }\n      return reverseComparator(function(a, b) {\n        return compare(get(a),get(b));\n      }, descending);\n    });\n    return slice.call(array).sort(reverseComparator(comparator, reverseOrder));\n\n    function comparator(o1, o2) {\n      for (var i = 0; i < sortPredicate.length; i++) {\n        var comp = sortPredicate[i](o1, o2);\n        if (comp !== 0) return comp;\n      }\n      return 0;\n    }\n    function reverseComparator(comp, descending) {\n      return descending\n          ? function(a, b) {return comp(b,a);}\n          : comp;\n    }\n\n    function isPrimitive(value) {\n      switch (typeof value) {\n        case 'number': /* falls through */\n        case 'boolean': /* falls through */\n        case 'string':\n          return true;\n        default:\n          return false;\n      }\n    }\n\n    function objectToString(value) {\n      if (value === null) return 'null';\n      if (typeof value.valueOf === 'function') {\n        value = value.valueOf();\n        if (isPrimitive(value)) return value;\n      }\n      if (typeof value.toString === 'function') {\n        value = value.toString();\n        if (isPrimitive(value)) return value;\n      }\n      return '';\n    }\n\n    function compare(v1, v2) {\n      var t1 = typeof v1;\n      var t2 = typeof v2;\n      if (t1 === t2 && t1 === \"object\") {\n        v1 = objectToString(v1);\n        v2 = objectToString(v2);\n      }\n      if (t1 === t2) {\n        if (t1 === \"string\") {\n           v1 = v1.toLowerCase();\n           v2 = v2.toLowerCase();\n        }\n        if (v1 === v2) return 0;\n        return v1 < v2 ? -1 : 1;\n      } else {\n        return t1 < t2 ? -1 : 1;\n      }\n    }\n  };\n}\n\nfunction ngDirective(directive) {\n  if (isFunction(directive)) {\n    directive = {\n      link: directive\n    };\n  }\n  directive.restrict = directive.restrict || 'AC';\n  return valueFn(directive);\n}\n\n/**\n * @ngdoc directive\n * @name a\n * @restrict E\n *\n * @description\n * Modifies the default behavior of the html A tag so that the default action is prevented when\n * the href attribute is empty.\n *\n * This change permits the easy creation of action links with the `ngClick` directive\n * without changing the location or causing page reloads, e.g.:\n * `<a href=\"\" ng-click=\"list.addItem()\">Add Item</a>`\n */\nvar htmlAnchorDirective = valueFn({\n  restrict: 'E',\n  compile: function(element, attr) {\n    if (!attr.href && !attr.xlinkHref && !attr.name) {\n      return function(scope, element) {\n        // If the linked element is not an anchor tag anymore, do nothing\n        if (element[0].nodeName.toLowerCase() !== 'a') return;\n\n        // SVGAElement does not use the href attribute, but rather the 'xlinkHref' attribute.\n        var href = toString.call(element.prop('href')) === '[object SVGAnimatedString]' ?\n                   'xlink:href' : 'href';\n        element.on('click', function(event) {\n          // if we have no href url, then don't navigate anywhere.\n          if (!element.attr(href)) {\n            event.preventDefault();\n          }\n        });\n      };\n    }\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ngHref\n * @restrict A\n * @priority 99\n *\n * @description\n * Using Angular markup like `{{hash}}` in an href attribute will\n * make the link go to the wrong URL if the user clicks it before\n * Angular has a chance to replace the `{{hash}}` markup with its\n * value. Until Angular replaces the markup the link will be broken\n * and will most likely return a 404 error. The `ngHref` directive\n * solves this problem.\n *\n * The wrong way to write it:\n * ```html\n * <a href=\"http://www.gravatar.com/avatar/{{hash}}\">link1</a>\n * ```\n *\n * The correct way to write it:\n * ```html\n * <a ng-href=\"http://www.gravatar.com/avatar/{{hash}}\">link1</a>\n * ```\n *\n * @element A\n * @param {template} ngHref any string which can contain `{{}}` markup.\n *\n * @example\n * This example shows various combinations of `href`, `ng-href` and `ng-click` attributes\n * in links and their different behaviors:\n    <example>\n      <file name=\"index.html\">\n        <input ng-model=\"value\" /><br />\n        <a id=\"link-1\" href ng-click=\"value = 1\">link 1</a> (link, don't reload)<br />\n        <a id=\"link-2\" href=\"\" ng-click=\"value = 2\">link 2</a> (link, don't reload)<br />\n        <a id=\"link-3\" ng-href=\"/{{'123'}}\">link 3</a> (link, reload!)<br />\n        <a id=\"link-4\" href=\"\" name=\"xx\" ng-click=\"value = 4\">anchor</a> (link, don't reload)<br />\n        <a id=\"link-5\" name=\"xxx\" ng-click=\"value = 5\">anchor</a> (no link)<br />\n        <a id=\"link-6\" ng-href=\"{{value}}\">link</a> (link, change location)\n      </file>\n      <file name=\"protractor.js\" type=\"protractor\">\n        it('should execute ng-click but not reload when href without value', function() {\n          element(by.id('link-1')).click();\n          expect(element(by.model('value')).getAttribute('value')).toEqual('1');\n          expect(element(by.id('link-1')).getAttribute('href')).toBe('');\n        });\n\n        it('should execute ng-click but not reload when href empty string', function() {\n          element(by.id('link-2')).click();\n          expect(element(by.model('value')).getAttribute('value')).toEqual('2');\n          expect(element(by.id('link-2')).getAttribute('href')).toBe('');\n        });\n\n        it('should execute ng-click and change url when ng-href specified', function() {\n          expect(element(by.id('link-3')).getAttribute('href')).toMatch(/\\/123$/);\n\n          element(by.id('link-3')).click();\n\n          // At this point, we navigate away from an Angular page, so we need\n          // to use browser.driver to get the base webdriver.\n\n          browser.wait(function() {\n            return browser.driver.getCurrentUrl().then(function(url) {\n              return url.match(/\\/123$/);\n            });\n          }, 5000, 'page should navigate to /123');\n        });\n\n        xit('should execute ng-click but not reload when href empty string and name specified', function() {\n          element(by.id('link-4')).click();\n          expect(element(by.model('value')).getAttribute('value')).toEqual('4');\n          expect(element(by.id('link-4')).getAttribute('href')).toBe('');\n        });\n\n        it('should execute ng-click but not reload when no href but name specified', function() {\n          element(by.id('link-5')).click();\n          expect(element(by.model('value')).getAttribute('value')).toEqual('5');\n          expect(element(by.id('link-5')).getAttribute('href')).toBe(null);\n        });\n\n        it('should only change url when only ng-href', function() {\n          element(by.model('value')).clear();\n          element(by.model('value')).sendKeys('6');\n          expect(element(by.id('link-6')).getAttribute('href')).toMatch(/\\/6$/);\n\n          element(by.id('link-6')).click();\n\n          // At this point, we navigate away from an Angular page, so we need\n          // to use browser.driver to get the base webdriver.\n          browser.wait(function() {\n            return browser.driver.getCurrentUrl().then(function(url) {\n              return url.match(/\\/6$/);\n            });\n          }, 5000, 'page should navigate to /6');\n        });\n      </file>\n    </example>\n */\n\n/**\n * @ngdoc directive\n * @name ngSrc\n * @restrict A\n * @priority 99\n *\n * @description\n * Using Angular markup like `{{hash}}` in a `src` attribute doesn't\n * work right: The browser will fetch from the URL with the literal\n * text `{{hash}}` until Angular replaces the expression inside\n * `{{hash}}`. The `ngSrc` directive solves this problem.\n *\n * The buggy way to write it:\n * ```html\n * <img src=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * ```\n *\n * The correct way to write it:\n * ```html\n * <img ng-src=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * ```\n *\n * @element IMG\n * @param {template} ngSrc any string which can contain `{{}}` markup.\n */\n\n/**\n * @ngdoc directive\n * @name ngSrcset\n * @restrict A\n * @priority 99\n *\n * @description\n * Using Angular markup like `{{hash}}` in a `srcset` attribute doesn't\n * work right: The browser will fetch from the URL with the literal\n * text `{{hash}}` until Angular replaces the expression inside\n * `{{hash}}`. The `ngSrcset` directive solves this problem.\n *\n * The buggy way to write it:\n * ```html\n * <img srcset=\"http://www.gravatar.com/avatar/{{hash}} 2x\"/>\n * ```\n *\n * The correct way to write it:\n * ```html\n * <img ng-srcset=\"http://www.gravatar.com/avatar/{{hash}} 2x\"/>\n * ```\n *\n * @element IMG\n * @param {template} ngSrcset any string which can contain `{{}}` markup.\n */\n\n/**\n * @ngdoc directive\n * @name ngDisabled\n * @restrict A\n * @priority 100\n *\n * @description\n *\n * We shouldn't do this, because it will make the button enabled on Chrome/Firefox but not on IE8 and older IEs:\n * ```html\n * <div ng-init=\"scope = { isDisabled: false }\">\n *  <button disabled=\"{{scope.isDisabled}}\">Disabled</button>\n * </div>\n * ```\n *\n * The HTML specification does not require browsers to preserve the values of boolean attributes\n * such as disabled. (Their presence means true and their absence means false.)\n * If we put an Angular interpolation expression into such an attribute then the\n * binding information would be lost when the browser removes the attribute.\n * The `ngDisabled` directive solves this problem for the `disabled` attribute.\n * This complementary directive is not removed by the browser and so provides\n * a permanent reliable place to store the binding information.\n *\n * @example\n    <example>\n      <file name=\"index.html\">\n        Click me to toggle: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        <button ng-model=\"button\" ng-disabled=\"checked\">Button</button>\n      </file>\n      <file name=\"protractor.js\" type=\"protractor\">\n        it('should toggle button', function() {\n          expect(element(by.css('button')).getAttribute('disabled')).toBeFalsy();\n          element(by.model('checked')).click();\n          expect(element(by.css('button')).getAttribute('disabled')).toBeTruthy();\n        });\n      </file>\n    </example>\n *\n * @element INPUT\n * @param {expression} ngDisabled If the {@link guide/expression expression} is truthy,\n *     then special attribute \"disabled\" will be set on the element\n */\n\n\n/**\n * @ngdoc directive\n * @name ngChecked\n * @restrict A\n * @priority 100\n *\n * @description\n * The HTML specification does not require browsers to preserve the values of boolean attributes\n * such as checked. (Their presence means true and their absence means false.)\n * If we put an Angular interpolation expression into such an attribute then the\n * binding information would be lost when the browser removes the attribute.\n * The `ngChecked` directive solves this problem for the `checked` attribute.\n * This complementary directive is not removed by the browser and so provides\n * a permanent reliable place to store the binding information.\n * @example\n    <example>\n      <file name=\"index.html\">\n        Check me to check both: <input type=\"checkbox\" ng-model=\"master\"><br/>\n        <input id=\"checkSlave\" type=\"checkbox\" ng-checked=\"master\">\n      </file>\n      <file name=\"protractor.js\" type=\"protractor\">\n        it('should check both checkBoxes', function() {\n          expect(element(by.id('checkSlave')).getAttribute('checked')).toBeFalsy();\n          element(by.model('master')).click();\n          expect(element(by.id('checkSlave')).getAttribute('checked')).toBeTruthy();\n        });\n      </file>\n    </example>\n *\n * @element INPUT\n * @param {expression} ngChecked If the {@link guide/expression expression} is truthy,\n *     then special attribute \"checked\" will be set on the element\n */\n\n\n/**\n * @ngdoc directive\n * @name ngReadonly\n * @restrict A\n * @priority 100\n *\n * @description\n * The HTML specification does not require browsers to preserve the values of boolean attributes\n * such as readonly. (Their presence means true and their absence means false.)\n * If we put an Angular interpolation expression into such an attribute then the\n * binding information would be lost when the browser removes the attribute.\n * The `ngReadonly` directive solves this problem for the `readonly` attribute.\n * This complementary directive is not removed by the browser and so provides\n * a permanent reliable place to store the binding information.\n * @example\n    <example>\n      <file name=\"index.html\">\n        Check me to make text readonly: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        <input type=\"text\" ng-readonly=\"checked\" value=\"I'm Angular\"/>\n      </file>\n      <file name=\"protractor.js\" type=\"protractor\">\n        it('should toggle readonly attr', function() {\n          expect(element(by.css('[type=\"text\"]')).getAttribute('readonly')).toBeFalsy();\n          element(by.model('checked')).click();\n          expect(element(by.css('[type=\"text\"]')).getAttribute('readonly')).toBeTruthy();\n        });\n      </file>\n    </example>\n *\n * @element INPUT\n * @param {expression} ngReadonly If the {@link guide/expression expression} is truthy,\n *     then special attribute \"readonly\" will be set on the element\n */\n\n\n/**\n * @ngdoc directive\n * @name ngSelected\n * @restrict A\n * @priority 100\n *\n * @description\n * The HTML specification does not require browsers to preserve the values of boolean attributes\n * such as selected. (Their presence means true and their absence means false.)\n * If we put an Angular interpolation expression into such an attribute then the\n * binding information would be lost when the browser removes the attribute.\n * The `ngSelected` directive solves this problem for the `selected` attribute.\n * This complementary directive is not removed by the browser and so provides\n * a permanent reliable place to store the binding information.\n *\n * @example\n    <example>\n      <file name=\"index.html\">\n        Check me to select: <input type=\"checkbox\" ng-model=\"selected\"><br/>\n        <select>\n          <option>Hello!</option>\n          <option id=\"greet\" ng-selected=\"selected\">Greetings!</option>\n        </select>\n      </file>\n      <file name=\"protractor.js\" type=\"protractor\">\n        it('should select Greetings!', function() {\n          expect(element(by.id('greet')).getAttribute('selected')).toBeFalsy();\n          element(by.model('selected')).click();\n          expect(element(by.id('greet')).getAttribute('selected')).toBeTruthy();\n        });\n      </file>\n    </example>\n *\n * @element OPTION\n * @param {expression} ngSelected If the {@link guide/expression expression} is truthy,\n *     then special attribute \"selected\" will be set on the element\n */\n\n/**\n * @ngdoc directive\n * @name ngOpen\n * @restrict A\n * @priority 100\n *\n * @description\n * The HTML specification does not require browsers to preserve the values of boolean attributes\n * such as open. (Their presence means true and their absence means false.)\n * If we put an Angular interpolation expression into such an attribute then the\n * binding information would be lost when the browser removes the attribute.\n * The `ngOpen` directive solves this problem for the `open` attribute.\n * This complementary directive is not removed by the browser and so provides\n * a permanent reliable place to store the binding information.\n * @example\n     <example>\n       <file name=\"index.html\">\n         Check me check multiple: <input type=\"checkbox\" ng-model=\"open\"><br/>\n         <details id=\"details\" ng-open=\"open\">\n            <summary>Show/Hide me</summary>\n         </details>\n       </file>\n       <file name=\"protractor.js\" type=\"protractor\">\n         it('should toggle open', function() {\n           expect(element(by.id('details')).getAttribute('open')).toBeFalsy();\n           element(by.model('open')).click();\n           expect(element(by.id('details')).getAttribute('open')).toBeTruthy();\n         });\n       </file>\n     </example>\n *\n * @element DETAILS\n * @param {expression} ngOpen If the {@link guide/expression expression} is truthy,\n *     then special attribute \"open\" will be set on the element\n */\n\nvar ngAttributeAliasDirectives = {};\n\n\n// boolean attrs are evaluated\nforEach(BOOLEAN_ATTR, function(propName, attrName) {\n  // binding to multiple is not supported\n  if (propName == \"multiple\") return;\n\n  var normalized = directiveNormalize('ng-' + attrName);\n  ngAttributeAliasDirectives[normalized] = function() {\n    return {\n      restrict: 'A',\n      priority: 100,\n      link: function(scope, element, attr) {\n        scope.$watch(attr[normalized], function ngBooleanAttrWatchAction(value) {\n          attr.$set(attrName, !!value);\n        });\n      }\n    };\n  };\n});\n\n// aliased input attrs are evaluated\nforEach(ALIASED_ATTR, function(htmlAttr, ngAttr) {\n  ngAttributeAliasDirectives[ngAttr] = function() {\n    return {\n      priority: 100,\n      link: function(scope, element, attr) {\n        //special case ngPattern when a literal regular expression value\n        //is used as the expression (this way we don't have to watch anything).\n        if (ngAttr === \"ngPattern\" && attr.ngPattern.charAt(0) == \"/\") {\n          var match = attr.ngPattern.match(REGEX_STRING_REGEXP);\n          if (match) {\n            attr.$set(\"ngPattern\", new RegExp(match[1], match[2]));\n            return;\n          }\n        }\n\n        scope.$watch(attr[ngAttr], function ngAttrAliasWatchAction(value) {\n          attr.$set(ngAttr, value);\n        });\n      }\n    };\n  };\n});\n\n// ng-src, ng-srcset, ng-href are interpolated\nforEach(['src', 'srcset', 'href'], function(attrName) {\n  var normalized = directiveNormalize('ng-' + attrName);\n  ngAttributeAliasDirectives[normalized] = function() {\n    return {\n      priority: 99, // it needs to run after the attributes are interpolated\n      link: function(scope, element, attr) {\n        var propName = attrName,\n            name = attrName;\n\n        if (attrName === 'href' &&\n            toString.call(element.prop('href')) === '[object SVGAnimatedString]') {\n          name = 'xlinkHref';\n          attr.$attr[name] = 'xlink:href';\n          propName = null;\n        }\n\n        attr.$observe(normalized, function(value) {\n          if (!value) {\n            if (attrName === 'href') {\n              attr.$set(name, null);\n            }\n            return;\n          }\n\n          attr.$set(name, value);\n\n          // on IE, if \"ng:src\" directive declaration is used and \"src\" attribute doesn't exist\n          // then calling element.setAttribute('src', 'foo') doesn't do anything, so we need\n          // to set the property as well to achieve the desired effect.\n          // we use attr[attrName] value since $set can sanitize the url.\n          if (msie && propName) element.prop(propName, attr[name]);\n        });\n      }\n    };\n  };\n});\n\n/* global -nullFormCtrl, -SUBMITTED_CLASS, addSetValidityMethod: true\n */\nvar nullFormCtrl = {\n  $addControl: noop,\n  $$renameControl: nullFormRenameControl,\n  $removeControl: noop,\n  $setValidity: noop,\n  $setDirty: noop,\n  $setPristine: noop,\n  $setSubmitted: noop\n},\nSUBMITTED_CLASS = 'ng-submitted';\n\nfunction nullFormRenameControl(control, name) {\n  control.$name = name;\n}\n\n/**\n * @ngdoc type\n * @name form.FormController\n *\n * @property {boolean} $pristine True if user has not interacted with the form yet.\n * @property {boolean} $dirty True if user has already interacted with the form.\n * @property {boolean} $valid True if all of the containing forms and controls are valid.\n * @property {boolean} $invalid True if at least one containing control or form is invalid.\n * @property {boolean} $submitted True if user has submitted the form even if its invalid.\n *\n * @property {Object} $error Is an object hash, containing references to controls or\n *  forms with failing validators, where:\n *\n *  - keys are validation tokens (error names),\n *  - values are arrays of controls or forms that have a failing validator for given error name.\n *\n *  Built-in validation tokens:\n *\n *  - `email`\n *  - `max`\n *  - `maxlength`\n *  - `min`\n *  - `minlength`\n *  - `number`\n *  - `pattern`\n *  - `required`\n *  - `url`\n *  - `date`\n *  - `datetimelocal`\n *  - `time`\n *  - `week`\n *  - `month`\n *\n * @description\n * `FormController` keeps track of all its controls and nested forms as well as the state of them,\n * such as being valid/invalid or dirty/pristine.\n *\n * Each {@link ng.directive:form form} directive creates an instance\n * of `FormController`.\n *\n */\n//asks for $scope to fool the BC controller module\nFormController.$inject = ['$element', '$attrs', '$scope', '$animate', '$interpolate'];\nfunction FormController(element, attrs, $scope, $animate, $interpolate) {\n  var form = this,\n      controls = [];\n\n  var parentForm = form.$$parentForm = element.parent().controller('form') || nullFormCtrl;\n\n  // init state\n  form.$error = {};\n  form.$$success = {};\n  form.$pending = undefined;\n  form.$name = $interpolate(attrs.name || attrs.ngForm || '')($scope);\n  form.$dirty = false;\n  form.$pristine = true;\n  form.$valid = true;\n  form.$invalid = false;\n  form.$submitted = false;\n\n  parentForm.$addControl(form);\n\n  /**\n   * @ngdoc method\n   * @name form.FormController#$rollbackViewValue\n   *\n   * @description\n   * Rollback all form controls pending updates to the `$modelValue`.\n   *\n   * Updates may be pending by a debounced event or because the input is waiting for a some future\n   * event defined in `ng-model-options`. This method is typically needed by the reset button of\n   * a form that uses `ng-model-options` to pend updates.\n   */\n  form.$rollbackViewValue = function() {\n    forEach(controls, function(control) {\n      control.$rollbackViewValue();\n    });\n  };\n\n  /**\n   * @ngdoc method\n   * @name form.FormController#$commitViewValue\n   *\n   * @description\n   * Commit all form controls pending updates to the `$modelValue`.\n   *\n   * Updates may be pending by a debounced event or because the input is waiting for a some future\n   * event defined in `ng-model-options`. This method is rarely needed as `NgModelController`\n   * usually handles calling this in response to input events.\n   */\n  form.$commitViewValue = function() {\n    forEach(controls, function(control) {\n      control.$commitViewValue();\n    });\n  };\n\n  /**\n   * @ngdoc method\n   * @name form.FormController#$addControl\n   *\n   * @description\n   * Register a control with the form.\n   *\n   * Input elements using ngModelController do this automatically when they are linked.\n   */\n  form.$addControl = function(control) {\n    // Breaking change - before, inputs whose name was \"hasOwnProperty\" were quietly ignored\n    // and not added to the scope.  Now we throw an error.\n    assertNotHasOwnProperty(control.$name, 'input');\n    controls.push(control);\n\n    if (control.$name) {\n      form[control.$name] = control;\n    }\n  };\n\n  // Private API: rename a form control\n  form.$$renameControl = function(control, newName) {\n    var oldName = control.$name;\n\n    if (form[oldName] === control) {\n      delete form[oldName];\n    }\n    form[newName] = control;\n    control.$name = newName;\n  };\n\n  /**\n   * @ngdoc method\n   * @name form.FormController#$removeControl\n   *\n   * @description\n   * Deregister a control from the form.\n   *\n   * Input elements using ngModelController do this automatically when they are destroyed.\n   */\n  form.$removeControl = function(control) {\n    if (control.$name && form[control.$name] === control) {\n      delete form[control.$name];\n    }\n    forEach(form.$pending, function(value, name) {\n      form.$setValidity(name, null, control);\n    });\n    forEach(form.$error, function(value, name) {\n      form.$setValidity(name, null, control);\n    });\n    forEach(form.$$success, function(value, name) {\n      form.$setValidity(name, null, control);\n    });\n\n    arrayRemove(controls, control);\n  };\n\n\n  /**\n   * @ngdoc method\n   * @name form.FormController#$setValidity\n   *\n   * @description\n   * Sets the validity of a form control.\n   *\n   * This method will also propagate to parent forms.\n   */\n  addSetValidityMethod({\n    ctrl: this,\n    $element: element,\n    set: function(object, property, controller) {\n      var list = object[property];\n      if (!list) {\n        object[property] = [controller];\n      } else {\n        var index = list.indexOf(controller);\n        if (index === -1) {\n          list.push(controller);\n        }\n      }\n    },\n    unset: function(object, property, controller) {\n      var list = object[property];\n      if (!list) {\n        return;\n      }\n      arrayRemove(list, controller);\n      if (list.length === 0) {\n        delete object[property];\n      }\n    },\n    parentForm: parentForm,\n    $animate: $animate\n  });\n\n  /**\n   * @ngdoc method\n   * @name form.FormController#$setDirty\n   *\n   * @description\n   * Sets the form to a dirty state.\n   *\n   * This method can be called to add the 'ng-dirty' class and set the form to a dirty\n   * state (ng-dirty class). This method will also propagate to parent forms.\n   */\n  form.$setDirty = function() {\n    $animate.removeClass(element, PRISTINE_CLASS);\n    $animate.addClass(element, DIRTY_CLASS);\n    form.$dirty = true;\n    form.$pristine = false;\n    parentForm.$setDirty();\n  };\n\n  /**\n   * @ngdoc method\n   * @name form.FormController#$setPristine\n   *\n   * @description\n   * Sets the form to its pristine state.\n   *\n   * This method can be called to remove the 'ng-dirty' class and set the form to its pristine\n   * state (ng-pristine class). This method will also propagate to all the controls contained\n   * in this form.\n   *\n   * Setting a form back to a pristine state is often useful when we want to 'reuse' a form after\n   * saving or resetting it.\n   */\n  form.$setPristine = function() {\n    $animate.setClass(element, PRISTINE_CLASS, DIRTY_CLASS + ' ' + SUBMITTED_CLASS);\n    form.$dirty = false;\n    form.$pristine = true;\n    form.$submitted = false;\n    forEach(controls, function(control) {\n      control.$setPristine();\n    });\n  };\n\n  /**\n   * @ngdoc method\n   * @name form.FormController#$setUntouched\n   *\n   * @description\n   * Sets the form to its untouched state.\n   *\n   * This method can be called to remove the 'ng-touched' class and set the form controls to their\n   * untouched state (ng-untouched class).\n   *\n   * Setting a form controls back to their untouched state is often useful when setting the form\n   * back to its pristine state.\n   */\n  form.$setUntouched = function() {\n    forEach(controls, function(control) {\n      control.$setUntouched();\n    });\n  };\n\n  /**\n   * @ngdoc method\n   * @name form.FormController#$setSubmitted\n   *\n   * @description\n   * Sets the form to its submitted state.\n   */\n  form.$setSubmitted = function() {\n    $animate.addClass(element, SUBMITTED_CLASS);\n    form.$submitted = true;\n    parentForm.$setSubmitted();\n  };\n}\n\n/**\n * @ngdoc directive\n * @name ngForm\n * @restrict EAC\n *\n * @description\n * Nestable alias of {@link ng.directive:form `form`} directive. HTML\n * does not allow nesting of form elements. It is useful to nest forms, for example if the validity of a\n * sub-group of controls needs to be determined.\n *\n * Note: the purpose of `ngForm` is to group controls,\n * but not to be a replacement for the `<form>` tag with all of its capabilities\n * (e.g. posting to the server, ...).\n *\n * @param {string=} ngForm|name Name of the form. If specified, the form controller will be published into\n *                       related scope, under this name.\n *\n */\n\n /**\n * @ngdoc directive\n * @name form\n * @restrict E\n *\n * @description\n * Directive that instantiates\n * {@link form.FormController FormController}.\n *\n * If the `name` attribute is specified, the form controller is published onto the current scope under\n * this name.\n *\n * # Alias: {@link ng.directive:ngForm `ngForm`}\n *\n * In Angular forms can be nested. This means that the outer form is valid when all of the child\n * forms are valid as well. However, browsers do not allow nesting of `<form>` elements, so\n * Angular provides the {@link ng.directive:ngForm `ngForm`} directive which behaves identically to\n * `<form>` but can be nested.  This allows you to have nested forms, which is very useful when\n * using Angular validation directives in forms that are dynamically generated using the\n * {@link ng.directive:ngRepeat `ngRepeat`} directive. Since you cannot dynamically generate the `name`\n * attribute of input elements using interpolation, you have to wrap each set of repeated inputs in an\n * `ngForm` directive and nest these in an outer `form` element.\n *\n *\n * # CSS classes\n *  - `ng-valid` is set if the form is valid.\n *  - `ng-invalid` is set if the form is invalid.\n *  - `ng-pristine` is set if the form is pristine.\n *  - `ng-dirty` is set if the form is dirty.\n *  - `ng-submitted` is set if the form was submitted.\n *\n * Keep in mind that ngAnimate can detect each of these classes when added and removed.\n *\n *\n * # Submitting a form and preventing the default action\n *\n * Since the role of forms in client-side Angular applications is different than in classical\n * roundtrip apps, it is desirable for the browser not to translate the form submission into a full\n * page reload that sends the data to the server. Instead some javascript logic should be triggered\n * to handle the form submission in an application-specific way.\n *\n * For this reason, Angular prevents the default action (form submission to the server) unless the\n * `<form>` element has an `action` attribute specified.\n *\n * You can use one of the following two ways to specify what javascript method should be called when\n * a form is submitted:\n *\n * - {@link ng.directive:ngSubmit ngSubmit} directive on the form element\n * - {@link ng.directive:ngClick ngClick} directive on the first\n  *  button or input field of type submit (input[type=submit])\n *\n * To prevent double execution of the handler, use only one of the {@link ng.directive:ngSubmit ngSubmit}\n * or {@link ng.directive:ngClick ngClick} directives.\n * This is because of the following form submission rules in the HTML specification:\n *\n * - If a form has only one input field then hitting enter in this field triggers form submit\n * (`ngSubmit`)\n * - if a form has 2+ input fields and no buttons or input[type=submit] then hitting enter\n * doesn't trigger submit\n * - if a form has one or more input fields and one or more buttons or input[type=submit] then\n * hitting enter in any of the input fields will trigger the click handler on the *first* button or\n * input[type=submit] (`ngClick`) *and* a submit handler on the enclosing form (`ngSubmit`)\n *\n * Any pending `ngModelOptions` changes will take place immediately when an enclosing form is\n * submitted. Note that `ngClick` events will occur before the model is updated. Use `ngSubmit`\n * to have access to the updated model.\n *\n * ## Animation Hooks\n *\n * Animations in ngForm are triggered when any of the associated CSS classes are added and removed.\n * These classes are: `.ng-pristine`, `.ng-dirty`, `.ng-invalid` and `.ng-valid` as well as any\n * other validations that are performed within the form. Animations in ngForm are similar to how\n * they work in ngClass and animations can be hooked into using CSS transitions, keyframes as well\n * as JS animations.\n *\n * The following example shows a simple way to utilize CSS transitions to style a form element\n * that has been rendered as invalid after it has been validated:\n *\n * <pre>\n * //be sure to include ngAnimate as a module to hook into more\n * //advanced animations\n * .my-form {\n *   transition:0.5s linear all;\n *   background: white;\n * }\n * .my-form.ng-invalid {\n *   background: red;\n *   color:white;\n * }\n * </pre>\n *\n * @example\n    <example deps=\"angular-animate.js\" animations=\"true\" fixBase=\"true\" module=\"formExample\">\n      <file name=\"index.html\">\n       <script>\n         angular.module('formExample', [])\n           .controller('FormController', ['$scope', function($scope) {\n             $scope.userType = 'guest';\n           }]);\n       </script>\n       <style>\n        .my-form {\n          -webkit-transition:all linear 0.5s;\n          transition:all linear 0.5s;\n          background: transparent;\n        }\n        .my-form.ng-invalid {\n          background: red;\n        }\n       </style>\n       <form name=\"myForm\" ng-controller=\"FormController\" class=\"my-form\">\n         userType: <input name=\"input\" ng-model=\"userType\" required>\n         <span class=\"error\" ng-show=\"myForm.input.$error.required\">Required!</span><br>\n         <tt>userType = {{userType}}</tt><br>\n         <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br>\n         <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br>\n        </form>\n      </file>\n      <file name=\"protractor.js\" type=\"protractor\">\n        it('should initialize to model', function() {\n          var userType = element(by.binding('userType'));\n          var valid = element(by.binding('myForm.input.$valid'));\n\n          expect(userType.getText()).toContain('guest');\n          expect(valid.getText()).toContain('true');\n        });\n\n        it('should be invalid if empty', function() {\n          var userType = element(by.binding('userType'));\n          var valid = element(by.binding('myForm.input.$valid'));\n          var userInput = element(by.model('userType'));\n\n          userInput.clear();\n          userInput.sendKeys('');\n\n          expect(userType.getText()).toEqual('userType =');\n          expect(valid.getText()).toContain('false');\n        });\n      </file>\n    </example>\n *\n * @param {string=} name Name of the form. If specified, the form controller will be published into\n *                       related scope, under this name.\n */\nvar formDirectiveFactory = function(isNgForm) {\n  return ['$timeout', function($timeout) {\n    var formDirective = {\n      name: 'form',\n      restrict: isNgForm ? 'EAC' : 'E',\n      controller: FormController,\n      compile: function ngFormCompile(formElement) {\n        // Setup initial state of the control\n        formElement.addClass(PRISTINE_CLASS).addClass(VALID_CLASS);\n\n        return {\n          pre: function ngFormPreLink(scope, formElement, attr, controller) {\n            // if `action` attr is not present on the form, prevent the default action (submission)\n            if (!('action' in attr)) {\n              // we can't use jq events because if a form is destroyed during submission the default\n              // action is not prevented. see #1238\n              //\n              // IE 9 is not affected because it doesn't fire a submit event and try to do a full\n              // page reload if the form was destroyed by submission of the form via a click handler\n              // on a button in the form. Looks like an IE9 specific bug.\n              var handleFormSubmission = function(event) {\n                scope.$apply(function() {\n                  controller.$commitViewValue();\n                  controller.$setSubmitted();\n                });\n\n                event.preventDefault();\n              };\n\n              addEventListenerFn(formElement[0], 'submit', handleFormSubmission);\n\n              // unregister the preventDefault listener so that we don't not leak memory but in a\n              // way that will achieve the prevention of the default action.\n              formElement.on('$destroy', function() {\n                $timeout(function() {\n                  removeEventListenerFn(formElement[0], 'submit', handleFormSubmission);\n                }, 0, false);\n              });\n            }\n\n            var parentFormCtrl = controller.$$parentForm,\n                alias = controller.$name;\n\n            if (alias) {\n              setter(scope, null, alias, controller, alias);\n              attr.$observe(attr.name ? 'name' : 'ngForm', function(newValue) {\n                if (alias === newValue) return;\n                setter(scope, null, alias, undefined, alias);\n                alias = newValue;\n                setter(scope, null, alias, controller, alias);\n                parentFormCtrl.$$renameControl(controller, alias);\n              });\n            }\n            formElement.on('$destroy', function() {\n              parentFormCtrl.$removeControl(controller);\n              if (alias) {\n                setter(scope, null, alias, undefined, alias);\n              }\n              extend(controller, nullFormCtrl); //stop propagating child destruction handlers upwards\n            });\n          }\n        };\n      }\n    };\n\n    return formDirective;\n  }];\n};\n\nvar formDirective = formDirectiveFactory();\nvar ngFormDirective = formDirectiveFactory(true);\n\n/* global VALID_CLASS: false,\n  INVALID_CLASS: false,\n  PRISTINE_CLASS: false,\n  DIRTY_CLASS: false,\n  UNTOUCHED_CLASS: false,\n  TOUCHED_CLASS: false,\n  $ngModelMinErr: false,\n*/\n\n// Regex code is obtained from SO: https://stackoverflow.com/questions/3143070/javascript-regex-iso-datetime#answer-3143231\nvar ISO_DATE_REGEXP = /\\d{4}-[01]\\d-[0-3]\\dT[0-2]\\d:[0-5]\\d:[0-5]\\d\\.\\d+([+-][0-2]\\d:[0-5]\\d|Z)/;\nvar URL_REGEXP = /^(ftp|http|https):\\/\\/(\\w+:{0,1}\\w*@)?(\\S+)(:[0-9]+)?(\\/|\\/([\\w#!:.?+=&%@!\\-\\/]))?$/;\nvar EMAIL_REGEXP = /^[a-z0-9!#$%&'*+\\/=?^_`{|}~.-]+@[a-z0-9]([a-z0-9-]*[a-z0-9])?(\\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)*$/i;\nvar NUMBER_REGEXP = /^\\s*(\\-|\\+)?(\\d+|(\\d*(\\.\\d*)))\\s*$/;\nvar DATE_REGEXP = /^(\\d{4})-(\\d{2})-(\\d{2})$/;\nvar DATETIMELOCAL_REGEXP = /^(\\d{4})-(\\d\\d)-(\\d\\d)T(\\d\\d):(\\d\\d)(?::(\\d\\d)(\\.\\d{1,3})?)?$/;\nvar WEEK_REGEXP = /^(\\d{4})-W(\\d\\d)$/;\nvar MONTH_REGEXP = /^(\\d{4})-(\\d\\d)$/;\nvar TIME_REGEXP = /^(\\d\\d):(\\d\\d)(?::(\\d\\d)(\\.\\d{1,3})?)?$/;\n\nvar inputType = {\n\n  /**\n   * @ngdoc input\n   * @name input[text]\n   *\n   * @description\n   * Standard HTML text input with angular data binding, inherited by most of the `input` elements.\n   *\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Adds `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength. Setting the attribute to a negative or non-numeric value, allows view values of\n   *    any length.\n   * @param {string=} pattern Similar to `ngPattern` except that the attribute value is the actual string\n   *    that contains the regular expression body that will be converted to a regular expression\n   *    as in the ngPattern directive.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the ngModel value does not match\n   *    a RegExp found by evaluating the Angular expression given in the attribute value.\n   *    If the expression evaluates to a RegExp object then this is used directly.\n   *    If the expression is a string then it will be converted to a RegExp after wrapping it in `^` and `$`\n   *    characters. For instance, `\"abc\"` will be converted to `new RegExp('^abc$')`.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   * @param {boolean=} [ngTrim=true] If set to false Angular will not automatically trim the input.\n   *    This parameter is ignored for input[type=password] controls, which will never trim the\n   *    input.\n   *\n   * @example\n      <example name=\"text-input-directive\" module=\"textInputExample\">\n        <file name=\"index.html\">\n         <script>\n           angular.module('textInputExample', [])\n             .controller('ExampleController', ['$scope', function($scope) {\n               $scope.example = {\n                 text: 'guest',\n                 word: /^\\s*\\w*\\s*$/\n               };\n             }]);\n         </script>\n         <form name=\"myForm\" ng-controller=\"ExampleController\">\n           Single word: <input type=\"text\" name=\"input\" ng-model=\"example.text\"\n                               ng-pattern=\"example.word\" required ng-trim=\"false\">\n           <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.input.$error.pattern\">\n             Single word only!</span>\n\n           <tt>text = {{example.text}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n          </form>\n        </file>\n        <file name=\"protractor.js\" type=\"protractor\">\n          var text = element(by.binding('example.text'));\n          var valid = element(by.binding('myForm.input.$valid'));\n          var input = element(by.model('example.text'));\n\n          it('should initialize to model', function() {\n            expect(text.getText()).toContain('guest');\n            expect(valid.getText()).toContain('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input.clear();\n            input.sendKeys('');\n\n            expect(text.getText()).toEqual('text =');\n            expect(valid.getText()).toContain('false');\n          });\n\n          it('should be invalid if multi word', function() {\n            input.clear();\n            input.sendKeys('hello world');\n\n            expect(valid.getText()).toContain('false');\n          });\n        </file>\n      </example>\n   */\n  'text': textInputType,\n\n    /**\n     * @ngdoc input\n     * @name input[date]\n     *\n     * @description\n     * Input with date validation and transformation. In browsers that do not yet support\n     * the HTML5 date input, a text element will be used. In that case, text must be entered in a valid ISO-8601\n     * date format (yyyy-MM-dd), for example: `2009-01-06`. Since many\n     * modern browsers do not yet support this input type, it is important to provide cues to users on the\n     * expected input format via a placeholder or label.\n     *\n     * The model must always be a Date object, otherwise Angular will throw an error.\n     * Invalid `Date` objects (dates whose `getTime()` is `NaN`) will be rendered as an empty string.\n     *\n     * The timezone to be used to read/write the `Date` instance in the model can be defined using\n     * {@link ng.directive:ngModelOptions ngModelOptions}. By default, this is the timezone of the browser.\n     *\n     * @param {string} ngModel Assignable angular expression to data-bind to.\n     * @param {string=} name Property name of the form under which the control is published.\n     * @param {string=} min Sets the `min` validation error key if the value entered is less than `min`. This must be a\n     * valid ISO date string (yyyy-MM-dd).\n     * @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`. This must be\n     * a valid ISO date string (yyyy-MM-dd).\n     * @param {string=} required Sets `required` validation error key if the value is not entered.\n     * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n     *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n     *    `required` when you want to data-bind to the `required` attribute.\n     * @param {string=} ngChange Angular expression to be executed when input changes due to user\n     *    interaction with the input element.\n     *\n     * @example\n     <example name=\"date-input-directive\" module=\"dateInputExample\">\n     <file name=\"index.html\">\n       <script>\n          angular.module('dateInputExample', [])\n            .controller('DateController', ['$scope', function($scope) {\n              $scope.example = {\n                value: new Date(2013, 9, 22)\n              };\n            }]);\n       </script>\n       <form name=\"myForm\" ng-controller=\"DateController as dateCtrl\">\n          Pick a date in 2013:\n          <input type=\"date\" id=\"exampleInput\" name=\"input\" ng-model=\"example.value\"\n              placeholder=\"yyyy-MM-dd\" min=\"2013-01-01\" max=\"2013-12-31\" required />\n          <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n              Required!</span>\n          <span class=\"error\" ng-show=\"myForm.input.$error.date\">\n              Not a valid date!</span>\n           <tt>value = {{example.value | date: \"yyyy-MM-dd\"}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n       </form>\n     </file>\n     <file name=\"protractor.js\" type=\"protractor\">\n        var value = element(by.binding('example.value | date: \"yyyy-MM-dd\"'));\n        var valid = element(by.binding('myForm.input.$valid'));\n        var input = element(by.model('example.value'));\n\n        // currently protractor/webdriver does not support\n        // sending keys to all known HTML5 input controls\n        // for various browsers (see https://github.com/angular/protractor/issues/562).\n        function setInput(val) {\n          // set the value of the element and force validation.\n          var scr = \"var ipt = document.getElementById('exampleInput'); \" +\n          \"ipt.value = '\" + val + \"';\" +\n          \"angular.element(ipt).scope().$apply(function(s) { s.myForm[ipt.name].$setViewValue('\" + val + \"'); });\";\n          browser.executeScript(scr);\n        }\n\n        it('should initialize to model', function() {\n          expect(value.getText()).toContain('2013-10-22');\n          expect(valid.getText()).toContain('myForm.input.$valid = true');\n        });\n\n        it('should be invalid if empty', function() {\n          setInput('');\n          expect(value.getText()).toEqual('value =');\n          expect(valid.getText()).toContain('myForm.input.$valid = false');\n        });\n\n        it('should be invalid if over max', function() {\n          setInput('2015-01-01');\n          expect(value.getText()).toContain('');\n          expect(valid.getText()).toContain('myForm.input.$valid = false');\n        });\n     </file>\n     </example>\n     */\n  'date': createDateInputType('date', DATE_REGEXP,\n         createDateParser(DATE_REGEXP, ['yyyy', 'MM', 'dd']),\n         'yyyy-MM-dd'),\n\n   /**\n    * @ngdoc input\n    * @name input[datetime-local]\n    *\n    * @description\n    * Input with datetime validation and transformation. In browsers that do not yet support\n    * the HTML5 date input, a text element will be used. In that case, the text must be entered in a valid ISO-8601\n    * local datetime format (yyyy-MM-ddTHH:mm:ss), for example: `2010-12-28T14:57:00`.\n    *\n    * The model must always be a Date object, otherwise Angular will throw an error.\n    * Invalid `Date` objects (dates whose `getTime()` is `NaN`) will be rendered as an empty string.\n    *\n    * The timezone to be used to read/write the `Date` instance in the model can be defined using\n    * {@link ng.directive:ngModelOptions ngModelOptions}. By default, this is the timezone of the browser.\n    *\n    * @param {string} ngModel Assignable angular expression to data-bind to.\n    * @param {string=} name Property name of the form under which the control is published.\n    * @param {string=} min Sets the `min` validation error key if the value entered is less than `min`. This must be a\n    * valid ISO datetime format (yyyy-MM-ddTHH:mm:ss).\n    * @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`. This must be\n    * a valid ISO datetime format (yyyy-MM-ddTHH:mm:ss).\n    * @param {string=} required Sets `required` validation error key if the value is not entered.\n    * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n    *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n    *    `required` when you want to data-bind to the `required` attribute.\n    * @param {string=} ngChange Angular expression to be executed when input changes due to user\n    *    interaction with the input element.\n    *\n    * @example\n    <example name=\"datetimelocal-input-directive\" module=\"dateExample\">\n    <file name=\"index.html\">\n      <script>\n        angular.module('dateExample', [])\n          .controller('DateController', ['$scope', function($scope) {\n            $scope.example = {\n              value: new Date(2010, 11, 28, 14, 57)\n            };\n          }]);\n      </script>\n      <form name=\"myForm\" ng-controller=\"DateController as dateCtrl\">\n        Pick a date between in 2013:\n        <input type=\"datetime-local\" id=\"exampleInput\" name=\"input\" ng-model=\"example.value\"\n            placeholder=\"yyyy-MM-ddTHH:mm:ss\" min=\"2001-01-01T00:00:00\" max=\"2013-12-31T00:00:00\" required />\n        <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n            Required!</span>\n        <span class=\"error\" ng-show=\"myForm.input.$error.datetimelocal\">\n            Not a valid date!</span>\n        <tt>value = {{example.value | date: \"yyyy-MM-ddTHH:mm:ss\"}}</tt><br/>\n        <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n        <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n        <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n        <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n      </form>\n    </file>\n    <file name=\"protractor.js\" type=\"protractor\">\n      var value = element(by.binding('example.value | date: \"yyyy-MM-ddTHH:mm:ss\"'));\n      var valid = element(by.binding('myForm.input.$valid'));\n      var input = element(by.model('example.value'));\n\n      // currently protractor/webdriver does not support\n      // sending keys to all known HTML5 input controls\n      // for various browsers (https://github.com/angular/protractor/issues/562).\n      function setInput(val) {\n        // set the value of the element and force validation.\n        var scr = \"var ipt = document.getElementById('exampleInput'); \" +\n        \"ipt.value = '\" + val + \"';\" +\n        \"angular.element(ipt).scope().$apply(function(s) { s.myForm[ipt.name].$setViewValue('\" + val + \"'); });\";\n        browser.executeScript(scr);\n      }\n\n      it('should initialize to model', function() {\n        expect(value.getText()).toContain('2010-12-28T14:57:00');\n        expect(valid.getText()).toContain('myForm.input.$valid = true');\n      });\n\n      it('should be invalid if empty', function() {\n        setInput('');\n        expect(value.getText()).toEqual('value =');\n        expect(valid.getText()).toContain('myForm.input.$valid = false');\n      });\n\n      it('should be invalid if over max', function() {\n        setInput('2015-01-01T23:59:00');\n        expect(value.getText()).toContain('');\n        expect(valid.getText()).toContain('myForm.input.$valid = false');\n      });\n    </file>\n    </example>\n    */\n  'datetime-local': createDateInputType('datetimelocal', DATETIMELOCAL_REGEXP,\n      createDateParser(DATETIMELOCAL_REGEXP, ['yyyy', 'MM', 'dd', 'HH', 'mm', 'ss', 'sss']),\n      'yyyy-MM-ddTHH:mm:ss.sss'),\n\n  /**\n   * @ngdoc input\n   * @name input[time]\n   *\n   * @description\n   * Input with time validation and transformation. In browsers that do not yet support\n   * the HTML5 date input, a text element will be used. In that case, the text must be entered in a valid ISO-8601\n   * local time format (HH:mm:ss), for example: `14:57:00`. Model must be a Date object. This binding will always output a\n   * Date object to the model of January 1, 1970, or local date `new Date(1970, 0, 1, HH, mm, ss)`.\n   *\n   * The model must always be a Date object, otherwise Angular will throw an error.\n   * Invalid `Date` objects (dates whose `getTime()` is `NaN`) will be rendered as an empty string.\n   *\n   * The timezone to be used to read/write the `Date` instance in the model can be defined using\n   * {@link ng.directive:ngModelOptions ngModelOptions}. By default, this is the timezone of the browser.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} min Sets the `min` validation error key if the value entered is less than `min`. This must be a\n   * valid ISO time format (HH:mm:ss).\n   * @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`. This must be a\n   * valid ISO time format (HH:mm:ss).\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n   <example name=\"time-input-directive\" module=\"timeExample\">\n   <file name=\"index.html\">\n     <script>\n      angular.module('timeExample', [])\n        .controller('DateController', ['$scope', function($scope) {\n          $scope.example = {\n            value: new Date(1970, 0, 1, 14, 57, 0)\n          };\n        }]);\n     </script>\n     <form name=\"myForm\" ng-controller=\"DateController as dateCtrl\">\n        Pick a between 8am and 5pm:\n        <input type=\"time\" id=\"exampleInput\" name=\"input\" ng-model=\"example.value\"\n            placeholder=\"HH:mm:ss\" min=\"08:00:00\" max=\"17:00:00\" required />\n        <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n            Required!</span>\n        <span class=\"error\" ng-show=\"myForm.input.$error.time\">\n            Not a valid date!</span>\n        <tt>value = {{example.value | date: \"HH:mm:ss\"}}</tt><br/>\n        <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n        <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n        <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n        <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n     </form>\n   </file>\n   <file name=\"protractor.js\" type=\"protractor\">\n      var value = element(by.binding('example.value | date: \"HH:mm:ss\"'));\n      var valid = element(by.binding('myForm.input.$valid'));\n      var input = element(by.model('example.value'));\n\n      // currently protractor/webdriver does not support\n      // sending keys to all known HTML5 input controls\n      // for various browsers (https://github.com/angular/protractor/issues/562).\n      function setInput(val) {\n        // set the value of the element and force validation.\n        var scr = \"var ipt = document.getElementById('exampleInput'); \" +\n        \"ipt.value = '\" + val + \"';\" +\n        \"angular.element(ipt).scope().$apply(function(s) { s.myForm[ipt.name].$setViewValue('\" + val + \"'); });\";\n        browser.executeScript(scr);\n      }\n\n      it('should initialize to model', function() {\n        expect(value.getText()).toContain('14:57:00');\n        expect(valid.getText()).toContain('myForm.input.$valid = true');\n      });\n\n      it('should be invalid if empty', function() {\n        setInput('');\n        expect(value.getText()).toEqual('value =');\n        expect(valid.getText()).toContain('myForm.input.$valid = false');\n      });\n\n      it('should be invalid if over max', function() {\n        setInput('23:59:00');\n        expect(value.getText()).toContain('');\n        expect(valid.getText()).toContain('myForm.input.$valid = false');\n      });\n   </file>\n   </example>\n   */\n  'time': createDateInputType('time', TIME_REGEXP,\n      createDateParser(TIME_REGEXP, ['HH', 'mm', 'ss', 'sss']),\n     'HH:mm:ss.sss'),\n\n   /**\n    * @ngdoc input\n    * @name input[week]\n    *\n    * @description\n    * Input with week-of-the-year validation and transformation to Date. In browsers that do not yet support\n    * the HTML5 week input, a text element will be used. In that case, the text must be entered in a valid ISO-8601\n    * week format (yyyy-W##), for example: `2013-W02`.\n    *\n    * The model must always be a Date object, otherwise Angular will throw an error.\n    * Invalid `Date` objects (dates whose `getTime()` is `NaN`) will be rendered as an empty string.\n    *\n    * The timezone to be used to read/write the `Date` instance in the model can be defined using\n    * {@link ng.directive:ngModelOptions ngModelOptions}. By default, this is the timezone of the browser.\n    *\n    * @param {string} ngModel Assignable angular expression to data-bind to.\n    * @param {string=} name Property name of the form under which the control is published.\n    * @param {string=} min Sets the `min` validation error key if the value entered is less than `min`. This must be a\n    * valid ISO week format (yyyy-W##).\n    * @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`. This must be\n    * a valid ISO week format (yyyy-W##).\n    * @param {string=} required Sets `required` validation error key if the value is not entered.\n    * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n    *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n    *    `required` when you want to data-bind to the `required` attribute.\n    * @param {string=} ngChange Angular expression to be executed when input changes due to user\n    *    interaction with the input element.\n    *\n    * @example\n    <example name=\"week-input-directive\" module=\"weekExample\">\n    <file name=\"index.html\">\n      <script>\n      angular.module('weekExample', [])\n        .controller('DateController', ['$scope', function($scope) {\n          $scope.example = {\n            value: new Date(2013, 0, 3)\n          };\n        }]);\n      </script>\n      <form name=\"myForm\" ng-controller=\"DateController as dateCtrl\">\n        Pick a date between in 2013:\n        <input id=\"exampleInput\" type=\"week\" name=\"input\" ng-model=\"example.value\"\n            placeholder=\"YYYY-W##\" min=\"2012-W32\" max=\"2013-W52\" required />\n        <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n            Required!</span>\n        <span class=\"error\" ng-show=\"myForm.input.$error.week\">\n            Not a valid date!</span>\n        <tt>value = {{example.value | date: \"yyyy-Www\"}}</tt><br/>\n        <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n        <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n        <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n        <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n      </form>\n    </file>\n    <file name=\"protractor.js\" type=\"protractor\">\n      var value = element(by.binding('example.value | date: \"yyyy-Www\"'));\n      var valid = element(by.binding('myForm.input.$valid'));\n      var input = element(by.model('example.value'));\n\n      // currently protractor/webdriver does not support\n      // sending keys to all known HTML5 input controls\n      // for various browsers (https://github.com/angular/protractor/issues/562).\n      function setInput(val) {\n        // set the value of the element and force validation.\n        var scr = \"var ipt = document.getElementById('exampleInput'); \" +\n        \"ipt.value = '\" + val + \"';\" +\n        \"angular.element(ipt).scope().$apply(function(s) { s.myForm[ipt.name].$setViewValue('\" + val + \"'); });\";\n        browser.executeScript(scr);\n      }\n\n      it('should initialize to model', function() {\n        expect(value.getText()).toContain('2013-W01');\n        expect(valid.getText()).toContain('myForm.input.$valid = true');\n      });\n\n      it('should be invalid if empty', function() {\n        setInput('');\n        expect(value.getText()).toEqual('value =');\n        expect(valid.getText()).toContain('myForm.input.$valid = false');\n      });\n\n      it('should be invalid if over max', function() {\n        setInput('2015-W01');\n        expect(value.getText()).toContain('');\n        expect(valid.getText()).toContain('myForm.input.$valid = false');\n      });\n    </file>\n    </example>\n    */\n  'week': createDateInputType('week', WEEK_REGEXP, weekParser, 'yyyy-Www'),\n\n  /**\n   * @ngdoc input\n   * @name input[month]\n   *\n   * @description\n   * Input with month validation and transformation. In browsers that do not yet support\n   * the HTML5 month input, a text element will be used. In that case, the text must be entered in a valid ISO-8601\n   * month format (yyyy-MM), for example: `2009-01`.\n   *\n   * The model must always be a Date object, otherwise Angular will throw an error.\n   * Invalid `Date` objects (dates whose `getTime()` is `NaN`) will be rendered as an empty string.\n   * If the model is not set to the first of the month, the next view to model update will set it\n   * to the first of the month.\n   *\n   * The timezone to be used to read/write the `Date` instance in the model can be defined using\n   * {@link ng.directive:ngModelOptions ngModelOptions}. By default, this is the timezone of the browser.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} min Sets the `min` validation error key if the value entered is less than `min`. This must be\n   * a valid ISO month format (yyyy-MM).\n   * @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`. This must\n   * be a valid ISO month format (yyyy-MM).\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n   <example name=\"month-input-directive\" module=\"monthExample\">\n   <file name=\"index.html\">\n     <script>\n      angular.module('monthExample', [])\n        .controller('DateController', ['$scope', function($scope) {\n          $scope.example = {\n            value: new Date(2013, 9, 1)\n          };\n        }]);\n     </script>\n     <form name=\"myForm\" ng-controller=\"DateController as dateCtrl\">\n       Pick a month in 2013:\n       <input id=\"exampleInput\" type=\"month\" name=\"input\" ng-model=\"example.value\"\n          placeholder=\"yyyy-MM\" min=\"2013-01\" max=\"2013-12\" required />\n       <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n          Required!</span>\n       <span class=\"error\" ng-show=\"myForm.input.$error.month\">\n          Not a valid month!</span>\n       <tt>value = {{example.value | date: \"yyyy-MM\"}}</tt><br/>\n       <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n       <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n       <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n       <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n     </form>\n   </file>\n   <file name=\"protractor.js\" type=\"protractor\">\n      var value = element(by.binding('example.value | date: \"yyyy-MM\"'));\n      var valid = element(by.binding('myForm.input.$valid'));\n      var input = element(by.model('example.value'));\n\n      // currently protractor/webdriver does not support\n      // sending keys to all known HTML5 input controls\n      // for various browsers (https://github.com/angular/protractor/issues/562).\n      function setInput(val) {\n        // set the value of the element and force validation.\n        var scr = \"var ipt = document.getElementById('exampleInput'); \" +\n        \"ipt.value = '\" + val + \"';\" +\n        \"angular.element(ipt).scope().$apply(function(s) { s.myForm[ipt.name].$setViewValue('\" + val + \"'); });\";\n        browser.executeScript(scr);\n      }\n\n      it('should initialize to model', function() {\n        expect(value.getText()).toContain('2013-10');\n        expect(valid.getText()).toContain('myForm.input.$valid = true');\n      });\n\n      it('should be invalid if empty', function() {\n        setInput('');\n        expect(value.getText()).toEqual('value =');\n        expect(valid.getText()).toContain('myForm.input.$valid = false');\n      });\n\n      it('should be invalid if over max', function() {\n        setInput('2015-01');\n        expect(value.getText()).toContain('');\n        expect(valid.getText()).toContain('myForm.input.$valid = false');\n      });\n   </file>\n   </example>\n   */\n  'month': createDateInputType('month', MONTH_REGEXP,\n     createDateParser(MONTH_REGEXP, ['yyyy', 'MM']),\n     'yyyy-MM'),\n\n  /**\n   * @ngdoc input\n   * @name input[number]\n   *\n   * @description\n   * Text input with number validation and transformation. Sets the `number` validation\n   * error if not a valid number.\n   *\n   * The model must always be a number, otherwise Angular will throw an error.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} min Sets the `min` validation error key if the value entered is less than `min`.\n   * @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength. Setting the attribute to a negative or non-numeric value, allows view values of\n   *    any length.\n   * @param {string=} pattern Similar to `ngPattern` except that the attribute value is the actual string\n   *    that contains the regular expression body that will be converted to a regular expression\n   *    as in the ngPattern directive.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the ngModel value does not match\n   *    a RegExp found by evaluating the Angular expression given in the attribute value.\n   *    If the expression evaluates to a RegExp object then this is used directly.\n   *    If the expression is a string then it will be converted to a RegExp after wrapping it in `^` and `$`\n   *    characters. For instance, `\"abc\"` will be converted to `new RegExp('^abc$')`.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <example name=\"number-input-directive\" module=\"numberExample\">\n        <file name=\"index.html\">\n         <script>\n           angular.module('numberExample', [])\n             .controller('ExampleController', ['$scope', function($scope) {\n               $scope.example = {\n                 value: 12\n               };\n             }]);\n         </script>\n         <form name=\"myForm\" ng-controller=\"ExampleController\">\n           Number: <input type=\"number\" name=\"input\" ng-model=\"example.value\"\n                          min=\"0\" max=\"99\" required>\n           <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.input.$error.number\">\n             Not valid number!</span>\n           <tt>value = {{example.value}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n          </form>\n        </file>\n        <file name=\"protractor.js\" type=\"protractor\">\n          var value = element(by.binding('example.value'));\n          var valid = element(by.binding('myForm.input.$valid'));\n          var input = element(by.model('example.value'));\n\n          it('should initialize to model', function() {\n            expect(value.getText()).toContain('12');\n            expect(valid.getText()).toContain('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input.clear();\n            input.sendKeys('');\n            expect(value.getText()).toEqual('value =');\n            expect(valid.getText()).toContain('false');\n          });\n\n          it('should be invalid if over max', function() {\n            input.clear();\n            input.sendKeys('123');\n            expect(value.getText()).toEqual('value =');\n            expect(valid.getText()).toContain('false');\n          });\n        </file>\n      </example>\n   */\n  'number': numberInputType,\n\n\n  /**\n   * @ngdoc input\n   * @name input[url]\n   *\n   * @description\n   * Text input with URL validation. Sets the `url` validation error key if the content is not a\n   * valid URL.\n   *\n   * <div class=\"alert alert-warning\">\n   * **Note:** `input[url]` uses a regex to validate urls that is derived from the regex\n   * used in Chromium. If you need stricter validation, you can use `ng-pattern` or modify\n   * the built-in validators (see the {@link guide/forms Forms guide})\n   * </div>\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength. Setting the attribute to a negative or non-numeric value, allows view values of\n   *    any length.\n   * @param {string=} pattern Similar to `ngPattern` except that the attribute value is the actual string\n   *    that contains the regular expression body that will be converted to a regular expression\n   *    as in the ngPattern directive.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the ngModel value does not match\n   *    a RegExp found by evaluating the Angular expression given in the attribute value.\n   *    If the expression evaluates to a RegExp object then this is used directly.\n   *    If the expression is a string then it will be converted to a RegExp after wrapping it in `^` and `$`\n   *    characters. For instance, `\"abc\"` will be converted to `new RegExp('^abc$')`.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <example name=\"url-input-directive\" module=\"urlExample\">\n        <file name=\"index.html\">\n         <script>\n           angular.module('urlExample', [])\n             .controller('ExampleController', ['$scope', function($scope) {\n               $scope.url = {\n                 text: 'http://google.com'\n               };\n             }]);\n         </script>\n         <form name=\"myForm\" ng-controller=\"ExampleController\">\n           URL: <input type=\"url\" name=\"input\" ng-model=\"url.text\" required>\n           <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.input.$error.url\">\n             Not valid url!</span>\n           <tt>text = {{url.text}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n           <tt>myForm.$error.url = {{!!myForm.$error.url}}</tt><br/>\n          </form>\n        </file>\n        <file name=\"protractor.js\" type=\"protractor\">\n          var text = element(by.binding('url.text'));\n          var valid = element(by.binding('myForm.input.$valid'));\n          var input = element(by.model('url.text'));\n\n          it('should initialize to model', function() {\n            expect(text.getText()).toContain('http://google.com');\n            expect(valid.getText()).toContain('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input.clear();\n            input.sendKeys('');\n\n            expect(text.getText()).toEqual('text =');\n            expect(valid.getText()).toContain('false');\n          });\n\n          it('should be invalid if not url', function() {\n            input.clear();\n            input.sendKeys('box');\n\n            expect(valid.getText()).toContain('false');\n          });\n        </file>\n      </example>\n   */\n  'url': urlInputType,\n\n\n  /**\n   * @ngdoc input\n   * @name input[email]\n   *\n   * @description\n   * Text input with email validation. Sets the `email` validation error key if not a valid email\n   * address.\n   *\n   * <div class=\"alert alert-warning\">\n   * **Note:** `input[email]` uses a regex to validate email addresses that is derived from the regex\n   * used in Chromium. If you need stricter validation (e.g. requiring a top-level domain), you can\n   * use `ng-pattern` or modify the built-in validators (see the {@link guide/forms Forms guide})\n   * </div>\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength. Setting the attribute to a negative or non-numeric value, allows view values of\n   *    any length.\n   * @param {string=} pattern Similar to `ngPattern` except that the attribute value is the actual string\n   *    that contains the regular expression body that will be converted to a regular expression\n   *    as in the ngPattern directive.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the ngModel value does not match\n   *    a RegExp found by evaluating the Angular expression given in the attribute value.\n   *    If the expression evaluates to a RegExp object then this is used directly.\n   *    If the expression is a string then it will be converted to a RegExp after wrapping it in `^` and `$`\n   *    characters. For instance, `\"abc\"` will be converted to `new RegExp('^abc$')`.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <example name=\"email-input-directive\" module=\"emailExample\">\n        <file name=\"index.html\">\n         <script>\n           angular.module('emailExample', [])\n             .controller('ExampleController', ['$scope', function($scope) {\n               $scope.email = {\n                 text: 'me@example.com'\n               };\n             }]);\n         </script>\n           <form name=\"myForm\" ng-controller=\"ExampleController\">\n             Email: <input type=\"email\" name=\"input\" ng-model=\"email.text\" required>\n             <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n               Required!</span>\n             <span class=\"error\" ng-show=\"myForm.input.$error.email\">\n               Not valid email!</span>\n             <tt>text = {{email.text}}</tt><br/>\n             <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n             <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n             <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n             <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n             <tt>myForm.$error.email = {{!!myForm.$error.email}}</tt><br/>\n           </form>\n         </file>\n        <file name=\"protractor.js\" type=\"protractor\">\n          var text = element(by.binding('email.text'));\n          var valid = element(by.binding('myForm.input.$valid'));\n          var input = element(by.model('email.text'));\n\n          it('should initialize to model', function() {\n            expect(text.getText()).toContain('me@example.com');\n            expect(valid.getText()).toContain('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input.clear();\n            input.sendKeys('');\n            expect(text.getText()).toEqual('text =');\n            expect(valid.getText()).toContain('false');\n          });\n\n          it('should be invalid if not email', function() {\n            input.clear();\n            input.sendKeys('xxx');\n\n            expect(valid.getText()).toContain('false');\n          });\n        </file>\n      </example>\n   */\n  'email': emailInputType,\n\n\n  /**\n   * @ngdoc input\n   * @name input[radio]\n   *\n   * @description\n   * HTML radio button.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string} value The value to which the expression should be set when selected.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   * @param {string} ngValue Angular expression which sets the value to which the expression should\n   *    be set when selected.\n   *\n   * @example\n      <example name=\"radio-input-directive\" module=\"radioExample\">\n        <file name=\"index.html\">\n         <script>\n           angular.module('radioExample', [])\n             .controller('ExampleController', ['$scope', function($scope) {\n               $scope.color = {\n                 name: 'blue'\n               };\n               $scope.specialValue = {\n                 \"id\": \"12345\",\n                 \"value\": \"green\"\n               };\n             }]);\n         </script>\n         <form name=\"myForm\" ng-controller=\"ExampleController\">\n           <input type=\"radio\" ng-model=\"color.name\" value=\"red\">  Red <br/>\n           <input type=\"radio\" ng-model=\"color.name\" ng-value=\"specialValue\"> Green <br/>\n           <input type=\"radio\" ng-model=\"color.name\" value=\"blue\"> Blue <br/>\n           <tt>color = {{color.name | json}}</tt><br/>\n          </form>\n          Note that `ng-value=\"specialValue\"` sets radio item's value to be the value of `$scope.specialValue`.\n        </file>\n        <file name=\"protractor.js\" type=\"protractor\">\n          it('should change state', function() {\n            var color = element(by.binding('color.name'));\n\n            expect(color.getText()).toContain('blue');\n\n            element.all(by.model('color.name')).get(0).click();\n\n            expect(color.getText()).toContain('red');\n          });\n        </file>\n      </example>\n   */\n  'radio': radioInputType,\n\n\n  /**\n   * @ngdoc input\n   * @name input[checkbox]\n   *\n   * @description\n   * HTML checkbox.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {expression=} ngTrueValue The value to which the expression should be set when selected.\n   * @param {expression=} ngFalseValue The value to which the expression should be set when not selected.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <example name=\"checkbox-input-directive\" module=\"checkboxExample\">\n        <file name=\"index.html\">\n         <script>\n           angular.module('checkboxExample', [])\n             .controller('ExampleController', ['$scope', function($scope) {\n               $scope.checkboxModel = {\n                value1 : true,\n                value2 : 'YES'\n              };\n             }]);\n         </script>\n         <form name=\"myForm\" ng-controller=\"ExampleController\">\n           Value1: <input type=\"checkbox\" ng-model=\"checkboxModel.value1\"> <br/>\n           Value2: <input type=\"checkbox\" ng-model=\"checkboxModel.value2\"\n                          ng-true-value=\"'YES'\" ng-false-value=\"'NO'\"> <br/>\n           <tt>value1 = {{checkboxModel.value1}}</tt><br/>\n           <tt>value2 = {{checkboxModel.value2}}</tt><br/>\n          </form>\n        </file>\n        <file name=\"protractor.js\" type=\"protractor\">\n          it('should change state', function() {\n            var value1 = element(by.binding('checkboxModel.value1'));\n            var value2 = element(by.binding('checkboxModel.value2'));\n\n            expect(value1.getText()).toContain('true');\n            expect(value2.getText()).toContain('YES');\n\n            element(by.model('checkboxModel.value1')).click();\n            element(by.model('checkboxModel.value2')).click();\n\n            expect(value1.getText()).toContain('false');\n            expect(value2.getText()).toContain('NO');\n          });\n        </file>\n      </example>\n   */\n  'checkbox': checkboxInputType,\n\n  'hidden': noop,\n  'button': noop,\n  'submit': noop,\n  'reset': noop,\n  'file': noop\n};\n\nfunction stringBasedInputType(ctrl) {\n  ctrl.$formatters.push(function(value) {\n    return ctrl.$isEmpty(value) ? value : value.toString();\n  });\n}\n\nfunction textInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  baseInputType(scope, element, attr, ctrl, $sniffer, $browser);\n  stringBasedInputType(ctrl);\n}\n\nfunction baseInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  var type = lowercase(element[0].type);\n\n  // In composition mode, users are still inputing intermediate text buffer,\n  // hold the listener until composition is done.\n  // More about composition events: https://developer.mozilla.org/en-US/docs/Web/API/CompositionEvent\n  if (!$sniffer.android) {\n    var composing = false;\n\n    element.on('compositionstart', function(data) {\n      composing = true;\n    });\n\n    element.on('compositionend', function() {\n      composing = false;\n      listener();\n    });\n  }\n\n  var listener = function(ev) {\n    if (timeout) {\n      $browser.defer.cancel(timeout);\n      timeout = null;\n    }\n    if (composing) return;\n    var value = element.val(),\n        event = ev && ev.type;\n\n    // By default we will trim the value\n    // If the attribute ng-trim exists we will avoid trimming\n    // If input type is 'password', the value is never trimmed\n    if (type !== 'password' && (!attr.ngTrim || attr.ngTrim !== 'false')) {\n      value = trim(value);\n    }\n\n    // If a control is suffering from bad input (due to native validators), browsers discard its\n    // value, so it may be necessary to revalidate (by calling $setViewValue again) even if the\n    // control's value is the same empty value twice in a row.\n    if (ctrl.$viewValue !== value || (value === '' && ctrl.$$hasNativeValidators)) {\n      ctrl.$setViewValue(value, event);\n    }\n  };\n\n  // if the browser does support \"input\" event, we are fine - except on IE9 which doesn't fire the\n  // input event on backspace, delete or cut\n  if ($sniffer.hasEvent('input')) {\n    element.on('input', listener);\n  } else {\n    var timeout;\n\n    var deferListener = function(ev, input, origValue) {\n      if (!timeout) {\n        timeout = $browser.defer(function() {\n          timeout = null;\n          if (!input || input.value !== origValue) {\n            listener(ev);\n          }\n        });\n      }\n    };\n\n    element.on('keydown', function(event) {\n      var key = event.keyCode;\n\n      // ignore\n      //    command            modifiers                   arrows\n      if (key === 91 || (15 < key && key < 19) || (37 <= key && key <= 40)) return;\n\n      deferListener(event, this, this.value);\n    });\n\n    // if user modifies input value using context menu in IE, we need \"paste\" and \"cut\" events to catch it\n    if ($sniffer.hasEvent('paste')) {\n      element.on('paste cut', deferListener);\n    }\n  }\n\n  // if user paste into input using mouse on older browser\n  // or form autocomplete on newer browser, we need \"change\" event to catch it\n  element.on('change', listener);\n\n  ctrl.$render = function() {\n    element.val(ctrl.$isEmpty(ctrl.$viewValue) ? '' : ctrl.$viewValue);\n  };\n}\n\nfunction weekParser(isoWeek, existingDate) {\n  if (isDate(isoWeek)) {\n    return isoWeek;\n  }\n\n  if (isString(isoWeek)) {\n    WEEK_REGEXP.lastIndex = 0;\n    var parts = WEEK_REGEXP.exec(isoWeek);\n    if (parts) {\n      var year = +parts[1],\n          week = +parts[2],\n          hours = 0,\n          minutes = 0,\n          seconds = 0,\n          milliseconds = 0,\n          firstThurs = getFirstThursdayOfYear(year),\n          addDays = (week - 1) * 7;\n\n      if (existingDate) {\n        hours = existingDate.getHours();\n        minutes = existingDate.getMinutes();\n        seconds = existingDate.getSeconds();\n        milliseconds = existingDate.getMilliseconds();\n      }\n\n      return new Date(year, 0, firstThurs.getDate() + addDays, hours, minutes, seconds, milliseconds);\n    }\n  }\n\n  return NaN;\n}\n\nfunction createDateParser(regexp, mapping) {\n  return function(iso, date) {\n    var parts, map;\n\n    if (isDate(iso)) {\n      return iso;\n    }\n\n    if (isString(iso)) {\n      // When a date is JSON'ified to wraps itself inside of an extra\n      // set of double quotes. This makes the date parsing code unable\n      // to match the date string and parse it as a date.\n      if (iso.charAt(0) == '\"' && iso.charAt(iso.length - 1) == '\"') {\n        iso = iso.substring(1, iso.length - 1);\n      }\n      if (ISO_DATE_REGEXP.test(iso)) {\n        return new Date(iso);\n      }\n      regexp.lastIndex = 0;\n      parts = regexp.exec(iso);\n\n      if (parts) {\n        parts.shift();\n        if (date) {\n          map = {\n            yyyy: date.getFullYear(),\n            MM: date.getMonth() + 1,\n            dd: date.getDate(),\n            HH: date.getHours(),\n            mm: date.getMinutes(),\n            ss: date.getSeconds(),\n            sss: date.getMilliseconds() / 1000\n          };\n        } else {\n          map = { yyyy: 1970, MM: 1, dd: 1, HH: 0, mm: 0, ss: 0, sss: 0 };\n        }\n\n        forEach(parts, function(part, index) {\n          if (index < mapping.length) {\n            map[mapping[index]] = +part;\n          }\n        });\n        return new Date(map.yyyy, map.MM - 1, map.dd, map.HH, map.mm, map.ss || 0, map.sss * 1000 || 0);\n      }\n    }\n\n    return NaN;\n  };\n}\n\nfunction createDateInputType(type, regexp, parseDate, format) {\n  return function dynamicDateInputType(scope, element, attr, ctrl, $sniffer, $browser, $filter) {\n    badInputChecker(scope, element, attr, ctrl);\n    baseInputType(scope, element, attr, ctrl, $sniffer, $browser);\n    var timezone = ctrl && ctrl.$options && ctrl.$options.timezone;\n    var previousDate;\n\n    ctrl.$$parserName = type;\n    ctrl.$parsers.push(function(value) {\n      if (ctrl.$isEmpty(value)) return null;\n      if (regexp.test(value)) {\n        // Note: We cannot read ctrl.$modelValue, as there might be a different\n        // parser/formatter in the processing chain so that the model\n        // contains some different data format!\n        var parsedDate = parseDate(value, previousDate);\n        if (timezone === 'UTC') {\n          parsedDate.setMinutes(parsedDate.getMinutes() - parsedDate.getTimezoneOffset());\n        }\n        return parsedDate;\n      }\n      return undefined;\n    });\n\n    ctrl.$formatters.push(function(value) {\n      if (value && !isDate(value)) {\n        throw $ngModelMinErr('datefmt', 'Expected `{0}` to be a date', value);\n      }\n      if (isValidDate(value)) {\n        previousDate = value;\n        if (previousDate && timezone === 'UTC') {\n          var timezoneOffset = 60000 * previousDate.getTimezoneOffset();\n          previousDate = new Date(previousDate.getTime() + timezoneOffset);\n        }\n        return $filter('date')(value, format, timezone);\n      } else {\n        previousDate = null;\n        return '';\n      }\n    });\n\n    if (isDefined(attr.min) || attr.ngMin) {\n      var minVal;\n      ctrl.$validators.min = function(value) {\n        return !isValidDate(value) || isUndefined(minVal) || parseDate(value) >= minVal;\n      };\n      attr.$observe('min', function(val) {\n        minVal = parseObservedDateValue(val);\n        ctrl.$validate();\n      });\n    }\n\n    if (isDefined(attr.max) || attr.ngMax) {\n      var maxVal;\n      ctrl.$validators.max = function(value) {\n        return !isValidDate(value) || isUndefined(maxVal) || parseDate(value) <= maxVal;\n      };\n      attr.$observe('max', function(val) {\n        maxVal = parseObservedDateValue(val);\n        ctrl.$validate();\n      });\n    }\n\n    function isValidDate(value) {\n      // Invalid Date: getTime() returns NaN\n      return value && !(value.getTime && value.getTime() !== value.getTime());\n    }\n\n    function parseObservedDateValue(val) {\n      return isDefined(val) ? (isDate(val) ? val : parseDate(val)) : undefined;\n    }\n  };\n}\n\nfunction badInputChecker(scope, element, attr, ctrl) {\n  var node = element[0];\n  var nativeValidation = ctrl.$$hasNativeValidators = isObject(node.validity);\n  if (nativeValidation) {\n    ctrl.$parsers.push(function(value) {\n      var validity = element.prop(VALIDITY_STATE_PROPERTY) || {};\n      // Detect bug in FF35 for input[email] (https://bugzilla.mozilla.org/show_bug.cgi?id=1064430):\n      // - also sets validity.badInput (should only be validity.typeMismatch).\n      // - see http://www.whatwg.org/specs/web-apps/current-work/multipage/forms.html#e-mail-state-(type=email)\n      // - can ignore this case as we can still read out the erroneous email...\n      return validity.badInput && !validity.typeMismatch ? undefined : value;\n    });\n  }\n}\n\nfunction numberInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  badInputChecker(scope, element, attr, ctrl);\n  baseInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  ctrl.$$parserName = 'number';\n  ctrl.$parsers.push(function(value) {\n    if (ctrl.$isEmpty(value))      return null;\n    if (NUMBER_REGEXP.test(value)) return parseFloat(value);\n    return undefined;\n  });\n\n  ctrl.$formatters.push(function(value) {\n    if (!ctrl.$isEmpty(value)) {\n      if (!isNumber(value)) {\n        throw $ngModelMinErr('numfmt', 'Expected `{0}` to be a number', value);\n      }\n      value = value.toString();\n    }\n    return value;\n  });\n\n  if (attr.min || attr.ngMin) {\n    var minVal;\n    ctrl.$validators.min = function(value) {\n      return ctrl.$isEmpty(value) || isUndefined(minVal) || value >= minVal;\n    };\n\n    attr.$observe('min', function(val) {\n      if (isDefined(val) && !isNumber(val)) {\n        val = parseFloat(val, 10);\n      }\n      minVal = isNumber(val) && !isNaN(val) ? val : undefined;\n      // TODO(matsko): implement validateLater to reduce number of validations\n      ctrl.$validate();\n    });\n  }\n\n  if (attr.max || attr.ngMax) {\n    var maxVal;\n    ctrl.$validators.max = function(value) {\n      return ctrl.$isEmpty(value) || isUndefined(maxVal) || value <= maxVal;\n    };\n\n    attr.$observe('max', function(val) {\n      if (isDefined(val) && !isNumber(val)) {\n        val = parseFloat(val, 10);\n      }\n      maxVal = isNumber(val) && !isNaN(val) ? val : undefined;\n      // TODO(matsko): implement validateLater to reduce number of validations\n      ctrl.$validate();\n    });\n  }\n}\n\nfunction urlInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  // Note: no badInputChecker here by purpose as `url` is only a validation\n  // in browsers, i.e. we can always read out input.value even if it is not valid!\n  baseInputType(scope, element, attr, ctrl, $sniffer, $browser);\n  stringBasedInputType(ctrl);\n\n  ctrl.$$parserName = 'url';\n  ctrl.$validators.url = function(modelValue, viewValue) {\n    var value = modelValue || viewValue;\n    return ctrl.$isEmpty(value) || URL_REGEXP.test(value);\n  };\n}\n\nfunction emailInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  // Note: no badInputChecker here by purpose as `url` is only a validation\n  // in browsers, i.e. we can always read out input.value even if it is not valid!\n  baseInputType(scope, element, attr, ctrl, $sniffer, $browser);\n  stringBasedInputType(ctrl);\n\n  ctrl.$$parserName = 'email';\n  ctrl.$validators.email = function(modelValue, viewValue) {\n    var value = modelValue || viewValue;\n    return ctrl.$isEmpty(value) || EMAIL_REGEXP.test(value);\n  };\n}\n\nfunction radioInputType(scope, element, attr, ctrl) {\n  // make the name unique, if not defined\n  if (isUndefined(attr.name)) {\n    element.attr('name', nextUid());\n  }\n\n  var listener = function(ev) {\n    if (element[0].checked) {\n      ctrl.$setViewValue(attr.value, ev && ev.type);\n    }\n  };\n\n  element.on('click', listener);\n\n  ctrl.$render = function() {\n    var value = attr.value;\n    element[0].checked = (value == ctrl.$viewValue);\n  };\n\n  attr.$observe('value', ctrl.$render);\n}\n\nfunction parseConstantExpr($parse, context, name, expression, fallback) {\n  var parseFn;\n  if (isDefined(expression)) {\n    parseFn = $parse(expression);\n    if (!parseFn.constant) {\n      throw minErr('ngModel')('constexpr', 'Expected constant expression for `{0}`, but saw ' +\n                                   '`{1}`.', name, expression);\n    }\n    return parseFn(context);\n  }\n  return fallback;\n}\n\nfunction checkboxInputType(scope, element, attr, ctrl, $sniffer, $browser, $filter, $parse) {\n  var trueValue = parseConstantExpr($parse, scope, 'ngTrueValue', attr.ngTrueValue, true);\n  var falseValue = parseConstantExpr($parse, scope, 'ngFalseValue', attr.ngFalseValue, false);\n\n  var listener = function(ev) {\n    ctrl.$setViewValue(element[0].checked, ev && ev.type);\n  };\n\n  element.on('click', listener);\n\n  ctrl.$render = function() {\n    element[0].checked = ctrl.$viewValue;\n  };\n\n  // Override the standard `$isEmpty` because the $viewValue of an empty checkbox is always set to `false`\n  // This is because of the parser below, which compares the `$modelValue` with `trueValue` to convert\n  // it to a boolean.\n  ctrl.$isEmpty = function(value) {\n    return value === false;\n  };\n\n  ctrl.$formatters.push(function(value) {\n    return equals(value, trueValue);\n  });\n\n  ctrl.$parsers.push(function(value) {\n    return value ? trueValue : falseValue;\n  });\n}\n\n\n/**\n * @ngdoc directive\n * @name textarea\n * @restrict E\n *\n * @description\n * HTML textarea element control with angular data-binding. The data-binding and validation\n * properties of this element are exactly the same as those of the\n * {@link ng.directive:input input element}.\n *\n * @param {string} ngModel Assignable angular expression to data-bind to.\n * @param {string=} name Property name of the form under which the control is published.\n * @param {string=} required Sets `required` validation error key if the value is not entered.\n * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n *    `required` when you want to data-bind to the `required` attribute.\n * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n *    minlength.\n * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n *    maxlength. Setting the attribute to a negative or non-numeric value, allows view values of any\n *    length.\n * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n *    patterns defined as scope expressions.\n * @param {string=} ngChange Angular expression to be executed when input changes due to user\n *    interaction with the input element.\n * @param {boolean=} [ngTrim=true] If set to false Angular will not automatically trim the input.\n */\n\n\n/**\n * @ngdoc directive\n * @name input\n * @restrict E\n *\n * @description\n * HTML input element control. When used together with {@link ngModel `ngModel`}, it provides data-binding,\n * input state control, and validation.\n * Input control follows HTML5 input types and polyfills the HTML5 validation behavior for older browsers.\n *\n * <div class=\"alert alert-warning\">\n * **Note:** Not every feature offered is available for all input types.\n * Specifically, data binding and event handling via `ng-model` is unsupported for `input[file]`.\n * </div>\n *\n * @param {string} ngModel Assignable angular expression to data-bind to.\n * @param {string=} name Property name of the form under which the control is published.\n * @param {string=} required Sets `required` validation error key if the value is not entered.\n * @param {boolean=} ngRequired Sets `required` attribute if set to true\n * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n *    minlength.\n * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n *    maxlength. Setting the attribute to a negative or non-numeric value, allows view values of any\n *    length.\n * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n *    patterns defined as scope expressions.\n * @param {string=} ngChange Angular expression to be executed when input changes due to user\n *    interaction with the input element.\n * @param {boolean=} [ngTrim=true] If set to false Angular will not automatically trim the input.\n *    This parameter is ignored for input[type=password] controls, which will never trim the\n *    input.\n *\n * @example\n    <example name=\"input-directive\" module=\"inputExample\">\n      <file name=\"index.html\">\n       <script>\n          angular.module('inputExample', [])\n            .controller('ExampleController', ['$scope', function($scope) {\n              $scope.user = {name: 'guest', last: 'visitor'};\n            }]);\n       </script>\n       <div ng-controller=\"ExampleController\">\n         <form name=\"myForm\">\n           User name: <input type=\"text\" name=\"userName\" ng-model=\"user.name\" required>\n           <span class=\"error\" ng-show=\"myForm.userName.$error.required\">\n             Required!</span><br>\n           Last name: <input type=\"text\" name=\"lastName\" ng-model=\"user.last\"\n             ng-minlength=\"3\" ng-maxlength=\"10\">\n           <span class=\"error\" ng-show=\"myForm.lastName.$error.minlength\">\n             Too short!</span>\n           <span class=\"error\" ng-show=\"myForm.lastName.$error.maxlength\">\n             Too long!</span><br>\n         </form>\n         <hr>\n         <tt>user = {{user}}</tt><br/>\n         <tt>myForm.userName.$valid = {{myForm.userName.$valid}}</tt><br>\n         <tt>myForm.userName.$error = {{myForm.userName.$error}}</tt><br>\n         <tt>myForm.lastName.$valid = {{myForm.lastName.$valid}}</tt><br>\n         <tt>myForm.lastName.$error = {{myForm.lastName.$error}}</tt><br>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br>\n         <tt>myForm.$error.minlength = {{!!myForm.$error.minlength}}</tt><br>\n         <tt>myForm.$error.maxlength = {{!!myForm.$error.maxlength}}</tt><br>\n       </div>\n      </file>\n      <file name=\"protractor.js\" type=\"protractor\">\n        var user = element(by.exactBinding('user'));\n        var userNameValid = element(by.binding('myForm.userName.$valid'));\n        var lastNameValid = element(by.binding('myForm.lastName.$valid'));\n        var lastNameError = element(by.binding('myForm.lastName.$error'));\n        var formValid = element(by.binding('myForm.$valid'));\n        var userNameInput = element(by.model('user.name'));\n        var userLastInput = element(by.model('user.last'));\n\n        it('should initialize to model', function() {\n          expect(user.getText()).toContain('{\"name\":\"guest\",\"last\":\"visitor\"}');\n          expect(userNameValid.getText()).toContain('true');\n          expect(formValid.getText()).toContain('true');\n        });\n\n        it('should be invalid if empty when required', function() {\n          userNameInput.clear();\n          userNameInput.sendKeys('');\n\n          expect(user.getText()).toContain('{\"last\":\"visitor\"}');\n          expect(userNameValid.getText()).toContain('false');\n          expect(formValid.getText()).toContain('false');\n        });\n\n        it('should be valid if empty when min length is set', function() {\n          userLastInput.clear();\n          userLastInput.sendKeys('');\n\n          expect(user.getText()).toContain('{\"name\":\"guest\",\"last\":\"\"}');\n          expect(lastNameValid.getText()).toContain('true');\n          expect(formValid.getText()).toContain('true');\n        });\n\n        it('should be invalid if less than required min length', function() {\n          userLastInput.clear();\n          userLastInput.sendKeys('xx');\n\n          expect(user.getText()).toContain('{\"name\":\"guest\"}');\n          expect(lastNameValid.getText()).toContain('false');\n          expect(lastNameError.getText()).toContain('minlength');\n          expect(formValid.getText()).toContain('false');\n        });\n\n        it('should be invalid if longer than max length', function() {\n          userLastInput.clear();\n          userLastInput.sendKeys('some ridiculously long name');\n\n          expect(user.getText()).toContain('{\"name\":\"guest\"}');\n          expect(lastNameValid.getText()).toContain('false');\n          expect(lastNameError.getText()).toContain('maxlength');\n          expect(formValid.getText()).toContain('false');\n        });\n      </file>\n    </example>\n */\nvar inputDirective = ['$browser', '$sniffer', '$filter', '$parse',\n    function($browser, $sniffer, $filter, $parse) {\n  return {\n    restrict: 'E',\n    require: ['?ngModel'],\n    link: {\n      pre: function(scope, element, attr, ctrls) {\n        if (ctrls[0]) {\n          (inputType[lowercase(attr.type)] || inputType.text)(scope, element, attr, ctrls[0], $sniffer,\n                                                              $browser, $filter, $parse);\n        }\n      }\n    }\n  };\n}];\n\n\n\nvar CONSTANT_VALUE_REGEXP = /^(true|false|\\d+)$/;\n/**\n * @ngdoc directive\n * @name ngValue\n *\n * @description\n * Binds the given expression to the value of `<option>` or {@link input[radio] `input[radio]`},\n * so that when the element is selected, the {@link ngModel `ngModel`} of that element is set to\n * the bound value.\n *\n * `ngValue` is useful when dynamically generating lists of radio buttons using\n * {@link ngRepeat `ngRepeat`}, as shown below.\n *\n * Likewise, `ngValue` can be used to generate `<option>` elements for\n * the {@link select `select`} element. In that case however, only strings are supported\n * for the `value `attribute, so the resulting `ngModel` will always be a string.\n * Support for `select` models with non-string values is available via `ngOptions`.\n *\n * @element input\n * @param {string=} ngValue angular expression, whose value will be bound to the `value` attribute\n *   of the `input` element\n *\n * @example\n    <example name=\"ngValue-directive\" module=\"valueExample\">\n      <file name=\"index.html\">\n       <script>\n          angular.module('valueExample', [])\n            .controller('ExampleController', ['$scope', function($scope) {\n              $scope.names = ['pizza', 'unicorns', 'robots'];\n              $scope.my = { favorite: 'unicorns' };\n            }]);\n       </script>\n        <form ng-controller=\"ExampleController\">\n          <h2>Which is your favorite?</h2>\n            <label ng-repeat=\"name in names\" for=\"{{name}}\">\n              {{name}}\n              <input type=\"radio\"\n                     ng-model=\"my.favorite\"\n                     ng-value=\"name\"\n                     id=\"{{name}}\"\n                     name=\"favorite\">\n            </label>\n          <div>You chose {{my.favorite}}</div>\n        </form>\n      </file>\n      <file name=\"protractor.js\" type=\"protractor\">\n        var favorite = element(by.binding('my.favorite'));\n\n        it('should initialize to model', function() {\n          expect(favorite.getText()).toContain('unicorns');\n        });\n        it('should bind the values to the inputs', function() {\n          element.all(by.model('my.favorite')).get(0).click();\n          expect(favorite.getText()).toContain('pizza');\n        });\n      </file>\n    </example>\n */\nvar ngValueDirective = function() {\n  return {\n    restrict: 'A',\n    priority: 100,\n    compile: function(tpl, tplAttr) {\n      if (CONSTANT_VALUE_REGEXP.test(tplAttr.ngValue)) {\n        return function ngValueConstantLink(scope, elm, attr) {\n          attr.$set('value', scope.$eval(attr.ngValue));\n        };\n      } else {\n        return function ngValueLink(scope, elm, attr) {\n          scope.$watch(attr.ngValue, function valueWatchAction(value) {\n            attr.$set('value', value);\n          });\n        };\n      }\n    }\n  };\n};\n\n/**\n * @ngdoc directive\n * @name ngBind\n * @restrict AC\n *\n * @description\n * The `ngBind` attribute tells Angular to replace the text content of the specified HTML element\n * with the value of a given expression, and to update the text content when the value of that\n * expression changes.\n *\n * Typically, you don't use `ngBind` directly, but instead you use the double curly markup like\n * `{{ expression }}` which is similar but less verbose.\n *\n * It is preferable to use `ngBind` instead of `{{ expression }}` if a template is momentarily\n * displayed by the browser in its raw state before Angular compiles it. Since `ngBind` is an\n * element attribute, it makes the bindings invisible to the user while the page is loading.\n *\n * An alternative solution to this problem would be using the\n * {@link ng.directive:ngCloak ngCloak} directive.\n *\n *\n * @element ANY\n * @param {expression} ngBind {@link guide/expression Expression} to evaluate.\n *\n * @example\n * Enter a name in the Live Preview text box; the greeting below the text box changes instantly.\n   <example module=\"bindExample\">\n     <file name=\"index.html\">\n       <script>\n         angular.module('bindExample', [])\n           .controller('ExampleController', ['$scope', function($scope) {\n             $scope.name = 'Whirled';\n           }]);\n       </script>\n       <div ng-controller=\"ExampleController\">\n         Enter name: <input type=\"text\" ng-model=\"name\"><br>\n         Hello <span ng-bind=\"name\"></span>!\n       </div>\n     </file>\n     <file name=\"protractor.js\" type=\"protractor\">\n       it('should check ng-bind', function() {\n         var nameInput = element(by.model('name'));\n\n         expect(element(by.binding('name')).getText()).toBe('Whirled');\n         nameInput.clear();\n         nameInput.sendKeys('world');\n         expect(element(by.binding('name')).getText()).toBe('world');\n       });\n     </file>\n   </example>\n */\nvar ngBindDirective = ['$compile', function($compile) {\n  return {\n    restrict: 'AC',\n    compile: function ngBindCompile(templateElement) {\n      $compile.$$addBindingClass(templateElement);\n      return function ngBindLink(scope, element, attr) {\n        $compile.$$addBindingInfo(element, attr.ngBind);\n        element = element[0];\n        scope.$watch(attr.ngBind, function ngBindWatchAction(value) {\n          element.textContent = value === undefined ? '' : value;\n        });\n      };\n    }\n  };\n}];\n\n\n/**\n * @ngdoc directive\n * @name ngBindTemplate\n *\n * @description\n * The `ngBindTemplate` directive specifies that the element\n * text content should be replaced with the interpolation of the template\n * in the `ngBindTemplate` attribute.\n * Unlike `ngBind`, the `ngBindTemplate` can contain multiple `{{` `}}`\n * expressions. This directive is needed since some HTML elements\n * (such as TITLE and OPTION) cannot contain SPAN elements.\n *\n * @element ANY\n * @param {string} ngBindTemplate template of form\n *   <tt>{{</tt> <tt>expression</tt> <tt>}}</tt> to eval.\n *\n * @example\n * Try it here: enter text in text box and watch the greeting change.\n   <example module=\"bindExample\">\n     <file name=\"index.html\">\n       <script>\n         angular.module('bindExample', [])\n           .controller('ExampleController', ['$scope', function($scope) {\n             $scope.salutation = 'Hello';\n             $scope.name = 'World';\n           }]);\n       </script>\n       <div ng-controller=\"ExampleController\">\n        Salutation: <input type=\"text\" ng-model=\"salutation\"><br>\n        Name: <input type=\"text\" ng-model=\"name\"><br>\n        <pre ng-bind-template=\"{{salutation}} {{name}}!\"></pre>\n       </div>\n     </file>\n     <file name=\"protractor.js\" type=\"protractor\">\n       it('should check ng-bind', function() {\n         var salutationElem = element(by.binding('salutation'));\n         var salutationInput = element(by.model('salutation'));\n         var nameInput = element(by.model('name'));\n\n         expect(salutationElem.getText()).toBe('Hello World!');\n\n         salutationInput.clear();\n         salutationInput.sendKeys('Greetings');\n         nameInput.clear();\n         nameInput.sendKeys('user');\n\n         expect(salutationElem.getText()).toBe('Greetings user!');\n       });\n     </file>\n   </example>\n */\nvar ngBindTemplateDirective = ['$interpolate', '$compile', function($interpolate, $compile) {\n  return {\n    compile: function ngBindTemplateCompile(templateElement) {\n      $compile.$$addBindingClass(templateElement);\n      return function ngBindTemplateLink(scope, element, attr) {\n        var interpolateFn = $interpolate(element.attr(attr.$attr.ngBindTemplate));\n        $compile.$$addBindingInfo(element, interpolateFn.expressions);\n        element = element[0];\n        attr.$observe('ngBindTemplate', function(value) {\n          element.textContent = value === undefined ? '' : value;\n        });\n      };\n    }\n  };\n}];\n\n\n/**\n * @ngdoc directive\n * @name ngBindHtml\n *\n * @description\n * Evaluates the expression and inserts the resulting HTML into the element in a secure way. By default,\n * the resulting HTML content will be sanitized using the {@link ngSanitize.$sanitize $sanitize} service.\n * To utilize this functionality, ensure that `$sanitize` is available, for example, by including {@link\n * ngSanitize} in your module's dependencies (not in core Angular). In order to use {@link ngSanitize}\n * in your module's dependencies, you need to include \"angular-sanitize.js\" in your application.\n *\n * You may also bypass sanitization for values you know are safe. To do so, bind to\n * an explicitly trusted value via {@link ng.$sce#trustAsHtml $sce.trustAsHtml}.  See the example\n * under {@link ng.$sce#show-me-an-example-using-sce- Strict Contextual Escaping (SCE)}.\n *\n * Note: If a `$sanitize` service is unavailable and the bound value isn't explicitly trusted, you\n * will have an exception (instead of an exploit.)\n *\n * @element ANY\n * @param {expression} ngBindHtml {@link guide/expression Expression} to evaluate.\n *\n * @example\n\n   <example module=\"bindHtmlExample\" deps=\"angular-sanitize.js\">\n     <file name=\"index.html\">\n       <div ng-controller=\"ExampleController\">\n        <p ng-bind-html=\"myHTML\"></p>\n       </div>\n     </file>\n\n     <file name=\"script.js\">\n       angular.module('bindHtmlExample', ['ngSanitize'])\n         .controller('ExampleController', ['$scope', function($scope) {\n           $scope.myHTML =\n              'I am an <code>HTML</code>string with ' +\n              '<a href=\"#\">links!</a> and other <em>stuff</em>';\n         }]);\n     </file>\n\n     <file name=\"protractor.js\" type=\"protractor\">\n       it('should check ng-bind-html', function() {\n         expect(element(by.binding('myHTML')).getText()).toBe(\n             'I am an HTMLstring with links! and other stuff');\n       });\n     </file>\n   </example>\n */\nvar ngBindHtmlDirective = ['$sce', '$parse', '$compile', function($sce, $parse, $compile) {\n  return {\n    restrict: 'A',\n    compile: function ngBindHtmlCompile(tElement, tAttrs) {\n      var ngBindHtmlGetter = $parse(tAttrs.ngBindHtml);\n      var ngBindHtmlWatch = $parse(tAttrs.ngBindHtml, function getStringValue(value) {\n        return (value || '').toString();\n      });\n      $compile.$$addBindingClass(tElement);\n\n      return function ngBindHtmlLink(scope, element, attr) {\n        $compile.$$addBindingInfo(element, attr.ngBindHtml);\n\n        scope.$watch(ngBindHtmlWatch, function ngBindHtmlWatchAction() {\n          // we re-evaluate the expr because we want a TrustedValueHolderType\n          // for $sce, not a string\n          element.html($sce.getTrustedHtml(ngBindHtmlGetter(scope)) || '');\n        });\n      };\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ngChange\n *\n * @description\n * Evaluate the given expression when the user changes the input.\n * The expression is evaluated immediately, unlike the JavaScript onchange event\n * which only triggers at the end of a change (usually, when the user leaves the\n * form element or presses the return key).\n *\n * The `ngChange` expression is only evaluated when a change in the input value causes\n * a new value to be committed to the model.\n *\n * It will not be evaluated:\n * * if the value returned from the `$parsers` transformation pipeline has not changed\n * * if the input has continued to be invalid since the model will stay `null`\n * * if the model is changed programmatically and not by a change to the input value\n *\n *\n * Note, this directive requires `ngModel` to be present.\n *\n * @element input\n * @param {expression} ngChange {@link guide/expression Expression} to evaluate upon change\n * in input value.\n *\n * @example\n * <example name=\"ngChange-directive\" module=\"changeExample\">\n *   <file name=\"index.html\">\n *     <script>\n *       angular.module('changeExample', [])\n *         .controller('ExampleController', ['$scope', function($scope) {\n *           $scope.counter = 0;\n *           $scope.change = function() {\n *             $scope.counter++;\n *           };\n *         }]);\n *     </script>\n *     <div ng-controller=\"ExampleController\">\n *       <input type=\"checkbox\" ng-model=\"confirmed\" ng-change=\"change()\" id=\"ng-change-example1\" />\n *       <input type=\"checkbox\" ng-model=\"confirmed\" id=\"ng-change-example2\" />\n *       <label for=\"ng-change-example2\">Confirmed</label><br />\n *       <tt>debug = {{confirmed}}</tt><br/>\n *       <tt>counter = {{counter}}</tt><br/>\n *     </div>\n *   </file>\n *   <file name=\"protractor.js\" type=\"protractor\">\n *     var counter = element(by.binding('counter'));\n *     var debug = element(by.binding('confirmed'));\n *\n *     it('should evaluate the expression if changing from view', function() {\n *       expect(counter.getText()).toContain('0');\n *\n *       element(by.id('ng-change-example1')).click();\n *\n *       expect(counter.getText()).toContain('1');\n *       expect(debug.getText()).toContain('true');\n *     });\n *\n *     it('should not evaluate the expression if changing from model', function() {\n *       element(by.id('ng-change-example2')).click();\n\n *       expect(counter.getText()).toContain('0');\n *       expect(debug.getText()).toContain('true');\n *     });\n *   </file>\n * </example>\n */\nvar ngChangeDirective = valueFn({\n  restrict: 'A',\n  require: 'ngModel',\n  link: function(scope, element, attr, ctrl) {\n    ctrl.$viewChangeListeners.push(function() {\n      scope.$eval(attr.ngChange);\n    });\n  }\n});\n\nfunction classDirective(name, selector) {\n  name = 'ngClass' + name;\n  return ['$animate', function($animate) {\n    return {\n      restrict: 'AC',\n      link: function(scope, element, attr) {\n        var oldVal;\n\n        scope.$watch(attr[name], ngClassWatchAction, true);\n\n        attr.$observe('class', function(value) {\n          ngClassWatchAction(scope.$eval(attr[name]));\n        });\n\n\n        if (name !== 'ngClass') {\n          scope.$watch('$index', function($index, old$index) {\n            // jshint bitwise: false\n            var mod = $index & 1;\n            if (mod !== (old$index & 1)) {\n              var classes = arrayClasses(scope.$eval(attr[name]));\n              mod === selector ?\n                addClasses(classes) :\n                removeClasses(classes);\n            }\n          });\n        }\n\n        function addClasses(classes) {\n          var newClasses = digestClassCounts(classes, 1);\n          attr.$addClass(newClasses);\n        }\n\n        function removeClasses(classes) {\n          var newClasses = digestClassCounts(classes, -1);\n          attr.$removeClass(newClasses);\n        }\n\n        function digestClassCounts(classes, count) {\n          var classCounts = element.data('$classCounts') || {};\n          var classesToUpdate = [];\n          forEach(classes, function(className) {\n            if (count > 0 || classCounts[className]) {\n              classCounts[className] = (classCounts[className] || 0) + count;\n              if (classCounts[className] === +(count > 0)) {\n                classesToUpdate.push(className);\n              }\n            }\n          });\n          element.data('$classCounts', classCounts);\n          return classesToUpdate.join(' ');\n        }\n\n        function updateClasses(oldClasses, newClasses) {\n          var toAdd = arrayDifference(newClasses, oldClasses);\n          var toRemove = arrayDifference(oldClasses, newClasses);\n          toAdd = digestClassCounts(toAdd, 1);\n          toRemove = digestClassCounts(toRemove, -1);\n          if (toAdd && toAdd.length) {\n            $animate.addClass(element, toAdd);\n          }\n          if (toRemove && toRemove.length) {\n            $animate.removeClass(element, toRemove);\n          }\n        }\n\n        function ngClassWatchAction(newVal) {\n          if (selector === true || scope.$index % 2 === selector) {\n            var newClasses = arrayClasses(newVal || []);\n            if (!oldVal) {\n              addClasses(newClasses);\n            } else if (!equals(newVal,oldVal)) {\n              var oldClasses = arrayClasses(oldVal);\n              updateClasses(oldClasses, newClasses);\n            }\n          }\n          oldVal = shallowCopy(newVal);\n        }\n      }\n    };\n\n    function arrayDifference(tokens1, tokens2) {\n      var values = [];\n\n      outer:\n      for (var i = 0; i < tokens1.length; i++) {\n        var token = tokens1[i];\n        for (var j = 0; j < tokens2.length; j++) {\n          if (token == tokens2[j]) continue outer;\n        }\n        values.push(token);\n      }\n      return values;\n    }\n\n    function arrayClasses(classVal) {\n      if (isArray(classVal)) {\n        return classVal;\n      } else if (isString(classVal)) {\n        return classVal.split(' ');\n      } else if (isObject(classVal)) {\n        var classes = [];\n        forEach(classVal, function(v, k) {\n          if (v) {\n            classes = classes.concat(k.split(' '));\n          }\n        });\n        return classes;\n      }\n      return classVal;\n    }\n  }];\n}\n\n/**\n * @ngdoc directive\n * @name ngClass\n * @restrict AC\n *\n * @description\n * The `ngClass` directive allows you to dynamically set CSS classes on an HTML element by databinding\n * an expression that represents all classes to be added.\n *\n * The directive operates in three different ways, depending on which of three types the expression\n * evaluates to:\n *\n * 1. If the expression evaluates to a string, the string should be one or more space-delimited class\n * names.\n *\n * 2. If the expression evaluates to an array, each element of the array should be a string that is\n * one or more space-delimited class names.\n *\n * 3. If the expression evaluates to an object, then for each key-value pair of the\n * object with a truthy value the corresponding key is used as a class name.\n *\n * The directive won't add duplicate classes if a particular class was already set.\n *\n * When the expression changes, the previously added classes are removed and only then the\n * new classes are added.\n *\n * @animations\n * **add** - happens just before the class is applied to the elements\n *\n * **remove** - happens just before the class is removed from the element\n *\n * @element ANY\n * @param {expression} ngClass {@link guide/expression Expression} to eval. The result\n *   of the evaluation can be a string representing space delimited class\n *   names, an array, or a map of class names to boolean values. In the case of a map, the\n *   names of the properties whose values are truthy will be added as css classes to the\n *   element.\n *\n * @example Example that demonstrates basic bindings via ngClass directive.\n   <example>\n     <file name=\"index.html\">\n       <p ng-class=\"{strike: deleted, bold: important, red: error}\">Map Syntax Example</p>\n       <input type=\"checkbox\" ng-model=\"deleted\"> deleted (apply \"strike\" class)<br>\n       <input type=\"checkbox\" ng-model=\"important\"> important (apply \"bold\" class)<br>\n       <input type=\"checkbox\" ng-model=\"error\"> error (apply \"red\" class)\n       <hr>\n       <p ng-class=\"style\">Using String Syntax</p>\n       <input type=\"text\" ng-model=\"style\" placeholder=\"Type: bold strike red\">\n       <hr>\n       <p ng-class=\"[style1, style2, style3]\">Using Array Syntax</p>\n       <input ng-model=\"style1\" placeholder=\"Type: bold, strike or red\"><br>\n       <input ng-model=\"style2\" placeholder=\"Type: bold, strike or red\"><br>\n       <input ng-model=\"style3\" placeholder=\"Type: bold, strike or red\"><br>\n     </file>\n     <file name=\"style.css\">\n       .strike {\n         text-decoration: line-through;\n       }\n       .bold {\n           font-weight: bold;\n       }\n       .red {\n           color: red;\n       }\n     </file>\n     <file name=\"protractor.js\" type=\"protractor\">\n       var ps = element.all(by.css('p'));\n\n       it('should let you toggle the class', function() {\n\n         expect(ps.first().getAttribute('class')).not.toMatch(/bold/);\n         expect(ps.first().getAttribute('class')).not.toMatch(/red/);\n\n         element(by.model('important')).click();\n         expect(ps.first().getAttribute('class')).toMatch(/bold/);\n\n         element(by.model('error')).click();\n         expect(ps.first().getAttribute('class')).toMatch(/red/);\n       });\n\n       it('should let you toggle string example', function() {\n         expect(ps.get(1).getAttribute('class')).toBe('');\n         element(by.model('style')).clear();\n         element(by.model('style')).sendKeys('red');\n         expect(ps.get(1).getAttribute('class')).toBe('red');\n       });\n\n       it('array example should have 3 classes', function() {\n         expect(ps.last().getAttribute('class')).toBe('');\n         element(by.model('style1')).sendKeys('bold');\n         element(by.model('style2')).sendKeys('strike');\n         element(by.model('style3')).sendKeys('red');\n         expect(ps.last().getAttribute('class')).toBe('bold strike red');\n       });\n     </file>\n   </example>\n\n   ## Animations\n\n   The example below demonstrates how to perform animations using ngClass.\n\n   <example module=\"ngAnimate\" deps=\"angular-animate.js\" animations=\"true\">\n     <file name=\"index.html\">\n      <input id=\"setbtn\" type=\"button\" value=\"set\" ng-click=\"myVar='my-class'\">\n      <input id=\"clearbtn\" type=\"button\" value=\"clear\" ng-click=\"myVar=''\">\n      <br>\n      <span class=\"base-class\" ng-class=\"myVar\">Sample Text</span>\n     </file>\n     <file name=\"style.css\">\n       .base-class {\n         -webkit-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;\n         transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;\n       }\n\n       .base-class.my-class {\n         color: red;\n         font-size:3em;\n       }\n     </file>\n     <file name=\"protractor.js\" type=\"protractor\">\n       it('should check ng-class', function() {\n         expect(element(by.css('.base-class')).getAttribute('class')).not.\n           toMatch(/my-class/);\n\n         element(by.id('setbtn')).click();\n\n         expect(element(by.css('.base-class')).getAttribute('class')).\n           toMatch(/my-class/);\n\n         element(by.id('clearbtn')).click();\n\n         expect(element(by.css('.base-class')).getAttribute('class')).not.\n           toMatch(/my-class/);\n       });\n     </file>\n   </example>\n\n\n   ## ngClass and pre-existing CSS3 Transitions/Animations\n   The ngClass directive still supports CSS3 Transitions/Animations even if they do not follow the ngAnimate CSS naming structure.\n   Upon animation ngAnimate will apply supplementary CSS classes to track the start and end of an animation, but this will not hinder\n   any pre-existing CSS transitions already on the element. To get an idea of what happens during a class-based animation, be sure\n   to view the step by step details of {@link ng.$animate#addClass $animate.addClass} and\n   {@link ng.$animate#removeClass $animate.removeClass}.\n */\nvar ngClassDirective = classDirective('', true);\n\n/**\n * @ngdoc directive\n * @name ngClassOdd\n * @restrict AC\n *\n * @description\n * The `ngClassOdd` and `ngClassEven` directives work exactly as\n * {@link ng.directive:ngClass ngClass}, except they work in\n * conjunction with `ngRepeat` and take effect only on odd (even) rows.\n *\n * This directive can be applied only within the scope of an\n * {@link ng.directive:ngRepeat ngRepeat}.\n *\n * @element ANY\n * @param {expression} ngClassOdd {@link guide/expression Expression} to eval. The result\n *   of the evaluation can be a string representing space delimited class names or an array.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <ol ng-init=\"names=['John', 'Mary', 'Cate', 'Suz']\">\n          <li ng-repeat=\"name in names\">\n           <span ng-class-odd=\"'odd'\" ng-class-even=\"'even'\">\n             {{name}}\n           </span>\n          </li>\n        </ol>\n     </file>\n     <file name=\"style.css\">\n       .odd {\n         color: red;\n       }\n       .even {\n         color: blue;\n       }\n     </file>\n     <file name=\"protractor.js\" type=\"protractor\">\n       it('should check ng-class-odd and ng-class-even', function() {\n         expect(element(by.repeater('name in names').row(0).column('name')).getAttribute('class')).\n           toMatch(/odd/);\n         expect(element(by.repeater('name in names').row(1).column('name')).getAttribute('class')).\n           toMatch(/even/);\n       });\n     </file>\n   </example>\n */\nvar ngClassOddDirective = classDirective('Odd', 0);\n\n/**\n * @ngdoc directive\n * @name ngClassEven\n * @restrict AC\n *\n * @description\n * The `ngClassOdd` and `ngClassEven` directives work exactly as\n * {@link ng.directive:ngClass ngClass}, except they work in\n * conjunction with `ngRepeat` and take effect only on odd (even) rows.\n *\n * This directive can be applied only within the scope of an\n * {@link ng.directive:ngRepeat ngRepeat}.\n *\n * @element ANY\n * @param {expression} ngClassEven {@link guide/expression Expression} to eval. The\n *   result of the evaluation can be a string representing space delimited class names or an array.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <ol ng-init=\"names=['John', 'Mary', 'Cate', 'Suz']\">\n          <li ng-repeat=\"name in names\">\n           <span ng-class-odd=\"'odd'\" ng-class-even=\"'even'\">\n             {{name}} &nbsp; &nbsp; &nbsp;\n           </span>\n          </li>\n        </ol>\n     </file>\n     <file name=\"style.css\">\n       .odd {\n         color: red;\n       }\n       .even {\n         color: blue;\n       }\n     </file>\n     <file name=\"protractor.js\" type=\"protractor\">\n       it('should check ng-class-odd and ng-class-even', function() {\n         expect(element(by.repeater('name in names').row(0).column('name')).getAttribute('class')).\n           toMatch(/odd/);\n         expect(element(by.repeater('name in names').row(1).column('name')).getAttribute('class')).\n           toMatch(/even/);\n       });\n     </file>\n   </example>\n */\nvar ngClassEvenDirective = classDirective('Even', 1);\n\n/**\n * @ngdoc directive\n * @name ngCloak\n * @restrict AC\n *\n * @description\n * The `ngCloak` directive is used to prevent the Angular html template from being briefly\n * displayed by the browser in its raw (uncompiled) form while your application is loading. Use this\n * directive to avoid the undesirable flicker effect caused by the html template display.\n *\n * The directive can be applied to the `<body>` element, but the preferred usage is to apply\n * multiple `ngCloak` directives to small portions of the page to permit progressive rendering\n * of the browser view.\n *\n * `ngCloak` works in cooperation with the following css rule embedded within `angular.js` and\n * `angular.min.js`.\n * For CSP mode please add `angular-csp.css` to your html file (see {@link ng.directive:ngCsp ngCsp}).\n *\n * ```css\n * [ng\\:cloak], [ng-cloak], [data-ng-cloak], [x-ng-cloak], .ng-cloak, .x-ng-cloak {\n *   display: none !important;\n * }\n * ```\n *\n * When this css rule is loaded by the browser, all html elements (including their children) that\n * are tagged with the `ngCloak` directive are hidden. When Angular encounters this directive\n * during the compilation of the template it deletes the `ngCloak` element attribute, making\n * the compiled element visible.\n *\n * For the best result, the `angular.js` script must be loaded in the head section of the html\n * document; alternatively, the css rule above must be included in the external stylesheet of the\n * application.\n *\n * Legacy browsers, like IE7, do not provide attribute selector support (added in CSS 2.1) so they\n * cannot match the `[ng\\:cloak]` selector. To work around this limitation, you must add the css\n * class `ng-cloak` in addition to the `ngCloak` directive as shown in the example below.\n *\n * @element ANY\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <div id=\"template1\" ng-cloak>{{ 'hello' }}</div>\n        <div id=\"template2\" ng-cloak class=\"ng-cloak\">{{ 'hello IE7' }}</div>\n     </file>\n     <file name=\"protractor.js\" type=\"protractor\">\n       it('should remove the template directive and css class', function() {\n         expect($('#template1').getAttribute('ng-cloak')).\n           toBeNull();\n         expect($('#template2').getAttribute('ng-cloak')).\n           toBeNull();\n       });\n     </file>\n   </example>\n *\n */\nvar ngCloakDirective = ngDirective({\n  compile: function(element, attr) {\n    attr.$set('ngCloak', undefined);\n    element.removeClass('ng-cloak');\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ngController\n *\n * @description\n * The `ngController` directive attaches a controller class to the view. This is a key aspect of how angular\n * supports the principles behind the Model-View-Controller design pattern.\n *\n * MVC components in angular:\n *\n * * Model — Models are the properties of a scope; scopes are attached to the DOM where scope properties\n *   are accessed through bindings.\n * * View — The template (HTML with data bindings) that is rendered into the View.\n * * Controller — The `ngController` directive specifies a Controller class; the class contains business\n *   logic behind the application to decorate the scope with functions and values\n *\n * Note that you can also attach controllers to the DOM by declaring it in a route definition\n * via the {@link ngRoute.$route $route} service. A common mistake is to declare the controller\n * again using `ng-controller` in the template itself.  This will cause the controller to be attached\n * and executed twice.\n *\n * @element ANY\n * @scope\n * @priority 500\n * @param {expression} ngController Name of a constructor function registered with the current\n * {@link ng.$controllerProvider $controllerProvider} or an {@link guide/expression expression}\n * that on the current scope evaluates to a constructor function.\n *\n * The controller instance can be published into a scope property by specifying\n * `ng-controller=\"as propertyName\"`.\n *\n * If the current `$controllerProvider` is configured to use globals (via\n * {@link ng.$controllerProvider#allowGlobals `$controllerProvider.allowGlobals()` }), this may\n * also be the name of a globally accessible constructor function (not recommended).\n *\n * @example\n * Here is a simple form for editing user contact information. Adding, removing, clearing, and\n * greeting are methods declared on the controller (see source tab). These methods can\n * easily be called from the angular markup. Any changes to the data are automatically reflected\n * in the View without the need for a manual update.\n *\n * Two different declaration styles are included below:\n *\n * * one binds methods and properties directly onto the controller using `this`:\n * `ng-controller=\"SettingsController1 as settings\"`\n * * one injects `$scope` into the controller:\n * `ng-controller=\"SettingsController2\"`\n *\n * The second option is more common in the Angular community, and is generally used in boilerplates\n * and in this guide. However, there are advantages to binding properties directly to the controller\n * and avoiding scope.\n *\n * * Using `controller as` makes it obvious which controller you are accessing in the template when\n * multiple controllers apply to an element.\n * * If you are writing your controllers as classes you have easier access to the properties and\n * methods, which will appear on the scope, from inside the controller code.\n * * Since there is always a `.` in the bindings, you don't have to worry about prototypal\n * inheritance masking primitives.\n *\n * This example demonstrates the `controller as` syntax.\n *\n * <example name=\"ngControllerAs\" module=\"controllerAsExample\">\n *   <file name=\"index.html\">\n *    <div id=\"ctrl-as-exmpl\" ng-controller=\"SettingsController1 as settings\">\n *      Name: <input type=\"text\" ng-model=\"settings.name\"/>\n *      [ <a href=\"\" ng-click=\"settings.greet()\">greet</a> ]<br/>\n *      Contact:\n *      <ul>\n *        <li ng-repeat=\"contact in settings.contacts\">\n *          <select ng-model=\"contact.type\">\n *             <option>phone</option>\n *             <option>email</option>\n *          </select>\n *          <input type=\"text\" ng-model=\"contact.value\"/>\n *          [ <a href=\"\" ng-click=\"settings.clearContact(contact)\">clear</a>\n *          | <a href=\"\" ng-click=\"settings.removeContact(contact)\">X</a> ]\n *        </li>\n *        <li>[ <a href=\"\" ng-click=\"settings.addContact()\">add</a> ]</li>\n *     </ul>\n *    </div>\n *   </file>\n *   <file name=\"app.js\">\n *    angular.module('controllerAsExample', [])\n *      .controller('SettingsController1', SettingsController1);\n *\n *    function SettingsController1() {\n *      this.name = \"John Smith\";\n *      this.contacts = [\n *        {type: 'phone', value: '408 555 1212'},\n *        {type: 'email', value: 'john.smith@example.org'} ];\n *    }\n *\n *    SettingsController1.prototype.greet = function() {\n *      alert(this.name);\n *    };\n *\n *    SettingsController1.prototype.addContact = function() {\n *      this.contacts.push({type: 'email', value: 'yourname@example.org'});\n *    };\n *\n *    SettingsController1.prototype.removeContact = function(contactToRemove) {\n *     var index = this.contacts.indexOf(contactToRemove);\n *      this.contacts.splice(index, 1);\n *    };\n *\n *    SettingsController1.prototype.clearContact = function(contact) {\n *      contact.type = 'phone';\n *      contact.value = '';\n *    };\n *   </file>\n *   <file name=\"protractor.js\" type=\"protractor\">\n *     it('should check controller as', function() {\n *       var container = element(by.id('ctrl-as-exmpl'));\n *         expect(container.element(by.model('settings.name'))\n *           .getAttribute('value')).toBe('John Smith');\n *\n *       var firstRepeat =\n *           container.element(by.repeater('contact in settings.contacts').row(0));\n *       var secondRepeat =\n *           container.element(by.repeater('contact in settings.contacts').row(1));\n *\n *       expect(firstRepeat.element(by.model('contact.value')).getAttribute('value'))\n *           .toBe('408 555 1212');\n *\n *       expect(secondRepeat.element(by.model('contact.value')).getAttribute('value'))\n *           .toBe('john.smith@example.org');\n *\n *       firstRepeat.element(by.linkText('clear')).click();\n *\n *       expect(firstRepeat.element(by.model('contact.value')).getAttribute('value'))\n *           .toBe('');\n *\n *       container.element(by.linkText('add')).click();\n *\n *       expect(container.element(by.repeater('contact in settings.contacts').row(2))\n *           .element(by.model('contact.value'))\n *           .getAttribute('value'))\n *           .toBe('yourname@example.org');\n *     });\n *   </file>\n * </example>\n *\n * This example demonstrates the \"attach to `$scope`\" style of controller.\n *\n * <example name=\"ngController\" module=\"controllerExample\">\n *  <file name=\"index.html\">\n *   <div id=\"ctrl-exmpl\" ng-controller=\"SettingsController2\">\n *     Name: <input type=\"text\" ng-model=\"name\"/>\n *     [ <a href=\"\" ng-click=\"greet()\">greet</a> ]<br/>\n *     Contact:\n *     <ul>\n *       <li ng-repeat=\"contact in contacts\">\n *         <select ng-model=\"contact.type\">\n *            <option>phone</option>\n *            <option>email</option>\n *         </select>\n *         <input type=\"text\" ng-model=\"contact.value\"/>\n *         [ <a href=\"\" ng-click=\"clearContact(contact)\">clear</a>\n *         | <a href=\"\" ng-click=\"removeContact(contact)\">X</a> ]\n *       </li>\n *       <li>[ <a href=\"\" ng-click=\"addContact()\">add</a> ]</li>\n *    </ul>\n *   </div>\n *  </file>\n *  <file name=\"app.js\">\n *   angular.module('controllerExample', [])\n *     .controller('SettingsController2', ['$scope', SettingsController2]);\n *\n *   function SettingsController2($scope) {\n *     $scope.name = \"John Smith\";\n *     $scope.contacts = [\n *       {type:'phone', value:'408 555 1212'},\n *       {type:'email', value:'john.smith@example.org'} ];\n *\n *     $scope.greet = function() {\n *       alert($scope.name);\n *     };\n *\n *     $scope.addContact = function() {\n *       $scope.contacts.push({type:'email', value:'yourname@example.org'});\n *     };\n *\n *     $scope.removeContact = function(contactToRemove) {\n *       var index = $scope.contacts.indexOf(contactToRemove);\n *       $scope.contacts.splice(index, 1);\n *     };\n *\n *     $scope.clearContact = function(contact) {\n *       contact.type = 'phone';\n *       contact.value = '';\n *     };\n *   }\n *  </file>\n *  <file name=\"protractor.js\" type=\"protractor\">\n *    it('should check controller', function() {\n *      var container = element(by.id('ctrl-exmpl'));\n *\n *      expect(container.element(by.model('name'))\n *          .getAttribute('value')).toBe('John Smith');\n *\n *      var firstRepeat =\n *          container.element(by.repeater('contact in contacts').row(0));\n *      var secondRepeat =\n *          container.element(by.repeater('contact in contacts').row(1));\n *\n *      expect(firstRepeat.element(by.model('contact.value')).getAttribute('value'))\n *          .toBe('408 555 1212');\n *      expect(secondRepeat.element(by.model('contact.value')).getAttribute('value'))\n *          .toBe('john.smith@example.org');\n *\n *      firstRepeat.element(by.linkText('clear')).click();\n *\n *      expect(firstRepeat.element(by.model('contact.value')).getAttribute('value'))\n *          .toBe('');\n *\n *      container.element(by.linkText('add')).click();\n *\n *      expect(container.element(by.repeater('contact in contacts').row(2))\n *          .element(by.model('contact.value'))\n *          .getAttribute('value'))\n *          .toBe('yourname@example.org');\n *    });\n *  </file>\n *</example>\n\n */\nvar ngControllerDirective = [function() {\n  return {\n    restrict: 'A',\n    scope: true,\n    controller: '@',\n    priority: 500\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ngCsp\n *\n * @element html\n * @description\n * Enables [CSP (Content Security Policy)](https://developer.mozilla.org/en/Security/CSP) support.\n *\n * This is necessary when developing things like Google Chrome Extensions or Universal Windows Apps.\n *\n * CSP forbids apps to use `eval` or `Function(string)` generated functions (among other things).\n * For Angular to be CSP compatible there are only two things that we need to do differently:\n *\n * - don't use `Function` constructor to generate optimized value getters\n * - don't inject custom stylesheet into the document\n *\n * AngularJS uses `Function(string)` generated functions as a speed optimization. Applying the `ngCsp`\n * directive will cause Angular to use CSP compatibility mode. When this mode is on AngularJS will\n * evaluate all expressions up to 30% slower than in non-CSP mode, but no security violations will\n * be raised.\n *\n * CSP forbids JavaScript to inline stylesheet rules. In non CSP mode Angular automatically\n * includes some CSS rules (e.g. {@link ng.directive:ngCloak ngCloak}).\n * To make those directives work in CSP mode, include the `angular-csp.css` manually.\n *\n * Angular tries to autodetect if CSP is active and automatically turn on the CSP-safe mode. This\n * autodetection however triggers a CSP error to be logged in the console:\n *\n * ```\n * Refused to evaluate a string as JavaScript because 'unsafe-eval' is not an allowed source of\n * script in the following Content Security Policy directive: \"default-src 'self'\". Note that\n * 'script-src' was not explicitly set, so 'default-src' is used as a fallback.\n * ```\n *\n * This error is harmless but annoying. To prevent the error from showing up, put the `ngCsp`\n * directive on the root element of the application or on the `angular.js` script tag, whichever\n * appears first in the html document.\n *\n * *Note: This directive is only available in the `ng-csp` and `data-ng-csp` attribute form.*\n *\n * @example\n * This example shows how to apply the `ngCsp` directive to the `html` tag.\n   ```html\n     <!doctype html>\n     <html ng-app ng-csp>\n     ...\n     ...\n     </html>\n   ```\n  * @example\n      // Note: the suffix `.csp` in the example name triggers\n      // csp mode in our http server!\n      <example name=\"example.csp\" module=\"cspExample\" ng-csp=\"true\">\n        <file name=\"index.html\">\n          <div ng-controller=\"MainController as ctrl\">\n            <div>\n              <button ng-click=\"ctrl.inc()\" id=\"inc\">Increment</button>\n              <span id=\"counter\">\n                {{ctrl.counter}}\n              </span>\n            </div>\n\n            <div>\n              <button ng-click=\"ctrl.evil()\" id=\"evil\">Evil</button>\n              <span id=\"evilError\">\n                {{ctrl.evilError}}\n              </span>\n            </div>\n          </div>\n        </file>\n        <file name=\"script.js\">\n           angular.module('cspExample', [])\n             .controller('MainController', function() {\n                this.counter = 0;\n                this.inc = function() {\n                  this.counter++;\n                };\n                this.evil = function() {\n                  // jshint evil:true\n                  try {\n                    eval('1+2');\n                  } catch (e) {\n                    this.evilError = e.message;\n                  }\n                };\n              });\n        </file>\n        <file name=\"protractor.js\" type=\"protractor\">\n          var util, webdriver;\n\n          var incBtn = element(by.id('inc'));\n          var counter = element(by.id('counter'));\n          var evilBtn = element(by.id('evil'));\n          var evilError = element(by.id('evilError'));\n\n          function getAndClearSevereErrors() {\n            return browser.manage().logs().get('browser').then(function(browserLog) {\n              return browserLog.filter(function(logEntry) {\n                return logEntry.level.value > webdriver.logging.Level.WARNING.value;\n              });\n            });\n          }\n\n          function clearErrors() {\n            getAndClearSevereErrors();\n          }\n\n          function expectNoErrors() {\n            getAndClearSevereErrors().then(function(filteredLog) {\n              expect(filteredLog.length).toEqual(0);\n              if (filteredLog.length) {\n                console.log('browser console errors: ' + util.inspect(filteredLog));\n              }\n            });\n          }\n\n          function expectError(regex) {\n            getAndClearSevereErrors().then(function(filteredLog) {\n              var found = false;\n              filteredLog.forEach(function(log) {\n                if (log.message.match(regex)) {\n                  found = true;\n                }\n              });\n              if (!found) {\n                throw new Error('expected an error that matches ' + regex);\n              }\n            });\n          }\n\n          beforeEach(function() {\n            util = require('util');\n            webdriver = require('protractor/node_modules/selenium-webdriver');\n          });\n\n          // For now, we only test on Chrome,\n          // as Safari does not load the page with Protractor's injected scripts,\n          // and Firefox webdriver always disables content security policy (#6358)\n          if (browser.params.browser !== 'chrome') {\n            return;\n          }\n\n          it('should not report errors when the page is loaded', function() {\n            // clear errors so we are not dependent on previous tests\n            clearErrors();\n            // Need to reload the page as the page is already loaded when\n            // we come here\n            browser.driver.getCurrentUrl().then(function(url) {\n              browser.get(url);\n            });\n            expectNoErrors();\n          });\n\n          it('should evaluate expressions', function() {\n            expect(counter.getText()).toEqual('0');\n            incBtn.click();\n            expect(counter.getText()).toEqual('1');\n            expectNoErrors();\n          });\n\n          it('should throw and report an error when using \"eval\"', function() {\n            evilBtn.click();\n            expect(evilError.getText()).toMatch(/Content Security Policy/);\n            expectError(/Content Security Policy/);\n          });\n        </file>\n      </example>\n  */\n\n// ngCsp is not implemented as a proper directive any more, because we need it be processed while we\n// bootstrap the system (before $parse is instantiated), for this reason we just have\n// the csp.isActive() fn that looks for ng-csp attribute anywhere in the current doc\n\n/**\n * @ngdoc directive\n * @name ngClick\n *\n * @description\n * The ngClick directive allows you to specify custom behavior when\n * an element is clicked.\n *\n * @element ANY\n * @priority 0\n * @param {expression} ngClick {@link guide/expression Expression} to evaluate upon\n * click. ({@link guide/expression#-event- Event object is available as `$event`})\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n      <button ng-click=\"count = count + 1\" ng-init=\"count=0\">\n        Increment\n      </button>\n      <span>\n        count: {{count}}\n      </span>\n     </file>\n     <file name=\"protractor.js\" type=\"protractor\">\n       it('should check ng-click', function() {\n         expect(element(by.binding('count')).getText()).toMatch('0');\n         element(by.css('button')).click();\n         expect(element(by.binding('count')).getText()).toMatch('1');\n       });\n     </file>\n   </example>\n */\n/*\n * A collection of directives that allows creation of custom event handlers that are defined as\n * angular expressions and are compiled and executed within the current scope.\n */\nvar ngEventDirectives = {};\n\n// For events that might fire synchronously during DOM manipulation\n// we need to execute their event handlers asynchronously using $evalAsync,\n// so that they are not executed in an inconsistent state.\nvar forceAsyncEvents = {\n  'blur': true,\n  'focus': true\n};\nforEach(\n  'click dblclick mousedown mouseup mouseover mouseout mousemove mouseenter mouseleave keydown keyup keypress submit focus blur copy cut paste'.split(' '),\n  function(eventName) {\n    var directiveName = directiveNormalize('ng-' + eventName);\n    ngEventDirectives[directiveName] = ['$parse', '$rootScope', function($parse, $rootScope) {\n      return {\n        restrict: 'A',\n        compile: function($element, attr) {\n          // We expose the powerful $event object on the scope that provides access to the Window,\n          // etc. that isn't protected by the fast paths in $parse.  We explicitly request better\n          // checks at the cost of speed since event handler expressions are not executed as\n          // frequently as regular change detection.\n          var fn = $parse(attr[directiveName], /* interceptorFn */ null, /* expensiveChecks */ true);\n          return function ngEventHandler(scope, element) {\n            element.on(eventName, function(event) {\n              var callback = function() {\n                fn(scope, {$event:event});\n              };\n              if (forceAsyncEvents[eventName] && $rootScope.$$phase) {\n                scope.$evalAsync(callback);\n              } else {\n                scope.$apply(callback);\n              }\n            });\n          };\n        }\n      };\n    }];\n  }\n);\n\n/**\n * @ngdoc directive\n * @name ngDblclick\n *\n * @description\n * The `ngDblclick` directive allows you to specify custom behavior on a dblclick event.\n *\n * @element ANY\n * @priority 0\n * @param {expression} ngDblclick {@link guide/expression Expression} to evaluate upon\n * a dblclick. (The Event object is available as `$event`)\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n      <button ng-dblclick=\"count = count + 1\" ng-init=\"count=0\">\n        Increment (on double click)\n      </button>\n      count: {{count}}\n     </file>\n   </example>\n */\n\n\n/**\n * @ngdoc directive\n * @name ngMousedown\n *\n * @description\n * The ngMousedown directive allows you to specify custom behavior on mousedown event.\n *\n * @element ANY\n * @priority 0\n * @param {expression} ngMousedown {@link guide/expression Expression} to evaluate upon\n * mousedown. ({@link guide/expression#-event- Event object is available as `$event`})\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n      <button ng-mousedown=\"count = count + 1\" ng-init=\"count=0\">\n        Increment (on mouse down)\n      </button>\n      count: {{count}}\n     </file>\n   </example>\n */\n\n\n/**\n * @ngdoc directive\n * @name ngMouseup\n *\n * @description\n * Specify custom behavior on mouseup event.\n *\n * @element ANY\n * @priority 0\n * @param {expression} ngMouseup {@link guide/expression Expression} to evaluate upon\n * mouseup. ({@link guide/expression#-event- Event object is available as `$event`})\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n      <button ng-mouseup=\"count = count + 1\" ng-init=\"count=0\">\n        Increment (on mouse up)\n      </button>\n      count: {{count}}\n     </file>\n   </example>\n */\n\n/**\n * @ngdoc directive\n * @name ngMouseover\n *\n * @description\n * Specify custom behavior on mouseover event.\n *\n * @element ANY\n * @priority 0\n * @param {expression} ngMouseover {@link guide/expression Expression} to evaluate upon\n * mouseover. ({@link guide/expression#-event- Event object is available as `$event`})\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n      <button ng-mouseover=\"count = count + 1\" ng-init=\"count=0\">\n        Increment (when mouse is over)\n      </button>\n      count: {{count}}\n     </file>\n   </example>\n */\n\n\n/**\n * @ngdoc directive\n * @name ngMouseenter\n *\n * @description\n * Specify custom behavior on mouseenter event.\n *\n * @element ANY\n * @priority 0\n * @param {expression} ngMouseenter {@link guide/expression Expression} to evaluate upon\n * mouseenter. ({@link guide/expression#-event- Event object is available as `$event`})\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n      <button ng-mouseenter=\"count = count + 1\" ng-init=\"count=0\">\n        Increment (when mouse enters)\n      </button>\n      count: {{count}}\n     </file>\n   </example>\n */\n\n\n/**\n * @ngdoc directive\n * @name ngMouseleave\n *\n * @description\n * Specify custom behavior on mouseleave event.\n *\n * @element ANY\n * @priority 0\n * @param {expression} ngMouseleave {@link guide/expression Expression} to evaluate upon\n * mouseleave. ({@link guide/expression#-event- Event object is available as `$event`})\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n      <button ng-mouseleave=\"count = count + 1\" ng-init=\"count=0\">\n        Increment (when mouse leaves)\n      </button>\n      count: {{count}}\n     </file>\n   </example>\n */\n\n\n/**\n * @ngdoc directive\n * @name ngMousemove\n *\n * @description\n * Specify custom behavior on mousemove event.\n *\n * @element ANY\n * @priority 0\n * @param {expression} ngMousemove {@link guide/expression Expression} to evaluate upon\n * mousemove. ({@link guide/expression#-event- Event object is available as `$event`})\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n      <button ng-mousemove=\"count = count + 1\" ng-init=\"count=0\">\n        Increment (when mouse moves)\n      </button>\n      count: {{count}}\n     </file>\n   </example>\n */\n\n\n/**\n * @ngdoc directive\n * @name ngKeydown\n *\n * @description\n * Specify custom behavior on keydown event.\n *\n * @element ANY\n * @priority 0\n * @param {expression} ngKeydown {@link guide/expression Expression} to evaluate upon\n * keydown. (Event object is available as `$event` and can be interrogated for keyCode, altKey, etc.)\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n      <input ng-keydown=\"count = count + 1\" ng-init=\"count=0\">\n      key down count: {{count}}\n     </file>\n   </example>\n */\n\n\n/**\n * @ngdoc directive\n * @name ngKeyup\n *\n * @description\n * Specify custom behavior on keyup event.\n *\n * @element ANY\n * @priority 0\n * @param {expression} ngKeyup {@link guide/expression Expression} to evaluate upon\n * keyup. (Event object is available as `$event` and can be interrogated for keyCode, altKey, etc.)\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n       <p>Typing in the input box below updates the key count</p>\n       <input ng-keyup=\"count = count + 1\" ng-init=\"count=0\"> key up count: {{count}}\n\n       <p>Typing in the input box below updates the keycode</p>\n       <input ng-keyup=\"event=$event\">\n       <p>event keyCode: {{ event.keyCode }}</p>\n       <p>event altKey: {{ event.altKey }}</p>\n     </file>\n   </example>\n */\n\n\n/**\n * @ngdoc directive\n * @name ngKeypress\n *\n * @description\n * Specify custom behavior on keypress event.\n *\n * @element ANY\n * @param {expression} ngKeypress {@link guide/expression Expression} to evaluate upon\n * keypress. ({@link guide/expression#-event- Event object is available as `$event`}\n * and can be interrogated for keyCode, altKey, etc.)\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n      <input ng-keypress=\"count = count + 1\" ng-init=\"count=0\">\n      key press count: {{count}}\n     </file>\n   </example>\n */\n\n\n/**\n * @ngdoc directive\n * @name ngSubmit\n *\n * @description\n * Enables binding angular expressions to onsubmit events.\n *\n * Additionally it prevents the default action (which for form means sending the request to the\n * server and reloading the current page), but only if the form does not contain `action`,\n * `data-action`, or `x-action` attributes.\n *\n * <div class=\"alert alert-warning\">\n * **Warning:** Be careful not to cause \"double-submission\" by using both the `ngClick` and\n * `ngSubmit` handlers together. See the\n * {@link form#submitting-a-form-and-preventing-the-default-action `form` directive documentation}\n * for a detailed discussion of when `ngSubmit` may be triggered.\n * </div>\n *\n * @element form\n * @priority 0\n * @param {expression} ngSubmit {@link guide/expression Expression} to eval.\n * ({@link guide/expression#-event- Event object is available as `$event`})\n *\n * @example\n   <example module=\"submitExample\">\n     <file name=\"index.html\">\n      <script>\n        angular.module('submitExample', [])\n          .controller('ExampleController', ['$scope', function($scope) {\n            $scope.list = [];\n            $scope.text = 'hello';\n            $scope.submit = function() {\n              if ($scope.text) {\n                $scope.list.push(this.text);\n                $scope.text = '';\n              }\n            };\n          }]);\n      </script>\n      <form ng-submit=\"submit()\" ng-controller=\"ExampleController\">\n        Enter text and hit enter:\n        <input type=\"text\" ng-model=\"text\" name=\"text\" />\n        <input type=\"submit\" id=\"submit\" value=\"Submit\" />\n        <pre>list={{list}}</pre>\n      </form>\n     </file>\n     <file name=\"protractor.js\" type=\"protractor\">\n       it('should check ng-submit', function() {\n         expect(element(by.binding('list')).getText()).toBe('list=[]');\n         element(by.css('#submit')).click();\n         expect(element(by.binding('list')).getText()).toContain('hello');\n         expect(element(by.model('text')).getAttribute('value')).toBe('');\n       });\n       it('should ignore empty strings', function() {\n         expect(element(by.binding('list')).getText()).toBe('list=[]');\n         element(by.css('#submit')).click();\n         element(by.css('#submit')).click();\n         expect(element(by.binding('list')).getText()).toContain('hello');\n        });\n     </file>\n   </example>\n */\n\n/**\n * @ngdoc directive\n * @name ngFocus\n *\n * @description\n * Specify custom behavior on focus event.\n *\n * Note: As the `focus` event is executed synchronously when calling `input.focus()`\n * AngularJS executes the expression using `scope.$evalAsync` if the event is fired\n * during an `$apply` to ensure a consistent state.\n *\n * @element window, input, select, textarea, a\n * @priority 0\n * @param {expression} ngFocus {@link guide/expression Expression} to evaluate upon\n * focus. ({@link guide/expression#-event- Event object is available as `$event`})\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n/**\n * @ngdoc directive\n * @name ngBlur\n *\n * @description\n * Specify custom behavior on blur event.\n *\n * A [blur event](https://developer.mozilla.org/en-US/docs/Web/Events/blur) fires when\n * an element has lost focus.\n *\n * Note: As the `blur` event is executed synchronously also during DOM manipulations\n * (e.g. removing a focussed input),\n * AngularJS executes the expression using `scope.$evalAsync` if the event is fired\n * during an `$apply` to ensure a consistent state.\n *\n * @element window, input, select, textarea, a\n * @priority 0\n * @param {expression} ngBlur {@link guide/expression Expression} to evaluate upon\n * blur. ({@link guide/expression#-event- Event object is available as `$event`})\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n/**\n * @ngdoc directive\n * @name ngCopy\n *\n * @description\n * Specify custom behavior on copy event.\n *\n * @element window, input, select, textarea, a\n * @priority 0\n * @param {expression} ngCopy {@link guide/expression Expression} to evaluate upon\n * copy. ({@link guide/expression#-event- Event object is available as `$event`})\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n      <input ng-copy=\"copied=true\" ng-init=\"copied=false; value='copy me'\" ng-model=\"value\">\n      copied: {{copied}}\n     </file>\n   </example>\n */\n\n/**\n * @ngdoc directive\n * @name ngCut\n *\n * @description\n * Specify custom behavior on cut event.\n *\n * @element window, input, select, textarea, a\n * @priority 0\n * @param {expression} ngCut {@link guide/expression Expression} to evaluate upon\n * cut. ({@link guide/expression#-event- Event object is available as `$event`})\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n      <input ng-cut=\"cut=true\" ng-init=\"cut=false; value='cut me'\" ng-model=\"value\">\n      cut: {{cut}}\n     </file>\n   </example>\n */\n\n/**\n * @ngdoc directive\n * @name ngPaste\n *\n * @description\n * Specify custom behavior on paste event.\n *\n * @element window, input, select, textarea, a\n * @priority 0\n * @param {expression} ngPaste {@link guide/expression Expression} to evaluate upon\n * paste. ({@link guide/expression#-event- Event object is available as `$event`})\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n      <input ng-paste=\"paste=true\" ng-init=\"paste=false\" placeholder='paste here'>\n      pasted: {{paste}}\n     </file>\n   </example>\n */\n\n/**\n * @ngdoc directive\n * @name ngIf\n * @restrict A\n *\n * @description\n * The `ngIf` directive removes or recreates a portion of the DOM tree based on an\n * {expression}. If the expression assigned to `ngIf` evaluates to a false\n * value then the element is removed from the DOM, otherwise a clone of the\n * element is reinserted into the DOM.\n *\n * `ngIf` differs from `ngShow` and `ngHide` in that `ngIf` completely removes and recreates the\n * element in the DOM rather than changing its visibility via the `display` css property.  A common\n * case when this difference is significant is when using css selectors that rely on an element's\n * position within the DOM, such as the `:first-child` or `:last-child` pseudo-classes.\n *\n * Note that when an element is removed using `ngIf` its scope is destroyed and a new scope\n * is created when the element is restored.  The scope created within `ngIf` inherits from\n * its parent scope using\n * [prototypal inheritance](https://github.com/angular/angular.js/wiki/Understanding-Scopes#javascript-prototypal-inheritance).\n * An important implication of this is if `ngModel` is used within `ngIf` to bind to\n * a javascript primitive defined in the parent scope. In this case any modifications made to the\n * variable within the child scope will override (hide) the value in the parent scope.\n *\n * Also, `ngIf` recreates elements using their compiled state. An example of this behavior\n * is if an element's class attribute is directly modified after it's compiled, using something like\n * jQuery's `.addClass()` method, and the element is later removed. When `ngIf` recreates the element\n * the added class will be lost because the original compiled state is used to regenerate the element.\n *\n * Additionally, you can provide animations via the `ngAnimate` module to animate the `enter`\n * and `leave` effects.\n *\n * @animations\n * enter - happens just after the `ngIf` contents change and a new DOM element is created and injected into the `ngIf` container\n * leave - happens just before the `ngIf` contents are removed from the DOM\n *\n * @element ANY\n * @scope\n * @priority 600\n * @param {expression} ngIf If the {@link guide/expression expression} is falsy then\n *     the element is removed from the DOM tree. If it is truthy a copy of the compiled\n *     element is added to the DOM tree.\n *\n * @example\n  <example module=\"ngAnimate\" deps=\"angular-animate.js\" animations=\"true\">\n    <file name=\"index.html\">\n      Click me: <input type=\"checkbox\" ng-model=\"checked\" ng-init=\"checked=true\" /><br/>\n      Show when checked:\n      <span ng-if=\"checked\" class=\"animate-if\">\n        This is removed when the checkbox is unchecked.\n      </span>\n    </file>\n    <file name=\"animations.css\">\n      .animate-if {\n        background:white;\n        border:1px solid black;\n        padding:10px;\n      }\n\n      .animate-if.ng-enter, .animate-if.ng-leave {\n        -webkit-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;\n        transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;\n      }\n\n      .animate-if.ng-enter,\n      .animate-if.ng-leave.ng-leave-active {\n        opacity:0;\n      }\n\n      .animate-if.ng-leave,\n      .animate-if.ng-enter.ng-enter-active {\n        opacity:1;\n      }\n    </file>\n  </example>\n */\nvar ngIfDirective = ['$animate', function($animate) {\n  return {\n    multiElement: true,\n    transclude: 'element',\n    priority: 600,\n    terminal: true,\n    restrict: 'A',\n    $$tlb: true,\n    link: function($scope, $element, $attr, ctrl, $transclude) {\n        var block, childScope, previousElements;\n        $scope.$watch($attr.ngIf, function ngIfWatchAction(value) {\n\n          if (value) {\n            if (!childScope) {\n              $transclude(function(clone, newScope) {\n                childScope = newScope;\n                clone[clone.length++] = document.createComment(' end ngIf: ' + $attr.ngIf + ' ');\n                // Note: We only need the first/last node of the cloned nodes.\n                // However, we need to keep the reference to the jqlite wrapper as it might be changed later\n                // by a directive with templateUrl when its template arrives.\n                block = {\n                  clone: clone\n                };\n                $animate.enter(clone, $element.parent(), $element);\n              });\n            }\n          } else {\n            if (previousElements) {\n              previousElements.remove();\n              previousElements = null;\n            }\n            if (childScope) {\n              childScope.$destroy();\n              childScope = null;\n            }\n            if (block) {\n              previousElements = getBlockNodes(block.clone);\n              $animate.leave(previousElements).then(function() {\n                previousElements = null;\n              });\n              block = null;\n            }\n          }\n        });\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ngInclude\n * @restrict ECA\n *\n * @description\n * Fetches, compiles and includes an external HTML fragment.\n *\n * By default, the template URL is restricted to the same domain and protocol as the\n * application document. This is done by calling {@link $sce#getTrustedResourceUrl\n * $sce.getTrustedResourceUrl} on it. To load templates from other domains or protocols\n * you may either {@link ng.$sceDelegateProvider#resourceUrlWhitelist whitelist them} or\n * {@link $sce#trustAsResourceUrl wrap them} as trusted values. Refer to Angular's {@link\n * ng.$sce Strict Contextual Escaping}.\n *\n * In addition, the browser's\n * [Same Origin Policy](https://code.google.com/p/browsersec/wiki/Part2#Same-origin_policy_for_XMLHttpRequest)\n * and [Cross-Origin Resource Sharing (CORS)](http://www.w3.org/TR/cors/)\n * policy may further restrict whether the template is successfully loaded.\n * For example, `ngInclude` won't work for cross-domain requests on all browsers and for `file://`\n * access on some browsers.\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 *\n * @param {string} ngInclude|src angular expression evaluating to URL. If the source is a string constant,\n *                 make sure you wrap it in **single** quotes, e.g. `src=\"'myPartialTemplate.html'\"`.\n * @param {string=} onload Expression to evaluate when a new partial is loaded.\n *\n * @param {string=} autoscroll Whether `ngInclude` should call {@link ng.$anchorScroll\n *                  $anchorScroll} to scroll the viewport after the content is loaded.\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 expression evaluates to truthy value.\n *\n * @example\n  <example module=\"includeExample\" deps=\"angular-animate.js\" animations=\"true\">\n    <file name=\"index.html\">\n     <div ng-controller=\"ExampleController\">\n       <select ng-model=\"template\" ng-options=\"t.name for t in templates\">\n        <option value=\"\">(blank)</option>\n       </select>\n       url of the template: <code>{{template.url}}</code>\n       <hr/>\n       <div class=\"slide-animate-container\">\n         <div class=\"slide-animate\" ng-include=\"template.url\"></div>\n       </div>\n     </div>\n    </file>\n    <file name=\"script.js\">\n      angular.module('includeExample', ['ngAnimate'])\n        .controller('ExampleController', ['$scope', function($scope) {\n          $scope.templates =\n            [ { name: 'template1.html', url: 'template1.html'},\n              { name: 'template2.html', url: 'template2.html'} ];\n          $scope.template = $scope.templates[0];\n        }]);\n     </file>\n    <file name=\"template1.html\">\n      Content of template1.html\n    </file>\n    <file name=\"template2.html\">\n      Content of template2.html\n    </file>\n    <file name=\"animations.css\">\n      .slide-animate-container {\n        position:relative;\n        background:white;\n        border:1px solid black;\n        height:40px;\n        overflow:hidden;\n      }\n\n      .slide-animate {\n        padding:10px;\n      }\n\n      .slide-animate.ng-enter, .slide-animate.ng-leave {\n        -webkit-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;\n        transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;\n\n        position:absolute;\n        top:0;\n        left:0;\n        right:0;\n        bottom:0;\n        display:block;\n        padding:10px;\n      }\n\n      .slide-animate.ng-enter {\n        top:-50px;\n      }\n      .slide-animate.ng-enter.ng-enter-active {\n        top:0;\n      }\n\n      .slide-animate.ng-leave {\n        top:0;\n      }\n      .slide-animate.ng-leave.ng-leave-active {\n        top:50px;\n      }\n    </file>\n    <file name=\"protractor.js\" type=\"protractor\">\n      var templateSelect = element(by.model('template'));\n      var includeElem = element(by.css('[ng-include]'));\n\n      it('should load template1.html', function() {\n        expect(includeElem.getText()).toMatch(/Content of template1.html/);\n      });\n\n      it('should load template2.html', function() {\n        if (browser.params.browser == 'firefox') {\n          // Firefox can't handle using selects\n          // See https://github.com/angular/protractor/issues/480\n          return;\n        }\n        templateSelect.click();\n        templateSelect.all(by.css('option')).get(2).click();\n        expect(includeElem.getText()).toMatch(/Content of template2.html/);\n      });\n\n      it('should change to blank', function() {\n        if (browser.params.browser == 'firefox') {\n          // Firefox can't handle using selects\n          return;\n        }\n        templateSelect.click();\n        templateSelect.all(by.css('option')).get(0).click();\n        expect(includeElem.isPresent()).toBe(false);\n      });\n    </file>\n  </example>\n */\n\n\n/**\n * @ngdoc event\n * @name ngInclude#$includeContentRequested\n * @eventType emit on the scope ngInclude was declared in\n * @description\n * Emitted every time the ngInclude content is requested.\n *\n * @param {Object} angularEvent Synthetic event object.\n * @param {String} src URL of content to load.\n */\n\n\n/**\n * @ngdoc event\n * @name ngInclude#$includeContentLoaded\n * @eventType emit on the current ngInclude scope\n * @description\n * Emitted every time the ngInclude content is reloaded.\n *\n * @param {Object} angularEvent Synthetic event object.\n * @param {String} src URL of content to load.\n */\n\n\n/**\n * @ngdoc event\n * @name ngInclude#$includeContentError\n * @eventType emit on the scope ngInclude was declared in\n * @description\n * Emitted when a template HTTP request yields an erroneous response (status < 200 || status > 299)\n *\n * @param {Object} angularEvent Synthetic event object.\n * @param {String} src URL of content to load.\n */\nvar ngIncludeDirective = ['$templateRequest', '$anchorScroll', '$animate', '$sce',\n                  function($templateRequest,   $anchorScroll,   $animate,   $sce) {\n  return {\n    restrict: 'ECA',\n    priority: 400,\n    terminal: true,\n    transclude: 'element',\n    controller: angular.noop,\n    compile: function(element, attr) {\n      var srcExp = attr.ngInclude || attr.src,\n          onloadExp = attr.onload || '',\n          autoScrollExp = attr.autoscroll;\n\n      return function(scope, $element, $attr, ctrl, $transclude) {\n        var changeCounter = 0,\n            currentScope,\n            previousElement,\n            currentElement;\n\n        var cleanupLastIncludeContent = function() {\n          if (previousElement) {\n            previousElement.remove();\n            previousElement = null;\n          }\n          if (currentScope) {\n            currentScope.$destroy();\n            currentScope = null;\n          }\n          if (currentElement) {\n            $animate.leave(currentElement).then(function() {\n              previousElement = null;\n            });\n            previousElement = currentElement;\n            currentElement = null;\n          }\n        };\n\n        scope.$watch($sce.parseAsResourceUrl(srcExp), function ngIncludeWatchAction(src) {\n          var afterAnimation = function() {\n            if (isDefined(autoScrollExp) && (!autoScrollExp || scope.$eval(autoScrollExp))) {\n              $anchorScroll();\n            }\n          };\n          var thisChangeId = ++changeCounter;\n\n          if (src) {\n            //set the 2nd param to true to ignore the template request error so that the inner\n            //contents and scope can be cleaned up.\n            $templateRequest(src, true).then(function(response) {\n              if (thisChangeId !== changeCounter) return;\n              var newScope = scope.$new();\n              ctrl.template = response;\n\n              // Note: This will also link all children of ng-include that were contained in the original\n              // html. If that content contains controllers, ... they could pollute/change the scope.\n              // However, using ng-include 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                cleanupLastIncludeContent();\n                $animate.enter(clone, null, $element).then(afterAnimation);\n              });\n\n              currentScope = newScope;\n              currentElement = clone;\n\n              currentScope.$emit('$includeContentLoaded', src);\n              scope.$eval(onloadExp);\n            }, function() {\n              if (thisChangeId === changeCounter) {\n                cleanupLastIncludeContent();\n                scope.$emit('$includeContentError', src);\n              }\n            });\n            scope.$emit('$includeContentRequested', src);\n          } else {\n            cleanupLastIncludeContent();\n            ctrl.template = null;\n          }\n        });\n      };\n    }\n  };\n}];\n\n// This directive is called during the $transclude call of the first `ngInclude` 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 ngInclude\n// is called.\nvar ngIncludeFillContentDirective = ['$compile',\n  function($compile) {\n    return {\n      restrict: 'ECA',\n      priority: -400,\n      require: 'ngInclude',\n      link: function(scope, $element, $attr, ctrl) {\n        if (/SVG/.test($element[0].toString())) {\n          // WebKit: https://bugs.webkit.org/show_bug.cgi?id=135698 --- SVG elements do not\n          // support innerHTML, so detect this here and try to generate the contents\n          // specially.\n          $element.empty();\n          $compile(jqLiteBuildFragment(ctrl.template, document).childNodes)(scope,\n              function namespaceAdaptedClone(clone) {\n            $element.append(clone);\n          }, {futureParentElement: $element});\n          return;\n        }\n\n        $element.html(ctrl.template);\n        $compile($element.contents())(scope);\n      }\n    };\n  }];\n\n/**\n * @ngdoc directive\n * @name ngInit\n * @restrict AC\n *\n * @description\n * The `ngInit` directive allows you to evaluate an expression in the\n * current scope.\n *\n * <div class=\"alert alert-error\">\n * The only appropriate use of `ngInit` is for aliasing special properties of\n * {@link ng.directive:ngRepeat `ngRepeat`}, as seen in the demo below. Besides this case, you\n * should use {@link guide/controller controllers} rather than `ngInit`\n * to initialize values on a scope.\n * </div>\n * <div class=\"alert alert-warning\">\n * **Note**: If you have assignment in `ngInit` along with {@link ng.$filter `$filter`}, make\n * sure you have parenthesis for correct precedence:\n * <pre class=\"prettyprint\">\n * `<div ng-init=\"test1 = (data | orderBy:'name')\"></div>`\n * </pre>\n * </div>\n *\n * @priority 450\n *\n * @element ANY\n * @param {expression} ngInit {@link guide/expression Expression} to eval.\n *\n * @example\n   <example module=\"initExample\">\n     <file name=\"index.html\">\n   <script>\n     angular.module('initExample', [])\n       .controller('ExampleController', ['$scope', function($scope) {\n         $scope.list = [['a', 'b'], ['c', 'd']];\n       }]);\n   </script>\n   <div ng-controller=\"ExampleController\">\n     <div ng-repeat=\"innerList in list\" ng-init=\"outerIndex = $index\">\n       <div ng-repeat=\"value in innerList\" ng-init=\"innerIndex = $index\">\n          <span class=\"example-init\">list[ {{outerIndex}} ][ {{innerIndex}} ] = {{value}};</span>\n       </div>\n     </div>\n   </div>\n     </file>\n     <file name=\"protractor.js\" type=\"protractor\">\n       it('should alias index positions', function() {\n         var elements = element.all(by.css('.example-init'));\n         expect(elements.get(0).getText()).toBe('list[ 0 ][ 0 ] = a;');\n         expect(elements.get(1).getText()).toBe('list[ 0 ][ 1 ] = b;');\n         expect(elements.get(2).getText()).toBe('list[ 1 ][ 0 ] = c;');\n         expect(elements.get(3).getText()).toBe('list[ 1 ][ 1 ] = d;');\n       });\n     </file>\n   </example>\n */\nvar ngInitDirective = ngDirective({\n  priority: 450,\n  compile: function() {\n    return {\n      pre: function(scope, element, attrs) {\n        scope.$eval(attrs.ngInit);\n      }\n    };\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ngList\n *\n * @description\n * Text input that converts between a delimited string and an array of strings. The default\n * delimiter is a comma followed by a space - equivalent to `ng-list=\", \"`. You can specify a custom\n * delimiter as the value of the `ngList` attribute - for example, `ng-list=\" | \"`.\n *\n * The behaviour of the directive is affected by the use of the `ngTrim` attribute.\n * * If `ngTrim` is set to `\"false\"` then whitespace around both the separator and each\n *   list item is respected. This implies that the user of the directive is responsible for\n *   dealing with whitespace but also allows you to use whitespace as a delimiter, such as a\n *   tab or newline character.\n * * Otherwise whitespace around the delimiter is ignored when splitting (although it is respected\n *   when joining the list items back together) and whitespace around each list item is stripped\n *   before it is added to the model.\n *\n * ### Example with Validation\n *\n * <example name=\"ngList-directive\" module=\"listExample\">\n *   <file name=\"app.js\">\n *      angular.module('listExample', [])\n *        .controller('ExampleController', ['$scope', function($scope) {\n *          $scope.names = ['morpheus', 'neo', 'trinity'];\n *        }]);\n *   </file>\n *   <file name=\"index.html\">\n *    <form name=\"myForm\" ng-controller=\"ExampleController\">\n *      List: <input name=\"namesInput\" ng-model=\"names\" ng-list required>\n *      <span class=\"error\" ng-show=\"myForm.namesInput.$error.required\">\n *        Required!</span>\n *      <br>\n *      <tt>names = {{names}}</tt><br/>\n *      <tt>myForm.namesInput.$valid = {{myForm.namesInput.$valid}}</tt><br/>\n *      <tt>myForm.namesInput.$error = {{myForm.namesInput.$error}}</tt><br/>\n *      <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n *      <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n *     </form>\n *   </file>\n *   <file name=\"protractor.js\" type=\"protractor\">\n *     var listInput = element(by.model('names'));\n *     var names = element(by.exactBinding('names'));\n *     var valid = element(by.binding('myForm.namesInput.$valid'));\n *     var error = element(by.css('span.error'));\n *\n *     it('should initialize to model', function() {\n *       expect(names.getText()).toContain('[\"morpheus\",\"neo\",\"trinity\"]');\n *       expect(valid.getText()).toContain('true');\n *       expect(error.getCssValue('display')).toBe('none');\n *     });\n *\n *     it('should be invalid if empty', function() {\n *       listInput.clear();\n *       listInput.sendKeys('');\n *\n *       expect(names.getText()).toContain('');\n *       expect(valid.getText()).toContain('false');\n *       expect(error.getCssValue('display')).not.toBe('none');\n *     });\n *   </file>\n * </example>\n *\n * ### Example - splitting on whitespace\n * <example name=\"ngList-directive-newlines\">\n *   <file name=\"index.html\">\n *    <textarea ng-model=\"list\" ng-list=\"&#10;\" ng-trim=\"false\"></textarea>\n *    <pre>{{ list | json }}</pre>\n *   </file>\n *   <file name=\"protractor.js\" type=\"protractor\">\n *     it(\"should split the text by newlines\", function() {\n *       var listInput = element(by.model('list'));\n *       var output = element(by.binding('list | json'));\n *       listInput.sendKeys('abc\\ndef\\nghi');\n *       expect(output.getText()).toContain('[\\n  \"abc\",\\n  \"def\",\\n  \"ghi\"\\n]');\n *     });\n *   </file>\n * </example>\n *\n * @element input\n * @param {string=} ngList optional delimiter that should be used to split the value.\n */\nvar ngListDirective = function() {\n  return {\n    restrict: 'A',\n    priority: 100,\n    require: 'ngModel',\n    link: function(scope, element, attr, ctrl) {\n      // We want to control whitespace trimming so we use this convoluted approach\n      // to access the ngList attribute, which doesn't pre-trim the attribute\n      var ngList = element.attr(attr.$attr.ngList) || ', ';\n      var trimValues = attr.ngTrim !== 'false';\n      var separator = trimValues ? trim(ngList) : ngList;\n\n      var parse = function(viewValue) {\n        // If the viewValue is invalid (say required but empty) it will be `undefined`\n        if (isUndefined(viewValue)) return;\n\n        var list = [];\n\n        if (viewValue) {\n          forEach(viewValue.split(separator), function(value) {\n            if (value) list.push(trimValues ? trim(value) : value);\n          });\n        }\n\n        return list;\n      };\n\n      ctrl.$parsers.push(parse);\n      ctrl.$formatters.push(function(value) {\n        if (isArray(value)) {\n          return value.join(ngList);\n        }\n\n        return undefined;\n      });\n\n      // Override the standard $isEmpty because an empty array means the input is empty.\n      ctrl.$isEmpty = function(value) {\n        return !value || !value.length;\n      };\n    }\n  };\n};\n\n/* global VALID_CLASS: true,\n  INVALID_CLASS: true,\n  PRISTINE_CLASS: true,\n  DIRTY_CLASS: true,\n  UNTOUCHED_CLASS: true,\n  TOUCHED_CLASS: true,\n*/\n\nvar VALID_CLASS = 'ng-valid',\n    INVALID_CLASS = 'ng-invalid',\n    PRISTINE_CLASS = 'ng-pristine',\n    DIRTY_CLASS = 'ng-dirty',\n    UNTOUCHED_CLASS = 'ng-untouched',\n    TOUCHED_CLASS = 'ng-touched',\n    PENDING_CLASS = 'ng-pending';\n\n\nvar $ngModelMinErr = new minErr('ngModel');\n\n/**\n * @ngdoc type\n * @name ngModel.NgModelController\n *\n * @property {string} $viewValue Actual string value in the view.\n * @property {*} $modelValue The value in the model that the control is bound to.\n * @property {Array.<Function>} $parsers Array of functions to execute, as a pipeline, whenever\n       the control reads value from the DOM. The functions are called in array order, each passing\n       its return value through to the next. The last return value is forwarded to the\n       {@link ngModel.NgModelController#$validators `$validators`} collection.\n\nParsers are used to sanitize / convert the {@link ngModel.NgModelController#$viewValue\n`$viewValue`}.\n\nReturning `undefined` from a parser means a parse error occurred. In that case,\nno {@link ngModel.NgModelController#$validators `$validators`} will run and the `ngModel`\nwill be set to `undefined` unless {@link ngModelOptions `ngModelOptions.allowInvalid`}\nis set to `true`. The parse error is stored in `ngModel.$error.parse`.\n\n *\n * @property {Array.<Function>} $formatters Array of functions to execute, as a pipeline, whenever\n       the model value changes. The functions are called in reverse array order, each passing the value through to the\n       next. The last return value is used as the actual DOM value.\n       Used to format / convert values for display in the control.\n * ```js\n * function formatter(value) {\n *   if (value) {\n *     return value.toUpperCase();\n *   }\n * }\n * ngModel.$formatters.push(formatter);\n * ```\n *\n * @property {Object.<string, function>} $validators A collection of validators that are applied\n *      whenever the model value changes. The key value within the object refers to the name of the\n *      validator while the function refers to the validation operation. The validation operation is\n *      provided with the model value as an argument and must return a true or false value depending\n *      on the response of that validation.\n *\n * ```js\n * ngModel.$validators.validCharacters = function(modelValue, viewValue) {\n *   var value = modelValue || viewValue;\n *   return /[0-9]+/.test(value) &&\n *          /[a-z]+/.test(value) &&\n *          /[A-Z]+/.test(value) &&\n *          /\\W+/.test(value);\n * };\n * ```\n *\n * @property {Object.<string, function>} $asyncValidators A collection of validations that are expected to\n *      perform an asynchronous validation (e.g. a HTTP request). The validation function that is provided\n *      is expected to return a promise when it is run during the model validation process. Once the promise\n *      is delivered then the validation status will be set to true when fulfilled and false when rejected.\n *      When the asynchronous validators are triggered, each of the validators will run in parallel and the model\n *      value will only be updated once all validators have been fulfilled. As long as an asynchronous validator\n *      is unfulfilled, its key will be added to the controllers `$pending` property. Also, all asynchronous validators\n *      will only run once all synchronous validators have passed.\n *\n * Please note that if $http is used then it is important that the server returns a success HTTP response code\n * in order to fulfill the validation and a status level of `4xx` in order to reject the validation.\n *\n * ```js\n * ngModel.$asyncValidators.uniqueUsername = function(modelValue, viewValue) {\n *   var value = modelValue || viewValue;\n *\n *   // Lookup user by username\n *   return $http.get('/api/users/' + value).\n *      then(function resolved() {\n *        //username exists, this means validation fails\n *        return $q.reject('exists');\n *      }, function rejected() {\n *        //username does not exist, therefore this validation passes\n *        return true;\n *      });\n * };\n * ```\n *\n * @property {Array.<Function>} $viewChangeListeners Array of functions to execute whenever the\n *     view value has changed. It is called with no arguments, and its return value is ignored.\n *     This can be used in place of additional $watches against the model value.\n *\n * @property {Object} $error An object hash with all failing validator ids as keys.\n * @property {Object} $pending An object hash with all pending validator ids as keys.\n *\n * @property {boolean} $untouched True if control has not lost focus yet.\n * @property {boolean} $touched True if control has lost focus.\n * @property {boolean} $pristine True if user has not interacted with the control yet.\n * @property {boolean} $dirty True if user has already interacted with the control.\n * @property {boolean} $valid True if there is no error.\n * @property {boolean} $invalid True if at least one error on the control.\n * @property {string} $name The name attribute of the control.\n *\n * @description\n *\n * `NgModelController` provides API for the {@link ngModel `ngModel`} directive.\n * The controller contains services for data-binding, validation, CSS updates, and value formatting\n * and parsing. It purposefully does not contain any logic which deals with DOM rendering or\n * listening to DOM events.\n * Such DOM related logic should be provided by other directives which make use of\n * `NgModelController` for data-binding to control elements.\n * Angular provides this DOM logic for most {@link input `input`} elements.\n * At the end of this page you can find a {@link ngModel.NgModelController#custom-control-example\n * custom control example} that uses `ngModelController` to bind to `contenteditable` elements.\n *\n * @example\n * ### Custom Control Example\n * This example shows how to use `NgModelController` with a custom control to achieve\n * data-binding. Notice how different directives (`contenteditable`, `ng-model`, and `required`)\n * collaborate together to achieve the desired result.\n *\n * Note that `contenteditable` is an HTML5 attribute, which tells the browser to let the element\n * contents be edited in place by the user.  This will not work on older browsers.\n *\n * We are using the {@link ng.service:$sce $sce} service here and include the {@link ngSanitize $sanitize}\n * module to automatically remove \"bad\" content like inline event listener (e.g. `<span onclick=\"...\">`).\n * However, as we are using `$sce` the model can still decide to provide unsafe content if it marks\n * that content using the `$sce` service.\n *\n * <example name=\"NgModelController\" module=\"customControl\" deps=\"angular-sanitize.js\">\n    <file name=\"style.css\">\n      [contenteditable] {\n        border: 1px solid black;\n        background-color: white;\n        min-height: 20px;\n      }\n\n      .ng-invalid {\n        border: 1px solid red;\n      }\n\n    </file>\n    <file name=\"script.js\">\n      angular.module('customControl', ['ngSanitize']).\n        directive('contenteditable', ['$sce', function($sce) {\n          return {\n            restrict: 'A', // only activate on element attribute\n            require: '?ngModel', // get a hold of NgModelController\n            link: function(scope, element, attrs, ngModel) {\n              if (!ngModel) return; // do nothing if no ng-model\n\n              // Specify how UI should be updated\n              ngModel.$render = function() {\n                element.html($sce.getTrustedHtml(ngModel.$viewValue || ''));\n              };\n\n              // Listen for change events to enable binding\n              element.on('blur keyup change', function() {\n                scope.$evalAsync(read);\n              });\n              read(); // initialize\n\n              // Write data to the model\n              function read() {\n                var html = element.html();\n                // When we clear the content editable the browser leaves a <br> behind\n                // If strip-br attribute is provided then we strip this out\n                if ( attrs.stripBr && html == '<br>' ) {\n                  html = '';\n                }\n                ngModel.$setViewValue(html);\n              }\n            }\n          };\n        }]);\n    </file>\n    <file name=\"index.html\">\n      <form name=\"myForm\">\n       <div contenteditable\n            name=\"myWidget\" ng-model=\"userContent\"\n            strip-br=\"true\"\n            required>Change me!</div>\n        <span ng-show=\"myForm.myWidget.$error.required\">Required!</span>\n       <hr>\n       <textarea ng-model=\"userContent\"></textarea>\n      </form>\n    </file>\n    <file name=\"protractor.js\" type=\"protractor\">\n    it('should data-bind and become invalid', function() {\n      if (browser.params.browser == 'safari' || browser.params.browser == 'firefox') {\n        // SafariDriver can't handle contenteditable\n        // and Firefox driver can't clear contenteditables very well\n        return;\n      }\n      var contentEditable = element(by.css('[contenteditable]'));\n      var content = 'Change me!';\n\n      expect(contentEditable.getText()).toEqual(content);\n\n      contentEditable.clear();\n      contentEditable.sendKeys(protractor.Key.BACK_SPACE);\n      expect(contentEditable.getText()).toEqual('');\n      expect(contentEditable.getAttribute('class')).toMatch(/ng-invalid-required/);\n    });\n    </file>\n * </example>\n *\n *\n */\nvar NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$parse', '$animate', '$timeout', '$rootScope', '$q', '$interpolate',\n    function($scope, $exceptionHandler, $attr, $element, $parse, $animate, $timeout, $rootScope, $q, $interpolate) {\n  this.$viewValue = Number.NaN;\n  this.$modelValue = Number.NaN;\n  this.$$rawModelValue = undefined; // stores the parsed modelValue / model set from scope regardless of validity.\n  this.$validators = {};\n  this.$asyncValidators = {};\n  this.$parsers = [];\n  this.$formatters = [];\n  this.$viewChangeListeners = [];\n  this.$untouched = true;\n  this.$touched = false;\n  this.$pristine = true;\n  this.$dirty = false;\n  this.$valid = true;\n  this.$invalid = false;\n  this.$error = {}; // keep invalid keys here\n  this.$$success = {}; // keep valid keys here\n  this.$pending = undefined; // keep pending keys here\n  this.$name = $interpolate($attr.name || '', false)($scope);\n\n\n  var parsedNgModel = $parse($attr.ngModel),\n      parsedNgModelAssign = parsedNgModel.assign,\n      ngModelGet = parsedNgModel,\n      ngModelSet = parsedNgModelAssign,\n      pendingDebounce = null,\n      ctrl = this;\n\n  this.$$setOptions = function(options) {\n    ctrl.$options = options;\n    if (options && options.getterSetter) {\n      var invokeModelGetter = $parse($attr.ngModel + '()'),\n          invokeModelSetter = $parse($attr.ngModel + '($$$p)');\n\n      ngModelGet = function($scope) {\n        var modelValue = parsedNgModel($scope);\n        if (isFunction(modelValue)) {\n          modelValue = invokeModelGetter($scope);\n        }\n        return modelValue;\n      };\n      ngModelSet = function($scope, newValue) {\n        if (isFunction(parsedNgModel($scope))) {\n          invokeModelSetter($scope, {$$$p: ctrl.$modelValue});\n        } else {\n          parsedNgModelAssign($scope, ctrl.$modelValue);\n        }\n      };\n    } else if (!parsedNgModel.assign) {\n      throw $ngModelMinErr('nonassign', \"Expression '{0}' is non-assignable. Element: {1}\",\n          $attr.ngModel, startingTag($element));\n    }\n  };\n\n  /**\n   * @ngdoc method\n   * @name ngModel.NgModelController#$render\n   *\n   * @description\n   * Called when the view needs to be updated. It is expected that the user of the ng-model\n   * directive will implement this method.\n   *\n   * The `$render()` method is invoked in the following situations:\n   *\n   * * `$rollbackViewValue()` is called.  If we are rolling back the view value to the last\n   *   committed value then `$render()` is called to update the input control.\n   * * The value referenced by `ng-model` is changed programmatically and both the `$modelValue` and\n   *   the `$viewValue` are different to last time.\n   *\n   * Since `ng-model` does not do a deep watch, `$render()` is only invoked if the values of\n   * `$modelValue` and `$viewValue` are actually different to their previous value. If `$modelValue`\n   * or `$viewValue` are objects (rather than a string or number) then `$render()` will not be\n   * invoked if you only change a property on the objects.\n   */\n  this.$render = noop;\n\n  /**\n   * @ngdoc method\n   * @name ngModel.NgModelController#$isEmpty\n   *\n   * @description\n   * This is called when we need to determine if the value of an input is empty.\n   *\n   * For instance, the required directive does this to work out if the input has data or not.\n   *\n   * The default `$isEmpty` function checks whether the value is `undefined`, `''`, `null` or `NaN`.\n   *\n   * You can override this for input directives whose concept of being empty is different to the\n   * default. The `checkboxInputType` directive does this because in its case a value of `false`\n   * implies empty.\n   *\n   * @param {*} value The value of the input to check for emptiness.\n   * @returns {boolean} True if `value` is \"empty\".\n   */\n  this.$isEmpty = function(value) {\n    return isUndefined(value) || value === '' || value === null || value !== value;\n  };\n\n  var parentForm = $element.inheritedData('$formController') || nullFormCtrl,\n      currentValidationRunId = 0;\n\n  /**\n   * @ngdoc method\n   * @name ngModel.NgModelController#$setValidity\n   *\n   * @description\n   * Change the validity state, and notify the form.\n   *\n   * This method can be called within $parsers/$formatters or a custom validation implementation.\n   * However, in most cases it should be sufficient to use the `ngModel.$validators` and\n   * `ngModel.$asyncValidators` collections which will call `$setValidity` automatically.\n   *\n   * @param {string} validationErrorKey Name of the validator. The `validationErrorKey` will be assigned\n   *        to either `$error[validationErrorKey]` or `$pending[validationErrorKey]`\n   *        (for unfulfilled `$asyncValidators`), so that it is available for data-binding.\n   *        The `validationErrorKey` should be in camelCase and will get converted into dash-case\n   *        for class name. Example: `myError` will result in `ng-valid-my-error` and `ng-invalid-my-error`\n   *        class and can be bound to as  `{{someForm.someControl.$error.myError}}` .\n   * @param {boolean} isValid Whether the current state is valid (true), invalid (false), pending (undefined),\n   *                          or skipped (null). Pending is used for unfulfilled `$asyncValidators`.\n   *                          Skipped is used by Angular when validators do not run because of parse errors and\n   *                          when `$asyncValidators` do not run because any of the `$validators` failed.\n   */\n  addSetValidityMethod({\n    ctrl: this,\n    $element: $element,\n    set: function(object, property) {\n      object[property] = true;\n    },\n    unset: function(object, property) {\n      delete object[property];\n    },\n    parentForm: parentForm,\n    $animate: $animate\n  });\n\n  /**\n   * @ngdoc method\n   * @name ngModel.NgModelController#$setPristine\n   *\n   * @description\n   * Sets the control to its pristine state.\n   *\n   * This method can be called to remove the `ng-dirty` class and set the control to its pristine\n   * state (`ng-pristine` class). A model is considered to be pristine when the control\n   * has not been changed from when first compiled.\n   */\n  this.$setPristine = function() {\n    ctrl.$dirty = false;\n    ctrl.$pristine = true;\n    $animate.removeClass($element, DIRTY_CLASS);\n    $animate.addClass($element, PRISTINE_CLASS);\n  };\n\n  /**\n   * @ngdoc method\n   * @name ngModel.NgModelController#$setDirty\n   *\n   * @description\n   * Sets the control to its dirty state.\n   *\n   * This method can be called to remove the `ng-pristine` class and set the control to its dirty\n   * state (`ng-dirty` class). A model is considered to be dirty when the control has been changed\n   * from when first compiled.\n   */\n  this.$setDirty = function() {\n    ctrl.$dirty = true;\n    ctrl.$pristine = false;\n    $animate.removeClass($element, PRISTINE_CLASS);\n    $animate.addClass($element, DIRTY_CLASS);\n    parentForm.$setDirty();\n  };\n\n  /**\n   * @ngdoc method\n   * @name ngModel.NgModelController#$setUntouched\n   *\n   * @description\n   * Sets the control to its untouched state.\n   *\n   * This method can be called to remove the `ng-touched` class and set the control to its\n   * untouched state (`ng-untouched` class). Upon compilation, a model is set as untouched\n   * by default, however this function can be used to restore that state if the model has\n   * already been touched by the user.\n   */\n  this.$setUntouched = function() {\n    ctrl.$touched = false;\n    ctrl.$untouched = true;\n    $animate.setClass($element, UNTOUCHED_CLASS, TOUCHED_CLASS);\n  };\n\n  /**\n   * @ngdoc method\n   * @name ngModel.NgModelController#$setTouched\n   *\n   * @description\n   * Sets the control to its touched state.\n   *\n   * This method can be called to remove the `ng-untouched` class and set the control to its\n   * touched state (`ng-touched` class). A model is considered to be touched when the user has\n   * first focused the control element and then shifted focus away from the control (blur event).\n   */\n  this.$setTouched = function() {\n    ctrl.$touched = true;\n    ctrl.$untouched = false;\n    $animate.setClass($element, TOUCHED_CLASS, UNTOUCHED_CLASS);\n  };\n\n  /**\n   * @ngdoc method\n   * @name ngModel.NgModelController#$rollbackViewValue\n   *\n   * @description\n   * Cancel an update and reset the input element's value to prevent an update to the `$modelValue`,\n   * which may be caused by a pending debounced event or because the input is waiting for a some\n   * future event.\n   *\n   * If you have an input that uses `ng-model-options` to set up debounced events or events such\n   * as blur you can have a situation where there is a period when the `$viewValue`\n   * is out of synch with the ngModel's `$modelValue`.\n   *\n   * In this case, you can run into difficulties if you try to update the ngModel's `$modelValue`\n   * programmatically before these debounced/future events have resolved/occurred, because Angular's\n   * dirty checking mechanism is not able to tell whether the model has actually changed or not.\n   *\n   * The `$rollbackViewValue()` method should be called before programmatically changing the model of an\n   * input which may have such events pending. This is important in order to make sure that the\n   * input field will be updated with the new model value and any pending operations are cancelled.\n   *\n   * <example name=\"ng-model-cancel-update\" module=\"cancel-update-example\">\n   *   <file name=\"app.js\">\n   *     angular.module('cancel-update-example', [])\n   *\n   *     .controller('CancelUpdateController', ['$scope', function($scope) {\n   *       $scope.resetWithCancel = function(e) {\n   *         if (e.keyCode == 27) {\n   *           $scope.myForm.myInput1.$rollbackViewValue();\n   *           $scope.myValue = '';\n   *         }\n   *       };\n   *       $scope.resetWithoutCancel = function(e) {\n   *         if (e.keyCode == 27) {\n   *           $scope.myValue = '';\n   *         }\n   *       };\n   *     }]);\n   *   </file>\n   *   <file name=\"index.html\">\n   *     <div ng-controller=\"CancelUpdateController\">\n   *       <p>Try typing something in each input.  See that the model only updates when you\n   *          blur off the input.\n   *        </p>\n   *        <p>Now see what happens if you start typing then press the Escape key</p>\n   *\n   *       <form name=\"myForm\" ng-model-options=\"{ updateOn: 'blur' }\">\n   *         <p>With $rollbackViewValue()</p>\n   *         <input name=\"myInput1\" ng-model=\"myValue\" ng-keydown=\"resetWithCancel($event)\"><br/>\n   *         myValue: \"{{ myValue }}\"\n   *\n   *         <p>Without $rollbackViewValue()</p>\n   *         <input name=\"myInput2\" ng-model=\"myValue\" ng-keydown=\"resetWithoutCancel($event)\"><br/>\n   *         myValue: \"{{ myValue }}\"\n   *       </form>\n   *     </div>\n   *   </file>\n   * </example>\n   */\n  this.$rollbackViewValue = function() {\n    $timeout.cancel(pendingDebounce);\n    ctrl.$viewValue = ctrl.$$lastCommittedViewValue;\n    ctrl.$render();\n  };\n\n  /**\n   * @ngdoc method\n   * @name ngModel.NgModelController#$validate\n   *\n   * @description\n   * Runs each of the registered validators (first synchronous validators and then\n   * asynchronous validators).\n   * If the validity changes to invalid, the model will be set to `undefined`,\n   * unless {@link ngModelOptions `ngModelOptions.allowInvalid`} is `true`.\n   * If the validity changes to valid, it will set the model to the last available valid\n   * modelValue, i.e. either the last parsed value or the last value set from the scope.\n   */\n  this.$validate = function() {\n    // ignore $validate before model is initialized\n    if (isNumber(ctrl.$modelValue) && isNaN(ctrl.$modelValue)) {\n      return;\n    }\n\n    var viewValue = ctrl.$$lastCommittedViewValue;\n    // Note: we use the $$rawModelValue as $modelValue might have been\n    // set to undefined during a view -> model update that found validation\n    // errors. We can't parse the view here, since that could change\n    // the model although neither viewValue nor the model on the scope changed\n    var modelValue = ctrl.$$rawModelValue;\n\n    // Check if the there's a parse error, so we don't unset it accidentially\n    var parserName = ctrl.$$parserName || 'parse';\n    var parserValid = ctrl.$error[parserName] ? false : undefined;\n\n    var prevValid = ctrl.$valid;\n    var prevModelValue = ctrl.$modelValue;\n\n    var allowInvalid = ctrl.$options && ctrl.$options.allowInvalid;\n\n    ctrl.$$runValidators(parserValid, modelValue, viewValue, function(allValid) {\n      // If there was no change in validity, don't update the model\n      // This prevents changing an invalid modelValue to undefined\n      if (!allowInvalid && prevValid !== allValid) {\n        // Note: Don't check ctrl.$valid here, as we could have\n        // external validators (e.g. calculated on the server),\n        // that just call $setValidity and need the model value\n        // to calculate their validity.\n        ctrl.$modelValue = allValid ? modelValue : undefined;\n\n        if (ctrl.$modelValue !== prevModelValue) {\n          ctrl.$$writeModelToScope();\n        }\n      }\n    });\n\n  };\n\n  this.$$runValidators = function(parseValid, modelValue, viewValue, doneCallback) {\n    currentValidationRunId++;\n    var localValidationRunId = currentValidationRunId;\n\n    // check parser error\n    if (!processParseErrors(parseValid)) {\n      validationDone(false);\n      return;\n    }\n    if (!processSyncValidators()) {\n      validationDone(false);\n      return;\n    }\n    processAsyncValidators();\n\n    function processParseErrors(parseValid) {\n      var errorKey = ctrl.$$parserName || 'parse';\n      if (parseValid === undefined) {\n        setValidity(errorKey, null);\n      } else {\n        setValidity(errorKey, parseValid);\n        if (!parseValid) {\n          forEach(ctrl.$validators, function(v, name) {\n            setValidity(name, null);\n          });\n          forEach(ctrl.$asyncValidators, function(v, name) {\n            setValidity(name, null);\n          });\n          return false;\n        }\n      }\n      return true;\n    }\n\n    function processSyncValidators() {\n      var syncValidatorsValid = true;\n      forEach(ctrl.$validators, function(validator, name) {\n        var result = validator(modelValue, viewValue);\n        syncValidatorsValid = syncValidatorsValid && result;\n        setValidity(name, result);\n      });\n      if (!syncValidatorsValid) {\n        forEach(ctrl.$asyncValidators, function(v, name) {\n          setValidity(name, null);\n        });\n        return false;\n      }\n      return true;\n    }\n\n    function processAsyncValidators() {\n      var validatorPromises = [];\n      var allValid = true;\n      forEach(ctrl.$asyncValidators, function(validator, name) {\n        var promise = validator(modelValue, viewValue);\n        if (!isPromiseLike(promise)) {\n          throw $ngModelMinErr(\"$asyncValidators\",\n            \"Expected asynchronous validator to return a promise but got '{0}' instead.\", promise);\n        }\n        setValidity(name, undefined);\n        validatorPromises.push(promise.then(function() {\n          setValidity(name, true);\n        }, function(error) {\n          allValid = false;\n          setValidity(name, false);\n        }));\n      });\n      if (!validatorPromises.length) {\n        validationDone(true);\n      } else {\n        $q.all(validatorPromises).then(function() {\n          validationDone(allValid);\n        }, noop);\n      }\n    }\n\n    function setValidity(name, isValid) {\n      if (localValidationRunId === currentValidationRunId) {\n        ctrl.$setValidity(name, isValid);\n      }\n    }\n\n    function validationDone(allValid) {\n      if (localValidationRunId === currentValidationRunId) {\n\n        doneCallback(allValid);\n      }\n    }\n  };\n\n  /**\n   * @ngdoc method\n   * @name ngModel.NgModelController#$commitViewValue\n   *\n   * @description\n   * Commit a pending update to the `$modelValue`.\n   *\n   * Updates may be pending by a debounced event or because the input is waiting for a some future\n   * event defined in `ng-model-options`. this method is rarely needed as `NgModelController`\n   * usually handles calling this in response to input events.\n   */\n  this.$commitViewValue = function() {\n    var viewValue = ctrl.$viewValue;\n\n    $timeout.cancel(pendingDebounce);\n\n    // If the view value has not changed then we should just exit, except in the case where there is\n    // a native validator on the element. In this case the validation state may have changed even though\n    // the viewValue has stayed empty.\n    if (ctrl.$$lastCommittedViewValue === viewValue && (viewValue !== '' || !ctrl.$$hasNativeValidators)) {\n      return;\n    }\n    ctrl.$$lastCommittedViewValue = viewValue;\n\n    // change to dirty\n    if (ctrl.$pristine) {\n      this.$setDirty();\n    }\n    this.$$parseAndValidate();\n  };\n\n  this.$$parseAndValidate = function() {\n    var viewValue = ctrl.$$lastCommittedViewValue;\n    var modelValue = viewValue;\n    var parserValid = isUndefined(modelValue) ? undefined : true;\n\n    if (parserValid) {\n      for (var i = 0; i < ctrl.$parsers.length; i++) {\n        modelValue = ctrl.$parsers[i](modelValue);\n        if (isUndefined(modelValue)) {\n          parserValid = false;\n          break;\n        }\n      }\n    }\n    if (isNumber(ctrl.$modelValue) && isNaN(ctrl.$modelValue)) {\n      // ctrl.$modelValue has not been touched yet...\n      ctrl.$modelValue = ngModelGet($scope);\n    }\n    var prevModelValue = ctrl.$modelValue;\n    var allowInvalid = ctrl.$options && ctrl.$options.allowInvalid;\n    ctrl.$$rawModelValue = modelValue;\n\n    if (allowInvalid) {\n      ctrl.$modelValue = modelValue;\n      writeToModelIfNeeded();\n    }\n\n    // Pass the $$lastCommittedViewValue here, because the cached viewValue might be out of date.\n    // This can happen if e.g. $setViewValue is called from inside a parser\n    ctrl.$$runValidators(parserValid, modelValue, ctrl.$$lastCommittedViewValue, function(allValid) {\n      if (!allowInvalid) {\n        // Note: Don't check ctrl.$valid here, as we could have\n        // external validators (e.g. calculated on the server),\n        // that just call $setValidity and need the model value\n        // to calculate their validity.\n        ctrl.$modelValue = allValid ? modelValue : undefined;\n        writeToModelIfNeeded();\n      }\n    });\n\n    function writeToModelIfNeeded() {\n      if (ctrl.$modelValue !== prevModelValue) {\n        ctrl.$$writeModelToScope();\n      }\n    }\n  };\n\n  this.$$writeModelToScope = function() {\n    ngModelSet($scope, ctrl.$modelValue);\n    forEach(ctrl.$viewChangeListeners, function(listener) {\n      try {\n        listener();\n      } catch (e) {\n        $exceptionHandler(e);\n      }\n    });\n  };\n\n  /**\n   * @ngdoc method\n   * @name ngModel.NgModelController#$setViewValue\n   *\n   * @description\n   * Update the view value.\n   *\n   * This method should be called when an input directive want to change the view value; typically,\n   * this is done from within a DOM event handler.\n   *\n   * For example {@link ng.directive:input input} calls it when the value of the input changes and\n   * {@link ng.directive:select select} calls it when an option is selected.\n   *\n   * If the new `value` is an object (rather than a string or a number), we should make a copy of the\n   * object before passing it to `$setViewValue`.  This is because `ngModel` does not perform a deep\n   * watch of objects, it only looks for a change of identity. If you only change the property of\n   * the object then ngModel will not realise that the object has changed and will not invoke the\n   * `$parsers` and `$validators` pipelines.\n   *\n   * For this reason, you should not change properties of the copy once it has been passed to\n   * `$setViewValue`. Otherwise you may cause the model value on the scope to change incorrectly.\n   *\n   * When this method is called, the new `value` will be staged for committing through the `$parsers`\n   * and `$validators` pipelines. If there are no special {@link ngModelOptions} specified then the staged\n   * value sent directly for processing, finally to be applied to `$modelValue` and then the\n   * **expression** specified in the `ng-model` attribute.\n   *\n   * Lastly, all the registered change listeners, in the `$viewChangeListeners` list, are called.\n   *\n   * In case the {@link ng.directive:ngModelOptions ngModelOptions} directive is used with `updateOn`\n   * and the `default` trigger is not listed, all those actions will remain pending until one of the\n   * `updateOn` events is triggered on the DOM element.\n   * All these actions will be debounced if the {@link ng.directive:ngModelOptions ngModelOptions}\n   * directive is used with a custom debounce for this particular event.\n   *\n   * Note that calling this function does not trigger a `$digest`.\n   *\n   * @param {string} value Value from the view.\n   * @param {string} trigger Event that triggered the update.\n   */\n  this.$setViewValue = function(value, trigger) {\n    ctrl.$viewValue = value;\n    if (!ctrl.$options || ctrl.$options.updateOnDefault) {\n      ctrl.$$debounceViewValueCommit(trigger);\n    }\n  };\n\n  this.$$debounceViewValueCommit = function(trigger) {\n    var debounceDelay = 0,\n        options = ctrl.$options,\n        debounce;\n\n    if (options && isDefined(options.debounce)) {\n      debounce = options.debounce;\n      if (isNumber(debounce)) {\n        debounceDelay = debounce;\n      } else if (isNumber(debounce[trigger])) {\n        debounceDelay = debounce[trigger];\n      } else if (isNumber(debounce['default'])) {\n        debounceDelay = debounce['default'];\n      }\n    }\n\n    $timeout.cancel(pendingDebounce);\n    if (debounceDelay) {\n      pendingDebounce = $timeout(function() {\n        ctrl.$commitViewValue();\n      }, debounceDelay);\n    } else if ($rootScope.$$phase) {\n      ctrl.$commitViewValue();\n    } else {\n      $scope.$apply(function() {\n        ctrl.$commitViewValue();\n      });\n    }\n  };\n\n  // model -> value\n  // Note: we cannot use a normal scope.$watch as we want to detect the following:\n  // 1. scope value is 'a'\n  // 2. user enters 'b'\n  // 3. ng-change kicks in and reverts scope value to 'a'\n  //    -> scope value did not change since the last digest as\n  //       ng-change executes in apply phase\n  // 4. view should be changed back to 'a'\n  $scope.$watch(function ngModelWatch() {\n    var modelValue = ngModelGet($scope);\n\n    // if scope model value and ngModel value are out of sync\n    // TODO(perf): why not move this to the action fn?\n    if (modelValue !== ctrl.$modelValue) {\n      ctrl.$modelValue = ctrl.$$rawModelValue = modelValue;\n\n      var formatters = ctrl.$formatters,\n          idx = formatters.length;\n\n      var viewValue = modelValue;\n      while (idx--) {\n        viewValue = formatters[idx](viewValue);\n      }\n      if (ctrl.$viewValue !== viewValue) {\n        ctrl.$viewValue = ctrl.$$lastCommittedViewValue = viewValue;\n        ctrl.$render();\n\n        ctrl.$$runValidators(undefined, modelValue, viewValue, noop);\n      }\n    }\n\n    return modelValue;\n  });\n}];\n\n\n/**\n * @ngdoc directive\n * @name ngModel\n *\n * @element input\n * @priority 1\n *\n * @description\n * The `ngModel` directive binds an `input`,`select`, `textarea` (or custom form control) to a\n * property on the scope using {@link ngModel.NgModelController NgModelController},\n * which is created and exposed by this directive.\n *\n * `ngModel` is responsible for:\n *\n * - Binding the view into the model, which other directives such as `input`, `textarea` or `select`\n *   require.\n * - Providing validation behavior (i.e. required, number, email, url).\n * - Keeping the state of the control (valid/invalid, dirty/pristine, touched/untouched, validation errors).\n * - Setting related css classes on the element (`ng-valid`, `ng-invalid`, `ng-dirty`, `ng-pristine`, `ng-touched`, `ng-untouched`) including animations.\n * - Registering the control with its parent {@link ng.directive:form form}.\n *\n * Note: `ngModel` will try to bind to the property given by evaluating the expression on the\n * current scope. If the property doesn't already exist on this scope, it will be created\n * implicitly and added to the scope.\n *\n * For best practices on using `ngModel`, see:\n *\n *  - [Understanding Scopes](https://github.com/angular/angular.js/wiki/Understanding-Scopes)\n *\n * For basic examples, how to use `ngModel`, see:\n *\n *  - {@link ng.directive:input input}\n *    - {@link input[text] text}\n *    - {@link input[checkbox] checkbox}\n *    - {@link input[radio] radio}\n *    - {@link input[number] number}\n *    - {@link input[email] email}\n *    - {@link input[url] url}\n *    - {@link input[date] date}\n *    - {@link input[datetime-local] datetime-local}\n *    - {@link input[time] time}\n *    - {@link input[month] month}\n *    - {@link input[week] week}\n *  - {@link ng.directive:select select}\n *  - {@link ng.directive:textarea textarea}\n *\n * # CSS classes\n * The following CSS classes are added and removed on the associated input/select/textarea element\n * depending on the validity of the model.\n *\n *  - `ng-valid`: the model is valid\n *  - `ng-invalid`: the model is invalid\n *  - `ng-valid-[key]`: for each valid key added by `$setValidity`\n *  - `ng-invalid-[key]`: for each invalid key added by `$setValidity`\n *  - `ng-pristine`: the control hasn't been interacted with yet\n *  - `ng-dirty`: the control has been interacted with\n *  - `ng-touched`: the control has been blurred\n *  - `ng-untouched`: the control hasn't been blurred\n *  - `ng-pending`: any `$asyncValidators` are unfulfilled\n *\n * Keep in mind that ngAnimate can detect each of these classes when added and removed.\n *\n * ## Animation Hooks\n *\n * Animations within models are triggered when any of the associated CSS classes are added and removed\n * on the input element which is attached to the model. These classes are: `.ng-pristine`, `.ng-dirty`,\n * `.ng-invalid` and `.ng-valid` as well as any other validations that are performed on the model itself.\n * The animations that are triggered within ngModel are similar to how they work in ngClass and\n * animations can be hooked into using CSS transitions, keyframes as well as JS animations.\n *\n * The following example shows a simple way to utilize CSS transitions to style an input element\n * that has been rendered as invalid after it has been validated:\n *\n * <pre>\n * //be sure to include ngAnimate as a module to hook into more\n * //advanced animations\n * .my-input {\n *   transition:0.5s linear all;\n *   background: white;\n * }\n * .my-input.ng-invalid {\n *   background: red;\n *   color:white;\n * }\n * </pre>\n *\n * @example\n * <example deps=\"angular-animate.js\" animations=\"true\" fixBase=\"true\" module=\"inputExample\">\n     <file name=\"index.html\">\n       <script>\n        angular.module('inputExample', [])\n          .controller('ExampleController', ['$scope', function($scope) {\n            $scope.val = '1';\n          }]);\n       </script>\n       <style>\n         .my-input {\n           -webkit-transition:all linear 0.5s;\n           transition:all linear 0.5s;\n           background: transparent;\n         }\n         .my-input.ng-invalid {\n           color:white;\n           background: red;\n         }\n       </style>\n       Update input to see transitions when valid/invalid.\n       Integer is a valid value.\n       <form name=\"testForm\" ng-controller=\"ExampleController\">\n         <input ng-model=\"val\" ng-pattern=\"/^\\d+$/\" name=\"anim\" class=\"my-input\" />\n       </form>\n     </file>\n * </example>\n *\n * ## Binding to a getter/setter\n *\n * Sometimes it's helpful to bind `ngModel` to a getter/setter function.  A getter/setter is a\n * function that returns a representation of the model when called with zero arguments, and sets\n * the internal state of a model when called with an argument. It's sometimes useful to use this\n * for models that have an internal representation that's different than what the model exposes\n * to the view.\n *\n * <div class=\"alert alert-success\">\n * **Best Practice:** It's best to keep getters fast because Angular is likely to call them more\n * frequently than other parts of your code.\n * </div>\n *\n * You use this behavior by adding `ng-model-options=\"{ getterSetter: true }\"` to an element that\n * has `ng-model` attached to it. You can also add `ng-model-options=\"{ getterSetter: true }\"` to\n * a `<form>`, which will enable this behavior for all `<input>`s within it. See\n * {@link ng.directive:ngModelOptions `ngModelOptions`} for more.\n *\n * The following example shows how to use `ngModel` with a getter/setter:\n *\n * @example\n * <example name=\"ngModel-getter-setter\" module=\"getterSetterExample\">\n     <file name=\"index.html\">\n       <div ng-controller=\"ExampleController\">\n         <form name=\"userForm\">\n           Name:\n           <input type=\"text\" name=\"userName\"\n                  ng-model=\"user.name\"\n                  ng-model-options=\"{ getterSetter: true }\" />\n         </form>\n         <pre>user.name = <span ng-bind=\"user.name()\"></span></pre>\n       </div>\n     </file>\n     <file name=\"app.js\">\n       angular.module('getterSetterExample', [])\n         .controller('ExampleController', ['$scope', function($scope) {\n           var _name = 'Brian';\n           $scope.user = {\n             name: function(newName) {\n               if (angular.isDefined(newName)) {\n                 _name = newName;\n               }\n               return _name;\n             }\n           };\n         }]);\n     </file>\n * </example>\n */\nvar ngModelDirective = ['$rootScope', function($rootScope) {\n  return {\n    restrict: 'A',\n    require: ['ngModel', '^?form', '^?ngModelOptions'],\n    controller: NgModelController,\n    // Prelink needs to run before any input directive\n    // so that we can set the NgModelOptions in NgModelController\n    // before anyone else uses it.\n    priority: 1,\n    compile: function ngModelCompile(element) {\n      // Setup initial state of the control\n      element.addClass(PRISTINE_CLASS).addClass(UNTOUCHED_CLASS).addClass(VALID_CLASS);\n\n      return {\n        pre: function ngModelPreLink(scope, element, attr, ctrls) {\n          var modelCtrl = ctrls[0],\n              formCtrl = ctrls[1] || nullFormCtrl;\n\n          modelCtrl.$$setOptions(ctrls[2] && ctrls[2].$options);\n\n          // notify others, especially parent forms\n          formCtrl.$addControl(modelCtrl);\n\n          attr.$observe('name', function(newValue) {\n            if (modelCtrl.$name !== newValue) {\n              formCtrl.$$renameControl(modelCtrl, newValue);\n            }\n          });\n\n          scope.$on('$destroy', function() {\n            formCtrl.$removeControl(modelCtrl);\n          });\n        },\n        post: function ngModelPostLink(scope, element, attr, ctrls) {\n          var modelCtrl = ctrls[0];\n          if (modelCtrl.$options && modelCtrl.$options.updateOn) {\n            element.on(modelCtrl.$options.updateOn, function(ev) {\n              modelCtrl.$$debounceViewValueCommit(ev && ev.type);\n            });\n          }\n\n          element.on('blur', function(ev) {\n            if (modelCtrl.$touched) return;\n\n            if ($rootScope.$$phase) {\n              scope.$evalAsync(modelCtrl.$setTouched);\n            } else {\n              scope.$apply(modelCtrl.$setTouched);\n            }\n          });\n        }\n      };\n    }\n  };\n}];\n\nvar DEFAULT_REGEXP = /(\\s+|^)default(\\s+|$)/;\n\n/**\n * @ngdoc directive\n * @name ngModelOptions\n *\n * @description\n * Allows tuning how model updates are done. Using `ngModelOptions` you can specify a custom list of\n * events that will trigger a model update and/or a debouncing delay so that the actual update only\n * takes place when a timer expires; this timer will be reset after another change takes place.\n *\n * Given the nature of `ngModelOptions`, the value displayed inside input fields in the view might\n * be different than the value in the actual model. This means that if you update the model you\n * should also invoke {@link ngModel.NgModelController `$rollbackViewValue`} on the relevant input field in\n * order to make sure it is synchronized with the model and that any debounced action is canceled.\n *\n * The easiest way to reference the control's {@link ngModel.NgModelController `$rollbackViewValue`}\n * method is by making sure the input is placed inside a form that has a `name` attribute. This is\n * important because `form` controllers are published to the related scope under the name in their\n * `name` attribute.\n *\n * Any pending changes will take place immediately when an enclosing form is submitted via the\n * `submit` event. Note that `ngClick` events will occur before the model is updated. Use `ngSubmit`\n * to have access to the updated model.\n *\n * `ngModelOptions` has an effect on the element it's declared on and its descendants.\n *\n * @param {Object} ngModelOptions options to apply to the current model. Valid keys are:\n *   - `updateOn`: string specifying which event should the input be bound to. You can set several\n *     events using an space delimited list. There is a special event called `default` that\n *     matches the default events belonging of the control.\n *   - `debounce`: integer value which contains the debounce model update value in milliseconds. A\n *     value of 0 triggers an immediate update. If an object is supplied instead, you can specify a\n *     custom value for each event. For example:\n *     `ng-model-options=\"{ updateOn: 'default blur', debounce: {'default': 500, 'blur': 0} }\"`\n *   - `allowInvalid`: boolean value which indicates that the model can be set with values that did\n *     not validate correctly instead of the default behavior of setting the model to undefined.\n *   - `getterSetter`: boolean value which determines whether or not to treat functions bound to\n       `ngModel` as getters/setters.\n *   - `timezone`: Defines the timezone to be used to read/write the `Date` instance in the model for\n *     `<input type=\"date\">`, `<input type=\"time\">`, ... . Right now, the only supported value is `'UTC'`,\n *     otherwise the default timezone of the browser will be used.\n *\n * @example\n\n  The following example shows how to override immediate updates. Changes on the inputs within the\n  form will update the model only when the control loses focus (blur event). If `escape` key is\n  pressed while the input field is focused, the value is reset to the value in the current model.\n\n  <example name=\"ngModelOptions-directive-blur\" module=\"optionsExample\">\n    <file name=\"index.html\">\n      <div ng-controller=\"ExampleController\">\n        <form name=\"userForm\">\n          Name:\n          <input type=\"text\" name=\"userName\"\n                 ng-model=\"user.name\"\n                 ng-model-options=\"{ updateOn: 'blur' }\"\n                 ng-keyup=\"cancel($event)\" /><br />\n\n          Other data:\n          <input type=\"text\" ng-model=\"user.data\" /><br />\n        </form>\n        <pre>user.name = <span ng-bind=\"user.name\"></span></pre>\n      </div>\n    </file>\n    <file name=\"app.js\">\n      angular.module('optionsExample', [])\n        .controller('ExampleController', ['$scope', function($scope) {\n          $scope.user = { name: 'say', data: '' };\n\n          $scope.cancel = function(e) {\n            if (e.keyCode == 27) {\n              $scope.userForm.userName.$rollbackViewValue();\n            }\n          };\n        }]);\n    </file>\n    <file name=\"protractor.js\" type=\"protractor\">\n      var model = element(by.binding('user.name'));\n      var input = element(by.model('user.name'));\n      var other = element(by.model('user.data'));\n\n      it('should allow custom events', function() {\n        input.sendKeys(' hello');\n        input.click();\n        expect(model.getText()).toEqual('say');\n        other.click();\n        expect(model.getText()).toEqual('say hello');\n      });\n\n      it('should $rollbackViewValue when model changes', function() {\n        input.sendKeys(' hello');\n        expect(input.getAttribute('value')).toEqual('say hello');\n        input.sendKeys(protractor.Key.ESCAPE);\n        expect(input.getAttribute('value')).toEqual('say');\n        other.click();\n        expect(model.getText()).toEqual('say');\n      });\n    </file>\n  </example>\n\n  This one shows how to debounce model changes. Model will be updated only 1 sec after last change.\n  If the `Clear` button is pressed, any debounced action is canceled and the value becomes empty.\n\n  <example name=\"ngModelOptions-directive-debounce\" module=\"optionsExample\">\n    <file name=\"index.html\">\n      <div ng-controller=\"ExampleController\">\n        <form name=\"userForm\">\n          Name:\n          <input type=\"text\" name=\"userName\"\n                 ng-model=\"user.name\"\n                 ng-model-options=\"{ debounce: 1000 }\" />\n          <button ng-click=\"userForm.userName.$rollbackViewValue(); user.name=''\">Clear</button><br />\n        </form>\n        <pre>user.name = <span ng-bind=\"user.name\"></span></pre>\n      </div>\n    </file>\n    <file name=\"app.js\">\n      angular.module('optionsExample', [])\n        .controller('ExampleController', ['$scope', function($scope) {\n          $scope.user = { name: 'say' };\n        }]);\n    </file>\n  </example>\n\n  This one shows how to bind to getter/setters:\n\n  <example name=\"ngModelOptions-directive-getter-setter\" module=\"getterSetterExample\">\n    <file name=\"index.html\">\n      <div ng-controller=\"ExampleController\">\n        <form name=\"userForm\">\n          Name:\n          <input type=\"text\" name=\"userName\"\n                 ng-model=\"user.name\"\n                 ng-model-options=\"{ getterSetter: true }\" />\n        </form>\n        <pre>user.name = <span ng-bind=\"user.name()\"></span></pre>\n      </div>\n    </file>\n    <file name=\"app.js\">\n      angular.module('getterSetterExample', [])\n        .controller('ExampleController', ['$scope', function($scope) {\n          var _name = 'Brian';\n          $scope.user = {\n            name: function(newName) {\n              return angular.isDefined(newName) ? (_name = newName) : _name;\n            }\n          };\n        }]);\n    </file>\n  </example>\n */\nvar ngModelOptionsDirective = function() {\n  return {\n    restrict: 'A',\n    controller: ['$scope', '$attrs', function($scope, $attrs) {\n      var that = this;\n      this.$options = $scope.$eval($attrs.ngModelOptions);\n      // Allow adding/overriding bound events\n      if (this.$options.updateOn !== undefined) {\n        this.$options.updateOnDefault = false;\n        // extract \"default\" pseudo-event from list of events that can trigger a model update\n        this.$options.updateOn = trim(this.$options.updateOn.replace(DEFAULT_REGEXP, function() {\n          that.$options.updateOnDefault = true;\n          return ' ';\n        }));\n      } else {\n        this.$options.updateOnDefault = true;\n      }\n    }]\n  };\n};\n\n\n\n// helper methods\nfunction addSetValidityMethod(context) {\n  var ctrl = context.ctrl,\n      $element = context.$element,\n      classCache = {},\n      set = context.set,\n      unset = context.unset,\n      parentForm = context.parentForm,\n      $animate = context.$animate;\n\n  classCache[INVALID_CLASS] = !(classCache[VALID_CLASS] = $element.hasClass(VALID_CLASS));\n\n  ctrl.$setValidity = setValidity;\n\n  function setValidity(validationErrorKey, state, controller) {\n    if (state === undefined) {\n      createAndSet('$pending', validationErrorKey, controller);\n    } else {\n      unsetAndCleanup('$pending', validationErrorKey, controller);\n    }\n    if (!isBoolean(state)) {\n      unset(ctrl.$error, validationErrorKey, controller);\n      unset(ctrl.$$success, validationErrorKey, controller);\n    } else {\n      if (state) {\n        unset(ctrl.$error, validationErrorKey, controller);\n        set(ctrl.$$success, validationErrorKey, controller);\n      } else {\n        set(ctrl.$error, validationErrorKey, controller);\n        unset(ctrl.$$success, validationErrorKey, controller);\n      }\n    }\n    if (ctrl.$pending) {\n      cachedToggleClass(PENDING_CLASS, true);\n      ctrl.$valid = ctrl.$invalid = undefined;\n      toggleValidationCss('', null);\n    } else {\n      cachedToggleClass(PENDING_CLASS, false);\n      ctrl.$valid = isObjectEmpty(ctrl.$error);\n      ctrl.$invalid = !ctrl.$valid;\n      toggleValidationCss('', ctrl.$valid);\n    }\n\n    // re-read the state as the set/unset methods could have\n    // combined state in ctrl.$error[validationError] (used for forms),\n    // where setting/unsetting only increments/decrements the value,\n    // and does not replace it.\n    var combinedState;\n    if (ctrl.$pending && ctrl.$pending[validationErrorKey]) {\n      combinedState = undefined;\n    } else if (ctrl.$error[validationErrorKey]) {\n      combinedState = false;\n    } else if (ctrl.$$success[validationErrorKey]) {\n      combinedState = true;\n    } else {\n      combinedState = null;\n    }\n\n    toggleValidationCss(validationErrorKey, combinedState);\n    parentForm.$setValidity(validationErrorKey, combinedState, ctrl);\n  }\n\n  function createAndSet(name, value, controller) {\n    if (!ctrl[name]) {\n      ctrl[name] = {};\n    }\n    set(ctrl[name], value, controller);\n  }\n\n  function unsetAndCleanup(name, value, controller) {\n    if (ctrl[name]) {\n      unset(ctrl[name], value, controller);\n    }\n    if (isObjectEmpty(ctrl[name])) {\n      ctrl[name] = undefined;\n    }\n  }\n\n  function cachedToggleClass(className, switchValue) {\n    if (switchValue && !classCache[className]) {\n      $animate.addClass($element, className);\n      classCache[className] = true;\n    } else if (!switchValue && classCache[className]) {\n      $animate.removeClass($element, className);\n      classCache[className] = false;\n    }\n  }\n\n  function toggleValidationCss(validationErrorKey, isValid) {\n    validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : '';\n\n    cachedToggleClass(VALID_CLASS + validationErrorKey, isValid === true);\n    cachedToggleClass(INVALID_CLASS + validationErrorKey, isValid === false);\n  }\n}\n\nfunction isObjectEmpty(obj) {\n  if (obj) {\n    for (var prop in obj) {\n      return false;\n    }\n  }\n  return true;\n}\n\n/**\n * @ngdoc directive\n * @name ngNonBindable\n * @restrict AC\n * @priority 1000\n *\n * @description\n * The `ngNonBindable` directive tells Angular not to compile or bind the contents of the current\n * DOM element. This is useful if the element contains what appears to be Angular directives and\n * bindings but which should be ignored by Angular. This could be the case if you have a site that\n * displays snippets of code, for instance.\n *\n * @element ANY\n *\n * @example\n * In this example there are two locations where a simple interpolation binding (`{{}}`) is present,\n * but the one wrapped in `ngNonBindable` is left alone.\n *\n * @example\n    <example>\n      <file name=\"index.html\">\n        <div>Normal: {{1 + 2}}</div>\n        <div ng-non-bindable>Ignored: {{1 + 2}}</div>\n      </file>\n      <file name=\"protractor.js\" type=\"protractor\">\n       it('should check ng-non-bindable', function() {\n         expect(element(by.binding('1 + 2')).getText()).toContain('3');\n         expect(element.all(by.css('div')).last().getText()).toMatch(/1 \\+ 2/);\n       });\n      </file>\n    </example>\n */\nvar ngNonBindableDirective = ngDirective({ terminal: true, priority: 1000 });\n\n/**\n * @ngdoc directive\n * @name ngPluralize\n * @restrict EA\n *\n * @description\n * `ngPluralize` is a directive that displays messages according to en-US localization rules.\n * These rules are bundled with angular.js, but can be overridden\n * (see {@link guide/i18n Angular i18n} dev guide). You configure ngPluralize directive\n * by specifying the mappings between\n * [plural categories](http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html)\n * and the strings to be displayed.\n *\n * # Plural categories and explicit number rules\n * There are two\n * [plural categories](http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html)\n * in Angular's default en-US locale: \"one\" and \"other\".\n *\n * While a plural category may match many numbers (for example, in en-US locale, \"other\" can match\n * any number that is not 1), an explicit number rule can only match one number. For example, the\n * explicit number rule for \"3\" matches the number 3. There are examples of plural categories\n * and explicit number rules throughout the rest of this documentation.\n *\n * # Configuring ngPluralize\n * You configure ngPluralize by providing 2 attributes: `count` and `when`.\n * You can also provide an optional attribute, `offset`.\n *\n * The value of the `count` attribute can be either a string or an {@link guide/expression\n * Angular expression}; these are evaluated on the current scope for its bound value.\n *\n * The `when` attribute specifies the mappings between plural categories and the actual\n * string to be displayed. The value of the attribute should be a JSON object.\n *\n * The following example shows how to configure ngPluralize:\n *\n * ```html\n * <ng-pluralize count=\"personCount\"\n                 when=\"{'0': 'Nobody is viewing.',\n *                      'one': '1 person is viewing.',\n *                      'other': '{} people are viewing.'}\">\n * </ng-pluralize>\n *```\n *\n * In the example, `\"0: Nobody is viewing.\"` is an explicit number rule. If you did not\n * specify this rule, 0 would be matched to the \"other\" category and \"0 people are viewing\"\n * would be shown instead of \"Nobody is viewing\". You can specify an explicit number rule for\n * other numbers, for example 12, so that instead of showing \"12 people are viewing\", you can\n * show \"a dozen people are viewing\".\n *\n * You can use a set of closed braces (`{}`) as a placeholder for the number that you want substituted\n * into pluralized strings. In the previous example, Angular will replace `{}` with\n * <span ng-non-bindable>`{{personCount}}`</span>. The closed braces `{}` is a placeholder\n * for <span ng-non-bindable>{{numberExpression}}</span>.\n *\n * # Configuring ngPluralize with offset\n * The `offset` attribute allows further customization of pluralized text, which can result in\n * a better user experience. For example, instead of the message \"4 people are viewing this document\",\n * you might display \"John, Kate and 2 others are viewing this document\".\n * The offset attribute allows you to offset a number by any desired value.\n * Let's take a look at an example:\n *\n * ```html\n * <ng-pluralize count=\"personCount\" offset=2\n *               when=\"{'0': 'Nobody is viewing.',\n *                      '1': '{{person1}} is viewing.',\n *                      '2': '{{person1}} and {{person2}} are viewing.',\n *                      'one': '{{person1}}, {{person2}} and one other person are viewing.',\n *                      'other': '{{person1}}, {{person2}} and {} other people are viewing.'}\">\n * </ng-pluralize>\n * ```\n *\n * Notice that we are still using two plural categories(one, other), but we added\n * three explicit number rules 0, 1 and 2.\n * When one person, perhaps John, views the document, \"John is viewing\" will be shown.\n * When three people view the document, no explicit number rule is found, so\n * an offset of 2 is taken off 3, and Angular uses 1 to decide the plural category.\n * In this case, plural category 'one' is matched and \"John, Mary and one other person are viewing\"\n * is shown.\n *\n * Note that when you specify offsets, you must provide explicit number rules for\n * numbers from 0 up to and including the offset. If you use an offset of 3, for example,\n * you must provide explicit number rules for 0, 1, 2 and 3. You must also provide plural strings for\n * plural categories \"one\" and \"other\".\n *\n * @param {string|expression} count The variable to be bound to.\n * @param {string} when The mapping between plural category to its corresponding strings.\n * @param {number=} offset Offset to deduct from the total number.\n *\n * @example\n    <example module=\"pluralizeExample\">\n      <file name=\"index.html\">\n        <script>\n          angular.module('pluralizeExample', [])\n            .controller('ExampleController', ['$scope', function($scope) {\n              $scope.person1 = 'Igor';\n              $scope.person2 = 'Misko';\n              $scope.personCount = 1;\n            }]);\n        </script>\n        <div ng-controller=\"ExampleController\">\n          Person 1:<input type=\"text\" ng-model=\"person1\" value=\"Igor\" /><br/>\n          Person 2:<input type=\"text\" ng-model=\"person2\" value=\"Misko\" /><br/>\n          Number of People:<input type=\"text\" ng-model=\"personCount\" value=\"1\" /><br/>\n\n          <!--- Example with simple pluralization rules for en locale --->\n          Without Offset:\n          <ng-pluralize count=\"personCount\"\n                        when=\"{'0': 'Nobody is viewing.',\n                               'one': '1 person is viewing.',\n                               'other': '{} people are viewing.'}\">\n          </ng-pluralize><br>\n\n          <!--- Example with offset --->\n          With Offset(2):\n          <ng-pluralize count=\"personCount\" offset=2\n                        when=\"{'0': 'Nobody is viewing.',\n                               '1': '{{person1}} is viewing.',\n                               '2': '{{person1}} and {{person2}} are viewing.',\n                               'one': '{{person1}}, {{person2}} and one other person are viewing.',\n                               'other': '{{person1}}, {{person2}} and {} other people are viewing.'}\">\n          </ng-pluralize>\n        </div>\n      </file>\n      <file name=\"protractor.js\" type=\"protractor\">\n        it('should show correct pluralized string', function() {\n          var withoutOffset = element.all(by.css('ng-pluralize')).get(0);\n          var withOffset = element.all(by.css('ng-pluralize')).get(1);\n          var countInput = element(by.model('personCount'));\n\n          expect(withoutOffset.getText()).toEqual('1 person is viewing.');\n          expect(withOffset.getText()).toEqual('Igor is viewing.');\n\n          countInput.clear();\n          countInput.sendKeys('0');\n\n          expect(withoutOffset.getText()).toEqual('Nobody is viewing.');\n          expect(withOffset.getText()).toEqual('Nobody is viewing.');\n\n          countInput.clear();\n          countInput.sendKeys('2');\n\n          expect(withoutOffset.getText()).toEqual('2 people are viewing.');\n          expect(withOffset.getText()).toEqual('Igor and Misko are viewing.');\n\n          countInput.clear();\n          countInput.sendKeys('3');\n\n          expect(withoutOffset.getText()).toEqual('3 people are viewing.');\n          expect(withOffset.getText()).toEqual('Igor, Misko and one other person are viewing.');\n\n          countInput.clear();\n          countInput.sendKeys('4');\n\n          expect(withoutOffset.getText()).toEqual('4 people are viewing.');\n          expect(withOffset.getText()).toEqual('Igor, Misko and 2 other people are viewing.');\n        });\n        it('should show data-bound names', function() {\n          var withOffset = element.all(by.css('ng-pluralize')).get(1);\n          var personCount = element(by.model('personCount'));\n          var person1 = element(by.model('person1'));\n          var person2 = element(by.model('person2'));\n          personCount.clear();\n          personCount.sendKeys('4');\n          person1.clear();\n          person1.sendKeys('Di');\n          person2.clear();\n          person2.sendKeys('Vojta');\n          expect(withOffset.getText()).toEqual('Di, Vojta and 2 other people are viewing.');\n        });\n      </file>\n    </example>\n */\nvar ngPluralizeDirective = ['$locale', '$interpolate', function($locale, $interpolate) {\n  var BRACE = /{}/g,\n      IS_WHEN = /^when(Minus)?(.+)$/;\n\n  return {\n    restrict: 'EA',\n    link: function(scope, element, attr) {\n      var numberExp = attr.count,\n          whenExp = attr.$attr.when && element.attr(attr.$attr.when), // we have {{}} in attrs\n          offset = attr.offset || 0,\n          whens = scope.$eval(whenExp) || {},\n          whensExpFns = {},\n          startSymbol = $interpolate.startSymbol(),\n          endSymbol = $interpolate.endSymbol(),\n          braceReplacement = startSymbol + numberExp + '-' + offset + endSymbol,\n          watchRemover = angular.noop,\n          lastCount;\n\n      forEach(attr, function(expression, attributeName) {\n        var tmpMatch = IS_WHEN.exec(attributeName);\n        if (tmpMatch) {\n          var whenKey = (tmpMatch[1] ? '-' : '') + lowercase(tmpMatch[2]);\n          whens[whenKey] = element.attr(attr.$attr[attributeName]);\n        }\n      });\n      forEach(whens, function(expression, key) {\n        whensExpFns[key] = $interpolate(expression.replace(BRACE, braceReplacement));\n\n      });\n\n      scope.$watch(numberExp, function ngPluralizeWatchAction(newVal) {\n        var count = parseFloat(newVal);\n        var countIsNaN = isNaN(count);\n\n        if (!countIsNaN && !(count in whens)) {\n          // If an explicit number rule such as 1, 2, 3... is defined, just use it.\n          // Otherwise, check it against pluralization rules in $locale service.\n          count = $locale.pluralCat(count - offset);\n        }\n\n        // If both `count` and `lastCount` are NaN, we don't need to re-register a watch.\n        // In JS `NaN !== NaN`, so we have to exlicitly check.\n        if ((count !== lastCount) && !(countIsNaN && isNaN(lastCount))) {\n          watchRemover();\n          watchRemover = scope.$watch(whensExpFns[count], updateElementText);\n          lastCount = count;\n        }\n      });\n\n      function updateElementText(newText) {\n        element.text(newText || '');\n      }\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ngRepeat\n *\n * @description\n * The `ngRepeat` directive instantiates a template once per item from a collection. Each template\n * instance gets its own scope, where the given loop variable is set to the current collection item,\n * and `$index` is set to the item index or key.\n *\n * Special properties are exposed on the local scope of each template instance, including:\n *\n * | Variable  | Type            | Details                                                                     |\n * |-----------|-----------------|-----------------------------------------------------------------------------|\n * | `$index`  | {@type number}  | iterator offset of the repeated element (0..length-1)                       |\n * | `$first`  | {@type boolean} | true if the repeated element is first in the iterator.                      |\n * | `$middle` | {@type boolean} | true if the repeated element is between the first and last in the iterator. |\n * | `$last`   | {@type boolean} | true if the repeated element is last in the iterator.                       |\n * | `$even`   | {@type boolean} | true if the iterator position `$index` is even (otherwise false).           |\n * | `$odd`    | {@type boolean} | true if the iterator position `$index` is odd (otherwise false).            |\n *\n * Creating aliases for these properties is possible with {@link ng.directive:ngInit `ngInit`}.\n * This may be useful when, for instance, nesting ngRepeats.\n *\n * # Iterating over object properties\n *\n * It is possible to get `ngRepeat` to iterate over the properties of an object using the following\n * syntax:\n *\n * ```js\n * <div ng-repeat=\"(key, value) in myObj\"> ... </div>\n * ```\n *\n * You need to be aware that the JavaScript specification does not define what order\n * it will return the keys for an object. In order to have a guaranteed deterministic order\n * for the keys, Angular versions up to and including 1.3 **sort the keys alphabetically**.\n *\n * If this is not desired, the recommended workaround is to convert your object into an array\n * that is sorted into the order that you prefer before providing it to `ngRepeat`.  You could\n * do this with a filter such as [toArrayFilter](http://ngmodules.org/modules/angular-toArrayFilter)\n * or implement a `$watch` on the object yourself.\n *\n * In version 1.4 we will remove the sorting, since it seems that browsers generally follow the\n * strategy of providing keys in the order in which they were defined, although there are exceptions\n * when keys are deleted and reinstated.\n *\n *\n * # Special repeat start and end points\n * To repeat a series of elements instead of just one parent element, ngRepeat (as well as other ng directives) supports extending\n * the range of the repeater by defining explicit start and end points by using **ng-repeat-start** and **ng-repeat-end** respectively.\n * The **ng-repeat-start** directive works the same as **ng-repeat**, but will repeat all the HTML code (including the tag it's defined on)\n * up to and including the ending HTML tag where **ng-repeat-end** is placed.\n *\n * The example below makes use of this feature:\n * ```html\n *   <header ng-repeat-start=\"item in items\">\n *     Header {{ item }}\n *   </header>\n *   <div class=\"body\">\n *     Body {{ item }}\n *   </div>\n *   <footer ng-repeat-end>\n *     Footer {{ item }}\n *   </footer>\n * ```\n *\n * And with an input of {@type ['A','B']} for the items variable in the example above, the output will evaluate to:\n * ```html\n *   <header>\n *     Header A\n *   </header>\n *   <div class=\"body\">\n *     Body A\n *   </div>\n *   <footer>\n *     Footer A\n *   </footer>\n *   <header>\n *     Header B\n *   </header>\n *   <div class=\"body\">\n *     Body B\n *   </div>\n *   <footer>\n *     Footer B\n *   </footer>\n * ```\n *\n * The custom start and end points for ngRepeat also support all other HTML directive syntax flavors provided in AngularJS (such\n * as **data-ng-repeat-start**, **x-ng-repeat-start** and **ng:repeat-start**).\n *\n * @animations\n * **.enter** - when a new item is added to the list or when an item is revealed after a filter\n *\n * **.leave** - when an item is removed from the list or when an item is filtered out\n *\n * **.move** - when an adjacent item is filtered out causing a reorder or when the item contents are reordered\n *\n * @element ANY\n * @scope\n * @priority 1000\n * @param {repeat_expression} ngRepeat The expression indicating how to enumerate a collection. These\n *   formats are currently supported:\n *\n *   * `variable in expression` – where variable is the user defined loop variable and `expression`\n *     is a scope expression giving the collection to enumerate.\n *\n *     For example: `album in artist.albums`.\n *\n *   * `(key, value) in expression` – where `key` and `value` can be any user defined identifiers,\n *     and `expression` is the scope expression giving the collection to enumerate.\n *\n *     For example: `(name, age) in {'adam':10, 'amalie':12}`.\n *\n *   * `variable in expression track by tracking_expression` – You can also provide an optional tracking function\n *     which can be used to associate the objects in the collection with the DOM elements. If no tracking function\n *     is specified the ng-repeat associates elements by identity in the collection. It is an error to have\n *     more than one tracking function to resolve to the same key. (This would mean that two distinct objects are\n *     mapped to the same DOM element, which is not possible.)  Filters should be applied to the expression,\n *     before specifying a tracking expression.\n *\n *     For example: `item in items` is equivalent to `item in items track by $id(item)`. This implies that the DOM elements\n *     will be associated by item identity in the array.\n *\n *     For example: `item in items track by $id(item)`. A built in `$id()` function can be used to assign a unique\n *     `$$hashKey` property to each item in the array. This property is then used as a key to associated DOM elements\n *     with the corresponding item in the array by identity. Moving the same object in array would move the DOM\n *     element in the same way in the DOM.\n *\n *     For example: `item in items track by item.id` is a typical pattern when the items come from the database. In this\n *     case the object identity does not matter. Two objects are considered equivalent as long as their `id`\n *     property is same.\n *\n *     For example: `item in items | filter:searchText track by item.id` is a pattern that might be used to apply a filter\n *     to items in conjunction with a tracking expression.\n *\n *   * `variable in expression as alias_expression` – You can also provide an optional alias expression which will then store the\n *     intermediate results of the repeater after the filters have been applied. Typically this is used to render a special message\n *     when a filter is active on the repeater, but the filtered result set is empty.\n *\n *     For example: `item in items | filter:x as results` will store the fragment of the repeated items as `results`, but only after\n *     the items have been processed through the filter.\n *\n * @example\n * This example initializes the scope to a list of names and\n * then uses `ngRepeat` to display every person:\n  <example module=\"ngAnimate\" deps=\"angular-animate.js\" animations=\"true\">\n    <file name=\"index.html\">\n      <div ng-init=\"friends = [\n        {name:'John', age:25, gender:'boy'},\n        {name:'Jessie', age:30, gender:'girl'},\n        {name:'Johanna', age:28, gender:'girl'},\n        {name:'Joy', age:15, gender:'girl'},\n        {name:'Mary', age:28, gender:'girl'},\n        {name:'Peter', age:95, gender:'boy'},\n        {name:'Sebastian', age:50, gender:'boy'},\n        {name:'Erika', age:27, gender:'girl'},\n        {name:'Patrick', age:40, gender:'boy'},\n        {name:'Samantha', age:60, gender:'girl'}\n      ]\">\n        I have {{friends.length}} friends. They are:\n        <input type=\"search\" ng-model=\"q\" placeholder=\"filter friends...\" />\n        <ul class=\"example-animate-container\">\n          <li class=\"animate-repeat\" ng-repeat=\"friend in friends | filter:q as results\">\n            [{{$index + 1}}] {{friend.name}} who is {{friend.age}} years old.\n          </li>\n          <li class=\"animate-repeat\" ng-if=\"results.length == 0\">\n            <strong>No results found...</strong>\n          </li>\n        </ul>\n      </div>\n    </file>\n    <file name=\"animations.css\">\n      .example-animate-container {\n        background:white;\n        border:1px solid black;\n        list-style:none;\n        margin:0;\n        padding:0 10px;\n      }\n\n      .animate-repeat {\n        line-height:40px;\n        list-style:none;\n        box-sizing:border-box;\n      }\n\n      .animate-repeat.ng-move,\n      .animate-repeat.ng-enter,\n      .animate-repeat.ng-leave {\n        -webkit-transition:all linear 0.5s;\n        transition:all linear 0.5s;\n      }\n\n      .animate-repeat.ng-leave.ng-leave-active,\n      .animate-repeat.ng-move,\n      .animate-repeat.ng-enter {\n        opacity:0;\n        max-height:0;\n      }\n\n      .animate-repeat.ng-leave,\n      .animate-repeat.ng-move.ng-move-active,\n      .animate-repeat.ng-enter.ng-enter-active {\n        opacity:1;\n        max-height:40px;\n      }\n    </file>\n    <file name=\"protractor.js\" type=\"protractor\">\n      var friends = element.all(by.repeater('friend in friends'));\n\n      it('should render initial data set', function() {\n        expect(friends.count()).toBe(10);\n        expect(friends.get(0).getText()).toEqual('[1] John who is 25 years old.');\n        expect(friends.get(1).getText()).toEqual('[2] Jessie who is 30 years old.');\n        expect(friends.last().getText()).toEqual('[10] Samantha who is 60 years old.');\n        expect(element(by.binding('friends.length')).getText())\n            .toMatch(\"I have 10 friends. They are:\");\n      });\n\n       it('should update repeater when filter predicate changes', function() {\n         expect(friends.count()).toBe(10);\n\n         element(by.model('q')).sendKeys('ma');\n\n         expect(friends.count()).toBe(2);\n         expect(friends.get(0).getText()).toEqual('[1] Mary who is 28 years old.');\n         expect(friends.last().getText()).toEqual('[2] Samantha who is 60 years old.');\n       });\n      </file>\n    </example>\n */\nvar ngRepeatDirective = ['$parse', '$animate', function($parse, $animate) {\n  var NG_REMOVED = '$$NG_REMOVED';\n  var ngRepeatMinErr = minErr('ngRepeat');\n\n  var updateScope = function(scope, index, valueIdentifier, value, keyIdentifier, key, arrayLength) {\n    // TODO(perf): generate setters to shave off ~40ms or 1-1.5%\n    scope[valueIdentifier] = value;\n    if (keyIdentifier) scope[keyIdentifier] = key;\n    scope.$index = index;\n    scope.$first = (index === 0);\n    scope.$last = (index === (arrayLength - 1));\n    scope.$middle = !(scope.$first || scope.$last);\n    // jshint bitwise: false\n    scope.$odd = !(scope.$even = (index&1) === 0);\n    // jshint bitwise: true\n  };\n\n  var getBlockStart = function(block) {\n    return block.clone[0];\n  };\n\n  var getBlockEnd = function(block) {\n    return block.clone[block.clone.length - 1];\n  };\n\n\n  return {\n    restrict: 'A',\n    multiElement: true,\n    transclude: 'element',\n    priority: 1000,\n    terminal: true,\n    $$tlb: true,\n    compile: function ngRepeatCompile($element, $attr) {\n      var expression = $attr.ngRepeat;\n      var ngRepeatEndComment = document.createComment(' end ngRepeat: ' + expression + ' ');\n\n      var match = expression.match(/^\\s*([\\s\\S]+?)\\s+in\\s+([\\s\\S]+?)(?:\\s+as\\s+([\\s\\S]+?))?(?:\\s+track\\s+by\\s+([\\s\\S]+?))?\\s*$/);\n\n      if (!match) {\n        throw ngRepeatMinErr('iexp', \"Expected expression in form of '_item_ in _collection_[ track by _id_]' but got '{0}'.\",\n            expression);\n      }\n\n      var lhs = match[1];\n      var rhs = match[2];\n      var aliasAs = match[3];\n      var trackByExp = match[4];\n\n      match = lhs.match(/^(?:(\\s*[\\$\\w]+)|\\(\\s*([\\$\\w]+)\\s*,\\s*([\\$\\w]+)\\s*\\))$/);\n\n      if (!match) {\n        throw ngRepeatMinErr('iidexp', \"'_item_' in '_item_ in _collection_' should be an identifier or '(_key_, _value_)' expression, but got '{0}'.\",\n            lhs);\n      }\n      var valueIdentifier = match[3] || match[1];\n      var keyIdentifier = match[2];\n\n      if (aliasAs && (!/^[$a-zA-Z_][$a-zA-Z0-9_]*$/.test(aliasAs) ||\n          /^(null|undefined|this|\\$index|\\$first|\\$middle|\\$last|\\$even|\\$odd|\\$parent|\\$root|\\$id)$/.test(aliasAs))) {\n        throw ngRepeatMinErr('badident', \"alias '{0}' is invalid --- must be a valid JS identifier which is not a reserved name.\",\n          aliasAs);\n      }\n\n      var trackByExpGetter, trackByIdExpFn, trackByIdArrayFn, trackByIdObjFn;\n      var hashFnLocals = {$id: hashKey};\n\n      if (trackByExp) {\n        trackByExpGetter = $parse(trackByExp);\n      } else {\n        trackByIdArrayFn = function(key, value) {\n          return hashKey(value);\n        };\n        trackByIdObjFn = function(key) {\n          return key;\n        };\n      }\n\n      return function ngRepeatLink($scope, $element, $attr, ctrl, $transclude) {\n\n        if (trackByExpGetter) {\n          trackByIdExpFn = function(key, value, index) {\n            // assign key, value, and $index to the locals so that they can be used in hash functions\n            if (keyIdentifier) hashFnLocals[keyIdentifier] = key;\n            hashFnLocals[valueIdentifier] = value;\n            hashFnLocals.$index = index;\n            return trackByExpGetter($scope, hashFnLocals);\n          };\n        }\n\n        // Store a list of elements from previous run. This is a hash where key is the item from the\n        // iterator, and the value is objects with following properties.\n        //   - scope: bound scope\n        //   - element: previous element.\n        //   - index: position\n        //\n        // We are using no-proto object so that we don't need to guard against inherited props via\n        // hasOwnProperty.\n        var lastBlockMap = createMap();\n\n        //watch props\n        $scope.$watchCollection(rhs, function ngRepeatAction(collection) {\n          var index, length,\n              previousNode = $element[0],     // node that cloned nodes should be inserted after\n                                              // initialized to the comment node anchor\n              nextNode,\n              // Same as lastBlockMap but it has the current state. It will become the\n              // lastBlockMap on the next iteration.\n              nextBlockMap = createMap(),\n              collectionLength,\n              key, value, // key/value of iteration\n              trackById,\n              trackByIdFn,\n              collectionKeys,\n              block,       // last object information {scope, element, id}\n              nextBlockOrder,\n              elementsToRemove;\n\n          if (aliasAs) {\n            $scope[aliasAs] = collection;\n          }\n\n          if (isArrayLike(collection)) {\n            collectionKeys = collection;\n            trackByIdFn = trackByIdExpFn || trackByIdArrayFn;\n          } else {\n            trackByIdFn = trackByIdExpFn || trackByIdObjFn;\n            // if object, extract keys, sort them and use to determine order of iteration over obj props\n            collectionKeys = [];\n            for (var itemKey in collection) {\n              if (collection.hasOwnProperty(itemKey) && itemKey.charAt(0) != '$') {\n                collectionKeys.push(itemKey);\n              }\n            }\n            collectionKeys.sort();\n          }\n\n          collectionLength = collectionKeys.length;\n          nextBlockOrder = new Array(collectionLength);\n\n          // locate existing items\n          for (index = 0; index < collectionLength; index++) {\n            key = (collection === collectionKeys) ? index : collectionKeys[index];\n            value = collection[key];\n            trackById = trackByIdFn(key, value, index);\n            if (lastBlockMap[trackById]) {\n              // found previously seen block\n              block = lastBlockMap[trackById];\n              delete lastBlockMap[trackById];\n              nextBlockMap[trackById] = block;\n              nextBlockOrder[index] = block;\n            } else if (nextBlockMap[trackById]) {\n              // if collision detected. restore lastBlockMap and throw an error\n              forEach(nextBlockOrder, function(block) {\n                if (block && block.scope) lastBlockMap[block.id] = block;\n              });\n              throw ngRepeatMinErr('dupes',\n                  \"Duplicates in a repeater are not allowed. Use 'track by' expression to specify unique keys. Repeater: {0}, Duplicate key: {1}, Duplicate value: {2}\",\n                  expression, trackById, value);\n            } else {\n              // new never before seen block\n              nextBlockOrder[index] = {id: trackById, scope: undefined, clone: undefined};\n              nextBlockMap[trackById] = true;\n            }\n          }\n\n          // remove leftover items\n          for (var blockKey in lastBlockMap) {\n            block = lastBlockMap[blockKey];\n            elementsToRemove = getBlockNodes(block.clone);\n            $animate.leave(elementsToRemove);\n            if (elementsToRemove[0].parentNode) {\n              // if the element was not removed yet because of pending animation, mark it as deleted\n              // so that we can ignore it later\n              for (index = 0, length = elementsToRemove.length; index < length; index++) {\n                elementsToRemove[index][NG_REMOVED] = true;\n              }\n            }\n            block.scope.$destroy();\n          }\n\n          // we are not using forEach for perf reasons (trying to avoid #call)\n          for (index = 0; index < collectionLength; index++) {\n            key = (collection === collectionKeys) ? index : collectionKeys[index];\n            value = collection[key];\n            block = nextBlockOrder[index];\n\n            if (block.scope) {\n              // if we have already seen this object, then we need to reuse the\n              // associated scope/element\n\n              nextNode = previousNode;\n\n              // skip nodes that are already pending removal via leave animation\n              do {\n                nextNode = nextNode.nextSibling;\n              } while (nextNode && nextNode[NG_REMOVED]);\n\n              if (getBlockStart(block) != nextNode) {\n                // existing item which got moved\n                $animate.move(getBlockNodes(block.clone), null, jqLite(previousNode));\n              }\n              previousNode = getBlockEnd(block);\n              updateScope(block.scope, index, valueIdentifier, value, keyIdentifier, key, collectionLength);\n            } else {\n              // new item which we don't know about\n              $transclude(function ngRepeatTransclude(clone, scope) {\n                block.scope = scope;\n                // http://jsperf.com/clone-vs-createcomment\n                var endNode = ngRepeatEndComment.cloneNode(false);\n                clone[clone.length++] = endNode;\n\n                // TODO(perf): support naked previousNode in `enter` to avoid creation of jqLite wrapper?\n                $animate.enter(clone, null, jqLite(previousNode));\n                previousNode = endNode;\n                // Note: We only need the first/last node of the cloned nodes.\n                // However, we need to keep the reference to the jqlite wrapper as it might be changed later\n                // by a directive with templateUrl when its template arrives.\n                block.clone = clone;\n                nextBlockMap[block.id] = block;\n                updateScope(block.scope, index, valueIdentifier, value, keyIdentifier, key, collectionLength);\n              });\n            }\n          }\n          lastBlockMap = nextBlockMap;\n        });\n      };\n    }\n  };\n}];\n\nvar NG_HIDE_CLASS = 'ng-hide';\nvar NG_HIDE_IN_PROGRESS_CLASS = 'ng-hide-animate';\n/**\n * @ngdoc directive\n * @name ngShow\n *\n * @description\n * The `ngShow` directive shows or hides the given HTML element based on the expression\n * provided to the `ngShow` attribute. The element is shown or hidden by removing or adding\n * the `.ng-hide` CSS class onto the element. The `.ng-hide` CSS class is predefined\n * in AngularJS and sets the display style to none (using an !important flag).\n * For CSP mode please add `angular-csp.css` to your html file (see {@link ng.directive:ngCsp ngCsp}).\n *\n * ```html\n * <!-- when $scope.myValue is truthy (element is visible) -->\n * <div ng-show=\"myValue\"></div>\n *\n * <!-- when $scope.myValue is falsy (element is hidden) -->\n * <div ng-show=\"myValue\" class=\"ng-hide\"></div>\n * ```\n *\n * When the `ngShow` expression evaluates to a falsy value then the `.ng-hide` CSS class is added to the class\n * attribute on the element causing it to become hidden. When truthy, the `.ng-hide` CSS class is removed\n * from the element causing the element not to appear hidden.\n *\n * ## Why is !important used?\n *\n * You may be wondering why !important is used for the `.ng-hide` CSS class. This is because the `.ng-hide` selector\n * can be easily overridden by heavier selectors. For example, something as simple\n * as changing the display style on a HTML list item would make hidden elements appear visible.\n * This also becomes a bigger issue when dealing with CSS frameworks.\n *\n * By using !important, the show and hide behavior will work as expected despite any clash between CSS selector\n * specificity (when !important isn't used with any conflicting styles). If a developer chooses to override the\n * styling to change how to hide an element then it is just a matter of using !important in their own CSS code.\n *\n * ### Overriding `.ng-hide`\n *\n * By default, the `.ng-hide` class will style the element with `display: none!important`. If you wish to change\n * the hide behavior with ngShow/ngHide then this can be achieved by restating the styles for the `.ng-hide`\n * class CSS. Note that the selector that needs to be used is actually `.ng-hide:not(.ng-hide-animate)` to cope\n * with extra animation classes that can be added.\n *\n * ```css\n * .ng-hide:not(.ng-hide-animate) {\n *   /&#42; this is just another form of hiding an element &#42;/\n *   display: block!important;\n *   position: absolute;\n *   top: -9999px;\n *   left: -9999px;\n * }\n * ```\n *\n * By default you don't need to override in CSS anything and the animations will work around the display style.\n *\n * ## A note about animations with `ngShow`\n *\n * Animations in ngShow/ngHide work with the show and hide events that are triggered when the directive expression\n * is true and false. This system works like the animation system present with ngClass except that\n * you must also include the !important flag to override the display property\n * so that you can perform an animation when the element is hidden during the time of the animation.\n *\n * ```css\n * //\n * //a working example can be found at the bottom of this page\n * //\n * .my-element.ng-hide-add, .my-element.ng-hide-remove {\n *   /&#42; this is required as of 1.3x to properly\n *      apply all styling in a show/hide animation &#42;/\n *   transition: 0s linear all;\n * }\n *\n * .my-element.ng-hide-add-active,\n * .my-element.ng-hide-remove-active {\n *   /&#42; the transition is defined in the active class &#42;/\n *   transition: 1s linear all;\n * }\n *\n * .my-element.ng-hide-add { ... }\n * .my-element.ng-hide-add.ng-hide-add-active { ... }\n * .my-element.ng-hide-remove { ... }\n * .my-element.ng-hide-remove.ng-hide-remove-active { ... }\n * ```\n *\n * Keep in mind that, as of AngularJS version 1.3.0-beta.11, there is no need to change the display\n * property to block during animation states--ngAnimate will handle the style toggling automatically for you.\n *\n * @animations\n * addClass: `.ng-hide` - happens after the `ngShow` expression evaluates to a truthy value and the just before contents are set to visible\n * removeClass: `.ng-hide` - happens after the `ngShow` expression evaluates to a non truthy value and just before the contents are set to hidden\n *\n * @element ANY\n * @param {expression} ngShow If the {@link guide/expression expression} is truthy\n *     then the element is shown or hidden respectively.\n *\n * @example\n  <example module=\"ngAnimate\" deps=\"angular-animate.js\" animations=\"true\">\n    <file name=\"index.html\">\n      Click me: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n      <div>\n        Show:\n        <div class=\"check-element animate-show\" ng-show=\"checked\">\n          <span class=\"glyphicon glyphicon-thumbs-up\"></span> I show up when your checkbox is checked.\n        </div>\n      </div>\n      <div>\n        Hide:\n        <div class=\"check-element animate-show\" ng-hide=\"checked\">\n          <span class=\"glyphicon glyphicon-thumbs-down\"></span> I hide when your checkbox is checked.\n        </div>\n      </div>\n    </file>\n    <file name=\"glyphicons.css\">\n      @import url(../../components/bootstrap-3.1.1/css/bootstrap.css);\n    </file>\n    <file name=\"animations.css\">\n      .animate-show {\n        line-height: 20px;\n        opacity: 1;\n        padding: 10px;\n        border: 1px solid black;\n        background: white;\n      }\n\n      .animate-show.ng-hide-add.ng-hide-add-active,\n      .animate-show.ng-hide-remove.ng-hide-remove-active {\n        -webkit-transition: all linear 0.5s;\n        transition: all linear 0.5s;\n      }\n\n      .animate-show.ng-hide {\n        line-height: 0;\n        opacity: 0;\n        padding: 0 10px;\n      }\n\n      .check-element {\n        padding: 10px;\n        border: 1px solid black;\n        background: white;\n      }\n    </file>\n    <file name=\"protractor.js\" type=\"protractor\">\n      var thumbsUp = element(by.css('span.glyphicon-thumbs-up'));\n      var thumbsDown = element(by.css('span.glyphicon-thumbs-down'));\n\n      it('should check ng-show / ng-hide', function() {\n        expect(thumbsUp.isDisplayed()).toBeFalsy();\n        expect(thumbsDown.isDisplayed()).toBeTruthy();\n\n        element(by.model('checked')).click();\n\n        expect(thumbsUp.isDisplayed()).toBeTruthy();\n        expect(thumbsDown.isDisplayed()).toBeFalsy();\n      });\n    </file>\n  </example>\n */\nvar ngShowDirective = ['$animate', function($animate) {\n  return {\n    restrict: 'A',\n    multiElement: true,\n    link: function(scope, element, attr) {\n      scope.$watch(attr.ngShow, function ngShowWatchAction(value) {\n        // we're adding a temporary, animation-specific class for ng-hide since this way\n        // we can control when the element is actually displayed on screen without having\n        // to have a global/greedy CSS selector that breaks when other animations are run.\n        // Read: https://github.com/angular/angular.js/issues/9103#issuecomment-58335845\n        $animate[value ? 'removeClass' : 'addClass'](element, NG_HIDE_CLASS, {\n          tempClasses: NG_HIDE_IN_PROGRESS_CLASS\n        });\n      });\n    }\n  };\n}];\n\n\n/**\n * @ngdoc directive\n * @name ngHide\n *\n * @description\n * The `ngHide` directive shows or hides the given HTML element based on the expression\n * provided to the `ngHide` attribute. The element is shown or hidden by removing or adding\n * the `ng-hide` CSS class onto the element. The `.ng-hide` CSS class is predefined\n * in AngularJS and sets the display style to none (using an !important flag).\n * For CSP mode please add `angular-csp.css` to your html file (see {@link ng.directive:ngCsp ngCsp}).\n *\n * ```html\n * <!-- when $scope.myValue is truthy (element is hidden) -->\n * <div ng-hide=\"myValue\" class=\"ng-hide\"></div>\n *\n * <!-- when $scope.myValue is falsy (element is visible) -->\n * <div ng-hide=\"myValue\"></div>\n * ```\n *\n * When the `ngHide` expression evaluates to a truthy value then the `.ng-hide` CSS class is added to the class\n * attribute on the element causing it to become hidden. When falsy, the `.ng-hide` CSS class is removed\n * from the element causing the element not to appear hidden.\n *\n * ## Why is !important used?\n *\n * You may be wondering why !important is used for the `.ng-hide` CSS class. This is because the `.ng-hide` selector\n * can be easily overridden by heavier selectors. For example, something as simple\n * as changing the display style on a HTML list item would make hidden elements appear visible.\n * This also becomes a bigger issue when dealing with CSS frameworks.\n *\n * By using !important, the show and hide behavior will work as expected despite any clash between CSS selector\n * specificity (when !important isn't used with any conflicting styles). If a developer chooses to override the\n * styling to change how to hide an element then it is just a matter of using !important in their own CSS code.\n *\n * ### Overriding `.ng-hide`\n *\n * By default, the `.ng-hide` class will style the element with `display: none!important`. If you wish to change\n * the hide behavior with ngShow/ngHide then this can be achieved by restating the styles for the `.ng-hide`\n * class in CSS:\n *\n * ```css\n * .ng-hide {\n *   /&#42; this is just another form of hiding an element &#42;/\n *   display: block!important;\n *   position: absolute;\n *   top: -9999px;\n *   left: -9999px;\n * }\n * ```\n *\n * By default you don't need to override in CSS anything and the animations will work around the display style.\n *\n * ## A note about animations with `ngHide`\n *\n * Animations in ngShow/ngHide work with the show and hide events that are triggered when the directive expression\n * is true and false. This system works like the animation system present with ngClass, except that the `.ng-hide`\n * CSS class is added and removed for you instead of your own CSS class.\n *\n * ```css\n * //\n * //a working example can be found at the bottom of this page\n * //\n * .my-element.ng-hide-add, .my-element.ng-hide-remove {\n *   transition: 0.5s linear all;\n * }\n *\n * .my-element.ng-hide-add { ... }\n * .my-element.ng-hide-add.ng-hide-add-active { ... }\n * .my-element.ng-hide-remove { ... }\n * .my-element.ng-hide-remove.ng-hide-remove-active { ... }\n * ```\n *\n * Keep in mind that, as of AngularJS version 1.3.0-beta.11, there is no need to change the display\n * property to block during animation states--ngAnimate will handle the style toggling automatically for you.\n *\n * @animations\n * removeClass: `.ng-hide` - happens after the `ngHide` expression evaluates to a truthy value and just before the contents are set to hidden\n * addClass: `.ng-hide` - happens after the `ngHide` expression evaluates to a non truthy value and just before the contents are set to visible\n *\n * @element ANY\n * @param {expression} ngHide If the {@link guide/expression expression} is truthy then\n *     the element is shown or hidden respectively.\n *\n * @example\n  <example module=\"ngAnimate\" deps=\"angular-animate.js\" animations=\"true\">\n    <file name=\"index.html\">\n      Click me: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n      <div>\n        Show:\n        <div class=\"check-element animate-hide\" ng-show=\"checked\">\n          <span class=\"glyphicon glyphicon-thumbs-up\"></span> I show up when your checkbox is checked.\n        </div>\n      </div>\n      <div>\n        Hide:\n        <div class=\"check-element animate-hide\" ng-hide=\"checked\">\n          <span class=\"glyphicon glyphicon-thumbs-down\"></span> I hide when your checkbox is checked.\n        </div>\n      </div>\n    </file>\n    <file name=\"glyphicons.css\">\n      @import url(../../components/bootstrap-3.1.1/css/bootstrap.css);\n    </file>\n    <file name=\"animations.css\">\n      .animate-hide {\n        -webkit-transition: all linear 0.5s;\n        transition: all linear 0.5s;\n        line-height: 20px;\n        opacity: 1;\n        padding: 10px;\n        border: 1px solid black;\n        background: white;\n      }\n\n      .animate-hide.ng-hide {\n        line-height: 0;\n        opacity: 0;\n        padding: 0 10px;\n      }\n\n      .check-element {\n        padding: 10px;\n        border: 1px solid black;\n        background: white;\n      }\n    </file>\n    <file name=\"protractor.js\" type=\"protractor\">\n      var thumbsUp = element(by.css('span.glyphicon-thumbs-up'));\n      var thumbsDown = element(by.css('span.glyphicon-thumbs-down'));\n\n      it('should check ng-show / ng-hide', function() {\n        expect(thumbsUp.isDisplayed()).toBeFalsy();\n        expect(thumbsDown.isDisplayed()).toBeTruthy();\n\n        element(by.model('checked')).click();\n\n        expect(thumbsUp.isDisplayed()).toBeTruthy();\n        expect(thumbsDown.isDisplayed()).toBeFalsy();\n      });\n    </file>\n  </example>\n */\nvar ngHideDirective = ['$animate', function($animate) {\n  return {\n    restrict: 'A',\n    multiElement: true,\n    link: function(scope, element, attr) {\n      scope.$watch(attr.ngHide, function ngHideWatchAction(value) {\n        // The comment inside of the ngShowDirective explains why we add and\n        // remove a temporary class for the show/hide animation\n        $animate[value ? 'addClass' : 'removeClass'](element,NG_HIDE_CLASS, {\n          tempClasses: NG_HIDE_IN_PROGRESS_CLASS\n        });\n      });\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ngStyle\n * @restrict AC\n *\n * @description\n * The `ngStyle` directive allows you to set CSS style on an HTML element conditionally.\n *\n * @element ANY\n * @param {expression} ngStyle\n *\n * {@link guide/expression Expression} which evals to an\n * object whose keys are CSS style names and values are corresponding values for those CSS\n * keys.\n *\n * Since some CSS style names are not valid keys for an object, they must be quoted.\n * See the 'background-color' style in the example below.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <input type=\"button\" value=\"set color\" ng-click=\"myStyle={color:'red'}\">\n        <input type=\"button\" value=\"set background\" ng-click=\"myStyle={'background-color':'blue'}\">\n        <input type=\"button\" value=\"clear\" ng-click=\"myStyle={}\">\n        <br/>\n        <span ng-style=\"myStyle\">Sample Text</span>\n        <pre>myStyle={{myStyle}}</pre>\n     </file>\n     <file name=\"style.css\">\n       span {\n         color: black;\n       }\n     </file>\n     <file name=\"protractor.js\" type=\"protractor\">\n       var colorSpan = element(by.css('span'));\n\n       it('should check ng-style', function() {\n         expect(colorSpan.getCssValue('color')).toBe('rgba(0, 0, 0, 1)');\n         element(by.css('input[value=\\'set color\\']')).click();\n         expect(colorSpan.getCssValue('color')).toBe('rgba(255, 0, 0, 1)');\n         element(by.css('input[value=clear]')).click();\n         expect(colorSpan.getCssValue('color')).toBe('rgba(0, 0, 0, 1)');\n       });\n     </file>\n   </example>\n */\nvar ngStyleDirective = ngDirective(function(scope, element, attr) {\n  scope.$watchCollection(attr.ngStyle, function ngStyleWatchAction(newStyles, oldStyles) {\n    if (oldStyles && (newStyles !== oldStyles)) {\n      forEach(oldStyles, function(val, style) { element.css(style, '');});\n    }\n    if (newStyles) element.css(newStyles);\n  });\n});\n\n/**\n * @ngdoc directive\n * @name ngSwitch\n * @restrict EA\n *\n * @description\n * The `ngSwitch` directive is used to conditionally swap DOM structure on your template based on a scope expression.\n * Elements within `ngSwitch` but without `ngSwitchWhen` or `ngSwitchDefault` directives will be preserved at the location\n * as specified in the template.\n *\n * The directive itself works similar to ngInclude, however, instead of downloading template code (or loading it\n * from the template cache), `ngSwitch` simply chooses one of the nested elements and makes it visible based on which element\n * matches the value obtained from the evaluated expression. In other words, you define a container element\n * (where you place the directive), place an expression on the **`on=\"...\"` attribute**\n * (or the **`ng-switch=\"...\"` attribute**), define any inner elements inside of the directive and place\n * a when attribute per element. The when attribute is used to inform ngSwitch which element to display when the on\n * expression is evaluated. If a matching expression is not found via a when attribute then an element with the default\n * attribute is displayed.\n *\n * <div class=\"alert alert-info\">\n * Be aware that the attribute values to match against cannot be expressions. They are interpreted\n * as literal string values to match against.\n * For example, **`ng-switch-when=\"someVal\"`** will match against the string `\"someVal\"` not against the\n * value of the expression `$scope.someVal`.\n * </div>\n\n * @animations\n * enter - happens after the ngSwitch contents change and the matched child element is placed inside the container\n * leave - happens just after the ngSwitch contents change and just before the former contents are removed from the DOM\n *\n * @usage\n *\n * ```\n * <ANY ng-switch=\"expression\">\n *   <ANY ng-switch-when=\"matchValue1\">...</ANY>\n *   <ANY ng-switch-when=\"matchValue2\">...</ANY>\n *   <ANY ng-switch-default>...</ANY>\n * </ANY>\n * ```\n *\n *\n * @scope\n * @priority 1200\n * @param {*} ngSwitch|on expression to match against <tt>ng-switch-when</tt>.\n * On child elements add:\n *\n * * `ngSwitchWhen`: the case statement to match against. If match then this\n *   case will be displayed. If the same match appears multiple times, all the\n *   elements will be displayed.\n * * `ngSwitchDefault`: the default case when no other case match. If there\n *   are multiple default cases, all of them will be displayed when no other\n *   case match.\n *\n *\n * @example\n  <example module=\"switchExample\" deps=\"angular-animate.js\" animations=\"true\">\n    <file name=\"index.html\">\n      <div ng-controller=\"ExampleController\">\n        <select ng-model=\"selection\" ng-options=\"item for item in items\">\n        </select>\n        <tt>selection={{selection}}</tt>\n        <hr/>\n        <div class=\"animate-switch-container\"\n          ng-switch on=\"selection\">\n            <div class=\"animate-switch\" ng-switch-when=\"settings\">Settings Div</div>\n            <div class=\"animate-switch\" ng-switch-when=\"home\">Home Span</div>\n            <div class=\"animate-switch\" ng-switch-default>default</div>\n        </div>\n      </div>\n    </file>\n    <file name=\"script.js\">\n      angular.module('switchExample', ['ngAnimate'])\n        .controller('ExampleController', ['$scope', function($scope) {\n          $scope.items = ['settings', 'home', 'other'];\n          $scope.selection = $scope.items[0];\n        }]);\n    </file>\n    <file name=\"animations.css\">\n      .animate-switch-container {\n        position:relative;\n        background:white;\n        border:1px solid black;\n        height:40px;\n        overflow:hidden;\n      }\n\n      .animate-switch {\n        padding:10px;\n      }\n\n      .animate-switch.ng-animate {\n        -webkit-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;\n        transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;\n\n        position:absolute;\n        top:0;\n        left:0;\n        right:0;\n        bottom:0;\n      }\n\n      .animate-switch.ng-leave.ng-leave-active,\n      .animate-switch.ng-enter {\n        top:-50px;\n      }\n      .animate-switch.ng-leave,\n      .animate-switch.ng-enter.ng-enter-active {\n        top:0;\n      }\n    </file>\n    <file name=\"protractor.js\" type=\"protractor\">\n      var switchElem = element(by.css('[ng-switch]'));\n      var select = element(by.model('selection'));\n\n      it('should start in settings', function() {\n        expect(switchElem.getText()).toMatch(/Settings Div/);\n      });\n      it('should change to home', function() {\n        select.all(by.css('option')).get(1).click();\n        expect(switchElem.getText()).toMatch(/Home Span/);\n      });\n      it('should select default', function() {\n        select.all(by.css('option')).get(2).click();\n        expect(switchElem.getText()).toMatch(/default/);\n      });\n    </file>\n  </example>\n */\nvar ngSwitchDirective = ['$animate', function($animate) {\n  return {\n    restrict: 'EA',\n    require: 'ngSwitch',\n\n    // asks for $scope to fool the BC controller module\n    controller: ['$scope', function ngSwitchController() {\n     this.cases = {};\n    }],\n    link: function(scope, element, attr, ngSwitchController) {\n      var watchExpr = attr.ngSwitch || attr.on,\n          selectedTranscludes = [],\n          selectedElements = [],\n          previousLeaveAnimations = [],\n          selectedScopes = [];\n\n      var spliceFactory = function(array, index) {\n          return function() { array.splice(index, 1); };\n      };\n\n      scope.$watch(watchExpr, function ngSwitchWatchAction(value) {\n        var i, ii;\n        for (i = 0, ii = previousLeaveAnimations.length; i < ii; ++i) {\n          $animate.cancel(previousLeaveAnimations[i]);\n        }\n        previousLeaveAnimations.length = 0;\n\n        for (i = 0, ii = selectedScopes.length; i < ii; ++i) {\n          var selected = getBlockNodes(selectedElements[i].clone);\n          selectedScopes[i].$destroy();\n          var promise = previousLeaveAnimations[i] = $animate.leave(selected);\n          promise.then(spliceFactory(previousLeaveAnimations, i));\n        }\n\n        selectedElements.length = 0;\n        selectedScopes.length = 0;\n\n        if ((selectedTranscludes = ngSwitchController.cases['!' + value] || ngSwitchController.cases['?'])) {\n          forEach(selectedTranscludes, function(selectedTransclude) {\n            selectedTransclude.transclude(function(caseElement, selectedScope) {\n              selectedScopes.push(selectedScope);\n              var anchor = selectedTransclude.element;\n              caseElement[caseElement.length++] = document.createComment(' end ngSwitchWhen: ');\n              var block = { clone: caseElement };\n\n              selectedElements.push(block);\n              $animate.enter(caseElement, anchor.parent(), anchor);\n            });\n          });\n        }\n      });\n    }\n  };\n}];\n\nvar ngSwitchWhenDirective = ngDirective({\n  transclude: 'element',\n  priority: 1200,\n  require: '^ngSwitch',\n  multiElement: true,\n  link: function(scope, element, attrs, ctrl, $transclude) {\n    ctrl.cases['!' + attrs.ngSwitchWhen] = (ctrl.cases['!' + attrs.ngSwitchWhen] || []);\n    ctrl.cases['!' + attrs.ngSwitchWhen].push({ transclude: $transclude, element: element });\n  }\n});\n\nvar ngSwitchDefaultDirective = ngDirective({\n  transclude: 'element',\n  priority: 1200,\n  require: '^ngSwitch',\n  multiElement: true,\n  link: function(scope, element, attr, ctrl, $transclude) {\n    ctrl.cases['?'] = (ctrl.cases['?'] || []);\n    ctrl.cases['?'].push({ transclude: $transclude, element: element });\n   }\n});\n\n/**\n * @ngdoc directive\n * @name ngTransclude\n * @restrict EAC\n *\n * @description\n * Directive that marks the insertion point for the transcluded DOM of the nearest parent directive that uses transclusion.\n *\n * Any existing content of the element that this directive is placed on will be removed before the transcluded content is inserted.\n *\n * @element ANY\n *\n * @example\n   <example module=\"transcludeExample\">\n     <file name=\"index.html\">\n       <script>\n         angular.module('transcludeExample', [])\n          .directive('pane', function(){\n             return {\n               restrict: 'E',\n               transclude: true,\n               scope: { title:'@' },\n               template: '<div style=\"border: 1px solid black;\">' +\n                           '<div style=\"background-color: gray\">{{title}}</div>' +\n                           '<ng-transclude></ng-transclude>' +\n                         '</div>'\n             };\n         })\n         .controller('ExampleController', ['$scope', function($scope) {\n           $scope.title = 'Lorem Ipsum';\n           $scope.text = 'Neque porro quisquam est qui dolorem ipsum quia dolor...';\n         }]);\n       </script>\n       <div ng-controller=\"ExampleController\">\n         <input ng-model=\"title\"> <br/>\n         <textarea ng-model=\"text\"></textarea> <br/>\n         <pane title=\"{{title}}\">{{text}}</pane>\n       </div>\n     </file>\n     <file name=\"protractor.js\" type=\"protractor\">\n        it('should have transcluded', function() {\n          var titleElement = element(by.model('title'));\n          titleElement.clear();\n          titleElement.sendKeys('TITLE');\n          var textElement = element(by.model('text'));\n          textElement.clear();\n          textElement.sendKeys('TEXT');\n          expect(element(by.binding('title')).getText()).toEqual('TITLE');\n          expect(element(by.binding('text')).getText()).toEqual('TEXT');\n        });\n     </file>\n   </example>\n *\n */\nvar ngTranscludeDirective = ngDirective({\n  restrict: 'EAC',\n  link: function($scope, $element, $attrs, controller, $transclude) {\n    if (!$transclude) {\n      throw minErr('ngTransclude')('orphan',\n       'Illegal use of ngTransclude directive in the template! ' +\n       'No parent directive that requires a transclusion found. ' +\n       'Element: {0}',\n       startingTag($element));\n    }\n\n    $transclude(function(clone) {\n      $element.empty();\n      $element.append(clone);\n    });\n  }\n});\n\n/**\n * @ngdoc directive\n * @name script\n * @restrict E\n *\n * @description\n * Load the content of a `<script>` element into {@link ng.$templateCache `$templateCache`}, so that the\n * template can be used by {@link ng.directive:ngInclude `ngInclude`},\n * {@link ngRoute.directive:ngView `ngView`}, or {@link guide/directive directives}. The type of the\n * `<script>` element must be specified as `text/ng-template`, and a cache name for the template must be\n * assigned through the element's `id`, which can then be used as a directive's `templateUrl`.\n *\n * @param {string} type Must be set to `'text/ng-template'`.\n * @param {string} id Cache name of the template.\n *\n * @example\n  <example>\n    <file name=\"index.html\">\n      <script type=\"text/ng-template\" id=\"/tpl.html\">\n        Content of the template.\n      </script>\n\n      <a ng-click=\"currentTpl='/tpl.html'\" id=\"tpl-link\">Load inlined template</a>\n      <div id=\"tpl-content\" ng-include src=\"currentTpl\"></div>\n    </file>\n    <file name=\"protractor.js\" type=\"protractor\">\n      it('should load template defined inside script tag', function() {\n        element(by.css('#tpl-link')).click();\n        expect(element(by.css('#tpl-content')).getText()).toMatch(/Content of the template/);\n      });\n    </file>\n  </example>\n */\nvar scriptDirective = ['$templateCache', function($templateCache) {\n  return {\n    restrict: 'E',\n    terminal: true,\n    compile: function(element, attr) {\n      if (attr.type == 'text/ng-template') {\n        var templateUrl = attr.id,\n            text = element[0].text;\n\n        $templateCache.put(templateUrl, text);\n      }\n    }\n  };\n}];\n\nvar ngOptionsMinErr = minErr('ngOptions');\n/**\n * @ngdoc directive\n * @name select\n * @restrict E\n *\n * @description\n * HTML `SELECT` element with angular data-binding.\n *\n * # `ngOptions`\n *\n * The `ngOptions` attribute can be used to dynamically generate a list of `<option>`\n * elements for the `<select>` element using the array or object obtained by evaluating the\n * `ngOptions` comprehension expression.\n *\n * In many cases, `ngRepeat` can be used on `<option>` elements instead of `ngOptions` to achieve a\n * similar result. However, `ngOptions` provides some benefits such as reducing memory and\n * increasing speed by not creating a new scope for each repeated instance, as well as providing\n * more flexibility in how the `<select>`'s model is assigned via the `select` **`as`** part of the\n * comprehension expression. `ngOptions` should be used when the `<select>` model needs to be bound\n *  to a non-string value. This is because an option element can only be bound to string values at\n * present.\n *\n * When an item in the `<select>` menu is selected, the array element or object property\n * represented by the selected option will be bound to the model identified by the `ngModel`\n * directive.\n *\n * Optionally, a single hard-coded `<option>` element, with the value set to an empty string, can\n * be nested into the `<select>` element. This element will then represent the `null` or \"not selected\"\n * option. See example below for demonstration.\n *\n * <div class=\"alert alert-warning\">\n * **Note:** `ngModel` compares by reference, not value. This is important when binding to an\n * array of objects. See an example [in this jsfiddle](http://jsfiddle.net/qWzTb/).\n * </div>\n *\n * ## `select` **`as`**\n *\n * Using `select` **`as`** will bind the result of the `select` expression to the model, but\n * the value of the `<select>` and `<option>` html elements will be either the index (for array data sources)\n * or property name (for object data sources) of the value within the collection. If a **`track by`** expression\n * is used, the result of that expression will be set as the value of the `option` and `select` elements.\n *\n *\n * ### `select` **`as`** and **`track by`**\n *\n * <div class=\"alert alert-warning\">\n * Do not use `select` **`as`** and **`track by`** in the same expression. They are not designed to work together.\n * </div>\n *\n * Consider the following example:\n *\n * ```html\n * <select ng-options=\"item.subItem as item.label for item in values track by item.id\" ng-model=\"selected\">\n * ```\n *\n * ```js\n * $scope.values = [{\n *   id: 1,\n *   label: 'aLabel',\n *   subItem: { name: 'aSubItem' }\n * }, {\n *   id: 2,\n *   label: 'bLabel',\n *   subItem: { name: 'bSubItem' }\n * }];\n *\n * $scope.selected = { name: 'aSubItem' };\n * ```\n *\n * With the purpose of preserving the selection, the **`track by`** expression is always applied to the element\n * of the data source (to `item` in this example). To calculate whether an element is selected, we do the\n * following:\n *\n * 1. Apply **`track by`** to the elements in the array. In the example: `[1, 2]`\n * 2. Apply **`track by`** to the already selected value in `ngModel`.\n *    In the example: this is not possible as **`track by`** refers to `item.id`, but the selected\n *    value from `ngModel` is `{name: 'aSubItem'}`, so the **`track by`** expression is applied to\n *    a wrong object, the selected element can't be found, `<select>` is always reset to the \"not\n *    selected\" option.\n *\n *\n * @param {string} ngModel Assignable angular expression to data-bind to.\n * @param {string=} name Property name of the form under which the control is published.\n * @param {string=} required The control is considered valid only if value is entered.\n * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n *    `required` when you want to data-bind to the `required` attribute.\n * @param {comprehension_expression=} ngOptions in one of the following forms:\n *\n *   * for array data sources:\n *     * `label` **`for`** `value` **`in`** `array`\n *     * `select` **`as`** `label` **`for`** `value` **`in`** `array`\n *     * `label` **`group by`** `group` **`for`** `value` **`in`** `array`\n *     * `label` **`group by`** `group` **`for`** `value` **`in`** `array` **`track by`** `trackexpr`\n *     * `label` **`for`** `value` **`in`** `array` | orderBy:`orderexpr` **`track by`** `trackexpr`\n *        (for including a filter with `track by`)\n *   * for object data sources:\n *     * `label` **`for (`**`key` **`,`** `value`**`) in`** `object`\n *     * `select` **`as`** `label` **`for (`**`key` **`,`** `value`**`) in`** `object`\n *     * `label` **`group by`** `group` **`for (`**`key`**`,`** `value`**`) in`** `object`\n *     * `select` **`as`** `label` **`group by`** `group`\n *         **`for` `(`**`key`**`,`** `value`**`) in`** `object`\n *\n * Where:\n *\n *   * `array` / `object`: an expression which evaluates to an array / object to iterate over.\n *   * `value`: local variable which will refer to each item in the `array` or each property value\n *      of `object` during iteration.\n *   * `key`: local variable which will refer to a property name in `object` during iteration.\n *   * `label`: The result of this expression will be the label for `<option>` element. The\n *     `expression` will most likely refer to the `value` variable (e.g. `value.propertyName`).\n *   * `select`: The result of this expression will be bound to the model of the parent `<select>`\n *      element. If not specified, `select` expression will default to `value`.\n *   * `group`: The result of this expression will be used to group options using the `<optgroup>`\n *      DOM element.\n *   * `trackexpr`: Used when working with an array of objects. The result of this expression will be\n *      used to identify the objects in the array. The `trackexpr` will most likely refer to the\n *     `value` variable (e.g. `value.propertyName`). With this the selection is preserved\n *      even when the options are recreated (e.g. reloaded from the server).\n *\n * @example\n    <example module=\"selectExample\">\n      <file name=\"index.html\">\n        <script>\n        angular.module('selectExample', [])\n          .controller('ExampleController', ['$scope', function($scope) {\n            $scope.colors = [\n              {name:'black', shade:'dark'},\n              {name:'white', shade:'light'},\n              {name:'red', shade:'dark'},\n              {name:'blue', shade:'dark'},\n              {name:'yellow', shade:'light'}\n            ];\n            $scope.myColor = $scope.colors[2]; // red\n          }]);\n        </script>\n        <div ng-controller=\"ExampleController\">\n          <ul>\n            <li ng-repeat=\"color in colors\">\n              Name: <input ng-model=\"color.name\">\n              [<a href ng-click=\"colors.splice($index, 1)\">X</a>]\n            </li>\n            <li>\n              [<a href ng-click=\"colors.push({})\">add</a>]\n            </li>\n          </ul>\n          <hr/>\n          Color (null not allowed):\n          <select ng-model=\"myColor\" ng-options=\"color.name for color in colors\"></select><br>\n\n          Color (null allowed):\n          <span  class=\"nullable\">\n            <select ng-model=\"myColor\" ng-options=\"color.name for color in colors\">\n              <option value=\"\">-- choose color --</option>\n            </select>\n          </span><br/>\n\n          Color grouped by shade:\n          <select ng-model=\"myColor\" ng-options=\"color.name group by color.shade for color in colors\">\n          </select><br/>\n\n\n          Select <a href ng-click=\"myColor = { name:'not in list', shade: 'other' }\">bogus</a>.<br>\n          <hr/>\n          Currently selected: {{ {selected_color:myColor} }}\n          <div style=\"border:solid 1px black; height:20px\"\n               ng-style=\"{'background-color':myColor.name}\">\n          </div>\n        </div>\n      </file>\n      <file name=\"protractor.js\" type=\"protractor\">\n         it('should check ng-options', function() {\n           expect(element(by.binding('{selected_color:myColor}')).getText()).toMatch('red');\n           element.all(by.model('myColor')).first().click();\n           element.all(by.css('select[ng-model=\"myColor\"] option')).first().click();\n           expect(element(by.binding('{selected_color:myColor}')).getText()).toMatch('black');\n           element(by.css('.nullable select[ng-model=\"myColor\"]')).click();\n           element.all(by.css('.nullable select[ng-model=\"myColor\"] option')).first().click();\n           expect(element(by.binding('{selected_color:myColor}')).getText()).toMatch('null');\n         });\n      </file>\n    </example>\n */\n\nvar ngOptionsDirective = valueFn({\n  restrict: 'A',\n  terminal: true\n});\n\n// jshint maxlen: false\nvar selectDirective = ['$compile', '$parse', function($compile,   $parse) {\n                         //000011111111110000000000022222222220000000000000000000003333333333000000000000004444444444444440000000005555555555555550000000666666666666666000000000000000777777777700000000000000000008888888888\n  var NG_OPTIONS_REGEXP = /^\\s*([\\s\\S]+?)(?:\\s+as\\s+([\\s\\S]+?))?(?:\\s+group\\s+by\\s+([\\s\\S]+?))?\\s+for\\s+(?:([\\$\\w][\\$\\w]*)|(?:\\(\\s*([\\$\\w][\\$\\w]*)\\s*,\\s*([\\$\\w][\\$\\w]*)\\s*\\)))\\s+in\\s+([\\s\\S]+?)(?:\\s+track\\s+by\\s+([\\s\\S]+?))?$/,\n      nullModelCtrl = {$setViewValue: noop};\n// jshint maxlen: 100\n\n  return {\n    restrict: 'E',\n    require: ['select', '?ngModel'],\n    controller: ['$element', '$scope', '$attrs', function($element, $scope, $attrs) {\n      var self = this,\n          optionsMap = {},\n          ngModelCtrl = nullModelCtrl,\n          nullOption,\n          unknownOption;\n\n\n      self.databound = $attrs.ngModel;\n\n\n      self.init = function(ngModelCtrl_, nullOption_, unknownOption_) {\n        ngModelCtrl = ngModelCtrl_;\n        nullOption = nullOption_;\n        unknownOption = unknownOption_;\n      };\n\n\n      self.addOption = function(value, element) {\n        assertNotHasOwnProperty(value, '\"option value\"');\n        optionsMap[value] = true;\n\n        if (ngModelCtrl.$viewValue == value) {\n          $element.val(value);\n          if (unknownOption.parent()) unknownOption.remove();\n        }\n        // Workaround for https://code.google.com/p/chromium/issues/detail?id=381459\n        // Adding an <option selected=\"selected\"> element to a <select required=\"required\"> should\n        // automatically select the new element\n        if (element && element[0].hasAttribute('selected')) {\n          element[0].selected = true;\n        }\n      };\n\n\n      self.removeOption = function(value) {\n        if (this.hasOption(value)) {\n          delete optionsMap[value];\n          if (ngModelCtrl.$viewValue === value) {\n            this.renderUnknownOption(value);\n          }\n        }\n      };\n\n\n      self.renderUnknownOption = function(val) {\n        var unknownVal = '? ' + hashKey(val) + ' ?';\n        unknownOption.val(unknownVal);\n        $element.prepend(unknownOption);\n        $element.val(unknownVal);\n        unknownOption.prop('selected', true); // needed for IE\n      };\n\n\n      self.hasOption = function(value) {\n        return optionsMap.hasOwnProperty(value);\n      };\n\n      $scope.$on('$destroy', function() {\n        // disable unknown option so that we don't do work when the whole select is being destroyed\n        self.renderUnknownOption = noop;\n      });\n    }],\n\n    link: function(scope, element, attr, ctrls) {\n      // if ngModel is not defined, we don't need to do anything\n      if (!ctrls[1]) return;\n\n      var selectCtrl = ctrls[0],\n          ngModelCtrl = ctrls[1],\n          multiple = attr.multiple,\n          optionsExp = attr.ngOptions,\n          nullOption = false, // if false, user will not be able to select it (used by ngOptions)\n          emptyOption,\n          renderScheduled = false,\n          // we can't just jqLite('<option>') since jqLite is not smart enough\n          // to create it in <select> and IE barfs otherwise.\n          optionTemplate = jqLite(document.createElement('option')),\n          optGroupTemplate =jqLite(document.createElement('optgroup')),\n          unknownOption = optionTemplate.clone();\n\n      // find \"null\" option\n      for (var i = 0, children = element.children(), ii = children.length; i < ii; i++) {\n        if (children[i].value === '') {\n          emptyOption = nullOption = children.eq(i);\n          break;\n        }\n      }\n\n      selectCtrl.init(ngModelCtrl, nullOption, unknownOption);\n\n      // required validator\n      if (multiple) {\n        ngModelCtrl.$isEmpty = function(value) {\n          return !value || value.length === 0;\n        };\n      }\n\n      if (optionsExp) setupAsOptions(scope, element, ngModelCtrl);\n      else if (multiple) setupAsMultiple(scope, element, ngModelCtrl);\n      else setupAsSingle(scope, element, ngModelCtrl, selectCtrl);\n\n\n      ////////////////////////////\n\n\n\n      function setupAsSingle(scope, selectElement, ngModelCtrl, selectCtrl) {\n        ngModelCtrl.$render = function() {\n          var viewValue = ngModelCtrl.$viewValue;\n\n          if (selectCtrl.hasOption(viewValue)) {\n            if (unknownOption.parent()) unknownOption.remove();\n            selectElement.val(viewValue);\n            if (viewValue === '') emptyOption.prop('selected', true); // to make IE9 happy\n          } else {\n            if (isUndefined(viewValue) && emptyOption) {\n              selectElement.val('');\n            } else {\n              selectCtrl.renderUnknownOption(viewValue);\n            }\n          }\n        };\n\n        selectElement.on('change', function() {\n          scope.$apply(function() {\n            if (unknownOption.parent()) unknownOption.remove();\n            ngModelCtrl.$setViewValue(selectElement.val());\n          });\n        });\n      }\n\n      function setupAsMultiple(scope, selectElement, ctrl) {\n        var lastView;\n        ctrl.$render = function() {\n          var items = new HashMap(ctrl.$viewValue);\n          forEach(selectElement.find('option'), function(option) {\n            option.selected = isDefined(items.get(option.value));\n          });\n        };\n\n        // we have to do it on each watch since ngModel watches reference, but\n        // we need to work of an array, so we need to see if anything was inserted/removed\n        scope.$watch(function selectMultipleWatch() {\n          if (!equals(lastView, ctrl.$viewValue)) {\n            lastView = shallowCopy(ctrl.$viewValue);\n            ctrl.$render();\n          }\n        });\n\n        selectElement.on('change', function() {\n          scope.$apply(function() {\n            var array = [];\n            forEach(selectElement.find('option'), function(option) {\n              if (option.selected) {\n                array.push(option.value);\n              }\n            });\n            ctrl.$setViewValue(array);\n          });\n        });\n      }\n\n      function setupAsOptions(scope, selectElement, ctrl) {\n        var match;\n\n        if (!(match = optionsExp.match(NG_OPTIONS_REGEXP))) {\n          throw ngOptionsMinErr('iexp',\n            \"Expected expression in form of \" +\n            \"'_select_ (as _label_)? for (_key_,)?_value_ in _collection_'\" +\n            \" but got '{0}'. Element: {1}\",\n            optionsExp, startingTag(selectElement));\n        }\n\n        var displayFn = $parse(match[2] || match[1]),\n            valueName = match[4] || match[6],\n            selectAs = / as /.test(match[0]) && match[1],\n            selectAsFn = selectAs ? $parse(selectAs) : null,\n            keyName = match[5],\n            groupByFn = $parse(match[3] || ''),\n            valueFn = $parse(match[2] ? match[1] : valueName),\n            valuesFn = $parse(match[7]),\n            track = match[8],\n            trackFn = track ? $parse(match[8]) : null,\n            trackKeysCache = {},\n            // This is an array of array of existing option groups in DOM.\n            // We try to reuse these if possible\n            // - optionGroupsCache[0] is the options with no option group\n            // - optionGroupsCache[?][0] is the parent: either the SELECT or OPTGROUP element\n            optionGroupsCache = [[{element: selectElement, label:''}]],\n            //re-usable object to represent option's locals\n            locals = {};\n\n        if (nullOption) {\n          // compile the element since there might be bindings in it\n          $compile(nullOption)(scope);\n\n          // remove the class, which is added automatically because we recompile the element and it\n          // becomes the compilation root\n          nullOption.removeClass('ng-scope');\n\n          // we need to remove it before calling selectElement.empty() because otherwise IE will\n          // remove the label from the element. wtf?\n          nullOption.remove();\n        }\n\n        // clear contents, we'll add what's needed based on the model\n        selectElement.empty();\n\n        selectElement.on('change', selectionChanged);\n\n        ctrl.$render = render;\n\n        scope.$watchCollection(valuesFn, scheduleRendering);\n        scope.$watchCollection(getLabels, scheduleRendering);\n\n        if (multiple) {\n          scope.$watchCollection(function() { return ctrl.$modelValue; }, scheduleRendering);\n        }\n\n        // ------------------------------------------------------------------ //\n\n        function callExpression(exprFn, key, value) {\n          locals[valueName] = value;\n          if (keyName) locals[keyName] = key;\n          return exprFn(scope, locals);\n        }\n\n        function selectionChanged() {\n          scope.$apply(function() {\n            var collection = valuesFn(scope) || [];\n            var viewValue;\n            if (multiple) {\n              viewValue = [];\n              forEach(selectElement.val(), function(selectedKey) {\n                  selectedKey = trackFn ? trackKeysCache[selectedKey] : selectedKey;\n                viewValue.push(getViewValue(selectedKey, collection[selectedKey]));\n              });\n            } else {\n              var selectedKey = trackFn ? trackKeysCache[selectElement.val()] : selectElement.val();\n              viewValue = getViewValue(selectedKey, collection[selectedKey]);\n            }\n            ctrl.$setViewValue(viewValue);\n            render();\n          });\n        }\n\n        function getViewValue(key, value) {\n          if (key === '?') {\n            return undefined;\n          } else if (key === '') {\n            return null;\n          } else {\n            var viewValueFn = selectAsFn ? selectAsFn : valueFn;\n            return callExpression(viewValueFn, key, value);\n          }\n        }\n\n        function getLabels() {\n          var values = valuesFn(scope);\n          var toDisplay;\n          if (values && isArray(values)) {\n            toDisplay = new Array(values.length);\n            for (var i = 0, ii = values.length; i < ii; i++) {\n              toDisplay[i] = callExpression(displayFn, i, values[i]);\n            }\n            return toDisplay;\n          } else if (values) {\n            // TODO: Add a test for this case\n            toDisplay = {};\n            for (var prop in values) {\n              if (values.hasOwnProperty(prop)) {\n                toDisplay[prop] = callExpression(displayFn, prop, values[prop]);\n              }\n            }\n          }\n          return toDisplay;\n        }\n\n        function createIsSelectedFn(viewValue) {\n          var selectedSet;\n          if (multiple) {\n            if (trackFn && isArray(viewValue)) {\n\n              selectedSet = new HashMap([]);\n              for (var trackIndex = 0; trackIndex < viewValue.length; trackIndex++) {\n                // tracking by key\n                selectedSet.put(callExpression(trackFn, null, viewValue[trackIndex]), true);\n              }\n            } else {\n              selectedSet = new HashMap(viewValue);\n            }\n          } else if (trackFn) {\n            viewValue = callExpression(trackFn, null, viewValue);\n          }\n\n          return function isSelected(key, value) {\n            var compareValueFn;\n            if (trackFn) {\n              compareValueFn = trackFn;\n            } else if (selectAsFn) {\n              compareValueFn = selectAsFn;\n            } else {\n              compareValueFn = valueFn;\n            }\n\n            if (multiple) {\n              return isDefined(selectedSet.remove(callExpression(compareValueFn, key, value)));\n            } else {\n              return viewValue === callExpression(compareValueFn, key, value);\n            }\n          };\n        }\n\n        function scheduleRendering() {\n          if (!renderScheduled) {\n            scope.$$postDigest(render);\n            renderScheduled = true;\n          }\n        }\n\n        /**\n         * A new labelMap is created with each render.\n         * This function is called for each existing option with added=false,\n         * and each new option with added=true.\n         * - Labels that are passed to this method twice,\n         * (once with added=true and once with added=false) will end up with a value of 0, and\n         * will cause no change to happen to the corresponding option.\n         * - Labels that are passed to this method only once with added=false will end up with a\n         * value of -1 and will eventually be passed to selectCtrl.removeOption()\n         * - Labels that are passed to this method only once with added=true will end up with a\n         * value of 1 and will eventually be passed to selectCtrl.addOption()\n        */\n        function updateLabelMap(labelMap, label, added) {\n          labelMap[label] = labelMap[label] || 0;\n          labelMap[label] += (added ? 1 : -1);\n        }\n\n        function render() {\n          renderScheduled = false;\n\n          // Temporary location for the option groups before we render them\n          var optionGroups = {'':[]},\n              optionGroupNames = [''],\n              optionGroupName,\n              optionGroup,\n              option,\n              existingParent, existingOptions, existingOption,\n              viewValue = ctrl.$viewValue,\n              values = valuesFn(scope) || [],\n              keys = keyName ? sortedKeys(values) : values,\n              key,\n              value,\n              groupLength, length,\n              groupIndex, index,\n              labelMap = {},\n              selected,\n              isSelected = createIsSelectedFn(viewValue),\n              anySelected = false,\n              lastElement,\n              element,\n              label,\n              optionId;\n\n          trackKeysCache = {};\n\n          // We now build up the list of options we need (we merge later)\n          for (index = 0; length = keys.length, index < length; index++) {\n            key = index;\n            if (keyName) {\n              key = keys[index];\n              if (key.charAt(0) === '$') continue;\n            }\n            value = values[key];\n\n            optionGroupName = callExpression(groupByFn, key, value) || '';\n            if (!(optionGroup = optionGroups[optionGroupName])) {\n              optionGroup = optionGroups[optionGroupName] = [];\n              optionGroupNames.push(optionGroupName);\n            }\n\n            selected = isSelected(key, value);\n            anySelected = anySelected || selected;\n\n            label = callExpression(displayFn, key, value); // what will be seen by the user\n\n            // doing displayFn(scope, locals) || '' overwrites zero values\n            label = isDefined(label) ? label : '';\n            optionId = trackFn ? trackFn(scope, locals) : (keyName ? keys[index] : index);\n            if (trackFn) {\n              trackKeysCache[optionId] = key;\n            }\n\n            optionGroup.push({\n              // either the index into array or key from object\n              id: optionId,\n              label: label,\n              selected: selected                   // determine if we should be selected\n            });\n          }\n          if (!multiple) {\n            if (nullOption || viewValue === null) {\n              // insert null option if we have a placeholder, or the model is null\n              optionGroups[''].unshift({id:'', label:'', selected:!anySelected});\n            } else if (!anySelected) {\n              // option could not be found, we have to insert the undefined item\n              optionGroups[''].unshift({id:'?', label:'', selected:true});\n            }\n          }\n\n          // Now we need to update the list of DOM nodes to match the optionGroups we computed above\n          for (groupIndex = 0, groupLength = optionGroupNames.length;\n               groupIndex < groupLength;\n               groupIndex++) {\n            // current option group name or '' if no group\n            optionGroupName = optionGroupNames[groupIndex];\n\n            // list of options for that group. (first item has the parent)\n            optionGroup = optionGroups[optionGroupName];\n\n            if (optionGroupsCache.length <= groupIndex) {\n              // we need to grow the optionGroups\n              existingParent = {\n                element: optGroupTemplate.clone().attr('label', optionGroupName),\n                label: optionGroup.label\n              };\n              existingOptions = [existingParent];\n              optionGroupsCache.push(existingOptions);\n              selectElement.append(existingParent.element);\n            } else {\n              existingOptions = optionGroupsCache[groupIndex];\n              existingParent = existingOptions[0];  // either SELECT (no group) or OPTGROUP element\n\n              // update the OPTGROUP label if not the same.\n              if (existingParent.label != optionGroupName) {\n                existingParent.element.attr('label', existingParent.label = optionGroupName);\n              }\n            }\n\n            lastElement = null;  // start at the beginning\n            for (index = 0, length = optionGroup.length; index < length; index++) {\n              option = optionGroup[index];\n              if ((existingOption = existingOptions[index + 1])) {\n                // reuse elements\n                lastElement = existingOption.element;\n                if (existingOption.label !== option.label) {\n                  updateLabelMap(labelMap, existingOption.label, false);\n                  updateLabelMap(labelMap, option.label, true);\n                  lastElement.text(existingOption.label = option.label);\n                  lastElement.prop('label', existingOption.label);\n                }\n                if (existingOption.id !== option.id) {\n                  lastElement.val(existingOption.id = option.id);\n                }\n                // lastElement.prop('selected') provided by jQuery has side-effects\n                if (lastElement[0].selected !== option.selected) {\n                  lastElement.prop('selected', (existingOption.selected = option.selected));\n                  if (msie) {\n                    // See #7692\n                    // The selected item wouldn't visually update on IE without this.\n                    // Tested on Win7: IE9, IE10 and IE11. Future IEs should be tested as well\n                    lastElement.prop('selected', existingOption.selected);\n                  }\n                }\n              } else {\n                // grow elements\n\n                // if it's a null option\n                if (option.id === '' && nullOption) {\n                  // put back the pre-compiled element\n                  element = nullOption;\n                } else {\n                  // jQuery(v1.4.2) Bug: We should be able to chain the method calls, but\n                  // in this version of jQuery on some browser the .text() returns a string\n                  // rather then the element.\n                  (element = optionTemplate.clone())\n                      .val(option.id)\n                      .prop('selected', option.selected)\n                      .attr('selected', option.selected)\n                      .prop('label', option.label)\n                      .text(option.label);\n                }\n\n                existingOptions.push(existingOption = {\n                    element: element,\n                    label: option.label,\n                    id: option.id,\n                    selected: option.selected\n                });\n                updateLabelMap(labelMap, option.label, true);\n                if (lastElement) {\n                  lastElement.after(element);\n                } else {\n                  existingParent.element.append(element);\n                }\n                lastElement = element;\n              }\n            }\n            // remove any excessive OPTIONs in a group\n            index++; // increment since the existingOptions[0] is parent element not OPTION\n            while (existingOptions.length > index) {\n              option = existingOptions.pop();\n              updateLabelMap(labelMap, option.label, false);\n              option.element.remove();\n            }\n          }\n          // remove any excessive OPTGROUPs from select\n          while (optionGroupsCache.length > groupIndex) {\n            // remove all the labels in the option group\n            optionGroup = optionGroupsCache.pop();\n            for (index = 1; index < optionGroup.length; ++index) {\n              updateLabelMap(labelMap, optionGroup[index].label, false);\n            }\n            optionGroup[0].element.remove();\n          }\n          forEach(labelMap, function(count, label) {\n            if (count > 0) {\n              selectCtrl.addOption(label);\n            } else if (count < 0) {\n              selectCtrl.removeOption(label);\n            }\n          });\n        }\n      }\n    }\n  };\n}];\n\nvar optionDirective = ['$interpolate', function($interpolate) {\n  var nullSelectCtrl = {\n    addOption: noop,\n    removeOption: noop\n  };\n\n  return {\n    restrict: 'E',\n    priority: 100,\n    compile: function(element, attr) {\n      if (isUndefined(attr.value)) {\n        var interpolateFn = $interpolate(element.text(), true);\n        if (!interpolateFn) {\n          attr.$set('value', element.text());\n        }\n      }\n\n      return function(scope, element, attr) {\n        var selectCtrlName = '$selectController',\n            parent = element.parent(),\n            selectCtrl = parent.data(selectCtrlName) ||\n              parent.parent().data(selectCtrlName); // in case we are in optgroup\n\n        if (!selectCtrl || !selectCtrl.databound) {\n          selectCtrl = nullSelectCtrl;\n        }\n\n        if (interpolateFn) {\n          scope.$watch(interpolateFn, function interpolateWatchAction(newVal, oldVal) {\n            attr.$set('value', newVal);\n            if (oldVal !== newVal) {\n              selectCtrl.removeOption(oldVal);\n            }\n            selectCtrl.addOption(newVal, element);\n          });\n        } else {\n          selectCtrl.addOption(attr.value, element);\n        }\n\n        element.on('$destroy', function() {\n          selectCtrl.removeOption(attr.value);\n        });\n      };\n    }\n  };\n}];\n\nvar styleDirective = valueFn({\n  restrict: 'E',\n  terminal: false\n});\n\nvar requiredDirective = function() {\n  return {\n    restrict: 'A',\n    require: '?ngModel',\n    link: function(scope, elm, attr, ctrl) {\n      if (!ctrl) return;\n      attr.required = true; // force truthy in case we are on non input element\n\n      ctrl.$validators.required = function(modelValue, viewValue) {\n        return !attr.required || !ctrl.$isEmpty(viewValue);\n      };\n\n      attr.$observe('required', function() {\n        ctrl.$validate();\n      });\n    }\n  };\n};\n\n\nvar patternDirective = function() {\n  return {\n    restrict: 'A',\n    require: '?ngModel',\n    link: function(scope, elm, attr, ctrl) {\n      if (!ctrl) return;\n\n      var regexp, patternExp = attr.ngPattern || attr.pattern;\n      attr.$observe('pattern', function(regex) {\n        if (isString(regex) && regex.length > 0) {\n          regex = new RegExp('^' + regex + '$');\n        }\n\n        if (regex && !regex.test) {\n          throw minErr('ngPattern')('noregexp',\n            'Expected {0} to be a RegExp but was {1}. Element: {2}', patternExp,\n            regex, startingTag(elm));\n        }\n\n        regexp = regex || undefined;\n        ctrl.$validate();\n      });\n\n      ctrl.$validators.pattern = function(value) {\n        return ctrl.$isEmpty(value) || isUndefined(regexp) || regexp.test(value);\n      };\n    }\n  };\n};\n\n\nvar maxlengthDirective = function() {\n  return {\n    restrict: 'A',\n    require: '?ngModel',\n    link: function(scope, elm, attr, ctrl) {\n      if (!ctrl) return;\n\n      var maxlength = -1;\n      attr.$observe('maxlength', function(value) {\n        var intVal = int(value);\n        maxlength = isNaN(intVal) ? -1 : intVal;\n        ctrl.$validate();\n      });\n      ctrl.$validators.maxlength = function(modelValue, viewValue) {\n        return (maxlength < 0) || ctrl.$isEmpty(viewValue) || (viewValue.length <= maxlength);\n      };\n    }\n  };\n};\n\nvar minlengthDirective = function() {\n  return {\n    restrict: 'A',\n    require: '?ngModel',\n    link: function(scope, elm, attr, ctrl) {\n      if (!ctrl) return;\n\n      var minlength = 0;\n      attr.$observe('minlength', function(value) {\n        minlength = int(value) || 0;\n        ctrl.$validate();\n      });\n      ctrl.$validators.minlength = function(modelValue, viewValue) {\n        return ctrl.$isEmpty(viewValue) || viewValue.length >= minlength;\n      };\n    }\n  };\n};\n\n  if (window.angular.bootstrap) {\n    //AngularJS is already loaded, so we can return here...\n    console.log('WARNING: Tried to load angular more than once.');\n    return;\n  }\n\n  //try to bind to jquery now so that one can write jqLite(document).ready()\n  //but we will rebind on bootstrap again.\n  bindJQuery();\n\n  publishExternalAPI(angular);\n\n  jqLite(document).ready(function() {\n    angularInit(document, bootstrap);\n  });\n\n})(window, document);\n\n!window.angular.$$csp() && window.angular.element(document).find('head').prepend('<style type=\"text/css\">@charset \"UTF-8\";[ng\\\\:cloak],[ng-cloak],[data-ng-cloak],[x-ng-cloak],.ng-cloak,.x-ng-cloak,.ng-hide:not(.ng-hide-animate){display:none !important;}ng\\\\:form{display:block;}</style>');"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/angular/bower.json",
    "content": "{\n  \"name\": \"angular\",\n  \"version\": \"1.3.13\",\n  \"main\": \"./angular.js\",\n  \"ignore\": [],\n  \"dependencies\": {\n  }\n}\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/angular/package.json",
    "content": "{\n  \"name\": \"angular\",\n  \"version\": \"1.3.13\",\n  \"description\": \"HTML enhanced for web apps\",\n  \"main\": \"angular.js\",\n  \"scripts\": {\n    \"test\": \"echo \\\"Error: no test specified\\\" && exit 1\"\n  },\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/angular/angular.js.git\"\n  },\n  \"keywords\": [\n    \"angular\",\n    \"framework\",\n    \"browser\",\n    \"client-side\"\n  ],\n  \"author\": \"Angular Core Team <angular-core+npm@google.com>\",\n  \"license\": \"MIT\",\n  \"bugs\": {\n    \"url\": \"https://github.com/angular/angular.js/issues\"\n  },\n  \"homepage\": \"http://angularjs.org\"\n}\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/angular-bootstrap/.bower.json",
    "content": "{\n  \"author\": {\n    \"name\": \"https://github.com/angular-ui/bootstrap/graphs/contributors\"\n  },\n  \"name\": \"angular-bootstrap\",\n  \"keywords\": [\n    \"angular\",\n    \"angular-ui\",\n    \"bootstrap\"\n  ],\n  \"description\": \"Native AngularJS (Angular) directives for Bootstrap.\",\n  \"version\": \"0.12.0\",\n  \"main\": [\n    \"./ui-bootstrap-tpls.js\"\n  ],\n  \"dependencies\": {\n    \"angular\": \">=1 <1.3.0\"\n  },\n  \"homepage\": \"https://github.com/angular-ui/bootstrap-bower\",\n  \"_release\": \"0.12.0\",\n  \"_resolution\": {\n    \"type\": \"version\",\n    \"tag\": \"0.12.0\",\n    \"commit\": \"b7a256c24b4545e633920ca9a9545b35ed425412\"\n  },\n  \"_source\": \"https://github.com/angular-ui/bootstrap-bower.git\",\n  \"_target\": \"0.12.0\",\n  \"_originalSource\": \"angular-bootstrap\"\n}"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/angular-bootstrap/bower.json",
    "content": "{\n    \"author\": {\n        \"name\": \"https://github.com/angular-ui/bootstrap/graphs/contributors\"\n    },\n    \"name\": \"angular-bootstrap\",\n    \"keywords\": [\n        \"angular\",\n        \"angular-ui\",\n        \"bootstrap\"\n    ],\n    \"description\": \"Native AngularJS (Angular) directives for Bootstrap.\",\n    \"version\": \"0.12.0\",\n    \"main\": [\"./ui-bootstrap-tpls.js\"],\n    \"dependencies\": {\n        \"angular\": \">=1 <1.3.0\"\n    }    \n}\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/angular-bootstrap/ui-bootstrap-tpls.js",
    "content": "/*\n * angular-ui-bootstrap\n * http://angular-ui.github.io/bootstrap/\n\n * Version: 0.12.0 - 2014-11-16\n * License: MIT\n */\nangular.module(\"ui.bootstrap\", [\"ui.bootstrap.tpls\", \"ui.bootstrap.transition\",\"ui.bootstrap.collapse\",\"ui.bootstrap.accordion\",\"ui.bootstrap.alert\",\"ui.bootstrap.bindHtml\",\"ui.bootstrap.buttons\",\"ui.bootstrap.carousel\",\"ui.bootstrap.dateparser\",\"ui.bootstrap.position\",\"ui.bootstrap.datepicker\",\"ui.bootstrap.dropdown\",\"ui.bootstrap.modal\",\"ui.bootstrap.pagination\",\"ui.bootstrap.tooltip\",\"ui.bootstrap.popover\",\"ui.bootstrap.progressbar\",\"ui.bootstrap.rating\",\"ui.bootstrap.tabs\",\"ui.bootstrap.timepicker\",\"ui.bootstrap.typeahead\"]);\nangular.module(\"ui.bootstrap.tpls\", [\"template/accordion/accordion-group.html\",\"template/accordion/accordion.html\",\"template/alert/alert.html\",\"template/carousel/carousel.html\",\"template/carousel/slide.html\",\"template/datepicker/datepicker.html\",\"template/datepicker/day.html\",\"template/datepicker/month.html\",\"template/datepicker/popup.html\",\"template/datepicker/year.html\",\"template/modal/backdrop.html\",\"template/modal/window.html\",\"template/pagination/pager.html\",\"template/pagination/pagination.html\",\"template/tooltip/tooltip-html-unsafe-popup.html\",\"template/tooltip/tooltip-popup.html\",\"template/popover/popover.html\",\"template/progressbar/bar.html\",\"template/progressbar/progress.html\",\"template/progressbar/progressbar.html\",\"template/rating/rating.html\",\"template/tabs/tab.html\",\"template/tabs/tabset.html\",\"template/timepicker/timepicker.html\",\"template/typeahead/typeahead-match.html\",\"template/typeahead/typeahead-popup.html\"]);\nangular.module('ui.bootstrap.transition', [])\n\n/**\n * $transition service provides a consistent interface to trigger CSS 3 transitions and to be informed when they complete.\n * @param  {DOMElement} element  The DOMElement that will be animated.\n * @param  {string|object|function} trigger  The thing that will cause the transition to start:\n *   - As a string, it represents the css class to be added to the element.\n *   - As an object, it represents a hash of style attributes to be applied to the element.\n *   - As a function, it represents a function to be called that will cause the transition to occur.\n * @return {Promise}  A promise that is resolved when the transition finishes.\n */\n.factory('$transition', ['$q', '$timeout', '$rootScope', function($q, $timeout, $rootScope) {\n\n  var $transition = function(element, trigger, options) {\n    options = options || {};\n    var deferred = $q.defer();\n    var endEventName = $transition[options.animation ? 'animationEndEventName' : 'transitionEndEventName'];\n\n    var transitionEndHandler = function(event) {\n      $rootScope.$apply(function() {\n        element.unbind(endEventName, transitionEndHandler);\n        deferred.resolve(element);\n      });\n    };\n\n    if (endEventName) {\n      element.bind(endEventName, transitionEndHandler);\n    }\n\n    // Wrap in a timeout to allow the browser time to update the DOM before the transition is to occur\n    $timeout(function() {\n      if ( angular.isString(trigger) ) {\n        element.addClass(trigger);\n      } else if ( angular.isFunction(trigger) ) {\n        trigger(element);\n      } else if ( angular.isObject(trigger) ) {\n        element.css(trigger);\n      }\n      //If browser does not support transitions, instantly resolve\n      if ( !endEventName ) {\n        deferred.resolve(element);\n      }\n    });\n\n    // Add our custom cancel function to the promise that is returned\n    // We can call this if we are about to run a new transition, which we know will prevent this transition from ending,\n    // i.e. it will therefore never raise a transitionEnd event for that transition\n    deferred.promise.cancel = function() {\n      if ( endEventName ) {\n        element.unbind(endEventName, transitionEndHandler);\n      }\n      deferred.reject('Transition cancelled');\n    };\n\n    return deferred.promise;\n  };\n\n  // Work out the name of the transitionEnd event\n  var transElement = document.createElement('trans');\n  var transitionEndEventNames = {\n    'WebkitTransition': 'webkitTransitionEnd',\n    'MozTransition': 'transitionend',\n    'OTransition': 'oTransitionEnd',\n    'transition': 'transitionend'\n  };\n  var animationEndEventNames = {\n    'WebkitTransition': 'webkitAnimationEnd',\n    'MozTransition': 'animationend',\n    'OTransition': 'oAnimationEnd',\n    'transition': 'animationend'\n  };\n  function findEndEventName(endEventNames) {\n    for (var name in endEventNames){\n      if (transElement.style[name] !== undefined) {\n        return endEventNames[name];\n      }\n    }\n  }\n  $transition.transitionEndEventName = findEndEventName(transitionEndEventNames);\n  $transition.animationEndEventName = findEndEventName(animationEndEventNames);\n  return $transition;\n}]);\n\nangular.module('ui.bootstrap.collapse', ['ui.bootstrap.transition'])\n\n  .directive('collapse', ['$transition', function ($transition) {\n\n    return {\n      link: function (scope, element, attrs) {\n\n        var initialAnimSkip = true;\n        var currentTransition;\n\n        function doTransition(change) {\n          var newTransition = $transition(element, change);\n          if (currentTransition) {\n            currentTransition.cancel();\n          }\n          currentTransition = newTransition;\n          newTransition.then(newTransitionDone, newTransitionDone);\n          return newTransition;\n\n          function newTransitionDone() {\n            // Make sure it's this transition, otherwise, leave it alone.\n            if (currentTransition === newTransition) {\n              currentTransition = undefined;\n            }\n          }\n        }\n\n        function expand() {\n          if (initialAnimSkip) {\n            initialAnimSkip = false;\n            expandDone();\n          } else {\n            element.removeClass('collapse').addClass('collapsing');\n            doTransition({ height: element[0].scrollHeight + 'px' }).then(expandDone);\n          }\n        }\n\n        function expandDone() {\n          element.removeClass('collapsing');\n          element.addClass('collapse in');\n          element.css({height: 'auto'});\n        }\n\n        function collapse() {\n          if (initialAnimSkip) {\n            initialAnimSkip = false;\n            collapseDone();\n            element.css({height: 0});\n          } else {\n            // CSS transitions don't work with height: auto, so we have to manually change the height to a specific value\n            element.css({ height: element[0].scrollHeight + 'px' });\n            //trigger reflow so a browser realizes that height was updated from auto to a specific value\n            var x = element[0].offsetWidth;\n\n            element.removeClass('collapse in').addClass('collapsing');\n\n            doTransition({ height: 0 }).then(collapseDone);\n          }\n        }\n\n        function collapseDone() {\n          element.removeClass('collapsing');\n          element.addClass('collapse');\n        }\n\n        scope.$watch(attrs.collapse, function (shouldCollapse) {\n          if (shouldCollapse) {\n            collapse();\n          } else {\n            expand();\n          }\n        });\n      }\n    };\n  }]);\n\nangular.module('ui.bootstrap.accordion', ['ui.bootstrap.collapse'])\n\n.constant('accordionConfig', {\n  closeOthers: true\n})\n\n.controller('AccordionController', ['$scope', '$attrs', 'accordionConfig', function ($scope, $attrs, accordionConfig) {\n\n  // This array keeps track of the accordion groups\n  this.groups = [];\n\n  // Ensure that all the groups in this accordion are closed, unless close-others explicitly says not to\n  this.closeOthers = function(openGroup) {\n    var closeOthers = angular.isDefined($attrs.closeOthers) ? $scope.$eval($attrs.closeOthers) : accordionConfig.closeOthers;\n    if ( closeOthers ) {\n      angular.forEach(this.groups, function (group) {\n        if ( group !== openGroup ) {\n          group.isOpen = false;\n        }\n      });\n    }\n  };\n\n  // This is called from the accordion-group directive to add itself to the accordion\n  this.addGroup = function(groupScope) {\n    var that = this;\n    this.groups.push(groupScope);\n\n    groupScope.$on('$destroy', function (event) {\n      that.removeGroup(groupScope);\n    });\n  };\n\n  // This is called from the accordion-group directive when to remove itself\n  this.removeGroup = function(group) {\n    var index = this.groups.indexOf(group);\n    if ( index !== -1 ) {\n      this.groups.splice(index, 1);\n    }\n  };\n\n}])\n\n// The accordion directive simply sets up the directive controller\n// and adds an accordion CSS class to itself element.\n.directive('accordion', function () {\n  return {\n    restrict:'EA',\n    controller:'AccordionController',\n    transclude: true,\n    replace: false,\n    templateUrl: 'template/accordion/accordion.html'\n  };\n})\n\n// The accordion-group directive indicates a block of html that will expand and collapse in an accordion\n.directive('accordionGroup', function() {\n  return {\n    require:'^accordion',         // We need this directive to be inside an accordion\n    restrict:'EA',\n    transclude:true,              // It transcludes the contents of the directive into the template\n    replace: true,                // The element containing the directive will be replaced with the template\n    templateUrl:'template/accordion/accordion-group.html',\n    scope: {\n      heading: '@',               // Interpolate the heading attribute onto this scope\n      isOpen: '=?',\n      isDisabled: '=?'\n    },\n    controller: function() {\n      this.setHeading = function(element) {\n        this.heading = element;\n      };\n    },\n    link: function(scope, element, attrs, accordionCtrl) {\n      accordionCtrl.addGroup(scope);\n\n      scope.$watch('isOpen', function(value) {\n        if ( value ) {\n          accordionCtrl.closeOthers(scope);\n        }\n      });\n\n      scope.toggleOpen = function() {\n        if ( !scope.isDisabled ) {\n          scope.isOpen = !scope.isOpen;\n        }\n      };\n    }\n  };\n})\n\n// Use accordion-heading below an accordion-group to provide a heading containing HTML\n// <accordion-group>\n//   <accordion-heading>Heading containing HTML - <img src=\"...\"></accordion-heading>\n// </accordion-group>\n.directive('accordionHeading', function() {\n  return {\n    restrict: 'EA',\n    transclude: true,   // Grab the contents to be used as the heading\n    template: '',       // In effect remove this element!\n    replace: true,\n    require: '^accordionGroup',\n    link: function(scope, element, attr, accordionGroupCtrl, transclude) {\n      // Pass the heading to the accordion-group controller\n      // so that it can be transcluded into the right place in the template\n      // [The second parameter to transclude causes the elements to be cloned so that they work in ng-repeat]\n      accordionGroupCtrl.setHeading(transclude(scope, function() {}));\n    }\n  };\n})\n\n// Use in the accordion-group template to indicate where you want the heading to be transcluded\n// You must provide the property on the accordion-group controller that will hold the transcluded element\n// <div class=\"accordion-group\">\n//   <div class=\"accordion-heading\" ><a ... accordion-transclude=\"heading\">...</a></div>\n//   ...\n// </div>\n.directive('accordionTransclude', function() {\n  return {\n    require: '^accordionGroup',\n    link: function(scope, element, attr, controller) {\n      scope.$watch(function() { return controller[attr.accordionTransclude]; }, function(heading) {\n        if ( heading ) {\n          element.html('');\n          element.append(heading);\n        }\n      });\n    }\n  };\n});\n\nangular.module('ui.bootstrap.alert', [])\n\n.controller('AlertController', ['$scope', '$attrs', function ($scope, $attrs) {\n  $scope.closeable = 'close' in $attrs;\n  this.close = $scope.close;\n}])\n\n.directive('alert', function () {\n  return {\n    restrict:'EA',\n    controller:'AlertController',\n    templateUrl:'template/alert/alert.html',\n    transclude:true,\n    replace:true,\n    scope: {\n      type: '@',\n      close: '&'\n    }\n  };\n})\n\n.directive('dismissOnTimeout', ['$timeout', function($timeout) {\n  return {\n    require: 'alert',\n    link: function(scope, element, attrs, alertCtrl) {\n      $timeout(function(){\n        alertCtrl.close();\n      }, parseInt(attrs.dismissOnTimeout, 10));\n    }\n  };\n}]);\n\nangular.module('ui.bootstrap.bindHtml', [])\n\n  .directive('bindHtmlUnsafe', function () {\n    return function (scope, element, attr) {\n      element.addClass('ng-binding').data('$binding', attr.bindHtmlUnsafe);\n      scope.$watch(attr.bindHtmlUnsafe, function bindHtmlUnsafeWatchAction(value) {\n        element.html(value || '');\n      });\n    };\n  });\nangular.module('ui.bootstrap.buttons', [])\n\n.constant('buttonConfig', {\n  activeClass: 'active',\n  toggleEvent: 'click'\n})\n\n.controller('ButtonsController', ['buttonConfig', function(buttonConfig) {\n  this.activeClass = buttonConfig.activeClass || 'active';\n  this.toggleEvent = buttonConfig.toggleEvent || 'click';\n}])\n\n.directive('btnRadio', function () {\n  return {\n    require: ['btnRadio', 'ngModel'],\n    controller: 'ButtonsController',\n    link: function (scope, element, attrs, ctrls) {\n      var buttonsCtrl = ctrls[0], ngModelCtrl = ctrls[1];\n\n      //model -> UI\n      ngModelCtrl.$render = function () {\n        element.toggleClass(buttonsCtrl.activeClass, angular.equals(ngModelCtrl.$modelValue, scope.$eval(attrs.btnRadio)));\n      };\n\n      //ui->model\n      element.bind(buttonsCtrl.toggleEvent, function () {\n        var isActive = element.hasClass(buttonsCtrl.activeClass);\n\n        if (!isActive || angular.isDefined(attrs.uncheckable)) {\n          scope.$apply(function () {\n            ngModelCtrl.$setViewValue(isActive ? null : scope.$eval(attrs.btnRadio));\n            ngModelCtrl.$render();\n          });\n        }\n      });\n    }\n  };\n})\n\n.directive('btnCheckbox', function () {\n  return {\n    require: ['btnCheckbox', 'ngModel'],\n    controller: 'ButtonsController',\n    link: function (scope, element, attrs, ctrls) {\n      var buttonsCtrl = ctrls[0], ngModelCtrl = ctrls[1];\n\n      function getTrueValue() {\n        return getCheckboxValue(attrs.btnCheckboxTrue, true);\n      }\n\n      function getFalseValue() {\n        return getCheckboxValue(attrs.btnCheckboxFalse, false);\n      }\n\n      function getCheckboxValue(attributeValue, defaultValue) {\n        var val = scope.$eval(attributeValue);\n        return angular.isDefined(val) ? val : defaultValue;\n      }\n\n      //model -> UI\n      ngModelCtrl.$render = function () {\n        element.toggleClass(buttonsCtrl.activeClass, angular.equals(ngModelCtrl.$modelValue, getTrueValue()));\n      };\n\n      //ui->model\n      element.bind(buttonsCtrl.toggleEvent, function () {\n        scope.$apply(function () {\n          ngModelCtrl.$setViewValue(element.hasClass(buttonsCtrl.activeClass) ? getFalseValue() : getTrueValue());\n          ngModelCtrl.$render();\n        });\n      });\n    }\n  };\n});\n\n/**\n* @ngdoc overview\n* @name ui.bootstrap.carousel\n*\n* @description\n* AngularJS version of an image carousel.\n*\n*/\nangular.module('ui.bootstrap.carousel', ['ui.bootstrap.transition'])\n.controller('CarouselController', ['$scope', '$timeout', '$interval', '$transition', function ($scope, $timeout, $interval, $transition) {\n  var self = this,\n    slides = self.slides = $scope.slides = [],\n    currentIndex = -1,\n    currentInterval, isPlaying;\n  self.currentSlide = null;\n\n  var destroyed = false;\n  /* direction: \"prev\" or \"next\" */\n  self.select = $scope.select = function(nextSlide, direction) {\n    var nextIndex = slides.indexOf(nextSlide);\n    //Decide direction if it's not given\n    if (direction === undefined) {\n      direction = nextIndex > currentIndex ? 'next' : 'prev';\n    }\n    if (nextSlide && nextSlide !== self.currentSlide) {\n      if ($scope.$currentTransition) {\n        $scope.$currentTransition.cancel();\n        //Timeout so ng-class in template has time to fix classes for finished slide\n        $timeout(goNext);\n      } else {\n        goNext();\n      }\n    }\n    function goNext() {\n      // Scope has been destroyed, stop here.\n      if (destroyed) { return; }\n      //If we have a slide to transition from and we have a transition type and we're allowed, go\n      if (self.currentSlide && angular.isString(direction) && !$scope.noTransition && nextSlide.$element) {\n        //We shouldn't do class manip in here, but it's the same weird thing bootstrap does. need to fix sometime\n        nextSlide.$element.addClass(direction);\n        var reflow = nextSlide.$element[0].offsetWidth; //force reflow\n\n        //Set all other slides to stop doing their stuff for the new transition\n        angular.forEach(slides, function(slide) {\n          angular.extend(slide, {direction: '', entering: false, leaving: false, active: false});\n        });\n        angular.extend(nextSlide, {direction: direction, active: true, entering: true});\n        angular.extend(self.currentSlide||{}, {direction: direction, leaving: true});\n\n        $scope.$currentTransition = $transition(nextSlide.$element, {});\n        //We have to create new pointers inside a closure since next & current will change\n        (function(next,current) {\n          $scope.$currentTransition.then(\n            function(){ transitionDone(next, current); },\n            function(){ transitionDone(next, current); }\n          );\n        }(nextSlide, self.currentSlide));\n      } else {\n        transitionDone(nextSlide, self.currentSlide);\n      }\n      self.currentSlide = nextSlide;\n      currentIndex = nextIndex;\n      //every time you change slides, reset the timer\n      restartTimer();\n    }\n    function transitionDone(next, current) {\n      angular.extend(next, {direction: '', active: true, leaving: false, entering: false});\n      angular.extend(current||{}, {direction: '', active: false, leaving: false, entering: false});\n      $scope.$currentTransition = null;\n    }\n  };\n  $scope.$on('$destroy', function () {\n    destroyed = true;\n  });\n\n  /* Allow outside people to call indexOf on slides array */\n  self.indexOfSlide = function(slide) {\n    return slides.indexOf(slide);\n  };\n\n  $scope.next = function() {\n    var newIndex = (currentIndex + 1) % slides.length;\n\n    //Prevent this user-triggered transition from occurring if there is already one in progress\n    if (!$scope.$currentTransition) {\n      return self.select(slides[newIndex], 'next');\n    }\n  };\n\n  $scope.prev = function() {\n    var newIndex = currentIndex - 1 < 0 ? slides.length - 1 : currentIndex - 1;\n\n    //Prevent this user-triggered transition from occurring if there is already one in progress\n    if (!$scope.$currentTransition) {\n      return self.select(slides[newIndex], 'prev');\n    }\n  };\n\n  $scope.isActive = function(slide) {\n     return self.currentSlide === slide;\n  };\n\n  $scope.$watch('interval', restartTimer);\n  $scope.$on('$destroy', resetTimer);\n\n  function restartTimer() {\n    resetTimer();\n    var interval = +$scope.interval;\n    if (!isNaN(interval) && interval > 0) {\n      currentInterval = $interval(timerFn, interval);\n    }\n  }\n\n  function resetTimer() {\n    if (currentInterval) {\n      $interval.cancel(currentInterval);\n      currentInterval = null;\n    }\n  }\n\n  function timerFn() {\n    var interval = +$scope.interval;\n    if (isPlaying && !isNaN(interval) && interval > 0) {\n      $scope.next();\n    } else {\n      $scope.pause();\n    }\n  }\n\n  $scope.play = function() {\n    if (!isPlaying) {\n      isPlaying = true;\n      restartTimer();\n    }\n  };\n  $scope.pause = function() {\n    if (!$scope.noPause) {\n      isPlaying = false;\n      resetTimer();\n    }\n  };\n\n  self.addSlide = function(slide, element) {\n    slide.$element = element;\n    slides.push(slide);\n    //if this is the first slide or the slide is set to active, select it\n    if(slides.length === 1 || slide.active) {\n      self.select(slides[slides.length-1]);\n      if (slides.length == 1) {\n        $scope.play();\n      }\n    } else {\n      slide.active = false;\n    }\n  };\n\n  self.removeSlide = function(slide) {\n    //get the index of the slide inside the carousel\n    var index = slides.indexOf(slide);\n    slides.splice(index, 1);\n    if (slides.length > 0 && slide.active) {\n      if (index >= slides.length) {\n        self.select(slides[index-1]);\n      } else {\n        self.select(slides[index]);\n      }\n    } else if (currentIndex > index) {\n      currentIndex--;\n    }\n  };\n\n}])\n\n/**\n * @ngdoc directive\n * @name ui.bootstrap.carousel.directive:carousel\n * @restrict EA\n *\n * @description\n * Carousel is the outer container for a set of image 'slides' to showcase.\n *\n * @param {number=} interval The time, in milliseconds, that it will take the carousel to go to the next slide.\n * @param {boolean=} noTransition Whether to disable transitions on the carousel.\n * @param {boolean=} noPause Whether to disable pausing on the carousel (by default, the carousel interval pauses on hover).\n *\n * @example\n<example module=\"ui.bootstrap\">\n  <file name=\"index.html\">\n    <carousel>\n      <slide>\n        <img src=\"http://placekitten.com/150/150\" style=\"margin:auto;\">\n        <div class=\"carousel-caption\">\n          <p>Beautiful!</p>\n        </div>\n      </slide>\n      <slide>\n        <img src=\"http://placekitten.com/100/150\" style=\"margin:auto;\">\n        <div class=\"carousel-caption\">\n          <p>D'aww!</p>\n        </div>\n      </slide>\n    </carousel>\n  </file>\n  <file name=\"demo.css\">\n    .carousel-indicators {\n      top: auto;\n      bottom: 15px;\n    }\n  </file>\n</example>\n */\n.directive('carousel', [function() {\n  return {\n    restrict: 'EA',\n    transclude: true,\n    replace: true,\n    controller: 'CarouselController',\n    require: 'carousel',\n    templateUrl: 'template/carousel/carousel.html',\n    scope: {\n      interval: '=',\n      noTransition: '=',\n      noPause: '='\n    }\n  };\n}])\n\n/**\n * @ngdoc directive\n * @name ui.bootstrap.carousel.directive:slide\n * @restrict EA\n *\n * @description\n * Creates a slide inside a {@link ui.bootstrap.carousel.directive:carousel carousel}.  Must be placed as a child of a carousel element.\n *\n * @param {boolean=} active Model binding, whether or not this slide is currently active.\n *\n * @example\n<example module=\"ui.bootstrap\">\n  <file name=\"index.html\">\n<div ng-controller=\"CarouselDemoCtrl\">\n  <carousel>\n    <slide ng-repeat=\"slide in slides\" active=\"slide.active\">\n      <img ng-src=\"{{slide.image}}\" style=\"margin:auto;\">\n      <div class=\"carousel-caption\">\n        <h4>Slide {{$index}}</h4>\n        <p>{{slide.text}}</p>\n      </div>\n    </slide>\n  </carousel>\n  Interval, in milliseconds: <input type=\"number\" ng-model=\"myInterval\">\n  <br />Enter a negative number to stop the interval.\n</div>\n  </file>\n  <file name=\"script.js\">\nfunction CarouselDemoCtrl($scope) {\n  $scope.myInterval = 5000;\n}\n  </file>\n  <file name=\"demo.css\">\n    .carousel-indicators {\n      top: auto;\n      bottom: 15px;\n    }\n  </file>\n</example>\n*/\n\n.directive('slide', function() {\n  return {\n    require: '^carousel',\n    restrict: 'EA',\n    transclude: true,\n    replace: true,\n    templateUrl: 'template/carousel/slide.html',\n    scope: {\n      active: '=?'\n    },\n    link: function (scope, element, attrs, carouselCtrl) {\n      carouselCtrl.addSlide(scope, element);\n      //when the scope is destroyed then remove the slide from the current slides array\n      scope.$on('$destroy', function() {\n        carouselCtrl.removeSlide(scope);\n      });\n\n      scope.$watch('active', function(active) {\n        if (active) {\n          carouselCtrl.select(scope);\n        }\n      });\n    }\n  };\n});\n\nangular.module('ui.bootstrap.dateparser', [])\n\n.service('dateParser', ['$locale', 'orderByFilter', function($locale, orderByFilter) {\n\n  this.parsers = {};\n\n  var formatCodeToRegex = {\n    'yyyy': {\n      regex: '\\\\d{4}',\n      apply: function(value) { this.year = +value; }\n    },\n    'yy': {\n      regex: '\\\\d{2}',\n      apply: function(value) { this.year = +value + 2000; }\n    },\n    'y': {\n      regex: '\\\\d{1,4}',\n      apply: function(value) { this.year = +value; }\n    },\n    'MMMM': {\n      regex: $locale.DATETIME_FORMATS.MONTH.join('|'),\n      apply: function(value) { this.month = $locale.DATETIME_FORMATS.MONTH.indexOf(value); }\n    },\n    'MMM': {\n      regex: $locale.DATETIME_FORMATS.SHORTMONTH.join('|'),\n      apply: function(value) { this.month = $locale.DATETIME_FORMATS.SHORTMONTH.indexOf(value); }\n    },\n    'MM': {\n      regex: '0[1-9]|1[0-2]',\n      apply: function(value) { this.month = value - 1; }\n    },\n    'M': {\n      regex: '[1-9]|1[0-2]',\n      apply: function(value) { this.month = value - 1; }\n    },\n    'dd': {\n      regex: '[0-2][0-9]{1}|3[0-1]{1}',\n      apply: function(value) { this.date = +value; }\n    },\n    'd': {\n      regex: '[1-2]?[0-9]{1}|3[0-1]{1}',\n      apply: function(value) { this.date = +value; }\n    },\n    'EEEE': {\n      regex: $locale.DATETIME_FORMATS.DAY.join('|')\n    },\n    'EEE': {\n      regex: $locale.DATETIME_FORMATS.SHORTDAY.join('|')\n    }\n  };\n\n  function createParser(format) {\n    var map = [], regex = format.split('');\n\n    angular.forEach(formatCodeToRegex, function(data, code) {\n      var index = format.indexOf(code);\n\n      if (index > -1) {\n        format = format.split('');\n\n        regex[index] = '(' + data.regex + ')';\n        format[index] = '$'; // Custom symbol to define consumed part of format\n        for (var i = index + 1, n = index + code.length; i < n; i++) {\n          regex[i] = '';\n          format[i] = '$';\n        }\n        format = format.join('');\n\n        map.push({ index: index, apply: data.apply });\n      }\n    });\n\n    return {\n      regex: new RegExp('^' + regex.join('') + '$'),\n      map: orderByFilter(map, 'index')\n    };\n  }\n\n  this.parse = function(input, format) {\n    if ( !angular.isString(input) || !format ) {\n      return input;\n    }\n\n    format = $locale.DATETIME_FORMATS[format] || format;\n\n    if ( !this.parsers[format] ) {\n      this.parsers[format] = createParser(format);\n    }\n\n    var parser = this.parsers[format],\n        regex = parser.regex,\n        map = parser.map,\n        results = input.match(regex);\n\n    if ( results && results.length ) {\n      var fields = { year: 1900, month: 0, date: 1, hours: 0 }, dt;\n\n      for( var i = 1, n = results.length; i < n; i++ ) {\n        var mapper = map[i-1];\n        if ( mapper.apply ) {\n          mapper.apply.call(fields, results[i]);\n        }\n      }\n\n      if ( isValid(fields.year, fields.month, fields.date) ) {\n        dt = new Date( fields.year, fields.month, fields.date, fields.hours);\n      }\n\n      return dt;\n    }\n  };\n\n  // Check if date is valid for specific month (and year for February).\n  // Month: 0 = Jan, 1 = Feb, etc\n  function isValid(year, month, date) {\n    if ( month === 1 && date > 28) {\n        return date === 29 && ((year % 4 === 0 && year % 100 !== 0) || year % 400 === 0);\n    }\n\n    if ( month === 3 || month === 5 || month === 8 || month === 10) {\n        return date < 31;\n    }\n\n    return true;\n  }\n}]);\n\nangular.module('ui.bootstrap.position', [])\n\n/**\n * A set of utility methods that can be use to retrieve position of DOM elements.\n * It is meant to be used where we need to absolute-position DOM elements in\n * relation to other, existing elements (this is the case for tooltips, popovers,\n * typeahead suggestions etc.).\n */\n  .factory('$position', ['$document', '$window', function ($document, $window) {\n\n    function getStyle(el, cssprop) {\n      if (el.currentStyle) { //IE\n        return el.currentStyle[cssprop];\n      } else if ($window.getComputedStyle) {\n        return $window.getComputedStyle(el)[cssprop];\n      }\n      // finally try and get inline style\n      return el.style[cssprop];\n    }\n\n    /**\n     * Checks if a given element is statically positioned\n     * @param element - raw DOM element\n     */\n    function isStaticPositioned(element) {\n      return (getStyle(element, 'position') || 'static' ) === 'static';\n    }\n\n    /**\n     * returns the closest, non-statically positioned parentOffset of a given element\n     * @param element\n     */\n    var parentOffsetEl = function (element) {\n      var docDomEl = $document[0];\n      var offsetParent = element.offsetParent || docDomEl;\n      while (offsetParent && offsetParent !== docDomEl && isStaticPositioned(offsetParent) ) {\n        offsetParent = offsetParent.offsetParent;\n      }\n      return offsetParent || docDomEl;\n    };\n\n    return {\n      /**\n       * Provides read-only equivalent of jQuery's position function:\n       * http://api.jquery.com/position/\n       */\n      position: function (element) {\n        var elBCR = this.offset(element);\n        var offsetParentBCR = { top: 0, left: 0 };\n        var offsetParentEl = parentOffsetEl(element[0]);\n        if (offsetParentEl != $document[0]) {\n          offsetParentBCR = this.offset(angular.element(offsetParentEl));\n          offsetParentBCR.top += offsetParentEl.clientTop - offsetParentEl.scrollTop;\n          offsetParentBCR.left += offsetParentEl.clientLeft - offsetParentEl.scrollLeft;\n        }\n\n        var boundingClientRect = element[0].getBoundingClientRect();\n        return {\n          width: boundingClientRect.width || element.prop('offsetWidth'),\n          height: boundingClientRect.height || element.prop('offsetHeight'),\n          top: elBCR.top - offsetParentBCR.top,\n          left: elBCR.left - offsetParentBCR.left\n        };\n      },\n\n      /**\n       * Provides read-only equivalent of jQuery's offset function:\n       * http://api.jquery.com/offset/\n       */\n      offset: function (element) {\n        var boundingClientRect = element[0].getBoundingClientRect();\n        return {\n          width: boundingClientRect.width || element.prop('offsetWidth'),\n          height: boundingClientRect.height || element.prop('offsetHeight'),\n          top: boundingClientRect.top + ($window.pageYOffset || $document[0].documentElement.scrollTop),\n          left: boundingClientRect.left + ($window.pageXOffset || $document[0].documentElement.scrollLeft)\n        };\n      },\n\n      /**\n       * Provides coordinates for the targetEl in relation to hostEl\n       */\n      positionElements: function (hostEl, targetEl, positionStr, appendToBody) {\n\n        var positionStrParts = positionStr.split('-');\n        var pos0 = positionStrParts[0], pos1 = positionStrParts[1] || 'center';\n\n        var hostElPos,\n          targetElWidth,\n          targetElHeight,\n          targetElPos;\n\n        hostElPos = appendToBody ? this.offset(hostEl) : this.position(hostEl);\n\n        targetElWidth = targetEl.prop('offsetWidth');\n        targetElHeight = targetEl.prop('offsetHeight');\n\n        var shiftWidth = {\n          center: function () {\n            return hostElPos.left + hostElPos.width / 2 - targetElWidth / 2;\n          },\n          left: function () {\n            return hostElPos.left;\n          },\n          right: function () {\n            return hostElPos.left + hostElPos.width;\n          }\n        };\n\n        var shiftHeight = {\n          center: function () {\n            return hostElPos.top + hostElPos.height / 2 - targetElHeight / 2;\n          },\n          top: function () {\n            return hostElPos.top;\n          },\n          bottom: function () {\n            return hostElPos.top + hostElPos.height;\n          }\n        };\n\n        switch (pos0) {\n          case 'right':\n            targetElPos = {\n              top: shiftHeight[pos1](),\n              left: shiftWidth[pos0]()\n            };\n            break;\n          case 'left':\n            targetElPos = {\n              top: shiftHeight[pos1](),\n              left: hostElPos.left - targetElWidth\n            };\n            break;\n          case 'bottom':\n            targetElPos = {\n              top: shiftHeight[pos0](),\n              left: shiftWidth[pos1]()\n            };\n            break;\n          default:\n            targetElPos = {\n              top: hostElPos.top - targetElHeight,\n              left: shiftWidth[pos1]()\n            };\n            break;\n        }\n\n        return targetElPos;\n      }\n    };\n  }]);\n\nangular.module('ui.bootstrap.datepicker', ['ui.bootstrap.dateparser', 'ui.bootstrap.position'])\n\n.constant('datepickerConfig', {\n  formatDay: 'dd',\n  formatMonth: 'MMMM',\n  formatYear: 'yyyy',\n  formatDayHeader: 'EEE',\n  formatDayTitle: 'MMMM yyyy',\n  formatMonthTitle: 'yyyy',\n  datepickerMode: 'day',\n  minMode: 'day',\n  maxMode: 'year',\n  showWeeks: true,\n  startingDay: 0,\n  yearRange: 20,\n  minDate: null,\n  maxDate: null\n})\n\n.controller('DatepickerController', ['$scope', '$attrs', '$parse', '$interpolate', '$timeout', '$log', 'dateFilter', 'datepickerConfig', function($scope, $attrs, $parse, $interpolate, $timeout, $log, dateFilter, datepickerConfig) {\n  var self = this,\n      ngModelCtrl = { $setViewValue: angular.noop }; // nullModelCtrl;\n\n  // Modes chain\n  this.modes = ['day', 'month', 'year'];\n\n  // Configuration attributes\n  angular.forEach(['formatDay', 'formatMonth', 'formatYear', 'formatDayHeader', 'formatDayTitle', 'formatMonthTitle',\n                   'minMode', 'maxMode', 'showWeeks', 'startingDay', 'yearRange'], function( key, index ) {\n    self[key] = angular.isDefined($attrs[key]) ? (index < 8 ? $interpolate($attrs[key])($scope.$parent) : $scope.$parent.$eval($attrs[key])) : datepickerConfig[key];\n  });\n\n  // Watchable date attributes\n  angular.forEach(['minDate', 'maxDate'], function( key ) {\n    if ( $attrs[key] ) {\n      $scope.$parent.$watch($parse($attrs[key]), function(value) {\n        self[key] = value ? new Date(value) : null;\n        self.refreshView();\n      });\n    } else {\n      self[key] = datepickerConfig[key] ? new Date(datepickerConfig[key]) : null;\n    }\n  });\n\n  $scope.datepickerMode = $scope.datepickerMode || datepickerConfig.datepickerMode;\n  $scope.uniqueId = 'datepicker-' + $scope.$id + '-' + Math.floor(Math.random() * 10000);\n  this.activeDate = angular.isDefined($attrs.initDate) ? $scope.$parent.$eval($attrs.initDate) : new Date();\n\n  $scope.isActive = function(dateObject) {\n    if (self.compare(dateObject.date, self.activeDate) === 0) {\n      $scope.activeDateId = dateObject.uid;\n      return true;\n    }\n    return false;\n  };\n\n  this.init = function( ngModelCtrl_ ) {\n    ngModelCtrl = ngModelCtrl_;\n\n    ngModelCtrl.$render = function() {\n      self.render();\n    };\n  };\n\n  this.render = function() {\n    if ( ngModelCtrl.$modelValue ) {\n      var date = new Date( ngModelCtrl.$modelValue ),\n          isValid = !isNaN(date);\n\n      if ( isValid ) {\n        this.activeDate = date;\n      } else {\n        $log.error('Datepicker directive: \"ng-model\" value must be a Date object, a number of milliseconds since 01.01.1970 or a string representing an RFC2822 or ISO 8601 date.');\n      }\n      ngModelCtrl.$setValidity('date', isValid);\n    }\n    this.refreshView();\n  };\n\n  this.refreshView = function() {\n    if ( this.element ) {\n      this._refreshView();\n\n      var date = ngModelCtrl.$modelValue ? new Date(ngModelCtrl.$modelValue) : null;\n      ngModelCtrl.$setValidity('date-disabled', !date || (this.element && !this.isDisabled(date)));\n    }\n  };\n\n  this.createDateObject = function(date, format) {\n    var model = ngModelCtrl.$modelValue ? new Date(ngModelCtrl.$modelValue) : null;\n    return {\n      date: date,\n      label: dateFilter(date, format),\n      selected: model && this.compare(date, model) === 0,\n      disabled: this.isDisabled(date),\n      current: this.compare(date, new Date()) === 0\n    };\n  };\n\n  this.isDisabled = function( date ) {\n    return ((this.minDate && this.compare(date, this.minDate) < 0) || (this.maxDate && this.compare(date, this.maxDate) > 0) || ($attrs.dateDisabled && $scope.dateDisabled({date: date, mode: $scope.datepickerMode})));\n  };\n\n  // Split array into smaller arrays\n  this.split = function(arr, size) {\n    var arrays = [];\n    while (arr.length > 0) {\n      arrays.push(arr.splice(0, size));\n    }\n    return arrays;\n  };\n\n  $scope.select = function( date ) {\n    if ( $scope.datepickerMode === self.minMode ) {\n      var dt = ngModelCtrl.$modelValue ? new Date( ngModelCtrl.$modelValue ) : new Date(0, 0, 0, 0, 0, 0, 0);\n      dt.setFullYear( date.getFullYear(), date.getMonth(), date.getDate() );\n      ngModelCtrl.$setViewValue( dt );\n      ngModelCtrl.$render();\n    } else {\n      self.activeDate = date;\n      $scope.datepickerMode = self.modes[ self.modes.indexOf( $scope.datepickerMode ) - 1 ];\n    }\n  };\n\n  $scope.move = function( direction ) {\n    var year = self.activeDate.getFullYear() + direction * (self.step.years || 0),\n        month = self.activeDate.getMonth() + direction * (self.step.months || 0);\n    self.activeDate.setFullYear(year, month, 1);\n    self.refreshView();\n  };\n\n  $scope.toggleMode = function( direction ) {\n    direction = direction || 1;\n\n    if (($scope.datepickerMode === self.maxMode && direction === 1) || ($scope.datepickerMode === self.minMode && direction === -1)) {\n      return;\n    }\n\n    $scope.datepickerMode = self.modes[ self.modes.indexOf( $scope.datepickerMode ) + direction ];\n  };\n\n  // Key event mapper\n  $scope.keys = { 13:'enter', 32:'space', 33:'pageup', 34:'pagedown', 35:'end', 36:'home', 37:'left', 38:'up', 39:'right', 40:'down' };\n\n  var focusElement = function() {\n    $timeout(function() {\n      self.element[0].focus();\n    }, 0 , false);\n  };\n\n  // Listen for focus requests from popup directive\n  $scope.$on('datepicker.focus', focusElement);\n\n  $scope.keydown = function( evt ) {\n    var key = $scope.keys[evt.which];\n\n    if ( !key || evt.shiftKey || evt.altKey ) {\n      return;\n    }\n\n    evt.preventDefault();\n    evt.stopPropagation();\n\n    if (key === 'enter' || key === 'space') {\n      if ( self.isDisabled(self.activeDate)) {\n        return; // do nothing\n      }\n      $scope.select(self.activeDate);\n      focusElement();\n    } else if (evt.ctrlKey && (key === 'up' || key === 'down')) {\n      $scope.toggleMode(key === 'up' ? 1 : -1);\n      focusElement();\n    } else {\n      self.handleKeyDown(key, evt);\n      self.refreshView();\n    }\n  };\n}])\n\n.directive( 'datepicker', function () {\n  return {\n    restrict: 'EA',\n    replace: true,\n    templateUrl: 'template/datepicker/datepicker.html',\n    scope: {\n      datepickerMode: '=?',\n      dateDisabled: '&'\n    },\n    require: ['datepicker', '?^ngModel'],\n    controller: 'DatepickerController',\n    link: function(scope, element, attrs, ctrls) {\n      var datepickerCtrl = ctrls[0], ngModelCtrl = ctrls[1];\n\n      if ( ngModelCtrl ) {\n        datepickerCtrl.init( ngModelCtrl );\n      }\n    }\n  };\n})\n\n.directive('daypicker', ['dateFilter', function (dateFilter) {\n  return {\n    restrict: 'EA',\n    replace: true,\n    templateUrl: 'template/datepicker/day.html',\n    require: '^datepicker',\n    link: function(scope, element, attrs, ctrl) {\n      scope.showWeeks = ctrl.showWeeks;\n\n      ctrl.step = { months: 1 };\n      ctrl.element = element;\n\n      var DAYS_IN_MONTH = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];\n      function getDaysInMonth( year, month ) {\n        return ((month === 1) && (year % 4 === 0) && ((year % 100 !== 0) || (year % 400 === 0))) ? 29 : DAYS_IN_MONTH[month];\n      }\n\n      function getDates(startDate, n) {\n        var dates = new Array(n), current = new Date(startDate), i = 0;\n        current.setHours(12); // Prevent repeated dates because of timezone bug\n        while ( i < n ) {\n          dates[i++] = new Date(current);\n          current.setDate( current.getDate() + 1 );\n        }\n        return dates;\n      }\n\n      ctrl._refreshView = function() {\n        var year = ctrl.activeDate.getFullYear(),\n          month = ctrl.activeDate.getMonth(),\n          firstDayOfMonth = new Date(year, month, 1),\n          difference = ctrl.startingDay - firstDayOfMonth.getDay(),\n          numDisplayedFromPreviousMonth = (difference > 0) ? 7 - difference : - difference,\n          firstDate = new Date(firstDayOfMonth);\n\n        if ( numDisplayedFromPreviousMonth > 0 ) {\n          firstDate.setDate( - numDisplayedFromPreviousMonth + 1 );\n        }\n\n        // 42 is the number of days on a six-month calendar\n        var days = getDates(firstDate, 42);\n        for (var i = 0; i < 42; i ++) {\n          days[i] = angular.extend(ctrl.createDateObject(days[i], ctrl.formatDay), {\n            secondary: days[i].getMonth() !== month,\n            uid: scope.uniqueId + '-' + i\n          });\n        }\n\n        scope.labels = new Array(7);\n        for (var j = 0; j < 7; j++) {\n          scope.labels[j] = {\n            abbr: dateFilter(days[j].date, ctrl.formatDayHeader),\n            full: dateFilter(days[j].date, 'EEEE')\n          };\n        }\n\n        scope.title = dateFilter(ctrl.activeDate, ctrl.formatDayTitle);\n        scope.rows = ctrl.split(days, 7);\n\n        if ( scope.showWeeks ) {\n          scope.weekNumbers = [];\n          var weekNumber = getISO8601WeekNumber( scope.rows[0][0].date ),\n              numWeeks = scope.rows.length;\n          while( scope.weekNumbers.push(weekNumber++) < numWeeks ) {}\n        }\n      };\n\n      ctrl.compare = function(date1, date2) {\n        return (new Date( date1.getFullYear(), date1.getMonth(), date1.getDate() ) - new Date( date2.getFullYear(), date2.getMonth(), date2.getDate() ) );\n      };\n\n      function getISO8601WeekNumber(date) {\n        var checkDate = new Date(date);\n        checkDate.setDate(checkDate.getDate() + 4 - (checkDate.getDay() || 7)); // Thursday\n        var time = checkDate.getTime();\n        checkDate.setMonth(0); // Compare with Jan 1\n        checkDate.setDate(1);\n        return Math.floor(Math.round((time - checkDate) / 86400000) / 7) + 1;\n      }\n\n      ctrl.handleKeyDown = function( key, evt ) {\n        var date = ctrl.activeDate.getDate();\n\n        if (key === 'left') {\n          date = date - 1;   // up\n        } else if (key === 'up') {\n          date = date - 7;   // down\n        } else if (key === 'right') {\n          date = date + 1;   // down\n        } else if (key === 'down') {\n          date = date + 7;\n        } else if (key === 'pageup' || key === 'pagedown') {\n          var month = ctrl.activeDate.getMonth() + (key === 'pageup' ? - 1 : 1);\n          ctrl.activeDate.setMonth(month, 1);\n          date = Math.min(getDaysInMonth(ctrl.activeDate.getFullYear(), ctrl.activeDate.getMonth()), date);\n        } else if (key === 'home') {\n          date = 1;\n        } else if (key === 'end') {\n          date = getDaysInMonth(ctrl.activeDate.getFullYear(), ctrl.activeDate.getMonth());\n        }\n        ctrl.activeDate.setDate(date);\n      };\n\n      ctrl.refreshView();\n    }\n  };\n}])\n\n.directive('monthpicker', ['dateFilter', function (dateFilter) {\n  return {\n    restrict: 'EA',\n    replace: true,\n    templateUrl: 'template/datepicker/month.html',\n    require: '^datepicker',\n    link: function(scope, element, attrs, ctrl) {\n      ctrl.step = { years: 1 };\n      ctrl.element = element;\n\n      ctrl._refreshView = function() {\n        var months = new Array(12),\n            year = ctrl.activeDate.getFullYear();\n\n        for ( var i = 0; i < 12; i++ ) {\n          months[i] = angular.extend(ctrl.createDateObject(new Date(year, i, 1), ctrl.formatMonth), {\n            uid: scope.uniqueId + '-' + i\n          });\n        }\n\n        scope.title = dateFilter(ctrl.activeDate, ctrl.formatMonthTitle);\n        scope.rows = ctrl.split(months, 3);\n      };\n\n      ctrl.compare = function(date1, date2) {\n        return new Date( date1.getFullYear(), date1.getMonth() ) - new Date( date2.getFullYear(), date2.getMonth() );\n      };\n\n      ctrl.handleKeyDown = function( key, evt ) {\n        var date = ctrl.activeDate.getMonth();\n\n        if (key === 'left') {\n          date = date - 1;   // up\n        } else if (key === 'up') {\n          date = date - 3;   // down\n        } else if (key === 'right') {\n          date = date + 1;   // down\n        } else if (key === 'down') {\n          date = date + 3;\n        } else if (key === 'pageup' || key === 'pagedown') {\n          var year = ctrl.activeDate.getFullYear() + (key === 'pageup' ? - 1 : 1);\n          ctrl.activeDate.setFullYear(year);\n        } else if (key === 'home') {\n          date = 0;\n        } else if (key === 'end') {\n          date = 11;\n        }\n        ctrl.activeDate.setMonth(date);\n      };\n\n      ctrl.refreshView();\n    }\n  };\n}])\n\n.directive('yearpicker', ['dateFilter', function (dateFilter) {\n  return {\n    restrict: 'EA',\n    replace: true,\n    templateUrl: 'template/datepicker/year.html',\n    require: '^datepicker',\n    link: function(scope, element, attrs, ctrl) {\n      var range = ctrl.yearRange;\n\n      ctrl.step = { years: range };\n      ctrl.element = element;\n\n      function getStartingYear( year ) {\n        return parseInt((year - 1) / range, 10) * range + 1;\n      }\n\n      ctrl._refreshView = function() {\n        var years = new Array(range);\n\n        for ( var i = 0, start = getStartingYear(ctrl.activeDate.getFullYear()); i < range; i++ ) {\n          years[i] = angular.extend(ctrl.createDateObject(new Date(start + i, 0, 1), ctrl.formatYear), {\n            uid: scope.uniqueId + '-' + i\n          });\n        }\n\n        scope.title = [years[0].label, years[range - 1].label].join(' - ');\n        scope.rows = ctrl.split(years, 5);\n      };\n\n      ctrl.compare = function(date1, date2) {\n        return date1.getFullYear() - date2.getFullYear();\n      };\n\n      ctrl.handleKeyDown = function( key, evt ) {\n        var date = ctrl.activeDate.getFullYear();\n\n        if (key === 'left') {\n          date = date - 1;   // up\n        } else if (key === 'up') {\n          date = date - 5;   // down\n        } else if (key === 'right') {\n          date = date + 1;   // down\n        } else if (key === 'down') {\n          date = date + 5;\n        } else if (key === 'pageup' || key === 'pagedown') {\n          date += (key === 'pageup' ? - 1 : 1) * ctrl.step.years;\n        } else if (key === 'home') {\n          date = getStartingYear( ctrl.activeDate.getFullYear() );\n        } else if (key === 'end') {\n          date = getStartingYear( ctrl.activeDate.getFullYear() ) + range - 1;\n        }\n        ctrl.activeDate.setFullYear(date);\n      };\n\n      ctrl.refreshView();\n    }\n  };\n}])\n\n.constant('datepickerPopupConfig', {\n  datepickerPopup: 'yyyy-MM-dd',\n  currentText: 'Today',\n  clearText: 'Clear',\n  closeText: 'Done',\n  closeOnDateSelection: true,\n  appendToBody: false,\n  showButtonBar: true\n})\n\n.directive('datepickerPopup', ['$compile', '$parse', '$document', '$position', 'dateFilter', 'dateParser', 'datepickerPopupConfig',\nfunction ($compile, $parse, $document, $position, dateFilter, dateParser, datepickerPopupConfig) {\n  return {\n    restrict: 'EA',\n    require: 'ngModel',\n    scope: {\n      isOpen: '=?',\n      currentText: '@',\n      clearText: '@',\n      closeText: '@',\n      dateDisabled: '&'\n    },\n    link: function(scope, element, attrs, ngModel) {\n      var dateFormat,\n          closeOnDateSelection = angular.isDefined(attrs.closeOnDateSelection) ? scope.$parent.$eval(attrs.closeOnDateSelection) : datepickerPopupConfig.closeOnDateSelection,\n          appendToBody = angular.isDefined(attrs.datepickerAppendToBody) ? scope.$parent.$eval(attrs.datepickerAppendToBody) : datepickerPopupConfig.appendToBody;\n\n      scope.showButtonBar = angular.isDefined(attrs.showButtonBar) ? scope.$parent.$eval(attrs.showButtonBar) : datepickerPopupConfig.showButtonBar;\n\n      scope.getText = function( key ) {\n        return scope[key + 'Text'] || datepickerPopupConfig[key + 'Text'];\n      };\n\n      attrs.$observe('datepickerPopup', function(value) {\n          dateFormat = value || datepickerPopupConfig.datepickerPopup;\n          ngModel.$render();\n      });\n\n      // popup element used to display calendar\n      var popupEl = angular.element('<div datepicker-popup-wrap><div datepicker></div></div>');\n      popupEl.attr({\n        'ng-model': 'date',\n        'ng-change': 'dateSelection()'\n      });\n\n      function cameltoDash( string ){\n        return string.replace(/([A-Z])/g, function($1) { return '-' + $1.toLowerCase(); });\n      }\n\n      // datepicker element\n      var datepickerEl = angular.element(popupEl.children()[0]);\n      if ( attrs.datepickerOptions ) {\n        angular.forEach(scope.$parent.$eval(attrs.datepickerOptions), function( value, option ) {\n          datepickerEl.attr( cameltoDash(option), value );\n        });\n      }\n\n      scope.watchData = {};\n      angular.forEach(['minDate', 'maxDate', 'datepickerMode'], function( key ) {\n        if ( attrs[key] ) {\n          var getAttribute = $parse(attrs[key]);\n          scope.$parent.$watch(getAttribute, function(value){\n            scope.watchData[key] = value;\n          });\n          datepickerEl.attr(cameltoDash(key), 'watchData.' + key);\n\n          // Propagate changes from datepicker to outside\n          if ( key === 'datepickerMode' ) {\n            var setAttribute = getAttribute.assign;\n            scope.$watch('watchData.' + key, function(value, oldvalue) {\n              if ( value !== oldvalue ) {\n                setAttribute(scope.$parent, value);\n              }\n            });\n          }\n        }\n      });\n      if (attrs.dateDisabled) {\n        datepickerEl.attr('date-disabled', 'dateDisabled({ date: date, mode: mode })');\n      }\n\n      function parseDate(viewValue) {\n        if (!viewValue) {\n          ngModel.$setValidity('date', true);\n          return null;\n        } else if (angular.isDate(viewValue) && !isNaN(viewValue)) {\n          ngModel.$setValidity('date', true);\n          return viewValue;\n        } else if (angular.isString(viewValue)) {\n          var date = dateParser.parse(viewValue, dateFormat) || new Date(viewValue);\n          if (isNaN(date)) {\n            ngModel.$setValidity('date', false);\n            return undefined;\n          } else {\n            ngModel.$setValidity('date', true);\n            return date;\n          }\n        } else {\n          ngModel.$setValidity('date', false);\n          return undefined;\n        }\n      }\n      ngModel.$parsers.unshift(parseDate);\n\n      // Inner change\n      scope.dateSelection = function(dt) {\n        if (angular.isDefined(dt)) {\n          scope.date = dt;\n        }\n        ngModel.$setViewValue(scope.date);\n        ngModel.$render();\n\n        if ( closeOnDateSelection ) {\n          scope.isOpen = false;\n          element[0].focus();\n        }\n      };\n\n      element.bind('input change keyup', function() {\n        scope.$apply(function() {\n          scope.date = ngModel.$modelValue;\n        });\n      });\n\n      // Outter change\n      ngModel.$render = function() {\n        var date = ngModel.$viewValue ? dateFilter(ngModel.$viewValue, dateFormat) : '';\n        element.val(date);\n        scope.date = parseDate( ngModel.$modelValue );\n      };\n\n      var documentClickBind = function(event) {\n        if (scope.isOpen && event.target !== element[0]) {\n          scope.$apply(function() {\n            scope.isOpen = false;\n          });\n        }\n      };\n\n      var keydown = function(evt, noApply) {\n        scope.keydown(evt);\n      };\n      element.bind('keydown', keydown);\n\n      scope.keydown = function(evt) {\n        if (evt.which === 27) {\n          evt.preventDefault();\n          evt.stopPropagation();\n          scope.close();\n        } else if (evt.which === 40 && !scope.isOpen) {\n          scope.isOpen = true;\n        }\n      };\n\n      scope.$watch('isOpen', function(value) {\n        if (value) {\n          scope.$broadcast('datepicker.focus');\n          scope.position = appendToBody ? $position.offset(element) : $position.position(element);\n          scope.position.top = scope.position.top + element.prop('offsetHeight');\n\n          $document.bind('click', documentClickBind);\n        } else {\n          $document.unbind('click', documentClickBind);\n        }\n      });\n\n      scope.select = function( date ) {\n        if (date === 'today') {\n          var today = new Date();\n          if (angular.isDate(ngModel.$modelValue)) {\n            date = new Date(ngModel.$modelValue);\n            date.setFullYear(today.getFullYear(), today.getMonth(), today.getDate());\n          } else {\n            date = new Date(today.setHours(0, 0, 0, 0));\n          }\n        }\n        scope.dateSelection( date );\n      };\n\n      scope.close = function() {\n        scope.isOpen = false;\n        element[0].focus();\n      };\n\n      var $popup = $compile(popupEl)(scope);\n      // Prevent jQuery cache memory leak (template is now redundant after linking)\n      popupEl.remove();\n\n      if ( appendToBody ) {\n        $document.find('body').append($popup);\n      } else {\n        element.after($popup);\n      }\n\n      scope.$on('$destroy', function() {\n        $popup.remove();\n        element.unbind('keydown', keydown);\n        $document.unbind('click', documentClickBind);\n      });\n    }\n  };\n}])\n\n.directive('datepickerPopupWrap', function() {\n  return {\n    restrict:'EA',\n    replace: true,\n    transclude: true,\n    templateUrl: 'template/datepicker/popup.html',\n    link:function (scope, element, attrs) {\n      element.bind('click', function(event) {\n        event.preventDefault();\n        event.stopPropagation();\n      });\n    }\n  };\n});\n\nangular.module('ui.bootstrap.dropdown', [])\n\n.constant('dropdownConfig', {\n  openClass: 'open'\n})\n\n.service('dropdownService', ['$document', function($document) {\n  var openScope = null;\n\n  this.open = function( dropdownScope ) {\n    if ( !openScope ) {\n      $document.bind('click', closeDropdown);\n      $document.bind('keydown', escapeKeyBind);\n    }\n\n    if ( openScope && openScope !== dropdownScope ) {\n        openScope.isOpen = false;\n    }\n\n    openScope = dropdownScope;\n  };\n\n  this.close = function( dropdownScope ) {\n    if ( openScope === dropdownScope ) {\n      openScope = null;\n      $document.unbind('click', closeDropdown);\n      $document.unbind('keydown', escapeKeyBind);\n    }\n  };\n\n  var closeDropdown = function( evt ) {\n    // This method may still be called during the same mouse event that\n    // unbound this event handler. So check openScope before proceeding.\n    if (!openScope) { return; }\n\n    var toggleElement = openScope.getToggleElement();\n    if ( evt && toggleElement && toggleElement[0].contains(evt.target) ) {\n        return;\n    }\n\n    openScope.$apply(function() {\n      openScope.isOpen = false;\n    });\n  };\n\n  var escapeKeyBind = function( evt ) {\n    if ( evt.which === 27 ) {\n      openScope.focusToggleElement();\n      closeDropdown();\n    }\n  };\n}])\n\n.controller('DropdownController', ['$scope', '$attrs', '$parse', 'dropdownConfig', 'dropdownService', '$animate', function($scope, $attrs, $parse, dropdownConfig, dropdownService, $animate) {\n  var self = this,\n      scope = $scope.$new(), // create a child scope so we are not polluting original one\n      openClass = dropdownConfig.openClass,\n      getIsOpen,\n      setIsOpen = angular.noop,\n      toggleInvoker = $attrs.onToggle ? $parse($attrs.onToggle) : angular.noop;\n\n  this.init = function( element ) {\n    self.$element = element;\n\n    if ( $attrs.isOpen ) {\n      getIsOpen = $parse($attrs.isOpen);\n      setIsOpen = getIsOpen.assign;\n\n      $scope.$watch(getIsOpen, function(value) {\n        scope.isOpen = !!value;\n      });\n    }\n  };\n\n  this.toggle = function( open ) {\n    return scope.isOpen = arguments.length ? !!open : !scope.isOpen;\n  };\n\n  // Allow other directives to watch status\n  this.isOpen = function() {\n    return scope.isOpen;\n  };\n\n  scope.getToggleElement = function() {\n    return self.toggleElement;\n  };\n\n  scope.focusToggleElement = function() {\n    if ( self.toggleElement ) {\n      self.toggleElement[0].focus();\n    }\n  };\n\n  scope.$watch('isOpen', function( isOpen, wasOpen ) {\n    $animate[isOpen ? 'addClass' : 'removeClass'](self.$element, openClass);\n\n    if ( isOpen ) {\n      scope.focusToggleElement();\n      dropdownService.open( scope );\n    } else {\n      dropdownService.close( scope );\n    }\n\n    setIsOpen($scope, isOpen);\n    if (angular.isDefined(isOpen) && isOpen !== wasOpen) {\n      toggleInvoker($scope, { open: !!isOpen });\n    }\n  });\n\n  $scope.$on('$locationChangeSuccess', function() {\n    scope.isOpen = false;\n  });\n\n  $scope.$on('$destroy', function() {\n    scope.$destroy();\n  });\n}])\n\n.directive('dropdown', function() {\n  return {\n    controller: 'DropdownController',\n    link: function(scope, element, attrs, dropdownCtrl) {\n      dropdownCtrl.init( element );\n    }\n  };\n})\n\n.directive('dropdownToggle', function() {\n  return {\n    require: '?^dropdown',\n    link: function(scope, element, attrs, dropdownCtrl) {\n      if ( !dropdownCtrl ) {\n        return;\n      }\n\n      dropdownCtrl.toggleElement = element;\n\n      var toggleDropdown = function(event) {\n        event.preventDefault();\n\n        if ( !element.hasClass('disabled') && !attrs.disabled ) {\n          scope.$apply(function() {\n            dropdownCtrl.toggle();\n          });\n        }\n      };\n\n      element.bind('click', toggleDropdown);\n\n      // WAI-ARIA\n      element.attr({ 'aria-haspopup': true, 'aria-expanded': false });\n      scope.$watch(dropdownCtrl.isOpen, function( isOpen ) {\n        element.attr('aria-expanded', !!isOpen);\n      });\n\n      scope.$on('$destroy', function() {\n        element.unbind('click', toggleDropdown);\n      });\n    }\n  };\n});\n\nangular.module('ui.bootstrap.modal', ['ui.bootstrap.transition'])\n\n/**\n * A helper, internal data structure that acts as a map but also allows getting / removing\n * elements in the LIFO order\n */\n  .factory('$$stackedMap', function () {\n    return {\n      createNew: function () {\n        var stack = [];\n\n        return {\n          add: function (key, value) {\n            stack.push({\n              key: key,\n              value: value\n            });\n          },\n          get: function (key) {\n            for (var i = 0; i < stack.length; i++) {\n              if (key == stack[i].key) {\n                return stack[i];\n              }\n            }\n          },\n          keys: function() {\n            var keys = [];\n            for (var i = 0; i < stack.length; i++) {\n              keys.push(stack[i].key);\n            }\n            return keys;\n          },\n          top: function () {\n            return stack[stack.length - 1];\n          },\n          remove: function (key) {\n            var idx = -1;\n            for (var i = 0; i < stack.length; i++) {\n              if (key == stack[i].key) {\n                idx = i;\n                break;\n              }\n            }\n            return stack.splice(idx, 1)[0];\n          },\n          removeTop: function () {\n            return stack.splice(stack.length - 1, 1)[0];\n          },\n          length: function () {\n            return stack.length;\n          }\n        };\n      }\n    };\n  })\n\n/**\n * A helper directive for the $modal service. It creates a backdrop element.\n */\n  .directive('modalBackdrop', ['$timeout', function ($timeout) {\n    return {\n      restrict: 'EA',\n      replace: true,\n      templateUrl: 'template/modal/backdrop.html',\n      link: function (scope, element, attrs) {\n        scope.backdropClass = attrs.backdropClass || '';\n\n        scope.animate = false;\n\n        //trigger CSS transitions\n        $timeout(function () {\n          scope.animate = true;\n        });\n      }\n    };\n  }])\n\n  .directive('modalWindow', ['$modalStack', '$timeout', function ($modalStack, $timeout) {\n    return {\n      restrict: 'EA',\n      scope: {\n        index: '@',\n        animate: '='\n      },\n      replace: true,\n      transclude: true,\n      templateUrl: function(tElement, tAttrs) {\n        return tAttrs.templateUrl || 'template/modal/window.html';\n      },\n      link: function (scope, element, attrs) {\n        element.addClass(attrs.windowClass || '');\n        scope.size = attrs.size;\n\n        $timeout(function () {\n          // trigger CSS transitions\n          scope.animate = true;\n\n          /**\n           * Auto-focusing of a freshly-opened modal element causes any child elements\n           * with the autofocus attribute to lose focus. This is an issue on touch\n           * based devices which will show and then hide the onscreen keyboard.\n           * Attempts to refocus the autofocus element via JavaScript will not reopen\n           * the onscreen keyboard. Fixed by updated the focusing logic to only autofocus\n           * the modal element if the modal does not contain an autofocus element.\n           */\n          if (!element[0].querySelectorAll('[autofocus]').length) {\n            element[0].focus();\n          }\n        });\n\n        scope.close = function (evt) {\n          var modal = $modalStack.getTop();\n          if (modal && modal.value.backdrop && modal.value.backdrop != 'static' && (evt.target === evt.currentTarget)) {\n            evt.preventDefault();\n            evt.stopPropagation();\n            $modalStack.dismiss(modal.key, 'backdrop click');\n          }\n        };\n      }\n    };\n  }])\n\n  .directive('modalTransclude', function () {\n    return {\n      link: function($scope, $element, $attrs, controller, $transclude) {\n        $transclude($scope.$parent, function(clone) {\n          $element.empty();\n          $element.append(clone);\n        });\n      }\n    };\n  })\n\n  .factory('$modalStack', ['$transition', '$timeout', '$document', '$compile', '$rootScope', '$$stackedMap',\n    function ($transition, $timeout, $document, $compile, $rootScope, $$stackedMap) {\n\n      var OPENED_MODAL_CLASS = 'modal-open';\n\n      var backdropDomEl, backdropScope;\n      var openedWindows = $$stackedMap.createNew();\n      var $modalStack = {};\n\n      function backdropIndex() {\n        var topBackdropIndex = -1;\n        var opened = openedWindows.keys();\n        for (var i = 0; i < opened.length; i++) {\n          if (openedWindows.get(opened[i]).value.backdrop) {\n            topBackdropIndex = i;\n          }\n        }\n        return topBackdropIndex;\n      }\n\n      $rootScope.$watch(backdropIndex, function(newBackdropIndex){\n        if (backdropScope) {\n          backdropScope.index = newBackdropIndex;\n        }\n      });\n\n      function removeModalWindow(modalInstance) {\n\n        var body = $document.find('body').eq(0);\n        var modalWindow = openedWindows.get(modalInstance).value;\n\n        //clean up the stack\n        openedWindows.remove(modalInstance);\n\n        //remove window DOM element\n        removeAfterAnimate(modalWindow.modalDomEl, modalWindow.modalScope, 300, function() {\n          modalWindow.modalScope.$destroy();\n          body.toggleClass(OPENED_MODAL_CLASS, openedWindows.length() > 0);\n          checkRemoveBackdrop();\n        });\n      }\n\n      function checkRemoveBackdrop() {\n          //remove backdrop if no longer needed\n          if (backdropDomEl && backdropIndex() == -1) {\n            var backdropScopeRef = backdropScope;\n            removeAfterAnimate(backdropDomEl, backdropScope, 150, function () {\n              backdropScopeRef.$destroy();\n              backdropScopeRef = null;\n            });\n            backdropDomEl = undefined;\n            backdropScope = undefined;\n          }\n      }\n\n      function removeAfterAnimate(domEl, scope, emulateTime, done) {\n        // Closing animation\n        scope.animate = false;\n\n        var transitionEndEventName = $transition.transitionEndEventName;\n        if (transitionEndEventName) {\n          // transition out\n          var timeout = $timeout(afterAnimating, emulateTime);\n\n          domEl.bind(transitionEndEventName, function () {\n            $timeout.cancel(timeout);\n            afterAnimating();\n            scope.$apply();\n          });\n        } else {\n          // Ensure this call is async\n          $timeout(afterAnimating);\n        }\n\n        function afterAnimating() {\n          if (afterAnimating.done) {\n            return;\n          }\n          afterAnimating.done = true;\n\n          domEl.remove();\n          if (done) {\n            done();\n          }\n        }\n      }\n\n      $document.bind('keydown', function (evt) {\n        var modal;\n\n        if (evt.which === 27) {\n          modal = openedWindows.top();\n          if (modal && modal.value.keyboard) {\n            evt.preventDefault();\n            $rootScope.$apply(function () {\n              $modalStack.dismiss(modal.key, 'escape key press');\n            });\n          }\n        }\n      });\n\n      $modalStack.open = function (modalInstance, modal) {\n\n        openedWindows.add(modalInstance, {\n          deferred: modal.deferred,\n          modalScope: modal.scope,\n          backdrop: modal.backdrop,\n          keyboard: modal.keyboard\n        });\n\n        var body = $document.find('body').eq(0),\n            currBackdropIndex = backdropIndex();\n\n        if (currBackdropIndex >= 0 && !backdropDomEl) {\n          backdropScope = $rootScope.$new(true);\n          backdropScope.index = currBackdropIndex;\n          var angularBackgroundDomEl = angular.element('<div modal-backdrop></div>');\n          angularBackgroundDomEl.attr('backdrop-class', modal.backdropClass);\n          backdropDomEl = $compile(angularBackgroundDomEl)(backdropScope);\n          body.append(backdropDomEl);\n        }\n\n        var angularDomEl = angular.element('<div modal-window></div>');\n        angularDomEl.attr({\n          'template-url': modal.windowTemplateUrl,\n          'window-class': modal.windowClass,\n          'size': modal.size,\n          'index': openedWindows.length() - 1,\n          'animate': 'animate'\n        }).html(modal.content);\n\n        var modalDomEl = $compile(angularDomEl)(modal.scope);\n        openedWindows.top().value.modalDomEl = modalDomEl;\n        body.append(modalDomEl);\n        body.addClass(OPENED_MODAL_CLASS);\n      };\n\n      $modalStack.close = function (modalInstance, result) {\n        var modalWindow = openedWindows.get(modalInstance);\n        if (modalWindow) {\n          modalWindow.value.deferred.resolve(result);\n          removeModalWindow(modalInstance);\n        }\n      };\n\n      $modalStack.dismiss = function (modalInstance, reason) {\n        var modalWindow = openedWindows.get(modalInstance);\n        if (modalWindow) {\n          modalWindow.value.deferred.reject(reason);\n          removeModalWindow(modalInstance);\n        }\n      };\n\n      $modalStack.dismissAll = function (reason) {\n        var topModal = this.getTop();\n        while (topModal) {\n          this.dismiss(topModal.key, reason);\n          topModal = this.getTop();\n        }\n      };\n\n      $modalStack.getTop = function () {\n        return openedWindows.top();\n      };\n\n      return $modalStack;\n    }])\n\n  .provider('$modal', function () {\n\n    var $modalProvider = {\n      options: {\n        backdrop: true, //can be also false or 'static'\n        keyboard: true\n      },\n      $get: ['$injector', '$rootScope', '$q', '$http', '$templateCache', '$controller', '$modalStack',\n        function ($injector, $rootScope, $q, $http, $templateCache, $controller, $modalStack) {\n\n          var $modal = {};\n\n          function getTemplatePromise(options) {\n            return options.template ? $q.when(options.template) :\n              $http.get(angular.isFunction(options.templateUrl) ? (options.templateUrl)() : options.templateUrl,\n                {cache: $templateCache}).then(function (result) {\n                  return result.data;\n              });\n          }\n\n          function getResolvePromises(resolves) {\n            var promisesArr = [];\n            angular.forEach(resolves, function (value) {\n              if (angular.isFunction(value) || angular.isArray(value)) {\n                promisesArr.push($q.when($injector.invoke(value)));\n              }\n            });\n            return promisesArr;\n          }\n\n          $modal.open = function (modalOptions) {\n\n            var modalResultDeferred = $q.defer();\n            var modalOpenedDeferred = $q.defer();\n\n            //prepare an instance of a modal to be injected into controllers and returned to a caller\n            var modalInstance = {\n              result: modalResultDeferred.promise,\n              opened: modalOpenedDeferred.promise,\n              close: function (result) {\n                $modalStack.close(modalInstance, result);\n              },\n              dismiss: function (reason) {\n                $modalStack.dismiss(modalInstance, reason);\n              }\n            };\n\n            //merge and clean up options\n            modalOptions = angular.extend({}, $modalProvider.options, modalOptions);\n            modalOptions.resolve = modalOptions.resolve || {};\n\n            //verify options\n            if (!modalOptions.template && !modalOptions.templateUrl) {\n              throw new Error('One of template or templateUrl options is required.');\n            }\n\n            var templateAndResolvePromise =\n              $q.all([getTemplatePromise(modalOptions)].concat(getResolvePromises(modalOptions.resolve)));\n\n\n            templateAndResolvePromise.then(function resolveSuccess(tplAndVars) {\n\n              var modalScope = (modalOptions.scope || $rootScope).$new();\n              modalScope.$close = modalInstance.close;\n              modalScope.$dismiss = modalInstance.dismiss;\n\n              var ctrlInstance, ctrlLocals = {};\n              var resolveIter = 1;\n\n              //controllers\n              if (modalOptions.controller) {\n                ctrlLocals.$scope = modalScope;\n                ctrlLocals.$modalInstance = modalInstance;\n                angular.forEach(modalOptions.resolve, function (value, key) {\n                  ctrlLocals[key] = tplAndVars[resolveIter++];\n                });\n\n                ctrlInstance = $controller(modalOptions.controller, ctrlLocals);\n                if (modalOptions.controllerAs) {\n                  modalScope[modalOptions.controllerAs] = ctrlInstance;\n                }\n              }\n\n              $modalStack.open(modalInstance, {\n                scope: modalScope,\n                deferred: modalResultDeferred,\n                content: tplAndVars[0],\n                backdrop: modalOptions.backdrop,\n                keyboard: modalOptions.keyboard,\n                backdropClass: modalOptions.backdropClass,\n                windowClass: modalOptions.windowClass,\n                windowTemplateUrl: modalOptions.windowTemplateUrl,\n                size: modalOptions.size\n              });\n\n            }, function resolveError(reason) {\n              modalResultDeferred.reject(reason);\n            });\n\n            templateAndResolvePromise.then(function () {\n              modalOpenedDeferred.resolve(true);\n            }, function () {\n              modalOpenedDeferred.reject(false);\n            });\n\n            return modalInstance;\n          };\n\n          return $modal;\n        }]\n    };\n\n    return $modalProvider;\n  });\n\nangular.module('ui.bootstrap.pagination', [])\n\n.controller('PaginationController', ['$scope', '$attrs', '$parse', function ($scope, $attrs, $parse) {\n  var self = this,\n      ngModelCtrl = { $setViewValue: angular.noop }, // nullModelCtrl\n      setNumPages = $attrs.numPages ? $parse($attrs.numPages).assign : angular.noop;\n\n  this.init = function(ngModelCtrl_, config) {\n    ngModelCtrl = ngModelCtrl_;\n    this.config = config;\n\n    ngModelCtrl.$render = function() {\n      self.render();\n    };\n\n    if ($attrs.itemsPerPage) {\n      $scope.$parent.$watch($parse($attrs.itemsPerPage), function(value) {\n        self.itemsPerPage = parseInt(value, 10);\n        $scope.totalPages = self.calculateTotalPages();\n      });\n    } else {\n      this.itemsPerPage = config.itemsPerPage;\n    }\n  };\n\n  this.calculateTotalPages = function() {\n    var totalPages = this.itemsPerPage < 1 ? 1 : Math.ceil($scope.totalItems / this.itemsPerPage);\n    return Math.max(totalPages || 0, 1);\n  };\n\n  this.render = function() {\n    $scope.page = parseInt(ngModelCtrl.$viewValue, 10) || 1;\n  };\n\n  $scope.selectPage = function(page) {\n    if ( $scope.page !== page && page > 0 && page <= $scope.totalPages) {\n      ngModelCtrl.$setViewValue(page);\n      ngModelCtrl.$render();\n    }\n  };\n\n  $scope.getText = function( key ) {\n    return $scope[key + 'Text'] || self.config[key + 'Text'];\n  };\n  $scope.noPrevious = function() {\n    return $scope.page === 1;\n  };\n  $scope.noNext = function() {\n    return $scope.page === $scope.totalPages;\n  };\n\n  $scope.$watch('totalItems', function() {\n    $scope.totalPages = self.calculateTotalPages();\n  });\n\n  $scope.$watch('totalPages', function(value) {\n    setNumPages($scope.$parent, value); // Readonly variable\n\n    if ( $scope.page > value ) {\n      $scope.selectPage(value);\n    } else {\n      ngModelCtrl.$render();\n    }\n  });\n}])\n\n.constant('paginationConfig', {\n  itemsPerPage: 10,\n  boundaryLinks: false,\n  directionLinks: true,\n  firstText: 'First',\n  previousText: 'Previous',\n  nextText: 'Next',\n  lastText: 'Last',\n  rotate: true\n})\n\n.directive('pagination', ['$parse', 'paginationConfig', function($parse, paginationConfig) {\n  return {\n    restrict: 'EA',\n    scope: {\n      totalItems: '=',\n      firstText: '@',\n      previousText: '@',\n      nextText: '@',\n      lastText: '@'\n    },\n    require: ['pagination', '?ngModel'],\n    controller: 'PaginationController',\n    templateUrl: 'template/pagination/pagination.html',\n    replace: true,\n    link: function(scope, element, attrs, ctrls) {\n      var paginationCtrl = ctrls[0], ngModelCtrl = ctrls[1];\n\n      if (!ngModelCtrl) {\n         return; // do nothing if no ng-model\n      }\n\n      // Setup configuration parameters\n      var maxSize = angular.isDefined(attrs.maxSize) ? scope.$parent.$eval(attrs.maxSize) : paginationConfig.maxSize,\n          rotate = angular.isDefined(attrs.rotate) ? scope.$parent.$eval(attrs.rotate) : paginationConfig.rotate;\n      scope.boundaryLinks = angular.isDefined(attrs.boundaryLinks) ? scope.$parent.$eval(attrs.boundaryLinks) : paginationConfig.boundaryLinks;\n      scope.directionLinks = angular.isDefined(attrs.directionLinks) ? scope.$parent.$eval(attrs.directionLinks) : paginationConfig.directionLinks;\n\n      paginationCtrl.init(ngModelCtrl, paginationConfig);\n\n      if (attrs.maxSize) {\n        scope.$parent.$watch($parse(attrs.maxSize), function(value) {\n          maxSize = parseInt(value, 10);\n          paginationCtrl.render();\n        });\n      }\n\n      // Create page object used in template\n      function makePage(number, text, isActive) {\n        return {\n          number: number,\n          text: text,\n          active: isActive\n        };\n      }\n\n      function getPages(currentPage, totalPages) {\n        var pages = [];\n\n        // Default page limits\n        var startPage = 1, endPage = totalPages;\n        var isMaxSized = ( angular.isDefined(maxSize) && maxSize < totalPages );\n\n        // recompute if maxSize\n        if ( isMaxSized ) {\n          if ( rotate ) {\n            // Current page is displayed in the middle of the visible ones\n            startPage = Math.max(currentPage - Math.floor(maxSize/2), 1);\n            endPage   = startPage + maxSize - 1;\n\n            // Adjust if limit is exceeded\n            if (endPage > totalPages) {\n              endPage   = totalPages;\n              startPage = endPage - maxSize + 1;\n            }\n          } else {\n            // Visible pages are paginated with maxSize\n            startPage = ((Math.ceil(currentPage / maxSize) - 1) * maxSize) + 1;\n\n            // Adjust last page if limit is exceeded\n            endPage = Math.min(startPage + maxSize - 1, totalPages);\n          }\n        }\n\n        // Add page number links\n        for (var number = startPage; number <= endPage; number++) {\n          var page = makePage(number, number, number === currentPage);\n          pages.push(page);\n        }\n\n        // Add links to move between page sets\n        if ( isMaxSized && ! rotate ) {\n          if ( startPage > 1 ) {\n            var previousPageSet = makePage(startPage - 1, '...', false);\n            pages.unshift(previousPageSet);\n          }\n\n          if ( endPage < totalPages ) {\n            var nextPageSet = makePage(endPage + 1, '...', false);\n            pages.push(nextPageSet);\n          }\n        }\n\n        return pages;\n      }\n\n      var originalRender = paginationCtrl.render;\n      paginationCtrl.render = function() {\n        originalRender();\n        if (scope.page > 0 && scope.page <= scope.totalPages) {\n          scope.pages = getPages(scope.page, scope.totalPages);\n        }\n      };\n    }\n  };\n}])\n\n.constant('pagerConfig', {\n  itemsPerPage: 10,\n  previousText: '« Previous',\n  nextText: 'Next »',\n  align: true\n})\n\n.directive('pager', ['pagerConfig', function(pagerConfig) {\n  return {\n    restrict: 'EA',\n    scope: {\n      totalItems: '=',\n      previousText: '@',\n      nextText: '@'\n    },\n    require: ['pager', '?ngModel'],\n    controller: 'PaginationController',\n    templateUrl: 'template/pagination/pager.html',\n    replace: true,\n    link: function(scope, element, attrs, ctrls) {\n      var paginationCtrl = ctrls[0], ngModelCtrl = ctrls[1];\n\n      if (!ngModelCtrl) {\n         return; // do nothing if no ng-model\n      }\n\n      scope.align = angular.isDefined(attrs.align) ? scope.$parent.$eval(attrs.align) : pagerConfig.align;\n      paginationCtrl.init(ngModelCtrl, pagerConfig);\n    }\n  };\n}]);\n\n/**\n * The following features are still outstanding: animation as a\n * function, placement as a function, inside, support for more triggers than\n * just mouse enter/leave, html tooltips, and selector delegation.\n */\nangular.module( 'ui.bootstrap.tooltip', [ 'ui.bootstrap.position', 'ui.bootstrap.bindHtml' ] )\n\n/**\n * The $tooltip service creates tooltip- and popover-like directives as well as\n * houses global options for them.\n */\n.provider( '$tooltip', function () {\n  // The default options tooltip and popover.\n  var defaultOptions = {\n    placement: 'top',\n    animation: true,\n    popupDelay: 0\n  };\n\n  // Default hide triggers for each show trigger\n  var triggerMap = {\n    'mouseenter': 'mouseleave',\n    'click': 'click',\n    'focus': 'blur'\n  };\n\n  // The options specified to the provider globally.\n  var globalOptions = {};\n\n  /**\n   * `options({})` allows global configuration of all tooltips in the\n   * application.\n   *\n   *   var app = angular.module( 'App', ['ui.bootstrap.tooltip'], function( $tooltipProvider ) {\n   *     // place tooltips left instead of top by default\n   *     $tooltipProvider.options( { placement: 'left' } );\n   *   });\n   */\n\tthis.options = function( value ) {\n\t\tangular.extend( globalOptions, value );\n\t};\n\n  /**\n   * This allows you to extend the set of trigger mappings available. E.g.:\n   *\n   *   $tooltipProvider.setTriggers( 'openTrigger': 'closeTrigger' );\n   */\n  this.setTriggers = function setTriggers ( triggers ) {\n    angular.extend( triggerMap, triggers );\n  };\n\n  /**\n   * This is a helper function for translating camel-case to snake-case.\n   */\n  function snake_case(name){\n    var regexp = /[A-Z]/g;\n    var separator = '-';\n    return name.replace(regexp, function(letter, pos) {\n      return (pos ? separator : '') + letter.toLowerCase();\n    });\n  }\n\n  /**\n   * Returns the actual instance of the $tooltip service.\n   * TODO support multiple triggers\n   */\n  this.$get = [ '$window', '$compile', '$timeout', '$document', '$position', '$interpolate', function ( $window, $compile, $timeout, $document, $position, $interpolate ) {\n    return function $tooltip ( type, prefix, defaultTriggerShow ) {\n      var options = angular.extend( {}, defaultOptions, globalOptions );\n\n      /**\n       * Returns an object of show and hide triggers.\n       *\n       * If a trigger is supplied,\n       * it is used to show the tooltip; otherwise, it will use the `trigger`\n       * option passed to the `$tooltipProvider.options` method; else it will\n       * default to the trigger supplied to this directive factory.\n       *\n       * The hide trigger is based on the show trigger. If the `trigger` option\n       * was passed to the `$tooltipProvider.options` method, it will use the\n       * mapped trigger from `triggerMap` or the passed trigger if the map is\n       * undefined; otherwise, it uses the `triggerMap` value of the show\n       * trigger; else it will just use the show trigger.\n       */\n      function getTriggers ( trigger ) {\n        var show = trigger || options.trigger || defaultTriggerShow;\n        var hide = triggerMap[show] || show;\n        return {\n          show: show,\n          hide: hide\n        };\n      }\n\n      var directiveName = snake_case( type );\n\n      var startSym = $interpolate.startSymbol();\n      var endSym = $interpolate.endSymbol();\n      var template =\n        '<div '+ directiveName +'-popup '+\n          'title=\"'+startSym+'title'+endSym+'\" '+\n          'content=\"'+startSym+'content'+endSym+'\" '+\n          'placement=\"'+startSym+'placement'+endSym+'\" '+\n          'animation=\"animation\" '+\n          'is-open=\"isOpen\"'+\n          '>'+\n        '</div>';\n\n      return {\n        restrict: 'EA',\n        compile: function (tElem, tAttrs) {\n          var tooltipLinker = $compile( template );\n\n          return function link ( scope, element, attrs ) {\n            var tooltip;\n            var tooltipLinkedScope;\n            var transitionTimeout;\n            var popupTimeout;\n            var appendToBody = angular.isDefined( options.appendToBody ) ? options.appendToBody : false;\n            var triggers = getTriggers( undefined );\n            var hasEnableExp = angular.isDefined(attrs[prefix+'Enable']);\n            var ttScope = scope.$new(true);\n\n            var positionTooltip = function () {\n\n              var ttPosition = $position.positionElements(element, tooltip, ttScope.placement, appendToBody);\n              ttPosition.top += 'px';\n              ttPosition.left += 'px';\n\n              // Now set the calculated positioning.\n              tooltip.css( ttPosition );\n            };\n\n            // By default, the tooltip is not open.\n            // TODO add ability to start tooltip opened\n            ttScope.isOpen = false;\n\n            function toggleTooltipBind () {\n              if ( ! ttScope.isOpen ) {\n                showTooltipBind();\n              } else {\n                hideTooltipBind();\n              }\n            }\n\n            // Show the tooltip with delay if specified, otherwise show it immediately\n            function showTooltipBind() {\n              if(hasEnableExp && !scope.$eval(attrs[prefix+'Enable'])) {\n                return;\n              }\n\n              prepareTooltip();\n\n              if ( ttScope.popupDelay ) {\n                // Do nothing if the tooltip was already scheduled to pop-up.\n                // This happens if show is triggered multiple times before any hide is triggered.\n                if (!popupTimeout) {\n                  popupTimeout = $timeout( show, ttScope.popupDelay, false );\n                  popupTimeout.then(function(reposition){reposition();});\n                }\n              } else {\n                show()();\n              }\n            }\n\n            function hideTooltipBind () {\n              scope.$apply(function () {\n                hide();\n              });\n            }\n\n            // Show the tooltip popup element.\n            function show() {\n\n              popupTimeout = null;\n\n              // If there is a pending remove transition, we must cancel it, lest the\n              // tooltip be mysteriously removed.\n              if ( transitionTimeout ) {\n                $timeout.cancel( transitionTimeout );\n                transitionTimeout = null;\n              }\n\n              // Don't show empty tooltips.\n              if ( ! ttScope.content ) {\n                return angular.noop;\n              }\n\n              createTooltip();\n\n              // Set the initial positioning.\n              tooltip.css({ top: 0, left: 0, display: 'block' });\n\n              // Now we add it to the DOM because need some info about it. But it's not\n              // visible yet anyway.\n              if ( appendToBody ) {\n                  $document.find( 'body' ).append( tooltip );\n              } else {\n                element.after( tooltip );\n              }\n\n              positionTooltip();\n\n              // And show the tooltip.\n              ttScope.isOpen = true;\n              ttScope.$digest(); // digest required as $apply is not called\n\n              // Return positioning function as promise callback for correct\n              // positioning after draw.\n              return positionTooltip;\n            }\n\n            // Hide the tooltip popup element.\n            function hide() {\n              // First things first: we don't show it anymore.\n              ttScope.isOpen = false;\n\n              //if tooltip is going to be shown after delay, we must cancel this\n              $timeout.cancel( popupTimeout );\n              popupTimeout = null;\n\n              // And now we remove it from the DOM. However, if we have animation, we\n              // need to wait for it to expire beforehand.\n              // FIXME: this is a placeholder for a port of the transitions library.\n              if ( ttScope.animation ) {\n                if (!transitionTimeout) {\n                  transitionTimeout = $timeout(removeTooltip, 500);\n                }\n              } else {\n                removeTooltip();\n              }\n            }\n\n            function createTooltip() {\n              // There can only be one tooltip element per directive shown at once.\n              if (tooltip) {\n                removeTooltip();\n              }\n              tooltipLinkedScope = ttScope.$new();\n              tooltip = tooltipLinker(tooltipLinkedScope, angular.noop);\n            }\n\n            function removeTooltip() {\n              transitionTimeout = null;\n              if (tooltip) {\n                tooltip.remove();\n                tooltip = null;\n              }\n              if (tooltipLinkedScope) {\n                tooltipLinkedScope.$destroy();\n                tooltipLinkedScope = null;\n              }\n            }\n\n            function prepareTooltip() {\n              prepPlacement();\n              prepPopupDelay();\n            }\n\n            /**\n             * Observe the relevant attributes.\n             */\n            attrs.$observe( type, function ( val ) {\n              ttScope.content = val;\n\n              if (!val && ttScope.isOpen ) {\n                hide();\n              }\n            });\n\n            attrs.$observe( prefix+'Title', function ( val ) {\n              ttScope.title = val;\n            });\n\n            function prepPlacement() {\n              var val = attrs[ prefix + 'Placement' ];\n              ttScope.placement = angular.isDefined( val ) ? val : options.placement;\n            }\n\n            function prepPopupDelay() {\n              var val = attrs[ prefix + 'PopupDelay' ];\n              var delay = parseInt( val, 10 );\n              ttScope.popupDelay = ! isNaN(delay) ? delay : options.popupDelay;\n            }\n\n            var unregisterTriggers = function () {\n              element.unbind(triggers.show, showTooltipBind);\n              element.unbind(triggers.hide, hideTooltipBind);\n            };\n\n            function prepTriggers() {\n              var val = attrs[ prefix + 'Trigger' ];\n              unregisterTriggers();\n\n              triggers = getTriggers( val );\n\n              if ( triggers.show === triggers.hide ) {\n                element.bind( triggers.show, toggleTooltipBind );\n              } else {\n                element.bind( triggers.show, showTooltipBind );\n                element.bind( triggers.hide, hideTooltipBind );\n              }\n            }\n            prepTriggers();\n\n            var animation = scope.$eval(attrs[prefix + 'Animation']);\n            ttScope.animation = angular.isDefined(animation) ? !!animation : options.animation;\n\n            var appendToBodyVal = scope.$eval(attrs[prefix + 'AppendToBody']);\n            appendToBody = angular.isDefined(appendToBodyVal) ? appendToBodyVal : appendToBody;\n\n            // if a tooltip is attached to <body> we need to remove it on\n            // location change as its parent scope will probably not be destroyed\n            // by the change.\n            if ( appendToBody ) {\n              scope.$on('$locationChangeSuccess', function closeTooltipOnLocationChangeSuccess () {\n              if ( ttScope.isOpen ) {\n                hide();\n              }\n            });\n            }\n\n            // Make sure tooltip is destroyed and removed.\n            scope.$on('$destroy', function onDestroyTooltip() {\n              $timeout.cancel( transitionTimeout );\n              $timeout.cancel( popupTimeout );\n              unregisterTriggers();\n              removeTooltip();\n              ttScope = null;\n            });\n          };\n        }\n      };\n    };\n  }];\n})\n\n.directive( 'tooltipPopup', function () {\n  return {\n    restrict: 'EA',\n    replace: true,\n    scope: { content: '@', placement: '@', animation: '&', isOpen: '&' },\n    templateUrl: 'template/tooltip/tooltip-popup.html'\n  };\n})\n\n.directive( 'tooltip', [ '$tooltip', function ( $tooltip ) {\n  return $tooltip( 'tooltip', 'tooltip', 'mouseenter' );\n}])\n\n.directive( 'tooltipHtmlUnsafePopup', function () {\n  return {\n    restrict: 'EA',\n    replace: true,\n    scope: { content: '@', placement: '@', animation: '&', isOpen: '&' },\n    templateUrl: 'template/tooltip/tooltip-html-unsafe-popup.html'\n  };\n})\n\n.directive( 'tooltipHtmlUnsafe', [ '$tooltip', function ( $tooltip ) {\n  return $tooltip( 'tooltipHtmlUnsafe', 'tooltip', 'mouseenter' );\n}]);\n\n/**\n * The following features are still outstanding: popup delay, animation as a\n * function, placement as a function, inside, support for more triggers than\n * just mouse enter/leave, html popovers, and selector delegatation.\n */\nangular.module( 'ui.bootstrap.popover', [ 'ui.bootstrap.tooltip' ] )\n\n.directive( 'popoverPopup', function () {\n  return {\n    restrict: 'EA',\n    replace: true,\n    scope: { title: '@', content: '@', placement: '@', animation: '&', isOpen: '&' },\n    templateUrl: 'template/popover/popover.html'\n  };\n})\n\n.directive( 'popover', [ '$tooltip', function ( $tooltip ) {\n  return $tooltip( 'popover', 'popover', 'click' );\n}]);\n\nangular.module('ui.bootstrap.progressbar', [])\n\n.constant('progressConfig', {\n  animate: true,\n  max: 100\n})\n\n.controller('ProgressController', ['$scope', '$attrs', 'progressConfig', function($scope, $attrs, progressConfig) {\n    var self = this,\n        animate = angular.isDefined($attrs.animate) ? $scope.$parent.$eval($attrs.animate) : progressConfig.animate;\n\n    this.bars = [];\n    $scope.max = angular.isDefined($attrs.max) ? $scope.$parent.$eval($attrs.max) : progressConfig.max;\n\n    this.addBar = function(bar, element) {\n        if ( !animate ) {\n            element.css({'transition': 'none'});\n        }\n\n        this.bars.push(bar);\n\n        bar.$watch('value', function( value ) {\n            bar.percent = +(100 * value / $scope.max).toFixed(2);\n        });\n\n        bar.$on('$destroy', function() {\n            element = null;\n            self.removeBar(bar);\n        });\n    };\n\n    this.removeBar = function(bar) {\n        this.bars.splice(this.bars.indexOf(bar), 1);\n    };\n}])\n\n.directive('progress', function() {\n    return {\n        restrict: 'EA',\n        replace: true,\n        transclude: true,\n        controller: 'ProgressController',\n        require: 'progress',\n        scope: {},\n        templateUrl: 'template/progressbar/progress.html'\n    };\n})\n\n.directive('bar', function() {\n    return {\n        restrict: 'EA',\n        replace: true,\n        transclude: true,\n        require: '^progress',\n        scope: {\n            value: '=',\n            type: '@'\n        },\n        templateUrl: 'template/progressbar/bar.html',\n        link: function(scope, element, attrs, progressCtrl) {\n            progressCtrl.addBar(scope, element);\n        }\n    };\n})\n\n.directive('progressbar', function() {\n    return {\n        restrict: 'EA',\n        replace: true,\n        transclude: true,\n        controller: 'ProgressController',\n        scope: {\n            value: '=',\n            type: '@'\n        },\n        templateUrl: 'template/progressbar/progressbar.html',\n        link: function(scope, element, attrs, progressCtrl) {\n            progressCtrl.addBar(scope, angular.element(element.children()[0]));\n        }\n    };\n});\nangular.module('ui.bootstrap.rating', [])\n\n.constant('ratingConfig', {\n  max: 5,\n  stateOn: null,\n  stateOff: null\n})\n\n.controller('RatingController', ['$scope', '$attrs', 'ratingConfig', function($scope, $attrs, ratingConfig) {\n  var ngModelCtrl  = { $setViewValue: angular.noop };\n\n  this.init = function(ngModelCtrl_) {\n    ngModelCtrl = ngModelCtrl_;\n    ngModelCtrl.$render = this.render;\n\n    this.stateOn = angular.isDefined($attrs.stateOn) ? $scope.$parent.$eval($attrs.stateOn) : ratingConfig.stateOn;\n    this.stateOff = angular.isDefined($attrs.stateOff) ? $scope.$parent.$eval($attrs.stateOff) : ratingConfig.stateOff;\n\n    var ratingStates = angular.isDefined($attrs.ratingStates) ? $scope.$parent.$eval($attrs.ratingStates) :\n                        new Array( angular.isDefined($attrs.max) ? $scope.$parent.$eval($attrs.max) : ratingConfig.max );\n    $scope.range = this.buildTemplateObjects(ratingStates);\n  };\n\n  this.buildTemplateObjects = function(states) {\n    for (var i = 0, n = states.length; i < n; i++) {\n      states[i] = angular.extend({ index: i }, { stateOn: this.stateOn, stateOff: this.stateOff }, states[i]);\n    }\n    return states;\n  };\n\n  $scope.rate = function(value) {\n    if ( !$scope.readonly && value >= 0 && value <= $scope.range.length ) {\n      ngModelCtrl.$setViewValue(value);\n      ngModelCtrl.$render();\n    }\n  };\n\n  $scope.enter = function(value) {\n    if ( !$scope.readonly ) {\n      $scope.value = value;\n    }\n    $scope.onHover({value: value});\n  };\n\n  $scope.reset = function() {\n    $scope.value = ngModelCtrl.$viewValue;\n    $scope.onLeave();\n  };\n\n  $scope.onKeydown = function(evt) {\n    if (/(37|38|39|40)/.test(evt.which)) {\n      evt.preventDefault();\n      evt.stopPropagation();\n      $scope.rate( $scope.value + (evt.which === 38 || evt.which === 39 ? 1 : -1) );\n    }\n  };\n\n  this.render = function() {\n    $scope.value = ngModelCtrl.$viewValue;\n  };\n}])\n\n.directive('rating', function() {\n  return {\n    restrict: 'EA',\n    require: ['rating', 'ngModel'],\n    scope: {\n      readonly: '=?',\n      onHover: '&',\n      onLeave: '&'\n    },\n    controller: 'RatingController',\n    templateUrl: 'template/rating/rating.html',\n    replace: true,\n    link: function(scope, element, attrs, ctrls) {\n      var ratingCtrl = ctrls[0], ngModelCtrl = ctrls[1];\n\n      if ( ngModelCtrl ) {\n        ratingCtrl.init( ngModelCtrl );\n      }\n    }\n  };\n});\n\n/**\n * @ngdoc overview\n * @name ui.bootstrap.tabs\n *\n * @description\n * AngularJS version of the tabs directive.\n */\n\nangular.module('ui.bootstrap.tabs', [])\n\n.controller('TabsetController', ['$scope', function TabsetCtrl($scope) {\n  var ctrl = this,\n      tabs = ctrl.tabs = $scope.tabs = [];\n\n  ctrl.select = function(selectedTab) {\n    angular.forEach(tabs, function(tab) {\n      if (tab.active && tab !== selectedTab) {\n        tab.active = false;\n        tab.onDeselect();\n      }\n    });\n    selectedTab.active = true;\n    selectedTab.onSelect();\n  };\n\n  ctrl.addTab = function addTab(tab) {\n    tabs.push(tab);\n    // we can't run the select function on the first tab\n    // since that would select it twice\n    if (tabs.length === 1) {\n      tab.active = true;\n    } else if (tab.active) {\n      ctrl.select(tab);\n    }\n  };\n\n  ctrl.removeTab = function removeTab(tab) {\n    var index = tabs.indexOf(tab);\n    //Select a new tab if the tab to be removed is selected and not destroyed\n    if (tab.active && tabs.length > 1 && !destroyed) {\n      //If this is the last tab, select the previous tab. else, the next tab.\n      var newActiveIndex = index == tabs.length - 1 ? index - 1 : index + 1;\n      ctrl.select(tabs[newActiveIndex]);\n    }\n    tabs.splice(index, 1);\n  };\n\n  var destroyed;\n  $scope.$on('$destroy', function() {\n    destroyed = true;\n  });\n}])\n\n/**\n * @ngdoc directive\n * @name ui.bootstrap.tabs.directive:tabset\n * @restrict EA\n *\n * @description\n * Tabset is the outer container for the tabs directive\n *\n * @param {boolean=} vertical Whether or not to use vertical styling for the tabs.\n * @param {boolean=} justified Whether or not to use justified styling for the tabs.\n *\n * @example\n<example module=\"ui.bootstrap\">\n  <file name=\"index.html\">\n    <tabset>\n      <tab heading=\"Tab 1\"><b>First</b> Content!</tab>\n      <tab heading=\"Tab 2\"><i>Second</i> Content!</tab>\n    </tabset>\n    <hr />\n    <tabset vertical=\"true\">\n      <tab heading=\"Vertical Tab 1\"><b>First</b> Vertical Content!</tab>\n      <tab heading=\"Vertical Tab 2\"><i>Second</i> Vertical Content!</tab>\n    </tabset>\n    <tabset justified=\"true\">\n      <tab heading=\"Justified Tab 1\"><b>First</b> Justified Content!</tab>\n      <tab heading=\"Justified Tab 2\"><i>Second</i> Justified Content!</tab>\n    </tabset>\n  </file>\n</example>\n */\n.directive('tabset', function() {\n  return {\n    restrict: 'EA',\n    transclude: true,\n    replace: true,\n    scope: {\n      type: '@'\n    },\n    controller: 'TabsetController',\n    templateUrl: 'template/tabs/tabset.html',\n    link: function(scope, element, attrs) {\n      scope.vertical = angular.isDefined(attrs.vertical) ? scope.$parent.$eval(attrs.vertical) : false;\n      scope.justified = angular.isDefined(attrs.justified) ? scope.$parent.$eval(attrs.justified) : false;\n    }\n  };\n})\n\n/**\n * @ngdoc directive\n * @name ui.bootstrap.tabs.directive:tab\n * @restrict EA\n *\n * @param {string=} heading The visible heading, or title, of the tab. Set HTML headings with {@link ui.bootstrap.tabs.directive:tabHeading tabHeading}.\n * @param {string=} select An expression to evaluate when the tab is selected.\n * @param {boolean=} active A binding, telling whether or not this tab is selected.\n * @param {boolean=} disabled A binding, telling whether or not this tab is disabled.\n *\n * @description\n * Creates a tab with a heading and content. Must be placed within a {@link ui.bootstrap.tabs.directive:tabset tabset}.\n *\n * @example\n<example module=\"ui.bootstrap\">\n  <file name=\"index.html\">\n    <div ng-controller=\"TabsDemoCtrl\">\n      <button class=\"btn btn-small\" ng-click=\"items[0].active = true\">\n        Select item 1, using active binding\n      </button>\n      <button class=\"btn btn-small\" ng-click=\"items[1].disabled = !items[1].disabled\">\n        Enable/disable item 2, using disabled binding\n      </button>\n      <br />\n      <tabset>\n        <tab heading=\"Tab 1\">First Tab</tab>\n        <tab select=\"alertMe()\">\n          <tab-heading><i class=\"icon-bell\"></i> Alert me!</tab-heading>\n          Second Tab, with alert callback and html heading!\n        </tab>\n        <tab ng-repeat=\"item in items\"\n          heading=\"{{item.title}}\"\n          disabled=\"item.disabled\"\n          active=\"item.active\">\n          {{item.content}}\n        </tab>\n      </tabset>\n    </div>\n  </file>\n  <file name=\"script.js\">\n    function TabsDemoCtrl($scope) {\n      $scope.items = [\n        { title:\"Dynamic Title 1\", content:\"Dynamic Item 0\" },\n        { title:\"Dynamic Title 2\", content:\"Dynamic Item 1\", disabled: true }\n      ];\n\n      $scope.alertMe = function() {\n        setTimeout(function() {\n          alert(\"You've selected the alert tab!\");\n        });\n      };\n    };\n  </file>\n</example>\n */\n\n/**\n * @ngdoc directive\n * @name ui.bootstrap.tabs.directive:tabHeading\n * @restrict EA\n *\n * @description\n * Creates an HTML heading for a {@link ui.bootstrap.tabs.directive:tab tab}. Must be placed as a child of a tab element.\n *\n * @example\n<example module=\"ui.bootstrap\">\n  <file name=\"index.html\">\n    <tabset>\n      <tab>\n        <tab-heading><b>HTML</b> in my titles?!</tab-heading>\n        And some content, too!\n      </tab>\n      <tab>\n        <tab-heading><i class=\"icon-heart\"></i> Icon heading?!?</tab-heading>\n        That's right.\n      </tab>\n    </tabset>\n  </file>\n</example>\n */\n.directive('tab', ['$parse', function($parse) {\n  return {\n    require: '^tabset',\n    restrict: 'EA',\n    replace: true,\n    templateUrl: 'template/tabs/tab.html',\n    transclude: true,\n    scope: {\n      active: '=?',\n      heading: '@',\n      onSelect: '&select', //This callback is called in contentHeadingTransclude\n                          //once it inserts the tab's content into the dom\n      onDeselect: '&deselect'\n    },\n    controller: function() {\n      //Empty controller so other directives can require being 'under' a tab\n    },\n    compile: function(elm, attrs, transclude) {\n      return function postLink(scope, elm, attrs, tabsetCtrl) {\n        scope.$watch('active', function(active) {\n          if (active) {\n            tabsetCtrl.select(scope);\n          }\n        });\n\n        scope.disabled = false;\n        if ( attrs.disabled ) {\n          scope.$parent.$watch($parse(attrs.disabled), function(value) {\n            scope.disabled = !! value;\n          });\n        }\n\n        scope.select = function() {\n          if ( !scope.disabled ) {\n            scope.active = true;\n          }\n        };\n\n        tabsetCtrl.addTab(scope);\n        scope.$on('$destroy', function() {\n          tabsetCtrl.removeTab(scope);\n        });\n\n        //We need to transclude later, once the content container is ready.\n        //when this link happens, we're inside a tab heading.\n        scope.$transcludeFn = transclude;\n      };\n    }\n  };\n}])\n\n.directive('tabHeadingTransclude', [function() {\n  return {\n    restrict: 'A',\n    require: '^tab',\n    link: function(scope, elm, attrs, tabCtrl) {\n      scope.$watch('headingElement', function updateHeadingElement(heading) {\n        if (heading) {\n          elm.html('');\n          elm.append(heading);\n        }\n      });\n    }\n  };\n}])\n\n.directive('tabContentTransclude', function() {\n  return {\n    restrict: 'A',\n    require: '^tabset',\n    link: function(scope, elm, attrs) {\n      var tab = scope.$eval(attrs.tabContentTransclude);\n\n      //Now our tab is ready to be transcluded: both the tab heading area\n      //and the tab content area are loaded.  Transclude 'em both.\n      tab.$transcludeFn(tab.$parent, function(contents) {\n        angular.forEach(contents, function(node) {\n          if (isTabHeading(node)) {\n            //Let tabHeadingTransclude know.\n            tab.headingElement = node;\n          } else {\n            elm.append(node);\n          }\n        });\n      });\n    }\n  };\n  function isTabHeading(node) {\n    return node.tagName &&  (\n      node.hasAttribute('tab-heading') ||\n      node.hasAttribute('data-tab-heading') ||\n      node.tagName.toLowerCase() === 'tab-heading' ||\n      node.tagName.toLowerCase() === 'data-tab-heading'\n    );\n  }\n})\n\n;\n\nangular.module('ui.bootstrap.timepicker', [])\n\n.constant('timepickerConfig', {\n  hourStep: 1,\n  minuteStep: 1,\n  showMeridian: true,\n  meridians: null,\n  readonlyInput: false,\n  mousewheel: true\n})\n\n.controller('TimepickerController', ['$scope', '$attrs', '$parse', '$log', '$locale', 'timepickerConfig', function($scope, $attrs, $parse, $log, $locale, timepickerConfig) {\n  var selected = new Date(),\n      ngModelCtrl = { $setViewValue: angular.noop }, // nullModelCtrl\n      meridians = angular.isDefined($attrs.meridians) ? $scope.$parent.$eval($attrs.meridians) : timepickerConfig.meridians || $locale.DATETIME_FORMATS.AMPMS;\n\n  this.init = function( ngModelCtrl_, inputs ) {\n    ngModelCtrl = ngModelCtrl_;\n    ngModelCtrl.$render = this.render;\n\n    var hoursInputEl = inputs.eq(0),\n        minutesInputEl = inputs.eq(1);\n\n    var mousewheel = angular.isDefined($attrs.mousewheel) ? $scope.$parent.$eval($attrs.mousewheel) : timepickerConfig.mousewheel;\n    if ( mousewheel ) {\n      this.setupMousewheelEvents( hoursInputEl, minutesInputEl );\n    }\n\n    $scope.readonlyInput = angular.isDefined($attrs.readonlyInput) ? $scope.$parent.$eval($attrs.readonlyInput) : timepickerConfig.readonlyInput;\n    this.setupInputEvents( hoursInputEl, minutesInputEl );\n  };\n\n  var hourStep = timepickerConfig.hourStep;\n  if ($attrs.hourStep) {\n    $scope.$parent.$watch($parse($attrs.hourStep), function(value) {\n      hourStep = parseInt(value, 10);\n    });\n  }\n\n  var minuteStep = timepickerConfig.minuteStep;\n  if ($attrs.minuteStep) {\n    $scope.$parent.$watch($parse($attrs.minuteStep), function(value) {\n      minuteStep = parseInt(value, 10);\n    });\n  }\n\n  // 12H / 24H mode\n  $scope.showMeridian = timepickerConfig.showMeridian;\n  if ($attrs.showMeridian) {\n    $scope.$parent.$watch($parse($attrs.showMeridian), function(value) {\n      $scope.showMeridian = !!value;\n\n      if ( ngModelCtrl.$error.time ) {\n        // Evaluate from template\n        var hours = getHoursFromTemplate(), minutes = getMinutesFromTemplate();\n        if (angular.isDefined( hours ) && angular.isDefined( minutes )) {\n          selected.setHours( hours );\n          refresh();\n        }\n      } else {\n        updateTemplate();\n      }\n    });\n  }\n\n  // Get $scope.hours in 24H mode if valid\n  function getHoursFromTemplate ( ) {\n    var hours = parseInt( $scope.hours, 10 );\n    var valid = ( $scope.showMeridian ) ? (hours > 0 && hours < 13) : (hours >= 0 && hours < 24);\n    if ( !valid ) {\n      return undefined;\n    }\n\n    if ( $scope.showMeridian ) {\n      if ( hours === 12 ) {\n        hours = 0;\n      }\n      if ( $scope.meridian === meridians[1] ) {\n        hours = hours + 12;\n      }\n    }\n    return hours;\n  }\n\n  function getMinutesFromTemplate() {\n    var minutes = parseInt($scope.minutes, 10);\n    return ( minutes >= 0 && minutes < 60 ) ? minutes : undefined;\n  }\n\n  function pad( value ) {\n    return ( angular.isDefined(value) && value.toString().length < 2 ) ? '0' + value : value;\n  }\n\n  // Respond on mousewheel spin\n  this.setupMousewheelEvents = function( hoursInputEl, minutesInputEl ) {\n    var isScrollingUp = function(e) {\n      if (e.originalEvent) {\n        e = e.originalEvent;\n      }\n      //pick correct delta variable depending on event\n      var delta = (e.wheelDelta) ? e.wheelDelta : -e.deltaY;\n      return (e.detail || delta > 0);\n    };\n\n    hoursInputEl.bind('mousewheel wheel', function(e) {\n      $scope.$apply( (isScrollingUp(e)) ? $scope.incrementHours() : $scope.decrementHours() );\n      e.preventDefault();\n    });\n\n    minutesInputEl.bind('mousewheel wheel', function(e) {\n      $scope.$apply( (isScrollingUp(e)) ? $scope.incrementMinutes() : $scope.decrementMinutes() );\n      e.preventDefault();\n    });\n\n  };\n\n  this.setupInputEvents = function( hoursInputEl, minutesInputEl ) {\n    if ( $scope.readonlyInput ) {\n      $scope.updateHours = angular.noop;\n      $scope.updateMinutes = angular.noop;\n      return;\n    }\n\n    var invalidate = function(invalidHours, invalidMinutes) {\n      ngModelCtrl.$setViewValue( null );\n      ngModelCtrl.$setValidity('time', false);\n      if (angular.isDefined(invalidHours)) {\n        $scope.invalidHours = invalidHours;\n      }\n      if (angular.isDefined(invalidMinutes)) {\n        $scope.invalidMinutes = invalidMinutes;\n      }\n    };\n\n    $scope.updateHours = function() {\n      var hours = getHoursFromTemplate();\n\n      if ( angular.isDefined(hours) ) {\n        selected.setHours( hours );\n        refresh( 'h' );\n      } else {\n        invalidate(true);\n      }\n    };\n\n    hoursInputEl.bind('blur', function(e) {\n      if ( !$scope.invalidHours && $scope.hours < 10) {\n        $scope.$apply( function() {\n          $scope.hours = pad( $scope.hours );\n        });\n      }\n    });\n\n    $scope.updateMinutes = function() {\n      var minutes = getMinutesFromTemplate();\n\n      if ( angular.isDefined(minutes) ) {\n        selected.setMinutes( minutes );\n        refresh( 'm' );\n      } else {\n        invalidate(undefined, true);\n      }\n    };\n\n    minutesInputEl.bind('blur', function(e) {\n      if ( !$scope.invalidMinutes && $scope.minutes < 10 ) {\n        $scope.$apply( function() {\n          $scope.minutes = pad( $scope.minutes );\n        });\n      }\n    });\n\n  };\n\n  this.render = function() {\n    var date = ngModelCtrl.$modelValue ? new Date( ngModelCtrl.$modelValue ) : null;\n\n    if ( isNaN(date) ) {\n      ngModelCtrl.$setValidity('time', false);\n      $log.error('Timepicker directive: \"ng-model\" value must be a Date object, a number of milliseconds since 01.01.1970 or a string representing an RFC2822 or ISO 8601 date.');\n    } else {\n      if ( date ) {\n        selected = date;\n      }\n      makeValid();\n      updateTemplate();\n    }\n  };\n\n  // Call internally when we know that model is valid.\n  function refresh( keyboardChange ) {\n    makeValid();\n    ngModelCtrl.$setViewValue( new Date(selected) );\n    updateTemplate( keyboardChange );\n  }\n\n  function makeValid() {\n    ngModelCtrl.$setValidity('time', true);\n    $scope.invalidHours = false;\n    $scope.invalidMinutes = false;\n  }\n\n  function updateTemplate( keyboardChange ) {\n    var hours = selected.getHours(), minutes = selected.getMinutes();\n\n    if ( $scope.showMeridian ) {\n      hours = ( hours === 0 || hours === 12 ) ? 12 : hours % 12; // Convert 24 to 12 hour system\n    }\n\n    $scope.hours = keyboardChange === 'h' ? hours : pad(hours);\n    $scope.minutes = keyboardChange === 'm' ? minutes : pad(minutes);\n    $scope.meridian = selected.getHours() < 12 ? meridians[0] : meridians[1];\n  }\n\n  function addMinutes( minutes ) {\n    var dt = new Date( selected.getTime() + minutes * 60000 );\n    selected.setHours( dt.getHours(), dt.getMinutes() );\n    refresh();\n  }\n\n  $scope.incrementHours = function() {\n    addMinutes( hourStep * 60 );\n  };\n  $scope.decrementHours = function() {\n    addMinutes( - hourStep * 60 );\n  };\n  $scope.incrementMinutes = function() {\n    addMinutes( minuteStep );\n  };\n  $scope.decrementMinutes = function() {\n    addMinutes( - minuteStep );\n  };\n  $scope.toggleMeridian = function() {\n    addMinutes( 12 * 60 * (( selected.getHours() < 12 ) ? 1 : -1) );\n  };\n}])\n\n.directive('timepicker', function () {\n  return {\n    restrict: 'EA',\n    require: ['timepicker', '?^ngModel'],\n    controller:'TimepickerController',\n    replace: true,\n    scope: {},\n    templateUrl: 'template/timepicker/timepicker.html',\n    link: function(scope, element, attrs, ctrls) {\n      var timepickerCtrl = ctrls[0], ngModelCtrl = ctrls[1];\n\n      if ( ngModelCtrl ) {\n        timepickerCtrl.init( ngModelCtrl, element.find('input') );\n      }\n    }\n  };\n});\n\nangular.module('ui.bootstrap.typeahead', ['ui.bootstrap.position', 'ui.bootstrap.bindHtml'])\n\n/**\n * A helper service that can parse typeahead's syntax (string provided by users)\n * Extracted to a separate service for ease of unit testing\n */\n  .factory('typeaheadParser', ['$parse', function ($parse) {\n\n  //                      00000111000000000000022200000000000000003333333333333330000000000044000\n  var TYPEAHEAD_REGEXP = /^\\s*([\\s\\S]+?)(?:\\s+as\\s+([\\s\\S]+?))?\\s+for\\s+(?:([\\$\\w][\\$\\w\\d]*))\\s+in\\s+([\\s\\S]+?)$/;\n\n  return {\n    parse:function (input) {\n\n      var match = input.match(TYPEAHEAD_REGEXP);\n      if (!match) {\n        throw new Error(\n          'Expected typeahead specification in form of \"_modelValue_ (as _label_)? for _item_ in _collection_\"' +\n            ' but got \"' + input + '\".');\n      }\n\n      return {\n        itemName:match[3],\n        source:$parse(match[4]),\n        viewMapper:$parse(match[2] || match[1]),\n        modelMapper:$parse(match[1])\n      };\n    }\n  };\n}])\n\n  .directive('typeahead', ['$compile', '$parse', '$q', '$timeout', '$document', '$position', 'typeaheadParser',\n    function ($compile, $parse, $q, $timeout, $document, $position, typeaheadParser) {\n\n  var HOT_KEYS = [9, 13, 27, 38, 40];\n\n  return {\n    require:'ngModel',\n    link:function (originalScope, element, attrs, modelCtrl) {\n\n      //SUPPORTED ATTRIBUTES (OPTIONS)\n\n      //minimal no of characters that needs to be entered before typeahead kicks-in\n      var minSearch = originalScope.$eval(attrs.typeaheadMinLength) || 1;\n\n      //minimal wait time after last character typed before typehead kicks-in\n      var waitTime = originalScope.$eval(attrs.typeaheadWaitMs) || 0;\n\n      //should it restrict model values to the ones selected from the popup only?\n      var isEditable = originalScope.$eval(attrs.typeaheadEditable) !== false;\n\n      //binding to a variable that indicates if matches are being retrieved asynchronously\n      var isLoadingSetter = $parse(attrs.typeaheadLoading).assign || angular.noop;\n\n      //a callback executed when a match is selected\n      var onSelectCallback = $parse(attrs.typeaheadOnSelect);\n\n      var inputFormatter = attrs.typeaheadInputFormatter ? $parse(attrs.typeaheadInputFormatter) : undefined;\n\n      var appendToBody =  attrs.typeaheadAppendToBody ? originalScope.$eval(attrs.typeaheadAppendToBody) : false;\n\n      var focusFirst = originalScope.$eval(attrs.typeaheadFocusFirst) !== false;\n\n      //INTERNAL VARIABLES\n\n      //model setter executed upon match selection\n      var $setModelValue = $parse(attrs.ngModel).assign;\n\n      //expressions used by typeahead\n      var parserResult = typeaheadParser.parse(attrs.typeahead);\n\n      var hasFocus;\n\n      //create a child scope for the typeahead directive so we are not polluting original scope\n      //with typeahead-specific data (matches, query etc.)\n      var scope = originalScope.$new();\n      originalScope.$on('$destroy', function(){\n        scope.$destroy();\n      });\n\n      // WAI-ARIA\n      var popupId = 'typeahead-' + scope.$id + '-' + Math.floor(Math.random() * 10000);\n      element.attr({\n        'aria-autocomplete': 'list',\n        'aria-expanded': false,\n        'aria-owns': popupId\n      });\n\n      //pop-up element used to display matches\n      var popUpEl = angular.element('<div typeahead-popup></div>');\n      popUpEl.attr({\n        id: popupId,\n        matches: 'matches',\n        active: 'activeIdx',\n        select: 'select(activeIdx)',\n        query: 'query',\n        position: 'position'\n      });\n      //custom item template\n      if (angular.isDefined(attrs.typeaheadTemplateUrl)) {\n        popUpEl.attr('template-url', attrs.typeaheadTemplateUrl);\n      }\n\n      var resetMatches = function() {\n        scope.matches = [];\n        scope.activeIdx = -1;\n        element.attr('aria-expanded', false);\n      };\n\n      var getMatchId = function(index) {\n        return popupId + '-option-' + index;\n      };\n\n      // Indicate that the specified match is the active (pre-selected) item in the list owned by this typeahead.\n      // This attribute is added or removed automatically when the `activeIdx` changes.\n      scope.$watch('activeIdx', function(index) {\n        if (index < 0) {\n          element.removeAttr('aria-activedescendant');\n        } else {\n          element.attr('aria-activedescendant', getMatchId(index));\n        }\n      });\n\n      var getMatchesAsync = function(inputValue) {\n\n        var locals = {$viewValue: inputValue};\n        isLoadingSetter(originalScope, true);\n        $q.when(parserResult.source(originalScope, locals)).then(function(matches) {\n\n          //it might happen that several async queries were in progress if a user were typing fast\n          //but we are interested only in responses that correspond to the current view value\n          var onCurrentRequest = (inputValue === modelCtrl.$viewValue);\n          if (onCurrentRequest && hasFocus) {\n            if (matches.length > 0) {\n\n              scope.activeIdx = focusFirst ? 0 : -1;\n              scope.matches.length = 0;\n\n              //transform labels\n              for(var i=0; i<matches.length; i++) {\n                locals[parserResult.itemName] = matches[i];\n                scope.matches.push({\n                  id: getMatchId(i),\n                  label: parserResult.viewMapper(scope, locals),\n                  model: matches[i]\n                });\n              }\n\n              scope.query = inputValue;\n              //position pop-up with matches - we need to re-calculate its position each time we are opening a window\n              //with matches as a pop-up might be absolute-positioned and position of an input might have changed on a page\n              //due to other elements being rendered\n              scope.position = appendToBody ? $position.offset(element) : $position.position(element);\n              scope.position.top = scope.position.top + element.prop('offsetHeight');\n\n              element.attr('aria-expanded', true);\n            } else {\n              resetMatches();\n            }\n          }\n          if (onCurrentRequest) {\n            isLoadingSetter(originalScope, false);\n          }\n        }, function(){\n          resetMatches();\n          isLoadingSetter(originalScope, false);\n        });\n      };\n\n      resetMatches();\n\n      //we need to propagate user's query so we can higlight matches\n      scope.query = undefined;\n\n      //Declare the timeout promise var outside the function scope so that stacked calls can be cancelled later \n      var timeoutPromise;\n\n      var scheduleSearchWithTimeout = function(inputValue) {\n        timeoutPromise = $timeout(function () {\n          getMatchesAsync(inputValue);\n        }, waitTime);\n      };\n\n      var cancelPreviousTimeout = function() {\n        if (timeoutPromise) {\n          $timeout.cancel(timeoutPromise);\n        }\n      };\n\n      //plug into $parsers pipeline to open a typeahead on view changes initiated from DOM\n      //$parsers kick-in on all the changes coming from the view as well as manually triggered by $setViewValue\n      modelCtrl.$parsers.unshift(function (inputValue) {\n\n        hasFocus = true;\n\n        if (inputValue && inputValue.length >= minSearch) {\n          if (waitTime > 0) {\n            cancelPreviousTimeout();\n            scheduleSearchWithTimeout(inputValue);\n          } else {\n            getMatchesAsync(inputValue);\n          }\n        } else {\n          isLoadingSetter(originalScope, false);\n          cancelPreviousTimeout();\n          resetMatches();\n        }\n\n        if (isEditable) {\n          return inputValue;\n        } else {\n          if (!inputValue) {\n            // Reset in case user had typed something previously.\n            modelCtrl.$setValidity('editable', true);\n            return inputValue;\n          } else {\n            modelCtrl.$setValidity('editable', false);\n            return undefined;\n          }\n        }\n      });\n\n      modelCtrl.$formatters.push(function (modelValue) {\n\n        var candidateViewValue, emptyViewValue;\n        var locals = {};\n\n        if (inputFormatter) {\n\n          locals.$model = modelValue;\n          return inputFormatter(originalScope, locals);\n\n        } else {\n\n          //it might happen that we don't have enough info to properly render input value\n          //we need to check for this situation and simply return model value if we can't apply custom formatting\n          locals[parserResult.itemName] = modelValue;\n          candidateViewValue = parserResult.viewMapper(originalScope, locals);\n          locals[parserResult.itemName] = undefined;\n          emptyViewValue = parserResult.viewMapper(originalScope, locals);\n\n          return candidateViewValue!== emptyViewValue ? candidateViewValue : modelValue;\n        }\n      });\n\n      scope.select = function (activeIdx) {\n        //called from within the $digest() cycle\n        var locals = {};\n        var model, item;\n\n        locals[parserResult.itemName] = item = scope.matches[activeIdx].model;\n        model = parserResult.modelMapper(originalScope, locals);\n        $setModelValue(originalScope, model);\n        modelCtrl.$setValidity('editable', true);\n\n        onSelectCallback(originalScope, {\n          $item: item,\n          $model: model,\n          $label: parserResult.viewMapper(originalScope, locals)\n        });\n\n        resetMatches();\n\n        //return focus to the input element if a match was selected via a mouse click event\n        // use timeout to avoid $rootScope:inprog error\n        $timeout(function() { element[0].focus(); }, 0, false);\n      };\n\n      //bind keyboard events: arrows up(38) / down(40), enter(13) and tab(9), esc(27)\n      element.bind('keydown', function (evt) {\n\n        //typeahead is open and an \"interesting\" key was pressed\n        if (scope.matches.length === 0 || HOT_KEYS.indexOf(evt.which) === -1) {\n          return;\n        }\n\n        // if there's nothing selected (i.e. focusFirst) and enter is hit, don't do anything\n        if (scope.activeIdx == -1 && (evt.which === 13 || evt.which === 9)) {\n          return;\n        }\n\n        evt.preventDefault();\n\n        if (evt.which === 40) {\n          scope.activeIdx = (scope.activeIdx + 1) % scope.matches.length;\n          scope.$digest();\n\n        } else if (evt.which === 38) {\n          scope.activeIdx = (scope.activeIdx > 0 ? scope.activeIdx : scope.matches.length) - 1;\n          scope.$digest();\n\n        } else if (evt.which === 13 || evt.which === 9) {\n          scope.$apply(function () {\n            scope.select(scope.activeIdx);\n          });\n\n        } else if (evt.which === 27) {\n          evt.stopPropagation();\n\n          resetMatches();\n          scope.$digest();\n        }\n      });\n\n      element.bind('blur', function (evt) {\n        hasFocus = false;\n      });\n\n      // Keep reference to click handler to unbind it.\n      var dismissClickHandler = function (evt) {\n        if (element[0] !== evt.target) {\n          resetMatches();\n          scope.$digest();\n        }\n      };\n\n      $document.bind('click', dismissClickHandler);\n\n      originalScope.$on('$destroy', function(){\n        $document.unbind('click', dismissClickHandler);\n        if (appendToBody) {\n          $popup.remove();\n        }\n      });\n\n      var $popup = $compile(popUpEl)(scope);\n      if (appendToBody) {\n        $document.find('body').append($popup);\n      } else {\n        element.after($popup);\n      }\n    }\n  };\n\n}])\n\n  .directive('typeaheadPopup', function () {\n    return {\n      restrict:'EA',\n      scope:{\n        matches:'=',\n        query:'=',\n        active:'=',\n        position:'=',\n        select:'&'\n      },\n      replace:true,\n      templateUrl:'template/typeahead/typeahead-popup.html',\n      link:function (scope, element, attrs) {\n\n        scope.templateUrl = attrs.templateUrl;\n\n        scope.isOpen = function () {\n          return scope.matches.length > 0;\n        };\n\n        scope.isActive = function (matchIdx) {\n          return scope.active == matchIdx;\n        };\n\n        scope.selectActive = function (matchIdx) {\n          scope.active = matchIdx;\n        };\n\n        scope.selectMatch = function (activeIdx) {\n          scope.select({activeIdx:activeIdx});\n        };\n      }\n    };\n  })\n\n  .directive('typeaheadMatch', ['$http', '$templateCache', '$compile', '$parse', function ($http, $templateCache, $compile, $parse) {\n    return {\n      restrict:'EA',\n      scope:{\n        index:'=',\n        match:'=',\n        query:'='\n      },\n      link:function (scope, element, attrs) {\n        var tplUrl = $parse(attrs.templateUrl)(scope.$parent) || 'template/typeahead/typeahead-match.html';\n        $http.get(tplUrl, {cache: $templateCache}).success(function(tplContent){\n           element.replaceWith($compile(tplContent.trim())(scope));\n        });\n      }\n    };\n  }])\n\n  .filter('typeaheadHighlight', function() {\n\n    function escapeRegexp(queryToEscape) {\n      return queryToEscape.replace(/([.?*+^$[\\]\\\\(){}|-])/g, '\\\\$1');\n    }\n\n    return function(matchItem, query) {\n      return query ? ('' + matchItem).replace(new RegExp(escapeRegexp(query), 'gi'), '<strong>$&</strong>') : matchItem;\n    };\n  });\n\nangular.module(\"template/accordion/accordion-group.html\", []).run([\"$templateCache\", function($templateCache) {\n  $templateCache.put(\"template/accordion/accordion-group.html\",\n    \"<div class=\\\"panel panel-default\\\">\\n\" +\n    \"  <div class=\\\"panel-heading\\\">\\n\" +\n    \"    <h4 class=\\\"panel-title\\\">\\n\" +\n    \"      <a href class=\\\"accordion-toggle\\\" ng-click=\\\"toggleOpen()\\\" accordion-transclude=\\\"heading\\\"><span ng-class=\\\"{'text-muted': isDisabled}\\\">{{heading}}</span></a>\\n\" +\n    \"    </h4>\\n\" +\n    \"  </div>\\n\" +\n    \"  <div class=\\\"panel-collapse\\\" collapse=\\\"!isOpen\\\">\\n\" +\n    \"\t  <div class=\\\"panel-body\\\" ng-transclude></div>\\n\" +\n    \"  </div>\\n\" +\n    \"</div>\\n\" +\n    \"\");\n}]);\n\nangular.module(\"template/accordion/accordion.html\", []).run([\"$templateCache\", function($templateCache) {\n  $templateCache.put(\"template/accordion/accordion.html\",\n    \"<div class=\\\"panel-group\\\" ng-transclude></div>\");\n}]);\n\nangular.module(\"template/alert/alert.html\", []).run([\"$templateCache\", function($templateCache) {\n  $templateCache.put(\"template/alert/alert.html\",\n    \"<div class=\\\"alert\\\" ng-class=\\\"['alert-' + (type || 'warning'), closeable ? 'alert-dismissable' : null]\\\" role=\\\"alert\\\">\\n\" +\n    \"    <button ng-show=\\\"closeable\\\" type=\\\"button\\\" class=\\\"close\\\" ng-click=\\\"close()\\\">\\n\" +\n    \"        <span aria-hidden=\\\"true\\\">&times;</span>\\n\" +\n    \"        <span class=\\\"sr-only\\\">Close</span>\\n\" +\n    \"    </button>\\n\" +\n    \"    <div ng-transclude></div>\\n\" +\n    \"</div>\\n\" +\n    \"\");\n}]);\n\nangular.module(\"template/carousel/carousel.html\", []).run([\"$templateCache\", function($templateCache) {\n  $templateCache.put(\"template/carousel/carousel.html\",\n    \"<div ng-mouseenter=\\\"pause()\\\" ng-mouseleave=\\\"play()\\\" class=\\\"carousel\\\" ng-swipe-right=\\\"prev()\\\" ng-swipe-left=\\\"next()\\\">\\n\" +\n    \"    <ol class=\\\"carousel-indicators\\\" ng-show=\\\"slides.length > 1\\\">\\n\" +\n    \"        <li ng-repeat=\\\"slide in slides track by $index\\\" ng-class=\\\"{active: isActive(slide)}\\\" ng-click=\\\"select(slide)\\\"></li>\\n\" +\n    \"    </ol>\\n\" +\n    \"    <div class=\\\"carousel-inner\\\" ng-transclude></div>\\n\" +\n    \"    <a class=\\\"left carousel-control\\\" ng-click=\\\"prev()\\\" ng-show=\\\"slides.length > 1\\\"><span class=\\\"glyphicon glyphicon-chevron-left\\\"></span></a>\\n\" +\n    \"    <a class=\\\"right carousel-control\\\" ng-click=\\\"next()\\\" ng-show=\\\"slides.length > 1\\\"><span class=\\\"glyphicon glyphicon-chevron-right\\\"></span></a>\\n\" +\n    \"</div>\\n\" +\n    \"\");\n}]);\n\nangular.module(\"template/carousel/slide.html\", []).run([\"$templateCache\", function($templateCache) {\n  $templateCache.put(\"template/carousel/slide.html\",\n    \"<div ng-class=\\\"{\\n\" +\n    \"    'active': leaving || (active && !entering),\\n\" +\n    \"    'prev': (next || active) && direction=='prev',\\n\" +\n    \"    'next': (next || active) && direction=='next',\\n\" +\n    \"    'right': direction=='prev',\\n\" +\n    \"    'left': direction=='next'\\n\" +\n    \"  }\\\" class=\\\"item text-center\\\" ng-transclude></div>\\n\" +\n    \"\");\n}]);\n\nangular.module(\"template/datepicker/datepicker.html\", []).run([\"$templateCache\", function($templateCache) {\n  $templateCache.put(\"template/datepicker/datepicker.html\",\n    \"<div ng-switch=\\\"datepickerMode\\\" role=\\\"application\\\" ng-keydown=\\\"keydown($event)\\\">\\n\" +\n    \"  <daypicker ng-switch-when=\\\"day\\\" tabindex=\\\"0\\\"></daypicker>\\n\" +\n    \"  <monthpicker ng-switch-when=\\\"month\\\" tabindex=\\\"0\\\"></monthpicker>\\n\" +\n    \"  <yearpicker ng-switch-when=\\\"year\\\" tabindex=\\\"0\\\"></yearpicker>\\n\" +\n    \"</div>\");\n}]);\n\nangular.module(\"template/datepicker/day.html\", []).run([\"$templateCache\", function($templateCache) {\n  $templateCache.put(\"template/datepicker/day.html\",\n    \"<table role=\\\"grid\\\" aria-labelledby=\\\"{{uniqueId}}-title\\\" aria-activedescendant=\\\"{{activeDateId}}\\\">\\n\" +\n    \"  <thead>\\n\" +\n    \"    <tr>\\n\" +\n    \"      <th><button type=\\\"button\\\" class=\\\"btn btn-default btn-sm pull-left\\\" ng-click=\\\"move(-1)\\\" tabindex=\\\"-1\\\"><i class=\\\"glyphicon glyphicon-chevron-left\\\"></i></button></th>\\n\" +\n    \"      <th colspan=\\\"{{5 + showWeeks}}\\\"><button id=\\\"{{uniqueId}}-title\\\" role=\\\"heading\\\" aria-live=\\\"assertive\\\" aria-atomic=\\\"true\\\" type=\\\"button\\\" class=\\\"btn btn-default btn-sm\\\" ng-click=\\\"toggleMode()\\\" tabindex=\\\"-1\\\" style=\\\"width:100%;\\\"><strong>{{title}}</strong></button></th>\\n\" +\n    \"      <th><button type=\\\"button\\\" class=\\\"btn btn-default btn-sm pull-right\\\" ng-click=\\\"move(1)\\\" tabindex=\\\"-1\\\"><i class=\\\"glyphicon glyphicon-chevron-right\\\"></i></button></th>\\n\" +\n    \"    </tr>\\n\" +\n    \"    <tr>\\n\" +\n    \"      <th ng-show=\\\"showWeeks\\\" class=\\\"text-center\\\"></th>\\n\" +\n    \"      <th ng-repeat=\\\"label in labels track by $index\\\" class=\\\"text-center\\\"><small aria-label=\\\"{{label.full}}\\\">{{label.abbr}}</small></th>\\n\" +\n    \"    </tr>\\n\" +\n    \"  </thead>\\n\" +\n    \"  <tbody>\\n\" +\n    \"    <tr ng-repeat=\\\"row in rows track by $index\\\">\\n\" +\n    \"      <td ng-show=\\\"showWeeks\\\" class=\\\"text-center h6\\\"><em>{{ weekNumbers[$index] }}</em></td>\\n\" +\n    \"      <td ng-repeat=\\\"dt in row track by dt.date\\\" class=\\\"text-center\\\" role=\\\"gridcell\\\" id=\\\"{{dt.uid}}\\\" aria-disabled=\\\"{{!!dt.disabled}}\\\">\\n\" +\n    \"        <button type=\\\"button\\\" style=\\\"width:100%;\\\" class=\\\"btn btn-default btn-sm\\\" ng-class=\\\"{'btn-info': dt.selected, active: isActive(dt)}\\\" ng-click=\\\"select(dt.date)\\\" ng-disabled=\\\"dt.disabled\\\" tabindex=\\\"-1\\\"><span ng-class=\\\"{'text-muted': dt.secondary, 'text-info': dt.current}\\\">{{dt.label}}</span></button>\\n\" +\n    \"      </td>\\n\" +\n    \"    </tr>\\n\" +\n    \"  </tbody>\\n\" +\n    \"</table>\\n\" +\n    \"\");\n}]);\n\nangular.module(\"template/datepicker/month.html\", []).run([\"$templateCache\", function($templateCache) {\n  $templateCache.put(\"template/datepicker/month.html\",\n    \"<table role=\\\"grid\\\" aria-labelledby=\\\"{{uniqueId}}-title\\\" aria-activedescendant=\\\"{{activeDateId}}\\\">\\n\" +\n    \"  <thead>\\n\" +\n    \"    <tr>\\n\" +\n    \"      <th><button type=\\\"button\\\" class=\\\"btn btn-default btn-sm pull-left\\\" ng-click=\\\"move(-1)\\\" tabindex=\\\"-1\\\"><i class=\\\"glyphicon glyphicon-chevron-left\\\"></i></button></th>\\n\" +\n    \"      <th><button id=\\\"{{uniqueId}}-title\\\" role=\\\"heading\\\" aria-live=\\\"assertive\\\" aria-atomic=\\\"true\\\" type=\\\"button\\\" class=\\\"btn btn-default btn-sm\\\" ng-click=\\\"toggleMode()\\\" tabindex=\\\"-1\\\" style=\\\"width:100%;\\\"><strong>{{title}}</strong></button></th>\\n\" +\n    \"      <th><button type=\\\"button\\\" class=\\\"btn btn-default btn-sm pull-right\\\" ng-click=\\\"move(1)\\\" tabindex=\\\"-1\\\"><i class=\\\"glyphicon glyphicon-chevron-right\\\"></i></button></th>\\n\" +\n    \"    </tr>\\n\" +\n    \"  </thead>\\n\" +\n    \"  <tbody>\\n\" +\n    \"    <tr ng-repeat=\\\"row in rows track by $index\\\">\\n\" +\n    \"      <td ng-repeat=\\\"dt in row track by dt.date\\\" class=\\\"text-center\\\" role=\\\"gridcell\\\" id=\\\"{{dt.uid}}\\\" aria-disabled=\\\"{{!!dt.disabled}}\\\">\\n\" +\n    \"        <button type=\\\"button\\\" style=\\\"width:100%;\\\" class=\\\"btn btn-default\\\" ng-class=\\\"{'btn-info': dt.selected, active: isActive(dt)}\\\" ng-click=\\\"select(dt.date)\\\" ng-disabled=\\\"dt.disabled\\\" tabindex=\\\"-1\\\"><span ng-class=\\\"{'text-info': dt.current}\\\">{{dt.label}}</span></button>\\n\" +\n    \"      </td>\\n\" +\n    \"    </tr>\\n\" +\n    \"  </tbody>\\n\" +\n    \"</table>\\n\" +\n    \"\");\n}]);\n\nangular.module(\"template/datepicker/popup.html\", []).run([\"$templateCache\", function($templateCache) {\n  $templateCache.put(\"template/datepicker/popup.html\",\n    \"<ul class=\\\"dropdown-menu\\\" ng-style=\\\"{display: (isOpen && 'block') || 'none', top: position.top+'px', left: position.left+'px'}\\\" ng-keydown=\\\"keydown($event)\\\">\\n\" +\n    \"\t<li ng-transclude></li>\\n\" +\n    \"\t<li ng-if=\\\"showButtonBar\\\" style=\\\"padding:10px 9px 2px\\\">\\n\" +\n    \"\t\t<span class=\\\"btn-group pull-left\\\">\\n\" +\n    \"\t\t\t<button type=\\\"button\\\" class=\\\"btn btn-sm btn-info\\\" ng-click=\\\"select('today')\\\">{{ getText('current') }}</button>\\n\" +\n    \"\t\t\t<button type=\\\"button\\\" class=\\\"btn btn-sm btn-danger\\\" ng-click=\\\"select(null)\\\">{{ getText('clear') }}</button>\\n\" +\n    \"\t\t</span>\\n\" +\n    \"\t\t<button type=\\\"button\\\" class=\\\"btn btn-sm btn-success pull-right\\\" ng-click=\\\"close()\\\">{{ getText('close') }}</button>\\n\" +\n    \"\t</li>\\n\" +\n    \"</ul>\\n\" +\n    \"\");\n}]);\n\nangular.module(\"template/datepicker/year.html\", []).run([\"$templateCache\", function($templateCache) {\n  $templateCache.put(\"template/datepicker/year.html\",\n    \"<table role=\\\"grid\\\" aria-labelledby=\\\"{{uniqueId}}-title\\\" aria-activedescendant=\\\"{{activeDateId}}\\\">\\n\" +\n    \"  <thead>\\n\" +\n    \"    <tr>\\n\" +\n    \"      <th><button type=\\\"button\\\" class=\\\"btn btn-default btn-sm pull-left\\\" ng-click=\\\"move(-1)\\\" tabindex=\\\"-1\\\"><i class=\\\"glyphicon glyphicon-chevron-left\\\"></i></button></th>\\n\" +\n    \"      <th colspan=\\\"3\\\"><button id=\\\"{{uniqueId}}-title\\\" role=\\\"heading\\\" aria-live=\\\"assertive\\\" aria-atomic=\\\"true\\\" type=\\\"button\\\" class=\\\"btn btn-default btn-sm\\\" ng-click=\\\"toggleMode()\\\" tabindex=\\\"-1\\\" style=\\\"width:100%;\\\"><strong>{{title}}</strong></button></th>\\n\" +\n    \"      <th><button type=\\\"button\\\" class=\\\"btn btn-default btn-sm pull-right\\\" ng-click=\\\"move(1)\\\" tabindex=\\\"-1\\\"><i class=\\\"glyphicon glyphicon-chevron-right\\\"></i></button></th>\\n\" +\n    \"    </tr>\\n\" +\n    \"  </thead>\\n\" +\n    \"  <tbody>\\n\" +\n    \"    <tr ng-repeat=\\\"row in rows track by $index\\\">\\n\" +\n    \"      <td ng-repeat=\\\"dt in row track by dt.date\\\" class=\\\"text-center\\\" role=\\\"gridcell\\\" id=\\\"{{dt.uid}}\\\" aria-disabled=\\\"{{!!dt.disabled}}\\\">\\n\" +\n    \"        <button type=\\\"button\\\" style=\\\"width:100%;\\\" class=\\\"btn btn-default\\\" ng-class=\\\"{'btn-info': dt.selected, active: isActive(dt)}\\\" ng-click=\\\"select(dt.date)\\\" ng-disabled=\\\"dt.disabled\\\" tabindex=\\\"-1\\\"><span ng-class=\\\"{'text-info': dt.current}\\\">{{dt.label}}</span></button>\\n\" +\n    \"      </td>\\n\" +\n    \"    </tr>\\n\" +\n    \"  </tbody>\\n\" +\n    \"</table>\\n\" +\n    \"\");\n}]);\n\nangular.module(\"template/modal/backdrop.html\", []).run([\"$templateCache\", function($templateCache) {\n  $templateCache.put(\"template/modal/backdrop.html\",\n    \"<div class=\\\"modal-backdrop fade {{ backdropClass }}\\\"\\n\" +\n    \"     ng-class=\\\"{in: animate}\\\"\\n\" +\n    \"     ng-style=\\\"{'z-index': 1040 + (index && 1 || 0) + index*10}\\\"\\n\" +\n    \"></div>\\n\" +\n    \"\");\n}]);\n\nangular.module(\"template/modal/window.html\", []).run([\"$templateCache\", function($templateCache) {\n  $templateCache.put(\"template/modal/window.html\",\n    \"<div tabindex=\\\"-1\\\" role=\\\"dialog\\\" class=\\\"modal fade\\\" ng-class=\\\"{in: animate}\\\" ng-style=\\\"{'z-index': 1050 + index*10, display: 'block'}\\\" ng-click=\\\"close($event)\\\">\\n\" +\n    \"    <div class=\\\"modal-dialog\\\" ng-class=\\\"{'modal-sm': size == 'sm', 'modal-lg': size == 'lg'}\\\"><div class=\\\"modal-content\\\" modal-transclude></div></div>\\n\" +\n    \"</div>\");\n}]);\n\nangular.module(\"template/pagination/pager.html\", []).run([\"$templateCache\", function($templateCache) {\n  $templateCache.put(\"template/pagination/pager.html\",\n    \"<ul class=\\\"pager\\\">\\n\" +\n    \"  <li ng-class=\\\"{disabled: noPrevious(), previous: align}\\\"><a href ng-click=\\\"selectPage(page - 1)\\\">{{getText('previous')}}</a></li>\\n\" +\n    \"  <li ng-class=\\\"{disabled: noNext(), next: align}\\\"><a href ng-click=\\\"selectPage(page + 1)\\\">{{getText('next')}}</a></li>\\n\" +\n    \"</ul>\");\n}]);\n\nangular.module(\"template/pagination/pagination.html\", []).run([\"$templateCache\", function($templateCache) {\n  $templateCache.put(\"template/pagination/pagination.html\",\n    \"<ul class=\\\"pagination\\\">\\n\" +\n    \"  <li ng-if=\\\"boundaryLinks\\\" ng-class=\\\"{disabled: noPrevious()}\\\"><a href ng-click=\\\"selectPage(1)\\\">{{getText('first')}}</a></li>\\n\" +\n    \"  <li ng-if=\\\"directionLinks\\\" ng-class=\\\"{disabled: noPrevious()}\\\"><a href ng-click=\\\"selectPage(page - 1)\\\">{{getText('previous')}}</a></li>\\n\" +\n    \"  <li ng-repeat=\\\"page in pages track by $index\\\" ng-class=\\\"{active: page.active}\\\"><a href ng-click=\\\"selectPage(page.number)\\\">{{page.text}}</a></li>\\n\" +\n    \"  <li ng-if=\\\"directionLinks\\\" ng-class=\\\"{disabled: noNext()}\\\"><a href ng-click=\\\"selectPage(page + 1)\\\">{{getText('next')}}</a></li>\\n\" +\n    \"  <li ng-if=\\\"boundaryLinks\\\" ng-class=\\\"{disabled: noNext()}\\\"><a href ng-click=\\\"selectPage(totalPages)\\\">{{getText('last')}}</a></li>\\n\" +\n    \"</ul>\");\n}]);\n\nangular.module(\"template/tooltip/tooltip-html-unsafe-popup.html\", []).run([\"$templateCache\", function($templateCache) {\n  $templateCache.put(\"template/tooltip/tooltip-html-unsafe-popup.html\",\n    \"<div class=\\\"tooltip {{placement}}\\\" ng-class=\\\"{ in: isOpen(), fade: animation() }\\\">\\n\" +\n    \"  <div class=\\\"tooltip-arrow\\\"></div>\\n\" +\n    \"  <div class=\\\"tooltip-inner\\\" bind-html-unsafe=\\\"content\\\"></div>\\n\" +\n    \"</div>\\n\" +\n    \"\");\n}]);\n\nangular.module(\"template/tooltip/tooltip-popup.html\", []).run([\"$templateCache\", function($templateCache) {\n  $templateCache.put(\"template/tooltip/tooltip-popup.html\",\n    \"<div class=\\\"tooltip {{placement}}\\\" ng-class=\\\"{ in: isOpen(), fade: animation() }\\\">\\n\" +\n    \"  <div class=\\\"tooltip-arrow\\\"></div>\\n\" +\n    \"  <div class=\\\"tooltip-inner\\\" ng-bind=\\\"content\\\"></div>\\n\" +\n    \"</div>\\n\" +\n    \"\");\n}]);\n\nangular.module(\"template/popover/popover.html\", []).run([\"$templateCache\", function($templateCache) {\n  $templateCache.put(\"template/popover/popover.html\",\n    \"<div class=\\\"popover {{placement}}\\\" ng-class=\\\"{ in: isOpen(), fade: animation() }\\\">\\n\" +\n    \"  <div class=\\\"arrow\\\"></div>\\n\" +\n    \"\\n\" +\n    \"  <div class=\\\"popover-inner\\\">\\n\" +\n    \"      <h3 class=\\\"popover-title\\\" ng-bind=\\\"title\\\" ng-show=\\\"title\\\"></h3>\\n\" +\n    \"      <div class=\\\"popover-content\\\" ng-bind=\\\"content\\\"></div>\\n\" +\n    \"  </div>\\n\" +\n    \"</div>\\n\" +\n    \"\");\n}]);\n\nangular.module(\"template/progressbar/bar.html\", []).run([\"$templateCache\", function($templateCache) {\n  $templateCache.put(\"template/progressbar/bar.html\",\n    \"<div class=\\\"progress-bar\\\" ng-class=\\\"type && 'progress-bar-' + type\\\" role=\\\"progressbar\\\" aria-valuenow=\\\"{{value}}\\\" aria-valuemin=\\\"0\\\" aria-valuemax=\\\"{{max}}\\\" ng-style=\\\"{width: percent + '%'}\\\" aria-valuetext=\\\"{{percent | number:0}}%\\\" ng-transclude></div>\");\n}]);\n\nangular.module(\"template/progressbar/progress.html\", []).run([\"$templateCache\", function($templateCache) {\n  $templateCache.put(\"template/progressbar/progress.html\",\n    \"<div class=\\\"progress\\\" ng-transclude></div>\");\n}]);\n\nangular.module(\"template/progressbar/progressbar.html\", []).run([\"$templateCache\", function($templateCache) {\n  $templateCache.put(\"template/progressbar/progressbar.html\",\n    \"<div class=\\\"progress\\\">\\n\" +\n    \"  <div class=\\\"progress-bar\\\" ng-class=\\\"type && 'progress-bar-' + type\\\" role=\\\"progressbar\\\" aria-valuenow=\\\"{{value}}\\\" aria-valuemin=\\\"0\\\" aria-valuemax=\\\"{{max}}\\\" ng-style=\\\"{width: percent + '%'}\\\" aria-valuetext=\\\"{{percent | number:0}}%\\\" ng-transclude></div>\\n\" +\n    \"</div>\");\n}]);\n\nangular.module(\"template/rating/rating.html\", []).run([\"$templateCache\", function($templateCache) {\n  $templateCache.put(\"template/rating/rating.html\",\n    \"<span ng-mouseleave=\\\"reset()\\\" ng-keydown=\\\"onKeydown($event)\\\" tabindex=\\\"0\\\" role=\\\"slider\\\" aria-valuemin=\\\"0\\\" aria-valuemax=\\\"{{range.length}}\\\" aria-valuenow=\\\"{{value}}\\\">\\n\" +\n    \"    <i ng-repeat=\\\"r in range track by $index\\\" ng-mouseenter=\\\"enter($index + 1)\\\" ng-click=\\\"rate($index + 1)\\\" class=\\\"glyphicon\\\" ng-class=\\\"$index < value && (r.stateOn || 'glyphicon-star') || (r.stateOff || 'glyphicon-star-empty')\\\">\\n\" +\n    \"        <span class=\\\"sr-only\\\">({{ $index < value ? '*' : ' ' }})</span>\\n\" +\n    \"    </i>\\n\" +\n    \"</span>\");\n}]);\n\nangular.module(\"template/tabs/tab.html\", []).run([\"$templateCache\", function($templateCache) {\n  $templateCache.put(\"template/tabs/tab.html\",\n    \"<li ng-class=\\\"{active: active, disabled: disabled}\\\">\\n\" +\n    \"  <a href ng-click=\\\"select()\\\" tab-heading-transclude>{{heading}}</a>\\n\" +\n    \"</li>\\n\" +\n    \"\");\n}]);\n\nangular.module(\"template/tabs/tabset.html\", []).run([\"$templateCache\", function($templateCache) {\n  $templateCache.put(\"template/tabs/tabset.html\",\n    \"<div>\\n\" +\n    \"  <ul class=\\\"nav nav-{{type || 'tabs'}}\\\" ng-class=\\\"{'nav-stacked': vertical, 'nav-justified': justified}\\\" ng-transclude></ul>\\n\" +\n    \"  <div class=\\\"tab-content\\\">\\n\" +\n    \"    <div class=\\\"tab-pane\\\" \\n\" +\n    \"         ng-repeat=\\\"tab in tabs\\\" \\n\" +\n    \"         ng-class=\\\"{active: tab.active}\\\"\\n\" +\n    \"         tab-content-transclude=\\\"tab\\\">\\n\" +\n    \"    </div>\\n\" +\n    \"  </div>\\n\" +\n    \"</div>\\n\" +\n    \"\");\n}]);\n\nangular.module(\"template/timepicker/timepicker.html\", []).run([\"$templateCache\", function($templateCache) {\n  $templateCache.put(\"template/timepicker/timepicker.html\",\n    \"<table>\\n\" +\n    \"\t<tbody>\\n\" +\n    \"\t\t<tr class=\\\"text-center\\\">\\n\" +\n    \"\t\t\t<td><a ng-click=\\\"incrementHours()\\\" class=\\\"btn btn-link\\\"><span class=\\\"glyphicon glyphicon-chevron-up\\\"></span></a></td>\\n\" +\n    \"\t\t\t<td>&nbsp;</td>\\n\" +\n    \"\t\t\t<td><a ng-click=\\\"incrementMinutes()\\\" class=\\\"btn btn-link\\\"><span class=\\\"glyphicon glyphicon-chevron-up\\\"></span></a></td>\\n\" +\n    \"\t\t\t<td ng-show=\\\"showMeridian\\\"></td>\\n\" +\n    \"\t\t</tr>\\n\" +\n    \"\t\t<tr>\\n\" +\n    \"\t\t\t<td style=\\\"width:50px;\\\" class=\\\"form-group\\\" ng-class=\\\"{'has-error': invalidHours}\\\">\\n\" +\n    \"\t\t\t\t<input type=\\\"text\\\" ng-model=\\\"hours\\\" ng-change=\\\"updateHours()\\\" class=\\\"form-control text-center\\\" ng-mousewheel=\\\"incrementHours()\\\" ng-readonly=\\\"readonlyInput\\\" maxlength=\\\"2\\\">\\n\" +\n    \"\t\t\t</td>\\n\" +\n    \"\t\t\t<td>:</td>\\n\" +\n    \"\t\t\t<td style=\\\"width:50px;\\\" class=\\\"form-group\\\" ng-class=\\\"{'has-error': invalidMinutes}\\\">\\n\" +\n    \"\t\t\t\t<input type=\\\"text\\\" ng-model=\\\"minutes\\\" ng-change=\\\"updateMinutes()\\\" class=\\\"form-control text-center\\\" ng-readonly=\\\"readonlyInput\\\" maxlength=\\\"2\\\">\\n\" +\n    \"\t\t\t</td>\\n\" +\n    \"\t\t\t<td ng-show=\\\"showMeridian\\\"><button type=\\\"button\\\" class=\\\"btn btn-default text-center\\\" ng-click=\\\"toggleMeridian()\\\">{{meridian}}</button></td>\\n\" +\n    \"\t\t</tr>\\n\" +\n    \"\t\t<tr class=\\\"text-center\\\">\\n\" +\n    \"\t\t\t<td><a ng-click=\\\"decrementHours()\\\" class=\\\"btn btn-link\\\"><span class=\\\"glyphicon glyphicon-chevron-down\\\"></span></a></td>\\n\" +\n    \"\t\t\t<td>&nbsp;</td>\\n\" +\n    \"\t\t\t<td><a ng-click=\\\"decrementMinutes()\\\" class=\\\"btn btn-link\\\"><span class=\\\"glyphicon glyphicon-chevron-down\\\"></span></a></td>\\n\" +\n    \"\t\t\t<td ng-show=\\\"showMeridian\\\"></td>\\n\" +\n    \"\t\t</tr>\\n\" +\n    \"\t</tbody>\\n\" +\n    \"</table>\\n\" +\n    \"\");\n}]);\n\nangular.module(\"template/typeahead/typeahead-match.html\", []).run([\"$templateCache\", function($templateCache) {\n  $templateCache.put(\"template/typeahead/typeahead-match.html\",\n    \"<a tabindex=\\\"-1\\\" bind-html-unsafe=\\\"match.label | typeaheadHighlight:query\\\"></a>\");\n}]);\n\nangular.module(\"template/typeahead/typeahead-popup.html\", []).run([\"$templateCache\", function($templateCache) {\n  $templateCache.put(\"template/typeahead/typeahead-popup.html\",\n    \"<ul class=\\\"dropdown-menu\\\" ng-show=\\\"isOpen()\\\" ng-style=\\\"{top: position.top+'px', left: position.left+'px'}\\\" style=\\\"display: block;\\\" role=\\\"listbox\\\" aria-hidden=\\\"{{!isOpen()}}\\\">\\n\" +\n    \"    <li ng-repeat=\\\"match in matches track by $index\\\" ng-class=\\\"{active: isActive($index) }\\\" ng-mouseenter=\\\"selectActive($index)\\\" ng-click=\\\"selectMatch($index)\\\" role=\\\"option\\\" id=\\\"{{match.id}}\\\">\\n\" +\n    \"        <div typeahead-match index=\\\"$index\\\" match=\\\"match\\\" query=\\\"query\\\" template-url=\\\"templateUrl\\\"></div>\\n\" +\n    \"    </li>\\n\" +\n    \"</ul>\\n\" +\n    \"\");\n}]);\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/angular-bootstrap/ui-bootstrap.js",
    "content": "/*\n * angular-ui-bootstrap\n * http://angular-ui.github.io/bootstrap/\n\n * Version: 0.12.0 - 2014-11-16\n * License: MIT\n */\nangular.module(\"ui.bootstrap\", [\"ui.bootstrap.transition\",\"ui.bootstrap.collapse\",\"ui.bootstrap.accordion\",\"ui.bootstrap.alert\",\"ui.bootstrap.bindHtml\",\"ui.bootstrap.buttons\",\"ui.bootstrap.carousel\",\"ui.bootstrap.dateparser\",\"ui.bootstrap.position\",\"ui.bootstrap.datepicker\",\"ui.bootstrap.dropdown\",\"ui.bootstrap.modal\",\"ui.bootstrap.pagination\",\"ui.bootstrap.tooltip\",\"ui.bootstrap.popover\",\"ui.bootstrap.progressbar\",\"ui.bootstrap.rating\",\"ui.bootstrap.tabs\",\"ui.bootstrap.timepicker\",\"ui.bootstrap.typeahead\"]);\nangular.module('ui.bootstrap.transition', [])\n\n/**\n * $transition service provides a consistent interface to trigger CSS 3 transitions and to be informed when they complete.\n * @param  {DOMElement} element  The DOMElement that will be animated.\n * @param  {string|object|function} trigger  The thing that will cause the transition to start:\n *   - As a string, it represents the css class to be added to the element.\n *   - As an object, it represents a hash of style attributes to be applied to the element.\n *   - As a function, it represents a function to be called that will cause the transition to occur.\n * @return {Promise}  A promise that is resolved when the transition finishes.\n */\n.factory('$transition', ['$q', '$timeout', '$rootScope', function($q, $timeout, $rootScope) {\n\n  var $transition = function(element, trigger, options) {\n    options = options || {};\n    var deferred = $q.defer();\n    var endEventName = $transition[options.animation ? 'animationEndEventName' : 'transitionEndEventName'];\n\n    var transitionEndHandler = function(event) {\n      $rootScope.$apply(function() {\n        element.unbind(endEventName, transitionEndHandler);\n        deferred.resolve(element);\n      });\n    };\n\n    if (endEventName) {\n      element.bind(endEventName, transitionEndHandler);\n    }\n\n    // Wrap in a timeout to allow the browser time to update the DOM before the transition is to occur\n    $timeout(function() {\n      if ( angular.isString(trigger) ) {\n        element.addClass(trigger);\n      } else if ( angular.isFunction(trigger) ) {\n        trigger(element);\n      } else if ( angular.isObject(trigger) ) {\n        element.css(trigger);\n      }\n      //If browser does not support transitions, instantly resolve\n      if ( !endEventName ) {\n        deferred.resolve(element);\n      }\n    });\n\n    // Add our custom cancel function to the promise that is returned\n    // We can call this if we are about to run a new transition, which we know will prevent this transition from ending,\n    // i.e. it will therefore never raise a transitionEnd event for that transition\n    deferred.promise.cancel = function() {\n      if ( endEventName ) {\n        element.unbind(endEventName, transitionEndHandler);\n      }\n      deferred.reject('Transition cancelled');\n    };\n\n    return deferred.promise;\n  };\n\n  // Work out the name of the transitionEnd event\n  var transElement = document.createElement('trans');\n  var transitionEndEventNames = {\n    'WebkitTransition': 'webkitTransitionEnd',\n    'MozTransition': 'transitionend',\n    'OTransition': 'oTransitionEnd',\n    'transition': 'transitionend'\n  };\n  var animationEndEventNames = {\n    'WebkitTransition': 'webkitAnimationEnd',\n    'MozTransition': 'animationend',\n    'OTransition': 'oAnimationEnd',\n    'transition': 'animationend'\n  };\n  function findEndEventName(endEventNames) {\n    for (var name in endEventNames){\n      if (transElement.style[name] !== undefined) {\n        return endEventNames[name];\n      }\n    }\n  }\n  $transition.transitionEndEventName = findEndEventName(transitionEndEventNames);\n  $transition.animationEndEventName = findEndEventName(animationEndEventNames);\n  return $transition;\n}]);\n\nangular.module('ui.bootstrap.collapse', ['ui.bootstrap.transition'])\n\n  .directive('collapse', ['$transition', function ($transition) {\n\n    return {\n      link: function (scope, element, attrs) {\n\n        var initialAnimSkip = true;\n        var currentTransition;\n\n        function doTransition(change) {\n          var newTransition = $transition(element, change);\n          if (currentTransition) {\n            currentTransition.cancel();\n          }\n          currentTransition = newTransition;\n          newTransition.then(newTransitionDone, newTransitionDone);\n          return newTransition;\n\n          function newTransitionDone() {\n            // Make sure it's this transition, otherwise, leave it alone.\n            if (currentTransition === newTransition) {\n              currentTransition = undefined;\n            }\n          }\n        }\n\n        function expand() {\n          if (initialAnimSkip) {\n            initialAnimSkip = false;\n            expandDone();\n          } else {\n            element.removeClass('collapse').addClass('collapsing');\n            doTransition({ height: element[0].scrollHeight + 'px' }).then(expandDone);\n          }\n        }\n\n        function expandDone() {\n          element.removeClass('collapsing');\n          element.addClass('collapse in');\n          element.css({height: 'auto'});\n        }\n\n        function collapse() {\n          if (initialAnimSkip) {\n            initialAnimSkip = false;\n            collapseDone();\n            element.css({height: 0});\n          } else {\n            // CSS transitions don't work with height: auto, so we have to manually change the height to a specific value\n            element.css({ height: element[0].scrollHeight + 'px' });\n            //trigger reflow so a browser realizes that height was updated from auto to a specific value\n            var x = element[0].offsetWidth;\n\n            element.removeClass('collapse in').addClass('collapsing');\n\n            doTransition({ height: 0 }).then(collapseDone);\n          }\n        }\n\n        function collapseDone() {\n          element.removeClass('collapsing');\n          element.addClass('collapse');\n        }\n\n        scope.$watch(attrs.collapse, function (shouldCollapse) {\n          if (shouldCollapse) {\n            collapse();\n          } else {\n            expand();\n          }\n        });\n      }\n    };\n  }]);\n\nangular.module('ui.bootstrap.accordion', ['ui.bootstrap.collapse'])\n\n.constant('accordionConfig', {\n  closeOthers: true\n})\n\n.controller('AccordionController', ['$scope', '$attrs', 'accordionConfig', function ($scope, $attrs, accordionConfig) {\n\n  // This array keeps track of the accordion groups\n  this.groups = [];\n\n  // Ensure that all the groups in this accordion are closed, unless close-others explicitly says not to\n  this.closeOthers = function(openGroup) {\n    var closeOthers = angular.isDefined($attrs.closeOthers) ? $scope.$eval($attrs.closeOthers) : accordionConfig.closeOthers;\n    if ( closeOthers ) {\n      angular.forEach(this.groups, function (group) {\n        if ( group !== openGroup ) {\n          group.isOpen = false;\n        }\n      });\n    }\n  };\n\n  // This is called from the accordion-group directive to add itself to the accordion\n  this.addGroup = function(groupScope) {\n    var that = this;\n    this.groups.push(groupScope);\n\n    groupScope.$on('$destroy', function (event) {\n      that.removeGroup(groupScope);\n    });\n  };\n\n  // This is called from the accordion-group directive when to remove itself\n  this.removeGroup = function(group) {\n    var index = this.groups.indexOf(group);\n    if ( index !== -1 ) {\n      this.groups.splice(index, 1);\n    }\n  };\n\n}])\n\n// The accordion directive simply sets up the directive controller\n// and adds an accordion CSS class to itself element.\n.directive('accordion', function () {\n  return {\n    restrict:'EA',\n    controller:'AccordionController',\n    transclude: true,\n    replace: false,\n    templateUrl: 'template/accordion/accordion.html'\n  };\n})\n\n// The accordion-group directive indicates a block of html that will expand and collapse in an accordion\n.directive('accordionGroup', function() {\n  return {\n    require:'^accordion',         // We need this directive to be inside an accordion\n    restrict:'EA',\n    transclude:true,              // It transcludes the contents of the directive into the template\n    replace: true,                // The element containing the directive will be replaced with the template\n    templateUrl:'template/accordion/accordion-group.html',\n    scope: {\n      heading: '@',               // Interpolate the heading attribute onto this scope\n      isOpen: '=?',\n      isDisabled: '=?'\n    },\n    controller: function() {\n      this.setHeading = function(element) {\n        this.heading = element;\n      };\n    },\n    link: function(scope, element, attrs, accordionCtrl) {\n      accordionCtrl.addGroup(scope);\n\n      scope.$watch('isOpen', function(value) {\n        if ( value ) {\n          accordionCtrl.closeOthers(scope);\n        }\n      });\n\n      scope.toggleOpen = function() {\n        if ( !scope.isDisabled ) {\n          scope.isOpen = !scope.isOpen;\n        }\n      };\n    }\n  };\n})\n\n// Use accordion-heading below an accordion-group to provide a heading containing HTML\n// <accordion-group>\n//   <accordion-heading>Heading containing HTML - <img src=\"...\"></accordion-heading>\n// </accordion-group>\n.directive('accordionHeading', function() {\n  return {\n    restrict: 'EA',\n    transclude: true,   // Grab the contents to be used as the heading\n    template: '',       // In effect remove this element!\n    replace: true,\n    require: '^accordionGroup',\n    link: function(scope, element, attr, accordionGroupCtrl, transclude) {\n      // Pass the heading to the accordion-group controller\n      // so that it can be transcluded into the right place in the template\n      // [The second parameter to transclude causes the elements to be cloned so that they work in ng-repeat]\n      accordionGroupCtrl.setHeading(transclude(scope, function() {}));\n    }\n  };\n})\n\n// Use in the accordion-group template to indicate where you want the heading to be transcluded\n// You must provide the property on the accordion-group controller that will hold the transcluded element\n// <div class=\"accordion-group\">\n//   <div class=\"accordion-heading\" ><a ... accordion-transclude=\"heading\">...</a></div>\n//   ...\n// </div>\n.directive('accordionTransclude', function() {\n  return {\n    require: '^accordionGroup',\n    link: function(scope, element, attr, controller) {\n      scope.$watch(function() { return controller[attr.accordionTransclude]; }, function(heading) {\n        if ( heading ) {\n          element.html('');\n          element.append(heading);\n        }\n      });\n    }\n  };\n});\n\nangular.module('ui.bootstrap.alert', [])\n\n.controller('AlertController', ['$scope', '$attrs', function ($scope, $attrs) {\n  $scope.closeable = 'close' in $attrs;\n  this.close = $scope.close;\n}])\n\n.directive('alert', function () {\n  return {\n    restrict:'EA',\n    controller:'AlertController',\n    templateUrl:'template/alert/alert.html',\n    transclude:true,\n    replace:true,\n    scope: {\n      type: '@',\n      close: '&'\n    }\n  };\n})\n\n.directive('dismissOnTimeout', ['$timeout', function($timeout) {\n  return {\n    require: 'alert',\n    link: function(scope, element, attrs, alertCtrl) {\n      $timeout(function(){\n        alertCtrl.close();\n      }, parseInt(attrs.dismissOnTimeout, 10));\n    }\n  };\n}]);\n\nangular.module('ui.bootstrap.bindHtml', [])\n\n  .directive('bindHtmlUnsafe', function () {\n    return function (scope, element, attr) {\n      element.addClass('ng-binding').data('$binding', attr.bindHtmlUnsafe);\n      scope.$watch(attr.bindHtmlUnsafe, function bindHtmlUnsafeWatchAction(value) {\n        element.html(value || '');\n      });\n    };\n  });\nangular.module('ui.bootstrap.buttons', [])\n\n.constant('buttonConfig', {\n  activeClass: 'active',\n  toggleEvent: 'click'\n})\n\n.controller('ButtonsController', ['buttonConfig', function(buttonConfig) {\n  this.activeClass = buttonConfig.activeClass || 'active';\n  this.toggleEvent = buttonConfig.toggleEvent || 'click';\n}])\n\n.directive('btnRadio', function () {\n  return {\n    require: ['btnRadio', 'ngModel'],\n    controller: 'ButtonsController',\n    link: function (scope, element, attrs, ctrls) {\n      var buttonsCtrl = ctrls[0], ngModelCtrl = ctrls[1];\n\n      //model -> UI\n      ngModelCtrl.$render = function () {\n        element.toggleClass(buttonsCtrl.activeClass, angular.equals(ngModelCtrl.$modelValue, scope.$eval(attrs.btnRadio)));\n      };\n\n      //ui->model\n      element.bind(buttonsCtrl.toggleEvent, function () {\n        var isActive = element.hasClass(buttonsCtrl.activeClass);\n\n        if (!isActive || angular.isDefined(attrs.uncheckable)) {\n          scope.$apply(function () {\n            ngModelCtrl.$setViewValue(isActive ? null : scope.$eval(attrs.btnRadio));\n            ngModelCtrl.$render();\n          });\n        }\n      });\n    }\n  };\n})\n\n.directive('btnCheckbox', function () {\n  return {\n    require: ['btnCheckbox', 'ngModel'],\n    controller: 'ButtonsController',\n    link: function (scope, element, attrs, ctrls) {\n      var buttonsCtrl = ctrls[0], ngModelCtrl = ctrls[1];\n\n      function getTrueValue() {\n        return getCheckboxValue(attrs.btnCheckboxTrue, true);\n      }\n\n      function getFalseValue() {\n        return getCheckboxValue(attrs.btnCheckboxFalse, false);\n      }\n\n      function getCheckboxValue(attributeValue, defaultValue) {\n        var val = scope.$eval(attributeValue);\n        return angular.isDefined(val) ? val : defaultValue;\n      }\n\n      //model -> UI\n      ngModelCtrl.$render = function () {\n        element.toggleClass(buttonsCtrl.activeClass, angular.equals(ngModelCtrl.$modelValue, getTrueValue()));\n      };\n\n      //ui->model\n      element.bind(buttonsCtrl.toggleEvent, function () {\n        scope.$apply(function () {\n          ngModelCtrl.$setViewValue(element.hasClass(buttonsCtrl.activeClass) ? getFalseValue() : getTrueValue());\n          ngModelCtrl.$render();\n        });\n      });\n    }\n  };\n});\n\n/**\n* @ngdoc overview\n* @name ui.bootstrap.carousel\n*\n* @description\n* AngularJS version of an image carousel.\n*\n*/\nangular.module('ui.bootstrap.carousel', ['ui.bootstrap.transition'])\n.controller('CarouselController', ['$scope', '$timeout', '$interval', '$transition', function ($scope, $timeout, $interval, $transition) {\n  var self = this,\n    slides = self.slides = $scope.slides = [],\n    currentIndex = -1,\n    currentInterval, isPlaying;\n  self.currentSlide = null;\n\n  var destroyed = false;\n  /* direction: \"prev\" or \"next\" */\n  self.select = $scope.select = function(nextSlide, direction) {\n    var nextIndex = slides.indexOf(nextSlide);\n    //Decide direction if it's not given\n    if (direction === undefined) {\n      direction = nextIndex > currentIndex ? 'next' : 'prev';\n    }\n    if (nextSlide && nextSlide !== self.currentSlide) {\n      if ($scope.$currentTransition) {\n        $scope.$currentTransition.cancel();\n        //Timeout so ng-class in template has time to fix classes for finished slide\n        $timeout(goNext);\n      } else {\n        goNext();\n      }\n    }\n    function goNext() {\n      // Scope has been destroyed, stop here.\n      if (destroyed) { return; }\n      //If we have a slide to transition from and we have a transition type and we're allowed, go\n      if (self.currentSlide && angular.isString(direction) && !$scope.noTransition && nextSlide.$element) {\n        //We shouldn't do class manip in here, but it's the same weird thing bootstrap does. need to fix sometime\n        nextSlide.$element.addClass(direction);\n        var reflow = nextSlide.$element[0].offsetWidth; //force reflow\n\n        //Set all other slides to stop doing their stuff for the new transition\n        angular.forEach(slides, function(slide) {\n          angular.extend(slide, {direction: '', entering: false, leaving: false, active: false});\n        });\n        angular.extend(nextSlide, {direction: direction, active: true, entering: true});\n        angular.extend(self.currentSlide||{}, {direction: direction, leaving: true});\n\n        $scope.$currentTransition = $transition(nextSlide.$element, {});\n        //We have to create new pointers inside a closure since next & current will change\n        (function(next,current) {\n          $scope.$currentTransition.then(\n            function(){ transitionDone(next, current); },\n            function(){ transitionDone(next, current); }\n          );\n        }(nextSlide, self.currentSlide));\n      } else {\n        transitionDone(nextSlide, self.currentSlide);\n      }\n      self.currentSlide = nextSlide;\n      currentIndex = nextIndex;\n      //every time you change slides, reset the timer\n      restartTimer();\n    }\n    function transitionDone(next, current) {\n      angular.extend(next, {direction: '', active: true, leaving: false, entering: false});\n      angular.extend(current||{}, {direction: '', active: false, leaving: false, entering: false});\n      $scope.$currentTransition = null;\n    }\n  };\n  $scope.$on('$destroy', function () {\n    destroyed = true;\n  });\n\n  /* Allow outside people to call indexOf on slides array */\n  self.indexOfSlide = function(slide) {\n    return slides.indexOf(slide);\n  };\n\n  $scope.next = function() {\n    var newIndex = (currentIndex + 1) % slides.length;\n\n    //Prevent this user-triggered transition from occurring if there is already one in progress\n    if (!$scope.$currentTransition) {\n      return self.select(slides[newIndex], 'next');\n    }\n  };\n\n  $scope.prev = function() {\n    var newIndex = currentIndex - 1 < 0 ? slides.length - 1 : currentIndex - 1;\n\n    //Prevent this user-triggered transition from occurring if there is already one in progress\n    if (!$scope.$currentTransition) {\n      return self.select(slides[newIndex], 'prev');\n    }\n  };\n\n  $scope.isActive = function(slide) {\n     return self.currentSlide === slide;\n  };\n\n  $scope.$watch('interval', restartTimer);\n  $scope.$on('$destroy', resetTimer);\n\n  function restartTimer() {\n    resetTimer();\n    var interval = +$scope.interval;\n    if (!isNaN(interval) && interval > 0) {\n      currentInterval = $interval(timerFn, interval);\n    }\n  }\n\n  function resetTimer() {\n    if (currentInterval) {\n      $interval.cancel(currentInterval);\n      currentInterval = null;\n    }\n  }\n\n  function timerFn() {\n    var interval = +$scope.interval;\n    if (isPlaying && !isNaN(interval) && interval > 0) {\n      $scope.next();\n    } else {\n      $scope.pause();\n    }\n  }\n\n  $scope.play = function() {\n    if (!isPlaying) {\n      isPlaying = true;\n      restartTimer();\n    }\n  };\n  $scope.pause = function() {\n    if (!$scope.noPause) {\n      isPlaying = false;\n      resetTimer();\n    }\n  };\n\n  self.addSlide = function(slide, element) {\n    slide.$element = element;\n    slides.push(slide);\n    //if this is the first slide or the slide is set to active, select it\n    if(slides.length === 1 || slide.active) {\n      self.select(slides[slides.length-1]);\n      if (slides.length == 1) {\n        $scope.play();\n      }\n    } else {\n      slide.active = false;\n    }\n  };\n\n  self.removeSlide = function(slide) {\n    //get the index of the slide inside the carousel\n    var index = slides.indexOf(slide);\n    slides.splice(index, 1);\n    if (slides.length > 0 && slide.active) {\n      if (index >= slides.length) {\n        self.select(slides[index-1]);\n      } else {\n        self.select(slides[index]);\n      }\n    } else if (currentIndex > index) {\n      currentIndex--;\n    }\n  };\n\n}])\n\n/**\n * @ngdoc directive\n * @name ui.bootstrap.carousel.directive:carousel\n * @restrict EA\n *\n * @description\n * Carousel is the outer container for a set of image 'slides' to showcase.\n *\n * @param {number=} interval The time, in milliseconds, that it will take the carousel to go to the next slide.\n * @param {boolean=} noTransition Whether to disable transitions on the carousel.\n * @param {boolean=} noPause Whether to disable pausing on the carousel (by default, the carousel interval pauses on hover).\n *\n * @example\n<example module=\"ui.bootstrap\">\n  <file name=\"index.html\">\n    <carousel>\n      <slide>\n        <img src=\"http://placekitten.com/150/150\" style=\"margin:auto;\">\n        <div class=\"carousel-caption\">\n          <p>Beautiful!</p>\n        </div>\n      </slide>\n      <slide>\n        <img src=\"http://placekitten.com/100/150\" style=\"margin:auto;\">\n        <div class=\"carousel-caption\">\n          <p>D'aww!</p>\n        </div>\n      </slide>\n    </carousel>\n  </file>\n  <file name=\"demo.css\">\n    .carousel-indicators {\n      top: auto;\n      bottom: 15px;\n    }\n  </file>\n</example>\n */\n.directive('carousel', [function() {\n  return {\n    restrict: 'EA',\n    transclude: true,\n    replace: true,\n    controller: 'CarouselController',\n    require: 'carousel',\n    templateUrl: 'template/carousel/carousel.html',\n    scope: {\n      interval: '=',\n      noTransition: '=',\n      noPause: '='\n    }\n  };\n}])\n\n/**\n * @ngdoc directive\n * @name ui.bootstrap.carousel.directive:slide\n * @restrict EA\n *\n * @description\n * Creates a slide inside a {@link ui.bootstrap.carousel.directive:carousel carousel}.  Must be placed as a child of a carousel element.\n *\n * @param {boolean=} active Model binding, whether or not this slide is currently active.\n *\n * @example\n<example module=\"ui.bootstrap\">\n  <file name=\"index.html\">\n<div ng-controller=\"CarouselDemoCtrl\">\n  <carousel>\n    <slide ng-repeat=\"slide in slides\" active=\"slide.active\">\n      <img ng-src=\"{{slide.image}}\" style=\"margin:auto;\">\n      <div class=\"carousel-caption\">\n        <h4>Slide {{$index}}</h4>\n        <p>{{slide.text}}</p>\n      </div>\n    </slide>\n  </carousel>\n  Interval, in milliseconds: <input type=\"number\" ng-model=\"myInterval\">\n  <br />Enter a negative number to stop the interval.\n</div>\n  </file>\n  <file name=\"script.js\">\nfunction CarouselDemoCtrl($scope) {\n  $scope.myInterval = 5000;\n}\n  </file>\n  <file name=\"demo.css\">\n    .carousel-indicators {\n      top: auto;\n      bottom: 15px;\n    }\n  </file>\n</example>\n*/\n\n.directive('slide', function() {\n  return {\n    require: '^carousel',\n    restrict: 'EA',\n    transclude: true,\n    replace: true,\n    templateUrl: 'template/carousel/slide.html',\n    scope: {\n      active: '=?'\n    },\n    link: function (scope, element, attrs, carouselCtrl) {\n      carouselCtrl.addSlide(scope, element);\n      //when the scope is destroyed then remove the slide from the current slides array\n      scope.$on('$destroy', function() {\n        carouselCtrl.removeSlide(scope);\n      });\n\n      scope.$watch('active', function(active) {\n        if (active) {\n          carouselCtrl.select(scope);\n        }\n      });\n    }\n  };\n});\n\nangular.module('ui.bootstrap.dateparser', [])\n\n.service('dateParser', ['$locale', 'orderByFilter', function($locale, orderByFilter) {\n\n  this.parsers = {};\n\n  var formatCodeToRegex = {\n    'yyyy': {\n      regex: '\\\\d{4}',\n      apply: function(value) { this.year = +value; }\n    },\n    'yy': {\n      regex: '\\\\d{2}',\n      apply: function(value) { this.year = +value + 2000; }\n    },\n    'y': {\n      regex: '\\\\d{1,4}',\n      apply: function(value) { this.year = +value; }\n    },\n    'MMMM': {\n      regex: $locale.DATETIME_FORMATS.MONTH.join('|'),\n      apply: function(value) { this.month = $locale.DATETIME_FORMATS.MONTH.indexOf(value); }\n    },\n    'MMM': {\n      regex: $locale.DATETIME_FORMATS.SHORTMONTH.join('|'),\n      apply: function(value) { this.month = $locale.DATETIME_FORMATS.SHORTMONTH.indexOf(value); }\n    },\n    'MM': {\n      regex: '0[1-9]|1[0-2]',\n      apply: function(value) { this.month = value - 1; }\n    },\n    'M': {\n      regex: '[1-9]|1[0-2]',\n      apply: function(value) { this.month = value - 1; }\n    },\n    'dd': {\n      regex: '[0-2][0-9]{1}|3[0-1]{1}',\n      apply: function(value) { this.date = +value; }\n    },\n    'd': {\n      regex: '[1-2]?[0-9]{1}|3[0-1]{1}',\n      apply: function(value) { this.date = +value; }\n    },\n    'EEEE': {\n      regex: $locale.DATETIME_FORMATS.DAY.join('|')\n    },\n    'EEE': {\n      regex: $locale.DATETIME_FORMATS.SHORTDAY.join('|')\n    }\n  };\n\n  function createParser(format) {\n    var map = [], regex = format.split('');\n\n    angular.forEach(formatCodeToRegex, function(data, code) {\n      var index = format.indexOf(code);\n\n      if (index > -1) {\n        format = format.split('');\n\n        regex[index] = '(' + data.regex + ')';\n        format[index] = '$'; // Custom symbol to define consumed part of format\n        for (var i = index + 1, n = index + code.length; i < n; i++) {\n          regex[i] = '';\n          format[i] = '$';\n        }\n        format = format.join('');\n\n        map.push({ index: index, apply: data.apply });\n      }\n    });\n\n    return {\n      regex: new RegExp('^' + regex.join('') + '$'),\n      map: orderByFilter(map, 'index')\n    };\n  }\n\n  this.parse = function(input, format) {\n    if ( !angular.isString(input) || !format ) {\n      return input;\n    }\n\n    format = $locale.DATETIME_FORMATS[format] || format;\n\n    if ( !this.parsers[format] ) {\n      this.parsers[format] = createParser(format);\n    }\n\n    var parser = this.parsers[format],\n        regex = parser.regex,\n        map = parser.map,\n        results = input.match(regex);\n\n    if ( results && results.length ) {\n      var fields = { year: 1900, month: 0, date: 1, hours: 0 }, dt;\n\n      for( var i = 1, n = results.length; i < n; i++ ) {\n        var mapper = map[i-1];\n        if ( mapper.apply ) {\n          mapper.apply.call(fields, results[i]);\n        }\n      }\n\n      if ( isValid(fields.year, fields.month, fields.date) ) {\n        dt = new Date( fields.year, fields.month, fields.date, fields.hours);\n      }\n\n      return dt;\n    }\n  };\n\n  // Check if date is valid for specific month (and year for February).\n  // Month: 0 = Jan, 1 = Feb, etc\n  function isValid(year, month, date) {\n    if ( month === 1 && date > 28) {\n        return date === 29 && ((year % 4 === 0 && year % 100 !== 0) || year % 400 === 0);\n    }\n\n    if ( month === 3 || month === 5 || month === 8 || month === 10) {\n        return date < 31;\n    }\n\n    return true;\n  }\n}]);\n\nangular.module('ui.bootstrap.position', [])\n\n/**\n * A set of utility methods that can be use to retrieve position of DOM elements.\n * It is meant to be used where we need to absolute-position DOM elements in\n * relation to other, existing elements (this is the case for tooltips, popovers,\n * typeahead suggestions etc.).\n */\n  .factory('$position', ['$document', '$window', function ($document, $window) {\n\n    function getStyle(el, cssprop) {\n      if (el.currentStyle) { //IE\n        return el.currentStyle[cssprop];\n      } else if ($window.getComputedStyle) {\n        return $window.getComputedStyle(el)[cssprop];\n      }\n      // finally try and get inline style\n      return el.style[cssprop];\n    }\n\n    /**\n     * Checks if a given element is statically positioned\n     * @param element - raw DOM element\n     */\n    function isStaticPositioned(element) {\n      return (getStyle(element, 'position') || 'static' ) === 'static';\n    }\n\n    /**\n     * returns the closest, non-statically positioned parentOffset of a given element\n     * @param element\n     */\n    var parentOffsetEl = function (element) {\n      var docDomEl = $document[0];\n      var offsetParent = element.offsetParent || docDomEl;\n      while (offsetParent && offsetParent !== docDomEl && isStaticPositioned(offsetParent) ) {\n        offsetParent = offsetParent.offsetParent;\n      }\n      return offsetParent || docDomEl;\n    };\n\n    return {\n      /**\n       * Provides read-only equivalent of jQuery's position function:\n       * http://api.jquery.com/position/\n       */\n      position: function (element) {\n        var elBCR = this.offset(element);\n        var offsetParentBCR = { top: 0, left: 0 };\n        var offsetParentEl = parentOffsetEl(element[0]);\n        if (offsetParentEl != $document[0]) {\n          offsetParentBCR = this.offset(angular.element(offsetParentEl));\n          offsetParentBCR.top += offsetParentEl.clientTop - offsetParentEl.scrollTop;\n          offsetParentBCR.left += offsetParentEl.clientLeft - offsetParentEl.scrollLeft;\n        }\n\n        var boundingClientRect = element[0].getBoundingClientRect();\n        return {\n          width: boundingClientRect.width || element.prop('offsetWidth'),\n          height: boundingClientRect.height || element.prop('offsetHeight'),\n          top: elBCR.top - offsetParentBCR.top,\n          left: elBCR.left - offsetParentBCR.left\n        };\n      },\n\n      /**\n       * Provides read-only equivalent of jQuery's offset function:\n       * http://api.jquery.com/offset/\n       */\n      offset: function (element) {\n        var boundingClientRect = element[0].getBoundingClientRect();\n        return {\n          width: boundingClientRect.width || element.prop('offsetWidth'),\n          height: boundingClientRect.height || element.prop('offsetHeight'),\n          top: boundingClientRect.top + ($window.pageYOffset || $document[0].documentElement.scrollTop),\n          left: boundingClientRect.left + ($window.pageXOffset || $document[0].documentElement.scrollLeft)\n        };\n      },\n\n      /**\n       * Provides coordinates for the targetEl in relation to hostEl\n       */\n      positionElements: function (hostEl, targetEl, positionStr, appendToBody) {\n\n        var positionStrParts = positionStr.split('-');\n        var pos0 = positionStrParts[0], pos1 = positionStrParts[1] || 'center';\n\n        var hostElPos,\n          targetElWidth,\n          targetElHeight,\n          targetElPos;\n\n        hostElPos = appendToBody ? this.offset(hostEl) : this.position(hostEl);\n\n        targetElWidth = targetEl.prop('offsetWidth');\n        targetElHeight = targetEl.prop('offsetHeight');\n\n        var shiftWidth = {\n          center: function () {\n            return hostElPos.left + hostElPos.width / 2 - targetElWidth / 2;\n          },\n          left: function () {\n            return hostElPos.left;\n          },\n          right: function () {\n            return hostElPos.left + hostElPos.width;\n          }\n        };\n\n        var shiftHeight = {\n          center: function () {\n            return hostElPos.top + hostElPos.height / 2 - targetElHeight / 2;\n          },\n          top: function () {\n            return hostElPos.top;\n          },\n          bottom: function () {\n            return hostElPos.top + hostElPos.height;\n          }\n        };\n\n        switch (pos0) {\n          case 'right':\n            targetElPos = {\n              top: shiftHeight[pos1](),\n              left: shiftWidth[pos0]()\n            };\n            break;\n          case 'left':\n            targetElPos = {\n              top: shiftHeight[pos1](),\n              left: hostElPos.left - targetElWidth\n            };\n            break;\n          case 'bottom':\n            targetElPos = {\n              top: shiftHeight[pos0](),\n              left: shiftWidth[pos1]()\n            };\n            break;\n          default:\n            targetElPos = {\n              top: hostElPos.top - targetElHeight,\n              left: shiftWidth[pos1]()\n            };\n            break;\n        }\n\n        return targetElPos;\n      }\n    };\n  }]);\n\nangular.module('ui.bootstrap.datepicker', ['ui.bootstrap.dateparser', 'ui.bootstrap.position'])\n\n.constant('datepickerConfig', {\n  formatDay: 'dd',\n  formatMonth: 'MMMM',\n  formatYear: 'yyyy',\n  formatDayHeader: 'EEE',\n  formatDayTitle: 'MMMM yyyy',\n  formatMonthTitle: 'yyyy',\n  datepickerMode: 'day',\n  minMode: 'day',\n  maxMode: 'year',\n  showWeeks: true,\n  startingDay: 0,\n  yearRange: 20,\n  minDate: null,\n  maxDate: null\n})\n\n.controller('DatepickerController', ['$scope', '$attrs', '$parse', '$interpolate', '$timeout', '$log', 'dateFilter', 'datepickerConfig', function($scope, $attrs, $parse, $interpolate, $timeout, $log, dateFilter, datepickerConfig) {\n  var self = this,\n      ngModelCtrl = { $setViewValue: angular.noop }; // nullModelCtrl;\n\n  // Modes chain\n  this.modes = ['day', 'month', 'year'];\n\n  // Configuration attributes\n  angular.forEach(['formatDay', 'formatMonth', 'formatYear', 'formatDayHeader', 'formatDayTitle', 'formatMonthTitle',\n                   'minMode', 'maxMode', 'showWeeks', 'startingDay', 'yearRange'], function( key, index ) {\n    self[key] = angular.isDefined($attrs[key]) ? (index < 8 ? $interpolate($attrs[key])($scope.$parent) : $scope.$parent.$eval($attrs[key])) : datepickerConfig[key];\n  });\n\n  // Watchable date attributes\n  angular.forEach(['minDate', 'maxDate'], function( key ) {\n    if ( $attrs[key] ) {\n      $scope.$parent.$watch($parse($attrs[key]), function(value) {\n        self[key] = value ? new Date(value) : null;\n        self.refreshView();\n      });\n    } else {\n      self[key] = datepickerConfig[key] ? new Date(datepickerConfig[key]) : null;\n    }\n  });\n\n  $scope.datepickerMode = $scope.datepickerMode || datepickerConfig.datepickerMode;\n  $scope.uniqueId = 'datepicker-' + $scope.$id + '-' + Math.floor(Math.random() * 10000);\n  this.activeDate = angular.isDefined($attrs.initDate) ? $scope.$parent.$eval($attrs.initDate) : new Date();\n\n  $scope.isActive = function(dateObject) {\n    if (self.compare(dateObject.date, self.activeDate) === 0) {\n      $scope.activeDateId = dateObject.uid;\n      return true;\n    }\n    return false;\n  };\n\n  this.init = function( ngModelCtrl_ ) {\n    ngModelCtrl = ngModelCtrl_;\n\n    ngModelCtrl.$render = function() {\n      self.render();\n    };\n  };\n\n  this.render = function() {\n    if ( ngModelCtrl.$modelValue ) {\n      var date = new Date( ngModelCtrl.$modelValue ),\n          isValid = !isNaN(date);\n\n      if ( isValid ) {\n        this.activeDate = date;\n      } else {\n        $log.error('Datepicker directive: \"ng-model\" value must be a Date object, a number of milliseconds since 01.01.1970 or a string representing an RFC2822 or ISO 8601 date.');\n      }\n      ngModelCtrl.$setValidity('date', isValid);\n    }\n    this.refreshView();\n  };\n\n  this.refreshView = function() {\n    if ( this.element ) {\n      this._refreshView();\n\n      var date = ngModelCtrl.$modelValue ? new Date(ngModelCtrl.$modelValue) : null;\n      ngModelCtrl.$setValidity('date-disabled', !date || (this.element && !this.isDisabled(date)));\n    }\n  };\n\n  this.createDateObject = function(date, format) {\n    var model = ngModelCtrl.$modelValue ? new Date(ngModelCtrl.$modelValue) : null;\n    return {\n      date: date,\n      label: dateFilter(date, format),\n      selected: model && this.compare(date, model) === 0,\n      disabled: this.isDisabled(date),\n      current: this.compare(date, new Date()) === 0\n    };\n  };\n\n  this.isDisabled = function( date ) {\n    return ((this.minDate && this.compare(date, this.minDate) < 0) || (this.maxDate && this.compare(date, this.maxDate) > 0) || ($attrs.dateDisabled && $scope.dateDisabled({date: date, mode: $scope.datepickerMode})));\n  };\n\n  // Split array into smaller arrays\n  this.split = function(arr, size) {\n    var arrays = [];\n    while (arr.length > 0) {\n      arrays.push(arr.splice(0, size));\n    }\n    return arrays;\n  };\n\n  $scope.select = function( date ) {\n    if ( $scope.datepickerMode === self.minMode ) {\n      var dt = ngModelCtrl.$modelValue ? new Date( ngModelCtrl.$modelValue ) : new Date(0, 0, 0, 0, 0, 0, 0);\n      dt.setFullYear( date.getFullYear(), date.getMonth(), date.getDate() );\n      ngModelCtrl.$setViewValue( dt );\n      ngModelCtrl.$render();\n    } else {\n      self.activeDate = date;\n      $scope.datepickerMode = self.modes[ self.modes.indexOf( $scope.datepickerMode ) - 1 ];\n    }\n  };\n\n  $scope.move = function( direction ) {\n    var year = self.activeDate.getFullYear() + direction * (self.step.years || 0),\n        month = self.activeDate.getMonth() + direction * (self.step.months || 0);\n    self.activeDate.setFullYear(year, month, 1);\n    self.refreshView();\n  };\n\n  $scope.toggleMode = function( direction ) {\n    direction = direction || 1;\n\n    if (($scope.datepickerMode === self.maxMode && direction === 1) || ($scope.datepickerMode === self.minMode && direction === -1)) {\n      return;\n    }\n\n    $scope.datepickerMode = self.modes[ self.modes.indexOf( $scope.datepickerMode ) + direction ];\n  };\n\n  // Key event mapper\n  $scope.keys = { 13:'enter', 32:'space', 33:'pageup', 34:'pagedown', 35:'end', 36:'home', 37:'left', 38:'up', 39:'right', 40:'down' };\n\n  var focusElement = function() {\n    $timeout(function() {\n      self.element[0].focus();\n    }, 0 , false);\n  };\n\n  // Listen for focus requests from popup directive\n  $scope.$on('datepicker.focus', focusElement);\n\n  $scope.keydown = function( evt ) {\n    var key = $scope.keys[evt.which];\n\n    if ( !key || evt.shiftKey || evt.altKey ) {\n      return;\n    }\n\n    evt.preventDefault();\n    evt.stopPropagation();\n\n    if (key === 'enter' || key === 'space') {\n      if ( self.isDisabled(self.activeDate)) {\n        return; // do nothing\n      }\n      $scope.select(self.activeDate);\n      focusElement();\n    } else if (evt.ctrlKey && (key === 'up' || key === 'down')) {\n      $scope.toggleMode(key === 'up' ? 1 : -1);\n      focusElement();\n    } else {\n      self.handleKeyDown(key, evt);\n      self.refreshView();\n    }\n  };\n}])\n\n.directive( 'datepicker', function () {\n  return {\n    restrict: 'EA',\n    replace: true,\n    templateUrl: 'template/datepicker/datepicker.html',\n    scope: {\n      datepickerMode: '=?',\n      dateDisabled: '&'\n    },\n    require: ['datepicker', '?^ngModel'],\n    controller: 'DatepickerController',\n    link: function(scope, element, attrs, ctrls) {\n      var datepickerCtrl = ctrls[0], ngModelCtrl = ctrls[1];\n\n      if ( ngModelCtrl ) {\n        datepickerCtrl.init( ngModelCtrl );\n      }\n    }\n  };\n})\n\n.directive('daypicker', ['dateFilter', function (dateFilter) {\n  return {\n    restrict: 'EA',\n    replace: true,\n    templateUrl: 'template/datepicker/day.html',\n    require: '^datepicker',\n    link: function(scope, element, attrs, ctrl) {\n      scope.showWeeks = ctrl.showWeeks;\n\n      ctrl.step = { months: 1 };\n      ctrl.element = element;\n\n      var DAYS_IN_MONTH = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];\n      function getDaysInMonth( year, month ) {\n        return ((month === 1) && (year % 4 === 0) && ((year % 100 !== 0) || (year % 400 === 0))) ? 29 : DAYS_IN_MONTH[month];\n      }\n\n      function getDates(startDate, n) {\n        var dates = new Array(n), current = new Date(startDate), i = 0;\n        current.setHours(12); // Prevent repeated dates because of timezone bug\n        while ( i < n ) {\n          dates[i++] = new Date(current);\n          current.setDate( current.getDate() + 1 );\n        }\n        return dates;\n      }\n\n      ctrl._refreshView = function() {\n        var year = ctrl.activeDate.getFullYear(),\n          month = ctrl.activeDate.getMonth(),\n          firstDayOfMonth = new Date(year, month, 1),\n          difference = ctrl.startingDay - firstDayOfMonth.getDay(),\n          numDisplayedFromPreviousMonth = (difference > 0) ? 7 - difference : - difference,\n          firstDate = new Date(firstDayOfMonth);\n\n        if ( numDisplayedFromPreviousMonth > 0 ) {\n          firstDate.setDate( - numDisplayedFromPreviousMonth + 1 );\n        }\n\n        // 42 is the number of days on a six-month calendar\n        var days = getDates(firstDate, 42);\n        for (var i = 0; i < 42; i ++) {\n          days[i] = angular.extend(ctrl.createDateObject(days[i], ctrl.formatDay), {\n            secondary: days[i].getMonth() !== month,\n            uid: scope.uniqueId + '-' + i\n          });\n        }\n\n        scope.labels = new Array(7);\n        for (var j = 0; j < 7; j++) {\n          scope.labels[j] = {\n            abbr: dateFilter(days[j].date, ctrl.formatDayHeader),\n            full: dateFilter(days[j].date, 'EEEE')\n          };\n        }\n\n        scope.title = dateFilter(ctrl.activeDate, ctrl.formatDayTitle);\n        scope.rows = ctrl.split(days, 7);\n\n        if ( scope.showWeeks ) {\n          scope.weekNumbers = [];\n          var weekNumber = getISO8601WeekNumber( scope.rows[0][0].date ),\n              numWeeks = scope.rows.length;\n          while( scope.weekNumbers.push(weekNumber++) < numWeeks ) {}\n        }\n      };\n\n      ctrl.compare = function(date1, date2) {\n        return (new Date( date1.getFullYear(), date1.getMonth(), date1.getDate() ) - new Date( date2.getFullYear(), date2.getMonth(), date2.getDate() ) );\n      };\n\n      function getISO8601WeekNumber(date) {\n        var checkDate = new Date(date);\n        checkDate.setDate(checkDate.getDate() + 4 - (checkDate.getDay() || 7)); // Thursday\n        var time = checkDate.getTime();\n        checkDate.setMonth(0); // Compare with Jan 1\n        checkDate.setDate(1);\n        return Math.floor(Math.round((time - checkDate) / 86400000) / 7) + 1;\n      }\n\n      ctrl.handleKeyDown = function( key, evt ) {\n        var date = ctrl.activeDate.getDate();\n\n        if (key === 'left') {\n          date = date - 1;   // up\n        } else if (key === 'up') {\n          date = date - 7;   // down\n        } else if (key === 'right') {\n          date = date + 1;   // down\n        } else if (key === 'down') {\n          date = date + 7;\n        } else if (key === 'pageup' || key === 'pagedown') {\n          var month = ctrl.activeDate.getMonth() + (key === 'pageup' ? - 1 : 1);\n          ctrl.activeDate.setMonth(month, 1);\n          date = Math.min(getDaysInMonth(ctrl.activeDate.getFullYear(), ctrl.activeDate.getMonth()), date);\n        } else if (key === 'home') {\n          date = 1;\n        } else if (key === 'end') {\n          date = getDaysInMonth(ctrl.activeDate.getFullYear(), ctrl.activeDate.getMonth());\n        }\n        ctrl.activeDate.setDate(date);\n      };\n\n      ctrl.refreshView();\n    }\n  };\n}])\n\n.directive('monthpicker', ['dateFilter', function (dateFilter) {\n  return {\n    restrict: 'EA',\n    replace: true,\n    templateUrl: 'template/datepicker/month.html',\n    require: '^datepicker',\n    link: function(scope, element, attrs, ctrl) {\n      ctrl.step = { years: 1 };\n      ctrl.element = element;\n\n      ctrl._refreshView = function() {\n        var months = new Array(12),\n            year = ctrl.activeDate.getFullYear();\n\n        for ( var i = 0; i < 12; i++ ) {\n          months[i] = angular.extend(ctrl.createDateObject(new Date(year, i, 1), ctrl.formatMonth), {\n            uid: scope.uniqueId + '-' + i\n          });\n        }\n\n        scope.title = dateFilter(ctrl.activeDate, ctrl.formatMonthTitle);\n        scope.rows = ctrl.split(months, 3);\n      };\n\n      ctrl.compare = function(date1, date2) {\n        return new Date( date1.getFullYear(), date1.getMonth() ) - new Date( date2.getFullYear(), date2.getMonth() );\n      };\n\n      ctrl.handleKeyDown = function( key, evt ) {\n        var date = ctrl.activeDate.getMonth();\n\n        if (key === 'left') {\n          date = date - 1;   // up\n        } else if (key === 'up') {\n          date = date - 3;   // down\n        } else if (key === 'right') {\n          date = date + 1;   // down\n        } else if (key === 'down') {\n          date = date + 3;\n        } else if (key === 'pageup' || key === 'pagedown') {\n          var year = ctrl.activeDate.getFullYear() + (key === 'pageup' ? - 1 : 1);\n          ctrl.activeDate.setFullYear(year);\n        } else if (key === 'home') {\n          date = 0;\n        } else if (key === 'end') {\n          date = 11;\n        }\n        ctrl.activeDate.setMonth(date);\n      };\n\n      ctrl.refreshView();\n    }\n  };\n}])\n\n.directive('yearpicker', ['dateFilter', function (dateFilter) {\n  return {\n    restrict: 'EA',\n    replace: true,\n    templateUrl: 'template/datepicker/year.html',\n    require: '^datepicker',\n    link: function(scope, element, attrs, ctrl) {\n      var range = ctrl.yearRange;\n\n      ctrl.step = { years: range };\n      ctrl.element = element;\n\n      function getStartingYear( year ) {\n        return parseInt((year - 1) / range, 10) * range + 1;\n      }\n\n      ctrl._refreshView = function() {\n        var years = new Array(range);\n\n        for ( var i = 0, start = getStartingYear(ctrl.activeDate.getFullYear()); i < range; i++ ) {\n          years[i] = angular.extend(ctrl.createDateObject(new Date(start + i, 0, 1), ctrl.formatYear), {\n            uid: scope.uniqueId + '-' + i\n          });\n        }\n\n        scope.title = [years[0].label, years[range - 1].label].join(' - ');\n        scope.rows = ctrl.split(years, 5);\n      };\n\n      ctrl.compare = function(date1, date2) {\n        return date1.getFullYear() - date2.getFullYear();\n      };\n\n      ctrl.handleKeyDown = function( key, evt ) {\n        var date = ctrl.activeDate.getFullYear();\n\n        if (key === 'left') {\n          date = date - 1;   // up\n        } else if (key === 'up') {\n          date = date - 5;   // down\n        } else if (key === 'right') {\n          date = date + 1;   // down\n        } else if (key === 'down') {\n          date = date + 5;\n        } else if (key === 'pageup' || key === 'pagedown') {\n          date += (key === 'pageup' ? - 1 : 1) * ctrl.step.years;\n        } else if (key === 'home') {\n          date = getStartingYear( ctrl.activeDate.getFullYear() );\n        } else if (key === 'end') {\n          date = getStartingYear( ctrl.activeDate.getFullYear() ) + range - 1;\n        }\n        ctrl.activeDate.setFullYear(date);\n      };\n\n      ctrl.refreshView();\n    }\n  };\n}])\n\n.constant('datepickerPopupConfig', {\n  datepickerPopup: 'yyyy-MM-dd',\n  currentText: 'Today',\n  clearText: 'Clear',\n  closeText: 'Done',\n  closeOnDateSelection: true,\n  appendToBody: false,\n  showButtonBar: true\n})\n\n.directive('datepickerPopup', ['$compile', '$parse', '$document', '$position', 'dateFilter', 'dateParser', 'datepickerPopupConfig',\nfunction ($compile, $parse, $document, $position, dateFilter, dateParser, datepickerPopupConfig) {\n  return {\n    restrict: 'EA',\n    require: 'ngModel',\n    scope: {\n      isOpen: '=?',\n      currentText: '@',\n      clearText: '@',\n      closeText: '@',\n      dateDisabled: '&'\n    },\n    link: function(scope, element, attrs, ngModel) {\n      var dateFormat,\n          closeOnDateSelection = angular.isDefined(attrs.closeOnDateSelection) ? scope.$parent.$eval(attrs.closeOnDateSelection) : datepickerPopupConfig.closeOnDateSelection,\n          appendToBody = angular.isDefined(attrs.datepickerAppendToBody) ? scope.$parent.$eval(attrs.datepickerAppendToBody) : datepickerPopupConfig.appendToBody;\n\n      scope.showButtonBar = angular.isDefined(attrs.showButtonBar) ? scope.$parent.$eval(attrs.showButtonBar) : datepickerPopupConfig.showButtonBar;\n\n      scope.getText = function( key ) {\n        return scope[key + 'Text'] || datepickerPopupConfig[key + 'Text'];\n      };\n\n      attrs.$observe('datepickerPopup', function(value) {\n          dateFormat = value || datepickerPopupConfig.datepickerPopup;\n          ngModel.$render();\n      });\n\n      // popup element used to display calendar\n      var popupEl = angular.element('<div datepicker-popup-wrap><div datepicker></div></div>');\n      popupEl.attr({\n        'ng-model': 'date',\n        'ng-change': 'dateSelection()'\n      });\n\n      function cameltoDash( string ){\n        return string.replace(/([A-Z])/g, function($1) { return '-' + $1.toLowerCase(); });\n      }\n\n      // datepicker element\n      var datepickerEl = angular.element(popupEl.children()[0]);\n      if ( attrs.datepickerOptions ) {\n        angular.forEach(scope.$parent.$eval(attrs.datepickerOptions), function( value, option ) {\n          datepickerEl.attr( cameltoDash(option), value );\n        });\n      }\n\n      scope.watchData = {};\n      angular.forEach(['minDate', 'maxDate', 'datepickerMode'], function( key ) {\n        if ( attrs[key] ) {\n          var getAttribute = $parse(attrs[key]);\n          scope.$parent.$watch(getAttribute, function(value){\n            scope.watchData[key] = value;\n          });\n          datepickerEl.attr(cameltoDash(key), 'watchData.' + key);\n\n          // Propagate changes from datepicker to outside\n          if ( key === 'datepickerMode' ) {\n            var setAttribute = getAttribute.assign;\n            scope.$watch('watchData.' + key, function(value, oldvalue) {\n              if ( value !== oldvalue ) {\n                setAttribute(scope.$parent, value);\n              }\n            });\n          }\n        }\n      });\n      if (attrs.dateDisabled) {\n        datepickerEl.attr('date-disabled', 'dateDisabled({ date: date, mode: mode })');\n      }\n\n      function parseDate(viewValue) {\n        if (!viewValue) {\n          ngModel.$setValidity('date', true);\n          return null;\n        } else if (angular.isDate(viewValue) && !isNaN(viewValue)) {\n          ngModel.$setValidity('date', true);\n          return viewValue;\n        } else if (angular.isString(viewValue)) {\n          var date = dateParser.parse(viewValue, dateFormat) || new Date(viewValue);\n          if (isNaN(date)) {\n            ngModel.$setValidity('date', false);\n            return undefined;\n          } else {\n            ngModel.$setValidity('date', true);\n            return date;\n          }\n        } else {\n          ngModel.$setValidity('date', false);\n          return undefined;\n        }\n      }\n      ngModel.$parsers.unshift(parseDate);\n\n      // Inner change\n      scope.dateSelection = function(dt) {\n        if (angular.isDefined(dt)) {\n          scope.date = dt;\n        }\n        ngModel.$setViewValue(scope.date);\n        ngModel.$render();\n\n        if ( closeOnDateSelection ) {\n          scope.isOpen = false;\n          element[0].focus();\n        }\n      };\n\n      element.bind('input change keyup', function() {\n        scope.$apply(function() {\n          scope.date = ngModel.$modelValue;\n        });\n      });\n\n      // Outter change\n      ngModel.$render = function() {\n        var date = ngModel.$viewValue ? dateFilter(ngModel.$viewValue, dateFormat) : '';\n        element.val(date);\n        scope.date = parseDate( ngModel.$modelValue );\n      };\n\n      var documentClickBind = function(event) {\n        if (scope.isOpen && event.target !== element[0]) {\n          scope.$apply(function() {\n            scope.isOpen = false;\n          });\n        }\n      };\n\n      var keydown = function(evt, noApply) {\n        scope.keydown(evt);\n      };\n      element.bind('keydown', keydown);\n\n      scope.keydown = function(evt) {\n        if (evt.which === 27) {\n          evt.preventDefault();\n          evt.stopPropagation();\n          scope.close();\n        } else if (evt.which === 40 && !scope.isOpen) {\n          scope.isOpen = true;\n        }\n      };\n\n      scope.$watch('isOpen', function(value) {\n        if (value) {\n          scope.$broadcast('datepicker.focus');\n          scope.position = appendToBody ? $position.offset(element) : $position.position(element);\n          scope.position.top = scope.position.top + element.prop('offsetHeight');\n\n          $document.bind('click', documentClickBind);\n        } else {\n          $document.unbind('click', documentClickBind);\n        }\n      });\n\n      scope.select = function( date ) {\n        if (date === 'today') {\n          var today = new Date();\n          if (angular.isDate(ngModel.$modelValue)) {\n            date = new Date(ngModel.$modelValue);\n            date.setFullYear(today.getFullYear(), today.getMonth(), today.getDate());\n          } else {\n            date = new Date(today.setHours(0, 0, 0, 0));\n          }\n        }\n        scope.dateSelection( date );\n      };\n\n      scope.close = function() {\n        scope.isOpen = false;\n        element[0].focus();\n      };\n\n      var $popup = $compile(popupEl)(scope);\n      // Prevent jQuery cache memory leak (template is now redundant after linking)\n      popupEl.remove();\n\n      if ( appendToBody ) {\n        $document.find('body').append($popup);\n      } else {\n        element.after($popup);\n      }\n\n      scope.$on('$destroy', function() {\n        $popup.remove();\n        element.unbind('keydown', keydown);\n        $document.unbind('click', documentClickBind);\n      });\n    }\n  };\n}])\n\n.directive('datepickerPopupWrap', function() {\n  return {\n    restrict:'EA',\n    replace: true,\n    transclude: true,\n    templateUrl: 'template/datepicker/popup.html',\n    link:function (scope, element, attrs) {\n      element.bind('click', function(event) {\n        event.preventDefault();\n        event.stopPropagation();\n      });\n    }\n  };\n});\n\nangular.module('ui.bootstrap.dropdown', [])\n\n.constant('dropdownConfig', {\n  openClass: 'open'\n})\n\n.service('dropdownService', ['$document', function($document) {\n  var openScope = null;\n\n  this.open = function( dropdownScope ) {\n    if ( !openScope ) {\n      $document.bind('click', closeDropdown);\n      $document.bind('keydown', escapeKeyBind);\n    }\n\n    if ( openScope && openScope !== dropdownScope ) {\n        openScope.isOpen = false;\n    }\n\n    openScope = dropdownScope;\n  };\n\n  this.close = function( dropdownScope ) {\n    if ( openScope === dropdownScope ) {\n      openScope = null;\n      $document.unbind('click', closeDropdown);\n      $document.unbind('keydown', escapeKeyBind);\n    }\n  };\n\n  var closeDropdown = function( evt ) {\n    // This method may still be called during the same mouse event that\n    // unbound this event handler. So check openScope before proceeding.\n    if (!openScope) { return; }\n\n    var toggleElement = openScope.getToggleElement();\n    if ( evt && toggleElement && toggleElement[0].contains(evt.target) ) {\n        return;\n    }\n\n    openScope.$apply(function() {\n      openScope.isOpen = false;\n    });\n  };\n\n  var escapeKeyBind = function( evt ) {\n    if ( evt.which === 27 ) {\n      openScope.focusToggleElement();\n      closeDropdown();\n    }\n  };\n}])\n\n.controller('DropdownController', ['$scope', '$attrs', '$parse', 'dropdownConfig', 'dropdownService', '$animate', function($scope, $attrs, $parse, dropdownConfig, dropdownService, $animate) {\n  var self = this,\n      scope = $scope.$new(), // create a child scope so we are not polluting original one\n      openClass = dropdownConfig.openClass,\n      getIsOpen,\n      setIsOpen = angular.noop,\n      toggleInvoker = $attrs.onToggle ? $parse($attrs.onToggle) : angular.noop;\n\n  this.init = function( element ) {\n    self.$element = element;\n\n    if ( $attrs.isOpen ) {\n      getIsOpen = $parse($attrs.isOpen);\n      setIsOpen = getIsOpen.assign;\n\n      $scope.$watch(getIsOpen, function(value) {\n        scope.isOpen = !!value;\n      });\n    }\n  };\n\n  this.toggle = function( open ) {\n    return scope.isOpen = arguments.length ? !!open : !scope.isOpen;\n  };\n\n  // Allow other directives to watch status\n  this.isOpen = function() {\n    return scope.isOpen;\n  };\n\n  scope.getToggleElement = function() {\n    return self.toggleElement;\n  };\n\n  scope.focusToggleElement = function() {\n    if ( self.toggleElement ) {\n      self.toggleElement[0].focus();\n    }\n  };\n\n  scope.$watch('isOpen', function( isOpen, wasOpen ) {\n    $animate[isOpen ? 'addClass' : 'removeClass'](self.$element, openClass);\n\n    if ( isOpen ) {\n      scope.focusToggleElement();\n      dropdownService.open( scope );\n    } else {\n      dropdownService.close( scope );\n    }\n\n    setIsOpen($scope, isOpen);\n    if (angular.isDefined(isOpen) && isOpen !== wasOpen) {\n      toggleInvoker($scope, { open: !!isOpen });\n    }\n  });\n\n  $scope.$on('$locationChangeSuccess', function() {\n    scope.isOpen = false;\n  });\n\n  $scope.$on('$destroy', function() {\n    scope.$destroy();\n  });\n}])\n\n.directive('dropdown', function() {\n  return {\n    controller: 'DropdownController',\n    link: function(scope, element, attrs, dropdownCtrl) {\n      dropdownCtrl.init( element );\n    }\n  };\n})\n\n.directive('dropdownToggle', function() {\n  return {\n    require: '?^dropdown',\n    link: function(scope, element, attrs, dropdownCtrl) {\n      if ( !dropdownCtrl ) {\n        return;\n      }\n\n      dropdownCtrl.toggleElement = element;\n\n      var toggleDropdown = function(event) {\n        event.preventDefault();\n\n        if ( !element.hasClass('disabled') && !attrs.disabled ) {\n          scope.$apply(function() {\n            dropdownCtrl.toggle();\n          });\n        }\n      };\n\n      element.bind('click', toggleDropdown);\n\n      // WAI-ARIA\n      element.attr({ 'aria-haspopup': true, 'aria-expanded': false });\n      scope.$watch(dropdownCtrl.isOpen, function( isOpen ) {\n        element.attr('aria-expanded', !!isOpen);\n      });\n\n      scope.$on('$destroy', function() {\n        element.unbind('click', toggleDropdown);\n      });\n    }\n  };\n});\n\nangular.module('ui.bootstrap.modal', ['ui.bootstrap.transition'])\n\n/**\n * A helper, internal data structure that acts as a map but also allows getting / removing\n * elements in the LIFO order\n */\n  .factory('$$stackedMap', function () {\n    return {\n      createNew: function () {\n        var stack = [];\n\n        return {\n          add: function (key, value) {\n            stack.push({\n              key: key,\n              value: value\n            });\n          },\n          get: function (key) {\n            for (var i = 0; i < stack.length; i++) {\n              if (key == stack[i].key) {\n                return stack[i];\n              }\n            }\n          },\n          keys: function() {\n            var keys = [];\n            for (var i = 0; i < stack.length; i++) {\n              keys.push(stack[i].key);\n            }\n            return keys;\n          },\n          top: function () {\n            return stack[stack.length - 1];\n          },\n          remove: function (key) {\n            var idx = -1;\n            for (var i = 0; i < stack.length; i++) {\n              if (key == stack[i].key) {\n                idx = i;\n                break;\n              }\n            }\n            return stack.splice(idx, 1)[0];\n          },\n          removeTop: function () {\n            return stack.splice(stack.length - 1, 1)[0];\n          },\n          length: function () {\n            return stack.length;\n          }\n        };\n      }\n    };\n  })\n\n/**\n * A helper directive for the $modal service. It creates a backdrop element.\n */\n  .directive('modalBackdrop', ['$timeout', function ($timeout) {\n    return {\n      restrict: 'EA',\n      replace: true,\n      templateUrl: 'template/modal/backdrop.html',\n      link: function (scope, element, attrs) {\n        scope.backdropClass = attrs.backdropClass || '';\n\n        scope.animate = false;\n\n        //trigger CSS transitions\n        $timeout(function () {\n          scope.animate = true;\n        });\n      }\n    };\n  }])\n\n  .directive('modalWindow', ['$modalStack', '$timeout', function ($modalStack, $timeout) {\n    return {\n      restrict: 'EA',\n      scope: {\n        index: '@',\n        animate: '='\n      },\n      replace: true,\n      transclude: true,\n      templateUrl: function(tElement, tAttrs) {\n        return tAttrs.templateUrl || 'template/modal/window.html';\n      },\n      link: function (scope, element, attrs) {\n        element.addClass(attrs.windowClass || '');\n        scope.size = attrs.size;\n\n        $timeout(function () {\n          // trigger CSS transitions\n          scope.animate = true;\n\n          /**\n           * Auto-focusing of a freshly-opened modal element causes any child elements\n           * with the autofocus attribute to lose focus. This is an issue on touch\n           * based devices which will show and then hide the onscreen keyboard.\n           * Attempts to refocus the autofocus element via JavaScript will not reopen\n           * the onscreen keyboard. Fixed by updated the focusing logic to only autofocus\n           * the modal element if the modal does not contain an autofocus element.\n           */\n          if (!element[0].querySelectorAll('[autofocus]').length) {\n            element[0].focus();\n          }\n        });\n\n        scope.close = function (evt) {\n          var modal = $modalStack.getTop();\n          if (modal && modal.value.backdrop && modal.value.backdrop != 'static' && (evt.target === evt.currentTarget)) {\n            evt.preventDefault();\n            evt.stopPropagation();\n            $modalStack.dismiss(modal.key, 'backdrop click');\n          }\n        };\n      }\n    };\n  }])\n\n  .directive('modalTransclude', function () {\n    return {\n      link: function($scope, $element, $attrs, controller, $transclude) {\n        $transclude($scope.$parent, function(clone) {\n          $element.empty();\n          $element.append(clone);\n        });\n      }\n    };\n  })\n\n  .factory('$modalStack', ['$transition', '$timeout', '$document', '$compile', '$rootScope', '$$stackedMap',\n    function ($transition, $timeout, $document, $compile, $rootScope, $$stackedMap) {\n\n      var OPENED_MODAL_CLASS = 'modal-open';\n\n      var backdropDomEl, backdropScope;\n      var openedWindows = $$stackedMap.createNew();\n      var $modalStack = {};\n\n      function backdropIndex() {\n        var topBackdropIndex = -1;\n        var opened = openedWindows.keys();\n        for (var i = 0; i < opened.length; i++) {\n          if (openedWindows.get(opened[i]).value.backdrop) {\n            topBackdropIndex = i;\n          }\n        }\n        return topBackdropIndex;\n      }\n\n      $rootScope.$watch(backdropIndex, function(newBackdropIndex){\n        if (backdropScope) {\n          backdropScope.index = newBackdropIndex;\n        }\n      });\n\n      function removeModalWindow(modalInstance) {\n\n        var body = $document.find('body').eq(0);\n        var modalWindow = openedWindows.get(modalInstance).value;\n\n        //clean up the stack\n        openedWindows.remove(modalInstance);\n\n        //remove window DOM element\n        removeAfterAnimate(modalWindow.modalDomEl, modalWindow.modalScope, 300, function() {\n          modalWindow.modalScope.$destroy();\n          body.toggleClass(OPENED_MODAL_CLASS, openedWindows.length() > 0);\n          checkRemoveBackdrop();\n        });\n      }\n\n      function checkRemoveBackdrop() {\n          //remove backdrop if no longer needed\n          if (backdropDomEl && backdropIndex() == -1) {\n            var backdropScopeRef = backdropScope;\n            removeAfterAnimate(backdropDomEl, backdropScope, 150, function () {\n              backdropScopeRef.$destroy();\n              backdropScopeRef = null;\n            });\n            backdropDomEl = undefined;\n            backdropScope = undefined;\n          }\n      }\n\n      function removeAfterAnimate(domEl, scope, emulateTime, done) {\n        // Closing animation\n        scope.animate = false;\n\n        var transitionEndEventName = $transition.transitionEndEventName;\n        if (transitionEndEventName) {\n          // transition out\n          var timeout = $timeout(afterAnimating, emulateTime);\n\n          domEl.bind(transitionEndEventName, function () {\n            $timeout.cancel(timeout);\n            afterAnimating();\n            scope.$apply();\n          });\n        } else {\n          // Ensure this call is async\n          $timeout(afterAnimating);\n        }\n\n        function afterAnimating() {\n          if (afterAnimating.done) {\n            return;\n          }\n          afterAnimating.done = true;\n\n          domEl.remove();\n          if (done) {\n            done();\n          }\n        }\n      }\n\n      $document.bind('keydown', function (evt) {\n        var modal;\n\n        if (evt.which === 27) {\n          modal = openedWindows.top();\n          if (modal && modal.value.keyboard) {\n            evt.preventDefault();\n            $rootScope.$apply(function () {\n              $modalStack.dismiss(modal.key, 'escape key press');\n            });\n          }\n        }\n      });\n\n      $modalStack.open = function (modalInstance, modal) {\n\n        openedWindows.add(modalInstance, {\n          deferred: modal.deferred,\n          modalScope: modal.scope,\n          backdrop: modal.backdrop,\n          keyboard: modal.keyboard\n        });\n\n        var body = $document.find('body').eq(0),\n            currBackdropIndex = backdropIndex();\n\n        if (currBackdropIndex >= 0 && !backdropDomEl) {\n          backdropScope = $rootScope.$new(true);\n          backdropScope.index = currBackdropIndex;\n          var angularBackgroundDomEl = angular.element('<div modal-backdrop></div>');\n          angularBackgroundDomEl.attr('backdrop-class', modal.backdropClass);\n          backdropDomEl = $compile(angularBackgroundDomEl)(backdropScope);\n          body.append(backdropDomEl);\n        }\n\n        var angularDomEl = angular.element('<div modal-window></div>');\n        angularDomEl.attr({\n          'template-url': modal.windowTemplateUrl,\n          'window-class': modal.windowClass,\n          'size': modal.size,\n          'index': openedWindows.length() - 1,\n          'animate': 'animate'\n        }).html(modal.content);\n\n        var modalDomEl = $compile(angularDomEl)(modal.scope);\n        openedWindows.top().value.modalDomEl = modalDomEl;\n        body.append(modalDomEl);\n        body.addClass(OPENED_MODAL_CLASS);\n      };\n\n      $modalStack.close = function (modalInstance, result) {\n        var modalWindow = openedWindows.get(modalInstance);\n        if (modalWindow) {\n          modalWindow.value.deferred.resolve(result);\n          removeModalWindow(modalInstance);\n        }\n      };\n\n      $modalStack.dismiss = function (modalInstance, reason) {\n        var modalWindow = openedWindows.get(modalInstance);\n        if (modalWindow) {\n          modalWindow.value.deferred.reject(reason);\n          removeModalWindow(modalInstance);\n        }\n      };\n\n      $modalStack.dismissAll = function (reason) {\n        var topModal = this.getTop();\n        while (topModal) {\n          this.dismiss(topModal.key, reason);\n          topModal = this.getTop();\n        }\n      };\n\n      $modalStack.getTop = function () {\n        return openedWindows.top();\n      };\n\n      return $modalStack;\n    }])\n\n  .provider('$modal', function () {\n\n    var $modalProvider = {\n      options: {\n        backdrop: true, //can be also false or 'static'\n        keyboard: true\n      },\n      $get: ['$injector', '$rootScope', '$q', '$http', '$templateCache', '$controller', '$modalStack',\n        function ($injector, $rootScope, $q, $http, $templateCache, $controller, $modalStack) {\n\n          var $modal = {};\n\n          function getTemplatePromise(options) {\n            return options.template ? $q.when(options.template) :\n              $http.get(angular.isFunction(options.templateUrl) ? (options.templateUrl)() : options.templateUrl,\n                {cache: $templateCache}).then(function (result) {\n                  return result.data;\n              });\n          }\n\n          function getResolvePromises(resolves) {\n            var promisesArr = [];\n            angular.forEach(resolves, function (value) {\n              if (angular.isFunction(value) || angular.isArray(value)) {\n                promisesArr.push($q.when($injector.invoke(value)));\n              }\n            });\n            return promisesArr;\n          }\n\n          $modal.open = function (modalOptions) {\n\n            var modalResultDeferred = $q.defer();\n            var modalOpenedDeferred = $q.defer();\n\n            //prepare an instance of a modal to be injected into controllers and returned to a caller\n            var modalInstance = {\n              result: modalResultDeferred.promise,\n              opened: modalOpenedDeferred.promise,\n              close: function (result) {\n                $modalStack.close(modalInstance, result);\n              },\n              dismiss: function (reason) {\n                $modalStack.dismiss(modalInstance, reason);\n              }\n            };\n\n            //merge and clean up options\n            modalOptions = angular.extend({}, $modalProvider.options, modalOptions);\n            modalOptions.resolve = modalOptions.resolve || {};\n\n            //verify options\n            if (!modalOptions.template && !modalOptions.templateUrl) {\n              throw new Error('One of template or templateUrl options is required.');\n            }\n\n            var templateAndResolvePromise =\n              $q.all([getTemplatePromise(modalOptions)].concat(getResolvePromises(modalOptions.resolve)));\n\n\n            templateAndResolvePromise.then(function resolveSuccess(tplAndVars) {\n\n              var modalScope = (modalOptions.scope || $rootScope).$new();\n              modalScope.$close = modalInstance.close;\n              modalScope.$dismiss = modalInstance.dismiss;\n\n              var ctrlInstance, ctrlLocals = {};\n              var resolveIter = 1;\n\n              //controllers\n              if (modalOptions.controller) {\n                ctrlLocals.$scope = modalScope;\n                ctrlLocals.$modalInstance = modalInstance;\n                angular.forEach(modalOptions.resolve, function (value, key) {\n                  ctrlLocals[key] = tplAndVars[resolveIter++];\n                });\n\n                ctrlInstance = $controller(modalOptions.controller, ctrlLocals);\n                if (modalOptions.controllerAs) {\n                  modalScope[modalOptions.controllerAs] = ctrlInstance;\n                }\n              }\n\n              $modalStack.open(modalInstance, {\n                scope: modalScope,\n                deferred: modalResultDeferred,\n                content: tplAndVars[0],\n                backdrop: modalOptions.backdrop,\n                keyboard: modalOptions.keyboard,\n                backdropClass: modalOptions.backdropClass,\n                windowClass: modalOptions.windowClass,\n                windowTemplateUrl: modalOptions.windowTemplateUrl,\n                size: modalOptions.size\n              });\n\n            }, function resolveError(reason) {\n              modalResultDeferred.reject(reason);\n            });\n\n            templateAndResolvePromise.then(function () {\n              modalOpenedDeferred.resolve(true);\n            }, function () {\n              modalOpenedDeferred.reject(false);\n            });\n\n            return modalInstance;\n          };\n\n          return $modal;\n        }]\n    };\n\n    return $modalProvider;\n  });\n\nangular.module('ui.bootstrap.pagination', [])\n\n.controller('PaginationController', ['$scope', '$attrs', '$parse', function ($scope, $attrs, $parse) {\n  var self = this,\n      ngModelCtrl = { $setViewValue: angular.noop }, // nullModelCtrl\n      setNumPages = $attrs.numPages ? $parse($attrs.numPages).assign : angular.noop;\n\n  this.init = function(ngModelCtrl_, config) {\n    ngModelCtrl = ngModelCtrl_;\n    this.config = config;\n\n    ngModelCtrl.$render = function() {\n      self.render();\n    };\n\n    if ($attrs.itemsPerPage) {\n      $scope.$parent.$watch($parse($attrs.itemsPerPage), function(value) {\n        self.itemsPerPage = parseInt(value, 10);\n        $scope.totalPages = self.calculateTotalPages();\n      });\n    } else {\n      this.itemsPerPage = config.itemsPerPage;\n    }\n  };\n\n  this.calculateTotalPages = function() {\n    var totalPages = this.itemsPerPage < 1 ? 1 : Math.ceil($scope.totalItems / this.itemsPerPage);\n    return Math.max(totalPages || 0, 1);\n  };\n\n  this.render = function() {\n    $scope.page = parseInt(ngModelCtrl.$viewValue, 10) || 1;\n  };\n\n  $scope.selectPage = function(page) {\n    if ( $scope.page !== page && page > 0 && page <= $scope.totalPages) {\n      ngModelCtrl.$setViewValue(page);\n      ngModelCtrl.$render();\n    }\n  };\n\n  $scope.getText = function( key ) {\n    return $scope[key + 'Text'] || self.config[key + 'Text'];\n  };\n  $scope.noPrevious = function() {\n    return $scope.page === 1;\n  };\n  $scope.noNext = function() {\n    return $scope.page === $scope.totalPages;\n  };\n\n  $scope.$watch('totalItems', function() {\n    $scope.totalPages = self.calculateTotalPages();\n  });\n\n  $scope.$watch('totalPages', function(value) {\n    setNumPages($scope.$parent, value); // Readonly variable\n\n    if ( $scope.page > value ) {\n      $scope.selectPage(value);\n    } else {\n      ngModelCtrl.$render();\n    }\n  });\n}])\n\n.constant('paginationConfig', {\n  itemsPerPage: 10,\n  boundaryLinks: false,\n  directionLinks: true,\n  firstText: 'First',\n  previousText: 'Previous',\n  nextText: 'Next',\n  lastText: 'Last',\n  rotate: true\n})\n\n.directive('pagination', ['$parse', 'paginationConfig', function($parse, paginationConfig) {\n  return {\n    restrict: 'EA',\n    scope: {\n      totalItems: '=',\n      firstText: '@',\n      previousText: '@',\n      nextText: '@',\n      lastText: '@'\n    },\n    require: ['pagination', '?ngModel'],\n    controller: 'PaginationController',\n    templateUrl: 'template/pagination/pagination.html',\n    replace: true,\n    link: function(scope, element, attrs, ctrls) {\n      var paginationCtrl = ctrls[0], ngModelCtrl = ctrls[1];\n\n      if (!ngModelCtrl) {\n         return; // do nothing if no ng-model\n      }\n\n      // Setup configuration parameters\n      var maxSize = angular.isDefined(attrs.maxSize) ? scope.$parent.$eval(attrs.maxSize) : paginationConfig.maxSize,\n          rotate = angular.isDefined(attrs.rotate) ? scope.$parent.$eval(attrs.rotate) : paginationConfig.rotate;\n      scope.boundaryLinks = angular.isDefined(attrs.boundaryLinks) ? scope.$parent.$eval(attrs.boundaryLinks) : paginationConfig.boundaryLinks;\n      scope.directionLinks = angular.isDefined(attrs.directionLinks) ? scope.$parent.$eval(attrs.directionLinks) : paginationConfig.directionLinks;\n\n      paginationCtrl.init(ngModelCtrl, paginationConfig);\n\n      if (attrs.maxSize) {\n        scope.$parent.$watch($parse(attrs.maxSize), function(value) {\n          maxSize = parseInt(value, 10);\n          paginationCtrl.render();\n        });\n      }\n\n      // Create page object used in template\n      function makePage(number, text, isActive) {\n        return {\n          number: number,\n          text: text,\n          active: isActive\n        };\n      }\n\n      function getPages(currentPage, totalPages) {\n        var pages = [];\n\n        // Default page limits\n        var startPage = 1, endPage = totalPages;\n        var isMaxSized = ( angular.isDefined(maxSize) && maxSize < totalPages );\n\n        // recompute if maxSize\n        if ( isMaxSized ) {\n          if ( rotate ) {\n            // Current page is displayed in the middle of the visible ones\n            startPage = Math.max(currentPage - Math.floor(maxSize/2), 1);\n            endPage   = startPage + maxSize - 1;\n\n            // Adjust if limit is exceeded\n            if (endPage > totalPages) {\n              endPage   = totalPages;\n              startPage = endPage - maxSize + 1;\n            }\n          } else {\n            // Visible pages are paginated with maxSize\n            startPage = ((Math.ceil(currentPage / maxSize) - 1) * maxSize) + 1;\n\n            // Adjust last page if limit is exceeded\n            endPage = Math.min(startPage + maxSize - 1, totalPages);\n          }\n        }\n\n        // Add page number links\n        for (var number = startPage; number <= endPage; number++) {\n          var page = makePage(number, number, number === currentPage);\n          pages.push(page);\n        }\n\n        // Add links to move between page sets\n        if ( isMaxSized && ! rotate ) {\n          if ( startPage > 1 ) {\n            var previousPageSet = makePage(startPage - 1, '...', false);\n            pages.unshift(previousPageSet);\n          }\n\n          if ( endPage < totalPages ) {\n            var nextPageSet = makePage(endPage + 1, '...', false);\n            pages.push(nextPageSet);\n          }\n        }\n\n        return pages;\n      }\n\n      var originalRender = paginationCtrl.render;\n      paginationCtrl.render = function() {\n        originalRender();\n        if (scope.page > 0 && scope.page <= scope.totalPages) {\n          scope.pages = getPages(scope.page, scope.totalPages);\n        }\n      };\n    }\n  };\n}])\n\n.constant('pagerConfig', {\n  itemsPerPage: 10,\n  previousText: '« Previous',\n  nextText: 'Next »',\n  align: true\n})\n\n.directive('pager', ['pagerConfig', function(pagerConfig) {\n  return {\n    restrict: 'EA',\n    scope: {\n      totalItems: '=',\n      previousText: '@',\n      nextText: '@'\n    },\n    require: ['pager', '?ngModel'],\n    controller: 'PaginationController',\n    templateUrl: 'template/pagination/pager.html',\n    replace: true,\n    link: function(scope, element, attrs, ctrls) {\n      var paginationCtrl = ctrls[0], ngModelCtrl = ctrls[1];\n\n      if (!ngModelCtrl) {\n         return; // do nothing if no ng-model\n      }\n\n      scope.align = angular.isDefined(attrs.align) ? scope.$parent.$eval(attrs.align) : pagerConfig.align;\n      paginationCtrl.init(ngModelCtrl, pagerConfig);\n    }\n  };\n}]);\n\n/**\n * The following features are still outstanding: animation as a\n * function, placement as a function, inside, support for more triggers than\n * just mouse enter/leave, html tooltips, and selector delegation.\n */\nangular.module( 'ui.bootstrap.tooltip', [ 'ui.bootstrap.position', 'ui.bootstrap.bindHtml' ] )\n\n/**\n * The $tooltip service creates tooltip- and popover-like directives as well as\n * houses global options for them.\n */\n.provider( '$tooltip', function () {\n  // The default options tooltip and popover.\n  var defaultOptions = {\n    placement: 'top',\n    animation: true,\n    popupDelay: 0\n  };\n\n  // Default hide triggers for each show trigger\n  var triggerMap = {\n    'mouseenter': 'mouseleave',\n    'click': 'click',\n    'focus': 'blur'\n  };\n\n  // The options specified to the provider globally.\n  var globalOptions = {};\n\n  /**\n   * `options({})` allows global configuration of all tooltips in the\n   * application.\n   *\n   *   var app = angular.module( 'App', ['ui.bootstrap.tooltip'], function( $tooltipProvider ) {\n   *     // place tooltips left instead of top by default\n   *     $tooltipProvider.options( { placement: 'left' } );\n   *   });\n   */\n\tthis.options = function( value ) {\n\t\tangular.extend( globalOptions, value );\n\t};\n\n  /**\n   * This allows you to extend the set of trigger mappings available. E.g.:\n   *\n   *   $tooltipProvider.setTriggers( 'openTrigger': 'closeTrigger' );\n   */\n  this.setTriggers = function setTriggers ( triggers ) {\n    angular.extend( triggerMap, triggers );\n  };\n\n  /**\n   * This is a helper function for translating camel-case to snake-case.\n   */\n  function snake_case(name){\n    var regexp = /[A-Z]/g;\n    var separator = '-';\n    return name.replace(regexp, function(letter, pos) {\n      return (pos ? separator : '') + letter.toLowerCase();\n    });\n  }\n\n  /**\n   * Returns the actual instance of the $tooltip service.\n   * TODO support multiple triggers\n   */\n  this.$get = [ '$window', '$compile', '$timeout', '$document', '$position', '$interpolate', function ( $window, $compile, $timeout, $document, $position, $interpolate ) {\n    return function $tooltip ( type, prefix, defaultTriggerShow ) {\n      var options = angular.extend( {}, defaultOptions, globalOptions );\n\n      /**\n       * Returns an object of show and hide triggers.\n       *\n       * If a trigger is supplied,\n       * it is used to show the tooltip; otherwise, it will use the `trigger`\n       * option passed to the `$tooltipProvider.options` method; else it will\n       * default to the trigger supplied to this directive factory.\n       *\n       * The hide trigger is based on the show trigger. If the `trigger` option\n       * was passed to the `$tooltipProvider.options` method, it will use the\n       * mapped trigger from `triggerMap` or the passed trigger if the map is\n       * undefined; otherwise, it uses the `triggerMap` value of the show\n       * trigger; else it will just use the show trigger.\n       */\n      function getTriggers ( trigger ) {\n        var show = trigger || options.trigger || defaultTriggerShow;\n        var hide = triggerMap[show] || show;\n        return {\n          show: show,\n          hide: hide\n        };\n      }\n\n      var directiveName = snake_case( type );\n\n      var startSym = $interpolate.startSymbol();\n      var endSym = $interpolate.endSymbol();\n      var template =\n        '<div '+ directiveName +'-popup '+\n          'title=\"'+startSym+'title'+endSym+'\" '+\n          'content=\"'+startSym+'content'+endSym+'\" '+\n          'placement=\"'+startSym+'placement'+endSym+'\" '+\n          'animation=\"animation\" '+\n          'is-open=\"isOpen\"'+\n          '>'+\n        '</div>';\n\n      return {\n        restrict: 'EA',\n        compile: function (tElem, tAttrs) {\n          var tooltipLinker = $compile( template );\n\n          return function link ( scope, element, attrs ) {\n            var tooltip;\n            var tooltipLinkedScope;\n            var transitionTimeout;\n            var popupTimeout;\n            var appendToBody = angular.isDefined( options.appendToBody ) ? options.appendToBody : false;\n            var triggers = getTriggers( undefined );\n            var hasEnableExp = angular.isDefined(attrs[prefix+'Enable']);\n            var ttScope = scope.$new(true);\n\n            var positionTooltip = function () {\n\n              var ttPosition = $position.positionElements(element, tooltip, ttScope.placement, appendToBody);\n              ttPosition.top += 'px';\n              ttPosition.left += 'px';\n\n              // Now set the calculated positioning.\n              tooltip.css( ttPosition );\n            };\n\n            // By default, the tooltip is not open.\n            // TODO add ability to start tooltip opened\n            ttScope.isOpen = false;\n\n            function toggleTooltipBind () {\n              if ( ! ttScope.isOpen ) {\n                showTooltipBind();\n              } else {\n                hideTooltipBind();\n              }\n            }\n\n            // Show the tooltip with delay if specified, otherwise show it immediately\n            function showTooltipBind() {\n              if(hasEnableExp && !scope.$eval(attrs[prefix+'Enable'])) {\n                return;\n              }\n\n              prepareTooltip();\n\n              if ( ttScope.popupDelay ) {\n                // Do nothing if the tooltip was already scheduled to pop-up.\n                // This happens if show is triggered multiple times before any hide is triggered.\n                if (!popupTimeout) {\n                  popupTimeout = $timeout( show, ttScope.popupDelay, false );\n                  popupTimeout.then(function(reposition){reposition();});\n                }\n              } else {\n                show()();\n              }\n            }\n\n            function hideTooltipBind () {\n              scope.$apply(function () {\n                hide();\n              });\n            }\n\n            // Show the tooltip popup element.\n            function show() {\n\n              popupTimeout = null;\n\n              // If there is a pending remove transition, we must cancel it, lest the\n              // tooltip be mysteriously removed.\n              if ( transitionTimeout ) {\n                $timeout.cancel( transitionTimeout );\n                transitionTimeout = null;\n              }\n\n              // Don't show empty tooltips.\n              if ( ! ttScope.content ) {\n                return angular.noop;\n              }\n\n              createTooltip();\n\n              // Set the initial positioning.\n              tooltip.css({ top: 0, left: 0, display: 'block' });\n\n              // Now we add it to the DOM because need some info about it. But it's not\n              // visible yet anyway.\n              if ( appendToBody ) {\n                  $document.find( 'body' ).append( tooltip );\n              } else {\n                element.after( tooltip );\n              }\n\n              positionTooltip();\n\n              // And show the tooltip.\n              ttScope.isOpen = true;\n              ttScope.$digest(); // digest required as $apply is not called\n\n              // Return positioning function as promise callback for correct\n              // positioning after draw.\n              return positionTooltip;\n            }\n\n            // Hide the tooltip popup element.\n            function hide() {\n              // First things first: we don't show it anymore.\n              ttScope.isOpen = false;\n\n              //if tooltip is going to be shown after delay, we must cancel this\n              $timeout.cancel( popupTimeout );\n              popupTimeout = null;\n\n              // And now we remove it from the DOM. However, if we have animation, we\n              // need to wait for it to expire beforehand.\n              // FIXME: this is a placeholder for a port of the transitions library.\n              if ( ttScope.animation ) {\n                if (!transitionTimeout) {\n                  transitionTimeout = $timeout(removeTooltip, 500);\n                }\n              } else {\n                removeTooltip();\n              }\n            }\n\n            function createTooltip() {\n              // There can only be one tooltip element per directive shown at once.\n              if (tooltip) {\n                removeTooltip();\n              }\n              tooltipLinkedScope = ttScope.$new();\n              tooltip = tooltipLinker(tooltipLinkedScope, angular.noop);\n            }\n\n            function removeTooltip() {\n              transitionTimeout = null;\n              if (tooltip) {\n                tooltip.remove();\n                tooltip = null;\n              }\n              if (tooltipLinkedScope) {\n                tooltipLinkedScope.$destroy();\n                tooltipLinkedScope = null;\n              }\n            }\n\n            function prepareTooltip() {\n              prepPlacement();\n              prepPopupDelay();\n            }\n\n            /**\n             * Observe the relevant attributes.\n             */\n            attrs.$observe( type, function ( val ) {\n              ttScope.content = val;\n\n              if (!val && ttScope.isOpen ) {\n                hide();\n              }\n            });\n\n            attrs.$observe( prefix+'Title', function ( val ) {\n              ttScope.title = val;\n            });\n\n            function prepPlacement() {\n              var val = attrs[ prefix + 'Placement' ];\n              ttScope.placement = angular.isDefined( val ) ? val : options.placement;\n            }\n\n            function prepPopupDelay() {\n              var val = attrs[ prefix + 'PopupDelay' ];\n              var delay = parseInt( val, 10 );\n              ttScope.popupDelay = ! isNaN(delay) ? delay : options.popupDelay;\n            }\n\n            var unregisterTriggers = function () {\n              element.unbind(triggers.show, showTooltipBind);\n              element.unbind(triggers.hide, hideTooltipBind);\n            };\n\n            function prepTriggers() {\n              var val = attrs[ prefix + 'Trigger' ];\n              unregisterTriggers();\n\n              triggers = getTriggers( val );\n\n              if ( triggers.show === triggers.hide ) {\n                element.bind( triggers.show, toggleTooltipBind );\n              } else {\n                element.bind( triggers.show, showTooltipBind );\n                element.bind( triggers.hide, hideTooltipBind );\n              }\n            }\n            prepTriggers();\n\n            var animation = scope.$eval(attrs[prefix + 'Animation']);\n            ttScope.animation = angular.isDefined(animation) ? !!animation : options.animation;\n\n            var appendToBodyVal = scope.$eval(attrs[prefix + 'AppendToBody']);\n            appendToBody = angular.isDefined(appendToBodyVal) ? appendToBodyVal : appendToBody;\n\n            // if a tooltip is attached to <body> we need to remove it on\n            // location change as its parent scope will probably not be destroyed\n            // by the change.\n            if ( appendToBody ) {\n              scope.$on('$locationChangeSuccess', function closeTooltipOnLocationChangeSuccess () {\n              if ( ttScope.isOpen ) {\n                hide();\n              }\n            });\n            }\n\n            // Make sure tooltip is destroyed and removed.\n            scope.$on('$destroy', function onDestroyTooltip() {\n              $timeout.cancel( transitionTimeout );\n              $timeout.cancel( popupTimeout );\n              unregisterTriggers();\n              removeTooltip();\n              ttScope = null;\n            });\n          };\n        }\n      };\n    };\n  }];\n})\n\n.directive( 'tooltipPopup', function () {\n  return {\n    restrict: 'EA',\n    replace: true,\n    scope: { content: '@', placement: '@', animation: '&', isOpen: '&' },\n    templateUrl: 'template/tooltip/tooltip-popup.html'\n  };\n})\n\n.directive( 'tooltip', [ '$tooltip', function ( $tooltip ) {\n  return $tooltip( 'tooltip', 'tooltip', 'mouseenter' );\n}])\n\n.directive( 'tooltipHtmlUnsafePopup', function () {\n  return {\n    restrict: 'EA',\n    replace: true,\n    scope: { content: '@', placement: '@', animation: '&', isOpen: '&' },\n    templateUrl: 'template/tooltip/tooltip-html-unsafe-popup.html'\n  };\n})\n\n.directive( 'tooltipHtmlUnsafe', [ '$tooltip', function ( $tooltip ) {\n  return $tooltip( 'tooltipHtmlUnsafe', 'tooltip', 'mouseenter' );\n}]);\n\n/**\n * The following features are still outstanding: popup delay, animation as a\n * function, placement as a function, inside, support for more triggers than\n * just mouse enter/leave, html popovers, and selector delegatation.\n */\nangular.module( 'ui.bootstrap.popover', [ 'ui.bootstrap.tooltip' ] )\n\n.directive( 'popoverPopup', function () {\n  return {\n    restrict: 'EA',\n    replace: true,\n    scope: { title: '@', content: '@', placement: '@', animation: '&', isOpen: '&' },\n    templateUrl: 'template/popover/popover.html'\n  };\n})\n\n.directive( 'popover', [ '$tooltip', function ( $tooltip ) {\n  return $tooltip( 'popover', 'popover', 'click' );\n}]);\n\nangular.module('ui.bootstrap.progressbar', [])\n\n.constant('progressConfig', {\n  animate: true,\n  max: 100\n})\n\n.controller('ProgressController', ['$scope', '$attrs', 'progressConfig', function($scope, $attrs, progressConfig) {\n    var self = this,\n        animate = angular.isDefined($attrs.animate) ? $scope.$parent.$eval($attrs.animate) : progressConfig.animate;\n\n    this.bars = [];\n    $scope.max = angular.isDefined($attrs.max) ? $scope.$parent.$eval($attrs.max) : progressConfig.max;\n\n    this.addBar = function(bar, element) {\n        if ( !animate ) {\n            element.css({'transition': 'none'});\n        }\n\n        this.bars.push(bar);\n\n        bar.$watch('value', function( value ) {\n            bar.percent = +(100 * value / $scope.max).toFixed(2);\n        });\n\n        bar.$on('$destroy', function() {\n            element = null;\n            self.removeBar(bar);\n        });\n    };\n\n    this.removeBar = function(bar) {\n        this.bars.splice(this.bars.indexOf(bar), 1);\n    };\n}])\n\n.directive('progress', function() {\n    return {\n        restrict: 'EA',\n        replace: true,\n        transclude: true,\n        controller: 'ProgressController',\n        require: 'progress',\n        scope: {},\n        templateUrl: 'template/progressbar/progress.html'\n    };\n})\n\n.directive('bar', function() {\n    return {\n        restrict: 'EA',\n        replace: true,\n        transclude: true,\n        require: '^progress',\n        scope: {\n            value: '=',\n            type: '@'\n        },\n        templateUrl: 'template/progressbar/bar.html',\n        link: function(scope, element, attrs, progressCtrl) {\n            progressCtrl.addBar(scope, element);\n        }\n    };\n})\n\n.directive('progressbar', function() {\n    return {\n        restrict: 'EA',\n        replace: true,\n        transclude: true,\n        controller: 'ProgressController',\n        scope: {\n            value: '=',\n            type: '@'\n        },\n        templateUrl: 'template/progressbar/progressbar.html',\n        link: function(scope, element, attrs, progressCtrl) {\n            progressCtrl.addBar(scope, angular.element(element.children()[0]));\n        }\n    };\n});\nangular.module('ui.bootstrap.rating', [])\n\n.constant('ratingConfig', {\n  max: 5,\n  stateOn: null,\n  stateOff: null\n})\n\n.controller('RatingController', ['$scope', '$attrs', 'ratingConfig', function($scope, $attrs, ratingConfig) {\n  var ngModelCtrl  = { $setViewValue: angular.noop };\n\n  this.init = function(ngModelCtrl_) {\n    ngModelCtrl = ngModelCtrl_;\n    ngModelCtrl.$render = this.render;\n\n    this.stateOn = angular.isDefined($attrs.stateOn) ? $scope.$parent.$eval($attrs.stateOn) : ratingConfig.stateOn;\n    this.stateOff = angular.isDefined($attrs.stateOff) ? $scope.$parent.$eval($attrs.stateOff) : ratingConfig.stateOff;\n\n    var ratingStates = angular.isDefined($attrs.ratingStates) ? $scope.$parent.$eval($attrs.ratingStates) :\n                        new Array( angular.isDefined($attrs.max) ? $scope.$parent.$eval($attrs.max) : ratingConfig.max );\n    $scope.range = this.buildTemplateObjects(ratingStates);\n  };\n\n  this.buildTemplateObjects = function(states) {\n    for (var i = 0, n = states.length; i < n; i++) {\n      states[i] = angular.extend({ index: i }, { stateOn: this.stateOn, stateOff: this.stateOff }, states[i]);\n    }\n    return states;\n  };\n\n  $scope.rate = function(value) {\n    if ( !$scope.readonly && value >= 0 && value <= $scope.range.length ) {\n      ngModelCtrl.$setViewValue(value);\n      ngModelCtrl.$render();\n    }\n  };\n\n  $scope.enter = function(value) {\n    if ( !$scope.readonly ) {\n      $scope.value = value;\n    }\n    $scope.onHover({value: value});\n  };\n\n  $scope.reset = function() {\n    $scope.value = ngModelCtrl.$viewValue;\n    $scope.onLeave();\n  };\n\n  $scope.onKeydown = function(evt) {\n    if (/(37|38|39|40)/.test(evt.which)) {\n      evt.preventDefault();\n      evt.stopPropagation();\n      $scope.rate( $scope.value + (evt.which === 38 || evt.which === 39 ? 1 : -1) );\n    }\n  };\n\n  this.render = function() {\n    $scope.value = ngModelCtrl.$viewValue;\n  };\n}])\n\n.directive('rating', function() {\n  return {\n    restrict: 'EA',\n    require: ['rating', 'ngModel'],\n    scope: {\n      readonly: '=?',\n      onHover: '&',\n      onLeave: '&'\n    },\n    controller: 'RatingController',\n    templateUrl: 'template/rating/rating.html',\n    replace: true,\n    link: function(scope, element, attrs, ctrls) {\n      var ratingCtrl = ctrls[0], ngModelCtrl = ctrls[1];\n\n      if ( ngModelCtrl ) {\n        ratingCtrl.init( ngModelCtrl );\n      }\n    }\n  };\n});\n\n/**\n * @ngdoc overview\n * @name ui.bootstrap.tabs\n *\n * @description\n * AngularJS version of the tabs directive.\n */\n\nangular.module('ui.bootstrap.tabs', [])\n\n.controller('TabsetController', ['$scope', function TabsetCtrl($scope) {\n  var ctrl = this,\n      tabs = ctrl.tabs = $scope.tabs = [];\n\n  ctrl.select = function(selectedTab) {\n    angular.forEach(tabs, function(tab) {\n      if (tab.active && tab !== selectedTab) {\n        tab.active = false;\n        tab.onDeselect();\n      }\n    });\n    selectedTab.active = true;\n    selectedTab.onSelect();\n  };\n\n  ctrl.addTab = function addTab(tab) {\n    tabs.push(tab);\n    // we can't run the select function on the first tab\n    // since that would select it twice\n    if (tabs.length === 1) {\n      tab.active = true;\n    } else if (tab.active) {\n      ctrl.select(tab);\n    }\n  };\n\n  ctrl.removeTab = function removeTab(tab) {\n    var index = tabs.indexOf(tab);\n    //Select a new tab if the tab to be removed is selected and not destroyed\n    if (tab.active && tabs.length > 1 && !destroyed) {\n      //If this is the last tab, select the previous tab. else, the next tab.\n      var newActiveIndex = index == tabs.length - 1 ? index - 1 : index + 1;\n      ctrl.select(tabs[newActiveIndex]);\n    }\n    tabs.splice(index, 1);\n  };\n\n  var destroyed;\n  $scope.$on('$destroy', function() {\n    destroyed = true;\n  });\n}])\n\n/**\n * @ngdoc directive\n * @name ui.bootstrap.tabs.directive:tabset\n * @restrict EA\n *\n * @description\n * Tabset is the outer container for the tabs directive\n *\n * @param {boolean=} vertical Whether or not to use vertical styling for the tabs.\n * @param {boolean=} justified Whether or not to use justified styling for the tabs.\n *\n * @example\n<example module=\"ui.bootstrap\">\n  <file name=\"index.html\">\n    <tabset>\n      <tab heading=\"Tab 1\"><b>First</b> Content!</tab>\n      <tab heading=\"Tab 2\"><i>Second</i> Content!</tab>\n    </tabset>\n    <hr />\n    <tabset vertical=\"true\">\n      <tab heading=\"Vertical Tab 1\"><b>First</b> Vertical Content!</tab>\n      <tab heading=\"Vertical Tab 2\"><i>Second</i> Vertical Content!</tab>\n    </tabset>\n    <tabset justified=\"true\">\n      <tab heading=\"Justified Tab 1\"><b>First</b> Justified Content!</tab>\n      <tab heading=\"Justified Tab 2\"><i>Second</i> Justified Content!</tab>\n    </tabset>\n  </file>\n</example>\n */\n.directive('tabset', function() {\n  return {\n    restrict: 'EA',\n    transclude: true,\n    replace: true,\n    scope: {\n      type: '@'\n    },\n    controller: 'TabsetController',\n    templateUrl: 'template/tabs/tabset.html',\n    link: function(scope, element, attrs) {\n      scope.vertical = angular.isDefined(attrs.vertical) ? scope.$parent.$eval(attrs.vertical) : false;\n      scope.justified = angular.isDefined(attrs.justified) ? scope.$parent.$eval(attrs.justified) : false;\n    }\n  };\n})\n\n/**\n * @ngdoc directive\n * @name ui.bootstrap.tabs.directive:tab\n * @restrict EA\n *\n * @param {string=} heading The visible heading, or title, of the tab. Set HTML headings with {@link ui.bootstrap.tabs.directive:tabHeading tabHeading}.\n * @param {string=} select An expression to evaluate when the tab is selected.\n * @param {boolean=} active A binding, telling whether or not this tab is selected.\n * @param {boolean=} disabled A binding, telling whether or not this tab is disabled.\n *\n * @description\n * Creates a tab with a heading and content. Must be placed within a {@link ui.bootstrap.tabs.directive:tabset tabset}.\n *\n * @example\n<example module=\"ui.bootstrap\">\n  <file name=\"index.html\">\n    <div ng-controller=\"TabsDemoCtrl\">\n      <button class=\"btn btn-small\" ng-click=\"items[0].active = true\">\n        Select item 1, using active binding\n      </button>\n      <button class=\"btn btn-small\" ng-click=\"items[1].disabled = !items[1].disabled\">\n        Enable/disable item 2, using disabled binding\n      </button>\n      <br />\n      <tabset>\n        <tab heading=\"Tab 1\">First Tab</tab>\n        <tab select=\"alertMe()\">\n          <tab-heading><i class=\"icon-bell\"></i> Alert me!</tab-heading>\n          Second Tab, with alert callback and html heading!\n        </tab>\n        <tab ng-repeat=\"item in items\"\n          heading=\"{{item.title}}\"\n          disabled=\"item.disabled\"\n          active=\"item.active\">\n          {{item.content}}\n        </tab>\n      </tabset>\n    </div>\n  </file>\n  <file name=\"script.js\">\n    function TabsDemoCtrl($scope) {\n      $scope.items = [\n        { title:\"Dynamic Title 1\", content:\"Dynamic Item 0\" },\n        { title:\"Dynamic Title 2\", content:\"Dynamic Item 1\", disabled: true }\n      ];\n\n      $scope.alertMe = function() {\n        setTimeout(function() {\n          alert(\"You've selected the alert tab!\");\n        });\n      };\n    };\n  </file>\n</example>\n */\n\n/**\n * @ngdoc directive\n * @name ui.bootstrap.tabs.directive:tabHeading\n * @restrict EA\n *\n * @description\n * Creates an HTML heading for a {@link ui.bootstrap.tabs.directive:tab tab}. Must be placed as a child of a tab element.\n *\n * @example\n<example module=\"ui.bootstrap\">\n  <file name=\"index.html\">\n    <tabset>\n      <tab>\n        <tab-heading><b>HTML</b> in my titles?!</tab-heading>\n        And some content, too!\n      </tab>\n      <tab>\n        <tab-heading><i class=\"icon-heart\"></i> Icon heading?!?</tab-heading>\n        That's right.\n      </tab>\n    </tabset>\n  </file>\n</example>\n */\n.directive('tab', ['$parse', function($parse) {\n  return {\n    require: '^tabset',\n    restrict: 'EA',\n    replace: true,\n    templateUrl: 'template/tabs/tab.html',\n    transclude: true,\n    scope: {\n      active: '=?',\n      heading: '@',\n      onSelect: '&select', //This callback is called in contentHeadingTransclude\n                          //once it inserts the tab's content into the dom\n      onDeselect: '&deselect'\n    },\n    controller: function() {\n      //Empty controller so other directives can require being 'under' a tab\n    },\n    compile: function(elm, attrs, transclude) {\n      return function postLink(scope, elm, attrs, tabsetCtrl) {\n        scope.$watch('active', function(active) {\n          if (active) {\n            tabsetCtrl.select(scope);\n          }\n        });\n\n        scope.disabled = false;\n        if ( attrs.disabled ) {\n          scope.$parent.$watch($parse(attrs.disabled), function(value) {\n            scope.disabled = !! value;\n          });\n        }\n\n        scope.select = function() {\n          if ( !scope.disabled ) {\n            scope.active = true;\n          }\n        };\n\n        tabsetCtrl.addTab(scope);\n        scope.$on('$destroy', function() {\n          tabsetCtrl.removeTab(scope);\n        });\n\n        //We need to transclude later, once the content container is ready.\n        //when this link happens, we're inside a tab heading.\n        scope.$transcludeFn = transclude;\n      };\n    }\n  };\n}])\n\n.directive('tabHeadingTransclude', [function() {\n  return {\n    restrict: 'A',\n    require: '^tab',\n    link: function(scope, elm, attrs, tabCtrl) {\n      scope.$watch('headingElement', function updateHeadingElement(heading) {\n        if (heading) {\n          elm.html('');\n          elm.append(heading);\n        }\n      });\n    }\n  };\n}])\n\n.directive('tabContentTransclude', function() {\n  return {\n    restrict: 'A',\n    require: '^tabset',\n    link: function(scope, elm, attrs) {\n      var tab = scope.$eval(attrs.tabContentTransclude);\n\n      //Now our tab is ready to be transcluded: both the tab heading area\n      //and the tab content area are loaded.  Transclude 'em both.\n      tab.$transcludeFn(tab.$parent, function(contents) {\n        angular.forEach(contents, function(node) {\n          if (isTabHeading(node)) {\n            //Let tabHeadingTransclude know.\n            tab.headingElement = node;\n          } else {\n            elm.append(node);\n          }\n        });\n      });\n    }\n  };\n  function isTabHeading(node) {\n    return node.tagName &&  (\n      node.hasAttribute('tab-heading') ||\n      node.hasAttribute('data-tab-heading') ||\n      node.tagName.toLowerCase() === 'tab-heading' ||\n      node.tagName.toLowerCase() === 'data-tab-heading'\n    );\n  }\n})\n\n;\n\nangular.module('ui.bootstrap.timepicker', [])\n\n.constant('timepickerConfig', {\n  hourStep: 1,\n  minuteStep: 1,\n  showMeridian: true,\n  meridians: null,\n  readonlyInput: false,\n  mousewheel: true\n})\n\n.controller('TimepickerController', ['$scope', '$attrs', '$parse', '$log', '$locale', 'timepickerConfig', function($scope, $attrs, $parse, $log, $locale, timepickerConfig) {\n  var selected = new Date(),\n      ngModelCtrl = { $setViewValue: angular.noop }, // nullModelCtrl\n      meridians = angular.isDefined($attrs.meridians) ? $scope.$parent.$eval($attrs.meridians) : timepickerConfig.meridians || $locale.DATETIME_FORMATS.AMPMS;\n\n  this.init = function( ngModelCtrl_, inputs ) {\n    ngModelCtrl = ngModelCtrl_;\n    ngModelCtrl.$render = this.render;\n\n    var hoursInputEl = inputs.eq(0),\n        minutesInputEl = inputs.eq(1);\n\n    var mousewheel = angular.isDefined($attrs.mousewheel) ? $scope.$parent.$eval($attrs.mousewheel) : timepickerConfig.mousewheel;\n    if ( mousewheel ) {\n      this.setupMousewheelEvents( hoursInputEl, minutesInputEl );\n    }\n\n    $scope.readonlyInput = angular.isDefined($attrs.readonlyInput) ? $scope.$parent.$eval($attrs.readonlyInput) : timepickerConfig.readonlyInput;\n    this.setupInputEvents( hoursInputEl, minutesInputEl );\n  };\n\n  var hourStep = timepickerConfig.hourStep;\n  if ($attrs.hourStep) {\n    $scope.$parent.$watch($parse($attrs.hourStep), function(value) {\n      hourStep = parseInt(value, 10);\n    });\n  }\n\n  var minuteStep = timepickerConfig.minuteStep;\n  if ($attrs.minuteStep) {\n    $scope.$parent.$watch($parse($attrs.minuteStep), function(value) {\n      minuteStep = parseInt(value, 10);\n    });\n  }\n\n  // 12H / 24H mode\n  $scope.showMeridian = timepickerConfig.showMeridian;\n  if ($attrs.showMeridian) {\n    $scope.$parent.$watch($parse($attrs.showMeridian), function(value) {\n      $scope.showMeridian = !!value;\n\n      if ( ngModelCtrl.$error.time ) {\n        // Evaluate from template\n        var hours = getHoursFromTemplate(), minutes = getMinutesFromTemplate();\n        if (angular.isDefined( hours ) && angular.isDefined( minutes )) {\n          selected.setHours( hours );\n          refresh();\n        }\n      } else {\n        updateTemplate();\n      }\n    });\n  }\n\n  // Get $scope.hours in 24H mode if valid\n  function getHoursFromTemplate ( ) {\n    var hours = parseInt( $scope.hours, 10 );\n    var valid = ( $scope.showMeridian ) ? (hours > 0 && hours < 13) : (hours >= 0 && hours < 24);\n    if ( !valid ) {\n      return undefined;\n    }\n\n    if ( $scope.showMeridian ) {\n      if ( hours === 12 ) {\n        hours = 0;\n      }\n      if ( $scope.meridian === meridians[1] ) {\n        hours = hours + 12;\n      }\n    }\n    return hours;\n  }\n\n  function getMinutesFromTemplate() {\n    var minutes = parseInt($scope.minutes, 10);\n    return ( minutes >= 0 && minutes < 60 ) ? minutes : undefined;\n  }\n\n  function pad( value ) {\n    return ( angular.isDefined(value) && value.toString().length < 2 ) ? '0' + value : value;\n  }\n\n  // Respond on mousewheel spin\n  this.setupMousewheelEvents = function( hoursInputEl, minutesInputEl ) {\n    var isScrollingUp = function(e) {\n      if (e.originalEvent) {\n        e = e.originalEvent;\n      }\n      //pick correct delta variable depending on event\n      var delta = (e.wheelDelta) ? e.wheelDelta : -e.deltaY;\n      return (e.detail || delta > 0);\n    };\n\n    hoursInputEl.bind('mousewheel wheel', function(e) {\n      $scope.$apply( (isScrollingUp(e)) ? $scope.incrementHours() : $scope.decrementHours() );\n      e.preventDefault();\n    });\n\n    minutesInputEl.bind('mousewheel wheel', function(e) {\n      $scope.$apply( (isScrollingUp(e)) ? $scope.incrementMinutes() : $scope.decrementMinutes() );\n      e.preventDefault();\n    });\n\n  };\n\n  this.setupInputEvents = function( hoursInputEl, minutesInputEl ) {\n    if ( $scope.readonlyInput ) {\n      $scope.updateHours = angular.noop;\n      $scope.updateMinutes = angular.noop;\n      return;\n    }\n\n    var invalidate = function(invalidHours, invalidMinutes) {\n      ngModelCtrl.$setViewValue( null );\n      ngModelCtrl.$setValidity('time', false);\n      if (angular.isDefined(invalidHours)) {\n        $scope.invalidHours = invalidHours;\n      }\n      if (angular.isDefined(invalidMinutes)) {\n        $scope.invalidMinutes = invalidMinutes;\n      }\n    };\n\n    $scope.updateHours = function() {\n      var hours = getHoursFromTemplate();\n\n      if ( angular.isDefined(hours) ) {\n        selected.setHours( hours );\n        refresh( 'h' );\n      } else {\n        invalidate(true);\n      }\n    };\n\n    hoursInputEl.bind('blur', function(e) {\n      if ( !$scope.invalidHours && $scope.hours < 10) {\n        $scope.$apply( function() {\n          $scope.hours = pad( $scope.hours );\n        });\n      }\n    });\n\n    $scope.updateMinutes = function() {\n      var minutes = getMinutesFromTemplate();\n\n      if ( angular.isDefined(minutes) ) {\n        selected.setMinutes( minutes );\n        refresh( 'm' );\n      } else {\n        invalidate(undefined, true);\n      }\n    };\n\n    minutesInputEl.bind('blur', function(e) {\n      if ( !$scope.invalidMinutes && $scope.minutes < 10 ) {\n        $scope.$apply( function() {\n          $scope.minutes = pad( $scope.minutes );\n        });\n      }\n    });\n\n  };\n\n  this.render = function() {\n    var date = ngModelCtrl.$modelValue ? new Date( ngModelCtrl.$modelValue ) : null;\n\n    if ( isNaN(date) ) {\n      ngModelCtrl.$setValidity('time', false);\n      $log.error('Timepicker directive: \"ng-model\" value must be a Date object, a number of milliseconds since 01.01.1970 or a string representing an RFC2822 or ISO 8601 date.');\n    } else {\n      if ( date ) {\n        selected = date;\n      }\n      makeValid();\n      updateTemplate();\n    }\n  };\n\n  // Call internally when we know that model is valid.\n  function refresh( keyboardChange ) {\n    makeValid();\n    ngModelCtrl.$setViewValue( new Date(selected) );\n    updateTemplate( keyboardChange );\n  }\n\n  function makeValid() {\n    ngModelCtrl.$setValidity('time', true);\n    $scope.invalidHours = false;\n    $scope.invalidMinutes = false;\n  }\n\n  function updateTemplate( keyboardChange ) {\n    var hours = selected.getHours(), minutes = selected.getMinutes();\n\n    if ( $scope.showMeridian ) {\n      hours = ( hours === 0 || hours === 12 ) ? 12 : hours % 12; // Convert 24 to 12 hour system\n    }\n\n    $scope.hours = keyboardChange === 'h' ? hours : pad(hours);\n    $scope.minutes = keyboardChange === 'm' ? minutes : pad(minutes);\n    $scope.meridian = selected.getHours() < 12 ? meridians[0] : meridians[1];\n  }\n\n  function addMinutes( minutes ) {\n    var dt = new Date( selected.getTime() + minutes * 60000 );\n    selected.setHours( dt.getHours(), dt.getMinutes() );\n    refresh();\n  }\n\n  $scope.incrementHours = function() {\n    addMinutes( hourStep * 60 );\n  };\n  $scope.decrementHours = function() {\n    addMinutes( - hourStep * 60 );\n  };\n  $scope.incrementMinutes = function() {\n    addMinutes( minuteStep );\n  };\n  $scope.decrementMinutes = function() {\n    addMinutes( - minuteStep );\n  };\n  $scope.toggleMeridian = function() {\n    addMinutes( 12 * 60 * (( selected.getHours() < 12 ) ? 1 : -1) );\n  };\n}])\n\n.directive('timepicker', function () {\n  return {\n    restrict: 'EA',\n    require: ['timepicker', '?^ngModel'],\n    controller:'TimepickerController',\n    replace: true,\n    scope: {},\n    templateUrl: 'template/timepicker/timepicker.html',\n    link: function(scope, element, attrs, ctrls) {\n      var timepickerCtrl = ctrls[0], ngModelCtrl = ctrls[1];\n\n      if ( ngModelCtrl ) {\n        timepickerCtrl.init( ngModelCtrl, element.find('input') );\n      }\n    }\n  };\n});\n\nangular.module('ui.bootstrap.typeahead', ['ui.bootstrap.position', 'ui.bootstrap.bindHtml'])\n\n/**\n * A helper service that can parse typeahead's syntax (string provided by users)\n * Extracted to a separate service for ease of unit testing\n */\n  .factory('typeaheadParser', ['$parse', function ($parse) {\n\n  //                      00000111000000000000022200000000000000003333333333333330000000000044000\n  var TYPEAHEAD_REGEXP = /^\\s*([\\s\\S]+?)(?:\\s+as\\s+([\\s\\S]+?))?\\s+for\\s+(?:([\\$\\w][\\$\\w\\d]*))\\s+in\\s+([\\s\\S]+?)$/;\n\n  return {\n    parse:function (input) {\n\n      var match = input.match(TYPEAHEAD_REGEXP);\n      if (!match) {\n        throw new Error(\n          'Expected typeahead specification in form of \"_modelValue_ (as _label_)? for _item_ in _collection_\"' +\n            ' but got \"' + input + '\".');\n      }\n\n      return {\n        itemName:match[3],\n        source:$parse(match[4]),\n        viewMapper:$parse(match[2] || match[1]),\n        modelMapper:$parse(match[1])\n      };\n    }\n  };\n}])\n\n  .directive('typeahead', ['$compile', '$parse', '$q', '$timeout', '$document', '$position', 'typeaheadParser',\n    function ($compile, $parse, $q, $timeout, $document, $position, typeaheadParser) {\n\n  var HOT_KEYS = [9, 13, 27, 38, 40];\n\n  return {\n    require:'ngModel',\n    link:function (originalScope, element, attrs, modelCtrl) {\n\n      //SUPPORTED ATTRIBUTES (OPTIONS)\n\n      //minimal no of characters that needs to be entered before typeahead kicks-in\n      var minSearch = originalScope.$eval(attrs.typeaheadMinLength) || 1;\n\n      //minimal wait time after last character typed before typehead kicks-in\n      var waitTime = originalScope.$eval(attrs.typeaheadWaitMs) || 0;\n\n      //should it restrict model values to the ones selected from the popup only?\n      var isEditable = originalScope.$eval(attrs.typeaheadEditable) !== false;\n\n      //binding to a variable that indicates if matches are being retrieved asynchronously\n      var isLoadingSetter = $parse(attrs.typeaheadLoading).assign || angular.noop;\n\n      //a callback executed when a match is selected\n      var onSelectCallback = $parse(attrs.typeaheadOnSelect);\n\n      var inputFormatter = attrs.typeaheadInputFormatter ? $parse(attrs.typeaheadInputFormatter) : undefined;\n\n      var appendToBody =  attrs.typeaheadAppendToBody ? originalScope.$eval(attrs.typeaheadAppendToBody) : false;\n\n      var focusFirst = originalScope.$eval(attrs.typeaheadFocusFirst) !== false;\n\n      //INTERNAL VARIABLES\n\n      //model setter executed upon match selection\n      var $setModelValue = $parse(attrs.ngModel).assign;\n\n      //expressions used by typeahead\n      var parserResult = typeaheadParser.parse(attrs.typeahead);\n\n      var hasFocus;\n\n      //create a child scope for the typeahead directive so we are not polluting original scope\n      //with typeahead-specific data (matches, query etc.)\n      var scope = originalScope.$new();\n      originalScope.$on('$destroy', function(){\n        scope.$destroy();\n      });\n\n      // WAI-ARIA\n      var popupId = 'typeahead-' + scope.$id + '-' + Math.floor(Math.random() * 10000);\n      element.attr({\n        'aria-autocomplete': 'list',\n        'aria-expanded': false,\n        'aria-owns': popupId\n      });\n\n      //pop-up element used to display matches\n      var popUpEl = angular.element('<div typeahead-popup></div>');\n      popUpEl.attr({\n        id: popupId,\n        matches: 'matches',\n        active: 'activeIdx',\n        select: 'select(activeIdx)',\n        query: 'query',\n        position: 'position'\n      });\n      //custom item template\n      if (angular.isDefined(attrs.typeaheadTemplateUrl)) {\n        popUpEl.attr('template-url', attrs.typeaheadTemplateUrl);\n      }\n\n      var resetMatches = function() {\n        scope.matches = [];\n        scope.activeIdx = -1;\n        element.attr('aria-expanded', false);\n      };\n\n      var getMatchId = function(index) {\n        return popupId + '-option-' + index;\n      };\n\n      // Indicate that the specified match is the active (pre-selected) item in the list owned by this typeahead.\n      // This attribute is added or removed automatically when the `activeIdx` changes.\n      scope.$watch('activeIdx', function(index) {\n        if (index < 0) {\n          element.removeAttr('aria-activedescendant');\n        } else {\n          element.attr('aria-activedescendant', getMatchId(index));\n        }\n      });\n\n      var getMatchesAsync = function(inputValue) {\n\n        var locals = {$viewValue: inputValue};\n        isLoadingSetter(originalScope, true);\n        $q.when(parserResult.source(originalScope, locals)).then(function(matches) {\n\n          //it might happen that several async queries were in progress if a user were typing fast\n          //but we are interested only in responses that correspond to the current view value\n          var onCurrentRequest = (inputValue === modelCtrl.$viewValue);\n          if (onCurrentRequest && hasFocus) {\n            if (matches.length > 0) {\n\n              scope.activeIdx = focusFirst ? 0 : -1;\n              scope.matches.length = 0;\n\n              //transform labels\n              for(var i=0; i<matches.length; i++) {\n                locals[parserResult.itemName] = matches[i];\n                scope.matches.push({\n                  id: getMatchId(i),\n                  label: parserResult.viewMapper(scope, locals),\n                  model: matches[i]\n                });\n              }\n\n              scope.query = inputValue;\n              //position pop-up with matches - we need to re-calculate its position each time we are opening a window\n              //with matches as a pop-up might be absolute-positioned and position of an input might have changed on a page\n              //due to other elements being rendered\n              scope.position = appendToBody ? $position.offset(element) : $position.position(element);\n              scope.position.top = scope.position.top + element.prop('offsetHeight');\n\n              element.attr('aria-expanded', true);\n            } else {\n              resetMatches();\n            }\n          }\n          if (onCurrentRequest) {\n            isLoadingSetter(originalScope, false);\n          }\n        }, function(){\n          resetMatches();\n          isLoadingSetter(originalScope, false);\n        });\n      };\n\n      resetMatches();\n\n      //we need to propagate user's query so we can higlight matches\n      scope.query = undefined;\n\n      //Declare the timeout promise var outside the function scope so that stacked calls can be cancelled later \n      var timeoutPromise;\n\n      var scheduleSearchWithTimeout = function(inputValue) {\n        timeoutPromise = $timeout(function () {\n          getMatchesAsync(inputValue);\n        }, waitTime);\n      };\n\n      var cancelPreviousTimeout = function() {\n        if (timeoutPromise) {\n          $timeout.cancel(timeoutPromise);\n        }\n      };\n\n      //plug into $parsers pipeline to open a typeahead on view changes initiated from DOM\n      //$parsers kick-in on all the changes coming from the view as well as manually triggered by $setViewValue\n      modelCtrl.$parsers.unshift(function (inputValue) {\n\n        hasFocus = true;\n\n        if (inputValue && inputValue.length >= minSearch) {\n          if (waitTime > 0) {\n            cancelPreviousTimeout();\n            scheduleSearchWithTimeout(inputValue);\n          } else {\n            getMatchesAsync(inputValue);\n          }\n        } else {\n          isLoadingSetter(originalScope, false);\n          cancelPreviousTimeout();\n          resetMatches();\n        }\n\n        if (isEditable) {\n          return inputValue;\n        } else {\n          if (!inputValue) {\n            // Reset in case user had typed something previously.\n            modelCtrl.$setValidity('editable', true);\n            return inputValue;\n          } else {\n            modelCtrl.$setValidity('editable', false);\n            return undefined;\n          }\n        }\n      });\n\n      modelCtrl.$formatters.push(function (modelValue) {\n\n        var candidateViewValue, emptyViewValue;\n        var locals = {};\n\n        if (inputFormatter) {\n\n          locals.$model = modelValue;\n          return inputFormatter(originalScope, locals);\n\n        } else {\n\n          //it might happen that we don't have enough info to properly render input value\n          //we need to check for this situation and simply return model value if we can't apply custom formatting\n          locals[parserResult.itemName] = modelValue;\n          candidateViewValue = parserResult.viewMapper(originalScope, locals);\n          locals[parserResult.itemName] = undefined;\n          emptyViewValue = parserResult.viewMapper(originalScope, locals);\n\n          return candidateViewValue!== emptyViewValue ? candidateViewValue : modelValue;\n        }\n      });\n\n      scope.select = function (activeIdx) {\n        //called from within the $digest() cycle\n        var locals = {};\n        var model, item;\n\n        locals[parserResult.itemName] = item = scope.matches[activeIdx].model;\n        model = parserResult.modelMapper(originalScope, locals);\n        $setModelValue(originalScope, model);\n        modelCtrl.$setValidity('editable', true);\n\n        onSelectCallback(originalScope, {\n          $item: item,\n          $model: model,\n          $label: parserResult.viewMapper(originalScope, locals)\n        });\n\n        resetMatches();\n\n        //return focus to the input element if a match was selected via a mouse click event\n        // use timeout to avoid $rootScope:inprog error\n        $timeout(function() { element[0].focus(); }, 0, false);\n      };\n\n      //bind keyboard events: arrows up(38) / down(40), enter(13) and tab(9), esc(27)\n      element.bind('keydown', function (evt) {\n\n        //typeahead is open and an \"interesting\" key was pressed\n        if (scope.matches.length === 0 || HOT_KEYS.indexOf(evt.which) === -1) {\n          return;\n        }\n\n        // if there's nothing selected (i.e. focusFirst) and enter is hit, don't do anything\n        if (scope.activeIdx == -1 && (evt.which === 13 || evt.which === 9)) {\n          return;\n        }\n\n        evt.preventDefault();\n\n        if (evt.which === 40) {\n          scope.activeIdx = (scope.activeIdx + 1) % scope.matches.length;\n          scope.$digest();\n\n        } else if (evt.which === 38) {\n          scope.activeIdx = (scope.activeIdx > 0 ? scope.activeIdx : scope.matches.length) - 1;\n          scope.$digest();\n\n        } else if (evt.which === 13 || evt.which === 9) {\n          scope.$apply(function () {\n            scope.select(scope.activeIdx);\n          });\n\n        } else if (evt.which === 27) {\n          evt.stopPropagation();\n\n          resetMatches();\n          scope.$digest();\n        }\n      });\n\n      element.bind('blur', function (evt) {\n        hasFocus = false;\n      });\n\n      // Keep reference to click handler to unbind it.\n      var dismissClickHandler = function (evt) {\n        if (element[0] !== evt.target) {\n          resetMatches();\n          scope.$digest();\n        }\n      };\n\n      $document.bind('click', dismissClickHandler);\n\n      originalScope.$on('$destroy', function(){\n        $document.unbind('click', dismissClickHandler);\n        if (appendToBody) {\n          $popup.remove();\n        }\n      });\n\n      var $popup = $compile(popUpEl)(scope);\n      if (appendToBody) {\n        $document.find('body').append($popup);\n      } else {\n        element.after($popup);\n      }\n    }\n  };\n\n}])\n\n  .directive('typeaheadPopup', function () {\n    return {\n      restrict:'EA',\n      scope:{\n        matches:'=',\n        query:'=',\n        active:'=',\n        position:'=',\n        select:'&'\n      },\n      replace:true,\n      templateUrl:'template/typeahead/typeahead-popup.html',\n      link:function (scope, element, attrs) {\n\n        scope.templateUrl = attrs.templateUrl;\n\n        scope.isOpen = function () {\n          return scope.matches.length > 0;\n        };\n\n        scope.isActive = function (matchIdx) {\n          return scope.active == matchIdx;\n        };\n\n        scope.selectActive = function (matchIdx) {\n          scope.active = matchIdx;\n        };\n\n        scope.selectMatch = function (activeIdx) {\n          scope.select({activeIdx:activeIdx});\n        };\n      }\n    };\n  })\n\n  .directive('typeaheadMatch', ['$http', '$templateCache', '$compile', '$parse', function ($http, $templateCache, $compile, $parse) {\n    return {\n      restrict:'EA',\n      scope:{\n        index:'=',\n        match:'=',\n        query:'='\n      },\n      link:function (scope, element, attrs) {\n        var tplUrl = $parse(attrs.templateUrl)(scope.$parent) || 'template/typeahead/typeahead-match.html';\n        $http.get(tplUrl, {cache: $templateCache}).success(function(tplContent){\n           element.replaceWith($compile(tplContent.trim())(scope));\n        });\n      }\n    };\n  }])\n\n  .filter('typeaheadHighlight', function() {\n\n    function escapeRegexp(queryToEscape) {\n      return queryToEscape.replace(/([.?*+^$[\\]\\\\(){}|-])/g, '\\\\$1');\n    }\n\n    return function(matchItem, query) {\n      return query ? ('' + matchItem).replace(new RegExp(escapeRegexp(query), 'gi'), '<strong>$&</strong>') : matchItem;\n    };\n  });\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/angular-cookies/.bower.json",
    "content": "{\n  \"name\": \"angular-cookies\",\n  \"version\": \"1.3.13\",\n  \"main\": \"./angular-cookies.js\",\n  \"ignore\": [],\n  \"dependencies\": {\n    \"angular\": \"1.3.13\"\n  },\n  \"homepage\": \"https://github.com/angular/bower-angular-cookies\",\n  \"_release\": \"1.3.13\",\n  \"_resolution\": {\n    \"type\": \"version\",\n    \"tag\": \"v1.3.13\",\n    \"commit\": \"97277f6a7f1c0135e45d3880b813699349b6efa4\"\n  },\n  \"_source\": \"https://github.com/angular/bower-angular-cookies.git\",\n  \"_target\": \"1.3.13\",\n  \"_originalSource\": \"angular-cookies\"\n}"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/angular-cookies/README.md",
    "content": "# packaged angular-cookies\n\nThis repo is for distribution on `npm` and `bower`. The source for this module is in the\n[main AngularJS repo](https://github.com/angular/angular.js/tree/master/src/ngCookies).\nPlease file issues and pull requests against that repo.\n\n## Install\n\nYou can install this package either with `npm` or with `bower`.\n\n### npm\n\n```shell\nnpm install angular-cookies\n```\n\nAdd a `<script>` to your `index.html`:\n\n```html\n<script src=\"/node_modules/angular-cookies/angular-cookies.js\"></script>\n```\n\nThen add `ngCookies` as a dependency for your app:\n\n```javascript\nangular.module('myApp', ['ngCookies']);\n```\n\nNote that this package is not in CommonJS format, so doing `require('angular-cookies')` will\nreturn `undefined`.\n\n### bower\n\n```shell\nbower install angular-cookies\n```\n\nAdd a `<script>` to your `index.html`:\n\n```html\n<script src=\"/bower_components/angular-cookies/angular-cookies.js\"></script>\n```\n\nThen add `ngCookies` as a dependency for your app:\n\n```javascript\nangular.module('myApp', ['ngCookies']);\n```\n\n## Documentation\n\nDocumentation is available on the\n[AngularJS docs site](http://docs.angularjs.org/api/ngCookies).\n\n## License\n\nThe MIT License\n\nCopyright (c) 2010-2012 Google, Inc. http://angularjs.org\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies 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 FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/angular-cookies/angular-cookies.js",
    "content": "/**\n * @license AngularJS v1.3.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 module\n * @name ngCookies\n * @description\n *\n * # ngCookies\n *\n * The `ngCookies` module provides a convenient wrapper for reading and writing browser cookies.\n *\n *\n * <div doc-module-components=\"ngCookies\"></div>\n *\n * See {@link ngCookies.$cookies `$cookies`} and\n * {@link ngCookies.$cookieStore `$cookieStore`} for usage.\n */\n\n\nangular.module('ngCookies', ['ng']).\n  /**\n   * @ngdoc service\n   * @name $cookies\n   *\n   * @description\n   * Provides read/write access to browser's cookies.\n   *\n   * Only a simple Object is exposed and by adding or removing properties to/from this object, new\n   * cookies are created/deleted at the end of current $eval.\n   * The object's properties can only be strings.\n   *\n   * Requires the {@link ngCookies `ngCookies`} module to be installed.\n   *\n   * @example\n   *\n   * ```js\n   * angular.module('cookiesExample', ['ngCookies'])\n   *   .controller('ExampleController', ['$cookies', function($cookies) {\n   *     // Retrieving a cookie\n   *     var favoriteCookie = $cookies.myFavorite;\n   *     // Setting a cookie\n   *     $cookies.myFavorite = 'oatmeal';\n   *   }]);\n   * ```\n   */\n   factory('$cookies', ['$rootScope', '$browser', function($rootScope, $browser) {\n      var cookies = {},\n          lastCookies = {},\n          lastBrowserCookies,\n          runEval = false,\n          copy = angular.copy,\n          isUndefined = angular.isUndefined;\n\n      //creates a poller fn that copies all cookies from the $browser to service & inits the service\n      $browser.addPollFn(function() {\n        var currentCookies = $browser.cookies();\n        if (lastBrowserCookies != currentCookies) { //relies on browser.cookies() impl\n          lastBrowserCookies = currentCookies;\n          copy(currentCookies, lastCookies);\n          copy(currentCookies, cookies);\n          if (runEval) $rootScope.$apply();\n        }\n      })();\n\n      runEval = true;\n\n      //at the end of each eval, push cookies\n      //TODO: this should happen before the \"delayed\" watches fire, because if some cookies are not\n      //      strings or browser refuses to store some cookies, we update the model in the push fn.\n      $rootScope.$watch(push);\n\n      return cookies;\n\n\n      /**\n       * Pushes all the cookies from the service to the browser and verifies if all cookies were\n       * stored.\n       */\n      function push() {\n        var name,\n            value,\n            browserCookies,\n            updated;\n\n        //delete any cookies deleted in $cookies\n        for (name in lastCookies) {\n          if (isUndefined(cookies[name])) {\n            $browser.cookies(name, undefined);\n          }\n        }\n\n        //update all cookies updated in $cookies\n        for (name in cookies) {\n          value = cookies[name];\n          if (!angular.isString(value)) {\n            value = '' + value;\n            cookies[name] = value;\n          }\n          if (value !== lastCookies[name]) {\n            $browser.cookies(name, value);\n            updated = true;\n          }\n        }\n\n        //verify what was actually stored\n        if (updated) {\n          updated = false;\n          browserCookies = $browser.cookies();\n\n          for (name in cookies) {\n            if (cookies[name] !== browserCookies[name]) {\n              //delete or reset all cookies that the browser dropped from $cookies\n              if (isUndefined(browserCookies[name])) {\n                delete cookies[name];\n              } else {\n                cookies[name] = browserCookies[name];\n              }\n              updated = true;\n            }\n          }\n        }\n      }\n    }]).\n\n\n  /**\n   * @ngdoc service\n   * @name $cookieStore\n   * @requires $cookies\n   *\n   * @description\n   * Provides a key-value (string-object) storage, that is backed by session cookies.\n   * Objects put or retrieved from this storage are automatically serialized or\n   * deserialized by angular's toJson/fromJson.\n   *\n   * Requires the {@link ngCookies `ngCookies`} module to be installed.\n   *\n   * @example\n   *\n   * ```js\n   * angular.module('cookieStoreExample', ['ngCookies'])\n   *   .controller('ExampleController', ['$cookieStore', function($cookieStore) {\n   *     // Put cookie\n   *     $cookieStore.put('myFavorite','oatmeal');\n   *     // Get cookie\n   *     var favoriteCookie = $cookieStore.get('myFavorite');\n   *     // Removing a cookie\n   *     $cookieStore.remove('myFavorite');\n   *   }]);\n   * ```\n   */\n   factory('$cookieStore', ['$cookies', function($cookies) {\n\n      return {\n        /**\n         * @ngdoc method\n         * @name $cookieStore#get\n         *\n         * @description\n         * Returns the value of given cookie key\n         *\n         * @param {string} key Id to use for lookup.\n         * @returns {Object} Deserialized cookie value.\n         */\n        get: function(key) {\n          var value = $cookies[key];\n          return value ? angular.fromJson(value) : value;\n        },\n\n        /**\n         * @ngdoc method\n         * @name $cookieStore#put\n         *\n         * @description\n         * Sets a value for given cookie key\n         *\n         * @param {string} key Id for the `value`.\n         * @param {Object} value Value to be stored.\n         */\n        put: function(key, value) {\n          $cookies[key] = angular.toJson(value);\n        },\n\n        /**\n         * @ngdoc method\n         * @name $cookieStore#remove\n         *\n         * @description\n         * Remove given cookie\n         *\n         * @param {string} key Id of the key-value pair to delete.\n         */\n        remove: function(key) {\n          delete $cookies[key];\n        }\n      };\n\n    }]);\n\n\n})(window, window.angular);\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/angular-cookies/bower.json",
    "content": "{\n  \"name\": \"angular-cookies\",\n  \"version\": \"1.3.13\",\n  \"main\": \"./angular-cookies.js\",\n  \"ignore\": [],\n  \"dependencies\": {\n    \"angular\": \"1.3.13\"\n  }\n}\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/angular-cookies/package.json",
    "content": "{\n  \"name\": \"angular-cookies\",\n  \"version\": \"1.3.13\",\n  \"description\": \"AngularJS module for cookies\",\n  \"main\": \"angular-cookies.js\",\n  \"scripts\": {\n    \"test\": \"echo \\\"Error: no test specified\\\" && exit 1\"\n  },\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/angular/angular.js.git\"\n  },\n  \"keywords\": [\n    \"angular\",\n    \"framework\",\n    \"browser\",\n    \"cookies\",\n    \"client-side\"\n  ],\n  \"author\": \"Angular Core Team <angular-core+npm@google.com>\",\n  \"license\": \"MIT\",\n  \"bugs\": {\n    \"url\": \"https://github.com/angular/angular.js/issues\"\n  },\n  \"homepage\": \"http://angularjs.org\"\n}\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/angular-mocks/.bower.json",
    "content": "{\n  \"name\": \"angular-mocks\",\n  \"version\": \"1.3.13\",\n  \"main\": \"./angular-mocks.js\",\n  \"ignore\": [],\n  \"dependencies\": {\n    \"angular\": \"1.3.13\"\n  },\n  \"homepage\": \"https://github.com/angular/bower-angular-mocks\",\n  \"_release\": \"1.3.13\",\n  \"_resolution\": {\n    \"type\": \"version\",\n    \"tag\": \"v1.3.13\",\n    \"commit\": \"8f53bfda01696e53549fe3266b0a4d220ea9bf77\"\n  },\n  \"_source\": \"https://github.com/angular/bower-angular-mocks.git\",\n  \"_target\": \"1.3.13\",\n  \"_originalSource\": \"angular-mocks\"\n}"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/angular-mocks/README.md",
    "content": "# packaged angular-mocks\n\nThis repo is for distribution on `npm` and `bower`. The source for this module is in the\n[main AngularJS repo](https://github.com/angular/angular.js/tree/master/src/ngMock).\nPlease file issues and pull requests against that repo.\n\n## Install\n\nYou can install this package either with `npm` or with `bower`.\n\n### npm\n\n```shell\nnpm install angular-mocks\n```\n\nThe mocks are then available at `node_modules/angular-mocks/angular-mocks.js`.\n\nNote that this package is not in CommonJS format, so doing `require('angular-mocks')` will\nreturn `undefined`.\n\n### bower\n\n```shell\nbower install angular-mocks\n```\n\nThe mocks are then available at `bower_components/angular-mocks/angular-mocks.js`.\n\n## Documentation\n\nDocumentation is available on the\n[AngularJS docs site](https://docs.angularjs.org/guide/unit-testing).\n\n## License\n\nThe MIT License\n\nCopyright (c) 2010-2012 Google, Inc. http://angularjs.org\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies 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 FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/angular-mocks/angular-mocks.js",
    "content": "/**\n * @license AngularJS v1.3.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 object\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 $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 || self.$$state !== self.$$lastState) {\n          self.$$lastUrl = self.$$url;\n          self.$$lastState = self.$$state;\n          listener(self.$$url, self.$$state);\n        }\n      }\n    );\n\n    return listener;\n  };\n\n  self.$$checkUrlChange = angular.noop;\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 $browser#defer.now\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 $browser#defer.flush\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 $browser#poll\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, state) {\n    if (angular.isUndefined(state)) {\n      state = null;\n    }\n    if (url) {\n      this.$$url = url;\n      // Native pushState serializes & copies the object; simulate it.\n      this.$$state = angular.copy(state);\n      return this;\n    }\n\n    return this.$$url;\n  },\n\n  state: function() {\n    return this.$$state;\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 provider\n * @name $exceptionHandlerProvider\n *\n * @description\n * Configures the mock implementation of {@link ng.$exceptionHandler} to rethrow or to log errors\n * passed to the `$exceptionHandler`.\n */\n\n/**\n * @ngdoc service\n * @name $exceptionHandler\n *\n * @description\n * Mock implementation of {@link ng.$exceptionHandler} that rethrows or logs errors passed\n * to it. See {@link ngMock.$exceptionHandlerProvider $exceptionHandlerProvider} for configuration\n * information.\n *\n *\n * ```js\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 * ```\n */\n\nangular.mock.$ExceptionHandlerProvider = function() {\n  var handler;\n\n  /**\n   * @ngdoc method\n   * @name $exceptionHandlerProvider#mode\n   *\n   * @description\n   * Sets the logging mode.\n   *\n   * @param {string} mode Mode of operation, defaults to `rethrow`.\n   *\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   *   - `rethrow`: If any errors are passed to the handler in tests, it typically means that there\n   *                is a bug in the application or test, so this mock will make these tests fail.\n   *                For any implementations that expect exceptions to be thrown, the `rethrow` mode\n   *                will also maintain a log of thrown errors.\n   */\n  this.mode = function(mode) {\n\n    switch (mode) {\n      case 'log':\n      case 'rethrow':\n        var errors = [];\n        handler = function(e) {\n          if (arguments.length == 1) {\n            errors.push(e);\n          } else {\n            errors.push([].slice.call(arguments, 0));\n          }\n          if (mode === \"rethrow\") {\n            throw e;\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 $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 $log#reset\n     *\n     * @description\n     * Reset all of the logging arrays to empty.\n     */\n    $log.reset = function() {\n      /**\n       * @ngdoc property\n       * @name $log#log.logs\n       *\n       * @description\n       * Array of messages logged using {@link ng.$log#log `log()`}.\n       *\n       * @example\n       * ```js\n       * $log.log('Some Log');\n       * var first = $log.log.logs.unshift();\n       * ```\n       */\n      $log.log.logs = [];\n      /**\n       * @ngdoc property\n       * @name $log#info.logs\n       *\n       * @description\n       * Array of messages logged using {@link ng.$log#info `info()`}.\n       *\n       * @example\n       * ```js\n       * $log.info('Some Info');\n       * var first = $log.info.logs.unshift();\n       * ```\n       */\n      $log.info.logs = [];\n      /**\n       * @ngdoc property\n       * @name $log#warn.logs\n       *\n       * @description\n       * Array of messages logged using {@link ng.$log#warn `warn()`}.\n       *\n       * @example\n       * ```js\n       * $log.warn('Some Warning');\n       * var first = $log.warn.logs.unshift();\n       * ```\n       */\n      $log.warn.logs = [];\n      /**\n       * @ngdoc property\n       * @name $log#error.logs\n       *\n       * @description\n       * Array of messages logged using {@link ng.$log#error `error()`}.\n       *\n       * @example\n       * ```js\n       * $log.error('Some Error');\n       * var first = $log.error.logs.unshift();\n       * ```\n       */\n      $log.error.logs = [];\n        /**\n       * @ngdoc property\n       * @name $log#debug.logs\n       *\n       * @description\n       * Array of messages logged using {@link ng.$log#debug `debug()`}.\n       *\n       * @example\n       * ```js\n       * $log.debug('Some Error');\n       * var first = $log.debug.logs.unshift();\n       * ```\n       */\n      $log.debug.logs = [];\n    };\n\n    /**\n     * @ngdoc method\n     * @name $log#assertEmpty\n     *\n     * @description\n     * Assert that all of the logging methods have no logged messages. If any messages are present,\n     * an 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 $interval\n *\n * @description\n * Mock implementation of the $interval service.\n *\n * Use {@link ngMock.$interval#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#$apply $apply} block.\n * @returns {promise} A promise which will be notified on each iteration.\n */\nangular.mock.$IntervalProvider = function() {\n  this.$get = ['$browser', '$rootScope', '$q', '$$q',\n       function($browser,   $rootScope,   $q,   $$q) {\n    var repeatFns = [],\n        nextRepeatId = 0,\n        now = 0;\n\n    var $interval = function(fn, delay, count, invokeApply) {\n      var iteration = 0,\n          skipApply = (angular.isDefined(invokeApply) && !invokeApply),\n          deferred = (skipApply ? $$q : $q).defer(),\n          promise = deferred.promise;\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) {\n          $browser.defer.flush();\n        } else {\n          $rootScope.$apply();\n        }\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     * @ngdoc method\n     * @name $interval#cancel\n     *\n     * @description\n     * Cancels a task associated with the `promise`.\n     *\n     * @param {promise} promise A promise from calling the `$interval` function.\n     * @returns {boolean} Returns `true` if the task was successfully cancelled.\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 $interval#flush\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 type\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 * ```js\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 * ```\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\n    var reflowQueue = [];\n    $provide.value('$$animateReflow', function(fn) {\n      var index = reflowQueue.length;\n      reflowQueue.push(fn);\n      return function cancel() {\n        reflowQueue.splice(index, 1);\n      };\n    });\n\n    $provide.decorator('$animate', ['$delegate', '$$asyncCallback', '$timeout', '$browser',\n                            function($delegate,   $$asyncCallback,   $timeout,   $browser) {\n      var animate = {\n        queue: [],\n        cancel: $delegate.cancel,\n        enabled: $delegate.enabled,\n        triggerCallbackEvents: function() {\n          $$asyncCallback.flush();\n        },\n        triggerCallbackPromise: function() {\n          $timeout.flush(0);\n        },\n        triggerCallbacks: function() {\n          this.triggerCallbackEvents();\n          this.triggerCallbackPromise();\n        },\n        triggerReflow: function() {\n          angular.forEach(reflowQueue, function(fn) {\n            fn();\n          });\n          reflowQueue = [];\n        }\n      };\n\n      angular.forEach(\n        ['animate','enter','leave','move','addClass','removeClass','setClass'], function(method) {\n        animate[method] = function() {\n          animate.queue.push({\n            event: method,\n            element: arguments[0],\n            options: arguments[arguments.length - 1],\n            args: arguments\n          });\n          return $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 service\n * @name $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 [XHR](https://developer.mozilla.org/en/xmlhttprequest) or\n * [JSONP](http://en.wikipedia.org/wiki/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 a 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 asynchronously. If we preserved\n * this behavior in unit testing, we'd have to create async unit tests, which are hard to write,\n * to follow and to maintain. But neither can the testing mock respond synchronously; that would\n * change the execution of the code under test. For this reason, the mock $httpBackend has a\n * `flush()` method, which allows the test to explicitly flush pending requests. This preserves\n * the async api of the backend, while allowing the test to execute 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  ```js\n  // The module code\n  angular\n    .module('MyApp', [])\n    .controller('MyController', MyController);\n\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  ```\n *\n * Now we setup the mock backend and create the test specs:\n *\n  ```js\n    // testing controller\n    describe('MyController', function() {\n       var $httpBackend, $rootScope, createController, authRequestHandler;\n\n       // Set up the module\n       beforeEach(module('MyApp'));\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         authRequestHandler = $httpBackend.when('GET', '/auth.py')\n                                .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 fail authentication', function() {\n\n         // Notice how you can change the response even after it was set\n         authRequestHandler.respond(401, '');\n\n         $httpBackend.expectGET('/auth.py');\n         var controller = createController();\n         $httpBackend.flush();\n         expect($rootScope.status).toBe('Failed...');\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   ```\n */\nangular.mock.$HttpBackendProvider = function() {\n  this.$get = ['$rootScope', '$timeout', 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, $timeout, $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, statusText) {\n    if (angular.isFunction(status)) return status;\n\n    return function() {\n      return angular.isNumber(status)\n          ? [status, data, headers, statusText]\n          : [200, status, data, headers];\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) {\n        timeout.then ? timeout.then(handleTimeout) : $timeout(handleTimeout, timeout);\n      }\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                 copy(response[3] || ''));\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 $httpBackend#when\n   * @description\n   * Creates a new backend definition.\n   *\n   * @param {string} method HTTP method.\n   * @param {string|RegExp|function(string)} url HTTP url or function that receives the url\n   *   and returns true if the url match the current definition.\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. You can save this object for later use and invoke `respond` again in\n   *   order to change how a matched request is handled.\n   *\n   *  - respond –\n   *      `{function([status,] data[, headers, statusText])\n   *      | function(function(method, url, data, headers)}`\n   *    – The respond method takes a set of static data to be returned or a function that can\n   *    return an array containing response status (number), response data (string), response\n   *    headers (Object), and the text for the status (string). The respond method returns the\n   *    `requestHandler` object for possible overrides.\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, statusText) {\n            definition.passThrough = undefined;\n            definition.response = createResponse(status, data, headers, statusText);\n            return chain;\n          }\n        };\n\n    if ($browser) {\n      chain.passThrough = function() {\n        definition.response = undefined;\n        definition.passThrough = true;\n        return chain;\n      };\n    }\n\n    definitions.push(definition);\n    return chain;\n  };\n\n  /**\n   * @ngdoc method\n   * @name $httpBackend#whenGET\n   * @description\n   * Creates a new backend definition for GET requests. For more info see `when()`.\n   *\n   * @param {string|RegExp|function(string)} url HTTP url or function that receives the url\n   *   and returns true if the url match the current definition.\n   * @param {(Object|function(Object))=} headers HTTP headers.\n   * @returns {requestHandler} Returns an object with `respond` method that controls how a matched\n   * request is handled. You can save this object for later use and invoke `respond` again in\n   * order to change how a matched request is handled.\n   */\n\n  /**\n   * @ngdoc method\n   * @name $httpBackend#whenHEAD\n   * @description\n   * Creates a new backend definition for HEAD requests. For more info see `when()`.\n   *\n   * @param {string|RegExp|function(string)} url HTTP url or function that receives the url\n   *   and returns true if the url match the current definition.\n   * @param {(Object|function(Object))=} headers HTTP headers.\n   * @returns {requestHandler} Returns an object with `respond` method that controls how a matched\n   * request is handled. You can save this object for later use and invoke `respond` again in\n   * order to change how a matched request is handled.\n   */\n\n  /**\n   * @ngdoc method\n   * @name $httpBackend#whenDELETE\n   * @description\n   * Creates a new backend definition for DELETE requests. For more info see `when()`.\n   *\n   * @param {string|RegExp|function(string)} url HTTP url or function that receives the url\n   *   and returns true if the url match the current definition.\n   * @param {(Object|function(Object))=} headers HTTP headers.\n   * @returns {requestHandler} Returns an object with `respond` method that controls how a matched\n   * request is handled. You can save this object for later use and invoke `respond` again in\n   * order to change how a matched request is handled.\n   */\n\n  /**\n   * @ngdoc method\n   * @name $httpBackend#whenPOST\n   * @description\n   * Creates a new backend definition for POST requests. For more info see `when()`.\n   *\n   * @param {string|RegExp|function(string)} url HTTP url or function that receives the url\n   *   and returns true if the url match the current definition.\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 controls how a matched\n   * request is handled. You can save this object for later use and invoke `respond` again in\n   * order to change how a matched request is handled.\n   */\n\n  /**\n   * @ngdoc method\n   * @name $httpBackend#whenPUT\n   * @description\n   * Creates a new backend definition for PUT requests.  For more info see `when()`.\n   *\n   * @param {string|RegExp|function(string)} url HTTP url or function that receives the url\n   *   and returns true if the url match the current definition.\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 controls how a matched\n   * request is handled. You can save this object for later use and invoke `respond` again in\n   * order to change how a matched request is handled.\n   */\n\n  /**\n   * @ngdoc method\n   * @name $httpBackend#whenJSONP\n   * @description\n   * Creates a new backend definition for JSONP requests. For more info see `when()`.\n   *\n   * @param {string|RegExp|function(string)} url HTTP url or function that receives the url\n   *   and returns true if the url match the current definition.\n   * @returns {requestHandler} Returns an object with `respond` method that controls how a matched\n   * request is handled. You can save this object for later use and invoke `respond` again in\n   * order to change how a matched request is handled.\n   */\n  createShortMethods('when');\n\n\n  /**\n   * @ngdoc method\n   * @name $httpBackend#expect\n   * @description\n   * Creates a new request expectation.\n   *\n   * @param {string} method HTTP method.\n   * @param {string|RegExp|function(string)} url HTTP url or function that receives the url\n   *   and returns true if the url match the current definition.\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 controls how a matched\n   *  request is handled. You can save this object for later use and invoke `respond` again in\n   *  order to change how a matched request is handled.\n   *\n   *  - respond –\n   *    `{function([status,] data[, headers, statusText])\n   *    | function(function(method, url, data, headers)}`\n   *    – The respond method takes a set of static data to be returned or a function that can\n   *    return an array containing response status (number), response data (string), response\n   *    headers (Object), and the text for the status (string). The respond method returns the\n   *    `requestHandler` object for possible overrides.\n   */\n  $httpBackend.expect = function(method, url, data, headers) {\n    var expectation = new MockHttpExpectation(method, url, data, headers),\n        chain = {\n          respond: function(status, data, headers, statusText) {\n            expectation.response = createResponse(status, data, headers, statusText);\n            return chain;\n          }\n        };\n\n    expectations.push(expectation);\n    return chain;\n  };\n\n\n  /**\n   * @ngdoc method\n   * @name $httpBackend#expectGET\n   * @description\n   * Creates a new request expectation for GET requests. For more info see `expect()`.\n   *\n   * @param {string|RegExp|function(string)} url HTTP url or function that receives the url\n   *   and returns true if the url match the current definition.\n   * @param {Object=} headers HTTP headers.\n   * @returns {requestHandler} Returns an object with `respond` method that controls how a matched\n   * request is handled. You can save this object for later use and invoke `respond` again in\n   * order to change how a matched request is handled. See #expect for more info.\n   */\n\n  /**\n   * @ngdoc method\n   * @name $httpBackend#expectHEAD\n   * @description\n   * Creates a new request expectation for HEAD requests. For more info see `expect()`.\n   *\n   * @param {string|RegExp|function(string)} url HTTP url or function that receives the url\n   *   and returns true if the url match the current definition.\n   * @param {Object=} headers HTTP headers.\n   * @returns {requestHandler} Returns an object with `respond` method that controls how a matched\n   *   request is handled. You can save this object for later use and invoke `respond` again in\n   *   order to change how a matched request is handled.\n   */\n\n  /**\n   * @ngdoc method\n   * @name $httpBackend#expectDELETE\n   * @description\n   * Creates a new request expectation for DELETE requests. For more info see `expect()`.\n   *\n   * @param {string|RegExp|function(string)} url HTTP url or function that receives the url\n   *   and returns true if the url match the current definition.\n   * @param {Object=} headers HTTP headers.\n   * @returns {requestHandler} Returns an object with `respond` method that controls how a matched\n   *   request is handled. You can save this object for later use and invoke `respond` again in\n   *   order to change how a matched request is handled.\n   */\n\n  /**\n   * @ngdoc method\n   * @name $httpBackend#expectPOST\n   * @description\n   * Creates a new request expectation for POST requests. For more info see `expect()`.\n   *\n   * @param {string|RegExp|function(string)} url HTTP url or function that receives the url\n   *   and returns true if the url match the current definition.\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 controls how a matched\n   *   request is handled. You can save this object for later use and invoke `respond` again in\n   *   order to change how a matched request is handled.\n   */\n\n  /**\n   * @ngdoc method\n   * @name $httpBackend#expectPUT\n   * @description\n   * Creates a new request expectation for PUT requests. For more info see `expect()`.\n   *\n   * @param {string|RegExp|function(string)} url HTTP url or function that receives the url\n   *   and returns true if the url match the current definition.\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 controls how a matched\n   *   request is handled. You can save this object for later use and invoke `respond` again in\n   *   order to change how a matched request is handled.\n   */\n\n  /**\n   * @ngdoc method\n   * @name $httpBackend#expectPATCH\n   * @description\n   * Creates a new request expectation for PATCH requests. For more info see `expect()`.\n   *\n   * @param {string|RegExp|function(string)} url HTTP url or function that receives the url\n   *   and returns true if the url match the current definition.\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 controls how a matched\n   *   request is handled. You can save this object for later use and invoke `respond` again in\n   *   order to change how a matched request is handled.\n   */\n\n  /**\n   * @ngdoc method\n   * @name $httpBackend#expectJSONP\n   * @description\n   * Creates a new request expectation for JSONP requests. For more info see `expect()`.\n   *\n   * @param {string|RegExp|function(string)} url HTTP url or function that receives the url\n   *   and returns true if the url match the current definition.\n   * @returns {requestHandler} Returns an object with `respond` method that controls how a matched\n   *   request is handled. You can save this object for later use and invoke `respond` again in\n   *   order to change how a matched request is handled.\n   */\n  createShortMethods('expect');\n\n\n  /**\n   * @ngdoc method\n   * @name $httpBackend#flush\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, digest) {\n    if (digest !== false) $rootScope.$digest();\n    if (!responses.length) throw new Error('No pending request to flush !');\n\n    if (angular.isDefined(count) && count !== null) {\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(digest);\n  };\n\n\n  /**\n   * @ngdoc method\n   * @name $httpBackend#verifyNoOutstandingExpectation\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   * ```js\n   *   afterEach($httpBackend.verifyNoOutstandingExpectation);\n   * ```\n   */\n  $httpBackend.verifyNoOutstandingExpectation = function(digest) {\n    if (digest !== false) $rootScope.$digest();\n    if (expectations.length) {\n      throw new Error('Unsatisfied requests: ' + expectations.join(', '));\n    }\n  };\n\n\n  /**\n   * @ngdoc method\n   * @name $httpBackend#verifyNoOutstandingRequest\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   * ```js\n   *   afterEach($httpBackend.verifyNoOutstandingRequest);\n   * ```\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 $httpBackend#resetExpectations\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', 'HEAD'], 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    if (angular.isFunction(url)) return url(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)) {\n      return angular.equals(angular.fromJson(angular.toJson(data)), angular.fromJson(d));\n    }\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 service\n * @name $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 = ['$delegate', '$browser', function($delegate, $browser) {\n\n  /**\n   * @ngdoc method\n   * @name $timeout#flush\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 $timeout#verifyNoPendingTasks\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\nangular.mock.$RAFDecorator = ['$delegate', function($delegate) {\n  var queue = [];\n  var rafFn = function(fn) {\n    var index = queue.length;\n    queue.push(fn);\n    return function() {\n      queue.splice(index, 1);\n    };\n  };\n\n  rafFn.supported = $delegate.supported;\n\n  rafFn.flush = function() {\n    if (queue.length === 0) {\n      throw new Error('No rAF callbacks present');\n    }\n\n    var length = queue.length;\n    for (var i = 0; i < length; i++) {\n      queue[i]();\n    }\n\n    queue = [];\n  };\n\n  return rafFn;\n}];\n\nangular.mock.$AsyncCallbackDecorator = ['$delegate', function($delegate) {\n  var callbacks = [];\n  var addFn = function(fn) {\n    callbacks.push(fn);\n  };\n  addFn.flush = function() {\n    angular.forEach(callbacks, function(fn) {\n      fn();\n    });\n    callbacks = [];\n  };\n  return addFn;\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 module\n * @name ngMock\n * @packageName angular-mocks\n * @description\n *\n * # ngMock\n *\n * The `ngMock` module provides 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 *\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  $provide.decorator('$$rAF', angular.mock.$RAFDecorator);\n  $provide.decorator('$$asyncCallback', angular.mock.$AsyncCallbackDecorator);\n  $provide.decorator('$rootScope', angular.mock.$RootScopeDecorator);\n}]);\n\n/**\n * @ngdoc module\n * @name ngMockE2E\n * @module ngMockE2E\n * @packageName angular-mocks\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 service\n * @name $httpBackend\n * @module ngMockE2E\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 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 * ```js\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 *       var phone = angular.fromJson(data);\n *       phones.push(phone);\n *       return [200, phone, {}];\n *     });\n *     $httpBackend.whenGET(/^\\/templates\\//).passThrough();\n *     //...\n *   });\n * ```\n *\n * Afterwards, bootstrap your app with this new module.\n */\n\n/**\n * @ngdoc method\n * @name $httpBackend#when\n * @module ngMockE2E\n * @description\n * Creates a new backend definition.\n *\n * @param {string} method HTTP method.\n * @param {string|RegExp|function(string)} url HTTP url or function that receives the url\n *   and returns true if the url match the current definition.\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. You can save this object for later use and invoke\n *   `respond` or `passThrough` again in order to change how a matched request is handled.\n *\n *  - respond –\n *    `{function([status,] data[, headers, statusText])\n *    | 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), response headers\n *    (Object), and the text for the status (string).\n *  - passThrough – `{function()}` – Any request matching a backend definition with\n *    `passThrough` handler will be passed through to the real backend (an XHR request will be made\n *    to the server.)\n *  - Both methods return the `requestHandler` object for possible overrides.\n */\n\n/**\n * @ngdoc method\n * @name $httpBackend#whenGET\n * @module ngMockE2E\n * @description\n * Creates a new backend definition for GET requests. For more info see `when()`.\n *\n * @param {string|RegExp|function(string)} url HTTP url or function that receives the url\n *   and returns true if the url match the current definition.\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. You can save this object for later use and invoke\n *   `respond` or `passThrough` again in order to change how a matched request is handled.\n */\n\n/**\n * @ngdoc method\n * @name $httpBackend#whenHEAD\n * @module ngMockE2E\n * @description\n * Creates a new backend definition for HEAD requests. For more info see `when()`.\n *\n * @param {string|RegExp|function(string)} url HTTP url or function that receives the url\n *   and returns true if the url match the current definition.\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. You can save this object for later use and invoke\n *   `respond` or `passThrough` again in order to change how a matched request is handled.\n */\n\n/**\n * @ngdoc method\n * @name $httpBackend#whenDELETE\n * @module ngMockE2E\n * @description\n * Creates a new backend definition for DELETE requests. For more info see `when()`.\n *\n * @param {string|RegExp|function(string)} url HTTP url or function that receives the url\n *   and returns true if the url match the current definition.\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. You can save this object for later use and invoke\n *   `respond` or `passThrough` again in order to change how a matched request is handled.\n */\n\n/**\n * @ngdoc method\n * @name $httpBackend#whenPOST\n * @module ngMockE2E\n * @description\n * Creates a new backend definition for POST requests. For more info see `when()`.\n *\n * @param {string|RegExp|function(string)} url HTTP url or function that receives the url\n *   and returns true if the url match the current definition.\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. You can save this object for later use and invoke\n *   `respond` or `passThrough` again in order to change how a matched request is handled.\n */\n\n/**\n * @ngdoc method\n * @name $httpBackend#whenPUT\n * @module ngMockE2E\n * @description\n * Creates a new backend definition for PUT requests.  For more info see `when()`.\n *\n * @param {string|RegExp|function(string)} url HTTP url or function that receives the url\n *   and returns true if the url match the current definition.\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. You can save this object for later use and invoke\n *   `respond` or `passThrough` again in order to change how a matched request is handled.\n */\n\n/**\n * @ngdoc method\n * @name $httpBackend#whenPATCH\n * @module ngMockE2E\n * @description\n * Creates a new backend definition for PATCH requests.  For more info see `when()`.\n *\n * @param {string|RegExp|function(string)} url HTTP url or function that receives the url\n *   and returns true if the url match the current definition.\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. You can save this object for later use and invoke\n *   `respond` or `passThrough` again in order to change how a matched request is handled.\n */\n\n/**\n * @ngdoc method\n * @name $httpBackend#whenJSONP\n * @module ngMockE2E\n * @description\n * Creates a new backend definition for JSONP requests. For more info see `when()`.\n *\n * @param {string|RegExp|function(string)} url HTTP url or function that receives the url\n *   and returns true if the url match the current definition.\n * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that\n *   control how a matched request is handled. You can save this object for later use and invoke\n *   `respond` or `passThrough` again in order to change how a matched request is handled.\n */\nangular.mock.e2e = {};\nangular.mock.e2e.$httpBackendDecorator =\n  ['$rootScope', '$timeout', '$delegate', '$browser', createHttpBackendMock];\n\n\n/**\n * @ngdoc type\n * @name $rootScope.Scope\n * @module ngMock\n * @description\n * {@link ng.$rootScope.Scope Scope} type decorated with helper methods useful for testing. These\n * methods are automatically available on any {@link ng.$rootScope.Scope Scope} instance when\n * `ngMock` module is loaded.\n *\n * In addition to all the regular `Scope` methods, the following helper methods are available:\n */\nangular.mock.$RootScopeDecorator = ['$delegate', function($delegate) {\n\n  var $rootScopePrototype = Object.getPrototypeOf($delegate);\n\n  $rootScopePrototype.$countChildScopes = countChildScopes;\n  $rootScopePrototype.$countWatchers = countWatchers;\n\n  return $delegate;\n\n  // ------------------------------------------------------------------------------------------ //\n\n  /**\n   * @ngdoc method\n   * @name $rootScope.Scope#$countChildScopes\n   * @module ngMock\n   * @description\n   * Counts all the direct and indirect child scopes of the current scope.\n   *\n   * The current scope is excluded from the count. The count includes all isolate child scopes.\n   *\n   * @returns {number} Total number of child scopes.\n   */\n  function countChildScopes() {\n    // jshint validthis: true\n    var count = 0; // exclude the current scope\n    var pendingChildHeads = [this.$$childHead];\n    var currentScope;\n\n    while (pendingChildHeads.length) {\n      currentScope = pendingChildHeads.shift();\n\n      while (currentScope) {\n        count += 1;\n        pendingChildHeads.push(currentScope.$$childHead);\n        currentScope = currentScope.$$nextSibling;\n      }\n    }\n\n    return count;\n  }\n\n\n  /**\n   * @ngdoc method\n   * @name $rootScope.Scope#$countWatchers\n   * @module ngMock\n   * @description\n   * Counts all the watchers of direct and indirect child scopes of the current scope.\n   *\n   * The watchers of the current scope are included in the count and so are all the watchers of\n   * isolate child scopes.\n   *\n   * @returns {number} Total number of watchers.\n   */\n  function countWatchers() {\n    // jshint validthis: true\n    var count = this.$$watchers ? this.$$watchers.length : 0; // include the current scope\n    var pendingChildHeads = [this.$$childHead];\n    var currentScope;\n\n    while (pendingChildHeads.length) {\n      currentScope = pendingChildHeads.shift();\n\n      while (currentScope) {\n        count += currentScope.$$watchers ? currentScope.$$watchers.length : 0;\n        pendingChildHeads.push(currentScope.$$childHead);\n        currentScope = currentScope.$$nextSibling;\n      }\n    }\n\n    return count;\n  }\n}];\n\n\nif (window.jasmine || window.mocha) {\n\n  var currentSpec = null,\n      annotatedFunctions = [],\n      isSpecRunning = function() {\n        return !!currentSpec;\n      };\n\n  angular.mock.$$annotate = angular.injector.$$annotate;\n  angular.injector.$$annotate = function(fn) {\n    if (typeof fn === 'function' && !fn.$inject) {\n      annotatedFunctions.push(fn);\n    }\n    return angular.mock.$$annotate.apply(this, arguments);\n  };\n\n\n  (window.beforeEach || window.setup)(function() {\n    annotatedFunctions = [];\n    currentSpec = this;\n  });\n\n  (window.afterEach || window.teardown)(function() {\n    var injector = currentSpec.$injector;\n\n    annotatedFunctions.forEach(function(fn) {\n      delete fn.$inject;\n    });\n\n    angular.forEach(currentSpec.$modules, function(module) {\n      if (module && module.$$hashKey) {\n        module.$$hashKey = undefined;\n      }\n    });\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    // 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   * *NOTE*: This function is declared ONLY WHEN running tests with jasmine or mocha\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 registered 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   * *NOTE*: This function is declared ONLY WHEN running tests with jasmine or mocha\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   * ```js\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   * ```\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      var strictDi = !!currentSpec.$injectorStrict;\n      modules.unshift('ngMock');\n      modules.unshift('ng');\n      var injector = currentSpec.$injector;\n      if (!injector) {\n        if (strictDi) {\n          // If strictDi is enabled, annotate the providerInjector blocks\n          angular.forEach(modules, function(moduleFn) {\n            if (typeof moduleFn === \"function\") {\n              angular.injector.$$annotate(moduleFn);\n            }\n          });\n        }\n        injector = currentSpec.$injector = angular.injector(modules, strictDi);\n        currentSpec.$injectorStrict = strictDi;\n      }\n      for (var i = 0, ii = blockFns.length; i < ii; i++) {\n        if (currentSpec.$injectorStrict) {\n          // If the injector is strict / strictDi, and the spec wants to inject using automatic\n          // annotation, then annotate the function here.\n          injector.annotate(blockFns[i]);\n        }\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  angular.mock.inject.strictDi = function(value) {\n    value = arguments.length ? !!value : true;\n    return isSpecRunning() ? workFn() : workFn;\n\n    function workFn() {\n      if (value !== currentSpec.$injectorStrict) {\n        if (currentSpec.$injector) {\n          throw new Error('Injector already created, can not modify strict annotations');\n        } else {\n          currentSpec.$injectorStrict = value;\n        }\n      }\n    }\n  };\n}\n\n\n})(window, window.angular);\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/angular-mocks/bower.json",
    "content": "{\n  \"name\": \"angular-mocks\",\n  \"version\": \"1.3.13\",\n  \"main\": \"./angular-mocks.js\",\n  \"ignore\": [],\n  \"dependencies\": {\n    \"angular\": \"1.3.13\"\n  }\n}\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/angular-mocks/package.json",
    "content": "{\n  \"name\": \"angular-mocks\",\n  \"version\": \"1.3.13\",\n  \"description\": \"AngularJS mocks for testing\",\n  \"main\": \"angular-mocks.js\",\n  \"scripts\": {\n    \"test\": \"echo \\\"Error: no test specified\\\" && exit 1\"\n  },\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/angular/angular.js.git\"\n  },\n  \"keywords\": [\n    \"angular\",\n    \"framework\",\n    \"browser\",\n    \"mocks\",\n    \"testing\",\n    \"client-side\"\n  ],\n  \"author\": \"Angular Core Team <angular-core+npm@google.com>\",\n  \"license\": \"MIT\",\n  \"bugs\": {\n    \"url\": \"https://github.com/angular/angular.js/issues\"\n  },\n  \"homepage\": \"http://angularjs.org\"\n}\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/angular-resource/.bower.json",
    "content": "{\n  \"name\": \"angular-resource\",\n  \"version\": \"1.3.13\",\n  \"main\": \"./angular-resource.js\",\n  \"ignore\": [],\n  \"dependencies\": {\n    \"angular\": \"1.3.13\"\n  },\n  \"homepage\": \"https://github.com/angular/bower-angular-resource\",\n  \"_release\": \"1.3.13\",\n  \"_resolution\": {\n    \"type\": \"version\",\n    \"tag\": \"v1.3.13\",\n    \"commit\": \"0f19e2ca9f4ab1bbc440bd994a063a63cca28ab8\"\n  },\n  \"_source\": \"https://github.com/angular/bower-angular-resource.git\",\n  \"_target\": \"1.3.13\",\n  \"_originalSource\": \"angular-resource\"\n}"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/angular-resource/README.md",
    "content": "# packaged angular-resource\n\nThis repo is for distribution on `npm` and `bower`. The source for this module is in the\n[main AngularJS repo](https://github.com/angular/angular.js/tree/master/src/ngResource).\nPlease file issues and pull requests against that repo.\n\n## Install\n\nYou can install this package either with `npm` or with `bower`.\n\n### npm\n\n```shell\nnpm install angular-resource\n```\n\nAdd a `<script>` to your `index.html`:\n\n```html\n<script src=\"/node_modules/angular-resource/angular-resource.js\"></script>\n```\n\nThen add `ngResource` as a dependency for your app:\n\n```javascript\nangular.module('myApp', ['ngResource']);\n```\n\nNote that this package is not in CommonJS format, so doing `require('angular-resource')` will\nreturn `undefined`.\n\n### bower\n\n```shell\nbower install angular-resource\n```\n\nAdd a `<script>` to your `index.html`:\n\n```html\n<script src=\"/bower_components/angular-resource/angular-resource.js\"></script>\n```\n\nThen add `ngResource` as a dependency for your app:\n\n```javascript\nangular.module('myApp', ['ngResource']);\n```\n\n## Documentation\n\nDocumentation is available on the\n[AngularJS docs site](http://docs.angularjs.org/api/ngResource).\n\n## License\n\nThe MIT License\n\nCopyright (c) 2010-2012 Google, Inc. http://angularjs.org\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies 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 FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/angular-resource/angular-resource.js",
    "content": "/**\n * @license AngularJS v1.3.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 module\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 *\n * <div doc-module-components=\"ngResource\"></div>\n *\n * See {@link ngResource.$resource `$resource`} for usage.\n */\n\n/**\n * @ngdoc service\n * @name $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 * By default, trailing slashes will be stripped from the calculated URLs,\n * which can pose problems with server backends that do not expect that\n * behavior.  This can be disabled by configuring the `$resourceProvider` like\n * this:\n *\n * ```js\n     app.config(['$resourceProvider', function($resourceProvider) {\n       // Don't strip trailing slashes from calculated URLs\n       $resourceProvider.defaults.stripTrailingSlashes = false;\n     }]);\n * ```\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 for that parameter will be extracted\n *   from the corresponding property on the `data` object (provided when calling an action method).  For\n *   example, if the `defaultParam` object is `{someParam: '@someProp'}` then the value of `someParam`\n *   will be `data.someProp`.\n *\n * @param {Object.<Object>=} actions Hash with declaration of custom actions that should extend\n *   the default set of resource actions. The declaration should be created in the format of {@link\n *   ng.$http#usage $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} – Case insensitive HTTP method (e.g. `GET`, `POST`, `PUT`,\n *     `DELETE`, `JSONP`, etc).\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 *     By default, transformRequest will contain one function that checks if the request data is\n *     an object and serializes to using `angular.toJson`. To prevent this behavior, set\n *     `transformRequest` to an empty array: `transformRequest: []`\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 *     By default, transformResponse will contain one function that checks if the response looks like\n *     a JSON string and deserializes it using `angular.fromJson`. To prevent this behavior, set\n *     `transformResponse` to an empty array: `transformResponse: []`\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\n *     [requests with credentials](https://developer.mozilla.org/en/http_access_control#section_5)\n *     for more information.\n *   - **`responseType`** - `{string}` - see\n *     [requestType](https://developer.mozilla.org/en-US/docs/DOM/XMLHttpRequest#responseType).\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 * @param {Object} options Hash with custom settings that should extend the\n *   default `$resourceProvider` behavior.  The only supported option is\n *\n *   Where:\n *\n *   - **`stripTrailingSlashes`** – {boolean} – If true then the trailing\n *   slashes from any calculated URL will be stripped. (Defaults to true.)\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 *   ```js\n *   { 'get':    {method:'GET'},\n *     'save':   {method:'POST'},\n *     'query':  {method:'GET', isArray:true},\n *     'remove': {method:'DELETE'},\n *     'delete': {method:'DELETE'} };\n *   ```\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 *   ```js\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 *   ```\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 *     If an interceptor object was provided, the promise will instead be resolved with the value\n *     returned by the interceptor.\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 * ```js\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 * ```\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   ```js\n     var User = $resource('/user/:userId', {userId:'@id'});\n     User.get({userId:123}, function(user) {\n       user.abc = true;\n       user.$save();\n     });\n   ```\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   ```js\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   ```\n *\n * You can also access the raw `$http` promise via the `$promise` property on the object returned\n *\n   ```\n     var User = $resource('/user/:userId', {userId:'@id'});\n     User.get({userId:123})\n         .$promise.then(function(user) {\n           $scope.user = user;\n         });\n   ```\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 * ```js\n *    var app = angular.module('app', ['ngResource', 'ngRoute']);\n *\n *    // Some APIs expect a PUT request in the format URL/object/ID\n *    // Here we are creating an 'update' method\n *    app.factory('Notes', ['$resource', function($resource) {\n *    return $resource('/notes/:id', null,\n *        {\n *            'update': { method:'PUT' }\n *        });\n *    }]);\n *\n *    // In our controller we get the ID from the URL using ngRoute and $routeParams\n *    // We pass in $routeParams and our Notes factory along with $scope\n *    app.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 *    }]);\n * ```\n */\nangular.module('ngResource', ['ng']).\n  provider('$resource', function() {\n    var provider = this;\n\n    this.defaults = {\n      // Strip slashes by default\n      stripTrailingSlashes: true,\n\n      // Default actions configuration\n      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    };\n\n    this.$get = ['$http', '$q', function($http, $q) {\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\n       * (pchar) allowed in path 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 = extend({}, provider.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 (unless this behavior is specifically disabled)\n          if (self.defaults.stripTrailingSlashes) {\n            url = url.replace(/\\/+$/, '') || '/';\n          }\n\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, options) {\n        var route = new Route(url, options);\n\n        actions = extend({}, provider.defaults.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        Resource.prototype.toJSON = function() {\n          var data = extend({}, this);\n          delete data.$promise;\n          delete data.$resolved;\n          return data;\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',\n                      'Error in resource configuration for action `{0}`. Expected response to ' +\n                      'contain an {1} but got an {2}', name, action.isArray ? 'array' : 'object',\n                    angular.isArray(data) ? 'array' : 'object');\n                }\n                // jshint +W018\n                if (action.isArray) {\n                  value.length = 0;\n                  forEach(data, function(item) {\n                    if (typeof item === \"object\") {\n                      value.push(new Resource(item));\n                    } else {\n                      // Valid JSON values may be string literals, and these should not be converted\n                      // into objects. These items will not have access to the Resource prototype\n                      // methods, but unfortunately there\n                      value.push(item);\n                    }\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\n})(window, window.angular);\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/angular-resource/bower.json",
    "content": "{\n  \"name\": \"angular-resource\",\n  \"version\": \"1.3.13\",\n  \"main\": \"./angular-resource.js\",\n  \"ignore\": [],\n  \"dependencies\": {\n    \"angular\": \"1.3.13\"\n  }\n}\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/angular-resource/package.json",
    "content": "{\n  \"name\": \"angular-resource\",\n  \"version\": \"1.3.13\",\n  \"description\": \"AngularJS module for interacting with RESTful server-side data sources\",\n  \"main\": \"angular-resource.js\",\n  \"scripts\": {\n    \"test\": \"echo \\\"Error: no test specified\\\" && exit 1\"\n  },\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/angular/angular.js.git\"\n  },\n  \"keywords\": [\n    \"angular\",\n    \"framework\",\n    \"browser\",\n    \"rest\",\n    \"client-side\"\n  ],\n  \"author\": \"Angular Core Team <angular-core+npm@google.com>\",\n  \"license\": \"MIT\",\n  \"bugs\": {\n    \"url\": \"https://github.com/angular/angular.js/issues\"\n  },\n  \"homepage\": \"http://angularjs.org\"\n}\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/angular-route/.bower.json",
    "content": "{\n  \"name\": \"angular-route\",\n  \"version\": \"1.3.13\",\n  \"main\": \"./angular-route.js\",\n  \"ignore\": [],\n  \"dependencies\": {\n    \"angular\": \"1.3.13\"\n  },\n  \"homepage\": \"https://github.com/angular/bower-angular-route\",\n  \"_release\": \"1.3.13\",\n  \"_resolution\": {\n    \"type\": \"version\",\n    \"tag\": \"v1.3.13\",\n    \"commit\": \"d5dadc9ae3c16bd246156561a329518bac328c26\"\n  },\n  \"_source\": \"https://github.com/angular/bower-angular-route.git\",\n  \"_target\": \"1.3.13\",\n  \"_originalSource\": \"angular-route\"\n}"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/angular-route/README.md",
    "content": "# packaged angular-route\n\nThis repo is for distribution on `npm` and `bower`. The source for this module is in the\n[main AngularJS repo](https://github.com/angular/angular.js/tree/master/src/ngRoute).\nPlease file issues and pull requests against that repo.\n\n## Install\n\nYou can install this package either with `npm` or with `bower`.\n\n### npm\n\n```shell\nnpm install angular-route\n```\n\nAdd a `<script>` to your `index.html`:\n\n```html\n<script src=\"/node_modules/angular-route/angular-route.js\"></script>\n```\n\nThen add `ngRoute` as a dependency for your app:\n\n```javascript\nangular.module('myApp', ['ngRoute']);\n```\n\nNote that this package is not in CommonJS format, so doing `require('angular-route')` will\nreturn `undefined`.\n\n### bower\n\n```shell\nbower install angular-route\n```\n\nAdd a `<script>` to your `index.html`:\n\n```html\n<script src=\"/bower_components/angular-route/angular-route.js\"></script>\n```\n\nThen add `ngRoute` as a dependency for your app:\n\n```javascript\nangular.module('myApp', ['ngRoute']);\n```\n\n## Documentation\n\nDocumentation is available on the\n[AngularJS docs site](http://docs.angularjs.org/api/ngRoute).\n\n## License\n\nThe MIT License\n\nCopyright (c) 2010-2012 Google, Inc. http://angularjs.org\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies 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 FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/angular-route/angular-route.js",
    "content": "/**\n * @license AngularJS v1.3.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 module\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 *\n * <div doc-module-components=\"ngRoute\"></div>\n */\n /* global -ngRouteModule */\nvar ngRouteModule = angular.module('ngRoute', ['ng']).\n                        provider('$route', $RouteProvider),\n    $routeMinErr = angular.$$minErr('ngRoute');\n\n/**\n * @ngdoc provider\n * @name $routeProvider\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(Object.create(parent), extra);\n  }\n\n  var routes = {};\n\n  /**\n   * @ngdoc method\n   * @name $routeProvider#when\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/slashes/edit` and extract:\n   *\n   *    * `color: brown`\n   *    * `largecode: code/with/slashes`.\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 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    //copy original route object to preserve params inherited from proto chain\n    var routeCopy = angular.copy(route);\n    if (angular.isUndefined(routeCopy.reloadOnSearch)) {\n      routeCopy.reloadOnSearch = true;\n    }\n    if (angular.isUndefined(routeCopy.caseInsensitiveMatch)) {\n      routeCopy.caseInsensitiveMatch = this.caseInsensitiveMatch;\n    }\n    routes[path] = angular.extend(\n      routeCopy,\n      path && pathRegExp(path, routeCopy)\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, routeCopy)\n      );\n    }\n\n    return this;\n  };\n\n  /**\n   * @ngdoc property\n   * @name $routeProvider#caseInsensitiveMatch\n   * @description\n   *\n   * A boolean property indicating if routes defined\n   * using this provider should be matched using a case insensitive\n   * algorithm. Defaults to `false`.\n   */\n  this.caseInsensitiveMatch = false;\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 $routeProvider#otherwise\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|string} params Mapping information to be assigned to `$route.current`.\n   * If called with a string, the value maps to `redirectTo`.\n   * @returns {Object} self\n   */\n  this.otherwise = function(params) {\n    if (typeof params === 'string') {\n      params = {redirectTo: params};\n    }\n    this.when(null, params);\n    return this;\n  };\n\n\n  this.$get = ['$rootScope',\n               '$location',\n               '$routeParams',\n               '$q',\n               '$injector',\n               '$templateRequest',\n               '$sce',\n      function($rootScope, $location, $routeParams, $q, $injector, $templateRequest, $sce) {\n\n    /**\n     * @ngdoc service\n     * @name $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 {Object} routes Object with all route configuration Objects as its properties.\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     * <example name=\"$route-service\" module=\"ngRouteExample\"\n     *          deps=\"angular-route.js\" fixBase=\"true\">\n     *   <file name=\"index.html\">\n     *     <div ng-controller=\"MainController\">\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     *\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('ngRouteExample', ['ngRoute'])\n     *\n     *      .controller('MainController', function($scope, $route, $routeParams, $location) {\n     *          $scope.$route = $route;\n     *          $scope.$location = $location;\n     *          $scope.$routeParams = $routeParams;\n     *      })\n     *\n     *      .controller('BookController', function($scope, $routeParams) {\n     *          $scope.name = \"BookController\";\n     *          $scope.params = $routeParams;\n     *      })\n     *\n     *      .controller('ChapterController', function($scope, $routeParams) {\n     *          $scope.name = \"ChapterController\";\n     *          $scope.params = $routeParams;\n     *      })\n     *\n     *     .config(function($routeProvider, $locationProvider) {\n     *       $routeProvider\n     *        .when('/Book/:bookId', {\n     *         templateUrl: 'book.html',\n     *         controller: 'BookController',\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     *       .when('/Book/:bookId/ch/:chapterId', {\n     *         templateUrl: 'chapter.html',\n     *         controller: 'ChapterController'\n     *       });\n     *\n     *       // configure html5 to get links working on jsfiddle\n     *       $locationProvider.html5Mode(true);\n     *     });\n     *\n     *   </file>\n     *\n     *   <file name=\"protractor.js\" type=\"protractor\">\n     *     it('should load and compile correct template', function() {\n     *       element(by.linkText('Moby: Ch1')).click();\n     *       var content = element(by.css('[ng-view]')).getText();\n     *       expect(content).toMatch(/controller\\: ChapterController/);\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('[ng-view]')).getText();\n     *       expect(content).toMatch(/controller\\: BookController/);\n     *       expect(content).toMatch(/Book Id\\: Scarlet/);\n     *     });\n     *   </file>\n     * </example>\n     */\n\n    /**\n     * @ngdoc event\n     * @name $route#$routeChangeStart\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     * The route change (and the `$location` change that triggered it) can be prevented\n     * by calling `preventDefault` method of the event. See {@link ng.$rootScope.Scope#$on}\n     * for more details about event object.\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 $route#$routeChangeSuccess\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 $route#$routeChangeError\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 $route#$routeUpdate\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        preparedRoute,\n        preparedRouteIsUpdateOnly,\n        $route = {\n          routes: routes,\n\n          /**\n           * @ngdoc method\n           * @name $route#reload\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 and reinstantiates the controller.\n           */\n          reload: function() {\n            forceReload = true;\n            $rootScope.$evalAsync(function() {\n              // Don't support cancellation of a reload for now...\n              prepareRoute();\n              commitRoute();\n            });\n          },\n\n          /**\n           * @ngdoc method\n           * @name $route#updateParams\n           *\n           * @description\n           * Causes `$route` service to update the current URL, replacing\n           * current route parameters with those specified in `newParams`.\n           * Provided property names that match the route's path segment\n           * definitions will be interpolated into the location's path, while\n           * remaining properties will be treated as query params.\n           *\n           * @param {!Object<string, string>} newParams mapping of URL parameter names to values\n           */\n          updateParams: function(newParams) {\n            if (this.current && this.current.$$route) {\n              newParams = angular.extend({}, this.current.params, newParams);\n              $location.path(interpolate(this.current.$$route.originalPath, newParams));\n              // interpolate modifies newParams, only query params are left\n              $location.search(newParams);\n            } else {\n              throw $routeMinErr('norout', 'Tried updating route when with no current route');\n            }\n          }\n        };\n\n    $rootScope.$on('$locationChangeStart', prepareRoute);\n    $rootScope.$on('$locationChangeSuccess', commitRoute);\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 = m[i];\n\n        if (key && val) {\n          params[key.name] = val;\n        }\n      }\n      return params;\n    }\n\n    function prepareRoute($locationEvent) {\n      var lastRoute = $route.current;\n\n      preparedRoute = parseRoute();\n      preparedRouteIsUpdateOnly = preparedRoute && lastRoute && preparedRoute.$$route === lastRoute.$$route\n          && angular.equals(preparedRoute.pathParams, lastRoute.pathParams)\n          && !preparedRoute.reloadOnSearch && !forceReload;\n\n      if (!preparedRouteIsUpdateOnly && (lastRoute || preparedRoute)) {\n        if ($rootScope.$broadcast('$routeChangeStart', preparedRoute, lastRoute).defaultPrevented) {\n          if ($locationEvent) {\n            $locationEvent.preventDefault();\n          }\n        }\n      }\n    }\n\n    function commitRoute() {\n      var lastRoute = $route.current;\n      var nextRoute = preparedRoute;\n\n      if (preparedRouteIsUpdateOnly) {\n        lastRoute.params = nextRoute.params;\n        angular.copy(lastRoute.params, $routeParams);\n        $rootScope.$broadcast('$routeUpdate', lastRoute);\n      } else if (nextRoute || lastRoute) {\n        forceReload = false;\n        $route.current = nextRoute;\n        if (nextRoute) {\n          if (nextRoute.redirectTo) {\n            if (angular.isString(nextRoute.redirectTo)) {\n              $location.path(interpolate(nextRoute.redirectTo, nextRoute.params)).search(nextRoute.params)\n                       .replace();\n            } else {\n              $location.url(nextRoute.redirectTo(nextRoute.pathParams, $location.path(), $location.search()))\n                       .replace();\n            }\n          }\n        }\n\n        $q.when(nextRoute).\n          then(function() {\n            if (nextRoute) {\n              var locals = angular.extend({}, nextRoute.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, null, null, key);\n              });\n\n              if (angular.isDefined(template = nextRoute.template)) {\n                if (angular.isFunction(template)) {\n                  template = template(nextRoute.params);\n                }\n              } else if (angular.isDefined(templateUrl = nextRoute.templateUrl)) {\n                if (angular.isFunction(templateUrl)) {\n                  templateUrl = templateUrl(nextRoute.params);\n                }\n                templateUrl = $sce.getTrustedResourceUrl(templateUrl);\n                if (angular.isDefined(templateUrl)) {\n                  nextRoute.loadedTemplateUrl = templateUrl;\n                  template = $templateRequest(templateUrl);\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 (nextRoute == $route.current) {\n              if (nextRoute) {\n                nextRoute.locals = locals;\n                angular.copy(nextRoute.params, $routeParams);\n              }\n              $rootScope.$broadcast('$routeChangeSuccess', nextRoute, lastRoute);\n            }\n          }, function(error) {\n            if (nextRoute == $route.current) {\n              $rootScope.$broadcast('$routeChangeError', nextRoute, lastRoute, error);\n            }\n          });\n      }\n    }\n\n\n    /**\n     * @returns {Object} 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 {string} 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 service\n * @name $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#search `search()`} and {@link ng.$location#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 * ```js\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 * ```\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 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 name=\"ngView-directive\" module=\"ngViewExample\"\n             deps=\"angular-route.js;angular-animate.js\"\n             animations=\"true\" fixBase=\"true\">\n      <file name=\"index.html\">\n        <div ng-controller=\"MainCtrl 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>$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          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          .config(['$routeProvider', '$locationProvider',\n            function($routeProvider, $locationProvider) {\n              $routeProvider\n                .when('/Book/:bookId', {\n                  templateUrl: 'book.html',\n                  controller: 'BookCtrl',\n                  controllerAs: 'book'\n                })\n                .when('/Book/:bookId/ch/:chapterId', {\n                  templateUrl: 'chapter.html',\n                  controller: 'ChapterCtrl',\n                  controllerAs: 'chapter'\n                });\n\n              $locationProvider.html5Mode(true);\n          }])\n          .controller('MainCtrl', ['$route', '$routeParams', '$location',\n            function($route, $routeParams, $location) {\n              this.$route = $route;\n              this.$location = $location;\n              this.$routeParams = $routeParams;\n          }])\n          .controller('BookCtrl', ['$routeParams', function($routeParams) {\n            this.name = \"BookCtrl\";\n            this.params = $routeParams;\n          }])\n          .controller('ChapterCtrl', ['$routeParams', function($routeParams) {\n            this.name = \"ChapterCtrl\";\n            this.params = $routeParams;\n          }]);\n\n      </file>\n\n      <file name=\"protractor.js\" type=\"protractor\">\n        it('should load and compile correct template', function() {\n          element(by.linkText('Moby: Ch1')).click();\n          var content = element(by.css('[ng-view]')).getText();\n          expect(content).toMatch(/controller\\: ChapterCtrl/);\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('[ng-view]')).getText();\n          expect(content).toMatch(/controller\\: BookCtrl/);\n          expect(content).toMatch(/Book Id\\: Scarlet/);\n        });\n      </file>\n    </example>\n */\n\n\n/**\n * @ngdoc event\n * @name ngView#$viewContentLoaded\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            previousLeaveAnimation,\n            autoScrollExp = attr.autoscroll,\n            onloadExp = attr.onload || '';\n\n        scope.$on('$routeChangeSuccess', update);\n        update();\n\n        function cleanupLastView() {\n          if (previousLeaveAnimation) {\n            $animate.cancel(previousLeaveAnimation);\n            previousLeaveAnimation = null;\n          }\n\n          if (currentScope) {\n            currentScope.$destroy();\n            currentScope = null;\n          }\n          if (currentElement) {\n            previousLeaveAnimation = $animate.leave(currentElement);\n            previousLeaveAnimation.then(function() {\n              previousLeaveAnimation = null;\n            });\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).then(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": "flowable-ui-web/admin/bower_components/angular-route/bower.json",
    "content": "{\n  \"name\": \"angular-route\",\n  \"version\": \"1.3.13\",\n  \"main\": \"./angular-route.js\",\n  \"ignore\": [],\n  \"dependencies\": {\n    \"angular\": \"1.3.13\"\n  }\n}\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/angular-route/package.json",
    "content": "{\n  \"name\": \"angular-route\",\n  \"version\": \"1.3.13\",\n  \"description\": \"AngularJS router module\",\n  \"main\": \"angular-route.js\",\n  \"scripts\": {\n    \"test\": \"echo \\\"Error: no test specified\\\" && exit 1\"\n  },\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/angular/angular.js.git\"\n  },\n  \"keywords\": [\n    \"angular\",\n    \"framework\",\n    \"browser\",\n    \"router\",\n    \"client-side\"\n  ],\n  \"author\": \"Angular Core Team <angular-core+npm@google.com>\",\n  \"license\": \"MIT\",\n  \"bugs\": {\n    \"url\": \"https://github.com/angular/angular.js/issues\"\n  },\n  \"homepage\": \"http://angularjs.org\"\n}\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/angular-sanitize/.bower.json",
    "content": "{\n  \"name\": \"angular-sanitize\",\n  \"version\": \"1.3.13\",\n  \"main\": \"./angular-sanitize.js\",\n  \"ignore\": [],\n  \"dependencies\": {\n    \"angular\": \"1.3.13\"\n  },\n  \"homepage\": \"https://github.com/angular/bower-angular-sanitize\",\n  \"_release\": \"1.3.13\",\n  \"_resolution\": {\n    \"type\": \"version\",\n    \"tag\": \"v1.3.13\",\n    \"commit\": \"ee7a595d32ae566701da29873eb1dfb466e3cfef\"\n  },\n  \"_source\": \"https://github.com/angular/bower-angular-sanitize.git\",\n  \"_target\": \"1.3.13\",\n  \"_originalSource\": \"angular-sanitize\"\n}"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/angular-sanitize/README.md",
    "content": "# packaged angular-sanitize\n\nThis repo is for distribution on `npm` and `bower`. The source for this module is in the\n[main AngularJS repo](https://github.com/angular/angular.js/tree/master/src/ngSanitize).\nPlease file issues and pull requests against that repo.\n\n## Install\n\nYou can install this package either with `npm` or with `bower`.\n\n### npm\n\n```shell\nnpm install angular-sanitize\n```\n\nAdd a `<script>` to your `index.html`:\n\n```html\n<script src=\"/node_modules/angular-sanitize/angular-sanitize.js\"></script>\n```\n\nThen add `ngSanitize` as a dependency for your app:\n\n```javascript\nangular.module('myApp', ['ngSanitize']);\n```\n\nNote that this package is not in CommonJS format, so doing `require('angular-sanitize')` will\nreturn `undefined`.\n\n### bower\n\n```shell\nbower install angular-sanitize\n```\n\nAdd a `<script>` to your `index.html`:\n\n```html\n<script src=\"/bower_components/angular-sanitize/angular-sanitize.js\"></script>\n```\n\nThen add `ngSanitize` as a dependency for your app:\n\n```javascript\nangular.module('myApp', ['ngSanitize']);\n```\n\n## Documentation\n\nDocumentation is available on the\n[AngularJS docs site](http://docs.angularjs.org/api/ngSanitize).\n\n## License\n\nThe MIT License\n\nCopyright (c) 2010-2012 Google, Inc. http://angularjs.org\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies 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 FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/angular-sanitize/angular-sanitize.js",
    "content": "/**\n * @license AngularJS v1.3.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 module\n * @name ngSanitize\n * @description\n *\n * # ngSanitize\n *\n * The `ngSanitize` module provides functionality to sanitize HTML.\n *\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 $sanitize\n * @kind 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. The input may also contain SVG markup.\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   <example module=\"sanitizeExample\" deps=\"angular-sanitize.js\">\n   <file name=\"index.html\">\n     <script>\n         angular.module('sanitizeExample', ['ngSanitize'])\n           .controller('ExampleController', ['$scope', '$sce', function($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=\"ExampleController\">\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   </file>\n   <file name=\"protractor.js\" type=\"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   </file>\n   </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       /^<((?:[a-zA-Z])[\\w:-]*)((?:\\s+[\\w:-]+(?:\\s*=\\s*(?:(?:\"[^\"]*\")|(?:'[^']*')|[^>\\s]+))?)*)\\s*(\\/?)\\s*(>?)/,\n  END_TAG_REGEXP = /^<\\/\\s*([\\w:-]+)[^>]*>/,\n  ATTR_REGEXP = /([\\w:-]+)(?:\\s*=\\s*(?:(?:\"((?:[^\"])*)\")|(?:'((?:[^'])*)')|([^>\\s]+)))?/g,\n  BEGIN_TAG_REGEXP = /^</,\n  BEGING_END_TAGE_REGEXP = /^<\\//,\n  COMMENT_REGEXP = /<!--(.*?)-->/g,\n  DOCTYPE_REGEXP = /<!DOCTYPE([^>]*?)>/i,\n  CDATA_REGEXP = /<!\\[CDATA\\[(.*?)]]>/g,\n  SURROGATE_PAIR_REGEXP = /[\\uD800-\\uDBFF][\\uDC00-\\uDFFF]/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// SVG Elements\n// https://wiki.whatwg.org/wiki/Sanitization_rules#svg_Elements\nvar svgElements = makeMap(\"animate,animateColor,animateMotion,animateTransform,circle,defs,\" +\n        \"desc,ellipse,font-face,font-face-name,font-face-src,g,glyph,hkern,image,linearGradient,\" +\n        \"line,marker,metadata,missing-glyph,mpath,path,polygon,polyline,radialGradient,rect,set,\" +\n        \"stop,svg,switch,text,title,tspan,use\");\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                                   svgElements);\n\n//Attributes that have href and hence need to be sanitized\nvar uriAttrs = makeMap(\"background,cite,href,longdesc,src,usemap,xlink:href\");\n\nvar htmlAttrs = makeMap('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\n// SVG attributes (without \"id\" and \"name\" attributes)\n// https://wiki.whatwg.org/wiki/Sanitization_rules#svg_Attributes\nvar svgAttrs = makeMap('accent-height,accumulate,additive,alphabetic,arabic-form,ascent,' +\n    'attributeName,attributeType,baseProfile,bbox,begin,by,calcMode,cap-height,class,color,' +\n    'color-rendering,content,cx,cy,d,dx,dy,descent,display,dur,end,fill,fill-rule,font-family,' +\n    'font-size,font-stretch,font-style,font-variant,font-weight,from,fx,fy,g1,g2,glyph-name,' +\n    'gradientUnits,hanging,height,horiz-adv-x,horiz-origin-x,ideographic,k,keyPoints,' +\n    'keySplines,keyTimes,lang,marker-end,marker-mid,marker-start,markerHeight,markerUnits,' +\n    'markerWidth,mathematical,max,min,offset,opacity,orient,origin,overline-position,' +\n    'overline-thickness,panose-1,path,pathLength,points,preserveAspectRatio,r,refX,refY,' +\n    'repeatCount,repeatDur,requiredExtensions,requiredFeatures,restart,rotate,rx,ry,slope,stemh,' +\n    'stemv,stop-color,stop-opacity,strikethrough-position,strikethrough-thickness,stroke,' +\n    'stroke-dasharray,stroke-dashoffset,stroke-linecap,stroke-linejoin,stroke-miterlimit,' +\n    'stroke-opacity,stroke-width,systemLanguage,target,text-anchor,to,transform,type,u1,u2,' +\n    'underline-position,underline-thickness,unicode,unicode-range,units-per-em,values,version,' +\n    'viewBox,visibility,width,widths,x,x-height,x1,x2,xlink:actuate,xlink:arcrole,xlink:role,' +\n    'xlink:show,xlink:title,xlink:type,xml:base,xml:lang,xml:space,xmlns,xmlns:xlink,y,y1,y2,' +\n    'zoomAndPan');\n\nvar validAttrs = angular.extend({},\n                                uriAttrs,\n                                svgAttrs,\n                                htmlAttrs);\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  if (typeof html !== 'string') {\n    if (html === null || typeof html === 'undefined') {\n      html = '';\n    } else {\n      html = '' + html;\n    }\n  }\n  var index, chars, match, stack = [], last = html, text;\n  stack.last = function() { return stack[stack.length - 1]; };\n\n  while (html) {\n    text = '';\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          // We only have a valid start-tag if there is a '>'.\n          if (match[4]) {\n            html = html.substring(match[0].length);\n            match[0].replace(START_TAG_REGEXP, parseStartTag);\n          }\n          chars = false;\n        } else {\n          // no ending tag found --- this piece should be encoded as an entity.\n          text += '<';\n          html = html.substring(1);\n        }\n      }\n\n      if (chars) {\n        index = html.indexOf(\"<\");\n\n        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      // IE versions 9 and 10 do not understand the regex '[^]', so using a workaround with [\\W\\w].\n      html = html.replace(new RegExp(\"([\\\\W\\\\w]*)<\\\\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 {string} escaped text\n */\nfunction encodeEntities(value) {\n  return value.\n    replace(/&/g, '&amp;').\n    replace(SURROGATE_PAIR_REGEXP, function(value) {\n      var hi = value.charCodeAt(0);\n      var low = value.charCodeAt(1);\n      return '&#' + (((hi - 0xD800) * 0x400) + (low - 0xDC00) + 0x10000) + ';';\n    }).\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 linky\n * @kind 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   <example module=\"linkyExample\" deps=\"angular-sanitize.js\">\n     <file name=\"index.html\">\n       <script>\n         angular.module('linkyExample', ['ngSanitize'])\n           .controller('ExampleController', ['$scope', function($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=\"ExampleController\">\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     </file>\n     <file name=\"protractor.js\" type=\"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     </file>\n   </example>\n */\nangular.module('ngSanitize').filter('linky', ['$sanitize', function($sanitize) {\n  var LINKY_URL_REGEXP =\n        /((ftp|https?):\\/\\/|(www\\.)|(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/www/mailto then assume mailto\n      if (!match[2] && !match[4]) {\n        url = (match[3] ? 'http://' : 'mailto:') + url;\n      }\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                  target,\n                  '\" ');\n      }\n      html.push('href=\"',\n                url.replace(/\"/g, '&quot;'),\n                '\">');\n      addText(text);\n      html.push('</a>');\n    }\n  };\n}]);\n\n\n})(window, window.angular);\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/angular-sanitize/bower.json",
    "content": "{\n  \"name\": \"angular-sanitize\",\n  \"version\": \"1.3.13\",\n  \"main\": \"./angular-sanitize.js\",\n  \"ignore\": [],\n  \"dependencies\": {\n    \"angular\": \"1.3.13\"\n  }\n}\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/angular-sanitize/package.json",
    "content": "{\n  \"name\": \"angular-sanitize\",\n  \"version\": \"1.3.13\",\n  \"description\": \"AngularJS module for sanitizing HTML\",\n  \"main\": \"angular-sanitize.js\",\n  \"scripts\": {\n    \"test\": \"echo \\\"Error: no test specified\\\" && exit 1\"\n  },\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/angular/angular.js.git\"\n  },\n  \"keywords\": [\n    \"angular\",\n    \"framework\",\n    \"browser\",\n    \"html\",\n    \"client-side\"\n  ],\n  \"author\": \"Angular Core Team <angular-core+npm@google.com>\",\n  \"license\": \"MIT\",\n  \"bugs\": {\n    \"url\": \"https://github.com/angular/angular.js/issues\"\n  },\n  \"homepage\": \"http://angularjs.org\"\n}\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/angular-scenario/.bower.json",
    "content": "{\n  \"name\": \"angular-scenario\",\n  \"version\": \"1.3.13\",\n  \"main\": \"./angular-scenario.js\",\n  \"ignore\": [],\n  \"dependencies\": {\n    \"angular\": \"1.3.13\"\n  },\n  \"homepage\": \"https://github.com/angular/bower-angular-scenario\",\n  \"_release\": \"1.3.13\",\n  \"_resolution\": {\n    \"type\": \"version\",\n    \"tag\": \"v1.3.13\",\n    \"commit\": \"a17344ddd44cbe47bba7c6653ce08a76fc395cc5\"\n  },\n  \"_source\": \"https://github.com/angular/bower-angular-scenario.git\",\n  \"_target\": \"1.3.13\",\n  \"_originalSource\": \"angular-scenario\"\n}"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/angular-scenario/README.md",
    "content": "# packaged angular-scenario\n\nThis tool is now in maintenance mode. If you are starting a new project, please use\n[Protractor](https://github.com/angular/protractor). Existing projects using scenario runner are\nadvised to migrate to protractor, as this tool is unlikely to receive updates.\n\nThis repo is for distribution on `npm` and `bower`. The source for this module is in the\n[main AngularJS repo](https://github.com/angular/angular.js/tree/master/src/ngScenario).\nPlease file issues and pull requests against that repo.\n\n## Install\n\nYou can install this package either with `npm` or with `bower`.\n\n### npm\n\n```shell\nnpm install angular-scenario\n```\n\nThe files are then available at `node_modules/angular-scenario/`.\n\nNote that this package is not in CommonJS format, so doing `require('angular-scenario')` will\nreturn `undefined`.\n\n### bower\n\n```shell\nbower install angular-scenario\n```\n\nThe files are then available at `bower_components/angular-scenario/`.\n\n## Documentation\n\nDocumentation is available on the\n[AngularJS docs site](http://docs.angularjs.org/).\n\n## License\n\nThe MIT License\n\nCopyright (c) 2010-2012 Google, Inc. http://angularjs.org\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies 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 FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/angular-scenario/angular-scenario.js",
    "content": "Unexpected error.  File contents could not be restored from local history during undo/redo."
  },
  {
    "path": "flowable-ui-web/admin/bower_components/angular-scenario/bower.json",
    "content": "{\n  \"name\": \"angular-scenario\",\n  \"version\": \"1.3.13\",\n  \"main\": \"./angular-scenario.js\",\n  \"ignore\": [],\n  \"dependencies\": {\n    \"angular\": \"1.3.13\"\n  }\n}\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/angular-scenario/jstd-scenario-adapter-config.js",
    "content": "/**\n * Configuration for jstd scenario adapter \n */\nvar jstdScenarioAdapter = {\n  relativeUrlPrefix: '/build/docs/'\n};\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/angular-scenario/jstd-scenario-adapter.js",
    "content": "/**\n * @license AngularJS v1.0.4\n * (c) 2010-2012 Google, Inc. http://angularjs.org\n * License: MIT\n */\n(function(window) {\n'use strict';\n\n/**\n * JSTestDriver adapter for angular scenario tests\n *\n * Example of jsTestDriver.conf for running scenario tests with JSTD:\n  <pre>\n    server: http://localhost:9877\n\n    load:\n      - lib/angular-scenario.js\n      - lib/jstd-scenario-adapter-config.js\n      - lib/jstd-scenario-adapter.js\n      # your test files go here #\n\n    proxy:\n     - {matcher: \"/your-prefix/*\", server: \"http://localhost:8000/\"}\n  </pre>\n *\n * For more information on how to configure jstd proxy, see {@link http://code.google.com/p/js-test-driver/wiki/Proxy}\n * Note the order of files - it's important !\n *\n * Example of jstd-scenario-adapter-config.js\n  <pre>\n    var jstdScenarioAdapter = {\n      relativeUrlPrefix: '/your-prefix/'\n    };\n  </pre>\n *\n * Whenever you use <code>browser().navigateTo('relativeUrl')</code> in your scenario test, the relativeUrlPrefix will be prepended.\n * You have to configure this to work together with JSTD proxy.\n *\n * Let's assume you are using the above configuration (jsTestDriver.conf and jstd-scenario-adapter-config.js):\n * Now, when you call <code>browser().navigateTo('index.html')</code> in your scenario test, the browser will open /your-prefix/index.html.\n * That matches the proxy, so JSTD will proxy this request to http://localhost:8000/index.html.\n */\n\n/**\n * Custom type of test case\n *\n * @const\n * @see jstestdriver.TestCaseInfo\n */\nvar SCENARIO_TYPE = 'scenario';\n\n/**\n * Plugin for JSTestDriver\n * Connection point between scenario's jstd output and jstestdriver.\n *\n * @see jstestdriver.PluginRegistrar\n */\nfunction JstdPlugin() {\n  var nop = function() {};\n\n  this.reportResult = nop;\n  this.reportEnd = nop;\n  this.runScenario = nop;\n\n  this.name = 'Angular Scenario Adapter';\n\n  /**\n   * Called for each JSTD TestCase\n   *\n   * Handles only SCENARIO_TYPE test cases. There should be only one fake TestCase.\n   * Runs all scenario tests (under one fake TestCase) and report all results to JSTD.\n   *\n   * @param {jstestdriver.TestRunConfiguration} configuration\n   * @param {Function} onTestDone\n   * @param {Function} onAllTestsComplete\n   * @returns {boolean} True if this type of test is handled by this plugin, false otherwise\n   */\n  this.runTestConfiguration = function(configuration, onTestDone, onAllTestsComplete) {\n    if (configuration.getTestCaseInfo().getType() != SCENARIO_TYPE) return false;\n\n    this.reportResult = onTestDone;\n    this.reportEnd = onAllTestsComplete;\n    this.runScenario();\n\n    return true;\n  };\n\n  this.getTestRunsConfigurationFor = function(testCaseInfos, expressions, testRunsConfiguration) {\n    testRunsConfiguration.push(\n        new jstestdriver.TestRunConfiguration(\n            new jstestdriver.TestCaseInfo(\n                'Angular Scenario Tests', function() {}, SCENARIO_TYPE), []));\n\n    return true;\n  };\n}\n\n/**\n * Singleton instance of the plugin\n * Accessed using closure by:\n *  - jstd output (reports to this plugin)\n *  - initScenarioAdapter (register the plugin to jstd)\n */\nvar plugin = new JstdPlugin();\n\n/**\n * Initialise scenario jstd-adapter\n * (only if jstestdriver is defined)\n *\n * @param {Object} jstestdriver Undefined when run from browser (without jstd)\n * @param {Function} initScenarioAndRun Function that inits scenario and runs all the tests\n * @param {Object=} config Configuration object, supported properties:\n *  - relativeUrlPrefix: prefix for all relative links when navigateTo()\n */\nfunction initScenarioAdapter(jstestdriver, initScenarioAndRun, config) {\n  if (jstestdriver) {\n    // create and register ScenarioPlugin\n    jstestdriver.pluginRegistrar.register(plugin);\n    plugin.runScenario = initScenarioAndRun;\n\n    /**\n     * HACK (angular.scenario.Application.navigateTo)\n     *\n     * We need to navigate to relative urls when running from browser (without JSTD),\n     * because we want to allow running scenario tests without creating its own virtual host.\n     * For example: http://angular.local/build/docs/docs-scenario.html\n     *\n     * On the other hand, when running with JSTD, we need to navigate to absolute urls,\n     * because of JSTD proxy. (proxy, because of same domain policy)\n     *\n     * So this hack is applied only if running with JSTD and change all relative urls to absolute.\n     */\n    var appProto = angular.scenario.Application.prototype,\n        navigateTo = appProto.navigateTo,\n        relativeUrlPrefix = config && config.relativeUrlPrefix || '/';\n\n    appProto.navigateTo = function(url, loadFn, errorFn) {\n      if (url.charAt(0) != '/' && url.charAt(0) != '#' &&\n          url != 'about:blank' && !url.match(/^https?/)) {\n        url = relativeUrlPrefix + url;\n      }\n\n      return navigateTo.call(this, url, loadFn, errorFn);\n    };\n  }\n}\n\n/**\n * Builds proper TestResult object from given model spec\n *\n * TODO(vojta) report error details\n *\n * @param {angular.scenario.ObjectModel.Spec} spec\n * @returns {jstestdriver.TestResult}\n */\nfunction createTestResultFromSpec(spec) {\n  var map = {\n    success: 'PASSED',\n    error:   'ERROR',\n    failure: 'FAILED'\n  };\n\n  return new jstestdriver.TestResult(\n    spec.fullDefinitionName,\n    spec.name,\n    jstestdriver.TestResult.RESULT[map[spec.status]],\n    spec.error || '',\n    spec.line || '',\n    spec.duration);\n}\n\n/**\n * Generates JSTD output (jstestdriver.TestResult)\n */\nangular.scenario.output('jstd', function(context, runner, model) {\n  model.on('SpecEnd', function(spec) {\n    plugin.reportResult(createTestResultFromSpec(spec));\n  });\n\n  model.on('RunnerEnd', function() {\n    plugin.reportEnd();\n  });\n});\ninitScenarioAdapter(window.jstestdriver, angular.scenario.setUpAndRun, window.jstdScenarioAdapter);\n})(window);\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/angular-scenario/package.json",
    "content": "{\n  \"name\": \"angular-scenario\",\n  \"version\": \"1.3.13\",\n  \"description\": \"AngularJS module for end-to-end testing\",\n  \"main\": \"angular-scenario.js\",\n  \"scripts\": {\n    \"test\": \"echo \\\"Error: no test specified\\\" && exit 1\"\n  },\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/angular/angular.js.git\"\n  },\n  \"keywords\": [\n    \"angular\",\n    \"framework\",\n    \"browser\",\n    \"testing\",\n    \"client-side\"\n  ],\n  \"author\": \"Angular Core Team <angular-core+npm@google.com>\",\n  \"license\": \"MIT\",\n  \"bugs\": {\n    \"url\": \"https://github.com/angular/angular.js/issues\"\n  },\n  \"homepage\": \"http://angularjs.org\"\n}\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/angular-translate/.bower.json",
    "content": "{\n  \"name\": \"angular-translate\",\n  \"version\": \"2.4.2\",\n  \"main\": \"./angular-translate.js\",\n  \"ignore\": [],\n  \"homepage\": \"https://github.com/PascalPrecht/bower-angular-translate\",\n  \"_release\": \"2.4.2\",\n  \"_resolution\": {\n    \"type\": \"version\",\n    \"tag\": \"2.4.2\",\n    \"commit\": \"7533b4a01684282d034c887f4234c99b0f2ebb39\"\n  },\n  \"_source\": \"https://github.com/PascalPrecht/bower-angular-translate.git\",\n  \"_target\": \"2.4.2\",\n  \"_originalSource\": \"angular-translate\"\n}"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/angular-translate/angular-translate.js",
    "content": "/*!\n * angular-translate - v2.15.1 - 2017-03-04\n * \n * Copyright (c) 2017 The angular-translate team, Pascal Precht; Licensed MIT\n */\n(function (root, factory) {\n  if (typeof define === 'function' && define.amd) {\n    // AMD. Register as an anonymous module unless amdModuleId is set\n    define([], function () {\n      return (factory());\n    });\n  } else if (typeof exports === 'object') {\n    // Node. Does not work with strict CommonJS, but\n    // only CommonJS-like environments that support module.exports,\n    // like Node.\n    module.exports = factory();\n  } else {\n    factory();\n  }\n}(this, function () {\n\n/**\n * @ngdoc overview\n * @name pascalprecht.translate\n *\n * @description\n * The main module which holds everything together.\n */\nrunTranslate.$inject = ['$translate'];\n$translate.$inject = ['$STORAGE_KEY', '$windowProvider', '$translateSanitizationProvider', 'pascalprechtTranslateOverrider'];\n$translateDefaultInterpolation.$inject = ['$interpolate', '$translateSanitization'];\ntranslateDirective.$inject = ['$translate', '$interpolate', '$compile', '$parse', '$rootScope'];\ntranslateAttrDirective.$inject = ['$translate', '$rootScope'];\ntranslateCloakDirective.$inject = ['$translate', '$rootScope'];\ntranslateFilterFactory.$inject = ['$parse', '$translate'];\n$translationCache.$inject = ['$cacheFactory'];\nangular.module('pascalprecht.translate', ['ng'])\n  .run(runTranslate);\n\nfunction runTranslate($translate) {\n\n  'use strict';\n\n  var key = $translate.storageKey(),\n    storage = $translate.storage();\n\n  var fallbackFromIncorrectStorageValue = function () {\n    var preferred = $translate.preferredLanguage();\n    if (angular.isString(preferred)) {\n      $translate.use(preferred);\n      // $translate.use() will also remember the language.\n      // So, we don't need to call storage.put() here.\n    } else {\n      storage.put(key, $translate.use());\n    }\n  };\n\n  fallbackFromIncorrectStorageValue.displayName = 'fallbackFromIncorrectStorageValue';\n\n  if (storage) {\n    if (!storage.get(key)) {\n      fallbackFromIncorrectStorageValue();\n    } else {\n      $translate.use(storage.get(key))['catch'](fallbackFromIncorrectStorageValue);\n    }\n  } else if (angular.isString($translate.preferredLanguage())) {\n    $translate.use($translate.preferredLanguage());\n  }\n}\n\nrunTranslate.displayName = 'runTranslate';\n\n/**\n * @ngdoc object\n * @name pascalprecht.translate.$translateSanitizationProvider\n *\n * @description\n *\n * Configurations for $translateSanitization\n */\nangular.module('pascalprecht.translate').provider('$translateSanitization', $translateSanitizationProvider);\n\nfunction $translateSanitizationProvider () {\n\n  'use strict';\n\n  var $sanitize,\n      $sce,\n      currentStrategy = null, // TODO change to either 'sanitize', 'escape' or ['sanitize', 'escapeParameters'] in 3.0.\n      hasConfiguredStrategy = false,\n      hasShownNoStrategyConfiguredWarning = false,\n      strategies;\n\n  /**\n   * Definition of a sanitization strategy function\n   * @callback StrategyFunction\n   * @param {string|object} value - value to be sanitized (either a string or an interpolated value map)\n   * @param {string} mode - either 'text' for a string (translation) or 'params' for the interpolated params\n   * @return {string|object}\n   */\n\n  /**\n   * @ngdoc property\n   * @name strategies\n   * @propertyOf pascalprecht.translate.$translateSanitizationProvider\n   *\n   * @description\n   * Following strategies are built-in:\n   * <dl>\n   *   <dt>sanitize</dt>\n   *   <dd>Sanitizes HTML in the translation text using $sanitize</dd>\n   *   <dt>escape</dt>\n   *   <dd>Escapes HTML in the translation</dd>\n   *   <dt>sanitizeParameters</dt>\n   *   <dd>Sanitizes HTML in the values of the interpolation parameters using $sanitize</dd>\n   *   <dt>escapeParameters</dt>\n   *   <dd>Escapes HTML in the values of the interpolation parameters</dd>\n   *   <dt>escaped</dt>\n   *   <dd>Support legacy strategy name 'escaped' for backwards compatibility (will be removed in 3.0)</dd>\n   * </dl>\n   *\n   */\n\n  strategies = {\n    sanitize: function (value, mode/*, context*/) {\n      if (mode === 'text') {\n        value = htmlSanitizeValue(value);\n      }\n      return value;\n    },\n    escape: function (value, mode/*, context*/) {\n      if (mode === 'text') {\n        value = htmlEscapeValue(value);\n      }\n      return value;\n    },\n    sanitizeParameters: function (value, mode/*, context*/) {\n      if (mode === 'params') {\n        value = mapInterpolationParameters(value, htmlSanitizeValue);\n      }\n      return value;\n    },\n    escapeParameters: function (value, mode/*, context*/) {\n      if (mode === 'params') {\n        value = mapInterpolationParameters(value, htmlEscapeValue);\n      }\n      return value;\n    },\n    sce: function (value, mode, context) {\n      if (mode === 'text') {\n        value = htmlTrustValue(value);\n      } else if (mode === 'params') {\n        if (context !== 'filter') {\n          // do html escape in filter context #1101\n          value = mapInterpolationParameters(value, htmlEscapeValue);\n        }\n      }\n      return value;\n    },\n    sceParameters: function (value, mode/*, context*/) {\n      if (mode === 'params') {\n        value = mapInterpolationParameters(value, htmlTrustValue);\n      }\n      return value;\n    }\n  };\n  // Support legacy strategy name 'escaped' for backwards compatibility.\n  // TODO should be removed in 3.0\n  strategies.escaped = strategies.escapeParameters;\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateSanitizationProvider#addStrategy\n   * @methodOf pascalprecht.translate.$translateSanitizationProvider\n   *\n   * @description\n   * Adds a sanitization strategy to the list of known strategies.\n   *\n   * @param {string} strategyName - unique key for a strategy\n   * @param {StrategyFunction} strategyFunction - strategy function\n   * @returns {object} this\n   */\n  this.addStrategy = function (strategyName, strategyFunction) {\n    strategies[strategyName] = strategyFunction;\n    return this;\n  };\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateSanitizationProvider#removeStrategy\n   * @methodOf pascalprecht.translate.$translateSanitizationProvider\n   *\n   * @description\n   * Removes a sanitization strategy from the list of known strategies.\n   *\n   * @param {string} strategyName - unique key for a strategy\n   * @returns {object} this\n   */\n  this.removeStrategy = function (strategyName) {\n    delete strategies[strategyName];\n    return this;\n  };\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateSanitizationProvider#useStrategy\n   * @methodOf pascalprecht.translate.$translateSanitizationProvider\n   *\n   * @description\n   * Selects a sanitization strategy. When an array is provided the strategies will be executed in order.\n   *\n   * @param {string|StrategyFunction|array} strategy The sanitization strategy / strategies which should be used. Either a name of an existing strategy, a custom strategy function, or an array consisting of multiple names and / or custom functions.\n   * @returns {object} this\n   */\n  this.useStrategy = function (strategy) {\n    hasConfiguredStrategy = true;\n    currentStrategy = strategy;\n    return this;\n  };\n\n  /**\n   * @ngdoc object\n   * @name pascalprecht.translate.$translateSanitization\n   * @requires $injector\n   * @requires $log\n   *\n   * @description\n   * Sanitizes interpolation parameters and translated texts.\n   *\n   */\n  this.$get = ['$injector', '$log', function ($injector, $log) {\n\n    var cachedStrategyMap = {};\n\n    var applyStrategies = function (value, mode, context, selectedStrategies) {\n      angular.forEach(selectedStrategies, function (selectedStrategy) {\n        if (angular.isFunction(selectedStrategy)) {\n          value = selectedStrategy(value, mode, context);\n        } else if (angular.isFunction(strategies[selectedStrategy])) {\n          value = strategies[selectedStrategy](value, mode, context);\n        } else if (angular.isString(strategies[selectedStrategy])) {\n          if (!cachedStrategyMap[strategies[selectedStrategy]]) {\n            try {\n              cachedStrategyMap[strategies[selectedStrategy]] = $injector.get(strategies[selectedStrategy]);\n            } catch (e) {\n              cachedStrategyMap[strategies[selectedStrategy]] = function() {};\n              throw new Error('pascalprecht.translate.$translateSanitization: Unknown sanitization strategy: \\'' + selectedStrategy + '\\'');\n            }\n          }\n          value = cachedStrategyMap[strategies[selectedStrategy]](value, mode, context);\n        } else {\n          throw new Error('pascalprecht.translate.$translateSanitization: Unknown sanitization strategy: \\'' + selectedStrategy + '\\'');\n        }\n      });\n      return value;\n    };\n\n    // TODO: should be removed in 3.0\n    var showNoStrategyConfiguredWarning = function () {\n      if (!hasConfiguredStrategy && !hasShownNoStrategyConfiguredWarning) {\n        $log.warn('pascalprecht.translate.$translateSanitization: No sanitization strategy has been configured. This can have serious security implications. See http://angular-translate.github.io/docs/#/guide/19_security for details.');\n        hasShownNoStrategyConfiguredWarning = true;\n      }\n    };\n\n    if ($injector.has('$sanitize')) {\n      $sanitize = $injector.get('$sanitize');\n    }\n    if ($injector.has('$sce')) {\n      $sce = $injector.get('$sce');\n    }\n\n    return {\n      /**\n       * @ngdoc function\n       * @name pascalprecht.translate.$translateSanitization#useStrategy\n       * @methodOf pascalprecht.translate.$translateSanitization\n       *\n       * @description\n       * Selects a sanitization strategy. When an array is provided the strategies will be executed in order.\n       *\n       * @param {string|StrategyFunction|array} strategy The sanitization strategy / strategies which should be used. Either a name of an existing strategy, a custom strategy function, or an array consisting of multiple names and / or custom functions.\n       */\n      useStrategy: (function (self) {\n        return function (strategy) {\n          self.useStrategy(strategy);\n        };\n      })(this),\n\n      /**\n       * @ngdoc function\n       * @name pascalprecht.translate.$translateSanitization#sanitize\n       * @methodOf pascalprecht.translate.$translateSanitization\n       *\n       * @description\n       * Sanitizes a value.\n       *\n       * @param {string|object} value The value which should be sanitized.\n       * @param {string} mode The current sanitization mode, either 'params' or 'text'.\n       * @param {string|StrategyFunction|array} [strategy] Optional custom strategy which should be used instead of the currently selected strategy.\n       * @param {string} [context] The context of this call: filter, service. Default is service\n       * @returns {string|object} sanitized value\n       */\n      sanitize: function (value, mode, strategy, context) {\n        if (!currentStrategy) {\n          showNoStrategyConfiguredWarning();\n        }\n\n        if (!strategy && strategy !== null) {\n          strategy = currentStrategy;\n        }\n\n        if (!strategy) {\n          return value;\n        }\n\n        if (!context) {\n          context = 'service';\n        }\n\n        var selectedStrategies = angular.isArray(strategy) ? strategy : [strategy];\n        return applyStrategies(value, mode, context, selectedStrategies);\n      }\n    };\n  }];\n\n  var htmlEscapeValue = function (value) {\n    var element = angular.element('<div></div>');\n    element.text(value); // not chainable, see #1044\n    return element.html();\n  };\n\n  var htmlSanitizeValue = function (value) {\n    if (!$sanitize) {\n      throw new Error('pascalprecht.translate.$translateSanitization: Error cannot find $sanitize service. Either include the ngSanitize module (https://docs.angularjs.org/api/ngSanitize) or use a sanitization strategy which does not depend on $sanitize, such as \\'escape\\'.');\n    }\n    return $sanitize(value);\n  };\n\n  var htmlTrustValue = function (value) {\n    if (!$sce) {\n      throw new Error('pascalprecht.translate.$translateSanitization: Error cannot find $sce service.');\n    }\n    return $sce.trustAsHtml(value);\n  };\n\n  var mapInterpolationParameters = function (value, iteratee, stack) {\n    if (angular.isDate(value)) {\n      return value;\n    } else if (angular.isObject(value)) {\n      var result = angular.isArray(value) ? [] : {};\n\n      if (!stack) {\n        stack = [];\n      } else {\n        if (stack.indexOf(value) > -1) {\n          throw new Error('pascalprecht.translate.$translateSanitization: Error cannot interpolate parameter due recursive object');\n        }\n      }\n\n      stack.push(value);\n      angular.forEach(value, function (propertyValue, propertyKey) {\n\n        /* Skipping function properties. */\n        if (angular.isFunction(propertyValue)) {\n          return;\n        }\n\n        result[propertyKey] = mapInterpolationParameters(propertyValue, iteratee, stack);\n      });\n      stack.splice(-1, 1); // remove last\n\n      return result;\n    } else if (angular.isNumber(value)) {\n      return value;\n    } else if (!angular.isUndefined(value) && value !== null) {\n      return iteratee(value);\n    } else {\n      return value;\n    }\n  };\n}\n\n/**\n * @ngdoc object\n * @name pascalprecht.translate.$translateProvider\n * @description\n *\n * $translateProvider allows developers to register translation-tables, asynchronous loaders\n * and similar to configure translation behavior directly inside of a module.\n *\n */\nangular.module('pascalprecht.translate')\n  .constant('pascalprechtTranslateOverrider', {})\n  .provider('$translate', $translate);\n\nfunction $translate($STORAGE_KEY, $windowProvider, $translateSanitizationProvider, pascalprechtTranslateOverrider) {\n\n  'use strict';\n\n  var $translationTable = {},\n    $preferredLanguage,\n    $availableLanguageKeys = [],\n    $languageKeyAliases,\n    $fallbackLanguage,\n    $fallbackWasString,\n    $uses,\n    $nextLang,\n    $storageFactory,\n    $storageKey = $STORAGE_KEY,\n    $storagePrefix,\n    $missingTranslationHandlerFactory,\n    $interpolationFactory,\n    $interpolatorFactories = [],\n    $loaderFactory,\n    $cloakClassName = 'translate-cloak',\n    $loaderOptions,\n    $notFoundIndicatorLeft,\n    $notFoundIndicatorRight,\n    $postCompilingEnabled = false,\n    $forceAsyncReloadEnabled = false,\n    $nestedObjectDelimeter = '.',\n    $isReady = false,\n    $keepContent = false,\n    loaderCache,\n    directivePriority = 0,\n    statefulFilter = true,\n    postProcessFn,\n    uniformLanguageTagResolver = 'default',\n    languageTagResolver = {\n      'default' : function (tag) {\n        return (tag || '').split('-').join('_');\n      },\n      java : function (tag) {\n        var temp = (tag || '').split('-').join('_');\n        var parts = temp.split('_');\n        return parts.length > 1 ? (parts[0].toLowerCase() + '_' + parts[1].toUpperCase()) : temp;\n      },\n      bcp47 : function (tag) {\n        var temp = (tag || '').split('_').join('-');\n        var parts = temp.split('-');\n        return parts.length > 1 ? (parts[0].toLowerCase() + '-' + parts[1].toUpperCase()) : temp;\n      },\n      'iso639-1' : function (tag) {\n        var temp = (tag || '').split('_').join('-');\n        var parts = temp.split('-');\n        return parts[0].toLowerCase();\n      }\n    };\n\n  var version = '2.15.1';\n\n  // tries to determine the browsers language\n  var getFirstBrowserLanguage = function () {\n\n    // internal purpose only\n    if (angular.isFunction(pascalprechtTranslateOverrider.getLocale)) {\n      return pascalprechtTranslateOverrider.getLocale();\n    }\n\n    var nav = $windowProvider.$get().navigator,\n      browserLanguagePropertyKeys = ['language', 'browserLanguage', 'systemLanguage', 'userLanguage'],\n      i,\n      language;\n\n    // support for HTML 5.1 \"navigator.languages\"\n    if (angular.isArray(nav.languages)) {\n      for (i = 0; i < nav.languages.length; i++) {\n        language = nav.languages[i];\n        if (language && language.length) {\n          return language;\n        }\n      }\n    }\n\n    // support for other well known properties in browsers\n    for (i = 0; i < browserLanguagePropertyKeys.length; i++) {\n      language = nav[browserLanguagePropertyKeys[i]];\n      if (language && language.length) {\n        return language;\n      }\n    }\n\n    return null;\n  };\n  getFirstBrowserLanguage.displayName = 'angular-translate/service: getFirstBrowserLanguage';\n\n  // tries to determine the browsers locale\n  var getLocale = function () {\n    var locale = getFirstBrowserLanguage() || '';\n    if (languageTagResolver[uniformLanguageTagResolver]) {\n      locale = languageTagResolver[uniformLanguageTagResolver](locale);\n    }\n    return locale;\n  };\n  getLocale.displayName = 'angular-translate/service: getLocale';\n\n  /**\n   * @name indexOf\n   * @private\n   *\n   * @description\n   * indexOf polyfill. Kinda sorta.\n   *\n   * @param {array} array Array to search in.\n   * @param {string} searchElement Element to search for.\n   *\n   * @returns {int} Index of search element.\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\n  /**\n   * @name trim\n   * @private\n   *\n   * @description\n   * trim polyfill\n   *\n   * @returns {string} The string stripped of whitespace from both ends\n   */\n  var trim = function () {\n    return this.toString().replace(/^\\s+|\\s+$/g, '');\n  };\n\n  var negotiateLocale = function (preferred) {\n    if (!preferred) {\n      return;\n    }\n\n    var avail = [],\n      locale = angular.lowercase(preferred),\n      i = 0,\n      n = $availableLanguageKeys.length;\n\n    for (; i < n; i++) {\n      avail.push(angular.lowercase($availableLanguageKeys[i]));\n    }\n\n    // Check for an exact match in our list of available keys\n    if (indexOf(avail, locale) > -1) {\n      return preferred;\n    }\n\n    if ($languageKeyAliases) {\n      var alias;\n      for (var langKeyAlias in $languageKeyAliases) {\n        if ($languageKeyAliases.hasOwnProperty(langKeyAlias)) {\n          var hasWildcardKey = false;\n          var hasExactKey = Object.prototype.hasOwnProperty.call($languageKeyAliases, langKeyAlias) &&\n            angular.lowercase(langKeyAlias) === angular.lowercase(preferred);\n\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    }\n\n    // Check for a language code without region\n    var parts = preferred.split('_');\n\n    if (parts.length > 1 && indexOf(avail, angular.lowercase(parts[0])) > -1) {\n      return parts[0];\n    }\n\n    // If everything fails, return undefined.\n    return;\n  };\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#translations\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * Registers a new translation table for specific language key.\n   *\n   * To register a translation table for specific language, pass a defined language\n   * key as first parameter.\n   *\n   * <pre>\n   *  // register translation table for language: 'de_DE'\n   *  $translateProvider.translations('de_DE', {\n   *    'GREETING': 'Hallo Welt!'\n   *  });\n   *\n   *  // register another one\n   *  $translateProvider.translations('en_US', {\n   *    'GREETING': 'Hello world!'\n   *  });\n   * </pre>\n   *\n   * When registering multiple translation tables for for the same language key,\n   * the actual translation table gets extended. This allows you to define module\n   * specific translation which only get added, once a specific module is loaded in\n   * your app.\n   *\n   * Invoking this method with no arguments returns the translation table which was\n   * registered with no language key. Invoking it with a language key returns the\n   * related translation table.\n   *\n   * @param {string} langKey A language key.\n   * @param {object} translationTable A plain old JavaScript object that represents a translation table.\n   *\n   */\n  var translations = function (langKey, translationTable) {\n\n    if (!langKey && !translationTable) {\n      return $translationTable;\n    }\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\n  this.translations = translations;\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#cloakClassName\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   *\n   * Let's you change the class name for `translate-cloak` directive.\n   * Default class name is `translate-cloak`.\n   *\n   * @param {string} name translate-cloak class name\n   */\n  this.cloakClassName = function (name) {\n    if (!name) {\n      return $cloakClassName;\n    }\n    $cloakClassName = name;\n    return this;\n  };\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#nestedObjectDelimeter\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   *\n   * Let's you change the delimiter for namespaced translations.\n   * Default delimiter is `.`.\n   *\n   * @param {string} delimiter namespace separator\n   */\n  this.nestedObjectDelimeter = function (delimiter) {\n    if (!delimiter) {\n      return $nestedObjectDelimeter;\n    }\n    $nestedObjectDelimeter = delimiter;\n    return this;\n  };\n\n  /**\n   * @name flatObject\n   * @private\n   *\n   * @description\n   * Flats an object. This function is used to flatten given translation data with\n   * namespaces, so they are later accessible via dot notation.\n   */\n  var flatObject = function (data, path, result, prevKey) {\n    var key, keyWithPath, keyWithShortPath, val;\n\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($nestedObjectDelimeter) + $nestedObjectDelimeter + key) : key;\n        if (path.length && key === prevKey) {\n          // Create shortcut path (foo.bar == foo.bar.bar)\n          keyWithShortPath = '' + path.join($nestedObjectDelimeter);\n          // Link it to original path\n          result[keyWithShortPath] = '@:' + keyWithPath;\n        }\n        result[keyWithPath] = val;\n      }\n    }\n    return result;\n  };\n  flatObject.displayName = 'flatObject';\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#addInterpolation\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * Adds interpolation services to angular-translate, so it can manage them.\n   *\n   * @param {object} factory Interpolation service factory\n   */\n  this.addInterpolation = function (factory) {\n    $interpolatorFactories.push(factory);\n    return this;\n  };\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#useMessageFormatInterpolation\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * Tells angular-translate to use interpolation functionality of messageformat.js.\n   * This is useful when having high level pluralization and gender selection.\n   */\n  this.useMessageFormatInterpolation = function () {\n    return this.useInterpolation('$translateMessageFormatInterpolation');\n  };\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#useInterpolation\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * Tells angular-translate which interpolation style to use as default, application-wide.\n   * Simply pass a factory/service name. The interpolation service has to implement\n   * the correct interface.\n   *\n   * @param {string} factory Interpolation service name.\n   */\n  this.useInterpolation = function (factory) {\n    $interpolationFactory = factory;\n    return this;\n  };\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#useSanitizeStrategy\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * Simply sets a sanitation strategy type.\n   *\n   * @param {string} value Strategy type.\n   */\n  this.useSanitizeValueStrategy = function (value) {\n    $translateSanitizationProvider.useStrategy(value);\n    return this;\n  };\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#preferredLanguage\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * Tells the module which of the registered translation tables to use for translation\n   * at initial startup by passing a language key. Similar to `$translateProvider#use`\n   * only that it says which language to **prefer**.\n   *\n   * @param {string} langKey A language key.\n   */\n  this.preferredLanguage = function (langKey) {\n    if (langKey) {\n      setupPreferredLanguage(langKey);\n      return this;\n    }\n    return $preferredLanguage;\n  };\n  var setupPreferredLanguage = function (langKey) {\n    if (langKey) {\n      $preferredLanguage = langKey;\n    }\n    return $preferredLanguage;\n  };\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#translationNotFoundIndicator\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * Sets an indicator which is used when a translation isn't found. E.g. when\n   * setting the indicator as 'X' and one tries to translate a translation id\n   * called `NOT_FOUND`, this will result in `X NOT_FOUND X`.\n   *\n   * Internally this methods sets a left indicator and a right indicator using\n   * `$translateProvider.translationNotFoundIndicatorLeft()` and\n   * `$translateProvider.translationNotFoundIndicatorRight()`.\n   *\n   * **Note**: These methods automatically add a whitespace between the indicators\n   * and the translation id.\n   *\n   * @param {string} indicator An indicator, could be any string.\n   */\n  this.translationNotFoundIndicator = function (indicator) {\n    this.translationNotFoundIndicatorLeft(indicator);\n    this.translationNotFoundIndicatorRight(indicator);\n    return this;\n  };\n\n  /**\n   * ngdoc function\n   * @name pascalprecht.translate.$translateProvider#translationNotFoundIndicatorLeft\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * Sets an indicator which is used when a translation isn't found left to the\n   * translation id.\n   *\n   * @param {string} indicator An indicator.\n   */\n  this.translationNotFoundIndicatorLeft = function (indicator) {\n    if (!indicator) {\n      return $notFoundIndicatorLeft;\n    }\n    $notFoundIndicatorLeft = indicator;\n    return this;\n  };\n\n  /**\n   * ngdoc function\n   * @name pascalprecht.translate.$translateProvider#translationNotFoundIndicatorLeft\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * Sets an indicator which is used when a translation isn't found right to the\n   * translation id.\n   *\n   * @param {string} indicator An indicator.\n   */\n  this.translationNotFoundIndicatorRight = function (indicator) {\n    if (!indicator) {\n      return $notFoundIndicatorRight;\n    }\n    $notFoundIndicatorRight = indicator;\n    return this;\n  };\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#fallbackLanguage\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * Tells the module which of the registered translation tables to use when missing translations\n   * at initial startup by passing a language key. Similar to `$translateProvider#use`\n   * only that it says which language to **fallback**.\n   *\n   * @param {string||array} langKey A language key.\n   *\n   */\n  this.fallbackLanguage = function (langKey) {\n    fallbackStack(langKey);\n    return this;\n  };\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\n      return this;\n    } else {\n      if ($fallbackWasString) {\n        return $fallbackLanguage[0];\n      } else {\n        return $fallbackLanguage;\n      }\n    }\n  };\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#use\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * Set which translation table to use for translation by given language key. When\n   * trying to 'use' a language which isn't provided, it'll throw an error.\n   *\n   * You actually don't have to use this method since `$translateProvider#preferredLanguage`\n   * does the job too.\n   *\n   * @param {string} langKey A language key.\n   */\n  this.use = function (langKey) {\n    if (langKey) {\n      if (!$translationTable[langKey] && (!$loaderFactory)) {\n        // only throw an error, when not loading translation data asynchronously\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\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#resolveClientLocale\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * This returns the current browser/client's language key. The result is processed with the configured uniform tag resolver.\n   *\n   * @returns {string} the current client/browser language key\n   */\n  this.resolveClientLocale = function () {\n    return getLocale();\n  };\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#storageKey\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * Tells the module which key must represent the choosed language by a user in the storage.\n   *\n   * @param {string} key A key for the storage.\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    return this;\n  };\n\n  this.storageKey = storageKey;\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#useUrlLoader\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * Tells angular-translate to use `$translateUrlLoader` extension service as loader.\n   *\n   * @param {string} url Url\n   * @param {Object=} options Optional configuration object\n   */\n  this.useUrlLoader = function (url, options) {\n    return this.useLoader('$translateUrlLoader', angular.extend({url : url}, options));\n  };\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#useStaticFilesLoader\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * Tells angular-translate to use `$translateStaticFilesLoader` extension service as loader.\n   *\n   * @param {Object=} options Optional configuration object\n   */\n  this.useStaticFilesLoader = function (options) {\n    return this.useLoader('$translateStaticFilesLoader', options);\n  };\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#useLoader\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * Tells angular-translate to use any other service as loader.\n   *\n   * @param {string} loaderFactory Factory name to use\n   * @param {Object=} options Optional configuration object\n   */\n  this.useLoader = function (loaderFactory, options) {\n    $loaderFactory = loaderFactory;\n    $loaderOptions = options || {};\n    return this;\n  };\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#useLocalStorage\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * Tells angular-translate to use `$translateLocalStorage` service as storage layer.\n   *\n   */\n  this.useLocalStorage = function () {\n    return this.useStorage('$translateLocalStorage');\n  };\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#useCookieStorage\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * Tells angular-translate to use `$translateCookieStorage` service as storage layer.\n   */\n  this.useCookieStorage = function () {\n    return this.useStorage('$translateCookieStorage');\n  };\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#useStorage\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * Tells angular-translate to use custom service as storage layer.\n   */\n  this.useStorage = function (storageFactory) {\n    $storageFactory = storageFactory;\n    return this;\n  };\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#storagePrefix\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * Sets prefix for storage key.\n   *\n   * @param {string} prefix Storage key prefix\n   */\n  this.storagePrefix = function (prefix) {\n    if (!prefix) {\n      return prefix;\n    }\n    $storagePrefix = prefix;\n    return this;\n  };\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#useMissingTranslationHandlerLog\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * Tells angular-translate to use built-in log handler when trying to translate\n   * a translation Id which doesn't exist.\n   *\n   * This is actually a shortcut method for `useMissingTranslationHandler()`.\n   *\n   */\n  this.useMissingTranslationHandlerLog = function () {\n    return this.useMissingTranslationHandler('$translateMissingTranslationHandlerLog');\n  };\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#useMissingTranslationHandler\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * Expects a factory name which later gets instantiated with `$injector`.\n   * This method can be used to tell angular-translate to use a custom\n   * missingTranslationHandler. Just build a factory which returns a function\n   * and expects a translation id as argument.\n   *\n   * Example:\n   * <pre>\n   *  app.config(function ($translateProvider) {\n   *    $translateProvider.useMissingTranslationHandler('customHandler');\n   *  });\n   *\n   *  app.factory('customHandler', function (dep1, dep2) {\n   *    return function (translationId) {\n   *      // something with translationId and dep1 and dep2\n   *    };\n   *  });\n   * </pre>\n   *\n   * @param {string} factory Factory name\n   */\n  this.useMissingTranslationHandler = function (factory) {\n    $missingTranslationHandlerFactory = factory;\n    return this;\n  };\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#usePostCompiling\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * If post compiling is enabled, all translated values will be processed\n   * again with AngularJS' $compile.\n   *\n   * Example:\n   * <pre>\n   *  app.config(function ($translateProvider) {\n   *    $translateProvider.usePostCompiling(true);\n   *  });\n   * </pre>\n   *\n   * @param {string} factory Factory name\n   */\n  this.usePostCompiling = function (value) {\n    $postCompilingEnabled = !(!value);\n    return this;\n  };\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#forceAsyncReload\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * If force async reload is enabled, async loader will always be called\n   * even if $translationTable already contains the language key, adding\n   * possible new entries to the $translationTable.\n   *\n   * Example:\n   * <pre>\n   *  app.config(function ($translateProvider) {\n   *    $translateProvider.forceAsyncReload(true);\n   *  });\n   * </pre>\n   *\n   * @param {boolean} value - valid values are true or false\n   */\n  this.forceAsyncReload = function (value) {\n    $forceAsyncReloadEnabled = !(!value);\n    return this;\n  };\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#uniformLanguageTag\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * Tells angular-translate which language tag should be used as a result when determining\n   * the current browser language.\n   *\n   * This setting must be set before invoking {@link pascalprecht.translate.$translateProvider#methods_determinePreferredLanguage determinePreferredLanguage()}.\n   *\n   * <pre>\n   * $translateProvider\n   *   .uniformLanguageTag('bcp47')\n   *   .determinePreferredLanguage()\n   * </pre>\n   *\n   * The resolver currently supports:\n   * * default\n   *     (traditionally: hyphens will be converted into underscores, i.e. en-US => en_US)\n   *     en-US => en_US\n   *     en_US => en_US\n   *     en-us => en_us\n   * * java\n   *     like default, but the second part will be always in uppercase\n   *     en-US => en_US\n   *     en_US => en_US\n   *     en-us => en_US\n   * * BCP 47 (RFC 4646 & 4647)\n   *     en-US => en-US\n   *     en_US => en-US\n   *     en-us => en-US\n   *\n   * See also:\n   * * http://en.wikipedia.org/wiki/IETF_language_tag\n   * * http://www.w3.org/International/core/langtags/\n   * * http://tools.ietf.org/html/bcp47\n   *\n   * @param {string|object} options - options (or standard)\n   * @param {string} options.standard - valid values are 'default', 'bcp47', 'java'\n   */\n  this.uniformLanguageTag = function (options) {\n\n    if (!options) {\n      options = {};\n    } else if (angular.isString(options)) {\n      options = {\n        standard : options\n      };\n    }\n\n    uniformLanguageTagResolver = options.standard;\n\n    return this;\n  };\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#determinePreferredLanguage\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * Tells angular-translate to try to determine on its own which language key\n   * to set as preferred language. When `fn` is given, angular-translate uses it\n   * to determine a language key, otherwise it uses the built-in `getLocale()`\n   * method.\n   *\n   * The `getLocale()` returns a language key in the format `[lang]_[country]` or\n   * `[lang]` depending on what the browser provides.\n   *\n   * Use this method at your own risk, since not all browsers return a valid\n   * locale (see {@link pascalprecht.translate.$translateProvider#methods_uniformLanguageTag uniformLanguageTag()}).\n   *\n   * @param {Function=} fn Function to determine a browser's locale\n   */\n  this.determinePreferredLanguage = function (fn) {\n\n    var locale = (fn && angular.isFunction(fn)) ? fn() : getLocale();\n\n    if (!$availableLanguageKeys.length) {\n      $preferredLanguage = locale;\n    } else {\n      $preferredLanguage = negotiateLocale(locale) || locale;\n    }\n\n    return this;\n  };\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#registerAvailableLanguageKeys\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * Registers a set of language keys the app will work with. Use this method in\n   * combination with\n   * {@link pascalprecht.translate.$translateProvider#determinePreferredLanguage determinePreferredLanguage}.\n   * When available languages keys are registered, angular-translate\n   * tries to find the best fitting language key depending on the browsers locale,\n   * considering your language key convention.\n   *\n   * @param {object} languageKeys Array of language keys the your app will use\n   * @param {object=} aliases Alias map.\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\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#useLoaderCache\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * Registers a cache for internal $http based loaders.\n   * {@link pascalprecht.translate.$translationCache $translationCache}.\n   * When false the cache will be disabled (default). When true or undefined\n   * the cache will be a default (see $cacheFactory). When an object it will\n   * be treat as a cache object itself: the usage is $http({cache: cache})\n   *\n   * @param {object} cache boolean, string or cache-object\n   */\n  this.useLoaderCache = function (cache) {\n    if (cache === false) {\n      // disable cache\n      loaderCache = undefined;\n    } else if (cache === true) {\n      // enable cache using AJS defaults\n      loaderCache = true;\n    } else if (typeof(cache) === 'undefined') {\n      // enable cache using default\n      loaderCache = '$translationCache';\n    } else if (cache) {\n      // enable cache using given one (see $cacheFactory)\n      loaderCache = cache;\n    }\n    return this;\n  };\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#directivePriority\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * Sets the default priority of the translate directive. The standard value is `0`.\n   * Calling this function without an argument will return the current value.\n   *\n   * @param {number} priority for the translate-directive\n   */\n  this.directivePriority = function (priority) {\n    if (priority === undefined) {\n      // getter\n      return directivePriority;\n    } else {\n      // setter with chaining\n      directivePriority = priority;\n      return this;\n    }\n  };\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#statefulFilter\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * Since AngularJS 1.3, filters which are not stateless (depending at the scope)\n   * have to explicit define this behavior.\n   * Sets whether the translate filter should be stateful or stateless. The standard value is `true`\n   * meaning being stateful.\n   * Calling this function without an argument will return the current value.\n   *\n   * @param {boolean} state - defines the state of the filter\n   */\n  this.statefulFilter = function (state) {\n    if (state === undefined) {\n      // getter\n      return statefulFilter;\n    } else {\n      // setter with chaining\n      statefulFilter = state;\n      return this;\n    }\n  };\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#postProcess\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * The post processor will be intercept right after the translation result. It can modify the result.\n   *\n   * @param {object} fn Function or service name (string) to be called after the translation value has been set / resolved. The function itself will enrich every value being processed and then continue the normal resolver process\n   */\n  this.postProcess = function (fn) {\n    if (fn) {\n      postProcessFn = fn;\n    } else {\n      postProcessFn = undefined;\n    }\n    return this;\n  };\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#keepContent\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * If keepContent is set to true than translate directive will always use innerHTML\n   * as a default translation\n   *\n   * Example:\n   * <pre>\n   *  app.config(function ($translateProvider) {\n   *    $translateProvider.keepContent(true);\n   *  });\n   * </pre>\n   *\n   * @param {boolean} value - valid values are true or false\n   */\n  this.keepContent = function (value) {\n    $keepContent = !(!value);\n    return this;\n  };\n\n  /**\n   * @ngdoc object\n   * @name pascalprecht.translate.$translate\n   * @requires $interpolate\n   * @requires $log\n   * @requires $rootScope\n   * @requires $q\n   *\n   * @description\n   * The `$translate` service is the actual core of angular-translate. It expects a translation id\n   * and optional interpolate parameters to translate contents.\n   *\n   * <pre>\n   *  $translate('HEADLINE_TEXT').then(function (translation) {\n   *    $scope.translatedText = translation;\n   *  });\n   * </pre>\n   *\n   * @param {string|array} translationId A token which represents a translation id\n   *                                     This can be optionally an array of translation ids which\n   *                                     results that the function returns an object where each key\n   *                                     is the translation id and the value the translation.\n   * @param {object=} interpolateParams An object hash for dynamic values\n   * @param {string} interpolationId The id of the interpolation to use\n   * @param {string} defaultTranslationText the optional default translation text that is written as\n   *                                        as default text in case it is not found in any configured language\n   * @param {string} forceLanguage A language to be used instead of the current language\n   * @returns {object} promise\n   */\n  this.$get = ['$log', '$injector', '$rootScope', '$q', function ($log, $injector, $rootScope, $q) {\n\n    var Storage,\n      defaultInterpolator = $injector.get($interpolationFactory || '$translateDefaultInterpolation'),\n      pendingLoader = false,\n      interpolatorHashMap = {},\n      langPromises = {},\n      fallbackIndex,\n      startFallbackIteration;\n\n    var $translate = function (translationId, interpolateParams, interpolationId, defaultTranslationText, forceLanguage) {\n      if (!$uses && $preferredLanguage) {\n        $uses = $preferredLanguage;\n      }\n      var uses = (forceLanguage && forceLanguage !== $uses) ? // we don't want to re-negotiate $uses\n        (negotiateLocale(forceLanguage) || forceLanguage) : $uses;\n\n      // Check forceLanguage is present\n      if (forceLanguage) {\n        loadTranslationsIfMissing(forceLanguage);\n      }\n\n      // Duck detection: If the first argument is an array, a bunch of translations was requested.\n      // The result is an object.\n      if (angular.isArray(translationId)) {\n        // Inspired by Q.allSettled by Kris Kowal\n        // https://github.com/kriskowal/q/blob/b0fa72980717dc202ffc3cbf03b936e10ebbb9d7/q.js#L1553-1563\n        // This transforms all promises regardless resolved or rejected\n        var translateAll = function (translationIds) {\n          var results = {}; // storing the actual results\n          var promises = []; // promises to wait for\n          // Wraps the promise a) being always resolved and b) storing the link id->value\n          var translate = function (translationId) {\n            var deferred = $q.defer();\n            var regardless = function (value) {\n              results[translationId] = value;\n              deferred.resolve([translationId, value]);\n            };\n            // we don't care whether the promise was resolved or rejected; just store the values\n            $translate(translationId, interpolateParams, interpolationId, defaultTranslationText, forceLanguage).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          // wait for all (including storing to results)\n          return $q.all(promises).then(function () {\n            // return the results\n            return results;\n          });\n        };\n        return translateAll(translationId);\n      }\n\n      var deferred = $q.defer();\n\n      // trim off any whitespace\n      if (translationId) {\n        translationId = trim.apply(translationId);\n      }\n\n      var promiseToWaitFor = (function () {\n        var promise = $preferredLanguage ?\n          langPromises[$preferredLanguage] :\n          langPromises[uses];\n\n        fallbackIndex = 0;\n\n        if ($storageFactory && !promise) {\n          // looks like there's no pending promise for $preferredLanguage or\n          // $uses. Maybe there's one pending for a language that comes from\n          // storage.\n          var langKey = Storage.get($storageKey);\n          promise = langPromises[langKey];\n\n          if ($fallbackLanguage && $fallbackLanguage.length) {\n            var index = indexOf($fallbackLanguage, langKey);\n            // maybe the language from storage is also defined as fallback language\n            // we increase the fallback language index to not search in that language\n            // as fallback, since it's probably the first used language\n            // in that case the index starts after the first element\n            fallbackIndex = (index === 0) ? 1 : 0;\n\n            // but we can make sure to ALWAYS fallback to preferred language at least\n            if (indexOf($fallbackLanguage, $preferredLanguage) < 0) {\n              $fallbackLanguage.push($preferredLanguage);\n            }\n          }\n        }\n        return promise;\n      }());\n\n      if (!promiseToWaitFor) {\n        // no promise to wait for? okay. Then there's no loader registered\n        // nor is a one pending for language that comes from storage.\n        // We can just translate.\n        determineTranslation(translationId, interpolateParams, interpolationId, defaultTranslationText, uses).then(deferred.resolve, deferred.reject);\n      } else {\n        var promiseResolved = function () {\n          // $uses may have changed while waiting\n          if (!forceLanguage) {\n            uses = $uses;\n          }\n          determineTranslation(translationId, interpolateParams, interpolationId, defaultTranslationText, uses).then(deferred.resolve, deferred.reject);\n        };\n        promiseResolved.displayName = 'promiseResolved';\n\n        promiseToWaitFor['finally'](promiseResolved)\n          .catch(angular.noop); // we don't care about errors here, already handled\n      }\n      return deferred.promise;\n    };\n\n    /**\n     * @name applyNotFoundIndicators\n     * @private\n     *\n     * @description\n     * Applies not fount indicators to given translation id, if needed.\n     * This function gets only executed, if a translation id doesn't exist,\n     * which is why a translation id is expected as argument.\n     *\n     * @param {string} translationId Translation id.\n     * @returns {string} Same as given translation id but applied with not found\n     * indicators.\n     */\n    var applyNotFoundIndicators = function (translationId) {\n      // applying notFoundIndicators\n      if ($notFoundIndicatorLeft) {\n        translationId = [$notFoundIndicatorLeft, translationId].join(' ');\n      }\n      if ($notFoundIndicatorRight) {\n        translationId = [translationId, $notFoundIndicatorRight].join(' ');\n      }\n      return translationId;\n    };\n\n    /**\n     * @name useLanguage\n     * @private\n     *\n     * @description\n     * Makes actual use of a language by setting a given language key as used\n     * language and informs registered interpolators to also use the given\n     * key as locale.\n     *\n     * @param {string} key Locale key.\n     */\n    var useLanguage = function (key) {\n      $uses = key;\n\n      // make sure to store new language key before triggering success event\n      if ($storageFactory) {\n        Storage.put($translate.storageKey(), $uses);\n      }\n\n      $rootScope.$emit('$translateChangeSuccess', {language : key});\n\n      // inform default interpolator\n      defaultInterpolator.setLocale($uses);\n\n      var eachInterpolator = function (interpolator, id) {\n        interpolatorHashMap[id].setLocale($uses);\n      };\n      eachInterpolator.displayName = 'eachInterpolatorLocaleSetter';\n\n      // inform all others too!\n      angular.forEach(interpolatorHashMap, eachInterpolator);\n      $rootScope.$emit('$translateChangeEnd', {language : key});\n    };\n\n    /**\n     * @name loadAsync\n     * @private\n     *\n     * @description\n     * Kicks off registered async loader using `$injector` and applies existing\n     * loader options. When resolved, it updates translation tables accordingly\n     * or rejects with given language key.\n     *\n     * @param {string} key Language key.\n     * @return {Promise} A promise.\n     */\n    var loadAsync = function (key) {\n      if (!key) {\n        throw 'No language key specified for loading.';\n      }\n\n      var deferred = $q.defer();\n\n      $rootScope.$emit('$translateLoadingStart', {language : key});\n      pendingLoader = true;\n\n      var cache = loaderCache;\n      if (typeof(cache) === 'string') {\n        // getting on-demand instance of loader\n        cache = $injector.get(cache);\n      }\n\n      var loaderOptions = angular.extend({}, $loaderOptions, {\n        key : key,\n        $http : angular.extend({}, {\n          cache : cache\n        }, $loaderOptions.$http)\n      });\n\n      var onLoaderSuccess = function (data) {\n        var translationTable = {};\n        $rootScope.$emit('$translateLoadingSuccess', {language : key});\n\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      };\n      onLoaderSuccess.displayName = 'onLoaderSuccess';\n\n      var onLoaderError = function (key) {\n        $rootScope.$emit('$translateLoadingError', {language : key});\n        deferred.reject(key);\n        $rootScope.$emit('$translateLoadingEnd', {language : key});\n      };\n      onLoaderError.displayName = 'onLoaderError';\n\n      $injector.get($loaderFactory)(loaderOptions)\n        .then(onLoaderSuccess, onLoaderError);\n\n      return deferred.promise;\n    };\n\n    if ($storageFactory) {\n      Storage = $injector.get($storageFactory);\n\n      if (!Storage.get || !Storage.put) {\n        throw new Error('Couldn\\'t use storage \\'' + $storageFactory + '\\', missing get() or put() method!');\n      }\n    }\n\n    // if we have additional interpolations that were added via\n    // $translateProvider.addInterpolation(), we have to map'em\n    if ($interpolatorFactories.length) {\n      var eachInterpolationFactory = function (interpolatorFactory) {\n        var interpolator = $injector.get(interpolatorFactory);\n        // setting initial locale for each interpolation service\n        interpolator.setLocale($preferredLanguage || $uses);\n        // make'em recognizable through id\n        interpolatorHashMap[interpolator.getInterpolationIdentifier()] = interpolator;\n      };\n      eachInterpolationFactory.displayName = 'interpolationFactoryAdder';\n\n      angular.forEach($interpolatorFactories, eachInterpolationFactory);\n    }\n\n    /**\n     * @name getTranslationTable\n     * @private\n     *\n     * @description\n     * Returns a promise that resolves to the translation table\n     * or is rejected if an error occurred.\n     *\n     * @param langKey\n     * @returns {Q.promise}\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        var onResolve = function (data) {\n          translations(data.key, data.table);\n          deferred.resolve(data.table);\n        };\n        onResolve.displayName = 'translationTableResolver';\n        langPromises[langKey].then(onResolve, deferred.reject);\n      } else {\n        deferred.reject();\n      }\n      return deferred.promise;\n    };\n\n    /**\n     * @name getFallbackTranslation\n     * @private\n     *\n     * @description\n     * Returns a promise that will resolve to the translation\n     * or be rejected if no translation was found for the language.\n     * This function is currently only used for fallback language translation.\n     *\n     * @param langKey The language to translate to.\n     * @param translationId\n     * @param interpolateParams\n     * @param Interpolator\n     * @param sanitizeStrategy\n     * @returns {Q.promise}\n     */\n    var getFallbackTranslation = function (langKey, translationId, interpolateParams, Interpolator, sanitizeStrategy) {\n      var deferred = $q.defer();\n\n      var onResolve = function (translationTable) {\n        if (Object.prototype.hasOwnProperty.call(translationTable, translationId) && translationTable[translationId] !== null) {\n          Interpolator.setLocale(langKey);\n          var translation = translationTable[translationId];\n          if (translation.substr(0, 2) === '@:') {\n            getFallbackTranslation(langKey, translation.substr(2), interpolateParams, Interpolator, sanitizeStrategy)\n              .then(deferred.resolve, deferred.reject);\n          } else {\n            var interpolatedValue = Interpolator.interpolate(translationTable[translationId], interpolateParams, 'service', sanitizeStrategy, translationId);\n            interpolatedValue = applyPostProcessing(translationId, translationTable[translationId], interpolatedValue, interpolateParams, langKey);\n\n            deferred.resolve(interpolatedValue);\n\n          }\n          Interpolator.setLocale($uses);\n        } else {\n          deferred.reject();\n        }\n      };\n      onResolve.displayName = 'fallbackTranslationResolver';\n\n      getTranslationTable(langKey).then(onResolve, deferred.reject);\n\n      return deferred.promise;\n    };\n\n    /**\n     * @name getFallbackTranslationInstant\n     * @private\n     *\n     * @description\n     * Returns a translation\n     * This function is currently only used for fallback language translation.\n     *\n     * @param langKey The language to translate to.\n     * @param translationId\n     * @param interpolateParams\n     * @param Interpolator\n     * @param sanitizeStrategy sanitize strategy override\n     *\n     * @returns {string} translation\n     */\n    var getFallbackTranslationInstant = function (langKey, translationId, interpolateParams, Interpolator, sanitizeStrategy) {\n      var result, translationTable = $translationTable[langKey];\n\n      if (translationTable && Object.prototype.hasOwnProperty.call(translationTable, translationId) && translationTable[translationId] !== null) {\n        Interpolator.setLocale(langKey);\n        result = Interpolator.interpolate(translationTable[translationId], interpolateParams, 'filter', sanitizeStrategy, translationId);\n        result = applyPostProcessing(translationId, translationTable[translationId], result, interpolateParams, langKey, sanitizeStrategy);\n        // workaround for TrustedValueHolderType\n        if (!angular.isString(result) && angular.isFunction(result.$$unwrapTrustedValue)) {\n          var result2 = result.$$unwrapTrustedValue();\n          if (result2.substr(0, 2) === '@:') {\n            return getFallbackTranslationInstant(langKey, result2.substr(2), interpolateParams, Interpolator, sanitizeStrategy);\n          }\n        } else if (result.substr(0, 2) === '@:') {\n          return getFallbackTranslationInstant(langKey, result.substr(2), interpolateParams, Interpolator, sanitizeStrategy);\n        }\n        Interpolator.setLocale($uses);\n      }\n\n      return result;\n    };\n\n\n    /**\n     * @name translateByHandler\n     * @private\n     *\n     * Translate by missing translation handler.\n     *\n     * @param translationId\n     * @param interpolateParams\n     * @param defaultTranslationText\n     * @param sanitizeStrategy sanitize strategy override\n     *\n     * @returns translation created by $missingTranslationHandler or translationId is $missingTranslationHandler is\n     * absent\n     */\n    var translateByHandler = function (translationId, interpolateParams, defaultTranslationText, sanitizeStrategy) {\n      // If we have a handler factory - we might also call it here to determine if it provides\n      // a default text for a translationid that can't be found anywhere in our tables\n      if ($missingTranslationHandlerFactory) {\n        return $injector.get($missingTranslationHandlerFactory)(translationId, $uses, interpolateParams, defaultTranslationText, sanitizeStrategy);\n      } else {\n        return translationId;\n      }\n    };\n\n    /**\n     * @name resolveForFallbackLanguage\n     * @private\n     *\n     * Recursive helper function for fallbackTranslation that will sequentially look\n     * for a translation in the fallbackLanguages starting with fallbackLanguageIndex.\n     *\n     * @param fallbackLanguageIndex\n     * @param translationId\n     * @param interpolateParams\n     * @param Interpolator\n     * @param defaultTranslationText\n     * @param sanitizeStrategy\n     * @returns {Q.promise} Promise that will resolve to the translation.\n     */\n    var resolveForFallbackLanguage = function (fallbackLanguageIndex, translationId, interpolateParams, Interpolator, defaultTranslationText, sanitizeStrategy) {\n      var deferred = $q.defer();\n\n      if (fallbackLanguageIndex < $fallbackLanguage.length) {\n        var langKey = $fallbackLanguage[fallbackLanguageIndex];\n        getFallbackTranslation(langKey, translationId, interpolateParams, Interpolator, sanitizeStrategy).then(\n          function (data) {\n            deferred.resolve(data);\n          },\n          function () {\n            // Look in the next fallback language for a translation.\n            // It delays the resolving by passing another promise to resolve.\n            return resolveForFallbackLanguage(fallbackLanguageIndex + 1, translationId, interpolateParams, Interpolator, defaultTranslationText, sanitizeStrategy).then(deferred.resolve, deferred.reject);\n          }\n        );\n      } else {\n        // No translation found in any fallback language\n        // if a default translation text is set in the directive, then return this as a result\n        if (defaultTranslationText) {\n          deferred.resolve(defaultTranslationText);\n        } else {\n          var missingTranslationHandlerTranslation = translateByHandler(translationId, interpolateParams, defaultTranslationText);\n\n          // if no default translation is set and an error handler is defined, send it to the handler\n          // and then return the result if it isn't undefined\n          if ($missingTranslationHandlerFactory && missingTranslationHandlerTranslation) {\n            deferred.resolve(missingTranslationHandlerTranslation);\n          } else {\n            deferred.reject(applyNotFoundIndicators(translationId));\n          }\n        }\n      }\n      return deferred.promise;\n    };\n\n    /**\n     * @name resolveForFallbackLanguageInstant\n     * @private\n     *\n     * Recursive helper function for fallbackTranslation that will sequentially look\n     * for a translation in the fallbackLanguages starting with fallbackLanguageIndex.\n     *\n     * @param fallbackLanguageIndex\n     * @param translationId\n     * @param interpolateParams\n     * @param Interpolator\n     * @param sanitizeStrategy\n     * @returns {string} translation\n     */\n    var resolveForFallbackLanguageInstant = function (fallbackLanguageIndex, translationId, interpolateParams, Interpolator, sanitizeStrategy) {\n      var result;\n\n      if (fallbackLanguageIndex < $fallbackLanguage.length) {\n        var langKey = $fallbackLanguage[fallbackLanguageIndex];\n        result = getFallbackTranslationInstant(langKey, translationId, interpolateParams, Interpolator, sanitizeStrategy);\n        if (!result && result !== '') {\n          result = resolveForFallbackLanguageInstant(fallbackLanguageIndex + 1, translationId, interpolateParams, Interpolator);\n        }\n      }\n      return result;\n    };\n\n    /**\n     * Translates with the usage of the fallback languages.\n     *\n     * @param translationId\n     * @param interpolateParams\n     * @param Interpolator\n     * @param defaultTranslationText\n     * @param sanitizeStrategy\n     * @returns {Q.promise} Promise, that resolves to the translation.\n     */\n    var fallbackTranslation = function (translationId, interpolateParams, Interpolator, defaultTranslationText, sanitizeStrategy) {\n      // Start with the fallbackLanguage with index 0\n      return resolveForFallbackLanguage((startFallbackIteration > 0 ? startFallbackIteration : fallbackIndex), translationId, interpolateParams, Interpolator, defaultTranslationText, sanitizeStrategy);\n    };\n\n    /**\n     * Translates with the usage of the fallback languages.\n     *\n     * @param translationId\n     * @param interpolateParams\n     * @param Interpolator\n     * @param sanitizeStrategy\n     * @returns {String} translation\n     */\n    var fallbackTranslationInstant = function (translationId, interpolateParams, Interpolator, sanitizeStrategy) {\n      // Start with the fallbackLanguage with index 0\n      return resolveForFallbackLanguageInstant((startFallbackIteration > 0 ? startFallbackIteration : fallbackIndex), translationId, interpolateParams, Interpolator, sanitizeStrategy);\n    };\n\n    var determineTranslation = function (translationId, interpolateParams, interpolationId, defaultTranslationText, uses, sanitizeStrategy) {\n\n      var deferred = $q.defer();\n\n      var table = uses ? $translationTable[uses] : $translationTable,\n        Interpolator = (interpolationId) ? interpolatorHashMap[interpolationId] : defaultInterpolator;\n\n      // if the translation id exists, we can just interpolate it\n      if (table && Object.prototype.hasOwnProperty.call(table, translationId) && table[translationId] !== null) {\n        var translation = table[translationId];\n\n        // If using link, rerun $translate with linked translationId and return it\n        if (translation.substr(0, 2) === '@:') {\n\n          $translate(translation.substr(2), interpolateParams, interpolationId, defaultTranslationText, uses)\n            .then(deferred.resolve, deferred.reject);\n        } else {\n          //\n          var resolvedTranslation = Interpolator.interpolate(translation, interpolateParams, 'service', sanitizeStrategy, translationId);\n          resolvedTranslation = applyPostProcessing(translationId, translation, resolvedTranslation, interpolateParams, uses);\n          deferred.resolve(resolvedTranslation);\n        }\n      } else {\n        var missingTranslationHandlerTranslation;\n        // for logging purposes only (as in $translateMissingTranslationHandlerLog), value is not returned to promise\n        if ($missingTranslationHandlerFactory && !pendingLoader) {\n          missingTranslationHandlerTranslation = translateByHandler(translationId, interpolateParams, defaultTranslationText);\n        }\n\n        // since we couldn't translate the inital requested translation id,\n        // we try it now with one or more fallback languages, if fallback language(s) is\n        // configured.\n        if (uses && $fallbackLanguage && $fallbackLanguage.length) {\n          fallbackTranslation(translationId, interpolateParams, Interpolator, defaultTranslationText, sanitizeStrategy)\n            .then(function (translation) {\n              deferred.resolve(translation);\n            }, function (_translationId) {\n              deferred.reject(applyNotFoundIndicators(_translationId));\n            });\n        } else if ($missingTranslationHandlerFactory && !pendingLoader && missingTranslationHandlerTranslation) {\n          // looks like the requested translation id doesn't exists.\n          // Now, if there is a registered handler for missing translations and no\n          // asyncLoader is pending, we execute the handler\n          if (defaultTranslationText) {\n            deferred.resolve(defaultTranslationText);\n          } else {\n            deferred.resolve(missingTranslationHandlerTranslation);\n          }\n        } else {\n          if (defaultTranslationText) {\n            deferred.resolve(defaultTranslationText);\n          } else {\n            deferred.reject(applyNotFoundIndicators(translationId));\n          }\n        }\n      }\n      return deferred.promise;\n    };\n\n    var determineTranslationInstant = function (translationId, interpolateParams, interpolationId, uses, sanitizeStrategy) {\n\n      var result, table = uses ? $translationTable[uses] : $translationTable,\n        Interpolator = defaultInterpolator;\n\n      // if the interpolation id exists use custom interpolator\n      if (interpolatorHashMap && Object.prototype.hasOwnProperty.call(interpolatorHashMap, interpolationId)) {\n        Interpolator = interpolatorHashMap[interpolationId];\n      }\n\n      // if the translation id exists, we can just interpolate it\n      if (table && Object.prototype.hasOwnProperty.call(table, translationId) && table[translationId] !== null) {\n        var translation = table[translationId];\n\n        // If using link, rerun $translate with linked translationId and return it\n        if (translation.substr(0, 2) === '@:') {\n          result = determineTranslationInstant(translation.substr(2), interpolateParams, interpolationId, uses, sanitizeStrategy);\n        } else {\n          result = Interpolator.interpolate(translation, interpolateParams, 'filter', sanitizeStrategy, translationId);\n          result = applyPostProcessing(translationId, translation, result, interpolateParams, uses, sanitizeStrategy);\n        }\n      } else {\n        var missingTranslationHandlerTranslation;\n        // for logging purposes only (as in $translateMissingTranslationHandlerLog), value is not returned to promise\n        if ($missingTranslationHandlerFactory && !pendingLoader) {\n          missingTranslationHandlerTranslation = translateByHandler(translationId, interpolateParams, sanitizeStrategy);\n        }\n\n        // since we couldn't translate the inital requested translation id,\n        // we try it now with one or more fallback languages, if fallback language(s) is\n        // configured.\n        if (uses && $fallbackLanguage && $fallbackLanguage.length) {\n          fallbackIndex = 0;\n          result = fallbackTranslationInstant(translationId, interpolateParams, Interpolator, sanitizeStrategy);\n        } else if ($missingTranslationHandlerFactory && !pendingLoader && missingTranslationHandlerTranslation) {\n          // looks like the requested translation id doesn't exists.\n          // Now, if there is a registered handler for missing translations and no\n          // asyncLoader is pending, we execute the handler\n          result = missingTranslationHandlerTranslation;\n        } else {\n          result = applyNotFoundIndicators(translationId);\n        }\n      }\n\n      return result;\n    };\n\n    var clearNextLangAndPromise = function (key) {\n      if ($nextLang === key) {\n        $nextLang = undefined;\n      }\n      langPromises[key] = undefined;\n    };\n\n    var applyPostProcessing = function (translationId, translation, resolvedTranslation, interpolateParams, uses, sanitizeStrategy) {\n      var fn = postProcessFn;\n\n      if (fn) {\n\n        if (typeof(fn) === 'string') {\n          // getting on-demand instance\n          fn = $injector.get(fn);\n        }\n        if (fn) {\n          return fn(translationId, translation, resolvedTranslation, interpolateParams, uses, sanitizeStrategy);\n        }\n      }\n\n      return resolvedTranslation;\n    };\n\n    var loadTranslationsIfMissing = function (key) {\n      if (!$translationTable[key] && $loaderFactory && !langPromises[key]) {\n        langPromises[key] = loadAsync(key).then(function (translation) {\n          translations(translation.key, translation.table);\n          return translation;\n        });\n      }\n    };\n\n    /**\n     * @ngdoc function\n     * @name pascalprecht.translate.$translate#preferredLanguage\n     * @methodOf pascalprecht.translate.$translate\n     *\n     * @description\n     * Returns the language key for the preferred language.\n     *\n     * @param {string} langKey language String or Array to be used as preferredLanguage (changing at runtime)\n     *\n     * @return {string} preferred language key\n     */\n    $translate.preferredLanguage = function (langKey) {\n      if (langKey) {\n        setupPreferredLanguage(langKey);\n      }\n      return $preferredLanguage;\n    };\n\n    /**\n     * @ngdoc function\n     * @name pascalprecht.translate.$translate#cloakClassName\n     * @methodOf pascalprecht.translate.$translate\n     *\n     * @description\n     * Returns the configured class name for `translate-cloak` directive.\n     *\n     * @return {string} cloakClassName\n     */\n    $translate.cloakClassName = function () {\n      return $cloakClassName;\n    };\n\n    /**\n     * @ngdoc function\n     * @name pascalprecht.translate.$translate#nestedObjectDelimeter\n     * @methodOf pascalprecht.translate.$translate\n     *\n     * @description\n     * Returns the configured delimiter for nested namespaces.\n     *\n     * @return {string} nestedObjectDelimeter\n     */\n    $translate.nestedObjectDelimeter = function () {\n      return $nestedObjectDelimeter;\n    };\n\n    /**\n     * @ngdoc function\n     * @name pascalprecht.translate.$translate#fallbackLanguage\n     * @methodOf pascalprecht.translate.$translate\n     *\n     * @description\n     * Returns the language key for the fallback languages or sets a new fallback stack.\n     *\n     * @param {string=} langKey language String or Array of fallback languages to be used (to change stack at runtime)\n     *\n     * @return {string||array} fallback language key\n     */\n    $translate.fallbackLanguage = function (langKey) {\n      if (langKey !== undefined && langKey !== null) {\n        fallbackStack(langKey);\n\n        // as we might have an async loader initiated and a new translation language might have been defined\n        // we need to add the promise to the stack also. So - iterate.\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    };\n\n    /**\n     * @ngdoc function\n     * @name pascalprecht.translate.$translate#useFallbackLanguage\n     * @methodOf pascalprecht.translate.$translate\n     *\n     * @description\n     * Sets the first key of the fallback language stack to be used for translation.\n     * Therefore all languages in the fallback array BEFORE this key will be skipped!\n     *\n     * @param {string=} langKey Contains the langKey the iteration shall start with. Set to false if you want to\n     * get back to the whole stack\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\n    };\n\n    /**\n     * @ngdoc function\n     * @name pascalprecht.translate.$translate#proposedLanguage\n     * @methodOf pascalprecht.translate.$translate\n     *\n     * @description\n     * Returns the language key of language that is currently loaded asynchronously.\n     *\n     * @return {string} language key\n     */\n    $translate.proposedLanguage = function () {\n      return $nextLang;\n    };\n\n    /**\n     * @ngdoc function\n     * @name pascalprecht.translate.$translate#storage\n     * @methodOf pascalprecht.translate.$translate\n     *\n     * @description\n     * Returns registered storage.\n     *\n     * @return {object} Storage\n     */\n    $translate.storage = function () {\n      return Storage;\n    };\n\n    /**\n     * @ngdoc function\n     * @name pascalprecht.translate.$translate#negotiateLocale\n     * @methodOf pascalprecht.translate.$translate\n     *\n     * @description\n     * Returns a language key based on available languages and language aliases. If a\n     * language key cannot be resolved, returns undefined.\n     *\n     * If no or a falsy key is given, returns undefined.\n     *\n     * @param {string} [key] Language key\n     * @return {string|undefined} Language key or undefined if no language key is found.\n     */\n    $translate.negotiateLocale = negotiateLocale;\n\n    /**\n     * @ngdoc function\n     * @name pascalprecht.translate.$translate#use\n     * @methodOf pascalprecht.translate.$translate\n     *\n     * @description\n     * Tells angular-translate which language to use by given language key. This method is\n     * used to change language at runtime. It also takes care of storing the language\n     * key in a configured store to let your app remember the choosed language.\n     *\n     * When trying to 'use' a language which isn't available it tries to load it\n     * asynchronously with registered loaders.\n     *\n     * Returns promise object with loaded language file data or string of the currently used language.\n     *\n     * If no or a falsy key is given it returns the currently used language key.\n     * The returned string will be ```undefined``` if setting up $translate hasn't finished.\n     * @example\n     * $translate.use(\"en_US\").then(function(data){\n       *   $scope.text = $translate(\"HELLO\");\n       * });\n     *\n     * @param {string} [key] Language key\n     * @return {object|string} Promise with loaded language data or the language key if a falsy param was given.\n     */\n    $translate.use = function (key) {\n      if (!key) {\n        return $uses;\n      }\n\n      var deferred = $q.defer();\n      deferred.promise.then(null, angular.noop); // AJS \"Possibly unhandled rejection\"\n\n      $rootScope.$emit('$translateChangeStart', {language : key});\n\n      // Try to get the aliased language key\n      var aliasedKey = negotiateLocale(key);\n      // Ensure only registered language keys will be loaded\n      if ($availableLanguageKeys.length > 0 && !aliasedKey) {\n        return $q.reject(key);\n      }\n\n      if (aliasedKey) {\n        key = aliasedKey;\n      }\n\n      // if there isn't a translation table for the language we've requested,\n      // we load it asynchronously\n      $nextLang = key;\n      if (($forceAsyncReloadEnabled || !$translationTable[key]) && $loaderFactory && !langPromises[key]) {\n        langPromises[key] = loadAsync(key).then(function (translation) {\n          translations(translation.key, translation.table);\n          deferred.resolve(translation.key);\n          if ($nextLang === key) {\n            useLanguage(translation.key);\n          }\n          return translation;\n        }, function (key) {\n          $rootScope.$emit('$translateChangeError', {language : key});\n          deferred.reject(key);\n          $rootScope.$emit('$translateChangeEnd', {language : key});\n          return $q.reject(key);\n        });\n        langPromises[key]['finally'](function () {\n          clearNextLangAndPromise(key);\n        }).catch(angular.noop); // we don't care about errors (clearing)\n      } else if (langPromises[key]) {\n        // we are already loading this asynchronously\n        // resolve our new deferred when the old langPromise is resolved\n        langPromises[key].then(function (translation) {\n          if ($nextLang === translation.key) {\n            useLanguage(translation.key);\n          }\n          deferred.resolve(translation.key);\n          return translation;\n        }, function (key) {\n          // find first available fallback language if that request has failed\n          if (!$uses && $fallbackLanguage && $fallbackLanguage.length > 0 && $fallbackLanguage[0] !== key) {\n            return $translate.use($fallbackLanguage[0]).then(deferred.resolve, deferred.reject);\n          } else {\n            return deferred.reject(key);\n          }\n        });\n      } else {\n        deferred.resolve(key);\n        useLanguage(key);\n      }\n\n      return deferred.promise;\n    };\n\n    /**\n     * @ngdoc function\n     * @name pascalprecht.translate.$translate#resolveClientLocale\n     * @methodOf pascalprecht.translate.$translate\n     *\n     * @description\n     * This returns the current browser/client's language key. The result is processed with the configured uniform tag resolver.\n     *\n     * @returns {string} the current client/browser language key\n     */\n    $translate.resolveClientLocale = function () {\n      return getLocale();\n    };\n\n    /**\n     * @ngdoc function\n     * @name pascalprecht.translate.$translate#storageKey\n     * @methodOf pascalprecht.translate.$translate\n     *\n     * @description\n     * Returns the key for the storage.\n     *\n     * @return {string} storage key\n     */\n    $translate.storageKey = function () {\n      return storageKey();\n    };\n\n    /**\n     * @ngdoc function\n     * @name pascalprecht.translate.$translate#isPostCompilingEnabled\n     * @methodOf pascalprecht.translate.$translate\n     *\n     * @description\n     * Returns whether post compiling is enabled or not\n     *\n     * @return {bool} storage key\n     */\n    $translate.isPostCompilingEnabled = function () {\n      return $postCompilingEnabled;\n    };\n\n    /**\n     * @ngdoc function\n     * @name pascalprecht.translate.$translate#isForceAsyncReloadEnabled\n     * @methodOf pascalprecht.translate.$translate\n     *\n     * @description\n     * Returns whether force async reload is enabled or not\n     *\n     * @return {boolean} forceAsyncReload value\n     */\n    $translate.isForceAsyncReloadEnabled = function () {\n      return $forceAsyncReloadEnabled;\n    };\n\n    /**\n     * @ngdoc function\n     * @name pascalprecht.translate.$translate#isKeepContent\n     * @methodOf pascalprecht.translate.$translate\n     *\n     * @description\n     * Returns whether keepContent or not\n     *\n     * @return {boolean} keepContent value\n     */\n    $translate.isKeepContent = function () {\n      return $keepContent;\n    };\n\n    /**\n     * @ngdoc function\n     * @name pascalprecht.translate.$translate#refresh\n     * @methodOf pascalprecht.translate.$translate\n     *\n     * @description\n     * Refreshes a translation table pointed by the given langKey. If langKey is not specified,\n     * the module will drop all existent translation tables and load new version of those which\n     * are currently in use.\n     *\n     * Refresh means that the module will drop target translation table and try to load it again.\n     *\n     * In case there are no loaders registered the refresh() method will throw an Error.\n     *\n     * If the module is able to refresh translation tables refresh() method will broadcast\n     * $translateRefreshStart and $translateRefreshEnd events.\n     *\n     * @example\n     * // this will drop all currently existent translation tables and reload those which are\n     * // currently in use\n     * $translate.refresh();\n     * // this will refresh a translation table for the en_US language\n     * $translate.refresh('en_US');\n     *\n     * @param {string} langKey A language key of the table, which has to be refreshed\n     *\n     * @return {promise} Promise, which will be resolved in case a translation tables refreshing\n     * process is finished successfully, and reject if not.\n     */\n    $translate.refresh = function (langKey) {\n      if (!$loaderFactory) {\n        throw new Error('Couldn\\'t refresh translation table, no loader registered!');\n      }\n\n      $rootScope.$emit('$translateRefreshStart', {language : langKey});\n\n      var deferred = $q.defer(), updatedLanguages = {};\n\n      //private helper\n      function loadNewData(languageKey) {\n        var promise = loadAsync(languageKey);\n        //update the load promise cache for this language\n        langPromises[languageKey] = promise;\n        //register a data handler for the promise\n        promise.then(function (data) {\n            //clear the cache for this language\n            $translationTable[languageKey] = {};\n            //add the new data for this language\n            translations(languageKey, data.table);\n            //track that we updated this language\n            updatedLanguages[languageKey] = true;\n          },\n          //handle rejection to appease the $q validation\n          angular.noop);\n        return promise;\n      }\n\n      //set up post-processing\n      deferred.promise.then(\n        function () {\n          for (var key in $translationTable) {\n            if ($translationTable.hasOwnProperty(key)) {\n              //delete cache entries that were not updated\n              if (!(key in updatedLanguages)) {\n                delete $translationTable[key];\n              }\n            }\n          }\n          if ($uses) {\n            useLanguage($uses);\n          }\n        },\n        //handle rejection to appease the $q validation\n        angular.noop\n      ).finally(\n        function () {\n          $rootScope.$emit('$translateRefreshEnd', {language : langKey});\n        }\n      );\n\n      if (!langKey) {\n        // if there's no language key specified we refresh ALL THE THINGS!\n        var languagesToReload = $fallbackLanguage && $fallbackLanguage.slice() || [];\n        if ($uses && languagesToReload.indexOf($uses) === -1) {\n          languagesToReload.push($uses);\n        }\n        $q.all(languagesToReload.map(loadNewData)).then(deferred.resolve, deferred.reject);\n\n      } else if ($translationTable[langKey]) {\n        //just refresh the specified language cache\n        loadNewData(langKey).then(deferred.resolve, deferred.reject);\n\n      } else {\n        deferred.reject();\n      }\n\n      return deferred.promise;\n    };\n\n    /**\n     * @ngdoc function\n     * @name pascalprecht.translate.$translate#instant\n     * @methodOf pascalprecht.translate.$translate\n     *\n     * @description\n     * Returns a translation instantly from the internal state of loaded translation. All rules\n     * regarding the current language, the preferred language of even fallback languages will be\n     * used except any promise handling. If a language was not found, an asynchronous loading\n     * will be invoked in the background.\n     *\n     * @param {string|array} translationId A token which represents a translation id\n     *                                     This can be optionally an array of translation ids which\n     *                                     results that the function's promise returns an object where\n     *                                     each key is the translation id and the value the translation.\n     * @param {object} interpolateParams Params\n     * @param {string} interpolationId The id of the interpolation to use\n     * @param {string} forceLanguage A language to be used instead of the current language\n     * @param {string} sanitizeStrategy force sanitize strategy for this call instead of using the configured one\n     *\n     * @return {string|object} translation\n     */\n    $translate.instant = function (translationId, interpolateParams, interpolationId, forceLanguage, sanitizeStrategy) {\n\n      // we don't want to re-negotiate $uses\n      var uses = (forceLanguage && forceLanguage !== $uses) ? // we don't want to re-negotiate $uses\n        (negotiateLocale(forceLanguage) || forceLanguage) : $uses;\n\n      // Detect undefined and null values to shorten the execution and prevent exceptions\n      if (translationId === null || angular.isUndefined(translationId)) {\n        return translationId;\n      }\n\n      // Check forceLanguage is present\n      if (forceLanguage) {\n        loadTranslationsIfMissing(forceLanguage);\n      }\n\n      // Duck detection: If the first argument is an array, a bunch of translations was requested.\n      // The result is an object.\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, forceLanguage, sanitizeStrategy);\n        }\n        return results;\n      }\n\n      // We discarded unacceptable values. So we just need to verify if translationId is empty String\n      if (angular.isString(translationId) && translationId.length < 1) {\n        return translationId;\n      }\n\n      // trim off any whitespace\n      if (translationId) {\n        translationId = trim.apply(translationId);\n      }\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, uses, sanitizeStrategy);\n          }\n        }\n        if (typeof result !== 'undefined') {\n          break;\n        }\n      }\n\n      if (!result && result !== '') {\n        if ($notFoundIndicatorLeft || $notFoundIndicatorRight) {\n          result = applyNotFoundIndicators(translationId);\n        } else {\n          // Return translation of default interpolator if not found anything.\n          result = defaultInterpolator.interpolate(translationId, interpolateParams, 'filter', sanitizeStrategy);\n\n          // looks like the requested translation id doesn't exists.\n          // Now, if there is a registered handler for missing translations and no\n          // asyncLoader is pending, we execute the handler\n          var missingTranslationHandlerTranslation;\n          if ($missingTranslationHandlerFactory && !pendingLoader) {\n            missingTranslationHandlerTranslation = translateByHandler(translationId, interpolateParams, sanitizeStrategy);\n          }\n\n          if ($missingTranslationHandlerFactory && !pendingLoader && missingTranslationHandlerTranslation) {\n            result = missingTranslationHandlerTranslation;\n          }\n        }\n      }\n\n      return result;\n    };\n\n    /**\n     * @ngdoc function\n     * @name pascalprecht.translate.$translate#versionInfo\n     * @methodOf pascalprecht.translate.$translate\n     *\n     * @description\n     * Returns the current version information for the angular-translate library\n     *\n     * @return {string} angular-translate version\n     */\n    $translate.versionInfo = function () {\n      return version;\n    };\n\n    /**\n     * @ngdoc function\n     * @name pascalprecht.translate.$translate#loaderCache\n     * @methodOf pascalprecht.translate.$translate\n     *\n     * @description\n     * Returns the defined loaderCache.\n     *\n     * @return {boolean|string|object} current value of loaderCache\n     */\n    $translate.loaderCache = function () {\n      return loaderCache;\n    };\n\n    // internal purpose only\n    $translate.directivePriority = function () {\n      return directivePriority;\n    };\n\n    // internal purpose only\n    $translate.statefulFilter = function () {\n      return statefulFilter;\n    };\n\n    /**\n     * @ngdoc function\n     * @name pascalprecht.translate.$translate#isReady\n     * @methodOf pascalprecht.translate.$translate\n     *\n     * @description\n     * Returns whether the service is \"ready\" to translate (i.e. loading 1st language).\n     *\n     * See also {@link pascalprecht.translate.$translate#methods_onReady onReady()}.\n     *\n     * @return {boolean} current value of ready\n     */\n    $translate.isReady = function () {\n      return $isReady;\n    };\n\n    var $onReadyDeferred = $q.defer();\n    $onReadyDeferred.promise.then(function () {\n      $isReady = true;\n    });\n\n    /**\n     * @ngdoc function\n     * @name pascalprecht.translate.$translate#onReady\n     * @methodOf pascalprecht.translate.$translate\n     *\n     * @description\n     * Calls the function provided or resolved the returned promise after the service is \"ready\" to translate (i.e. loading 1st language).\n     *\n     * See also {@link pascalprecht.translate.$translate#methods_isReady isReady()}.\n     *\n     * @param {Function=} fn Function to invoke when service is ready\n     * @return {object} Promise resolved when service is ready\n     */\n    $translate.onReady = function (fn) {\n      var deferred = $q.defer();\n      if (angular.isFunction(fn)) {\n        deferred.promise.then(fn);\n      }\n      if ($isReady) {\n        deferred.resolve();\n      } else {\n        $onReadyDeferred.promise.then(deferred.resolve);\n      }\n      return deferred.promise;\n    };\n\n    /**\n     * @ngdoc function\n     * @name pascalprecht.translate.$translate#getAvailableLanguageKeys\n     * @methodOf pascalprecht.translate.$translate\n     *\n     * @description\n     * This function simply returns the registered language keys being defined before in the config phase\n     * With this, an application can use the array to provide a language selection dropdown or similar\n     * without any additional effort\n     *\n     * @returns {object} returns the list of possibly registered language keys and mapping or null if not defined\n     */\n    $translate.getAvailableLanguageKeys = function () {\n      if ($availableLanguageKeys.length > 0) {\n        return $availableLanguageKeys;\n      }\n      return null;\n    };\n\n    /**\n     * @ngdoc function\n     * @name pascalprecht.translate.$translate#getTranslationTable\n     * @methodOf pascalprecht.translate.$translate\n     *\n     * @description\n     * Returns translation table by the given language key.\n     *\n     * Unless a language is provided it returns a translation table of the current one.\n     * Note: If translation dictionary is currently downloading or in progress\n     * it will return null.\n     *\n     * @param {string} langKey A token which represents a translation id\n     *\n     * @return {object} a copy of angular-translate $translationTable\n     */\n    $translate.getTranslationTable = function (langKey) {\n      langKey = langKey || $translate.use();\n      if (langKey && $translationTable[langKey]) {\n        return angular.copy($translationTable[langKey]);\n      }\n      return null;\n    };\n\n    // Whenever $translateReady is being fired, this will ensure the state of $isReady\n    var globalOnReadyListener = $rootScope.$on('$translateReady', function () {\n      $onReadyDeferred.resolve();\n      globalOnReadyListener(); // one time only\n      globalOnReadyListener = null;\n    });\n    var globalOnChangeListener = $rootScope.$on('$translateChangeEnd', function () {\n      $onReadyDeferred.resolve();\n      globalOnChangeListener(); // one time only\n      globalOnChangeListener = null;\n    });\n\n    if ($loaderFactory) {\n\n      // If at least one async loader is defined and there are no\n      // (default) translations available we should try to load them.\n      if (angular.equals($translationTable, {})) {\n        if ($translate.use()) {\n          $translate.use($translate.use());\n        }\n      }\n\n      // Also, if there are any fallback language registered, we start\n      // loading them asynchronously as soon as we can.\n      if ($fallbackLanguage && $fallbackLanguage.length) {\n        var processAsyncResult = function (translation) {\n          translations(translation.key, translation.table);\n          $rootScope.$emit('$translateChangeEnd', {language : translation.key});\n          return translation;\n        };\n        for (var i = 0, len = $fallbackLanguage.length; i < len; i++) {\n          var fallbackLanguageId = $fallbackLanguage[i];\n          if ($forceAsyncReloadEnabled || !$translationTable[fallbackLanguageId]) {\n            langPromises[fallbackLanguageId] = loadAsync(fallbackLanguageId).then(processAsyncResult);\n          }\n        }\n      }\n    } else {\n      $rootScope.$emit('$translateReady', {language : $translate.use()});\n    }\n\n    return $translate;\n  }];\n}\n\n$translate.displayName = 'displayName';\n\n/**\n * @ngdoc object\n * @name pascalprecht.translate.$translateDefaultInterpolation\n * @requires $interpolate\n *\n * @description\n * Uses angular's `$interpolate` services to interpolate strings against some values.\n *\n * Be aware to configure a proper sanitization strategy.\n *\n * See also:\n * * {@link pascalprecht.translate.$translateSanitization}\n *\n * @return {object} $translateDefaultInterpolation Interpolator service\n */\nangular.module('pascalprecht.translate').factory('$translateDefaultInterpolation', $translateDefaultInterpolation);\n\nfunction $translateDefaultInterpolation ($interpolate, $translateSanitization) {\n\n  'use strict';\n\n  var $translateInterpolator = {},\n      $locale,\n      $identifier = 'default';\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateDefaultInterpolation#setLocale\n   * @methodOf pascalprecht.translate.$translateDefaultInterpolation\n   *\n   * @description\n   * Sets current locale (this is currently not use in this interpolation).\n   *\n   * @param {string} locale Language key or locale.\n   */\n  $translateInterpolator.setLocale = function (locale) {\n    $locale = locale;\n  };\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateDefaultInterpolation#getInterpolationIdentifier\n   * @methodOf pascalprecht.translate.$translateDefaultInterpolation\n   *\n   * @description\n   * Returns an identifier for this interpolation service.\n   *\n   * @returns {string} $identifier\n   */\n  $translateInterpolator.getInterpolationIdentifier = function () {\n    return $identifier;\n  };\n\n  /**\n   * @deprecated will be removed in 3.0\n   * @see {@link pascalprecht.translate.$translateSanitization}\n   */\n  $translateInterpolator.useSanitizeValueStrategy = function (value) {\n    $translateSanitization.useStrategy(value);\n    return this;\n  };\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateDefaultInterpolation#interpolate\n   * @methodOf pascalprecht.translate.$translateDefaultInterpolation\n   *\n   * @description\n   * Interpolates given value agains given interpolate params using angulars\n   * `$interpolate` service.\n   *\n   * Since AngularJS 1.5, `value` must not be a string but can be anything input.\n   *\n   * @param {string} value translation\n   * @param {object} interpolationParams interpolation params\n   * @param {string} context current context (filter, directive, service)\n   * @param {string} sanitizeStrategy sanitize strategy\n   * @param {string} translationId current translationId\n   *\n   * @returns {string} interpolated string\n   */\n  $translateInterpolator.interpolate = function (value, interpolationParams, context, sanitizeStrategy, translationId) { // jshint ignore:line\n    interpolationParams = interpolationParams || {};\n    interpolationParams = $translateSanitization.sanitize(interpolationParams, 'params', sanitizeStrategy, context);\n\n    var interpolatedText;\n    if (angular.isNumber(value)) {\n      // numbers are safe\n      interpolatedText = '' + value;\n    } else if (angular.isString(value)) {\n      // strings must be interpolated (that's the job here)\n      interpolatedText = $interpolate(value)(interpolationParams);\n      interpolatedText = $translateSanitization.sanitize(interpolatedText, 'text', sanitizeStrategy, context);\n    } else {\n      // neither a number or a string, cant interpolate => empty string\n      interpolatedText = '';\n    }\n\n    return interpolatedText;\n  };\n\n  return $translateInterpolator;\n}\n\n$translateDefaultInterpolation.displayName = '$translateDefaultInterpolation';\n\nangular.module('pascalprecht.translate').constant('$STORAGE_KEY', 'NG_TRANSLATE_LANG_KEY');\n\nangular.module('pascalprecht.translate')\n/**\n * @ngdoc directive\n * @name pascalprecht.translate.directive:translate\n * @requires $interpolate, \n * @requires $compile, \n * @requires $parse, \n * @requires $rootScope\n * @restrict AE\n *\n * @description\n * Translates given translation id either through attribute or DOM content.\n * Internally it uses $translate service to translate the translation id. It possible to\n * pass an optional `translate-values` object literal as string into translation id.\n *\n * @param {string=} translate Translation id which could be either string or interpolated string.\n * @param {string=} translate-values Values to pass into translation id. Can be passed as object literal string or interpolated object.\n * @param {string=} translate-attr-ATTR translate Translation id and put it into ATTR attribute.\n * @param {string=} translate-default will be used unless translation was successful\n * @param {boolean=} translate-compile (default true if present) defines locally activation of {@link pascalprecht.translate.$translateProvider#methods_usePostCompiling}\n * @param {boolean=} translate-keep-content (default true if present) defines that in case a KEY could not be translated, that the existing content is left in the innerHTML}\n *\n * @example\n   <example module=\"ngView\">\n    <file name=\"index.html\">\n      <div ng-controller=\"TranslateCtrl\">\n\n        <pre translate=\"TRANSLATION_ID\"></pre>\n        <pre translate>TRANSLATION_ID</pre>\n        <pre translate translate-attr-title=\"TRANSLATION_ID\"></pre>\n        <pre translate=\"{{translationId}}\"></pre>\n        <pre translate>{{translationId}}</pre>\n        <pre translate=\"WITH_VALUES\" translate-values=\"{value: 5}\"></pre>\n        <pre translate translate-values=\"{value: 5}\">WITH_VALUES</pre>\n        <pre translate=\"WITH_VALUES\" translate-values=\"{{values}}\"></pre>\n        <pre translate translate-values=\"{{values}}\">WITH_VALUES</pre>\n        <pre translate translate-attr-title=\"WITH_VALUES\" translate-values=\"{{values}}\"></pre>\n        <pre translate=\"WITH_CAMEL_CASE_KEY\" translate-value-camel-case-key=\"Hi\"></pre>\n\n      </div>\n    </file>\n    <file name=\"script.js\">\n      angular.module('ngView', ['pascalprecht.translate'])\n\n      .config(function ($translateProvider) {\n\n        $translateProvider.translations('en',{\n          'TRANSLATION_ID': 'Hello there!',\n          'WITH_VALUES': 'The following value is dynamic: {{value}}',\n          'WITH_CAMEL_CASE_KEY': 'The interpolation key is camel cased: {{camelCaseKey}}'\n        }).preferredLanguage('en');\n\n      });\n\n      angular.module('ngView').controller('TranslateCtrl', function ($scope) {\n        $scope.translationId = 'TRANSLATION_ID';\n\n        $scope.values = {\n          value: 78\n        };\n      });\n    </file>\n    <file name=\"scenario.js\">\n      it('should translate', function () {\n        inject(function ($rootScope, $compile) {\n          $rootScope.translationId = 'TRANSLATION_ID';\n\n          element = $compile('<p translate=\"TRANSLATION_ID\"></p>')($rootScope);\n          $rootScope.$digest();\n          expect(element.text()).toBe('Hello there!');\n\n          element = $compile('<p translate=\"{{translationId}}\"></p>')($rootScope);\n          $rootScope.$digest();\n          expect(element.text()).toBe('Hello there!');\n\n          element = $compile('<p translate>TRANSLATION_ID</p>')($rootScope);\n          $rootScope.$digest();\n          expect(element.text()).toBe('Hello there!');\n\n          element = $compile('<p translate>{{translationId}}</p>')($rootScope);\n          $rootScope.$digest();\n          expect(element.text()).toBe('Hello there!');\n\n          element = $compile('<p translate translate-attr-title=\"TRANSLATION_ID\"></p>')($rootScope);\n          $rootScope.$digest();\n          expect(element.attr('title')).toBe('Hello there!');\n\n          element = $compile('<p translate=\"WITH_CAMEL_CASE_KEY\" translate-value-camel-case-key=\"Hello\"></p>')($rootScope);\n          $rootScope.$digest();\n          expect(element.text()).toBe('The interpolation key is camel cased: Hello');\n        });\n      });\n    </file>\n   </example>\n */\n.directive('translate', translateDirective);\nfunction translateDirective($translate, $interpolate, $compile, $parse, $rootScope) {\n\n  'use strict';\n\n  /**\n   * @name trim\n   * @private\n   *\n   * @description\n   * trim polyfill\n   *\n   * @returns {string} The string stripped of whitespace from both ends\n   */\n  var trim = function() {\n    return this.toString().replace(/^\\s+|\\s+$/g, '');\n  };\n\n  return {\n    restrict: 'AE',\n    scope: true,\n    priority: $translate.directivePriority(),\n    compile: function (tElement, tAttr) {\n\n      var translateValuesExist = (tAttr.translateValues) ?\n        tAttr.translateValues : undefined;\n\n      var translateInterpolation = (tAttr.translateInterpolation) ?\n        tAttr.translateInterpolation : undefined;\n\n      var translateValueExist = tElement[0].outerHTML.match(/translate-value-+/i);\n\n      var interpolateRegExp = '^(.*)(' + $interpolate.startSymbol() + '.*' + $interpolate.endSymbol() + ')(.*)',\n          watcherRegExp = '^(.*)' + $interpolate.startSymbol() + '(.*)' + $interpolate.endSymbol() + '(.*)';\n\n      return function linkFn(scope, iElement, iAttr) {\n\n        scope.interpolateParams = {};\n        scope.preText = '';\n        scope.postText = '';\n        scope.translateNamespace = getTranslateNamespace(scope);\n        var translationIds = {};\n\n        var initInterpolationParams = function (interpolateParams, iAttr, tAttr) {\n          // initial setup\n          if (iAttr.translateValues) {\n            angular.extend(interpolateParams, $parse(iAttr.translateValues)(scope.$parent));\n          }\n          // initially fetch all attributes if existing and fill the params\n          if (translateValueExist) {\n            for (var attr in tAttr) {\n              if (Object.prototype.hasOwnProperty.call(iAttr, attr) && attr.substr(0, 14) === 'translateValue' && attr !== 'translateValues') {\n                var attributeName = angular.lowercase(attr.substr(14, 1)) + attr.substr(15);\n                interpolateParams[attributeName] = tAttr[attr];\n              }\n            }\n          }\n        };\n\n        // Ensures any change of the attribute \"translate\" containing the id will\n        // be re-stored to the scope's \"translationId\".\n        // If the attribute has no content, the element's text value (white spaces trimmed off) will be used.\n        var observeElementTranslation = function (translationId) {\n\n          // Remove any old watcher\n          if (angular.isFunction(observeElementTranslation._unwatchOld)) {\n            observeElementTranslation._unwatchOld();\n            observeElementTranslation._unwatchOld = undefined;\n          }\n\n          if (angular.equals(translationId , '') || !angular.isDefined(translationId)) {\n            var iElementText = trim.apply(iElement.text());\n\n            // Resolve translation id by inner html if required\n            var interpolateMatches = iElementText.match(interpolateRegExp);\n            // Interpolate translation id if required\n            if (angular.isArray(interpolateMatches)) {\n              scope.preText = interpolateMatches[1];\n              scope.postText = interpolateMatches[3];\n              translationIds.translate = $interpolate(interpolateMatches[2])(scope.$parent);\n              var watcherMatches = iElementText.match(watcherRegExp);\n              if (angular.isArray(watcherMatches) && watcherMatches[2] && watcherMatches[2].length) {\n                observeElementTranslation._unwatchOld = scope.$watch(watcherMatches[2], function (newValue) {\n                  translationIds.translate = newValue;\n                  updateTranslations();\n                });\n              }\n            } else {\n              // do not assigne the translation id if it is empty.\n              translationIds.translate = !iElementText ? undefined : iElementText;\n            }\n          } else {\n            translationIds.translate = translationId;\n          }\n          updateTranslations();\n        };\n\n        var observeAttributeTranslation = function (translateAttr) {\n          iAttr.$observe(translateAttr, function (translationId) {\n            translationIds[translateAttr] = translationId;\n            updateTranslations();\n          });\n        };\n\n        // initial setup with values\n        initInterpolationParams(scope.interpolateParams, iAttr, tAttr);\n\n        var firstAttributeChangedEvent = true;\n        iAttr.$observe('translate', function (translationId) {\n          if (typeof translationId === 'undefined') {\n            // case of element \"<translate>xyz</translate>\"\n            observeElementTranslation('');\n          } else {\n            // case of regular attribute\n            if (translationId !== '' || !firstAttributeChangedEvent) {\n              translationIds.translate = translationId;\n              updateTranslations();\n            }\n          }\n          firstAttributeChangedEvent = false;\n        });\n\n        for (var translateAttr in iAttr) {\n          if (iAttr.hasOwnProperty(translateAttr) && translateAttr.substr(0, 13) === 'translateAttr' && translateAttr.length > 13) {\n            observeAttributeTranslation(translateAttr);\n          }\n        }\n\n        iAttr.$observe('translateDefault', function (value) {\n          scope.defaultText = value;\n          updateTranslations();\n        });\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\n        if (translateValueExist) {\n          var observeValueAttribute = function (attrName) {\n            iAttr.$observe(attrName, function (value) {\n              var attributeName = angular.lowercase(attrName.substr(14, 1)) + attrName.substr(15);\n              scope.interpolateParams[attributeName] = 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              observeValueAttribute(attr);\n            }\n          }\n        }\n\n        // Master update function\n        var updateTranslations = function () {\n          for (var key in translationIds) {\n            if (translationIds.hasOwnProperty(key) && translationIds[key] !== undefined) {\n              updateTranslation(key, translationIds[key], scope, scope.interpolateParams, scope.defaultText, scope.translateNamespace);\n            }\n          }\n        };\n\n        // Put translation processing function outside loop\n        var updateTranslation = function(translateAttr, translationId, scope, interpolateParams, defaultTranslationText, translateNamespace) {\n          if (translationId) {\n            // if translation id starts with '.' and translateNamespace given, prepend namespace\n            if (translateNamespace && translationId.charAt(0) === '.') {\n              translationId = translateNamespace + translationId;\n            }\n\n            $translate(translationId, interpolateParams, translateInterpolation, defaultTranslationText, scope.translateLanguage)\n              .then(function (translation) {\n                applyTranslation(translation, scope, true, translateAttr);\n              }, function (translationId) {\n                applyTranslation(translationId, scope, false, translateAttr);\n              });\n          } else {\n            // as an empty string cannot be translated, we can solve this using successful=false\n            applyTranslation(translationId, scope, false, translateAttr);\n          }\n        };\n\n        var applyTranslation = function (value, scope, successful, translateAttr) {\n          if (!successful) {\n            if (typeof scope.defaultText !== 'undefined') {\n              value = scope.defaultText;\n            }\n          }\n          if (translateAttr === 'translate') {\n            // default translate into innerHTML\n            if (successful || (!successful && !$translate.isKeepContent() && typeof iAttr.translateKeepContent === 'undefined')) {\n              iElement.empty().append(scope.preText + value + scope.postText);\n            }\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          } else {\n            // translate attribute\n            var attributeName = iAttr.$attr[translateAttr];\n            if (attributeName.substr(0, 5) === 'data-') {\n              // ensure html5 data prefix is stripped\n              attributeName = attributeName.substr(5);\n            }\n            attributeName = attributeName.substr(15);\n            iElement.attr(attributeName, value);\n          }\n        };\n\n        if (translateValuesExist || translateValueExist || iAttr.translateDefault) {\n          scope.$watch('interpolateParams', updateTranslations, true);\n        }\n\n        // Replaced watcher on translateLanguage with event listener\n        scope.$on('translateLanguageChanged', updateTranslations);\n\n        // Ensures the text will be refreshed after the current language was changed\n        // w/ $translate.use(...)\n        var unbind = $rootScope.$on('$translateChangeSuccess', updateTranslations);\n\n        // ensure translation will be looked up at least one\n        if (iElement.text().length) {\n          if (iAttr.translate) {\n            observeElementTranslation(iAttr.translate);\n          } else {\n            observeElementTranslation('');\n          }\n        } else if (iAttr.translate) {\n          // ensure attribute will be not skipped\n          observeElementTranslation(iAttr.translate);\n        }\n        updateTranslations();\n        scope.$on('$destroy', unbind);\n      };\n    }\n  };\n}\n\n/**\n * Returns the scope's namespace.\n * @private\n * @param scope\n * @returns {string}\n */\nfunction getTranslateNamespace(scope) {\n  'use strict';\n  if (scope.translateNamespace) {\n    return scope.translateNamespace;\n  }\n  if (scope.$parent) {\n    return getTranslateNamespace(scope.$parent);\n  }\n}\n\ntranslateDirective.displayName = 'translateDirective';\n\nangular.module('pascalprecht.translate')\n/**\n * @ngdoc directive\n * @name pascalprecht.translate.directive:translate-attr\n * @restrict A\n *\n * @description\n * Translates attributes like translate-attr-ATTR, but with an object like ng-class.\n * Internally it uses `translate` service to translate translation id. It possible to\n * pass an optional `translate-values` object literal as string into translation id.\n *\n * @param {string=} translate-attr Object literal mapping attributes to translation ids.\n * @param {string=} translate-values Values to pass into the translation ids. Can be passed as object literal string.\n *\n * @example\n   <example module=\"ngView\">\n    <file name=\"index.html\">\n      <div ng-controller=\"TranslateCtrl\">\n\n        <input translate-attr=\"{ placeholder: translationId, title: 'WITH_VALUES' }\" translate-values=\"{value: 5}\" />\n\n      </div>\n    </file>\n    <file name=\"script.js\">\n      angular.module('ngView', ['pascalprecht.translate'])\n\n      .config(function ($translateProvider) {\n\n        $translateProvider.translations('en',{\n          'TRANSLATION_ID': 'Hello there!',\n          'WITH_VALUES': 'The following value is dynamic: {{value}}',\n        }).preferredLanguage('en');\n\n      });\n\n      angular.module('ngView').controller('TranslateCtrl', function ($scope) {\n        $scope.translationId = 'TRANSLATION_ID';\n\n        $scope.values = {\n          value: 78\n        };\n      });\n    </file>\n    <file name=\"scenario.js\">\n      it('should translate', function () {\n        inject(function ($rootScope, $compile) {\n          $rootScope.translationId = 'TRANSLATION_ID';\n\n          element = $compile('<input translate-attr=\"{ placeholder: translationId, title: 'WITH_VALUES' }\" translate-values=\"{ value: 5 }\" />')($rootScope);\n          $rootScope.$digest();\n          expect(element.attr('placeholder)).toBe('Hello there!');\n          expect(element.attr('title)).toBe('The following value is dynamic: 5');\n        });\n      });\n    </file>\n   </example>\n */\n.directive('translateAttr', translateAttrDirective);\nfunction translateAttrDirective($translate, $rootScope) {\n\n  'use strict';\n\n  return {\n    restrict: 'A',\n    priority: $translate.directivePriority(),\n    link: function linkFn(scope, element, attr) {\n\n      var translateAttr,\n          translateValues,\n          previousAttributes = {};\n\n      // Main update translations function\n      var updateTranslations = function () {\n        angular.forEach(translateAttr, function (translationId, attributeName) {\n          if (!translationId) {\n            return;\n          }\n          previousAttributes[attributeName] = true;\n\n          // if translation id starts with '.' and translateNamespace given, prepend namespace\n          if (scope.translateNamespace && translationId.charAt(0) === '.') {\n            translationId = scope.translateNamespace + translationId;\n          }\n          $translate(translationId, translateValues, attr.translateInterpolation, undefined, scope.translateLanguage)\n            .then(function (translation) {\n              element.attr(attributeName, translation);\n            }, function (translationId) {\n              element.attr(attributeName, translationId);\n            });\n        });\n\n        // Removing unused attributes that were previously used\n        angular.forEach(previousAttributes, function (flag, attributeName) {\n          if (!translateAttr[attributeName]) {\n            element.removeAttr(attributeName);\n            delete previousAttributes[attributeName];\n          }\n        });\n      };\n\n      // Watch for attribute changes\n      watchAttribute(\n        scope,\n        attr.translateAttr,\n        function (newValue) { translateAttr = newValue; },\n        updateTranslations\n      );\n      // Watch for value changes\n      watchAttribute(\n        scope,\n        attr.translateValues,\n        function (newValue) { translateValues = newValue; },\n        updateTranslations\n      );\n\n      if (attr.translateValues) {\n        scope.$watch(attr.translateValues, updateTranslations, true);\n      }\n\n      // Replaced watcher on translateLanguage with event listener\n      scope.$on('translateLanguageChanged', updateTranslations);\n\n      // Ensures the text will be refreshed after the current language was changed\n      // w/ $translate.use(...)\n      var unbind = $rootScope.$on('$translateChangeSuccess', updateTranslations);\n\n      updateTranslations();\n      scope.$on('$destroy', unbind);\n    }\n  };\n}\n\nfunction watchAttribute(scope, attribute, valueCallback, changeCallback) {\n  'use strict';\n  if (!attribute) {\n    return;\n  }\n  if (attribute.substr(0, 2) === '::') {\n    attribute = attribute.substr(2);\n  } else {\n    scope.$watch(attribute, function(newValue) {\n      valueCallback(newValue);\n      changeCallback();\n    }, true);\n  }\n  valueCallback(scope.$eval(attribute));\n}\n\ntranslateAttrDirective.displayName = 'translateAttrDirective';\n\nangular.module('pascalprecht.translate')\n/**\n * @ngdoc directive\n * @name pascalprecht.translate.directive:translateCloak\n * @requires $translate\n * @restrict A\n *\n * $description\n * Adds a `translate-cloak` class name to the given element where this directive\n * is applied initially and removes it, once a loader has finished loading.\n *\n * This directive can be used to prevent initial flickering when loading translation\n * data asynchronously.\n *\n * The class name is defined in\n * {@link pascalprecht.translate.$translateProvider#cloakClassName $translate.cloakClassName()}.\n *\n * @param {string=} translate-cloak If a translationId is provided, it will be used for showing\n *                                  or hiding the cloak. Basically it relies on the translation\n *                                  resolve.\n */\n.directive('translateCloak', translateCloakDirective);\n\nfunction translateCloakDirective($translate, $rootScope) {\n\n  'use strict';\n\n  return {\n    compile : function (tElement) {\n      var applyCloak = function (element) {\n          element.addClass($translate.cloakClassName());\n        },\n        removeCloak = function (element) {\n          element.removeClass($translate.cloakClassName());\n        };\n      applyCloak(tElement);\n\n      return function linkFn(scope, iElement, iAttr) {\n        //Create bound functions that incorporate the active DOM element.\n        var iRemoveCloak = removeCloak.bind(this, iElement), iApplyCloak = applyCloak.bind(this, iElement);\n        if (iAttr.translateCloak && iAttr.translateCloak.length) {\n          // Register a watcher for the defined translation allowing a fine tuned cloak\n          iAttr.$observe('translateCloak', function (translationId) {\n            $translate(translationId).then(iRemoveCloak, iApplyCloak);\n          });\n          $rootScope.$on('$translateChangeSuccess', function () {\n            $translate(iAttr.translateCloak).then(iRemoveCloak, iApplyCloak);\n          });\n        } else {\n          $translate.onReady(iRemoveCloak);\n        }\n      };\n    }\n  };\n}\n\ntranslateCloakDirective.displayName = 'translateCloakDirective';\n\nangular.module('pascalprecht.translate')\n/**\n * @ngdoc directive\n * @name pascalprecht.translate.directive:translateNamespace\n * @restrict A\n *\n * @description\n * Translates given translation id either through attribute or DOM content.\n * Internally it uses `translate` filter to translate translation id. It possible to\n * pass an optional `translate-values` object literal as string into translation id.\n *\n * @param {string=} translate namespace name which could be either string or interpolated string.\n *\n * @example\n   <example module=\"ngView\">\n    <file name=\"index.html\">\n      <div translate-namespace=\"CONTENT\">\n\n        <div>\n            <h1 translate>.HEADERS.TITLE</h1>\n            <h1 translate>.HEADERS.WELCOME</h1>\n        </div>\n\n        <div translate-namespace=\".HEADERS\">\n            <h1 translate>.TITLE</h1>\n            <h1 translate>.WELCOME</h1>\n        </div>\n\n      </div>\n    </file>\n    <file name=\"script.js\">\n      angular.module('ngView', ['pascalprecht.translate'])\n\n      .config(function ($translateProvider) {\n\n        $translateProvider.translations('en',{\n          'TRANSLATION_ID': 'Hello there!',\n          'CONTENT': {\n            'HEADERS': {\n                TITLE: 'Title'\n            }\n          },\n          'CONTENT.HEADERS.WELCOME': 'Welcome'\n        }).preferredLanguage('en');\n\n      });\n\n    </file>\n   </example>\n */\n.directive('translateNamespace', translateNamespaceDirective);\n\nfunction translateNamespaceDirective() {\n\n  'use strict';\n\n  return {\n    restrict: 'A',\n    scope: true,\n    compile: function () {\n      return {\n        pre: function (scope, iElement, iAttrs) {\n          scope.translateNamespace = getTranslateNamespace(scope);\n\n          if (scope.translateNamespace && iAttrs.translateNamespace.charAt(0) === '.') {\n            scope.translateNamespace += iAttrs.translateNamespace;\n          } else {\n            scope.translateNamespace = iAttrs.translateNamespace;\n          }\n        }\n      };\n    }\n  };\n}\n\n/**\n * Returns the scope's namespace.\n * @private\n * @param scope\n * @returns {string}\n */\nfunction getTranslateNamespace(scope) {\n  'use strict';\n  if (scope.translateNamespace) {\n    return scope.translateNamespace;\n  }\n  if (scope.$parent) {\n    return getTranslateNamespace(scope.$parent);\n  }\n}\n\ntranslateNamespaceDirective.displayName = 'translateNamespaceDirective';\n\nangular.module('pascalprecht.translate')\n/**\n * @ngdoc directive\n * @name pascalprecht.translate.directive:translateLanguage\n * @restrict A\n *\n * @description\n * Forces the language to the directives in the underlying scope.\n *\n * @param {string=} translate language that will be negotiated.\n *\n * @example\n   <example module=\"ngView\">\n    <file name=\"index.html\">\n      <div>\n\n        <div>\n            <h1 translate>HELLO</h1>\n        </div>\n\n        <div translate-language=\"de\">\n            <h1 translate>HELLO</h1>\n        </div>\n\n      </div>\n    </file>\n    <file name=\"script.js\">\n      angular.module('ngView', ['pascalprecht.translate'])\n\n      .config(function ($translateProvider) {\n\n        $translateProvider\n          .translations('en',{\n            'HELLO': 'Hello world!'\n          })\n          .translations('de',{\n            'HELLO': 'Hallo Welt!'\n          })\n          .preferredLanguage('en');\n\n      });\n\n    </file>\n   </example>\n */\n.directive('translateLanguage', translateLanguageDirective);\n\nfunction translateLanguageDirective() {\n\n  'use strict';\n\n  return {\n    restrict: 'A',\n    scope: true,\n    compile: function () {\n      return function linkFn(scope, iElement, iAttrs) {\n\n        iAttrs.$observe('translateLanguage', function (newTranslateLanguage) {\n          scope.translateLanguage = newTranslateLanguage;\n        });\n\n        scope.$watch('translateLanguage', function(){\n          scope.$broadcast('translateLanguageChanged');\n        });\n      };\n    }\n  };\n}\n\ntranslateLanguageDirective.displayName = 'translateLanguageDirective';\n\nangular.module('pascalprecht.translate')\n/**\n * @ngdoc filter\n * @name pascalprecht.translate.filter:translate\n * @requires $parse\n * @requires pascalprecht.translate.$translate\n * @function\n *\n * @description\n * Uses `$translate` service to translate contents. Accepts interpolate parameters\n * to pass dynamized values though translation.\n *\n * @param {string} translationId A translation id to be translated.\n * @param {*=} interpolateParams Optional object literal (as hash or string) to pass values into translation.\n *\n * @returns {string} Translated text.\n *\n * @example\n   <example module=\"ngView\">\n    <file name=\"index.html\">\n      <div ng-controller=\"TranslateCtrl\">\n\n        <pre>{{ 'TRANSLATION_ID' | translate }}</pre>\n        <pre>{{ translationId | translate }}</pre>\n        <pre>{{ 'WITH_VALUES' | translate:'{value: 5}' }}</pre>\n        <pre>{{ 'WITH_VALUES' | translate:values }}</pre>\n\n      </div>\n    </file>\n    <file name=\"script.js\">\n      angular.module('ngView', ['pascalprecht.translate'])\n\n      .config(function ($translateProvider) {\n\n        $translateProvider.translations('en', {\n          'TRANSLATION_ID': 'Hello there!',\n          'WITH_VALUES': 'The following value is dynamic: {{value}}'\n        });\n        $translateProvider.preferredLanguage('en');\n\n      });\n\n      angular.module('ngView').controller('TranslateCtrl', function ($scope) {\n        $scope.translationId = 'TRANSLATION_ID';\n\n        $scope.values = {\n          value: 78\n        };\n      });\n    </file>\n   </example>\n */\n.filter('translate', translateFilterFactory);\n\nfunction translateFilterFactory($parse, $translate) {\n\n  'use strict';\n\n  var translateFilter = function (translationId, interpolateParams, interpolation, forceLanguage) {\n    if (!angular.isObject(interpolateParams)) {\n      var ctx = this || {\n        '__SCOPE_IS_NOT_AVAILABLE': 'More info at https://github.com/angular/angular.js/commit/8863b9d04c722b278fa93c5d66ad1e578ad6eb1f'\n        };\n      interpolateParams = $parse(interpolateParams)(ctx);\n    }\n\n    return $translate.instant(translationId, interpolateParams, interpolation, forceLanguage);\n  };\n\n  if ($translate.statefulFilter()) {\n    translateFilter.$stateful = true;\n  }\n\n  return translateFilter;\n}\n\ntranslateFilterFactory.displayName = 'translateFilterFactory';\n\nangular.module('pascalprecht.translate')\n\n/**\n * @ngdoc object\n * @name pascalprecht.translate.$translationCache\n * @requires $cacheFactory\n *\n * @description\n * The first time a translation table is used, it is loaded in the translation cache for quick retrieval. You\n * can load translation tables directly into the cache by consuming the\n * `$translationCache` service directly.\n *\n * @return {object} $cacheFactory object.\n */\n  .factory('$translationCache', $translationCache);\n\nfunction $translationCache($cacheFactory) {\n\n  'use strict';\n\n  return $cacheFactory('translations');\n}\n\n$translationCache.displayName = '$translationCache';\nreturn 'pascalprecht.translate';\n\n}));\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/angular-translate-loader-static-files/.bower.json",
    "content": "{\n  \"name\": \"angular-translate-loader-static-files\",\n  \"version\": \"2.4.2\",\n  \"main\": \"./angular-translate-loader-static-files.js\",\n  \"dependencies\": {\n    \"angular-translate\": \"~2.4.2\"\n  },\n  \"ignore\": [],\n  \"homepage\": \"https://github.com/PascalPrecht/bower-angular-translate-loader-static-files\",\n  \"_release\": \"2.4.2\",\n  \"_resolution\": {\n    \"type\": \"version\",\n    \"tag\": \"2.4.2\",\n    \"commit\": \"7fc66387a321d42a8d30bb8dd3630729d01382e7\"\n  },\n  \"_source\": \"https://github.com/PascalPrecht/bower-angular-translate-loader-static-files.git\",\n  \"_target\": \"2.4.2\",\n  \"_originalSource\": \"angular-translate-loader-static-files\"\n}"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/angular-translate-loader-static-files/angular-translate-loader-static-files.js",
    "content": "/*!\n * angular-translate - v2.15.1 - 2017-03-04\n * \n * Copyright (c) 2017 The angular-translate team, Pascal Precht; Licensed MIT\n */\n(function (root, factory) {\n  if (typeof define === 'function' && define.amd) {\n    // AMD. Register as an anonymous module unless amdModuleId is set\n    define([], function () {\n      return (factory());\n    });\n  } else if (typeof exports === 'object') {\n    // Node. Does not work with strict CommonJS, but\n    // only CommonJS-like environments that support module.exports,\n    // like Node.\n    module.exports = factory();\n  } else {\n    factory();\n  }\n}(this, function () {\n\n$translateStaticFilesLoader.$inject = ['$q', '$http'];\nangular.module('pascalprecht.translate')\n/**\n * @ngdoc object\n * @name pascalprecht.translate.$translateStaticFilesLoader\n * @requires $q\n * @requires $http\n *\n * @description\n * Creates a loading function for a typical static file url pattern:\n * \"lang-en_US.json\", \"lang-de_DE.json\", etc. Using this builder,\n * the response of these urls must be an object of key-value pairs.\n *\n * @param {object} options Options object, which gets prefix, suffix, key, and fileMap\n */\n.factory('$translateStaticFilesLoader', $translateStaticFilesLoader);\n\nfunction $translateStaticFilesLoader($q, $http) {\n\n  'use strict';\n\n  return function (options) {\n\n    if (!options || (!angular.isArray(options.files) && (!angular.isString(options.prefix) || !angular.isString(options.suffix)))) {\n      throw new Error('Couldn\\'t load static files, no files and prefix or suffix specified!');\n    }\n\n    if (!options.files) {\n      options.files = [{\n        prefix: options.prefix,\n        suffix: options.suffix\n      }];\n    }\n\n    var load = function (file) {\n      if (!file || (!angular.isString(file.prefix) || !angular.isString(file.suffix))) {\n        throw new Error('Couldn\\'t load static file, no prefix or suffix specified!');\n      }\n\n      var fileUrl = [\n        file.prefix,\n        options.key,\n        file.suffix\n      ].join('');\n\n      if (angular.isObject(options.fileMap) && options.fileMap[fileUrl]) {\n        fileUrl = options.fileMap[fileUrl];\n      }\n\n      return $http(angular.extend({\n        url: fileUrl,\n        method: 'GET'\n      }, options.$http))\n        .then(function(result) {\n          return result.data;\n        }, function () {\n          return $q.reject(options.key);\n        });\n    };\n\n    var promises = [],\n        length = options.files.length;\n\n    for (var i = 0; i < length; i++) {\n      promises.push(load({\n        prefix: options.files[i].prefix,\n        key: options.key,\n        suffix: options.files[i].suffix\n      }));\n    }\n\n    return $q.all(promises)\n      .then(function (data) {\n        var length = data.length,\n            mergedData = {};\n\n        for (var i = 0; i < length; i++) {\n          for (var key in data[i]) {\n            mergedData[key] = data[i][key];\n          }\n        }\n\n        return mergedData;\n      });\n  };\n}\n\n$translateStaticFilesLoader.displayName = '$translateStaticFilesLoader';\nreturn 'pascalprecht.translate';\n\n}));\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/angular-translate-storage-cookie/.bower.json",
    "content": "{\n  \"name\": \"angular-translate-storage-cookie\",\n  \"version\": \"2.4.2\",\n  \"main\": \"./angular-translate-storage-cookie.js\",\n  \"dependencies\": {\n    \"angular-translate\": \"~2.4.2\"\n  },\n  \"ignore\": [],\n  \"homepage\": \"https://github.com/PascalPrecht/bower-angular-translate-storage-cookie\",\n  \"_release\": \"2.4.2\",\n  \"_resolution\": {\n    \"type\": \"version\",\n    \"tag\": \"2.4.2\",\n    \"commit\": \"5b17921d9d6f820bf055d88afb8bb0f336d65ef9\"\n  },\n  \"_source\": \"https://github.com/PascalPrecht/bower-angular-translate-storage-cookie.git\",\n  \"_target\": \"2.4.2\",\n  \"_originalSource\": \"angular-translate-storage-cookie\"\n}"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/angular-translate-storage-cookie/angular-translate-storage-cookie.js",
    "content": "/*!\n * angular-translate - v2.15.1 - 2017-03-04\n * \n * Copyright (c) 2017 The angular-translate team, Pascal Precht; Licensed MIT\n */\n(function (root, factory) {\n  if (typeof define === 'function' && define.amd) {\n    // AMD. Register as an anonymous module unless amdModuleId is set\n    define([], function () {\n      return (factory());\n    });\n  } else if (typeof exports === 'object') {\n    // Node. Does not work with strict CommonJS, but\n    // only CommonJS-like environments that support module.exports,\n    // like Node.\n    module.exports = factory();\n  } else {\n    factory();\n  }\n}(this, function () {\n\n$translateCookieStorageFactory.$inject = ['$injector'];\nangular.module('pascalprecht.translate')\n\n/**\n * @ngdoc object\n * @name pascalprecht.translate.$translateCookieStorage\n * @requires $cookieStore\n *\n * @description\n * Abstraction layer for cookieStore. This service is used when telling angular-translate\n * to use cookieStore as storage.\n *\n */\n  .factory('$translateCookieStorage', $translateCookieStorageFactory);\n\nfunction $translateCookieStorageFactory($injector) {\n\n  'use strict';\n\n  // Since AngularJS 1.4, $cookieStore is deprecated\n  var delegate;\n  if (angular.version.major === 1 && angular.version.minor >= 4) {\n    var $cookies = $injector.get('$cookies');\n    delegate = {\n      get : function (key) {\n        return $cookies.get(key);\n      },\n      put : function (key, value) {\n        $cookies.put(key, value);\n      }\n    };\n  } else {\n    var $cookieStore = $injector.get('$cookieStore');\n    delegate = {\n      get : function (key) {\n        return $cookieStore.get(key);\n      },\n      put : function (key, value) {\n        $cookieStore.put(key, value);\n      }\n    };\n  }\n\n  var $translateCookieStorage = {\n\n    /**\n     * @ngdoc function\n     * @name pascalprecht.translate.$translateCookieStorage#get\n     * @methodOf pascalprecht.translate.$translateCookieStorage\n     *\n     * @description\n     * Returns an item from cookieStorage by given name.\n     *\n     * @param {string} name Item name\n     * @return {string} Value of item name\n     */\n    get : function (name) {\n      return delegate.get(name);\n    },\n\n    /**\n     * @ngdoc function\n     * @name pascalprecht.translate.$translateCookieStorage#set\n     * @methodOf pascalprecht.translate.$translateCookieStorage\n     *\n     * @description\n     * Sets an item in cookieStorage by given name.\n     *\n     * @deprecated use #put\n     *\n     * @param {string} name Item name\n     * @param {string} value Item value\n     */\n    set : function (name, value) {\n      delegate.put(name, value);\n    },\n\n    /**\n     * @ngdoc function\n     * @name pascalprecht.translate.$translateCookieStorage#put\n     * @methodOf pascalprecht.translate.$translateCookieStorage\n     *\n     * @description\n     * Sets an item in cookieStorage by given name.\n     *\n     * @param {string} name Item name\n     * @param {string} value Item value\n     */\n    put : function (name, value) {\n      delegate.put(name, value);\n    }\n  };\n\n  return $translateCookieStorage;\n}\n\n$translateCookieStorageFactory.displayName = '$translateCookieStorage';\nreturn 'pascalprecht.translate';\n\n}));\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/angular-ui-utils/.bower.json",
    "content": "{\n  \"name\": \"angular-ui-utils\",\n  \"version\": \"0.2.1\",\n  \"main\": \"./ui-utils.js\",\n  \"dependencies\": {\n    \"angular\": \">= 1.0.2\"\n  },\n  \"homepage\": \"https://github.com/angular-ui/ui-utils\",\n  \"_release\": \"0.2.1\",\n  \"_resolution\": {\n    \"type\": \"version\",\n    \"tag\": \"v0.2.1\",\n    \"commit\": \"8df0fcf665a8f14949e189c8d6e2e0204a858b06\"\n  },\n  \"_source\": \"https://github.com/angular-ui/ui-utils.git\",\n  \"_target\": \"0.2.1\",\n  \"_originalSource\": \"angular-ui-utils\"\n}"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/angular-ui-utils/.travis.yml",
    "content": "---\n# blacklist the bower branch\nbranches:\n  only:\n    - master\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/angular-ui-utils/CHANGELOG.md",
    "content": "<a name=\"v0.2.1\"></a>\n### v0.2.1 (2015-01-02)\n\n#### Bug Fixes\n\n* exclude demo code from final build ([5440d6fa](http://github.com/angular-ui/ui-utils/commit/8c91c5e1f4e43baf9bb910e39640586497ac06d0))\n\n<a name=\"v0.2.0\"></a>\n## v0.2.0 (2014-12-31)\n\n\n#### Bug Fixes\n\n* **dep:** correct jquery 2.1.0 component path ([fd03855a](http://github.com/angular-ui/ui-utils/commit/fd03855ac336d00ce19685f4df90b862e2f5c9b4))\n* **gh-pages:** wrong download link ([d575856e](http://github.com/angular-ui/ui-utils/commit/d575856e9ce575d40015d532d8a3684521f5d26d), closes [#186](http://github.com/angular-ui/ui-utils/issues/186))\n* **scrollfix:** get scrollTop from scrollfix-target ([0724d1d4](http://github.com/angular-ui/ui-utils/commit/0724d1d41593d3d89ecd015026576570360f2f20))\n* **travis:** fix jslint errors in mask.js ([41534729](http://github.com/angular-ui/ui-utils/commit/415347293d7200d8fc4a14b99e9744249e6c80da))\n\n\n#### Features\n\n* **scroll:** Rename ui-scroll* files to scroll* ([9dbb1b18](http://github.com/angular-ui/ui-utils/commit/9dbb1b185ac51bdce834405f7b43e514ad29d978))\n\n\n#### Breaking Changes\n\n* if you rely on ui-mask to invalidate an empty viewValue\nthis will no longer work. Please use the required attribute or ng-required\ndirective to specify whether the input is required.\n\nfixes #198\n ([781e59e5](http://github.com/angular-ui/ui-utils/commit/781e59e5a1fa72db91eca6a257408ffe72da0c57))\n\n<a name=\"v0.1.0\"></a>\n## v0.1.0 (2013-12-29)\n\n\n#### Bug Fixes\n\n* **mark:** TypeError: input is undefined ([5440d6fa](http://github.com/angular-ui/ui-utils/commit/5440d6fa8514ee86efc480b0abbf66cf244889ad))\n* **publisher:**\n  * don't throw error when 'dist/sub' don't exist ([bd319236](http://github.com/angular-ui/ui-utils/commit/bd31923668c0ea80311b9dbe7d72bfbe55956325))\n  * rename sub componenet stuff ([5dcdc379](http://github.com/angular-ui/ui-utils/commit/5dcdc3794efe66112522415aafe9ebe965a274f6))\n* **ui-scroll:**\n  * 'newitems' is not defined. ([796e310a](http://github.com/angular-ui/ui-utils/commit/796e310a26ac43a248c0c732877242890fdda2be))\n  * 'isArray' is not defined. ([3fd7fc47](http://github.com/angular-ui/ui-utils/commit/3fd7fc47de7d05460a55ca42e4afec60d8e8cc4d))\n  * 'setOffset' is not defined. ([32140e04](http://github.com/angular-ui/ui-utils/commit/32140e04be176c4b2a5954d2cf8e9ec3c48a6f5c))\n\n\n#### Features\n\n* **alias:** Created a new ui-alias module for renaming/combining directives ([1582d54e](http://github.com/angular-ui/ui-utils/commit/1582d54ecaf81cb516a28368c0d409b5d5fe7da9))\n* **grunt:**\n  * add 'changelog' task ([b7fed5a6](http://github.com/angular-ui/ui-utils/commit/b7fed5a6026121d0098f892aa0a221c0d9c14d56), closes [#145](http://github.com/angular-ui/ui-utils/issues/145))\n  * use Angular UI Publisher ([3c209713](http://github.com/angular-ui/ui-utils/commit/3c20971307e50741f88da21cb638077237e56da2), closes [#153](http://github.com/angular-ui/ui-utils/issues/153))\n  * new 'serve' task ([a18ed32c](http://github.com/angular-ui/ui-utils/commit/a18ed32ce134acabe7adc79b41e82ed6c52109ed))\n  * quality code more strict ([332ebff1](http://github.com/angular-ui/ui-utils/commit/332ebff1fdc7edf4d44d64f4796ec2f70e90947f))\n  * use ngmin in the 'dist' task ([93ba905f](http://github.com/angular-ui/ui-utils/commit/93ba905fadfd4d0970d384f7978e19a3561cea65))\n  * add ngmin build all subcomponents in dist/sub ([783140ab](http://github.com/angular-ui/ui-utils/commit/783140abe1b8d6c0f842eceb7fc24a0f16d73ca5))\n* **publisher:**\n  * change travis scripts to work with the component-publisher system ([12d97d3b](http://github.com/angular-ui/ui-utils/commit/12d97d3bf88da86875141093fc164f1537d0dfe2))\n  * add and config component-publisher system ([4cea7ea5](http://github.com/angular-ui/ui-utils/commit/4cea7ea5bb4c47ad74c4f5123121a2896bf6f717))\n* **travis:** add sub component auto publishing :) ([0d64db00](http://github.com/angular-ui/ui-utils/commit/0d64db00a5c50816cbf0b022aa5607fee29d5e2a))\n\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/angular-ui-utils/bower.json",
    "content": "{\n  \"name\": \"angular-ui-utils\",\n  \"version\": \"0.2.1\",\n  \"main\": \"./ui-utils.js\",\n  \"dependencies\": {\n    \"angular\": \">= 1.0.2\"\n  }\n}\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/angular-ui-utils/ui-utils-ieshiv.js",
    "content": "/**\n * angular-ui-utils - Swiss-Army-Knife of AngularJS tools (with no external dependencies!)\n * @version v0.2.1 - 2015-01-02\n * @link http://angular-ui.github.com\n * @license MIT License, http://www.opensource.org/licenses/MIT\n */\n// READ: http://docs-next.angularjs.org/guide/ie\n// element tags are statically defined in order to accommodate lazy-loading whereby directives are also unknown\n\n// The ieshiv takes care of our ui.directives and AngularJS's ng-view, ng-include, ng-pluralize, ng-switch.\n// However, IF you have custom directives that can be used as html tags (yours or someone else's) then\n// add list of directives into <code>window.myCustomTags</code>\n\n// <!--[if lte IE 8]>\n//    <script>\n//    window.myCustomTags = [ 'yourCustomDirective', 'somebodyElsesDirective' ]; // optional\n//    </script>\n//    <script src=\"build/angular-ui-ieshiv.js\"></script>\n// <![endif]-->\n\n(function (window, document) {\n  \"use strict\";\n\n  var tags = [ \"ngInclude\", \"ngPluralize\", \"ngView\", \"ngSwitch\", \"uiCurrency\", \"uiCodemirror\", \"uiDate\", \"uiEvent\",\n                \"uiKeypress\", \"uiKeyup\", \"uiKeydown\", \"uiMask\", \"uiMapInfoWindow\", \"uiMapMarker\", \"uiMapPolyline\",\n                \"uiMapPolygon\", \"uiMapRectangle\", \"uiMapCircle\", \"uiMapGroundOverlay\", \"uiModal\", \"uiReset\",\n                \"uiScrollfix\", \"uiSelect2\", \"uiShow\", \"uiHide\", \"uiToggle\", \"uiSortable\", \"uiTinymce\"\n                ];\n\n  window.myCustomTags =  window.myCustomTags || []; // externally defined by developer using angular-ui directives\n  tags.push.apply(tags, window.myCustomTags);\n\n  var toCustomElements = function (str) {\n    var result = [];\n    var dashed = str.replace(/([A-Z])/g, function ($1) {\n      return \" \" + $1.toLowerCase();\n    });\n    var tokens = dashed.split(\" \");\n\n    // If a token is just a single name (i.e. no namespace) then we juse define the elements the name given\n    if (tokens.length === 1) {\n      var name = tokens[0];\n\n      result.push(name);\n      result.push(\"x-\" + name);\n      result.push(\"data-\" + name);\n    } else {\n      var ns = tokens[0];\n      var dirname = tokens.slice(1).join(\"-\");\n\n      // this is finite list and it seemed senseless to create a custom method\n      result.push(ns + \":\" + dirname);\n      result.push(ns + \"-\" + dirname);\n      result.push(\"x-\" + ns + \"-\" + dirname);\n      result.push(\"data-\" + ns + \"-\" + dirname);\n    }\n    return result;\n  };\n\n  for (var i = 0, tlen = tags.length; i < tlen; i++) {\n    var customElements = toCustomElements(tags[i]);\n    for (var j = 0, clen = customElements.length; j < clen; j++) {\n      var customElement = customElements[j];\n      document.createElement(customElement);\n    }\n  }\n\n})(window, document);\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/angular-ui-utils/ui-utils.js",
    "content": "/**\n * angular-ui-utils - Swiss-Army-Knife of AngularJS tools (with no external dependencies!)\n * @version v0.2.1 - 2015-01-02\n * @link http://angular-ui.github.com\n * @license MIT License, http://www.opensource.org/licenses/MIT\n */\nangular.module('ui.alias', []).config(['$compileProvider', 'uiAliasConfig', function($compileProvider, uiAliasConfig){\n  'use strict';\n\n  uiAliasConfig = uiAliasConfig || {};\n  angular.forEach(uiAliasConfig, function(config, alias){\n    if (angular.isString(config)) {\n      config = {\n        replace: true,\n        template: config\n      };\n    }\n    $compileProvider.directive(alias, function(){\n      return config;\n    });\n  });\n}]);\n\n/**\n * General-purpose Event binding. Bind any event not natively supported by Angular\n * Pass an object with keynames for events to ui-event\n * Allows $event object and $params object to be passed\n *\n * @example <input ui-event=\"{ focus : 'counter++', blur : 'someCallback()' }\">\n * @example <input ui-event=\"{ myCustomEvent : 'myEventHandler($event, $params)'}\">\n *\n * @param ui-event {string|object literal} The event to bind to as a string or a hash of events with their callbacks\n */\nangular.module('ui.event',[]).directive('uiEvent', ['$parse',\n  function ($parse) {\n    'use strict';\n\n    return function ($scope, elm, attrs) {\n      var events = $scope.$eval(attrs.uiEvent);\n      angular.forEach(events, function (uiEvent, eventName) {\n        var fn = $parse(uiEvent);\n        elm.bind(eventName, function (evt) {\n          var params = Array.prototype.slice.call(arguments);\n          //Take out first paramater (event object);\n          params = params.splice(1);\n          fn($scope, {$event: evt, $params: params});\n          if (!$scope.$$phase) {\n            $scope.$apply();\n          }\n        });\n      });\n    };\n  }]);\n\n/**\n * A replacement utility for internationalization very similar to sprintf.\n *\n * @param replace {mixed} The tokens to replace depends on type\n *  string: all instances of $0 will be replaced\n *  array: each instance of $0, $1, $2 etc. will be placed with each array item in corresponding order\n *  object: all attributes will be iterated through, with :key being replaced with its corresponding value\n * @return string\n *\n * @example: 'Hello :name, how are you :day'.format({ name:'John', day:'Today' })\n * @example: 'Records $0 to $1 out of $2 total'.format(['10', '20', '3000'])\n * @example: '$0 agrees to all mentions $0 makes in the event that $0 hits a tree while $0 is driving drunk'.format('Bob')\n */\nangular.module('ui.format',[]).filter('format', function(){\n  'use strict';\n\n  return function(value, replace) {\n    var target = value;\n    if (angular.isString(target) && replace !== undefined) {\n      if (!angular.isArray(replace) && !angular.isObject(replace)) {\n        replace = [replace];\n      }\n      if (angular.isArray(replace)) {\n        var rlen = replace.length;\n        var rfx = function (str, i) {\n          i = parseInt(i, 10);\n          return (i >= 0 && i < rlen) ? replace[i] : str;\n        };\n        target = target.replace(/\\$([0-9]+)/g, rfx);\n      }\n      else {\n        angular.forEach(replace, function(value, key){\n          target = target.split(':' + key).join(value);\n        });\n      }\n    }\n    return target;\n  };\n});\n\n/**\n * Wraps the\n * @param text {string} haystack to search through\n * @param search {string} needle to search for\n * @param [caseSensitive] {boolean} optional boolean to use case-sensitive searching\n */\nangular.module('ui.highlight',[]).filter('highlight', function () {\n  'use strict';\n\n  return function (text, search, caseSensitive) {\n    if (text && (search || angular.isNumber(search))) {\n      text = text.toString();\n      search = search.toString();\n      if (caseSensitive) {\n        return text.split(search).join('<span class=\"ui-match\">' + search + '</span>');\n      } else {\n        return text.replace(new RegExp(search, 'gi'), '<span class=\"ui-match\">$&</span>');\n      }\n    } else {\n      return text;\n    }\n  };\n});\n\n// modeled after: angular-1.0.7/src/ng/directive/ngInclude.js\nangular.module('ui.include',[])\n.directive('uiInclude', ['$http', '$templateCache', '$anchorScroll', '$compile',\n                 function($http,   $templateCache,   $anchorScroll,   $compile) {\n  'use strict';\n\n  return {\n    restrict: 'ECA',\n    terminal: true,\n    compile: function(element, attr) {\n      var srcExp = attr.uiInclude || attr.src,\n          fragExp = attr.fragment || '',\n          onloadExp = attr.onload || '',\n          autoScrollExp = attr.autoscroll;\n\n      return function(scope, element) {\n        var changeCounter = 0,\n            childScope;\n\n        var clearContent = function() {\n          if (childScope) {\n            childScope.$destroy();\n            childScope = null;\n          }\n\n          element.html('');\n        };\n\n        function ngIncludeWatchAction() {\n          var thisChangeId = ++changeCounter;\n          var src = scope.$eval(srcExp);\n          var fragment = scope.$eval(fragExp);\n\n          if (src) {\n            $http.get(src, {cache: $templateCache}).success(function(response) {\n              if (thisChangeId !== changeCounter) { return; }\n\n              if (childScope) { childScope.$destroy(); }\n              childScope = scope.$new();\n\n              var contents;\n              if (fragment) {\n                contents = angular.element('<div/>').html(response).find(fragment);\n              }\n              else {\n                contents = angular.element('<div/>').html(response).contents();\n              }\n              element.html(contents);\n              $compile(contents)(childScope);\n\n              if (angular.isDefined(autoScrollExp) && (!autoScrollExp || scope.$eval(autoScrollExp))) {\n                $anchorScroll();\n              }\n\n              childScope.$emit('$includeContentLoaded');\n              scope.$eval(onloadExp);\n            }).error(function() {\n              if (thisChangeId === changeCounter) { clearContent(); }\n            });\n          } else { clearContent(); }\n        }\n\n        scope.$watch(fragExp, ngIncludeWatchAction);\n        scope.$watch(srcExp, ngIncludeWatchAction);\n      };\n    }\n  };\n}]);\n\n/**\n * Provides an easy way to toggle a checkboxes indeterminate property\n *\n * @example <input type=\"checkbox\" ui-indeterminate=\"isUnkown\">\n */\nangular.module('ui.indeterminate',[]).directive('uiIndeterminate', [\n  function () {\n    'use strict';\n\n    return {\n      compile: function(tElm, tAttrs) {\n        if (!tAttrs.type || tAttrs.type.toLowerCase() !== 'checkbox') {\n          return angular.noop;\n        }\n\n        return function ($scope, elm, attrs) {\n          $scope.$watch(attrs.uiIndeterminate, function(newVal) {\n            elm[0].indeterminate = !!newVal;\n          });\n        };\n      }\n    };\n  }]);\n\n/**\n * Converts variable-esque naming conventions to something presentational, capitalized words separated by space.\n * @param {String} value The value to be parsed and prettified.\n * @param {String} [inflector] The inflector to use. Default: humanize.\n * @return {String}\n * @example {{ 'Here Is my_phoneNumber' | inflector:'humanize' }} => Here Is My Phone Number\n *          {{ 'Here Is my_phoneNumber' | inflector:'underscore' }} => here_is_my_phone_number\n *          {{ 'Here Is my_phoneNumber' | inflector:'variable' }} => hereIsMyPhoneNumber\n */\nangular.module('ui.inflector',[]).filter('inflector', function () {\n  'use strict';\n\n  function tokenize(text) {\n    text = text.replace(/([A-Z])|([\\-|\\_])/g, function(_, $1) { return ' ' + ($1 || ''); });\n    return text.replace(/\\s\\s+/g, ' ').trim().toLowerCase().split(' ');\n  }\n\n  function capitalizeTokens(tokens) {\n    var result = [];\n    angular.forEach(tokens, function(token) {\n      result.push(token.charAt(0).toUpperCase() + token.substr(1));\n    });\n    return result;\n  }\n\n  var inflectors = {\n    humanize: function (value) {\n      return capitalizeTokens(tokenize(value)).join(' ');\n    },\n    underscore: function (value) {\n      return tokenize(value).join('_');\n    },\n    variable: function (value) {\n      value = tokenize(value);\n      value = value[0] + capitalizeTokens(value.slice(1)).join('');\n      return value;\n    }\n  };\n\n  return function (text, inflector) {\n    if (inflector !== false && angular.isString(text)) {\n      inflector = inflector || 'humanize';\n      return inflectors[inflector](text);\n    } else {\n      return text;\n    }\n  };\n});\n\n/**\n * General-purpose jQuery wrapper. Simply pass the plugin name as the expression.\n *\n * It is possible to specify a default set of parameters for each jQuery plugin.\n * Under the jq key, namespace each plugin by that which will be passed to ui-jq.\n * Unfortunately, at this time you can only pre-define the first parameter.\n * @example { jq : { datepicker : { showOn:'click' } } }\n *\n * @param ui-jq {string} The $elm.[pluginName]() to call.\n * @param [ui-options] {mixed} Expression to be evaluated and passed as options to the function\n *     Multiple parameters can be separated by commas\n * @param [ui-refresh] {expression} Watch expression and refire plugin on changes\n *\n * @example <input ui-jq=\"datepicker\" ui-options=\"{showOn:'click'},secondParameter,thirdParameter\" ui-refresh=\"iChange\">\n */\nangular.module('ui.jq',[]).\n  value('uiJqConfig',{}).\n  directive('uiJq', ['uiJqConfig', '$timeout', function uiJqInjectingFunction(uiJqConfig, $timeout) {\n  'use strict';\n\n\n  return {\n    restrict: 'A',\n    compile: function uiJqCompilingFunction(tElm, tAttrs) {\n\n      if (!angular.isFunction(tElm[tAttrs.uiJq])) {\n        throw new Error('ui-jq: The \"' + tAttrs.uiJq + '\" function does not exist');\n      }\n      var options = uiJqConfig && uiJqConfig[tAttrs.uiJq];\n\n      return function uiJqLinkingFunction(scope, elm, attrs) {\n\n        var linkOptions = [];\n\n        // If ui-options are passed, merge (or override) them onto global defaults and pass to the jQuery method\n        if (attrs.uiOptions) {\n          linkOptions = scope.$eval('[' + attrs.uiOptions + ']');\n          if (angular.isObject(options) && angular.isObject(linkOptions[0])) {\n            linkOptions[0] = angular.extend({}, options, linkOptions[0]);\n          }\n        } else if (options) {\n          linkOptions = [options];\n        }\n        // If change compatibility is enabled, the form input's \"change\" event will trigger an \"input\" event\n        if (attrs.ngModel && elm.is('select,input,textarea')) {\n          elm.bind('change', function() {\n            elm.trigger('input');\n          });\n        }\n\n        // Call jQuery method and pass relevant options\n        function callPlugin() {\n          $timeout(function() {\n            elm[attrs.uiJq].apply(elm, linkOptions);\n          }, 0, false);\n        }\n\n        // If ui-refresh is used, re-fire the the method upon every change\n        if (attrs.uiRefresh) {\n          scope.$watch(attrs.uiRefresh, function() {\n            callPlugin();\n          });\n        }\n        callPlugin();\n      };\n    }\n  };\n}]);\n\nangular.module('ui.keypress',[]).\nfactory('keypressHelper', ['$parse', function keypress($parse){\n  'use strict';\n\n  var keysByCode = {\n    8: 'backspace',\n    9: 'tab',\n    13: 'enter',\n    27: 'esc',\n    32: 'space',\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: 'delete'\n  };\n\n  var capitaliseFirstLetter = function (string) {\n    return string.charAt(0).toUpperCase() + string.slice(1);\n  };\n\n  return function(mode, scope, elm, attrs) {\n    var params, combinations = [];\n    params = scope.$eval(attrs['ui'+capitaliseFirstLetter(mode)]);\n\n    // Prepare combinations for simple checking\n    angular.forEach(params, function (v, k) {\n      var combination, expression;\n      expression = $parse(v);\n\n      angular.forEach(k.split(' '), function(variation) {\n        combination = {\n          expression: expression,\n          keys: {}\n        };\n        angular.forEach(variation.split('-'), function (value) {\n          combination.keys[value] = true;\n        });\n        combinations.push(combination);\n      });\n    });\n\n    // Check only matching of pressed keys one of the conditions\n    elm.bind(mode, function (event) {\n      // No need to do that inside the cycle\n      var metaPressed = !!(event.metaKey && !event.ctrlKey);\n      var altPressed = !!event.altKey;\n      var ctrlPressed = !!event.ctrlKey;\n      var shiftPressed = !!event.shiftKey;\n      var keyCode = event.keyCode;\n\n      // normalize keycodes\n      if (mode === 'keypress' && !shiftPressed && keyCode >= 97 && keyCode <= 122) {\n        keyCode = keyCode - 32;\n      }\n\n      // Iterate over prepared combinations\n      angular.forEach(combinations, function (combination) {\n\n        var mainKeyPressed = combination.keys[keysByCode[keyCode]] || combination.keys[keyCode.toString()];\n\n        var metaRequired = !!combination.keys.meta;\n        var altRequired = !!combination.keys.alt;\n        var ctrlRequired = !!combination.keys.ctrl;\n        var shiftRequired = !!combination.keys.shift;\n\n        if (\n          mainKeyPressed &&\n          ( metaRequired === metaPressed ) &&\n          ( altRequired === altPressed ) &&\n          ( ctrlRequired === ctrlPressed ) &&\n          ( shiftRequired === shiftPressed )\n        ) {\n          // Run the function\n          scope.$apply(function () {\n            combination.expression(scope, { '$event': event });\n          });\n        }\n      });\n    });\n  };\n}]);\n\n/**\n * Bind one or more handlers to particular keys or their combination\n * @param hash {mixed} keyBindings Can be an object or string where keybinding expression of keys or keys combinations and AngularJS Exspressions are set. Object syntax: \"{ keys1: expression1 [, keys2: expression2 [ , ... ]]}\". String syntax: \"\"expression1 on keys1 [ and expression2 on keys2 [ and ... ]]\"\". Expression is an AngularJS Expression, and key(s) are dash-separated combinations of keys and modifiers (one or many, if any. Order does not matter). Supported modifiers are 'ctrl', 'shift', 'alt' and key can be used either via its keyCode (13 for Return) or name. Named keys are 'backspace', 'tab', 'enter', 'esc', 'space', 'pageup', 'pagedown', 'end', 'home', 'left', 'up', 'right', 'down', 'insert', 'delete'.\n * @example <input ui-keypress=\"{enter:'x = 1', 'ctrl-shift-space':'foo()', 'shift-13':'bar()'}\" /> <input ui-keypress=\"foo = 2 on ctrl-13 and bar('hello') on shift-esc\" />\n **/\nangular.module('ui.keypress').directive('uiKeydown', ['keypressHelper', function(keypressHelper){\n  'use strict';\n\n  return {\n    link: function (scope, elm, attrs) {\n      keypressHelper('keydown', scope, elm, attrs);\n    }\n  };\n}]);\n\nangular.module('ui.keypress').directive('uiKeypress', ['keypressHelper', function(keypressHelper){\n  'use strict';\n\n  return {\n    link: function (scope, elm, attrs) {\n      keypressHelper('keypress', scope, elm, attrs);\n    }\n  };\n}]);\n\nangular.module('ui.keypress').directive('uiKeyup', ['keypressHelper', function(keypressHelper){\n  'use strict';\n\n  return {\n    link: function (scope, elm, attrs) {\n      keypressHelper('keyup', scope, elm, attrs);\n    }\n  };\n}]);\n\n/*\n Attaches input mask onto input element\n */\nangular.module('ui.mask', [])\n  .value('uiMaskConfig', {\n    'maskDefinitions': {\n      '9': /\\d/,\n      'A': /[a-zA-Z]/,\n      '*': /[a-zA-Z0-9]/\n    },\n    'clearOnBlur': true\n  })\n  .directive('uiMask', ['uiMaskConfig', '$parse', function (maskConfig, $parse) {\n    'use strict';\n\n    return {\n      priority: 100,\n      require: 'ngModel',\n      restrict: 'A',\n      compile: function uiMaskCompilingFunction(){\n        var options = maskConfig;\n\n        return function uiMaskLinkingFunction(scope, iElement, iAttrs, controller){\n          var maskProcessed = false, eventsBound = false,\n            maskCaretMap, maskPatterns, maskPlaceholder, maskComponents,\n          // Minimum required length of the value to be considered valid\n            minRequiredLength,\n            value, valueMasked, isValid,\n          // Vars for initializing/uninitializing\n            originalPlaceholder = iAttrs.placeholder,\n            originalMaxlength = iAttrs.maxlength,\n          // Vars used exclusively in eventHandler()\n            oldValue, oldValueUnmasked, oldCaretPosition, oldSelectionLength;\n\n          function initialize(maskAttr){\n            if (!angular.isDefined(maskAttr)) {\n              return uninitialize();\n            }\n            processRawMask(maskAttr);\n            if (!maskProcessed) {\n              return uninitialize();\n            }\n            initializeElement();\n            bindEventListeners();\n            return true;\n          }\n\n          function initPlaceholder(placeholderAttr) {\n            if(! angular.isDefined(placeholderAttr)) {\n              return;\n            }\n\n            maskPlaceholder = placeholderAttr;\n\n            // If the mask is processed, then we need to update the value\n            if (maskProcessed) {\n              eventHandler();\n            }\n          }\n\n          function formatter(fromModelValue){\n            if (!maskProcessed) {\n              return fromModelValue;\n            }\n            value = unmaskValue(fromModelValue || '');\n            isValid = validateValue(value);\n            controller.$setValidity('mask', isValid);\n            return isValid && value.length ? maskValue(value) : undefined;\n          }\n\n          function parser(fromViewValue){\n            if (!maskProcessed) {\n              return fromViewValue;\n            }\n            value = unmaskValue(fromViewValue || '');\n            isValid = validateValue(value);\n            // We have to set viewValue manually as the reformatting of the input\n            // value performed by eventHandler() doesn't happen until after\n            // this parser is called, which causes what the user sees in the input\n            // to be out-of-sync with what the controller's $viewValue is set to.\n            controller.$viewValue = value.length ? maskValue(value) : '';\n            controller.$setValidity('mask', isValid);\n            if (value === '' && iAttrs.required) {\n                controller.$setValidity('required', !controller.$error.required);\n            }\n            return isValid ? value : undefined;\n          }\n\n          var linkOptions = {};\n\n          if (iAttrs.uiOptions) {\n            linkOptions = scope.$eval('[' + iAttrs.uiOptions + ']');\n            if (angular.isObject(linkOptions[0])) {\n              // we can't use angular.copy nor angular.extend, they lack the power to do a deep merge\n              linkOptions = (function(original, current){\n                for(var i in original) {\n                  if (Object.prototype.hasOwnProperty.call(original, i)) {\n                    if (current[i] === undefined) {\n                      current[i] = angular.copy(original[i]);\n                    } else {\n                      angular.extend(current[i], original[i]);\n                    }\n                  }\n                }\n                return current;\n              })(options, linkOptions[0]);\n            }\n          } else {\n            linkOptions = options;\n          }\n\n          iAttrs.$observe('uiMask', initialize);\n          iAttrs.$observe('placeholder', initPlaceholder);\n          var modelViewValue = false;\n          iAttrs.$observe('modelViewValue', function(val) {\n            if(val === 'true') {\n              modelViewValue = true;\n            }\n          });\n          scope.$watch(iAttrs.ngModel, function(val) {\n            if(modelViewValue && val) {\n              var model = $parse(iAttrs.ngModel);\n              model.assign(scope, controller.$viewValue);\n            }\n          });\n          controller.$formatters.push(formatter);\n          controller.$parsers.push(parser);\n\n          function uninitialize(){\n            maskProcessed = false;\n            unbindEventListeners();\n\n            if (angular.isDefined(originalPlaceholder)) {\n              iElement.attr('placeholder', originalPlaceholder);\n            } else {\n              iElement.removeAttr('placeholder');\n            }\n\n            if (angular.isDefined(originalMaxlength)) {\n              iElement.attr('maxlength', originalMaxlength);\n            } else {\n              iElement.removeAttr('maxlength');\n            }\n\n            iElement.val(controller.$modelValue);\n            controller.$viewValue = controller.$modelValue;\n            return false;\n          }\n\n          function initializeElement(){\n            value = oldValueUnmasked = unmaskValue(controller.$modelValue || '');\n            valueMasked = oldValue = maskValue(value);\n            isValid = validateValue(value);\n            var viewValue = isValid && value.length ? valueMasked : '';\n            if (iAttrs.maxlength) { // Double maxlength to allow pasting new val at end of mask\n              iElement.attr('maxlength', maskCaretMap[maskCaretMap.length - 1] * 2);\n            }\n            iElement.attr('placeholder', maskPlaceholder);\n            iElement.val(viewValue);\n            controller.$viewValue = viewValue;\n            // Not using $setViewValue so we don't clobber the model value and dirty the form\n            // without any kind of user interaction.\n          }\n\n          function bindEventListeners(){\n            if (eventsBound) {\n              return;\n            }\n            iElement.bind('blur', blurHandler);\n            iElement.bind('mousedown mouseup', mouseDownUpHandler);\n            iElement.bind('input keyup click focus', eventHandler);\n            eventsBound = true;\n          }\n\n          function unbindEventListeners(){\n            if (!eventsBound) {\n              return;\n            }\n            iElement.unbind('blur', blurHandler);\n            iElement.unbind('mousedown', mouseDownUpHandler);\n            iElement.unbind('mouseup', mouseDownUpHandler);\n            iElement.unbind('input', eventHandler);\n            iElement.unbind('keyup', eventHandler);\n            iElement.unbind('click', eventHandler);\n            iElement.unbind('focus', eventHandler);\n            eventsBound = false;\n          }\n\n          function validateValue(value){\n            // Zero-length value validity is ngRequired's determination\n            return value.length ? value.length >= minRequiredLength : true;\n          }\n\n          function unmaskValue(value){\n            var valueUnmasked = '',\n              maskPatternsCopy = maskPatterns.slice();\n            // Preprocess by stripping mask components from value\n            value = value.toString();\n            angular.forEach(maskComponents, function (component){\n              value = value.replace(component, '');\n            });\n            angular.forEach(value.split(''), function (chr){\n              if (maskPatternsCopy.length && maskPatternsCopy[0].test(chr)) {\n                valueUnmasked += chr;\n                maskPatternsCopy.shift();\n              }\n            });\n            return valueUnmasked;\n          }\n\n          function maskValue(unmaskedValue){\n            var valueMasked = '',\n                maskCaretMapCopy = maskCaretMap.slice();\n\n            angular.forEach(maskPlaceholder.split(''), function (chr, i){\n              if (unmaskedValue.length && i === maskCaretMapCopy[0]) {\n                valueMasked  += unmaskedValue.charAt(0) || '_';\n                unmaskedValue = unmaskedValue.substr(1);\n                maskCaretMapCopy.shift();\n              }\n              else {\n                valueMasked += chr;\n              }\n            });\n            return valueMasked;\n          }\n\n          function getPlaceholderChar(i) {\n            var placeholder = iAttrs.placeholder;\n\n            if (typeof placeholder !== 'undefined' && placeholder[i]) {\n              return placeholder[i];\n            } else {\n              return '_';\n            }\n          }\n\n          // Generate array of mask components that will be stripped from a masked value\n          // before processing to prevent mask components from being added to the unmasked value.\n          // E.g., a mask pattern of '+7 9999' won't have the 7 bleed into the unmasked value.\n          // If a maskable char is followed by a mask char and has a mask\n          // char behind it, we'll split it into it's own component so if\n          // a user is aggressively deleting in the input and a char ahead\n          // of the maskable char gets deleted, we'll still be able to strip\n          // it in the unmaskValue() preprocessing.\n          function getMaskComponents() {\n            return maskPlaceholder.replace(/[_]+/g, '_').replace(/([^_]+)([a-zA-Z0-9])([^_])/g, '$1$2_$3').split('_');\n          }\n\n          function processRawMask(mask){\n            var characterCount = 0;\n\n            maskCaretMap    = [];\n            maskPatterns    = [];\n            maskPlaceholder = '';\n\n            if (typeof mask === 'string') {\n              minRequiredLength = 0;\n\n              var isOptional = false,\n                  splitMask  = mask.split('');\n\n              angular.forEach(splitMask, function (chr, i){\n                if (linkOptions.maskDefinitions[chr]) {\n\n                  maskCaretMap.push(characterCount);\n\n                  maskPlaceholder += getPlaceholderChar(i);\n                  maskPatterns.push(linkOptions.maskDefinitions[chr]);\n\n                  characterCount++;\n                  if (!isOptional) {\n                    minRequiredLength++;\n                  }\n                }\n                else if (chr === '?') {\n                  isOptional = true;\n                }\n                else {\n                  maskPlaceholder += chr;\n                  characterCount++;\n                }\n              });\n            }\n            // Caret position immediately following last position is valid.\n            maskCaretMap.push(maskCaretMap.slice().pop() + 1);\n\n            maskComponents = getMaskComponents();\n            maskProcessed  = maskCaretMap.length > 1 ? true : false;\n          }\n\n          function blurHandler(){\n            if (linkOptions.clearOnBlur) {\n              oldCaretPosition = 0;\n              oldSelectionLength = 0;\n            }\n            if (!isValid || value.length === 0) {\n              if (linkOptions.clearOnBlur) {\n                valueMasked = '';\n                iElement.val('');\n              }\n              scope.$apply(function (){\n                controller.$setViewValue('');\n              });\n            }\n          }\n\n          function mouseDownUpHandler(e){\n            if (e.type === 'mousedown') {\n              iElement.bind('mouseout', mouseoutHandler);\n            } else {\n              iElement.unbind('mouseout', mouseoutHandler);\n            }\n          }\n\n          iElement.bind('mousedown mouseup', mouseDownUpHandler);\n\n          function mouseoutHandler(){\n            /*jshint validthis: true */\n            oldSelectionLength = getSelectionLength(this);\n            iElement.unbind('mouseout', mouseoutHandler);\n          }\n\n          function eventHandler(e){\n            /*jshint validthis: true */\n            e = e || {};\n            // Allows more efficient minification\n            var eventWhich = e.which,\n              eventType = e.type;\n\n            // Prevent shift and ctrl from mucking with old values\n            if (eventWhich === 16 || eventWhich === 91) { return;}\n\n            var val = iElement.val(),\n              valOld = oldValue,\n              valMasked,\n              valUnmasked = unmaskValue(val),\n              valUnmaskedOld = oldValueUnmasked,\n              valAltered = false,\n\n              caretPos = getCaretPosition(this) || 0,\n              caretPosOld = oldCaretPosition || 0,\n              caretPosDelta = caretPos - caretPosOld,\n              caretPosMin = maskCaretMap[0],\n              caretPosMax = maskCaretMap[valUnmasked.length] || maskCaretMap.slice().shift(),\n\n              selectionLenOld = oldSelectionLength || 0,\n              isSelected = getSelectionLength(this) > 0,\n              wasSelected = selectionLenOld > 0,\n\n            // Case: Typing a character to overwrite a selection\n              isAddition = (val.length > valOld.length) || (selectionLenOld && val.length > valOld.length - selectionLenOld),\n            // Case: Delete and backspace behave identically on a selection\n              isDeletion = (val.length < valOld.length) || (selectionLenOld && val.length === valOld.length - selectionLenOld),\n              isSelection = (eventWhich >= 37 && eventWhich <= 40) && e.shiftKey, // Arrow key codes\n\n              isKeyLeftArrow = eventWhich === 37,\n            // Necessary due to \"input\" event not providing a key code\n              isKeyBackspace = eventWhich === 8 || (eventType !== 'keyup' && isDeletion && (caretPosDelta === -1)),\n              isKeyDelete = eventWhich === 46 || (eventType !== 'keyup' && isDeletion && (caretPosDelta === 0 ) && !wasSelected),\n\n            // Handles cases where caret is moved and placed in front of invalid maskCaretMap position. Logic below\n            // ensures that, on click or leftward caret placement, caret is moved leftward until directly right of\n            // non-mask character. Also applied to click since users are (arguably) more likely to backspace\n            // a character when clicking within a filled input.\n              caretBumpBack = (isKeyLeftArrow || isKeyBackspace || eventType === 'click') && caretPos > caretPosMin;\n\n            oldSelectionLength = getSelectionLength(this);\n\n            // These events don't require any action\n            if (isSelection || (isSelected && (eventType === 'click' || eventType === 'keyup'))) {\n              return;\n            }\n\n            // Value Handling\n            // ==============\n\n            // User attempted to delete but raw value was unaffected--correct this grievous offense\n            if ((eventType === 'input') && isDeletion && !wasSelected && valUnmasked === valUnmaskedOld) {\n              while (isKeyBackspace && caretPos > caretPosMin && !isValidCaretPosition(caretPos)) {\n                caretPos--;\n              }\n              while (isKeyDelete && caretPos < caretPosMax && maskCaretMap.indexOf(caretPos) === -1) {\n                caretPos++;\n              }\n              var charIndex = maskCaretMap.indexOf(caretPos);\n              // Strip out non-mask character that user would have deleted if mask hadn't been in the way.\n              valUnmasked = valUnmasked.substring(0, charIndex) + valUnmasked.substring(charIndex + 1);\n              valAltered = true;\n            }\n\n            // Update values\n            valMasked = maskValue(valUnmasked);\n\n            oldValue = valMasked;\n            oldValueUnmasked = valUnmasked;\n            iElement.val(valMasked);\n            if (valAltered) {\n              // We've altered the raw value after it's been $digest'ed, we need to $apply the new value.\n              scope.$apply(function (){\n                controller.$setViewValue(valUnmasked);\n              });\n            }\n\n            // Caret Repositioning\n            // ===================\n\n            // Ensure that typing always places caret ahead of typed character in cases where the first char of\n            // the input is a mask char and the caret is placed at the 0 position.\n            if (isAddition && (caretPos <= caretPosMin)) {\n              caretPos = caretPosMin + 1;\n            }\n\n            if (caretBumpBack) {\n              caretPos--;\n            }\n\n            // Make sure caret is within min and max position limits\n            caretPos = caretPos > caretPosMax ? caretPosMax : caretPos < caretPosMin ? caretPosMin : caretPos;\n\n            // Scoot the caret back or forth until it's in a non-mask position and within min/max position limits\n            while (!isValidCaretPosition(caretPos) && caretPos > caretPosMin && caretPos < caretPosMax) {\n              caretPos += caretBumpBack ? -1 : 1;\n            }\n\n            if ((caretBumpBack && caretPos < caretPosMax) || (isAddition && !isValidCaretPosition(caretPosOld))) {\n              caretPos++;\n            }\n            oldCaretPosition = caretPos;\n            setCaretPosition(this, caretPos);\n          }\n\n          function isValidCaretPosition(pos){ return maskCaretMap.indexOf(pos) > -1; }\n\n          function getCaretPosition(input){\n            if (!input) return 0;\n            if (input.selectionStart !== undefined) {\n              return input.selectionStart;\n            } else if (document.selection) {\n              // Curse you IE\n              input.focus();\n              var selection = document.selection.createRange();\n              selection.moveStart('character', input.value ? -input.value.length : 0);\n              return selection.text.length;\n            }\n            return 0;\n          }\n\n          function setCaretPosition(input, pos){\n            if (!input) return 0;\n            if (input.offsetWidth === 0 || input.offsetHeight === 0) {\n              return; // Input's hidden\n            }\n            if (input.setSelectionRange) {\n              input.focus();\n              input.setSelectionRange(pos, pos);\n            }\n            else if (input.createTextRange) {\n              // Curse you IE\n              var range = input.createTextRange();\n              range.collapse(true);\n              range.moveEnd('character', pos);\n              range.moveStart('character', pos);\n              range.select();\n            }\n          }\n\n          function getSelectionLength(input){\n            if (!input) return 0;\n            if (input.selectionStart !== undefined) {\n              return (input.selectionEnd - input.selectionStart);\n            }\n            if (document.selection) {\n              return (document.selection.createRange().text.length);\n            }\n            return 0;\n          }\n\n          // https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/indexOf\n          if (!Array.prototype.indexOf) {\n            Array.prototype.indexOf = function (searchElement /*, fromIndex */){\n              if (this === null) {\n                throw new TypeError();\n              }\n              var t = Object(this);\n              var len = t.length >>> 0;\n              if (len === 0) {\n                return -1;\n              }\n              var n = 0;\n              if (arguments.length > 1) {\n                n = Number(arguments[1]);\n                if (n !== n) { // shortcut for verifying if it's NaN\n                  n = 0;\n                } else if (n !== 0 && n !== Infinity && n !== -Infinity) {\n                  n = (n > 0 || -1) * Math.floor(Math.abs(n));\n                }\n              }\n              if (n >= len) {\n                return -1;\n              }\n              var k = n >= 0 ? n : Math.max(len - Math.abs(n), 0);\n              for (; k < len; k++) {\n                if (k in t && t[k] === searchElement) {\n                  return k;\n                }\n              }\n              return -1;\n            };\n          }\n\n        };\n      }\n    };\n  }\n]);\n\n/**\n * Add a clear button to form inputs to reset their value\n */\nangular.module('ui.reset',[]).value('uiResetConfig',null).directive('uiReset', ['uiResetConfig', function (uiResetConfig) {\n  'use strict';\n\n  var resetValue = null;\n  if (uiResetConfig !== undefined){\n      resetValue = uiResetConfig;\n  }\n  return {\n    require: 'ngModel',\n    link: function (scope, elm, attrs, ctrl) {\n      var aElement;\n      aElement = angular.element('<a class=\"ui-reset\" />');\n      elm.wrap('<span class=\"ui-resetwrap\" />').after(aElement);\n      aElement.bind('click', function (e) {\n        e.preventDefault();\n        scope.$apply(function () {\n          if (attrs.uiReset){\n            ctrl.$setViewValue(scope.$eval(attrs.uiReset));\n          }else{\n            ctrl.$setViewValue(resetValue);\n          }\n          ctrl.$render();\n        });\n      });\n    }\n  };\n}]);\n\n/**\n * Set a $uiRoute boolean to see if the current route matches\n */\nangular.module('ui.route', []).directive('uiRoute', ['$location', '$parse', function ($location, $parse) {\n  'use strict';\n\n  return {\n    restrict: 'AC',\n    scope: true,\n    compile: function(tElement, tAttrs) {\n      var useProperty;\n      if (tAttrs.uiRoute) {\n        useProperty = 'uiRoute';\n      } else if (tAttrs.ngHref) {\n        useProperty = 'ngHref';\n      } else if (tAttrs.href) {\n        useProperty = 'href';\n      } else {\n        throw new Error('uiRoute missing a route or href property on ' + tElement[0]);\n      }\n      return function ($scope, elm, attrs) {\n        var modelSetter = $parse(attrs.ngModel || attrs.routeModel || '$uiRoute').assign;\n        var watcher = angular.noop;\n\n        // Used by href and ngHref\n        function staticWatcher(newVal) {\n          var hash = newVal.indexOf('#');\n          if (hash > -1){\n            newVal = newVal.substr(hash + 1);\n          }\n          watcher = function watchHref() {\n            modelSetter($scope, ($location.path().indexOf(newVal) > -1));\n          };\n          watcher();\n        }\n        // Used by uiRoute\n        function regexWatcher(newVal) {\n          var hash = newVal.indexOf('#');\n          if (hash > -1){\n            newVal = newVal.substr(hash + 1);\n          }\n          watcher = function watchRegex() {\n            var regexp = new RegExp('^' + newVal + '$', ['i']);\n            modelSetter($scope, regexp.test($location.path()));\n          };\n          watcher();\n        }\n\n        switch (useProperty) {\n          case 'uiRoute':\n            // if uiRoute={{}} this will be undefined, otherwise it will have a value and $observe() never gets triggered\n            if (attrs.uiRoute){\n              regexWatcher(attrs.uiRoute);\n            }else{\n              attrs.$observe('uiRoute', regexWatcher);\n            }\n            break;\n          case 'ngHref':\n            // Setup watcher() every time ngHref changes\n            if (attrs.ngHref){\n              staticWatcher(attrs.ngHref);\n            }else{\n              attrs.$observe('ngHref', staticWatcher);\n            }\n            break;\n          case 'href':\n            // Setup watcher()\n            staticWatcher(attrs.href);\n        }\n\n        $scope.$on('$routeChangeSuccess', function(){\n          watcher();\n        });\n\n        //Added for compatibility with ui-router\n        $scope.$on('$stateChangeSuccess', function(){\n          watcher();\n        });\n      };\n    }\n  };\n}]);\n\nangular.module('ui.scroll.jqlite', ['ui.scroll']).service('jqLiteExtras', [\n  '$log', '$window', function(console, window) {\n    'use strict';\n\n    return {\n      registerFor: function(element) {\n        var convertToPx, css, getMeasurements, getStyle, getWidthHeight, isWindow, scrollTo;\n        css = angular.element.prototype.css;\n        element.prototype.css = function(name, value) {\n          var elem, self;\n          self = this;\n          elem = self[0];\n          if (!(!elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style)) {\n            return css.call(self, name, value);\n          }\n        };\n        isWindow = function(obj) {\n          return obj && obj.document && obj.location && obj.alert && obj.setInterval;\n        };\n        scrollTo = function(self, direction, value) {\n          var elem, method, preserve, prop, _ref;\n          elem = self[0];\n          _ref = {\n            top: ['scrollTop', 'pageYOffset', 'scrollLeft'],\n            left: ['scrollLeft', 'pageXOffset', 'scrollTop']\n          }[direction], method = _ref[0], prop = _ref[1], preserve = _ref[2];\n          if (isWindow(elem)) {\n            if (angular.isDefined(value)) {\n              return elem.scrollTo(self[preserve].call(self), value);\n            } else {\n              if (prop in elem) {\n                return elem[prop];\n              } else {\n                return elem.document.documentElement[method];\n              }\n            }\n          } else {\n            if (angular.isDefined(value)) {\n              return elem[method] = value;\n            } else {\n              return elem[method];\n            }\n          }\n        };\n        if (window.getComputedStyle) {\n          getStyle = function(elem) {\n            return window.getComputedStyle(elem, null);\n          };\n          convertToPx = function(elem, value) {\n            return parseFloat(value);\n          };\n        } else {\n          getStyle = function(elem) {\n            return elem.currentStyle;\n          };\n          convertToPx = function(elem, value) {\n            var core_pnum, left, result, rnumnonpx, rs, rsLeft, style;\n            core_pnum = /[+-]?(?:\\d*\\.|)\\d+(?:[eE][+-]?\\d+|)/.source;\n            rnumnonpx = new RegExp('^(' + core_pnum + ')(?!px)[a-z%]+$', 'i');\n            if (!rnumnonpx.test(value)) {\n              return parseFloat(value);\n            } else {\n              style = elem.style;\n              left = style.left;\n              rs = elem.runtimeStyle;\n              rsLeft = rs && rs.left;\n              if (rs) {\n                rs.left = style.left;\n              }\n              style.left = value;\n              result = style.pixelLeft;\n              style.left = left;\n              if (rsLeft) {\n                rs.left = rsLeft;\n              }\n              return result;\n            }\n          };\n        }\n        getMeasurements = function(elem, measure) {\n          var base, borderA, borderB, computedMarginA, computedMarginB, computedStyle, dirA, dirB, marginA, marginB, paddingA, paddingB, _ref;\n          if (isWindow(elem)) {\n            base = document.documentElement[{\n              height: 'clientHeight',\n              width: 'clientWidth'\n            }[measure]];\n            return {\n              base: base,\n              padding: 0,\n              border: 0,\n              margin: 0\n            };\n          }\n          _ref = {\n            width: [elem.offsetWidth, 'Left', 'Right'],\n            height: [elem.offsetHeight, 'Top', 'Bottom']\n          }[measure], base = _ref[0], dirA = _ref[1], dirB = _ref[2];\n          computedStyle = getStyle(elem);\n          paddingA = convertToPx(elem, computedStyle['padding' + dirA]) || 0;\n          paddingB = convertToPx(elem, computedStyle['padding' + dirB]) || 0;\n          borderA = convertToPx(elem, computedStyle['border' + dirA + 'Width']) || 0;\n          borderB = convertToPx(elem, computedStyle['border' + dirB + 'Width']) || 0;\n          computedMarginA = computedStyle['margin' + dirA];\n          computedMarginB = computedStyle['margin' + dirB];\n          marginA = convertToPx(elem, computedMarginA) || 0;\n          marginB = convertToPx(elem, computedMarginB) || 0;\n          return {\n            base: base,\n            padding: paddingA + paddingB,\n            border: borderA + borderB,\n            margin: marginA + marginB\n          };\n        };\n        getWidthHeight = function(elem, direction, measure) {\n          var computedStyle, measurements, result;\n          measurements = getMeasurements(elem, direction);\n          if (measurements.base > 0) {\n            return {\n              base: measurements.base - measurements.padding - measurements.border,\n              outer: measurements.base,\n              outerfull: measurements.base + measurements.margin\n            }[measure];\n          } else {\n            computedStyle = getStyle(elem);\n            result = computedStyle[direction];\n            if (result < 0 || result === null) {\n              result = elem.style[direction] || 0;\n            }\n            result = parseFloat(result) || 0;\n            return {\n              base: result - measurements.padding - measurements.border,\n              outer: result,\n              outerfull: result + measurements.padding + measurements.border + measurements.margin\n            }[measure];\n          }\n        };\n        return angular.forEach({\n          before: function(newElem) {\n            var children, elem, i, parent, self, _i, _ref;\n            self = this;\n            elem = self[0];\n            parent = self.parent();\n            children = parent.contents();\n            if (children[0] === elem) {\n              return parent.prepend(newElem);\n            } else {\n              for (i = _i = 1, _ref = children.length - 1; 1 <= _ref ? _i <= _ref : _i >= _ref; i = 1 <= _ref ? ++_i : --_i) {\n                if (children[i] === elem) {\n                  angular.element(children[i - 1]).after(newElem);\n                  return;\n                }\n              }\n              throw new Error('invalid DOM structure ' + elem.outerHTML);\n            }\n          },\n          height: function(value) {\n            var self;\n            self = this;\n            if (angular.isDefined(value)) {\n              if (angular.isNumber(value)) {\n                value = value + 'px';\n              }\n              return css.call(self, 'height', value);\n            } else {\n              return getWidthHeight(this[0], 'height', 'base');\n            }\n          },\n          outerHeight: function(option) {\n            return getWidthHeight(this[0], 'height', option ? 'outerfull' : 'outer');\n          },\n          /*\n          UIScroller no longer relies on jQuery method offset. The jQLite implementation of the method\n          is kept here just for the reference. Also the offset setter method was never implemented\n          */\n\n          offset: function(value) {\n            var box, doc, docElem, elem, self, win;\n            self = this;\n            if (arguments.length) {\n              if (value === void 0) {\n                return self;\n              } else {\n                throw new Error('offset setter method is not implemented');\n              }\n            }\n            box = {\n              top: 0,\n              left: 0\n            };\n            elem = self[0];\n            doc = elem && elem.ownerDocument;\n            if (!doc) {\n              return;\n            }\n            docElem = doc.documentElement;\n            if (elem.getBoundingClientRect != null) {\n              box = elem.getBoundingClientRect();\n            }\n            win = doc.defaultView || doc.parentWindow;\n            return {\n              top: box.top + (win.pageYOffset || docElem.scrollTop) - (docElem.clientTop || 0),\n              left: box.left + (win.pageXOffset || docElem.scrollLeft) - (docElem.clientLeft || 0)\n            };\n          },\n          scrollTop: function(value) {\n            return scrollTo(this, 'top', value);\n          },\n          scrollLeft: function(value) {\n            return scrollTo(this, 'left', value);\n          }\n        }, function(value, key) {\n          if (!element.prototype[key]) {\n            return element.prototype[key] = value;\n          }\n        });\n      }\n    };\n  }\n]).run([\n  '$log', '$window', 'jqLiteExtras', function(console, window, jqLiteExtras) {\n    'use strict';\n\n    if (!window.jQuery) {\n      return jqLiteExtras.registerFor(angular.element);\n    }\n  }\n]);\n\n/*\n//# sourceURL=src/scripts/ui-scroll-jqlite.js\n*/\n\n\n/*\nglobals: angular, window\n\n\tList of used element methods available in JQuery but not in JQuery Lite\n\n\t\telement.before(elem)\n\t\telement.height()\n\t\telement.outerHeight(true)\n\t\telement.height(value) = only for Top/Bottom padding elements\n\t\telement.scrollTop()\n\t\telement.scrollTop(value)\n*/\n\nangular.module('ui.scroll', []).directive('uiScrollViewport', [\n  '$log', function() {\n    'use strict';\n\n    return {\n      controller: [\n        '$scope', '$element', function(scope, element) {\n          this.viewport = element;\n          return this;\n        }\n      ]\n    };\n  }\n]).directive('uiScroll', [\n  '$log', '$injector', '$rootScope', '$timeout', function(console, $injector, $rootScope, $timeout) {\n    'use strict';\n\n    return {\n      require: ['?^uiScrollViewport'],\n      transclude: 'element',\n      priority: 1000,\n      terminal: true,\n      compile: function(elementTemplate, attr, linker) {\n        return function($scope, element, $attr, controllers) {\n          var adapter, adjustBuffer, adjustRowHeight, bof, bottomVisiblePos, buffer, bufferPadding, bufferSize, clipBottom, clipTop, datasource, datasourceName, doAdjustment, enqueueFetch, eof, eventListener, fetch, finalize, first, getValueChain, hideElementBeforeAppend, insert, isDatasource, isLoading, itemName, loading, log, match, next, pending, reload, removeFromBuffer, resizeHandler, ridActual, scrollHandler, scrollHeight, shouldLoadBottom, shouldLoadTop, showElementAfterRender, tempScope, topVisible, topVisibleElement, topVisibleItem, topVisiblePos, topVisibleScope, viewport, viewportScope, wheelHandler;\n          log = console.debug || console.log;\n          match = $attr.uiScroll.match(/^\\s*(\\w+)\\s+in\\s+([\\w\\.]+)\\s*$/);\n          if (!match) {\n            throw new Error('Expected uiScroll in form of \\'_item_ in _datasource_\\' but got \\'' + $attr.uiScroll + '\\'');\n          }\n          itemName = match[1];\n          datasourceName = match[2];\n          isDatasource = function(datasource) {\n            return angular.isObject(datasource) && datasource.get && angular.isFunction(datasource.get);\n          };\n          getValueChain = function(targetScope, target) {\n            var chain;\n            if (!targetScope) {\n              return null;\n            }\n            chain = target.match(/^([\\w]+)\\.(.+)$/);\n            if (!chain || chain.length !== 3) {\n              return targetScope[target];\n            }\n            return getValueChain(targetScope[chain[1]], chain[2]);\n          };\n          datasource = getValueChain($scope, datasourceName);\n          if (!isDatasource(datasource)) {\n            datasource = $injector.get(datasourceName);\n            if (!isDatasource(datasource)) {\n              throw new Error('' + datasourceName + ' is not a valid datasource');\n            }\n          }\n          bufferSize = Math.max(3, +$attr.bufferSize || 10);\n          bufferPadding = function() {\n            return viewport.outerHeight() * Math.max(0.1, +$attr.padding || 0.1);\n          };\n          scrollHeight = function(elem) {\n            var _ref;\n            return (_ref = elem[0].scrollHeight) != null ? _ref : elem[0].document.documentElement.scrollHeight;\n          };\n          adapter = null;\n          linker(tempScope = $scope.$new(), function(template) {\n            var bottomPadding, createPadding, padding, repeaterType, topPadding, viewport;\n            repeaterType = template[0].localName;\n            if (repeaterType === 'dl') {\n              throw new Error('ui-scroll directive does not support <' + template[0].localName + '> as a repeating tag: ' + template[0].outerHTML);\n            }\n            if (repeaterType !== 'li' && repeaterType !== 'tr') {\n              repeaterType = 'div';\n            }\n            viewport = controllers[0] && controllers[0].viewport ? controllers[0].viewport : angular.element(window);\n            viewport.css({\n              'overflow-y': 'auto',\n              'display': 'block'\n            });\n            padding = function(repeaterType) {\n              var div, result, table;\n              switch (repeaterType) {\n                case 'tr':\n                  table = angular.element('<table><tr><td><div></div></td></tr></table>');\n                  div = table.find('div');\n                  result = table.find('tr');\n                  result.paddingHeight = function() {\n                    return div.height.apply(div, arguments);\n                  };\n                  return result;\n                default:\n                  result = angular.element('<' + repeaterType + '></' + repeaterType + '>');\n                  result.paddingHeight = result.height;\n                  return result;\n              }\n            };\n            createPadding = function(padding, element, direction) {\n              element[{\n                top: 'before',\n                bottom: 'after'\n              }[direction]](padding);\n              return {\n                paddingHeight: function() {\n                  return padding.paddingHeight.apply(padding, arguments);\n                },\n                insert: function(element) {\n                  return padding[{\n                    top: 'after',\n                    bottom: 'before'\n                  }[direction]](element);\n                }\n              };\n            };\n            topPadding = createPadding(padding(repeaterType), element, 'top');\n            bottomPadding = createPadding(padding(repeaterType), element, 'bottom');\n            tempScope.$destroy();\n            return adapter = {\n              viewport: viewport,\n              topPadding: topPadding.paddingHeight,\n              bottomPadding: bottomPadding.paddingHeight,\n              append: bottomPadding.insert,\n              prepend: topPadding.insert,\n              bottomDataPos: function() {\n                return scrollHeight(viewport) - bottomPadding.paddingHeight();\n              },\n              topDataPos: function() {\n                return topPadding.paddingHeight();\n              }\n            };\n          });\n          viewport = adapter.viewport;\n          viewportScope = viewport.scope() || $rootScope;\n          if (angular.isDefined($attr.topVisible)) {\n            topVisibleItem = function(item) {\n              return viewportScope[$attr.topVisible] = item;\n            };\n          }\n          if (angular.isDefined($attr.topVisibleElement)) {\n            topVisibleElement = function(element) {\n              return viewportScope[$attr.topVisibleElement] = element;\n            };\n          }\n          if (angular.isDefined($attr.topVisibleScope)) {\n            topVisibleScope = function(scope) {\n              return viewportScope[$attr.topVisibleScope] = scope;\n            };\n          }\n          topVisible = function(item) {\n            if (topVisibleItem) {\n              topVisibleItem(item.scope[itemName]);\n            }\n            if (topVisibleElement) {\n              topVisibleElement(item.element);\n            }\n            if (topVisibleScope) {\n              topVisibleScope(item.scope);\n            }\n            if (datasource.topVisible) {\n              return datasource.topVisible(item);\n            }\n          };\n          if (angular.isDefined($attr.isLoading)) {\n            loading = function(value) {\n              viewportScope[$attr.isLoading] = value;\n              if (datasource.loading) {\n                return datasource.loading(value);\n              }\n            };\n          } else {\n            loading = function(value) {\n              if (datasource.loading) {\n                return datasource.loading(value);\n              }\n            };\n          }\n          ridActual = 0;\n          first = 1;\n          next = 1;\n          buffer = [];\n          pending = [];\n          eof = false;\n          bof = false;\n          isLoading = false;\n          removeFromBuffer = function(start, stop) {\n            var i, _i;\n            for (i = _i = start; start <= stop ? _i < stop : _i > stop; i = start <= stop ? ++_i : --_i) {\n              buffer[i].scope.$destroy();\n              buffer[i].element.remove();\n            }\n            return buffer.splice(start, stop - start);\n          };\n          reload = function() {\n            ridActual++;\n            first = 1;\n            next = 1;\n            removeFromBuffer(0, buffer.length);\n            adapter.topPadding(0);\n            adapter.bottomPadding(0);\n            pending = [];\n            eof = false;\n            bof = false;\n            return adjustBuffer(ridActual, false);\n          };\n          bottomVisiblePos = function() {\n            return viewport.scrollTop() + viewport.outerHeight();\n          };\n          topVisiblePos = function() {\n            return viewport.scrollTop();\n          };\n          shouldLoadBottom = function() {\n            return !eof && adapter.bottomDataPos() < bottomVisiblePos() + bufferPadding();\n          };\n          clipBottom = function() {\n            var bottomHeight, i, item, itemHeight, itemTop, newRow, overage, rowTop, _i, _ref;\n            bottomHeight = 0;\n            overage = 0;\n            for (i = _i = _ref = buffer.length - 1; _ref <= 0 ? _i <= 0 : _i >= 0; i = _ref <= 0 ? ++_i : --_i) {\n              item = buffer[i];\n              itemTop = item.element.offset().top;\n              newRow = rowTop !== itemTop;\n              rowTop = itemTop;\n              if (newRow) {\n                itemHeight = item.element.outerHeight(true);\n              }\n              if (adapter.bottomDataPos() - bottomHeight - itemHeight > bottomVisiblePos() + bufferPadding()) {\n                if (newRow) {\n                  bottomHeight += itemHeight;\n                }\n                overage++;\n                eof = false;\n              } else {\n                if (newRow) {\n                  break;\n                }\n                overage++;\n              }\n            }\n            if (overage > 0) {\n              adapter.bottomPadding(adapter.bottomPadding() + bottomHeight);\n              removeFromBuffer(buffer.length - overage, buffer.length);\n              next -= overage;\n              return log('clipped off bottom ' + overage + ' bottom padding ' + (adapter.bottomPadding()));\n            }\n          };\n          shouldLoadTop = function() {\n            return !bof && (adapter.topDataPos() > topVisiblePos() - bufferPadding());\n          };\n          clipTop = function() {\n            var item, itemHeight, itemTop, newRow, overage, rowTop, topHeight, _i, _len;\n            topHeight = 0;\n            overage = 0;\n            for (_i = 0, _len = buffer.length; _i < _len; _i++) {\n              item = buffer[_i];\n              itemTop = item.element.offset().top;\n              newRow = rowTop !== itemTop;\n              rowTop = itemTop;\n              if (newRow) {\n                itemHeight = item.element.outerHeight(true);\n              }\n              if (adapter.topDataPos() + topHeight + itemHeight < topVisiblePos() - bufferPadding()) {\n                if (newRow) {\n                  topHeight += itemHeight;\n                }\n                overage++;\n                bof = false;\n              } else {\n                if (newRow) {\n                  break;\n                }\n                overage++;\n              }\n            }\n            if (overage > 0) {\n              adapter.topPadding(adapter.topPadding() + topHeight);\n              removeFromBuffer(0, overage);\n              first += overage;\n              return log('clipped off top ' + overage + ' top padding ' + (adapter.topPadding()));\n            }\n          };\n          enqueueFetch = function(rid, direction, scrolling) {\n            if (!isLoading) {\n              isLoading = true;\n              loading(true);\n            }\n            if (pending.push(direction) === 1) {\n              return fetch(rid, scrolling);\n            }\n          };\n          hideElementBeforeAppend = function(element) {\n            element.displayTemp = element.css('display');\n            return element.css('display', 'none');\n          };\n          showElementAfterRender = function(element) {\n            if (element.hasOwnProperty('displayTemp')) {\n              return element.css('display', element.displayTemp);\n            }\n          };\n          insert = function(index, item) {\n            var itemScope, toBeAppended, wrapper;\n            itemScope = $scope.$new();\n            itemScope[itemName] = item;\n            toBeAppended = index > first;\n            itemScope.$index = index;\n            if (toBeAppended) {\n              itemScope.$index--;\n            }\n            wrapper = {\n              scope: itemScope\n            };\n            linker(itemScope, function(clone) {\n              wrapper.element = clone;\n              if (toBeAppended) {\n                if (index === next) {\n                  hideElementBeforeAppend(clone);\n                  adapter.append(clone);\n                  return buffer.push(wrapper);\n                } else {\n                  buffer[index - first].element.after(clone);\n                  return buffer.splice(index - first + 1, 0, wrapper);\n                }\n              } else {\n                hideElementBeforeAppend(clone);\n                adapter.prepend(clone);\n                return buffer.unshift(wrapper);\n              }\n            });\n            return {\n              appended: toBeAppended,\n              wrapper: wrapper\n            };\n          };\n          adjustRowHeight = function(appended, wrapper) {\n            var newHeight;\n            if (appended) {\n              return adapter.bottomPadding(Math.max(0, adapter.bottomPadding() - wrapper.element.outerHeight(true)));\n            } else {\n              newHeight = adapter.topPadding() - wrapper.element.outerHeight(true);\n              if (newHeight >= 0) {\n                return adapter.topPadding(newHeight);\n              } else {\n                return viewport.scrollTop(viewport.scrollTop() + wrapper.element.outerHeight(true));\n              }\n            }\n          };\n          doAdjustment = function(rid, scrolling, finalize) {\n            var item, itemHeight, itemTop, newRow, rowTop, topHeight, _i, _len, _results;\n            log('top {actual=' + (adapter.topDataPos()) + ' visible from=' + (topVisiblePos()) + ' bottom {visible through=' + (bottomVisiblePos()) + ' actual=' + (adapter.bottomDataPos()) + '}');\n            if (shouldLoadBottom()) {\n              enqueueFetch(rid, true, scrolling);\n            } else {\n              if (shouldLoadTop()) {\n                enqueueFetch(rid, false, scrolling);\n              }\n            }\n            if (finalize) {\n              finalize(rid);\n            }\n            if (pending.length === 0) {\n              topHeight = 0;\n              _results = [];\n              for (_i = 0, _len = buffer.length; _i < _len; _i++) {\n                item = buffer[_i];\n                itemTop = item.element.offset().top;\n                newRow = rowTop !== itemTop;\n                rowTop = itemTop;\n                if (newRow) {\n                  itemHeight = item.element.outerHeight(true);\n                }\n                if (newRow && (adapter.topDataPos() + topHeight + itemHeight < topVisiblePos())) {\n                  _results.push(topHeight += itemHeight);\n                } else {\n                  if (newRow) {\n                    topVisible(item);\n                  }\n                  break;\n                }\n              }\n              return _results;\n            }\n          };\n          adjustBuffer = function(rid, scrolling, newItems, finalize) {\n            if (newItems && newItems.length) {\n              return $timeout(function() {\n                var itemTop, row, rowTop, rows, _i, _j, _len, _len1;\n                rows = [];\n                for (_i = 0, _len = newItems.length; _i < _len; _i++) {\n                  row = newItems[_i];\n                  element = row.wrapper.element;\n                  showElementAfterRender(element);\n                  itemTop = element.offset().top;\n                  if (rowTop !== itemTop) {\n                    rows.push(row);\n                    rowTop = itemTop;\n                  }\n                }\n                for (_j = 0, _len1 = rows.length; _j < _len1; _j++) {\n                  row = rows[_j];\n                  adjustRowHeight(row.appended, row.wrapper);\n                }\n                return doAdjustment(rid, scrolling, finalize);\n              });\n            } else {\n              return doAdjustment(rid, scrolling, finalize);\n            }\n          };\n          finalize = function(rid, scrolling, newItems) {\n            return adjustBuffer(rid, scrolling, newItems, function() {\n              pending.shift();\n              if (pending.length === 0) {\n                isLoading = false;\n                return loading(false);\n              } else {\n                return fetch(rid, scrolling);\n              }\n            });\n          };\n          fetch = function(rid, scrolling) {\n            var direction;\n            direction = pending[0];\n            if (direction) {\n              if (buffer.length && !shouldLoadBottom()) {\n                return finalize(rid, scrolling);\n              } else {\n                return datasource.get(next, bufferSize, function(result) {\n                  var item, newItems, _i, _len;\n                  if (rid && rid !== ridActual) {\n                    return;\n                  }\n                  newItems = [];\n                  if (result.length < bufferSize) {\n                    eof = true;\n                    adapter.bottomPadding(0);\n                  }\n                  if (result.length > 0) {\n                    clipTop();\n                    for (_i = 0, _len = result.length; _i < _len; _i++) {\n                      item = result[_i];\n                      newItems.push(insert(++next, item));\n                    }\n                  }\n                  return finalize(rid, scrolling, newItems);\n                });\n              }\n            } else {\n              if (buffer.length && !shouldLoadTop()) {\n                return finalize(rid, scrolling);\n              } else {\n                return datasource.get(first - bufferSize, bufferSize, function(result) {\n                  var i, newItems, _i, _ref;\n                  if (rid && rid !== ridActual) {\n                    return;\n                  }\n                  newItems = [];\n                  if (result.length < bufferSize) {\n                    bof = true;\n                    adapter.topPadding(0);\n                  }\n                  if (result.length > 0) {\n                    if (buffer.length) {\n                      clipBottom();\n                    }\n                    for (i = _i = _ref = result.length - 1; _ref <= 0 ? _i <= 0 : _i >= 0; i = _ref <= 0 ? ++_i : --_i) {\n                      newItems.unshift(insert(--first, result[i]));\n                    }\n                  }\n                  return finalize(rid, scrolling, newItems);\n                });\n              }\n            }\n          };\n          resizeHandler = function() {\n            if (!$rootScope.$$phase && !isLoading) {\n              adjustBuffer(null, false);\n              return $scope.$apply();\n            }\n          };\n          viewport.bind('resize', resizeHandler);\n          scrollHandler = function() {\n            if (!$rootScope.$$phase && !isLoading) {\n              adjustBuffer(null, true);\n              return $scope.$apply();\n            }\n          };\n          viewport.bind('scroll', scrollHandler);\n          wheelHandler = function(event) {\n            var scrollTop, yMax;\n            scrollTop = viewport[0].scrollTop;\n            yMax = viewport[0].scrollHeight - viewport[0].clientHeight;\n            if ((scrollTop === 0 && !bof) || (scrollTop === yMax && !eof)) {\n              return event.preventDefault();\n            }\n          };\n          viewport.bind('mousewheel', wheelHandler);\n          $scope.$watch(datasource.revision, function() {\n            return reload();\n          });\n          if (datasource.scope) {\n            eventListener = datasource.scope.$new();\n          } else {\n            eventListener = $scope.$new();\n          }\n          $scope.$on('$destroy', function() {\n            eventListener.$destroy();\n            viewport.unbind('resize', resizeHandler);\n            viewport.unbind('scroll', scrollHandler);\n            return viewport.unbind('mousewheel', wheelHandler);\n          });\n          eventListener.$on('update.items', function(event, locator, newItem) {\n            var wrapper, _fn, _i, _len, _ref;\n            if (angular.isFunction(locator)) {\n              _fn = function(wrapper) {\n                return locator(wrapper.scope);\n              };\n              for (_i = 0, _len = buffer.length; _i < _len; _i++) {\n                wrapper = buffer[_i];\n                _fn(wrapper);\n              }\n            } else {\n              if ((0 <= (_ref = locator - first - 1) && _ref < buffer.length)) {\n                buffer[locator - first - 1].scope[itemName] = newItem;\n              }\n            }\n            return null;\n          });\n          eventListener.$on('delete.items', function(event, locator) {\n            var i, item, temp, wrapper, _fn, _i, _j, _k, _len, _len1, _len2, _ref;\n            if (angular.isFunction(locator)) {\n              temp = [];\n              for (_i = 0, _len = buffer.length; _i < _len; _i++) {\n                item = buffer[_i];\n                temp.unshift(item);\n              }\n              _fn = function(wrapper) {\n                if (locator(wrapper.scope)) {\n                  removeFromBuffer(temp.length - 1 - i, temp.length - i);\n                  return next--;\n                }\n              };\n              for (i = _j = 0, _len1 = temp.length; _j < _len1; i = ++_j) {\n                wrapper = temp[i];\n                _fn(wrapper);\n              }\n            } else {\n              if ((0 <= (_ref = locator - first - 1) && _ref < buffer.length)) {\n                removeFromBuffer(locator - first - 1, locator - first);\n                next--;\n              }\n            }\n            for (i = _k = 0, _len2 = buffer.length; _k < _len2; i = ++_k) {\n              item = buffer[i];\n              item.scope.$index = first + i;\n            }\n            return adjustBuffer(null, false);\n          });\n          return eventListener.$on('insert.item', function(event, locator, item) {\n            var i, inserted, _i, _len, _ref;\n            inserted = [];\n            if (angular.isFunction(locator)) {\n              throw new Error('not implemented - Insert with locator function');\n            } else {\n              if ((0 <= (_ref = locator - first - 1) && _ref < buffer.length)) {\n                inserted.push(insert(locator, item));\n                next++;\n              }\n            }\n            for (i = _i = 0, _len = buffer.length; _i < _len; i = ++_i) {\n              item = buffer[i];\n              item.scope.$index = first + i;\n            }\n            return adjustBuffer(null, false, inserted);\n          });\n        };\n      }\n    };\n  }\n]);\n\n/*\n//# sourceURL=src/scripts/ui-scroll.js\n*/\n\n\n/**\n * Adds a 'ui-scrollfix' class to the element when the page scrolls past it's position.\n * @param [offset] {int} optional Y-offset to override the detected offset.\n *   Takes 300 (absolute) or -300 or +300 (relative to detected)\n */\nangular.module('ui.scrollfix',[]).directive('uiScrollfix', ['$window', function ($window) {\n  'use strict';\n\n  function getWindowScrollTop() {\n    if (angular.isDefined($window.pageYOffset)) {\n      return $window.pageYOffset;\n    } else {\n      var iebody = (document.compatMode && document.compatMode !== 'BackCompat') ? document.documentElement : document.body;\n      return iebody.scrollTop;\n    }\n  }\n  return {\n    require: '^?uiScrollfixTarget',\n    link: function (scope, elm, attrs, uiScrollfixTarget) {\n      var top = elm[0].offsetTop,\n          $target = uiScrollfixTarget && uiScrollfixTarget.$element || angular.element($window);\n\n      if (!attrs.uiScrollfix) {\n        attrs.uiScrollfix = top;\n      } else if (typeof(attrs.uiScrollfix) === 'string') {\n        // charAt is generally faster than indexOf: http://jsperf.com/indexof-vs-charat\n        if (attrs.uiScrollfix.charAt(0) === '-') {\n          attrs.uiScrollfix = top - parseFloat(attrs.uiScrollfix.substr(1));\n        } else if (attrs.uiScrollfix.charAt(0) === '+') {\n          attrs.uiScrollfix = top + parseFloat(attrs.uiScrollfix.substr(1));\n        }\n      }\n\n      function onScroll() {\n        // if pageYOffset is defined use it, otherwise use other crap for IE\n        var offset = uiScrollfixTarget ? $target[0].scrollTop : getWindowScrollTop();\n        if (!elm.hasClass('ui-scrollfix') && offset > attrs.uiScrollfix) {\n          elm.addClass('ui-scrollfix');\n        } else if (elm.hasClass('ui-scrollfix') && offset < attrs.uiScrollfix) {\n          elm.removeClass('ui-scrollfix');\n        }\n      }\n\n      $target.on('scroll', onScroll);\n\n      // Unbind scroll event handler when directive is removed\n      scope.$on('$destroy', function() {\n        $target.off('scroll', onScroll);\n      });\n    }\n  };\n}]).directive('uiScrollfixTarget', [function () {\n  'use strict';\n  return {\n    controller: ['$element', function($element) {\n      this.$element = $element;\n    }]\n  };\n}]);\n\n/**\n * uiShow Directive\n *\n * Adds a 'ui-show' class to the element instead of display:block\n * Created to allow tighter control  of CSS without bulkier directives\n *\n * @param expression {boolean} evaluated expression to determine if the class should be added\n */\nangular.module('ui.showhide',[])\n.directive('uiShow', [function () {\n  'use strict';\n\n  return function (scope, elm, attrs) {\n    scope.$watch(attrs.uiShow, function (newVal) {\n      if (newVal) {\n        elm.addClass('ui-show');\n      } else {\n        elm.removeClass('ui-show');\n      }\n    });\n  };\n}])\n\n/**\n * uiHide Directive\n *\n * Adds a 'ui-hide' class to the element instead of display:block\n * Created to allow tighter control  of CSS without bulkier directives\n *\n * @param expression {boolean} evaluated expression to determine if the class should be added\n */\n.directive('uiHide', [function () {\n  'use strict';\n\n  return function (scope, elm, attrs) {\n    scope.$watch(attrs.uiHide, function (newVal) {\n      if (newVal) {\n        elm.addClass('ui-hide');\n      } else {\n        elm.removeClass('ui-hide');\n      }\n    });\n  };\n}])\n\n/**\n * uiToggle Directive\n *\n * Adds a class 'ui-show' if true, and a 'ui-hide' if false to the element instead of display:block/display:none\n * Created to allow tighter control  of CSS without bulkier directives. This also allows you to override the\n * default visibility of the element using either class.\n *\n * @param expression {boolean} evaluated expression to determine if the class should be added\n */\n.directive('uiToggle', [function () {\n  'use strict';\n\n  return function (scope, elm, attrs) {\n    scope.$watch(attrs.uiToggle, function (newVal) {\n      if (newVal) {\n        elm.removeClass('ui-hide').addClass('ui-show');\n      } else {\n        elm.removeClass('ui-show').addClass('ui-hide');\n      }\n    });\n  };\n}]);\n\n/**\n * Filters out all duplicate items from an array by checking the specified key\n * @param [key] {string} the name of the attribute of each object to compare for uniqueness\n if the key is empty, the entire object will be compared\n if the key === false then no filtering will be performed\n * @return {array}\n */\nangular.module('ui.unique',[]).filter('unique', ['$parse', function ($parse) {\n  'use strict';\n\n  return function (items, filterOn) {\n\n    if (filterOn === false) {\n      return items;\n    }\n\n    if ((filterOn || angular.isUndefined(filterOn)) && angular.isArray(items)) {\n      var newItems = [],\n        get = angular.isString(filterOn) ? $parse(filterOn) : function (item) { return item; };\n\n      var extractValueToCompare = function (item) {\n        return angular.isObject(item) ? get(item) : item;\n      };\n\n      angular.forEach(items, function (item) {\n        var isDuplicate = false;\n\n        for (var i = 0; i < newItems.length; i++) {\n          if (angular.equals(extractValueToCompare(newItems[i]), extractValueToCompare(item))) {\n            isDuplicate = true;\n            break;\n          }\n        }\n        if (!isDuplicate) {\n          newItems.push(item);\n        }\n\n      });\n      items = newItems;\n    }\n    return items;\n  };\n}]);\n\n/*\n * Author: Remy Alain Ticona Carbajal http://realtica.org\n * Description: The main objective of ng-uploader is to have a user control,\n * clean, simple, customizable, and above all very easy to implement.\n * Licence: MIT\n */\n\nangular.module('ui.uploader', []).service('uiUploader', uiUploader);\n\nuiUploader.$inject = ['$log'];\n\nfunction uiUploader($log) {\n    'use strict';\n\n    /*jshint validthis: true */\n    var self = this;\n    self.files = [];\n    self.options = {};\n    self.activeUploads = 0;\n    $log.info('uiUploader loaded');\n    \n    function addFiles(files) {\n        for (var i = 0; i < files.length; i++) {\n            self.files.push(files[i]);\n        }\n    }\n\n    function getFiles() {\n        return self.files;\n    }\n\n    function startUpload(options) {\n        self.options = options;\n        for (var i = 0; i < self.files.length; i++) {\n            if (self.activeUploads == self.options.concurrency) {\n                break;\n            }\n            if (self.files[i].active)\n                continue;\n            ajaxUpload(self.files[i], self.options.url);\n        }\n    }\n    \n    function removeFile(file){\n        self.files.splice(self.files.indexOf(file),1);\n    }\n    \n    function removeAll(){\n        self.files.splice(0,self.files.length);\n    }\n    \n    return {\n        addFiles: addFiles,\n        getFiles: getFiles,\n        files: self.files,\n        startUpload: startUpload,\n        removeFile: removeFile,\n        removeAll:removeAll\n    };\n    \n    function getHumanSize(bytes) {\n        var sizes = ['n/a', 'bytes', 'KiB', 'MiB', 'GiB', 'TB', 'PB', 'EiB', 'ZiB', 'YiB'];\n        var i = +Math.floor(Math.log(bytes) / Math.log(1024));\n        return (bytes / Math.pow(1024, i)).toFixed(i ? 1 : 0) + ' ' + sizes[isNaN(bytes) ? 0 : i + 1];\n    }\n\n    function ajaxUpload(file, url) {\n        var xhr, formData, prop, data = '',\n            key = '' || 'file';\n        self.activeUploads += 1;\n        file.active = true;\n        xhr = new window.XMLHttpRequest();\n        formData = new window.FormData();\n        xhr.open('POST', url);\n\n        // Triggered when upload starts:\n        xhr.upload.onloadstart = function() {};\n\n        // Triggered many times during upload:\n        xhr.upload.onprogress = function(event) {\n            if (!event.lengthComputable) {\n                return;\n            }\n            // Update file size because it might be bigger than reported by\n            // the fileSize:\n            //$log.info(\"progres..\");\n            //console.info(event.loaded);\n            file.loaded = event.loaded;\n            file.humanSize = getHumanSize(event.loaded);\n            self.options.onProgress(file);\n        };\n\n        // Triggered when upload is completed:\n        xhr.onload = function() {\n            self.activeUploads -= 1;\n            startUpload(self.options);\n            self.options.onCompleted(file);\n        };\n\n        // Triggered when upload fails:\n        xhr.onerror = function() {};\n\n        // Append additional data if provided:\n        if (data) {\n            for (prop in data) {\n                if (data.hasOwnProperty(prop)) {\n                    formData.append(prop, data[prop]);\n                }\n            }\n        }\n\n        // Append file data:\n        formData.append(key, file, file.name);\n\n        // Initiate upload:\n        xhr.send(formData);\n\n        return xhr;\n    }\n\n}\n\n/**\n * General-purpose validator for ngModel.\n * angular.js comes with several built-in validation mechanism for input fields (ngRequired, ngPattern etc.) but using\n * an arbitrary validation function requires creation of a custom formatters and / or parsers.\n * The ui-validate directive makes it easy to use any function(s) defined in scope as a validator function(s).\n * A validator function will trigger validation on both model and input changes.\n *\n * @example <input ui-validate=\" 'myValidatorFunction($value)' \">\n * @example <input ui-validate=\"{ foo : '$value > anotherModel', bar : 'validateFoo($value)' }\">\n * @example <input ui-validate=\"{ foo : '$value > anotherModel' }\" ui-validate-watch=\" 'anotherModel' \">\n * @example <input ui-validate=\"{ foo : '$value > anotherModel', bar : 'validateFoo($value)' }\" ui-validate-watch=\" { foo : 'anotherModel' } \">\n *\n * @param ui-validate {string|object literal} If strings is passed it should be a scope's function to be used as a validator.\n * If an object literal is passed a key denotes a validation error key while a value should be a validator function.\n * In both cases validator function should take a value to validate as its argument and should return true/false indicating a validation result.\n */\nangular.module('ui.validate',[]).directive('uiValidate', function () {\n  'use strict';\n\n  return {\n    restrict: 'A',\n    require: 'ngModel',\n    link: function (scope, elm, attrs, ctrl) {\n      var validateFn, validators = {},\n          validateExpr = scope.$eval(attrs.uiValidate);\n\n      if (!validateExpr){ return;}\n\n      if (angular.isString(validateExpr)) {\n        validateExpr = { validator: validateExpr };\n      }\n\n      angular.forEach(validateExpr, function (exprssn, key) {\n        validateFn = function (valueToValidate) {\n          var expression = scope.$eval(exprssn, { '$value' : valueToValidate });\n          if (angular.isObject(expression) && angular.isFunction(expression.then)) {\n            // expression is a promise\n            expression.then(function(){\n              ctrl.$setValidity(key, true);\n            }, function(){\n              ctrl.$setValidity(key, false);\n            });\n            return valueToValidate;\n          } else if (expression) {\n            // expression is true\n            ctrl.$setValidity(key, true);\n            return valueToValidate;\n          } else {\n            // expression is false\n            ctrl.$setValidity(key, false);\n            return valueToValidate;\n          }\n        };\n        validators[key] = validateFn;\n        ctrl.$formatters.push(validateFn);\n        ctrl.$parsers.push(validateFn);\n      });\n\n      function apply_watch(watch)\n      {\n          //string - update all validators on expression change\n          if (angular.isString(watch))\n          {\n              scope.$watch(watch, function(){\n                  angular.forEach(validators, function(validatorFn){\n                      validatorFn(ctrl.$modelValue);\n                  });\n              });\n              return;\n          }\n\n          //array - update all validators on change of any expression\n          if (angular.isArray(watch))\n          {\n              angular.forEach(watch, function(expression){\n                  scope.$watch(expression, function()\n                  {\n                      angular.forEach(validators, function(validatorFn){\n                          validatorFn(ctrl.$modelValue);\n                      });\n                  });\n              });\n              return;\n          }\n\n          //object - update appropriate validator\n          if (angular.isObject(watch))\n          {\n              angular.forEach(watch, function(expression, validatorKey)\n              {\n                  //value is string - look after one expression\n                  if (angular.isString(expression))\n                  {\n                      scope.$watch(expression, function(){\n                          validators[validatorKey](ctrl.$modelValue);\n                      });\n                  }\n\n                  //value is array - look after all expressions in array\n                  if (angular.isArray(expression))\n                  {\n                      angular.forEach(expression, function(intExpression)\n                      {\n                          scope.$watch(intExpression, function(){\n                              validators[validatorKey](ctrl.$modelValue);\n                          });\n                      });\n                  }\n              });\n          }\n      }\n      // Support for ui-validate-watch\n      if (attrs.uiValidateWatch){\n          apply_watch( scope.$eval(attrs.uiValidateWatch) );\n      }\n    }\n  };\n});\n\nangular.module('ui.utils',  [\n  'ui.event',\n  'ui.format',\n  'ui.highlight',\n  'ui.include',\n  'ui.indeterminate',\n  'ui.inflector',\n  'ui.jq',\n  'ui.keypress',\n  'ui.mask',\n  'ui.reset',\n  'ui.route',\n  'ui.scrollfix',\n  'ui.scroll',\n  'ui.scroll.jqlite',\n  'ui.showhide',\n  'ui.unique',\n  'ui.validate'\n]);\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/atmosphere/.bower.json",
    "content": "{\n  \"main\": \"atmosphere.js\",\n  \"version\": \"2.1.2\",\n  \"name\": \"atmosphere-js\",\n  \"homepage\": \"https://github.com/Atmosphere/bower-atmosphere\",\n  \"_release\": \"2.1.2\",\n  \"_resolution\": {\n    \"type\": \"version\",\n    \"tag\": \"v2.1.2\",\n    \"commit\": \"d8483f26c8a072ebba5449c20d46dd4bafe1ee7c\"\n  },\n  \"_source\": \"https://github.com/Atmosphere/bower-atmosphere.git\",\n  \"_target\": \"2.1.2\",\n  \"_originalSource\": \"atmosphere\"\n}"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/atmosphere/README.md",
    "content": "bower-atmosphere\n============================\n\nThis repository is for distribution on `bower`\n\n```shell\nbower install atmosphere\n```\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/atmosphere/atmosphere.js",
    "content": "/**\n * Copyright 2013 Jeanfrancois Arcand\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 * Highly inspired by Portal v1.0\n * http://github.com/flowersinthesand/portal\n *\n * Copyright 2011-2013, Donghwan Kim\n * Licensed under the Apache License, Version 2.0\n * http://www.apache.org/licenses/LICENSE-2.0\n */\n/**\n * Official documentation of this library: https://github.com/Atmosphere/atmosphere/wiki/jQuery.atmosphere.js-API\n */\n(function () {\n\n    \"use strict\";\n\n    var version = \"2.1.2-javascript\",\n        atmosphere = {},\n        guid,\n        requests = [],\n        callbacks = [],\n        uuid = 0,\n        hasOwn = Object.prototype.hasOwnProperty;\n\n    atmosphere = {\n\n        onError: function (response) {\n        },\n        onClose: function (response) {\n        },\n        onOpen: function (response) {\n        },\n        onReopen: function (response) {\n        },\n        onMessage: function (response) {\n        },\n        onReconnect: function (request, response) {\n        },\n        onMessagePublished: function (response) {\n        },\n        onTransportFailure: function (errorMessage, _request) {\n        },\n        onLocalMessage: function (response) {\n        },\n        onFailureToReconnect: function (request, response) {\n        },\n        onClientTimeout: function(request){\n        },\n\n        AtmosphereRequest: function (options) {\n\n            /**\n             * {Object} Request parameters.\n             *\n             * @private\n             */\n            var _request = {\n                timeout: 300000,\n                method: 'GET',\n                headers: {},\n                contentType: '',\n                callback: null,\n                url: '',\n                data: '',\n                suspend: true,\n                maxRequest: -1,\n                reconnect: true,\n                maxStreamingLength: 10000000,\n                lastIndex: 0,\n                logLevel: 'info',\n                requestCount: 0,\n                fallbackMethod: 'GET',\n                fallbackTransport: 'streaming',\n                transport: 'long-polling',\n                webSocketImpl: null,\n                webSocketBinaryType: null,\n                dispatchUrl: null,\n                webSocketPathDelimiter: \"@@\",\n                enableXDR: false,\n                rewriteURL: false,\n                attachHeadersAsQueryString: true,\n                executeCallbackBeforeReconnect: false,\n                readyState: 0,\n                lastTimestamp: 0,\n                withCredentials: false,\n                trackMessageLength: false,\n                messageDelimiter: '|',\n                connectTimeout: -1,\n                reconnectInterval: 0,\n                dropHeaders: true,\n                uuid: 0,\n                async: true,\n                shared: false,\n                readResponsesHeaders: false,\n                maxReconnectOnClose: 5,\n                enableProtocol: true,\n                onError: function (response) {\n                },\n                onClose: function (response) {\n                },\n                onOpen: function (response) {\n                },\n                onMessage: function (response) {\n                },\n                onReopen: function (request, response) {\n                },\n                onReconnect: function (request, response) {\n                },\n                onMessagePublished: function (response) {\n                },\n                onTransportFailure: function (reason, request) {\n                },\n                onLocalMessage: function (request) {\n                },\n                onFailureToReconnect: function (request, response) {\n                },\n                onClientTimeout: function(request){\n                }\n            };\n\n            /**\n             * {Object} Request's last response.\n             *\n             * @private\n             */\n            var _response = {\n                status: 200,\n                reasonPhrase: \"OK\",\n                responseBody: '',\n                messages: [],\n                headers: [],\n                state: \"messageReceived\",\n                transport: \"polling\",\n                error: null,\n                request: null,\n                partialMessage: \"\",\n                errorHandled: false,\n                closedByClientTimeout: false\n            };\n\n            /**\n             * {websocket} Opened web socket.\n             *\n             * @private\n             */\n            var _websocket = null;\n\n            /**\n             * {SSE} Opened SSE.\n             *\n             * @private\n             */\n            var _sse = null;\n\n            /**\n             * {XMLHttpRequest, ActiveXObject} Opened ajax request (in case of http-streaming or long-polling)\n             *\n             * @private\n             */\n            var _activeRequest = null;\n\n            /**\n             * {Object} Object use for streaming with IE.\n             *\n             * @private\n             */\n            var _ieStream = null;\n\n            /**\n             * {Object} Object use for jsonp transport.\n             *\n             * @private\n             */\n            var _jqxhr = null;\n\n            /**\n             * {boolean} If request has been subscribed or not.\n             *\n             * @private\n             */\n            var _subscribed = true;\n\n            /**\n             * {number} Number of test reconnection.\n             *\n             * @private\n             */\n            var _requestCount = 0;\n\n            /**\n             * {boolean} If request is currently aborded.\n             *\n             * @private\n             */\n            var _abordingConnection = false;\n\n            /**\n             * A local \"channel' of communication.\n             *\n             * @private\n             */\n            var _localSocketF = null;\n\n            /**\n             * The storage used.\n             *\n             * @private\n             */\n            var _storageService;\n\n            /**\n             * Local communication\n             *\n             * @private\n             */\n            var _localStorageService = null;\n\n            /**\n             * A Unique ID\n             *\n             * @private\n             */\n            var guid = atmosphere.util.now();\n\n            /** Trace time */\n            var _traceTimer;\n\n            /** Key for connection sharing */\n            var _sharingKey;\n\n            // Automatic call to subscribe\n            _subscribe(options);\n\n            /**\n             * Initialize atmosphere request object.\n             *\n             * @private\n             */\n            function _init() {\n                _subscribed = true;\n                _abordingConnection = false;\n                _requestCount = 0;\n\n                _websocket = null;\n                _sse = null;\n                _activeRequest = null;\n                _ieStream = null;\n            }\n\n            /**\n             * Re-initialize atmosphere object.\n             *\n             * @private\n             */\n            function _reinit() {\n                _clearState();\n                _init();\n            }\n\n            /**\n             *\n             * @private\n             */\n            function _verifyStreamingLength(ajaxRequest, rq) {\n                // Wait to be sure we have the full message before closing.\n                if (_response.partialMessage === \"\" && (rq.transport === 'streaming') && (ajaxRequest.responseText.length > rq.maxStreamingLength)) {\n                    _response.messages = [];\n                    _invokeClose(true);\n                    _disconnect();\n                    _clearState();\n                    _reconnect(ajaxRequest, rq, 0);\n                }\n            }\n\n            /**\n             * Disconnect\n             *\n             * @private\n             */\n            function _disconnect() {\n                if (_request.enableProtocol && !_request.firstMessage) {\n                    var query = \"X-Atmosphere-Transport=close&X-Atmosphere-tracking-id=\" + _request.uuid;\n\n                    atmosphere.util.each(_request.headers, function (name, value) {\n                        var h = atmosphere.util.isFunction(value) ? value.call(this, _request, _request, _response) : value;\n                        if (h != null) {\n                            query += \"&\" + encodeURIComponent(name) + \"=\" + encodeURIComponent(h);\n                        }\n                    });\n\n                    var url = _request.url.replace(/([?&])_=[^&]*/, query);\n                    url = url + (url === _request.url ? (/\\?/.test(_request.url) ? \"&\" : \"?\") + query : \"\");\n\n                    var rq = {\n                        connected: false\n                    };\n                    var closeR = new atmosphere.AtmosphereRequest(rq);\n                    closeR.attachHeadersAsQueryString = false;\n                    closeR.dropHeaders = true;\n                    closeR.url = url;\n                    closeR.contentType = \"text/plain\";\n                    closeR.transport = 'polling';\n                    closeR.async = false;\n                    _pushOnClose(\"\", closeR);\n                }\n            }\n\n            /**\n             * Close request.\n             *\n             * @private\n             */\n            function _close() {\n                if (_request.reconnectId) {\n                    clearTimeout(_request.reconnectId);\n                    delete _request.reconnectId;\n                }\n                _request.reconnect = false;\n                _abordingConnection = true;\n                _response.request = _request;\n                _response.state = 'unsubscribe';\n                _response.responseBody = \"\";\n                _response.status = 408;\n                _response.partialMessage = \"\";\n                _invokeCallback();\n                _disconnect();\n                _clearState();\n            }\n\n            function _clearState() {\n                _response.partialMessage = \"\";\n                if (_request.id) {\n                    clearTimeout(_request.id);\n                }\n\n                if (_ieStream != null) {\n                    _ieStream.close();\n                    _ieStream = null;\n                }\n                if (_jqxhr != null) {\n                    _jqxhr.abort();\n                    _jqxhr = null;\n                }\n                if (_activeRequest != null) {\n                    _activeRequest.abort();\n                    _activeRequest = null;\n                }\n                if (_websocket != null) {\n                    if (_websocket.webSocketOpened) {\n                        _websocket.close();\n                    }\n                    _websocket = null;\n                }\n                if (_sse != null) {\n                    _sse.close();\n                    _sse = null;\n                }\n                _clearStorage();\n            }\n\n            function _clearStorage() {\n                // Stop sharing a connection\n                if (_storageService != null) {\n                    // Clears trace timer\n                    clearInterval(_traceTimer);\n                    // Removes the trace\n                    document.cookie = _sharingKey + \"=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/\";\n                    // The heir is the parent unless unloading\n                    _storageService.signal(\"close\", {\n                        reason: \"\",\n                        heir: !_abordingConnection ? guid : (_storageService.get(\"children\") || [])[0]\n                    });\n                    _storageService.close();\n                }\n                if (_localStorageService != null) {\n                    _localStorageService.close();\n                }\n            }\n\n            /**\n             * Subscribe request using request transport. <br>\n             * If request is currently opened, this one will be closed.\n             *\n             * @param {Object} Request parameters.\n             * @private\n             */\n            function _subscribe(options) {\n                _reinit();\n\n                _request = atmosphere.util.extend(_request, options);\n                // Allow at least 1 request\n                _request.mrequest = _request.reconnect;\n                if (!_request.reconnect) {\n                    _request.reconnect = true;\n                }\n            }\n\n            /**\n             * Check if web socket is supported (check for custom implementation provided by request object or browser implementation).\n             *\n             * @returns {boolean} True if web socket is supported, false otherwise.\n             * @private\n             */\n            function _supportWebsocket() {\n                return _request.webSocketImpl != null || window.WebSocket || window.MozWebSocket;\n            }\n\n            /**\n             * Check if server side events (SSE) is supported (check for custom implementation provided by request object or browser implementation).\n             *\n             * @returns {boolean} True if web socket is supported, false otherwise.\n             * @private\n             */\n            function _supportSSE() {\n                return window.EventSource;\n            }\n\n            /**\n             * Open request using request transport. <br>\n             * If request transport is 'websocket' but websocket can't be opened, request will automatically reconnect using fallback transport.\n             *\n             * @private\n             */\n            function _execute() {\n                // Shared across multiple tabs/windows.\n                if (_request.shared) {\n                    _localStorageService = _local(_request);\n                    if (_localStorageService != null) {\n                        if (_request.logLevel === 'debug') {\n                            atmosphere.util.debug(\"Storage service available. All communication will be local\");\n                        }\n\n                        if (_localStorageService.open(_request)) {\n                            // Local connection.\n                            return;\n                        }\n                    }\n\n                    if (_request.logLevel === 'debug') {\n                        atmosphere.util.debug(\"No Storage service available.\");\n                    }\n                    // Wasn't local or an error occurred\n                    _localStorageService = null;\n                }\n\n                // Protocol\n                _request.firstMessage = uuid == 0 ? true : false;\n                _request.isOpen = false;\n                _request.ctime = atmosphere.util.now();\n\n                // We carry any UUID set by the user or from a previous connection.\n                if (_request.uuid === 0) {\n                    _request.uuid = uuid;\n                }\n                _response.closedByClientTimeout = false;\n\n                if (_request.transport !== 'websocket' && _request.transport !== 'sse') {\n                    _executeRequest(_request);\n\n                } else if (_request.transport === 'websocket') {\n                    if (!_supportWebsocket()) {\n                        _reconnectWithFallbackTransport(\"Websocket is not supported, using request.fallbackTransport (\" + _request.fallbackTransport\n                            + \")\");\n                    } else {\n                        _executeWebSocket(false);\n                    }\n                } else if (_request.transport === 'sse') {\n                    if (!_supportSSE()) {\n                        _reconnectWithFallbackTransport(\"Server Side Events(SSE) is not supported, using request.fallbackTransport (\"\n                            + _request.fallbackTransport + \")\");\n                    } else {\n                        _executeSSE(false);\n                    }\n                }\n            }\n\n            function _local(request) {\n                var trace, connector, orphan, name = \"atmosphere-\" + request.url, connectors = {\n                    storage: function () {\n                        function onstorage(event) {\n                            if (event.key === name && event.newValue) {\n                                listener(event.newValue);\n                            }\n                        }\n\n                        if (!atmosphere.util.storage) {\n                            return;\n                        }\n\n                        var storage = window.localStorage,\n                            get = function (key) {\n                                return atmosphere.util.parseJSON(storage.getItem(name + \"-\" + key));\n                            },\n                            set = function (key, value) {\n                                storage.setItem(name + \"-\" + key, atmosphere.util.stringifyJSON(value));\n                            };\n\n                        return {\n                            init: function () {\n                                set(\"children\", get(\"children\").concat([guid]));\n                                atmosphere.util.on(window, \"storage\", onstorage);\n                                return get(\"opened\");\n                            },\n                            signal: function (type, data) {\n                                storage.setItem(name, atmosphere.util.stringifyJSON({\n                                    target: \"p\",\n                                    type: type,\n                                    data: data\n                                }));\n                            },\n                            close: function () {\n                                var children = get(\"children\");\n\n                                atmosphere.util.off(window, \"storage\", onstorage);\n                                if (children) {\n                                    if (removeFromArray(children, request.id)) {\n                                        set(\"children\", children);\n                                    }\n                                }\n                            }\n                        };\n                    },\n                    windowref: function () {\n                        var win = window.open(\"\", name.replace(/\\W/g, \"\"));\n\n                        if (!win || win.closed || !win.callbacks) {\n                            return;\n                        }\n\n                        return {\n                            init: function () {\n                                win.callbacks.push(listener);\n                                win.children.push(guid);\n                                return win.opened;\n                            },\n                            signal: function (type, data) {\n                                if (!win.closed && win.fire) {\n                                    win.fire(atmosphere.util.stringifyJSON({\n                                        target: \"p\",\n                                        type: type,\n                                        data: data\n                                    }));\n                                }\n                            },\n                            close: function () {\n                                // Removes traces only if the parent is alive\n                                if (!orphan) {\n                                    removeFromArray(win.callbacks, listener);\n                                    removeFromArray(win.children, guid);\n                                }\n                            }\n\n                        };\n                    }\n                };\n\n                function removeFromArray(array, val) {\n                    var i, length = array.length;\n\n                    for (i = 0; i < length; i++) {\n                        if (array[i] === val) {\n                            array.splice(i, 1);\n                        }\n                    }\n\n                    return length !== array.length;\n                }\n\n                // Receives open, close and message command from the parent\n                function listener(string) {\n                    var command = atmosphere.util.parseJSON(string), data = command.data;\n\n                    if (command.target === \"c\") {\n                        switch (command.type) {\n                            case \"open\":\n                                _open(\"opening\", 'local', _request);\n                                break;\n                            case \"close\":\n                                if (!orphan) {\n                                    orphan = true;\n                                    if (data.reason === \"aborted\") {\n                                        _close();\n                                    } else {\n                                        // Gives the heir some time to reconnect\n                                        if (data.heir === guid) {\n                                            _execute();\n                                        } else {\n                                            setTimeout(function () {\n                                                _execute();\n                                            }, 100);\n                                        }\n                                    }\n                                }\n                                break;\n                            case \"message\":\n                                _prepareCallback(data, \"messageReceived\", 200, request.transport);\n                                break;\n                            case \"localMessage\":\n                                _localMessage(data);\n                                break;\n                        }\n                    }\n                }\n\n                function findTrace() {\n                    var matcher = new RegExp(\"(?:^|; )(\" + encodeURIComponent(name) + \")=([^;]*)\").exec(document.cookie);\n                    if (matcher) {\n                        return atmosphere.util.parseJSON(decodeURIComponent(matcher[2]));\n                    }\n                }\n\n                // Finds and validates the parent socket's trace from the cookie\n                trace = findTrace();\n                if (!trace || atmosphere.util.now() - trace.ts > 1000) {\n                    return;\n                }\n\n                // Chooses a connector\n                connector = connectors.storage() || connectors.windowref();\n                if (!connector) {\n                    return;\n                }\n\n                return {\n                    open: function () {\n                        var parentOpened;\n\n                        // Checks the shared one is alive\n                        _traceTimer = setInterval(function () {\n                            var oldTrace = trace;\n                            trace = findTrace();\n                            if (!trace || oldTrace.ts === trace.ts) {\n                                // Simulates a close signal\n                                listener(atmosphere.util.stringifyJSON({\n                                    target: \"c\",\n                                    type: \"close\",\n                                    data: {\n                                        reason: \"error\",\n                                        heir: oldTrace.heir\n                                    }\n                                }));\n                            }\n                        }, 1000);\n\n                        parentOpened = connector.init();\n                        if (parentOpened) {\n                            // Firing the open event without delay robs the user of the opportunity to bind connecting event handlers\n                            setTimeout(function () {\n                                _open(\"opening\", 'local', request);\n                            }, 50);\n                        }\n                        return parentOpened;\n                    },\n                    send: function (event) {\n                        connector.signal(\"send\", event);\n                    },\n                    localSend: function (event) {\n                        connector.signal(\"localSend\", atmosphere.util.stringifyJSON({\n                            id: guid,\n                            event: event\n                        }));\n                    },\n                    close: function () {\n                        // Do not signal the parent if this method is executed by the unload event handler\n                        if (!_abordingConnection) {\n                            clearInterval(_traceTimer);\n                            connector.signal(\"close\");\n                            connector.close();\n                        }\n                    }\n                };\n            }\n\n            function share() {\n                var storageService, name = \"atmosphere-\" + _request.url, servers = {\n                    // Powered by the storage event and the localStorage\n                    // http://www.w3.org/TR/webstorage/#event-storage\n                    storage: function () {\n                        function onstorage(event) {\n                            // When a deletion, newValue initialized to null\n                            if (event.key === name && event.newValue) {\n                                listener(event.newValue);\n                            }\n                        }\n\n                        if (!atmosphere.util.storage) {\n                            return;\n                        }\n\n                        var storage = window.localStorage;\n\n                        return {\n                            init: function () {\n                                // Handles the storage event\n                                atmosphere.util.on(window, \"storage\", onstorage);\n                            },\n                            signal: function (type, data) {\n                                storage.setItem(name, atmosphere.util.stringifyJSON({\n                                    target: \"c\",\n                                    type: type,\n                                    data: data\n                                }));\n                            },\n                            get: function (key) {\n                                return atmosphere.util.parseJSON(storage.getItem(name + \"-\" + key));\n                            },\n                            set: function (key, value) {\n                                storage.setItem(name + \"-\" + key, atmosphere.util.stringifyJSON(value));\n                            },\n                            close: function () {\n                                atmosphere.util.off(window, \"storage\", onstorage);\n                                storage.removeItem(name);\n                                storage.removeItem(name + \"-opened\");\n                                storage.removeItem(name + \"-children\");\n                            }\n\n                        };\n                    },\n                    // Powered by the window.open method\n                    // https://developer.mozilla.org/en/DOM/window.open\n                    windowref: function () {\n                        // Internet Explorer raises an invalid argument error\n                        // when calling the window.open method with the name containing non-word characters\n                        var neim = name.replace(/\\W/g, \"\"), container = document.getElementById(neim), win;\n\n                        if (!container) {\n                            container = document.createElement(\"div\");\n                            container.id = neim;\n                            container.style.display = \"none\";\n                            container.innerHTML = '<iframe name=\"' + neim + '\" />';\n                            document.body.appendChild(container);\n                        }\n\n                        win = container.firstChild.contentWindow;\n\n                        return {\n                            init: function () {\n                                // Callbacks from different windows\n                                win.callbacks = [listener];\n                                // In IE 8 and less, only string argument can be safely passed to the function in other window\n                                win.fire = function (string) {\n                                    var i;\n\n                                    for (i = 0; i < win.callbacks.length; i++) {\n                                        win.callbacks[i](string);\n                                    }\n                                };\n                            },\n                            signal: function (type, data) {\n                                if (!win.closed && win.fire) {\n                                    win.fire(atmosphere.util.stringifyJSON({\n                                        target: \"c\",\n                                        type: type,\n                                        data: data\n                                    }));\n                                }\n                            },\n                            get: function (key) {\n                                return !win.closed ? win[key] : null;\n                            },\n                            set: function (key, value) {\n                                if (!win.closed) {\n                                    win[key] = value;\n                                }\n                            },\n                            close: function () {\n                            }\n                        };\n                    }\n                };\n\n                // Receives send and close command from the children\n                function listener(string) {\n                    var command = atmosphere.util.parseJSON(string), data = command.data;\n\n                    if (command.target === \"p\") {\n                        switch (command.type) {\n                            case \"send\":\n                                _push(data);\n                                break;\n                            case \"localSend\":\n                                _localMessage(data);\n                                break;\n                            case \"close\":\n                                _close();\n                                break;\n                        }\n                    }\n                }\n\n                _localSocketF = function propagateMessageEvent(context) {\n                    storageService.signal(\"message\", context);\n                };\n\n                function leaveTrace() {\n                    document.cookie = _sharingKey + \"=\" +\n                        // Opera's JSON implementation ignores a number whose a last digit of 0 strangely\n                        // but has no problem with a number whose a last digit of 9 + 1\n                        encodeURIComponent(atmosphere.util.stringifyJSON({\n                            ts: atmosphere.util.now() + 1,\n                            heir: (storageService.get(\"children\") || [])[0]\n                        })) + \"; path=/\";\n                }\n\n                // Chooses a storageService\n                storageService = servers.storage() || servers.windowref();\n                storageService.init();\n\n                if (_request.logLevel === 'debug') {\n                    atmosphere.util.debug(\"Installed StorageService \" + storageService);\n                }\n\n                // List of children sockets\n                storageService.set(\"children\", []);\n\n                if (storageService.get(\"opened\") != null && !storageService.get(\"opened\")) {\n                    // Flag indicating the parent socket is opened\n                    storageService.set(\"opened\", false);\n                }\n                // Leaves traces\n                _sharingKey = encodeURIComponent(name);\n                leaveTrace();\n                _traceTimer = setInterval(leaveTrace, 1000);\n\n                _storageService = storageService;\n            }\n\n            /**\n             * @private\n             */\n            function _open(state, transport, request) {\n                if (_request.shared && transport !== 'local') {\n                    share();\n                }\n\n                if (_storageService != null) {\n                    _storageService.set(\"opened\", true);\n                }\n\n                request.close = function () {\n                    _close();\n                };\n\n                if (_requestCount > 0 && state === 're-connecting') {\n                    request.isReopen = true;\n                    _tryingToReconnect(_response);\n                } else if (_response.error == null) {\n                    _response.request = request;\n                    var prevState = _response.state;\n                    _response.state = state;\n                    var prevTransport = _response.transport;\n                    _response.transport = transport;\n\n                    var _body = _response.responseBody;\n                    _invokeCallback();\n                    _response.responseBody = _body;\n\n                    _response.state = prevState;\n                    _response.transport = prevTransport;\n                }\n            }\n\n            /**\n             * Execute request using jsonp transport.\n             *\n             * @param request {Object} request Request parameters, if undefined _request object will be used.\n             * @private\n             */\n            function _jsonp(request) {\n                // When CORS is enabled, make sure we force the proper transport.\n                request.transport = \"jsonp\";\n\n                var rq = _request, script;\n                if ((request != null) && (typeof (request) !== 'undefined')) {\n                    rq = request;\n                }\n\n                _jqxhr = {\n                    open: function () {\n                        var callback = \"atmosphere\" + (++guid);\n\n                        function poll() {\n                            var url = rq.url;\n                            if (rq.dispatchUrl != null) {\n                                url += rq.dispatchUrl;\n                            }\n\n                            var data = rq.data;\n                            if (rq.attachHeadersAsQueryString) {\n                                url = _attachHeaders(rq);\n                                if (data !== '') {\n                                    url += \"&X-Atmosphere-Post-Body=\" + encodeURIComponent(data);\n                                }\n                                data = '';\n                            }\n\n                            var head = document.head || document.getElementsByTagName(\"head\")[0] || document.documentElement;\n\n                            script = document.createElement(\"script\");\n                            script.src = url + \"&jsonpTransport=\" + callback;\n                            script.clean = function () {\n                                script.clean = script.onerror = script.onload = script.onreadystatechange = null;\n                                if (script.parentNode) {\n                                    script.parentNode.removeChild(script);\n                                }\n                            };\n                            script.onload = script.onreadystatechange = function () {\n                                if (!script.readyState || /loaded|complete/.test(script.readyState)) {\n                                    script.clean();\n                                }\n                            };\n                            script.onerror = function () {\n                                script.clean();\n                                rq.lastIndex = 0;\n\n                                if (rq.openId) {\n                                    clearTimeout(rq.openId);\n                                }\n\n                                if (rq.reconnect && _requestCount++ < rq.maxReconnectOnClose) {\n                                    _open('re-connecting', rq.transport, rq);\n                                    _reconnect(_jqxhr, rq, request.reconnectInterval);\n                                    rq.openId = setTimeout(function() {\n                                        _triggerOpen(rq);\n                                    }, rq.reconnectInterval + 1000);\n                                } else {\n                                    _onError(0, \"maxReconnectOnClose reached\");\n                                }\n                            };\n\n                            head.insertBefore(script, head.firstChild);\n                        }\n\n                        // Attaches callback\n                        window[callback] = function (msg) {\n                            if (rq.reconnect) {\n                                if (rq.maxRequest === -1 || rq.requestCount++ < rq.maxRequest) {\n                                    // _readHeaders(_jqxhr, rq);\n\n                                    if (!rq.executeCallbackBeforeReconnect) {\n                                        _reconnect(_jqxhr, rq, 0);\n                                    }\n\n                                    if (msg != null && typeof msg !== 'string') {\n                                        try {\n                                            msg = msg.message;\n                                        } catch (err) {\n                                            // The message was partial\n                                        }\n                                    }\n\n                                    var skipCallbackInvocation = _trackMessageSize(msg, rq, _response);\n                                    if (!skipCallbackInvocation) {\n                                        _prepareCallback(_response.responseBody, \"messageReceived\", 200, rq.transport);\n                                    }\n\n                                    if (rq.executeCallbackBeforeReconnect) {\n                                        _reconnect(_jqxhr, rq, 0);\n                                    }\n                                } else {\n                                    atmosphere.util.log(_request.logLevel, [\"JSONP reconnect maximum try reached \" + _request.requestCount]);\n                                    _onError(0, \"maxRequest reached\");\n                                }\n                            }\n                        };\n                        setTimeout(function () {\n                            poll();\n                        }, 50);\n                    },\n                    abort: function () {\n                        if (script.clean) {\n                            script.clean();\n                        }\n                    }\n                };\n\n                _jqxhr.open();\n            }\n\n            /**\n             * Build websocket object.\n             *\n             * @param location {string} Web socket url.\n             * @returns {websocket} Web socket object.\n             * @private\n             */\n            function _getWebSocket(location) {\n                if (_request.webSocketImpl != null) {\n                    return _request.webSocketImpl;\n                } else {\n                    if (window.WebSocket) {\n                        return new WebSocket(location);\n                    } else {\n                        return new MozWebSocket(location);\n                    }\n                }\n            }\n\n            /**\n             * Build web socket url from request url.\n             *\n             * @return {string} Web socket url (start with \"ws\" or \"wss\" for secure web socket).\n             * @private\n             */\n            function _buildWebSocketUrl() {\n                return atmosphere.util.getAbsoluteURL(_attachHeaders(_request)).replace(/^http/, \"ws\");\n            }\n\n            /**\n             * Build SSE url from request url.\n             *\n             * @return a url with Atmosphere's headers\n             * @private\n             */\n            function _buildSSEUrl() {\n                var url = _attachHeaders(_request);\n                return url;\n            }\n\n            /**\n             * Open SSE. <br>\n             * Automatically use fallback transport if SSE can't be opened.\n             *\n             * @private\n             */\n            function _executeSSE(sseOpened) {\n\n                _response.transport = \"sse\";\n\n                var location = _buildSSEUrl();\n\n                if (_request.logLevel === 'debug') {\n                    atmosphere.util.debug(\"Invoking executeSSE\");\n                    atmosphere.util.debug(\"Using URL: \" + location);\n                }\n\n                if (_request.enableProtocol && sseOpened) {\n                    var time = atmosphere.util.now() - _request.ctime;\n                    _request.lastTimestamp = Number(_request.stime) + Number(time);\n                }\n\n                if (sseOpened && !_request.reconnect) {\n                    if (_sse != null) {\n                        _clearState();\n                    }\n                    return;\n                }\n\n                try {\n                    _sse = new EventSource(location, {\n                        withCredentials: _request.withCredentials\n                    });\n                } catch (e) {\n                    _onError(0, e);\n                    _reconnectWithFallbackTransport(\"SSE failed. Downgrading to fallback transport and resending\");\n                    return;\n                }\n\n                if (_request.connectTimeout > 0) {\n                    _request.id = setTimeout(function () {\n                        if (!sseOpened) {\n                            _clearState();\n                        }\n                    }, _request.connectTimeout);\n                }\n\n                _sse.onopen = function (event) {\n                    _timeout(_request);\n                    if (_request.logLevel === 'debug') {\n                        atmosphere.util.debug(\"SSE successfully opened\");\n                    }\n\n                    if (!_request.enableProtocol) {\n                        if (!sseOpened) {\n                            _open('opening', \"sse\", _request);\n                        } else {\n                            _open('re-opening', \"sse\", _request);\n                        }\n                    } else if (_request.isReopen) {\n                        _request.isReopen = false;\n                        _open('re-opening', _request.transport, _request);\n                    }\n\n                    sseOpened = true;\n\n                    if (_request.method === 'POST') {\n                        _response.state = \"messageReceived\";\n                        _sse.send(_request.data);\n                    }\n                };\n\n                _sse.onmessage = function (message) {\n                    _timeout(_request);\n\n                    if (!_request.enableXDR && message.origin && message.origin !== window.location.protocol + \"//\" + window.location.host) {\n                        atmosphere.util.log(_request.logLevel, [\"Origin was not \" + window.location.protocol + \"//\" + window.location.host]);\n                        return;\n                    }\n\n                    _response.state = 'messageReceived';\n                    _response.status = 200;\n\n                    message = message.data;\n                    var skipCallbackInvocation = _trackMessageSize(message, _request, _response);\n\n                    // https://github.com/remy/polyfills/blob/master/EventSource.js\n                    // Since we polling.\n                   /* if (_sse.URL) {\n                        _sse.interval = 100;\n                        _sse.URL = _buildSSEUrl();\n                    } */\n\n                    if (!skipCallbackInvocation) {\n                        _invokeCallback();\n                        _response.responseBody = '';\n                        _response.messages = [];\n                    }\n                };\n\n                _sse.onerror = function (message) {\n                    clearTimeout(_request.id);\n\n                    if (_response.closedByClientTimeout) return;\n\n                    _invokeClose(sseOpened);\n                    _clearState();\n\n                    if (_abordingConnection) {\n                        atmosphere.util.log(_request.logLevel, [\"SSE closed normally\"]);\n                    } else if (!sseOpened) {\n                        _reconnectWithFallbackTransport(\"SSE failed. Downgrading to fallback transport and resending\");\n                    } else if (_request.reconnect && (_response.transport === 'sse')) {\n                        if (_requestCount++ < _request.maxReconnectOnClose) {\n                            _open('re-connecting', _request.transport, _request);\n                            if (_request.reconnectInterval > 0) {\n                                _request.reconnectId = setTimeout(function () {\n                                    _executeSSE(true);\n                                }, _request.reconnectInterval);\n                            } else {\n                                _executeSSE(true);\n                            }\n                            _response.responseBody = \"\";\n                            _response.messages = [];\n                        } else {\n                            atmosphere.util.log(_request.logLevel, [\"SSE reconnect maximum try reached \" + _requestCount]);\n                            _onError(0, \"maxReconnectOnClose reached\");\n                        }\n                    }\n                };\n            }\n\n            /**\n             * Open web socket. <br>\n             * Automatically use fallback transport if web socket can't be opened.\n             *\n             * @private\n             */\n            function _executeWebSocket(webSocketOpened) {\n\n                _response.transport = \"websocket\";\n\n                if (_request.enableProtocol && webSocketOpened) {\n                    var time = atmosphere.util.now() - _request.ctime;\n                    _request.lastTimestamp = Number(_request.stime) + Number(time);\n                }\n\n                var location = _buildWebSocketUrl(_request.url);\n                if (_request.logLevel === 'debug') {\n                    atmosphere.util.debug(\"Invoking executeWebSocket\");\n                    atmosphere.util.debug(\"Using URL: \" + location);\n                }\n\n                if (webSocketOpened && !_request.reconnect) {\n                    if (_websocket != null) {\n                        _clearState();\n                    }\n                    return;\n                }\n\n                _websocket = _getWebSocket(location);\n                if (_request.webSocketBinaryType != null) {\n                    _websocket.binaryType = _request.webSocketBinaryType;\n                }\n\n                if (_request.connectTimeout > 0) {\n                    _request.id = setTimeout(function () {\n                        if (!webSocketOpened) {\n                            var _message = {\n                                code: 1002,\n                                reason: \"\",\n                                wasClean: false\n                            };\n                            _websocket.onclose(_message);\n                            // Close it anyway\n                            try {\n                                _clearState();\n                            } catch (e) {\n                            }\n                            return;\n                        }\n\n                    }, _request.connectTimeout);\n                }\n\n                _websocket.onopen = function (message) {\n                    _timeout(_request);\n\n                    if (_request.logLevel === 'debug') {\n                        atmosphere.util.debug(\"Websocket successfully opened\");\n                    }\n\n                    var reopening = webSocketOpened;\n\n                    webSocketOpened = true;\n                    if(_websocket != null) {\n                        _websocket.webSocketOpened = webSocketOpened;\n                    }\n\n                    if (!_request.enableProtocol) {\n                        if (reopening) {\n                            _open('re-opening', \"websocket\", _request);\n                        } else {\n                            _open('opening', \"websocket\", _request);\n                        }\n                    }\n\n                    if (_websocket != null) {\n                        if (_request.method === 'POST') {\n                            _response.state = \"messageReceived\";\n                            _websocket.send(_request.data);\n                        }\n                    }\n                };\n\n                _websocket.onmessage = function (message) {\n                    _timeout(_request);\n\n                    _response.state = 'messageReceived';\n                    _response.status = 200;\n\n                    message = message.data;\n                    var isString = typeof (message) === 'string';\n                    if (isString) {\n                        var skipCallbackInvocation = _trackMessageSize(message, _request, _response);\n                        if (!skipCallbackInvocation) {\n                            _invokeCallback();\n                            _response.responseBody = '';\n                            _response.messages = [];\n                        }\n                    } else {\n                        if (!_handleProtocol(_request, message))\n                            return;\n\n                        _response.responseBody = message;\n                        _invokeCallback();\n                        _response.responseBody = null;\n                    }\n                };\n\n                _websocket.onerror = function (message) {\n                    clearTimeout(_request.id);\n                };\n\n                _websocket.onclose = function (message) {\n                    clearTimeout(_request.id);\n                    if (_response.state === 'closed')\n                        return;\n\n                    var reason = message.reason;\n                    if (reason === \"\") {\n                        switch (message.code) {\n                            case 1000:\n                                reason = \"Normal closure; the connection successfully completed whatever purpose for which \" + \"it was created.\";\n                                break;\n                            case 1001:\n                                reason = \"The endpoint is going away, either because of a server failure or because the \"\n                                    + \"browser is navigating away from the page that opened the connection.\";\n                                break;\n                            case 1002:\n                                reason = \"The endpoint is terminating the connection due to a protocol error.\";\n                                break;\n                            case 1003:\n                                reason = \"The connection is being terminated because the endpoint received data of a type it \"\n                                    + \"cannot accept (for example, a text-only endpoint received binary data).\";\n                                break;\n                            case 1004:\n                                reason = \"The endpoint is terminating the connection because a data frame was received that \" + \"is too large.\";\n                                break;\n                            case 1005:\n                                reason = \"Unknown: no status code was provided even though one was expected.\";\n                                break;\n                            case 1006:\n                                reason = \"Connection was closed abnormally (that is, with no close frame being sent).\";\n                                break;\n                        }\n                    }\n\n                    if (_request.logLevel === 'warn') {\n                        atmosphere.util.warn(\"Websocket closed, reason: \" + reason);\n                        atmosphere.util.warn(\"Websocket closed, wasClean: \" + message.wasClean);\n                    }\n\n                    if (_response.closedByClientTimeout) {\n                        return;\n                    }\n\n                    _invokeClose(webSocketOpened);\n\n                    _response.state = 'closed';\n\n                    if (_abordingConnection) {\n                        atmosphere.util.log(_request.logLevel, [\"Websocket closed normally\"]);\n                    } else if (!webSocketOpened) {\n                        _reconnectWithFallbackTransport(\"Websocket failed. Downgrading to Comet and resending\");\n\n                    } else if (_request.reconnect && _response.transport === 'websocket') {\n                        _clearState();\n                        if (_requestCount++ < _request.maxReconnectOnClose) {\n                            _open('re-connecting', _request.transport, _request);\n                            if (_request.reconnectInterval > 0) {\n                                _request.reconnectId = setTimeout(function () {\n                                    _response.responseBody = \"\";\n                                    _response.messages = [];\n                                    _executeWebSocket(true);\n                                }, _request.reconnectInterval);\n                            } else {\n                                _response.responseBody = \"\";\n                                _response.messages = [];\n                                _executeWebSocket(true);\n                            }\n                        } else {\n                            atmosphere.util.log(_request.logLevel, [\"Websocket reconnect maximum try reached \" + _request.requestCount]);\n                            if (_request.logLevel === 'warn') {\n                                atmosphere.util.warn(\"Websocket error, reason: \" + message.reason);\n                            }\n                            _onError(0, \"maxReconnectOnClose reached\");\n                        }\n                    }\n                };\n\n                if (_websocket.url === undefined) {\n                    // Android 4.1 does not really support websockets and fails silently\n                    _websocket.onclose({\n                        reason: \"Android 4.1 does not support websockets.\",\n                        wasClean: false\n                    });\n                }\n            }\n\n            function _handleProtocol(request, message) {\n\n                // The first messages is always the uuid.\n                var b = true;\n\n                if (request.transport === 'polling') return b;\n\n                if (atmosphere.util.trim(message).length !== 0 && request.enableProtocol && request.firstMessage) {\n                    request.firstMessage = false;\n                    var messages = message.split(request.messageDelimiter);\n                    var pos = messages.length === 2 ? 0 : 1;\n                    request.uuid = atmosphere.util.trim(messages[pos]);\n                    request.stime = atmosphere.util.trim(messages[pos + 1]);\n                    b = false;\n                    if (request.transport !== 'long-polling') {\n                        _triggerOpen(request);\n                    }\n                    uuid = request.uuid;\n                } else if (request.enableProtocol && request.firstMessage) {\n                    // In case we are getting some junk from IE\n                    b = false;\n                } else {\n                    _triggerOpen(request);\n                }\n                return b;\n            }\n\n            function _timeout(_request) {\n                clearTimeout(_request.id);\n                if (_request.timeout > 0 && _request.transport !== 'polling') {\n                    _request.id = setTimeout(function () {\n                        _onClientTimeout(_request);\n                        _disconnect();\n                        _clearState();\n                    }, _request.timeout);\n                }\n            }\n\n            function _onClientTimeout(_request) {\n                _response.closedByClientTimeout = true;\n                _response.state = 'closedByClient';\n                _response.responseBody = \"\";\n                _response.status = 408;\n                _response.messages = [];\n                _invokeCallback();\n            }\n\n            function _onError(code, reason) {\n                _clearState();\n                clearTimeout(_request.id);\n                _response.state = 'error';\n                _response.reasonPhrase = reason;\n                _response.responseBody = \"\";\n                _response.status = code;\n                _response.messages = [];\n                _invokeCallback();\n            }\n\n            /**\n             * Track received message and make sure callbacks/functions are only invoked when the complete message has been received.\n             *\n             * @param message\n             * @param request\n             * @param response\n             */\n            function _trackMessageSize(message, request, response) {\n                if (!_handleProtocol(request, message))\n                    return true;\n                if (message.length === 0)\n                    return true;\n\n                if (request.trackMessageLength) {\n                    // prepend partialMessage if any\n                    message = response.partialMessage + message;\n\n                    var messages = [];\n                    var messageStart = message.indexOf(request.messageDelimiter);\n                    while (messageStart !== -1) {\n                        var str = atmosphere.util.trim(message.substring(0, messageStart));\n                        var messageLength = +str;\n                        if (isNaN(messageLength))\n                            throw new Error('message length \"' + str + '\" is not a number');\n                        messageStart += request.messageDelimiter.length;\n                        if (messageStart + messageLength > message.length) {\n                            // message not complete, so there is no trailing messageDelimiter\n                            messageStart = -1;\n                        } else {\n                            // message complete, so add it\n                            messages.push(message.substring(messageStart, messageStart + messageLength));\n                            // remove consumed characters\n                            message = message.substring(messageStart + messageLength, message.length);\n                            messageStart = message.indexOf(request.messageDelimiter);\n                        }\n                    }\n\n                    /* keep any remaining data */\n                    response.partialMessage = message;\n\n                    if (messages.length !== 0) {\n                        response.responseBody = messages.join(request.messageDelimiter);\n                        response.messages = messages;\n                        return false;\n                    } else {\n                        response.responseBody = \"\";\n                        response.messages = [];\n                        return true;\n                    }\n                } else {\n                    response.responseBody = message;\n                }\n                return false;\n            }\n\n            /**\n             * Reconnect request with fallback transport. <br>\n             * Used in case websocket can't be opened.\n             *\n             * @private\n             */\n            function _reconnectWithFallbackTransport(errorMessage) {\n                atmosphere.util.log(_request.logLevel, [errorMessage]);\n\n                if (typeof (_request.onTransportFailure) !== 'undefined') {\n                    _request.onTransportFailure(errorMessage, _request);\n                } else if (typeof (atmosphere.util.onTransportFailure) !== 'undefined') {\n                    atmosphere.util.onTransportFailure(errorMessage, _request);\n                }\n\n                _request.transport = _request.fallbackTransport;\n                var reconnectInterval = _request.connectTimeout === -1 ? 0 : _request.connectTimeout;\n                if (_request.reconnect && _request.transport !== 'none' || _request.transport == null) {\n                    _request.method = _request.fallbackMethod;\n                    _response.transport = _request.fallbackTransport;\n                    _request.fallbackTransport = 'none';\n                    if (reconnectInterval > 0) {\n                        _request.reconnectId = setTimeout(function () {\n                            _execute();\n                        }, reconnectInterval);\n                    } else {\n                        _execute();\n                    }\n                } else {\n                    _onError(500, \"Unable to reconnect with fallback transport\");\n                }\n            }\n\n            /**\n             * Get url from request and attach headers to it.\n             *\n             * @param request {Object} request Request parameters, if undefined _request object will be used.\n             *\n             * @returns {Object} Request object, if undefined, _request object will be used.\n             * @private\n             */\n            function _attachHeaders(request, url) {\n                var rq = _request;\n                if ((request != null) && (typeof (request) !== 'undefined')) {\n                    rq = request;\n                }\n\n                if (url == null) {\n                    url = rq.url;\n                }\n\n                // If not enabled\n                if (!rq.attachHeadersAsQueryString)\n                    return url;\n\n                // If already added\n                if (url.indexOf(\"X-Atmosphere-Framework\") !== -1) {\n                    return url;\n                }\n\n                url += (url.indexOf('?') !== -1) ? '&' : '?';\n                url += \"X-Atmosphere-tracking-id=\" + rq.uuid;\n                url += \"&X-Atmosphere-Framework=\" + version;\n                url += \"&X-Atmosphere-Transport=\" + rq.transport;\n\n                if (rq.trackMessageLength) {\n                    url += \"&X-Atmosphere-TrackMessageSize=\" + \"true\";\n                }\n\n                if (rq.lastTimestamp != null) {\n                    url += \"&X-Cache-Date=\" + rq.lastTimestamp;\n                } else {\n                    url += \"&X-Cache-Date=\" + 0;\n                }\n\n                if (rq.contentType !== '') {\n                    //Eurk!\n                    url += \"&Content-Type=\" + rq.transport === 'websocket' ? rq.contentType : encodeURIComponent(rq.contentType);\n                }\n\n                if (rq.enableProtocol) {\n                    url += \"&X-atmo-protocol=true\";\n                }\n\n                atmosphere.util.each(rq.headers, function (name, value) {\n                    var h = atmosphere.util.isFunction(value) ? value.call(this, rq, request, _response) : value;\n                    if (h != null) {\n                        url += \"&\" + encodeURIComponent(name) + \"=\" + encodeURIComponent(h);\n                    }\n                });\n\n                return url;\n            }\n\n            function _triggerOpen(rq) {\n                if (!rq.isOpen) {\n                    rq.isOpen = true;\n                    _open('opening', rq.transport, rq);\n                } else if (rq.isReopen) {\n                    rq.isReopen = false;\n                    _open('re-opening', rq.transport, rq);\n                }\n            }\n\n            /**\n             * Execute ajax request. <br>\n             *\n             * @param request {Object} request Request parameters, if undefined _request object will be used.\n             * @private\n             */\n            function _executeRequest(request) {\n                var rq = _request;\n                if ((request != null) || (typeof (request) !== 'undefined')) {\n                    rq = request;\n                }\n\n                rq.lastIndex = 0;\n                rq.readyState = 0;\n\n                // CORS fake using JSONP\n                if ((rq.transport === 'jsonp') || ((rq.enableXDR) && (atmosphere.util.checkCORSSupport()))) {\n                    _jsonp(rq);\n                    return;\n                }\n\n                if (atmosphere.util.browser.msie && +atmosphere.util.browser.version.split(\".\")[0] < 10) {\n                    if ((rq.transport === 'streaming')) {\n                        if (rq.enableXDR && window.XDomainRequest) {\n                            _ieXDR(rq);\n                        } else {\n                            _ieStreaming(rq);\n                        }\n                        return;\n                    }\n\n                    if ((rq.enableXDR) && (window.XDomainRequest)) {\n                        _ieXDR(rq);\n                        return;\n                    }\n                }\n\n                var reconnectF = function () {\n                    rq.lastIndex = 0;\n                    if (rq.reconnect && _requestCount++ < rq.maxReconnectOnClose) {\n                        _open('re-connecting', request.transport, request);\n                        _reconnect(ajaxRequest, rq, request.reconnectInterval);\n                    } else {\n                        _onError(0, \"maxReconnectOnClose reached\");\n                    }\n                };\n\n                if (rq.force || (rq.reconnect && (rq.maxRequest === -1 || rq.requestCount++ < rq.maxRequest))) {\n                    rq.force = false;\n\n                    var ajaxRequest = atmosphere.util.xhr();\n                    ajaxRequest.hasData = false;\n\n                    _doRequest(ajaxRequest, rq, true);\n\n                    if (rq.suspend) {\n                        _activeRequest = ajaxRequest;\n                    }\n\n                    if (rq.transport !== 'polling') {\n                        _response.transport = rq.transport;\n\n                        ajaxRequest.onabort = function () {\n                            _invokeClose(true);\n                        };\n\n                        ajaxRequest.onerror = function () {\n                            _response.error = true;\n                            try {\n                                _response.status = XMLHttpRequest.status;\n                            } catch (e) {\n                                _response.status = 500;\n                            }\n\n                            if (!_response.status) {\n                                _response.status = 500;\n                            }\n                            if (!_response.errorHandled) {\n                                _clearState();\n                                reconnectF();\n                            }\n                        };\n                    }\n\n                    ajaxRequest.onreadystatechange = function () {\n                        if (_abordingConnection) {\n                            return;\n                        }\n\n                        _response.error = null;\n                        var skipCallbackInvocation = false;\n                        var update = false;\n\n                        if (rq.transport === 'streaming' && rq.readyState > 2 && ajaxRequest.readyState === 4) {\n                            _clearState();\n                            reconnectF();\n                            return;\n                        }\n\n                        rq.readyState = ajaxRequest.readyState;\n\n                        if (rq.transport === 'streaming' && ajaxRequest.readyState >= 3) {\n                            update = true;\n                        } else if (rq.transport === 'long-polling' && ajaxRequest.readyState === 4) {\n                            update = true;\n                        }\n                        _timeout(_request);\n\n                        if (rq.transport !== 'polling') {\n                            // MSIE 9 and lower status can be higher than 1000, Chrome can be 0\n                            var status = 200;\n                            if (ajaxRequest.readyState === 4) {\n                                status = ajaxRequest.status > 1000 ? 0 : ajaxRequest.status;\n                            }\n\n                            if (status >= 300 || status === 0) {\n                                // Prevent onerror callback to be called\n                                _response.errorHandled = true;\n                                _clearState();\n                                reconnectF();\n                                return;\n                            }\n\n                            // Firefox incorrectly send statechange 0->2 when a reconnect attempt fails. The above checks ensure that onopen is not called for these\n                            if ((!rq.enableProtocol || !request.firstMessage) && ajaxRequest.readyState === 2) {\n                                _triggerOpen(rq);\n                            }\n\n                        } else if (ajaxRequest.readyState === 4) {\n                            update = true;\n                        }\n\n                        if (update) {\n                            var responseText = ajaxRequest.responseText;\n\n                            if (atmosphere.util.trim(responseText).length === 0 && rq.transport === 'long-polling') {\n                                // For browser that aren't support onabort\n                                if (!ajaxRequest.hasData) {\n                                    _reconnect(ajaxRequest, rq, 0);\n                                } else {\n                                    ajaxRequest.hasData = false;\n                                }\n                                return;\n                            }\n                            ajaxRequest.hasData = true;\n\n                            _readHeaders(ajaxRequest, _request);\n\n                            if (rq.transport === 'streaming') {\n                                if (!atmosphere.util.browser.opera) {\n                                    var message = responseText.substring(rq.lastIndex, responseText.length);\n                                    skipCallbackInvocation = _trackMessageSize(message, rq, _response);\n\n                                    rq.lastIndex = responseText.length;\n                                    if (skipCallbackInvocation) {\n                                        return;\n                                    }\n                                } else {\n                                    atmosphere.util.iterate(function () {\n                                        if (_response.status !== 500 && ajaxRequest.responseText.length > rq.lastIndex) {\n                                            try {\n                                                _response.status = ajaxRequest.status;\n                                                _response.headers = atmosphere.util.parseHeaders(ajaxRequest.getAllResponseHeaders());\n\n                                                _readHeaders(ajaxRequest, _request);\n\n                                            } catch (e) {\n                                                _response.status = 404;\n                                            }\n                                            _timeout(_request);\n\n                                            _response.state = \"messageReceived\";\n                                            var message = ajaxRequest.responseText.substring(rq.lastIndex);\n                                            rq.lastIndex = ajaxRequest.responseText.length;\n\n                                            skipCallbackInvocation = _trackMessageSize(message, rq, _response);\n                                            if (!skipCallbackInvocation) {\n                                                _invokeCallback();\n                                            }\n\n                                            _verifyStreamingLength(ajaxRequest, rq);\n                                        } else if (_response.status > 400) {\n                                            // Prevent replaying the last message.\n                                            rq.lastIndex = ajaxRequest.responseText.length;\n                                            return false;\n                                        }\n                                    }, 0);\n                                }\n                            } else {\n                                skipCallbackInvocation = _trackMessageSize(responseText, rq, _response);\n                            }\n\n                            try {\n                                _response.status = ajaxRequest.status;\n                                _response.headers = atmosphere.util.parseHeaders(ajaxRequest.getAllResponseHeaders());\n\n                                _readHeaders(ajaxRequest, rq);\n                            } catch (e) {\n                                _response.status = 404;\n                            }\n\n                            if (rq.suspend) {\n                                _response.state = _response.status === 0 ? \"closed\" : \"messageReceived\";\n                            } else {\n                                _response.state = \"messagePublished\";\n                            }\n\n                            var isAllowedToReconnect = request.transport !== 'streaming' && request.transport !== 'polling';\n                            if (isAllowedToReconnect && !rq.executeCallbackBeforeReconnect) {\n                                _reconnect(ajaxRequest, rq, 0);\n                            }\n\n                            if (_response.responseBody.length !== 0 && !skipCallbackInvocation)\n                                _invokeCallback();\n\n                            if (isAllowedToReconnect && rq.executeCallbackBeforeReconnect) {\n                                _reconnect(ajaxRequest, rq, 0);\n                            }\n\n                            _verifyStreamingLength(ajaxRequest, rq);\n                        }\n                    };\n\n                    try {\n                        ajaxRequest.send(rq.data);\n                        _subscribed = true;\n                    } catch (e) {\n                        atmosphere.util.log(rq.logLevel, [\"Unable to connect to \" + rq.url]);\n                    }\n\n                } else {\n                    if (rq.logLevel === 'debug') {\n                        atmosphere.util.log(rq.logLevel, [\"Max re-connection reached.\"]);\n                    }\n                    _onError(0, \"maxRequest reached\");\n                }\n            }\n\n            /**\n             * Do ajax request.\n             *\n             * @param ajaxRequest Ajax request.\n             * @param request Request parameters.\n             * @param create If ajax request has to be open.\n             */\n            function _doRequest(ajaxRequest, request, create) {\n                // Prevent Android to cache request\n                var url = request.url;\n                if (request.dispatchUrl != null && request.method === 'POST') {\n                    url += request.dispatchUrl;\n                }\n                url = _attachHeaders(request, url);\n                url = atmosphere.util.prepareURL(url);\n\n                if (create) {\n                    ajaxRequest.open(request.method, url, request.async);\n                    if (request.connectTimeout > 0) {\n                        request.id = setTimeout(function () {\n                            if (request.requestCount === 0) {\n                                _clearState();\n                                _prepareCallback(\"Connect timeout\", \"closed\", 200, request.transport);\n                            }\n                        }, request.connectTimeout);\n                    }\n                }\n\n                if (_request.withCredentials) {\n                    if (\"withCredentials\" in ajaxRequest) {\n                        ajaxRequest.withCredentials = true;\n                    }\n                }\n\n                if (!_request.dropHeaders) {\n                    ajaxRequest.setRequestHeader(\"X-Atmosphere-Framework\", atmosphere.util.version);\n                    ajaxRequest.setRequestHeader(\"X-Atmosphere-Transport\", request.transport);\n                    if (request.lastTimestamp != null) {\n                        ajaxRequest.setRequestHeader(\"X-Cache-Date\", request.lastTimestamp);\n                    } else {\n                        ajaxRequest.setRequestHeader(\"X-Cache-Date\", 0);\n                    }\n\n                    if (request.trackMessageLength) {\n                        ajaxRequest.setRequestHeader(\"X-Atmosphere-TrackMessageSize\", \"true\");\n                    }\n                    ajaxRequest.setRequestHeader(\"X-Atmosphere-tracking-id\", request.uuid);\n\n                    atmosphere.util.each(request.headers, function (name, value) {\n                        var h = atmosphere.util.isFunction(value) ? value.call(this, ajaxRequest, request, create, _response) : value;\n                        if (h != null) {\n                            ajaxRequest.setRequestHeader(name, h);\n                        }\n                    });\n                }\n\n                if (request.contentType !== '') {\n                    ajaxRequest.setRequestHeader(\"Content-Type\", request.contentType);\n                }\n            }\n\n            function _reconnect(ajaxRequest, request, reconnectInterval) {\n                if (request.reconnect || (request.suspend && _subscribed)) {\n                    var status = 0;\n                    if (ajaxRequest && ajaxRequest.readyState !== 0) {\n                        status = ajaxRequest.status > 1000 ? 0 : ajaxRequest.status;\n                    }\n                    _response.status = status === 0 ? 204 : status;\n                    _response.reason = status === 0 ? \"Server resumed the connection or down.\" : \"OK\";\n\n                    clearTimeout(request.id);\n                    if (request.reconnectId) {\n                        clearTimeout(request.reconnectId);\n                        delete request.reconnectId;\n                    }\n\n                    if (reconnectInterval > 0) {\n                        // For whatever reason, never cancel a reconnect timeout as it is mandatory to reconnect.\n                        _request.reconnectId = setTimeout(function () {\n                            _executeRequest(request);\n                        }, reconnectInterval);\n                    } else {\n                        _executeRequest(request);\n                    }\n                }\n            }\n\n            function _tryingToReconnect(response) {\n                response.state = 're-connecting';\n                _invokeFunction(response);\n            }\n\n            function _ieXDR(request) {\n                if (request.transport !== \"polling\") {\n                    _ieStream = _configureXDR(request);\n                    _ieStream.open();\n                } else {\n                    _configureXDR(request).open();\n                }\n            }\n\n            function _configureXDR(request) {\n                var rq = _request;\n                if ((request != null) && (typeof (request) !== 'undefined')) {\n                    rq = request;\n                }\n\n                var transport = rq.transport;\n                var lastIndex = 0;\n                var xdr = new window.XDomainRequest();\n\n                var reconnect = function () {\n                    if (rq.transport === \"long-polling\" && (rq.reconnect && (rq.maxRequest === -1 || rq.requestCount++ < rq.maxRequest))) {\n                        xdr.status = 200;\n                        _ieXDR(rq);\n                    }\n                };\n\n                var rewriteURL = rq.rewriteURL || function (url) {\n                    // Maintaining session by rewriting URL\n                    // http://stackoverflow.com/questions/6453779/maintaining-session-by-rewriting-url\n                    var match = /(?:^|;\\s*)(JSESSIONID|PHPSESSID)=([^;]*)/.exec(document.cookie);\n\n                    switch (match && match[1]) {\n                        case \"JSESSIONID\":\n                            return url.replace(/;jsessionid=[^\\?]*|(\\?)|$/, \";jsessionid=\" + match[2] + \"$1\");\n                        case \"PHPSESSID\":\n                            return url.replace(/\\?PHPSESSID=[^&]*&?|\\?|$/, \"?PHPSESSID=\" + match[2] + \"&\").replace(/&$/, \"\");\n                    }\n                    return url;\n                };\n\n                // Handles open and message event\n                xdr.onprogress = function () {\n                    handle(xdr);\n                };\n                // Handles error event\n                xdr.onerror = function () {\n                    // If the server doesn't send anything back to XDR will fail with polling\n                    if (rq.transport !== 'polling') {\n                        _clearState();\n                        if (_requestCount++ < rq.maxReconnectOnClose) {\n                            if (rq.reconnectInterval > 0) {\n                                rq.reconnectId = setTimeout(function () {\n                                    _open('re-connecting', request.transport, request);\n                                    _ieXDR(rq);\n                                }, rq.reconnectInterval);\n                            } else {\n                                _open('re-connecting', request.transport, request);\n                                _ieXDR(rq);\n                            }\n                        } else {\n                            _onError(0, \"maxReconnectOnClose reached\");\n                        }\n                    }\n                };\n\n                // Handles close event\n                xdr.onload = function () {\n                };\n\n                var handle = function (xdr) {\n                    clearTimeout(rq.id);\n                    var message = xdr.responseText;\n\n                    message = message.substring(lastIndex);\n                    lastIndex += message.length;\n\n                    if (transport !== 'polling') {\n                        _timeout(rq);\n\n                        var skipCallbackInvocation = _trackMessageSize(message, rq, _response);\n\n                        if (transport === 'long-polling' && atmosphere.util.trim(message).length === 0)\n                            return;\n\n                        if (rq.executeCallbackBeforeReconnect) {\n                            reconnect();\n                        }\n\n                        if (!skipCallbackInvocation) {\n                            _prepareCallback(_response.responseBody, \"messageReceived\", 200, transport);\n                        }\n\n                        if (!rq.executeCallbackBeforeReconnect) {\n                            reconnect();\n                        }\n                    }\n                };\n\n                return {\n                    open: function () {\n                        var url = rq.url;\n                        if (rq.dispatchUrl != null) {\n                            url += rq.dispatchUrl;\n                        }\n                        url = _attachHeaders(rq, url);\n                        xdr.open(rq.method, rewriteURL(url));\n                        if (rq.method === 'GET') {\n                            xdr.send();\n                        } else {\n                            xdr.send(rq.data);\n                        }\n\n                        if (rq.connectTimeout > 0) {\n                            rq.id = setTimeout(function () {\n                                if (rq.requestCount === 0) {\n                                    _clearState();\n                                    _prepareCallback(\"Connect timeout\", \"closed\", 200, rq.transport);\n                                }\n                            }, rq.connectTimeout);\n                        }\n                    },\n                    close: function () {\n                        xdr.abort();\n                    }\n                };\n            }\n\n            function _ieStreaming(request) {\n                _ieStream = _configureIE(request);\n                _ieStream.open();\n            }\n\n            function _configureIE(request) {\n                var rq = _request;\n                if ((request != null) && (typeof (request) !== 'undefined')) {\n                    rq = request;\n                }\n\n                var stop;\n                var doc = new window.ActiveXObject(\"htmlfile\");\n\n                doc.open();\n                doc.close();\n\n                var url = rq.url;\n                if (rq.dispatchUrl != null) {\n                    url += rq.dispatchUrl;\n                }\n\n                if (rq.transport !== 'polling') {\n                    _response.transport = rq.transport;\n                }\n\n                return {\n                    open: function () {\n                        var iframe = doc.createElement(\"iframe\");\n\n                        url = _attachHeaders(rq);\n                        if (rq.data !== '') {\n                            url += \"&X-Atmosphere-Post-Body=\" + encodeURIComponent(rq.data);\n                        }\n\n                        // Finally attach a timestamp to prevent Android and IE caching.\n                        url = atmosphere.util.prepareURL(url);\n\n                        iframe.src = url;\n                        doc.body.appendChild(iframe);\n\n                        // For the server to respond in a consistent format regardless of user agent, we polls response text\n                        var cdoc = iframe.contentDocument || iframe.contentWindow.document;\n\n                        stop = atmosphere.util.iterate(function () {\n                            try {\n                                if (!cdoc.firstChild) {\n                                    return;\n                                }\n\n                                var res = cdoc.body ? cdoc.body.lastChild : cdoc;\n                                var readResponse = function () {\n                                    // Clones the element not to disturb the original one\n                                    var clone = res.cloneNode(true);\n\n                                    // If the last character is a carriage return or a line feed, IE ignores it in the innerText property\n                                    // therefore, we add another non-newline character to preserve it\n                                    clone.appendChild(cdoc.createTextNode(\".\"));\n\n                                    var text = clone.innerText;\n\n                                    text = text.substring(0, text.length - 1);\n                                    return text;\n\n                                };\n\n                                // To support text/html content type\n                                if (!cdoc.body || !cdoc.body.firstChild || cdoc.body.firstChild.nodeName.toLowerCase() !== \"pre\") {\n                                    // Injects a plaintext element which renders text without interpreting the HTML and cannot be stopped\n                                    // it is deprecated in HTML5, but still works\n                                    var head = cdoc.head || cdoc.getElementsByTagName(\"head\")[0] || cdoc.documentElement || cdoc;\n                                    var script = cdoc.createElement(\"script\");\n\n                                    script.text = \"document.write('<plaintext>')\";\n\n                                    head.insertBefore(script, head.firstChild);\n                                    head.removeChild(script);\n\n                                    // The plaintext element will be the response container\n                                    res = cdoc.body.lastChild;\n                                }\n\n                                if (rq.closed) {\n                                    rq.isReopen = true;\n                                }\n\n                                // Handles message and close event\n                                stop = atmosphere.util.iterate(function () {\n                                    var text = readResponse();\n                                    if (text.length > rq.lastIndex) {\n                                        _timeout(_request);\n\n                                        _response.status = 200;\n                                        _response.error = null;\n\n                                        // Empties response every time that it is handled\n                                        res.innerText = \"\";\n                                        var skipCallbackInvocation = _trackMessageSize(text, rq, _response);\n                                        if (skipCallbackInvocation) {\n                                            return \"\";\n                                        }\n\n                                        _prepareCallback(_response.responseBody, \"messageReceived\", 200, rq.transport);\n                                    }\n\n                                    rq.lastIndex = 0;\n\n                                    if (cdoc.readyState === \"complete\") {\n                                        _invokeClose(true);\n                                        _open('re-connecting', rq.transport, rq);\n                                        if (rq.reconnectInterval > 0) {\n                                            rq.reconnectId = setTimeout(function () {\n                                                _ieStreaming(rq);\n                                            }, rq.reconnectInterval);\n                                        } else {\n                                            _ieStreaming(rq);\n                                        }\n                                        return false;\n                                    }\n                                }, null);\n\n                                return false;\n                            } catch (err) {\n                                _response.error = true;\n                                _open('re-connecting', rq.transport, rq);\n                                if (_requestCount++ < rq.maxReconnectOnClose) {\n                                    if (rq.reconnectInterval > 0) {\n                                        rq.reconnectId = setTimeout(function () {\n                                            _ieStreaming(rq);\n                                        }, rq.reconnectInterval);\n                                    } else {\n                                        _ieStreaming(rq);\n                                    }\n                                } else {\n                                    _onError(0, \"maxReconnectOnClose reached\");\n                                }\n                                doc.execCommand(\"Stop\");\n                                doc.close();\n                                return false;\n                            }\n                        });\n                    },\n\n                    close: function () {\n                        if (stop) {\n                            stop();\n                        }\n\n                        doc.execCommand(\"Stop\");\n                        _invokeClose(true);\n                    }\n                };\n            }\n\n            /**\n             * Send message. <br>\n             * Will be automatically dispatch to other connected.\n             *\n             * @param {Object, string} Message to send.\n             * @private\n             */\n            function _push(message) {\n\n                if (_localStorageService != null) {\n                    _pushLocal(message);\n                } else if (_activeRequest != null || _sse != null) {\n                    _pushAjaxMessage(message);\n                } else if (_ieStream != null) {\n                    _pushIE(message);\n                } else if (_jqxhr != null) {\n                    _pushJsonp(message);\n                } else if (_websocket != null) {\n                    _pushWebSocket(message);\n                } else {\n                    _onError(0, \"No suspended connection available\");\n                    atmosphere.util.error(\"No suspended connection available. Make sure atmosphere.subscribe has been called and request.onOpen invoked before invoking this method\");\n                }\n            }\n\n            function _pushOnClose(message, rq) {\n                if (!rq) {\n                    rq = _getPushRequest(message);\n                }\n                rq.transport = \"polling\";\n                rq.method = \"GET\";\n                rq.async = false;\n                rq.withCredentials = false;\n                rq.reconnect = false;\n                rq.force = true;\n                rq.suspend = false;\n                rq.timeout = 1000;\n                _executeRequest(rq);\n            }\n\n            function _pushLocal(message) {\n                _localStorageService.send(message);\n            }\n\n            function _intraPush(message) {\n                // IE 9 will crash if not.\n                if (message.length === 0)\n                    return;\n\n                try {\n                    if (_localStorageService) {\n                        _localStorageService.localSend(message);\n                    } else if (_storageService) {\n                        _storageService.signal(\"localMessage\", atmosphere.util.stringifyJSON({\n                            id: guid,\n                            event: message\n                        }));\n                    }\n                } catch (err) {\n                    atmosphere.util.error(err);\n                }\n            }\n\n            /**\n             * Send a message using currently opened ajax request (using http-streaming or long-polling). <br>\n             *\n             * @param {string, Object} Message to send. This is an object, string message is saved in data member.\n             * @private\n             */\n            function _pushAjaxMessage(message) {\n                var rq = _getPushRequest(message);\n                _executeRequest(rq);\n            }\n\n            /**\n             * Send a message using currently opened ie streaming (using http-streaming or long-polling). <br>\n             *\n             * @param {string, Object} Message to send. This is an object, string message is saved in data member.\n             * @private\n             */\n            function _pushIE(message) {\n                if (_request.enableXDR && atmosphere.util.checkCORSSupport()) {\n                    var rq = _getPushRequest(message);\n                    // Do not reconnect since we are pushing.\n                    rq.reconnect = false;\n                    _jsonp(rq);\n                } else {\n                    _pushAjaxMessage(message);\n                }\n            }\n\n            /**\n             * Send a message using jsonp transport. <br>\n             *\n             * @param {string, Object} Message to send. This is an object, string message is saved in data member.\n             * @private\n             */\n            function _pushJsonp(message) {\n                _pushAjaxMessage(message);\n            }\n\n            function _getStringMessage(message) {\n                var msg = message;\n                if (typeof (msg) === 'object') {\n                    msg = message.data;\n                }\n                return msg;\n            }\n\n            /**\n             * Build request use to push message using method 'POST' <br>. Transport is defined as 'polling' and 'suspend' is set to false.\n             *\n             * @return {Object} Request object use to push message.\n             * @private\n             */\n            function _getPushRequest(message) {\n                var msg = _getStringMessage(message);\n\n                var rq = {\n                    connected: false,\n                    timeout: 60000,\n                    method: 'POST',\n                    url: _request.url,\n                    contentType: _request.contentType,\n                    headers: _request.headers,\n                    reconnect: true,\n                    callback: null,\n                    data: msg,\n                    suspend: false,\n                    maxRequest: -1,\n                    logLevel: 'info',\n                    requestCount: 0,\n                    withCredentials: _request.withCredentials,\n                    async: _request.async,\n                    transport: 'polling',\n                    isOpen: true,\n                    attachHeadersAsQueryString: true,\n                    enableXDR: _request.enableXDR,\n                    uuid: _request.uuid,\n                    dispatchUrl: _request.dispatchUrl,\n                    enableProtocol: false,\n                    messageDelimiter: '|',\n                    maxReconnectOnClose: _request.maxReconnectOnClose\n                };\n\n                if (typeof (message) === 'object') {\n                    rq = atmosphere.util.extend(rq, message);\n                }\n\n                return rq;\n            }\n\n            /**\n             * Send a message using currently opened websocket. <br>\n             *\n             */\n            function _pushWebSocket(message) {\n                var msg = atmosphere.util.isBinary(message) ? message : _getStringMessage(message);\n                var data;\n                try {\n                    if (_request.dispatchUrl != null) {\n                        data = _request.webSocketPathDelimiter + _request.dispatchUrl + _request.webSocketPathDelimiter + msg;\n                    } else {\n                        data = msg;\n                    }\n\n                    if (!_websocket.webSocketOpened) {\n                        atmosphere.util.error(\"WebSocket not connected.\");\n                        return;\n                    }\n\n                    _websocket.send(data);\n\n                } catch (e) {\n                    _websocket.onclose = function (message) {\n                    };\n                    _clearState();\n\n                    _reconnectWithFallbackTransport(\"Websocket failed. Downgrading to Comet and resending \" + message);\n                    _pushAjaxMessage(message);\n                }\n            }\n\n            function _localMessage(message) {\n                var m = atmosphere.util.parseJSON(message);\n                if (m.id !== guid) {\n                    if (typeof (_request.onLocalMessage) !== 'undefined') {\n                        _request.onLocalMessage(m.event);\n                    } else if (typeof (atmosphere.util.onLocalMessage) !== 'undefined') {\n                        atmosphere.util.onLocalMessage(m.event);\n                    }\n                }\n            }\n\n            function _prepareCallback(messageBody, state, errorCode, transport) {\n\n                _response.responseBody = messageBody;\n                _response.transport = transport;\n                _response.status = errorCode;\n                _response.state = state;\n\n                _invokeCallback();\n            }\n\n            function _readHeaders(xdr, request) {\n                if (!request.readResponsesHeaders) {\n                    if (!request.enableProtocol) {\n                        request.lastTimestamp = atmosphere.util.now();\n                        request.uuid = guid;\n                    }\n                }\n                else {\n                    try {\n                        var tempDate = xdr.getResponseHeader('X-Cache-Date');\n                        if (tempDate && tempDate != null && tempDate.length > 0) {\n                            request.lastTimestamp = tempDate.split(\" \").pop();\n                        }\n\n                        var tempUUID = xdr.getResponseHeader('X-Atmosphere-tracking-id');\n                        if (tempUUID && tempUUID != null) {\n                            request.uuid = tempUUID.split(\" \").pop();\n                        }\n                    } catch (e) {\n                    }\n                }\n            }\n\n            function _invokeFunction(response) {\n                _f(response, _request);\n                // Global\n                _f(response, atmosphere.util);\n            }\n\n            function _f(response, f) {\n                switch (response.state) {\n                    case \"messageReceived\":\n                        _requestCount = 0;\n                        if (typeof (f.onMessage) !== 'undefined')\n                            f.onMessage(response);\n                        break;\n                    case \"error\":\n                        if (typeof (f.onError) !== 'undefined')\n                            f.onError(response);\n                        break;\n                    case \"opening\":\n                        delete _request.closed;\n                        if (typeof (f.onOpen) !== 'undefined')\n                            f.onOpen(response);\n                        break;\n                    case \"messagePublished\":\n                        if (typeof (f.onMessagePublished) !== 'undefined')\n                            f.onMessagePublished(response);\n                        break;\n                    case \"re-connecting\":\n                        if (typeof (f.onReconnect) !== 'undefined')\n                            f.onReconnect(_request, response);\n                        break;\n                    case \"closedByClient\":\n                        if (typeof (f.onClientTimeout) !== 'undefined')\n                           f.onClientTimeout(_request);\n                        break;\n                    case \"re-opening\":\n                        delete _request.closed;\n                        if (typeof (f.onReopen) !== 'undefined')\n                            f.onReopen(_request, response);\n                        break;\n                    case \"fail-to-reconnect\":\n                        if (typeof (f.onFailureToReconnect) !== 'undefined')\n                            f.onFailureToReconnect(_request, response);\n                        break;\n                    case \"unsubscribe\":\n                    case \"closed\":\n                        var closed = typeof (_request.closed) !== 'undefined' ? _request.closed : false;\n                        if (typeof (f.onClose) !== 'undefined' && !closed)\n                            f.onClose(response);\n                        _request.closed = true;\n                        break;\n                }\n            }\n\n            function _invokeClose(wasOpen) {\n                if (_response.state !== 'closed') {\n                    _response.state = 'closed';\n                    _response.responseBody = \"\";\n                    _response.messages = [];\n                    _response.status = !wasOpen ? 501 : 200;\n                    _invokeCallback();\n                }\n            }\n\n            /**\n             * Invoke request callbacks.\n             *\n             * @private\n             */\n            function _invokeCallback() {\n                var call = function (index, func) {\n                    func(_response);\n                };\n\n                if (_localStorageService == null && _localSocketF != null) {\n                    _localSocketF(_response.responseBody);\n                }\n\n                _request.reconnect = _request.mrequest;\n\n                var isString = typeof (_response.responseBody) === 'string';\n                var messages = (isString && _request.trackMessageLength) ? (_response.messages.length > 0 ? _response.messages : ['']) : new Array(\n                    _response.responseBody);\n                for (var i = 0; i < messages.length; i++) {\n\n                    if (messages.length > 1 && messages[i].length === 0) {\n                        continue;\n                    }\n                    _response.responseBody = (isString) ? atmosphere.util.trim(messages[i]) : messages[i];\n\n                    if (_localStorageService == null && _localSocketF != null) {\n                        _localSocketF(_response.responseBody);\n                    }\n\n                    if (_response.responseBody.length === 0 && _response.state === \"messageReceived\") {\n                        continue;\n                    }\n\n                    _invokeFunction(_response);\n\n                    // Invoke global callbacks\n                    if (callbacks.length > 0) {\n                        if (_request.logLevel === 'debug') {\n                            atmosphere.util.debug(\"Invoking \" + callbacks.length + \" global callbacks: \" + _response.state);\n                        }\n                        try {\n                            atmosphere.util.each(callbacks, call);\n                        } catch (e) {\n                            atmosphere.util.log(_request.logLevel, [\"Callback exception\" + e]);\n                        }\n                    }\n\n                    // Invoke request callback\n                    if (typeof (_request.callback) === 'function') {\n                        if (_request.logLevel === 'debug') {\n                            atmosphere.util.debug(\"Invoking request callbacks\");\n                        }\n                        try {\n                            _request.callback(_response);\n                        } catch (e) {\n                            atmosphere.util.log(_request.logLevel, [\"Callback exception\" + e]);\n                        }\n                    }\n                }\n            }\n\n            this.subscribe = function (options) {\n                _subscribe(options);\n                _execute();\n            };\n\n            this.execute = function () {\n                _execute();\n            };\n\n            this.close = function () {\n                _close();\n            };\n\n            this.disconnect = function () {\n                _disconnect();\n            };\n\n            this.getUrl = function () {\n                return _request.url;\n            };\n\n            this.push = function (message, dispatchUrl) {\n                if (dispatchUrl != null) {\n                    var originalDispatchUrl = _request.dispatchUrl;\n                    _request.dispatchUrl = dispatchUrl;\n                    _push(message);\n                    _request.dispatchUrl = originalDispatchUrl;\n                } else {\n                    _push(message);\n                }\n            };\n\n            this.getUUID = function () {\n                return _request.uuid;\n            };\n\n            this.pushLocal = function (message) {\n                _intraPush(message);\n            };\n\n            this.enableProtocol = function (message) {\n                return _request.enableProtocol;\n            };\n\n            this.request = _request;\n            this.response = _response;\n        }\n    };\n\n    atmosphere.subscribe = function (url, callback, request) {\n        if (typeof (callback) === 'function') {\n            atmosphere.addCallback(callback);\n        }\n\n        // https://github.com/Atmosphere/atmosphere-javascript/issues/58\n        uuid = 0;\n\n        if (typeof (url) !== \"string\") {\n            request = url;\n        } else {\n            request.url = url;\n        }\n\n        var rq = new atmosphere.AtmosphereRequest(request);\n        rq.execute();\n\n        requests[requests.length] = rq;\n        return rq;\n    };\n\n    atmosphere.unsubscribe = function () {\n        if (requests.length > 0) {\n            var requestsClone = [].concat(requests);\n            for (var i = 0; i < requestsClone.length; i++) {\n                var rq = requestsClone[i];\n                rq.close();\n                clearTimeout(rq.response.request.id);\n            }\n        }\n        requests = [];\n        callbacks = [];\n    };\n\n    atmosphere.unsubscribeUrl = function (url) {\n        var idx = -1;\n        if (requests.length > 0) {\n            for (var i = 0; i < requests.length; i++) {\n                var rq = requests[i];\n\n                // Suppose you can subscribe once to an url\n                if (rq.getUrl() === url) {\n                    rq.close();\n                    clearTimeout(rq.response.request.id);\n                    idx = i;\n                    break;\n                }\n            }\n        }\n        if (idx >= 0) {\n            requests.splice(idx, 1);\n        }\n    };\n\n    atmosphere.addCallback = function (func) {\n        if (atmosphere.util.inArray(func, callbacks) === -1) {\n            callbacks.push(func);\n        }\n    };\n\n    atmosphere.removeCallback = function (func) {\n        var index = atmosphere.util.inArray(func, callbacks);\n        if (index !== -1) {\n            callbacks.splice(index, 1);\n        }\n    };\n\n    atmosphere.util = {\n        browser: {},\n\n        parseHeaders: function (headerString) {\n            var match, rheaders = /^(.*?):[ \\t]*([^\\r\\n]*)\\r?$/mg, headers = {};\n            while (match = rheaders.exec(headerString)) {\n                headers[match[1]] = match[2];\n            }\n            return headers;\n        },\n\n        now: function () {\n            return new Date().getTime();\n        },\n\n        isArray: function (array) {\n            return Object.prototype.toString.call(array) === \"[object Array]\";\n        },\n\n        inArray: function (elem, array) {\n            if (!Array.prototype.indexOf) {\n                var len = array.length;\n                for (var i = 0; i < len; ++i) {\n                    if (array[i] === elem) {\n                        return i;\n                    }\n                }\n                return -1;\n            }\n            return array.indexOf(elem);\n        },\n\n        isBinary: function (data) {\n            // True if data is an instance of Blob, ArrayBuffer or ArrayBufferView \n            return /^\\[object\\s(?:Blob|ArrayBuffer|.+Array)\\]$/.test(Object.prototype.toString.call(data));\n        },\n\n        isFunction: function (fn) {\n            return Object.prototype.toString.call(fn) === \"[object Function]\";\n        },\n\n        getAbsoluteURL: function (url) {\n            var div = document.createElement(\"div\");\n\n            // Uses an innerHTML property to obtain an absolute URL\n            div.innerHTML = '<a href=\"' + url + '\"/>';\n\n            // encodeURI and decodeURI are needed to normalize URL between IE and non-IE,\n            // since IE doesn't encode the href property value and return it - http://jsfiddle.net/Yq9M8/1/\n            return encodeURI(decodeURI(div.firstChild.href));\n        },\n\n        prepareURL: function (url) {\n            // Attaches a time stamp to prevent caching\n            var ts = atmosphere.util.now();\n            var ret = url.replace(/([?&])_=[^&]*/, \"$1_=\" + ts);\n\n            return ret + (ret === url ? (/\\?/.test(url) ? \"&\" : \"?\") + \"_=\" + ts : \"\");\n        },\n\n        trim: function (str) {\n            if (!String.prototype.trim) {\n                return str.toString().replace(/(?:(?:^|\\n)\\s+|\\s+(?:$|\\n))/g, \"\").replace(/\\s+/g, \" \");\n            } else {\n                return str.toString().trim();\n            }\n        },\n\n        param: function (params) {\n            var prefix, s = [];\n\n            function add(key, value) {\n                value = atmosphere.util.isFunction(value) ? value() : (value == null ? \"\" : value);\n                s.push(encodeURIComponent(key) + \"=\" + encodeURIComponent(value));\n            }\n\n            function buildParams(prefix, obj) {\n                var name;\n\n                if (atmosphere.util.isArray(obj)) {\n                    atmosphere.util.each(obj, function (i, v) {\n                        if (/\\[\\]$/.test(prefix)) {\n                            add(prefix, v);\n                        } else {\n                            buildParams(prefix + \"[\" + (typeof v === \"object\" ? i : \"\") + \"]\", v);\n                        }\n                    });\n                } else if (Object.prototype.toString.call(obj) === \"[object Object]\") {\n                    for (name in obj) {\n                        buildParams(prefix + \"[\" + name + \"]\", obj[name]);\n                    }\n                } else {\n                    add(prefix, obj);\n                }\n            }\n\n            for (prefix in params) {\n                buildParams(prefix, params[prefix]);\n            }\n\n            return s.join(\"&\").replace(/%20/g, \"+\");\n        },\n\n        storage: !!(window.localStorage && window.StorageEvent),\n\n        iterate: function (fn, interval) {\n            var timeoutId;\n\n            // Though the interval is 0 for real-time application, there is a delay between setTimeout calls\n            // For detail, see https://developer.mozilla.org/en/window.setTimeout#Minimum_delay_and_timeout_nesting\n            interval = interval || 0;\n\n            (function loop() {\n                timeoutId = setTimeout(function () {\n                    if (fn() === false) {\n                        return;\n                    }\n\n                    loop();\n                }, interval);\n            })();\n\n            return function () {\n                clearTimeout(timeoutId);\n            };\n        },\n\n        each: function (obj, callback, args) {\n            if (!obj) return;\n            var value, i = 0, length = obj.length, isArray = atmosphere.util.isArray(obj);\n\n            if (args) {\n                if (isArray) {\n                    for (; i < length; i++) {\n                        value = callback.apply(obj[i], args);\n\n                        if (value === false) {\n                            break;\n                        }\n                    }\n                } else {\n                    for (i in obj) {\n                        value = callback.apply(obj[i], args);\n\n                        if (value === false) {\n                            break;\n                        }\n                    }\n                }\n\n                // A special, fast, case for the most common use of each\n            } else {\n                if (isArray) {\n                    for (; i < length; i++) {\n                        value = callback.call(obj[i], i, obj[i]);\n\n                        if (value === false) {\n                            break;\n                        }\n                    }\n                } else {\n                    for (i in obj) {\n                        value = callback.call(obj[i], i, obj[i]);\n\n                        if (value === false) {\n                            break;\n                        }\n                    }\n                }\n            }\n\n            return obj;\n        },\n\n        extend: function (target) {\n            var i, options, name;\n\n            for (i = 1; i < arguments.length; i++) {\n                if ((options = arguments[i]) != null) {\n                    for (name in options) {\n                        target[name] = options[name];\n                    }\n                }\n            }\n\n            return target;\n        },\n        on: function (elem, type, fn) {\n            if (elem.addEventListener) {\n                elem.addEventListener(type, fn, false);\n            } else if (elem.attachEvent) {\n                elem.attachEvent(\"on\" + type, fn);\n            }\n        },\n        off: function (elem, type, fn) {\n            if (elem.removeEventListener) {\n                elem.removeEventListener(type, fn, false);\n            } else if (elem.detachEvent) {\n                elem.detachEvent(\"on\" + type, fn);\n            }\n        },\n\n        log: function (level, args) {\n            if (window.console) {\n                var logger = window.console[level];\n                if (typeof logger === 'function') {\n                    logger.apply(window.console, args);\n                }\n            }\n        },\n\n        warn: function () {\n            atmosphere.util.log('warn', arguments);\n        },\n\n        info: function () {\n            atmosphere.util.log('info', arguments);\n        },\n\n        debug: function () {\n            atmosphere.util.log('debug', arguments);\n        },\n\n        error: function () {\n            atmosphere.util.log('error', arguments);\n        },\n        xhr: function () {\n            try {\n                return new window.XMLHttpRequest();\n            } catch (e1) {\n                try {\n                    return new window.ActiveXObject(\"Microsoft.XMLHTTP\");\n                } catch (e2) {\n                }\n            }\n        },\n        parseJSON: function (data) {\n            return !data ? null : window.JSON && window.JSON.parse ? window.JSON.parse(data) : new Function(\"return \" + data)();\n        },\n        // http://github.com/flowersinthesand/stringifyJSON\n        stringifyJSON: function (value) {\n            var escapable = /[\\\\\\\"\\x00-\\x1f\\x7f-\\x9f\\u00ad\\u0600-\\u0604\\u070f\\u17b4\\u17b5\\u200c-\\u200f\\u2028-\\u202f\\u2060-\\u206f\\ufeff\\ufff0-\\uffff]/g, meta = {\n                '\\b': '\\\\b',\n                '\\t': '\\\\t',\n                '\\n': '\\\\n',\n                '\\f': '\\\\f',\n                '\\r': '\\\\r',\n                '\"': '\\\\\"',\n                '\\\\': '\\\\\\\\'\n            };\n\n            function quote(string) {\n                return '\"' + string.replace(escapable, function (a) {\n                    var c = meta[a];\n                    return typeof c === \"string\" ? c : \"\\\\u\" + (\"0000\" + a.charCodeAt(0).toString(16)).slice(-4);\n                }) + '\"';\n            }\n\n            function f(n) {\n                return n < 10 ? \"0\" + n : n;\n            }\n\n            return window.JSON && window.JSON.stringify ? window.JSON.stringify(value) : (function str(key, holder) {\n                var i, v, len, partial, value = holder[key], type = typeof value;\n\n                if (value && typeof value === \"object\" && typeof value.toJSON === \"function\") {\n                    value = value.toJSON(key);\n                    type = typeof value;\n                }\n\n                switch (type) {\n                    case \"string\":\n                        return quote(value);\n                    case \"number\":\n                        return isFinite(value) ? String(value) : \"null\";\n                    case \"boolean\":\n                        return String(value);\n                    case \"object\":\n                        if (!value) {\n                            return \"null\";\n                        }\n\n                        switch (Object.prototype.toString.call(value)) {\n                            case \"[object Date]\":\n                                return isFinite(value.valueOf()) ? '\"' + value.getUTCFullYear() + \"-\" + f(value.getUTCMonth() + 1) + \"-\"\n                                    + f(value.getUTCDate()) + \"T\" + f(value.getUTCHours()) + \":\" + f(value.getUTCMinutes()) + \":\" + f(value.getUTCSeconds())\n                                    + \"Z\" + '\"' : \"null\";\n                            case \"[object Array]\":\n                                len = value.length;\n                                partial = [];\n                                for (i = 0; i < len; i++) {\n                                    partial.push(str(i, value) || \"null\");\n                                }\n\n                                return \"[\" + partial.join(\",\") + \"]\";\n                            default:\n                                partial = [];\n                                for (i in value) {\n                                    if (hasOwn.call(value, i)) {\n                                        v = str(i, value);\n                                        if (v) {\n                                            partial.push(quote(i) + \":\" + v);\n                                        }\n                                    }\n                                }\n\n                                return \"{\" + partial.join(\",\") + \"}\";\n                        }\n                }\n            })(\"\", {\n                \"\": value\n            });\n        },\n\n        checkCORSSupport: function () {\n            if (atmosphere.util.browser.msie && !window.XDomainRequest) {\n                return true;\n            } else if (atmosphere.util.browser.opera && atmosphere.util.browser.version < 12.0) {\n                return true;\n            }\n\n            // KreaTV 4.1 -> 4.4\n            else if (atmosphere.util.trim(navigator.userAgent).slice(0, 16) === \"KreaTVWebKit/531\") {\n                return true;\n            }\n            // KreaTV 3.8\n            else if (atmosphere.util.trim(navigator.userAgent).slice(-7).toLowerCase() === \"kreatel\") {\n                return true;\n            }\n\n            // Force Android to use CORS as some version like 2.2.3 fail otherwise\n            var ua = navigator.userAgent.toLowerCase();\n            var isAndroid = ua.indexOf(\"android\") > -1;\n            if (isAndroid) {\n                return true;\n            }\n            return false;\n        }\n    };\n\n    guid = atmosphere.util.now();\n\n    // Browser sniffing\n    (function () {\n        var ua = navigator.userAgent.toLowerCase(),\n            match = /(chrome)[ \\/]([\\w.]+)/.exec(ua) ||\n                /(webkit)[ \\/]([\\w.]+)/.exec(ua) ||\n                /(opera)(?:.*version|)[ \\/]([\\w.]+)/.exec(ua) ||\n                /(msie) ([\\w.]+)/.exec(ua) ||\n                /(trident)(?:.*? rv:([\\w.]+)|)/.exec(ua) ||\n                ua.indexOf(\"compatible\") < 0 && /(mozilla)(?:.*? rv:([\\w.]+)|)/.exec(ua) ||\n                [];\n\n        atmosphere.util.browser[match[1] || \"\"] = true;\n        atmosphere.util.browser.version = match[2] || \"0\";\n        \n        // Trident is the layout engine of the Internet Explorer\n        // IE 11 has no \"MSIE: 11.0\" token\n        if (atmosphere.util.browser.trident) {\n        \tatmosphere.util.browser.msie = true;\n        }\n\n        // The storage event of Internet Explorer and Firefox 3 works strangely\n        if (atmosphere.util.browser.msie || (atmosphere.util.browser.mozilla && atmosphere.util.browser.version.split(\".\")[0] === \"1\")) {\n            atmosphere.util.storage = false;\n        }\n    })();\n\n    atmosphere.util.on(window, \"unload\", function (event) {\n        atmosphere.unsubscribe();\n    });\n\n    // Pressing ESC key in Firefox kills the connection\n    // for your information, this is fixed in Firefox 20\n    // https://bugzilla.mozilla.org/show_bug.cgi?id=614304\n    atmosphere.util.on(window, \"keypress\", function (event) {\n        if (event.charCode === 27 || event.keyCode === 27) {\n            if (event.preventDefault) {\n            \tevent.preventDefault();\n            }\n        }\n    });\n\n    atmosphere.util.on(window, \"offline\", function () {\n        atmosphere.unsubscribe();\n    });\n    window.atmosphere = atmosphere;\n})();\n/* jshint eqnull:true, noarg:true, noempty:true, eqeqeq:true, evil:true, laxbreak:true, undef:true, browser:true, indent:false, maxerr:50 */\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/atmosphere/bower.json",
    "content": "{\n  \"main\": \"atmosphere.js\", \n  \"version\": \"2.1.2\",\n  \"name\": \"atmosphere-js\"\n}"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/jquery/.bower.json",
    "content": "{\n  \"name\": \"jquery\",\n  \"version\": \"2.0.3\",\n  \"description\": \"jQuery component\",\n  \"keywords\": [\n    \"jquery\",\n    \"component\"\n  ],\n  \"main\": \"jquery.js\",\n  \"license\": \"MIT\",\n  \"homepage\": \"https://github.com/jquery/jquery-dist\",\n  \"_release\": \"2.0.3\",\n  \"_resolution\": {\n    \"type\": \"version\",\n    \"tag\": \"2.0.3\",\n    \"commit\": \"f852e631ba85af7da4ad7594785e122504e7b233\"\n  },\n  \"_source\": \"https://github.com/jquery/jquery-dist.git\",\n  \"_target\": \"2.0.3\",\n  \"_originalSource\": \"jquery\"\n}"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/jquery/.editorconfig",
    "content": "# This file is for unifying the coding style for different editors and IDEs\n# editorconfig.org\n\nroot = true\n\n\n[*]\nend_of_line = lf\ncharset = utf-8\ntrim_trailing_whitespace = true\ninsert_final_newline = true\n\n# Tabs in JS unless otherwise specified\n[**.js]\nindent_style = tab\n\n[Makefile]\nindent_style = tab\n\n\n[speed/**.html]\nindent_style = tab\n\n[speed/**.css]\nindent_style = tab\n\n[speed/benchmarker.js]\nindent_style = space\nindent_size = 2\n\n\n[test/**.xml]\nindent_style = tab\n\n[test/**.php]\nindent_style = tab\n\n[test/**.html]\nindent_style = tab\n\n[test/**.css]\nindent_style = space\nindent_size = 8\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/jquery/.gitmodules",
    "content": "[submodule \"src/sizzle\"]\n\tpath = src/sizzle\n\turl = git://github.com/jquery/sizzle.git\n[submodule \"test/qunit\"]\n\tpath = test/qunit\n\turl = git://github.com/jquery/qunit.git\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/jquery/.jshintrc",
    "content": "{\n\t\"boss\": true,\n\t\"curly\": true,\n\t\"eqeqeq\": true,\n\t\"eqnull\": true,\n\t\"expr\": true,\n\t\"immed\": true,\n\t\"noarg\": true,\n\t\"onevar\": true,\n\t\"quotmark\": \"double\",\n\t\"smarttabs\": true,\n\t\"trailing\": true,\n\t\"undef\": true,\n\t\"unused\": true,\n\n\t\"node\": true\n}"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/jquery/.mailmap",
    "content": "Adam Coulombe <me@adam.co> <adamcoulombe187@hotmail.com>\nAdam J. Sontag <ajpiano@ajpiano.com>\nAlexander Farkas <info@corrupt-system.de>\nAlexander Farkas <info@corrupt-system.de> <a.farkas.pm@googlemail.com>\nAlexis Abril <me@alexisabril.com> <alexis.abril@gmail.com>\nAndrew E Monat <amonat@gmail.com>\nAnton Matzneller <obhvsbypqghgc@gmail.com>\nAnton Matzneller <obhvsbypqghgc@gmail.com> <haskell_noob-github@yahoo.de>\nBatiste Bieler <batiste@gmail.com> <batiste.bieler@gmail.com>\nBenjamin Truyman <bentruyman@gmail.com>\nBrandon Aaron <brandon.aaron@gmail.com>\nCarl Danley <carldanley@gmail.com>\nCarl Fürstenberg <azatoth@gmail.com>\nCarl Fürstenberg <azatoth@gmail.com> <carl@excito.com>\nCharles McNulty <cmcnulty@kznf.com>\nColin Snover <colin@alpha.zetafleet.com> <github.com@zetafleet.com>\nCorey Frang <gnarf@gnarf.net>\nDan Heberden <danheberden@gmail.com>\nDaniel Chatfield <chatfielddaniel@gmail.com> <chatfielddaniel@googlemail.com>\nDaniel Gálvez <dgalvez@editablething.com>\nDanil Somsikov <danilasomsikov@gmail.com>\nDave Methvin <dave.methvin@gmail.com>\nDave Reed <dareed@microsoft.com>\nDavid Fox <dfoxinator@gmail.com> <dfox@snap-interactive.com>\nDevin Cooper <cooper.semantics@gmail.com> <dcooper@snap-interactive.com>\nDmitry Gusev <dmitry.gusev@gmail.com>\nEarle Castledine <mrspeaker@gmail.com>\nErick Ruiz de Chávez <erickrdch@gmail.com>\nGianni Alessandro Chiappetta <gianni@runlevel6.org>\nHeungsub Lee <h@subl.ee> <lee@heungsub.net>\nIraê Carvalho <irae@irae.pro.br>\nIsaac Z. Schlueter <i@izs.me>\nIsmail Khair <ismail.khair@gmail.com>\nJames Burke <jrburke@gmail.com>\nJames Padolsey <cla@padolsey.net> <jamespadolsey@gmail.com>\nJason Bedard <jason+jquery@jbedard.ca> <github@jbedard.ca>\nJay Merrifield <fracmak@gmail.com>\nJay Merrifield <fracmak@gmail.com> <jmerrifiel@gannett.com>\nJean Boussier <jean.boussier@gmail.com>\nJephte Clain <Jephte.Clain@univ-reunion.fr>\nJess Thrysoee <jess@thrysoee.dk>\nJoao Henrique de Andrade Bruni <joaohbruni@yahoo.com.br>\nJoe Presbrey <presbrey@gmail.com> <presbrey+jwp@gmail.com>\nJohn Resig <jeresig@gmail.com>\nJohn Resig <jeresig@gmail.com> <jeresig@Archimedes.local>\nJordan Boesch <jboesch26@gmail.com> <jordan@boedesign.com>\nJosh Varner <josh.varner@gmail.com> <josh.varner@gmail.com>\nJulian Aubourg <aubourg.julian@gmail.com>\nJulian Aubourg <aubourg.julian@gmail.com> <j@ubourg.net>\nJulian Aubourg <aubourg.julian@gmail.com> <Julian@.(none)>\nJörn Zaefferer <joern.zaefferer@gmail.com>\nJörn Zaefferer <joern.zaefferer@gmail.com> <joern.zaefferer@googlemail.com>\nJörn Zaefferer <joern.zaefferer@gmail.com> <JZA@.(none)>\nKarl Swedberg <kswedberg@gmail.com> <karl@englishrules.com>\nKris Borchers <kris.borchers@gmail.com>\nLee Carpenter <elcarpie@gmail.com>\nLi Xudong <istonelee@gmail.com>\nLouis-Rémi Babé <lrbabe@gmail.com>\nLouis-Rémi Babé <lrbabe@gmail.com> <louisremi@louisremi-laptop.(none)>\nLouis-Rémi Babé <lrbabe@gmail.com> <lrbabe@lrbabe-laptop.(none)>\nLouis-Rémi Babé <lrbabe@gmail.com> <lrbabe@lrbabe-laptop>\nMarcel Greter <marcel.greter@ocbnet.ch> <mgr@rtp.ch>\nMatthias Jäggli <matthias.jaeggli@gmail.com> <matthias.jaeggli@scout24.ch>\nMichael Murray <m@murz.net> <mmurray.wa@gmail.com>\nMichał Gołębiowski <m.goleb@gmail.com>\nMichał Gołębiowski <m.goleb@gmail.com> <michal.golebiowski@laboratorium.ee>\nMike Alsup <malsup@gmail.com>\nNguyen Phuc Lam <ruado1987@gmail.com>\nOleg Gaidarenko <markelog@gmail.com>\nRafaël Blais Masson <rafbmasson@gmail.com>\nRichard D. Worth <rdworth@gmail.com>\nRick Waldron <waldron.rick@gmail.com>\nRick Waldron <waldron.rick@gmail.com> <rick@bocoup.com>\nRobert Katić <robert.katic@gmail.com>\nRon Otten <r.j.g.otten@gmail.com>\nSai Lung Wong <sai.wong@huffingtonpost.com>\nScott González <scott.gonzalez@gmail.com> <sgonzale@sgonzale-laptop.local>\nScott Jehl <scott@scottjehl.com>\nSebastian Burkhard <sebi.burkhard@gmail.com>\nTimmy Willison <timmywillisn@gmail.com>\nTimmy Willison <timmywillisn@gmail.com> <tim.willison@thisismedium.com>\nTimo Tijhof <krinklemail@gmail.com>\nTJ Holowaychuk <tj@vision-media.ca>\nTom H Fuertes <tomfuertes@gmail.com>\nTom H Fuertes <tomfuertes@gmail.com> Tom H Fuertes <TomFuertes@gmail.com>\nTom Viner <github@viner.tv>\nXavi Ramirez <xavi.rmz@gmail.com>\nXavier Montillet <xavierm02.net@gmail.com>\nYehuda Katz <wycats@gmail.com>\nYehuda Katz <wycats@gmail.com> <wycats@12-189-125-93.att-inc.com>\nYehuda Katz <wycats@gmail.com> <wycats@mobile005.mycingular.net>\nYehuda Katz <wycats@gmail.com> <wycats@Yehuda-Katz.local>\nYiming He <yiminghe@gmail.com>\nTerry Jones <terry@jon.es> <terry@fluidinfo.com>\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/jquery/AUTHORS.txt",
    "content": "Authors ordered by first contribution.\n\nJohn Resig <jeresig@gmail.com>\nGilles van den Hoven <gilles0181@gmail.com>\nMichael Geary <mike@geary.com>\nStefan Petre <stefan.petre@gmail.com>\nYehuda Katz <wycats@gmail.com>\nCorey Jewett <cj@syntheticplayground.com>\nKlaus Hartl <klaus.hartl@googlemail.com>\nFranck Marcia <franck.marcia@gmail.com>\nJörn Zaefferer <joern.zaefferer@gmail.com>\nPaul Bakaus <paul.bakaus@googlemail.com>\nBrandon Aaron <brandon.aaron@gmail.com>\nMike Alsup <malsup@gmail.com>\nDave Methvin <dave.methvin@gmail.com>\nEd Engelhardt <edengelhardt@gmail.com>\nSean Catchpole <sean@sunsean.com>\nPaul Mclanahan <pmclanahan@gmail.com>\nDavid Serduke <davidserduke@gmail.com>\nRichard D. Worth <rdworth@gmail.com>\nScott González <scott.gonzalez@gmail.com>\nAriel Flesler <aflesler@gmail.com>\nJon Evans <jon@springyweb.com>\nTJ Holowaychuk <tj@vision-media.ca>\nMichael Bensoussan <mickey@seesmic.com>\nRobert Katić <robert.katic@gmail.com>\nLouis-Rémi Babé <lrbabe@gmail.com>\nEarle Castledine <mrspeaker@gmail.com>\nDamian Janowski <damian.janowski@gmail.com>\nRich Dougherty <rich@rd.gen.nz>\nKim Dalsgaard <kim@kimdalsgaard.com>\nAndrea Giammarchi <andrea.giammarchi@gmail.com>\nMark Gibson <jollytoad@gmail.com>\nKarl Swedberg <kswedberg@gmail.com>\nJustin Meyer <justinbmeyer@gmail.com>\nBen Alman <cowboy@rj3.net>\nJames Padolsey <cla@padolsey.net>\nDavid Petersen <public@petersendidit.com>\nBatiste Bieler <batiste@gmail.com>\nAlexander Farkas <info@corrupt-system.de>\nRick Waldron <waldron.rick@gmail.com>\nFilipe Fortes <filipe@fortes.com>\nNeeraj Singh <neerajdotname@gmail.com>\nPaul Irish <paul.irish@gmail.com>\nIraê Carvalho <irae@irae.pro.br>\nMatt Curry <matt@pseudocoder.com>\nMichael Monteleone <michael@michaelmonteleone.net>\nNoah Sloan <noah.sloan@gmail.com>\nTom Viner <github@viner.tv>\nDouglas Neiner <doug@pixelgraphics.us>\nAdam J. Sontag <ajpiano@ajpiano.com>\nDave Reed <dareed@microsoft.com>\nRalph Whitbeck <ralph.whitbeck@gmail.com>\nCarl Fürstenberg <azatoth@gmail.com>\nJacob Wright <jacwright@gmail.com>\nJ. Ryan Stinnett <jryans@gmail.com>\nHeungsub Lee <h@subl.ee>\nColin Snover <colin@alpha.zetafleet.com>\nRyan W Tenney <ryan@10e.us>\nRon Otten <r.j.g.otten@gmail.com>\nJephte Clain <Jephte.Clain@univ-reunion.fr>\nAnton Matzneller <obhvsbypqghgc@gmail.com>\nAlex Sexton <AlexSexton@gmail.com>\nDan Heberden <danheberden@gmail.com>\nHenri Wiechers <hwiechers@gmail.com>\nRussell Holbrook <russellholbrook@gmail.com>\nJulian Aubourg <aubourg.julian@gmail.com>\nGianni Alessandro Chiappetta <gianni@runlevel6.org>\nScott Jehl <scott@scottjehl.com>\nJames Burke <jrburke@gmail.com>\nJonas Pfenniger <jonas@pfenniger.name>\nXavi Ramirez <xavi.rmz@gmail.com>\nJared Grippe <jared@deadlyicon.com>\nSylvester Keil <sylvester@keil.or.at>\nBrandon Sterne <bsterne@mozilla.com>\nMathias Bynens <mathias@qiwi.be>\nTimmy Willison <timmywillisn@gmail.com>\nCorey Frang <gnarf@gnarf.net>\nAnton Kovalyov <anton@kovalyov.net>\nDavid Murdoch <musicisair@yahoo.com>\nJosh Varner <josh.varner@gmail.com>\nCharles McNulty <cmcnulty@kznf.com>\nJordan Boesch <jboesch26@gmail.com>\nJess Thrysoee <jess@thrysoee.dk>\nMichael Murray <m@murz.net>\nLee Carpenter <elcarpie@gmail.com>\nAlexis Abril <me@alexisabril.com>\nRob Morgan <robbym@gmail.com>\nJohn Firebaugh <john_firebaugh@bigfix.com>\nSam Bisbee <sam@sbisbee.com>\nGilmore Davidson <gilmoreorless@gmail.com>\nBrian Brennan <me@brianlovesthings.com>\nXavier Montillet <xavierm02.net@gmail.com>\nDaniel Pihlstrom <sciolist.se@gmail.com>\nSahab Yazdani <sahab.yazdani+github@gmail.com>\nScott Hughes <shughes@atlassian.com>\nMike Sherov <mike.sherov@gmail.com>\nGreg Hazel <ghazel@gmail.com>\nSchalk Neethling <schalk@ossreleasefeed.com>\nDenis Knauf <Denis.Knauf@gmail.com>\nTimo Tijhof <krinklemail@gmail.com>\nSteen Nielsen <swinedk@gmail.com>\nAnton Ryzhov <anton@ryzhov.me>\nShi Chuan <shichuanr@gmail.com>\nBerker Peksag <berker.peksag@gmail.com>\nToby Brain <tobyb@freshview.com>\nMatt Mueller <mattmuelle@gmail.com>\nDaniel Herman <daniel.c.herman@gmail.com>\nOleg Gaidarenko <markelog@gmail.com>\nRichard Gibson <richard.gibson@gmail.com>\nRafaël Blais Masson <rafbmasson@gmail.com>\nJoe Presbrey <presbrey@gmail.com>\nSindre Sorhus <sindresorhus@gmail.com>\nArne de Bree <arne@bukkie.nl>\nVladislav Zarakovsky <vlad.zar@gmail.com>\nAndrew E Monat <amonat@gmail.com>\nJoao Henrique de Andrade Bruni <joaohbruni@yahoo.com.br>\nDominik D. Geyer <dominik.geyer@gmail.com>\nMatt Farmer <matt@frmr.me>\nTrey Hunner <treyhunner@gmail.com>\nJason Moon <jmoon@socialcast.com>\nJeffery To <jeffery.to@gmail.com>\nKris Borchers <kris.borchers@gmail.com>\nVladimir Zhuravlev <private.face@gmail.com>\nJacob Thornton <jacobthornton@gmail.com>\nChad Killingsworth <chadkillingsworth@missouristate.edu>\nNowres Rafid <nowres.rafed@gmail.com>\nDavid Benjamin <davidben@mit.edu>\nUri Gilad <antishok@gmail.com>\nChris Faulkner <thefaulkner@gmail.com>\nElijah Manor <elijah.manor@gmail.com>\nDaniel Chatfield <chatfielddaniel@gmail.com>\nNikita Govorov <nikita.govorov@gmail.com>\nWesley Walser <wwalser@atlassian.com>\nMichael Pennisi <mike@mikepennisi.com>\nMarkus Staab <markus.staab@redaxo.de>\nBenjamin Truyman <bentruyman@gmail.com>\nJames Huston <james@jameshuston.net>\nIsmail Khair <ismail.khair@gmail.com>\nCarl Danley <carldanley@gmail.com>\nMichael Petrovich <michael.c.petrovich@gmail.com>\nCallum Macrae <callum@lynxphp.com>\nDavid Bonner <dbonner@cogolabs.com>\nErick Ruiz de Chávez <erickrdch@gmail.com>\nAkintayo Akinwunmi <aakinwunmi@judge.com>\nDave Riddle <david@joyvuu.com>\nGreg Lavallee <greglavallee@wapolabs.com>\nDaniel Gálvez <dgalvez@editablething.com>\nSai Lung Wong <sai.wong@huffingtonpost.com>\nTom H Fuertes <tomfuertes@gmail.com>\nRoland Eckl <eckl.roland@googlemail.com>\nJay Merrifield <fracmak@gmail.com>\nAllen J Schmidt Jr <cobrasoft@gmail.com>\nMarcel Greter <marcel.greter@ocbnet.ch>\nMatthias Jäggli <matthias.jaeggli@gmail.com>\nYiming He <yiminghe@gmail.com>\nDevin Cooper <cooper.semantics@gmail.com>\nBennett Sorbo <bsorbo@gmail.com>\nSebastian Burkhard <sebi.burkhard@gmail.com>\nDanil Somsikov <danilasomsikov@gmail.com>\nJean Boussier <jean.boussier@gmail.com>\nAdam Coulombe <me@adam.co>\nAndrew Plummer <plummer.andrew@gmail.com>\nNguyen Phuc Lam <ruado1987@gmail.com>\nDmitry Gusev <dmitry.gusev@gmail.com>\nMichał Gołębiowski <m.goleb@gmail.com>\nSteven Benner <admin@stevenbenner.com>\nLi Xudong <istonelee@gmail.com>\nRenato Oliveira dos Santos <ros3@cin.ufpe.br>\nJason Bedard <jason+jquery@jbedard.ca>\nKyle Robinson Young <kyle@dontkry.com>\nChris Talkington <chris@talkingtontech.com>\nJason Merino <jasonmerino@gmail.com>\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/jquery/CONTRIBUTING.md",
    "content": "# Contributing to jQuery\n\n1. [Getting Involved](#getting-involved)\n2. [Discussion](#discussion)\n3. [How To Report Bugs](#how-to-report-bugs)\n4. [Core Style Guide](#jquery-core-style-guide)\n5. [Tips For Bug Patching](#tips-for-bug-patching)\n\n\n\n## Getting Involved\n\nThere are a number of ways to get involved with the development of jQuery core. Even if you've never contributed code to an Open Source project before, we're always looking for help identifying bugs, writing and reducing test cases and documentation.\n\nThis is the best way to contribute to jQuery core. Please read through the full guide detailing [How to Report Bugs](#how-to-report-bugs).\n\n## Discussion\n\n### Forum and IRC\n\nThe jQuery core development team frequently tracks posts on the [jQuery Development Forum](http://forum.jquery.com/developing-jquery-core). If you have longer posts or questions please feel free to post them there. If you think you've found a bug please [file it in the bug tracker](#how-to-report-bugs).\n\nAdditionally most of the jQuery core development team can be found in the [#jquery-dev](http://webchat.freenode.net/?channels=jquery-dev) IRC channel on irc.freenode.net.\n\n### Weekly Status Meetings\n\nEvery week (unless otherwise noted) the jQuery core dev team has a meeting to discuss the progress of current work and to bring forward possible new blocker bugs for discussion.\n\nThe meeting is held in the [#jquery-meeting](http://webchat.freenode.net/?channels=jquery-meeting) IRC channel on irc.freenode.net at [Noon EST](http://www.timeanddate.com/worldclock/fixedtime.html?month=1&day=17&year=2011&hour=12&min=0&sec=0&p1=43) on Mondays.\n\n[Past Meeting Notes](https://docs.google.com/document/d/1MrLFvoxW7GMlH9KK-bwypn77cC98jUnz7sMW1rg_TP4/edit?hl=en)\n\n\n## How to Report Bugs\n\n### Make sure it is a jQuery bug\n\nMany bugs reported to our bug tracker are actually bugs in user code, not in jQuery code. Keep in mind that just because your code throws an error and the console points to a line number inside of jQuery, this does *not* mean the bug is a jQuery bug; more often than not, these errors result from providing incorrect arguments when calling a jQuery function.\n\nIf you are new to jQuery, it is usually a much better idea to ask for help first in the [Using jQuery Forum](http://forum.jquery.com/using-jquery) or the [jQuery IRC channel](http://webchat.freenode.net/?channels=%23jquery). You will get much quicker support, and you will help avoid tying up the jQuery team with invalid bug reports. These same resources can also be useful if you want to confirm that your bug is indeed a bug in jQuery before filing any tickets.\n\n\n### Disable any browser extensions\n\nMake sure you have reproduced the bug with all browser extensions and add-ons disabled, as these can sometimes cause things to break in interesting and unpredictable ways. Try using incognito, stealth or anonymous browsing modes.\n\n\n### Try the latest version of jQuery\n\nBugs in old versions of jQuery may have already been fixed. In order to avoid reporting known issues, make sure you are always testing against the [latest build](http://code.jquery.com/jquery.js).\n\n### Try an older version of jQuery\n\nSometimes, bugs are introduced in newer versions of jQuery that do not exist in previous versions. When possible, it can be useful to try testing with an older release.\n\n### Reduce, reduce, reduce!\n\nWhen you are experiencing a problem, the most useful thing you can possibly do is to [reduce your code](http://webkit.org/quality/reduction.html) to the bare minimum required to reproduce the issue. This makes it *much* easier to isolate and fix the offending code. Bugs that are reported without reduced test cases take on average 9001% longer to fix than bugs that are submitted with them, so you really should try to do this if at all possible.\n\n## jQuery Core Style Guide\n\nSee: [jQuery Core Style Guide](http://docs.jquery.com/JQuery_Core_Style_Guidelines)\n\n## Tips For Bug Patching\n\n\n### Environment: localhost w/ PHP, Node & Grunt\n\nStarting in jQuery 1.8, a newly overhauled development workflow has been introduced. In this new system, we rely on node & gruntjs to automate the building and validation of source code—while you write code.\n\nThe Ajax tests still depend on PHP running locally*, so make sure you have the following installed:\n\n* Some kind of localhost server program that supports PHP (any will do)\n* Node.js\n* NPM (comes with the latest version of Node.js)\n* Grunt (install with: `npm install grunt -g`\n\n\nMaintaining a list of platform specific instructions is outside of the scope of this document and there is plenty of existing documentation for the above technologies.\n\n* The PHP dependency will soon be shed in favor of an all-node solution.\n\n\n### Build a Local Copy of jQuery\n\nCreate a fork of the jQuery repo on github at http://github.com/jquery/jquery\n\nChange directory to your web root directory, whatever that might be:\n\n```bash\n$ cd /path/to/your/www/root/\n```\n\nClone your jQuery fork to work locally\n\n```bash\n$ git clone git@github.com:username/jquery.git\n```\n\nChange directory to the newly created dir jquery/\n\n```bash\n$ cd jquery\n```\n\nAdd the jQuery master as a remote. I label mine \"upstream\"\n\n```bash\n$ git remote add upstream git://github.com/jquery/jquery.git\n```\n\nGet in the habit of pulling in the \"upstream\" master to stay up to date as jQuery receives new commits\n\n```bash\n$ git pull upstream master\n```\n\nRun the Grunt tools:\n\n```bash\n$ grunt && grunt watch\n```\n\nNow open the jQuery test suite in a browser at http://localhost/test. If there is a port, be sure to include it.\n\nSuccess! You just built and tested jQuery!\n\n\n### Fix a bug from a ticket filed at bugs.jquery.com:\n\n**NEVER write your patches to the master branch** - it gets messy (I say this from experience!)\n\n**ALWAYS USE A \"TOPIC\" BRANCH!** Like so (#### = the ticket #)...\n\nMake sure you start with your up-to-date master:\n\n```bash\n$ git checkout master\n```\n\nCreate and checkout a new branch that includes the ticket #\n\n```bash\n$ git checkout -b bug_####\n\n# ( Explanation: this useful command will:\n# \"checkout\" a \"-b\" (branch) by the name of \"bug_####\"\n# or create it if it doesn't exist )\n```\n\nNow you're on branch: bug_####\n\nDetermine the module/file you'll be working in...\n\nOpen up the corresponding /test/unit/?????.js and add the initial failing unit tests. This may seem awkward at first, but in the long run it will make sense. To truly and efficiently patch a bug, you need to be working against that bug.\n\nNext, open the module files and make your changes\n\nRun http://localhost/test --> **ALL TESTS MUST PASS**\n\nOnce you're satisfied with your patch...\n\nStage the files to be tracked:\n\n```bash\n$ git add filename\n# (you can use \"git status\" to list the files you've changed)\n```\n\n\n( I recommend NEVER, EVER using \"git add . \" )\n\nOnce you've staged all of your changed files, go ahead and commit them\n\n```bash\n$ git commit -m \"Brief description of fix. Fixes #0000\"\n```\n\nFor a multiple line commit message, leave off the `-m \"description\"`.\n\nYou will then be led into vi (or the text editor that you have set up) to complete your commit message.\n\nThen, push your branch with the bug fix commits to your github fork\n\n```bash\n$ git push origin -u bug_####\n```\n\nBefore you tackle your next bug patch, return to the master:\n\n```bash\n$ git checkout master\n```\n\n\n\n### Test Suite Tips...\n\nDuring the process of writing your patch, you will run the test suite MANY times. You can speed up the process by narrowing the running test suite down to the module you are testing by either double clicking the title of the test or appending it to the url. The following examples assume you're working on a local repo, hosted on your localhost server.\n\nExample:\n\nhttp://localhost/test/?filter=css\n\nThis will only run the \"css\" module tests. This will significantly speed up your development and debugging.\n\n**ALWAYS RUN THE FULL SUITE BEFORE COMMITTING AND PUSHING A PATCH!**\n\n\n### jQuery 2.x supports the following browsers:\n\n* Chrome Current-1\n* Safari Current-1\n* Firefox Current-1\n* IE 9+\n* Opera Current-1\n\njQuery 1.x additionally supports IE6+.\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/jquery/Gruntfile.js",
    "content": "module.exports = function( grunt ) {\n\n\t\"use strict\";\n\n\tvar distpaths = [\n\t\t\t\"dist/jquery.js\",\n\t\t\t\"dist/jquery.min.map\",\n\t\t\t\"dist/jquery.min.js\"\n\t\t],\n\t\tgzip = require(\"gzip-js\"),\n\t\treadOptionalJSON = function( filepath ) {\n\t\t\tvar data = {};\n\t\t\ttry {\n\t\t\t\tdata = grunt.file.readJSON( filepath );\n\t\t\t} catch(e) {}\n\t\t\treturn data;\n\t\t},\n\t\tsrcHintOptions = readOptionalJSON(\"src/.jshintrc\");\n\n\t// The concatenated file won't pass onevar\n\t// But our modules can\n\tdelete srcHintOptions.onevar;\n\n\tgrunt.initConfig({\n\t\tpkg: grunt.file.readJSON(\"package.json\"),\n\t\tdst: readOptionalJSON(\"dist/.destination.json\"),\n\t\tcompare_size: {\n\t\t\tfiles: [ \"dist/jquery.js\", \"dist/jquery.min.js\" ],\n\t\t\toptions: {\n\t\t\t\tcompress: {\n\t\t\t\t\tgz: function( contents ) {\n\t\t\t\t\t\treturn gzip.zip( contents, {} ).length;\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tcache: \"dist/.sizecache.json\"\n\t\t\t}\n\t\t},\n\t\tselector: {\n\t\t\tdestFile: \"src/selector-sizzle.js\",\n\t\t\tapiFile: \"src/sizzle-jquery.js\",\n\t\t\tsrcFile: \"src/sizzle/dist/sizzle.js\"\n\t\t},\n\t\tbuild: {\n\t\t\tall: {\n\t\t\t\tdest: \"dist/jquery.js\",\n\t\t\t\tsrc: [\n\t\t\t\t\t\"src/intro.js\",\n\t\t\t\t\t\"src/core.js\",\n\t\t\t\t\t{ flag: \"sizzle\", src: \"src/selector-sizzle.js\", alt: \"src/selector-native.js\" },\n\t\t\t\t\t\"src/callbacks.js\",\n\t\t\t\t\t\"src/deferred.js\",\n\t\t\t\t\t\"src/support.js\",\n\t\t\t\t\t\"src/data.js\",\n\t\t\t\t\t\"src/queue.js\",\n\t\t\t\t\t\"src/attributes.js\",\n\t\t\t\t\t\"src/event.js\",\n\t\t\t\t\t\"src/traversing.js\",\n\t\t\t\t\t\"src/manipulation.js\",\n\t\t\t\t\t{ flag: \"wrap\", src: \"src/wrap.js\" },\n\t\t\t\t\t{ flag: \"css\", src: \"src/css.js\" },\n\t\t\t\t\t\"src/serialize.js\",\n\t\t\t\t\t{ flag: \"event-alias\", src: \"src/event-alias.js\" },\n\t\t\t\t\t{ flag: \"ajax\", src: \"src/ajax.js\" },\n\t\t\t\t\t{ flag: \"ajax/script\", src: \"src/ajax/script.js\", needs: [\"ajax\"]  },\n\t\t\t\t\t{ flag: \"ajax/jsonp\", src: \"src/ajax/jsonp.js\", needs: [ \"ajax\", \"ajax/script\" ]  },\n\t\t\t\t\t{ flag: \"ajax/xhr\", src: \"src/ajax/xhr.js\", needs: [\"ajax\"]  },\n\t\t\t\t\t{ flag: \"effects\", src: \"src/effects.js\", needs: [\"css\"] },\n\t\t\t\t\t{ flag: \"offset\", src: \"src/offset.js\", needs: [\"css\"] },\n\t\t\t\t\t{ flag: \"dimensions\", src: \"src/dimensions.js\", needs: [\"css\"] },\n\t\t\t\t\t{ flag: \"deprecated\", src: \"src/deprecated.js\" },\n\n\t\t\t\t\t\"src/exports.js\",\n\t\t\t\t\t\"src/outro.js\"\n\t\t\t\t]\n\t\t\t}\n\t\t},\n\n\t\tjshint: {\n\t\t\tdist: {\n\t\t\t\tsrc: [ \"dist/jquery.js\" ],\n\t\t\t\toptions: srcHintOptions\n\t\t\t},\n\t\t\tgrunt: {\n\t\t\t\tsrc: [ \"Gruntfile.js\" ],\n\t\t\t\toptions: {\n\t\t\t\t\tjshintrc: \".jshintrc\"\n\t\t\t\t}\n\t\t\t},\n\t\t\ttests: {\n\t\t\t\t// TODO: Once .jshintignore is supported, use that instead.\n\t\t\t\t// issue located here: https://github.com/gruntjs/grunt-contrib-jshint/issues/1\n\t\t\t\tsrc: [ \"test/data/{test,testinit,testrunner}.js\", \"test/unit/**/*.js\" ],\n\t\t\t\toptions: {\n\t\t\t\t\tjshintrc: \"test/.jshintrc\"\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\ttestswarm: {\n\t\t\ttests: \"ajax attributes callbacks core css data deferred dimensions effects event manipulation offset queue selector serialize support traversing Sizzle\".split(\" \")\n\t\t},\n\n\t\twatch: {\n\t\t\tfiles: [ \"<%= jshint.grunt.src %>\", \"<%= jshint.tests.src %>\", \"src/**/*.js\" ],\n\t\t\ttasks: \"dev\"\n\t\t},\n\n\t\t\"pre-uglify\": {\n\t\t\tall: {\n\t\t\t\tfiles: {\n\t\t\t\t\t\"dist/jquery.pre-min.js\": [ \"dist/jquery.js\" ]\n\t\t\t\t},\n\t\t\t\toptions: {\n\t\t\t\t\tbanner: \"\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\" + // banner line size must be preserved\n\t\t\t\t\t\t\"/*! jQuery v<%= pkg.version %> | \" +\n\t\t\t\t\t\t\"(c) 2005, 2013 jQuery Foundation, Inc. | \" +\n\t\t\t\t\t\t\"jquery.org/license\\n\" +\n\t\t\t\t\t\t\"//@ sourceMappingURL=jquery.min.map\\n\" +\n\t\t\t\t\t\t\"*/\\n\"\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\tuglify: {\n\t\t\tall: {\n\t\t\t\tfiles: {\n\t\t\t\t\t\"dist/jquery.min.js\": [ \"dist/jquery.pre-min.js\" ]\n\t\t\t\t},\n\t\t\t\toptions: {\n\t\t\t\t\t// Keep our hard-coded banner\n\t\t\t\t\tpreserveComments: \"some\",\n\t\t\t\t\tsourceMap: \"dist/jquery.min.map\",\n\t\t\t\t\tsourceMappingURL: \"jquery.min.map\",\n\t\t\t\t\treport: \"min\",\n\t\t\t\t\tbeautify: {\n\t\t\t\t\t\tascii_only: true\n\t\t\t\t\t},\n\t\t\t\t\tcompress: {\n\t\t\t\t\t\thoist_funs: false,\n\t\t\t\t\t\tjoin_vars: false,\n\t\t\t\t\t\tloops: false,\n\t\t\t\t\t\tunused: false\n\t\t\t\t\t},\n\t\t\t\t\tmangle: {\n\t\t\t\t\t\t// saves some bytes when gzipped\n\t\t\t\t\t\texcept: [ \"undefined\" ]\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t\"post-uglify\": {\n\t\t\tall: {\n\t\t\t\tfiles: {\n\t\t\t\t\t\"dist/jquery.min.map.tmp\": [ \"dist/jquery.min.map\" ],\n\t\t\t\t\t\"dist/jquery.min.js.tmp\": [ \"dist/jquery.min.js\" ]\n\t\t\t\t},\n\t\t\t\toptions: {\n\t\t\t\t\ttempFiles: [ \"dist/jquery.min.map.tmp\", \"dist/jquery.min.js.tmp\", \"dist/jquery.pre-min.js\" ]\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t});\n\n\tgrunt.registerTask( \"testswarm\", function( commit, configFile ) {\n\t\tvar jobName,\n\t\t\ttestswarm = require( \"testswarm\" ),\n\t\t\truns = {},\n\t\t\tdone = this.async(),\n\t\t\tpull = /PR-(\\d+)/.exec( commit ),\n\t\t\tconfig = grunt.file.readJSON( configFile ).jquery,\n\t\t\ttests = grunt.config([ this.name, \"tests\" ]);\n\n\t\tif ( pull ) {\n\t\t\tjobName = \"jQuery pull <a href='https://github.com/jquery/jquery/pull/\" +\n\t\t\t\tpull[ 1 ] + \"'>#\" + pull[ 1 ] + \"</a>\";\n\t\t} else {\n\t\t\tjobName = \"jQuery commit #<a href='https://github.com/jquery/jquery/commit/\" +\n\t\t\t\tcommit + \"'>\" + commit.substr( 0, 10 ) + \"</a>\";\n\t\t}\n\n\t\ttests.forEach(function( test ) {\n\t\t\truns[test] = config.testUrl + commit + \"/test/index.html?module=\" + test;\n\t\t});\n\n\t\t// TODO: create separate job for git/git2 so we can do different browsersets\n\t\ttestswarm.createClient( {\n\t\t\turl: config.swarmUrl,\n\t\t\tpollInterval: 10000,\n\t\t\ttimeout: 1000 * 60 * 30\n\t\t} )\n\t\t.addReporter( testswarm.reporters.cli )\n\t\t.auth( {\n\t\t\tid: config.authUsername,\n\t\t\ttoken: config.authToken\n\t\t})\n\t\t.addjob(\n\t\t\t{\n\t\t\t\tname: jobName,\n\t\t\t\truns: runs,\n\t\t\t\trunMax: config.runMax,\n\t\t\t\tbrowserSets: \"popular-no-old-ie\"\n\t\t\t}, function( err, passed ) {\n\t\t\t\tif ( err ) {\n\t\t\t\t\tgrunt.log.error( err );\n\t\t\t\t}\n\t\t\t\tdone( passed );\n\t\t\t}\n\t\t);\n\t});\n\n\tgrunt.registerTask( \"selector\", \"Build Sizzle-based selector module\", function() {\n\n\t\tvar cfg = grunt.config(\"selector\"),\n\t\t\tname = cfg.destFile,\n\t\t\tsizzle = {\n\t\t\t\tapi: grunt.file.read( cfg.apiFile ),\n\t\t\t\tsrc: grunt.file.read( cfg.srcFile )\n\t\t\t},\n\t\t\tcompiled, parts;\n\n\t\t/**\n\n\t\t\tsizzle-jquery.js -> sizzle between \"EXPOSE\" blocks,\n\t\t\treplace define & window.Sizzle assignment\n\n\n\t\t\t// EXPOSE\n\t\t\tif ( typeof define === \"function\" && define.amd ) {\n\t\t\t\tdefine(function() { return Sizzle; });\n\t\t\t} else {\n\t\t\t\twindow.Sizzle = Sizzle;\n\t\t\t}\n\t\t\t// EXPOSE\n\n\t\t\tBecomes...\n\n\t\t\tSizzle.attr = jQuery.attr;\n\t\t\tjQuery.find = Sizzle;\n\t\t\tjQuery.expr = Sizzle.selectors;\n\t\t\tjQuery.expr[\":\"] = jQuery.expr.pseudos;\n\t\t\tjQuery.unique = Sizzle.uniqueSort;\n\t\t\tjQuery.text = Sizzle.getText;\n\t\t\tjQuery.isXMLDoc = Sizzle.isXML;\n\t\t\tjQuery.contains = Sizzle.contains;\n\n\t\t */\n\n\t\t// Break into 3 pieces\n\t\tparts = sizzle.src.split(\"// EXPOSE\");\n\t\t// Replace the if/else block with api\n\t\tparts[1] = sizzle.api;\n\t\t// Rejoin the pieces\n\t\tcompiled = parts.join(\"\");\n\n\t\tgrunt.verbose.writeln(\"Injected \" + cfg.apiFile + \" into \" + cfg.srcFile);\n\n\t\t// Write concatenated source to file, and ensure newline-only termination\n\t\tgrunt.file.write( name, compiled.replace( /\\x0d\\x0a/g, \"\\x0a\" ) );\n\n\t\t// Fail task if errors were logged.\n\t\tif ( this.errorCount ) {\n\t\t\treturn false;\n\t\t}\n\n\t\t// Otherwise, print a success message.\n\t\tgrunt.log.writeln( \"File '\" + name + \"' created.\" );\n\t});\n\n\t// Special \"alias\" task to make custom build creation less grawlix-y\n\tgrunt.registerTask( \"custom\", function() {\n\t\tvar done = this.async(),\n\t\t\t\targs = [].slice.call(arguments),\n\t\t\t\tmodules = args.length ? args[0].replace(/,/g, \":\") : \"\";\n\n\n\t\t// Translation example\n\t\t//\n\t\t//   grunt custom:+ajax,-dimensions,-effects,-offset\n\t\t//\n\t\t// Becomes:\n\t\t//\n\t\t//   grunt build:*:*:+ajax:-dimensions:-effects:-offset\n\n\t\tgrunt.log.writeln( \"Creating custom build...\\n\" );\n\n\t\tgrunt.util.spawn({\n\t\t\tgrunt: true,\n\t\t\targs: [ \"build:*:*:\" + modules, \"pre-uglify\", \"uglify\", \"dist\" ]\n\t\t}, function( err, result ) {\n\t\t\tif ( err ) {\n\t\t\t\tgrunt.verbose.error();\n\t\t\t\tdone( err );\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tgrunt.log.writeln( result.stdout.replace(\"Done, without errors.\", \"\") );\n\n\t\t\tdone();\n\t\t});\n\t});\n\n\t// Special concat/build task to handle various jQuery build requirements\n\tgrunt.registerMultiTask(\n\t\t\"build\",\n\t\t\"Concatenate source (include/exclude modules with +/- flags), embed date/version\",\n\t\tfunction() {\n\n\t\t\t// Concat specified files.\n\t\t\tvar compiled = \"\",\n\t\t\t\tmodules = this.flags,\n\t\t\t\toptIn = !modules[\"*\"],\n\t\t\t\texplicit = optIn || Object.keys(modules).length > 1,\n\t\t\t\tname = this.data.dest,\n\t\t\t\tsrc = this.data.src,\n\t\t\t\tdeps = {},\n\t\t\t\texcluded = {},\n\t\t\t\tversion = grunt.config( \"pkg.version\" ),\n\t\t\t\texcluder = function( flag, needsFlag ) {\n\t\t\t\t\t// optIn defaults implicit behavior to weak exclusion\n\t\t\t\t\tif ( optIn && !modules[ flag ] && !modules[ \"+\" + flag ] ) {\n\t\t\t\t\t\texcluded[ flag ] = false;\n\t\t\t\t\t}\n\n\t\t\t\t\t// explicit or inherited strong exclusion\n\t\t\t\t\tif ( excluded[ needsFlag ] || modules[ \"-\" + flag ] ) {\n\t\t\t\t\t\texcluded[ flag ] = true;\n\n\t\t\t\t\t// explicit inclusion overrides weak exclusion\n\t\t\t\t\t} else if ( excluded[ needsFlag ] === false &&\n\t\t\t\t\t\t( modules[ flag ] || modules[ \"+\" + flag ] ) ) {\n\n\t\t\t\t\t\tdelete excluded[ needsFlag ];\n\n\t\t\t\t\t\t// ...all the way down\n\t\t\t\t\t\tif ( deps[ needsFlag ] ) {\n\t\t\t\t\t\t\tdeps[ needsFlag ].forEach(function( subDep ) {\n\t\t\t\t\t\t\t\tmodules[ needsFlag ] = true;\n\t\t\t\t\t\t\t\texcluder( needsFlag, subDep );\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// append commit id to version\n\t\t\tif ( process.env.COMMIT ) {\n\t\t\t\tversion += \" \" + process.env.COMMIT;\n\t\t\t}\n\n\t\t\t// figure out which files to exclude based on these rules in this order:\n\t\t\t//  dependency explicit exclude\n\t\t\t//  > explicit exclude\n\t\t\t//  > explicit include\n\t\t\t//  > dependency implicit exclude\n\t\t\t//  > implicit exclude\n\t\t\t// examples:\n\t\t\t//  *                  none (implicit exclude)\n\t\t\t//  *:*                all (implicit include)\n\t\t\t//  *:*:-css           all except css and dependents (explicit > implicit)\n\t\t\t//  *:*:-css:+effects  same (excludes effects because explicit include is trumped by explicit exclude of dependency)\n\t\t\t//  *:+effects         none except effects and its dependencies (explicit include trumps implicit exclude of dependency)\n\t\t\tsrc.forEach(function( filepath ) {\n\t\t\t\tvar flag = filepath.flag;\n\n\t\t\t\tif ( flag ) {\n\n\t\t\t\t\texcluder(flag);\n\n\t\t\t\t\t// check for dependencies\n\t\t\t\t\tif ( filepath.needs ) {\n\t\t\t\t\t\tdeps[ flag ] = filepath.needs;\n\t\t\t\t\t\tfilepath.needs.forEach(function( needsFlag ) {\n\t\t\t\t\t\t\texcluder( flag, needsFlag );\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// append excluded modules to version\n\t\t\tif ( Object.keys( excluded ).length ) {\n\t\t\t\tversion += \" -\" + Object.keys( excluded ).join( \",-\" );\n\t\t\t\t// set pkg.version to version with excludes, so minified file picks it up\n\t\t\t\tgrunt.config.set( \"pkg.version\", version );\n\t\t\t}\n\n\n\t\t\t// conditionally concatenate source\n\t\t\tsrc.forEach(function( filepath ) {\n\t\t\t\tvar flag = filepath.flag,\n\t\t\t\t\t\tspecified = false,\n\t\t\t\t\t\tomit = false,\n\t\t\t\t\t\tmessages = [];\n\n\t\t\t\tif ( flag ) {\n\t\t\t\t\tif ( excluded[ flag ] !== undefined ) {\n\t\t\t\t\t\tmessages.push([\n\t\t\t\t\t\t\t( \"Excluding \" + flag ).red,\n\t\t\t\t\t\t\t( \"(\" + filepath.src + \")\" ).grey\n\t\t\t\t\t\t]);\n\t\t\t\t\t\tspecified = true;\n\t\t\t\t\t\tomit = !filepath.alt;\n\t\t\t\t\t\tif ( !omit ) {\n\t\t\t\t\t\t\tflag += \" alternate\";\n\t\t\t\t\t\t\tfilepath.src = filepath.alt;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif ( excluded[ flag ] === undefined ) {\n\t\t\t\t\t\tmessages.push([\n\t\t\t\t\t\t\t( \"Including \" + flag ).green,\n\t\t\t\t\t\t\t( \"(\" + filepath.src + \")\" ).grey\n\t\t\t\t\t\t]);\n\n\t\t\t\t\t\t// If this module was actually specified by the\n\t\t\t\t\t\t// builder, then set the flag to include it in the\n\t\t\t\t\t\t// output list\n\t\t\t\t\t\tif ( modules[ \"+\" + flag ] ) {\n\t\t\t\t\t\t\tspecified = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tfilepath = filepath.src;\n\n\t\t\t\t\t// Only display the inclusion/exclusion list when handling\n\t\t\t\t\t// an explicit list.\n\t\t\t\t\t//\n\t\t\t\t\t// Additionally, only display modules that have been specified\n\t\t\t\t\t// by the user\n\t\t\t\t\tif ( explicit && specified ) {\n\t\t\t\t\t\tmessages.forEach(function( message ) {\n\t\t\t\t\t\t\tgrunt.log.writetableln( [ 27, 30 ], message );\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif ( !omit ) {\n\t\t\t\t\tcompiled += grunt.file.read( filepath );\n\t\t\t\t}\n\t\t\t});\n\n\t\t\t// Embed Version\n\t\t\t// Embed Date\n\t\t\tcompiled = compiled.replace( /@VERSION/g, version )\n\t\t\t\t// yyyy-mm-ddThh:mmZ\n\t\t\t\t.replace( /@DATE/g, ( new Date() ).toISOString().replace( /:\\d+\\.\\d+Z$/, \"Z\" ) );\n\n\t\t\t// Write concatenated source to file\n\t\t\tgrunt.file.write( name, compiled );\n\n\t\t\t// Fail task if errors were logged.\n\t\t\tif ( this.errorCount ) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\t// Otherwise, print a success message.\n\t\t\tgrunt.log.writeln( \"File '\" + name + \"' created.\" );\n\t\t});\n\n\t// Process files for distribution\n\tgrunt.registerTask( \"dist\", function() {\n\t\tvar stored, flags, paths, fs, nonascii;\n\n\t\t// Check for stored destination paths\n\t\t// ( set in dist/.destination.json )\n\t\tstored = Object.keys( grunt.config( \"dst\" ) );\n\n\t\t// Allow command line input as well\n\t\tflags = Object.keys( this.flags );\n\n\t\t// Combine all output target paths\n\t\tpaths = [].concat( stored, flags ).filter(function( path ) {\n\t\t\treturn path !== \"*\";\n\t\t});\n\n\t\t// Ensure the dist files are pure ASCII\n\t\tfs = require( \"fs\" );\n\t\tnonascii = false;\n\n\t\tdistpaths.forEach(function( filename ) {\n\t\t\tvar i, c,\n\t\t\t\ttext = fs.readFileSync( filename, \"utf8\" );\n\n\t\t\t// Ensure files use only \\n for line endings, not \\r\\n\n\t\t\tif ( /\\x0d\\x0a/.test( text ) ) {\n\t\t\t\tgrunt.log.writeln( filename + \": Incorrect line endings (\\\\r\\\\n)\" );\n\t\t\t\tnonascii = true;\n\t\t\t}\n\n\t\t\t// Ensure only ASCII chars so script tags don't need a charset attribute\n\t\t\tif ( text.length !== Buffer.byteLength( text, \"utf8\" ) ) {\n\t\t\t\tgrunt.log.writeln( filename + \": Non-ASCII characters detected:\" );\n\t\t\t\tfor ( i = 0; i < text.length; i++ ) {\n\t\t\t\t\tc = text.charCodeAt( i );\n\t\t\t\t\tif ( c > 127 ) {\n\t\t\t\t\t\tgrunt.log.writeln( \"- position \" + i + \": \" + c );\n\t\t\t\t\t\tgrunt.log.writeln( \"-- \" + text.substring( i - 20, i + 20 ) );\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tnonascii = true;\n\t\t\t}\n\n\t\t\t// Modify map/min so that it points to files in the same folder;\n\t\t\t// see https://github.com/mishoo/UglifyJS2/issues/47\n\t\t\tif ( /\\.map$/.test( filename ) ) {\n\t\t\t\ttext = text.replace( /\"dist\\//g, \"\\\"\" );\n\t\t\t\tfs.writeFileSync( filename, text, \"utf-8\" );\n\n\t\t\t// Use our hard-coded sourceMap directive instead of the autogenerated one (#13274; #13776)\n\t\t\t} else if ( /\\.min\\.js$/.test( filename ) ) {\n\t\t\t\ti = 0;\n\t\t\t\ttext = text.replace( /(?:\\/\\*|)\\n?\\/\\/@\\s*sourceMappingURL=.*(\\n\\*\\/|)/g,\n\t\t\t\t\tfunction( match ) {\n\t\t\t\t\t\tif ( i++ ) {\n\t\t\t\t\t\t\treturn \"\";\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn match;\n\t\t\t\t\t});\n\t\t\t\tfs.writeFileSync( filename, text, \"utf-8\" );\n\t\t\t}\n\n\t\t\t// Optionally copy dist files to other locations\n\t\t\tpaths.forEach(function( path ) {\n\t\t\t\tvar created;\n\n\t\t\t\tif ( !/\\/$/.test( path ) ) {\n\t\t\t\t\tpath += \"/\";\n\t\t\t\t}\n\n\t\t\t\tcreated = path + filename.replace( \"dist/\", \"\" );\n\t\t\t\tgrunt.file.write( created, text );\n\t\t\t\tgrunt.log.writeln( \"File '\" + created + \"' created.\" );\n\t\t\t});\n\t\t});\n\n\t\treturn !nonascii;\n\t});\n\n\t// Work around grunt-contrib-uglify sourceMap issues (jQuery #13776)\n\tgrunt.registerMultiTask( \"pre-uglify\", function() {\n\t\tvar banner = this.options().banner;\n\n\t\tthis.files.forEach(function( mapping ) {\n\t\t\t// Join src\n\t\t\tvar input = mapping.src.map(function( file ) {\n\t\t\t\tvar contents = grunt.file.read( file );\n\n\t\t\t\t// Strip banners\n\t\t\t\treturn contents\n\t\t\t\t\t// Remove the main jQuery banner, it'll be replaced by the new banner anyway.\n\t\t\t\t\t.replace( /^\\/\\*!(?:.|\\n)*?\\*\\/\\n?/g, \"\" )\n\t\t\t\t\t// Strip other banners preserving line count.\n\t\t\t\t\t.replace( /^\\/\\*!(?:.|\\n)*?\\*\\/\\n?/gm, function ( match ) {\n\t\t\t\t\t\treturn match.replace( /[^\\n]/gm, \"\" );\n\t\t\t\t\t});\n\t\t\t}).join(\"\\n\");\n\n\t\t\t// Write temp file (with optional banner)\n\t\t\tgrunt.file.write( mapping.dest, ( banner || \"\" ) + input );\n\t\t});\n\t});\n\n\t// Change the map file to point back to jquery.js instead of jquery.pre-min.js.\n\t// The problem is caused by the pre-uglify task.\n\t// Also, remove temporary files.\n\tgrunt.registerMultiTask( \"post-uglify\", function() {\n\t\tvar fs = require( \"fs\" );\n\n\t\tthis.files.forEach(function( mapping ) {\n\t\t\tvar mapFileName = mapping.src[ 0 ];\n\n\t\t\t// Rename the file to a temporary name.\n\t\t\tfs.renameSync( mapFileName, mapping.dest);\n\t\t\tgrunt.file.write( mapFileName, grunt.file.read( mapping.dest )\n\t\t\t\t// The uglify task erroneously prepends dist/ to file names.\n\t\t\t\t.replace( /\"dist\\//g, \"\\\"\" )\n\t\t\t\t// Refer to the source jquery.js, not the temporary jquery.pre-min.js.\n\t\t\t\t.replace( /\\.pre-min\\./g, \".\" )\n\t\t\t\t// There's already a pragma at the beginning of the file, remove the one at the end.\n\t\t\t\t.replace( /\\/\\/@ sourceMappingURL=jquery\\.min\\.map$/g, \"\" ));\n\t\t});\n\n\t\t// Remove temporary files.\n\t\tthis.options().tempFiles.forEach(function( fileName ) {\n\t\t\tfs.unlink( fileName );\n\t\t});\n\t});\n\n\t// Load grunt tasks from NPM packages\n\tgrunt.loadNpmTasks(\"grunt-compare-size\");\n\tgrunt.loadNpmTasks(\"grunt-git-authors\");\n\tgrunt.loadNpmTasks(\"grunt-update-submodules\");\n\tgrunt.loadNpmTasks(\"grunt-contrib-watch\");\n\tgrunt.loadNpmTasks(\"grunt-contrib-jshint\");\n\tgrunt.loadNpmTasks(\"grunt-contrib-uglify\");\n\n\t// Default grunt\n\tgrunt.registerTask( \"default\", [ \"update_submodules\", \"selector\", \"build:*:*\", \"jshint\", \"pre-uglify\", \"uglify\", \"post-uglify\", \"dist:*\", \"compare_size\" ] );\n\n\t// Short list as a high frequency watch task\n\tgrunt.registerTask( \"dev\", [ \"selector\", \"build:*:*\", \"jshint\" ] );\n};\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/jquery/MIT-LICENSE.txt",
    "content": "Copyright 2013 jQuery Foundation and other contributors\nhttp://jquery.com/\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n\"Software\"), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\nLIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\nOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\nWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/jquery/README.md",
    "content": "[jQuery](http://jquery.com/) - New Wave JavaScript\n==================================================\n\nContribution Guides\n--------------------------------------\n\nIn the spirit of open source software development, jQuery always encourages community code contribution. To help you get started and before you jump into writing code, be sure to read these important contribution guidelines thoroughly:\n\n1. [Getting Involved](http://docs.jquery.com/Getting_Involved)\n2. [Core Style Guide](http://docs.jquery.com/JQuery_Core_Style_Guidelines)\n3. [Tips For Bug Patching](http://docs.jquery.com/Tips_for_jQuery_Bug_Patching)\n\n\nWhat you need to build your own jQuery\n--------------------------------------\n\nIn order to build jQuery, you need to have Node.js/npm latest and git 1.7 or later.\n(Earlier versions might work OK, but are not tested.)\n\nWindows users have two options:\n\n1. Install [msysgit](https://code.google.com/p/msysgit/) (Full installer for official Git) and a\n   [binary version of Node.js](http://nodejs.org). Make sure all two packages are installed to the same\n   location (by default, this is C:\\Program Files\\Git).\n2. Install [Cygwin](http://cygwin.com/) (make sure you install the git and which packages), and\n   a [binary version of Node.js](http://nodejs.org/).\n\nMac OS users should install Xcode (comes on your Mac OS install DVD, or downloadable from\n[Apple's Xcode site](http://developer.apple.com/technologies/xcode.html)) and\n[Homebrew](http://mxcl.github.com/homebrew/). Once Homebrew is installed, run `brew install git` to install git,\nand `brew install node` to install Node.js.\n\nLinux/BSD users should use their appropriate package managers to install git and Node.js, or build from source\nif you swing that way. Easy-peasy.\n\n\nHow to build your own jQuery\n----------------------------\n\nFirst, clone a copy of the main jQuery git repo by running:\n\n```bash\ngit clone git://github.com/jquery/jquery.git\n```\n\nInstall the grunt-cli package so that you will have the correct version of grunt available from any project that needs it. This should be done as a global install:\n\n```bash\nnpm install -g grunt-cli\n```\n\nEnter the jquery directory and install the Node dependencies, this time *without* specifying a global install:\n\n```bash\ncd jquery && npm install\n```\n\nMake sure you have `grunt` installed by testing:\n\n```bash\ngrunt -version\n```\n\nThen, to get a complete, minified (w/ Uglify.js), linted (w/ JSHint) version of jQuery, type the following:\n\n```bash\ngrunt\n```\n\nThe built version of jQuery will be put in the `dist/` subdirectory, along with the minified copy and associated map file.\n\n\n### Modules\n\nSpecial builds can be created that exclude subsets of jQuery functionality.\nThis allows for smaller custom builds when the builder is certain that those parts of jQuery are not being used.\nFor example, an app that only used JSONP for `$.ajax()` and did not need to calculate offsets or positions of elements could exclude the offset and ajax/xhr modules. The current modules that can be excluded are:\n\n- **ajax**: All AJAX functionality: `$.ajax()`, `$.get()`, `$.post()`, `$.ajaxSetup()`, `.load()`, transports, and ajax event shorthands such as `.ajaxStart()`.\n- **ajax/xhr**: The XMLHTTPRequest AJAX transport only.\n- **ajax/script**: The `<script>` AJAX transport only; used to retrieve scripts.\n- **ajax/jsonp**: The JSONP AJAX transport only; depends on the ajax/script transport.\n- **css**: The `.css()` method plus non-animated `.show()`, `.hide()` and `.toggle()`.\n- **deprecated**: Methods documented as deprecated but not yet removed; currently only `.andSelf()`.\n- **dimensions**: The `.width()` and `.height()` methods, including `inner-` and `outer-` variations.\n- **effects**: The `.animate()` method and its shorthands such as `.slideUp()` or `.hide(\"slow\")`. \n- **event-alias**: All event attaching/triggering shorthands like `.click()` or `.mouseover()`.\n- **offset**: The `.offset()`, `.position()`, `.offsetParent()`, `.scrollLeft()`, and `.scrollTop()` methods.\n- **wrap**: The `.wrap()`, `.wrapAll()`, `.wrapInner()`, and `.unwrap()` methods.\n- **sizzle**: The Sizzle selector engine. When this module is excluded, it is replaced by a rudimentary selector engine based on the browser's `querySelectorAll` method that does not support jQuery selector extensions or enhanced semantics. See the selector-native.js file for details.\n\nThe grunt build process is aware of dependencies across modules. If you explicitly remove a module, its dependent modules will be removed as well. For example, excluding the css module also excludes effects, since the effects module uses `.css()` to animate CSS properties. These dependencies are listed in Gruntfile.js and the build process shows a message for each dependent module it excludes.\n\nTo create a custom build of the latest stable version, first check out the version:\n\n```bash\ngit pull; git checkout $(git describe --abbrev=0 --tags)\n```\n\nThen, make sure all Node dependencies are installed and all Git submodules are checked out:\n\n```bash\nnpm install && grunt\n```\n\nCreate the custom build, use the `grunt custom` option, listing the modules to be excluded. Examples:\n\nExclude all **ajax** functionality:\n\n```bash\ngrunt custom:-ajax\n```\n\nExclude **css**, **effects**, **offset**, **dimensions**, and **position**. Excluding **css** automatically excludes its dependent modules:\n\n```bash\ngrunt custom:-css,-position\n```\n\nExclude **all** optional modules and use the `querySelectorAll`-based selector engine:\n\n```bash\ngrunt custom:-ajax,-css,-deprecated,-dimensions,-effects,-event-alias,-offset,-wrap,-sizzle\n```\n\nFor questions or requests regarding custom builds, please start a thread on the [Developing jQuery Core](https://forum.jquery.com/developing-jquery-core) section of the forum. Due to the combinatorics and custom nature of these builds, they are not regularly tested in jQuery's unit test process. The non-Sizzle selector engine currently does not pass unit tests because it is missing too much essential functionality.\n\nRunning the Unit Tests\n--------------------------------------\n\nStart grunt to auto-build jQuery as you work:\n\n```bash\ncd jquery && grunt watch\n```\n\n\nRun the unit tests with a local server that supports PHP. Ensure that you run the site from the root directory, not the \"test\" directory. No database is required. Pre-configured php local servers are available for Windows and Mac. Here are some options:\n\n- Windows: [WAMP download](http://www.wampserver.com/en/)\n- Mac: [MAMP download](http://www.mamp.info/en/index.html)\n- Linux: [Setting up LAMP](https://www.linux.com/learn/tutorials/288158-easy-lamp-server-installation)\n- [Mongoose (most platforms)](http://code.google.com/p/mongoose/)\n\n\n\n\nBuilding to a different directory\n---------------------------------\n\nTo copy the built jQuery files from `/dist` to another directory:\n\n```bash\ngrunt && grunt dist:/path/to/special/location/\n```\nWith this example, the output files would be:\n\n```bash\n/path/to/special/location/jquery.js\n/path/to/special/location/jquery.min.js\n```\n\nTo add a permanent copy destination, create a file in `dist/` called \".destination.json\". Inside the file, paste and customize the following:\n\n```json\n\n{\n  \"/Absolute/path/to/other/destination\": true\n}\n```\n\nAdditionally, both methods can be combined.\n\n\n\nUpdating Submodules\n-------------------\n\nUpdate the submodules to what is probably the latest upstream code.\n\n```bash\ngrunt update_submodules\n```\n\nNote: This task will also be run any time the default `grunt` command is used.\n\n\n\nEssential Git\n-------------\n\nAs the source code is handled by the version control system Git, it's useful to know some features used.\n\n### Submodules ###\n\nThe repository uses submodules, which normally are handled directly by the `grunt update_submodules` command, but sometimes you want to\nbe able to work with them manually.\n\nFollowing are the steps to manually get the submodules:\n\n```bash\ngit clone https://github.com/jquery/jquery.git\ncd jquery\ngit submodule init\ngit submodule update\n```\n\nOr:\n\n```bash\ngit clone https://github.com/jquery/jquery.git\ncd jquery\ngit submodule update --init\n```\n\nOr:\n\n```bash\ngit clone --recursive https://github.com/jquery/jquery.git\ncd jquery\n```\n\nIf you want to work inside a submodule, it is possible, but first you need to checkout a branch:\n\n```bash\ncd src/sizzle\ngit checkout master\n```\n\nAfter you've committed your changes to the submodule, you'll update the jquery project to point to the new commit,\nbut remember to push the submodule changes before pushing the new jquery commit:\n\n```bash\ncd src/sizzle\ngit push origin master\ncd ..\ngit add src/sizzle\ngit commit\n```\n\n\n### cleaning ###\n\nIf you want to purge your working directory back to the status of upstream, following commands can be used (remember everything you've worked on is gone after these):\n\n```bash\ngit reset --hard upstream/master\ngit clean -fdx\n```\n\n### rebasing ###\n\nFor feature/topic branches, you should always used the `--rebase` flag to `git pull`, or if you are usually handling many temporary \"to be in a github pull request\" branches, run following to automate this:\n\n```bash\ngit config branch.autosetuprebase local\n```\n(see `man git-config` for more information)\n\n### handling merge conflicts ###\n\nIf you're getting merge conflicts when merging, instead of editing the conflicted files manually, you can use the feature\n`git mergetool`. Even though the default tool `xxdiff` looks awful/old, it's rather useful.\n\nFollowing are some commands that can be used there:\n\n* `Ctrl + Alt + M` - automerge as much as possible\n* `b` - jump to next merge conflict\n* `s` - change the order of the conflicted lines\n* `u` - undo an merge\n* `left mouse button` - mark a block to be the winner\n* `middle mouse button` - mark a line to be the winner\n* `Ctrl + S` - save\n* `Ctrl + Q` - quit\n\n[QUnit](http://docs.jquery.com/QUnit) Reference\n-----------------\n\n### Test methods ###\n\n```js\nexpect( numAssertions );\nstop();\nstart();\n```\n\n\nnote: QUnit's eventual addition of an argument to stop/start is ignored in this test suite so that start and stop can be passed as callbacks without worrying about their parameters\n\n### Test assertions ###\n\n\n```js\nok( value, [message] );\nequal( actual, expected, [message] );\nnotEqual( actual, expected, [message] );\ndeepEqual( actual, expected, [message] );\nnotDeepEqual( actual, expected, [message] );\nstrictEqual( actual, expected, [message] );\nnotStrictEqual( actual, expected, [message] );\nraises( block, [expected], [message] );\n```\n\n\nTest Suite Convenience Methods Reference (See [test/data/testinit.js](https://github.com/jquery/jquery/blob/master/test/data/testinit.js))\n------------------------------\n\n### Returns an array of elements with the given IDs ###\n\n```js\nq( ... );\n```\n\nExample:\n\n```js\nq(\"main\", \"foo\", \"bar\");\n\n=> [ div#main, span#foo, input#bar ]\n```\n\n### Asserts that a selection matches the given IDs ###\n\n```js\nt( testName, selector, [ \"array\", \"of\", \"ids\" ] );\n```\n\nExample:\n\n```js\nt(\"Check for something\", \"//[a]\", [\"foo\", \"baar\"]);\n```\n\n\n\n### Fires a native DOM event without going through jQuery ###\n\n```js\nfireNative( node, eventType )\n```\n\nExample:\n\n```js\nfireNative( jQuery(\"#elem\")[0], \"click\" );\n```\n\n### Add random number to url to stop caching ###\n\n```js\nurl( \"some/url.php\" );\n```\n\nExample:\n\n```js\nurl(\"data/test.html\");\n\n=> \"data/test.html?10538358428943\"\n\n\nurl(\"data/test.php?foo=bar\");\n\n=> \"data/test.php?foo=bar&10538358345554\"\n```\n\n\n### Load tests in an iframe ###\n\nLoads a given page constructing a url with fileName: `\"./data/\" + fileName + \".html\"`\nand fires the given callback on jQuery ready (using the jQuery loading from that page)\nand passes the iFrame's jQuery to the callback.\n\n```js\ntestIframe( fileName, testName, callback );\n```\n\nCallback arguments:\n\n```js\ncallback( jQueryFromIFrame, iFrameWindow, iFrameDocument );\n```\n\n### Load tests in an iframe (window.iframeCallback) ###\n\nLoads a given page constructing a url with fileName: `\"./data/\" + fileName + \".html\"`\nThe given callback is fired when window.iframeCallback is called by the page\nThe arguments passed to the callback are the same as the\narguments passed to window.iframeCallback, whatever that may be\n\n```js\ntestIframeWithCallback( testName, fileName, callback );\n```\n\nQuestions?\n----------\n\nIf you have any questions, please feel free to ask on the\n[Developing jQuery Core forum](http://forum.jquery.com/developing-jquery-core) or in #jquery on irc.freenode.net.\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/jquery/bower.json",
    "content": "{\n  \"name\": \"jquery\",\n  \"version\": \"2.0.3\",\n  \"description\": \"jQuery component\",\n  \"keywords\": [\n    \"jquery\",\n    \"component\"\n  ],\n  \"main\": \"jquery.js\",\n  \"license\": \"MIT\"\n}\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/jquery/build/release-notes.js",
    "content": "#!/usr/bin/env node\n/*\n * jQuery Release Note Generator\n */\n\nvar fs = require(\"fs\"),\n\thttp = require(\"http\"),\n\textract = /<a href=\"\\/ticket\\/(\\d+)\" title=\"View ticket\">(.*?)<[^\"]+\"component\">\\s*(\\S+)/g,\n\tcategories = [],\n\tversion = process.argv[2];\n\nif ( !/^\\d+\\.\\d+/.test( version ) ) {\n\tconsole.error( \"Invalid version number: \" + version );\n\tprocess.exit( 1 );\n}\n\nhttp.request({\n\thost: \"bugs.jquery.com\",\n\tport: 80,\n\tmethod: \"GET\",\n\tpath: \"/query?status=closed&resolution=fixed&max=400&component=!web&order=component&milestone=\" + version\n}, function (res) {\n\tvar data = [];\n\n\tres.on( \"data\", function( chunk ) {\n\t\tdata.push( chunk );\n\t});\n\n\tres.on( \"end\", function() {\n\t\tvar match,\n\t\t\tfile = data.join(\"\"),\n\t\t\tcur;\n\n\t\twhile ( (match = extract.exec( file )) ) {\n\t\t\tif ( \"#\" + match[1] !== match[2] ) {\n\t\t\t\tvar cat = match[3];\n\n\t\t\t\tif ( !cur || cur !== cat ) {\n\t\t\t\t\tif ( cur ) {\n\t\t\t\t\t\tconsole.log(\"</ul>\");\n\t\t\t\t\t}\n\t\t\t\t\tcur = cat;\n\t\t\t\t\tconsole.log( \"<h3>\" + cat.charAt(0).toUpperCase() + cat.slice(1) + \"</h3>\" );\n\t\t\t\t\tconsole.log(\"<ul>\");\n\t\t\t\t}\n\n\t\t\t\tconsole.log(\n\t\t\t\t\t\"  <li><a href=\\\"http://bugs.jquery.com/ticket/\" + match[1] + \"\\\">#\" +\n\t\t\t\t\tmatch[1] + \": \" + match[2] + \"</a></li>\"\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t\tif ( cur ) {\n\t\t\tconsole.log(\"</ul>\");\n\t\t}\n\n\t});\n}).end();\n\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/jquery/build/release.js",
    "content": "#!/usr/bin/env node\n/*\n * jQuery Core Release Management\n */\n\n// Debugging variables\nvar\tdebug = false,\n\tskipRemote = false;\n\nvar fs = require(\"fs\"),\n\tchild = require(\"child_process\"),\n\tpath = require(\"path\"),\n\tarchiver = require(\"archiver\");\n\nvar releaseVersion,\n\tnextVersion,\n\tisBeta,\n\tpkg,\n\tbranch,\n\n\tscpURL = \"jqadmin@code.origin.jquery.com:/var/www/html/code.jquery.com/\",\n\tcdnURL = \"http://code.origin.jquery.com/\",\n\trepoURL = \"git@github.com:jquery/jquery.git\",\n\n\t// Windows needs the .cmd version but will find the non-.cmd\n\t// On Windows, ensure the HOME environment variable is set\n\tgruntCmd = process.platform === \"win32\" ? \"grunt.cmd\" : \"grunt\",\n\n\tdevFile = \"dist/jquery.js\",\n\tminFile = \"dist/jquery.min.js\",\n\tmapFile = \"dist/jquery.min.map\",\n\n\treleaseFiles = {\n\t\t\"jquery-VER.js\": devFile,\n\t\t\"jquery-VER.min.js\": minFile,\n\t\t\"jquery-VER.min.map\": mapFile //,\n// Disable these until 2.0 defeats 1.9 as the ONE TRUE JQUERY\n//\t\t\"jquery.js\": devFile,\n//\t\t\"jquery.min.js\": minFile,\n//\t\t\"jquery.min.map\": mapFile,\n//\t\t\"jquery-latest.js\": devFile,\n//\t\t\"jquery-latest.min.js\": minFile,\n//\t\t\"jquery-latest.min.map\": mapFile\n\t},\n\n\tjQueryFilesCDN = [],\n\n\tgoogleFilesCDN = [\n\t\t\"jquery.js\", \"jquery.min.js\", \"jquery.min.map\"\n\t],\n\n\tmsFilesCDN = [\n\t\t\"jquery-VER.js\", \"jquery-VER.min.js\", \"jquery-VER.min.map\"\n\t];\n\n\nsteps(\n\tinitialize,\n\tcheckGitStatus,\n\ttagReleaseVersion,\n\tgruntBuild,\n\tmakeReleaseCopies,\n\tsetNextVersion,\n\tcopyTojQueryCDN,\n\tbuildGoogleCDN,\n\tbuildMicrosoftCDN,\n\tpushToGithub,\n\texit\n);\n\nfunction initialize( next ) {\n\n\tif ( process.argv[2] === \"-d\" ) {\n\t\tprocess.argv.shift();\n\t\tdebug = true;\n\t\tconsole.warn(\"=== DEBUG MODE ===\" );\n\t}\n\n\t// First arg should be the version number being released\n\tvar newver, oldver,\n\t\trsemver = /^(\\d+)\\.(\\d+)\\.(\\d+)(?:-([\\dA-Za-z\\-]+(?:\\.[\\dA-Za-z\\-]+)*))?$/,\n\t\tversion = ( process.argv[3] || \"\" ).toLowerCase().match( rsemver ) || {},\n\t\tmajor = version[1],\n\t\tminor = version[2],\n\t\tpatch = version[3],\n\t\txbeta = version[4];\n\n\tbranch = process.argv[2];\n\treleaseVersion = process.argv[3];\n\tisBeta = !!xbeta;\n\n\tif ( !branch || !major || !minor || !patch ) {\n\t\tdie( \"Usage: \" + process.argv[1] + \" branch releaseVersion\" );\n\t}\n\tif ( xbeta === \"pre\" ) {\n\t\tdie( \"Cannot release a 'pre' version!\" );\n\t}\n\tif ( !(fs.existsSync || path.existsSync)( \"package.json\" ) ) {\n\t\tdie( \"No package.json in this directory\" );\n\t}\n\tpkg = JSON.parse( fs.readFileSync( \"package.json\" ) );\n\n\tconsole.log( \"Current version is \" + pkg.version + \"; generating release \" + releaseVersion );\n\tversion = pkg.version.match( rsemver );\n\toldver = ( +version[1] ) * 10000 + ( +version[2] * 100 ) + ( +version[3] )\n\tnewver = ( +major ) * 10000 + ( +minor * 100 ) + ( +patch );\n\tif ( newver < oldver ) {\n\t\tdie( \"Next version is older than current version!\" );\n\t}\n\n\tnextVersion = major + \".\" + minor + \".\" + ( isBeta ? patch : +patch + 1 ) + \"-pre\";\n\tnext();\n}\n\nfunction checkGitStatus( next ) {\n\tgit( [ \"status\" ], function( error, stdout, stderr ) {\n\t\tvar onBranch = ((stdout||\"\").match( /On branch (\\S+)/ ) || [])[1];\n\t\tif ( onBranch !== branch ) {\n\t\t\tdieIfReal( \"Branches don't match: Wanted \" + branch + \", got \" + onBranch );\n\t\t}\n\t\tif ( /Changes to be committed/i.test( stdout ) ) {\n\t\t\tdieIfReal( \"Please commit changed files before attemping to push a release.\" );\n\t\t}\n\t\tif ( /Changes not staged for commit/i.test( stdout ) ) {\n\t\t\tdieIfReal( \"Please stash files before attempting to push a release.\" );\n\t\t}\n\t\tnext();\n\t});\n}\n\nfunction tagReleaseVersion( next ) {\n\tupdatePackageVersion( releaseVersion );\n\tgit( [ \"commit\", \"-a\", \"-m\", \"Tagging the \" + releaseVersion + \" release.\" ], function(){\n\t\tgit( [ \"tag\", releaseVersion ], next, debug);\n\t}, debug);\n}\n\nfunction gruntBuild( next ) {\n\texec( gruntCmd, [], function( error, stdout ) {\n\t\tif ( error ) {\n\t\t\tdie( error + stderr );\n\t\t}\n\t\tconsole.log( stdout );\n\t\tnext();\n\t}, false );\n}\n\nfunction makeReleaseCopies( next ) {\n\tObject.keys( releaseFiles ).forEach(function( key ) {\n\t\tvar text,\n\t\t\tbuiltFile = releaseFiles[ key ],\n\t\t\tunpathedFile = key.replace( /VER/g, releaseVersion ),\n\t\t\treleaseFile = \"dist/\" + unpathedFile;\n\n\t\t// Beta releases don't update the jquery-latest etc. copies\n\t\tif ( !isBeta || key.indexOf( \"VER\" ) >= 0 ) {\n\n\t\t\tif ( /\\.map$/.test( releaseFile ) ) {\n\t\t\t\t// Map files need to reference the new uncompressed name;\n\t\t\t\t// assume that all files reside in the same directory.\n\t\t\t\t// \"file\":\"jquery.min.js\",\"sources\":[\"jquery.js\"]\n\t\t\t\ttext = fs.readFileSync( builtFile, \"utf8\" )\n\t\t\t\t\t.replace( /\"file\":\"([^\"]+)\",\"sources\":\\[\"([^\"]+)\"\\]/,\n\t\t\t\t\t\t\"\\\"file\\\":\\\"\" + unpathedFile.replace( /\\.min\\.map/, \".min.js\" ) +\n\t\t\t\t\t\t\"\\\",\\\"sources\\\":[\\\"\" + unpathedFile.replace( /\\.min\\.map/, \".js\" ) + \"\\\"]\" );\n\t\t\t\tfs.writeFileSync( releaseFile, text );\n\t\t\t} else if ( /\\.min\\.js$/.test( releaseFile ) ) {\n\t\t\t\t// Minified files point back to the corresponding map;\n\t\t\t\t// again assume one big happy directory.\n\t\t\t\t// \"//@ sourceMappingURL=jquery.min.map\"\n\t\t\t\ttext = fs.readFileSync( builtFile, \"utf8\" )\n\t\t\t\t\t.replace( /\\/\\/@ sourceMappingURL=\\S+/,\n\t\t\t\t\t\t\"//@ sourceMappingURL=\" + unpathedFile.replace( /\\.js$/, \".map\" ) );\n\t\t\t\tfs.writeFileSync( releaseFile, text );\n\t\t\t} else if ( builtFile !== releaseFile ) {\n\t\t\t\tcopy( builtFile, releaseFile );\n\t\t\t}\n\n\t\t\tjQueryFilesCDN.push( releaseFile );\n\t\t}\n\t});\n\tnext();\n}\n\nfunction setNextVersion( next ) {\n\tupdatePackageVersion( nextVersion );\n\tgit( [ \"commit\", \"-a\", \"-m\", \"Updating the source version to \" + nextVersion + \"✓™\" ], next, debug );\n}\n\nfunction copyTojQueryCDN( next ) {\n\tvar cmds = [];\n\n\tjQueryFilesCDN.forEach(function( name ) {\n\t\tcmds.push(function( nxt ){\n\t\t\texec( \"scp\", [ name, scpURL ], nxt, debug || skipRemote );\n\t\t});\n\t\tcmds.push(function( nxt ){\n\t\t\texec( \"curl\", [ cdnURL + name + \"?reload\" ], nxt, debug || skipRemote );\n\t\t});\n\t});\n\tcmds.push( next );\n\n\tsteps.apply( this, cmds );\n}\n\nfunction buildGoogleCDN( next ) {\n\tmakeArchive( \"googlecdn\", googleFilesCDN, next );\n}\n\nfunction buildMicrosoftCDN( next ) {\n\tmakeArchive( \"mscdn\", msFilesCDN, next );\n}\n\nfunction pushToGithub( next ) {\n\tgit( [ \"push\", \"--tags\", repoURL, branch ], next, debug || skipRemote );\n}\n\n//==============================\n\nfunction steps() {\n\tvar cur = 0,\n\t\tsteps = arguments;\n\t(function next(){\n\t\tprocess.nextTick(function(){\n\t\t\tsteps[ cur++ ]( next );\n\t\t});\n\t})();\n}\n\nfunction updatePackageVersion( ver ) {\n\tconsole.log( \"Updating package.json version to \" + ver );\n\tpkg.version = ver;\n\tif ( !debug ) {\n\t\tfs.writeFileSync( \"package.json\", JSON.stringify( pkg, null, \"\\t\" ) + \"\\n\" );\n\t}\n}\n\nfunction makeArchive( cdn, files, fn ) {\n\tif ( isBeta ) {\n\t\tconsole.log( \"Skipping archive creation for \" + cdn + \"; \" + releaseVersion + \" is beta\" );\n\t\tprocess.nextTick( fn );\n\t\treturn;\n\t}\n\n\tconsole.log( \"Creating production archive for \" + cdn );\n\n\tvar archive = archiver( \"zip\" ),\n\t\tmd5file = \"dist/\" + cdn + \"-md5.txt\",\n\t\toutput = fs.createWriteStream( \"dist/\" + cdn + \"-jquery-\" + releaseVersion + \".zip\" );\n\n\tarchive.on( \"error\", function( err ) {\n\t\tthrow err;\n\t});\n\n\toutput.on( \"close\", fn );\n\tarchive.pipe( output );\n\n\tfiles = files.map(function( item ) {\n\t\treturn \"dist/\" + item.replace( /VER/g, releaseVersion );\n\t});\n\n\texec( \"md5sum\", files, function( err, stdout, stderr ) {\n\t\tfs.writeFileSync( md5file, stdout );\n\t\tfiles.push( md5file );\n\n\t\tfiles.forEach(function( file ) {\n\t\t\tarchive.append( fs.createReadStream( file ), { name: file } );\n\t\t});\n\n\t\tarchive.finalize();\n\t}, false );\n}\n\nfunction copy( oldFile, newFile, skip ) {\n\tconsole.log( \"Copying \" + oldFile + \" to \" + newFile );\n\tif ( !skip ) {\n\t\tfs.writeFileSync( newFile, fs.readFileSync( oldFile, \"utf8\" ) );\n\t}\n}\n\nfunction git( args, fn, skip ) {\n\texec( \"git\", args, fn, skip );\n}\n\nfunction exec( cmd, args, fn, skip ) {\n\tif ( skip ) {\n\t\tconsole.log( \"# \" + cmd + \" \" + args.join(\" \") );\n\t\tfn( \"\", \"\", \"\" );\n\t} else {\n\t\tconsole.log( cmd + \" \" + args.join(\" \") );\n\t\tchild.execFile( cmd, args, { env: process.env },\n\t\t\tfunction( err, stdout, stderr ) {\n\t\t\t\tif ( err ) {\n\t\t\t\t\tdie( stderr || stdout || err );\n\t\t\t\t}\n\t\t\t\tfn.apply( this, arguments );\n\t\t\t}\n\t\t);\n\t}\n}\n\nfunction die( msg ) {\n\tconsole.error( \"ERROR: \" + msg );\n\tprocess.exit( 1 );\n}\n\nfunction dieIfReal( msg ) {\n\tif ( debug ) {\n\t\tconsole.log ( \"DIE: \" + msg );\n\t} else {\n\t\tdie( msg );\n\t}\n}\n\nfunction exit() {\n\tprocess.exit( 0 );\n}\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/jquery/component.json",
    "content": "{\n  \"name\": \"jquery\",\n  \"repo\": \"components/jquery\",\n  \"version\": \"2.0.3\",\n  \"description\": \"jQuery component\",\n  \"keywords\": [\n    \"jquery\",\n    \"component\"\n  ],\n  \"main\": \"jquery.js\",\n  \"scripts\": [\n    \"jquery.js\"\n  ],\n  \"license\": \"MIT\"\n}\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/jquery/composer.json",
    "content": "{\n    \"name\": \"components/jquery\",\n    \"description\": \"jQuery JavaScript Library\",\n    \"type\": \"component\",\n    \"homepage\": \"http://jquery.com\",\n    \"license\": \"MIT\",\n    \"support\": {\n        \"irc\": \"irc://irc.freenode.org/jquery\",\n        \"issues\": \"http://bugs.jquery.com\",\n        \"forum\": \"http://forum.jquery.com\",\n        \"wiki\": \"http://docs.jquery.com/\",\n        \"source\": \"https://github.com/jquery/jquery\"\n    },\n    \"authors\": [\n        {\n            \"name\": \"John Resig\",\n            \"email\": \"jeresig@gmail.com\"\n        }\n    ],\n    \"require\": {\n        \"robloach/component-installer\": \"*\"\n    },\n    \"extra\": {\n        \"component\": {\n            \"scripts\": [\n                \"jquery.js\"\n            ],\n            \"files\": [\n                \"jquery.min.js\",\n                \"jquery-migrate.js\",\n                \"jquery-migrate.min.js\"\n            ]\n        }\n    }\n}\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/jquery/jquery-migrate.js",
    "content": "/*!\n * jQuery Migrate - v1.1.1 - 2013-02-16\n * https://github.com/jquery/jquery-migrate\n * Copyright 2005, 2013 jQuery Foundation, Inc. and other contributors; Licensed MIT\n */\n(function( jQuery, window, undefined ) {\n// See http://bugs.jquery.com/ticket/13335\n// \"use strict\";\n\n\nvar warnedAbout = {};\n\n// List of warnings already given; public read only\njQuery.migrateWarnings = [];\n\n// Set to true to prevent console output; migrateWarnings still maintained\n// jQuery.migrateMute = false;\n\n// Show a message on the console so devs know we're active\nif ( !jQuery.migrateMute && window.console && console.log ) {\n\tconsole.log(\"JQMIGRATE: Logging is active\");\n}\n\n// Set to false to disable traces that appear with warnings\nif ( jQuery.migrateTrace === undefined ) {\n\tjQuery.migrateTrace = true;\n}\n\n// Forget any warnings we've already given; public\njQuery.migrateReset = function() {\n\twarnedAbout = {};\n\tjQuery.migrateWarnings.length = 0;\n};\n\nfunction migrateWarn( msg) {\n\tif ( !warnedAbout[ msg ] ) {\n\t\twarnedAbout[ msg ] = true;\n\t\tjQuery.migrateWarnings.push( msg );\n\t\tif ( window.console && console.warn && !jQuery.migrateMute ) {\n\t\t\tconsole.warn( \"JQMIGRATE: \" + msg );\n\t\t\tif ( jQuery.migrateTrace && console.trace ) {\n\t\t\t\tconsole.trace();\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunction migrateWarnProp( obj, prop, value, msg ) {\n\tif ( Object.defineProperty ) {\n\t\t// On ES5 browsers (non-oldIE), warn if the code tries to get prop;\n\t\t// allow property to be overwritten in case some other plugin wants it\n\t\ttry {\n\t\t\tObject.defineProperty( obj, prop, {\n\t\t\t\tconfigurable: true,\n\t\t\t\tenumerable: true,\n\t\t\t\tget: function() {\n\t\t\t\t\tmigrateWarn( msg );\n\t\t\t\t\treturn value;\n\t\t\t\t},\n\t\t\t\tset: function( newValue ) {\n\t\t\t\t\tmigrateWarn( msg );\n\t\t\t\t\tvalue = newValue;\n\t\t\t\t}\n\t\t\t});\n\t\t\treturn;\n\t\t} catch( err ) {\n\t\t\t// IE8 is a dope about Object.defineProperty, can't warn there\n\t\t}\n\t}\n\n\t// Non-ES5 (or broken) browser; just set the property\n\tjQuery._definePropertyBroken = true;\n\tobj[ prop ] = value;\n}\n\nif ( document.compatMode === \"BackCompat\" ) {\n\t// jQuery has never supported or tested Quirks Mode\n\tmigrateWarn( \"jQuery is not compatible with Quirks Mode\" );\n}\n\n\nvar attrFn = jQuery( \"<input/>\", { size: 1 } ).attr(\"size\") && jQuery.attrFn,\n\toldAttr = jQuery.attr,\n\tvalueAttrGet = jQuery.attrHooks.value && jQuery.attrHooks.value.get ||\n\t\tfunction() { return null; },\n\tvalueAttrSet = jQuery.attrHooks.value && jQuery.attrHooks.value.set ||\n\t\tfunction() { return undefined; },\n\trnoType = /^(?:input|button)$/i,\n\trnoAttrNodeType = /^[238]$/,\n\trboolean = /^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i,\n\truseDefault = /^(?:checked|selected)$/i;\n\n// jQuery.attrFn\nmigrateWarnProp( jQuery, \"attrFn\", attrFn || {}, \"jQuery.attrFn is deprecated\" );\n\njQuery.attr = function( elem, name, value, pass ) {\n\tvar lowerName = name.toLowerCase(),\n\t\tnType = elem && elem.nodeType;\n\n\tif ( pass ) {\n\t\t// Since pass is used internally, we only warn for new jQuery\n\t\t// versions where there isn't a pass arg in the formal params\n\t\tif ( oldAttr.length < 4 ) {\n\t\t\tmigrateWarn(\"jQuery.fn.attr( props, pass ) is deprecated\");\n\t\t}\n\t\tif ( elem && !rnoAttrNodeType.test( nType ) &&\n\t\t\t(attrFn ? name in attrFn : jQuery.isFunction(jQuery.fn[name])) ) {\n\t\t\treturn jQuery( elem )[ name ]( value );\n\t\t}\n\t}\n\n\t// Warn if user tries to set `type`, since it breaks on IE 6/7/8; by checking\n\t// for disconnected elements we don't warn on $( \"<button>\", { type: \"button\" } ).\n\tif ( name === \"type\" && value !== undefined && rnoType.test( elem.nodeName ) && elem.parentNode ) {\n\t\tmigrateWarn(\"Can't change the 'type' of an input or button in IE 6/7/8\");\n\t}\n\n\t// Restore boolHook for boolean property/attribute synchronization\n\tif ( !jQuery.attrHooks[ lowerName ] && rboolean.test( lowerName ) ) {\n\t\tjQuery.attrHooks[ lowerName ] = {\n\t\t\tget: function( elem, name ) {\n\t\t\t\t// Align boolean attributes with corresponding properties\n\t\t\t\t// Fall back to attribute presence where some booleans are not supported\n\t\t\t\tvar attrNode,\n\t\t\t\t\tproperty = jQuery.prop( elem, name );\n\t\t\t\treturn property === true || typeof property !== \"boolean\" &&\n\t\t\t\t\t( attrNode = elem.getAttributeNode(name) ) && attrNode.nodeValue !== false ?\n\n\t\t\t\t\tname.toLowerCase() :\n\t\t\t\t\tundefined;\n\t\t\t},\n\t\t\tset: function( elem, value, name ) {\n\t\t\t\tvar propName;\n\t\t\t\tif ( value === false ) {\n\t\t\t\t\t// Remove boolean attributes when set to false\n\t\t\t\t\tjQuery.removeAttr( elem, name );\n\t\t\t\t} else {\n\t\t\t\t\t// value is true since we know at this point it's type boolean and not false\n\t\t\t\t\t// Set boolean attributes to the same name and set the DOM property\n\t\t\t\t\tpropName = jQuery.propFix[ name ] || name;\n\t\t\t\t\tif ( propName in elem ) {\n\t\t\t\t\t\t// Only set the IDL specifically if it already exists on the element\n\t\t\t\t\t\telem[ propName ] = true;\n\t\t\t\t\t}\n\n\t\t\t\t\telem.setAttribute( name, name.toLowerCase() );\n\t\t\t\t}\n\t\t\t\treturn name;\n\t\t\t}\n\t\t};\n\n\t\t// Warn only for attributes that can remain distinct from their properties post-1.9\n\t\tif ( ruseDefault.test( lowerName ) ) {\n\t\t\tmigrateWarn( \"jQuery.fn.attr('\" + lowerName + \"') may use property instead of attribute\" );\n\t\t}\n\t}\n\n\treturn oldAttr.call( jQuery, elem, name, value );\n};\n\n// attrHooks: value\njQuery.attrHooks.value = {\n\tget: function( elem, name ) {\n\t\tvar nodeName = ( elem.nodeName || \"\" ).toLowerCase();\n\t\tif ( nodeName === \"button\" ) {\n\t\t\treturn valueAttrGet.apply( this, arguments );\n\t\t}\n\t\tif ( nodeName !== \"input\" && nodeName !== \"option\" ) {\n\t\t\tmigrateWarn(\"jQuery.fn.attr('value') no longer gets properties\");\n\t\t}\n\t\treturn name in elem ?\n\t\t\telem.value :\n\t\t\tnull;\n\t},\n\tset: function( elem, value ) {\n\t\tvar nodeName = ( elem.nodeName || \"\" ).toLowerCase();\n\t\tif ( nodeName === \"button\" ) {\n\t\t\treturn valueAttrSet.apply( this, arguments );\n\t\t}\n\t\tif ( nodeName !== \"input\" && nodeName !== \"option\" ) {\n\t\t\tmigrateWarn(\"jQuery.fn.attr('value', val) no longer sets properties\");\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\nvar matched, browser,\n\toldInit = jQuery.fn.init,\n\toldParseJSON = jQuery.parseJSON,\n\t// Note this does NOT include the #9521 XSS fix from 1.7!\n\trquickExpr = /^(?:[^<]*(<[\\w\\W]+>)[^>]*|#([\\w\\-]*))$/;\n\n// $(html) \"looks like html\" rule change\njQuery.fn.init = function( selector, context, rootjQuery ) {\n\tvar match;\n\n\tif ( selector && typeof selector === \"string\" && !jQuery.isPlainObject( context ) &&\n\t\t\t(match = rquickExpr.exec( selector )) && match[1] ) {\n\t\t// This is an HTML string according to the \"old\" rules; is it still?\n\t\tif ( selector.charAt( 0 ) !== \"<\" ) {\n\t\t\tmigrateWarn(\"$(html) HTML strings must start with '<' character\");\n\t\t}\n\t\t// Now process using loose rules; let pre-1.8 play too\n\t\tif ( context && context.context ) {\n\t\t\t// jQuery object as context; parseHTML expects a DOM object\n\t\t\tcontext = context.context;\n\t\t}\n\t\tif ( jQuery.parseHTML ) {\n\t\t\treturn oldInit.call( this, jQuery.parseHTML( jQuery.trim(selector), context, true ),\n\t\t\t\t\tcontext, rootjQuery );\n\t\t}\n\t}\n\treturn oldInit.apply( this, arguments );\n};\njQuery.fn.init.prototype = jQuery.fn;\n\n// Let $.parseJSON(falsy_value) return null\njQuery.parseJSON = function( json ) {\n\tif ( !json && json !== null ) {\n\t\tmigrateWarn(\"jQuery.parseJSON requires a valid JSON string\");\n\t\treturn null;\n\t}\n\treturn oldParseJSON.apply( this, arguments );\n};\n\njQuery.uaMatch = function( ua ) {\n\tua = ua.toLowerCase();\n\n\tvar match = /(chrome)[ \\/]([\\w.]+)/.exec( ua ) ||\n\t\t/(webkit)[ \\/]([\\w.]+)/.exec( ua ) ||\n\t\t/(opera)(?:.*version|)[ \\/]([\\w.]+)/.exec( ua ) ||\n\t\t/(msie) ([\\w.]+)/.exec( ua ) ||\n\t\tua.indexOf(\"compatible\") < 0 && /(mozilla)(?:.*? rv:([\\w.]+)|)/.exec( ua ) ||\n\t\t[];\n\n\treturn {\n\t\tbrowser: match[ 1 ] || \"\",\n\t\tversion: match[ 2 ] || \"0\"\n\t};\n};\n\n// Don't clobber any existing jQuery.browser in case it's different\nif ( !jQuery.browser ) {\n\tmatched = jQuery.uaMatch( navigator.userAgent );\n\tbrowser = {};\n\n\tif ( matched.browser ) {\n\t\tbrowser[ matched.browser ] = true;\n\t\tbrowser.version = matched.version;\n\t}\n\n\t// Chrome is Webkit, but Webkit is also Safari.\n\tif ( browser.chrome ) {\n\t\tbrowser.webkit = true;\n\t} else if ( browser.webkit ) {\n\t\tbrowser.safari = true;\n\t}\n\n\tjQuery.browser = browser;\n}\n\n// Warn if the code tries to get jQuery.browser\nmigrateWarnProp( jQuery, \"browser\", jQuery.browser, \"jQuery.browser is deprecated\" );\n\njQuery.sub = function() {\n\tfunction jQuerySub( selector, context ) {\n\t\treturn new jQuerySub.fn.init( selector, context );\n\t}\n\tjQuery.extend( true, jQuerySub, this );\n\tjQuerySub.superclass = this;\n\tjQuerySub.fn = jQuerySub.prototype = this();\n\tjQuerySub.fn.constructor = jQuerySub;\n\tjQuerySub.sub = this.sub;\n\tjQuerySub.fn.init = function init( selector, context ) {\n\t\tif ( context && context instanceof jQuery && !(context instanceof jQuerySub) ) {\n\t\t\tcontext = jQuerySub( context );\n\t\t}\n\n\t\treturn jQuery.fn.init.call( this, selector, context, rootjQuerySub );\n\t};\n\tjQuerySub.fn.init.prototype = jQuerySub.fn;\n\tvar rootjQuerySub = jQuerySub(document);\n\tmigrateWarn( \"jQuery.sub() is deprecated\" );\n\treturn jQuerySub;\n};\n\n\n// Ensure that $.ajax gets the new parseJSON defined in core.js\njQuery.ajaxSetup({\n\tconverters: {\n\t\t\"text json\": jQuery.parseJSON\n\t}\n});\n\n\nvar oldFnData = jQuery.fn.data;\n\njQuery.fn.data = function( name ) {\n\tvar ret, evt,\n\t\telem = this[0];\n\n\t// Handles 1.7 which has this behavior and 1.8 which doesn't\n\tif ( elem && name === \"events\" && arguments.length === 1 ) {\n\t\tret = jQuery.data( elem, name );\n\t\tevt = jQuery._data( elem, name );\n\t\tif ( ( ret === undefined || ret === evt ) && evt !== undefined ) {\n\t\t\tmigrateWarn(\"Use of jQuery.fn.data('events') is deprecated\");\n\t\t\treturn evt;\n\t\t}\n\t}\n\treturn oldFnData.apply( this, arguments );\n};\n\n\nvar rscriptType = /\\/(java|ecma)script/i,\n\toldSelf = jQuery.fn.andSelf || jQuery.fn.addBack;\n\njQuery.fn.andSelf = function() {\n\tmigrateWarn(\"jQuery.fn.andSelf() replaced by jQuery.fn.addBack()\");\n\treturn oldSelf.apply( this, arguments );\n};\n\n// Since jQuery.clean is used internally on older versions, we only shim if it's missing\nif ( !jQuery.clean ) {\n\tjQuery.clean = function( elems, context, fragment, scripts ) {\n\t\t// Set context per 1.8 logic\n\t\tcontext = context || document;\n\t\tcontext = !context.nodeType && context[0] || context;\n\t\tcontext = context.ownerDocument || context;\n\n\t\tmigrateWarn(\"jQuery.clean() is deprecated\");\n\n\t\tvar i, elem, handleScript, jsTags,\n\t\t\tret = [];\n\n\t\tjQuery.merge( ret, jQuery.buildFragment( elems, context ).childNodes );\n\n\t\t// Complex logic lifted directly from jQuery 1.8\n\t\tif ( fragment ) {\n\t\t\t// Special handling of each script element\n\t\t\thandleScript = function( elem ) {\n\t\t\t\t// Check if we consider it executable\n\t\t\t\tif ( !elem.type || rscriptType.test( elem.type ) ) {\n\t\t\t\t\t// Detach the script and store it in the scripts array (if provided) or the fragment\n\t\t\t\t\t// Return truthy to indicate that it has been handled\n\t\t\t\t\treturn scripts ?\n\t\t\t\t\t\tscripts.push( elem.parentNode ? elem.parentNode.removeChild( elem ) : elem ) :\n\t\t\t\t\t\tfragment.appendChild( elem );\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tfor ( i = 0; (elem = ret[i]) != null; i++ ) {\n\t\t\t\t// Check if we're done after handling an executable script\n\t\t\t\tif ( !( jQuery.nodeName( elem, \"script\" ) && handleScript( elem ) ) ) {\n\t\t\t\t\t// Append to fragment and handle embedded scripts\n\t\t\t\t\tfragment.appendChild( elem );\n\t\t\t\t\tif ( typeof elem.getElementsByTagName !== \"undefined\" ) {\n\t\t\t\t\t\t// handleScript alters the DOM, so use jQuery.merge to ensure snapshot iteration\n\t\t\t\t\t\tjsTags = jQuery.grep( jQuery.merge( [], elem.getElementsByTagName(\"script\") ), handleScript );\n\n\t\t\t\t\t\t// Splice the scripts into ret after their former ancestor and advance our index beyond them\n\t\t\t\t\t\tret.splice.apply( ret, [i + 1, 0].concat( jsTags ) );\n\t\t\t\t\t\ti += jsTags.length;\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\nvar eventAdd = jQuery.event.add,\n\teventRemove = jQuery.event.remove,\n\teventTrigger = jQuery.event.trigger,\n\toldToggle = jQuery.fn.toggle,\n\toldLive = jQuery.fn.live,\n\toldDie = jQuery.fn.die,\n\tajaxEvents = \"ajaxStart|ajaxStop|ajaxSend|ajaxComplete|ajaxError|ajaxSuccess\",\n\trajaxEvent = new RegExp( \"\\\\b(?:\" + ajaxEvents + \")\\\\b\" ),\n\trhoverHack = /(?:^|\\s)hover(\\.\\S+|)\\b/,\n\thoverHack = function( events ) {\n\t\tif ( typeof( events ) !== \"string\" || jQuery.event.special.hover ) {\n\t\t\treturn events;\n\t\t}\n\t\tif ( rhoverHack.test( events ) ) {\n\t\t\tmigrateWarn(\"'hover' pseudo-event is deprecated, use 'mouseenter mouseleave'\");\n\t\t}\n\t\treturn events && events.replace( rhoverHack, \"mouseenter$1 mouseleave$1\" );\n\t};\n\n// Event props removed in 1.9, put them back if needed; no practical way to warn them\nif ( jQuery.event.props && jQuery.event.props[ 0 ] !== \"attrChange\" ) {\n\tjQuery.event.props.unshift( \"attrChange\", \"attrName\", \"relatedNode\", \"srcElement\" );\n}\n\n// Undocumented jQuery.event.handle was \"deprecated\" in jQuery 1.7\nif ( jQuery.event.dispatch ) {\n\tmigrateWarnProp( jQuery.event, \"handle\", jQuery.event.dispatch, \"jQuery.event.handle is undocumented and deprecated\" );\n}\n\n// Support for 'hover' pseudo-event and ajax event warnings\njQuery.event.add = function( elem, types, handler, data, selector ){\n\tif ( elem !== document && rajaxEvent.test( types ) ) {\n\t\tmigrateWarn( \"AJAX events should be attached to document: \" + types );\n\t}\n\teventAdd.call( this, elem, hoverHack( types || \"\" ), handler, data, selector );\n};\njQuery.event.remove = function( elem, types, handler, selector, mappedTypes ){\n\teventRemove.call( this, elem, hoverHack( types ) || \"\", handler, selector, mappedTypes );\n};\n\njQuery.fn.error = function() {\n\tvar args = Array.prototype.slice.call( arguments, 0);\n\tmigrateWarn(\"jQuery.fn.error() is deprecated\");\n\targs.splice( 0, 0, \"error\" );\n\tif ( arguments.length ) {\n\t\treturn this.bind.apply( this, args );\n\t}\n\t// error event should not bubble to window, although it does pre-1.7\n\tthis.triggerHandler.apply( this, args );\n\treturn this;\n};\n\njQuery.fn.toggle = function( fn, fn2 ) {\n\n\t// Don't mess with animation or css toggles\n\tif ( !jQuery.isFunction( fn ) || !jQuery.isFunction( fn2 ) ) {\n\t\treturn oldToggle.apply( this, arguments );\n\t}\n\tmigrateWarn(\"jQuery.fn.toggle(handler, handler...) is deprecated\");\n\n\t// Save reference to arguments for access in closure\n\tvar args = arguments,\n\t\tguid = fn.guid || jQuery.guid++,\n\t\ti = 0,\n\t\ttoggler = function( event ) {\n\t\t\t// Figure out which function to execute\n\t\t\tvar lastToggle = ( jQuery._data( this, \"lastToggle\" + fn.guid ) || 0 ) % i;\n\t\t\tjQuery._data( this, \"lastToggle\" + fn.guid, lastToggle + 1 );\n\n\t\t\t// Make sure that clicks stop\n\t\t\tevent.preventDefault();\n\n\t\t\t// and execute the function\n\t\t\treturn args[ lastToggle ].apply( this, arguments ) || false;\n\t\t};\n\n\t// link all the functions, so any of them can unbind this click handler\n\ttoggler.guid = guid;\n\twhile ( i < args.length ) {\n\t\targs[ i++ ].guid = guid;\n\t}\n\n\treturn this.click( toggler );\n};\n\njQuery.fn.live = function( types, data, fn ) {\n\tmigrateWarn(\"jQuery.fn.live() is deprecated\");\n\tif ( oldLive ) {\n\t\treturn oldLive.apply( this, arguments );\n\t}\n\tjQuery( this.context ).on( types, this.selector, data, fn );\n\treturn this;\n};\n\njQuery.fn.die = function( types, fn ) {\n\tmigrateWarn(\"jQuery.fn.die() is deprecated\");\n\tif ( oldDie ) {\n\t\treturn oldDie.apply( this, arguments );\n\t}\n\tjQuery( this.context ).off( types, this.selector || \"**\", fn );\n\treturn this;\n};\n\n// Turn global events into document-triggered events\njQuery.event.trigger = function( event, data, elem, onlyHandlers  ){\n\tif ( !elem && !rajaxEvent.test( event ) ) {\n\t\tmigrateWarn( \"Global events are undocumented and deprecated\" );\n\t}\n\treturn eventTrigger.call( this,  event, data, elem || document, onlyHandlers  );\n};\njQuery.each( ajaxEvents.split(\"|\"),\n\tfunction( _, name ) {\n\t\tjQuery.event.special[ name ] = {\n\t\t\tsetup: function() {\n\t\t\t\tvar elem = this;\n\n\t\t\t\t// The document needs no shimming; must be !== for oldIE\n\t\t\t\tif ( elem !== document ) {\n\t\t\t\t\tjQuery.event.add( document, name + \".\" + jQuery.guid, function() {\n\t\t\t\t\t\tjQuery.event.trigger( name, null, elem, true );\n\t\t\t\t\t});\n\t\t\t\t\tjQuery._data( this, name, jQuery.guid++ );\n\t\t\t\t}\n\t\t\t\treturn false;\n\t\t\t},\n\t\t\tteardown: function() {\n\t\t\t\tif ( this !== document ) {\n\t\t\t\t\tjQuery.event.remove( document, name + \".\" + jQuery._data( this, name ) );\n\t\t\t\t}\n\t\t\t\treturn false;\n\t\t\t}\n\t\t};\n\t}\n);\n\n\n})( jQuery, window );\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/jquery/jquery.js",
    "content": "/*!\n * jQuery JavaScript Library v2.0.3\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:30Z\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// A central reference to the root jQuery(document)\n\trootjQuery,\n\n\t// The deferred used on DOM ready\n\treadyList,\n\n\t// Support: IE9\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 = \"2.0.3\",\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// 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// 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 and self cleanup method\n\tcompleted = function() {\n\t\tdocument.removeEventListener( \"DOMContentLoaded\", completed, false );\n\t\twindow.removeEventListener( \"load\", completed, false );\n\t\tjQuery.ready();\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// 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 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\t// Unique for each copy of jQuery on the page\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// 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,\n\n\tisWindow: function( obj ) {\n\t\treturn obj != null && obj === obj.window;\n\t},\n\n\tisNumeric: function( obj ) {\n\t\treturn !isNaN( parseFloat(obj) ) && isFinite( obj );\n\t},\n\n\ttype: function( obj ) {\n\t\tif ( obj == null ) {\n\t\t\treturn String( obj );\n\t\t}\n\t\t// Support: Safari <= 5.1 (functionish RegExp)\n\t\treturn typeof obj === \"object\" || typeof obj === \"function\" ?\n\t\t\tclass2type[ core_toString.call(obj) ] || \"object\" :\n\t\t\ttypeof obj;\n\t},\n\n\tisPlainObject: function( obj ) {\n\t\t// Not plain objects:\n\t\t// - Any object or value whose internal [[Class]] property is not \"[object Object]\"\n\t\t// - DOM nodes\n\t\t// - window\n\t\tif ( jQuery.type( obj ) !== \"object\" || obj.nodeType || jQuery.isWindow( obj ) ) {\n\t\t\treturn false;\n\t\t}\n\n\t\t// Support: Firefox <20\n\t\t// The try/catch suppresses exceptions thrown when attempting to access\n\t\t// the \"constructor\" property of certain host objects, ie. |window.location|\n\t\t// https://bugzilla.mozilla.org/show_bug.cgi?id=814622\n\t\ttry {\n\t\t\tif ( obj.constructor &&\n\t\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\treturn false;\n\t\t}\n\n\t\t// If the function hasn't returned already, we're confident that\n\t\t// |obj| is a plain object, created by {} or constructed with new Object\n\t\treturn true;\n\t},\n\n\tisEmptyObject: function( obj ) {\n\t\tvar name;\n\t\tfor ( name in obj ) {\n\t\t\treturn false;\n\t\t}\n\t\treturn true;\n\t},\n\n\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\n\t\tif ( scripts ) {\n\t\t\tjQuery( scripts ).remove();\n\t\t}\n\n\t\treturn jQuery.merge( [], parsed.childNodes );\n\t},\n\n\tparseJSON: JSON.parse,\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\n\t\t// Support: IE9\n\t\ttry {\n\t\t\ttmp = new DOMParser();\n\t\t\txml = tmp.parseFromString( data , \"text/xml\" );\n\t\t} catch ( e ) {\n\t\t\txml = undefined;\n\t\t}\n\n\t\tif ( !xml || xml.getElementsByTagName( \"parsererror\" ).length ) {\n\t\t\tjQuery.error( \"Invalid XML: \" + data );\n\t\t}\n\t\treturn xml;\n\t},\n\n\tnoop: function() {},\n\n\t// Evaluates a script in a global context\n\tglobalEval: function( code ) {\n\t\tvar script,\n\t\t\t\tindirect = eval;\n\n\t\tcode = jQuery.trim( code );\n\n\t\tif ( code ) {\n\t\t\t// If the code includes a valid, prologue position\n\t\t\t// strict mode pragma, execute code by injecting a\n\t\t\t// script tag into the document.\n\t\t\tif ( code.indexOf(\"use strict\") === 1 ) {\n\t\t\t\tscript = document.createElement(\"script\");\n\t\t\t\tscript.text = code;\n\t\t\t\tdocument.head.appendChild( script ).parentNode.removeChild( script );\n\t\t\t} else {\n\t\t\t// Otherwise, avoid the DOM node creation, insertion\n\t\t\t// and removal by using an indirect global eval\n\t\t\t\tindirect( code );\n\t\t\t}\n\t\t}\n\t},\n\n\t// Convert dashed to camelCase; used by the css and data modules\n\t// 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\ttrim: function( text ) {\n\t\treturn text == null ? \"\" : core_trim.call( text );\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\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\treturn arr == null ? -1 : core_indexOf.call( arr, elem, i );\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 tmp, args, proxy;\n\n\t\tif ( typeof context === \"string\" ) {\n\t\t\ttmp = fn[ context ];\n\t\t\tcontext = fn;\n\t\t\tfn = tmp;\n\t\t}\n\n\t\t// Quick check to determine if target is callable, in the spec\n\t\t// this throws a TypeError, but we will just return undefined.\n\t\tif ( !jQuery.isFunction( fn ) ) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\t// Simulated bind\n\t\targs = 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: Date.now,\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} else {\n\n\t\t\t// Use the handy event callback\n\t\t\tdocument.addEventListener( \"DOMContentLoaded\", completed, false );\n\n\t\t\t// A fallback to window.onload, that will always work\n\t\t\twindow.addEventListener( \"load\", completed, false );\n\t\t}\n\t}\n\treturn readyList.promise( obj );\n};\n\n// 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.9.4-pre\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-06-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 // Last fire value (for non-forgettable lists)\n\t\tmemory,\n\t\t// Flag to know if list was already fired\n\t\tfired,\n\t\t// Flag to know if list is currently firing\n\t\tfiring,\n\t\t// First callback to fire (used internally by add and fireWith)\n\t\tfiringStart,\n\t\t// End of the loop when firing\n\t\tfiringLength,\n\t\t// Index of currently firing callback (modified by remove if needed)\n\t\tfiringIndex,\n\t\t// Actual callback list\n\t\tlist = [],\n\t\t// Stack of fire calls for repeatable lists\n\t\tstack = !options.once && [],\n\t\t// Fire callbacks\n\t\tfire = function( data ) {\n\t\t\tmemory = options.memory && data;\n\t\t\tfired = true;\n\t\t\tfiringIndex = firingStart || 0;\n\t\t\tfiringStart = 0;\n\t\t\tfiringLength = list.length;\n\t\t\tfiring = true;\n\t\t\tfor ( ; list && firingIndex < firingLength; firingIndex++ ) {\n\t\t\t\tif ( list[ firingIndex ].apply( data[ 0 ], data[ 1 ] ) === false && options.stopOnFalse ) {\n\t\t\t\t\tmemory = false; // To prevent further calls using add\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tfiring = false;\n\t\t\tif ( list ) {\n\t\t\t\tif ( stack ) {\n\t\t\t\t\tif ( stack.length ) {\n\t\t\t\t\t\tfire( stack.shift() );\n\t\t\t\t\t}\n\t\t\t\t} else if ( memory ) {\n\t\t\t\t\tlist = [];\n\t\t\t\t} else {\n\t\t\t\t\tself.disable();\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t// Actual Callbacks object\n\t\tself = {\n\t\t\t// Add a callback or a collection of callbacks to the list\n\t\t\tadd: function() {\n\t\t\t\tif ( list ) {\n\t\t\t\t\t// First, we save the current length\n\t\t\t\t\tvar start = list.length;\n\t\t\t\t\t(function add( args ) {\n\t\t\t\t\t\tjQuery.each( args, function( _, arg ) {\n\t\t\t\t\t\t\tvar type = jQuery.type( arg );\n\t\t\t\t\t\t\tif ( type === \"function\" ) {\n\t\t\t\t\t\t\t\tif ( !options.unique || !self.has( arg ) ) {\n\t\t\t\t\t\t\t\t\tlist.push( arg );\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} else if ( arg && arg.length && type !== \"string\" ) {\n\t\t\t\t\t\t\t\t// Inspect recursively\n\t\t\t\t\t\t\t\tadd( arg );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t});\n\t\t\t\t\t})( arguments );\n\t\t\t\t\t// Do we need to add the callbacks to the\n\t\t\t\t\t// current firing batch?\n\t\t\t\t\tif ( firing ) {\n\t\t\t\t\t\tfiringLength = list.length;\n\t\t\t\t\t// With memory, if we're not firing then\n\t\t\t\t\t// we should call right away\n\t\t\t\t\t} else if ( memory ) {\n\t\t\t\t\t\tfiringStart = start;\n\t\t\t\t\t\tfire( memory );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Remove a callback from the list\n\t\t\tremove: function() {\n\t\t\t\tif ( list ) {\n\t\t\t\t\tjQuery.each( arguments, function( _, arg ) {\n\t\t\t\t\t\tvar index;\n\t\t\t\t\t\twhile( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) {\n\t\t\t\t\t\t\tlist.splice( index, 1 );\n\t\t\t\t\t\t\t// Handle firing indexes\n\t\t\t\t\t\t\tif ( firing ) {\n\t\t\t\t\t\t\t\tif ( index <= firingLength ) {\n\t\t\t\t\t\t\t\t\tfiringLength--;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif ( index <= firingIndex ) {\n\t\t\t\t\t\t\t\t\tfiringIndex--;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Check if a given callback is in the list.\n\t\t\t// If no argument is given, return whether or not list has callbacks attached.\n\t\t\thas: function( fn ) {\n\t\t\t\treturn fn ? jQuery.inArray( fn, list ) > -1 : !!( list && list.length );\n\t\t\t},\n\t\t\t// Remove all callbacks from the list\n\t\t\tempty: function() {\n\t\t\t\tlist = [];\n\t\t\t\tfiringLength = 0;\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Have the list do nothing anymore\n\t\t\tdisable: function() {\n\t\t\t\tlist = stack = memory = undefined;\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Is it disabled?\n\t\t\tdisabled: function() {\n\t\t\t\treturn !list;\n\t\t\t},\n\t\t\t// Lock the list in its current state\n\t\t\tlock: function() {\n\t\t\t\tstack = undefined;\n\t\t\t\tif ( !memory ) {\n\t\t\t\t\tself.disable();\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Is it locked?\n\t\t\tlocked: function() {\n\t\t\t\treturn !stack;\n\t\t\t},\n\t\t\t// Call all callbacks with the given context and arguments\n\t\t\tfireWith: function( context, args ) {\n\t\t\t\tif ( list && ( !fired || stack ) ) {\n\t\t\t\t\targs = args || [];\n\t\t\t\t\targs = [ context, args.slice ? args.slice() : args ];\n\t\t\t\t\tif ( firing ) {\n\t\t\t\t\t\tstack.push( args );\n\t\t\t\t\t} else {\n\t\t\t\t\t\tfire( args );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Call all the callbacks with the given arguments\n\t\t\tfire: function() {\n\t\t\t\tself.fireWith( this, arguments );\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// To know if the callbacks have already been called at least once\n\t\t\tfired: function() {\n\t\t\t\treturn !!fired;\n\t\t\t}\n\t\t};\n\n\treturn self;\n};\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\tvar input = document.createElement(\"input\"),\n\t\tfragment = document.createDocumentFragment(),\n\t\tdiv = document.createElement(\"div\"),\n\t\tselect = document.createElement(\"select\"),\n\t\topt = select.appendChild( document.createElement(\"option\") );\n\n\t// Finish early in limited environments\n\tif ( !input.type ) {\n\t\treturn support;\n\t}\n\n\tinput.type = \"checkbox\";\n\n\t// Support: Safari 5.1, iOS 5.1, Android 4.x, Android 2.3\n\t// Check the default checkbox/radio value (\"\" on old WebKit; \"on\" elsewhere)\n\tsupport.checkOn = input.value !== \"\";\n\n\t// Must access the parent to make an option select properly\n\t// Support: IE9, IE10\n\tsupport.optSelected = opt.selected;\n\n\t// Will be defined later\n\tsupport.reliableMarginRight = true;\n\tsupport.boxSizingReliable = true;\n\tsupport.pixelPosition = false;\n\n\t// Make sure checked status is properly cloned\n\t// Support: IE9, IE10\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// Check if an input maintains its value after becoming a radio\n\t// Support: IE9, IE10\n\tinput = document.createElement(\"input\");\n\tinput.value = \"t\";\n\tinput.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.appendChild( input );\n\n\t// Support: Safari 5.1, Android 4.x, Android 2.3\n\t// old WebKit doesn't clone checked state correctly in fragments\n\tsupport.checkClone = fragment.cloneNode( true ).cloneNode( true ).lastChild.checked;\n\n\t// Support: Firefox, Chrome, Safari\n\t// Beware of CSP restrictions (https://developer.mozilla.org/en/Security/CSP)\n\tsupport.focusinBubbles = \"onfocusin\" in window;\n\n\tdiv.style.backgroundClip = \"content-box\";\n\tdiv.cloneNode( true ).style.backgroundClip = \"\";\n\tsupport.clearCloneStyle = div.style.backgroundClip === \"content-box\";\n\n\t// Run tests that need a body at doc ready\n\tjQuery(function() {\n\t\tvar container, marginDiv,\n\t\t\t// Support: Firefox, Android 2.3 (Prefixed box-sizing versions).\n\t\t\tdivReset = \"padding:0;margin:0;border:0;display:block;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;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\t// Check box-sizing and margin behavior.\n\t\tbody.appendChild( container ).appendChild( div );\n\t\tdiv.innerHTML = \"\";\n\t\t// Support: Firefox, Android 2.3 (Prefixed box-sizing versions).\n\t\tdiv.style.cssText = \"-webkit-box-sizing:border-box;-moz-box-sizing:border-box;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// Support: Android 2.3\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// 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\tbody.removeChild( container );\n\t});\n\n\treturn support;\n})( {} );\n\n/*\n\tImplementation Summary\n\n\t1. Enforce API surface and semantic compatibility with 1.9.x branch\n\t2. Improve the module's maintainability by reducing the storage\n\t\tpaths to a single mechanism.\n\t3. Use the same single mechanism to support \"private\" and \"user\" data.\n\t4. _Never_ expose \"private\" data to user code (TODO: Drop _data, _removeData)\n\t5. Avoid exposing implementation details on user objects (eg. expando properties)\n\t6. Provide a clear path for implementation upgrade to WeakMap in 2014\n*/\nvar data_user, data_priv,\n\trbrace = /(?:\\{[\\s\\S]*\\}|\\[[\\s\\S]*\\])$/,\n\trmultiDash = /([A-Z])/g;\n\nfunction Data() {\n\t// Support: Android < 4,\n\t// Old WebKit does not have Object.preventExtensions/freeze method,\n\t// return new empty object instead with no [[set]] accessor\n\tObject.defineProperty( this.cache = {}, 0, {\n\t\tget: function() {\n\t\t\treturn {};\n\t\t}\n\t});\n\n\tthis.expando = jQuery.expando + Math.random();\n}\n\nData.uid = 1;\n\nData.accepts = function( owner ) {\n\t// Accepts only:\n\t//  - Node\n\t//    - Node.ELEMENT_NODE\n\t//    - Node.DOCUMENT_NODE\n\t//  - Object\n\t//    - Any\n\treturn owner.nodeType ?\n\t\towner.nodeType === 1 || owner.nodeType === 9 : true;\n};\n\nData.prototype = {\n\tkey: function( owner ) {\n\t\t// We can accept data for non-element nodes in modern browsers,\n\t\t// but we should not, see #8335.\n\t\t// Always return the key for a frozen object.\n\t\tif ( !Data.accepts( owner ) ) {\n\t\t\treturn 0;\n\t\t}\n\n\t\tvar descriptor = {},\n\t\t\t// Check if the owner object already has a cache key\n\t\t\tunlock = owner[ this.expando ];\n\n\t\t// If not, create one\n\t\tif ( !unlock ) {\n\t\t\tunlock = Data.uid++;\n\n\t\t\t// Secure it in a non-enumerable, non-writable property\n\t\t\ttry {\n\t\t\t\tdescriptor[ this.expando ] = { value: unlock };\n\t\t\t\tObject.defineProperties( owner, descriptor );\n\n\t\t\t// Support: Android < 4\n\t\t\t// Fallback to a less secure definition\n\t\t\t} catch ( e ) {\n\t\t\t\tdescriptor[ this.expando ] = unlock;\n\t\t\t\tjQuery.extend( owner, descriptor );\n\t\t\t}\n\t\t}\n\n\t\t// Ensure the cache object\n\t\tif ( !this.cache[ unlock ] ) {\n\t\t\tthis.cache[ unlock ] = {};\n\t\t}\n\n\t\treturn unlock;\n\t},\n\tset: function( owner, data, value ) {\n\t\tvar prop,\n\t\t\t// There may be an unlock assigned to this node,\n\t\t\t// if there is no entry for this \"owner\", create one inline\n\t\t\t// and set the unlock as though an owner entry had always existed\n\t\t\tunlock = this.key( owner ),\n\t\t\tcache = this.cache[ unlock ];\n\n\t\t// Handle: [ owner, key, value ] args\n\t\tif ( typeof data === \"string\" ) {\n\t\t\tcache[ data ] = value;\n\n\t\t// Handle: [ owner, { properties } ] args\n\t\t} else {\n\t\t\t// Fresh assignments by object are shallow copied\n\t\t\tif ( jQuery.isEmptyObject( cache ) ) {\n\t\t\t\tjQuery.extend( this.cache[ unlock ], data );\n\t\t\t// Otherwise, copy the properties one-by-one to the cache object\n\t\t\t} else {\n\t\t\t\tfor ( prop in data ) {\n\t\t\t\t\tcache[ prop ] = data[ prop ];\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn cache;\n\t},\n\tget: function( owner, key ) {\n\t\t// Either a valid cache is found, or will be created.\n\t\t// New caches will be created and the unlock returned,\n\t\t// allowing direct access to the newly created\n\t\t// empty data object. A valid owner object must be provided.\n\t\tvar cache = this.cache[ this.key( owner ) ];\n\n\t\treturn key === undefined ?\n\t\t\tcache : cache[ key ];\n\t},\n\taccess: function( owner, key, value ) {\n\t\tvar stored;\n\t\t// In cases where either:\n\t\t//\n\t\t//   1. No key was specified\n\t\t//   2. A string key was specified, but no value provided\n\t\t//\n\t\t// Take the \"read\" path and allow the get method to determine\n\t\t// which value to return, respectively either:\n\t\t//\n\t\t//   1. The entire cache object\n\t\t//   2. The data stored at the key\n\t\t//\n\t\tif ( key === undefined ||\n\t\t\t\t((key && typeof key === \"string\") && value === undefined) ) {\n\n\t\t\tstored = this.get( owner, key );\n\n\t\t\treturn stored !== undefined ?\n\t\t\t\tstored : this.get( owner, jQuery.camelCase(key) );\n\t\t}\n\n\t\t// [*]When the key is not a string, or both a key and value\n\t\t// are specified, set or extend (existing objects) with either:\n\t\t//\n\t\t//   1. An object of properties\n\t\t//   2. A key and value\n\t\t//\n\t\tthis.set( owner, key, value );\n\n\t\t// Since the \"set\" path can have two possible entry points\n\t\t// return the expected data based on which path was taken[*]\n\t\treturn value !== undefined ? value : key;\n\t},\n\tremove: function( owner, key ) {\n\t\tvar i, name, camel,\n\t\t\tunlock = this.key( owner ),\n\t\t\tcache = this.cache[ unlock ];\n\n\t\tif ( key === undefined ) {\n\t\t\tthis.cache[ unlock ] = {};\n\n\t\t} else {\n\t\t\t// Support array or space separated string of keys\n\t\t\tif ( jQuery.isArray( key ) ) {\n\t\t\t\t// If \"name\" is an array of keys...\n\t\t\t\t// When data is initially created, via (\"key\", \"val\") signature,\n\t\t\t\t// keys will be converted to camelCase.\n\t\t\t\t// Since there is no way to tell _how_ a key was added, remove\n\t\t\t\t// both plain key and camelCase key. #12786\n\t\t\t\t// This will only penalize the array argument path.\n\t\t\t\tname = key.concat( key.map( jQuery.camelCase ) );\n\t\t\t} else {\n\t\t\t\tcamel = jQuery.camelCase( key );\n\t\t\t\t// Try the string as a key before any manipulation\n\t\t\t\tif ( key in cache ) {\n\t\t\t\t\tname = [ key, camel ];\n\t\t\t\t} else {\n\t\t\t\t\t// If a key with the spaces exists, use it.\n\t\t\t\t\t// Otherwise, create an array by matching non-whitespace\n\t\t\t\t\tname = camel;\n\t\t\t\t\tname = name in cache ?\n\t\t\t\t\t\t[ name ] : ( name.match( core_rnotwhite ) || [] );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\ti = name.length;\n\t\t\twhile ( i-- ) {\n\t\t\t\tdelete cache[ name[ i ] ];\n\t\t\t}\n\t\t}\n\t},\n\thasData: function( owner ) {\n\t\treturn !jQuery.isEmptyObject(\n\t\t\tthis.cache[ owner[ this.expando ] ] || {}\n\t\t);\n\t},\n\tdiscard: function( owner ) {\n\t\tif ( owner[ this.expando ] ) {\n\t\t\tdelete this.cache[ owner[ this.expando ] ];\n\t\t}\n\t}\n};\n\n// These may be used throughout the jQuery core codebase\ndata_user = new Data();\ndata_priv = new Data();\n\n\njQuery.extend({\n\tacceptData: Data.accepts,\n\n\thasData: function( elem ) {\n\t\treturn data_user.hasData( elem ) || data_priv.hasData( elem );\n\t},\n\n\tdata: function( elem, name, data ) {\n\t\treturn data_user.access( elem, name, data );\n\t},\n\n\tremoveData: function( elem, name ) {\n\t\tdata_user.remove( elem, name );\n\t},\n\n\t// TODO: Now that all calls to _data and _removeData have been replaced\n\t// with direct calls to data_priv methods, these can be deprecated.\n\t_data: function( elem, name, data ) {\n\t\treturn data_priv.access( elem, name, data );\n\t},\n\n\t_removeData: function( elem, name ) {\n\t\tdata_priv.remove( elem, name );\n\t}\n});\n\njQuery.fn.extend({\n\tdata: function( key, value ) {\n\t\tvar attrs, name,\n\t\t\telem = this[ 0 ],\n\t\t\ti = 0,\n\t\t\tdata = null;\n\n\t\t// Gets all values\n\t\tif ( key === undefined ) {\n\t\t\tif ( this.length ) {\n\t\t\t\tdata = data_user.get( elem );\n\n\t\t\t\tif ( elem.nodeType === 1 && !data_priv.get( elem, \"hasDataAttrs\" ) ) {\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\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\tdata_priv.set( elem, \"hasDataAttrs\", true );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn data;\n\t\t}\n\n\t\t// Sets multiple values\n\t\tif ( typeof key === \"object\" ) {\n\t\t\treturn this.each(function() {\n\t\t\t\tdata_user.set( this, key );\n\t\t\t});\n\t\t}\n\n\t\treturn jQuery.access( this, function( value ) {\n\t\t\tvar data,\n\t\t\t\tcamelKey = jQuery.camelCase( key );\n\n\t\t\t// The calling jQuery object (element matches) is not empty\n\t\t\t// (and therefore has an element appears at this[ 0 ]) and the\n\t\t\t// `value` parameter was not undefined. An empty jQuery object\n\t\t\t// will result in `undefined` for elem = this[ 0 ] which will\n\t\t\t// throw an exception if an attempt to read a data cache is made.\n\t\t\tif ( elem && value === undefined ) {\n\t\t\t\t// Attempt to get data from the cache\n\t\t\t\t// with the key as-is\n\t\t\t\tdata = data_user.get( elem, key );\n\t\t\t\tif ( data !== undefined ) {\n\t\t\t\t\treturn data;\n\t\t\t\t}\n\n\t\t\t\t// Attempt to get data from the cache\n\t\t\t\t// with the key camelized\n\t\t\t\tdata = data_user.get( elem, camelKey );\n\t\t\t\tif ( data !== undefined ) {\n\t\t\t\t\treturn data;\n\t\t\t\t}\n\n\t\t\t\t// Attempt to \"discover\" the data in\n\t\t\t\t// HTML5 custom data-* attrs\n\t\t\t\tdata = dataAttr( elem, camelKey, undefined );\n\t\t\t\tif ( data !== undefined ) {\n\t\t\t\t\treturn data;\n\t\t\t\t}\n\n\t\t\t\t// We tried really hard, but the data doesn't exist.\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Set the data...\n\t\t\tthis.each(function() {\n\t\t\t\t// First, attempt to store a copy or reference of any\n\t\t\t\t// data that might've been store with a camelCased key.\n\t\t\t\tvar data = data_user.get( this, camelKey );\n\n\t\t\t\t// For HTML5 data-* attribute interop, we have to\n\t\t\t\t// store property names with dashes in a camelCase form.\n\t\t\t\t// This might not apply to all properties...*\n\t\t\t\tdata_user.set( this, camelKey, value );\n\n\t\t\t\t// *... In the case of properties that might _actually_\n\t\t\t\t// have dashes, we need to also store a copy of that\n\t\t\t\t// unchanged property.\n\t\t\t\tif ( key.indexOf(\"-\") !== -1 && data !== undefined ) {\n\t\t\t\t\tdata_user.set( this, key, value );\n\t\t\t\t}\n\t\t\t});\n\t\t}, null, value, arguments.length > 1, null, true );\n\t},\n\n\tremoveData: function( key ) {\n\t\treturn this.each(function() {\n\t\t\tdata_user.remove( this, key );\n\t\t});\n\t}\n});\n\nfunction dataAttr( elem, key, data ) {\n\tvar name;\n\n\t// If nothing was found internally, try to fetch any\n\t// data from the HTML5 data-* attribute\n\tif ( data === undefined && elem.nodeType === 1 ) {\n\t\tname = \"data-\" + key.replace( rmultiDash, \"-$1\" ).toLowerCase();\n\t\tdata = elem.getAttribute( name );\n\n\t\tif ( typeof data === \"string\" ) {\n\t\t\ttry {\n\t\t\t\tdata = data === \"true\" ? true :\n\t\t\t\t\tdata === \"false\" ? false :\n\t\t\t\t\tdata === \"null\" ? null :\n\t\t\t\t\t// Only convert to a number if it doesn't change the string\n\t\t\t\t\t+data + \"\" === data ? +data :\n\t\t\t\t\trbrace.test( data ) ? JSON.parse( data ) :\n\t\t\t\t\tdata;\n\t\t\t} catch( e ) {}\n\n\t\t\t// Make sure we set the data so it isn't changed later\n\t\t\tdata_user.set( elem, key, data );\n\t\t} else {\n\t\t\tdata = undefined;\n\t\t}\n\t}\n\treturn data;\n}\njQuery.extend({\n\tqueue: function( elem, type, data ) {\n\t\tvar queue;\n\n\t\tif ( elem ) {\n\t\t\ttype = ( type || \"fx\" ) + \"queue\";\n\t\t\tqueue = data_priv.get( elem, type );\n\n\t\t\t// Speed up dequeue by getting out quickly if this is just a lookup\n\t\t\tif ( data ) {\n\t\t\t\tif ( !queue || jQuery.isArray( data ) ) {\n\t\t\t\t\tqueue = data_priv.access( elem, type, jQuery.makeArray(data) );\n\t\t\t\t} else {\n\t\t\t\t\tqueue.push( data );\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn queue || [];\n\t\t}\n\t},\n\n\tdequeue: function( elem, type ) {\n\t\ttype = type || \"fx\";\n\n\t\tvar queue = jQuery.queue( elem, type ),\n\t\t\tstartLength = queue.length,\n\t\t\tfn = queue.shift(),\n\t\t\thooks = jQuery._queueHooks( elem, type ),\n\t\t\tnext = function() {\n\t\t\t\tjQuery.dequeue( elem, type );\n\t\t\t};\n\n\t\t// If the fx queue is dequeued, always remove the progress sentinel\n\t\tif ( fn === \"inprogress\" ) {\n\t\t\tfn = queue.shift();\n\t\t\tstartLength--;\n\t\t}\n\n\t\tif ( fn ) {\n\n\t\t\t// Add a progress sentinel to prevent the fx queue from being\n\t\t\t// automatically dequeued\n\t\t\tif ( type === \"fx\" ) {\n\t\t\t\tqueue.unshift( \"inprogress\" );\n\t\t\t}\n\n\t\t\t// clear up the last queue stop function\n\t\t\tdelete hooks.stop;\n\t\t\tfn.call( elem, next, hooks );\n\t\t}\n\n\t\tif ( !startLength && hooks ) {\n\t\t\thooks.empty.fire();\n\t\t}\n\t},\n\n\t// not 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 data_priv.get( elem, key ) || data_priv.access( elem, key, {\n\t\t\tempty: jQuery.Callbacks(\"once memory\").add(function() {\n\t\t\t\tdata_priv.remove( elem, [ type + \"queue\", key ] );\n\t\t\t})\n\t\t});\n\t}\n});\n\njQuery.fn.extend({\n\tqueue: function( type, data ) {\n\t\tvar setter = 2;\n\n\t\tif ( typeof type !== \"string\" ) {\n\t\t\tdata = type;\n\t\t\ttype = \"fx\";\n\t\t\tsetter--;\n\t\t}\n\n\t\tif ( arguments.length < setter ) {\n\t\t\treturn jQuery.queue( this[0], type );\n\t\t}\n\n\t\treturn data === undefined ?\n\t\t\tthis :\n\t\t\tthis.each(function() {\n\t\t\t\tvar queue = jQuery.queue( this, type, data );\n\n\t\t\t\t// ensure a hooks for this queue\n\t\t\t\tjQuery._queueHooks( this, type );\n\n\t\t\t\tif ( type === \"fx\" && queue[0] !== \"inprogress\" ) {\n\t\t\t\t\tjQuery.dequeue( this, type );\n\t\t\t\t}\n\t\t\t});\n\t},\n\tdequeue: function( type ) {\n\t\treturn this.each(function() {\n\t\t\tjQuery.dequeue( this, type );\n\t\t});\n\t},\n\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 = data_priv.get( elements[ i ], type + \"queueHooks\" );\n\t\t\tif ( tmp && tmp.empty ) {\n\t\t\t\tcount++;\n\t\t\t\ttmp.empty.add( resolve );\n\t\t\t}\n\t\t}\n\t\tresolve();\n\t\treturn defer.promise( obj );\n\t}\n});\nvar nodeHook, boolHook,\n\trclass = /[\\t\\r\\n\\f]/g,\n\trreturn = /\\r/g,\n\trfocusable = /^(?:input|select|textarea|button)$/i;\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\treturn this.each(function() {\n\t\t\tdelete this[ jQuery.propFix[ name ] || name ];\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\tdata_priv.set( this, \"__className__\", this.className );\n\t\t\t\t}\n\n\t\t\t\t// If the element has a class name or if we're passed \"false\",\n\t\t\t\t// then remove the whole classname (if there was one, the above saved it).\n\t\t\t\t// Otherwise bring back whatever was previously saved (if anything),\n\t\t\t\t// falling back to the empty string if nothing was stored.\n\t\t\t\tthis.className = this.className || value === false ? \"\" : data_priv.get( this, \"__className__\" ) || \"\";\n\t\t\t}\n\t\t});\n\t},\n\n\thasClass: function( selector ) {\n\t\tvar className = \" \" + selector + \" \",\n\t\t\ti = 0,\n\t\t\tl = this.length;\n\t\tfor ( ; i < l; i++ ) {\n\t\t\tif ( this[i].nodeType === 1 && (\" \" + this[i].className + \" \").replace(rclass, \" \").indexOf( className ) >= 0 ) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\n\t\treturn false;\n\t},\n\n\tval: function( value ) {\n\t\tvar hooks, ret, isFunction,\n\t\t\telem = this[0];\n\n\t\tif ( !arguments.length ) {\n\t\t\tif ( elem ) {\n\t\t\t\thooks = jQuery.valHooks[ elem.type ] || jQuery.valHooks[ elem.nodeName.toLowerCase() ];\n\n\t\t\t\tif ( hooks && \"get\" in hooks && (ret = hooks.get( elem, \"value\" )) !== undefined ) {\n\t\t\t\t\treturn ret;\n\t\t\t\t}\n\n\t\t\t\tret = elem.value;\n\n\t\t\t\treturn typeof ret === \"string\" ?\n\t\t\t\t\t// handle most common string cases\n\t\t\t\t\tret.replace(rreturn, \"\") :\n\t\t\t\t\t// handle cases where value is null/undef or number\n\t\t\t\t\tret == null ? \"\" : ret;\n\t\t\t}\n\n\t\t\treturn;\n\t\t}\n\n\t\tisFunction = jQuery.isFunction( value );\n\n\t\treturn this.each(function( i ) {\n\t\t\tvar val;\n\n\t\t\tif ( this.nodeType !== 1 ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif ( isFunction ) {\n\t\t\t\tval = value.call( this, i, jQuery( this ).val() );\n\t\t\t} else {\n\t\t\t\tval = value;\n\t\t\t}\n\n\t\t\t// Treat null/undefined as \"\"; convert numbers to string\n\t\t\tif ( val == null ) {\n\t\t\t\tval = \"\";\n\t\t\t} else if ( typeof val === \"number\" ) {\n\t\t\t\tval += \"\";\n\t\t\t} else if ( jQuery.isArray( val ) ) {\n\t\t\t\tval = jQuery.map(val, function ( value ) {\n\t\t\t\t\treturn value == null ? \"\" : value + \"\";\n\t\t\t\t});\n\t\t\t}\n\n\t\t\thooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ];\n\n\t\t\t// If set returns undefined, fall back to normal setting\n\t\t\tif ( !hooks || !(\"set\" in hooks) || hooks.set( this, val, \"value\" ) === undefined ) {\n\t\t\t\tthis.value = val;\n\t\t\t}\n\t\t});\n\t}\n});\n\njQuery.extend({\n\tvalHooks: {\n\t\toption: {\n\t\t\tget: function( elem ) {\n\t\t\t\t// attributes.value is undefined in Blackberry 4.7 but\n\t\t\t\t// uses .value. See #6932\n\t\t\t\tvar val = elem.attributes.value;\n\t\t\t\treturn !val || val.specified ? elem.value : elem.text;\n\t\t\t}\n\t\t},\n\t\tselect: {\n\t\t\tget: function( elem ) {\n\t\t\t\tvar value, option,\n\t\t\t\t\toptions = elem.options,\n\t\t\t\t\tindex = elem.selectedIndex,\n\t\t\t\t\tone = elem.type === \"select-one\" || index < 0,\n\t\t\t\t\tvalues = one ? null : [],\n\t\t\t\t\tmax = one ? index + 1 : options.length,\n\t\t\t\t\ti = index < 0 ?\n\t\t\t\t\t\tmax :\n\t\t\t\t\t\tone ? index : 0;\n\n\t\t\t\t// Loop through all the selected options\n\t\t\t\tfor ( ; i < max; i++ ) {\n\t\t\t\t\toption = options[ i ];\n\n\t\t\t\t\t// IE6-9 doesn't update selected after form reset (#2551)\n\t\t\t\t\tif ( ( option.selected || i === index ) &&\n\t\t\t\t\t\t\t// Don't return options that are disabled or in a disabled optgroup\n\t\t\t\t\t\t\t( 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\telem[ propName ] = false;\n\t\t\t\t}\n\n\t\t\t\telem.removeAttribute( name );\n\t\t\t}\n\t\t}\n\t},\n\n\tattrHooks: {\n\t\ttype: {\n\t\t\tset: function( elem, value ) {\n\t\t\t\tif ( !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\treturn elem.hasAttribute( \"tabindex\" ) || rfocusable.test( elem.nodeName ) || elem.href ?\n\t\t\t\t\telem.tabIndex :\n\t\t\t\t\t-1;\n\t\t\t}\n\t\t}\n\t}\n});\n\n// Hooks for boolean attributes\nboolHook = {\n\tset: function( elem, value, name ) {\n\t\tif ( value === false ) {\n\t\t\t// Remove boolean attributes when set to false\n\t\t\tjQuery.removeAttr( elem, name );\n\t\t} else {\n\t\t\telem.setAttribute( name, name );\n\t\t}\n\t\treturn name;\n\t}\n};\njQuery.each( jQuery.expr.match.bool.source.match( /\\w+/g ), function( i, name ) {\n\tvar getter = jQuery.expr.attrHandle[ name ] || jQuery.find.attr;\n\n\tjQuery.expr.attrHandle[ name ] = function( elem, name, isXML ) {\n\t\tvar fn = jQuery.expr.attrHandle[ name ],\n\t\t\tret = isXML ?\n\t\t\t\tundefined :\n\t\t\t\t/* jshint eqeqeq: false */\n\t\t\t\t// Temporarily disable this handler to check existence\n\t\t\t\t(jQuery.expr.attrHandle[ name ] = undefined) !=\n\t\t\t\t\tgetter( elem, name, isXML ) ?\n\n\t\t\t\t\tname.toLowerCase() :\n\t\t\t\t\tnull;\n\n\t\t// Restore handler\n\t\tjQuery.expr.attrHandle[ name ] = fn;\n\n\t\treturn ret;\n\t};\n});\n\n// Support: IE9+\n// Selectedness for an option in an optgroup can be inaccurate\nif ( !jQuery.support.optSelected ) {\n\tjQuery.propHooks.selected = {\n\t\tget: function( elem ) {\n\t\t\tvar parent = elem.parentNode;\n\t\t\tif ( parent && parent.parentNode ) {\n\t\t\t\tparent.parentNode.selectedIndex;\n\t\t\t}\n\t\t\treturn null;\n\t\t}\n\t};\n}\n\njQuery.each([\n\t\"tabIndex\",\n\t\"readOnly\",\n\t\"maxLength\",\n\t\"cellSpacing\",\n\t\"cellPadding\",\n\t\"rowSpan\",\n\t\"colSpan\",\n\t\"useMap\",\n\t\"frameBorder\",\n\t\"contentEditable\"\n], function() {\n\tjQuery.propFix[ this.toLowerCase() ] = this;\n});\n\n// 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 rkeyEvent = /^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\n\t\tvar handleObjIn, eventHandle, tmp,\n\t\t\tevents, t, handleObj,\n\t\t\tspecial, handlers, type, namespaces, origType,\n\t\t\telemData = data_priv.get( elem );\n\n\t\t// Don't attach events to noData or text/comment nodes (but allow plain objects)\n\t\tif ( !elemData ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Caller can pass in an object of custom data in lieu of the handler\n\t\tif ( handler.handler ) {\n\t\t\thandleObjIn = handler;\n\t\t\thandler = handleObjIn.handler;\n\t\t\tselector = handleObjIn.selector;\n\t\t}\n\n\t\t// Make sure that the handler has a unique ID, used to find/remove it later\n\t\tif ( !handler.guid ) {\n\t\t\thandler.guid = jQuery.guid++;\n\t\t}\n\n\t\t// Init the element's event structure and main handler, if this is the first\n\t\tif ( !(events = elemData.events) ) {\n\t\t\tevents = elemData.events = {};\n\t\t}\n\t\tif ( !(eventHandle = elemData.handle) ) {\n\t\t\teventHandle = elemData.handle = function( e ) {\n\t\t\t\t// Discard the second event of a jQuery.event.trigger() and\n\t\t\t\t// when an event is called after a page has unloaded\n\t\t\t\treturn typeof jQuery !== 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 if the special events handler returns false\n\t\t\t\tif ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) {\n\t\t\t\t\tif ( elem.addEventListener ) {\n\t\t\t\t\t\telem.addEventListener( type, eventHandle, false );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( special.add ) {\n\t\t\t\tspecial.add.call( elem, handleObj );\n\n\t\t\t\tif ( !handleObj.handler.guid ) {\n\t\t\t\t\thandleObj.handler.guid = handler.guid;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Add to the element's handler list, delegates in front\n\t\t\tif ( selector ) {\n\t\t\t\thandlers.splice( handlers.delegateCount++, 0, handleObj );\n\t\t\t} else {\n\t\t\t\thandlers.push( handleObj );\n\t\t\t}\n\n\t\t\t// Keep track of which events have ever been used, for event optimization\n\t\t\tjQuery.event.global[ type ] = true;\n\t\t}\n\n\t\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\n\t\tvar j, origCount, tmp,\n\t\t\tevents, t, handleObj,\n\t\t\tspecial, handlers, type, namespaces, origType,\n\t\t\telemData = data_priv.hasData( elem ) && data_priv.get( elem );\n\n\t\tif ( !elemData || !(events = elemData.events) ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Once for each type.namespace in types; type may be omitted\n\t\ttypes = ( types || \"\" ).match( 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\t\t\tdata_priv.remove( elem, \"events\" );\n\t\t}\n\t},\n\n\ttrigger: function( event, data, elem, onlyHandlers ) {\n\n\t\tvar i, cur, tmp, bubbleType, ontype, handle, special,\n\t\t\teventPath = [ elem || document ],\n\t\t\ttype = 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 = ( data_priv.get( cur, \"events\" ) || {} )[ event.type ] && data_priv.get( cur, \"handle\" );\n\t\t\tif ( handle ) {\n\t\t\t\thandle.apply( cur, data );\n\t\t\t}\n\n\t\t\t// Native handler\n\t\t\thandle = ontype && cur[ ontype ];\n\t\t\tif ( handle && 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// Don't do default actions on window, that's where global variables be (#6170)\n\t\t\t\tif ( ontype && jQuery.isFunction( elem[ type ] ) && !jQuery.isWindow( elem ) ) {\n\n\t\t\t\t\t// Don't re-trigger an onFOO event when we call its FOO() method\n\t\t\t\t\ttmp = elem[ ontype ];\n\n\t\t\t\t\tif ( tmp ) {\n\t\t\t\t\t\telem[ ontype ] = null;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Prevent re-triggering of the same event, since we already bubbled it above\n\t\t\t\t\tjQuery.event.triggered = type;\n\t\t\t\t\telem[ type ]();\n\t\t\t\t\tjQuery.event.triggered = undefined;\n\n\t\t\t\t\tif ( tmp ) {\n\t\t\t\t\t\telem[ ontype ] = tmp;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn event.result;\n\t},\n\n\tdispatch: function( event ) {\n\n\t\t// Make a writable jQuery.Event from the native event object\n\t\tevent = jQuery.event.fix( event );\n\n\t\tvar i, j, ret, matched, handleObj,\n\t\t\thandlerQueue = [],\n\t\t\targs = core_slice.call( arguments ),\n\t\t\thandlers = ( data_priv.get( this, \"events\" ) || {} )[ event.type ] || [],\n\t\t\tspecial = jQuery.event.special[ event.type ] || {};\n\n\t\t// Use the fix-ed jQuery.Event rather than the (read-only) native event\n\t\targs[0] = event;\n\t\tevent.delegateTarget = this;\n\n\t\t// Call the preDispatch hook for the mapped type, and let it bail if desired\n\t\tif ( special.preDispatch && special.preDispatch.call( this, event ) === false ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Determine handlers\n\t\thandlerQueue = jQuery.event.handlers.call( this, event, handlers );\n\n\t\t// Run delegates first; they may want to stop propagation beneath us\n\t\ti = 0;\n\t\twhile ( (matched = handlerQueue[ i++ ]) && !event.isPropagationStopped() ) {\n\t\t\tevent.currentTarget = matched.elem;\n\n\t\t\tj = 0;\n\t\t\twhile ( (handleObj = matched.handlers[ j++ ]) && !event.isImmediatePropagationStopped() ) {\n\n\t\t\t\t// Triggered event must either 1) have no namespace, or\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 i, matches, sel, handleObj,\n\t\t\thandlerQueue = [],\n\t\t\tdelegateCount = handlers.delegateCount,\n\t\t\tcur = event.target;\n\n\t\t// Find delegate handlers\n\t\t// Black-hole SVG <use> instance trees (#13180)\n\t\t// Avoid non-left-click bubbling in Firefox (#3861)\n\t\tif ( delegateCount && cur.nodeType && (!event.button || event.type !== \"click\") ) {\n\n\t\t\tfor ( ; cur !== this; cur = cur.parentNode || this ) {\n\n\t\t\t\t// Don't process clicks on disabled elements (#6911, #8165, #11382, #11764)\n\t\t\t\tif ( cur.disabled !== true || event.type !== \"click\" ) {\n\t\t\t\t\tmatches = [];\n\t\t\t\t\tfor ( i = 0; i < delegateCount; i++ ) {\n\t\t\t\t\t\thandleObj = handlers[ i ];\n\n\t\t\t\t\t\t// Don't conflict with Object.prototype properties (#13203)\n\t\t\t\t\t\tsel = handleObj.selector + \" \";\n\n\t\t\t\t\t\tif ( matches[ sel ] === undefined ) {\n\t\t\t\t\t\t\tmatches[ sel ] = handleObj.needsContext ?\n\t\t\t\t\t\t\t\tjQuery( sel, this ).index( cur ) >= 0 :\n\t\t\t\t\t\t\t\tjQuery.find( sel, this, null, [ cur ] ).length;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif ( matches[ sel ] ) {\n\t\t\t\t\t\t\tmatches.push( handleObj );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif ( matches.length ) {\n\t\t\t\t\t\thandlerQueue.push({ elem: cur, handlers: matches });\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Add the remaining (directly-bound) handlers\n\t\tif ( delegateCount < handlers.length ) {\n\t\t\thandlerQueue.push({ elem: this, handlers: handlers.slice( delegateCount ) });\n\t\t}\n\n\t\treturn handlerQueue;\n\t},\n\n\t// Includes some event props shared by KeyEvent and MouseEvent\n\tprops: \"altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which\".split(\" \"),\n\n\tfixHooks: {},\n\n\tkeyHooks: {\n\t\tprops: \"char charCode key keyCode\".split(\" \"),\n\t\tfilter: function( event, original ) {\n\n\t\t\t// Add which for key events\n\t\t\tif ( event.which == null ) {\n\t\t\t\tevent.which = original.charCode != null ? original.charCode : original.keyCode;\n\t\t\t}\n\n\t\t\treturn event;\n\t\t}\n\t},\n\n\tmouseHooks: {\n\t\tprops: \"button buttons clientX clientY offsetX offsetY pageX pageY screenX screenY toElement\".split(\" \"),\n\t\tfilter: function( event, original ) {\n\t\t\tvar eventDoc, doc, body,\n\t\t\t\tbutton = original.button;\n\n\t\t\t// Calculate pageX/Y if missing and clientX/Y available\n\t\t\tif ( event.pageX == null && original.clientX != null ) {\n\t\t\t\teventDoc = event.target.ownerDocument || document;\n\t\t\t\tdoc = eventDoc.documentElement;\n\t\t\t\tbody = eventDoc.body;\n\n\t\t\t\tevent.pageX = original.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && body.clientLeft || 0 );\n\t\t\t\tevent.pageY = original.clientY + ( doc && doc.scrollTop  || body && body.scrollTop  || 0 ) - ( doc && doc.clientTop  || body && body.clientTop  || 0 );\n\t\t\t}\n\n\t\t\t// Add which for click: 1 === left; 2 === middle; 3 === right\n\t\t\t// Note: button is not normalized, so don't use it\n\t\t\tif ( !event.which && button !== undefined ) {\n\t\t\t\tevent.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) );\n\t\t\t}\n\n\t\t\treturn event;\n\t\t}\n\t},\n\n\tfix: function( event ) {\n\t\tif ( event[ jQuery.expando ] ) {\n\t\t\treturn event;\n\t\t}\n\n\t\t// Create a writable copy of the event object and normalize some properties\n\t\tvar i, prop, copy,\n\t\t\ttype = event.type,\n\t\t\toriginalEvent = event,\n\t\t\tfixHook = this.fixHooks[ type ];\n\n\t\tif ( !fixHook ) {\n\t\t\tthis.fixHooks[ type ] = fixHook =\n\t\t\t\trmouseEvent.test( type ) ? this.mouseHooks :\n\t\t\t\trkeyEvent.test( type ) ? this.keyHooks :\n\t\t\t\t{};\n\t\t}\n\t\tcopy = fixHook.props ? this.props.concat( fixHook.props ) : this.props;\n\n\t\tevent = new jQuery.Event( originalEvent );\n\n\t\ti = copy.length;\n\t\twhile ( i-- ) {\n\t\t\tprop = copy[ i ];\n\t\t\tevent[ prop ] = originalEvent[ prop ];\n\t\t}\n\n\t\t// Support: Cordova 2.5 (WebKit) (#13255)\n\t\t// All events should have a target; Cordova deviceready doesn't\n\t\tif ( !event.target ) {\n\t\t\tevent.target = document;\n\t\t}\n\n\t\t// Support: Safari 6.0+, Chrome < 28\n\t\t// Target should not be a text node (#504, #13143)\n\t\tif ( event.target.nodeType === 3 ) {\n\t\t\tevent.target = event.target.parentNode;\n\t\t}\n\n\t\treturn fixHook.filter? fixHook.filter( event, originalEvent ) : event;\n\t},\n\n\tspecial: {\n\t\tload: {\n\t\t\t// Prevent triggered image.load events from bubbling to window.load\n\t\t\tnoBubble: true\n\t\t},\n\t\tfocus: {\n\t\t\t// Fire native event if possible so blur/focus sequence is correct\n\t\t\ttrigger: function() {\n\t\t\t\tif ( this !== safeActiveElement() && this.focus ) {\n\t\t\t\t\tthis.focus();\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t},\n\t\t\tdelegateType: \"focusin\"\n\t\t},\n\t\tblur: {\n\t\t\ttrigger: function() {\n\t\t\t\tif ( this === safeActiveElement() && this.blur ) {\n\t\t\t\t\tthis.blur();\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t},\n\t\t\tdelegateType: \"focusout\"\n\t\t},\n\t\tclick: {\n\t\t\t// For checkbox, fire native event so checked state will be right\n\t\t\ttrigger: function() {\n\t\t\t\tif ( this.type === \"checkbox\" && this.click && jQuery.nodeName( this, \"input\" ) ) {\n\t\t\t\t\tthis.click();\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t},\n\n\t\t\t// For cross-browser consistency, don't fire native .click() on links\n\t\t\t_default: function( event ) {\n\t\t\t\treturn jQuery.nodeName( event.target, \"a\" );\n\t\t\t}\n\t\t},\n\n\t\tbeforeunload: {\n\t\t\tpostDispatch: function( event ) {\n\n\t\t\t\t// Support: Firefox 20+\n\t\t\t\t// Firefox doesn't alert if the returnValue field is not set.\n\t\t\t\tif ( event.result !== undefined ) {\n\t\t\t\t\tevent.originalEvent.returnValue = event.result;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\n\tsimulate: function( type, elem, event, bubble ) {\n\t\t// Piggyback on a donor event to simulate a different one.\n\t\t// Fake originalEvent to avoid donor's stopPropagation, but if the\n\t\t// simulated event prevents default then we do the same on the donor.\n\t\tvar e = jQuery.extend(\n\t\t\tnew jQuery.Event(),\n\t\t\tevent,\n\t\t\t{\n\t\t\t\ttype: type,\n\t\t\t\tisSimulated: true,\n\t\t\t\toriginalEvent: {}\n\t\t\t}\n\t\t);\n\t\tif ( bubble ) {\n\t\t\tjQuery.event.trigger( e, null, elem );\n\t\t} else {\n\t\t\tjQuery.event.dispatch.call( elem, e );\n\t\t}\n\t\tif ( e.isDefaultPrevented() ) {\n\t\t\tevent.preventDefault();\n\t\t}\n\t}\n};\n\njQuery.removeEvent = function( elem, type, handle ) {\n\tif ( elem.removeEventListener ) {\n\t\telem.removeEventListener( type, handle, false );\n\t}\n};\n\njQuery.Event = function( src, props ) {\n\t// Allow instantiation without the 'new' keyword\n\tif ( !(this instanceof jQuery.Event) ) {\n\t\treturn new jQuery.Event( src, props );\n\t}\n\n\t// Event object\n\tif ( src && src.type ) {\n\t\tthis.originalEvent = src;\n\t\tthis.type = src.type;\n\n\t\t// Events bubbling up the document may have been marked as prevented\n\t\t// by a handler lower down the tree; reflect the correct value.\n\t\tthis.isDefaultPrevented = ( src.defaultPrevented ||\n\t\t\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\n\t\tif ( e && e.preventDefault ) {\n\t\t\te.preventDefault();\n\t\t}\n\t},\n\tstopPropagation: function() {\n\t\tvar e = this.originalEvent;\n\n\t\tthis.isPropagationStopped = returnTrue;\n\n\t\tif ( e && e.stopPropagation ) {\n\t\t\te.stopPropagation();\n\t\t}\n\t},\n\tstopImmediatePropagation: function() {\n\t\tthis.isImmediatePropagationStopped = returnTrue;\n\t\tthis.stopPropagation();\n\t}\n};\n\n// Create mouseenter/leave events using mouseover/out and event-time checks\n// Support: Chrome 15+\njQuery.each({\n\tmouseenter: \"mouseover\",\n\tmouseleave: \"mouseout\"\n}, 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// Create \"bubbling\" focus and blur events\n// Support: Firefox, Chrome, Safari\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 = 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 targets = jQuery( target, this ),\n\t\t\tl = targets.length;\n\n\t\treturn this.filter(function() {\n\t\t\tvar i = 0;\n\t\t\tfor ( ; i < l; i++ ) {\n\t\t\t\tif ( jQuery.contains( this, targets[i] ) ) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t},\n\n\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\tmatched = [],\n\t\t\tpos = ( rneedsContext.test( selectors ) || typeof selectors !== \"string\" ) ?\n\t\t\t\tjQuery( selectors, context || this.context ) :\n\t\t\t\t0;\n\n\t\tfor ( ; i < l; i++ ) {\n\t\t\tfor ( cur = this[i]; cur && cur !== context; cur = cur.parentNode ) {\n\t\t\t\t// Always skip document fragments\n\t\t\t\tif ( cur.nodeType < 11 && (pos ?\n\t\t\t\t\tpos.index(cur) > -1 :\n\n\t\t\t\t\t// Don't pass non-elements to Sizzle\n\t\t\t\t\tcur.nodeType === 1 &&\n\t\t\t\t\t\tjQuery.find.matchesSelector(cur, selectors)) ) {\n\n\t\t\t\t\tcur = matched.push( cur );\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn this.pushStack( matched.length > 1 ? jQuery.unique( matched ) : matched );\n\t},\n\n\t// Determine the position of an element within\n\t// the matched set of elements\n\tindex: function( elem ) {\n\n\t\t// No argument, return index in parent\n\t\tif ( !elem ) {\n\t\t\treturn ( this[ 0 ] && this[ 0 ].parentNode ) ? this.first().prevAll().length : -1;\n\t\t}\n\n\t\t// index in selector\n\t\tif ( typeof elem === \"string\" ) {\n\t\t\treturn core_indexOf.call( jQuery( elem ), this[ 0 ] );\n\t\t}\n\n\t\t// Locate the position of the desired element\n\t\treturn core_indexOf.call( this,\n\n\t\t\t// If it receives a jQuery object, the first element is used\n\t\t\telem.jquery ? elem[ 0 ] : elem\n\t\t);\n\t},\n\n\tadd: function( selector, context ) {\n\t\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\twhile ( (cur = cur[dir]) && 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 elem.contentDocument || jQuery.merge( [], elem.childNodes );\n\t}\n}, function( name, fn ) {\n\tjQuery.fn[ name ] = function( until, selector ) {\n\t\tvar matched = jQuery.map( this, fn, until );\n\n\t\tif ( name.slice( -5 ) !== \"Until\" ) {\n\t\t\tselector = until;\n\t\t}\n\n\t\tif ( selector && typeof selector === \"string\" ) {\n\t\t\tmatched = jQuery.filter( selector, matched );\n\t\t}\n\n\t\tif ( this.length > 1 ) {\n\t\t\t// Remove duplicates\n\t\t\tif ( !guaranteedUnique[ name ] ) {\n\t\t\t\tjQuery.unique( matched );\n\t\t\t}\n\n\t\t\t// Reverse order for parents* and prev-derivatives\n\t\t\tif ( rparentsprev.test( name ) ) {\n\t\t\t\tmatched.reverse();\n\t\t\t}\n\t\t}\n\n\t\treturn this.pushStack( matched );\n\t};\n});\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\ttruncate = until !== undefined;\n\n\t\twhile ( (elem = elem[ dir ]) && elem.nodeType !== 9 ) {\n\t\t\tif ( elem.nodeType === 1 ) {\n\t\t\t\tif ( truncate && jQuery( elem ).is( until ) ) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tmatched.push( elem );\n\t\t\t}\n\t\t}\n\t\treturn matched;\n\t},\n\n\tsibling: function( n, elem ) {\n\t\tvar matched = [];\n\n\t\tfor ( ; n; n = n.nextSibling ) {\n\t\t\tif ( n.nodeType === 1 && n !== elem ) {\n\t\t\t\tmatched.push( n );\n\t\t\t}\n\t\t}\n\n\t\treturn matched;\n\t}\n});\n\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 ( core_indexOf.call( qualifier, elem ) >= 0 ) !== not;\n\t});\n}\nvar rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\\w:]+)[^>]*)\\/>/gi,\n\trtagName = /<([\\w:]+)/,\n\trhtml = /<|&#?\\w+;/,\n\trnoInnerhtml = /<(?:script|style|link)/i,\n\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\n\t\t// Support: IE 9\n\t\toption: [ 1, \"<select multiple='multiple'>\", \"</select>\" ],\n\n\t\tthead: [ 1, \"<table>\", \"</table>\" ],\n\t\tcol: [ 2, \"<table><colgroup>\", \"</colgroup></table>\" ],\n\t\ttr: [ 2, \"<table><tbody>\", \"</tbody></table>\" ],\n\t\ttd: [ 3, \"<table><tbody><tr>\", \"</tr></tbody></table>\" ],\n\n\t\t_default: [ 0, \"\", \"\" ]\n\t};\n\n// Support: IE 9\nwrapMap.optgroup = wrapMap.option;\n\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\t\t\tif ( !keepData && elem.nodeType === 1 ) {\n\t\t\t\tjQuery.cleanData( getAll( elem ) );\n\t\t\t}\n\n\t\t\tif ( elem.parentNode ) {\n\t\t\t\tif ( keepData && jQuery.contains( elem.ownerDocument, elem ) ) {\n\t\t\t\t\tsetGlobalEval( getAll( elem, \"script\" ) );\n\t\t\t\t}\n\t\t\t\telem.parentNode.removeChild( elem );\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\tempty: function() {\n\t\tvar elem,\n\t\t\ti = 0;\n\n\t\tfor ( ; (elem = this[i]) != null; i++ ) {\n\t\t\tif ( elem.nodeType === 1 ) {\n\n\t\t\t\t// Prevent memory leaks\n\t\t\t\tjQuery.cleanData( getAll( elem, false ) );\n\n\t\t\t\t// Remove any remaining nodes\n\t\t\t\telem.textContent = \"\";\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\tclone: function( dataAndEvents, deepDataAndEvents ) {\n\t\tdataAndEvents = dataAndEvents == null ? false : dataAndEvents;\n\t\tdeepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents;\n\n\t\treturn this.map( function () {\n\t\t\treturn jQuery.clone( this, dataAndEvents, deepDataAndEvents );\n\t\t});\n\t},\n\n\thtml: function( value ) {\n\t\treturn 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 && elem.nodeType === 1 ) {\n\t\t\t\treturn elem.innerHTML;\n\t\t\t}\n\n\t\t\t// See if we can take a shortcut and just use innerHTML\n\t\t\tif ( typeof value === \"string\" && !rnoInnerhtml.test( value ) &&\n\t\t\t\t!wrapMap[ ( rtagName.exec( value ) || [ \"\", \"\" ] )[ 1 ].toLowerCase() ] ) {\n\n\t\t\t\tvalue = value.replace( rxhtmlTag, \"<$1></$2>\" );\n\n\t\t\t\ttry {\n\t\t\t\t\tfor ( ; i < l; i++ ) {\n\t\t\t\t\t\telem = this[ i ] || {};\n\n\t\t\t\t\t\t// Remove element nodes and prevent memory leaks\n\t\t\t\t\t\tif ( elem.nodeType === 1 ) {\n\t\t\t\t\t\t\tjQuery.cleanData( getAll( elem, false ) );\n\t\t\t\t\t\t\telem.innerHTML = value;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\telem = 0;\n\n\t\t\t\t// If using innerHTML throws an exception, use the fallback method\n\t\t\t\t} catch( e ) {}\n\t\t\t}\n\n\t\t\tif ( elem ) {\n\t\t\t\tthis.empty().append( value );\n\t\t\t}\n\t\t}, null, value, arguments.length );\n\t},\n\n\treplaceWith: function() {\n\t\tvar\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 fragment, first, scripts, hasScripts, node, doc,\n\t\t\ti = 0,\n\t\t\tl = this.length,\n\t\t\tset = this,\n\t\t\tiNoClone = l - 1,\n\t\t\tvalue = args[ 0 ],\n\t\t\tisFunction = jQuery.isFunction( value );\n\n\t\t// We can't cloneNode fragments that contain checked, in WebKit\n\t\tif ( isFunction || !( 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\t// Support: QtWebKit\n\t\t\t\t\t\t\t// jQuery.merge because core_push.apply(_, arraylike) throws\n\t\t\t\t\t\t\tjQuery.merge( scripts, getAll( node, \"script\" ) );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tcallback.call( this[ i ], node, i );\n\t\t\t\t}\n\n\t\t\t\tif ( hasScripts ) {\n\t\t\t\t\tdoc = scripts[ scripts.length - 1 ].ownerDocument;\n\n\t\t\t\t\t// Reenable scripts\n\t\t\t\t\tjQuery.map( scripts, restoreScript );\n\n\t\t\t\t\t// Evaluate executable scripts on first document insertion\n\t\t\t\t\tfor ( i = 0; i < hasScripts; i++ ) {\n\t\t\t\t\t\tnode = scripts[ i ];\n\t\t\t\t\t\tif ( rscriptType.test( node.type || \"\" ) &&\n\t\t\t\t\t\t\t!data_priv.access( node, \"globalEval\" ) && jQuery.contains( doc, node ) ) {\n\n\t\t\t\t\t\t\tif ( node.src ) {\n\t\t\t\t\t\t\t\t// 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.textContent.replace( rcleanScript, \"\" ) );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t}\n});\n\njQuery.each({\n\tappendTo: \"append\",\n\tprependTo: \"prepend\",\n\tinsertBefore: \"before\",\n\tinsertAfter: \"after\",\n\treplaceAll: \"replaceWith\"\n}, function( name, original ) {\n\tjQuery.fn[ name ] = function( selector ) {\n\t\tvar elems,\n\t\t\tret = [],\n\t\t\tinsert = jQuery( selector ),\n\t\t\tlast = insert.length - 1,\n\t\t\ti = 0;\n\n\t\tfor ( ; i <= last; i++ ) {\n\t\t\telems = i === last ? this : this.clone( true );\n\t\t\tjQuery( insert[ i ] )[ original ]( elems );\n\n\t\t\t// Support: QtWebKit\n\t\t\t// .get() because core_push.apply(_, arraylike) throws\n\t\t\tcore_push.apply( ret, elems.get() );\n\t\t}\n\n\t\treturn this.pushStack( ret );\n\t};\n});\n\njQuery.extend({\n\tclone: function( elem, dataAndEvents, deepDataAndEvents ) {\n\t\tvar i, l, srcElements, destElements,\n\t\t\tclone = elem.cloneNode( true ),\n\t\t\tinPage = jQuery.contains( elem.ownerDocument, elem );\n\n\t\t// Support: IE >= 9\n\t\t// Fix Cloning issues\n\t\tif ( !jQuery.support.noCloneChecked && ( 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\tfor ( i = 0, l = srcElements.length; i < l; i++ ) {\n\t\t\t\tfixInput( srcElements[ i ], destElements[ i ] );\n\t\t\t}\n\t\t}\n\n\t\t// Copy the events from the original to the clone\n\t\tif ( dataAndEvents ) {\n\t\t\tif ( deepDataAndEvents ) {\n\t\t\t\tsrcElements = srcElements || getAll( elem );\n\t\t\t\tdestElements = destElements || getAll( clone );\n\n\t\t\t\tfor ( i = 0, l = srcElements.length; i < l; i++ ) {\n\t\t\t\t\tcloneCopyEvent( srcElements[ i ], destElements[ i ] );\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tcloneCopyEvent( elem, clone );\n\t\t\t}\n\t\t}\n\n\t\t// Preserve script evaluation history\n\t\tdestElements = getAll( clone, \"script\" );\n\t\tif ( destElements.length > 0 ) {\n\t\t\tsetGlobalEval( destElements, !inPage && getAll( elem, \"script\" ) );\n\t\t}\n\n\t\t// Return the cloned set\n\t\treturn clone;\n\t},\n\n\tbuildFragment: function( elems, context, scripts, selection ) {\n\t\tvar elem, tmp, tag, wrap, contains, j,\n\t\t\ti = 0,\n\t\t\tl = elems.length,\n\t\t\tfragment = context.createDocumentFragment(),\n\t\t\tnodes = [];\n\n\t\tfor ( ; i < l; i++ ) {\n\t\t\telem = elems[ i ];\n\n\t\t\tif ( elem || elem === 0 ) {\n\n\t\t\t\t// Add nodes directly\n\t\t\t\tif ( jQuery.type( elem ) === \"object\" ) {\n\t\t\t\t\t// Support: QtWebKit\n\t\t\t\t\t// jQuery.merge because core_push.apply(_, arraylike) throws\n\t\t\t\t\tjQuery.merge( nodes, elem.nodeType ? [ elem ] : elem );\n\n\t\t\t\t// Convert non-html into a text node\n\t\t\t\t} else if ( !rhtml.test( elem ) ) {\n\t\t\t\t\tnodes.push( context.createTextNode( elem ) );\n\n\t\t\t\t// Convert html into DOM nodes\n\t\t\t\t} else {\n\t\t\t\t\ttmp = tmp || fragment.appendChild( context.createElement(\"div\") );\n\n\t\t\t\t\t// Deserialize a standard representation\n\t\t\t\t\ttag = ( rtagName.exec( elem ) || [\"\", \"\"] )[ 1 ].toLowerCase();\n\t\t\t\t\twrap = wrapMap[ tag ] || wrapMap._default;\n\t\t\t\t\ttmp.innerHTML = wrap[ 1 ] + elem.replace( rxhtmlTag, \"<$1></$2>\" ) + wrap[ 2 ];\n\n\t\t\t\t\t// Descend through wrappers to the right content\n\t\t\t\t\tj = wrap[ 0 ];\n\t\t\t\t\twhile ( j-- ) {\n\t\t\t\t\t\ttmp = tmp.lastChild;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Support: QtWebKit\n\t\t\t\t\t// jQuery.merge because core_push.apply(_, arraylike) throws\n\t\t\t\t\tjQuery.merge( nodes, tmp.childNodes );\n\n\t\t\t\t\t// Remember the top-level container\n\t\t\t\t\ttmp = fragment.firstChild;\n\n\t\t\t\t\t// Fixes #12346\n\t\t\t\t\t// Support: Webkit, IE\n\t\t\t\t\ttmp.textContent = \"\";\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Remove wrapper from fragment\n\t\tfragment.textContent = \"\";\n\n\t\ti = 0;\n\t\twhile ( (elem = nodes[ i++ ]) ) {\n\n\t\t\t// #4087 - If origin and destination elements are the same, and this is\n\t\t\t// that element, do not do anything\n\t\t\tif ( selection && jQuery.inArray( elem, selection ) !== -1 ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tcontains = jQuery.contains( elem.ownerDocument, elem );\n\n\t\t\t// Append to fragment\n\t\t\ttmp = getAll( fragment.appendChild( elem ), \"script\" );\n\n\t\t\t// Preserve script evaluation history\n\t\t\tif ( contains ) {\n\t\t\t\tsetGlobalEval( tmp );\n\t\t\t}\n\n\t\t\t// Capture executables\n\t\t\tif ( scripts ) {\n\t\t\t\tj = 0;\n\t\t\t\twhile ( (elem = tmp[ j++ ]) ) {\n\t\t\t\t\tif ( rscriptType.test( elem.type || \"\" ) ) {\n\t\t\t\t\t\tscripts.push( elem );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn fragment;\n\t},\n\n\tcleanData: function( elems ) {\n\t\tvar data, elem, events, type, key, j,\n\t\t\tspecial = jQuery.event.special,\n\t\t\ti = 0;\n\n\t\tfor ( ; (elem = elems[ i ]) !== undefined; i++ ) {\n\t\t\tif ( Data.accepts( elem ) ) {\n\t\t\t\tkey = elem[ data_priv.expando ];\n\n\t\t\t\tif ( key && (data = data_priv.cache[ key ]) ) {\n\t\t\t\t\tevents = Object.keys( data.events || {} );\n\t\t\t\t\tif ( events.length ) {\n\t\t\t\t\t\tfor ( j = 0; (type = events[j]) !== undefined; j++ ) {\n\t\t\t\t\t\t\tif ( special[ type ] ) {\n\t\t\t\t\t\t\t\tjQuery.event.remove( elem, type );\n\n\t\t\t\t\t\t\t// This is a shortcut to avoid jQuery.event.remove's overhead\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tjQuery.removeEvent( elem, type, data.handle );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif ( data_priv.cache[ key ] ) {\n\t\t\t\t\t\t// Discard any remaining `private` data\n\t\t\t\t\t\tdelete data_priv.cache[ key ];\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t// Discard any remaining `user` data\n\t\t\tdelete data_user.cache[ elem[ data_user.expando ] ];\n\t\t}\n\t},\n\n\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});\n\n// Support: 1.x compatibility\n// Manipulating tables requires a tbody\nfunction manipulationTarget( elem, content ) {\n\treturn jQuery.nodeName( elem, \"table\" ) &&\n\t\tjQuery.nodeName( content.nodeType === 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 = (elem.getAttribute(\"type\") !== null) + \"/\" + elem.type;\n\treturn elem;\n}\nfunction restoreScript( elem ) {\n\tvar match = rscriptTypeMasked.exec( elem.type );\n\n\tif ( match ) {\n\t\telem.type = match[ 1 ];\n\t} else {\n\t\telem.removeAttribute(\"type\");\n\t}\n\n\treturn elem;\n}\n\n// Mark scripts as having already been evaluated\nfunction setGlobalEval( elems, refElements ) {\n\tvar l = elems.length,\n\t\ti = 0;\n\n\tfor ( ; i < l; i++ ) {\n\t\tdata_priv.set(\n\t\t\telems[ i ], \"globalEval\", !refElements || data_priv.get( refElements[ i ], \"globalEval\" )\n\t\t);\n\t}\n}\n\nfunction cloneCopyEvent( src, dest ) {\n\tvar i, l, type, pdataOld, pdataCur, udataOld, udataCur, events;\n\n\tif ( dest.nodeType !== 1 ) {\n\t\treturn;\n\t}\n\n\t// 1. Copy private data: events, handlers, etc.\n\tif ( data_priv.hasData( src ) ) {\n\t\tpdataOld = data_priv.access( src );\n\t\tpdataCur = data_priv.set( dest, pdataOld );\n\t\tevents = pdataOld.events;\n\n\t\tif ( events ) {\n\t\t\tdelete pdataCur.handle;\n\t\t\tpdataCur.events = {};\n\n\t\t\tfor ( type in events ) {\n\t\t\t\tfor ( i = 0, l = events[ type ].length; i < l; i++ ) {\n\t\t\t\t\tjQuery.event.add( dest, type, events[ type ][ i ] );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// 2. Copy user data\n\tif ( data_user.hasData( src ) ) {\n\t\tudataOld = data_user.access( src );\n\t\tudataCur = jQuery.extend( {}, udataOld );\n\n\t\tdata_user.set( dest, udataCur );\n\t}\n}\n\n\nfunction getAll( context, tag ) {\n\tvar ret = context.getElementsByTagName ? context.getElementsByTagName( tag || \"*\" ) :\n\t\t\tcontext.querySelectorAll ? context.querySelectorAll( tag || \"*\" ) :\n\t\t\t[];\n\n\treturn tag === undefined || tag && jQuery.nodeName( context, tag ) ?\n\t\tjQuery.merge( [ context ], ret ) :\n\t\tret;\n}\n\n// Support: IE >= 9\nfunction fixInput( src, dest ) {\n\tvar nodeName = dest.nodeName.toLowerCase();\n\n\t// Fails to persist the checked state of a cloned checkbox or radio button.\n\tif ( nodeName === \"input\" && manipulation_rcheckableType.test( src.type ) ) {\n\t\tdest.checked = src.checked;\n\n\t// Fails to return the selected option to the default selected state when cloning options\n\t} else if ( nodeName === \"input\" || nodeName === \"textarea\" ) {\n\t\tdest.defaultValue = src.defaultValue;\n\t}\n}\njQuery.fn.extend({\n\twrapAll: function( html ) {\n\t\tvar wrap;\n\n\t\tif ( jQuery.isFunction( html ) ) {\n\t\t\treturn this.each(function( i ) {\n\t\t\t\tjQuery( this ).wrapAll( html.call(this, i) );\n\t\t\t});\n\t\t}\n\n\t\tif ( this[ 0 ] ) {\n\n\t\t\t// The elements to wrap the target around\n\t\t\twrap = jQuery( html, this[ 0 ].ownerDocument ).eq( 0 ).clone( true );\n\n\t\t\tif ( this[ 0 ].parentNode ) {\n\t\t\t\twrap.insertBefore( this[ 0 ] );\n\t\t\t}\n\n\t\t\twrap.map(function() {\n\t\t\t\tvar elem = this;\n\n\t\t\t\twhile ( elem.firstElementChild ) {\n\t\t\t\t\telem = elem.firstElementChild;\n\t\t\t\t}\n\n\t\t\t\treturn elem;\n\t\t\t}).append( this );\n\t\t}\n\n\t\treturn this;\n\t},\n\n\twrapInner: function( html ) {\n\t\tif ( jQuery.isFunction( html ) ) {\n\t\t\treturn this.each(function( i ) {\n\t\t\t\tjQuery( this ).wrapInner( html.call(this, i) );\n\t\t\t});\n\t\t}\n\n\t\treturn this.each(function() {\n\t\t\tvar self = jQuery( this ),\n\t\t\t\tcontents = self.contents();\n\n\t\t\tif ( contents.length ) {\n\t\t\t\tcontents.wrapAll( html );\n\n\t\t\t} else {\n\t\t\t\tself.append( html );\n\t\t\t}\n\t\t});\n\t},\n\n\twrap: function( html ) {\n\t\tvar isFunction = jQuery.isFunction( html );\n\n\t\treturn this.each(function( i ) {\n\t\t\tjQuery( this ).wrapAll( isFunction ? html.call(this, i) : html );\n\t\t});\n\t},\n\n\tunwrap: function() {\n\t\treturn this.parent().each(function() {\n\t\t\tif ( !jQuery.nodeName( this, \"body\" ) ) {\n\t\t\t\tjQuery( this ).replaceWith( this.childNodes );\n\t\t\t}\n\t\t}).end();\n\t}\n});\nvar curCSS, iframe,\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\n// NOTE: we've included the \"window\" in window.getComputedStyle\n// because jsdom on node.js will break without it.\nfunction getStyles( elem ) {\n\treturn window.getComputedStyle( elem, null );\n}\n\nfunction showHide( elements, show ) {\n\tvar display, elem, hidden,\n\t\tvalues = [],\n\t\tindex = 0,\n\t\tlength = elements.length;\n\n\tfor ( ; index < length; index++ ) {\n\t\telem = elements[ index ];\n\t\tif ( !elem.style ) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tvalues[ index ] = data_priv.get( elem, \"olddisplay\" );\n\t\tdisplay = elem.style.display;\n\t\tif ( show ) {\n\t\t\t// Reset the inline display of this element to learn if it is\n\t\t\t// being hidden by cascaded rules or not\n\t\t\tif ( !values[ index ] && display === \"none\" ) {\n\t\t\t\telem.style.display = \"\";\n\t\t\t}\n\n\t\t\t// Set elements which have been overridden with display: none\n\t\t\t// in a stylesheet to whatever the default browser style is\n\t\t\t// for such an element\n\t\t\tif ( elem.style.display === \"\" && isHidden( elem ) ) {\n\t\t\t\tvalues[ index ] = data_priv.access( elem, \"olddisplay\", 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\tdata_priv.set( 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 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\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\": \"cssFloat\"\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 specifying 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\t\t\t\tstyle[ name ] = value;\n\t\t\t}\n\n\t\t} else {\n\t\t\t// If a hook was provided get the non-computed value from there\n\t\t\tif ( hooks && \"get\" in hooks && (ret = hooks.get( elem, false, extra )) !== undefined ) {\n\t\t\t\treturn ret;\n\t\t\t}\n\n\t\t\t// Otherwise just get the value from the style object\n\t\t\treturn style[ name ];\n\t\t}\n\t},\n\n\tcss: function( elem, name, extra, styles ) {\n\t\tvar val, num, hooks,\n\t\t\torigName = jQuery.camelCase( name );\n\n\t\t// Make sure that we're working with the right name\n\t\tname = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( elem.style, origName ) );\n\n\t\t// 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\ncurCSS = function( elem, name, _computed ) {\n\tvar width, minWidth, maxWidth,\n\t\tcomputed = _computed || getStyles( elem ),\n\n\t\t// Support: IE9\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\t\tstyle = elem.style;\n\n\tif ( computed ) {\n\n\t\tif ( ret === \"\" && !jQuery.contains( elem.ownerDocument, elem ) ) {\n\t\t\tret = jQuery.style( elem, name );\n\t\t}\n\n\t\t// Support: Safari 5.1\n\t\t// A tribute to the \"awesome hack by Dean Edwards\"\n\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// this is against the CSSOM draft spec: http://dev.w3.org/csswg/cssom/#resolved-values\n\t\tif ( rnumnonpx.test( ret ) && rmargin.test( name ) ) {\n\n\t\t\t// Remember the original values\n\t\t\twidth = style.width;\n\t\t\tminWidth = style.minWidth;\n\t\t\tmaxWidth = style.maxWidth;\n\n\t\t\t// Put in the new values to get a computed value out\n\t\t\tstyle.minWidth = style.maxWidth = style.width = ret;\n\t\t\tret = computed.width;\n\n\t\t\t// Revert the changed values\n\t\t\tstyle.width = width;\n\t\t\tstyle.minWidth = minWidth;\n\t\t\tstyle.maxWidth = maxWidth;\n\t\t}\n\t}\n\n\treturn ret;\n};\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\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\t// Support: Android 2.3\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// Support: Android 2.3\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};\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\n\tajax_nonce = jQuery.now(),\n\n\tajax_rquery = /\\?/,\n\trhash = /#.*$/,\n\trts = /([?&])_=[^&]*/,\n\trheaders = /^(.*?):[ \\t]*([^\\r\\n]*)$/mg,\n\t// #7653, #8125, #8152: local protocol detection\n\trlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/,\n\trnoContent = /^(?:GET|HEAD)$/,\n\trprotocol = /^\\/\\//,\n\trurl = /^([\\w.+-]+:)(?:\\/\\/([^\\/?#:]*)(?::(\\d+)|)|)/,\n\n\t// 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 key, deep,\n\t\tflatOptions = jQuery.ajaxSettings.flatOptions || {};\n\n\tfor ( key in src ) {\n\t\tif ( src[ key ] !== undefined ) {\n\t\t\t( flatOptions[ key ] ? target : ( deep || (deep = {}) ) )[ key ] = src[ key ];\n\t\t}\n\t}\n\tif ( deep ) {\n\t\tjQuery.extend( true, target, deep );\n\t}\n\n\treturn target;\n}\n\njQuery.fn.load = function( url, params, callback ) {\n\tif ( typeof url !== \"string\" && _load ) {\n\t\treturn _load.apply( this, arguments );\n\t}\n\n\tvar selector, type, response,\n\t\tself = this,\n\t\toff = url.indexOf(\" \");\n\n\tif ( off >= 0 ) {\n\t\tselector = url.slice( off );\n\t\turl = url.slice( 0, off );\n\t}\n\n\t// If it's a function\n\tif ( jQuery.isFunction( params ) ) {\n\n\t\t// We assume that it's the callback\n\t\tcallback = params;\n\t\tparams = undefined;\n\n\t// Otherwise, build a param string\n\t} else if ( params && typeof params === \"object\" ) {\n\t\ttype = \"POST\";\n\t}\n\n\t// If we have elements to modify, make the request\n\tif ( self.length > 0 ) {\n\t\tjQuery.ajax({\n\t\t\turl: url,\n\n\t\t\t// if \"type\" variable is undefined, then \"GET\" method will be used\n\t\t\ttype: type,\n\t\t\tdataType: \"html\",\n\t\t\tdata: params\n\t\t}).done(function( responseText ) {\n\n\t\t\t// Save response for use in complete callback\n\t\t\tresponse = arguments;\n\n\t\t\tself.html( selector ?\n\n\t\t\t\t// If a selector was specified, locate the right elements in a dummy div\n\t\t\t\t// Exclude scripts to avoid IE 'Permission Denied' errors\n\t\t\t\tjQuery(\"<div>\").append( jQuery.parseHTML( responseText ) ).find( selector ) :\n\n\t\t\t\t// Otherwise use the full result\n\t\t\t\tresponseText );\n\n\t\t}).complete( callback && function( jqXHR, status ) {\n\t\t\tself.each( callback, response || [ jqXHR.responseText, status, jqXHR ] );\n\t\t});\n\t}\n\n\treturn this;\n};\n\n// 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 transport,\n\t\t\t// URL without anti-cache param\n\t\t\tcacheURL,\n\t\t\t// Response headers\n\t\t\tresponseHeadersString,\n\t\t\tresponseHeaders,\n\t\t\t// timeout handle\n\t\t\ttimeoutTimer,\n\t\t\t// Cross-domain detection vars\n\t\t\tparts,\n\t\t\t// To know if global events are to be dispatched\n\t\t\tfireGlobals,\n\t\t\t// Loop variable\n\t\t\ti,\n\t\t\t// Create the final options object\n\t\t\ts = jQuery.ajaxSetup( {}, options ),\n\t\t\t// Callbacks context\n\t\t\tcallbackContext = s.context || s,\n\t\t\t// Context for global events is callbackContext if it is a DOM node or jQuery collection\n\t\t\tglobalEventContext = s.context && ( callbackContext.nodeType || callbackContext.jquery ) ?\n\t\t\t\tjQuery( callbackContext ) :\n\t\t\t\tjQuery.event,\n\t\t\t// Deferreds\n\t\t\tdeferred = jQuery.Deferred(),\n\t\t\tcompleteDeferred = jQuery.Callbacks(\"once memory\"),\n\t\t\t// Status-dependent callbacks\n\t\t\tstatusCode = s.statusCode || {},\n\t\t\t// Headers (they are sent all at once)\n\t\t\trequestHeaders = {},\n\t\t\trequestHeadersNames = {},\n\t\t\t// The jqXHR state\n\t\t\tstate = 0,\n\t\t\t// Default abort message\n\t\t\tstrAbort = \"canceled\",\n\t\t\t// Fake xhr\n\t\t\tjqXHR = {\n\t\t\t\treadyState: 0,\n\n\t\t\t\t// Builds headers hashtable if needed\n\t\t\t\tgetResponseHeader: function( key ) {\n\t\t\t\t\tvar match;\n\t\t\t\t\tif ( state === 2 ) {\n\t\t\t\t\t\tif ( !responseHeaders ) {\n\t\t\t\t\t\t\tresponseHeaders = {};\n\t\t\t\t\t\t\twhile ( (match = rheaders.exec( responseHeadersString )) ) {\n\t\t\t\t\t\t\t\tresponseHeaders[ match[1].toLowerCase() ] = match[ 2 ];\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tmatch = responseHeaders[ key.toLowerCase() ];\n\t\t\t\t\t}\n\t\t\t\t\treturn match == null ? null : match;\n\t\t\t\t},\n\n\t\t\t\t// Raw string\n\t\t\t\tgetAllResponseHeaders: function() {\n\t\t\t\t\treturn state === 2 ? responseHeadersString : null;\n\t\t\t\t},\n\n\t\t\t\t// Caches the header\n\t\t\t\tsetRequestHeader: function( name, value ) {\n\t\t\t\t\tvar lname = name.toLowerCase();\n\t\t\t\t\tif ( !state ) {\n\t\t\t\t\t\tname = requestHeadersNames[ lname ] = requestHeadersNames[ lname ] || name;\n\t\t\t\t\t\trequestHeaders[ name ] = value;\n\t\t\t\t\t}\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\n\t\t\t\t// Overrides response content-type header\n\t\t\t\toverrideMimeType: function( type ) {\n\t\t\t\t\tif ( !state ) {\n\t\t\t\t\t\ts.mimeType = type;\n\t\t\t\t\t}\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\n\t\t\t\t// Status-dependent callbacks\n\t\t\t\tstatusCode: function( map ) {\n\t\t\t\t\tvar code;\n\t\t\t\t\tif ( map ) {\n\t\t\t\t\t\tif ( state < 2 ) {\n\t\t\t\t\t\t\tfor ( code in map ) {\n\t\t\t\t\t\t\t\t// Lazy-add the new callback in a way that preserves old ones\n\t\t\t\t\t\t\t\tstatusCode[ code ] = [ statusCode[ code ], map[ code ] ];\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t// Execute the appropriate callbacks\n\t\t\t\t\t\t\tjqXHR.always( map[ jqXHR.status ] );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\n\t\t\t\t// Cancel the request\n\t\t\t\tabort: function( statusText ) {\n\t\t\t\t\tvar finalText = statusText || strAbort;\n\t\t\t\t\tif ( transport ) {\n\t\t\t\t\t\ttransport.abort( finalText );\n\t\t\t\t\t}\n\t\t\t\t\tdone( 0, finalText );\n\t\t\t\t\treturn this;\n\t\t\t\t}\n\t\t\t};\n\n\t\t// Attach deferreds\n\t\tdeferred.promise( jqXHR ).complete = completeDeferred.add;\n\t\tjqXHR.success = jqXHR.done;\n\t\tjqXHR.error = jqXHR.fail;\n\n\t\t// Remove hash character (#7531: and string promotion)\n\t\t// Add protocol if not provided (prefilters might expect it)\n\t\t// Handle falsy url in the settings object (#10093: consistency with old signature)\n\t\t// We also use the url parameter if available\n\t\ts.url = ( ( url || s.url || ajaxLocation ) + \"\" ).replace( rhash, \"\" )\n\t\t\t.replace( rprotocol, ajaxLocParts[ 1 ] + \"//\" );\n\n\t\t// Alias method option to type as per ticket #12004\n\t\ts.type = options.method || options.type || s.method || s.type;\n\n\t\t// Extract dataTypes list\n\t\ts.dataTypes = jQuery.trim( s.dataType || \"*\" ).toLowerCase().match( 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\n\tvar ct, type, finalDataType, firstDataType,\n\t\tcontents = s.contents,\n\t\tdataTypes = s.dataTypes;\n\n\t// Remove auto dataType and get content-type in the process\n\twhile( dataTypes[ 0 ] === \"*\" ) {\n\t\tdataTypes.shift();\n\t\tif ( ct === undefined ) {\n\t\t\tct = s.mimeType || jqXHR.getResponseHeader(\"Content-Type\");\n\t\t}\n\t}\n\n\t// Check if we're dealing with a known content-type\n\tif ( ct ) {\n\t\tfor ( type in contents ) {\n\t\t\tif ( contents[ type ] && contents[ type ].test( ct ) ) {\n\t\t\t\tdataTypes.unshift( type );\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\t// Check to see if we have a response for the expected dataType\n\tif ( dataTypes[ 0 ] in responses ) {\n\t\tfinalDataType = dataTypes[ 0 ];\n\t} else {\n\t\t// Try convertible dataTypes\n\t\tfor ( type in responses ) {\n\t\t\tif ( !dataTypes[ 0 ] || s.converters[ type + \" \" + dataTypes[0] ] ) {\n\t\t\t\tfinalDataType = type;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif ( !firstDataType ) {\n\t\t\t\tfirstDataType = type;\n\t\t\t}\n\t\t}\n\t\t// Or just use first one\n\t\tfinalDataType = finalDataType || firstDataType;\n\t}\n\n\t// If we found a dataType\n\t// We add the dataType to the list if needed\n\t// and return the corresponding response\n\tif ( finalDataType ) {\n\t\tif ( finalDataType !== dataTypes[ 0 ] ) {\n\t\t\tdataTypes.unshift( finalDataType );\n\t\t}\n\t\treturn responses[ finalDataType ];\n\t}\n}\n\n/* Chain conversions given the request and the original response\n * Also sets the responseXXX fields on the jqXHR instance\n */\nfunction ajaxConvert( s, response, jqXHR, isSuccess ) {\n\tvar conv2, current, conv, tmp, prev,\n\t\tconverters = {},\n\t\t// Work with a copy of dataTypes in case we need to modify it for conversion\n\t\tdataTypes = s.dataTypes.slice();\n\n\t// Create converters map with lowercased keys\n\tif ( dataTypes[ 1 ] ) {\n\t\tfor ( conv in s.converters ) {\n\t\t\tconverters[ conv.toLowerCase() ] = s.converters[ conv ];\n\t\t}\n\t}\n\n\tcurrent = dataTypes.shift();\n\n\t// Convert to each sequential dataType\n\twhile ( current ) {\n\n\t\tif ( s.responseFields[ current ] ) {\n\t\t\tjqXHR[ s.responseFields[ current ] ] = response;\n\t\t}\n\n\t\t// Apply the dataFilter if provided\n\t\tif ( !prev && isSuccess && s.dataFilter ) {\n\t\t\tresponse = s.dataFilter( response, s.dataType );\n\t\t}\n\n\t\tprev = current;\n\t\tcurrent = dataTypes.shift();\n\n\t\tif ( current ) {\n\n\t\t// There's only work to do if current dataType is non-auto\n\t\t\tif ( current === \"*\" ) {\n\n\t\t\t\tcurrent = prev;\n\n\t\t\t// Convert response if prev dataType is non-auto and differs from current\n\t\t\t} else if ( prev !== \"*\" && prev !== current ) {\n\n\t\t\t\t// Seek a direct converter\n\t\t\t\tconv = converters[ prev + \" \" + current ] || converters[ \"* \" + current ];\n\n\t\t\t\t// If none found, seek a pair\n\t\t\t\tif ( !conv ) {\n\t\t\t\t\tfor ( conv2 in converters ) {\n\n\t\t\t\t\t\t// If conv2 outputs current\n\t\t\t\t\t\ttmp = conv2.split( \" \" );\n\t\t\t\t\t\tif ( tmp[ 1 ] === current ) {\n\n\t\t\t\t\t\t\t// If prev can be converted to accepted input\n\t\t\t\t\t\t\tconv = converters[ prev + \" \" + tmp[ 0 ] ] ||\n\t\t\t\t\t\t\t\tconverters[ \"* \" + tmp[ 0 ] ];\n\t\t\t\t\t\t\tif ( conv ) {\n\t\t\t\t\t\t\t\t// Condense equivalence converters\n\t\t\t\t\t\t\t\tif ( conv === true ) {\n\t\t\t\t\t\t\t\t\tconv = converters[ conv2 ];\n\n\t\t\t\t\t\t\t\t// Otherwise, insert the intermediate dataType\n\t\t\t\t\t\t\t\t} else if ( converters[ conv2 ] !== true ) {\n\t\t\t\t\t\t\t\t\tcurrent = tmp[ 0 ];\n\t\t\t\t\t\t\t\t\tdataTypes.unshift( tmp[ 1 ] );\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Apply converter (if not an equivalence)\n\t\t\t\tif ( conv !== true ) {\n\n\t\t\t\t\t// Unless errors are allowed to bubble, catch and return them\n\t\t\t\t\tif ( conv && s[ \"throws\" ] ) {\n\t\t\t\t\t\tresponse = conv( response );\n\t\t\t\t\t} else {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tresponse = conv( response );\n\t\t\t\t\t\t} catch ( e ) {\n\t\t\t\t\t\t\treturn { state: \"parsererror\", error: conv ? e : \"No conversion from \" + prev + \" to \" + current };\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn { state: \"success\", data: response };\n}\n// Install script dataType\njQuery.ajaxSetup({\n\taccepts: {\n\t\tscript: \"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript\"\n\t},\n\tcontents: {\n\t\tscript: /(?:java|ecma)script/\n\t},\n\tconverters: {\n\t\t\"text script\": function( text ) {\n\t\t\tjQuery.globalEval( text );\n\t\t\treturn text;\n\t\t}\n\t}\n});\n\n// Handle cache's special case and crossDomain\njQuery.ajaxPrefilter( \"script\", function( s ) {\n\tif ( s.cache === undefined ) {\n\t\ts.cache = false;\n\t}\n\tif ( s.crossDomain ) {\n\t\ts.type = \"GET\";\n\t}\n});\n\n// Bind script tag hack transport\njQuery.ajaxTransport( \"script\", function( s ) {\n\t// This transport only deals with cross domain requests\n\tif ( s.crossDomain ) {\n\t\tvar script, callback;\n\t\treturn {\n\t\t\tsend: function( _, complete ) {\n\t\t\t\tscript = jQuery(\"<script>\").prop({\n\t\t\t\t\tasync: true,\n\t\t\t\t\tcharset: s.scriptCharset,\n\t\t\t\t\tsrc: s.url\n\t\t\t\t}).on(\n\t\t\t\t\t\"load error\",\n\t\t\t\t\tcallback = function( evt ) {\n\t\t\t\t\t\tscript.remove();\n\t\t\t\t\t\tcallback = null;\n\t\t\t\t\t\tif ( evt ) {\n\t\t\t\t\t\t\tcomplete( evt.type === \"error\" ? 404 : 200, evt.type );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t);\n\t\t\t\tdocument.head.appendChild( script[ 0 ] );\n\t\t\t},\n\t\t\tabort: function() {\n\t\t\t\tif ( callback ) {\n\t\t\t\t\tcallback();\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t}\n});\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});\njQuery.ajaxSettings.xhr = function() {\n\ttry {\n\t\treturn new XMLHttpRequest();\n\t} catch( e ) {}\n};\n\nvar xhrSupported = jQuery.ajaxSettings.xhr(),\n\txhrSuccessStatus = {\n\t\t// file protocol always yields status code 0, assume 200\n\t\t0: 200,\n\t\t// Support: IE9\n\t\t// #1450: sometimes IE returns 1223 when it should be 204\n\t\t1223: 204\n\t},\n\t// Support: IE9\n\t// We need to keep track of outbound xhr and abort them manually\n\t// because IE is not smart enough to do it all by itself\n\txhrId = 0,\n\txhrCallbacks = {};\n\nif ( window.ActiveXObject ) {\n\tjQuery( window ).on( \"unload\", function() {\n\t\tfor( var key in xhrCallbacks ) {\n\t\t\txhrCallbacks[ key ]();\n\t\t}\n\t\txhrCallbacks = undefined;\n\t});\n}\n\njQuery.support.cors = !!xhrSupported && ( \"withCredentials\" in xhrSupported );\njQuery.support.ajax = xhrSupported = !!xhrSupported;\n\njQuery.ajaxTransport(function( options ) {\n\tvar callback;\n\t// Cross domain only allowed if supported through XMLHttpRequest\n\tif ( jQuery.support.cors || xhrSupported && !options.crossDomain ) {\n\t\treturn {\n\t\t\tsend: function( headers, complete ) {\n\t\t\t\tvar i, id,\n\t\t\t\t\txhr = options.xhr();\n\t\t\t\txhr.open( options.type, options.url, options.async, options.username, options.password );\n\t\t\t\t// Apply custom fields if provided\n\t\t\t\tif ( options.xhrFields ) {\n\t\t\t\t\tfor ( i in options.xhrFields ) {\n\t\t\t\t\t\txhr[ i ] = options.xhrFields[ i ];\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// Override mime type if needed\n\t\t\t\tif ( options.mimeType && xhr.overrideMimeType ) {\n\t\t\t\t\txhr.overrideMimeType( options.mimeType );\n\t\t\t\t}\n\t\t\t\t// X-Requested-With header\n\t\t\t\t// For cross-domain requests, seeing as conditions for a preflight are\n\t\t\t\t// akin to a jigsaw puzzle, we simply never set it to be sure.\n\t\t\t\t// (it can always be set on a per-request basis or even using ajaxSetup)\n\t\t\t\t// For same-domain requests, won't change header if already provided.\n\t\t\t\tif ( !options.crossDomain && !headers[\"X-Requested-With\"] ) {\n\t\t\t\t\theaders[\"X-Requested-With\"] = \"XMLHttpRequest\";\n\t\t\t\t}\n\t\t\t\t// Set headers\n\t\t\t\tfor ( i in headers ) {\n\t\t\t\t\txhr.setRequestHeader( i, headers[ i ] );\n\t\t\t\t}\n\t\t\t\t// Callback\n\t\t\t\tcallback = function( type ) {\n\t\t\t\t\treturn function() {\n\t\t\t\t\t\tif ( callback ) {\n\t\t\t\t\t\t\tdelete xhrCallbacks[ id ];\n\t\t\t\t\t\t\tcallback = xhr.onload = xhr.onerror = null;\n\t\t\t\t\t\t\tif ( type === \"abort\" ) {\n\t\t\t\t\t\t\t\txhr.abort();\n\t\t\t\t\t\t\t} else if ( type === \"error\" ) {\n\t\t\t\t\t\t\t\tcomplete(\n\t\t\t\t\t\t\t\t\t// file protocol always yields status 0, assume 404\n\t\t\t\t\t\t\t\t\txhr.status || 404,\n\t\t\t\t\t\t\t\t\txhr.statusText\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tcomplete(\n\t\t\t\t\t\t\t\t\txhrSuccessStatus[ xhr.status ] || xhr.status,\n\t\t\t\t\t\t\t\t\txhr.statusText,\n\t\t\t\t\t\t\t\t\t// Support: IE9\n\t\t\t\t\t\t\t\t\t// #11426: When requesting binary data, IE9 will throw an exception\n\t\t\t\t\t\t\t\t\t// on any attempt to access responseText\n\t\t\t\t\t\t\t\t\ttypeof xhr.responseText === \"string\" ? {\n\t\t\t\t\t\t\t\t\t\ttext: xhr.responseText\n\t\t\t\t\t\t\t\t\t} : undefined,\n\t\t\t\t\t\t\t\t\txhr.getAllResponseHeaders()\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t};\n\t\t\t\t};\n\t\t\t\t// Listen to events\n\t\t\t\txhr.onload = callback();\n\t\t\t\txhr.onerror = callback(\"error\");\n\t\t\t\t// Create the abort callback\n\t\t\t\tcallback = xhrCallbacks[( id = xhrId++ )] = callback(\"abort\");\n\t\t\t\t// Do send the request\n\t\t\t\t// This may raise an exception which is actually\n\t\t\t\t// handled in jQuery.ajax (so no try/catch here)\n\t\t\t\txhr.send( options.hasContent && options.data || null );\n\t\t\t},\n\t\t\tabort: function() {\n\t\t\t\tif ( callback ) {\n\t\t\t\t\tcallback();\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t}\n});\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 = data_priv.get( elem, \"fxshow\" );\n\n\t// handle queue: false promises\n\tif ( !opts.queue ) {\n\t\thooks = jQuery._queueHooks( elem, \"fx\" );\n\t\tif ( hooks.unqueued == null ) {\n\t\t\thooks.unqueued = 0;\n\t\t\toldfire = hooks.empty.fire;\n\t\t\thooks.empty.fire = function() {\n\t\t\t\tif ( !hooks.unqueued ) {\n\t\t\t\t\toldfire();\n\t\t\t\t}\n\t\t\t};\n\t\t}\n\t\thooks.unqueued++;\n\n\t\tanim.always(function() {\n\t\t\t// 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 IE9-10 do not\n\t\t// change the overflow attribute when overflowX and\n\t\t// overflowY are set to the same value\n\t\topts.overflow = [ style.overflow, style.overflowX, style.overflowY ];\n\n\t\t// Set display property to inline-block for height/width\n\t\t// animations on inline elements that are having width/height animated\n\t\tif ( jQuery.css( elem, \"display\" ) === \"inline\" &&\n\t\t\t\tjQuery.css( elem, \"float\" ) === \"none\" ) {\n\n\t\t\tstyle.display = \"inline-block\";\n\t\t}\n\t}\n\n\tif ( opts.overflow ) {\n\t\tstyle.overflow = \"hidden\";\n\t\tanim.always(function() {\n\t\t\tstyle.overflow = opts.overflow[ 0 ];\n\t\t\tstyle.overflowX = opts.overflow[ 1 ];\n\t\t\tstyle.overflowY = opts.overflow[ 2 ];\n\t\t});\n\t}\n\n\n\t// show/hide pass\n\tfor ( prop in props ) {\n\t\tvalue = props[ prop ];\n\t\tif ( rfxtypes.exec( value ) ) {\n\t\t\tdelete props[ prop ];\n\t\t\ttoggle = toggle || value === \"toggle\";\n\t\t\tif ( value === ( hidden ? \"hide\" : \"show\" ) ) {\n\n\t\t\t\t// If there is dataShow left over from a stopped hide or show and we are going to proceed with show, we should pretend to be hidden\n\t\t\t\tif ( value === \"show\" && dataShow && dataShow[ prop ] !== undefined ) {\n\t\t\t\t\thidden = true;\n\t\t\t\t} else {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t}\n\t\t\torig[ prop ] = dataShow && dataShow[ prop ] || jQuery.style( elem, prop );\n\t\t}\n\t}\n\n\tif ( !jQuery.isEmptyObject( orig ) ) {\n\t\tif ( dataShow ) {\n\t\t\tif ( \"hidden\" in dataShow ) {\n\t\t\t\thidden = dataShow.hidden;\n\t\t\t}\n\t\t} else {\n\t\t\tdataShow = data_priv.access( elem, \"fxshow\", {} );\n\t\t}\n\n\t\t// store state if its toggle - enables .stop().toggle() to \"reverse\"\n\t\tif ( toggle ) {\n\t\t\tdataShow.hidden = !hidden;\n\t\t}\n\t\tif ( hidden ) {\n\t\t\tjQuery( elem ).show();\n\t\t} else {\n\t\t\tanim.done(function() {\n\t\t\t\tjQuery( elem ).hide();\n\t\t\t});\n\t\t}\n\t\tanim.done(function() {\n\t\t\tvar prop;\n\n\t\t\tdata_priv.remove( elem, \"fxshow\" );\n\t\t\tfor ( prop in orig ) {\n\t\t\t\tjQuery.style( elem, prop, orig[ prop ] );\n\t\t\t}\n\t\t});\n\t\tfor ( prop in orig ) {\n\t\t\ttween = createTween( hidden ? dataShow[ prop ] : 0, prop, anim );\n\n\t\t\tif ( !( prop in dataShow ) ) {\n\t\t\t\tdataShow[ prop ] = tween.start;\n\t\t\t\tif ( hidden ) {\n\t\t\t\t\ttween.end = tween.start;\n\t\t\t\t\ttween.start = prop === \"width\" || prop === \"height\" ? 1 : 0;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\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: IE9\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 || data_priv.get( this, \"finish\" ) ) {\n\t\t\t\t\tanim.stop( true );\n\t\t\t\t}\n\t\t\t};\n\t\t\tdoAnimation.finish = doAnimation;\n\n\t\treturn empty || optall.queue === false ?\n\t\t\tthis.each( doAnimation ) :\n\t\t\tthis.queue( optall.queue, doAnimation );\n\t},\n\tstop: function( type, clearQueue, gotoEnd ) {\n\t\tvar stopQueue = function( hooks ) {\n\t\t\tvar stop = hooks.stop;\n\t\t\tdelete hooks.stop;\n\t\t\tstop( gotoEnd );\n\t\t};\n\n\t\tif ( typeof type !== \"string\" ) {\n\t\t\tgotoEnd = clearQueue;\n\t\t\tclearQueue = type;\n\t\t\ttype = undefined;\n\t\t}\n\t\tif ( clearQueue && type !== false ) {\n\t\t\tthis.queue( type || \"fx\", [] );\n\t\t}\n\n\t\treturn this.each(function() {\n\t\t\tvar dequeue = true,\n\t\t\t\tindex = type != null && type + \"queueHooks\",\n\t\t\t\ttimers = jQuery.timers,\n\t\t\t\tdata = data_priv.get( this );\n\n\t\t\tif ( index ) {\n\t\t\t\tif ( data[ index ] && data[ index ].stop ) {\n\t\t\t\t\tstopQueue( data[ index ] );\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tfor ( index in data ) {\n\t\t\t\t\tif ( data[ index ] && data[ index ].stop && rrun.test( index ) ) {\n\t\t\t\t\t\tstopQueue( data[ index ] );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfor ( index = timers.length; index--; ) {\n\t\t\t\tif ( timers[ index ].elem === this && (type == null || timers[ index ].queue === type) ) {\n\t\t\t\t\ttimers[ index ].anim.stop( gotoEnd );\n\t\t\t\t\tdequeue = false;\n\t\t\t\t\ttimers.splice( index, 1 );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// start the next in the queue if the last step wasn't forced\n\t\t\t// timers currently will call their complete callbacks, which 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 = data_priv.get( this ),\n\t\t\t\tqueue = data[ type + \"queue\" ],\n\t\t\t\thooks = data[ type + \"queueHooks\" ],\n\t\t\t\ttimers = jQuery.timers,\n\t\t\t\tlength = queue ? queue.length : 0;\n\n\t\t\t// enable finishing flag on private data\n\t\t\tdata.finish = true;\n\n\t\t\t// empty the queue first\n\t\t\tjQuery.queue( this, type, [] );\n\n\t\t\tif ( hooks && hooks.stop ) {\n\t\t\t\thooks.stop.call( this, true );\n\t\t\t}\n\n\t\t\t// look for any active animations, and finish them\n\t\t\tfor ( index = timers.length; index--; ) {\n\t\t\t\tif ( timers[ index ].elem === this && timers[ index ].queue === type ) {\n\t\t\t\t\ttimers[ index ].anim.stop( true );\n\t\t\t\t\ttimers.splice( index, 1 );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// look for any animations in the old queue and finish them\n\t\t\tfor ( index = 0; index < length; index++ ) {\n\t\t\t\tif ( queue[ index ] && queue[ index ].finish ) {\n\t\t\t\t\tqueue[ index ].finish.call( this );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// turn off finishing flag\n\t\t\tdelete data.finish;\n\t\t});\n\t}\n});\n\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\telem = this[ 0 ],\n\t\tbox = { top: 0, left: 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.clientTop,\n\t\tleft: box.left + win.pageXOffset - docElem.clientLeft\n\t};\n};\n\njQuery.offset = {\n\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\" ) && ( curCSSTop + curCSSLeft ).indexOf(\"auto\") > -1;\n\n\t\t// Need to be able to calculate position if either top or left is auto and position is either absolute or fixed\n\t\tif ( calculatePosition ) {\n\t\t\tcurPosition = curElem.position();\n\t\t\tcurTop = curPosition.top;\n\t\t\tcurLeft = curPosition.left;\n\n\t\t} else {\n\t\t\tcurTop = parseFloat( curCSSTop ) || 0;\n\t\t\tcurLeft = parseFloat( curCSSLeft ) || 0;\n\t\t}\n\n\t\tif ( jQuery.isFunction( options ) ) {\n\t\t\toptions = options.call( elem, i, curOffset );\n\t\t}\n\n\t\tif ( options.top != null ) {\n\t\t\tprops.top = ( options.top - curOffset.top ) + curTop;\n\t\t}\n\t\tif ( options.left != null ) {\n\t\t\tprops.left = ( options.left - curOffset.left ) + curLeft;\n\t\t}\n\n\t\tif ( \"using\" in options ) {\n\t\t\toptions.using.call( elem, props );\n\n\t\t} else {\n\t\t\tcurElem.css( props );\n\t\t}\n\t}\n};\n\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\telem = this[ 0 ],\n\t\t\tparentOffset = { top: 0, left: 0 };\n\n\t\t// Fixed elements are offset from window (parentOffset = {top:0, left: 0}, because it is 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\n\t\t} else {\n\t\t\t// Get *real* offsetParent\n\t\t\toffsetParent = this.offsetParent();\n\n\t\t\t// Get correct offsets\n\t\t\toffset = this.offset();\n\t\t\tif ( !jQuery.nodeName( offsetParent[ 0 ], \"html\" ) ) {\n\t\t\t\tparentOffset = offsetParent.offset();\n\t\t\t}\n\n\t\t\t// Add offsetParent borders\n\t\t\tparentOffset.top += jQuery.css( offsetParent[ 0 ], \"borderTopWidth\", true );\n\t\t\tparentOffset.left += jQuery.css( offsetParent[ 0 ], \"borderLeftWidth\", true );\n\t\t}\n\n\t\t// Subtract parent offsets and element margins\n\t\treturn {\n\t\t\ttop: offset.top - parentOffset.top - jQuery.css( elem, \"marginTop\", true ),\n\t\t\tleft: offset.left - parentOffset.left - jQuery.css( elem, \"marginLeft\", true )\n\t\t};\n\t},\n\n\toffsetParent: function() {\n\t\treturn this.map(function() {\n\t\t\tvar offsetParent = this.offsetParent || docElem;\n\n\t\t\twhile ( offsetParent && ( !jQuery.nodeName( offsetParent, \"html\" ) && jQuery.css( offsetParent, \"position\") === \"static\" ) ) {\n\t\t\t\toffsetParent = offsetParent.offsetParent;\n\t\t\t}\n\n\t\t\treturn offsetParent || docElem;\n\t\t});\n\t}\n});\n\n\n// Create scrollLeft and scrollTop methods\njQuery.each( {scrollLeft: \"pageXOffset\", scrollTop: \"pageYOffset\"}, function( method, prop ) {\n\tvar top = \"pageYOffset\" === prop;\n\n\tjQuery.fn[ method ] = function( val ) {\n\t\treturn 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 ? win[ prop ] : elem[ method ];\n\t\t\t}\n\n\t\t\tif ( win ) {\n\t\t\t\twin.scrollTo(\n\t\t\t\t\t!top ? val : window.pageXOffset,\n\t\t\t\t\ttop ? val : window.pageYOffset\n\t\t\t\t);\n\n\t\t\t} else {\n\t\t\t\telem[ method ] = val;\n\t\t\t}\n\t\t}, method, val, arguments.length, null );\n\t};\n});\n\nfunction getWindow( elem ) {\n\treturn jQuery.isWindow( elem ) ? elem : elem.nodeType === 9 && elem.defaultView;\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],\n\t\t\t\t\t// whichever is greatest\n\t\t\t\t\treturn Math.max(\n\t\t\t\t\t\telem.body[ \"scroll\" + name ], doc[ \"scroll\" + name ],\n\t\t\t\t\t\telem.body[ \"offset\" + name ], doc[ \"offset\" + name ],\n\t\t\t\t\t\tdoc[ \"client\" + name ]\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\treturn value === undefined ?\n\t\t\t\t\t// Get width or height on the element, requesting but not forcing parseFloat\n\t\t\t\t\tjQuery.css( elem, type, extra ) :\n\n\t\t\t\t\t// Set width or height on the element\n\t\t\t\t\tjQuery.style( elem, type, value, extra );\n\t\t\t}, type, chainable ? margin : undefined, chainable, null );\n\t\t};\n\t});\n});\n// 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// 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// If there is a window object, that at least has a document property,\n// define jQuery and $ identifiers\nif ( typeof window === \"object\" && typeof window.document === \"object\" ) {\n\twindow.jQuery = window.$ = jQuery;\n}\n\n})( window );\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/jquery/package.json",
    "content": "{\n\t\"name\": \"jquery\",\n\t\"title\": \"jQuery\",\n\t\"description\": \"JavaScript library for DOM operations\",\n\t\"version\": \"2.0.3\",\n\t\"homepage\": \"http://jquery.com\",\n\t\"author\": {\n\t\t\"name\": \"jQuery Foundation and other contributors\",\n\t\t\"url\": \"https://github.com/jquery/jquery/blob/master/AUTHORS.txt\"\n\t},\n\t\"repository\": {\n\t\t\"type\": \"git\",\n\t\t\"url\": \"https://github.com/jquery/jquery.git\"\n\t},\n\t\"bugs\": {\n\t\t\"url\": \"http://bugs.jquery.com\"\n\t},\n\t\"licenses\": [\n\t\t{\n\t\t\t\"type\": \"MIT\",\n\t\t\t\"url\": \"https://github.com/jquery/jquery/blob/master/MIT-LICENSE.txt\"\n\t\t}\n\t],\n\t\"dependencies\": {},\n\t\"devDependencies\": {\n\t\t\"grunt-compare-size\": \"~0.4.0\",\n\t\t\"grunt-git-authors\": \"1.2.0\",\n\t\t\"grunt-update-submodules\": \"0.2.0\",\n\t\t\"grunt-contrib-watch\": \"0.3.1\",\n\t\t\"grunt-contrib-jshint\": \"0.3.0\",\n\t\t\"grunt-contrib-uglify\": \"0.2.0\",\n\t\t\"grunt\": \"0.4.1\",\n\t\t\"gzip-js\": \"0.3.1\",\n\t\t\"testswarm\": \"~1.1.0\",\n\t\t\"archiver\": \"~0.4.2\"\n\t},\n\t\"keywords\": []\n}\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/jquery/speed/benchmark.js",
    "content": "// Runs a function many times without the function call overhead\nfunction benchmark(fn, times, name){\n\tfn = fn.toString();\n\tvar s = fn.indexOf('{')+1,\n\t\te = fn.lastIndexOf('}');\n\tfn = fn.substring(s,e);\n\n\treturn benchmarkString(fn, times, name);\n}\n\nfunction benchmarkString(fn, times, name) {\n\tvar fn = new Function(\"i\", \"var t=new Date; while(i--) {\" + fn + \"}; return new Date - t\")(times)\n\tfn.displayName = name || \"benchmarked\";\n\treturn fn;\n}\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/jquery/speed/benchmarker.css",
    "content": "\n   .dialog {\n     margin-bottom: 1em;\n   }\n   a.expand {\n     background: #e3e3e3;\n   }\n\n   div#time-test {\n     font-family: Arial, Helvetica, sans-serif;\n     font-size: 62.5%;\n   }\n\n   td.test button {\n     float: right;\n   }\n\n   table {\n     border: 1px solid #000;\n   }\n\n   table td, table th {\n     border: 1px solid #000;\n     padding: 10px;\n   }\n\n   td.winner {\n     background-color: #cfc;\n   }\n\n   td.tie {\n     background-color: #ffc;\n   }\n\n   td.fail {\n     background-color: #f99;\n     font-weight: bold;\n     text-align: center;\n   }\n\n   tfoot td {\n     text-align: center;\n   }\n\n   #time-test {\n     margin: 1em 0;\n     padding: .5em;\n     background: #e3e3e3;\n   }\n   #time-taken {\n     font-weight: bold;\n   }\n\n   span.wins {\n     color: #330;\n   }\n\n   span.fails {\n     color: #900;\n   }\n\n   div.buttons {\n     margin-top: 10px;\n     margin-bottom: 10px;\n   }\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/jquery/speed/benchmarker.js",
    "content": "  jQuery.benchmarker.tests = [\n    // Selectors from:\n    // http://ejohn.org/blog/selectors-that-people-actually-use/\n    /*\n    // For Amazon.com\n      \"#navAmazonLogo\", \"#navSwmSkedPop\",\n    \".navbar\", \".navGreeting\",\n    \"div\", \"table\",\n    \"img.navCrossshopTabCap\", \"span.navGreeting\",\n    \"#navbar table\", \"#navidWelcomeMsg span\",\n    \"div#navbar\", \"ul#navAmazonLogo\",\n    \"#navAmazonLogo .navAmazonLogoGatewayPanel\", \"#navidWelcomeMsg .navGreeting\",\n    \".navbar .navAmazonLogoGatewayPanel\", \".navbar .navGreeting\",\n    \"*\",\n    \"#navAmazonLogo li.navAmazonLogoGatewayPanel\", \"#navidWelcomeMsg span.navGreeting\",\n    \"a[name=top]\", \"form[name=site-search]\",\n    \".navbar li\", \".navbar span\",\n    \"[name=top]\", \"[name=site-search]\",\n    \"ul li\", \"a img\",\n    \"#navbar #navidWelcomeMsg\", \"#navbar #navSwmDWPop\",\n    \"#navbar ul li\", \"#navbar a img\"\n    */\n    // For Yahoo.com\n    \"#page\", \"#masthead\", \"#mastheadhd\",\n    \".mastheadbd\", \".first\", \".on\",\n    \"div\", \"li\", \"a\",\n    \"div.mastheadbd\", \"li.first\", \"li.on\",\n    \"#page div\", \"#dtba span\",\n    \"div#page\", \"div#masthead\",\n    \"#page .mastheadbd\", \"#page .first\",\n    \".outer_search_container .search_container\", \".searchbox_container .inputtext\",\n    \"*\",\n    \"#page div.mastheadbd\", \"#page li.first\",\n    \"input[name=p]\", \"a[name=marketplace]\",\n    \".outer_search_container div\", \".searchbox_container span\",\n    \"[name=p]\", \"[name=marketplace]\",\n    \"ul li\", \"form input\",\n    \"#page #e2econtent\", \"#page #e2e\"\n  ];\n\n  jQuery.fn.benchmark = function() {\n    this.each(function() {\n      try {\n        jQuery(this).parent().children(\"*:gt(1)\").remove();\n      } catch(e) { }\n    })\n    // set # times to run the test in index.html\n    var times = parseInt(jQuery(\"#times\").val());\n    jQuery.benchmarker.startingList = this.get();\n    benchmark(this.get(), times, jQuery.benchmarker.libraries);\n  }\n\n  jQuery(function() {\n    for(i = 0; i < jQuery.benchmarker.tests.length; i++) {\n      jQuery(\"tbody\").append(\"<tr><td class='test'>\" + jQuery.benchmarker.tests[i] + \"</td></tr>\");\n    }\n    jQuery(\"tbody tr:first-child\").remove();\n    jQuery(\"td.test\").before(\"<td><input type='checkbox' checked='checked' /></td>\");\n    jQuery(\"button.runTests\").bind(\"click\", function() {\n      jQuery('td:has(input:checked) + td.test').benchmark();\n    });\n\n    jQuery(\"button.retryTies\").bind(\"click\", function() { jQuery(\"tr:has(td.tie) td.test\").benchmark() })\n\n    jQuery(\"button.selectAll\").bind(\"click\", function() { jQuery(\"input[type=checkbox]\").each(function() { this.checked = true }) })\n    jQuery(\"button.deselectAll\").bind(\"click\", function() { jQuery(\"input[type=checkbox]\").each(function() { this.checked = false }) })\n\n    jQuery(\"#addTest\").bind(\"click\", function() {\n      jQuery(\"table\").append(\"<tr><td><input type='checkbox' /></td><td><input type='text' /><button>Add</button></td></tr>\");\n      jQuery(\"div#time-test > button\").each(function() { this.disabled = true; })\n      jQuery(\"tbody tr:last button\").bind(\"click\", function() {\n        var td = jQuery(this).parent();\n        td.html(\"<button>-</button>\" + jQuery(this).prev().val()).addClass(\"test\");\n        jQuery(\"div#time-test > button\").each(function() { this.disabled = false; })\n        jQuery(\"button\", td).bind(\"click\", function() { jQuery(this).parents(\"tr\").remove(); })\n      })\n    })\n\n    var headers = jQuery.map(jQuery.benchmarker.libraries, function(i,n) {\n      var extra = n == 0 ? \"basis - \" : \"\";\n      return \"<th>\" + extra + i + \"</th>\"\n    }).join(\"\");\n\n    jQuery(\"thead tr\").append(headers);\n\n    var footers = \"\";\n    for(i = 0; i < jQuery.benchmarker.libraries.length; i++)\n      footers += \"<th></th>\"\n\n    var wlfooters = \"\";\n    for(i = 0; i < jQuery.benchmarker.libraries.length; i++)\n      wlfooters += \"<td><span class='wins'>W</span> / <span class='fails'>F</span></th>\"\n\n    jQuery(\"tfoot tr:first\").append(footers);\n    jQuery(\"tfoot tr:last\").append(wlfooters);\n\n  });\n\n   benchmark = function(list, times, libraries) {\n     if(list[0]) {\n       var times = times || 50;\n       var el = list[0];\n       var code = jQuery(el).text().replace(/^-/, \"\");\n         var timeArr = []\n         for(i = 0; i < times + 2; i++) {\n           var time = new Date()\n           try {\n             window[libraries[0]](code);\n           } catch(e) { }\n           timeArr.push(new Date() - time);\n         }\n         var diff = Math.sum(timeArr) - Math.max.apply( Math, timeArr )\n         - Math.min.apply( Math, timeArr );\n         try {\n           var libRes = window[libraries[0]](code);\n           var jqRes = jQuery(code);\n           if(((jqRes.length == 0) && (libRes.length != 0)) ||\n             (libRes.length > 0 && (jqRes.length == libRes.length)) ||\n             ((libraries[0] == \"cssQuery\" || libraries[0] == \"jQuery\") && code.match(/nth\\-child/) && (libRes.length > 0)) ||\n             ((libraries[0] == \"jQold\") && jqRes.length > 0)) {\n             jQuery(el).parent().append(\"<td>\" + Math.round(diff / times * 100) / 100 + \"ms</td>\");\n           } else {\n             jQuery(el).parent().append(\"<td class='fail'>FAIL</td>\");\n           }\n         } catch(e) {\n           jQuery(el).parent().append(\"<td class='fail'>FAIL</td>\");\n         }\n       setTimeout(benchmarkList(list, times, libraries), 100);\n     } else if(libraries[1]) {\n       benchmark(jQuery.benchmarker.startingList, times, libraries.slice(1));\n     } else {\n       jQuery(\"tbody tr\").each(function() {\n         var winners = jQuery(\"td:gt(1)\", this).min(2);\n         if(winners.length == 1) winners.addClass(\"winner\");\n         else winners.addClass(\"tie\");\n       });\n       setTimeout(count, 100);\n     }\n   }\n\n  function benchmarkList(list, times, libraries) {\n    return function() {\n      benchmark(list.slice(1), times, libraries);\n    }\n  }\n\n function count() {\n   for(i = 3; i <= jQuery.benchmarker.libraries.length + 2 ; i++) {\n     var fails = jQuery(\"td:nth-child(\" + i + \").fail\").length;\n     var wins = jQuery(\"td:nth-child(\" + i + \").winner\").length;\n     jQuery(\"tfoot tr:first th:eq(\" + (i - 1) + \")\")\n      .html(\"<span class='wins'>\" + wins + \"</span> / <span class='fails'>\" + fails + \"</span>\");\n   }\n }\n\n\n jQuery.fn.maxmin = function(tolerance, maxmin, percentage) {\n   tolerance = tolerance || 0;\n   var target = Math[maxmin].apply(Math, jQuery.map(this, function(i) {\n     var parsedNum = parseFloat(i.innerHTML.replace(/[^\\.\\d]/g, \"\"));\n     if(parsedNum || (parsedNum == 0)) return parsedNum;\n   }));\n   return this.filter(function() {\n     if( withinTolerance(parseFloat(this.innerHTML.replace(/[^\\.\\d]/g, \"\")), target, tolerance, percentage) ) return true;\n   })\n }\n\n jQuery.fn.max = function(tolerance, percentage) { return this.maxmin(tolerance, \"max\", percentage) }\n jQuery.fn.min = function(tolerance, percentage) { return this.maxmin(tolerance, \"min\", percentage) }\n\n function withinTolerance(number, target, tolerance, percentage) {\n   if(percentage) { var high = target + ((tolerance / 100) * target); var low = target - ((tolerance / 100) * target); }\n   else { var high = target + tolerance; var low = target - tolerance; }\n   if(number >= low && number <= high) return true;\n }\n\n Math.sum = function(arr) {\n   var sum = 0;\n   for(i = 0; i < arr.length; i++) sum += arr[i];\n   return sum;\n }\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/jquery/speed/closest.html",
    "content": "<!doctype html>\n<html>\n<head>\n\t<title>Test .closest() Performance</title>\n\t<script src=\"benchmark.js\"></script>\n\t<script src=\"jquery-basis.js\"></script>\n\t<script>var old = jQuery.noConflict(true);</script>\n\t<script src=\"../dist/jquery.js\"></script>\n\t<script>\n\t\tjQuery(function ready() {\n\t\t\tvar node = $(\"#child\"), name;\n\n\t\t\tjQuery.each([\".zoo\", \"#zoo\", \"[data-foo=zoo]\", \"#nonexistant\"], function(i, item) {\n\tsetTimeout(function(){\n\t\t\t\t\tname = \"closest '\" + item + \"'\";\n\n\t\tjQuery(\"#results\").append(\"<li>\" + name + \"<ul>\" +\n\t\t\t\t\t\t\"<li>new: \" + benchmarkString(\"$('#child').closest('\" + item + \"')\", 2500, name) + \"</li>\" +\n\t\t\t\t\t\t\"<li>old: \" + benchmarkString(\"old('#child').closest('\" + item + \"')\", 2500, name) + \"</li>\"\n\t\t\t+ \"</ul></li>\");\n\t}, 100);\n\t\t\t});\n\t\t});\n\t</script>\n</head>\n<body>\n\t<div>\n\t\t<p>Hello</p>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\">\n\t\t\t<div>\n\t\t\t\t<p id=\"child\">lorem ipsum</p>\n\t\t\t\t<p>dolor sit amet</p>\n\t\t\t</div>\n\t\t</div>\n\t</div>\n\t<ul id=\"results\"></ul>\n</body>\n</html>\n\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/jquery/speed/css.html",
    "content": "<!doctype html>\n<html>\n<head>\n\t<title>Test Event Handling Performance</title>\n\t<script src=\"benchmark.js\"></script>\n\t<script src=\"jquery-basis.js\"></script>\n\t<script>var old = jQuery.noConflict(true);</script>\n\t<script src=\"../dist/jquery.js\"></script>\n\t<script>\n\tvar num = 400;\n\n\tjQuery(function(){\n\t\tvar p = old(\"p\");\n\t\tvar s = (new Date).getTime();\n\n\t\tfor ( var n = 0; n < 5; n++ ) {\n\t\t\tfor ( var i = 0; i < num; i++ ) {\n\t\t\t\tp.css(\"position\");\n\t\t\t\tp.css(\"top\");\n\t\t\t\tp.css(\"left\");\n\t\t\t\tp.css(\"display\");\n\t\t\t}\n\t\t}\n\n\t\tvar oldNum = (new Date).getTime() - s;\n\n\t\tp = jQuery(\"p\");\n\t\ts = (new Date).getTime();\n\n\t\tfor ( var n = 0; n < 5; n++ ) {\n\t\t\tfor ( var i = 0; i < num; i++ ) {\n\t\t\t\tp.css(\"position\");\n\t\t\t\tp.css(\"top\");\n\t\t\t\tp.css(\"left\");\n\t\t\t\tp.css(\"display\");\n\t\t\t}\n\t\t}\n\n\t\tvar curNum = (new Date).getTime() - s;\n\n\t\tjQuery(\"#num\").text( old.fn.jquery + \": \" + oldNum + \" \" + jQuery.fn.jquery + \": \" + curNum );\n\t});\n\n\tjQuery(function(){\n\t\tvar p = old(\"p\");\n\t\tvar s = (new Date).getTime();\n\n\t\tfor ( var n = 0; n < 5; n++ ) {\n\t\t\tfor ( var i = 0; i < num; i++ ) {\n\t\t\t\tp.css(\"position\", \"relative\");\n\t\t\t\tp.css(\"top\", 15);\n\t\t\t\tp.css(\"left\", 15);\n\t\t\t\tp.css(\"display\", \"block\");\n\t\t\t}\n\t\t}\n\n\t\tvar oldNum = (new Date).getTime() - s;\n\n\t\tp = jQuery(\"p\");\n\t\ts = (new Date).getTime();\n\n\t\tfor ( var n = 0; n < 5; n++ ) {\n\t\t\tfor ( var i = 0; i < num; i++ ) {\n\t\t\t\tp.css(\"position\", \"relative\");\n\t\t\t\tp.css(\"top\", 15);\n\t\t\t\tp.css(\"left\", 15);\n\t\t\t\tp.css(\"display\", \"block\");\n\t\t\t}\n\t\t}\n\n\t\tvar curNum = (new Date).getTime() - s;\n\n\t\tjQuery(\"#num2\").text( old.fn.jquery + \": \" + oldNum + \" \" + jQuery.fn.jquery + \": \" + curNum );\n\t});\n\t</script>\n\t<style>p { position: absolute; top: 5px; left: 5px; }</style>\n</head>\n<body>\n\t<p><strong>Getting Values:</strong> <span id=\"num\">Loading...</span></p>\n\t<p><strong>Setting Values:</strong> <span id=\"num2\">Loading...</span></p>\n</body>\n</html>\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/jquery/speed/event.html",
    "content": "<!doctype html>\n<html>\n<head>\n\t<title>Test Event Handling Performance</title>\n\t<script src=\"benchmark.js\"></script>\n\t<script src=\"jquery-basis.js\"></script>\n\t<script>var old = jQuery.noConflict(true);</script>\n\t<script src=\"../dist/jquery.js\"></script>\n\t<script>\n\tjQuery(function(){\n\n\t});\n\n\tvar events = [], num = 400, exec = false;\n\n\tjQuery(document).mousemove(function(e){\n\t\tif ( exec ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( events.length >= num ) {\n\t\t\texec = true;\n\t\t\tvar s = (new Date).getTime();\n\n\t\t\tfor ( var n = 0; n < 5; n++ ) {\n\t\t\t\tfor ( var i = 0; i < num; i++ ) {\n\t\t\t\t\told.event.handle.call( document, events[i] );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tvar oldNum = (new Date).getTime() - s;\n\n\t\t\ts = (new Date).getTime();\n\n\t\t\tfor ( var n = 0; n < 5; n++ ) {\n\t\t\t\tfor ( var i = 0; i < num; i++ ) {\n\t\t\t\t\tjQuery.event.handle.call( document, events[i] );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tvar curNum = (new Date).getTime() - s;\n\n\t\t\tjQuery(\"#num\").text( old.fn.jquery + \": \" + oldNum + \" \" + jQuery.fn.jquery + \": \" + curNum );\n\n\t\t\tjQuery(this).unbind( \"mousemove\", e.handler );\n\n\t\t} else {\n\t\t\tevents.push( e.originalEvent );\n\t\t\tjQuery(\"#num\").text( events.length + \" / \" + num );\n\t\t}\n\t});\n\t</script>\n</head>\n<body>\n\t<p>Move the mouse, please!</p>\n\t<p id=\"num\"></p>\n</body>\n</html>\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/jquery/speed/filter.html",
    "content": "<!doctype html>\n<html>\n<head>\n\t<title>Test .filter() Performance</title>\n\t<script src=\"benchmark.js\"></script>\n\t<script src=\"jquery-basis.js\"></script>\n\t<script>var old = jQuery.noConflict(true);</script>\n\t<script src=\"../dist/jquery.js\"></script>\n\t<script>\n\t\tjQuery(function ready() {\n\t\t\tvar node = $(\"#child\"), name;\n\n\t\t\tjQuery.each([\".zoo\", \"#zoo\", \"[data-foo=zoo]\", \"#nonexistant\"], function(i, item) {\n\tsetTimeout(function(){\n\t\t\t\t\tname = \"filter '\" + item + \"'\";\n\t\tjQuery(\"#results\").append(\"<li>\" + name + \"<ul>\" +\n\t\t\t\t\t\t\"<li>new: \" + benchmarkString(\"$('div').filter('\" + item + \"')\", 100, name) + \"</li>\" +\n\t\t\t\t\t\t\"<li>old: \" + benchmarkString(\"old('div').filter('\" + item + \"')\", 100, name) + \"</li>\" +\n\t\t\t\"</ul></li>\");\n\t\tjQuery(\"#results\").append(\"<li>single \" + name + \"<ul>\" +\n\t\t\t\t\t\t\"<li>new: \" + benchmarkString(\"$('#nonexistant').filter('\" + item + \"')\", 1000, name) + \"</li>\" +\n\t\t\t\t\t\t\"<li>old: \" + benchmarkString(\"old('#nonexistant').filter('\" + item + \"')\", 1000, name) + \"</li>\" +\n\t\t\t\"</ul></li>\");\n\t}, 100);\n\t\t\t});\n\t\t});\n\t</script>\n</head>\n<body>\n\t<div>\n\t\t<p>Hello</p>\n\t\t<div class=\"zoo\" id=\"nonexistant\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t</div>\n\t<ul id=\"results\"></ul>\n</body>\n</html>\n\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/jquery/speed/find.html",
    "content": "<!doctype html>\n<html>\n<head>\n\t<title>Test .find() Performance</title>\n\t<script src=\"benchmark.js\"></script>\n\t<script src=\"jquery-basis.js\"></script>\n\t<script>var old = jQuery.noConflict(true);</script>\n\t<script src=\"../dist/jquery.js\"></script>\n\t<script>\n\t\tjQuery(function ready() {\n\t\t\tvar node = $(\"#child\"), name;\n\n\t\t\tjQuery.each([\".zoo\", \"#zoo\", \"[data-foo=zoo]\", \"#nonexistant\"], function(i, item) {\n\tsetTimeout(function(){\n\t\t\t\t\tname = \"find '\" + item + \"'\";\n\t\tjQuery(\"#results\").append(\"<li>rooted \" + name + \"<ul>\" +\n\t\t\t\t\t\t\"<li>new: \" + benchmarkString(\"$('body').find('\" + item + \"')\", 250, name) + \"</li>\" +\n\t\t\t\t\t\t\"<li>old: \" + benchmarkString(\"old('body').find('\" + item + \"')\", 250, name) + \"</li>\" +\n\t\t\t\"</ul></li>\");\n\t}, 100);\n\t\t\t});\n\t\t});\n\t</script>\n</head>\n<body>\n\t<div>\n\t\t<p>Hello</p>\n\t\t<div class=\"zoo\" id=\"nonexistant\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t\t<div class=\"zoo\" id=\"zoo\" data-foo=\"bar\"><div></div></div>\n\t</div>\n\t<ul id=\"results\"></ul>\n</body>\n</html>\n\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/jquery/speed/index.html",
    "content": "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\"\n\t\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n\n<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\">\n<head>\n\t<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\"/>\n\t<title>Speed Test</title>\n\t<script src=\"jquery-basis.js\" type=\"text/javascript\"></script>\n\t<script src=\"../dist/jquery.js\" type=\"text/javascript\"></script>\n\t<script type=\"text/javascript\">jQuery.noConflict();</script>\n\t<link rel=\"stylesheet\" href=\"benchmarker.css\" type=\"text/css\" media=\"screen\" />\n</head>\n\n<body>\n\n<h1>Speed Test</h1>\n<div id=\"badid\"></div>\n<div id=\"time-test\">\n<p>Using the following selector expressions (<input type=\"text\" id=\"times\" maxlength=\"5\" size=\"5\" value=\"20\"/> times each):</p>\n<p>NOTE: Number shown is an average.</p>\n<div class=\"buttons\">\n\t<button class=\"selectAll\">Select All</button>\n\t<button class=\"deselectAll\">Deselect All</button>\n\n\t<button class=\"runTests\">Run Tests</button>\n\t<button class=\"retryTies\">Retry Ties</button>\n</div>\n<table cellspacing=\"0\">\n\t<thead>\n\t\t<tr>\n\t\t\t<th>Run?</th>\n\t\t\t<th>Test</th>\n\n\t\t</tr>\n\t</thead>\n\t<tfoot>\n\t\t<tr>\n\t\t\t <th></th>\n\t\t\t <th></th>\n\t\t</tr>\n\t\t<tr>\n\t\t\t <th></th>\n\n\t\t\t <th></th>\n\t\t </tr>\n\t</tfoot>\n\t<tbody>\n\t\t<tr>\n\t\t\t<td></td>\n\t\t\t<td></td>\n\t\t</tr>\n\t</tbody>\n\n</table>\n\n\t<div class=\"buttons\">\n\t<button class=\"selectAll\">Select All</button>\n\t<button class=\"deselectAll\">Deselect All</button>\n\t<button class=\"runTests\">Run Tests</button>\n\t<button class=\"retryTies\">Retry Ties</button>\n\t<button id=\"addTest\">+</button>\n\n\t</div>\n</div>\n<div style=\"display:none;\"><div id=\"page\"><div id=\"masthead\"><div id=\"mastheadhd\"></div><div id=\"mastheadbd\"><div class=\"mastheadbd\"><div id=\"eyebrow\"><ul id=\"ypromo\"><li><a id=\"sethomepage\" href=\"\"><strong>Make Y! your home page</strong></a></li><li id=\"toolbar\"><a id=\"dtba\" href=\"\"><span id=\"tba\">Get</span> Yahoo! Toolbar</a></li></ul><div id=\"ffhpcx\"></div><div id=\"headline\"><span><a href=\"\">How much home can you afford?</a></span></div></div><h1><img src=\"blank.gif\" border=0 width=232 height=44 alt=\"Yahoo!\" id=\"ylogo\"></h1><div id=\"searchwrapper\"><form name=\"sf1\" id=\"search\" action=\"r/sx/*-http://search.yahoo.com/search\"><fieldset><legend>Yahoo! Search</legend><ul id=\"vsearchtabs\"><li class=\"first on\"><a href=\"\">Web</a></li><li><a href=\"\">Images</a></li><li><a href=\"\">Video</a></li><li><a href=\"\">Local</a></li><li><a href=\"\">Shopping</a></li><li class=\"last ignore\"><dl id=\"vsearchm\"><dt><a id=\"vsearchmore\" href=\"\">More</a></dt><dd id=\"vslist\"></dd></dl></li></ul><div id=\"sbox\"><label id=\"searchlabel\" for=\"p\">Search:</label><div class=\"outer_search_container\"><div id=\"search_container\" class=\"search_container\"><img src=\"blank.gif\" id=\"searchother_e2e\" alt=\"\"><div id=\"searchIE\"><div id=\"searchmw1\" class=\"iemw\"></div></div><div class=\"fixfloat searchbox_container\"><div id=\"searchbox\"><input class=\"plong inputtext\" type=\"text\" id=\"p\" name=\"p\" accesskey=\"s\"></div><span id=\"searchbtn\"><input type=\"submit\" id=\"searchsubmit\" class=\"btn-more-2\" value=\"Web Search\"></span></div></div><div id=\"e2eClass\" class=\"e2e\"><div class=\"e2eTween\"></div><div id=\"e2e\"><div id=\"e2econtent\"><div id=\"e2e_intl\"></div><div class=\"ac_container\"><div id=\"e2einfo\"></div><div id=\"ac_container\"></div><div id=\"e2escroll\"></div></div></div><a title=\"toggle search suggestions\" id=\"e2etoggle\" href=\"\" onclick=\"return false;\"><img src=\"blank.gif\" id=\"searchtoggle_e2e\" alt=\"toggle search suggestions\"></a></div></div></div><input type=\"hidden\" name=\"fr\" value=\"yfp\"><input type=\"hidden\" name=\"toggle\" value=\"1\"><input type=\"hidden\" name=\"cop\" value=\"mss\"><input type=\"hidden\" name=\"ei\" value=\"UTF-8\"></div><div id=\"sboxfooter\"></div></fieldset></form></div><div class=\"mh_footer\"><div id=\"doors\"><h3 class=\"a11y\">Popular Yahoo! Properties</h3><ul id=\"doors-links\" class=\"fixfloat\"><li class=\"first\"><strong>Yahoo! Home</strong></li><li class=\"middle\"><a href=r/i1 title=\"Go to My Yahoo!\">My Yahoo!</a></li><li class=\"last\"></li></ul></div><div id=\"pagesettingscx\"><span id=\"navbardate\"><cite class=\"timestamp\">&nbsp;</cite></span><a href=\"\" id=\"editpage\">Page Options</a><div id=\"pagesettings\"><div class=\"bd\"><span><div class=\"iemw\"></div><div id=\"pscolors\"><h4>Color:</h4><ol id=\"themes\"><li><a href=\"\" id=\"t1\" class=\"on\" title=\"Ocean\">Ocean</a></li><li><a href=\"\" id=\"t4\"  title=\"Tangerine\">Tangerine</a></li><li><a href=\"\" id=\"t3\"  title=\"Violet\">Violet</a></li><li><a href=\"\" id=\"t2\"  title=\"Oyster\">Oyster</a></li><li><a href=\"\" id=\"t5\"  title=\"Grass\">Grass</a></li><li><a href=\"\" id=\"t7\"  title=\"Pink\">Pink</a></li></ol></div><a id=\"sizetogglelink\" href=\"\">Switch to narrow layout</a><a id=\"myyahoolink\" href=\"\">Want more ways to customize <span>your home page?</span><span class=\"trymyyahoo\">Try My Yahoo! &#187;</span></a></span></div></div></div></div></div></div><div id=\"mastheadft\"></div></div><div id=\"colcx\"><div id=\"left\"><div id=\"trough\" class=\"md\"><div class=\"bd\"><div id=\"trough-cols\" class=\"fixfloat\"><ul id=\"trough-1\" class=\"col1\"><li><a style=\"background-position:-400px -120px\" href=\"\">Answers</a></li><li><a style=\"background-position:-400px -440px\" href=\"\">Autos</a></li><li><a style=\"background-position:0 -761px\" href=\"\">Finance</a></li><li><a style=\"background-position:0 -1600px\" href=\"\">Games</a></li><li><a style=\"background-position:0 -1400px\" href=\"\">Groups</a></li><li><a style=\"background-position:0 -439px\" href=\"\">HotJobs</a></li><li><a style=\"background-position:0 -600px\" href=\"\">Maps</a></li><li><a style=\"background-position:0 -161px\" href=\"\">Mobile Web</a></li><li><a style=\"background-position:0 -561px;display:inline\" href=\"\">Movies</a> | <a class=\"trough_tv\" href=\"\">TV</a></li><li><a style=\"background-position:0 -1562px\" href=\"\">Music</a></li><li><a style=\"background-position:-400px -1119px\" href=\"\">OMG</a></li><li class=\"highlight\"><a style=\"background-position:0 -40px\" href=\"\">Personals</a></li><li><a style=\"background-position:-400px -161px\" href=\"\">Real Estate<small class=\"updated\"></small></a></li><li><a style=\"background-position:-400px -1321px\" href=\"\">Shine</a></li><li><a style=\"background-position:0 -1640px\" href=\"\">Shopping</a></li><li><a style=\"background-position:0 -800px\" href=\"\">Sports</a></li><li><a style=\"background-position:0 -79px\" href=\"\">Travel</a></li><li><a style=\"background-position:0 -121px\" href=\"\">Yellow Pages</a></li></ul></div><span id=\"allyservicescx\"><a href=\"\" id=\"allyservices\" class=\"btn-more-2\" title=\"View the complete list of Yahoo! Services\">More Yahoo! Services</a></span></div></div><div class=\"md minimantle\"><div id=\"smallbiz\" class=\"md-sub\"><div class=\"hd\"><h2><a href=\"\">Small Business</a></h2></div><ul id=\"smallbiz-links\"><li><a href=\"\">Get a Web Site</a></li><li><a href=\"\">Domain Names</a></li><li><a href=\"\">Sell Online</a></li><li><a href=\"\">Search Ads</a></li></ul></div></div><div class=\"md minimantle\"><div id=\"advertising\" class=\"md-sub\"><div class=\"hd\"><h2><a href=\"\">Featured Services</a></h2></div><ul id=\"advertising-links\"><li><a href=\"\">Downloads</a></li><li><a href=\"\">Health</a></li><li><a href=\"\">Kids</a></li><li><a href=\"\">GeoCities</a></li><li><a href=\"\">Mail Plus</a></li><li><a href=\"\">Y! International</a></li></ul></div></div></div><div id=\"rightcx\"><div id=\"middle\"><div class=\"colpadding\"><div id=\"today\" class=\"md featured1\"><div class=\"hd tabs\"><h3 class=\"a11y\">Featured Navigation</h3><ul id=\"todaytabs\"><li class=\"on first\"><em><a hidefocus=\"true\" id=\"featured1\" href=\"\">Featured</a></em><span class=\"pipe\"></span></li><li class=\"tab2\"><em><a hidefocus=\"true\" id=\"entertainment1\" href=\"\">Entertainment</a></em><span class=\"pipe\"></span></li><li class=\"tab3\"><em><a hidefocus=\"true\" id=\"sports1\" href=\"\">Sports</a></em><span class=\"pipe\"></span></li><li class=\"last\"><em><a hidefocus=\"true\" id=\"money1\" href=\"\">Video</a></em><span class=\"pipe\"></span></li></ul></div><div id=\"todayvideo\"></div><div id=\"todaybd\" class=\"bd\"><cite class=\"timestamp\">&nbsp;</cite><span id=\"featured1ct\" class=\"current\"><div id=\"featured1main\"><a href=s/1014544><img src=\"blank.gif\" width=\"154\" height=\"115\" alt=\"Renee Zellweger (Steve Granitz/WireImage)\"></a><span><h3><a href=s/1014544>Worst dressed at the Globes</a></h3><p>Renee's look is a mess, and Miley's gown is a mistake. <a class=more href=s/1014544>&#187; See bad outfits</a></p><ul><li><a class=slideshow href=s/1014545>Best dressed</a></li><li><a class=slideshow href=s/1014546>Stunning couples</a></li><li><a class=video href=s/1014547>Watch Brangelina diss Ryan Seacrest</a></li><li><a class=bullet href=s/1014548>Outrageous moments</a></li><li><a class=bullet href=s/1014549>Big winners</a></li></ul></span></div></span><span id=\"featured2ct\"></span><span id=\"featured3ct\"></span><span id=\"featured4ct\"></span><span id=\"entertainment1ct\"></span><span id=\"entertainment2ct\"></span><span id=\"entertainment3ct\"></span><span id=\"entertainment4ct\"></span><span id=\"sports1ct\"></span><span id=\"sports2ct\"></span><span id=\"sports3ct\"></span><span id=\"sports4ct\"></span><span id=\"money1ct\"></span><span id=\"money2ct\"></span><span id=\"money3ct\"></span><span id=\"money4ct\"></span></div><div id=\"todayft\" class=\"ft\"><span id=\"footer1\" class=\"current\"><ul id=\"todaystories1\"><li id=\"featured1|106537\" class=\"on\"><a href=s/1014556><img src=\"blank.gif\" alt=\"\" width=\"29\" height=\"21\">See the worst-dressed stars at Golden Globes</a></li><li id=\"featured2|106533\"><a href=s/1014475><img src=\"blank.gif\" alt=\"\" width=\"29\" height=\"21\">Obama: Dog search down to two breeds</a></li><li id=\"featured3|106522\"><a href=s/1014275><img src=\"blank.gif\" alt=\"\" width=\"29\" height=\"21\">Eagles star gets penalty for 'phone call'</a></li><li id=\"featured4|106538\"><a href=s/1014566><img src=\"blank.gif\" alt=\"\" width=\"29\" height=\"21\">Teen sends 14,528 texts in one month</a></li></ul><div id=\"more-featured\" class=\"btn-more\"><b>&#187;</b> More:<a class=\"first\" href=\"\">Featured</a><a class=\"last\" href=\"\">Buzz</a></div></span><span id=\"footer2\"></span><span id=\"footer3\"></span><span id=\"footer4\"></span></div></div><div id=\"adwest\" class=\"ad\"></div><div id=\"news\" class=\"md\"><div class=\"hd tabs\"><h3 class=\"a11y\">News Navigation</h3><ul id=\"newstabs\"><li class=\"on first\"><em><a hidefocus=\"true\" id=\"inthenews2\" href=\"\">News</a></em><span class=\"pipe\"></span></li><li class=\"tab2\"><em><a hidefocus=\"true\" id=\"worldnews\" href=\"\">World</a></em><span class=\"pipe\"></span></li><li class=\"tab3\"><em><a hidefocus=\"true\" id=\"localnews\" href=\"\">Local</a></em><span class=\"pipe\"></span></li><li class=\"last\"><em><a hidefocus=\"true\" id=\"finsnews\" href=\"\">Finance</a></em><span class=\"pipe\"></span></li></ul></div><div id=\"newsbd\" class=\"bd\"><span id=\"inthenews2ct\" class=\"current\"><h2 class=\"a11y\">In the News</h2><div id=\"newstop\"><cite class=\"timestamp\">&nbsp;</cite>&#149;&nbsp;<a href=s/1014558>Obama advises Bush to request remaining $350B of bailout</a><br>&#149;&nbsp;<a href=s/1014502>Bush defends his presidency in final news conference</a><br>&#149;&nbsp;<a href=s/1014534>More than 900 Gazans dead as Israel continues attacks</a><br>&#149;&nbsp;<a href=s/1014517>Openly gay Episcopal bishop to say prayer at inaugural event</a><br>&#149;&nbsp;<a href=s/1014567>NYC judge allows Bernard Madoff to remain free on bail</a><br>&#149;&nbsp;<a href=s/1014516>British PM backing Prince Harry after racist remark</a><br>&#149;&nbsp;<a class=video style=\"background-position:-3px -48px;font:normal 100% arial;\" href=s/1014537 onclick=\"window.open('s/1014537','playerWindow','width=793,height=608,scrollbars=no');return false;\">Brothers separated at birth reunite after 80 years</a><br><ul id=\"more-news\" class=\"btn-more\"><li class=\"first\"><b>&#187;</b> More:</li><li><a href=r/xn>News</a></li><li><a href=r/me>Popular</a></li><li class=\"last\"><a href=r/z0>Politics</a></li></ul></div><div id=\"newsft\"><div id=\"newsbottom\"><div id=\"finance-data\"><div id=\"markets\"><h3><a href=\"\">Markets:</a></h3><ul><li><strong><a href=\"\">Dow: </a><span class=\"down\">-1.0%</span></strong></li><li><strong><a href=\"\">Nasdaq: </a><span class=\"down\">-1.7%</span></strong></li></ul></div><div id=\"quotes\"><form name=\"fq\" id=\"fq\" action=\"r/f4/*-http://finance.yahoo.com/q\"><fieldset><legend>Yahoo! Finance</legend>     <a href=\"\">Real-Time Quotes:</a><input accesskey=\"q\" class=\"inputtext\" type=\"text\" id=\"s\" name=\"s\" size=\"5\" title=\"Enter ticker symbol\" /><input type=\"submit\" class=\"submit\" value=\"Go\" /></fieldset></form></div></div><div id=\"news-sponsor\"><a href=\"\"><img src=\"blank.gif\" border=0 width=165 height=15 title=\"Switch to Scottrade\"></a></div></div></div></span><span id=\"worldnewsct\"></span><span id=\"localnewsct\"></span><span id=\"finsnewsct\"></span></div></div><div id=\"marketplace\" class=\"md\"><div class=\"hd\"><h2><a href=\"\" name=\"marketplace\">Marketplace</a></h2></div><div id=\"marketplacebd\" class=\"bd\"><table border=0 cellpadding=0 cellspacing=0 width=\"100%\"><tr><td valign=top><a href=\"\"><img src=\"blank.gif\" width=70 height=50 border=0></a></td><td width=8>&nbsp;</td><td valign=top><font face=arial size=-1><a href=\"\">Why online college is rocking:</a><br>1) Accredited Associates, Bachelor&#39;s, Master&#39;s, MBA degrees 2) Some jobs pay tuition <a href=\"\">3) Top schools online.</a></font></td></tr></table><hr size=1 noshade><a href=\"\">A bad credit score is 600 or below. Click here to see yours online in just 2 easy steps for $0. By Experian&reg;</a><hr size=1 noshade><a href=\"\">GEICO Car Insurance -</a> You could save over $500 on car insurance. <a href=\"\">Get a fast, free quote.</a><hr size=1 noshade><a href=\"\">100+ credit cards from 9 of the top 10 issuers. Instant approvals. Choose the right card for you. LendingTree&reg;</a></div></div></div></div><div id=\"right\"><div class=\"colpadding\"><div id=\"pa\" class=\"md\"><div id=\"pabd\"><div id=\"patop\"><ul id=\"reg\" class=\"so\"><li class=\"mailstatus\">Check your mail status: <a href=\"\">Sign In</a></li><li id=\"signup\">Free mail: <a href=\"\">Sign Up</a></li></ul></div><div id=\"patabs\"><ul id=\"tabs1\" class=\"patabs first\"><li id=\"mail\" class=\"first\"><div><h4><a id=\"pamail\" accesskey=\"m\" href=\"\"><span class=\"icon\">Mail</span></a></h4></div></li><li id=\"messenger\"><div><h4><a id=\"pamsgr\" href=\"\"><span class=\"icon\">Messenger</span></a></h4></div></li><li id=\"games\" class=\"last\"><div><h4><a id=\"pagames\" href=\"\"><span class=\"icon\">Puzzles</span></a></h4></div></li></ul><div id=\"tabs1previewdiv\" class=\"papreviewdiv\"></div><ul id=\"tabs2\" class=\"patabs last\"><li id=\"weather\" class=\"first\"><div><h4><a id=\"paweather\" href=\"\"><span class=\"icon\">Weather</span></a></h4></div></li><li id=\"events\"><div><h4><a id=\"paevents\" href=\"\"><span class=\"icon\">Events</span></a></h4></div></li><li id=\"horoscope\" class=\"last\"><div><h4><a id=\"pahoroscope\" href=\"\"><span class=\"icon\">Horoscopes</span></a></h4></div></li></ul><div id=\"tabs2previewdiv\" class=\"papreviewdiv\"></div></div></div></div><div id=\"ad\" class=\"ad\"><table cellspacing=0 cellpadding=0 border=0 width=100%><tr><td align=center><a href=\"\" target=\"_top\"><img src=\"blank.gif\" alt=\"\" width=300 height=250 border=0></a></td></tr><tr><td align=center><br><font face=\"verdana\" size=\"-2\"><a href=\"\" target=\"_blank\">Ad Feedback</a></font></td></tr></table></div><div id=\"mantlecx\"><div id=\"mantle\"><div id=\"mantle2\" class=\"md\"><div class=\"hd\"><h2><a href=\"\">Inside Yahoo! HotJobs</a></h2>\t</div><div class=\"bd\"><a href=\"\"><img src=\"blank.gif\" height=\"68\" width=\"92\" alt=\"Yahoo! HotJobs\" border=\"0\"></a><h3><a href=\"\">Great companies hiring now</a></h3><ul><li><a href=\"\">Careers with bright futures</a></li><li><a href=\"\">Low-stress jobs that pay</a></li><li><a href=\"\">Super-easy career changes</a></li><li><a href=\"\">How to find a job right for you</a></li></ul></div></div></div></div><div id=\"pulse\" class=\"md\"><div class=\"hd\"><h2>Pulse - What Yahoos Are Into</h2></div><div id=\"pulsebd\" class=\"bd\"><h3>Star Searches: Most Popular Actors</h3><a href=s/1013525/*-http://movies.yahoo.com/movie/contributor/1800043966><img src=\"blank.gif\" alt=\"Alyssa Milano (Steve Granitz, WireImage.com)\" width=\"139\" height=\"119\"></a><ol><li class=\"tt1\"><a href=s/1013525/*-http://movies.yahoo.com/movie/contributor/1800043966>Alyssa Milano</a></li><li class=\"tt2\"><a href=s/1013526/*-http://movies.yahoo.com/movie/contributor/1800018965>Brad Pitt</a></li><li class=\"tt3\"><a href=s/1013527/*-http://movies.yahoo.com/movie/contributor/1804705919>Anne Hathaway</a></li><li class=\"tt4\"><a href=s/1013528/*-http://movies.yahoo.com/movie/contributor/1800424122>Ziyi Zhang</a></li><li class=\"tt5\"><a href=s/1013529/*-http://movies.yahoo.com/movie/contributor/1800019484>Charlize Theron</a></li><li class=\"tt6\"><a href=s/1013530/*-http://movies.yahoo.com/movie/contributor/1800019485>Johnny Depp</a></li></ol></div><a class=btn-more href=s/1013531/*-http://movies.yahoo.com>&#187; More Yahoo! Movies</a></div><div id=\"popsearch\" class=\"md\"><div class=\"hd\"><h2>Today&#039;s Top Searches</h2></div><div id=\"popsearchbd\" class=\"bd\"><ol start=1><li><a href=\"\">Odette Yustman</a></li><li><a href=\"\">Kate Hudson</a></li><li><a href=\"\">Ana Ortiz</a></li><li><a href=\"\">Weight Loss Tips</a></li><li><a href=\"\">Kimberley Locke</a></li></ol><ol start=6><li><a href=\"\">Rod Blagojevich</a></li><li><a href=\"\">2009 Jeep Commander</a></li><li><a href=\"\">Attention Deficit...</a></li><li><a href=\"\">Snoring</a></li><li><a href=\"\">New Orleans Vacations</a></li></ol></div></div></div></div></div></div><div id=\"footer\" class=\"md\"><ul id=\"flist2\"><li class=\"first\"><a href=\"\">Advertise with Us</a></li><li><a href=\"\">Search Marketing</a></li><li><a href=\"\">Privacy Policy</a></li><li><a href=\"\">Terms of Service</a></li><li><a href=r/ad>Suggest a Site</a></li><li><a href=\"\">Yahoo! en Espa&ntilde;ol</a></li><li><a href=\"\">Send Feedback</a></li><li class=\"last\"><a href=\"\">Help</a></li></ul><ul id=\"copyright\"><li class=\"first\">Copyright &copy; 2009 Yahoo! Inc. All rights reserved.</li><li class=\"first\"><a href=\"\">Copyright/IP Policy</a></li><li><a href=\"\">Company Info</a></li><li><a href=\"\">Participate in Research</a></li><li><a href=\"\">Jobs</a></li></ul></div></div> <div id=\"yblthm_sip\" style=\"display:none\"></div></div>\n\t<script type=\"text/javascript\" charset=\"utf-8\">\n\t\t\t\tjQuery.benchmarker = {libraries: [\"$\", \"jQuery\"]};\n\t</script>\n\n\t<script type=\"text/javascript\" src=\"benchmarker.js\"></script>\n</body>\n</html>\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/jquery/speed/jquery-basis.js",
    "content": "/*!\n * jQuery JavaScript Library v1.4.2\n * http://jquery.com/\n *\n * Copyright 2010, 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 2010, The Dojo Foundation\n * Released under the MIT, BSD, and GPL Licenses.\n *\n * Date: Sat Feb 13 22:33:48 2010 -0500\n */\n(function( window, undefined ) {\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 );\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// Use the correct document accordingly with window argument (sandbox)\n\tdocument = window.document,\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// Is it a simple selector\n\tisSimple = /^.[^:#\\[\\.,]*$/,\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\trtrim = /^(\\s|\\u00A0)+|(\\s|\\u00A0)+$/g,\n\n\t// Match a standalone tag\n\trsingleTag = /^<(\\w+)\\s*\\/?>(?:<\\/\\1>)?$/,\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\t\n\t// Has the ready events already been bound?\n\treadyBound = false,\n\t\n\t// The functions to execute 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\thasOwnProperty = Object.prototype.hasOwnProperty,\n\tpush = Array.prototype.push,\n\tslice = Array.prototype.slice,\n\tindexOf = Array.prototype.indexOf;\n\njQuery.fn = jQuery.prototype = {\n\tinit: function( selector, context ) {\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\t\t\n\t\t// The body element only exists once, optimize finding it\n\t\tif ( selector === \"body\" && !context ) {\n\t\t\tthis.context = document;\n\t\t\tthis[0] = document.body;\n\t\t\tthis.selector = \"body\";\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\tmatch = quickExpr.exec( selector );\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\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 = buildFragment( [ match[1] ], [ doc ] );\n\t\t\t\t\t\tselector = (ret.cacheable ? ret.fragment.cloneNode(true) : ret.fragment).childNodes;\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\treturn jQuery.merge( this, selector );\n\t\t\t\t\t\n\t\t\t\t// HANDLE: $(\"#id\")\n\t\t\t\t} else {\n\t\t\t\t\telem = document.getElementById( match[2] );\n\n\t\t\t\t\tif ( elem ) {\n\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: $(\"TAG\")\n\t\t\t} else if ( !context && /^\\w+$/.test( selector ) ) {\n\t\t\t\tthis.selector = selector;\n\t\t\t\tthis.context = document;\n\t\t\t\tselector = document.getElementsByTagName( selector );\n\t\t\t\treturn jQuery.merge( this, selector );\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 jQuery( 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.4.2\",\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.slice(num)[ 0 ] : 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 = jQuery();\n\n\t\tif ( jQuery.isArray( elems ) ) {\n\t\t\tpush.apply( ret, elems );\n\t\t\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\t\n\tready: function( fn ) {\n\t\t// Attach the listeners\n\t\tjQuery.bindReady();\n\n\t\t// If the DOM is already ready\n\t\tif ( jQuery.isReady ) {\n\t\t\t// Execute the function immediately\n\t\t\tfn.call( document, jQuery );\n\n\t\t// Otherwise, remember the function for later\n\t\t} else if ( readyList ) {\n\t\t\t// Add the function to the wait list\n\t\t\treadyList.push( fn );\n\t\t}\n\n\t\treturn this;\n\t},\n\t\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\t\n\tend: function() {\n\t\treturn this.prevObject || jQuery(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\t// copy reference to target object\n\tvar target = arguments[0] || {}, i = 1, length = arguments.length, deep = false, options, name, src, copy;\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 object literal values or arrays\n\t\t\t\tif ( deep && copy && ( jQuery.isPlainObject(copy) || jQuery.isArray(copy) ) ) {\n\t\t\t\t\tvar clone = src && ( jQuery.isPlainObject(src) || jQuery.isArray(src) ) ? src\n\t\t\t\t\t\t: jQuery.isArray(copy) ? [] : {};\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\twindow.$ = _$;\n\n\t\tif ( deep ) {\n\t\t\twindow.jQuery = _jQuery;\n\t\t}\n\n\t\treturn jQuery;\n\t},\n\t\n\t// Is the DOM ready to be used? Set to true once it occurs.\n\tisReady: false,\n\t\n\t// Handle when the DOM is ready\n\tready: function() {\n\t\t// Make sure that the DOM is not already loaded\n\t\tif ( !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, 13 );\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 there are functions bound, to execute\n\t\t\tif ( readyList ) {\n\t\t\t\t// Execute all of them\n\t\t\t\tvar fn, i = 0;\n\t\t\t\twhile ( (fn = readyList[ i++ ]) ) {\n\t\t\t\t\tfn.call( document, jQuery );\n\t\t\t\t}\n\n\t\t\t\t// Reset the list of functions\n\t\t\t\treadyList = null;\n\t\t\t}\n\n\t\t\t// Trigger any bound ready events\n\t\t\tif ( jQuery.fn.triggerHandler ) {\n\t\t\t\tjQuery( document ).triggerHandler( \"ready\" );\n\t\t\t}\n\t\t}\n\t},\n\t\n\tbindReady: function() {\n\t\tif ( readyBound ) {\n\t\t\treturn;\n\t\t}\n\n\t\treadyBound = true;\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\treturn jQuery.ready();\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\t\t\t\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\t\t\t\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 toString.call(obj) === \"[object Function]\";\n\t},\n\n\tisArray: function( obj ) {\n\t\treturn toString.call(obj) === \"[object Array]\";\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 || toString.call(obj) !== \"[object Object]\" || obj.nodeType || obj.setInterval ) {\n\t\t\treturn false;\n\t\t}\n\t\t\n\t\t// Not own constructor property must be Object\n\t\tif ( obj.constructor\n\t\t\t&& !hasOwnProperty.call(obj, \"constructor\")\n\t\t\t&& !hasOwnProperty.call(obj.constructor.prototype, \"isPrototypeOf\") ) {\n\t\t\treturn false;\n\t\t}\n\t\t\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\n\t\tvar key;\n\t\tfor ( key in obj ) {}\n\t\t\n\t\treturn key === undefined || hasOwnProperty.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\t\n\terror: function( msg ) {\n\t\tthrow msg;\n\t},\n\t\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\t\t\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 ( /^[\\],:{}\\s]*$/.test(data.replace(/\\\\(?:[\"\\\\\\/bfnrt]|u[0-9a-fA-F]{4})/g, \"@\")\n\t\t\t.replace(/\"[^\"\\\\\\n\\r]*\"|true|false|null|-?\\d+(?:\\.\\d*)?(?:[eE][+\\-]?\\d+)?/g, \"]\")\n\t\t\t.replace(/(?:^|:|,)(?:\\s*\\[)+/g, \"\")) ) {\n\n\t\t\t// Try to use the native JSON parser first\n\t\t\treturn window.JSON && window.JSON.parse ?\n\t\t\t\twindow.JSON.parse( data ) :\n\t\t\t\t(new Function(\"return \" + data))();\n\n\t\t} else {\n\t\t\tjQuery.error( \"Invalid JSON: \" + data );\n\t\t}\n\t},\n\n\tnoop: function() {},\n\n\t// Evaluates a script in a global context\n\tglobalEval: function( data ) {\n\t\tif ( data && rnotwhite.test(data) ) {\n\t\t\t// Inspired by code by Andrea Giammarchi\n\t\t\t// http://webreflection.blogspot.com/2007/08/global-scope-evaluation-and-dom.html\n\t\t\tvar head = document.head || document.getElementsByTagName(\"head\")[0] || document.documentElement,\n\t\t\t\tscript = document.createElement(\"script\");\n\n\t\t\tif ( jQuery.support.scriptEval ) {\n\t\t\t\tscript.appendChild( document.createTextNode( data ) );\n\t\t\t} else {\n\t\t\t\tscript.text = data;\n\t\t\t}\n\n\t\t\t// Use insertBefore instead of appendChild to circumvent an IE6 bug.\n\t\t\t// This arises when a base node is used (#2709).\n\t\t\thead.insertBefore( script, head.firstChild );\n\t\t\thead.removeChild( script );\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 ( var value = object[0];\n\t\t\t\t\ti < length && callback.call( value, i, value ) !== false; value = object[++i] ) {}\n\t\t\t}\n\t\t}\n\n\t\treturn object;\n\t},\n\n\ttrim: function( text ) {\n\t\treturn (text || \"\").replace( rtrim, \"\" );\n\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\tif ( array.length == null || typeof array === \"string\" || jQuery.isFunction(array) || (typeof array !== \"function\" && array.setInterval) ) {\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\t\tif ( array.indexOf ) {\n\t\t\treturn array.indexOf( 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, j = 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\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 ret = [];\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\tif ( !inv !== !callback( elems[ i ], i ) ) {\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 ret = [], value;\n\n\t\t// Go through the array, translating each of the items to their\n\t\t// new value (or values).\n\t\tfor ( var i = 0, length = elems.length; i < length; i++ ) {\n\t\t\tvalue = callback( elems[ i ], i, arg );\n\n\t\t\tif ( value != null ) {\n\t\t\t\tret[ ret.length ] = value;\n\t\t\t}\n\t\t}\n\n\t\treturn ret.concat.apply( [], ret );\n\t},\n\n\t// A global GUID counter for objects\n\tguid: 1,\n\n\tproxy: function( fn, proxy, thisObject ) {\n\t\tif ( arguments.length === 2 ) {\n\t\t\tif ( typeof proxy === \"string\" ) {\n\t\t\t\tthisObject = fn;\n\t\t\t\tfn = thisObject[ proxy ];\n\t\t\t\tproxy = undefined;\n\n\t\t\t} else if ( proxy && !jQuery.isFunction( proxy ) ) {\n\t\t\t\tthisObject = proxy;\n\t\t\t\tproxy = undefined;\n\t\t\t}\n\t\t}\n\n\t\tif ( !proxy && fn ) {\n\t\t\tproxy = function() {\n\t\t\t\treturn fn.apply( thisObject || this, arguments );\n\t\t\t};\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\tif ( fn ) {\n\t\t\tproxy.guid = fn.guid = fn.guid || proxy.guid || jQuery.guid++;\n\t\t}\n\n\t\t// So proxy can be declared as an argument\n\t\treturn proxy;\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 = /(webkit)[ \\/]([\\w.]+)/.exec( ua ) ||\n\t\t\t/(opera)(?:.*version)?[ \\/]([\\w.]+)/.exec( ua ) ||\n\t\t\t/(msie) ([\\w.]+)/.exec( ua ) ||\n\t\t\t!/compatible/.test( ua ) && /(mozilla)(?:.*? rv:([\\w.]+))?/.exec( ua ) ||\n\t\t\t[];\n\n\t\treturn { browser: match[1] || \"\", version: match[2] || \"0\" };\n\t},\n\n\tbrowser: {}\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\nif ( indexOf ) {\n\tjQuery.inArray = function( elem, array ) {\n\t\treturn indexOf.call( array, elem );\n\t};\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( error ) {\n\t\tsetTimeout( doScrollCheck, 1 );\n\t\treturn;\n\t}\n\n\t// and execute any waiting functions\n\tjQuery.ready();\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 || \"\" );\n\t}\n\n\tif ( elem.parentNode ) {\n\t\telem.parentNode.removeChild( elem );\n\t}\n}\n\n// Multifunctional method to get and set values to a collection\n// The value/s can be optionally by executed if its a function\nfunction access( elems, key, value, exec, fn, pass ) {\n\tvar length = elems.length;\n\t\n\t// Setting many attributes\n\tif ( typeof key === \"object\" ) {\n\t\tfor ( var k in key ) {\n\t\t\taccess( elems, k, key[k], exec, fn, value );\n\t\t}\n\t\treturn elems;\n\t}\n\t\n\t// Setting one attribute\n\tif ( value !== undefined ) {\n\t\t// Optionally, function values get executed if exec is true\n\t\texec = !pass && exec && jQuery.isFunction(value);\n\t\t\n\t\tfor ( var i = 0; i < length; i++ ) {\n\t\t\tfn( elems[i], key, exec ? value.call( elems[i], i, fn( elems[i], key ) ) : value, pass );\n\t\t}\n\t\t\n\t\treturn elems;\n\t}\n\t\n\t// Getting an attribute\n\treturn length ? fn( elems[0], key ) : undefined;\n}\n\nfunction now() {\n\treturn (new Date).getTime();\n}\n(function() {\n\n\tjQuery.support = {};\n\n\tvar root = document.documentElement,\n\t\tscript = document.createElement(\"script\"),\n\t\tdiv = document.createElement(\"div\"),\n\t\tid = \"script\" + now();\n\n\tdiv.style.display = \"none\";\n\tdiv.innerHTML = \"   <link/><table></table><a href='/a' style='color:red;float:left;opacity:.55;'>a</a><input type='checkbox'/>\";\n\n\tvar all = div.getElementsByTagName(\"*\"),\n\t\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\tjQuery.support = {\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 insted)\n\t\tstyle: /red/.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: div.getElementsByTagName(\"input\")[0].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: document.createElement(\"select\").appendChild( document.createElement(\"option\") ).selected,\n\n\t\tparentNode: div.removeChild( div.appendChild( document.createElement(\"div\") ) ).parentNode === null,\n\n\t\t// Will be defined later\n\t\tdeleteExpando: true,\n\t\tcheckClone: false,\n\t\tscriptEval: false,\n\t\tnoCloneEvent: true,\n\t\tboxModel: null\n\t};\n\n\tscript.type = \"text/javascript\";\n\ttry {\n\t\tscript.appendChild( document.createTextNode( \"window.\" + id + \"=1;\" ) );\n\t} catch(e) {}\n\n\troot.insertBefore( script, root.firstChild );\n\n\t// Make sure that the execution of code works by injecting a script\n\t// tag with appendChild/createTextNode\n\t// (IE doesn't support this, fails, and uses .text instead)\n\tif ( window[ id ] ) {\n\t\tjQuery.support.scriptEval = true;\n\t\tdelete window[ id ];\n\t}\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 script.test;\n\t\n\t} catch(e) {\n\t\tjQuery.support.deleteExpando = false;\n\t}\n\n\troot.removeChild( script );\n\n\tif ( 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\tjQuery.support.noCloneEvent = false;\n\t\t\tdiv.detachEvent(\"onclick\", click);\n\t\t});\n\t\tdiv.cloneNode(true).fireEvent(\"onclick\");\n\t}\n\n\tdiv = document.createElement(\"div\");\n\tdiv.innerHTML = \"<input type='radio' name='radiotest' checked='checked'/>\";\n\n\tvar fragment = document.createDocumentFragment();\n\tfragment.appendChild( div.firstChild );\n\n\t// WebKit doesn't clone checked state correctly in fragments\n\tjQuery.support.checkClone = fragment.cloneNode(true).cloneNode(true).lastChild.checked;\n\n\t// Figure out if the W3C box model works as expected\n\t// document.body must exist before we can do this\n\tjQuery(function() {\n\t\tvar div = document.createElement(\"div\");\n\t\tdiv.style.width = div.style.paddingLeft = \"1px\";\n\n\t\tdocument.body.appendChild( div );\n\t\tjQuery.boxModel = jQuery.support.boxModel = div.offsetWidth === 2;\n\t\tdocument.body.removeChild( div ).style.display = 'none';\n\n\t\tdiv = null;\n\t});\n\n\t// Technique from Juriy Zaytsev\n\t// http://thinkweb2.com/projects/prototype/detecting-event-support-without-browser-sniffing/\n\tvar eventSupported = function( eventName ) { \n\t\tvar el = document.createElement(\"div\"); \n\t\teventName = \"on\" + eventName; \n\n\t\tvar isSupported = (eventName in el); \n\t\tif ( !isSupported ) { \n\t\t\tel.setAttribute(eventName, \"return;\"); \n\t\t\tisSupported = typeof el[eventName] === \"function\"; \n\t\t} \n\t\tel = null; \n\n\t\treturn isSupported; \n\t};\n\t\n\tjQuery.support.submitBubbles = eventSupported(\"submit\");\n\tjQuery.support.changeBubbles = eventSupported(\"change\");\n\n\t// release memory in IE\n\troot = script = div = all = a = null;\n})();\n\njQuery.props = {\n\t\"for\": \"htmlFor\",\n\t\"class\": \"className\",\n\treadonly: \"readOnly\",\n\tmaxlength: \"maxLength\",\n\tcellspacing: \"cellSpacing\",\n\trowspan: \"rowSpan\",\n\tcolspan: \"colSpan\",\n\ttabindex: \"tabIndex\",\n\tusemap: \"useMap\",\n\tframeborder: \"frameBorder\"\n};\nvar expando = \"jQuery\" + now(), uuid = 0, windowData = {};\n\njQuery.extend({\n\tcache: {},\n\t\n\texpando:expando,\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\"object\": true,\n\t\t\"applet\": true\n\t},\n\n\tdata: function( elem, name, data ) {\n\t\tif ( elem.nodeName && jQuery.noData[elem.nodeName.toLowerCase()] ) {\n\t\t\treturn;\n\t\t}\n\n\t\telem = elem == window ?\n\t\t\twindowData :\n\t\t\telem;\n\n\t\tvar id = elem[ expando ], cache = jQuery.cache, thisCache;\n\n\t\tif ( !id && typeof name === \"string\" && data === undefined ) {\n\t\t\treturn null;\n\t\t}\n\n\t\t// Compute a unique ID for the element\n\t\tif ( !id ) { \n\t\t\tid = ++uuid;\n\t\t}\n\n\t\t// Avoid generating a new cache unless none exists and we\n\t\t// want to manipulate it.\n\t\tif ( typeof name === \"object\" ) {\n\t\t\telem[ expando ] = id;\n\t\t\tthisCache = cache[ id ] = jQuery.extend(true, {}, name);\n\n\t\t} else if ( !cache[ id ] ) {\n\t\t\telem[ expando ] = id;\n\t\t\tcache[ id ] = {};\n\t\t}\n\n\t\tthisCache = cache[ id ];\n\n\t\t// Prevent overriding the named cache with undefined values\n\t\tif ( data !== undefined ) {\n\t\t\tthisCache[ name ] = data;\n\t\t}\n\n\t\treturn typeof name === \"string\" ? thisCache[ name ] : thisCache;\n\t},\n\n\tremoveData: function( elem, name ) {\n\t\tif ( elem.nodeName && jQuery.noData[elem.nodeName.toLowerCase()] ) {\n\t\t\treturn;\n\t\t}\n\n\t\telem = elem == window ?\n\t\t\twindowData :\n\t\t\telem;\n\n\t\tvar id = elem[ expando ], cache = jQuery.cache, thisCache = cache[ id ];\n\n\t\t// If we want to remove a specific section of the element's data\n\t\tif ( name ) {\n\t\t\tif ( thisCache ) {\n\t\t\t\t// Remove the section of cache data\n\t\t\t\tdelete thisCache[ name ];\n\n\t\t\t\t// If we've removed all the data, remove the element's cache\n\t\t\t\tif ( jQuery.isEmptyObject(thisCache) ) {\n\t\t\t\t\tjQuery.removeData( elem );\n\t\t\t\t}\n\t\t\t}\n\n\t\t// Otherwise, we want to remove all of the element's data\n\t\t} else {\n\t\t\tif ( jQuery.support.deleteExpando ) {\n\t\t\t\tdelete elem[ jQuery.expando ];\n\n\t\t\t} else if ( elem.removeAttribute ) {\n\t\t\t\telem.removeAttribute( jQuery.expando );\n\t\t\t}\n\n\t\t\t// Completely remove the data cache\n\t\t\tdelete cache[ id ];\n\t\t}\n\t}\n});\n\njQuery.fn.extend({\n\tdata: function( key, value ) {\n\t\tif ( typeof key === \"undefined\" && this.length ) {\n\t\t\treturn jQuery.data( this[0] );\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\tvar data = this.triggerHandler(\"getData\" + parts[1] + \"!\", [parts[0]]);\n\n\t\t\tif ( data === undefined && this.length ) {\n\t\t\t\tdata = jQuery.data( this[0], key );\n\t\t\t}\n\t\t\treturn data === undefined && parts[1] ?\n\t\t\t\tthis.data( parts[0] ) :\n\t\t\t\tdata;\n\t\t} else {\n\t\t\treturn this.trigger(\"setData\" + parts[1] + \"!\", [parts[0], value]).each(function() {\n\t\t\t\tjQuery.data( this, key, value );\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});\njQuery.extend({\n\tqueue: function( elem, type, data ) {\n\t\tif ( !elem ) {\n\t\t\treturn;\n\t\t}\n\n\t\ttype = (type || \"fx\") + \"queue\";\n\t\tvar q = jQuery.data( elem, type );\n\n\t\t// Speed up dequeue by getting out quickly if this is just a lookup\n\t\tif ( !data ) {\n\t\t\treturn q || [];\n\t\t}\n\n\t\tif ( !q || jQuery.isArray(data) ) {\n\t\t\tq = jQuery.data( elem, type, jQuery.makeArray(data) );\n\n\t\t} else {\n\t\t\tq.push( data );\n\t\t}\n\n\t\treturn q;\n\t},\n\n\tdequeue: function( elem, type ) {\n\t\ttype = type || \"fx\";\n\n\t\tvar queue = jQuery.queue( elem, type ), fn = queue.shift();\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\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( i, elem ) {\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\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\n\tclearQueue: function( type ) {\n\t\treturn this.queue( type || \"fx\", [] );\n\t}\n});\nvar rclass = /[\\n\\t]/g,\n\trspace = /\\s+/,\n\trreturn = /\\r/g,\n\trspecialurl = /href|src|style/,\n\trtype = /(button|input)/i,\n\trfocusable = /(button|input|object|select|textarea)/i,\n\trclickable = /^(a|area)$/i,\n\trradiocheck = /radio|checkbox/;\n\njQuery.fn.extend({\n\tattr: function( name, value ) {\n\t\treturn access( this, name, value, true, jQuery.attr );\n\t},\n\n\tremoveAttr: function( name, fn ) {\n\t\treturn this.each(function(){\n\t\t\tjQuery.attr( this, name, \"\" );\n\t\t\tif ( this.nodeType === 1 ) {\n\t\t\t\tthis.removeAttribute( name );\n\t\t\t}\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 + \" \", setClass = elem.className;\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, isBool = 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, i = 0, self = 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 separated list\n\t\t\t\t\tstate = isBool ? state : !self.hasClass( className );\n\t\t\t\t\tself[ state ? \"addClass\" : \"removeClass\" ]( className );\n\t\t\t\t}\n\n\t\t\t} 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\tif ( value === undefined ) {\n\t\t\tvar elem = this[0];\n\n\t\t\tif ( elem ) {\n\t\t\t\tif ( jQuery.nodeName( elem, \"option\" ) ) {\n\t\t\t\t\treturn (elem.attributes.value || {}).specified ? elem.value : elem.text;\n\t\t\t\t}\n\n\t\t\t\t// We need to handle select boxes special\n\t\t\t\tif ( jQuery.nodeName( elem, \"select\" ) ) {\n\t\t\t\t\tvar index = elem.selectedIndex,\n\t\t\t\t\t\tvalues = [],\n\t\t\t\t\t\toptions = elem.options,\n\t\t\t\t\t\tone = elem.type === \"select-one\";\n\n\t\t\t\t\t// Nothing was selected\n\t\t\t\t\tif ( index < 0 ) {\n\t\t\t\t\t\treturn null;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Loop through all the selected options\n\t\t\t\t\tfor ( var i = one ? index : 0, max = one ? index + 1 : options.length; i < max; i++ ) {\n\t\t\t\t\t\tvar option = options[ i ];\n\n\t\t\t\t\t\tif ( option.selected ) {\n\t\t\t\t\t\t\t// Get the specific value for the option\n\t\t\t\t\t\t\tvalue = jQuery(option).val();\n\n\t\t\t\t\t\t\t// We don't need an array for one selects\n\t\t\t\t\t\t\tif ( one ) {\n\t\t\t\t\t\t\t\treturn value;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t// Multi-Selects return an array\n\t\t\t\t\t\t\tvalues.push( value );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\treturn values;\n\t\t\t\t}\n\n\t\t\t\t// Handle the case where in Webkit \"\" is returned instead of \"on\" if a value isn't specified\n\t\t\t\tif ( rradiocheck.test( elem.type ) && !jQuery.support.checkOn ) {\n\t\t\t\t\treturn elem.getAttribute(\"value\") === null ? \"on\" : elem.value;\n\t\t\t\t}\n\t\t\t\t\n\n\t\t\t\t// Everything else, we just grab the value\n\t\t\t\treturn (elem.value || \"\").replace(rreturn, \"\");\n\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 = value;\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}\n\n\t\t\t// Typecast each time if the value is a Function and the appended\n\t\t\t// value is therefore different each time.\n\t\t\tif ( typeof val === \"number\" ) {\n\t\t\t\tval += \"\";\n\t\t\t}\n\n\t\t\tif ( jQuery.isArray(val) && rradiocheck.test( this.type ) ) {\n\t\t\t\tthis.checked = jQuery.inArray( self.val(), val ) >= 0;\n\n\t\t\t} else if ( jQuery.nodeName( this, \"select\" ) ) {\n\t\t\t\tvar values = jQuery.makeArray(val);\n\n\t\t\t\tjQuery( \"option\", this ).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\tthis.selectedIndex = -1;\n\t\t\t\t}\n\n\t\t\t} else {\n\t\t\t\tthis.value = val;\n\t\t\t}\n\t\t});\n\t}\n});\n\njQuery.extend({\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\t\n\tattr: function( elem, name, value, pass ) {\n\t\t// don't set attributes on text and comment nodes\n\t\tif ( !elem || elem.nodeType === 3 || elem.nodeType === 8 ) {\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\tvar notxml = elem.nodeType !== 1 || !jQuery.isXMLDoc( elem ),\n\t\t\t// Whether we are setting (or getting)\n\t\t\tset = value !== undefined;\n\n\t\t// Try to normalize/fix the name\n\t\tname = notxml && jQuery.props[ name ] || name;\n\n\t\t// Only do all the following if this is a node (faster for style)\n\t\tif ( elem.nodeType === 1 ) {\n\t\t\t// These attributes require special treatment\n\t\t\tvar special = rspecialurl.test( name );\n\n\t\t\t// Safari mis-reports the default selected property of an option\n\t\t\t// Accessing the parent's selectedIndex property fixes it\n\t\t\tif ( name === \"selected\" && !jQuery.support.optSelected ) {\n\t\t\t\tvar parent = elem.parentNode;\n\t\t\t\tif ( parent ) {\n\t\t\t\t\tparent.selectedIndex;\n\t\n\t\t\t\t\t// Make sure that it also works with optgroups, see #5701\n\t\t\t\t\tif ( parent.parentNode ) {\n\t\t\t\t\t\tparent.parentNode.selectedIndex;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// If applicable, access the attribute via the DOM 0 way\n\t\t\tif ( name in elem && notxml && !special ) {\n\t\t\t\tif ( set ) {\n\t\t\t\t\t// We can't allow the type property to be changed (since it causes problems in IE)\n\t\t\t\t\tif ( name === \"type\" && rtype.test( elem.nodeName ) && elem.parentNode ) {\n\t\t\t\t\t\tjQuery.error( \"type property can't be changed\" );\n\t\t\t\t\t}\n\n\t\t\t\t\telem[ name ] = value;\n\t\t\t\t}\n\n\t\t\t\t// browsers index elements by id/name on forms, give priority to attributes.\n\t\t\t\tif ( jQuery.nodeName( elem, \"form\" ) && elem.getAttributeNode(name) ) {\n\t\t\t\t\treturn elem.getAttributeNode( name ).nodeValue;\n\t\t\t\t}\n\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\tif ( name === \"tabIndex\" ) {\n\t\t\t\t\tvar attributeNode = elem.getAttributeNode( \"tabIndex\" );\n\n\t\t\t\t\treturn attributeNode && attributeNode.specified ?\n\t\t\t\t\t\tattributeNode.value :\n\t\t\t\t\t\trfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ?\n\t\t\t\t\t\t\t0 :\n\t\t\t\t\t\t\tundefined;\n\t\t\t\t}\n\n\t\t\t\treturn elem[ name ];\n\t\t\t}\n\n\t\t\tif ( !jQuery.support.style && notxml && name === \"style\" ) {\n\t\t\t\tif ( set ) {\n\t\t\t\t\telem.style.cssText = \"\" + value;\n\t\t\t\t}\n\n\t\t\t\treturn elem.style.cssText;\n\t\t\t}\n\n\t\t\tif ( set ) {\n\t\t\t\t// convert the value to a string (all browsers do this but IE) see #1070\n\t\t\t\telem.setAttribute( name, \"\" + value );\n\t\t\t}\n\n\t\t\tvar attr = !jQuery.support.hrefNormalized && notxml && special ?\n\t\t\t\t\t// Some attributes require a special call on IE\n\t\t\t\t\telem.getAttribute( name, 2 ) :\n\t\t\t\t\telem.getAttribute( name );\n\n\t\t\t// Non-existent attributes return null, we normalize to undefined\n\t\t\treturn attr === null ? undefined : attr;\n\t\t}\n\n\t\t// elem is actually elem.style ... set the style\n\t\t// Using attr for specific style information is now deprecated. Use style instead.\n\t\treturn jQuery.style( elem, name, value );\n\t}\n});\nvar rnamespaces = /\\.(.*)$/,\n\tfcleanup = function( nm ) {\n\t\treturn nm.replace(/[^\\w\\s\\.\\|`]/g, function( ch ) {\n\t\t\treturn \"\\\\\" + ch;\n\t\t});\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\t// For whatever reason, IE has trouble passing the window object\n\t\t// around, causing it to be cloned in the process\n\t\tif ( elem.setInterval && ( elem !== window && !elem.frameElement ) ) {\n\t\t\telem = window;\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 = elemData.events || {},\n\t\t\teventHandle = elemData.handle, eventHandle;\n\n\t\tif ( !eventHandle ) {\n\t\t\telemData.handle = eventHandle = function() {\n\t\t\t\t// Handle the second event of a trigger and when\n\t\t\t\t// an event is called after a page has unloaded\n\t\t\t\treturn typeof jQuery !== \"undefined\" && !jQuery.event.triggered ?\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\thandleObj.guid = handler.guid;\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\t\t\t\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 global triggering\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\tvar ret, type, fn, i = 0, all, namespaces, namespace, special, eventType, handleObj, origType,\n\t\t\telemData = 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 ( var 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 ( var 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\tremoveEvent( 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 );\n\t\t\t}\n\t\t}\n\t},\n\n\t// bubbling is internal\n\ttrigger: function( event, data, elem /*, bubbling */ ) {\n\t\t// Event object or event type\n\t\tvar type = event.type || event,\n\t\t\tbubbling = arguments[3];\n\n\t\tif ( !bubbling ) {\n\t\t\tevent = typeof event === \"object\" ?\n\t\t\t\t// jQuery.Event object\n\t\t\t\tevent[expando] ? event :\n\t\t\t\t// Object literal\n\t\t\t\tjQuery.extend( jQuery.Event(type), event ) :\n\t\t\t\t// Just the event type (string)\n\t\t\t\tjQuery.Event(type);\n\n\t\t\tif ( type.indexOf(\"!\") >= 0 ) {\n\t\t\t\tevent.type = type = type.slice(0, -1);\n\t\t\t\tevent.exclusive = true;\n\t\t\t}\n\n\t\t\t// Handle a global trigger\n\t\t\tif ( !elem ) {\n\t\t\t\t// Don't bubble custom events when global (to avoid too much overhead)\n\t\t\t\tevent.stopPropagation();\n\n\t\t\t\t// Only trigger if we've ever bound an event for it\n\t\t\t\tif ( jQuery.event.global[ type ] ) {\n\t\t\t\t\tjQuery.each( jQuery.cache, function() {\n\t\t\t\t\t\tif ( this.events && this.events[type] ) {\n\t\t\t\t\t\t\tjQuery.event.trigger( event, data, this.handle.elem );\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// Handle triggering a single element\n\n\t\t\t// don't do events on text and comment nodes\n\t\t\tif ( !elem || elem.nodeType === 3 || elem.nodeType === 8 ) {\n\t\t\t\treturn undefined;\n\t\t\t}\n\n\t\t\t// Clean up in case it is reused\n\t\t\tevent.result = undefined;\n\t\t\tevent.target = elem;\n\n\t\t\t// Clone the incoming data, if any\n\t\t\tdata = jQuery.makeArray( data );\n\t\t\tdata.unshift( event );\n\t\t}\n\n\t\tevent.currentTarget = elem;\n\n\t\t// Trigger the event, it is assumed that \"handle\" is a function\n\t\tvar handle = jQuery.data( elem, \"handle\" );\n\t\tif ( handle ) {\n\t\t\thandle.apply( elem, data );\n\t\t}\n\n\t\tvar parent = elem.parentNode || elem.ownerDocument;\n\n\t\t// Trigger an inline bound script\n\t\ttry {\n\t\t\tif ( !(elem && elem.nodeName && jQuery.noData[elem.nodeName.toLowerCase()]) ) {\n\t\t\t\tif ( elem[ \"on\" + type ] && elem[ \"on\" + type ].apply( elem, data ) === false ) {\n\t\t\t\t\tevent.result = false;\n\t\t\t\t}\n\t\t\t}\n\n\t\t// prevent IE from throwing an error for some elements with some event types, see #3533\n\t\t} catch (e) {}\n\n\t\tif ( !event.isPropagationStopped() && parent ) {\n\t\t\tjQuery.event.trigger( event, data, parent, true );\n\n\t\t} else if ( !event.isDefaultPrevented() ) {\n\t\t\tvar target = event.target, old,\n\t\t\t\tisClick = jQuery.nodeName(target, \"a\") && type === \"click\",\n\t\t\t\tspecial = jQuery.event.special[ type ] || {};\n\n\t\t\tif ( (!special._default || special._default.call( elem, event ) === false) && \n\t\t\t\t!isClick && !(target && target.nodeName && jQuery.noData[target.nodeName.toLowerCase()]) ) {\n\n\t\t\t\ttry {\n\t\t\t\t\tif ( target[ type ] ) {\n\t\t\t\t\t\t// Make sure that we don't accidentally re-trigger the onFOO events\n\t\t\t\t\t\told = target[ \"on\" + type ];\n\n\t\t\t\t\t\tif ( old ) {\n\t\t\t\t\t\t\ttarget[ \"on\" + type ] = null;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tjQuery.event.triggered = true;\n\t\t\t\t\t\ttarget[ type ]();\n\t\t\t\t\t}\n\n\t\t\t\t// prevent IE from throwing an error for some elements with some event types, see #3533\n\t\t\t\t} catch (e) {}\n\n\t\t\t\tif ( old ) {\n\t\t\t\t\ttarget[ \"on\" + type ] = old;\n\t\t\t\t}\n\n\t\t\t\tjQuery.event.triggered = false;\n\t\t\t}\n\t\t}\n\t},\n\n\thandle: function( event ) {\n\t\tvar all, handlers, namespaces, namespace, events;\n\n\t\tevent = arguments[0] = jQuery.event.fix( event || window.event );\n\t\tevent.currentTarget = this;\n\n\t\t// Namespaced event handlers\n\t\tall = event.type.indexOf(\".\") < 0 && !event.exclusive;\n\n\t\tif ( !all ) {\n\t\t\tnamespaces = event.type.split(\".\");\n\t\t\tevent.type = namespaces.shift();\n\t\t\tnamespace = new RegExp(\"(^|\\\\.)\" + namespaces.slice(0).sort().join(\"\\\\.(?:.*\\\\.)?\") + \"(\\\\.|$)\");\n\t\t}\n\n\t\tvar events = jQuery.data(this, \"events\"), handlers = events[ event.type ];\n\n\t\tif ( events && handlers ) {\n\t\t\t// Clone the handlers to prevent manipulation\n\t\t\thandlers = handlers.slice(0);\n\n\t\t\tfor ( var j = 0, l = handlers.length; j < l; j++ ) {\n\t\t\t\tvar handleObj = handlers[ j ];\n\n\t\t\t\t// Filter the functions by class\n\t\t\t\tif ( all || namespace.test( handleObj.namespace ) ) {\n\t\t\t\t\t// Pass in a reference to the handler function itself\n\t\t\t\t\t// So that we can later remove it\n\t\t\t\t\tevent.handler = handleObj.handler;\n\t\t\t\t\tevent.data = handleObj.data;\n\t\t\t\t\tevent.handleObj = handleObj;\n\t\n\t\t\t\t\tvar ret = handleObj.handler.apply( this, arguments );\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\n\t\t\t\t\tif ( event.isImmediatePropagationStopped() ) {\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 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 originalTarget pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which\".split(\" \"),\n\n\tfix: function( event ) {\n\t\tif ( event[ 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\tevent.target = event.srcElement || document; // Fixes #1925 where srcElement might not be defined either\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 doc = document.documentElement, body = document.body;\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 && ((event.charCode || event.charCode === 0) ? event.charCode : event.keyCode) ) {\n\t\t\tevent.which = 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, handleObj.origType, jQuery.extend({}, handleObj, {handler: liveHandler}) ); \n\t\t\t},\n\n\t\t\tremove: function( handleObj ) {\n\t\t\t\tvar remove = true,\n\t\t\t\t\ttype = handleObj.origType.replace(rnamespaces, \"\");\n\t\t\t\t\n\t\t\t\tjQuery.each( jQuery.data(this, \"events\").live || [], function() {\n\t\t\t\t\tif ( type === this.origType.replace(rnamespaces, \"\") ) {\n\t\t\t\t\t\tremove = false;\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t});\n\n\t\t\t\tif ( remove ) {\n\t\t\t\t\tjQuery.event.remove( this, handleObj.origType, liveHandler );\n\t\t\t\t}\n\t\t\t}\n\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 ( this.setInterval ) {\n\t\t\t\t\tthis.onbeforeunload = eventHandle;\n\t\t\t\t}\n\n\t\t\t\treturn false;\n\t\t\t},\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\nvar removeEvent = document.removeEventListener ?\n\tfunction( elem, type, handle ) {\n\t\telem.removeEventListener( type, handle, false );\n\t} : \n\tfunction( elem, type, handle ) {\n\t\telem.detachEvent( \"on\" + type, handle );\n\t};\n\njQuery.Event = function( src ) {\n\t// Allow instantiation without the 'new' keyword\n\tif ( !this.preventDefault ) {\n\t\treturn new jQuery.Event( src );\n\t}\n\n\t// Event object\n\tif ( src && src.type ) {\n\t\tthis.originalEvent = src;\n\t\tthis.type = src.type;\n\t// Event type\n\t} else {\n\t\tthis.type = src;\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 = now();\n\n\t// Mark it as fixed\n\tthis[ 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\t\t\n\t\t// if preventDefault exists run it on the original event\n\t\tif ( e.preventDefault ) {\n\t\t\te.preventDefault();\n\t\t}\n\t\t// otherwise set the returnValue property of the original event to false (IE)\n\t\te.returnValue = false;\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// Firefox sometimes assigns relatedTarget a XUL element\n\t// which we cannot access the parentNode property of\n\ttry {\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// set the correct event type\n\t\t\tevent.type = event.data;\n\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 ( this.nodeName.toLowerCase() !== \"form\" ) {\n\t\t\t\tjQuery.event.add(this, \"click.specialSubmit\", function( e ) {\n\t\t\t\t\tvar elem = e.target, type = elem.type;\n\n\t\t\t\t\tif ( (type === \"submit\" || type === \"image\") && jQuery( elem ).closest(\"form\").length ) {\n\t\t\t\t\t\treturn trigger( \"submit\", this, arguments );\n\t\t\t\t\t}\n\t\t\t\t});\n\t \n\t\t\t\tjQuery.event.add(this, \"keypress.specialSubmit\", function( e ) {\n\t\t\t\t\tvar elem = e.target, type = 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\treturn trigger( \"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 formElems = /textarea|input|select/i,\n\n\tchangeFilters,\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 ( elem.nodeName.toLowerCase() === \"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 ( !formElems.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\t\t\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\treturn jQuery.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\tclick: function( e ) {\n\t\t\t\tvar elem = e.target, type = elem.type;\n\n\t\t\t\tif ( type === \"radio\" || type === \"checkbox\" || elem.nodeName.toLowerCase() === \"select\" ) {\n\t\t\t\t\treturn testChange.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 = elem.type;\n\n\t\t\t\tif ( (e.keyCode === 13 && elem.nodeName.toLowerCase() !== \"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\treturn testChange.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/focus[in] is not needed anymore\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 formElems.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 formElems.test( this.nodeName );\n\t\t}\n\t};\n\n\tchangeFilters = jQuery.event.special.change.filters;\n}\n\nfunction trigger( type, elem, args ) {\n\targs[0].type = type;\n\treturn jQuery.event.handle.apply( elem, args );\n}\n\n// Create \"bubbling\" focus and blur events\nif ( document.addEventListener ) {\n\tjQuery.each({ focus: \"focusin\", blur: \"focusout\" }, function( orig, fix ) {\n\t\tjQuery.event.special[ fix ] = {\n\t\t\tsetup: function() {\n\t\t\t\tthis.addEventListener( orig, handler, true );\n\t\t\t}, \n\t\t\tteardown: function() { \n\t\t\t\tthis.removeEventListener( orig, handler, true );\n\t\t\t}\n\t\t};\n\n\t\tfunction handler( e ) { \n\t\t\te = jQuery.event.fix( e );\n\t\t\te.type = fix;\n\t\t\treturn jQuery.event.handle.call( this, e );\n\t\t}\n\t});\n}\n\njQuery.each([\"bind\", \"one\"], function( i, name ) {\n\tjQuery.fn[ name ] = function( type, data, fn ) {\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\t\t\n\t\tif ( jQuery.isFunction( data ) ) {\n\t\t\tfn = data;\n\t\t\tdata = undefined;\n\t\t}\n\n\t\tvar handler = name === \"one\" ? jQuery.proxy( fn, function( event ) {\n\t\t\tjQuery( this ).unbind( event, handler );\n\t\t\treturn fn.apply( this, arguments );\n\t\t}) : fn;\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\t\n\tdelegate: function( selector, types, data, fn ) {\n\t\treturn this.live( types, data, fn, selector );\n\t},\n\t\n\tundelegate: function( selector, types, fn ) {\n\t\tif ( arguments.length === 0 ) {\n\t\t\t\treturn this.unbind( \"live\" );\n\t\t\n\t\t} else {\n\t\t\treturn this.die( types, null, fn, selector );\n\t\t}\n\t},\n\t\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\tvar event = jQuery.Event( type );\n\t\t\tevent.preventDefault();\n\t\t\tevent.stopPropagation();\n\t\t\tjQuery.event.trigger( event, data, this[0] );\n\t\t\treturn event.result;\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, i = 1;\n\n\t\t// link all the functions, so any of them can unbind this click handler\n\t\twhile ( i < args.length ) {\n\t\t\tjQuery.proxy( fn, args[ i++ ] );\n\t\t}\n\n\t\treturn this.click( jQuery.proxy( fn, function( event ) {\n\t\t\t// Figure out which function to execute\n\t\t\tvar lastToggle = ( jQuery.data( this, \"lastToggle\" + fn.guid ) || 0 ) % i;\n\t\t\tjQuery.data( this, \"lastToggle\" + fn.guid, lastToggle + 1 );\n\n\t\t\t// Make sure that clicks stop\n\t\t\tevent.preventDefault();\n\n\t\t\t// and execute the function\n\t\t\treturn args[ lastToggle ].apply( this, arguments ) || false;\n\t\t}));\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 ( jQuery.isFunction( data ) ) {\n\t\t\tfn = data;\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 ( type === \"focus\" || type === \"blur\" ) {\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\tcontext.each(function(){\n\t\t\t\t\tjQuery.event.add( this, 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( liveConvert( type, selector ), fn );\n\t\t\t}\n\t\t}\n\t\t\n\t\treturn this;\n\t}\n});\n\nfunction liveHandler( event ) {\n\tvar stop, elems = [], selectors = [], args = arguments,\n\t\trelated, match, handleObj, elem, j, i, l, data,\n\t\tevents = jQuery.data( this, \"events\" );\n\n\t// Make sure we avoid non-left-click bubbling in Firefox (#3861)\n\tif ( event.liveFired === this || !events || !events.live || event.button && event.type === \"click\" ) {\n\t\treturn;\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\tfor ( j = 0; j < live.length; j++ ) {\n\t\t\thandleObj = live[j];\n\n\t\t\tif ( match[i].selector === handleObj.selector ) {\n\t\t\t\telem = match[i].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\trelated = jQuery( event.relatedTarget ).closest( handleObj.selector )[0];\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 });\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\t\tevent.currentTarget = match.elem;\n\t\tevent.data = match.handleObj.data;\n\t\tevent.handleObj = match.handleObj;\n\n\t\tif ( match.handleObj.origHandler.apply( match.elem, args ) === false ) {\n\t\t\tstop = false;\n\t\t\tbreak;\n\t\t}\n\t}\n\n\treturn stop;\n}\n\nfunction liveConvert( type, selector ) {\n\treturn \"live.\" + (type && type !== \"*\" ? type + \".\" : \"\") + selector.replace(/\\./g, \"`\").replace(/ /g, \"&\");\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( fn ) {\n\t\treturn fn ? this.bind( name, fn ) : this.trigger( name );\n\t};\n\n\tif ( jQuery.attrFn ) {\n\t\tjQuery.attrFn[ name ] = true;\n\t}\n});\n\n// Prevent memory leaks in IE\n// Window isn't included so as not to unbind existing unload events\n// More info:\n//  - http://isaacschlueter.com/2006/10/msie-memory-leaks/\nif ( window.attachEvent && !window.addEventListener ) {\n\twindow.attachEvent(\"onunload\", function() {\n\t\tfor ( var id in jQuery.cache ) {\n\t\t\tif ( jQuery.cache[ id ].handle ) {\n\t\t\t\t// Try/Catch is to handle iframes being unloaded, see #4280\n\t\t\t\ttry {\n\t\t\t\t\tjQuery.event.remove( jQuery.cache[ id ].handle.elem );\n\t\t\t\t} catch(e) {}\n\t\t\t}\n\t\t}\n\t});\n}\n/*!\n * Sizzle CSS Selector Engine - v1.0\n *  Copyright 2009, 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\n// Here we check if the JavaScript engine is using some sort of\n// optimization where it does not always call our comparison\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\tvar origContext = context = context || document;\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 parts = [], m, set, checkSet, extra, prune = true, contextXML = isXML(context),\n\t\tsoFar = selector;\n\t\n\t// Reset the position of the chunker regexp (start from head)\n\twhile ( (chunker.exec(\"\"), m = chunker.exec(soFar)) !== null ) {\n\t\tsoFar = m[3];\n\t\t\n\t\tparts.push( m[1] );\n\t\t\n\t\tif ( m[2] ) {\n\t\t\textra = m[3];\n\t\t\tbreak;\n\t\t}\n\t}\n\n\tif ( parts.length > 1 && origPOS.exec( selector ) ) {\n\t\tif ( parts.length === 2 && Expr.relative[ parts[0] ] ) {\n\t\t\tset = posProcess( parts[0] + parts[1], context );\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\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\t\t\tvar ret = Sizzle.find( parts.shift(), context, contextXML );\n\t\t\tcontext = ret.expr ? Sizzle.filter( ret.expr, ret.set )[0] : ret.set[0];\n\t\t}\n\n\t\tif ( context ) {\n\t\t\tvar ret = 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\t\t\tset = ret.expr ? Sizzle.filter( ret.expr, ret.set ) : ret.set;\n\n\t\t\tif ( parts.length > 0 ) {\n\t\t\t\tcheckSet = makeArray(set);\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\tvar cur = parts.pop(), pop = 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\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\t\t} else if ( context && context.nodeType === 1 ) {\n\t\t\tfor ( var i = 0; checkSet[i] != null; i++ ) {\n\t\t\t\tif ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && contains(context, checkSet[i])) ) {\n\t\t\t\t\tresults.push( set[i] );\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tfor ( var 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\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.find = function(expr, context, isXML){\n\tvar set, match;\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 type = Expr.order[i], match;\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(/\\\\/g, \"\");\n\t\t\t\tset = Expr.find[ type ]( match, context, isXML );\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 = context.getElementsByTagName(\"*\");\n\t}\n\n\treturn {set: set, expr: expr};\n};\n\nSizzle.filter = function(expr, set, inplace, not){\n\tvar old = expr, result = [], curLoop = set, match, anyFound,\n\t\tisXMLFilter = set && set[0] && 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 filter = Expr.filter[ type ], found, item, left = match[1];\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\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\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\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\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\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|)\\s*\\]/,\n\t\tTAG: /^((?:[\\w\\u00c0-\\uFFFF\\*-]|\\\\.)+)/,\n\t\tCHILD: /:(only|nth|last|first)-child(?:\\((even|odd|[\\dn+-]*)\\))?/,\n\t\tPOS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\\((\\d*)\\))?(?=[^-]|$)/,\n\t\tPSEUDO: /:((?:[\\w\\u00c0-\\uFFFF-]|\\\\.)+)(?:\\((['\"]?)((?:\\([^\\)]+\\)|[^\\(\\)]*)+)\\2\\))?/\n\t},\n\tleftMatch: {},\n\tattrMap: {\n\t\t\"class\": \"className\",\n\t\t\"for\": \"htmlFor\"\n\t},\n\tattrHandle: {\n\t\thref: function(elem){\n\t\t\treturn elem.getAttribute(\"href\");\n\t\t}\n\t},\n\trelative: {\n\t\t\"+\": function(checkSet, part){\n\t\t\tvar isPartStr = typeof part === \"string\",\n\t\t\t\tisTag = isPartStr && !/\\W/.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\t\t\">\": function(checkSet, part){\n\t\t\tvar isPartStr = typeof part === \"string\";\n\n\t\t\tif ( isPartStr && !/\\W/.test(part) ) {\n\t\t\t\tpart = part.toLowerCase();\n\n\t\t\t\tfor ( var i = 0, l = checkSet.length; i < l; i++ ) {\n\t\t\t\t\tvar elem = checkSet[i];\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\t\t\t} else {\n\t\t\t\tfor ( var i = 0, l = checkSet.length; i < l; i++ ) {\n\t\t\t\t\tvar elem = checkSet[i];\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\t\t\"\": function(checkSet, part, isXML){\n\t\t\tvar doneName = done++, checkFn = dirCheck;\n\n\t\t\tif ( typeof part === \"string\" && !/\\W/.test(part) ) {\n\t\t\t\tvar nodeCheck = part = part.toLowerCase();\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\t\t\"~\": function(checkSet, part, isXML){\n\t\t\tvar doneName = done++, checkFn = dirCheck;\n\n\t\t\tif ( typeof part === \"string\" && !/\\W/.test(part) ) {\n\t\t\t\tvar nodeCheck = part = part.toLowerCase();\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\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\treturn m ? [m] : [];\n\t\t\t}\n\t\t},\n\t\tNAME: function(match, context){\n\t\t\tif ( typeof context.getElementsByName !== \"undefined\" ) {\n\t\t\t\tvar ret = [], results = 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\t\tTAG: function(match, context){\n\t\t\treturn context.getElementsByTagName(match[1]);\n\t\t}\n\t},\n\tpreFilter: {\n\t\tCLASS: function(match, curLoop, inplace, result, not, isXML){\n\t\t\tmatch = \" \" + match[1].replace(/\\\\/g, \"\") + \" \";\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]/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\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\t\tID: function(match){\n\t\t\treturn match[1].replace(/\\\\/g, \"\");\n\t\t},\n\t\tTAG: function(match, curLoop){\n\t\t\treturn match[1].toLowerCase();\n\t\t},\n\t\tCHILD: function(match){\n\t\t\tif ( match[1] === \"nth\" ) {\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\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\t\tATTR: function(match, curLoop, inplace, result, not, isXML){\n\t\t\tvar name = match[1].replace(/\\\\/g, \"\");\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\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\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\t\t\t\t} else {\n\t\t\t\t\tvar ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not);\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\t\t\t\t\treturn false;\n\t\t\t\t}\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\t\tPOS: function(match){\n\t\t\tmatch.unshift( true );\n\t\t\treturn match;\n\t\t}\n\t},\n\tfilters: {\n\t\tenabled: function(elem){\n\t\t\treturn elem.disabled === false && elem.type !== \"hidden\";\n\t\t},\n\t\tdisabled: function(elem){\n\t\t\treturn elem.disabled === true;\n\t\t},\n\t\tchecked: function(elem){\n\t\t\treturn elem.checked === true;\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\telem.parentNode.selectedIndex;\n\t\t\treturn elem.selected === true;\n\t\t},\n\t\tparent: function(elem){\n\t\t\treturn !!elem.firstChild;\n\t\t},\n\t\tempty: function(elem){\n\t\t\treturn !elem.firstChild;\n\t\t},\n\t\thas: function(elem, i, match){\n\t\t\treturn !!Sizzle( match[3], elem ).length;\n\t\t},\n\t\theader: function(elem){\n\t\t\treturn /h\\d/i.test( elem.nodeName );\n\t\t},\n\t\ttext: function(elem){\n\t\t\treturn \"text\" === elem.type;\n\t\t},\n\t\tradio: function(elem){\n\t\t\treturn \"radio\" === elem.type;\n\t\t},\n\t\tcheckbox: function(elem){\n\t\t\treturn \"checkbox\" === elem.type;\n\t\t},\n\t\tfile: function(elem){\n\t\t\treturn \"file\" === elem.type;\n\t\t},\n\t\tpassword: function(elem){\n\t\t\treturn \"password\" === elem.type;\n\t\t},\n\t\tsubmit: function(elem){\n\t\t\treturn \"submit\" === elem.type;\n\t\t},\n\t\timage: function(elem){\n\t\t\treturn \"image\" === elem.type;\n\t\t},\n\t\treset: function(elem){\n\t\t\treturn \"reset\" === elem.type;\n\t\t},\n\t\tbutton: function(elem){\n\t\t\treturn \"button\" === elem.type || elem.nodeName.toLowerCase() === \"button\";\n\t\t},\n\t\tinput: function(elem){\n\t\t\treturn /input|select|textarea|button/i.test(elem.nodeName);\n\t\t}\n\t},\n\tsetFilters: {\n\t\tfirst: function(elem, i){\n\t\t\treturn i === 0;\n\t\t},\n\t\tlast: function(elem, i, match, array){\n\t\t\treturn i === array.length - 1;\n\t\t},\n\t\teven: function(elem, i){\n\t\t\treturn i % 2 === 0;\n\t\t},\n\t\todd: function(elem, i){\n\t\t\treturn i % 2 === 1;\n\t\t},\n\t\tlt: function(elem, i, match){\n\t\t\treturn i < match[3] - 0;\n\t\t},\n\t\tgt: function(elem, i, match){\n\t\t\treturn i > match[3] - 0;\n\t\t},\n\t\tnth: function(elem, i, match){\n\t\t\treturn match[3] - 0 === i;\n\t\t},\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], filter = Expr.filters[ name ];\n\n\t\t\tif ( filter ) {\n\t\t\t\treturn filter( elem, i, match, array );\n\t\t\t} else if ( name === \"contains\" ) {\n\t\t\t\treturn (elem.textContent || elem.innerText || getText([ elem ]) || \"\").indexOf(match[3]) >= 0;\n\t\t\t} else if ( name === \"not\" ) {\n\t\t\t\tvar not = match[3];\n\n\t\t\t\tfor ( var i = 0, l = not.length; i < l; i++ ) {\n\t\t\t\t\tif ( not[i] === 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\t\t\t} else {\n\t\t\t\tSizzle.error( \"Syntax error, unrecognized expression: \" + name );\n\t\t\t}\n\t\t},\n\t\tCHILD: function(elem, match){\n\t\t\tvar type = match[1], node = elem;\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\t\t\t\t\tif ( type === \"first\" ) { \n\t\t\t\t\t\treturn true; \n\t\t\t\t\t}\n\t\t\t\t\tnode = elem;\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\t\t\t\t\treturn true;\n\t\t\t\tcase 'nth':\n\t\t\t\t\tvar first = match[2], last = 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\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\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\t\t\t\t\tif ( first === 0 ) {\n\t\t\t\t\t\treturn diff === 0;\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\t\tID: function(elem, match){\n\t\t\treturn elem.nodeType === 1 && elem.getAttribute(\"id\") === match;\n\t\t},\n\t\tTAG: function(elem, match){\n\t\t\treturn (match === \"*\" && elem.nodeType === 1) || elem.nodeName.toLowerCase() === match;\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\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\t\tPOS: function(elem, match, i, array){\n\t\t\tvar name = match[2], filter = 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\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, function(all, num){\n\t\treturn \"\\\\\" + (num - 0 + 1);\n\t}));\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 ret = results || [];\n\n\t\tif ( toString.call(array) === \"[object Array]\" ) {\n\t\t\tArray.prototype.push.apply( ret, array );\n\t\t} else {\n\t\t\tif ( typeof array.length === \"number\" ) {\n\t\t\t\tfor ( var i = 0, l = array.length; i < l; i++ ) {\n\t\t\t\t\tret.push( array[i] );\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tfor ( var i = 0; 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;\n\nif ( document.documentElement.compareDocumentPosition ) {\n\tsortOrder = function( a, b ) {\n\t\tif ( !a.compareDocumentPosition || !b.compareDocumentPosition ) {\n\t\t\tif ( a == b ) {\n\t\t\t\thasDuplicate = true;\n\t\t\t}\n\t\t\treturn a.compareDocumentPosition ? -1 : 1;\n\t\t}\n\n\t\tvar ret = a.compareDocumentPosition(b) & 4 ? -1 : a === b ? 0 : 1;\n\t\tif ( ret === 0 ) {\n\t\t\thasDuplicate = true;\n\t\t}\n\t\treturn ret;\n\t};\n} else if ( \"sourceIndex\" in document.documentElement ) {\n\tsortOrder = function( a, b ) {\n\t\tif ( !a.sourceIndex || !b.sourceIndex ) {\n\t\t\tif ( a == b ) {\n\t\t\t\thasDuplicate = true;\n\t\t\t}\n\t\t\treturn a.sourceIndex ? -1 : 1;\n\t\t}\n\n\t\tvar ret = a.sourceIndex - b.sourceIndex;\n\t\tif ( ret === 0 ) {\n\t\t\thasDuplicate = true;\n\t\t}\n\t\treturn ret;\n\t};\n} else if ( document.createRange ) {\n\tsortOrder = function( a, b ) {\n\t\tif ( !a.ownerDocument || !b.ownerDocument ) {\n\t\t\tif ( a == b ) {\n\t\t\t\thasDuplicate = true;\n\t\t\t}\n\t\t\treturn a.ownerDocument ? -1 : 1;\n\t\t}\n\n\t\tvar aRange = a.ownerDocument.createRange(), bRange = b.ownerDocument.createRange();\n\t\taRange.setStart(a, 0);\n\t\taRange.setEnd(a, 0);\n\t\tbRange.setStart(b, 0);\n\t\tbRange.setEnd(b, 0);\n\t\tvar ret = aRange.compareBoundaryPoints(Range.START_TO_END, bRange);\n\t\tif ( ret === 0 ) {\n\t\t\thasDuplicate = true;\n\t\t}\n\t\treturn ret;\n\t};\n}\n\n// Utility function for retrieving the text value of an array of DOM nodes\nfunction getText( 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 += 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\tform.innerHTML = \"<a name='\" + id + \"'/>\";\n\n\t// Inject it into the root element, check its status, and remove it quickly\n\tvar root = document.documentElement;\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\t\t\t\treturn m ? m.id === match[1] || typeof m.getAttributeNode !== \"undefined\" && m.getAttributeNode(\"id\").nodeValue === match[1] ? [m] : undefined : [];\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\t\t\treturn elem.nodeType === 1 && node && node.nodeValue === match;\n\t\t};\n\t}\n\n\troot.removeChild( form );\n\troot = form = null; // release memory in IE\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\tif ( div.firstChild && typeof div.firstChild.getAttribute !== \"undefined\" &&\n\t\t\tdiv.firstChild.getAttribute(\"href\") !== \"#\" ) {\n\t\tExpr.attrHandle.href = function(elem){\n\t\t\treturn elem.getAttribute(\"href\", 2);\n\t\t};\n\t}\n\n\tdiv = null; // release memory in IE\n})();\n\nif ( document.querySelectorAll ) {\n\t(function(){\n\t\tvar oldSizzle = Sizzle, div = document.createElement(\"div\");\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 && context.nodeType === 9 && !isXML(context) ) {\n\t\t\t\ttry {\n\t\t\t\t\treturn makeArray( context.querySelectorAll(query), extra );\n\t\t\t\t} catch(e){}\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\tdiv = null; // release memory in IE\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\tdiv = null; // release memory in IE\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\t\tif ( elem ) {\n\t\t\telem = elem[dir];\n\t\t\tvar match = false;\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\t\tif ( elem ) {\n\t\t\telem = elem[dir];\n\t\t\tvar match = false;\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\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\nvar contains = document.compareDocumentPosition ? function(a, b){\n\treturn !!(a.compareDocumentPosition(b) & 16);\n} : function(a, b){\n\treturn a !== b && (a.contains ? a.contains(b) : true);\n};\n\nvar 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\treturn documentElement ? documentElement.nodeName !== \"HTML\" : false;\n};\n\nvar posProcess = function(selector, context){\n\tvar tmpSet = [], later = \"\", match,\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 = getText;\njQuery.isXMLDoc = isXML;\njQuery.contains = contains;\n\nreturn;\n\nwindow.Sizzle = Sizzle;\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\tslice = Array.prototype.slice;\n\n// Implement the identical functionality for filter and not\nvar winnow = function( elements, qualifier, keep ) {\n\tif ( jQuery.isFunction( qualifier ) ) {\n\t\treturn jQuery.grep(elements, function( elem, i ) {\n\t\t\treturn !!qualifier.call( elem, i, elem ) === 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\njQuery.fn.extend({\n\tfind: function( selector ) {\n\t\tvar ret = this.pushStack( \"\", \"find\", selector ), length = 0;\n\n\t\tfor ( var 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 ( var n = length; n < ret.length; n++ ) {\n\t\t\t\t\tfor ( var 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\t\n\tis: function( selector ) {\n\t\treturn !!selector && jQuery.filter( selector, this ).length > 0;\n\t},\n\n\tclosest: function( selectors, context ) {\n\t\tif ( jQuery.isArray( selectors ) ) {\n\t\t\tvar ret = [], cur = this[0], match, matches = {}, selector;\n\n\t\t\tif ( cur && selectors.length ) {\n\t\t\t\tfor ( var 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] = jQuery.expr.match.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 });\n\t\t\t\t\t\t\tdelete matches[selector];\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tcur = cur.parentNode;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn ret;\n\t\t}\n\n\t\tvar pos = jQuery.expr.match.POS.test( selectors ) ? \n\t\t\tjQuery( selectors, context || this.context ) : null;\n\n\t\treturn this.map(function( i, cur ) {\n\t\t\twhile ( cur && cur.ownerDocument && cur !== context ) {\n\t\t\t\tif ( pos ? pos.index(cur) > -1 : jQuery(cur).is(selectors) ) {\n\t\t\t\t\treturn cur;\n\t\t\t\t}\n\t\t\t\tcur = cur.parentNode;\n\t\t\t}\n\t\t\treturn null;\n\t\t});\n\t},\n\t\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 || this.context ) :\n\t\t\t\tjQuery.makeArray( 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\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 ? 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 jQuery.find.matches(expr, elems);\n\t},\n\t\n\tdir: function( elem, dir, until ) {\n\t\tvar matched = [], cur = elem[dir];\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});\nvar rinlinejQuery = / jQuery\\d+=\"(?:\\d+|null)\"/g,\n\trleadingWhitespace = /^\\s+/,\n\trxhtmlTag = /(<([\\w:]+)[^>]*?)\\/>/g,\n\trselfClosing = /^(?:area|br|col|embed|hr|img|input|link|meta|param)$/i,\n\trtagName = /<([\\w:]+)/,\n\trtbody = /<tbody/i,\n\trhtml = /<|&#?\\w+;/,\n\trnocache = /<script|<object|<embed|<option|<style/i,\n\trchecked = /checked\\s*(?:[^=]|=\\s*.checked.)/i,  // checked=\"checked\" or checked (html5)\n\tfcloseTag = function( all, front, tag ) {\n\t\treturn rselfClosing.test( tag ) ?\n\t\t\tall :\n\t\t\tfront + \"></\" + tag + \">\";\n\t},\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\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 ), contents = 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\t\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\t elem.parentNode.removeChild( elem );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t\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\t\t\n\t\treturn this;\n\t},\n\n\tclone: function( events ) {\n\t\t// Do the clone\n\t\tvar ret = this.map(function() {\n\t\t\tif ( !jQuery.support.noCloneEvent && !jQuery.isXMLDoc(this) ) {\n\t\t\t\t// IE copies events bound via attachEvent when\n\t\t\t\t// using cloneNode. Calling detachEvent on the\n\t\t\t\t// clone will also remove the events from the original.\n\t\t\t\t// In order to get around this, we use innerHTML.\n\t\t\t\t// Unfortunately, this means some modifications to\n\t\t\t\t// attributes in IE that are actually only stored\n\t\t\t\t// as properties will not be copied (such as the\n\t\t\t\t// name attribute on an input).\n\t\t\t\tvar html = this.outerHTML, ownerDocument = this.ownerDocument;\n\t\t\t\tif ( !html ) {\n\t\t\t\t\tvar div = ownerDocument.createElement(\"div\");\n\t\t\t\t\tdiv.appendChild( this.cloneNode(true) );\n\t\t\t\t\thtml = div.innerHTML;\n\t\t\t\t}\n\n\t\t\t\treturn jQuery.clean([html.replace(rinlinejQuery, \"\")\n\t\t\t\t\t// Handle the case in IE 8 where action=/test/> self-closes a tag\n\t\t\t\t\t.replace(/=([^=\"'>\\s]+\\/)>/g, '=\"$1\">')\n\t\t\t\t\t.replace(rleadingWhitespace, \"\")], ownerDocument)[0];\n\t\t\t} else {\n\t\t\t\treturn this.cloneNode(true);\n\t\t\t}\n\t\t});\n\n\t\t// Copy the events from the original to the clone\n\t\tif ( events === true ) {\n\t\t\tcloneCopyEvent( this, ret );\n\t\t\tcloneCopyEvent( this.find(\"*\"), ret.find(\"*\") );\n\t\t}\n\n\t\t// Return the cloned set\n\t\treturn ret;\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, fcloseTag);\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), old = self.html();\n\t\t\t\tself.empty().append(function(){\n\t\t\t\t\treturn value.call( this, i, old );\n\t\t\t\t});\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, parent = 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.pushStack( jQuery(jQuery.isFunction(value) ? value() : value), \"replaceWith\", value );\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, value = args[0], scripts = [], fragment, parent;\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 = buildFragment( args, this, scripts );\n\t\t\t}\n\t\t\t\n\t\t\tfragment = results.fragment;\n\t\t\t\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; 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\ti > 0 || results.cacheable || this.length > 1  ?\n\t\t\t\t\t\t\tfragment.cloneNode(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\n\t\tfunction root( elem, cur ) {\n\t\t\treturn jQuery.nodeName(elem, \"table\") ?\n\t\t\t\t(elem.getElementsByTagName(\"tbody\")[0] ||\n\t\t\t\telem.appendChild(elem.ownerDocument.createElement(\"tbody\"))) :\n\t\t\t\telem;\n\t\t}\n\t}\n});\n\nfunction cloneCopyEvent(orig, ret) {\n\tvar i = 0;\n\n\tret.each(function() {\n\t\tif ( this.nodeName !== (orig[i] && orig[i].nodeName) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar oldData = jQuery.data( orig[i++] ), curData = jQuery.data( this, oldData ), events = oldData && oldData.events;\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 handler in events[ type ] ) {\n\t\t\t\t\tjQuery.event.add( this, type, events[ type ][ handler ], events[ type ][ handler ].data );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t});\n}\n\nfunction buildFragment( 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) 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\t!rnocache.test( args[0] ) && (jQuery.support.checkClone || !rchecked.test( args[0] )) ) {\n\n\t\tcacheable = true;\n\t\tcacheresults = jQuery.fragments[ args[0] ];\n\t\tif ( cacheresults ) {\n\t\t\tif ( cacheresults !== 1 ) {\n\t\t\t\tfragment = cacheresults;\n\t\t\t}\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 = [], insert = jQuery( selector ),\n\t\t\tparent = this.length === 1 && this[0].parentNode;\n\t\t\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\t\t\t\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.fn[ original ].apply( jQuery(insert[i]), elems );\n\t\t\t\tret = ret.concat( elems );\n\t\t\t}\n\t\t\n\t\t\treturn this.pushStack( ret, name, insert.selector );\n\t\t}\n\t};\n});\n\njQuery.extend({\n\tclean: function( elems, context, fragment, scripts ) {\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 = [];\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\" && !rhtml.test( elem ) ) {\n\t\t\t\telem = context.createTextNode( elem );\n\n\t\t\t} else if ( typeof elem === \"string\" ) {\n\t\t\t\t// Fix \"XHTML\"-style tags in all browsers\n\t\t\t\telem = elem.replace(rxhtmlTag, fcloseTag);\n\n\t\t\t\t// Trim whitespace, otherwise indexOf won't work as expected\n\t\t\t\tvar tag = (rtagName.exec( elem ) || [\"\", \"\"])[1].toLowerCase(),\n\t\t\t\t\twrap = wrapMap[ tag ] || wrapMap._default,\n\t\t\t\t\tdepth = wrap[0],\n\t\t\t\t\tdiv = context.createElement(\"div\");\n\n\t\t\t\t// Go to html and back, then peel off extra wrappers\n\t\t\t\tdiv.innerHTML = wrap[1] + elem + wrap[2];\n\n\t\t\t\t// Move to the right depth\n\t\t\t\twhile ( depth-- ) {\n\t\t\t\t\tdiv = div.lastChild;\n\t\t\t\t}\n\n\t\t\t\t// Remove IE's autoinserted <tbody> from table fragments\n\t\t\t\tif ( !jQuery.support.tbody ) {\n\n\t\t\t\t\t// String was a <table>, *may* have spurious <tbody>\n\t\t\t\t\tvar hasBody = rtbody.test(elem),\n\t\t\t\t\t\ttbody = tag === \"table\" && !hasBody ?\n\t\t\t\t\t\t\tdiv.firstChild && div.firstChild.childNodes :\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>\" && !hasBody ?\n\t\t\t\t\t\t\t\tdiv.childNodes :\n\t\t\t\t\t\t\t\t[];\n\n\t\t\t\t\tfor ( var j = tbody.length - 1; j >= 0 ; --j ) {\n\t\t\t\t\t\tif ( jQuery.nodeName( tbody[ j ], \"tbody\" ) && !tbody[ j ].childNodes.length ) {\n\t\t\t\t\t\t\ttbody[ j ].parentNode.removeChild( tbody[ j ] );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t}\n\n\t\t\t\t// IE completely kills leading whitespace when innerHTML is used\n\t\t\t\tif ( !jQuery.support.leadingWhitespace && rleadingWhitespace.test( elem ) ) {\n\t\t\t\t\tdiv.insertBefore( context.createTextNode( rleadingWhitespace.exec(elem)[0] ), div.firstChild );\n\t\t\t\t}\n\n\t\t\t\telem = div.childNodes;\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\tfor ( var 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\t\t\t\t\n\t\t\t\t} else {\n\t\t\t\t\tif ( ret[i].nodeType === 1 ) {\n\t\t\t\t\t\tret.splice.apply( ret, [i + 1, 0].concat(jQuery.makeArray(ret[i].getElementsByTagName(\"script\"))) );\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\t\n\tcleanData: function( elems ) {\n\t\tvar data, id, cache = jQuery.cache,\n\t\t\tspecial = jQuery.event.special,\n\t\t\tdeleteExpando = jQuery.support.deleteExpando;\n\t\t\n\t\tfor ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {\n\t\t\tid = elem[ jQuery.expando ];\n\t\t\t\n\t\t\tif ( id ) {\n\t\t\t\tdata = cache[ id ];\n\t\t\t\t\n\t\t\t\tif ( 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} else {\n\t\t\t\t\t\t\tremoveEvent( elem, type, data.handle );\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\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\t\t\t\t\n\t\t\t\tdelete cache[ id ];\n\t\t\t}\n\t\t}\n\t}\n});\n// exclude the following css properties to add px\nvar rexclude = /z-?index|font-?weight|opacity|zoom|line-?height/i,\n\tralpha = /alpha\\([^)]*\\)/,\n\tropacity = /opacity=([^)]*)/,\n\trfloat = /float/i,\n\trdashAlpha = /-([a-z])/ig,\n\trupper = /([A-Z])/g,\n\trnumpx = /^-?\\d+(?:px)?$/i,\n\trnum = /^-?\\d/,\n\n\tcssShow = { position: \"absolute\", visibility: \"hidden\", display:\"block\" },\n\tcssWidth = [ \"Left\", \"Right\" ],\n\tcssHeight = [ \"Top\", \"Bottom\" ],\n\n\t// cache check for defaultView.getComputedStyle\n\tgetComputedStyle = document.defaultView && document.defaultView.getComputedStyle,\n\t// normalize float css property\n\tstyleFloat = jQuery.support.cssFloat ? \"cssFloat\" : \"styleFloat\",\n\tfcamelCase = function( all, letter ) {\n\t\treturn letter.toUpperCase();\n\t};\n\njQuery.fn.css = function( name, value ) {\n\treturn access( this, name, value, true, function( elem, name, value ) {\n\t\tif ( value === undefined ) {\n\t\t\treturn jQuery.curCSS( elem, name );\n\t\t}\n\t\t\n\t\tif ( typeof value === \"number\" && !rexclude.test(name) ) {\n\t\t\tvalue += \"px\";\n\t\t}\n\n\t\tjQuery.style( elem, name, value );\n\t});\n};\n\njQuery.extend({\n\tstyle: function( elem, name, value ) {\n\t\t// don't set styles on text and comment nodes\n\t\tif ( !elem || elem.nodeType === 3 || elem.nodeType === 8 ) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\t// ignore negative width and height values #1599\n\t\tif ( (name === \"width\" || name === \"height\") && parseFloat(value) < 0 ) {\n\t\t\tvalue = undefined;\n\t\t}\n\n\t\tvar style = elem.style || elem, set = value !== undefined;\n\n\t\t// IE uses filters for opacity\n\t\tif ( !jQuery.support.opacity && name === \"opacity\" ) {\n\t\t\tif ( set ) {\n\t\t\t\t// IE has trouble with opacity if it does not have layout\n\t\t\t\t// Force it by setting the zoom level\n\t\t\t\tstyle.zoom = 1;\n\n\t\t\t\t// Set the alpha filter to set the opacity\n\t\t\t\tvar opacity = parseInt( value, 10 ) + \"\" === \"NaN\" ? \"\" : \"alpha(opacity=\" + value * 100 + \")\";\n\t\t\t\tvar filter = style.filter || jQuery.curCSS( elem, \"filter\" ) || \"\";\n\t\t\t\tstyle.filter = ralpha.test(filter) ? filter.replace(ralpha, opacity) : opacity;\n\t\t\t}\n\n\t\t\treturn style.filter && style.filter.indexOf(\"opacity=\") >= 0 ?\n\t\t\t\t(parseFloat( ropacity.exec(style.filter)[1] ) / 100) + \"\":\n\t\t\t\t\"\";\n\t\t}\n\n\t\t// Make sure we're using the right name for getting the float value\n\t\tif ( rfloat.test( name ) ) {\n\t\t\tname = styleFloat;\n\t\t}\n\n\t\tname = name.replace(rdashAlpha, fcamelCase);\n\n\t\tif ( set ) {\n\t\t\tstyle[ name ] = value;\n\t\t}\n\n\t\treturn style[ name ];\n\t},\n\n\tcss: function( elem, name, force, extra ) {\n\t\tif ( name === \"width\" || name === \"height\" ) {\n\t\t\tvar val, props = cssShow, which = name === \"width\" ? cssWidth : cssHeight;\n\n\t\t\tfunction getWH() {\n\t\t\t\tval = name === \"width\" ? elem.offsetWidth : elem.offsetHeight;\n\n\t\t\t\tif ( extra === \"border\" ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tjQuery.each( which, function() {\n\t\t\t\t\tif ( !extra ) {\n\t\t\t\t\t\tval -= parseFloat(jQuery.curCSS( elem, \"padding\" + this, true)) || 0;\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( extra === \"margin\" ) {\n\t\t\t\t\t\tval += parseFloat(jQuery.curCSS( elem, \"margin\" + this, true)) || 0;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tval -= parseFloat(jQuery.curCSS( elem, \"border\" + this + \"Width\", true)) || 0;\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tif ( elem.offsetWidth !== 0 ) {\n\t\t\t\tgetWH();\n\t\t\t} else {\n\t\t\t\tjQuery.swap( elem, props, getWH );\n\t\t\t}\n\n\t\t\treturn Math.max(0, Math.round(val));\n\t\t}\n\n\t\treturn jQuery.curCSS( elem, name, force );\n\t},\n\n\tcurCSS: function( elem, name, force ) {\n\t\tvar ret, style = elem.style, filter;\n\n\t\t// IE uses filters for opacity\n\t\tif ( !jQuery.support.opacity && name === \"opacity\" && elem.currentStyle ) {\n\t\t\tret = ropacity.test(elem.currentStyle.filter || \"\") ?\n\t\t\t\t(parseFloat(RegExp.$1) / 100) + \"\" :\n\t\t\t\t\"\";\n\n\t\t\treturn ret === \"\" ?\n\t\t\t\t\"1\" :\n\t\t\t\tret;\n\t\t}\n\n\t\t// Make sure we're using the right name for getting the float value\n\t\tif ( rfloat.test( name ) ) {\n\t\t\tname = styleFloat;\n\t\t}\n\n\t\tif ( !force && style && style[ name ] ) {\n\t\t\tret = style[ name ];\n\n\t\t} else if ( getComputedStyle ) {\n\n\t\t\t// Only \"float\" is needed here\n\t\t\tif ( rfloat.test( name ) ) {\n\t\t\t\tname = \"float\";\n\t\t\t}\n\n\t\t\tname = name.replace( rupper, \"-$1\" ).toLowerCase();\n\n\t\t\tvar defaultView = elem.ownerDocument.defaultView;\n\n\t\t\tif ( !defaultView ) {\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\tvar computedStyle = defaultView.getComputedStyle( elem, null );\n\n\t\t\tif ( computedStyle ) {\n\t\t\t\tret = computedStyle.getPropertyValue( name );\n\t\t\t}\n\n\t\t\t// We should always get a number back from opacity\n\t\t\tif ( name === \"opacity\" && ret === \"\" ) {\n\t\t\t\tret = \"1\";\n\t\t\t}\n\n\t\t} else if ( elem.currentStyle ) {\n\t\t\tvar camelCase = name.replace(rdashAlpha, fcamelCase);\n\n\t\t\tret = elem.currentStyle[ name ] || elem.currentStyle[ camelCase ];\n\n\t\t\t// From the awesome hack by Dean Edwards\n\t\t\t// http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291\n\n\t\t\t// If we're not dealing with a regular pixel number\n\t\t\t// but a number that has a weird ending, we need to convert it to pixels\n\t\t\tif ( !rnumpx.test( ret ) && rnum.test( ret ) ) {\n\t\t\t\t// Remember the original values\n\t\t\t\tvar left = style.left, rsLeft = elem.runtimeStyle.left;\n\n\t\t\t\t// Put in the new values to get a computed value out\n\t\t\t\telem.runtimeStyle.left = elem.currentStyle.left;\n\t\t\t\tstyle.left = camelCase === \"fontSize\" ? \"1em\" : (ret || 0);\n\t\t\t\tret = style.pixelLeft + \"px\";\n\n\t\t\t\t// Revert the changed values\n\t\t\t\tstyle.left = left;\n\t\t\t\telem.runtimeStyle.left = rsLeft;\n\t\t\t}\n\t\t}\n\n\t\treturn ret;\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 ( var name in options ) {\n\t\t\telem.style[ name ] = old[ name ];\n\t\t}\n\t}\n});\n\nif ( jQuery.expr && jQuery.expr.filters ) {\n\tjQuery.expr.filters.hidden = function( elem ) {\n\t\tvar width = elem.offsetWidth, height = elem.offsetHeight,\n\t\t\tskip = elem.nodeName.toLowerCase() === \"tr\";\n\n\t\treturn width === 0 && height === 0 && !skip ?\n\t\t\ttrue :\n\t\t\twidth > 0 && height > 0 && !skip ?\n\t\t\t\tfalse :\n\t\t\t\tjQuery.curCSS(elem, \"display\") === \"none\";\n\t};\n\n\tjQuery.expr.filters.visible = function( elem ) {\n\t\treturn !jQuery.expr.filters.hidden( elem );\n\t};\n}\nvar jsc = now(),\n\trscript = /<script(.|\\s)*?\\/script>/gi,\n\trselectTextarea = /select|textarea/i,\n\trinput = /color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week/i,\n\tjsre = /=\\?(&|$)/,\n\trquery = /\\?/,\n\trts = /(\\?|&)_=.*?(&|$)/,\n\trurl = /^(\\w+:)?\\/\\/([^\\/?#]+)/,\n\tr20 = /%20/g,\n\n\t// Keep a copy of the old load method\n\t_load = jQuery.fn.load;\n\njQuery.fn.extend({\n\tload: function( url, params, callback ) {\n\t\tif ( typeof url !== \"string\" ) {\n\t\t\treturn _load.call( this, url );\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 = null;\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\tcomplete: function( res, status ) {\n\t\t\t\t// If successful, inject the HTML into all the matched elements\n\t\t\t\tif ( status === \"success\" || status === \"notmodified\" ) {\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(res.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\tres.responseText );\n\t\t\t\t}\n\n\t\t\t\tif ( callback ) {\n\t\t\t\t\tself.each( callback, [res.responseText, status, res] );\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\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 };\n\t\t\t\t\t}) :\n\t\t\t\t\t{ name: elem.name, value: val };\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.extend({\n\n\tget: 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 = null;\n\t\t}\n\n\t\treturn jQuery.ajax({\n\t\t\ttype: \"GET\",\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\tgetScript: function( url, callback ) {\n\t\treturn jQuery.get(url, null, callback, \"script\");\n\t},\n\n\tgetJSON: function( url, data, callback ) {\n\t\treturn jQuery.get(url, data, callback, \"json\");\n\t},\n\n\tpost: 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 = {};\n\t\t}\n\n\t\treturn jQuery.ajax({\n\t\t\ttype: \"POST\",\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\tajaxSetup: function( settings ) {\n\t\tjQuery.extend( jQuery.ajaxSettings, settings );\n\t},\n\n\tajaxSettings: {\n\t\turl: location.href,\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\tusername: null,\n\t\tpassword: null,\n\t\ttraditional: false,\n\t\t*/\n\t\t// Create the request object; Microsoft failed to properly\n\t\t// implement the XMLHttpRequest in IE7 (can't request local files),\n\t\t// so we use the ActiveXObject when it is available\n\t\t// This function can be overridden by calling jQuery.ajaxSetup\n\t\txhr: window.XMLHttpRequest && (window.location.protocol !== \"file:\" || !window.ActiveXObject) ?\n\t\t\tfunction() {\n\t\t\t\treturn new window.XMLHttpRequest();\n\t\t\t} :\n\t\t\tfunction() {\n\t\t\t\ttry {\n\t\t\t\t\treturn new window.ActiveXObject(\"Microsoft.XMLHTTP\");\n\t\t\t\t} catch(e) {}\n\t\t\t},\n\t\taccepts: {\n\t\t\txml: \"application/xml, text/xml\",\n\t\t\thtml: \"text/html\",\n\t\t\tscript: \"text/javascript, application/javascript\",\n\t\t\tjson: \"application/json, text/javascript\",\n\t\t\ttext: \"text/plain\",\n\t\t\t_default: \"*/*\"\n\t\t}\n\t},\n\n\t// Last-Modified header cache for next request\n\tlastModified: {},\n\tetag: {},\n\n\tajax: function( origSettings ) {\n\t\tvar s = jQuery.extend(true, {}, jQuery.ajaxSettings, origSettings);\n\t\t\n\t\tvar jsonp, status, data,\n\t\t\tcallbackContext = origSettings && origSettings.context || s,\n\t\t\ttype = s.type.toUpperCase();\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// Handle JSONP Parameter Callbacks\n\t\tif ( s.dataType === \"jsonp\" ) {\n\t\t\tif ( type === \"GET\" ) {\n\t\t\t\tif ( !jsre.test( s.url ) ) {\n\t\t\t\t\ts.url += (rquery.test( s.url ) ? \"&\" : \"?\") + (s.jsonp || \"callback\") + \"=?\";\n\t\t\t\t}\n\t\t\t} else if ( !s.data || !jsre.test(s.data) ) {\n\t\t\t\ts.data = (s.data ? s.data + \"&\" : \"\") + (s.jsonp || \"callback\") + \"=?\";\n\t\t\t}\n\t\t\ts.dataType = \"json\";\n\t\t}\n\n\t\t// Build temporary JSONP function\n\t\tif ( s.dataType === \"json\" && (s.data && jsre.test(s.data) || jsre.test(s.url)) ) {\n\t\t\tjsonp = s.jsonpCallback || (\"jsonp\" + jsc++);\n\n\t\t\t// Replace the =? sequence both in the query string and the data\n\t\t\tif ( s.data ) {\n\t\t\t\ts.data = (s.data + \"\").replace(jsre, \"=\" + jsonp + \"$1\");\n\t\t\t}\n\n\t\t\ts.url = s.url.replace(jsre, \"=\" + jsonp + \"$1\");\n\n\t\t\t// We need to make sure\n\t\t\t// that a JSONP style response is executed properly\n\t\t\ts.dataType = \"script\";\n\n\t\t\t// Handle JSONP-style loading\n\t\t\twindow[ jsonp ] = window[ jsonp ] || function( tmp ) {\n\t\t\t\tdata = tmp;\n\t\t\t\tsuccess();\n\t\t\t\tcomplete();\n\t\t\t\t// Garbage collect\n\t\t\t\twindow[ jsonp ] = undefined;\n\n\t\t\t\ttry {\n\t\t\t\t\tdelete window[ jsonp ];\n\t\t\t\t} catch(e) {}\n\n\t\t\t\tif ( head ) {\n\t\t\t\t\thead.removeChild( script );\n\t\t\t\t}\n\t\t\t};\n\t\t}\n\n\t\tif ( s.dataType === \"script\" && s.cache === null ) {\n\t\t\ts.cache = false;\n\t\t}\n\n\t\tif ( s.cache === false && type === \"GET\" ) {\n\t\t\tvar ts = now();\n\n\t\t\t// try replacing _= if it is there\n\t\t\tvar ret = s.url.replace(rts, \"$1_=\" + ts + \"$2\");\n\n\t\t\t// if nothing was replaced, add timestamp to the end\n\t\t\ts.url = ret + ((ret === s.url) ? (rquery.test(s.url) ? \"&\" : \"?\") + \"_=\" + ts : \"\");\n\t\t}\n\n\t\t// If data is available, append data to url for get requests\n\t\tif ( s.data && type === \"GET\" ) {\n\t\t\ts.url += (rquery.test(s.url) ? \"&\" : \"?\") + s.data;\n\t\t}\n\n\t\t// Watch for a new set of requests\n\t\tif ( s.global && ! jQuery.active++ ) {\n\t\t\tjQuery.event.trigger( \"ajaxStart\" );\n\t\t}\n\n\t\t// Matches an absolute URL, and saves the domain\n\t\tvar parts = rurl.exec( s.url ),\n\t\t\tremote = parts && (parts[1] && parts[1] !== location.protocol || parts[2] !== location.host);\n\n\t\t// If we're requesting a remote document\n\t\t// and trying to load JSON or Script with a GET\n\t\tif ( s.dataType === \"script\" && type === \"GET\" && remote ) {\n\t\t\tvar head = document.head || document.getElementsByTagName( \"head\" )[0] || document.documentElement;\n\t\t\tvar script = document.createElement(\"script\");\n\t\t\tscript.src = s.url;\n\t\t\tif ( s.scriptCharset ) {\n\t\t\t\tscript.charset = s.scriptCharset;\n\t\t\t}\n\n\t\t\t// Handle Script loading\n\t\t\tif ( !jsonp ) {\n\t\t\t\tvar done = false;\n\n\t\t\t\t// Attach handlers for all browsers\n\t\t\t\tscript.onload = script.onreadystatechange = function() {\n\t\t\t\t\tif ( !done && (!this.readyState ||\n\t\t\t\t\t\t\tthis.readyState === \"loaded\" || this.readyState === \"complete\") ) {\n\t\t\t\t\t\tdone = true;\n\t\t\t\t\t\tsuccess();\n\t\t\t\t\t\tcomplete();\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\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\t\t\t\t\t}\n\t\t\t\t};\n\t\t\t}\n\n\t\t\t// Use insertBefore instead of appendChild  to circumvent an IE6 bug.\n\t\t\t// This arises when a base node is used (#2709 and #4378).\n\t\t\thead.insertBefore( script, head.firstChild );\n\n\t\t\t// We handle everything using the script element injection\n\t\t\treturn undefined;\n\t\t}\n\n\t\tvar requestDone = false;\n\n\t\t// Create the request object\n\t\tvar xhr = s.xhr();\n\n\t\tif ( !xhr ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Open the socket\n\t\t// Passing null username, generates a login popup on Opera (#2865)\n\t\tif ( s.username ) {\n\t\t\txhr.open(type, s.url, s.async, s.username, s.password);\n\t\t} else {\n\t\t\txhr.open(type, s.url, s.async);\n\t\t}\n\n\t\t// Need an extra try/catch for cross domain requests in Firefox 3\n\t\ttry {\n\t\t\t// Set the correct header, if data is being sent\n\t\t\tif ( s.data || origSettings && origSettings.contentType ) {\n\t\t\t\txhr.setRequestHeader(\"Content-Type\", s.contentType);\n\t\t\t}\n\n\t\t\t// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.\n\t\t\tif ( s.ifModified ) {\n\t\t\t\tif ( jQuery.lastModified[s.url] ) {\n\t\t\t\t\txhr.setRequestHeader(\"If-Modified-Since\", jQuery.lastModified[s.url]);\n\t\t\t\t}\n\n\t\t\t\tif ( jQuery.etag[s.url] ) {\n\t\t\t\t\txhr.setRequestHeader(\"If-None-Match\", jQuery.etag[s.url]);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Set header so the called script knows that it's an XMLHttpRequest\n\t\t\t// Only send the header if it's not a remote XHR\n\t\t\tif ( !remote ) {\n\t\t\t\txhr.setRequestHeader(\"X-Requested-With\", \"XMLHttpRequest\");\n\t\t\t}\n\n\t\t\t// Set the Accepts header for the server, depending on the dataType\n\t\t\txhr.setRequestHeader(\"Accept\", s.dataType && s.accepts[ s.dataType ] ?\n\t\t\t\ts.accepts[ s.dataType ] + \", */*\" :\n\t\t\t\ts.accepts._default );\n\t\t} catch(e) {}\n\n\t\t// Allow custom headers/mimetypes and early abort\n\t\tif ( s.beforeSend && s.beforeSend.call(callbackContext, xhr, s) === false ) {\n\t\t\t// Handle the global AJAX counter\n\t\t\tif ( s.global && ! --jQuery.active ) {\n\t\t\t\tjQuery.event.trigger( \"ajaxStop\" );\n\t\t\t}\n\n\t\t\t// close opened socket\n\t\t\txhr.abort();\n\t\t\treturn false;\n\t\t}\n\n\t\tif ( s.global ) {\n\t\t\ttrigger(\"ajaxSend\", [xhr, s]);\n\t\t}\n\n\t\t// Wait for a response to come back\n\t\tvar onreadystatechange = xhr.onreadystatechange = function( isTimeout ) {\n\t\t\t// The request was aborted\n\t\t\tif ( !xhr || xhr.readyState === 0 || isTimeout === \"abort\" ) {\n\t\t\t\t// Opera doesn't call onreadystatechange before this point\n\t\t\t\t// so we simulate the call\n\t\t\t\tif ( !requestDone ) {\n\t\t\t\t\tcomplete();\n\t\t\t\t}\n\n\t\t\t\trequestDone = true;\n\t\t\t\tif ( xhr ) {\n\t\t\t\t\txhr.onreadystatechange = jQuery.noop;\n\t\t\t\t}\n\n\t\t\t// The transfer is complete and the data is available, or the request timed out\n\t\t\t} else if ( !requestDone && xhr && (xhr.readyState === 4 || isTimeout === \"timeout\") ) {\n\t\t\t\trequestDone = true;\n\t\t\t\txhr.onreadystatechange = jQuery.noop;\n\n\t\t\t\tstatus = isTimeout === \"timeout\" ?\n\t\t\t\t\t\"timeout\" :\n\t\t\t\t\t!jQuery.httpSuccess( xhr ) ?\n\t\t\t\t\t\t\"error\" :\n\t\t\t\t\t\ts.ifModified && jQuery.httpNotModified( xhr, s.url ) ?\n\t\t\t\t\t\t\t\"notmodified\" :\n\t\t\t\t\t\t\t\"success\";\n\n\t\t\t\tvar errMsg;\n\n\t\t\t\tif ( status === \"success\" ) {\n\t\t\t\t\t// Watch for, and catch, XML document parse errors\n\t\t\t\t\ttry {\n\t\t\t\t\t\t// process the data (runs the xml through httpData regardless of callback)\n\t\t\t\t\t\tdata = jQuery.httpData( xhr, s.dataType, s );\n\t\t\t\t\t} catch(err) {\n\t\t\t\t\t\tstatus = \"parsererror\";\n\t\t\t\t\t\terrMsg = err;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Make sure that the request was successful or notmodified\n\t\t\t\tif ( status === \"success\" || status === \"notmodified\" ) {\n\t\t\t\t\t// JSONP handles its own success callback\n\t\t\t\t\tif ( !jsonp ) {\n\t\t\t\t\t\tsuccess();\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tjQuery.handleError(s, xhr, status, errMsg);\n\t\t\t\t}\n\n\t\t\t\t// Fire the complete handlers\n\t\t\t\tcomplete();\n\n\t\t\t\tif ( isTimeout === \"timeout\" ) {\n\t\t\t\t\txhr.abort();\n\t\t\t\t}\n\n\t\t\t\t// Stop memory leaks\n\t\t\t\tif ( s.async ) {\n\t\t\t\t\txhr = null;\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\n\t\t// Override the abort handler, if we can (IE doesn't allow it, but that's OK)\n\t\t// Opera doesn't fire onreadystatechange at all on abort\n\t\ttry {\n\t\t\tvar oldAbort = xhr.abort;\n\t\t\txhr.abort = function() {\n\t\t\t\tif ( xhr ) {\n\t\t\t\t\toldAbort.call( xhr );\n\t\t\t\t}\n\n\t\t\t\tonreadystatechange( \"abort\" );\n\t\t\t};\n\t\t} catch(e) { }\n\n\t\t// Timeout checker\n\t\tif ( s.async && s.timeout > 0 ) {\n\t\t\tsetTimeout(function() {\n\t\t\t\t// Check to see if the request is still happening\n\t\t\t\tif ( xhr && !requestDone ) {\n\t\t\t\t\tonreadystatechange( \"timeout\" );\n\t\t\t\t}\n\t\t\t}, s.timeout);\n\t\t}\n\n\t\t// Send the data\n\t\ttry {\n\t\t\txhr.send( type === \"POST\" || type === \"PUT\" || type === \"DELETE\" ? s.data : null );\n\t\t} catch(e) {\n\t\t\tjQuery.handleError(s, xhr, null, e);\n\t\t\t// Fire the complete handlers\n\t\t\tcomplete();\n\t\t}\n\n\t\t// Firefox 1.5 doesn't fire statechange for sync requests\n\t\tif ( !s.async ) {\n\t\t\tonreadystatechange();\n\t\t}\n\n\t\tfunction success() {\n\t\t\t// If a local callback was specified, fire it and pass it the data\n\t\t\tif ( s.success ) {\n\t\t\t\ts.success.call( callbackContext, data, status, xhr );\n\t\t\t}\n\n\t\t\t// Fire the global callback\n\t\t\tif ( s.global ) {\n\t\t\t\ttrigger( \"ajaxSuccess\", [xhr, s] );\n\t\t\t}\n\t\t}\n\n\t\tfunction complete() {\n\t\t\t// Process result\n\t\t\tif ( s.complete ) {\n\t\t\t\ts.complete.call( callbackContext, xhr, status);\n\t\t\t}\n\n\t\t\t// The request was completed\n\t\t\tif ( s.global ) {\n\t\t\t\ttrigger( \"ajaxComplete\", [xhr, s] );\n\t\t\t}\n\n\t\t\t// Handle the global AJAX counter\n\t\t\tif ( s.global && ! --jQuery.active ) {\n\t\t\t\tjQuery.event.trigger( \"ajaxStop\" );\n\t\t\t}\n\t\t}\n\t\t\n\t\tfunction trigger(type, args) {\n\t\t\t(s.context ? jQuery(s.context) : jQuery.event).trigger(type, args);\n\t\t}\n\n\t\t// return XMLHttpRequest to allow aborting the request etc.\n\t\treturn xhr;\n\t},\n\n\thandleError: function( s, xhr, status, e ) {\n\t\t// If a local callback was specified, fire it\n\t\tif ( s.error ) {\n\t\t\ts.error.call( s.context || s, xhr, status, e );\n\t\t}\n\n\t\t// Fire the global callback\n\t\tif ( s.global ) {\n\t\t\t(s.context ? jQuery(s.context) : jQuery.event).trigger( \"ajaxError\", [xhr, s, e] );\n\t\t}\n\t},\n\n\t// Counter for holding the number of active queries\n\tactive: 0,\n\n\t// Determines if an XMLHttpRequest was successful or not\n\thttpSuccess: function( xhr ) {\n\t\ttry {\n\t\t\t// IE error sometimes returns 1223 when it should be 204 so treat it as success, see #1450\n\t\t\treturn !xhr.status && location.protocol === \"file:\" ||\n\t\t\t\t// Opera returns 0 when status is 304\n\t\t\t\t( xhr.status >= 200 && xhr.status < 300 ) ||\n\t\t\t\txhr.status === 304 || xhr.status === 1223 || xhr.status === 0;\n\t\t} catch(e) {}\n\n\t\treturn false;\n\t},\n\n\t// Determines if an XMLHttpRequest returns NotModified\n\thttpNotModified: function( xhr, url ) {\n\t\tvar lastModified = xhr.getResponseHeader(\"Last-Modified\"),\n\t\t\tetag = xhr.getResponseHeader(\"Etag\");\n\n\t\tif ( lastModified ) {\n\t\t\tjQuery.lastModified[url] = lastModified;\n\t\t}\n\n\t\tif ( etag ) {\n\t\t\tjQuery.etag[url] = etag;\n\t\t}\n\n\t\t// Opera returns 0 when status is 304\n\t\treturn xhr.status === 304 || xhr.status === 0;\n\t},\n\n\thttpData: function( xhr, type, s ) {\n\t\tvar ct = xhr.getResponseHeader(\"content-type\") || \"\",\n\t\t\txml = type === \"xml\" || !type && ct.indexOf(\"xml\") >= 0,\n\t\t\tdata = xml ? xhr.responseXML : xhr.responseText;\n\n\t\tif ( xml && data.documentElement.nodeName === \"parsererror\" ) {\n\t\t\tjQuery.error( \"parsererror\" );\n\t\t}\n\n\t\t// Allow a pre-filtering function to sanitize the response\n\t\t// s is checked to keep backwards compatibility\n\t\tif ( s && s.dataFilter ) {\n\t\t\tdata = s.dataFilter( data, type );\n\t\t}\n\n\t\t// The filter can actually parse the response\n\t\tif ( typeof data === \"string\" ) {\n\t\t\t// Get the JavaScript object, if JSON is used.\n\t\t\tif ( type === \"json\" || !type && ct.indexOf(\"json\") >= 0 ) {\n\t\t\t\tdata = jQuery.parseJSON( data );\n\n\t\t\t// If the type is \"script\", eval it in global context\n\t\t\t} else if ( type === \"script\" || !type && ct.indexOf(\"javascript\") >= 0 ) {\n\t\t\t\tjQuery.globalEval( data );\n\t\t\t}\n\t\t}\n\n\t\treturn data;\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\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\t\t\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 ) {\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\t\t\t\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] );\n\t\t\t}\n\t\t}\n\n\t\t// Return the resulting serialization\n\t\treturn s.join(\"&\").replace(r20, \"+\");\n\n\t\tfunction buildParams( prefix, obj ) {\n\t\t\tif ( jQuery.isArray(obj) ) {\n\t\t\t\t// Serialize array item.\n\t\t\t\tjQuery.each( obj, function( i, v ) {\n\t\t\t\t\tif ( traditional || /\\[\\]$/.test( prefix ) ) {\n\t\t\t\t\t\t// Treat each array item as a scalar.\n\t\t\t\t\t\tadd( prefix, v );\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// If array item is non-scalar (array or object), encode its\n\t\t\t\t\t\t// numeric index to resolve deserialization ambiguity issues.\n\t\t\t\t\t\t// Note that rack (as of 1.0.0) can't currently deserialize\n\t\t\t\t\t\t// nested arrays properly, and attempting to do so may cause\n\t\t\t\t\t\t// a server error. Possible fixes are to modify rack's\n\t\t\t\t\t\t// deserialization algorithm or to provide an option or flag\n\t\t\t\t\t\t// to force array serialization to be shallow.\n\t\t\t\t\t\tbuildParams( prefix + \"[\" + ( typeof v === \"object\" || jQuery.isArray(v) ? i : \"\" ) + \"]\", v );\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\t\t\n\t\t\t} else if ( !traditional && obj != null && typeof obj === \"object\" ) {\n\t\t\t\t// Serialize object item.\n\t\t\t\tjQuery.each( obj, function( k, v ) {\n\t\t\t\t\tbuildParams( prefix + \"[\" + k + \"]\", v );\n\t\t\t\t});\n\t\t\t\t\t\n\t\t\t} else {\n\t\t\t\t// Serialize scalar item.\n\t\t\t\tadd( prefix, obj );\n\t\t\t}\n\t\t}\n\n\t\tfunction add( 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;\n\t\t\ts[ s.length ] = encodeURIComponent(key) + \"=\" + encodeURIComponent(value);\n\t\t}\n\t}\n});\nvar elemdisplay = {},\n\trfxtypes = /toggle|show|hide/,\n\trfxnum = /^([+-]=)?([\\d+-.]+)(.*)$/,\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\njQuery.fn.extend({\n\tshow: function( speed, callback ) {\n\t\tif ( speed || speed === 0) {\n\t\t\treturn this.animate( genFx(\"show\", 3), speed, callback);\n\n\t\t} else {\n\t\t\tfor ( var i = 0, l = this.length; i < l; i++ ) {\n\t\t\t\tvar old = jQuery.data(this[i], \"olddisplay\");\n\n\t\t\t\tthis[i].style.display = old || \"\";\n\n\t\t\t\tif ( jQuery.css(this[i], \"display\") === \"none\" ) {\n\t\t\t\t\tvar nodeName = this[i].nodeName, display;\n\n\t\t\t\t\tif ( elemdisplay[ nodeName ] ) {\n\t\t\t\t\t\tdisplay = elemdisplay[ nodeName ];\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\tvar elem = jQuery(\"<\" + nodeName + \" />\").appendTo(\"body\");\n\n\t\t\t\t\t\tdisplay = elem.css(\"display\");\n\n\t\t\t\t\t\tif ( display === \"none\" ) {\n\t\t\t\t\t\t\tdisplay = \"block\";\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\telem.remove();\n\n\t\t\t\t\t\telemdisplay[ nodeName ] = display;\n\t\t\t\t\t}\n\n\t\t\t\t\tjQuery.data(this[i], \"olddisplay\", display);\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 ( var j = 0, k = this.length; j < k; j++ ) {\n\t\t\t\tthis[j].style.display = jQuery.data(this[j], \"olddisplay\") || \"\";\n\t\t\t}\n\n\t\t\treturn this;\n\t\t}\n\t},\n\n\thide: function( speed, callback ) {\n\t\tif ( speed || speed === 0 ) {\n\t\t\treturn this.animate( genFx(\"hide\", 3), speed, callback);\n\n\t\t} else {\n\t\t\tfor ( var i = 0, l = this.length; i < l; i++ ) {\n\t\t\t\tvar old = jQuery.data(this[i], \"olddisplay\");\n\t\t\t\tif ( !old && old !== \"none\" ) {\n\t\t\t\t\tjQuery.data(this[i], \"olddisplay\", jQuery.css(this[i], \"display\"));\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 ( var j = 0, k = this.length; j < k; j++ ) {\n\t\t\t\tthis[j].style.display = \"none\";\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 ) {\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);\n\t\t}\n\n\t\treturn this;\n\t},\n\n\tfadeTo: function( speed, to, callback ) {\n\t\treturn this.filter(\":hidden\").css(\"opacity\", 0).show().end()\n\t\t\t\t\t.animate({opacity: to}, speed, 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 );\n\t\t}\n\n\t\treturn this[ optall.queue === false ? \"each\" : \"queue\" ](function() {\n\t\t\tvar opt = jQuery.extend({}, optall), p,\n\t\t\t\thidden = this.nodeType === 1 && jQuery(this).is(\":hidden\"),\n\t\t\t\tself = this;\n\n\t\t\tfor ( p in prop ) {\n\t\t\t\tvar name = p.replace(rdashAlpha, fcamelCase);\n\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\tp = name;\n\t\t\t\t}\n\n\t\t\t\tif ( prop[p] === \"hide\" && hidden || prop[p] === \"show\" && !hidden ) {\n\t\t\t\t\treturn opt.complete.call(this);\n\t\t\t\t}\n\n\t\t\t\tif ( ( p === \"height\" || p === \"width\" ) && this.style ) {\n\t\t\t\t\t// Store display property\n\t\t\t\t\topt.display = jQuery.css(this, \"display\");\n\n\t\t\t\t\t// Make sure that nothing sneaks out\n\t\t\t\t\topt.overflow = this.style.overflow;\n\t\t\t\t}\n\n\t\t\t\tif ( jQuery.isArray( prop[p] ) ) {\n\t\t\t\t\t// Create (if needed) and add to specialEasing\n\t\t\t\t\t(opt.specialEasing = opt.specialEasing || {})[p] = prop[p][1];\n\t\t\t\t\tprop[p] = prop[p][0];\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\topt.curAnim = jQuery.extend({}, prop);\n\n\t\t\tjQuery.each( prop, function( name, val ) {\n\t\t\t\tvar e = new jQuery.fx( self, opt, name );\n\n\t\t\t\tif ( rfxtypes.test(val) ) {\n\t\t\t\t\te[ val === \"toggle\" ? hidden ? \"show\" : \"hide\" : val ]( prop );\n\n\t\t\t\t} else {\n\t\t\t\t\tvar parts = rfxnum.exec(val),\n\t\t\t\t\t\tstart = e.cur(true) || 0;\n\n\t\t\t\t\tif ( parts ) {\n\t\t\t\t\t\tvar end = parseFloat( parts[2] ),\n\t\t\t\t\t\t\tunit = parts[3] || \"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\tself.style[ name ] = (end || 1) + unit;\n\t\t\t\t\t\t\tstart = ((end || 1) / e.cur(true)) * start;\n\t\t\t\t\t\t\tself.style[ name ] = 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\tvar timers = jQuery.timers;\n\n\t\tif ( clearQueue ) {\n\t\t\tthis.queue([]);\n\t\t}\n\n\t\tthis.each(function() {\n\t\t\t// go in reverse order so anything added to the queue during the loop is ignored\n\t\t\tfor ( var i = timers.length - 1; i >= 0; 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// 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}, function( name, props ) {\n\tjQuery.fn[ name ] = function( speed, callback ) {\n\t\treturn this.animate( props, speed, callback );\n\t};\n});\n\njQuery.extend({\n\tspeed: function( speed, easing, fn ) {\n\t\tvar opt = speed && typeof speed === \"object\" ? 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\tjQuery.fx.speeds[opt.duration] || jQuery.fx.speeds._default;\n\n\t\t// Queueing\n\t\topt.old = opt.complete;\n\t\topt.complete = function() {\n\t\t\tif ( opt.queue !== false ) {\n\t\t\t\tjQuery(this).dequeue();\n\t\t\t}\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\tif ( !options.orig ) {\n\t\t\toptions.orig = {};\n\t\t}\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\n\t\t// Set display property to block for height/width animations\n\t\tif ( ( this.prop === \"height\" || this.prop === \"width\" ) && this.elem.style ) {\n\t\t\tthis.elem.style.display = \"block\";\n\t\t}\n\t},\n\n\t// Get the current size\n\tcur: function( force ) {\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 r = parseFloat(jQuery.css(this.elem, this.prop, force));\n\t\treturn r && r > -10000 ? r : parseFloat(jQuery.curCSS(this.elem, this.prop)) || 0;\n\t},\n\n\t// Start an animation from one number to another\n\tcustom: function( from, to, unit ) {\n\t\tthis.startTime = now();\n\t\tthis.start = from;\n\t\tthis.end = to;\n\t\tthis.unit = unit || this.unit || \"px\";\n\t\tthis.now = this.start;\n\t\tthis.pos = this.state = 0;\n\n\t\tvar self = this;\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\ttimerId = setInterval(jQuery.fx.tick, 13);\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 = now(), done = true;\n\n\t\tif ( gotoEnd || t >= this.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\tthis.options.curAnim[ this.prop ] = true;\n\n\t\t\tfor ( var i in this.options.curAnim ) {\n\t\t\t\tif ( this.options.curAnim[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\tif ( this.options.display != null ) {\n\t\t\t\t\t// Reset the overflow\n\t\t\t\t\tthis.elem.style.overflow = this.options.overflow;\n\n\t\t\t\t\t// Reset the display\n\t\t\t\t\tvar old = jQuery.data(this.elem, \"olddisplay\");\n\t\t\t\t\tthis.elem.style.display = old ? old : this.options.display;\n\n\t\t\t\t\tif ( jQuery.css(this.elem, \"display\") === \"none\" ) {\n\t\t\t\t\t\tthis.elem.style.display = \"block\";\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 ( this.options.hide ) {\n\t\t\t\t\tjQuery(this.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 ( this.options.hide || this.options.show ) {\n\t\t\t\t\tfor ( var p in this.options.curAnim ) {\n\t\t\t\t\t\tjQuery.style(this.elem, p, this.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\tthis.options.complete.call( this.elem );\n\t\t\t}\n\n\t\t\treturn false;\n\n\t\t} else {\n\t\t\tvar n = t - this.startTime;\n\t\t\tthis.state = n / this.options.duration;\n\n\t\t\t// Perform the easing function, defaults to swing\n\t\t\tvar specialEasing = this.options.specialEasing && this.options.specialEasing[this.prop];\n\t\t\tvar defaultEasing = this.options.easing || (jQuery.easing.swing ? \"swing\" : \"linear\");\n\t\t\tthis.pos = jQuery.easing[specialEasing || defaultEasing](this.state, n, 0, 1, this.options.duration);\n\t\t\tthis.now = this.start + ((this.end - this.start) * this.pos);\n\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 timers = jQuery.timers;\n\n\t\tfor ( var 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\t\t\n\tstop: function() {\n\t\tclearInterval( timerId );\n\t\ttimerId = null;\n\t},\n\t\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\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}\nif ( \"getBoundingClientRect\" in document.documentElement ) {\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 box = elem.getBoundingClientRect(), doc = elem.ownerDocument, body = doc.body, docElem = doc.documentElement,\n\t\t\tclientTop = docElem.clientTop || body.clientTop || 0, clientLeft = docElem.clientLeft || body.clientLeft || 0,\n\t\t\ttop  = box.top  + (self.pageYOffset || jQuery.support.boxModel && docElem.scrollTop  || body.scrollTop ) - clientTop,\n\t\t\tleft = box.left + (self.pageXOffset || jQuery.support.boxModel && docElem.scrollLeft || body.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 offsetParent = elem.offsetParent, prevOffsetParent = elem,\n\t\t\tdoc = elem.ownerDocument, computedStyle, docElem = doc.documentElement,\n\t\t\tbody = doc.body, defaultView = doc.defaultView,\n\t\t\tprevComputedStyle = defaultView ? defaultView.getComputedStyle( elem, null ) : elem.currentStyle,\n\t\t\ttop = elem.offsetTop, left = 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 && /^t(able|d|h)$/i.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, offsetParent = 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.curCSS(body, \"marginTop\", true) ) || 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\", checkDiv.style.top = \"20px\";\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\", innerDiv.style.position = \"relative\";\n\t\tthis.subtractsBorderForOverflowNotVisible = (checkDiv.offsetTop === -5);\n\n\t\tthis.doesNotIncludeMarginInBodyOffset = (body.offsetTop !== bodyMarginTop);\n\n\t\tbody.removeChild( container );\n\t\tbody = container = innerDiv = checkDiv = table = td = null;\n\t\tjQuery.offset.initialize = jQuery.noop;\n\t},\n\n\tbodyOffset: function( body ) {\n\t\tvar top = body.offsetTop, left = body.offsetLeft;\n\n\t\tjQuery.offset.initialize();\n\n\t\tif ( jQuery.offset.doesNotIncludeMarginInBodyOffset ) {\n\t\t\ttop  += parseFloat( jQuery.curCSS(body, \"marginTop\",  true) ) || 0;\n\t\t\tleft += parseFloat( jQuery.curCSS(body, \"marginLeft\", true) ) || 0;\n\t\t}\n\n\t\treturn { top: top, left: left };\n\t},\n\t\n\tsetOffset: function( elem, options, i ) {\n\t\t// set position first, in-case top/left are set even on static elem\n\t\tif ( /static/.test( jQuery.curCSS( elem, \"position\" ) ) ) {\n\t\t\telem.style.position = \"relative\";\n\t\t}\n\t\tvar curElem   = jQuery( elem ),\n\t\t\tcurOffset = curElem.offset(),\n\t\t\tcurTop    = parseInt( jQuery.curCSS( elem, \"top\",  true ), 10 ) || 0,\n\t\t\tcurLeft   = parseInt( jQuery.curCSS( elem, \"left\", true ), 10 ) || 0;\n\n\t\tif ( jQuery.isFunction( options ) ) {\n\t\t\toptions = options.call( elem, i, curOffset );\n\t\t}\n\n\t\tvar props = {\n\t\t\ttop:  (options.top  - curOffset.top)  + curTop,\n\t\t\tleft: (options.left - curOffset.left) + curLeft\n\t\t};\n\t\t\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 = /^body|html$/i.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.curCSS(elem, \"marginTop\",  true) ) || 0;\n\t\toffset.left -= parseFloat( jQuery.curCSS(elem, \"marginLeft\", true) ) || 0;\n\n\t\t// Add offsetParent borders\n\t\tparentOffset.top  += parseFloat( jQuery.curCSS(offsetParent[0], \"borderTopWidth\",  true) ) || 0;\n\t\tparentOffset.left += parseFloat( jQuery.curCSS(offsetParent[0], \"borderLeftWidth\", true) ) || 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 && (!/^body|html$/i.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 = this[0], win;\n\t\t\n\t\tif ( !elem ) {\n\t\t\treturn null;\n\t\t}\n\n\t\tif ( val !== undefined ) {\n\t\t\t// Set the scroll offset\n\t\t\treturn this.each(function() {\n\t\t\t\twin = getWindow( this );\n\n\t\t\t\tif ( win ) {\n\t\t\t\t\twin.scrollTo(\n\t\t\t\t\t\t!i ? val : jQuery(win).scrollLeft(),\n\t\t\t\t\t\t i ? val : jQuery(win).scrollTop()\n\t\t\t\t\t);\n\n\t\t\t\t} else {\n\t\t\t\t\tthis[ method ] = val;\n\t\t\t\t}\n\t\t\t});\n\t\t} else {\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\t};\n});\n\nfunction getWindow( elem ) {\n\treturn (\"scrollTo\" in elem && elem.document) ?\n\t\telem :\n\t\telem.nodeType === 9 ?\n\t\t\telem.defaultView || elem.parentWindow :\n\t\t\tfalse;\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\tjQuery.css( this[0], type, false, \"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\tjQuery.css( this[0], type, false, 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\t\t\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\treturn (\"scrollTo\" in elem && elem.document) ? // does it walk and quack like a window?\n\t\t\t// Everyone else use document.documentElement or document.body depending on Quirks vs Standards mode\n\t\t\telem.document.compatMode === \"CSS1Compat\" && elem.document.documentElement[ \"client\" + name ] ||\n\t\t\telem.document.body[ \"client\" + name ] :\n\n\t\t\t// Get document width or height\n\t\t\t(elem.nodeType === 9) ? // is it a document\n\t\t\t\t// Either scroll[Width/Height] or offset[Width/Height], whichever is greater\n\t\t\t\tMath.max(\n\t\t\t\t\telem.documentElement[\"client\" + name],\n\t\t\t\t\telem.body[\"scroll\" + name], elem.documentElement[\"scroll\" + name],\n\t\t\t\t\telem.body[\"offset\" + name], elem.documentElement[\"offset\" + name]\n\t\t\t\t) :\n\n\t\t\t\t// Get or set width or height on the element\n\t\t\t\tsize === undefined ?\n\t\t\t\t\t// Get width or height on the element\n\t\t\t\t\tjQuery.css( elem, type ) :\n\n\t\t\t\t\t// Set the width or height on the element (default to pixels if value is unitless)\n\t\t\t\t\tthis.css( type, typeof size === \"string\" ? size : size + \"px\" );\n\t};\n\n});\n// Expose jQuery to the global object\nwindow.jQuery = window.$ = jQuery;\n\n})(window);\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/jquery/speed/slice.vs.concat.html",
    "content": "<script type=\"text/javascript\">\n(function(){\n\t// Conclusions:\n\t// slice() is a little faster than concat() except on Chrome\n\t// This clone() is slower on FF & IE but takes 50% on Safari & Chrome\n\n\tvar SIZE = 1e4,\n\t\tLOOPS = 500;\n\n\tvar arr = new Array(SIZE);\n\tfor ( var i = arr.length - 1; i >= 0; --i )\n\t\tarr[i] = 0;\n\n\tvar t = new Date;\n\tfor ( i = 0; i < LOOPS; i++ )\n\t\tarr.slice(0);\n\tvar tslice = new Date - t;\n\n\tt = new Date;\n\tfor ( i = 0; i < LOOPS; i++ )\n\t\tarr.concat();\n\tvar tconcat = new Date - t;\n\n\t// clone() is just to see how fast built-ins are\n\tt = new Date;\n\tfor ( i = 0; i < LOOPS; i++ )\n\t\tclone(arr);\n\tvar tclone = new Date - t;\n\n\talert([\n\t\t'slice:'+tslice,\n\t\t'concat:'+tconcat,\n\t\t'clone:'+tclone\n\t].join('\\n'));\n\n\n\tfunction clone(arr){\n\t\tvar i = arr.length,\n\t\t\tcopy = new Array(i);\n\n\t\twhile (i--)\n\t\t\tcopy[i] = arr[i];\n\n\t\treturn copy;\n\t}\n})();\n</script>\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/jquery/src/.jshintrc",
    "content": "{\n\t\"boss\": true,\n\t\"curly\": true,\n\t\"eqeqeq\": true,\n\t\"eqnull\": true,\n\t\"expr\": true,\n\t\"immed\": true,\n\t\"noarg\": true,\n\t\"onevar\": true,\n\t\"quotmark\": \"double\",\n\t\"smarttabs\": true,\n\t\"trailing\": true,\n\t\"undef\": true,\n\t\"unused\": true,\n\n\t\"sub\": true,\n\n\t\"browser\": true,\n\t\"es5\": true,\n\n\t\"globals\": {\n\t\t\"jQuery\": true,\n\t\t\"define\": true,\n\t\t\"module\": true\n\t}\n}\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/jquery/src/ajax/jsonp.js",
    "content": "var 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});\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/jquery/src/ajax/script.js",
    "content": "// Install script dataType\njQuery.ajaxSetup({\n\taccepts: {\n\t\tscript: \"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript\"\n\t},\n\tcontents: {\n\t\tscript: /(?:java|ecma)script/\n\t},\n\tconverters: {\n\t\t\"text script\": function( text ) {\n\t\t\tjQuery.globalEval( text );\n\t\t\treturn text;\n\t\t}\n\t}\n});\n\n// Handle cache's special case and crossDomain\njQuery.ajaxPrefilter( \"script\", function( s ) {\n\tif ( s.cache === undefined ) {\n\t\ts.cache = false;\n\t}\n\tif ( s.crossDomain ) {\n\t\ts.type = \"GET\";\n\t}\n});\n\n// Bind script tag hack transport\njQuery.ajaxTransport( \"script\", function( s ) {\n\t// This transport only deals with cross domain requests\n\tif ( s.crossDomain ) {\n\t\tvar script, callback;\n\t\treturn {\n\t\t\tsend: function( _, complete ) {\n\t\t\t\tscript = jQuery(\"<script>\").prop({\n\t\t\t\t\tasync: true,\n\t\t\t\t\tcharset: s.scriptCharset,\n\t\t\t\t\tsrc: s.url\n\t\t\t\t}).on(\n\t\t\t\t\t\"load error\",\n\t\t\t\t\tcallback = function( evt ) {\n\t\t\t\t\t\tscript.remove();\n\t\t\t\t\t\tcallback = null;\n\t\t\t\t\t\tif ( evt ) {\n\t\t\t\t\t\t\tcomplete( evt.type === \"error\" ? 404 : 200, evt.type );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t);\n\t\t\t\tdocument.head.appendChild( script[ 0 ] );\n\t\t\t},\n\t\t\tabort: function() {\n\t\t\t\tif ( callback ) {\n\t\t\t\t\tcallback();\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t}\n});\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/jquery/src/ajax/xhr.js",
    "content": "jQuery.ajaxSettings.xhr = function() {\n\ttry {\n\t\treturn new XMLHttpRequest();\n\t} catch( e ) {}\n};\n\nvar xhrSupported = jQuery.ajaxSettings.xhr(),\n\txhrSuccessStatus = {\n\t\t// file protocol always yields status code 0, assume 200\n\t\t0: 200,\n\t\t// Support: IE9\n\t\t// #1450: sometimes IE returns 1223 when it should be 204\n\t\t1223: 204\n\t},\n\t// Support: IE9\n\t// We need to keep track of outbound xhr and abort them manually\n\t// because IE is not smart enough to do it all by itself\n\txhrId = 0,\n\txhrCallbacks = {};\n\nif ( window.ActiveXObject ) {\n\tjQuery( window ).on( \"unload\", function() {\n\t\tfor( var key in xhrCallbacks ) {\n\t\t\txhrCallbacks[ key ]();\n\t\t}\n\t\txhrCallbacks = undefined;\n\t});\n}\n\njQuery.support.cors = !!xhrSupported && ( \"withCredentials\" in xhrSupported );\njQuery.support.ajax = xhrSupported = !!xhrSupported;\n\njQuery.ajaxTransport(function( options ) {\n\tvar callback;\n\t// Cross domain only allowed if supported through XMLHttpRequest\n\tif ( jQuery.support.cors || xhrSupported && !options.crossDomain ) {\n\t\treturn {\n\t\t\tsend: function( headers, complete ) {\n\t\t\t\tvar i, id,\n\t\t\t\t\txhr = options.xhr();\n\t\t\t\txhr.open( options.type, options.url, options.async, options.username, options.password );\n\t\t\t\t// Apply custom fields if provided\n\t\t\t\tif ( options.xhrFields ) {\n\t\t\t\t\tfor ( i in options.xhrFields ) {\n\t\t\t\t\t\txhr[ i ] = options.xhrFields[ i ];\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// Override mime type if needed\n\t\t\t\tif ( options.mimeType && xhr.overrideMimeType ) {\n\t\t\t\t\txhr.overrideMimeType( options.mimeType );\n\t\t\t\t}\n\t\t\t\t// X-Requested-With header\n\t\t\t\t// For cross-domain requests, seeing as conditions for a preflight are\n\t\t\t\t// akin to a jigsaw puzzle, we simply never set it to be sure.\n\t\t\t\t// (it can always be set on a per-request basis or even using ajaxSetup)\n\t\t\t\t// For same-domain requests, won't change header if already provided.\n\t\t\t\tif ( !options.crossDomain && !headers[\"X-Requested-With\"] ) {\n\t\t\t\t\theaders[\"X-Requested-With\"] = \"XMLHttpRequest\";\n\t\t\t\t}\n\t\t\t\t// Set headers\n\t\t\t\tfor ( i in headers ) {\n\t\t\t\t\txhr.setRequestHeader( i, headers[ i ] );\n\t\t\t\t}\n\t\t\t\t// Callback\n\t\t\t\tcallback = function( type ) {\n\t\t\t\t\treturn function() {\n\t\t\t\t\t\tif ( callback ) {\n\t\t\t\t\t\t\tdelete xhrCallbacks[ id ];\n\t\t\t\t\t\t\tcallback = xhr.onload = xhr.onerror = null;\n\t\t\t\t\t\t\tif ( type === \"abort\" ) {\n\t\t\t\t\t\t\t\txhr.abort();\n\t\t\t\t\t\t\t} else if ( type === \"error\" ) {\n\t\t\t\t\t\t\t\tcomplete(\n\t\t\t\t\t\t\t\t\t// file protocol always yields status 0, assume 404\n\t\t\t\t\t\t\t\t\txhr.status || 404,\n\t\t\t\t\t\t\t\t\txhr.statusText\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tcomplete(\n\t\t\t\t\t\t\t\t\txhrSuccessStatus[ xhr.status ] || xhr.status,\n\t\t\t\t\t\t\t\t\txhr.statusText,\n\t\t\t\t\t\t\t\t\t// Support: IE9\n\t\t\t\t\t\t\t\t\t// #11426: When requesting binary data, IE9 will throw an exception\n\t\t\t\t\t\t\t\t\t// on any attempt to access responseText\n\t\t\t\t\t\t\t\t\ttypeof xhr.responseText === \"string\" ? {\n\t\t\t\t\t\t\t\t\t\ttext: xhr.responseText\n\t\t\t\t\t\t\t\t\t} : undefined,\n\t\t\t\t\t\t\t\t\txhr.getAllResponseHeaders()\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t};\n\t\t\t\t};\n\t\t\t\t// Listen to events\n\t\t\t\txhr.onload = callback();\n\t\t\t\txhr.onerror = callback(\"error\");\n\t\t\t\t// Create the abort callback\n\t\t\t\tcallback = xhrCallbacks[( id = xhrId++ )] = callback(\"abort\");\n\t\t\t\t// Do send the request\n\t\t\t\t// This may raise an exception which is actually\n\t\t\t\t// handled in jQuery.ajax (so no try/catch here)\n\t\t\t\txhr.send( options.hasContent && options.data || null );\n\t\t\t},\n\t\t\tabort: function() {\n\t\t\t\tif ( callback ) {\n\t\t\t\t\tcallback();\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t}\n});\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/jquery/src/ajax.js",
    "content": "var\n\t// Document location\n\tajaxLocParts,\n\tajaxLocation,\n\n\tajax_nonce = jQuery.now(),\n\n\tajax_rquery = /\\?/,\n\trhash = /#.*$/,\n\trts = /([?&])_=[^&]*/,\n\trheaders = /^(.*?):[ \\t]*([^\\r\\n]*)$/mg,\n\t// #7653, #8125, #8152: local protocol detection\n\trlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/,\n\trnoContent = /^(?:GET|HEAD)$/,\n\trprotocol = /^\\/\\//,\n\trurl = /^([\\w.+-]+:)(?:\\/\\/([^\\/?#:]*)(?::(\\d+)|)|)/,\n\n\t// 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 key, deep,\n\t\tflatOptions = jQuery.ajaxSettings.flatOptions || {};\n\n\tfor ( key in src ) {\n\t\tif ( src[ key ] !== undefined ) {\n\t\t\t( flatOptions[ key ] ? target : ( deep || (deep = {}) ) )[ key ] = src[ key ];\n\t\t}\n\t}\n\tif ( deep ) {\n\t\tjQuery.extend( true, target, deep );\n\t}\n\n\treturn target;\n}\n\njQuery.fn.load = function( url, params, callback ) {\n\tif ( typeof url !== \"string\" && _load ) {\n\t\treturn _load.apply( this, arguments );\n\t}\n\n\tvar selector, type, response,\n\t\tself = this,\n\t\toff = url.indexOf(\" \");\n\n\tif ( off >= 0 ) {\n\t\tselector = url.slice( off );\n\t\turl = url.slice( 0, off );\n\t}\n\n\t// If it's a function\n\tif ( jQuery.isFunction( params ) ) {\n\n\t\t// We assume that it's the callback\n\t\tcallback = params;\n\t\tparams = undefined;\n\n\t// Otherwise, build a param string\n\t} else if ( params && typeof params === \"object\" ) {\n\t\ttype = \"POST\";\n\t}\n\n\t// If we have elements to modify, make the request\n\tif ( self.length > 0 ) {\n\t\tjQuery.ajax({\n\t\t\turl: url,\n\n\t\t\t// if \"type\" variable is undefined, then \"GET\" method will be used\n\t\t\ttype: type,\n\t\t\tdataType: \"html\",\n\t\t\tdata: params\n\t\t}).done(function( responseText ) {\n\n\t\t\t// Save response for use in complete callback\n\t\t\tresponse = arguments;\n\n\t\t\tself.html( selector ?\n\n\t\t\t\t// If a selector was specified, locate the right elements in a dummy div\n\t\t\t\t// Exclude scripts to avoid IE 'Permission Denied' errors\n\t\t\t\tjQuery(\"<div>\").append( jQuery.parseHTML( responseText ) ).find( selector ) :\n\n\t\t\t\t// Otherwise use the full result\n\t\t\t\tresponseText );\n\n\t\t}).complete( callback && function( jqXHR, status ) {\n\t\t\tself.each( callback, response || [ jqXHR.responseText, status, jqXHR ] );\n\t\t});\n\t}\n\n\treturn this;\n};\n\n// 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 transport,\n\t\t\t// URL without anti-cache param\n\t\t\tcacheURL,\n\t\t\t// Response headers\n\t\t\tresponseHeadersString,\n\t\t\tresponseHeaders,\n\t\t\t// timeout handle\n\t\t\ttimeoutTimer,\n\t\t\t// Cross-domain detection vars\n\t\t\tparts,\n\t\t\t// To know if global events are to be dispatched\n\t\t\tfireGlobals,\n\t\t\t// Loop variable\n\t\t\ti,\n\t\t\t// Create the final options object\n\t\t\ts = jQuery.ajaxSetup( {}, options ),\n\t\t\t// Callbacks context\n\t\t\tcallbackContext = s.context || s,\n\t\t\t// Context for global events is callbackContext if it is a DOM node or jQuery collection\n\t\t\tglobalEventContext = s.context && ( callbackContext.nodeType || callbackContext.jquery ) ?\n\t\t\t\tjQuery( callbackContext ) :\n\t\t\t\tjQuery.event,\n\t\t\t// Deferreds\n\t\t\tdeferred = jQuery.Deferred(),\n\t\t\tcompleteDeferred = jQuery.Callbacks(\"once memory\"),\n\t\t\t// Status-dependent callbacks\n\t\t\tstatusCode = s.statusCode || {},\n\t\t\t// Headers (they are sent all at once)\n\t\t\trequestHeaders = {},\n\t\t\trequestHeadersNames = {},\n\t\t\t// The jqXHR state\n\t\t\tstate = 0,\n\t\t\t// Default abort message\n\t\t\tstrAbort = \"canceled\",\n\t\t\t// Fake xhr\n\t\t\tjqXHR = {\n\t\t\t\treadyState: 0,\n\n\t\t\t\t// Builds headers hashtable if needed\n\t\t\t\tgetResponseHeader: function( key ) {\n\t\t\t\t\tvar match;\n\t\t\t\t\tif ( state === 2 ) {\n\t\t\t\t\t\tif ( !responseHeaders ) {\n\t\t\t\t\t\t\tresponseHeaders = {};\n\t\t\t\t\t\t\twhile ( (match = rheaders.exec( responseHeadersString )) ) {\n\t\t\t\t\t\t\t\tresponseHeaders[ match[1].toLowerCase() ] = match[ 2 ];\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tmatch = responseHeaders[ key.toLowerCase() ];\n\t\t\t\t\t}\n\t\t\t\t\treturn match == null ? null : match;\n\t\t\t\t},\n\n\t\t\t\t// Raw string\n\t\t\t\tgetAllResponseHeaders: function() {\n\t\t\t\t\treturn state === 2 ? responseHeadersString : null;\n\t\t\t\t},\n\n\t\t\t\t// Caches the header\n\t\t\t\tsetRequestHeader: function( name, value ) {\n\t\t\t\t\tvar lname = name.toLowerCase();\n\t\t\t\t\tif ( !state ) {\n\t\t\t\t\t\tname = requestHeadersNames[ lname ] = requestHeadersNames[ lname ] || name;\n\t\t\t\t\t\trequestHeaders[ name ] = value;\n\t\t\t\t\t}\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\n\t\t\t\t// Overrides response content-type header\n\t\t\t\toverrideMimeType: function( type ) {\n\t\t\t\t\tif ( !state ) {\n\t\t\t\t\t\ts.mimeType = type;\n\t\t\t\t\t}\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\n\t\t\t\t// Status-dependent callbacks\n\t\t\t\tstatusCode: function( map ) {\n\t\t\t\t\tvar code;\n\t\t\t\t\tif ( map ) {\n\t\t\t\t\t\tif ( state < 2 ) {\n\t\t\t\t\t\t\tfor ( code in map ) {\n\t\t\t\t\t\t\t\t// Lazy-add the new callback in a way that preserves old ones\n\t\t\t\t\t\t\t\tstatusCode[ code ] = [ statusCode[ code ], map[ code ] ];\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t// Execute the appropriate callbacks\n\t\t\t\t\t\t\tjqXHR.always( map[ jqXHR.status ] );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\n\t\t\t\t// Cancel the request\n\t\t\t\tabort: function( statusText ) {\n\t\t\t\t\tvar finalText = statusText || strAbort;\n\t\t\t\t\tif ( transport ) {\n\t\t\t\t\t\ttransport.abort( finalText );\n\t\t\t\t\t}\n\t\t\t\t\tdone( 0, finalText );\n\t\t\t\t\treturn this;\n\t\t\t\t}\n\t\t\t};\n\n\t\t// Attach deferreds\n\t\tdeferred.promise( jqXHR ).complete = completeDeferred.add;\n\t\tjqXHR.success = jqXHR.done;\n\t\tjqXHR.error = jqXHR.fail;\n\n\t\t// Remove hash character (#7531: and string promotion)\n\t\t// Add protocol if not provided (prefilters might expect it)\n\t\t// Handle falsy url in the settings object (#10093: consistency with old signature)\n\t\t// We also use the url parameter if available\n\t\ts.url = ( ( url || s.url || ajaxLocation ) + \"\" ).replace( rhash, \"\" )\n\t\t\t.replace( rprotocol, ajaxLocParts[ 1 ] + \"//\" );\n\n\t\t// Alias method option to type as per ticket #12004\n\t\ts.type = options.method || options.type || s.method || s.type;\n\n\t\t// Extract dataTypes list\n\t\ts.dataTypes = jQuery.trim( s.dataType || \"*\" ).toLowerCase().match( 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\n\tvar ct, type, finalDataType, firstDataType,\n\t\tcontents = s.contents,\n\t\tdataTypes = s.dataTypes;\n\n\t// Remove auto dataType and get content-type in the process\n\twhile( dataTypes[ 0 ] === \"*\" ) {\n\t\tdataTypes.shift();\n\t\tif ( ct === undefined ) {\n\t\t\tct = s.mimeType || jqXHR.getResponseHeader(\"Content-Type\");\n\t\t}\n\t}\n\n\t// Check if we're dealing with a known content-type\n\tif ( ct ) {\n\t\tfor ( type in contents ) {\n\t\t\tif ( contents[ type ] && contents[ type ].test( ct ) ) {\n\t\t\t\tdataTypes.unshift( type );\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\t// Check to see if we have a response for the expected dataType\n\tif ( dataTypes[ 0 ] in responses ) {\n\t\tfinalDataType = dataTypes[ 0 ];\n\t} else {\n\t\t// Try convertible dataTypes\n\t\tfor ( type in responses ) {\n\t\t\tif ( !dataTypes[ 0 ] || s.converters[ type + \" \" + dataTypes[0] ] ) {\n\t\t\t\tfinalDataType = type;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif ( !firstDataType ) {\n\t\t\t\tfirstDataType = type;\n\t\t\t}\n\t\t}\n\t\t// Or just use first one\n\t\tfinalDataType = finalDataType || firstDataType;\n\t}\n\n\t// If we found a dataType\n\t// We add the dataType to the list if needed\n\t// and return the corresponding response\n\tif ( finalDataType ) {\n\t\tif ( finalDataType !== dataTypes[ 0 ] ) {\n\t\t\tdataTypes.unshift( finalDataType );\n\t\t}\n\t\treturn responses[ finalDataType ];\n\t}\n}\n\n/* Chain conversions given the request and the original response\n * Also sets the responseXXX fields on the jqXHR instance\n */\nfunction ajaxConvert( s, response, jqXHR, isSuccess ) {\n\tvar conv2, current, conv, tmp, prev,\n\t\tconverters = {},\n\t\t// Work with a copy of dataTypes in case we need to modify it for conversion\n\t\tdataTypes = s.dataTypes.slice();\n\n\t// Create converters map with lowercased keys\n\tif ( dataTypes[ 1 ] ) {\n\t\tfor ( conv in s.converters ) {\n\t\t\tconverters[ conv.toLowerCase() ] = s.converters[ conv ];\n\t\t}\n\t}\n\n\tcurrent = dataTypes.shift();\n\n\t// Convert to each sequential dataType\n\twhile ( current ) {\n\n\t\tif ( s.responseFields[ current ] ) {\n\t\t\tjqXHR[ s.responseFields[ current ] ] = response;\n\t\t}\n\n\t\t// Apply the dataFilter if provided\n\t\tif ( !prev && isSuccess && s.dataFilter ) {\n\t\t\tresponse = s.dataFilter( response, s.dataType );\n\t\t}\n\n\t\tprev = current;\n\t\tcurrent = dataTypes.shift();\n\n\t\tif ( current ) {\n\n\t\t// There's only work to do if current dataType is non-auto\n\t\t\tif ( current === \"*\" ) {\n\n\t\t\t\tcurrent = prev;\n\n\t\t\t// Convert response if prev dataType is non-auto and differs from current\n\t\t\t} else if ( prev !== \"*\" && prev !== current ) {\n\n\t\t\t\t// Seek a direct converter\n\t\t\t\tconv = converters[ prev + \" \" + current ] || converters[ \"* \" + current ];\n\n\t\t\t\t// If none found, seek a pair\n\t\t\t\tif ( !conv ) {\n\t\t\t\t\tfor ( conv2 in converters ) {\n\n\t\t\t\t\t\t// If conv2 outputs current\n\t\t\t\t\t\ttmp = conv2.split( \" \" );\n\t\t\t\t\t\tif ( tmp[ 1 ] === current ) {\n\n\t\t\t\t\t\t\t// If prev can be converted to accepted input\n\t\t\t\t\t\t\tconv = converters[ prev + \" \" + tmp[ 0 ] ] ||\n\t\t\t\t\t\t\t\tconverters[ \"* \" + tmp[ 0 ] ];\n\t\t\t\t\t\t\tif ( conv ) {\n\t\t\t\t\t\t\t\t// Condense equivalence converters\n\t\t\t\t\t\t\t\tif ( conv === true ) {\n\t\t\t\t\t\t\t\t\tconv = converters[ conv2 ];\n\n\t\t\t\t\t\t\t\t// Otherwise, insert the intermediate dataType\n\t\t\t\t\t\t\t\t} else if ( converters[ conv2 ] !== true ) {\n\t\t\t\t\t\t\t\t\tcurrent = tmp[ 0 ];\n\t\t\t\t\t\t\t\t\tdataTypes.unshift( tmp[ 1 ] );\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Apply converter (if not an equivalence)\n\t\t\t\tif ( conv !== true ) {\n\n\t\t\t\t\t// Unless errors are allowed to bubble, catch and return them\n\t\t\t\t\tif ( conv && s[ \"throws\" ] ) {\n\t\t\t\t\t\tresponse = conv( response );\n\t\t\t\t\t} else {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tresponse = conv( response );\n\t\t\t\t\t\t} catch ( e ) {\n\t\t\t\t\t\t\treturn { state: \"parsererror\", error: conv ? e : \"No conversion from \" + prev + \" to \" + current };\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn { state: \"success\", data: response };\n}\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/jquery/src/attributes.js",
    "content": "var nodeHook, boolHook,\n\trclass = /[\\t\\r\\n\\f]/g,\n\trreturn = /\\r/g,\n\trfocusable = /^(?:input|select|textarea|button)$/i;\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\treturn this.each(function() {\n\t\t\tdelete this[ jQuery.propFix[ name ] || name ];\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\tdata_priv.set( this, \"__className__\", this.className );\n\t\t\t\t}\n\n\t\t\t\t// If the element has a class name or if we're passed \"false\",\n\t\t\t\t// then remove the whole classname (if there was one, the above saved it).\n\t\t\t\t// Otherwise bring back whatever was previously saved (if anything),\n\t\t\t\t// falling back to the empty string if nothing was stored.\n\t\t\t\tthis.className = this.className || value === false ? \"\" : data_priv.get( this, \"__className__\" ) || \"\";\n\t\t\t}\n\t\t});\n\t},\n\n\thasClass: function( selector ) {\n\t\tvar className = \" \" + selector + \" \",\n\t\t\ti = 0,\n\t\t\tl = this.length;\n\t\tfor ( ; i < l; i++ ) {\n\t\t\tif ( this[i].nodeType === 1 && (\" \" + this[i].className + \" \").replace(rclass, \" \").indexOf( className ) >= 0 ) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\n\t\treturn false;\n\t},\n\n\tval: function( value ) {\n\t\tvar hooks, ret, isFunction,\n\t\t\telem = this[0];\n\n\t\tif ( !arguments.length ) {\n\t\t\tif ( elem ) {\n\t\t\t\thooks = jQuery.valHooks[ elem.type ] || jQuery.valHooks[ elem.nodeName.toLowerCase() ];\n\n\t\t\t\tif ( hooks && \"get\" in hooks && (ret = hooks.get( elem, \"value\" )) !== undefined ) {\n\t\t\t\t\treturn ret;\n\t\t\t\t}\n\n\t\t\t\tret = elem.value;\n\n\t\t\t\treturn typeof ret === \"string\" ?\n\t\t\t\t\t// handle most common string cases\n\t\t\t\t\tret.replace(rreturn, \"\") :\n\t\t\t\t\t// handle cases where value is null/undef or number\n\t\t\t\t\tret == null ? \"\" : ret;\n\t\t\t}\n\n\t\t\treturn;\n\t\t}\n\n\t\tisFunction = jQuery.isFunction( value );\n\n\t\treturn this.each(function( i ) {\n\t\t\tvar val;\n\n\t\t\tif ( this.nodeType !== 1 ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif ( isFunction ) {\n\t\t\t\tval = value.call( this, i, jQuery( this ).val() );\n\t\t\t} else {\n\t\t\t\tval = value;\n\t\t\t}\n\n\t\t\t// Treat null/undefined as \"\"; convert numbers to string\n\t\t\tif ( val == null ) {\n\t\t\t\tval = \"\";\n\t\t\t} else if ( typeof val === \"number\" ) {\n\t\t\t\tval += \"\";\n\t\t\t} else if ( jQuery.isArray( val ) ) {\n\t\t\t\tval = jQuery.map(val, function ( value ) {\n\t\t\t\t\treturn value == null ? \"\" : value + \"\";\n\t\t\t\t});\n\t\t\t}\n\n\t\t\thooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ];\n\n\t\t\t// If set returns undefined, fall back to normal setting\n\t\t\tif ( !hooks || !(\"set\" in hooks) || hooks.set( this, val, \"value\" ) === undefined ) {\n\t\t\t\tthis.value = val;\n\t\t\t}\n\t\t});\n\t}\n});\n\njQuery.extend({\n\tvalHooks: {\n\t\toption: {\n\t\t\tget: function( elem ) {\n\t\t\t\t// attributes.value is undefined in Blackberry 4.7 but\n\t\t\t\t// uses .value. See #6932\n\t\t\t\tvar val = elem.attributes.value;\n\t\t\t\treturn !val || val.specified ? elem.value : elem.text;\n\t\t\t}\n\t\t},\n\t\tselect: {\n\t\t\tget: function( elem ) {\n\t\t\t\tvar value, option,\n\t\t\t\t\toptions = elem.options,\n\t\t\t\t\tindex = elem.selectedIndex,\n\t\t\t\t\tone = elem.type === \"select-one\" || index < 0,\n\t\t\t\t\tvalues = one ? null : [],\n\t\t\t\t\tmax = one ? index + 1 : options.length,\n\t\t\t\t\ti = index < 0 ?\n\t\t\t\t\t\tmax :\n\t\t\t\t\t\tone ? index : 0;\n\n\t\t\t\t// Loop through all the selected options\n\t\t\t\tfor ( ; i < max; i++ ) {\n\t\t\t\t\toption = options[ i ];\n\n\t\t\t\t\t// IE6-9 doesn't update selected after form reset (#2551)\n\t\t\t\t\tif ( ( option.selected || i === index ) &&\n\t\t\t\t\t\t\t// Don't return options that are disabled or in a disabled optgroup\n\t\t\t\t\t\t\t( 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\telem[ propName ] = false;\n\t\t\t\t}\n\n\t\t\t\telem.removeAttribute( name );\n\t\t\t}\n\t\t}\n\t},\n\n\tattrHooks: {\n\t\ttype: {\n\t\t\tset: function( elem, value ) {\n\t\t\t\tif ( !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\treturn elem.hasAttribute( \"tabindex\" ) || rfocusable.test( elem.nodeName ) || elem.href ?\n\t\t\t\t\telem.tabIndex :\n\t\t\t\t\t-1;\n\t\t\t}\n\t\t}\n\t}\n});\n\n// Hooks for boolean attributes\nboolHook = {\n\tset: function( elem, value, name ) {\n\t\tif ( value === false ) {\n\t\t\t// Remove boolean attributes when set to false\n\t\t\tjQuery.removeAttr( elem, name );\n\t\t} else {\n\t\t\telem.setAttribute( name, name );\n\t\t}\n\t\treturn name;\n\t}\n};\njQuery.each( jQuery.expr.match.bool.source.match( /\\w+/g ), function( i, name ) {\n\tvar getter = jQuery.expr.attrHandle[ name ] || jQuery.find.attr;\n\n\tjQuery.expr.attrHandle[ name ] = function( elem, name, isXML ) {\n\t\tvar fn = jQuery.expr.attrHandle[ name ],\n\t\t\tret = isXML ?\n\t\t\t\tundefined :\n\t\t\t\t/* jshint eqeqeq: false */\n\t\t\t\t// Temporarily disable this handler to check existence\n\t\t\t\t(jQuery.expr.attrHandle[ name ] = undefined) !=\n\t\t\t\t\tgetter( elem, name, isXML ) ?\n\n\t\t\t\t\tname.toLowerCase() :\n\t\t\t\t\tnull;\n\n\t\t// Restore handler\n\t\tjQuery.expr.attrHandle[ name ] = fn;\n\n\t\treturn ret;\n\t};\n});\n\n// Support: IE9+\n// Selectedness for an option in an optgroup can be inaccurate\nif ( !jQuery.support.optSelected ) {\n\tjQuery.propHooks.selected = {\n\t\tget: function( elem ) {\n\t\t\tvar parent = elem.parentNode;\n\t\t\tif ( parent && parent.parentNode ) {\n\t\t\t\tparent.parentNode.selectedIndex;\n\t\t\t}\n\t\t\treturn null;\n\t\t}\n\t};\n}\n\njQuery.each([\n\t\"tabIndex\",\n\t\"readOnly\",\n\t\"maxLength\",\n\t\"cellSpacing\",\n\t\"cellPadding\",\n\t\"rowSpan\",\n\t\"colSpan\",\n\t\"useMap\",\n\t\"frameBorder\",\n\t\"contentEditable\"\n], function() {\n\tjQuery.propFix[ this.toLowerCase() ] = this;\n});\n\n// 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});\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/jquery/src/callbacks.js",
    "content": "// 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 // Last fire value (for non-forgettable lists)\n\t\tmemory,\n\t\t// Flag to know if list was already fired\n\t\tfired,\n\t\t// Flag to know if list is currently firing\n\t\tfiring,\n\t\t// First callback to fire (used internally by add and fireWith)\n\t\tfiringStart,\n\t\t// End of the loop when firing\n\t\tfiringLength,\n\t\t// Index of currently firing callback (modified by remove if needed)\n\t\tfiringIndex,\n\t\t// Actual callback list\n\t\tlist = [],\n\t\t// Stack of fire calls for repeatable lists\n\t\tstack = !options.once && [],\n\t\t// Fire callbacks\n\t\tfire = function( data ) {\n\t\t\tmemory = options.memory && data;\n\t\t\tfired = true;\n\t\t\tfiringIndex = firingStart || 0;\n\t\t\tfiringStart = 0;\n\t\t\tfiringLength = list.length;\n\t\t\tfiring = true;\n\t\t\tfor ( ; list && firingIndex < firingLength; firingIndex++ ) {\n\t\t\t\tif ( list[ firingIndex ].apply( data[ 0 ], data[ 1 ] ) === false && options.stopOnFalse ) {\n\t\t\t\t\tmemory = false; // To prevent further calls using add\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tfiring = false;\n\t\t\tif ( list ) {\n\t\t\t\tif ( stack ) {\n\t\t\t\t\tif ( stack.length ) {\n\t\t\t\t\t\tfire( stack.shift() );\n\t\t\t\t\t}\n\t\t\t\t} else if ( memory ) {\n\t\t\t\t\tlist = [];\n\t\t\t\t} else {\n\t\t\t\t\tself.disable();\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t// Actual Callbacks object\n\t\tself = {\n\t\t\t// Add a callback or a collection of callbacks to the list\n\t\t\tadd: function() {\n\t\t\t\tif ( list ) {\n\t\t\t\t\t// First, we save the current length\n\t\t\t\t\tvar start = list.length;\n\t\t\t\t\t(function add( args ) {\n\t\t\t\t\t\tjQuery.each( args, function( _, arg ) {\n\t\t\t\t\t\t\tvar type = jQuery.type( arg );\n\t\t\t\t\t\t\tif ( type === \"function\" ) {\n\t\t\t\t\t\t\t\tif ( !options.unique || !self.has( arg ) ) {\n\t\t\t\t\t\t\t\t\tlist.push( arg );\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} else if ( arg && arg.length && type !== \"string\" ) {\n\t\t\t\t\t\t\t\t// Inspect recursively\n\t\t\t\t\t\t\t\tadd( arg );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t});\n\t\t\t\t\t})( arguments );\n\t\t\t\t\t// Do we need to add the callbacks to the\n\t\t\t\t\t// current firing batch?\n\t\t\t\t\tif ( firing ) {\n\t\t\t\t\t\tfiringLength = list.length;\n\t\t\t\t\t// With memory, if we're not firing then\n\t\t\t\t\t// we should call right away\n\t\t\t\t\t} else if ( memory ) {\n\t\t\t\t\t\tfiringStart = start;\n\t\t\t\t\t\tfire( memory );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Remove a callback from the list\n\t\t\tremove: function() {\n\t\t\t\tif ( list ) {\n\t\t\t\t\tjQuery.each( arguments, function( _, arg ) {\n\t\t\t\t\t\tvar index;\n\t\t\t\t\t\twhile( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) {\n\t\t\t\t\t\t\tlist.splice( index, 1 );\n\t\t\t\t\t\t\t// Handle firing indexes\n\t\t\t\t\t\t\tif ( firing ) {\n\t\t\t\t\t\t\t\tif ( index <= firingLength ) {\n\t\t\t\t\t\t\t\t\tfiringLength--;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif ( index <= firingIndex ) {\n\t\t\t\t\t\t\t\t\tfiringIndex--;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Check if a given callback is in the list.\n\t\t\t// If no argument is given, return whether or not list has callbacks attached.\n\t\t\thas: function( fn ) {\n\t\t\t\treturn fn ? jQuery.inArray( fn, list ) > -1 : !!( list && list.length );\n\t\t\t},\n\t\t\t// Remove all callbacks from the list\n\t\t\tempty: function() {\n\t\t\t\tlist = [];\n\t\t\t\tfiringLength = 0;\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Have the list do nothing anymore\n\t\t\tdisable: function() {\n\t\t\t\tlist = stack = memory = undefined;\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Is it disabled?\n\t\t\tdisabled: function() {\n\t\t\t\treturn !list;\n\t\t\t},\n\t\t\t// Lock the list in its current state\n\t\t\tlock: function() {\n\t\t\t\tstack = undefined;\n\t\t\t\tif ( !memory ) {\n\t\t\t\t\tself.disable();\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Is it locked?\n\t\t\tlocked: function() {\n\t\t\t\treturn !stack;\n\t\t\t},\n\t\t\t// Call all callbacks with the given context and arguments\n\t\t\tfireWith: function( context, args ) {\n\t\t\t\tif ( list && ( !fired || stack ) ) {\n\t\t\t\t\targs = args || [];\n\t\t\t\t\targs = [ context, args.slice ? args.slice() : args ];\n\t\t\t\t\tif ( firing ) {\n\t\t\t\t\t\tstack.push( args );\n\t\t\t\t\t} else {\n\t\t\t\t\t\tfire( args );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Call all the callbacks with the given arguments\n\t\t\tfire: function() {\n\t\t\t\tself.fireWith( this, arguments );\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// To know if the callbacks have already been called at least once\n\t\t\tfired: function() {\n\t\t\t\treturn !!fired;\n\t\t\t}\n\t\t};\n\n\treturn self;\n};\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/jquery/src/core.js",
    "content": "var\n\t// A central reference to the root jQuery(document)\n\trootjQuery,\n\n\t// The deferred used on DOM ready\n\treadyList,\n\n\t// Support: IE9\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 = \"@VERSION\",\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// 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// 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 and self cleanup method\n\tcompleted = function() {\n\t\tdocument.removeEventListener( \"DOMContentLoaded\", completed, false );\n\t\twindow.removeEventListener( \"load\", completed, false );\n\t\tjQuery.ready();\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// 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 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\t// Unique for each copy of jQuery on the page\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// 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,\n\n\tisWindow: function( obj ) {\n\t\treturn obj != null && obj === obj.window;\n\t},\n\n\tisNumeric: function( obj ) {\n\t\treturn !isNaN( parseFloat(obj) ) && isFinite( obj );\n\t},\n\n\ttype: function( obj ) {\n\t\tif ( obj == null ) {\n\t\t\treturn String( obj );\n\t\t}\n\t\t// Support: Safari <= 5.1 (functionish RegExp)\n\t\treturn typeof obj === \"object\" || typeof obj === \"function\" ?\n\t\t\tclass2type[ core_toString.call(obj) ] || \"object\" :\n\t\t\ttypeof obj;\n\t},\n\n\tisPlainObject: function( obj ) {\n\t\t// Not plain objects:\n\t\t// - Any object or value whose internal [[Class]] property is not \"[object Object]\"\n\t\t// - DOM nodes\n\t\t// - window\n\t\tif ( jQuery.type( obj ) !== \"object\" || obj.nodeType || jQuery.isWindow( obj ) ) {\n\t\t\treturn false;\n\t\t}\n\n\t\t// Support: Firefox <20\n\t\t// The try/catch suppresses exceptions thrown when attempting to access\n\t\t// the \"constructor\" property of certain host objects, ie. |window.location|\n\t\t// https://bugzilla.mozilla.org/show_bug.cgi?id=814622\n\t\ttry {\n\t\t\tif ( obj.constructor &&\n\t\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\treturn false;\n\t\t}\n\n\t\t// If the function hasn't returned already, we're confident that\n\t\t// |obj| is a plain object, created by {} or constructed with new Object\n\t\treturn true;\n\t},\n\n\tisEmptyObject: function( obj ) {\n\t\tvar name;\n\t\tfor ( name in obj ) {\n\t\t\treturn false;\n\t\t}\n\t\treturn true;\n\t},\n\n\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\n\t\tif ( scripts ) {\n\t\t\tjQuery( scripts ).remove();\n\t\t}\n\n\t\treturn jQuery.merge( [], parsed.childNodes );\n\t},\n\n\tparseJSON: JSON.parse,\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\n\t\t// Support: IE9\n\t\ttry {\n\t\t\ttmp = new DOMParser();\n\t\t\txml = tmp.parseFromString( data , \"text/xml\" );\n\t\t} catch ( e ) {\n\t\t\txml = undefined;\n\t\t}\n\n\t\tif ( !xml || xml.getElementsByTagName( \"parsererror\" ).length ) {\n\t\t\tjQuery.error( \"Invalid XML: \" + data );\n\t\t}\n\t\treturn xml;\n\t},\n\n\tnoop: function() {},\n\n\t// Evaluates a script in a global context\n\tglobalEval: function( code ) {\n\t\tvar script,\n\t\t\t\tindirect = eval;\n\n\t\tcode = jQuery.trim( code );\n\n\t\tif ( code ) {\n\t\t\t// If the code includes a valid, prologue position\n\t\t\t// strict mode pragma, execute code by injecting a\n\t\t\t// script tag into the document.\n\t\t\tif ( code.indexOf(\"use strict\") === 1 ) {\n\t\t\t\tscript = document.createElement(\"script\");\n\t\t\t\tscript.text = code;\n\t\t\t\tdocument.head.appendChild( script ).parentNode.removeChild( script );\n\t\t\t} else {\n\t\t\t// Otherwise, avoid the DOM node creation, insertion\n\t\t\t// and removal by using an indirect global eval\n\t\t\t\tindirect( code );\n\t\t\t}\n\t\t}\n\t},\n\n\t// Convert dashed to camelCase; used by the css and data modules\n\t// 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\ttrim: function( text ) {\n\t\treturn text == null ? \"\" : core_trim.call( text );\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\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\treturn arr == null ? -1 : core_indexOf.call( arr, elem, i );\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 tmp, args, proxy;\n\n\t\tif ( typeof context === \"string\" ) {\n\t\t\ttmp = fn[ context ];\n\t\t\tcontext = fn;\n\t\t\tfn = tmp;\n\t\t}\n\n\t\t// Quick check to determine if target is callable, in the spec\n\t\t// this throws a TypeError, but we will just return undefined.\n\t\tif ( !jQuery.isFunction( fn ) ) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\t// Simulated bind\n\t\targs = 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: Date.now,\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} else {\n\n\t\t\t// Use the handy event callback\n\t\t\tdocument.addEventListener( \"DOMContentLoaded\", completed, false );\n\n\t\t\t// A fallback to window.onload, that will always work\n\t\t\twindow.addEventListener( \"load\", completed, false );\n\t\t}\n\t}\n\treturn readyList.promise( obj );\n};\n\n// 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"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/jquery/src/css.js",
    "content": "var curCSS, iframe,\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\n// NOTE: we've included the \"window\" in window.getComputedStyle\n// because jsdom on node.js will break without it.\nfunction getStyles( elem ) {\n\treturn window.getComputedStyle( elem, null );\n}\n\nfunction showHide( elements, show ) {\n\tvar display, elem, hidden,\n\t\tvalues = [],\n\t\tindex = 0,\n\t\tlength = elements.length;\n\n\tfor ( ; index < length; index++ ) {\n\t\telem = elements[ index ];\n\t\tif ( !elem.style ) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tvalues[ index ] = data_priv.get( elem, \"olddisplay\" );\n\t\tdisplay = elem.style.display;\n\t\tif ( show ) {\n\t\t\t// Reset the inline display of this element to learn if it is\n\t\t\t// being hidden by cascaded rules or not\n\t\t\tif ( !values[ index ] && display === \"none\" ) {\n\t\t\t\telem.style.display = \"\";\n\t\t\t}\n\n\t\t\t// Set elements which have been overridden with display: none\n\t\t\t// in a stylesheet to whatever the default browser style is\n\t\t\t// for such an element\n\t\t\tif ( elem.style.display === \"\" && isHidden( elem ) ) {\n\t\t\t\tvalues[ index ] = data_priv.access( elem, \"olddisplay\", 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\tdata_priv.set( 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 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\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\": \"cssFloat\"\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 specifying 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\t\t\t\tstyle[ name ] = value;\n\t\t\t}\n\n\t\t} else {\n\t\t\t// If a hook was provided get the non-computed value from there\n\t\t\tif ( hooks && \"get\" in hooks && (ret = hooks.get( elem, false, extra )) !== undefined ) {\n\t\t\t\treturn ret;\n\t\t\t}\n\n\t\t\t// Otherwise just get the value from the style object\n\t\t\treturn style[ name ];\n\t\t}\n\t},\n\n\tcss: function( elem, name, extra, styles ) {\n\t\tvar val, num, hooks,\n\t\t\torigName = jQuery.camelCase( name );\n\n\t\t// Make sure that we're working with the right name\n\t\tname = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( elem.style, origName ) );\n\n\t\t// 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\ncurCSS = function( elem, name, _computed ) {\n\tvar width, minWidth, maxWidth,\n\t\tcomputed = _computed || getStyles( elem ),\n\n\t\t// Support: IE9\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\t\tstyle = elem.style;\n\n\tif ( computed ) {\n\n\t\tif ( ret === \"\" && !jQuery.contains( elem.ownerDocument, elem ) ) {\n\t\t\tret = jQuery.style( elem, name );\n\t\t}\n\n\t\t// Support: Safari 5.1\n\t\t// A tribute to the \"awesome hack by Dean Edwards\"\n\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// this is against the CSSOM draft spec: http://dev.w3.org/csswg/cssom/#resolved-values\n\t\tif ( rnumnonpx.test( ret ) && rmargin.test( name ) ) {\n\n\t\t\t// Remember the original values\n\t\t\twidth = style.width;\n\t\t\tminWidth = style.minWidth;\n\t\t\tmaxWidth = style.maxWidth;\n\n\t\t\t// Put in the new values to get a computed value out\n\t\t\tstyle.minWidth = style.maxWidth = style.width = ret;\n\t\t\tret = computed.width;\n\n\t\t\t// Revert the changed values\n\t\t\tstyle.width = width;\n\t\t\tstyle.minWidth = minWidth;\n\t\t\tstyle.maxWidth = maxWidth;\n\t\t}\n\t}\n\n\treturn ret;\n};\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\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\t// Support: Android 2.3\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// Support: Android 2.3\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};\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});\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/jquery/src/data.js",
    "content": "/*\n\tImplementation Summary\n\n\t1. Enforce API surface and semantic compatibility with 1.9.x branch\n\t2. Improve the module's maintainability by reducing the storage\n\t\tpaths to a single mechanism.\n\t3. Use the same single mechanism to support \"private\" and \"user\" data.\n\t4. _Never_ expose \"private\" data to user code (TODO: Drop _data, _removeData)\n\t5. Avoid exposing implementation details on user objects (eg. expando properties)\n\t6. Provide a clear path for implementation upgrade to WeakMap in 2014\n*/\nvar data_user, data_priv,\n\trbrace = /(?:\\{[\\s\\S]*\\}|\\[[\\s\\S]*\\])$/,\n\trmultiDash = /([A-Z])/g;\n\nfunction Data() {\n\t// Support: Android < 4,\n\t// Old WebKit does not have Object.preventExtensions/freeze method,\n\t// return new empty object instead with no [[set]] accessor\n\tObject.defineProperty( this.cache = {}, 0, {\n\t\tget: function() {\n\t\t\treturn {};\n\t\t}\n\t});\n\n\tthis.expando = jQuery.expando + Math.random();\n}\n\nData.uid = 1;\n\nData.accepts = function( owner ) {\n\t// Accepts only:\n\t//  - Node\n\t//    - Node.ELEMENT_NODE\n\t//    - Node.DOCUMENT_NODE\n\t//  - Object\n\t//    - Any\n\treturn owner.nodeType ?\n\t\towner.nodeType === 1 || owner.nodeType === 9 : true;\n};\n\nData.prototype = {\n\tkey: function( owner ) {\n\t\t// We can accept data for non-element nodes in modern browsers,\n\t\t// but we should not, see #8335.\n\t\t// Always return the key for a frozen object.\n\t\tif ( !Data.accepts( owner ) ) {\n\t\t\treturn 0;\n\t\t}\n\n\t\tvar descriptor = {},\n\t\t\t// Check if the owner object already has a cache key\n\t\t\tunlock = owner[ this.expando ];\n\n\t\t// If not, create one\n\t\tif ( !unlock ) {\n\t\t\tunlock = Data.uid++;\n\n\t\t\t// Secure it in a non-enumerable, non-writable property\n\t\t\ttry {\n\t\t\t\tdescriptor[ this.expando ] = { value: unlock };\n\t\t\t\tObject.defineProperties( owner, descriptor );\n\n\t\t\t// Support: Android < 4\n\t\t\t// Fallback to a less secure definition\n\t\t\t} catch ( e ) {\n\t\t\t\tdescriptor[ this.expando ] = unlock;\n\t\t\t\tjQuery.extend( owner, descriptor );\n\t\t\t}\n\t\t}\n\n\t\t// Ensure the cache object\n\t\tif ( !this.cache[ unlock ] ) {\n\t\t\tthis.cache[ unlock ] = {};\n\t\t}\n\n\t\treturn unlock;\n\t},\n\tset: function( owner, data, value ) {\n\t\tvar prop,\n\t\t\t// There may be an unlock assigned to this node,\n\t\t\t// if there is no entry for this \"owner\", create one inline\n\t\t\t// and set the unlock as though an owner entry had always existed\n\t\t\tunlock = this.key( owner ),\n\t\t\tcache = this.cache[ unlock ];\n\n\t\t// Handle: [ owner, key, value ] args\n\t\tif ( typeof data === \"string\" ) {\n\t\t\tcache[ data ] = value;\n\n\t\t// Handle: [ owner, { properties } ] args\n\t\t} else {\n\t\t\t// Fresh assignments by object are shallow copied\n\t\t\tif ( jQuery.isEmptyObject( cache ) ) {\n\t\t\t\tjQuery.extend( this.cache[ unlock ], data );\n\t\t\t// Otherwise, copy the properties one-by-one to the cache object\n\t\t\t} else {\n\t\t\t\tfor ( prop in data ) {\n\t\t\t\t\tcache[ prop ] = data[ prop ];\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn cache;\n\t},\n\tget: function( owner, key ) {\n\t\t// Either a valid cache is found, or will be created.\n\t\t// New caches will be created and the unlock returned,\n\t\t// allowing direct access to the newly created\n\t\t// empty data object. A valid owner object must be provided.\n\t\tvar cache = this.cache[ this.key( owner ) ];\n\n\t\treturn key === undefined ?\n\t\t\tcache : cache[ key ];\n\t},\n\taccess: function( owner, key, value ) {\n\t\tvar stored;\n\t\t// In cases where either:\n\t\t//\n\t\t//   1. No key was specified\n\t\t//   2. A string key was specified, but no value provided\n\t\t//\n\t\t// Take the \"read\" path and allow the get method to determine\n\t\t// which value to return, respectively either:\n\t\t//\n\t\t//   1. The entire cache object\n\t\t//   2. The data stored at the key\n\t\t//\n\t\tif ( key === undefined ||\n\t\t\t\t((key && typeof key === \"string\") && value === undefined) ) {\n\n\t\t\tstored = this.get( owner, key );\n\n\t\t\treturn stored !== undefined ?\n\t\t\t\tstored : this.get( owner, jQuery.camelCase(key) );\n\t\t}\n\n\t\t// [*]When the key is not a string, or both a key and value\n\t\t// are specified, set or extend (existing objects) with either:\n\t\t//\n\t\t//   1. An object of properties\n\t\t//   2. A key and value\n\t\t//\n\t\tthis.set( owner, key, value );\n\n\t\t// Since the \"set\" path can have two possible entry points\n\t\t// return the expected data based on which path was taken[*]\n\t\treturn value !== undefined ? value : key;\n\t},\n\tremove: function( owner, key ) {\n\t\tvar i, name, camel,\n\t\t\tunlock = this.key( owner ),\n\t\t\tcache = this.cache[ unlock ];\n\n\t\tif ( key === undefined ) {\n\t\t\tthis.cache[ unlock ] = {};\n\n\t\t} else {\n\t\t\t// Support array or space separated string of keys\n\t\t\tif ( jQuery.isArray( key ) ) {\n\t\t\t\t// If \"name\" is an array of keys...\n\t\t\t\t// When data is initially created, via (\"key\", \"val\") signature,\n\t\t\t\t// keys will be converted to camelCase.\n\t\t\t\t// Since there is no way to tell _how_ a key was added, remove\n\t\t\t\t// both plain key and camelCase key. #12786\n\t\t\t\t// This will only penalize the array argument path.\n\t\t\t\tname = key.concat( key.map( jQuery.camelCase ) );\n\t\t\t} else {\n\t\t\t\tcamel = jQuery.camelCase( key );\n\t\t\t\t// Try the string as a key before any manipulation\n\t\t\t\tif ( key in cache ) {\n\t\t\t\t\tname = [ key, camel ];\n\t\t\t\t} else {\n\t\t\t\t\t// If a key with the spaces exists, use it.\n\t\t\t\t\t// Otherwise, create an array by matching non-whitespace\n\t\t\t\t\tname = camel;\n\t\t\t\t\tname = name in cache ?\n\t\t\t\t\t\t[ name ] : ( name.match( core_rnotwhite ) || [] );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\ti = name.length;\n\t\t\twhile ( i-- ) {\n\t\t\t\tdelete cache[ name[ i ] ];\n\t\t\t}\n\t\t}\n\t},\n\thasData: function( owner ) {\n\t\treturn !jQuery.isEmptyObject(\n\t\t\tthis.cache[ owner[ this.expando ] ] || {}\n\t\t);\n\t},\n\tdiscard: function( owner ) {\n\t\tif ( owner[ this.expando ] ) {\n\t\t\tdelete this.cache[ owner[ this.expando ] ];\n\t\t}\n\t}\n};\n\n// These may be used throughout the jQuery core codebase\ndata_user = new Data();\ndata_priv = new Data();\n\n\njQuery.extend({\n\tacceptData: Data.accepts,\n\n\thasData: function( elem ) {\n\t\treturn data_user.hasData( elem ) || data_priv.hasData( elem );\n\t},\n\n\tdata: function( elem, name, data ) {\n\t\treturn data_user.access( elem, name, data );\n\t},\n\n\tremoveData: function( elem, name ) {\n\t\tdata_user.remove( elem, name );\n\t},\n\n\t// TODO: Now that all calls to _data and _removeData have been replaced\n\t// with direct calls to data_priv methods, these can be deprecated.\n\t_data: function( elem, name, data ) {\n\t\treturn data_priv.access( elem, name, data );\n\t},\n\n\t_removeData: function( elem, name ) {\n\t\tdata_priv.remove( elem, name );\n\t}\n});\n\njQuery.fn.extend({\n\tdata: function( key, value ) {\n\t\tvar attrs, name,\n\t\t\telem = this[ 0 ],\n\t\t\ti = 0,\n\t\t\tdata = null;\n\n\t\t// Gets all values\n\t\tif ( key === undefined ) {\n\t\t\tif ( this.length ) {\n\t\t\t\tdata = data_user.get( elem );\n\n\t\t\t\tif ( elem.nodeType === 1 && !data_priv.get( elem, \"hasDataAttrs\" ) ) {\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\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\tdata_priv.set( elem, \"hasDataAttrs\", true );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn data;\n\t\t}\n\n\t\t// Sets multiple values\n\t\tif ( typeof key === \"object\" ) {\n\t\t\treturn this.each(function() {\n\t\t\t\tdata_user.set( this, key );\n\t\t\t});\n\t\t}\n\n\t\treturn jQuery.access( this, function( value ) {\n\t\t\tvar data,\n\t\t\t\tcamelKey = jQuery.camelCase( key );\n\n\t\t\t// The calling jQuery object (element matches) is not empty\n\t\t\t// (and therefore has an element appears at this[ 0 ]) and the\n\t\t\t// `value` parameter was not undefined. An empty jQuery object\n\t\t\t// will result in `undefined` for elem = this[ 0 ] which will\n\t\t\t// throw an exception if an attempt to read a data cache is made.\n\t\t\tif ( elem && value === undefined ) {\n\t\t\t\t// Attempt to get data from the cache\n\t\t\t\t// with the key as-is\n\t\t\t\tdata = data_user.get( elem, key );\n\t\t\t\tif ( data !== undefined ) {\n\t\t\t\t\treturn data;\n\t\t\t\t}\n\n\t\t\t\t// Attempt to get data from the cache\n\t\t\t\t// with the key camelized\n\t\t\t\tdata = data_user.get( elem, camelKey );\n\t\t\t\tif ( data !== undefined ) {\n\t\t\t\t\treturn data;\n\t\t\t\t}\n\n\t\t\t\t// Attempt to \"discover\" the data in\n\t\t\t\t// HTML5 custom data-* attrs\n\t\t\t\tdata = dataAttr( elem, camelKey, undefined );\n\t\t\t\tif ( data !== undefined ) {\n\t\t\t\t\treturn data;\n\t\t\t\t}\n\n\t\t\t\t// We tried really hard, but the data doesn't exist.\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Set the data...\n\t\t\tthis.each(function() {\n\t\t\t\t// First, attempt to store a copy or reference of any\n\t\t\t\t// data that might've been store with a camelCased key.\n\t\t\t\tvar data = data_user.get( this, camelKey );\n\n\t\t\t\t// For HTML5 data-* attribute interop, we have to\n\t\t\t\t// store property names with dashes in a camelCase form.\n\t\t\t\t// This might not apply to all properties...*\n\t\t\t\tdata_user.set( this, camelKey, value );\n\n\t\t\t\t// *... In the case of properties that might _actually_\n\t\t\t\t// have dashes, we need to also store a copy of that\n\t\t\t\t// unchanged property.\n\t\t\t\tif ( key.indexOf(\"-\") !== -1 && data !== undefined ) {\n\t\t\t\t\tdata_user.set( this, key, value );\n\t\t\t\t}\n\t\t\t});\n\t\t}, null, value, arguments.length > 1, null, true );\n\t},\n\n\tremoveData: function( key ) {\n\t\treturn this.each(function() {\n\t\t\tdata_user.remove( this, key );\n\t\t});\n\t}\n});\n\nfunction dataAttr( elem, key, data ) {\n\tvar name;\n\n\t// If nothing was found internally, try to fetch any\n\t// data from the HTML5 data-* attribute\n\tif ( data === undefined && elem.nodeType === 1 ) {\n\t\tname = \"data-\" + key.replace( rmultiDash, \"-$1\" ).toLowerCase();\n\t\tdata = elem.getAttribute( name );\n\n\t\tif ( typeof data === \"string\" ) {\n\t\t\ttry {\n\t\t\t\tdata = data === \"true\" ? true :\n\t\t\t\t\tdata === \"false\" ? false :\n\t\t\t\t\tdata === \"null\" ? null :\n\t\t\t\t\t// Only convert to a number if it doesn't change the string\n\t\t\t\t\t+data + \"\" === data ? +data :\n\t\t\t\t\trbrace.test( data ) ? JSON.parse( data ) :\n\t\t\t\t\tdata;\n\t\t\t} catch( e ) {}\n\n\t\t\t// Make sure we set the data so it isn't changed later\n\t\t\tdata_user.set( elem, key, data );\n\t\t} else {\n\t\t\tdata = undefined;\n\t\t}\n\t}\n\treturn data;\n}\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/jquery/src/deferred.js",
    "content": "jQuery.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});\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/jquery/src/deprecated.js",
    "content": "// 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// })();\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/jquery/src/dimensions.js",
    "content": "// 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],\n\t\t\t\t\t// whichever is greatest\n\t\t\t\t\treturn Math.max(\n\t\t\t\t\t\telem.body[ \"scroll\" + name ], doc[ \"scroll\" + name ],\n\t\t\t\t\t\telem.body[ \"offset\" + name ], doc[ \"offset\" + name ],\n\t\t\t\t\t\tdoc[ \"client\" + name ]\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\treturn value === undefined ?\n\t\t\t\t\t// Get width or height on the element, requesting but not forcing parseFloat\n\t\t\t\t\tjQuery.css( elem, type, extra ) :\n\n\t\t\t\t\t// Set width or height on the element\n\t\t\t\t\tjQuery.style( elem, type, value, extra );\n\t\t\t}, type, chainable ? margin : undefined, chainable, null );\n\t\t};\n\t});\n});\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/jquery/src/effects.js",
    "content": "var 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 = data_priv.get( elem, \"fxshow\" );\n\n\t// handle queue: false promises\n\tif ( !opts.queue ) {\n\t\thooks = jQuery._queueHooks( elem, \"fx\" );\n\t\tif ( hooks.unqueued == null ) {\n\t\t\thooks.unqueued = 0;\n\t\t\toldfire = hooks.empty.fire;\n\t\t\thooks.empty.fire = function() {\n\t\t\t\tif ( !hooks.unqueued ) {\n\t\t\t\t\toldfire();\n\t\t\t\t}\n\t\t\t};\n\t\t}\n\t\thooks.unqueued++;\n\n\t\tanim.always(function() {\n\t\t\t// 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 IE9-10 do not\n\t\t// change the overflow attribute when overflowX and\n\t\t// overflowY are set to the same value\n\t\topts.overflow = [ style.overflow, style.overflowX, style.overflowY ];\n\n\t\t// Set display property to inline-block for height/width\n\t\t// animations on inline elements that are having width/height animated\n\t\tif ( jQuery.css( elem, \"display\" ) === \"inline\" &&\n\t\t\t\tjQuery.css( elem, \"float\" ) === \"none\" ) {\n\n\t\t\tstyle.display = \"inline-block\";\n\t\t}\n\t}\n\n\tif ( opts.overflow ) {\n\t\tstyle.overflow = \"hidden\";\n\t\tanim.always(function() {\n\t\t\tstyle.overflow = opts.overflow[ 0 ];\n\t\t\tstyle.overflowX = opts.overflow[ 1 ];\n\t\t\tstyle.overflowY = opts.overflow[ 2 ];\n\t\t});\n\t}\n\n\n\t// show/hide pass\n\tfor ( prop in props ) {\n\t\tvalue = props[ prop ];\n\t\tif ( rfxtypes.exec( value ) ) {\n\t\t\tdelete props[ prop ];\n\t\t\ttoggle = toggle || value === \"toggle\";\n\t\t\tif ( value === ( hidden ? \"hide\" : \"show\" ) ) {\n\n\t\t\t\t// If there is dataShow left over from a stopped hide or show and we are going to proceed with show, we should pretend to be hidden\n\t\t\t\tif ( value === \"show\" && dataShow && dataShow[ prop ] !== undefined ) {\n\t\t\t\t\thidden = true;\n\t\t\t\t} else {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t}\n\t\t\torig[ prop ] = dataShow && dataShow[ prop ] || jQuery.style( elem, prop );\n\t\t}\n\t}\n\n\tif ( !jQuery.isEmptyObject( orig ) ) {\n\t\tif ( dataShow ) {\n\t\t\tif ( \"hidden\" in dataShow ) {\n\t\t\t\thidden = dataShow.hidden;\n\t\t\t}\n\t\t} else {\n\t\t\tdataShow = data_priv.access( elem, \"fxshow\", {} );\n\t\t}\n\n\t\t// store state if its toggle - enables .stop().toggle() to \"reverse\"\n\t\tif ( toggle ) {\n\t\t\tdataShow.hidden = !hidden;\n\t\t}\n\t\tif ( hidden ) {\n\t\t\tjQuery( elem ).show();\n\t\t} else {\n\t\t\tanim.done(function() {\n\t\t\t\tjQuery( elem ).hide();\n\t\t\t});\n\t\t}\n\t\tanim.done(function() {\n\t\t\tvar prop;\n\n\t\t\tdata_priv.remove( elem, \"fxshow\" );\n\t\t\tfor ( prop in orig ) {\n\t\t\t\tjQuery.style( elem, prop, orig[ prop ] );\n\t\t\t}\n\t\t});\n\t\tfor ( prop in orig ) {\n\t\t\ttween = createTween( hidden ? dataShow[ prop ] : 0, prop, anim );\n\n\t\t\tif ( !( prop in dataShow ) ) {\n\t\t\t\tdataShow[ prop ] = tween.start;\n\t\t\t\tif ( hidden ) {\n\t\t\t\t\ttween.end = tween.start;\n\t\t\t\t\ttween.start = prop === \"width\" || prop === \"height\" ? 1 : 0;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\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: IE9\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 || data_priv.get( this, \"finish\" ) ) {\n\t\t\t\t\tanim.stop( true );\n\t\t\t\t}\n\t\t\t};\n\t\t\tdoAnimation.finish = doAnimation;\n\n\t\treturn empty || optall.queue === false ?\n\t\t\tthis.each( doAnimation ) :\n\t\t\tthis.queue( optall.queue, doAnimation );\n\t},\n\tstop: function( type, clearQueue, gotoEnd ) {\n\t\tvar stopQueue = function( hooks ) {\n\t\t\tvar stop = hooks.stop;\n\t\t\tdelete hooks.stop;\n\t\t\tstop( gotoEnd );\n\t\t};\n\n\t\tif ( typeof type !== \"string\" ) {\n\t\t\tgotoEnd = clearQueue;\n\t\t\tclearQueue = type;\n\t\t\ttype = undefined;\n\t\t}\n\t\tif ( clearQueue && type !== false ) {\n\t\t\tthis.queue( type || \"fx\", [] );\n\t\t}\n\n\t\treturn this.each(function() {\n\t\t\tvar dequeue = true,\n\t\t\t\tindex = type != null && type + \"queueHooks\",\n\t\t\t\ttimers = jQuery.timers,\n\t\t\t\tdata = data_priv.get( this );\n\n\t\t\tif ( index ) {\n\t\t\t\tif ( data[ index ] && data[ index ].stop ) {\n\t\t\t\t\tstopQueue( data[ index ] );\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tfor ( index in data ) {\n\t\t\t\t\tif ( data[ index ] && data[ index ].stop && rrun.test( index ) ) {\n\t\t\t\t\t\tstopQueue( data[ index ] );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfor ( index = timers.length; index--; ) {\n\t\t\t\tif ( timers[ index ].elem === this && (type == null || timers[ index ].queue === type) ) {\n\t\t\t\t\ttimers[ index ].anim.stop( gotoEnd );\n\t\t\t\t\tdequeue = false;\n\t\t\t\t\ttimers.splice( index, 1 );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// start the next in the queue if the last step wasn't forced\n\t\t\t// timers currently will call their complete callbacks, which 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 = data_priv.get( this ),\n\t\t\t\tqueue = data[ type + \"queue\" ],\n\t\t\t\thooks = data[ type + \"queueHooks\" ],\n\t\t\t\ttimers = jQuery.timers,\n\t\t\t\tlength = queue ? queue.length : 0;\n\n\t\t\t// enable finishing flag on private data\n\t\t\tdata.finish = true;\n\n\t\t\t// empty the queue first\n\t\t\tjQuery.queue( this, type, [] );\n\n\t\t\tif ( hooks && hooks.stop ) {\n\t\t\t\thooks.stop.call( this, true );\n\t\t\t}\n\n\t\t\t// look for any active animations, and finish them\n\t\t\tfor ( index = timers.length; index--; ) {\n\t\t\t\tif ( timers[ index ].elem === this && timers[ index ].queue === type ) {\n\t\t\t\t\ttimers[ index ].anim.stop( true );\n\t\t\t\t\ttimers.splice( index, 1 );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// look for any animations in the old queue and finish them\n\t\t\tfor ( index = 0; index < length; index++ ) {\n\t\t\t\tif ( queue[ index ] && queue[ index ].finish ) {\n\t\t\t\t\tqueue[ index ].finish.call( this );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// turn off finishing flag\n\t\t\tdelete data.finish;\n\t\t});\n\t}\n});\n\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}\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/jquery/src/event-alias.js",
    "content": "jQuery.each( (\"blur focus focusin focusout load resize scroll unload click dblclick \" +\n\t\"mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave \" +\n\t\"change select submit keydown keypress keyup error contextmenu\").split(\" \"), function( i, name ) {\n\n\t// Handle event binding\n\tjQuery.fn[ name ] = function( data, fn ) {\n\t\treturn arguments.length > 0 ?\n\t\t\tthis.on( name, null, data, fn ) :\n\t\t\tthis.trigger( name );\n\t};\n});\n\njQuery.fn.extend({\n\thover: function( fnOver, fnOut ) {\n\t\treturn this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );\n\t},\n\n\tbind: function( types, data, fn ) {\n\t\treturn this.on( types, null, data, fn );\n\t},\n\tunbind: function( types, fn ) {\n\t\treturn this.off( types, null, fn );\n\t},\n\n\tdelegate: function( selector, types, data, fn ) {\n\t\treturn this.on( types, selector, data, fn );\n\t},\n\tundelegate: function( selector, types, fn ) {\n\t\t// ( namespace ) or ( selector, types [, fn] )\n\t\treturn arguments.length === 1 ? this.off( selector, \"**\" ) : this.off( types, selector || \"**\", fn );\n\t}\n});\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/jquery/src/event.js",
    "content": "var rkeyEvent = /^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\n\t\tvar handleObjIn, eventHandle, tmp,\n\t\t\tevents, t, handleObj,\n\t\t\tspecial, handlers, type, namespaces, origType,\n\t\t\telemData = data_priv.get( elem );\n\n\t\t// Don't attach events to noData or text/comment nodes (but allow plain objects)\n\t\tif ( !elemData ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Caller can pass in an object of custom data in lieu of the handler\n\t\tif ( handler.handler ) {\n\t\t\thandleObjIn = handler;\n\t\t\thandler = handleObjIn.handler;\n\t\t\tselector = handleObjIn.selector;\n\t\t}\n\n\t\t// Make sure that the handler has a unique ID, used to find/remove it later\n\t\tif ( !handler.guid ) {\n\t\t\thandler.guid = jQuery.guid++;\n\t\t}\n\n\t\t// Init the element's event structure and main handler, if this is the first\n\t\tif ( !(events = elemData.events) ) {\n\t\t\tevents = elemData.events = {};\n\t\t}\n\t\tif ( !(eventHandle = elemData.handle) ) {\n\t\t\teventHandle = elemData.handle = function( e ) {\n\t\t\t\t// Discard the second event of a jQuery.event.trigger() and\n\t\t\t\t// when an event is called after a page has unloaded\n\t\t\t\treturn typeof jQuery !== 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 if the special events handler returns false\n\t\t\t\tif ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) {\n\t\t\t\t\tif ( elem.addEventListener ) {\n\t\t\t\t\t\telem.addEventListener( type, eventHandle, false );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( special.add ) {\n\t\t\t\tspecial.add.call( elem, handleObj );\n\n\t\t\t\tif ( !handleObj.handler.guid ) {\n\t\t\t\t\thandleObj.handler.guid = handler.guid;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Add to the element's handler list, delegates in front\n\t\t\tif ( selector ) {\n\t\t\t\thandlers.splice( handlers.delegateCount++, 0, handleObj );\n\t\t\t} else {\n\t\t\t\thandlers.push( handleObj );\n\t\t\t}\n\n\t\t\t// Keep track of which events have ever been used, for event optimization\n\t\t\tjQuery.event.global[ type ] = true;\n\t\t}\n\n\t\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\n\t\tvar j, origCount, tmp,\n\t\t\tevents, t, handleObj,\n\t\t\tspecial, handlers, type, namespaces, origType,\n\t\t\telemData = data_priv.hasData( elem ) && data_priv.get( elem );\n\n\t\tif ( !elemData || !(events = elemData.events) ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Once for each type.namespace in types; type may be omitted\n\t\ttypes = ( types || \"\" ).match( 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\t\t\tdata_priv.remove( elem, \"events\" );\n\t\t}\n\t},\n\n\ttrigger: function( event, data, elem, onlyHandlers ) {\n\n\t\tvar i, cur, tmp, bubbleType, ontype, handle, special,\n\t\t\teventPath = [ elem || document ],\n\t\t\ttype = 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 = ( data_priv.get( cur, \"events\" ) || {} )[ event.type ] && data_priv.get( cur, \"handle\" );\n\t\t\tif ( handle ) {\n\t\t\t\thandle.apply( cur, data );\n\t\t\t}\n\n\t\t\t// Native handler\n\t\t\thandle = ontype && cur[ ontype ];\n\t\t\tif ( handle && 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// Don't do default actions on window, that's where global variables be (#6170)\n\t\t\t\tif ( ontype && jQuery.isFunction( elem[ type ] ) && !jQuery.isWindow( elem ) ) {\n\n\t\t\t\t\t// Don't re-trigger an onFOO event when we call its FOO() method\n\t\t\t\t\ttmp = elem[ ontype ];\n\n\t\t\t\t\tif ( tmp ) {\n\t\t\t\t\t\telem[ ontype ] = null;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Prevent re-triggering of the same event, since we already bubbled it above\n\t\t\t\t\tjQuery.event.triggered = type;\n\t\t\t\t\telem[ type ]();\n\t\t\t\t\tjQuery.event.triggered = undefined;\n\n\t\t\t\t\tif ( tmp ) {\n\t\t\t\t\t\telem[ ontype ] = tmp;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn event.result;\n\t},\n\n\tdispatch: function( event ) {\n\n\t\t// Make a writable jQuery.Event from the native event object\n\t\tevent = jQuery.event.fix( event );\n\n\t\tvar i, j, ret, matched, handleObj,\n\t\t\thandlerQueue = [],\n\t\t\targs = core_slice.call( arguments ),\n\t\t\thandlers = ( data_priv.get( this, \"events\" ) || {} )[ event.type ] || [],\n\t\t\tspecial = jQuery.event.special[ event.type ] || {};\n\n\t\t// Use the fix-ed jQuery.Event rather than the (read-only) native event\n\t\targs[0] = event;\n\t\tevent.delegateTarget = this;\n\n\t\t// Call the preDispatch hook for the mapped type, and let it bail if desired\n\t\tif ( special.preDispatch && special.preDispatch.call( this, event ) === false ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Determine handlers\n\t\thandlerQueue = jQuery.event.handlers.call( this, event, handlers );\n\n\t\t// Run delegates first; they may want to stop propagation beneath us\n\t\ti = 0;\n\t\twhile ( (matched = handlerQueue[ i++ ]) && !event.isPropagationStopped() ) {\n\t\t\tevent.currentTarget = matched.elem;\n\n\t\t\tj = 0;\n\t\t\twhile ( (handleObj = matched.handlers[ j++ ]) && !event.isImmediatePropagationStopped() ) {\n\n\t\t\t\t// Triggered event must either 1) have no namespace, or\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 i, matches, sel, handleObj,\n\t\t\thandlerQueue = [],\n\t\t\tdelegateCount = handlers.delegateCount,\n\t\t\tcur = event.target;\n\n\t\t// Find delegate handlers\n\t\t// Black-hole SVG <use> instance trees (#13180)\n\t\t// Avoid non-left-click bubbling in Firefox (#3861)\n\t\tif ( delegateCount && cur.nodeType && (!event.button || event.type !== \"click\") ) {\n\n\t\t\tfor ( ; cur !== this; cur = cur.parentNode || this ) {\n\n\t\t\t\t// Don't process clicks on disabled elements (#6911, #8165, #11382, #11764)\n\t\t\t\tif ( cur.disabled !== true || event.type !== \"click\" ) {\n\t\t\t\t\tmatches = [];\n\t\t\t\t\tfor ( i = 0; i < delegateCount; i++ ) {\n\t\t\t\t\t\thandleObj = handlers[ i ];\n\n\t\t\t\t\t\t// Don't conflict with Object.prototype properties (#13203)\n\t\t\t\t\t\tsel = handleObj.selector + \" \";\n\n\t\t\t\t\t\tif ( matches[ sel ] === undefined ) {\n\t\t\t\t\t\t\tmatches[ sel ] = handleObj.needsContext ?\n\t\t\t\t\t\t\t\tjQuery( sel, this ).index( cur ) >= 0 :\n\t\t\t\t\t\t\t\tjQuery.find( sel, this, null, [ cur ] ).length;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif ( matches[ sel ] ) {\n\t\t\t\t\t\t\tmatches.push( handleObj );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif ( matches.length ) {\n\t\t\t\t\t\thandlerQueue.push({ elem: cur, handlers: matches });\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Add the remaining (directly-bound) handlers\n\t\tif ( delegateCount < handlers.length ) {\n\t\t\thandlerQueue.push({ elem: this, handlers: handlers.slice( delegateCount ) });\n\t\t}\n\n\t\treturn handlerQueue;\n\t},\n\n\t// Includes some event props shared by KeyEvent and MouseEvent\n\tprops: \"altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which\".split(\" \"),\n\n\tfixHooks: {},\n\n\tkeyHooks: {\n\t\tprops: \"char charCode key keyCode\".split(\" \"),\n\t\tfilter: function( event, original ) {\n\n\t\t\t// Add which for key events\n\t\t\tif ( event.which == null ) {\n\t\t\t\tevent.which = original.charCode != null ? original.charCode : original.keyCode;\n\t\t\t}\n\n\t\t\treturn event;\n\t\t}\n\t},\n\n\tmouseHooks: {\n\t\tprops: \"button buttons clientX clientY offsetX offsetY pageX pageY screenX screenY toElement\".split(\" \"),\n\t\tfilter: function( event, original ) {\n\t\t\tvar eventDoc, doc, body,\n\t\t\t\tbutton = original.button;\n\n\t\t\t// Calculate pageX/Y if missing and clientX/Y available\n\t\t\tif ( event.pageX == null && original.clientX != null ) {\n\t\t\t\teventDoc = event.target.ownerDocument || document;\n\t\t\t\tdoc = eventDoc.documentElement;\n\t\t\t\tbody = eventDoc.body;\n\n\t\t\t\tevent.pageX = original.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && body.clientLeft || 0 );\n\t\t\t\tevent.pageY = original.clientY + ( doc && doc.scrollTop  || body && body.scrollTop  || 0 ) - ( doc && doc.clientTop  || body && body.clientTop  || 0 );\n\t\t\t}\n\n\t\t\t// Add which for click: 1 === left; 2 === middle; 3 === right\n\t\t\t// Note: button is not normalized, so don't use it\n\t\t\tif ( !event.which && button !== undefined ) {\n\t\t\t\tevent.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) );\n\t\t\t}\n\n\t\t\treturn event;\n\t\t}\n\t},\n\n\tfix: function( event ) {\n\t\tif ( event[ jQuery.expando ] ) {\n\t\t\treturn event;\n\t\t}\n\n\t\t// Create a writable copy of the event object and normalize some properties\n\t\tvar i, prop, copy,\n\t\t\ttype = event.type,\n\t\t\toriginalEvent = event,\n\t\t\tfixHook = this.fixHooks[ type ];\n\n\t\tif ( !fixHook ) {\n\t\t\tthis.fixHooks[ type ] = fixHook =\n\t\t\t\trmouseEvent.test( type ) ? this.mouseHooks :\n\t\t\t\trkeyEvent.test( type ) ? this.keyHooks :\n\t\t\t\t{};\n\t\t}\n\t\tcopy = fixHook.props ? this.props.concat( fixHook.props ) : this.props;\n\n\t\tevent = new jQuery.Event( originalEvent );\n\n\t\ti = copy.length;\n\t\twhile ( i-- ) {\n\t\t\tprop = copy[ i ];\n\t\t\tevent[ prop ] = originalEvent[ prop ];\n\t\t}\n\n\t\t// Support: Cordova 2.5 (WebKit) (#13255)\n\t\t// All events should have a target; Cordova deviceready doesn't\n\t\tif ( !event.target ) {\n\t\t\tevent.target = document;\n\t\t}\n\n\t\t// Support: Safari 6.0+, Chrome < 28\n\t\t// Target should not be a text node (#504, #13143)\n\t\tif ( event.target.nodeType === 3 ) {\n\t\t\tevent.target = event.target.parentNode;\n\t\t}\n\n\t\treturn fixHook.filter? fixHook.filter( event, originalEvent ) : event;\n\t},\n\n\tspecial: {\n\t\tload: {\n\t\t\t// Prevent triggered image.load events from bubbling to window.load\n\t\t\tnoBubble: true\n\t\t},\n\t\tfocus: {\n\t\t\t// Fire native event if possible so blur/focus sequence is correct\n\t\t\ttrigger: function() {\n\t\t\t\tif ( this !== safeActiveElement() && this.focus ) {\n\t\t\t\t\tthis.focus();\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t},\n\t\t\tdelegateType: \"focusin\"\n\t\t},\n\t\tblur: {\n\t\t\ttrigger: function() {\n\t\t\t\tif ( this === safeActiveElement() && this.blur ) {\n\t\t\t\t\tthis.blur();\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t},\n\t\t\tdelegateType: \"focusout\"\n\t\t},\n\t\tclick: {\n\t\t\t// For checkbox, fire native event so checked state will be right\n\t\t\ttrigger: function() {\n\t\t\t\tif ( this.type === \"checkbox\" && this.click && jQuery.nodeName( this, \"input\" ) ) {\n\t\t\t\t\tthis.click();\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t},\n\n\t\t\t// For cross-browser consistency, don't fire native .click() on links\n\t\t\t_default: function( event ) {\n\t\t\t\treturn jQuery.nodeName( event.target, \"a\" );\n\t\t\t}\n\t\t},\n\n\t\tbeforeunload: {\n\t\t\tpostDispatch: function( event ) {\n\n\t\t\t\t// Support: Firefox 20+\n\t\t\t\t// Firefox doesn't alert if the returnValue field is not set.\n\t\t\t\tif ( event.result !== undefined ) {\n\t\t\t\t\tevent.originalEvent.returnValue = event.result;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\n\tsimulate: function( type, elem, event, bubble ) {\n\t\t// Piggyback on a donor event to simulate a different one.\n\t\t// Fake originalEvent to avoid donor's stopPropagation, but if the\n\t\t// simulated event prevents default then we do the same on the donor.\n\t\tvar e = jQuery.extend(\n\t\t\tnew jQuery.Event(),\n\t\t\tevent,\n\t\t\t{\n\t\t\t\ttype: type,\n\t\t\t\tisSimulated: true,\n\t\t\t\toriginalEvent: {}\n\t\t\t}\n\t\t);\n\t\tif ( bubble ) {\n\t\t\tjQuery.event.trigger( e, null, elem );\n\t\t} else {\n\t\t\tjQuery.event.dispatch.call( elem, e );\n\t\t}\n\t\tif ( e.isDefaultPrevented() ) {\n\t\t\tevent.preventDefault();\n\t\t}\n\t}\n};\n\njQuery.removeEvent = function( elem, type, handle ) {\n\tif ( elem.removeEventListener ) {\n\t\telem.removeEventListener( type, handle, false );\n\t}\n};\n\njQuery.Event = function( src, props ) {\n\t// Allow instantiation without the 'new' keyword\n\tif ( !(this instanceof jQuery.Event) ) {\n\t\treturn new jQuery.Event( src, props );\n\t}\n\n\t// Event object\n\tif ( src && src.type ) {\n\t\tthis.originalEvent = src;\n\t\tthis.type = src.type;\n\n\t\t// Events bubbling up the document may have been marked as prevented\n\t\t// by a handler lower down the tree; reflect the correct value.\n\t\tthis.isDefaultPrevented = ( src.defaultPrevented ||\n\t\t\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\n\t\tif ( e && e.preventDefault ) {\n\t\t\te.preventDefault();\n\t\t}\n\t},\n\tstopPropagation: function() {\n\t\tvar e = this.originalEvent;\n\n\t\tthis.isPropagationStopped = returnTrue;\n\n\t\tif ( e && e.stopPropagation ) {\n\t\t\te.stopPropagation();\n\t\t}\n\t},\n\tstopImmediatePropagation: function() {\n\t\tthis.isImmediatePropagationStopped = returnTrue;\n\t\tthis.stopPropagation();\n\t}\n};\n\n// Create mouseenter/leave events using mouseover/out and event-time checks\n// Support: Chrome 15+\njQuery.each({\n\tmouseenter: \"mouseover\",\n\tmouseleave: \"mouseout\"\n}, 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// Create \"bubbling\" focus and blur events\n// Support: Firefox, Chrome, Safari\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 = data || selector;\n\t\t\t\tselector = undefined;\n\t\t\t}\n\t\t\tfor ( type in types ) {\n\t\t\t\tthis.on( type, selector, data, types[ type ], one );\n\t\t\t}\n\t\t\treturn this;\n\t\t}\n\n\t\tif ( data == null && fn == null ) {\n\t\t\t// ( types, fn )\n\t\t\tfn = selector;\n\t\t\tdata = selector = undefined;\n\t\t} else if ( fn == null ) {\n\t\t\tif ( typeof selector === \"string\" ) {\n\t\t\t\t// ( types, selector, fn )\n\t\t\t\tfn = data;\n\t\t\t\tdata = undefined;\n\t\t\t} else {\n\t\t\t\t// ( types, data, fn )\n\t\t\t\tfn = data;\n\t\t\t\tdata = selector;\n\t\t\t\tselector = undefined;\n\t\t\t}\n\t\t}\n\t\tif ( fn === false ) {\n\t\t\tfn = returnFalse;\n\t\t} else if ( !fn ) {\n\t\t\treturn this;\n\t\t}\n\n\t\tif ( one === 1 ) {\n\t\t\torigFn = fn;\n\t\t\tfn = function( event ) {\n\t\t\t\t// Can use an empty set, since event contains the info\n\t\t\t\tjQuery().off( event );\n\t\t\t\treturn origFn.apply( this, arguments );\n\t\t\t};\n\t\t\t// Use same guid so caller can remove using origFn\n\t\t\tfn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ );\n\t\t}\n\t\treturn this.each( function() {\n\t\t\tjQuery.event.add( this, types, fn, data, selector );\n\t\t});\n\t},\n\tone: function( types, selector, data, fn ) {\n\t\treturn this.on( types, selector, data, fn, 1 );\n\t},\n\toff: function( types, selector, fn ) {\n\t\tvar handleObj, type;\n\t\tif ( types && types.preventDefault && types.handleObj ) {\n\t\t\t// ( event )  dispatched jQuery.Event\n\t\t\thandleObj = types.handleObj;\n\t\t\tjQuery( types.delegateTarget ).off(\n\t\t\t\thandleObj.namespace ? handleObj.origType + \".\" + handleObj.namespace : handleObj.origType,\n\t\t\t\thandleObj.selector,\n\t\t\t\thandleObj.handler\n\t\t\t);\n\t\t\treturn this;\n\t\t}\n\t\tif ( typeof types === \"object\" ) {\n\t\t\t// ( types-object [, selector] )\n\t\t\tfor ( type in types ) {\n\t\t\t\tthis.off( type, selector, types[ type ] );\n\t\t\t}\n\t\t\treturn this;\n\t\t}\n\t\tif ( selector === false || typeof selector === \"function\" ) {\n\t\t\t// ( types [, fn] )\n\t\t\tfn = selector;\n\t\t\tselector = undefined;\n\t\t}\n\t\tif ( fn === false ) {\n\t\t\tfn = returnFalse;\n\t\t}\n\t\treturn this.each(function() {\n\t\t\tjQuery.event.remove( this, types, fn, selector );\n\t\t});\n\t},\n\n\ttrigger: function( type, data ) {\n\t\treturn this.each(function() {\n\t\t\tjQuery.event.trigger( type, data, this );\n\t\t});\n\t},\n\ttriggerHandler: function( type, data ) {\n\t\tvar elem = this[0];\n\t\tif ( elem ) {\n\t\t\treturn jQuery.event.trigger( type, data, elem, true );\n\t\t}\n\t}\n});\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/jquery/src/exports.js",
    "content": "if ( 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// 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// If there is a window object, that at least has a document property,\n// define jQuery and $ identifiers\nif ( typeof window === \"object\" && typeof window.document === \"object\" ) {\n\twindow.jQuery = window.$ = jQuery;\n}\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/jquery/src/intro.js",
    "content": "/*!\n * jQuery JavaScript Library v@VERSION\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: @DATE\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\";\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/jquery/src/manipulation.js",
    "content": "var rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\\w:]+)[^>]*)\\/>/gi,\n\trtagName = /<([\\w:]+)/,\n\trhtml = /<|&#?\\w+;/,\n\trnoInnerhtml = /<(?:script|style|link)/i,\n\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\n\t\t// Support: IE 9\n\t\toption: [ 1, \"<select multiple='multiple'>\", \"</select>\" ],\n\n\t\tthead: [ 1, \"<table>\", \"</table>\" ],\n\t\tcol: [ 2, \"<table><colgroup>\", \"</colgroup></table>\" ],\n\t\ttr: [ 2, \"<table><tbody>\", \"</tbody></table>\" ],\n\t\ttd: [ 3, \"<table><tbody><tr>\", \"</tr></tbody></table>\" ],\n\n\t\t_default: [ 0, \"\", \"\" ]\n\t};\n\n// Support: IE 9\nwrapMap.optgroup = wrapMap.option;\n\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\t\t\tif ( !keepData && elem.nodeType === 1 ) {\n\t\t\t\tjQuery.cleanData( getAll( elem ) );\n\t\t\t}\n\n\t\t\tif ( elem.parentNode ) {\n\t\t\t\tif ( keepData && jQuery.contains( elem.ownerDocument, elem ) ) {\n\t\t\t\t\tsetGlobalEval( getAll( elem, \"script\" ) );\n\t\t\t\t}\n\t\t\t\telem.parentNode.removeChild( elem );\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\tempty: function() {\n\t\tvar elem,\n\t\t\ti = 0;\n\n\t\tfor ( ; (elem = this[i]) != null; i++ ) {\n\t\t\tif ( elem.nodeType === 1 ) {\n\n\t\t\t\t// Prevent memory leaks\n\t\t\t\tjQuery.cleanData( getAll( elem, false ) );\n\n\t\t\t\t// Remove any remaining nodes\n\t\t\t\telem.textContent = \"\";\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\tclone: function( dataAndEvents, deepDataAndEvents ) {\n\t\tdataAndEvents = dataAndEvents == null ? false : dataAndEvents;\n\t\tdeepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents;\n\n\t\treturn this.map( function () {\n\t\t\treturn jQuery.clone( this, dataAndEvents, deepDataAndEvents );\n\t\t});\n\t},\n\n\thtml: function( value ) {\n\t\treturn 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 && elem.nodeType === 1 ) {\n\t\t\t\treturn elem.innerHTML;\n\t\t\t}\n\n\t\t\t// See if we can take a shortcut and just use innerHTML\n\t\t\tif ( typeof value === \"string\" && !rnoInnerhtml.test( value ) &&\n\t\t\t\t!wrapMap[ ( rtagName.exec( value ) || [ \"\", \"\" ] )[ 1 ].toLowerCase() ] ) {\n\n\t\t\t\tvalue = value.replace( rxhtmlTag, \"<$1></$2>\" );\n\n\t\t\t\ttry {\n\t\t\t\t\tfor ( ; i < l; i++ ) {\n\t\t\t\t\t\telem = this[ i ] || {};\n\n\t\t\t\t\t\t// Remove element nodes and prevent memory leaks\n\t\t\t\t\t\tif ( elem.nodeType === 1 ) {\n\t\t\t\t\t\t\tjQuery.cleanData( getAll( elem, false ) );\n\t\t\t\t\t\t\telem.innerHTML = value;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\telem = 0;\n\n\t\t\t\t// If using innerHTML throws an exception, use the fallback method\n\t\t\t\t} catch( e ) {}\n\t\t\t}\n\n\t\t\tif ( elem ) {\n\t\t\t\tthis.empty().append( value );\n\t\t\t}\n\t\t}, null, value, arguments.length );\n\t},\n\n\treplaceWith: function() {\n\t\tvar\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 fragment, first, scripts, hasScripts, node, doc,\n\t\t\ti = 0,\n\t\t\tl = this.length,\n\t\t\tset = this,\n\t\t\tiNoClone = l - 1,\n\t\t\tvalue = args[ 0 ],\n\t\t\tisFunction = jQuery.isFunction( value );\n\n\t\t// We can't cloneNode fragments that contain checked, in WebKit\n\t\tif ( isFunction || !( 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\t// Support: QtWebKit\n\t\t\t\t\t\t\t// jQuery.merge because core_push.apply(_, arraylike) throws\n\t\t\t\t\t\t\tjQuery.merge( scripts, getAll( node, \"script\" ) );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tcallback.call( this[ i ], node, i );\n\t\t\t\t}\n\n\t\t\t\tif ( hasScripts ) {\n\t\t\t\t\tdoc = scripts[ scripts.length - 1 ].ownerDocument;\n\n\t\t\t\t\t// Reenable scripts\n\t\t\t\t\tjQuery.map( scripts, restoreScript );\n\n\t\t\t\t\t// Evaluate executable scripts on first document insertion\n\t\t\t\t\tfor ( i = 0; i < hasScripts; i++ ) {\n\t\t\t\t\t\tnode = scripts[ i ];\n\t\t\t\t\t\tif ( rscriptType.test( node.type || \"\" ) &&\n\t\t\t\t\t\t\t!data_priv.access( node, \"globalEval\" ) && jQuery.contains( doc, node ) ) {\n\n\t\t\t\t\t\t\tif ( node.src ) {\n\t\t\t\t\t\t\t\t// 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.textContent.replace( rcleanScript, \"\" ) );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t}\n});\n\njQuery.each({\n\tappendTo: \"append\",\n\tprependTo: \"prepend\",\n\tinsertBefore: \"before\",\n\tinsertAfter: \"after\",\n\treplaceAll: \"replaceWith\"\n}, function( name, original ) {\n\tjQuery.fn[ name ] = function( selector ) {\n\t\tvar elems,\n\t\t\tret = [],\n\t\t\tinsert = jQuery( selector ),\n\t\t\tlast = insert.length - 1,\n\t\t\ti = 0;\n\n\t\tfor ( ; i <= last; i++ ) {\n\t\t\telems = i === last ? this : this.clone( true );\n\t\t\tjQuery( insert[ i ] )[ original ]( elems );\n\n\t\t\t// Support: QtWebKit\n\t\t\t// .get() because core_push.apply(_, arraylike) throws\n\t\t\tcore_push.apply( ret, elems.get() );\n\t\t}\n\n\t\treturn this.pushStack( ret );\n\t};\n});\n\njQuery.extend({\n\tclone: function( elem, dataAndEvents, deepDataAndEvents ) {\n\t\tvar i, l, srcElements, destElements,\n\t\t\tclone = elem.cloneNode( true ),\n\t\t\tinPage = jQuery.contains( elem.ownerDocument, elem );\n\n\t\t// Support: IE >= 9\n\t\t// Fix Cloning issues\n\t\tif ( !jQuery.support.noCloneChecked && ( 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\tfor ( i = 0, l = srcElements.length; i < l; i++ ) {\n\t\t\t\tfixInput( srcElements[ i ], destElements[ i ] );\n\t\t\t}\n\t\t}\n\n\t\t// Copy the events from the original to the clone\n\t\tif ( dataAndEvents ) {\n\t\t\tif ( deepDataAndEvents ) {\n\t\t\t\tsrcElements = srcElements || getAll( elem );\n\t\t\t\tdestElements = destElements || getAll( clone );\n\n\t\t\t\tfor ( i = 0, l = srcElements.length; i < l; i++ ) {\n\t\t\t\t\tcloneCopyEvent( srcElements[ i ], destElements[ i ] );\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tcloneCopyEvent( elem, clone );\n\t\t\t}\n\t\t}\n\n\t\t// Preserve script evaluation history\n\t\tdestElements = getAll( clone, \"script\" );\n\t\tif ( destElements.length > 0 ) {\n\t\t\tsetGlobalEval( destElements, !inPage && getAll( elem, \"script\" ) );\n\t\t}\n\n\t\t// Return the cloned set\n\t\treturn clone;\n\t},\n\n\tbuildFragment: function( elems, context, scripts, selection ) {\n\t\tvar elem, tmp, tag, wrap, contains, j,\n\t\t\ti = 0,\n\t\t\tl = elems.length,\n\t\t\tfragment = context.createDocumentFragment(),\n\t\t\tnodes = [];\n\n\t\tfor ( ; i < l; i++ ) {\n\t\t\telem = elems[ i ];\n\n\t\t\tif ( elem || elem === 0 ) {\n\n\t\t\t\t// Add nodes directly\n\t\t\t\tif ( jQuery.type( elem ) === \"object\" ) {\n\t\t\t\t\t// Support: QtWebKit\n\t\t\t\t\t// jQuery.merge because core_push.apply(_, arraylike) throws\n\t\t\t\t\tjQuery.merge( nodes, elem.nodeType ? [ elem ] : elem );\n\n\t\t\t\t// Convert non-html into a text node\n\t\t\t\t} else if ( !rhtml.test( elem ) ) {\n\t\t\t\t\tnodes.push( context.createTextNode( elem ) );\n\n\t\t\t\t// Convert html into DOM nodes\n\t\t\t\t} else {\n\t\t\t\t\ttmp = tmp || fragment.appendChild( context.createElement(\"div\") );\n\n\t\t\t\t\t// Deserialize a standard representation\n\t\t\t\t\ttag = ( rtagName.exec( elem ) || [\"\", \"\"] )[ 1 ].toLowerCase();\n\t\t\t\t\twrap = wrapMap[ tag ] || wrapMap._default;\n\t\t\t\t\ttmp.innerHTML = wrap[ 1 ] + elem.replace( rxhtmlTag, \"<$1></$2>\" ) + wrap[ 2 ];\n\n\t\t\t\t\t// Descend through wrappers to the right content\n\t\t\t\t\tj = wrap[ 0 ];\n\t\t\t\t\twhile ( j-- ) {\n\t\t\t\t\t\ttmp = tmp.lastChild;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Support: QtWebKit\n\t\t\t\t\t// jQuery.merge because core_push.apply(_, arraylike) throws\n\t\t\t\t\tjQuery.merge( nodes, tmp.childNodes );\n\n\t\t\t\t\t// Remember the top-level container\n\t\t\t\t\ttmp = fragment.firstChild;\n\n\t\t\t\t\t// Fixes #12346\n\t\t\t\t\t// Support: Webkit, IE\n\t\t\t\t\ttmp.textContent = \"\";\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Remove wrapper from fragment\n\t\tfragment.textContent = \"\";\n\n\t\ti = 0;\n\t\twhile ( (elem = nodes[ i++ ]) ) {\n\n\t\t\t// #4087 - If origin and destination elements are the same, and this is\n\t\t\t// that element, do not do anything\n\t\t\tif ( selection && jQuery.inArray( elem, selection ) !== -1 ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tcontains = jQuery.contains( elem.ownerDocument, elem );\n\n\t\t\t// Append to fragment\n\t\t\ttmp = getAll( fragment.appendChild( elem ), \"script\" );\n\n\t\t\t// Preserve script evaluation history\n\t\t\tif ( contains ) {\n\t\t\t\tsetGlobalEval( tmp );\n\t\t\t}\n\n\t\t\t// Capture executables\n\t\t\tif ( scripts ) {\n\t\t\t\tj = 0;\n\t\t\t\twhile ( (elem = tmp[ j++ ]) ) {\n\t\t\t\t\tif ( rscriptType.test( elem.type || \"\" ) ) {\n\t\t\t\t\t\tscripts.push( elem );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn fragment;\n\t},\n\n\tcleanData: function( elems ) {\n\t\tvar data, elem, events, type, key, j,\n\t\t\tspecial = jQuery.event.special,\n\t\t\ti = 0;\n\n\t\tfor ( ; (elem = elems[ i ]) !== undefined; i++ ) {\n\t\t\tif ( Data.accepts( elem ) ) {\n\t\t\t\tkey = elem[ data_priv.expando ];\n\n\t\t\t\tif ( key && (data = data_priv.cache[ key ]) ) {\n\t\t\t\t\tevents = Object.keys( data.events || {} );\n\t\t\t\t\tif ( events.length ) {\n\t\t\t\t\t\tfor ( j = 0; (type = events[j]) !== undefined; j++ ) {\n\t\t\t\t\t\t\tif ( special[ type ] ) {\n\t\t\t\t\t\t\t\tjQuery.event.remove( elem, type );\n\n\t\t\t\t\t\t\t// This is a shortcut to avoid jQuery.event.remove's overhead\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tjQuery.removeEvent( elem, type, data.handle );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif ( data_priv.cache[ key ] ) {\n\t\t\t\t\t\t// Discard any remaining `private` data\n\t\t\t\t\t\tdelete data_priv.cache[ key ];\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t// Discard any remaining `user` data\n\t\t\tdelete data_user.cache[ elem[ data_user.expando ] ];\n\t\t}\n\t},\n\n\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});\n\n// Support: 1.x compatibility\n// Manipulating tables requires a tbody\nfunction manipulationTarget( elem, content ) {\n\treturn jQuery.nodeName( elem, \"table\" ) &&\n\t\tjQuery.nodeName( content.nodeType === 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 = (elem.getAttribute(\"type\") !== null) + \"/\" + elem.type;\n\treturn elem;\n}\nfunction restoreScript( elem ) {\n\tvar match = rscriptTypeMasked.exec( elem.type );\n\n\tif ( match ) {\n\t\telem.type = match[ 1 ];\n\t} else {\n\t\telem.removeAttribute(\"type\");\n\t}\n\n\treturn elem;\n}\n\n// Mark scripts as having already been evaluated\nfunction setGlobalEval( elems, refElements ) {\n\tvar l = elems.length,\n\t\ti = 0;\n\n\tfor ( ; i < l; i++ ) {\n\t\tdata_priv.set(\n\t\t\telems[ i ], \"globalEval\", !refElements || data_priv.get( refElements[ i ], \"globalEval\" )\n\t\t);\n\t}\n}\n\nfunction cloneCopyEvent( src, dest ) {\n\tvar i, l, type, pdataOld, pdataCur, udataOld, udataCur, events;\n\n\tif ( dest.nodeType !== 1 ) {\n\t\treturn;\n\t}\n\n\t// 1. Copy private data: events, handlers, etc.\n\tif ( data_priv.hasData( src ) ) {\n\t\tpdataOld = data_priv.access( src );\n\t\tpdataCur = data_priv.set( dest, pdataOld );\n\t\tevents = pdataOld.events;\n\n\t\tif ( events ) {\n\t\t\tdelete pdataCur.handle;\n\t\t\tpdataCur.events = {};\n\n\t\t\tfor ( type in events ) {\n\t\t\t\tfor ( i = 0, l = events[ type ].length; i < l; i++ ) {\n\t\t\t\t\tjQuery.event.add( dest, type, events[ type ][ i ] );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// 2. Copy user data\n\tif ( data_user.hasData( src ) ) {\n\t\tudataOld = data_user.access( src );\n\t\tudataCur = jQuery.extend( {}, udataOld );\n\n\t\tdata_user.set( dest, udataCur );\n\t}\n}\n\n\nfunction getAll( context, tag ) {\n\tvar ret = context.getElementsByTagName ? context.getElementsByTagName( tag || \"*\" ) :\n\t\t\tcontext.querySelectorAll ? context.querySelectorAll( tag || \"*\" ) :\n\t\t\t[];\n\n\treturn tag === undefined || tag && jQuery.nodeName( context, tag ) ?\n\t\tjQuery.merge( [ context ], ret ) :\n\t\tret;\n}\n\n// Support: IE >= 9\nfunction fixInput( src, dest ) {\n\tvar nodeName = dest.nodeName.toLowerCase();\n\n\t// Fails to persist the checked state of a cloned checkbox or radio button.\n\tif ( nodeName === \"input\" && manipulation_rcheckableType.test( src.type ) ) {\n\t\tdest.checked = src.checked;\n\n\t// Fails to return the selected option to the default selected state when cloning options\n\t} else if ( nodeName === \"input\" || nodeName === \"textarea\" ) {\n\t\tdest.defaultValue = src.defaultValue;\n\t}\n}\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/jquery/src/offset.js",
    "content": "jQuery.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\telem = this[ 0 ],\n\t\tbox = { top: 0, left: 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.clientTop,\n\t\tleft: box.left + win.pageXOffset - docElem.clientLeft\n\t};\n};\n\njQuery.offset = {\n\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\" ) && ( curCSSTop + curCSSLeft ).indexOf(\"auto\") > -1;\n\n\t\t// Need to be able to calculate position if either top or left is auto and position is either absolute or fixed\n\t\tif ( calculatePosition ) {\n\t\t\tcurPosition = curElem.position();\n\t\t\tcurTop = curPosition.top;\n\t\t\tcurLeft = curPosition.left;\n\n\t\t} else {\n\t\t\tcurTop = parseFloat( curCSSTop ) || 0;\n\t\t\tcurLeft = parseFloat( curCSSLeft ) || 0;\n\t\t}\n\n\t\tif ( jQuery.isFunction( options ) ) {\n\t\t\toptions = options.call( elem, i, curOffset );\n\t\t}\n\n\t\tif ( options.top != null ) {\n\t\t\tprops.top = ( options.top - curOffset.top ) + curTop;\n\t\t}\n\t\tif ( options.left != null ) {\n\t\t\tprops.left = ( options.left - curOffset.left ) + curLeft;\n\t\t}\n\n\t\tif ( \"using\" in options ) {\n\t\t\toptions.using.call( elem, props );\n\n\t\t} else {\n\t\t\tcurElem.css( props );\n\t\t}\n\t}\n};\n\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\telem = this[ 0 ],\n\t\t\tparentOffset = { top: 0, left: 0 };\n\n\t\t// Fixed elements are offset from window (parentOffset = {top:0, left: 0}, because it is 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\n\t\t} else {\n\t\t\t// Get *real* offsetParent\n\t\t\toffsetParent = this.offsetParent();\n\n\t\t\t// Get correct offsets\n\t\t\toffset = this.offset();\n\t\t\tif ( !jQuery.nodeName( offsetParent[ 0 ], \"html\" ) ) {\n\t\t\t\tparentOffset = offsetParent.offset();\n\t\t\t}\n\n\t\t\t// Add offsetParent borders\n\t\t\tparentOffset.top += jQuery.css( offsetParent[ 0 ], \"borderTopWidth\", true );\n\t\t\tparentOffset.left += jQuery.css( offsetParent[ 0 ], \"borderLeftWidth\", true );\n\t\t}\n\n\t\t// Subtract parent offsets and element margins\n\t\treturn {\n\t\t\ttop: offset.top - parentOffset.top - jQuery.css( elem, \"marginTop\", true ),\n\t\t\tleft: offset.left - parentOffset.left - jQuery.css( elem, \"marginLeft\", true )\n\t\t};\n\t},\n\n\toffsetParent: function() {\n\t\treturn this.map(function() {\n\t\t\tvar offsetParent = this.offsetParent || docElem;\n\n\t\t\twhile ( offsetParent && ( !jQuery.nodeName( offsetParent, \"html\" ) && jQuery.css( offsetParent, \"position\") === \"static\" ) ) {\n\t\t\t\toffsetParent = offsetParent.offsetParent;\n\t\t\t}\n\n\t\t\treturn offsetParent || docElem;\n\t\t});\n\t}\n});\n\n\n// Create scrollLeft and scrollTop methods\njQuery.each( {scrollLeft: \"pageXOffset\", scrollTop: \"pageYOffset\"}, function( method, prop ) {\n\tvar top = \"pageYOffset\" === prop;\n\n\tjQuery.fn[ method ] = function( val ) {\n\t\treturn 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 ? win[ prop ] : elem[ method ];\n\t\t\t}\n\n\t\t\tif ( win ) {\n\t\t\t\twin.scrollTo(\n\t\t\t\t\t!top ? val : window.pageXOffset,\n\t\t\t\t\ttop ? val : window.pageYOffset\n\t\t\t\t);\n\n\t\t\t} else {\n\t\t\t\telem[ method ] = val;\n\t\t\t}\n\t\t}, method, val, arguments.length, null );\n\t};\n});\n\nfunction getWindow( elem ) {\n\treturn jQuery.isWindow( elem ) ? elem : elem.nodeType === 9 && elem.defaultView;\n}\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/jquery/src/outro.js",
    "content": "\n})( window );\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/jquery/src/queue.js",
    "content": "jQuery.extend({\n\tqueue: function( elem, type, data ) {\n\t\tvar queue;\n\n\t\tif ( elem ) {\n\t\t\ttype = ( type || \"fx\" ) + \"queue\";\n\t\t\tqueue = data_priv.get( elem, type );\n\n\t\t\t// Speed up dequeue by getting out quickly if this is just a lookup\n\t\t\tif ( data ) {\n\t\t\t\tif ( !queue || jQuery.isArray( data ) ) {\n\t\t\t\t\tqueue = data_priv.access( elem, type, jQuery.makeArray(data) );\n\t\t\t\t} else {\n\t\t\t\t\tqueue.push( data );\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn queue || [];\n\t\t}\n\t},\n\n\tdequeue: function( elem, type ) {\n\t\ttype = type || \"fx\";\n\n\t\tvar queue = jQuery.queue( elem, type ),\n\t\t\tstartLength = queue.length,\n\t\t\tfn = queue.shift(),\n\t\t\thooks = jQuery._queueHooks( elem, type ),\n\t\t\tnext = function() {\n\t\t\t\tjQuery.dequeue( elem, type );\n\t\t\t};\n\n\t\t// If the fx queue is dequeued, always remove the progress sentinel\n\t\tif ( fn === \"inprogress\" ) {\n\t\t\tfn = queue.shift();\n\t\t\tstartLength--;\n\t\t}\n\n\t\tif ( fn ) {\n\n\t\t\t// Add a progress sentinel to prevent the fx queue from being\n\t\t\t// automatically dequeued\n\t\t\tif ( type === \"fx\" ) {\n\t\t\t\tqueue.unshift( \"inprogress\" );\n\t\t\t}\n\n\t\t\t// clear up the last queue stop function\n\t\t\tdelete hooks.stop;\n\t\t\tfn.call( elem, next, hooks );\n\t\t}\n\n\t\tif ( !startLength && hooks ) {\n\t\t\thooks.empty.fire();\n\t\t}\n\t},\n\n\t// not 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 data_priv.get( elem, key ) || data_priv.access( elem, key, {\n\t\t\tempty: jQuery.Callbacks(\"once memory\").add(function() {\n\t\t\t\tdata_priv.remove( elem, [ type + \"queue\", key ] );\n\t\t\t})\n\t\t});\n\t}\n});\n\njQuery.fn.extend({\n\tqueue: function( type, data ) {\n\t\tvar setter = 2;\n\n\t\tif ( typeof type !== \"string\" ) {\n\t\t\tdata = type;\n\t\t\ttype = \"fx\";\n\t\t\tsetter--;\n\t\t}\n\n\t\tif ( arguments.length < setter ) {\n\t\t\treturn jQuery.queue( this[0], type );\n\t\t}\n\n\t\treturn data === undefined ?\n\t\t\tthis :\n\t\t\tthis.each(function() {\n\t\t\t\tvar queue = jQuery.queue( this, type, data );\n\n\t\t\t\t// ensure a hooks for this queue\n\t\t\t\tjQuery._queueHooks( this, type );\n\n\t\t\t\tif ( type === \"fx\" && queue[0] !== \"inprogress\" ) {\n\t\t\t\t\tjQuery.dequeue( this, type );\n\t\t\t\t}\n\t\t\t});\n\t},\n\tdequeue: function( type ) {\n\t\treturn this.each(function() {\n\t\t\tjQuery.dequeue( this, type );\n\t\t});\n\t},\n\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 = data_priv.get( elements[ i ], type + \"queueHooks\" );\n\t\t\tif ( tmp && tmp.empty ) {\n\t\t\t\tcount++;\n\t\t\t\ttmp.empty.add( resolve );\n\t\t\t}\n\t\t}\n\t\tresolve();\n\t\treturn defer.promise( obj );\n\t}\n});\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/jquery/src/selector-native.js",
    "content": "/*\n * Optional (non-Sizzle) selector module for custom builds.\n *\n * Note that this DOES NOT SUPPORT many documented jQuery\n * features in exchange for its smaller size:\n *\n * Attribute not equal selector\n * Positional selectors (:first; :eq(n); :odd; etc.)\n * Type selectors (:input; :checkbox; :button; etc.)\n * State-based selectors (:animated; :visible; :hidden; etc.)\n * :has(selector)\n * :not(complex selector)\n * custom selectors via Sizzle extensions\n * Leading combinators (e.g., $collection.find(\"> *\"))\n * Reliable functionality on XML fragments\n * Requiring all parts of a selector to match elements under context\n *   (e.g., $div.find(\"div > *\") now matches children of $div)\n * Matching against non-elements\n * Reliable sorting of disconnected nodes\n * querySelectorAll bug fixes (e.g., unreliable :focus on WebKit)\n *\n * If any of these are unacceptable tradeoffs, either use Sizzle or\n * customize this stub for the project's specific needs.\n */\n\nvar selector_hasDuplicate,\n\tmatches = docElem.webkitMatchesSelector ||\n\t\tdocElem.mozMatchesSelector ||\n\t\tdocElem.oMatchesSelector ||\n\t\tdocElem.msMatchesSelector,\n\tselector_sortOrder = function( a, b ) {\n\t\t// Flag for duplicate removal\n\t\tif ( a === b ) {\n\t\t\tselector_hasDuplicate = 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\n\t\t\t\t// Choose the first element that is related to our document\n\t\t\t\tif ( a === document || jQuery.contains(document, a) ) {\n\t\t\t\t\treturn -1;\n\t\t\t\t}\n\t\t\t\tif ( b === document || jQuery.contains(document, 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 0;\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\njQuery.extend({\n\tfind: function( selector, context, results, seed ) {\n\t\tvar elem, nodeType,\n\t\t\ti = 0;\n\n\t\tresults = results || [];\n\t\tcontext = context || document;\n\n\t\t// Same basic safeguard as Sizzle\n\t\tif ( !selector || typeof selector !== \"string\" ) {\n\t\t\treturn results;\n\t\t}\n\n\t\t// Early return if context is not an element or document\n\t\tif ( (nodeType = context.nodeType) !== 1 && nodeType !== 9 ) {\n\t\t\treturn [];\n\t\t}\n\n\t\tif ( seed ) {\n\t\t\twhile ( (elem = seed[i++]) ) {\n\t\t\t\tif ( jQuery.find.matchesSelector(elem, selector) ) {\n\t\t\t\t\tresults.push( elem );\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tjQuery.merge( results, context.querySelectorAll(selector) );\n\t\t}\n\n\t\treturn results;\n\t},\n\tunique: function( results ) {\n\t\tvar elem,\n\t\t\tduplicates = [],\n\t\t\ti = 0,\n\t\t\tj = 0;\n\n\t\tselector_hasDuplicate = false;\n\t\tresults.sort( selector_sortOrder );\n\n\t\tif ( selector_hasDuplicate ) {\n\t\t\twhile ( (elem = results[i++]) ) {\n\t\t\t\tif ( elem === results[ i ] ) {\n\t\t\t\t\tj = duplicates.push( i );\n\t\t\t\t}\n\t\t\t}\n\t\t\twhile ( j-- ) {\n\t\t\t\tresults.splice( duplicates[ j ], 1 );\n\t\t\t}\n\t\t}\n\n\t\treturn results;\n\t},\n\ttext: function( elem ) {\n\t\tvar node,\n\t\t\tret = \"\",\n\t\t\ti = 0,\n\t\t\tnodeType = elem.nodeType;\n\n\t\tif ( !nodeType ) {\n\t\t\t// If no nodeType, this is expected to be an array\n\t\t\twhile ( (node = elem[i++]) ) {\n\t\t\t\t// Do not traverse comment nodes\n\t\t\t\tret += jQuery.text( node );\n\t\t\t}\n\t\t} else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) {\n\t\t\t// Use textContent for elements\n\t\t\treturn elem.textContent;\n\t\t} else if ( nodeType === 3 || nodeType === 4 ) {\n\t\t\treturn elem.nodeValue;\n\t\t}\n\t\t// Do not include comment or processing instruction nodes\n\n\t\treturn ret;\n\t},\n\tcontains: function( a, b ) {\n\t\tvar adown = a.nodeType === 9 ? a.documentElement : a,\n\t\t\tbup = b && b.parentNode;\n\t\treturn a === bup || !!( bup && bup.nodeType === 1 && adown.contains(bup) );\n\t},\n\tisXMLDoc: function( elem ) {\n\t\treturn (elem.ownerDocument || elem).documentElement.nodeName !== \"HTML\";\n\t},\n\texpr: {\n\t\tattrHandle: {},\n\t\tmatch: {\n\t\t\tbool: /^(?:checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped)$/i,\n\t\t\tneedsContext: /^[\\x20\\t\\r\\n\\f]*[>+~]/\n\t\t}\n\t}\n});\n\njQuery.extend( jQuery.find, {\n\tmatches: function( expr, elements ) {\n\t\treturn jQuery.find( expr, null, null, elements );\n\t},\n\tmatchesSelector: function( elem, expr ) {\n\t\treturn matches.call( elem, expr );\n\t},\n\tattr: function( elem, name ) {\n\t\treturn elem.getAttribute( name );\n\t}\n});\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/jquery/src/serialize.js",
    "content": "var 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}\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/jquery/src/sizzle-jquery.js",
    "content": "jQuery.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"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/jquery/src/support.js",
    "content": "jQuery.support = (function( support ) {\n\tvar input = document.createElement(\"input\"),\n\t\tfragment = document.createDocumentFragment(),\n\t\tdiv = document.createElement(\"div\"),\n\t\tselect = document.createElement(\"select\"),\n\t\topt = select.appendChild( document.createElement(\"option\") );\n\n\t// Finish early in limited environments\n\tif ( !input.type ) {\n\t\treturn support;\n\t}\n\n\tinput.type = \"checkbox\";\n\n\t// Support: Safari 5.1, iOS 5.1, Android 4.x, Android 2.3\n\t// Check the default checkbox/radio value (\"\" on old WebKit; \"on\" elsewhere)\n\tsupport.checkOn = input.value !== \"\";\n\n\t// Must access the parent to make an option select properly\n\t// Support: IE9, IE10\n\tsupport.optSelected = opt.selected;\n\n\t// Will be defined later\n\tsupport.reliableMarginRight = true;\n\tsupport.boxSizingReliable = true;\n\tsupport.pixelPosition = false;\n\n\t// Make sure checked status is properly cloned\n\t// Support: IE9, IE10\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// Check if an input maintains its value after becoming a radio\n\t// Support: IE9, IE10\n\tinput = document.createElement(\"input\");\n\tinput.value = \"t\";\n\tinput.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.appendChild( input );\n\n\t// Support: Safari 5.1, Android 4.x, Android 2.3\n\t// old WebKit doesn't clone checked state correctly in fragments\n\tsupport.checkClone = fragment.cloneNode( true ).cloneNode( true ).lastChild.checked;\n\n\t// Support: Firefox, Chrome, Safari\n\t// Beware of CSP restrictions (https://developer.mozilla.org/en/Security/CSP)\n\tsupport.focusinBubbles = \"onfocusin\" in window;\n\n\tdiv.style.backgroundClip = \"content-box\";\n\tdiv.cloneNode( true ).style.backgroundClip = \"\";\n\tsupport.clearCloneStyle = div.style.backgroundClip === \"content-box\";\n\n\t// Run tests that need a body at doc ready\n\tjQuery(function() {\n\t\tvar container, marginDiv,\n\t\t\t// Support: Firefox, Android 2.3 (Prefixed box-sizing versions).\n\t\t\tdivReset = \"padding:0;margin:0;border:0;display:block;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;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\t// Check box-sizing and margin behavior.\n\t\tbody.appendChild( container ).appendChild( div );\n\t\tdiv.innerHTML = \"\";\n\t\t// Support: Firefox, Android 2.3 (Prefixed box-sizing versions).\n\t\tdiv.style.cssText = \"-webkit-box-sizing:border-box;-moz-box-sizing:border-box;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// Support: Android 2.3\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// 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\tbody.removeChild( container );\n\t});\n\n\treturn support;\n})( {} );\n\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/jquery/src/traversing.js",
    "content": "var 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 targets = jQuery( target, this ),\n\t\t\tl = targets.length;\n\n\t\treturn this.filter(function() {\n\t\t\tvar i = 0;\n\t\t\tfor ( ; i < l; i++ ) {\n\t\t\t\tif ( jQuery.contains( this, targets[i] ) ) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t},\n\n\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\tmatched = [],\n\t\t\tpos = ( rneedsContext.test( selectors ) || typeof selectors !== \"string\" ) ?\n\t\t\t\tjQuery( selectors, context || this.context ) :\n\t\t\t\t0;\n\n\t\tfor ( ; i < l; i++ ) {\n\t\t\tfor ( cur = this[i]; cur && cur !== context; cur = cur.parentNode ) {\n\t\t\t\t// Always skip document fragments\n\t\t\t\tif ( cur.nodeType < 11 && (pos ?\n\t\t\t\t\tpos.index(cur) > -1 :\n\n\t\t\t\t\t// Don't pass non-elements to Sizzle\n\t\t\t\t\tcur.nodeType === 1 &&\n\t\t\t\t\t\tjQuery.find.matchesSelector(cur, selectors)) ) {\n\n\t\t\t\t\tcur = matched.push( cur );\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn this.pushStack( matched.length > 1 ? jQuery.unique( matched ) : matched );\n\t},\n\n\t// Determine the position of an element within\n\t// the matched set of elements\n\tindex: function( elem ) {\n\n\t\t// No argument, return index in parent\n\t\tif ( !elem ) {\n\t\t\treturn ( this[ 0 ] && this[ 0 ].parentNode ) ? this.first().prevAll().length : -1;\n\t\t}\n\n\t\t// index in selector\n\t\tif ( typeof elem === \"string\" ) {\n\t\t\treturn core_indexOf.call( jQuery( elem ), this[ 0 ] );\n\t\t}\n\n\t\t// Locate the position of the desired element\n\t\treturn core_indexOf.call( this,\n\n\t\t\t// If it receives a jQuery object, the first element is used\n\t\t\telem.jquery ? elem[ 0 ] : elem\n\t\t);\n\t},\n\n\tadd: function( selector, context ) {\n\t\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\twhile ( (cur = cur[dir]) && 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 elem.contentDocument || jQuery.merge( [], elem.childNodes );\n\t}\n}, function( name, fn ) {\n\tjQuery.fn[ name ] = function( until, selector ) {\n\t\tvar matched = jQuery.map( this, fn, until );\n\n\t\tif ( name.slice( -5 ) !== \"Until\" ) {\n\t\t\tselector = until;\n\t\t}\n\n\t\tif ( selector && typeof selector === \"string\" ) {\n\t\t\tmatched = jQuery.filter( selector, matched );\n\t\t}\n\n\t\tif ( this.length > 1 ) {\n\t\t\t// Remove duplicates\n\t\t\tif ( !guaranteedUnique[ name ] ) {\n\t\t\t\tjQuery.unique( matched );\n\t\t\t}\n\n\t\t\t// Reverse order for parents* and prev-derivatives\n\t\t\tif ( rparentsprev.test( name ) ) {\n\t\t\t\tmatched.reverse();\n\t\t\t}\n\t\t}\n\n\t\treturn this.pushStack( matched );\n\t};\n});\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\ttruncate = until !== undefined;\n\n\t\twhile ( (elem = elem[ dir ]) && elem.nodeType !== 9 ) {\n\t\t\tif ( elem.nodeType === 1 ) {\n\t\t\t\tif ( truncate && jQuery( elem ).is( until ) ) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tmatched.push( elem );\n\t\t\t}\n\t\t}\n\t\treturn matched;\n\t},\n\n\tsibling: function( n, elem ) {\n\t\tvar matched = [];\n\n\t\tfor ( ; n; n = n.nextSibling ) {\n\t\t\tif ( n.nodeType === 1 && n !== elem ) {\n\t\t\t\tmatched.push( n );\n\t\t\t}\n\t\t}\n\n\t\treturn matched;\n\t}\n});\n\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 ( core_indexOf.call( qualifier, elem ) >= 0 ) !== not;\n\t});\n}\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/jquery/src/wrap.js",
    "content": "jQuery.fn.extend({\n\twrapAll: function( html ) {\n\t\tvar wrap;\n\n\t\tif ( jQuery.isFunction( html ) ) {\n\t\t\treturn this.each(function( i ) {\n\t\t\t\tjQuery( this ).wrapAll( html.call(this, i) );\n\t\t\t});\n\t\t}\n\n\t\tif ( this[ 0 ] ) {\n\n\t\t\t// The elements to wrap the target around\n\t\t\twrap = jQuery( html, this[ 0 ].ownerDocument ).eq( 0 ).clone( true );\n\n\t\t\tif ( this[ 0 ].parentNode ) {\n\t\t\t\twrap.insertBefore( this[ 0 ] );\n\t\t\t}\n\n\t\t\twrap.map(function() {\n\t\t\t\tvar elem = this;\n\n\t\t\t\twhile ( elem.firstElementChild ) {\n\t\t\t\t\telem = elem.firstElementChild;\n\t\t\t\t}\n\n\t\t\t\treturn elem;\n\t\t\t}).append( this );\n\t\t}\n\n\t\treturn this;\n\t},\n\n\twrapInner: function( html ) {\n\t\tif ( jQuery.isFunction( html ) ) {\n\t\t\treturn this.each(function( i ) {\n\t\t\t\tjQuery( this ).wrapInner( html.call(this, i) );\n\t\t\t});\n\t\t}\n\n\t\treturn this.each(function() {\n\t\t\tvar self = jQuery( this ),\n\t\t\t\tcontents = self.contents();\n\n\t\t\tif ( contents.length ) {\n\t\t\t\tcontents.wrapAll( html );\n\n\t\t\t} else {\n\t\t\t\tself.append( html );\n\t\t\t}\n\t\t});\n\t},\n\n\twrap: function( html ) {\n\t\tvar isFunction = jQuery.isFunction( html );\n\n\t\treturn this.each(function( i ) {\n\t\t\tjQuery( this ).wrapAll( isFunction ? html.call(this, i) : html );\n\t\t});\n\t},\n\n\tunwrap: function() {\n\t\treturn this.parent().each(function() {\n\t\t\tif ( !jQuery.nodeName( this, \"body\" ) ) {\n\t\t\t\tjQuery( this ).replaceWith( this.childNodes );\n\t\t\t}\n\t\t}).end();\n\t}\n});\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/jquery/test/.jshintignore",
    "content": "qunit/\ndata/badjson.js\ndata/jquery-1.9.1.ajax_xhr.min.js\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/jquery/test/.jshintrc",
    "content": "{\n\t\"boss\": true,\n\t\"curly\": true,\n\t\"eqeqeq\": true,\n\t\"eqnull\": true,\n\t\"expr\": true,\n\t\"immed\": true,\n\t\"noarg\": true,\n\t\"onevar\": true,\n\t\"quotmark\": \"double\",\n\t\"smarttabs\": true,\n\t\"trailing\": true,\n\t\"undef\": true,\n\t\"unused\": true,\n\n\t\"evil\": true,\n\t\"sub\": true,\n\n\t\"browser\": true,\n\t\"devel\": true,\n\t\"wsh\": true,\n\n\t\"globals\": {\n\t\t\"DOMParser\": true,\n\t\t\"jQuery\": true,\n\t\t\"QUnit\": true,\n\t\t\"module\": true,\n\t\t\"ok\": true,\n\t\t\"equal\": true,\n\t\t\"test\": true,\n\t\t\"asyncTest\": true,\n\t\t\"notEqual\": true,\n\t\t\"deepEqual\": true,\n\t\t\"strictEqual\": true,\n\t\t\"notStrictEqual\": true,\n\t\t\"start\": true,\n\t\t\"stop\": true,\n\t\t\"expect\": true,\n\t\t\"raises\": true,\n\t\t\"ajaxTest\": true,\n\t\t\"testIframe\": true,\n\t\t\"testIframeWithCallback\": true,\n\t\t\"createDashboardXML\": true,\n\t\t\"createXMLFragment\": true,\n\t\t\"moduleTeardown\": true,\n\t\t\"testFoo\": true,\n\t\t\"url\": true,\n\t\t\"t\": true,\n\t\t\"q\": true,\n\t\t\"amdDefined\": true,\n\t\t\"fireNative\": true,\n\t\t\"Globals\": true,\n\t\t\"hasPHP\": true,\n\t\t\"isLocal\": true,\n\t\t\"originaljQuery\": true,\n\t\t\"$\": true,\n\t\t\"original$\": true,\n\t\t\"externalHost\": true\n\t}\n}\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/jquery/test/data/ajax/unreleasedXHR.html",
    "content": "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n<html>\n<head>\n<meta http-equiv=\"content-type\" content=\"text/html; charset=utf-8\">\n<title>Attempt to block tests because of dangling XHR requests (IE)</title>\n<script src=\"../../jquery.js\"></script>\n<script type=\"text/javascript\">\nwindow.onunload = function() {};\njQuery(function() {\n\tsetTimeout(function() {\n\t\tvar parent = window.parent;\n\t\tdocument.write(\"\");\n\t\tparent.iframeCallback();\n\t}, 200 );\n\tvar number = 50;\n\twhile( number-- ) {\n\t\tjQuery.ajax(\"../name.php?wait=600\");\n\t}\n});\n</script>\n</head>\n<body>\n<!-- empty body -->\n</body>\n</html>\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/jquery/test/data/atom+xml.php",
    "content": "<?php header(\"Content-type: atom+xml\") ?>\n<root>\n\t<element />\n</root>"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/jquery/test/data/badcall.js",
    "content": "undefined();\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/jquery/test/data/badjson.js",
    "content": "{bad: toTheBone}\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/jquery/test/data/cleanScript.html",
    "content": "<script>\n<!--\nok( true, \"script within html comments executed\" );\n-->\n</script>\n<script>\n<![CDATA[\nok( true, \"script within CDATA executed\" );\n]]>\n</script>\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/jquery/test/data/core/cc_on.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">\n\t<script>\n\t\tvar cc_on = false,\n\t\t\terrors = [];\n/*@cc_on\n\t\tcc_on = true;\n@*/\n\t\twindow.onerror = function( errorMessage, filePath, lineNumber ) {\n\t\t\terrors.push( errorMessage );\n\t\t};\n\t</script>\n\t<script src=\"../../jquery.js\"></script>\n</head>\n<body>\n\t<script>\n\t\twindow.parent.iframeCallback( cc_on, errors, jQuery );\n\t</script>\n</body>\n</html>\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/jquery/test/data/core/dont_return.php",
    "content": "<?php\nsleep(10000);\n?>\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/jquery/test/data/core/dynamic_ready.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n\t<meta charset=\"utf-8\">\n\t<script src=\"../../jquery.js\"></script>\n\t<script>var $j = jQuery.noConflict();</script>\n</head>\n<body>\n<iframe id=\"dont_return\" src=\"dont_return.php\"></iframe>\n<script>\n\tvar timeoutId, $,\n\t\ttimeoutFired = false;\n\n\tsetTimeout(function () {\n\t\t// Load another jQuery copy using the first one.\n\t\t$j.getScript( \"../../../dist/jquery.js\", function () {\n\t\t\t$j( \"#dont_return\" ).attr( \"src\", \"about:blank\" );\n\n\t\t\t// document ready handled by the just-loaded jQuery copy.\n\t\t\t$(function () {\n\t\t\t\tclearTimeout( timeoutId );\n\t\t\t\tif ( !timeoutFired ) {\n\t\t\t\t\twindow.parent.iframeCallback( true );\n\t\t\t\t}\n\t\t\t});\n\t\t});\n\n\t\ttimeoutId = setTimeout(function () {\n\t\t\ttimeoutFired = true;\n\t\t\twindow.parent.iframeCallback( false );\n\t\t}, 3000);\n\t});\n</script>\n</body>\n</html>\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/jquery/test/data/dashboard.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<dashboard>\n\t<locations class=\"foo\">\n\t\t<location for=\"bar\" checked=\"different\">\n\t\t\t<infowindowtab>\n\t\t\t\t<tab title=\"Location\"><![CDATA[blabla]]></tab>\n\t\t\t\t<tab title=\"Users\"><![CDATA[blublu]]></tab>\n\t\t\t</infowindowtab>\n\t\t</location>\n\t</locations>\n</dashboard>\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/jquery/test/data/dimensions/documentLarge.html",
    "content": "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\" dir=\"ltr\" id=\"html\">\n<head>\n\t<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />\n\t<style>\n\t\tbody {\n\t\t\twidth: 1000px;\n\t\t\theight: 1000px;\n\t\t}\n\t</style>\n</head>\n<body>\n\t<div>\n\t\t<script src=\"../../jquery.js\"></script>\n\t</div>\n</body>\n</html>\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/jquery/test/data/dimensions/documentSmall.html",
    "content": "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\" dir=\"ltr\" id=\"html\">\n<head>\n\t<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />\n\t<style>\n\t\thtml {\n\t\t\t/**\n\t\t\t * we need to null out border-width, because it causes bug #3838\n\t\t\t * and until we drop IE6, this test will fail in IE6 if we didn't\n\t\t\t * special case this situation.\n\t\t\t **/\n\t\t\tborder-width: 0;\n\t\t}\n\t</style>\n</head>\n<body>\n\t<div>\n\t\t<script src=\"../../jquery.js\"></script>\n\t</div>\n</body>\n</html>\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/jquery/test/data/echoData.php",
    "content": "<?php echo file_get_contents('php://input'); ?>\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/jquery/test/data/echoQuery.php",
    "content": "<?php echo $_SERVER['QUERY_STRING']; ?>"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/jquery/test/data/errorWithJSON.php",
    "content": "<?php\n\nheader(\"HTTP/1.0 400 Bad Request\");\nheader(\"Content-Type: application/json\");\n\necho '{ \"code\": 40, \"message\": \"Bad Request\" }';"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/jquery/test/data/errorWithText.php",
    "content": "<?php\n\nheader(\"HTTP/1.0 400 Bad Request\");\n\necho \"plain text message\";"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/jquery/test/data/etag.php",
    "content": "<?php\nerror_reporting(0);\n\n$ts = $_REQUEST['ts'];\n$etag = md5($ts);\n\n$ifNoneMatch = isset($_SERVER['HTTP_IF_NONE_MATCH']) ? stripslashes($_SERVER['HTTP_IF_NONE_MATCH']) : false;\nif ($ifNoneMatch == $etag) {\n\theader('HTTP/1.0 304 Not Modified');\n\tdie; // stop processing\n}\n\nheader(\"Etag: \" . $etag);\n\nif ( $ifNoneMatch ) {\n\techo \"OK: \" . $etag;\n} else {\n\techo \"FAIL\";\n}\n\n?>\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/jquery/test/data/evalScript.php",
    "content": "ok( \"<?php echo $_SERVER['REQUEST_METHOD'] ?>\" === \"GET\", \"request method is <?php echo $_SERVER['REQUEST_METHOD'] ?>\" );"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/jquery/test/data/event/focusElem.html",
    "content": "<!doctype html>\n<html>\n<head>\n\t<meta http-equiv=\"Content-type\" content=\"text/html; charset=utf-8\">\n\t<title>.focus() (activeElement access #13393)</title>\n\n\t<script src=\"../../jquery.js\"></script>\n</head>\n<body>\n\t<a href=\"#\" id=\"frame-link\"></a>\n\t<script>\n\t\tjQuery(\"#frame-link\").focus();\n\t\twindow.parent.iframeCallback( true );\n\t</script>\n</body>\n</html>\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/jquery/test/data/event/longLoadScript.php",
    "content": "<?php\nsleep((int)$_GET['sleep']);\nheader('Content-type: text/javascript');\n?>"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/jquery/test/data/event/onbeforeunload.html",
    "content": "<!doctype html>\n<html>\n\t<script src=\"../../jquery.js\"></script>\n\t<script>\n\t\tfunction report( event ) {\n\t\t\tvar payload = {\n\t\t\t\tevent: event.type\n\t\t\t};\n\t\t\treturn parent.postMessage( JSON.stringify(payload), \"*\" );\n\t\t}\n\n\t\tjQuery( window ).on( \"beforeunload\", function( event ) {\n\t\t\treport( event );\n\t\t}).on( \"load\", function( event ) {\n\t\t\tsetTimeout(function() {\n\t\t\t\twindow.location.reload();\n\t\t\t}, 50);\n\t\t});\n\t</script>\n</html>\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/jquery/test/data/event/promiseReady.html",
    "content": "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n<html>\n<head>\n<meta http-equiv=\"content-type\" content=\"text/html; charset=utf-8\">\n<title>Test case for jQuery ticket #11470</title>\n<script src=\"../../jquery.js\"></script>\n<script type=\"text/javascript\">\njQuery.when( jQuery.ready ).done(function() {\n\tjQuery(\"body\").append(\"<div>modifying DOM</div>\");\n\twindow.parent.iframeCallback( $(\"div\").text() === \"modifying DOM\" );\n});\n</script>\n</head>\n<body>\n<!-- empty body -->\n</body>\n</html>\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/jquery/test/data/event/syncReady.html",
    "content": "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n<html>\n<head>\n<meta http-equiv=\"content-type\" content=\"text/html; charset=utf-8\">\n<title>Test case for jQuery ticket #10067</title>\n<script src=\"../../jquery.js\"></script>\n</head>\n<body>\n\n<script type=\"text/javascript\">\njQuery( document ).ready(function () {\n\twindow.parent.iframeCallback( jQuery('#container').length === 1 );\n});\n</script>\n\n<!-- external resources that come before elements trick\n\toldIE into thinking the dom is ready, but it's not...\n\tleaving this check here for future trailblazers to attempt\n\tfixing this...-->\n<script type=\"text/javascript\" src=\"longLoadScript.php?sleep=1\"></script>\n<div id=\"container\" style=\"height: 300px\"></div>\n</body>\n</html>\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/jquery/test/data/headers.php",
    "content": "<?php\n\nheader( \"Sample-Header: Hello World\" );\nheader( \"Empty-Header: \" );\nheader( \"Sample-Header2: Hello World 2\" );\n\n$headers = array();\n\nforeach( $_SERVER as $key => $value ) {\n\n\t$key = str_replace( \"_\" , \"-\" , substr( $key , 0 , 5 ) == \"HTTP_\" ? substr( $key , 5 ) : $key );\n\t$headers[ $key ] = $value;\n\n}\n\nforeach( explode( \"_\" , $_GET[ \"keys\" ] ) as $key ) {\n\techo \"$key: \" . @$headers[ strtoupper( $key ) ] . \"\\n\";\n}\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/jquery/test/data/if_modified_since.php",
    "content": "<?php\nerror_reporting(0);\n\n$ts = $_REQUEST['ts'];\n\n$ifModifiedSince = isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) ? stripslashes($_SERVER['HTTP_IF_MODIFIED_SINCE']) : false;\nif ($ifModifiedSince == $ts) {\n\theader('HTTP/1.0 304 Not Modified');\n\tdie; // stop processing\n}\n\nheader(\"Last-Modified: \" . $ts);\n\nif ( $ifModifiedSince ) {\n\techo \"OK: \" . $ts;\n} else {\n\techo \"FAIL\";\n}\n\n?>\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/jquery/test/data/iframe.html",
    "content": "<html>\n\t<head>\n\t\t<title>iframe</title>\n\t</head>\n\t<body>\n\t\t<div><span>span text</span></div>\n\t</body>\n</html>\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/jquery/test/data/json.php",
    "content": "<?php\nerror_reporting(0);\nif ( $_REQUEST['header'] ) {\n\theader(\"Content-type: application/json\");\n}\n\n$json = $_REQUEST['json'];\nif($json) {\n\techo '[ {\"name\": \"John\", \"age\": 21}, {\"name\": \"Peter\", \"age\": 25 } ]';\n} else {\n\techo '{ \"data\": {\"lang\": \"en\", \"length\": 25} }';\n}\n?>\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/jquery/test/data/json_obj.js",
    "content": "{ \"data\": {\"lang\": \"en\", \"length\": 25} }\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/jquery/test/data/jsonp.php",
    "content": "<?php\nerror_reporting(0);\n$callback = $_REQUEST['callback'];\nif ( ! $callback ) {\n\t$callback = explode(\"?\",end(explode(\"/\",$_SERVER['REQUEST_URI'])));\n\t$callback = $callback[0];\n}\n$json = $_REQUEST['json'];\nif($json) {\n\techo $callback . '([ {\"name\": \"John\", \"age\": 21}, {\"name\": \"Peter\", \"age\": 25 } ])';\n} else {\n\techo $callback . '({ \"data\": {\"lang\": \"en\", \"length\": 25} })';\n}\n?>\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/jquery/test/data/manipulation/iframe-denied.html",
    "content": "<!DOCTYPE html>\n<html>\n\t<head>\n\t\t<meta charset=utf-8 />\n\t\t<title>body</title>\n\t</head>\n\t<body>\n\t\t<div id=\"qunit-fixture\"></div>\n\t\t<script src=\"../../jquery.js\"></script>\n\t\t<script>\n\t\t\tvar script = document.getElementsByTagName( \"script\" )[ 0 ],\n\t\t\t\tdiv = document.createElement( \"div\" ),\n\t\t\t\tsrc = \"http://\" + window.parent.externalHost,\n\t\t\t\tsuccess = true,\n\t\t\t\terror = \"\";\n\n\t\t\tscript.parentNode.appendChild( div );\n\t\t\tdiv.innerHTML = \"<iframe name=\\\"test\\\" src=\\\"\" + src + \"\\\">\";\n\n\t\t\tjQuery(function() {\n\t\t\t\ttry {\n\t\t\t\t\tjQuery( \"<div>hello<div>world</div>!</div>\" ).appendTo( \"#qunit-fixture\" );\n\t\t\t\t} catch( e ) {\n\t\t\t\t\tsuccess = false;\n\t\t\t\t\terror = e;\n\t\t\t\t}\n\n\t\t\t\twindow.parent.iframeCallback({\n\t\t\t\t\tstatus: success,\n\t\t\t\t\tdescription: \"buildFragment sets the context without throwing an exception\" +\n\t\t\t\t\t\t( error ? \": \" + error : \"\" )\n\t\t\t\t});\n\t\t\t});\n\t\t</script>\n\t</body>\n</html>\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/jquery/test/data/name.html",
    "content": "ERROR <script type=\"text/javascript\">ok( true, \"name.html retrieved\" );</script>\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/jquery/test/data/name.php",
    "content": "<?php\nerror_reporting(0);\n$wait = $_REQUEST['wait'];\nif($wait) {\n\tsleep($wait);\n}\n$xml = $_REQUEST['xml'];\nif($xml) {\n\theader(\"Content-type: text/xml\");\n\t$result = ($xml == \"5-2\") ? \"3\" : \"?\";\n\techo \"<math><calculation>$xml</calculation><result>$result</result></math>\";\n\tdie();\n}\n$name = $_REQUEST['name'];\nif($name == 'foo') {\n\techo \"bar\";\n\tdie();\n} else if($name == 'peter') {\n\techo \"pan\";\n\tdie();\n}\n\necho 'ERROR <script type=\"text/javascript\">ok( true, \"name.php executed\" );</script>';\n?>"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/jquery/test/data/nocontent.php",
    "content": "<?php\n\nheader('HTTP/1.0 204 No Content');\n\n?>"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/jquery/test/data/offset/absolute.html",
    "content": "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\"\n\t\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n<html>\n\t<head>\n\t\t<meta http-equiv=\"Content-type\" content=\"text/html; charset=utf-8\">\n\t\t<title>absolute</title>\n\t\t<style type=\"text/css\" media=\"screen\">\n\t\t\tbody { margin: 1px; padding: 5px; }\n\t\t\tdiv.absolute { position: absolute; margin: 1px; border: 2px solid #000; padding: 5px; width: 100px; height: 100px; background: #fff; }\n\t\t\t#absolute-1 { top: 0; left: 0; }\n\t\t\t\t#absolute-1-1 { top: 1px; left: 1px; }\n\t\t\t\t\t#absolute-1-1-1 { top: 1px; left: 1px; }\n\t\t\t#absolute-2 { top: 19px; left: 19px; }\n\t\t\t#marker { position: absolute; border: 2px solid #000; width: 50px; height: 50px; background: #ccc; }\n\t\t\tp.instructions { position: absolute; bottom: 0; }\n\t\t\t#positionTest { position: absolute; }\n\t\t</style>\n\t\t<script src=\"../../jquery.js\"></script>\n\t\t<script type=\"text/javascript\" charset=\"utf-8\">\n\t\t\tjQuery(function($) {\n\t\t\t\t$('.absolute').click(function() {\n\t\t\t\t\t$('#marker').css( $(this).offset() );\n\t\t\t\t\tvar pos = $(this).position();\n\t\t\t\t\t$(this).css({ top: pos.top, left: pos.left });\n\t\t\t\t\treturn false;\n\t\t\t\t});\n\t\t\t});\n\t\t</script>\n\t</head>\n\t<body>\n\t\t<div id=\"absolute-1\" class=\"absolute\">absolute-1\n\t\t\t<div id=\"absolute-1-1\" class=\"absolute\">absolute-1-1\n\t\t\t\t<div id=\"absolute-1-1-1\" class=\"absolute\">absolute-1-1-1</div>\n\t\t\t</div>\n\t\t</div>\n\t\t<div id=\"absolute-2\" class=\"absolute\">absolute-2</div>\n\t\t<div id=\"positionTest\">Has absolute position but no values set for the location ('auto').</div>\n\t\t<div id=\"marker\"></div>\n\t\t<p class=\"instructions\">Click the white box to move the marker to it. Clicking the box also changes the position to absolute (if not already) and sets the position according to the position method.</p>\n\t</body>\n</html>\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/jquery/test/data/offset/body.html",
    "content": "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\"\n\t\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n<html>\n\t<head>\n\t\t<meta http-equiv=\"Content-type\" content=\"text/html; charset=utf-8\">\n\t\t<title>body</title>\n\t\t<style type=\"text/css\" media=\"screen\">\n\t\t\tbody { margin: 1px; padding: 5px; position: relative }\n\t\t\t#marker { position: absolute; border: 2px solid #000; width: 50px; height: 50px; background: #ccc; }\n\t\t\t#firstElement { width: 50px; height: 50px; background: green; }\n\t\t</style>\n\t\t<script src=\"../../jquery.js\"></script>\n\t\t<script type=\"text/javascript\" charset=\"utf-8\">\n\t\t\tjQuery(function($) {\n\t\t\t\t$('body').click(function() {\n\t\t\t\t\t$('#marker').css( $(this).offset() );\n\t\t\t\t\treturn false;\n\t\t\t\t});\n\t\t\t});\n\t\t</script>\n\t</head>\n\t<body>\n\t\t<div id=\"firstElement\"></div>\n\t\t<div id=\"marker\"></div>\n\t</body>\n</html>\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/jquery/test/data/offset/fixed.html",
    "content": "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\"\n\t\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n<html>\n\t<head>\n\t\t<meta http-equiv=\"Content-type\" content=\"text/html; charset=utf-8\">\n\t\t<title>fixed</title>\n\t\t<style type=\"text/css\" media=\"screen\">\n\t\t\tbody { margin: 1px; padding: 5px; }\n\t\t\tdiv.fixed { position: fixed; margin: 1px; border: 2px solid #000; padding: 5px; width: 100px; height: 100px; background: #fff; overflow: hidden; }\n\t\t\t#fixed-1 { top: 0; left: 0; }\n\t\t\t#fixed-2 { top: 20px; left: 20px; }\n\t\t\t#forceScroll { width: 5000px; height: 5000px; }\n\t\t\t#marker { position: absolute; border: 2px solid #000; width: 50px; height: 50px; background: #ccc; }\n\t\t</style>\n\t\t<script src=\"../../jquery.js\"></script>\n\t\t<script type=\"text/javascript\" charset=\"utf-8\">\n\t\t\tjQuery(function($) {\n\t\t\t\twindow.scrollTo(1000,1000);\n\t\t\t\t$('.fixed').click(function() {\n\t\t\t\t\t$('#marker').css( $(this).offset() );\n\t\t\t\t\treturn false;\n\t\t\t\t});\n\t\t\t});\n\t\t</script>\n\t</head>\n\t<body>\n\t\t<div id=\"fixed-1\" class=\"fixed\"></div>\n\t\t<div id=\"fixed-2\" class=\"fixed\"></div>\n\t\t<div id=\"fixed-no-top-left\" class=\"fixed\"></div>\n\t\t<div id=\"forceScroll\"></div>\n\t\t<div id=\"marker\"></div>\n\t\t<p class=\"instructions\">Click the white box to move the marker to it.</p>\n\t</body>\n</html>\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/jquery/test/data/offset/relative.html",
    "content": "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\"\n\t\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n<html>\n\t<head>\n\t\t<meta http-equiv=\"Content-type\" content=\"text/html; charset=utf-8\">\n\t\t<title>relative</title>\n\t\t<style type=\"text/css\" media=\"screen\">\n\t\t\tbody { margin: 1px; padding: 5px; }\n\t\t\tdiv.relative { position: relative; top: 0; left: 0; margin: 1px; border: 2px solid #000; padding: 5px; width: 100px; height: 100px; background: #fff; overflow: hidden; }\n\t\t\t#relative-2 { top: 20px; left: 20px; }\n\t\t\t#marker { position: absolute; border: 2px solid #000; width: 50px; height: 50px; background: #ccc; }\n\t\t</style>\n\t\t<script src=\"../../jquery.js\"></script>\n\t\t<script type=\"text/javascript\" charset=\"utf-8\">\n\t\t\tjQuery(function($) {\n\t\t\t\t$('.relative').click(function() {\n\t\t\t\t\t$('#marker').css( $(this).offset() );\n\t\t\t\t\tvar pos = $(this).position();\n\t\t\t\t\t$(this).css({ position: 'absolute', top: pos.top, left: pos.left });\n\t\t\t\t\treturn false;\n\t\t\t\t});\n\t\t\t});\n\t\t</script>\n\t</head>\n\t<body>\n\t\t<div id=\"relative-1\" class=\"relative\"><div id=\"relative-1-1\" class=\"relative\"><div id=\"relative-1-1-1\" class=\"relative\"></div></div></div>\n\t\t<div id=\"relative-2\" class=\"relative\"></div>\n\t\t<div id=\"marker\"></div>\n\t\t<p class=\"instructions\">Click the white box to move the marker to it. Clicking the box also changes the position to absolute (if not already) and sets the position according to the position method.</p>\n\t</body>\n</html>\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/jquery/test/data/offset/scroll.html",
    "content": "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\"\n\t\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n<html>\n\t<head>\n\t\t<meta http-equiv=\"Content-type\" content=\"text/html; charset=utf-8\">\n\t\t<title>scroll</title>\n\t\t<style type=\"text/css\" media=\"screen\">\n\t\t\tbody { margin: 1px; padding: 5px; }\n\t\t\tdiv.scroll { position: relative; margin: 1px; border: 2px solid #000; padding: 5px; width: 100px; height: 100px; background: #fff; overflow: auto; }\n\t\t\t#scroll-1 { top: 0; left: 0; }\n\t\t\t\t#scroll-1-1 { top: 1px; left: 1px; }\n\t\t\t\t\t#scroll-1-1-1 { top: 1px; left: 1px; }\n\t\t\t#forceScroll { width: 5000px; height: 5000px; }\n\t\t\t#marker { position: absolute; border: 2px solid #000; width: 50px; height: 50px; background: #ccc; }\n\t\t</style>\n\t\t<script src=\"../../jquery.js\"></script>\n\t\t<script type=\"text/javascript\" charset=\"utf-8\">\n\t\t\tjQuery(function($) {\n\t\t\t\twindow.scrollTo(1000,1000);\n\t\t\t\t$('#scroll-1')[0].scrollLeft = 5;\n\t\t\t\t$('#scroll-1')[0].scrollTop = 5;\n\t\t\t\t$('.scroll').click(function() {\n\t\t\t\t\t$('#marker').css( $(this).offset() );\n\t\t\t\t\treturn false;\n\t\t\t\t});\n\t\t\t});\n\t\t</script>\n\t</head>\n\t<body>\n\t\t<div id=\"scroll-1\" class=\"scroll\">\n\t\t\t<div id=\"scroll-1-1\" class=\"scroll\">\n\t\t\t\t<div id=\"scroll-1-1-1\" class=\"scroll\"></div>\n\t\t\t</div>\n\t\t</div>\n\t\t<div id=\"forceScroll\"></div>\n\t\t<div id=\"marker\"></div>\n\t\t<p class=\"instructions\">Click the white box to move the marker to it.</p>\n\t</body>\n</html>\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/jquery/test/data/offset/static.html",
    "content": "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\"\n\t\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n<html>\n\t<head>\n\t\t<meta http-equiv=\"Content-type\" content=\"text/html; charset=utf-8\">\n\t\t<title>static</title>\n\t\t<style type=\"text/css\" media=\"screen\">\n\t\t\tbody { margin: 1px; padding: 5px; }\n\t\t\tdiv.static { position: static; top: 0; left: 0; margin: 1px; border: 2px solid #000; padding: 5px; width: 100px; height: 100px; background: #fff; overflow: hidden; }\n\t\t\t#static-2 { top: 20px; left: 20px; }\n\t\t\t#marker { position: absolute; border: 2px solid #000; width: 50px; height: 50px; background: #ccc; }\n\t\t</style>\n\t\t<script src=\"../../jquery.js\"></script>\n\t\t<script type=\"text/javascript\" charset=\"utf-8\">\n\t\t\tjQuery(function($) {\n\t\t\t\t$('.static').click(function() {\n\t\t\t\t\t$('#marker').css( $(this).offset() );\n\t\t\t\t\tvar pos = $(this).position();\n\t\t\t\t\t$(this).css({ position: 'absolute', top: pos.top, left: pos.left });\n\t\t\t\t\treturn false;\n\t\t\t\t});\n\t\t\t});\n\t\t</script>\n\t</head>\n\t<body>\n\t\t<div id=\"static-1\" class=\"static\"><div id=\"static-1-1\" class=\"static\"><div id=\"static-1-1-1\" class=\"static\"></div></div></div>\n\t\t<div id=\"static-2\" class=\"static\"></div>\n\t\t<div id=\"marker\"></div>\n\t\t<p class=\"instructions\">Click the white box to move the marker to it. Clicking the box also changes the position to absolute (if not already) and sets the position according to the position method.</p>\n\t</body>\n</html>\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/jquery/test/data/offset/table.html",
    "content": "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\"\n\t\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n<html>\n\t<head>\n\t\t<meta http-equiv=\"Content-type\" content=\"text/html; charset=utf-8\">\n\t\t<title>table</title>\n\t\t<style type=\"text/css\" media=\"screen\">\n\t\t\tbody { margin: 1px; padding: 5px; }\n\t\t\ttable { border: 2px solid #000; }\n\t\t\tth, td { border: 1px solid #000; width: 100px; height: 100px; }\n\t\t\t#marker { position: absolute; border: 2px solid #000; width: 50px; height: 50px; background: #ccc; }\n\t\t</style>\n\t\t<script src=\"../../jquery.js\"></script>\n\t\t<script type=\"text/javascript\" charset=\"utf-8\">\n\t\t\tjQuery(function($) {\n\t\t\t\t$('table, th, td').click(function() {\n\t\t\t\t\t$('#marker').css( $(this).offset() );\n\t\t\t\t\treturn false;\n\t\t\t\t});\n\t\t\t});\n\t\t</script>\n\t</head>\n\t<body>\n\t\t<table id=\"table-1\">\n\t\t\t<thead>\n\t\t\t\t<tr valign=\"top\">\n\t\t\t\t\t<th id=\"th-1\">th-1</th>\n\t\t\t\t\t<th id=\"th-2\">th-2</th>\n\t\t\t\t\t<th id=\"th-3\">th-3</th>\n\t\t\t\t</tr>\n\t\t\t</thead>\n\t\t\t<tbody>\n\t\t\t\t<tr valign=\"top\">\n\t\t\t\t\t<td id=\"td-1\">td-1</td>\n\t\t\t\t\t<td id=\"td-2\">td-2</td>\n\t\t\t\t\t<td id=\"td-3\">td-3</td>\n\t\t\t\t</tr>\n\t\t\t</tbody>\n\t\t</table>\n\t\t<div id=\"marker\"></div>\n\t\t<p class=\"instructions\">Click the white box to move the marker to it.</p>\n\t</body>\n</html>\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/jquery/test/data/params_html.php",
    "content": "<div id=\"post\">\n<?php\n\tforeach( $_POST as $key=>$value )\n\t\techo \"<b id='$key'>$value</b>\";\n?>\n</div>\n<div id=\"get\">\n<?php\n\tforeach( $_GET as $key=>$value )\n\t\techo \"<b id='$key'>$value</b>\";\n?>\n</div>"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/jquery/test/data/readywaitasset.js",
    "content": "var delayedMessage = \"It worked!\";\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/jquery/test/data/readywaitloader.js",
    "content": "// Simple script loader that uses jQuery.readyWait via jQuery.holdReady()\n\n//Hold on jQuery!\njQuery.holdReady(true);\n\nvar readyRegExp = /^(complete|loaded)$/;\n\nfunction assetLoaded( evt ){\n\tvar node = evt.currentTarget || evt.srcElement;\n\tif ( evt.type === \"load\" || readyRegExp.test(node.readyState) ) {\n\t\tjQuery.holdReady(false);\n\t}\n}\n\nsetTimeout( function() {\n\tvar script = document.createElement(\"script\");\n\tscript.type = \"text/javascript\";\n\tif ( script.addEventListener ) {\n\t\tscript.addEventListener( \"load\", assetLoaded, false );\n\t} else {\n\t\tscript.attachEvent( \"onreadystatechange\", assetLoaded );\n\t}\n\tscript.src = \"data/readywaitasset.js\";\n\tdocument.getElementsByTagName(\"head\")[0].appendChild(script);\n}, 2000 );\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/jquery/test/data/script.php",
    "content": "<?php\nerror_reporting(0);\nif ( $_REQUEST['header'] ) {\n\tif ( $_REQUEST['header'] == \"ecma\" ) {\n\t\theader(\"Content-type: application/ecmascript\");\n\t} else {\n\t\theader(\"Content-type: text/javascript\");\n\t}\n}\n?>\nok( true, \"Script executed correctly.\" );\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/jquery/test/data/selector/html5_selector.html",
    "content": "<!doctype html>\n<html>\n<head>\n\t<meta http-equiv=\"Content-type\" content=\"text/html; charset=utf-8\">\n\t<title>jQuery selector - attributes</title>\n\n\t<script src=\"../../jquery.js\"></script>\n\n\t<script id=\"script1\"\n\t\t\tdefer\n\t\t\tasync></script>\n\n\t<script type=\"text/javascript\">\n\t\tdocument.createElement('video');\n\t\tdocument.createElement('audio');\n\t\tdocument.createElement('article');\n\t\tdocument.createElement('details');\n\t</script>\n</head>\n<body>\n\t<img id=\"img1\"\n\t\t ismap>\n\n\t<hr id=\"hr1\"\n\t\tnoshade>\n\n\t<form id=\"form1\"\n\t\t  name=\"formName\"\n\t\t  novalidate\n\t\t  formnovalidate>\n\t\t<input type=\"text\" id=\"text1\"\n\t\t\t   tabindex=\"1\"\n\t\t\t   name=\"name\"\n\t\t\t   required\n\t\t\t   autofocus\n\t\t\t   readonly>\n\t\t<textarea id=\"textarea1\"\n\t\t\t\t  noresize></textarea>\n\t</form>\n\n\t<table>\n\t\t<tr><td id=\"td1\"\n\t\t\t\tnowrap></td></tr>\n\t</table>\n\n\t<iframe id=\"iframe1\"\n\t\t\tsrc=\"iframe.html\"\n\t\t\tseamless></iframe>\n\n\t<style id=\"style1\"\n\t\t   scoped></style>\n\n\t<ol id=\"ol1\"\n\t\treversed></ol>\n\n\t<article id=\"article1\"\n\t\t\t pubdate></article>\n\n\t<details id=\"details1\"\n\t\t\t open></details>\n\n\t<div id=\"div1\"\n\t\t nowrap\n\t\t hidden\n\t\t itemscope\n\t\t draggable=\"true\"\n\t\t contenteditable=\"true\"\n\t\t aria-disabled=\"true\">\n\t\t<p>My name is <span id=\"span1\"\n\t\t\t\t\t\t\tspellcheck=\"true\"\n\t\t\t\t\t\t\titemprop=\"name\">Elizabeth</span>.</p>\n\t</div>\n\n\t<audio id=\"audio1\"\n\t\t   muted></audio>\n\n\t<video id=\"video1\"\n\t\t   loop\n\t\t   controls\n\t\t   autoplay\n\t\t   autobuffer></video>\n\n\t<map id=\"map1\">\n\t\t<area id=\"area1\"\n\t\t\t  nohref\n\t\t\t  shape=\"default\">\n\t</map>\n\n\t<input id=\"check1\"\n\t\t   type=\"checkbox\"\n\t\t   disabled\n\t\t   checked>\n\n\t<select id=\"select1\"\n\t\t\tmultiple>\n\t\t<option id=\"option1\"\n\t\t\t\tselected\n\t\t\t\tvalue=\"blar\">blar</option>\n\t</select>\n\n\t<dl id=\"dl\"\n\t\tcompact>\n\t\t<dt>Term</dt><dd>This is the first definition in compact format.</dd>\n\t\t<dt>Term</dt><dd>This is the second definition in compact format.</dd>\n\t</dl>\n\n\t<object id=\"object1\"\n\t\t\tdeclare></object>\n\n\t<marquee id=\"marquee1\"\n\t\t\t direction=\"up\"\n\t\t\t truespeed>Scrolling text (non-standard)</marquee>\n</body>\n</html>\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/jquery/test/data/selector/sizzle_cache.html",
    "content": "<!doctype html>\n<html>\n<head>\n\t<meta http-equiv=\"Content-type\" content=\"text/html; charset=utf-8\">\n\t<title>jQuery selector - sizzle cache</title>\n\n\t<script src=\"../../jquery.js\"></script>\n\t<script>\n\t\tdocument.write(\n\t\t\t\"<script>var $cached = jQuery.noConflict(true);<\\x2Fscript>\" +\n\t\t\t\"<script src='\" + document.getElementById(\"jquery-js\").src + \"?overwrite'><\\x2Fscript>\"\n\t\t);\n\t</script>\n\n</head>\n<body>\n\t<div class=\"test\">\n\t\t<a href=\"#\" id=\"collision\">Worlds collide</a>\n\t</div>\n</body>\n</html>\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/jquery/test/data/statusText.php",
    "content": "<?php\n\nheader( \"HTTP/1.0 $_GET[status] $_GET[text]\" );\n\n?>"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/jquery/test/data/support/bodyBackground.html",
    "content": "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\" dir=\"ltr\" id=\"html\">\n<head>\n\t<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />\n\t<style>\n\t\tbody {\n\t\t\tbackground: #000000;\n\t\t}\n\n\t\tdiv {\n\t\t\tpadding: 15px;\n\t\t\tborder: 1px solid #999;\n\t\t\tdisplay: inline;\n\t\t\tmargin:8px;\n\t\t}\n\t</style>\n</head>\n<body>\n\t<div>\n\t\t<script src=\"../../jquery.js\"></script>\n\t</div>\n\t<script>\n\t\tjQuery(function() {\n\t\t\twindow.parent.iframeCallback( jQuery( \"body\" ).css( \"backgroundColor\" ), jQuery.support );\n\t\t});\n\t</script>\n</body>\n</html>\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/jquery/test/data/support/boxSizing.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n\t<meta charset=\"utf-8\">\n\t<style>\n\t\tbody {\n\t\t\tzoom: 0.87;\n\t\t}\n\t</style>\n</head>\n<body>\n<script src=\"../../jquery.js\"></script>\n<script>\n\tjQuery(function() {\n\t\twindow.parent.iframeCallback( jQuery.support.boxSizing );\n\t});\n</script>\n</body>\n</html>\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/jquery/test/data/support/csp.js",
    "content": "jQuery(function() {\n\tparent.iframeCallback( jQuery.support );\n});\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/jquery/test/data/support/csp.php",
    "content": "<?php\n\t# Support: Firefox\n\theader(\"X-Content-Security-Policy: default-src 'self';\");\n\n\t# Support: Webkit, Safari 5\n\t# http://stackoverflow.com/questions/13663302/why-does-my-content-security-policy-work-everywhere-but-safari\n\theader(\"X-WebKit-CSP: script-src \" . $_SERVER[\"HTTP_HOST\"] . \" 'self'\");\n\n\theader(\"Content-Security-Policy: default-src 'self'\");\n?>\n<!DOCTYPE html>\n<html>\n<head>\n\t<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />\n\t<title>CSP Test Page</title>\n\t<script src=\"../../jquery.js\"></script>\n\t<script src=\"csp.js\"></script>\n</head>\n<body>\n\t<p>CSP Test Page</p>\n</body>\n</html>\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/jquery/test/data/support/shrinkWrapBlocks.html",
    "content": "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\" dir=\"ltr\" id=\"html\">\n<head>\n\t<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />\n\t<style>\n\t\t* {\n\t\t\t-webkit-box-sizing: border-box;\n\t\t\t-moz-box-sizing:    border-box;\n\t\t\tbox-sizing:         border-box;\n\t\t}\n\t</style>\n</head>\n<body>\n\t<div>\n\t\t<script src=\"../../jquery.js\"></script>\n\t</div>\n\t<script>\n\t\tjQuery(function() {\n\t\t\twindow.parent.iframeCallback( jQuery.support.shrinkWrapBlocks );\n\t\t});\n\t</script>\n</body>\n</html>\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/jquery/test/data/support/testElementCrash.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">\n\t<style>\n\t\tbody {\n\t\t\tbackground: url('../1x1.jpg');\n\t\t}\n\t</style>\n\t<script src=\"../../jquery.js\"></script>\n</head>\n<body>\n\t<script>\n\t\twindow.parent.iframeCallback();\n\t</script>\n</body>\n</html>\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/jquery/test/data/test.html",
    "content": "html text<br/>\n<script type=\"text/javascript\">/* <![CDATA[ */\ntestFoo = \"foo\"; jQuery('#foo').html('foo');\nok( true, \"test.html executed\" );\n/* ]]> */</script>\n<script src=\"data/test.js\"></script>\nblabla\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/jquery/test/data/test.js",
    "content": "this.testBar = \"bar\";\njQuery(\"#ap\").html(\"bar\");\nok( true, \"test.js executed\");\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/jquery/test/data/test.php",
    "content": "html text<br/>\n<script type=\"text/javascript\">/* <![CDATA[ */\ntestFoo = \"foo\"; jQuery('#foo').html('foo');\nok( true, \"test.php executed\" );\n/* ]]> */</script>\n<script src=\"data/test.js?<?php srand(); echo time() . '' . rand(); ?>\"></script>\nblabla"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/jquery/test/data/test2.html",
    "content": "<script type=\"text/javascript\">\nvar testFoo = \"foo\";\njQuery('#foo').html('foo');\nok( true, \"test2.html executed\" );\n</script>\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/jquery/test/data/test3.html",
    "content": "<div class=\"user\">This is a user</div>\n<div class=\"user\">This is a user</div>\n<div class=\"teacher\">This is a teacher</div>\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/jquery/test/data/testinit.js",
    "content": "/*jshint multistr:true, quotmark:false */\n\nvar amdDefined, fireNative,\n\toriginaljQuery = this.jQuery || \"jQuery\",\n\toriginal$ = this.$ || \"$\",\n\t// see RFC 2606\n\texternalHost = \"example.com\";\n\nthis.hasPHP = true;\nthis.isLocal = window.location.protocol === \"file:\";\n\n// For testing .noConflict()\nthis.jQuery = originaljQuery;\nthis.$ = original$;\n\n/**\n * Set up a mock AMD define function for testing AMD registration.\n */\nfunction define( name, dependencies, callback ) {\n\tamdDefined = callback();\n}\n\ndefine.amd = {};\n\n/**\n * Returns an array of elements with the given IDs\n * @example q(\"main\", \"foo\", \"bar\")\n * @result [<div id=\"main\">, <span id=\"foo\">, <input id=\"bar\">]\n */\nthis.q = function() {\n\tvar r = [],\n\t\ti = 0;\n\n\tfor ( ; i < arguments.length; i++ ) {\n\t\tr.push( document.getElementById( arguments[i] ) );\n\t}\n\treturn r;\n};\n\n/**\n * Asserts that a select matches the given IDs\n * @param {String} a - Assertion name\n * @param {String} b - Sizzle selector\n * @param {String} c - Array of ids to construct what is expected\n * @example t(\"Check for something\", \"//[a]\", [\"foo\", \"baar\"]);\n * @result returns true if \"//[a]\" return two elements with the IDs 'foo' and 'baar'\n */\nthis.t = function( a, b, c ) {\n\tvar f = jQuery(b).get(),\n\t\ts = \"\",\n\t\ti = 0;\n\n\tfor ( ; i < f.length; i++ ) {\n\t\ts += ( s && \",\" ) + '\"' + f[ i ].id + '\"';\n\t}\n\n\tdeepEqual(f, q.apply( q, c ), a + \" (\" + b + \")\");\n};\n\nthis.createDashboardXML = function() {\n\tvar string = '<?xml version=\"1.0\" encoding=\"UTF-8\"?> \\\n\t<dashboard> \\\n\t\t<locations class=\"foo\"> \\\n\t\t\t<location for=\"bar\" checked=\"different\"> \\\n\t\t\t\t<infowindowtab normal=\"ab\" mixedCase=\"yes\"> \\\n\t\t\t\t\t<tab title=\"Location\"><![CDATA[blabla]]></tab> \\\n\t\t\t\t\t<tab title=\"Users\"><![CDATA[blublu]]></tab> \\\n\t\t\t\t</infowindowtab> \\\n\t\t\t</location> \\\n\t\t</locations> \\\n\t</dashboard>';\n\n\treturn jQuery.parseXML(string);\n};\n\nthis.createWithFriesXML = function() {\n\tvar string = '<?xml version=\"1.0\" encoding=\"UTF-8\"?> \\\n\t<soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\" \\\n\t\txmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" \\\n\t\txmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"> \\\n\t\t<soap:Body> \\\n\t\t\t<jsconf xmlns=\"http://{{ externalHost }}/ns1\"> \\\n\t\t\t\t<response xmlns:ab=\"http://{{ externalHost }}/ns2\"> \\\n\t\t\t\t\t<meta> \\\n\t\t\t\t\t\t<component id=\"seite1\" class=\"component\"> \\\n\t\t\t\t\t\t\t<properties xmlns:cd=\"http://{{ externalHost }}/ns3\"> \\\n\t\t\t\t\t\t\t\t<property name=\"prop1\"> \\\n\t\t\t\t\t\t\t\t\t<thing /> \\\n\t\t\t\t\t\t\t\t\t<value>1</value> \\\n\t\t\t\t\t\t\t\t</property> \\\n\t\t\t\t\t\t\t\t<property name=\"prop2\"> \\\n\t\t\t\t\t\t\t\t\t<thing att=\"something\" /> \\\n\t\t\t\t\t\t\t\t</property> \\\n\t\t\t\t\t\t\t\t<foo_bar>foo</foo_bar> \\\n\t\t\t\t\t\t\t</properties> \\\n\t\t\t\t\t\t</component> \\\n\t\t\t\t\t</meta> \\\n\t\t\t\t</response> \\\n\t\t\t</jsconf> \\\n\t\t</soap:Body> \\\n\t</soap:Envelope>';\n\n\treturn jQuery.parseXML( string.replace( /\\{\\{\\s*externalHost\\s*\\}\\}/g, externalHost ) );\n};\n\nthis.createXMLFragment = function() {\n\tvar xml, frag;\n\tif ( window.ActiveXObject ) {\n\t\txml = new ActiveXObject(\"msxml2.domdocument\");\n\t} else {\n\t\txml = document.implementation.createDocument( \"\", \"\", null );\n\t}\n\n\tif ( xml ) {\n\t\tfrag = xml.createElement(\"data\");\n\t}\n\n\treturn frag;\n};\n\nfireNative = document.createEvent ?\n\tfunction( node, type ) {\n\t\tvar event = document.createEvent('HTMLEvents');\n\t\tevent.initEvent( type, true, true );\n\t\tnode.dispatchEvent( event );\n\t} :\n\tfunction( node, type ) {\n\t\tvar event = document.createEventObject();\n\t\tnode.fireEvent( 'on' + type, event );\n\t};\n\n/**\n * Add random number to url to stop caching\n *\n * @example url(\"data/test.html\")\n * @result \"data/test.html?10538358428943\"\n *\n * @example url(\"data/test.php?foo=bar\")\n * @result \"data/test.php?foo=bar&10538358345554\"\n */\nfunction url( value ) {\n\treturn value + (/\\?/.test(value) ? \"&\" : \"?\") + new Date().getTime() + \"\" + parseInt(Math.random() * 100000, 10);\n}\n\n// Ajax testing helper\nthis.ajaxTest = function( title, expect, options ) {\n\tvar requestOptions;\n\tif ( jQuery.isFunction( options ) ) {\n\t\toptions = options();\n\t}\n\toptions = options || [];\n\trequestOptions = options.requests || options.request || options;\n\tif ( !jQuery.isArray( requestOptions ) ) {\n\t\trequestOptions = [ requestOptions ];\n\t}\n\tasyncTest( title, expect, function() {\n\t\tif ( options.setup ) {\n\t\t\toptions.setup();\n\t\t}\n\n\t\tvar completed = false,\n\t\t\tremaining = requestOptions.length,\n\t\t\tcomplete = function() {\n\t\t\t\tif ( !completed && --remaining === 0 ) {\n\t\t\t\t\tcompleted = true;\n\t\t\t\t\tdelete ajaxTest.abort;\n\t\t\t\t\tif ( options.teardown ) {\n\t\t\t\t\t\toptions.teardown();\n\t\t\t\t\t}\n\t\t\t\t\tstart();\n\t\t\t\t}\n\t\t\t},\n\t\t\trequests = jQuery.map( requestOptions, function( options ) {\n\t\t\t\tvar request = ( options.create || jQuery.ajax )( options ),\n\t\t\t\t\tcallIfDefined = function( deferType, optionType ) {\n\t\t\t\t\t\tvar handler = options[ deferType ] || !!options[ optionType ];\n\t\t\t\t\t\treturn function( _, status ) {\n\t\t\t\t\t\t\tif ( !completed ) {\n\t\t\t\t\t\t\t\tif ( !handler ) {\n\t\t\t\t\t\t\t\t\tok( false, \"unexpected \" + status );\n\t\t\t\t\t\t\t\t} else if ( jQuery.isFunction( handler ) ) {\n\t\t\t\t\t\t\t\t\thandler.apply( this, 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};\n\n\t\t\t\tif ( options.afterSend ) {\n\t\t\t\t\toptions.afterSend( request );\n\t\t\t\t}\n\n\t\t\t\treturn request\n\t\t\t\t\t.done( callIfDefined( \"done\", \"success\" ) )\n\t\t\t\t\t.fail( callIfDefined( \"fail\", \"error\" ) )\n\t\t\t\t\t.always( complete );\n\t\t\t});\n\n\t\tajaxTest.abort = function( reason ) {\n\t\t\tif ( !completed ) {\n\t\t\t\tcompleted = true;\n\t\t\t\tdelete ajaxTest.abort;\n\t\t\t\tok( false, \"aborted \" + reason );\n\t\t\t\tjQuery.each( requests, function( i, request ) {\n\t\t\t\t\trequest.abort();\n\t\t\t\t});\n\t\t\t}\n\t\t};\n\t});\n};\n\n\nthis.testIframe = function( fileName, name, fn ) {\n\n\ttest(name, function() {\n\t\t// pause execution for now\n\t\tstop();\n\n\t\t// load fixture in iframe\n\t\tvar iframe = loadFixture(),\n\t\t\twin = iframe.contentWindow,\n\t\t\tinterval = setInterval( function() {\n\t\t\t\tif ( win && win.jQuery && win.jQuery.isReady ) {\n\t\t\t\t\tclearInterval( interval );\n\t\t\t\t\t// continue\n\t\t\t\t\tstart();\n\t\t\t\t\t// call actual tests passing the correct jQuery instance to use\n\t\t\t\t\tfn.call( this, win.jQuery, win, win.document );\n\t\t\t\t\tdocument.body.removeChild( iframe );\n\t\t\t\t\tiframe = null;\n\t\t\t\t}\n\t\t\t}, 15 );\n\t});\n\n\tfunction loadFixture() {\n\t\tvar src = url(\"./data/\" + fileName + \".html\"),\n\t\t\tiframe = jQuery(\"<iframe />\").appendTo(\"body\")[0];\n\t\t\tiframe.style.cssText = \"width: 500px; height: 500px; position: absolute; top: -600px; left: -600px; visibility: hidden;\";\n\t\tiframe.contentWindow.location = src;\n\t\treturn iframe;\n\t}\n};\n\nthis.testIframeWithCallback = function( title, fileName, func ) {\n\n\ttest( title, function() {\n\t\tvar iframe;\n\n\t\tstop();\n\t\twindow.iframeCallback = function() {\n\t\t\tvar self = this,\n\t\t\t\targs = arguments;\n\t\t\tsetTimeout(function() {\n\t\t\t\twindow.iframeCallback = undefined;\n\t\t\t\tiframe.remove();\n\t\t\t\tfunc.apply( self, args );\n\t\t\t\tfunc = function() {};\n\t\t\t\tstart();\n\t\t\t}, 0 );\n\t\t};\n\t\tiframe = jQuery( \"<div/>\" ).append(\n\t\t\tjQuery( \"<iframe/>\" ).attr( \"src\", url( \"./data/\" + fileName ) )\n\t\t).appendTo( \"body\" );\n\t});\n};\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/jquery/test/data/testrunner.js",
    "content": "/**\n * Allow the test suite to run with other libs or jQuery's.\n */\njQuery.noConflict();\n\n// For checking globals pollution despite auto-created globals in various environments\njQuery.each( [ jQuery.expando, \"getInterface\", \"Packages\", \"java\", \"netscape\" ], function( i, name ) {\n\twindow[ name ] = window[ name ];\n});\n\n// Expose Sizzle for Sizzle's selector tests\n// We remove Sizzle's globalization in jQuery\nvar Sizzle = Sizzle || jQuery.find,\n\n// Allow subprojects to test against their own fixtures\n\tqunitModule = QUnit.module,\n\tqunitTest = QUnit.test;\n\nthis.testSubproject = function( label, url, risTests ) {\n\tvar sub, fixture, fixtureHTML,\n\t\tfixtureReplaced = false;\n\n\t// Don't let subproject tests jump the gun\n\tQUnit.config.reorder = false;\n\n\t// Create module\n\tmodule( label );\n\n\t// Duckpunch QUnit\n\t// TODO restore parent fixture on teardown to support reordering\n\tmodule = QUnit.module = function( name ) {\n\t\tvar args = arguments;\n\n\t\t// Remember subproject-scoped module name\n\t\tsub = name;\n\n\t\t// Override\n\t\targs[0] = label;\n\t\treturn qunitModule.apply( this, args );\n\t};\n\ttest = function( name ) {\n\t\tvar args = arguments,\n\t\t\ti = args.length - 1;\n\n\t\t// Prepend subproject-scoped module name to test name\n\t\targs[0] = sub + \": \" + name;\n\n\t\t// Find test function and wrap to require subproject fixture\n\t\tfor ( ; i >= 0; i-- ) {\n\t\t\tif ( originaljQuery.isFunction( args[i] ) ) {\n\t\t\t\targs[i] = requireFixture( args[i] );\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\treturn qunitTest.apply( this, args );\n\t};\n\n\t// Load tests and fixture from subproject\n\t// Test order matters, so we must be synchronous and throw an error on load failure\n\toriginaljQuery.ajax( url, {\n\t\tasync: false,\n\t\tdataType: \"html\",\n\t\terror: function( jqXHR, status ) {\n\t\t\tthrow new Error( \"Could not load: \" + url + \" (\" + status + \")\" );\n\t\t},\n\t\tsuccess: function( data, status, jqXHR ) {\n\t\t\tvar page = originaljQuery.parseHTML(\n\t\t\t\t// replace html/head with dummy elements so they are represented in the DOM\n\t\t\t\t( data || \"\" ).replace( /<\\/?((!DOCTYPE|html|head)\\b.*?)>/gi, \"[$1]\" ),\n\t\t\t\tdocument,\n\t\t\t\ttrue\n\t\t\t);\n\n\t\t\tif ( !page || !page.length ) {\n\t\t\t\tthis.error( jqXHR, \"no data\" );\n\t\t\t}\n\t\t\tpage = originaljQuery( page );\n\n\t\t\t// Include subproject tests\n\t\t\tpage.filter(\"script[src]\").add( page.find(\"script[src]\") ).each(function() {\n\t\t\t\tvar src = originaljQuery( this ).attr(\"src\"),\n\t\t\t\t\thtml = \"<script src='\" + url + src + \"'></script>\";\n\t\t\t\tif ( risTests.test( src ) ) {\n\t\t\t\t\tif ( originaljQuery.isReady ) {\n\t\t\t\t\t\toriginaljQuery(\"head\").first().append( html );\n\t\t\t\t\t} else {\n\t\t\t\t\t\tdocument.write( html );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\n\t\t\t// Get the fixture, including content outside of #qunit-fixture\n\t\t\tfixture = page.find(\"[id='qunit-fixture']\");\n\t\t\tfixtureHTML = fixture.html();\n\t\t\tfixture.empty();\n\t\t\twhile ( fixture.length && !fixture.prevAll(\"[id='qunit']\").length ) {\n\t\t\t\tfixture = fixture.parent();\n\t\t\t}\n\t\t\tfixture = fixture.add( fixture.nextAll() );\n\t\t}\n\t});\n\n\tfunction requireFixture( fn ) {\n\t\treturn function() {\n\t\t\tif ( !fixtureReplaced ) {\n\t\t\t\t// Make sure that we retrieved a fixture for the subproject\n\t\t\t\tif ( !fixture.length ) {\n\t\t\t\t\tok( false, \"Found subproject fixture\" );\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\t// Replace the current fixture, including content outside of #qunit-fixture\n\t\t\t\tvar oldFixture = originaljQuery(\"#qunit-fixture\");\n\t\t\t\twhile ( oldFixture.length && !oldFixture.prevAll(\"[id='qunit']\").length ) {\n\t\t\t\t\toldFixture = oldFixture.parent();\n\t\t\t\t}\n\t\t\t\toldFixture.nextAll().remove();\n\t\t\t\toldFixture.replaceWith( fixture );\n\n\t\t\t\t// WARNING: UNDOCUMENTED INTERFACE\n\t\t\t\tQUnit.config.fixture = fixtureHTML;\n\t\t\t\tQUnit.reset();\n\t\t\t\tif ( originaljQuery(\"#qunit-fixture\").html() !== fixtureHTML ) {\n\t\t\t\t\tok( false, \"Copied subproject fixture\" );\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tfixtureReplaced = true;\n\t\t\t}\n\n\t\t\tfn.apply( this, arguments );\n\t\t};\n\t}\n};\n\n// Register globals for cleanup and the cleanup code itself\n// Explanation at http://perfectionkills.com/understanding-delete/#ie_bugs\nthis.Globals = (function() {\n\tvar globals = {};\n\treturn {\n\t\tregister: function( name ) {\n\t\t\tglobals[ name ] = true;\n\t\t\tjQuery.globalEval( \"var \" + name + \" = undefined;\" );\n\t\t},\n\t\tcleanup: function() {\n\t\t\tvar name,\n\t\t\t\tcurrent = globals;\n\t\t\tglobals = {};\n\t\t\tfor ( name in current ) {\n\t\t\t\tjQuery.globalEval( \"try { \" +\n\t\t\t\t\t\"delete \" + ( jQuery.support.deleteExpando ? \"window['\" + name + \"']\" : name ) +\n\t\t\t\t\"; } catch( x ) {}\" );\n\t\t\t}\n\t\t}\n\t};\n})();\n\n// Sandbox start for great justice\n(function() {\n\tvar oldStart = window.start;\n\twindow.start = function() {\n\t\toldStart();\n\t};\n})();\n\n/**\n * QUnit hooks\n */\n(function() {\n\t// Store the old counts so that we only assert on tests that have actually leaked,\n\t// instead of asserting every time a test has leaked sometime in the past\n\tvar oldCacheLength = 0,\n\t\toldFragmentsLength = 0,\n\t\toldActive = 0,\n\n\t\texpectedDataKeys = {},\n\n\t\tsplice = [].splice,\n\t\treset = QUnit.reset,\n\t\tajaxSettings = jQuery.ajaxSettings;\n\n\tfunction keys(o) {\n\t\tvar ret, key;\n\t\tif ( Object.keys ) {\n\t\t\tret = Object.keys( o );\n\t\t} else {\n\t\t\tret = [];\n\t\t\tfor ( key in o ) {\n\t\t\t\tret.push( key );\n\t\t\t}\n\t\t}\n\t\tret.sort();\n\t\treturn ret;\n\t}\n\n\t/**\n\t * @param {jQuery|HTMLElement|Object|Array} elems Target (or array of targets) for jQuery.data.\n\t * @param {string} key\n\t */\n\tQUnit.expectJqData = function( elems, key ) {\n\t\tvar i, elem, expando;\n\n\t\t// As of jQuery 2.0, there will be no \"cache\"-data is\n\t\t// stored and managed completely below the API surface\n\t\tif ( jQuery.cache ) {\n\t\t\tQUnit.current_testEnvironment.checkJqData = true;\n\n\t\t\tif ( elems.jquery && elems.toArray ) {\n\t\t\t\telems = elems.toArray();\n\t\t\t}\n\t\t\tif ( !jQuery.isArray( elems ) ) {\n\t\t\t\telems = [ elems ];\n\t\t\t}\n\n\t\t\tfor ( i = 0; i < elems.length; i++ ) {\n\t\t\t\telem = elems[i];\n\n\t\t\t\t// jQuery.data only stores data for nodes in jQuery.cache,\n\t\t\t\t// for other data targets the data is stored in the object itself,\n\t\t\t\t// in that case we can't test that target for memory leaks.\n\t\t\t\t// But we don't have to since in that case the data will/must will\n\t\t\t\t// be available as long as the object is not garbage collected by\n\t\t\t\t// the js engine, and when it is, the data will be removed with it.\n\t\t\t\tif ( !elem.nodeType ) {\n\t\t\t\t\t// Fixes false positives for dataTests(window), dataTests({}).\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\texpando = elem[ jQuery.expando ];\n\n\t\t\t\tif ( expando === undefined ) {\n\t\t\t\t\t// In this case the element exists fine, but\n\t\t\t\t\t// jQuery.data (or internal data) was never (in)directly\n\t\t\t\t\t// called.\n\t\t\t\t\t// Since this method was called it means some data was\n\t\t\t\t\t// expected to be found, but since there is nothing, fail early\n\t\t\t\t\t// (instead of in teardown).\n\t\t\t\t\tnotStrictEqual( expando, undefined, \"Target for expectJqData must have an expando, for else there can be no data to expect.\" );\n\t\t\t\t} else {\n\t\t\t\t\tif ( expectedDataKeys[expando] ) {\n\t\t\t\t\t\texpectedDataKeys[expando].push( key );\n\t\t\t\t\t} else {\n\t\t\t\t\t\texpectedDataKeys[expando] = [ key ];\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t};\n\tQUnit.config.urlConfig.push( {\n\t\tid: \"jqdata\",\n\t\tlabel: \"Always check jQuery.data\",\n\t\ttooltip: \"Trigger QUnit.expectJqData detection for all tests instead of just the ones that call it\"\n\t} );\n\n\t/**\n\t * Ensures that tests have cleaned up properly after themselves. Should be passed as the\n\t * teardown function on all modules' lifecycle object.\n\t */\n\tthis.moduleTeardown = function() {\n\t\tvar i,\n\t\t\texpectedKeys, actualKeys,\n\t\t\tfragmentsLength = 0,\n\t\t\tcacheLength = 0;\n\n\t\t// Only look for jQuery data problems if this test actually\n\t\t// provided some information to compare against.\n\t\tif ( QUnit.urlParams.jqdata || this.checkJqData ) {\n\t\t\tfor ( i in jQuery.cache ) {\n\t\t\t\texpectedKeys = expectedDataKeys[i];\n\t\t\t\tactualKeys = jQuery.cache[i] ? keys( jQuery.cache[i] ) : jQuery.cache[i];\n\t\t\t\tif ( !QUnit.equiv( expectedKeys, actualKeys ) ) {\n\t\t\t\t\tdeepEqual( actualKeys, expectedKeys, \"Expected keys exist in jQuery.cache\" );\n\t\t\t\t}\n\t\t\t\tdelete jQuery.cache[i];\n\t\t\t\tdelete expectedDataKeys[i];\n\t\t\t}\n\t\t\t// In case it was removed from cache before (or never there in the first place)\n\t\t\tfor ( i in expectedDataKeys ) {\n\t\t\t\tdeepEqual( expectedDataKeys[i], undefined, \"No unexpected keys were left in jQuery.cache (#\" + i + \")\" );\n\t\t\t\tdelete expectedDataKeys[i];\n\t\t\t}\n\t\t}\n\n\t\t// Reset data register\n\t\texpectedDataKeys = {};\n\n\t\t// Check for (and clean up, if possible) incomplete animations/requests/etc.\n\t\tif ( jQuery.timers && jQuery.timers.length !== 0 ) {\n\t\t\tequal( jQuery.timers.length, 0, \"No timers are still running\" );\n\t\t\tsplice.call( jQuery.timers, 0, jQuery.timers.length );\n\t\t\tjQuery.fx.stop();\n\t\t}\n\t\tif ( jQuery.active !== undefined && jQuery.active !== oldActive ) {\n\t\t\tequal( jQuery.active, oldActive, \"No AJAX requests are still active\" );\n\t\t\tif ( ajaxTest.abort ) {\n\t\t\t\tajaxTest.abort(\"active requests\");\n\t\t\t}\n\t\t\toldActive = jQuery.active;\n\t\t}\n\n\t\t// Allow QUnit.reset to clean up any attached elements before checking for leaks\n\t\tQUnit.reset();\n\n\t\tfor ( i in jQuery.cache ) {\n\t\t\t++cacheLength;\n\t\t}\n\n\t\tjQuery.fragments = {};\n\n\t\tfor ( i in jQuery.fragments ) {\n\t\t\t++fragmentsLength;\n\t\t}\n\n\t\t// Because QUnit doesn't have a mechanism for retrieving the number of expected assertions for a test,\n\t\t// if we unconditionally assert any of these, the test will fail with too many assertions :|\n\t\tif ( cacheLength !== oldCacheLength ) {\n\t\t\tequal( cacheLength, oldCacheLength, \"No unit tests leak memory in jQuery.cache\" );\n\t\t\toldCacheLength = cacheLength;\n\t\t}\n\t\tif ( fragmentsLength !== oldFragmentsLength ) {\n\t\t\tequal( fragmentsLength, oldFragmentsLength, \"No unit tests leak memory in jQuery.fragments\" );\n\t\t\toldFragmentsLength = fragmentsLength;\n\t\t}\n\t};\n\n\tQUnit.done(function() {\n\t\t// Remove our own fixtures outside #qunit-fixture\n\t\tjQuery(\"#qunit ~ *\").remove();\n\t});\n\n\t// jQuery-specific QUnit.reset\n\tQUnit.reset = function() {\n\n\t\t// Ensure jQuery events and data on the fixture are properly removed\n\t\tjQuery(\"#qunit-fixture\").empty();\n\n\t\t// Reset internal jQuery state\n\t\tjQuery.event.global = {};\n\t\tif ( ajaxSettings ) {\n\t\t\tjQuery.ajaxSettings = jQuery.extend( true, {}, ajaxSettings );\n\t\t} else {\n\t\t\tdelete jQuery.ajaxSettings;\n\t\t}\n\n\t\t// Cleanup globals\n\t\tGlobals.cleanup();\n\n\t\t// Let QUnit reset the fixture\n\t\treset.apply( this, arguments );\n\t};\n})();\n\n/**\n * QUnit configuration\n */\n// Max time for stop() and asyncTest() until it aborts test\n// and start()'s the next test.\nQUnit.config.testTimeout = 20 * 1000; // 20 seconds\n\n// Enforce an \"expect\" argument or expect() call in all test bodies.\nQUnit.config.requireExpects = true;\n\n/**\n * Load the TestSwarm listener if swarmURL is in the address.\n */\n(function() {\n\tvar url = window.location.search;\n\turl = decodeURIComponent( url.slice( url.indexOf(\"swarmURL=\") + \"swarmURL=\".length ) );\n\n\tif ( !url || url.indexOf(\"http\") !== 0 ) {\n\t\treturn;\n\t}\n\n\tdocument.write(\"<scr\" + \"ipt src='http://swarm.jquery.org/js/inject.js?\" + (new Date()).getTime() + \"'></scr\" + \"ipt>\");\n})();\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/jquery/test/data/testsuite.css",
    "content": "/* for testing opacity set in styles in IE */\nol#empty {\n\topacity: 0;\n\tfilter:Alpha(opacity=0) progid:DXImageTransform.Microsoft.gradient(startColorStr='#ffff0000', EndColorStr='#ffffffff');\n}\n\ndiv#fx-tests h4 {\n\tbackground: red;\n}\n\ndiv#fx-tests h4.pass {\n\tbackground: green;\n}\n\ndiv#fx-tests div.box {\n\tbackground: red;\n\toverflow: hidden;\n\tborder: 2px solid #000;\n}\n\ndiv#fx-tests div.overflow {\n\toverflow: visible;\n}\n\ndiv.inline {\n\tdisplay: inline;\n}\n\ndiv.autoheight {\n\theight: auto;\n}\n\ndiv.autowidth {\n\twidth: auto;\n}\n\ndiv.autoopacity {\n\topacity: auto;\n}\n\ndiv.largewidth {\n\twidth: 100px;\n}\n\ndiv.largeheight {\n\theight: 100px;\n}\n\ndiv.largeopacity {\n\tfilter: progid:DXImageTransform.Microsoft.Alpha(opacity=100);\n}\n\ndiv.medwidth {\n\twidth: 50px;\n}\n\ndiv.medheight {\n\theight: 50px;\n}\n\ndiv.medopacity {\n\topacity: 0.5;\n\tfilter: progid:DXImageTransform.Microsoft.Alpha(opacity=50);\n}\n\ndiv.nowidth {\n\twidth: 0px;\n}\n\ndiv.noheight {\n\theight: 0px;\n}\n\ndiv.noopacity {\n\topacity: 0;\n\tfilter: progid:DXImageTransform.Microsoft.Alpha(opacity=0);\n}\n\ndiv.hidden {\n\tdisplay: none;\n}\n\ndiv#fx-tests div.widewidth {\n\tbackground-repeat: repeat-x;\n}\n\ndiv#fx-tests div.wideheight {\n\tbackground-repeat: repeat-y;\n}\n\ndiv#fx-tests div.widewidth.wideheight {\n\tbackground-repeat: repeat;\n}\n\ndiv#fx-tests div.noback {\n\tbackground-image: none;\n}\n\n.chain-test,\n.chain-test div {\n\twidth: 100px;\n\theight: 20px;\n\tposition: relative;\n\tfloat: left;\n}\n.chain-test div {\n\tposition: absolute;\n\ttop: 0;\n\tleft: 0;\n}\n\n.chain-test {\n\tbackground: red;\n}\n.chain-test div {\n\tbackground: green;\n}\n\n.chain-test-out {\n\tbackground: green;\n}\n.chain-test-out div {\n\tbackground: red;\n\tdisplay: none;\n}\n\n/* tests to ensure jQuery can determine the native display mode of elements\n   that have been set as display: none in stylesheets */\ndiv#show-tests * { display: none; }\n\n#nothiddendiv { font-size: 16px; }\n#nothiddendivchild.em { font-size: 2em; }\n#nothiddendivchild.prct { font-size: 150%; }\n\n/* For testing type on vml in IE #7071 */\nv\\:oval { behavior:url(#default#VML); display:inline-block; }\n\n/* 8099 changes to default styles are read correctly */\ntt { display: none; }\nsup { display: none; }\ndfn { display: none; }\n\n/* #9239 Attach a background to the body( avoid crashes in removing the test element in support ) */\nbody, div { background: url(http://static.jquery.com/files/rocker/images/logo_jquery_215x53.gif) no-repeat -1000px 0; }\n\n/* #6652 REMOVE FILTER:ALPHA(OPACITY=100) AFTER ANIMATION */\n#t6652 div { filter: alpha(opacity=50); }\n\n/* #10501 */\nsection { background:#f0f; display:block; }\n\n/* #11971 */\n#foo { background: url(1x1.jpg) right bottom no-repeat; }\n\n#display { display: list-item !important; }\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/jquery/test/data/text.php",
    "content": "Lorem ipsum dolor sit amet\nconsectetuer adipiscing elit\nSed lorem leo\nlorem leo consectetuer adipiscing elit\nSed lorem leo\nrhoncus sit amet\nelementum at\nbibendum at, eros\nCras at mi et tortor egestas vestibulum\nsed Cras at mi vestibulum\nPhasellus sed felis sit amet\norci dapibus semper.\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/jquery/test/data/ua.txt",
    "content": "msie\t6.0\tMozilla/4.0 (compatible; MSIE 6.0; Windows 98; Win 9x 4.90; http://www.Abolimba.de)\nmsie\t6.0\tMozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; JyxoToolbar1.0; http://www.Abolimba.de; .NET CLR 2.0.50727; .NET CLR 3.0.04506.648; .NET CLR 3.5.21022; .NET CLR 1.1.4322)\n\t0\tMozilla/5.0 (compatible; ABrowse 0.4; Syllable)\nwebkit\t420\tMozilla/5.0 (compatible; U; ABrowse 0.6; Syllable) AppleWebKit/420+ (KHTML, like Gecko)\nmsie\t7.0\tMozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Acoo Browser; InfoPath.2; .NET CLR 2.0.50727; Alexa Toolbar)\nmsie\t6.0\tMozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; Acoo Browser; .NET CLR 1.1.4322; .NET CLR 2.0.50727)\nmsie\t7.0\tMozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; Acoo Browser; SLCC1; .NET CLR 2.0.50727; Media Center PC 5.0; .NET CLR 3.0.04506)\n\t0\tamaya/9.52 libwww/5.4.0\n\t0\tamaya/11.1 libwww/5.4.0\n\t0\tAmiga-AWeb/3.5.07 beta\n\t0\tAmigaVoyager/3.4.4 (MorphOS/PPC native)\n\t0\tAmigaVoyager/2.95 (compatible; MC680x0; AmigaOS)\nmsie\t7.0\tMozilla/4.0 (compatible; MSIE 7.0; AOL 7.0; Windows NT 5.1; FunWebProducts)\nmsie\t6.0\tMozilla/4.0 (compatible; MSIE 6.0; AOL 8.0; Windows NT 5.1; SV1)\nmsie\t7.0\tMozilla/4.0 (compatible; MSIE 7.0; AOL 9.0; Windows NT 5.1; .NET CLR 1.1.4322; Zango 10.1.181.0)\nmsie\t6.0\tMozilla/4.0 (compatible; MSIE 6.0; AOL 6.0; Windows NT 5.1)\nmsie\t7.0\tMozilla/4.0 (compatible; MSIE 7.0; AOL 9.5; AOLBuild 4337.35; Windows NT 5.1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)\nwebkit\t523.15\tMozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN) AppleWebKit/523.15 (KHTML, like Gecko, Safari/419.3) Arora/0.3 (Change: 287 c9dfb30)\nwebkit\t527\tMozilla/5.0 (X11; U; Linux; en-US) AppleWebKit/527+ (KHTML, like Gecko, Safari/419.3) Arora/0.6\nwebkit\t523.15\tMozilla/5.0 (X11; U; Linux; C -) AppleWebKit/523.15 (KHTML, like Gecko, Safari/419.3) Arora/0.5\nmsie\t6.0\tMozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Avant Browser; Avant Browser; .NET CLR 1.1.4322; .NET CLR 2.0.50727; InfoPath.1)\n\t0\tAvant Browser (http://www.avantbrowser.com)\nmsie\t6.0\tMozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; JyxoToolbar1.0;  Embedded Web Browser from: http://bsalsa.com/; Avant Browser; .NET CLR 2.0.50727; .NET CLR 3.0.04506.648; .NET CLR 3.5.21022; .NET CLR 1.1.4322)\nmsie\t7.0\tMozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; GTB5; Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1) ; Avant Browser)\nmozilla\t0\tMozilla/5.0 (Windows; U; Win9x; en; Stable) Gecko/20020911 Beonex/0.8.1-stable\nmozilla\t0\tMozilla/5.0 (Windows; U; WinNT; en; Preview) Gecko/20020603 Beonex/0.8-stable\nmozilla\t1.0.2\tMozilla/5.0 (Windows; U; WinNT; en; rv:1.0.2) Gecko/20030311 Beonex/0.8.2-stable\nmozilla\t1.9\tMozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9) Gecko/2008120120 Blackbird/0.9991\nwebkit\t527\tMozilla/5.0 (X11; 78; CentOS; US-en) AppleWebKit/527+ (KHTML, like Gecko) Bolt/0.862 Version/3.0 Safari/523.15\nmsie\t6.0\tMozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; Browzar)\n\t0\tBunjalloo/0.7.4(Nintendo DS;U;en)\n\t0\tBunjalloo/0.7.6(Nintendo DS;U;en)\nmozilla\t1.8.1.4pre\tMozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en; rv:1.8.1.4pre) Gecko/20070511 Camino/1.6pre\nmozilla\t1.7.2\tMozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.7.2) Gecko/20040825 Camino/0.8.1\nmozilla\t1.8.1.12\tMozilla/5.0 (Macintosh; U; Intel Mac OS X Mach-O; en; rv:1.8.1.12) Gecko/20080206 Camino/1.5.5\nmozilla\t1.0.1\tMozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.0.1) Gecko/20030111 Chimera/0.6\nmozilla\t1.8.0.10\tMozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.8.0.10) Gecko/20070228 Camino/1.0.4\nwebkit\t418.9\tMozilla/5.0 (Macintosh; U; PPC Mac OS X; en) AppleWebKit/418.9 (KHTML, like Gecko, Safari) Safari/419.3 Cheshire/1.0.ALPHA\nwebkit\t419\tMozilla/5.0 (Macintosh; U; PPC Mac OS X; en) AppleWebKit/419 (KHTML, like Gecko, Safari/419.3) Cheshire/1.0.ALPHA\nchrome\t1.0.154.36\tMozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/525.19 (KHTML, like Gecko) Chrome/1.0.154.36 Safari/525.19\nchrome\t1.0.154.53\tMozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/525.19 (KHTML, like Gecko) Chrome/1.0.154.53 Safari/525.19\nmozilla\t1.9.0.10\tMozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.0.10) Gecko/2009042815 Firefox/3.0.10 CometBird/3.0.10\nmozilla\t1.9.0.5\tMozilla/5.0 (Windows; U; Windows NT 6.0; en-US; rv:1.9.0.5) Gecko/2009011615 Firefox/3.0.5 CometBird/3.0.5\nmsie\t7.0\tMozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; .NET CLR 1.1.4322; .NET CLR 2.0.50727; Crazy Browser 3.0.0 Beta2)\nmsie\t6.0\tMozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; Crazy Browser 2.0.1)\nmsie\t6.0\tMozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; Crazy Browser 1.0.5; .NET CLR 1.1.4322; InfoPath.1)\nmsie\t6.0\tMozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Deepnet Explorer 1.5.0; .NET CLR 1.0.3705)\nwebkit\t525.27.1\tMozilla/5.0 (Macintosh; U; Intel Mac OS X 10_5_6; en-us) AppleWebKit/525.27.1 (KHTML, like Gecko) Demeter/1.0.9 Safari/125\nwebkit\t312.8\tMozilla/5.0 (Macintosh; U; PPC Mac OS X; pl-pl) AppleWebKit/312.8 (KHTML, like Gecko, Safari) DeskBrowse/1.0\n\t0\tDillo/0.8.5\n\t0\tDillo/2.0\n\t0\tDocZilla/1.0 (Windows; U; WinNT4.0; en-US; rv:1.0.0) Gecko/20020804\n\t0\tDocZilla/2.7 (Windows; U; Windows NT 5.1; en-US; rv:2.7.0) Gecko/20050706 CiTEC Information\nwebkit\t527\tMozilla/5.0 (Windows; U; Windows NT 5.1; cs-CZ) AppleWebKit/527+ (KHTML, like Gecko, Safari/419.3)  Dooble\n\t0\tDoris/1.15 [en] (Symbian)\n\t0\tedbrowse/1.5.17-2\n\t0\tedbrowse/2.2.10\n\t0\tedbrowse/3.1.2-1\n\t0\tELinks/0.13.GIT (textmode; Linux 2.6.22-2-686 i686; 148x68-3)\n\t0\tELinks/0.9.3 (textmode; Linux 2.6.11 i686; 79x24)\n\t0\tEnigma Browser\nmozilla\t1.8.1.12\tMozilla/5.0 (X11; U; Linux i686; en; rv:1.8.1.12) Gecko/20080208 (Debian-1.8.1.12-2) Epiphany/2.20\nmozilla\t1.9.0.12\tMozilla/5.0 (X11; U; Linux x86_64; en; rv:1.9.0.12) Gecko/20080528 Fedora/2.24.3-8.fc10 Epiphany/2.22 Firefox/3.0\nmozilla\t1.7.3\tMozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.3) Gecko/20041007 Epiphany/1.4.7\nmozilla\t1.5\tMozilla/5.0 (Windows; U; Win98; en-US; rv:1.5) Gecko/20031007 Firebird/0.7\nmozilla\t1.5\tMozilla/5.0 (Windows; U; Win95; en-US; rv:1.5) Gecko/20031007 Firebird/0.7\nmozilla\t1.8.0.3\tMozilla/5.0 (Windows; U; Windows NT 5.0; es-ES; rv:1.8.0.3) Gecko/20060426 Firefox/1.5.0.3\nmozilla\t1.9.1b2\tMozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; ko; rv:1.9.1b2) Gecko/20081201 Firefox/3.1b2\nmozilla\t1.9.0.8\tMozilla/5.0 (Windows; U; Windows NT 5.1; cs; rv:1.9.0.8) Gecko/2009032609 Firefox/3.0.8\nmozilla\t1.7.9\tMozilla/5.0 (Windows; U; WinNT4.0; en-US; rv:1.7.9) Gecko/20050711 Firefox/1.0.5\nmozilla\t1.9b5\tMozilla/5.0 (X11; U; SunOS sun4u; en-US; rv:1.9b5) Gecko/2008032620 Firefox/3.0b5\nmozilla\t1.8.0.5\tMozilla/5.0 (X11; U; OpenBSD i386; en-US; rv:1.8.0.5) Gecko/20060819 Firefox/1.5.0.5\nmozilla\t1.9.1b3\tMozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.1b3) Gecko/20090305 Firefox/3.1b3 GTB5\nmozilla\t1.8.1.12\tMozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.8.1.12) Gecko/20080214 Firefox/2.0.0.12\nmozilla\t1.8.1.9\tMozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.1.9) Gecko/20071113 BonEcho/2.0.0.9\nmozilla\t1.8.1\tMozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.1) Gecko/20061026 BonEcho/2.0\nmozilla\t1.8.1.21pre\tMozilla/5.0 (BeOS; U; Haiku BePC; en-US; rv:1.8.1.21pre) Gecko/20090227 BonEcho/2.0.0.21pre\nmozilla\t1.9.0.8\tMozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.8) Gecko/2009033017 GranParadiso/3.0.8\nmozilla\t1.9.2a2pre\tMozilla/5.0 (Windows; U; Windows NT 6.1; cs; rv:1.9.2a2pre) Gecko/20090912 Namoroka/3.6a2pre (.NET CLR 3.5.30729)\nmozilla\t1.9.2a2pre\tMozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2a2pre) Gecko/20090901 Ubuntu/9.10 (karmic) Namoroka/3.6a2pre\nmozilla\t1.9.2a1\tMozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.2a1) Gecko/20090806 Namoroka/3.6a1\nmozilla\t1.9.1b3pre\tMozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.1b3pre) Gecko/20090109 Shiretoko/3.1b3pre\nmozilla\t1.9.1b4pre\tMozilla/5.0 (Windows; U; Windows NT 6.0; en-US; rv:1.9.1b4pre) Gecko/20090311 Shiretoko/3.1b4pre\nmozilla\t1.8.0.1\tMozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.8.0.1) Gecko/20060314 Flock/0.5.13.2\nmozilla\t1.9.0.2\tMozilla/5.0 (Windows; U; Windows NT 6.0; en-US; rv:1.9.0.2) Gecko/2008092122 Firefox/3.0.2 Flock/2.0b3\nwebkit\t525.13\tMozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/525.13 (KHTML, like Gecko) Fluid/0.9.4 Safari/525.13\nmozilla\t1.7.12\tMozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.12) Gecko/20050929 Galeon/1.3.21\nmozilla\t1.9.0.8\tMozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.8) Gecko/20090327 Galeon/2.0.7\nmozilla\t1.9.1.5\tMozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1.5) Gecko/20091105 Firefox/3.5.5 compat GlobalMojo/1.5.5 GlobalMojoExt/1.5\nmsie\t6.0\tMozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; GreenBrowser)\nmsie\t7.0\tMozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; .NET CLR 2.0.50727; GreenBrowser)\nmsie\t7.0\tMozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; .NET CLR 1.1.4322; InfoPath.1; .NET CLR 2.0.50727; .NET CLR 3.0.04506.30; GreenBrowser)\n\t0\tHotJava/1.1.2 FCS\nmozilla\t0\tMozilla/3.0 (x86 [cs] Windows NT 5.1; Sun)\nmozilla\t1.8.0.3\tMozilla/5.1 (X11; U; Linux i686; en-US; rv:1.8.0.3) Gecko/20060425 SUSE/1.5.0.3-7 Hv3/alpha\nmsie\t7.0\tMozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Trident/4.0; SIMBAR={CFBFDAEA-F21E-4D6E-A9B0-E100A69B860F}; Hydra Browser; .NET CLR 2.0.50727; .NET CLR 1.1.4322; .NET CLR 3.0.04506.30)\nmsie\t6.0\tMozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; Hydra Browser; .NET CLR 2.0.50727; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729)\n\t0\tIBrowse/2.3 (AmigaOS 3.9)\n\t0\tMozilla/5.0 (compatible; IBrowse 3.0; AmigaOS4.0)\n\t0\tiCab/4.0 (Macintosh; U; Intel Mac OS X)\n\t0\tMozilla/4.5 (compatible; iCab 2.9.1; Macintosh; U; PPC)\n\t0\tiCab/3.0.2 (Macintosh; U; PPC Mac OS X)\n\t0\tICE Browser/v5_4_3 (Java 1.4.2; Windows XP 5.1 x86)\nmozilla\t0\tMozilla/5.0 (Java 1.6.0_01; Windows XP 5.1 x86; en) ICEbrowser/v6_1_2\n\t0\tICE Browser/5.05 (Java 1.4.0; Windows 2000 5.0 x86)\nmozilla\t1.8.1.9\tMozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.1.9) Gecko/20071030 Iceape/1.1.6 (Debian-1.1.6-3)\nmozilla\t1.8.1.8\tMozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.8.1.8) Gecko/20071008 Iceape/1.1.5 (Ubuntu-1.1.5-1ubuntu0.7.10)\nmozilla\t1.9.0.3\tMozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.3) Gecko/2008092921 IceCat/3.0.3-g1\nmozilla\t1.8.1.11\tMozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.1.11) Gecko/20071203 IceCat/2.0.0.11-g1\nmozilla\t1.9.0.5\tMozilla/5.0 (X11; U; Linux i686; de; rv:1.9.0.5) Gecko/2008122011 Iceweasel/3.0.5 (Debian-3.0.5-1)\nmozilla\t1.8.1.1\tMozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.8.1.1) Gecko/20061205 Iceweasel/2.0.0.1 (Debian-2.0.0.1+dfsg-4)\nmozilla\t1.9.0.5\tMozilla/5.0 (X11; U; Linux i686; it; rv:1.9.0.5) Gecko/2008122011 Iceweasel/3.0.5 (Debian-3.0.5-1)\nmsie\t4.0\tMozilla/2.0 (compatible; MSIE 4.0; Windows 98)\nmsie\t6.0\tMozilla/4.0 (Windows; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 2.0.50727)\nmsie\t7.0\tMozilla/4.0 (Mozilla/4.0; MSIE 7.0; Windows NT 5.1; FDM; SV1; .NET CLR 3.0.04506.30)\nmsie\t5.01\tMozilla/4.0 (compatible; MSIE 5.01; Windows NT)\nmsie\t8.0\tMozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0; SLCC1; .NET CLR 2.0.50727; .NET CLR 1.1.4322; InfoPath.2; .NET CLR 3.5.21022; .NET CLR 3.5.30729; MS-RTC LM 8; OfficeLiveConnector.1.4; OfficeLivePatch.1.3; .NET CLR 3.0.30729)\nmsie\t6.0\tMozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.0.3705; .NET CLR 1.1.4322; Media Center PC 4.0; .NET CLR 2.0.50727)\nmsie\t5.0b1\tMozilla/4.0 (compatible; MSIE 5.0b1; Mac_PowerPC)\nmsie\t5.0\tMozilla/4.0 (compatible; MSIE 5.0; Windows NT;)\nmsie\t5.23\tMozilla/4.0 (compatible; MSIE 5.23; Mac_PowerPC)\nmsie\t6.0\tMozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; GTB6; Ant.com Toolbar 1.6; MSIECrawler)\nmsie\t8.0\tMozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0; GTB5; SLCC1; .NET CLR 2.0.50727; Media Center PC 5.0; .NET CLR 3.0.04506; InfoPath.2; OfficeLiveConnector.1.3; OfficeLivePatch.0.0)\nmsie\t7.0\tMozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; Trident/4.0; SLCC1; .NET CLR 2.0.50727; .NET CLR 1.1.4322; InfoPath.2; .NET CLR 3.5.21022; .NET CLR 3.5.30729; MS-RTC LM 8; OfficeLiveConnector.1.4; OfficeLivePatch.1.3; .NET CLR 3.0.30729)\nmsie\t7.0\tMozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; InfoPath.2)\nmsie\t6.0\tMozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; iRider 2.21.1108; FDM)\nwebkit\t528.5\tMozilla/5.0 (Windows; U; Windows NT 6.0; en-US) AppleWebKit/528.5 (KHTML, like Gecko) Iron/0.4.155.0 Safari/528.5\nwebkit\t528.7\tMozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/528.7 (KHTML, like Gecko) Iron/1.0.155.0 Safari/528.7\nwebkit\t525.19\tMozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/525.19 (KHTML, like Gecko) Iron/0.2.152.0 Safari/12081672.525\nwebkit\t531.0\tMozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/531.0 (KHTML, like Gecko) Iron/3.0.189.0 Safari/531.0\nmozilla\t1.8.1.19\tMozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.8.1.19) Gecko/20081217 K-Meleon/1.5.2\nmozilla\t1.8.1.21\tMozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.21) Gecko/20090331 K-Meleon/1.5.3\nmozilla\t1.8.0.5\tMozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.0.5) Gecko/20060706 K-Meleon/1.0\nmozilla\t1.8.1.21\tMozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.8.1.21) Gecko/20090331 K-Meleon/1.5.3\nmozilla\t1.8.0.6\tMozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.0.6) Gecko/20060731 K-Ninja/2.0.2\nmozilla\t1.8.1.4pre\tMozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.4pre) Gecko/20070404 K-Ninja/2.1.3\nmozilla\t1.8.1.2pre\tMozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.2pre) Gecko/20070215 K-Ninja/2.1.1\nmozilla\t1.9\tMozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9) Gecko/20080705 Firefox/3.0 Kapiko/3.0\nmozilla\t0\tMozilla/5.0 (X11; Linux i686; U;) Gecko/20070322 Kazehakase/0.4.5\nmozilla\t1.9.0.8\tMozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.8) Gecko Fedora/1.9.0.8-1.fc10 Kazehakase/0.5.6\nmsie\t6.0\tMozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; KKman2.0)\nmsie\t6.0\tMozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; KKMAN3.2)\nmsie\t6.0\tMozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; KKman3.0)\n\t0\tMozilla/5.0 (compatible; Konqueror/3.1-rc5; i686 Linux; 20020712)\n\t0\tMozilla/5.0 (compatible; Konqueror/4.3; Windows) KHTML/4.3.0 (like Gecko)\n\t0\tMozilla/5.0 (compatible; Konqueror/2.2.1; Linux)\n\t0\tMozilla/5.0 (compatible; Konqueror/3.5; SunOS)\n\t0\tMozilla/5.0 (compatible; Konqueror/4.1; OpenBSD) KHTML/4.1.4 (like Gecko)\n\t0\tLinks (0.96; Linux 2.4.20-18.7 i586)\n\t0\tLinks (0.98; Win32; 80x25)\n\t0\tLinks (2.1pre18; Linux 2.4.31 i686; 100x37)\n\t0\tLinks (2.1; Linux 2.6.18-gentoo-r6 x86_64; 80x24)\n\t0\tLinks (2.2; Linux 2.6.25-gentoo-r9 sparc64; 166x52)\nmsie\t6.0\tMozilla/4.0 (compatible; MSIE 6.0; Linux 2.6.26-1-amd64) Lobo/0.98.3\nmsie\t6.0\tMozilla/4.0 (compatible; MSIE 6.0; Windows XP 5.1) Lobo/0.98.4\n\t0\tMozilla/4.0 (compatible; Lotus-Notes/5.0; Windows-NT)\n\t0\tMozilla/4.0 (compatible; Lotus-Notes/6.0; Windows-NT)\nmsie\t6.0\tMozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; .NET CLR 1.1.4322; Lunascape 2.1.3)\nmozilla\t1.9.1b3pre\tMozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.1b3pre) Gecko/2008 Lunascape/4.9.9.98\nmsie\t6.0\tMozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; JyxoToolbar1.0; .NET CLR 2.0.50727; .NET CLR 3.0.04506.648; .NET CLR 3.5.21022; .NET CLR 1.1.4322; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729; Lunascape 5.1.4.5)\nwebkit\t528\tMozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/528+ (KHTML, like Gecko, Safari/528.0) Lunascape/5.0.2.0\nmozilla\t1.9.1.2\tMozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.1.2) Gecko/20090804 Firefox/3.5.2 Lunascape/5.1.4.5\n\t0\tLynx/2.8.6rel.4 libwww-FM/2.14 SSL-MM/1.4.1 GNUTLS/1.6.3\n\t0\tLynx/2.8.3dev.6 libwww-FM/2.14\n\t0\tLynx/2.8.5dev.16 libwww-FM/2.14 SSL-MM/1.4.1 OpenSSL/0.9.7a\nmozilla\t1.7.12\tMozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.12) Gecko/20051001 Firefox/1.0.7 Madfox/0.3.2u3\nwebkit\t530.6\tMozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/530.6 (KHTML, like Gecko) Maxthon/3.0 Safari/530.6\nmsie\t7.0\tMozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; SV1; Maxthon; .NET CLR 1.1.4322)\nmsie\t6.0\tMozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; MyIE2)\nmsie\t8.0\tMozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; .NET CLR 2.0.50727; MAXTHON 2.0)\n\t0\tMidori/0.1.7\nwebkit\t532\tMidori/0.1.5 (X11; Linux; U; en-gb) WebKit/532+\nmozilla\t1.0.1\tMozilla/5.0 (X11; U; Linux i686; en-US; rv:1.0.1) Gecko/20020919\nmozilla\t1.7.12\tMozilla/5.0 (Windows; U; Windows NT 5.0; it-IT; rv:1.7.12) Gecko/20050915\nmozilla\t1.4\tMozilla/5.0 (X11; U; Linux i686; en-US; rv:1.4; MultiZilla v1.5.0.0f) Gecko/20030624\nmozilla\t1.2.1\tMozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.2.1; MultiZilla v1.1.32 final) Gecko/20021130\n\t0\tNCSA_Mosaic/2.0 (Windows 3.1)\n\t0\tNCSA_Mosaic/3.0 (Windows 95)\n\t0\tNCSA Mosaic/1.0 (X11;SunOS 4.1.4 sun4m)\n\t0\tNCSA_Mosaic/2.6 (X11; SunOS 4.1.3 sun4m)\n\t0\tMozilla/3.01 (compatible; Netbox/3.5 R92; Linux 2.2)\nmsie\t6.0\tMozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; NetCaptor 7.5.4; .NET CLR 2.0.50727; .NET CLR 3.0.04506.648; .NET CLR 3.5.21022; .NET CLR 1.1.4322; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729)\nmsie\t5.01\tMozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0; NetCaptor 6.5.0RC1)\nmozilla\t1.7.5\tMozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.5) Gecko/20060127 Netscape/8.1\nmozilla\t0\tMozilla/4.04 [en] (X11; I; IRIX 5.3 IP22)\nmozilla\t0.9.2\tMozilla/5.0 (Windows; U; Win 9x 4.90; de-DE; rv:0.9.2) Gecko/20010726 Netscape6/6.1\nmozilla\t1.8.1.12\tMozilla/5.0 (Windows; U; Windows NT 6.0; en-US; rv:1.8.1.12) Gecko/20080219 Firefox/2.0.0.12 Navigator/9.0.0.6\nmozilla\t0\tMozilla/4.08 [en] (WinNT; U ;Nav)\nmozilla\t1.0.2\tMozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.0.2) Gecko/20030208 Netscape/7.02\nmozilla\t0\tMozilla/3.0 (Win95; I)\nmozilla\t0\tMozilla/4.51 [en] (Win98; U)\n\t0\tNetSurf/2.0 (RISC OS; armv3l)\n\t0\tNetSurf/1.2 (Linux; i686)\n\t0\tMozilla/4.7 (compatible; OffByOne; Windows 2000)\n\t0\tMozilla/4.7 (compatible; OffByOne; Windows 98)\n\t0\tMozilla/4.5 (compatible; OmniWeb/4.1.1-v424.6; Mac_PowerPC)\n\t0\tOmniWeb/2.7-beta-3 OWF/1.0\nwebkit\t420\tMozilla/5.0 (Macintosh; U; PPC Mac OS X; en-US) AppleWebKit/420+ (KHTML, like Gecko, Safari) OmniWeb/v595\nopera\t6.0\tOpera/6.0 (Windows 2000; U) [fr]\nopera\t7.10\tMozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1) Opera 7.10 [en]\nopera\t10.00\tOpera/9.80 (Windows NT 5.1; U; cs) Presto/2.2.15 Version/10.00\nopera\t5.11\tOpera/5.11 (Windows 98; U) [en]\nopera\t9.51\tOpera/9.51 (Macintosh; Intel Mac OS X; U; en)\nopera\t6.01\tMozilla/4.0 (compatible; MSIE 5.0; Windows NT 4.0) Opera 6.01 [en]\nopera\t9.02\tOpera/9.02 (Windows XP; U; ru)\nopera\t5.12\tMozilla/4.0 (compatible; MSIE 5.0; Windows 98) Opera 5.12 [en]\nopera\t9.70\tOpera/9.70 (Linux i686 ; U; en) Presto/2.2.1\nopera\t7.03\tOpera/7.03 (Windows NT 5.0; U) [en]\nopera\t9.24\tMozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; en) Opera 9.24\nmozilla\t1.9.0.7\tMozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.0.7) Gecko/2009030821 Firefox/3.0.7 Orca/1.1 build 2\nmozilla\t1.9.0.6\tMozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.0.6) Gecko/2009022300 Firefox/3.0.6 Orca/1.1 build 1\n\t0\tMozilla/1.10 [en] (Compatible; RISC OS 3.70; Oregano 1.10)\nwebkit\t530.0\tMozilla/5.0 (compatible; Origyn Web Browser; AmigaOS 4.1; ppc; U; en) AppleWebKit/530.0+ (KHTML, like Gecko, Safari/530.0+)\nwebkit\t531.0\tMozilla/5.0 (compatible; Origyn Web Browser; AmigaOS 4.0; U; en) AppleWebKit/531.0+ (KHTML, like Gecko, Safari/531.0+)\nwebkit\t528.5\tMozilla/5.0 (compatible; Origyn Web Browser; MorphOS; PPC; U) AppleWebKit/528.5+ (KHTML, like Gecko, Safari/528.5+)\nmsie\t6.0\tMozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; PhaseOut-www.phaseout.net)\nmozilla\t1.4a\tMozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.4a) Gecko/20030411 Phoenix/0.5\nmozilla\t1.2b\tMozilla/5.0 (X11; U; Linux i686; en-US; rv:1.2b) Gecko/20021029 Phoenix/0.4\nwebkit\t527\tMozilla/5.0 (Windows; U; Windows NT 5.1; cs-CZ) AppleWebKit/527+ (KHTML, like Gecko)  QtWeb Internet Browser/2.5 http://www.QtWeb.net\nwebkit\t527\tMozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/527+ (KHTML, like Gecko) QtWeb Internet Browser/1.2 http://www.QtWeb.net\nwebkit\t527\tMozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/527+ (KHTML, like Gecko) QtWeb Internet Browser/1.7 http://www.QtWeb.net\nwebkit\t527\tMozilla/5.0 (X11; U; Linux; cs-CZ) AppleWebKit/527+ (KHTML, like Gecko, Safari/419.3)  rekonq\n\t0\tretawq/0.2.6c [en] (text)\nwebkit\t312.8\tMozilla/5.0 (Macintosh; U; PPC Mac OS X; en-us) AppleWebKit/312.8 (KHTML, like Gecko) Safari/312.6\nwebkit\t528.16\tMozilla/5.0 (Macintosh; U; PPC Mac OS X 10_5_6; it-it) AppleWebKit/528.16 (KHTML, like Gecko) Version/4.0 Safari/528.16\nwebkit\t523.15\tMozilla/5.0 (Windows; U; Windows NT 5.1; cs-CZ) AppleWebKit/523.15 (KHTML, like Gecko) Version/3.0 Safari/523.15\nwebkit\t125.2\tMozilla/5.0 (Macintosh; U; PPC Mac OS X; de-de) AppleWebKit/125.2 (KHTML, like Gecko) Safari/125.7\nwebkit\t528.16\tMozilla/5.0 (Windows; U; Windows NT 6.0; en-US) AppleWebKit/528.16 (KHTML, like Gecko) Version/4.0 Safari/528.16\nwebkit\t420\tMozilla/5.0 (Macintosh; U; PPC Mac OS X; fi-fi) AppleWebKit/420+ (KHTML, like Gecko) Safari/419.3\nmozilla\t1.8.1.13\tMozilla/5.0 (Macintosh; U; Intel Mac OS X; en-US; rv:1.8.1.13) Gecko/20080313 SeaMonkey/1.1.9\nmozilla\t1.9.1a2pre\tMozilla/5.0 (X11; U; Linux i686; rv:1.9.1a2pre) Gecko/20080824052448 SeaMonkey/2.0a1pre\nmozilla\t1.8.1.6\tMozilla/5.0 (Windows; U; Win 9x 4.90; en-GB; rv:1.8.1.6) Gecko/20070802 SeaMonkey/1.1.4\nmozilla\t1.9.1b3pre\tMozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1b3pre) Gecko/20081208 SeaMonkey/2.0a3pre\nmozilla\t1.9a1\tMozilla/5.0 (BeOS; U; BeOS BePC; en-US; rv:1.9a1) Gecko/20060702 SeaMonkey/1.5a\nmozilla\t1.9.1b3pre\tMozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.1b3pre) Gecko/20081202 SeaMonkey/2.0a2\nwebkit\t419\tMozilla/5.0 (Macintosh; U; PPC Mac OS X; ja-jp) AppleWebKit/419 (KHTML, like Gecko) Shiira/1.2.3 Safari/125\nwebkit\t417.9\tMozilla/5.0 (Macintosh; U; PPC Mac OS X; en) AppleWebKit/417.9 (KHTML, like Gecko, Safari) Shiira/1.1\nwebkit\t418.9.1\tMozilla/5.0 (Macintosh; U; Intel Mac OS X; fr) AppleWebKit/418.9.1 (KHTML, like Gecko) Shiira Safari/125\nmsie\t6.0\tMozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1) Sleipnir/2.8.1\nmsie\t7.0\tMozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; .NET CLR 1.1.4322; InfoPath.1; .NET CLR 2.0.50727) Sleipnir/2.8.4\nwebkit\t525.27.1\tMozilla/5.0 (Macintosh; U; Intel Mac OS X 10_5_5; en-us) AppleWebKit/525.27.1 (KHTML, like Gecko) Stainless/0.4 Safari/525.20.1\nwebkit\t528.16\tMozilla/5.0 (Macintosh; U; Intel Mac OS X 10_5_6; en-us) AppleWebKit/528.16 (KHTML, like Gecko) Stainless/0.5.3 Safari/525.20.1\nwebkit\t525.18\tMozilla/5.0 (Macintosh; U; Intel Mac OS X 10_4_11; en) AppleWebKit/525.18 (KHTML, like Gecko) Sunrise/1.7.4 like Safari/4525.22\nwebkit\t125.5.7\tMozilla/5.0 (Macintosh; U; PPC Mac OS X; en-us) AppleWebKit/125.5.7 (KHTML, like Gecko) SunriseBrowser/0.853\nmozilla\t1.9.0.10pre\tMozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.10pre) Gecko/2009041814 Firefox/3.0.10pre (Swiftfox)\nmsie\t6.0\tMozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 2.0.50727; .NET CLR 3.0.04506.648; .NET CLR 3.5.21022; .NET CLR 1.1.4322; TheWorld)\nwebkit\t1.1.8\tWebkit/1.1.8 (Linux; en-us) Uzbl\nwebkit\t1.1.10\tUzbl (X11; U; Linux x86_64; en-GB) AppleWebkit/1.1.10\nwebkit\t1.1.9\tUzbl (Webkit 1.1.9) (Linux)\nwebkit\t1.1.10\tUzbl (U; Linux x86_64; en-GB) Webkit 1.1.10\n\t0\tw3m/0.5.1\n\t0\tw3m/0.5.2\nwebkit\t103u\tMozilla/5.0 (Macintosh; U; PPC Mac OS X; en-us) AppleWebKit/103u (KHTML, like Gecko) wKiosk/100\nmozilla\t1.9.0.9\tMozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.0.9) Gecko/2009042410 Firefox/3.0.9 Wyzo/3.0.3\n\t0\tX-Smiles/1.2-20081113\nmsie\t7.0\tMozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1) ; .NET CLR 2.0.50727; .NET CLR 1.1.4322; .NET CLR 3.0.04506.30; MEGAUPLOAD 2.0)\nmsie\t7.0\tMozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1) ; .NET CLR 1.1.4322; .NET CLR 2.0.50727; .NET CLR 3.0.04506.30)\nmozilla\t1.9.0.4\tMozilla/5.0 (X11; U; Linux i686; en-GB; rv:1.9.0.4) Gecko/2008111217 Fedora/3.0.4-1.fc9 Firefox/3.0.4\nmozilla\t1.9.0.4\tMozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.0.4) Gecko/2008102920 Firefox/3.0.4\nmsie\t7.0\tMozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1) ; SLCC1; .NET CLR 2.0.50727; Media Center PC 5.0; .NET CLR 3.0.04506; .NET CLR 1.1.4322; FDM)\nmsie\t6.0\tmozilla/4.0 (compatible; msie 6.0; windows nt 5.1; mra 4.6 (build 01425); .net clr 2.0.50727)\nmsie\t7.0\tmozilla/4.0 (compatible; msie 7.0; windows nt 5.1; mra 4.9 (build 01863))\nmsie\t7.0\tMozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1) ; SLCC1; .NET CLR 2.0.50727; Media Center PC 5.0; InfoPath?.2; .NET CLR 3.5.21022; .NET CLR 3.5.30729; .NET CLR 3.0.30618; MS-RTC LM 8; .NET CLR 1.1.4322)\nmsie\t7.0\tMozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; SLCC1; .NET CLR 2.0.50727; .NET CLR 3.0.04506; InfoPath?.2; .NET CLR 3.5.21022)\nmsie\t7.0\tMozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Sky Broadband; Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1) ; .NET CLR 1.1.4322)\nmsie\t7.0\tMozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1) ; SLCC1; .NET CLR 2.0.50727; Media Center PC 5.0; InfoPath.2; .NET CLR 3.5.21022; .NET CLR 3.5.30729; .NET CLR 3.0.30618; MS-RTC LM 8; .NET CLR 1.1.4322)\nmsie\t7.0\tMozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; SLCC1; .NET CLR 2.0.50727; .NET CLR 3.0.04506; InfoPath.2; .NET CLR 3.5.21022)\nmsie\t7.0\tMozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; GTB6; User-agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; http://bsalsa.com); .NET CLR 1.1.4322; .NET CLR 2.0.50727\nopera\t10.00\tOpera/9.80 (Macintosh; Intel Mac OS X; U; en) Presto/2.2.15 Version/10.00\nmsie\t8.0\tMozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1) ; .NET CLR 1.1.4322; InfoPath?.2; .NET CLR 2.0.50727; CIBA; .NET CLR 3.0.04506.648; .NET CLR 3.5.21022; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729)\nopera\t10.00\tOpera/9.80 (X11; Linux x86_64; U; de) Presto/2.2.15 Version/10.00\nopera\t10.50\tOpera/9.80 (Macintosh; Intel Mac OS X; U; en) Presto/2.5.18 Version/10.50\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/jquery/test/data/with_fries.xml",
    "content": "<?xml version='1.0' encoding='UTF-8'?>\n<soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\"\n\txmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"\n\txmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\n\t<soap:Body>\n\t\t<jsconf xmlns=\"http://example.com/ns1\">\n\t\t\t<response xmlns:ab=\"http://example.com/ns2\">\n\t\t\t\t<meta>\n\t\t\t\t\t<component id=\"seite1\" class=\"component\">\n\t\t\t\t\t\t<properties xmlns:cd=\"http://example.com/ns3\">\n\t\t\t\t\t\t\t<property name=\"prop1\">\n\t\t\t\t\t\t\t\t<thing />\n\t\t\t\t\t\t\t\t<value>1</value>\n\t\t\t\t\t\t\t</property>\n\t\t\t\t\t\t\t<property name=\"prop2\">\n\t\t\t\t\t\t\t\t<thing att=\"something\" />\n\t\t\t\t\t\t\t</property>\n\t\t\t\t\t\t\t<foo_bar>foo</foo_bar>\n\t\t\t\t\t\t</properties>\n\t\t\t\t\t</component>\n\t\t\t\t</meta>\n\t\t\t</response>\n\t\t</jsconf>\n\t</soap:Body>\n</soap:Envelope>\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/jquery/test/data/with_fries_over_jsonp.php",
    "content": "<?php\nerror_reporting(0);\n$callback = $_REQUEST['callback'];\n$json = $_REQUEST['json'];\n$text = json_encode(file_get_contents(dirname(__FILE__).\"/with_fries.xml\"));\necho \"$callback($text)\";\n?>\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/jquery/test/delegatetest.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n<title>Event Delegation Tests</title>\n<script src=\"jquery.js\"></script>\n<style>\ntable {\n\tborder-collapse: collapse;\n\tempty-cells: show;\n}\nth {\n\ttext-align: left;\n}\nthead td {\n\twidth: 11%;\n}\ntbody td {\n\tbackground: #fed;\n}\nth, td {\n\tborder: 1px solid #bbb;\n}\n</style>\n</head>\n<body>\n<h2>Delegate Tests (<span id=\"fileversion\">x</span>)</h2>\n\n<table id=\"changes\">\n<thead>\n\t<tr>\n\t\t<th>\n\t\t\tControls:\n\t\t</th>\n\t\t<td id=\"select-one\">\n\t\t\t<select>\n\t\t\t\t<option value='one1'>one1</option>\n\t\t\t\t<option value='one2'>one2</option>\n\t\t\t\t<option value='one3'>one3</option>\n\t\t\t</select>\n\t\t\t<select>\n\t\t\t\t<option value='two1'>two1</option>\n\t\t\t\t<option value='two2' selected=\"selected\">two2</option>\n\t\t\t\t<option value='two3'>two3</option>\n\t\t\t</select>\n\t\t</td>\n\t\t<td id=\"select-mult\">\n\t\t\t<select multiple=\"multiple\">\n\t\t\t\t<option value='multi1'>multi1</option>\n\t\t\t\t<option value='multi2'>multi2</option>\n\t\t\t\t<option value='multi3'>multi3</option>\n\t\t\t</select>\n\t\t</td>\n\t\t<td id=\"checkbox\">\n\t\t\t<input type=\"checkbox\" name=\"mycheckbox\" id=\"check1\"/>\n\t\t\t<label for=\"check1\">check1</label><br/>\n\t\t\t<input type=\"checkbox\" name=\"mycheckbox\" id=\"check2\"/>\n\t\t\t<label for=\"check2\">check2</label><br />\n\t\t\t<input type=\"checkbox\" name=\"mycheckbox\" id=\"check3\" disabled=\"disabled\"/>\n\t\t\t<label for=\"check3\">check3</label>\n\t\t</td>\n\t\t<td id=\"radio\">\n\t\t\t<input type=\"radio\" name=\"myradio\" id=\"radio1\"/>\n\t\t\t<label for=\"radio1\">Radio1</label><br/>\n\t\t\t<input type=\"radio\" name=\"myradio\" id=\"radio2\"/>\n\t\t\t<label for=\"radio2\">Radio2</label><br />\n\t\t\t<input type=\"radio\" name=\"myradio\" id=\"radio3\" disabled=\"disabled\"/>\n\t\t\t<label for=\"radio3\">Radio3</label>\n\t\t</td>\n\t\t<td id=\"file\">\n\t\t\t<input class=\"file_test\" id=\"file1\" type=\"file\"/>\n\t\t</td>\n\t\t<td id=\"text\">\n\t\t\t<input class='test' value='' id='input' size='10' />\n\t\t\t<input class='test' value='test' id='input2' size='10' readonly=\"readonly\" />\n\t\t</td>\n\t\t<td id=\"textarea\">\n\t\t\t<textarea rows='2'></textarea>\n\t\t</td>\n\t\t<td id=\"button\">\n\t\t\t<button name=\"mybutton1\" id=\"button1\">Button</button><br />\n\t\t\t<button name=\"mybutton2\" id=\"button2\"><span>Button w/ child</span></button><br />\n\t\t\t<button name=\"mybutton3\" id=\"button3\" disabled=\"disabled\">Button Disabled</button><br />\n\t\t\t<button name=\"mybutton4\" id=\"button4\" disabled=\"disabled\"><span disabled=\"disabled\">Button, child Disabled</span></button><br />\n\t\t</td>\n\t</tr>\n</thead>\n<tbody>\n</tbody>\n</table>\n<p>NOTE: Only IE supports propertychange, beforeactivate, beforedeactivate; buttons do not support change events.</p>\n\n<h2>Submit Tests</h2>\n<table>\n\t<tr>\n\t\t<td>\n\t\t\tSubmit each:\n\t\t</td>\n\t\t<td>\n\t\t\t<form action=\"\" id=\"text_submit\">\n\t\t\t\t<input class='test' type='text' value='Key Return To Submit'/>\n\t\t\t</form>\n\t\t</td>\n\t\t<td>\n\t\t\t<form action=\"\" id=\"password_submit\">\n\t\t\t\t<input class='test' type='password' value=''/>\n\t\t\t</form>\n\t\t</td>\n\t\t<td>\n\t\t\t<form action=\"\" id=\"submit_submit\">\n\t\t\t\t<input type='submit' value=\"Click Me To Submit\" />\n\t\t\t</form>\n\t\t</td>\n\t\t<td>$(document).bind('submit')</td>\n\t</tr>\n\t<tr>\n\t\t<td>Results:</td>\n\t\t<td id='textSubmit' class=\"red\">TEXT</td>\n\t\t<td id='passwordSubmit' class=\"red\">PASSWORD</td>\n\t\t<td id='submitSubmit' class=\"red\">BUTTON</td>\n\t\t<td id='boundSubmit' class=\"red\">DOCUMENT</td>\n\t</tr>\n</table>\n\n\t<form id=\"autosub\"><input type=submit name=subme /></form>\n\n<script type='text/javascript'>\n\n$(\"#fileversion\").text($.fn.jquery);\n\n// Try an auto-submit, it should only fire once\n$(function(){\n\tvar triggered = false;\n\t$(\"#autosub input\").trigger(\"keypress\");\n\t$(\"body\").on(\"submit\", \"#autosub\", function( e ){\n\t\te.preventDefault();\n\t\te.stopPropagation();\n\t\tif ( triggered ) {\n\t\t\talert(\"autosubmit FAIL\");\n\t\t}\n\t\ttriggered = true;\n\t});\n\t$(\"#autosub\").submit().remove();\n});\n\n// Events we want to track in row-order\nvar events = \"bind-change live-change onX-change bind-propertychange live-beforeactivate live-focusin bind-focus live-beforedeactivate live-focusout bind-blur live-click live-keydown\".split(\" \"),\n\tcounter = 0;\n\tblinker = function(event){\n\t\tif ( !counter ) {\n\t\t\t$(\"#changes tbody td\").text(\"\");\n\t\t}\n\t\tvar $el = event.data,\n\t\t\tprev = $el.text();\n\t\tprev = prev? prev +\" | \" : \"\";\n\t\treturn $el\n\t\t\t.text(prev + ++counter+\" \" + (this.value.replace(/^on$/,\"\") || this.id || this.checked || \"\"))\n\t\t\t.css(\"backgroundColor\",\"#0f0\")\n\t\t\t.delay(800)\n\t\t\t.queue(function(next){\n\t\t\t\t$el.css(\"backgroundColor\",\"#afa\");\n\t\t\t\t--counter;\n\t\t\t\tnext();\n\t\t\t});\n\t};\n\nfor ( var i=0; i < events.length; i++ ) {\n\tvar m = events[i].split(\"-\"),\n\t\tapi = m[0],\n\t\ttype = m[1],\n\t\t$row = $(\"<tr><th>\"+type+\" \"+api+\"</th></tr>\");\n\n\t$(\"#changes thead td\").each(function(){\n\t\tvar id = \"#\"+this.id,\n\t\t\t$cell = $('<td></td>');\n\t\tif ( api == \"onX\" ) {\n\t\t\t$(this).find(\"input, button, select, textarea\").each(function(){\n\t\t\t\tthis[\"on\"+type] = function(e){ e = $.event.fix(e||event); e.data = $cell; blinker.call(this, e); };\n\t\t\t});\n\t\t} else if ( api == \"bind\" ) {\n\t\t\t$(this).find(\"input, button, select, textarea\").bind(type, $cell, blinker);\n\t\t} else {\n\t\t\t$(id+\" input,\"+id+\" button,\"+id+\" select,\"+id+\" textarea\").live(type, $cell, blinker);\n\t\t}\n\t\t$row.append($cell);\n\t});\n\t$(\"#changes tbody\").append($row);\n}\n\n// Ensure that cloned elements get the delegated event magic; this is\n// implementation-specific knowledge but otherwise impossible to test.\n// The beforeactivate event attaches a direct-bound change event.\n// (Only care about the live change for this third select element.)\nvar sel1 = $(\"#select-one select:first-child\");\nif ( typeof(sel1[0].fireEvent) !== \"undefined\" ) {\n\tsel1.trigger( \"beforeactivate\" ).clone().appendTo(\"#select-one\");\n\t//alert($(\"#select-one select\").map(function(){ return this._change_attached || \"undef\"; }).get().join(\"|\"));\n}\n\njQuery.fn.blink = function(){\n\treturn this\n\t\t.css(\"backgroundColor\",\"green\")\n\t\t.text( (parseInt(this.text(), 10) || 0) + 1 )\n\t\t.delay(700).queue(function(next){\n\t\t\tjQuery(this).css(\"backgroundColor\",\"#afa\");\n\t\t\tnext();\n\t\t});\n};\n\njQuery.fn.addSubmitTest = function( id, prevent ) {\n\treturn this.live(\"submit\", function(e){\n\t\tif ( prevent ) {\n\t\t\t\te.preventDefault();\n\t\t}\n\t\tjQuery(id).blink();\n\t});\n};\n\n$(\"#text_submit\").addSubmitTest(\"#textSubmit\", true);\n$(\"#password_submit\").addSubmitTest(\"#passwordSubmit\", true);\n$(\"#submit_submit\").addSubmitTest(\"#submitSubmit\", true);\n$(\"#prog_submit\").addSubmitTest(\"#submitSubmit\", true);\n$(document).bind(\"submit\", function(){\n\tjQuery(\"#boundSubmit\").blink();\n});\n\n</script>\n</body>\n</html>\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/jquery/test/hovertest.html",
    "content": "<html>\n<head>\n<title>Hover tests</title>\n<script src=\"jquery.js\"></script>\n<style>\n/* Remove body dimensions so we can test enter/leave to surrounding browser chrome */\nbody, html {\n\tborder: 0;\n\tmargin: 0;\n\tpadding: 0;\n}\np {\n\tmargin: 2px 0;\n}\n.hover-box {\n\tbackground: #f33;\n\tpadding: 3px;\n\tmargin: 10px 40px 20px 0;\n}\n.hover-status {\n\tbackground: #f66;\n\tpadding: 1px;\n}\n.hover-inside {\n\tbackground: #6f6;\n\tpadding: 1px;\n\tmargin: 8px auto;\n\twidth: 40%;\n\ttext-align: center;\n}\n</style>\n </head>\n <body>\n\t<h2>Hover (mouse{over,out,enter,leave}) Tests</h2>\n\t<p>Be sure to try moving the mouse out of the browser via the left side on each test.</p>\n\t<div id=\"wrapper\">\n\n\t<div id=\"hoverbox\" class=\"hover-box\">\n\t\t<div class=\"hover-status\">\n\t\t\t<button>Activate</button>\n\t\t\t.hover() in/out: <span class=\"ins\">0</span> / <span class=\"outs\">0</span>\n\t\t</div>\n\t\t<div class=\"hover-inside\">\n\t\t\tMouse over here should NOT trigger the counter.\n\t\t</div>\n\t</div>\n\t<div id=\"liveenterbox\" class=\"hover-box\">\n\t\t<div class=\"hover-status\">\n\t\t\t<button>Activate</button>\n\t\t\tLive enter/leave: <span class=\"ins\">0</span> / <span class=\"outs\">0</span>\n\t\t</div>\n\t\t<div class=\"hover-inside\">\n\t\t\tMouse over here should NOT trigger the counter.\n\t\t</div>\n\t</div>\n\t<div id=\"delegateenterbox\" class=\"hover-box\">\n\t\t<div class=\"hover-status\">\n\t\t\t<button>Activate</button>\n\t\t\tDelegated enter/leave: <span class=\"ins\">0</span> / <span class=\"outs\">0</span>\n\t\t</div>\n\t\t<div class=\"hover-inside\">\n\t\t\tMouse over here should NOT trigger the counter.\n\t\t</div>\n\t</div>\n\n\t<div id=\"overbox\" class=\"hover-box\">\n\t\t<div class=\"hover-status\">\n\t\t\t<button>Activate</button>\n\t\t\tBind over/out: <span class=\"ins\">0</span> / <span class=\"outs\">0</span>\n\t\t</div>\n\t\t<div class=\"hover-inside\">\n\t\t\tMouse over here SHOULD trigger the counter.\n\t\t</div>\n\t</div>\n\t<div id=\"liveoverbox\" class=\"hover-box\">\n\t\t<div class=\"hover-status\">\n\t\t\t<button>Activate</button>\n\t\t\tLive over/out: <span class=\"ins\">0</span> / <span class=\"outs\">0</span>\n\t\t</div>\n\t\t<div class=\"hover-inside\">\n\t\t\tMouse over here SHOULD trigger the counter.\n\t\t</div>\n\t</div>\n\t<div id=\"delegateoverbox\" class=\"hover-box\">\n\t\t<div class=\"hover-status\">\n\t\t\t<button>Activate</button>\n\t\t\tDelegated over/out: <span class=\"ins\">0</span> / <span class=\"outs\">0</span>\n\t\t</div>\n\t\t<div class=\"hover-inside\">\n\t\t\tMouse over here SHOULD trigger the counter.\n\t\t</div>\n\t</div>\n\n\t</div> <!-- wrapper -->\n\n<script>\n\n$(function(){\n\n\tvar x,\n\t\tcountIns = function() {\n\t\t\tvar d = $(this).data();\n\t\t\t$(\"span.ins\", this).text(++d.ins);\n\t\t},\n\t\tcountOuts = function() {\n\t\t\tvar d = $(this).data();\n\t\t\t$(\"span.outs\", this).text(++d.outs);\n\t\t};\n\n\t// Tests can be activated separately or in combination to check for interference\n\n\t$(\"#hoverbox button\").click(function(){\n\t\t$(\"#hoverbox\")\n\t\t\t.data({ ins: 0, outs: 0 })\n\t\t\t.hover( countIns, countOuts );\n\t\t$(this).remove();\n\t});\n\t$(\"#delegateenterbox button\").click(function(){\n\t\t$(\"html\")\n\t\t\t.find(\"#delegateenterbox\").data({ ins: 0, outs: 0 }).end()\n\t\t\t.delegate(\"#delegateenterbox\", \"mouseenter\", countIns )\n\t\t\t.delegate(\"#delegateenterbox\", \"mouseleave\", countOuts );\n\t\t$(this).remove();\n\t});\n\t$(\"#liveenterbox button\").click(function(){\n\t\t$(\"#liveenterbox\")\n\t\t\t.data({ ins: 0, outs: 0 })\n\t\t\t.live(\"mouseenter\", countIns )\n\t\t\t.live(\"mouseleave\", countOuts );\n\t\t$(this).remove();\n\t});\n\n\t$(\"#overbox button\").click(function(){\n\t\t$(\"#overbox\")\n\t\t\t.data({ ins: 0, outs: 0 })\n\t\t\t.bind(\"mouseover\", countIns )\n\t\t\t.bind(\"mouseout\", countOuts );\n\t\t$(this).remove();\n\t});\n\t$(\"#liveoverbox button\").click(function(){\n\t\t$(\"#liveoverbox\")\n\t\t\t.data({ ins: 0, outs: 0 })\n\t\t\t.live(\"mouseover\", countIns )\n\t\t\t.live(\"mouseout\", countOuts );\n\t\t$(this).remove();\n\t});\n\t$(\"#delegateoverbox button\").click(function(){\n\t\t$(document)\n\t\t\t.find(\"#delegateoverbox\").data({ ins: 0, outs: 0 }).end()\n\t\t\t.delegate(\"#delegateoverbox\", \"mouseover\", countIns )\n\t\t\t.delegate(\"#delegateoverbox\", \"mouseout\", countOuts );\n\t\t$(this).remove();\n\t});\n});\n\n</script>\n</body>\n</html>\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/jquery/test/index.html",
    "content": "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\" dir=\"ltr\" id=\"html\">\n<head>\n\t<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />\n\t<meta http-equiv=\"X-UA-Compatible\" content=\"IE=Edge\" />\n\t<title>jQuery Test Suite</title>\n\t<link rel=\"Stylesheet\" media=\"screen\" href=\"qunit/qunit/qunit.css\" />\n\t<link rel=\"Stylesheet\" media=\"screen\" href=\"data/testsuite.css\" />\n\t<!-- Includes -->\n\n\t<!-- Allows us to fetch submodule tests when using a no-ajax build -->\n\t<script src=\"data/jquery-1.9.1.ajax_xhr.min.js\"></script>\n\n\t<script src=\"data/testinit.js\"></script>\n\n\t<script src=\"qunit/qunit/qunit.js\"></script>\n\t<script>\n\t\t(function() {\n\t\t\tvar src = \"../dist/jquery.min.js\";\n\n\t\t\t// Config parameter to use minified jQuery\n\t\t\tQUnit.config.urlConfig.push({\n\t\t\t\tid: \"dev\",\n\t\t\t\tlabel: \"Load unminified\",\n\t\t\t\ttooltip: \"Load the development (unminified) jQuery file\"\n\t\t\t});\n\t\t\tif ( QUnit.urlParams.dev ) {\n\t\t\t\tsrc = \"../dist/jquery.js\";\n\t\t\t}\n\n\t\t\t// Config parameter to force basic code paths\n\t\t\tQUnit.config.urlConfig.push({\n\t\t\t\tid: \"basic\",\n\t\t\t\tlabel: \"Bypass optimizations\",\n\t\t\t\ttooltip: \"Force use of the most basic code by disabling native querySelectorAll; contains; compareDocumentPosition\"\n\t\t\t});\n\t\t\tif ( QUnit.urlParams.basic ) {\n\t\t\t\tdocument.querySelectorAll = null;\n\t\t\t\tdocument.documentElement.contains = null;\n\t\t\t\tdocument.documentElement.compareDocumentPosition = null;\n\t\t\t}\n\n\t\t\t// Load jQuery\n\t\t\tdocument.write( \"<script id='jquery-js' src='\" + src + \"'><\\x2Fscript>\" );\n\t\t})();\n\t</script>\n\t<script src=\"data/testrunner.js\"></script>\n\n\t<script src=\"unit/core.js\"></script>\n\t<script src=\"unit/callbacks.js\"></script>\n\t<script src=\"unit/deferred.js\"></script>\n\t<script src=\"unit/support.js\"></script>\n\t<script src=\"unit/data.js\"></script>\n\t<script src=\"unit/queue.js\"></script>\n\t<script src=\"unit/attributes.js\"></script>\n\t<script src=\"unit/event.js\"></script>\n\t<script src=\"unit/selector.js\"></script>\n\t<script src=\"unit/traversing.js\"></script>\n\t<script src=\"unit/manipulation.js\"></script>\n\t<script src=\"unit/wrap.js\"></script>\n\t<script src=\"unit/css.js\"></script>\n\t<script src=\"unit/serialize.js\"></script>\n\t<script src=\"unit/ajax.js\"></script>\n\t<script src=\"unit/effects.js\"></script>\n\t<script src=\"unit/offset.js\"></script>\n\t<script src=\"unit/dimensions.js\"></script>\n\t<script src=\"unit/deprecated.js\"></script>\n\t<script src=\"unit/exports.js\"></script>\n\n\t<!-- Subproject tests must be last because they replace our test fixture -->\n\t<script>\n\t\ttestSubproject( \"Sizzle\", \"../src/sizzle/test/\", /^unit\\/.*\\.js$/ );\n\t</script>\n\n\t<script>\n\t\t// html5shiv, enabling HTML5 elements to be used with jQuery\n\t\t( \"abbr article aside audio bdi canvas data datalist details figcaption figure footer header hgroup \" +\n\t\t\t\"mark meter nav output progress section summary time video\"\n\t\t).replace(/\\w+/g, function(n) {\n\t\t\tdocument.createElement(n);\n\t\t});\n\t</script>\n</head>\n\n<body id=\"body\">\n\t<div id=\"qunit\"></div>\n\n\t<!-- Test HTML -->\n\t<!-- this iframe is outside the #qunit-fixture so it won't reload constantly wasting time, but it means the tests must be \"safe\" and clean up after themselves -->\n\t<iframe id=\"loadediframe\" name=\"loadediframe\" style=\"display:none;\" src=\"data/iframe.html\"></iframe>\n\t<dl id=\"dl\" style=\"position:absolute;top:-32767px;left:-32767px;width:1px;\">\n\t<div id=\"qunit-fixture\">\n\t\t<p id=\"firstp\">See <a id=\"simon1\" href=\"http://simon.incutio.com/archive/2003/03/25/#getElementsBySelector\" rel=\"bookmark\">this blog entry</a> for more information.</p>\n\t\t<p id=\"ap\">\n\t\t\tHere are some links in a normal paragraph: <a id=\"google\" href=\"http://www.google.com/\" title=\"Google!\">Google</a>,\n\t\t\t<a id=\"groups\" href=\"http://groups.google.com/\" class=\"GROUPS\">Google Groups (Link)</a>.\n\t\t\tThis link has <code><a href=\"http://smin\" id=\"anchor1\">class=\"blog\"</a></code>:\n\t\t\t<a href=\"http://diveintomark.org/\" class=\"blog\" hreflang=\"en\" id=\"mark\">diveintomark</a>\n\n\t\t</p>\n\t\t<div id=\"foo\">\n\t\t\t<p id=\"sndp\">Everything inside the red border is inside a div with <code>id=\"foo\"</code>.</p>\n\t\t\t<p lang=\"en\" id=\"en\">This is a normal link: <a id=\"yahoo\" href=\"http://www.yahoo.com/\" class=\"blogTest\">Yahoo</a></p>\n\t\t\t<p id=\"sap\">This link has <code><a href=\"#2\" id=\"anchor2\">class=\"blog\"</a></code>: <a href=\"http://simon.incutio.com/\" class=\"blog link\" id=\"simon\">Simon Willison's Weblog</a></p>\n\n\t\t</div>\n\t\t<div id=\"nothiddendiv\" style=\"height:1px;background:white;\" class=\"nothiddendiv\">\n\t\t\t<div id=\"nothiddendivchild\"></div>\n\t\t</div>\n\t\t<span id=\"name+value\"></span>\n\t\t<p id=\"first\">Try them out:</p>\n\t\t<ul id=\"firstUL\"></ul>\n\t\t<ol id=\"empty\"></ol>\n\t\t<form id=\"form\" action=\"formaction\">\n\t\t\t<label for=\"action\" id=\"label-for\">Action:</label>\n\t\t\t<input type=\"text\" name=\"action\" value=\"Test\" id=\"text1\" maxlength=\"30\"/>\n\t\t\t<input type=\"text\" name=\"text2\" value=\"Test\" id=\"text2\" disabled=\"disabled\"/>\n\t\t\t<input type=\"radio\" name=\"radio1\" id=\"radio1\" value=\"on\"/>\n\n\t\t\t<input type=\"radio\" name=\"radio2\" id=\"radio2\" checked=\"checked\"/>\n\t\t\t<input type=\"checkbox\" name=\"check\" id=\"check1\" checked=\"checked\"/>\n\t\t\t<input type=\"checkbox\" id=\"check2\" value=\"on\"/>\n\n\t\t\t<input type=\"hidden\" name=\"hidden\" id=\"hidden1\"/>\n\t\t\t<input type=\"text\" style=\"display:none;\" name=\"foo[bar]\" id=\"hidden2\"/>\n\n\t\t\t<input type=\"text\" id=\"name\" name=\"name\" value=\"name\" />\n\t\t\t<input type=\"search\" id=\"search\" name=\"search\" value=\"search\" />\n\n\t\t\t<button id=\"button\" name=\"button\" type=\"button\">Button</button>\n\n\t\t\t<textarea id=\"area1\" maxlength=\"30\">foobar</textarea>\n\n\t\t\t<select name=\"select1\" id=\"select1\">\n\t\t\t\t<option id=\"option1a\" class=\"emptyopt\" value=\"\">Nothing</option>\n\t\t\t\t<option id=\"option1b\" value=\"1\">1</option>\n\t\t\t\t<option id=\"option1c\" value=\"2\">2</option>\n\t\t\t\t<option id=\"option1d\" value=\"3\">3</option>\n\t\t\t</select>\n\t\t\t<select name=\"select2\" id=\"select2\">\n\t\t\t\t<option id=\"option2a\" class=\"emptyopt\" value=\"\">Nothing</option>\n\t\t\t\t<option id=\"option2b\" value=\"1\">1</option>\n\t\t\t\t<option id=\"option2c\" value=\"2\">2</option>\n\t\t\t\t<option id=\"option2d\" selected=\"selected\" value=\"3\">3</option>\n\t\t\t</select>\n\t\t\t<select name=\"select3\" id=\"select3\" multiple=\"multiple\">\n\t\t\t\t<option id=\"option3a\" class=\"emptyopt\" value=\"\">Nothing</option>\n\t\t\t\t<option id=\"option3b\" selected=\"selected\" value=\"1\">1</option>\n\t\t\t\t<option id=\"option3c\" selected=\"selected\" value=\"2\">2</option>\n\t\t\t\t<option id=\"option3d\" value=\"3\">3</option>\n\t\t\t\t<option id=\"option3e\">no value</option>\n\t\t\t</select>\n\t\t\t<select name=\"select4\" id=\"select4\" multiple=\"multiple\">\n\t\t\t\t<optgroup disabled=\"disabled\">\n\t\t\t\t\t<option id=\"option4a\" class=\"emptyopt\" value=\"\">Nothing</option>\n\t\t\t\t\t<option id=\"option4b\" disabled=\"disabled\" selected=\"selected\" value=\"1\">1</option>\n\t\t\t\t\t<option id=\"option4c\" selected=\"selected\" value=\"2\">2</option>\n\t\t\t\t</optgroup>\n\t\t\t\t<option selected=\"selected\" disabled=\"disabled\" id=\"option4d\" value=\"3\">3</option>\n\t\t\t\t<option id=\"option4e\">no value</option>\n\t\t\t</select>\n\t\t\t<select name=\"select5\" id=\"select5\">\n\t\t\t\t<option id=\"option5a\" value=\"3\">1</option>\n\t\t\t\t<option id=\"option5b\" value=\"2\">2</option>\n\t\t\t\t<option id=\"option5c\" value=\"1\" data-attr=\"\">3</option>\n\t\t\t</select>\n\n\t\t\t<object id=\"object1\" codebase=\"stupid\">\n\t\t\t\t<param name=\"p1\" value=\"x1\" />\n\t\t\t\t<param name=\"p2\" value=\"x2\" />\n\t\t\t</object>\n\n\t\t\t<span id=\"台北Táiběi\"></span>\n\t\t\t<span id=\"台北\" lang=\"中文\"></span>\n\t\t\t<span id=\"utf8class1\" class=\"台北Táiběi 台北\"></span>\n\t\t\t<span id=\"utf8class2\" class=\"台北\"></span>\n\t\t\t<span id=\"foo:bar\" class=\"foo:bar\"></span>\n\t\t\t<span id=\"test.foo[5]bar\" class=\"test.foo[5]bar\"></span>\n\n\t\t\t<foo_bar id=\"foobar\">test element</foo_bar>\n\t\t</form>\n\t\t<b id=\"floatTest\">Float test.</b>\n\t\t<iframe id=\"iframe\" name=\"iframe\"></iframe>\n\t\t<form id=\"lengthtest\">\n\t\t\t<input type=\"text\" id=\"length\" name=\"test\"/>\n\t\t\t<input type=\"text\" id=\"idTest\" name=\"id\"/>\n\t\t</form>\n\t\t<table id=\"table\"></table>\n\n\t\t<form id=\"name-tests\">\n\t\t\t<!-- Inputs with a grouped name attribute. -->\n\t\t\t<input name=\"types[]\" id=\"types_all\" type=\"checkbox\" value=\"all\" />\n\t\t\t<input name=\"types[]\" id=\"types_anime\" type=\"checkbox\" value=\"anime\" />\n\t\t\t<input name=\"types[]\" id=\"types_movie\" type=\"checkbox\" value=\"movie\" />\n\t\t</form>\n\n\t\t<form id=\"testForm\" action=\"#\" method=\"get\">\n\t\t\t<textarea name=\"T3\" rows=\"2\" cols=\"15\">?\nZ</textarea>\n\t\t\t<input type=\"hidden\" name=\"H1\" value=\"x\" />\n\t\t\t<input type=\"hidden\" name=\"H2\" />\n\t\t\t<input name=\"PWD\" type=\"password\" value=\"\" />\n\t\t\t<input name=\"T1\" type=\"text\" />\n\t\t\t<input name=\"T2\" type=\"text\" value=\"YES\" readonly=\"readonly\" />\n\t\t\t<input type=\"checkbox\" name=\"C1\" value=\"1\" />\n\t\t\t<input type=\"checkbox\" name=\"C2\" />\n\t\t\t<input type=\"radio\" name=\"R1\" value=\"1\" />\n\t\t\t<input type=\"radio\" name=\"R1\" value=\"2\" />\n\t\t\t<input type=\"text\" name=\"My Name\" value=\"me\" />\n\t\t\t<input type=\"reset\" name=\"reset\" value=\"NO\" />\n\t\t\t<select name=\"S1\">\n\t\t\t\t<option value=\"abc\">ABC</option>\n\t\t\t\t<option value=\"abc\">ABC</option>\n\t\t\t\t<option value=\"abc\">ABC</option>\n\t\t\t</select>\n\t\t\t<select name=\"S2\" multiple=\"multiple\" size=\"3\">\n\t\t\t\t<option value=\"abc\">ABC</option>\n\t\t\t\t<option value=\"abc\">ABC</option>\n\t\t\t\t<option value=\"abc\">ABC</option>\n\t\t\t</select>\n\t\t\t<select name=\"S3\">\n\t\t\t\t<option selected=\"selected\">YES</option>\n\t\t\t</select>\n\t\t\t<select name=\"S4\">\n\t\t\t\t<option value=\"\" selected=\"selected\">NO</option>\n\t\t\t</select>\n\t\t\t<input type=\"submit\" name=\"sub1\" value=\"NO\" />\n\t\t\t<input type=\"submit\" name=\"sub2\" value=\"NO\" />\n\t\t\t<input type=\"image\" name=\"sub3\" value=\"NO\" />\n\t\t\t<button name=\"sub4\" type=\"submit\" value=\"NO\">NO</button>\n\t\t\t<input name=\"D1\" type=\"text\" value=\"NO\" disabled=\"disabled\" />\n\t\t\t<input type=\"checkbox\" checked=\"checked\" disabled=\"disabled\" name=\"D2\" value=\"NO\" />\n\t\t\t<input type=\"radio\" name=\"D3\" value=\"NO\" checked=\"checked\" disabled=\"disabled\" />\n\t\t\t<select name=\"D4\" disabled=\"disabled\">\n\t\t\t\t<option selected=\"selected\" value=\"NO\">NO</option>\n\t\t\t</select>\n\t\t\t<input id=\"list-test\" type=\"text\" />\n\t\t\t<datalist id=\"datalist\">\n\t\t\t\t<option value=\"option\"></option>\n\t\t\t</datalist>\n\t\t</form>\n\t\t<div id=\"moretests\">\n\t\t\t<form>\n\t\t\t\t<div id=\"checkedtest\" style=\"display:none;\">\n\t\t\t\t\t<input type=\"radio\" name=\"checkedtestradios\" checked=\"checked\"/>\n\t\t\t\t\t<input type=\"radio\" name=\"checkedtestradios\" value=\"on\"/>\n\t\t\t\t\t<input type=\"checkbox\" name=\"checkedtestcheckboxes\" checked=\"checked\"/>\n\t\t\t\t\t<input type=\"checkbox\" name=\"checkedtestcheckboxes\" />\n\t\t\t\t</div>\n\t\t\t</form>\n\t\t\t<div id=\"nonnodes\"><span id=\"nonnodesElement\">hi</span> there <!-- mon ami --></div>\n\t\t\t<div id=\"t2037\">\n\t\t\t\t<div><div class=\"hidden\">hidden</div></div>\n\t\t\t</div>\n\t\t\t<div id=\"t6652\">\n\t\t\t\t<div></div>\n\t\t\t</div>\n\t\t\t<div id=\"no-clone-exception\"><object><embed></embed></object></div>\n\t\t</div>\n\n\t\t<div id=\"tabindex-tests\">\n\t\t\t<ol id=\"listWithTabIndex\" tabindex=\"5\">\n\t\t\t\t<li id=\"foodWithNegativeTabIndex\" tabindex=\"-1\">Rice</li>\n\t\t\t\t<li id=\"foodNoTabIndex\">Beans</li>\n\t\t\t\t<li>Blinis</li>\n\t\t\t\t<li>Tofu</li>\n\t\t\t</ol>\n\n\t\t\t<div id=\"divWithNoTabIndex\">I'm hungry. I should...</div>\n\t\t\t<span>...</span><a href=\"#\" id=\"linkWithNoTabIndex\">Eat lots of food</a><span>...</span> |\n\t\t\t<span>...</span><a href=\"#\" id=\"linkWithTabIndex\" tabindex=\"2\">Eat a little food</a><span>...</span> |\n\t\t\t<span>...</span><a href=\"#\" id=\"linkWithNegativeTabIndex\" tabindex=\"-1\">Eat no food</a><span>...</span>\n\t\t\t<span>...</span><a id=\"linkWithNoHrefWithNoTabIndex\">Eat a burger</a><span>...</span>\n\t\t\t<span>...</span><a id=\"linkWithNoHrefWithTabIndex\" tabindex=\"1\">Eat some funyuns</a><span>...</span>\n\t\t\t<span>...</span><a id=\"linkWithNoHrefWithNegativeTabIndex\" tabindex=\"-1\">Eat some funyuns</a><span>...</span>\n\t\t\t<input id=\"inputWithoutTabIndex\"/>\n\t\t\t<button id=\"buttonWithoutTabIndex\"></button>\n\t\t\t<textarea id=\"textareaWithoutTabIndex\"></textarea>\n\t\t\t<menu type=\"popup\">\n\t\t\t\t<menuitem id=\"menuitemWithoutTabIndex\" command=\"submitbutton\" default/>\n\t\t\t</menu>\n\t\t</div>\n\n\t\t<div id=\"liveHandlerOrder\">\n\t\t\t<span id=\"liveSpan1\"><a href=\"#\" id=\"liveLink1\"></a></span>\n\t\t\t<span id=\"liveSpan2\"><a href=\"#\" id=\"liveLink2\"></a></span>\n\t\t</div>\n\n\t\t<div id=\"siblingTest\">\n\t\t\t<em id=\"siblingfirst\">1</em>\n\t\t\t<em id=\"siblingnext\">2</em>\n\t\t\t<em id=\"siblingthird\">\n\t\t\t\t<em id=\"siblingchild\">\n\t\t\t\t\t<em id=\"siblinggrandchild\">\n\t\t\t\t\t\t<em id=\"siblinggreatgrandchild\"></em>\n\t\t\t\t\t</em>\n\t\t\t\t</em>\n\t\t\t</em>\n\t\t\t<span id=\"siblingspan\"></span>\n\t\t</div>\n\t\t<div id=\"fx-test-group\" style=\"position: absolute; width: 1px; height: 1px; overflow: hidden;\">\n\t\t\t<div id=\"fx-queue\" name=\"test\">\n\t\t\t\t<div id=\"fadein\" class='chain-test' name='div'>fadeIn<div>fadeIn</div></div>\n\t\t\t\t<div id=\"fadeout\" class='chain-test chain-test-out'>fadeOut<div>fadeOut</div></div>\n\n\t\t\t\t<div id=\"show\" class='chain-test'>show<div>show</div></div>\n\t\t\t\t<div id=\"hide\" class='chain-test chain-test-out'>hide<div>hide</div></div>\n\t\t\t\t<div id=\"easehide\" class='chain-test chain-test-out'>hide<div>hide</div></div>\n\n\t\t\t\t<div id=\"togglein\" class='chain-test'>togglein<div>togglein</div></div>\n\t\t\t\t<div id=\"toggleout\" class='chain-test chain-test-out'>toggleout<div>toggleout</div></div>\n\t\t\t\t<div id=\"easetoggleout\" class='chain-test chain-test-out'>toggleout<div>toggleout</div></div>\n\n\t\t\t\t<div id=\"slideup\" class='chain-test'>slideUp<div>slideUp</div></div>\n\t\t\t\t<div id=\"slidedown\" class='chain-test chain-test-out'>slideDown<div>slideDown</div></div>\n\t\t\t\t<div id=\"easeslideup\" class='chain-test'>slideUp<div>slideUp</div></div>\n\n\t\t\t\t<div id=\"slidetogglein\" class='chain-test'>slideToggleIn<div>slideToggleIn</div></div>\n\t\t\t\t<div id=\"slidetoggleout\" class='chain-test chain-test-out'>slideToggleOut<div>slideToggleOut</div></div>\n\n\t\t\t\t<div id=\"fadetogglein\" class='chain-test'>fadeToggleIn<div>fadeToggleIn</div></div>\n\t\t\t\t<div id=\"fadetoggleout\" class='chain-test chain-test-out'>fadeToggleOut<div>fadeToggleOut</div></div>\n\n\t\t\t\t<div id=\"fadeto\" class='chain-test'>fadeTo<div>fadeTo</div></div>\n\t\t\t</div>\n\n\t\t\t<div id=\"fx-tests\"></div>\n\t\t\t<span id=\"display\"></span>\n\t\t</div>\n\t</div>\n\t</dl>\n\t<map name=\"imgmap\" id=\"imgmap\">\n\t\t<area shape=\"rect\" coords=\"0,0,200,50\">\n\t</map>\n\n</body>\n</html>\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/jquery/test/jquery.js",
    "content": "// Use the right jQuery source in iframe tests\ndocument.write( \"<script id='jquery-js' src='\" +\n\tparent.document.getElementById(\"jquery-js\").src.replace( /^(?![^\\/?#]+:)/,\n\t\tparent.location.pathname.replace( /[^\\/]$/, \"$0/\" ) ) +\n\"'><\\x2Fscript>\" );\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/jquery/test/localfile.html",
    "content": "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\" dir=\"ltr\" id=\"html\">\n<head>\n\t<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />\n\t<title>jQuery Local File Test</title>\n\t<!-- Includes -->\n\t<script src=\"jquery.js\"></script>\n\t<style>\n\t\t.error { color: red; }\n\t\t.success { color: green; }\n\t</style>\n</head>\n<body>\n\t<h1>jQuery Local File Test</h1>\n\t<h2>\n\t\tIntroduction\n\t</h2>\n\t<ul>\n\t\t<li>\n\t\t\tAccess this file using the \"file:\" protocol,\n\t\t</li>\n\t\t<li>\n\t\t\ttwo green \"OK\" strings must appear below,\n\t\t</li>\n\t\t<li>\n\t\t\tEmpty local files will issue errors, it's a known limitation.\n\t\t</li>\n\t</ul>\n\t<h2>\n\t\tResults\n\t</h2>\n\t<ul>\n\t\t<li>\n\t\t\tSuccess:\n\t\t\t<span id=\"success\">\n\t\t\t</span>\n\t\t</li>\n\t\t<li>\n\t\t\tError:\n\t\t\t<span id=\"error\">\n\t\t\t</span>\n\t\t</li>\n\t</ul>\n\t<h2>\n\t\tLogs:\n\t</h2>\n\t<ul id=\"log\">\n\t</ul>\n\t<script>\n\t\tvar logUL = jQuery( \"#log\" );\n\t\tfunction doLog( message, args ) {\n\t\t\tjQuery( \"<li />\").appendTo( logUL ).text( message + ': \"' + Array.prototype.join.call( args, '\" - \"' ) + '\"' );\n\t\t}\n\t\tjQuery.ajax( \"./data/badjson.js\" , {\n\t\t\tcontext: jQuery( \"#success\" ),\n\t\t\tdataType: \"text\"\n\t\t}).success(function( data, _, xhr ) {\n\t\t\tdoLog( \"Success (\" + xhr.status + \")\" , arguments );\n\t\t\tthis.addClass( data ? \"success\" : \"error\" ).text( \"OK\" );\n\t\t}).error(function( xhr ) {\n\t\t\tdoLog( \"Success (\" + xhr.status + \")\" , arguments );\n\t\t\tthis.addClass( \"error\" ).text( \"FAIL\" );\n\t\t});\n\t\tjQuery.ajax( \"./data/doesnotexist.ext\" , {\n\t\t\tcontext: jQuery( \"#error\" ),\n\t\t\tdataType: \"text\"\n\t\t}).error(function( xhr ) {\n\t\t\tdoLog( \"Error (\" + xhr.status + \")\" , arguments );\n\t\t\tthis.addClass( \"success\" ).text( \"OK\" );\n\t\t}).success(function( data, _, xhr ) {\n\t\t\tdoLog( \"Error (\" + xhr.status + \")\" , arguments );\n\t\t\tthis.addClass( \"error\" ).text( \"FAIL\" );\n\t\t});\n\t</script>\n</body>\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/jquery/test/networkerror.html",
    "content": "<!DOCTYPE html>\n<html>\n<!--\n\tTest for #8135\n\n\tThanks John Firebaugh for this test page based on his gist\n\thttps://gist.github.com/807090\n\n\tAccess this page through a web server, then stop said server and click the button.\n-->\n<head>\n\t<title>\n\t\tjQuery Network Error Test for Firefox\n\t</title>\n\t<style>\n\t\tdiv { margin-top: 10px; }\n\t</style>\n\t<script src=\"jquery.js\"></script>\n\t<script type=\"text/javascript\">\n\t$('button').live('click', function () {\n\t\t$.ajax({\n\t\t\turl: '/',\n\t\t\terror: function() {\n\t\t\t\tconsole.log( \"abort\", arguments );\n\t\t\t}\n\t\t}).abort();\n\t\t$.ajax({\n\t\t\turl: '/',\n\t\t\terror: function() {\n\t\t\t\tconsole.log( \"complete\", arguments );\n\t\t\t}\n\t\t});\n\t\treturn false;\n\t})\n\t</script>\n</head>\n<body>\n\t<h1>\n\t\tjQuery Network Error Test for Firefox\n\t</h1>\n\t<div>\n\t\tThis is a test page for\n\t\t<a href=\"http://bugs.jquery.com/ticket/8135\">\n\t\t\t#8135\n\t\t</a>\n\t\twhich was reported in Firefox when accessing properties\n\t\tof an XMLHttpRequest object after a network error occurred.\n\t</div>\n\t<div>Take the following steps:</div>\n\t<ol>\n\t\t<li>\n\t\t\tmake sure you accessed this page through a web server,\n\t\t</li>\n\t\t<li>\n\t\t\tstop the web server,\n\t\t</li>\n\t\t<li>\n\t\t\topen the console,\n\t\t</li>\n\t\t<li>\n\t\t\tclick this\n\t\t\t<button>button</button>\n\t\t\t,\n\t\t</li>\n\t\t<li>\n\t\t\twait for both requests to fail.\n\t\t</li>\n\t</ol>\n\t<div>\n\t\tTest passes if you get two log lines:\n\t\t<ul>\n\t\t\t<li>\n\t\t\t\tthe first starting with \"abort\",\n\t\t\t</li>\n\t\t\t<li>\n\t\t\t\tthe second starting with \"complete\",\n\t\t\t</li>\n\t\t</ul>\n\t</div>\n\t<div>\n\t\tTest fails if the browser notifies an exception.\n\t</div>\n</body>\n</html>\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/jquery/test/readywait.html",
    "content": "<!DOCTYPE html>\n<html>\n<!--\n\tTest for jQuery.holdReady. Needs to be a\n\tstandalone test since it deals with DOM\n\tready.\n-->\n<head>\n\t<title>\n\t\tjQuery.holdReady Test\n\t</title>\n\t<style>\n\t\tdiv { margin-top: 10px; }\n\t\t#output { background-color: green }\n\t\t#expectedOutput { background-color: green }\n\t</style>\n\t<script src=\"jquery.js\"></script>\n\n\t<!-- Load the script loader that uses\n\t\tjQuery.readyWait -->\n\t<script src=\"data/readywaitloader.js\"></script>\n\n\t<script type=\"text/javascript\">\n\tjQuery(function() {\n\t\t// The delayedMessage is defined by\n\t\t// the readywaitasset.js file, so the\n\t\t// next line will only work if this DOM\n\t\t// ready callback is called after readyWait\n\t\t// has been decremented by readywaitloader.js\n\t\t// If an error occurs.\n\t\tjQuery(\"#output\").append(delayedMessage);\n\t});\n\t</script>\n</head>\n<body>\n\t<h1>\n\t\tjQuery.holdReady Test\n\t</h1>\n\t<p>\n\t\tThis is a test page for jQuery.readyWait and jQuery.holdReady,\n\t\tsee\n\t\t<a href=\"http://bugs.jquery.com/ticket/6781\">#6781</a>\n\t\tand\n\t\t<a href=\"http://bugs.jquery.com/ticket/8803\">#8803</a>.\n\t</p>\n\t<p>\n\tTest for jQuery.holdReady, which can be used\n\tby plugins and other scripts to indicate something\n\timportant to the page is still loading and needs\n\tto block the DOM ready callbacks that are registered\n\twith jQuery.\n\t</p>\n\t<p>\n\tScript loaders are the most likely kind of script\n\tto use jQuery.holdReady, but it could be used by\n\tother things like a script that loads a CSS file\n\tand wants to pause the DOM ready callbacks.\n\t</p>\n\t<p>\n\t<strong>Expected Result</strong>: The text\n\t<span id=\"expectedOutput\">It Worked!</span>\n\tappears below after about <strong>2 seconds.</strong>\n\t</p>\n\t<p>\n\tIf there is an error in the console,\n\tor the text does not show up, then the test failed.\n\t</p>\n\t<div id=\"output\"></div>\n</body>\n</html>\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/jquery/test/unit/ajax.js",
    "content": "module( \"ajax\", {\n\tsetup: function() {\n\t\tvar jsonpCallback = this.jsonpCallback = jQuery.ajaxSettings.jsonpCallback;\n\t\tjQuery.ajaxSettings.jsonpCallback = function() {\n\t\t\tvar callback = jsonpCallback.apply( this, arguments );\n\t\t\tGlobals.register( callback );\n\t\t\treturn callback;\n\t\t};\n\t},\n\tteardown: function() {\n\t\tjQuery( document ).off( \"ajaxStart ajaxStop ajaxSend ajaxComplete ajaxError ajaxSuccess\" );\n\t\tmoduleTeardown.apply( this, arguments );\n\t}\n});\n\n(function() {\n\n\tif ( !jQuery.ajax || ( isLocal && !hasPHP ) ) {\n\t\treturn;\n\t}\n\n\tfunction addGlobalEvents( expected ) {\n\t\treturn function() {\n\t\t\texpected = expected || \"\";\n\t\t\tjQuery( document ).on( \"ajaxStart ajaxStop ajaxSend ajaxComplete ajaxError ajaxSuccess\", function( e ) {\n\t\t\t\tok( expected.indexOf(e.type) !== -1, e.type );\n\t\t\t});\n\t\t};\n\t}\n\n//----------- jQuery.ajax()\n\n\ttestIframeWithCallback( \"XMLHttpRequest - Attempt to block tests because of dangling XHR requests (IE)\", \"ajax/unreleasedXHR.html\", function() {\n\t\texpect( 1 );\n\t\tok( true, \"done\" );\n\t});\n\n\tajaxTest( \"jQuery.ajax() - success callbacks\", 8, {\n\t\tsetup: addGlobalEvents(\"ajaxStart ajaxStop ajaxSend ajaxComplete ajaxSuccess\"),\n\t\turl: url(\"data/name.html\"),\n\t\tbeforeSend: function() {\n\t\t\tok( true, \"beforeSend\" );\n\t\t},\n\t\tsuccess: function() {\n\t\t\tok( true, \"success\" );\n\t\t},\n\t\tcomplete: function() {\n\t\t\tok( true, \"complete\");\n\t\t}\n\t});\n\n\tajaxTest( \"jQuery.ajax() - success callbacks - (url, options) syntax\", 8, {\n\t\tsetup: addGlobalEvents(\"ajaxStart ajaxStop ajaxSend ajaxComplete ajaxSuccess\"),\n\t\tcreate: function( options ) {\n\t\t\treturn jQuery.ajax( url(\"data/name.html\"), options );\n\t\t},\n\t\tbeforeSend: function() {\n\t\t\tok( true, \"beforeSend\" );\n\t\t},\n\t\tsuccess: function() {\n\t\t\tok( true, \"success\" );\n\t\t},\n\t\tcomplete: function() {\n\t\t\tok( true, \"complete\" );\n\t\t}\n\t});\n\n\tajaxTest( \"jQuery.ajax() - success callbacks (late binding)\", 8, {\n\t\tsetup: addGlobalEvents(\"ajaxStart ajaxStop ajaxSend ajaxComplete ajaxSuccess\"),\n\t\turl: url(\"data/name.html\"),\n\t\tbeforeSend: function() {\n\t\t\tok( true, \"beforeSend\" );\n\t\t},\n\t\tsuccess: true,\n\t\tafterSend: function( request ) {\n\t\t\trequest.complete(function() {\n\t\t\t\tok( true, \"complete\" );\n\t\t\t}).success(function() {\n\t\t\t\tok( true, \"success\" );\n\t\t\t}).error(function() {\n\t\t\t\tok( false, \"error\" );\n\t\t\t});\n\t\t}\n\t});\n\n\tajaxTest( \"jQuery.ajax() - success callbacks (oncomplete binding)\", 8, {\n\t\tsetup: addGlobalEvents(\"ajaxStart ajaxStop ajaxSend ajaxComplete ajaxSuccess\"),\n\t\turl: url(\"data/name.html\"),\n\t\tbeforeSend: function() {\n\t\t\tok( true, \"beforeSend\" );\n\t\t},\n\t\tsuccess: true,\n\t\tcomplete: function( xhr ) {\n\t\t\txhr.complete(function() {\n\t\t\t\tok( true, \"complete\" );\n\t\t\t}).success(function() {\n\t\t\t\tok( true, \"success\" );\n\t\t\t}).error(function() {\n\t\t\t\tok( false, \"error\" );\n\t\t\t});\n\t\t}\n\t});\n\n\tajaxTest( \"jQuery.ajax() - error callbacks\", 8, {\n\t\tsetup: addGlobalEvents(\"ajaxStart ajaxStop ajaxSend ajaxComplete ajaxError\"),\n\t\turl: url(\"data/name.php?wait=5\"),\n\t\tbeforeSend: function() {\n\t\t\tok( true, \"beforeSend\" );\n\t\t},\n\t\tafterSend: function( request ) {\n\t\t\trequest.abort();\n\t\t},\n\t\terror: function() {\n\t\t\tok( true, \"error\" );\n\t\t},\n\t\tcomplete: function() {\n\t\t\tok( true, \"complete\" );\n\t\t}\n\t});\n\n\tajaxTest( \"jQuery.ajax() - textStatus and errorThrown values\", 4, [\n\t\t{\n\t\t\turl: url(\"data/name.php?wait=5\"),\n\t\t\terror: function( _, textStatus, errorThrown ) {\n\t\t\t\tstrictEqual( textStatus, \"abort\", \"textStatus is 'abort' for abort\" );\n\t\t\t\tstrictEqual( errorThrown, \"abort\", \"errorThrown is 'abort' for abort\" );\n\t\t\t},\n\t\t\tafterSend: function( request ) {\n\t\t\t\trequest.abort();\n\t\t\t}\n\t\t},\n\t\t{\n\t\t\turl: url(\"data/name.php?wait=5\"),\n\t\t\terror: function( _, textStatus, errorThrown ) {\n\t\t\t\tstrictEqual( textStatus, \"mystatus\", \"textStatus is 'mystatus' for abort('mystatus')\" );\n\t\t\t\tstrictEqual( errorThrown, \"mystatus\", \"errorThrown is 'mystatus' for abort('mystatus')\" );\n\t\t\t},\n\t\t\tafterSend: function( request ) {\n\t\t\t\trequest.abort(\"mystatus\");\n\t\t\t}\n\t\t}\n\t]);\n\n\tajaxTest( \"jQuery.ajax() - responseText on error\", 1, {\n\t\turl: url(\"data/errorWithText.php\"),\n\t\terror: function( xhr ) {\n\t\t\tstrictEqual( xhr.responseText, \"plain text message\", \"Test jqXHR.responseText is filled for HTTP errors\" );\n\t\t}\n\t});\n\n\tasyncTest( \"jQuery.ajax() - retry with jQuery.ajax( this )\", 2, function() {\n\t\tvar previousUrl,\n\t\t\tfirstTime = true;\n\t\tjQuery.ajax({\n\t\t\turl: url(\"data/errorWithText.php\"),\n\t\t\terror: function() {\n\t\t\t\tif ( firstTime ) {\n\t\t\t\t\tfirstTime = false;\n\t\t\t\t\tjQuery.ajax( this );\n\t\t\t\t} else {\n\t\t\t\t\tok ( true, \"Test retrying with jQuery.ajax(this) works\" );\n\t\t\t\t\tjQuery.ajax({\n\t\t\t\t\t\turl: url(\"data/errorWithText.php\"),\n\t\t\t\t\t\tdata: {\n\t\t\t\t\t\t\t\"x\": 1\n\t\t\t\t\t\t},\n\t\t\t\t\t\tbeforeSend: function() {\n\t\t\t\t\t\t\tif ( !previousUrl ) {\n\t\t\t\t\t\t\t\tpreviousUrl = this.url;\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tstrictEqual( this.url, previousUrl, \"url parameters are not re-appended\" );\n\t\t\t\t\t\t\t\tstart();\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\terror: function() {\n\t\t\t\t\t\t\tjQuery.ajax( this );\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\tajaxTest( \"jQuery.ajax() - headers\", 4, {\n\t\tsetup: function() {\n\t\t\tjQuery( document ).ajaxSend(function( evt, xhr ) {\n\t\t\t\txhr.setRequestHeader( \"ajax-send\", \"test\" );\n\t\t\t});\n\t\t},\n\t\turl: url(\"data/headers.php?keys=siMPle_SometHing-elsE_OthEr_ajax-send\"),\n\t\theaders: {\n\t\t\t\"siMPle\": \"value\",\n\t\t\t\"SometHing-elsE\": \"other value\",\n\t\t\t\"OthEr\": \"something else\"\n\t\t},\n\t\tsuccess: function( data, _, xhr ) {\n\t\t\tvar i, emptyHeader,\n\t\t\t\trequestHeaders = jQuery.extend( this.headers, {\n\t\t\t\t\t\"ajax-send\": \"test\"\n\t\t\t\t}),\n\t\t\t\ttmp = [];\n\t\t\tfor ( i in requestHeaders ) {\n\t\t\t\ttmp.push( i, \": \", requestHeaders[ i ], \"\\n\" );\n\t\t\t}\n\t\t\ttmp = tmp.join(\"\");\n\n\t\t\tstrictEqual( data, tmp, \"Headers were sent\" );\n\t\t\tstrictEqual( xhr.getResponseHeader(\"Sample-Header\"), \"Hello World\", \"Sample header received\" );\n\n\t\t\temptyHeader = xhr.getResponseHeader(\"Empty-Header\");\n\t\t\tif ( emptyHeader === null ) {\n\t\t\t\tok( true, \"Firefox doesn't support empty headers\" );\n\t\t\t} else {\n\t\t\t\tstrictEqual( emptyHeader, \"\", \"Empty header received\" );\n\t\t\t}\n\t\t\tstrictEqual( xhr.getResponseHeader(\"Sample-Header2\"), \"Hello World 2\", \"Second sample header received\" );\n\t\t}\n\t});\n\n\tajaxTest( \"jQuery.ajax() - Accept header\", 1, {\n\t\turl: url(\"data/headers.php?keys=accept\"),\n\t\theaders: {\n\t\t\tAccept: \"very wrong accept value\"\n\t\t},\n\t\tbeforeSend: function( xhr ) {\n\t\t\txhr.setRequestHeader(\"Accept\", \"*/*\");\n\t\t},\n\t\tsuccess: function( data ) {\n\t\t\tstrictEqual( data, \"accept: */*\\n\", \"Test Accept header is set to last value provided\" );\n\t\t}\n\t});\n\n\tajaxTest( \"jQuery.ajax() - contentType\", 2, [\n\t\t{\n\t\t\turl: url(\"data/headers.php?keys=content-type\"),\n\t\t\tcontentType: \"test\",\n\t\t\tsuccess: function( data ) {\n\t\t\t\tstrictEqual( data, \"content-type: test\\n\", \"Test content-type is sent when options.contentType is set\" );\n\t\t\t}\n\t\t},\n\t\t{\n\t\t\turl: url(\"data/headers.php?keys=content-type\"),\n\t\t\tcontentType: false,\n\t\t\tsuccess: function( data ) {\n\t\t\t\tstrictEqual( data, \"content-type: \\n\", \"Test content-type is not sent when options.contentType===false\" );\n\t\t\t}\n\t\t}\n\t]);\n\n\tajaxTest( \"jQuery.ajax() - protocol-less urls\", 1, {\n\t\turl: \"//somedomain.com\",\n\t\tbeforeSend: function( xhr, settings ) {\n\t\t\tequal( settings.url, location.protocol + \"//somedomain.com\", \"Make sure that the protocol is added.\" );\n\t\t\treturn false;\n\t\t},\n\t\terror: true\n\t});\n\n\tajaxTest( \"jQuery.ajax() - hash\", 3, [\n\t\t{\n\t\t\turl: \"data/name.html#foo\",\n\t\t\tbeforeSend: function( xhr, settings ) {\n\t\t\t\tequal( settings.url, \"data/name.html\", \"Make sure that the URL is trimmed.\" );\n\t\t\t\treturn false;\n\t\t\t},\n\t\t\terror: true\n\t\t},\n\t\t{\n\t\t\turl: \"data/name.html?abc#foo\",\n\t\t\tbeforeSend: function( xhr, settings ) {\n\t\t\t\tequal( settings.url, \"data/name.html?abc\", \"Make sure that the URL is trimmed.\" );\n\t\t\t\treturn false;\n\t\t\t},\n\t\t\terror: true\n\t\t},\n\t\t{\n\t\t\turl: \"data/name.html?abc#foo\",\n\t\t\tdata: {\n\t\t\t\t\"test\": 123\n\t\t\t},\n\t\t\tbeforeSend: function( xhr, settings ) {\n\t\t\t\tequal( settings.url, \"data/name.html?abc&test=123\", \"Make sure that the URL is trimmed.\" );\n\t\t\t\treturn false;\n\t\t\t},\n\t\t\terror: true\n\t\t}\n\t]);\n\n\tajaxTest( \"jQuery.ajax() - cross-domain detection\", 7, function() {\n\t\tfunction request( url, title, crossDomainOrOptions ) {\n\t\t\treturn jQuery.extend( {\n\t\t\t\tdataType: \"jsonp\",\n\t\t\t\turl: url,\n\t\t\t\tbeforeSend: function( _, s ) {\n\t\t\t\t\tok( crossDomainOrOptions === false ? !s.crossDomain : s.crossDomain, title );\n\t\t\t\t\treturn false;\n\t\t\t\t},\n\t\t\t\terror: true\n\t\t\t}, crossDomainOrOptions );\n\t\t}\n\n\t\tvar loc = document.location,\n\t\t\tsamePort = loc.port || ( loc.protocol === \"http:\" ? 80 : 443 ),\n\t\t\totherPort = loc.port === 666 ? 667 : 666,\n\t\t\totherProtocol = loc.protocol === \"http:\" ? \"https:\" : \"http:\";\n\n\t\treturn [\n\t\t\trequest(\n\t\t\t\tloc.protocol + \"//\" + loc.host + \":\" + samePort,\n\t\t\t\t\"Test matching ports are not detected as cross-domain\",\n\t\t\t\tfalse\n\t\t\t),\n\t\t\trequest(\n\t\t\t\totherProtocol + \"//\" + loc.host,\n\t\t\t\t\"Test different protocols are detected as cross-domain\"\n\t\t\t),\n\t\t\trequest(\n\t\t\t\t\"app:/path\",\n\t\t\t\t\"Adobe AIR app:/ URL detected as cross-domain\"\n\t\t\t),\n\t\t\trequest(\n\t\t\t\tloc.protocol + \"//example.invalid:\" + ( loc.port || 80 ),\n\t\t\t\t\"Test different hostnames are detected as cross-domain\"\n\t\t\t),\n\t\t\trequest(\n\t\t\t\tloc.protocol + \"//\" + loc.hostname + \":\" + otherPort,\n\t\t\t\t\"Test different ports are detected as cross-domain\"\n\t\t\t),\n\t\t\trequest(\n\t\t\t\t\"about:blank\",\n\t\t\t\t\"Test about:blank is detected as cross-domain\"\n\t\t\t),\n\t\t\trequest(\n\t\t\t\tloc.protocol + \"//\" + loc.host,\n\t\t\t\t\"Test forced crossDomain is detected as cross-domain\",\n\t\t\t\t{\n\t\t\t\t\tcrossDomain: true\n\t\t\t\t}\n\t\t\t)\n\t\t];\n\t});\n\n\tajaxTest( \"jQuery.ajax() - abort\", 9, {\n\t\tsetup: addGlobalEvents(\"ajaxStart ajaxStop ajaxSend ajaxError ajaxComplete\"),\n\t\turl: url(\"data/name.php?wait=5\"),\n\t\tbeforeSend: function() {\n\t\t\tok( true, \"beforeSend\" );\n\t\t},\n\t\tafterSend: function( xhr ) {\n\t\t\tstrictEqual( xhr.readyState, 1, \"XHR readyState indicates successful dispatch\" );\n\t\t\txhr.abort();\n\t\t\tstrictEqual( xhr.readyState, 0, \"XHR readyState indicates successful abortion\" );\n\t\t},\n\t\terror: true,\n\t\tcomplete: function() {\n\t\t\tok( true, \"complete\" );\n\t\t}\n\t});\n\n\tajaxTest( \"jQuery.ajax() - events with context\", 12, function() {\n\n\t\tvar context = document.createElement(\"div\");\n\n\t\tfunction event( e ) {\n\t\t\tequal( this, context, e.type );\n\t\t}\n\n\t\tfunction callback( msg ) {\n\t\t\treturn function() {\n\t\t\t\tequal( this, context, \"context is preserved on callback \" + msg );\n\t\t\t};\n\t\t}\n\n\t\treturn {\n\t\t\tsetup: function() {\n\t\t\t\tjQuery( context ).appendTo(\"#foo\")\n\t\t\t\t\t.ajaxSend( event )\n\t\t\t\t\t.ajaxComplete( event )\n\t\t\t\t\t.ajaxError( event )\n\t\t\t\t\t.ajaxSuccess( event );\n\t\t\t},\n\t\t\trequests: [{\n\t\t\t\turl: url(\"data/name.html\"),\n\t\t\t\tcontext: context,\n\t\t\t\tbeforeSend: callback(\"beforeSend\"),\n\t\t\t\tsuccess: callback(\"success\"),\n\t\t\t\tcomplete: callback(\"complete\")\n\t\t\t}, {\n\t\t\t\turl: url(\"data/404.html\"),\n\t\t\t\tcontext: context,\n\t\t\t\tbeforeSend: callback(\"beforeSend\"),\n\t\t\t\terror: callback(\"error\"),\n\t\t\t\tcomplete: callback(\"complete\")\n\t\t\t}]\n\t\t};\n\t});\n\n\tajaxTest( \"jQuery.ajax() - events without context\", 3, function() {\n\t\tfunction nocallback( msg ) {\n\t\t\treturn function() {\n\t\t\t\tequal( typeof this.url, \"string\", \"context is settings on callback \" + msg );\n\t\t\t};\n\t\t}\n\t\treturn {\n\t\t\turl: url(\"data/404.html\"),\n\t\t\tbeforeSend: nocallback(\"beforeSend\"),\n\t\t\terror: nocallback(\"error\"),\n\t\t\tcomplete:  nocallback(\"complete\")\n\t\t};\n\t});\n\n\tajaxTest( \"jQuery.ajax() - context modification\", 1, {\n\t\turl: url(\"data/name.html\"),\n\t\tcontext: {},\n\t\tbeforeSend: function() {\n\t\t\tthis.test = \"foo\";\n\t\t},\n\t\tafterSend: function() {\n\t\t\tstrictEqual( this.context.test, \"foo\", \"Make sure the original object is maintained.\" );\n\t\t},\n\t\tsuccess: true\n\t});\n\n\tajaxTest( \"jQuery.ajax() - context modification through ajaxSetup\", 3, function() {\n\t\tvar obj = {};\n\t\treturn {\n\t\t\tsetup: function() {\n\t\t\t\tjQuery.ajaxSetup({\n\t\t\t\t\tcontext: obj\n\t\t\t\t});\n\t\t\t\tstrictEqual( jQuery.ajaxSettings.context, obj, \"Make sure the context is properly set in ajaxSettings.\" );\n\t\t\t},\n\t\t\trequests: [{\n\t\t\t\turl: url(\"data/name.html\"),\n\t\t\t\tsuccess: function() {\n\t\t\t\t\tstrictEqual( this, obj, \"Make sure the original object is maintained.\" );\n\t\t\t\t}\n\t\t\t}, {\n\t\t\t\turl: url(\"data/name.html\"),\n\t\t\t\tcontext: {},\n\t\t\t\tsuccess: function() {\n\t\t\t\t\tok( this !== obj, \"Make sure overriding context is possible.\" );\n\t\t\t\t}\n\t\t\t}]\n\t\t};\n\t});\n\n\tajaxTest( \"jQuery.ajax() - disabled globals\", 3, {\n\t\tsetup: addGlobalEvents(\"\"),\n\t\tglobal: false,\n\t\turl: url(\"data/name.html\"),\n\t\tbeforeSend: function() {\n\t\t\tok( true, \"beforeSend\" );\n\t\t},\n\t\tsuccess: function() {\n\t\t\tok( true, \"success\" );\n\t\t},\n\t\tcomplete: function() {\n\t\t\tok( true, \"complete\" );\n\t\t}\n\t});\n\n\tajaxTest( \"jQuery.ajax() - xml: non-namespace elements inside namespaced elements\", 3, {\n\t\turl: url(\"data/with_fries.xml\"),\n\t\tdataType: \"xml\",\n\t\tsuccess: function( resp ) {\n\t\t\tequal( jQuery( \"properties\", resp ).length, 1, \"properties in responseXML\" );\n\t\t\tequal( jQuery( \"jsconf\", resp ).length, 1, \"jsconf in responseXML\" );\n\t\t\tequal( jQuery( \"thing\", resp ).length, 2, \"things in responseXML\" );\n\t\t}\n\t});\n\n\tajaxTest( \"jQuery.ajax() - xml: non-namespace elements inside namespaced elements (over JSONP)\", 3, {\n\t\turl: url(\"data/with_fries_over_jsonp.php\"),\n\t\tdataType: \"jsonp xml\",\n\t\tsuccess: function( resp ) {\n\t\t\tequal( jQuery( \"properties\", resp ).length, 1, \"properties in responseXML\" );\n\t\t\tequal( jQuery( \"jsconf\", resp ).length, 1, \"jsconf in responseXML\" );\n\t\t\tequal( jQuery( \"thing\", resp ).length, 2, \"things in responseXML\" );\n\t\t}\n\t});\n\n\tajaxTest( \"jQuery.ajax() - HEAD requests\", 2, [\n\t\t{\n\t\t\turl: url(\"data/name.html\"),\n\t\t\ttype: \"HEAD\",\n\t\t\tsuccess: function( data, status, xhr ) {\n\t\t\t\tok( /Date/i.test( xhr.getAllResponseHeaders() ), \"No Date in HEAD response\" );\n\t\t\t}\n\t\t},\n\t\t{\n\t\t\turl: url(\"data/name.html\"),\n\t\t\tdata: {\n\t\t\t\t\"whip_it\": \"good\"\n\t\t\t},\n\t\t\ttype: \"HEAD\",\n\t\t\tsuccess: function( data, status, xhr ) {\n\t\t\t\tok( /Date/i.test( xhr.getAllResponseHeaders() ), \"No Date in HEAD response with data\" );\n\t\t\t}\n\t\t}\n\t]);\n\n\tajaxTest( \"jQuery.ajax() - beforeSend\", 1, {\n\t\turl: url(\"data/name.html\"),\n\t\tbeforeSend: function() {\n\t\t\tthis.check = true;\n\t\t},\n\t\tsuccess: function() {\n\t\t\tok( this.check, \"check beforeSend was executed\" );\n\t\t}\n\t});\n\n\tajaxTest( \"jQuery.ajax() - beforeSend, cancel request manually\", 2, {\n\t\tcreate: function() {\n\t\t\treturn jQuery.ajax({\n\t\t\t\turl: url(\"data/name.html\"),\n\t\t\t\tbeforeSend: function( xhr ) {\n\t\t\t\t\tok( true, \"beforeSend got called, canceling\" );\n\t\t\t\t\txhr.abort();\n\t\t\t\t},\n\t\t\t\tsuccess: function() {\n\t\t\t\t\tok( false, \"request didn't get canceled\" );\n\t\t\t\t},\n\t\t\t\tcomplete: function() {\n\t\t\t\t\tok( false, \"request didn't get canceled\" );\n\t\t\t\t},\n\t\t\t\terror: function() {\n\t\t\t\t\tok( false, \"request didn't get canceled\" );\n\t\t\t\t}\n\t\t\t});\n\t\t},\n\t\tfail: function( _, reason ) {\n\t\t\tstrictEqual( reason, \"canceled\", \"canceled request must fail with 'canceled' status text\" );\n\t\t}\n\t});\n\n\tajaxTest( \"jQuery.ajax() - dataType html\", 5, {\n\t\tsetup: function() {\n\t\t\tGlobals.register(\"testFoo\");\n\t\t\tGlobals.register(\"testBar\");\n\t\t},\n\t\tdataType: \"html\",\n\t\turl: url(\"data/test.html\"),\n\t\tsuccess: function( data ) {\n\t\t\tok( data.match( /^html text/ ), \"Check content for datatype html\" );\n\t\t\tjQuery(\"#ap\").html( data );\n\t\t\tstrictEqual( window[\"testFoo\"], \"foo\", \"Check if script was evaluated for datatype html\" );\n\t\t\tstrictEqual( window[\"testBar\"], \"bar\", \"Check if script src was evaluated for datatype html\" );\n\t\t}\n\t});\n\n\tajaxTest( \"jQuery.ajax() - synchronous request\", 1, {\n\t\turl: url(\"data/json_obj.js\"),\n\t\tdataType: \"text\",\n\t\tasync: false,\n\t\tsuccess: true,\n\t\tafterSend: function( xhr ) {\n\t\t\tok( /^\\{ \"data\"/.test( xhr.responseText ), \"check returned text\" );\n\t\t}\n\t});\n\n\tajaxTest( \"jQuery.ajax() - synchronous request with callbacks\", 2, {\n\t\turl: url(\"data/json_obj.js\"),\n\t\tasync: false,\n\t\tdataType: \"text\",\n\t\tsuccess: true,\n\t\tafterSend: function( xhr ) {\n\t\t\tvar result;\n\t\t\txhr.done(function( data ) {\n\t\t\t\tok( true, \"success callback executed\" );\n\t\t\t\tresult = data;\n\t\t\t});\n\t\t\tok( /^\\{ \"data\"/.test( result ), \"check returned text\" );\n\t\t}\n\t});\n\n\tasyncTest( \"jQuery.ajax(), jQuery.get[Script|JSON](), jQuery.post(), pass-through request object\", 8, function() {\n\t\tvar target = \"data/name.html\",\n\t\t\tsuccessCount = 0,\n\t\t\terrorCount = 0,\n\t\t\terrorEx = \"\",\n\t\t\tsuccess = function() {\n\t\t\t\tsuccessCount++;\n\t\t\t};\n\t\tjQuery( document ).on( \"ajaxError.passthru\", function( e, xml ) {\n\t\t\terrorCount++;\n\t\t\terrorEx += \": \" + xml.status;\n\t\t});\n\t\tjQuery( document ).one( \"ajaxStop\", function() {\n\t\t\tequal( successCount, 5, \"Check all ajax calls successful\" );\n\t\t\tequal( errorCount, 0, \"Check no ajax errors (status\" + errorEx + \")\" );\n\t\t\tjQuery( document ).off(\"ajaxError.passthru\");\n\t\t\tstart();\n\t\t});\n\t\tGlobals.register(\"testBar\");\n\n\t\tok( jQuery.get( url(target), success ), \"get\" );\n\t\tok( jQuery.post( url(target), success ), \"post\" );\n\t\tok( jQuery.getScript( url(\"data/test.js\"), success ), \"script\" );\n\t\tok( jQuery.getJSON( url(\"data/json_obj.js\"), success ), \"json\" );\n\t\tok( jQuery.ajax({\n\t\t\turl: url( target ),\n\t\t\tsuccess: success\n\t\t}), \"generic\" );\n\t});\n\n\tajaxTest( \"jQuery.ajax() - cache\", 12, function() {\n\n\t\tvar re = /_=(.*?)(&|$)/g;\n\n\t\tfunction request( url, title ) {\n\t\t\treturn {\n\t\t\t\turl: url,\n\t\t\t\tcache: false,\n\t\t\t\tbeforeSend: function() {\n\t\t\t\t\tvar parameter, tmp;\n\t\t\t\t\twhile(( tmp = re.exec( this.url ) )) {\n\t\t\t\t\t\tstrictEqual( parameter, undefined, title + \": only one 'no-cache' parameter\" );\n\t\t\t\t\t\tparameter = tmp[ 1 ];\n\t\t\t\t\t\tnotStrictEqual( parameter, \"tobereplaced555\", title + \": parameter (if it was there) was replaced\" );\n\t\t\t\t\t}\n\t\t\t\t\treturn false;\n\t\t\t\t},\n\t\t\t\terror: true\n\t\t\t};\n\t\t}\n\n\t\treturn [\n\t\t\trequest(\n\t\t\t\t\"data/text.php\",\n\t\t\t\t\"no parameter\"\n\t\t\t),\n\t\t\trequest(\n\t\t\t\t\"data/text.php?pizza=true\",\n\t\t\t\t\"1 parameter\"\n\t\t\t),\n\t\t\trequest(\n\t\t\t\t\"data/text.php?_=tobereplaced555\",\n\t\t\t\t\"_= parameter\"\n\t\t\t),\n\t\t\trequest(\n\t\t\t\t\"data/text.php?pizza=true&_=tobereplaced555\",\n\t\t\t\t\"1 parameter and _=\"\n\t\t\t),\n\t\t\trequest(\n\t\t\t\t\"data/text.php?_=tobereplaced555&tv=false\",\n\t\t\t\t\"_= and 1 parameter\"\n\t\t\t),\n\t\t\trequest(\n\t\t\t\t\"data/text.php?name=David&_=tobereplaced555&washere=true\",\n\t\t\t\t\"2 parameters surrounding _=\"\n\t\t\t)\n\t\t];\n\t});\n\n\tjQuery.each( [ \" - Same Domain\", \" - Cross Domain\" ], function( crossDomain, label ) {\n\n\t\tajaxTest( \"jQuery.ajax() - JSONP - Query String (?n)\" + label, 4, [\n\t\t\t{\n\t\t\t\turl: \"data/jsonp.php?callback=?\",\n\t\t\t\tdataType: \"jsonp\",\n\t\t\t\tcrossDomain: crossDomain,\n\t\t\t\tsuccess: function( data ) {\n\t\t\t\t\tok( data.data, \"JSON results returned (GET, url callback)\" );\n\t\t\t\t}\n\t\t\t},\n\t\t\t{\n\t\t\t\turl: \"data/jsonp.php?callback=??\",\n\t\t\t\tdataType: \"jsonp\",\n\t\t\t\tcrossDomain: crossDomain,\n\t\t\t\tsuccess: function( data ) {\n\t\t\t\t\tok( data.data, \"JSON results returned (GET, url context-free callback)\" );\n\t\t\t\t}\n\t\t\t},\n\t\t\t{\n\t\t\t\turl: \"data/jsonp.php/??\",\n\t\t\t\tdataType: \"jsonp\",\n\t\t\t\tcrossDomain: crossDomain,\n\t\t\t\tsuccess: function( data ) {\n\t\t\t\t\tok( data.data, \"JSON results returned (GET, REST-like)\" );\n\t\t\t\t}\n\t\t\t},\n\t\t\t{\n\t\t\t\turl: \"data/jsonp.php/???json=1\",\n\t\t\t\tdataType: \"jsonp\",\n\t\t\t\tcrossDomain: crossDomain,\n\t\t\t\tsuccess: function( data ) {\n\t\t\t\t\tstrictEqual( jQuery.type( data ), \"array\", \"JSON results returned (GET, REST-like with param)\" );\n\t\t\t\t}\n\t\t\t}\n\t\t]);\n\n\t\tajaxTest( \"jQuery.ajax() - JSONP - Explicit callback param\" + label, 9, {\n\t\t\tsetup: function() {\n\t\t\t\tGlobals.register(\"functionToCleanUp\");\n\t\t\t\tGlobals.register(\"XXX\");\n\t\t\t\tGlobals.register(\"jsonpResults\");\n\t\t\t\twindow[\"jsonpResults\"] = function( data ) {\n\t\t\t\t\tok( data[\"data\"], \"JSON results returned (GET, custom callback function)\" );\n\t\t\t\t};\n\t\t\t},\n\t\t\trequests: [{\n\t\t\t\turl: \"data/jsonp.php\",\n\t\t\t\tdataType: \"jsonp\",\n\t\t\t\tcrossDomain: crossDomain,\n\t\t\t\tjsonp: \"callback\",\n\t\t\t\tsuccess: function( data ) {\n\t\t\t\t\tok( data[\"data\"], \"JSON results returned (GET, data obj callback)\" );\n\t\t\t\t}\n\t\t\t}, {\n\t\t\t\turl: \"data/jsonp.php\",\n\t\t\t\tdataType: \"jsonp\",\n\t\t\t\tcrossDomain: crossDomain,\n\t\t\t\tjsonpCallback: \"jsonpResults\",\n\t\t\t\tsuccess: function( data ) {\n\t\t\t\t\tok( data.data, \"JSON results returned (GET, custom callback name)\" );\n\t\t\t\t}\n\t\t\t}, {\n\t\t\t\turl: \"data/jsonp.php\",\n\t\t\t\tdataType: \"jsonp\",\n\t\t\t\tcrossDomain: crossDomain,\n\t\t\t\tjsonpCallback: \"functionToCleanUp\",\n\t\t\t\tsuccess: function( data ) {\n\t\t\t\t\tok( data[\"data\"], \"JSON results returned (GET, custom callback name to be cleaned up)\" );\n\t\t\t\t\tstrictEqual( window[\"functionToCleanUp\"], undefined, \"Callback was removed (GET, custom callback name to be cleaned up)\" );\n\t\t\t\t\tvar xhr;\n\t\t\t\t\tjQuery.ajax({\n\t\t\t\t\t\turl: \"data/jsonp.php\",\n\t\t\t\t\t\tdataType: \"jsonp\",\n\t\t\t\t\t\tcrossDomain: crossDomain,\n\t\t\t\t\t\tjsonpCallback: \"functionToCleanUp\",\n\t\t\t\t\t\tbeforeSend: function( jqXHR ) {\n\t\t\t\t\t\t\txhr = jqXHR;\n\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t\txhr.fail(function() {\n\t\t\t\t\t\tok( true, \"Ajax error JSON (GET, custom callback name to be cleaned up)\" );\n\t\t\t\t\t\tstrictEqual( window[\"functionToCleanUp\"], undefined, \"Callback was removed after early abort (GET, custom callback name to be cleaned up)\" );\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}, {\n\t\t\t\turl: \"data/jsonp.php?callback=XXX\",\n\t\t\t\tdataType: \"jsonp\",\n\t\t\t\tjsonp: false,\n\t\t\t\tjsonpCallback: \"XXX\",\n\t\t\t\tcrossDomain: crossDomain,\n\t\t\t\tbeforeSend: function() {\n\t\t\t\t\tok( /^data\\/jsonp.php\\?callback=XXX&_=\\d+$/.test( this.url ), \"The URL wasn't messed with (GET, custom callback name with no url manipulation)\" );\n\t\t\t\t},\n\t\t\t\tsuccess: function( data ) {\n\t\t\t\t\tok( data[\"data\"], \"JSON results returned (GET, custom callback name with no url manipulation)\" );\n\t\t\t\t}\n\t\t\t}]\n\t\t});\n\n\t\tajaxTest( \"jQuery.ajax() - JSONP - Callback in data\" + label, 2, [\n\t\t\t{\n\t\t\t\turl: \"data/jsonp.php\",\n\t\t\t\tdataType: \"jsonp\",\n\t\t\t\tcrossDomain: crossDomain,\n\t\t\t\tdata: \"callback=?\",\n\t\t\t\tsuccess: function( data ) {\n\t\t\t\t\tok( data.data, \"JSON results returned (GET, data callback)\" );\n\t\t\t\t}\n\t\t\t},\n\t\t\t{\n\t\t\t\turl: \"data/jsonp.php\",\n\t\t\t\tdataType: \"jsonp\",\n\t\t\t\tcrossDomain: crossDomain,\n\t\t\t\tdata: \"callback=??\",\n\t\t\t\tsuccess: function( data ) {\n\t\t\t\t\tok( data.data, \"JSON results returned (GET, data context-free callback)\" );\n\t\t\t\t}\n\t\t\t}\n\t\t]);\n\n\n\t\tajaxTest( \"jQuery.ajax() - JSONP - POST\" + label, 3, [\n\t\t\t{\n\t\t\t\ttype: \"POST\",\n\t\t\t\turl: \"data/jsonp.php\",\n\t\t\t\tdataType: \"jsonp\",\n\t\t\t\tcrossDomain: crossDomain,\n\t\t\t\tsuccess: function( data ) {\n\t\t\t\t\tok( data[\"data\"], \"JSON results returned (POST, no callback)\" );\n\t\t\t\t}\n\t\t\t},\n\t\t\t{\n\t\t\t\ttype: \"POST\",\n\t\t\t\turl: \"data/jsonp.php\",\n\t\t\t\tdata: \"callback=?\",\n\t\t\t\tdataType: \"jsonp\",\n\t\t\t\tcrossDomain: crossDomain,\n\t\t\t\tsuccess: function( data ) {\n\t\t\t\t\tok( data[\"data\"], \"JSON results returned (POST, data callback)\" );\n\t\t\t\t}\n\t\t\t},\n\t\t\t{\n\t\t\t\ttype: \"POST\",\n\t\t\t\turl: \"data/jsonp.php\",\n\t\t\t\tjsonp: \"callback\",\n\t\t\t\tdataType: \"jsonp\",\n\t\t\t\tcrossDomain: crossDomain,\n\t\t\t\tsuccess: function( data ) {\n\t\t\t\t\tok( data[\"data\"], \"JSON results returned (POST, data obj callback)\" );\n\t\t\t\t}\n\t\t\t}\n\t\t]);\n\n\t\tajaxTest( \"jQuery.ajax() - JSONP\" + label, 3, [\n\t\t\t{\n\t\t\t\turl: \"data/jsonp.php\",\n\t\t\t\tdataType: \"jsonp\",\n\t\t\t\tcrossDomain: crossDomain,\n\t\t\t\tsuccess: function( data ) {\n\t\t\t\t\tok( data.data, \"JSON results returned (GET, no callback)\" );\n\t\t\t\t}\n\t\t\t},\n\t\t\t{\n\t\t\t\tcreate: function( options ) {\n\t\t\t\t\tvar request = jQuery.ajax( options ),\n\t\t\t\t\t\tpromise = request.then(function( data ) {\n\t\t\t\t\t\t\tok( data.data, \"first request: JSON results returned (GET, no callback)\" );\n\t\t\t\t\t\t\trequest = jQuery.ajax( this ).done(function( data ) {\n\t\t\t\t\t\t\t\tok( data.data, \"this re-used: JSON results returned (GET, no callback)\" );\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tpromise.abort = request.abort;\n\t\t\t\t\t\t\treturn request;\n\t\t\t\t\t\t});\n\t\t\t\t\tpromise.abort = request.abort;\n\t\t\t\t\treturn promise;\n\t\t\t\t},\n\t\t\t\turl: \"data/jsonp.php\",\n\t\t\t\tdataType: \"jsonp\",\n\t\t\t\tcrossDomain: crossDomain,\n\t\t\t\tsuccess: true\n\t\t\t}\n\t\t]);\n\n\t});\n\n\tajaxTest( \"jQuery.ajax() - script, Remote\", 2, {\n\t\tsetup: function() {\n\t\t\tGlobals.register(\"testBar\");\n\t\t},\n\t\turl: window.location.href.replace( /[^\\/]*$/, \"\" ) + \"data/test.js\",\n\t\tdataType: \"script\",\n\t\tsuccess: function() {\n\t\t\tstrictEqual( window[\"testBar\"], \"bar\", \"Script results returned (GET, no callback)\" );\n\t\t}\n\t});\n\n\tajaxTest( \"jQuery.ajax() - script, Remote with POST\", 3, {\n\t\tsetup: function() {\n\t\t\tGlobals.register(\"testBar\");\n\t\t},\n\t\turl: window.location.href.replace( /[^\\/]*$/, \"\" ) + \"data/test.js\",\n\t\ttype: \"POST\",\n\t\tdataType: \"script\",\n\t\tsuccess: function( data, status ) {\n\t\t\tstrictEqual( window[\"testBar\"], \"bar\", \"Script results returned (POST, no callback)\" );\n\t\t\tstrictEqual( status, \"success\", \"Script results returned (POST, no callback)\" );\n\t\t}\n\t});\n\n\tajaxTest( \"jQuery.ajax() - script, Remote with scheme-less URL\", 2, {\n\t\tsetup: function() {\n\t\t\tGlobals.register(\"testBar\");\n\t\t},\n\t\turl: window.location.href.replace( /[^\\/]*$/, \"\" ).replace( /^.*?\\/\\//, \"//\" ) + \"data/test.js\",\n\t\tdataType: \"script\",\n\t\tsuccess: function() {\n\t\t\tstrictEqual( window[\"testBar\"], \"bar\", \"Script results returned (GET, no callback)\" );\n\t\t}\n\t});\n\n\tajaxTest( \"jQuery.ajax() - malformed JSON\", 2, {\n\t\turl: \"data/badjson.js\",\n\t\tdataType: \"json\",\n\t\terror: function( xhr, msg, detailedMsg ) {\n\t\t\tstrictEqual( msg, \"parsererror\", \"A parse error occurred.\" );\n\t\t\tok( /(invalid|error|exception)/i.test( detailedMsg ), \"Detailed parsererror message provided\" );\n\t\t}\n\t});\n\n\tajaxTest( \"jQuery.ajax() - script by content-type\", 2, [\n\t\t{\n\t\t\turl: \"data/script.php\",\n\t\t\tdata: {\n\t\t\t\t\"header\": \"script\"\n\t\t\t},\n\t\t\tsuccess: true\n\t\t},\n\t\t{\n\t\t\turl: \"data/script.php\",\n\t\t\tdata: {\n\t\t\t\t\"header\": \"ecma\"\n\t\t\t},\n\t\t\tsuccess: true\n\t\t}\n\t]);\n\n\tajaxTest( \"jQuery.ajax() - JSON by content-type\", 5, {\n\t\turl: \"data/json.php\",\n\t\tdata: {\n\t\t\t\"header\": \"json\",\n\t\t\t\"json\": \"array\"\n\t\t},\n\t\tsuccess: function( json ) {\n\t\t\tok( json.length >= 2, \"Check length\" );\n\t\t\tstrictEqual( json[ 0 ][\"name\"], \"John\", \"Check JSON: first, name\" );\n\t\t\tstrictEqual( json[ 0 ][\"age\"], 21, \"Check JSON: first, age\" );\n\t\t\tstrictEqual( json[ 1 ][\"name\"], \"Peter\", \"Check JSON: second, name\" );\n\t\t\tstrictEqual( json[ 1 ][\"age\"], 25, \"Check JSON: second, age\" );\n\t\t}\n\t});\n\n\tajaxTest( \"jQuery.ajax() - JSON by content-type disabled with options\", 6, {\n\t\turl: url(\"data/json.php\"),\n\t\tdata: {\n\t\t\t\"header\": \"json\",\n\t\t\t\"json\": \"array\"\n\t\t},\n\t\tcontents: {\n\t\t\t\"json\": false\n\t\t},\n\t\tsuccess: function( text ) {\n\t\t\tstrictEqual( typeof text, \"string\", \"json wasn't auto-determined\" );\n\t\t\tvar json = jQuery.parseJSON( text );\n\t\t\tok( json.length >= 2, \"Check length\");\n\t\t\tstrictEqual( json[ 0 ][\"name\"], \"John\", \"Check JSON: first, name\" );\n\t\t\tstrictEqual( json[ 0 ][\"age\"], 21, \"Check JSON: first, age\" );\n\t\t\tstrictEqual( json[ 1 ][\"name\"], \"Peter\", \"Check JSON: second, name\" );\n\t\t\tstrictEqual( json[ 1 ][\"age\"], 25, \"Check JSON: second, age\" );\n\t\t}\n\t});\n\n\tajaxTest( \"jQuery.ajax() - simple get\", 1, {\n\t\ttype: \"GET\",\n\t\turl: url(\"data/name.php?name=foo\"),\n\t\tsuccess: function( msg ) {\n\t\t\tstrictEqual( msg, \"bar\", \"Check for GET\" );\n\t\t}\n\t});\n\n\tajaxTest( \"jQuery.ajax() - simple post\", 1, {\n\t\ttype: \"POST\",\n\t\turl: url(\"data/name.php\"),\n\t\tdata: \"name=peter\",\n\t\tsuccess: function( msg ) {\n\t\t\tstrictEqual( msg, \"pan\", \"Check for POST\" );\n\t\t}\n\t});\n\n\tajaxTest( \"jQuery.ajax() - data option - empty bodies for non-GET requests\", 1, {\n\t\turl: \"data/echoData.php\",\n\t\tdata: undefined,\n\t\ttype: \"post\",\n\t\tsuccess: function( result ) {\n\t\t\tstrictEqual( result, \"\" );\n\t\t}\n\t});\n\n\tvar ifModifiedNow = new Date();\n\n\tjQuery.each(\n\t\t/* jQuery.each arguments start */\n\t\t{\n\t\t\t\" (cache)\": true,\n\t\t\t\" (no cache)\": false\n\t\t},\n\t\tfunction( label, cache ) {\n\t\t\t// Support: Opera 12.0\n\t\t\t// In Opera 12.0, XHR doesn't notify 304 back to the user properly\n\t\t\tvar opera = window.opera && window.opera.version();\n\t\t\tjQuery.each(\n\t\t\t\t{\n\t\t\t\t\t\"If-Modified-Since\": \"if_modified_since.php\",\n\t\t\t\t\t\"Etag\": \"etag.php\"\n\t\t\t\t},\n\t\t\t\tfunction( type, url ) {\n\t\t\t\t\turl = \"data/\" + url + \"?ts=\" + ifModifiedNow++;\n\t\t\t\t\tasyncTest( \"jQuery.ajax() - \" + type + \" support\" + label, 4, function() {\n\t\t\t\t\t\tjQuery.ajax({\n\t\t\t\t\t\t\turl: url,\n\t\t\t\t\t\t\tifModified: true,\n\t\t\t\t\t\t\tcache: cache,\n\t\t\t\t\t\t\tsuccess: function( _, status ) {\n\t\t\t\t\t\t\t\tstrictEqual( status, \"success\", \"Initial status is 'success'\" );\n\t\t\t\t\t\t\t\tjQuery.ajax({\n\t\t\t\t\t\t\t\t\turl: url,\n\t\t\t\t\t\t\t\t\tifModified: true,\n\t\t\t\t\t\t\t\t\tcache: cache,\n\t\t\t\t\t\t\t\t\tsuccess: function( data, status, jqXHR ) {\n\t\t\t\t\t\t\t\t\t\tif ( status === \"success\" && opera === \"12.00\" ) {\n\t\t\t\t\t\t\t\t\t\t\tstrictEqual( status, \"success\", \"Opera 12.0: Following status is 'success'\" );\n\t\t\t\t\t\t\t\t\t\t\tstrictEqual( jqXHR.status, 200, \"Opera 12.0: XHR status is 200, not 304\" );\n\t\t\t\t\t\t\t\t\t\t\tstrictEqual( data, \"\", \"Opera 12.0: response body is empty\" );\n\t\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\t\tstrictEqual( status, \"notmodified\", \"Following status is 'notmodified'\" );\n\t\t\t\t\t\t\t\t\t\t\tstrictEqual( jqXHR.status, 304, \"XHR status is 304\" );\n\t\t\t\t\t\t\t\t\t\t\tequal( data, null, \"no response body is given\" );\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\tcomplete: function() {\n\t\t\t\t\t\t\t\t\t\tstart();\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t});\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t);\n\t\t}\n\t\t/* jQuery.each arguments end */\n\t);\n\n\tajaxTest( \"jQuery.ajax() - failing cross-domain (non-existing)\", 1, {\n\t\t// see RFC 2606\n\t\turl: \"http://example.invalid\",\n\t\terror: function( xhr, _, e ) {\n\t\t\tok( true, \"file not found: \" + xhr.status + \" => \" + e );\n\t\t}\n\t});\n\n\tajaxTest( \"jQuery.ajax() - failing cross-domain\", 1, {\n\t\turl: \"http://\" + externalHost,\n\t\terror: function( xhr, _, e ) {\n\t\t\tok( true, \"access denied: \" + xhr.status + \" => \" + e );\n\t\t}\n\t});\n\n\tajaxTest( \"jQuery.ajax() - atom+xml\", 1, {\n\t\turl: url(\"data/atom+xml.php\"),\n\t\tsuccess: function() {\n\t\t\tok( true, \"success\" );\n\t\t}\n\t});\n\n\tasyncTest( \"jQuery.ajax() - statusText\", 3, function() {\n\t\tjQuery.ajax( url(\"data/statusText.php?status=200&text=Hello\") ).done(function( _, statusText, jqXHR ) {\n\t\t\tstrictEqual( statusText, \"success\", \"callback status text ok for success\" );\n\t\t\tok( jqXHR.statusText === \"Hello\" || jqXHR.statusText === \"OK\", \"jqXHR status text ok for success (\" + jqXHR.statusText + \")\" );\n\t\t\tjQuery.ajax( url(\"data/statusText.php?status=404&text=World\") ).fail(function( jqXHR, statusText ) {\n\t\t\t\tstrictEqual( statusText, \"error\", \"callback status text ok for error\" );\n\t\t\t\tstart();\n\t\t\t});\n\t\t});\n\t});\n\n\tasyncTest( \"jQuery.ajax() - statusCode\", 20, function() {\n\n\t\tvar count = 12;\n\n\t\tfunction countComplete() {\n\t\t\tif ( ! --count ) {\n\t\t\t\tstart();\n\t\t\t}\n\t\t}\n\n\t\tfunction createStatusCodes( name, isSuccess ) {\n\t\t\tname = \"Test \" + name + \" \" + ( isSuccess ? \"success\" : \"error\" );\n\t\t\treturn {\n\t\t\t\t200: function() {\n\t\t\t\t\tok( isSuccess, name );\n\t\t\t\t},\n\t\t\t\t404: function() {\n\t\t\t\t\tok( !isSuccess, name );\n\t\t\t\t}\n\t\t\t};\n\t\t}\n\n\t\tjQuery.each(\n\t\t\t/* jQuery.each arguments start */\n\t\t\t{\n\t\t\t\t\"data/name.html\": true,\n\t\t\t\t\"data/someFileThatDoesNotExist.html\": false\n\t\t\t},\n\t\t\tfunction( uri, isSuccess ) {\n\n\t\t\t\tjQuery.ajax( url(uri), {\n\t\t\t\t\tstatusCode: createStatusCodes( \"in options\", isSuccess ),\n\t\t\t\t\tcomplete: countComplete\n\t\t\t\t});\n\n\t\t\t\tjQuery.ajax( url(uri), {\n\t\t\t\t\tcomplete: countComplete\n\t\t\t\t}).statusCode( createStatusCodes(\"immediately with method\", isSuccess) );\n\n\t\t\t\tjQuery.ajax( url(uri), {\n\t\t\t\t\tcomplete: function( jqXHR ) {\n\t\t\t\t\t\tjqXHR.statusCode( createStatusCodes(\"on complete\", isSuccess) );\n\t\t\t\t\t\tcountComplete();\n\t\t\t\t\t}\n\t\t\t\t});\n\n\t\t\t\tjQuery.ajax( url(uri), {\n\t\t\t\t\tcomplete: function( jqXHR ) {\n\t\t\t\t\t\tsetTimeout(function() {\n\t\t\t\t\t\t\tjqXHR.statusCode( createStatusCodes(\"very late binding\", isSuccess) );\n\t\t\t\t\t\t\tcountComplete();\n\t\t\t\t\t\t}, 100 );\n\t\t\t\t\t}\n\t\t\t\t});\n\n\t\t\t\tjQuery.ajax( url(uri), {\n\t\t\t\t\tstatusCode: createStatusCodes( \"all (options)\", isSuccess ),\n\t\t\t\t\tcomplete: function( jqXHR ) {\n\t\t\t\t\t\tjqXHR.statusCode( createStatusCodes(\"all (on complete)\", isSuccess) );\n\t\t\t\t\t\tsetTimeout(function() {\n\t\t\t\t\t\t\tjqXHR.statusCode( createStatusCodes(\"all (very late binding)\", isSuccess) );\n\t\t\t\t\t\t\tcountComplete();\n\t\t\t\t\t\t}, 100 );\n\t\t\t\t\t}\n\t\t\t\t}).statusCode( createStatusCodes(\"all (immediately with method)\", isSuccess) );\n\n\t\t\t\tvar testString = \"\";\n\n\t\t\t\tjQuery.ajax( url(uri), {\n\t\t\t\t\tsuccess: function( a, b, jqXHR ) {\n\t\t\t\t\t\tok( isSuccess, \"success\" );\n\t\t\t\t\t\tvar statusCode = {};\n\t\t\t\t\t\tstatusCode[ jqXHR.status ] = function() {\n\t\t\t\t\t\t\ttestString += \"B\";\n\t\t\t\t\t\t};\n\t\t\t\t\t\tjqXHR.statusCode( statusCode );\n\t\t\t\t\t\ttestString += \"A\";\n\t\t\t\t\t},\n\t\t\t\t\terror: function( jqXHR ) {\n\t\t\t\t\t\tok( !isSuccess, \"error\" );\n\t\t\t\t\t\tvar statusCode = {};\n\t\t\t\t\t\tstatusCode[ jqXHR.status ] = function() {\n\t\t\t\t\t\t\ttestString += \"B\";\n\t\t\t\t\t\t};\n\t\t\t\t\t\tjqXHR.statusCode( statusCode );\n\t\t\t\t\t\ttestString += \"A\";\n\t\t\t\t\t},\n\t\t\t\t\tcomplete: function() {\n\t\t\t\t\t\tstrictEqual(\n\t\t\t\t\t\t\ttestString,\n\t\t\t\t\t\t\t\"AB\",\n\t\t\t\t\t\t\t\"Test statusCode callbacks are ordered like \" + ( isSuccess ? \"success\" :  \"error\" ) + \" callbacks\"\n\t\t\t\t\t\t);\n\t\t\t\t\t\tcountComplete();\n\t\t\t\t\t}\n\t\t\t\t});\n\n\t\t\t}\n\t\t\t/* jQuery.each arguments end*/\n\t\t);\n\t});\n\n\tajaxTest( \"jQuery.ajax() - transitive conversions\", 8, [\n\t\t{\n\t\t\turl: url(\"data/json.php\"),\n\t\t\tconverters: {\n\t\t\t\t\"json myJson\": function( data ) {\n\t\t\t\t\tok( true, \"converter called\" );\n\t\t\t\t\treturn data;\n\t\t\t\t}\n\t\t\t},\n\t\t\tdataType: \"myJson\",\n\t\t\tsuccess: function() {\n\t\t\t\tok( true, \"Transitive conversion worked\" );\n\t\t\t\tstrictEqual( this.dataTypes[ 0 ], \"text\", \"response was retrieved as text\" );\n\t\t\t\tstrictEqual( this.dataTypes[ 1 ], \"myjson\", \"request expected myjson dataType\" );\n\t\t\t}\n\t\t},\n\t\t{\n\t\t\turl: url(\"data/json.php\"),\n\t\t\tconverters: {\n\t\t\t\t\"json myJson\": function( data ) {\n\t\t\t\t\tok( true, \"converter called (*)\" );\n\t\t\t\t\treturn data;\n\t\t\t\t}\n\t\t\t},\n\t\t\tcontents: false, /* headers are wrong so we ignore them */\n\t\t\tdataType: \"* myJson\",\n\t\t\tsuccess: function() {\n\t\t\t\tok( true, \"Transitive conversion worked (*)\" );\n\t\t\t\tstrictEqual( this.dataTypes[ 0 ], \"text\", \"response was retrieved as text (*)\" );\n\t\t\t\tstrictEqual( this.dataTypes[ 1 ], \"myjson\", \"request expected myjson dataType (*)\" );\n\t\t\t}\n\t\t}\n\t]);\n\n\tajaxTest( \"jQuery.ajax() - overrideMimeType\", 2, [\n\t\t{\n\t\t\turl: url(\"data/json.php\"),\n\t\t\tbeforeSend: function( xhr ) {\n\t\t\t\txhr.overrideMimeType( \"application/json\" );\n\t\t\t},\n\t\t\tsuccess: function( json ) {\n\t\t\t\tok( json.data, \"Mimetype overridden using beforeSend\" );\n\t\t\t}\n\t\t},\n\t\t{\n\t\t\turl: url(\"data/json.php\"),\n\t\t\tmimeType: \"application/json\",\n\t\t\tsuccess: function( json ) {\n\t\t\t\tok( json.data, \"Mimetype overridden using mimeType option\" );\n\t\t\t}\n\t\t}\n\t]);\n\n\tajaxTest( \"jQuery.ajax() - empty json gets to error callback instead of success callback.\", 1, {\n\t\turl: url(\"data/echoData.php\"),\n\t\terror: function( _, __, error ) {\n\t\t\tequal( typeof error === \"object\", true,  \"Didn't get back error object for empty json response\" );\n\t\t},\n\t\tdataType: \"json\"\n\t});\n\n\tajaxTest( \"#2688 - jQuery.ajax() - beforeSend, cancel request\", 2, {\n\t\tcreate: function() {\n\t\t\treturn jQuery.ajax({\n\t\t\t\turl: url(\"data/name.html\"),\n\t\t\t\tbeforeSend: function() {\n\t\t\t\t\tok( true, \"beforeSend got called, canceling\" );\n\t\t\t\t\treturn false;\n\t\t\t\t},\n\t\t\t\tsuccess: function() {\n\t\t\t\t\tok( false, \"request didn't get canceled\" );\n\t\t\t\t},\n\t\t\t\tcomplete: function() {\n\t\t\t\t\tok( false, \"request didn't get canceled\" );\n\t\t\t\t},\n\t\t\t\terror: function() {\n\t\t\t\t\tok( false, \"request didn't get canceled\" );\n\t\t\t\t}\n\t\t\t});\n\t\t},\n\t\tfail: function( _, reason ) {\n\t\t\tstrictEqual( reason, \"canceled\", \"canceled request must fail with 'canceled' status text\" );\n\t\t}\n\t});\n\n\tajaxTest( \"#2806 - jQuery.ajax() - data option - evaluate function values\", 1, {\n\t\turl: \"data/echoQuery.php\",\n\t\tdata: {\n\t\t\tkey: function() {\n\t\t\t\treturn \"value\";\n\t\t\t}\n\t\t},\n\t\tsuccess: function( result ) {\n\t\t\tstrictEqual( result, \"key=value\" );\n\t\t}\n\t});\n\n\ttest( \"#7531 - jQuery.ajax() - Location object as url\", 1, function () {\n\t\tvar xhr,\n\t\t\tsuccess = false;\n\t\ttry {\n\t\t\txhr = jQuery.ajax({\n\t\t\t\turl: window.location\n\t\t\t});\n\t\t\tsuccess = true;\n\t\t\txhr.abort();\n\t\t} catch (e) {\n\n\t\t}\n\t\tok( success, \"document.location did not generate exception\" );\n\t});\n\n\tjQuery.each( [ \" - Same Domain\", \" - Cross Domain\" ], function( crossDomain, label ) {\n\t\tajaxTest( \"#7578 - jQuery.ajax() - JSONP - default for cache option\" + label, 1, {\n\t\t\turl: \"data/jsonp.php\",\n\t\t\tdataType: \"jsonp\",\n\t\t\tcrossDomain: crossDomain,\n\t\t\tbeforeSend: function() {\n\t\t\t\tstrictEqual( this.cache, false, \"cache must be false on JSON request\" );\n\t\t\t\treturn false;\n\t\t\t},\n\t\t\terror: true\n\t\t});\n\t});\n\n\tajaxTest( \"#8107 - jQuery.ajax() - multiple method signatures introduced in 1.5\", 4, [\n\t\t{\n\t\t\tcreate: function() {\n\t\t\t\treturn jQuery.ajax();\n\t\t\t},\n\t\t\tdone: function() {\n\t\t\t\tok( true, \"With no arguments\" );\n\t\t\t}\n\t\t},\n\t\t{\n\t\t\tcreate: function() {\n\t\t\t\treturn jQuery.ajax(\"data/name.html\");\n\t\t\t},\n\t\t\tdone: function() {\n\t\t\t\tok( true, \"With only string URL argument\" );\n\t\t\t}\n\t\t},\n\t\t{\n\t\t\tcreate: function() {\n\t\t\t\treturn jQuery.ajax( \"data/name.html\", {});\n\t\t\t},\n\t\t\tdone: function() {\n\t\t\t\tok( true, \"With string URL param and map\" );\n\t\t\t}\n\t\t},\n\t\t{\n\t\t\tcreate: function( options ) {\n\t\t\t\treturn jQuery.ajax( options );\n\t\t\t},\n\t\t\turl: \"data/name.html\",\n\t\t\tsuccess: function() {\n\t\t\t\tok( true, \"With only map\" );\n\t\t\t}\n\t\t}\n\t]);\n\n\tjQuery.each( [ \" - Same Domain\", \" - Cross Domain\" ], function( crossDomain, label ) {\n\t\tajaxTest( \"#8205 - jQuery.ajax() - JSONP - re-use callbacks name\" + label, 2, {\n\t\t\turl: \"data/jsonp.php\",\n\t\t\tdataType: \"jsonp\",\n\t\t\tcrossDomain: crossDomain,\n\t\t\tbeforeSend: function( jqXHR, s ) {\n\t\t\t\ts.callback = s.jsonpCallback;\n\t\t\t},\n\t\t\tsuccess: function() {\n\t\t\t\tvar previous = this;\n\t\t\t\tstrictEqual( previous.jsonpCallback, undefined, \"jsonpCallback option is set back to default in callbacks\" );\n\t\t\t\tjQuery.ajax({\n\t\t\t\t\turl: \"data/jsonp.php\",\n\t\t\t\t\tdataType: \"jsonp\",\n\t\t\t\t\tcrossDomain: crossDomain,\n\t\t\t\t\tbeforeSend: function() {\n\t\t\t\t\t\tstrictEqual( this.jsonpCallback, previous.callback, \"JSONP callback name is re-used\" );\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t});\n\t});\n\n\ttest( \"#9887 - jQuery.ajax() - Context with circular references (#9887)\", 2, function () {\n\t\tvar success = false,\n\t\t\tcontext = {};\n\t\tcontext.field = context;\n\t\ttry {\n\t\t\tjQuery.ajax( \"non-existing\", {\n\t\t\t\tcontext: context,\n\t\t\t\tbeforeSend: function() {\n\t\t\t\t\tok( this === context, \"context was not deep extended\" );\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t});\n\t\t\tsuccess = true;\n\t\t} catch ( e ) {\n\t\t\tconsole.log( e );\n\t\t}\n\t\tok( success, \"context with circular reference did not generate an exception\" );\n\t});\n\n\tjQuery.each( [ \"as argument\", \"in settings object\" ], function( inSetting, title ) {\n\n\t\tfunction request( url, test ) {\n\t\t\treturn {\n\t\t\t\tcreate: function() {\n\t\t\t\t\treturn jQuery.ajax( inSetting ? { url: url } : url );\n\t\t\t\t},\n\t\t\t\tdone: function() {\n\t\t\t\t\tok( true, ( test || url ) + \" \" + title );\n\t\t\t\t}\n\t\t\t};\n\t\t}\n\n\t\tajaxTest( \"#10093 - jQuery.ajax() - falsy url \" + title, 4, [\n\t\t\trequest( \"\", \"empty string\" ),\n\t\t\trequest( false ),\n\t\t\trequest( null ),\n\t\t\trequest( undefined )\n\t\t]);\n\n\t});\n\n\tajaxTest( \"#11151 - jQuery.ajax() - parse error body\", 2, {\n\t\turl: url(\"data/errorWithJSON.php\"),\n\t\tdataFilter: function( string ) {\n\t\t\tok( false, \"dataFilter called\" );\n\t\t\treturn string;\n\t\t},\n\t\terror: function( jqXHR ) {\n\t\t\tstrictEqual( jqXHR.responseText, \"{ \\\"code\\\": 40, \\\"message\\\": \\\"Bad Request\\\" }\", \"Error body properly set\" );\n\t\t\tdeepEqual( jqXHR.responseJSON, { code: 40, message: \"Bad Request\" }, \"Error body properly parsed\" );\n\t\t}\n\t});\n\n\tajaxTest( \"#11426 - jQuery.ajax() - loading binary data shouldn't throw an exception in IE\", 1, {\n\t\turl: url(\"data/1x1.jpg\"),\n\t\tsuccess: function( data ) {\n\t\t\tok( data === undefined || /JFIF/.test( data ), \"success callback reached\" );\n\t\t}\n\t});\n\n\tasyncTest( \"#11743 - jQuery.ajax() - script, throws exception\", 1, function() {\n\t\tvar onerror = window.onerror;\n\t\twindow.onerror = function() {\n\t\t\tok( true, \"Exception thrown\" );\n\t\t\twindow.onerror = onerror;\n\t\t\tstart();\n\t\t};\n\t\tjQuery.ajax({\n\t\t\turl: \"data/badjson.js\",\n\t\t\tdataType: \"script\",\n\t\t\tthrows: true,\n\t\t\t// Global events get confused by the exception\n\t\t\tglobal: false,\n\t\t\tsuccess: function() {\n\t\t\t\tok( false, \"Success.\" );\n\t\t\t},\n\t\t\terror: function() {\n\t\t\t\tok( false, \"Error.\" );\n\t\t\t}\n\t\t});\n\t});\n\n\tjQuery.each( [ \"method\", \"type\" ], function( _, globalOption ) {\n\n\t\tfunction request( option ) {\n\t\t\tvar options = {\n\t\t\t\t\turl: url(\"data/echoData.php\"),\n\t\t\t\t\tdata: \"hello\",\n\t\t\t\t\tsuccess: function( msg ) {\n\t\t\t\t\t\tstrictEqual( msg, \"hello\", \"Check for POST (no override)\" );\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\tif ( option ) {\n\t\t\t\toptions[ option ] = \"GET\";\n\t\t\t\toptions.success = function( msg ) {\n\t\t\t\t\tstrictEqual( msg, \"\", \"Check for no POST (overriding with \" + option + \")\" );\n\t\t\t\t};\n\t\t\t}\n\t\t\treturn options;\n\t\t}\n\n\t\tajaxTest( \"#12004 - jQuery.ajax() - method is an alias of type - \" + globalOption + \" set globally\", 3, {\n\t\t\tsetup: function() {\n\t\t\t\tvar options = {};\n\t\t\t\toptions[ globalOption ] = \"POST\";\n\t\t\t\tjQuery.ajaxSetup( options );\n\t\t\t},\n\t\t\trequests: [\n\t\t\t\trequest(\"type\"),\n\t\t\t\trequest(\"method\"),\n\t\t\t\trequest()\n\t\t\t]\n\t\t});\n\n\t});\n\n\tajaxTest( \"#13276 - jQuery.ajax() - compatibility between XML documents from ajax requests and parsed string\", 1, {\n\t\turl: \"data/dashboard.xml\",\n\t\tdataType: \"xml\",\n\t\tsuccess: function( ajaxXML ) {\n\t\t\tvar parsedXML = jQuery( jQuery.parseXML(\"<tab title=\\\"Added\\\">blibli</tab>\") ).find(\"tab\");\n\t\t\tajaxXML = jQuery( ajaxXML );\n\t\t\ttry {\n\t\t\t\tajaxXML.find(\"infowindowtab\").append( parsedXML );\n\t\t\t} catch( e ) {\n\t\t\t\tstrictEqual( e, undefined, \"error\" );\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tstrictEqual( ajaxXML.find(\"tab\").length, 3, \"Parsed node was added properly\" );\n\t\t}\n\t});\n\n\tajaxTest( \"#13292 - jQuery.ajax() - converter is bypassed for 204 requests\", 3, {\n\t\turl: \"data/nocontent.php\",\n\t\tdataType: \"testing\",\n\t\tconverters: {\n\t\t\t\"* testing\": function() {\n\t\t\t\tthrow \"converter was called\";\n\t\t\t}\n\t\t},\n\t\tsuccess: function( data, status, jqXHR ) {\n\t\t\tstrictEqual( jqXHR.status, 204, \"status code is 204\" );\n\t\t\tstrictEqual( status, \"nocontent\", \"status text is 'nocontent'\" );\n\t\t\tstrictEqual( data, undefined, \"data is undefined\" );\n\t\t},\n\t\terror: function( _, status, error ) {\n\t\t\tok( false, \"error\" );\n\t\t\tstrictEqual( status, \"parsererror\", \"Parser Error\" );\n\t\t\tstrictEqual( error, \"converter was called\", \"Converter was called\" );\n\t\t}\n\t});\n\n\tajaxTest( \"#13388 - jQuery.ajax() - responseXML\", 3, {\n\t\turl: url(\"data/with_fries.xml\"),\n\t\tdataType: \"xml\",\n\t\tsuccess: function( resp, _, jqXHR ) {\n\t\t\tnotStrictEqual( resp, undefined, \"XML document exists\" );\n\t\t\tok( \"responseXML\" in jqXHR, \"jqXHR.responseXML exists\" );\n\t\t\tstrictEqual( resp, jqXHR.responseXML, \"jqXHR.responseXML is set correctly\" );\n\t\t}\n\t});\n\n\tajaxTest( \"#13922 - jQuery.ajax() - converter is bypassed for HEAD requests\", 3, {\n\t\turl: \"data/json.php\",\n\t\tmethod: \"HEAD\",\n\t\tdata: {\n\t\t\theader: \"yes\"\n\t\t},\n\t\tconverters: {\n\t\t\t\"text json\": function() {\n\t\t\t\tthrow \"converter was called\";\n\t\t\t}\n\t\t},\n\t\tsuccess: function( data, status ) {\n\t\t\tok( true, \"success\" );\n\t\t\tstrictEqual( status, \"nocontent\", \"data is undefined\" );\n\t\t\tstrictEqual( data, undefined, \"data is undefined\" );\n\t\t},\n\t\terror: function( _, status, error ) {\n\t\t\tok( false, \"error\" );\n\t\t\tstrictEqual( status, \"parsererror\", \"Parser Error\" );\n\t\t\tstrictEqual( error, \"converter was called\", \"Converter was called\" );\n\t\t}\n\t} );\n\n//----------- jQuery.ajaxPrefilter()\n\n\tajaxTest( \"jQuery.ajaxPrefilter() - abort\", 1, {\n\t\tsetup: function() {\n\t\t\tjQuery.ajaxPrefilter(function( options, _, jqXHR ) {\n\t\t\t\tif ( options.abortInPrefilter ) {\n\t\t\t\t\tjqXHR.abort();\n\t\t\t\t}\n\t\t\t});\n\t\t},\n\t\tabortInPrefilter: true,\n\t\terror: function() {\n\t\t\tok( false, \"error callback called\" );\n\t\t},\n\t\tfail: function( _, reason ) {\n\t\t\tstrictEqual( reason, \"canceled\", \"Request aborted by the prefilter must fail with 'canceled' status text\" );\n\t\t}\n\t});\n\n//----------- jQuery.ajaxSetup()\n\n\tasyncTest( \"jQuery.ajaxSetup()\", 1, function() {\n\t\tjQuery.ajaxSetup({\n\t\t\turl: url(\"data/name.php?name=foo\"),\n\t\t\tsuccess: function( msg ) {\n\t\t\t\tstrictEqual( msg, \"bar\", \"Check for GET\" );\n\t\t\t\tstart();\n\t\t\t}\n\t\t});\n\t\tjQuery.ajax();\n\t});\n\n\tasyncTest( \"jQuery.ajaxSetup({ timeout: Number }) - with global timeout\", 2, function() {\n\t\tvar passed = 0,\n\t\t\tpass = function() {\n\t\t\t\tok( passed++ < 2, \"Error callback executed\" );\n\t\t\t\tif ( passed === 2 ) {\n\t\t\t\t\tjQuery( document ).off(\"ajaxError.setupTest\");\n\t\t\t\t\tstart();\n\t\t\t\t}\n\t\t\t},\n\t\t\tfail = function( a, b ) {\n\t\t\t\tok( false, \"Check for timeout failed \" + a + \" \" + b );\n\t\t\t\tstart();\n\t\t\t};\n\n\t\tjQuery( document ).on( \"ajaxError.setupTest\", pass );\n\n\t\tjQuery.ajaxSetup({\n\t\t\ttimeout: 1000\n\t\t});\n\n\t\tjQuery.ajax({\n\t\t\ttype: \"GET\",\n\t\t\turl: url(\"data/name.php?wait=5\"),\n\t\t\terror: pass,\n\t\t\tsuccess: fail\n\t\t});\n\t});\n\n\tasyncTest( \"jQuery.ajaxSetup({ timeout: Number }) with localtimeout\", 1, function() {\n\t\tjQuery.ajaxSetup({\n\t\t\ttimeout: 50\n\t\t});\n\t\tjQuery.ajax({\n\t\t\ttype: \"GET\",\n\t\t\ttimeout: 15000,\n\t\t\turl: url(\"data/name.php?wait=1\"),\n\t\t\terror: function() {\n\t\t\t\tok( false, \"Check for local timeout failed\" );\n\t\t\t\tstart();\n\t\t\t},\n\t\t\tsuccess: function() {\n\t\t\t\tok( true, \"Check for local timeout\" );\n\t\t\t\tstart();\n\t\t\t}\n\t\t});\n\t});\n\n//----------- jQuery.domManip()\n\n\ttest( \"#11264 - jQuery.domManip() - no side effect because of ajaxSetup or global events\", 1, function() {\n\t\tjQuery.ajaxSetup({\n\t\t\ttype: \"POST\"\n\t\t});\n\n\t\tjQuery( document ).on( \"ajaxStart ajaxStop\", function() {\n\t\t\tok( false, \"Global event triggered\" );\n\t\t});\n\n\t\tjQuery(\"#qunit-fixture\").append(\"<script src='data/evalScript.php'></script>\");\n\n\t\tjQuery( document ).off(\"ajaxStart ajaxStop\");\n\t});\n\n\tasyncTest( \"#11402 - jQuery.domManip() - script in comments are properly evaluated\", 2, function() {\n\t\tjQuery(\"#qunit-fixture\").load( \"data/cleanScript.html\", start );\n\t});\n\n//----------- jQuery.get()\n\n\tasyncTest( \"jQuery.get( String, Hash, Function ) - parse xml and use text() on nodes\", 2, function() {\n\t\tjQuery.get( url(\"data/dashboard.xml\"), function( xml ) {\n\t\t\tvar content = [];\n\t\t\tjQuery( \"tab\", xml ).each(function() {\n\t\t\t\tcontent.push( jQuery( this ).text() );\n\t\t\t});\n\t\t\tstrictEqual( content[ 0 ], \"blabla\", \"Check first tab\" );\n\t\t\tstrictEqual( content[ 1 ], \"blublu\", \"Check second tab\" );\n\t\t\tstart();\n\t\t});\n\t});\n\n\tasyncTest( \"#8277 - jQuery.get( String, Function ) - data in ajaxSettings\", 1, function() {\n\t\tjQuery.ajaxSetup({\n\t\t\tdata: \"helloworld\"\n\t\t});\n\t\tjQuery.get( url(\"data/echoQuery.php\"), function( data ) {\n\t\t\tok( /helloworld$/.test( data ), \"Data from ajaxSettings was used\" );\n\t\t\tstart();\n\t\t});\n\t});\n\n//----------- jQuery.getJSON()\n\n\tasyncTest( \"jQuery.getJSON( String, Hash, Function ) - JSON array\", 5, function() {\n\t\tjQuery.getJSON(\n\t\t\turl(\"data/json.php\"),\n\t\t\t{\n\t\t\t\t\"json\": \"array\"\n\t\t\t},\n\t\t\tfunction( json ) {\n\t\t\t\tok( json.length >= 2, \"Check length\" );\n\t\t\t\tstrictEqual( json[ 0 ][\"name\"], \"John\", \"Check JSON: first, name\" );\n\t\t\t\tstrictEqual( json[ 0 ][\"age\"], 21, \"Check JSON: first, age\" );\n\t\t\t\tstrictEqual( json[ 1 ][\"name\"], \"Peter\", \"Check JSON: second, name\" );\n\t\t\t\tstrictEqual( json[ 1 ][\"age\"], 25, \"Check JSON: second, age\" );\n\t\t\t\tstart();\n\t\t\t}\n\t\t);\n\t});\n\n\tasyncTest( \"jQuery.getJSON( String, Function ) - JSON object\", 2, function() {\n\t\tjQuery.getJSON( url(\"data/json.php\"), function( json ) {\n\t\t\tif ( json && json[\"data\"] ) {\n\t\t\t\tstrictEqual( json[\"data\"][\"lang\"], \"en\", \"Check JSON: lang\" );\n\t\t\t\tstrictEqual( json[\"data\"].length, 25, \"Check JSON: length\" );\n\t\t\t\tstart();\n\t\t\t}\n\t\t});\n\t});\n\n\tasyncTest( \"jQuery.getJSON( String, Function ) - JSON object with absolute url to local content\", 2, function() {\n\t\tjQuery.getJSON( url( window.location.href.replace( /[^\\/]*$/, \"\" ) + \"data/json.php\" ), function( json ) {\n\t\t\tstrictEqual( json.data.lang, \"en\", \"Check JSON: lang\" );\n\t\t\tstrictEqual( json.data.length, 25, \"Check JSON: length\" );\n\t\t\tstart();\n\t\t});\n\t});\n\n//----------- jQuery.getScript()\n\n\tasyncTest( \"jQuery.getScript( String, Function ) - with callback\", 2, function() {\n\t\tGlobals.register(\"testBar\");\n\t\tjQuery.getScript( url(\"data/test.js\"), function() {\n\t\t\tstrictEqual( window[\"testBar\"], \"bar\", \"Check if script was evaluated\" );\n\t\t\tstart();\n\t\t});\n\t});\n\n\tasyncTest( \"jQuery.getScript( String, Function ) - no callback\", 1, function() {\n\t\tGlobals.register(\"testBar\");\n\t\tjQuery.getScript( url(\"data/test.js\") ).done( start );\n\t});\n\n\tasyncTest( \"#8082 - jQuery.getScript( String, Function ) - source as responseText\", 2, function() {\n\t\tGlobals.register(\"testBar\");\n\t\tjQuery.getScript( url(\"data/test.js\"), function( data, _, jqXHR ) {\n\t\t\tstrictEqual( data, jqXHR.responseText, \"Same-domain script requests returns the source of the script\" );\n\t\t\tstart();\n\t\t});\n\t});\n\n//----------- jQuery.fn.load()\n\n\t// check if load can be called with only url\n\tasyncTest( \"jQuery.fn.load( String )\", 2, function() {\n\t\tjQuery.ajaxSetup({\n\t\t\tbeforeSend: function() {\n\t\t\t\tstrictEqual( this.type, \"GET\", \"no data means GET request\" );\n\t\t\t}\n\t\t});\n\t\tjQuery(\"#first\").load( \"data/name.html\", start );\n\t});\n\n\tasyncTest( \"jQuery.fn.load() - 404 error callbacks\", 6, function() {\n\t\taddGlobalEvents(\"ajaxStart ajaxStop ajaxSend ajaxComplete ajaxError\")();\n\t\tjQuery( document ).ajaxStop( start );\n\t\tjQuery(\"<div/>\").load( \"data/404.html\", function() {\n\t\t\tok( true, \"complete\" );\n\t\t});\n\t});\n\n\t// check if load can be called with url and null data\n\tasyncTest( \"jQuery.fn.load( String, null )\", 2, function() {\n\t\tjQuery.ajaxSetup({\n\t\t\tbeforeSend: function() {\n\t\t\t\tstrictEqual( this.type, \"GET\", \"no data means GET request\" );\n\t\t\t}\n\t\t});\n\t\tjQuery(\"#first\").load( \"data/name.html\", null, start );\n\t});\n\n\t// check if load can be called with url and undefined data\n\tasyncTest( \"jQuery.fn.load( String, undefined )\", 2, function() {\n\t\tjQuery.ajaxSetup({\n\t\t\tbeforeSend: function() {\n\t\t\t\tstrictEqual( this.type, \"GET\", \"no data means GET request\" );\n\t\t\t}\n\t\t});\n\t\tjQuery(\"#first\").load( \"data/name.html\", undefined, start );\n\t});\n\n\t// check if load can be called with only url\n\tasyncTest( \"jQuery.fn.load( URL_SELECTOR )\", 1, function() {\n\t\tjQuery(\"#first\").load( \"data/test3.html div.user\", function() {\n\t\t\tstrictEqual( jQuery( this ).children(\"div\").length, 2, \"Verify that specific elements were injected\" );\n\t\t\tstart();\n\t\t});\n\t});\n\n\tasyncTest( \"jQuery.fn.load( String, Function ) - simple: inject text into DOM\", 2, function() {\n\t\tjQuery(\"#first\").load( url(\"data/name.html\"), function() {\n\t\t\tok( /^ERROR/.test(jQuery(\"#first\").text()), \"Check if content was injected into the DOM\" );\n\t\t\tstart();\n\t\t});\n\t});\n\n\tasyncTest( \"jQuery.fn.load( String, Function ) - check scripts\", 7, function() {\n\t\tvar verifyEvaluation = function() {\n\t\t\tstrictEqual( window[\"testBar\"], \"bar\", \"Check if script src was evaluated after load\" );\n\t\t\tstrictEqual( jQuery(\"#ap\").html(), \"bar\", \"Check if script evaluation has modified DOM\");\n\t\t\tstart();\n\t\t};\n\n\t\tGlobals.register(\"testFoo\");\n\t\tGlobals.register(\"testBar\");\n\n\t\tjQuery(\"#first\").load( url(\"data/test.html\"), function() {\n\t\t\tok( jQuery(\"#first\").html().match( /^html text/ ), \"Check content after loading html\" );\n\t\t\tstrictEqual( jQuery(\"#foo\").html(), \"foo\", \"Check if script evaluation has modified DOM\" );\n\t\t\tstrictEqual( window[\"testFoo\"], \"foo\", \"Check if script was evaluated after load\" );\n\t\t\tsetTimeout( verifyEvaluation, 600 );\n\t\t});\n\t});\n\n\tasyncTest( \"jQuery.fn.load( String, Function ) - check file with only a script tag\", 3, function() {\n\t\tGlobals.register(\"testFoo\");\n\n\t\tjQuery(\"#first\").load( url(\"data/test2.html\"), function() {\n\t\t\tstrictEqual( jQuery(\"#foo\").html(), \"foo\", \"Check if script evaluation has modified DOM\");\n\t\t\tstrictEqual( window[\"testFoo\"], \"foo\", \"Check if script was evaluated after load\" );\n\t\t\tstart();\n\t\t});\n\t});\n\n\tasyncTest( \"jQuery.fn.load( String, Function ) - dataFilter in ajaxSettings\", 2, function() {\n\t\tjQuery.ajaxSetup({\n\t\t\tdataFilter: function() {\n\t\t\t\treturn \"Hello World\";\n\t\t\t}\n\t\t});\n\t\tjQuery(\"<div/>\").load( url(\"data/name.html\"), function( responseText ) {\n\t\t\tstrictEqual( jQuery( this ).html(), \"Hello World\", \"Test div was filled with filtered data\" );\n\t\t\tstrictEqual( responseText, \"Hello World\", \"Test callback receives filtered data\" );\n\t\t\tstart();\n\t\t});\n\t});\n\n\tasyncTest( \"jQuery.fn.load( String, Object, Function )\", 2, function() {\n\t\tjQuery(\"<div />\").load( url(\"data/params_html.php\"), {\n\t\t\t\"foo\": 3,\n\t\t\t\"bar\": \"ok\"\n\t\t}, function() {\n\t\t\tvar $post = jQuery( this ).find(\"#post\");\n\t\t\tstrictEqual( $post.find(\"#foo\").text(), \"3\", \"Check if a hash of data is passed correctly\" );\n\t\t\tstrictEqual( $post.find(\"#bar\").text(), \"ok\", \"Check if a hash of data is passed correctly\" );\n\t\t\tstart();\n\t\t});\n\t});\n\n\tasyncTest( \"jQuery.fn.load( String, String, Function )\", 2, function() {\n\t\tjQuery(\"<div />\").load( url(\"data/params_html.php\"), \"foo=3&bar=ok\", function() {\n\t\t\tvar $get = jQuery( this ).find(\"#get\");\n\t\t\tstrictEqual( $get.find(\"#foo\").text(), \"3\", \"Check if a string of data is passed correctly\" );\n\t\t\tstrictEqual( $get.find(\"#bar\").text(), \"ok\", \"Check if a   of data is passed correctly\" );\n\t\t\tstart();\n\t\t});\n\t});\n\n\tasyncTest( \"jQuery.fn.load() - callbacks get the correct parameters\", 8, function() {\n\t\tvar completeArgs = {};\n\n\t\tjQuery.ajaxSetup({\n\t\t\tsuccess: function( _, status, jqXHR ) {\n\t\t\t\tcompleteArgs[ this.url ] = [ jqXHR.responseText, status, jqXHR ];\n\t\t\t},\n\t\t\terror: function( jqXHR, status ) {\n\t\t\t\tcompleteArgs[ this.url ] = [ jqXHR.responseText, status, jqXHR ];\n\t\t\t}\n\t\t});\n\n\t\tjQuery.when.apply(\n\t\t\tjQuery,\n\t\t\tjQuery.map([\n\t\t\t\t{\n\t\t\t\t\ttype: \"success\",\n\t\t\t\t\turl: \"data/echoQuery.php?arg=pop\"\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\ttype: \"error\",\n\t\t\t\t\turl: \"data/404.php\"\n\t\t\t\t}\n\t\t\t],\n\t\t\tfunction( options ) {\n\t\t\t\treturn jQuery.Deferred(function( defer ) {\n\t\t\t\t\tjQuery(\"#foo\").load( options.url, function() {\n\t\t\t\t\t\tvar args = arguments;\n\t\t\t\t\t\tstrictEqual( completeArgs[ options.url ].length, args.length, \"same number of arguments (\" + options.type + \")\" );\n\t\t\t\t\t\tjQuery.each( completeArgs[ options.url ], function( i, value ) {\n\t\t\t\t\t\t\tstrictEqual( args[ i ], value, \"argument #\" + i + \" is the same (\" + options.type + \")\" );\n\t\t\t\t\t\t});\n\t\t\t\t\t\tdefer.resolve();\n\t\t\t\t\t});\n\t\t\t\t});\n\t\t\t})\n\t\t).always( start );\n\t});\n\n\tasyncTest( \"#2046 - jQuery.fn.load( String, Function ) with ajaxSetup on dataType json\", 1, function() {\n\t\tjQuery.ajaxSetup({\n\t\t\tdataType: \"json\"\n\t\t});\n\t\tjQuery( document ).ajaxComplete(function( e, xml, s ) {\n\t\t\tstrictEqual( s.dataType, \"html\", \"Verify the load() dataType was html\" );\n\t\t\tjQuery( document ).off(\"ajaxComplete\");\n\t\t\tstart();\n\t\t});\n\t\tjQuery(\"#first\").load(\"data/test3.html\");\n\t});\n\n\tasyncTest( \"#10524 - jQuery.fn.load() - data specified in ajaxSettings is merged in\", 1, function() {\n\t\tvar data = {\n\t\t\t\"baz\": 1\n\t\t};\n\t\tjQuery.ajaxSetup({\n\t\t\tdata: {\n\t\t\t\t\"foo\": \"bar\"\n\t\t\t}\n\t\t});\n\t\tjQuery(\"#foo\").load( \"data/echoQuery.php\", data );\n\t\tjQuery( document ).ajaxComplete(function( event, jqXHR, options ) {\n\t\t\tok( ~options.data.indexOf(\"foo=bar\"), \"Data from ajaxSettings was used\" );\n\t\t\tstart();\n\t\t});\n\t});\n\n//----------- jQuery.post()\n\n\tasyncTest( \"jQuery.post() - data\", 3, function() {\n\t\tjQuery.when(\n\t\t\tjQuery.post(\n\t\t\t\turl(\"data/name.php\"),\n\t\t\t\t{\n\t\t\t\t\txml: \"5-2\",\n\t\t\t\t\tlength: 3\n\t\t\t\t},\n\t\t\t\tfunction( xml ) {\n\t\t\t\t\tjQuery( \"math\", xml ).each(function() {\n\t\t\t\t\t\tstrictEqual( jQuery( \"calculation\", this ).text(), \"5-2\", \"Check for XML\" );\n\t\t\t\t\t\tstrictEqual( jQuery( \"result\", this ).text(), \"3\", \"Check for XML\" );\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t),\n\t\t\tjQuery.ajax({\n\t\t\t\turl: url(\"data/echoData.php\"),\n\t\t\t\ttype: \"POST\",\n\t\t\t\tdata: {\n\t\t\t\t\t\"test\": {\n\t\t\t\t\t\t\"length\": 7,\n\t\t\t\t\t\t\"foo\": \"bar\"\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tsuccess: function( data ) {\n\t\t\t\t\tstrictEqual( data, \"test%5Blength%5D=7&test%5Bfoo%5D=bar\", \"Check if a sub-object with a length param is serialized correctly\" );\n\t\t\t\t}\n\t\t\t})\n\t\t).always( start );\n\t});\n\n\tasyncTest( \"jQuery.post( String, Hash, Function ) - simple with xml\", 4, function() {\n\t\tjQuery.when(\n\t\t\tjQuery.post(\n\t\t\t\turl(\"data/name.php\"),\n\t\t\t\t{\n\t\t\t\t\t\"xml\": \"5-2\"\n\t\t\t\t},\n\t\t\t\tfunction( xml ) {\n\t\t\t\t\tjQuery( \"math\", xml ).each(function() {\n\t\t\t\t\t\tstrictEqual( jQuery( \"calculation\", this ).text(), \"5-2\", \"Check for XML\" );\n\t\t\t\t\t\tstrictEqual( jQuery( \"result\", this ).text(), \"3\", \"Check for XML\" );\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t),\n\t\t\tjQuery.post( url(\"data/name.php?xml=5-2\"), {}, function( xml ) {\n\t\t\t\tjQuery( \"math\", xml ).each(function() {\n\t\t\t\t\tstrictEqual( jQuery( \"calculation\", this ).text(), \"5-2\", \"Check for XML\" );\n\t\t\t\t\tstrictEqual( jQuery( \"result\", this ).text(), \"3\", \"Check for XML\" );\n\t\t\t\t});\n\t\t\t})\n\t\t).always( start );\n\t});\n\n//----------- jQuery.active\n\n\ttest( \"jQuery.active\", 1, function() {\n\t\tok( jQuery.active === 0, \"ajax active counter should be zero: \" + jQuery.active );\n\t});\n\n})();\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/jquery/test/unit/attributes.js",
    "content": "module( \"attributes\", {\n\tteardown: moduleTeardown\n});\n\nfunction bareObj( value ) {\n\treturn value;\n}\n\nfunction functionReturningObj( value ) {\n\treturn function() {\n\t\treturn value;\n\t};\n}\n\n/*\n\t======== local reference =======\n\tbareObj and functionReturningObj can be used to test passing functions to setters\n\tSee testVal below for an example\n\n\tbareObj( value );\n\t\tThis function returns whatever value is passed in\n\n\tfunctionReturningObj( value );\n\t\tReturns a function that returns the value\n*/\n\ntest( \"jQuery.propFix integrity test\", function() {\n\texpect( 1 );\n\n\t//  This must be maintained and equal jQuery.attrFix when appropriate\n\t//  Ensure that accidental or erroneous property\n\t//  overwrites don't occur\n\t//  This is simply for better code coverage and future proofing.\n\tvar props = {\n\t\t\"tabindex\": \"tabIndex\",\n\t\t\"readonly\": \"readOnly\",\n\t\t\"for\": \"htmlFor\",\n\t\t\"class\": \"className\",\n\t\t\"maxlength\": \"maxLength\",\n\t\t\"cellspacing\": \"cellSpacing\",\n\t\t\"cellpadding\": \"cellPadding\",\n\t\t\"rowspan\": \"rowSpan\",\n\t\t\"colspan\": \"colSpan\",\n\t\t\"usemap\": \"useMap\",\n\t\t\"frameborder\": \"frameBorder\",\n\t\t\"contenteditable\": \"contentEditable\"\n\t};\n\n\tdeepEqual( props, jQuery.propFix, \"jQuery.propFix passes integrity check\" );\n});\n\ntest( \"attr(String)\", function() {\n\texpect( 50 );\n\n\tvar extras, body, $body,\n\t\tselect, optgroup, option, $img, styleElem,\n\t\t$button, $form, $a;\n\n\tequal( jQuery(\"#text1\").attr(\"type\"), \"text\", \"Check for type attribute\" );\n\tequal( jQuery(\"#radio1\").attr(\"type\"), \"radio\", \"Check for type attribute\" );\n\tequal( jQuery(\"#check1\").attr(\"type\"), \"checkbox\", \"Check for type attribute\" );\n\tequal( jQuery(\"#simon1\").attr(\"rel\"), \"bookmark\", \"Check for rel attribute\" );\n\tequal( jQuery(\"#google\").attr(\"title\"), \"Google!\", \"Check for title attribute\" );\n\tequal( jQuery(\"#mark\").attr(\"hreflang\"), \"en\", \"Check for hreflang attribute\" );\n\tequal( jQuery(\"#en\").attr(\"lang\"), \"en\", \"Check for lang attribute\" );\n\tequal( jQuery(\"#simon\").attr(\"class\"), \"blog link\", \"Check for class attribute\" );\n\tequal( jQuery(\"#name\").attr(\"name\"), \"name\", \"Check for name attribute\" );\n\tequal( jQuery(\"#text1\").attr(\"name\"), \"action\", \"Check for name attribute\" );\n\tok( jQuery(\"#form\").attr(\"action\").indexOf(\"formaction\") >= 0, \"Check for action attribute\" );\n\tequal( jQuery(\"#text1\").attr(\"value\", \"t\").attr(\"value\"), \"t\", \"Check setting the value attribute\" );\n\tequal( jQuery(\"#text1\").attr(\"value\", \"\").attr(\"value\"), \"\", \"Check setting the value attribute to empty string\" );\n\tequal( jQuery(\"<div value='t'></div>\").attr(\"value\"), \"t\", \"Check setting custom attr named 'value' on a div\" );\n\tequal( jQuery(\"#form\").attr(\"blah\", \"blah\").attr(\"blah\"), \"blah\", \"Set non-existent attribute on a form\" );\n\tequal( jQuery(\"#foo\").attr(\"height\"), undefined, \"Non existent height attribute should return undefined\" );\n\n\t// [7472] & [3113] (form contains an input with name=\"action\" or name=\"id\")\n\textras = jQuery(\"<input id='id' name='id' /><input id='name' name='name' /><input id='target' name='target' />\").appendTo(\"#testForm\");\n\tequal( jQuery(\"#form\").attr(\"action\",\"newformaction\").attr(\"action\"), \"newformaction\", \"Check that action attribute was changed\" );\n\tequal( jQuery(\"#testForm\").attr(\"target\"), undefined, \"Retrieving target does not equal the input with name=target\" );\n\tequal( jQuery(\"#testForm\").attr(\"target\", \"newTarget\").attr(\"target\"), \"newTarget\", \"Set target successfully on a form\" );\n\tequal( jQuery(\"#testForm\").removeAttr(\"id\").attr(\"id\"), undefined, \"Retrieving id does not equal the input with name=id after id is removed [#7472]\" );\n\t// Bug #3685 (form contains input with name=\"name\")\n\tequal( jQuery(\"#testForm\").attr(\"name\"), undefined, \"Retrieving name does not retrieve input with name=name\" );\n\textras.remove();\n\n\tequal( jQuery(\"#text1\").attr(\"maxlength\"), \"30\", \"Check for maxlength attribute\" );\n\tequal( jQuery(\"#text1\").attr(\"maxLength\"), \"30\", \"Check for maxLength attribute\" );\n\tequal( jQuery(\"#area1\").attr(\"maxLength\"), \"30\", \"Check for maxLength attribute\" );\n\n\t// using innerHTML in IE causes href attribute to be serialized to the full path\n\tjQuery(\"<a/>\").attr({\n\t\t\"id\": \"tAnchor5\",\n\t\t\"href\": \"#5\"\n\t}).appendTo(\"#qunit-fixture\");\n\tequal( jQuery(\"#tAnchor5\").attr(\"href\"), \"#5\", \"Check for non-absolute href (an anchor)\" );\n\tjQuery(\"<a id='tAnchor6' href='#5' />\").appendTo(\"#qunit-fixture\");\n\tequal( jQuery(\"#tAnchor5\").prop(\"href\"), jQuery(\"#tAnchor6\").prop(\"href\"), \"Check for absolute href prop on an anchor\" );\n\n\t$(\"<script type='jquery/test' src='#5' id='scriptSrc'></script>\").appendTo(\"#qunit-fixture\");\n\tequal( jQuery(\"#tAnchor5\").prop(\"href\"), jQuery(\"#scriptSrc\").prop(\"src\"), \"Check for absolute src prop on a script\" );\n\n\t// list attribute is readonly by default in browsers that support it\n\tjQuery(\"#list-test\").attr( \"list\", \"datalist\" );\n\tequal( jQuery(\"#list-test\").attr(\"list\"), \"datalist\", \"Check setting list attribute\" );\n\n\t// Related to [5574] and [5683]\n\tbody = document.body;\n\t$body = jQuery( body );\n\n\tstrictEqual( $body.attr(\"foo\"), undefined, \"Make sure that a non existent attribute returns undefined\" );\n\n\tbody.setAttribute( \"foo\", \"baz\" );\n\tequal( $body.attr(\"foo\"), \"baz\", \"Make sure the dom attribute is retrieved when no expando is found\" );\n\n\t$body.attr( \"foo\",\"cool\" );\n\tequal( $body.attr(\"foo\"), \"cool\", \"Make sure that setting works well when both expando and dom attribute are available\" );\n\n\tbody.removeAttribute(\"foo\"); // Cleanup\n\n\tselect = document.createElement(\"select\");\n\toptgroup = document.createElement(\"optgroup\");\n\toption = document.createElement(\"option\");\n\n\toptgroup.appendChild( option );\n\tselect.appendChild( optgroup );\n\n\tequal( jQuery( option ).prop(\"selected\"), true, \"Make sure that a single option is selected, even when in an optgroup.\" );\n\n\t$img = jQuery(\"<img style='display:none' width='215' height='53' src='data/1x1.jpg'/>\").appendTo(\"body\");\n\tequal( $img.attr(\"width\"), \"215\", \"Retrieve width attribute an an element with display:none.\" );\n\tequal( $img.attr(\"height\"), \"53\", \"Retrieve height attribute an an element with display:none.\" );\n\n\t// Check for style support\n\tstyleElem = jQuery(\"<div/>\").appendTo(\"#qunit-fixture\").css({\n\t\tbackground: \"url(UPPERlower.gif)\"\n\t});\n\tok( !!~styleElem.attr(\"style\").indexOf(\"UPPERlower.gif\"), \"Check style attribute getter\" );\n\tok( !!~styleElem.attr(\"style\", \"position:absolute;\").attr(\"style\").indexOf(\"absolute\"), \"Check style setter\" );\n\n\t// Check value on button element (#1954)\n\t$button = jQuery(\"<button>text</button>\").insertAfter(\"#button\");\n\tstrictEqual( $button.attr(\"value\"), undefined, \"Absence of value attribute on a button\" );\n\tequal( $button.attr( \"value\", \"foobar\" ).attr(\"value\"), \"foobar\", \"Value attribute on a button does not return innerHTML\" );\n\tequal( $button.attr(\"value\", \"baz\").html(), \"text\", \"Setting the value attribute does not change innerHTML\" );\n\n\t// Attributes with a colon on a table element (#1591)\n\tequal( jQuery(\"#table\").attr(\"test:attrib\"), undefined, \"Retrieving a non-existent attribute on a table with a colon does not throw an error.\" );\n\tequal( jQuery(\"#table\").attr( \"test:attrib\", \"foobar\" ).attr(\"test:attrib\"), \"foobar\", \"Setting an attribute on a table with a colon does not throw an error.\" );\n\n\t$form = jQuery(\"<form class='something'></form>\").appendTo(\"#qunit-fixture\");\n\tequal( $form.attr(\"class\"), \"something\", \"Retrieve the class attribute on a form.\" );\n\n\t$a = jQuery(\"<a href='#' onclick='something()'>Click</a>\").appendTo(\"#qunit-fixture\");\n\tequal( $a.attr(\"onclick\"), \"something()\", \"Retrieve ^on attribute without anonymous function wrapper.\" );\n\n\tok( jQuery(\"<div/>\").attr(\"doesntexist\") === undefined, \"Make sure undefined is returned when no attribute is found.\" );\n\tok( jQuery(\"<div/>\").attr(\"title\") === undefined, \"Make sure undefined is returned when no attribute is found.\" );\n\tequal( jQuery(\"<div/>\").attr( \"title\", \"something\" ).attr(\"title\"), \"something\", \"Set the title attribute.\" );\n\tok( jQuery().attr(\"doesntexist\") === undefined, \"Make sure undefined is returned when no element is there.\" );\n\tequal( jQuery(\"<div/>\").attr(\"value\"), undefined, \"An unset value on a div returns undefined.\" );\n\tstrictEqual( jQuery(\"<select><option value='property'></option></select>\").attr(\"value\"), undefined, \"An unset value on a select returns undefined.\" );\n\n\t$form = jQuery(\"#form\").attr( \"enctype\", \"multipart/form-data\" );\n\tequal( $form.prop(\"enctype\"), \"multipart/form-data\", \"Set the enctype of a form (encoding in IE6/7 #6743)\" );\n\n});\n\ntest( \"attr(String) on cloned elements, #9646\", function() {\n\texpect( 4 );\n\n\tvar div,\n\t\tinput = jQuery(\"<input name='tester' />\");\n\n\tinput.attr(\"name\");\n\n\tstrictEqual( input.clone( true ).attr( \"name\", \"test\" )[ 0 ].name, \"test\", \"Name attribute should be changed on cloned element\" );\n\n\tdiv = jQuery(\"<div id='tester' />\");\n\tdiv.attr(\"id\");\n\n\tstrictEqual( div.clone( true ).attr( \"id\", \"test\" )[ 0 ].id, \"test\", \"Id attribute should be changed on cloned element\" );\n\n\tinput = jQuery(\"<input value='tester' />\");\n\tinput.attr(\"value\");\n\n\tstrictEqual( input.clone( true ).attr( \"value\", \"test\" )[ 0 ].value, \"test\", \"Value attribute should be changed on cloned element\" );\n\n\tstrictEqual( input.clone( true ).attr( \"value\", 42 )[ 0 ].value, \"42\", \"Value attribute should be changed on cloned element\" );\n});\n\ntest( \"attr(String) in XML Files\", function() {\n\texpect( 3 );\n\tvar xml = createDashboardXML();\n\tequal( jQuery( \"locations\", xml ).attr(\"class\"), \"foo\", \"Check class attribute in XML document\" );\n\tequal( jQuery( \"location\", xml ).attr(\"for\"), \"bar\", \"Check for attribute in XML document\" );\n\tequal( jQuery( \"location\", xml ).attr(\"checked\"), \"different\", \"Check that hooks are not attached in XML document\" );\n});\n\ntest( \"attr(String, Function)\", function() {\n\texpect( 2 );\n\n\tequal(\n\t\tjQuery(\"#text1\").attr( \"value\", function() {\n\t\t\treturn this.id;\n\t\t}).attr(\"value\"),\n\t\t\"text1\",\n\t\t\"Set value from id\"\n\t);\n\n\tequal(\n\t\tjQuery(\"#text1\").attr( \"title\", function(i) {\n\t\t\treturn i;\n\t\t}).attr(\"title\"),\n\t\t\"0\",\n\t\t\"Set value with an index\"\n\t);\n});\n\ntest( \"attr(Hash)\", function() {\n\texpect( 3 );\n\tvar pass = true;\n\tjQuery(\"div\").attr({\n\t\t\"foo\": \"baz\",\n\t\t\"zoo\": \"ping\"\n\t}).each(function() {\n\t\tif ( this.getAttribute(\"foo\") !== \"baz\" && this.getAttribute(\"zoo\") !== \"ping\" ) {\n\t\t\tpass = false;\n\t\t}\n\t});\n\n\tok( pass, \"Set Multiple Attributes\" );\n\n\tequal(\n\t\tjQuery(\"#text1\").attr({\n\t\t\t\"value\": function() {\n\t\t\t\treturn this[\"id\"];\n\t\t\t}}).attr(\"value\"),\n\t\t\"text1\",\n\t\t\"Set attribute to computed value #1\"\n\t);\n\n\tequal(\n\t\tjQuery(\"#text1\").attr({\n\t\t\t\"title\": function(i) {\n\t\t\t\treturn i;\n\t\t\t}\n\t\t}).attr(\"title\"),\n\t\t\"0\",\n\t\t\"Set attribute to computed value #2\"\n\t);\n});\n\ntest( \"attr(String, Object)\", function() {\n\texpect( 71 );\n\n\tvar $input, $text, $details,\n\t\tattributeNode, commentNode, textNode, obj,\n\t\ttable, td, j, type,\n\t\tcheck, thrown, button, $radio, $radios, $svg,\n\t\tdiv = jQuery(\"div\").attr(\"foo\", \"bar\"),\n\t\ti = 0,\n\t\tfail = false;\n\n\tfor ( ; i < div.length; i++ ) {\n\t\tif ( div[ i ].getAttribute(\"foo\") !== \"bar\" ) {\n\t\t\tfail = i;\n\t\t\tbreak;\n\t\t}\n\t}\n\n\tequal( fail, false, \"Set Attribute, the #\" + fail + \" element didn't get the attribute 'foo'\" );\n\n\tok(\n\t\tjQuery(\"#foo\").attr({\n\t\t\t\"width\": null\n\t\t}),\n\t\t\"Try to set an attribute to nothing\"\n\t);\n\n\tjQuery(\"#name\").attr( \"name\", \"something\" );\n\tequal( jQuery(\"#name\").attr(\"name\"), \"something\", \"Set name attribute\" );\n\tjQuery(\"#name\").attr( \"name\", null );\n\tequal( jQuery(\"#name\").attr(\"name\"), undefined, \"Remove name attribute\" );\n\n\t$input = jQuery( \"<input>\", {\n\t\tname: \"something\",\n\t\tid: \"specified\"\n\t});\n\tequal( $input.attr(\"name\"), \"something\", \"Check element creation gets/sets the name attribute.\" );\n\tequal( $input.attr(\"id\"), \"specified\", \"Check element creation gets/sets the id attribute.\" );\n\n\t// As of fixing #11115, we only guarantee boolean property update for checked and selected\n\t$input = jQuery(\"<input type='checkbox'/>\").attr( \"checked\", true );\n\tequal( $input.prop(\"checked\"), true, \"Setting checked updates property (verified by .prop)\" );\n\tequal( $input[0].checked, true, \"Setting checked updates property (verified by native property)\" );\n\t$input = jQuery(\"<option/>\").attr( \"selected\", true );\n\tequal( $input.prop(\"selected\"), true, \"Setting selected updates property (verified by .prop)\" );\n\tequal( $input[0].selected, true, \"Setting selected updates property (verified by native property)\" );\n\n\t$input = jQuery(\"#check2\");\n\t$input.prop( \"checked\", true ).prop( \"checked\", false ).attr( \"checked\", true );\n\tequal( $input.attr(\"checked\"), \"checked\", \"Set checked (verified by .attr)\" );\n\t$input.prop( \"checked\", false ).prop( \"checked\", true ).attr( \"checked\", false );\n\tequal( $input.attr(\"checked\"), undefined, \"Remove checked (verified by .attr)\" );\n\n\t$input = jQuery(\"#text1\").prop( \"readOnly\", true ).prop( \"readOnly\", false ).attr( \"readonly\", true );\n\tequal( $input.attr(\"readonly\"), \"readonly\", \"Set readonly (verified by .attr)\" );\n\t$input.prop( \"readOnly\", false ).prop( \"readOnly\", true ).attr( \"readonly\", false );\n\tequal( $input.attr(\"readonly\"), undefined, \"Remove readonly (verified by .attr)\" );\n\n\t$input = jQuery(\"#check2\").attr( \"checked\", true ).attr( \"checked\", false ).prop( \"checked\", true );\n\tequal( $input[0].checked, true, \"Set checked property (verified by native property)\" );\n\tequal( $input.prop(\"checked\"), true, \"Set checked property (verified by .prop)\" );\n\tequal( $input.attr(\"checked\"), undefined, \"Setting checked property doesn't affect checked attribute\" );\n\t$input.attr( \"checked\", false ).attr( \"checked\", true ).prop( \"checked\", false );\n\tequal( $input[0].checked, false, \"Clear checked property (verified by native property)\" );\n\tequal( $input.prop(\"checked\"), false, \"Clear checked property (verified by .prop)\" );\n\tequal( $input.attr(\"checked\"), \"checked\", \"Clearing checked property doesn't affect checked attribute\" );\n\n\t$input = jQuery(\"#check2\").attr( \"checked\", false ).attr( \"checked\", \"checked\" );\n\tequal( $input.attr(\"checked\"), \"checked\", \"Set checked to 'checked' (verified by .attr)\" );\n\n\t$radios = jQuery(\"#checkedtest\").find(\"input[type='radio']\");\n\t$radios.eq( 1 ).trigger(\"click\");\n\tequal( $radios.eq( 1 ).prop(\"checked\"), true, \"Second radio was checked when clicked\" );\n\tequal( $radios.eq( 0 ).attr(\"checked\"), \"checked\", \"First radio is still [checked]\" );\n\n\t$input = jQuery(\"#text1\").attr( \"readonly\", false ).prop( \"readOnly\", true );\n\tequal( $input[0].readOnly, true, \"Set readonly property (verified by native property)\" );\n\tequal( $input.prop(\"readOnly\"), true, \"Set readonly property (verified by .prop)\" );\n\t$input.attr( \"readonly\", true ).prop( \"readOnly\", false );\n\tequal( $input[0].readOnly, false, \"Clear readonly property (verified by native property)\" );\n\tequal( $input.prop(\"readOnly\"), false, \"Clear readonly property (verified by .prop)\" );\n\n\t$input = jQuery(\"#name\").attr( \"maxlength\", \"5\" );\n\tequal( $input[0].maxLength, 5, \"Set maxlength (verified by native property)\" );\n\t$input.attr( \"maxLength\", \"10\" );\n\tequal( $input[0].maxLength, 10, \"Set maxlength (verified by native property)\" );\n\n\t// HTML5 boolean attributes\n\t$text = jQuery(\"#text1\").attr({\n\t\t\"autofocus\": true,\n\t\t\"required\": true\n\t});\n\tequal( $text.attr(\"autofocus\"), \"autofocus\", \"Reading autofocus attribute yields 'autofocus'\" );\n\tequal( $text.attr( \"autofocus\", false ).attr(\"autofocus\"), undefined, \"Setting autofocus to false removes it\" );\n\tequal( $text.attr(\"required\"), \"required\", \"Reading required attribute yields 'required'\" );\n\tequal( $text.attr( \"required\", false ).attr(\"required\"), undefined, \"Setting required attribute to false removes it\" );\n\n\t$details = jQuery(\"<details open></details>\").appendTo(\"#qunit-fixture\");\n\tequal( $details.attr(\"open\"), \"open\", \"open attribute presence indicates true\" );\n\tequal( $details.attr( \"open\", false ).attr(\"open\"), undefined, \"Setting open attribute to false removes it\" );\n\n\t$text.attr( \"data-something\", true );\n\tequal( $text.attr(\"data-something\"), \"true\", \"Set data attributes\");\n\tequal( $text.data(\"something\"), true, \"Setting data attributes are not affected by boolean settings\");\n\t$text.attr( \"data-another\", false );\n\tequal( $text.attr(\"data-another\"), \"false\", \"Set data attributes\");\n\tequal( $text.data(\"another\"), false, \"Setting data attributes are not affected by boolean settings\" );\n\tequal( $text.attr( \"aria-disabled\", false ).attr(\"aria-disabled\"), \"false\", \"Setting aria attributes are not affected by boolean settings\" );\n\t$text.removeData(\"something\").removeData(\"another\").removeAttr(\"aria-disabled\");\n\n\tjQuery(\"#foo\").attr(\"contenteditable\", true);\n\tequal( jQuery(\"#foo\").attr(\"contenteditable\"), \"true\", \"Enumerated attributes are set properly\" );\n\n\tattributeNode = document.createAttribute(\"irrelevant\");\n\tcommentNode = document.createComment(\"some comment\");\n\ttextNode = document.createTextNode(\"some text\");\n\tobj = {};\n\n\tjQuery.each( [ commentNode, textNode, attributeNode ], function( i, elem ) {\n\t\tvar $elem = jQuery( elem );\n\t\t$elem.attr( \"nonexisting\", \"foo\" );\n\t\tstrictEqual( $elem.attr(\"nonexisting\"), undefined, \"attr(name, value) works correctly on comment and text nodes (bug #7500).\" );\n\t});\n\n\t// Register the property name to avoid generating a new global when testing window\n\tGlobals.register(\"nonexisting\");\n\tjQuery.each( [ window, document, obj, \"#firstp\" ], function( i, elem ) {\n\t\tvar oldVal = elem.nonexisting,\n\t\t\t$elem = jQuery( elem );\n\t\tstrictEqual( $elem.attr(\"nonexisting\"), undefined, \"attr works correctly for non existing attributes (bug #7500).\" );\n\t\tequal( $elem.attr( \"nonexisting\", \"foo\" ).attr(\"nonexisting\"), \"foo\", \"attr falls back to prop on unsupported arguments\" );\n\t\telem.nonexisting = oldVal;\n\t});\n\n\ttable = jQuery(\"#table\").append(\"<tr><td>cell</td></tr><tr><td>cell</td><td>cell</td></tr><tr><td>cell</td><td>cell</td></tr>\");\n\ttd = table.find(\"td\").eq(0);\n\ttd.attr( \"rowspan\", \"2\" );\n\tequal( td[ 0 ][\"rowSpan\"], 2, \"Check rowspan is correctly set\" );\n\ttd.attr( \"colspan\", \"2\" );\n\tequal( td[ 0 ][\"colSpan\"], 2, \"Check colspan is correctly set\" );\n\ttable.attr(\"cellspacing\", \"2\");\n\tequal( table[ 0 ][\"cellSpacing\"], \"2\", \"Check cellspacing is correctly set\" );\n\n\tequal( jQuery(\"#area1\").attr(\"value\"), undefined, \"Value attribute is distinct from value property.\" );\n\n\t// for #1070\n\tjQuery(\"#name\").attr( \"someAttr\", \"0\" );\n\tequal( jQuery(\"#name\").attr(\"someAttr\"), \"0\", \"Set attribute to a string of '0'\" );\n\tjQuery(\"#name\").attr( \"someAttr\", 0 );\n\tequal( jQuery(\"#name\").attr(\"someAttr\"), \"0\", \"Set attribute to the number 0\" );\n\tjQuery(\"#name\").attr( \"someAttr\", 1 );\n\tequal( jQuery(\"#name\").attr(\"someAttr\"), \"1\", \"Set attribute to the number 1\" );\n\n\t// using contents will get comments regular, text, and comment nodes\n\tj = jQuery(\"#nonnodes\").contents();\n\n\tj.attr( \"name\", \"attrvalue\" );\n\tequal( j.attr(\"name\"), \"attrvalue\", \"Check node,textnode,comment for attr\" );\n\tj.removeAttr(\"name\");\n\n\t// Type\n\ttype = jQuery(\"#check2\").attr(\"type\");\n\ttry {\n\t\tjQuery(\"#check2\").attr( \"type\", \"hidden\" );\n\t\tok( true, \"No exception thrown on input type change\" );\n\t} catch( e ) {\n\t\tok( true, \"Exception thrown on input type change: \" + e );\n\t}\n\n\tcheck = document.createElement(\"input\");\n\tthrown = true;\n\ttry {\n\t\tjQuery( check ).attr( \"type\", \"checkbox\" );\n\t} catch( e ) {\n\t\tthrown = false;\n\t}\n\tok( thrown, \"Exception thrown when trying to change type property\" );\n\tequal( \"checkbox\", jQuery( check ).attr(\"type\"), \"Verify that you can change the type of an input element that isn't in the DOM\" );\n\n\tcheck = jQuery(\"<input />\");\n\tthrown = true;\n\ttry {\n\t\tcheck.attr( \"type\", \"checkbox\" );\n\t} catch( e ) {\n\t\tthrown = false;\n\t}\n\tok( thrown, \"Exception thrown when trying to change type property\" );\n\tequal( \"checkbox\", check.attr(\"type\"), \"Verify that you can change the type of an input element that isn't in the DOM\" );\n\n\tbutton = jQuery(\"#button\");\n\ttry {\n\t\tbutton.attr( \"type\", \"submit\" );\n\t\tok( true, \"No exception thrown on button type change\" );\n\t} catch( e ) {\n\t\tok( true, \"Exception thrown on button type change: \" + e );\n\t}\n\n\t$radio = jQuery( \"<input>\", {\n\t\t\"value\": \"sup\",\n\t\t\"type\": \"radio\"\n\t}).appendTo(\"#testForm\");\n\tequal( $radio.val(), \"sup\", \"Value is not reset when type is set after value on a radio\" );\n\n\t// Setting attributes on svg elements (bug #3116)\n\t$svg = jQuery(\n\t\t\"<svg xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' version='1.1' baseProfile='full' width='200' height='200'>\" +\n\n\t\t\t\"<circle cx='200' cy='200' r='150' />\" +\n\t\t\t\"</svg>\"\n\t\t).appendTo(\"body\");\n\tequal( $svg.attr( \"cx\", 100 ).attr(\"cx\"), \"100\", \"Set attribute on svg element\" );\n\t$svg.remove();\n\n\t// undefined values are chainable\n\tjQuery(\"#name\").attr( \"maxlength\", \"5\" ).removeAttr(\"nonexisting\");\n\tequal( typeof jQuery(\"#name\").attr( \"maxlength\", undefined ), \"object\", \".attr('attribute', undefined) is chainable (#5571)\" );\n\tequal( jQuery(\"#name\").attr( \"maxlength\", undefined ).attr(\"maxlength\"), \"5\", \".attr('attribute', undefined) does not change value (#5571)\" );\n\tequal( jQuery(\"#name\").attr( \"nonexisting\", undefined ).attr(\"nonexisting\"), undefined, \".attr('attribute', undefined) does not create attribute (#5571)\" );\n});\n\ntest( \"attr(String, Object) - Loaded via XML document\", function() {\n\texpect( 2 );\n\tvar xml = createDashboardXML(),\n\t\ttitles = [];\n\tjQuery( \"tab\", xml ).each(function() {\n\t\ttitles.push( jQuery( this ).attr(\"title\") );\n\t});\n\tequal( titles[ 0 ], \"Location\", \"attr() in XML context: Check first title\" );\n\tequal( titles[ 1 ], \"Users\", \"attr() in XML context: Check second title\" );\n});\n\ntest( \"attr(String, Object) - Loaded via XML fragment\", function() {\n\texpect( 2 );\n\tvar frag = createXMLFragment(),\n\t\t$frag = jQuery( frag );\n\n\t$frag.attr( \"test\", \"some value\" );\n\tequal( $frag.attr(\"test\"), \"some value\", \"set attribute\" );\n\t$frag.attr( \"test\", null );\n\tequal( $frag.attr(\"test\"), undefined, \"remove attribute\" );\n});\n\ntest( \"attr('tabindex')\", function() {\n\texpect( 8 );\n\n\t// elements not natively tabbable\n\tequal( jQuery(\"#listWithTabIndex\").attr(\"tabindex\"), \"5\", \"not natively tabbable, with tabindex set to 0\" );\n\tequal( jQuery(\"#divWithNoTabIndex\").attr(\"tabindex\"), undefined, \"not natively tabbable, no tabindex set\" );\n\n\t// anchor with href\n\tequal( jQuery(\"#linkWithNoTabIndex\").attr(\"tabindex\"), undefined, \"anchor with href, no tabindex set\" );\n\tequal( jQuery(\"#linkWithTabIndex\").attr(\"tabindex\"), \"2\", \"anchor with href, tabindex set to 2\" );\n\tequal( jQuery(\"#linkWithNegativeTabIndex\").attr(\"tabindex\"), \"-1\", \"anchor with href, tabindex set to -1\" );\n\n\t// anchor without href\n\tequal( jQuery(\"#linkWithNoHrefWithNoTabIndex\").attr(\"tabindex\"), undefined, \"anchor without href, no tabindex set\" );\n\tequal( jQuery(\"#linkWithNoHrefWithTabIndex\").attr(\"tabindex\"), \"1\", \"anchor without href, tabindex set to 2\" );\n\tequal( jQuery(\"#linkWithNoHrefWithNegativeTabIndex\").attr(\"tabindex\"), \"-1\", \"anchor without href, no tabindex set\" );\n});\n\ntest( \"attr('tabindex', value)\", function() {\n\texpect( 9 );\n\n\tvar element = jQuery(\"#divWithNoTabIndex\");\n\tequal( element.attr(\"tabindex\"), undefined, \"start with no tabindex\" );\n\n\t// set a positive string\n\telement.attr( \"tabindex\", \"1\" );\n\tequal( element.attr(\"tabindex\"), \"1\", \"set tabindex to 1 (string)\" );\n\n\t// set a zero string\n\telement.attr( \"tabindex\", \"0\" );\n\tequal( element.attr(\"tabindex\"), \"0\", \"set tabindex to 0 (string)\" );\n\n\t// set a negative string\n\telement.attr( \"tabindex\", \"-1\" );\n\tequal( element.attr(\"tabindex\"), \"-1\", \"set tabindex to -1 (string)\" );\n\n\t// set a positive number\n\telement.attr( \"tabindex\", 1 );\n\tequal( element.attr(\"tabindex\"), \"1\", \"set tabindex to 1 (number)\" );\n\n\t// set a zero number\n\telement.attr( \"tabindex\", 0 );\n\tequal(element.attr(\"tabindex\"), \"0\", \"set tabindex to 0 (number)\");\n\n\t// set a negative number\n\telement.attr( \"tabindex\", -1 );\n\tequal( element.attr(\"tabindex\"), \"-1\", \"set tabindex to -1 (number)\" );\n\n\telement = jQuery(\"#linkWithTabIndex\");\n\tequal( element.attr(\"tabindex\"), \"2\", \"start with tabindex 2\" );\n\n\telement.attr( \"tabindex\", -1 );\n\tequal( element.attr(\"tabindex\"), \"-1\", \"set negative tabindex\" );\n});\n\ntest( \"removeAttr(String)\", function() {\n\texpect( 12 );\n\tvar $first;\n\n\tequal( jQuery(\"#mark\").removeAttr(\"class\").attr(\"class\"), undefined, \"remove class\" );\n\tequal( jQuery(\"#form\").removeAttr(\"id\").attr(\"id\"), undefined, \"Remove id\" );\n\tequal( jQuery(\"#foo\").attr( \"style\", \"position:absolute;\" ).removeAttr(\"style\").attr(\"style\"), undefined, \"Check removing style attribute\" );\n\tequal( jQuery(\"#form\").attr( \"style\", \"position:absolute;\" ).removeAttr(\"style\").attr(\"style\"), undefined, \"Check removing style attribute on a form\" );\n\tequal( jQuery(\"<div style='position: absolute'></div>\").appendTo(\"#foo\").removeAttr(\"style\").prop(\"style\").cssText, \"\", \"Check removing style attribute (#9699 Webkit)\" );\n\tequal( jQuery(\"#fx-test-group\").attr( \"height\", \"3px\" ).removeAttr(\"height\").get( 0 ).style.height, \"1px\", \"Removing height attribute has no effect on height set with style attribute\" );\n\n\tjQuery(\"#check1\").removeAttr(\"checked\").prop( \"checked\", true ).removeAttr(\"checked\");\n\tequal( document.getElementById(\"check1\").checked, false, \"removeAttr sets boolean properties to false\" );\n\tjQuery(\"#text1\").prop( \"readOnly\", true ).removeAttr(\"readonly\");\n\tequal( document.getElementById(\"text1\").readOnly, false, \"removeAttr sets boolean properties to false\" );\n\n\tjQuery(\"#option2c\").removeAttr(\"selected\");\n\tequal( jQuery(\"#option2d\").attr(\"selected\"), \"selected\", \"Removing `selected` from an option that is not selected does not remove selected from the currently selected option (#10870)\" );\n\n\ttry {\n\t\t$first = jQuery(\"#first\").attr( \"contenteditable\", \"true\" ).removeAttr(\"contenteditable\");\n\t\tequal( $first.attr(\"contenteditable\"), undefined, \"Remove the contenteditable attribute\" );\n\t} catch( e ) {\n\t\tok( false, \"Removing contenteditable threw an error (#10429)\" );\n\t}\n\n\t$first = jQuery(\"<div Case='mixed'></div>\");\n\tequal( $first.attr(\"Case\"), \"mixed\", \"case of attribute doesn't matter\" );\n\t$first.removeAttr(\"Case\");\n\t// IE 6/7 return empty string here, not undefined\n\tok( !$first.attr(\"Case\"), \"mixed-case attribute was removed\" );\n});\n\ntest( \"removeAttr(String) in XML\", function() {\n\texpect( 7 );\n\tvar xml = createDashboardXML(),\n\t\tiwt = jQuery( \"infowindowtab\", xml );\n\n\tequal( iwt.attr(\"normal\"), \"ab\", \"Check initial value\" );\n\tiwt.removeAttr(\"Normal\");\n\tequal( iwt.attr(\"normal\"), \"ab\", \"Should still be there\" );\n\tiwt.removeAttr(\"normal\");\n\tequal( iwt.attr(\"normal\"), undefined, \"Removed\" );\n\n\tequal( iwt.attr(\"mixedCase\"), \"yes\", \"Check initial value\" );\n\tequal( iwt.attr(\"mixedcase\"), undefined, \"toLowerCase not work good\" );\n\tiwt.removeAttr(\"mixedcase\");\n\tequal( iwt.attr(\"mixedCase\"), \"yes\", \"Should still be there\" );\n\tiwt.removeAttr(\"mixedCase\");\n\tequal( iwt.attr(\"mixedCase\"), undefined, \"Removed\" );\n});\n\ntest( \"removeAttr(Multi String, variable space width)\", function() {\n\texpect( 8 );\n\n\tvar div = jQuery(\"<div id='a' alt='b' title='c' rel='d'></div>\"),\n\t\ttests = {\n\t\t\tid: \"a\",\n\t\t\talt: \"b\",\n\t\t\ttitle: \"c\",\n\t\t\trel: \"d\"\n\t\t};\n\n\tjQuery.each( tests, function( key, val ) {\n\t\tequal( div.attr( key ), val, \"Attribute `\" + key + \"` exists, and has a value of `\" + val + \"`\" );\n\t});\n\n\tdiv.removeAttr( \"id   alt title  rel  \" );\n\n\tjQuery.each( tests, function( key ) {\n\t\tequal( div.attr( key ), undefined, \"Attribute `\" + key + \"` was removed\" );\n\t});\n});\n\ntest( \"prop(String, Object)\", function() {\n\texpect( 31 );\n\n\tequal( jQuery(\"#text1\").prop(\"value\"), \"Test\", \"Check for value attribute\" );\n\tequal( jQuery(\"#text1\").prop( \"value\", \"Test2\" ).prop(\"defaultValue\"), \"Test\", \"Check for defaultValue attribute\" );\n\tequal( jQuery(\"#select2\").prop(\"selectedIndex\"), 3, \"Check for selectedIndex attribute\" );\n\tequal( jQuery(\"#foo\").prop(\"nodeName\").toUpperCase(), \"DIV\", \"Check for nodeName attribute\" );\n\tequal( jQuery(\"#foo\").prop(\"tagName\").toUpperCase(), \"DIV\", \"Check for tagName attribute\" );\n\tequal( jQuery(\"<option/>\").prop(\"selected\"), false, \"Check selected attribute on disconnected element.\" );\n\n\tequal( jQuery(\"#listWithTabIndex\").prop(\"tabindex\"), 5, \"Check retrieving tabindex\" );\n\tjQuery(\"#text1\").prop( \"readonly\", true );\n\tequal( document.getElementById(\"text1\").readOnly, true, \"Check setting readOnly property with 'readonly'\" );\n\tequal( jQuery(\"#label-for\").prop(\"for\"), \"action\", \"Check retrieving htmlFor\" );\n\tjQuery(\"#text1\").prop(\"class\", \"test\");\n\tequal( document.getElementById(\"text1\").className, \"test\", \"Check setting className with 'class'\" );\n\tequal( jQuery(\"#text1\").prop(\"maxlength\"), 30, \"Check retrieving maxLength\" );\n\tjQuery(\"#table\").prop( \"cellspacing\", 1 );\n\tequal( jQuery(\"#table\").prop(\"cellSpacing\"), \"1\", \"Check setting and retrieving cellSpacing\" );\n\tjQuery(\"#table\").prop( \"cellpadding\", 1 );\n\tequal( jQuery(\"#table\").prop(\"cellPadding\"), \"1\", \"Check setting and retrieving cellPadding\" );\n\tjQuery(\"#table\").prop( \"rowspan\", 1 );\n\tequal( jQuery(\"#table\").prop(\"rowSpan\"), 1, \"Check setting and retrieving rowSpan\" );\n\tjQuery(\"#table\").prop( \"colspan\", 1 );\n\tequal( jQuery(\"#table\").prop(\"colSpan\"), 1, \"Check setting and retrieving colSpan\" );\n\tjQuery(\"#table\").prop( \"usemap\", 1 );\n\tequal( jQuery(\"#table\").prop(\"useMap\"), 1, \"Check setting and retrieving useMap\" );\n\tjQuery(\"#table\").prop( \"frameborder\", 1 );\n\tequal( jQuery(\"#table\").prop(\"frameBorder\"), 1, \"Check setting and retrieving frameBorder\" );\n\tQUnit.reset();\n\n\tvar select, optgroup, option, attributeNode, commentNode, textNode, obj, $form,\n\t\tbody = document.body,\n\t\t$body = jQuery( body );\n\n\tok( $body.prop(\"nextSibling\") === null, \"Make sure a null expando returns null\" );\n\tbody[\"foo\"] = \"bar\";\n\tequal( $body.prop(\"foo\"), \"bar\", \"Make sure the expando is preferred over the dom attribute\" );\n\tbody[\"foo\"] = undefined;\n\tok( $body.prop(\"foo\") === undefined, \"Make sure the expando is preferred over the dom attribute, even if undefined\" );\n\n\tselect = document.createElement(\"select\");\n\toptgroup = document.createElement(\"optgroup\");\n\toption = document.createElement(\"option\");\n\n\toptgroup.appendChild( option );\n\tselect.appendChild( optgroup );\n\n\tequal( jQuery( option ).prop(\"selected\"), true, \"Make sure that a single option is selected, even when in an optgroup.\" );\n\tequal( jQuery( document ).prop(\"nodeName\"), \"#document\", \"prop works correctly on document nodes (bug #7451).\" );\n\n\tattributeNode = document.createAttribute(\"irrelevant\");\n\tcommentNode = document.createComment(\"some comment\");\n\ttextNode = document.createTextNode(\"some text\");\n\tobj = {};\n\tjQuery.each( [ document, attributeNode, commentNode, textNode, obj, \"#firstp\" ], function( i, ele ) {\n\t\tstrictEqual( jQuery( ele ).prop(\"nonexisting\"), undefined, \"prop works correctly for non existing attributes (bug #7500).\" );\n\t});\n\n\tobj = {};\n\tjQuery.each( [ document, obj ], function( i, ele ) {\n\t\tvar $ele = jQuery( ele );\n\t\t$ele.prop( \"nonexisting\", \"foo\" );\n\t\tequal( $ele.prop(\"nonexisting\"), \"foo\", \"prop(name, value) works correctly for non existing attributes (bug #7500).\" );\n\t});\n\tjQuery( document ).removeProp(\"nonexisting\");\n\n\t$form = jQuery(\"#form\").prop( \"enctype\", \"multipart/form-data\" );\n\tequal( $form.prop(\"enctype\"), \"multipart/form-data\", \"Set the enctype of a form (encoding in IE6/7 #6743)\" );\n});\n\ntest( \"prop('tabindex')\", function() {\n\texpect( 11 );\n\n\t// inputs without tabIndex attribute\n\tequal( jQuery(\"#inputWithoutTabIndex\").prop(\"tabindex\"), 0, \"input without tabindex\" );\n\tequal( jQuery(\"#buttonWithoutTabIndex\").prop(\"tabindex\"), 0, \"button without tabindex\" );\n\tequal( jQuery(\"#textareaWithoutTabIndex\").prop(\"tabindex\"), 0, \"textarea without tabindex\" );\n\n\t// elements not natively tabbable\n\tequal( jQuery(\"#listWithTabIndex\").prop(\"tabindex\"), 5, \"not natively tabbable, with tabindex set to 0\" );\n\tequal( jQuery(\"#divWithNoTabIndex\").prop(\"tabindex\"), -1, \"not natively tabbable, no tabindex set\" );\n\n\t// anchor with href\n\tequal( jQuery(\"#linkWithNoTabIndex\").prop(\"tabindex\"), 0, \"anchor with href, no tabindex set\" );\n\tequal( jQuery(\"#linkWithTabIndex\").prop(\"tabindex\"), 2, \"anchor with href, tabindex set to 2\" );\n\tequal( jQuery(\"#linkWithNegativeTabIndex\").prop(\"tabindex\"), -1, \"anchor with href, tabindex set to -1\" );\n\n\t// anchor without href\n\tequal( jQuery(\"#linkWithNoHrefWithNoTabIndex\").prop(\"tabindex\"), -1, \"anchor without href, no tabindex set\" );\n\tequal( jQuery(\"#linkWithNoHrefWithTabIndex\").prop(\"tabindex\"), 1, \"anchor without href, tabindex set to 2\" );\n\tequal( jQuery(\"#linkWithNoHrefWithNegativeTabIndex\").prop(\"tabindex\"), -1, \"anchor without href, no tabindex set\" );\n});\n\ntest( \"prop('tabindex', value)\", 10, function() {\n\n\tvar clone,\n\t\telement = jQuery(\"#divWithNoTabIndex\");\n\n\tequal( element.prop(\"tabindex\"), -1, \"start with no tabindex\" );\n\n\t// set a positive string\n\telement.prop( \"tabindex\", \"1\" );\n\tequal( element.prop(\"tabindex\"), 1, \"set tabindex to 1 (string)\" );\n\n\t// set a zero string\n\telement.prop( \"tabindex\", \"0\" );\n\tequal( element.prop(\"tabindex\"), 0, \"set tabindex to 0 (string)\" );\n\n\t// set a negative string\n\telement.prop( \"tabindex\", \"-1\" );\n\tequal( element.prop(\"tabindex\"), -1, \"set tabindex to -1 (string)\" );\n\n\t// set a positive number\n\telement.prop( \"tabindex\", 1 );\n\tequal( element.prop(\"tabindex\"), 1, \"set tabindex to 1 (number)\" );\n\n\t// set a zero number\n\telement.prop( \"tabindex\", 0 );\n\tequal( element.prop(\"tabindex\"), 0, \"set tabindex to 0 (number)\" );\n\n\t// set a negative number\n\telement.prop( \"tabindex\", -1 );\n\tequal( element.prop(\"tabindex\"), -1, \"set tabindex to -1 (number)\" );\n\n\telement = jQuery(\"#linkWithTabIndex\");\n\tequal( element.prop(\"tabindex\"), 2, \"start with tabindex 2\" );\n\n\telement.prop( \"tabindex\", -1 );\n\tequal( element.prop(\"tabindex\"), -1, \"set negative tabindex\" );\n\n\tclone = element.clone();\n\tclone.prop( \"tabindex\", 1 );\n\tequal( clone[ 0 ].getAttribute(\"tabindex\"), \"1\", \"set tabindex on cloned element\" );\n});\n\ntest( \"removeProp(String)\", function() {\n\texpect( 6 );\n\tvar attributeNode = document.createAttribute(\"irrelevant\"),\n\t\tcommentNode = document.createComment(\"some comment\"),\n\t\ttextNode = document.createTextNode(\"some text\"),\n\t\tobj = {};\n\n\tstrictEqual(\n\t\tjQuery( \"#firstp\" ).prop( \"nonexisting\", \"foo\" ).removeProp( \"nonexisting\" )[ 0 ][\"nonexisting\"],\n\t\tundefined,\n\t\t\"removeprop works correctly on DOM element nodes\"\n\t);\n\n\tjQuery.each( [ document, obj ], function( i, ele ) {\n\t\tvar $ele = jQuery( ele );\n\t\t$ele.prop( \"nonexisting\", \"foo\" ).removeProp(\"nonexisting\");\n\t\tstrictEqual( ele[\"nonexisting\"], undefined, \"removeProp works correctly on non DOM element nodes (bug #7500).\" );\n\t});\n\tjQuery.each( [ commentNode, textNode, attributeNode ], function( i, ele ) {\n\t\tvar $ele = jQuery( ele );\n\t\t$ele.prop( \"nonexisting\", \"foo\" ).removeProp(\"nonexisting\");\n\t\tstrictEqual( ele[\"nonexisting\"], undefined, \"removeProp works correctly on non DOM element nodes (bug #7500).\" );\n\t});\n});\n\ntest( \"val()\", function() {\n\texpect( 21 + ( jQuery.fn.serialize ? 6 : 0 ) );\n\n\tvar checks, $button;\n\n\tdocument.getElementById(\"text1\").value = \"bla\";\n\tequal( jQuery(\"#text1\").val(), \"bla\", \"Check for modified value of input element\" );\n\n\tQUnit.reset();\n\n\tequal( jQuery(\"#text1\").val(), \"Test\", \"Check for value of input element\" );\n\t// ticket #1714 this caused a JS error in IE\n\tequal( jQuery(\"#first\").val(), \"\", \"Check a paragraph element to see if it has a value\" );\n\tok( jQuery([]).val() === undefined, \"Check an empty jQuery object will return undefined from val\" );\n\n\tequal( jQuery(\"#select2\").val(), \"3\", \"Call val() on a single='single' select\" );\n\n\tdeepEqual( jQuery(\"#select3\").val(), [ \"1\", \"2\" ], \"Call val() on a multiple='multiple' select\" );\n\n\tequal( jQuery(\"#option3c\").val(), \"2\", \"Call val() on a option element with value\" );\n\n\tequal( jQuery(\"#option3a\").val(), \"\", \"Call val() on a option element with empty value\" );\n\n\tequal( jQuery(\"#option3e\").val(), \"no value\", \"Call val() on a option element with no value attribute\" );\n\n\tequal( jQuery(\"#option3a\").val(), \"\", \"Call val() on a option element with no value attribute\" );\n\n\tjQuery(\"#select3\").val(\"\");\n\tdeepEqual( jQuery(\"#select3\").val(), [\"\"], \"Call val() on a multiple='multiple' select\" );\n\n\tdeepEqual( jQuery(\"#select4\").val(), [], \"Call val() on multiple='multiple' select with all disabled options\" );\n\n\tjQuery(\"#select4 optgroup\").add(\"#select4 > [disabled]\").attr( \"disabled\", false );\n\tdeepEqual( jQuery(\"#select4\").val(), [ \"2\", \"3\" ], \"Call val() on multiple='multiple' select with some disabled options\" );\n\n\tjQuery(\"#select4\").attr( \"disabled\", true );\n\tdeepEqual( jQuery(\"#select4\").val(), [ \"2\", \"3\" ], \"Call val() on disabled multiple='multiple' select\" );\n\n\tequal( jQuery(\"#select5\").val(), \"3\", \"Check value on ambiguous select.\" );\n\n\tjQuery(\"#select5\").val( 1 );\n\tequal( jQuery(\"#select5\").val(), \"1\", \"Check value on ambiguous select.\" );\n\n\tjQuery(\"#select5\").val( 3 );\n\tequal( jQuery(\"#select5\").val(), \"3\", \"Check value on ambiguous select.\" );\n\n\tstrictEqual(\n\t\tjQuery(\"<select name='select12584' id='select12584'><option value='1' disabled='disabled'>1</option></select>\").val(),\n\t\tnull,\n\t\t\"Select-one with only option disabled (#12584)\"\n\t);\n\n\tif ( jQuery.fn.serialize ) {\n\t\tchecks = jQuery(\"<input type='checkbox' name='test' value='1'/><input type='checkbox' name='test' value='2'/><input type='checkbox' name='test' value=''/><input type='checkbox' name='test'/>\").appendTo(\"#form\");\n\n\t\tdeepEqual( checks.serialize(), \"\", \"Get unchecked values.\" );\n\n\t\tequal( checks.eq( 3 ).val(), \"on\", \"Make sure a value of 'on' is provided if none is specified.\" );\n\n\t\tchecks.val([ \"2\" ]);\n\t\tdeepEqual( checks.serialize(), \"test=2\", \"Get a single checked value.\" );\n\n\t\tchecks.val([ \"1\", \"\" ]);\n\t\tdeepEqual( checks.serialize(), \"test=1&test=\", \"Get multiple checked values.\" );\n\n\t\tchecks.val([ \"\", \"2\" ]);\n\t\tdeepEqual( checks.serialize(), \"test=2&test=\", \"Get multiple checked values.\" );\n\n\t\tchecks.val([ \"1\", \"on\" ]);\n\t\tdeepEqual( checks.serialize(), \"test=1&test=on\", \"Get multiple checked values.\" );\n\n\t\tchecks.remove();\n\t}\n\n\t$button = jQuery(\"<button value='foobar'>text</button>\").insertAfter(\"#button\");\n\tequal( $button.val(), \"foobar\", \"Value retrieval on a button does not return innerHTML\" );\n\tequal( $button.val(\"baz\").html(), \"text\", \"Setting the value does not change innerHTML\" );\n\n\tequal( jQuery(\"<option/>\").val(\"test\").attr(\"value\"), \"test\", \"Setting value sets the value attribute\" );\n});\n\ntest(\"val() with non-matching values on dropdown list\", function() {\n\texpect( 3 );\n\n\tjQuery(\"#select5\").val( \"\" );\n\tequal( jQuery(\"#select5\").val(), null, \"Non-matching set on select-one\" );\n\n\tvar select6 = jQuery(\"<select multiple id=\\\"select6\\\"><option value=\\\"1\\\">A</option><option value=\\\"2\\\">B</option></select>\").appendTo(\"#form\");\n\tjQuery(select6).val( \"nothing\" );\n\tequal( jQuery(select6).val(), null, \"Non-matching set (single value) on select-multiple\" );\n\n\tjQuery(select6).val( [\"nothing1\", \"nothing2\"] );\n\tequal( jQuery(select6).val(), null, \"Non-matching set (array of values) on select-multiple\" );\n\n\tselect6.remove();\n});\n\nif ( \"value\" in document.createElement(\"meter\") &&\n\t\t\t\"value\" in document.createElement(\"progress\") ) {\n\n\ttest( \"val() respects numbers without exception (Bug #9319)\", function() {\n\n\t\texpect( 4 );\n\n\t\tvar $meter = jQuery(\"<meter min='0' max='10' value='5.6'></meter>\"),\n\t\t\t$progress = jQuery(\"<progress max='10' value='1.5'></progress>\");\n\n\t\ttry {\n\t\t\tequal( typeof $meter.val(), \"number\", \"meter, returns a number and does not throw exception\" );\n\t\t\tequal( $meter.val(), $meter[ 0 ].value, \"meter, api matches host and does not throw exception\" );\n\n\t\t\tequal( typeof $progress.val(), \"number\", \"progress, returns a number and does not throw exception\" );\n\t\t\tequal( $progress.val(), $progress[ 0 ].value, \"progress, api matches host and does not throw exception\" );\n\n\t\t} catch( e ) {}\n\n\t\t$meter.remove();\n\t\t$progress.remove();\n\t});\n}\n\nvar testVal = function( valueObj ) {\n\texpect( 8 );\n\n\tQUnit.reset();\n\tjQuery(\"#text1\").val( valueObj(\"test\") );\n\tequal( document.getElementById(\"text1\").value, \"test\", \"Check for modified (via val(String)) value of input element\" );\n\n\tjQuery(\"#text1\").val( valueObj( undefined ) );\n\tequal( document.getElementById(\"text1\").value, \"\", \"Check for modified (via val(undefined)) value of input element\" );\n\n\tjQuery(\"#text1\").val( valueObj( 67 ) );\n\tequal( document.getElementById(\"text1\").value, \"67\", \"Check for modified (via val(Number)) value of input element\" );\n\n\tjQuery(\"#text1\").val( valueObj( null ) );\n\tequal( document.getElementById(\"text1\").value, \"\", \"Check for modified (via val(null)) value of input element\" );\n\n\tvar j,\n\t\t$select1 = jQuery(\"#select1\");\n\t$select1.val( valueObj(\"3\") );\n\tequal( $select1.val(), \"3\", \"Check for modified (via val(String)) value of select element\" );\n\n\t$select1.val( valueObj( 2 ) );\n\tequal( $select1.val(), \"2\", \"Check for modified (via val(Number)) value of select element\" );\n\n\t$select1.append(\"<option value='4'>four</option>\");\n\t$select1.val( valueObj( 4 ) );\n\tequal( $select1.val(), \"4\", \"Should be possible to set the val() to a newly created option\" );\n\n\t// using contents will get comments regular, text, and comment nodes\n\tj = jQuery(\"#nonnodes\").contents();\n\tj.val( valueObj( \"asdf\" ) );\n\tequal( j.val(), \"asdf\", \"Check node,textnode,comment with val()\" );\n\tj.removeAttr(\"value\");\n};\n\ntest( \"val(String/Number)\", function() {\n\ttestVal( bareObj );\n});\n\ntest( \"val(Function)\", function() {\n\ttestVal( functionReturningObj );\n});\n\ntest( \"val(Array of Numbers) (Bug #7123)\", function() {\n\texpect( 4 );\n\tjQuery(\"#form\").append(\"<input type='checkbox' name='arrayTest' value='1' /><input type='checkbox' name='arrayTest' value='2' /><input type='checkbox' name='arrayTest' value='3' checked='checked' /><input type='checkbox' name='arrayTest' value='4' />\");\n\tvar elements = jQuery(\"input[name=arrayTest]\").val([ 1, 2 ]);\n\tok( elements[ 0 ].checked, \"First element was checked\" );\n\tok( elements[ 1 ].checked, \"Second element was checked\" );\n\tok( !elements[ 2 ].checked, \"Third element was unchecked\" );\n\tok( !elements[ 3 ].checked, \"Fourth element remained unchecked\" );\n\n\telements.remove();\n});\n\ntest( \"val(Function) with incoming value\", function() {\n\texpect( 10 );\n\n\tQUnit.reset();\n\tvar oldVal = jQuery(\"#text1\").val();\n\n\tjQuery(\"#text1\").val(function( i, val ) {\n\t\tequal( val, oldVal, \"Make sure the incoming value is correct.\" );\n\t\treturn \"test\";\n\t});\n\n\tequal( document.getElementById(\"text1\").value, \"test\", \"Check for modified (via val(String)) value of input element\" );\n\n\toldVal = jQuery(\"#text1\").val();\n\n\tjQuery(\"#text1\").val(function( i, val ) {\n\t\tequal( val, oldVal, \"Make sure the incoming value is correct.\" );\n\t\treturn 67;\n\t});\n\n\tequal( document.getElementById(\"text1\").value, \"67\", \"Check for modified (via val(Number)) value of input element\" );\n\n\toldVal = jQuery(\"#select1\").val();\n\n\tjQuery(\"#select1\").val(function( i, val ) {\n\t\tequal( val, oldVal, \"Make sure the incoming value is correct.\" );\n\t\treturn \"3\";\n\t});\n\n\tequal( jQuery(\"#select1\").val(), \"3\", \"Check for modified (via val(String)) value of select element\" );\n\n\toldVal = jQuery(\"#select1\").val();\n\n\tjQuery(\"#select1\").val(function( i, val ) {\n\t\tequal( val, oldVal, \"Make sure the incoming value is correct.\" );\n\t\treturn 2;\n\t});\n\n\tequal( jQuery(\"#select1\").val(), \"2\", \"Check for modified (via val(Number)) value of select element\" );\n\n\tjQuery(\"#select1\").append(\"<option value='4'>four</option>\");\n\n\toldVal = jQuery(\"#select1\").val();\n\n\tjQuery(\"#select1\").val(function( i, val ) {\n\t\tequal( val, oldVal, \"Make sure the incoming value is correct.\" );\n\t\treturn 4;\n\t});\n\n\tequal( jQuery(\"#select1\").val(), \"4\", \"Should be possible to set the val() to a newly created option\" );\n});\n\n// testing if a form.reset() breaks a subsequent call to a select element's .val() (in IE only)\ntest( \"val(select) after form.reset() (Bug #2551)\", function() {\n\texpect( 3 );\n\n\tjQuery(\"<form id='kk' name='kk'><select id='kkk'><option value='cf'>cf</option><option value='gf'>gf</option></select></form>\").appendTo(\"#qunit-fixture\");\n\n\tjQuery(\"#kkk\").val(\"gf\");\n\n\tdocument[\"kk\"].reset();\n\n\tequal( jQuery(\"#kkk\")[ 0 ].value, \"cf\", \"Check value of select after form reset.\" );\n\tequal( jQuery(\"#kkk\").val(), \"cf\", \"Check value of select after form reset.\" );\n\n\t// re-verify the multi-select is not broken (after form.reset) by our fix for single-select\n\tdeepEqual( jQuery(\"#select3\").val(), [\"1\", \"2\"], \"Call val() on a multiple='multiple' select\" );\n\n\tjQuery(\"#kk\").remove();\n});\n\nvar testAddClass = function( valueObj ) {\n\texpect( 9 );\n\n\tvar pass, j, i,\n\t\tdiv = jQuery(\"#qunit-fixture div\");\n\tdiv.addClass( valueObj(\"test\") );\n\tpass = true;\n\tfor ( i = 0; i < div.length; i++ ) {\n\t\tif ( !~div.get( i ).className.indexOf(\"test\") ) {\n\t\t\tpass = false;\n\t\t}\n\t}\n\tok( pass, \"Add Class\" );\n\n\t// using contents will get regular, text, and comment nodes\n\tj = jQuery(\"#nonnodes\").contents();\n\tj.addClass( valueObj(\"asdf\") );\n\tok( j.hasClass(\"asdf\"), \"Check node,textnode,comment for addClass\" );\n\n\tdiv = jQuery(\"<div/>\");\n\n\tdiv.addClass( valueObj(\"test\") );\n\tequal( div.attr(\"class\"), \"test\", \"Make sure there's no extra whitespace.\" );\n\n\tdiv.attr( \"class\", \" foo\" );\n\tdiv.addClass( valueObj(\"test\") );\n\tequal( div.attr(\"class\"), \"foo test\", \"Make sure there's no extra whitespace.\" );\n\n\tdiv.attr( \"class\", \"foo\" );\n\tdiv.addClass( valueObj(\"bar baz\") );\n\tequal( div.attr(\"class\"), \"foo bar baz\", \"Make sure there isn't too much trimming.\" );\n\n\tdiv.removeClass();\n\tdiv.addClass( valueObj(\"foo\") ).addClass( valueObj(\"foo\") );\n\tequal( div.attr(\"class\"), \"foo\", \"Do not add the same class twice in separate calls.\" );\n\n\tdiv.addClass( valueObj(\"fo\") );\n\tequal( div.attr(\"class\"), \"foo fo\", \"Adding a similar class does not get interrupted.\" );\n\tdiv.removeClass().addClass(\"wrap2\");\n\tok( div.addClass(\"wrap\").hasClass(\"wrap\"), \"Can add similarly named classes\");\n\n\tdiv.removeClass();\n\tdiv.addClass( valueObj(\"bar bar\") );\n\tequal( div.attr(\"class\"), \"bar\", \"Do not add the same class twice in the same call.\" );\n};\n\ntest( \"addClass(String)\", function() {\n\ttestAddClass( bareObj );\n});\n\ntest( \"addClass(Function)\", function() {\n\ttestAddClass( functionReturningObj );\n});\n\ntest( \"addClass(Function) with incoming value\", function() {\n\texpect( 52 );\n\tvar pass, i,\n\t\tdiv = jQuery(\"#qunit-fixture div\"),\n\t\told = div.map(function() {\n\t\t\treturn jQuery(this).attr(\"class\") || \"\";\n\t\t});\n\n\tdiv.addClass(function( i, val ) {\n\t\tif ( this.id !== \"_firebugConsole\" ) {\n\t\t\tequal( val, old[ i ], \"Make sure the incoming value is correct.\" );\n\t\t\treturn \"test\";\n\t\t}\n\t});\n\n\tpass = true;\n\tfor ( i = 0; i < div.length; i++ ) {\n\t\tif ( div.get(i).className.indexOf(\"test\") === -1 ) {\n\t\t\tpass = false;\n\t\t}\n\t}\n\tok( pass, \"Add Class\" );\n});\n\nvar testRemoveClass = function(valueObj) {\n\texpect( 8 );\n\n\tvar $set = jQuery(\"#qunit-fixture div\"),\n\t\tdiv = document.createElement(\"div\");\n\n\t$set.addClass(\"test\").removeClass( valueObj(\"test\") );\n\n\tok( !$set.is(\".test\"), \"Remove Class\" );\n\n\t$set.addClass(\"test\").addClass(\"foo\").addClass(\"bar\");\n\t$set.removeClass( valueObj(\"test\") ).removeClass( valueObj(\"bar\") ).removeClass( valueObj(\"foo\") );\n\n\tok( !$set.is(\".test,.bar,.foo\"), \"Remove multiple classes\" );\n\n\t// Make sure that a null value doesn't cause problems\n\t$set.eq( 0 ).addClass(\"expected\").removeClass( valueObj( null ) );\n\tok( $set.eq( 0 ).is(\".expected\"), \"Null value passed to removeClass\" );\n\n\t$set.eq( 0 ).addClass(\"expected\").removeClass( valueObj(\"\") );\n\tok( $set.eq( 0 ).is(\".expected\"), \"Empty string passed to removeClass\" );\n\n\t// using contents will get regular, text, and comment nodes\n\t$set = jQuery(\"#nonnodes\").contents();\n\t$set.removeClass( valueObj(\"asdf\") );\n\tok( !$set.hasClass(\"asdf\"), \"Check node,textnode,comment for removeClass\" );\n\n\n\tjQuery( div ).removeClass( valueObj(\"foo\") );\n\tstrictEqual( jQuery( div ).attr(\"class\"), undefined, \"removeClass doesn't create a class attribute\" );\n\n\tdiv.className = \" test foo \";\n\n\tjQuery( div ).removeClass( valueObj(\"foo\") );\n\tequal( div.className, \"test\", \"Make sure remaining className is trimmed.\" );\n\n\tdiv.className = \" test \";\n\n\tjQuery( div ).removeClass( valueObj(\"test\") );\n\tequal( div.className, \"\", \"Make sure there is nothing left after everything is removed.\" );\n};\n\ntest( \"removeClass(String) - simple\", function() {\n\ttestRemoveClass( bareObj );\n});\n\ntest( \"removeClass(Function) - simple\", function() {\n\ttestRemoveClass( functionReturningObj );\n});\n\ntest( \"removeClass(Function) with incoming value\", function() {\n\texpect( 52 );\n\n\tvar $divs = jQuery(\"#qunit-fixture div\").addClass(\"test\"), old = $divs.map(function() {\n\t\treturn jQuery( this ).attr(\"class\");\n\t});\n\n\t$divs.removeClass(function( i, val ) {\n\t\tif ( this.id !== \"_firebugConsole\" ) {\n\t\t\tequal( val, old[ i ], \"Make sure the incoming value is correct.\" );\n\t\t\treturn \"test\";\n\t\t}\n\t});\n\n\tok( !$divs.is(\".test\"), \"Remove Class\" );\n});\n\ntest( \"removeClass() removes duplicates\", function() {\n\texpect( 1 );\n\n\tvar $div = jQuery( jQuery.parseHTML(\"<div class='x x x'></div>\") );\n\n\t$div.removeClass(\"x\");\n\n\tok( !$div.hasClass(\"x\"), \"Element with multiple same classes does not escape the wrath of removeClass()\" );\n});\n\ntest(\"removeClass(undefined) is a no-op\", function() {\n\texpect( 1 );\n\n\tvar $div = jQuery(\"<div class='base second'></div>\");\n\t$div.removeClass( undefined );\n\n\tok( $div.hasClass(\"base\") && $div.hasClass(\"second\"), \"Element still has classes after removeClass(undefined)\" );\n});\n\nvar testToggleClass = function(valueObj) {\n\texpect( 17 );\n\n\tvar e = jQuery(\"#firstp\");\n\tok( !e.is(\".test\"), \"Assert class not present\" );\n\te.toggleClass( valueObj(\"test\") );\n\tok( e.is(\".test\"), \"Assert class present\" );\n\te.toggleClass( valueObj(\"test\") );\n\tok( !e.is(\".test\"), \"Assert class not present\" );\n\n\t// class name with a boolean\n\te.toggleClass( valueObj(\"test\"), false );\n\tok( !e.is(\".test\"), \"Assert class not present\" );\n\te.toggleClass( valueObj(\"test\"), true );\n\tok( e.is(\".test\"), \"Assert class present\" );\n\te.toggleClass( valueObj(\"test\"), false );\n\tok( !e.is(\".test\"), \"Assert class not present\" );\n\n\t// multiple class names\n\te.addClass(\"testA testB\");\n\tok( e.is(\".testA.testB\"), \"Assert 2 different classes present\" );\n\te.toggleClass( valueObj(\"testB testC\") );\n\tok( (e.is(\".testA.testC\") && !e.is(\".testB\")), \"Assert 1 class added, 1 class removed, and 1 class kept\" );\n\te.toggleClass( valueObj(\"testA testC\") );\n\tok( (!e.is(\".testA\") && !e.is(\".testB\") && !e.is(\".testC\")), \"Assert no class present\" );\n\n\t// toggleClass storage\n\te.toggleClass( true );\n\tok( e[ 0 ].className === \"\", \"Assert class is empty (data was empty)\" );\n\te.addClass(\"testD testE\");\n\tok( e.is(\".testD.testE\"), \"Assert class present\" );\n\te.toggleClass();\n\tok( !e.is(\".testD.testE\"), \"Assert class not present\" );\n\tok( jQuery._data(e[ 0 ], \"__className__\") === \"testD testE\", \"Assert data was stored\" );\n\te.toggleClass();\n\tok( e.is(\".testD.testE\"), \"Assert class present (restored from data)\" );\n\te.toggleClass( false );\n\tok( !e.is(\".testD.testE\"), \"Assert class not present\" );\n\te.toggleClass( true );\n\tok( e.is(\".testD.testE\"), \"Assert class present (restored from data)\" );\n\te.toggleClass();\n\te.toggleClass( false );\n\te.toggleClass();\n\tok( e.is(\".testD.testE\"), \"Assert class present (restored from data)\" );\n\n\t// Cleanup\n\te.removeClass(\"testD\");\n\tQUnit.expectJqData( e[ 0 ], \"__className__\" );\n};\n\ntest( \"toggleClass(String|boolean|undefined[, boolean])\", function() {\n\ttestToggleClass( bareObj );\n});\n\ntest( \"toggleClass(Function[, boolean])\", function() {\n\ttestToggleClass( functionReturningObj );\n});\n\ntest( \"toggleClass(Function[, boolean]) with incoming value\", function() {\n\texpect( 14 );\n\n\tvar e = jQuery(\"#firstp\"),\n\t\told = e.attr(\"class\") || \"\";\n\n\tok( !e.is(\".test\"), \"Assert class not present\" );\n\n\te.toggleClass(function( i, val ) {\n\t\tequal( old, val, \"Make sure the incoming value is correct.\" );\n\t\treturn \"test\";\n\t});\n\tok( e.is(\".test\"), \"Assert class present\" );\n\n\told = e.attr(\"class\");\n\n\te.toggleClass(function( i, val ) {\n\t\tequal( old, val, \"Make sure the incoming value is correct.\" );\n\t\treturn \"test\";\n\t});\n\tok( !e.is(\".test\"), \"Assert class not present\" );\n\n\told = e.attr(\"class\") || \"\";\n\n\t// class name with a boolean\n\te.toggleClass(function( i, val, state ) {\n\t\tequal( old, val, \"Make sure the incoming value is correct.\" );\n\t\tequal( state, false, \"Make sure that the state is passed in.\" );\n\t\treturn \"test\";\n\t}, false );\n\tok( !e.is(\".test\"), \"Assert class not present\" );\n\n\told = e.attr(\"class\") || \"\";\n\n\te.toggleClass(function( i, val, state ) {\n\t\tequal( old, val, \"Make sure the incoming value is correct.\" );\n\t\tequal( state, true, \"Make sure that the state is passed in.\" );\n\t\treturn \"test\";\n\t}, true );\n\tok( e.is(\".test\"), \"Assert class present\" );\n\n\told = e.attr(\"class\");\n\n\te.toggleClass(function( i, val, state ) {\n\t\tequal( old, val, \"Make sure the incoming value is correct.\" );\n\t\tequal( state, false, \"Make sure that the state is passed in.\" );\n\t\treturn \"test\";\n\t}, false );\n\tok( !e.is(\".test\"), \"Assert class not present\" );\n});\n\ntest( \"addClass, removeClass, hasClass\", function() {\n\texpect( 17 );\n\n\tvar jq = jQuery(\"<p>Hi</p>\"), x = jq[ 0 ];\n\n\tjq.addClass(\"hi\");\n\tequal( x.className, \"hi\", \"Check single added class\" );\n\n\tjq.addClass(\"foo bar\");\n\tequal( x.className, \"hi foo bar\", \"Check more added classes\" );\n\n\tjq.removeClass();\n\tequal( x.className, \"\", \"Remove all classes\" );\n\n\tjq.addClass(\"hi foo bar\");\n\tjq.removeClass(\"foo\");\n\tequal( x.className, \"hi bar\", \"Check removal of one class\" );\n\n\tok( jq.hasClass(\"hi\"), \"Check has1\" );\n\tok( jq.hasClass(\"bar\"), \"Check has2\" );\n\n\tjq = jQuery(\"<p class='class1\\nclass2\\tcla.ss3\\n\\rclass4'></p>\");\n\n\tok( jq.hasClass(\"class1\"), \"Check hasClass with line feed\" );\n\tok( jq.is(\".class1\"), \"Check is with line feed\" );\n\tok( jq.hasClass(\"class2\"), \"Check hasClass with tab\" );\n\tok( jq.is(\".class2\"), \"Check is with tab\" );\n\tok( jq.hasClass(\"cla.ss3\"), \"Check hasClass with dot\" );\n\tok( jq.hasClass(\"class4\"), \"Check hasClass with carriage return\" );\n\tok( jq.is(\".class4\"), \"Check is with carriage return\" );\n\n\tjq.removeClass(\"class2\");\n\tok( jq.hasClass(\"class2\") === false, \"Check the class has been properly removed\" );\n\tjq.removeClass(\"cla\");\n\tok( jq.hasClass(\"cla.ss3\"), \"Check the dotted class has not been removed\" );\n\tjq.removeClass(\"cla.ss3\");\n\tok( jq.hasClass(\"cla.ss3\") === false, \"Check the dotted class has been removed\" );\n\tjq.removeClass(\"class4\");\n\tok( jq.hasClass(\"class4\") === false, \"Check the class has been properly removed\" );\n});\n\ntest( \"contents().hasClass() returns correct values\", function() {\n\texpect( 2 );\n\n\tvar $div = jQuery(\"<div><span class='foo'></span><!-- comment -->text</div>\"),\n\t$contents = $div.contents();\n\n\tok( $contents.hasClass(\"foo\"), \"Found 'foo' in $contents\" );\n\tok( !$contents.hasClass(\"undefined\"), \"Did not find 'undefined' in $contents (correctly)\" );\n});\n\ntest( \"hasClass correctly interprets non-space separators (#13835)\", function() {\n\texpect( 4 );\n\n\tvar\n\t\tmap = {\n\t\t\ttab: \"&#9;\",\n\t\t\t\"line-feed\": \"&#10;\",\n\t\t\t\"form-feed\": \"&#12;\",\n\t\t\t\"carriage-return\": \"&#13;\"\n\t\t},\n\t\tclasses = jQuery.map( map, function( separator, label ) {\n\t\t\treturn \" \" + separator + label + separator + \" \";\n\t\t}),\n\t\t$div = jQuery( \"<div class='\" + classes + \"'></div>\" );\n\n\tjQuery.each( map, function( label ) {\n\t\tok( $div.hasClass( label ), label.replace( \"-\", \" \" ) );\n\t});\n});\n\ntest( \"coords returns correct values in IE6/IE7, see #10828\", function() {\n\texpect( 1 );\n\n\tvar area,\n\t\tmap = jQuery(\"<map />\");\n\n\tarea = map.html(\"<area shape='rect' coords='0,0,0,0' href='#' alt='a' />\").find(\"area\");\n\tequal( area.attr(\"coords\"), \"0,0,0,0\", \"did not retrieve coords correctly\" );\n});\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/jquery/test/unit/callbacks.js",
    "content": "module( \"callbacks\", {\n\tteardown: moduleTeardown\n});\n\n(function() {\n\nvar output,\n\taddToOutput = function( string ) {\n\t\treturn function() {\n\t\t\toutput += string;\n\t\t};\n\t},\n\toutputA = addToOutput(\"A\"),\n\toutputB = addToOutput(\"B\"),\n\toutputC = addToOutput(\"C\"),\n\ttests = {\n\t\t\"\":                   \"XABC   X     XABCABCC  X  XBB X   XABA  X   XX\",\n\t\t\"once\":               \"XABC   X     X         X  X   X   XABA  X   XX\",\n\t\t\"memory\":             \"XABC   XABC  XABCABCCC XA XBB XB  XABA  XC  XX\",\n\t\t\"unique\":             \"XABC   X     XABCA     X  XBB X   XAB   X   X\",\n\t\t\"stopOnFalse\":        \"XABC   X     XABCABCC  X  XBB X   XA    X   XX\",\n\t\t\"once memory\":        \"XABC   XABC  X         XA X   XA  XABA  XC  XX\",\n\t\t\"once unique\":        \"XABC   X     X         X  X   X   XAB   X   X\",\n\t\t\"once stopOnFalse\":   \"XABC   X     X         X  X   X   XA    X   XX\",\n\t\t\"memory unique\":      \"XABC   XA    XABCA     XA XBB XB  XAB   XC  X\",\n\t\t\"memory stopOnFalse\": \"XABC   XABC  XABCABCCC XA XBB XB  XA    X   XX\",\n\t\t\"unique stopOnFalse\": \"XABC   X     XABCA     X  XBB X   XA    X   X\"\n\t},\n\tfilters = {\n\t\t\"no filter\": undefined,\n\t\t\"filter\": function( fn ) {\n\t\t\treturn function() {\n\t\t\t\treturn fn.apply( this, arguments );\n\t\t\t};\n\t\t}\n\t};\n\n\tfunction showFlags( flags ) {\n\t\tif ( typeof flags === \"string\" ) {\n\t\t\treturn \"'\" + flags + \"'\";\n\t\t}\n\t\tvar output = [], key;\n\t\tfor ( key in flags ) {\n\t\t\toutput.push( \"'\" + key + \"': \" + flags[ key ] );\n\t\t}\n\t\treturn \"{ \" + output.join( \", \" ) + \" }\";\n\t}\n\njQuery.each( tests, function( strFlags, resultString ) {\n\n\t\tvar objectFlags = {};\n\n\t\tjQuery.each( strFlags.split( \" \" ), function() {\n\t\t\tif ( this.length ) {\n\t\t\t\tobjectFlags[ this ] = true;\n\t\t\t}\n\t\t});\n\n\t\tjQuery.each( filters, function( filterLabel ) {\n\n\t\t\tjQuery.each({\n\t\t\t\t\"string\": strFlags,\n\t\t\t\t\"object\": objectFlags\n\t\t\t}, function( flagsTypes, flags ) {\n\n\t\t\t\ttest( \"jQuery.Callbacks( \" + showFlags( flags ) + \" ) - \" + filterLabel, function() {\n\n\t\t\t\t\texpect( 21 );\n\n\t\t\t\t\t// Give qunit a little breathing room\n\t\t\t\t\tstop();\n\t\t\t\t\tsetTimeout( start, 0 );\n\n\t\t\t\t\tvar cblist,\n\t\t\t\t\t\tresults = resultString.split( /\\s+/ );\n\n\t\t\t\t\t// Basic binding and firing\n\t\t\t\t\toutput = \"X\";\n\t\t\t\t\tcblist = jQuery.Callbacks( flags );\n\t\t\t\t\tcblist.add(function( str ) {\n\t\t\t\t\t\toutput += str;\n\t\t\t\t\t});\n\t\t\t\t\tcblist.fire(\"A\");\n\t\t\t\t\tstrictEqual( output, \"XA\", \"Basic binding and firing\" );\n\t\t\t\t\tstrictEqual( cblist.fired(), true, \".fired() detects firing\" );\n\t\t\t\t\toutput = \"X\";\n\t\t\t\t\tcblist.disable();\n\t\t\t\t\tcblist.add(function( str ) {\n\t\t\t\t\t\toutput += str;\n\t\t\t\t\t});\n\t\t\t\t\tstrictEqual( output, \"X\", \"Adding a callback after disabling\" );\n\t\t\t\t\tcblist.fire(\"A\");\n\t\t\t\t\tstrictEqual( output, \"X\", \"Firing after disabling\" );\n\n\t\t\t\t\t// #13517 - Emptying while firing\n\t\t\t\t\tcblist = jQuery.Callbacks( flags );\n\t\t\t\t\tcblist.add( cblist.empty );\n\t\t\t\t\tcblist.add( function() {\n\t\t\t\t\t\tok( false, \"not emptied\" );\n\t\t\t\t\t} );\n\t\t\t\t\tcblist.fire();\n\n\t\t\t\t\t// Disabling while firing\n\t\t\t\t\tcblist = jQuery.Callbacks( flags );\n\t\t\t\t\tcblist.add( cblist.disable );\n\t\t\t\t\tcblist.add( function() {\n\t\t\t\t\t\tok( false, \"not disabled\" );\n\t\t\t\t\t} );\n\t\t\t\t\tcblist.fire();\n\n\t\t\t\t\t// Basic binding and firing (context, arguments)\n\t\t\t\t\toutput = \"X\";\n\t\t\t\t\tcblist = jQuery.Callbacks( flags );\n\t\t\t\t\tcblist.add(function() {\n\t\t\t\t\t\tequal( this, window, \"Basic binding and firing (context)\" );\n\t\t\t\t\t\toutput += Array.prototype.join.call( arguments, \"\" );\n\t\t\t\t\t});\n\t\t\t\t\tcblist.fireWith( window, [ \"A\", \"B\" ] );\n\t\t\t\t\tstrictEqual( output, \"XAB\", \"Basic binding and firing (arguments)\" );\n\n\t\t\t\t\t// fireWith with no arguments\n\t\t\t\t\toutput = \"\";\n\t\t\t\t\tcblist = jQuery.Callbacks( flags );\n\t\t\t\t\tcblist.add(function() {\n\t\t\t\t\t\tequal( this, window, \"fireWith with no arguments (context is window)\" );\n\t\t\t\t\t\tstrictEqual( arguments.length, 0, \"fireWith with no arguments (no arguments)\" );\n\t\t\t\t\t});\n\t\t\t\t\tcblist.fireWith();\n\n\t\t\t\t\t// Basic binding, removing and firing\n\t\t\t\t\toutput = \"X\";\n\t\t\t\t\tcblist = jQuery.Callbacks( flags );\n\t\t\t\t\tcblist.add( outputA, outputB, outputC );\n\t\t\t\t\tcblist.remove( outputB, outputC );\n\t\t\t\t\tcblist.fire();\n\t\t\t\t\tstrictEqual( output, \"XA\", \"Basic binding, removing and firing\" );\n\n\t\t\t\t\t// Empty\n\t\t\t\t\toutput = \"X\";\n\t\t\t\t\tcblist = jQuery.Callbacks( flags );\n\t\t\t\t\tcblist.add( outputA );\n\t\t\t\t\tcblist.add( outputB );\n\t\t\t\t\tcblist.add( outputC );\n\t\t\t\t\tcblist.empty();\n\t\t\t\t\tcblist.fire();\n\t\t\t\t\tstrictEqual( output, \"X\", \"Empty\" );\n\n\t\t\t\t\t// Locking\n\t\t\t\t\toutput = \"X\";\n\t\t\t\t\tcblist = jQuery.Callbacks( flags );\n\t\t\t\t\tcblist.add(function( str ) {\n\t\t\t\t\t\toutput += str;\n\t\t\t\t\t});\n\t\t\t\t\tcblist.lock();\n\t\t\t\t\tcblist.add(function( str ) {\n\t\t\t\t\t\toutput += str;\n\t\t\t\t\t});\n\t\t\t\t\tcblist.fire(\"A\");\n\t\t\t\t\tcblist.add(function( str ) {\n\t\t\t\t\t\toutput += str;\n\t\t\t\t\t});\n\t\t\t\t\tstrictEqual( output, \"X\", \"Lock early\" );\n\n\t\t\t\t\t// Ordering\n\t\t\t\t\toutput = \"X\";\n\t\t\t\t\tcblist = jQuery.Callbacks( flags );\n\t\t\t\t\tcblist.add(function() {\n\t\t\t\t\t\tcblist.add( outputC );\n\t\t\t\t\t\toutputA();\n\t\t\t\t\t}, outputB );\n\t\t\t\t\tcblist.fire();\n\t\t\t\t\tstrictEqual( output, results.shift(), \"Proper ordering\" );\n\n\t\t\t\t\t// Add and fire again\n\t\t\t\t\toutput = \"X\";\n\t\t\t\t\tcblist.add(function() {\n\t\t\t\t\t\tcblist.add( outputC );\n\t\t\t\t\t\toutputA();\n\t\t\t\t\t}, outputB );\n\t\t\t\t\tstrictEqual( output, results.shift(), \"Add after fire\" );\n\n\t\t\t\t\toutput = \"X\";\n\t\t\t\t\tcblist.fire();\n\t\t\t\t\tstrictEqual( output, results.shift(), \"Fire again\" );\n\n\t\t\t\t\t// Multiple fire\n\t\t\t\t\toutput = \"X\";\n\t\t\t\t\tcblist = jQuery.Callbacks( flags );\n\t\t\t\t\tcblist.add(function( str ) {\n\t\t\t\t\t\toutput += str;\n\t\t\t\t\t});\n\t\t\t\t\tcblist.fire(\"A\");\n\t\t\t\t\tstrictEqual( output, \"XA\", \"Multiple fire (first fire)\" );\n\t\t\t\t\toutput = \"X\";\n\t\t\t\t\tcblist.add(function( str ) {\n\t\t\t\t\t\toutput += str;\n\t\t\t\t\t});\n\t\t\t\t\tstrictEqual( output, results.shift(), \"Multiple fire (first new callback)\" );\n\t\t\t\t\toutput = \"X\";\n\t\t\t\t\tcblist.fire(\"B\");\n\t\t\t\t\tstrictEqual( output, results.shift(), \"Multiple fire (second fire)\" );\n\t\t\t\t\toutput = \"X\";\n\t\t\t\t\tcblist.add(function( str ) {\n\t\t\t\t\t\toutput += str;\n\t\t\t\t\t});\n\t\t\t\t\tstrictEqual( output, results.shift(), \"Multiple fire (second new callback)\" );\n\n\t\t\t\t\t// Return false\n\t\t\t\t\toutput = \"X\";\n\t\t\t\t\tcblist = jQuery.Callbacks( flags );\n\t\t\t\t\tcblist.add( outputA, function() { return false; }, outputB );\n\t\t\t\t\tcblist.add( outputA );\n\t\t\t\t\tcblist.fire();\n\t\t\t\t\tstrictEqual( output, results.shift(), \"Callback returning false\" );\n\n\t\t\t\t\t// Add another callback (to control lists with memory do not fire anymore)\n\t\t\t\t\toutput = \"X\";\n\t\t\t\t\tcblist.add( outputC );\n\t\t\t\t\tstrictEqual( output, results.shift(), \"Adding a callback after one returned false\" );\n\n\t\t\t\t\t// Callbacks are not iterated\n\t\t\t\t\toutput = \"\";\n\t\t\t\t\tfunction handler() {\n\t\t\t\t\t\toutput += \"X\";\n\t\t\t\t\t}\n\t\t\t\t\thandler.method = function() {\n\t\t\t\t\t\toutput += \"!\";\n\t\t\t\t\t};\n\t\t\t\t\tcblist = jQuery.Callbacks( flags );\n\t\t\t\t\tcblist.add( handler );\n\t\t\t\t\tcblist.add( handler );\n\t\t\t\t\tcblist.fire();\n\t\t\t\t\tstrictEqual( output, results.shift(), \"No callback iteration\" );\n\t\t\t\t});\n\t\t\t});\n\t\t});\n});\n\n})();\n\ntest( \"jQuery.Callbacks( options ) - options are copied\", function() {\n\n\texpect( 1 );\n\n\tvar options = {\n\t\t\t\"unique\": true\n\t\t},\n\t\tcb = jQuery.Callbacks( options ),\n\t\tcount = 0,\n\t\tfn = function() {\n\t\t\tok( !( count++ ), \"called once\" );\n\t\t};\n\toptions[\"unique\"] = false;\n\tcb.add( fn, fn );\n\tcb.fire();\n});\n\ntest( \"jQuery.Callbacks.fireWith - arguments are copied\", function() {\n\n\texpect( 1 );\n\n\tvar cb = jQuery.Callbacks(\"memory\"),\n\t\targs = [\"hello\"];\n\n\tcb.fireWith( null, args );\n\targs[ 0 ] = \"world\";\n\n\tcb.add(function( hello ) {\n\t\tstrictEqual( hello, \"hello\", \"arguments are copied internally\" );\n\t});\n});\n\ntest( \"jQuery.Callbacks.remove - should remove all instances\", function() {\n\n\texpect( 1 );\n\n\tvar cb = jQuery.Callbacks();\n\n\tfunction fn() {\n\t\tok( false, \"function wasn't removed\" );\n\t}\n\n\tcb.add( fn, fn, function() {\n\t\tok( true, \"end of test\" );\n\t}).remove( fn ).fire();\n});\n\ntest( \"jQuery.Callbacks.has\", function() {\n\n\texpect( 13 );\n\n\tvar cb = jQuery.Callbacks();\n\tfunction getA() {\n\t\treturn \"A\";\n\t}\n\tfunction getB() {\n\t\treturn \"B\";\n\t}\n\tfunction getC() {\n\t\treturn \"C\";\n\t}\n\tcb.add(getA, getB, getC);\n\tstrictEqual( cb.has(), true, \"No arguments to .has() returns whether callback function(s) are attached or not\" );\n\tstrictEqual( cb.has(getA), true, \"Check if a specific callback function is in the Callbacks list\" );\n\n\tcb.remove(getB);\n\tstrictEqual( cb.has(getB), false, \"Remove a specific callback function and make sure its no longer there\" );\n\tstrictEqual( cb.has(getA), true, \"Remove a specific callback function and make sure other callback function is still there\" );\n\n\tcb.empty();\n\tstrictEqual( cb.has(), false, \"Empty list and make sure there are no callback function(s)\" );\n\tstrictEqual( cb.has(getA), false, \"Check for a specific function in an empty() list\" );\n\n\tcb.add(getA, getB, function(){\n\t\tstrictEqual( cb.has(), true, \"Check if list has callback function(s) from within a callback function\" );\n\t\tstrictEqual( cb.has(getA), true, \"Check if list has a specific callback from within a callback function\" );\n\t}).fire();\n\n\tstrictEqual( cb.has(), true, \"Callbacks list has callback function(s) after firing\" );\n\n\tcb.disable();\n\tstrictEqual( cb.has(), false, \"disabled() list has no callback functions (returns false)\" );\n\tstrictEqual( cb.has(getA), false, \"Check for a specific function in a disabled() list\" );\n\n\tcb = jQuery.Callbacks(\"unique\");\n\tcb.add(getA);\n\tcb.add(getA);\n\tstrictEqual( cb.has(), true, \"Check if unique list has callback function(s) attached\" );\n\tcb.lock();\n\tstrictEqual( cb.has(), false, \"locked() list is empty and returns false\" );\n\n\n});\n\ntest( \"jQuery.Callbacks() - adding a string doesn't cause a stack overflow\", function() {\n\n\texpect( 1 );\n\n\tjQuery.Callbacks().add( \"hello world\" );\n\n\tok( true, \"no stack overflow\" );\n});\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/jquery/test/unit/core.js",
    "content": "module(\"core\", { teardown: moduleTeardown });\n\ntest(\"Unit Testing Environment\", function () {\n\texpect(2);\n\tok( hasPHP, \"Running in an environment with PHP support. The AJAX tests only run if the environment supports PHP!\" );\n\tok( !isLocal, \"Unit tests are not ran from file:// (especially in Chrome. If you must test from file:// with Chrome, run it with the --allow-file-access-from-files flag!)\" );\n});\n\ntest(\"Basic requirements\", function() {\n\texpect(7);\n\tok( Array.prototype.push, \"Array.push()\" );\n\tok( Function.prototype.apply, \"Function.apply()\" );\n\tok( document.getElementById, \"getElementById\" );\n\tok( document.getElementsByTagName, \"getElementsByTagName\" );\n\tok( RegExp, \"RegExp\" );\n\tok( jQuery, \"jQuery\" );\n\tok( $, \"$\" );\n});\n\ntestIframeWithCallback( \"Conditional compilation compatibility (#13274)\", \"core/cc_on.html\", function( cc_on, errors, $ ) {\n\texpect( 3 );\n\tok( true, \"JScript conditional compilation \" + ( cc_on ? \"supported\" : \"not supported\" ) );\n\tdeepEqual( errors, [], \"No errors\" );\n\tok( $(), \"jQuery executes\" );\n});\n\ntestIframeWithCallback( \"document ready when jQuery loaded asynchronously (#13655)\", \"core/dynamic_ready.html\", function( ready ) {\n\texpect( 1 );\n\tequal( true, ready, \"document ready correctly fired when jQuery is loaded after DOMContentLoaded\" );\n});\n\ntest(\"jQuery()\", function() {\n\n\tvar elem, i,\n\t\tobj = jQuery(\"div\"),\n\t\tcode = jQuery(\"<code/>\"),\n\t\timg = jQuery(\"<img/>\"),\n\t\tdiv = jQuery(\"<div/><hr/><code/><b/>\"),\n\t\texec = false,\n\t\tlng = \"\",\n\t\texpected = 22,\n\t\tattrObj = {\n\t\t\t\"text\": \"test\",\n\t\t\t\"class\": \"test2\",\n\t\t\t\"id\": \"test3\"\n\t\t};\n\n\t// The $(html, props) signature can stealth-call any $.fn method, check for a\n\t// few here but beware of modular builds where these methods may be excluded.\n\tif ( jQuery.fn.click ) {\n\t\texpected++;\n\t\tattrObj[\"click\"] = function() { ok( exec, \"Click executed.\" ); };\n\t}\n\tif ( jQuery.fn.width ) {\n\t\texpected++;\n\t\tattrObj[\"width\"] = 10;\n\t}\n\tif ( jQuery.fn.offset ) {\n\t\texpected++;\n\t\tattrObj[\"offset\"] = { \"top\": 1, \"left\": 1 };\n\t}\n\tif ( jQuery.fn.css ) {\n\t\texpected += 2;\n\t\tattrObj[\"css\"] = { \"paddingLeft\": 1, \"paddingRight\": 1 };\n\t}\n\tif ( jQuery.fn.attr ) {\n\t\texpected++;\n\t\tattrObj.attr = { \"desired\": \"very\" };\n\t}\n\n\texpect( expected );\n\n\t// Basic constructor's behavior\n\tequal( jQuery().length, 0, \"jQuery() === jQuery([])\" );\n\tequal( jQuery(undefined).length, 0, \"jQuery(undefined) === jQuery([])\" );\n\tequal( jQuery(null).length, 0, \"jQuery(null) === jQuery([])\" );\n\tequal( jQuery(\"\").length, 0, \"jQuery('') === jQuery([])\" );\n\tequal( jQuery(\"#\").length, 0, \"jQuery('#') === jQuery([])\" );\n\n\tequal( jQuery(obj).selector, \"div\", \"jQuery(jQueryObj) == jQueryObj\" );\n\n\t// can actually yield more than one, when iframes are included, the window is an array as well\n\tequal( jQuery(window).length, 1, \"Correct number of elements generated for jQuery(window)\" );\n\n/*\n\t// disabled since this test was doing nothing. i tried to fix it but i'm not sure\n\t// what the expected behavior should even be. FF returns \"\\n\" for the text node\n\t// make sure this is handled\n\tvar crlfContainer = jQuery('<p>\\r\\n</p>');\n\tvar x = crlfContainer.contents().get(0).nodeValue;\n\tequal( x, what???, \"Check for \\\\r and \\\\n in jQuery()\" );\n*/\n\n\t/* // Disabled until we add this functionality in\n\tvar pass = true;\n\ttry {\n\t\tjQuery(\"<div>Testing</div>\").appendTo(document.getElementById(\"iframe\").contentDocument.body);\n\t} catch(e){\n\t\tpass = false;\n\t}\n\tok( pass, \"jQuery('&lt;tag&gt;') needs optional document parameter to ease cross-frame DOM wrangling, see #968\" );*/\n\n\tequal( code.length, 1, \"Correct number of elements generated for code\" );\n\tequal( code.parent().length, 0, \"Make sure that the generated HTML has no parent.\" );\n\n\tequal( img.length, 1, \"Correct number of elements generated for img\" );\n\tequal( img.parent().length, 0, \"Make sure that the generated HTML has no parent.\" );\n\n\tequal( div.length, 4, \"Correct number of elements generated for div hr code b\" );\n\tequal( div.parent().length, 0, \"Make sure that the generated HTML has no parent.\" );\n\n\tequal( jQuery([1,2,3]).get(1), 2, \"Test passing an array to the factory\" );\n\n\tequal( jQuery(document.body).get(0), jQuery(\"body\").get(0), \"Test passing an html node to the factory\" );\n\n\telem = jQuery(\"  <em>hello</em>\")[0];\n\tequal( elem.nodeName.toLowerCase(), \"em\", \"leading space\" );\n\n\telem = jQuery(\"\\n\\n<em>world</em>\")[0];\n\tequal( elem.nodeName.toLowerCase(), \"em\", \"leading newlines\" );\n\n\telem = jQuery(\"<div/>\", attrObj );\n\n\tif ( jQuery.fn.width ) {\n\t\tequal( elem[0].style.width, \"10px\", \"jQuery() quick setter width\");\n\t}\n\n\tif ( jQuery.fn.offset ) {\n\t\tequal( elem[0].style.top, \"1px\", \"jQuery() quick setter offset\");\n\t}\n\n\tif ( jQuery.fn.css ) {\n\t\tequal( elem[0].style.paddingLeft, \"1px\", \"jQuery quick setter css\");\n\t\tequal( elem[0].style.paddingRight, \"1px\", \"jQuery quick setter css\");\n\t}\n\n\tif ( jQuery.fn.attr ) {\n\t\tequal( elem[0].getAttribute(\"desired\"), \"very\", \"jQuery quick setter attr\");\n\t}\n\n\tequal( elem[0].childNodes.length, 1, \"jQuery quick setter text\");\n\tequal( elem[0].firstChild.nodeValue, \"test\", \"jQuery quick setter text\");\n\tequal( elem[0].className, \"test2\", \"jQuery() quick setter class\");\n\tequal( elem[0].id, \"test3\", \"jQuery() quick setter id\");\n\n\texec = true;\n\telem.trigger(\"click\");\n\n\t// manually clean up detached elements\n\telem.remove();\n\n\tfor ( i = 0; i < 3; ++i ) {\n\t\telem = jQuery(\"<input type='text' value='TEST' />\");\n\t}\n\tequal( elem[0].defaultValue, \"TEST\", \"Ensure cached nodes are cloned properly (Bug #6655)\" );\n\n\t// manually clean up detached elements\n\telem.remove();\n\n\tfor ( i = 0; i < 128; i++ ) {\n\t\tlng += \"12345678\";\n\t}\n});\n\ntest(\"jQuery(selector, context)\", function() {\n\texpect(3);\n\tdeepEqual( jQuery(\"div p\", \"#qunit-fixture\").get(), q(\"sndp\", \"en\", \"sap\"), \"Basic selector with string as context\" );\n\tdeepEqual( jQuery(\"div p\", q(\"qunit-fixture\")[0]).get(), q(\"sndp\", \"en\", \"sap\"), \"Basic selector with element as context\" );\n\tdeepEqual( jQuery(\"div p\", jQuery(\"#qunit-fixture\")).get(), q(\"sndp\", \"en\", \"sap\"), \"Basic selector with jQuery object as context\" );\n});\n\ntest( \"selector state\", function() {\n\texpect( 18 );\n\n\tvar test;\n\n\ttest = jQuery( undefined );\n\tequal( test.selector, \"\", \"Empty jQuery Selector\" );\n\tequal( test.context, undefined, \"Empty jQuery Context\" );\n\n\ttest = jQuery( document );\n\tequal( test.selector, \"\", \"Document Selector\" );\n\tequal( test.context, document, \"Document Context\" );\n\n\ttest = jQuery( document.body );\n\tequal( test.selector, \"\", \"Body Selector\" );\n\tequal( test.context, document.body, \"Body Context\" );\n\n\ttest = jQuery(\"#qunit-fixture\");\n\tequal( test.selector, \"#qunit-fixture\", \"#qunit-fixture Selector\" );\n\tequal( test.context, document, \"#qunit-fixture Context\" );\n\n\ttest = jQuery(\"#notfoundnono\");\n\tequal( test.selector, \"#notfoundnono\", \"#notfoundnono Selector\" );\n\tequal( test.context, document, \"#notfoundnono Context\" );\n\n\ttest = jQuery( \"#qunit-fixture\", document );\n\tequal( test.selector, \"#qunit-fixture\", \"#qunit-fixture Selector\" );\n\tequal( test.context, document, \"#qunit-fixture Context\" );\n\n\ttest = jQuery( \"#qunit-fixture\", document.body );\n\tequal( test.selector, \"#qunit-fixture\", \"#qunit-fixture Selector\" );\n\tequal( test.context, document.body, \"#qunit-fixture Context\" );\n\n\t// Test cloning\n\ttest = jQuery( test );\n\tequal( test.selector, \"#qunit-fixture\", \"#qunit-fixture Selector\" );\n\tequal( test.context, document.body, \"#qunit-fixture Context\" );\n\n\ttest = jQuery( document.body ).find(\"#qunit-fixture\");\n\tequal( test.selector, \"#qunit-fixture\", \"#qunit-fixture find Selector\" );\n\tequal( test.context, document.body, \"#qunit-fixture find Context\" );\n});\n\ntest( \"globalEval\", function() {\n\texpect( 3 );\n\tGlobals.register(\"globalEvalTest\");\n\n\tjQuery.globalEval(\"globalEvalTest = 1;\");\n\tequal( window.globalEvalTest, 1, \"Test variable assignments are global\" );\n\n\tjQuery.globalEval(\"var globalEvalTest = 2;\");\n\tequal( window.globalEvalTest, 2, \"Test variable declarations are global\" );\n\n\tjQuery.globalEval(\"this.globalEvalTest = 3;\");\n\tequal( window.globalEvalTest, 3, \"Test context (this) is the window object\" );\n});\n\ntest( \"globalEval with 'use strict'\", function() {\n\texpect( 1 );\n\tGlobals.register(\"strictEvalTest\");\n\n\tjQuery.globalEval(\"'use strict'; var strictEvalTest = 1;\");\n\tequal( window.strictEvalTest, 1, \"Test variable declarations are global (strict mode)\" );\n});\n\ntest(\"noConflict\", function() {\n\texpect(7);\n\n\tvar $$ = jQuery;\n\n\tstrictEqual( jQuery, jQuery.noConflict(), \"noConflict returned the jQuery object\" );\n\tstrictEqual( window[\"jQuery\"], $$, \"Make sure jQuery wasn't touched.\" );\n\tstrictEqual( window[\"$\"], original$, \"Make sure $ was reverted.\" );\n\n\tjQuery = $ = $$;\n\n\tstrictEqual( jQuery.noConflict(true), $$, \"noConflict returned the jQuery object\" );\n\tstrictEqual( window[\"jQuery\"], originaljQuery, \"Make sure jQuery was reverted.\" );\n\tstrictEqual( window[\"$\"], original$, \"Make sure $ was reverted.\" );\n\tok( $$().pushStack([]), \"Make sure that jQuery still works.\" );\n\n\twindow[\"jQuery\"] = jQuery = $$;\n});\n\ntest(\"trim\", function() {\n\texpect(13);\n\n\tvar nbsp = String.fromCharCode(160);\n\n\tequal( jQuery.trim(\"hello  \"), \"hello\", \"trailing space\" );\n\tequal( jQuery.trim(\"  hello\"), \"hello\", \"leading space\" );\n\tequal( jQuery.trim(\"  hello   \"), \"hello\", \"space on both sides\" );\n\tequal( jQuery.trim(\"  \" + nbsp + \"hello  \" + nbsp + \" \"), \"hello\", \"&nbsp;\" );\n\n\tequal( jQuery.trim(), \"\", \"Nothing in.\" );\n\tequal( jQuery.trim( undefined ), \"\", \"Undefined\" );\n\tequal( jQuery.trim( null ), \"\", \"Null\" );\n\tequal( jQuery.trim( 5 ), \"5\", \"Number\" );\n\tequal( jQuery.trim( false ), \"false\", \"Boolean\" );\n\n\tequal( jQuery.trim(\" \"), \"\", \"space should be trimmed\" );\n\tequal( jQuery.trim(\"ipad\\xA0\"), \"ipad\", \"nbsp should be trimmed\" );\n\tequal( jQuery.trim(\"\\uFEFF\"), \"\", \"zwsp should be trimmed\" );\n\tequal( jQuery.trim(\"\\uFEFF \\xA0! | \\uFEFF\"), \"! |\", \"leading/trailing should be trimmed\" );\n});\n\ntest(\"type\", function() {\n\texpect( 28 );\n\n\tequal( jQuery.type(null), \"null\", \"null\" );\n\tequal( jQuery.type(undefined), \"undefined\", \"undefined\" );\n\tequal( jQuery.type(true), \"boolean\", \"Boolean\" );\n\tequal( jQuery.type(false), \"boolean\", \"Boolean\" );\n\tequal( jQuery.type(Boolean(true)), \"boolean\", \"Boolean\" );\n\tequal( jQuery.type(0), \"number\", \"Number\" );\n\tequal( jQuery.type(1), \"number\", \"Number\" );\n\tequal( jQuery.type(Number(1)), \"number\", \"Number\" );\n\tequal( jQuery.type(\"\"), \"string\", \"String\" );\n\tequal( jQuery.type(\"a\"), \"string\", \"String\" );\n\tequal( jQuery.type(String(\"a\")), \"string\", \"String\" );\n\tequal( jQuery.type({}), \"object\", \"Object\" );\n\tequal( jQuery.type(/foo/), \"regexp\", \"RegExp\" );\n\tequal( jQuery.type(new RegExp(\"asdf\")), \"regexp\", \"RegExp\" );\n\tequal( jQuery.type([1]), \"array\", \"Array\" );\n\tequal( jQuery.type(new Date()), \"date\", \"Date\" );\n\tequal( jQuery.type(new Function(\"return;\")), \"function\", \"Function\" );\n\tequal( jQuery.type(function(){}), \"function\", \"Function\" );\n\tequal( jQuery.type(new Error()), \"error\", \"Error\" );\n\tequal( jQuery.type(window), \"object\", \"Window\" );\n\tequal( jQuery.type(document), \"object\", \"Document\" );\n\tequal( jQuery.type(document.body), \"object\", \"Element\" );\n\tequal( jQuery.type(document.createTextNode(\"foo\")), \"object\", \"TextNode\" );\n\tequal( jQuery.type(document.getElementsByTagName(\"*\")), \"object\", \"NodeList\" );\n\n\t// Avoid Lint complaints\n\tvar MyString = String,\n\t\tMyNumber = Number,\n\t\tMyBoolean = Boolean,\n\t\tMyObject = Object;\n\tequal( jQuery.type(new MyBoolean(true)), \"boolean\", \"Boolean\" );\n\tequal( jQuery.type(new MyNumber(1)), \"number\", \"Number\" );\n\tequal( jQuery.type(new MyString(\"a\")), \"string\", \"String\" );\n\tequal( jQuery.type(new MyObject()), \"object\", \"Object\" );\n});\n\nasyncTest(\"isPlainObject\", function() {\n\texpect(15);\n\n\tvar pass, iframe, doc,\n\t\tfn = function() {};\n\n\t// The use case that we want to match\n\tok( jQuery.isPlainObject({}), \"{}\" );\n\n\t// Not objects shouldn't be matched\n\tok( !jQuery.isPlainObject(\"\"), \"string\" );\n\tok( !jQuery.isPlainObject(0) && !jQuery.isPlainObject(1), \"number\" );\n\tok( !jQuery.isPlainObject(true) && !jQuery.isPlainObject(false), \"boolean\" );\n\tok( !jQuery.isPlainObject(null), \"null\" );\n\tok( !jQuery.isPlainObject(undefined), \"undefined\" );\n\n\t// Arrays shouldn't be matched\n\tok( !jQuery.isPlainObject([]), \"array\" );\n\n\t// Instantiated objects shouldn't be matched\n\tok( !jQuery.isPlainObject(new Date()), \"new Date\" );\n\n\t// Functions shouldn't be matched\n\tok( !jQuery.isPlainObject(fn), \"fn\" );\n\n\t// Again, instantiated objects shouldn't be matched\n\tok( !jQuery.isPlainObject(new fn()), \"new fn (no methods)\" );\n\n\t// Makes the function a little more realistic\n\t// (and harder to detect, incidentally)\n\tfn.prototype[\"someMethod\"] = function(){};\n\n\t// Again, instantiated objects shouldn't be matched\n\tok( !jQuery.isPlainObject(new fn()), \"new fn\" );\n\n\t// DOM Element\n\tok( !jQuery.isPlainObject( document.createElement(\"div\") ), \"DOM Element\" );\n\n\t// Window\n\tok( !jQuery.isPlainObject( window ), \"window\" );\n\n\tpass = false;\n\ttry {\n\t\tjQuery.isPlainObject( window.location );\n\t\tpass = true;\n\t} catch ( e ) {}\n\tok( pass, \"Does not throw exceptions on host objects\" );\n\n\t// Objects from other windows should be matched\n\twindow.iframeCallback = function( otherObject, detail ) {\n\t\twindow.iframeCallback = undefined;\n\t\tiframe.parentNode.removeChild( iframe );\n\t\tok( jQuery.isPlainObject(new otherObject()), \"new otherObject\" + ( detail ? \" - \" + detail : \"\" ) );\n\t\tstart();\n\t};\n\n\ttry {\n\t\tiframe = jQuery(\"#qunit-fixture\")[0].appendChild( document.createElement(\"iframe\") );\n\t\tdoc = iframe.contentDocument || iframe.contentWindow.document;\n\t\tdoc.open();\n\t\tdoc.write(\"<body onload='window.parent.iframeCallback(Object);'>\");\n\t\tdoc.close();\n\t} catch(e) {\n\t\twindow.iframeDone( Object, \"iframes not supported\" );\n\t}\n});\n\ntest(\"isFunction\", function() {\n\texpect(19);\n\n\tvar mystr, myarr, myfunction, fn, obj, nodes, first, input, a;\n\n\t// Make sure that false values return false\n\tok( !jQuery.isFunction(), \"No Value\" );\n\tok( !jQuery.isFunction( null ), \"null Value\" );\n\tok( !jQuery.isFunction( undefined ), \"undefined Value\" );\n\tok( !jQuery.isFunction( \"\" ), \"Empty String Value\" );\n\tok( !jQuery.isFunction( 0 ), \"0 Value\" );\n\n\t// Check built-ins\n\t// Safari uses \"(Internal Function)\"\n\tok( jQuery.isFunction(String), \"String Function(\"+String+\")\" );\n\tok( jQuery.isFunction(Array), \"Array Function(\"+Array+\")\" );\n\tok( jQuery.isFunction(Object), \"Object Function(\"+Object+\")\" );\n\tok( jQuery.isFunction(Function), \"Function Function(\"+Function+\")\" );\n\n\t// When stringified, this could be misinterpreted\n\tmystr = \"function\";\n\tok( !jQuery.isFunction(mystr), \"Function String\" );\n\n\t// When stringified, this could be misinterpreted\n\tmyarr = [ \"function\" ];\n\tok( !jQuery.isFunction(myarr), \"Function Array\" );\n\n\t// When stringified, this could be misinterpreted\n\tmyfunction = { \"function\": \"test\" };\n\tok( !jQuery.isFunction(myfunction), \"Function Object\" );\n\n\t// Make sure normal functions still work\n\tfn = function(){};\n\tok( jQuery.isFunction(fn), \"Normal Function\" );\n\n\tobj = document.createElement(\"object\");\n\n\t// Firefox says this is a function\n\tok( !jQuery.isFunction(obj), \"Object Element\" );\n\n\t// IE says this is an object\n\t// Since 1.3, this isn't supported (#2968)\n\t//ok( jQuery.isFunction(obj.getAttribute), \"getAttribute Function\" );\n\n\tnodes = document.body.childNodes;\n\n\t// Safari says this is a function\n\tok( !jQuery.isFunction(nodes), \"childNodes Property\" );\n\n\tfirst = document.body.firstChild;\n\n\t// Normal elements are reported ok everywhere\n\tok( !jQuery.isFunction(first), \"A normal DOM Element\" );\n\n\tinput = document.createElement(\"input\");\n\tinput.type = \"text\";\n\tdocument.body.appendChild( input );\n\n\t// IE says this is an object\n\t// Since 1.3, this isn't supported (#2968)\n\t//ok( jQuery.isFunction(input.focus), \"A default function property\" );\n\n\tdocument.body.removeChild( input );\n\n\ta = document.createElement(\"a\");\n\ta.href = \"some-function\";\n\tdocument.body.appendChild( a );\n\n\t// This serializes with the word 'function' in it\n\tok( !jQuery.isFunction(a), \"Anchor Element\" );\n\n\tdocument.body.removeChild( a );\n\n\t// Recursive function calls have lengths and array-like properties\n\tfunction callme(callback){\n\t\tfunction fn(response){\n\t\t\tcallback(response);\n\t\t}\n\n\t\tok( jQuery.isFunction(fn), \"Recursive Function Call\" );\n\n\t\tfn({ some: \"data\" });\n\t}\n\n\tcallme(function(){\n\t\tcallme(function(){});\n\t});\n});\n\ntest( \"isNumeric\", function() {\n\texpect( 36 );\n\n\tvar t = jQuery.isNumeric,\n\t\tTraditionalists = /** @constructor */ function(n) {\n\t\t\tthis.value = n;\n\t\t\tthis.toString = function(){\n\t\t\t\treturn String(this.value);\n\t\t\t};\n\t\t},\n\t\tanswer = new Traditionalists( \"42\" ),\n\t\trong = new Traditionalists( \"Devo\" );\n\n\tok( t(\"-10\"), \"Negative integer string\");\n\tok( t(\"0\"), \"Zero string\");\n\tok( t(\"5\"), \"Positive integer string\");\n\tok( t(-16), \"Negative integer number\");\n\tok( t(0), \"Zero integer number\");\n\tok( t(32), \"Positive integer number\");\n\tok( t(\"040\"), \"Octal integer literal string\");\n\t// OctalIntegerLiteral has been deprecated since ES3/1999\n\t// It doesn't pass lint, so disabling until a solution can be found\n\t//ok( t(0144), \"Octal integer literal\");\n\tok( t(\"0xFF\"), \"Hexadecimal integer literal string\");\n\tok( t(0xFFF), \"Hexadecimal integer literal\");\n\tok( t(\"-1.6\"), \"Negative floating point string\");\n\tok( t(\"4.536\"), \"Positive floating point string\");\n\tok( t(-2.6), \"Negative floating point number\");\n\tok( t(3.1415), \"Positive floating point number\");\n\tok( t(8e5), \"Exponential notation\");\n\tok( t(\"123e-2\"), \"Exponential notation string\");\n\tok( t(answer), \"Custom .toString returning number\");\n\tequal( t(\"\"), false, \"Empty string\");\n\tequal( t(\"        \"), false, \"Whitespace characters string\");\n\tequal( t(\"\\t\\t\"), false, \"Tab characters string\");\n\tequal( t(\"abcdefghijklm1234567890\"), false, \"Alphanumeric character string\");\n\tequal( t(\"xabcdefx\"), false, \"Non-numeric character string\");\n\tequal( t(true), false, \"Boolean true literal\");\n\tequal( t(false), false, \"Boolean false literal\");\n\tequal( t(\"bcfed5.2\"), false, \"Number with preceding non-numeric characters\");\n\tequal( t(\"7.2acdgs\"), false, \"Number with trailling non-numeric characters\");\n\tequal( t(undefined), false, \"Undefined value\");\n\tequal( t(null), false, \"Null value\");\n\tequal( t(NaN), false, \"NaN value\");\n\tequal( t(Infinity), false, \"Infinity primitive\");\n\tequal( t(Number.POSITIVE_INFINITY), false, \"Positive Infinity\");\n\tequal( t(Number.NEGATIVE_INFINITY), false, \"Negative Infinity\");\n\tequal( t(rong), false, \"Custom .toString returning non-number\");\n\tequal( t({}), false, \"Empty object\");\n\tequal( t(function(){} ), false, \"Instance of a function\");\n\tequal( t( new Date() ), false, \"Instance of a Date\");\n\tequal( t(function(){} ), false, \"Instance of a function\");\n});\n\ntest(\"isXMLDoc - HTML\", function() {\n\texpect(4);\n\n\tok( !jQuery.isXMLDoc( document ), \"HTML document\" );\n\tok( !jQuery.isXMLDoc( document.documentElement ), \"HTML documentElement\" );\n\tok( !jQuery.isXMLDoc( document.body ), \"HTML Body Element\" );\n\n\tvar body,\n\t\tiframe = document.createElement(\"iframe\");\n\tdocument.body.appendChild( iframe );\n\n\ttry {\n\t\tbody = jQuery(iframe).contents()[0];\n\n\t\ttry {\n\t\t\tok( !jQuery.isXMLDoc( body ), \"Iframe body element\" );\n\t\t} catch(e) {\n\t\t\tok( false, \"Iframe body element exception\" );\n\t\t}\n\n\t} catch(e) {\n\t\tok( true, \"Iframe body element - iframe not working correctly\" );\n\t}\n\n\tdocument.body.removeChild( iframe );\n});\n\ntest(\"XSS via location.hash\", function() {\n\texpect(1);\n\n\tstop();\n\tjQuery[\"_check9521\"] = function(x){\n\t\tok( x, \"script called from #id-like selector with inline handler\" );\n\t\tjQuery(\"#check9521\").remove();\n\t\tdelete jQuery[\"_check9521\"];\n\t\tstart();\n\t};\n\ttry {\n\t\t// This throws an error because it's processed like an id\n\t\tjQuery( \"#<img id='check9521' src='no-such-.gif' onerror='jQuery._check9521(false)'>\" ).appendTo(\"#qunit-fixture\");\n\t} catch (err) {\n\t\tjQuery[\"_check9521\"](true);\n\t}\n});\n\ntest(\"isXMLDoc - XML\", function() {\n\texpect(3);\n\tvar xml = createDashboardXML();\n\tok( jQuery.isXMLDoc( xml ), \"XML document\" );\n\tok( jQuery.isXMLDoc( xml.documentElement ), \"XML documentElement\" );\n\tok( jQuery.isXMLDoc( jQuery(\"tab\", xml)[0] ), \"XML Tab Element\" );\n});\n\ntest(\"isWindow\", function() {\n\texpect( 14 );\n\n\tok( jQuery.isWindow(window), \"window\" );\n\tok( jQuery.isWindow(document.getElementsByTagName(\"iframe\")[0].contentWindow), \"iframe.contentWindow\" );\n\tok( !jQuery.isWindow(), \"empty\" );\n\tok( !jQuery.isWindow(null), \"null\" );\n\tok( !jQuery.isWindow(undefined), \"undefined\" );\n\tok( !jQuery.isWindow(document), \"document\" );\n\tok( !jQuery.isWindow(document.documentElement), \"documentElement\" );\n\tok( !jQuery.isWindow(\"\"), \"string\" );\n\tok( !jQuery.isWindow(1), \"number\" );\n\tok( !jQuery.isWindow(true), \"boolean\" );\n\tok( !jQuery.isWindow({}), \"object\" );\n\tok( !jQuery.isWindow({ setInterval: function(){} }), \"fake window\" );\n\tok( !jQuery.isWindow(/window/), \"regexp\" );\n\tok( !jQuery.isWindow(function(){}), \"function\" );\n});\n\ntest(\"jQuery('html')\", function() {\n\texpect( 15 );\n\n\tvar s, div, j;\n\n\tQUnit.reset();\n\tjQuery[\"foo\"] = false;\n\ts = jQuery(\"<script>jQuery.foo='test';</script>\")[0];\n\tok( s, \"Creating a script\" );\n\tok( !jQuery[\"foo\"], \"Make sure the script wasn't executed prematurely\" );\n\tjQuery(\"body\").append(\"<script>jQuery.foo='test';</script>\");\n\tok( jQuery[\"foo\"], \"Executing a scripts contents in the right context\" );\n\n\t// Test multi-line HTML\n\tdiv = jQuery(\"<div>\\r\\nsome text\\n<p>some p</p>\\nmore text\\r\\n</div>\")[0];\n\tequal( div.nodeName.toUpperCase(), \"DIV\", \"Make sure we're getting a div.\" );\n\tequal( div.firstChild.nodeType, 3, \"Text node.\" );\n\tequal( div.lastChild.nodeType, 3, \"Text node.\" );\n\tequal( div.childNodes[1].nodeType, 1, \"Paragraph.\" );\n\tequal( div.childNodes[1].firstChild.nodeType, 3, \"Paragraph text.\" );\n\n\tQUnit.reset();\n\tok( jQuery(\"<link rel='stylesheet'/>\")[0], \"Creating a link\" );\n\n\tok( !jQuery(\"<script/>\")[0].parentNode, \"Create a script\" );\n\n\tok( jQuery(\"<input/>\").attr(\"type\", \"hidden\"), \"Create an input and set the type.\" );\n\n\tj = jQuery(\"<span>hi</span> there <!-- mon ami -->\");\n\tok( j.length >= 2, \"Check node,textnode,comment creation (some browsers delete comments)\" );\n\n\tok( !jQuery(\"<option>test</option>\")[0].selected, \"Make sure that options are auto-selected #2050\" );\n\n\tok( jQuery(\"<div></div>\")[0], \"Create a div with closing tag.\" );\n\tok( jQuery(\"<table></table>\")[0], \"Create a table with closing tag.\" );\n\n\t// equal( jQuery(\"element[attribute='<div></div>']\").length, 0, \"When html is within brackets, do not recognize as html.\" );\n\t// equal( jQuery(\"element[attribute=<div></div>]\").length, 0, \"When html is within brackets, do not recognize as html.\" );\n\t// equal( jQuery(\"element:not(<div></div>)\").length, 0, \"When html is within parens, do not recognize as html.\" );\n\t// equal( jQuery(\"\\\\<div\\\\>\").length, 0, \"Ignore escaped html characters\" );\n});\n\ntest(\"jQuery('massive html #7990')\", function() {\n\texpect( 3 );\n\n\tvar i,\n\t\tli = \"<li>very very very very large html string</li>\",\n\t\thtml = [\"<ul>\"];\n\n\tfor ( i = 0; i < 30000; i += 1 ) {\n\t\thtml[html.length] = li;\n\t}\n\thtml[html.length] = \"</ul>\";\n\thtml = jQuery(html.join(\"\"))[0];\n\tequal( html.nodeName.toLowerCase(), \"ul\");\n\tequal( html.firstChild.nodeName.toLowerCase(), \"li\");\n\tequal( html.childNodes.length, 30000 );\n});\n\ntest(\"jQuery('html', context)\", function() {\n\texpect(1);\n\n\tvar $div = jQuery(\"<div/>\")[0],\n\t\t$span = jQuery(\"<span/>\", $div);\n\tequal($span.length, 1, \"verify a span created with a div context works, #1763\");\n});\n\ntest(\"jQuery(selector, xml).text(str) - loaded via xml document\", function() {\n\texpect(2);\n\n\tvar xml = createDashboardXML(),\n\t// tests for #1419 where ie was a problem\n\t\ttab = jQuery(\"tab\", xml).eq(0);\n\tequal( tab.text(), \"blabla\", \"verify initial text correct\" );\n\ttab.text(\"newtext\");\n\tequal( tab.text(), \"newtext\", \"verify new text correct\" );\n});\n\ntest(\"end()\", function() {\n\texpect(3);\n\tequal( \"Yahoo\", jQuery(\"#yahoo\").parent().end().text(), \"check for end\" );\n\tok( jQuery(\"#yahoo\").end(), \"check for end with nothing to end\" );\n\n\tvar x = jQuery(\"#yahoo\");\n\tx.parent();\n\tequal( \"Yahoo\", jQuery(\"#yahoo\").text(), \"check for non-destructive behaviour\" );\n});\n\ntest(\"length\", function() {\n\texpect(1);\n\tequal( jQuery(\"#qunit-fixture p\").length, 6, \"Get Number of Elements Found\" );\n});\n\ntest(\"get()\", function() {\n\texpect(1);\n\tdeepEqual( jQuery(\"#qunit-fixture p\").get(), q(\"firstp\",\"ap\",\"sndp\",\"en\",\"sap\",\"first\"), \"Get All Elements\" );\n});\n\ntest(\"toArray()\", function() {\n\texpect(1);\n\tdeepEqual( jQuery(\"#qunit-fixture p\").toArray(),\n\t\tq(\"firstp\",\"ap\",\"sndp\",\"en\",\"sap\",\"first\"),\n\t\t\"Convert jQuery object to an Array\" );\n});\n\ntest(\"inArray()\", function() {\n\texpect(19);\n\n\tvar selections = {\n\t\tp:   q(\"firstp\", \"sap\", \"ap\", \"first\"),\n\t\tem:  q(\"siblingnext\", \"siblingfirst\"),\n\t\tdiv: q(\"qunit-testrunner-toolbar\", \"nothiddendiv\", \"nothiddendivchild\", \"foo\"),\n\t\ta:   q(\"mark\", \"groups\", \"google\", \"simon1\"),\n\t\tempty: []\n\t},\n\ttests = {\n\t\tp:    { elem: jQuery(\"#ap\")[0],           index: 2 },\n\t\tem:   { elem: jQuery(\"#siblingfirst\")[0], index: 1 },\n\t\tdiv:  { elem: jQuery(\"#nothiddendiv\")[0], index: 1 },\n\t\ta:    { elem: jQuery(\"#simon1\")[0],       index: 3 }\n\t},\n\tfalseTests = {\n\t\tp:  jQuery(\"#liveSpan1\")[0],\n\t\tem: jQuery(\"#nothiddendiv\")[0],\n\t\tempty: \"\"\n\t};\n\n\tjQuery.each( tests, function( key, obj ) {\n\t\tequal( jQuery.inArray( obj.elem, selections[ key ] ), obj.index, \"elem is in the array of selections of its tag\" );\n\t\t// Third argument (fromIndex)\n\t\tequal( !!~jQuery.inArray( obj.elem, selections[ key ], 5 ), false, \"elem is NOT in the array of selections given a starting index greater than its position\" );\n\t\tequal( !!~jQuery.inArray( obj.elem, selections[ key ], 1 ), true, \"elem is in the array of selections given a starting index less than or equal to its position\" );\n\t\tequal( !!~jQuery.inArray( obj.elem, selections[ key ], -3 ), true, \"elem is in the array of selections given a negative index\" );\n\t});\n\n\tjQuery.each( falseTests, function( key, elem ) {\n\t\tequal( !!~jQuery.inArray( elem, selections[ key ] ), false, \"elem is NOT in the array of selections\" );\n\t});\n\n});\n\ntest(\"get(Number)\", function() {\n\texpect(2);\n\tequal( jQuery(\"#qunit-fixture p\").get(0), document.getElementById(\"firstp\"), \"Get A Single Element\" );\n\tstrictEqual( jQuery(\"#firstp\").get(1), undefined, \"Try get with index larger elements count\" );\n});\n\ntest(\"get(-Number)\",function() {\n\texpect(2);\n\tequal( jQuery(\"p\").get(-1), document.getElementById(\"first\"), \"Get a single element with negative index\" );\n\tstrictEqual( jQuery(\"#firstp\").get(-2), undefined, \"Try get with index negative index larger then elements count\" );\n});\n\ntest(\"each(Function)\", function() {\n\texpect(1);\n\tvar div, pass, i;\n\n\tdiv = jQuery(\"div\");\n\tdiv.each(function(){this.foo = \"zoo\";});\n\tpass = true;\n\tfor ( i = 0; i < div.length; i++ ) {\n\t\tif ( div.get(i).foo !== \"zoo\" ) {\n\t\t\tpass = false;\n\t\t}\n\t}\n\tok( pass, \"Execute a function, Relative\" );\n});\n\ntest(\"slice()\", function() {\n\texpect(7);\n\n\tvar $links = jQuery(\"#ap a\");\n\n\tdeepEqual( $links.slice(1,2).get(), q(\"groups\"), \"slice(1,2)\" );\n\tdeepEqual( $links.slice(1).get(), q(\"groups\", \"anchor1\", \"mark\"), \"slice(1)\" );\n\tdeepEqual( $links.slice(0,3).get(), q(\"google\", \"groups\", \"anchor1\"), \"slice(0,3)\" );\n\tdeepEqual( $links.slice(-1).get(), q(\"mark\"), \"slice(-1)\" );\n\n\tdeepEqual( $links.eq(1).get(), q(\"groups\"), \"eq(1)\" );\n\tdeepEqual( $links.eq(\"2\").get(), q(\"anchor1\"), \"eq('2')\" );\n\tdeepEqual( $links.eq(-1).get(), q(\"mark\"), \"eq(-1)\" );\n});\n\ntest(\"first()/last()\", function() {\n\texpect(4);\n\n\tvar $links = jQuery(\"#ap a\"), $none = jQuery(\"asdf\");\n\n\tdeepEqual( $links.first().get(), q(\"google\"), \"first()\" );\n\tdeepEqual( $links.last().get(), q(\"mark\"), \"last()\" );\n\n\tdeepEqual( $none.first().get(), [], \"first() none\" );\n\tdeepEqual( $none.last().get(), [], \"last() none\" );\n});\n\ntest(\"map()\", function() {\n\texpect( 2 );\n\n\tdeepEqual(\n\t\tjQuery(\"#ap\").map(function() {\n\t\t\treturn jQuery( this ).find(\"a\").get();\n\t\t}).get(),\n\t\tq( \"google\", \"groups\", \"anchor1\", \"mark\" ),\n\t\t\"Array Map\"\n\t);\n\n\tdeepEqual(\n\t\tjQuery(\"#ap > a\").map(function() {\n\t\t\treturn this.parentNode;\n\t\t}).get(),\n\t\tq( \"ap\",\"ap\",\"ap\" ),\n\t\t\"Single Map\"\n\t);\n});\n\ntest(\"jQuery.map\", function() {\n\texpect( 25 );\n\n\tvar i, label, result, callback;\n\n\tresult = jQuery.map( [ 3, 4, 5 ], function( v, k ) {\n\t\treturn k;\n\t});\n\tequal( result.join(\"\"), \"012\", \"Map the keys from an array\" );\n\n\tresult = jQuery.map( [ 3, 4, 5 ], function( v ) {\n\t\treturn v;\n\t});\n\tequal( result.join(\"\"), \"345\", \"Map the values from an array\" );\n\n\tresult = jQuery.map( { a: 1, b: 2 }, function( v, k ) {\n\t\treturn k;\n\t});\n\tequal( result.join(\"\"), \"ab\", \"Map the keys from an object\" );\n\n\tresult = jQuery.map( { a: 1, b: 2 }, function( v ) {\n\t\treturn v;\n\t});\n\tequal( result.join(\"\"), \"12\", \"Map the values from an object\" );\n\n\tresult = jQuery.map( [ \"a\", undefined, null, \"b\" ], function( v ) {\n\t\treturn v;\n\t});\n\tequal( result.join(\"\"), \"ab\", \"Array iteration does not include undefined/null results\" );\n\n\tresult = jQuery.map( { a: \"a\", b: undefined, c: null, d: \"b\" }, function( v ) {\n\t\treturn v;\n\t});\n\tequal( result.join(\"\"), \"ab\", \"Object iteration does not include undefined/null results\" );\n\n\tresult = {\n\t\tZero: function() {},\n\t\tOne: function( a ) { a = a; },\n\t\tTwo: function( a, b ) { a = a; b = b; }\n\t};\n\tcallback = function( v, k ) {\n\t\tequal( k, \"foo\", label + \"-argument function treated like object\" );\n\t};\n\tfor ( i in result ) {\n\t\tlabel = i;\n\t\tresult[ i ].foo = \"bar\";\n\t\tjQuery.map( result[ i ], callback );\n\t}\n\n\tresult = {\n\t\t\"undefined\": undefined,\n\t\t\"null\": null,\n\t\t\"false\": false,\n\t\t\"true\": true,\n\t\t\"empty string\": \"\",\n\t\t\"nonempty string\": \"string\",\n\t\t\"string \\\"0\\\"\": \"0\",\n\t\t\"negative\": -1,\n\t\t\"excess\": 1\n\t};\n\tcallback = function( v, k ) {\n\t\tequal( k, \"length\", \"Object with \" + label + \" length treated like object\" );\n\t};\n\tfor ( i in result ) {\n\t\tlabel = i;\n\t\tjQuery.map( { length: result[ i ] }, callback );\n\t}\n\n\tresult = {\n\t\t\"sparse Array\": Array( 4 ),\n\t\t\"length: 1 plain object\": { length: 1, \"0\": true },\n\t\t\"length: 2 plain object\": { length: 2, \"0\": true, \"1\": true },\n\t\tNodeList: document.getElementsByTagName(\"html\")\n\t};\n\tcallback = function( v, k ) {\n\t\tif ( result[ label ] ) {\n\t\t\tdelete result[ label ];\n\t\t\tequal( k, \"0\", label + \" treated like array\" );\n\t\t}\n\t};\n\tfor ( i in result ) {\n\t\tlabel = i;\n\t\tjQuery.map( result[ i ], callback );\n\t}\n\n\tresult = false;\n\tjQuery.map( { length: 0 }, function() {\n\t\tresult = true;\n\t});\n\tok( !result, \"length: 0 plain object treated like array\" );\n\n\tresult = false;\n\tjQuery.map( document.getElementsByTagName(\"asdf\"), function() {\n\t\tresult = true;\n\t});\n\tok( !result, \"empty NodeList treated like array\" );\n\n\tresult = jQuery.map( Array(4), function( v, k ){\n\t\treturn k % 2 ? k : [k,k,k];\n\t});\n\tequal( result.join(\"\"), \"00012223\", \"Array results flattened (#2616)\" );\n});\n\ntest(\"jQuery.merge()\", function() {\n\texpect(8);\n\n\tdeepEqual( jQuery.merge([],[]), [], \"Empty arrays\" );\n\n\tdeepEqual( jQuery.merge([ 1 ],[ 2 ]), [ 1, 2 ], \"Basic\" );\n\tdeepEqual( jQuery.merge([ 1, 2 ], [ 3, 4 ]), [ 1, 2, 3, 4 ], \"Basic\" );\n\n\tdeepEqual( jQuery.merge([ 1, 2 ],[]), [ 1, 2 ], \"Second empty\" );\n\tdeepEqual( jQuery.merge([],[ 1, 2 ]), [ 1, 2 ], \"First empty\" );\n\n\t// Fixed at [5998], #3641\n\tdeepEqual( jQuery.merge([ -2, -1 ], [ 0, 1, 2 ]), [ -2, -1 , 0, 1, 2 ],\n\t\t\"Second array including a zero (falsy)\");\n\n\t// After fixing #5527\n\tdeepEqual( jQuery.merge([], [ null, undefined ]), [ null, undefined ],\n\t\t\"Second array including null and undefined values\");\n\tdeepEqual( jQuery.merge({ length: 0 }, [ 1, 2 ] ), { length: 2, 0: 1, 1: 2},\n\t\t\"First array like\");\n});\n\ntest(\"jQuery.extend(Object, Object)\", function() {\n\texpect(28);\n\n\tvar empty, optionsWithLength, optionsWithDate, myKlass,\n\t\tcustomObject, optionsWithCustomObject, MyNumber, ret,\n\t\tnullUndef, target, recursive, obj,\n\t\tdefaults, defaultsCopy, options1, options1Copy, options2, options2Copy, merged2,\n\t\tsettings = { \"xnumber1\": 5, \"xnumber2\": 7, \"xstring1\": \"peter\", \"xstring2\": \"pan\" },\n\t\toptions = { \"xnumber2\": 1, \"xstring2\": \"x\", \"xxx\": \"newstring\" },\n\t\toptionsCopy = { \"xnumber2\": 1, \"xstring2\": \"x\", \"xxx\": \"newstring\" },\n\t\tmerged = { \"xnumber1\": 5, \"xnumber2\": 1, \"xstring1\": \"peter\", \"xstring2\": \"x\", \"xxx\": \"newstring\" },\n\t\tdeep1 = { \"foo\": { \"bar\": true } },\n\t\tdeep2 = { \"foo\": { \"baz\": true }, \"foo2\": document },\n\t\tdeep2copy = { \"foo\": { \"baz\": true }, \"foo2\": document },\n\t\tdeepmerged = { \"foo\": { \"bar\": true, \"baz\": true }, \"foo2\": document },\n\t\tarr = [1, 2, 3],\n\t\tnestedarray = { \"arr\": arr };\n\n\tjQuery.extend(settings, options);\n\tdeepEqual( settings, merged, \"Check if extended: settings must be extended\" );\n\tdeepEqual( options, optionsCopy, \"Check if not modified: options must not be modified\" );\n\n\tjQuery.extend(settings, null, options);\n\tdeepEqual( settings, merged, \"Check if extended: settings must be extended\" );\n\tdeepEqual( options, optionsCopy, \"Check if not modified: options must not be modified\" );\n\n\tjQuery.extend(true, deep1, deep2);\n\tdeepEqual( deep1[\"foo\"], deepmerged[\"foo\"], \"Check if foo: settings must be extended\" );\n\tdeepEqual( deep2[\"foo\"], deep2copy[\"foo\"], \"Check if not deep2: options must not be modified\" );\n\tequal( deep1[\"foo2\"], document, \"Make sure that a deep clone was not attempted on the document\" );\n\n\tok( jQuery.extend(true, {}, nestedarray)[\"arr\"] !== arr, \"Deep extend of object must clone child array\" );\n\n\t// #5991\n\tok( jQuery.isArray( jQuery.extend(true, { \"arr\": {} }, nestedarray)[\"arr\"] ), \"Cloned array have to be an Array\" );\n\tok( jQuery.isPlainObject( jQuery.extend(true, { \"arr\": arr }, { \"arr\": {} })[\"arr\"] ), \"Cloned object have to be an plain object\" );\n\n\tempty = {};\n\toptionsWithLength = { \"foo\": { \"length\": -1 } };\n\tjQuery.extend(true, empty, optionsWithLength);\n\tdeepEqual( empty[\"foo\"], optionsWithLength[\"foo\"], \"The length property must copy correctly\" );\n\n\tempty = {};\n\toptionsWithDate = { \"foo\": { \"date\": new Date() } };\n\tjQuery.extend(true, empty, optionsWithDate);\n\tdeepEqual( empty[\"foo\"], optionsWithDate[\"foo\"], \"Dates copy correctly\" );\n\n\t/** @constructor */\n\tmyKlass = function() {};\n\tcustomObject = new myKlass();\n\toptionsWithCustomObject = { \"foo\": { \"date\": customObject } };\n\tempty = {};\n\tjQuery.extend(true, empty, optionsWithCustomObject);\n\tok( empty[\"foo\"] && empty[\"foo\"][\"date\"] === customObject, \"Custom objects copy correctly (no methods)\" );\n\n\t// Makes the class a little more realistic\n\tmyKlass.prototype = { \"someMethod\": function(){} };\n\tempty = {};\n\tjQuery.extend(true, empty, optionsWithCustomObject);\n\tok( empty[\"foo\"] && empty[\"foo\"][\"date\"] === customObject, \"Custom objects copy correctly\" );\n\n\tMyNumber = Number;\n\n\tret = jQuery.extend(true, { \"foo\": 4 }, { \"foo\": new MyNumber(5) } );\n\tok( parseInt(ret.foo, 10) === 5, \"Wrapped numbers copy correctly\" );\n\n\tnullUndef;\n\tnullUndef = jQuery.extend({}, options, { \"xnumber2\": null });\n\tok( nullUndef[\"xnumber2\"] === null, \"Check to make sure null values are copied\");\n\n\tnullUndef = jQuery.extend({}, options, { \"xnumber2\": undefined });\n\tok( nullUndef[\"xnumber2\"] === options[\"xnumber2\"], \"Check to make sure undefined values are not copied\");\n\n\tnullUndef = jQuery.extend({}, options, { \"xnumber0\": null });\n\tok( nullUndef[\"xnumber0\"] === null, \"Check to make sure null values are inserted\");\n\n\ttarget = {};\n\trecursive = { foo:target, bar:5 };\n\tjQuery.extend(true, target, recursive);\n\tdeepEqual( target, { bar:5 }, \"Check to make sure a recursive obj doesn't go never-ending loop by not copying it over\" );\n\n\tret = jQuery.extend(true, { foo: [] }, { foo: [0] } ); // 1907\n\tequal( ret.foo.length, 1, \"Check to make sure a value with coercion 'false' copies over when necessary to fix #1907\" );\n\n\tret = jQuery.extend(true, { foo: \"1,2,3\" }, { foo: [1, 2, 3] } );\n\tok( typeof ret.foo !== \"string\", \"Check to make sure values equal with coercion (but not actually equal) overwrite correctly\" );\n\n\tret = jQuery.extend(true, { foo:\"bar\" }, { foo:null } );\n\tok( typeof ret.foo !== \"undefined\", \"Make sure a null value doesn't crash with deep extend, for #1908\" );\n\n\tobj = { foo:null };\n\tjQuery.extend(true, obj, { foo:\"notnull\" } );\n\tequal( obj.foo, \"notnull\", \"Make sure a null value can be overwritten\" );\n\n\tfunction func() {}\n\tjQuery.extend(func, { key: \"value\" } );\n\tequal( func.key, \"value\", \"Verify a function can be extended\" );\n\n\tdefaults = { xnumber1: 5, xnumber2: 7, xstring1: \"peter\", xstring2: \"pan\" };\n\tdefaultsCopy = { xnumber1: 5, xnumber2: 7, xstring1: \"peter\", xstring2: \"pan\" };\n\toptions1 = { xnumber2: 1, xstring2: \"x\" };\n\toptions1Copy = { xnumber2: 1, xstring2: \"x\" };\n\toptions2 = { xstring2: \"xx\", xxx: \"newstringx\" };\n\toptions2Copy = { xstring2: \"xx\", xxx: \"newstringx\" };\n\tmerged2 = { xnumber1: 5, xnumber2: 1, xstring1: \"peter\", xstring2: \"xx\", xxx: \"newstringx\" };\n\n\tsettings = jQuery.extend({}, defaults, options1, options2);\n\tdeepEqual( settings, merged2, \"Check if extended: settings must be extended\" );\n\tdeepEqual( defaults, defaultsCopy, \"Check if not modified: options1 must not be modified\" );\n\tdeepEqual( options1, options1Copy, \"Check if not modified: options1 must not be modified\" );\n\tdeepEqual( options2, options2Copy, \"Check if not modified: options2 must not be modified\" );\n});\n\ntest(\"jQuery.extend(true,{},{a:[], o:{}}); deep copy with array, followed by object\", function() {\n\texpect(2);\n\n\tvar result, initial = {\n\t\t// This will make \"copyIsArray\" true\n\t\tarray: [ 1, 2, 3, 4 ],\n\t\t// If \"copyIsArray\" doesn't get reset to false, the check\n\t\t// will evaluate true and enter the array copy block\n\t\t// instead of the object copy block. Since the ternary in the\n\t\t// \"copyIsArray\" block will will evaluate to false\n\t\t// (check if operating on an array with ), this will be\n\t\t// replaced by an empty array.\n\t\tobject: {}\n\t};\n\n\tresult = jQuery.extend( true, {}, initial );\n\n\tdeepEqual( result, initial, \"The [result] and [initial] have equal shape and values\" );\n\tok( !jQuery.isArray( result.object ), \"result.object wasn't paved with an empty array\" );\n});\n\ntest(\"jQuery.each(Object,Function)\", function() {\n\texpect( 23 );\n\n\tvar i, label, seen, callback;\n\n\tseen = {};\n\tjQuery.each( [ 3, 4, 5 ], function( k, v ) {\n\t\tseen[ k ] = v;\n\t});\n\tdeepEqual( seen, { \"0\": 3, \"1\": 4, \"2\": 5 }, \"Array iteration\" );\n\n\tseen = {};\n\tjQuery.each( { name: \"name\", lang: \"lang\" }, function( k, v ) {\n\t\tseen[ k ] = v;\n\t});\n\tdeepEqual( seen, { name: \"name\", lang: \"lang\" }, \"Object iteration\" );\n\n\tseen = [];\n\tjQuery.each( [ 1, 2, 3 ], function( k, v ) {\n\t\tseen.push( v );\n\t\tif ( k === 1 ) {\n\t\t\treturn false;\n\t\t}\n\t});\n\tdeepEqual( seen, [ 1, 2 ] , \"Broken array iteration\" );\n\n\tseen = [];\n\tjQuery.each( {\"a\": 1, \"b\": 2,\"c\": 3 }, function( k, v ) {\n\t\tseen.push( v );\n\t\treturn false;\n\t});\n\tdeepEqual( seen, [ 1 ], \"Broken object iteration\" );\n\n\tseen = {\n\t\tZero: function() {},\n\t\tOne: function( a ) { a = a; },\n\t\tTwo: function( a, b ) { a = a; b = b; }\n\t};\n\tcallback = function( k ) {\n\t\tequal( k, \"foo\", label + \"-argument function treated like object\" );\n\t};\n\tfor ( i in seen ) {\n\t\tlabel = i;\n\t\tseen[ i ].foo = \"bar\";\n\t\tjQuery.each( seen[ i ], callback );\n\t}\n\n\tseen = {\n\t\t\"undefined\": undefined,\n\t\t\"null\": null,\n\t\t\"false\": false,\n\t\t\"true\": true,\n\t\t\"empty string\": \"\",\n\t\t\"nonempty string\": \"string\",\n\t\t\"string \\\"0\\\"\": \"0\",\n\t\t\"negative\": -1,\n\t\t\"excess\": 1\n\t};\n\tcallback = function( k ) {\n\t\tequal( k, \"length\", \"Object with \" + label + \" length treated like object\" );\n\t};\n\tfor ( i in seen ) {\n\t\tlabel = i;\n\t\tjQuery.each( { length: seen[ i ] }, callback );\n\t}\n\n\tseen = {\n\t\t\"sparse Array\": Array( 4 ),\n\t\t\"length: 1 plain object\": { length: 1, \"0\": true },\n\t\t\"length: 2 plain object\": { length: 2, \"0\": true, \"1\": true },\n\t\tNodeList: document.getElementsByTagName(\"html\")\n\t};\n\tcallback = function( k ) {\n\t\tif ( seen[ label ] ) {\n\t\t\tdelete seen[ label ];\n\t\t\tequal( k, \"0\", label + \" treated like array\" );\n\t\t\treturn false;\n\t\t}\n\t};\n\tfor ( i in seen ) {\n\t\tlabel = i;\n\t\tjQuery.each( seen[ i ], callback );\n\t}\n\n\tseen = false;\n\tjQuery.each( { length: 0 }, function() {\n\t\tseen = true;\n\t});\n\tok( !seen, \"length: 0 plain object treated like array\" );\n\n\tseen = false;\n\tjQuery.each( document.getElementsByTagName(\"asdf\"), function() {\n\t\tseen = true;\n\t});\n\tok( !seen, \"empty NodeList treated like array\" );\n\n\ti = 0;\n\tjQuery.each( document.styleSheets, function() {\n\t\ti++;\n\t});\n\tequal( i, 2, \"Iteration over document.styleSheets\" );\n});\n\ntest(\"jQuery.makeArray\", function(){\n\texpect(15);\n\n\tequal( jQuery.makeArray(jQuery(\"html>*\"))[0].nodeName.toUpperCase(), \"HEAD\", \"Pass makeArray a jQuery object\" );\n\n\tequal( jQuery.makeArray(document.getElementsByName(\"PWD\")).slice(0,1)[0].name, \"PWD\", \"Pass makeArray a nodelist\" );\n\n\tequal( (function() { return jQuery.makeArray(arguments); })(1,2).join(\"\"), \"12\", \"Pass makeArray an arguments array\" );\n\n\tequal( jQuery.makeArray([1,2,3]).join(\"\"), \"123\", \"Pass makeArray a real array\" );\n\n\tequal( jQuery.makeArray().length, 0, \"Pass nothing to makeArray and expect an empty array\" );\n\n\tequal( jQuery.makeArray( 0 )[0], 0 , \"Pass makeArray a number\" );\n\n\tequal( jQuery.makeArray( \"foo\" )[0], \"foo\", \"Pass makeArray a string\" );\n\n\tequal( jQuery.makeArray( true )[0].constructor, Boolean, \"Pass makeArray a boolean\" );\n\n\tequal( jQuery.makeArray( document.createElement(\"div\") )[0].nodeName.toUpperCase(), \"DIV\", \"Pass makeArray a single node\" );\n\n\tequal( jQuery.makeArray( {length:2, 0:\"a\", 1:\"b\"} ).join(\"\"), \"ab\", \"Pass makeArray an array like map (with length)\" );\n\n\tok( !!jQuery.makeArray( document.documentElement.childNodes ).slice(0,1)[0].nodeName, \"Pass makeArray a childNodes array\" );\n\n\t// function, is tricky as it has length\n\tequal( jQuery.makeArray( function(){ return 1;} )[0](), 1, \"Pass makeArray a function\" );\n\n\t//window, also has length\n\tequal( jQuery.makeArray(window)[0], window, \"Pass makeArray the window\" );\n\n\tequal( jQuery.makeArray(/a/)[0].constructor, RegExp, \"Pass makeArray a regex\" );\n\n\t// Some nodes inherit traits of nodelists\n\tok( jQuery.makeArray(document.getElementById(\"form\")).length >= 13,\n\t\t\"Pass makeArray a form (treat as elements)\" );\n});\n\ntest(\"jQuery.inArray\", function(){\n\texpect(3);\n\n\tequal( jQuery.inArray( 0, false ), -1 , \"Search in 'false' as array returns -1 and doesn't throw exception\" );\n\n\tequal( jQuery.inArray( 0, null ), -1 , \"Search in 'null' as array returns -1 and doesn't throw exception\" );\n\n\tequal( jQuery.inArray( 0, undefined ), -1 , \"Search in 'undefined' as array returns -1 and doesn't throw exception\" );\n});\n\ntest(\"jQuery.isEmptyObject\", function(){\n\texpect(2);\n\n\tequal(true, jQuery.isEmptyObject({}), \"isEmptyObject on empty object literal\" );\n\tequal(false, jQuery.isEmptyObject({a:1}), \"isEmptyObject on non-empty object literal\" );\n\n\t// What about this ?\n\t// equal(true, jQuery.isEmptyObject(null), \"isEmptyObject on null\" );\n});\n\ntest(\"jQuery.proxy\", function(){\n\texpect( 9 );\n\n\tvar test2, test3, test4, fn, cb,\n\t\ttest = function(){ equal( this, thisObject, \"Make sure that scope is set properly.\" ); },\n\t\tthisObject = { foo: \"bar\", method: test };\n\n\t// Make sure normal works\n\ttest.call( thisObject );\n\n\t// Basic scoping\n\tjQuery.proxy( test, thisObject )();\n\n\t// Another take on it\n\tjQuery.proxy( thisObject, \"method\" )();\n\n\t// Make sure it doesn't freak out\n\tequal( jQuery.proxy( null, thisObject ), undefined, \"Make sure no function was returned.\" );\n\n\t// Partial application\n\ttest2 = function( a ){ equal( a, \"pre-applied\", \"Ensure arguments can be pre-applied.\" ); };\n\tjQuery.proxy( test2, null, \"pre-applied\" )();\n\n\t// Partial application w/ normal arguments\n\ttest3 = function( a, b ){ equal( b, \"normal\", \"Ensure arguments can be pre-applied and passed as usual.\" ); };\n\tjQuery.proxy( test3, null, \"pre-applied\" )( \"normal\" );\n\n\t// Test old syntax\n\ttest4 = { \"meth\": function( a ){ equal( a, \"boom\", \"Ensure old syntax works.\" ); } };\n\tjQuery.proxy( test4, \"meth\" )( \"boom\" );\n\n\t// jQuery 1.9 improved currying with `this` object\n\tfn = function() {\n\t\tequal( Array.prototype.join.call( arguments, \",\" ), \"arg1,arg2,arg3\", \"args passed\" );\n\t\tequal( this.foo, \"bar\", \"this-object passed\" );\n\t};\n\tcb = jQuery.proxy( fn, null, \"arg1\", \"arg2\" );\n\tcb.call( thisObject, \"arg3\" );\n});\n\ntest(\"jQuery.parseHTML\", function() {\n\texpect( 18 );\n\n\tvar html, nodes;\n\n\tequal( jQuery.parseHTML(), null, \"Nothing in, null out.\" );\n\tequal( jQuery.parseHTML( null ), null, \"Null in, null out.\" );\n\tequal( jQuery.parseHTML( \"\" ), null, \"Empty string in, null out.\" );\n\traises(function() {\n\t\tjQuery.parseHTML( \"<div></div>\", document.getElementById(\"form\") );\n\t}, \"Passing an element as the context raises an exception (context should be a document)\");\n\n\tnodes = jQuery.parseHTML( jQuery(\"body\")[0].innerHTML );\n\tok( nodes.length > 4, \"Parse a large html string\" );\n\tequal( jQuery.type( nodes ), \"array\", \"parseHTML returns an array rather than a nodelist\" );\n\n\thtml = \"<script>undefined()</script>\";\n\tequal( jQuery.parseHTML( html ).length, 0, \"Ignore scripts by default\" );\n\tequal( jQuery.parseHTML( html, true )[0].nodeName.toLowerCase(), \"script\", \"Preserve scripts when requested\" );\n\n\thtml += \"<div></div>\";\n\tequal( jQuery.parseHTML( html )[0].nodeName.toLowerCase(), \"div\", \"Preserve non-script nodes\" );\n\tequal( jQuery.parseHTML( html, true )[0].nodeName.toLowerCase(), \"script\", \"Preserve script position\");\n\n\tequal( jQuery.parseHTML(\"text\")[0].nodeType, 3, \"Parsing text returns a text node\" );\n\tequal( jQuery.parseHTML( \"\\t<div></div>\" )[0].nodeValue, \"\\t\", \"Preserve leading whitespace\" );\n\n\tequal( jQuery.parseHTML(\" <div/> \")[0].nodeType, 3, \"Leading spaces are treated as text nodes (#11290)\" );\n\n\thtml = jQuery.parseHTML( \"<div>test div</div>\" );\n\n\tequal( html[ 0 ].parentNode.nodeType, 11, \"parentNode should be documentFragment\" );\n\tequal( html[ 0 ].innerHTML, \"test div\", \"Content should be preserved\" );\n\n\tequal( jQuery.parseHTML(\"<span><span>\").length, 1, \"Incorrect html-strings should not break anything\" );\n\tequal( jQuery.parseHTML(\"<td><td>\")[ 1 ].parentNode.nodeType, 11,\n\t\t\"parentNode should be documentFragment for wrapMap (variable in manipulation module) elements too\" );\n\tok( jQuery.parseHTML(\"<#if><tr><p>This is a test.</p></tr><#/if>\") || true, \"Garbage input should not cause error\" );\n});\n\ntest(\"jQuery.parseJSON\", function(){\n\texpect( 9 );\n\n\tequal( jQuery.parseJSON( null ), null, \"Actual null returns null\" );\n\tequal( jQuery.isEmptyObject( jQuery.parseJSON(\"{}\") ), true, \"Empty object returns empty object\" );\n\tdeepEqual( jQuery.parseJSON(\"{\\\"test\\\":1}\"), { \"test\": 1 }, \"Plain object parses\" );\n\tdeepEqual( jQuery.parseJSON(\"\\n{\\\"test\\\":1}\"), { \"test\": 1 }, \"Leading whitespaces are ignored.\" );\n\traises(function() {\n\t\tjQuery.parseJSON();\n\t}, null, \"Undefined raises an error\" );\n\traises( function() {\n\t\tjQuery.parseJSON( \"\" );\n\t}, null, \"Empty string raises an error\" );\n\traises(function() {\n\t\tjQuery.parseJSON(\"''\");\n\t}, null, \"Single-quoted string raises an error\" );\n\traises(function() {\n\t\tjQuery.parseJSON(\"{a:1}\");\n\t}, null, \"Unquoted property raises an error\" );\n\traises(function() {\n\t\tjQuery.parseJSON(\"{'a':1}\");\n\t}, null, \"Single-quoted property raises an error\" );\n});\n\ntest(\"jQuery.parseXML\", 8, function(){\n\tvar xml, tmp;\n\ttry {\n\t\txml = jQuery.parseXML( \"<p>A <b>well-formed</b> xml string</p>\" );\n\t\ttmp = xml.getElementsByTagName( \"p\" )[ 0 ];\n\t\tok( !!tmp, \"<p> present in document\" );\n\t\ttmp = tmp.getElementsByTagName( \"b\" )[ 0 ];\n\t\tok( !!tmp, \"<b> present in document\" );\n\t\tstrictEqual( tmp.childNodes[ 0 ].nodeValue, \"well-formed\", \"<b> text is as expected\" );\n\t} catch (e) {\n\t\tstrictEqual( e, undefined, \"unexpected error\" );\n\t}\n\ttry {\n\t\txml = jQuery.parseXML( \"<p>Not a <<b>well-formed</b> xml string</p>\" );\n\t\tok( false, \"invalid xml not detected\" );\n\t} catch( e ) {\n\t\tstrictEqual( e.message, \"Invalid XML: <p>Not a <<b>well-formed</b> xml string</p>\", \"invalid xml detected\" );\n\t}\n\ttry {\n\t\txml = jQuery.parseXML( \"\" );\n\t\tstrictEqual( xml, null, \"empty string => null document\" );\n\t\txml = jQuery.parseXML();\n\t\tstrictEqual( xml, null, \"undefined string => null document\" );\n\t\txml = jQuery.parseXML( null );\n\t\tstrictEqual( xml, null, \"null string => null document\" );\n\t\txml = jQuery.parseXML( true );\n\t\tstrictEqual( xml, null, \"non-string => null document\" );\n\t} catch( e ) {\n\t\tok( false, \"empty input throws exception\" );\n\t}\n});\n\ntest(\"jQuery.camelCase()\", function() {\n\n\tvar tests = {\n\t\t\"foo-bar\": \"fooBar\",\n\t\t\"foo-bar-baz\": \"fooBarBaz\",\n\t\t\"girl-u-want\": \"girlUWant\",\n\t\t\"the-4th-dimension\": \"the4thDimension\",\n\t\t\"-o-tannenbaum\": \"OTannenbaum\",\n\t\t\"-moz-illa\": \"MozIlla\",\n\t\t\"-ms-take\": \"msTake\"\n\t};\n\n\texpect(7);\n\n\tjQuery.each( tests, function( key, val ) {\n\t\tequal( jQuery.camelCase( key ), val, \"Converts: \" + key + \" => \" + val );\n\t});\n});\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/jquery/test/unit/css.js",
    "content": "if ( jQuery.css ) {\n\nmodule(\"css\", { teardown: moduleTeardown });\n\ntest(\"css(String|Hash)\", function() {\n\texpect( 40 );\n\n\tequal( jQuery(\"#qunit-fixture\").css(\"display\"), \"block\", \"Check for css property \\\"display\\\"\" );\n\n\tvar $child, div, div2, width, height, child, prctval, checkval, old;\n\n\t$child = jQuery(\"#nothiddendivchild\").css({ \"width\": \"20%\", \"height\": \"20%\" });\n\tnotEqual( $child.css(\"width\"), \"20px\", \"Retrieving a width percentage on the child of a hidden div returns percentage\" );\n\tnotEqual( $child.css(\"height\"), \"20px\", \"Retrieving a height percentage on the child of a hidden div returns percentage\" );\n\n\tdiv = jQuery( \"<div>\" );\n\n\t// These should be \"auto\" (or some better value)\n\t// temporarily provide \"0px\" for backwards compat\n\tequal( div.css(\"width\"), \"0px\", \"Width on disconnected node.\" );\n\tequal( div.css(\"height\"), \"0px\", \"Height on disconnected node.\" );\n\n\tdiv.css({ \"width\": 4, \"height\": 4 });\n\n\tequal( div.css(\"width\"), \"4px\", \"Width on disconnected node.\" );\n\tequal( div.css(\"height\"), \"4px\", \"Height on disconnected node.\" );\n\n\tdiv2 = jQuery( \"<div style='display:none;'><input type='text' style='height:20px;'/><textarea style='height:20px;'/><div style='height:20px;'></div></div>\").appendTo(\"body\");\n\n\tequal( div2.find(\"input\").css(\"height\"), \"20px\", \"Height on hidden input.\" );\n\tequal( div2.find(\"textarea\").css(\"height\"), \"20px\", \"Height on hidden textarea.\" );\n\tequal( div2.find(\"div\").css(\"height\"), \"20px\", \"Height on hidden textarea.\" );\n\n\tdiv2.remove();\n\n\t// handle negative numbers by setting to zero #11604\n\tjQuery(\"#nothiddendiv\").css( {\"width\": 1, \"height\": 1} );\n\n\twidth = parseFloat(jQuery(\"#nothiddendiv\").css(\"width\"));\n\theight = parseFloat(jQuery(\"#nothiddendiv\").css(\"height\"));\n\tjQuery(\"#nothiddendiv\").css({ \"overflow\":\"hidden\", \"width\": -1, \"height\": -1 });\n\tequal( parseFloat(jQuery(\"#nothiddendiv\").css(\"width\")), 0, \"Test negative width set to 0\");\n\tequal( parseFloat(jQuery(\"#nothiddendiv\").css(\"height\")), 0, \"Test negative height set to 0\");\n\n\tequal( jQuery(\"<div style='display: none;'>\").css(\"display\"), \"none\", \"Styles on disconnected nodes\");\n\n\tjQuery(\"#floatTest\").css({\"float\": \"right\"});\n\tequal( jQuery(\"#floatTest\").css(\"float\"), \"right\", \"Modified CSS float using \\\"float\\\": Assert float is right\");\n\tjQuery(\"#floatTest\").css({\"font-size\": \"30px\"});\n\tequal( jQuery(\"#floatTest\").css(\"font-size\"), \"30px\", \"Modified CSS font-size: Assert font-size is 30px\");\n\tjQuery.each(\"0,0.25,0.5,0.75,1\".split(\",\"), function(i, n) {\n\t\tjQuery(\"#foo\").css({\"opacity\": n});\n\n\t\tequal( jQuery(\"#foo\").css(\"opacity\"), parseFloat(n), \"Assert opacity is \" + parseFloat(n) + \" as a String\" );\n\t\tjQuery(\"#foo\").css({\"opacity\": parseFloat(n)});\n\t\tequal( jQuery(\"#foo\").css(\"opacity\"), parseFloat(n), \"Assert opacity is \" + parseFloat(n) + \" as a Number\" );\n\t});\n\tjQuery(\"#foo\").css({\"opacity\": \"\"});\n\tequal( jQuery(\"#foo\").css(\"opacity\"), \"1\", \"Assert opacity is 1 when set to an empty String\" );\n\n\tequal( jQuery(\"#empty\").css(\"opacity\"), \"0\", \"Assert opacity is accessible via filter property set in stylesheet in IE\" );\n\tjQuery(\"#empty\").css({ \"opacity\": \"1\" });\n\tequal( jQuery(\"#empty\").css(\"opacity\"), \"1\", \"Assert opacity is taken from style attribute when set vs stylesheet in IE with filters\" );\n\n\tdiv = jQuery(\"#nothiddendiv\");\n\tchild = jQuery(\"#nothiddendivchild\");\n\n\tequal( parseInt(div.css(\"fontSize\"), 10), 16, \"Verify fontSize px set.\" );\n\tequal( parseInt(div.css(\"font-size\"), 10), 16, \"Verify fontSize px set.\" );\n\tequal( parseInt(child.css(\"fontSize\"), 10), 16, \"Verify fontSize px set.\" );\n\tequal( parseInt(child.css(\"font-size\"), 10), 16, \"Verify fontSize px set.\" );\n\n\tchild.css(\"height\", \"100%\");\n\tequal( child[0].style.height, \"100%\", \"Make sure the height is being set correctly.\" );\n\n\tchild.attr(\"class\", \"em\");\n\tequal( parseInt(child.css(\"fontSize\"), 10), 32, \"Verify fontSize em set.\" );\n\n\t// Have to verify this as the result depends upon the browser's CSS\n\t// support for font-size percentages\n\tchild.attr(\"class\", \"prct\");\n\tprctval = parseInt(child.css(\"fontSize\"), 10);\n\tcheckval = 0;\n\tif ( prctval === 16 || prctval === 24 ) {\n\t\tcheckval = prctval;\n\t}\n\n\tequal( prctval, checkval, \"Verify fontSize % set.\" );\n\n\tequal( typeof child.css(\"width\"), \"string\", \"Make sure that a string width is returned from css('width').\" );\n\n\told = child[0].style.height;\n\n\t// Test NaN\n\tchild.css(\"height\", parseFloat(\"zoo\"));\n\tequal( child[0].style.height, old, \"Make sure height isn't changed on NaN.\" );\n\n\t// Test null\n\tchild.css(\"height\", null);\n\tequal( child[0].style.height, old, \"Make sure height isn't changed on null.\" );\n\n\told = child[0].style.fontSize;\n\n\t// Test NaN\n\tchild.css(\"font-size\", parseFloat(\"zoo\"));\n\tequal( child[0].style.fontSize, old, \"Make sure font-size isn't changed on NaN.\" );\n\n\t// Test null\n\tchild.css(\"font-size\", null);\n\tequal( child[0].style.fontSize, old, \"Make sure font-size isn't changed on null.\" );\n});\n\ntest(\"css() explicit and relative values\", function() {\n\texpect( 30 );\n\tvar $elem = jQuery(\"#nothiddendiv\");\n\n\t$elem.css({ \"width\": 1, \"height\": 1, \"paddingLeft\": \"1px\", \"opacity\": 1 });\n\tequal( $elem.css(\"width\"), \"1px\", \"Initial css set or width/height works (hash)\" );\n\tequal( $elem.css(\"paddingLeft\"), \"1px\", \"Initial css set of paddingLeft works (hash)\" );\n\tequal( $elem.css(\"opacity\"), \"1\", \"Initial css set of opacity works (hash)\" );\n\n\t$elem.css({ width: \"+=9\" });\n\tequal( $elem.css(\"width\"), \"10px\", \"'+=9' on width (hash)\" );\n\n\t$elem.css({ \"width\": \"-=9\" });\n\tequal( $elem.css(\"width\"), \"1px\", \"'-=9' on width (hash)\" );\n\n\t$elem.css({ \"width\": \"+=9px\" });\n\tequal( $elem.css(\"width\"), \"10px\", \"'+=9px' on width (hash)\" );\n\n\t$elem.css({ \"width\": \"-=9px\" });\n\tequal( $elem.css(\"width\"), \"1px\", \"'-=9px' on width (hash)\" );\n\n\t$elem.css( \"width\", \"+=9\" );\n\tequal( $elem.css(\"width\"), \"10px\", \"'+=9' on width (params)\" );\n\n\t$elem.css( \"width\", \"-=9\" ) ;\n\tequal( $elem.css(\"width\"), \"1px\", \"'-=9' on width (params)\" );\n\n\t$elem.css( \"width\", \"+=9px\" );\n\tequal( $elem.css(\"width\"), \"10px\", \"'+=9px' on width (params)\" );\n\n\t$elem.css( \"width\", \"-=9px\" );\n\tequal( $elem.css(\"width\"), \"1px\", \"'-=9px' on width (params)\" );\n\n\t$elem.css( \"width\", \"-=-9px\" );\n\tequal( $elem.css(\"width\"), \"10px\", \"'-=-9px' on width (params)\" );\n\n\t$elem.css( \"width\", \"+=-9px\" );\n\tequal( $elem.css(\"width\"), \"1px\", \"'+=-9px' on width (params)\" );\n\n\t$elem.css({ \"paddingLeft\": \"+=4\" });\n\tequal( $elem.css(\"paddingLeft\"), \"5px\", \"'+=4' on paddingLeft (hash)\" );\n\n\t$elem.css({ \"paddingLeft\": \"-=4\" });\n\tequal( $elem.css(\"paddingLeft\"), \"1px\", \"'-=4' on paddingLeft (hash)\" );\n\n\t$elem.css({ \"paddingLeft\": \"+=4px\" });\n\tequal( $elem.css(\"paddingLeft\"), \"5px\", \"'+=4px' on paddingLeft (hash)\" );\n\n\t$elem.css({ \"paddingLeft\": \"-=4px\" });\n\tequal( $elem.css(\"paddingLeft\"), \"1px\", \"'-=4px' on paddingLeft (hash)\" );\n\n\t$elem.css({ \"padding-left\": \"+=4\" });\n\tequal( $elem.css(\"paddingLeft\"), \"5px\", \"'+=4' on padding-left (hash)\" );\n\n\t$elem.css({ \"padding-left\": \"-=4\" });\n\tequal( $elem.css(\"paddingLeft\"), \"1px\", \"'-=4' on padding-left (hash)\" );\n\n\t$elem.css({ \"padding-left\": \"+=4px\" });\n\tequal( $elem.css(\"paddingLeft\"), \"5px\", \"'+=4px' on padding-left (hash)\" );\n\n\t$elem.css({ \"padding-left\": \"-=4px\" });\n\tequal( $elem.css(\"paddingLeft\"), \"1px\", \"'-=4px' on padding-left (hash)\" );\n\n\t$elem.css( \"paddingLeft\", \"+=4\" );\n\tequal( $elem.css(\"paddingLeft\"), \"5px\", \"'+=4' on paddingLeft (params)\" );\n\n\t$elem.css( \"paddingLeft\", \"-=4\" );\n\tequal( $elem.css(\"paddingLeft\"), \"1px\", \"'-=4' on paddingLeft (params)\" );\n\n\t$elem.css( \"padding-left\", \"+=4px\" );\n\tequal( $elem.css(\"paddingLeft\"), \"5px\", \"'+=4px' on padding-left (params)\" );\n\n\t$elem.css( \"padding-left\", \"-=4px\" );\n\tequal( $elem.css(\"paddingLeft\"), \"1px\", \"'-=4px' on padding-left (params)\" );\n\n\t$elem.css({ \"opacity\": \"-=0.5\" });\n\tequal( $elem.css(\"opacity\"), \"0.5\", \"'-=0.5' on opacity (hash)\" );\n\n\t$elem.css({ \"opacity\": \"+=0.5\" });\n\tequal( $elem.css(\"opacity\"), \"1\", \"'+=0.5' on opacity (hash)\" );\n\n\t$elem.css( \"opacity\", \"-=0.5\" );\n\tequal( $elem.css(\"opacity\"), \"0.5\", \"'-=0.5' on opacity (params)\" );\n\n\t$elem.css( \"opacity\", \"+=0.5\" );\n\tequal( $elem.css(\"opacity\"), \"1\", \"'+=0.5' on opacity (params)\" );\n\n\t$elem.css( \"order\", 2 );\n\tequal( $elem.css(\"order\"), \"2\", \"2 on order\" );\n});\n\ntest(\"css(String, Object)\", function() {\n\texpect( 19 );\n\tvar j, div, display, ret, success;\n\n\tjQuery(\"#nothiddendiv\").css(\"top\", \"-1em\");\n\tok( jQuery(\"#nothiddendiv\").css(\"top\"), -16, \"Check negative number in EMs.\" );\n\n\tjQuery(\"#floatTest\").css(\"float\", \"left\");\n\tequal( jQuery(\"#floatTest\").css(\"float\"), \"left\", \"Modified CSS float using \\\"float\\\": Assert float is left\");\n\tjQuery(\"#floatTest\").css(\"font-size\", \"20px\");\n\tequal( jQuery(\"#floatTest\").css(\"font-size\"), \"20px\", \"Modified CSS font-size: Assert font-size is 20px\");\n\n\tjQuery.each(\"0,0.25,0.5,0.75,1\".split(\",\"), function(i, n) {\n\t\tjQuery(\"#foo\").css(\"opacity\", n);\n\t\tequal( jQuery(\"#foo\").css(\"opacity\"), parseFloat(n), \"Assert opacity is \" + parseFloat(n) + \" as a String\" );\n\t\tjQuery(\"#foo\").css(\"opacity\", parseFloat(n));\n\t\tequal( jQuery(\"#foo\").css(\"opacity\"), parseFloat(n), \"Assert opacity is \" + parseFloat(n) + \" as a Number\" );\n\t});\n\tjQuery(\"#foo\").css(\"opacity\", \"\");\n\tequal( jQuery(\"#foo\").css(\"opacity\"), \"1\", \"Assert opacity is 1 when set to an empty String\" );\n\n\t// using contents will get comments regular, text, and comment nodes\n\tj = jQuery(\"#nonnodes\").contents();\n\tj.css(\"overflow\", \"visible\");\n\tequal( j.css(\"overflow\"), \"visible\", \"Check node,textnode,comment css works\" );\n\t// opera sometimes doesn't update 'display' correctly, see #2037\n\tjQuery(\"#t2037\")[0].innerHTML = jQuery(\"#t2037\")[0].innerHTML;\n\tequal( jQuery(\"#t2037 .hidden\").css(\"display\"), \"none\", \"Make sure browser thinks it is hidden\" );\n\n\tdiv = jQuery(\"#nothiddendiv\");\n\tdisplay = div.css(\"display\");\n\tret = div.css(\"display\", undefined);\n\n\tequal( ret, div, \"Make sure setting undefined returns the original set.\" );\n\tequal( div.css(\"display\"), display, \"Make sure that the display wasn't changed.\" );\n\n\t// Test for Bug #5509\n\tsuccess = true;\n\ttry {\n\t\tjQuery(\"#foo\").css(\"backgroundColor\", \"rgba(0, 0, 0, 0.1)\");\n\t}\n\tcatch (e) {\n\t\tsuccess = false;\n\t}\n\tok( success, \"Setting RGBA values does not throw Error\" );\n});\n\ntest( \"css(Array)\", function() {\n\texpect( 2 );\n\n\tvar expectedMany = {\n\t\t\t\"overflow\": \"visible\",\n\t\t\t\"width\": \"16px\"\n\t\t},\n\t\texpectedSingle = {\n\t\t\t\"width\": \"16px\"\n\t\t},\n\t\telem = jQuery(\"<div></div>\").appendTo(\"#qunit-fixture\");\n\n\tdeepEqual( elem.css( expectedMany ).css([ \"overflow\", \"width\" ]), expectedMany, \"Getting multiple element array\" );\n\tdeepEqual( elem.css( expectedSingle ).css([ \"width\" ]), expectedSingle, \"Getting single element array\" );\n});\n\ntest(\"css(String, Function)\", function() {\n\texpect(3);\n\n\tvar index,\n\t\tsizes = [\"10px\", \"20px\", \"30px\"];\n\n\tjQuery(\"<div id='cssFunctionTest'><div class='cssFunction'></div>\" +\n\t\t\t\t \"<div class='cssFunction'></div>\" +\n\t\t\t\t \"<div class='cssFunction'></div></div>\")\n\t\t.appendTo(\"body\");\n\n\tindex = 0;\n\n\tjQuery(\"#cssFunctionTest div\").css(\"font-size\", function() {\n\t\tvar size = sizes[index];\n\t\tindex++;\n\t\treturn size;\n\t});\n\n\tindex = 0;\n\n\tjQuery(\"#cssFunctionTest div\").each(function() {\n\t\tvar computedSize = jQuery(this).css(\"font-size\"),\n\t\t\texpectedSize = sizes[index];\n\t\tequal( computedSize, expectedSize, \"Div #\" + index + \" should be \" + expectedSize );\n\t\tindex++;\n\t});\n\n\tjQuery(\"#cssFunctionTest\").remove();\n});\n\ntest(\"css(String, Function) with incoming value\", function() {\n\texpect(3);\n\n\tvar index,\n\t\tsizes = [\"10px\", \"20px\", \"30px\"];\n\n\tjQuery(\"<div id='cssFunctionTest'><div class='cssFunction'></div>\" +\n\t\t\t\t \"<div class='cssFunction'></div>\" +\n\t\t\t\t \"<div class='cssFunction'></div></div>\")\n\t\t.appendTo(\"body\");\n\n\tindex = 0;\n\n\tjQuery(\"#cssFunctionTest div\").css(\"font-size\", function() {\n\t\tvar size = sizes[index];\n\t\tindex++;\n\t\treturn size;\n\t});\n\n\tindex = 0;\n\n\tjQuery(\"#cssFunctionTest div\").css(\"font-size\", function(i, computedSize) {\n\t\tvar expectedSize = sizes[index];\n\t\tequal( computedSize, expectedSize, \"Div #\" + index + \" should be \" + expectedSize );\n\t\tindex++;\n\t\treturn computedSize;\n\t});\n\n\tjQuery(\"#cssFunctionTest\").remove();\n});\n\ntest(\"css(Object) where values are Functions\", function() {\n\texpect(3);\n\n\tvar index,\n\t\tsizes = [\"10px\", \"20px\", \"30px\"];\n\n\tjQuery(\"<div id='cssFunctionTest'><div class='cssFunction'></div>\" +\n\t\t\t\t \"<div class='cssFunction'></div>\" +\n\t\t\t\t \"<div class='cssFunction'></div></div>\")\n\t\t.appendTo(\"body\");\n\n\tindex = 0;\n\n\tjQuery(\"#cssFunctionTest div\").css({\"fontSize\": function() {\n\t\tvar size = sizes[index];\n\t\tindex++;\n\t\treturn size;\n\t}});\n\n\tindex = 0;\n\n\tjQuery(\"#cssFunctionTest div\").each(function() {\n\t\tvar computedSize = jQuery(this).css(\"font-size\"),\n\t\t\texpectedSize = sizes[index];\n\t\tequal( computedSize, expectedSize, \"Div #\" + index + \" should be \" + expectedSize );\n\t\tindex++;\n\t});\n\n\tjQuery(\"#cssFunctionTest\").remove();\n});\n\ntest(\"css(Object) where values are Functions with incoming values\", function() {\n\texpect(3);\n\n\tvar index,\n\t\tsizes = [\"10px\", \"20px\", \"30px\"];\n\n\tjQuery(\"<div id='cssFunctionTest'><div class='cssFunction'></div>\" +\n\t\t\t\t \"<div class='cssFunction'></div>\" +\n\t\t\t\t \"<div class='cssFunction'></div></div>\")\n\t\t.appendTo(\"body\");\n\n\tindex = 0;\n\n\tjQuery(\"#cssFunctionTest div\").css({\"fontSize\": function() {\n\t\tvar size = sizes[index];\n\t\tindex++;\n\t\treturn size;\n\t}});\n\n\tindex = 0;\n\n\tjQuery(\"#cssFunctionTest div\").css({\"font-size\": function(i, computedSize) {\n\t\tvar expectedSize = sizes[index];\n\t\tequal( computedSize, expectedSize, \"Div #\" + index + \" should be \" + expectedSize );\n\t\tindex++;\n\t\treturn computedSize;\n\t}});\n\n\tjQuery(\"#cssFunctionTest\").remove();\n});\n\ntest(\"show(); hide()\", function() {\n\texpect(22);\n\n\tvar hiddendiv, div, pass, old, test;\n\n\thiddendiv = jQuery(\"div.hidden\");\n\thiddendiv.hide();\n\tequal( hiddendiv.css(\"display\"), \"none\", \"Non-detached div hidden\" );\n\thiddendiv.show();\n\tequal( hiddendiv.css(\"display\"), \"block\", \"Pre-hidden div shown\" );\n\n\tdiv = jQuery(\"<div>\").hide();\n\tequal( div.css(\"display\"), \"none\", \"Detached div hidden\" );\n\tdiv.appendTo(\"#qunit-fixture\").show();\n\tequal( div.css(\"display\"), \"block\", \"Pre-hidden div shown\" );\n\n\tQUnit.reset();\n\n\thiddendiv = jQuery(\"div.hidden\");\n\n\tequal(jQuery.css( hiddendiv[0], \"display\"), \"none\", \"hiddendiv is display: none\");\n\n\thiddendiv.css(\"display\", \"block\");\n\tequal(jQuery.css( hiddendiv[0], \"display\"), \"block\", \"hiddendiv is display: block\");\n\n\thiddendiv.show();\n\tequal(jQuery.css( hiddendiv[0], \"display\"), \"block\", \"hiddendiv is display: block\");\n\n\thiddendiv.css(\"display\",\"\");\n\n\tpass = true;\n\tdiv = jQuery(\"#qunit-fixture div\");\n\tdiv.show().each(function(){\n\t\tif ( this.style.display === \"none\" ) {\n\t\t\tpass = false;\n\t\t}\n\t});\n\tok( pass, \"Show\" );\n\n\t// #show-tests * is set display: none in CSS\n\tjQuery(\"#qunit-fixture\").append(\"<div id='show-tests'><div><p><a href='#'></a></p><code></code><pre></pre><span></span></div><table><thead><tr><th></th></tr></thead><tbody><tr><td></td></tr></tbody></table><ul><li></li></ul></div><table id='test-table'></table>\");\n\n\told = jQuery(\"#test-table\").show().css(\"display\") !== \"table\";\n\tjQuery(\"#test-table\").remove();\n\n\ttest = {\n\t\t\"div\"      : \"block\",\n\t\t\"p\"        : \"block\",\n\t\t\"a\"        : \"inline\",\n\t\t\"code\"     : \"inline\",\n\t\t\"pre\"      : \"block\",\n\t\t\"span\"     : \"inline\",\n\t\t\"table\"    : old ? \"block\" : \"table\",\n\t\t\"thead\"    : old ? \"block\" : \"table-header-group\",\n\t\t\"tbody\"    : old ? \"block\" : \"table-row-group\",\n\t\t\"tr\"       : old ? \"block\" : \"table-row\",\n\t\t\"th\"       : old ? \"block\" : \"table-cell\",\n\t\t\"td\"       : old ? \"block\" : \"table-cell\",\n\t\t\"ul\"       : \"block\",\n\t\t\"li\"       : old ? \"block\" : \"list-item\"\n\t};\n\n\tjQuery.each(test, function(selector, expected) {\n\t\tvar elem = jQuery(selector, \"#show-tests\").show();\n\t\tequal( elem.css(\"display\"), expected, \"Show using correct display type for \" + selector );\n\t});\n\n\t// Make sure that showing or hiding a text node doesn't cause an error\n\tjQuery(\"<div>test</div> text <span>test</span>\").show().remove();\n\tjQuery(\"<div>test</div> text <span>test</span>\").hide().remove();\n});\n\ntest(\"show() resolves correct default display #8099\", function() {\n\texpect(7);\n\tvar tt8099 = jQuery(\"<tt/>\").appendTo(\"body\"),\n\t\t\tdfn8099 = jQuery(\"<dfn/>\", { \"html\": \"foo\"}).appendTo(\"body\");\n\n\tequal( tt8099.css(\"display\"), \"none\", \"default display override for all tt\" );\n\tequal( tt8099.show().css(\"display\"), \"inline\", \"Correctly resolves display:inline\" );\n\n\tequal( jQuery(\"#foo\").hide().show().css(\"display\"), \"block\", \"Correctly resolves display:block after hide/show\" );\n\n\tequal( tt8099.hide().css(\"display\"), \"none\", \"default display override for all tt\" );\n\tequal( tt8099.show().css(\"display\"), \"inline\", \"Correctly resolves display:inline\" );\n\n\tequal( dfn8099.css(\"display\"), \"none\", \"default display override for all dfn\" );\n\tequal( dfn8099.show().css(\"display\"), \"inline\", \"Correctly resolves display:inline\" );\n\n\ttt8099.remove();\n\tdfn8099.remove();\n});\n\ntest( \"show() resolves correct default display for detached nodes\", function(){\n\texpect( 13 );\n\n\tvar div, span, tr, trDisplay;\n\n\tdiv = jQuery(\"<div class='hidden'>\");\n\tdiv.show().appendTo(\"#qunit-fixture\");\n\tequal( div.css(\"display\"), \"block\", \"Make sure a detached, pre-hidden( through stylesheets ) div is visible.\" );\n\n\tdiv = jQuery(\"<div style='display: none'>\");\n\tdiv.show().appendTo(\"#qunit-fixture\");\n\tequal( div.css(\"display\"), \"block\", \"Make sure a detached, pre-hidden( through inline style ) div is visible.\" );\n\n\tspan = jQuery(\"<span class='hidden'/>\");\n\tspan.show().appendTo(\"#qunit-fixture\");\n\tequal( span.css(\"display\"), \"inline\", \"Make sure a detached, pre-hidden( through stylesheets ) span has default display.\" );\n\n\tspan = jQuery(\"<span style='display: inline'/>\");\n\tspan.show().appendTo(\"#qunit-fixture\");\n\tequal( span.css(\"display\"), \"inline\", \"Make sure a detached, pre-hidden( through inline style ) span has default display.\" );\n\n\tdiv = jQuery(\"<div><div class='hidden'></div></div>\").children(\"div\");\n\tdiv.show().appendTo(\"#qunit-fixture\");\n\tequal( div.css(\"display\"), \"block\", \"Make sure a detached, pre-hidden( through stylesheets ) div inside another visible div is visible.\" );\n\n\tdiv = jQuery(\"<div><div style='display: none'></div></div>\").children(\"div\");\n\tdiv.show().appendTo(\"#qunit-fixture\");\n\tequal( div.css(\"display\"), \"block\", \"Make sure a detached, pre-hidden( through inline style ) div inside another visible div is visible.\" );\n\n\tdiv = jQuery(\"div.hidden\");\n\tdiv.detach().show();\n\tequal( div.css(\"display\"), \"block\", \"Make sure a detached( through detach() ), pre-hidden div is visible.\" );\n\tdiv.remove();\n\n\tspan = jQuery(\"<span>\");\n\tspan.appendTo(\"#qunit-fixture\").detach().show().appendTo(\"#qunit-fixture\" );\n\tequal( span.css(\"display\"), \"inline\", \"Make sure a detached( through detach() ), pre-hidden span has default display.\" );\n\tspan.remove();\n\n\tdiv = jQuery(\"<div>\");\n\tdiv.show().appendTo(\"#qunit-fixture\");\n\tok( !!div.get( 0 ).style.display, \"Make sure not hidden div has a inline style.\" );\n\tdiv.remove();\n\n\tdiv = jQuery( document.createElement(\"div\") );\n\tdiv.show().appendTo(\"#qunit-fixture\");\n\tequal( div.css(\"display\"), \"block\", \"Make sure a pre-created element has default display.\" );\n\tdiv.remove();\n\n\tdiv = jQuery(\"<div style='display: inline'/>\");\n\tdiv.show().appendTo(\"#qunit-fixture\");\n\tequal( div.css(\"display\"), \"inline\", \"Make sure that element has same display when it was created.\" );\n\tdiv.remove();\n\n\ttr = jQuery(\"<tr/>\");\n\tjQuery(\"#table\").append( tr );\n\ttrDisplay = tr.css( \"display\" );\n\ttr.detach().hide().show();\n\n\tequal( tr[ 0 ].style.display, trDisplay, \"For detached tr elements, display should always be like for attached trs\" );\n\ttr.remove();\n\n\tspan = jQuery(\"<span/>\").hide().show();\n\tequal( span[ 0 ].style.display, \"inline\", \"For detached span elements, display should always be inline\" );\n\tspan.remove();\n});\n\ntest(\"show() resolves correct default display #10227\", function() {\n\texpect(2);\n\n\tvar body = jQuery(\"body\");\n\tbody.append(\n\t\t\"<p id='ddisplay'>a<style>body{display:none}</style></p>\"\n\t);\n\n\tequal( body.css(\"display\"), \"none\", \"Initial display: none\" );\n\n\tbody.show();\n\tequal( body.css(\"display\"), \"block\", \"Correct display: block\" );\n\n\tjQuery(\"#ddisplay\").remove();\n\tQUnit.expectJqData( body[0], \"olddisplay\" );\n});\n\ntest(\"show() resolves correct default display when iframe display:none #12904\", function() {\n\texpect(2);\n\n\tvar ddisplay = jQuery(\n\t\t\"<p id='ddisplay'>a<style>p{display:none}iframe{display:none !important}</style></p>\"\n\t).appendTo(\"body\");\n\n\tequal( ddisplay.css(\"display\"), \"none\", \"Initial display: none\" );\n\n\tddisplay.show();\n\tequal( ddisplay.css(\"display\"), \"block\", \"Correct display: block\" );\n\n\tddisplay.remove();\n});\n\ntest(\"toggle()\", function() {\n\texpect(9);\n\tvar div, oldHide,\n\t\tx = jQuery(\"#foo\");\n\n\tok( x.is(\":visible\"), \"is visible\" );\n\tx.toggle();\n\tok( x.is(\":hidden\"), \"is hidden\" );\n\tx.toggle();\n\tok( x.is(\":visible\"), \"is visible again\" );\n\n\tx.toggle(true);\n\tok( x.is(\":visible\"), \"is visible\" );\n\tx.toggle(false);\n\tok( x.is(\":hidden\"), \"is hidden\" );\n\tx.toggle(true);\n\tok( x.is(\":visible\"), \"is visible again\" );\n\n\tdiv = jQuery(\"<div style='display:none'><div></div></div>\").appendTo(\"#qunit-fixture\");\n\tx = div.find(\"div\");\n\tstrictEqual( x.toggle().css( \"display\" ), \"none\", \"is hidden\" );\n\tstrictEqual( x.toggle().css( \"display\" ), \"block\", \"is visible\" );\n\n\t// Ensure hide() is called when toggled (#12148)\n\toldHide = jQuery.fn.hide;\n\tjQuery.fn.hide = function() {\n\t\tok( true, name + \" method called on toggle\" );\n\t\treturn oldHide.apply( this, arguments );\n\t};\n\tx.toggle( name === \"show\" );\n\tjQuery.fn.hide = oldHide;\n});\n\ntest(\"hide hidden elements (bug #7141)\", function() {\n\texpect(3);\n\tQUnit.reset();\n\n\tvar div = jQuery(\"<div style='display:none'></div>\").appendTo(\"#qunit-fixture\");\n\tequal( div.css(\"display\"), \"none\", \"Element is hidden by default\" );\n\tdiv.hide();\n\tok( !jQuery._data(div, \"olddisplay\"), \"olddisplay is undefined after hiding an already-hidden element\" );\n\tdiv.show();\n\tequal( div.css(\"display\"), \"block\", \"Show a double-hidden element\" );\n\n\tdiv.remove();\n});\n\ntest(\"jQuery.css(elem, 'height') doesn't clear radio buttons (bug #1095)\", function () {\n\texpect(4);\n\n\tvar $checkedtest = jQuery(\"#checkedtest\");\n\tjQuery.css($checkedtest[0], \"height\");\n\n\tok( jQuery(\"input[type='radio']\", $checkedtest).first().attr(\"checked\"), \"Check first radio still checked.\" );\n\tok( !jQuery(\"input[type='radio']\", $checkedtest).last().attr(\"checked\"), \"Check last radio still NOT checked.\" );\n\tok( jQuery(\"input[type='checkbox']\", $checkedtest).first().attr(\"checked\"), \"Check first checkbox still checked.\" );\n\tok( !jQuery(\"input[type='checkbox']\", $checkedtest).last().attr(\"checked\"), \"Check last checkbox still NOT checked.\" );\n});\n\ntest(\"internal ref to elem.runtimeStyle (bug #7608)\", function () {\n\texpect(1);\n\tvar result = true;\n\n\ttry {\n\t\tjQuery(\"#foo\").css( { \"width\": \"0%\" } ).css(\"width\");\n\t} catch (e) {\n\t\tresult = false;\n\t}\n\n\tok( result, \"elem.runtimeStyle does not throw exception\" );\n});\n\ntest(\"marginRight computed style (bug #3333)\", function() {\n\texpect(1);\n\n\tvar $div = jQuery(\"#foo\");\n\t$div.css({\n\t\t\"width\": \"1px\",\n\t\t\"marginRight\": 0\n\t});\n\n\tequal($div.css(\"marginRight\"), \"0px\", \"marginRight correctly calculated with a width and display block\");\n});\n\ntest(\"box model properties incorrectly returning % instead of px, see #10639 and #12088\", function() {\n\texpect( 2 );\n\n\tvar container = jQuery(\"<div/>\").width( 400 ).appendTo(\"#qunit-fixture\"),\n\t\tel = jQuery(\"<div/>\").css({ \"width\": \"50%\", \"marginRight\": \"50%\" }).appendTo( container ),\n\t\tel2 = jQuery(\"<div/>\").css({ \"width\": \"50%\", \"minWidth\": \"300px\", \"marginLeft\": \"25%\" }).appendTo( container );\n\n\tequal( el.css(\"marginRight\"), \"200px\", \"css('marginRight') returning % instead of px, see #10639\" );\n\tequal( el2.css(\"marginLeft\"), \"100px\", \"css('marginLeft') returning incorrect pixel value, see #12088\" );\n});\n\ntest(\"jQuery.cssProps behavior, (bug #8402)\", function() {\n\texpect( 2 );\n\n\tvar div = jQuery( \"<div>\" ).appendTo(document.body).css({\n\t\t\"position\": \"absolute\",\n\t\t\"top\": 0,\n\t\t\"left\": 10\n\t});\n\tjQuery.cssProps.top = \"left\";\n\tequal( div.css(\"top\"), \"10px\", \"the fixed property is used when accessing the computed style\");\n\tdiv.css(\"top\", \"100px\");\n\tequal( div[0].style.left, \"100px\", \"the fixed property is used when setting the style\");\n\t// cleanup jQuery.cssProps\n\tjQuery.cssProps.top = undefined;\n});\n\ntest(\"widows & orphans #8936\", function () {\n\n\tvar $p = jQuery(\"<p>\").appendTo(\"#qunit-fixture\");\n\n\tif ( \"widows\" in $p[0].style ) {\n\t\texpect(4);\n\t\t$p.css({\n\t\t\t\"widows\": 0,\n\t\t\t\"orphans\": 0\n\t\t});\n\n\t\tequal( $p.css(\"widows\") || jQuery.style( $p[0], \"widows\" ), 0, \"widows correctly start with value 0\");\n\t\tequal( $p.css(\"orphans\") || jQuery.style( $p[0], \"orphans\" ), 0, \"orphans correctly start with value 0\");\n\n\t\t$p.css({\n\t\t\t\"widows\": 3,\n\t\t\t\"orphans\": 3\n\t\t});\n\n\t\tequal( $p.css(\"widows\") || jQuery.style( $p[0], \"widows\" ), 3, \"widows correctly set to 3\");\n\t\tequal( $p.css(\"orphans\") || jQuery.style( $p[0], \"orphans\" ), 3, \"orphans correctly set to 3\");\n\t} else {\n\n\t\texpect(1);\n\t\tok( true, \"jQuery does not attempt to test for style props that definitely don't exist in older versions of IE\");\n\t}\n\n\n\t$p.remove();\n});\n\ntest(\"can't get css for disconnected in IE<9, see #10254 and #8388\", function() {\n\texpect( 2 );\n\tvar span, div;\n\n\tspan = jQuery( \"<span/>\" ).css( \"background-image\", \"url(data/1x1.jpg)\" );\n\tnotEqual( span.css( \"background-image\" ), null, \"can't get background-image in IE<9, see #10254\" );\n\n\tdiv = jQuery( \"<div/>\" ).css( \"top\", 10 );\n\tequal( div.css( \"top\" ), \"10px\", \"can't get top in IE<9, see #8388\" );\n});\n\ntest(\"can't get background-position in IE<9, see #10796\", function() {\n\tvar div = jQuery( \"<div/>\" ).appendTo( \"#qunit-fixture\" ),\n\t\tunits = [\n\t\t\t\"0 0\",\n\t\t\t\"12px 12px\",\n\t\t\t\"13px 12em\",\n\t\t\t\"12em 13px\",\n\t\t\t\"12em center\",\n\t\t\t\"+12em center\",\n\t\t\t\"12.2em center\",\n\t\t\t\"center center\"\n\t\t],\n\t\tl = units.length,\n\t\ti = 0;\n\n\texpect( l );\n\n\tfor( ; i < l; i++ ) {\n\t\tdiv.css( \"background-position\", units [ i ] );\n\t\tok( div.css( \"background-position\" ), \"can't get background-position in IE<9, see #10796\" );\n\t}\n});\n\ntest(\"percentage properties for bottom and right in IE<9 should not be incorrectly transformed to pixels, see #11311\", function() {\n\texpect( 1 );\n\tvar div = jQuery(\"<div style='position: absolute; width: 1px; height: 20px; bottom:50%;'></div>\").appendTo( \"#qunit-fixture\" );\n\tok( window.getComputedStyle || div.css( \"bottom\" ) === \"50%\", \"position properties get incorrectly transformed in IE<8, see #11311\" );\n});\n\nif ( jQuery.fn.offset ) {\n\ttest(\"percentage properties for left and top should be transformed to pixels, see #9505\", function() {\n\t\texpect( 2 );\n\t\tvar parent = jQuery(\"<div style='position:relative;width:200px;height:200px;margin:0;padding:0;border-width:0'></div>\").appendTo( \"#qunit-fixture\" ),\n\t\t\tdiv = jQuery(\"<div style='position: absolute; width: 20px; height: 20px; top:50%; left:50%'></div>\").appendTo( parent );\n\n\t\tequal( div.css(\"top\"), \"100px\", \"position properties not transformed to pixels, see #9505\" );\n\t\tequal( div.css(\"left\"), \"100px\", \"position properties not transformed to pixels, see #9505\" );\n\t});\n}\n\ntest(\"Do not append px (#9548, #12990)\", function() {\n\texpect( 2 );\n\n\tvar $div = jQuery(\"<div>\").appendTo(\"#qunit-fixture\");\n\n\t$div.css( \"fill-opacity\", 1 );\n\tequal( $div.css(\"fill-opacity\"), 1, \"Do not append px to 'fill-opacity'\" );\n\n\t$div.css( \"column-count\", 1 );\n\tif ( $div.css(\"column-count\") ) {\n\t\tequal( $div.css(\"column-count\"), 1, \"Do not append px to 'column-count'\" );\n\t} else {\n\t\tok( true, \"No support for column-count CSS property\" );\n\t}\n});\n\ntest(\"css('width') and css('height') should respect box-sizing, see #11004\", function() {\n\texpect( 4 );\n\n\t// Support: Firefox, Android 2.3 (Prefixed box-sizing versions).\n\tvar el_dis = jQuery(\"<div style='width:300px;height:300px;margin:2px;padding:2px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;'>test</div>\"),\n\t\tel = el_dis.clone().appendTo(\"#qunit-fixture\");\n\n\tequal( el.css(\"width\"), el.css(\"width\", el.css(\"width\")).css(\"width\"), \"css('width') is not respecting box-sizing, see #11004\");\n\tequal( el_dis.css(\"width\"), el_dis.css(\"width\", el_dis.css(\"width\")).css(\"width\"), \"css('width') is not respecting box-sizing for disconnected element, see #11004\");\n\tequal( el.css(\"height\"), el.css(\"height\", el.css(\"height\")).css(\"height\"), \"css('height') is not respecting box-sizing, see #11004\");\n\tequal( el_dis.css(\"height\"), el_dis.css(\"height\", el_dis.css(\"height\")).css(\"height\"), \"css('height') is not respecting box-sizing for disconnected element, see #11004\");\n});\n\ntest(\"certain css values of 'normal' should be convertable to a number, see #8627\", function() {\n\texpect ( 2 );\n\n\tvar el = jQuery(\"<div style='letter-spacing:normal;font-weight:normal;'>test</div>\").appendTo(\"#qunit-fixture\");\n\n\tok( jQuery.isNumeric( parseFloat( el.css(\"letterSpacing\") ) ), \"css('letterSpacing') not convertable to number, see #8627\" );\n\tok( jQuery.isNumeric( parseFloat( el.css(\"fontWeight\") ) ), \"css('fontWeight') not convertable to number, see #8627\" );\n});\n\n// only run this test in IE9\nif ( document.documentMode === 9 ) {\n\ttest( \".css('filter') returns a string in IE9, see #12537\", 1, function() {\n\t\tequal( jQuery(\"<div style='-ms-filter:\\\"progid:DXImageTransform.Microsoft.gradient(startColorstr=#FFFFFF, endColorstr=#ECECEC)\\\";'></div>\").css(\"filter\"), \"progid:DXImageTransform.Microsoft.gradient(startColorstr=#FFFFFF, endColorstr=#ECECEC)\", \"IE9 returns the correct value from css('filter').\" );\n\t});\n}\n\ntest( \"cssHooks - expand\", function() {\n\texpect( 15 );\n\tvar result,\n\t\tproperties = {\n\t\t\tmargin: [ \"marginTop\", \"marginRight\", \"marginBottom\", \"marginLeft\" ],\n\t\t\tborderWidth: [ \"borderTopWidth\", \"borderRightWidth\", \"borderBottomWidth\", \"borderLeftWidth\"],\n\t\t\tpadding: [ \"paddingTop\", \"paddingRight\", \"paddingBottom\", \"paddingLeft\" ]\n\t\t};\n\n\tjQuery.each( properties, function( property, keys ) {\n\t\tvar hook = jQuery.cssHooks[ property ],\n\t\t\texpected = {};\n\t\tjQuery.each( keys, function( _, key ) {\n\t\t\texpected[ key ] = 10;\n\t\t});\n\t\tresult = hook.expand( 10 );\n\t\tdeepEqual( result, expected, property + \" expands properly with a number\" );\n\n\t\tjQuery.each( keys, function( _, key ) {\n\t\t\texpected[ key ] = \"10px\";\n\t\t});\n\t\tresult = hook.expand( \"10px\" );\n\t\tdeepEqual( result, expected, property + \" expands properly with '10px'\" );\n\n\t\texpected[ keys[1] ] = expected[ keys[3] ] = \"20px\";\n\t\tresult = hook.expand( \"10px 20px\" );\n\t\tdeepEqual( result, expected, property + \" expands properly with '10px 20px'\" );\n\n\t\texpected[ keys[2] ] = \"30px\";\n\t\tresult = hook.expand( \"10px 20px 30px\" );\n\t\tdeepEqual( result, expected, property + \" expands properly with '10px 20px 30px'\" );\n\n\t\texpected[ keys[3] ] = \"40px\";\n\t\tresult = hook.expand( \"10px 20px 30px 40px\" );\n\t\tdeepEqual( result, expected, property + \" expands properly with '10px 20px 30px 40px'\" );\n\n\t});\n\n});\n\ntest( \"css opacity consistency across browsers (#12685)\", function() {\n\texpect( 4 );\n\n\tvar el,\n\t\tfixture = jQuery(\"#qunit-fixture\");\n\n\t// Append style element\n\tjQuery(\"<style>.opacityWithSpaces_t12685 { opacity: 0.1; filter: alpha(opacity = 10); } .opacityNoSpaces_t12685 { opacity: 0.2; filter: alpha(opacity=20); }</style>\").appendTo( fixture );\n\n\tel = jQuery(\"<div class='opacityWithSpaces_t12685'></div>\").appendTo(fixture);\n\n\tequal( Math.round( el.css(\"opacity\") * 100 ), 10, \"opacity from style sheet (filter:alpha with spaces)\" );\n\tel.removeClass(\"opacityWithSpaces_t12685\").addClass(\"opacityNoSpaces_t12685\");\n\tequal( Math.round( el.css(\"opacity\") * 100 ), 20, \"opacity from style sheet (filter:alpha without spaces)\" );\n\tel.css( \"opacity\", 0.3 );\n\tequal( Math.round( el.css(\"opacity\") * 100 ), 30, \"override opacity\" );\n\tel.css( \"opacity\", \"\" );\n\tequal( Math.round( el.css(\"opacity\") * 100 ), 20, \"remove opacity override\" );\n});\n\ntest( \":visible/:hidden selectors\", function() {\n\texpect( 13 );\n\n\tok( jQuery(\"#nothiddendiv\").is(\":visible\"), \"Modifying CSS display: Assert element is visible\" );\n\tjQuery(\"#nothiddendiv\").css({ display: \"none\" });\n\tok( !jQuery(\"#nothiddendiv\").is(\":visible\"), \"Modified CSS display: Assert element is hidden\" );\n\tjQuery(\"#nothiddendiv\").css({\"display\": \"block\"});\n\tok( jQuery(\"#nothiddendiv\").is(\":visible\"), \"Modified CSS display: Assert element is visible\");\n\tok( jQuery(window).is(\":visible\") || true, \"Calling is(':visible') on window does not throw an exception (#10267)\");\n\tok( jQuery(document).is(\":visible\") || true, \"Calling is(':visible') on document does not throw an exception (#10267)\");\n\n\tok( jQuery(\"#nothiddendiv\").is(\":visible\"), \"Modifying CSS display: Assert element is visible\");\n\tjQuery(\"#nothiddendiv\").css(\"display\", \"none\");\n\tok( !jQuery(\"#nothiddendiv\").is(\":visible\"), \"Modified CSS display: Assert element is hidden\");\n\tjQuery(\"#nothiddendiv\").css(\"display\", \"block\");\n\tok( jQuery(\"#nothiddendiv\").is(\":visible\"), \"Modified CSS display: Assert element is visible\");\n\n\t// ok( !jQuery(\"#siblingspan\").is(\":visible\"), \"Span with no content not visible (#13132)\" );\n\t// var $newDiv = jQuery(\"<div><span></span></div>\").appendTo(\"#qunit-fixture\");\n\t// equal( $newDiv.find(\":visible\").length, 0, \"Span with no content not visible (#13132)\" );\n\t// var $br = jQuery(\"<br/>\").appendTo(\"#qunit-fixture\");\n\t// ok( !$br.is(\":visible\"), \"br element not visible (#10406)\");\n\n\tvar $table = jQuery(\"#table\");\n\t$table.html(\"<tr><td style='display:none'>cell</td><td>cell</td></tr>\");\n\tequal(jQuery(\"#table td:visible\").length, 1, \"hidden cell is not perceived as visible (#4512). Works on table elements\");\n\t$table.css(\"display\", \"none\").html(\"<tr><td>cell</td><td>cell</td></tr>\");\n\tequal(jQuery(\"#table td:visible\").length, 0, \"hidden cell children not perceived as visible (#4512)\");\n\n\tt( \"Is Visible\", \"#qunit-fixture div:visible:lt(2)\", [\"foo\", \"nothiddendiv\"] );\n\tt( \"Is Not Hidden\", \"#qunit-fixture:hidden\", [] );\n\tt( \"Is Hidden\", \"#form input:hidden\", [\"hidden1\",\"hidden2\"] );\n});\n\nasyncTest( \"Clearing a Cloned Element's Style Shouldn't Clear the Original Element's Style (#8908)\", 24, function() {\n\tvar baseUrl = document.location.href.replace( /([^\\/]*)$/, \"\" ),\n\tstyles = [{\n\t\t\tname: \"backgroundAttachment\",\n\t\t\tvalue: [\"fixed\"],\n\t\t\texpected: [ \"scroll\" ]\n\t\t},{\n\t\t\tname: \"backgroundColor\",\n\t\t\tvalue: [ \"rgb(255, 0, 0)\", \"rgb(255,0,0)\", \"#ff0000\" ],\n\t\t\texpected: [\"transparent\"]\n\t\t}, {\n\t\t\t// Firefox returns auto's value\n\t\t\tname: \"backgroundImage\",\n\t\t\tvalue: [ \"url('test.png')\", \"url(\" + baseUrl + \"test.png)\", \"url(\\\"\" + baseUrl + \"test.png\\\")\" ],\n\t\t\texpected: [ \"none\", \"url(\\\"http://static.jquery.com/files/rocker/images/logo_jquery_215x53.gif\\\")\" ]\n\t\t}, {\n\t\t\tname: \"backgroundPosition\",\n\t\t\tvalue: [\"5% 5%\"],\n\t\t\texpected: [ \"0% 0%\", \"-1000px 0px\", \"-1000px 0%\" ]\n\t\t}, {\n\t\t\t// Firefox returns no-repeat\n\t\t\tname: \"backgroundRepeat\",\n\t\t\tvalue: [\"repeat-y\"],\n\t\t\texpected: [ \"repeat\", \"no-repeat\" ]\n\t\t}, {\n\t\t\tname: \"backgroundClip\",\n\t\t\tvalue: [\"padding-box\"],\n\t\t\texpected: [\"border-box\"]\n\t\t}, {\n\t\t\tname: \"backgroundOrigin\",\n\t\t\tvalue: [\"content-box\"],\n\t\t\texpected: [\"padding-box\"]\n\t\t}, {\n\t\t\tname: \"backgroundSize\",\n\t\t\tvalue: [\"80px 60px\"],\n\t\t\texpected: [ \"auto auto\" ]\n\t}];\n\n\tjQuery.each(styles, function( index, style ) {\n\t\tvar $clone, $clonedChildren,\n\t\t\t$source = jQuery( \"#firstp\" ),\n\t\t\tsource = $source[ 0 ],\n\t\t\t$children = $source.children();\n\n\t\tstyle.expected = style.expected.concat( [ \"\", \"auto\" ] );\n\n\t\tif ( source.style[ style.name ] === undefined ) {\n\t\t\tok( true, style.name +  \": style isn't supported and therefore not an issue\" );\n\t\t\tok( true );\n\n\t\t\treturn true;\n\t\t}\n\n\t\t$source.css( style.name, style.value[ 0 ] );\n\t\t$children.css( style.name, style.value[ 0 ] );\n\n\t\t$clone = $source.clone();\n\t\t$clonedChildren = $clone.children();\n\n\t\t$clone.css( style.name, \"\" );\n\t\t$clonedChildren.css( style.name, \"\" );\n\n\t\twindow.setTimeout(function() {\n\t\t\tnotEqual( $clone.css( style.name ), style.value[ 0 ], \"Cloned css was changed\" );\n\n\t\t\tok( jQuery.inArray( $source.css( style.name ) !== -1, style.value ),\n\t\t\t\t\"Clearing clone.css() doesn't affect source.css(): \" + style.name +\n\t\t\t\t\"; result: \" + $source.css( style.name ) +\n\t\t\t\t\"; expected: \" + style.value.join( \",\" ) );\n\n\t\t\tok( jQuery.inArray( $children.css( style.name ) !== -1, style.value ),\n\t\t\t\t\"Clearing clonedChildren.css() doesn't affect children.css(): \" + style.name +\n\t\t\t\t\"; result: \" + $children.css( style.name ) +\n\t\t\t\t\"; expected: \" + style.value.join( \",\" ) );\n\t\t}, 100 );\n\t});\n\n\twindow.setTimeout( start, 1000 );\n});\n\nasyncTest( \"Make sure initialized display value for disconnected nodes is correct (#13310)\", 4, function() {\n\tvar display = jQuery(\"#display\").css(\"display\"),\n\t\tdiv = jQuery(\"<div/>\");\n\n\tequal( div.css( \"display\", \"inline\" ).hide().show().appendTo(\"body\").css( \"display\" ), \"inline\", \"Initialized display value has returned\" );\n\tdiv.remove();\n\n\tdiv.css( \"display\", \"none\" ).hide();\n\tequal( jQuery._data( div[ 0 ], \"olddisplay\" ), undefined, \"olddisplay is undefined after hiding a detached and hidden element\" );\n\tdiv.remove();\n\n\tdiv.css( \"display\", \"inline-block\" ).hide().appendTo(\"body\").fadeIn(function() {\n\t\tequal( div.css( \"display\" ), \"inline-block\", \"Initialized display value has returned\" );\n\t\tdiv.remove();\n\n\t\tstart();\n\t});\n\n\tequal( jQuery._data( jQuery(\"#display\").css( \"display\", \"inline\" ).hide()[ 0 ], \"olddisplay\" ), display,\n\t\"display: * !Important value should used as initialized display\" );\n\tjQuery._removeData( jQuery(\"#display\")[ 0 ] );\n});\n\n}\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/jquery/test/unit/data.js",
    "content": "module(\"data\", { teardown: moduleTeardown });\n\ntest(\"expando\", function(){\n\texpect(1);\n\n\tequal(jQuery.expando !== undefined, true, \"jQuery is exposing the expando\");\n});\n\ntest( \"jQuery.data & removeData, expected returns\", function() {\n\texpect(4);\n\tvar elem = document.body;\n\n\tequal(\n\t\tjQuery.data( elem, \"hello\", \"world\" ), \"world\",\n\t\t\"jQuery.data( elem, key, value ) returns value\"\n\t);\n\tequal(\n\t\tjQuery.data( elem, \"hello\" ), \"world\",\n\t\t\"jQuery.data( elem, key ) returns value\"\n\t);\n\tdeepEqual(\n\t\tjQuery.data( elem, { goodnight: \"moon\" }), { goodnight: \"moon\" },\n\t\t\"jQuery.data( elem, obj ) returns obj\"\n\t);\n\tequal(\n\t\tjQuery.removeData( elem, \"hello\" ), undefined,\n\t\t\"jQuery.removeData( elem, key, value ) returns undefined\"\n\t);\n\n});\n\ntest( \"jQuery._data & _removeData, expected returns\", function() {\n\texpect(4);\n\tvar elem = document.body;\n\n\tequal(\n\t\tjQuery._data( elem, \"hello\", \"world\" ), \"world\",\n\t\t\"jQuery._data( elem, key, value ) returns value\"\n\t);\n\tequal(\n\t\tjQuery._data( elem, \"hello\" ), \"world\",\n\t\t\"jQuery._data( elem, key ) returns value\"\n\t);\n\tdeepEqual(\n\t\tjQuery._data( elem, { goodnight: \"moon\" }), { goodnight: \"moon\" },\n\t\t\"jQuery._data( elem, obj ) returns obj\"\n\t);\n\tequal(\n\t\tjQuery._removeData( elem, \"hello\" ), undefined,\n\t\t\"jQuery._removeData( elem, key, value ) returns undefined\"\n\t);\n});\n\ntest( \"jQuery.hasData no side effects\", function() {\n\texpect(1);\n\tvar obj = {};\n\n\tjQuery.hasData( obj );\n\n\tequal( Object.getOwnPropertyNames( obj ).length, 0,\n\t\t\"No data expandos where added when calling jQuery.hasData(o)\"\n\t);\n});\n\nfunction dataTests (elem) {\n\tvar dataObj, internalDataObj;\n\n\tequal( jQuery.data(elem, \"foo\"), undefined, \"No data exists initially\" );\n\tstrictEqual( jQuery.hasData(elem), false, \"jQuery.hasData agrees no data exists initially\" );\n\n\tdataObj = jQuery.data(elem);\n\tequal( typeof dataObj, \"object\", \"Calling data with no args gives us a data object reference\" );\n\tstrictEqual( jQuery.data(elem), dataObj, \"Calling jQuery.data returns the same data object when called multiple times\" );\n\n\tstrictEqual( jQuery.hasData(elem), false, \"jQuery.hasData agrees no data exists even when an empty data obj exists\" );\n\n\tdataObj[\"foo\"] = \"bar\";\n\tequal( jQuery.data(elem, \"foo\"), \"bar\", \"Data is readable by jQuery.data when set directly on a returned data object\" );\n\n\tstrictEqual( jQuery.hasData(elem), true, \"jQuery.hasData agrees data exists when data exists\" );\n\n\tjQuery.data(elem, \"foo\", \"baz\");\n\tequal( jQuery.data(elem, \"foo\"), \"baz\", \"Data can be changed by jQuery.data\" );\n\tequal( dataObj[\"foo\"], \"baz\", \"Changes made through jQuery.data propagate to referenced data object\" );\n\n\tjQuery.data(elem, \"foo\", undefined);\n\tequal( jQuery.data(elem, \"foo\"), \"baz\", \"Data is not unset by passing undefined to jQuery.data\" );\n\n\tjQuery.data(elem, \"foo\", null);\n\tstrictEqual( jQuery.data(elem, \"foo\"), null, \"Setting null using jQuery.data works OK\" );\n\n\tjQuery.data(elem, \"foo\", \"foo1\");\n\n\tjQuery.data(elem, { \"bar\" : \"baz\", \"boom\" : \"bloz\" });\n\tstrictEqual( jQuery.data(elem, \"foo\"), \"foo1\", \"Passing an object extends the data object instead of replacing it\" );\n\tequal( jQuery.data(elem, \"boom\"), \"bloz\", \"Extending the data object works\" );\n\n\tjQuery._data(elem, \"foo\", \"foo2\", true);\n\tequal( jQuery._data(elem, \"foo\"), \"foo2\", \"Setting internal data works\" );\n\tequal( jQuery.data(elem, \"foo\"), \"foo1\", \"Setting internal data does not override user data\" );\n\n\tinternalDataObj = jQuery._data( elem );\n\tok( internalDataObj, \"Internal data object exists\" );\n\tnotStrictEqual( dataObj, internalDataObj, \"Internal data object is not the same as user data object\" );\n\n\tstrictEqual( elem.boom, undefined, \"Data is never stored directly on the object\" );\n\n\tjQuery.removeData(elem, \"foo\");\n\tstrictEqual( jQuery.data(elem, \"foo\"), undefined, \"jQuery.removeData removes single properties\" );\n\n\tjQuery.removeData(elem);\n\tstrictEqual( jQuery._data(elem), internalDataObj, \"jQuery.removeData does not remove internal data if it exists\" );\n\n\tjQuery.data(elem, \"foo\", \"foo1\");\n\tjQuery._data(elem, \"foo\", \"foo2\");\n\n\tequal( jQuery.data(elem, \"foo\"), \"foo1\", \"(sanity check) Ensure data is set in user data object\" );\n\tequal( jQuery._data(elem, \"foo\"), \"foo2\", \"(sanity check) Ensure data is set in internal data object\" );\n\n\tstrictEqual( jQuery._data(elem, jQuery.expando), undefined, \"Removing the last item in internal data destroys the internal data object\" );\n\n\tjQuery._data(elem, \"foo\", \"foo2\");\n\tequal( jQuery._data(elem, \"foo\"), \"foo2\", \"(sanity check) Ensure data is set in internal data object\" );\n\n\tjQuery.removeData(elem, \"foo\");\n\tequal( jQuery._data(elem, \"foo\"), \"foo2\", \"(sanity check) jQuery.removeData for user data does not remove internal data\" );\n}\n\ntest(\"jQuery.data(div)\", 25, function() {\n\tvar div = document.createElement(\"div\");\n\n\tdataTests(div);\n\n\t// We stored one key in the private data\n\t// assert that nothing else was put in there, and that that\n\t// one stayed there.\n\tQUnit.expectJqData(div, \"foo\");\n});\n\ntest(\"jQuery.data({})\", 25, function() {\n\tdataTests({});\n});\n\ntest(\"jQuery.data(window)\", 25, function() {\n\t// remove bound handlers from window object to stop potential false positives caused by fix for #5280 in\n\t// transports/xhr.js\n\tjQuery(window).off(\"unload\");\n\n\tdataTests(window);\n});\n\ntest(\"jQuery.data(document)\", 25, function() {\n\tdataTests(document);\n\n\tQUnit.expectJqData(document, \"foo\");\n});\n\ntest(\"jQuery.data(<embed>)\", 25, function() {\n\tdataTests( document.createElement(\"embed\") );\n});\n\ntest(\"jQuery.data(<applet>)\", 25, function() {\n\tdataTests( document.createElement(\"applet\") );\n});\n\ntest(\"jQuery.data(object/flash)\", 25, function() {\n\tvar flash = document.createElement(\"object\");\n\tflash.setAttribute( \"classid\", \"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000\" );\n\n\tdataTests( flash );\n});\n\ntest(\".data()\", function() {\n\texpect(5);\n\n\tvar div, dataObj, nodiv, obj;\n\n\tdiv = jQuery(\"#foo\");\n\tstrictEqual( div.data(\"foo\"), undefined, \"Make sure that missing result is undefined\" );\n\tdiv.data(\"test\", \"success\");\n\n\tdataObj = div.data();\n\n\tdeepEqual( dataObj, {test: \"success\"}, \"data() returns entire data object with expected properties\" );\n\tstrictEqual( div.data(\"foo\"), undefined, \"Make sure that missing result is still undefined\" );\n\n\tnodiv = jQuery(\"#unfound\");\n\tequal( nodiv.data(), null, \"data() on empty set returns null\" );\n\n\tobj = { foo: \"bar\" };\n\tjQuery(obj).data(\"foo\", \"baz\");\n\n\tdataObj = jQuery.extend(true, {}, jQuery(obj).data());\n\n\tdeepEqual( dataObj, { \"foo\": \"baz\" }, \"Retrieve data object from a wrapped JS object (#7524)\" );\n});\n\nfunction testDataTypes( $obj ) {\n\tjQuery.each({\n\t\t\"null\": null,\n\t\t\"true\": true,\n\t\t\"false\": false,\n\t\t\"zero\": 0,\n\t\t\"one\": 1,\n\t\t\"empty string\": \"\",\n\t\t\"empty array\": [],\n\t\t\"array\": [1],\n\t\t\"empty object\": {},\n\t\t\"object\": { foo: \"bar\" },\n\t\t\"date\": new Date(),\n\t\t\"regex\": /test/,\n\t\t\"function\": function() {}\n\t}, function( type, value ) {\n\t\tstrictEqual( $obj.data( \"test\", value ).data(\"test\"), value, \"Data set to \" + type );\n\t});\n}\n\ntest(\"jQuery(Element).data(String, Object).data(String)\", function() {\n\texpect( 18 );\n\tvar parent = jQuery(\"<div><div></div></div>\"),\n\t\tdiv = parent.children();\n\n\tstrictEqual( div.data(\"test\"), undefined, \"No data exists initially\" );\n\tstrictEqual( div.data(\"test\", \"success\").data(\"test\"), \"success\", \"Data added\" );\n\tstrictEqual( div.data(\"test\", \"overwritten\").data(\"test\"), \"overwritten\", \"Data overwritten\" );\n\tstrictEqual( div.data(\"test\", undefined).data(\"test\"), \"overwritten\", \".data(key,undefined) does nothing but is chainable (#5571)\");\n\tstrictEqual( div.data(\"notexist\"), undefined, \"No data exists for unset key\" );\n\ttestDataTypes( div );\n\n\tparent.remove();\n});\n\ntest(\"jQuery(plain Object).data(String, Object).data(String)\", function() {\n\texpect( 16 );\n\n\t// #3748\n\tvar $obj = jQuery({ exists: true });\n\tstrictEqual( $obj.data(\"nothing\"), undefined, \"Non-existent data returns undefined\");\n\tstrictEqual( $obj.data(\"exists\"), undefined, \"Object properties are not returned as data\" );\n\ttestDataTypes( $obj );\n\n\t// Clean up\n\t$obj.removeData();\n\tdeepEqual( $obj[0], { exists: true }, \"removeData does not clear the object\" );\n});\n\ntest(\".data(object) does not retain references. #13815\", function() {\n\texpect( 2 );\n\n\tvar $divs = jQuery(\"<div></div><div></div>\").appendTo(\"#qunit-fixture\");\n\n\t$divs.data({ \"type\": \"foo\" });\n\t$divs.eq( 0 ).data( \"type\", \"bar\" );\n\n\tequal( $divs.eq( 0 ).data(\"type\"), \"bar\", \"Correct updated value\" );\n\tequal( $divs.eq( 1 ).data(\"type\"), \"foo\", \"Original value retained\" );\n});\n\ntest(\"data-* attributes\", function() {\n\texpect(40);\n\tvar prop, i, l, metadata, elem,\n\t\tobj, obj2, check, num, num2,\n\t\tdiv = jQuery(\"<div>\"),\n\t\tchild = jQuery(\"<div data-myobj='old data' data-ignored=\\\"DOM\\\" data-other='test'></div>\"),\n\t\tdummy = jQuery(\"<div data-myobj='old data' data-ignored=\\\"DOM\\\" data-other='test'></div>\");\n\n\tequal( div.data(\"attr\"), undefined, \"Check for non-existing data-attr attribute\" );\n\n\tdiv.attr(\"data-attr\", \"exists\");\n\tequal( div.data(\"attr\"), \"exists\", \"Check for existing data-attr attribute\" );\n\n\tdiv.attr(\"data-attr\", \"exists2\");\n\tequal( div.data(\"attr\"), \"exists\", \"Check that updates to data- don't update .data()\" );\n\n\tdiv.data(\"attr\", \"internal\").attr(\"data-attr\", \"external\");\n\tequal( div.data(\"attr\"), \"internal\", \"Check for .data('attr') precedence (internal > external data-* attribute)\" );\n\n\tdiv.remove();\n\n\tchild.appendTo(\"#qunit-fixture\");\n\tequal( child.data(\"myobj\"), \"old data\", \"Value accessed from data-* attribute\");\n\n\tchild.data(\"myobj\", \"replaced\");\n\tequal( child.data(\"myobj\"), \"replaced\", \"Original data overwritten\");\n\n\tchild.data(\"ignored\", \"cache\");\n\tequal( child.data(\"ignored\"), \"cache\", \"Cached data used before DOM data-* fallback\");\n\n\tobj = child.data();\n\tobj2 = dummy.data();\n\tcheck = [ \"myobj\", \"ignored\", \"other\" ];\n\tnum = 0;\n\tnum2 = 0;\n\n\tdummy.remove();\n\n\tfor ( i = 0, l = check.length; i < l; i++ ) {\n\t\tok( obj[ check[i] ], \"Make sure data- property exists when calling data-.\" );\n\t\tok( obj2[ check[i] ], \"Make sure data- property exists when calling data-.\" );\n\t}\n\n\tfor ( prop in obj ) {\n\t\tnum++;\n\t}\n\n\tequal( num, check.length, \"Make sure that the right number of properties came through.\" );\n\n\tfor ( prop in obj2 ) {\n\t\tnum2++;\n\t}\n\n\tequal( num2, check.length, \"Make sure that the right number of properties came through.\" );\n\n\tchild.attr(\"data-other\", \"newvalue\");\n\n\tequal( child.data(\"other\"), \"test\", \"Make sure value was pulled in properly from a .data().\" );\n\n\tchild\n\t\t.attr(\"data-true\", \"true\")\n\t\t.attr(\"data-false\", \"false\")\n\t\t.attr(\"data-five\", \"5\")\n\t\t.attr(\"data-point\", \"5.5\")\n\t\t.attr(\"data-pointe\", \"5.5E3\")\n\t\t.attr(\"data-grande\", \"5.574E9\")\n\t\t.attr(\"data-hexadecimal\", \"0x42\")\n\t\t.attr(\"data-pointbad\", \"5..5\")\n\t\t.attr(\"data-pointbad2\", \"-.\")\n\t\t.attr(\"data-bigassnum\", \"123456789123456789123456789\")\n\t\t.attr(\"data-badjson\", \"{123}\")\n\t\t.attr(\"data-badjson2\", \"[abc]\")\n\t\t.attr(\"data-empty\", \"\")\n\t\t.attr(\"data-space\", \" \")\n\t\t.attr(\"data-null\", \"null\")\n\t\t.attr(\"data-string\", \"test\");\n\n\tstrictEqual( child.data(\"true\"), true, \"Primitive true read from attribute\");\n\tstrictEqual( child.data(\"false\"), false, \"Primitive false read from attribute\");\n\tstrictEqual( child.data(\"five\"), 5, \"Primitive number read from attribute\");\n\tstrictEqual( child.data(\"point\"), 5.5, \"Primitive number read from attribute\");\n\tstrictEqual( child.data(\"pointe\"), \"5.5E3\", \"Floating point exponential number read from attribute\");\n\tstrictEqual( child.data(\"grande\"), \"5.574E9\", \"Big exponential number read from attribute\");\n\tstrictEqual( child.data(\"hexadecimal\"), \"0x42\", \"Hexadecimal number read from attribute\");\n\tstrictEqual( child.data(\"pointbad\"), \"5..5\", \"Bad number read from attribute\");\n\tstrictEqual( child.data(\"pointbad2\"), \"-.\", \"Bad number read from attribute\");\n\tstrictEqual( child.data(\"bigassnum\"), \"123456789123456789123456789\", \"Bad bigass number read from attribute\");\n\tstrictEqual( child.data(\"badjson\"), \"{123}\", \"Bad number read from attribute\");\n\tstrictEqual( child.data(\"badjson2\"), \"[abc]\", \"Bad number read from attribute\");\n\tstrictEqual( child.data(\"empty\"), \"\", \"Empty string read from attribute\");\n\tstrictEqual( child.data(\"space\"), \" \", \"Empty string read from attribute\");\n\tstrictEqual( child.data(\"null\"), null, \"Primitive null read from attribute\");\n\tstrictEqual( child.data(\"string\"), \"test\", \"Typical string read from attribute\");\n\n\tchild.remove();\n\n\t// tests from metadata plugin\n\tfunction testData(index, elem) {\n\t\tswitch (index) {\n\t\tcase 0:\n\t\t\tequal(jQuery(elem).data(\"foo\"), \"bar\", \"Check foo property\");\n\t\t\tequal(jQuery(elem).data(\"bar\"), \"baz\", \"Check baz property\");\n\t\t\tbreak;\n\t\tcase 1:\n\t\t\tequal(jQuery(elem).data(\"test\"), \"bar\", \"Check test property\");\n\t\t\tequal(jQuery(elem).data(\"bar\"), \"baz\", \"Check bar property\");\n\t\t\tbreak;\n\t\tcase 2:\n\t\t\tequal(jQuery(elem).data(\"zoooo\"), \"bar\", \"Check zoooo property\");\n\t\t\tdeepEqual(jQuery(elem).data(\"bar\"), {\"test\":\"baz\"}, \"Check bar property\");\n\t\t\tbreak;\n\t\tcase 3:\n\t\t\tequal(jQuery(elem).data(\"number\"), true, \"Check number property\");\n\t\t\tdeepEqual(jQuery(elem).data(\"stuff\"), [2,8], \"Check stuff property\");\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tok(false, [\"Assertion failed on index \", index, \", with data\"].join(\"\"));\n\t\t}\n\t}\n\n\tmetadata = \"<ol><li class='test test2' data-foo='bar' data-bar='baz' data-arr='[1,2]'>Some stuff</li><li class='test test2' data-test='bar' data-bar='baz'>Some stuff</li><li class='test test2' data-zoooo='bar' data-bar='{\\\"test\\\":\\\"baz\\\"}'>Some stuff</li><li class='test test2' data-number=true data-stuff='[2,8]'>Some stuff</li></ol>\";\n\telem = jQuery(metadata).appendTo(\"#qunit-fixture\");\n\n\telem.find(\"li\").each(testData);\n\telem.remove();\n});\n\ntest(\".data(Object)\", function() {\n\texpect(4);\n\n\tvar obj, jqobj,\n\t\tdiv = jQuery(\"<div/>\");\n\n\tdiv.data({ \"test\": \"in\", \"test2\": \"in2\" });\n\tequal( div.data(\"test\"), \"in\", \"Verify setting an object in data\" );\n\tequal( div.data(\"test2\"), \"in2\", \"Verify setting an object in data\" );\n\n\tobj = {test:\"unset\"};\n\tjqobj = jQuery(obj);\n\n\tjqobj.data(\"test\", \"unset\");\n\tjqobj.data({ \"test\": \"in\", \"test2\": \"in2\" });\n\tequal( jQuery.data(obj)[\"test\"], \"in\", \"Verify setting an object on an object extends the data object\" );\n\tequal( obj[\"test2\"], undefined, \"Verify setting an object on an object does not extend the object\" );\n\n\t// manually clean up detached elements\n\tdiv.remove();\n});\n\ntest(\"jQuery.removeData\", function() {\n\texpect(10);\n\n\tvar obj,\n\t\tdiv = jQuery(\"#foo\")[0];\n\tjQuery.data(div, \"test\", \"testing\");\n\tjQuery.removeData(div, \"test\");\n\tequal( jQuery.data(div, \"test\"), undefined, \"Check removal of data\" );\n\n\tjQuery.data(div, \"test2\", \"testing\");\n\tjQuery.removeData( div );\n\tok( !jQuery.data(div, \"test2\"), \"Make sure that the data property no longer exists.\" );\n\tok( !div[ jQuery.expando ], \"Make sure the expando no longer exists, as well.\" );\n\n\tjQuery.data(div, {\n\t\ttest3: \"testing\",\n\t\ttest4: \"testing\"\n\t});\n\tjQuery.removeData( div, \"test3 test4\" );\n\tok( !jQuery.data(div, \"test3\") || jQuery.data(div, \"test4\"), \"Multiple delete with spaces.\" );\n\n\tjQuery.data(div, {\n\t\ttest3: \"testing\",\n\t\ttest4: \"testing\"\n\t});\n\tjQuery.removeData( div, [ \"test3\", \"test4\" ] );\n\tok( !jQuery.data(div, \"test3\") || jQuery.data(div, \"test4\"), \"Multiple delete by array.\" );\n\n\tjQuery.data(div, {\n\t\t\"test3 test4\": \"testing\",\n\t\t\"test3\": \"testing\"\n\t});\n\tjQuery.removeData( div, \"test3 test4\" );\n\tok( !jQuery.data(div, \"test3 test4\"), \"Multiple delete with spaces deleted key with exact name\" );\n\tok( jQuery.data(div, \"test3\"), \"Left the partial matched key alone\" );\n\n\tobj = {};\n\tjQuery.data(obj, \"test\", \"testing\");\n\tequal( jQuery(obj).data(\"test\"), \"testing\", \"verify data on plain object\");\n\tjQuery.removeData(obj, \"test\");\n\tequal( jQuery.data(obj, \"test\"), undefined, \"Check removal of data on plain object\" );\n\n\tjQuery.data( window, \"BAD\", true );\n\tjQuery.removeData( window, \"BAD\" );\n\tok( !jQuery.data( window, \"BAD\" ), \"Make sure that the value was not still set.\" );\n});\n\ntest(\".removeData()\", function() {\n\texpect(6);\n\tvar div = jQuery(\"#foo\");\n\tdiv.data(\"test\", \"testing\");\n\tdiv.removeData(\"test\");\n\tequal( div.data(\"test\"), undefined, \"Check removal of data\" );\n\n\tdiv.data(\"test\", \"testing\");\n\tdiv.data(\"test.foo\", \"testing2\");\n\tdiv.removeData(\"test.bar\");\n\tequal( div.data(\"test.foo\"), \"testing2\", \"Make sure data is intact\" );\n\tequal( div.data(\"test\"), \"testing\", \"Make sure data is intact\" );\n\n\tdiv.removeData(\"test\");\n\tequal( div.data(\"test.foo\"), \"testing2\", \"Make sure data is intact\" );\n\tequal( div.data(\"test\"), undefined, \"Make sure data is intact\" );\n\n\tdiv.removeData(\"test.foo\");\n\tequal( div.data(\"test.foo\"), undefined, \"Make sure data is intact\" );\n});\n\nif (window.JSON && window.JSON.stringify) {\n\ttest(\"JSON serialization (#8108)\", function () {\n\t\texpect(1);\n\n\t\tvar obj = { \"foo\": \"bar\" };\n\t\tjQuery.data(obj, \"hidden\", true);\n\n\t\tequal( JSON.stringify(obj), \"{\\\"foo\\\":\\\"bar\\\"}\", \"Expando is hidden from JSON.stringify\" );\n\t});\n}\n\ntest(\".data should follow html5 specification regarding camel casing\", function() {\n\texpect(12);\n\n\tvar div = jQuery(\"<div id='myObject' data-w-t-f='ftw' data-big-a-little-a='bouncing-b' data-foo='a' data-foo-bar='b' data-foo-bar-baz='c'></div>\")\n\t\t.prependTo(\"body\");\n\n\tequal( div.data()[\"wTF\"], \"ftw\", \"Verify single letter data-* key\" );\n\tequal( div.data()[\"bigALittleA\"], \"bouncing-b\", \"Verify single letter mixed data-* key\" );\n\n\tequal( div.data()[\"foo\"], \"a\", \"Verify single word data-* key\" );\n\tequal( div.data()[\"fooBar\"], \"b\", \"Verify multiple word data-* key\" );\n\tequal( div.data()[\"fooBarBaz\"], \"c\", \"Verify multiple word data-* key\" );\n\n\tequal( div.data(\"foo\"), \"a\", \"Verify single word data-* key\" );\n\tequal( div.data(\"fooBar\"), \"b\", \"Verify multiple word data-* key\" );\n\tequal( div.data(\"fooBarBaz\"), \"c\", \"Verify multiple word data-* key\" );\n\n\tdiv.data(\"foo-bar\", \"d\");\n\n\tequal( div.data(\"fooBar\"), \"d\", \"Verify updated data-* key\" );\n\tequal( div.data(\"foo-bar\"), \"d\", \"Verify updated data-* key\" );\n\n\tequal( div.data(\"fooBar\"), \"d\", \"Verify updated data-* key (fooBar)\" );\n\tequal( div.data(\"foo-bar\"), \"d\", \"Verify updated data-* key (foo-bar)\" );\n\n\tdiv.remove();\n});\n\ntest(\".data should not miss preset data-* w/ hyphenated property names\", function() {\n\n\texpect(2);\n\n\tvar div = jQuery(\"<div/>\", { id: \"hyphened\" }).appendTo(\"#qunit-fixture\"),\n\t\ttest = {\n\t\t\t\"camelBar\": \"camelBar\",\n\t\t\t\"hyphen-foo\": \"hyphen-foo\"\n\t\t};\n\n\tdiv.data( test );\n\n\tjQuery.each( test , function(i, k) {\n\t\tequal( div.data(k), k, \"data with property '\"+k+\"' was correctly found\");\n\t});\n});\n\ntest(\"jQuery.data should not miss data-* w/ hyphenated property names #14047\", function() {\n\n\texpect(1);\n\n\tvar div = jQuery(\"<div/>\");\n\n\tdiv.data( \"foo-bar\", \"baz\" );\n\n\tequal( jQuery.data(div[0], \"foo-bar\"), \"baz\", \"data with property 'foo-bar' was correctly found\");\n});\n\ntest(\".data should not miss attr() set data-* with hyphenated property names\", function() {\n\texpect(2);\n\n\tvar a, b;\n\n\ta = jQuery(\"<div/>\").appendTo(\"#qunit-fixture\");\n\n\ta.attr( \"data-long-param\", \"test\" );\n\ta.data( \"long-param\", { a: 2 });\n\n\tdeepEqual( a.data(\"long-param\"), { a: 2 }, \"data with property long-param was found, 1\" );\n\n\tb = jQuery(\"<div/>\").appendTo(\"#qunit-fixture\");\n\n\tb.attr( \"data-long-param\", \"test\" );\n\tb.data( \"long-param\" );\n\tb.data( \"long-param\", { a: 2 });\n\n\tdeepEqual( b.data(\"long-param\"), { a: 2 }, \"data with property long-param was found, 2\" );\n});\n\ntest(\".data supports interoperable hyphenated/camelCase get/set of properties with arbitrary non-null|NaN|undefined values\", function() {\n\n\tvar div = jQuery(\"<div/>\", { id: \"hyphened\" }).appendTo(\"#qunit-fixture\"),\n\t\tdatas = {\n\t\t\t\"non-empty\": \"a string\",\n\t\t\t\"empty-string\": \"\",\n\t\t\t\"one-value\": 1,\n\t\t\t\"zero-value\": 0,\n\t\t\t\"an-array\": [],\n\t\t\t\"an-object\": {},\n\t\t\t\"bool-true\": true,\n\t\t\t\"bool-false\": false,\n\t\t\t// JSHint enforces double quotes,\n\t\t\t// but JSON strings need double quotes to parse\n\t\t\t// so we need escaped double quotes here\n\t\t\t\"some-json\": \"{ \\\"foo\\\": \\\"bar\\\" }\",\n\t\t\t\"num-1-middle\": true,\n\t\t\t\"num-end-2\": true,\n\t\t\t\"2-num-start\": true\n\t\t};\n\n\texpect( 24 );\n\n\tjQuery.each( datas, function( key, val ) {\n\t\tdiv.data( key, val );\n\n\t\tdeepEqual( div.data( key ), val, \"get: \" + key );\n\t\tdeepEqual( div.data( jQuery.camelCase( key ) ), val, \"get: \" + jQuery.camelCase( key ) );\n\t});\n});\n\ntest(\".data supports interoperable removal of hyphenated/camelCase properties\", function() {\n\tvar div = jQuery(\"<div/>\", { id: \"hyphened\" }).appendTo(\"#qunit-fixture\"),\n\t\tdatas = {\n\t\t\t\"non-empty\": \"a string\",\n\t\t\t\"empty-string\": \"\",\n\t\t\t\"one-value\": 1,\n\t\t\t\"zero-value\": 0,\n\t\t\t\"an-array\": [],\n\t\t\t\"an-object\": {},\n\t\t\t\"bool-true\": true,\n\t\t\t\"bool-false\": false,\n\t\t\t// JSHint enforces double quotes,\n\t\t\t// but JSON strings need double quotes to parse\n\t\t\t// so we need escaped double quotes here\n\t\t\t\"some-json\": \"{ \\\"foo\\\": \\\"bar\\\" }\"\n\t\t};\n\n\texpect( 27 );\n\n\tjQuery.each( datas, function( key, val ) {\n\t\tdiv.data( key, val );\n\n\t\tdeepEqual( div.data( key ), val, \"get: \" + key );\n\t\tdeepEqual( div.data( jQuery.camelCase( key ) ), val, \"get: \" + jQuery.camelCase( key ) );\n\n\t\tdiv.removeData( key );\n\n\t\tequal( div.data( key ), undefined, \"get: \" + key );\n\n\t});\n});\n\ntest(\".data supports interoperable removal of properties SET TWICE #13850\", function() {\n\tvar div = jQuery(\"<div>\").appendTo(\"#qunit-fixture\"),\n\t\tdatas = {\n\t\t\t\"non-empty\": \"a string\",\n\t\t\t\"empty-string\": \"\",\n\t\t\t\"one-value\": 1,\n\t\t\t\"zero-value\": 0,\n\t\t\t\"an-array\": [],\n\t\t\t\"an-object\": {},\n\t\t\t\"bool-true\": true,\n\t\t\t\"bool-false\": false,\n\t\t\t// JSHint enforces double quotes,\n\t\t\t// but JSON strings need double quotes to parse\n\t\t\t// so we need escaped double quotes here\n\t\t\t\"some-json\": \"{ \\\"foo\\\": \\\"bar\\\" }\"\n\t\t};\n\n\texpect( 9 );\n\n\tjQuery.each( datas, function( key, val ) {\n\t\tdiv.data( key, val );\n\t\tdiv.data( key, val );\n\n\t\tdiv.removeData( key );\n\n\t\tequal( div.data( key ), undefined, \"removal: \" + key );\n\t});\n});\n\ntest( \".removeData supports removal of hyphenated properties via array (#12786)\", function() {\n\texpect( 4 );\n\n\tvar div, plain, compare;\n\n\tdiv = jQuery(\"<div>\").appendTo(\"#qunit-fixture\");\n\tplain = jQuery({});\n\n\t// When data is batch assigned (via plain object), the properties\n\t// are not camel cased as they are with (property, value) calls\n\tcompare = {\n\t\t// From batch assignment .data({ \"a-a\": 1 })\n\t\t\"a-a\": 1,\n\t\t// From property, value assignment .data( \"b-b\", 1 )\n\t\t\"bB\": 1\n\t};\n\n\t// Mixed assignment\n\tdiv.data({ \"a-a\": 1 }).data( \"b-b\", 1 );\n\tplain.data({ \"a-a\": 1 }).data( \"b-b\", 1 );\n\n\tdeepEqual( div.data(), compare, \"Data appears as expected. (div)\" );\n\tdeepEqual( plain.data(), compare, \"Data appears as expected. (plain)\" );\n\n\tdiv.removeData([ \"a-a\", \"b-b\" ]);\n\tplain.removeData([ \"a-a\", \"b-b\" ]);\n\n\t// NOTE: Timo's proposal for \"propEqual\" (or similar) would be nice here\n\tdeepEqual( div.data(), {}, \"Data is empty. (div)\" );\n\tdeepEqual( plain.data(), {}, \"Data is empty. (plain)\" );\n});\n\n// Test originally by Moschel\ntest(\".removeData should not throw exceptions. (#10080)\", function() {\n\texpect(1);\n\tstop();\n\tvar frame = jQuery(\"#loadediframe\");\n\tjQuery(frame[0].contentWindow).on(\"unload\", function() {\n\t\tok(true, \"called unload\");\n\t\tstart();\n\t});\n\t// change the url to trigger unload\n\tframe.attr(\"src\", \"data/iframe.html?param=true\");\n});\n\ntest( \".data only checks element attributes once. #8909\", function() {\n\texpect( 2 );\n\tvar testing = {\n\t\t\t\"test\": \"testing\",\n\t\t\t\"test2\": \"testing\"\n\t\t},\n\t\telement = jQuery( \"<div data-test='testing'>\" ),\n\t\tnode = element[ 0 ];\n\n\t// set an attribute using attr to ensure it\n\tnode.setAttribute( \"data-test2\", \"testing\" );\n\tdeepEqual( element.data(), testing, \"Sanity Check\" );\n\n\tnode.setAttribute( \"data-test3\", \"testing\" );\n\tdeepEqual( element.data(), testing, \"The data didn't change even though the data-* attrs did\" );\n\n\t// clean up data cache\n\telement.remove();\n});\n\ntest( \"data-* with JSON value can have newlines\", function() {\n\texpect(1);\n\n\tvar x = jQuery(\"<div data-some='{\\n\\\"foo\\\":\\n\\t\\\"bar\\\"\\n}'></div>\");\n\tequal( x.data(\"some\").foo, \"bar\", \"got a JSON data- attribute with spaces\" );\n\tx.remove();\n});\n\ntest(\".data doesn't throw when calling selection is empty. #13551\", function() {\n\texpect(1);\n\n\ttry {\n\t\tjQuery( null ).data( \"prop\" );\n\t\tok( true, \"jQuery(null).data('prop') does not throw\" );\n\t} catch ( e ) {\n\t\tok( false, e.message );\n\t}\n});\n\ntest(\"jQuery.acceptData\", 6, function() {\n\tok( jQuery.acceptData( document ), \"document\" );\n\tok( jQuery.acceptData( document.documentElement ), \"documentElement\" );\n\tok( jQuery.acceptData( {} ), \"object\" );\n\n\tok( !jQuery.acceptData( document.createComment(\"\") ), \"comment\" );\n\tok( !jQuery.acceptData( document.createTextNode(\"\") ), \"text\" );\n\tok( !jQuery.acceptData( document.createDocumentFragment() ), \"documentFragment\" );\n});\n\ntest(\"Check proper data removal of non-element descendants nodes (#8335)\", 1, function() {\n\tvar div = jQuery(\"<div>text</div>\"),\n\t\ttext = div.contents();\n\n\ttext.data( \"test\", \"test\" ); // This should be a noop.\n\tdiv.remove();\n\n\tok( !text.data(\"test\"), \"Be sure data is not stored in non-element\" );\n});\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/jquery/test/unit/deferred.js",
    "content": "module( \"deferred\", {\n\tteardown: moduleTeardown\n});\n\njQuery.each( [ \"\", \" - new operator\" ], function( _, withNew ) {\n\n\tfunction createDeferred( fn ) {\n\t\treturn withNew ? new jQuery.Deferred( fn ) : jQuery.Deferred( fn );\n\t}\n\n\ttest( \"jQuery.Deferred\" + withNew, function() {\n\n\t\texpect( 23 );\n\n\t\tvar defer = createDeferred();\n\n\t\tstrictEqual( defer.pipe, defer.then, \"pipe is an alias of then\" );\n\n\t\tcreateDeferred().resolve().done(function() {\n\t\t\tok( true, \"Success on resolve\" );\n\t\t\tstrictEqual( this.state(), \"resolved\", \"Deferred is resolved (state)\" );\n\t\t}).fail(function() {\n\t\t\tok( false, \"Error on resolve\" );\n\t\t}).always(function() {\n\t\t\tok( true, \"Always callback on resolve\" );\n\t\t});\n\n\t\tcreateDeferred().reject().done(function() {\n\t\t\tok( false, \"Success on reject\" );\n\t\t}).fail(function() {\n\t\t\tok( true, \"Error on reject\" );\n\t\t\tstrictEqual( this.state(), \"rejected\", \"Deferred is rejected (state)\" );\n\t\t}).always(function() {\n\t\t\tok( true, \"Always callback on reject\" );\n\t\t});\n\n\t\tcreateDeferred(function( defer ) {\n\t\t\tok( this === defer, \"Defer passed as this & first argument\" );\n\t\t\tthis.resolve(\"done\");\n\t\t}).done(function( value ) {\n\t\t\tstrictEqual( value, \"done\", \"Passed function executed\" );\n\t\t});\n\n\t\tcreateDeferred(function( defer ) {\n\t\t\tvar promise = defer.promise(),\n\t\t\t\tfunc = function() {},\n\t\t\t\tfuncPromise = defer.promise( func );\n\t\t\tstrictEqual( defer.promise(), promise, \"promise is always the same\" );\n\t\t\tstrictEqual( funcPromise, func, \"non objects get extended\" );\n\t\t\tjQuery.each( promise, function( key ) {\n\t\t\t\tif ( !jQuery.isFunction( promise[ key ] ) ) {\n\t\t\t\t\tok( false, key + \" is a function (\" + jQuery.type( promise[ key ] ) + \")\" );\n\t\t\t\t}\n\t\t\t\tif ( promise[ key ] !== func[ key ] ) {\n\t\t\t\t\tstrictEqual( func[ key ], promise[ key ], key + \" is the same\" );\n\t\t\t\t}\n\t\t\t});\n\t\t});\n\n\t\tjQuery.expandedEach = jQuery.each;\n\t\tjQuery.expandedEach( \"resolve reject\".split(\" \"), function( _, change ) {\n\t\t\tcreateDeferred(function( defer ) {\n\t\t\t\tstrictEqual( defer.state(), \"pending\", \"pending after creation\" );\n\t\t\t\tvar checked = 0;\n\t\t\t\tdefer.progress(function( value ) {\n\t\t\t\t\tstrictEqual( value, checked, \"Progress: right value (\" + value + \") received\" );\n\t\t\t\t});\n\t\t\t\tfor ( checked = 0; checked < 3; checked++ ) {\n\t\t\t\t\tdefer.notify( checked );\n\t\t\t\t}\n\t\t\t\tstrictEqual( defer.state(), \"pending\", \"pending after notification\" );\n\t\t\t\tdefer[ change ]();\n\t\t\t\tnotStrictEqual( defer.state(), \"pending\", \"not pending after \" + change );\n\t\t\t\tdefer.notify();\n\t\t\t});\n\t\t});\n\t});\n});\n\n\ntest( \"jQuery.Deferred - chainability\", function() {\n\n\tvar defer = jQuery.Deferred();\n\n\texpect( 10 );\n\n\tjQuery.expandedEach = jQuery.each;\n\tjQuery.expandedEach( \"resolve reject notify resolveWith rejectWith notifyWith done fail progress always\".split(\" \"), function( _, method ) {\n\t\tvar object = {\n\t\t\tm: defer[ method ]\n\t\t};\n\t\tstrictEqual( object.m(), object, method + \" is chainable\" );\n\t});\n});\n\ntest( \"jQuery.Deferred.then - filtering (done)\", function() {\n\n\texpect( 4 );\n\n\tvar value1, value2, value3,\n\t\tdefer = jQuery.Deferred(),\n\t\tpiped = defer.then(function( a, b ) {\n\t\t\treturn a * b;\n\t\t});\n\n\tpiped.done(function( result ) {\n\t\tvalue3 = result;\n\t});\n\n\tdefer.done(function( a, b ) {\n\t\tvalue1 = a;\n\t\tvalue2 = b;\n\t});\n\n\tdefer.resolve( 2, 3 );\n\n\tstrictEqual( value1, 2, \"first resolve value ok\" );\n\tstrictEqual( value2, 3, \"second resolve value ok\" );\n\tstrictEqual( value3, 6, \"result of filter ok\" );\n\n\tjQuery.Deferred().reject().then(function() {\n\t\tok( false, \"then should not be called on reject\" );\n\t});\n\n\tjQuery.Deferred().resolve().then( jQuery.noop ).done(function( value ) {\n\t\tstrictEqual( value, undefined, \"then done callback can return undefined/null\" );\n\t});\n});\n\ntest( \"jQuery.Deferred.then - filtering (fail)\", function() {\n\n\texpect( 4 );\n\n\tvar value1, value2, value3,\n\t\tdefer = jQuery.Deferred(),\n\t\tpiped = defer.then( null, function( a, b ) {\n\t\t\treturn a * b;\n\t\t});\n\n\tpiped.fail(function( result ) {\n\t\tvalue3 = result;\n\t});\n\n\tdefer.fail(function( a, b ) {\n\t\tvalue1 = a;\n\t\tvalue2 = b;\n\t});\n\n\tdefer.reject( 2, 3 );\n\n\tstrictEqual( value1, 2, \"first reject value ok\" );\n\tstrictEqual( value2, 3, \"second reject value ok\" );\n\tstrictEqual( value3, 6, \"result of filter ok\" );\n\n\tjQuery.Deferred().resolve().then( null, function() {\n\t\tok( false, \"then should not be called on resolve\" );\n\t});\n\n\tjQuery.Deferred().reject().then( null, jQuery.noop ).fail(function( value ) {\n\t\tstrictEqual( value, undefined, \"then fail callback can return undefined/null\" );\n\t});\n});\n\ntest( \"jQuery.Deferred.then - filtering (progress)\", function() {\n\n\texpect( 3 );\n\n\tvar value1, value2, value3,\n\t\tdefer = jQuery.Deferred(),\n\t\tpiped = defer.then( null, null, function( a, b ) {\n\t\t\treturn a * b;\n\t\t});\n\n\tpiped.progress(function( result ) {\n\t\tvalue3 = result;\n\t});\n\n\tdefer.progress(function( a, b ) {\n\t\tvalue1 = a;\n\t\tvalue2 = b;\n\t});\n\n\tdefer.notify( 2, 3 );\n\n\tstrictEqual( value1, 2, \"first progress value ok\" );\n\tstrictEqual( value2, 3, \"second progress value ok\" );\n\tstrictEqual( value3, 6, \"result of filter ok\" );\n});\n\ntest( \"jQuery.Deferred.then - deferred (done)\", function() {\n\n\texpect( 3 );\n\n\tvar value1, value2, value3,\n\t\tdefer = jQuery.Deferred(),\n\t\tpiped = defer.then(function( a, b ) {\n\t\t\treturn jQuery.Deferred(function( defer ) {\n\t\t\t\tdefer.reject( a * b );\n\t\t\t});\n\t\t});\n\n\tpiped.fail(function( result ) {\n\t\tvalue3 = result;\n\t});\n\n\tdefer.done(function( a, b ) {\n\t\tvalue1 = a;\n\t\tvalue2 = b;\n\t});\n\n\tdefer.resolve( 2, 3 );\n\n\tstrictEqual( value1, 2, \"first resolve value ok\" );\n\tstrictEqual( value2, 3, \"second resolve value ok\" );\n\tstrictEqual( value3, 6, \"result of filter ok\" );\n});\n\ntest( \"jQuery.Deferred.then - deferred (fail)\", function() {\n\n\texpect( 3 );\n\n\tvar value1, value2, value3,\n\t\tdefer = jQuery.Deferred(),\n\t\tpiped = defer.then( null, function( a, b ) {\n\t\t\treturn jQuery.Deferred(function( defer ) {\n\t\t\t\tdefer.resolve( a * b );\n\t\t\t});\n\t\t});\n\n\tpiped.done(function( result ) {\n\t\tvalue3 = result;\n\t});\n\n\tdefer.fail(function( a, b ) {\n\t\tvalue1 = a;\n\t\tvalue2 = b;\n\t});\n\n\tdefer.reject( 2, 3 );\n\n\tstrictEqual( value1, 2, \"first reject value ok\" );\n\tstrictEqual( value2, 3, \"second reject value ok\" );\n\tstrictEqual( value3, 6, \"result of filter ok\" );\n});\n\ntest( \"jQuery.Deferred.then - deferred (progress)\", function() {\n\n\texpect( 3 );\n\n\tvar value1, value2, value3,\n\t\tdefer = jQuery.Deferred(),\n\t\tpiped = defer.then( null, null, function( a, b ) {\n\t\t\treturn jQuery.Deferred(function( defer ) {\n\t\t\t\tdefer.resolve( a * b );\n\t\t\t});\n\t\t});\n\n\tpiped.done(function( result ) {\n\t\tvalue3 = result;\n\t});\n\n\tdefer.progress(function( a, b ) {\n\t\tvalue1 = a;\n\t\tvalue2 = b;\n\t});\n\n\tdefer.notify( 2, 3 );\n\n\tstrictEqual( value1, 2, \"first progress value ok\" );\n\tstrictEqual( value2, 3, \"second progress value ok\" );\n\tstrictEqual( value3, 6, \"result of filter ok\" );\n});\n\ntest( \"jQuery.Deferred.then - context\", function() {\n\n\texpect( 7 );\n\n\tvar defer, piped, defer2, piped2,\n\t\tcontext = {};\n\n\tjQuery.Deferred().resolveWith( context, [ 2 ] ).then(function( value ) {\n\t\treturn value * 3;\n\t}).done(function( value ) {\n\t\tstrictEqual( this, context, \"custom context correctly propagated\" );\n\t\tstrictEqual( value, 6, \"proper value received\" );\n\t});\n\n\tjQuery.Deferred().resolve().then(function() {\n\t\treturn jQuery.Deferred().resolveWith(context);\n\t}).done(function() {\n\t\tstrictEqual( this, context, \"custom context of returned deferred correctly propagated\" );\n\t});\n\n\tdefer = jQuery.Deferred();\n\tpiped = defer.then(function( value ) {\n\t\treturn value * 3;\n\t});\n\n\tdefer.resolve( 2 );\n\n\tpiped.done(function( value ) {\n\t\tstrictEqual( this, piped, \"default context gets updated to latest promise in the chain\" );\n\t\tstrictEqual( value, 6, \"proper value received\" );\n\t});\n\n\tdefer2 = jQuery.Deferred();\n\tpiped2 = defer2.then();\n\n\tdefer2.resolve( 2 );\n\n\tpiped2.done(function( value ) {\n\t\tstrictEqual( this, piped2, \"default context gets updated to latest promise in the chain (without passing function)\" );\n\t\tstrictEqual( value, 2, \"proper value received (without passing function)\" );\n\t});\n});\n\ntest( \"jQuery.when\", function() {\n\n\texpect( 34 );\n\n\t// Some other objects\n\tjQuery.each({\n\t\t\"an empty string\": \"\",\n\t\t\"a non-empty string\": \"some string\",\n\t\t\"zero\": 0,\n\t\t\"a number other than zero\": 1,\n\t\t\"true\": true,\n\t\t\"false\": false,\n\t\t\"null\": null,\n\t\t\"undefined\": undefined,\n\t\t\"a plain object\": {}\n\t}, function( message, value ) {\n\t\tok(\n\t\t\tjQuery.isFunction(\n\t\t\t\tjQuery.when( value ).done(function( resolveValue ) {\n\t\t\t\t\tstrictEqual( this, window, \"Context is the global object with \" + message );\n\t\t\t\t\tstrictEqual( resolveValue, value, \"Test the promise was resolved with \" + message );\n\t\t\t\t}).promise\n\t\t\t),\n\t\t\t\"Test \" + message + \" triggers the creation of a new Promise\"\n\t\t);\n\t});\n\n\tok(\n\t\tjQuery.isFunction(\n\t\t\tjQuery.when().done(function( resolveValue ) {\n\t\t\t\tstrictEqual( this, window, \"Test the promise was resolved with window as its context\" );\n\t\t\t\tstrictEqual( resolveValue, undefined, \"Test the promise was resolved with no parameter\" );\n\t\t\t}).promise\n\t\t),\n\t\t\"Test calling when with no parameter triggers the creation of a new Promise\"\n\t);\n\n\tvar cache,\n\t\tcontext = {};\n\n\tjQuery.when( jQuery.Deferred().resolveWith( context ) ).done(function() {\n\t\tstrictEqual( this, context, \"when( promise ) propagates context\" );\n\t});\n\n\tjQuery.each([ 1, 2, 3 ], function( k, i ) {\n\n\t\tjQuery.when( cache || jQuery.Deferred(function() {\n\t\t\t\tthis.resolve( i );\n\t\t\t})\n\t\t).done(function( value ) {\n\n\t\t\tstrictEqual( value, 1, \"Function executed\" + ( i > 1 ? \" only once\" : \"\" ) );\n\t\t\tcache = value;\n\t\t});\n\n\t});\n});\n\ntest( \"jQuery.when - joined\", function() {\n\n\texpect( 119 );\n\n\tvar deferreds = {\n\t\t\tvalue: 1,\n\t\t\tsuccess: jQuery.Deferred().resolve( 1 ),\n\t\t\terror: jQuery.Deferred().reject( 0 ),\n\t\t\tfutureSuccess: jQuery.Deferred().notify( true ),\n\t\t\tfutureError: jQuery.Deferred().notify( true ),\n\t\t\tnotify: jQuery.Deferred().notify( true )\n\t\t},\n\t\twillSucceed = {\n\t\t\tvalue: true,\n\t\t\tsuccess: true,\n\t\t\tfutureSuccess: true\n\t\t},\n\t\twillError = {\n\t\t\terror: true,\n\t\t\tfutureError: true\n\t\t},\n\t\twillNotify = {\n\t\t\tfutureSuccess: true,\n\t\t\tfutureError: true,\n\t\t\tnotify: true\n\t\t};\n\n\tjQuery.each( deferreds, function( id1, defer1 ) {\n\t\tjQuery.each( deferreds, function( id2, defer2 ) {\n\t\t\tvar shouldResolve = willSucceed[ id1 ] && willSucceed[ id2 ],\n\t\t\t\tshouldError = willError[ id1 ] || willError[ id2 ],\n\t\t\t\tshouldNotify = willNotify[ id1 ] || willNotify[ id2 ],\n\t\t\t\texpected = shouldResolve ? [ 1, 1 ] : [ 0, undefined ],\n\t\t\t\texpectedNotify = shouldNotify && [ willNotify[ id1 ], willNotify[ id2 ] ],\n\t\t\t\tcode = id1 + \"/\" + id2,\n\t\t\t\tcontext1 = defer1 && jQuery.isFunction( defer1.promise ) ? defer1.promise() : undefined,\n\t\t\t\tcontext2 = defer2 && jQuery.isFunction( defer2.promise ) ? defer2.promise() : undefined;\n\n\t\t\tjQuery.when( defer1, defer2 ).done(function( a, b ) {\n\t\t\t\tif ( shouldResolve ) {\n\t\t\t\t\tdeepEqual( [ a, b ], expected, code + \" => resolve\" );\n\t\t\t\t\tstrictEqual( this[ 0 ], context1, code + \" => first context OK\" );\n\t\t\t\t\tstrictEqual( this[ 1 ], context2, code + \" => second context OK\" );\n\t\t\t\t} else {\n\t\t\t\t\tok( false,  code + \" => resolve\" );\n\t\t\t\t}\n\t\t\t}).fail(function( a, b ) {\n\t\t\t\tif ( shouldError ) {\n\t\t\t\t\tdeepEqual( [ a, b ], expected, code + \" => reject\" );\n\t\t\t\t} else {\n\t\t\t\t\tok( false, code + \" => reject\" );\n\t\t\t\t}\n\t\t\t}).progress(function( a, b ) {\n\t\t\t\tdeepEqual( [ a, b ], expectedNotify, code + \" => progress\" );\n\t\t\t\tstrictEqual( this[ 0 ], expectedNotify[ 0 ] ? context1 : undefined, code + \" => first context OK\" );\n\t\t\t\tstrictEqual( this[ 1 ], expectedNotify[ 1 ] ? context2 : undefined, code + \" => second context OK\" );\n\t\t\t});\n\t\t});\n\t});\n\tdeferreds.futureSuccess.resolve( 1 );\n\tdeferreds.futureError.reject( 0 );\n});\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/jquery/test/unit/deprecated.js",
    "content": "module(\"deprecated\", { teardown: moduleTeardown });\n\nif ( jQuery.fn.size ) {\n\ttest(\"size()\", function() {\n\t\texpect(1);\n\t\tequal( jQuery(\"#qunit-fixture p\").size(), 6, \"Get Number of Elements Found\" );\n\t});\n}\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/jquery/test/unit/dimensions.js",
    "content": "(function() {\n\nif ( !jQuery.fn.width ) {\n\treturn;\n}\n\nmodule(\"dimensions\", { teardown: moduleTeardown });\n\nfunction pass( val ) {\n\treturn val;\n}\n\nfunction fn( val ) {\n\treturn function() {\n\t\treturn val;\n\t};\n}\n\n/*\n\t======== local reference =======\n\tpass and fn can be used to test passing functions to setters\n\tSee testWidth below for an example\n\n\tpass( value );\n\t\tThis function returns whatever value is passed in\n\n\tfn( value );\n\t\tReturns a function that returns the value\n*/\n\nfunction testWidth( val ) {\n\texpect(9);\n\tvar $div, blah;\n\n\t$div = jQuery(\"#nothiddendiv\");\n\t$div.width( val(30) );\n\tequal($div.width(), 30, \"Test set to 30 correctly\");\n\t$div.hide();\n\tequal($div.width(), 30, \"Test hidden div\");\n\t$div.show();\n\t$div.width( val(-1) ); // handle negative numbers by setting to 0 #11604\n\tequal($div.width(), 0, \"Test negative width normalized to 0\");\n\t$div.css(\"padding\", \"20px\");\n\tequal($div.width(), 0, \"Test padding specified with pixels\");\n\t$div.css(\"border\", \"2px solid #fff\");\n\tequal($div.width(), 0, \"Test border specified with pixels\");\n\n\t$div.css({ \"display\": \"\", \"border\": \"\", \"padding\": \"\" });\n\n\tjQuery(\"#nothiddendivchild\").css({ \"width\": 20, \"padding\": \"3px\", \"border\": \"2px solid #fff\" });\n\tequal(jQuery(\"#nothiddendivchild\").width(), 20, \"Test child width with border and padding\");\n\tjQuery(\"#nothiddendiv, #nothiddendivchild\").css({ \"border\": \"\", \"padding\": \"\", \"width\": \"\" });\n\n\tblah = jQuery(\"blah\");\n\tequal( blah.width( val(10) ), blah, \"Make sure that setting a width on an empty set returns the set.\" );\n\tequal( blah.width(), null, \"Make sure 'null' is returned on an empty set\");\n\n\tequal( jQuery(window).width(), document.documentElement.clientWidth, \"Window width is equal to width reported by window/document.\" );\n\n\tQUnit.expectJqData( $div[0], \"olddisplay\" );\n}\n\ntest(\"width()\", function() {\n\ttestWidth( pass );\n});\n\ntest(\"width(Function)\", function() {\n\ttestWidth( fn );\n});\n\ntest(\"width(Function(args))\", function() {\n\texpect( 2 );\n\n\tvar $div = jQuery(\"#nothiddendiv\");\n\t$div.width( 30 ).width(function(i, width) {\n\t\tequal( width, 30, \"Make sure previous value is correct.\" );\n\t\treturn width + 1;\n\t});\n\n\tequal( $div.width(), 31, \"Make sure value was modified correctly.\" );\n});\n\nfunction testHeight( val ) {\n\texpect(9);\n\n\tvar $div, blah;\n\n\t$div = jQuery(\"#nothiddendiv\");\n\t$div.height( val(30) );\n\tequal($div.height(), 30, \"Test set to 30 correctly\");\n\t$div.hide();\n\tequal($div.height(), 30, \"Test hidden div\");\n\t$div.show();\n\t$div.height( val(-1) ); // handle negative numbers by setting to 0 #11604\n\tequal($div.height(), 0, \"Test negative height normalized to 0\");\n\t$div.css(\"padding\", \"20px\");\n\tequal($div.height(), 0, \"Test padding specified with pixels\");\n\t$div.css(\"border\", \"2px solid #fff\");\n\tequal($div.height(), 0, \"Test border specified with pixels\");\n\n\t$div.css({ \"display\": \"\", \"border\": \"\", \"padding\": \"\", \"height\": \"1px\" });\n\n\tjQuery(\"#nothiddendivchild\").css({ \"height\": 20, \"padding\": \"3px\", \"border\": \"2px solid #fff\" });\n\tequal(jQuery(\"#nothiddendivchild\").height(), 20, \"Test child height with border and padding\");\n\tjQuery(\"#nothiddendiv, #nothiddendivchild\").css({ \"border\": \"\", \"padding\": \"\", \"height\": \"\" });\n\n\tblah = jQuery(\"blah\");\n\tequal( blah.height( val(10) ), blah, \"Make sure that setting a height on an empty set returns the set.\" );\n\tequal( blah.height(), null, \"Make sure 'null' is returned on an empty set\");\n\n\tequal( jQuery(window).height(), document.documentElement.clientHeight, \"Window width is equal to width reported by window/document.\" );\n\n\tQUnit.expectJqData( $div[0], \"olddisplay\" );\n}\n\ntest(\"height()\", function() {\n\ttestHeight( pass );\n});\n\ntest(\"height(Function)\", function() {\n\ttestHeight( fn );\n});\n\ntest(\"height(Function(args))\", function() {\n\texpect( 2 );\n\n\tvar $div = jQuery(\"#nothiddendiv\");\n\t$div.height( 30 ).height(function(i, height) {\n\t\tequal( height, 30, \"Make sure previous value is correct.\" );\n\t\treturn height + 1;\n\t});\n\n\tequal( $div.height(), 31, \"Make sure value was modified correctly.\" );\n});\n\ntest(\"innerWidth()\", function() {\n\texpect(6);\n\n\tvar $div, div,\n\t\twinWidth = jQuery( window ).width(),\n\t\tdocWidth = jQuery( document ).width();\n\n\tequal(jQuery(window).innerWidth(), winWidth, \"Test on window\");\n\tequal(jQuery(document).innerWidth(), docWidth, \"Test on document\");\n\n\t$div = jQuery(\"#nothiddendiv\");\n\t// set styles\n\t$div.css({\n\t\t\"margin\": 10,\n\t\t\"border\": \"2px solid #fff\",\n\t\t\"width\": 30\n\t});\n\n\tequal($div.innerWidth(), 30, \"Test with margin and border\");\n\t$div.css(\"padding\", \"20px\");\n\tequal($div.innerWidth(), 70, \"Test with margin, border and padding\");\n\t$div.hide();\n\tequal($div.innerWidth(), 70, \"Test hidden div\");\n\n\t// reset styles\n\t$div.css({ \"display\": \"\", \"border\": \"\", \"padding\": \"\", \"width\": \"\", \"height\": \"\" });\n\n\tdiv = jQuery( \"<div>\" );\n\n\t// Temporarily require 0 for backwards compat - should be auto\n\tequal( div.innerWidth(), 0, \"Make sure that disconnected nodes are handled.\" );\n\n\tdiv.remove();\n\tQUnit.expectJqData( $div[0], \"olddisplay\" );\n});\n\ntest(\"innerHeight()\", function() {\n\texpect(6);\n\n\tvar $div, div,\n\t\twinHeight = jQuery( window ).height(),\n\t\tdocHeight = jQuery( document ).height();\n\n\tequal(jQuery(window).innerHeight(), winHeight, \"Test on window\");\n\tequal(jQuery(document).innerHeight(), docHeight, \"Test on document\");\n\n\t$div = jQuery(\"#nothiddendiv\");\n\t// set styles\n\t$div.css({\n\t\t\"margin\": 10,\n\t\t\"border\": \"2px solid #fff\",\n\t\t\"height\": 30\n\t});\n\n\tequal($div.innerHeight(), 30, \"Test with margin and border\");\n\t$div.css(\"padding\", \"20px\");\n\tequal($div.innerHeight(), 70, \"Test with margin, border and padding\");\n\t$div.hide();\n\tequal($div.innerHeight(), 70, \"Test hidden div\");\n\n\t// reset styles\n\t$div.css({ \"display\": \"\", \"border\": \"\", \"padding\": \"\", \"width\": \"\", \"height\": \"\" });\n\n\tdiv = jQuery( \"<div>\" );\n\n\t// Temporarily require 0 for backwards compat - should be auto\n\tequal( div.innerHeight(), 0, \"Make sure that disconnected nodes are handled.\" );\n\n\tdiv.remove();\n\tQUnit.expectJqData( $div[0], \"olddisplay\" );\n});\n\ntest(\"outerWidth()\", function() {\n\texpect(11);\n\n\tvar $div, div,\n\twinWidth = jQuery( window ).width(),\n\t\tdocWidth = jQuery( document ).width();\n\n\tequal( jQuery( window ).outerWidth(), winWidth, \"Test on window without margin option\" );\n\tequal( jQuery( window ).outerWidth( true ), winWidth, \"Test on window with margin option\" );\n\tequal( jQuery( document ).outerWidth(), docWidth, \"Test on document without margin option\" );\n\tequal( jQuery( document ).outerWidth( true ), docWidth, \"Test on document with margin option\" );\n\n\t$div = jQuery(\"#nothiddendiv\");\n\t$div.css(\"width\", 30);\n\n\tequal($div.outerWidth(), 30, \"Test with only width set\");\n\t$div.css(\"padding\", \"20px\");\n\tequal($div.outerWidth(), 70, \"Test with padding\");\n\t$div.css(\"border\", \"2px solid #fff\");\n\tequal($div.outerWidth(), 74, \"Test with padding and border\");\n\t$div.css(\"margin\", \"10px\");\n\tequal($div.outerWidth(), 74, \"Test with padding, border and margin without margin option\");\n\t$div.css(\"position\", \"absolute\");\n\tequal($div.outerWidth(true), 94, \"Test with padding, border and margin with margin option\");\n\t$div.hide();\n\tequal($div.outerWidth(true), 94, \"Test hidden div with padding, border and margin with margin option\");\n\n\t// reset styles\n\t$div.css({ \"position\": \"\", \"display\": \"\", \"border\": \"\", \"padding\": \"\", \"width\": \"\", \"height\": \"\" });\n\n\tdiv = jQuery( \"<div>\" );\n\n\t// Temporarily require 0 for backwards compat - should be auto\n\tequal( div.outerWidth(), 0, \"Make sure that disconnected nodes are handled.\" );\n\n\tdiv.remove();\n\tQUnit.expectJqData( $div[0], \"olddisplay\" );\n});\n\ntest(\"child of a hidden elem (or unconnected node) has accurate inner/outer/Width()/Height()  see #9441 #9300\", function() {\n\texpect(16);\n\n\t// setup html\n\tvar $divNormal = jQuery(\"<div>\").css({ \"width\": \"100px\", \"height\": \"100px\", \"border\": \"10px solid white\", \"padding\": \"2px\", \"margin\": \"3px\" }),\n\t\t$divChild = $divNormal.clone(),\n\t\t$divUnconnected = $divNormal.clone(),\n\t\t$divHiddenParent = jQuery(\"<div>\").css( \"display\", \"none\" ).append( $divChild ).appendTo(\"body\");\n\t$divNormal.appendTo(\"body\");\n\n\t// tests that child div of a hidden div works the same as a normal div\n\tequal( $divChild.width(), $divNormal.width(), \"child of a hidden element width() is wrong see #9441\" );\n\tequal( $divChild.innerWidth(), $divNormal.innerWidth(), \"child of a hidden element innerWidth() is wrong see #9441\" );\n\tequal( $divChild.outerWidth(), $divNormal.outerWidth(), \"child of a hidden element outerWidth() is wrong see #9441\" );\n\tequal( $divChild.outerWidth(true), $divNormal.outerWidth( true ), \"child of a hidden element outerWidth( true ) is wrong see #9300\" );\n\n\tequal( $divChild.height(), $divNormal.height(), \"child of a hidden element height() is wrong see #9441\" );\n\tequal( $divChild.innerHeight(), $divNormal.innerHeight(), \"child of a hidden element innerHeight() is wrong see #9441\" );\n\tequal( $divChild.outerHeight(), $divNormal.outerHeight(), \"child of a hidden element outerHeight() is wrong see #9441\" );\n\tequal( $divChild.outerHeight(true), $divNormal.outerHeight( true ), \"child of a hidden element outerHeight( true ) is wrong see #9300\" );\n\n\t// tests that child div of an unconnected div works the same as a normal div\n\tequal( $divUnconnected.width(), $divNormal.width(), \"unconnected element width() is wrong see #9441\" );\n\tequal( $divUnconnected.innerWidth(), $divNormal.innerWidth(), \"unconnected element innerWidth() is wrong see #9441\" );\n\tequal( $divUnconnected.outerWidth(), $divNormal.outerWidth(), \"unconnected element outerWidth() is wrong see #9441\" );\n\tequal( $divUnconnected.outerWidth(true), $divNormal.outerWidth( true ), \"unconnected element outerWidth( true ) is wrong see #9300\" );\n\n\tequal( $divUnconnected.height(), $divNormal.height(), \"unconnected element height() is wrong see #9441\" );\n\tequal( $divUnconnected.innerHeight(), $divNormal.innerHeight(), \"unconnected element innerHeight() is wrong see #9441\" );\n\tequal( $divUnconnected.outerHeight(), $divNormal.outerHeight(), \"unconnected element outerHeight() is wrong see #9441\" );\n\tequal( $divUnconnected.outerHeight(true), $divNormal.outerHeight( true ), \"unconnected element outerHeight( true ) is wrong see #9300\" );\n\n\t// teardown html\n\t$divHiddenParent.remove();\n\t$divNormal.remove();\n});\n\ntest(\"getting dimensions shouldn't modify runtimeStyle see #9233\", function() {\n\texpect( 1 );\n\n\tvar $div = jQuery( \"<div>\" ).appendTo( \"#qunit-fixture\" ),\n\t\tdiv = $div.get( 0 ),\n\t\truntimeStyle = div.runtimeStyle;\n\n\tif ( runtimeStyle ) {\n\t\tdiv.runtimeStyle.marginLeft = \"12em\";\n\t\tdiv.runtimeStyle.left = \"11em\";\n\t}\n\n\t$div.outerWidth( true );\n\n\tif ( runtimeStyle ) {\n\t\tequal( div.runtimeStyle.left, \"11em\", \"getting dimensions modifies runtimeStyle, see #9233\" );\n\t} else {\n\t\tok( true, \"this browser doesn't support runtimeStyle, see #9233\" );\n\t}\n\n\t$div.remove();\n});\n\ntest( \"table dimensions\", 2, function() {\n\tvar table = jQuery(\"<table><colgroup><col/><col/></colgroup><tbody><tr><td></td><td>a</td></tr><tr><td></td><td>a</td></tr></tbody></table>\").appendTo(\"#qunit-fixture\"),\n\t\ttdElem = table.find(\"td\").first(),\n\t\tcolElem = table.find(\"col\").first().width( 300 );\n\n\ttable.find(\"td\").css({ \"margin\": 0, \"padding\": 0 });\n\n\tequal( tdElem.width(), tdElem.width(), \"width() doesn't alter dimension values of empty cells, see #11293\" );\n\tequal( colElem.width(), 300, \"col elements have width(), see #12243\" );\n});\n\ntest(\"box-sizing:border-box child of a hidden elem (or unconnected node) has accurate inner/outer/Width()/Height()  see #10413\", function() {\n\texpect(16);\n\n\t// setup html\n\tvar $divNormal = jQuery(\"<div>\").css({ \"boxSizing\": \"border-box\", \"width\": \"100px\", \"height\": \"100px\", \"border\": \"10px solid white\", \"padding\": \"2px\", \"margin\": \"3px\" }),\n\t\t$divChild = $divNormal.clone(),\n\t\t$divUnconnected = $divNormal.clone(),\n\t\t$divHiddenParent = jQuery(\"<div>\").css( \"display\", \"none\" ).append( $divChild ).appendTo(\"body\");\n\t$divNormal.appendTo(\"body\");\n\n\t// tests that child div of a hidden div works the same as a normal div\n\tequal( $divChild.width(), $divNormal.width(), \"child of a hidden element width() is wrong see #10413\" );\n\tequal( $divChild.innerWidth(), $divNormal.innerWidth(), \"child of a hidden element innerWidth() is wrong see #10413\" );\n\tequal( $divChild.outerWidth(), $divNormal.outerWidth(), \"child of a hidden element outerWidth() is wrong see #10413\" );\n\tequal( $divChild.outerWidth(true), $divNormal.outerWidth( true ), \"child of a hidden element outerWidth( true ) is wrong see #10413\" );\n\n\tequal( $divChild.height(), $divNormal.height(), \"child of a hidden element height() is wrong see #10413\" );\n\tequal( $divChild.innerHeight(), $divNormal.innerHeight(), \"child of a hidden element innerHeight() is wrong see #10413\" );\n\tequal( $divChild.outerHeight(), $divNormal.outerHeight(), \"child of a hidden element outerHeight() is wrong see #10413\" );\n\tequal( $divChild.outerHeight(true), $divNormal.outerHeight( true ), \"child of a hidden element outerHeight( true ) is wrong see #10413\" );\n\n\t// tests that child div of an unconnected div works the same as a normal div\n\tequal( $divUnconnected.width(), $divNormal.width(), \"unconnected element width() is wrong see #10413\" );\n\tequal( $divUnconnected.innerWidth(), $divNormal.innerWidth(), \"unconnected element innerWidth() is wrong see #10413\" );\n\tequal( $divUnconnected.outerWidth(), $divNormal.outerWidth(), \"unconnected element outerWidth() is wrong see #10413\" );\n\tequal( $divUnconnected.outerWidth(true), $divNormal.outerWidth( true ), \"unconnected element outerWidth( true ) is wrong see #10413\" );\n\n\tequal( $divUnconnected.height(), $divNormal.height(), \"unconnected element height() is wrong see #10413\" );\n\tequal( $divUnconnected.innerHeight(), $divNormal.innerHeight(), \"unconnected element innerHeight() is wrong see #10413\" );\n\tequal( $divUnconnected.outerHeight(), $divNormal.outerHeight(), \"unconnected element outerHeight() is wrong see #10413\" );\n\tequal( $divUnconnected.outerHeight(true), $divNormal.outerHeight( true ), \"unconnected element outerHeight( true ) is wrong see #10413\" );\n\n\t// teardown html\n\t$divHiddenParent.remove();\n\t$divNormal.remove();\n});\n\ntest(\"outerHeight()\", function() {\n\texpect(11);\n\n\tvar $div, div,\n\twinHeight = jQuery( window ).height(),\n\t\tdocHeight = jQuery( document ).height();\n\n\n\tequal( jQuery( window ).outerHeight(), winHeight, \"Test on window without margin option\" );\n\tequal( jQuery( window ).outerHeight( true ), winHeight, \"Test on window with margin option\" );\n\tequal( jQuery( document ).outerHeight(), docHeight, \"Test on document without margin option\" );\n\tequal( jQuery( document ).outerHeight( true ), docHeight, \"Test on document with margin option\" );\n\n\t$div = jQuery(\"#nothiddendiv\");\n\t$div.css(\"height\", 30);\n\n\tequal($div.outerHeight(), 30, \"Test with only width set\");\n\t$div.css(\"padding\", \"20px\");\n\tequal($div.outerHeight(), 70, \"Test with padding\");\n\t$div.css(\"border\", \"2px solid #fff\");\n\tequal($div.outerHeight(), 74, \"Test with padding and border\");\n\t$div.css(\"margin\", \"10px\");\n\tequal($div.outerHeight(), 74, \"Test with padding, border and margin without margin option\");\n\tequal($div.outerHeight(true), 94, \"Test with padding, border and margin with margin option\");\n\t$div.hide();\n\tequal($div.outerHeight(true), 94, \"Test hidden div with padding, border and margin with margin option\");\n\n\t// reset styles\n\t$div.css({ \"display\": \"\", \"border\": \"\", \"padding\": \"\", \"width\": \"\", \"height\": \"\" });\n\n\tdiv = jQuery( \"<div>\" );\n\n\t// Temporarily require 0 for backwards compat - should be auto\n\tequal( div.outerHeight(), 0, \"Make sure that disconnected nodes are handled.\" );\n\n\tdiv.remove();\n\tQUnit.expectJqData( $div[0], \"olddisplay\" );\n});\n\ntest(\"passing undefined is a setter #5571\", function() {\n\texpect(4);\n\tequal(jQuery(\"#nothiddendiv\").height(30).height(undefined).height(), 30, \".height(undefined) is chainable (#5571)\");\n\tequal(jQuery(\"#nothiddendiv\").height(30).innerHeight(undefined).height(), 30, \".innerHeight(undefined) is chainable (#5571)\");\n\tequal(jQuery(\"#nothiddendiv\").height(30).outerHeight(undefined).height(), 30, \".outerHeight(undefined) is chainable (#5571)\");\n\tequal(jQuery(\"#nothiddendiv\").width(30).width(undefined).width(), 30, \".width(undefined) is chainable (#5571)\");\n});\n\ntest( \"getters on non elements should return null\", function() {\n\texpect( 8 );\n\n\tvar nonElem = jQuery(\"notAnElement\");\n\n\tstrictEqual( nonElem.width(), null, \".width() is not null (#12283)\" );\n\tstrictEqual( nonElem.innerWidth(), null, \".innerWidth() is not null (#12283)\" );\n\tstrictEqual( nonElem.outerWidth(), null, \".outerWidth() is not null (#12283)\" );\n\tstrictEqual( nonElem.outerWidth( true ), null, \".outerWidth(true) is not null (#12283)\" );\n\n\tstrictEqual( nonElem.height(), null, \".height() is not null (#12283)\" );\n\tstrictEqual( nonElem.innerHeight(), null, \".innerHeight() is not null (#12283)\" );\n\tstrictEqual( nonElem.outerHeight(), null, \".outerHeight() is not null (#12283)\" );\n\tstrictEqual( nonElem.outerHeight( true ), null, \".outerHeight(true) is not null (#12283)\" );\n});\n\ntest(\"setters with and without box-sizing:border-box\", function(){\n\texpect(20);\n\n\t// Support: Firefox, Android 2.3 (Prefixed box-sizing versions).\n\tvar el_bb = jQuery(\"<div style='width:114px;height:114px;margin:5px;padding:3px;border:4px solid white;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;'>test</div>\").appendTo(\"#qunit-fixture\"),\n\t\tel = jQuery(\"<div style='width:100px;height:100px;margin:5px;padding:3px;border:4px solid white;'>test</div>\").appendTo(\"#qunit-fixture\"),\n\t\texpected = 100;\n\n\tequal( el_bb.width( 101 ).width(), expected + 1, \"test border-box width(int) by roundtripping\" );\n\tequal( el_bb.innerWidth( 108 ).width(), expected + 2, \"test border-box innerWidth(int) by roundtripping\" );\n\tequal( el_bb.outerWidth( 117 ).width(), expected + 3, \"test border-box outerWidth(int) by roundtripping\" );\n\tequal( el_bb.outerWidth( 118, false ).width(), expected + 4, \"test border-box outerWidth(int, false) by roundtripping\" );\n\tequal( el_bb.outerWidth( 129, true ).width(), expected + 5, \"test border-box innerWidth(int, true) by roundtripping\" );\n\n\tequal( el_bb.height( 101 ).height(), expected + 1, \"test border-box height(int) by roundtripping\" );\n\tequal( el_bb.innerHeight( 108 ).height(), expected + 2, \"test border-box innerHeight(int) by roundtripping\" );\n\tequal( el_bb.outerHeight( 117 ).height(), expected + 3, \"test border-box outerHeight(int) by roundtripping\" );\n\tequal( el_bb.outerHeight( 118, false ).height(), expected + 4, \"test border-box outerHeight(int, false) by roundtripping\" );\n\tequal( el_bb.outerHeight( 129, true ).height(), expected + 5, \"test border-box innerHeight(int, true) by roundtripping\" );\n\n\tequal( el.width( 101 ).width(), expected + 1, \"test border-box width(int) by roundtripping\" );\n\tequal( el.innerWidth( 108 ).width(), expected + 2, \"test border-box innerWidth(int) by roundtripping\" );\n\tequal( el.outerWidth( 117 ).width(), expected + 3, \"test border-box outerWidth(int) by roundtripping\" );\n\tequal( el.outerWidth( 118, false ).width(), expected + 4, \"test border-box outerWidth(int, false) by roundtripping\" );\n\tequal( el.outerWidth( 129, true ).width(), expected + 5, \"test border-box innerWidth(int, true) by roundtripping\" );\n\n\tequal( el.height( 101 ).height(), expected + 1, \"test border-box height(int) by roundtripping\" );\n\tequal( el.innerHeight( 108 ).height(), expected + 2, \"test border-box innerHeight(int) by roundtripping\" );\n\tequal( el.outerHeight( 117 ).height(), expected + 3, \"test border-box outerHeight(int) by roundtripping\" );\n\tequal( el.outerHeight( 118, false ).height(), expected + 4, \"test border-box outerHeight(int, false) by roundtripping\" );\n\tequal( el.outerHeight( 129, true ).height(), expected + 5, \"test border-box innerHeight(int, true) by roundtripping\" );\n});\n\ntestIframe( \"dimensions/documentSmall\", \"window vs. small document\", function( jQuery, window, document ) {\n\t// this test is practically tautological, but there is a bug in IE8\n\t// with no simple workaround, so this test exposes the bug and works around it\n\tif ( document.body.offsetWidth >= document.documentElement.offsetWidth ) {\n\t\texpect( 2 );\n\n\t\tequal( jQuery( document ).height(), jQuery( window ).height(), \"document height matches window height\" );\n\t\tequal( jQuery( document ).width(), jQuery( window ).width(), \"document width matches window width\" );\n\t} else {\n\t\t// all tests should have at least one assertion\n\t\texpect( 1 );\n\t\tok( true, \"skipping test (conditions not satisfied)\" );\n\t}\n});\n\ntestIframe( \"dimensions/documentLarge\", \"window vs. large document\", function( jQuery, window, document ) {\n\texpect(2);\n\n\tok( jQuery( document ).height() > jQuery( window ).height(), \"document height is larger than window height\" );\n\tok( jQuery( document ).width() > jQuery( window ).width(), \"document width is larger than window width\" );\n});\n\n})();\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/jquery/test/unit/effects.js",
    "content": "(function() {\n\n// Can't test what ain't there\nif ( !jQuery.fx ) {\n\treturn;\n}\n\nvar off = jQuery.fx.off;\n\nmodule(\"effects\", {\n\tteardown: function() {\n\t\tjQuery.fx.off = off;\n\t\treturn moduleTeardown.apply( this, arguments );\n\t}\n});\n\ntest(\"sanity check\", function() {\n\texpect(1);\n\tok( jQuery(\"#dl:visible, #qunit-fixture:visible, #foo:visible\").length === 3, \"QUnit state is correct for testing effects\" );\n});\n\ntest(\"show() basic\", 2, function() {\n\tvar div,\n\t\thiddendiv = jQuery(\"div.hidden\");\n\n\thiddendiv.hide().show();\n\n\tequal( hiddendiv.css(\"display\"), \"block\", \"Make sure a pre-hidden div is visible.\" );\n\n\tdiv = jQuery(\"<div>\").hide().appendTo(\"#qunit-fixture\").show();\n\n\tequal( div.css(\"display\"), \"block\", \"Make sure pre-hidden divs show\" );\n\n\t// Clean up the detached node\n\tdiv.remove();\n\n\tQUnit.expectJqData(hiddendiv, \"olddisplay\");\n});\n\ntest(\"show()\", 27, function () {\n\tvar div, speeds, old, test,\n\t\thiddendiv = jQuery(\"div.hidden\");\n\n\tequal(jQuery.css( hiddendiv[0], \"display\"), \"none\", \"hiddendiv is display: none\");\n\n\thiddendiv.css(\"display\", \"block\");\n\tequal(jQuery.css( hiddendiv[0], \"display\"), \"block\", \"hiddendiv is display: block\");\n\n\thiddendiv.show();\n\tequal(jQuery.css( hiddendiv[0], \"display\"), \"block\", \"hiddendiv is display: block\");\n\n\thiddendiv.css(\"display\",\"\");\n\n\tdiv = jQuery(\"#fx-queue div\").slice(0, 4);\n\tdiv.show().each(function() {\n\t\tnotEqual(this.style.display, \"none\", \"don't change any <div> with display block\");\n\t});\n\n\tspeeds = {\n\t\t\"null speed\": null,\n\t\t\"undefined speed\": undefined,\n\t\t\"false speed\": false\n\t};\n\n\tjQuery.each(speeds, function(name, speed) {\n\t\tvar pass = true;\n\t\tdiv.hide().show(speed).each(function() {\n\t\t\tif ( this.style.display === \"none\" ) {\n\t\t\t\tpass = false;\n\t\t\t}\n\t\t});\n\t\tok( pass, \"Show with \" + name);\n\t});\n\n\tjQuery.each(speeds, function(name, speed) {\n\t\tvar pass = true;\n\t\tdiv.hide().show(speed, function() {\n\t\t\tpass = false;\n\t\t});\n\t\tok( pass, \"Show with \" + name + \" does not call animate callback\" );\n\t});\n\n\t// Tolerate data from show()/hide()\n\tQUnit.expectJqData(div, \"olddisplay\");\n\n\t// #show-tests * is set display: none in CSS\n\tjQuery(\"#qunit-fixture\").append(\"<div id='show-tests'><div><p><a href='#'></a></p><code></code><pre></pre><span></span></div><table><thead><tr><th></th></tr></thead><tbody><tr><td></td></tr></tbody></table><ul><li></li></ul></div><table id='test-table'></table>\");\n\n\told = jQuery(\"#test-table\").show().css(\"display\") !== \"table\";\n\tjQuery(\"#test-table\").remove();\n\n\ttest = {\n\t\t\"div\"      : \"block\",\n\t\t\"p\"        : \"block\",\n\t\t\"a\"        : \"inline\",\n\t\t\"code\"     : \"inline\",\n\t\t\"pre\"      : \"block\",\n\t\t\"span\"     : \"inline\",\n\t\t\"table\"    : old ? \"block\" : \"table\",\n\t\t\"thead\"    : old ? \"block\" : \"table-header-group\",\n\t\t\"tbody\"    : old ? \"block\" : \"table-row-group\",\n\t\t\"tr\"       : old ? \"block\" : \"table-row\",\n\t\t\"th\"       : old ? \"block\" : \"table-cell\",\n\t\t\"td\"       : old ? \"block\" : \"table-cell\",\n\t\t\"ul\"       : \"block\",\n\t\t\"li\"       : old ? \"block\" : \"list-item\"\n\t};\n\n\tjQuery.each(test, function(selector, expected) {\n\t\tvar elem = jQuery(selector, \"#show-tests\").show();\n\t\tequal( elem.css(\"display\"), expected, \"Show using correct display type for \" + selector );\n\t});\n\n\tjQuery(\"#show-tests\").remove();\n\n\t// Make sure that showing or hiding a text node doesn't cause an error\n\tjQuery(\"<div>test</div> text <span>test</span>\").show().remove();\n\tjQuery(\"<div>test</div> text <span>test</span>\").hide().remove();\n});\n\ntest(\"show(Number) - other displays\", function() {\n\texpect(15);\n\tQUnit.reset();\n\tstop();\n\n\t// #show-tests * is set display: none in CSS\n\tjQuery(\"#qunit-fixture\").append(\"<div id='show-tests'><div><p><a href='#'></a></p><code></code><pre></pre><span></span></div><table><thead><tr><th></th></tr></thead><tbody><tr><td></td></tr></tbody></table><ul><li></li></ul></div><table id='test-table'></table>\");\n\n\tvar test,\n\t\told = jQuery(\"#test-table\").show().css(\"display\") !== \"table\",\n\t\tnum = 0;\n\tjQuery(\"#test-table\").remove();\n\n\ttest = {\n\t\t\"div\"      : \"block\",\n\t\t\"p\"        : \"block\",\n\t\t\"a\"        : \"inline\",\n\t\t\"code\"     : \"inline\",\n\t\t\"pre\"      : \"block\",\n\t\t\"span\"     : \"inline\",\n\t\t\"table\"    : old ? \"block\" : \"table\",\n\t\t\"thead\"    : old ? \"block\" : \"table-header-group\",\n\t\t\"tbody\"    : old ? \"block\" : \"table-row-group\",\n\t\t\"tr\"       : old ? \"block\" : \"table-row\",\n\t\t\"th\"       : old ? \"block\" : \"table-cell\",\n\t\t\"td\"       : old ? \"block\" : \"table-cell\",\n\t\t\"ul\"       : \"block\",\n\t\t\"li\"       : old ? \"block\" : \"list-item\"\n\t};\n\n\tjQuery.each(test, function(selector, expected) {\n\t\tvar elem = jQuery(selector, \"#show-tests\").show(1, function() {\n\t\t\tequal( elem.css(\"display\"), expected, \"Show using correct display type for \" + selector );\n\t\t\tif ( ++num === 15 ) {\n\t\t\t\tstart();\n\t\t\t}\n\t\t});\n\t});\n\n\tjQuery(\"#show-tests\").remove();\n});\n\n// Supports #7397\ntest(\"Persist correct display value\", function() {\n\texpect(3);\n\tQUnit.reset();\n\tstop();\n\n\t// #show-tests * is set display: none in CSS\n\tjQuery(\"#qunit-fixture\").append(\"<div id='show-tests'><span style='position:absolute;'>foo</span></div>\");\n\n\tvar $span = jQuery(\"#show-tests span\"),\n\t\tdisplayNone = $span.css(\"display\"),\n\t\tdisplay = \"\";\n\n\t$span.show();\n\n\tdisplay = $span.css(\"display\");\n\n\t$span.hide();\n\n\t$span.fadeIn(100, function() {\n\t\tequal($span.css(\"display\"), display, \"Expecting display: \" + display);\n\t\t$span.fadeOut(100, function () {\n\t\t\tequal($span.css(\"display\"), displayNone, \"Expecting display: \" + displayNone);\n\t\t\t$span.fadeIn(100, function() {\n\t\t\t\tequal($span.css(\"display\"), display, \"Expecting display: \" + display);\n\t\t\t\tstart();\n\t\t\t});\n\t\t});\n\t});\n\n\tQUnit.expectJqData($span, \"olddisplay\");\n});\n\ntest(\"animate(Hash, Object, Function)\", function() {\n\texpect(1);\n\tstop();\n\tvar hash = {opacity: \"show\"},\n\t\thashCopy = jQuery.extend({}, hash);\n\tjQuery(\"#foo\").animate(hash, 0, function() {\n\t\tequal( hash.opacity, hashCopy.opacity, \"Check if animate changed the hash parameter\" );\n\t\tstart();\n\t});\n});\n\ntest(\"animate relative values\", function() {\n\tstop();\n\n\tvar value = 40,\n\t\tbases = [ \"%\", \"px\", \"em\" ],\n\t\tadjustments = [ \"px\", \"em\" ],\n\t\tcontainer = jQuery(\"<div></div>\")\n\t\t\t.css({ position: \"absolute\", height: \"50em\", width: \"50em\" }),\n\t\tanimations = bases.length * adjustments.length;\n\n\texpect( 2 * animations );\n\n\tjQuery.each( bases, function( _, baseUnit ) {\n\t\tjQuery.each( adjustments, function( _, adjustUnit ) {\n\t\t\tvar base = value + baseUnit,\n\t\t\t\tadjust = { height: \"+=2\" + adjustUnit, width: \"-=2\" + adjustUnit },\n\t\t\t\telem = jQuery(\"<div></div>\")\n\t\t\t\t\t.appendTo( container.clone().appendTo(\"#qunit-fixture\") )\n\t\t\t\t\t.css({\n\t\t\t\t\t\tposition: \"absolute\",\n\t\t\t\t\t\theight: base,\n\t\t\t\t\t\twidth: value + adjustUnit\n\t\t\t\t\t}),\n\t\t\t\tbaseScale = elem[ 0 ].offsetHeight / value,\n\t\t\t\tadjustScale = elem[ 0 ].offsetWidth / value;\n\n\t\t\telem.css( \"width\", base ).animate( adjust, 100, function() {\n\t\t\t\tequal( this.offsetHeight, value * baseScale + 2 * adjustScale,\n\t\t\t\t\tbaseUnit + \"+=\" + adjustUnit );\n\t\t\t\tequal( this.offsetWidth, value * baseScale - 2 * adjustScale,\n\t\t\t\t\tbaseUnit + \"-=\" + adjustUnit );\n\n\t\t\t\tif ( --animations === 0 ) {\n\t\t\t\t\tstart();\n\t\t\t\t}\n\t\t\t});\n\t\t});\n\t});\n});\n\ntest(\"animate negative height\", function() {\n\texpect(1);\n\tstop();\n\tjQuery(\"#foo\").animate({ height: -100 }, 100, function() {\n\t\tequal( this.offsetHeight, 0, \"Verify height.\" );\n\t\tstart();\n\t});\n});\n\ntest(\"animate negative margin\", function() {\n\texpect(1);\n\tstop();\n\tjQuery(\"#foo\").animate({ \"marginTop\": -100 }, 100, function() {\n\t\tequal( jQuery(this).css(\"marginTop\"), \"-100px\", \"Verify margin.\" );\n\t\tstart();\n\t});\n});\n\ntest(\"animate negative margin with px\", function() {\n\texpect(1);\n\tstop();\n\tjQuery(\"#foo\").animate({ marginTop: \"-100px\" }, 100, function() {\n\t\tequal( jQuery(this).css(\"marginTop\"), \"-100px\", \"Verify margin.\" );\n\t\tstart();\n\t});\n});\n\ntest(\"animate negative padding\", function() {\n\texpect(1);\n\tstop();\n\tjQuery(\"#foo\").animate({ \"paddingBottom\": -100 }, 100, function() {\n\t\tequal( jQuery(this).css(\"paddingBottom\"), \"0px\", \"Verify paddingBottom.\" );\n\t\tstart();\n\t});\n});\n\ntest(\"animate block as inline width/height\", function() {\n\texpect(3);\n\n\tstop();\n\n\tjQuery(\"#foo\").css({ display: \"inline\", width: \"\", height: \"\" }).animate({ width: 42, height: 42 }, 100, function() {\n\t\tequal( jQuery(this).css(\"display\"), \"inline-block\", \"inline-block was set on non-floated inline element when animating width/height\" );\n\t\tequal( this.offsetWidth, 42, \"width was animated\" );\n\t\tequal( this.offsetHeight, 42, \"height was animated\" );\n\t\tstart();\n\t});\n});\n\ntest(\"animate native inline width/height\", function() {\n\texpect(3);\n\n\tstop();\n\tjQuery(\"#foo\").css({ display: \"\", width: \"\", height: \"\" })\n\t\t.append(\"<span>text</span>\")\n\t\t.children(\"span\")\n\t\t\t.animate({ width: 42, height: 42 }, 100, function() {\n\t\t\t\tequal( jQuery(this).css(\"display\"), \"inline-block\", \"inline-block was set on non-floated inline element when animating width/height\" );\n\t\t\t\tequal( this.offsetWidth, 42, \"width was animated\" );\n\t\t\t\tequal( this.offsetHeight, 42, \"height was animated\" );\n\t\t\t\tstart();\n\t\t\t});\n});\n\ntest( \"animate block width/height\", function() {\n\texpect( 3 );\n\tstop();\n\n\tjQuery(\"<div>\").appendTo(\"#qunit-fixture\").css({\n\t\tdisplay: \"block\",\n\t\twidth: 20,\n\t\theight: 20,\n\t\tpaddingLeft: 60\n\t}).animate({\n\t\twidth: 42,\n\t\theight: 42\n\t}, {\n\t\tduration: 100,\n\t\tstep: function() {\n\t\t\tif ( jQuery( this ).width() > 42 ) {\n\t\t\t\tok( false, \"width was incorrectly augmented during animation\" );\n\t\t\t}\n\t\t},\n\t\tcomplete: function() {\n\t\t\tequal( jQuery( this ).css(\"display\"), \"block\", \"inline-block was not set on block element when animating width/height\" );\n\t\t\tequal( jQuery( this ).width(), 42, \"width was animated\" );\n\t\t\tequal( jQuery( this ).height(), 42, \"height was animated\" );\n\t\t\tstart();\n\t\t}\n\t});\n});\n\ntest(\"animate table width/height\", function() {\n\texpect(1);\n\tstop();\n\n\tvar displayMode = jQuery(\"#table\").css(\"display\") !== \"table\" ? \"block\" : \"table\";\n\n\tjQuery(\"#table\").animate({ width: 42, height: 42 }, 100, function() {\n\t\tequal( jQuery(this).css(\"display\"), displayMode, \"display mode is correct\" );\n\t\tstart();\n\t});\n});\n\ntest(\"animate table-row width/height\", function() {\n\texpect(3);\n\tstop();\n\tvar displayMode,\n\t\ttr = jQuery(\"#table\")\n\t\t\t.attr({ \"cellspacing\": 0, \"cellpadding\": 0, \"border\": 0 })\n\t\t\t.html(\"<tr style='height:42px;'><td style='padding:0;'><div style='width:20px;height:20px;'></div></td></tr>\")\n\t\t\t.find(\"tr\");\n\n\t// IE<8 uses \"block\" instead of the correct display type\n\tdisplayMode = tr.css(\"display\") !== \"table-row\" ? \"block\" : \"table-row\";\n\n\ttr.animate({ width: 10, height: 10 }, 100, function() {\n\t\tequal( jQuery(this).css(\"display\"), displayMode, \"display mode is correct\" );\n\t\tequal( this.offsetWidth, 20, \"width animated to shrink wrap point\" );\n\t\tequal( this.offsetHeight, 20, \"height animated to shrink wrap point\" );\n\t\tstart();\n\t});\n});\n\ntest(\"animate table-cell width/height\", function() {\n\texpect(3);\n\tstop();\n\tvar displayMode,\n\t\ttd = jQuery(\"#table\")\n\t\t\t.attr({ \"cellspacing\": 0, \"cellpadding\": 0, \"border\": 0 })\n\t\t\t.html(\"<tr><td style='width:42px;height:42px;padding:0;'><div style='width:20px;height:20px;'></div></td></tr>\")\n\t\t\t.find(\"td\");\n\n\t// IE<8 uses \"block\" instead of the correct display type\n\tdisplayMode = td.css(\"display\") !== \"table-cell\" ? \"block\" : \"table-cell\";\n\n\ttd.animate({ width: 10, height: 10 }, 100, function() {\n\t\tequal( jQuery(this).css(\"display\"), displayMode, \"display mode is correct\" );\n\t\tequal( this.offsetWidth, 20, \"width animated to shrink wrap point\" );\n\t\tequal( this.offsetHeight, 20, \"height animated to shrink wrap point\" );\n\t\tstart();\n\t});\n});\n\ntest(\"animate percentage(%) on width/height\", function() {\n\texpect( 2 );\n\n\tvar $div = jQuery(\"<div style='position:absolute;top:-999px;left:-999px;width:60px;height:60px;'><div style='width:50%;height:50%;'></div></div>\")\n\t\t.appendTo(\"#qunit-fixture\").children(\"div\");\n\n\tstop();\n\t$div.animate({ width: \"25%\", height: \"25%\" }, 13, function() {\n\t\tvar $this = jQuery(this);\n\t\tequal( $this.css(\"width\"), \"15px\", \"Width was animated to 15px rather than 25px\");\n\t\tequal( $this.css(\"height\"), \"15px\", \"Height was animated to 15px rather than 25px\");\n\t\tstart();\n\t});\n});\n\ntest(\"animate resets overflow-x and overflow-y when finished\", function() {\n\texpect(2);\n\tstop();\n\tjQuery(\"#foo\")\n\t\t.css({ display: \"block\", width: 20, height: 20, overflowX: \"visible\", overflowY: \"auto\" })\n\t\t.animate({ width: 42, height: 42 }, 100, function() {\n\t\t\tequal( this.style.overflowX, \"visible\", \"overflow-x is visible\" );\n\t\t\tequal( this.style.overflowY, \"auto\", \"overflow-y is auto\" );\n\t\t\tstart();\n\t\t});\n});\n\n/* // This test ends up being flaky depending upon the CPU load\ntest(\"animate option (queue === false)\", function () {\n\texpect(1);\n\tstop();\n\n\tvar order = [];\n\n\tvar $foo = jQuery(\"#foo\");\n\t$foo.animate({width:\"100px\"}, 3000, function () {\n\t\t// should finish after unqueued animation so second\n\t\torder.push(2);\n\t\tdeepEqual( order, [ 1, 2 ], \"Animations finished in the correct order\" );\n\t\tstart();\n\t});\n\t$foo.animate({fontSize:\"2em\"}, {queue:false, duration:10, complete:function () {\n\t\t// short duration and out of queue so should finish first\n\t\torder.push(1);\n\t}});\n});\n*/\n\nasyncTest( \"animate option { queue: false }\", function() {\n\texpect( 2 );\n\tvar foo = jQuery( \"#foo\" );\n\n\tfoo.animate({\n\t\tfontSize: \"2em\"\n\t}, {\n\t\tqueue: false,\n\t\tduration: 10,\n\t\tcomplete: function() {\n\t\t\tok( true, \"Animation Completed\" );\n\t\t\tstart();\n\t\t}\n\t});\n\n\tequal( foo.queue().length, 0, \"Queue is empty\" );\n});\n\nasyncTest( \"animate option { queue: true }\", function() {\n\texpect( 2 );\n\tvar foo = jQuery( \"#foo\" );\n\n\tfoo.animate({\n\t\tfontSize: \"2em\"\n\t}, {\n\t\tqueue: true,\n\t\tduration: 10,\n\t\tcomplete: function() {\n\t\t\tok( true, \"Animation Completed\" );\n\t\t\tstart();\n\t\t}\n\t});\n\n\tnotEqual( foo.queue().length, 0, \"Default queue is not empty\" );\n});\n\nasyncTest( \"animate option { queue: 'name' }\", function() {\n\texpect( 5 );\n\tvar foo = jQuery( \"#foo\" ),\n\t\torigWidth = parseFloat( foo.css(\"width\") ),\n\t\torder = [];\n\n\tfoo.animate( { width: origWidth + 100 }, {\n\t\tqueue: \"name\",\n\t\tduration: 1,\n\t\tcomplete: function() {\n\n\t\t\t// second callback function\n\t\t\torder.push( 2 );\n\t\t\tequal( parseFloat( foo.css(\"width\") ), origWidth + 100, \"Animation ended\" );\n\t\t\tequal( foo.queue(\"name\").length, 1, \"Queue length of 'name' queue\" );\n\t\t}\n\t}).queue( \"name\", function() {\n\n\t\t// last callback function\n\t\tdeepEqual( order, [ 1, 2 ], \"Callbacks in expected order\" );\n\t\tstart();\n\t});\n\n\tsetTimeout( function() {\n\n\t\t// this is the first callback function that should be called\n\t\torder.push( 1 );\n\t\tequal( parseFloat( foo.css(\"width\") ), origWidth, \"Animation does not start on its own.\" );\n\t\tequal( foo.queue(\"name\").length, 2, \"Queue length of 'name' queue\" );\n\t\tfoo.dequeue( \"name\" );\n\t}, 100 );\n\n});\n\ntest(\"animate with no properties\", function() {\n\texpect(2);\n\n\tvar foo,\n\t\tdivs = jQuery(\"div\"),\n\t\tcount = 0;\n\n\tdivs.animate({}, function(){\n\t\tcount++;\n\t});\n\n\tequal( divs.length, count, \"Make sure that callback is called for each element in the set.\" );\n\n\tstop();\n\n\tfoo = jQuery(\"#foo\");\n\n\tfoo.animate({});\n\tfoo.animate({top: 10}, 100, function(){\n\t\tok( true, \"Animation was properly dequeued.\" );\n\t\tstart();\n\t});\n});\n\ntest(\"animate duration 0\", function() {\n\texpect(11);\n\n\tstop();\n\n\tvar $elem,\n\t\t$elems = jQuery([{ a:0 },{ a:0 }]),\n\t\tcounter = 0;\n\n\tequal( jQuery.timers.length, 0, \"Make sure no animation was running from another test\" );\n\n\t$elems.eq(0).animate( {a:1}, 0, function(){\n\t\tok( true, \"Animate a simple property.\" );\n\t\tcounter++;\n\t});\n\n\t// Failed until [6115]\n\tequal( jQuery.timers.length, 0, \"Make sure synchronic animations are not left on jQuery.timers\" );\n\n\tequal( counter, 1, \"One synchronic animations\" );\n\n\t$elems.animate( { a:2 }, 0, function(){\n\t\tok( true, \"Animate a second simple property.\" );\n\t\tcounter++;\n\t});\n\n\tequal( counter, 3, \"Multiple synchronic animations\" );\n\n\t$elems.eq(0).animate( {a:3}, 0, function(){\n\t\tok( true, \"Animate a third simple property.\" );\n\t\tcounter++;\n\t});\n\t$elems.eq(1).animate( {a:3}, 200, function(){\n\t\tcounter++;\n\t\t// Failed until [6115]\n\t\tequal( counter, 5, \"One synchronic and one asynchronic\" );\n\t\tstart();\n\t});\n\n\t$elem = jQuery(\"<div />\");\n\t$elem.show(0, function(){\n\t\tok(true, \"Show callback with no duration\");\n\t});\n\t$elem.hide(0, function(){\n\t\tok(true, \"Hide callback with no duration\");\n\t});\n\n\t// manually clean up detached elements\n\t$elem.remove();\n});\n\ntest(\"animate hyphenated properties\", function() {\n\texpect(1);\n\tstop();\n\n\tjQuery(\"#foo\")\n\t\t.css(\"font-size\", 10)\n\t\t.animate({\"font-size\": 20}, 200, function() {\n\t\t\tequal( this.style.fontSize, \"20px\", \"The font-size property was animated.\" );\n\t\t\tstart();\n\t\t});\n});\n\ntest(\"animate non-element\", function() {\n\texpect(1);\n\tstop();\n\n\tvar obj = { test: 0 };\n\n\tjQuery(obj).animate({test: 200}, 200, function(){\n\t\tequal( obj.test, 200, \"The custom property should be modified.\" );\n\t\tstart();\n\t});\n});\n\ntest(\"stop()\", function() {\n\texpect( 4 );\n\tstop();\n\n\tvar $one, $two,\n\t\t$foo = jQuery(\"#foo\"),\n\t\ttests = 2,\n\t\tw = 0;\n\n\t$foo.hide().css( \"width\", 200 )\n\t\t.animate( { \"width\": \"show\" }, 1500 );\n\n\tsetTimeout(function() {\n\t\tvar nw = $foo.css(\"width\");\n\t\tnotEqual( parseFloat( nw ), w, \"An animation occurred \" + nw + \" \" + w + \"px\" );\n\t\t$foo.stop();\n\n\t\tnw = $foo.css(\"width\");\n\t\tnotEqual( parseFloat( nw ), w, \"Stop didn't reset the animation \" + nw + \" \" + w + \"px\" );\n\t\tsetTimeout(function() {\n\t\t\t$foo.removeData();\n\t\t\t$foo.removeData(undefined, true);\n\t\t\tequal( nw, $foo.css(\"width\"), \"The animation didn't continue\" );\n\t\t\tif ( --tests === 0 ) {\n\t\t\t\tstart();\n\t\t\t}\n\t\t}, 100);\n\t}, 100);\n\n\t$one = jQuery(\"#fadein\");\n\t$two = jQuery(\"#show\");\n\t$one.fadeTo(100, 0, function() {\n\t\t$one.stop();\n\t});\n\tsetTimeout(function() {\n\t\t$two.fadeTo(100, 0, function() {\n\t\t\tequal( $two.css(\"opacity\"), \"0\", \"Stop does not interfere with animations on other elements (#6641)\" );\n\t\t\t// Reset styles\n\t\t\t$one.add( $two ).css(\"opacity\", \"\");\n\t\t\tif ( --tests === 0 ) {\n\t\t\t\tstart();\n\t\t\t}\n\t\t});\n\t}, 50);\n});\n\ntest(\"stop() - several in queue\", function() {\n\texpect( 5 );\n\n\tvar nw, time,\n\t\t$foo = jQuery( \"#foo\" );\n\n\t// default duration is 400ms, so 800px ensures we aren't 0 or 1 after 1ms\n\t$foo.hide().css( \"width\", 800 );\n\n\t$foo.animate({ \"width\": \"show\" }, 400, \"linear\");\n\t$foo.animate({ \"width\": \"hide\" });\n\t$foo.animate({ \"width\": \"show\" });\n\n\t// could be replaced by something nicer using sinon.\n\ttime = jQuery.now();\n\twhile( time === jQuery.now() ) {}\n\n\tjQuery.fx.tick();\n\tequal( $foo.queue().length, 3, \"3 in the queue\" );\n\n\tnw = $foo.css( \"width\" );\n\tnotEqual( parseFloat( nw ), 1, \"An animation occurred \" + nw );\n\t$foo.stop();\n\n\tequal( $foo.queue().length, 2, \"2 in the queue\" );\n\tnw = $foo.css( \"width\" );\n\tnotEqual( parseFloat( nw ), 1, \"Stop didn't reset the animation \" + nw );\n\n\t$foo.stop( true );\n\n\tequal( $foo.queue().length, 0, \"0 in the queue\" );\n});\n\ntest(\"stop(clearQueue)\", function() {\n\texpect(4);\n\tstop();\n\n\tvar $foo = jQuery(\"#foo\"),\n\t\tw = 0;\n\t$foo.hide().css( \"width\", 200 ).css(\"width\");\n\n\t$foo.animate({ \"width\": \"show\" }, 1000);\n\t$foo.animate({ \"width\": \"hide\" }, 1000);\n\t$foo.animate({ \"width\": \"show\" }, 1000);\n\tsetTimeout(function(){\n\t\tvar nw = $foo.css(\"width\");\n\t\tok( parseFloat( nw ) !== w, \"An animation occurred \" + nw + \" \" + w + \"px\");\n\t\t$foo.stop(true);\n\n\t\tnw = $foo.css(\"width\");\n\t\tok( parseFloat( nw ) !== w, \"Stop didn't reset the animation \" + nw + \" \" + w + \"px\");\n\n\t\tequal( $foo.queue().length, 0, \"The animation queue was cleared\" );\n\t\tsetTimeout(function(){\n\t\t\tequal( nw, $foo.css(\"width\"), \"The animation didn't continue\" );\n\t\t\tstart();\n\t\t}, 100);\n\t}, 100);\n});\n\ntest(\"stop(clearQueue, gotoEnd)\", function() {\n\texpect(1);\n\tstop();\n\n\tvar $foo = jQuery(\"#foo\"),\n\t\tw = 0;\n\t$foo.hide().css( \"width\", 200 ).css(\"width\");\n\n\t$foo.animate({ width: \"show\" }, 1000);\n\t$foo.animate({ width: \"hide\" }, 1000);\n\t$foo.animate({ width: \"show\" }, 1000);\n\t$foo.animate({ width: \"hide\" }, 1000);\n\tsetTimeout(function(){\n\t\tvar nw = $foo.css(\"width\");\n\t\tok( parseFloat( nw ) !== w, \"An animation occurred \" + nw + \" \" + w + \"px\");\n\t\t$foo.stop(false, true);\n\n\t\tnw = $foo.css(\"width\");\n\t\t// Disabled, being flaky\n\t\t//equal( nw, 1, \"Stop() reset the animation\" );\n\n\t\tsetTimeout(function(){\n\t\t\t// Disabled, being flaky\n\t\t\t//equal( $foo.queue().length, 2, \"The next animation continued\" );\n\t\t\t$foo.stop(true);\n\t\t\tstart();\n\t\t}, 100);\n\t}, 100);\n});\n\nasyncTest( \"stop( queue, ..., ... ) - Stop single queues\", function() {\n\texpect( 3 );\n\tvar saved,\n\t\tfoo = jQuery(\"#foo\").css({ width: 200, height: 200 });\n\n\tfoo.animate({\n\t\twidth: 400\n\t},{\n\t\tduration: 500,\n\t\tcomplete: function() {\n\t\t\tequal( parseFloat( foo.css(\"width\") ), 400, \"Animation completed for standard queue\" );\n\t\t\tequal( parseFloat( foo.css(\"height\") ), saved, \"Height was not changed after the second stop\");\n\t\t\tstart();\n\t\t}\n\t});\n\n\tfoo.animate({\n\t\theight: 400\n\t},{\n\t\tduration: 1000,\n\t\tqueue: \"height\"\n\t}).dequeue(\"height\").stop( \"height\", false, true );\n\n\tequal( parseFloat( foo.css(\"height\") ), 400, \"Height was stopped with gotoEnd\" );\n\n\tfoo.animate({\n\t\theight: 200\n\t},{\n\t\tduration: 1000,\n\t\tqueue: \"height\"\n\t}).dequeue( \"height\" ).stop( \"height\", false, false );\n\tsaved = parseFloat( foo.css(\"height\") );\n});\n\ntest(\"toggle()\", function() {\n\texpect(6);\n\tvar x = jQuery(\"#foo\");\n\tok( x.is(\":visible\"), \"is visible\" );\n\tx.toggle();\n\tok( x.is(\":hidden\"), \"is hidden\" );\n\tx.toggle();\n\tok( x.is(\":visible\"), \"is visible again\" );\n\n\tx.toggle(true);\n\tok( x.is(\":visible\"), \"is visible\" );\n\tx.toggle(false);\n\tok( x.is(\":hidden\"), \"is hidden\" );\n\tx.toggle(true);\n\tok( x.is(\":visible\"), \"is visible again\" );\n});\n\ntest( \"jQuery.fx.prototype.cur() - <1.8 Back Compat\", 7, function() {\n\tvar div = jQuery( \"<div></div>\" ).appendTo( \"#qunit-fixture\" ).css({\n\t\t\tcolor: \"#ABC\",\n\t\t\tborder: \"5px solid black\",\n\t\t\tleft: \"auto\",\n\t\t\tmarginBottom: \"-11000px\"\n\t\t})[0];\n\n\tequal(\n\t\t( new jQuery.fx( div, {}, \"color\" ) ).cur(),\n\t\tjQuery.css( div, \"color\" ),\n\t\t\"Return the same value as jQuery.css for complex properties (bug #7912)\"\n\t);\n\n\tstrictEqual(\n\t\t( new jQuery.fx( div, {}, \"borderLeftWidth\" ) ).cur(),\n\t\t5,\n\t\t\"Return simple values parsed as Float\"\n\t);\n\n\t// backgroundPosition actually returns 0% 0% in most browser\n\t// this fakes a \"\" return\n\t// hook now gets called twice because Tween will grab the current\n\t// value as it is being newed\n\tjQuery.cssHooks.backgroundPosition = {\n\t\tget: function() {\n\t\t\tok( true, \"hook used\" );\n\t\t\treturn \"\";\n\t\t}\n\t};\n\n\tstrictEqual(\n\t\t( new jQuery.fx( div, {}, \"backgroundPosition\" ) ).cur(),\n\t\t0,\n\t\t\"Return 0 when jQuery.css returns an empty string\"\n\t);\n\n\tdelete jQuery.cssHooks.backgroundPosition;\n\n\tstrictEqual(\n\t\t( new jQuery.fx( div, {}, \"left\" ) ).cur(),\n\t\t0,\n\t\t\"Return 0 when jQuery.css returns 'auto'\"\n\t);\n\n\tequal(\n\t\t( new jQuery.fx( div, {}, \"marginBottom\" ) ).cur(),\n\t\t-11000,\n\t\t\"support negative values < -10000 (bug #7193)\"\n\t);\n\n\tjQuery( div ).remove();\n});\n\ntest(\"Overflow and Display\", function() {\n\texpect(4);\n\tstop();\n\n\tvar\n\t\ttestClass = jQuery.makeTest(\"Overflow and Display\")\n\t\t\t.addClass(\"overflow inline\"),\n\t\ttestStyle = jQuery.makeTest(\"Overflow and Display (inline style)\")\n\t\t\t.css({ overflow: \"visible\", display: \"inline\" }),\n\t\tremaining = 2,\n\t\tdone = function() {\n\t\t\tequal( jQuery.css( this, \"overflow\" ), \"visible\", \"Overflow should be 'visible'\" );\n\t\t\tequal( jQuery.css( this, \"display\" ), \"inline\", \"Display should be 'inline'\" );\n\n\t\t\tif ( --remaining === 0 ) {\n\t\t\t\tstart();\n\t\t\t}\n\t\t};\n\n\ttestClass.add( testStyle )\n\t\t.addClass(\"widewidth\")\n\t\t.text(\"Some sample text.\")\n\t\t.before(\"text before\")\n\t\t.after(\"text after\")\n\t\t.animate({ opacity: 0.5 }, \"slow\", done );\n});\n\njQuery.each({\n\t\"CSS Auto\": function( elem, prop ) {\n\t\tjQuery( elem ).addClass( \"auto\" + prop )\n\t\t\t.text( \"This is a long string of text.\" );\n\t\treturn \"\";\n\t},\n\t\"JS Auto\": function( elem, prop ) {\n\t\tjQuery( elem ).css( prop, \"\" )\n\t\t\t.text( \"This is a long string of text.\" );\n\t\treturn \"\";\n\t},\n\t\"CSS 100\": function( elem, prop ) {\n\t\tjQuery( elem ).addClass( \"large\" + prop );\n\t\treturn \"\";\n\t},\n\t\"JS 100\": function( elem, prop ) {\n\t\tjQuery( elem ).css( prop, prop === \"opacity\" ? 1 : \"100px\" );\n\t\treturn prop === \"opacity\" ? 1 : 100;\n\t},\n\t\"CSS 50\": function( elem, prop ) {\n\t\tjQuery( elem ).addClass( \"med\" + prop );\n\t\treturn \"\";\n\t},\n\t\"JS 50\": function( elem, prop ) {\n\t\tjQuery( elem ).css( prop, prop === \"opacity\" ? 0.50 : \"50px\" );\n\t\treturn prop === \"opacity\" ? 0.5 : 50;\n\t},\n\t\"CSS 0\": function( elem, prop ) {\n\t\tjQuery( elem ).addClass( \"no\" + prop );\n\t\treturn \"\";\n\t},\n\t\"JS 0\": function( elem, prop ) {\n\t\tjQuery( elem ).css( prop, prop === \"opacity\" ? 0 : \"0px\" );\n\t\treturn 0;\n\t}\n}, function( fn, f ) {\n\tjQuery.each({\n\t\t\"show\": function( elem, prop ) {\n\t\t\tjQuery( elem ).hide( ).addClass( \"wide\" + prop );\n\t\t\treturn \"show\";\n\t\t},\n\t\t\"hide\": function( elem, prop ) {\n\t\t\tjQuery( elem ).addClass( \"wide\" + prop );\n\t\t\treturn \"hide\";\n\t\t},\n\t\t\"100\": function( elem, prop ) {\n\t\t\tjQuery( elem ).addClass( \"wide\" + prop );\n\t\t\treturn prop === \"opacity\" ? 1 : 100;\n\t\t},\n\t\t\"50\": function( elem, prop ) {\n\t\t\treturn prop === \"opacity\" ? 0.50 : 50;\n\t\t},\n\t\t\"0\": function( elem ) {\n\t\t\tjQuery( elem ).addClass( \"noback\" );\n\t\t\treturn 0;\n\t\t}\n\t}, function( tn, t ) {\n\t\ttest(fn + \" to \" + tn, function() {\n\t\t\tvar num, anim,\n\t\t\t\telem = jQuery.makeTest( fn + \" to \" + tn ),\n\t\t\t\tt_w = t( elem, \"width\" ),\n\t\t\t\tf_w = f( elem, \"width\" ),\n\t\t\t\tt_h = t( elem, \"height\" ),\n\t\t\t\tf_h = f( elem, \"height\" ),\n\t\t\t\tt_o = t( elem, \"opacity\" ),\n\t\t\t\tf_o = f( elem, \"opacity\" );\n\n\t\t\tif ( f_o === \"\" ) {\n\t\t\t\tf_o = 1;\n\t\t\t}\n\n\t\t\tnum = 0;\n\t\t\t// TODO: uncrowd this\n\t\t\tif ( t_h === \"show\" ) {num++;}\n\t\t\tif ( t_w === \"show\" ) {num++;}\n\t\t\tif ( t_w === \"hide\" || t_w === \"show\" ) {num++;}\n\t\t\tif ( t_h === \"hide\" || t_h === \"show\" ) {num++;}\n\t\t\tif ( t_o === \"hide\" || t_o === \"show\" ) {num++;}\n\t\t\tif ( t_w === \"hide\" ) {num++;}\n\t\t\tif ( t_o.constructor === Number ) {num += 2;}\n\t\t\tif ( t_w.constructor === Number ) {num += 2;}\n\t\t\tif ( t_h.constructor === Number ) {num +=2;}\n\n\t\t\texpect( num );\n\t\t\tstop();\n\n\t\t\tanim = { width: t_w, height: t_h, opacity: t_o };\n\n\t\t\telem.animate(anim, 50);\n\n\t\t\tjQuery.when( elem ).done(function( elem ) {\n\t\t\t\tvar cur_o, cur_w, cur_h, old_h;\n\n\t\t\t\telem = elem[ 0 ];\n\n\t\t\t\tif ( t_w === \"show\" ) {\n\t\t\t\t\tequal( elem.style.display, \"block\", \"Showing, display should block: \" + elem.style.display );\n\t\t\t\t}\n\n\t\t\t\tif ( t_w === \"hide\" || t_w === \"show\" ) {\n\t\t\t\t\tok( f_w === \"\" ? elem.style.width === f_w : elem.style.width.indexOf( f_w ) === 0, \"Width must be reset to \" + f_w + \": \" + elem.style.width );\n\t\t\t\t}\n\n\t\t\t\tif ( t_h === \"hide\" || t_h === \"show\" ) {\n\t\t\t\t\tok( f_h === \"\" ? elem.style.height === f_h : elem.style.height.indexOf( f_h ) === 0, \"Height must be reset to \" + f_h + \": \" + elem.style.height );\n\t\t\t\t}\n\n\t\t\t\tcur_o = jQuery.style(elem, \"opacity\");\n\n\t\t\t\tif ( f_o !== jQuery.css(elem, \"opacity\") ) {\n\t\t\t\t\tf_o = f( elem, \"opacity\" );\n\t\t\t\t}\n\n\t\t\t\t// The only time an _empty_string_ will be matched is in IE\n\t\t\t\t// otherwise, the correct values will be tested as usual\n\t\t\t\tif ( f_o === \"\" ) {\n\t\t\t\t\tf_o = 1;\n\t\t\t\t}\n\t\t\t\t// See above\n\t\t\t\tif ( cur_o === \"\" ) {\n\t\t\t\t\tcur_o = 1;\n\t\t\t\t}\n\n\t\t\t\tif ( t_o === \"hide\" || t_o === \"show\" ) {\n\t\t\t\t\tequal( cur_o, f_o, \"Opacity must be reset to \" + f_o + \": \" + cur_o );\n\t\t\t\t}\n\n\t\t\t\tif ( t_w === \"hide\" ) {\n\t\t\t\t\tequal( elem.style.display, \"none\", \"Hiding, display should be none: \" + elem.style.display );\n\t\t\t\t}\n\n\t\t\t\tif ( t_o.constructor === Number ) {\n\t\t\t\t\tequal( cur_o, t_o, \"Final opacity should be \" + t_o + \": \" + cur_o );\n\n\t\t\t\t\tok( jQuery.css(elem, \"opacity\") !== \"\" || cur_o === t_o, \"Opacity should be explicitly set to \" + t_o + \", is instead: \" + cur_o );\n\t\t\t\t}\n\n\t\t\t\tif ( t_w.constructor === Number ) {\n\t\t\t\t\tequal( elem.style.width, t_w + \"px\", \"Final width should be \" + t_w + \": \" + elem.style.width );\n\n\t\t\t\t\tcur_w = jQuery.css( elem,\"width\" );\n\n\t\t\t\t\tok( elem.style.width !== \"\" || cur_w === t_w, \"Width should be explicitly set to \" + t_w + \", is instead: \" + cur_w );\n\t\t\t\t}\n\n\t\t\t\tif ( t_h.constructor === Number ) {\n\t\t\t\t\tequal( elem.style.height, t_h + \"px\", \"Final height should be \" + t_h + \": \" + elem.style.height );\n\n\t\t\t\t\tcur_h = jQuery.css( elem,\"height\" );\n\n\t\t\t\t\tok( elem.style.height !== \"\" || cur_h === t_h, \"Height should be explicitly set to \" + t_h + \", is instead: \" + cur_h );\n\t\t\t\t}\n\n\t\t\t\tif ( t_h === \"show\" ) {\n\t\t\t\t\told_h = jQuery.css( elem, \"height\" );\n\t\t\t\t\tjQuery( elem ).append(\"<br/>Some more text<br/>and some more...\");\n\n\t\t\t\t\tif ( /Auto/.test( fn ) ) {\n\t\t\t\t\t\tnotEqual( jQuery.css( elem, \"height\" ), old_h, \"Make sure height is auto.\" );\n\t\t\t\t\t} else {\n\t\t\t\t\t\tequal( jQuery.css( elem, \"height\" ), old_h, \"Make sure height is not auto.\" );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// manually remove generated element\n\t\t\t\tjQuery( elem ).remove();\n\n\t\t\t\tstart();\n\t\t\t});\n\t\t});\n\t});\n});\n\nasyncTest(\"Effects chaining\", function() {\n\tvar remaining = 16,\n\t\tprops = [ \"opacity\", \"height\", \"width\", \"display\", \"overflow\" ],\n\t\tsetup = function( name, selector ) {\n\t\t\tvar $el = jQuery( selector );\n\t\t\treturn $el.data( getProps( $el[0] ) ).data( \"name\", name );\n\t\t},\n\t\tassert = function() {\n\t\t\tvar data = jQuery.data( this ),\n\t\t\t\tname = data.name;\n\t\t\tdelete data.name;\n\n\t\t\tdeepEqual( getProps( this ), data, name );\n\n\t\t\tjQuery.removeData( this );\n\t\t\tif ( --remaining === 0 ) {\n\t\t\t\tstart();\n\t\t\t}\n\t\t},\n\t\tgetProps = function( el ) {\n\t\t\tvar obj = {};\n\t\t\tjQuery.each( props, function( i, prop ) {\n\t\t\t\tobj[ prop ] = prop === \"overflow\" && el.style[ prop ] || jQuery.css( el, prop );\n\t\t\t});\n\t\t\treturn obj;\n\t\t};\n\n\texpect( remaining );\n\n\tsetup( \".fadeOut().fadeIn()\", \"#fadein div\" ).fadeOut(\"fast\").fadeIn( \"fast\", assert );\n\tsetup( \".fadeIn().fadeOut()\", \"#fadeout div\" ).fadeIn(\"fast\").fadeOut( \"fast\", assert );\n\tsetup( \".hide().show()\", \"#show div\" ).hide(\"fast\").show( \"fast\", assert );\n\tsetup( \".show().hide()\", \"#hide div\" ).show(\"fast\").hide( \"fast\", assert );\n\tsetup( \".show().hide(easing)\", \"#easehide div\" ).show(\"fast\").hide( \"fast\", \"linear\", assert );\n\tsetup( \".toggle().toggle() - in\", \"#togglein div\" ).toggle(\"fast\").toggle( \"fast\", assert );\n\tsetup( \".toggle().toggle() - out\", \"#toggleout div\" ).toggle(\"fast\").toggle( \"fast\", assert );\n\tsetup( \".toggle().toggle(easing) - out\", \"#easetoggleout div\" ).toggle(\"fast\").toggle( \"fast\", \"linear\", assert );\n\tsetup( \".slideDown().slideUp()\", \"#slidedown div\" ).slideDown(\"fast\").slideUp( \"fast\", assert );\n\tsetup( \".slideUp().slideDown()\", \"#slideup div\" ).slideUp(\"fast\").slideDown( \"fast\", assert );\n\tsetup( \".slideUp().slideDown(easing)\", \"#easeslideup div\" ).slideUp(\"fast\").slideDown( \"fast\", \"linear\", assert );\n\tsetup( \".slideToggle().slideToggle() - in\", \"#slidetogglein div\" ).slideToggle(\"fast\").slideToggle( \"fast\", assert );\n\tsetup( \".slideToggle().slideToggle() - out\", \"#slidetoggleout div\" ).slideToggle(\"fast\").slideToggle( \"fast\", assert );\n\tsetup( \".fadeToggle().fadeToggle() - in\", \"#fadetogglein div\" ).fadeToggle(\"fast\").fadeToggle( \"fast\", assert );\n\tsetup( \".fadeToggle().fadeToggle() - out\", \"#fadetoggleout div\" ).fadeToggle(\"fast\").fadeToggle( \"fast\", assert );\n\tsetup( \".fadeTo(0.5).fadeTo(1.0, easing)\", \"#fadeto div\" ).fadeTo( \"fast\", 0.5 ).fadeTo( \"fast\", 1.0, \"linear\", assert );\n});\n\njQuery.makeTest = function( text ){\n\tvar elem = jQuery(\"<div></div>\")\n\t\t.attr( \"id\", \"test\" + jQuery.makeTest.id++ )\n\t\t.addClass(\"box\");\n\n\tjQuery(\"<h4></h4>\")\n\t\t.text( text )\n\t\t.appendTo(\"#fx-tests\")\n\t\t.after( elem );\n\n\treturn elem;\n};\n\njQuery.makeTest.id = 1;\n\ntest(\"jQuery.show('fast') doesn't clear radio buttons (bug #1095)\", function () {\n\texpect(4);\n\tstop();\n\n\tvar $checkedtest = jQuery(\"#checkedtest\");\n\t$checkedtest.hide().show(\"fast\", function() {\n\t\tok( jQuery(\"input[type='radio']\", $checkedtest).first().attr(\"checked\"), \"Check first radio still checked.\" );\n\t\tok( !jQuery(\"input[type='radio']\", $checkedtest).last().attr(\"checked\"), \"Check last radio still NOT checked.\" );\n\t\tok( jQuery(\"input[type='checkbox']\", $checkedtest).first().attr(\"checked\"), \"Check first checkbox still checked.\" );\n\t\tok( !jQuery(\"input[type='checkbox']\", $checkedtest).last().attr(\"checked\"), \"Check last checkbox still NOT checked.\" );\n\t\tstart();\n\t});\n});\n\ntest( \"interrupt toggle\", function() {\n\texpect( 24 );\n\tstop();\n\n\tvar longDuration = 2000,\n\t\tshortDuration = 500,\n\t\tremaining = 0,\n\t\t$elems = jQuery(\".chain-test\"),\n\t\tfinish = function() {\n\t\t\tif ( !(--remaining) ) {\n\t\t\t\tstart();\n\t\t\t}\n\t\t};\n\n\tjQuery.each( { slideToggle: \"height\", fadeToggle: \"opacity\", toggle: \"width\" }, function( method, prop ) {\n\t\tvar $methodElems = $elems.filter( \"[id^='\" + method.toLowerCase() + \"']\" ).each(function() {\n\t\t\t// Don't end test until we're done with this element\n\t\t\tremaining++;\n\n\t\t\t// Save original property value for comparison\n\t\t\tjQuery.data( this, \"startVal\", jQuery( this ).css( prop ) );\n\n\t\t\t// Expect olddisplay data from our .hide() call below\n\t\t\tQUnit.expectJqData( this, \"olddisplay\" );\n\t\t});\n\n\t\t// Interrupt a hiding toggle\n\t\t$methodElems[ method ]( longDuration );\n\t\tsetTimeout(function() {\n\t\t\t$methodElems.stop().each(function() {\n\t\t\t\tnotEqual( jQuery( this ).css( prop ), jQuery.data( this, \"startVal\" ), \".stop() before completion of hiding .\" + method + \"() - #\" + this.id );\n\t\t\t});\n\n\t\t\t// Restore\n\t\t\t$methodElems[ method ]( shortDuration, function() {\n\t\t\t\tvar id = this.id,\n\t\t\t\t\t$elem = jQuery( this ),\n\t\t\t\t\tstartVal = $elem.data(\"startVal\");\n\n\t\t\t\t$elem.removeData(\"startVal\");\n\n\t\t\t\tequal( $elem.css( prop ), startVal, \"original value restored by .\" + method + \"() - #\" + id );\n\n\t\t\t\t// Interrupt a showing toggle\n\t\t\t\t$elem.hide()[ method ]( longDuration );\n\t\t\t\tsetTimeout(function() {\n\t\t\t\t\t$elem.stop();\n\t\t\t\t\tnotEqual( $elem.css( prop ), startVal, \".stop() before completion of showing .\" + method + \"() - #\" + id );\n\n\t\t\t\t\t// Restore\n\t\t\t\t\t$elem[ method ]( shortDuration, function() {\n\t\t\t\t\t\tequal( $elem.css( prop ), startVal, \"original value restored by .\" + method + \"() - #\" + id );\n\t\t\t\t\t\tfinish();\n\t\t\t\t\t});\n\t\t\t\t}, shortDuration );\n\t\t\t});\n\t\t}, shortDuration );\n\t});\n});\n\ntest(\"animate with per-property easing\", function(){\n\n\texpect(5);\n\tstop();\n\n\tvar data = { a:0, b:0, c:0 },\n\t\t_test1_called = false,\n\t\t_test2_called = false,\n\t\t_default_test_called = false,\n\t\tprops = {\n\t\t\ta: [ 100, \"_test1\" ],\n\t\t\tb: [ 100, \"_test2\" ],\n\t\t\tc: 100\n\t\t};\n\n\tjQuery.easing[\"_test1\"] = function(p) {\n\t\t_test1_called = true;\n\t\treturn p;\n\t};\n\n\tjQuery.easing[\"_test2\"] = function(p) {\n\t\t_test2_called = true;\n\t\treturn p;\n\t};\n\n\tjQuery.easing[\"_default_test\"] = function(p) {\n\t\t_default_test_called = true;\n\t\treturn p;\n\t};\n\n\tjQuery(data).animate( props, 400, \"_default_test\", function(){\n\t\tstart();\n\n\t\tok( _test1_called, \"Easing function (_test1) called\" );\n\t\tok( _test2_called, \"Easing function (_test2) called\" );\n\t\tok( _default_test_called, \"Easing function (_default) called\" );\n\t\tequal( props.a[ 1 ], \"_test1\", \"animate does not change original props (per-property easing would be lost)\");\n\t\tequal( props.b[ 1 ], \"_test2\", \"animate does not change original props (per-property easing would be lost)\");\n\t});\n\n});\n\ntest(\"animate with CSS shorthand properties\", function(){\n\texpect(11);\n\tstop();\n\n\tvar _default_count = 0,\n\t\t_special_count = 0,\n\t\tpropsBasic = { \"padding\": \"10 20 30\" },\n\t\tpropsSpecial = { \"padding\": [ \"1 2 3\", \"_special\" ] };\n\n\tjQuery.easing._default = function(p) {\n\t\tif ( p >= 1 ) {\n\t\t\t_default_count++;\n\t\t}\n\t\treturn p;\n\t};\n\n\tjQuery.easing._special = function(p) {\n\t\tif ( p >= 1 ) {\n\t\t\t_special_count++;\n\t\t}\n\t\treturn p;\n\t};\n\n\tjQuery(\"#foo\")\n\t\t.animate( propsBasic, 200, \"_default\", function() {\n\t\t\tequal( this.style.paddingTop, \"10px\", \"padding-top was animated\" );\n\t\t\tequal( this.style.paddingLeft, \"20px\", \"padding-left was animated\" );\n\t\t\tequal( this.style.paddingRight, \"20px\", \"padding-right was animated\" );\n\t\t\tequal( this.style.paddingBottom, \"30px\", \"padding-bottom was animated\" );\n\t\t\tequal( _default_count, 4, \"per-animation default easing called for each property\" );\n\t\t\t_default_count = 0;\n\t\t})\n\t\t.animate( propsSpecial, 200, \"_default\", function() {\n\t\t\tequal( this.style.paddingTop, \"1px\", \"padding-top was animated again\" );\n\t\t\tequal( this.style.paddingLeft, \"2px\", \"padding-left was animated again\" );\n\t\t\tequal( this.style.paddingRight, \"2px\", \"padding-right was animated again\" );\n\t\t\tequal( this.style.paddingBottom, \"3px\", \"padding-bottom was animated again\" );\n\t\t\tequal( _default_count, 0, \"per-animation default easing not called\" );\n\t\t\tequal( _special_count, 4, \"special easing called for each property\" );\n\n\t\t\tjQuery(this).css(\"padding\", \"0\");\n\t\t\tdelete jQuery.easing._default;\n\t\t\tdelete jQuery.easing._special;\n\t\t\tstart();\n\t\t});\n});\n\ntest(\"hide hidden elements, with animation (bug #7141)\", function() {\n\texpect(3);\n\tQUnit.reset();\n\tstop();\n\n\tvar div = jQuery(\"<div style='display:none'></div>\").appendTo(\"#qunit-fixture\");\n\tequal( div.css(\"display\"), \"none\", \"Element is hidden by default\" );\n\tdiv.hide(1, function () {\n\t\tok( !jQuery._data(div, \"olddisplay\"), \"olddisplay is undefined after hiding an already-hidden element\" );\n\t\tdiv.show(1, function () {\n\t\t\tequal( div.css(\"display\"), \"block\", \"Show a double-hidden element\" );\n\t\t\tstart();\n\t\t});\n\t});\n});\n\ntest(\"animate unit-less properties (#4966)\", 2, function() {\n\tstop();\n\tvar div = jQuery( \"<div style='z-index: 0; position: absolute;'></div>\" ).appendTo( \"#qunit-fixture\" );\n\tequal( div.css( \"z-index\" ), \"0\", \"z-index is 0\" );\n\tdiv.animate({ zIndex: 2 }, function() {\n\t\tequal( div.css( \"z-index\" ), \"2\", \"z-index is 2\" );\n\t\tstart();\n\t});\n});\n\ntest( \"animate properties missing px w/ opacity as last (#9074)\", 2, function() {\n\texpect( 6 );\n\tstop();\n\tvar div = jQuery( \"<div style='position: absolute; margin-left: 0; left: 0px;'></div>\" )\n\t\t.appendTo( \"#qunit-fixture\" );\n\tfunction cssInt( prop ) {\n\t\treturn parseInt( div.css( prop ), 10 );\n\t}\n\tequal( cssInt( \"marginLeft\" ), 0, \"Margin left is 0\" );\n\tequal( cssInt( \"left\" ), 0, \"Left is 0\" );\n\tdiv.animate({\n\t\tleft: 200,\n\t\tmarginLeft: 200,\n\t\topacity: 0\n\t}, 2000);\n\tsetTimeout(function() {\n\t\tvar ml = cssInt( \"marginLeft\" ),\n\t\t\tl = cssInt( \"left\" );\n\t\tnotEqual( ml, 0, \"Margin left is not 0 after partial animate\" );\n\t\tnotEqual( ml, 200, \"Margin left is not 200 after partial animate\" );\n\t\tnotEqual( l, 0, \"Left is not 0 after partial animate\" );\n\t\tnotEqual( l, 200, \"Left is not 200 after partial animate\" );\n\t\tdiv.stop().remove();\n\t\tstart();\n\t}, 500);\n});\n\ntest(\"callbacks should fire in correct order (#9100)\", function() {\n\texpect( 1 );\n\n\tstop();\n\tvar a = 1,\n\t\tcb = 0;\n\n\tjQuery(\"<p data-operation='*2'></p><p data-operation='^2'></p>\").appendTo(\"#qunit-fixture\")\n\t\t// The test will always pass if no properties are animated or if the duration is 0\n\t\t.animate({fontSize: 12}, 13, function() {\n\t\t\ta *= jQuery(this).data(\"operation\") === \"*2\" ? 2 : a;\n\t\t\tcb++;\n\t\t\tif ( cb === 2 ) {\n\t\t\t\tequal( a, 4, \"test value has been *2 and _then_ ^2\");\n\t\t\t\tstart();\n\t\t\t}\n\t\t});\n});\n\nasyncTest( \"callbacks that throw exceptions will be removed (#5684)\", function() {\n\texpect( 2 );\n\n\tvar foo = jQuery( \"#foo\" );\n\n\tfunction TestException() {\n\t}\n\n\tfoo.animate({ height: 1 }, 1, function() {\n\t\tthrow new TestException();\n\t});\n\n\t// this test thoroughly abuses undocumented methods - please feel free to update\n\t// with any changes internally to these functions.\n\n\t// make sure that the standard timer loop will NOT run.\n\tjQuery.fx.stop();\n\n\tsetTimeout(function() {\n\n\t\t// the first call to fx.tick should raise the callback exception\n\t\traises( jQuery.fx.tick, TestException, \"Exception was thrown\" );\n\n\t\t// the second call shouldn't\n\t\tjQuery.fx.tick();\n\n\t\tok( true, \"Test completed without throwing a second exception\" );\n\n\t\tstart();\n\t}, 1);\n});\n\ntest(\"animate will scale margin properties individually\", function() {\n\texpect( 2 );\n\tstop();\n\n\tvar foo = jQuery( \"#foo\" ).css({\n\t\t\"margin\": 0,\n\t\t\"marginLeft\": 100\n\t});\n\n\tok( foo.css( \"marginLeft\" ) !== foo.css( \"marginRight\" ), \"Sanity Check\" );\n\n\tfoo.animate({\n\t\t\"margin\": 200\n\t}).stop();\n\n\tok( foo.css( \"marginLeft\") !== foo.css( \"marginRight\" ), \"The margin properties are different\");\n\n\t// clean up for next test\n\tfoo.css({\n\t\t\"marginLeft\": \"\",\n\t\t\"marginRight\": \"\",\n\t\t\"marginTop\": \"\",\n\t\t\"marginBottom\": \"\"\n\t});\n\tstart();\n});\n\ntest(\"Do not append px to 'fill-opacity' #9548\", 1, function() {\n\tvar $div = jQuery(\"<div>\").appendTo(\"#qunit-fixture\");\n\n\t$div.css(\"fill-opacity\", 0).animate({ \"fill-opacity\": 1.0 }, 0, function () {\n\t\tequal( jQuery(this).css(\"fill-opacity\"), 1, \"Do not append px to 'fill-opacity'\");\n\t\t$div.remove();\n\t});\n});\n\ntest(\"line-height animates correctly (#13855)\", function() {\n\texpect( 12 );\n\tstop();\n\n\tvar\n\t\tanimated = jQuery(\n\t\t\t\"<p style='line-height: 4;'>unitless</p>\" +\n\t\t\t\"<p style='line-height: 50px;'>px</p>\" +\n\t\t\t\"<p style='line-height: 420%;'>percent</p>\" +\n\t\t\t\"<p style='line-height: 2.5em;'>em</p>\"\n\t\t).appendTo(\"#qunit-fixture\"),\n\t\tinitialHeight = jQuery.map( animated, function( el ) {\n\t\t\treturn jQuery( el ).height();\n\t\t});\n\n\tanimated.animate( { \"line-height\": \"hide\" }, 1500 );\n\tsetTimeout(function() {\n\t\tanimated.each(function( i ) {\n\t\t\tvar label = jQuery.text( this ),\n\t\t\t\tinitial = initialHeight[ i ],\n\t\t\t\theight = jQuery( this ).height();\n\t\t\tok( height < initial, \"hide \" + label + \": upper bound\" );\n\t\t\tok( height > initial / 2, \"hide \" + label + \": lower bound\" );\n\t\t});\n\t\tanimated.stop( true, true ).hide().animate( { \"line-height\": \"show\" }, 1500 );\n\t\tsetTimeout(function() {\n\t\t\tanimated.each(function( i ) {\n\t\t\t\tvar label = jQuery.text( this ),\n\t\t\t\t\tinitial = initialHeight[ i ],\n\t\t\t\t\theight = jQuery( this ).height();\n\t\t\t\tok( height < initial / 2, \"show \" + label + \": upper bound\" );\n\t\t\t});\n\t\t\tanimated.stop( true, true );\n\t\t\tstart();\n\t\t}, 400 );\n\t}, 400 );\n});\n\n// Start 1.8 Animation tests\nasyncTest( \"jQuery.Animation( object, props, opts )\", 4, function() {\n\tvar animation,\n\t\ttestObject = {\n\t\t\t\"foo\": 0,\n\t\t\t\"bar\": 1,\n\t\t\t\"width\": 100\n\t\t},\n\t\ttestDest = {\n\t\t\t\"foo\": 1,\n\t\t\t\"bar\": 0,\n\t\t\t\"width\": 200\n\t\t};\n\n\tanimation = jQuery.Animation( testObject, testDest, { \"duration\": 1 });\n\tanimation.done(function() {\n\t\tfor ( var prop in testDest ) {\n\t\t\tequal( testObject[ prop ], testDest[ prop ], \"Animated: \" + prop );\n\t\t}\n\t\tanimation.done(function() {\n\t\t\tdeepEqual( testObject, testDest, \"No unexpected properties\" );\n\t\t\tstart();\n\t\t});\n\t});\n});\n\nasyncTest( \"Animate Option: step: function( percent, tween )\", 1, function() {\n\tvar counter = {};\n\tjQuery( \"#foo\" ).animate({\n\t\tprop1: 1,\n\t\tprop2: 2,\n\t\tprop3: 3\n\t}, {\n\t\tduration: 1,\n\t\tstep: function( value, tween ) {\n\t\t\tvar calls = counter[ tween.prop ] = counter[ tween.prop ] || [];\n\t\t\t// in case this is called multiple times for either, lets store it in\n\t\t\t// 0 or 1 in the array\n\t\t\tcalls[ value === 0 ? 0 : 1 ] = value;\n\t\t}\n\t}).queue( function( next ) {\n\t\tdeepEqual( counter, {\n\t\t\tprop1: [0, 1],\n\t\t\tprop2: [0, 2],\n\t\t\tprop3: [0, 3]\n\t\t}, \"Step function was called once at 0% and once at 100% for each property\");\n\t\tnext();\n\t\tstart();\n\t});\n});\n\nasyncTest( \"Animate callbacks have correct context\", 2, function() {\n\tvar foo = jQuery( \"#foo\" );\n\tfoo.animate({\n\t\theight: 10\n\t}, 10, function() {\n\t\tequal( foo[ 0 ], this, \"Complete callback after stop(true) `this` is element\" );\n\t}).stop( true, true );\n\tfoo.animate({\n\t\theight: 100\n\t}, 10, function() {\n\t\tequal( foo[ 0 ], this, \"Complete callback `this` is element\" );\n\t\tstart();\n\t});\n});\n\nasyncTest( \"User supplied callback called after show when fx off (#8892)\", 2, function() {\n\tvar foo = jQuery( \"#foo\" );\n\tjQuery.fx.off = true;\n\tfoo.hide();\n\tfoo.fadeIn( 500, function() {\n\t\tok( jQuery( this ).is( \":visible\" ), \"Element is visible in callback\" );\n\t\tfoo.fadeOut( 500, function() {\n\t\t\tok( jQuery( this ).is( \":hidden\" ), \"Element is hidden in callback\" );\n\t\t\tjQuery.fx.off = false;\n\t\t\tstart();\n\t\t});\n\t});\n});\n\ntest( \"animate should set display for disconnected nodes\", function() {\n\texpect( 18 );\n\n\tvar i = 0,\n\t\tmethods = {\n\t\t\ttoggle: [ 1 ],\n\t\t\tslideToggle: [],\n\t\t\tfadeIn: [],\n\t\t\tfadeTo: [ \"fast\", 0.5 ],\n\t\t\tslideDown: [ \"fast\" ],\n\t\t\tshow: [ 1 ],\n\t\t\tanimate: [{ width: \"show\" }]\n\t\t},\n\t\t$divTest = jQuery(\"<div>test</div>\"),\n\t\t// parentNode = null\n\t\t$divEmpty = jQuery(\"<div/>\"),\n\t\t$divNone = jQuery(\"<div style='display: none;'/>\"),\n\t\t$divInline = jQuery(\"<div style='display: inline;'/>\");\n\n\tstrictEqual( $divTest.show()[ 0 ].style.display, \"block\", \"set display with show() for element with parentNode = document fragment\" );\n\tstrictEqual( $divEmpty.show()[ 0 ].style.display, \"block\", \"set display with show() for element with parentNode = null\" );\n\tstrictEqual( $divNone.show()[ 0 ].style.display, \"block\", \"show() should change display if it already set to none\" );\n\tstrictEqual( $divInline.show()[ 0 ].style.display, \"inline\", \"show() should not change display if it already set\" );\n\n\tQUnit.expectJqData( $divTest[ 0 ], \"olddisplay\" );\n\tQUnit.expectJqData( $divEmpty[ 0 ], \"olddisplay\" );\n\tQUnit.expectJqData( $divNone[ 0 ], \"olddisplay\" );\n\n\tstop();\n\tjQuery.each( methods, function( name, opt ) {\n\t\tjQuery.each([\n\n\t\t\t// parentNode = document fragment\n\t\t\tjQuery(\"<div>test</div>\"),\n\n\t\t\t// parentNode = null\n\t\t\tjQuery(\"<div/>\")\n\n\t\t], function() {\n\t\t\tvar callback = [function () {\n\t\t\t\t\tstrictEqual( this.style.display, \"block\", \"set display to block with \" + name );\n\n\t\t\t\t\tQUnit.expectJqData( this, \"olddisplay\" );\n\n\t\t\t\t\tif ( ++i === 14 ) {\n\t\t\t\t\t\tstart();\n\t\t\t\t\t}\n\t\t\t}];\n\t\t\tjQuery.fn[ name ].apply( this, opt.concat( callback ) );\n\t\t});\n\t});\n});\n\nasyncTest(\"Animation callback should not show animated element as :animated (#7157)\", 1, function() {\n\tvar foo = jQuery( \"#foo\" );\n\n\tfoo.animate({\n\t\topacity: 0\n\t}, 100, function() {\n\t\tok( !foo.is(\":animated\"), \"The element is not animated\" );\n\t\tstart();\n\t});\n});\n\nasyncTest( \"hide called on element within hidden parent should set display to none (#10045)\", 3, function() {\n\tvar hidden = jQuery(\".hidden\"),\n\t\telems = jQuery(\"<div>hide</div><div>hide0</div><div>hide1</div>\");\n\n\thidden.append( elems );\n\n\tjQuery.when(\n\t\telems.eq( 0 ).hide(),\n\t\telems.eq( 1 ).hide( 0 ),\n\t\telems.eq( 2 ).hide( 1 )\n\t).done(function() {\n\t\tstrictEqual( elems.get( 0 ).style.display, \"none\", \"hide() called on element within hidden parent should set display to none\" );\n\t\tstrictEqual( elems.get( 1 ).style.display, \"none\", \"hide( 0 ) called on element within hidden parent should set display to none\" );\n\t\tstrictEqual( elems.get( 2 ).style.display, \"none\", \"hide( 1 ) called on element within hidden parent should set display to none\" );\n\n\t\telems.remove();\n\t\tstart();\n\t});\n});\n\nasyncTest( \"hide, fadeOut and slideUp called on element width height and width = 0 should set display to none\", 5, function() {\n\tvar foo = jQuery(\"#foo\"),\n\t\ti = 0,\n\t\telems = jQuery();\n\n\tfor ( ; i < 5; i++ ) {\n\t\telems = elems.add(\"<div style='width:0;height:0;'></div>\");\n\t}\n\n\tfoo.append( elems );\n\n\tjQuery.when(\n\t\telems.eq( 0 ).hide(),\n\t\telems.eq( 1 ).hide( jQuery.noop ),\n\t\telems.eq( 2 ).hide( 1 ),\n\t\telems.eq( 3 ).fadeOut(),\n\t\telems.eq( 4 ).slideUp()\n\t).done(function() {\n\t\tstrictEqual( elems.get( 0 ).style.display, \"none\", \"hide() called on element width height and width = 0 should set display to none\" );\n\t\tstrictEqual( elems.get( 1 ).style.display, \"none\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"hide( jQuery.noop ) called on element width height and width = 0 should set display to none\" );\n\t\tstrictEqual( elems.get( 2 ).style.display, \"none\", \"hide( 1 ) called on element width height and width = 0 should set display to none\" );\n\t\tstrictEqual( elems.get( 3 ).style.display, \"none\", \"fadeOut() called on element width height and width = 0 should set display to none\" );\n\t\tstrictEqual( elems.get( 4 ).style.display, \"none\", \"slideUp() called on element width height and width = 0 should set display to none\" );\n\n\t\tstart();\n\t});\n});\n\nasyncTest( \"Handle queue:false promises\", 10, function() {\n\tvar foo = jQuery( \"#foo\" ).clone().addBack(),\n\t\tstep = 1;\n\n\tfoo.animate({\n\t\ttop: 1\n\t}, {\n\t\tduration: 10,\n\t\tqueue: false,\n\t\tcomplete: function() {\n\t\t\tok( step++ <= 2, \"Step one or two\" );\n\t\t}\n\t}).animate({\n\t\tbottom: 1\n\t}, {\n\t\tduration: 10,\n\t\tcomplete: function() {\n\t\t\tok( step > 2 && step < 5, \"Step three or four\" );\n\t\t\tstep++;\n\t\t}\n\t});\n\n\tfoo.promise().done( function() {\n\t\tequal( step++, 5, \"steps 1-5: queue:false then queue:fx done\" );\n\t\tfoo.animate({\n\t\t\ttop: 10\n\t\t}, {\n\t\t\tduration: 10,\n\t\t\tcomplete: function() {\n\t\t\t\tok( step > 5 && step < 8, \"Step six or seven\" );\n\t\t\t\tstep++;\n\t\t\t}\n\t\t}).animate({\n\t\t\tbottom: 10\n\t\t}, {\n\t\t\tduration: 10,\n\t\t\tqueue: false,\n\t\t\tcomplete: function() {\n\t\t\t\tok( step > 7 && step < 10, \"Step eight or nine\" );\n\t\t\t\tstep++;\n\t\t\t}\n\t\t}).promise().done( function() {\n\t\t\tequal( step++, 10, \"steps 6-10: queue:fx then queue:false\" );\n\t\t\tstart();\n\t\t});\n\n\t});\n});\n\nasyncTest( \"multiple unqueued and promise\", 4, function() {\n\tvar foo = jQuery( \"#foo\" ),\n\t\tstep = 1;\n\tfoo.animate({\n\t\tmarginLeft: 300\n\t}, {\n\t\tduration: 500,\n\t\tqueue: false,\n\t\tcomplete: function() {\n\t\t\tstrictEqual( step++, 2, \"Step 2\" );\n\t\t}\n\t}).animate({\n\t\ttop: 100\n\t}, {\n\t\tduration: 1000,\n\t\tqueue: false,\n\t\tcomplete: function() {\n\t\t\tstrictEqual( step++, 3, \"Step 3\" );\n\t\t}\n\t}).animate({}, {\n\t\tduration: 2000,\n\t\tqueue: false,\n\t\tcomplete: function() {\n\t\t\t// no properties is a non-op and finishes immediately\n\t\t\tstrictEqual( step++, 1, \"Step 1\" );\n\t\t}\n\t}).promise().done( function() {\n\t\tstrictEqual( step++, 4, \"Step 4\" );\n\t\tstart();\n\t});\n});\n\nasyncTest( \"animate does not change start value for non-px animation (#7109)\", 1, function() {\n\tvar parent = jQuery( \"<div><div></div></div>\" ).css({ width: 284, height: 1 }).appendTo( \"#qunit-fixture\" ),\n\t\tchild = parent.children().css({ fontSize: \"98.6in\", width: \"0.01em\", height: 1 }),\n\t\tactual = parseFloat( child.css( \"width\" ) ),\n\t\tcomputed = [];\n\n\tchild.animate({ width: \"0%\" }, {\n\t\tduration: 1,\n\t\tstep: function() {\n\t\t\tcomputed.push( parseFloat( child.css( \"width\" ) ) );\n\t\t}\n\t}).queue( function( next ) {\n\t\tvar ratio = computed[ 0 ] / actual;\n\t\tok( ratio > 0.9 && ratio < 1.1 , \"Starting width was close enough\" );\n\t\tnext();\n\t\tparent.remove();\n\t\tstart();\n\t});\n});\n\nasyncTest( \"non-px animation handles non-numeric start (#11971)\", 2, function() {\n\tvar foo = jQuery(\"#foo\"),\n\t\tinitial = foo.css(\"backgroundPositionX\");\n\n\tif ( !initial ) {\n\t\texpect(1);\n\t\tok( true, \"Style property not understood\" );\n\t\tstart();\n\t\treturn;\n\t}\n\n\tfoo.animate({ backgroundPositionX: \"42%\" }, {\n\t\tduration: 1,\n\t\tprogress: function( anim, percent ) {\n\t\t\tif ( percent ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif ( parseFloat( initial ) ) {\n\t\t\t\tequal( jQuery.style( this, \"backgroundPositionX\" ), initial, \"Numeric start preserved\" );\n\t\t\t} else {\n\t\t\t\tequal( jQuery.style( this, \"backgroundPositionX\" ), \"0%\", \"Non-numeric start zeroed\" );\n\t\t\t}\n\t\t},\n\t\tdone: function() {\n\t\t\tequal( jQuery.style( this, \"backgroundPositionX\" ), \"42%\", \"End reached\" );\n\t\t\tstart();\n\t\t}\n\t});\n});\n\nasyncTest(\"Animation callbacks (#11797)\", 15, function() {\n\tvar targets = jQuery(\"#foo\").children(),\n\t\tdone = false,\n\t\texpectedProgress = 0;\n\n\ttargets.eq( 0 ).animate( {}, {\n\t\tduration: 1,\n\t\tstart: function() {\n\t\t\tok( true, \"empty: start\" );\n\t\t},\n\t\tprogress: function( anim, percent ) {\n\t\t\tequal( percent, 0, \"empty: progress 0\" );\n\t\t},\n\t\tdone: function() {\n\t\t\tok( true, \"empty: done\" );\n\t\t},\n\t\tfail: function() {\n\t\t\tok( false, \"empty: fail\" );\n\t\t},\n\t\talways: function() {\n\t\t\tok( true, \"empty: always\" );\n\t\t\tdone = true;\n\t\t}\n\t});\n\n\tok( done, \"empty: done immediately\" );\n\n\tdone = false;\n\ttargets.eq( 1 ).animate({\n\t\topacity: 0\n\t}, {\n\t\tduration: 1,\n\t\tstart: function() {\n\t\t\tok( true, \"stopped: start\" );\n\t\t},\n\t\tprogress: function( anim, percent ) {\n\t\t\tequal( percent, 0, \"stopped: progress 0\" );\n\t\t},\n\t\tdone: function() {\n\t\t\tok( false, \"stopped: done\" );\n\t\t},\n\t\tfail: function() {\n\t\t\tok( true, \"stopped: fail\" );\n\t\t},\n\t\talways: function() {\n\t\t\tok( true, \"stopped: always\" );\n\t\t\tdone = true;\n\t\t}\n\t}).stop();\n\n\tok( done, \"stopped: stopped immediately\" );\n\n\ttargets.eq( 2 ).animate({\n\t\topacity: 0\n\t}, {\n\t\tduration: 1,\n\t\tstart: function() {\n\t\t\tok( true, \"async: start\" );\n\t\t},\n\t\tprogress: function( anim, percent ) {\n\t\t\t// occasionally the progress handler is called twice in first frame.... *shrug*\n\t\t\tif ( percent === 0 && expectedProgress === 1 ) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tequal( percent, expectedProgress, \"async: progress \" + expectedProgress );\n\t\t\t// once at 0, once at 1\n\t\t\texpectedProgress++;\n\t\t},\n\t\tdone: function() {\n\t\t\tok( true, \"async: done\" );\n\t\t},\n\t\tfail: function() {\n\t\t\tok( false, \"async: fail\" );\n\t\t},\n\t\talways: function() {\n\t\t\tok( true, \"async: always\" );\n\t\t\tstart();\n\t\t}\n\t});\n});\n\ntest( \"Animate properly sets overflow hidden when animating width/height (#12117)\", 8, function() {\n\tjQuery.each( [ \"height\", \"width\" ], function( _, prop ) {\n\t\tjQuery.each( [ 100, 0 ], function( _, value ) {\n\t\t\tvar div = jQuery(\"<div>\").css( \"overflow\", \"auto\" ),\n\t\t\t\tprops = {};\n\t\t\tprops[ prop ] = value;\n\t\t\tdiv.animate( props, 1 );\n\t\t\tequal( div.css( \"overflow\" ), \"hidden\",\n\t\t\t\t\"overflow: hidden set when animating \" + prop + \" to \" + value );\n\t\t\tdiv.stop();\n\t\t\tequal( div.css( \"overflow\" ), \"auto\",\n\t\t\t\t\"overflow: auto restored after animating \" + prop + \" to \" + value );\n\t\t});\n\t});\n});\n\ntest( \"Each tick of the timer loop uses a fresh time (#12837)\", function() {\n\tvar lastVal, current,\n\t\ttmp = jQuery({\n\t\t\ttest: 0\n\t\t});\n\texpect( 3 );\n\ttmp.animate({\n\t\ttest: 100\n\t}, {\n\t\tstep: function( p, fx ) {\n\t\t\tok( fx.now !== lastVal, \"Current value is not the last value: \" + lastVal + \" - \" + fx.now );\n\t\t\tlastVal = fx.now;\n\t\t}\n\t});\n\tcurrent = jQuery.now();\n\t// intentionally empty, we want to spin wheels until the time changes.\n\twhile ( current === jQuery.now() ) { }\n\n\t// now that we have a new time, run another tick\n\tjQuery.fx.tick();\n\n\tcurrent = jQuery.now();\n\t// intentionally empty, we want to spin wheels until the time changes.\n\twhile ( current === jQuery.now() ) { }\n\n\tjQuery.fx.tick();\n\ttmp.stop();\n});\n\ntest( \"Animations with 0 duration don't ease (#12273)\", 1, function() {\n\tjQuery.easing.test = function() {\n\t\tok( false, \"Called easing\" );\n\t};\n\n\tjQuery( \"#foo\" ).animate({\n\t\theight: 100\n\t}, {\n\t\tduration: 0,\n\t\teasing: \"test\",\n\t\tcomplete: function() {\n\t\t\tequal( jQuery( this ).height(), 100, \"Height is 100\" );\n\t\t}\n\t});\n\n\tdelete jQuery.easing.test;\n});\n\njQuery.map([ \"toggle\", \"slideToggle\", \"fadeToggle\" ], function ( method ) {\n\t// this test would look a lot better if we were using something to override\n\t// the default timers\n\tvar duration = 1500;\n\tasyncTest( \"toggle state tests: \" + method + \" (#8685)\", function() {\n\t\tfunction secondToggle() {\n\t\t\tvar stopped = parseFloat( element.css( check ) );\n\t\t\ttested = false;\n\t\t\telement[ method ]({\n\t\t\t\tduration: duration,\n\t\t\t\tstep: function( p, fx ) {\n\t\t\t\t\tif ( fx.pos > 0.1 && fx.prop === check && !tested ) {\n\t\t\t\t\t\ttested = true;\n\t\t\t\t\t\tequal( fx.start, stopped, check + \" starts at \" + stopped + \" where it stopped\" );\n\t\t\t\t\t\tequal( fx.end, original, check + \" ending value is \" + original );\n\t\t\t\t\t\telement.stop();\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\talways: start\n\t\t\t});\n\t\t}\n\n\t\tvar tested,\n\t\t\toriginal,\n\t\t\tcheck = method === \"slideToggle\" ? \"height\" : \"opacity\",\n\t\t\telement = jQuery(\"#foo\").height( 200 );\n\n\t\texpect( 4 );\n\n\t\telement[ method ]({\n\t\t\tduration: duration,\n\t\t\teasing: \"linear\",\n\t\t\tstep: function( p, fx ) {\n\t\t\t\tif ( fx.pos > 0.1 && fx.prop === check && !tested ) {\n\t\t\t\t\ttested = true;\n\t\t\t\t\toriginal = fx.start;\n\t\t\t\t\tok( fx.start !== 0, check + \" is starting at \" + original + \" on first toggle (non-zero)\" );\n\t\t\t\t\tequal( fx.end, 0, check + \" is ending at 0 on first toggle\" );\n\t\t\t\t\telement.stop();\n\t\t\t\t}\n\t\t\t},\n\t\t\talways: secondToggle\n\t\t});\n\t});\n});\n\ntest( \"jQuery.fx.start & jQuery.fx.stop hook points\", function() {\n\tvar oldStart = jQuery.fx.start,\n\t\toldStop = jQuery.fx.stop,\n\t\tfoo = jQuery({ foo: 0 });\n\n\texpect( 3 );\n\n\tjQuery.fx.start = function() {\n\t\tok( true, \"start called\" );\n\t};\n\tjQuery.fx.stop = function() {\n\t\tok( true, \"stop called\" );\n\t};\n\n\t// calls start\n\tfoo.animate({ foo: 1 }, { queue: false });\n\t// calls start\n\tfoo.animate({ foo: 2 }, { queue: false });\n\tfoo.stop();\n\t// calls stop\n\tjQuery.fx.tick();\n\n\t// cleanup\n\tjQuery.fx.start = oldStart;\n\tjQuery.fx.stop = oldStop;\n});\n\ntest( \".finish() completes all queued animations\", function() {\n\tvar animations = {\n\t\t\ttop: 100,\n\t\t\tleft: 100,\n\t\t\theight: 100,\n\t\t\twidth: 100\n\t\t},\n\t\tdiv = jQuery(\"<div>\");\n\n\texpect( 11 );\n\n\tjQuery.each( animations, function( prop, value ) {\n\t\tvar anim = {};\n\t\tanim[ prop ] = value;\n\t\t// the delay shouldn't matter at all!\n\t\tdiv.css( prop, 1 ).animate( anim, function() {\n\t\t\tok( true, \"Called animation callback for \" + prop );\n\t\t}).delay( 100 );\n\t});\n\tequal( div.queue().length, 8, \"8 animations in the queue\" );\n\tdiv.finish();\n\tjQuery.each( animations, function( prop, value ) {\n\t\tequal( parseFloat( div.css( prop ) ), value, prop + \" finished at correct value\" );\n\t});\n\tequal( div.queue().length, 0, \"empty queue when done\" );\n\tequal( div.is(\":animated\"), false, \":animated doesn't match\" );\n\n\t// cleanup\n\tdiv.remove();\n\t// leaves a \"shadow timer\" which does nothing around, need to force a tick\n\tjQuery.fx.tick();\n});\n\ntest( \".finish( false ) - unqueued animations\", function() {\n\tvar animations = {\n\t\t\ttop: 100,\n\t\t\tleft: 100,\n\t\t\theight: 100,\n\t\t\twidth: 100\n\t\t},\n\t\tdiv = jQuery(\"<div>\");\n\n\texpect( 10 );\n\n\tjQuery.each( animations, function( prop, value ) {\n\t\tvar anim = {};\n\t\tanim[ prop ] = value;\n\t\tdiv.css( prop, 1 ).animate( anim, {\n\t\t\tqueue: false,\n\t\t\tcomplete: function() {\n\t\t\t\tok( true, \"Called animation callback for \" + prop );\n\t\t\t}\n\t\t});\n\t});\n\tequal( div.queue().length, 0, \"0 animations in the queue\" );\n\tdiv.finish( false );\n\tjQuery.each( animations, function( prop, value ) {\n\t\tequal( parseFloat( div.css( prop ) ), value, prop + \" finished at correct value\" );\n\t});\n\tequal( div.is(\":animated\"), false, \":animated doesn't match\" );\n\n\t// cleanup\n\tdiv.remove();\n\t// leaves a \"shadow timer\" which does nothing around, need to force a tick\n\tjQuery.fx.tick();\n});\n\ntest( \".finish( \\\"custom\\\" ) - custom queue animations\", function() {\n\tvar animations = {\n\t\t\ttop: 100,\n\t\t\tleft: 100,\n\t\t\theight: 100,\n\t\t\twidth: 100\n\t\t},\n\t\tdiv = jQuery(\"<div>\");\n\n\texpect( 11 );\n\n\tjQuery.each( animations, function( prop, value ) {\n\t\tvar anim = {};\n\t\tanim[ prop ] = value;\n\t\tdiv.css( prop, 1 ).animate( anim, {\n\t\t\tqueue: \"custom\",\n\t\t\tcomplete: function() {\n\t\t\t\tok( true, \"Called animation callback for \" + prop );\n\t\t\t}\n\t\t});\n\t});\n\tequal( div.queue( \"custom\" ).length, 4, \"4 animations in the queue\" );\n\t// start the first animation\n\tdiv.dequeue( \"custom\" );\n\tequal( div.is(\":animated\"), true, \":animated matches\" );\n\tdiv.finish( \"custom\" );\n\tjQuery.each( animations, function( prop, value ) {\n\t\tequal( parseFloat( div.css( prop ) ), value, prop + \" finished at correct value\" );\n\t});\n\tequal( div.is(\":animated\"), false, \":animated doesn't match\" );\n\n\t// cleanup\n\tdiv.remove();\n\t// leaves a \"shadow timer\" which does nothing around, need to force a tick\n\tjQuery.fx.tick();\n});\n\ntest( \".finish() calls finish of custom queue functions\", function() {\n\tfunction queueTester( next, hooks ) {\n\t\thooks.stop = function( gotoEnd ) {\n\t\t\tinside++;\n\t\t\tequal( this, div[0] );\n\t\t\tok( gotoEnd, \"hooks.stop(true) called\");\n\t\t};\n\t}\n\tvar div = jQuery( \"<div>\" ),\n\t\tinside = 0,\n\t\toutside = 0;\n\n\texpect( 6 );\n\tqueueTester.finish = function() {\n\t\toutside++;\n\t\tok( true, \"Finish called on custom queue function\" );\n\t};\n\n\tdiv.queue( queueTester ).queue( queueTester ).queue( queueTester ).finish();\n\n\tequal( inside, 1, \"1 stop(true) callback\" );\n\tequal( outside, 2, \"2 finish callbacks\" );\n\n\tdiv.remove();\n});\n\nasyncTest( \".finish() is applied correctly when multiple elements were animated (#13937)\", function() {\n\texpect( 3 );\n\n\tvar elems = jQuery(\"<a>0</a><a>1</a><a>2</a>\");\n\n\telems.animate( { opacity: 0 }, 1500 ).animate( { opacity: 1 }, 1500 );\n\tsetTimeout(function() {\n\t\telems.eq( 1 ).finish();\n\t\tok( !elems.eq( 1 ).queue().length, \"empty queue for .finish()ed element\" );\n\t\tok( elems.eq( 0 ).queue().length, \"non-empty queue for preceding element\" );\n\t\tok( elems.eq( 2 ).queue().length, \"non-empty queue for following element\" );\n\t\telems.stop( true );\n\n\t\t// setTimeout needed in order to avoid setInterval/setTimeout execution bug in FF\n\t\twindow.setTimeout(function() {\n\t\t\tstart();\n\t\t}, 1000 );\n\t}, 100 );\n});\n\nasyncTest( \"slideDown() after stop() (#13483)\", 2, function() {\n\tvar ul = jQuery( \"<ul style='height: 100px;display: block'></ul>\" ),\n\t\torigHeight = ul.height();\n\n\t// First test. slideUp() -> stop() in the middle -> slideDown() until the end\n\tul.slideUp( 1000 );\n\tsetTimeout( function() {\n\t\tul.stop( true );\n\t\tul.slideDown( 1, function() {\n\t\t\tequal( ul.height(), origHeight, \"slideDown() after interrupting slideUp() with stop(). Height must be in original value\" );\n\n\t\t\t// Second test. slideDown() -> stop() in the middle -> slideDown() until the end\n\t\t\tul.slideUp( 1, function() {\n\t\t\t\tul.slideDown( 1000 );\n\t\t\t\tsetTimeout( function() {\n\t\t\t\t\tul.stop( true );\n\t\t\t\t\tul.slideDown( 1, function() {\n\t\t\t\t\t\tequal( ul.height(), origHeight, \"slideDown() after interrupting slideDown() with stop(). Height must be in original value\" );\n\n\t\t\t\t\t\t// Cleanup\n\t\t\t\t\t\tul.remove();\n\t\t\t\t\t\tstart();\n\t\t\t\t\t});\n\t\t\t\t}, 500 );\n\t\t\t});\n\n\t\t});\n\t}, 500 );\n});\n\nasyncTest( \"fadeIn() after stop() (related to #13483)\", 2, function() {\n\tvar ul = jQuery( \"<ul style='height: 100px;display: block; opacity: 1'></ul>\" ),\n\t\torigOpacity = ul.css( \"opacity\" );\n\n\t// First test. fadeOut() -> stop() in the middle -> fadeIn() until the end\n\tul.fadeOut( 1000 );\n\tsetTimeout( function() {\n\t\tul.stop( true );\n\t\tul.fadeIn( 1, function() {\n\t\t\tequal( ul.css( \"opacity\" ), origOpacity, \"fadeIn() after interrupting fadeOut() with stop(). Opacity must be in original value\" );\n\n\t\t\t// Second test. fadeIn() -> stop() in the middle -> fadeIn() until the end\n\t\t\tul.fadeOut( 1, function() {\n\t\t\t\tul.fadeIn( 1000 );\n\t\t\t\tsetTimeout( function() {\n\t\t\t\t\tul.stop( true );\n\t\t\t\t\tul.fadeIn( 1, function() {\n\t\t\t\t\t\tequal( ul.css(\"opacity\"), origOpacity, \"fadeIn() after interrupting fadeIn() with stop(). Opacity must be in original value\" );\n\n\t\t\t\t\t\t// Cleanup\n\t\t\t\t\t\tul.remove();\n\t\t\t\t\t\tstart();\n\t\t\t\t\t});\n\t\t\t\t}, 500 );\n\t\t\t});\n\n\t\t});\n\t}, 500 );\n});\n\n})();\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/jquery/test/unit/event.js",
    "content": "module(\"event\", { teardown: moduleTeardown });\n\ntest(\"null or undefined handler\", function() {\n\texpect(2);\n\t// Supports Fixes bug #7229\n\ttry {\n\t\tjQuery(\"#firstp\").on( \"click\", null );\n\t\tok(true, \"Passing a null handler will not throw an exception\");\n\t} catch ( e ) {}\n\n\ttry {\n\t\tjQuery(\"#firstp\").on( \"click\", undefined );\n\t\tok(true, \"Passing an undefined handler will not throw an exception\");\n\t} catch ( e ) {}\n});\n\ntest(\"on() with non-null,defined data\", function() {\n\n\texpect(2);\n\n\tvar handler = function( event, data ) {\n\t\tequal( data, 0, \"non-null, defined data (zero) is correctly passed\" );\n\t};\n\n\tjQuery(\"#foo\").on(\"foo.on\", handler);\n\tjQuery(\"div\").on(\"foo.delegate\", \"#foo\", handler);\n\n\tjQuery(\"#foo\").trigger(\"foo\", 0);\n\n\tjQuery(\"#foo\").off(\"foo.on\", handler);\n\tjQuery(\"div\").off(\"foo.delegate\", \"#foo\");\n\n});\n\ntest(\"Handler changes and .trigger() order\", function() {\n\texpect(1);\n\n\tvar markup = jQuery(\n\t\t\"<div><div><p><span><b class=\\\"a\\\">b</b></span></p></div></div>\"\n\t),\n\tpath = \"\";\n\n\tmarkup\n\t\t.find( \"*\" ).addBack().on( \"click\", function() {\n\t\t\tpath += this.nodeName.toLowerCase() + \" \";\n\t\t})\n\t\t.filter( \"b\" ).on( \"click\", function( e ) {\n\t\t\t// Removing span should not stop propagation to original parents\n\t\t\tif ( e.target === this ) {\n\t\t\t\tjQuery(this).parent().remove();\n\t\t\t}\n\t\t});\n\n\tmarkup.find( \"b\" ).trigger( \"click\" );\n\n\tequal( path, \"b p div div \", \"Delivered all events\" );\n\n\tmarkup.remove();\n});\n\ntest(\"on(), with data\", function() {\n\texpect(4);\n\tvar test, handler, handler2;\n\n\thandler = function(event) {\n\t\tok( event.data, \"on() with data, check passed data exists\" );\n\t\tequal( event.data[\"foo\"], \"bar\", \"on() with data, Check value of passed data\" );\n\t};\n\tjQuery(\"#firstp\").on(\"click\", {\"foo\": \"bar\"}, handler).trigger(\"click\").off(\"click\", handler);\n\n\tok( !jQuery._data(jQuery(\"#firstp\")[0], \"events\"), \"Event handler unbound when using data.\" );\n\n\ttest = function(){};\n\thandler2 = function(event) {\n\t\tequal( event.data, test, \"on() with function data, Check value of passed data\" );\n\t};\n\tjQuery(\"#firstp\").on(\"click\", test, handler2).trigger(\"click\").off(\"click\", handler2);\n});\n\ntest(\"click(), with data\", function() {\n\texpect(3);\n\tvar handler = function(event) {\n\t\tok( event.data, \"on() with data, check passed data exists\" );\n\t\tequal( event.data[\"foo\"], \"bar\", \"on() with data, Check value of passed data\" );\n\t};\n\tjQuery(\"#firstp\").on( \"click\", {\"foo\": \"bar\"}, handler).trigger(\"click\").off(\"click\", handler);\n\n\tok( !jQuery._data(jQuery(\"#firstp\")[0], \"events\"), \"Event handler unbound when using data.\" );\n});\n\ntest(\"on(), with data, trigger with data\", function() {\n\texpect(4);\n\tvar handler = function(event, data) {\n\t\tok( event.data, \"check passed data exists\" );\n\t\tequal( event.data.foo, \"bar\", \"Check value of passed data\" );\n\t\tok( data, \"Check trigger data\" );\n\t\tequal( data.bar, \"foo\", \"Check value of trigger data\" );\n\t};\n\tjQuery(\"#firstp\").on(\"click\", {foo: \"bar\"}, handler).trigger(\"click\", [{bar: \"foo\"}]).off(\"click\", handler);\n});\n\ntest(\"on(), multiple events at once\", function() {\n\texpect(2);\n\tvar handler,\n\t\tclickCounter = 0,\n\t\tmouseoverCounter = 0;\n\thandler = function(event) {\n\t\tif (event.type === \"click\") {\n\t\t\tclickCounter += 1;\n\t\t}\n\t\telse if (event.type === \"mouseover\") {\n\t\t\tmouseoverCounter += 1;\n\t\t}\n\t};\n\n\tjQuery(\"#firstp\").on(\"click mouseover\", handler).trigger(\"click\").trigger(\"mouseover\");\n\tequal( clickCounter, 1, \"on() with multiple events at once\" );\n\tequal( mouseoverCounter, 1, \"on() with multiple events at once\" );\n});\n\ntest(\"on(), five events at once\", function() {\n\texpect(1);\n\n\tvar count = 0,\n\t\thandler = function() {\n\t\t\tcount++;\n\t\t};\n\n\tjQuery(\"#firstp\").on(\"click mouseover foo bar baz\", handler)\n\t.trigger(\"click\").trigger(\"mouseover\")\n\t\t.trigger(\"foo\").trigger(\"bar\")\n\t\t.trigger(\"baz\");\n\n\tequal( count, 5, \"on() five events at once\" );\n});\n\ntest(\"on(), multiple events at once and namespaces\", function() {\n\texpect(7);\n\n\tvar cur, div,\n\t\tobj = {};\n\n\tdiv = jQuery(\"<div/>\").on(\"focusin.a\", function(e) {\n\t\tequal( e.type, cur, \"Verify right single event was fired.\" );\n\t});\n\n\tcur = \"focusin\";\n\tdiv.trigger(\"focusin.a\");\n\n\t// manually clean up detached elements\n\tdiv.remove();\n\n\tdiv = jQuery(\"<div/>\").on(\"click mouseover\", obj, function(e) {\n\t\tequal( e.type, cur, \"Verify right multi event was fired.\" );\n\t\tequal( e.data, obj, \"Make sure the data came in correctly.\" );\n\t});\n\n\tcur = \"click\";\n\tdiv.trigger(\"click\");\n\n\tcur = \"mouseover\";\n\tdiv.trigger(\"mouseover\");\n\n\t// manually clean up detached elements\n\tdiv.remove();\n\n\tdiv = jQuery(\"<div/>\").on(\"focusin.a focusout.b\", function(e) {\n\t\tequal( e.type, cur, \"Verify right multi event was fired.\" );\n\t});\n\n\tcur = \"focusin\";\n\tdiv.trigger(\"focusin.a\");\n\n\tcur = \"focusout\";\n\tdiv.trigger(\"focusout.b\");\n\n\t// manually clean up detached elements\n\tdiv.remove();\n});\n\ntest(\"on(), namespace with special add\", function() {\n\texpect(27);\n\n\tvar i = 0,\n\t\tdiv = jQuery(\"<div/>\").appendTo(\"#qunit-fixture\").on( \"test\", function() {\n\t\t\tok( true, \"Test event fired.\" );\n\t\t});\n\n\tjQuery.event.special[\"test\"] = {\n\t\t_default: function( e, data ) {\n\t\t\tequal( e.type, \"test\", \"Make sure we're dealing with a test event.\" );\n\t\t\tok( data, \"And that trigger data was passed.\" );\n\t\t\tstrictEqual( e.target, div[0], \"And that the target is correct.\" );\n\t\t\tequal( this, window, \"And that the context is correct.\" );\n\t\t},\n\t\tsetup: function() {},\n\t\tteardown: function() {\n\t\t\tok( true, \"Teardown called.\" );\n\t\t},\n\t\tadd: function( handleObj ) {\n\t\t\tvar handler = handleObj.handler;\n\t\t\thandleObj.handler = function( e ) {\n\t\t\t\te.xyz = ++i;\n\t\t\t\thandler.apply( this, arguments );\n\t\t\t};\n\t\t},\n\t\tremove: function() {\n\t\t\tok( true, \"Remove called.\" );\n\t\t}\n\t};\n\n\tdiv.on( \"test.a\", { x: 1 }, function( e ) {\n\t\tok( !!e.xyz, \"Make sure that the data is getting passed through.\" );\n\t\tequal( e.data[\"x\"], 1, \"Make sure data is attached properly.\" );\n\t});\n\n\tdiv.on( \"test.b\", { x: 2 }, function( e ) {\n\t\tok( !!e.xyz, \"Make sure that the data is getting passed through.\" );\n\t\tequal( e.data[\"x\"], 2, \"Make sure data is attached properly.\" );\n\t});\n\n\t// Should trigger 5\n\tdiv.trigger( \"test\", 33.33 );\n\n\t// Should trigger 2\n\tdiv.trigger( \"test.a\", \"George Harrison\" );\n\n\t// Should trigger 2\n\tdiv.trigger( \"test.b\", { year: 1982 } );\n\n\t// Should trigger 4\n\tdiv.off(\"test\");\n\n\tdiv = jQuery(\"<div/>\").on( \"test\", function() {\n\t\tok( true, \"Test event fired.\" );\n\t});\n\n\t// Should trigger 2\n\tdiv.appendTo(\"#qunit-fixture\").remove();\n\n\tdelete jQuery.event.special[\"test\"];\n});\n\ntest(\"on(), no data\", function() {\n\texpect(1);\n\tvar handler = function(event) {\n\t\tok ( !event.data, \"Check that no data is added to the event object\" );\n\t};\n\tjQuery(\"#firstp\").on(\"click\", handler).trigger(\"click\");\n});\n\ntest(\"on/one/off(Object)\", function(){\n\texpect(6);\n\n\tvar $elem,\n\t\tclickCounter = 0,\n\t\tmouseoverCounter = 0;\n\n\tfunction handler(event) {\n\t\tif (event.type === \"click\") {\n\t\t\tclickCounter++;\n\t\t} else if (event.type === \"mouseover\") {\n\t\t\tmouseoverCounter++;\n\t\t}\n\t}\n\n\tfunction handlerWithData(event) {\n\t\tif (event.type === \"click\") {\n\t\t\tclickCounter += event.data;\n\t\t} else if (event.type === \"mouseover\") {\n\t\t\tmouseoverCounter += event.data;\n\t\t}\n\t}\n\n\tfunction trigger(){\n\t\t$elem.trigger(\"click\").trigger(\"mouseover\");\n\t}\n\n\t$elem = jQuery(\"#firstp\")\n\t\t// Regular bind\n\t\t.on({\n\t\t\t\"click\":handler,\n\t\t\t\"mouseover\":handler\n\t\t})\n\t\t// Bind with data\n\t\t.one({\n\t\t\t\"click\":handlerWithData,\n\t\t\t\"mouseover\":handlerWithData\n\t\t}, 2 );\n\n\ttrigger();\n\n\tequal( clickCounter, 3, \"on(Object)\" );\n\tequal( mouseoverCounter, 3, \"on(Object)\" );\n\n\ttrigger();\n\tequal( clickCounter, 4, \"on(Object)\" );\n\tequal( mouseoverCounter, 4, \"on(Object)\" );\n\n\tjQuery(\"#firstp\").off({\n\t\t\"click\":handler,\n\t\t\"mouseover\":handler\n\t});\n\n\ttrigger();\n\tequal( clickCounter, 4, \"on(Object)\" );\n\tequal( mouseoverCounter, 4, \"on(Object)\" );\n});\n\ntest(\"on/off(Object), on/off(Object, String)\", function() {\n\texpect(6);\n\n\tvar events,\n\t\tclickCounter = 0,\n\t\tmouseoverCounter = 0,\n\t\t$p = jQuery(\"#firstp\"),\n\t\t$a = $p.find(\"a\").eq(0);\n\n\tevents = {\n\t\t\"click\": function( event ) {\n\t\t\tclickCounter += ( event.data || 1 );\n\t\t},\n\t\t\"mouseover\": function( event ) {\n\t\t\tmouseoverCounter += ( event.data || 1 );\n\t\t}\n\t};\n\n\tfunction trigger() {\n\t\t$a.trigger(\"click\").trigger(\"mouseover\");\n\t}\n\n\tjQuery( document ).on( events, \"#firstp a\" );\n\t$p.on( events, \"a\", 2 );\n\n\ttrigger();\n\tequal( clickCounter, 3, \"on\" );\n\tequal( mouseoverCounter, 3, \"on\" );\n\n\t$p.off( events, \"a\" );\n\n\ttrigger();\n\tequal( clickCounter, 4, \"off\" );\n\tequal( mouseoverCounter, 4, \"off\" );\n\n\tjQuery( document ).off( events, \"#firstp a\" );\n\n\ttrigger();\n\tequal( clickCounter, 4, \"off\" );\n\tequal( mouseoverCounter, 4, \"off\" );\n});\n\ntest(\"on immediate propagation\", function() {\n\texpect(2);\n\n\tvar lastClick,\n\t\t$p = jQuery(\"#firstp\"),\n\t\t$a = $p.find(\"a\").eq(0);\n\n\tlastClick = \"\";\n\tjQuery( document ).on( \"click\", \"#firstp a\", function(e) {\n\t\tlastClick = \"click1\";\n\t\te.stopImmediatePropagation();\n\t});\n\tjQuery( document ).on( \"click\", \"#firstp a\", function() {\n\t\tlastClick = \"click2\";\n\t});\n\t$a.trigger( \"click\" );\n\tequal( lastClick, \"click1\", \"on stopImmediatePropagation\" );\n\tjQuery( document ).off( \"click\", \"#firstp a\" );\n\n\tlastClick = \"\";\n\t$p.on( \"click\", \"a\", function(e) {\n\t\tlastClick = \"click1\";\n\t\te.stopImmediatePropagation();\n\t});\n\t$p.on( \"click\", \"a\", function() {\n\t\tlastClick = \"click2\";\n\t});\n\t$a.trigger( \"click\" );\n\tequal( lastClick, \"click1\", \"on stopImmediatePropagation\" );\n\t$p.off( \"click\", \"**\" );\n});\n\ntest(\"on bubbling, isDefaultPrevented\", function() {\n\texpect(2);\n\tvar $anchor2 = jQuery( \"#anchor2\" ),\n\t\t$main = jQuery( \"#qunit-fixture\" ),\n\t\tfakeClick = function($jq) {\n\t\t\t// Use a native click so we don't get jQuery simulated bubbling\n\t\t\tif ( document.createEvent ) {\n\t\t\t\tvar e = document.createEvent( \"MouseEvents\" );\n\t\t\t\te.initEvent( \"click\", true, true );\n\t\t\t\t$jq[0].dispatchEvent(e);\n\t\t\t}\n\t\t\telse if ( $jq[0].click ) {\n\t\t\t\t$jq[0].click();\t// IE\n\t\t\t}\n\t\t};\n\t$anchor2.on( \"click\", function(e) {\n\t\te.preventDefault();\n\t});\n\t$main.on(\"click\", \"#foo\", function(e) {\n\t\tvar orig = e.originalEvent;\n\n\t\tif ( typeof(orig.defaultPrevented) === \"boolean\" || typeof(orig.returnValue) === \"boolean\" || orig[\"getPreventDefault\"] ) {\n\t\t\tequal( e.isDefaultPrevented(), true, \"isDefaultPrevented true passed to bubbled event\" );\n\n\t\t} else {\n\t\t\t// Opera < 11 doesn't implement any interface we can use, so give it a pass\n\t\t\tok( true, \"isDefaultPrevented not supported by this browser, test skipped\" );\n\t\t}\n\t});\n\tfakeClick( $anchor2 );\n\t$anchor2.off( \"click\" );\n\t$main.off( \"click\", \"**\" );\n\t$anchor2.on( \"click\", function() {\n\t\t// Let the default action occur\n\t});\n\t$main.on(\"click\", \"#foo\", function(e) {\n\t\tequal( e.isDefaultPrevented(), false, \"isDefaultPrevented false passed to bubbled event\" );\n\t});\n\tfakeClick( $anchor2 );\n\t$anchor2.off( \"click\" );\n\t$main.off( \"click\", \"**\" );\n});\n\ntest(\"on(), iframes\", function() {\n\texpect( 1 );\n\n\t// events don't work with iframes, see #939 - this test fails in IE because of contentDocument\n\tvar doc = jQuery(\"#loadediframe\").contents();\n\n\tjQuery(\"div\", doc).on(\"click\", function() {\n\t\tok( true, \"Binding to element inside iframe\" );\n\t}).trigger(\"click\").off(\"click\");\n});\n\ntest(\"on(), trigger change on select\", function() {\n\texpect(5);\n\tvar counter = 0;\n\tfunction selectOnChange(event) {\n\t\tequal( event.data, counter++, \"Event.data is not a global event object\" );\n\t}\n\tjQuery(\"#form select\").each(function(i){\n\t\tjQuery(this).on(\"change\", i, selectOnChange);\n\t}).trigger(\"change\");\n});\n\ntest(\"on(), namespaced events, cloned events\", 18, function() {\n\tvar firstp = jQuery( \"#firstp\" );\n\n\tfirstp.on(\"custom.test\",function(){\n\t\tok(false, \"Custom event triggered\");\n\t});\n\n\tfirstp.on(\"click\",function(e){\n\t\tok(true, \"Normal click triggered\");\n\t\tequal( e.type + e.namespace, \"click\", \"Check that only click events trigger this fn\" );\n\t});\n\n\tfirstp.on(\"click.test\",function(e){\n\t\tvar check = \"click\";\n\t\tok( true, \"Namespaced click triggered\" );\n\t\tif ( e.namespace ) {\n\t\t\tcheck += \"test\";\n\t\t}\n\t\tequal( e.type + e.namespace, check, \"Check that only click/click.test events trigger this fn\" );\n\t});\n\n\t//clone(true) element to verify events are cloned correctly\n\tfirstp = firstp.add( firstp.clone( true ).attr( \"id\", \"firstp2\" ).insertBefore( firstp ) );\n\n\t// Trigger both bound fn (8)\n\tfirstp.trigger(\"click\");\n\n\t// Trigger one bound fn (4)\n\tfirstp.trigger(\"click.test\");\n\n\t// Remove only the one fn\n\tfirstp.off(\"click.test\");\n\n\t// Trigger the remaining fn (4)\n\tfirstp.trigger(\"click\");\n\n\t// Remove the remaining namespaced fn\n\tfirstp.off(\".test\");\n\n\t// Try triggering the custom event (0)\n\tfirstp.trigger(\"custom\");\n\n\t// using contents will get comments regular, text, and comment nodes\n\tjQuery(\"#nonnodes\").contents().on(\"tester\", function () {\n\t\tequal(this.nodeType, 1, \"Check node,textnode,comment on just does real nodes\" );\n\t}).trigger(\"tester\");\n\n\t// Make sure events stick with appendTo'd elements (which are cloned) #2027\n\tjQuery(\"<a href='#fail' class='test'>test</a>\").on( \"click\", function(){ return false; }).appendTo(\"#qunit-fixture\");\n\tok( jQuery(\"a.test\").eq(0).triggerHandler(\"click\") === false, \"Handler is bound to appendTo'd elements\" );\n});\n\ntest(\"on(), multi-namespaced events\", function() {\n\texpect(6);\n\n\tvar order = [\n\t\t\"click.test.abc\",\n\t\t\"click.test.abc\",\n\t\t\"click.test\",\n\t\t\"click.test.abc\",\n\t\t\"click.test\",\n\t\t\"custom.test2\"\n\t];\n\n\tfunction check(name, msg){\n\t\tdeepEqual( name, order.shift(), msg );\n\t}\n\n\tjQuery(\"#firstp\").on(\"custom.test\",function() {\n\t\tcheck(\"custom.test\", \"Custom event triggered\");\n\t});\n\n\tjQuery(\"#firstp\").on(\"custom.test2\",function() {\n\t\tcheck(\"custom.test2\", \"Custom event triggered\");\n\t});\n\n\tjQuery(\"#firstp\").on(\"click.test\",function() {\n\t\tcheck(\"click.test\", \"Normal click triggered\");\n\t});\n\n\tjQuery(\"#firstp\").on(\"click.test.abc\",function() {\n\t\tcheck(\"click.test.abc\", \"Namespaced click triggered\");\n\t});\n\n\t// Those would not trigger/off (#5303)\n\tjQuery(\"#firstp\").trigger(\"click.a.test\");\n\tjQuery(\"#firstp\").off(\"click.a.test\");\n\n\t// Trigger both bound fn (1)\n\tjQuery(\"#firstp\").trigger(\"click.test.abc\");\n\n\t// Trigger one bound fn (1)\n\tjQuery(\"#firstp\").trigger(\"click.abc\");\n\n\t// Trigger two bound fn (2)\n\tjQuery(\"#firstp\").trigger(\"click.test\");\n\n\t// Remove only the one fn\n\tjQuery(\"#firstp\").off(\"click.abc\");\n\n\t// Trigger the remaining fn (1)\n\tjQuery(\"#firstp\").trigger(\"click\");\n\n\t// Remove the remaining fn\n\tjQuery(\"#firstp\").off(\".test\");\n\n\t// Trigger the remaining fn (1)\n\tjQuery(\"#firstp\").trigger(\"custom\");\n});\n\ntest(\"namespace-only event binding is a no-op\", function(){\n\texpect(2);\n\n\tjQuery(\"#firstp\")\n\t\t.on( \".whoops\", function() {\n\t\t\tok( false, \"called a namespace-only event\" );\n\t\t})\n\t\t.on( \"whoops\", function() {\n\t\t\tok( true, \"called whoops\" );\n\t\t})\n\t\t.trigger(\"whoops\")\t// 1\n\t\t.off(\".whoops\")\n\t\t.trigger(\"whoops\")\t// 2\n\t\t.off(\"whoops\");\n});\n\ntest(\"on(), with same function\", function() {\n\texpect(2);\n\n\tvar count = 0, func = function(){\n\t\tcount++;\n\t};\n\n\tjQuery(\"#liveHandlerOrder\").on(\"foo.bar\", func).on(\"foo.zar\", func);\n\tjQuery(\"#liveHandlerOrder\").trigger(\"foo.bar\");\n\n\tequal(count, 1, \"Verify binding function with multiple namespaces.\" );\n\n\tjQuery(\"#liveHandlerOrder\").off(\"foo.bar\", func).off(\"foo.zar\", func);\n\tjQuery(\"#liveHandlerOrder\").trigger(\"foo.bar\");\n\n\tequal(count, 1, \"Verify that removing events still work.\" );\n});\n\ntest(\"on(), make sure order is maintained\", function() {\n\texpect(1);\n\n\tvar elem = jQuery(\"#firstp\"), log = [], check = [];\n\n\tjQuery.each( new Array(100), function( i ) {\n\t\telem.on( \"click\", function(){\n\t\t\tlog.push( i );\n\t\t});\n\n\t\tcheck.push( i );\n\n\t});\n\n\telem.trigger(\"click\");\n\n\tequal( log.join(\",\"), check.join(\",\"), \"Make sure order was maintained.\" );\n\n\telem.off(\"click\");\n});\n\ntest(\"on(), with different this object\", function() {\n\texpect(4);\n\tvar thisObject = { myThis: true },\n\t\tdata = { myData: true },\n\t\thandler1 = function() {\n\t\t\tequal( this, thisObject, \"on() with different this object\" );\n\t\t},\n\t\thandler2 = function( event ) {\n\t\t\tequal( this, thisObject, \"on() with different this object and data\" );\n\t\t\tequal( event.data, data, \"on() with different this object and data\" );\n\t\t};\n\n\tjQuery(\"#firstp\")\n\t\t.on(\"click\", jQuery.proxy(handler1, thisObject)).trigger(\"click\").off(\"click\", handler1)\n\t\t.on(\"click\", data, jQuery.proxy(handler2, thisObject)).trigger(\"click\").off(\"click\", handler2);\n\n\tok( !jQuery._data(jQuery(\"#firstp\")[0], \"events\"), \"Event handler unbound when using different this object and data.\" );\n});\n\ntest(\"on(name, false), off(name, false)\", function() {\n\texpect(3);\n\n\tvar main = 0;\n\tjQuery(\"#qunit-fixture\").on(\"click\", function(){ main++; });\n\tjQuery(\"#ap\").trigger(\"click\");\n\tequal( main, 1, \"Verify that the trigger happened correctly.\" );\n\n\tmain = 0;\n\tjQuery(\"#ap\").on(\"click\", false);\n\tjQuery(\"#ap\").trigger(\"click\");\n\tequal( main, 0, \"Verify that no bubble happened.\" );\n\n\tmain = 0;\n\tjQuery(\"#ap\").off(\"click\", false);\n\tjQuery(\"#ap\").trigger(\"click\");\n\tequal( main, 1, \"Verify that the trigger happened correctly.\" );\n\n\t// manually clean up events from elements outside the fixture\n\tjQuery(\"#qunit-fixture\").off(\"click\");\n});\n\ntest(\"on(name, selector, false), off(name, selector, false)\", function() {\n\texpect(3);\n\n\tvar main = 0;\n\n\tjQuery(\"#qunit-fixture\").on(\"click\", \"#ap\", function(){ main++; });\n\tjQuery(\"#ap\").trigger(\"click\");\n\tequal( main, 1, \"Verify that the trigger happened correctly.\" );\n\n\tmain = 0;\n\tjQuery(\"#ap\").on(\"click\", \"#groups\", false);\n\tjQuery(\"#groups\").trigger(\"click\");\n\tequal( main, 0, \"Verify that no bubble happened.\" );\n\n\tmain = 0;\n\tjQuery(\"#ap\").off(\"click\", \"#groups\", false);\n\tjQuery(\"#groups\").trigger(\"click\");\n\tequal( main, 1, \"Verify that the trigger happened correctly.\" );\n\tjQuery(\"#qunit-fixture\").off(\"click\", \"#ap\");\n});\n\ntest(\"on()/trigger()/off() on plain object\", function() {\n\texpect( 7 );\n\n\tvar events,\n\t\tobj = {};\n\n\t// Make sure it doesn't complain when no events are found\n\tjQuery(obj).trigger(\"test\");\n\n\t// Make sure it doesn't complain when no events are found\n\tjQuery(obj).off(\"test\");\n\n\tjQuery(obj).on({\n\t\t\"test\": function() {\n\t\t\tok( true, \"Custom event run.\" );\n\t\t},\n\t\t\"submit\": function() {\n\t\t\tok( true, \"Custom submit event run.\" );\n\t\t}\n\t});\n\n\tevents = jQuery._data(obj, \"events\");\n\tok( events, \"Object has events bound.\" );\n\tequal( obj[\"events\"], undefined, \"Events object on plain objects is not events\" );\n\tequal( obj[\"test\"], undefined, \"Make sure that test event is not on the plain object.\" );\n\tequal( obj[\"handle\"], undefined, \"Make sure that the event handler is not on the plain object.\" );\n\n\t// Should trigger 1\n\tjQuery(obj).trigger(\"test\");\n\tjQuery(obj).trigger(\"submit\");\n\n\tjQuery(obj).off(\"test\");\n\tjQuery(obj).off(\"submit\");\n\n\t// Should trigger 0\n\tjQuery(obj).trigger(\"test\");\n\n\t// Make sure it doesn't complain when no events are found\n\tjQuery(obj).off(\"test\");\n\n\tequal( obj && obj[ jQuery.expando ] &&\n\t\t\tobj[ jQuery.expando ][ jQuery.expando ] &&\n\t\t\tobj[ jQuery.expando ][ jQuery.expando ][\"events\"], undefined, \"Make sure events object is removed\" );\n});\n\ntest(\"off(type)\", function() {\n\texpect( 1 );\n\n\tvar message, func,\n\t\t$elem = jQuery(\"#firstp\");\n\n\tfunction error(){\n\t\tok( false, message );\n\t}\n\n\tmessage = \"unbind passing function\";\n\t$elem.on(\"error1\", error).off(\"error1\", error).triggerHandler(\"error1\");\n\n\tmessage = \"unbind all from event\";\n\t$elem.on(\"error1\", error).off(\"error1\").triggerHandler(\"error1\");\n\n\tmessage = \"unbind all\";\n\t$elem.on(\"error1\", error).off().triggerHandler(\"error1\");\n\n\tmessage = \"unbind many with function\";\n\t$elem.on(\"error1 error2\",error)\n\t\t.off(\"error1 error2\", error )\n\t\t.trigger(\"error1\").triggerHandler(\"error2\");\n\n\tmessage = \"unbind many\"; // #3538\n\t$elem.on(\"error1 error2\", error)\n\t\t.off(\"error1 error2\")\n\t\t.trigger(\"error1\").triggerHandler(\"error2\");\n\n\tmessage = \"unbind without a type or handler\";\n\t$elem.on(\"error1 error2.test\",error)\n\t\t.off()\n\t\t.trigger(\"error1\").triggerHandler(\"error2\");\n\n\t// Should only unbind the specified function\n\tjQuery( document ).on( \"click\", function(){\n\t\tok( true, \"called handler after selective removal\");\n\t});\n\tfunc = function() {};\n\tjQuery( document )\n\t\t.on( \"click\", func )\n\t\t.off( \"click\", func )\n\t\t.trigger(\"click\")\n\t\t.off( \"click\" );\n});\n\ntest(\"off(eventObject)\", function() {\n\texpect(4);\n\n\tvar $elem = jQuery(\"#firstp\"),\n\t\tnum;\n\n\tfunction assert( expected ){\n\t\tnum = 0;\n\t\t$elem.trigger(\"foo\").triggerHandler(\"bar\");\n\t\tequal( num, expected, \"Check the right handlers are triggered\" );\n\t}\n\n\t$elem\n\t\t// This handler shouldn't be unbound\n\t\t.on(\"foo\", function(){\n\t\t\tnum += 1;\n\t\t})\n\t\t.on(\"foo\", function(e){\n\t\t\t$elem.off( e );\n\t\t\tnum += 2;\n\t\t})\n\t\t// Neither this one\n\t\t.on(\"bar\", function(){\n\t\t\tnum += 4;\n\t\t});\n\n\tassert( 7 );\n\tassert( 5 );\n\n\t$elem.off(\"bar\");\n\tassert( 1 );\n\n\t$elem.off();\n\tassert( 0 );\n});\n\nif ( jQuery.fn.hover ) {\n\ttest(\"hover() mouseenter mouseleave\", function() {\n\t\texpect(1);\n\n\t\tvar times = 0,\n\t\t\thandler1 = function() { ++times; },\n\t\t\thandler2 = function() { ++times; };\n\n\t\tjQuery(\"#firstp\")\n\t\t\t.hover(handler1, handler2)\n\t\t\t.mouseenter().mouseleave()\n\t\t\t.off(\"mouseenter\", handler1)\n\t\t\t.off(\"mouseleave\", handler2)\n\t\t\t.hover(handler1)\n\t\t\t.mouseenter().mouseleave()\n\t\t\t.off(\"mouseenter mouseleave\", handler1)\n\t\t\t.mouseenter().mouseleave();\n\n\t\tequal( times, 4, \"hover handlers fired\" );\n\n\t});\n}\n\ntest(\"mouseover triggers mouseenter\", function() {\n\texpect(1);\n\n\tvar count = 0,\n\t\telem = jQuery(\"<a />\");\n\telem.on( \"mouseenter\", function () {\n\t\tcount++;\n\t});\n\telem.trigger(\"mouseover\");\n\tequal(count, 1, \"make sure mouseover triggers a mouseenter\" );\n\n\telem.remove();\n});\n\ntest(\"withinElement implemented with jQuery.contains()\", function() {\n\n\texpect(1);\n\n\tjQuery(\"#qunit-fixture\").append(\"<div id='jc-outer'><div id='jc-inner'></div></div>\");\n\n\tjQuery(\"#jc-outer\").on(\"mouseenter mouseleave\", function( event ) {\n\n\t\tequal( this.id, \"jc-outer\", this.id + \" \" + event.type );\n\n\t}).trigger(\"mouseenter\");\n\n\tjQuery(\"#jc-inner\").trigger(\"mousenter\");\n\n\tjQuery(\"#jc-outer\").off(\"mouseenter mouseleave\").remove();\n\tjQuery(\"#jc-inner\").remove();\n\n});\n\ntest(\"mouseenter, mouseleave don't catch exceptions\", function() {\n\texpect(2);\n\n\tvar elem = jQuery(\"#firstp\").on( \"mouseenter mouseleave\", function() {\n\t\t\tthrow \"an Exception\";\n\t\t});\n\n\ttry {\n\t\telem.trigger(\"mouseenter\");\n\t} catch (e) {\n\t\tequal( e, \"an Exception\", \"mouseenter doesn't catch exceptions\" );\n\t}\n\n\ttry {\n\t\telem.trigger(\"mouseleave\");\n\t} catch (e) {\n\t\tequal( e, \"an Exception\", \"mouseleave doesn't catch exceptions\" );\n\t}\n});\n\nif ( jQuery.fn.click ) {\n\n\ttest(\"trigger() shortcuts\", function() {\n\t\texpect(6);\n\n\t\tvar counter, clickCounter,\n\t\t\telem = jQuery(\"<li><a href='#'>Change location</a></li>\").prependTo(\"#firstUL\");\n\t\telem.find(\"a\").on(\"click\", function() {\n\t\t\tvar close = jQuery(\"spanx\", this); // same with jQuery(this).find(\"span\");\n\t\t\tequal( close.length, 0, \"Context element does not exist, length must be zero\" );\n\t\t\tok( !close[0], \"Context element does not exist, direct access to element must return undefined\" );\n\t\t\treturn false;\n\t\t}).click();\n\n\t\t// manually clean up detached elements\n\t\telem.remove();\n\n\t\tjQuery(\"#check1\").click(function() {\n\t\t\tok( true, \"click event handler for checkbox gets fired twice, see #815\" );\n\t\t}).click();\n\n\t\tcounter = 0;\n\t\tjQuery(\"#firstp\")[0].onclick = function() {\n\t\t\tcounter++;\n\t\t};\n\t\tjQuery(\"#firstp\").click();\n\t\tequal( counter, 1, \"Check that click, triggers onclick event handler also\" );\n\n\t\tclickCounter = 0;\n\t\tjQuery(\"#simon1\")[0].onclick = function() {\n\t\t\tclickCounter++;\n\t\t};\n\t\tjQuery(\"#simon1\").click();\n\t\tequal( clickCounter, 1, \"Check that click, triggers onclick event handler on an a tag also\" );\n\n\t\telem = jQuery(\"<img />\").load(function(){\n\t\t\tok( true, \"Trigger the load event, using the shortcut .load() (#2819)\");\n\t\t}).load();\n\n\t\t// manually clean up detached elements\n\t\telem.remove();\n\n\t\t// test that special handlers do not blow up with VML elements (#7071)\n\t\tjQuery(\"<xml:namespace ns='urn:schemas-microsoft-com:vml' prefix='v' />\").appendTo(\"head\");\n\t\tjQuery(\"<v:oval id='oval' style='width:100pt;height:75pt;' fillcolor='red'> </v:oval>\").appendTo(\"#form\");\n\t\tjQuery(\"#oval\").click().keydown();\n\t});\n\n}\n\ntest(\"trigger() bubbling\", function() {\n\texpect(18);\n\n\tvar win = 0, doc = 0, html = 0, body = 0, main = 0, ap = 0;\n\n\tjQuery(window).on(\"click\", function(){ win++; });\n\tjQuery(document).on(\"click\", function( e ){ if ( e.target !== document) { doc++; } });\n\tjQuery(\"html\").on(\"click\", function(){ html++; });\n\tjQuery(\"body\").on(\"click\", function(){ body++; });\n\tjQuery(\"#qunit-fixture\").on(\"click\", function(){ main++; });\n\tjQuery(\"#ap\").on(\"click\", function(){ ap++; return false; });\n\n\tjQuery(\"html\").trigger(\"click\");\n\tequal( win, 1, \"HTML bubble\" );\n\tequal( doc, 1, \"HTML bubble\" );\n\tequal( html, 1, \"HTML bubble\" );\n\n\tjQuery(\"body\").trigger(\"click\");\n\tequal( win, 2, \"Body bubble\" );\n\tequal( doc, 2, \"Body bubble\" );\n\tequal( html, 2, \"Body bubble\" );\n\tequal( body, 1, \"Body bubble\" );\n\n\tjQuery(\"#qunit-fixture\").trigger(\"click\");\n\tequal( win, 3, \"Main bubble\" );\n\tequal( doc, 3, \"Main bubble\" );\n\tequal( html, 3, \"Main bubble\" );\n\tequal( body, 2, \"Main bubble\" );\n\tequal( main, 1, \"Main bubble\" );\n\n\tjQuery(\"#ap\").trigger(\"click\");\n\tequal( doc, 3, \"ap bubble\" );\n\tequal( html, 3, \"ap bubble\" );\n\tequal( body, 2, \"ap bubble\" );\n\tequal( main, 1, \"ap bubble\" );\n\tequal( ap, 1, \"ap bubble\" );\n\n\tjQuery( document ).trigger(\"click\");\n\tequal( win, 4, \"doc bubble\" );\n\n\t// manually clean up events from elements outside the fixture\n\tjQuery(document).off(\"click\");\n\tjQuery(\"html, body, #qunit-fixture\").off(\"click\");\n});\n\ntest(\"trigger(type, [data], [fn])\", function() {\n\texpect(16);\n\n\tvar $elem, pass, form, elem2,\n\t\thandler = function(event, a, b, c) {\n\t\tequal( event.type, \"click\", \"check passed data\" );\n\t\tequal( a, 1, \"check passed data\" );\n\t\tequal( b, \"2\", \"check passed data\" );\n\t\tequal( c, \"abc\", \"check passed data\" );\n\t\treturn \"test\";\n\t};\n\n\t$elem = jQuery(\"#firstp\");\n\n\t// Simulate a \"native\" click\n\t$elem[0].click = function(){\n\t\tok( true, \"Native call was triggered\" );\n\t};\n\n\n\tjQuery( document ).on(\"mouseenter\", \"#firstp\", function(){\n\t\tok( true, \"Trigger mouseenter bound by on\" );\n\t});\n\n\tjQuery( document ).on(\"mouseleave\", \"#firstp\", function(){\n\t\tok( true, \"Trigger mouseleave bound by on\" );\n\t});\n\n\t$elem.trigger(\"mouseenter\");\n\n\t$elem.trigger(\"mouseleave\");\n\n\tjQuery( document ).off( \"mouseenter mouseleave\", \"#firstp\");\n\n\t// Triggers handlers and native\n\t// Trigger 5\n\t$elem.on(\"click\", handler).trigger(\"click\", [1, \"2\", \"abc\"]);\n\n\t// Simulate a \"native\" click\n\t$elem[0].click = function(){\n\t\tok( false, \"Native call was triggered\" );\n\t};\n\n\t// Trigger only the handlers (no native)\n\t// Triggers 5\n\tequal( $elem.triggerHandler(\"click\", [1, \"2\", \"abc\"]), \"test\", \"Verify handler response\" );\n\n\tpass = true;\n\ttry {\n\t\telem2 = jQuery(\"#form input\").eq(0);\n\t\telem2.get(0).style.display = \"none\";\n\t\telem2.trigger(\"focus\");\n\t} catch( e ) {\n\t\tpass = false;\n\t}\n\tok( pass, \"Trigger focus on hidden element\" );\n\n\tpass = true;\n\ttry {\n\t\tjQuery(\"#qunit-fixture table\").eq(0).on(\"test:test\", function(){}).trigger(\"test:test\");\n\t} catch ( e ) {\n\t\tpass = false;\n\t}\n\tok( pass, \"Trigger on a table with a colon in the even type, see #3533\" );\n\n\tform = jQuery(\"<form action=''></form>\").appendTo(\"body\");\n\n\t// Make sure it can be prevented locally\n\tform.on( \"submit\", function(){\n\t\tok( true, \"Local `on` still works.\" );\n\t\treturn false;\n\t});\n\n\t// Trigger 1\n\tform.trigger(\"submit\");\n\n\tform.off(\"submit\");\n\n\tjQuery(document).on( \"submit\", function(){\n\t\tok( true, \"Make sure bubble works up to document.\" );\n\t\treturn false;\n\t});\n\n\t// Trigger 1\n\tform.trigger(\"submit\");\n\n\tjQuery(document).off(\"submit\");\n\n\tform.remove();\n});\n\ntest( \"submit event bubbles on copied forms (#11649)\", function() {\n\texpect( 3 );\n\n\tvar $formByClone, $formByHTML,\n\t\t$testForm = jQuery(\"#testForm\"),\n\t\t$fixture = jQuery(\"#qunit-fixture\"),\n\t\t$wrapperDiv = jQuery(\"<div/>\").appendTo( $fixture );\n\n\tfunction noSubmit( e ) {\n\t\te.preventDefault();\n\t}\n\tfunction delegatedSubmit() {\n\t\tok( true, \"Make sure submit event bubbles up.\" );\n\t\treturn false;\n\t}\n\n\t// Attach a delegated submit handler to the parent element\n\t$fixture.on( \"submit\", \"form\", delegatedSubmit );\n\n\t// Trigger form submission to introduce the _submit_attached property\n\t$testForm.on( \"submit\", noSubmit ).find(\"input[name=sub1]\").trigger(\"click\");\n\n\t// Copy the form via .clone() and .html()\n\t$formByClone = $testForm.clone( true, true ).removeAttr(\"id\");\n\t$formByHTML = jQuery( jQuery.parseHTML($fixture.html()) ).filter(\"#testForm\").removeAttr(\"id\");\n\t$wrapperDiv.append( $formByClone, $formByHTML );\n\n\t// Check submit bubbling on the copied forms\n\t$wrapperDiv.find(\"form\").on( \"submit\", noSubmit ).find(\"input[name=sub1]\").trigger(\"click\");\n\n\t// Clean up\n\t$wrapperDiv.remove();\n\t$fixture.off( \"submit\", \"form\", delegatedSubmit );\n\t$testForm.off( \"submit\", noSubmit );\n});\n\ntest( \"change event bubbles on copied forms (#11796)\", function(){\n\texpect( 3 );\n\n\tvar $formByClone, $formByHTML,\n\t\t$form = jQuery(\"#form\"),\n\t\t$fixture = jQuery(\"#qunit-fixture\"),\n\t\t$wrapperDiv = jQuery(\"<div/>\").appendTo( $fixture );\n\n\tfunction delegatedChange() {\n\t\tok( true, \"Make sure change event bubbles up.\" );\n\t\treturn false;\n\t}\n\n\t// Attach a delegated change handler to the form\n\t$fixture.on( \"change\", \"form\", delegatedChange );\n\n\t// Trigger change event to introduce the _change_attached property\n\t$form.find(\"select[name=select1]\").val(\"1\").trigger(\"change\");\n\n\t// Copy the form via .clone() and .html()\n\t$formByClone = $form.clone( true, true ).removeAttr(\"id\");\n\t$formByHTML = jQuery( jQuery.parseHTML($fixture.html()) ).filter(\"#form\").removeAttr(\"id\");\n\t$wrapperDiv.append( $formByClone, $formByHTML );\n\n\t// Check change bubbling on the copied forms\n\t$wrapperDiv.find(\"form select[name=select1]\").val(\"2\").trigger(\"change\");\n\n\t// Clean up\n\t$wrapperDiv.remove();\n\t$fixture.off( \"change\", \"form\", delegatedChange );\n});\n\ntest(\"trigger(eventObject, [data], [fn])\", function() {\n\texpect(28);\n\n\tvar event,\n\t\t$parent = jQuery(\"<div id='par' />\").appendTo(\"body\"),\n\t\t$child = jQuery(\"<p id='child'>foo</p>\").appendTo( $parent );\n\n\t$parent.get( 0 ).style.display = \"none\";\n\n\tevent = jQuery.Event(\"noNew\");\n\tok( event !== window, \"Instantiate jQuery.Event without the 'new' keyword\" );\n\tequal( event.type, \"noNew\", \"Verify its type\" );\n\n\tequal( event.isDefaultPrevented(), false, \"Verify isDefaultPrevented\" );\n\tequal( event.isPropagationStopped(), false, \"Verify isPropagationStopped\" );\n\tequal( event.isImmediatePropagationStopped(), false, \"Verify isImmediatePropagationStopped\" );\n\n\tevent.preventDefault();\n\tequal( event.isDefaultPrevented(), true, \"Verify isDefaultPrevented\" );\n\tevent.stopPropagation();\n\tequal( event.isPropagationStopped(), true, \"Verify isPropagationStopped\" );\n\n\tevent.isPropagationStopped = function(){ return false; };\n\tevent.stopImmediatePropagation();\n\tequal( event.isPropagationStopped(), true, \"Verify isPropagationStopped\" );\n\tequal( event.isImmediatePropagationStopped(), true, \"Verify isPropagationStopped\" );\n\n\t$parent.on(\"foo\",function( e ) {\n\t\t// Tries bubbling\n\t\tequal( e.type, \"foo\", \"Verify event type when passed passing an event object\" );\n\t\tequal( e.target.id, \"child\", \"Verify event.target when passed passing an event object\" );\n\t\tequal( e.currentTarget.id, \"par\", \"Verify event.currentTarget when passed passing an event object\" );\n\t\tequal( e.secret, \"boo!\", \"Verify event object's custom attribute when passed passing an event object\" );\n\t});\n\n\t// test with an event object\n\tevent = new jQuery.Event(\"foo\");\n\tevent.secret = \"boo!\";\n\t$child.trigger(event);\n\n\t// test with a literal object\n\t$child.trigger({\"type\": \"foo\", \"secret\": \"boo!\"});\n\n\t$parent.off();\n\n\tfunction error(){\n\t\tok( false, \"This assertion shouldn't be reached\");\n\t}\n\n\t$parent.on(\"foo\", error );\n\n\t$child.on(\"foo\",function(e, a, b, c ){\n\t\tequal( arguments.length, 4, \"Check arguments length\");\n\t\tequal( a, 1, \"Check first custom argument\");\n\t\tequal( b, 2, \"Check second custom argument\");\n\t\tequal( c, 3, \"Check third custom argument\");\n\n\t\tequal( e.isDefaultPrevented(), false, \"Verify isDefaultPrevented\" );\n\t\tequal( e.isPropagationStopped(), false, \"Verify isPropagationStopped\" );\n\t\tequal( e.isImmediatePropagationStopped(), false, \"Verify isImmediatePropagationStopped\" );\n\n\t\t// Skips both errors\n\t\te.stopImmediatePropagation();\n\n\t\treturn \"result\";\n\t});\n\n\t// We should add this back in when we want to test the order\n\t// in which event handlers are iterated.\n\t//$child.on(\"foo\", error );\n\n\tevent = new jQuery.Event(\"foo\");\n\t$child.trigger( event, [1,2,3] ).off();\n\tequal( event.result, \"result\", \"Check event.result attribute\");\n\n\t// Will error if it bubbles\n\t$child.triggerHandler(\"foo\");\n\n\t$child.off();\n\t$parent.off().remove();\n\n\t// Ensure triggerHandler doesn't molest its event object (#xxx)\n\tevent = jQuery.Event( \"zowie\" );\n\tjQuery( document ).triggerHandler( event );\n\tequal( event.type, \"zowie\", \"Verify its type\" );\n\tequal( event.isPropagationStopped(), false, \"propagation not stopped\" );\n\tequal( event.isDefaultPrevented(), false, \"default not prevented\" );\n});\n\n// Explicitly introduce global variable for oldIE so QUnit doesn't complain if checking globals\nwindow.onclick = undefined;\ntest(\".trigger() bubbling on disconnected elements (#10489)\", function() {\n\texpect(2);\n\n\tjQuery( window ).on( \"click\", function(){\n\t\tok( false, \"click fired on window\" );\n\t});\n\n\tjQuery( \"<div><p>hi</p></div>\" )\n\t\t.on( \"click\", function() {\n\t\t\tok( true, \"click fired on div\" );\n\t\t})\n\t\t.find( \"p\" )\n\t\t\t.on( \"click\", function() {\n\t\t\t\tok( true, \"click fired on p\" );\n\t\t\t})\n\t\t\t.trigger(\"click\")\n\t\t\t.off( \"click\" )\n\t\t.end()\n\t\t.off( \"click\" )\n\t\t.remove();\n\n\tjQuery( window ).off( \"click\" );\n});\n\ntest(\".trigger() doesn't bubble load event (#10717)\", function() {\n\texpect(1);\n\n\tjQuery( window ).on( \"load\", function(){\n\t\tok( false, \"load fired on window\" );\n\t});\n\n\t// It's not an image, but as long as it fires load...\n\tjQuery(\"<img src='index.html' />\")\n\t\t.appendTo( \"body\" )\n\t\t.on( \"load\", function() {\n\t\t\tok( true, \"load fired on img\" );\n\t\t})\n\t\t.trigger( \"load\" )\n\t\t.remove();\n\n\tjQuery( window ).off( \"load\" );\n});\n\ntest(\"Delegated events in SVG (#10791; #13180)\", function() {\n\texpect(2);\n\n\tvar useElem, e,\n\t\tsvg = jQuery(\n\t\t\t\"<svg height='1' version='1.1' width='1' xmlns='http://www.w3.org/2000/svg'>\" +\n\t\t\t\"<defs><rect id='ref' x='10' y='20' width='100' height='60' r='10' rx='10' ry='10'></rect></defs>\" +\n\t\t\t\"<rect class='svg-by-class' x='10' y='20' width='100' height='60' r='10' rx='10' ry='10'></rect>\" +\n\t\t\t\"<rect id='svg-by-id' x='10' y='20' width='100' height='60' r='10' rx='10' ry='10'></rect>\" +\n\t\t\t\"<use id='use' xlink:href='#ref'></use>\" +\n\t\t\t\"</svg>\"\n\t\t);\n\n\tjQuery(\"#qunit-fixture\")\n\t\t.append( svg )\n\t\t.on( \"click\", \"#svg-by-id\", function() {\n\t\t\tok( true, \"delegated id selector\" );\n\t\t})\n\t\t.on( \"click\", \"[class~='svg-by-class']\", function() {\n\t\t\tok( true, \"delegated class selector\" );\n\t\t})\n\t\t.find( \"#svg-by-id, [class~='svg-by-class']\" )\n\t\t\t.trigger(\"click\")\n\t\t.end();\n\n\t// Fire a native click on an SVGElementInstance (the instance tree of an SVG <use>)\n\t// to confirm that it doesn't break our event delegation handling (#13180)\n\tuseElem = svg.find(\"#use\")[0];\n\tif ( document.createEvent && useElem && useElem.instanceRoot ) {\n\t\te = document.createEvent(\"MouseEvents\");\n\t\te.initEvent( \"click\", true, true );\n\t\tuseElem.instanceRoot.dispatchEvent( e );\n\t}\n\n\tjQuery(\"#qunit-fixture\").off(\"click\");\n});\n\ntest(\"Delegated events in forms (#10844; #11145; #8165; #11382, #11764)\", function() {\n\texpect(5);\n\n\t// Alias names like \"id\" cause havoc\n\tvar form = jQuery(\n\t\t\t\"<form id='myform'>\" +\n\t\t\t\t\"<input type='text' name='id' value='secret agent man' />\" +\n\t\t\t\"</form>\"\n\t\t)\n\t\t.on( \"submit\", function( event ) {\n\t\t\tevent.preventDefault();\n\t\t})\n\t\t.appendTo(\"body\");\n\n\tjQuery(\"body\")\n\t\t.on( \"submit\", \"#myform\", function() {\n\t\t\tok( true, \"delegated id selector with aliased id\" );\n\t\t})\n\t\t.find(\"#myform\")\n\t\t\t.trigger(\"submit\")\n\t\t.end()\n\t\t.off(\"submit\");\n\n\tform.append(\"<input type='text' name='disabled' value='differently abled' />\");\n\tjQuery(\"body\")\n\t\t.on( \"submit\", \"#myform\", function() {\n\t\t\tok( true, \"delegated id selector with aliased disabled\" );\n\t\t})\n\t\t.find(\"#myform\")\n\t\t\t.trigger(\"submit\")\n\t\t.end()\n\t\t.off(\"submit\");\n\n\tform\n\t\t.append( \"<button id='nestyDisabledBtn'><span>Zing</span></button>\" )\n\t\t.on( \"click\", \"#nestyDisabledBtn\", function() {\n\t\t\tok( true, \"click on enabled/disabled button with nesty elements\" );\n\t\t})\n\t\t.on( \"mouseover\", \"#nestyDisabledBtn\", function() {\n\t\t\tok( true, \"mouse on enabled/disabled button with nesty elements\" );\n\t\t})\n\t\t.find( \"span\" )\n\t\t\t.trigger( \"click\" )\t\t// yep\n\t\t\t.trigger( \"mouseover\" )\t// yep\n\t\t.end()\n\t\t.find( \"#nestyDisabledBtn\" ).prop( \"disabled\", true ).end()\n\t\t.find( \"span\" )\n\t\t\t.trigger( \"click\" )\t\t// nope\n\t\t\t.trigger( \"mouseover\" )\t// yep\n\t\t.end()\n\t\t.off( \"click\" );\n\n\tform.remove();\n});\n\ntest(\"Submit event can be stopped (#11049)\", function() {\n\texpect(1);\n\n\t// Since we manually bubble in IE, make sure inner handlers get a chance to cancel\n\tvar form = jQuery(\n\t\t\t\"<form id='myform'>\" +\n\t\t\t\t\"<input type='text' name='sue' value='bawls' />\" +\n\t\t\t\t\"<input type='submit' />\" +\n\t\t\t\"</form>\"\n\t\t)\n\t\t.appendTo(\"body\");\n\n\tjQuery( \"body\" )\n\t\t.on( \"submit\", function() {\n\t\t\tok( true, \"submit bubbled on first handler\" );\n\t\t\treturn false;\n\t\t})\n\t\t.find( \"#myform input[type=submit]\" )\n\t\t\t.each( function(){ this.click(); } )\n\t\t.end()\n\t\t.on( \"submit\", function() {\n\t\t\tok( false, \"submit bubbled on second handler\" );\n\t\t\treturn false;\n\t\t})\n\t\t.find( \"#myform input[type=submit]\" )\n\t\t\t.each( function(){\n\t\t\t\tjQuery( this.form ).on( \"submit\", function( e ) {\n\t\t\t\t\te.preventDefault();\n\t\t\t\t\te.stopPropagation();\n\t\t\t\t});\n\t\t\t\tthis.click();\n\t\t\t})\n\t\t.end()\n\t\t.off( \"submit\" );\n\n\tform.remove();\n});\n\n// Test beforeunload event only if it supported (i.e. not Opera)\nif ( window.onbeforeunload === null ) {\n\tasyncTest(\"on(beforeunload)\", 1, function() {\n\t\tvar iframe = jQuery(jQuery.parseHTML(\"<iframe src='data/event/onbeforeunload.html'><iframe>\"));\n\n\t\twindow.onmessage = function( event ) {\n\t\t\tvar payload = JSON.parse( event.data );\n\n\t\t\tok( payload.event, \"beforeunload\", \"beforeunload event\" );\n\n\t\t\tiframe.remove();\n\t\t\twindow.onmessage = null;\n\t\t\tstart();\n\t\t};\n\n\t\tiframe.appendTo(\"#qunit-fixture\");\n\t});\n}\n\ntest(\"jQuery.Event( type, props )\", function() {\n\n\texpect(5);\n\n\tvar event = jQuery.Event( \"keydown\", { keyCode: 64 }),\n\t\t\thandler = function( event ) {\n\t\t\t\tok( \"keyCode\" in event, \"Special property 'keyCode' exists\" );\n\t\t\t\tequal( event.keyCode, 64, \"event.keyCode has explicit value '64'\" );\n\t\t\t};\n\n\t// Supports jQuery.Event implementation\n\tequal( event.type, \"keydown\", \"Verify type\" );\n\n\t// ensure \"type\" in props won't clobber the one set by constructor\n\tequal( jQuery.inArray(\"type\", jQuery.event.props), -1, \"'type' property not in props (#10375)\" );\n\n\tok( \"keyCode\" in event, \"Special 'keyCode' property exists\" );\n\n\tjQuery(\"body\").on( \"keydown\", handler ).trigger( event );\n\n\tjQuery(\"body\").off( \"keydown\" );\n\n});\n\ntest(\"jQuery.Event properties\", function(){\n\texpect(12);\n\n\tvar handler,\n\t\t$structure = jQuery(\"<div id='ancestor'><p id='delegate'><span id='target'>shiny</span></p></div>\"),\n\t\t$target = $structure.find(\"#target\");\n\n\thandler = function( e ) {\n\t\tstrictEqual( e.currentTarget, this, \"currentTarget at \" + this.id );\n\t\tequal( e.isTrigger, 3, \"trigger at \" + this.id );\n\t};\n\t$structure.one( \"click\", handler );\n\t$structure.one( \"click\", \"p\", handler );\n\t$target.one( \"click\", handler );\n\t$target[0].onclick = function( e ) {\n\t\tstrictEqual( e.currentTarget, this, \"currentTarget at target (native handler)\" );\n\t\tequal( e.isTrigger, 3, \"trigger at target (native handler)\" );\n\t};\n\t$target.trigger(\"click\");\n\n\t$target.one( \"click\", function( e ) {\n\t\tequal( e.isTrigger, 2, \"triggerHandler at target\" );\n\t});\n\t$target[0].onclick = function( e ) {\n\t\tequal( e.isTrigger, 2, \"triggerHandler at target (native handler)\" );\n\t};\n\t$target.triggerHandler(\"click\");\n\n\thandler = function( e ) {\n\t\tstrictEqual( e.isTrigger, undefined, \"native event at \" + this.id );\n\t};\n\t$target.one( \"click\", handler );\n\t$target[0].onclick = function( e ) {\n\t\tstrictEqual( e.isTrigger, undefined, \"native event at target (native handler)\" );\n\t};\n\tfireNative( $target[0], \"click\" );\n});\n\ntest(\".on()/.off()\", function() {\n\texpect(65);\n\n\tvar event, clicked, hash, called, livec, lived, livee,\n\t\tsubmit = 0, div = 0, livea = 0, liveb = 0;\n\n\tjQuery(\"#body\").on(\"submit\", \"#qunit-fixture div\", function(){ submit++; return false; });\n\tjQuery(\"#body\").on(\"click\", \"#qunit-fixture div\", function(){ div++; });\n\tjQuery(\"#body\").on(\"click\", \"div#nothiddendiv\", function(){ livea++; });\n\tjQuery(\"#body\").on(\"click\", \"div#nothiddendivchild\", function(){ liveb++; });\n\n\t// Nothing should trigger on the body\n\tjQuery(\"body\").trigger(\"click\");\n\tequal( submit, 0, \"Click on body\" );\n\tequal( div, 0, \"Click on body\" );\n\tequal( livea, 0, \"Click on body\" );\n\tequal( liveb, 0, \"Click on body\" );\n\n\t// This should trigger two events\n\tsubmit = 0; div = 0; livea = 0; liveb = 0;\n\tjQuery(\"div#nothiddendiv\").trigger(\"click\");\n\tequal( submit, 0, \"Click on div\" );\n\tequal( div, 1, \"Click on div\" );\n\tequal( livea, 1, \"Click on div\" );\n\tequal( liveb, 0, \"Click on div\" );\n\n\t// This should trigger three events (w/ bubbling)\n\tsubmit = 0; div = 0; livea = 0; liveb = 0;\n\tjQuery(\"div#nothiddendivchild\").trigger(\"click\");\n\tequal( submit, 0, \"Click on inner div\" );\n\tequal( div, 2, \"Click on inner div\" );\n\tequal( livea, 1, \"Click on inner div\" );\n\tequal( liveb, 1, \"Click on inner div\" );\n\n\t// This should trigger one submit\n\tsubmit = 0; div = 0; livea = 0; liveb = 0;\n\tjQuery(\"div#nothiddendivchild\").trigger(\"submit\");\n\tequal( submit, 1, \"Submit on div\" );\n\tequal( div, 0, \"Submit on div\" );\n\tequal( livea, 0, \"Submit on div\" );\n\tequal( liveb, 0, \"Submit on div\" );\n\n\t// Make sure no other events were removed in the process\n\tsubmit = 0; div = 0; livea = 0; liveb = 0;\n\tjQuery(\"div#nothiddendivchild\").trigger(\"click\");\n\tequal( submit, 0, \"off Click on inner div\" );\n\tequal( div, 2, \"off Click on inner div\" );\n\tequal( livea, 1, \"off Click on inner div\" );\n\tequal( liveb, 1, \"off Click on inner div\" );\n\n\t// Now make sure that the removal works\n\tsubmit = 0; div = 0; livea = 0; liveb = 0;\n\tjQuery(\"#body\").off(\"click\", \"div#nothiddendivchild\");\n\tjQuery(\"div#nothiddendivchild\").trigger(\"click\");\n\tequal( submit, 0, \"off Click on inner div\" );\n\tequal( div, 2, \"off Click on inner div\" );\n\tequal( livea, 1, \"off Click on inner div\" );\n\tequal( liveb, 0, \"off Click on inner div\" );\n\n\t// Make sure that the click wasn't removed too early\n\tsubmit = 0; div = 0; livea = 0; liveb = 0;\n\tjQuery(\"div#nothiddendiv\").trigger(\"click\");\n\tequal( submit, 0, \"off Click on inner div\" );\n\tequal( div, 1, \"off Click on inner div\" );\n\tequal( livea, 1, \"off Click on inner div\" );\n\tequal( liveb, 0, \"off Click on inner div\" );\n\n\t// Make sure that stopPropagation doesn't stop live events\n\tsubmit = 0; div = 0; livea = 0; liveb = 0;\n\tjQuery(\"#body\").on(\"click\", \"div#nothiddendivchild\", function( e ){ liveb++; e.stopPropagation(); });\n\tjQuery(\"div#nothiddendivchild\").trigger(\"click\");\n\tequal( submit, 0, \"stopPropagation Click on inner div\" );\n\tequal( div, 1, \"stopPropagation Click on inner div\" );\n\tequal( livea, 0, \"stopPropagation Click on inner div\" );\n\tequal( liveb, 1, \"stopPropagation Click on inner div\" );\n\n\t// Make sure click events only fire with primary click\n\tsubmit = 0; div = 0; livea = 0; liveb = 0;\n\tevent = jQuery.Event(\"click\");\n\tevent.button = 1;\n\tjQuery(\"div#nothiddendiv\").trigger(event);\n\n\tequal( livea, 0, \"on secondary click\" );\n\n\tjQuery(\"#body\").off(\"click\", \"div#nothiddendivchild\");\n\tjQuery(\"#body\").off(\"click\", \"div#nothiddendiv\");\n\tjQuery(\"#body\").off(\"click\", \"#qunit-fixture div\");\n\tjQuery(\"#body\").off(\"submit\", \"#qunit-fixture div\");\n\n\t// Test binding with a different context\n\tclicked = 0;\n\tjQuery(\"#qunit-fixture\").on(\"click\", \"#foo\", function(){ clicked++; });\n\tjQuery(\"#qunit-fixture div\").trigger(\"click\");\n\tjQuery(\"#foo\").trigger(\"click\");\n\tjQuery(\"#qunit-fixture\").trigger(\"click\");\n\tjQuery(\"body\").trigger(\"click\");\n\tequal( clicked, 2, \"on with a context\" );\n\n\t// Test unbinding with a different context\n\tjQuery(\"#qunit-fixture\").off(\"click\", \"#foo\");\n\tjQuery(\"#foo\").trigger(\"click\");\n\tequal( clicked, 2, \"off with a context\");\n\n\t// Test binding with event data\n\tjQuery(\"#body\").on(\"click\", \"#foo\", true, function( e ){ equal( e.data, true, \"on with event data\" ); });\n\tjQuery(\"#foo\").trigger(\"click\");\n\tjQuery(\"#body\").off(\"click\", \"#foo\");\n\n\t// Test binding with trigger data\n\tjQuery(\"#body\").on(\"click\", \"#foo\", function(e, data){ equal( data, true, \"on with trigger data\" ); });\n\tjQuery(\"#foo\").trigger(\"click\", true);\n\tjQuery(\"#body\").off(\"click\", \"#foo\");\n\n\t// Test binding with different this object\n\tjQuery(\"#body\").on(\"click\", \"#foo\", jQuery.proxy(function(){ equal( this[\"foo\"], \"bar\", \"on with event scope\" ); }, { \"foo\": \"bar\" }));\n\tjQuery(\"#foo\").trigger(\"click\");\n\tjQuery(\"#body\").off(\"click\", \"#foo\");\n\n\t// Test binding with different this object, event data, and trigger data\n\tjQuery(\"#body\").on(\"click\", \"#foo\", true, jQuery.proxy(function(e, data){\n\t\tequal( e.data, true, \"on with with different this object, event data, and trigger data\" );\n\t\tequal( this.foo, \"bar\", \"on with with different this object, event data, and trigger data\" );\n\t\tequal( data, true, \"on with with different this object, event data, and trigger data\");\n\t}, { \"foo\": \"bar\" }));\n\tjQuery(\"#foo\").trigger(\"click\", true);\n\tjQuery(\"#body\").off(\"click\", \"#foo\");\n\n\t// Verify that return false prevents default action\n\tjQuery(\"#body\").on(\"click\", \"#anchor2\", function(){ return false; });\n\thash = window.location.hash;\n\tjQuery(\"#anchor2\").trigger(\"click\");\n\tequal( window.location.hash, hash, \"return false worked\" );\n\tjQuery(\"#body\").off(\"click\", \"#anchor2\");\n\n\t// Verify that .preventDefault() prevents default action\n\tjQuery(\"#body\").on(\"click\", \"#anchor2\", function(e){ e.preventDefault(); });\n\thash = window.location.hash;\n\tjQuery(\"#anchor2\").trigger(\"click\");\n\tequal( window.location.hash, hash, \"e.preventDefault() worked\" );\n\tjQuery(\"#body\").off(\"click\", \"#anchor2\");\n\n\t// Test binding the same handler to multiple points\n\tcalled = 0;\n\tfunction callback(){ called++; return false; }\n\n\tjQuery(\"#body\").on(\"click\", \"#nothiddendiv\", callback);\n\tjQuery(\"#body\").on(\"click\", \"#anchor2\", callback);\n\n\tjQuery(\"#nothiddendiv\").trigger(\"click\");\n\tequal( called, 1, \"Verify that only one click occurred.\" );\n\n\tcalled = 0;\n\tjQuery(\"#anchor2\").trigger(\"click\");\n\tequal( called, 1, \"Verify that only one click occurred.\" );\n\n\t// Make sure that only one callback is removed\n\tjQuery(\"#body\").off(\"click\", \"#anchor2\", callback);\n\n\tcalled = 0;\n\tjQuery(\"#nothiddendiv\").trigger(\"click\");\n\tequal( called, 1, \"Verify that only one click occurred.\" );\n\n\tcalled = 0;\n\tjQuery(\"#anchor2\").trigger(\"click\");\n\tequal( called, 0, \"Verify that no click occurred.\" );\n\n\t// Make sure that it still works if the selector is the same,\n\t// but the event type is different\n\tjQuery(\"#body\").on(\"foo\", \"#nothiddendiv\", callback);\n\n\t// Cleanup\n\tjQuery(\"#body\").off(\"click\", \"#nothiddendiv\", callback);\n\n\tcalled = 0;\n\tjQuery(\"#nothiddendiv\").trigger(\"click\");\n\tequal( called, 0, \"Verify that no click occurred.\" );\n\n\tcalled = 0;\n\tjQuery(\"#nothiddendiv\").trigger(\"foo\");\n\tequal( called, 1, \"Verify that one foo occurred.\" );\n\n\t// Cleanup\n\tjQuery(\"#body\").off(\"foo\", \"#nothiddendiv\", callback);\n\n\t// Make sure we don't loose the target by DOM modifications\n\t// after the bubble already reached the liveHandler\n\tlivec = 0;\n\tjQuery(\"#nothiddendivchild\").html(\"<span></span>\");\n\n\tjQuery(\"#body\").on(\"click\", \"#nothiddendivchild\", function(){ jQuery(\"#nothiddendivchild\").html(\"\"); });\n\tjQuery(\"#body\").on(\"click\", \"#nothiddendivchild\", function(e){ if(e.target) {livec++;} });\n\n\tjQuery(\"#nothiddendiv span\").trigger(\"click\");\n\tequal( jQuery(\"#nothiddendiv span\").length, 0, \"Verify that first handler occurred and modified the DOM.\" );\n\tequal( livec, 1, \"Verify that second handler occurred even with nuked target.\" );\n\n\t// Cleanup\n\tjQuery(\"#body\").off(\"click\", \"#nothiddendivchild\");\n\n\t// Verify that .live() occurs and cancel bubble in the same order as\n\t// we would expect .on() and .click() without delegation\n\tlived = 0;\n\tlivee = 0;\n\n\t// bind one pair in one order\n\tjQuery(\"#body\").on(\"click\", \"span#liveSpan1 a\", function(){ lived++; return false; });\n\tjQuery(\"#body\").on(\"click\", \"span#liveSpan1\", function(){ livee++; });\n\n\tjQuery(\"span#liveSpan1 a\").trigger(\"click\");\n\tequal( lived, 1, \"Verify that only one first handler occurred.\" );\n\tequal( livee, 0, \"Verify that second handler doesn't.\" );\n\n\t// and one pair in inverse\n\tjQuery(\"#body\").on(\"click\", \"span#liveSpan2\", function(){ livee++; });\n\tjQuery(\"#body\").on(\"click\", \"span#liveSpan2 a\", function(){ lived++; return false; });\n\n\tlived = 0;\n\tlivee = 0;\n\tjQuery(\"span#liveSpan2 a\").trigger(\"click\");\n\tequal( lived, 1, \"Verify that only one first handler occurred.\" );\n\tequal( livee, 0, \"Verify that second handler doesn't.\" );\n\n\t// Cleanup\n\tjQuery(\"#body\").off(\"click\", \"**\");\n\n\t// Test this, target and currentTarget are correct\n\tjQuery(\"#body\").on(\"click\", \"span#liveSpan1\", function( e ) {\n\t\tequal( this.id, \"liveSpan1\", \"Check the this within a on handler\" );\n\t\tequal( e.currentTarget.id, \"liveSpan1\", \"Check the event.currentTarget within a on handler\" );\n\t\tequal( e.delegateTarget, document.body, \"Check the event.delegateTarget within a on handler\" );\n\t\tequal( e.target.nodeName.toUpperCase(), \"A\", \"Check the event.target within a on handler\" );\n\t});\n\n\tjQuery(\"span#liveSpan1 a\").trigger(\"click\");\n\n\tjQuery(\"#body\").off(\"click\", \"span#liveSpan1\");\n\n\t// Work with deep selectors\n\tlivee = 0;\n\n\tfunction clickB() { livee++; }\n\n\tjQuery(\"#body\").on(\"click\", \"#nothiddendiv div\", function(){ livee++; });\n\tjQuery(\"#body\").on(\"click\", \"#nothiddendiv div\", clickB);\n\tjQuery(\"#body\").on(\"mouseover\", \"#nothiddendiv div\", function(){ livee++; });\n\n\tequal( livee, 0, \"No clicks, deep selector.\" );\n\n\tlivee = 0;\n\tjQuery(\"#nothiddendivchild\").trigger(\"click\");\n\tequal( livee, 2, \"Click, deep selector.\" );\n\n\tlivee = 0;\n\tjQuery(\"#nothiddendivchild\").trigger(\"mouseover\");\n\tequal( livee, 1, \"Mouseover, deep selector.\" );\n\n\tjQuery(\"#body\").off(\"mouseover\", \"#nothiddendiv div\");\n\n\tlivee = 0;\n\tjQuery(\"#nothiddendivchild\").trigger(\"click\");\n\tequal( livee, 2, \"Click, deep selector.\" );\n\n\tlivee = 0;\n\tjQuery(\"#nothiddendivchild\").trigger(\"mouseover\");\n\tequal( livee, 0, \"Mouseover, deep selector.\" );\n\n\tjQuery(\"#body\").off(\"click\", \"#nothiddendiv div\", clickB);\n\n\tlivee = 0;\n\tjQuery(\"#nothiddendivchild\").trigger(\"click\");\n\tequal( livee, 1, \"Click, deep selector.\" );\n\n\tjQuery(\"#body\").off(\"click\", \"#nothiddendiv div\");\n});\n\ntest(\"jQuery.off using dispatched jQuery.Event\", function() {\n\texpect(1);\n\n\tvar markup = jQuery(\"<p><a href='#'>target</a></p>\"),\n\t\tcount = 0;\n\tmarkup\n\t\t.on( \"click.name\", \"a\", function( event ) {\n\t\t\tequal( ++count, 1, \"event called once before removal\" );\n\t\t\tjQuery().off( event );\n\t\t})\n\t\t.find(\"a\").trigger(\"click\").trigger(\"click\").end()\n\t\t.remove();\n});\n\ntest( \"delegated event with delegateTarget-relative selector\", function() {\n\texpect(3);\n\tvar markup = jQuery(\"<div><ul><li><a id=\\\"a0\\\"></a><ul id=\\\"ul0\\\"><li class=test><a id=\\\"a0_0\\\"></a></li><li><a id=\\\"a0_1\\\"></a></li></ul></li></ul></div>\").appendTo(\"#qunit-fixture\");\n\n\t// Non-positional selector (#12383)\n\tmarkup.find(\"#ul0\")\n\t\t.on( \"click\", \"div li a\", function() {\n\t\t\tok( false, \"div is ABOVE the delegation point!\" );\n\t\t})\n\t\t.on( \"click\", \"ul a\", function() {\n\t\t\tok( false, \"ul IS the delegation point!\" );\n\t\t})\n\t\t.on( \"click\", \"li.test a\", function() {\n\t\t\tok( true, \"li.test is below the delegation point.\" );\n\t\t})\n\t\t.find(\"#a0_0\").trigger(\"click\").end()\n\t\t.off(\"click\");\n\n\t// Positional selector (#11315)\n\tmarkup.find(\"ul\").eq(0)\n\t\t.on( \"click\", \">li>a\", function() {\n\t\t\tok( this.id === \"a0\", \"child li was clicked\" );\n\t\t})\n\t\t.find(\"#ul0\")\n\t\t\t.on( \"click\", \"li:first>a\", function() {\n\t\t\t\tok( this.id === \"a0_0\" , \"first li under #u10 was clicked\" );\n\t\t\t})\n\t\t.end()\n\t\t.find(\"a\").trigger(\"click\").end()\n\t\t.find(\"#ul0\").off();\n\n\tmarkup.remove();\n});\n\ntest( \"delegated event with selector matching Object.prototype property (#13203)\", function() {\n\texpect(1);\n\n\tvar matched = 0;\n\n\tjQuery(\"#foo\").on( \"click\", \"toString\", function() {\n\t\tmatched++;\n\t});\n\n\tjQuery(\"#anchor2\").trigger(\"click\");\n\n\tequal( matched, 0, \"Nothing matched 'toString'\" );\n});\n\ntest(\"stopPropagation() stops directly-bound events on delegated target\", function() {\n\texpect(1);\n\n\tvar markup = jQuery(\"<div><p><a href=\\\"#\\\">target</a></p></div>\");\n\tmarkup\n\t\t.on( \"click\", function() {\n\t\t\tok( false, \"directly-bound event on delegate target was called\" );\n\t\t})\n\t\t.on( \"click\", \"a\", function( e ) {\n\t\t\te.stopPropagation();\n\t\t\tok( true, \"delegated handler was called\" );\n\t\t})\n\t\t.find(\"a\").trigger(\"click\").end()\n\t\t.remove();\n});\n\ntest(\"off all bound delegated events\", function(){\n\texpect(2);\n\n\tvar count = 0,\n\t\tclicks = 0,\n\t\tdiv = jQuery(\"#body\");\n\n\tdiv.on( \"click submit\", \"div#nothiddendivchild\", function(){ count++; } );\n\tdiv.on( \"click\", function(){ clicks++; } );\n\tdiv.off( undefined, \"**\" );\n\n\tjQuery(\"div#nothiddendivchild\").trigger(\"click\");\n\tjQuery(\"div#nothiddendivchild\").trigger(\"submit\");\n\n\tequal( count, 0, \"Make sure no events were triggered.\" );\n\n\tdiv.trigger(\"click\");\n\tequal( clicks, 2, \"Make sure delegated and directly bound event occurred.\" );\n\tdiv.off(\"click\");\n});\n\ntest(\"on with multiple delegated events\", function(){\n\texpect(1);\n\n\tvar count = 0,\n\t\tdiv = jQuery(\"#body\");\n\n\tdiv.on(\"click submit\", \"div#nothiddendivchild\", function(){ count++; });\n\n\tjQuery(\"div#nothiddendivchild\").trigger(\"click\");\n\tjQuery(\"div#nothiddendivchild\").trigger(\"submit\");\n\n\tequal( count, 2, \"Make sure both the click and submit were triggered.\" );\n\n\tjQuery(\"#body\").off( undefined, \"**\" );\n});\n\ntest(\"delegated on with change\", function(){\n\texpect(8);\n\n\tvar select, checkbox, checkboxFunction,\n\t\ttext, textChange, oldTextVal,\n\t\tpassword, passwordChange, oldPasswordVal,\n\t\tselectChange = 0,\n\t\tcheckboxChange = 0;\n\n\tselect = jQuery(\"select[name='S1']\");\n\tjQuery(\"#body\").on(\"change\", \"select[name='S1']\", function() {\n\t\tselectChange++;\n\t});\n\n\tcheckbox = jQuery(\"#check2\");\n\tcheckboxFunction = function(){\n\t\tcheckboxChange++;\n\t};\n\tjQuery(\"#body\").on(\"change\", \"#check2\", checkboxFunction);\n\n\t// test click on select\n\n\t// second click that changed it\n\tselectChange = 0;\n\tselect[0].selectedIndex = select[0].selectedIndex ? 0 : 1;\n\tselect.trigger(\"change\");\n\tequal( selectChange, 1, \"Change on click.\" );\n\n\t// test keys on select\n\tselectChange = 0;\n\tselect[0].selectedIndex = select[0].selectedIndex ? 0 : 1;\n\tselect.trigger(\"change\");\n\tequal( selectChange, 1, \"Change on keyup.\" );\n\n\t// test click on checkbox\n\tcheckbox.trigger(\"change\");\n\tequal( checkboxChange, 1, \"Change on checkbox.\" );\n\n\t// test blur/focus on text\n\ttext = jQuery(\"#name\");\n\ttextChange = 0;\n\toldTextVal = text.val();\n\n\tjQuery(\"#body\").on(\"change\", \"#name\", function() {\n\t\ttextChange++;\n\t});\n\n\ttext.val(oldTextVal+\"foo\");\n\ttext.trigger(\"change\");\n\tequal( textChange, 1, \"Change on text input.\" );\n\n\ttext.val(oldTextVal);\n\tjQuery(\"#body\").off(\"change\", \"#name\");\n\n\t// test blur/focus on password\n\tpassword = jQuery(\"#name\");\n\tpasswordChange = 0;\n\toldPasswordVal = password.val();\n\tjQuery(\"#body\").on(\"change\", \"#name\", function() {\n\t\tpasswordChange++;\n\t});\n\n\tpassword.val(oldPasswordVal + \"foo\");\n\tpassword.trigger(\"change\");\n\tequal( passwordChange, 1, \"Change on password input.\" );\n\n\tpassword.val(oldPasswordVal);\n\tjQuery(\"#body\").off(\"change\", \"#name\");\n\n\t// make sure die works\n\n\t// die all changes\n\tselectChange = 0;\n\tjQuery(\"#body\").off(\"change\", \"select[name='S1']\");\n\tselect[0].selectedIndex = select[0].selectedIndex ? 0 : 1;\n\tselect.trigger(\"change\");\n\tequal( selectChange, 0, \"Die on click works.\" );\n\n\tselectChange = 0;\n\tselect[0].selectedIndex = select[0].selectedIndex ? 0 : 1;\n\tselect.trigger(\"change\");\n\tequal( selectChange, 0, \"Die on keyup works.\" );\n\n\t// die specific checkbox\n\tjQuery(\"#body\").off(\"change\", \"#check2\", checkboxFunction);\n\tcheckbox.trigger(\"change\");\n\tequal( checkboxChange, 1, \"Die on checkbox.\" );\n});\n\ntest(\"delegated on with submit\", function() {\n\texpect( 2 );\n\n\tvar count1 = 0, count2 = 0;\n\n\tjQuery(\"#body\").on(\"submit\", \"#testForm\", function(ev) {\n\t\tcount1++;\n\t\tev.preventDefault();\n\t});\n\n\tjQuery(document).on(\"submit\", \"body\", function(ev) {\n\t\tcount2++;\n\t\tev.preventDefault();\n\t});\n\n\tjQuery(\"#testForm input[name=sub1]\").trigger(\"submit\");\n\tequal( count1, 1, \"Verify form submit.\" );\n\tequal( count2, 1, \"Verify body submit.\" );\n\n\tjQuery(\"#body\").off( undefined, \"**\" );\n\tjQuery(document).off( undefined, \"**\" );\n});\n\ntest(\"delegated off() with only namespaces\", function() {\n\texpect(2);\n\n\tvar $delegate = jQuery(\"#liveHandlerOrder\"),\n\t\tcount = 0;\n\n\t$delegate.on(\"click.ns\", \"a\", function() {\n\t\tcount++;\n\t});\n\n\tjQuery(\"a\", $delegate).eq(0).trigger(\"click.ns\");\n\n\tequal( count, 1, \"delegated click.ns\");\n\n\t$delegate.off( \".ns\", \"**\" );\n\n\tjQuery(\"a\", $delegate).eq(1).trigger(\"click.ns\");\n\n\tequal( count, 1, \"no more .ns after off\");\n});\n\ntest(\"Non DOM element events\", function() {\n\texpect(1);\n\n\tvar o = {};\n\n\tjQuery(o).on(\"nonelementobj\", function() {\n\t\tok( true, \"Event on non-DOM object triggered\" );\n\t});\n\n\tjQuery(o).trigger(\"nonelementobj\");\n});\n\ntest(\"inline handler returning false stops default\", function() {\n\texpect(1);\n\n\tvar markup = jQuery(\"<div><a href=\\\"#\\\" onclick=\\\"return false\\\">x</a></div>\");\n\tmarkup.on( \"click\", function(e) {\n\t\tok( e.isDefaultPrevented(), \"inline handler prevented default\");\n\t\treturn false;\n\t});\n\tmarkup.find(\"a\").trigger(\"click\");\n\tmarkup.off(\"click\");\n});\n\ntest(\"window resize\", function() {\n\texpect(2);\n\n\tjQuery(window).off();\n\n\tjQuery(window).on( \"resize\", function(){\n\t\tok( true, \"Resize event fired.\" );\n\t}).trigger(\"resize\").off(\"resize\");\n\n\tok( !jQuery._data(window, \"events\"), \"Make sure all the events are gone.\" );\n});\n\ntest(\"focusin bubbles\", function() {\n\texpect(2);\n\n\tvar input = jQuery( \"<input type='text' />\" ).prependTo( \"body\" ),\n\t\torder = 0;\n\n\t// focus the element so DOM focus won't fire\n\tinput[0].focus();\n\n\tjQuery( \"body\" ).on( \"focusin.focusinBubblesTest\", function(){\n\t\tequal( 1, order++, \"focusin on the body second\" );\n\t});\n\n\tinput.on( \"focusin.focusinBubblesTest\", function(){\n\t\tequal( 0, order++, \"focusin on the element first\" );\n\t});\n\n// Removed since DOM focus is unreliable on test swarm\n\t// DOM focus method\n//\tinput[0].focus();\n\n\t// To make the next focus test work, we need to take focus off the input.\n\t// This will fire another focusin event, so set order to reflect that.\n//\torder = 1;\n//\tjQuery(\"#text1\")[0].focus();\n\n\t// jQuery trigger, which calls DOM focus\n\torder = 0;\n\tinput.trigger( \"focus\" );\n\n\tinput.remove();\n\tjQuery( \"body\" ).off( \"focusin.focusinBubblesTest\" );\n});\n\ntest(\"custom events with colons (#3533, #8272)\", function() {\n\texpect(1);\n\n\tvar tab = jQuery(\"<table><tr><td>trigger</td></tr></table>\").appendTo(\"body\");\n\ttry {\n\t\ttab.trigger(\"back:forth\");\n\t\tok( true, \"colon events don't throw\" );\n\t} catch ( e ) {\n\t\tok( false, \"colon events die\" );\n\t}\n\ttab.remove();\n\n});\n\ntest(\".on and .off\", function() {\n\texpect(9);\n\tvar counter, mixfn, data,\n\t\t$onandoff = jQuery(\"<div id=\\\"onandoff\\\"><p>on<b>and</b>off</p><div>worked<em>or</em>borked?</div></div>\").appendTo(\"body\");\n\n\t// Simple case\n\tjQuery( \"#onandoff\" )\n\t\t.on( \"whip\", function() {\n\t\t\tok( true, \"whipped it good\" );\n\t\t})\n\t\t.trigger( \"whip\" )\n\t\t.off();\n\n\t// Direct events only\n\tcounter = 0;\n\tjQuery( \"#onandoff b\" )\n\t\t.on( \"click\", 5, function( e, trig ) {\n\t\t\tcounter += e.data + (trig || 9);\t// twice, 5+9+5+17=36\n\t\t})\n\t\t.one( \"click\", 7, function( e, trig ) {\n\t\t\tcounter += e.data + (trig || 11);\t// once, 7+11=18\n\t\t})\n\t\t.trigger(\"click\")\n\t\t.trigger( \"click\", 17 )\n\t\t.off( \"click\" );\n\tequal( counter, 54, \"direct event bindings with data\" );\n\n\t// Delegated events only\n\tcounter = 0;\n\tjQuery( \"#onandoff\" )\n\t\t.on( \"click\", \"em\", 5, function( e, trig ) {\n\t\t\tcounter += e.data + (trig || 9);\t// twice, 5+9+5+17=36\n\t\t})\n\t\t.one( \"click\", \"em\", 7, function( e, trig ) {\n\t\t\tcounter += e.data + (trig || 11);\t// once, 7+11=18\n\t\t})\n\t\t.find(\"em\")\n\t\t\t.trigger(\"click\")\n\t\t\t.trigger( \"click\", 17 )\n\t\t.end()\n\t\t.off( \"click\", \"em\" );\n\tequal( counter, 54, \"delegated event bindings with data\" );\n\n\n\t// Mixed event bindings and types\n\tcounter = 0;\n\tmixfn = function(e, trig) {\n\t\tcounter += (e.data || 0) + (trig || 1);\n\t};\n\tjQuery( \"#onandoff\" )\n\t\t.on( \" click  clack cluck \", \"em\", 2, mixfn )\n\t\t.on( \"cluck\", \"b\", 7, mixfn )\n\t\t.on( \"cluck\", mixfn )\n\t\t.trigger( \"what!\" )\n\t\t.each( function() {\n\t\t\tequal( counter, 0, \"nothing triggered yet\" );\n\t\t})\n\t\t.find( \"em\" )\n\t\t\t.one( \"cluck\", 3, mixfn )\n\t\t\t.trigger( \"cluck\", 8 )\t\t\t// 3+8 2+8 + 0+8 = 29\n\t\t\t.off()\n\t\t\t.trigger( \"cluck\", 9 )\t\t\t// 2+9 + 0+9 = 20\n\t\t.end()\n\t\t.each( function() {\n\t\t\tequal( counter, 49, \"after triggering em element\" );\n\t\t})\n\t\t.off( \"cluck\", function(){} )\t\t// shouldn't remove anything\n\t\t.trigger( \"cluck\", 2 )\t\t\t\t// 0+2 = 2\n\t\t.each( function() {\n\t\t\tequal( counter, 51, \"after triggering #onandoff cluck\" );\n\t\t})\n\t\t.find( \"b\" )\n\t\t\t.on( \"click\", 95, mixfn )\n\t\t\t.on( \"clack\", \"p\", 97, mixfn )\n\t\t\t.one( \"cluck\", 3, mixfn )\n\t\t\t.trigger( \"quack\", 19 )\t\t\t// 0\n\t\t\t.off( \"click clack cluck\" )\n\t\t.end()\n\t\t.each( function() {\n\t\t\tequal( counter, 51, \"after triggering b\" );\n\t\t})\n\t\t.trigger( \"cluck\", 3 )\t\t\t\t// 0+3 = 3\n\t\t.off( \"clack\", \"em\", mixfn )\n\t\t.find( \"em\" )\n\t\t\t.trigger( \"clack\" )\t\t\t\t// 0\n\t\t.end()\n\t\t.each( function() {\n\t\t\tequal( counter, 54, \"final triggers\" );\n\t\t})\n\t\t.off( \"click cluck\" );\n\n\t// We should have removed all the event handlers ... kinda hacky way to check this\n\tdata = jQuery.data[ jQuery( \"#onandoff\" )[0].expando ] || {};\n\tequal( data[\"events\"], undefined, \"no events left\" );\n\n\t$onandoff.remove();\n});\n\ntest(\"special on name mapping\", function() {\n\texpect( 7 );\n\n\tjQuery.event.special[\"slap\"] = {\n\t\tbindType: \"click\",\n\t\tdelegateType: \"swing\",\n\t\thandle: function( event ) {\n\t\t\tequal( event.handleObj.origType, \"slap\", \"slapped your mammy, \" + event.type );\n\t\t}\n\t};\n\n\tvar comeback = function( event ) {\n\t\tok( true, \"event \" + event.type + \" triggered\" );\n\t};\n\n\tjQuery(\"<div><button id=\\\"mammy\\\">Are We Not Men?</button></div>\")\n\t\t.on( \"slap\", \"button\", jQuery.noop )\n\t\t.on( \"swing\", \"button\", comeback )\n\t\t.find( \"button\" )\n\t\t\t.on( \"slap\", jQuery.noop )\n\t\t\t.on( \"click\", comeback )\n\t\t\t.trigger( \"click\" )\t\t// bindType-slap and click\n\t\t\t.off( \"slap\" )\n\t\t\t.trigger( \"click\" )\t\t// click\n\t\t\t.off( \"click\" )\n\t\t\t.trigger( \"swing\" )\t\t// delegateType-slap and swing\n\t\t.end()\n\t\t.off( \"slap swing\", \"button\" )\n\t\t.find( \"button\" )\t\t\t// everything should be gone\n\t\t\t.trigger( \"slap\" )\n\t\t\t.trigger( \"click\" )\n\t\t\t.trigger( \"swing\" )\n\t\t.end()\n\t\t.remove();\n\tdelete jQuery.event.special[\"slap\"];\n\n\tjQuery.event.special[\"gutfeeling\"] = {\n\t\tbindType: \"click\",\n\t\tdelegateType: \"click\",\n\t\thandle: function( event ) {\n\t\t\tequal( event.handleObj.origType, \"gutfeeling\", \"got a gutfeeling\" );\n\t\t\t// Need to call the handler since .one() uses it to unbind\n\t\t\treturn event.handleObj.handler.call( this , event );\n\t\t}\n\t};\n\n\t// Ensure a special event isn't removed by its mapped type\n\tjQuery( \"<p>Gut Feeling</p>\" )\n\t\t.on( \"click\", jQuery.noop )\n\t\t.on( \"gutfeeling\", jQuery.noop )\n\t\t.off( \"click\" )\n\t\t.trigger( \"gutfeeling\" )\n\t\t.remove();\n\n\t// Ensure special events are removed when only a namespace is provided\n\tjQuery( \"<p>Gut Feeling</p>\" )\n\t\t.on( \"gutfeeling.Devo\", jQuery.noop )\n\t\t.off( \".Devo\" )\n\t\t.trigger( \"gutfeeling\" )\n\t\t.remove();\n\n\t// Ensure .one() events are removed after their maiden voyage\n\tjQuery( \"<p>Gut Feeling</p>\" )\n\t\t.one( \"gutfeeling\", jQuery.noop )\n\t\t.trigger( \"gutfeeling\" )\t// This one should\n\t\t.trigger( \"gutfeeling\" )\t// This one should not\n\t\t.remove();\n\n\tdelete jQuery.event.special[\"gutfeeling\"];\n});\n\ntest(\".on and .off, selective mixed removal (#10705)\", function() {\n\texpect(7);\n\n\tvar timingx = function( e ) {\n\t\tok( true, \"triggered \" + e.type );\n\t};\n\n\tjQuery( \"<p>Strange Pursuit</p>\" )\n\t\t.on( \"click\", timingx )\n\t\t.on( \"click.duty\", timingx )\n\t\t.on( \"click.now\", timingx )\n\t\t.on( \"devo\", timingx )\n\t\t.on( \"future\", timingx )\n\t\t.trigger( \"click\" )\t\t// 3\n\t\t.trigger( \"devo\" )\t\t// 1\n\t\t.off( \".duty devo \" )\t// trailing space\n\t\t.trigger( \"future\" )\t// 1\n\t\t.trigger( \"click\" )\t\t// 2\n\t\t.off( \"future click\" )\n\t\t.trigger( \"click\" );\t// 0\n});\n\ntest(\".on( event-map, null-selector, data ) #11130\", function() {\n\n\texpect( 1 );\n\n\tvar $p = jQuery(\"<p>Strange Pursuit</p>\"),\n\t\tdata = \"bar\",\n\t\tmap = {\n\t\t\t\"foo\": function( event ) {\n\t\t\t\tequal( event.data, \"bar\", \"event.data correctly relayed with null selector\" );\n\t\t\t\t$p.remove();\n\t\t\t}\n\t\t};\n\n\t$p.on( map, null, data ).trigger(\"foo\");\n});\n\ntest(\"clone() delegated events (#11076)\", function() {\n\texpect(3);\n\n\tvar counter = { \"center\": 0, \"fold\": 0, \"centerfold\": 0 },\n\t\tclicked = function() {\n\t\t\tcounter[ jQuery(this).text().replace(/\\s+/, \"\") ]++;\n\t\t},\n\t\ttable =\n\t\t\tjQuery( \"<table><tr><td>center</td><td>fold</td></tr></table>\" )\n\t\t\t.on( \"click\", \"tr\", clicked )\n\t\t\t.on( \"click\", \"td:first-child\", clicked )\n\t\t\t.on( \"click\", \"td:last-child\", clicked ),\n\t\tclone = table.clone( true );\n\n\tclone.find(\"td\").trigger(\"click\");\n\tequal( counter[\"center\"], 1, \"first child\" );\n\tequal( counter[\"fold\"], 1, \"last child\" );\n\tequal( counter[\"centerfold\"], 2, \"all children\" );\n\n\ttable.remove();\n\tclone.remove();\n});\n\ntest(\"checkbox state (#3827)\", function() {\n\texpect( 9 );\n\n\tvar markup = jQuery(\"<div><input type=checkbox><div>\").appendTo(\"#qunit-fixture\"),\n\t\tcb = markup.find(\"input\")[0];\n\n\tjQuery(cb).on( \"click\", function(){\n\t\tequal( this.checked, false, \"just-clicked checkbox is not checked\" );\n\t});\n\tmarkup.on( \"click\", function(){\n\t\tequal( cb.checked, false, \"checkbox is not checked in bubbled event\" );\n\t});\n\n\t// Native click\n\tcb.checked = true;\n\tequal( cb.checked, true, \"native - checkbox is initially checked\" );\n\tcb.click();\n\tequal( cb.checked, false, \"native - checkbox is no longer checked\" );\n\n\t// jQuery click\n\tcb.checked = true;\n\tequal( cb.checked, true, \"jQuery - checkbox is initially checked\" );\n\tjQuery( cb ).trigger(\"click\");\n\tequal( cb.checked, false, \"jQuery - checkbox is no longer checked\" );\n\n\t// Handlers only; checkbox state remains false\n\tjQuery( cb ).triggerHandler( \"click\" );\n});\n\ntest(\"focus-blur order (#12868)\", function() {\n\texpect( 5 );\n\n\tvar order,\n\t\t$text = jQuery(\"#text1\"),\n\t\t$radio = jQuery(\"#radio1\").trigger(\"focus\");\n\n\t// IE6-10 fire focus/blur events asynchronously; this is the resulting mess.\n\t// IE's browser window must be topmost for this to work properly!!\n\tstop();\n\t$radio[0].focus();\n\n\tsetTimeout( function() {\n\n\t\t$text\n\t\t\t.on( \"focus\", function(){\n\t\t\t\tequal( order++, 1, \"text focus\" );\n\t\t\t})\n\t\t\t.on( \"blur\", function(){\n\t\t\t\tequal( order++, 0, \"text blur\" );\n\t\t\t});\n\t\t$radio\n\t\t\t.on( \"focus\", function(){\n\t\t\t\tequal( order++, 1, \"radio focus\" );\n\t\t\t})\n\t\t\t.on( \"blur\", function(){\n\t\t\t\tequal( order++, 0, \"radio blur\" );\n\t\t\t});\n\n\t\t// Enabled input getting focus\n\t\torder = 0;\n\t\tequal( document.activeElement, $radio[0], \"radio has focus\" );\n\t\t$text.trigger(\"focus\");\n\t\tsetTimeout( function() {\n\t\t\tequal( document.activeElement, $text[0], \"text has focus\" );\n\n\t\t\t// Run handlers without native method on an input\n\t\t\torder = 1;\n\t\t\t$radio.triggerHandler( \"focus\" );\n\t\t\tstart();\n\t\t}, 50 );\n\t}, 50 );\n});\n\ntest(\"hover event no longer special since 1.9\", function() {\n\texpect( 1 );\n\n\tjQuery(\"<div>craft</div>\")\n\t\t.on( \"hover\", function( e ) {\n\t\t\tequal( e.type, \"hover\", \"I am hovering!\" );\n\t\t})\n\t\t.trigger(\"hover\")\n\t\t.off(\"hover\");\n});\n\ntest(\"fixHooks extensions\", function() {\n\texpect( 2 );\n\n\t// IE requires focusable elements to be visible, so append to body\n\tvar $fixture = jQuery( \"<input type='text' id='hook-fixture' />\" ).appendTo( \"body\" ),\n\t\tsaved = jQuery.event.fixHooks.click;\n\n\t// Ensure the property doesn't exist\n\t$fixture.on( \"click\", function( event ) {\n\t\tok( !(\"blurrinessLevel\" in event), \"event.blurrinessLevel does not exist\" );\n\t});\n\tfireNative( $fixture[0], \"click\" );\n\t$fixture.off( \"click\" );\n\n\tjQuery.event.fixHooks.click = {\n\t\tfilter: function( event ) {\n\t\t\tevent.blurrinessLevel = 42;\n\t\t\treturn event;\n\t\t}\n\t};\n\n\t// Trigger a native click and ensure the property is set\n\t$fixture.on( \"click\", function( event ) {\n\t\tequal( event.blurrinessLevel, 42, \"event.blurrinessLevel was set\" );\n\t});\n\tfireNative( $fixture[0], \"click\" );\n\n\tdelete jQuery.event.fixHooks.click;\n\t$fixture.off( \"click\" ).remove();\n\tjQuery.event.fixHooks.click = saved;\n});\n\ntestIframeWithCallback( \"jQuery.ready promise\", \"event/promiseReady.html\", function( isOk ) {\n\texpect(1);\n\tok( isOk, \"$.when( $.ready ) works\" );\n});\n\ntestIframeWithCallback( \"Focusing iframe element\", \"event/focusElem.html\", function( isOk ) {\n\texpect(1);\n\tok( isOk, \"Focused an element in an iframe\" );\n});\n\n// need PHP here to make the incepted IFRAME hang\nif ( hasPHP ) {\n\ttestIframeWithCallback( \"jQuery.ready synchronous load with long loading subresources\", \"event/syncReady.html\", function( isOk ) {\n\t\texpect(1);\n\t\tok( isOk, \"jQuery loaded synchronously fires ready when the DOM can truly be interacted with\" );\n\t});\n}\n\n(function(){\n\t// This code must be run before DOM ready!\n\tvar notYetReady, noEarlyExecution,\n\t\torder = [],\n\t\targs = {};\n\n\tnotYetReady = !jQuery.isReady;\n\n\ttest(\"jQuery.isReady\", function() {\n\t\texpect(2);\n\n\t\tequal(notYetReady, true, \"jQuery.isReady should not be true before DOM ready\");\n\t\tequal(jQuery.isReady, true, \"jQuery.isReady should be true once DOM is ready\");\n\t});\n\n\t// Create an event handler.\n\tfunction makeHandler( testId ) {\n\t\t// When returned function is executed, push testId onto `order` array\n\t\t// to ensure execution order. Also, store event handler arg to ensure\n\t\t// the correct arg is being passed into the event handler.\n\t\treturn function( arg ) {\n\t\t\torder.push(testId);\n\t\t\targs[testId] = arg;\n\t\t};\n\t}\n\n\t// Bind to the ready event in every possible way.\n\tjQuery(makeHandler(\"a\"));\n\tjQuery(document).ready(makeHandler(\"b\"));\n\tjQuery(document).on(\"ready.readytest\", makeHandler(\"c\"));\n\n\t// Do it twice, just to be sure.\n\tjQuery(makeHandler(\"d\"));\n\tjQuery(document).ready(makeHandler(\"e\"));\n\tjQuery(document).on(\"ready.readytest\", makeHandler(\"f\"));\n\n\tnoEarlyExecution = order.length === 0;\n\n\t// This assumes that QUnit tests are run on DOM ready!\n\ttest(\"jQuery ready\", function() {\n\t\texpect(10);\n\n\t\tok(noEarlyExecution, \"Handlers bound to DOM ready should not execute before DOM ready\");\n\n\t\t// Ensure execution order.\n\t\tdeepEqual(order, [\"a\", \"b\", \"d\", \"e\", \"c\", \"f\"], \"Bound DOM ready handlers should execute in on-order, but those bound with jQuery(document).on( 'ready', fn ) will always execute last\");\n\n\t\t// Ensure handler argument is correct.\n\t\tequal(args[\"a\"], jQuery, \"Argument passed to fn in jQuery( fn ) should be jQuery\");\n\t\tequal(args[\"b\"], jQuery, \"Argument passed to fn in jQuery(document).ready( fn ) should be jQuery\");\n\t\tok(args[\"c\"] instanceof jQuery.Event, \"Argument passed to fn in jQuery(document).on( 'ready', fn ) should be an event object\");\n\n\t\torder = [];\n\n\t\t// Now that the ready event has fired, again bind to the ready event\n\t\t// in every possible way. These event handlers should execute immediately.\n\t\tjQuery(makeHandler(\"g\"));\n\t\tequal(order.pop(), \"g\", \"Event handler should execute immediately\");\n\t\tequal(args[\"g\"], jQuery, \"Argument passed to fn in jQuery( fn ) should be jQuery\");\n\n\t\tjQuery(document).ready(makeHandler(\"h\"));\n\t\tequal(order.pop(), \"h\", \"Event handler should execute immediately\");\n\t\tequal(args[\"h\"], jQuery, \"Argument passed to fn in jQuery(document).ready( fn ) should be jQuery\");\n\n\t\tjQuery(document).on(\"ready.readytest\", makeHandler(\"never\"));\n\t\tequal(order.length, 0, \"Event handler should never execute since DOM ready has already passed\");\n\n\t\t// Cleanup.\n\t\tjQuery(document).off(\"ready.readytest\");\n\t});\n\n})();\n\ntest(\"change handler should be detached from element\", function() {\n\texpect( 2 );\n\n\tvar $fixture = jQuery( \"<input type='text' id='change-ie-leak' />\" ).appendTo( \"body\" ),\n\t\toriginRemoveEvent = jQuery.removeEvent,\n\t\twrapperRemoveEvent =  function(elem, type, handle){\n\t\t\tequal(\"change\", type, \"Event handler for 'change' event should be removed\");\n\t\t\tequal(\"change-ie-leak\", jQuery(elem).attr(\"id\"), \"Event handler for 'change' event should be removed from appropriate element\");\n\t\t\toriginRemoveEvent(elem, type, handle);\n\t\t};\n\n\tjQuery.removeEvent = wrapperRemoveEvent ;\n\n\t$fixture.on( \"change\", function() {});\n\t$fixture.off( \"change\" );\n\n\t$fixture.remove();\n\n\tjQuery.removeEvent = originRemoveEvent;\n});\n\nasyncTest(\"trigger click on checkbox, fires change event\", function() {\n\texpect(1);\n\n\tvar check = jQuery(\"#check2\");\n\n\tcheck.on( \"change\", function() {\n\t\t// get it?\n\t\tcheck.off(\"change\");\n\t\tok( true, \"Change event fired as a result of triggered click\" );\n\t\tstart();\n\t}).trigger(\"click\");\n});\n\ntest( \"Namespace preserved when passed an Event (#12739)\", function() {\n\texpect( 4 );\n\n\tvar markup = jQuery(\n\t\t\t\"<div id='parent'><div id='child'></div></div>\"\n\t\t),\n\t\ttriggered = 0,\n\t\tfooEvent;\n\n\tmarkup.find(\"div\")\n\t\t.addBack()\n\t\t.on( \"foo.bar\", function( e ) {\n\t\t\tif ( !e.handled ) {\n\t\t\t\ttriggered++;\n\t\t\t\te.handled = true;\n\t\t\t\tequal( e.namespace, \"bar\", \"namespace is bar\" );\n\t\t\t\tjQuery( e.target ).find(\"div\").each(function() {\n\t\t\t\t\tjQuery( this ).triggerHandler( e );\n\t\t\t\t});\n\t\t\t}\n\t\t})\n\t\t.on( \"foo.bar2\", function() {\n\t\t\tok( false, \"foo.bar2 called on trigger \" + triggered + \" id \" + this.id );\n\t\t});\n\n\tmarkup.trigger(\"foo.bar\");\n\tmarkup.trigger( jQuery.Event(\"foo.bar\") );\n\tfooEvent = jQuery.Event(\"foo\");\n\tfooEvent.namespace = \"bar\";\n\tmarkup.trigger( fooEvent );\n\tmarkup.remove();\n\n\tequal( triggered, 3, \"foo.bar triggered\" );\n});\n\ntest( \"make sure events cloned correctly\", 18, function() {\n\tvar clone,\n\t\tfixture = jQuery(\"#qunit-fixture\"),\n\t\tcheckbox = jQuery(\"#check1\"),\n\t\tp = jQuery(\"#firstp\");\n\n\tfixture.on( \"click change\", function( event, result ) {\n\t\tok( result,  event.type + \" on original element is fired\" );\n\n\t}).on( \"click\", \"#firstp\", function( event, result ) {\n\t\tok( result, \"Click on original child element though delegation is fired\" );\n\n\t}).on( \"change\", \"#check1\", function( event, result ) {\n\t\tok( result, \"Change on original child element though delegation is fired\" );\n\t});\n\n\tp.on(\"click\", function() {\n\t\tok( true, \"Click on original child element is fired\" );\n\t});\n\n\tcheckbox.on(\"change\", function() {\n\t\tok( true, \"Change on original child element is fired\" );\n\t});\n\n\tfixture.clone().trigger(\"click\").trigger(\"change\"); // 0 events should be fired\n\n\tclone = fixture.clone( true );\n\n\tclone.find(\"p\").eq(0).trigger( \"click\", true ); // 3 events should fire\n\tclone.find(\"#check1\").trigger( \"change\", true ); // 3 events should fire\n\tclone.remove();\n\n\tclone = fixture.clone( true, true );\n\tclone.find(\"p\").eq(0).trigger( \"click\", true ); // 3 events should fire\n\tclone.find(\"#check1\").trigger( \"change\", true ); // 3 events should fire\n\n\tfixture.off();\n\tp.off();\n\tcheckbox.off();\n\n\tp.trigger(\"click\"); // 0 should be fired\n\tcheckbox.trigger(\"change\"); // 0 should be fired\n\n\tclone.find(\"p\").eq(0).trigger( \"click\", true );  // 3 events should fire\n\tclone.find(\"#check1\").trigger( \"change\", true ); // 3 events should fire\n\tclone.remove();\n\n\tclone.find(\"p\").eq(0).trigger(\"click\");  // 0 should be fired\n\tclone.find(\"#check1\").trigger(\"change\"); // 0 events should fire\n});\n\ntest( \"Check order of focusin/focusout events\", 2, function() {\n\tvar focus, blur,\n\t\tinput = jQuery(\"#name\");\n\n\tinput.on(\"focus\", function() {\n\t\tfocus = true;\n\n\t}).on(\"focusin\", function() {\n\t\tok( !focus, \"Focusin event should fire before focus does\" );\n\n\t}).on(\"blur\", function() {\n\t\tblur = true;\n\n\t}).on(\"focusout\", function() {\n\t\tok( !blur, \"Focusout event should fire before blur does\" );\n\t});\n\n\t// gain focus\n\tinput.trigger(\"focus\");\n\n\t// then lose it\n\tjQuery(\"#search\").trigger(\"focus\");\n\n\t// cleanup\n\tinput.off();\n});\n\ntest( \"String.prototype.namespace does not cause trigger() to throw (#13360)\", function() {\n\texpect( 1 );\n\tvar errored = false;\n\n\tString.prototype.namespace = function() {};\n\n\ttry {\n\t\tjQuery(\"<p>\").trigger(\"foo.bar\");\n\t} catch( e ) {\n\t\terrored = true;\n\t}\n\tequal( errored, false, \"trigger() did not throw exception\" );\n\tdelete String.prototype.namespace;\n});\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/jquery/test/unit/exports.js",
    "content": "module(\"exports\", { teardown: moduleTeardown });\n\ntest(\"amdModule\", function() {\n\texpect(1);\n\n\tequal( jQuery, amdDefined, \"Make sure defined module matches jQuery\" );\n});\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/jquery/test/unit/manipulation.js",
    "content": "module( \"manipulation\", {\n\tteardown: moduleTeardown\n});\n\n// Ensure that an extended Array prototype doesn't break jQuery\nArray.prototype.arrayProtoFn = function() {\n\tthrow(\"arrayProtoFn should not be called\");\n};\n\nfunction manipulationBareObj( value ) {\n\treturn value;\n}\n\nfunction manipulationFunctionReturningObj( value ) {\n\treturn function() {\n\t\treturn value;\n\t};\n}\n\n/*\n\t======== local reference =======\n\tmanipulationBareObj and manipulationFunctionReturningObj can be used to test passing functions to setters\n\tSee testVal below for an example\n\n\tbareObj( value );\n\t\tThis function returns whatever value is passed in\n\n\tfunctionReturningObj( value );\n\t\tReturns a function that returns the value\n*/\n\ntest( \"text()\", function() {\n\n\texpect( 5 );\n\n\tvar expected, frag, $newLineTest;\n\n\texpected = \"This link has class=\\\"blog\\\": Simon Willison's Weblog\";\n\tequal( jQuery(\"#sap\").text(), expected, \"Check for merged text of more then one element.\" );\n\n\t// Check serialization of text values\n\tequal( jQuery(document.createTextNode(\"foo\")).text(), \"foo\", \"Text node was retrieved from .text().\" );\n\tnotEqual( jQuery(document).text(), \"\", \"Retrieving text for the document retrieves all text (#10724).\" );\n\n\t// Retrieve from document fragments #10864\n\tfrag = document.createDocumentFragment();\n\tfrag.appendChild( document.createTextNode(\"foo\") );\n\n\tequal( jQuery(frag).text(), \"foo\", \"Document Fragment Text node was retrieved from .text().\" );\n\n\t$newLineTest = jQuery(\"<div>test<br/>testy</div>\").appendTo(\"#moretests\");\n\t$newLineTest.find(\"br\").replaceWith(\"\\n\");\n\tequal( $newLineTest.text(), \"test\\ntesty\", \"text() does not remove new lines (#11153)\" );\n\n\t$newLineTest.remove();\n});\n\ntest( \"text(undefined)\", function() {\n\n\texpect( 1 );\n\n\tequal( jQuery(\"#foo\").text(\"<div\").text(undefined)[ 0 ].innerHTML, \"&lt;div\", \".text(undefined) is chainable (#5571)\" );\n});\n\nfunction testText( valueObj ) {\n\n\texpect( 4 );\n\n\tvar val, j;\n\n\tval = valueObj(\"<div><b>Hello</b> cruel world!</div>\");\n\tequal( jQuery(\"#foo\").text(val)[ 0 ].innerHTML.replace(/>/g, \"&gt;\"), \"&lt;div&gt;&lt;b&gt;Hello&lt;/b&gt; cruel world!&lt;/div&gt;\", \"Check escaped text\" );\n\n\t// using contents will get comments regular, text, and comment nodes\n\tj = jQuery(\"#nonnodes\").contents();\n\tj.text( valueObj(\"hi!\") );\n\tequal( jQuery( j[ 0 ] ).text(), \"hi!\", \"Check node,textnode,comment with text()\" );\n\tequal( j[ 1 ].nodeValue, \" there \", \"Check node,textnode,comment with text()\" );\n\n\t// Blackberry 4.6 doesn't maintain comments in the DOM\n\tequal( jQuery(\"#nonnodes\")[ 0 ].childNodes.length < 3 ? 8 : j[ 2 ].nodeType, 8, \"Check node,textnode,comment with text()\" );\n}\n\ntest( \"text(String)\", function() {\n\ttestText( manipulationBareObj );\n});\n\ntest( \"text(Function)\", function() {\n\ttestText( manipulationFunctionReturningObj );\n});\n\ntest( \"text(Function) with incoming value\", function() {\n\n\texpect( 2 );\n\n\tvar old = \"This link has class=\\\"blog\\\": Simon Willison's Weblog\";\n\n\tjQuery(\"#sap\").text(function( i, val ) {\n\t\tequal( val, old, \"Make sure the incoming value is correct.\" );\n\t\treturn \"foobar\";\n\t});\n\n\tequal( jQuery(\"#sap\").text(), \"foobar\", \"Check for merged text of more then one element.\" );\n});\n\nfunction testAppendForObject( valueObj, isFragment ) {\n\tvar $base,\n\t\ttype = isFragment ? \" (DocumentFragment)\" : \" (Element)\",\n\t\ttext = \"This link has class=\\\"blog\\\": Simon Willison's Weblog\",\n\t\tel = document.getElementById(\"sap\").cloneNode( true ),\n\t\tfirst = document.getElementById(\"first\"),\n\t\tyahoo = document.getElementById(\"yahoo\");\n\n\tif ( isFragment ) {\n\t\t$base = document.createDocumentFragment();\n\t\tjQuery( el ).contents().each(function() {\n\t\t\t$base.appendChild( this );\n\t\t});\n\t\t$base = jQuery( $base );\n\t} else {\n\t\t$base = jQuery( el );\n\t}\n\n\tequal( $base.clone().append( valueObj(first.cloneNode(true)) ).text(),\n\t\ttext + \"Try them out:\",\n\t\t\"Check for appending of element\" + type\n\t);\n\n\tequal( $base.clone().append( valueObj([ first.cloneNode(true), yahoo.cloneNode(true) ]) ).text(),\n\t\ttext + \"Try them out:Yahoo\",\n\t\t\"Check for appending of array of elements\" + type\n\t);\n\n\tequal( $base.clone().append( valueObj(jQuery(\"#yahoo, #first\").clone()) ).text(),\n\t\ttext + \"YahooTry them out:\",\n\t\t\"Check for appending of jQuery object\" + type\n\t);\n\n\tequal( $base.clone().append( valueObj( 5 ) ).text(),\n\t\ttext + \"5\",\n\t\t\"Check for appending a number\" + type\n\t);\n\n\tequal( $base.clone().append( valueObj([ jQuery(\"#first\").clone(), jQuery(\"#yahoo, #google\").clone() ]) ).text(),\n\t\ttext + \"Try them out:GoogleYahoo\",\n\t\t\"Check for appending of array of jQuery objects\"\n\t);\n\n\tequal( $base.clone().append( valueObj(\" text with spaces \") ).text(),\n\t\ttext + \" text with spaces \",\n\t\t\"Check for appending text with spaces\" + type\n\t);\n\n\tequal( $base.clone().append( valueObj([]) ).text(),\n\t\ttext,\n\t\t\"Check for appending an empty array\" + type\n\t);\n\n\tequal( $base.clone().append( valueObj(\"\") ).text(),\n\t\ttext,\n\t\t\"Check for appending an empty string\" + type\n\t);\n\n\tequal( $base.clone().append( valueObj(document.getElementsByTagName(\"foo\")) ).text(),\n\t\ttext,\n\t\t\"Check for appending an empty nodelist\" + type\n\t);\n\n\tequal( $base.clone().append( \"<span></span>\", \"<span></span>\", \"<span></span>\" ).children().length,\n\t\t$base.children().length + 3,\n\t\t\"Make sure that multiple arguments works.\" + type\n\t);\n\n\tequal( $base.clone().append( valueObj(document.getElementById(\"form\").cloneNode(true)) ).children(\"form\").length,\n\t\t1,\n\t\t\"Check for appending a form (#910)\" + type\n\t);\n}\n\nfunction testAppend( valueObj ) {\n\n\texpect( 78 );\n\n\ttestAppendForObject( valueObj, false );\n\ttestAppendForObject( valueObj, true );\n\n\tvar defaultText, result, message, iframe, iframeDoc, j, d,\n\t\t$input, $radioChecked, $radioUnchecked, $radioParent, $map, $table;\n\n\tdefaultText = \"Try them out:\";\n\tresult = jQuery(\"#first\").append( valueObj(\"<b>buga</b>\") );\n\n\tequal( result.text(), defaultText + \"buga\", \"Check if text appending works\" );\n\tequal( jQuery(\"#select3\").append( valueObj(\"<option value='appendTest'>Append Test</option>\") ).find(\"option:last-child\").attr(\"value\"), \"appendTest\", \"Appending html options to select element\" );\n\n\tjQuery(\"form\").append( valueObj(\"<input name='radiotest' type='radio' checked='checked' />\") );\n\tjQuery(\"form input[name=radiotest]\").each(function() {\n\t\tok( jQuery(this).is(\":checked\"), \"Append checked radio\" );\n\t}).remove();\n\n\tjQuery(\"form\").append( valueObj(\"<input name='radiotest2' type='radio' checked    =   'checked' />\") );\n\tjQuery(\"form input[name=radiotest2]\").each(function() {\n\t\tok( jQuery(this).is(\":checked\"), \"Append alternately formated checked radio\" );\n\t}).remove();\n\n\tjQuery(\"form\").append( valueObj(\"<input name='radiotest3' type='radio' checked />\") );\n\tjQuery(\"form input[name=radiotest3]\").each(function() {\n\t\tok( jQuery(this).is(\":checked\"), \"Append HTML5-formated checked radio\" );\n\t}).remove();\n\n\tjQuery(\"form\").append( valueObj(\"<input type='radio' checked='checked' name='radiotest4' />\") );\n\tjQuery(\"form input[name=radiotest4]\").each(function() {\n\t\tok( jQuery(this).is(\":checked\"), \"Append with name attribute after checked attribute\" );\n\t}).remove();\n\n\tmessage = \"Test for appending a DOM node to the contents of an iframe\";\n\tiframe = jQuery(\"#iframe\")[ 0 ];\n\tiframeDoc = iframe.contentDocument || iframe.contentWindow && iframe.contentWindow.document;\n\n\ttry {\n\t\tif ( iframeDoc && iframeDoc.body ) {\n\t\t\tequal( jQuery(iframeDoc.body).append( valueObj(\"<div id='success'>test</div>\") )[ 0 ].lastChild.id, \"success\", message );\n\t\t} else {\n\t\t\tok( true, message + \" - can't test\" );\n\t\t}\n\t} catch( e ) {\n\t\tstrictEqual( e.message || e, undefined, message );\n\t}\n\n\tjQuery(\"<fieldset/>\").appendTo(\"#form\").append( valueObj(\"<legend id='legend'>test</legend>\") );\n\tt( \"Append legend\", \"#legend\", [ \"legend\" ] );\n\n\t$map = jQuery(\"<map/>\").append( valueObj(\"<area id='map01' shape='rect' coords='50,50,150,150' href='http://www.jquery.com/' alt='jQuery'>\") );\n\n\tequal( $map[ 0 ].childNodes.length, 1, \"The area was inserted.\" );\n\tequal( $map[ 0 ].firstChild.nodeName.toLowerCase(), \"area\", \"The area was inserted.\" );\n\n\tjQuery(\"#select1\").append( valueObj(\"<OPTION>Test</OPTION>\") );\n\tequal( jQuery(\"#select1 option:last-child\").text(), \"Test\", \"Appending OPTION (all caps)\" );\n\n\tjQuery(\"#select1\").append( valueObj(\"<optgroup label='optgroup'><option>optgroup</option></optgroup>\") );\n\tequal( jQuery(\"#select1 optgroup\").attr(\"label\"), \"optgroup\", \"Label attribute in newly inserted optgroup is correct\" );\n\tequal( jQuery(\"#select1 option\").last().text(), \"optgroup\", \"Appending optgroup\" );\n\n\t$table = jQuery(\"#table\");\n\n\tjQuery.each( \"thead tbody tfoot colgroup caption tr th td\".split(\" \"), function( i, name ) {\n\t\t$table.append( valueObj( \"<\" + name + \"/>\" ) );\n\t\tequal( $table.find( name ).length, 1, \"Append \" + name );\n\t\tok( jQuery.parseHTML( \"<\" + name + \"/>\" ).length, name + \" wrapped correctly\" );\n\t});\n\n\tjQuery(\"#table colgroup\").append( valueObj(\"<col/>\") );\n\tequal( jQuery(\"#table colgroup col\").length, 1, \"Append col\" );\n\n\tjQuery(\"#form\")\n\t\t.append( valueObj(\"<select id='appendSelect1'></select>\") )\n\t\t.append( valueObj(\"<select id='appendSelect2'><option>Test</option></select>\") );\n\tt( \"Append Select\", \"#appendSelect1, #appendSelect2\", [ \"appendSelect1\", \"appendSelect2\" ] );\n\n\tequal( \"Two nodes\", jQuery(\"<div />\").append( \"Two\", \" nodes\" ).text(), \"Appending two text nodes (#4011)\" );\n\tequal( jQuery(\"<div />\").append( \"1\", \"\", 3 ).text(), \"13\", \"If median is false-like value, subsequent arguments should not be ignored\" );\n\n\t// using contents will get comments regular, text, and comment nodes\n\tj = jQuery(\"#nonnodes\").contents();\n\td = jQuery(\"<div/>\").appendTo(\"#nonnodes\").append( j );\n\n\tequal( jQuery(\"#nonnodes\").length, 1, \"Check node,textnode,comment append moved leaving just the div\" );\n\tequal( d.contents().length, 3, \"Check node,textnode,comment append works\" );\n\td.contents().appendTo(\"#nonnodes\");\n\td.remove();\n\tequal( jQuery(\"#nonnodes\").contents().length, 3, \"Check node,textnode,comment append cleanup worked\" );\n\n\t$input = jQuery(\"<input type='checkbox'/>\").prop( \"checked\", true ).appendTo(\"#testForm\");\n\tequal( $input[ 0 ].checked, true, \"A checked checkbox that is appended stays checked\" );\n\n\t$radioChecked = jQuery(\"input[type='radio'][name='R1']\").eq( 1 );\n\t$radioParent = $radioChecked.parent();\n\t$radioUnchecked = jQuery(\"<input type='radio' name='R1' checked='checked'/>\").appendTo( $radioParent );\n\t$radioChecked.trigger(\"click\");\n\t$radioUnchecked[ 0 ].checked = false;\n\n\tjQuery(\"<div/>\").insertBefore($radioParent).append($radioParent);\n\n\tequal( $radioChecked[ 0 ].checked, true, \"Reappending radios uphold which radio is checked\" );\n\tequal( $radioUnchecked[ 0 ].checked, false, \"Reappending radios uphold not being checked\" );\n\n\tequal( jQuery(\"<div/>\").append( valueObj(\"option<area/>\") )[ 0 ].childNodes.length, 2, \"HTML-string with leading text should be processed correctly\" );\n}\n\ntest( \"append(String|Element|Array<Element>|jQuery)\", function() {\n\ttestAppend( manipulationBareObj );\n});\n\ntest( \"append(Function)\", function() {\n\ttestAppend( manipulationFunctionReturningObj );\n});\n\ntest( \"append(param) to object, see #11280\", function() {\n\n\texpect( 5 );\n\n\tvar object = jQuery( document.createElement(\"object\") ).appendTo( document.body );\n\n\tequal( object.children().length, 0, \"object does not start with children\" );\n\n\tobject.append( jQuery(\"<param type='wmode' name='foo'>\") );\n\tequal( object.children().length, 1, \"appended param\" );\n\tequal( object.children().eq(0).attr(\"name\"), \"foo\", \"param has name=foo\" );\n\n\tobject = jQuery(\"<object><param type='baz' name='bar'></object>\");\n\tequal( object.children().length, 1, \"object created with child param\" );\n\tequal( object.children().eq(0).attr(\"name\"), \"bar\", \"param has name=bar\" );\n});\n\ntest( \"append(Function) with incoming value\", function() {\n\n\texpect( 12 );\n\n\tvar defaultText, result, select, old, expected;\n\n\tdefaultText = \"Try them out:\";\n\told = jQuery(\"#first\").html();\n\n\tresult = jQuery(\"#first\").append(function( i, val ) {\n\t\tequal( val, old, \"Make sure the incoming value is correct.\" );\n\t\treturn \"<b>buga</b>\";\n\t});\n\tequal( result.text(), defaultText + \"buga\", \"Check if text appending works\" );\n\n\tselect = jQuery(\"#select3\");\n\told = select.html();\n\n\tequal( select.append(function( i, val ) {\n\t\tequal( val, old, \"Make sure the incoming value is correct.\" );\n\t\treturn \"<option value='appendTest'>Append Test</option>\";\n\t}).find(\"option:last-child\").attr(\"value\"), \"appendTest\", \"Appending html options to select element\" );\n\n\tQUnit.reset();\n\texpected = \"This link has class=\\\"blog\\\": Simon Willison's WeblogTry them out:\";\n\told = jQuery(\"#sap\").html();\n\n\tjQuery(\"#sap\").append(function( i, val ) {\n\t\tequal( val, old, \"Make sure the incoming value is correct.\" );\n\t\treturn document.getElementById(\"first\");\n\t});\n\tequal( jQuery(\"#sap\").text(), expected, \"Check for appending of element\" );\n\n\tQUnit.reset();\n\texpected = \"This link has class=\\\"blog\\\": Simon Willison's WeblogTry them out:Yahoo\";\n\told = jQuery(\"#sap\").html();\n\n\tjQuery(\"#sap\").append(function( i, val ) {\n\t\tequal( val, old, \"Make sure the incoming value is correct.\" );\n\t\treturn [ document.getElementById(\"first\"), document.getElementById(\"yahoo\") ];\n\t});\n\tequal( jQuery(\"#sap\").text(), expected, \"Check for appending of array of elements\" );\n\n\tQUnit.reset();\n\texpected = \"This link has class=\\\"blog\\\": Simon Willison's WeblogYahooTry them out:\";\n\told = jQuery(\"#sap\").html();\n\n\tjQuery(\"#sap\").append(function( i, val ) {\n\t\tequal( val, old, \"Make sure the incoming value is correct.\" );\n\t\treturn jQuery(\"#yahoo, #first\");\n\t});\n\tequal( jQuery(\"#sap\").text(), expected, \"Check for appending of jQuery object\" );\n\n\tQUnit.reset();\n\told = jQuery(\"#sap\").html();\n\n\tjQuery(\"#sap\").append(function( i, val ) {\n\t\tequal( val, old, \"Make sure the incoming value is correct.\" );\n\t\treturn 5;\n\t});\n\tok( jQuery(\"#sap\")[ 0 ].innerHTML.match( /5$/ ), \"Check for appending a number\" );\n\n\tQUnit.reset();\n});\n\ntest( \"XML DOM manipulation (#9960)\", function() {\n\n\texpect( 5 );\n\n\tvar\n\t\txmlDoc1 = jQuery.parseXML(\"<scxml xmlns='http://www.w3.org/2005/07/scxml' version='1.0'><state x='100' y='100' initial='actions' id='provisioning'></state><state x='100' y='100' id='error'></state><state x='100' y='100' id='finished' final='true'></state></scxml>\"),\n\t\txmlDoc2 = jQuery.parseXML(\"<scxml xmlns='http://www.w3.org/2005/07/scxml' version='1.0'><state id='provisioning3'></state></scxml>\"),\n\t\txml1 = jQuery( xmlDoc1 ),\n\t\txml2 = jQuery( xmlDoc2 ),\n\t\tscxml1 = jQuery( \"scxml\", xml1 ),\n\t\tscxml2 = jQuery( \"scxml\", xml2 ),\n\t\tstate = scxml2.find(\"state\");\n\n\tscxml1.append( state );\n\tstrictEqual( scxml1[0].lastChild, state[0], \"append\" );\n\n\tscxml1.prepend( state );\n\tstrictEqual( scxml1[0].firstChild, state[0], \"prepend\" );\n\n\tscxml1.find(\"#finished\").after( state );\n\tstrictEqual( scxml1[0].lastChild, state[0], \"after\" );\n\n\tscxml1.find(\"#provisioning\").before( state );\n\tstrictEqual( scxml1[0].firstChild, state[0], \"before\" );\n\n\tscxml2.replaceWith( scxml1 );\n\tdeepEqual( jQuery( \"state\", xml2 ).get(), scxml1.find(\"state\").get(), \"replaceWith\" );\n});\n\ntest( \"append HTML5 sectioning elements (Bug #6485)\", function() {\n\n\texpect( 2 );\n\n\tvar article, aside;\n\n\tjQuery(\"#qunit-fixture\").append(\"<article style='font-size:10px'><section><aside>HTML5 elements</aside></section></article>\");\n\n\tarticle = jQuery(\"article\");\n\taside = jQuery(\"aside\");\n\n\tequal( article.get( 0 ).style.fontSize, \"10px\", \"HTML5 elements are styleable\" );\n\tequal( aside.length, 1, \"HTML5 elements do not collapse their children\" );\n});\n\nif ( jQuery.css ) {\n\ttest( \"HTML5 Elements inherit styles from style rules (Bug #10501)\", function() {\n\n\t\texpect( 1 );\n\n\t\tjQuery(\"#qunit-fixture\").append(\"<article id='article'></article>\");\n\t\tjQuery(\"#article\").append(\"<section>This section should have a pink background.</section>\");\n\n\t\t// In IE, the missing background color will claim its value is \"transparent\"\n\t\tnotEqual( jQuery(\"section\").css(\"background-color\"), \"transparent\", \"HTML5 elements inherit styles\" );\n\t});\n}\n\ntest( \"html(String) with HTML5 (Bug #6485)\", function() {\n\n\texpect( 2 );\n\n\tjQuery(\"#qunit-fixture\").html(\"<article><section><aside>HTML5 elements</aside></section></article>\");\n\tequal( jQuery(\"#qunit-fixture\").children().children().length, 1, \"Make sure HTML5 article elements can hold children. innerHTML shortcut path\" );\n\tequal( jQuery(\"#qunit-fixture\").children().children().children().length, 1, \"Make sure nested HTML5 elements can hold children.\" );\n});\n\ntest( \"IE8 serialization bug\", function() {\n\n\texpect( 2 );\n\tvar wrapper = jQuery(\"<div></div>\");\n\n\twrapper.html(\"<div></div><article></article>\");\n\tequal( wrapper.children(\"article\").length, 1, \"HTML5 elements are insertable with .html()\" );\n\n\twrapper.html(\"<div></div><link></link>\");\n\tequal( wrapper.children(\"link\").length, 1, \"Link elements are insertable with .html()\" );\n});\n\ntest( \"html() object element #10324\", function() {\n\n\texpect( 1 );\n\n\tvar object = jQuery(\"<object id='object2'><param name='object2test' value='test'></param></object>?\").appendTo(\"#qunit-fixture\"),\n\t\tclone = object.clone();\n\n\tequal( clone.html(), object.html(), \"html() returns correct innerhtml of cloned object elements\" );\n});\n\ntest( \"append(xml)\", function() {\n\n\texpect( 1 );\n\n\tvar xmlDoc, xml1, xml2;\n\n\tfunction createXMLDoc() {\n\t\t// Initialize DOM based upon latest installed MSXML or Netscape\n\t\tvar elem, n, len,\n\t\t\taActiveX =\n\t\t\t\t[ \"MSXML6.DomDocument\",\n\t\t\t\t\"MSXML3.DomDocument\",\n\t\t\t\t\"MSXML2.DomDocument\",\n\t\t\t\t\"MSXML.DomDocument\",\n\t\t\t\t\"Microsoft.XmlDom\" ];\n\n\t\tif ( document.implementation && \"createDocument\" in document.implementation ) {\n\t\t\treturn document.implementation.createDocument( \"\", \"\", null );\n\t\t} else {\n\t\t\t// IE\n\t\t\tfor ( n = 0, len = aActiveX.length; n < len; n++ ) {\n\t\t\t\ttry {\n\t\t\t\t\telem = new ActiveXObject( aActiveX[ n ] );\n\t\t\t\t\treturn elem;\n\t\t\t\t} catch(_) {}\n\t\t\t}\n\t\t}\n\t}\n\n\txmlDoc = createXMLDoc();\n\txml1 = xmlDoc.createElement(\"head\");\n\txml2 = xmlDoc.createElement(\"test\");\n\n\tok( jQuery(xml1).append(xml2), \"Append an xml element to another without raising an exception.\" );\n\n});\n\ntest( \"appendTo(String|Element|Array<Element>|jQuery)\", function() {\n\n\texpect( 16 );\n\n\tvar defaultText, l, expected, num, div;\n\n\tdefaultText = \"Try them out:\";\n\tjQuery(\"<b>buga</b>\").appendTo(\"#first\");\n\tequal( jQuery(\"#first\").text(), defaultText + \"buga\", \"Check if text appending works\" );\n\tequal( jQuery(\"<option value='appendTest'>Append Test</option>\").appendTo(\"#select3\").parent().find(\"option:last-child\").attr(\"value\"), \"appendTest\", \"Appending html options to select element\" );\n\n\tl = jQuery(\"#first\").children().length + 2;\n\tjQuery(\"<strong>test</strong>\");\n\tjQuery(\"<strong>test</strong>\");\n\tjQuery([ jQuery(\"<strong>test</strong>\")[ 0 ], jQuery(\"<strong>test</strong>\")[ 0 ] ])\n\t\t.appendTo(\"#first\");\n\tequal( jQuery(\"#first\").children().length, l, \"Make sure the elements were inserted.\" );\n\tequal( jQuery(\"#first\").children().last()[ 0 ].nodeName.toLowerCase(), \"strong\", \"Verify the last element.\" );\n\n\tQUnit.reset();\n\texpected = \"This link has class=\\\"blog\\\": Simon Willison's WeblogTry them out:\";\n\tjQuery( document.getElementById(\"first\") ).appendTo(\"#sap\");\n\tequal( jQuery(\"#sap\").text(), expected, \"Check for appending of element\" );\n\n\texpected = \"This link has class=\\\"blog\\\": Simon Willison's WeblogTry them out:Yahoo\";\n\tjQuery([ document.getElementById(\"first\"), document.getElementById(\"yahoo\") ]).appendTo(\"#sap\");\n\tequal( jQuery(\"#sap\").text(), expected, \"Check for appending of array of elements\" );\n\n\tQUnit.reset();\n\tok( jQuery(document.createElement(\"script\")).appendTo(\"body\").length, \"Make sure a disconnected script can be appended.\" );\n\n\texpected = \"This link has class=\\\"blog\\\": Simon Willison's WeblogYahooTry them out:\";\n\tjQuery(\"#yahoo, #first\").appendTo(\"#sap\");\n\tequal( jQuery(\"#sap\").text(), expected, \"Check for appending of jQuery object\" );\n\n\tjQuery(\"#select1\").appendTo(\"#foo\");\n\tt( \"Append select\", \"#foo select\", [ \"select1\" ] );\n\n\tdiv = jQuery(\"<div/>\").on( \"click\", function() {\n\t\tok( true, \"Running a cloned click.\" );\n\t});\n\tdiv.appendTo(\"#qunit-fixture, #moretests\");\n\n\tjQuery(\"#qunit-fixture div\").last().trigger(\"click\");\n\tjQuery(\"#moretests div\").last().trigger(\"click\");\n\n\tdiv = jQuery(\"<div/>\").appendTo(\"#qunit-fixture, #moretests\");\n\n\tequal( div.length, 2, \"appendTo returns the inserted elements\" );\n\n\tdiv.addClass(\"test\");\n\n\tok( jQuery(\"#qunit-fixture div\").last().hasClass(\"test\"), \"appendTo element was modified after the insertion\" );\n\tok( jQuery(\"#moretests div\").last().hasClass(\"test\"), \"appendTo element was modified after the insertion\" );\n\n\tdiv = jQuery(\"<div/>\");\n\tjQuery(\"<span>a</span><b>b</b>\").filter(\"span\").appendTo( div );\n\n\tequal( div.children().length, 1, \"Make sure the right number of children were inserted.\" );\n\n\tdiv = jQuery(\"#moretests div\");\n\n\tnum = jQuery(\"#qunit-fixture div\").length;\n\tdiv.remove().appendTo(\"#qunit-fixture\");\n\n\tequal( jQuery(\"#qunit-fixture div\").length, num, \"Make sure all the removed divs were inserted.\" );\n});\n\nfunction testPrepend( val ) {\n\n\texpect( 6 );\n\n\tvar defaultText, result, expected;\n\n\tdefaultText = \"Try them out:\";\n\tresult = jQuery(\"#first\").prepend( val(\"<b>buga</b>\") );\n\n\tequal( result.text(), \"buga\" + defaultText, \"Check if text prepending works\" );\n\tequal( jQuery(\"#select3\").prepend( val(\"<option value='prependTest'>Prepend Test</option>\" ) ).find(\"option:first-child\").attr(\"value\"), \"prependTest\", \"Prepending html options to select element\" );\n\n\tQUnit.reset();\n\texpected = \"Try them out:This link has class=\\\"blog\\\": Simon Willison's Weblog\";\n\tjQuery(\"#sap\").prepend( val(document.getElementById(\"first\")) );\n\tequal( jQuery(\"#sap\").text(), expected, \"Check for prepending of element\" );\n\n\tQUnit.reset();\n\texpected = \"Try them out:YahooThis link has class=\\\"blog\\\": Simon Willison's Weblog\";\n\tjQuery(\"#sap\").prepend( val([ document.getElementById(\"first\"), document.getElementById(\"yahoo\") ]) );\n\tequal( jQuery(\"#sap\").text(), expected, \"Check for prepending of array of elements\" );\n\n\tQUnit.reset();\n\texpected = \"YahooTry them out:This link has class=\\\"blog\\\": Simon Willison's Weblog\";\n\tjQuery(\"#sap\").prepend( val(jQuery(\"#yahoo, #first\")) );\n\tequal( jQuery(\"#sap\").text(), expected, \"Check for prepending of jQuery object\" );\n\n\tQUnit.reset();\n\texpected = \"Try them out:GoogleYahooThis link has class=\\\"blog\\\": Simon Willison's Weblog\";\n\tjQuery(\"#sap\").prepend( val([ jQuery(\"#first\"), jQuery(\"#yahoo, #google\") ]) );\n\tequal( jQuery(\"#sap\").text(), expected, \"Check for prepending of array of jQuery objects\" );\n}\n\ntest( \"prepend(String|Element|Array<Element>|jQuery)\", function() {\n\ttestPrepend( manipulationBareObj );\n});\n\ntest( \"prepend(Function)\", function() {\n\ttestPrepend( manipulationFunctionReturningObj );\n});\n\ntest( \"prepend(Function) with incoming value\", function() {\n\n\texpect( 10 );\n\n\tvar defaultText, old, result, expected;\n\n\tdefaultText = \"Try them out:\";\n\told = jQuery(\"#first\").html();\n\tresult = jQuery(\"#first\").prepend(function( i, val ) {\n\t\tequal( val, old, \"Make sure the incoming value is correct.\" );\n\t\treturn \"<b>buga</b>\";\n\t});\n\n\tequal( result.text(), \"buga\" + defaultText, \"Check if text prepending works\" );\n\n\told = jQuery(\"#select3\").html();\n\n\tequal( jQuery(\"#select3\").prepend(function( i, val ) {\n\t\tequal( val, old, \"Make sure the incoming value is correct.\" );\n\t\treturn \"<option value='prependTest'>Prepend Test</option>\";\n\t}).find(\"option:first-child\").attr(\"value\"), \"prependTest\", \"Prepending html options to select element\" );\n\n\tQUnit.reset();\n\texpected = \"Try them out:This link has class=\\\"blog\\\": Simon Willison's Weblog\";\n\told = jQuery(\"#sap\").html();\n\n\tjQuery(\"#sap\").prepend(function( i, val ) {\n\t\tequal( val, old, \"Make sure the incoming value is correct.\" );\n\t\treturn document.getElementById(\"first\");\n\t});\n\n\tequal( jQuery(\"#sap\").text(), expected, \"Check for prepending of element\" );\n\n\tQUnit.reset();\n\texpected = \"Try them out:YahooThis link has class=\\\"blog\\\": Simon Willison's Weblog\";\n\told = jQuery(\"#sap\").html();\n\n\tjQuery(\"#sap\").prepend(function( i, val ) {\n\t\tequal( val, old, \"Make sure the incoming value is correct.\" );\n\t\treturn [ document.getElementById(\"first\"), document.getElementById(\"yahoo\") ];\n\t});\n\n\tequal( jQuery(\"#sap\").text(), expected, \"Check for prepending of array of elements\" );\n\n\tQUnit.reset();\n\texpected = \"YahooTry them out:This link has class=\\\"blog\\\": Simon Willison's Weblog\";\n\told = jQuery(\"#sap\").html();\n\n\tjQuery(\"#sap\").prepend(function( i, val ) {\n\t\tequal( val, old, \"Make sure the incoming value is correct.\" );\n\t\treturn jQuery(\"#yahoo, #first\");\n\t});\n\n\tequal( jQuery(\"#sap\").text(), expected, \"Check for prepending of jQuery object\" );\n});\n\ntest( \"prependTo(String|Element|Array<Element>|jQuery)\", function() {\n\n\texpect( 6 );\n\n\tvar defaultText, expected;\n\n\tdefaultText = \"Try them out:\";\n\tjQuery(\"<b>buga</b>\").prependTo(\"#first\");\n\tequal( jQuery(\"#first\").text(), \"buga\" + defaultText, \"Check if text prepending works\" );\n\tequal( jQuery(\"<option value='prependTest'>Prepend Test</option>\").prependTo(\"#select3\").parent().find(\"option:first-child\").attr(\"value\"), \"prependTest\", \"Prepending html options to select element\" );\n\n\tQUnit.reset();\n\texpected = \"Try them out:This link has class=\\\"blog\\\": Simon Willison's Weblog\";\n\tjQuery( document.getElementById(\"first\") ).prependTo(\"#sap\");\n\tequal( jQuery(\"#sap\").text(), expected, \"Check for prepending of element\" );\n\n\tQUnit.reset();\n\texpected = \"Try them out:YahooThis link has class=\\\"blog\\\": Simon Willison's Weblog\";\n\tjQuery( [ document.getElementById(\"first\"), document.getElementById(\"yahoo\") ] ).prependTo(\"#sap\");\n\tequal( jQuery(\"#sap\").text(), expected, \"Check for prepending of array of elements\" );\n\n\tQUnit.reset();\n\texpected = \"YahooTry them out:This link has class=\\\"blog\\\": Simon Willison's Weblog\";\n\tjQuery(\"#yahoo, #first\").prependTo(\"#sap\");\n\tequal( jQuery(\"#sap\").text(), expected, \"Check for prepending of jQuery object\" );\n\n\tQUnit.reset();\n\tjQuery(\"<select id='prependSelect1'></select>\").prependTo(\"#form\");\n\tjQuery(\"<select id='prependSelect2'><option>Test</option></select>\").prependTo(\"#form\");\n\n\tt( \"Prepend Select\", \"#prependSelect2, #prependSelect1\", [ \"prependSelect2\", \"prependSelect1\" ] );\n});\n\nfunction testBefore( val ) {\n\n\texpect( 7 );\n\n\tvar expected, set;\n\n\texpected = \"This is a normal link: bugaYahoo\";\n\tjQuery(\"#yahoo\").before( val(\"<b>buga</b>\") );\n\tequal( jQuery(\"#en\").text(), expected, \"Insert String before\" );\n\n\tQUnit.reset();\n\texpected = \"This is a normal link: Try them out:Yahoo\";\n\tjQuery(\"#yahoo\").before( val(document.getElementById(\"first\")) );\n\tequal( jQuery(\"#en\").text(), expected, \"Insert element before\" );\n\n\tQUnit.reset();\n\texpected = \"This is a normal link: Try them out:diveintomarkYahoo\";\n\tjQuery(\"#yahoo\").before( val([ document.getElementById(\"first\"), document.getElementById(\"mark\") ]) );\n\tequal( jQuery(\"#en\").text(), expected, \"Insert array of elements before\" );\n\n\tQUnit.reset();\n\texpected = \"This is a normal link: diveintomarkTry them out:Yahoo\";\n\tjQuery(\"#yahoo\").before( val(jQuery(\"#mark, #first\")) );\n\tequal( jQuery(\"#en\").text(), expected, \"Insert jQuery before\" );\n\n\tQUnit.reset();\n\texpected = \"This is a normal link: Try them out:GooglediveintomarkYahoo\";\n\tjQuery(\"#yahoo\").before( val([ jQuery(\"#first\"), jQuery(\"#mark, #google\") ]) );\n\tequal( jQuery(\"#en\").text(), expected, \"Insert array of jQuery objects before\" );\n\n\tset = jQuery(\"<div/>\").before(\"<span>test</span>\");\n\tequal( set[ 0 ].nodeName.toLowerCase(), \"div\", \"Insert before a disconnected node should be a no-op\" );\n\tequal( set.length, 1, \"Insert the element before the disconnected node. should be a no-op\" );\n}\n\ntest( \"before(String|Element|Array<Element>|jQuery)\", function() {\n\ttestBefore( manipulationBareObj );\n});\n\ntest( \"before(Function)\", function() {\n\ttestBefore( manipulationFunctionReturningObj );\n});\n\ntest( \"before and after w/ empty object (#10812)\", function() {\n\n\texpect( 1 );\n\n\tvar res;\n\n\tres = jQuery( \"#notInTheDocument\" ).before( \"(\" ).after( \")\" );\n\tequal( res.length, 0, \"didn't choke on empty object\" );\n});\n\ntest( \"before and after on disconnected node (#10517)\", function() {\n\n\texpect( 6 );\n\n\tvar expectedBefore = \"This is a normal link: bugaYahoo\",\n\t\texpectedAfter = \"This is a normal link: Yahoobuga\";\n\n\tequal( jQuery(\"<input type='checkbox'/>\").before(\"<div/>\").length, 1, \"before() on disconnected node is no-op\" );\n\tequal( jQuery(\"<input type='checkbox'/>\").after(\"<div/>\").length, 1, \"after() on disconnected node is no-op\" );\n\n\tQUnit.reset();\n\tjQuery(\"#yahoo\").add(\"<span/>\").before(\"<b>buga</b>\");\n\tequal( jQuery(\"#en\").text(), expectedBefore, \"Insert String before with disconnected node last\" );\n\n\tQUnit.reset();\n\tjQuery(\"<span/>\").add(\"#yahoo\").before(\"<b>buga</b>\");\n\tequal( jQuery(\"#en\").text(), expectedBefore, \"Insert String before with disconnected node first\" );\n\n\tQUnit.reset();\n\tjQuery(\"#yahoo\").add(\"<span/>\").after(\"<b>buga</b>\");\n\tequal( jQuery(\"#en\").text(), expectedAfter, \"Insert String after with disconnected node last\" );\n\n\tQUnit.reset();\n\tjQuery(\"<span/>\").add(\"#yahoo\").after(\"<b>buga</b>\");\n\tequal( jQuery(\"#en\").text(), expectedAfter, \"Insert String after with disconnected node first\" );\n});\n\ntest( \"insertBefore(String|Element|Array<Element>|jQuery)\", function() {\n\n\texpect( 4 );\n\n\tvar expected;\n\n\texpected = \"This is a normal link: bugaYahoo\";\n\tjQuery(\"<b>buga</b>\").insertBefore(\"#yahoo\");\n\tequal( jQuery(\"#en\").text(), expected, \"Insert String before\" );\n\n\tQUnit.reset();\n\texpected = \"This is a normal link: Try them out:Yahoo\";\n\tjQuery( document.getElementById(\"first\") ).insertBefore(\"#yahoo\");\n\tequal( jQuery(\"#en\").text(), expected, \"Insert element before\" );\n\n\tQUnit.reset();\n\texpected = \"This is a normal link: Try them out:diveintomarkYahoo\";\n\tjQuery( [ document.getElementById(\"first\"), document.getElementById(\"mark\") ] ).insertBefore(\"#yahoo\");\n\tequal( jQuery(\"#en\").text(), expected, \"Insert array of elements before\" );\n\n\tQUnit.reset();\n\texpected = \"This is a normal link: diveintomarkTry them out:Yahoo\";\n\tjQuery(\"#mark, #first\").insertBefore(\"#yahoo\");\n\tequal( jQuery(\"#en\").text(), expected, \"Insert jQuery before\" );\n});\n\nfunction testAfter( val ) {\n\n\texpect( 7 );\n\n\tvar set, expected;\n\n\texpected = \"This is a normal link: Yahoobuga\";\n\tjQuery(\"#yahoo\").after( val(\"<b>buga</b>\") );\n\tequal( jQuery(\"#en\").text(), expected, \"Insert String after\" );\n\n\tQUnit.reset();\n\texpected = \"This is a normal link: YahooTry them out:\";\n\tjQuery(\"#yahoo\").after( val(document.getElementById(\"first\")) );\n\tequal( jQuery(\"#en\").text(), expected, \"Insert element after\" );\n\n\tQUnit.reset();\n\texpected = \"This is a normal link: YahooTry them out:diveintomark\";\n\tjQuery(\"#yahoo\").after( val([ document.getElementById(\"first\"), document.getElementById(\"mark\") ]) );\n\tequal( jQuery(\"#en\").text(), expected, \"Insert array of elements after\" );\n\n\tQUnit.reset();\n\texpected = \"This is a normal link: YahoodiveintomarkTry them out:\";\n\tjQuery(\"#yahoo\").after(val( jQuery(\"#mark, #first\") ));\n\tequal( jQuery(\"#en\").text(), expected, \"Insert jQuery after\" );\n\n\tQUnit.reset();\n\texpected = \"This is a normal link: YahooTry them out:Googlediveintomark\";\n\tjQuery(\"#yahoo\").after( val([ jQuery(\"#first\"), jQuery(\"#mark, #google\") ]) );\n\tequal( jQuery(\"#en\").text(), expected, \"Insert array of jQuery objects after\" );\n\n\tset = jQuery(\"<div/>\").before(\"<span>test</span>\");\n\tequal( set[ 0 ].nodeName.toLowerCase(), \"div\", \"Insert after a disconnected node should be a no-op\" );\n\tequal( set.length, 1, \"Insert the element after the disconnected node should be a no-op\" );\n}\n\ntest( \"after(String|Element|Array<Element>|jQuery)\", function() {\n\ttestAfter( manipulationBareObj );\n});\n\ntest( \"after(Function)\", function() {\n\ttestAfter( manipulationFunctionReturningObj );\n});\n\ntest( \"insertAfter(String|Element|Array<Element>|jQuery)\", function() {\n\n\texpect( 4 ) ;\n\n\tvar expected;\n\n\texpected = \"This is a normal link: Yahoobuga\";\n\tjQuery(\"<b>buga</b>\").insertAfter(\"#yahoo\");\n\tequal( jQuery(\"#en\").text(), expected, \"Insert String after\" );\n\n\tQUnit.reset();\n\texpected = \"This is a normal link: YahooTry them out:\";\n\tjQuery( document.getElementById(\"first\") ).insertAfter(\"#yahoo\");\n\tequal( jQuery(\"#en\").text(), expected, \"Insert element after\" );\n\n\tQUnit.reset();\n\texpected = \"This is a normal link: YahooTry them out:diveintomark\";\n\tjQuery( [ document.getElementById(\"first\"), document.getElementById(\"mark\") ] ).insertAfter(\"#yahoo\");\n\tequal( jQuery(\"#en\").text(), expected, \"Insert array of elements after\" );\n\n\tQUnit.reset();\n\texpected = \"This is a normal link: YahoodiveintomarkTry them out:\";\n\tjQuery(\"#mark, #first\").insertAfter(\"#yahoo\");\n\tequal( jQuery(\"#en\").text(), expected, \"Insert jQuery after\" );\n});\n\nfunction testReplaceWith( val ) {\n\n\tvar tmp, y, child, child2, set, non_existent, $div,\n\t\texpected = 29;\n\n\texpect( expected );\n\n\tjQuery(\"#yahoo\").replaceWith( val(\"<b id='replace'>buga</b>\") );\n\tok( jQuery(\"#replace\")[ 0 ], \"Replace element with element from string\" );\n\tok( !jQuery(\"#yahoo\")[ 0 ], \"Verify that original element is gone, after string\" );\n\n\tjQuery(\"#anchor2\").replaceWith( val(document.getElementById(\"first\")) );\n\tok( jQuery(\"#first\")[ 0 ], \"Replace element with element\" );\n\tok( !jQuery(\"#anchor2\")[ 0 ], \"Verify that original element is gone, after element\" );\n\n\tjQuery(\"#qunit-fixture\").append(\"<div id='bar'><div id='baz'></div></div>\");\n\tjQuery(\"#baz\").replaceWith( val(\"Baz\") );\n\tequal( jQuery(\"#bar\").text(),\"Baz\", \"Replace element with text\" );\n\tok( !jQuery(\"#baz\")[ 0 ], \"Verify that original element is gone, after element\" );\n\n\tjQuery(\"#bar\").replaceWith( \"<div id='yahoo'></div>\", \"...\", \"<div id='baz'></div>\" );\n\tdeepEqual( jQuery(\"#yahoo, #baz\").get(), q( \"yahoo\", \"baz\" ),  \"Replace element with multiple arguments (#13722)\" );\n\tstrictEqual( jQuery(\"#yahoo\")[0].nextSibling, jQuery(\"#baz\")[0].previousSibling, \"Argument order preserved\" );\n\tdeepEqual( jQuery(\"#bar\").get(), [], \"Verify that original element is gone, after multiple arguments\" );\n\n\tjQuery(\"#google\").replaceWith( val([ document.getElementById(\"first\"), document.getElementById(\"mark\") ]) );\n\tdeepEqual( jQuery(\"#mark, #first\").get(), q( \"first\", \"mark\" ),  \"Replace element with array of elements\" );\n\tok( !jQuery(\"#google\")[ 0 ], \"Verify that original element is gone, after array of elements\" );\n\n\tjQuery(\"#groups\").replaceWith( val(jQuery(\"#mark, #first\")) );\n\tdeepEqual( jQuery(\"#mark, #first\").get(), q( \"first\", \"mark\" ),  \"Replace element with jQuery collection\" );\n\tok( !jQuery(\"#groups\")[ 0 ], \"Verify that original element is gone, after jQuery collection\" );\n\n\tjQuery(\"#mark, #first\").replaceWith( val(\"<span class='replacement'></span><span class='replacement'></span>\") );\n\tequal( jQuery(\"#qunit-fixture .replacement\").length, 4, \"Replace multiple elements (#12449)\" );\n\tdeepEqual( jQuery(\"#mark, #first\").get(), [], \"Verify that original elements are gone, after replace multiple\" );\n\n\ttmp = jQuery(\"<b>content</b>\")[0];\n\tjQuery(\"#anchor1\").contents().replaceWith( val(tmp) );\n\tdeepEqual( jQuery(\"#anchor1\").contents().get(), [ tmp ], \"Replace text node with element\" );\n\n\n\ttmp = jQuery(\"<div/>\").appendTo(\"#qunit-fixture\").on( \"click\", function() {\n\t\tok( true, \"Newly bound click run.\" );\n\t});\n\ty = jQuery(\"<div/>\").appendTo(\"#qunit-fixture\").on( \"click\", function() {\n\t\tok( false, \"Previously bound click run.\" );\n\t});\n\tchild = y.append(\"<b>test</b>\").find(\"b\").on( \"click\", function() {\n\t\tok( true, \"Child bound click run.\" );\n\t\treturn false;\n\t});\n\n\ty.replaceWith( val(tmp) );\n\n\ttmp.trigger(\"click\");\n\ty.trigger(\"click\"); // Shouldn't be run\n\tchild.trigger(\"click\"); // Shouldn't be run\n\n\n\ty = jQuery(\"<div/>\").appendTo(\"#qunit-fixture\").on( \"click\", function() {\n\t\tok( false, \"Previously bound click run.\" );\n\t});\n\tchild2 = y.append(\"<u>test</u>\").find(\"u\").on( \"click\", function() {\n\t\tok( true, \"Child 2 bound click run.\" );\n\t\treturn false;\n\t});\n\n\ty.replaceWith( val(child2) );\n\n\tchild2.trigger(\"click\");\n\n\n\tset = jQuery(\"<div/>\").replaceWith( val(\"<span>test</span>\") );\n\tequal( set[0].nodeName.toLowerCase(), \"div\", \"No effect on a disconnected node.\" );\n\tequal( set.length, 1, \"No effect on a disconnected node.\" );\n\tequal( set[0].childNodes.length, 0, \"No effect on a disconnected node.\" );\n\n\n\tchild = jQuery(\"#qunit-fixture\").children().first();\n\t$div = jQuery(\"<div class='pathological'/>\").insertBefore( child );\n\t$div.replaceWith( $div );\n\tdeepEqual( jQuery( \".pathological\", \"#qunit-fixture\" ).get(), $div.get(),\n\t\t\"Self-replacement\" );\n\t$div.replaceWith( child );\n\tdeepEqual( jQuery(\"#qunit-fixture\").children().first().get(), child.get(),\n\t\t\"Replacement with following sibling (#13810)\" );\n\tdeepEqual( jQuery( \".pathological\", \"#qunit-fixture\" ).get(), [],\n\t\t\"Replacement with following sibling (context removed)\" );\n\n\n\tnon_existent = jQuery(\"#does-not-exist\").replaceWith( val(\"<b>should not throw an error</b>\") );\n\tequal( non_existent.length, 0, \"Length of non existent element.\" );\n\n\t$div = jQuery(\"<div class='replacewith'></div>\").appendTo(\"#qunit-fixture\");\n\t$div.replaceWith( val(\"<div class='replacewith'></div><script>\" +\n\t\t\"equal( jQuery('.replacewith').length, 1, 'Check number of elements in page.' );\" +\n\t\t\"</script>\") );\n\n\tjQuery(\"#qunit-fixture\").append(\"<div id='replaceWith'></div>\");\n\tequal( jQuery(\"#qunit-fixture\").find(\"div[id=replaceWith]\").length, 1, \"Make sure only one div exists.\" );\n\tjQuery(\"#replaceWith\").replaceWith( val(\"<div id='replaceWith'></div>\") );\n\tequal( jQuery(\"#qunit-fixture\").find(\"div[id=replaceWith]\").length, 1, \"Make sure only one div exists after replacement.\" );\n\tjQuery(\"#replaceWith\").replaceWith( val(\"<div id='replaceWith'></div>\") );\n\tequal( jQuery(\"#qunit-fixture\").find(\"div[id=replaceWith]\").length, 1, \"Make sure only one div exists after subsequent replacement.\" );\n\n\treturn expected;\n}\n\ntest( \"replaceWith(String|Element|Array<Element>|jQuery)\", function() {\n\ttestReplaceWith( manipulationBareObj );\n});\n\ntest( \"replaceWith(Function)\", function() {\n\texpect( testReplaceWith(manipulationFunctionReturningObj) + 1 );\n\n\tvar y = jQuery(\"#foo\")[ 0 ];\n\n\tjQuery( y ).replaceWith(function() {\n\t\tequal( this, y, \"Make sure the context is coming in correctly.\" );\n\t});\n});\n\ntest( \"replaceWith(string) for more than one element\", function() {\n\n\texpect( 3 );\n\n\tequal( jQuery(\"#foo p\").length, 3, \"ensuring that test data has not changed\" );\n\n\tjQuery(\"#foo p\").replaceWith(\"<span>bar</span>\");\n\tequal(jQuery(\"#foo span\").length, 3, \"verify that all the three original element have been replaced\");\n\tequal(jQuery(\"#foo p\").length, 0, \"verify that all the three original element have been replaced\");\n});\n\ntest( \"empty replaceWith (#13401; #13596)\", 4, function() {\n\texpect( 6 );\n\n\tvar $el = jQuery(\"<div/>\"),\n\t\ttests = {\n\t\t\t\"empty string\": \"\",\n\t\t\t\"empty array\": [],\n\t\t\t\"empty collection\": jQuery(\"#nonexistent\")\n\t\t};\n\n\tjQuery.each( tests, function( label, input ) {\n\t\t$el.html(\"<a/>\").children().replaceWith( input );\n\t\tstrictEqual( $el.html(), \"\", \"replaceWith(\" + label + \")\" );\n\t\t$el.html(\"<b/>\").children().replaceWith(function() { return input; });\n\t\tstrictEqual( $el.html(), \"\", \"replaceWith(function returning \" + label + \")\" );\n\t});\n});\n\ntest( \"replaceAll(String|Element|Array<Element>|jQuery)\", function() {\n\n\texpect( 10 );\n\n\tjQuery(\"<b id='replace'>buga</b>\").replaceAll(\"#yahoo\");\n\tok( jQuery(\"#replace\")[ 0 ], \"Replace element with string\" );\n\tok( !jQuery(\"#yahoo\")[ 0 ], \"Verify that original element is gone, after string\" );\n\n\tQUnit.reset();\n\tjQuery( document.getElementById(\"first\") ).replaceAll(\"#yahoo\");\n\tok( jQuery(\"#first\")[ 0 ], \"Replace element with element\" );\n\tok( !jQuery(\"#yahoo\")[ 0 ], \"Verify that original element is gone, after element\" );\n\n\tQUnit.reset();\n\tjQuery( [ document.getElementById(\"first\"), document.getElementById(\"mark\") ] ).replaceAll(\"#yahoo\");\n\tok( jQuery(\"#first\")[ 0 ], \"Replace element with array of elements\" );\n\tok( jQuery(\"#mark\")[ 0 ], \"Replace element with array of elements\" );\n\tok( !jQuery(\"#yahoo\")[ 0 ], \"Verify that original element is gone, after array of elements\" );\n\n\tQUnit.reset();\n\tjQuery(\"#mark, #first\").replaceAll(\"#yahoo\");\n\tok( jQuery(\"#first\")[ 0 ], \"Replace element with set of elements\" );\n\tok( jQuery(\"#mark\")[ 0 ], \"Replace element with set of elements\" );\n\tok( !jQuery(\"#yahoo\")[ 0 ], \"Verify that original element is gone, after set of elements\" );\n});\n\ntest( \"jQuery.clone() (#8017)\", function() {\n\n\texpect( 2 );\n\n\tok( jQuery.clone && jQuery.isFunction( jQuery.clone ) , \"jQuery.clone() utility exists and is a function.\");\n\n\tvar main = jQuery(\"#qunit-fixture\")[ 0 ],\n\t\tclone = jQuery.clone( main );\n\n\tequal( main.childNodes.length, clone.childNodes.length, \"Simple child length to ensure a large dom tree copies correctly\" );\n});\n\ntest( \"append to multiple elements (#8070)\", function() {\n\n\texpect( 2 );\n\n\tvar selects = jQuery(\"<select class='test8070'></select><select class='test8070'></select>\").appendTo(\"#qunit-fixture\");\n\tselects.append(\"<OPTION>1</OPTION><OPTION>2</OPTION>\");\n\n\tequal( selects[ 0 ].childNodes.length, 2, \"First select got two nodes\" );\n\tequal( selects[ 1 ].childNodes.length, 2, \"Second select got two nodes\" );\n});\n\ntest( \"table manipulation\", function() {\n\texpect( 2 );\n\n\tvar table = jQuery(\"<table style='font-size:16px'></table>\").appendTo(\"#qunit-fixture\").empty(),\n\t\theight = table[0].offsetHeight;\n\n\ttable.append(\"<tr><td>DATA</td></tr>\");\n\tok( table[0].offsetHeight - height >= 15, \"appended rows are visible\" );\n\n\ttable.empty();\n\theight = table[0].offsetHeight;\n\ttable.prepend(\"<tr><td>DATA</td></tr>\");\n\tok( table[0].offsetHeight - height >= 15, \"prepended rows are visible\" );\n});\n\ntest( \"clone()\", function() {\n\n\texpect( 45 );\n\n\tvar div, clone, form, body;\n\n\tequal( jQuery(\"#en\").text(), \"This is a normal link: Yahoo\", \"Assert text for #en\" );\n\tequal( jQuery(\"#first\").append( jQuery(\"#yahoo\").clone() ).text(), \"Try them out:Yahoo\", \"Check for clone\" );\n\tequal( jQuery(\"#en\").text(), \"This is a normal link: Yahoo\", \"Reassert text for #en\" );\n\n\tjQuery.each( \"table thead tbody tfoot tr td div button ul ol li select option textarea iframe\".split(\" \"), function( i, nodeName ) {\n\t\tequal( jQuery( \"<\" + nodeName + \"/>\" ).clone()[ 0 ].nodeName.toLowerCase(), nodeName, \"Clone a \" + nodeName );\n\t});\n\tequal( jQuery(\"<input type='checkbox' />\").clone()[ 0 ].nodeName.toLowerCase(), \"input\", \"Clone a <input type='checkbox' />\" );\n\n\t// Check cloning non-elements\n\tequal( jQuery(\"#nonnodes\").contents().clone().length, 3, \"Check node,textnode,comment clone works (some browsers delete comments on clone)\" );\n\n\t// Verify that clones of clones can keep event listeners\n\tdiv = jQuery(\"<div><ul><li>test</li></ul></div>\").on( \"click\", function() {\n\t\tok( true, \"Bound event still exists.\" );\n\t});\n\tclone = div.clone( true ); div.remove();\n\tdiv = clone.clone( true ); clone.remove();\n\n\tequal( div.length, 1, \"One element cloned\" );\n\tequal( div[ 0 ].nodeName.toUpperCase(), \"DIV\", \"DIV element cloned\" );\n\tdiv.trigger(\"click\");\n\n\t// Manually clean up detached elements\n\tdiv.remove();\n\n\t// Verify that cloned children can keep event listeners\n\tdiv = jQuery(\"<div/>\").append([ document.createElement(\"table\"), document.createElement(\"table\") ]);\n\tdiv.find(\"table\").on( \"click\", function() {\n\t\tok( true, \"Bound event still exists.\" );\n\t});\n\n\tclone = div.clone( true );\n\tequal( clone.length, 1, \"One element cloned\" );\n\tequal( clone[ 0 ].nodeName.toUpperCase(), \"DIV\", \"DIV element cloned\" );\n\tclone.find(\"table\").trigger(\"click\");\n\n\t// Manually clean up detached elements\n\tdiv.remove();\n\tclone.remove();\n\n\t// Make sure that doing .clone() doesn't clone event listeners\n\tdiv = jQuery(\"<div><ul><li>test</li></ul></div>\").on( \"click\", function() {\n\t\tok( false, \"Bound event still exists after .clone().\" );\n\t});\n\tclone = div.clone();\n\n\tclone.trigger(\"click\");\n\n\t// Manually clean up detached elements\n\tclone.remove();\n\tdiv.remove();\n\n\t// Test both html() and clone() for <embed> and <object> types\n\tdiv = jQuery(\"<div/>\").html(\"<embed height='355' width='425' src='http://www.youtube.com/v/3KANI2dpXLw&amp;hl=en'></embed>\");\n\n\tclone = div.clone( true );\n\tequal( clone.length, 1, \"One element cloned\" );\n\tequal( clone.html(), div.html(), \"Element contents cloned\" );\n\tequal( clone[ 0 ].nodeName.toUpperCase(), \"DIV\", \"DIV element cloned\" );\n\n\t// this is technically an invalid object, but because of the special\n\t// classid instantiation it is the only kind that IE has trouble with,\n\t// so let's test with it too.\n\tdiv = jQuery(\"<div/>\").html(\"<object height='355' width='425' classid='clsid:D27CDB6E-AE6D-11cf-96B8-444553540000'>  <param name='movie' value='http://www.youtube.com/v/3KANI2dpXLw&amp;hl=en'>  <param name='wmode' value='transparent'> </object>\");\n\n\tclone = div.clone( true );\n\tequal( clone.length, 1, \"One element cloned\" );\n\tequal( clone[ 0 ].nodeName.toUpperCase(), \"DIV\", \"DIV element cloned\" );\n\tdiv = div.find(\"object\");\n\tclone = clone.find(\"object\");\n\t// oldIE adds extra attributes and <param> elements, so just test for existence of the defined set\n\tjQuery.each( [ \"height\", \"width\", \"classid\" ], function( i, attr ) {\n\t\tequal( clone.attr( attr ), div.attr( attr ), \"<object> attribute cloned: \" + attr );\n\t} );\n\t(function() {\n\t\tvar params = {};\n\n\t\tclone.find(\"param\").each(function( index, param ) {\n\t\t\tparams[ param.attributes.name.nodeValue.toLowerCase() ] =\n\t\t\t\tparam.attributes.value.nodeValue.toLowerCase();\n\t\t});\n\n\t\tdiv.find(\"param\").each(function( index, param ) {\n\t\t\tvar key = param.attributes.name.nodeValue.toLowerCase();\n\t\t\tequal( params[ key ], param.attributes.value.nodeValue.toLowerCase(), \"<param> cloned: \" + key );\n\t\t});\n\t})();\n\n\t// and here's a valid one.\n\tdiv = jQuery(\"<div/>\").html(\"<object height='355' width='425' type='application/x-shockwave-flash' data='http://www.youtube.com/v/3KANI2dpXLw&amp;hl=en'>  <param name='movie' value='http://www.youtube.com/v/3KANI2dpXLw&amp;hl=en'>  <param name='wmode' value='transparent'> </object>\");\n\n\tclone = div.clone(true);\n\tequal( clone.length, 1, \"One element cloned\" );\n\tequal( clone.html(), div.html(), \"Element contents cloned\" );\n\tequal( clone[ 0 ].nodeName.toUpperCase(), \"DIV\", \"DIV element cloned\" );\n\n\tdiv = jQuery(\"<div/>\").data({ \"a\": true });\n\tclone = div.clone( true );\n\tequal( clone.data(\"a\"), true, \"Data cloned.\" );\n\tclone.data( \"a\", false );\n\tequal( clone.data(\"a\"), false, \"Ensure cloned element data object was correctly modified\" );\n\tequal( div.data(\"a\"), true, \"Ensure cloned element data object is copied, not referenced\" );\n\n\t// manually clean up detached elements\n\tdiv.remove();\n\tclone.remove();\n\n\tform = document.createElement(\"form\");\n\tform.action = \"/test/\";\n\n\tdiv = document.createElement(\"div\");\n\tdiv.appendChild( document.createTextNode(\"test\") );\n\tform.appendChild( div );\n\n\tequal( jQuery(form).clone().children().length, 1, \"Make sure we just get the form back.\" );\n\n\tbody = jQuery(\"body\").clone();\n\tequal( body.children()[ 0 ].id, \"qunit\", \"Make sure cloning body works\" );\n\tbody.remove();\n});\n\ntest( \"clone(script type=non-javascript) (#11359)\", function() {\n\n\texpect( 3 );\n\n\tvar src = jQuery(\"<script type='text/filler'>Lorem ipsum dolor sit amet</script><q><script type='text/filler'>consectetur adipiscing elit</script></q>\"),\n\t\tdest = src.clone();\n\n\tequal( dest[ 0 ].text, \"Lorem ipsum dolor sit amet\", \"Cloning preserves script text\" );\n\tequal( dest.last().html(), src.last().html(), \"Cloning preserves nested script text\" );\n\tok( /^\\s*<scr.pt\\s+type=['\"]?text\\/filler['\"]?\\s*>consectetur adipiscing elit<\\/scr.pt>\\s*$/i.test( dest.last().html() ), \"Cloning preserves nested script text\" );\n\tdest.remove();\n});\n\ntest( \"clone(form element) (Bug #3879, #6655)\", function() {\n\n\texpect( 5 );\n\n\tvar clone, element;\n\n\telement = jQuery(\"<select><option>Foo</option><option value='selected' selected>Bar</option></select>\");\n\n\tequal( element.clone().find(\"option\").filter(function() { return this.selected; }).val(), \"selected\", \"Selected option cloned correctly\" );\n\n\telement = jQuery(\"<input type='checkbox' value='foo'>\").attr( \"checked\", \"checked\" );\n\tclone = element.clone();\n\n\tequal( clone.is(\":checked\"), element.is(\":checked\"), \"Checked input cloned correctly\" );\n\tequal( clone[ 0 ].defaultValue, \"foo\", \"Checked input defaultValue cloned correctly\" );\n\n\telement = jQuery(\"<input type='text' value='foo'>\");\n\tclone = element.clone();\n\tequal( clone[ 0 ].defaultValue, \"foo\", \"Text input defaultValue cloned correctly\" );\n\n\telement = jQuery(\"<textarea>foo</textarea>\");\n\tclone = element.clone();\n\tequal( clone[ 0 ].defaultValue, \"foo\", \"Textarea defaultValue cloned correctly\" );\n});\n\ntest( \"clone(multiple selected options) (Bug #8129)\", function() {\n\n\texpect( 1 );\n\n\tvar element = jQuery(\"<select><option>Foo</option><option selected>Bar</option><option selected>Baz</option></select>\");\n\n\tequal( element.clone().find(\"option:selected\").length, element.find(\"option:selected\").length, \"Multiple selected options cloned correctly\" );\n\n});\n\ntest( \"clone() on XML nodes\", function() {\n\n\texpect( 2 );\n\n\tvar xml = createDashboardXML(),\n\t\troot = jQuery(xml.documentElement).clone(),\n\t\torigTab = jQuery(\"tab\", xml).eq( 0 ),\n\t\tcloneTab = jQuery(\"tab\", root).eq( 0 );\n\n\torigTab.text(\"origval\");\n\tcloneTab.text(\"cloneval\");\n\tequal( origTab.text(), \"origval\", \"Check original XML node was correctly set\" );\n\tequal( cloneTab.text(), \"cloneval\", \"Check cloned XML node was correctly set\" );\n});\n\ntest( \"clone() on local XML nodes with html5 nodename\", function() {\n\n\texpect( 2 );\n\n\tvar $xmlDoc = jQuery( jQuery.parseXML( \"<root><meter /></root>\" ) ),\n\t\t$meter = $xmlDoc.find( \"meter\" ).clone();\n\n\tequal( $meter[ 0 ].nodeName, \"meter\", \"Check if nodeName was not changed due to cloning\" );\n\tequal( $meter[ 0 ].nodeType, 1, \"Check if nodeType is not changed due to cloning\" );\n});\n\ntest( \"html(undefined)\", function() {\n\n\texpect( 1 );\n\n\tequal( jQuery(\"#foo\").html(\"<i>test</i>\").html(undefined).html().toLowerCase(), \"<i>test</i>\", \".html(undefined) is chainable (#5571)\" );\n});\n\ntest( \"html() on empty set\", function() {\n\n\texpect( 1 );\n\n\tstrictEqual( jQuery().html(), undefined, \".html() returns undefined for empty sets (#11962)\" );\n});\n\nfunction childNodeNames( node ) {\n\treturn jQuery.map( node.childNodes, function( child ) {\n\t\treturn child.nodeName.toUpperCase();\n\t}).join(\" \");\n}\n\nfunction testHtml( valueObj ) {\n\texpect( 37 );\n\n\tvar actual, expected, tmp,\n\t\tdiv = jQuery(\"<div></div>\"),\n\t\tfixture = jQuery(\"#qunit-fixture\");\n\n\tdiv.html( valueObj(\"<div id='parent_1'><div id='child_1'/></div><div id='parent_2'/>\") );\n\tequal( div.children().length, 2, \"Found children\" );\n\tequal( div.children().children().length, 1, \"Found grandchild\" );\n\n\tactual = []; expected = [];\n\ttmp = jQuery(\"<map/>\").html( valueObj(\"<area alt='area'/>\") ).each(function() {\n\t\texpected.push(\"AREA\");\n\t\tactual.push( childNodeNames( this ) );\n\t});\n\tequal( expected.length, 1, \"Expecting one parent\" );\n\tdeepEqual( actual, expected, \"Found the inserted area element\" );\n\n\tequal( div.html(valueObj(5)).html(), \"5\", \"Setting a number as html\" );\n\tequal( div.html(valueObj(0)).html(), \"0\", \"Setting a zero as html\" );\n\n\tdiv.html( valueObj(\"&#160;&amp;\") );\n\tequal(\n\t\tdiv[ 0 ].innerHTML.replace( /\\xA0/, \"&nbsp;\" ),\n\t\t\"&nbsp;&amp;\",\n\t\t\"Entities are passed through correctly\"\n\t);\n\n\ttmp = \"&lt;div&gt;hello1&lt;/div&gt;\";\n\tequal( div.html(valueObj(tmp) ).html().replace( />/g, \"&gt;\" ), tmp, \"Escaped html\" );\n\ttmp = \"x\" + tmp;\n\tequal( div.html(valueObj( tmp )).html().replace( />/g, \"&gt;\" ), tmp, \"Escaped html, leading x\" );\n\ttmp = \" \" + tmp.slice( 1 );\n\tequal( div.html(valueObj( tmp )).html().replace( />/g, \"&gt;\" ), tmp, \"Escaped html, leading space\" );\n\n\tactual = []; expected = []; tmp = {};\n\tjQuery(\"#nonnodes\").contents().html( valueObj(\"<b>bold</b>\") ).each(function() {\n\t\tvar html = jQuery( this ).html();\n\t\ttmp[ this.nodeType ] = true;\n\t\texpected.push( this.nodeType === 1 ? \"<b>bold</b>\" : undefined );\n\t\tactual.push( html ? html.toLowerCase() : html );\n\t});\n\tdeepEqual( actual, expected, \"Set containing element, text node, comment\" );\n\tok( tmp[ 1 ], \"element\" );\n\tok( tmp[ 3 ], \"text node\" );\n\tok( tmp[ 8 ], \"comment\" );\n\n\tactual = []; expected = [];\n\tfixture.children(\"div\").html( valueObj(\"<b>test</b>\") ).each(function() {\n\t\texpected.push(\"B\");\n\t\tactual.push( childNodeNames( this ) );\n\t});\n\tequal( expected.length, 7, \"Expecting many parents\" );\n\tdeepEqual( actual, expected, \"Correct childNodes after setting HTML\" );\n\n\tactual = []; expected = [];\n\tfixture.html( valueObj(\"<style>.foobar{color:green;}</style>\") ).each(function() {\n\t\texpected.push(\"STYLE\");\n\t\tactual.push( childNodeNames( this ) );\n\t});\n\tequal( expected.length, 1, \"Expecting one parent\" );\n\tdeepEqual( actual, expected, \"Found the inserted style element\" );\n\n\tfixture.html( valueObj(\"<select/>\") );\n\tjQuery(\"#qunit-fixture select\").html( valueObj(\"<option>O1</option><option selected='selected'>O2</option><option>O3</option>\") );\n\tequal( jQuery(\"#qunit-fixture select\").val(), \"O2\", \"Selected option correct\" );\n\n\ttmp = fixture.html(\n\t\tvalueObj([\n\t\t\t\"<script type='something/else'>ok( false, 'evaluated: non-script' );</script>\",\n\t\t\t\"<script type='text/javascript'>ok( true, 'evaluated: text/javascript' );</script>\",\n\t\t\t\"<script type='text/ecmascript'>ok( true, 'evaluated: text/ecmascript' );</script>\",\n\t\t\t\"<script>ok( true, 'evaluated: no type' );</script>\",\n\t\t\t\"<div>\",\n\t\t\t\t\"<script type='something/else'>ok( false, 'evaluated: inner non-script' );</script>\",\n\t\t\t\t\"<script type='text/javascript'>ok( true, 'evaluated: inner text/javascript' );</script>\",\n\t\t\t\t\"<script type='text/ecmascript'>ok( true, 'evaluated: inner text/ecmascript' );</script>\",\n\t\t\t\t\"<script>ok( true, 'evaluated: inner no type' );</script>\",\n\t\t\t\"</div>\"\n\t\t].join(\"\"))\n\t).find(\"script\");\n\tequal( tmp.length, 8, \"All script tags remain.\" );\n\tequal( tmp[ 0 ].type, \"something/else\", \"Non-evaluated type.\" );\n\tequal( tmp[ 1 ].type, \"text/javascript\", \"Evaluated type.\" );\n\n\tfixture.html( valueObj(\"<script type='text/javascript'>ok( true, 'Injection of identical script' );</script>\") );\n\tfixture.html( valueObj(\"<script type='text/javascript'>ok( true, 'Injection of identical script' );</script>\") );\n\tfixture.html( valueObj(\"<script type='text/javascript'>ok( true, 'Injection of identical script' );</script>\") );\n\tfixture.html( valueObj(\"foo <form><script type='text/javascript'>ok( true, 'Injection of identical script (#975)' );</script></form>\") );\n\n\tjQuery.scriptorder = 0;\n\tfixture.html( valueObj([\n\t\t\"<script>\",\n\t\t\t\"equal( jQuery('#scriptorder').length, 1,'Execute after html' );\",\n\t\t\t\"equal( jQuery.scriptorder++, 0, 'Script is executed in order' );\",\n\t\t\"</script>\",\n\t\t\"<span id='scriptorder'><script>equal( jQuery.scriptorder++, 1, 'Script (nested) is executed in order');</script></span>\",\n\t\t\"<script>equal( jQuery.scriptorder++, 2, 'Script (unnested) is executed in order' );</script>\"\n\t].join(\"\")) );\n\n\tQUnit.reset();\n\tfixture.html( valueObj( fixture.text() ) );\n\tok( /^[^<]*[^<\\s][^<]*$/.test( fixture.html() ), \"Replace html with text\" );\n}\n\ntest( \"html(String)\", function() {\n\ttestHtml( manipulationBareObj );\n});\n\ntest( \"html(Function)\", function() {\n\ttestHtml( manipulationFunctionReturningObj );\n});\n\ntest( \"html(Function) with incoming value\", function() {\n\n\texpect( 18 );\n\n\tvar els, actualhtml, pass, j, $div, $div2, insert;\n\n\tels = jQuery(\"#foo > p\");\n\tactualhtml = els.map(function() {\n\t\treturn jQuery( this ).html();\n\t});\n\n\tels.html(function( i, val ) {\n\t\tequal( val, actualhtml[ i ], \"Make sure the incoming value is correct.\" );\n\t\treturn \"<b>test</b>\";\n\t});\n\n\tpass = true;\n\tels.each(function() {\n\t\tif ( this.childNodes.length !== 1 ) {\n\t\t\tpass = false;\n\t\t}\n\t});\n\tok( pass, \"Set HTML\" );\n\n\tQUnit.reset();\n\t// using contents will get comments regular, text, and comment nodes\n\tj = jQuery(\"#nonnodes\").contents();\n\tactualhtml = j.map(function() {\n\t\treturn jQuery( this ).html();\n\t});\n\n\tj.html(function( i, val ) {\n\t\tequal( val, actualhtml[ i ], \"Make sure the incoming value is correct.\" );\n\t\treturn \"<b>bold</b>\";\n\t});\n\n\t// Handle the case where no comment is in the document\n\tif ( j.length === 2 ) {\n\t\tequal( null, null, \"Make sure the incoming value is correct.\" );\n\t}\n\n\tequal( j.html().replace( / xmlns=\"[^\"]+\"/g, \"\" ).toLowerCase(), \"<b>bold</b>\", \"Check node,textnode,comment with html()\" );\n\n\t$div = jQuery(\"<div />\");\n\n\tequal( $div.html(function( i, val ) {\n\t\tequal( val, \"\", \"Make sure the incoming value is correct.\" );\n\t\treturn 5;\n\t}).html(), \"5\", \"Setting a number as html\" );\n\n\tequal( $div.html(function( i, val ) {\n\t\tequal( val, \"5\", \"Make sure the incoming value is correct.\" );\n\t\treturn 0;\n\t}).html(), \"0\", \"Setting a zero as html\" );\n\n\t$div2 = jQuery(\"<div/>\");\n\tinsert = \"&lt;div&gt;hello1&lt;/div&gt;\";\n\tequal( $div2.html(function( i, val ) {\n\t\tequal( val, \"\", \"Make sure the incoming value is correct.\" );\n\t\treturn insert;\n\t}).html().replace(/>/g, \"&gt;\"), insert, \"Verify escaped insertion.\" );\n\n\tequal( $div2.html(function( i, val ) {\n\t\tequal( val.replace(/>/g, \"&gt;\"), insert, \"Make sure the incoming value is correct.\" );\n\t\treturn \"x\" + insert;\n\t}).html().replace( />/g, \"&gt;\" ), \"x\" + insert, \"Verify escaped insertion.\" );\n\n\tequal( $div2.html(function( i, val ) {\n\t\tequal( val.replace( />/g, \"&gt;\" ), \"x\" + insert, \"Make sure the incoming value is correct.\" );\n\t\treturn \" \" + insert;\n\t}).html().replace( />/g, \"&gt;\" ), \" \" + insert, \"Verify escaped insertion.\" );\n});\n\ntest( \"clone()/html() don't expose jQuery/Sizzle expandos (#12858)\", function() {\n\n\texpect( 2 );\n\n\tvar $content = jQuery(\"<div><b><i>text</i></b></div>\").appendTo(\"#qunit-fixture\"),\n\t\texpected = /^<b><i>text<\\/i><\\/b>$/i;\n\n\t// Attach jQuery and Sizzle data (the latter with a non-qSA nth-child)\n\ttry {\n\t\t$content.find(\":nth-child(1):lt(4)\").data( \"test\", true );\n\n\t// But don't break on a non-Sizzle build\n\t} catch( e ) {\n\t\t$content.find(\"*\").data( \"test\", true );\n\t}\n\n\tok( expected.test( $content.clone( false )[ 0 ].innerHTML ), \"clone()\" );\n\tok( expected.test( $content.html() ), \"html()\" );\n});\n\nfunction testRemove( method ) {\n\tvar markup, div,\n\t\tfirst = jQuery(\"#ap\").children().first();\n\n\tfirst.data(\"foo\", \"bar\");\n\n\tjQuery(\"#ap\").children()[ method ]();\n\tok( jQuery(\"#ap\").text().length > 10, \"Check text is not removed\" );\n\tequal( jQuery(\"#ap\").children().length, 0, \"Check remove\" );\n\n\tequal( first.data(\"foo\"), method === \"remove\" ? null : \"bar\", \"first data\" );\n\n\tQUnit.reset();\n\tjQuery(\"#ap\").children()[ method ](\"a\");\n\tok( jQuery(\"#ap\").text().length > 10, \"Check text is not removed\" );\n\tequal( jQuery(\"#ap\").children().length, 1, \"Check filtered remove\" );\n\n\tjQuery(\"#ap\").children()[ method ](\"a, code\");\n\tequal( jQuery(\"#ap\").children().length, 0, \"Check multi-filtered remove\" );\n\n\t// Positional and relative selectors\n\tmarkup = \"<div><span>1</span><span>2</span><span>3</span><span>4</span></div>\";\n\tdiv = jQuery( markup );\n\tdiv.children().remove(\"span:nth-child(2n)\");\n\tequal( div.text(), \"13\", \"relative selector in \" + method );\n\tdiv = jQuery( markup );\n\tdiv.children().remove(\"span:first\");\n\tequal( div.text(), \"234\", \"positional selector in \" + method );\n\tdiv = jQuery( markup );\n\tdiv.children().remove(\"span:last\");\n\tequal( div.text(), \"123\", \"positional selector in \" + method );\n\n\t// using contents will get comments regular, text, and comment nodes\n\t// Handle the case where no comment is in the document\n\tok( jQuery(\"#nonnodes\").contents().length >= 2, \"Check node,textnode,comment remove works\" );\n\tjQuery(\"#nonnodes\").contents()[ method ]();\n\tequal( jQuery(\"#nonnodes\").contents().length, 0, \"Check node,textnode,comment remove works\" );\n\n\t// manually clean up detached elements\n\tif (method === \"detach\") {\n\t\tfirst.remove();\n\t}\n}\n\ntest( \"remove()\", 11, function() {\n\ttestRemove(\"remove\");\n});\n\ntest( \"remove() event cleaning \", 1, function() {\n\tvar count, first, cleanUp;\n\n\tcount = 0;\n\tfirst = jQuery(\"#ap\").children().first();\n\tcleanUp = first.on( \"click\", function() {\n\t\tcount++;\n\t}).remove().appendTo(\"#qunit-fixture\").trigger(\"click\");\n\n\tstrictEqual( 0, count, \"Event handler has been removed\" );\n\n\t// Clean up detached data\n\tcleanUp.remove();\n});\n\ntest( \"remove() in document order #13779\", 1, function() {\n\tvar last,\n\t\tcleanData = jQuery.cleanData;\n\n\tjQuery.cleanData = function( nodes ) {\n\t\tlast = jQuery.text( nodes[0] );\n\t\tcleanData.call( this, nodes );\n\t};\n\n\tjQuery(\"#qunit-fixture\").append(\n\t\tjQuery.parseHTML(\n\t\t\t\"<div class='removal-fixture'>1</div>\" +\n\t\t\t\"<div class='removal-fixture'>2</div>\" +\n\t\t\t\"<div class='removal-fixture'>3</div>\"\n\t\t)\n\t);\n\n\tjQuery(\".removal-fixture\").remove();\n\n\tequal( last, 3, \"The removal fixtures were removed in document order\" );\n\n\tjQuery.cleanData = cleanData;\n});\n\ntest( \"detach()\", 11, function() {\n\ttestRemove(\"detach\");\n});\n\ntest( \"detach() event cleaning \", 1, function() {\n\tvar count, first, cleanUp;\n\n\tcount = 0;\n\tfirst = jQuery(\"#ap\").children().first();\n\tcleanUp = first.on( \"click\", function() {\n\t\tcount++;\n\t}).detach().appendTo(\"#qunit-fixture\").trigger(\"click\");\n\n\tstrictEqual( 1, count, \"Event handler has not been removed\" );\n\n\t// Clean up detached data\n\tcleanUp.remove();\n});\n\ntest(\"empty()\", function() {\n\n\texpect( 3 );\n\n\tequal( jQuery(\"#ap\").children().empty().text().length, 0, \"Check text is removed\" );\n\tequal( jQuery(\"#ap\").children().length, 4, \"Check elements are not removed\" );\n\n\t// using contents will get comments regular, text, and comment nodes\n\tvar j = jQuery(\"#nonnodes\").contents();\n\tj.empty();\n\tequal( j.html(), \"\", \"Check node,textnode,comment empty works\" );\n});\n\ntest( \"jQuery.cleanData\", function() {\n\n\texpect( 14 );\n\n\tvar type, pos, div, child;\n\n\ttype = \"remove\";\n\n\t// Should trigger 4 remove event\n\tdiv = getDiv().remove();\n\n\t// Should both do nothing\n\tpos = \"Outer\";\n\tdiv.trigger(\"click\");\n\n\tpos = \"Inner\";\n\tdiv.children().trigger(\"click\");\n\n\ttype = \"empty\";\n\tdiv = getDiv();\n\tchild = div.children();\n\n\t// Should trigger 2 remove event\n\tdiv.empty();\n\n\t// Should trigger 1\n\tpos = \"Outer\";\n\tdiv.trigger(\"click\");\n\n\t// Should do nothing\n\tpos = \"Inner\";\n\tchild.trigger(\"click\");\n\n\t// Should trigger 2\n\tdiv.remove();\n\n\ttype = \"html\";\n\n\tdiv = getDiv();\n\tchild = div.children();\n\n\t// Should trigger 2 remove event\n\tdiv.html(\"<div></div>\");\n\n\t// Should trigger 1\n\tpos = \"Outer\";\n\tdiv.trigger(\"click\");\n\n\t// Should do nothing\n\tpos = \"Inner\";\n\tchild.trigger(\"click\");\n\n\t// Should trigger 2\n\tdiv.remove();\n\n\tfunction getDiv() {\n\t\tvar div = jQuery(\"<div class='outer'><div class='inner'></div></div>\").on( \"click\", function() {\n\t\t\tok( true, type + \" \" + pos + \" Click event fired.\" );\n\t\t}).on( \"focus\", function() {\n\t\t\tok( true, type + \" \" + pos + \" Focus event fired.\" );\n\t\t}).find(\"div\").on( \"click\", function() {\n\t\t\tok( false, type + \" \" + pos + \" Click event fired.\" );\n\t\t}).on( \"focus\", function() {\n\t\t\tok( false, type + \" \" + pos + \" Focus event fired.\" );\n\t\t}).end().appendTo(\"body\");\n\n\t\tdiv[ 0 ].detachEvent = div[ 0 ].removeEventListener = function( t ) {\n\t\t\tok( true, type + \" Outer \" + t + \" event unbound\" );\n\t\t};\n\n\t\tdiv[ 0 ].firstChild.detachEvent = div[ 0 ].firstChild.removeEventListener = function( t ) {\n\t\t\tok( true, type + \" Inner \" + t + \" event unbound\" );\n\t\t};\n\n\t\treturn div;\n\t}\n});\n\ntest( \"jQuery.buildFragment - no plain-text caching (Bug #6779)\", function() {\n\n\texpect( 1 );\n\n\t// DOM manipulation fails if added text matches an Object method\n\tvar i,\n\t\t$f = jQuery( \"<div />\" ).appendTo( \"#qunit-fixture\" ),\n\t\tbad = [ \"start-\", \"toString\", \"hasOwnProperty\", \"append\", \"here&there!\", \"-end\" ];\n\n\tfor ( i = 0; i < bad.length; i++ ) {\n\t\ttry {\n\t\t\t$f.append( bad[ i ] );\n\t\t}\n\t\tcatch( e ) {}\n\t}\n\tequal( $f.text(), bad.join(\"\"), \"Cached strings that match Object properties\" );\n\t$f.remove();\n});\n\ntest( \"jQuery.html - execute scripts escaped with html comment or CDATA (#9221)\", function() {\n\n\texpect( 3 );\n\n\tjQuery([\n\t\t\t\t\"<script type='text/javascript'>\",\n\t\t\t\t\"<!--\",\n\t\t\t\t\"ok( true, '<!-- handled' );\",\n\t\t\t\t\"//-->\",\n\t\t\t\t\"</script>\"\n\t\t\t].join(\"\\n\")).appendTo(\"#qunit-fixture\");\n\tjQuery([\n\t\t\t\t\"<script type='text/javascript'>\",\n\t\t\t\t\"<![CDATA[\",\n\t\t\t\t\"ok( true, '<![CDATA[ handled' );\",\n\t\t\t\t\"//]]>\",\n\t\t\t\t\"</script>\"\n\t\t\t].join(\"\\n\")).appendTo(\"#qunit-fixture\");\n\tjQuery([\n\t\t\t\t\"<script type='text/javascript'>\",\n\t\t\t\t\"<!--//--><![CDATA[//><!--\",\n\t\t\t\t\"ok( true, '<!--//--><![CDATA[//><!-- (Drupal case) handled' );\",\n\t\t\t\t\"//--><!]]>\",\n\t\t\t\t\"</script>\"\n\t\t\t].join(\"\\n\")).appendTo(\"#qunit-fixture\");\n});\n\ntest( \"jQuery.buildFragment - plain objects are not a document #8950\", function() {\n\n\texpect( 1 );\n\n\ttry {\n\t\tjQuery( \"<input type='hidden'>\", {} );\n\t\tok( true, \"Does not allow attribute object to be treated like a doc object\" );\n\t} catch ( e ) {}\n});\n\ntest( \"jQuery.clone - no exceptions for object elements #9587\", function() {\n\n\texpect( 1 );\n\n\ttry {\n\t\tjQuery(\"#no-clone-exception\").clone();\n\t\tok( true, \"cloned with no exceptions\" );\n\t} catch( e ) {\n\t\tok( false, e.message );\n\t}\n});\n\ntest( \"Cloned, detached HTML5 elems (#10667,10670)\", function() {\n\n\texpect( 7 );\n\n\tvar $clone,\n\t\t$section = jQuery( \"<section>\" ).appendTo( \"#qunit-fixture\" );\n\n\t// First clone\n\t$clone = $section.clone();\n\n\t// Infer that the test is being run in IE<=8\n\tif ( $clone[ 0 ].outerHTML && !jQuery.support.opacity ) {\n\t\t// This branch tests cloning nodes by reading the outerHTML, used only in IE<=8\n\t\tequal( $clone[ 0 ].outerHTML, \"<section></section>\", \"detached clone outerHTML matches '<section></section>'\" );\n\t} else {\n\t\t// This branch tests a known behaviour in modern browsers that should never fail.\n\t\t// Included for expected test count symmetry (expecting 1)\n\t\tequal( $clone[ 0 ].nodeName, \"SECTION\", \"detached clone nodeName matches 'SECTION' in modern browsers\" );\n\t}\n\n\t// Bind an event\n\t$section.on( \"click\", function() {\n\t\tok( true, \"clone fired event\" );\n\t});\n\n\t// Second clone (will have an event bound)\n\t$clone = $section.clone( true );\n\n\t// Trigger an event from the first clone\n\t$clone.trigger(\"click\");\n\t$clone.off(\"click\");\n\n\t// Add a child node with text to the original\n\t$section.append(\"<p>Hello</p>\");\n\n\t// Third clone (will have child node and text)\n\t$clone = $section.clone( true );\n\n\tequal( $clone.find(\"p\").text(), \"Hello\", \"Assert text in child of clone\" );\n\n\t// Trigger an event from the third clone\n\t$clone.trigger(\"click\");\n\t$clone.off(\"click\");\n\n\t// Add attributes to copy\n\t$section.attr({\n\t\t\"class\": \"foo bar baz\",\n\t\t\"title\": \"This is a title\"\n\t});\n\n\t// Fourth clone (will have newly added attributes)\n\t$clone = $section.clone( true );\n\n\tequal( $clone.attr(\"class\"), $section.attr(\"class\"), \"clone and element have same class attribute\" );\n\tequal( $clone.attr(\"title\"), $section.attr(\"title\"), \"clone and element have same title attribute\" );\n\n\t// Remove the original\n\t$section.remove();\n\n\t// Clone the clone\n\t$section = $clone.clone( true );\n\n\t// Remove the clone\n\t$clone.remove();\n\n\t// Trigger an event from the clone of the clone\n\t$section.trigger(\"click\");\n\n\t// Unbind any remaining events\n\t$section.off(\"click\");\n\t$clone.off(\"click\");\n});\n\ntest( \"Guard against exceptions when clearing safeChildNodes\", function() {\n\n\texpect( 1 );\n\n\tvar div;\n\n\ttry {\n\t\tdiv = jQuery(\"<div/><hr/><code/><b/>\");\n\t} catch(e) {}\n\n\tok( div && div.jquery, \"Created nodes safely, guarded against exceptions on safeChildNodes[ -1 ]\" );\n});\n\ntest( \"Ensure oldIE creates a new set on appendTo (#8894)\", function() {\n\n\texpect( 5 );\n\n\tstrictEqual( jQuery(\"<div/>\").clone().addClass(\"test\").appendTo(\"<div/>\").end().end().hasClass(\"test\"), false, \"Check jQuery.fn.appendTo after jQuery.clone\" );\n\tstrictEqual( jQuery(\"<div/>\").find(\"p\").end().addClass(\"test\").appendTo(\"<div/>\").end().end().hasClass(\"test\"), false, \"Check jQuery.fn.appendTo after jQuery.fn.find\" );\n\tstrictEqual( jQuery(\"<div/>\").text(\"test\").addClass(\"test\").appendTo(\"<div/>\").end().end().hasClass(\"test\"), false, \"Check jQuery.fn.appendTo after jQuery.fn.text\" );\n\tstrictEqual( jQuery(\"<bdi/>\").clone().addClass(\"test\").appendTo(\"<div/>\").end().end().hasClass(\"test\"), false, \"Check jQuery.fn.appendTo after clone html5 element\" );\n\tstrictEqual( jQuery(\"<p/>\").appendTo(\"<div/>\").end().length, jQuery(\"<p>test</p>\").appendTo(\"<div/>\").end().length, \"Elements created with createElement and with createDocumentFragment should be treated alike\" );\n});\n\ntest( \"html() - script exceptions bubble (#11743)\", function() {\n\n\texpect( 3 );\n\n\traises(function() {\n\t\tjQuery(\"#qunit-fixture\").html(\"<script>undefined(); ok( false, 'Exception not thrown' );</script>\");\n\t\tok( false, \"Exception ignored\" );\n\t}, \"Exception bubbled from inline script\" );\n\n\tif ( jQuery.ajax ) {\n\t\tvar onerror = window.onerror;\n\t\twindow.onerror = function() {\n\t\t\tok( true, \"Exception thrown in remote script\" );\n\t\t};\n\n\t\tjQuery(\"#qunit-fixture\").html(\"<script src='data/badcall.js'></script>\");\n\t\tok( true, \"Exception ignored\" );\n\t\twindow.onerror = onerror;\n\t} else {\n\t\tok( true, \"No jQuery.ajax\" );\n\t\tok( true, \"No jQuery.ajax\" );\n\t}\n});\n\ntest( \"checked state is cloned with clone()\", function() {\n\n\texpect( 2 );\n\n\tvar elem = jQuery.parseHTML(\"<input type='checkbox' checked='checked'/>\")[ 0 ];\n\telem.checked = false;\n\tequal( jQuery(elem).clone().attr(\"id\",\"clone\")[ 0 ].checked, false, \"Checked false state correctly cloned\" );\n\n\telem = jQuery.parseHTML(\"<input type='checkbox'/>\")[ 0 ];\n\telem.checked = true;\n\tequal( jQuery(elem).clone().attr(\"id\",\"clone\")[ 0 ].checked, true, \"Checked true state correctly cloned\" );\n});\n\ntest( \"manipulate mixed jQuery and text (#12384, #12346)\", function() {\n\n\texpect( 2 );\n\n\tvar div = jQuery(\"<div>a</div>\").append( \"&nbsp;\", jQuery(\"<span>b</span>\"), \"&nbsp;\", jQuery(\"<span>c</span>\") ),\n\t\tnbsp = String.fromCharCode( 160 );\n\n\tequal( div.text(), \"a\" + nbsp + \"b\" + nbsp+ \"c\", \"Appending mixed jQuery with text nodes\" );\n\n\tdiv = jQuery(\"<div><div></div></div>\")\n\t\t.find(\"div\")\n\t\t.after( \"<p>a</p>\", \"<p>b</p>\" )\n\t\t.parent();\n\tequal( div.find(\"*\").length, 3, \"added 2 paragraphs after inner div\" );\n});\n\ntestIframeWithCallback( \"buildFragment works even if document[0] is iframe's window object in IE9/10 (#12266)\", \"manipulation/iframe-denied.html\", function( test ) {\n\texpect( 1 );\n\n\tok( test.status, test.description );\n});\n\ntest( \"script evaluation (#11795)\", function() {\n\n\texpect( 13 );\n\n\tvar scriptsIn, scriptsOut,\n\t\tfixture = jQuery(\"#qunit-fixture\").empty(),\n\t\tobjGlobal = (function() {\n\t\t\treturn this;\n\t\t})(),\n\t\tisOk = objGlobal.ok,\n\t\tnotOk = function() {\n\t\t\tvar args = arguments;\n\t\t\targs[ 0 ] = !args[ 0 ];\n\t\t\treturn isOk.apply( this, args );\n\t\t};\n\n\tobjGlobal.ok = notOk;\n\tscriptsIn = jQuery([\n\t\t\"<script type='something/else'>ok( false, 'evaluated: non-script' );</script>\",\n\t\t\"<script type='text/javascript'>ok( true, 'evaluated: text/javascript' );</script>\",\n\t\t\"<script type='text/ecmascript'>ok( true, 'evaluated: text/ecmascript' );</script>\",\n\t\t\"<script>ok( true, 'evaluated: no type' );</script>\",\n\t\t\"<div>\",\n\t\t\t\"<script type='something/else'>ok( false, 'evaluated: inner non-script' );</script>\",\n\t\t\t\"<script type='text/javascript'>ok( true, 'evaluated: inner text/javascript' );</script>\",\n\t\t\t\"<script type='text/ecmascript'>ok( true, 'evaluated: inner text/ecmascript' );</script>\",\n\t\t\t\"<script>ok( true, 'evaluated: inner no type' );</script>\",\n\t\t\"</div>\"\n\t].join(\"\"));\n\tscriptsIn.appendTo( jQuery(\"<div class='detached'/>\") );\n\tobjGlobal.ok = isOk;\n\n\tscriptsOut = fixture.append( scriptsIn ).find(\"script\");\n\tequal( scriptsOut[ 0 ].type, \"something/else\", \"Non-evaluated type.\" );\n\tequal( scriptsOut[ 1 ].type, \"text/javascript\", \"Evaluated type.\" );\n\tdeepEqual( scriptsOut.get(), fixture.find(\"script\").get(), \"All script tags remain.\" );\n\n\tobjGlobal.ok = notOk;\n\tscriptsOut = scriptsOut.add( scriptsOut.clone() ).appendTo( fixture.find(\"div\") );\n\tdeepEqual( fixture.find(\"div script\").get(), scriptsOut.get(), \"Scripts cloned without reevaluation\" );\n\tfixture.append( scriptsOut.detach() );\n\tdeepEqual( fixture.children(\"script\").get(), scriptsOut.get(), \"Scripts detached without reevaluation\" );\n\tobjGlobal.ok = isOk;\n\n\tif ( jQuery.ajax ) {\n\t\tGlobals.register(\"testBar\");\n\t\tjQuery(\"#qunit-fixture\").append( \"<script src='\" + url(\"data/test.js\") + \"'/>\" );\n\t\tstrictEqual( window[\"testBar\"], \"bar\", \"Global script evaluation\" );\n\t} else {\n\t\tok( true, \"No jQuery.ajax\" );\n\t\tok( true, \"No jQuery.ajax\" );\n\t}\n});\n\ntest( \"jQuery._evalUrl (#12838)\", function() {\n\n\texpect( 5 );\n\n\tvar message, expectedArgument,\n\t\tajax = jQuery.ajax,\n\t\tevalUrl = jQuery._evalUrl;\n\n\tmessage = \"jQuery.ajax implementation\";\n\texpectedArgument = 1;\n\tjQuery.ajax = function( input ) {\n\t\tequal( ( input.url || input ).slice( -1 ), expectedArgument, message );\n\t\texpectedArgument++;\n\t};\n\tjQuery(\"#qunit-fixture\").append(\"<script src='1'/><script src='2'/>\");\n\tequal( expectedArgument, 3, \"synchronous execution\" );\n\n\tmessage = \"custom implementation\";\n\texpectedArgument = 3;\n\tjQuery._evalUrl = jQuery.ajax;\n\tjQuery.ajax = function( options ) {\n\t\tstrictEqual( options, {}, \"Unexpected call to jQuery.ajax\" );\n\t};\n\tjQuery(\"#qunit-fixture\").append(\"<script src='3'/><script src='4'/>\");\n\n\tjQuery.ajax = ajax;\n\tjQuery._evalUrl = evalUrl;\n});\n\ntest( \"insertAfter, insertBefore, etc do not work when destination is original element. Element is removed (#4087)\", function() {\n\n\texpect( 10 );\n\n\tvar elems;\n\n\tjQuery.each([\n\t\t\"appendTo\",\n\t\t\"prependTo\",\n\t\t\"insertBefore\",\n\t\t\"insertAfter\",\n\t\t\"replaceAll\"\n\t], function( index, name ) {\n\t\telems = jQuery( [\n\t\t\t\"<ul id='test4087-complex'><li class='test4087'><div>c1</div>h1</li><li><div>c2</div>h2</li></ul>\",\n\t\t\t\"<div id='test4087-simple'><div class='test4087-1'>1<div class='test4087-2'>2</div><div class='test4087-3'>3</div></div></div>\",\n\t\t\t\"<div id='test4087-multiple'><div class='test4087-multiple'>1</div><div class='test4087-multiple'>2</div></div>\"\n\t\t].join(\"\") ).appendTo( \"#qunit-fixture\" );\n\n\t\t// complex case based on http://jsfiddle.net/pbramos/gZ7vB/\n\t\tjQuery(\"#test4087-complex div\")[ name ](\"#test4087-complex li:last-child div:last-child\");\n\t\tequal( jQuery(\"#test4087-complex li:last-child div\").length, name === \"replaceAll\" ? 1 : 2, name +\" a node to itself, complex case.\" );\n\n\t\t// simple case\n\t\tjQuery( \".test4087-1\" )[ name ](\".test4087-1\");\n\t\tequal( jQuery(\".test4087-1\").length, 1, name +\" a node to itself, simple case.\" );\n\n\t\t// clean for next test\n\t\tjQuery(\"#test4087-complex\").remove();\n\t\tjQuery(\"#test4087-simple\").remove();\n\t\tjQuery(\"#test4087-multiple\").remove();\n\t});\n});\n\ntest( \"Index for function argument should be received (#13094)\", 2, function() {\n\tvar i = 0;\n\n\tjQuery(\"<div/><div/>\").before(function( index ) {\n\t\tequal( index, i++, \"Index should be correct\" );\n\t});\n\n});\n\ntest( \"Make sure jQuery.fn.remove can work on elements in documentFragment\", 1, function() {\n\tvar fragment = document.createDocumentFragment(),\n\t\tdiv = fragment.appendChild( document.createElement(\"div\") );\n\n\tjQuery( div ).remove();\n\n\tequal( fragment.childNodes.length, 0, \"div element was removed from documentFragment\" );\n});\n\ntest( \"Make sure specific elements with content created correctly (#13232)\", 20, function() {\n\tvar results = [],\n\t\targs = [],\n\t\telems = {\n\t\t\tthead: \"<tr><td>thead</td></tr>\",\n\t\t\ttbody: \"<tr><td>tbody</td></tr>\",\n\t\t\ttfoot: \"<tr><td>tfoot</td></tr>\",\n\t\t\tcolgroup: \"<col span='5' />\",\n\t\t\tcaption: \"caption\",\n\t\t\ttr: \"<td>tr</td>\",\n\t\t\tth: \"th\",\n\t\t\ttd: \"<div>td</div>\",\n\t\t\toptgroup: \"<option>optgroup</option>\",\n\t\t\toption: \"option\"\n\t\t};\n\n\tjQuery.each( elems, function( name, value ) {\n\t\tvar html = \"<\" + name + \">\" + value + \"</\" + name + \">\";\n\t\tok( jQuery.nodeName( jQuery.parseHTML( \"<\" + name + \">\" + value + \"</\" + name + \">\" )[ 0 ], name ), name + \" is created correctly\" );\n\n\t\tresults.push( name );\n\t\targs.push( html );\n\t});\n\n\tjQuery.fn.append.apply( jQuery(\"<div/>\"), args ).children().each(function( i ) {\n\t\tok( jQuery.nodeName( this, results[ i ] ) );\n\t});\n});\n\ntest( \"Validate creation of multiple quantities of certain elements (#13818)\", 44, function() {\n\tvar tags = [ \"thead\", \"tbody\", \"tfoot\", \"colgroup\", \"col\", \"caption\", \"tr\", \"th\", \"td\", \"optgroup\", \"option\" ];\n\n\tjQuery.each( tags, function( index, tag ) {\n\t\tjQuery( \"<\" + tag + \"/><\" + tag + \"/>\" ).each(function() {\n\t\t\tok( jQuery.nodeName( this, tag ), tag + \" empty elements created correctly\" );\n\t\t});\n\n\t\tjQuery( \"<\" + this + \"></\" + tag + \"><\" + tag + \"></\" + tag + \">\" ).each(function() {\n\t\t\tok( jQuery.nodeName( this, tag ), tag + \" elements with closing tag created correctly\" );\n\t\t});\n\t});\n});\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/jquery/test/unit/offset.js",
    "content": "(function() {\n\nif ( !jQuery.fn.offset ) {\n\treturn;\n}\n\nvar supportsScroll, supportsFixedPosition,\n\tforceScroll = jQuery(\"<div/>\").css({ width: 2000, height: 2000 }),\n\tcheckSupport = function() {\n\t\t// Only run once\n\t\tcheckSupport = false;\n\n\t\tvar checkFixed = jQuery(\"<div/>\").css({ position: \"fixed\", top: \"20px\" }).appendTo(\"#qunit-fixture\");\n\n\t\t// Must append to body because #qunit-fixture is hidden and elements inside it don't have a scrollTop\n\t\tforceScroll.appendTo(\"body\");\n\t\twindow.scrollTo( 200, 200 );\n\t\tsupportsScroll = document.documentElement.scrollTop || document.body.scrollTop;\n\t\tforceScroll.detach();\n\n\t\tsupportsFixedPosition = checkFixed[0].offsetTop === 20;\n\t\tcheckFixed.remove();\n\t};\n\nmodule(\"offset\", { setup: function(){\n\tif ( typeof checkSupport === \"function\" ) {\n\t\tcheckSupport();\n\t}\n\n\t// Force a scroll value on the main window to ensure incorrect results\n\t// if offset is using the scroll offset of the parent window\n\tforceScroll.appendTo(\"body\");\n\twindow.scrollTo( 1, 1 );\n\tforceScroll.detach();\n}, teardown: moduleTeardown });\n\n/*\n\tClosure-compiler will roll static methods off of the jQuery object and so they will\n\tnot be passed with the jQuery object across the windows. To differentiate this, the\n\ttestIframe callbacks use the \"$\" symbol to refer to the jQuery object passed from\n\tthe iframe window and the \"jQuery\" symbol is used to access any static methods.\n*/\n\ntest(\"empty set\", function() {\n\texpect(2);\n\tstrictEqual( jQuery().offset(), undefined, \"offset() returns undefined for empty set (#11962)\" );\n\tstrictEqual( jQuery().position(), undefined, \"position() returns undefined for empty set (#11962)\" );\n});\n\ntest(\"object without getBoundingClientRect\", function() {\n\texpect(2);\n\n\t// Simulates a browser without gBCR on elements, we just want to return 0,0\n\tvar result = jQuery({ ownerDocument: document }).offset();\n\tequal( result.top, 0, \"Check top\" );\n\tequal( result.left, 0, \"Check left\" );\n});\n\ntest(\"disconnected node\", function() {\n\texpect(2);\n\n\tvar result = jQuery( document.createElement(\"div\") ).offset();\n\n\tequal( result.top, 0, \"Check top\" );\n\tequal( result.left, 0, \"Check left\" );\n});\n\ntestIframe(\"offset/absolute\", \"absolute\", function($, iframe) {\n\texpect(4);\n\n\tvar doc = iframe.document,\n\t\t\ttests;\n\n\t// get offset\n\ttests = [\n\t\t{ \"id\": \"#absolute-1\", \"top\": 1, \"left\": 1 }\n\t];\n\tjQuery.each( tests, function() {\n\t\tequal( jQuery( this[\"id\"], doc ).offset().top,  this[\"top\"],  \"jQuery('\" + this[\"id\"] + \"').offset().top\" );\n\t\tequal( jQuery( this[\"id\"], doc ).offset().left, this[\"left\"], \"jQuery('\" + this[\"id\"] + \"').offset().left\" );\n\t});\n\n\n\t// get position\n\ttests = [\n\t\t{ \"id\": \"#absolute-1\", \"top\": 0, \"left\": 0 }\n\t];\n\tjQuery.each( tests, function() {\n\t\tequal( jQuery( this[\"id\"], doc ).position().top,  this[\"top\"],  \"jQuery('\" + this[\"id\"] + \"').position().top\" );\n\t\tequal( jQuery( this[\"id\"], doc ).position().left, this[\"left\"], \"jQuery('\" + this[\"id\"] + \"').position().left\" );\n\t});\n});\n\ntestIframe(\"offset/absolute\", \"absolute\", function( $ ) {\n\texpect(178);\n\n\tvar tests, offset;\n\n\t// get offset tests\n\ttests = [\n\t\t{ \"id\": \"#absolute-1\",     \"top\":  1, \"left\":  1 },\n\t\t{ \"id\": \"#absolute-1-1\",   \"top\":  5, \"left\":  5 },\n\t\t{ \"id\": \"#absolute-1-1-1\", \"top\":  9, \"left\":  9 },\n\t\t{ \"id\": \"#absolute-2\",     \"top\": 20, \"left\": 20 }\n\t];\n\tjQuery.each( tests, function() {\n\t\tequal( $( this[\"id\"] ).offset().top,  this[\"top\"],  \"jQuery('\" + this[\"id\"] + \"').offset().top\" );\n\t\tequal( $( this[\"id\"] ).offset().left, this[\"left\"], \"jQuery('\" + this[\"id\"] + \"').offset().left\" );\n\t});\n\n\n\t// get position\n\ttests = [\n\t\t{ \"id\": \"#absolute-1\",     \"top\":  0, \"left\":  0 },\n\t\t{ \"id\": \"#absolute-1-1\",   \"top\":  1, \"left\":  1 },\n\t\t{ \"id\": \"#absolute-1-1-1\", \"top\":  1, \"left\":  1 },\n\t\t{ \"id\": \"#absolute-2\",     \"top\": 19, \"left\": 19 }\n\t];\n\tjQuery.each( tests, function() {\n\t\tequal( $( this[\"id\"] ).position().top,  this[\"top\"],  \"jQuery('\" + this[\"id\"] + \"').position().top\" );\n\t\tequal( $( this[\"id\"] ).position().left, this[\"left\"], \"jQuery('\" + this[\"id\"] + \"').position().left\" );\n\t});\n\n\t// test #5781\n\toffset = $( \"#positionTest\" ).offset({ \"top\": 10, \"left\": 10 }).offset();\n\tequal( offset.top,  10, \"Setting offset on element with position absolute but 'auto' values.\" );\n\tequal( offset.left, 10, \"Setting offset on element with position absolute but 'auto' values.\" );\n\n\n\t// set offset\n\ttests = [\n\t\t{ \"id\": \"#absolute-2\",     \"top\": 30, \"left\": 30 },\n\t\t{ \"id\": \"#absolute-2\",     \"top\": 10, \"left\": 10 },\n\t\t{ \"id\": \"#absolute-2\",     \"top\": -1, \"left\": -1 },\n\t\t{ \"id\": \"#absolute-2\",     \"top\": 19, \"left\": 19 },\n\t\t{ \"id\": \"#absolute-1-1-1\", \"top\": 15, \"left\": 15 },\n\t\t{ \"id\": \"#absolute-1-1-1\", \"top\":  5, \"left\":  5 },\n\t\t{ \"id\": \"#absolute-1-1-1\", \"top\": -1, \"left\": -1 },\n\t\t{ \"id\": \"#absolute-1-1-1\", \"top\":  9, \"left\":  9 },\n\t\t{ \"id\": \"#absolute-1-1\",   \"top\": 10, \"left\": 10 },\n\t\t{ \"id\": \"#absolute-1-1\",   \"top\":  0, \"left\":  0 },\n\t\t{ \"id\": \"#absolute-1-1\",   \"top\": -1, \"left\": -1 },\n\t\t{ \"id\": \"#absolute-1-1\",   \"top\":  5, \"left\":  5 },\n\t\t{ \"id\": \"#absolute-1\",     \"top\":  2, \"left\":  2 },\n\t\t{ \"id\": \"#absolute-1\",     \"top\":  0, \"left\":  0 },\n\t\t{ \"id\": \"#absolute-1\",     \"top\": -1, \"left\": -1 },\n\t\t{ \"id\": \"#absolute-1\",     \"top\":  1, \"left\":  1 }\n\t];\n\tjQuery.each( tests, function() {\n\t\t$( this[\"id\"] ).offset({ \"top\": this[\"top\"], \"left\": this[\"left\"] });\n\t\tequal( $( this[\"id\"] ).offset().top,  this[\"top\"],  \"jQuery('\" + this[\"id\"] + \"').offset({ top: \"  + this[\"top\"]  + \" })\" );\n\t\tequal( $( this[\"id\"] ).offset().left, this[\"left\"], \"jQuery('\" + this[\"id\"] + \"').offset({ left: \" + this[\"left\"] + \" })\" );\n\n\t\tvar top = this[\"top\"], left = this[\"left\"];\n\n\t\t$( this[\"id\"] ).offset(function(i, val){\n\t\t\tequal( val.top, top, \"Verify incoming top position.\" );\n\t\t\tequal( val.left, left, \"Verify incoming top position.\" );\n\t\t\treturn { \"top\": top + 1, \"left\": left + 1 };\n\t\t});\n\t\tequal( $( this[\"id\"] ).offset().top,  this[\"top\"]  + 1, \"jQuery('\" + this[\"id\"] + \"').offset({ top: \"  + (this[\"top\"]  + 1) + \" })\" );\n\t\tequal( $( this[\"id\"] ).offset().left, this[\"left\"] + 1, \"jQuery('\" + this[\"id\"] + \"').offset({ left: \" + (this[\"left\"] + 1) + \" })\" );\n\n\t\t$( this[\"id\"] )\n\t\t\t.offset({ \"left\": this[\"left\"] + 2 })\n\t\t\t.offset({ \"top\":  this[\"top\"]  + 2 });\n\t\tequal( $( this[\"id\"] ).offset().top,  this[\"top\"]  + 2, \"Setting one property at a time.\" );\n\t\tequal( $( this[\"id\"] ).offset().left, this[\"left\"] + 2, \"Setting one property at a time.\" );\n\n\t\t$( this[\"id\"] ).offset({ \"top\": this[\"top\"], \"left\": this[\"left\"], \"using\": function( props ) {\n\t\t\t$( this ).css({\n\t\t\t\t\"top\":  props.top  + 1,\n\t\t\t\t\"left\": props.left + 1\n\t\t\t});\n\t\t}});\n\t\tequal( $( this[\"id\"] ).offset().top,  this[\"top\"]  + 1, \"jQuery('\" + this[\"id\"] + \"').offset({ top: \"  + (this[\"top\"]  + 1) + \", using: fn })\" );\n\t\tequal( $( this[\"id\"] ).offset().left, this[\"left\"] + 1, \"jQuery('\" + this[\"id\"] + \"').offset({ left: \" + (this[\"left\"] + 1) + \", using: fn })\" );\n\t});\n});\n\ntestIframe(\"offset/relative\", \"relative\", function( $ ) {\n\texpect(60);\n\n\tvar ie, tests;\n\n\t// IE is collapsing the top margin of 1px; detect and adjust accordingly\n\tie = $(\"#relative-1\").offset().top === 6;\n\n\t// get offset\n\ttests = [\n\t\t{ \"id\": \"#relative-1\",   \"top\": ie ?   6 :   7, \"left\":  7 },\n\t\t{ \"id\": \"#relative-1-1\", \"top\": ie ?  13 :  15, \"left\": 15 },\n\t\t{ \"id\": \"#relative-2\",   \"top\": ie ? 141 : 142, \"left\": 27 }\n\t];\n\tjQuery.each( tests, function() {\n\t\tequal( $( this[\"id\"] ).offset().top,  this[\"top\"],  \"jQuery('\" + this[\"id\"] + \"').offset().top\" );\n\t\tequal( $( this[\"id\"] ).offset().left, this[\"left\"], \"jQuery('\" + this[\"id\"] + \"').offset().left\" );\n\t});\n\n\n\t// get position\n\ttests = [\n\t\t{ \"id\": \"#relative-1\",   \"top\": ie ?   5 :   6, \"left\":  6 },\n\t\t{ \"id\": \"#relative-1-1\", \"top\": ie ?   4 :   5, \"left\":  5 },\n\t\t{ \"id\": \"#relative-2\",   \"top\": ie ? 140 : 141, \"left\": 26 }\n\t];\n\tjQuery.each( tests, function() {\n\t\tequal( $( this[\"id\"] ).position().top,  this[\"top\"],  \"jQuery('\" + this[\"id\"] + \"').position().top\" );\n\t\tequal( $( this[\"id\"] ).position().left, this[\"left\"], \"jQuery('\" + this[\"id\"] + \"').position().left\" );\n\t});\n\n\n\t// set offset\n\ttests = [\n\t\t{ \"id\": \"#relative-2\",   \"top\": 200, \"left\":  50 },\n\t\t{ \"id\": \"#relative-2\",   \"top\": 100, \"left\":  10 },\n\t\t{ \"id\": \"#relative-2\",   \"top\":  -5, \"left\":  -5 },\n\t\t{ \"id\": \"#relative-2\",   \"top\": 142, \"left\":  27 },\n\t\t{ \"id\": \"#relative-1-1\", \"top\": 100, \"left\": 100 },\n\t\t{ \"id\": \"#relative-1-1\", \"top\":   5, \"left\":   5 },\n\t\t{ \"id\": \"#relative-1-1\", \"top\":  -1, \"left\":  -1 },\n\t\t{ \"id\": \"#relative-1-1\", \"top\":  15, \"left\":  15 },\n\t\t{ \"id\": \"#relative-1\",   \"top\": 100, \"left\": 100 },\n\t\t{ \"id\": \"#relative-1\",   \"top\":   0, \"left\":   0 },\n\t\t{ \"id\": \"#relative-1\",   \"top\":  -1, \"left\":  -1 },\n\t\t{ \"id\": \"#relative-1\",   \"top\":   7, \"left\":   7 }\n\t];\n\tjQuery.each( tests, function() {\n\t\t$( this[\"id\"] ).offset({ \"top\": this[\"top\"], \"left\": this[\"left\"] });\n\t\tequal( $( this[\"id\"] ).offset().top,  this[\"top\"],  \"jQuery('\" + this[\"id\"] + \"').offset({ top: \"  + this[\"top\"]  + \" })\" );\n\t\tequal( $( this[\"id\"] ).offset().left, this[\"left\"], \"jQuery('\" + this[\"id\"] + \"').offset({ left: \" + this[\"left\"] + \" })\" );\n\n\t\t$( this[\"id\"] ).offset({ \"top\": this[\"top\"], \"left\": this[\"left\"], \"using\": function( props ) {\n\t\t\t$( this ).css({\n\t\t\t\t\"top\":  props.top  + 1,\n\t\t\t\t\"left\": props.left + 1\n\t\t\t});\n\t\t}});\n\t\tequal( $( this[\"id\"] ).offset().top,  this[\"top\"]  + 1, \"jQuery('\" + this[\"id\"] + \"').offset({ top: \"  + (this[\"top\"]  + 1) + \", using: fn })\" );\n\t\tequal( $( this[\"id\"] ).offset().left, this[\"left\"] + 1, \"jQuery('\" + this[\"id\"] + \"').offset({ left: \" + (this[\"left\"] + 1) + \", using: fn })\" );\n\t});\n});\n\ntestIframe(\"offset/static\", \"static\", function( $ ) {\n\texpect( 80 );\n\n\tvar ie, tests;\n\n\t// IE is collapsing the top margin of 1px; detect and adjust accordingly\n\tie = $(\"#static-1\").offset().top === 6;\n\n\t// get offset\n\ttests = [\n\t\t{ \"id\": \"#static-1\",     \"top\": ie ?   6 :   7, \"left\":  7 },\n\t\t{ \"id\": \"#static-1-1\",   \"top\": ie ?  13 :  15, \"left\": 15 },\n\t\t{ \"id\": \"#static-1-1-1\", \"top\": ie ?  20 :  23, \"left\": 23 },\n\t\t{ \"id\": \"#static-2\", \"top\": ie ? 121 : 122, left: 7 }\n\t];\n\tjQuery.each( tests, function() {\n\t\tequal( $( this[\"id\"] ).offset().top,  this[\"top\"],  \"jQuery('\" + this[\"id\"] + \"').offset().top\" );\n\t\tequal( $( this[\"id\"] ).offset().left, this[\"left\"], \"jQuery('\" + this[\"id\"] + \"').offset().left\" );\n\t});\n\n\n\t// get position\n\ttests = [\n\t\t{ \"id\": \"#static-1\",     \"top\": ie ?   5 :   6, \"left\":  6 },\n\t\t{ \"id\": \"#static-1-1\",   \"top\": ie ?  12 :  14, \"left\": 14 },\n\t\t{ \"id\": \"#static-1-1-1\", \"top\": ie ?  19 :  22, \"left\": 22 },\n\t\t{ \"id\": \"#static-2\", \"top\": ie ? 120 : 121, \"left\": 6 }\n\t];\n\tjQuery.each( tests, function() {\n\t\tequal( $( this[\"id\"] ).position().top,  this[\"top\"],  \"jQuery('\" + this[\"top\"]  + \"').position().top\" );\n\t\tequal( $( this[\"id\"] ).position().left, this[\"left\"], \"jQuery('\" + this[\"left\"] +\"').position().left\" );\n\t});\n\n\n\t// set offset\n\ttests = [\n\t\t{ \"id\": \"#static-2\",     \"top\": 200, \"left\": 200 },\n\t\t{ \"id\": \"#static-2\",     \"top\": 100, \"left\": 100 },\n\t\t{ \"id\": \"#static-2\",     \"top\":  -2, \"left\":  -2 },\n\t\t{ \"id\": \"#static-2\",     \"top\": 121, \"left\":   6 },\n\t\t{ \"id\": \"#static-1-1-1\", \"top\":  50, \"left\":  50 },\n\t\t{ \"id\": \"#static-1-1-1\", \"top\":  10, \"left\":  10 },\n\t\t{ \"id\": \"#static-1-1-1\", \"top\":  -1, \"left\":  -1 },\n\t\t{ \"id\": \"#static-1-1-1\", \"top\":  22, \"left\":  22 },\n\t\t{ \"id\": \"#static-1-1\",   \"top\":  25, \"left\":  25 },\n\t\t{ \"id\": \"#static-1-1\",   \"top\":  10, \"left\":  10 },\n\t\t{ \"id\": \"#static-1-1\",   \"top\":  -3, \"left\":  -3 },\n\t\t{ \"id\": \"#static-1-1\",   \"top\":  14, \"left\":  14 },\n\t\t{ \"id\": \"#static-1\",     \"top\":  30, \"left\":  30 },\n\t\t{ \"id\": \"#static-1\",     \"top\":   2, \"left\":   2 },\n\t\t{ \"id\": \"#static-1\",     \"top\":  -2, \"left\":  -2 },\n\t\t{ \"id\": \"#static-1\",     \"top\":   7, \"left\":   7 }\n\t];\n\tjQuery.each( tests, function() {\n\t\t$( this[\"id\"] ).offset({ \"top\": this[\"top\"], \"left\": this[\"left\"] });\n\t\tequal( $( this[\"id\"] ).offset().top,  this[\"top\"],  \"jQuery('\" + this[\"id\"] + \"').offset({ top: \"  + this[\"top\"]  + \" })\" );\n\t\tequal( $( this[\"id\"] ).offset().left, this[\"left\"], \"jQuery('\" + this[\"id\"] + \"').offset({ left: \" + this[\"left\"] + \" })\" );\n\n\t\t$( this[\"id\"] ).offset({ \"top\": this[\"top\"], \"left\": this[\"left\"], \"using\": function( props ) {\n\t\t\t$( this ).css({\n\t\t\t\t\"top\":  props.top  + 1,\n\t\t\t\t\"left\": props.left + 1\n\t\t\t});\n\t\t}});\n\t\tequal( $( this[\"id\"] ).offset().top,  this[\"top\"]  + 1, \"jQuery('\" + this[\"id\"] + \"').offset({ top: \"  + (this[\"top\"]  + 1) + \", using: fn })\" );\n\t\tequal( $( this[\"id\"] ).offset().left, this[\"left\"] + 1, \"jQuery('\" + this[\"id\"] + \"').offset({ left: \" + (this[\"left\"] + 1) + \", using: fn })\" );\n\t});\n});\n\ntestIframe(\"offset/fixed\", \"fixed\", function( $ ) {\n\texpect(34);\n\n\tvar ie, tests, $noTopLeft;\n\n\t// IE is collapsing the top margin of 1px; detect and adjust accordingly\n\tie = $(\"#fixed-1\").position().top === 2;\n\n\ttests = [\n\t\t{\n\t\t\t\"id\": \"#fixed-1\",\n\t\t\t\"offsetTop\": 1001,\n\t\t\t\"offsetLeft\": 1001,\n\t\t\t\"positionTop\": ie ? 2 : 0,\n\t\t\t\"positionLeft\": ie ? 2 : 0\n\t\t},\n\t\t{\n\t\t\t\"id\": \"#fixed-2\",\n\t\t\t\"offsetTop\": 1021,\n\t\t\t\"offsetLeft\": 1021,\n\t\t\t\"positionTop\": ie ? 22 : 20,\n\t\t\t\"positionLeft\": ie ? 22 : 20\n\t\t}\n\t];\n\n\tjQuery.each( tests, function() {\n\t\tif ( !window.supportsScroll ) {\n\t\t\tok( true, \"Browser doesn't support scroll position.\" );\n\t\t\tok( true, \"Browser doesn't support scroll position.\" );\n\t\t\tok( true, \"Browser doesn't support scroll position.\" );\n\t\t\tok( true, \"Browser doesn't support scroll position.\" );\n\n\t\t} else if ( window.supportsFixedPosition ) {\n\t\t\tequal( $( this[\"id\"] ).offset().top,  this[\"offsetTop\"],  \"jQuery('\" + this[\"id\"] + \"').offset().top\" );\n\t\t\tequal( $( this[\"id\"] ).position().top,  this[\"positionTop\"],  \"jQuery('\" + this[\"id\"] + \"').position().top\" );\n\t\t\tequal( $( this[\"id\"] ).offset().left, this[\"offsetLeft\"], \"jQuery('\" + this[\"id\"] + \"').offset().left\" );\n\t\t\tequal( $( this[\"id\"] ).position().left,  this[\"positionLeft\"],  \"jQuery('\" + this[\"id\"] + \"').position().left\" );\n\t\t} else {\n\t\t\t// need to have same number of assertions\n\t\t\tok( true, \"Fixed position is not supported\" );\n\t\t\tok( true, \"Fixed position is not supported\" );\n\t\t\tok( true, \"Fixed position is not supported\" );\n\t\t\tok( true, \"Fixed position is not supported\" );\n\t\t}\n\t});\n\n\ttests = [\n\t\t{ \"id\": \"#fixed-1\", \"top\": 100, \"left\": 100 },\n\t\t{ \"id\": \"#fixed-1\", \"top\":   0, \"left\":   0 },\n\t\t{ \"id\": \"#fixed-1\", \"top\":  -4, \"left\":  -4 },\n\t\t{ \"id\": \"#fixed-2\", \"top\": 200, \"left\": 200 },\n\t\t{ \"id\": \"#fixed-2\", \"top\":   0, \"left\":   0 },\n\t\t{ \"id\": \"#fixed-2\", \"top\":  -5, \"left\":  -5 }\n\t];\n\n\tjQuery.each( tests, function() {\n\t\tif ( window.supportsFixedPosition ) {\n\t\t\t$( this[\"id\"] ).offset({ \"top\": this[\"top\"], \"left\": this[\"left\"] });\n\t\t\tequal( $( this[\"id\"] ).offset().top,  this[\"top\"],  \"jQuery('\" + this[\"id\"] + \"').offset({ top: \"  + this[\"top\"]  + \" })\" );\n\t\t\tequal( $( this[\"id\"] ).offset().left, this[\"left\"], \"jQuery('\" + this[\"id\"] + \"').offset({ left: \" + this[\"left\"] + \" })\" );\n\n\t\t\t$( this[\"id\"] ).offset({ \"top\": this[\"top\"], \"left\": this[\"left\"], \"using\": function( props ) {\n\t\t\t\t$( this ).css({\n\t\t\t\t\t\"top\":  props.top  + 1,\n\t\t\t\t\t\"left\": props.left + 1\n\t\t\t\t});\n\t\t\t}});\n\t\t\tequal( $( this[\"id\"] ).offset().top,  this[\"top\"]  + 1, \"jQuery('\" + this[\"id\"] + \"').offset({ top: \"  + (this[\"top\"]  + 1) + \", using: fn })\" );\n\t\t\tequal( $( this[\"id\"] ).offset().left, this[\"left\"] + 1, \"jQuery('\" + this[\"id\"] + \"').offset({ left: \" + (this[\"left\"] + 1) + \", using: fn })\" );\n\t\t} else {\n\t\t\t// need to have same number of assertions\n\t\t\tok( true, \"Fixed position is not supported\" );\n\t\t\tok( true, \"Fixed position is not supported\" );\n\t\t\tok( true, \"Fixed position is not supported\" );\n\t\t\tok( true, \"Fixed position is not supported\" );\n\t\t}\n\t});\n\n\t// Bug 8316\n\t$noTopLeft = $(\"#fixed-no-top-left\");\n\tif ( window.supportsFixedPosition ) {\n\t\tequal( $noTopLeft.offset().top,  1007,  \"Check offset top for fixed element with no top set\" );\n\t\tequal( $noTopLeft.offset().left, 1007, \"Check offset left for fixed element with no left set\" );\n\t} else {\n\t\t// need to have same number of assertions\n\t\tok( true, \"Fixed position is not supported\" );\n\t\tok( true, \"Fixed position is not supported\" );\n\t}\n});\n\ntestIframe(\"offset/table\", \"table\", function( $ ) {\n\texpect(4);\n\n\tequal( $(\"#table-1\").offset().top, 6, \"jQuery('#table-1').offset().top\" );\n\tequal( $(\"#table-1\").offset().left, 6, \"jQuery('#table-1').offset().left\" );\n\n\tequal( $(\"#th-1\").offset().top, 10, \"jQuery('#th-1').offset().top\" );\n\tequal( $(\"#th-1\").offset().left, 10, \"jQuery('#th-1').offset().left\" );\n});\n\ntestIframe(\"offset/scroll\", \"scroll\", function( $, win ) {\n\texpect(24);\n\n\t// If we're going to bastardize the tests, let's just DO it\n\tvar ie = /msie [678]/i.test( navigator.userAgent );\n\n\tif ( ie ) {\n\t\tok( true, \"TestSwarm's iframe has hosed this test in oldIE, we surrender\" );\n\t} else {\n\t\tequal( $(\"#scroll-1\").offset().top, 7, \"jQuery('#scroll-1').offset().top\" );\n\t}\n\tequal( $(\"#scroll-1\").offset().left, 7, \"jQuery('#scroll-1').offset().left\" );\n\n\tif ( ie ) {\n\t\tok( true, \"TestSwarm's iframe has hosed this test in oldIE, we surrender\" );\n\t} else {\n\t\tequal( $(\"#scroll-1-1\").offset().top, 11, \"jQuery('#scroll-1-1').offset().top\" );\n\t}\n\tequal( $(\"#scroll-1-1\").offset().left, 11, \"jQuery('#scroll-1-1').offset().left\" );\n\n\t// scroll offset tests .scrollTop/Left\n\tequal( $(\"#scroll-1\").scrollTop(), 5, \"jQuery('#scroll-1').scrollTop()\" );\n\tequal( $(\"#scroll-1\").scrollLeft(), 5, \"jQuery('#scroll-1').scrollLeft()\" );\n\n\tequal( $(\"#scroll-1-1\").scrollTop(), 0, \"jQuery('#scroll-1-1').scrollTop()\" );\n\tequal( $(\"#scroll-1-1\").scrollLeft(), 0, \"jQuery('#scroll-1-1').scrollLeft()\" );\n\n\t// scroll method chaining\n\tequal( $(\"#scroll-1\").scrollTop(undefined).scrollTop(), 5, \".scrollTop(undefined) is chainable (#5571)\" );\n\tequal( $(\"#scroll-1\").scrollLeft(undefined).scrollLeft(), 5, \".scrollLeft(undefined) is chainable (#5571)\" );\n\n\twin.name = \"test\";\n\n\tif ( !window.supportsScroll ) {\n\t\tok( true, \"Browser doesn't support scroll position.\" );\n\t\tok( true, \"Browser doesn't support scroll position.\" );\n\n\t\tok( true, \"Browser doesn't support scroll position.\" );\n\t\tok( true, \"Browser doesn't support scroll position.\" );\n\t} else {\n\t\tequal( $(win).scrollTop(), 1000, \"jQuery(window).scrollTop()\" );\n\t\tequal( $(win).scrollLeft(), 1000, \"jQuery(window).scrollLeft()\" );\n\n\t\tequal( $(win.document).scrollTop(), 1000, \"jQuery(document).scrollTop()\" );\n\t\tequal( $(win.document).scrollLeft(), 1000, \"jQuery(document).scrollLeft()\" );\n\t}\n\n\t// test jQuery using parent window/document\n\t// jQuery reference here is in the iframe\n\twindow.scrollTo(0,0);\n\tequal( $(window).scrollTop(), 0, \"jQuery(window).scrollTop() other window\" );\n\tequal( $(window).scrollLeft(), 0, \"jQuery(window).scrollLeft() other window\" );\n\tequal( $(document).scrollTop(), 0, \"jQuery(window).scrollTop() other document\" );\n\tequal( $(document).scrollLeft(), 0, \"jQuery(window).scrollLeft() other document\" );\n\n\t// Tests scrollTop/Left with empty jquery objects\n\tnotEqual( $().scrollTop(100), null, \"jQuery().scrollTop(100) testing setter on empty jquery object\" );\n\tnotEqual( $().scrollLeft(100), null, \"jQuery().scrollLeft(100) testing setter on empty jquery object\" );\n\tnotEqual( $().scrollTop(null), null, \"jQuery().scrollTop(null) testing setter on empty jquery object\" );\n\tnotEqual( $().scrollLeft(null), null, \"jQuery().scrollLeft(null) testing setter on empty jquery object\" );\n\tstrictEqual( $().scrollTop(), null, \"jQuery().scrollTop(100) testing setter on empty jquery object\" );\n\tstrictEqual( $().scrollLeft(), null, \"jQuery().scrollLeft(100) testing setter on empty jquery object\" );\n});\n\ntestIframe(\"offset/body\", \"body\", function( $ ) {\n\texpect(4);\n\n\tequal( $(\"body\").offset().top, 1, \"jQuery('#body').offset().top\" );\n\tequal( $(\"body\").offset().left, 1, \"jQuery('#body').offset().left\" );\n\tequal( $(\"#firstElement\").position().left, 5, \"$('#firstElement').position().left\" );\n\tequal( $(\"#firstElement\").position().top, 5, \"$('#firstElement').position().top\" );\n});\n\ntest(\"chaining\", function() {\n\texpect(3);\n\tvar coords = { \"top\":  1, \"left\":  1 };\n\tequal( jQuery(\"#absolute-1\").offset(coords).selector, \"#absolute-1\", \"offset(coords) returns jQuery object\" );\n\tequal( jQuery(\"#non-existent\").offset(coords).selector, \"#non-existent\", \"offset(coords) with empty jQuery set returns jQuery object\" );\n\tequal( jQuery(\"#absolute-1\").offset(undefined).selector, \"#absolute-1\", \"offset(undefined) returns jQuery object (#5571)\" );\n});\n\ntest(\"offsetParent\", function(){\n\texpect(13);\n\n\tvar body, header, div, area;\n\n\tbody = jQuery(\"body\").offsetParent();\n\tequal( body.length, 1, \"Only one offsetParent found.\" );\n\tequal( body[0], document.documentElement, \"The html element is the offsetParent of the body.\" );\n\n\theader = jQuery(\"#qunit\").offsetParent();\n\tequal( header.length, 1, \"Only one offsetParent found.\" );\n\tequal( header[0], document.documentElement, \"The html element is the offsetParent of #qunit.\" );\n\n\tdiv = jQuery(\"#nothiddendivchild\").offsetParent();\n\tequal( div.length, 1, \"Only one offsetParent found.\" );\n\tequal( div[0], document.getElementById(\"qunit-fixture\"), \"The #qunit-fixture is the offsetParent of #nothiddendivchild.\" );\n\n\tjQuery(\"#nothiddendiv\").css(\"position\", \"relative\");\n\n\tdiv = jQuery(\"#nothiddendivchild\").offsetParent();\n\tequal( div.length, 1, \"Only one offsetParent found.\" );\n\tequal( div[0], jQuery(\"#nothiddendiv\")[0], \"The div is the offsetParent.\" );\n\n\tdiv = jQuery(\"body, #nothiddendivchild\").offsetParent();\n\tequal( div.length, 2, \"Two offsetParent found.\" );\n\tequal( div[0], document.documentElement, \"The html element is the offsetParent of the body.\" );\n\tequal( div[1], jQuery(\"#nothiddendiv\")[0], \"The div is the offsetParent.\" );\n\n\tarea = jQuery(\"#imgmap area\").offsetParent();\n\tequal( area[0], document.documentElement, \"The html element is the offsetParent of the body.\" );\n\n\tdiv = jQuery(\"<div>\").css({ \"position\": \"absolute\" }).appendTo(\"body\");\n\tequal( div.offsetParent()[0], document.documentElement, \"Absolutely positioned div returns html as offset parent, see #12139\" );\n\n\tdiv.remove();\n});\n\ntest(\"fractions (see #7730 and #7885)\", function() {\n\texpect(2);\n\n\tjQuery(\"body\").append(\"<div id='fractions'/>\");\n\n\tvar result,\n\t\texpected = { \"top\": 1000, \"left\": 1000 },\n\t\tdiv = jQuery(\"#fractions\");\n\n\tdiv.css({\n\t\t\"position\": \"absolute\",\n\t\t\"left\": \"1000.7432222px\",\n\t\t\"top\": \"1000.532325px\",\n\t\t\"width\": 100,\n\t\t\"height\": 100\n\t});\n\n\tdiv.offset(expected);\n\n\tresult = div.offset();\n\n\tequal( result.top, expected.top, \"Check top\" );\n\tequal( result.left, expected.left, \"Check left\" );\n\n\tdiv.remove();\n});\n\n})();\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/jquery/test/unit/queue.js",
    "content": "module( \"queue\", { teardown: moduleTeardown });\n\ntest( \"queue() with other types\", 14, function() {\n\tstop();\n\n\tvar $div = jQuery({}),\n\t\tcounter = 0;\n\n\t$div.promise( \"foo\" ).done(function() {\n\t\tequal( counter, 0, \"Deferred for collection with no queue is automatically resolved\" );\n\t});\n\n\t$div\n\t\t.queue(\"foo\",function(){\n\t\t\tequal( ++counter, 1, \"Dequeuing\" );\n\t\t\tjQuery.dequeue(this,\"foo\");\n\t\t})\n\t\t.queue(\"foo\",function(){\n\t\t\tequal( ++counter, 2, \"Dequeuing\" );\n\t\t\tjQuery(this).dequeue(\"foo\");\n\t\t})\n\t\t.queue(\"foo\",function(){\n\t\t\tequal( ++counter, 3, \"Dequeuing\" );\n\t\t})\n\t\t.queue(\"foo\",function(){\n\t\t\tequal( ++counter, 4, \"Dequeuing\" );\n\t\t});\n\n\t$div.promise(\"foo\").done(function() {\n\t\tequal( counter, 4, \"Testing previous call to dequeue in deferred\"  );\n\t\tstart();\n\t});\n\n\tequal( $div.queue(\"foo\").length, 4, \"Testing queue length\" );\n\n\tequal( $div.queue(\"foo\", undefined).queue(\"foo\").length, 4, \".queue('name',undefined) does nothing but is chainable (#5571)\");\n\n\t$div.dequeue(\"foo\");\n\n\tequal( counter, 3, \"Testing previous call to dequeue\" );\n\tequal( $div.queue(\"foo\").length, 1, \"Testing queue length\" );\n\n\t$div.dequeue(\"foo\");\n\n\tequal( counter, 4, \"Testing previous call to dequeue\" );\n\tequal( $div.queue(\"foo\").length, 0, \"Testing queue length\" );\n\n\t$div.dequeue(\"foo\");\n\n\tequal( counter, 4, \"Testing previous call to dequeue\" );\n\tequal( $div.queue(\"foo\").length, 0, \"Testing queue length\" );\n\n});\n\ntest(\"queue(name) passes in the next item in the queue as a parameter\", function() {\n\texpect(2);\n\n\tvar div = jQuery({}),\n\t\tcounter = 0;\n\n\tdiv.queue(\"foo\", function(next) {\n\t\tequal(++counter, 1, \"Dequeueing\");\n\t\tnext();\n\t}).queue(\"foo\", function(next) {\n\t\tequal(++counter, 2, \"Next was called\");\n\t\tnext();\n\t}).queue(\"bar\", function() {\n\t\tequal(++counter, 3, \"Other queues are not triggered by next()\");\n\t});\n\n\tdiv.dequeue(\"foo\");\n});\n\ntest(\"queue() passes in the next item in the queue as a parameter to fx queues\", function() {\n\texpect(3);\n\tstop();\n\n\tvar div = jQuery({}),\n\t\tcounter = 0;\n\n\tdiv.queue(function(next) {\n\t\tequal(++counter, 1, \"Dequeueing\");\n\t\tsetTimeout(function() { next(); }, 500);\n\t}).queue(function(next) {\n\t\tequal(++counter, 2, \"Next was called\");\n\t\tnext();\n\t}).queue(\"bar\", function() {\n\t\tequal(++counter, 3, \"Other queues are not triggered by next()\");\n\t});\n\n\tjQuery.when( div.promise(\"fx\"), div ).done(function() {\n\t\tequal(counter, 2, \"Deferreds resolved\");\n\t\tstart();\n\t});\n});\n\ntest(\"callbacks keep their place in the queue\", function() {\n\texpect(5);\n\tstop();\n\tvar div = jQuery(\"<div>\"),\n\t\tcounter = 0;\n\n\tdiv.queue(function( next ) {\n\t\tequal( ++counter, 1, \"Queue/callback order: first called\" );\n\t\tsetTimeout( next, 200 );\n\t}).delay( 100 ).queue(function( next ) {\n\t\tequal( ++counter, 2, \"Queue/callback order: second called\" );\n\t\tjQuery( this ).delay( 100 ).queue(function( next ) {\n\t\t\tequal( ++counter, 4, \"Queue/callback order: fourth called\" );\n\t\t\tnext();\n\t\t});\n\t\tnext();\n\t}).queue(function( next ) {\n\t\tequal( ++counter, 3, \"Queue/callback order: third called\" );\n\t\tnext();\n\t});\n\n\tdiv.promise(\"fx\").done(function() {\n\t\tequal(counter, 4, \"Deferreds resolved\");\n\t\tstart();\n\t});\n});\n\ntest( \"jQuery.queue should return array while manipulating the queue\", 1, function() {\n\tvar div = document.createElement(\"div\");\n\n\tok( jQuery.isArray( jQuery.queue( div, \"fx\", jQuery.noop ) ), \"jQuery.queue should return an array while manipulating the queue\" );\n});\n\ntest(\"delay()\", function() {\n\texpect(2);\n\tstop();\n\n\tvar foo = jQuery({}), run = 0;\n\n\tfoo.delay(100).queue(function(){\n\t\trun = 1;\n\t\tok( true, \"The function was dequeued.\" );\n\t\tstart();\n\t});\n\n\tequal( run, 0, \"The delay delayed the next function from running.\" );\n});\n\ntest(\"clearQueue(name) clears the queue\", function() {\n\texpect(2);\n\n\tstop();\n\n\tvar div = jQuery({}),\n\t\tcounter = 0;\n\n\tdiv.queue(\"foo\", function( next ) {\n\t\tcounter++;\n\t\tjQuery(this).clearQueue(\"foo\");\n\t\tnext();\n\t}).queue(\"foo\", function() {\n\t\tcounter++;\n\t});\n\n\tdiv.promise(\"foo\").done(function() {\n\t\tok( true, \"dequeue resolves the deferred\" );\n\t\tstart();\n\t});\n\n\tdiv.dequeue(\"foo\");\n\n\tequal(counter, 1, \"the queue was cleared\");\n});\n\ntest(\"clearQueue() clears the fx queue\", function() {\n\texpect(1);\n\n\tvar div = jQuery({}),\n\t\tcounter = 0;\n\n\tdiv.queue(function( next ) {\n\t\tcounter++;\n\t\tvar self = this;\n\t\tsetTimeout(function() { jQuery(self).clearQueue(); next(); }, 50);\n\t}).queue(function() {\n\t\tcounter++;\n\t});\n\n\tequal(counter, 1, \"the queue was cleared\");\n\n\tdiv.removeData();\n});\n\nasyncTest( \"fn.promise() - called when fx queue is empty\", 3, function() {\n\tvar foo = jQuery( \"#foo\" ).clone().addBack(),\n\t\tpromised = false;\n\n\tfoo.queue( function( next ) {\n\t\t// called twice!\n\t\tok( !promised, \"Promised hasn't been called\" );\n\t\tsetTimeout( next, 10 );\n\t});\n\tfoo.promise().done( function() {\n\t\tok( promised = true, \"Promised\" );\n\t\tstart();\n\t});\n});\n\nasyncTest( \"fn.promise( \\\"queue\\\" ) - called whenever last queue function is dequeued\", 5, function() {\n\tvar foo = jQuery( \"#foo\" ),\n\t\ttest;\n\tfoo.promise( \"queue\" ).done( function() {\n\t\tstrictEqual( test, undefined, \"called immediately when queue was already empty\" );\n\t});\n\ttest = 1;\n\tfoo.queue( \"queue\", function( next ) {\n\t\tstrictEqual( test++, 1, \"step one\" );\n\t\tsetTimeout( next, 0 );\n\t}).queue( \"queue\", function( next ) {\n\t\tstrictEqual( test++, 2, \"step two\" );\n\t\tsetTimeout( function() {\n\t\t\tnext();\n\t\t\tstrictEqual( test++, 4, \"step four\" );\n\t\t\tstart();\n\t\t}, 10 );\n\t}).promise( \"queue\" ).done( function() {\n\t\tstrictEqual( test++, 3, \"step three\" );\n\t});\n\n\tfoo.dequeue( \"queue\" );\n});\n\nasyncTest( \"fn.promise( \\\"queue\\\" ) - waits for animation to complete before resolving\", 2, function() {\n\tvar foo = jQuery( \"#foo\" ),\n\t\ttest = 1;\n\n\tfoo.animate({\n\t\ttop: 100\n\t}, {\n\t\tduration: 1,\n\t\tqueue: \"queue\",\n\t\tcomplete: function() {\n\t\t\tstrictEqual( test++, 1, \"step one\" );\n\t\t}\n\t}).dequeue( \"queue\" );\n\n\tfoo.promise( \"queue\" ).done( function() {\n\t\tstrictEqual( test++, 2, \"step two\" );\n\t\tstart();\n\t});\n\n});\n\ntest( \".promise(obj)\", function() {\n\texpect(2);\n\n\tvar obj = {},\n\t\tpromise = jQuery( \"#foo\" ).promise( \"promise\", obj );\n\n\tok( jQuery.isFunction( promise.promise ), \".promise(type, obj) returns a promise\" );\n\tstrictEqual( promise, obj, \".promise(type, obj) returns obj\" );\n});\n\n\nif ( jQuery.fn.stop ) {\n\ttest(\"delay() can be stopped\", function() {\n\t\texpect( 3 );\n\t\tstop();\n\n\t\tvar done = {};\n\t\tjQuery({})\n\t\t\t.queue( \"alternate\", function( next ) {\n\t\t\t\tdone.alt1 = true;\n\t\t\t\tok( true, \"This first function was dequeued\" );\n\t\t\t\tnext();\n\t\t\t})\n\t\t\t.delay( 1000, \"alternate\" )\n\t\t\t.queue( \"alternate\", function() {\n\t\t\t\tdone.alt2 = true;\n\t\t\t\tok( true, \"The function was dequeued immediately, the delay was stopped\" );\n\t\t\t})\n\t\t\t.dequeue( \"alternate\" )\n\n\t\t\t// stop( \"alternate\", false ) will NOT clear the queue, so it should automatically dequeue the next\n\t\t\t.stop( \"alternate\", false, false )\n\n\t\t\t// this test\n\t\t\t.delay( 1 )\n\t\t\t.queue(function() {\n\t\t\t\tdone.default1 = true;\n\t\t\t\tok( false, \"This queue should never run\" );\n\t\t\t})\n\n\t\t\t// stop( clearQueue ) should clear the queue\n\t\t\t.stop( true, false );\n\n\t\tdeepEqual( done, { alt1: true, alt2: true }, \"Queue ran the proper functions\" );\n\n\t\tsetTimeout(function() {\n\t\t\tstart();\n\t\t}, 1500 );\n\t});\n\n\tasyncTest( \"queue stop hooks\", 2, function() {\n\t\tvar foo = jQuery( \"#foo\" );\n\n\t\tfoo.queue( function( next, hooks ) {\n\t\t\thooks.stop = function( gotoEnd ) {\n\t\t\t\tequal( !!gotoEnd, false, \"Stopped without gotoEnd\" );\n\t\t\t};\n\t\t});\n\t\tfoo.stop();\n\n\t\tfoo.queue( function( next, hooks ) {\n\t\t\thooks.stop = function( gotoEnd ) {\n\t\t\t\tequal( gotoEnd, true, \"Stopped with gotoEnd\" );\n\t\t\t\tstart();\n\t\t\t};\n\t\t});\n\n\t\tfoo.stop( false, true );\n\t});\n\n} // if ( jQuery.fn.stop )\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/jquery/test/unit/selector.js",
    "content": "module(\"selector\", { teardown: moduleTeardown });\n\n/**\n * This test page is for selector tests that require jQuery in order to do the selection\n */\n\ntest(\"element - jQuery only\", function() {\n\texpect( 7 );\n\n\tvar fixture = document.getElementById(\"qunit-fixture\");\n\n\tdeepEqual( jQuery(\"p\", fixture).get(), q(\"firstp\",\"ap\",\"sndp\",\"en\",\"sap\",\"first\"), \"Finding elements with a Node context.\" );\n\tdeepEqual( jQuery(\"p\", \"#qunit-fixture\").get(), q(\"firstp\",\"ap\",\"sndp\",\"en\",\"sap\",\"first\"), \"Finding elements with a selector context.\" );\n\tdeepEqual( jQuery(\"p\", jQuery(\"#qunit-fixture\")).get(), q(\"firstp\",\"ap\",\"sndp\",\"en\",\"sap\",\"first\"), \"Finding elements with a jQuery object context.\" );\n\tdeepEqual( jQuery(\"#qunit-fixture\").find(\"p\").get(), q(\"firstp\",\"ap\",\"sndp\",\"en\",\"sap\",\"first\"), \"Finding elements with a context via .find().\" );\n\n\tok( jQuery(\"#length\").length, \"<input name=\\\"length\\\"> cannot be found under IE, see #945\" );\n\tok( jQuery(\"#lengthtest input\").length, \"<input name=\\\"length\\\"> cannot be found under IE, see #945\" );\n\n\t// #7533\n\tequal( jQuery(\"<div id=\\\"A'B~C.D[E]\\\"><p>foo</p></div>\").find(\"p\").length, 1, \"Find where context root is a node and has an ID with CSS3 meta characters\" );\n});\n\ntest(\"class - jQuery only\", function() {\n\texpect( 4 );\n\n\tdeepEqual( jQuery(\".blog\", document.getElementsByTagName(\"p\")).get(), q(\"mark\", \"simon\"), \"Finding elements with a context.\" );\n\tdeepEqual( jQuery(\".blog\", \"p\").get(), q(\"mark\", \"simon\"), \"Finding elements with a context.\" );\n\tdeepEqual( jQuery(\".blog\", jQuery(\"p\")).get(), q(\"mark\", \"simon\"), \"Finding elements with a context.\" );\n\tdeepEqual( jQuery(\"p\").find(\".blog\").get(), q(\"mark\", \"simon\"), \"Finding elements with a context.\" );\n});\n\ntest(\"attributes - jQuery only\", function() {\n\texpect( 5 );\n\n\tt( \"Find elements with a tabindex attribute\", \"[tabindex]\", [\"listWithTabIndex\", \"foodWithNegativeTabIndex\", \"linkWithTabIndex\", \"linkWithNegativeTabIndex\", \"linkWithNoHrefWithTabIndex\", \"linkWithNoHrefWithNegativeTabIndex\"] );\n\n\t// #12600\n\tok(\n\t\tjQuery(\"<select value='12600'><option value='option' selected='selected'></option><option value=''></option></select>\")\n\t\t.prop( \"value\", \"option\" )\n\t\t.is(\":input[value='12600']\"),\n\n\t\t\":input[value=foo] selects select by attribute\"\n\t);\n\tok( jQuery(\"<input type='text' value='12600'/>\").prop( \"value\", \"option\" ).is(\":input[value='12600']\"),\n\t\t\":input[value=foo] selects text input by attribute\"\n\t);\n\n\t// #11115\n\tok( jQuery(\"<input type='checkbox' checked='checked'/>\").prop( \"checked\", false ).is(\"[checked]\"),\n\t\t\"[checked] selects by attribute (positive)\"\n\t);\n\tok( !jQuery(\"<input type='checkbox'/>\").prop( \"checked\", true ).is(\"[checked]\"),\n\t\t\"[checked] selects by attribute (negative)\"\n\t);\n});\n\ntest(\"disconnected nodes\", function() {\n\texpect( 1 );\n\n\tvar $div = jQuery(\"<div/>\");\n\tequal( $div.is(\"div\"), true, \"Make sure .is('nodeName') works on disconnected nodes.\" );\n});\n\ntest(\"disconnected nodes - jQuery only\", function() {\n\texpect( 3 );\n\n\tvar $opt = jQuery(\"<option></option>\").attr(\"value\", \"whipit\").appendTo(\"#qunit-fixture\").detach();\n\tequal( $opt.val(), \"whipit\", \"option value\" );\n\tequal( $opt.is(\":selected\"), false, \"unselected option\" );\n\t$opt.prop(\"selected\", true);\n\tequal( $opt.is(\":selected\"), true, \"selected option\" );\n});\n\ntestIframe(\"selector/html5_selector\", \"attributes - jQuery.attr\", function( jQuery, window, document ) {\n\texpect( 35 );\n\n\t/**\n\t * Returns an array of elements with the given IDs\n\t * q & t are added here for the iFrame's context\n\t */\n\tfunction q() {\n\t\tvar r = [],\n\t\t\ti = 0;\n\n\t\tfor ( ; i < arguments.length; i++ ) {\n\t\t\tr.push( document.getElementById( arguments[i] ) );\n\t\t}\n\t\treturn r;\n\t}\n\n\t/**\n\t * Asserts that a select matches the given IDs\n\t * @example t(\"Check for something\", \"//[a]\", [\"foo\", \"baar\"]);\n\t * @param {String} a - Assertion name\n\t * @param {String} b - Sizzle selector\n\t * @param {Array} c - Array of ids to construct what is expected\n\t */\n\tfunction t( a, b, c ) {\n\t\tvar f = jQuery(b).get(),\n\t\t\ts = \"\",\n\t\t\ti = 0;\n\n\t\tfor ( ; i < f.length; i++ ) {\n\t\t\ts += (s && \",\") + \"'\" + f[i].id + \"'\";\n\t\t}\n\n\t\tdeepEqual(f, q.apply( q, c ), a + \" (\" + b + \")\");\n\t}\n\n\t// ====== All known boolean attributes, including html5 booleans ======\n\t// autobuffer, autofocus, autoplay, async, checked,\n\t// compact, controls, declare, defer, disabled,\n\t// formnovalidate, hidden, indeterminate (property only),\n\t// ismap, itemscope, loop, multiple, muted, nohref, noresize,\n\t// noshade, nowrap, novalidate, open, pubdate, readonly, required,\n\t// reversed, scoped, seamless, selected, truespeed, visible (skipping visible attribute, which is on a barprop object)\n\n\tt( \"Attribute Exists\", \"[autobuffer]\",     [\"video1\"]);\n\tt( \"Attribute Exists\", \"[autofocus]\",      [\"text1\"]);\n\tt( \"Attribute Exists\", \"[autoplay]\",       [\"video1\"]);\n\tt( \"Attribute Exists\", \"[async]\",          [\"script1\"]);\n\tt( \"Attribute Exists\", \"[checked]\",        [\"check1\"]);\n\tt( \"Attribute Exists\", \"[compact]\",        [\"dl\"]);\n\tt( \"Attribute Exists\", \"[controls]\",       [\"video1\"]);\n\tt( \"Attribute Exists\", \"[declare]\",        [\"object1\"]);\n\tt( \"Attribute Exists\", \"[defer]\",          [\"script1\"]);\n\tt( \"Attribute Exists\", \"[disabled]\",       [\"check1\"]);\n\tt( \"Attribute Exists\", \"[formnovalidate]\", [\"form1\"]);\n\tt( \"Attribute Exists\", \"[hidden]\",         [\"div1\"]);\n\tt( \"Attribute Exists\", \"[indeterminate]\",  []);\n\tt( \"Attribute Exists\", \"[ismap]\",          [\"img1\"]);\n\tt( \"Attribute Exists\", \"[itemscope]\",      [\"div1\"]);\n\t// t( \"Attribute Exists\", \"[loop]\",           [\"video1\"]); // IE 6/7 cannot differentiate here. loop is also used on img, input, and marquee tags as well as video/audio. getAttributeNode unfortunately also retrieves the property value.\n\tt( \"Attribute Exists\", \"[multiple]\",       [\"select1\"]);\n\tt( \"Attribute Exists\", \"[muted]\",          [\"audio1\"]);\n\t// t( \"Attribute Exists\", \"[nohref]\",         [\"area1\"]); // IE 6/7 keep this set to false regardless of presence. The attribute node is not retrievable.\n\tt( \"Attribute Exists\", \"[noresize]\",       [\"textarea1\"]);\n\tt( \"Attribute Exists\", \"[noshade]\",        [\"hr1\"]);\n\tt( \"Attribute Exists\", \"[nowrap]\",         [\"td1\", \"div1\"]);\n\tt( \"Attribute Exists\", \"[novalidate]\",     [\"form1\"]);\n\tt( \"Attribute Exists\", \"[open]\",           [\"details1\"]);\n\tt( \"Attribute Exists\", \"[pubdate]\",        [\"article1\"]);\n\tt( \"Attribute Exists\", \"[readonly]\",       [\"text1\"]);\n\tt( \"Attribute Exists\", \"[required]\",       [\"text1\"]);\n\tt( \"Attribute Exists\", \"[reversed]\",       [\"ol1\"]);\n\tt( \"Attribute Exists\", \"[scoped]\",         [\"style1\"]);\n\tt( \"Attribute Exists\", \"[seamless]\",       [\"iframe1\"]);\n\tt( \"Attribute Exists\", \"[selected]\",       [\"option1\"]);\n\tt( \"Attribute Exists\", \"[truespeed]\",      [\"marquee1\"]);\n\n\t// Enumerated attributes (these are not boolean content attributes)\n\tjQuery.expandedEach = jQuery.each;\n\tjQuery.expandedEach([ \"draggable\", \"contenteditable\", \"aria-disabled\" ], function( i, val ) {\n\t\tt( \"Enumerated attribute\", \"[\" + val + \"]\", [\"div1\"]);\n\t});\n\tt( \"Enumerated attribute\", \"[spellcheck]\", [\"span1\"]);\n\n\t// t( \"tabindex selector does not retrieve all elements in IE6/7(#8473)\", \"form, [tabindex]\", [\"form1\", \"text1\"] ); // sigh, FF12 QSA mistakenly includes video elements even though they have no tabindex attribute (see https://bugzilla.mozilla.org/show_bug.cgi?id=618737)\n\tt( \"Improperly named form elements do not interfere with form selections (#9570)\", \"form[name='formName']\", [\"form1\"] );\n});\n\ntestIframe(\"selector/sizzle_cache\", \"Sizzle cache collides with multiple Sizzles on a page\", function( jQuery, window, document ) {\n\tvar $cached = window[\"$cached\"];\n\n\texpect(4);\n\tnotStrictEqual( jQuery, $cached, \"Loaded two engines\" );\n\tdeepEqual( $cached(\".test a\").get(), [ document.getElementById(\"collision\") ], \"Select collision anchor with first sizzle\" );\n\tequal( jQuery(\".evil a\").length, 0, \"Select nothing with second sizzle\" );\n\tequal( jQuery(\".evil a\").length, 0, \"Select nothing again with second sizzle\" );\n});\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/jquery/test/unit/serialize.js",
    "content": "module(\"serialize\", { teardown: moduleTeardown });\n\ntest(\"jQuery.param()\", function() {\n\texpect(22);\n\n\tvar params, settings;\n\n\tequal( !( jQuery.ajaxSettings && jQuery.ajaxSettings.traditional ), true, \"traditional flag, falsy by default\" );\n\n\tparams = {\"foo\":\"bar\", \"baz\":42, \"quux\":\"All your base are belong to us\"};\n\tequal( jQuery.param(params), \"foo=bar&baz=42&quux=All+your+base+are+belong+to+us\", \"simple\" );\n\n\tparams = {\"string\":\"foo\",\"null\":null,\"undefined\":undefined};\n\tequal( jQuery.param(params), \"string=foo&null=&undefined=\", \"handle nulls and undefineds properly\" );\n\n\tparams = {\"someName\": [1, 2, 3], \"regularThing\": \"blah\" };\n\tequal( jQuery.param(params), \"someName%5B%5D=1&someName%5B%5D=2&someName%5B%5D=3&regularThing=blah\", \"with array\" );\n\n\tparams = {\"foo\": [\"a\", \"b\", \"c\"]};\n\tequal( jQuery.param(params), \"foo%5B%5D=a&foo%5B%5D=b&foo%5B%5D=c\", \"with array of strings\" );\n\n\tparams = {\"foo\": [\"baz\", 42, \"All your base are belong to us\"] };\n\tequal( jQuery.param(params), \"foo%5B%5D=baz&foo%5B%5D=42&foo%5B%5D=All+your+base+are+belong+to+us\", \"more array\" );\n\n\tparams = {\"foo\": { \"bar\": \"baz\", \"beep\": 42, \"quux\": \"All your base are belong to us\" } };\n\tequal( jQuery.param(params), \"foo%5Bbar%5D=baz&foo%5Bbeep%5D=42&foo%5Bquux%5D=All+your+base+are+belong+to+us\", \"even more arrays\" );\n\n\tparams = { a:[1,2], b:{ c:3, d:[4,5], e:{ x:[6], y:7, z:[8,9] }, f:true, g:false, h:undefined }, i:[10,11], j:true, k:false, l:[undefined,0], m:\"cowboy hat?\" };\n\tequal( decodeURIComponent( jQuery.param(params) ), \"a[]=1&a[]=2&b[c]=3&b[d][]=4&b[d][]=5&b[e][x][]=6&b[e][y]=7&b[e][z][]=8&b[e][z][]=9&b[f]=true&b[g]=false&b[h]=&i[]=10&i[]=11&j=true&k=false&l[]=&l[]=0&m=cowboy+hat?\", \"huge structure\" );\n\n\tparams = { \"a\": [ 0, [ 1, 2 ], [ 3, [ 4, 5 ], [ 6 ] ], { \"b\": [ 7, [ 8, 9 ], [ { \"c\": 10, \"d\": 11 } ], [ [ 12 ] ], [ [ [ 13 ] ] ], { \"e\": { \"f\": { \"g\": [ 14, [ 15 ] ] } } }, 16 ] }, 17 ] };\n\tequal( decodeURIComponent( jQuery.param(params) ), \"a[]=0&a[1][]=1&a[1][]=2&a[2][]=3&a[2][1][]=4&a[2][1][]=5&a[2][2][]=6&a[3][b][]=7&a[3][b][1][]=8&a[3][b][1][]=9&a[3][b][2][0][c]=10&a[3][b][2][0][d]=11&a[3][b][3][0][]=12&a[3][b][4][0][0][]=13&a[3][b][5][e][f][g][]=14&a[3][b][5][e][f][g][1][]=15&a[3][b][]=16&a[]=17\", \"nested arrays\" );\n\n\tparams = { \"a\":[1,2], \"b\":{ \"c\":3, \"d\":[4,5], \"e\":{ \"x\":[6], \"y\":7, \"z\":[8,9] }, \"f\":true, \"g\":false, \"h\":undefined }, \"i\":[10,11], \"j\":true, \"k\":false, \"l\":[undefined,0], \"m\":\"cowboy hat?\" };\n\tequal( jQuery.param(params,true), \"a=1&a=2&b=%5Bobject+Object%5D&i=10&i=11&j=true&k=false&l=&l=0&m=cowboy+hat%3F\", \"huge structure, forced traditional\" );\n\n\tequal( decodeURIComponent( jQuery.param({ \"a\": [1,2,3], \"b[]\": [4,5,6], \"c[d]\": [7,8,9], \"e\": { \"f\": [10], \"g\": [11,12], \"h\": 13 } }) ), \"a[]=1&a[]=2&a[]=3&b[]=4&b[]=5&b[]=6&c[d][]=7&c[d][]=8&c[d][]=9&e[f][]=10&e[g][]=11&e[g][]=12&e[h]=13\", \"Make sure params are not double-encoded.\" );\n\n\t// #7945\n\tequal( jQuery.param({\"jquery\": \"1.4.2\"}), \"jquery=1.4.2\", \"Check that object with a jQuery property get serialized correctly\" );\n\n\tsettings = { traditional: true };\n\n\tif ( jQuery.ajaxSettings ) {\n\t\tjQuery.ajaxSetup( settings );\n\t} else {\n\t\tjQuery.ajaxSettings = settings;\n\t}\n\n\tparams = {\"foo\":\"bar\", \"baz\":42, \"quux\":\"All your base are belong to us\"};\n\tequal( jQuery.param(params), \"foo=bar&baz=42&quux=All+your+base+are+belong+to+us\", \"simple\" );\n\n\tparams = {\"someName\": [1, 2, 3], \"regularThing\": \"blah\" };\n\tequal( jQuery.param(params), \"someName=1&someName=2&someName=3&regularThing=blah\", \"with array\" );\n\n\tparams = {\"foo\": [\"a\", \"b\", \"c\"]};\n\tequal( jQuery.param(params), \"foo=a&foo=b&foo=c\", \"with array of strings\" );\n\n\tparams = {\"foo[]\":[\"baz\", 42, \"All your base are belong to us\"]};\n\tequal( jQuery.param(params), \"foo%5B%5D=baz&foo%5B%5D=42&foo%5B%5D=All+your+base+are+belong+to+us\", \"more array\" );\n\n\tparams = {\"foo[bar]\":\"baz\", \"foo[beep]\":42, \"foo[quux]\":\"All your base are belong to us\"};\n\tequal( jQuery.param(params), \"foo%5Bbar%5D=baz&foo%5Bbeep%5D=42&foo%5Bquux%5D=All+your+base+are+belong+to+us\", \"even more arrays\" );\n\n\tparams = { a:[1,2], b:{ c:3, d:[4,5], e:{ x:[6], y:7, z:[8,9] }, f:true, g:false, h:undefined }, i:[10,11], j:true, k:false, l:[undefined,0], m:\"cowboy hat?\" };\n\tequal( jQuery.param(params), \"a=1&a=2&b=%5Bobject+Object%5D&i=10&i=11&j=true&k=false&l=&l=0&m=cowboy+hat%3F\", \"huge structure\" );\n\n\tparams = { \"a\": [ 0, [ 1, 2 ], [ 3, [ 4, 5 ], [ 6 ] ], { \"b\": [ 7, [ 8, 9 ], [ { \"c\": 10, d: 11 } ], [ [ 12 ] ], [ [ [ 13 ] ] ], { \"e\": { \"f\": { \"g\": [ 14, [ 15 ] ] } } }, 16 ] }, 17 ] };\n\tequal( jQuery.param(params), \"a=0&a=1%2C2&a=3%2C4%2C5%2C6&a=%5Bobject+Object%5D&a=17\", \"nested arrays (not possible when jQuery.param.traditional == true)\" );\n\n\tparams = { a:[1,2], b:{ c:3, d:[4,5], e:{ x:[6], y:7, z:[8,9] }, f:true, g:false, h:undefined }, i:[10,11], j:true, k:false, l:[undefined,0], m:\"cowboy hat?\" };\n\tequal( decodeURIComponent( jQuery.param(params,false) ), \"a[]=1&a[]=2&b[c]=3&b[d][]=4&b[d][]=5&b[e][x][]=6&b[e][y]=7&b[e][z][]=8&b[e][z][]=9&b[f]=true&b[g]=false&b[h]=&i[]=10&i[]=11&j=true&k=false&l[]=&l[]=0&m=cowboy+hat?\", \"huge structure, forced not traditional\" );\n\n\tparams = { \"param1\": null };\n\tequal( jQuery.param(params,false), \"param1=\", \"Make sure that null params aren't traversed.\" );\n\n\tparams = {\"test\": {\"length\": 3, \"foo\": \"bar\"} };\n\tequal( jQuery.param( params, false ), \"test%5Blength%5D=3&test%5Bfoo%5D=bar\", \"Sub-object with a length property\" );\n\n\tif ( jQuery.ajaxSettings === settings ) {\n\t\tdelete jQuery.ajaxSettings;\n\t} else {\n\t\tjQuery.ajaxSetup({ traditional: false });\n\t}\n});\n\ntest(\"jQuery.param() Constructed prop values\", function() {\n\texpect( 4 );\n\n\t/** @constructor */\n\tfunction Record() {\n\t\tthis[\"prop\"] = \"val\";\n\t}\n\n\tvar MyString = String,\n\t\t\tMyNumber = Number,\n\t\t\tparams = { \"test\": new MyString(\"foo\") };\n\n\tequal( jQuery.param( params, false ), \"test=foo\", \"Do not mistake new String() for a plain object\" );\n\n\tparams = { \"test\": new MyNumber(5) };\n\tequal( jQuery.param( params, false ), \"test=5\", \"Do not mistake new Number() for a plain object\" );\n\n\tparams = { \"test\": new Date() };\n\tok( jQuery.param( params, false ), \"(Non empty string returned) Do not mistake new Date() for a plain object\" );\n\n\t// should allow non-native constructed objects\n\tparams = { \"test\": new Record() };\n\tequal( jQuery.param( params, false ), jQuery.param({ \"test\": { \"prop\": \"val\" } }), \"Allow non-native constructed objects\" );\n});\n\ntest(\"serialize()\", function() {\n\texpect(5);\n\n\t// Add html5 elements only for serialize because selector can't yet find them on non-html5 browsers\n\tjQuery(\"#search\").after(\n\t\t\"<input type='email' id='html5email' name='email' value='dave@jquery.com' />\" +\n\t\t\"<input type='number' id='html5number' name='number' value='43' />\" +\n\t\t\"<input type='file' name='fileupload' />\"\n\t);\n\n\tequal( jQuery(\"#form\").serialize(),\n\t\t\"action=Test&radio2=on&check=on&hidden=&foo%5Bbar%5D=&name=name&search=search&email=dave%40jquery.com&number=43&select1=&select2=3&select3=1&select3=2&select5=3\",\n\t\t\"Check form serialization as query string\");\n\n\tequal( jQuery(\"input,select,textarea,button\", \"#form\").serialize(),\n\t\t\"action=Test&radio2=on&check=on&hidden=&foo%5Bbar%5D=&name=name&search=search&email=dave%40jquery.com&number=43&select1=&select2=3&select3=1&select3=2&select5=3\",\n\t\t\"Check input serialization as query string\");\n\n\tequal( jQuery(\"#testForm\").serialize(),\n\t\t\"T3=%3F%0D%0AZ&H1=x&H2=&PWD=&T1=&T2=YES&My+Name=me&S1=abc&S3=YES&S4=\",\n\t\t\"Check form serialization as query string\");\n\n\tequal( jQuery(\"input,select,textarea,button\", \"#testForm\").serialize(),\n\t\t\"T3=%3F%0D%0AZ&H1=x&H2=&PWD=&T1=&T2=YES&My+Name=me&S1=abc&S3=YES&S4=\",\n\t\t\"Check input serialization as query string\");\n\n\tequal( jQuery(\"#form, #testForm\").serialize(),\n\t\t\"action=Test&radio2=on&check=on&hidden=&foo%5Bbar%5D=&name=name&search=search&email=dave%40jquery.com&number=43&select1=&select2=3&select3=1&select3=2&select5=3&T3=%3F%0D%0AZ&H1=x&H2=&PWD=&T1=&T2=YES&My+Name=me&S1=abc&S3=YES&S4=\",\n\t\t\"Multiple form serialization as query string\");\n\n\t/* Temporarily disabled. Opera 10 has problems with form serialization.\n\tequal( jQuery(\"#form, #testForm :input\").serialize(),\n\t\t\"action=Test&radio2=on&check=on&hidden=&foo%5Bbar%5D=&name=name&search=search&email=dave%40jquery.com&number=43&select1=&select2=3&select3=1&select3=2&T3=%3F%0D%0AZ&H1=x&H2=&PWD=&T1=&T2=YES&My+Name=me&S1=abc&S3=YES&S4=\",\n\t\t\"Mixed form/input serialization as query string\");\n\t*/\n\tjQuery(\"#html5email, #html5number\").remove();\n});\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/jquery/test/unit/support.js",
    "content": "module(\"support\", { teardown: moduleTeardown });\n\nif ( jQuery.css ) {\n\ttestIframeWithCallback( \"body background is not lost if set prior to loading jQuery (#9239)\", \"support/bodyBackground.html\", function( color, support ) {\n\t\texpect( 2 );\n\t\t\tvar okValue = {\n\t\t\t\t\"#000000\": true,\n\t\t\t\t\"rgb(0, 0, 0)\": true\n\t\t\t};\n\t\tok( okValue[ color ], \"color was not reset (\" + color + \")\" );\n\n\t\tdeepEqual( jQuery.extend( {}, support ), jQuery.support, \"Same support properties\" );\n\t});\n}\n\ntestIframeWithCallback( \"A non-1 zoom on body doesn't cause WebKit to fail box-sizing test\", \"support/boxSizing.html\", function( boxSizing ) {\n\texpect( 1 );\n\tequal( boxSizing, jQuery.support.boxSizing, \"box-sizing properly detected on page with non-1 body zoom\" );\n});\n\ntestIframeWithCallback( \"A background on the testElement does not cause IE8 to crash (#9823)\", \"support/testElementCrash.html\", function() {\n\texpect( 1 );\n\tok( true, \"IE8 does not crash\" );\n});\n\ntestIframeWithCallback( \"box-sizing does not affect jQuery.support.shrinkWrapBlocks\", \"support/shrinkWrapBlocks.html\", function( shrinkWrapBlocks ) {\n\texpect( 1 );\n\tstrictEqual( shrinkWrapBlocks, jQuery.support.shrinkWrapBlocks, \"jQuery.support.shrinkWrapBlocks properties are the same\" );\n});\n\n(function() {\n\tvar expected, version,\n\t\tuserAgent = window.navigator.userAgent;\n\n\tif ( /chrome/i.test( userAgent ) ) {\n\t\texpected = {\n\t\t\t\"checkOn\":true,\n\t\t\t\"optSelected\":true,\n\t\t\t\"optDisabled\":true,\n\t\t\t\"focusinBubbles\":false,\n\t\t\t\"reliableMarginRight\":true,\n\t\t\t\"noCloneChecked\":true,\n\t\t\t\"radioValue\":true,\n\t\t\t\"checkClone\":true,\n\t\t\t\"ajax\":true,\n\t\t\t\"cors\":true,\n\t\t\t\"clearCloneStyle\": true,\n\t\t\t\"boxSizing\": true,\n\t\t\t\"boxSizingReliable\": true,\n\t\t\t\"pixelPosition\": false\n\t\t};\n\t} else if ( /opera.*version\\/12\\.1/i.test( userAgent ) ) {\n\t\texpected = {\n\t\t\t\"checkOn\":true,\n\t\t\t\"optSelected\":true,\n\t\t\t\"optDisabled\":true,\n\t\t\t\"focusinBubbles\":false,\n\t\t\t\"reliableMarginRight\":true,\n\t\t\t\"noCloneChecked\":true,\n\t\t\t\"radioValue\":false,\n\t\t\t\"checkClone\":true,\n\t\t\t\"ajax\":true,\n\t\t\t\"cors\":true,\n\t\t\t\"clearCloneStyle\": true,\n\t\t\t\"boxSizing\": true,\n\t\t\t\"boxSizingReliable\": true,\n\t\t\t\"pixelPosition\": true\n\t\t};\n\t} else if ( /msie 10\\.0/i.test( userAgent ) ) {\n\t\texpected = {\n\t\t\t\"checkOn\":true,\n\t\t\t\"optSelected\":false,\n\t\t\t\"optDisabled\":true,\n\t\t\t\"focusinBubbles\":true,\n\t\t\t\"reliableMarginRight\":true,\n\t\t\t\"noCloneChecked\":false,\n\t\t\t\"radioValue\":false,\n\t\t\t\"checkClone\":true,\n\t\t\t\"ajax\":true,\n\t\t\t\"cors\":true,\n\t\t\t\"clearCloneStyle\": false,\n\t\t\t\"boxSizing\": true,\n\t\t\t\"boxSizingReliable\": false,\n\t\t\t\"pixelPosition\": true\n\t\t};\n\t} else if ( /msie 9\\.0/i.test( userAgent ) ) {\n\t\texpected = {\n\t\t\t\"checkOn\":true,\n\t\t\t\"optSelected\":false,\n\t\t\t\"optDisabled\":true,\n\t\t\t\"focusinBubbles\":true,\n\t\t\t\"reliableMarginRight\":true,\n\t\t\t\"noCloneChecked\":false,\n\t\t\t\"radioValue\":false,\n\t\t\t\"checkClone\":true,\n\t\t\t\"ajax\":true,\n\t\t\t\"cors\":false,\n\t\t\t\"clearCloneStyle\": false,\n\t\t\t\"boxSizing\": true,\n\t\t\t\"boxSizingReliable\": false,\n\t\t\t\"pixelPosition\": true\n\t\t};\n\t} else if ( /5\\.1\\.\\d+ safari/i.test( userAgent ) ) {\n\t\texpected = {\n\t\t\t\"checkOn\":false,\n\t\t\t\"optSelected\":true,\n\t\t\t\"optDisabled\":true,\n\t\t\t\"focusinBubbles\":false,\n\t\t\t\"reliableMarginRight\":true,\n\t\t\t\"noCloneChecked\":true,\n\t\t\t\"radioValue\":true,\n\t\t\t\"checkClone\":false,\n\t\t\t\"ajax\":true,\n\t\t\t\"cors\":true,\n\t\t\t\"clearCloneStyle\": true,\n\t\t\t\"boxSizing\": true,\n\t\t\t\"boxSizingReliable\": true,\n\t\t\t\"pixelPosition\": false\n\t\t};\n\t} else if ( /firefox/i.test( userAgent ) ) {\n\t\tversion = userAgent.match( /firefox\\/(\\d+)/i )[ 1 ];\n\t\texpected = {\n\t\t\t\"checkOn\":true,\n\t\t\t\"optSelected\":true,\n\t\t\t\"optDisabled\":true,\n\t\t\t\"focusinBubbles\":false,\n\t\t\t\"reliableMarginRight\":true,\n\t\t\t\"noCloneChecked\":true,\n\t\t\t\"radioValue\":true,\n\t\t\t\"checkClone\":true,\n\t\t\t\"ajax\":true,\n\t\t\t\"cors\":true,\n\t\t\t\"clearCloneStyle\": true,\n\t\t\t\"boxSizing\": true,\n\t\t\t\"boxSizingReliable\": version >= 23,\n\t\t\t\"pixelPosition\": true\n\t\t};\n\t}\n\n\tif ( expected ) {\n\t\ttest(\"Verify that the support tests resolve as expected per browser\", function() {\n\t\t\tvar i, prop,\n\t\t\t\tj = 0;\n\n\t\t\tfor ( prop in jQuery.support ) {\n\t\t\t\tj++;\n\t\t\t}\n\n\t\t\texpect( j );\n\n\t\t\tfor ( i in expected ) {\n\t\t\t\tif ( jQuery.ajax || i !== \"ajax\" && i !== \"cors\" ) {\n\t\t\t\t\tequal( jQuery.support[i], expected[i], \"jQuery.support['\" + i + \"']: \" + jQuery.support[i] + \", expected['\" + i + \"']: \" + expected[i]);\n\t\t\t\t} else {\n\t\t\t\t\tok( true, \"no ajax; skipping jQuery.support['\" + i + \"']\" );\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t}\n\n})();\n\n// Support: Safari 5.1\n// Shameless browser-sniff, but Safari 5.1 mishandles CSP\nif ( !( typeof navigator !== \"undefined\" &&\n\t(/ AppleWebKit\\/\\d.*? Version\\/(\\d+)/.exec(navigator.userAgent) || [])[1] < 6 ) ) {\n\n\ttestIframeWithCallback( \"Check CSP (https://developer.mozilla.org/en-US/docs/Security/CSP) restrictions\", \"support/csp.php\", function( support ) {\n\t\texpect( 1 );\n\t\tdeepEqual( jQuery.extend( {}, support ), jQuery.support, \"No violations of CSP polices\" );\n\t});\n}\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/jquery/test/unit/traversing.js",
    "content": "module(\"traversing\", { teardown: moduleTeardown });\n\ntest( \"find(String)\", function() {\n\texpect( 1 );\n\tequal( jQuery(\"#foo\").find(\".blogTest\").text(), \"Yahoo\", \"Basic selector\" );\n});\n\ntest( \"find(String) under non-elements\", function() {\n\texpect( 2 );\n\n\tvar j = jQuery(\"#nonnodes\").contents();\n\tequal( j.find(\"div\").length, 0, \"Check node,textnode,comment to find zero divs\" );\n\tequal( j.find(\"div\").addBack().length, 3, \"Check node,textnode,comment to find zero divs, but preserves pushStack\" );\n});\n\ntest( \"find(leading combinator)\", function() {\n\texpect( 4 );\n\n\tdeepEqual( jQuery(\"#qunit-fixture\").find(\"> div\").get(), q( \"foo\", \"nothiddendiv\", \"moretests\", \"tabindex-tests\", \"liveHandlerOrder\", \"siblingTest\", \"fx-test-group\" ), \"find child elements\" );\n\tdeepEqual( jQuery(\"#qunit-fixture\").find(\"> #foo, > #moretests\").get(), q( \"foo\", \"moretests\" ), \"find child elements\" );\n\tdeepEqual( jQuery(\"#qunit-fixture\").find(\"> #foo > p\").get(), q( \"sndp\", \"en\", \"sap\" ), \"find child elements\" );\n\n\tdeepEqual( jQuery(\"#siblingTest, #siblingfirst\").find(\"+ *\").get(), q( \"siblingnext\", \"fx-test-group\" ), \"ensure document order\" );\n});\n\ntest( \"find(node|jQuery object)\", function() {\n\texpect( 12 );\n\n\tvar $foo = jQuery(\"#foo\"),\n\t\t$blog = jQuery(\".blogTest\"),\n\t\t$first = jQuery(\"#first\"),\n\t\t$two = $blog.add( $first ),\n\t\t$fooTwo = $foo.add( $blog );\n\n\tequal( $foo.find( $blog ).text(), \"Yahoo\", \"Find with blog jQuery object\" );\n\tequal( $foo.find( $blog[ 0 ] ).text(), \"Yahoo\", \"Find with blog node\" );\n\tequal( $foo.find( $first ).length, 0, \"#first is not in #foo\" );\n\tequal( $foo.find( $first[ 0 ]).length, 0, \"#first not in #foo (node)\" );\n\tok( $foo.find( $two ).is(\".blogTest\"), \"Find returns only nodes within #foo\" );\n\tok( $fooTwo.find( $blog ).is(\".blogTest\"), \"Blog is part of the collection, but also within foo\" );\n\tok( $fooTwo.find( $blog[ 0 ] ).is(\".blogTest\"), \"Blog is part of the collection, but also within foo(node)\" );\n\n\tequal( $two.find( $foo ).length, 0, \"Foo is not in two elements\" );\n\tequal( $two.find( $foo[ 0 ] ).length, 0, \"Foo is not in two elements(node)\" );\n\tequal( $two.find( $first ).length, 0, \"first is in the collection and not within two\" );\n\tequal( $two.find( $first ).length, 0, \"first is in the collection and not within two(node)\" );\n\n\tequal( $two.find( $foo[ 0 ] ).addBack().length, 2, \"find preserves the pushStack, see #12009\" );\n});\n\ntest(\"is(String|undefined)\", function() {\n\texpect(23);\n\tok( jQuery(\"#form\").is(\"form\"), \"Check for element: A form must be a form\" );\n\tok( !jQuery(\"#form\").is(\"div\"), \"Check for element: A form is not a div\" );\n\tok( jQuery(\"#mark\").is(\".blog\"), \"Check for class: Expected class 'blog'\" );\n\tok( !jQuery(\"#mark\").is(\".link\"), \"Check for class: Did not expect class 'link'\" );\n\tok( jQuery(\"#simon\").is(\".blog.link\"), \"Check for multiple classes: Expected classes 'blog' and 'link'\" );\n\tok( !jQuery(\"#simon\").is(\".blogTest\"), \"Check for multiple classes: Expected classes 'blog' and 'link', but not 'blogTest'\" );\n\tok( jQuery(\"#en\").is(\"[lang=\\\"en\\\"]\"), \"Check for attribute: Expected attribute lang to be 'en'\" );\n\tok( !jQuery(\"#en\").is(\"[lang=\\\"de\\\"]\"), \"Check for attribute: Expected attribute lang to be 'en', not 'de'\" );\n\tok( jQuery(\"#text1\").is(\"[type=\\\"text\\\"]\"), \"Check for attribute: Expected attribute type to be 'text'\" );\n\tok( !jQuery(\"#text1\").is(\"[type=\\\"radio\\\"]\"), \"Check for attribute: Expected attribute type to be 'text', not 'radio'\" );\n\tok( jQuery(\"#text2\").is(\":disabled\"), \"Check for pseudoclass: Expected to be disabled\" );\n\tok( !jQuery(\"#text1\").is(\":disabled\"), \"Check for pseudoclass: Expected not disabled\" );\n\tok( jQuery(\"#radio2\").is(\":checked\"), \"Check for pseudoclass: Expected to be checked\" );\n\tok( !jQuery(\"#radio1\").is(\":checked\"), \"Check for pseudoclass: Expected not checked\" );\n\n\tok( !jQuery(\"#foo\").is(0), \"Expected false for an invalid expression - 0\" );\n\tok( !jQuery(\"#foo\").is(null), \"Expected false for an invalid expression - null\" );\n\tok( !jQuery(\"#foo\").is(\"\"), \"Expected false for an invalid expression - \\\"\\\"\" );\n\tok( !jQuery(\"#foo\").is(undefined), \"Expected false for an invalid expression - undefined\" );\n\tok( !jQuery(\"#foo\").is({ plain: \"object\" }), \"Check passing invalid object\" );\n\n\t// test is() with comma-separated expressions\n\tok( jQuery(\"#en\").is(\"[lang=\\\"en\\\"],[lang=\\\"de\\\"]\"), \"Comma-separated; Check for lang attribute: Expect en or de\" );\n\tok( jQuery(\"#en\").is(\"[lang=\\\"de\\\"],[lang=\\\"en\\\"]\"), \"Comma-separated; Check for lang attribute: Expect en or de\" );\n\tok( jQuery(\"#en\").is(\"[lang=\\\"en\\\"] , [lang=\\\"de\\\"]\"), \"Comma-separated; Check for lang attribute: Expect en or de\" );\n\tok( jQuery(\"#en\").is(\"[lang=\\\"de\\\"] , [lang=\\\"en\\\"]\"), \"Comma-separated; Check for lang attribute: Expect en or de\" );\n});\n\ntest(\"is() against non-elements (#10178)\", function() {\n\texpect(14);\n\n\tvar label, i, test,\n\t\tcollection = jQuery( document ),\n\t\ttests = [ \"a\", \"*\" ],\n\t\tnonelements = {\n\t\t\ttext: document.createTextNode(\"\"),\n\t\t\tcomment: document.createComment(\"\"),\n\t\t\tdocument: document,\n\t\t\twindow: window,\n\t\t\tarray: [],\n\t\t\t\"plain object\": {},\n\t\t\t\"function\": function() {}\n\t\t};\n\n\tfor ( label in nonelements ) {\n\t\tcollection[ 0 ] = nonelements[ label ];\n\t\tfor ( i = 0; i < tests.length; i++ ) {\n\t\t\ttest = tests[ i ];\n\t\t\tok( !collection.is( test ), label + \" does not match \\\"\" + test + \"\\\"\" );\n\t\t}\n\t}\n});\n\ntest(\"is(jQuery)\", function() {\n\texpect(19);\n\tok( jQuery(\"#form\").is( jQuery(\"form\") ), \"Check for element: A form is a form\" );\n\tok( !jQuery(\"#form\").is( jQuery(\"div\") ), \"Check for element: A form is not a div\" );\n\tok( jQuery(\"#mark\").is( jQuery(\".blog\") ), \"Check for class: Expected class 'blog'\" );\n\tok( !jQuery(\"#mark\").is( jQuery(\".link\") ), \"Check for class: Did not expect class 'link'\" );\n\tok( jQuery(\"#simon\").is( jQuery(\".blog.link\") ), \"Check for multiple classes: Expected classes 'blog' and 'link'\" );\n\tok( !jQuery(\"#simon\").is( jQuery(\".blogTest\") ), \"Check for multiple classes: Expected classes 'blog' and 'link', but not 'blogTest'\" );\n\tok( jQuery(\"#en\").is( jQuery(\"[lang=\\\"en\\\"]\") ), \"Check for attribute: Expected attribute lang to be 'en'\" );\n\tok( !jQuery(\"#en\").is( jQuery(\"[lang=\\\"de\\\"]\") ), \"Check for attribute: Expected attribute lang to be 'en', not 'de'\" );\n\tok( jQuery(\"#text1\").is( jQuery(\"[type=\\\"text\\\"]\") ), \"Check for attribute: Expected attribute type to be 'text'\" );\n\tok( !jQuery(\"#text1\").is( jQuery(\"[type=\\\"radio\\\"]\") ), \"Check for attribute: Expected attribute type to be 'text', not 'radio'\" );\n\tok( !jQuery(\"#text1\").is( jQuery(\"input:disabled\") ), \"Check for pseudoclass: Expected not disabled\" );\n\tok( jQuery(\"#radio2\").is( jQuery(\"input:checked\") ), \"Check for pseudoclass: Expected to be checked\" );\n\tok( !jQuery(\"#radio1\").is( jQuery(\"input:checked\") ), \"Check for pseudoclass: Expected not checked\" );\n\n\t// Some raw elements\n\tok( jQuery(\"#form\").is( jQuery(\"form\")[0] ), \"Check for element: A form is a form\" );\n\tok( !jQuery(\"#form\").is( jQuery(\"div\")[0] ), \"Check for element: A form is not a div\" );\n\tok( jQuery(\"#mark\").is( jQuery(\".blog\")[0] ), \"Check for class: Expected class 'blog'\" );\n\tok( !jQuery(\"#mark\").is( jQuery(\".link\")[0] ), \"Check for class: Did not expect class 'link'\" );\n\tok( jQuery(\"#simon\").is( jQuery(\".blog.link\")[0] ), \"Check for multiple classes: Expected classes 'blog' and 'link'\" );\n\tok( !jQuery(\"#simon\").is( jQuery(\".blogTest\")[0] ), \"Check for multiple classes: Expected classes 'blog' and 'link', but not 'blogTest'\" );\n});\n\ntest(\"is() with :has() selectors\", function() {\n\texpect(6);\n\n\tok( jQuery(\"#foo\").is(\":has(p)\"), \"Check for child: Expected a child 'p' element\" );\n\tok( !jQuery(\"#foo\").is(\":has(ul)\"), \"Check for child: Did not expect 'ul' element\" );\n\tok( jQuery(\"#foo\").is(\":has(p):has(a):has(code)\"), \"Check for childs: Expected 'p', 'a' and 'code' child elements\" );\n\tok( !jQuery(\"#foo\").is(\":has(p):has(a):has(code):has(ol)\"), \"Check for childs: Expected 'p', 'a' and 'code' child elements, but no 'ol'\" );\n\n\tok( jQuery(\"#foo\").is( jQuery(\"div:has(p)\") ), \"Check for child: Expected a child 'p' element\" );\n\tok( !jQuery(\"#foo\").is( jQuery(\"div:has(ul)\") ), \"Check for child: Did not expect 'ul' element\" );\n});\n\ntest(\"is() with positional selectors\", function() {\n\texpect(27);\n\n\tvar\n\t\tposp = jQuery(\n\t\t\t\"<p id='posp'><a class='firsta' href='#'><em>first</em></a>\" +\n\t\t\t\"<a class='seconda' href='#'><b>test</b></a><em></em></p>\"\n\t\t).appendTo( \"#qunit-fixture\" ),\n\t\tisit = function( sel, match, expect ) {\n\t\t\tequal(\n\t\t\t\tjQuery( sel ).is( match ),\n\t\t\t\texpect,\n\t\t\t\t\"jQuery('\" + sel + \"').is('\" + match + \"')\"\n\t\t\t);\n\t\t};\n\n\tisit( \"#posp\", \"p:last\", true );\n\tisit( \"#posp\", \"#posp:first\", true );\n\tisit( \"#posp\", \"#posp:eq(2)\", false );\n\tisit( \"#posp\", \"#posp a:first\", false );\n\n\tisit( \"#posp .firsta\", \"#posp a:first\", true );\n\tisit( \"#posp .firsta\", \"#posp a:last\", false );\n\tisit( \"#posp .firsta\", \"#posp a:even\", true );\n\tisit( \"#posp .firsta\", \"#posp a:odd\", false );\n\tisit( \"#posp .firsta\", \"#posp a:eq(0)\", true );\n\tisit( \"#posp .firsta\", \"#posp a:eq(9)\", false );\n\tisit( \"#posp .firsta\", \"#posp em:eq(0)\", false );\n\tisit( \"#posp .firsta\", \"#posp em:first\", false );\n\tisit( \"#posp .firsta\", \"#posp:first\", false );\n\n\tisit( \"#posp .seconda\", \"#posp a:first\", false );\n\tisit( \"#posp .seconda\", \"#posp a:last\", true );\n\tisit( \"#posp .seconda\", \"#posp a:gt(0)\", true );\n\tisit( \"#posp .seconda\", \"#posp a:lt(5)\", true );\n\tisit( \"#posp .seconda\", \"#posp a:lt(1)\", false );\n\n\tisit( \"#posp em\", \"#posp a:eq(0) em\", true );\n\tisit( \"#posp em\", \"#posp a:lt(1) em\", true );\n\tisit( \"#posp em\", \"#posp a:gt(1) em\", false );\n\tisit( \"#posp em\", \"#posp a:first em\", true );\n\tisit( \"#posp em\", \"#posp a em:last\", true );\n\tisit( \"#posp em\", \"#posp a em:eq(2)\", false );\n\n\tok( jQuery(\"#option1b\").is(\"#select1 option:not(:first)\"), \"POS inside of :not() (#10970)\" );\n\n\tok( jQuery( posp[0] ).is(\"p:last\"), \"context constructed from a single node (#13797)\" );\n\tok( !jQuery( posp[0] ).find(\"#firsta\").is(\"a:first\"), \"context derived from a single node (#13797)\" );\n});\n\ntest(\"index()\", function() {\n\texpect( 2 );\n\n\tequal( jQuery(\"#text2\").index(), 2, \"Returns the index of a child amongst its siblings\" );\n\n\tequal( jQuery(\"<div/>\").index(), -1, \"Node without parent returns -1\" );\n});\n\ntest(\"index(Object|String|undefined)\", function() {\n\texpect(16);\n\n\tvar elements = jQuery([window, document]),\n\t\tinputElements = jQuery(\"#radio1,#radio2,#check1,#check2\");\n\n\t// Passing a node\n\tequal( elements.index(window), 0, \"Check for index of elements\" );\n\tequal( elements.index(document), 1, \"Check for index of elements\" );\n\tequal( inputElements.index(document.getElementById(\"radio1\")), 0, \"Check for index of elements\" );\n\tequal( inputElements.index(document.getElementById(\"radio2\")), 1, \"Check for index of elements\" );\n\tequal( inputElements.index(document.getElementById(\"check1\")), 2, \"Check for index of elements\" );\n\tequal( inputElements.index(document.getElementById(\"check2\")), 3, \"Check for index of elements\" );\n\tequal( inputElements.index(window), -1, \"Check for not found index\" );\n\tequal( inputElements.index(document), -1, \"Check for not found index\" );\n\n\t// Passing a jQuery object\n\t// enabled since [5500]\n\tequal( elements.index( elements ), 0, \"Pass in a jQuery object\" );\n\tequal( elements.index( elements.eq(1) ), 1, \"Pass in a jQuery object\" );\n\tequal( jQuery(\"#form input[type='radio']\").index( jQuery(\"#radio2\") ), 1, \"Pass in a jQuery object\" );\n\n\t// Passing a selector or nothing\n\t// enabled since [6330]\n\tequal( jQuery(\"#text2\").index(), 2, \"Check for index amongst siblings\" );\n\tequal( jQuery(\"#form\").children().eq(4).index(), 4, \"Check for index amongst siblings\" );\n\tequal( jQuery(\"#radio2\").index(\"#form input[type='radio']\") , 1, \"Check for index within a selector\" );\n\tequal( jQuery(\"#form input[type='radio']\").index( jQuery(\"#radio2\") ), 1, \"Check for index within a selector\" );\n\tequal( jQuery(\"#radio2\").index(\"#form input[type='text']\") , -1, \"Check for index not found within a selector\" );\n});\n\ntest(\"filter(Selector|undefined)\", function() {\n\texpect(9);\n\tdeepEqual( jQuery(\"#form input\").filter(\":checked\").get(), q(\"radio2\", \"check1\"), \"filter(String)\" );\n\tdeepEqual( jQuery(\"p\").filter(\"#ap, #sndp\").get(), q(\"ap\", \"sndp\"), \"filter('String, String')\" );\n\tdeepEqual( jQuery(\"p\").filter(\"#ap,#sndp\").get(), q(\"ap\", \"sndp\"), \"filter('String,String')\" );\n\n\tdeepEqual( jQuery(\"p\").filter(null).get(),      [], \"filter(null) should return an empty jQuery object\");\n\tdeepEqual( jQuery(\"p\").filter(undefined).get(), [], \"filter(undefined) should return an empty jQuery object\");\n\tdeepEqual( jQuery(\"p\").filter(0).get(),         [], \"filter(0) should return an empty jQuery object\");\n\tdeepEqual( jQuery(\"p\").filter(\"\").get(),        [], \"filter('') should return an empty jQuery object\");\n\n\t// using contents will get comments regular, text, and comment nodes\n\tvar j = jQuery(\"#nonnodes\").contents();\n\tequal( j.filter(\"span\").length, 1, \"Check node,textnode,comment to filter the one span\" );\n\tequal( j.filter(\"[name]\").length, 0, \"Check node,textnode,comment to filter the one span\" );\n});\n\ntest(\"filter(Function)\", function() {\n\texpect(2);\n\n\tdeepEqual( jQuery(\"#qunit-fixture p\").filter(function() {\n\t\treturn !jQuery(\"a\", this).length;\n\t}).get(), q(\"sndp\", \"first\"), \"filter(Function)\" );\n\n\tdeepEqual( jQuery(\"#qunit-fixture p\").filter(function(i, elem) { return !jQuery(\"a\", elem).length; }).get(), q(\"sndp\", \"first\"), \"filter(Function) using arg\" );\n});\n\ntest(\"filter(Element)\", function() {\n\texpect(1);\n\n\tvar element = document.getElementById(\"text1\");\n\tdeepEqual( jQuery(\"#form input\").filter(element).get(), q(\"text1\"), \"filter(Element)\" );\n});\n\ntest(\"filter(Array)\", function() {\n\texpect(1);\n\n\tvar elements = [ document.getElementById(\"text1\") ];\n\tdeepEqual( jQuery(\"#form input\").filter(elements).get(), q(\"text1\"), \"filter(Element)\" );\n});\n\ntest(\"filter(jQuery)\", function() {\n\texpect(1);\n\n\tvar elements = jQuery(\"#text1\");\n\tdeepEqual( jQuery(\"#form input\").filter(elements).get(), q(\"text1\"), \"filter(Element)\" );\n});\n\n\ntest(\"filter() with positional selectors\", function() {\n\texpect(19);\n\n\tvar filterit = function(sel, filter, length) {\n\t\tequal( jQuery( sel ).filter( filter ).length, length, \"jQuery( \" + sel + \" ).filter( \" + filter + \" )\" );\n\t};\n\n\tjQuery( \"\" +\n\t\t\"<p id='posp'>\" +\n\t\t\t\"<a class='firsta' href='#'>\" +\n\t\t\t\t\"<em>first</em>\" +\n\t\t\t\"</a>\" +\n\t\t\t\"<a class='seconda' href='#'>\" +\n\t\t\t\t\"<b>test</b>\" +\n\t\t\t\"</a>\" +\n\t\t\t\"<em></em>\" +\n\t\t\"</p>\" ).appendTo( \"#qunit-fixture\" );\n\n\tfilterit( \"#posp\", \"#posp:first\", 1);\n\tfilterit( \"#posp\", \"#posp:eq(2)\", 0 );\n\tfilterit( \"#posp\", \"#posp a:first\", 0 );\n\n\t// Keep in mind this is within the selection and\n\t// not in relation to other elements (.is() is a different story)\n\tfilterit( \"#posp .firsta\", \"#posp a:first\", 1 );\n\tfilterit( \"#posp .firsta\", \"#posp a:last\", 1 );\n\tfilterit( \"#posp .firsta\", \"#posp a:last-child\", 0 );\n\tfilterit( \"#posp .firsta\", \"#posp a:even\", 1 );\n\tfilterit( \"#posp .firsta\", \"#posp a:odd\", 0 );\n\tfilterit( \"#posp .firsta\", \"#posp a:eq(0)\", 1 );\n\tfilterit( \"#posp .firsta\", \"#posp a:eq(9)\", 0 );\n\tfilterit( \"#posp .firsta\", \"#posp em:eq(0)\", 0 );\n\tfilterit( \"#posp .firsta\", \"#posp em:first\", 0 );\n\tfilterit( \"#posp .firsta\", \"#posp:first\", 0 );\n\n\tfilterit( \"#posp .seconda\", \"#posp a:first\", 1 );\n\tfilterit( \"#posp .seconda\", \"#posp em:first\", 0 );\n\tfilterit( \"#posp .seconda\", \"#posp a:last\", 1 );\n\tfilterit( \"#posp .seconda\", \"#posp a:gt(0)\", 0 );\n\tfilterit( \"#posp .seconda\", \"#posp a:lt(5)\", 1 );\n\tfilterit( \"#posp .seconda\", \"#posp a:lt(1)\", 1 );\n});\n\ntest(\"closest()\", function() {\n\texpect( 13 );\n\n\tvar jq;\n\n\tdeepEqual( jQuery(\"body\").closest(\"body\").get(), q(\"body\"), \"closest(body)\" );\n\tdeepEqual( jQuery(\"body\").closest(\"html\").get(), q(\"html\"), \"closest(html)\" );\n\tdeepEqual( jQuery(\"body\").closest(\"div\").get(), [], \"closest(div)\" );\n\tdeepEqual( jQuery(\"#qunit-fixture\").closest(\"span,#html\").get(), q(\"html\"), \"closest(span,#html)\" );\n\n\t// Test .closest() limited by the context\n\tjq = jQuery(\"#nothiddendivchild\");\n\tdeepEqual( jq.closest(\"html\", document.body).get(), [], \"Context limited.\" );\n\tdeepEqual( jq.closest(\"body\", document.body).get(), [], \"Context limited.\" );\n\tdeepEqual( jq.closest(\"#nothiddendiv\", document.body).get(), q(\"nothiddendiv\"), \"Context not reached.\" );\n\n\t//Test that .closest() returns unique'd set\n\tequal( jQuery(\"#qunit-fixture p\").closest(\"#qunit-fixture\").length, 1, \"Closest should return a unique set\" );\n\n\t// Test on disconnected node\n\tequal( jQuery(\"<div><p></p></div>\").find(\"p\").closest(\"table\").length, 0, \"Make sure disconnected closest work.\" );\n\n\t// Bug #7369\n\tequal( jQuery(\"<div foo='bar'></div>\").closest(\"[foo]\").length, 1, \"Disconnected nodes with attribute selector\" );\n\tequal( jQuery(\"<div>text</div>\").closest(\"[lang]\").length, 0, \"Disconnected nodes with text and non-existent attribute selector\" );\n\n\tok( !jQuery(document).closest(\"#foo\").length, \"Calling closest on a document fails silently\" );\n\n\tjq = jQuery(\"<div>text</div>\");\n\tdeepEqual( jq.contents().closest(\"*\").get(), jq.get(), \"Text node input (#13332)\" );\n});\n\ntest(\"closest() with positional selectors\", function() {\n\texpect( 2 );\n\n\tdeepEqual( jQuery(\"#qunit-fixture\").closest(\"div:first\").get(), [], \"closest(div:first)\" );\n\tdeepEqual( jQuery(\"#qunit-fixture div\").closest(\"body:first div:last\").get(), q(\"fx-tests\"), \"closest(body:first div:last)\" );\n});\n\ntest(\"closest(jQuery)\", function() {\n\texpect(8);\n\tvar $child = jQuery(\"#nothiddendivchild\"),\n\t\t$parent = jQuery(\"#nothiddendiv\"),\n\t\t$sibling = jQuery(\"#foo\"),\n\t\t$body = jQuery(\"body\");\n\tok( $child.closest( $parent ).is(\"#nothiddendiv\"), \"closest( jQuery('#nothiddendiv') )\" );\n\tok( $child.closest( $parent[0] ).is(\"#nothiddendiv\"), \"closest( jQuery('#nothiddendiv') ) :: node\" );\n\tok( $child.closest( $child ).is(\"#nothiddendivchild\"), \"child is included\" );\n\tok( $child.closest( $child[0] ).is(\"#nothiddendivchild\"), \"child is included  :: node\" );\n\tequal( $child.closest( document.createElement(\"div\") ).length, 0, \"created element is not related\" );\n\tequal( $child.closest( $sibling ).length, 0, \"Sibling not a parent of child\" );\n\tequal( $child.closest( $sibling[0] ).length, 0, \"Sibling not a parent of child :: node\" );\n\tok( $child.closest( $body.add($parent) ).is(\"#nothiddendiv\"), \"Closest ancestor retrieved.\" );\n});\n\ntest(\"not(Selector|undefined)\", function() {\n\texpect(11);\n\tequal( jQuery(\"#qunit-fixture > p#ap > a\").not(\"#google\").length, 2, \"not('selector')\" );\n\tdeepEqual( jQuery(\"p\").not(\".result\").get(), q(\"firstp\", \"ap\", \"sndp\", \"en\", \"sap\", \"first\"), \"not('.class')\" );\n\tdeepEqual( jQuery(\"p\").not(\"#ap, #sndp, .result\").get(), q(\"firstp\", \"en\", \"sap\", \"first\"), \"not('selector, selector')\" );\n\n\tdeepEqual( jQuery(\"#ap *\").not(\"code\").get(), q(\"google\", \"groups\", \"anchor1\", \"mark\"), \"not('tag selector')\" );\n\tdeepEqual( jQuery(\"#ap *\").not(\"code, #mark\").get(), q(\"google\", \"groups\", \"anchor1\"), \"not('tag, ID selector')\" );\n\tdeepEqual( jQuery(\"#ap *\").not(\"#mark, code\").get(), q(\"google\", \"groups\", \"anchor1\"), \"not('ID, tag selector')\");\n\n\tvar all = jQuery(\"p\").get();\n\tdeepEqual( jQuery(\"p\").not(null).get(),      all, \"not(null) should have no effect\");\n\tdeepEqual( jQuery(\"p\").not(undefined).get(), all, \"not(undefined) should have no effect\");\n\tdeepEqual( jQuery(\"p\").not(0).get(),         all, \"not(0) should have no effect\");\n\tdeepEqual( jQuery(\"p\").not(\"\").get(),        all, \"not('') should have no effect\");\n\n\tdeepEqual(\n\t\tjQuery(\"#form option\").not(\"option.emptyopt:contains('Nothing'),optgroup *,[value='1']\").get(),\n\t\tq(\"option1c\", \"option1d\", \"option2c\", \"option2d\", \"option3c\", \"option3d\", \"option3e\", \"option4d\", \"option4e\", \"option5a\", \"option5b\"),\n\t\t\"not('complex selector')\"\n\t);\n});\n\ntest(\"not(Element)\", function() {\n\texpect(1);\n\n\tvar selects = jQuery(\"#form select\");\n\tdeepEqual( selects.not( selects[1] ).get(), q(\"select1\", \"select3\", \"select4\", \"select5\"), \"filter out DOM element\");\n});\n\ntest(\"not(Function)\", function() {\n\texpect(1);\n\n\tdeepEqual( jQuery(\"#qunit-fixture p\").not(function() { return jQuery(\"a\", this).length; }).get(), q(\"sndp\", \"first\"), \"not(Function)\" );\n});\n\ntest(\"not(Array)\", function() {\n\texpect(2);\n\n\tequal( jQuery(\"#qunit-fixture > p#ap > a\").not(document.getElementById(\"google\")).length, 2, \"not(DOMElement)\" );\n\tequal( jQuery(\"p\").not(document.getElementsByTagName(\"p\")).length, 0, \"not(Array-like DOM collection)\" );\n});\n\ntest(\"not(jQuery)\", function() {\n\texpect( 1 );\n\n\tdeepEqual( jQuery(\"p\").not(jQuery(\"#ap, #sndp, .result\")).get(), q(\"firstp\", \"en\", \"sap\", \"first\"), \"not(jQuery)\" );\n});\n\ntest(\"has(Element)\", function() {\n\texpect(3);\n\tvar obj, detached, multipleParent;\n\n\tobj = jQuery(\"#qunit-fixture\").has(jQuery(\"#sndp\")[0]);\n\tdeepEqual( obj.get(), q(\"qunit-fixture\"), \"Keeps elements that have the element as a descendant\" );\n\n\tdetached = jQuery(\"<a><b><i/></b></a>\");\n\tdeepEqual( detached.has( detached.find(\"i\")[0] ).get(), detached.get(), \"...Even when detached\" );\n\n\tmultipleParent = jQuery(\"#qunit-fixture, #header\").has(jQuery(\"#sndp\")[0]);\n\tdeepEqual( multipleParent.get(), q(\"qunit-fixture\"), \"Does not include elements that do not have the element as a descendant\" );\n});\n\ntest(\"has(Selector)\", function() {\n\texpect( 5 );\n\n\tvar obj, detached, multipleParent, multipleHas;\n\n\tobj = jQuery(\"#qunit-fixture\").has(\"#sndp\");\n\tdeepEqual( obj.get(), q(\"qunit-fixture\"), \"Keeps elements that have any element matching the selector as a descendant\" );\n\n\tdetached = jQuery(\"<a><b><i/></b></a>\");\n\tdeepEqual( detached.has(\"i\").get(), detached.get(), \"...Even when detached\" );\n\n\tmultipleParent = jQuery(\"#qunit-fixture, #header\").has(\"#sndp\");\n\tdeepEqual( multipleParent.get(), q(\"qunit-fixture\"), \"Does not include elements that do not have the element as a descendant\" );\n\n\tmultipleParent = jQuery(\"#select1, #select2, #select3\").has(\"#option1a, #option3a\");\n\tdeepEqual( multipleParent.get(), q(\"select1\", \"select3\"), \"Multiple contexts are checks correctly\" );\n\n\tmultipleHas = jQuery(\"#qunit-fixture\").has(\"#sndp, #first\");\n\tdeepEqual( multipleHas.get(), q(\"qunit-fixture\"), \"Only adds elements once\" );\n});\n\ntest(\"has(Arrayish)\", function() {\n\texpect(4);\n\n\tvar simple, detached, multipleParent, multipleHas;\n\n\tsimple = jQuery(\"#qunit-fixture\").has(jQuery(\"#sndp\"));\n\tdeepEqual( simple.get(), q(\"qunit-fixture\"), \"Keeps elements that have any element in the jQuery list as a descendant\" );\n\n\tdetached = jQuery(\"<a><b><i/></b></a>\");\n\tdeepEqual( detached.has( detached.find(\"i\") ).get(), detached.get(), \"...Even when detached\" );\n\n\tmultipleParent = jQuery(\"#qunit-fixture, #header\").has(jQuery(\"#sndp\"));\n\tdeepEqual( multipleParent.get(), q(\"qunit-fixture\"), \"Does not include elements that do not have an element in the jQuery list as a descendant\" );\n\n\tmultipleHas = jQuery(\"#qunit-fixture\").has(jQuery(\"#sndp, #first\"));\n\tdeepEqual( multipleHas.get(), q(\"qunit-fixture\"), \"Only adds elements once\" );\n});\n\ntest(\"addBack()\", function() {\n\texpect(5);\n\tdeepEqual( jQuery(\"#en\").siblings().addBack().get(), q(\"sndp\", \"en\", \"sap\"), \"Check for siblings and self\" );\n\tdeepEqual( jQuery(\"#foo\").children().addBack().get(), q(\"foo\", \"sndp\", \"en\", \"sap\"), \"Check for children and self\" );\n\tdeepEqual( jQuery(\"#sndp, #en\").parent().addBack().get(), q(\"foo\",\"sndp\",\"en\"), \"Check for parent and self\" );\n\tdeepEqual( jQuery(\"#groups\").parents(\"p, div\").addBack().get(), q(\"qunit-fixture\", \"ap\", \"groups\"), \"Check for parents and self\" );\n\tdeepEqual( jQuery(\"#select1 > option\").filter(\":first-child\").addBack(\":last-child\").get(), q(\"option1a\", \"option1d\"), \"Should contain the last elems plus the *filtered* prior set elements\" );\n});\n\ntest(\"siblings([String])\", function() {\n\texpect(6);\n\tdeepEqual( jQuery(\"#en\").siblings().get(), q(\"sndp\", \"sap\"), \"Check for siblings\" );\n\tdeepEqual( jQuery(\"#nonnodes\").contents().eq(1).siblings().get(), q(\"nonnodesElement\"), \"Check for text node siblings\" );\n\tdeepEqual( jQuery(\"#foo\").siblings(\"form, b\").get(), q(\"form\", \"floatTest\", \"lengthtest\", \"name-tests\", \"testForm\"), \"Check for multiple filters\" );\n\n\tvar set = q(\"sndp\", \"en\", \"sap\");\n\tdeepEqual( jQuery(\"#en, #sndp\").siblings().get(), set, \"Check for unique results from siblings\" );\n\tdeepEqual( jQuery(\"#option5a\").siblings(\"option[data-attr]\").get(), q(\"option5c\"), \"Has attribute selector in siblings (#9261)\" );\n\tequal( jQuery(\"<a/>\").siblings().length, 0, \"Detached elements have no siblings (#11370)\" );\n});\n\ntest(\"siblings([String]) - jQuery only\", function() {\n\texpect(2);\n\tdeepEqual( jQuery(\"#sndp\").siblings(\":has(code)\").get(), q(\"sap\"), \"Check for filtered siblings (has code child element)\" );\n\tdeepEqual( jQuery(\"#sndp\").siblings(\":has(a)\").get(), q(\"en\", \"sap\"), \"Check for filtered siblings (has anchor child element)\" );\n});\n\ntest(\"children([String])\", function() {\n\texpect(2);\n\tdeepEqual( jQuery(\"#foo\").children().get(), q(\"sndp\", \"en\", \"sap\"), \"Check for children\" );\n\tdeepEqual( jQuery(\"#foo\").children(\"#en, #sap\").get(), q(\"en\", \"sap\"), \"Check for multiple filters\" );\n});\n\ntest(\"children([String]) - jQuery only\", function() {\n\texpect(1);\n\tdeepEqual( jQuery(\"#foo\").children(\":has(code)\").get(), q(\"sndp\", \"sap\"), \"Check for filtered children\" );\n});\n\ntest(\"parent([String])\", function() {\n\texpect(6);\n\n\tvar $el;\n\n\tequal( jQuery(\"#groups\").parent()[0].id, \"ap\", \"Simple parent check\" );\n\tequal( jQuery(\"#groups\").parent(\"p\")[0].id, \"ap\", \"Filtered parent check\" );\n\tequal( jQuery(\"#groups\").parent(\"div\").length, 0, \"Filtered parent check, no match\" );\n\tequal( jQuery(\"#groups\").parent(\"div, p\")[0].id, \"ap\", \"Check for multiple filters\" );\n\tdeepEqual( jQuery(\"#en, #sndp\").parent().get(), q(\"foo\"), \"Check for unique results from parent\" );\n\n\t$el = jQuery(\"<div>text</div>\");\n\tdeepEqual( $el.contents().parent().get(), $el.get(), \"Check for parent of text node (#13265)\" );\n});\n\ntest(\"parents([String])\", function() {\n\texpect(6);\n\tequal( jQuery(\"#groups\").parents()[0].id, \"ap\", \"Simple parents check\" );\n\tdeepEqual( jQuery(\"#nonnodes\").contents().eq(1).parents().eq(0).get(), q(\"nonnodes\"), \"Text node parents check\" );\n\tequal( jQuery(\"#groups\").parents(\"p\")[0].id, \"ap\", \"Filtered parents check\" );\n\tequal( jQuery(\"#groups\").parents(\"div\")[0].id, \"qunit-fixture\", \"Filtered parents check2\" );\n\tdeepEqual( jQuery(\"#groups\").parents(\"p, div\").get(), q(\"ap\", \"qunit-fixture\"), \"Check for multiple filters\" );\n\tdeepEqual( jQuery(\"#en, #sndp\").parents().get(), q(\"foo\", \"qunit-fixture\", \"dl\", \"body\", \"html\"), \"Check for unique results from parents\" );\n});\n\ntest(\"parentsUntil([String])\", function() {\n\texpect(10);\n\n\tvar parents = jQuery(\"#groups\").parents();\n\n\tdeepEqual( jQuery(\"#groups\").parentsUntil().get(), parents.get(), \"parentsUntil with no selector (nextAll)\" );\n\tdeepEqual( jQuery(\"#groups\").parentsUntil(\".foo\").get(), parents.get(), \"parentsUntil with invalid selector (nextAll)\" );\n\tdeepEqual( jQuery(\"#groups\").parentsUntil(\"#html\").get(), parents.slice(0, -1).get(), \"Simple parentsUntil check\" );\n\tequal( jQuery(\"#groups\").parentsUntil(\"#ap\").length, 0, \"Simple parentsUntil check\" );\n\tdeepEqual( jQuery(\"#nonnodes\").contents().eq(1).parentsUntil(\"#html\").eq(0).get(), q(\"nonnodes\"), \"Text node parentsUntil check\" );\n\tdeepEqual( jQuery(\"#groups\").parentsUntil(\"#html, #body\").get(), parents.slice( 0, 3 ).get(), \"Less simple parentsUntil check\" );\n\tdeepEqual( jQuery(\"#groups\").parentsUntil(\"#html\", \"div\").get(), jQuery(\"#qunit-fixture\").get(), \"Filtered parentsUntil check\" );\n\tdeepEqual( jQuery(\"#groups\").parentsUntil(\"#html\", \"p,div,dl\").get(), parents.slice( 0, 3 ).get(), \"Multiple-filtered parentsUntil check\" );\n\tequal( jQuery(\"#groups\").parentsUntil(\"#html\", \"span\").length, 0, \"Filtered parentsUntil check, no match\" );\n\tdeepEqual( jQuery(\"#groups, #ap\").parentsUntil(\"#html\", \"p,div,dl\").get(), parents.slice( 0, 3 ).get(), \"Multi-source, multiple-filtered parentsUntil check\" );\n});\n\ntest(\"next([String])\", function() {\n\texpect(6);\n\tequal( jQuery(\"#ap\").next()[0].id, \"foo\", \"Simple next check\" );\n\tequal( jQuery(\"<div>text<a id='element'></a></div>\").contents().eq(0).next().attr(\"id\"), \"element\", \"Text node next check\" );\n\tequal( jQuery(\"#ap\").next(\"div\")[0].id, \"foo\", \"Filtered next check\" );\n\tequal( jQuery(\"#ap\").next(\"p\").length, 0, \"Filtered next check, no match\" );\n\tequal( jQuery(\"#ap\").next(\"div, p\")[0].id, \"foo\", \"Multiple filters\" );\n\tequal( jQuery(\"body\").next().length, 0, \"Simple next check, no match\" );\n});\n\ntest(\"prev([String])\", function() {\n\texpect(5);\n\tequal( jQuery(\"#foo\").prev()[0].id, \"ap\", \"Simple prev check\" );\n\tdeepEqual( jQuery(\"#nonnodes\").contents().eq(1).prev().get(), q(\"nonnodesElement\"), \"Text node prev check\" );\n\tequal( jQuery(\"#foo\").prev(\"p\")[0].id, \"ap\", \"Filtered prev check\" );\n\tequal( jQuery(\"#foo\").prev(\"div\").length, 0, \"Filtered prev check, no match\" );\n\tequal( jQuery(\"#foo\").prev(\"p, div\")[0].id, \"ap\", \"Multiple filters\" );\n});\n\ntest(\"nextAll([String])\", function() {\n\texpect(5);\n\n\tvar elems = jQuery(\"#form\").children();\n\n\tdeepEqual( jQuery(\"#label-for\").nextAll().get(), elems.slice(1).get(), \"Simple nextAll check\" );\n\tequal( jQuery(\"<div>text<a id='element'></a></div>\").contents().eq(0).nextAll().attr(\"id\"), \"element\", \"Text node nextAll check\" );\n\tdeepEqual( jQuery(\"#label-for\").nextAll(\"input\").get(), elems.slice(1).filter(\"input\").get(), \"Filtered nextAll check\" );\n\tdeepEqual( jQuery(\"#label-for\").nextAll(\"input,select\").get(), elems.slice(1).filter(\"input,select\").get(), \"Multiple-filtered nextAll check\" );\n\tdeepEqual( jQuery(\"#label-for, #hidden1\").nextAll(\"input,select\").get(), elems.slice(1).filter(\"input,select\").get(), \"Multi-source, multiple-filtered nextAll check\" );\n});\n\ntest(\"prevAll([String])\", function() {\n\texpect(5);\n\n\tvar elems = jQuery( jQuery(\"#form\").children().slice(0, 12).get().reverse() );\n\n\tdeepEqual( jQuery(\"#area1\").prevAll().get(), elems.get(), \"Simple prevAll check\" );\n\tdeepEqual( jQuery(\"#nonnodes\").contents().eq(1).prevAll().get(), q(\"nonnodesElement\"), \"Text node prevAll check\" );\n\tdeepEqual( jQuery(\"#area1\").prevAll(\"input\").get(), elems.filter(\"input\").get(), \"Filtered prevAll check\" );\n\tdeepEqual( jQuery(\"#area1\").prevAll(\"input,select\").get(), elems.filter(\"input,select\").get(), \"Multiple-filtered prevAll check\" );\n\tdeepEqual( jQuery(\"#area1, #hidden1\").prevAll(\"input,select\").get(), elems.filter(\"input,select\").get(), \"Multi-source, multiple-filtered prevAll check\" );\n});\n\ntest(\"nextUntil([String])\", function() {\n\texpect(12);\n\n\tvar elems = jQuery(\"#form\").children().slice( 2, 12 );\n\n\tdeepEqual( jQuery(\"#text1\").nextUntil().get(), jQuery(\"#text1\").nextAll().get(), \"nextUntil with no selector (nextAll)\" );\n\tequal( jQuery(\"<div>text<a id='element'></a></div>\").contents().eq(0).nextUntil().attr(\"id\"), \"element\", \"Text node nextUntil with no selector (nextAll)\" );\n\tdeepEqual( jQuery(\"#text1\").nextUntil(\".foo\").get(), jQuery(\"#text1\").nextAll().get(), \"nextUntil with invalid selector (nextAll)\" );\n\tdeepEqual( jQuery(\"#text1\").nextUntil(\"#area1\").get(), elems.get(), \"Simple nextUntil check\" );\n\tequal( jQuery(\"#text1\").nextUntil(\"#text2\").length, 0, \"Simple nextUntil check\" );\n\tdeepEqual( jQuery(\"#text1\").nextUntil(\"#area1, #radio1\").get(), jQuery(\"#text1\").next().get(), \"Less simple nextUntil check\" );\n\tdeepEqual( jQuery(\"#text1\").nextUntil(\"#area1\", \"input\").get(), elems.not(\"button\").get(), \"Filtered nextUntil check\" );\n\tdeepEqual( jQuery(\"#text1\").nextUntil(\"#area1\", \"button\").get(), elems.not(\"input\").get(), \"Filtered nextUntil check\" );\n\tdeepEqual( jQuery(\"#text1\").nextUntil(\"#area1\", \"button,input\").get(), elems.get(), \"Multiple-filtered nextUntil check\" );\n\tequal( jQuery(\"#text1\").nextUntil(\"#area1\", \"div\").length, 0, \"Filtered nextUntil check, no match\" );\n\tdeepEqual( jQuery(\"#text1, #hidden1\").nextUntil(\"#area1\", \"button,input\").get(), elems.get(), \"Multi-source, multiple-filtered nextUntil check\" );\n\n\tdeepEqual( jQuery(\"#text1\").nextUntil(\"[class=foo]\").get(), jQuery(\"#text1\").nextAll().get(), \"Non-element nodes must be skipped, since they have no attributes\" );\n});\n\ntest(\"prevUntil([String])\", function() {\n\texpect(11);\n\n\tvar elems = jQuery(\"#area1\").prevAll();\n\n\tdeepEqual( jQuery(\"#area1\").prevUntil().get(), elems.get(), \"prevUntil with no selector (prevAll)\" );\n\tdeepEqual( jQuery(\"#nonnodes\").contents().eq(1).prevUntil().get(), q(\"nonnodesElement\"), \"Text node prevUntil with no selector (prevAll)\" );\n\tdeepEqual( jQuery(\"#area1\").prevUntil(\".foo\").get(), elems.get(), \"prevUntil with invalid selector (prevAll)\" );\n\tdeepEqual( jQuery(\"#area1\").prevUntil(\"label\").get(), elems.slice(0, -1).get(), \"Simple prevUntil check\" );\n\tequal( jQuery(\"#area1\").prevUntil(\"#button\").length, 0, \"Simple prevUntil check\" );\n\tdeepEqual( jQuery(\"#area1\").prevUntil(\"label, #search\").get(), jQuery(\"#area1\").prev().get(), \"Less simple prevUntil check\" );\n\tdeepEqual( jQuery(\"#area1\").prevUntil(\"label\", \"input\").get(), elems.slice(0, -1).not(\"button\").get(), \"Filtered prevUntil check\" );\n\tdeepEqual( jQuery(\"#area1\").prevUntil(\"label\", \"button\").get(), elems.slice(0, -1).not(\"input\").get(), \"Filtered prevUntil check\" );\n\tdeepEqual( jQuery(\"#area1\").prevUntil(\"label\", \"button,input\").get(), elems.slice(0, -1).get(), \"Multiple-filtered prevUntil check\" );\n\tequal( jQuery(\"#area1\").prevUntil(\"label\", \"div\").length, 0, \"Filtered prevUntil check, no match\" );\n\tdeepEqual( jQuery(\"#area1, #hidden1\").prevUntil(\"label\", \"button,input\").get(), elems.slice(0, -1).get(), \"Multi-source, multiple-filtered prevUntil check\" );\n});\n\ntest(\"contents()\", function() {\n\texpect(12);\n\tvar ibody, c;\n\n\tequal( jQuery(\"#ap\").contents().length, 9, \"Check element contents\" );\n\tok( jQuery(\"#iframe\").contents()[0], \"Check existence of IFrame document\" );\n\tibody = jQuery(\"#loadediframe\").contents()[0].body;\n\tok( ibody, \"Check existence of IFrame body\" );\n\n\tequal( jQuery(\"span\", ibody).text(), \"span text\", \"Find span in IFrame and check its text\" );\n\n\tjQuery(ibody).append(\"<div>init text</div>\");\n\tequal( jQuery(\"div\", ibody).length, 2, \"Check the original div and the new div are in IFrame\" );\n\n\tequal( jQuery(\"div\", ibody).last().text(), \"init text\", \"Add text to div in IFrame\" );\n\n\tjQuery(\"div\", ibody).last().text(\"div text\");\n\tequal( jQuery(\"div\", ibody).last().text(), \"div text\", \"Add text to div in IFrame\" );\n\n\tjQuery(\"div\", ibody).last().remove();\n\tequal( jQuery(\"div\", ibody).length, 1, \"Delete the div and check only one div left in IFrame\" );\n\n\tequal( jQuery(\"div\", ibody).text(), \"span text\", \"Make sure the correct div is still left after deletion in IFrame\" );\n\n\tjQuery(\"<table/>\", ibody).append(\"<tr><td>cell</td></tr>\").appendTo(ibody);\n\tjQuery(\"table\", ibody).remove();\n\tequal( jQuery(\"div\", ibody).length, 1, \"Check for JS error on add and delete of a table in IFrame\" );\n\n\t// using contents will get comments regular, text, and comment nodes\n\tc = jQuery(\"#nonnodes\").contents().contents();\n\tequal( c.length, 1, \"Check node,textnode,comment contents is just one\" );\n\tequal( c[0].nodeValue, \"hi\", \"Check node,textnode,comment contents is just the one from span\" );\n});\n\ntest(\"sort direction\", function() {\n\texpect( 12 );\n\n\tvar elems = jQuery(\"#ap, #select1 > *, #moretests > form\"),\n\t\tmethodDirections = {\n\t\t\tparent: false,\n\t\t\tparents: true,\n\t\t\tparentsUntil: true,\n\t\t\tnext: false,\n\t\t\tprev: false,\n\t\t\tnextAll: false,\n\t\t\tprevAll: true,\n\t\t\tnextUntil: false,\n\t\t\tprevUntil: true,\n\t\t\tsiblings: false,\n\t\t\tchildren: false,\n\t\t\tcontents: false\n\t\t};\n\n\tjQuery.each( methodDirections, function( method, reversed ) {\n\t\tvar actual = elems[ method ]().get(),\n\t\t\tforward = jQuery.unique( [].concat( actual ) );\n\t\tdeepEqual( actual, reversed ? forward.reverse() : forward, \"Correct sort direction for \" + method );\n\t});\n});\n\ntest(\"add(String|Element|Array|undefined)\", function() {\n\texpect( 15 );\n\n\tvar divs, tmp, x, notDefined;\n\n\tdeepEqual( jQuery(\"#sndp\").add(\"#en\").add(\"#sap\").get(), q(\"sndp\", \"en\", \"sap\"), \"Check elements from document\" );\n\tdeepEqual( jQuery(\"#sndp\").add( jQuery(\"#en\")[0] ).add( jQuery(\"#sap\") ).get(), q(\"sndp\", \"en\", \"sap\"), \"Check elements from document\" );\n\n\t// We no longer support .add(form.elements), unfortunately.\n\t// There is no way, in browsers, to reliably determine the difference\n\t// between form.elements and form - and doing .add(form) and having it\n\t// add the form elements is way to unexpected, so this gets the boot.\n\t// ok( jQuery([]).add(jQuery(\"#form\")[0].elements).length >= 13, \"Check elements from array\" );\n\n\t// For the time being, we're discontinuing support for jQuery(form.elements) since it's ambiguous in IE\n\t// use jQuery([]).add(form.elements) instead.\n\t//equal( jQuery([]).add(jQuery(\"#form\")[0].elements).length, jQuery(jQuery(\"#form\")[0].elements).length, \"Array in constructor must equals array in add()\" );\n\n\tdivs = jQuery(\"<div/>\").add(\"#sndp\");\n\tok( divs[0].parentNode, \"Sort with the disconnected node last (started with disconnected first).\" );\n\n\tdivs = jQuery(\"#sndp\").add(\"<div/>\");\n\tok( !divs[1].parentNode, \"Sort with the disconnected node last.\" );\n\n\ttmp = jQuery(\"<div/>\");\n\n\tx = jQuery([]).add(jQuery(\"<p id='x1'>xxx</p>\").appendTo(tmp)).add(jQuery(\"<p id='x2'>xxx</p>\").appendTo(tmp));\n\tequal( x[0].id, \"x1\", \"Check on-the-fly element1\" );\n\tequal( x[1].id, \"x2\", \"Check on-the-fly element2\" );\n\n\tx = jQuery([]).add(jQuery(\"<p id='x1'>xxx</p>\").appendTo(tmp)[0]).add(jQuery(\"<p id='x2'>xxx</p>\").appendTo(tmp)[0]);\n\tequal( x[0].id, \"x1\", \"Check on-the-fly element1\" );\n\tequal( x[1].id, \"x2\", \"Check on-the-fly element2\" );\n\n\tx = jQuery([]).add(jQuery(\"<p id='x1'>xxx</p>\")).add(jQuery(\"<p id='x2'>xxx</p>\"));\n\tequal( x[0].id, \"x1\", \"Check on-the-fly element1\" );\n\tequal( x[1].id, \"x2\", \"Check on-the-fly element2\" );\n\n\tx = jQuery([]).add(\"<p id='x1'>xxx</p>\").add(\"<p id='x2'>xxx</p>\");\n\tequal( x[0].id, \"x1\", \"Check on-the-fly element1\" );\n\tequal( x[1].id, \"x2\", \"Check on-the-fly element2\" );\n\n\tequal( jQuery([]).add(notDefined).length, 0, \"Check that undefined adds nothing\" );\n\n\tequal( jQuery([]).add( document.getElementById(\"form\") ).length, 1, \"Add a form\" );\n\tequal( jQuery([]).add( document.getElementById(\"select1\") ).length, 1, \"Add a select\" );\n});\n\ntest(\"add(String, Context)\", function() {\n\texpect(6);\n\n\tdeepEqual( jQuery( \"#firstp\" ).add( \"#ap\" ).get(), q( \"firstp\", \"ap\" ), \"Add selector to selector \" );\n\tdeepEqual( jQuery( document.getElementById(\"firstp\") ).add( \"#ap\" ).get(), q( \"firstp\", \"ap\" ), \"Add gEBId to selector\" );\n\tdeepEqual( jQuery( document.getElementById(\"firstp\") ).add( document.getElementById(\"ap\") ).get(), q( \"firstp\", \"ap\" ), \"Add gEBId to gEBId\" );\n\n\tvar ctx = document.getElementById(\"firstp\");\n\tdeepEqual( jQuery( \"#firstp\" ).add( \"#ap\", ctx ).get(), q( \"firstp\" ), \"Add selector to selector \" );\n\tdeepEqual( jQuery( document.getElementById(\"firstp\") ).add( \"#ap\", ctx ).get(), q( \"firstp\" ), \"Add gEBId to selector, not in context\" );\n\tdeepEqual( jQuery( document.getElementById(\"firstp\") ).add( \"#ap\", document.getElementsByTagName(\"body\")[0] ).get(), q( \"firstp\", \"ap\" ), \"Add gEBId to selector, in context\" );\n});\n\ntest(\"eq('-1') #10616\", function() {\n\texpect(3);\n\tvar $divs = jQuery( \"div\" );\n\n\tequal( $divs.eq( -1 ).length, 1, \"The number -1 returns a selection that has length 1\" );\n\tequal( $divs.eq( \"-1\" ).length, 1, \"The string '-1' returns a selection that has length 1\" );\n\tdeepEqual( $divs.eq( \"-1\" ), $divs.eq( -1 ), \"String and number -1 match\" );\n});\n\ntest(\"index(no arg) #10977\", function() {\n\texpect(2);\n\tvar $list, fragment, div;\n\n\t$list = jQuery(\"<ul id='indextest'><li class='zero'>THIS ONE</li><li class='one'>a</li><li class='two'>b</li><li class='three'>c</li></ul>\");\n\tjQuery(\"#qunit-fixture\").append( $list );\n\tstrictEqual ( jQuery( \"#indextest li.zero\" ).first().index() , 0, \"No Argument Index Check\" );\n\t$list.remove();\n\n\tfragment = document.createDocumentFragment();\n\tdiv = fragment.appendChild( document.createElement(\"div\") );\n\n\tequal( jQuery( div ).index(), 0, \"If jQuery#index called on element whose parent is fragment, it still should work correctly\" );\n});\n\ntest(\"traversing non-elements with attribute filters (#12523)\", function() {\n\texpect(5);\n\n\tvar nonnodes = jQuery(\"#nonnodes\").contents();\n\n\tequal( nonnodes.filter(\"[id]\").length, 1, \".filter\" );\n\tequal( nonnodes.find(\"[id]\").length, 0, \".find\" );\n\tstrictEqual( nonnodes.is(\"[id]\"), true, \".is\" );\n\tdeepEqual( nonnodes.closest(\"[id='nonnodes']\").get(), q(\"nonnodes\"), \".closest\" );\n\tdeepEqual( nonnodes.parents(\"[id='nonnodes']\").get(), q(\"nonnodes\"), \".parents\" );\n});\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/jquery/test/unit/wrap.js",
    "content": "(function() {\n\nif ( !jQuery.fn.wrap ) { // no wrap module\n\treturn;\n}\n\nmodule( \"wrap\", {\n\tteardown: moduleTeardown\n});\n\n// See test/unit/manipulation.js for explanation about these 2 functions\nfunction manipulationBareObj( value ) {\n\treturn value;\n}\n\nfunction manipulationFunctionReturningObj( value ) {\n\treturn function() {\n\t\treturn value;\n\t};\n}\n\nfunction testWrap( val ) {\n\n\texpect( 19 );\n\n\tvar defaultText, result, j, i, cacheLength;\n\n\tdefaultText = \"Try them out:\";\n\tresult = jQuery(\"#first\").wrap( val(\"<div class='red'><span></span></div>\") ).text();\n\n\tequal( defaultText, result, \"Check for wrapping of on-the-fly html\" );\n\tok( jQuery(\"#first\").parent().parent().is(\".red\"), \"Check if wrapper has class 'red'\" );\n\n\tQUnit.reset();\n\tresult = jQuery(\"#first\").wrap( val(document.getElementById(\"empty\")) ).parent();\n\tok( result.is(\"ol\"), \"Check for element wrapping\" );\n\tequal( result.text(), defaultText, \"Check for element wrapping\" );\n\n\tQUnit.reset();\n\tjQuery(\"#check1\").on( \"click\", function() {\n\t\tvar checkbox = this;\n\n\t\tok( checkbox.checked, \"Checkbox's state is erased after wrap() action, see #769\" );\n\t\tjQuery( checkbox ).wrap( val(\"<div id='c1' style='display:none;'></div>\") );\n\t\tok( checkbox.checked, \"Checkbox's state is erased after wrap() action, see #769\" );\n\t}).prop( \"checked\", false )[ 0 ].click();\n\n\t// using contents will get comments regular, text, and comment nodes\n\tj = jQuery(\"#nonnodes\").contents();\n\tj.wrap( val(\"<i></i>\") );\n\n\t// Blackberry 4.6 doesn't maintain comments in the DOM\n\tequal( jQuery(\"#nonnodes > i\").length, jQuery(\"#nonnodes\")[ 0 ].childNodes.length, \"Check node,textnode,comment wraps ok\" );\n\tequal( jQuery(\"#nonnodes > i\").text(), j.text(), \"Check node,textnode,comment wraps doesn't hurt text\" );\n\n\t// Try wrapping a disconnected node\n\tcacheLength = 0;\n\tfor ( i in jQuery.cache ) {\n\t\tcacheLength++;\n\t}\n\n\tj = jQuery(\"<label/>\").wrap( val(\"<li/>\") );\n\tequal( j[ 0 ] .nodeName.toUpperCase(), \"LABEL\", \"Element is a label\" );\n\tequal( j[ 0 ].parentNode.nodeName.toUpperCase(), \"LI\", \"Element has been wrapped\" );\n\n\tfor ( i in jQuery.cache ) {\n\t\tcacheLength--;\n\t}\n\tequal( cacheLength, 0, \"No memory leak in jQuery.cache (bug #7165)\" );\n\n\t// Wrap an element containing a text node\n\tj = jQuery(\"<span/>\").wrap(\"<div>test</div>\");\n\tequal( j[ 0 ].previousSibling.nodeType, 3, \"Make sure the previous node is a text element\" );\n\tequal( j[ 0 ].parentNode.nodeName.toUpperCase(), \"DIV\", \"And that we're in the div element.\" );\n\n\t// Try to wrap an element with multiple elements (should fail)\n\tj = jQuery(\"<div><span></span></div>\").children().wrap(\"<p></p><div></div>\");\n\tequal( j[ 0 ].parentNode.parentNode.childNodes.length, 1, \"There should only be one element wrapping.\" );\n\tequal( j.length, 1, \"There should only be one element (no cloning).\" );\n\tequal( j[ 0 ].parentNode.nodeName.toUpperCase(), \"P\", \"The span should be in the paragraph.\" );\n\n\t// Wrap an element with a jQuery set\n\tj = jQuery(\"<span/>\").wrap( jQuery(\"<div></div>\") );\n\tequal( j[ 0 ].parentNode.nodeName.toLowerCase(), \"div\", \"Wrapping works.\" );\n\n\t// Wrap an element with a jQuery set and event\n\tresult = jQuery(\"<div></div>\").on( \"click\", function() {\n\t\tok( true, \"Event triggered.\" );\n\n\t\t// Remove handlers on detached elements\n\t\tresult.off();\n\t\tjQuery(this).off();\n\t});\n\n\tj = jQuery(\"<span/>\").wrap( result );\n\tequal( j[ 0 ].parentNode.nodeName.toLowerCase(), \"div\", \"Wrapping works.\" );\n\n\tj.parent().trigger(\"click\");\n\n\t// clean up attached elements\n\tQUnit.reset();\n}\n\ntest( \"wrap(String|Element)\", function() {\n\ttestWrap( manipulationBareObj );\n});\n\ntest( \"wrap(Function)\", function() {\n\ttestWrap( manipulationFunctionReturningObj );\n});\n\ntest( \"wrap(Function) with index (#10177)\", function() {\n\tvar expectedIndex = 0,\n\t\ttargets = jQuery(\"#qunit-fixture p\");\n\n\texpect( targets.length );\n\ttargets.wrap(function(i) {\n\t\tequal( i, expectedIndex, \"Check if the provided index (\" + i + \") is as expected (\" + expectedIndex + \")\" );\n\t\texpectedIndex++;\n\n\t\treturn \"<div id='wrap_index_'\" + i + \"'></div>\";\n\t});\n});\n\ntest( \"wrap(String) consecutive elements (#10177)\", function() {\n\tvar targets = jQuery(\"#qunit-fixture p\");\n\n\texpect( targets.length * 2 );\n\ttargets.wrap(\"<div class='wrapper'></div>\");\n\n\ttargets.each(function() {\n\t\tvar $this = jQuery(this);\n\n\t\tok( $this.parent().is(\".wrapper\"), \"Check each elements parent is correct (.wrapper)\" );\n\t\tequal( $this.siblings().length, 0, \"Each element should be wrapped individually\" );\n\t});\n});\n\nfunction testWrapAll( val ) {\n\n\texpect( 8 );\n\n\tvar prev, p, result;\n\n\tprev = jQuery(\"#firstp\")[ 0 ].previousSibling;\n\tp = jQuery(\"#firstp,#first\")[ 0 ].parentNode;\n\tresult = jQuery(\"#firstp,#first\").wrapAll( val(\"<div class='red'><div class='tmp'></div></div>\") );\n\n\tequal( result.parent().length, 1, \"Check for wrapping of on-the-fly html\" );\n\tok( jQuery(\"#first\").parent().parent().is(\".red\"), \"Check if wrapper has class 'red'\" );\n\tok( jQuery(\"#firstp\").parent().parent().is(\".red\"), \"Check if wrapper has class 'red'\" );\n\tequal( jQuery(\"#first\").parent().parent()[ 0 ].previousSibling, prev, \"Correct Previous Sibling\" );\n\tequal( jQuery(\"#first\").parent().parent()[ 0 ].parentNode, p, \"Correct Parent\" );\n\n\tQUnit.reset();\n\tprev = jQuery(\"#firstp\")[ 0 ].previousSibling;\n\tp = jQuery(\"#first\")[ 0 ].parentNode;\n\tjQuery(\"#firstp,#first\").wrapAll( val(document.getElementById(\"empty\")) );\n\n\tequal( jQuery(\"#first\").parent()[ 0 ], jQuery(\"#firstp\").parent()[ 0 ], \"Same Parent\" );\n\tequal( jQuery(\"#first\").parent()[ 0 ].previousSibling, prev, \"Correct Previous Sibling\" );\n\tequal( jQuery(\"#first\").parent()[ 0 ].parentNode, p, \"Correct Parent\" );\n}\n\ntest( \"wrapAll(String|Element)\", function() {\n\ttestWrapAll( manipulationBareObj );\n});\n\nfunction testWrapInner( val ) {\n\n\texpect( 11 );\n\n\tvar num,\n\t\tdiv = jQuery(\"<div/>\");\n\n\tnum = jQuery(\"#first\").children().length;\n\tjQuery(\"#first\").wrapInner( val(\"<div class='red'><div id='tmp'></div></div>\") );\n\n\tequal( jQuery(\"#first\").children().length, 1, \"Only one child\" );\n\tok( jQuery(\"#first\").children().is(\".red\"), \"Verify Right Element\" );\n\tequal( jQuery(\"#first\").children().children().children().length, num, \"Verify Elements Intact\" );\n\n\tQUnit.reset();\n\tnum = jQuery(\"#first\").html(\"foo<div>test</div><div>test2</div>\").children().length;\n\tjQuery(\"#first\").wrapInner( val(\"<div class='red'><div id='tmp'></div></div>\") );\n\tequal( jQuery(\"#first\").children().length, 1, \"Only one child\" );\n\tok( jQuery(\"#first\").children().is(\".red\"), \"Verify Right Element\" );\n\tequal( jQuery(\"#first\").children().children().children().length, num, \"Verify Elements Intact\" );\n\n\tQUnit.reset();\n\tnum = jQuery(\"#first\").children().length;\n\tjQuery(\"#first\").wrapInner( val(document.getElementById(\"empty\")) );\n\tequal( jQuery(\"#first\").children().length, 1, \"Only one child\" );\n\tok( jQuery(\"#first\").children().is(\"#empty\"), \"Verify Right Element\" );\n\tequal( jQuery(\"#first\").children().children().length, num, \"Verify Elements Intact\" );\n\n\tdiv.wrapInner( val(\"<span></span>\") );\n\tequal( div.children().length, 1, \"The contents were wrapped.\" );\n\tequal( div.children()[ 0 ].nodeName.toLowerCase(), \"span\", \"A span was inserted.\" );\n}\n\ntest( \"wrapInner(String|Element)\", function() {\n\ttestWrapInner( manipulationBareObj );\n});\n\ntest( \"wrapInner(Function)\", function() {\n\ttestWrapInner( manipulationFunctionReturningObj );\n});\n\ntest( \"unwrap()\", function() {\n\n\texpect( 9 );\n\n\tjQuery(\"body\").append(\"  <div id='unwrap' style='display: none;'> <div id='unwrap1'> <span class='unwrap'>a</span> <span class='unwrap'>b</span> </div> <div id='unwrap2'> <span class='unwrap'>c</span> <span class='unwrap'>d</span> </div> <div id='unwrap3'> <b><span class='unwrap unwrap3'>e</span></b> <b><span class='unwrap unwrap3'>f</span></b> </div> </div>\");\n\n\tvar abcd = jQuery(\"#unwrap1 > span, #unwrap2 > span\").get(),\n\t\tabcdef = jQuery(\"#unwrap span\").get();\n\n\tequal( jQuery(\"#unwrap1 span\").add(\"#unwrap2 span:first-child\").unwrap().length, 3, \"make #unwrap1 and #unwrap2 go away\" );\n\tdeepEqual( jQuery(\"#unwrap > span\").get(), abcd, \"all four spans should still exist\" );\n\n\tdeepEqual( jQuery(\"#unwrap3 span\").unwrap().get(), jQuery(\"#unwrap3 > span\").get(), \"make all b in #unwrap3 go away\" );\n\n\tdeepEqual( jQuery(\"#unwrap3 span\").unwrap().get(), jQuery(\"#unwrap > span.unwrap3\").get(), \"make #unwrap3 go away\" );\n\n\tdeepEqual( jQuery(\"#unwrap\").children().get(), abcdef, \"#unwrap only contains 6 child spans\" );\n\n\tdeepEqual( jQuery(\"#unwrap > span\").unwrap().get(), jQuery(\"body > span.unwrap\").get(), \"make the 6 spans become children of body\" );\n\n\tdeepEqual( jQuery(\"body > span.unwrap\").unwrap().get(), jQuery(\"body > span.unwrap\").get(), \"can't unwrap children of body\" );\n\tdeepEqual( jQuery(\"body > span.unwrap\").unwrap().get(), abcdef, \"can't unwrap children of body\" );\n\n\tdeepEqual( jQuery(\"body > span.unwrap\").get(), abcdef, \"body contains 6 .unwrap child spans\" );\n\n\tjQuery(\"body > span.unwrap\").remove();\n});\n\ntest( \"jQuery(<tag>) & wrap[Inner/All]() handle unknown elems (#10667)\", function() {\n\n\texpect( 2 );\n\n\tvar $wraptarget = jQuery( \"<div id='wrap-target'>Target</div>\" ).appendTo( \"#qunit-fixture\" ),\n\t\t$section = jQuery( \"<section>\" ).appendTo( \"#qunit-fixture\" );\n\n\t$wraptarget.wrapAll(\"<aside style='background-color:green'></aside>\");\n\n\tnotEqual( $wraptarget.parent(\"aside\").get( 0 ).style.backgroundColor, \"transparent\", \"HTML5 elements created with wrapAll inherit styles\" );\n\tnotEqual( $section.get( 0 ).style.backgroundColor, \"transparent\", \"HTML5 elements create with jQuery( string ) inherit styles\" );\n});\n\ntest( \"wrapping scripts (#10470)\", function() {\n\n\texpect( 2 );\n\n\tvar script = document.createElement(\"script\");\n\tscript.text = script.textContent = \"ok( !document.eval10470, 'script evaluated once' ); document.eval10470 = true;\";\n\n\tdocument.eval10470 = false;\n\tjQuery(\"#qunit-fixture\").empty()[0].appendChild( script );\n\tjQuery(\"#qunit-fixture script\").wrap(\"<b></b>\");\n\tstrictEqual( script.parentNode, jQuery(\"#qunit-fixture > b\")[ 0 ], \"correctly wrapped\" );\n\tjQuery( script ).remove();\n});\n\n})();\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/jquery/test/xhtml.php",
    "content": "<?php\n\t# Load and run the test suite as a proper XHTML page\n\theader(\"Content-type: application/xhtml+xml\");\n\treadfile(\"index.html\");\n?>\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/jquery-atmosphere/.bower.json",
    "content": "{\n  \"main\": \"jquery.atmosphere.js\",\n  \"version\": \"2.1.2\",\n  \"dependencies\": {\n    \"jquery\": \">= 1.9.0\"\n  },\n  \"name\": \"atmosphere-jquery\",\n  \"homepage\": \"https://github.com/Atmosphere/bower-jquery-atmosphere\",\n  \"_release\": \"2.1.2\",\n  \"_resolution\": {\n    \"type\": \"version\",\n    \"tag\": \"v2.1.2\",\n    \"commit\": \"57916f3a7c036bf3fd615fab8c83a7d558d6062d\"\n  },\n  \"_source\": \"https://github.com/Atmosphere/bower-jquery-atmosphere.git\",\n  \"_target\": \"2.1.2\",\n  \"_originalSource\": \"jquery-atmosphere\"\n}"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/jquery-atmosphere/README.md",
    "content": "bower-jquery-atmosphere\n============================\n\nThis repository is for distribution on `bower`\n\n```shell\nbower install jquery-atmosphere\n```\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/jquery-atmosphere/bower.json",
    "content": "{\n  \"main\": \"jquery.atmosphere.js\", \n  \"version\": \"2.1.2\", \n  \"dependencies\": {\n    \"jquery\": \">= 1.9.0\"\n  }, \n  \"name\": \"atmosphere-jquery\"\n}"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/jquery-atmosphere/jquery.atmosphere.js",
    "content": "/**\n * Copyright 2013 Jeanfrancois Arcand\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 * IE streaming/XDR supports is copied/highly inspired by http://code.google.com/p/jquery-stream/\n *\n * Copyright 2011, Donghwan Kim\n * Licensed under the Apache License, Version 2.0\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * LocalStorage supports is copied/highly inspired by https://github.com/flowersinthesand/jquery-socket\n * Copyright 2011, Donghwan Kim\n * Licensed under the Apache License, Version 2.0\n * http://www.apache.org/licenses/LICENSE-2.0\n * */\n/**\n * Official documentation of this library: https://github.com/Atmosphere/atmosphere/wiki/jQuery.atmosphere.js-API\n */\njQuery.atmosphere = function () {\n\n    jQuery(window).bind(\"unload.atmosphere\", function () {\n        jQuery.atmosphere.unsubscribe();\n    });\n\n    jQuery(window).bind(\"offline\", function () {\n        jQuery.atmosphere.unsubscribe();\n    });\n\n    // Prevent ESC to kill the connection from Firefox.\n    jQuery(window).keypress(function (e) {\n        if (e.keyCode === 27) {\n            e.preventDefault();\n        }\n    });\n\n    var parseHeaders = function (headerString) {\n        var match, rheaders = /^(.*?):[ \\t]*([^\\r\\n]*)\\r?$/mg, headers = {};\n        while (match = rheaders.exec(headerString)) {\n            headers[match[1]] = match[2];\n        }\n        return headers;\n    };\n\n    return {\n        version: \"2.1.2-jquery\",\n        uuid : 0,\n        requests: [],\n        callbacks: [],\n\n        onError: function (response) {\n        },\n        onClose: function (response) {\n        },\n        onOpen: function (response) {\n        },\n        onMessage: function (response) {\n        },\n        onReconnect: function (request, response) {\n        },\n        onMessagePublished: function (response) {\n        },\n        onTransportFailure: function (errorMessage, _request) {\n        },\n        onLocalMessage: function (response) {\n        },\n        onClientTimeout: function(request){\n        },\n        onFailureToReconnect: function (request, response) {\n        },\n\n        AtmosphereRequest: function (options) {\n\n            /**\n             * {Object} Request parameters.\n             *\n             * @private\n             */\n            var _request = {\n                timeout: 300000,\n                method: 'GET',\n                headers: {},\n                contentType: '',\n                callback: null,\n                url: '',\n                data: '',\n                suspend: true,\n                maxRequest: -1,\n                reconnect: true,\n                maxStreamingLength: 10000000,\n                lastIndex: 0,\n                logLevel: 'info',\n                requestCount: 0,\n                fallbackMethod: 'GET',\n                fallbackTransport: 'streaming',\n                transport: 'long-polling',\n                webSocketImpl: null,\n                webSocketBinaryType: null,\n                dispatchUrl: null,\n                webSocketPathDelimiter: \"@@\",\n                enableXDR: false,\n                rewriteURL: false,\n                attachHeadersAsQueryString: true,\n                executeCallbackBeforeReconnect: false,\n                readyState: 0,\n                lastTimestamp: 0,\n                withCredentials: false,\n                trackMessageLength: false,\n                messageDelimiter: '|',\n                connectTimeout: -1,\n                reconnectInterval: 0,\n                dropHeaders: true,\n                uuid: 0,\n                shared: false,\n                readResponsesHeaders: false,\n                maxReconnectOnClose: 5,\n                enableProtocol: true,\n                onError: function (response) {\n                },\n                onClose: function (response) {\n                },\n                onOpen: function (response) {\n                },\n                onMessage: function (response) {\n                },\n                onReopen: function (request, response) {\n                },\n                onReconnect: function (request, response) {\n                },\n                onMessagePublished: function (response) {\n                },\n                onTransportFailure: function (reason, request) {\n                },\n                onLocalMessage: function (request) {\n                },\n                onFailureToReconnect: function (request, response) {\n                },\n                onClientTimeout: function(request){\n                }\n            };\n\n            /**\n             * {Object} Request's last response.\n             *\n             * @private\n             */\n            var _response = {\n                status: 200,\n                reasonPhrase: \"OK\",\n                responseBody: '',\n                messages: [],\n                headers: [],\n                state: \"messageReceived\",\n                transport: \"polling\",\n                error: null,\n                request: null,\n                partialMessage: \"\",\n                errorHandled: false,\n                closedByClientTimeout: false\n            };\n\n            /**\n             * {websocket} Opened web socket.\n             *\n             * @private\n             */\n            var _websocket = null;\n\n            /**\n             * {SSE} Opened SSE.\n             *\n             * @private\n             */\n            var _sse = null;\n\n            /**\n             * {XMLHttpRequest, ActiveXObject} Opened ajax request (in case of http-streaming or long-polling)\n             *\n             * @private\n             */\n            var _activeRequest = null;\n\n            /**\n             * {Object} Object use for streaming with IE.\n             *\n             * @private\n             */\n            var _ieStream = null;\n\n            /**\n             * {Object} Object use for jsonp transport.\n             *\n             * @private\n             */\n            var _jqxhr = null;\n\n            /**\n             * {boolean} If request has been subscribed or not.\n             *\n             * @private\n             */\n            var _subscribed = true;\n\n            /**\n             * {number} Number of test reconnection.\n             *\n             * @private\n             */\n            var _requestCount = 0;\n\n            /**\n             * {boolean} If request is currently aborded.\n             *\n             * @private\n             */\n            var _abordingConnection = false;\n\n            /**\n             * A local \"channel' of communication.\n             *\n             * @private\n             */\n            var _localSocketF = null;\n\n            /**\n             * The storage used.\n             *\n             * @private\n             */\n            var _storageService;\n\n            /**\n             * Local communication\n             *\n             * @private\n             */\n            var _localStorageService = null;\n\n            /**\n             * A Unique ID\n             *\n             * @private\n             */\n            var guid = jQuery.now();\n\n            /** Trace time */\n            var _traceTimer;\n\n            /** Key for connection sharing */\n            var _sharingKey;\n\n            // Automatic call to subscribe\n            _subscribe(options);\n\n            /**\n             * Initialize atmosphere request object.\n             *\n             * @private\n             */\n            function _init() {\n                _subscribed = true;\n                _abordingConnection = false;\n                _requestCount = 0;\n\n                _websocket = null;\n                _sse = null;\n                _activeRequest = null;\n                _ieStream = null;\n            }\n\n            /**\n             * Re-initialize atmosphere object.\n             *\n             * @private\n             */\n            function _reinit() {\n                _clearState();\n                _init();\n            }\n\n            /**\n             * Subscribe request using request transport. <br>\n             * If request is currently opened, this one will be closed.\n             *\n             * @param {Object} Request parameters.\n             * @private\n             */\n            function _subscribe(options) {\n                _reinit();\n\n                _request = jQuery.extend(_request, options);\n                // Allow at least 1 request\n                _request.mrequest = _request.reconnect;\n                if (!_request.reconnect) {\n                    _request.reconnect = true;\n                }\n            }\n\n            /**\n             * Check if web socket is supported (check for custom implementation provided by request object or browser implementation).\n             *\n             * @returns {boolean} True if web socket is supported, false otherwise.\n             * @private\n             */\n            function _supportWebsocket() {\n                return _request.webSocketImpl != null || window.WebSocket || window.MozWebSocket;\n            }\n\n            /**\n             * Check if server side events (SSE) is supported (check for custom implementation provided by request object or browser implementation).\n             *\n             * @returns {boolean} True if web socket is supported, false otherwise.\n             * @private\n             */\n            function _supportSSE() {\n                return window.EventSource;\n            }\n\n            /**\n             * Open request using request transport. <br>\n             * If request transport is 'websocket' but websocket can't be opened, request will automatically reconnect using fallback transport.\n             *\n             * @private\n             */\n            function _execute() {\n                // Shared across multiple tabs/windows.\n                if (_request.shared) {\n                    _localStorageService = _local(_request);\n                    if (_localStorageService != null) {\n                        if (_request.logLevel === 'debug') {\n                            jQuery.atmosphere.debug(\"Storage service available. All communication will be local\");\n                        }\n\n                        if (_localStorageService.open(_request)) {\n                            // Local connection.\n                            return;\n                        }\n                    }\n\n                    if (_request.logLevel === 'debug') {\n                        jQuery.atmosphere.debug(\"No Storage service available.\");\n                    }\n                    // Wasn't local or an error occurred\n                    _localStorageService = null;\n                }\n\n                // Protocol\n                _request.firstMessage = jQuery.atmosphere.uuid == 0 ? true : false;\n                _request.isOpen = false;\n                _request.ctime = jQuery.now();\n\n                // We carry any UUID set by the user or from a previous connection.\n                if (_request.uuid === 0) {\n                    _request.uuid = jQuery.atmosphere.uuid;\n                }\n                _request.closedByClientTimeout = false;\n\n                if (_request.transport !== 'websocket' && _request.transport !== 'sse') {\n                    _executeRequest(_request);\n\n                } else if (_request.transport === 'websocket') {\n                    if (!_supportWebsocket()) {\n                        _reconnectWithFallbackTransport(\"Websocket is not supported, using request.fallbackTransport (\" + _request.fallbackTransport\n                            + \")\");\n                    } else {\n                        _executeWebSocket(false);\n                    }\n                } else if (_request.transport === 'sse') {\n                    if (!_supportSSE()) {\n                        _reconnectWithFallbackTransport(\"Server Side Events(SSE) is not supported, using request.fallbackTransport (\"\n                            + _request.fallbackTransport + \")\");\n                    } else {\n                        _executeSSE(false);\n                    }\n                }\n            }\n\n            function _local(request) {\n                var trace, connector, orphan, name = \"atmosphere-\" + request.url, connectors = {\n                    storage: function () {\n                        if (!jQuery.atmosphere.supportStorage()) {\n                            return;\n                        }\n\n                        var storage = window.localStorage, get = function (key) {\n                            return jQuery.parseJSON(storage.getItem(name + \"-\" + key));\n                        }, set = function (key, value) {\n                            storage.setItem(name + \"-\" + key, jQuery.stringifyJSON(value));\n                        };\n\n                        return {\n                            init: function () {\n                                set(\"children\", get(\"children\").concat([guid]));\n                                jQuery(window).on(\"storage.socket\", function (event) {\n                                    event = event.originalEvent;\n                                    if (event.key === name && event.newValue) {\n                                        listener(event.newValue);\n                                    }\n                                });\n                                return get(\"opened\");\n                            },\n                            signal: function (type, data) {\n                                storage.setItem(name, jQuery.stringifyJSON({\n                                    target: \"p\",\n                                    type: type,\n                                    data: data\n                                }));\n                            },\n                            close: function () {\n                                var index, children = get(\"children\");\n\n                                jQuery(window).off(\"storage.socket\");\n                                if (children) {\n                                    index = jQuery.inArray(request.id, children);\n                                    if (index > -1) {\n                                        children.splice(index, 1);\n                                        set(\"children\", children);\n                                    }\n                                }\n                            }\n                        };\n                    },\n                    windowref: function () {\n                        var win = window.open(\"\", name.replace(/\\W/g, \"\"));\n\n                        if (!win || win.closed || !win.callbacks) {\n                            return;\n                        }\n\n                        return {\n                            init: function () {\n                                win.callbacks.push(listener);\n                                win.children.push(guid);\n                                return win.opened;\n                            },\n                            signal: function (type, data) {\n                                if (!win.closed && win.fire) {\n                                    win.fire(jQuery.stringifyJSON({\n                                        target: \"p\",\n                                        type: type,\n                                        data: data\n                                    }));\n                                }\n                            },\n                            close: function () {\n                                function remove(array, e) {\n                                    var index = jQuery.inArray(e, array);\n                                    if (index > -1) {\n                                        array.splice(index, 1);\n                                    }\n                                }\n\n                                // Removes traces only if the parent is alive\n                                if (!orphan) {\n                                    remove(win.callbacks, listener);\n                                    remove(win.children, guid);\n                                }\n                            }\n\n                        };\n                    }\n                };\n\n                // Receives open, close and message command from the parent\n                function listener(string) {\n                    var command = jQuery.parseJSON(string), data = command.data;\n\n                    if (command.target === \"c\") {\n                        switch (command.type) {\n                            case \"open\":\n                                _open(\"opening\", 'local', _request);\n                                break;\n                            case \"close\":\n                                if (!orphan) {\n                                    orphan = true;\n                                    if (data.reason === \"aborted\") {\n                                        _close();\n                                    } else {\n                                        // Gives the heir some time to reconnect\n                                        if (data.heir === guid) {\n                                            _execute();\n                                        } else {\n                                            setTimeout(function () {\n                                                _execute();\n                                            }, 100);\n                                        }\n                                    }\n                                }\n                                break;\n                            case \"message\":\n                                _prepareCallback(data, \"messageReceived\", 200, request.transport);\n                                break;\n                            case \"localMessage\":\n                                _localMessage(data);\n                                break;\n                        }\n                    }\n                }\n\n                function findTrace() {\n                    var matcher = new RegExp(\"(?:^|; )(\" + encodeURIComponent(name) + \")=([^;]*)\").exec(document.cookie);\n                    if (matcher) {\n                        return jQuery.parseJSON(decodeURIComponent(matcher[2]));\n                    }\n                }\n\n                // Finds and validates the parent socket's trace from the cookie\n                trace = findTrace();\n                if (!trace || jQuery.now() - trace.ts > 1000) {\n                    return;\n                }\n\n                // Chooses a connector\n                connector = connectors.storage() || connectors.windowref();\n                if (!connector) {\n                    return;\n                }\n\n                return {\n                    open: function () {\n                        var parentOpened;\n\n                        // Checks the shared one is alive\n                        _traceTimer = setInterval(function () {\n                            var oldTrace = trace;\n                            trace = findTrace();\n                            if (!trace || oldTrace.ts === trace.ts) {\n                                // Simulates a close signal\n                                listener(jQuery.stringifyJSON({\n                                    target: \"c\",\n                                    type: \"close\",\n                                    data: {\n                                        reason: \"error\",\n                                        heir: oldTrace.heir\n                                    }\n                                }));\n                            }\n                        }, 1000);\n\n                        parentOpened = connector.init();\n                        if (parentOpened) {\n                            // Firing the open event without delay robs the user of the opportunity to bind connecting event handlers\n                            setTimeout(function () {\n                                _open(\"opening\", 'local', request);\n                            }, 50);\n                        }\n                        return parentOpened;\n                    },\n                    send: function (event) {\n                        connector.signal(\"send\", event);\n                    },\n                    localSend: function (event) {\n                        connector.signal(\"localSend\", jQuery.stringifyJSON({\n                            id: guid,\n                            event: event\n                        }));\n                    },\n                    close: function () {\n                        // Do not signal the parent if this method is executed by the unload event handler\n                        if (!_abordingConnection) {\n                            clearInterval(_traceTimer);\n                            connector.signal(\"close\");\n                            connector.close();\n                        }\n                    }\n                };\n            }\n\n            function share() {\n                var storageService, name = \"atmosphere-\" + _request.url, servers = {\n                    // Powered by the storage event and the localStorage\n                    // http://www.w3.org/TR/webstorage/#event-storage\n                    storage: function () {\n                        if (!jQuery.atmosphere.supportStorage()) {\n                            return;\n                        }\n\n                        var storage = window.localStorage;\n\n                        return {\n                            init: function () {\n                                // Handles the storage event\n                                jQuery(window).on(\"storage.socket\", function (event) {\n                                    event = event.originalEvent;\n                                    // When a deletion, newValue initialized to null\n                                    if (event.key === name && event.newValue) {\n                                        listener(event.newValue);\n                                    }\n                                });\n                            },\n                            signal: function (type, data) {\n                                storage.setItem(name, jQuery.stringifyJSON({\n                                    target: \"c\",\n                                    type: type,\n                                    data: data\n                                }));\n                            },\n                            get: function (key) {\n                                return jQuery.parseJSON(storage.getItem(name + \"-\" + key));\n                            },\n                            set: function (key, value) {\n                                storage.setItem(name + \"-\" + key, jQuery.stringifyJSON(value));\n                            },\n                            close: function () {\n                                jQuery(window).off(\"storage.socket\");\n                                storage.removeItem(name);\n                                storage.removeItem(name + \"-opened\");\n                                storage.removeItem(name + \"-children\");\n                            }\n\n                        };\n                    },\n                    // Powered by the window.open method\n                    // https://developer.mozilla.org/en/DOM/window.open\n                    windowref: function () {\n                        // Internet Explorer raises an invalid argument error\n                        // when calling the window.open method with the name containing non-word characters\n                        var neim = name.replace(/\\W/g, \"\"), win = (jQuery('iframe[name=\"' + neim + '\"]')[0] || jQuery(\n                            '<iframe name=\"' + neim + '\" />').hide().appendTo(\"body\")[0]).contentWindow;\n\n                        return {\n                            init: function () {\n                                // Callbacks from different windows\n                                win.callbacks = [listener];\n                                // In IE 8 and less, only string argument can be safely passed to the function in other window\n                                win.fire = function (string) {\n                                    var i;\n\n                                    for (i = 0; i < win.callbacks.length; i++) {\n                                        win.callbacks[i](string);\n                                    }\n                                };\n                            },\n                            signal: function (type, data) {\n                                if (!win.closed && win.fire) {\n                                    win.fire(jQuery.stringifyJSON({\n                                        target: \"c\",\n                                        type: type,\n                                        data: data\n                                    }));\n                                }\n                            },\n                            get: function (key) {\n                                return !win.closed ? win[key] : null;\n                            },\n                            set: function (key, value) {\n                                if (!win.closed) {\n                                    win[key] = value;\n                                }\n                            },\n                            close: function () {\n                            }\n                        };\n                    }\n                };\n\n                // Receives send and close command from the children\n                function listener(string) {\n                    var command = jQuery.parseJSON(string), data = command.data;\n\n                    if (command.target === \"p\") {\n                        switch (command.type) {\n                            case \"send\":\n                                _push(data);\n                                break;\n                            case \"localSend\":\n                                _localMessage(data);\n                                break;\n                            case \"close\":\n                                _close();\n                                break;\n                        }\n                    }\n                }\n\n                _localSocketF = function propagateMessageEvent(context) {\n                    storageService.signal(\"message\", context);\n                };\n\n                function leaveTrace() {\n                    document.cookie = _sharingKey + \"=\" +\n                        // Opera's JSON implementation ignores a number whose a last digit of 0 strangely\n                        // but has no problem with a number whose a last digit of 9 + 1\n                        encodeURIComponent(jQuery.stringifyJSON({\n                            ts: jQuery.now() + 1,\n                            heir: (storageService.get(\"children\") || [])[0]\n                        })) + \"; path=/\";\n                }\n\n                // Chooses a storageService\n                storageService = servers.storage() || servers.windowref();\n                storageService.init();\n\n                if (_request.logLevel === 'debug') {\n                    jQuery.atmosphere.debug(\"Installed StorageService \" + storageService);\n                }\n\n                // List of children sockets\n                storageService.set(\"children\", []);\n\n                if (storageService.get(\"opened\") != null && !storageService.get(\"opened\")) {\n                    // Flag indicating the parent socket is opened\n                    storageService.set(\"opened\", false);\n                }\n                // Leaves traces\n                _sharingKey = encodeURIComponent(name);\n                leaveTrace();\n                _traceTimer = setInterval(leaveTrace, 1000);\n\n                _storageService = storageService;\n            }\n\n            /**\n             * @private\n             */\n            function _open(state, transport, request) {\n                if (_request.shared && transport !== 'local') {\n                    share();\n                }\n\n                if (_storageService != null) {\n                    _storageService.set(\"opened\", true);\n                }\n\n                request.close = function () {\n                    _close();\n                };\n\n                if (_requestCount > 0 && state === 're-connecting') {\n                    request.isReopen = true;\n                    _tryingToReconnect(_response);\n                } else if (_response.error == null) {\n                    _response.request = request;\n                    var prevState = _response.state;\n                    _response.state = state;\n                    var prevTransport = _response.transport;\n                    _response.transport = transport;\n\n                    var _body = _response.responseBody;\n                    _invokeCallback();\n                    _response.responseBody = _body;\n\n                    _response.state = prevState;\n                    _response.transport = prevTransport;\n                }\n            }\n\n            /**\n             * Execute request using jsonp transport.\n             *\n             * @param request {Object} request Request parameters, if undefined _request object will be used.\n             * @private\n             */\n            function _jsonp(request) {\n                // When CORS is enabled, make sure we force the proper transport.\n                request.transport = \"jsonp\";\n\n                var rq = _request;\n                if ((request != null) && (typeof (request) !== 'undefined')) {\n                    rq = request;\n                }\n\n                var url = rq.url;\n                if (rq.dispatchUrl != null) {\n                    url += rq.dispatchUrl;\n                }\n\n                var data = rq.data;\n                if (rq.attachHeadersAsQueryString) {\n                    url = _attachHeaders(rq);\n                    if (data !== '') {\n                        url += \"&X-Atmosphere-Post-Body=\" + encodeURIComponent(data);\n                    }\n                    data = '';\n                }\n\n                _jqxhr = jQuery.ajax({\n                    url: url,\n                    type: rq.method,\n                    dataType: \"jsonp\",\n                    error: function (jqXHR, textStatus, errorThrown) {\n                        _response.error = true;\n\n                        if (rq.openId) {\n                            clearTimeout(rq.openId);\n                        }\n\n                        if (rq.reconnect && _requestCount++ < rq.maxReconnectOnClose) {\n                            _open('re-connecting', rq.transport, rq);\n                            _reconnect(_jqxhr, rq, rq.reconnectInterval);\n                            rq.openId = setTimeout(function() {\n                                _triggerOpen(rq);\n                            }, rq.reconnectInterval + 1000);\n                        } else {\n                            _onError(jqXHR.status, errorThrown);\n                        }\n                    },\n                    jsonp: \"jsonpTransport\",\n                    success: function (json) {\n                        if (rq.reconnect) {\n                            if (rq.maxRequest === -1 || rq.requestCount++ < rq.maxRequest) {\n                                _readHeaders(_jqxhr, rq);\n\n                                if (!rq.executeCallbackBeforeReconnect) {\n                                    _reconnect(_jqxhr, rq, 0);\n                                }\n\n                                var msg = json.message;\n                                if (msg != null && typeof msg !== 'string') {\n                                    try {\n                                        msg = jQuery.stringifyJSON(msg);\n                                    } catch (err) {\n                                        // The message was partial\n                                    }\n                                }\n\n                                var skipCallbackInvocation = _trackMessageSize(msg, rq, _response);\n                                if (!skipCallbackInvocation) {\n                                    _prepareCallback(_response.responseBody, \"messageReceived\", 200, rq.transport);\n                                }\n\n                                if (rq.executeCallbackBeforeReconnect) {\n                                    _reconnect(_jqxhr, rq, 0);\n                                }\n                            } else {\n                                jQuery.atmosphere.log(_request.logLevel, [\"JSONP reconnect maximum try reached \" + _request.requestCount]);\n                                _onError(0, \"maxRequest reached\");\n                            }\n                        }\n                    },\n                    data: rq.data,\n                    beforeSend: function (jqXHR) {\n                        _doRequest(jqXHR, rq, false);\n                    }\n                });\n            }\n\n            /**\n             * Execute request using ajax transport.\n             *\n             * @param request {Object} request Request parameters, if undefined _request object will be used.\n             * @private\n             */\n            function _ajax(request) {\n                var rq = _request;\n                if ((request != null) && (typeof (request) !== 'undefined')) {\n                    rq = request;\n                }\n\n                var url = rq.url;\n                if (rq.dispatchUrl != null) {\n                    url += rq.dispatchUrl;\n                }\n\n                var data = rq.data;\n                if (rq.attachHeadersAsQueryString) {\n                    url = _attachHeaders(rq);\n                    if (data !== '') {\n                        url += \"&X-Atmosphere-Post-Body=\" + encodeURIComponent(data);\n                    }\n                    data = '';\n                }\n\n                var async = typeof (rq.async) !== 'undefined' ? rq.async : true;\n                _jqxhr = jQuery.ajax({\n                    url: url,\n                    type: rq.method,\n                    error: function (jqXHR, textStatus, errorThrown) {\n                        _response.error = true;\n                        if (jqXHR.status < 300) {\n                            _reconnect(_jqxhr, rq);\n                        } else {\n                            _onError(jqXHR.status, errorThrown);\n                        }\n                    },\n                    success: function (data, textStatus, jqXHR) {\n\n                        if (rq.reconnect) {\n                            if (rq.maxRequest === -1 || rq.requestCount++ < rq.maxRequest) {\n                                if (!rq.executeCallbackBeforeReconnect) {\n                                    _reconnect(_jqxhr, rq, 0);\n                                }\n                                var skipCallbackInvocation = _trackMessageSize(data, rq, _response);\n                                if (!skipCallbackInvocation) {\n                                    _prepareCallback(_response.responseBody, \"messageReceived\", 200, rq.transport);\n                                }\n\n                                if (rq.executeCallbackBeforeReconnect) {\n                                    _reconnect(_jqxhr, rq, 0);\n                                }\n                            } else {\n                                jQuery.atmosphere.log(_request.logLevel, [\"AJAX reconnect maximum try reached \" + _request.requestCount]);\n                                _onError(0, \"maxRequest reached\");\n                            }\n                        }\n                    },\n                    beforeSend: function (jqXHR) {\n                        _doRequest(jqXHR, rq, false);\n                    },\n                    crossDomain: rq.enableXDR,\n                    async: async\n                });\n            }\n\n            /**\n             * Build websocket object.\n             *\n             * @param location {string} Web socket url.\n             * @returns {websocket} Web socket object.\n             * @private\n             */\n            function _getWebSocket(location) {\n                if (_request.webSocketImpl != null) {\n                    return _request.webSocketImpl;\n                } else {\n                    if (window.WebSocket) {\n                        return new WebSocket(location);\n                    } else {\n                        return new MozWebSocket(location);\n                    }\n                }\n            }\n\n            /**\n             * Build web socket url from request url.\n             *\n             * @return {string} Web socket url (start with \"ws\" or \"wss\" for secure web socket).\n             * @private\n             */\n            function _buildWebSocketUrl() {\n                var url = _attachHeaders(_request);\n\n                return decodeURI(jQuery('<a href=\"' + url + '\"/>')[0].href.replace(/^http/, \"ws\"));\n            }\n\n            /**\n             * Build SSE url from request url.\n             *\n             * @return a url with Atmosphere's headers\n             * @private\n             */\n            function _buildSSEUrl() {\n                var url = _attachHeaders(_request);\n                return url;\n            }\n\n            /**\n             * Open SSE. <br>\n             * Automatically use fallback transport if SSE can't be opened.\n             *\n             * @private\n             */\n            function _executeSSE(sseOpened) {\n\n                _response.transport = \"sse\";\n\n                var location = _buildSSEUrl(_request.url);\n\n                if (_request.logLevel === 'debug') {\n                    jQuery.atmosphere.debug(\"Invoking executeSSE\");\n                    jQuery.atmosphere.debug(\"Using URL: \" + location);\n                }\n\n                if (_request.enableProtocol && sseOpened) {\n                    var time = jQuery.now() - _request.ctime;\n                    _request.lastTimestamp = Number(_request.stime) + Number(time);\n                }\n\n                if (sseOpened && !_request.reconnect) {\n                    if (_sse != null) {\n                        _clearState();\n                    }\n                    return;\n                }\n\n                try {\n                    _sse = new EventSource(location, {\n                        withCredentials: _request.withCredentials\n                    });\n                } catch (e) {\n                    _onError(0, e);\n                    _reconnectWithFallbackTransport(\"SSE failed. Downgrading to fallback transport and resending\");\n                    return;\n                }\n\n                if (_request.connectTimeout > 0) {\n                    _request.id = setTimeout(function () {\n                        if (!sseOpened) {\n                            _clearState();\n                        }\n                    }, _request.connectTimeout);\n                }\n\n                _sse.onopen = function (event) {\n                    _timeout(_request);\n                    if (_request.logLevel === 'debug') {\n                        jQuery.atmosphere.debug(\"SSE successfully opened\");\n                    }\n\n                    if (!_request.enableProtocol) {\n                        if (!sseOpened) {\n                            _open('opening', \"sse\", _request);\n                        } else {\n                            _open('re-opening', \"sse\", _request);\n                        }\n                    } else if (_request.isReopen) {\n                        _request.isReopen = false;\n                        _open('re-opening', _request.transport, _request);\n                    }\n                    sseOpened = true;\n\n                    if (_request.method === 'POST') {\n                        _response.state = \"messageReceived\";\n                        _sse.send(_request.data);\n                    }\n                };\n\n                _sse.onmessage = function (message) {\n                    _timeout(_request);\n                    if (!_request.enableXDR && message.origin !== window.location.protocol + \"//\" + window.location.host) {\n                        jQuery.atmosphere.log(_request.logLevel, [\"Origin was not \" + window.location.protocol + \"//\" + window.location.host]);\n                        return;\n                    }\n\n                    _response.state = 'messageReceived';\n                    _response.status = 200;\n\n                    message = message.data;\n                    var skipCallbackInvocation = _trackMessageSize(message, _request, _response);\n                    if (!skipCallbackInvocation) {\n                        _invokeCallback();\n                        _response.responseBody = '';\n                        _response.messages = [];\n                    }\n                };\n\n                _sse.onerror = function (message) {\n                    clearTimeout(_request.id);\n\n                    if (_response.closedByClientTimeout) return;\n\n                    _invokeClose(sseOpened);\n                    _clearState();\n\n                    if (_abordingConnection) {\n                        jQuery.atmosphere.log(_request.logLevel, [\"SSE closed normally\"]);\n                    } else if (!sseOpened) {\n                        _reconnectWithFallbackTransport(\"SSE failed. Downgrading to fallback transport and resending\");\n                    } else if (_request.reconnect && (_response.transport === 'sse')) {\n                        if (_requestCount++ < _request.maxReconnectOnClose) {\n                            _open('re-connecting', _request.transport, _request);\n                            if (_request.reconnectInterval > 0) {\n                                _request.reconnectId = setTimeout(function () {\n                                    _executeSSE(true);\n                                }, _request.reconnectInterval);\n                            } else {\n                                _executeSSE(true);\n                            }\n                            _response.responseBody = \"\";\n                            _response.messages = [];\n                        } else {\n                            jQuery.atmosphere.log(_request.logLevel, [\"SSE reconnect maximum try reached \" + _requestCount]);\n                            _onError(0, \"maxReconnectOnClose reached\");\n                        }\n                    }\n                };\n            }\n\n            /**\n             * Open web socket. <br>\n             * Automatically use fallback transport if web socket can't be opened.\n             *\n             * @private\n             */\n            function _executeWebSocket(webSocketOpened) {\n\n                _response.transport = \"websocket\";\n\n                if (_request.enableProtocol && webSocketOpened) {\n                    var time = jQuery.now() - _request.ctime;\n                    _request.lastTimestamp = Number(_request.stime) + Number(time);\n                }\n\n                var location = _buildWebSocketUrl(_request.url);\n                if (_request.logLevel === 'debug') {\n                    jQuery.atmosphere.debug(\"Invoking executeWebSocket\");\n                    jQuery.atmosphere.debug(\"Using URL: \" + location);\n                }\n\n                if (webSocketOpened && !_request.reconnect) {\n                    if (_websocket != null) {\n                        _clearState();\n                    }\n                    return;\n                }\n\n                _websocket = _getWebSocket(location);\n                if (_request.webSocketBinaryType != null) {\n                    _websocket.binaryType = _request.webSocketBinaryType;\n                }\n\n                if (_request.connectTimeout > 0) {\n                    _request.id = setTimeout(function () {\n                        if (!webSocketOpened) {\n                            var _message = {\n                                code: 1002,\n                                reason: \"\",\n                                wasClean: false\n                            };\n                            _websocket.onclose(_message);\n                            // Close it anyway\n                            try {\n                                _clearState();\n                            } catch (e) {\n                            }\n                            return;\n                        }\n\n                    }, _request.connectTimeout);\n                }\n\n                _websocket.onopen = function (message) {\n                    _timeout(_request);\n                    if (_request.logLevel === 'debug') {\n                        jQuery.atmosphere.debug(\"Websocket successfully opened\");\n                    }\n\n                    var reopening = webSocketOpened;\n\n                    webSocketOpened = true;\n                    if(_websocket != null) {\n                        _websocket.webSocketOpened = webSocketOpened;\n                    }\n\n                    if (!_request.enableProtocol) {\n                        if (reopening) {\n                            _open('re-opening', \"websocket\", _request);\n                        } else {\n                            _open('opening', \"websocket\", _request);\n                        }\n                    }\n\n                    if (_websocket != null) {\n                        if (_request.method === 'POST') {\n                            _response.state = \"messageReceived\";\n                            _websocket.send(_request.data);\n                        }\n                    }\n                };\n\n                _websocket.onmessage = function (message) {\n                    _timeout(_request);\n\n                    _response.state = 'messageReceived';\n                    _response.status = 200;\n\n                    message = message.data;\n                    var isString = typeof (message) === 'string';\n                    if (isString) {\n                        var skipCallbackInvocation = _trackMessageSize(message, _request, _response);\n                        if (!skipCallbackInvocation) {\n                            _invokeCallback();\n                            _response.responseBody = '';\n                            _response.messages = [];\n                        }\n                    } else {\n                        if (!_handleProtocol(_request, message))\n                            return;\n\n                        _response.responseBody = message;\n                        _invokeCallback();\n                        _response.responseBody = null;\n                    }\n                };\n\n                _websocket.onerror = function (message) {\n                    clearTimeout(_request.id);\n                };\n\n                _websocket.onclose = function (message) {\n                    if (_response.state === 'closed')\n                        return;\n                    clearTimeout(_request.id);\n\n                    var reason = message.reason;\n                    if (reason === \"\") {\n                        switch (message.code) {\n                            case 1000:\n                                reason = \"Normal closure; the connection successfully completed whatever purpose for which \" + \"it was created.\";\n                                break;\n                            case 1001:\n                                reason = \"The endpoint is going away, either because of a server failure or because the \"\n                                    + \"browser is navigating away from the page that opened the connection.\";\n                                break;\n                            case 1002:\n                                reason = \"The endpoint is terminating the connection due to a protocol error.\";\n                                break;\n                            case 1003:\n                                reason = \"The connection is being terminated because the endpoint received data of a type it \"\n                                    + \"cannot accept (for example, a text-only endpoint received binary data).\";\n                                break;\n                            case 1004:\n                                reason = \"The endpoint is terminating the connection because a data frame was received that \" + \"is too large.\";\n                                break;\n                            case 1005:\n                                reason = \"Unknown: no status code was provided even though one was expected.\";\n                                break;\n                            case 1006:\n                                reason = \"Connection was closed abnormally (that is, with no close frame being sent).\";\n                                break;\n                        }\n                    }\n\n                    if (_request.logLevel === 'warn') {\n                        jQuery.atmosphere.warn(\"Websocket closed, reason: \" + reason);\n                        jQuery.atmosphere.warn(\"Websocket closed, wasClean: \" + message.wasClean);\n                    }\n\n                    if (_response.closedByClientTimeout) {\n                        return;\n                    }\n\n                    _invokeClose(webSocketOpened);\n\n                    _response.state = 'closed';\n\n                    if (_abordingConnection) {\n                        jQuery.atmosphere.log(_request.logLevel, [\"Websocket closed normally\"]);\n                    } else if (!webSocketOpened) {\n                        _reconnectWithFallbackTransport(\"Websocket failed. Downgrading to Comet and resending\");\n\n                    } else if (_request.reconnect && _response.transport === 'websocket') {\n                        _clearState();\n                        if (_requestCount++ < _request.maxReconnectOnClose) {\n                            _open('re-connecting', _request.transport, _request);\n                            if (_request.reconnectInterval > 0) {\n                                _request.reconnectId = setTimeout(function () {\n                                    _response.responseBody = \"\";\n                                    _response.messages = [];\n                                    _executeWebSocket(true);\n                                }, _request.reconnectInterval);\n                            } else {\n                                _response.responseBody = \"\";\n                                _response.messages = [];\n                                _executeWebSocket(true);\n                            }\n                        } else {\n                            jQuery.atmosphere.log(_request.logLevel, [\"Websocket reconnect maximum try reached \" + _request.requestCount]);\n                            if (_request.logLevel === 'warn') {\n                                jQuery.atmosphere.warn(\"Websocket error, reason: \" + message.reason);\n                            }\n                            _onError(0, \"maxReconnectOnClose reached\");\n                        }\n                    }\n                };\n\n                if (_websocket.url === undefined) {\n                    // Android 4.1 does not really support websockets and fails silently\n                    _websocket.onclose({\n                        reason: \"Android 4.1 does not support websockets.\",\n                        wasClean: false\n                    });\n                }\n            }\n\n            function _handleProtocol(request, message) {\n                // The first messages is always the uuid.\n                var b = true;\n\n                if (request.transport === 'polling') return b;\n\n                if (jQuery.trim(message).length !== 0 && request.enableProtocol && request.firstMessage) {\n                    request.firstMessage = false;\n                    var messages = message.split(request.messageDelimiter);\n                    var pos = messages.length === 2 ? 0 : 1;\n                    request.uuid = jQuery.trim(messages[pos]);\n                    request.stime = jQuery.trim(messages[pos + 1]);\n                    b = false;\n                    if (request.transport !== 'long-polling') {\n                        _triggerOpen(request);\n                    }\n\n                    jQuery.atmosphere.uuid = request.uuid;\n                } else if (request.enableProtocol && request.firstMessage) {\n                    // In case we are getting some junk from IE\n                    b = false;\n                } else {\n                    _triggerOpen(request);\n                }\n                return b;\n            }\n\n            function _timeout(_request) {\n                clearTimeout(_request.id);\n                if (_request.timeout > 0 && _request.transport !== 'polling') {\n                    _request.id = setTimeout(function () {\n                        _onClientTimeout(_request);\n                        _disconnect();\n                        _clearState();\n                    }, _request.timeout);\n                }\n            }\n\n            function _onClientTimeout(_request) {\n                _response.closedByClientTimeout = true;\n                _response.state = 'closedByClient';\n                _response.responseBody = \"\";\n                _response.status = 408;\n                _response.messages = [];\n                _invokeCallback();\n            }\n\n            function _onError(code, reason) {\n                _clearState();\n                clearTimeout(_request.id);\n                _response.state = 'error';\n                _response.reasonPhrase = reason;\n                _response.responseBody = \"\";\n                _response.status = code;\n                _response.messages = [];\n                _invokeCallback();\n            }\n\n            /**\n             * Track received message and make sure callbacks/functions are only invoked when the complete message has been received.\n             *\n             * @param message\n             * @param request\n             * @param response\n             */\n            function _trackMessageSize(message, request, response) {\n                if (!_handleProtocol(request, message))\n                    return true;\n                if (message.length === 0)\n                    return true;\n\n                if (request.trackMessageLength) {\n                    // prepend partialMessage if any\n                    message = response.partialMessage + message;\n\n                    var messages = [];\n                    var messageStart = message.indexOf(request.messageDelimiter);\n                    while (messageStart !== -1) {\n                        var str = jQuery.trim(message.substring(0, messageStart));\n                        var messageLength = parseInt(str, 10);\n                        if (isNaN(messageLength))\n                            throw 'message length \"' + str + '\" is not a number';\n                        messageStart += request.messageDelimiter.length;\n                        if (messageStart + messageLength > message.length) {\n                            // message not complete, so there is no trailing messageDelimiter\n                            messageStart = -1;\n                        } else {\n                            // message complete, so add it\n                            messages.push(message.substring(messageStart, messageStart + messageLength));\n                            // remove consumed characters\n                            message = message.substring(messageStart + messageLength, message.length);\n                            messageStart = message.indexOf(request.messageDelimiter);\n                        }\n                    }\n\n                    /* keep any remaining data */\n                    response.partialMessage = message;\n\n                    if (messages.length !== 0) {\n                        response.responseBody = messages.join(request.messageDelimiter);\n                        response.messages = messages;\n                        return false;\n                    } else {\n                        response.responseBody = \"\";\n                        response.messages = [];\n                        return true;\n                    }\n                } else {\n                    response.responseBody = message;\n                }\n                return false;\n            }\n\n            /**\n             * Reconnect request with fallback transport. <br>\n             * Used in case websocket can't be opened.\n             *\n             * @private\n             */\n            function _reconnectWithFallbackTransport(errorMessage) {\n                jQuery.atmosphere.log(_request.logLevel, [errorMessage]);\n\n                if (typeof (_request.onTransportFailure) !== 'undefined') {\n                    _request.onTransportFailure(errorMessage, _request);\n                } else if (typeof (jQuery.atmosphere.onTransportFailure) !== 'undefined') {\n                    jQuery.atmosphere.onTransportFailure(errorMessage, _request);\n                }\n\n                _request.transport = _request.fallbackTransport;\n                var reconnectInterval = _request.connectTimeout === -1 ? 0 : _request.connectTimeout;\n                if (_request.reconnect && _request.transport !== 'none' || _request.transport == null) {\n                    _request.method = _request.fallbackMethod;\n                    _response.transport = _request.fallbackTransport;\n                    _request.fallbackTransport = 'none';\n                    if (reconnectInterval > 0) {\n                        _request.reconnectId = setTimeout(function () {\n                            _execute();\n                        }, reconnectInterval);\n                    } else {\n                        _execute();\n                    }\n                } else {\n                    _onError(500, \"Unable to reconnect with fallback transport\");\n                }\n            }\n\n            /**\n             * Get url from request and attach headers to it.\n             *\n             * @param request {Object} request Request parameters, if undefined _request object will be used.\n             *\n             * @returns {Object} Request object, if undefined, _request object will be used.\n             * @private\n             */\n            function _attachHeaders(request, url) {\n                var rq = _request;\n                if ((request != null) && (typeof (request) !== 'undefined')) {\n                    rq = request;\n                }\n\n                if (url == null) {\n                    url = rq.url;\n                }\n\n                // If not enabled\n                if (!rq.attachHeadersAsQueryString)\n                    return url;\n\n                // If already added\n                if (url.indexOf(\"X-Atmosphere-Framework\") !== -1) {\n                    return url;\n                }\n\n                url += (url.indexOf('?') !== -1) ? '&' : '?';\n                url += \"X-Atmosphere-tracking-id=\" + rq.uuid;\n                url += \"&X-Atmosphere-Framework=\" + jQuery.atmosphere.version;\n                url += \"&X-Atmosphere-Transport=\" + rq.transport;\n\n                if (rq.trackMessageLength) {\n                    url += \"&X-Atmosphere-TrackMessageSize=\" + \"true\";\n                }\n\n                if (rq.lastTimestamp != null) {\n                    url += \"&X-Cache-Date=\" + rq.lastTimestamp;\n                } else {\n                    url += \"&X-Cache-Date=\" + 0;\n                }\n\n                if (rq.contentType !== '') {\n                    url += \"&Content-Type=\" + encodeURIComponent(rq.contentType);\n                }\n\n                if (rq.enableProtocol) {\n                    url += \"&X-atmo-protocol=true\";\n                }\n\n                jQuery.each(rq.headers, function (name, value) {\n                    var h = jQuery.isFunction(value) ? value.call(this, rq, request, _response) : value;\n                    if (h != null) {\n                        url += \"&\" + encodeURIComponent(name) + \"=\" + encodeURIComponent(h);\n                    }\n                });\n\n                return url;\n            }\n\n            function _triggerOpen(rq) {\n                if (!rq.isOpen) {\n                    rq.isOpen = true;\n                    _open('opening', rq.transport, rq);\n                } else if (rq.isReopen) {\n                    rq.isReopen = false;\n                    _open('re-opening', rq.transport, rq);\n                }\n            }\n\n            /**\n             * Execute ajax request. <br>\n             *\n             * @param request {Object} request Request parameters, if undefined _request object will be used.\n             * @private\n             */\n            function _executeRequest(request) {\n                var rq = _request;\n                if ((request != null) || (typeof (request) !== 'undefined')) {\n                    rq = request;\n                }\n\n                rq.lastIndex = 0;\n                rq.readyState = 0;\n\n                // CORS fake using JSONP\n                if ((rq.transport === 'jsonp') || ((rq.enableXDR) && (jQuery.atmosphere.checkCORSSupport()))) {\n                    _jsonp(rq);\n                    return;\n                }\n\n                if (rq.transport === 'ajax') {\n                    _ajax(request);\n                    return;\n                }\n\n                if (jQuery.browser.msie && +jQuery.browser.version.split(\".\")[0] < 10) {\n                    if ((rq.transport === 'streaming')) {\n                        if (rq.enableXDR && window.XDomainRequest) {\n                            _ieXDR(rq);\n                        } else {\n                            _ieStreaming(rq);\n                        }\n                        return;\n                    }\n\n                    if ((rq.enableXDR) && (window.XDomainRequest)) {\n                        _ieXDR(rq);\n                        return;\n                    }\n                }\n\n                var reconnectF = function () {\n                    rq.lastIndex = 0;\n                    if (rq.reconnect && _requestCount++ < rq.maxReconnectOnClose) {\n                        _open('re-connecting', request.transport, request);\n                        _reconnect(ajaxRequest, rq, request.reconnectInterval);\n                    } else {\n                        _onError(0, \"maxReconnectOnClose reached\");\n                    }\n                };\n\n                if (rq.reconnect && (rq.maxRequest === -1 || rq.requestCount++ < rq.maxRequest)) {\n                    var ajaxRequest = jQuery.ajaxSettings.xhr();\n                    ajaxRequest.hasData = false;\n\n                    _doRequest(ajaxRequest, rq, true);\n\n                    if (rq.suspend) {\n                        _activeRequest = ajaxRequest;\n                    }\n\n                    if (rq.transport !== 'polling') {\n                        _response.transport = rq.transport;\n\n                        ajaxRequest.onabort = function () {\n                            _invokeClose(true);\n                        };\n\n                        ajaxRequest.onerror = function () {\n                            _response.error = true;\n                            try {\n                                _response.status = XMLHttpRequest.status;\n                            } catch (e) {\n                                _response.status = 500;\n                            }\n\n                            if (!_response.status) {\n                                _response.status = 500;\n                            }\n                            if (!_response.errorHandled) {\n                                _clearState();\n                                reconnectF();\n                            }\n                        };\n                    }\n\n                    ajaxRequest.onreadystatechange = function () {\n                        if (_abordingConnection) {\n                            return;\n                        }\n\n                        _response.error = null;\n                        var skipCallbackInvocation = false;\n                        var update = false;\n\n                        if (rq.transport === 'streaming' && rq.readyState > 2 && ajaxRequest.readyState === 4) {\n                            _clearState();\n                            reconnectF();\n                            return;\n                        }\n\n                        rq.readyState = ajaxRequest.readyState;\n\n                        if (rq.transport === 'streaming' && ajaxRequest.readyState >= 3) {\n                            update = true;\n                        } else if (rq.transport === 'long-polling' && ajaxRequest.readyState === 4) {\n                            update = true;\n                        }\n                        _timeout(_request);\n\n                        if (rq.transport !== 'polling') {\n                            // MSIE 9 and lower status can be higher than 1000, Chrome can be 0\n                            var status = 200;\n                            if (ajaxRequest.readyState === 4) {\n                                status = ajaxRequest.status > 1000 ? 0 : ajaxRequest.status;\n                            }\n\n                            if (status >= 300 || status === 0) {\n                                // Prevent onerror callback to be called\n                                _response.errorHandled = true;\n                                _clearState();\n                                reconnectF();\n                                return;\n                            }\n                            \n                            // Firefox incorrectly send statechange 0->2 when a reconnect attempt fails. The above checks ensure that onopen is not called for these\n                            if ((!rq.enableProtocol || !request.firstMessage) && ajaxRequest.readyState === 2) {\n                                _triggerOpen(rq);\n                            }\n                        } else if (ajaxRequest.readyState === 4) {\n                            update = true;\n                        }\n\n                        if (update) {\n                            var responseText = ajaxRequest.responseText;\n\n                            if (jQuery.trim(responseText).length === 0 && rq.transport === 'long-polling') {\n                                // For browser that aren't support onabort\n                                if (!ajaxRequest.hasData) {\n                                    _reconnect(ajaxRequest, rq, 0);\n                                } else {\n                                    ajaxRequest.hasData = false;\n                                }\n                                return;\n                            }\n                            ajaxRequest.hasData = true;\n\n                            _readHeaders(ajaxRequest, _request);\n\n                            if (rq.transport === 'streaming') {\n                                if (!jQuery.browser.opera) {\n                                    var message = responseText.substring(rq.lastIndex, responseText.length);\n                                    skipCallbackInvocation = _trackMessageSize(message, rq, _response);\n\n                                    rq.lastIndex = responseText.length;\n                                    if (skipCallbackInvocation) {\n                                        return;\n                                    }\n                                } else {\n                                    jQuery.atmosphere.iterate(function () {\n                                        if (_response.status !== 500 && ajaxRequest.responseText.length > rq.lastIndex) {\n                                            try {\n                                                _response.status = ajaxRequest.status;\n                                                _response.headers = parseHeaders(ajaxRequest.getAllResponseHeaders());\n\n                                                _readHeaders(ajaxRequest, _request);\n\n                                            } catch (e) {\n                                                _response.status = 404;\n                                            }\n                                            _timeout(_request);\n\n                                            _response.state = \"messageReceived\";\n                                            var message = ajaxRequest.responseText.substring(rq.lastIndex);\n                                            rq.lastIndex = ajaxRequest.responseText.length;\n\n                                            skipCallbackInvocation = _trackMessageSize(message, rq, _response);\n                                            if (!skipCallbackInvocation) {\n                                                _invokeCallback();\n                                            }\n\n                                            _verifyStreamingLength(ajaxRequest, rq);\n                                        } else if (_response.status > 400) {\n                                            // Prevent replaying the last message.\n                                            rq.lastIndex = ajaxRequest.responseText.length;\n                                            return false;\n                                        }\n                                    }, 0);\n                                }\n                            } else {\n                                skipCallbackInvocation = _trackMessageSize(responseText, rq, _response);\n                            }\n\n                            try {\n                                _response.status = ajaxRequest.status;\n                                _response.headers = parseHeaders(ajaxRequest.getAllResponseHeaders());\n\n                                _readHeaders(ajaxRequest, rq);\n                            } catch (e) {\n                                _response.status = 404;\n                            }\n\n                            if (rq.suspend) {\n                                _response.state = _response.status === 0 ? \"closed\" : \"messageReceived\";\n                            } else {\n                                _response.state = \"messagePublished\";\n                            }\n\n                            var isAllowedToReconnect = request.transport !== 'streaming' && request.transport !== 'polling';;\n                            if (isAllowedToReconnect && !rq.executeCallbackBeforeReconnect) {\n                                _reconnect(ajaxRequest, rq, 0);\n                            }\n\n                            if (_response.responseBody.length !== 0 && !skipCallbackInvocation)\n                                _invokeCallback();\n\n                            if (isAllowedToReconnect && rq.executeCallbackBeforeReconnect) {\n                                _reconnect(ajaxRequest, rq, 0);\n                            }\n\n                            _verifyStreamingLength(ajaxRequest, rq);\n                        }\n                    };\n\n                    ajaxRequest.send(rq.data);\n                    _subscribed = true;\n                } else {\n                    if (rq.logLevel === 'debug') {\n                        jQuery.atmosphere.log(rq.logLevel, [\"Max re-connection reached.\"]);\n                    }\n                    _onError(0, \"maxRequest reached\");\n                }\n            }\n\n            /**\n             * Do ajax request.\n             *\n             * @param ajaxRequest Ajax request.\n             * @param request Request parameters.\n             * @param create If ajax request has to be open.\n             */\n            function _doRequest(ajaxRequest, request, create) {\n                // Prevent Android to cache request\n                var url = request.url;\n                if (request.dispatchUrl != null && request.method === 'POST') {\n                    url += request.dispatchUrl;\n                }\n                url = _attachHeaders(request, url);\n                url = jQuery.atmosphere.prepareURL(url);\n\n                if (create) {\n                    ajaxRequest.open(request.method, url, true);\n                    if (request.connectTimeout > 0) {\n                        request.id = setTimeout(function () {\n                            if (request.requestCount === 0) {\n                                _clearState();\n                                _prepareCallback(\"Connect timeout\", \"closed\", 200, request.transport);\n                            }\n                        }, request.connectTimeout);\n                    }\n                }\n\n                if (_request.withCredentials) {\n                    if (\"withCredentials\" in ajaxRequest) {\n                        ajaxRequest.withCredentials = true;\n                    }\n                }\n\n                if (!_request.dropHeaders) {\n                    ajaxRequest.setRequestHeader(\"X-Atmosphere-Framework\", jQuery.atmosphere.version);\n                    ajaxRequest.setRequestHeader(\"X-Atmosphere-Transport\", request.transport);\n                    if (request.lastTimestamp != null) {\n                        ajaxRequest.setRequestHeader(\"X-Cache-Date\", request.lastTimestamp);\n                    } else {\n                        ajaxRequest.setRequestHeader(\"X-Cache-Date\", 0);\n                    }\n\n                    if (request.trackMessageLength) {\n                        ajaxRequest.setRequestHeader(\"X-Atmosphere-TrackMessageSize\", \"true\");\n                    }\n                    ajaxRequest.setRequestHeader(\"X-Atmosphere-tracking-id\", request.uuid);\n\n                    jQuery.each(request.headers, function (name, value) {\n                        var h = jQuery.isFunction(value) ? value.call(this, ajaxRequest, request, create, _response) : value;\n                        if (h != null) {\n                            ajaxRequest.setRequestHeader(name, h);\n                        }\n                    });\n                }\n\n                if (request.contentType !== '') {\n                    ajaxRequest.setRequestHeader(\"Content-Type\", request.contentType);\n                }\n            }\n\n            function _reconnect(ajaxRequest, request, reconnectInterval) {\n                if (request.reconnect || (request.suspend && _subscribed)) {\n                    var status = 0;\n                    if (ajaxRequest.readyState !== 0) {\n                        status = ajaxRequest.status > 1000 ? 0 : ajaxRequest.status;\n                    }\n                    _response.status = status === 0 ? 204 : status;\n                    _response.reason = status === 0 ? \"Server resumed the connection or down.\" : \"OK\";\n\n                    // Reconnect immediately\n                    clearTimeout(request.id);\n                    if (request.reconnectId) {\n                        clearTimeout(request.reconnectId);\n                        delete request.reconnectId;\n                    }\n\n                    if (reconnectInterval > 0) {\n                        setTimeout(function () {\n                            _request.reconnectId = _executeRequest(request);\n                        }, reconnectInterval);\n                    } else {\n                        _executeRequest(request);\n                    }\n                }\n            }\n\n            function _tryingToReconnect(response) {\n                response.state = 're-connecting';\n                _invokeFunction(response);\n            }\n\n            // From jquery-stream, which is APL2 licensed as well.\n            function _ieXDR(request) {\n                if (request.transport !== \"polling\") {\n                    _ieStream = _configureXDR(request);\n                    _ieStream.open();\n                } else {\n                    _configureXDR(request).open();\n                }\n            }\n\n            function _configureXDR(request) {\n                var rq = _request;\n                if ((request != null) && (typeof (request) !== 'undefined')) {\n                    rq = request;\n                }\n\n                var transport = rq.transport;\n                var lastIndex = 0;\n                var xdr = new window.XDomainRequest();\n\n                var reconnect = function () {\n                    if (rq.transport === \"long-polling\" && (rq.reconnect && (rq.maxRequest === -1 || rq.requestCount++ < rq.maxRequest))) {\n                        xdr.status = 200;\n                        _ieXDR(rq);\n                    }\n                };\n\n                var rewriteURL = rq.rewriteURL || function (url) {\n                    // Maintaining session by rewriting URL\n                    // http://stackoverflow.com/questions/6453779/maintaining-session-by-rewriting-url\n                    var match = /(?:^|;\\s*)(JSESSIONID|PHPSESSID)=([^;]*)/.exec(document.cookie);\n\n                    switch (match && match[1]) {\n                        case \"JSESSIONID\":\n                            return url.replace(/;jsessionid=[^\\?]*|(\\?)|$/, \";jsessionid=\" + match[2] + \"$1\");\n                        case \"PHPSESSID\":\n                            return url.replace(/\\?PHPSESSID=[^&]*&?|\\?|$/, \"?PHPSESSID=\" + match[2] + \"&\").replace(/&$/, \"\");\n                    }\n                    return url;\n                };\n\n                // Handles open and message event\n                xdr.onprogress = function () {\n                    handle(xdr);\n                };\n                // Handles error event\n                xdr.onerror = function () {\n                    // If the server doesn't send anything back to XDR will fail with polling\n                    if (rq.transport !== 'polling') {\n                        _clearState();\n                        if (_requestCount++ < rq.maxReconnectOnClose) {\n                            if (rq.reconnectInterval > 0) {\n                                rq.reconnectId = setTimeout(function () {\n                                    _open('re-connecting', request.transport, request);\n                                    _ieXDR(rq);\n                                }, rq.reconnectInterval);\n                            } else {\n                                _open('re-connecting', request.transport, request);\n                                _ieXDR(rq);\n                            }\n                        } else {\n                            _onError(0, \"maxReconnectOnClose reached\");\n                        }\n                    }\n                };\n\n                // Handles close event\n                xdr.onload = function () {\n                };\n\n                var handle = function (xdr) {\n                    clearTimeout(rq.id);\n                    var message = xdr.responseText;\n\n                    message = message.substring(lastIndex);\n                    lastIndex += message.length;\n\n                    if (transport !== 'polling') {\n                        _timeout(rq);\n\n                        var skipCallbackInvocation = _trackMessageSize(message, rq, _response);\n\n                        if (transport === 'long-polling' && jQuery.trim(message).length === 0)\n                            return;\n\n                        if (rq.executeCallbackBeforeReconnect) {\n                            reconnect();\n                        }\n\n                        if (!skipCallbackInvocation) {\n                            _prepareCallback(_response.responseBody, \"messageReceived\", 200, transport);\n                        }\n\n                        if (!rq.executeCallbackBeforeReconnect) {\n                            reconnect();\n                        }\n                    }\n                };\n\n                return {\n                    open: function () {\n                        var url = rq.url;\n                        if (rq.dispatchUrl != null) {\n                            url += rq.dispatchUrl;\n                        }\n                        url = _attachHeaders(rq, url);\n                        xdr.open(rq.method, rewriteURL(url));\n                        if (rq.method === 'GET') {\n                            xdr.send();\n                        } else {\n                            xdr.send(rq.data);\n                        }\n\n                        if (rq.connectTimeout > 0) {\n                            rq.id = setTimeout(function () {\n                                if (rq.requestCount === 0) {\n                                    _clearState();\n                                    _prepareCallback(\"Connect timeout\", \"closed\", 200, rq.transport);\n                                }\n                            }, rq.connectTimeout);\n                        }\n                    },\n                    close: function () {\n                        xdr.abort();\n                    }\n                };\n            }\n\n            function _ieStreaming(request) {\n                _ieStream = _configureIE(request);\n                _ieStream.open();\n            }\n\n            function _configureIE(request) {\n                var rq = _request;\n                if ((request != null) && (typeof (request) !== 'undefined')) {\n                    rq = request;\n                }\n\n                var stop;\n                var doc = new window.ActiveXObject(\"htmlfile\");\n\n                doc.open();\n                doc.close();\n\n                var url = rq.url;\n                if (rq.dispatchUrl != null) {\n                    url += rq.dispatchUrl;\n                }\n\n                if (rq.transport !== 'polling') {\n                    _response.transport = rq.transport;\n                }\n\n                return {\n                    open: function () {\n                        var iframe = doc.createElement(\"iframe\");\n\n                        url = _attachHeaders(rq);\n                        if (rq.data !== '') {\n                            url += \"&X-Atmosphere-Post-Body=\" + encodeURIComponent(rq.data);\n                        }\n\n                        // Finally attach a timestamp to prevent Android and IE caching.\n                        url = jQuery.atmosphere.prepareURL(url);\n\n                        iframe.src = url;\n                        doc.body.appendChild(iframe);\n\n                        // For the server to respond in a consistent format regardless of user agent, we polls response text\n                        var cdoc = iframe.contentDocument || iframe.contentWindow.document;\n\n                        stop = jQuery.atmosphere.iterate(function () {\n                            try {\n                                if (!cdoc.firstChild) {\n                                    return;\n                                }\n\n                                // Detects connection failure\n                                if (cdoc.readyState === \"complete\") {\n                                    try {\n                                        jQuery.noop(cdoc.fileSize);\n                                    } catch (e) {\n                                        _prepareCallback(\"Connection Failure\", \"error\", 500, rq.transport);\n                                        return false;\n                                    }\n                                }\n\n                                var res = cdoc.body ? cdoc.body.lastChild : cdoc;\n                                var readResponse = function () {\n                                    // Clones the element not to disturb the original one\n                                    var clone = res.cloneNode(true);\n\n                                    // If the last character is a carriage return or a line feed, IE ignores it in the innerText property\n                                    // therefore, we add another non-newline character to preserve it\n                                    clone.appendChild(cdoc.createTextNode(\".\"));\n\n                                    var text = clone.innerText;\n\n                                    text = text.substring(0, text.length - 1);\n                                    return text;\n\n                                };\n\n                                // To support text/html content type\n                                if (!jQuery.nodeName(res, \"pre\")) {\n                                    // Injects a plaintext element which renders text without interpreting the HTML and cannot be stopped\n                                    // it is deprecated in HTML5, but still works\n                                    var head = cdoc.head || cdoc.getElementsByTagName(\"head\")[0] || cdoc.documentElement || cdoc;\n                                    var script = cdoc.createElement(\"script\");\n\n                                    script.text = \"document.write('<plaintext>')\";\n\n                                    head.insertBefore(script, head.firstChild);\n                                    head.removeChild(script);\n\n                                    // The plaintext element will be the response container\n                                    res = cdoc.body.lastChild;\n                                }\n\n                                if (rq.closed) {\n                                    rq.isReopen = true;\n                                }\n\n                                // Handles message and close event\n                                stop = jQuery.atmosphere.iterate(function () {\n                                    var text = readResponse();\n                                    if (text.length > rq.lastIndex) {\n                                        _timeout(_request);\n\n                                        _response.status = 200;\n                                        _response.error = null;\n\n                                        // Empties response every time that it is handled\n                                        res.innerText = \"\";\n                                        var skipCallbackInvocation = _trackMessageSize(text, rq, _response);\n                                        if (skipCallbackInvocation) {\n                                            return \"\";\n                                        }\n\n                                        _prepareCallback(_response.responseBody, \"messageReceived\", 200, rq.transport);\n                                    }\n\n                                    rq.lastIndex = 0;\n\n                                    if (cdoc.readyState === \"complete\") {\n                                        _invokeClose(true);\n                                        _open('re-connecting', rq.transport, rq);\n                                        if (rq.reconnectInterval > 0) {\n                                            rq.reconnectId = setTimeout(function () {\n                                                _ieStreaming(rq);\n                                            }, rq.reconnectInterval);\n                                        } else {\n                                            _ieStreaming(rq);\n                                        }\n                                        return false;\n                                    }\n                                }, null);\n\n                                return false;\n                            } catch (err) {\n                                _response.error = true;\n                                _open('re-connecting', rq.transport, rq);\n                                if (_requestCount++ < rq.maxReconnectOnClose) {\n                                    if (rq.reconnectInterval > 0) {\n                                        rq.reconnectId = setTimeout(function () {\n                                            _ieStreaming(rq);\n                                        }, rq.reconnectInterval);\n                                    } else {\n                                        _ieStreaming(rq);\n                                    }\n                                } else {\n                                    _onError(0, \"maxReconnectOnClose reached\");\n                                }\n                                doc.execCommand(\"Stop\");\n                                doc.close();\n                                return false;\n                            }\n                        });\n                    },\n\n                    close: function () {\n                        if (stop) {\n                            stop();\n                        }\n\n                        doc.execCommand(\"Stop\");\n                        _invokeClose(true);\n                    }\n                };\n            }\n\n            /**\n             * Send message. <br>\n             * Will be automatically dispatch to other connected.\n             *\n             * @param {Object, string} Message to send.\n             * @private\n             */\n            function _push(message) {\n\n                if (_localStorageService != null) {\n                    _pushLocal(message);\n                } else if (_activeRequest != null || _sse != null) {\n                    _pushAjaxMessage(message);\n                } else if (_ieStream != null) {\n                    _pushIE(message);\n                } else if (_jqxhr != null) {\n                    _pushJsonp(message);\n                } else if (_websocket != null) {\n                    _pushWebSocket(message);\n                } else {\n                    _onError(0, \"No suspended connection available\");\n                    jQuery.atmosphere.error(\"No suspended connection available. Make sure atmosphere.subscribe has been called and request.onOpen invoked before invoking this method\");\n                }\n            }\n\n            function _pushOnClose(message) {\n                var rq = _getPushRequest(message);\n                rq.transport = \"ajax\";\n                rq.method = \"GET\";\n                rq.async = false;\n                rq.reconnect = false;\n                _executeRequest(rq);\n            }\n\n            function _pushLocal(message) {\n                _localStorageService.send(message);\n            }\n\n            function _intraPush(message) {\n                // IE 9 will crash if not.\n                if (message.length === 0)\n                    return;\n\n                try {\n                    if (_localStorageService) {\n                        _localStorageService.localSend(message);\n                    } else if (_storageService) {\n                        _storageService.signal(\"localMessage\", jQuery.stringifyJSON({\n                            id: guid,\n                            event: message\n                        }));\n                    }\n                } catch (err) {\n                    jQuery.atmosphere.error(err);\n                }\n            }\n\n            /**\n             * Send a message using currently opened ajax request (using http-streaming or long-polling). <br>\n             *\n             * @param {string, Object} Message to send. This is an object, string message is saved in data member.\n             * @private\n             */\n            function _pushAjaxMessage(message) {\n                var rq = _getPushRequest(message);\n                _executeRequest(rq);\n            }\n\n            /**\n             * Send a message using currently opened ie streaming (using http-streaming or long-polling). <br>\n             *\n             * @param {string, Object} Message to send. This is an object, string message is saved in data member.\n             * @private\n             */\n            function _pushIE(message) {\n                if (_request.enableXDR && jQuery.atmosphere.checkCORSSupport()) {\n                    var rq = _getPushRequest(message);\n                    // Do not reconnect since we are pushing.\n                    rq.reconnect = false;\n                    _jsonp(rq);\n                } else {\n                    _pushAjaxMessage(message);\n                }\n            }\n\n            /**\n             * Send a message using jsonp transport. <br>\n             *\n             * @param {string, Object} Message to send. This is an object, string message is saved in data member.\n             * @private\n             */\n            function _pushJsonp(message) {\n                _pushAjaxMessage(message);\n            }\n\n            function _getStringMessage(message) {\n                var msg = message;\n                if (typeof (msg) === 'object') {\n                    msg = message.data;\n                }\n                return msg;\n            }\n\n            /**\n             * Build request use to push message using method 'POST' <br>. Transport is defined as 'polling' and 'suspend' is set to false.\n             *\n             * @return {Object} Request object use to push message.\n             * @private\n             */\n            function _getPushRequest(message) {\n                var msg = _getStringMessage(message);\n\n                var rq = {\n                    connected: false,\n                    timeout: 60000,\n                    method: 'POST',\n                    url: _request.url,\n                    contentType: _request.contentType,\n                    headers: _request.headers,\n                    reconnect: true,\n                    callback: null,\n                    data: msg,\n                    suspend: false,\n                    maxRequest: -1,\n                    logLevel: 'info',\n                    requestCount: 0,\n                    withCredentials: _request.withCredentials,\n                    transport: 'polling',\n                    isOpen: true,\n                    attachHeadersAsQueryString: true,\n                    enableXDR: _request.enableXDR,\n                    uuid: _request.uuid,\n                    dispatchUrl: _request.dispatchUrl,\n                    enableProtocol: false,\n                    messageDelimiter: '|',\n                    maxReconnectOnClose: _request.maxReconnectOnClose\n                };\n\n                if (typeof (message) === 'object') {\n                    rq = jQuery.extend(rq, message);\n                }\n\n                return rq;\n            }\n\n            /**\n             * Send a message using currently opened websocket. <br>\n             *\n             */\n            function _pushWebSocket(message) {\n                var msg = jQuery.atmosphere.isBinary(message) ? message : _getStringMessage(message);\n                var data;\n                try {\n                    if (_request.dispatchUrl != null) {\n                        data = _request.webSocketPathDelimiter + _request.dispatchUrl + _request.webSocketPathDelimiter + msg;\n                    } else {\n                        data = msg;\n                    }\n\n                    if (!_websocket.webSocketOpened) {\n                        jQuery.atmosphere.error(\"WebSocket not connected.\");\n                        return;\n                    }\n\n                    _websocket.send(data);\n\n                } catch (e) {\n                    _websocket.onclose = function (message) {\n                    };\n                    _clearState();\n\n                    _reconnectWithFallbackTransport(\"Websocket failed. Downgrading to Comet and resending \" + data);\n                    _pushAjaxMessage(message);\n                }\n            }\n\n            function _localMessage(message) {\n                var m = jQuery.parseJSON(message);\n                if (m.id !== guid) {\n                    if (typeof (_request.onLocalMessage) !== 'undefined') {\n                        _request.onLocalMessage(m.event);\n                    } else if (typeof (jQuery.atmosphere.onLocalMessage) !== 'undefined') {\n                        jQuery.atmosphere.onLocalMessage(m.event);\n                    }\n                }\n            }\n\n            function _prepareCallback(messageBody, state, errorCode, transport) {\n\n                _response.responseBody = messageBody;\n                _response.transport = transport;\n                _response.status = errorCode;\n                _response.state = state;\n\n                _invokeCallback();\n            }\n\n            function _readHeaders(xdr, request) {\n                if (!request.readResponsesHeaders) {\n                    if (!request.enableProtocol) {\n                        request.lastTimestamp = jQuery.now();\n                        request.uuid = jQuery.atmosphere.guid();\n                    }\n                }\n                else {\n                    try {\n                        var tempDate = xdr.getResponseHeader('X-Cache-Date');\n                        if (tempDate && tempDate != null && tempDate.length > 0) {\n                            request.lastTimestamp = tempDate.split(\" \").pop();\n                        }\n\n                        var tempUUID = xdr.getResponseHeader('X-Atmosphere-tracking-id');\n                        if (tempUUID && tempUUID != null) {\n                            request.uuid = tempUUID.split(\" \").pop();\n                        }\n                    } catch (e) {\n                    }\n                }\n            }\n\n            function _invokeFunction(response) {\n                _f(response, _request);\n                // Global\n                _f(response, jQuery.atmosphere);\n            }\n\n            function _f(response, f) {\n                switch (response.state) {\n                    case \"messageReceived\":\n                        _requestCount = 0;\n                        if (typeof (f.onMessage) !== 'undefined')\n                            f.onMessage(response);\n                        break;\n                    case \"error\":\n                        if (typeof (f.onError) !== 'undefined')\n                            f.onError(response);\n                        break;\n                    case \"opening\":\n                        delete _request.closed;\n                        if (typeof (f.onOpen) !== 'undefined')\n                            f.onOpen(response);\n                        break;\n                    case \"messagePublished\":\n                        if (typeof (f.onMessagePublished) !== 'undefined')\n                            f.onMessagePublished(response);\n                        break;\n                    case \"re-connecting\":\n                        if (typeof (f.onReconnect) !== 'undefined')\n                            f.onReconnect(_request, response);\n                        break;\n                    case \"closedByClient\":\n                        if (typeof (f.onClientTimeout) !== 'undefined')\n                            f.onClientTimeout(_request);\n                        break;\n                    case \"re-opening\":\n                        delete _request.closed;\n                        if (typeof (f.onReopen) !== 'undefined')\n                            f.onReopen(_request, response);\n                        break;\n                    case \"fail-to-reconnect\":\n                        if (typeof (f.onFailureToReconnect) !== 'undefined')\n                            f.onFailureToReconnect(_request, response);\n                        break;\n                    case \"unsubscribe\":\n                    case \"closed\":\n                        var closed = typeof (_request.closed) !== 'undefined' ? _request.closed : false;\n                        if (typeof (f.onClose) !== 'undefined' && !closed)\n                            f.onClose(response);\n                        _request.closed = true;\n                        break;\n                }\n            }\n\n            function _invokeClose(wasOpen) {\n                if (_response.state !== 'closed') {\n                    _response.state = 'closed';\n                    _response.responseBody = \"\";\n                    _response.messages = [];\n                    _response.status = !wasOpen ? 501 : 200;\n                    _invokeCallback();\n                }\n            }\n\n            /**\n             * Invoke request callbacks.\n             *\n             * @private\n             */\n            function _invokeCallback() {\n                var call = function (index, func) {\n                    func(_response);\n                };\n\n                if (_localStorageService == null && _localSocketF != null) {\n                    _localSocketF(_response.responseBody);\n                }\n\n                _request.reconnect = _request.mrequest;\n\n                var isString = typeof (_response.responseBody) === 'string';\n                var messages = (isString && _request.trackMessageLength) ? (_response.messages.length > 0 ? _response.messages : ['']) : new Array(\n                    _response.responseBody);\n                for (var i = 0; i < messages.length; i++) {\n\n                    if (messages.length > 1 && messages[i].length === 0) {\n                        continue;\n                    }\n                    _response.responseBody = (isString) ? jQuery.trim(messages[i]) : messages[i];\n\n                    if (_localStorageService == null && _localSocketF != null) {\n                        _localSocketF(_response.responseBody);\n                    }\n\n                    if (_response.responseBody.length === 0 && _response.state === \"messageReceived\") {\n                        continue;\n                    }\n\n                    _invokeFunction(_response);\n\n                    // Invoke global callbacks\n                    if (jQuery.atmosphere.callbacks.length > 0) {\n                        if (_request.logLevel === 'debug') {\n                            jQuery.atmosphere.debug(\"Invoking \" + jQuery.atmosphere.callbacks.length + \" global callbacks: \" + _response.state);\n                        }\n                        try {\n                            jQuery.each(jQuery.atmosphere.callbacks, call);\n                        } catch (e) {\n                            jQuery.atmosphere.log(_request.logLevel, [\"Callback exception\" + e]);\n                        }\n                    }\n\n                    // Invoke request callback\n                    if (typeof (_request.callback) === 'function') {\n                        if (_request.logLevel === 'debug') {\n                            jQuery.atmosphere.debug(\"Invoking request callbacks\");\n                        }\n                        try {\n                            _request.callback(_response);\n                        } catch (e) {\n                            jQuery.atmosphere.log(_request.logLevel, [\"Callback exception\" + e]);\n                        }\n                    }\n                }\n\n            }\n\n            /**\n             *\n             * @private\n             */\n            function _verifyStreamingLength(ajaxRequest, rq) {\n                // Wait to be sure we have the full message before closing.\n                if (_response.partialMessage === \"\" && (rq.transport === 'streaming') && (ajaxRequest.responseText.length > rq.maxStreamingLength)) {\n                    _response.messages = [];\n                    _invokeClose(true);\n                    _disconnect();\n                    _clearState();\n                    _reconnect(ajaxRequest, rq, 0);\n                }\n            }\n\n            /**\n             * Disconnect\n             *\n             * @private\n             */\n            function _disconnect() {\n                if (_request.enableProtocol && !_request.firstMessage) {\n                    var query = \"X-Atmosphere-Transport=close&X-Atmosphere-tracking-id=\" + _request.uuid;\n\n                    jQuery.each(_request.headers, function (name, value) {\n                        var h = jQuery.isFunction(value) ? value.call(this, _request, _request, _response) : value;\n                        if (h != null) {\n                            query += \"&\" + encodeURIComponent(name) + \"=\" + encodeURIComponent(h);\n                        }\n                    });\n\n                    var url = _request.url.replace(/([?&])_=[^&]*/, query);\n                    url = url + (url === _request.url ? (/\\?/.test(_request.url) ? \"&\" : \"?\") + query : \"\");\n\n                    if (_request.connectTimeout > 0) {\n                        jQuery.ajax({\n                            url: url,\n                            async: true,\n                            timeout: _request.connectTimeout,\n                            cache: false\n                        });\n                    } else {\n                        jQuery.ajax({\n                            url: url,\n                            async: true,\n                            cache: false\n                        });\n                    }\n                }\n            }\n\n            /**\n             * Close request.\n             *\n             * @private\n             */\n            function _close() {\n                if (_request.reconnectId) {\n                    clearTimeout(_request.reconnectId);\n                    delete _request.reconnectId;\n                }\n                _request.reconnect = false;\n                _abordingConnection = true;\n                _response.request = _request;\n                _response.state = 'unsubscribe';\n                _response.responseBody = \"\";\n                _response.status = 408;\n                _invokeCallback();\n                _disconnect();\n\n                _clearState();\n            }\n\n            function _clearState() {\n                if (_request.id) {\n                    clearTimeout(_request.id);\n                }\n\n                if (_ieStream != null) {\n                    _ieStream.close();\n                    _ieStream = null;\n                }\n                if (_jqxhr != null) {\n                    _jqxhr.abort();\n                    _jqxhr = null;\n                }\n                if (_activeRequest != null) {\n                    _activeRequest.abort();\n                    _activeRequest = null;\n                }\n                if (_websocket != null) {\n                    if (_websocket.webSocketOpened) {\n                        _websocket.close();\n                    }\n                    _websocket = null;\n                }\n                if (_sse != null) {\n                    _sse.close();\n                    _sse = null;\n                }\n\n                _clearStorage();\n            }\n\n            function _clearStorage() {\n                // Stop sharing a connection\n                if (_storageService != null) {\n                    // Clears trace timer\n                    clearInterval(_traceTimer);\n                    // Removes the trace\n                    document.cookie = _sharingKey + \"=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/\";\n                    // The heir is the parent unless unloading\n                    _storageService.signal(\"close\", {\n                        reason: \"\",\n                        heir: !_abordingConnection ? guid : (_storageService.get(\"children\") || [])[0]\n                    });\n                    _storageService.close();\n                }\n                if (_localStorageService != null) {\n                    _localStorageService.close();\n                }\n            }\n\n            this.subscribe = function (options) {\n                _subscribe(options);\n                _execute();\n            };\n\n            this.execute = function () {\n                _execute();\n            };\n\n            this.invokeCallback = function () {\n                _invokeCallback();\n            };\n\n            this.close = function () {\n                _close();\n            };\n\n            this.disconnect = function () {\n                _disconnect();\n            };\n\n            this.getUrl = function () {\n                return _request.url;\n            };\n\n            this.push = function (message, dispatchUrl) {\n                if (dispatchUrl != null) {\n                    var originalDispatchUrl = _request.dispatchUrl;\n                    _request.dispatchUrl = dispatchUrl;\n                    _push(message);\n                    _request.dispatchUrl = originalDispatchUrl;\n                } else {\n                    _push(message);\n                }\n            };\n\n            this.getUUID = function () {\n                return _request.uuid;\n            };\n\n            this.pushLocal = function (message) {\n                _intraPush(message);\n            };\n\n            this.enableProtocol = function (message) {\n                return _request.enableProtocol;\n            };\n\n            this.request = _request;\n            this.response = _response;\n        },\n\n        subscribe: function (url, callback, request) {\n            if (typeof (callback) === 'function') {\n                jQuery.atmosphere.addCallback(callback);\n            }\n\n            // https://github.com/Atmosphere/atmosphere-javascript/issues/58\n            jQuery.atmosphere.uuid = 0;\n\n            if (typeof (url) !== \"string\") {\n                request = url;\n            } else {\n                request.url = url;\n            }\n\n            var rq = new jQuery.atmosphere.AtmosphereRequest(request);\n            rq.execute();\n\n            jQuery.atmosphere.requests[jQuery.atmosphere.requests.length] = rq;\n            return rq;\n        },\n\n        addCallback: function (func) {\n            if (jQuery.inArray(func, jQuery.atmosphere.callbacks) === -1) {\n                jQuery.atmosphere.callbacks.push(func);\n            }\n        },\n\n        removeCallback: function (func) {\n            var index = jQuery.inArray(func, jQuery.atmosphere.callbacks);\n            if (index !== -1) {\n                jQuery.atmosphere.callbacks.splice(index, 1);\n            }\n        },\n\n        unsubscribe: function () {\n            if (jQuery.atmosphere.requests.length > 0) {\n                var requestsClone = [].concat(jQuery.atmosphere.requests);\n                for (var i = 0; i < requestsClone.length; i++) {\n                    var rq = requestsClone[i];\n                    rq.close();\n                    clearTimeout(rq.response.request.id);\n                }\n            }\n            jQuery.atmosphere.requests = [];\n            jQuery.atmosphere.callbacks = [];\n        },\n\n        unsubscribeUrl: function (url) {\n            var idx = -1;\n            if (jQuery.atmosphere.requests.length > 0) {\n                for (var i = 0; i < jQuery.atmosphere.requests.length; i++) {\n                    var rq = jQuery.atmosphere.requests[i];\n\n                    // Suppose you can subscribe once to an url\n                    if (rq.getUrl() === url) {\n                        rq.close();\n                        clearTimeout(rq.response.request.id);\n                        idx = i;\n                        break;\n                    }\n                }\n            }\n            if (idx >= 0) {\n                jQuery.atmosphere.requests.splice(idx, 1);\n            }\n        },\n\n        publish: function (request) {\n            if (typeof (request.callback) === 'function') {\n                jQuery.atmosphere.addCallback(request.callback);\n            }\n            request.transport = \"polling\";\n\n            var rq = new jQuery.atmosphere.AtmosphereRequest(request);\n            jQuery.atmosphere.requests[jQuery.atmosphere.requests.length] = rq;\n            return rq;\n        },\n\n        checkCORSSupport: function () {\n            if (jQuery.browser.msie && !window.XDomainRequest) {\n                return true;\n            } else if (jQuery.browser.opera && +jQuery.browser.version.split(\".\")[0] < 12.0) {\n                return true;\n            }\n\n            // KreaTV 4.1 -> 4.4\n            else if (jQuery.trim(navigator.userAgent).slice(0, 16) === \"KreaTVWebKit/531\") {\n                return true;\n            }\n            // KreaTV 3.8\n            else if (jQuery.trim(navigator.userAgent).slice(-7).toLowerCase() === \"kreatel\") {\n                return true;\n            }\n\n            // Force Android to use CORS as some version like 2.2.3 fail otherwise\n            var ua = navigator.userAgent.toLowerCase();\n            var isAndroid = ua.indexOf(\"android\") > -1;\n            if (isAndroid) {\n                return true;\n            }\n            return false;\n        },\n\n        S4: function () {\n            return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1);\n        },\n\n        guid: function () {\n            return (jQuery.atmosphere.S4() + jQuery.atmosphere.S4() + \"-\" + jQuery.atmosphere.S4() + \"-\" + jQuery.atmosphere.S4() + \"-\"\n                + jQuery.atmosphere.S4() + \"-\" + jQuery.atmosphere.S4() + jQuery.atmosphere.S4() + jQuery.atmosphere.S4());\n        },\n\n        // From jQuery-Stream\n        prepareURL: function (url) {\n            // Attaches a time stamp to prevent caching\n            var ts = jQuery.now();\n            var ret = url.replace(/([?&])_=[^&]*/, \"$1_=\" + ts);\n\n            return ret + (ret === url ? (/\\?/.test(url) ? \"&\" : \"?\") + \"_=\" + ts : \"\");\n        },\n\n        // From jQuery-Stream\n        param: function (data) {\n            return jQuery.param(data, jQuery.ajaxSettings.traditional);\n        },\n\n        supportStorage: function () {\n            var storage = window.localStorage;\n            if (storage) {\n                try {\n                    storage.setItem(\"t\", \"t\");\n                    storage.removeItem(\"t\");\n                    // The storage event of Internet Explorer and Firefox 3 works strangely\n                    return window.StorageEvent && !jQuery.browser.msie && !(jQuery.browser.mozilla && jQuery.browser.version.split(\".\")[0] === \"1\");\n                } catch (e) {\n                }\n            }\n\n            return false;\n        },\n\n        iterate: function (fn, interval) {\n            var timeoutId;\n\n            // Though the interval is 0 for real-time application, there is a delay between setTimeout calls\n            // For detail, see https://developer.mozilla.org/en/window.setTimeout#Minimum_delay_and_timeout_nesting\n            interval = interval || 0;\n\n            (function loop() {\n                timeoutId = setTimeout(function () {\n                    if (fn() === false) {\n                        return;\n                    }\n\n                    loop();\n                }, interval);\n            })();\n\n            return function () {\n                clearTimeout(timeoutId);\n            };\n        },\n\n        log: function (level, args) {\n            if (window.console) {\n                var logger = window.console[level];\n                if (typeof logger === 'function') {\n                    logger.apply(window.console, args);\n                }\n            }\n        },\n\n        warn: function () {\n            jQuery.atmosphere.log('warn', arguments);\n        },\n\n        info: function () {\n            jQuery.atmosphere.log('info', arguments);\n        },\n\n        debug: function () {\n            jQuery.atmosphere.log('debug', arguments);\n        },\n\n        error: function () {\n            jQuery.atmosphere.log('error', arguments);\n        },\n\n        // TODO extract to utils or something\n        isBinary: function (data) {\n            // True if data is an instance of Blob, ArrayBuffer or ArrayBufferView \n            return /^\\[object\\s(?:Blob|ArrayBuffer|.+Array)\\]$/.test(Object.prototype.toString.call(data));\n        }\n    };\n}();\n\n// http://stackoverflow.com/questions/9645803/whats-the-replacement-for-browser\n// Limit scope pollution from any deprecated API\n(function () {\n\n    var matched, browser;\n\n    // Use of jQuery.browser is frowned upon.\n    // More details: http://api.jquery.com/jQuery.browser\n    // jQuery.uaMatch maintained for back-compat\n    jQuery.uaMatch = function (ua) {\n        ua = ua.toLowerCase();\n\n        var match = /(chrome)[ \\/]([\\w.]+)/.exec(ua) || \n                /(webkit)[ \\/]([\\w.]+)/.exec(ua) || \n                /(opera)(?:.*version|)[ \\/]([\\w.]+)/.exec(ua) || \n                /(msie) ([\\w.]+)/.exec(ua) || \n                /(trident)(?:.*? rv:([\\w.]+)|)/.exec(ua) ||\n                ua.indexOf(\"compatible\") < 0 && /(mozilla)(?:.*? rv:([\\w.]+)|)/.exec(ua) || \n                [];\n\n        return {\n            browser: match[1] || \"\",\n            version: match[2] || \"0\"\n        };\n    };\n\n    matched = jQuery.uaMatch(navigator.userAgent);\n    browser = {};\n\n    if (matched.browser) {\n        browser[matched.browser] = true;\n        browser.version = matched.version;\n    }\n\n    // Chrome is Webkit, but Webkit is also Safari.\n    if (browser.chrome) {\n        browser.webkit = true;\n    } else if (browser.webkit) {\n        browser.safari = true;\n    }\n    \n    // Trident is the layout engine of the Internet Explorer\n    // IE 11 has no \"MSIE: 11.0\" token\n    if (browser.trident) {\n    \tbrowser.msie = true;\n    }\n\n    jQuery.browser = browser;\n\n    jQuery.sub = function () {\n        function jQuerySub(selector, context) {\n            return new jQuerySub.fn.init(selector, context);\n        }\n\n        jQuery.extend(true, jQuerySub, this);\n        jQuerySub.superclass = this;\n        jQuerySub.fn = jQuerySub.prototype = this();\n        jQuerySub.fn.constructor = jQuerySub;\n        jQuerySub.sub = this.sub;\n        jQuerySub.fn.init = function init(selector, context) {\n            if (context && context instanceof jQuery && !(context instanceof jQuerySub)) {\n                context = jQuerySub(context);\n            }\n\n            return jQuery.fn.init.call(this, selector, context, rootjQuerySub);\n        };\n        jQuerySub.fn.init.prototype = jQuerySub.fn;\n        var rootjQuerySub = jQuerySub(document);\n        return jQuerySub;\n    };\n\n})();\n\n/*\n * jQuery stringifyJSON\n * http://github.com/flowersinthesand/jquery-stringifyJSON\n *\n * Copyright 2011, Donghwan Kim\n * Licensed under the Apache License, Version 2.0\n * http://www.apache.org/licenses/LICENSE-2.0\n */\n// This plugin is heavily based on Douglas Crockford's reference implementation\n(function (jQuery) {\n\n    var escapable = /[\\\\\\\"\\x00-\\x1f\\x7f-\\x9f\\u00ad\\u0600-\\u0604\\u070f\\u17b4\\u17b5\\u200c-\\u200f\\u2028-\\u202f\\u2060-\\u206f\\ufeff\\ufff0-\\uffff]/g, meta = {\n        '\\b': '\\\\b',\n        '\\t': '\\\\t',\n        '\\n': '\\\\n',\n        '\\f': '\\\\f',\n        '\\r': '\\\\r',\n        '\"': '\\\\\"',\n        '\\\\': '\\\\\\\\'\n    };\n\n    function quote(string) {\n        return '\"' + string.replace(escapable, function (a) {\n            var c = meta[a];\n            return typeof c === \"string\" ? c : \"\\\\u\" + (\"0000\" + a.charCodeAt(0).toString(16)).slice(-4);\n        }) + '\"';\n    }\n\n    function f(n) {\n        return n < 10 ? \"0\" + n : n;\n    }\n\n    function str(key, holder) {\n        var i, v, len, partial, value = holder[key], type = typeof value;\n\n        if (value && typeof value === \"object\" && typeof value.toJSON === \"function\") {\n            value = value.toJSON(key);\n            type = typeof value;\n        }\n\n        switch (type) {\n            case \"string\":\n                return quote(value);\n            case \"number\":\n                return isFinite(value) ? String(value) : \"null\";\n            case \"boolean\":\n                return String(value);\n            case \"object\":\n                if (!value) {\n                    return \"null\";\n                }\n\n                switch (Object.prototype.toString.call(value)) {\n                    case \"[object Date]\":\n                        return isFinite(value.valueOf()) ? '\"' + value.getUTCFullYear() + \"-\" + f(value.getUTCMonth() + 1) + \"-\" + f(value.getUTCDate())\n                            + \"T\" + f(value.getUTCHours()) + \":\" + f(value.getUTCMinutes()) + \":\" + f(value.getUTCSeconds()) + \"Z\" + '\"' : \"null\";\n                    case \"[object Array]\":\n                        len = value.length;\n                        partial = [];\n                        for (i = 0; i < len; i++) {\n                            partial.push(str(i, value) || \"null\");\n                        }\n\n                        return \"[\" + partial.join(\",\") + \"]\";\n                    default:\n                        partial = [];\n                        for (i in value) {\n                            if (Object.prototype.hasOwnProperty.call(value, i)) {\n                                v = str(i, value);\n                                if (v) {\n                                    partial.push(quote(i) + \":\" + v);\n                                }\n                            }\n                        }\n\n                        return \"{\" + partial.join(\",\") + \"}\";\n                }\n        }\n    }\n\n    jQuery.stringifyJSON = function (value) {\n        if (window.JSON && window.JSON.stringify) {\n            return window.JSON.stringify(value);\n        }\n\n        return str(\"\", {\n            \"\": value\n        });\n    };\n\n}(jQuery));\n/* jshint noarg:true, noempty:true, eqeqeq:true, evil:true, laxbreak:true, undef:true, browser:true, jquery:true, indent:false, maxerr:50, eqnull:true */\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/json3/.bower.json",
    "content": "{\n  \"name\": \"json3\",\n  \"homepage\": \"https://github.com/bestiejs/json3\",\n  \"version\": \"3.2.5\",\n  \"_release\": \"3.2.5\",\n  \"_resolution\": {\n    \"type\": \"version\",\n    \"tag\": \"v3.2.5\",\n    \"commit\": \"2675fe379eadbf9549da340da2c9cde35a0d2ebc\"\n  },\n  \"_source\": \"https://github.com/bestiejs/json3.git\",\n  \"_target\": \"3.2.5\",\n  \"_originalSource\": \"json3\"\n}"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/json3/.gitmodules",
    "content": "[submodule \"vendor/spec\"]\n\tpath = vendor/spec\n\turl = git://github.com/kitcambridge/spec.git\n[submodule \"vendor/marked\"]\n\tpath = vendor/marked\n\turl = git://github.com/chjj/marked.git\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/json3/.jshintrc",
    "content": "{\n  \"bitwise\": false,\n  \"camelcase\": false,\n  \"curly\": false,\n  \"eqeqeq\": false,\n  \"es3\": true,\n  \"forin\": false,\n  \"immed\": false,\n  \"latedef\": false,\n  \"newcap\": false,\n  \"noarg\": true,\n  \"noempty\": false,\n  \"nonew\": false,\n  \"plusplus\": false,\n  \"quotmark\": false,\n  \"undef\": true,\n  \"unused\": false,\n  \"strict\": false,\n  \"trailing\": true,\n\n  \"asi\": false,\n  \"boss\": true,\n  \"debug\": false,\n  \"eqnull\": true,\n  \"esnext\": false,\n  \"evil\": true,\n  \"expr\": true,\n  \"funcscope\": true,\n  \"globalstrict\": false,\n  \"iterator\": true,\n  \"lastsemic\": false,\n  \"laxbreak\": false,\n  \"laxcomma\": false,\n  \"loopfunc\": false,\n  \"moz\": false,\n  \"multistr\": false,\n  \"proto\": true,\n  \"scripturl\": false,\n  \"smarttabs\": false,\n  \"shadow\": true,\n  \"sub\": true,\n  \"supernew\": true,\n  \"validthis\": true,\n  \"onecase\": true,\n  \"regexdash\": true,\n  \"regexp\": true,\n\n  \"browser\": true,\n  \"couch\": false,\n  \"devel\": true,\n  \"dojo\": false,\n  \"jquery\": false,\n  \"mootools\": false,\n  \"node\": true,\n  \"nonstandard\": false,\n  \"prototypejs\": false,\n  \"rhino\": true,\n  \"worker\": false,\n  \"wsh\": true,\n  \"yui\": false,\n\n  \"-W038\": true,\n  \"-W053\": true,\n  \"-W086\": true,\n\n  \"predef\": [\"define\", \"environment\", \"Packages\", \"Benchmark\", \"_\"]\n}"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/json3/.npmignore",
    "content": "build.js\nindex.html\njsl.conf\n\npage\ntest\nvendor"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/json3/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": "flowable-ui-web/admin/bower_components/json3/README.md",
    "content": "# JSON 3 #\n\n![JSON 3 Logo](http://bestiejs.github.io/json3/page/logo.png)\n\n**JSON 3** is a modern JSON implementation compatible with a variety of JavaScript platforms, including Internet Explorer 6, Opera 7, Safari 2, and Netscape 6. The current version is **3.2.5**.\n\n- [Development Version](http://bestiejs.github.io/json3/lib/json3.js) *(38.8 KB; uncompressed with comments)*\n- [Production Version](http://bestiejs.github.io/json3/lib/json3.min.js) *(3.2 KB; compressed and `gzip`-ped)*\n\n[JSON](http://json.org/) is a language-independent data interchange format based on a loose subset of the JavaScript grammar. Originally popularized by [Douglas Crockford](http://www.crockford.com/), the format was standardized in the [fifth edition](http://es5.github.com/) of the ECMAScript specification. The 5.1 edition, ratified in June 2011, incorporates several modifications to the grammar pertaining to the serialization of dates.\n\nJSON 3 exposes two functions: `stringify()` for [serializing](https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/JSON/stringify) a JavaScript value to JSON, and `parse()` for [producing](https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/JSON/parse) a JavaScript value from a JSON source string. It is a **drop-in replacement** for [JSON 2](http://json.org/js). The functions behave exactly as described in the ECMAScript spec, **except** for the date serialization discrepancy noted below.\n\nThe JSON 3 parser does **not** use `eval` or regular expressions. This provides security and performance benefits in obsolete and mobile environments, where the margin is particularly significant. The complete [benchmark suite](http://jsperf.com/json3) is available on [jsPerf](http://jsperf.com/).\n\nThe project is [hosted on GitHub](http://git.io/json3), along with the [unit tests](http://bestiejs.github.io/json3/test/test_browser.html). It is part of the [BestieJS](https://github.com/bestiejs) family, a collection of best-in-class JavaScript libraries that promote cross-platform support, specification precedents, unit testing, and plenty of documentation.\n\n# Changes from JSON 2 #\n\nJSON 3...\n\n* Correctly serializes primitive wrapper objects.\n* Throws a `TypeError` when serializing cyclic structures (JSON 2 recurses until the call stack overflows).\n* Utilizes **feature tests** to detect broken or incomplete *native* JSON implementations (JSON 2 only checks for the presence of the native functions). The tests are only executed once at runtime, so there is no additional performance cost when parsing or serializing values.\n\n**As of v3.2.3**, JSON 3 is compatible with [Prototype](http://prototypejs.org) 1.6.1 and older.\n\nIn contrast to JSON 2, JSON 3 **does not**...\n\n* Add `toJSON()` methods to the `Boolean`, `Number`, and `String` prototypes. These are not part of any standard, and are made redundant by the design of the `stringify()` implementation.\n* Add `toJSON()` or `toISOString()` methods to `Date.prototype`. See the note about date serialization below.\n\n## Date Serialization\n\n**JSON 3 deviates from the specification in one important way**: it does not define `Date#toISOString()` or `Date#toJSON()`. This preserves CommonJS compatibility and avoids polluting native prototypes. Instead, date serialization is performed internally by the `stringify()` implementation: if a date object does not define a custom `toJSON()` method, it is serialized as a [simplified ISO 8601 date-time string](http://es5.github.com/#x15.9.1.15).\n\n**Several native `Date#toJSON()` implementations produce date time strings that do *not* conform to the grammar outlined in the spec**. For instance, all versions of Safari 4, as well as JSON 2, fail to serialize extended years correctly. Furthermore, JSON 2 and older implementations omit the milliseconds from the date-time string (optional in ES 5, but required in 5.1). Finally, in all versions of Safari 4 and 5, serializing an invalid date will produce the string `\"Invalid Date\"`, rather than `null`. Because these environments exhibit other serialization bugs, however, JSON 3 will override the native `stringify()` implementation.\n\nPortions of the date serialization code are adapted from the [`date-shim`](https://github.com/Yaffle/date-shim) project.\n\n# Usage #\n\n## Web Browsers\n\n    <script src=\"http://bestiejs.github.io/json3/lib/json3.js\"></script>\n    <script>\n      JSON.stringify({\"Hello\": 123});\n      // => '{\"Hello\":123}'\n      JSON.parse(\"[[1, 2, 3], 1, 2, 3, 4]\", function (key, value) {\n        if (typeof value == \"number\") {\n          value = value % 2 ? \"Odd\" : \"Even\";\n        }\n        return value;\n      });\n      // => [[\"Odd\", \"Even\", \"Odd\"], \"Odd\", \"Even\", \"Odd\", \"Even\"]\n    </script>\n\n## CommonJS Environments\n\n    var JSON3 = require(\"./path/to/json3\");\n    JSON3.parse(\"[1, 2, 3]\");\n    // => [1, 2, 3]\n\n## JavaScript Engines\n\n    load(\"path/to/json3.js\");\n    JSON.stringify({\"Hello\": 123, \"Good-bye\": 456}, [\"Hello\"], \"\\t\");\n    // => '{\\n\\t\"Hello\": 123\\n}'\n\n# Compatibility #\n\nJSON 3 has been **tested** with the following web browsers, CommonJS environments, and JavaScript engines.\n\n## Web Browsers\n\n- Windows [Internet Explorer](http://www.microsoft.com/windows/internet-explorer), version 6.0 and higher\n- Mozilla [Firefox](http://www.mozilla.com/firefox), version 1.0 and higher\n- Apple [Safari](http://www.apple.com/safari), version 2.0 and higher\n- [Opera](http://www.opera.com) 7.02 and higher\n- [Mozilla](http://sillydog.org/narchive/gecko.php) 1.0, [Netscape](http://sillydog.org/narchive/) 6.2.3, and [SeaMonkey](http://www.seamonkey-project.org/) 1.0 and higher\n\n## CommonJS Environments\n\n- [Node](http://nodejs.org/) 0.2.6 and higher\n- [RingoJS](http://ringojs.org/) 0.4 and higher\n- [Narwhal](http://narwhaljs.org/) 0.3.2 and higher\n\n## JavaScript Engines\n\n- Mozilla [Rhino](http://www.mozilla.org/rhino) 1.5R5 and higher\n- WebKit [JSC](https://trac.webkit.org/wiki/JSC)\n- Google [V8](http://code.google.com/p/v8)\n\n## Known Incompatibilities\n\n* Attempting to serialize the `arguments` object may produce inconsistent results across environments due to specification version differences. As a workaround, please convert the `arguments` object to an array first: `JSON.stringify([].slice.call(arguments, 0))`.\n\n## Required Native Methods\n\nJSON 3 assumes that the following methods exist and function as described in the ECMAScript specification:\n\n- The `Number`, `String`, `Array`, `Object`, `Date`, `SyntaxError`, and `TypeError` constructors.\n- `String.fromCharCode`\n- `Object#toString`\n- `Function#call`\n- `Math.floor`\n- `Number#toString`\n- `Date#valueOf`\n- `String.prototype`: `indexOf`, `charCodeAt`, `charAt`, `slice`.\n- `Array.prototype`: `push`, `pop`, `join`.\n\n# Contribute #\n\nCheck out a working copy of the JSON 3 source code with [Git](http://git-scm.com/):\n\n    $ git clone git://github.com/bestiejs/json3.git\n    $ cd json3\n    $ git submodule update --init\n\nIf you'd like to contribute a feature or bug fix, you can [fork](http://help.github.com/fork-a-repo/) JSON 3, commit your changes, and [send a pull request](http://help.github.com/send-pull-requests/). Please make sure to update the unit tests in the `test` directory as well.\n\nAlternatively, you can use the [GitHub issue tracker](https://github.com/bestiejs/json3/issues) to submit bug reports, feature requests, and questions, or send tweets to [@kitcambridge](http://twitter.com/kitcambridge).\n\nJSON 3 is released under the [MIT License](http://kit.mit-license.org/)."
  },
  {
    "path": "flowable-ui-web/admin/bower_components/json3/benchmark/assets/html5.js",
    "content": "/*!\n * HTML5.js v1.0.0-rc\n * Copyright 2012 John-David Dalton <http://allyoucanleet.com/>\n * Based on HTML5 Shiv vpre3.3 | @afarkas @jon_neal @rem | MIT/GPL2 Licensed\n * Available under MIT/GPL2 license\n */\n;(function(window, document) {\n  'use strict';\n\n  /** Preset for the install/uninstall methods */\n  var allOptions = { 'methods': true, 'print': true, 'styles': true };\n\n  /** Cache of created elements, document methods, and install state */\n  var html5Cache = {};\n\n  /** Previous `html5` object */\n  var old = window.html5;\n\n  /** List of HTML5 node names to install support for */\n  var nodeNames = [\n    'abbr', 'article', 'aside', 'audio', 'bdi', 'canvas', 'data', 'datalist',\n    'details', 'figcaption', 'figure', 'footer', 'header', 'main',\n    'mark', 'meter', 'nav', 'output', 'progress', 'section', 'summary', 'time',\n    'video'\n  ];\n\n  /** Used to namespace printable elements and define `expando` */\n  var namespace = 'html5js';\n\n  /** Used to store an elements `uid` if `element.uniqueNumber` is not supported */\n  var expando = namespace + /\\d+$/.exec(Math.random());\n\n  /** Used to filter media types */\n  var reMedia = /^$|\\b(?:all|print)\\b/;\n\n  /**\n   * Used to skip elements with type attributes because in IE they cannot be\n   * set/changed once an element is inserted into a document/fragment.\n   * http://msdn.microsoft.com/en-us/library/ie/ms534700(v=vs.85).aspx\n   */\n  var reSkip = /^(?:button|select)$/i;\n\n  /** Used to detect elements that cannot be cloned correctly */\n  var reUnclonable = /^<\\?/;\n\n  /** Used as a fallback for `element.uniqueNumber` */\n  var uid = 1;\n\n  /** Cache of unclonable element node names */\n  var unclonables = {};\n\n  /**\n   * An object used to flag features.\n   *\n   * @static\n   * @memberOf html5\n   * @type Object\n   */\n  var support = {};\n\n  (function() {\n    var p,\n        parent,\n        sandbox;\n\n    // create a new document used to get untainted styles\n    try {\n      // avoid https: protocol issues with IE\n      sandbox = new ActiveXObject(location.protocol == 'https:' && 'htmlfile');\n    } catch(e) {\n      // http://xkr.us/articles/dom/iframe-document/\n      (sandbox = document.createElement('iframe')).name = expando;\n      sandbox.frameBorder = sandbox.height = sandbox.width = 0;\n      parent = document.body || document.documentElement;\n      parent.insertBefore(sandbox, parent.firstChild);\n      sandbox = (sandbox = sandbox.contentWindow || sandbox.contentDocument || frames[expando]).document || sandbox;\n    }\n    sandbox.write('<!doctype html><title></title><body><script>document.w = this<\\/script>');\n    sandbox.close();\n\n    p = sandbox.body.appendChild(sandbox.createElement('p'));\n    p.innerHTML = '<nav/>';\n\n    /**\n     * Detect whether the browser supports default HTML5 styles.\n     * @memberOf html5.support\n     * @type Boolean\n     */\n    support.html5Styles = !!p.firstChild &&\n      (p.firstChild.currentStyle || sandbox.w.getComputedStyle(p.firstChild, null)).display == 'block';\n\n    /**\n     * Detect whether the browser supports unknown elements.\n     *\n     * @memberOf html5.support\n     * @type Boolean\n     */\n    support.unknownElements = p.childNodes.length == 1 || (function() {\n      // assign a false positive if unable to install\n      try {\n        (document.createElement)('p');\n      } catch(e) {\n        return true;\n      }\n      var frag = document.createDocumentFragment();\n      return (\n        typeof frag.createElement == 'undefined' ||\n        typeof p.uniqueNumber == 'undefined'\n      );\n    }());\n\n    /**\n     * Detect whether the browser supports printing html5 elements.\n     *\n     * @memberOf html5.support\n     * @type Boolean\n     */\n    support.html5Printing = support.unknownElements || (\n      // assign a false positive if unable to install\n      typeof document.namespaces == 'undefined' ||\n      typeof document.parentWindow == 'undefined' ||\n      typeof p.applyElement == 'undefined' ||\n      typeof p.removeNode == 'undefined' ||\n      typeof window.attachEvent == 'undefined'\n    );\n\n    parent && destroyElement(sandbox.w.frameElement);\n  }());\n\n  /*--------------------------------------------------------------------------*/\n\n  /**\n   * Creates a style sheet of modified CSS rules to style the print wrappers.\n   * (e.g. the CSS rule \"header{}\" becomes \"html5js\\:header{}\")\n   *\n   * @private\n   * @param {Document} ownerDocument The document.\n   * @param {String} cssText The CSS text.\n   * @returns {StyleSheet} The style element.\n   */\n  function addPrintSheet(ownerDocument, cssText) {\n    var pair,\n        parts = cssText.split('{'),\n        index = parts.length,\n        reElements = RegExp('(^|[\\\\s,>+~])(' + nodeNames.join('|') + ')(?=[[\\\\s,>+~#.:]|$)', 'gi'),\n        replacement = '$1' + namespace + '\\\\:$2';\n\n    while (index--) {\n      pair = parts[index] = parts[index].split('}');\n      pair[pair.length - 1] = pair[pair.length - 1].replace(reElements, replacement);\n      parts[index] = pair.join('}');\n    }\n    return addStyleSheet(ownerDocument, parts.join('{'));\n  }\n\n  /**\n   * Wraps all HTML5 elements in the given document with printable elements.\n   * (e.g. the \"header\" element is wrapped with the \"html5js:header\" element)\n   *\n   * @private\n   * @param {Document} ownerDocument The document.\n   * @returns {Array} An array of added wrappers.\n   */\n  function addPrintWrappers(ownerDocument) {\n    var node,\n        nodes = ownerDocument.getElementsByTagName('*'),\n        index = nodes.length,\n        reElements = RegExp('^(?:' + nodeNames.join('|') + ')$', 'i'),\n        result = [];\n\n    while (index--) {\n      node = nodes[index];\n      if (reElements.test(node.nodeName)) {\n        result.push(node.applyElement(createPrintWrapper(node)));\n      }\n    }\n    return result;\n  }\n\n  /**\n   * Creates a style sheet with the given CSS text and adds it to the document.\n   *\n   * @private\n   * @param {Document} ownerDocument The document.\n   * @param {String} cssText The CSS text.\n   * @returns {StyleSheet} The style sheet.\n   */\n  function addStyleSheet(ownerDocument, cssText) {\n    // IE8 only respects namespace prefixs when created with `innerHTML`\n    var p = ownerDocument.createElement('p'),\n        parent = ownerDocument.getElementsByTagName('head')[0] || ownerDocument.documentElement;\n\n    p.innerHTML = 'x<style>' + cssText + '</style>';\n    return parent.insertBefore(p.lastChild, parent.firstChild);\n  }\n\n  /**\n   * Creates HTML5 elements using the given document enabling the document to\n   * parse them correctly.\n   *\n   * @private\n   * @param {Document|Fragment} ownerDocument The document.\n   * @returns {Document|Fragment} The document.\n   */\n  function createElements(ownerDocument) {\n    var index = nodeNames.length,\n        create = ownerDocument.createElement;\n\n    while (index--) {\n      create(nodeNames[index]);\n    }\n    return ownerDocument;\n  }\n\n  /**\n   * Creates a printable wrapper for the given element.\n   *\n   * @private\n   * @param {Element} element The element.\n   * @returns {Element} The wrapper.\n   */\n  function createPrintWrapper(element) {\n    var node,\n        nodes = element.attributes,\n        index = nodes.length,\n        wrapper = element.ownerDocument.createElement(namespace + ':' + element.nodeName);\n\n    // copy element attributes to the wrapper\n    while (index--) {\n      node = nodes[index];\n      node.specified && wrapper.setAttribute(node.nodeName, node.nodeValue);\n    }\n    // copy element styles to the wrapper\n    wrapper.style.cssText = element.style.cssText;\n    return wrapper;\n  }\n\n  /**\n   * Destroys the given element.\n   *\n   * @private\n   * @param {Element} element The element to destroy.\n   * @param {Object} [cache] The cache object.\n   */\n  function destroyElement(element, cache) {\n    var trash = (cache || getCache(element.ownerDocument)).trash;\n    trash.appendChild(element);\n    trash.innerHTML = '';\n  }\n\n  /**\n   * Gets the cache object for the given document.\n   *\n   * @private\n   * @param {Document} ownerDocument The document.\n   * @returns {Object} The cache object.\n   */\n  function getCache(ownerDocument) {\n    var docEl = ownerDocument.documentElement,\n        id = docEl.uniqueNumber || docEl[expando] || (docEl[expando] = uid++),\n        skip = support.unknownElements;\n\n    return html5Cache[id] || (html5Cache[id] = {\n      'frag': !skip && createElements(ownerDocument.createDocumentFragment()),\n      'nativeCreateElement': !skip && createElements(ownerDocument).createElement,\n      'nativeCreateFragment': !skip && ownerDocument.createDocumentFragment,\n      'nodes': {},\n      'trash': ownerDocument.createElement('div')\n    });\n  }\n\n  /**\n   * Removes the given print wrappers, leaving the original elements.\n   *\n   * @private\n   * @param {Document} ownerDocument The document.\n   * @params {Array} wrappers An array of wrappers.\n   */\n  function removePrintWrappers(ownerDocument, wrappers) {\n    var cache = getCache(ownerDocument),\n        index = wrappers.length;\n\n    while (index--) {\n      destroyElement(wrappers[index].removeNode(), cache);\n    }\n  }\n\n  /**\n   * Resolves an options object from the given value.\n   *\n   * @private\n   * @param {Mixed} value The value to convert to an options object.\n   * @returns {Object} The options object.\n   */\n  function resolveOptions(value) {\n    var key;\n    value = value ? (value === 'all' || value.all ? allOptions : value) : {};\n\n    if (typeof value == 'string') {\n      var object = {};\n      value = value.split(/[, ]+/);\n      while ((key = value.pop())) {\n        object[key] = true;\n      }\n      value = object;\n    }\n    return value;\n  }\n\n  /**\n   * Overwrites the document's `createElement` and `createDocumentFragment` methods\n   * with `html5.createElement` and `html5.createDocumentFragment` equivalents.\n   *\n   * @private\n   * @param {Document} ownerDocument The document.\n   */\n  function setMethods(ownerDocument) {\n    var cache = getCache(ownerDocument),\n        create = cache.nativeCreateElement,\n        frag = cache.frag,\n        nodes = cache.nodes;\n\n    // allow a small amount of repeated code for better performance\n    ownerDocument.createElement = function(nodeName) {\n      var cached = nodes[nodeName],\n          node = cached ? cached.cloneNode() : create(nodeName);\n\n      if (!cached && !unclonables[nodeName] &&\n          !(unclonables[nodeName] = reUnclonable.test(node.outerHTML))) {\n        node = (nodes[nodeName] = node).cloneNode();\n      }\n      return node.canHaveChildren && !reSkip.test(nodeName) ? frag.appendChild(node) : node;\n    };\n\n    // compile unrolled `createElement` calls for better performance\n    ownerDocument.createDocumentFragment = Function('frag',\n      'return function() {\\n' +\n      '  var node = frag.cloneNode(), create = node.createElement;\\n' +\n      (nodeNames + '').replace(/\\w+/g, 'create(\"$&\")\\n') + ';\\n' +\n      '  return node\\n' +\n      '}'\n    )(frag);\n  }\n\n  /**\n   * Adds support for printing HTML5 elements.\n   *\n   * @private\n   * @param {Document} ownerDocument The document.\n   */\n  function setPrintSupport(ownerDocument) {\n    var printSheet,\n        wrappers,\n        cache = getCache(ownerDocument),\n        namespaces = ownerDocument.namespaces,\n        ownerWindow = ownerDocument.parentWindow;\n\n    ownerWindow.attachEvent('onbeforeprint', cache.onbeforeprint = function() {\n      var imports,\n          length,\n          sheet,\n          collection = ownerDocument.styleSheets,\n          cssText = [],\n          index = collection.length,\n          sheets = [];\n\n      // convert styleSheets collection to an array\n      while (index--) {\n        sheets[index] = collection[index];\n      }\n      // concat all style sheet CSS text\n      while ((sheet = sheets.pop())) {\n        // IE does not enforce a same origin policy for external style sheets...\n        if (!sheet.disabled && reMedia.test(sheet.media)) {\n          // ...but will throw an \"access denied\" error when attempting to read\n          // the CSS text of a style sheet added by a script from a different origin.\n          try {\n            cssText.push(sheet.cssText);\n            for (imports = sheet.imports, index = 0, length = imports.length; index < length; index++) {\n              sheets.push(imports[index]);\n            }\n          } catch(e) { }\n        }\n      }\n      // wrap all HTML5 elements with printable elements and add print style sheet\n      wrappers = addPrintWrappers(ownerDocument);\n      printSheet = addPrintSheet(ownerDocument, cssText.reverse().join(''));\n    });\n\n    ownerWindow.attachEvent('onafterprint', cache.onafterprint = function() {\n      // remove wrappers, leaving the original elements, and remove print style sheet\n      removePrintWrappers(ownerDocument, wrappers);\n      destroyElement(printSheet, cache);\n    });\n\n    if (typeof namespaces[namespace] == 'undefined') {\n      namespaces.add(namespace);\n    }\n  }\n\n  /**\n   * Adds minimal default HTML5 element styles to the given document.\n   *\n   * @private\n   * @param {Document} ownerDocument The document.\n   * @param {Object} options Options object.\n   */\n  function setStyles(ownerDocument, options) {\n    // for additional default and normalized HTML5 element styles checkout\n    // https://github.com/necolas/normalize.css\n    getCache(ownerDocument).sheet = addStyleSheet(ownerDocument,\n      // corrects block display not defined in IE6/7/8/9 and Firefox 3\n      'article, aside, figcaption, figure, footer, header, main, nav, section {' +\n      '  display: block' +\n      '}' +\n      // adds styling not present in IE6/7/8/9\n      'mark {' +\n      '  background: #ff0;' +\n      '  color: #000' +\n      '}'\n    );\n  }\n\n  /**\n   * Restores the document's original `createElement` and `createDocumentFragment` methods.\n   *\n   * @private\n   * @param {Document} ownerDocument The document.\n   */\n  function unsetMethods(ownerDocument) {\n    var cache = getCache(ownerDocument),\n        fn = cache.nativeCreateElement;\n\n    if (ownerDocument.createElement != fn) {\n      ownerDocument.createElement = fn;\n    }\n    if (ownerDocument.createDocumentFragment != (fn = cache.nativeCreateFragment)) {\n      ownerDocument.createDocumentFragment = fn;\n    }\n  }\n\n  /**\n   * Removes support for printing HTML5 elements.\n   *\n   * @private\n   * @param {Document} ownerDocument The document.\n   */\n  function unsetPrintSupport(ownerDocument) {\n    var cache = getCache(ownerDocument),\n        ownerWindow = ownerDocument.parentWindow;\n\n    ownerWindow.detachEvent('onbeforeprint', cache.onbeforeprint || unsetPrintSupport);\n    ownerWindow.detachEvent('onafterprint', cache.onafterprint || unsetPrintSupport);\n  }\n\n  /**\n   * Removes default HTML5 element styles.\n   *\n   * @private\n   * @param {Document} ownerDocument The document.\n   * @param {Object} options Options object.\n   */\n  function unsetStyles(ownerDocument, options) {\n    var cache = getCache(ownerDocument),\n        sheet = cache.sheet;\n\n    if (sheet) {\n      cache.sheet = null;\n      destroyElement(sheet, cache);\n    }\n  }\n\n  /*--------------------------------------------------------------------------*/\n\n  /**\n   * Creates a shimmed element of the given node name.\n   *\n   * @memberOf html5\n   * @param {Document} [ownerDocument=document] The context document.\n   * @param {String} nodeName The node name of the element to create.\n   * @returns {Element} The created element.\n   * @example\n   *\n   * // basic usage\n   * html5.createElement('div');\n   *\n   * // from a child iframe\n   * parent.html5.createElement(document, 'div');\n   */\n  function createElement(ownerDocument, nodeName) {\n    // juggle arguments\n    ownerDocument || (ownerDocument = document);\n    if (ownerDocument && !ownerDocument.nodeType) {\n      nodeName = ownerDocument;\n      ownerDocument = document;\n    }\n    if (support.unknownElements) {\n      return ownerDocument.createElement(nodeName);\n    }\n    // Avoid adding some elements to fragments in IE because\n    // * attributes like `type` cannot be set/changed once an element is inserted\n    //   into a document/fragment\n    // * link elements with `src` attributes that are inaccessible, as with\n    //   a 403 response, will cause the tab/window to crash\n    // * script elements appended to fragments will execute when their `src`\n    //   or `text` property is set\n    var cache = getCache(ownerDocument),\n        nodes = cache.nodes,\n        cached = nodes[nodeName],\n        node = cached ? cached.cloneNode() : cache.nativeCreateElement(nodeName);\n\n    // IE < 9 doesn't clone unknown elements correctly\n    if (!cached && !unclonables[nodeName] &&\n        !(unclonables[nodeName] = reUnclonable.test(node.outerHTML))) {\n      node = (nodes[nodeName] = node).cloneNode();\n    }\n    return node.canHaveChildren && !reSkip.test(nodeName) ? cache.frag.appendChild(node) : node;\n  }\n\n  /**\n   * Creates a shimmed document fragment.\n   *\n   * @memberOf html5\n   * @param {Document} [ownerDocument=document] The context document.\n   * @returns {Fragment} The created document fragment.\n   * @example\n   *\n   * // basic usage\n   * html5.createDocumentFragment();\n   *\n   * // from a child iframe\n   * parent.html5.createDocumentFragment(document);\n   */\n  function createDocumentFragment(ownerDocument) {\n    ownerDocument || (ownerDocument = document);\n    return support.unknownElements\n      ? ownerDocument.createDocumentFragment()\n      : createElements(getCache(ownerDocument).frag.cloneNode());\n  }\n\n  /**\n   * Installs shims according to the specified options.\n   *\n   * @memberOf html5\n   * @param {Document} [ownerDocument=document] The document.\n   * @param {Object} [options={}] Options object.\n   * @returns {Document} The document.\n   * @example\n   *\n   * // basic usage\n   * // autmatically called on the primary document to allow IE < 9 to\n   * // parse HTML5 elements correctly\n   * html5.install();\n   *\n   * // from a child iframe\n   * parent.html5.install(document);\n   *\n   * // with an options object\n   * html5.install({\n   *\n   *   // overwrite the document's `createElement` and `createDocumentFragment`\n   *   // methods with `html5.createElement` and `html5.createDocumentFragment` equivalents.\n   *   'methods': true,\n   *\n   *   // add support for printing HTML5 elements\n   *   'print': true,\n   *\n   *   // add minimal default HTML5 element styles\n   *   'styles': true\n   * });\n   *\n   * // with an options string\n   * html5.install('print styles');\n   *\n   * // from a child iframe with options\n   * parent.html5.install(document, options);\n   *\n   * // using a shortcut to install all support extensions\n   * html5.install('all');\n   */\n  function install(ownerDocument, options) {\n    ownerDocument || (ownerDocument = document);\n    if (ownerDocument && !ownerDocument.nodeType) {\n      options = ownerDocument;\n      ownerDocument = document;\n    }\n\n    options = resolveOptions(options);\n    uninstall(ownerDocument, {\n      'methods': options.methods,\n      'print': options.print,\n      'styles': options.styles\n    });\n\n    if (!support.html5Styles && options.styles) {\n      setStyles(ownerDocument, options);\n    }\n    if (!support.html5Printing && options.print) {\n      setPrintSupport(ownerDocument);\n    }\n    if (!support.unknownElements) {\n      // if not installing methods then init cache and install support\n      // for basic HTML5 element parsing\n      options.methods ? setMethods(ownerDocument) : getCache(ownerDocument);\n    }\n    return ownerDocument;\n  }\n\n  /**\n   * Restores a previously overwritten `html5` object.\n   * @memberOf html5\n   * @returns {Object} The current `html5` object.\n   */\n  function noConflict() {\n    window.html5 = old;\n    return this;\n  }\n\n  /**\n   * Uninstalls shims according to the specified options.\n   *\n   * @memberOf html5\n   * @param {Document} [ownerDocument=document] The document.\n   * @param {Object} [options={}] Options object.\n   * @returns {Document} The document.\n   * @example\n   *\n   * // basic usage with an options object\n   * html5.uninstall({\n   *\n   *   // restore the document's original `createElement`\n   *   // and `createDocumentFragment` methods.\n   *   'methods': true,\n   *\n   *   // remove support for printing HTML5 elements\n   *   'print': true,\n   *\n   *   // remove minimal default HTML5 element styles\n   *   'styles': true\n   * });\n   *\n   * // with an options string\n   * html5.uninstall('print styles');\n   *\n   * // from a child iframe with options\n   * parent.html5.uninstall(document, options);\n   *\n   * // using a shortcut to uninstall all support extensions\n   * html5.uninstall('all');\n   */\n  function uninstall(ownerDocument, options) {\n    ownerDocument || (ownerDocument = document);\n    if (ownerDocument && !ownerDocument.nodeType) {\n      options = ownerDocument;\n      ownerDocument = document;\n    }\n    options = resolveOptions(options);\n    if (!support.unknownElements && options.methods) {\n      unsetMethods(ownerDocument);\n    }\n    if (!support.html5Printing && options.print) {\n      unsetPrintSupport(ownerDocument);\n    }\n    if (!support.html5Styles && options.styles) {\n      unsetStyles(ownerDocument, options);\n    }\n    return ownerDocument;\n  }\n\n  /*--------------------------------------------------------------------------*/\n\n  /**\n   * The `html5` object.\n   * @type Object\n   */\n  var html5 = {\n\n    /**\n     * The semantic version number.\n     * @static\n     * @memberOf html5\n     * @type String\n     */\n    'version': '1.0.0-rc',\n\n    // an object of feature detection flags\n    'support': support,\n\n    // creates shimmed document fragments\n    'createDocumentFragment': createDocumentFragment,\n\n    // creates shimmed elements\n    'createElement': createElement,\n\n    // installs support extensions\n    'install': install,\n\n    // avoid `html5` object conflicts\n    'noConflict': noConflict,\n\n    // uninstalls support extensions\n    'uninstall': uninstall\n  };\n\n  /*--------------------------------------------------------------------------*/\n\n  // Expose the `html5` object to the global object even when an AMD loader is\n  // present in case html5.js was injected by a third-party script and not\n  // intended to be loaded as a module. The global assignment can be reverted in\n  // the `html5` module via its `noConflict()` method.\n  window.html5 = html5;\n\n  // some AMD build optimizers, like r.js, check for specific condition patterns like the following:\n  if (typeof define == 'function' && typeof define.amd == 'object' && define.amd) {\n    // define as an anonymous module so, through path mapping, it can be aliased\n    define(function() {\n      return html5;\n    });\n  }\n}(this, document));"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/json3/benchmark/assets/jsperf.css",
    "content": "html, body, h1, h2, h3, fieldset, #faq, #faq dt, #faq dd {\n  margin: 0;\n  padding: 0;\n  border: 0;\n}\n\ntable, p, ul, h1, h2, h3, #error-info, form div, #faq, .bs-rt {\n  margin-bottom: 1em;\n}\n\nbutton, input, textarea, a, .bs-rt {\n  -moz-border-radius: 4px;\n  -webkit-border-radius: 4px;\n  border-radius: 4px;\n}\n\nhtml, input, textarea, button {\n  font: 1em/1.5 sans-serif;\n}\n\nhtml {\n  background: #c4c4c4;\n  height: 100%;\n}\n\nbody {\n  background: #fff;\n  border: solid #aaa;\n  border-width: 0 1px;\n  width: 60em;\n  padding: 0 2.5em;\n  margin: 0 auto;\n  min-height: 100%;\n}\n\na {\n  color: #357ab0;\n  padding: .2em;\n}\n\na:hover, a:focus {\n  text-decoration: none;\n}\n\nblockquote {\n  margin: 0 0 1em;\n  border-left: 5px solid #b4b4b4;\n  padding-left: .5em;\n}\n\ntable {\n  width: 100%;\n  border-collapse: collapse;\n}\n\nthead th, button:hover, button:focus, .submit:hover, .submit:focus, a:hover, a:focus, #comments .meta a:hover, #comments .meta a:focus, li.current a:hover, li.current a:focus, form h3, #comments .owner .meta {\n  background: #1a6ab9;\n  background-image: -moz-linear-gradient(top, #6ca5dd, #1a6ab9);\n  background-image: -o-linear-gradient(top, #6ca5dd, #1a6ab9);\n  background-image: -webkit-gradient(linear, left top, left bottom, from(#6ca5dd), to(#1a6ab9));\n  background-image: -webkit-linear-gradient(#6ca5dd, #1a6ab9);\n  background-image: linear-gradient(top, #6ca5dd, #1a6ab9);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorStr='#6ca5dd', EndColorStr='#1a6ab9');\n  color: #fff;\n}\n\ncaption, #comments .meta {\n  background: #bcbcbc;\n  background-image: -moz-linear-gradient(top, #d0d0d0, #a7a7a7);\n  background-image: -o-linear-gradient(top, #d0d0d0, #a7a7a7);\n  background-image: -webkit-gradient(linear, left top, left bottom, from(#d0d0d0), to(#a7a7a7));\n  background-image: -webkit-linear-gradient(#d0d0d0, #a7a7a7);\n  background-image: linear-gradient(top, #d0d0d0, #a7a7a7);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorStr='#d0d0d0', EndColorStr='#a7a7a7');\n  color: #555;\n}\n\nthead th, caption {\n  font-weight: bold;\n}\n\n.js tbody th:hover, .js tbody th:focus {\n  text-decoration: underline;\n  cursor: pointer;\n}\n\ntbody th, td {\n  border: solid #b4b4b4;\n  border-width: 0 1px 1px 0;\n}\n\ntbody th {\n  background: #dde4ea;\n  min-width: 100px;\n}\n\ntbody th div {\n  max-width: 200px;\n  word-wrap: break-word;\n  overflow: auto;\n}\n\ntd.results {\n  text-align: center;\n  border-right: 0;\n}\n\n.results span, small {\n  display: block;\n  font-size: .8em;\n}\n\ntd, th, caption {\n  padding: .2em .5em;\n}\n\ntd.fastest {\n  background: #9cee82;\n}\n\ntr:last-child td, tr:last-child th {\n  border-bottom: 0;\n}\n\ntd.slowest, td.error, .invalid {\n  background: pink;\n}\n\n/* needs its own rule because of buggy IE */\n:focus:invalid {\n  background: pink;\n}\n\ntd.error {\n  text-transform: uppercase;\n  font-weight: bold;\n}\n\nbutton, .submit {\n  padding: .35em .5em;\n  cursor: pointer;\n  color: #000;\n  border: 1px solid #999;\n  background: #dadada;\n  background-image: -moz-linear-gradient(top, #ebebeb, #b8b8b8);\n  background-image: -o-linear-gradient(top, #ebebeb, #b8b8b8);\n  background-image: -webkit-gradient(linear, left top, left bottom, from(#ebebeb), to(#b8b8b8));\n  background-image: -webkit-linear-gradient(top, #ebebeb, #b8b8b8);\n  background-image: linear-gradient(top, #ebebeb, #b8b8b8);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorStr='#ebebeb', EndColorStr='#b8b8b8');\n}\n\na:hover span, a:focus span, #comments .owner .meta a {\n  color: #fff;\n}\n\n#controls, #run, .buttons {\n  float: right;\n}\n\nbutton:hover, button:focus, .submit:hover, .submit:focus {\n  border-color: #357ab0\n}\n\n#add-buttons button {\n  padding: .15em .4em;\n  font-size: 11px;\n  font-weight: bold;\n}\n\nform label {\n  float: left;\n  width: 14em;\n  cursor: pointer;\n  text-align: right;\n  margin-right: 1em;\n  padding: .4em;\n}\n\nlabel.inline {\n  float: none;\n  padding: 0;\n  margin: 0;\n}\n\nlabel[for=\"visible\"], label[for$=\"][defer]\"] {\n  position: relative;\n  top: -.37em;\n}\n\nlabel span {\n  display: block;\n  font-size: 90%;\n  color: #b4b4b4;\n}\n\nlabel em {\n  color: red;\n  font-style: normal;\n}\n\n.js #advanced {\n  display: none;\n}\n\n#show-advanced {\n  display: none;\n}\n\n.js #show-advanced {\n  display: block;\n}\n\nsection {\n  display: block;\n  border-top: 1px solid #ccc;\n  padding-top: 2em;\n  margin: 2em 0;\n}\n\ntextarea {\n  resize: vertical;\n  height: 15em;\n  width: 42.6em;\n}\n\n.ie textarea {\n  width: 42.4em; /* IE < 8 */\n}\n\ninput, textarea {\n  border: 1px solid #b4b4b4;\n  padding: .4em;\n}\n\n#visible, #calibrate { /* checkboxes, for IE */\n  border: 0;\n  padding: 0;\n}\n\nform h2, form h3, form h4, p.error, .preview, #add-libraries, #add-buttons {\n  padding-left: 250px;\n  display: block;\n}\n\n.js .question, hgroup h2, #controls, #firebug, #java {\n  display: none;\n}\n\npre {\n  width: 100%;\n  overflow: auto;\n}\n\ntable #results-1 {\n  width: 100px;\n}\n\n.ie table pre {\n  padding: 1.5em 0; /* IE < 8 */\n  overflow-y: hidden; /* IE < 8 */\n}\n\ntable pre, table td.code {\n  width: 650px;\n}\n\nmark {\n  background: #ff9;\n  padding: .2em .1em;\n}\n\nh1, h2, h3, h4 {\n  font-weight: bold;\n  font-size: 1em;\n}\n\nh1 {\n  padding-top: 1em;\n  font-size: 1.4em;\n}\n\nform h3 {\n  padding-top: .2em;\n  padding-bottom: .2em;\n}\n\nh1 em {\n  font-style: normal;\n}\n\nh1 strong {\n  font-style: italic;\n  font-family: Monaco, 'Lucida Console', monospace;\n}\n\nli.current a {\n  background: #90ee85;\n}\n\n#donate {\n  display: block;\n  background: #ffffdc;\n  border: 1px solid #faa700;\n  padding: 1em;\n}\n\n#donate h1 {\n  padding-top: 0;\n  font-size: 16px;\n}\n\n#paypal {\n  text-align: center;\n}\n\nfooter {\n  display: block;\n  margin-top: 2em;\n  padding: .5em 0 1.5em;\n  border-top: 2px solid #c4c4c4;\n}\n\n#add-test {\n  margin-right: .3em;\n}\n\n#bs-chart {\n  overflow: auto;\n}\n\n#bs-logo {\n  margin: 0;\n}\n\n#bs-logo span, applet {\n  position: absolute;\n  left: -9999em;\n}\n\n#bs-logo a {\n  display: block;\n  width: 232px;\n  height: 39px;\n  filter: none;\n  background: url(//www.browserscope.org/static/img/logo.png) 0 0 no-repeat;\n}\n\n#bs-ua {\n  padding: .5em .5em 0;\n  color: #555;\n}\n\n#bs-results .bs-rt {\n  font-size: 10pt;\n  padding: .5em;\n  background: #ddd;\n}\n\n#bs-results td {\n  border: 1px solid #ddd;\n  padding: .4em;\n  white-space: nowrap;\n}\n\n#bs-results .rt-ua-cur {\n  font-style: italic;\n  font-weight: bold;\n}\n\n#bs-results .bs-rt-message {\n  padding: 3em;\n  text-align: center;\n  font-weight: bold;\n  color: #555;\n}\n\n#bs-results .google-visualization-table-tr-head td {\n  white-space: normal;\n}\n\n#controls {\n  margin-top: -3.35em;\n}\n\n#comments h1 {\n  padding: 0;\n}\n\n#comments .meta img {\n  position: absolute;\n  left: 0;\n  top: 0;\n  margin: 0;\n}\n\n#comments .meta img {\n  top: 2px;\n  left: 2px;\n}\n\n#comments .meta {\n  padding-left: 35px;\n  margin-top: 0;\n  width: 923px;\n  line-height: 30px;\n}\n\n#comments .meta a {\n  font-weight: bold;\n  color: #555;\n}\n\n#comments article div {\n  padding: 0 1em 0;\n}\n\n#comments article {\n  display: block;\n  border: 1px solid #b4b4b4;\n  position: relative;\n  margin-bottom: 1em;\n}\n\n/* needs its own rule (cannot be grouped with `tbody th`) because of buggy IE */\n#comments article:target {\n  background: #dde4ea;\n}\n\n#error-info.show, .meta strong, #firebug strong, #java strong, #status strong {\n  background: pink;\n  border: 1px solid #b00b00;\n  padding: .4em;\n}\n\n#error-info.show {\n  padding: .5em 1em;\n}\n\n#error-info, code, samp, var, textarea, #slug {\n  font-family: Monaco, monospace;\n  font-size: .9em;\n}\n\n#java strong {\n  background: #ffffdc;\n  border: 1px solid #faa700;\n}\n\n#slug {\n  font-size: 1em;\n}\n\n#faq dt {\n  margin-top: 1em;\n  font-weight: bold;\n}\n\n#faq dt a {\n  display: none;\n}\n\n#faq dt:hover a {\n  display: inline;\n}\n\n#faq dt:target, #faq dt:target + dd {\n  background: #90ee85;\n  margin: 0 -.8em;\n  padding: 0 .8em;\n}\n\n#faq dt:target + dd {\n  padding-bottom: .5em;\n  margin-bottom: -.5em;\n}\n\n#faq dt:target {\n  margin-top: .5em;\n  padding-top: .5em;\n}\n\n#firebug, #java, #status {\n  margin: 0 0 1em;\n  padding: .3em 0;\n}\n\n#prep-code pre {\n  max-height: 500px;\n  overflow: auto;\n}\n\n#controls.show, #firebug.show, #java.show {\n  display: block;\n}\n\n.co1, .co2, .coMULTI {\n  font-style: italic;\n}\n\n.error {\n  color: #b00b00;\n}\n\n.imp {\n  color: red;\n}\n\n.kw1, .kw3 {\n  color: #006;\n}\n\n.kw2 {\n  color: #036;\n}\n\n.co1, .coMULTI {\n  color: #060;\n}\n\n.co2 {\n  color: #096;\n}\n\n.es0 {\n  color: #009;\n}\n\n.br0 {\n  color: #090;\n}\n\n.sy0 {\n  color: #393;\n}\n\n.st0 {\n  color: #36c;\n}\n\n.nu0 {\n  color: #c00;\n}\n\n.me1 {\n  color: #606;\n}\n\n/* < 1051px */\n@media (max-width: 1050px) {\n  table pre, table td.code {\n    width: 550px;\n  }\n}\n\n/* < 1041px */\n@media (max-width: 1040px) {\n  body {\n    margin: 0;\n    border: 0;\n  }\n\n  body, #comments .meta {\n    width: 100%;\n    -webkit-box-sizing: border-box;\n    -moz-box-sizing: border-box;\n    box-sizing: border-box;\n  }\n\n}\n\n/* < 801px */\n@media (max-width: 800px) {\n  table pre, table td.code {\n    width: 450px;\n  }\n}\n\n/* < 681px */\n@media (max-width: 680px) {\n  table pre, table td.code {\n    width: 350px;\n  }\n}\n\n/* < 651px */\n@media (max-width: 650px) {\n  table pre, table td.code {\n    width: 200px;\n  }\n}"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/json3/benchmark/assets/ui.js",
    "content": "/*!\n * ui.js\n * Copyright Mathias Bynens <http://mths.be/>\n * Modified by John-David Dalton <http://allyoucanleet.com/>\n * Available under MIT license <http://mths.be/mit>\n */\n(function(window, document) {\n  // The path to the Java timer applet, relative to the document.\n  var archive = 'assets/nano.jar';\n\n  // A cache of error messages.\n  var errors = [];\n\n  // Event handler cache.\n  var eventHandlers = {};\n\n  // Indicates whether the page has loaded.\n  var isPageLoaded = false;\n\n  // Benchmark results element ID prefix.\n  var idPrefix = 'results-';\n\n  // The element responsible for scrolling the page. Assumes that `ui.js` has\n  // been loaded immediately before `</body>`.\n  var scrollEl = document.body;\n\n  // The UI namespace.\n  var ui = new Benchmark.Suite();\n\n  // An array of benchmarks created from test cases.\n  ui.benchmarks = [];\n\n  // The parsed query parameters from the location hash.\n  ui.parameters = {};\n\n  // API shortcuts.\n  var join = Benchmark.join,\n      filter = Benchmark.filter,\n      formatNumber = Benchmark.formatNumber;\n\n  // A map of operations to the CSS class names of their respective target\n  // elements.\n  var classNames = {\n    // Used for error styles.\n    'error': 'error',\n    // Used to make content visible.\n    'show': 'show',\n    // Used to reset result styles.\n    'results': 'results'\n  };\n\n  // Various application messages.\n  var messages = {\n    // \"Run\" button states.\n    'run': {\n      'again': 'Run again',\n      'ready': 'Run tests',\n      'running': 'Stop running'\n    },\n    // Common status values.\n    'status': {\n      'again': 'Done. Ready to run again.',\n      'ready': 'Ready to run.'\n    }\n  };\n\n  // `Benchmark.Suite#run` options.\n  var runOptions = {\n    'async': true,\n    'queued': true\n  };\n\n  function onCycle() {\n    var size = this.stats.sample.length;\n    if (!this.aborted) {\n      setStatus(this.name + ' &times; ' + formatNumber(this.count) + ' (' + size + ' sample' + (size === 1 ? '' : 's') + ')');\n    }\n  }\n\n  function onButtonClick() {\n    var isStopped = !ui.running;\n    ui.abort();\n    ui.length = 0;\n    if (!isStopped) {\n      return;\n    }\n    logError({ 'clear': true });\n    ui.push.apply(ui, _.filter(ui.benchmarks, function(bench) {\n      return !bench.error && bench.reset();\n    }));\n    ui.run(runOptions);\n  }\n\n  function onTitleClick(event) {\n    var id;\n    // Retrieve the closest benchmark results element.\n    for (var target = event.target || event.srcElement; target && !(id = target.id); target = target.parentNode);\n    var index = id && --id.split('-', 2)[1] || 0,\n        bench = ui.benchmarks[index];\n    // Queue the benchmark for running.\n    ui.push(bench.reset());\n    if (ui.running) {\n      ui.render(index);\n    } else {\n      ui.run(runOptions);\n    }\n  }\n\n  function onTitleKey(event) {\n    var keyCode = event['which' in event ? 'which' : 'charCode' in event ? 'charCode' : 'keyCode'];\n    if (keyCode == 13) {\n      eventHandlers.title.click(event);\n    }\n  }\n\n  function onHashChange() {\n    ui.parseHash();\n    if (!isPageLoaded) {\n      return;\n    }\n    var parameters = ui.parameters,\n        filterBy = parameters.filterby,\n        scrollTop;\n\n    if (filterBy) {\n      scrollTop = $('results').offsetTop;\n    }\n\n    // Automatically run benchmarks.\n    if ('run' in parameters) {\n      scrollTop = $('runner').offsetTop;\n      setTimeout(eventHandlers.button.run, 1);\n    }\n\n    // Scroll to the relevant section.\n    if (scrollTop) {\n      scrollEl.scrollTop = scrollTop;\n    }\n  }\n\n  function onLoad() {\n    addClass('controls', classNames.show);\n    addListener('run', 'click', eventHandlers.button.run);\n\n    setHTML('run', messages.run.ready);\n    setHTML('user-agent', Benchmark.platform);\n    setStatus(messages.status.ready);\n\n    try {\n      // Show warning when Firebug is enabled, ignoring Firebug Lite.\n      // Firebug 1.9 no longer implements `console.firebug`.\n      if (console.firebug || /firebug/i.test(console.table())) {\n        addClass('firebug', classNames.show);\n      }\n    } catch (exception) {}\n\n    // Parse the location hash. Deferred to ensure that all other `load`\n    // event handlers have executed.\n    setTimeout(function() {\n      isPageLoaded = true;\n      eventHandlers.window.hashChange();\n    }, 1);\n  }\n\n  function $(element) {\n    return typeof element == 'string' ? document.getElementById(element) : element;\n  }\n\n  var crlfTab = /[\\r\\n\\t]/g;\n\n  function addClass(element, className) {\n    if (!(element = $(element))) {\n      return element;\n    }\n    var targetClass = (' ' + element.className + ' ').replace(crlfTab, ' ');\n    if (targetClass.indexOf(className) < 0) {\n      element.className = (targetClass + className).trim();\n    }\n    return element;\n  }\n\n  function addListener(element, type, handler) {\n    if (!(element = $(element))) {\n      return element;\n    }\n    if (typeof element.addEventListener != 'undefined') {\n      element.addEventListener(type, handler, false);\n    } else if (typeof element.attachEvent != 'undefined') {\n      element.attachEvent('on' + type, handler);\n    }\n    return element;\n  }\n\n  function appendHTML(element, html) {\n    if ((element = $(element)) && html != null) {\n      element.innerHTML += html;\n    }\n    return element;\n  }\n\n  function createElement(tagName) {\n    return document.createElement(tagName);\n  }\n\n  function setHTML(element, html) {\n    if ((element = $(element))) {\n      element.innerHTML = html == null ? '' : html;\n    }\n    return element;\n  }\n\n  function getHz(bench) {\n    return 1 / (bench.stats.mean + bench.stats.moe);\n  }\n\n  function logError(error) {\n    var options = {},\n        element = $('error-info');\n\n    // Juggle arguments.\n    if (typeof error == 'object' && error) {\n      options = error;\n      error = options.text;\n    } else if (arguments.length) {\n      options.text = error;\n    }\n\n    if (!element) {\n      var table = $('test-table');\n      element = createElement('div');\n      element.id = 'error-info';\n      table.parentNode.insertBefore(element, table.nextSibling);\n    }\n\n    if (options.clear === true) {\n      element.className = element.innerHTML = '';\n      errors.length = 0;\n    }\n\n    if ('text' in options && !_.contains(errors, error)) {\n      errors.push(error);\n      addClass(element, classNames.show);\n      appendHTML(element, error);\n    }\n  }\n\n  function setStatus(status) {\n    return setHTML('status', status);\n  }\n\n  var parseHash = ui.parseHash = function parseHash() {\n    var hashes = location.hash.slice(1).split('&'),\n        parameters = this.parameters || (this.parameters = {});\n\n    // Clear original parameters.\n    _.forOwn(parameters, function(value, property) {\n      delete parameters[property];\n    });\n\n    // Add new parameters.\n    _.forEach(hashes[0], function(member) {\n      var position = member.indexOf('='),\n          value = '',\n          parameter;\n\n      if (member && position) {\n        if (position < 0) {\n          parameter = member;\n        } else {\n          parameter = decodeURIComponent(member.slice(0, position));\n          // Parameters without corresponding values are set to `''`.\n          if ((value = member.slice(position + 1))) {\n            value = decodeURIComponent(value).toLowerCase();\n          }\n        }\n        parameter = parameter.toLowerCase();\n        // The values of identical parameters (e.g., `a=1&a=2`) are aggregated\n        // into an array of values.\n        if (parameter in parameters) {\n          if (!parameters[parameter] || !_.isArray(parameters[parameter])) {\n            parameters[parameter] = [parameters[parameter]];\n          }\n          parameters[parameter].push(value);\n        } else {\n          parameters[parameter] = value;\n        }\n      }\n    });\n    return this;\n  };\n\n  var render = ui.render = function render(index) {\n    var iterable;\n    if (index == null) {\n      index = 0;\n      iterable = ui.benchmarks;\n    } else {\n      iterable = [ui.benchmarks[index]];\n    }\n\n    _.forEach(iterable, function(bench) {\n      var cell = $(idPrefix + (++index));\n      // Reset the element title and class name.\n      cell.title = '';\n      cell.className = classNames.results;\n\n      var error = bench.error;\n      if (error) {\n        // Status: Error.\n        setHTML(cell, 'Error');\n        addClass(cell, classNames.error);\n        var serialized = join(error, '</li><li>');\n        logError('<p>' + error + '.</p>' + (serialized ? '<ul><li>' + serialized + '</li></ul>' : ''));\n      } else {\n        // Status: Running.\n        if (bench.running) {\n          setHTML(cell, 'running&hellip;');\n        } else if (bench.cycles) {\n          // Obscure details until the suite has completed.\n          if (ui.running) {\n            setHTML(cell, 'completed');\n          } else {\n            var hz = bench.hz;\n            cell.title = 'Ran ' + formatNumber(bench.count) + ' times in ' + bench.times.cycle.toFixed(3) + ' seconds.';\n            setHTML(cell, formatNumber(hz.toFixed(hz < 100 ? 2 : 0)) + ' <small>&plusmn;' + bench.stats.rme.toFixed(2) + '%</small>');\n          }\n        } else if (ui.running && _.indexOf(ui, bench) > -1) {\n          // Status: Pending.\n          setHTML(cell, 'pending&hellip;');\n        } else {\n          // Status: Ready.\n          setHTML(cell, 'ready');\n        }\n      }\n    });\n    return ui;\n  };\n\n  ui.on('add', function(event) {\n    var bench = event.target,\n        index = ui.benchmarks.length,\n        id = index + 1,\n        title = $('title-' + id);\n\n    delete ui[ui.length];\n    ui.length = 0;\n    ui.benchmarks.push(bench);\n\n    title.tabIndex = 0;\n    title.title = 'Click to run this test again.';\n\n    addListener(title, 'click', eventHandlers.title.click);\n    addListener(title, 'keyup', eventHandlers.title.keyup);\n\n    bench.on('start cycle', eventHandlers.benchmark.cycle);\n    ui.render(index);\n  });\n\n  ui.on('start cycle', function() {\n    ui.render();\n    setHTML('run', messages.run.running);\n  });\n\n  ui.on('complete', function() {\n    var benches = filter(ui.benchmarks, 'successful'),\n        fastest = filter(benches, 'fastest'),\n        slowest = filter(benches, 'slowest');\n\n    ui.render();\n    setHTML('run', messages.run.again);\n    setStatus(messages.status.again);\n\n    _.forEach(benches, function(bench) {\n      var cell = $(idPrefix + (_.indexOf(ui.benchmarks, bench) + 1)),\n          fastestHz = getHz(fastest[0]),\n          hz = getHz(bench),\n          percent = (1 - (hz / fastestHz)) * 100,\n          span = cell.getElementsByTagName('span')[0],\n          text = 'fastest';\n\n      if (_.contains(fastest, bench)) {\n        // Indicate the fastest result.\n        addClass(cell, text);\n      } else {\n        text = isFinite(hz) ? formatNumber(percent < 1 ? percent.toFixed(2) : Math.round(percent)) + '% slower' : '';\n        if (_.contains(slowest, bench)) {\n          // Indicate the slowest result.\n          addClass(cell, 'slowest');\n        }\n      }\n      // Print ranking.\n      if (span) {\n        setHTML(span, text);\n      } else {\n        appendHTML(cell, '<span>' + text + '</span>');\n      }\n    });\n  });\n\n  eventHandlers.benchmark = {\n    'cycle': onCycle\n  };\n\n  eventHandlers.button = {\n    'run': onButtonClick\n  };\n\n  eventHandlers.title = {\n    'click': onTitleClick,\n    'keyup': onTitleKey\n  };\n\n  eventHandlers.window = {\n    'hashChange': onHashChange,\n    'load': onLoad\n  };\n\n  // Expose.\n  window.ui = ui;\n\n  // Parse the new query parameters when the hash changes.\n  addListener(window, 'hashchange', eventHandlers.window.hashChange);\n\n  addListener(window, 'load', eventHandlers.window.load);\n\n  // Immediately parse the location hash.\n  ui.parseHash();\n\n  // Detect the scroll element.\n  (function() {\n    var scrollTop,\n        div = document.createElement('div'),\n        body = document.body,\n        bodyStyle = body.style,\n        bodyHeight = bodyStyle.height,\n        html = document.documentElement,\n        htmlStyle = html.style,\n        htmlHeight = htmlStyle.height;\n\n    bodyStyle.height = htmlStyle.height = 'auto';\n    div.style.cssText = 'display:block;height:9001px;';\n    body.insertBefore(div, body.firstChild);\n    scrollTop = html.scrollTop;\n\n    if (html.clientWidth !== 0 && ++html.scrollTop && html.scrollTop == scrollTop + 1) {\n      // Set the correct `scrollEl` used by the `hashchange` event handler.\n      scrollEl = html;\n    }\n\n    body.removeChild(div);\n    bodyStyle.height = bodyHeight;\n    htmlStyle.height = htmlHeight;\n    html.scrollTop = scrollTop;\n  }());\n\n  // Inject the `nano.jar` applet.\n  (function() {\n    if ('nojava' in ui.parameters) {\n      return addClass('java', classNames.show);\n    }\n    for (var begin = new Date(), measured; !(measured = new Date() - begin););\n    var getNow;\n    if (measured != 1 && !((getNow = window.performance) && typeof (getNow.now || getNow.webkitNow) == 'function')) {\n      // Inject the applet using `innerHTML` to avoid triggering alerts in some\n      // versions of IE 6.\n      document.body.insertBefore(setHTML(createElement('div'), '<applet code=nano archive=' + archive + '>').lastChild, document.body.firstChild);\n    }\n  }());\n\n  window.onerror = function(message, fileName, lineNumber) {\n    logError('<p>' + message + '.</p><ul><li>' + join({\n      'message': message,\n      'fileName': fileName,\n      'lineNumber': lineNumber\n    }, '</li><li>') + '</li></ul>');\n    scrollEl.scrollTop = $('error-info').offsetTop;\n  };\n}(this, document));"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/json3/benchmark/benchmark_browser.html",
    "content": "<!DOCTYPE html>\n<!--[if lt IE 8]><html lang=\"en\" class=\"ie\"><![endif]-->\n<!--[if (gte IE 8)|(!IE)]><!--><html lang=\"en\"><!--<![endif]-->\n<head>\n  <meta charset=\"utf-8\">\n  <title>JSON 3 Benchmark Suite</title>\n  <link href=\"assets/jsperf.css\" rel=\"stylesheet\">\n  <script>\n    document.documentElement.className += ' js';\n  </script>\n  <!--[if lt IE 9]>\n    <script src=\"assets/html5.js\"></script>\n  <![endif]-->\n</head>\n<body>\n  <article>\n    <h1>JSON 3 Benchmark Suite</h1>\n    <section>\n      <h2>About</h2>\n      <p>This is a mirror of the <a href=\"http://jsperf.com/json3\" rel=\"nofollow\">JSON 3 benchmark suite</a> available on <a href=\"http://jsperf.com/\" rel=\"nofollow\">jsPerf</a>.</p>\n      <p>The following implementations support parsing and serializing:</p>\n      <ul>\n        <li><a href=\"http://bestiejs.github.io/json3\" rel=\"nofollow\">JSON 3</a>: Uses a modified, character-based recursive descent parser.</li>\n        <li><a href=\"https://github.com/douglascrockford/JSON-js\" rel=\"nofollow\">JSON 2</a>: Uses <code><span class=\"kw1\">eval</span></code> and a series of validation RegExps.</li>\n      </ul>\n      <p>The following implementations only support parsing:</p>\n      <ul>\n        <li><code>json-parse</code>: Uses a character-based recursive descent parser.</li>\n        <li><code>json-parse-state</code>: Uses a state machine parser.</li>\n        <li><a href=\"http://code.google.com/p/json-sans-eval\" rel=\"nofollow\"><code>json-sans-eval</code></a>: Uses a non-validating RegExp.</li>\n        <li><a href=\"https://github.com/abozhilov/json\" rel=\"nofollow\"><code>evalJSON</code></a>: Uses a RegExp-based recursive descent parser.</li>\n      </ul>\n    </section>\n    <section id=\"runner\">\n      <h2>Benchmark Runner</h2>\n      <p id=\"firebug\">\n        <strong>\n          Warning! For accurate results, please disable Firebug before running the tests.\n          <a href=\"http://jsperf.com/faq#firebug-warning\">(Why?)</a>\n        </strong>\n      </p>\n      <p id=\"java\">\n        <strong>Java applet disabled.</strong>\n      </p>\n      <p id=\"status\">\n        <noscript>\n          <strong>To run the tests, please <a href=\"http://enable-javascript.com/\">enable JavaScript</a> and reload the page.</strong>\n        </noscript>\n      </p>\n      <div id=\"controls\">\n        <button id=\"run\" type=\"button\"></button>\n      </div>\n      <table id=\"test-table\">\n        <caption>Testing in <span id=\"user-agent\"></span></caption>\n        <thead>\n          <tr>\n            <th colspan=\"2\">Test</th>\n            <th title=\"Operations per second (higher is better)\">Ops/sec</th>\n          </tr>\n        </thead>\n        <tbody>\n          <!-- JSON 3. -->\n          <tr>\n            <th scope=\"row\" id=\"title-1\">\n              <div>JSON 3: <code>parse</code></div>\n            </th>\n            <td class=\"code\">\n              <pre><code>JSON3.<span class=\"me1\">parse</span><span class=\"br0\">&#40;</span>&hellip;<span class=\"br0\">&#41;</span><span class=\"sy0\">;</span></code></pre>\n            </td>\n            <td id=\"results-1\" class=\"results\"></td>\n          </tr>\n          <!-- JSON 2. -->\n          <tr>\n            <th scope=\"row\" id=\"title-2\">\n              <div>JSON 2: <code>parse</code></div>\n            </th>\n            <td class=\"code\">\n              <pre><code>JSON2.<span class=\"me1\">parse</span><span class=\"br0\">&#40;</span>&hellip;<span class=\"br0\">&#41;</span><span class=\"sy0\">;</span></code></pre>\n            </td>\n            <td id=\"results-2\" class=\"results\"></td>\n          </tr>\n          <!-- `json-parse-state`. -->\n          <tr>\n            <th scope=\"row\" id=\"title-3\">\n              <div><code>json-parse-state</code></div>\n            </th>\n            <td class=\"code\">\n              <pre><code>json_parse_state<span class=\"br0\">&#40;</span>&hellip;<span class=\"br0\">&#41;</span><span class=\"sy0\">;</span></code></pre>\n            </td>\n            <td id=\"results-3\" class=\"results\"></td>\n          </tr>\n          <!-- `json-parse`. -->\n          <tr>\n            <th scope=\"row\" id=\"title-4\">\n              <div><code>json-parse</code></div>\n            </th>\n            <td class=\"code\">\n              <pre><code>json_parse<span class=\"br0\">&#40;</span>&hellip;<span class=\"br0\">&#41;</span><span class=\"sy0\">;</span></code></pre>\n            </td>\n            <td id=\"results-4\" class=\"results\"></td>\n          </tr>\n          <!-- `json-sans-eval`. -->\n          <tr>\n            <th scope=\"row\" id=\"title-5\">\n              <div><code>json-sans-eval</code></div>\n            </th>\n            <td class=\"code\">\n              <pre><code>jsonParse<span class=\"br0\">&#40;</span>&hellip;<span class=\"br0\">&#41;</span><span class=\"sy0\">;</span></code></pre>\n            </td>\n            <td id=\"results-5\" class=\"results\"></td>\n          </tr>\n          <!-- `evalJSON`. -->\n          <tr>\n            <th scope=\"row\" id=\"title-6\">\n              <div><code>evalJSON</code></div>\n            </th>\n            <td class=\"code\">\n              <pre><code>evalJSON<span class=\"br0\">&#40;</span>&hellip;<span class=\"br0\">&#41;</span><span class=\"sy0\">;</span></code></pre>\n            </td>\n            <td id=\"results-6\" class=\"results\"></td>\n          </tr>\n        </tbody>\n      </table>\n    </section>\n  </article>\n  <script src=\"../vendor/lodash.js\"></script>\n  <script src=\"../vendor/platform.js\"></script>\n  <script src=\"../vendor/benchmark.js\"></script>\n  <script src=\"assets/ui.js\"></script>\n  <script src=\"benchmark_json3.js\"></script>\n</body>\n</html>"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/json3/benchmark/benchmark_json3.js",
    "content": "var ui;\n;(function(window) {\n  // Convenience aliases.\n  var getClass = {}.toString;\n\n  // Detect asynchronous module loaders (RequireJS, `curl.js`, etc).\n  var isLoader = typeof define == 'function' && typeof define.amd == 'object' && !!define.amd;\n\n  // Detect CommonJS implementations and Node.\n  var isModule = typeof require == 'function' && typeof exports == 'object' && exports != null && !isLoader;\n  var isNode = isModule && typeof process == 'object' && typeof process.binding == 'function';\n\n  // Detect web browsers.\n  var isBrowser = 'window' in window && window.window == window && typeof window.document != 'undefined' && typeof window.navigator != 'undefined';\n\n  // Detect JavaScript engines (SpiderMonkey, JS, V8, etc) and Mozilla Rhino.\n  var isEngine = !isBrowser && !isModule && typeof window.load == 'function';\n  var isRhino = isEngine && typeof environment != 'undefined' && environment && getClass.call(environment) == '[object Environment]';\n\n  // Loads a module with the given `exports` name and `path`.\n  function load(exports, path) {\n    if (window[exports]) {\n      return window[exports];\n    }\n    if (isModule) {\n      return require(path);\n    }\n    if (isEngine) {\n      // Normalize module paths.\n      window.load(path.replace(/\\.js$/, '') + '.js');\n      return window[exports];\n    }\n    return null;\n  }\n\n  // Synchronously loads a library with the given `exports` name and `path`.\n  function getLibrary(exports, path) {\n    // Normalize paths.\n    path = path.replace(/\\.js$/, '') + '.js';\n    if (isNode) {\n      // Use Node's `vm` module.\n      var vm = require('vm'), fs = require('fs');\n      if (!fs.existsSync(path)) {\n        throw Error('The script `' + path + '` does not exist.');\n      }\n      var scope = {};\n      scope[exports] = null;\n      var context = vm.createContext(scope);\n      vm.runInNewContext(fs.readFileSync(path, 'utf8'), context);\n      return context[exports];\n    }\n    if (isRhino) {\n      // Use Rhino's reflection mechanisms via LiveConnect.\n      var io = java.io, javascript = Packages.org.mozilla.javascript, Context = javascript.Context;\n      try {\n        var context = Context.enter();\n        // Evaluate all scripts in interpretive mode (avoids overflow errors).\n        context.setOptimizationLevel(-1);\n        // Set the JS version to 1.5 for compatibility with ECMA-262.\n        context.setLanguageVersion(150);\n        // Create the constructors for the standard built-in ECMAScript objects.\n        var scope = context.initStandardObjects();\n        var script = (new java.io.File(path)).getAbsoluteFile();\n        if (!script.isFile()) {\n          throw Error('The script `' + path + '` does not exist.');\n        }\n        scope[exports] = null;\n        context.evaluateReader(scope, new io.BufferedReader(new io.FileReader(script)), script.getName(), 1, null);\n      } finally {\n        // Leave the execution context, even if an error occurred.\n        Context.exit();\n      }\n      return scope[exports];\n    }\n    var previous, result;\n    if (isBrowser) {\n      var transport = typeof ActiveXObject != 'undefined' ? new ActiveXObject('Microsoft.XMLHTTP') : typeof XMLHttpRequest != 'undefined' ? new XMLHttpRequest() : null;\n      // Retrieve the script contents using a synchronous `XMLHttpRequest`.\n      transport.open('GET', path + (path.indexOf('?') < 0 ? '?' : '&') + '_=' + (+new Date()), false);\n      transport.send(null);\n      // Catch script errors.\n      var onError = window.onerror, exception;\n      window.onerror = function(message) {\n        exception = message;\n        return true;\n      };\n      // Remove the current exports.\n      previous = window[exports];\n      window[exports] = null;\n      // Inject the script into the document to force evaluation.\n      var script = document.createElement('script'), firstScript = document.scripts.item(0);\n      // Append a `sourceURL` to facilitate debugging.\n      script.text = transport.responseText + '\\n/*\\n//@ sourceURL=' + path + '\\n*/';\n      firstScript.parentNode.insertBefore(script, firstScript).parentNode.removeChild(script);\n      // Capture the exported value and restore the previous exports and\n      // `onerror` event handler.\n      result = window[exports];\n      window[exports] = previous;\n      window.onerror = onError;\n      // Re-throw caught exceptions.\n      if (exception) {\n        throw Error(exception);\n      }\n      return result;\n    }\n    if (isEngine) {\n      // Simple overwrite-load-restore for other engines.\n      previous = window[exports];\n      window[exports] = null;\n      window.load(path);\n      result = window[exports];\n      window[exports] = previous;\n      return result;\n    }\n  }\n\n  // Logs the given `value`.\n  function log(value) {\n    if (typeof console != 'undefined' && console && typeof console.log != 'undefined') {\n      return console.log.apply(console, arguments);\n    }\n    if (typeof print == 'function' && !isBrowser) {\n      // In browsers, the global `print` function shows the \"Print\" dialog.\n      return print(value);\n    }\n    throw value;\n  }\n\n  // Load Benchmark.\n  var Benchmark = load('Benchmark', '../vendor/benchmark'), _ = load('_', '../vendor/lodash'), platform = load('platform', '../vendor/platform');\n  if (!Benchmark.Suite) {\n    Benchmark = Benchmark.runInContext({\n      '_': _,\n      'platform': platform\n    });\n  }\n\n  // JSON 3.\n  var JSON3 = getLibrary('JSON', '../lib/json3');\n\n  // JSON 2.\n  var JSON2 = getLibrary('JSON', '../vendor/json2');\n\n  // `json-parse-state` (Crockford's state machine parser).\n  var json_parse_state = getLibrary('json_parse', '../vendor/json_parse_state');\n\n  // `json-parse` (Crockford's recursive descent parser).\n  var json_parse = getLibrary('json_parse', '../vendor/json_parse');\n\n  // Mike Samuel's `json-sans-eval`.\n  var json_sans_eval = getLibrary('jsonParse', '../vendor/json_sans_eval');\n\n  // Asen Bozhilov's `evalJSON`\n  var evalJSON = getLibrary('evalJSON', '../vendor/evalJSON');\n\n  var suite = typeof ui == 'object' && ui || new Benchmark.Suite('JSON 3 Benchmark Suite');\n\n  var value = '{\"kitcambridge\":\"Kit\",\"contributors\":{\"jdalton\":\"John-David\",\"mathias\":\"Mathias\"},\"list\":[1,2,3],\"number\":5,\"date\":\"2012-04-25T14:08:36.879Z\",\"boolean\":true,\"nil\":null}';\n\n  suite.add('JSON 3: `parse`', function() {\n    JSON3.parse(value);\n  });\n\n  suite.add('JSON 2: `parse`', function() {\n    JSON2.parse(value);\n  });\n\n  suite.add('`json-parse-state`', function() {\n    json_parse_state(value);\n  });\n\n  suite.add('`json-parse`', function() {\n    json_parse(value);\n  });\n\n  suite.add('`json-sans-eval`', function() {\n    json_sans_eval(value);\n  });\n\n  suite.add('`evalJSON`', function() {\n    evalJSON(value);\n  });\n\n  if (!isBrowser) {\n    suite.on('cycle', function(event) {\n      log(String(event.target));\n    }).on('complete', function() {\n      var results = this.filter(\"successful\"), fastest = results.filter(\"fastest\"), slowest = results.filter(\"slowest\");\n      _.forEach(results, function(result) {\n        var hz = result.hz;\n        if (_.contains(fastest, result)) {\n          log(\"Fastest: `%s`.\", result.name);\n        } else if (_.contains(slowest, result)) {\n          log(\"Slowest: `%s`.%s\", result.name, isFinite(hz) ? \" \" + Math.round((1 - hz / fastest[0].hz) * 100) + \"% slower.\" : \"\");\n        }\n      });\n    });\n\n    suite.run({\n      'async': true\n    });\n  }\n}(this));"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/json3/build.js",
    "content": "#!/usr/bin/env node\n\n/* JSON 3 Builder | http://bestiejs.github.io/json3 */\nvar path = require(\"path\"), fs = require(\"fs\"), gzip = require(\"zlib\").gzip, spawn = require(\"child_process\").spawn, marked = require(path.join(__dirname, \"vendor\", \"marked\")),\n\n// The path to the Closure Compiler `.jar` file.\nclosurePath = path.join(__dirname, \"vendor\", \"closure-compiler.jar\"),\n\n// The Closure Compiler options: enable advanced optimizations and suppress all\n// warnings apart from syntax and optimization errors.\nclosureOptions = [\"--compilation_level=ADVANCED_OPTIMIZATIONS\", \"--warning_level=QUIET\"];\n\n// A RegExp used to detect the `define` pragma used by asynchronous module\n// loaders.\nvar definePattern = RegExp('(?:' +\n  // `typeof define == \"function\"`. Matches `==` and `===`; `'` and `\"`.\n  'typeof\\\\s+define\\\\s*===?\\\\s*([\\'\"])function\\\\1|' +\n  // `\"function\" == typeof define`. Same rules as above.\n  '([\\'\"])function\\\\2\\\\s*===?\\\\s*typeof\\\\s+define' +\n')' +\n// `&&`.\n'\\\\s*&&\\\\s*(?:' +\n  // `define`.\n  'define\\\\s*(?:' +\n    // `.amd`.\n    '\\\\.\\\\s*amd|' +\n    // `[\"amd\"]` | `['amd']`.\n    '\\\\[\\\\s*([\\'\"])amd\\\\3\\\\s*\\\\]' +\n  ')|' +\n  '(?:' +\n    '(?:' +\n      // `typeof define.amd`.\n      'typeof\\\\s+define\\\\.\\\\s*amd|' +\n      // `typeof define[\"amd\"]` or `typeof define['amd']`.\n      'typeof\\\\s+define\\\\[\\\\s*([\\'\"])amd\\\\4\\\\s*\\\\]' +\n    ')' +\n    // `=== \"object\"`. Same rules for quotes and equality operators.\n    '\\\\s*===?\\\\s*([\\'\"])object\\\\5' +\n  '|' +\n    // `\"object\" ===`.\n    '([\\'\"])object\\\\6\\\\s*===?\\\\s*' +\n    '(?:' +\n      'typeof\\\\s+define\\\\.\\\\s*amd|' +\n      'typeof\\\\s+define\\\\[\\\\s*([\\'\"])amd\\\\7\\\\s*\\\\]' +\n    ')' + \n  ')' +\n  '(?:' +\n    // `&&` (optional Boolean test for `define.amd`).\n    '\\\\s*&&\\\\s*' +\n    '(?:' +\n      // `define.amd`.\n      'define\\\\.\\\\s*amd|' +\n      // `define[\"amd\"] | define['amd']`.\n      'define\\\\[\\\\s*([\\'\"])amd\\\\8\\\\s*\\\\]' +\n    ')' +\n  ')?' +\n')', 'g');\n\n// Enable GitHub-Flavored Markdown.\nmarked.setOptions({ \"gfm\": true });\n\n// Generate the GitHub project page.\nfs.readFile(path.join(__dirname, \"README.md\"), \"utf8\", function readInfo(exception, source) {\n  if (exception) {\n    console.log(exception);\n  } else {\n    // Read the project page template.\n    fs.readFile(path.join(__dirname, \"page\", \"page.html\"), \"utf8\", readTemplate);\n  }\n\n  // Interpolates the page template and writes the result to disk.\n  function readTemplate(exception, page) {\n    var headers, lines, lastSection, lastLevel, navigation;\n    if (exception) {\n      console.log(exception);\n    } else {\n      // Generate the page navigation. Ported from `mdtoc.rb` by Sam\n      // Stephenson.\n      headers = [];\n      lines = source.split(/\\r?\\n/);\n      // First pass: Scan the Markdown source looking for titles of the format:\n      // `### Title ###`. Record the line number, header level (number of\n      // octothorpes), and text of each matching title.\n      lines.forEach(function (line, index) {\n        var match = /^(\\#{1,6})\\s+(.+?)\\s+\\1$/.exec(line);\n        if (match) {\n          headers.push([index, match[1].length, match[2]]);\n        }\n      });\n      // Second pass: Iterate over all matched titles and compute their\n      // corresponding section numbers. Then replace the titles with annotated\n      // anchors.\n      headers.forEach(function (value) {\n        var index = value[0], level = value[1], text = value[2], section, length;\n        if (lastSection) {\n          // Clone the last section metadata array.\n          section = lastSection.slice(0);\n          if (lastLevel < level) {\n            section.push(1);\n          } else {\n            length = lastLevel - level;\n            while (length--) {\n              section.pop();\n            }\n            section[section.length - 1] += 1;\n          }\n        } else {\n          section = [1];\n        }\n        lines[index] = Array(level + 1).join(\"#\") + \"<a name=\\\"section_\" + section.join(\".\") + \"\\\"></a>\" + text;\n        value.push(section);\n        lastSection = section;\n        lastLevel = level;\n      });\n      // Third pass: Iterate over matched titles once more to produce the table of\n      // contents.\n      navigation = headers.map(function (value) {\n        var index = value[0], level = value[1], text = value[2], section = value[3], name = section.join(\".\");\n        return \"<li><a href=\\\"#section_\" + name + \"\\\">\" + text + \"</a></li>\";\n      });\n      navigation.push(\"\");\n      // Write the page source to disk.\n      fs.writeFile(path.join(__dirname, \"index.html\"), page.replace(/<%=\\s*(.+?)\\s*%>/g, function interpolate(match, data) {\n        switch (data) {\n          case \"navigation\":\n            // Insert the table of contents directly into the template.\n            return navigation.join(\"\\n\");\n          case \"source\":\n            // Convert the read me to HTML and insert it into the page body.\n            return marked(lines.join(\"\\n\"));\n        }\n        return \"\";\n      }), function writePage(exception) {\n        console.log(exception || \"GitHub project page generated successfully.\");\n      });\n    }\n  }\n});\n\n// Compress JSON 3 using the Closure Compiler.\nfs.readFile(path.join(__dirname, \"lib\", \"json3.js\"), \"utf8\", function readSource(exception, source) {\n  var error, output, compiler, results;\n  if (exception) {\n    console.log(exception);\n  } else {\n    // Shell out to the Closure Compiler. Requires Java 6 or higher.\n    error = output = \"\";\n    compiler = spawn(\"java\", [\"-jar\", closurePath].concat(closureOptions));\n    compiler.stdout.on(\"data\", function onData(data) {\n      // Append the data to the output stream.\n      output += data;\n    });\n    compiler.stderr.on(\"data\", function onError(data) {\n      // Append the error message to the error stream.\n      error += data;\n    });\n    compiler.on(\"exit\", function onExit(status) {\n      var exception;\n      // `status` specifies the process exit code.\n      if (status) {\n        exception = new Error(error);\n        exception.status = status;\n      }\n      compressSource(exception, output);\n    });\n    // Proxy the preprocessed source to the Closure Compiler.\n    compiler.stdin.end(preprocessSource(source));\n  }\n\n  // Post-processes the compressed source and writes the result to disk.\n  function compressSource(exception, compressed) {\n    if (exception) {\n      console.log(exception);\n    } else {\n      // Extract the JSON 3 header and clean up the minified source.\n      compressed = extractComments(source)[0] + postprocessSource(compressed);\n      // Write the compressed version to disk.\n      fs.writeFile(path.join(__dirname, \"lib\", \"json3.min.js\"), compressed, writeSource);\n    }\n\n    // Checks the `gzip`-ped size of the compressed version by shelling out to the\n    // Unix `gzip` executable.\n    function writeSource(exception) {\n      console.log(exception || \"Compressed version generated successfully.\");\n      // Automatically check the `gzip`-ped size of the compressed version.\n      gzip(compressed, function (exception, results) {\n        console.log(\"Compressed version size: %d bytes.\", results.length);\n      });\n    }\n  }\n});\n\n// Internal: Extracts line and block comments from a JavaScript `source`\n// string. Returns an array containing the comments.\nfunction extractComments(source) {\n  var index = 0, length = source.length, results = [], symbol, position, original;\n  while (index < length) {\n    symbol = source[index];\n    switch (symbol) {\n      // Parse line and block comments.\n      case \"/\":\n        original = symbol;\n        symbol = source[++index];\n        switch (symbol) {\n          // Extract line comments.\n          case \"/\":\n            position = source.indexOf(\"\\n\", index);\n            if (position < 0) {\n              // Check for CR line endings.\n              position = source.indexOf(\"\\r\", index);\n            }\n            results.push(original + source.slice(index, index = position < 0 ? length : position));\n            break;\n          // Extract block comments.\n          case \"*\":\n            position = source.indexOf(\"*/\", index);\n            if (position < 0) {\n              throw SyntaxError(\"Unterminated block comment.\");\n            }\n            // Advance past the end of the comment.\n            results.push(original + source.slice(index, index = position += 2));\n            break;\n          default:\n            index++;\n        }\n        break;\n      // Parse strings separately to ensure that any JavaScript comments within\n      // them are preserved.\n      case '\"':\n      case \"'\":\n        for (position = index, original = symbol; index < length;) {\n          symbol = source[++index];\n          if (symbol == \"\\\\\") {\n            // Skip past escaped characters.\n            index++;\n          } else if (\"\\n\\r\\u2028\\u2029\".indexOf(symbol) > -1) {\n            // According to the ES 5.1 spec, strings may not contain unescaped\n            // line terminators.\n            throw SyntaxError(\"Illegal line continuation.\");\n          } else if (symbol == original) {\n            break;\n          }\n        }\n        if (source[index] == original) {\n          index++;\n          break;\n        }\n        throw SyntaxError(\"Unterminated string.\");\n      default:\n        // Advance to the next character.\n        index++;\n    }\n  }\n  return results;\n}\n\nfunction preprocessSource(source) {\n  var result = source.replace(definePattern, 'typeof define === \"function\" && define[\"amd\"]');\n  // Remove the top-level immediately-invoked function expression, as the output\n  // is automatically wrapped in one.\n  return result.replace(/^;?\\(function\\s*\\(\\)\\s*\\{([\\s\\S]*?)}\\)\\.call\\(this\\);*?/m, \"$1\");\n}\n\nfunction postprocessSource(source) {\n  // Wrap the compressed source in an IIFE (enabling advanced optimizations\n  // causes the Compiler to add variables to the global scope) and fix the\n  // `define` pragma.\n  return \"\\n;(function(){\" + source.replace(definePattern, 'typeof define===\"function\"&&define.amd') + \"}());\";\n}"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/json3/index.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"utf-8\">\n    <title>JSON 3</title>\n    <link rel=\"stylesheet\" href=\"page/style.css\" media=\"screen\">\n  </head>\n  <body>\n    <ul id=\"navigation\">\n      <li><a href=\"#section_1\">JSON 3</a></li>\n<li><a href=\"#section_2\">Changes from JSON 2</a></li>\n<li><a href=\"#section_3\">Usage</a></li>\n<li><a href=\"#section_4\">Compatibility</a></li>\n<li><a href=\"#section_5\">Contribute</a></li>\n\n    </ul>\n    <div id=\"content\">\n      <h1><a name=\"section_1\"></a>JSON 3</h1>\n<p><img src=\"http://bestiejs.github.io/json3/page/logo.png\" alt=\"JSON 3 Logo\">\n\n</p>\n<p><strong>JSON 3</strong> is a modern JSON implementation compatible with a variety of JavaScript platforms, including Internet Explorer 6, Opera 7, Safari 2, and Netscape 6. The current version is <strong>3.2.5</strong>.\n\n</p>\n<ul>\n<li><a href=\"http://bestiejs.github.io/json3/lib/json3.js\">Development Version</a> <em>(38.8 KB; uncompressed with comments)</em></li>\n<li><a href=\"http://bestiejs.github.io/json3/lib/json3.min.js\">Production Version</a> <em>(3.2 KB; compressed and <code>gzip</code>-ped)</em></li>\n</ul>\n<p><a href=\"http://json.org/\">JSON</a> is a language-independent data interchange format based on a loose subset of the JavaScript grammar. Originally popularized by <a href=\"http://www.crockford.com/\">Douglas Crockford</a>, the format was standardized in the <a href=\"http://es5.github.com/\">fifth edition</a> of the ECMAScript specification. The 5.1 edition, ratified in June 2011, incorporates several modifications to the grammar pertaining to the serialization of dates.\n\n</p>\n<p>JSON 3 exposes two functions: <code>stringify()</code> for <a href=\"https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/JSON/stringify\">serializing</a> a JavaScript value to JSON, and <code>parse()</code> for <a href=\"https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/JSON/parse\">producing</a> a JavaScript value from a JSON source string. It is a <strong>drop-in replacement</strong> for <a href=\"http://json.org/js\">JSON 2</a>. The functions behave exactly as described in the ECMAScript spec, <strong>except</strong> for the date serialization discrepancy noted below.\n\n</p>\n<p>The JSON 3 parser does <strong>not</strong> use <code>eval</code> or regular expressions. This provides security and performance benefits in obsolete and mobile environments, where the margin is particularly significant. The complete <a href=\"http://jsperf.com/json3\">benchmark suite</a> is available on <a href=\"http://jsperf.com/\">jsPerf</a>.\n\n</p>\n<p>The project is <a href=\"http://git.io/json3\">hosted on GitHub</a>, along with the <a href=\"http://bestiejs.github.io/json3/test/test_browser.html\">unit tests</a>. It is part of the <a href=\"https://github.com/bestiejs\">BestieJS</a> family, a collection of best-in-class JavaScript libraries that promote cross-platform support, specification precedents, unit testing, and plenty of documentation.\n\n</p>\n<h1><a name=\"section_2\"></a>Changes from JSON 2</h1>\n<p>JSON 3...\n\n</p>\n<ul>\n<li>Correctly serializes primitive wrapper objects.</li>\n<li>Throws a <code>TypeError</code> when serializing cyclic structures (JSON 2 recurses until the call stack overflows).</li>\n<li>Utilizes <strong>feature tests</strong> to detect broken or incomplete <em>native</em> JSON implementations (JSON 2 only checks for the presence of the native functions). The tests are only executed once at runtime, so there is no additional performance cost when parsing or serializing values.</li>\n</ul>\n<p><strong>As of v3.2.3</strong>, JSON 3 is compatible with <a href=\"http://prototypejs.org\">Prototype</a> 1.6.1 and older.\n\n</p>\n<p>In contrast to JSON 2, JSON 3 <strong>does not</strong>...\n\n</p>\n<ul>\n<li>Add <code>toJSON()</code> methods to the <code>Boolean</code>, <code>Number</code>, and <code>String</code> prototypes. These are not part of any standard, and are made redundant by the design of the <code>stringify()</code> implementation.</li>\n<li>Add <code>toJSON()</code> or <code>toISOString()</code> methods to <code>Date.prototype</code>. See the note about date serialization below.</li>\n</ul>\n<h2>Date Serialization</h2>\n<p><strong>JSON 3 deviates from the specification in one important way</strong>: it does not define <code>Date#toISOString()</code> or <code>Date#toJSON()</code>. This preserves CommonJS compatibility and avoids polluting native prototypes. Instead, date serialization is performed internally by the <code>stringify()</code> implementation: if a date object does not define a custom <code>toJSON()</code> method, it is serialized as a <a href=\"http://es5.github.com/#x15.9.1.15\">simplified ISO 8601 date-time string</a>.\n\n</p>\n<p><strong>Several native <code>Date#toJSON()</code> implementations produce date time strings that do <em>not</em> conform to the grammar outlined in the spec</strong>. For instance, all versions of Safari 4, as well as JSON 2, fail to serialize extended years correctly. Furthermore, JSON 2 and older implementations omit the milliseconds from the date-time string (optional in ES 5, but required in 5.1). Finally, in all versions of Safari 4 and 5, serializing an invalid date will produce the string <code>&quot;Invalid Date&quot;</code>, rather than <code>null</code>. Because these environments exhibit other serialization bugs, however, JSON 3 will override the native <code>stringify()</code> implementation.\n\n</p>\n<p>Portions of the date serialization code are adapted from the <a href=\"https://github.com/Yaffle/date-shim\"><code>date-shim</code></a> project.\n\n</p>\n<h1><a name=\"section_3\"></a>Usage</h1>\n<h2>Web Browsers</h2>\n<pre><code>&lt;script src=&quot;http://bestiejs.github.io/json3/lib/json3.js&quot;&gt;&lt;/script&gt;\n&lt;script&gt;\n  JSON.stringify({&quot;Hello&quot;: 123});\n  // =&gt; &#39;{&quot;Hello&quot;:123}&#39;\n  JSON.parse(&quot;[[1, 2, 3], 1, 2, 3, 4]&quot;, function (key, value) {\n    if (typeof value == &quot;number&quot;) {\n      value = value % 2 ? &quot;Odd&quot; : &quot;Even&quot;;\n    }\n    return value;\n  });\n  // =&gt; [[&quot;Odd&quot;, &quot;Even&quot;, &quot;Odd&quot;], &quot;Odd&quot;, &quot;Even&quot;, &quot;Odd&quot;, &quot;Even&quot;]\n&lt;/script&gt;</code></pre>\n<h2>CommonJS Environments</h2>\n<pre><code>var JSON3 = require(&quot;./path/to/json3&quot;);\nJSON3.parse(&quot;[1, 2, 3]&quot;);\n// =&gt; [1, 2, 3]</code></pre>\n<h2>JavaScript Engines</h2>\n<pre><code>load(&quot;path/to/json3.js&quot;);\nJSON.stringify({&quot;Hello&quot;: 123, &quot;Good-bye&quot;: 456}, [&quot;Hello&quot;], &quot;\\t&quot;);\n// =&gt; &#39;{\\n\\t&quot;Hello&quot;: 123\\n}&#39;</code></pre>\n<h1><a name=\"section_4\"></a>Compatibility</h1>\n<p>JSON 3 has been <strong>tested</strong> with the following web browsers, CommonJS environments, and JavaScript engines.\n\n</p>\n<h2>Web Browsers</h2>\n<ul>\n<li>Windows <a href=\"http://www.microsoft.com/windows/internet-explorer\">Internet Explorer</a>, version 6.0 and higher</li>\n<li>Mozilla <a href=\"http://www.mozilla.com/firefox\">Firefox</a>, version 1.0 and higher</li>\n<li>Apple <a href=\"http://www.apple.com/safari\">Safari</a>, version 2.0 and higher</li>\n<li><a href=\"http://www.opera.com\">Opera</a> 7.02 and higher</li>\n<li><a href=\"http://sillydog.org/narchive/gecko.php\">Mozilla</a> 1.0, <a href=\"http://sillydog.org/narchive/\">Netscape</a> 6.2.3, and <a href=\"http://www.seamonkey-project.org/\">SeaMonkey</a> 1.0 and higher</li>\n</ul>\n<h2>CommonJS Environments</h2>\n<ul>\n<li><a href=\"http://nodejs.org/\">Node</a> 0.2.6 and higher</li>\n<li><a href=\"http://ringojs.org/\">RingoJS</a> 0.4 and higher</li>\n<li><a href=\"http://narwhaljs.org/\">Narwhal</a> 0.3.2 and higher</li>\n</ul>\n<h2>JavaScript Engines</h2>\n<ul>\n<li>Mozilla <a href=\"http://www.mozilla.org/rhino\">Rhino</a> 1.5R5 and higher</li>\n<li>WebKit <a href=\"https://trac.webkit.org/wiki/JSC\">JSC</a></li>\n<li>Google <a href=\"http://code.google.com/p/v8\">V8</a></li>\n</ul>\n<h2>Known Incompatibilities</h2>\n<ul>\n<li>Attempting to serialize the <code>arguments</code> object may produce inconsistent results across environments due to specification version differences. As a workaround, please convert the <code>arguments</code> object to an array first: <code>JSON.stringify([].slice.call(arguments, 0))</code>.</li>\n</ul>\n<h2>Required Native Methods</h2>\n<p>JSON 3 assumes that the following methods exist and function as described in the ECMAScript specification:\n\n</p>\n<ul>\n<li>The <code>Number</code>, <code>String</code>, <code>Array</code>, <code>Object</code>, <code>Date</code>, <code>SyntaxError</code>, and <code>TypeError</code> constructors.</li>\n<li><code>String.fromCharCode</code></li>\n<li><code>Object#toString</code></li>\n<li><code>Function#call</code></li>\n<li><code>Math.floor</code></li>\n<li><code>Number#toString</code></li>\n<li><code>Date#valueOf</code></li>\n<li><code>String.prototype</code>: <code>indexOf</code>, <code>charCodeAt</code>, <code>charAt</code>, <code>slice</code>.</li>\n<li><code>Array.prototype</code>: <code>push</code>, <code>pop</code>, <code>join</code>.</li>\n</ul>\n<h1><a name=\"section_5\"></a>Contribute</h1>\n<p>Check out a working copy of the JSON 3 source code with <a href=\"http://git-scm.com/\">Git</a>:\n\n</p>\n<pre><code>$ git clone git://github.com/bestiejs/json3.git\n$ cd json3\n$ git submodule update --init</code></pre>\n<p>If you&#39;d like to contribute a feature or bug fix, you can <a href=\"http://help.github.com/fork-a-repo/\">fork</a> JSON 3, commit your changes, and <a href=\"http://help.github.com/send-pull-requests/\">send a pull request</a>. Please make sure to update the unit tests in the <code>test</code> directory as well.\n\n</p>\n<p>Alternatively, you can use the <a href=\"https://github.com/bestiejs/json3/issues\">GitHub issue tracker</a> to submit bug reports, feature requests, and questions, or send tweets to <a href=\"http://twitter.com/kitcambridge\">@kitcambridge</a>.\n\n</p>\n<p>JSON 3 is released under the <a href=\"http://kit.mit-license.org/\">MIT License</a>.</p>\n\n    </div>\n    <div id=\"footer\">\n      <p>&copy; 2012-2013 <a href=\"http://kitcambridge.be/\">Kit Cambridge</a>.</p>\n    </div>\n  </body>\n</html>"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/json3/lib/json3.js",
    "content": "/*! JSON v3.2.5 | 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, JSON3 = typeof exports == \"object\" && exports;\n\n  if (JSON3 || isLoader) {\n    if (typeof JSON == \"object\" && JSON) {\n      // Delegate to the native `stringify` and `parse` implementations in\n      // asynchronous module loaders and CommonJS environments.\n      if (JSON3) {\n        JSON3.stringify = JSON.stringify;\n        JSON3.parse = JSON.parse;\n      } else {\n        JSON3 = JSON;\n      }\n    } else if (isLoader) {\n      JSON3 = window.JSON = {};\n    }\n  } else {\n    // Export for web browsers and JavaScript engines.\n    JSON3 = window.JSON || (window.JSON = {});\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 (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      return \"a\"[0] != \"a\";\n    }\n    var value, serialized = '{\"a\":[1,true,false,null,\"\\\\u0000\\\\b\\\\n\\\\f\\\\r\\\\t\"]}', isAll = name == \"json\";\n    if (isAll || name == \"json-stringify\" || name == \"json-parse\") {\n      // Test `JSON.stringify`.\n      if (name == \"json-stringify\" || isAll) {\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,],\". These versions\n              // of Firefox also allow trailing commas in JSON objects and arrays.\n              // FF 3.1b3 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        if (!isAll) {\n          return stringifySupported;\n        }\n      }\n      // Test `JSON.parse`.\n      if (name == \"json-parse\" || isAll) {\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 and\n                    // trailing decimal points. FF 4.0, 4.0.1, and IE 9-10 also\n                    // allow certain octal literals.\n                    parseSupported = parse(\"01\") !== 1;\n                  } catch (exception) {}\n                }\n              }\n            }\n          } catch (exception) {\n            parseSupported = false;\n          }\n        }\n        if (!isAll) {\n          return parseSupported;\n        }\n      }\n      return stringifySupported && parseSupported;\n    }\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: 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, forEach;\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          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\") && isProperty.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]; isProperty.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 = object[property], className, year, month, date, time, hours, minutes, seconds, milliseconds, results, element, index, length, prefix, hasMembers, 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; hasMembers || (hasMembers = true), index++) {\n              element = serialize(index, value, callback, properties, whitespace, indentation, stack);\n              results.push(element === undef ? \"null\" : element);\n            }\n            result = hasMembers ? (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              hasMembers || (hasMembers = true);\n            });\n            result = hasMembers ? (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;\n        if (typeof filter == \"function\" || typeof filter == \"object\" && filter) {\n          if (getClass.call(filter) == functionClass) {\n            callback = filter;\n          } else if (getClass.call(filter) == 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++], ((getClass.call(value) == stringClass || getClass.call(value) == numberClass) && (properties[value] = 1)));\n          }\n        }\n        if (width) {\n          if (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 (getClass.call(width) == 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 (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\" || 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": "flowable-ui-web/admin/bower_components/json3/package.json",
    "content": "{\n  \"name\": \"json3\",\n  \"version\": \"3.2.5\",\n  \"description\": \"A modern JSON implementation compatible with nearly all JavaScript platforms.\",\n  \"homepage\": \"http://bestiejs.github.io/json3\",\n  \"main\": \"./lib/json3\",\n  \"keywords\": [\"json\", \"spec\", \"ecma\", \"es5\", \"lexer\", \"parser\", \"stringify\"],\n  \"licenses\": [{\n    \"type\": \"MIT\",\n    \"url\": \"http://kit.mit-license.org/\"\n  }],\n  \"author\": {\n    \"name\": \"Kit Cambridge\",\n    \"email\": \"github@kitcambridge.be\",\n    \"web\": \"http://kitcambridge.be/\"\n  },\n  \"maintainers\": [{\n    \"name\": \"Kit Cambridge\",\n    \"email\": \"github@kitcambridge.be\",\n    \"web\": \"http://kitcambridge.be/\"\n  }],\n  \"contributors\": [{\n    \"name\": \"Øyvind Sean Kinsey\",\n    \"email\": \"oyvind@kinsey.no\",\n    \"web\": \"http://fb.me/ok\"\n  }, {\n    \"name\": \"Mangled Deutz\",\n    \"email\": \"olivier@webitup.fr\",\n    \"web\": \"http://tech.roxee.tv/\"\n  }, {\n    \"name\": \"Kiryl Yermakou\",\n    \"email\": \"rma4ok@gmail.com\",\n    \"web\": \"https://github.com/rma4ok\"\n  }, {\n    \"name\": \"Oskar Schöldström\",\n    \"email\": \"public@oxy.fi\",\n    \"web\": \"http://oxy.fi/\"\n  }],\n  \"bugs\": {\n    \"url\": \"https://github.com/bestiejs/json3/issues\"\n  },\n  \"scripts\": {\n    \"test\": \"node test/test_*.js\"\n  },\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git://github.com/bestiejs/json3.git\"\n  }\n}"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/json3/page/page.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"utf-8\">\n    <title>JSON 3</title>\n    <link rel=\"stylesheet\" href=\"page/style.css\" media=\"screen\">\n  </head>\n  <body>\n    <ul id=\"navigation\">\n      <%= navigation %>\n    </ul>\n    <div id=\"content\">\n      <%= source %>\n    </div>\n    <div id=\"footer\">\n      <p>&copy; 2012-2013 <a href=\"http://kitcambridge.be/\">Kit Cambridge</a>.</p>\n    </div>\n  </body>\n</html>"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/json3/page/style.css",
    "content": "/* Earl Grey | http://kitcambridge.github.com/earlgrey | Copyright 2011-2012, Kit Cambridge | http://creativecommons.org/licenses/by/3.0 */\nhtml {\n  font: 12px/24px \"Lucida Grande\", \"Lucida Sans Unicode\", Helvetica, Arial, sans-serif;\n  background: url(background.png);\n}\n\nbody {\n  width: 80%;\n  margin: 20px auto;\n  border: 3px solid #eee;\n  background: #fff;\n}\n\n#content {\n  padding: 25px;\n  text-align: justify;\n}\n\np, ul, ol {\n  padding: 5px 0;\n  margin: 0;\n}\n\nul, ol {\n  color: #333;\n  margin: auto auto auto 25px;\n}\n\na {\n  padding: 1px;\n  color: inherit;\n  text-decoration: underline;\n}\n\na:hover, a:focus {\n  text-decoration: none;\n}\n\n#content a:hover, #content a:focus {\n  background: #000;\n  color: #fff;\n}\n\n#footer a:hover, #footer a:focus {\n  background: #fff;\n  color: #000;\n}\n\nh1, h2, h3 {\n  padding: 5px 0;\n  margin: 0;\n}\n\nh1 {\n  font: 24px Palatino, Georgia, Times, \"Times New Roman\", serif;\n  color: #900;\n}\n\nh2, h3 {\n  text-transform: uppercase;\n  color: #666;\n  letter-spacing: 1px;\n  font-weight: bold;\n}\n\nh2 {\n  font-size: 14px;\n}\n\nh3 {\n  font-size: 12px;\n}\n\ntable {\n  border-collapse: collapse;\n  border: solid #ccc;\n  border-width: 1px 0 0 1px;\n  margin: 15px 0;\n}\n\ntd, th {\n  border: solid #ccc;\n  border-width: 0 1px 1px 0;\n  padding: 5px;\n  width: 20%;\n  text-align: center;\n}\n\nth {\n  font-weight: bold;\n  color: #333;\n}\n\n#navigation {\n  list-style: none;\n  float: left;\n  text-align: center;\n  width: 100%;\n  background: #333;\n  padding: 0;\n  margin: 0 0 10px 0;\n}\n\n#navigation li {\n  display: inline;\n}\n\n#navigation a {\n  display: inline-block;\n  color: #fff;\n  padding: 5px 5% 5px;\n  height: 20px;\n  text-decoration: none;\n  text-align: center;\n}\n\n#navigation a:hover, #navigation a:focus, #navigation a.active {\n  background: #eee;\n  color: #900;\n}\n\n#footer {\n  background: #333;\n  color: #fff;\n  text-align: center;\n}\n\npre, code, tt {\n  font: normal 12px/24px Menlo, Monaco, Consolas, \"Lucida Console\", monospace;\n}\n\npre {\n  background-color: #f8f8ff;\n  padding: 10px;\n  border: 1px solid #eee;\n  word-wrap: break-word;\n  white-space: pre-wrap;\n}\n\nimg {\n  padding: 0 0 30px 30px;\n  float: right;\n}"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/json3/test/test_browser.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"utf-8\">\n    <title>JSON 3 Unit Tests</title>\n    <link rel=\"stylesheet\" href=\"../vendor/spec/lib/newton.css\" media=\"screen\">\n    <script src=\"../vendor/spec/lib/spec.js\"></script>\n    <script src=\"../vendor/spec/lib/newton.js\"></script>\n    <script>\n    var curl;\n    (function () {\n      var parameters;\n      if (!(typeof Spec == \"object\" && Spec || typeof Newton == \"object\" && Newton)) {\n        return;\n      }\n      parameters = Newton.parseQuery(location.search);\n      if (Spec.hasKey(parameters, \"amd\")) {\n        // Load RequireJS or `curl.js`. `document.write` is used because older\n        // versions of Safari and Chrome do not support DOM script injection.\n        curl = { \"apiName\": \"require\" };\n        document.write('<script src=\"../vendor/' + (parameters.amd == \"require\" ? \"require\" : \"curl\") + '.js\"><\\/script>');\n      }\n      if (Spec.hasKey(parameters, \"prototype\")) {\n        document.write('<script src=\"../vendor/prototype.js\"><\\/script>');\n      }\n    }());\n    </script>\n    <script>\n    var JSON;\n    (function () {\n      if (typeof require == \"function\" && typeof define == \"function\") {\n        require({\n          // RequireJS accepts relative paths in the module name; `curl.js` does\n          // not. Both accept a `paths` map of module paths to relative paths.\n          \"paths\": { \"json\": \"../lib/json3\" },\n          // Thwart aggressive resource caching. RequireJS only.\n          \"urlArgs\": \"async=\" + (+new Date())\n        }, [\"json\", \"test_json3\"], function (JSON3, testSuite) {\n          // Test asynchronous module loading via RequireJS/`curl.js`.\n          testSuite.addTest(\"Asynchronous Module Definition\", function (test) {\n            setTimeout(function () {\n              test.equal(JSON3.stringify(1), \"1\", \"JSON 3 should be exported as an asynchronous module\").done(1);\n            }, 1500);\n          });\n          testSuite.run();\n        });\n      } else {\n        document.write('<script src=\"../lib/json3.js\"><\\/script>');\n        document.write('<script src=\"test_json3.js\"><\\/script>');\n        window.onload = function () {\n          JSON.testSuite.run();\n        };\n      }\n    }());\n    </script>\n  </head>\n  <body>\n    <div id=\"suite\"></div>\n  </body>\n</html>"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/json3/test/test_extendscript.jsx",
    "content": "function main() {\n  var exports = this.Spec = {};\n  #include \"../vendor/spec/lib/spec.js\"\n\n  exports = this.Newton = {};\n  #include \"../vendor/spec/lib/newton.js\"\n\n  exports = this.JSON = {};\n  #include \"../lib/json3.js\"\n\n  try {\n    #include \"./test_json3.js\"\n  } catch (exception) {\n    $.bp();\n    print(exception.source.split('\\n')[exception.line - 1] + '\\n' + exception);\n  }\n}\n\nmain.call({\n  'load': function load(identifier, path) {\n    return this[identifier];\n  }\n});"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/json3/test/test_json3.js",
    "content": "/* JSON 3 Unit Test Suite | http://bestiejs.github.io/json3 */\n(function (root) {\n  var isLoader = typeof define == \"function\" && !!define.amd;\n  var isModule = typeof require == \"function\" && typeof exports == \"object\" && exports && !isLoader;\n  var isBrowser = \"window\" in root && root.window == root && typeof root.navigator != \"undefined\";\n  var isEngine = !isBrowser && !isModule && typeof root.load == \"function\";\n\n  var load = function load(module, path) {\n    return root[module] || (isModule ? require(path) : isEngine ?\n      (root.load(path.replace(/\\.js$/, \"\") + \".js\"), root[module]) : null);\n  };\n\n  // Load Spec, Newton, and JSON 3.\n  var Spec = load(\"Spec\", \"./../vendor/spec/lib/spec\"), Newton = load(\"Newton\", \"./../vendor/spec/lib/newton\"), JSON = load(\"JSON\", \"../lib/json3\");\n  \n  // The ExtendScript engine doesn't support named exceptions.\n  var supportsNamedExceptions = new SyntaxError().name == \"SyntaxError\";\n\n  // Create the test suite.\n  var testSuite = JSON.testSuite = new Spec.Suite(\"JSON 3 Unit Tests\");\n\n  // Create and attach the logger event handler.\n  testSuite.on(\"all\", isBrowser ? Newton.createReport(\"suite\") : Newton.createConsole(function (value) {\n    if (typeof console != \"undefined\" && console.log) {\n      console.log(value);\n    } else if (typeof print == \"function\" && !isBrowser) {\n      // In browsers, the global `print` function prints the current page.\n      print(value);\n    } else {\n      throw value;\n    }\n  }));\n\n  // Ensures that `JSON.parse` throws an exception when parsing the given\n  // `source` string.\n  Spec.Test.prototype.parseError = function (source, message, callback) {\n    return this.error(function () {\n      JSON.parse(source, callback);\n    }, function (exception) {\n      return supportsNamedExceptions ? exception.name == \"SyntaxError\" : true;\n    }, message);\n  };\n\n  // Ensures that `JSON.parse` parses the given source string correctly.\n  Spec.Test.prototype.parses = function (expected, source, message, callback) {\n    return this.deepEqual(JSON.parse(source, callback), expected, message);\n  };\n\n  // Ensures that `JSON.stringify` serializes the given object correctly.\n  Spec.Test.prototype.serializes = function (expected, value, message, filter, width) {\n    return this.strictEqual(JSON.stringify(value, filter, width), expected, message);\n  };\n\n  // Ensures that `JSON.stringify` throws a `TypeError` if the given object\n  // contains a circular reference.\n  Spec.Test.prototype.cyclicError = function (value, message) {\n    return this.error(function () {\n      JSON.stringify(value);\n    }, function (exception) {\n      return supportsNamedExceptions ? exception.name == \"TypeError\" : true;\n    }, message);\n  };\n\n  // Tests\n  // -----\n\n  testSuite.addTest(\"`parse`: Empty Source Strings\", function () {\n    this.parseError(\"\", \"Empty JSON source string\");\n    this.parseError(\"\\n\\n\\r\\n\", \"Source string containing only line terminators\");\n    this.parseError(\" \", \"Source string containing a single space character\");\n    this.parseError(\" \", \"Source string containing multiple space characters\");\n    this.done(4);\n  });\n\n  testSuite.addTest(\"`parse`: Whitespace\", function (test) {\n    // The only valid JSON whitespace characters are tabs, spaces, and line\n    // terminators. All other Unicode category `Z` (`Zs`, `Zl`, and `Zp`)\n    // characters are invalid (note that the `Zs` category includes the\n    // space character).\n    var characters = [\"{\\u00a0}\", \"{\\u1680}\", \"{\\u180e}\", \"{\\u2000}\", \"{\\u2001}\",\n      \"{\\u2002}\", \"{\\u2003}\", \"{\\u2004}\", \"{\\u2005}\", \"{\\u2006}\", \"{\\u2007}\",\n      \"{\\u2008}\", \"{\\u2009}\", \"{\\u200a}\", \"{\\u202f}\", \"{\\u205f}\", \"{\\u3000}\",\n      \"{\\u2028}\", \"{\\u2029}\"];\n\n    Spec.forEach(characters, function (value) {\n      test.parseError(value, \"Source string containing an invalid Unicode whitespace character\");\n    });\n\n    this.parseError(\"{\\u000b}\", \"Source string containing a vertical tab\");\n    this.parseError(\"{\\u000c}\", \"Source string containing a form feed\");\n    this.parseError(\"{\\ufeff}\", \"Source string containing a byte-order mark\");\n\n    this.parses({}, \"{\\r\\n}\", \"Source string containing a CRLF line ending\");\n    this.parses({}, \"{\\n\\n\\r\\n}\", \"Source string containing multiple line terminators\");\n    this.parses({}, \"{\\t}\", \"Source string containing a tab character\");\n    this.parses({}, \"{ }\", \"Source string containing a space character\");\n    this.done(26);\n  });\n\n  testSuite.addTest(\"`parse`: Octal Values\", function (test) {\n    // `08` and `018` are invalid octal values.\n    Spec.forEach([\"00\", \"01\", \"02\", \"03\", \"04\", \"05\", \"06\", \"07\", \"010\", \"011\", \"08\", \"018\"], function (value) {\n      test.parseError(value, \"Octal literal\");\n      test.parseError(\"-\" + value, \"Negative octal literal\");\n      test.parseError('\"\\\\' + value + '\"', \"Octal escape sequence in a string\");\n      test.parseError('\"\\\\x' + value + '\"', \"Hex escape sequence in a string\");\n    });\n    this.done(48);\n  });\n\n  testSuite.addTest(\"`parse`: Numeric Literals\", function () {\n    this.parses(100, \"100\", \"Integer\");\n    this.parses(-100, \"-100\", \"Negative integer\");\n    this.parses(10.5, \"10.5\", \"Float\");\n    this.parses(-3.141, \"-3.141\", \"Negative float\");\n    this.parses(0.625, \"0.625\", \"Decimal\");\n    this.parses(-0.03125, \"-0.03125\", \"Negative decimal\");\n    this.parses(1000, \"1e3\", \"Exponential\");\n    this.parses(100, \"1e+2\", \"Positive exponential\");\n    this.parses(-0.01, \"-1e-2\", \"Negative exponential\");\n    this.parses(3125, \"0.03125e+5\", \"Decimalized exponential\");\n    this.parses(100, \"1E2\", \"Case-insensitive exponential delimiter\");\n\n    this.parseError(\"+1\", \"Leading `+`\");\n    this.parseError(\"1.\", \"Trailing decimal point\");\n    this.parseError(\".1\", \"Leading decimal point\");\n    this.parseError(\"1e\", \"Missing exponent\");\n    this.parseError(\"1e-\", \"Missing signed exponent\");\n    this.parseError(\"--1\", \"Leading `--`\");\n    this.parseError(\"1-+\", \"Trailing `-+`\");\n    this.parseError(\"0xaf\", \"Hex literal\");\n\n    // The native `JSON.parse` implementation in IE 9 allows this syntax, but\n    // the feature tests should detect the broken implementation.\n    this.parseError(\"- 5\", \"Invalid negative sign\");\n\n    this.done(20);\n  });\n\n  testSuite.addTest(\"`parse`: String Literals\", function (test) {\n    var expected = 48, controlCharacters = [\"\\u0001\", \"\\u0002\", \"\\u0003\",\n      \"\\u0004\", \"\\u0005\", \"\\u0006\", \"\\u0007\", \"\\b\", \"\\t\", \"\\n\", \"\\u000b\", \"\\f\",\n      \"\\r\", \"\\u000e\", \"\\u000f\", \"\\u0010\", \"\\u0011\", \"\\u0012\", \"\\u0013\",\n      \"\\u0014\", \"\\u0015\", \"\\u0016\", \"\\u0017\", \"\\u0018\", \"\\u0019\", \"\\u001a\",\n      \"\\u001b\", \"\\u001c\", \"\\u001d\", \"\\u001e\", \"\\u001f\"];\n\n    // Opera 7 discards null characters in strings.\n    if (\"\\0\".length) {\n      expected += 1;\n      controlCharacters.push(\"\\u0000\");\n    }\n\n    this.parses(\"value\", '\"value\"', \"Double-quoted string literal\");\n    this.parses(\"\", '\"\"', \"Empty string literal\");\n\n    this.parses(\"\\u2028\", '\"\\\\u2028\"', \"String containing an escaped Unicode line separator\");\n    this.parses(\"\\u2029\", '\"\\\\u2029\"', \"String containing an escaped Unicode paragraph separator\");\n    // ExtendScript doesn't handle surrogate pairs correctly; attempting to\n    // parse `\"\\ud834\\udf06\"` will throw an uncatchable error (issue #29).\n    this.parses(\"\\ud834\\udf06\", '\"\\ud834\\udf06\"', \"String containing an unescaped Unicode surrogate pair\");\n    this.parses(\"\\u0001\", '\"\\\\u0001\"', \"String containing an escaped ASCII control character\");\n    this.parses(\"\\b\", '\"\\\\b\"', \"String containing an escaped backspace\");\n    this.parses(\"\\f\", '\"\\\\f\"', \"String containing an escaped form feed\");\n    this.parses(\"\\n\", '\"\\\\n\"', \"String containing an escaped line feed\");\n    this.parses(\"\\r\", '\"\\\\r\"', \"String containing an escaped carriage return\");\n    this.parses(\"\\t\", '\"\\\\t\"', \"String containing an escaped tab\");\n\n    this.parses(\"hello/world\", '\"hello\\\\/world\"', \"String containing an escaped solidus\");\n    this.parses(\"hello\\\\world\", '\"hello\\\\\\\\world\"', \"String containing an escaped reverse solidus\");\n    this.parses(\"hello\\\"world\", '\"hello\\\\\"world\"', \"String containing an escaped double-quote character\");\n\n    this.parseError(\"'hello'\", \"Single-quoted string literal\");\n    this.parseError('\"\\\\x61\"', \"String containing a hex escape sequence\");\n    this.parseError('\"hello \\r\\n world\"', \"String containing an unescaped CRLF line ending\");\n\n    Spec.forEach(controlCharacters, function (value) {\n      test.parseError('\"' + value + '\"', \"String containing an unescaped ASCII control character\");\n    });\n\n    this.done(expected);\n  });\n\n  testSuite.addTest(\"`parse`: Array Literals\", function () {\n    this.parseError(\"[1, 2, 3,]\", \"Trailing comma in array literal\");\n    this.parses([1, 2, [3, [4, 5]], 6, [true, false], [null], [[]]], \"[1, 2, [3, [4, 5]], 6, [true, false], [null], [[]]]\", \"Nested arrays\");\n    this.parses([{}], \"[{}]\", \"Array containing empty object literal\");\n    this.parses([100, true, false, null, {\"a\": [\"hello\"], \"b\": [\"world\"]}, [0.01]], \"[1e2, true, false, null, {\\\"a\\\": [\\\"hello\\\"], \\\"b\\\": [\\\"world\\\"]}, [1e-2]]\", \"Mixed array\");\n    this.done(4);\n  });\n\n  testSuite.addTest(\"`parse`: Object Literals\", function () {\n    this.parses({\"hello\": \"world\"}, \"{\\\"hello\\\": \\\"world\\\"}\", \"Object literal containing one member\");\n    this.parses({\"hello\": \"world\", \"foo\": [\"bar\", true], \"fox\": {\"quick\": true, \"purple\": false}}, \"{\\\"hello\\\": \\\"world\\\", \\\"foo\\\": [\\\"bar\\\", true], \\\"fox\\\": {\\\"quick\\\": true, \\\"purple\\\": false}}\", \"Object literal containing multiple members\");\n\n    this.parseError(\"{key: 1}\", \"Unquoted identifier used as a property name\");\n    this.parseError(\"{false: 1}\", \"`false` used as a property name\");\n    this.parseError(\"{true: 1}\", \"`true` used as a property name\");\n    this.parseError(\"{null: 1}\", \"`null` used as a property name\");\n    this.parseError(\"{'key': 1}\", \"Single-quoted string used as a property name\");\n    this.parseError(\"{1: 2, 3: 4}\", \"Number used as a property name\");\n\n    this.parseError(\"{\\\"hello\\\": \\\"world\\\", \\\"foo\\\": \\\"bar\\\",}\", \"Trailing comma in object literal\");\n    this.done(9);\n  });\n\n  // JavaScript expressions should never be evaluated, as JSON 3 does not use\n  // `eval`.\n  testSuite.addTest(\"`parse`: Invalid Expressions\", function (test) {\n    Spec.forEach([\"1 + 1\", \"1 * 2\", \"var value = 123;\", \"{});value = 123;({}\", \"call()\", \"1, 2, 3, \\\"value\\\"\"], function (expression) {\n      test.parseError(expression, \"Source string containing a JavaScript expression\");\n    });\n    this.done(6);\n  });\n\n  testSuite.addTest(\"`stringify` and `parse`: Optional Arguments\", function () {\n    this.parses({\"a\": 1, \"b\": 16}, '{\"a\": 1, \"b\": \"10000\"}', \"Callback function provided\", function (key, value) {\n      return typeof value == \"string\" ? parseInt(value, 2) : value;\n    });\n    this.serializes(\"{\\n  \\\"bar\\\": 456\\n}\", {\"foo\": 123, \"bar\": 456}, \"Object; optional `filter` and `whitespace` arguments\", [\"bar\"], 2);\n    // Test adapted from the Opera JSON test suite via Ken Snyder.\n    // See http://testsuites.opera.com/JSON/correctness/scripts/045.js\n    // The regular expression is necessary because the ExtendScript engine\n    // only approximates pi to 14 decimal places (ES 3 and ES 5 approximate\n    // pi to 15 places).\n    this.ok(/^\\{\"PI\":3\\.\\d{14,15}\\}$/.test(JSON.stringify(Math, [\"PI\"])), \"List of non-enumerable property names specified as the `filter` argument\");\n    this.equal(3, JSON.parse(\"[1, 2, 3]\", function (key, value) {\n      if (typeof value == \"object\" && value) {\n        return value;\n      }\n    }).length, \"Issue #10: `walk` should not use `splice` when removing an array element\");\n    this.done(4);\n  });\n\n  testSuite.addTest(\"`stringify`\", function () {\n    var expected = 29;\n\n    // Special values.\n    this.serializes(\"null\", null, \"`null` is represented literally\");\n    this.serializes(\"null\", 1 / 0, \"`Infinity` is serialized as `null`\");\n    this.serializes(\"null\", 0 / 0, \"`NaN` is serialized as `null`\");\n    this.serializes(\"null\", -1 / 0, \"`-Infinity` is serialized as `null`\");\n    this.serializes(\"true\", true, \"Boolean primitives are represented literally\");\n    this.serializes(\"false\", new Boolean(false), \"Boolean objects are represented literally\");\n    this.serializes('\"\\\\\\\\\\\\\"How\\\\bquickly\\\\tdaft\\\\njumping\\\\fzebras\\\\rvex\\\\\"\"', new String('\\\\\"How\\bquickly\\tdaft\\njumping\\fzebras\\rvex\"'), \"All control characters in strings are escaped\");\n\n    this.serializes(\"[false,1,\\\"Kit\\\"]\", [new Boolean, new Number(1), new String(\"Kit\")], \"Arrays are serialized recursively\");\n    this.serializes(\"[null]\", [void 0], \"`[undefined]` is serialized as `[null]`\");\n\n    // Property enumeration is implementation-dependent.\n    var value = {\n      \"jdalton\": [\"John-David\", 29],\n      \"kitcambridge\": [\"Kit\", 18],\n      \"mathias\": [\"Mathias\", 23]\n    };\n    this.parses(value, JSON.stringify(value), \"Objects are serialized recursively\");\n\n    // Complex cyclic structures.\n    value = { \"foo\": { \"b\": { \"foo\": { \"c\": { \"foo\": null} } } } };\n    this.serializes('{\"foo\":{\"b\":{\"foo\":{\"c\":{\"foo\":null}}}}}', value, \"Nested objects containing identically-named properties should serialize correctly\");\n\n    var S = [], N = {};\n    S.push(N, N);\n    this.serializes('[{},{}]', S, \"Objects containing duplicate references should not throw a `TypeError`\");\n\n    value.foo.b.foo.c.foo = value;\n    this.cyclicError(value, \"Objects containing complex circular references should throw a `TypeError`\");\n\n    // Sparse arrays.\n    value = [];\n    value[5] = 1;\n    this.serializes(\"[null,null,null,null,null,1]\", value, \"Sparse arrays should serialize correctly\");\n\n    // Dates.\n    this.serializes('\"1994-07-03T00:00:00.000Z\"', new Date(Date.UTC(1994, 6, 3)), \"Dates should be serialized according to the simplified date time string format\");\n    this.serializes('\"1993-06-02T02:10:28.224Z\"', new Date(Date.UTC(1993, 5, 2, 2, 10, 28, 224)), \"The date time string should conform to the format outlined in the spec\");\n    this.serializes('\"-271821-04-20T00:00:00.000Z\"', new Date(-8.64e15), \"The minimum valid date value should serialize correctly\");\n    this.serializes('\"+275760-09-13T00:00:00.000Z\"', new Date(8.64e15), \"The maximum valid date value should serialize correctly\");\n    this.serializes('\"+010000-01-01T00:00:00.000Z\"', new Date(Date.UTC(10000, 0, 1)), \"https://bugs.ecmascript.org/show_bug.cgi?id=119\");\n\n    // Tests based on research by @Yaffle. See kriskowal/es5-shim#111.\n    this.serializes('\"1969-12-31T23:59:59.999Z\"', new Date(-1), \"Millisecond values < 1000 should be serialized correctly\");\n    this.serializes('\"-000001-01-01T00:00:00.000Z\"', new Date(-621987552e5), \"Years prior to 0 should be serialized as extended years\");\n    this.serializes('\"+010000-01-01T00:00:00.000Z\"', new Date(2534023008e5), \"Years after 9999 should be serialized as extended years\");\n    this.serializes('\"-109252-01-01T10:37:06.708Z\"', new Date(-3509827334573292), \"Issue #4: Opera > 9.64 should correctly serialize a date with a year of `-109252`\");\n\n    // Opera 7 normalizes dates with invalid time values to represent the\n    // current date.\n    value = new Date(\"Kit\");\n    if (!isFinite(value)) {\n      expected += 1;\n      this.serializes(\"null\", value, \"Invalid dates should serialize as `null`\");\n    }\n\n    // Additional arguments.\n    this.serializes(\"[\\n  1,\\n  2,\\n  3,\\n  [\\n    4,\\n    5\\n  ]\\n]\", [1, 2, 3, [4, 5]], \"Nested arrays; optional `whitespace` argument\", null, \"  \");\n    this.serializes(\"[]\", [], \"Empty array; optional string `whitespace` argument\", null, \"  \");\n    this.serializes(\"{}\", {}, \"Empty object; optional numeric `whitespace` argument\", null, 2);\n    this.serializes(\"[\\n  1\\n]\", [1], \"Single-element array; optional numeric `whitespace` argument\", null, 2);\n    this.serializes(\"{\\n  \\\"foo\\\": 123\\n}\", { \"foo\": 123 }, \"Single-member object; optional string `whitespace` argument\", null, \"  \");\n    this.serializes(\"{\\n  \\\"foo\\\": {\\n    \\\"bar\\\": [\\n      123\\n    ]\\n  }\\n}\", {\"foo\": {\"bar\": [123]}}, \"Nested objects; optional numeric `whitespace` argument\", null, 2);\n\n    this.done(expected);\n  });\n\n  /*\n   * The following tests are adapted from the ECMAScript 5 Conformance Suite.\n   * Copyright 2009, Microsoft Corporation. Distributed under the New BSD License.\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   *\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 Microsoft 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, THE\n   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n   * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n   * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n   * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n   * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n   * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n   * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n   * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n   * POSSIBILITY OF SUCH DAMAGE.\n  */\n  testSuite.addTest(\"ECMAScript 5 Conformance\", function () {\n    var value = { \"a1\": { \"b1\": [1, 2, 3, 4], \"b2\": { \"c1\": 1, \"c2\": 2 } }, \"a2\": \"a2\" };\n\n    // Section 15.12.1.1: The JSON Grammar.\n    // ------------------------------------\n\n    // Tests 15.12.1.1-0-1 thru 15.12.1.1-0-8.\n    this.parseError(\"12\\t\\r\\n 34\", \"Valid whitespace characters may not separate two discrete tokens\");\n    this.parseError(\"\\u000b1234\", \"The vertical tab is not a valid whitespace character\");\n    this.parseError(\"\\u000c1234\", \"The form feed is not a valid whitespace character\");\n    this.parseError(\"\\u00a01234\", \"The non-breaking space is not a valid whitespace character\");\n    this.parseError(\"\\u200b1234\", \"The zero-width space is not a valid whitespace character\");\n    this.parseError(\"\\ufeff1234\", \"The byte order mark (zero-width non-breaking space) is not a valid whitespace character\");\n    this.parseError(\"\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u30001234\", \"Other Unicode category `Z` characters are not valid whitespace characters\");\n    this.parseError(\"\\u2028\\u20291234\", \"The line (U+2028) and paragraph (U+2029) separators are not valid whitespace characters\");\n\n    // Test 15.12.1.1-0-9.\n    this.parses({ \"property\": {}, \"prop2\": [true, null, 123.456] },\n      '\\t\\r \\n{\\t\\r \\n' +\n      '\"property\"\\t\\r \\n:\\t\\r \\n{\\t\\r \\n}\\t\\r \\n,\\t\\r \\n' +\n      '\"prop2\"\\t\\r \\n:\\t\\r \\n' +\n        '[\\t\\r \\ntrue\\t\\r \\n,\\t\\r \\nnull\\t\\r \\n,123.456\\t\\r \\n]' +\n      '\\t\\r \\n}\\t\\r \\n',\n    \"Valid whitespace characters may precede and follow all tokens\");\n\n    // Tests 15.12.1.1-g1-1 thru 15.12.1.1-g1-4.\n    this.parses(1234, \"\\t1234\", \"Leading tab characters should be ignored\");\n    this.parseError(\"12\\t34\", \"A tab character may not separate two disparate tokens\");\n    this.parses(1234, \"\\r1234\", \"Leading carriage returns should be ignored\");\n    this.parseError(\"12\\r34\", \"A carriage return may not separate two disparate tokens\");\n    this.parses(1234, \"\\n1234\", \"Leading line feeds should be ignored\");\n    this.parseError(\"12\\n34\", \"A line feed may not separate two disparate tokens\");\n    this.parses(1234, \" 1234\", \"Leading space characters should be ignored\");\n    this.parseError(\"12 34\", \"A space character may not separate two disparate tokens\");\n\n    // Tests 15.12.1.1-g2-1 thru 15.12.1.1-g2-5.\n    this.parses(\"abc\", '\"abc\"', \"Strings must be enclosed in double quotes\");\n    this.parseError(\"'abc'\", \"Single-quoted strings are not permitted\");\n    // Note: the original test 15.12.1.1-g2-3 (`\"\\u0022abc\\u0022\"`) is incorrect,\n    // as the JavaScript interpreter will always convert `\\u0022` to `\"`.\n    this.parseError(\"\\\\u0022abc\\\\u0022\", \"Unicode-escaped double quote delimiters are not permitted\");\n    this.parseError('\"ab'+\"c'\", \"Strings must terminate with a double quote character\");\n    this.parses(\"\", '\"\"', \"Strings may be empty\");\n\n    // Tests 15.12.1.1-g4-1 thru 15.12.1.1-g4-4.\n    this.parseError('\"\\u0000\\u0001\\u0002\\u0003\\u0004\\u0005\\u0006\\u0007\"', \"Unescaped control characters in the range [U+0000, U+0007] are not permitted within strings\");\n    this.parseError('\"\\u0008\\u0009\\u000a\\u000b\\u000c\\u000d\\u000e\\u000f\"', \"Unescaped control characters in the range [U+0008, U+000F] are not permitted within strings\");\n    this.parseError('\"\\u0010\\u0011\\u0012\\u0013\\u0014\\u0015\\u0016\\u0017\"', \"Unescaped control characters in the range [U+0010, U+0017] are not permitted within strings\");\n    this.parseError('\"\\u0018\\u0019\\u001a\\u001b\\u001c\\u001d\\u001e\\u001f\"', \"Unescaped control characters in the range [U+0018, U+001F] are not permitted within strings\");\n\n    // Tests 15.12.1.1-g5-1 thru 15.12.1.1-g5-3.\n    this.parses(\"X\", '\"\\\\u0058\"', \"Unicode escape sequences are permitted within strings\");\n    this.parseError('\"\\\\u005\"', \"Unicode escape sequences may not comprise fewer than four hexdigits\");\n    this.parseError('\"\\\\u0X50\"', \"Unicode escape sequences may not contain non-hex characters\");\n\n    // Tests 15.12.1.1-g6-1 thru 15.12.1.1-g6-7.\n    this.parses(\"/\", '\"\\\\/\"', \"Escaped solidus\");\n    this.parses(\"\\\\\", '\"\\\\\\\\\"', \"Escaped reverse solidus\");\n    this.parses(\"\\b\", '\"\\\\b\"', \"Escaped backspace\");\n    this.parses(\"\\f\", '\"\\\\f\"', \"Escaped form feed\");\n    this.parses(\"\\n\", '\"\\\\n\"', \"Escaped line feed\");\n    this.parses(\"\\r\", '\"\\\\r\"', \"Escaped carriage return\");\n    this.parses(\"\\t\", '\"\\\\t\"', \"Escaped tab\");\n\n    // Section 15.12.3: `JSON.stringify()`.\n    // ------------------------------------\n\n    // Test 15.12.3-11-1 thru 5.12.3-11-15.\n    this.serializes(void 0, void 0, \"`JSON.stringify(undefined)` should return `undefined`\");\n    this.serializes('\"replacement\"', void 0, \"The `JSON.stringify` callback function can be called on a top-level `undefined` value\", function () {\n      return \"replacement\";\n    });\n    this.serializes('\"a string\"', \"a string\", \"`JSON.stringify` should serialize top-level string primitives\");\n    this.serializes(\"123\", 123, \"`JSON.stringify` should serialize top-level number primitives\");\n    this.serializes(\"true\", true, \"`JSON.stringify` should serialize top-level Boolean primitives\");\n    this.serializes(\"null\", null, \"`JSON.stringify` should serialize top-level `null` values\");\n    this.serializes(\"42\", new Number(42), \"`JSON.stringify` should serialize top-level number objects\");\n    this.serializes('\"wrapped\"', new String(\"wrapped\"), \"`JSON.stringify` should serialize top-level string objects\");\n    this.serializes(\"false\", new Boolean(false), \"`JSON.stringify` should serialize top-level Boolean objects\");\n    this.serializes(void 0, 42, \"The `JSON.stringify` callback function may return `undefined` when called on a top-level number primitive\", function () {\n      return void 0;\n    });\n    this.serializes(void 0, { \"prop\": 1 }, \"The `JSON.stringify` callback function may return `undefined` when called on a top-level object\", function () {\n      return void 0;\n    });\n    this.serializes(\"[4,2]\", 42, \"The `JSON.stringify` callback function may return an array when called on a top-level number primitive\", function (key, value) {\n      return value == 42 ? [4, 2] : value;\n    });\n    this.serializes('{\"forty\":2}', 42, \"The `JSON.stringify` callback function may return an object literal when called on a top-level number primitive\", function (key, value) {\n      return value == 42 ? { \"forty\": 2 } : value;\n    });\n    this.serializes(void 0, function () {}, \"`JSON.stringify` should return `undefined` when called on a top-level function\");\n    this.serializes(\"99\", function () {}, \"The `JSON.stringify` callback function may return a number primitive when called on a top-level function\", function () {\n      return 99;\n    });\n\n    // Test 15.12.3-4-1.\n    this.serializes(\"[42]\", [42], \"`JSON.stringify` should ignore `filter` arguments that are not functions or arrays\", {});\n\n    // Test 15.12.3-5-a-i-1 and 15.12.3-5-b-i-1.\n    this.equal(JSON.stringify(value, null, new Number(5)), JSON.stringify(value, null, 5), \"Optional `width` argument: Number object and primitive width values should produce identical results\");\n    this.equal(JSON.stringify(value, null, new String(\"xxx\")), JSON.stringify(value, null, \"xxx\"), \"Optional `width` argument: String object and primitive width values should produce identical results\");\n\n    // Test 15.12.3-6-a-1 and 15.12.3-6-a-2.\n    this.equal(JSON.stringify(value, null, 10), JSON.stringify(value, null, 100), \"Optional `width` argument: The maximum numeric width value should be 10\");\n    this.equal(JSON.stringify(value, null, 5.99999), JSON.stringify(value, null, 5), \"Optional `width` argument: Numeric values should be converted to integers\");\n\n    // Test 15.12.3-6-b-1 and 15.12.3-6-b-4.\n    this.equal(JSON.stringify(value, null, 0.999999), JSON.stringify(value), \"Optional `width` argument: Numeric width values between 0 and 1 should be ignored\");\n    this.equal(JSON.stringify(value, null, 0), JSON.stringify(value), \"Optional `width` argument: Zero should be ignored\");\n    this.equal(JSON.stringify(value, null, -5), JSON.stringify(value), \"Optional `width` argument: Negative numeric values should be ignored\");\n    this.equal(JSON.stringify(value, null, 5), JSON.stringify(value, null, \"     \"), \"Optional `width` argument: Numeric width values in the range [1, 10] should produce identical results to that of string values containing `width` spaces\");\n\n    // Test 15.12.3-7-a-1.\n    this.equal(JSON.stringify(value, null, \"0123456789xxxxxxxxx\"), JSON.stringify(value, null, \"0123456789\"), \"Optional `width` argument: String width values longer than 10 characters should be truncated\");\n\n    // Test 15.12.3-8-a-1 thru 15.12.3-8-a-5.\n    this.equal(JSON.stringify(value, null, \"\"), JSON.stringify(value), \"Empty string `width` arguments should be ignored\");\n    this.equal(JSON.stringify(value, null, true), JSON.stringify(value), \"Boolean primitive `width` arguments should be ignored\");\n    this.equal(JSON.stringify(value, null, null), JSON.stringify(value), \"`null` `width` arguments should be ignored\");\n    this.equal(JSON.stringify(value, null, new Boolean(false)), JSON.stringify(value), \"Boolean object `width` arguments should be ignored\");\n    this.equal(JSON.stringify(value, null, value), JSON.stringify(value), \"Object literal `width` arguments should be ignored\");\n\n    // Test 15.12.3@2-2-b-i-1.\n    this.serializes('[\"fortytwo objects\"]', [{\n      \"prop\": 42,\n      \"toJSON\": function () {\n        return \"fortytwo objects\";\n      }\n    }], \"An object literal with a custom `toJSON` method nested within an array may return a string primitive for serialization\");\n\n    // Test 15.12.3@2-2-b-i-2.\n    this.serializes('[42]', [{\n      \"prop\": 42,\n      \"toJSON\": function () {\n        return new Number(42);\n      }\n    }], \"An object literal with a custom `toJSON` method nested within an array may return a number object for serialization\");\n\n    // Test 15.12.3@2-2-b-i-3.\n    this.serializes('[true]', [{\n      \"prop\": 42,\n      \"toJSON\": function () {\n        return new Boolean(true);\n      }\n    }], \"An object liyeral with a custom `toJSON` method nested within an array may return a Boolean object for serialization\");\n\n    // Test 15.12.3@2-3-a-1.\n    this.serializes('[\"fortytwo\"]', [42], \"The `JSON.stringify` callback function may return a string object when called on an array\", function (key, value) {\n      return value === 42 ? new String(\"fortytwo\") : value;\n    });\n\n    // Test 15.12.3@2-3-a-2.\n    this.serializes('[84]', [42], \"The `JSON.stringify` callback function may return a number object when called on an array\", function (key, value) {\n      return value === 42 ? new Number(84) : value;\n    });\n\n    // Test 15.12.3@2-3-a-3.\n    this.serializes('[false]', [42], \"The `JSON.stringify` callback function may return a Boolean object when called on an array\", function (key, value) {\n      return value === 42 ? new Boolean(false) : value;\n    });\n\n    // Test 15.12.3@4-1-2. 15.12.3@4-1-1 only tests whether an exception is\n    // thrown; the type of the exception is not checked.\n    value = {};\n    value.prop = value;\n    this.cyclicError(value, \"An object containing a circular reference should throw a `TypeError`\");\n\n    // Test 15.12.3@4-1-3, modified to ensure that a `TypeError` is thrown.\n    value = { \"p1\": { \"p2\": {} } };\n    value.p1.p2.prop = value;\n    this.cyclicError(value, \"A nested cyclic structure should throw a `TypeError`\");\n    this.done(74);\n  });\n\n  // This test may fail in certain implementations.\n  testSuite.addTest(\"Anticipated ECMAScript 6 Additions\", function () {\n    var expected = 0, value;\n    try {\n      value = {};\n      // IE 8 only allows properties to be defined on DOM elements. Credits:\n      // John-David Dalton and Juriy Zaytsev.\n      if ((Object.defineProperty(value, value, value), \"value\" in Object.getOwnPropertyDescriptor(value, value))) {\n        expected += 1;\n        value = [0, 1, 2, 3];\n        Object.prototype[3] = 3;\n        Object.defineProperty(value, 1, {\n          \"get\": function () {\n            Object.defineProperty(value, 4, { \"value\": 4 });\n            delete value[2];\n            delete value[3];\n            value[5] = 5;\n            return 1;\n          }\n        });\n        // Test by Jeff Walden and Allen Wirfs-Brock.\n        this.serializes('{\"0\":{\"1\":{\"3\":{\"3\":3}},\"3\":3},\"3\":3}', { 0: { 1: { 3: { 4: { 5: { 2: \"omitted\" } } } } } }, \"Issue #12: `parse` should process property name arrays sequentially\", value);\n      }\n    } catch (exception) {}\n    // Clean up.\n    delete Object.prototype[3];\n    this.done(expected);\n  });\n\n  testSuite.shuffle();\n\n  if (isLoader) {\n    define(function () {\n      return testSuite;\n    });\n  } else if (!isBrowser && (!isModule || (typeof module == \"object\" && module == require.main))) {\n    testSuite.run();\n  }\n})(this);"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/json3/vendor/benchmark.js",
    "content": "/*!\n * Benchmark.js v1.0.0 <http://benchmarkjs.com/>\n * Copyright 2010-2013 Mathias Bynens <http://mths.be/>\n * Based on JSLitmus.js, copyright Robert Kieffer <http://broofa.com/>\n * Modified by John-David Dalton <http://allyoucanleet.com/>\n * Available under MIT license <http://mths.be/mit>\n */\n;(function(window, undefined) {\n  'use strict';\n\n  /** Detect free variable `define` */\n  var freeDefine = typeof define == 'function' &&\n    typeof define.amd == 'object' && define.amd && define;\n\n  /** Detect free variable `exports` */\n  var freeExports = typeof exports == 'object' && exports;\n\n  /** Detect free variable `module` */\n  var freeModule = typeof module == 'object' && module && module.exports == freeExports && module;\n\n  /** Detect free variable `require` */\n  var freeRequire = typeof require == 'function' && require;\n\n  /** Detect free variable `global`, from Node.js or Browserified code, and use it as `window` */\n  var freeGlobal = typeof global == 'object' && global;\n  if (freeGlobal.global === freeGlobal || freeGlobal.window === freeGlobal) {\n    window = freeGlobal;\n  }\n\n  /** Used to assign each benchmark an incrimented id */\n  var counter = 0;\n\n  /** Used to detect primitive types */\n  var rePrimitive = /^(?:boolean|number|string|undefined)$/;\n\n  /** Used to assign default `context` object properties */\n  var contextProps = [\n    'Array', 'Date', 'Function', 'Math', 'Object', 'RegExp', 'String', '_',\n    'clearTimeout', 'chrome', 'chromium', 'document', 'java', 'navigator',\n    'performance', 'platform', 'process', 'runtime', 'setTimeout'\n  ];\n\n  /** Used to avoid hz of Infinity */\n  var divisors = {\n    '1': 4096,\n    '2': 512,\n    '3': 64,\n    '4': 8,\n    '5': 0\n  };\n\n  /**\n   * T-Distribution two-tailed critical values for 95% confidence\n   * http://www.itl.nist.gov/div898/handbook/eda/section3/eda3672.htm\n   */\n  var tTable = {\n    '1':  12.706,'2':  4.303, '3':  3.182, '4':  2.776, '5':  2.571, '6':  2.447,\n    '7':  2.365, '8':  2.306, '9':  2.262, '10': 2.228, '11': 2.201, '12': 2.179,\n    '13': 2.16,  '14': 2.145, '15': 2.131, '16': 2.12,  '17': 2.11,  '18': 2.101,\n    '19': 2.093, '20': 2.086, '21': 2.08,  '22': 2.074, '23': 2.069, '24': 2.064,\n    '25': 2.06,  '26': 2.056, '27': 2.052, '28': 2.048, '29': 2.045, '30': 2.042,\n    'infinity': 1.96\n  };\n\n  /**\n   * Critical Mann-Whitney U-values for 95% confidence\n   * http://www.saburchill.com/IBbiology/stats/003.html\n   */\n  var uTable = {\n    '5':  [0, 1, 2],\n    '6':  [1, 2, 3, 5],\n    '7':  [1, 3, 5, 6, 8],\n    '8':  [2, 4, 6, 8, 10, 13],\n    '9':  [2, 4, 7, 10, 12, 15, 17],\n    '10': [3, 5, 8, 11, 14, 17, 20, 23],\n    '11': [3, 6, 9, 13, 16, 19, 23, 26, 30],\n    '12': [4, 7, 11, 14, 18, 22, 26, 29, 33, 37],\n    '13': [4, 8, 12, 16, 20, 24, 28, 33, 37, 41, 45],\n    '14': [5, 9, 13, 17, 22, 26, 31, 36, 40, 45, 50, 55],\n    '15': [5, 10, 14, 19, 24, 29, 34, 39, 44, 49, 54, 59, 64],\n    '16': [6, 11, 15, 21, 26, 31, 37, 42, 47, 53, 59, 64, 70, 75],\n    '17': [6, 11, 17, 22, 28, 34, 39, 45, 51, 57, 63, 67, 75, 81, 87],\n    '18': [7, 12, 18, 24, 30, 36, 42, 48, 55, 61, 67, 74, 80, 86, 93, 99],\n    '19': [7, 13, 19, 25, 32, 38, 45, 52, 58, 65, 72, 78, 85, 92, 99, 106, 113],\n    '20': [8, 14, 20, 27, 34, 41, 48, 55, 62, 69, 76, 83, 90, 98, 105, 112, 119, 127],\n    '21': [8, 15, 22, 29, 36, 43, 50, 58, 65, 73, 80, 88, 96, 103, 111, 119, 126, 134, 142],\n    '22': [9, 16, 23, 30, 38, 45, 53, 61, 69, 77, 85, 93, 101, 109, 117, 125, 133, 141, 150, 158],\n    '23': [9, 17, 24, 32, 40, 48, 56, 64, 73, 81, 89, 98, 106, 115, 123, 132, 140, 149, 157, 166, 175],\n    '24': [10, 17, 25, 33, 42, 50, 59, 67, 76, 85, 94, 102, 111, 120, 129, 138, 147, 156, 165, 174, 183, 192],\n    '25': [10, 18, 27, 35, 44, 53, 62, 71, 80, 89, 98, 107, 117, 126, 135, 145, 154, 163, 173, 182, 192, 201, 211],\n    '26': [11, 19, 28, 37, 46, 55, 64, 74, 83, 93, 102, 112, 122, 132, 141, 151, 161, 171, 181, 191, 200, 210, 220, 230],\n    '27': [11, 20, 29, 38, 48, 57, 67, 77, 87, 97, 107, 118, 125, 138, 147, 158, 168, 178, 188, 199, 209, 219, 230, 240, 250],\n    '28': [12, 21, 30, 40, 50, 60, 70, 80, 90, 101, 111, 122, 132, 143, 154, 164, 175, 186, 196, 207, 218, 228, 239, 250, 261, 272],\n    '29': [13, 22, 32, 42, 52, 62, 73, 83, 94, 105, 116, 127, 138, 149, 160, 171, 182, 193, 204, 215, 226, 238, 249, 260, 271, 282, 294],\n    '30': [13, 23, 33, 43, 54, 65, 76, 87, 98, 109, 120, 131, 143, 154, 166, 177, 189, 200, 212, 223, 235, 247, 258, 270, 282, 293, 305, 317]\n  };\n\n  /*--------------------------------------------------------------------------*/\n\n  /**\n   * Create a new `Benchmark` function using the given `context` object.\n   *\n   * @static\n   * @memberOf Benchmark\n   * @param {Object} [context=window] The context object.\n   * @returns {Function} Returns the `Benchmark` function.\n   */\n  function runInContext(context) {\n    // exit early if unable to acquire lodash\n    var _ = context && context._ || req('lodash') || window._;\n    if (!_) {\n      Benchmark.runInContext = runInContext;\n      return Benchmark;\n    }\n    // Avoid issues with some ES3 environments that attempt to use values, named\n    // after built-in constructors like `Object`, for the creation of literals.\n    // ES5 clears this up by stating that literals must use built-in constructors.\n    // See http://es5.github.com/#x11.1.5.\n    context = context ? _.defaults(window.Object(), context, _.pick(window, contextProps)) : window;\n\n    /** Native constructor references */\n    var Array = context.Array,\n        Date = context.Date,\n        Function = context.Function,\n        Math = context.Math,\n        Object = context.Object,\n        RegExp = context.RegExp,\n        String = context.String;\n\n    /** Used for `Array` and `Object` method references */\n    var arrayRef = Array(),\n        objectRef = Object();\n\n    /** Native method shortcuts */\n    var abs = Math.abs,\n        clearTimeout = context.clearTimeout,\n        floor = Math.floor,\n        log = Math.log,\n        max = Math.max,\n        min = Math.min,\n        pow = Math.pow,\n        setTimeout = context.setTimeout,\n        shift = arrayRef.shift,\n        slice = arrayRef.slice,\n        sqrt = Math.sqrt,\n        toString = objectRef.toString;\n\n    /** Detect DOM document object */\n    var doc = isHostType(context, 'document') && context.document;\n\n    /** Used to access Wade Simmons' Node microtime module */\n    var microtimeObject = req('microtime');\n\n    /** Used to access the browser's high resolution timer */\n    var perfObject = isHostType(context, 'performance') && context.performance;\n\n    /** Used to call the browser's high resolution timer */\n    var perfName = perfObject && (\n      perfObject.now && 'now' ||\n      perfObject.webkitNow && 'webkitNow'\n    );\n\n    /** Used to access Node's high resolution timer */\n    var processObject = isHostType(context, 'process') && context.process;\n\n    /** Used to prevent a `removeChild` memory leak in IE < 9 */\n    var trash = doc && doc.createElement('div');\n\n    /** Used to integrity check compiled tests */\n    var uid = 'uid' + (+new Date);\n\n    /** Used to avoid infinite recursion when methods call each other */\n    var calledBy = {};\n\n    /**\n     * An object used to flag environments/features.\n     *\n     * @static\n     * @memberOf Benchmark\n     * @type Object\n     */\n    var support = {};\n\n    (function() {\n\n      /**\n       * Detect Adobe AIR.\n       *\n       * @memberOf Benchmark.support\n       * @type Boolean\n       */\n      support.air = isClassOf(context.runtime, 'ScriptBridgingProxyObject');\n\n      /**\n       * Detect if in a browser environment.\n       *\n       * @memberOf Benchmark.support\n       * @type Boolean\n       */\n      support.browser = doc && isHostType(context, 'navigator') && !isHostType(context, 'phantom');\n\n      /**\n       * Detect if Java is enabled/exposed.\n       *\n       * @memberOf Benchmark.support\n       * @type Boolean\n       */\n      support.java = isClassOf(context.java, 'JavaPackage');\n\n      /**\n       * Detect if the Timers API exists.\n       *\n       * @memberOf Benchmark.support\n       * @type Boolean\n       */\n      support.timeout = isHostType(context, 'setTimeout') && isHostType(context, 'clearTimeout');\n\n      /**\n       * Detect if functions support decompilation.\n       *\n       * @name decompilation\n       * @memberOf Benchmark.support\n       * @type Boolean\n       */\n      try {\n        // Safari 2.x removes commas in object literals\n        // from Function#toString results\n        // http://webk.it/11609\n        // Firefox 3.6 and Opera 9.25 strip grouping\n        // parentheses from Function#toString results\n        // http://bugzil.la/559438\n        support.decompilation = Function(\n          'return (' + (function(x) { return { 'x': '' + (1 + x) + '', 'y': 0 }; }) + ')'\n        )()(0).x === '1';\n      } catch(e) {\n        support.decompilation = false;\n      }\n    }());\n\n    /**\n     * Timer object used by `clock()` and `Deferred#resolve`.\n     *\n     * @private\n     * @type Object\n     */\n    var timer = {\n\n     /**\n      * The timer namespace object or constructor.\n      *\n      * @private\n      * @memberOf timer\n      * @type Function|Object\n      */\n      'ns': Date,\n\n     /**\n      * Starts the deferred timer.\n      *\n      * @private\n      * @memberOf timer\n      * @param {Object} deferred The deferred instance.\n      */\n      'start': null, // lazy defined in `clock()`\n\n     /**\n      * Stops the deferred timer.\n      *\n      * @private\n      * @memberOf timer\n      * @param {Object} deferred The deferred instance.\n      */\n      'stop': null // lazy defined in `clock()`\n    };\n\n    /*------------------------------------------------------------------------*/\n\n    /**\n     * The Benchmark constructor.\n     *\n     * @constructor\n     * @param {String} name A name to identify the benchmark.\n     * @param {Function|String} fn The test to benchmark.\n     * @param {Object} [options={}] Options object.\n     * @example\n     *\n     * // basic usage (the `new` operator is optional)\n     * var bench = new Benchmark(fn);\n     *\n     * // or using a name first\n     * var bench = new Benchmark('foo', fn);\n     *\n     * // or with options\n     * var bench = new Benchmark('foo', fn, {\n     *\n     *   // displayed by Benchmark#toString if `name` is not available\n     *   'id': 'xyz',\n     *\n     *   // called when the benchmark starts running\n     *   'onStart': onStart,\n     *\n     *   // called after each run cycle\n     *   'onCycle': onCycle,\n     *\n     *   // called when aborted\n     *   'onAbort': onAbort,\n     *\n     *   // called when a test errors\n     *   'onError': onError,\n     *\n     *   // called when reset\n     *   'onReset': onReset,\n     *\n     *   // called when the benchmark completes running\n     *   'onComplete': onComplete,\n     *\n     *   // compiled/called before the test loop\n     *   'setup': setup,\n     *\n     *   // compiled/called after the test loop\n     *   'teardown': teardown\n     * });\n     *\n     * // or name and options\n     * var bench = new Benchmark('foo', {\n     *\n     *   // a flag to indicate the benchmark is deferred\n     *   'defer': true,\n     *\n     *   // benchmark test function\n     *   'fn': function(deferred) {\n     *     // call resolve() when the deferred test is finished\n     *     deferred.resolve();\n     *   }\n     * });\n     *\n     * // or options only\n     * var bench = new Benchmark({\n     *\n     *   // benchmark name\n     *   'name': 'foo',\n     *\n     *   // benchmark test as a string\n     *   'fn': '[1,2,3,4].sort()'\n     * });\n     *\n     * // a test's `this` binding is set to the benchmark instance\n     * var bench = new Benchmark('foo', function() {\n     *   'My name is '.concat(this.name); // My name is foo\n     * });\n     */\n    function Benchmark(name, fn, options) {\n      var bench = this;\n\n      // allow instance creation without the `new` operator\n      if (bench == null || bench.constructor != Benchmark) {\n        return new Benchmark(name, fn, options);\n      }\n      // juggle arguments\n      if (_.isPlainObject(name)) {\n        // 1 argument (options)\n        options = name;\n      }\n      else if (_.isFunction(name)) {\n        // 2 arguments (fn, options)\n        options = fn;\n        fn = name;\n      }\n      else if (_.isPlainObject(fn)) {\n        // 2 arguments (name, options)\n        options = fn;\n        fn = null;\n        bench.name = name;\n      }\n      else {\n        // 3 arguments (name, fn [, options])\n        bench.name = name;\n      }\n      setOptions(bench, options);\n\n      bench.id || (bench.id = ++counter);\n      bench.fn == null && (bench.fn = fn);\n\n      bench.stats = cloneDeep(bench.stats);\n      bench.times = cloneDeep(bench.times);\n    }\n\n    /**\n     * The Deferred constructor.\n     *\n     * @constructor\n     * @memberOf Benchmark\n     * @param {Object} clone The cloned benchmark instance.\n     */\n    function Deferred(clone) {\n      var deferred = this;\n      if (deferred == null || deferred.constructor != Deferred) {\n        return new Deferred(clone);\n      }\n      deferred.benchmark = clone;\n      clock(deferred);\n    }\n\n    /**\n     * The Event constructor.\n     *\n     * @constructor\n     * @memberOf Benchmark\n     * @param {String|Object} type The event type.\n     */\n    function Event(type) {\n      var event = this;\n      return (event == null || event.constructor != Event)\n        ? new Event(type)\n        : (type instanceof Event\n            ? type\n            : _.extend(event, { 'timeStamp': +new Date }, typeof type == 'string' ? { 'type': type } : type)\n          );\n    }\n\n    /**\n     * The Suite constructor.\n     *\n     * @constructor\n     * @memberOf Benchmark\n     * @param {String} name A name to identify the suite.\n     * @param {Object} [options={}] Options object.\n     * @example\n     *\n     * // basic usage (the `new` operator is optional)\n     * var suite = new Benchmark.Suite;\n     *\n     * // or using a name first\n     * var suite = new Benchmark.Suite('foo');\n     *\n     * // or with options\n     * var suite = new Benchmark.Suite('foo', {\n     *\n     *   // called when the suite starts running\n     *   'onStart': onStart,\n     *\n     *   // called between running benchmarks\n     *   'onCycle': onCycle,\n     *\n     *   // called when aborted\n     *   'onAbort': onAbort,\n     *\n     *   // called when a test errors\n     *   'onError': onError,\n     *\n     *   // called when reset\n     *   'onReset': onReset,\n     *\n     *   // called when the suite completes running\n     *   'onComplete': onComplete\n     * });\n     */\n    function Suite(name, options) {\n      var suite = this;\n\n      // allow instance creation without the `new` operator\n      if (suite == null || suite.constructor != Suite) {\n        return new Suite(name, options);\n      }\n      // juggle arguments\n      if (isClassOf(name, 'Object')) {\n        // 1 argument (options)\n        options = name;\n      } else {\n        // 2 arguments (name [, options])\n        suite.name = name;\n      }\n      setOptions(suite, options);\n    }\n\n    /*------------------------------------------------------------------------*/\n\n    /**\n     * A deep clone utility.\n     *\n     * @private\n     * @param {Mixed} value The value to clone.\n     * @returns {Mixed} The cloned value.\n     */\n    var cloneDeep = _.partialRight(_.cloneDeep, function(value) {\n      // do not clone non-Object objects\n      return (typeof value == 'object' && !_.isArray(value) && !_.isPlainObject(value))\n        ? value\n        : undefined;\n    });\n\n    /**\n     * Creates a function from the given arguments string and body.\n     *\n     * @private\n     * @param {String} args The comma separated function arguments.\n     * @param {String} body The function body.\n     * @returns {Function} The new function.\n     */\n    function createFunction() {\n      // lazy define\n      createFunction = function(args, body) {\n        var result,\n            anchor = freeDefine ? freeDefine.amd : Benchmark,\n            prop = uid + 'createFunction';\n\n        runScript((freeDefine ? 'define.amd.' : 'Benchmark.') + prop + '=function(' + args + '){' + body + '}');\n        result = anchor[prop];\n        delete anchor[prop];\n        return result;\n      };\n      // fix JaegerMonkey bug\n      // http://bugzil.la/639720\n      createFunction = support.browser && (createFunction('', 'return\"' + uid + '\"') || noop)() == uid ? createFunction : Function;\n      return createFunction.apply(null, arguments);\n    }\n\n    /**\n     * Delay the execution of a function based on the benchmark's `delay` property.\n     *\n     * @private\n     * @param {Object} bench The benchmark instance.\n     * @param {Object} fn The function to execute.\n     */\n    function delay(bench, fn) {\n      bench._timerId = _.delay(fn, bench.delay * 1e3);\n    }\n\n    /**\n     * Destroys the given element.\n     *\n     * @private\n     * @param {Element} element The element to destroy.\n     */\n    function destroyElement(element) {\n      trash.appendChild(element);\n      trash.innerHTML = '';\n    }\n\n    /**\n     * Gets the name of the first argument from a function's source.\n     *\n     * @private\n     * @param {Function} fn The function.\n     * @returns {String} The argument name.\n     */\n    function getFirstArgument(fn) {\n      return (!_.has(fn, 'toString') &&\n        (/^[\\s(]*function[^(]*\\(([^\\s,)]+)/.exec(fn) || 0)[1]) || '';\n    }\n\n    /**\n     * Computes the geometric mean (log-average) of a sample.\n     * See http://en.wikipedia.org/wiki/Geometric_mean#Relationship_with_arithmetic_mean_of_logarithms.\n     *\n     * @private\n     * @param {Array} sample The sample.\n     * @returns {Number} The geometric mean.\n     */\n    function getGeometricMean(sample) {\n      return pow(Math.E, _.reduce(sample, function(sum, x) {\n        return sum + log(x);\n      }) / sample.length) || 0;\n    }\n\n    /**\n     * Computes the arithmetic mean of a sample.\n     *\n     * @private\n     * @param {Array} sample The sample.\n     * @returns {Number} The mean.\n     */\n    function getMean(sample) {\n      return (_.reduce(sample, function(sum, x) {\n        return sum + x;\n      }) / sample.length) || 0;\n    }\n\n    /**\n     * Gets the source code of a function.\n     *\n     * @private\n     * @param {Function} fn The function.\n     * @param {String} altSource A string used when a function's source code is unretrievable.\n     * @returns {String} The function's source code.\n     */\n    function getSource(fn, altSource) {\n      var result = altSource;\n      if (isStringable(fn)) {\n        result = String(fn);\n      } else if (support.decompilation) {\n        // escape the `{` for Firefox 1\n        result = (/^[^{]+\\{([\\s\\S]*)\\}\\s*$/.exec(fn) || 0)[1];\n      }\n      // trim string\n      result = (result || '').replace(/^\\s+|\\s+$/g, '');\n\n      // detect strings containing only the \"use strict\" directive\n      return /^(?:\\/\\*+[\\w|\\W]*?\\*\\/|\\/\\/.*?[\\n\\r\\u2028\\u2029]|\\s)*([\"'])use strict\\1;?$/.test(result)\n        ? ''\n        : result;\n    }\n\n    /**\n     * Checks if an object is of the specified class.\n     *\n     * @private\n     * @param {Mixed} value The value to check.\n     * @param {String} name The name of the class.\n     * @returns {Boolean} Returns `true` if the value is of the specified class, else `false`.\n     */\n    function isClassOf(value, name) {\n      return value != null && toString.call(value) == '[object ' + name + ']';\n    }\n\n    /**\n     * Host objects can return type values that are different from their actual\n     * data type. The objects we are concerned with usually return non-primitive\n     * types of \"object\", \"function\", or \"unknown\".\n     *\n     * @private\n     * @param {Mixed} object The owner of the property.\n     * @param {String} property The property to check.\n     * @returns {Boolean} Returns `true` if the property value is a non-primitive, else `false`.\n     */\n    function isHostType(object, property) {\n      if (object == null) {\n        return false;\n      }\n      var type = typeof object[property];\n      return !rePrimitive.test(type) && (type != 'object' || !!object[property]);\n    }\n\n    /**\n     * Checks if a value can be safely coerced to a string.\n     *\n     * @private\n     * @param {Mixed} value The value to check.\n     * @returns {Boolean} Returns `true` if the value can be coerced, else `false`.\n     */\n    function isStringable(value) {\n      return _.has(value, 'toString') || isClassOf(value, 'String');\n    }\n\n    /**\n     * A no-operation function.\n     *\n     * @private\n     */\n    function noop() {\n      // no operation performed\n    }\n\n    /**\n     * A wrapper around require() to suppress `module missing` errors.\n     *\n     * @private\n     * @param {String} id The module id.\n     * @returns {Mixed} The exported module or `null`.\n     */\n    function req(id) {\n      try {\n        var result = freeExports && freeRequire(id);\n      } catch(e) { }\n      return result || null;\n    }\n\n    /**\n     * Runs a snippet of JavaScript via script injection.\n     *\n     * @private\n     * @param {String} code The code to run.\n     */\n    function runScript(code) {\n      var anchor = freeDefine ? define.amd : Benchmark,\n          script = doc.createElement('script'),\n          sibling = doc.getElementsByTagName('script')[0],\n          parent = sibling.parentNode,\n          prop = uid + 'runScript',\n          prefix = '(' + (freeDefine ? 'define.amd.' : 'Benchmark.') + prop + '||function(){})();';\n\n      // Firefox 2.0.0.2 cannot use script injection as intended because it executes\n      // asynchronously, but that's OK because script injection is only used to avoid\n      // the previously commented JaegerMonkey bug.\n      try {\n        // remove the inserted script *before* running the code to avoid differences\n        // in the expected script element count/order of the document.\n        script.appendChild(doc.createTextNode(prefix + code));\n        anchor[prop] = function() { destroyElement(script); };\n      } catch(e) {\n        parent = parent.cloneNode(false);\n        sibling = null;\n        script.text = code;\n      }\n      parent.insertBefore(script, sibling);\n      delete anchor[prop];\n    }\n\n    /**\n     * A helper function for setting options/event handlers.\n     *\n     * @private\n     * @param {Object} bench The benchmark instance.\n     * @param {Object} [options={}] Options object.\n     */\n    function setOptions(bench, options) {\n      options = _.extend({}, bench.constructor.options, options);\n      bench.options = _.forOwn(options, function(value, key) {\n        if (value != null) {\n          // add event listeners\n          if (/^on[A-Z]/.test(key)) {\n            _.each(key.split(' '), function(key) {\n              bench.on(key.slice(2).toLowerCase(), value);\n            });\n          } else if (!_.has(bench, key)) {\n            bench[key] = cloneDeep(value);\n          }\n        }\n      });\n    }\n\n    /*------------------------------------------------------------------------*/\n\n    /**\n     * Handles cycling/completing the deferred benchmark.\n     *\n     * @memberOf Benchmark.Deferred\n     */\n    function resolve() {\n      var deferred = this,\n          clone = deferred.benchmark,\n          bench = clone._original;\n\n      if (bench.aborted) {\n        // cycle() -> clone cycle/complete event -> compute()'s invoked bench.run() cycle/complete\n        deferred.teardown();\n        clone.running = false;\n        cycle(deferred);\n      }\n      else if (++deferred.cycles < clone.count) {\n        clone.compiled.call(deferred, context, timer);\n      }\n      else {\n        timer.stop(deferred);\n        deferred.teardown();\n        delay(clone, function() { cycle(deferred); });\n      }\n    }\n\n    /*------------------------------------------------------------------------*/\n\n    /**\n     * A generic `Array#filter` like method.\n     *\n     * @static\n     * @memberOf Benchmark\n     * @param {Array} array The array to iterate over.\n     * @param {Function|String} callback The function/alias called per iteration.\n     * @param {Mixed} thisArg The `this` binding for the callback.\n     * @returns {Array} A new array of values that passed callback filter.\n     * @example\n     *\n     * // get odd numbers\n     * Benchmark.filter([1, 2, 3, 4, 5], function(n) {\n     *   return n % 2;\n     * }); // -> [1, 3, 5];\n     *\n     * // get fastest benchmarks\n     * Benchmark.filter(benches, 'fastest');\n     *\n     * // get slowest benchmarks\n     * Benchmark.filter(benches, 'slowest');\n     *\n     * // get benchmarks that completed without erroring\n     * Benchmark.filter(benches, 'successful');\n     */\n    function filter(array, callback, thisArg) {\n      if (callback === 'successful') {\n        // callback to exclude those that are errored, unrun, or have hz of Infinity\n        callback = function(bench) {\n          return bench.cycles && _.isFinite(bench.hz);\n        };\n      }\n      else if (callback === 'fastest' || callback === 'slowest') {\n        // get successful, sort by period + margin of error, and filter fastest/slowest\n        var result = filter(array, 'successful').sort(function(a, b) {\n          a = a.stats; b = b.stats;\n          return (a.mean + a.moe > b.mean + b.moe ? 1 : -1) * (callback === 'fastest' ? 1 : -1);\n        });\n\n        return _.filter(result, function(bench) {\n          return result[0].compare(bench) == 0;\n        });\n      }\n      return _.filter(array, callback, thisArg);\n    }\n\n    /**\n     * Converts a number to a more readable comma-separated string representation.\n     *\n     * @static\n     * @memberOf Benchmark\n     * @param {Number} number The number to convert.\n     * @returns {String} The more readable string representation.\n     */\n    function formatNumber(number) {\n      number = String(number).split('.');\n      return number[0].replace(/(?=(?:\\d{3})+$)(?!\\b)/g, ',') +\n        (number[1] ? '.' + number[1] : '');\n    }\n\n    /**\n     * Invokes a method on all items in an array.\n     *\n     * @static\n     * @memberOf Benchmark\n     * @param {Array} benches Array of benchmarks to iterate over.\n     * @param {String|Object} name The name of the method to invoke OR options object.\n     * @param {Mixed} [arg1, arg2, ...] Arguments to invoke the method with.\n     * @returns {Array} A new array of values returned from each method invoked.\n     * @example\n     *\n     * // invoke `reset` on all benchmarks\n     * Benchmark.invoke(benches, 'reset');\n     *\n     * // invoke `emit` with arguments\n     * Benchmark.invoke(benches, 'emit', 'complete', listener);\n     *\n     * // invoke `run(true)`, treat benchmarks as a queue, and register invoke callbacks\n     * Benchmark.invoke(benches, {\n     *\n     *   // invoke the `run` method\n     *   'name': 'run',\n     *\n     *   // pass a single argument\n     *   'args': true,\n     *\n     *   // treat as queue, removing benchmarks from front of `benches` until empty\n     *   'queued': true,\n     *\n     *   // called before any benchmarks have been invoked.\n     *   'onStart': onStart,\n     *\n     *   // called between invoking benchmarks\n     *   'onCycle': onCycle,\n     *\n     *   // called after all benchmarks have been invoked.\n     *   'onComplete': onComplete\n     * });\n     */\n    function invoke(benches, name) {\n      var args,\n          bench,\n          queued,\n          index = -1,\n          eventProps = { 'currentTarget': benches },\n          options = { 'onStart': noop, 'onCycle': noop, 'onComplete': noop },\n          result = _.toArray(benches);\n\n      /**\n       * Invokes the method of the current object and if synchronous, fetches the next.\n       */\n      function execute() {\n        var listeners,\n            async = isAsync(bench);\n\n        if (async) {\n          // use `getNext` as the first listener\n          bench.on('complete', getNext);\n          listeners = bench.events.complete;\n          listeners.splice(0, 0, listeners.pop());\n        }\n        // execute method\n        result[index] = _.isFunction(bench && bench[name]) ? bench[name].apply(bench, args) : undefined;\n        // if synchronous return true until finished\n        return !async && getNext();\n      }\n\n      /**\n       * Fetches the next bench or executes `onComplete` callback.\n       */\n      function getNext(event) {\n        var cycleEvent,\n            last = bench,\n            async = isAsync(last);\n\n        if (async) {\n          last.off('complete', getNext);\n          last.emit('complete');\n        }\n        // emit \"cycle\" event\n        eventProps.type = 'cycle';\n        eventProps.target = last;\n        cycleEvent = Event(eventProps);\n        options.onCycle.call(benches, cycleEvent);\n\n        // choose next benchmark if not exiting early\n        if (!cycleEvent.aborted && raiseIndex() !== false) {\n          bench = queued ? benches[0] : result[index];\n          if (isAsync(bench)) {\n            delay(bench, execute);\n          }\n          else if (async) {\n            // resume execution if previously asynchronous but now synchronous\n            while (execute()) { }\n          }\n          else {\n            // continue synchronous execution\n            return true;\n          }\n        } else {\n          // emit \"complete\" event\n          eventProps.type = 'complete';\n          options.onComplete.call(benches, Event(eventProps));\n        }\n        // When used as a listener `event.aborted = true` will cancel the rest of\n        // the \"complete\" listeners because they were already called above and when\n        // used as part of `getNext` the `return false` will exit the execution while-loop.\n        if (event) {\n          event.aborted = true;\n        } else {\n          return false;\n        }\n      }\n\n      /**\n       * Checks if invoking `Benchmark#run` with asynchronous cycles.\n       */\n      function isAsync(object) {\n        // avoid using `instanceof` here because of IE memory leak issues with host objects\n        var async = args[0] && args[0].async;\n        return Object(object).constructor == Benchmark && name == 'run' &&\n          ((async == null ? object.options.async : async) && support.timeout || object.defer);\n      }\n\n      /**\n       * Raises `index` to the next defined index or returns `false`.\n       */\n      function raiseIndex() {\n        index++;\n\n        // if queued remove the previous bench\n        if (queued && index > 0) {\n          shift.call(benches);\n        }\n        // if we reached the last index then return `false`\n        return (queued ? benches.length : index < result.length)\n          ? index\n          : (index = false);\n      }\n\n      // juggle arguments\n      if (_.isString(name)) {\n        // 2 arguments (array, name)\n        args = slice.call(arguments, 2);\n      } else {\n        // 2 arguments (array, options)\n        options = _.extend(options, name);\n        name = options.name;\n        args = _.isArray(args = 'args' in options ? options.args : []) ? args : [args];\n        queued = options.queued;\n      }\n\n      // start iterating over the array\n      if (raiseIndex() !== false) {\n        // emit \"start\" event\n        bench = result[index];\n        eventProps.type = 'start';\n        eventProps.target = bench;\n        options.onStart.call(benches, Event(eventProps));\n\n        // end early if the suite was aborted in an \"onStart\" listener\n        if (benches.aborted && benches.constructor == Suite && name == 'run') {\n          // emit \"cycle\" event\n          eventProps.type = 'cycle';\n          options.onCycle.call(benches, Event(eventProps));\n          // emit \"complete\" event\n          eventProps.type = 'complete';\n          options.onComplete.call(benches, Event(eventProps));\n        }\n        // else start\n        else {\n          if (isAsync(bench)) {\n            delay(bench, execute);\n          } else {\n            while (execute()) { }\n          }\n        }\n      }\n      return result;\n    }\n\n    /**\n     * Creates a string of joined array values or object key-value pairs.\n     *\n     * @static\n     * @memberOf Benchmark\n     * @param {Array|Object} object The object to operate on.\n     * @param {String} [separator1=','] The separator used between key-value pairs.\n     * @param {String} [separator2=': '] The separator used between keys and values.\n     * @returns {String} The joined result.\n     */\n    function join(object, separator1, separator2) {\n      var result = [],\n          length = (object = Object(object)).length,\n          arrayLike = length === length >>> 0;\n\n      separator2 || (separator2 = ': ');\n      _.each(object, function(value, key) {\n        result.push(arrayLike ? value : key + separator2 + value);\n      });\n      return result.join(separator1 || ',');\n    }\n\n    /*------------------------------------------------------------------------*/\n\n    /**\n     * Aborts all benchmarks in the suite.\n     *\n     * @name abort\n     * @memberOf Benchmark.Suite\n     * @returns {Object} The suite instance.\n     */\n    function abortSuite() {\n      var event,\n          suite = this,\n          resetting = calledBy.resetSuite;\n\n      if (suite.running) {\n        event = Event('abort');\n        suite.emit(event);\n        if (!event.cancelled || resetting) {\n          // avoid infinite recursion\n          calledBy.abortSuite = true;\n          suite.reset();\n          delete calledBy.abortSuite;\n\n          if (!resetting) {\n            suite.aborted = true;\n            invoke(suite, 'abort');\n          }\n        }\n      }\n      return suite;\n    }\n\n    /**\n     * Adds a test to the benchmark suite.\n     *\n     * @memberOf Benchmark.Suite\n     * @param {String} name A name to identify the benchmark.\n     * @param {Function|String} fn The test to benchmark.\n     * @param {Object} [options={}] Options object.\n     * @returns {Object} The benchmark instance.\n     * @example\n     *\n     * // basic usage\n     * suite.add(fn);\n     *\n     * // or using a name first\n     * suite.add('foo', fn);\n     *\n     * // or with options\n     * suite.add('foo', fn, {\n     *   'onCycle': onCycle,\n     *   'onComplete': onComplete\n     * });\n     *\n     * // or name and options\n     * suite.add('foo', {\n     *   'fn': fn,\n     *   'onCycle': onCycle,\n     *   'onComplete': onComplete\n     * });\n     *\n     * // or options only\n     * suite.add({\n     *   'name': 'foo',\n     *   'fn': fn,\n     *   'onCycle': onCycle,\n     *   'onComplete': onComplete\n     * });\n     */\n    function add(name, fn, options) {\n      var suite = this,\n          bench = new Benchmark(name, fn, options),\n          event = Event({ 'type': 'add', 'target': bench });\n\n      if (suite.emit(event), !event.cancelled) {\n        suite.push(bench);\n      }\n      return suite;\n    }\n\n    /**\n     * Creates a new suite with cloned benchmarks.\n     *\n     * @name clone\n     * @memberOf Benchmark.Suite\n     * @param {Object} options Options object to overwrite cloned options.\n     * @returns {Object} The new suite instance.\n     */\n    function cloneSuite(options) {\n      var suite = this,\n          result = new suite.constructor(_.extend({}, suite.options, options));\n\n      // copy own properties\n      _.forOwn(suite, function(value, key) {\n        if (!_.has(result, key)) {\n          result[key] = value && _.isFunction(value.clone)\n            ? value.clone()\n            : cloneDeep(value);\n        }\n      });\n      return result;\n    }\n\n    /**\n     * An `Array#filter` like method.\n     *\n     * @name filter\n     * @memberOf Benchmark.Suite\n     * @param {Function|String} callback The function/alias called per iteration.\n     * @returns {Object} A new suite of benchmarks that passed callback filter.\n     */\n    function filterSuite(callback) {\n      var suite = this,\n          result = new suite.constructor;\n\n      result.push.apply(result, filter(suite, callback));\n      return result;\n    }\n\n    /**\n     * Resets all benchmarks in the suite.\n     *\n     * @name reset\n     * @memberOf Benchmark.Suite\n     * @returns {Object} The suite instance.\n     */\n    function resetSuite() {\n      var event,\n          suite = this,\n          aborting = calledBy.abortSuite;\n\n      if (suite.running && !aborting) {\n        // no worries, `resetSuite()` is called within `abortSuite()`\n        calledBy.resetSuite = true;\n        suite.abort();\n        delete calledBy.resetSuite;\n      }\n      // reset if the state has changed\n      else if ((suite.aborted || suite.running) &&\n          (suite.emit(event = Event('reset')), !event.cancelled)) {\n        suite.running = false;\n        if (!aborting) {\n          invoke(suite, 'reset');\n        }\n      }\n      return suite;\n    }\n\n    /**\n     * Runs the suite.\n     *\n     * @name run\n     * @memberOf Benchmark.Suite\n     * @param {Object} [options={}] Options object.\n     * @returns {Object} The suite instance.\n     * @example\n     *\n     * // basic usage\n     * suite.run();\n     *\n     * // or with options\n     * suite.run({ 'async': true, 'queued': true });\n     */\n    function runSuite(options) {\n      var suite = this;\n\n      suite.reset();\n      suite.running = true;\n      options || (options = {});\n\n      invoke(suite, {\n        'name': 'run',\n        'args': options,\n        'queued': options.queued,\n        'onStart': function(event) {\n          suite.emit(event);\n        },\n        'onCycle': function(event) {\n          var bench = event.target;\n          if (bench.error) {\n            suite.emit({ 'type': 'error', 'target': bench });\n          }\n          suite.emit(event);\n          event.aborted = suite.aborted;\n        },\n        'onComplete': function(event) {\n          suite.running = false;\n          suite.emit(event);\n        }\n      });\n      return suite;\n    }\n\n    /*------------------------------------------------------------------------*/\n\n    /**\n     * Executes all registered listeners of the specified event type.\n     *\n     * @memberOf Benchmark, Benchmark.Suite\n     * @param {String|Object} type The event type or object.\n     * @returns {Mixed} Returns the return value of the last listener executed.\n     */\n    function emit(type) {\n      var listeners,\n          object = this,\n          event = Event(type),\n          events = object.events,\n          args = (arguments[0] = event, arguments);\n\n      event.currentTarget || (event.currentTarget = object);\n      event.target || (event.target = object);\n      delete event.result;\n\n      if (events && (listeners = _.has(events, event.type) && events[event.type])) {\n        _.each(listeners.slice(), function(listener) {\n          if ((event.result = listener.apply(object, args)) === false) {\n            event.cancelled = true;\n          }\n          return !event.aborted;\n        });\n      }\n      return event.result;\n    }\n\n    /**\n     * Returns an array of event listeners for a given type that can be manipulated\n     * to add or remove listeners.\n     *\n     * @memberOf Benchmark, Benchmark.Suite\n     * @param {String} type The event type.\n     * @returns {Array} The listeners array.\n     */\n    function listeners(type) {\n      var object = this,\n          events = object.events || (object.events = {});\n\n      return _.has(events, type) ? events[type] : (events[type] = []);\n    }\n\n    /**\n     * Unregisters a listener for the specified event type(s),\n     * or unregisters all listeners for the specified event type(s),\n     * or unregisters all listeners for all event types.\n     *\n     * @memberOf Benchmark, Benchmark.Suite\n     * @param {String} [type] The event type.\n     * @param {Function} [listener] The function to unregister.\n     * @returns {Object} The benchmark instance.\n     * @example\n     *\n     * // unregister a listener for an event type\n     * bench.off('cycle', listener);\n     *\n     * // unregister a listener for multiple event types\n     * bench.off('start cycle', listener);\n     *\n     * // unregister all listeners for an event type\n     * bench.off('cycle');\n     *\n     * // unregister all listeners for multiple event types\n     * bench.off('start cycle complete');\n     *\n     * // unregister all listeners for all event types\n     * bench.off();\n     */\n    function off(type, listener) {\n      var object = this,\n          events = object.events;\n\n      if (!events) {\n        return object;\n      }\n      _.each(type ? type.split(' ') : events, function(listeners, type) {\n        var index;\n        if (typeof listeners == 'string') {\n          type = listeners;\n          listeners = _.has(events, type) && events[type];\n        }\n        if (listeners) {\n          if (listener) {\n            index = _.indexOf(listeners, listener);\n            if (index > -1) {\n              listeners.splice(index, 1);\n            }\n          } else {\n            listeners.length = 0;\n          }\n        }\n      });\n      return object;\n    }\n\n    /**\n     * Registers a listener for the specified event type(s).\n     *\n     * @memberOf Benchmark, Benchmark.Suite\n     * @param {String} type The event type.\n     * @param {Function} listener The function to register.\n     * @returns {Object} The benchmark instance.\n     * @example\n     *\n     * // register a listener for an event type\n     * bench.on('cycle', listener);\n     *\n     * // register a listener for multiple event types\n     * bench.on('start cycle', listener);\n     */\n    function on(type, listener) {\n      var object = this,\n          events = object.events || (object.events = {});\n\n      _.each(type.split(' '), function(type) {\n        (_.has(events, type)\n          ? events[type]\n          : (events[type] = [])\n        ).push(listener);\n      });\n      return object;\n    }\n\n    /*------------------------------------------------------------------------*/\n\n    /**\n     * Aborts the benchmark without recording times.\n     *\n     * @memberOf Benchmark\n     * @returns {Object} The benchmark instance.\n     */\n    function abort() {\n      var event,\n          bench = this,\n          resetting = calledBy.reset;\n\n      if (bench.running) {\n        event = Event('abort');\n        bench.emit(event);\n        if (!event.cancelled || resetting) {\n          // avoid infinite recursion\n          calledBy.abort = true;\n          bench.reset();\n          delete calledBy.abort;\n\n          if (support.timeout) {\n            clearTimeout(bench._timerId);\n            delete bench._timerId;\n          }\n          if (!resetting) {\n            bench.aborted = true;\n            bench.running = false;\n          }\n        }\n      }\n      return bench;\n    }\n\n    /**\n     * Creates a new benchmark using the same test and options.\n     *\n     * @memberOf Benchmark\n     * @param {Object} options Options object to overwrite cloned options.\n     * @returns {Object} The new benchmark instance.\n     * @example\n     *\n     * var bizarro = bench.clone({\n     *   'name': 'doppelganger'\n     * });\n     */\n    function clone(options) {\n      var bench = this,\n          sample = bench.stats.sample,\n          result = new bench.constructor(_.extend({}, bench, options));\n\n      // correct the `options` object\n      result.options = _.extend({}, bench.options, options);\n\n      // copy own custom properties\n      _.forOwn(bench, function(value, key) {\n        if (!_.has(result, key)) {\n          result[key] = cloneDeep(value);\n        }\n      });\n\n      return result;\n    }\n\n    /**\n     * Determines if a benchmark is faster than another.\n     *\n     * @memberOf Benchmark\n     * @param {Object} other The benchmark to compare.\n     * @returns {Number} Returns `-1` if slower, `1` if faster, and `0` if indeterminate.\n     */\n    function compare(other) {\n      var critical,\n          zStat,\n          bench = this,\n          sample1 = bench.stats.sample,\n          sample2 = other.stats.sample,\n          size1 = sample1.length,\n          size2 = sample2.length,\n          maxSize = max(size1, size2),\n          minSize = min(size1, size2),\n          u1 = getU(sample1, sample2),\n          u2 = getU(sample2, sample1),\n          u = min(u1, u2);\n\n      function getScore(xA, sampleB) {\n        return _.reduce(sampleB, function(total, xB) {\n          return total + (xB > xA ? 0 : xB < xA ? 1 : 0.5);\n        }, 0);\n      }\n\n      function getU(sampleA, sampleB) {\n        return _.reduce(sampleA, function(total, xA) {\n          return total + getScore(xA, sampleB);\n        }, 0);\n      }\n\n      function getZ(u) {\n        return (u - ((size1 * size2) / 2)) / sqrt((size1 * size2 * (size1 + size2 + 1)) / 12);\n      }\n\n      // exit early if comparing the same benchmark\n      if (bench == other) {\n        return 0;\n      }\n      // reject the null hyphothesis the two samples come from the\n      // same population (i.e. have the same median) if...\n      if (size1 + size2 > 30) {\n        // ...the z-stat is greater than 1.96 or less than -1.96\n        // http://www.statisticslectures.com/topics/mannwhitneyu/\n        zStat = getZ(u);\n        return abs(zStat) > 1.96 ? (zStat > 0 ? -1 : 1) : 0;\n      }\n      // ...the U value is less than or equal the critical U value\n      // http://www.geoib.com/mann-whitney-u-test.html\n      critical = maxSize < 5 || minSize < 3 ? 0 : uTable[maxSize][minSize - 3];\n      return u <= critical ? (u == u1 ? 1 : -1) : 0;\n    }\n\n    /**\n     * Reset properties and abort if running.\n     *\n     * @memberOf Benchmark\n     * @returns {Object} The benchmark instance.\n     */\n    function reset() {\n      var data,\n          event,\n          bench = this,\n          index = 0,\n          changes = { 'length': 0 },\n          queue = { 'length': 0 };\n\n      if (bench.running && !calledBy.abort) {\n        // no worries, `reset()` is called within `abort()`\n        calledBy.reset = true;\n        bench.abort();\n        delete calledBy.reset;\n      }\n      else {\n        // a non-recursive solution to check if properties have changed\n        // http://www.jslab.dk/articles/non.recursive.preorder.traversal.part4\n        data = { 'destination': bench, 'source': _.extend({}, bench.constructor.prototype, bench.options) };\n        do {\n          _.forOwn(data.source, function(value, key) {\n            var changed,\n                destination = data.destination,\n                currValue = destination[key];\n\n            if (value && typeof value == 'object') {\n              if (_.isArray(value)) {\n                // check if an array value has changed to a non-array value\n                if (!_.isArray(currValue)) {\n                  changed = currValue = [];\n                }\n                // or has changed its length\n                if (currValue.length != value.length) {\n                  changed = currValue = currValue.slice(0, value.length);\n                  currValue.length = value.length;\n                }\n              }\n              // check if an object has changed to a non-object value\n              else if (!currValue || typeof currValue != 'object') {\n                changed = currValue = {};\n              }\n              // register a changed object\n              if (changed) {\n                changes[changes.length++] = { 'destination': destination, 'key': key, 'value': currValue };\n              }\n              queue[queue.length++] = { 'destination': currValue, 'source': value };\n            }\n            // register a changed primitive\n            else if (value !== currValue && !(value == null || _.isFunction(value))) {\n              changes[changes.length++] = { 'destination': destination, 'key': key, 'value': value };\n            }\n          });\n        }\n        while ((data = queue[index++]));\n\n        // if changed emit the `reset` event and if it isn't cancelled reset the benchmark\n        if (changes.length && (bench.emit(event = Event('reset')), !event.cancelled)) {\n          _.each(changes, function(data) {\n            data.destination[data.key] = data.value;\n          });\n        }\n      }\n      return bench;\n    }\n\n    /**\n     * Displays relevant benchmark information when coerced to a string.\n     *\n     * @name toString\n     * @memberOf Benchmark\n     * @returns {String} A string representation of the benchmark instance.\n     */\n    function toStringBench() {\n      var bench = this,\n          error = bench.error,\n          hz = bench.hz,\n          id = bench.id,\n          stats = bench.stats,\n          size = stats.sample.length,\n          pm = support.java ? '+/-' : '\\xb1',\n          result = bench.name || (_.isNaN(id) ? id : '<Test #' + id + '>');\n\n      if (error) {\n        result += ': ' + join(error);\n      } else {\n        result += ' x ' + formatNumber(hz.toFixed(hz < 100 ? 2 : 0)) + ' ops/sec ' + pm +\n          stats.rme.toFixed(2) + '% (' + size + ' run' + (size == 1 ? '' : 's') + ' sampled)';\n      }\n      return result;\n    }\n\n    /*------------------------------------------------------------------------*/\n\n    /**\n     * Clocks the time taken to execute a test per cycle (secs).\n     *\n     * @private\n     * @param {Object} bench The benchmark instance.\n     * @returns {Number} The time taken.\n     */\n    function clock() {\n      var applet,\n          options = Benchmark.options,\n          timers = [{ 'ns': timer.ns, 'res': max(0.0015, getRes('ms')), 'unit': 'ms' }];\n\n      var templateData = {\n        'begin': interpolate('s#=new n#'),\n        'end': interpolate('r#=(new n#-s#)/1e3'),\n        'uid': uid\n      };\n\n      // lazy define for hi-res timers\n      clock = function(clone) {\n        var deferred;\n        if (clone instanceof Deferred) {\n          deferred = clone;\n          clone = deferred.benchmark;\n        }\n\n        var bench = clone._original,\n            fn = bench.fn,\n            fnArg = deferred ? getFirstArgument(fn) || 'deferred' : '',\n            stringable = isStringable(fn);\n\n        _.extend(templateData, {\n          'setup': getSource(bench.setup, interpolate('m#.setup()')),\n          'fn': getSource(fn, interpolate('m#.fn(' + fnArg + ')')),\n          'fnArg': fnArg,\n          'teardown': getSource(bench.teardown, interpolate('m#.teardown()'))\n        });\n\n        var count = bench.count = clone.count,\n            decompilable = support.decompilation || stringable,\n            id = bench.id,\n            isEmpty = !(templateData.fn || stringable),\n            name = bench.name || (typeof id == 'number' ? '<Test #' + id + '>' : id),\n            ns = timer.ns,\n            result = 0;\n\n        // init `minTime` if needed\n        clone.minTime = bench.minTime || (bench.minTime = bench.options.minTime = options.minTime);\n\n        // repair nanosecond timer\n        // (some Chrome builds erase the `ns` variable after millions of executions)\n        if (applet) {\n          try {\n            ns.nanoTime();\n          } catch(e) {\n            // use non-element to avoid issues with libs that augment them\n            ns = timer.ns = new applet.Packages.nano;\n          }\n        }\n\n        // Compile in setup/teardown functions and the test loop.\n        // Create a new compiled test, instead of using the cached `bench.compiled`,\n        // to avoid potential engine optimizations enabled over the life of the test.\n        var compiled = bench.compiled = createCompiled(\n          deferred\n            ? 'var d#=this,${fnArg}=d#,m#=d#.benchmark._original,f#=m#.fn,su#=m#.setup,td#=m#.teardown;' +\n              // when `deferred.cycles` is `0` then...\n              'if(!d#.cycles){' +\n              // set `deferred.fn`\n              'd#.fn=function(){var ${fnArg}=d#;if(typeof f#==\"function\"){try{${fn}\\n}catch(e#){f#(d#)}}else{${fn}\\n}};' +\n              // set `deferred.teardown`\n              'd#.teardown=function(){d#.cycles=0;if(typeof td#==\"function\"){try{${teardown}\\n}catch(e#){td#()}}else{${teardown}\\n}};' +\n              // execute the benchmark's `setup`\n              'if(typeof su#==\"function\"){try{${setup}\\n}catch(e#){su#()}}else{${setup}\\n};' +\n              // start timer\n              't#.start(d#);' +\n              // execute `deferred.fn` and return a dummy object\n              '}d#.fn();return{}'\n\n            : 'var r#,s#,m#=this,f#=m#.fn,i#=m#.count,n#=t#.ns;${setup}\\n${begin};' +\n              'while(i#--){${fn}\\n}${end};${teardown}\\nreturn{elapsed:r#,uid:\"${uid}\"}'\n        );\n\n        try {\n          if (isEmpty) {\n            // Firefox may remove dead code from Function#toString results\n            // http://bugzil.la/536085\n            throw new Error('The test \"' + name + '\" is empty. This may be the result of dead code removal.');\n          }\n          else if (!deferred) {\n            // pretest to determine if compiled code is exits early, usually by a\n            // rogue `return` statement, by checking for a return object with the uid\n            bench.count = 1;\n            compiled = (compiled.call(bench, context, timer) || {}).uid == uid && compiled;\n            bench.count = count;\n          }\n        } catch(e) {\n          compiled = null;\n          clone.error = e || new Error(String(e));\n          bench.count = count;\n        }\n        // fallback when a test exits early or errors during pretest\n        if (decompilable && !compiled && !deferred && !isEmpty) {\n          compiled = createCompiled(\n            (clone.error && !stringable\n              ? 'var r#,s#,m#=this,f#=m#.fn,i#=m#.count'\n              : 'function f#(){${fn}\\n}var r#,s#,m#=this,i#=m#.count'\n            ) +\n            ',n#=t#.ns;${setup}\\n${begin};m#.f#=f#;while(i#--){m#.f#()}${end};' +\n            'delete m#.f#;${teardown}\\nreturn{elapsed:r#}'\n          );\n\n          try {\n            // pretest one more time to check for errors\n            bench.count = 1;\n            compiled.call(bench, context, timer);\n            bench.compiled = compiled;\n            bench.count = count;\n            delete clone.error;\n          }\n          catch(e) {\n            bench.count = count;\n            if (clone.error) {\n              compiled = null;\n            } else {\n              bench.compiled = compiled;\n              clone.error = e || new Error(String(e));\n            }\n          }\n        }\n        // assign `compiled` to `clone` before calling in case a deferred benchmark\n        // immediately calls `deferred.resolve()`\n        clone.compiled = compiled;\n        // if no errors run the full test loop\n        if (!clone.error) {\n          result = compiled.call(deferred || bench, context, timer).elapsed;\n        }\n        return result;\n      };\n\n      /*----------------------------------------------------------------------*/\n\n      /**\n       * Creates a compiled function from the given function `body`.\n       */\n      function createCompiled(body) {\n        return createFunction(\n          interpolate('window,t#'),\n          'var global = window, clearTimeout = global.clearTimeout, setTimeout = global.setTimeout;\\n' +\n          interpolate(body)\n        );\n      }\n\n      /**\n       * Gets the current timer's minimum resolution (secs).\n       */\n      function getRes(unit) {\n        var measured,\n            begin,\n            count = 30,\n            divisor = 1e3,\n            ns = timer.ns,\n            sample = [];\n\n        // get average smallest measurable time\n        while (count--) {\n          if (unit == 'us') {\n            divisor = 1e6;\n            if (ns.stop) {\n              ns.start();\n              while (!(measured = ns.microseconds())) { }\n            } else if (ns[perfName]) {\n              divisor = 1e3;\n              measured = Function('n', 'var r,s=n.' + perfName + '();while(!(r=n.' + perfName + '()-s)){};return r')(ns);\n            } else {\n              begin = ns();\n              while (!(measured = ns() - begin)) { }\n            }\n          }\n          else if (unit == 'ns') {\n            divisor = 1e9;\n            if (ns.nanoTime) {\n              begin = ns.nanoTime();\n              while (!(measured = ns.nanoTime() - begin)) { }\n            } else {\n              begin = (begin = ns())[0] + (begin[1] / divisor);\n              while (!(measured = ((measured = ns())[0] + (measured[1] / divisor)) - begin)) { }\n              divisor = 1;\n            }\n          }\n          else {\n            begin = new ns;\n            while (!(measured = new ns - begin)) { }\n          }\n          // check for broken timers (nanoTime may have issues)\n          // http://alivebutsleepy.srnet.cz/unreliable-system-nanotime/\n          if (measured > 0) {\n            sample.push(measured);\n          } else {\n            sample.push(Infinity);\n            break;\n          }\n        }\n        // convert to seconds\n        return getMean(sample) / divisor;\n      }\n\n      /**\n       * Interpolates a given template string.\n       */\n      function interpolate(string) {\n        // replaces all occurrences of `#` with a unique number and template tokens with content\n        return _.template(string.replace(/\\#/g, /\\d+/.exec(uid)), templateData || {});\n      }\n\n      /*----------------------------------------------------------------------*/\n\n      // detect nanosecond support from a Java applet\n      _.each(doc && doc.applets || [], function(element) {\n        return !(timer.ns = applet = 'nanoTime' in element && element);\n      });\n\n      // check type in case Safari returns an object instead of a number\n      try {\n        if (typeof timer.ns.nanoTime() == 'number') {\n          timers.push({ 'ns': timer.ns, 'res': getRes('ns'), 'unit': 'ns' });\n        }\n      } catch(e) { }\n\n      // detect Chrome's microsecond timer:\n      // enable benchmarking via the --enable-benchmarking command\n      // line switch in at least Chrome 7 to use chrome.Interval\n      try {\n        if ((timer.ns = new (context.chrome || context.chromium).Interval)) {\n          timers.push({ 'ns': timer.ns, 'res': getRes('us'), 'unit': 'us' });\n        }\n      } catch(e) { }\n\n      // detect `performance.now` microsecond resolution timer\n      if ((timer.ns = perfName && perfObject)) {\n        timers.push({ 'ns': timer.ns, 'res': getRes('us'), 'unit': 'us' });\n      }\n\n      // detect Node's nanosecond resolution timer available in Node >= 0.8\n      if (processObject && typeof (timer.ns = processObject.hrtime) == 'function') {\n        timers.push({ 'ns': timer.ns, 'res': getRes('ns'), 'unit': 'ns' });\n      }\n\n      // detect Wade Simmons' Node microtime module\n      if (microtimeObject && typeof (timer.ns = microtimeObject.now) == 'function') {\n        timers.push({ 'ns': timer.ns,  'res': getRes('us'), 'unit': 'us' });\n      }\n\n      // pick timer with highest resolution\n      timer = _.reduce(timers, function(timer, other) {\n        return other.res < timer.res ? other : timer;\n      });\n\n      // remove unused applet\n      if (timer.unit != 'ns' && applet) {\n        applet = destroyElement(applet);\n      }\n      // error if there are no working timers\n      if (timer.res == Infinity) {\n        throw new Error('Benchmark.js was unable to find a working timer.');\n      }\n      // use API of chosen timer\n      if (timer.unit == 'ns') {\n        if (timer.ns.nanoTime) {\n          _.extend(templateData, {\n            'begin': interpolate('s#=n#.nanoTime()'),\n            'end': interpolate('r#=(n#.nanoTime()-s#)/1e9')\n          });\n        } else {\n          _.extend(templateData, {\n            'begin': interpolate('s#=n#()'),\n            'end': interpolate('r#=n#(s#);r#=r#[0]+(r#[1]/1e9)')\n          });\n        }\n      }\n      else if (timer.unit == 'us') {\n        if (timer.ns.stop) {\n          _.extend(templateData, {\n            'begin': interpolate('s#=n#.start()'),\n            'end': interpolate('r#=n#.microseconds()/1e6')\n          });\n        } else if (perfName) {\n          _.extend(templateData, {\n            'begin': interpolate('s#=n#.' + perfName + '()'),\n            'end': interpolate('r#=(n#.' + perfName + '()-s#)/1e3')\n          });\n        } else {\n          _.extend(templateData, {\n            'begin': interpolate('s#=n#()'),\n            'end': interpolate('r#=(n#()-s#)/1e6')\n          });\n        }\n      }\n\n      // define `timer` methods\n      timer.start = createFunction(\n        interpolate('o#'),\n        interpolate('var n#=this.ns,${begin};o#.elapsed=0;o#.timeStamp=s#')\n      );\n\n      timer.stop = createFunction(\n        interpolate('o#'),\n        interpolate('var n#=this.ns,s#=o#.timeStamp,${end};o#.elapsed=r#')\n      );\n\n      // resolve time span required to achieve a percent uncertainty of at most 1%\n      // http://spiff.rit.edu/classes/phys273/uncert/uncert.html\n      options.minTime || (options.minTime = max(timer.res / 2 / 0.01, 0.05));\n      return clock.apply(null, arguments);\n    }\n\n    /*------------------------------------------------------------------------*/\n\n    /**\n     * Computes stats on benchmark results.\n     *\n     * @private\n     * @param {Object} bench The benchmark instance.\n     * @param {Object} options The options object.\n     */\n    function compute(bench, options) {\n      options || (options = {});\n\n      var async = options.async,\n          elapsed = 0,\n          initCount = bench.initCount,\n          minSamples = bench.minSamples,\n          queue = [],\n          sample = bench.stats.sample;\n\n      /**\n       * Adds a clone to the queue.\n       */\n      function enqueue() {\n        queue.push(bench.clone({\n          '_original': bench,\n          'events': {\n            'abort': [update],\n            'cycle': [update],\n            'error': [update],\n            'start': [update]\n          }\n        }));\n      }\n\n      /**\n       * Updates the clone/original benchmarks to keep their data in sync.\n       */\n      function update(event) {\n        var clone = this,\n            type = event.type;\n\n        if (bench.running) {\n          if (type == 'start') {\n            // Note: `clone.minTime` prop is inited in `clock()`\n            clone.count = bench.initCount;\n          }\n          else {\n            if (type == 'error') {\n              bench.error = clone.error;\n            }\n            if (type == 'abort') {\n              bench.abort();\n              bench.emit('cycle');\n            } else {\n              event.currentTarget = event.target = bench;\n              bench.emit(event);\n            }\n          }\n        } else if (bench.aborted) {\n          // clear abort listeners to avoid triggering bench's abort/cycle again\n          clone.events.abort.length = 0;\n          clone.abort();\n        }\n      }\n\n      /**\n       * Determines if more clones should be queued or if cycling should stop.\n       */\n      function evaluate(event) {\n        var critical,\n            df,\n            mean,\n            moe,\n            rme,\n            sd,\n            sem,\n            variance,\n            clone = event.target,\n            done = bench.aborted,\n            now = +new Date,\n            size = sample.push(clone.times.period),\n            maxedOut = size >= minSamples && (elapsed += now - clone.times.timeStamp) / 1e3 > bench.maxTime,\n            times = bench.times,\n            varOf = function(sum, x) { return sum + pow(x - mean, 2); };\n\n        // exit early for aborted or unclockable tests\n        if (done || clone.hz == Infinity) {\n          maxedOut = !(size = sample.length = queue.length = 0);\n        }\n\n        if (!done) {\n          // sample mean (estimate of the population mean)\n          mean = getMean(sample);\n          // sample variance (estimate of the population variance)\n          variance = _.reduce(sample, varOf, 0) / (size - 1) || 0;\n          // sample standard deviation (estimate of the population standard deviation)\n          sd = sqrt(variance);\n          // standard error of the mean (a.k.a. the standard deviation of the sampling distribution of the sample mean)\n          sem = sd / sqrt(size);\n          // degrees of freedom\n          df = size - 1;\n          // critical value\n          critical = tTable[Math.round(df) || 1] || tTable.infinity;\n          // margin of error\n          moe = sem * critical;\n          // relative margin of error\n          rme = (moe / mean) * 100 || 0;\n\n          _.extend(bench.stats, {\n            'deviation': sd,\n            'mean': mean,\n            'moe': moe,\n            'rme': rme,\n            'sem': sem,\n            'variance': variance\n          });\n\n          // Abort the cycle loop when the minimum sample size has been collected\n          // and the elapsed time exceeds the maximum time allowed per benchmark.\n          // We don't count cycle delays toward the max time because delays may be\n          // increased by browsers that clamp timeouts for inactive tabs.\n          // https://developer.mozilla.org/en/window.setTimeout#Inactive_tabs\n          if (maxedOut) {\n            // reset the `initCount` in case the benchmark is rerun\n            bench.initCount = initCount;\n            bench.running = false;\n            done = true;\n            times.elapsed = (now - times.timeStamp) / 1e3;\n          }\n          if (bench.hz != Infinity) {\n            bench.hz = 1 / mean;\n            times.cycle = mean * bench.count;\n            times.period = mean;\n          }\n        }\n        // if time permits, increase sample size to reduce the margin of error\n        if (queue.length < 2 && !maxedOut) {\n          enqueue();\n        }\n        // abort the invoke cycle when done\n        event.aborted = done;\n      }\n\n      // init queue and begin\n      enqueue();\n      invoke(queue, {\n        'name': 'run',\n        'args': { 'async': async },\n        'queued': true,\n        'onCycle': evaluate,\n        'onComplete': function() { bench.emit('complete'); }\n      });\n    }\n\n    /*------------------------------------------------------------------------*/\n\n    /**\n     * Cycles a benchmark until a run `count` can be established.\n     *\n     * @private\n     * @param {Object} clone The cloned benchmark instance.\n     * @param {Object} options The options object.\n     */\n    function cycle(clone, options) {\n      options || (options = {});\n\n      var deferred;\n      if (clone instanceof Deferred) {\n        deferred = clone;\n        clone = clone.benchmark;\n      }\n\n      var clocked,\n          cycles,\n          divisor,\n          event,\n          minTime,\n          period,\n          async = options.async,\n          bench = clone._original,\n          count = clone.count,\n          times = clone.times;\n\n      // continue, if not aborted between cycles\n      if (clone.running) {\n        // `minTime` is set to `Benchmark.options.minTime` in `clock()`\n        cycles = ++clone.cycles;\n        clocked = deferred ? deferred.elapsed : clock(clone);\n        minTime = clone.minTime;\n\n        if (cycles > bench.cycles) {\n          bench.cycles = cycles;\n        }\n        if (clone.error) {\n          event = Event('error');\n          event.message = clone.error;\n          clone.emit(event);\n          if (!event.cancelled) {\n            clone.abort();\n          }\n        }\n      }\n\n      // continue, if not errored\n      if (clone.running) {\n        // time taken to complete last test cycle\n        bench.times.cycle = times.cycle = clocked;\n        // seconds per operation\n        period = bench.times.period = times.period = clocked / count;\n        // ops per second\n        bench.hz = clone.hz = 1 / period;\n        // avoid working our way up to this next time\n        bench.initCount = clone.initCount = count;\n        // do we need to do another cycle?\n        clone.running = clocked < minTime;\n\n        if (clone.running) {\n          // tests may clock at `0` when `initCount` is a small number,\n          // to avoid that we set its count to something a bit higher\n          if (!clocked && (divisor = divisors[clone.cycles]) != null) {\n            count = floor(4e6 / divisor);\n          }\n          // calculate how many more iterations it will take to achive the `minTime`\n          if (count <= clone.count) {\n            count += Math.ceil((minTime - clocked) / period);\n          }\n          clone.running = count != Infinity;\n        }\n      }\n      // should we exit early?\n      event = Event('cycle');\n      clone.emit(event);\n      if (event.aborted) {\n        clone.abort();\n      }\n      // figure out what to do next\n      if (clone.running) {\n        // start a new cycle\n        clone.count = count;\n        if (deferred) {\n          clone.compiled.call(deferred, context, timer);\n        } else if (async) {\n          delay(clone, function() { cycle(clone, options); });\n        } else {\n          cycle(clone);\n        }\n      }\n      else {\n        // fix TraceMonkey bug associated with clock fallbacks\n        // http://bugzil.la/509069\n        if (support.browser) {\n          runScript(uid + '=1;delete ' + uid);\n        }\n        // done\n        clone.emit('complete');\n      }\n    }\n\n    /*------------------------------------------------------------------------*/\n\n    /**\n     * Runs the benchmark.\n     *\n     * @memberOf Benchmark\n     * @param {Object} [options={}] Options object.\n     * @returns {Object} The benchmark instance.\n     * @example\n     *\n     * // basic usage\n     * bench.run();\n     *\n     * // or with options\n     * bench.run({ 'async': true });\n     */\n    function run(options) {\n      var bench = this,\n          event = Event('start');\n\n      // set `running` to `false` so `reset()` won't call `abort()`\n      bench.running = false;\n      bench.reset();\n      bench.running = true;\n\n      bench.count = bench.initCount;\n      bench.times.timeStamp = +new Date;\n      bench.emit(event);\n\n      if (!event.cancelled) {\n        options = { 'async': ((options = options && options.async) == null ? bench.async : options) && support.timeout };\n\n        // for clones created within `compute()`\n        if (bench._original) {\n          if (bench.defer) {\n            Deferred(bench);\n          } else {\n            cycle(bench, options);\n          }\n        }\n        // for original benchmarks\n        else {\n          compute(bench, options);\n        }\n      }\n      return bench;\n    }\n\n    /*------------------------------------------------------------------------*/\n\n    // Firefox 1 erroneously defines variable and argument names of functions on\n    // the function itself as non-configurable properties with `undefined` values.\n    // The bugginess continues as the `Benchmark` constructor has an argument\n    // named `options` and Firefox 1 will not assign a value to `Benchmark.options`,\n    // making it non-writable in the process, unless it is the first property\n    // assigned by for-in loop of `_.extend()`.\n    _.extend(Benchmark, {\n\n      /**\n       * The default options copied by benchmark instances.\n       *\n       * @static\n       * @memberOf Benchmark\n       * @type Object\n       */\n      'options': {\n\n        /**\n         * A flag to indicate that benchmark cycles will execute asynchronously\n         * by default.\n         *\n         * @memberOf Benchmark.options\n         * @type Boolean\n         */\n        'async': false,\n\n        /**\n         * A flag to indicate that the benchmark clock is deferred.\n         *\n         * @memberOf Benchmark.options\n         * @type Boolean\n         */\n        'defer': false,\n\n        /**\n         * The delay between test cycles (secs).\n         * @memberOf Benchmark.options\n         * @type Number\n         */\n        'delay': 0.005,\n\n        /**\n         * Displayed by Benchmark#toString when a `name` is not available\n         * (auto-generated if absent).\n         *\n         * @memberOf Benchmark.options\n         * @type String\n         */\n        'id': undefined,\n\n        /**\n         * The default number of times to execute a test on a benchmark's first cycle.\n         *\n         * @memberOf Benchmark.options\n         * @type Number\n         */\n        'initCount': 1,\n\n        /**\n         * The maximum time a benchmark is allowed to run before finishing (secs).\n         *\n         * Note: Cycle delays aren't counted toward the maximum time.\n         *\n         * @memberOf Benchmark.options\n         * @type Number\n         */\n        'maxTime': 5,\n\n        /**\n         * The minimum sample size required to perform statistical analysis.\n         *\n         * @memberOf Benchmark.options\n         * @type Number\n         */\n        'minSamples': 5,\n\n        /**\n         * The time needed to reduce the percent uncertainty of measurement to 1% (secs).\n         *\n         * @memberOf Benchmark.options\n         * @type Number\n         */\n        'minTime': 0,\n\n        /**\n         * The name of the benchmark.\n         *\n         * @memberOf Benchmark.options\n         * @type String\n         */\n        'name': undefined,\n\n        /**\n         * An event listener called when the benchmark is aborted.\n         *\n         * @memberOf Benchmark.options\n         * @type Function\n         */\n        'onAbort': undefined,\n\n        /**\n         * An event listener called when the benchmark completes running.\n         *\n         * @memberOf Benchmark.options\n         * @type Function\n         */\n        'onComplete': undefined,\n\n        /**\n         * An event listener called after each run cycle.\n         *\n         * @memberOf Benchmark.options\n         * @type Function\n         */\n        'onCycle': undefined,\n\n        /**\n         * An event listener called when a test errors.\n         *\n         * @memberOf Benchmark.options\n         * @type Function\n         */\n        'onError': undefined,\n\n        /**\n         * An event listener called when the benchmark is reset.\n         *\n         * @memberOf Benchmark.options\n         * @type Function\n         */\n        'onReset': undefined,\n\n        /**\n         * An event listener called when the benchmark starts running.\n         *\n         * @memberOf Benchmark.options\n         * @type Function\n         */\n        'onStart': undefined\n      },\n\n      /**\n       * Platform object with properties describing things like browser name,\n       * version, and operating system.\n       *\n       * @static\n       * @memberOf Benchmark\n       * @type Object\n       */\n      'platform': context.platform || req('platform') || ({\n        'description': context.navigator && context.navigator.userAgent || null,\n        'layout': null,\n        'product': null,\n        'name': null,\n        'manufacturer': null,\n        'os': null,\n        'prerelease': null,\n        'version': null,\n        'toString': function() {\n          return this.description || '';\n        }\n      }),\n\n      /**\n       * The semantic version number.\n       *\n       * @static\n       * @memberOf Benchmark\n       * @type String\n       */\n      'version': '1.0.0'\n    });\n\n    _.extend(Benchmark, {\n      'filter': filter,\n      'formatNumber': formatNumber,\n      'invoke': invoke,\n      'join': join,\n      'runInContext': runInContext,\n      'support': support\n    });\n\n    /*------------------------------------------------------------------------*/\n\n    _.extend(Benchmark.prototype, {\n\n      /**\n       * The number of times a test was executed.\n       *\n       * @memberOf Benchmark\n       * @type Number\n       */\n      'count': 0,\n\n      /**\n       * The number of cycles performed while benchmarking.\n       *\n       * @memberOf Benchmark\n       * @type Number\n       */\n      'cycles': 0,\n\n      /**\n       * The number of executions per second.\n       *\n       * @memberOf Benchmark\n       * @type Number\n       */\n      'hz': 0,\n\n      /**\n       * The compiled test function.\n       *\n       * @memberOf Benchmark\n       * @type Function|String\n       */\n      'compiled': undefined,\n\n      /**\n       * The error object if the test failed.\n       *\n       * @memberOf Benchmark\n       * @type Object\n       */\n      'error': undefined,\n\n      /**\n       * The test to benchmark.\n       *\n       * @memberOf Benchmark\n       * @type Function|String\n       */\n      'fn': undefined,\n\n      /**\n       * A flag to indicate if the benchmark is aborted.\n       *\n       * @memberOf Benchmark\n       * @type Boolean\n       */\n      'aborted': false,\n\n      /**\n       * A flag to indicate if the benchmark is running.\n       *\n       * @memberOf Benchmark\n       * @type Boolean\n       */\n      'running': false,\n\n      /**\n       * Compiled into the test and executed immediately **before** the test loop.\n       *\n       * @memberOf Benchmark\n       * @type Function|String\n       * @example\n       *\n       * // basic usage\n       * var bench = Benchmark({\n       *   'setup': function() {\n       *     var c = this.count,\n       *         element = document.getElementById('container');\n       *     while (c--) {\n       *       element.appendChild(document.createElement('div'));\n       *     }\n       *   },\n       *   'fn': function() {\n       *     element.removeChild(element.lastChild);\n       *   }\n       * });\n       *\n       * // compiles to something like:\n       * var c = this.count,\n       *     element = document.getElementById('container');\n       * while (c--) {\n       *   element.appendChild(document.createElement('div'));\n       * }\n       * var start = new Date;\n       * while (count--) {\n       *   element.removeChild(element.lastChild);\n       * }\n       * var end = new Date - start;\n       *\n       * // or using strings\n       * var bench = Benchmark({\n       *   'setup': '\\\n       *     var a = 0;\\n\\\n       *     (function() {\\n\\\n       *       (function() {\\n\\\n       *         (function() {',\n       *   'fn': 'a += 1;',\n       *   'teardown': '\\\n       *          }())\\n\\\n       *        }())\\n\\\n       *      }())'\n       * });\n       *\n       * // compiles to something like:\n       * var a = 0;\n       * (function() {\n       *   (function() {\n       *     (function() {\n       *       var start = new Date;\n       *       while (count--) {\n       *         a += 1;\n       *       }\n       *       var end = new Date - start;\n       *     }())\n       *   }())\n       * }())\n       */\n      'setup': noop,\n\n      /**\n       * Compiled into the test and executed immediately **after** the test loop.\n       *\n       * @memberOf Benchmark\n       * @type Function|String\n       */\n      'teardown': noop,\n\n      /**\n       * An object of stats including mean, margin or error, and standard deviation.\n       *\n       * @memberOf Benchmark\n       * @type Object\n       */\n      'stats': {\n\n        /**\n         * The margin of error.\n         *\n         * @memberOf Benchmark#stats\n         * @type Number\n         */\n        'moe': 0,\n\n        /**\n         * The relative margin of error (expressed as a percentage of the mean).\n         *\n         * @memberOf Benchmark#stats\n         * @type Number\n         */\n        'rme': 0,\n\n        /**\n         * The standard error of the mean.\n         *\n         * @memberOf Benchmark#stats\n         * @type Number\n         */\n        'sem': 0,\n\n        /**\n         * The sample standard deviation.\n         *\n         * @memberOf Benchmark#stats\n         * @type Number\n         */\n        'deviation': 0,\n\n        /**\n         * The sample arithmetic mean (secs).\n         *\n         * @memberOf Benchmark#stats\n         * @type Number\n         */\n        'mean': 0,\n\n        /**\n         * The array of sampled periods.\n         *\n         * @memberOf Benchmark#stats\n         * @type Array\n         */\n        'sample': [],\n\n        /**\n         * The sample variance.\n         *\n         * @memberOf Benchmark#stats\n         * @type Number\n         */\n        'variance': 0\n      },\n\n      /**\n       * An object of timing data including cycle, elapsed, period, start, and stop.\n       *\n       * @memberOf Benchmark\n       * @type Object\n       */\n      'times': {\n\n        /**\n         * The time taken to complete the last cycle (secs).\n         *\n         * @memberOf Benchmark#times\n         * @type Number\n         */\n        'cycle': 0,\n\n        /**\n         * The time taken to complete the benchmark (secs).\n         *\n         * @memberOf Benchmark#times\n         * @type Number\n         */\n        'elapsed': 0,\n\n        /**\n         * The time taken to execute the test once (secs).\n         *\n         * @memberOf Benchmark#times\n         * @type Number\n         */\n        'period': 0,\n\n        /**\n         * A timestamp of when the benchmark started (ms).\n         *\n         * @memberOf Benchmark#times\n         * @type Number\n         */\n        'timeStamp': 0\n      }\n    });\n\n    _.extend(Benchmark.prototype, {\n      'abort': abort,\n      'clone': clone,\n      'compare': compare,\n      'emit': emit,\n      'listeners': listeners,\n      'off': off,\n      'on': on,\n      'reset': reset,\n      'run': run,\n      'toString': toStringBench\n    });\n\n    /*------------------------------------------------------------------------*/\n\n    _.extend(Deferred.prototype, {\n\n      /**\n       * The deferred benchmark instance.\n       *\n       * @memberOf Benchmark.Deferred\n       * @type Object\n       */\n      'benchmark': null,\n\n      /**\n       * The number of deferred cycles performed while benchmarking.\n       *\n       * @memberOf Benchmark.Deferred\n       * @type Number\n       */\n      'cycles': 0,\n\n      /**\n       * The time taken to complete the deferred benchmark (secs).\n       *\n       * @memberOf Benchmark.Deferred\n       * @type Number\n       */\n      'elapsed': 0,\n\n      /**\n       * A timestamp of when the deferred benchmark started (ms).\n       *\n       * @memberOf Benchmark.Deferred\n       * @type Number\n       */\n      'timeStamp': 0\n    });\n\n    _.extend(Deferred.prototype, {\n      'resolve': resolve\n    });\n\n    /*------------------------------------------------------------------------*/\n\n    _.extend(Event.prototype, {\n\n      /**\n       * A flag to indicate if the emitters listener iteration is aborted.\n       *\n       * @memberOf Benchmark.Event\n       * @type Boolean\n       */\n      'aborted': false,\n\n      /**\n       * A flag to indicate if the default action is cancelled.\n       *\n       * @memberOf Benchmark.Event\n       * @type Boolean\n       */\n      'cancelled': false,\n\n      /**\n       * The object whose listeners are currently being processed.\n       *\n       * @memberOf Benchmark.Event\n       * @type Object\n       */\n      'currentTarget': undefined,\n\n      /**\n       * The return value of the last executed listener.\n       *\n       * @memberOf Benchmark.Event\n       * @type Mixed\n       */\n      'result': undefined,\n\n      /**\n       * The object to which the event was originally emitted.\n       *\n       * @memberOf Benchmark.Event\n       * @type Object\n       */\n      'target': undefined,\n\n      /**\n       * A timestamp of when the event was created (ms).\n       *\n       * @memberOf Benchmark.Event\n       * @type Number\n       */\n      'timeStamp': 0,\n\n      /**\n       * The event type.\n       *\n       * @memberOf Benchmark.Event\n       * @type String\n       */\n      'type': ''\n    });\n\n    /*------------------------------------------------------------------------*/\n\n    /**\n     * The default options copied by suite instances.\n     *\n     * @static\n     * @memberOf Benchmark.Suite\n     * @type Object\n     */\n    Suite.options = {\n\n      /**\n       * The name of the suite.\n       *\n       * @memberOf Benchmark.Suite.options\n       * @type String\n       */\n      'name': undefined\n    };\n\n    /*------------------------------------------------------------------------*/\n\n    _.extend(Suite.prototype, {\n\n      /**\n       * The number of benchmarks in the suite.\n       *\n       * @memberOf Benchmark.Suite\n       * @type Number\n       */\n      'length': 0,\n\n      /**\n       * A flag to indicate if the suite is aborted.\n       *\n       * @memberOf Benchmark.Suite\n       * @type Boolean\n       */\n      'aborted': false,\n\n      /**\n       * A flag to indicate if the suite is running.\n       *\n       * @memberOf Benchmark.Suite\n       * @type Boolean\n       */\n      'running': false\n    });\n\n    _.extend(Suite.prototype, {\n      'abort': abortSuite,\n      'add': add,\n      'clone': cloneSuite,\n      'emit': emit,\n      'filter': filterSuite,\n      'join': arrayRef.join,\n      'listeners': listeners,\n      'off': off,\n      'on': on,\n      'pop': arrayRef.pop,\n      'push': arrayRef.push,\n      'reset': resetSuite,\n      'run': runSuite,\n      'reverse': arrayRef.reverse,\n      'shift': shift,\n      'sort': arrayRef.sort,\n      'splice': arrayRef.splice,\n      'unshift': arrayRef.unshift\n    });\n\n    /*------------------------------------------------------------------------*/\n\n    // expose Deferred, Event, and Suite\n    _.extend(Benchmark, {\n      'Deferred': Deferred,\n      'Event': Event,\n      'Suite': Suite\n    });\n\n    /*------------------------------------------------------------------------*/\n\n    // avoid array-like object bugs with `Array#shift` and `Array#splice`\n    // in Firefox < 10 and IE < 9\n    if (!_.support.spliceObjects) {\n      _.each(['pop', 'shift', 'splice'], function(methodName) {\n        var func = arrayRef[methodName];\n\n        Suite.prototype[methodName] = function() {\n          var value = this,\n              result = func.apply(value, arguments);\n\n          if (value.length === 0) {\n            delete value[0];\n          }\n          return result;\n        };\n      });\n    }\n    // trigger clock's lazy define early to avoid a security error\n    if (support.air) {\n      clock({ '_original': { 'fn': noop, 'count': 1, 'options': {} } });\n    }\n    return Benchmark;\n  }\n\n  /*--------------------------------------------------------------------------*/\n\n  // expose Benchmark\n  // some AMD build optimizers, like r.js, check for specific condition patterns like the following:\n  if (typeof define == 'function' && typeof define.amd == 'object' && define.amd) {\n    // define as an anonymous module so, through path mapping, it can be aliased\n    define(['lodash', 'platform'], function(_, platform) {\n      return runInContext({\n        '_': _,\n        'platform': platform\n      });\n    });\n  }\n  else {\n    var Benchmark = runInContext();\n\n    // check for `exports` after `define` in case a build optimizer adds an `exports` object\n    if (freeExports && !freeExports.nodeType) {\n      // in Node.js or RingoJS v0.8.0+\n      if (freeModule) {\n        (freeModule.exports = Benchmark).Benchmark = Benchmark;\n      }\n      // in Narwhal or RingoJS v0.7.0-\n      else {\n        freeExports.Benchmark = Benchmark;\n      }\n    }\n    // in a browser or Rhino\n    else {\n      window.Benchmark = Benchmark;\n    }\n  }\n}(this));\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/json3/vendor/closure-compiler.jar",
    "content": "Unexpected error.  File contents could not be restored from local history during undo/redo."
  },
  {
    "path": "flowable-ui-web/admin/bower_components/json3/vendor/curl.js",
    "content": "/** @license MIT License (c) copyright B Cavalier & J Hann */\n\n/**\n * curl (cujo resource loader)\n * An AMD-compliant javascript module and resource loader\n *\n * curl is part of the cujo.js family of libraries (http://cujojs.com/)\n *\n * Licensed under the MIT License at:\n * \t\thttp://www.opensource.org/licenses/mit-license.php\n *\n * @version 0.6\n */\n(function (global) {\n\n\t/*\n\t * Basic operation:\n\t * When a dependency is encountered and it already exists, it's returned.\n\t * If it doesn't already exist, it is created and the dependency's script\n\t * is loaded. If there is a define call in the loaded script with a id,\n\t * it is resolved asap (i.e. as soon as the module's dependencies are\n\t * resolved). If there is a (single) define call with no id (anonymous),\n\t * the resource in the resNet is resolved after the script's onload fires.\n\t * IE requires a slightly different tactic. IE marks the readyState of the\n\t * currently executing script to 'interactive'. If we can find this script\n\t * while a define() is being called, we can match the define() to its id.\n\t * Opera marks scripts as 'interactive' but at inopportune times so we\n\t * have to handle it specifically.\n\t */\n\n\tvar\n\t\tversion = '0.6.0',\n\t\tuserCfg = global['curl'],\n\t\tdoc = global.document,\n\t\thead = doc && (doc['head'] || doc.getElementsByTagName('head')[0]),\n\t\t// constants / flags\n\t\tmsgUsingExports = {},\n\t\tinteractive = {},\n\t\t// this is the list of scripts that IE is loading. one of these will\n\t\t// be the \"interactive\" script. too bad IE doesn't send a readystatechange\n\t\t// event to tell us exactly which one.\n\t\tactiveScripts = {},\n\t\t// these are always handy :)\n\t\ttoString = ({}).toString,\n\t\tundef,\n\t\t// script ready states that signify it's loaded\n\t\treadyStates = { 'loaded': 1, 'interactive': interactive, 'complete': 1 },\n\t\t// local cache of resource definitions (lightweight promises)\n\t\tcache = {},\n\t\t// preload are files that must be loaded before any others\n\t\tpreload = false,\n\t\t// net to catch anonymous define calls' arguments (non-IE browsers)\n\t\targsNet,\n\t\t// RegExp's used later, \"cached\" here\n\t\tdontAddExtRx = /\\?/,\n\t\tabsUrlRx = /^\\/|^[^:]+:\\/\\//,\n\t\tfindLeadingDotsRx = /(?:^|\\/)(\\.)(\\.?)\\/?/g,\n\t\tremoveCommentsRx = /\\/\\*[\\s\\S]*?\\*\\/|(?:[^\\\\])\\/\\/.*?[\\n\\r]/g,\n\t\tfindRValueRequiresRx = /require\\s*\\(\\s*[\"']([^\"']+)[\"']\\s*\\)|(?:[^\\\\]?)([\"'])/g,\n\t\tcjsGetters,\n\t\tcore;\n\n\tfunction noop () {}\n\n\tfunction isType (obj, type) {\n\t\treturn toString.call(obj).indexOf('[object ' + type) == 0;\n\t}\n\n\tfunction normalizePkgDescriptor (descriptor) {\n\t\tvar path, main;\n\n\t\tpath = descriptor.path = removeEndSlash(descriptor['path'] || descriptor['location'] || '');\n\t\tmain = descriptor['main'] || 'main';\n\t\tdescriptor.config = descriptor['config'];\n\t\tdescriptor.main = main.charAt(0) == '.' ?\n\t\t\tremoveEndSlash(reduceLeadingDots(main, path)) :\n\t\t\tjoinPath(path, main);\n\n\t\treturn descriptor;\n\t}\n\n\tfunction joinPath (path, file) {\n\t\treturn removeEndSlash(path) + '/' + file;\n\t}\n\n\tfunction removeEndSlash (path) {\n\t\treturn path && path.charAt(path.length - 1) == '/' ? path.substr(0, path.length - 1) : path;\n\t\t//return endsWithSlash(path) ? path.substr(0, path.length - 1) : path;\n\t}\n\n\tfunction reduceLeadingDots (childId, baseId) {\n\t\t// this algorithm is similar to dojo's compactPath, which interprets\n\t\t// module ids of \".\" and \"..\" as meaning \"grab the module whose name is\n\t\t// the same as my folder or parent folder\".  These special module ids\n\t\t// are not included in the AMD spec.\n\t\tvar levels, removeLevels, isRelative;\n\t\tremoveLevels = 1;\n\t\tchildId = childId.replace(findLeadingDotsRx, function (m, dot, doubleDot) {\n\t\t\tif (doubleDot) removeLevels++;\n\t\t\tisRelative = true;\n\t\t\treturn '';\n\t\t});\n\t\t// TODO: throw if removeLevels > baseId levels\n\t\tif (isRelative) {\n\t\t\tlevels = baseId.split('/');\n\t\t\tlevels.splice(levels.length - removeLevels, removeLevels);\n\t\t\t// childId || [] is a trick to not concat if no childId\n\t\t\treturn levels.concat(childId || []).join('/');\n\t\t}\n\t\telse {\n\t\t\treturn childId;\n\t\t}\n\t}\n\n\tfunction pluginParts (id) {\n\t\tvar delPos = id.indexOf('!');\n\t\treturn {\n\t\t\tresourceId: id.substr(delPos + 1),\n\t\t\t// resourceId can be zero length\n\t\t\tpluginId: delPos >= 0 && id.substr(0, delPos)\n\t\t};\n\t}\n\n\tfunction Begetter () {}\n\n\tfunction beget (parent) {\n\t\tBegetter.prototype = parent;\n\t\tvar child = new Begetter();\n\t\tBegetter.prototype = undef;\n\t\treturn child;\n\t}\n\n\tfunction Promise () {\n\n\t\tvar self, thens, complete;\n\n\t\tself = this;\n\t\tthens = [];\n\n\t\tfunction then (resolved, rejected, progressed) {\n\t\t\t// capture calls to callbacks\n\t\t\tthens.push([resolved, rejected, progressed]);\n\t\t}\n\n\t\tfunction notify (which, arg) {\n\t\t\t// complete all callbacks\n\t\t\tvar aThen, cb, i = 0;\n\t\t\twhile ((aThen = thens[i++])) {\n\t\t\t\tcb = aThen[which];\n\t\t\t\tif (cb) cb(arg);\n\t\t\t}\n\t\t}\n\n\t\tcomplete = function promiseComplete (success, arg) {\n\t\t\t// switch over to sync then()\n\t\t\tthen = success ?\n\t\t\t\tfunction (resolved, rejected) { resolved && resolved(arg); } :\n\t\t\t\tfunction (resolved, rejected) { rejected && rejected(arg); };\n\t\t\t// we no longer throw during multiple calls to resolve or reject\n\t\t\t// since we don't really provide useful information anyways.\n\t\t\tcomplete = noop;\n\t\t\t// complete all callbacks\n\t\t\tnotify(success ? 0 : 1, arg);\n\t\t};\n\n\t\tthis.then = function (resolved, rejected, progressed) {\n\t\t\tthen(resolved, rejected, progressed);\n\t\t\treturn self;\n\t\t};\n\t\tthis.resolve = function (val) {\n\t\t\tself.resolved = val;\n\t\t\tcomplete(true, val);\n\t\t};\n\t\tthis.reject = function (ex) {\n\t\t\tself.rejected = ex;\n\t\t\tcomplete(false, ex);\n\t\t};\n\t\tthis.progress = function (msg) {\n\t\t\tnotify(2, msg);\n\t\t}\n\n\t}\n\n\tvar ResourceDef = Promise; // subclassing isn't worth the extra bytes\n\n\tfunction isPromise (o) {\n\t\treturn o instanceof Promise;\n\t}\n\n\tfunction when (promiseOrValue, callback, errback, progback) {\n\t\t// we can't just sniff for then(). if we do, resources that have a\n\t\t// then() method will make dependencies wait!\n\t\tif (isPromise(promiseOrValue)) {\n\t\t\tpromiseOrValue.then(callback, errback, progback);\n\t\t}\n\t\telse {\n\t\t\tcallback(promiseOrValue);\n\t\t}\n\t}\n\n\tcore = {\n\n\t\tcreateResourceDef: function (id, cfg, isPreload, optCtxId) {\n\t\t\tvar def, ctxId;\n\n\t\t\tctxId = optCtxId == undef ? id : optCtxId;\n\n\t\t\tdef = new ResourceDef();\n\t\t\tdef.id = id;\n\t\t\tdef.isPreload = isPreload;\n\n\t\t\t// replace cache with resolved value (overwrites self in cache)\n\t\t\tdef.then(function (res) { cache[id] = res; });\n\n\t\t\t// functions that dependencies will use:\n\n\t\t\tfunction toAbsId (childId) {\n\t\t\t\treturn reduceLeadingDots(childId, ctxId);\n\t\t\t}\n\n\t\t\tfunction toUrl (n) {\n\t\t\t\t// even though internally, we don't seem to need to do\n\t\t\t\t// toAbsId, the AMD spec says we need to do this for plugins.\n\t\t\t\t// also, thesec states that we should not append an extension\n\t\t\t\t// in this function.\n\t\t\t\treturn core.resolvePathInfo(toAbsId(n), cfg).url;\n\t\t\t}\n\n\t\t\tfunction localRequire (ids, callback) {\n\t\t\t\tvar cb, rvid, childDef, earlyExport;\n\n\t\t\t\t// this is a public function, so remove ability for callback\n\t\t\t\t// fixes issue #41\n\t\t\t\tcb = callback && function () { callback.apply(undef, arguments[0]); };\n\n\t\t\t\t// RValue require (CommonJS)\n\t\t\t\tif (isType(ids, 'String')) {\n\t\t\t\t\t// return resource\n\t\t\t\t\trvid = toAbsId(ids);\n\t\t\t\t\tchildDef = cache[rvid];\n\t\t\t\t\tearlyExport = isPromise(childDef) && childDef.exports;\n\t\t\t\t\tif (!(rvid in cache) || (isPromise(childDef) && !earlyExport)) {\n\t\t\t\t\t\tthrow new Error('Module not resolved: '  + rvid);\n\t\t\t\t\t}\n\t\t\t\t\tif (cb) {\n\t\t\t\t\t\tthrow new Error('require(id, callback) not allowed');\n\t\t\t\t\t}\n\t\t\t\t\treturn earlyExport || childDef;\n\t\t\t\t}\n\n\t\t\t\t// pass the callback, so the main def won't get resolved!\n\t\t\t\tcore.getDeps(def, ids, cb);\n\n\t\t\t}\n\n\t\t\tdef.require = localRequire;\n\t\t\tlocalRequire['toUrl'] = toUrl;\n\t\t\tdef.toAbsId = toAbsId;\n\n\t\t\treturn def;\n\t\t},\n\n\t\tgetCjsRequire: function (def) {\n\t\t\treturn def.require;\n\t\t},\n\n\t\tgetCjsExports: function (def) {\n\t\t\treturn def.exports || (def.exports = {});\n\t\t},\n\n\t\tgetCjsModule: function (def) {\n\t\t\tvar module = def.module;\n\t\t\tif (!module) {\n\t\t\t\tmodule = def.module = {\n\t\t\t\t\t'id': def.id,\n\t\t\t\t\t'uri': core.getDefUrl(def),\n\t\t\t\t\t'exports': core.getCjsExports(def)\n\t\t\t\t};\n\t\t\t\tmodule.exports = module['exports'];\n\t\t\t}\n\t\t\treturn module;\n\t\t},\n\n\t\tgetDefUrl: function (def) {\n\t\t\t// note: don't look up an anon module's id from it's own toUrl cuz\n\t\t\t// the parent's config was used to find this module\n\t\t\t// the toUrl fallback is for named modules in built files\n\t\t\t// which must have absolute ids.\n\t\t\treturn def.url || (def.url = core.checkToAddJsExt(def.require['toUrl'](def.id)));\n\t\t},\n\n\t\textractCfg: function (cfg) {\n\t\t\tvar pluginCfgs;\n\n\t\t\t// set defaults and convert from closure-safe names\n\t\t\tcfg.baseUrl = cfg['baseUrl'] || '';\n\t\t\tcfg.pluginPath = 'pluginPath' in cfg ? cfg['pluginPath'] : 'curl/plugin';\n\n\t\t\t// create object to hold path map.\n\t\t\t// each plugin and package will have its own pathMap, too.\n\t\t\tcfg.pathMap = {};\n\t\t\tpluginCfgs = cfg.plugins = cfg['plugins'] || {};\n\n\t\t\t// temporary arrays of paths. this will be converted to\n\t\t\t// a regexp for fast path parsing.\n\t\t\tcfg.pathList = [];\n\n\t\t\t// normalizes path/package info and places info on either\n\t\t\t// the global cfg.pathMap or on a plugin-specific altCfg.pathMap.\n\t\t\t// also populates a pathList on cfg or plugin configs.\n\t\t\tfunction fixAndPushPaths (coll, isPkg) {\n\t\t\t\tvar id, pluginId, data, parts, pluginCfg, info;\n\t\t\t\tfor (var name in coll) {\n\t\t\t\t\tdata = coll[name];\n\t\t\t\t\tpluginCfg = cfg;\n\t\t\t\t\t// grab the package id, if specified. default to\n\t\t\t\t\t// property name.\n\t\t\t\t\tparts = pluginParts(removeEndSlash(data['id'] || data['name'] || name));\n\t\t\t\t\tid = parts.resourceId;\n\t\t\t\t\tpluginId = parts.pluginId;\n\t\t\t\t\tif (pluginId) {\n\t\t\t\t\t\t// plugin-specific path\n\t\t\t\t\t\tpluginCfg = pluginCfgs[pluginId];\n\t\t\t\t\t\tif (!pluginCfg) {\n\t\t\t\t\t\t\tpluginCfg = pluginCfgs[pluginId] = beget(cfg);\n\t\t\t\t\t\t\tpluginCfg.pathMap = beget(cfg.pathMap);\n\t\t\t\t\t\t\tpluginCfg.pathList = [];\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// remove plugin-specific path from coll\n\t\t\t\t\t\tdelete coll[name];\n\t\t\t\t\t}\n\t\t\t\t\tif (isPkg) {\n\t\t\t\t\t\tinfo = normalizePkgDescriptor(data);\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\tinfo = { path: removeEndSlash(data) };\n\t\t\t\t\t}\n\t\t\t\t\tinfo.specificity = id.split('/').length;\n//\t\t\t\t\tinfo.specificity = (id.match(findSlashRx) || []).length;\n\t\t\t\t\tif (id) {\n\t\t\t\t\t\tpluginCfg.pathMap[id] = info;\n\t\t\t\t\t\tpluginCfg.pathList.push(id);\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\t// naked plugin name signifies baseUrl for plugin\n\t\t\t\t\t\t// resources. baseUrl could be relative to global\n\t\t\t\t\t\t// baseUrl.\n\t\t\t\t\t\tpluginCfg.baseUrl = core.resolveUrl(data, cfg);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// adds the path matching regexp onto the cfg or plugin cfgs.\n\t\t\tfunction convertPathMatcher (cfg) {\n\t\t\t\tvar pathMap = cfg.pathMap;\n\t\t\t\tcfg.pathRx = new RegExp('^(' +\n\t\t\t\t\tcfg.pathList.sort(function (a, b) { return pathMap[a].specificity < pathMap[b].specificity; } )\n\t\t\t\t\t\t.join('|')\n\t\t\t\t\t\t.replace(/\\//g, '\\\\/') +\n\t\t\t\t\t')(?=\\\\/|$)'\n\t\t\t\t);\n\t\t\t\tdelete cfg.pathList;\n\t\t\t}\n\n\t\t\t// fix all paths and packages\n\t\t\tfixAndPushPaths(cfg['paths'], false);\n\t\t\tfixAndPushPaths(cfg['packages'], true);\n\n\t\t\t// create search regex for each path map\n\t\t\tfor (var p in pluginCfgs) {\n\t\t\t\tvar pathList = pluginCfgs[p].pathList;\n\t\t\t\tif (pathList) {\n\t\t\t\t\tpluginCfgs[p].pathList = pathList.concat(cfg.pathList);\n\t\t\t\t\tconvertPathMatcher(pluginCfgs[p]);\n\t\t\t\t}\n\t\t\t}\n\t\t\tconvertPathMatcher(cfg);\n\n\t\t\treturn cfg;\n\n\t\t},\n\n\t\tcheckPreloads: function (cfg) {\n\t\t\tvar preloads = cfg['preloads'];\n\t\t\tif (preloads && preloads.length > 0){\n\t\t\t\t// chain from previous preload, if any (revisit when\n\t\t\t\t// doing package-specific configs).\n\t\t\t\twhen(preload, function () {\n\t\t\t\t\tpreload = core.createResourceDef(undef, cfg, true);\n\t\t\t\t\tcore.getDeps(preload, preloads);\n\t\t\t\t});\n\t\t\t}\n\n\t\t},\n\n\t\tresolvePathInfo: function (id, cfg, forPlugin) {\n\t\t\t// searches through the configured path mappings and packages\n\t\t\tvar pathMap, pathInfo, path, pkgCfg, found;\n\n\t\t\tpathMap = cfg.pathMap;\n\n\t\t\tif (forPlugin && cfg.pluginPath && id.indexOf('/') < 0 && !(id in pathMap)) {\n\t\t\t\t// prepend plugin folder path, if it's missing and path isn't in pathMap\n\t\t\t\t// Note: this munges the concepts of ids and paths for plugins,\n\t\t\t\t// but is generally safe since it's only for non-namespaced\n\t\t\t\t// plugins (plugins without path or package info).\n\t\t\t\tid = joinPath(cfg.pluginPath, id);\n\t\t\t}\n\n\t\t\tif (!absUrlRx.test(id)) {\n\t\t\t\tpath = id.replace(cfg.pathRx, function (match) {\n\n\t\t\t\t\tpathInfo = pathMap[match] || {};\n\t\t\t\t\tfound = true;\n\t\t\t\t\tpkgCfg = pathInfo.config;\n\n\t\t\t\t\t// if pathInfo.main and match == id, this is a main module\n\t\t\t\t\tif (pathInfo.main && match == id) {\n\t\t\t\t\t\treturn pathInfo.main;\n\t\t\t\t\t}\n\t\t\t\t\t// if pathInfo.path return pathInfo.path\n\t\t\t\t\telse {\n\t\t\t\t\t\treturn pathInfo.path || '';\n\t\t\t\t\t}\n\n\t\t\t\t});\n\t\t\t}\n\t\t\telse {\n\t\t\t\tpath = id;\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\tpath: path,\n\t\t\t\tconfig: pkgCfg || userCfg,\n\t\t\t\turl: core.resolveUrl(path, cfg)\n\t\t\t};\n\t\t},\n\n\t\tresolveUrl: function (path, cfg) {\n\t\t\tvar baseUrl = cfg.baseUrl;\n\t\t\treturn baseUrl && !absUrlRx.test(path) ? joinPath(baseUrl, path) : path;\n\t\t},\n\n\t\tcheckToAddJsExt: function (url) {\n\t\t\t// don't add extension if a ? is found in the url (query params)\n\t\t\t// i'd like to move this feature to a moduleLoader\n\t\t\treturn url + (dontAddExtRx.test(url) ? '' : '.js');\n\t\t},\n\n\t\tloadScript: function (def, success, failure) {\n\t\t\t// script processing rules learned from RequireJS\n\n\t\t\t// insert script\n\t\t\tvar el = doc.createElement('script');\n\n\t\t\t// initial script processing\n\t\t\tfunction process (ev) {\n\t\t\t\tev = ev || global.event;\n\t\t\t\t// detect when it's done loading\n\t\t\t\tif (ev.type == 'load' || readyStates[el.readyState]) {\n\t\t\t\t\tdelete activeScripts[def.id];\n\t\t\t\t\t// release event listeners\n\t\t\t\t\tel.onload = el.onreadystatechange = el.onerror = ''; // ie cries if we use undefined\n\t\t\t\t\tsuccess();\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfunction fail (e) {\n\t\t\t\t// some browsers send an event, others send a string,\n\t\t\t\t// but none of them send anything useful, so just say we failed:\n\t\t\t\tfailure(new Error('Syntax or http error: ' + def.url));\n\t\t\t}\n\n\t\t\t// set type first since setting other properties could\n\t\t\t// prevent us from setting this later\n\t\t\t// actually, we don't even need to set this at all\n\t\t\t//el.type = 'text/javascript';\n\t\t\t// using dom0 event handlers instead of wordy w3c/ms\n\t\t\tel.onload = el.onreadystatechange = process;\n\t\t\tel.onerror = fail;\n\t\t\t// TODO: support other charsets?\n\t\t\tel.charset = 'utf-8';\n\t\t\tel.async = true;\n\t\t\tel.src = def.url;\n\n\t\t\t// loading will start when the script is inserted into the dom.\n\t\t\t// IE will load the script sync if it's in the cache, so\n\t\t\t// indicate the current resource definition if this happens.\n\t\t\tactiveScripts[def.id] = el;\n\t\t\t// use insertBefore to keep IE from throwing Operation Aborted (thx Bryan Forbes!)\n\t\t\thead.insertBefore(el, head.firstChild);\n\n\t\t},\n\n\t\textractCjsDeps: function (defFunc) {\n\t\t\t// Note: ignores require() inside strings and comments\n\t\t\tvar source, ids = [], currQuote;\n\t\t\t// prefer toSource (FF) since it strips comments\n\t\t\tsource = typeof defFunc == 'string' ?\n\t\t\t\t\t defFunc :\n\t\t\t\t\t defFunc.toSource ? defFunc.toSource() : defFunc.toString();\n\t\t\t// remove comments, then look for require() or quotes\n\t\t\tsource.replace(removeCommentsRx, '').replace(findRValueRequiresRx, function (m, id, qq) {\n\t\t\t\t// if we encounter a quote\n\t\t\t\tif (qq) {\n\t\t\t\t\tcurrQuote = currQuote == qq ? undef : currQuote;\n\t\t\t\t}\n\t\t\t\t// if we're not inside a quoted string\n\t\t\t\telse if (!currQuote) {\n\t\t\t\t\tids.push(id);\n\t\t\t\t}\n\t\t\t\treturn m; // uses least RAM/CPU\n\t\t\t});\n\t\t\treturn ids;\n\t\t},\n\n\t\tfixArgs: function (args) {\n\t\t\t// resolve args\n\t\t\t// valid combinations for define:\n\t\t\t// (string, array, object|function) sax|saf\n\t\t\t// (array, object|function) ax|af\n\t\t\t// (string, object|function) sx|sf\n\t\t\t// (object|function) x|f\n\n\t\t\tvar id, deps, defFunc, isDefFunc, len, cjs;\n\n\t\t\tlen = args.length;\n\n\t\t\tdefFunc = args[len - 1];\n\t\t\tisDefFunc = isType(defFunc, 'Function');\n\n\t\t\tif (len == 2) {\n\t\t\t\tif (isType(args[0], 'Array')) {\n\t\t\t\t\tdeps = args[0];\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tid = args[0];\n\t\t\t\t}\n\t\t\t}\n\t\t\telse if (len == 3) {\n\t\t\t\tid = args[0];\n\t\t\t\tdeps = args[1];\n\t\t\t}\n\n\t\t\t// Hybrid format: assume that a definition function with zero\n\t\t\t// dependencies and non-zero arity is a wrapped CommonJS module\n\t\t\tif (!deps && isDefFunc && defFunc.length > 0) {\n\t\t\t\tcjs = true;\n\t\t\t\tdeps = ['require', 'exports', 'module'].concat(core.extractCjsDeps(defFunc));\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\tid: id,\n\t\t\t\tdeps: deps || [],\n\t\t\t\tres: isDefFunc ? defFunc : function () { return defFunc; },\n\t\t\t\tcjs: cjs\n\t\t\t};\n\t\t},\n\n\t\texecuteDefFunc: function (def) {\n\t\t\tvar resource, moduleThis;\n\t\t\t// the force of AMD is strong so anything returned\n\t\t\t// overrides exports.\n\t\t\t// node.js assumes `this` === `exports` so we do that\n\t\t\t// for all cjs-wrapped modules, just in case.\n\t\t\t// also, use module.exports if that was set\n\t\t\t// (node.js convention).\n\t\t\t// note: if .module exists, .exports exists.\n\t\t\tmoduleThis = def.cjs ? def.exports : undef;\n\t\t\tresource = def.res.apply(moduleThis, def.deps);\n\t\t\tif (resource === undef && def.exports) {\n\t\t\t\t// note: exports will equal module.exports unless\n\t\t\t\t// module.exports was reassigned inside module.\n\t\t\t\tresource = def.module ? def.module.exports : def.exports;\n\t\t\t}\n\t\t\treturn resource;\n\t\t},\n\n\t\tresolveResDef: function (def, args) {\n\n\t\t\tdef.cjs = args.cjs;\n\n\t\t\t// get the dependencies and then resolve/reject\n\t\t\tcore.getDeps(def, args.deps,\n\t\t\t\tfunction (deps) {\n\t\t\t\t\tvar resource;\n\t\t\t\t\tdef.deps = deps;\n\t\t\t\t\tdef.res = args.res;\n\t\t\t\t\ttry {\n\t\t\t\t\t\tresource = core.executeDefFunc(def);\n\t\t\t\t\t}\n\t\t\t\t\tcatch (ex) {\n\t\t\t\t\t\tdef.reject(ex);\n\t\t\t\t\t}\n\t\t\t\t\tdef.resolve(resource);\n\t\t\t\t}\n\t\t\t);\n\n\t\t},\n\n\t\tfetchResDef: function (def) {\n\n\t\t\t// ensure url is computed\n\t\t\tcore.getDefUrl(def);\n\n\t\t\tcore.loadScript(def,\n\n\t\t\t\tfunction () {\n\t\t\t\t\tvar args = argsNet;\n\t\t\t\t\targsNet = undef; // reset it before we get deps\n\n\t\t\t\t\t// if our resource was not explicitly defined with an id (anonymous)\n\t\t\t\t\t// Note: if it did have an id, it will be resolved in the define()\n\t\t\t\t\tif (def.useNet !== false) {\n\n\t\t\t\t\t\t// if !args, nothing was added to the argsNet\n\t\t\t\t\t\tif (!args || args.ex) {\n\t\t\t\t\t\t\tdef.reject(new Error(((args && args.ex) || 'define() missing or duplicated: url').replace('url', def.url)));\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse {\n\t\t\t\t\t\t\tcore.resolveResDef(def, args);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t},\n\n\t\t\t\tdef.reject\n\n\t\t\t);\n\n\t\t\treturn def;\n\n\t\t},\n\n\t\tfetchDep: function (depName, parentDef) {\n\t\t\tvar toAbsId, isPreload, parts, mainId, loaderId, pluginId,\n\t\t\t\tresId, pathInfo, def, tempDef, resCfg;\n\n\t\t\ttoAbsId = parentDef.toAbsId;\n\t\t\tisPreload = parentDef.isPreload;\n\n\t\t\t// check for plugin loaderId\n\t\t\tparts = pluginParts(depName);\n\t\t\t// resId is not normalized since the plugin may need to do it\n\t\t\tresId = parts.resourceId;\n\n\t\t\t// get id of first resource to load (which could be a plugin)\n\t\t\tmainId = toAbsId(parts.pluginId || resId);\n\t\t\tpathInfo = core.resolvePathInfo(mainId, userCfg, !!parts.pluginId);\n\n\t\t\t// get custom module loader from package config if not a plugin\n\t\t\t// TODO: figure out how to make module loaders work with plugins\n\t\t\tif (parts.pluginId) {\n\t\t\t\tloaderId = mainId;\n\t\t\t}\n\t\t\telse {\n\t\t\t\tloaderId = pathInfo.config['moduleLoader'];\n\t\t\t\tif (loaderId) {\n\t\t\t\t\t// since we're not using toAbsId, transformers must be absolute\n\t\t\t\t\tresId = mainId;\n\t\t\t\t\tmainId = loaderId;\n\t\t\t\t\tpathInfo = core.resolvePathInfo(loaderId, userCfg);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// find resource definition\n\t\t\tdef = cache[mainId];\n\t\t\tif (!def) {\n\t\t\t\tdef = cache[mainId] = core.createResourceDef(mainId, pathInfo.config, isPreload, pathInfo.path);\n\t\t\t\tdef.url = core.checkToAddJsExt(pathInfo.url);\n\t\t\t\tcore.fetchResDef(def);\n\t\t\t}\n\n\t\t\t// plugin or transformer\n\t\t\tif (mainId == loaderId) {\n\n\t\t\t\t// we need to use depName until plugin tells us normalized id.\n\t\t\t\t// if the plugin changes the id, we need to consolidate\n\t\t\t\t// def promises below.  Note: exports objects will be different\n\t\t\t\t// between pre-normalized and post-normalized defs! does this matter?\n\t\t\t\t// don't put this resource def in the cache because if the\n\t\t\t\t// resId doesn't change, the check if this is a new\n\t\t\t\t// normalizedDef (below) will think it's already being loaded.\n\t\t\t\ttempDef = /*cache[depName] =*/ core.createResourceDef(depName);\n\n\t\t\t\t// note: this means moduleLoaders can store config info in the\n\t\t\t\t// plugins config, too.\n\t\t\t\tresCfg = userCfg.plugins[loaderId] || userCfg;\n\n\t\t\t\t// wait for plugin resource def\n\t\t\t\twhen(def, function(plugin) {\n\t\t\t\t\tvar normalizedDef, fullId;\n\n\t\t\t\t\t// check if plugin supports the normalize method\n\t\t\t\t\tif ('normalize' in plugin) {\n\t\t\t\t\t\t// dojo/has may return falsey values (0, actually)\n\t\t\t\t\t\tresId = plugin['normalize'](resId, toAbsId, resCfg) || '';\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\tresId = toAbsId(resId);\n\t\t\t\t\t}\n\n\t\t\t\t\t// use the full id (loaderId + id) to id plugin resources\n\t\t\t\t\t// so multiple plugins may each process the same resource\n\t\t\t\t\t// resId could be blank if the plugin doesn't require any (e.g. \"domReady!\")\n\t\t\t\t\tfullId = loaderId + '!' + resId;\n\t\t\t\t\tnormalizedDef = cache[fullId];\n\n\t\t\t\t\t// if this is our first time fetching this (normalized) def\n\t\t\t\t\tif (!normalizedDef) {\n\n\t\t\t\t\t\t// because we're using resId, plugins, such as wire!,\n\t\t\t\t\t\t// can use paths relative to the resource\n\t\t\t\t\t\tnormalizedDef = core.createResourceDef(fullId, resCfg, isPreload, resId);\n\n\t\t\t\t\t\t// don't cache non-determinate \"dynamic\" resources (or non-existent resources)\n\t\t\t\t\t\tif (!plugin['dynamic']) {\n\t\t\t\t\t\t\tcache[fullId] = normalizedDef;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// curl's plugins prefer to receive a deferred,\n\t\t\t\t\t\t// but to be compatible with AMD spec, we have to\n\t\t\t\t\t\t// piggy-back on the callback function parameter:\n\t\t\t\t\t\tvar loaded = function (res) {\n\t\t\t\t\t\t\tnormalizedDef.resolve(res);\n\t\t\t\t\t\t\tif (plugin['dynamic']) delete cache[fullId];\n\t\t\t\t\t\t};\n\t\t\t\t\t\tloaded['resolve'] = loaded;\n\t\t\t\t\t\tloaded['reject'] = normalizedDef.reject;\n\n\t\t\t\t\t\t// load the resource!\n\t\t\t\t\t\tplugin.load(resId, normalizedDef.require, loaded, resCfg);\n\n\t\t\t\t\t}\n\n\t\t\t\t\t// chain defs (resolve when plugin.load executes)\n\t\t\t\t\tif (tempDef != normalizedDef) {\n\t\t\t\t\t\twhen(normalizedDef, tempDef.resolve, tempDef.reject);\n\t\t\t\t\t}\n\n\t\t\t\t}, tempDef.reject);\n\n\t\t\t}\n\n\t\t\t// return tempDef if this is a plugin-based resource\n\t\t\treturn tempDef || def;\n\t\t},\n\n\t\tgetDeps: function (parentDef, names, overrideCallback) {\n\t\t\tvar deps, count, len, i, name, completed, callback;\n\n\t\t\tdeps = [];\n\t\t\tcount = len = names.length;\n\t\t\tcompleted = false;\n\t\t\tcallback = overrideCallback || parentDef.resolve;\n\n\t\t\tfunction checkDone () {\n\t\t\t\tif (--count == 0) {\n\t\t\t\t\t// Note: IE may have obtained the dependencies sync, thus the completed flag\n\t\t\t\t\tcompleted = true;\n\t\t\t\t\tcallback(deps);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfunction getDep (index, depName) {\n\t\t\t\tvar childDef, doOnce;\n\n\t\t\t\tchildDef = core.fetchDep(depName, parentDef);\n\n\t\t\t\tdoOnce = function (dep) {\n\t\t\t\t\tdeps[index] = dep; // got it!\n\t\t\t\t\tcheckDone();\n\t\t\t\t\t// only run once for this dep (in case of early exports)\n\t\t\t\t\tdoOnce = noop;\n\t\t\t\t};\n\n\t\t\t\tfunction doSuccess (dep) {\n\t\t\t\t\tdoOnce(dep);\n\t\t\t\t}\n\n\t\t\t\tfunction doFailure (ex) {\n\t\t\t\t\tcompleted = true;\n\t\t\t\t\tparentDef.reject(ex);\n\t\t\t\t}\n\n\t\t\t\tfunction doProgress (msg) {\n\t\t\t\t\t// only early-export to modules that also export since\n\t\t\t\t\t// pure AMD modules don't expect to get an early export\n\t\t\t\t\t// Note: this logic makes dojo 1.7 work, too.\n\t\t\t\t\tif (msg == msgUsingExports && parentDef.exports) {\n\t\t\t\t\t\tdoOnce(childDef.exports);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// hook into promise callbacks.\n\t\t\t\twhen(childDef, doSuccess, doFailure, doProgress);\n\n\t\t\t}\n\n\t\t\t// wait for preload before fetching any other modules\n\t\t\twhen(parentDef.isPreload || preload, function () {\n\n\t\t\t\tfor (i = 0; i < len && !completed; i++) {\n\t\t\t\t\tname = names[i];\n\t\t\t\t\tif (name in cjsGetters) {\n\t\t\t\t\t\t// is this \"require\", \"exports\", or \"module\"?\n\t\t\t\t\t\tdeps[i] = cjsGetters[name](parentDef);\n\t\t\t\t\t\tcheckDone();\n\t\t\t\t\t}\n\t\t\t\t\t// check for blanks. fixes #32.\n\t\t\t\t\t// this helps support yepnope.js, has.js, and the has! plugin\n\t\t\t\t\telse if (names[i]) {\n\t\t\t\t\t\tgetDep(i, names[i]);\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\tcheckDone();\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (parentDef.exports) {\n\t\t\t\t\t// announce\n\t\t\t\t\tparentDef.progress(msgUsingExports);\n\t\t\t\t}\n\n\t\t\t\tif (count == 0 && !completed) {\n\t\t\t\t\t// there were none to fetch\n\t\t\t\t\tcallback(deps);\n\t\t\t\t}\n\n\t\t\t});\n\n\t\t},\n\n\t\tgetCurrentDefName: function () {\n\t\t\t// IE marks the currently executing thread as \"interactive\"\n\t\t\t// Note: Opera lies about which scripts are \"interactive\", so we\n\t\t\t// just have to test for it. Opera provides a true browser test, not\n\t\t\t// a UA sniff, thankfully.\n\t\t\t// learned this trick from James Burke's RequireJS\n\t\t\tvar def;\n\t\t\tif (!isType(global.opera, 'Opera')) {\n\t\t\t\tfor (var d in activeScripts) {\n\t\t\t\t\tif (readyStates[activeScripts[d].readyState] == interactive) {\n\t\t\t\t\t\tdef = d;\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\treturn def;\n\t\t}\n\n\t};\n\n\t// hook-up cjs free variable getters\n\tcjsGetters = {'require': core.getCjsRequire, 'exports': core.getCjsExports, 'module': core.getCjsModule};\n\n\tfunction _curl (/* various */) {\n\n\t\tvar args = [].slice.call(arguments), ids;\n\n\t\t// extract config, if it's specified\n\t\tif (isType(args[0], 'Object')) {\n\t\t\tuserCfg = core.extractCfg(args.shift());\n\t\t\tcore.checkPreloads(userCfg);\n\t\t}\n\n\t\t// thanks to Joop Ringelberg for helping troubleshoot the API\n\t\tfunction CurlApi (ids, callback, waitFor) {\n\t\t\tvar then, def;\n\t\t\tdef = core.createResourceDef(undef, userCfg);\n\t\t\tthis['then'] = then = function (resolved, rejected) {\n\t\t\t\twhen(def,\n\t\t\t\t\t// return the dependencies as arguments, not an array\n\t\t\t\t\tfunction (deps) { if (resolved) resolved.apply(undef, deps); },\n\t\t\t\t\t// just throw if the dev didn't specify an error handler\n\t\t\t\t\tfunction (ex) { if (rejected) rejected(ex); else throw ex; }\n\t\t\t\t);\n\t\t\t\treturn this;\n\t\t\t};\n\t\t\tthis['next'] = function (ids, cb) {\n\t\t\t\t// chain api\n\t\t\t\treturn new CurlApi(ids, cb, def);\n\t\t\t};\n\t\t\tif (callback) then(callback);\n\t\t\twhen(waitFor, function () {\n\t\t\t\tcore.getDeps(def, [].concat(ids));\n\t\t\t});\n\t\t}\n\n\t\tids = [].concat(args[0]); // force to array TODO: create unit test\n\t\treturn new CurlApi(ids, args[1]);\n\n\t}\n\n\tfunction _define (args) {\n\n\t\tvar id = args.id;\n\n\t\tif (id == undef) {\n\t\t\tif (argsNet !== undef) {\n\t\t\t\targsNet = {ex: 'Multiple anonymous defines in url'};\n\t\t\t}\n\t\t\telse if (!(id = core.getCurrentDefName())/* intentional assignment */) {\n\t\t\t\t// anonymous define(), defer processing until after script loads\n\t\t\t\targsNet = args;\n\t\t\t}\n\t\t}\n\t\tif (id != undef) {\n\t\t\t// named define(), it is in the cache if we are loading a dependency\n\t\t\t// (could also be a secondary define() appearing in a built file, etc.)\n\t\t\tvar def = cache[id];\n\t\t\tif (!def) {\n\t\t\t\t// id is an absolute id in this case, so we can get the config.\n\t\t\t\t// there's no way to allow a named define to fetch dependencies\n\t\t\t\t// in the preload phase since we can't cascade the parent def.\n\t\t\t\tvar cfg = core.resolvePathInfo(id, userCfg).config;\n\t\t\t\tdef = cache[id] = core.createResourceDef(id, cfg);\n\t\t\t}\n\t\t\t// check if this resource has already been resolved (can happen if\n\t\t\t// a module was defined inside a built file and outside of it and\n\t\t\t// dev didn't coordinate it explicitly)\n\t\t\tif (isPromise(def)) {\n\t\t\t\tdef.useNet = false;\n\t\t\t\tcore.resolveResDef(def, args);\n\t\t\t}\n\t\t}\n\n\t}\n\n\t/***** grab any global configuration info *****/\n\n\t// if userCfg is a function, assume curl() exists already\n\tif (isType(userCfg, 'Function')) return;\n\n\tuserCfg = core.extractCfg(userCfg || {});\n\tcore.checkPreloads(userCfg);\n\n\t/***** define public API *****/\n\n\tvar apiName, apiContext, define;\n\n\t// allow curl to be renamed and added to a specified context\n\tapiName = userCfg['apiName'] || 'curl';\n\tapiContext = userCfg['apiContext'] || global;\n\tapiContext[apiName] = _curl;\n\n\t// allow curl to be a dependency\n\tcache['curl'] = _curl;\n\n\t// wrap inner _define so it can be replaced without losing define.amd\n\tdefine = global['define'] = function () {\n\t\tvar args = core.fixArgs(arguments);\n\t\t_define(args);\n\t};\n\t_curl['version'] = version;\n\n\t// indicate our capabilities:\n\tdefine['amd'] = { 'plugins': true, 'jQuery': true, 'curl': version };\n\n\t// expose curl core for special plugins and modules\n\t// Note: core overrides will only work in either of two scenarios:\n\t// 1. the files are running un-compressed (Google Closure or Uglify)\n\t// 2. the overriding module was compressed with curl.js\n\t// Compiling curl and the overriding module separately won't work.\n\tcache['curl/_privileged'] = {\n\t\t'core': core,\n\t\t'cache': cache,\n\t\t'cfg': userCfg,\n\t\t'_define': _define,\n\t\t'_curl': _curl,\n\t\t'ResourceDef': ResourceDef\n\t};\n\n}(this));"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/json3/vendor/evalJSON.js",
    "content": "/**\n* @name JSONParser\n* @version 1.0.0\n* @author Asen Bozhilov\n* @date 2011-02-15\n*\n* @license MIT\n*\n* @description\n* Javascript parser of JSON (JavaScript Object Notation) according ECMAScript 5 JSON grammar\n*\n* @contributors\n* Alexander a.k.a @bga_\n*\n* @usage\n* var jsValue = evalJSON(JSONStr, function reviver(name, value) {return value;});\n*/\n\n\nvar evalJSON = (function () {\n\n    var LEFT_CURLY = '{',\n        RIGHT_CURLY = '}',\n        COLON = ':',\n        LEFT_BRACE = '[',\n        RIGHT_BRACE = ']',\n        COMMA = ',';\n\n    var tokenizer = /^(?:[{}:,\\[\\]]|true|false|null|\"(?:[^\"\\\\\\u0000-\\u001F]|\\\\[\"\\\\\\/bfnrt]|\\\\u[0-9A-F]{4})*\"|-?(?:0|[1-9]\\d*)(?:\\.\\d+)?(?:[eE][+-]?\\d+)?)/,\n        whiteSpace = /^[\\t ]+/,\n        lineTerminator = /^\\r?\\n/,\n        \n        tokenType = {\n            PUNCTUATOR : 1,\n            STRING : 2,\n            NUMBER : 3,\n            BOOLEAN : 4,\n            NULL : 5\n        },\n    \n        tokenMap = {\n            '{' : 1, '}' : 1, '[' : 1, ']' : 1, ',' : 1, ':' : 1,\n            '\"' : 2,\n            't' : 4, 'f' : 4,\n            'n' : 5\n        },\n    \n        escChars = {\n            'b' : '\\b',\n            'f' : '\\f',\n            'n' : '\\n',\n            'r' : '\\r',\n            't' : '\\t',\n            '\"' : '\"',\n            '\\\\' : '\\\\',\n            '/' : '/'\n        };\n        \n    function JSONLexer(JSONStr) {\n        this.line = 1;\n        this.col = 1;\n        this._tokLen = 0;\n        this._str = JSONStr;\n    }\n\n    JSONLexer.prototype = {\n        getNextToken : function () {\n            var str = this._str,\n                token, type;\n            \n            this.col += this._tokLen;\n            \n            if (!str.length) {\n                return 'END';\n            }\n            \n            token = tokenizer.exec(str);\n            \n            if (token) {\n                type = tokenMap[token[0].charAt(0)] || tokenType.NUMBER;\n            }\n            else if ((token = whiteSpace.exec(str))) {\n                this._tokLen = token[0].length;\n                this._str = str.slice(this._tokLen);\n                return this.getNextToken();\n            }\n            else if ((token = lineTerminator.exec(str))) {\n                this._tokLen = 0;\n                this._str = str.slice(token[0].length);\n                this.line++;\n                this.col = 1;\n                return this.getNextToken();\n            }\n            else {\n                this.error('Invalid token');\n            }\n            \n            this._tokLen = token[0].length;\n            this._str = str.slice(this._tokLen);\n            \n            return {\n                type : type,\n                value : token[0]\n            };\n        },\n        \n        error : function (message, line, col) {\n            var err = new SyntaxError(message);\n            err.line = line || this.line;\n            err.col = col || this.col;\n            \n            throw err;\n        }\n    }\n\n    function JSONParser(lexer) {\n        this.lex = lexer;\n    }\n\n    JSONParser.prototype = {\n        parse : function () {\n            var lex = this.lex,\n                jsValue = this.getValue();\n                \n            if (lex.getNextToken() !== 'END') {\n                lex.error('Illegal token');\n            }\n            \n            return jsValue;\n        },\n        \n        getObject : function () {\n            var jsObj = {},\n                lex = this.lex,\n                token, tval, prop,\n                line, col,\n                pairs = false;\n                \n            while (true) {\n                token = lex.getNextToken();\n                tval = token.value;\n                \n                if (tval == RIGHT_CURLY) {\n                    return jsObj;\n                }\n                \n                if (pairs) {\n                    if (tval == COMMA) {\n                        line = lex.line;\n                        col = lex.col - 1;                    \n                        token = lex.getNextToken();\n                        tval = token.value;\n                        if (tval == RIGHT_CURLY) {\n                            lex.error('Invalid trailing comma', line, col);\n                        }\n                    }\n                    else {\n                        lex.error('Illegal token where expect comma or right curly bracket');\n                    }\n                }\n                else if (tval == COMMA) {\n                    lex.error('Invalid leading comma');\n                }\n                \n                if (token.type != tokenType.STRING) {\n                    lex.error('Illegal token where expect string property name');\n                }\n                \n                prop = this.getString(tval);\n                \n                token = lex.getNextToken();\n                tval = token.value;\n                \n                if (tval != COLON) {\n                    lex.error('Illegal token where expect colon');\n                }\n                \n                jsObj[prop] = this.getValue();\n                pairs = true;\n            }\n        },\n        \n        getArray : function () {\n            var jsArr = [],\n                lex = this.lex,\n                token, tval, prop,\n                line, col,                \n                values = false;\n            while (true) {\n                token = lex.getNextToken();\n                tval = token.value;\n                \n                if (tval == RIGHT_BRACE) {\n                    return jsArr;\n                }\n                \n                if (values) {\n                    if (tval == COMMA) {\n                        line = lex.line;\n                        col = lex.col - 1;\n                        token = lex.getNextToken();\n                        tval = token.value;\n                        if (tval == RIGHT_BRACE) {\n                            lex.error('Invalid trailing comma', line, col);\n                        }\n                    }\n                    else {\n                        lex.error('Illegal token where expect comma or right square bracket');\n                    }\n                }\n                else if (tval == COMMA) {\n                    lex.error('Invalid leading comma');\n                }\n                \n                jsArr.push(this.getValue(token));\n                values = true;\n            }\n        },\n        \n        getString : function (strVal) {\n            return strVal.slice(1, -1).replace(/\\\\u?([0-9A-F]{4}|[\"\\\\\\/bfnrt])/g, function (match, escVal) {\n                return escChars[escVal] || String.fromCharCode(parseInt(escVal, 16));\n            });\n        },\n        \n        getValue : function(fromToken) {\n            var lex = this.lex,\n                token = fromToken || lex.getNextToken(),\n                tval = token.value;\n            switch (token.type) {\n                case tokenType.PUNCTUATOR:\n                    if (tval == LEFT_CURLY) {\n                        return this.getObject();\n                    }\n                    else if (tval == LEFT_BRACE) {\n                        return this.getArray();\n                    }\n                    else {\n                        lex.error('Illegal punctoator');\n                    }\n                case tokenType.STRING:\n                    return this.getString(tval);\n                case tokenType.NUMBER:\n                    return Number(tval);\n                case tokenType.BOOLEAN:\n                    return tval === \"true\";\n                case tokenType.NULL:\n                    return null;\n                default:\n                    lex.error('Invalid value');\n           }\n        }\n    };\n    \n    var getClass = Object.prototype.toString,\n        hasOwnProp = Object.prototype.hasOwnProperty;\n    \n    function filter(base, prop, value) {\n        if (typeof value == 'undefined') {\n            delete base[prop];\n            return;\n        }\n        base[prop] = value;\n    }\n    \n    function walk(holder, name, rev) {\n        var val = holder[name],\n            i, len;\n        \n        if (typeof val == 'object' && val) {\n            if (getClass.call(val) == '[object Array]') {\n                for (i = 0, len = val.length; i < len; i++) {\n                    filter(val, i, walk(val, i, rev));\n                }\n            }\n            else {\n                for (i in val) {\n                    if (hasOwnProp.call(val, i)) {\n                        filter(val, i, walk(val, i, rev));\n                    }\n                }\n            }\n        }\n        \n        return rev.call(holder, name, val);\n    }\n        \n    return function (JSONStr, reviver) {\n        var jsVal = new JSONParser(new JSONLexer(JSONStr)).parse();\n        if (typeof reviver == 'function') {\n            return walk({'' : jsVal}, '', reviver);\n        }\n        return jsVal;\n    };\n})();\n\n\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/json3/vendor/json2.js",
    "content": "/*\n    http://www.JSON.org/json2.js\n    2011-02-23\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\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    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\n/*jslint evil: true, strict: false, regexp: false */\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\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\nvar JSON;\nif (!JSON) {\n    JSON = {};\n}\n\n(function () {\n    \"use strict\";\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) ? '\"' + 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        }) + '\"' : '\"' + string + '\"';\n    }\n\n\n    function str(key, holder) {\n\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 ? '[]' : gap ?\n                    '[\\n' + gap + partial.join(',\\n' + gap) + '\\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                    if (typeof rep[i] === 'string') {\n                        k = rep[i];\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.prototype.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 ? '{}' : gap ?\n                '{\\n' + gap + partial.join(',\\n' + gap) + '\\n' + mind + '}' :\n                '{' + 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\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.prototype.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            text = String(text);\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]*$/\n                    .test(text.replace(/\\\\(?:[\"\\\\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@')\n                        .replace(/\"[^\"\\\\\\n\\r]*\"|true|false|null|-?\\d+(?:\\.\\d*)?(?:[eE][+\\-]?\\d+)?/g, ']')\n                        .replace(/(?:^|:|,)(?:\\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": "flowable-ui-web/admin/bower_components/json3/vendor/json_parse.js",
    "content": "/*\n    json_parse.js\n    2011-03-06\n\n    Public Domain.\n\n    NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.\n\n    This file creates a json_parse function.\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    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/*members \"\", \"\\\"\", \"\\/\", \"\\\\\", at, b, call, charAt, f, fromCharCode,\n    hasOwnProperty, message, n, name, prototype, push, r, t, text\n*/\n\nvar json_parse = (function () {\n    \"use strict\";\n\n// This is a function that can parse a JSON text, producing a JavaScript\n// data structure. It is a simple, recursive descent parser. It does not use\n// eval or regular expressions, so it can be used as a model for implementing\n// a JSON parser in other languages.\n\n// We are defining the function inside of another function to avoid creating\n// global variables.\n\n    var at,     // The index of the current character\n        ch,     // The current character\n        escapee = {\n            '\"':  '\"',\n            '\\\\': '\\\\',\n            '/':  '/',\n            b:    '\\b',\n            f:    '\\f',\n            n:    '\\n',\n            r:    '\\r',\n            t:    '\\t'\n        },\n        text,\n\n        error = function (m) {\n\n// Call error when something is wrong.\n\n            throw {\n                name:    'SyntaxError',\n                message: m,\n                at:      at,\n                text:    text\n            };\n        },\n\n        next = function (c) {\n\n// If a c parameter is provided, verify that it matches the current character.\n\n            if (c && c !== ch) {\n                error(\"Expected '\" + c + \"' instead of '\" + ch + \"'\");\n            }\n\n// Get the next character. When there are no more characters,\n// return the empty string.\n\n            ch = text.charAt(at);\n            at += 1;\n            return ch;\n        },\n\n        number = function () {\n\n// Parse a number value.\n\n            var number,\n                string = '';\n\n            if (ch === '-') {\n                string = '-';\n                next('-');\n            }\n            while (ch >= '0' && ch <= '9') {\n                string += ch;\n                next();\n            }\n            if (ch === '.') {\n                string += '.';\n                while (next() && ch >= '0' && ch <= '9') {\n                    string += ch;\n                }\n            }\n            if (ch === 'e' || ch === 'E') {\n                string += ch;\n                next();\n                if (ch === '-' || ch === '+') {\n                    string += ch;\n                    next();\n                }\n                while (ch >= '0' && ch <= '9') {\n                    string += ch;\n                    next();\n                }\n            }\n            number = +string;\n            if (!isFinite(number)) {\n                error(\"Bad number\");\n            } else {\n                return number;\n            }\n        },\n\n        string = function () {\n\n// Parse a string value.\n\n            var hex,\n                i,\n                string = '',\n                uffff;\n\n// When parsing for string values, we must look for \" and \\ characters.\n\n            if (ch === '\"') {\n                while (next()) {\n                    if (ch === '\"') {\n                        next();\n                        return string;\n                    } else if (ch === '\\\\') {\n                        next();\n                        if (ch === 'u') {\n                            uffff = 0;\n                            for (i = 0; i < 4; i += 1) {\n                                hex = parseInt(next(), 16);\n                                if (!isFinite(hex)) {\n                                    break;\n                                }\n                                uffff = uffff * 16 + hex;\n                            }\n                            string += String.fromCharCode(uffff);\n                        } else if (typeof escapee[ch] === 'string') {\n                            string += escapee[ch];\n                        } else {\n                            break;\n                        }\n                    } else {\n                        string += ch;\n                    }\n                }\n            }\n            error(\"Bad string\");\n        },\n\n        white = function () {\n\n// Skip whitespace.\n\n            while (ch && ch <= ' ') {\n                next();\n            }\n        },\n\n        word = function () {\n\n// true, false, or null.\n\n            switch (ch) {\n            case 't':\n                next('t');\n                next('r');\n                next('u');\n                next('e');\n                return true;\n            case 'f':\n                next('f');\n                next('a');\n                next('l');\n                next('s');\n                next('e');\n                return false;\n            case 'n':\n                next('n');\n                next('u');\n                next('l');\n                next('l');\n                return null;\n            }\n            error(\"Unexpected '\" + ch + \"'\");\n        },\n\n        value,  // Place holder for the value function.\n\n        array = function () {\n\n// Parse an array value.\n\n            var array = [];\n\n            if (ch === '[') {\n                next('[');\n                white();\n                if (ch === ']') {\n                    next(']');\n                    return array;   // empty array\n                }\n                while (ch) {\n                    array.push(value());\n                    white();\n                    if (ch === ']') {\n                        next(']');\n                        return array;\n                    }\n                    next(',');\n                    white();\n                }\n            }\n            error(\"Bad array\");\n        },\n\n        object = function () {\n\n// Parse an object value.\n\n            var key,\n                object = {};\n\n            if (ch === '{') {\n                next('{');\n                white();\n                if (ch === '}') {\n                    next('}');\n                    return object;   // empty object\n                }\n                while (ch) {\n                    key = string();\n                    white();\n                    next(':');\n                    if (Object.hasOwnProperty.call(object, key)) {\n                        error('Duplicate key \"' + key + '\"');\n                    }\n                    object[key] = value();\n                    white();\n                    if (ch === '}') {\n                        next('}');\n                        return object;\n                    }\n                    next(',');\n                    white();\n                }\n            }\n            error(\"Bad object\");\n        };\n\n    value = function () {\n\n// Parse a JSON value. It could be an object, an array, a string, a number,\n// or a word.\n\n        white();\n        switch (ch) {\n        case '{':\n            return object();\n        case '[':\n            return array();\n        case '\"':\n            return string();\n        case '-':\n            return number();\n        default:\n            return ch >= '0' && ch <= '9' ? number() : word();\n        }\n    };\n\n// Return the json_parse function. It will have access to all of the above\n// functions and variables.\n\n    return function (source, reviver) {\n        var result;\n\n        text = source;\n        at = 0;\n        ch = ' ';\n        result = value();\n        white();\n        if (ch) {\n            error(\"Syntax error\");\n        }\n\n// If there is a reviver function, we recursively walk the new structure,\n// passing each name/value pair to the reviver function for possible\n// transformation, starting with a temporary root object that holds the result\n// in an empty key. If there is not a reviver function, we simply return the\n// result.\n\n        return typeof reviver === 'function' ? (function walk(holder, key) {\n            var k, v, value = holder[key];\n            if (value && typeof value === 'object') {\n                for (k in value) {\n                    if (Object.prototype.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        }({'': result}, '')) : result;\n    };\n}());\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/json3/vendor/json_parse_state.js",
    "content": "/*\n    json_parse_state.js\n    2011-02-23\n\n    Public Domain.\n\n    NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.\n\n    This file creates a json_parse function.\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    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 regexp: false*/\n\n/*members \"\", \"\\\"\", \",\", \"\\/\", \":\", \"[\", \"\\\\\", \"]\", acomma, avalue, b,\n    call, colon, container, exec, f, false, firstavalue, firstokey,\n    fromCharCode, go, hasOwnProperty, key, length, n, null, ocomma, okey,\n    ovalue, pop, prototype, push, r, replace, slice, state, t, test, true,\n    value, \"{\", \"}\"\n*/\n\nvar json_parse = (function () {\n    \"use strict\";\n\n// This function creates a JSON parse function that uses a state machine rather\n// than the dangerous eval function to parse a JSON text.\n\n    var state,      // The state of the parser, one of\n                    // 'go'         The starting state\n                    // 'ok'         The final, accepting state\n                    // 'firstokey'  Ready for the first key of the object or\n                    //              the closing of an empty object\n                    // 'okey'       Ready for the next key of the object\n                    // 'colon'      Ready for the colon\n                    // 'ovalue'     Ready for the value half of a key/value pair\n                    // 'ocomma'     Ready for a comma or closing }\n                    // 'firstavalue' Ready for the first value of an array or\n                    //              an empty array\n                    // 'avalue'     Ready for the next value of an array\n                    // 'acomma'     Ready for a comma or closing ]\n        stack,      // The stack, for controlling nesting.\n        container,  // The current container object or array\n        key,        // The current key\n        value,      // The current value\n        escapes = { // Escapement translation table\n            '\\\\': '\\\\',\n            '\"': '\"',\n            '/': '/',\n            't': '\\t',\n            'n': '\\n',\n            'r': '\\r',\n            'f': '\\f',\n            'b': '\\b'\n        },\n        string = {   // The actions for string tokens\n            go: function () {\n                state = 'ok';\n            },\n            firstokey: function () {\n                key = value;\n                state = 'colon';\n            },\n            okey: function () {\n                key = value;\n                state = 'colon';\n            },\n            ovalue: function () {\n                state = 'ocomma';\n            },\n            firstavalue: function () {\n                state = 'acomma';\n            },\n            avalue: function () {\n                state = 'acomma';\n            }\n        },\n        number = {   // The actions for number tokens\n            go: function () {\n                state = 'ok';\n            },\n            ovalue: function () {\n                state = 'ocomma';\n            },\n            firstavalue: function () {\n                state = 'acomma';\n            },\n            avalue: function () {\n                state = 'acomma';\n            }\n        },\n        action = {\n\n// The action table describes the behavior of the machine. It contains an\n// object for each token. Each object contains a method that is called when\n// a token is matched in a state. An object will lack a method for illegal\n// states.\n\n            '{': {\n                go: function () {\n                    stack.push({state: 'ok'});\n                    container = {};\n                    state = 'firstokey';\n                },\n                ovalue: function () {\n                    stack.push({container: container, state: 'ocomma', key: key});\n                    container = {};\n                    state = 'firstokey';\n                },\n                firstavalue: function () {\n                    stack.push({container: container, state: 'acomma'});\n                    container = {};\n                    state = 'firstokey';\n                },\n                avalue: function () {\n                    stack.push({container: container, state: 'acomma'});\n                    container = {};\n                    state = 'firstokey';\n                }\n            },\n            '}': {\n                firstokey: function () {\n                    var pop = stack.pop();\n                    value = container;\n                    container = pop.container;\n                    key = pop.key;\n                    state = pop.state;\n                },\n                ocomma: function () {\n                    var pop = stack.pop();\n                    container[key] = value;\n                    value = container;\n                    container = pop.container;\n                    key = pop.key;\n                    state = pop.state;\n                }\n            },\n            '[': {\n                go: function () {\n                    stack.push({state: 'ok'});\n                    container = [];\n                    state = 'firstavalue';\n                },\n                ovalue: function () {\n                    stack.push({container: container, state: 'ocomma', key: key});\n                    container = [];\n                    state = 'firstavalue';\n                },\n                firstavalue: function () {\n                    stack.push({container: container, state: 'acomma'});\n                    container = [];\n                    state = 'firstavalue';\n                },\n                avalue: function () {\n                    stack.push({container: container, state: 'acomma'});\n                    container = [];\n                    state = 'firstavalue';\n                }\n            },\n            ']': {\n                firstavalue: function () {\n                    var pop = stack.pop();\n                    value = container;\n                    container = pop.container;\n                    key = pop.key;\n                    state = pop.state;\n                },\n                acomma: function () {\n                    var pop = stack.pop();\n                    container.push(value);\n                    value = container;\n                    container = pop.container;\n                    key = pop.key;\n                    state = pop.state;\n                }\n            },\n            ':': {\n                colon: function () {\n                    if (Object.hasOwnProperty.call(container, key)) {\n                        throw new SyntaxError('Duplicate key \"' + key + '\"');\n                    }\n                    state = 'ovalue';\n                }\n            },\n            ',': {\n                ocomma: function () {\n                    container[key] = value;\n                    state = 'okey';\n                },\n                acomma: function () {\n                    container.push(value);\n                    state = 'avalue';\n                }\n            },\n            'true': {\n                go: function () {\n                    value = true;\n                    state = 'ok';\n                },\n                ovalue: function () {\n                    value = true;\n                    state = 'ocomma';\n                },\n                firstavalue: function () {\n                    value = true;\n                    state = 'acomma';\n                },\n                avalue: function () {\n                    value = true;\n                    state = 'acomma';\n                }\n            },\n            'false': {\n                go: function () {\n                    value = false;\n                    state = 'ok';\n                },\n                ovalue: function () {\n                    value = false;\n                    state = 'ocomma';\n                },\n                firstavalue: function () {\n                    value = false;\n                    state = 'acomma';\n                },\n                avalue: function () {\n                    value = false;\n                    state = 'acomma';\n                }\n            },\n            'null': {\n                go: function () {\n                    value = null;\n                    state = 'ok';\n                },\n                ovalue: function () {\n                    value = null;\n                    state = 'ocomma';\n                },\n                firstavalue: function () {\n                    value = null;\n                    state = 'acomma';\n                },\n                avalue: function () {\n                    value = null;\n                    state = 'acomma';\n                }\n            }\n        };\n\n    function debackslashify(text) {\n\n// Remove and replace any backslash escapement.\n\n        return text.replace(/\\\\(?:u(.{4})|([^u]))/g, function (a, b, c) {\n            return b ? String.fromCharCode(parseInt(b, 16)) : escapes[c];\n        });\n    }\n\n    return function (source, reviver) {\n\n// A regular expression is used to extract tokens from the JSON text.\n// The extraction process is cautious.\n\n        var r,          // The result of the exec method.\n            tx = /^[\\x20\\t\\n\\r]*(?:([,:\\[\\]{}]|true|false|null)|(-?\\d+(?:\\.\\d*)?(?:[eE][+\\-]?\\d+)?)|\"((?:[^\\r\\n\\t\\\\\\\"]|\\\\(?:[\"\\\\\\/trnfb]|u[0-9a-fA-F]{4}))*)\")/;\n\n// Set the starting state.\n\n        state = 'go';\n\n// The stack records the container, key, and state for each object or array\n// that contains another object or array while processing nested structures.\n\n        stack = [];\n\n// If any error occurs, we will catch it and ultimately throw a syntax error.\n\n        try {\n\n// For each token...\n\n            for (;;) {\n                r = tx.exec(source);\n                if (!r) {\n                    break;\n                }\n\n// r is the result array from matching the tokenizing regular expression.\n//  r[0] contains everything that matched, including any initial whitespace.\n//  r[1] contains any punctuation that was matched, or true, false, or null.\n//  r[2] contains a matched number, still in string form.\n//  r[3] contains a matched string, without quotes but with ecapement.\n\n                if (r[1]) {\n\n// Token: Execute the action for this state and token.\n\n                    action[r[1]][state]();\n\n                } else if (r[2]) {\n\n// Number token: Convert the number string into a number value and execute\n// the action for this state and number.\n\n                    value = +r[2];\n                    number[state]();\n                } else {\n\n// String token: Replace the escapement sequences and execute the action for\n// this state and string.\n\n                    value = debackslashify(r[3]);\n                    string[state]();\n                }\n\n// Remove the token from the string. The loop will continue as long as there\n// are tokens. This is a slow process, but it allows the use of ^ matching,\n// which assures that no illegal tokens slip through.\n\n                source = source.slice(r[0].length);\n            }\n\n// If we find a state/token combination that is illegal, then the action will\n// cause an error. We handle the error by simply changing the state.\n\n        } catch (e) {\n            state = e;\n        }\n\n// The parsing is finished. If we are not in the final 'ok' state, or if the\n// remaining source contains anything except whitespace, then we did not have\n//a well-formed JSON text.\n\n        if (state !== 'ok' || /[^\\x20\\t\\n\\r]/.test(source)) {\n            throw state instanceof SyntaxError ? state : new SyntaxError('JSON');\n        }\n\n// If there is a reviver function, we recursively walk the new structure,\n// passing each name/value pair to the reviver function for possible\n// transformation, starting with a temporary root object that holds the current\n// value in an empty key. If there is not a reviver function, we simply return\n// that value.\n\n        return typeof reviver === 'function' ? (function walk(holder, key) {\n            var k, v, value = holder[key];\n            if (value && typeof value === 'object') {\n                for (k in value) {\n                    if (Object.prototype.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        }({'': value}, '')) : value;\n    };\n}());\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/json3/vendor/json_sans_eval.js",
    "content": "// This source code is free for use in the public domain.\n// NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.\n\n// http://code.google.com/p/json-sans-eval/\n\n/**\n * Parses a string of well-formed JSON text.\n *\n * If the input is not well-formed, then behavior is undefined, but it is\n * deterministic and is guaranteed not to modify any object other than its\n * return value.\n *\n * This does not use `eval` so is less likely to have obscure security bugs than\n * json2.js.\n * It is optimized for speed, so is much faster than json_parse.js.\n *\n * This library should be used whenever security is a concern (when JSON may\n * come from an untrusted source), speed is a concern, and erroring on malformed\n * JSON is *not* a concern.\n *\n *                      Pros                   Cons\n *                    +-----------------------+-----------------------+\n * json_sans_eval.js  | Fast, secure          | Not validating        |\n *                    +-----------------------+-----------------------+\n * json_parse.js      | Validating, secure    | Slow                  |\n *                    +-----------------------+-----------------------+\n * json2.js           | Fast, some validation | Potentially insecure  |\n *                    +-----------------------+-----------------------+\n *\n * json2.js is very fast, but potentially insecure since it calls `eval` to\n * parse JSON data, so an attacker might be able to supply strange JS that\n * looks like JSON, but that executes arbitrary javascript.\n * If you do have to use json2.js with untrusted data, make sure you keep\n * your version of json2.js up to date so that you get patches as they're\n * released.\n *\n * @param {string} json per RFC 4627\n * @param {function (this:Object, string, *):*} opt_reviver optional function\n *     that reworks JSON objects post-parse per Chapter 15.12 of EcmaScript3.1.\n *     If supplied, the function is called with a string key, and a value.\n *     The value is the property of 'this'.  The reviver should return\n *     the value to use in its place.  So if dates were serialized as\n *     {@code { \"type\": \"Date\", \"time\": 1234 }}, then a reviver might look like\n *     {@code\n *     function (key, value) {\n *       if (value && typeof value === 'object' && 'Date' === value.type) {\n *         return new Date(value.time);\n *       } else {\n *         return value;\n *       }\n *     }}.\n *     If the reviver returns {@code undefined} then the property named by key\n *     will be deleted from its container.\n *     {@code this} is bound to the object containing the specified property.\n * @return {Object|Array}\n * @author Mike Samuel <mikesamuel@gmail.com>\n */\nvar jsonParse = (function () {\n  var number\n      = '(?:-?\\\\b(?:0|[1-9][0-9]*)(?:\\\\.[0-9]+)?(?:[eE][+-]?[0-9]+)?\\\\b)';\n  var oneChar = '(?:[^\\\\0-\\\\x08\\\\x0a-\\\\x1f\\\"\\\\\\\\]'\n      + '|\\\\\\\\(?:[\\\"/\\\\\\\\bfnrt]|u[0-9A-Fa-f]{4}))';\n  var string = '(?:\\\"' + oneChar + '*\\\")';\n\n  // Will match a value in a well-formed JSON file.\n  // If the input is not well-formed, may match strangely, but not in an unsafe\n  // way.\n  // Since this only matches value tokens, it does not match whitespace, colons,\n  // or commas.\n  var jsonToken = new RegExp(\n      '(?:false|true|null|[\\\\{\\\\}\\\\[\\\\]]'\n      + '|' + number\n      + '|' + string\n      + ')', 'g');\n\n  // Matches escape sequences in a string literal\n  var escapeSequence = new RegExp('\\\\\\\\(?:([^u])|u(.{4}))', 'g');\n\n  // Decodes escape sequences in object literals\n  var escapes = {\n    '\"': '\"',\n    '/': '/',\n    '\\\\': '\\\\',\n    'b': '\\b',\n    'f': '\\f',\n    'n': '\\n',\n    'r': '\\r',\n    't': '\\t'\n  };\n  function unescapeOne(_, ch, hex) {\n    return ch ? escapes[ch] : String.fromCharCode(parseInt(hex, 16));\n  }\n\n  // A non-falsy value that coerces to the empty string when used as a key.\n  var EMPTY_STRING = new String('');\n  var SLASH = '\\\\';\n\n  // Constructor to use based on an open token.\n  var firstTokenCtors = { '{': Object, '[': Array };\n\n  var hop = Object.hasOwnProperty;\n\n  return function (json, opt_reviver) {\n    // Split into tokens\n    var toks = json.match(jsonToken);\n    // Construct the object to return\n    var result;\n    var tok = toks[0];\n    var topLevelPrimitive = false;\n    if ('{' === tok) {\n      result = {};\n    } else if ('[' === tok) {\n      result = [];\n    } else {\n      // The RFC only allows arrays or objects at the top level, but the JSON.parse\n      // defined by the EcmaScript 5 draft does allow strings, booleans, numbers, and null\n      // at the top level.\n      result = [];\n      topLevelPrimitive = true;\n    }\n\n    // If undefined, the key in an object key/value record to use for the next\n    // value parsed.\n    var key;\n    // Loop over remaining tokens maintaining a stack of uncompleted objects and\n    // arrays.\n    var stack = [result];\n    for (var i = 1 - topLevelPrimitive, n = toks.length; i < n; ++i) {\n      tok = toks[i];\n\n      var cont;\n      switch (tok.charCodeAt(0)) {\n        default:  // sign or digit\n          cont = stack[0];\n          cont[key || cont.length] = +(tok);\n          key = void 0;\n          break;\n        case 0x22:  // '\"'\n          tok = tok.substring(1, tok.length - 1);\n          if (tok.indexOf(SLASH) !== -1) {\n            tok = tok.replace(escapeSequence, unescapeOne);\n          }\n          cont = stack[0];\n          if (!key) {\n            if (cont instanceof Array) {\n              key = cont.length;\n            } else {\n              key = tok || EMPTY_STRING;  // Use as key for next value seen.\n              break;\n            }\n          }\n          cont[key] = tok;\n          key = void 0;\n          break;\n        case 0x5b:  // '['\n          cont = stack[0];\n          stack.unshift(cont[key || cont.length] = []);\n          key = void 0;\n          break;\n        case 0x5d:  // ']'\n          stack.shift();\n          break;\n        case 0x66:  // 'f'\n          cont = stack[0];\n          cont[key || cont.length] = false;\n          key = void 0;\n          break;\n        case 0x6e:  // 'n'\n          cont = stack[0];\n          cont[key || cont.length] = null;\n          key = void 0;\n          break;\n        case 0x74:  // 't'\n          cont = stack[0];\n          cont[key || cont.length] = true;\n          key = void 0;\n          break;\n        case 0x7b:  // '{'\n          cont = stack[0];\n          stack.unshift(cont[key || cont.length] = {});\n          key = void 0;\n          break;\n        case 0x7d:  // '}'\n          stack.shift();\n          break;\n      }\n    }\n    // Fail if we've got an uncompleted object.\n    if (topLevelPrimitive) {\n      if (stack.length !== 1) { throw new Error(); }\n      result = result[0];\n    } else {\n      if (stack.length) { throw new Error(); }\n    }\n\n    if (opt_reviver) {\n      // Based on walk as implemented in http://www.json.org/json2.js\n      var walk = function (holder, key) {\n        var value = holder[key];\n        if (value && typeof value === 'object') {\n          var toDelete = null;\n          for (var k in value) {\n            if (hop.call(value, k) && value !== holder) {\n              // Recurse to properties first.  This has the effect of causing\n              // the reviver to be called on the object graph depth-first.\n\n              // Since 'this' is bound to the holder of the property, the\n              // reviver can access sibling properties of k including ones\n              // that have not yet been revived.\n\n              // The value returned by the reviver is used in place of the\n              // current value of property k.\n              // If it returns undefined then the property is deleted.\n              var v = walk(value, k);\n              if (v !== void 0) {\n                value[k] = v;\n              } else {\n                // Deleting properties inside the loop has vaguely defined\n                // semantics in ES3 and ES3.1.\n                if (!toDelete) { toDelete = []; }\n                toDelete.push(k);\n              }\n            }\n          }\n          if (toDelete) {\n            for (var i = toDelete.length; --i >= 0;) {\n              delete value[toDelete[i]];\n            }\n          }\n        }\n        return opt_reviver.call(holder, key, value);\n      };\n      result = walk({ '': result }, '');\n    }\n\n    return result;\n  };\n})();\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/json3/vendor/lodash.js",
    "content": "/**\n * @license\n * Lo-Dash 1.1.1 <http://lodash.com/>\n * Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>\n * Based on Underscore.js 1.4.4 <http://underscorejs.org/>\n * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud Inc.\n * Available under MIT license <http://lodash.com/license>\n */\n;(function(window) {\n\n  /** Used as a safe reference for `undefined` in pre ES5 environments */\n  var undefined;\n\n  /** Detect free variable `exports` */\n  var freeExports = typeof exports == 'object' && exports;\n\n  /** Detect free variable `module` */\n  var freeModule = typeof module == 'object' && module && module.exports == freeExports && module;\n\n  /** Detect free variable `global` and use it as `window` */\n  var freeGlobal = typeof global == 'object' && global;\n  if (freeGlobal.global === freeGlobal) {\n    window = freeGlobal;\n  }\n\n  /** Used to generate unique IDs */\n  var idCounter = 0;\n\n  /** Used internally to indicate various things */\n  var indicatorObject = {};\n\n  /** Used to match empty string literals in compiled template source */\n  var reEmptyStringLeading = /\\b__p \\+= '';/g,\n      reEmptyStringMiddle = /\\b(__p \\+=) '' \\+/g,\n      reEmptyStringTrailing = /(__e\\(.*?\\)|\\b__t\\)) \\+\\n'';/g;\n\n  /** Used to match HTML entities */\n  var reEscapedHtml = /&(?:amp|lt|gt|quot|#39);/g;\n\n  /**\n   * Used to match ES6 template delimiters\n   * http://people.mozilla.org/~jorendorff/es6-draft.html#sec-7.8.6\n   */\n  var reEsTemplate = /\\$\\{([^\\\\}]*(?:\\\\.[^\\\\}]*)*)\\}/g;\n\n  /** Used to match regexp flags from their coerced string values */\n  var reFlags = /\\w*$/;\n\n  /** Used to match \"interpolate\" template delimiters */\n  var reInterpolate = /<%=([\\s\\S]+?)%>/g;\n\n  /** Used to match leading zeros to be removed */\n  var reLeadingZeros = /^0+(?=.$)/;\n\n  /** Used to ensure capturing order of template delimiters */\n  var reNoMatch = /($^)/;\n\n  /** Used to match HTML characters */\n  var reUnescapedHtml = /[&<>\"']/g;\n\n  /** Used to match unescaped characters in compiled string literals */\n  var reUnescapedString = /['\\n\\r\\t\\u2028\\u2029\\\\]/g;\n\n  /** Used to assign default `context` object properties */\n  var contextProps = [\n    'Array', 'Boolean', 'Date', 'Function', 'Math', 'Number', 'Object', 'RegExp',\n    'String', '_', 'attachEvent', 'clearTimeout', 'isFinite', 'isNaN', 'parseInt',\n    'setImmediate', 'setTimeout'\n  ];\n\n  /** Used to fix the JScript [[DontEnum]] bug */\n  var shadowedProps = [\n    'constructor', 'hasOwnProperty', 'isPrototypeOf', 'propertyIsEnumerable',\n    'toLocaleString', 'toString', 'valueOf'\n  ];\n\n  /** Used to make template sourceURLs easier to identify */\n  var templateCounter = 0;\n\n  /** `Object#toString` result shortcuts */\n  var argsClass = '[object Arguments]',\n      arrayClass = '[object Array]',\n      boolClass = '[object Boolean]',\n      dateClass = '[object Date]',\n      funcClass = '[object Function]',\n      numberClass = '[object Number]',\n      objectClass = '[object Object]',\n      regexpClass = '[object RegExp]',\n      stringClass = '[object String]';\n\n  /** Used to identify object classifications that `_.clone` supports */\n  var cloneableClasses = {};\n  cloneableClasses[funcClass] = false;\n  cloneableClasses[argsClass] = cloneableClasses[arrayClass] =\n  cloneableClasses[boolClass] = cloneableClasses[dateClass] =\n  cloneableClasses[numberClass] = cloneableClasses[objectClass] =\n  cloneableClasses[regexpClass] = cloneableClasses[stringClass] = true;\n\n  /** Used to determine if values are of the language type Object */\n  var objectTypes = {\n    'boolean': false,\n    'function': true,\n    'object': true,\n    'number': false,\n    'string': false,\n    'undefined': false\n  };\n\n  /** Used to escape characters for inclusion in compiled string literals */\n  var stringEscapes = {\n    '\\\\': '\\\\',\n    \"'\": \"'\",\n    '\\n': 'n',\n    '\\r': 'r',\n    '\\t': 't',\n    '\\u2028': 'u2028',\n    '\\u2029': 'u2029'\n  };\n\n  /*--------------------------------------------------------------------------*/\n\n  /**\n   * Create a new `lodash` function using the given `context` object.\n   *\n   * @static\n   * @memberOf _\n   * @category Utilities\n   * @param {Object} [context=window] The context object.\n   * @returns {Function} Returns the `lodash` function.\n   */\n  function runInContext(context) {\n    // Avoid issues with some ES3 environments that attempt to use values, named\n    // after built-in constructors like `Object`, for the creation of literals.\n    // ES5 clears this up by stating that literals must use built-in constructors.\n    // See http://es5.github.com/#x11.1.5.\n    context = context ? _.defaults(window.Object(), context, _.pick(window, contextProps)) : window;\n\n    /** Native constructor references */\n    var Array = context.Array,\n        Boolean = context.Boolean,\n        Date = context.Date,\n        Function = context.Function,\n        Math = context.Math,\n        Number = context.Number,\n        Object = context.Object,\n        RegExp = context.RegExp,\n        String = context.String,\n        TypeError = context.TypeError;\n\n    /** Used for `Array` and `Object` method references */\n    var arrayRef = Array(),\n        objectRef = Object();\n\n    /** Used to restore the original `_` reference in `noConflict` */\n    var oldDash = context._;\n\n    /** Used to detect if a method is native */\n    var reNative = RegExp('^' +\n      String(objectRef.valueOf)\n        .replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')\n        .replace(/valueOf|for [^\\]]+/g, '.+?') + '$'\n    );\n\n    /** Native method shortcuts */\n    var ceil = Math.ceil,\n        clearTimeout = context.clearTimeout,\n        concat = arrayRef.concat,\n        floor = Math.floor,\n        getPrototypeOf = reNative.test(getPrototypeOf = Object.getPrototypeOf) && getPrototypeOf,\n        hasOwnProperty = objectRef.hasOwnProperty,\n        push = arrayRef.push,\n        setImmediate = context.setImmediate,\n        setTimeout = context.setTimeout,\n        toString = objectRef.toString;\n\n    /* Native method shortcuts for methods with the same name as other `lodash` methods */\n    var nativeBind = reNative.test(nativeBind = slice.bind) && nativeBind,\n        nativeIsArray = reNative.test(nativeIsArray = Array.isArray) && nativeIsArray,\n        nativeIsFinite = context.isFinite,\n        nativeIsNaN = context.isNaN,\n        nativeKeys = reNative.test(nativeKeys = Object.keys) && nativeKeys,\n        nativeMax = Math.max,\n        nativeMin = Math.min,\n        nativeParseInt = context.parseInt,\n        nativeRandom = Math.random;\n\n    /** Detect various environments */\n    var isIeOpera = reNative.test(context.attachEvent),\n        isV8 = nativeBind && !/\\n|true/.test(nativeBind + isIeOpera);\n\n    /** Used to lookup a built-in constructor by [[Class]] */\n    var ctorByClass = {};\n    ctorByClass[arrayClass] = Array;\n    ctorByClass[boolClass] = Boolean;\n    ctorByClass[dateClass] = Date;\n    ctorByClass[objectClass] = Object;\n    ctorByClass[numberClass] = Number;\n    ctorByClass[regexpClass] = RegExp;\n    ctorByClass[stringClass] = String;\n\n    /*--------------------------------------------------------------------------*/\n\n    /**\n     * Creates a `lodash` object, that wraps the given `value`, to enable method\n     * chaining.\n     *\n     * In addition to Lo-Dash methods, wrappers also have the following `Array` methods:\n     * `concat`, `join`, `pop`, `push`, `reverse`, `shift`, `slice`, `sort`, `splice`,\n     * and `unshift`\n     *\n     * Chaining is supported in custom builds as long as the `value` method is\n     * implicitly or explicitly included in the build.\n     *\n     * The chainable wrapper functions are:\n     * `after`, `assign`, `bind`, `bindAll`, `bindKey`, `chain`, `compact`,\n     * `compose`, `concat`, `countBy`, `createCallback`, `debounce`, `defaults`,\n     * `defer`, `delay`, `difference`, `filter`, `flatten`, `forEach`, `forIn`,\n     * `forOwn`, `functions`, `groupBy`, `initial`, `intersection`, `invert`,\n     * `invoke`, `keys`, `map`, `max`, `memoize`, `merge`, `min`, `object`, `omit`,\n     * `once`, `pairs`, `partial`, `partialRight`, `pick`, `pluck`, `push`, `range`,\n     * `reject`, `rest`, `reverse`, `shuffle`, `slice`, `sort`, `sortBy`, `splice`,\n     * `tap`, `throttle`, `times`, `toArray`, `union`, `uniq`, `unshift`, `values`,\n     * `where`, `without`, `wrap`, and `zip`\n     *\n     * The non-chainable wrapper functions are:\n     * `clone`, `cloneDeep`, `contains`, `escape`, `every`, `find`, `has`,\n     * `identity`, `indexOf`, `isArguments`, `isArray`, `isBoolean`, `isDate`,\n     * `isElement`, `isEmpty`, `isEqual`, `isFinite`, `isFunction`, `isNaN`,\n     * `isNull`, `isNumber`, `isObject`, `isPlainObject`, `isRegExp`, `isString`,\n     * `isUndefined`, `join`, `lastIndexOf`, `mixin`, `noConflict`, `parseInt`,\n     * `pop`, `random`, `reduce`, `reduceRight`, `result`, `shift`, `size`, `some`,\n     * `sortedIndex`, `runInContext`, `template`, `unescape`, `uniqueId`, and `value`\n     *\n     * The wrapper functions `first` and `last` return wrapped values when `n` is\n     * passed, otherwise they return unwrapped values.\n     *\n     * @name _\n     * @constructor\n     * @category Chaining\n     * @param {Mixed} value The value to wrap in a `lodash` instance.\n     * @returns {Object} Returns a `lodash` instance.\n     */\n    function lodash(value) {\n      // don't wrap if already wrapped, even if wrapped by a different `lodash` constructor\n      return (value && typeof value == 'object' && !isArray(value) && hasOwnProperty.call(value, '__wrapped__'))\n       ? value\n       : new lodashWrapper(value);\n    }\n\n    /**\n     * An object used to flag environments features.\n     *\n     * @static\n     * @memberOf _\n     * @type Object\n     */\n    var support = lodash.support = {};\n\n    (function() {\n      var ctor = function() { this.x = 1; },\n          object = { '0': 1, 'length': 1 },\n          props = [];\n\n      ctor.prototype = { 'valueOf': 1, 'y': 1 };\n      for (var prop in new ctor) { props.push(prop); }\n      for (prop in arguments) { }\n\n      /**\n       * Detect if `arguments` objects are `Object` objects (all but Opera < 10.5).\n       *\n       * @memberOf _.support\n       * @type Boolean\n       */\n      support.argsObject = arguments.constructor == Object;\n\n      /**\n       * Detect if an `arguments` object's [[Class]] is resolvable (all but Firefox < 4, IE < 9).\n       *\n       * @memberOf _.support\n       * @type Boolean\n       */\n      support.argsClass = isArguments(arguments);\n\n      /**\n       * Detect if `prototype` properties are enumerable by default.\n       *\n       * Firefox < 3.6, Opera > 9.50 - Opera < 11.60, and Safari < 5.1\n       * (if the prototype or a property on the prototype has been set)\n       * incorrectly sets a function's `prototype` property [[Enumerable]]\n       * value to `true`.\n       *\n       * @memberOf _.support\n       * @type Boolean\n       */\n      support.enumPrototypes = ctor.propertyIsEnumerable('prototype');\n\n      /**\n       * Detect if `Function#bind` exists and is inferred to be fast (all but V8).\n       *\n       * @memberOf _.support\n       * @type Boolean\n       */\n      support.fastBind = nativeBind && !isV8;\n\n      /**\n       * Detect if own properties are iterated after inherited properties (all but IE < 9).\n       *\n       * @memberOf _.support\n       * @type Boolean\n       */\n      support.ownLast = props[0] != 'x';\n\n      /**\n       * Detect if `arguments` object indexes are non-enumerable\n       * (Firefox < 4, IE < 9, PhantomJS, Safari < 5.1).\n       *\n       * @memberOf _.support\n       * @type Boolean\n       */\n      support.nonEnumArgs = prop != 0;\n\n      /**\n       * Detect if properties shadowing those on `Object.prototype` are non-enumerable.\n       *\n       * In IE < 9 an objects own properties, shadowing non-enumerable ones, are\n       * made non-enumerable as well (a.k.a the JScript [[DontEnum]] bug).\n       *\n       * @memberOf _.support\n       * @type Boolean\n       */\n      support.nonEnumShadows = !/valueOf/.test(props);\n\n      /**\n       * Detect if `Array#shift` and `Array#splice` augment array-like objects correctly.\n       *\n       * Firefox < 10, IE compatibility mode, and IE < 9 have buggy Array `shift()`\n       * and `splice()` functions that fail to remove the last element, `value[0]`,\n       * of array-like objects even though the `length` property is set to `0`.\n       * The `shift()` method is buggy in IE 8 compatibility mode, while `splice()`\n       * is buggy regardless of mode in IE < 9 and buggy in compatibility mode in IE 9.\n       *\n       * @memberOf _.support\n       * @type Boolean\n       */\n      support.spliceObjects = (arrayRef.splice.call(object, 0, 1), !object[0]);\n\n      /**\n       * Detect lack of support for accessing string characters by index.\n       *\n       * IE < 8 can't access characters by index and IE 8 can only access\n       * characters by index on string literals.\n       *\n       * @memberOf _.support\n       * @type Boolean\n       */\n      support.unindexedChars = ('x'[0] + Object('x')[0]) != 'xx';\n\n      /**\n       * Detect if a DOM node's [[Class]] is resolvable (all but IE < 9)\n       * and that the JS engine errors when attempting to coerce an object to\n       * a string without a `toString` function.\n       *\n       * @memberOf _.support\n       * @type Boolean\n       */\n      try {\n        support.nodeClass = !(toString.call(document) == objectClass && !({ 'toString': 0 } + ''));\n      } catch(e) {\n        support.nodeClass = true;\n      }\n    }(1));\n\n    /**\n     * By default, the template delimiters used by Lo-Dash are similar to those in\n     * embedded Ruby (ERB). Change the following template settings to use alternative\n     * delimiters.\n     *\n     * @static\n     * @memberOf _\n     * @type Object\n     */\n    lodash.templateSettings = {\n\n      /**\n       * Used to detect `data` property values to be HTML-escaped.\n       *\n       * @memberOf _.templateSettings\n       * @type RegExp\n       */\n      'escape': /<%-([\\s\\S]+?)%>/g,\n\n      /**\n       * Used to detect code to be evaluated.\n       *\n       * @memberOf _.templateSettings\n       * @type RegExp\n       */\n      'evaluate': /<%([\\s\\S]+?)%>/g,\n\n      /**\n       * Used to detect `data` property values to inject.\n       *\n       * @memberOf _.templateSettings\n       * @type RegExp\n       */\n      'interpolate': reInterpolate,\n\n      /**\n       * Used to reference the data object in the template text.\n       *\n       * @memberOf _.templateSettings\n       * @type String\n       */\n      'variable': '',\n\n      /**\n       * Used to import variables into the compiled template.\n       *\n       * @memberOf _.templateSettings\n       * @type Object\n       */\n      'imports': {\n\n        /**\n         * A reference to the `lodash` function.\n         *\n         * @memberOf _.templateSettings.imports\n         * @type Function\n         */\n        '_': lodash\n      }\n    };\n\n    /*--------------------------------------------------------------------------*/\n\n    /**\n     * The template used to create iterator functions.\n     *\n     * @private\n     * @param {Obect} data The data object used to populate the text.\n     * @returns {String} Returns the interpolated text.\n     */\n    var iteratorTemplate = template(\n      // the `iterable` may be reassigned by the `top` snippet\n      'var index, iterable = <%= firstArg %>, ' +\n      // assign the `result` variable an initial value\n      'result = <%= init %>;\\n' +\n      // exit early if the first argument is falsey\n      'if (!iterable) return result;\\n' +\n      // add code before the iteration branches\n      '<%= top %>;\\n' +\n\n      // array-like iteration:\n      '<% if (arrays) { %>' +\n      'var length = iterable.length; index = -1;\\n' +\n      'if (<%= arrays %>) {' +\n\n      // add support for accessing string characters by index if needed\n      '  <% if (support.unindexedChars) { %>\\n' +\n      '  if (isString(iterable)) {\\n' +\n      \"    iterable = iterable.split('')\\n\" +\n      '  }' +\n      '  <% } %>\\n' +\n\n      // iterate over the array-like value\n      '  while (++index < length) {\\n' +\n      '    <%= loop %>\\n' +\n      '  }\\n' +\n      '}\\n' +\n      'else {' +\n\n      // object iteration:\n      // add support for iterating over `arguments` objects if needed\n      '  <%  } else if (support.nonEnumArgs) { %>\\n' +\n      '  var length = iterable.length; index = -1;\\n' +\n      '  if (length && isArguments(iterable)) {\\n' +\n      '    while (++index < length) {\\n' +\n      \"      index += '';\\n\" +\n      '      <%= loop %>\\n' +\n      '    }\\n' +\n      '  } else {' +\n      '  <% } %>' +\n\n      // avoid iterating over `prototype` properties in older Firefox, Opera, and Safari\n      '  <% if (support.enumPrototypes) { %>\\n' +\n      \"  var skipProto = typeof iterable == 'function';\\n\" +\n      '  <% } %>' +\n\n      // iterate own properties using `Object.keys` if it's fast\n      '  <% if (useHas && useKeys) { %>\\n' +\n      '  var ownIndex = -1,\\n' +\n      '      ownProps = objectTypes[typeof iterable] ? keys(iterable) : [],\\n' +\n      '      length = ownProps.length;\\n\\n' +\n      '  while (++ownIndex < length) {\\n' +\n      '    index = ownProps[ownIndex];\\n' +\n      \"    <% if (support.enumPrototypes) { %>if (!(skipProto && index == 'prototype')) {\\n  <% } %>\" +\n      '    <%= loop %>\\n' +\n      '    <% if (support.enumPrototypes) { %>}\\n<% } %>' +\n      '  }' +\n\n      // else using a for-in loop\n      '  <% } else { %>\\n' +\n      '  for (index in iterable) {<%' +\n      '    if (support.enumPrototypes || useHas) { %>\\n    if (<%' +\n      \"      if (support.enumPrototypes) { %>!(skipProto && index == 'prototype')<% }\" +\n      '      if (support.enumPrototypes && useHas) { %> && <% }' +\n      '      if (useHas) { %>hasOwnProperty.call(iterable, index)<% }' +\n      '    %>) {' +\n      '    <% } %>\\n' +\n      '    <%= loop %>;' +\n      '    <% if (support.enumPrototypes || useHas) { %>\\n    }<% } %>\\n' +\n      '  }' +\n\n      // Because IE < 9 can't set the `[[Enumerable]]` attribute of an\n      // existing property and the `constructor` property of a prototype\n      // defaults to non-enumerable, Lo-Dash skips the `constructor`\n      // property when it infers it's iterating over a `prototype` object.\n      '    <% if (support.nonEnumShadows) { %>\\n\\n' +\n      '  var ctor = iterable.constructor;\\n' +\n      '      <% for (var k = 0; k < 7; k++) { %>\\n' +\n      \"  index = '<%= shadowedProps[k] %>';\\n\" +\n      '  if (<%' +\n      \"      if (shadowedProps[k] == 'constructor') {\" +\n      '        %>!(ctor && ctor.prototype === iterable) && <%' +\n      '      } %>hasOwnProperty.call(iterable, index)) {\\n' +\n      '    <%= loop %>\\n' +\n      '  }' +\n      '      <% } %>' +\n      '    <% } %>' +\n      '  <% } %>' +\n      '  <% if (arrays || support.nonEnumArgs) { %>\\n}<% } %>\\n' +\n\n      // add code to the bottom of the iteration function\n      '<%= bottom %>;\\n' +\n      // finally, return the `result`\n      'return result'\n    );\n\n    /** Reusable iterator options for `assign` and `defaults` */\n    var defaultsIteratorOptions = {\n      'args': 'object, source, guard',\n      'top':\n        'var args = arguments,\\n' +\n        '    argsIndex = 0,\\n' +\n        \"    argsLength = typeof guard == 'number' ? 2 : args.length;\\n\" +\n        'while (++argsIndex < argsLength) {\\n' +\n        '  iterable = args[argsIndex];\\n' +\n        '  if (iterable && objectTypes[typeof iterable]) {',\n      'loop': \"if (typeof result[index] == 'undefined') result[index] = iterable[index]\",\n      'bottom': '  }\\n}'\n    };\n\n    /** Reusable iterator options shared by `each`, `forIn`, and `forOwn` */\n    var eachIteratorOptions = {\n      'args': 'collection, callback, thisArg',\n      'top': \"callback = callback && typeof thisArg == 'undefined' ? callback : lodash.createCallback(callback, thisArg)\",\n      'arrays': \"typeof length == 'number'\",\n      'loop': 'if (callback(iterable[index], index, collection) === false) return result'\n    };\n\n    /** Reusable iterator options for `forIn` and `forOwn` */\n    var forOwnIteratorOptions = {\n      'top': 'if (!objectTypes[typeof iterable]) return result;\\n' + eachIteratorOptions.top,\n      'arrays': false\n    };\n\n    /*--------------------------------------------------------------------------*/\n\n    /**\n     * Creates a function optimized to search large arrays for a given `value`,\n     * starting at `fromIndex`, using strict equality for comparisons, i.e. `===`.\n     *\n     * @private\n     * @param {Array} array The array to search.\n     * @param {Mixed} value The value to search for.\n     * @param {Number} fromIndex The index to search from.\n     * @param {Number} largeSize The length at which an array is considered large.\n     * @returns {Boolean} Returns `true`, if `value` is found, else `false`.\n     */\n    function cachedContains(array, fromIndex, largeSize) {\n      var length = array.length,\n          isLarge = (length - fromIndex) >= largeSize;\n\n      if (isLarge) {\n        var cache = {},\n            index = fromIndex - 1;\n\n        while (++index < length) {\n          // manually coerce `value` to a string because `hasOwnProperty`, in some\n          // older versions of Firefox, coerces objects incorrectly\n          var key = String(array[index]);\n          (hasOwnProperty.call(cache, key) ? cache[key] : (cache[key] = [])).push(array[index]);\n        }\n      }\n      return function(value) {\n        if (isLarge) {\n          var key = String(value);\n          return hasOwnProperty.call(cache, key) && indexOf(cache[key], value) > -1;\n        }\n        return indexOf(array, value, fromIndex) > -1;\n      }\n    }\n\n    /**\n     * Used by `_.max` and `_.min` as the default `callback` when a given\n     * `collection` is a string value.\n     *\n     * @private\n     * @param {String} value The character to inspect.\n     * @returns {Number} Returns the code unit of given character.\n     */\n    function charAtCallback(value) {\n      return value.charCodeAt(0);\n    }\n\n    /**\n     * Used by `sortBy` to compare transformed `collection` values, stable sorting\n     * them in ascending order.\n     *\n     * @private\n     * @param {Object} a The object to compare to `b`.\n     * @param {Object} b The object to compare to `a`.\n     * @returns {Number} Returns the sort order indicator of `1` or `-1`.\n     */\n    function compareAscending(a, b) {\n      var ai = a.index,\n          bi = b.index;\n\n      a = a.criteria;\n      b = b.criteria;\n\n      // ensure a stable sort in V8 and other engines\n      // http://code.google.com/p/v8/issues/detail?id=90\n      if (a !== b) {\n        if (a > b || typeof a == 'undefined') {\n          return 1;\n        }\n        if (a < b || typeof b == 'undefined') {\n          return -1;\n        }\n      }\n      return ai < bi ? -1 : 1;\n    }\n\n    /**\n     * Creates a function that, when called, invokes `func` with the `this` binding\n     * of `thisArg` and prepends any `partialArgs` to the arguments passed to the\n     * bound function.\n     *\n     * @private\n     * @param {Function|String} func The function to bind or the method name.\n     * @param {Mixed} [thisArg] The `this` binding of `func`.\n     * @param {Array} partialArgs An array of arguments to be partially applied.\n     * @param {Object} [idicator] Used to indicate binding by key or partially\n     *  applying arguments from the right.\n     * @returns {Function} Returns the new bound function.\n     */\n    function createBound(func, thisArg, partialArgs, indicator) {\n      var isFunc = isFunction(func),\n          isPartial = !partialArgs,\n          key = thisArg;\n\n      // juggle arguments\n      if (isPartial) {\n        var rightIndicator = indicator;\n        partialArgs = thisArg;\n      }\n      else if (!isFunc) {\n        if (!indicator) {\n          throw new TypeError;\n        }\n        thisArg = func;\n      }\n\n      function bound() {\n        // `Function#bind` spec\n        // http://es5.github.com/#x15.3.4.5\n        var args = arguments,\n            thisBinding = isPartial ? this : thisArg;\n\n        if (!isFunc) {\n          func = thisArg[key];\n        }\n        if (partialArgs.length) {\n          args = args.length\n            ? (args = slice(args), rightIndicator ? args.concat(partialArgs) : partialArgs.concat(args))\n            : partialArgs;\n        }\n        if (this instanceof bound) {\n          // ensure `new bound` is an instance of `func`\n          noop.prototype = func.prototype;\n          thisBinding = new noop;\n          noop.prototype = null;\n\n          // mimic the constructor's `return` behavior\n          // http://es5.github.com/#x13.2.2\n          var result = func.apply(thisBinding, args);\n          return isObject(result) ? result : thisBinding;\n        }\n        return func.apply(thisBinding, args);\n      }\n      return bound;\n    }\n\n    /**\n     * Creates compiled iteration functions.\n     *\n     * @private\n     * @param {Object} [options1, options2, ...] The compile options object(s).\n     *  arrays - A string of code to determine if the iterable is an array or array-like.\n     *  useHas - A boolean to specify using `hasOwnProperty` checks in the object loop.\n     *  args - A string of comma separated arguments the iteration function will accept.\n     *  top - A string of code to execute before the iteration branches.\n     *  loop - A string of code to execute in the object loop.\n     *  bottom - A string of code to execute after the iteration branches.\n     * @returns {Function} Returns the compiled function.\n     */\n    function createIterator() {\n      var data = {\n        // data properties\n        'shadowedProps': shadowedProps,\n        'support': support,\n\n        // iterator options\n        'arrays': 'isArray(iterable)',\n        'bottom': '',\n        'init': 'iterable',\n        'loop': '',\n        'top': '',\n        'useHas': true,\n        'useKeys': !!keys\n      };\n\n      // merge options into a template data object\n      for (var object, index = 0; object = arguments[index]; index++) {\n        for (var key in object) {\n          data[key] = object[key];\n        }\n      }\n      var args = data.args;\n      data.firstArg = /^[^,]+/.exec(args)[0];\n\n      // create the function factory\n      var factory = Function(\n          'hasOwnProperty, isArguments, isArray, isString, keys, ' +\n          'lodash, objectTypes',\n        'return function(' + args + ') {\\n' + iteratorTemplate(data) + '\\n}'\n      );\n      // return the compiled function\n      return factory(\n        hasOwnProperty, isArguments, isArray, isString, keys,\n        lodash, objectTypes\n      );\n    }\n\n    /**\n     * Used by `template` to escape characters for inclusion in compiled\n     * string literals.\n     *\n     * @private\n     * @param {String} match The matched character to escape.\n     * @returns {String} Returns the escaped character.\n     */\n    function escapeStringChar(match) {\n      return '\\\\' + stringEscapes[match];\n    }\n\n    /**\n     * Used by `escape` to convert characters to HTML entities.\n     *\n     * @private\n     * @param {String} match The matched character to escape.\n     * @returns {String} Returns the escaped character.\n     */\n    function escapeHtmlChar(match) {\n      return htmlEscapes[match];\n    }\n\n    /**\n     * Checks if `value` is a DOM node in IE < 9.\n     *\n     * @private\n     * @param {Mixed} value The value to check.\n     * @returns {Boolean} Returns `true` if the `value` is a DOM node, else `false`.\n     */\n    function isNode(value) {\n      // IE < 9 presents DOM nodes as `Object` objects except they have `toString`\n      // methods that are `typeof` \"string\" and still can coerce nodes to strings\n      return typeof value.toString != 'function' && typeof (value + '') == 'string';\n    }\n\n    /**\n     * A fast path for creating `lodash` wrapper objects.\n     *\n     * @private\n     * @param {Mixed} value The value to wrap in a `lodash` instance.\n     * @returns {Object} Returns a `lodash` instance.\n     */\n    function lodashWrapper(value) {\n      this.__wrapped__ = value;\n    }\n    // ensure `new lodashWrapper` is an instance of `lodash`\n    lodashWrapper.prototype = lodash.prototype;\n\n    /**\n     * A no-operation function.\n     *\n     * @private\n     */\n    function noop() {\n      // no operation performed\n    }\n\n    /**\n     * A fallback implementation of `isPlainObject` that checks if a given `value`\n     * is an object created by the `Object` constructor, assuming objects created\n     * by the `Object` constructor have no inherited enumerable properties and that\n     * there are no `Object.prototype` extensions.\n     *\n     * @private\n     * @param {Mixed} value The value to check.\n     * @returns {Boolean} Returns `true`, if `value` is a plain object, else `false`.\n     */\n    function shimIsPlainObject(value) {\n      // avoid non-objects and false positives for `arguments` objects\n      var result = false;\n      if (!(value && toString.call(value) == objectClass) || (!support.argsClass && isArguments(value))) {\n        return result;\n      }\n      // check that the constructor is `Object` (i.e. `Object instanceof Object`)\n      var ctor = value.constructor;\n\n      if (isFunction(ctor) ? ctor instanceof ctor : (support.nodeClass || !isNode(value))) {\n        // IE < 9 iterates inherited properties before own properties. If the first\n        // iterated property is an object's own property then there are no inherited\n        // enumerable properties.\n        if (support.ownLast) {\n          forIn(value, function(value, key, object) {\n            result = hasOwnProperty.call(object, key);\n            return false;\n          });\n          return result === true;\n        }\n        // In most environments an object's own properties are iterated before\n        // its inherited properties. If the last iterated property is an object's\n        // own property then there are no inherited enumerable properties.\n        forIn(value, function(value, key) {\n          result = key;\n        });\n        return result === false || hasOwnProperty.call(value, result);\n      }\n      return result;\n    }\n\n    /**\n     * Slices the `collection` from the `start` index up to, but not including,\n     * the `end` index.\n     *\n     * Note: This function is used, instead of `Array#slice`, to support node lists\n     * in IE < 9 and to ensure dense arrays are returned.\n     *\n     * @private\n     * @param {Array|Object|String} collection The collection to slice.\n     * @param {Number} start The start index.\n     * @param {Number} end The end index.\n     * @returns {Array} Returns the new array.\n     */\n    function slice(array, start, end) {\n      start || (start = 0);\n      if (typeof end == 'undefined') {\n        end = array ? array.length : 0;\n      }\n      var index = -1,\n          length = end - start || 0,\n          result = Array(length < 0 ? 0 : length);\n\n      while (++index < length) {\n        result[index] = array[start + index];\n      }\n      return result;\n    }\n\n    /**\n     * Used by `unescape` to convert HTML entities to characters.\n     *\n     * @private\n     * @param {String} match The matched character to unescape.\n     * @returns {String} Returns the unescaped character.\n     */\n    function unescapeHtmlChar(match) {\n      return htmlUnescapes[match];\n    }\n\n    /*--------------------------------------------------------------------------*/\n\n    /**\n     * Checks if `value` is an `arguments` object.\n     *\n     * @static\n     * @memberOf _\n     * @category Objects\n     * @param {Mixed} value The value to check.\n     * @returns {Boolean} Returns `true`, if the `value` is an `arguments` object, else `false`.\n     * @example\n     *\n     * (function() { return _.isArguments(arguments); })(1, 2, 3);\n     * // => true\n     *\n     * _.isArguments([1, 2, 3]);\n     * // => false\n     */\n    function isArguments(value) {\n      return toString.call(value) == argsClass;\n    }\n    // fallback for browsers that can't detect `arguments` objects by [[Class]]\n    if (!support.argsClass) {\n      isArguments = function(value) {\n        return value ? hasOwnProperty.call(value, 'callee') : false;\n      };\n    }\n\n    /**\n     * Checks if `value` is an array.\n     *\n     * @static\n     * @memberOf _\n     * @category Objects\n     * @param {Mixed} value The value to check.\n     * @returns {Boolean} Returns `true`, if the `value` is an array, else `false`.\n     * @example\n     *\n     * (function() { return _.isArray(arguments); })();\n     * // => false\n     *\n     * _.isArray([1, 2, 3]);\n     * // => true\n     */\n    var isArray = nativeIsArray || function(value) {\n      // `instanceof` may cause a memory leak in IE 7 if `value` is a host object\n      // http://ajaxian.com/archives/working-aroung-the-instanceof-memory-leak\n      return (support.argsObject && value instanceof Array) || toString.call(value) == arrayClass;\n    };\n\n    /**\n     * A fallback implementation of `Object.keys` that produces an array of the\n     * given object's own enumerable property names.\n     *\n     * @private\n     * @type Function\n     * @param {Object} object The object to inspect.\n     * @returns {Array} Returns a new array of property names.\n     */\n    var shimKeys = createIterator({\n      'args': 'object',\n      'init': '[]',\n      'top': 'if (!(objectTypes[typeof object])) return result',\n      'loop': 'result.push(index)',\n      'arrays': false\n    });\n\n    /**\n     * Creates an array composed of the own enumerable property names of `object`.\n     *\n     * @static\n     * @memberOf _\n     * @category Objects\n     * @param {Object} object The object to inspect.\n     * @returns {Array} Returns a new array of property names.\n     * @example\n     *\n     * _.keys({ 'one': 1, 'two': 2, 'three': 3 });\n     * // => ['one', 'two', 'three'] (order is not guaranteed)\n     */\n    var keys = !nativeKeys ? shimKeys : function(object) {\n      if (!isObject(object)) {\n        return [];\n      }\n      if ((support.enumPrototypes && typeof object == 'function') ||\n          (support.nonEnumArgs && object.length && isArguments(object))) {\n        return shimKeys(object);\n      }\n      return nativeKeys(object);\n    };\n\n    /**\n     * A function compiled to iterate `arguments` objects, arrays, objects, and\n     * strings consistenly across environments, executing the `callback` for each\n     * element in the `collection`. The `callback` is bound to `thisArg` and invoked\n     * with three arguments; (value, index|key, collection). Callbacks may exit\n     * iteration early by explicitly returning `false`.\n     *\n     * @private\n     * @type Function\n     * @param {Array|Object|String} collection The collection to iterate over.\n     * @param {Function} [callback=identity] The function called per iteration.\n     * @param {Mixed} [thisArg] The `this` binding of `callback`.\n     * @returns {Array|Object|String} Returns `collection`.\n     */\n    var each = createIterator(eachIteratorOptions);\n\n    /**\n     * Used to convert characters to HTML entities:\n     *\n     * Though the `>` character is escaped for symmetry, characters like `>` and `/`\n     * don't require escaping in HTML and have no special meaning unless they're part\n     * of a tag or an unquoted attribute value.\n     * http://mathiasbynens.be/notes/ambiguous-ampersands (under \"semi-related fun fact\")\n     */\n    var htmlEscapes = {\n      '&': '&amp;',\n      '<': '&lt;',\n      '>': '&gt;',\n      '\"': '&quot;',\n      \"'\": '&#39;'\n    };\n\n    /** Used to convert HTML entities to characters */\n    var htmlUnescapes = invert(htmlEscapes);\n\n    /*--------------------------------------------------------------------------*/\n\n    /**\n     * Assigns own enumerable properties of source object(s) to the destination\n     * object. Subsequent sources will overwrite property assignments of previous\n     * sources. If a `callback` function is passed, it will be executed to produce\n     * the assigned values. The `callback` is bound to `thisArg` and invoked with\n     * two arguments; (objectValue, sourceValue).\n     *\n     * @static\n     * @memberOf _\n     * @type Function\n     * @alias extend\n     * @category Objects\n     * @param {Object} object The destination object.\n     * @param {Object} [source1, source2, ...] The source objects.\n     * @param {Function} [callback] The function to customize assigning values.\n     * @param {Mixed} [thisArg] The `this` binding of `callback`.\n     * @returns {Object} Returns the destination object.\n     * @example\n     *\n     * _.assign({ 'name': 'moe' }, { 'age': 40 });\n     * // => { 'name': 'moe', 'age': 40 }\n     *\n     * var defaults = _.partialRight(_.assign, function(a, b) {\n     *   return typeof a == 'undefined' ? b : a;\n     * });\n     *\n     * var food = { 'name': 'apple' };\n     * defaults(food, { 'name': 'banana', 'type': 'fruit' });\n     * // => { 'name': 'apple', 'type': 'fruit' }\n     */\n    var assign = createIterator(defaultsIteratorOptions, {\n      'top':\n        defaultsIteratorOptions.top.replace(';',\n          ';\\n' +\n          \"if (argsLength > 3 && typeof args[argsLength - 2] == 'function') {\\n\" +\n          '  var callback = lodash.createCallback(args[--argsLength - 1], args[argsLength--], 2);\\n' +\n          \"} else if (argsLength > 2 && typeof args[argsLength - 1] == 'function') {\\n\" +\n          '  callback = args[--argsLength];\\n' +\n          '}'\n        ),\n      'loop': 'result[index] = callback ? callback(result[index], iterable[index]) : iterable[index]'\n    });\n\n    /**\n     * Creates a clone of `value`. If `deep` is `true`, nested objects will also\n     * be cloned, otherwise they will be assigned by reference. If a `callback`\n     * function is passed, it will be executed to produce the cloned values. If\n     * `callback` returns `undefined`, cloning will be handled by the method instead.\n     * The `callback` is bound to `thisArg` and invoked with one argument; (value).\n     *\n     * @static\n     * @memberOf _\n     * @category Objects\n     * @param {Mixed} value The value to clone.\n     * @param {Boolean} [deep=false] A flag to indicate a deep clone.\n     * @param {Function} [callback] The function to customize cloning values.\n     * @param {Mixed} [thisArg] The `this` binding of `callback`.\n     * @param- {Array} [stackA=[]] Tracks traversed source objects.\n     * @param- {Array} [stackB=[]] Associates clones with source counterparts.\n     * @returns {Mixed} Returns the cloned `value`.\n     * @example\n     *\n     * var stooges = [\n     *   { 'name': 'moe', 'age': 40 },\n     *   { 'name': 'larry', 'age': 50 }\n     * ];\n     *\n     * var shallow = _.clone(stooges);\n     * shallow[0] === stooges[0];\n     * // => true\n     *\n     * var deep = _.clone(stooges, true);\n     * deep[0] === stooges[0];\n     * // => false\n     *\n     * _.mixin({\n     *   'clone': _.partialRight(_.clone, function(value) {\n     *     return _.isElement(value) ? value.cloneNode(false) : undefined;\n     *   })\n     * });\n     *\n     * var clone = _.clone(document.body);\n     * clone.childNodes.length;\n     * // => 0\n     */\n    function clone(value, deep, callback, thisArg, stackA, stackB) {\n      var result = value;\n\n      // allows working with \"Collections\" methods without using their `callback`\n      // argument, `index|key`, for this method's `callback`\n      if (typeof deep == 'function') {\n        thisArg = callback;\n        callback = deep;\n        deep = false;\n      }\n      if (typeof callback == 'function') {\n        callback = (typeof thisArg == 'undefined')\n          ? callback\n          : lodash.createCallback(callback, thisArg, 1);\n\n        result = callback(result);\n        if (typeof result != 'undefined') {\n          return result;\n        }\n        result = value;\n      }\n      // inspect [[Class]]\n      var isObj = isObject(result);\n      if (isObj) {\n        var className = toString.call(result);\n        if (!cloneableClasses[className] || (!support.nodeClass && isNode(result))) {\n          return result;\n        }\n        var isArr = isArray(result);\n      }\n      // shallow clone\n      if (!isObj || !deep) {\n        return isObj\n          ? (isArr ? slice(result) : assign({}, result))\n          : result;\n      }\n      var ctor = ctorByClass[className];\n      switch (className) {\n        case boolClass:\n        case dateClass:\n          return new ctor(+result);\n\n        case numberClass:\n        case stringClass:\n          return new ctor(result);\n\n        case regexpClass:\n          return ctor(result.source, reFlags.exec(result));\n      }\n      // check for circular references and return corresponding clone\n      stackA || (stackA = []);\n      stackB || (stackB = []);\n\n      var length = stackA.length;\n      while (length--) {\n        if (stackA[length] == value) {\n          return stackB[length];\n        }\n      }\n      // init cloned object\n      result = isArr ? ctor(result.length) : {};\n\n      // add array properties assigned by `RegExp#exec`\n      if (isArr) {\n        if (hasOwnProperty.call(value, 'index')) {\n          result.index = value.index;\n        }\n        if (hasOwnProperty.call(value, 'input')) {\n          result.input = value.input;\n        }\n      }\n      // add the source value to the stack of traversed objects\n      // and associate it with its clone\n      stackA.push(value);\n      stackB.push(result);\n\n      // recursively populate clone (susceptible to call stack limits)\n      (isArr ? forEach : forOwn)(value, function(objValue, key) {\n        result[key] = clone(objValue, deep, callback, undefined, stackA, stackB);\n      });\n\n      return result;\n    }\n\n    /**\n     * Creates a deep clone of `value`. If a `callback` function is passed,\n     * it will be executed to produce the cloned values. If `callback` returns\n     * `undefined`, cloning will be handled by the method instead. The `callback`\n     * is bound to `thisArg` and invoked with one argument; (value).\n     *\n     * Note: This function is loosely based on the structured clone algorithm. Functions\n     * and DOM nodes are **not** cloned. The enumerable properties of `arguments` objects and\n     * objects created by constructors other than `Object` are cloned to plain `Object` objects.\n     * See http://www.w3.org/TR/html5/infrastructure.html#internal-structured-cloning-algorithm.\n     *\n     * @static\n     * @memberOf _\n     * @category Objects\n     * @param {Mixed} value The value to deep clone.\n     * @param {Function} [callback] The function to customize cloning values.\n     * @param {Mixed} [thisArg] The `this` binding of `callback`.\n     * @returns {Mixed} Returns the deep cloned `value`.\n     * @example\n     *\n     * var stooges = [\n     *   { 'name': 'moe', 'age': 40 },\n     *   { 'name': 'larry', 'age': 50 }\n     * ];\n     *\n     * var deep = _.cloneDeep(stooges);\n     * deep[0] === stooges[0];\n     * // => false\n     *\n     * var view = {\n     *   'label': 'docs',\n     *   'node': element\n     * };\n     *\n     * var clone = _.cloneDeep(view, function(value) {\n     *   return _.isElement(value) ? value.cloneNode(true) : undefined;\n     * });\n     *\n     * clone.node == view.node;\n     * // => false\n     */\n    function cloneDeep(value, callback, thisArg) {\n      return clone(value, true, callback, thisArg);\n    }\n\n    /**\n     * Assigns own enumerable properties of source object(s) to the destination\n     * object for all destination properties that resolve to `undefined`. Once a\n     * property is set, additional defaults of the same property will be ignored.\n     *\n     * @static\n     * @memberOf _\n     * @type Function\n     * @category Objects\n     * @param {Object} object The destination object.\n     * @param {Object} [source1, source2, ...] The source objects.\n     * @param- {Object} [guard] Allows working with `_.reduce` without using its\n     *  callback's `key` and `object` arguments as sources.\n     * @returns {Object} Returns the destination object.\n     * @example\n     *\n     * var food = { 'name': 'apple' };\n     * _.defaults(food, { 'name': 'banana', 'type': 'fruit' });\n     * // => { 'name': 'apple', 'type': 'fruit' }\n     */\n    var defaults = createIterator(defaultsIteratorOptions);\n\n\n    /**\n     * This method is similar to `_.find`, except that it returns the key of the\n     * element that passes the callback check, instead of the element itself.\n     *\n     * @static\n     * @memberOf _\n     * @category Objects\n     * @param {Array|Object|String} collection The collection to iterate over.\n     * @param {Function|Object|String} [callback=identity] The function called per\n     *  iteration. If a property name or object is passed, it will be used to create\n     *  a \"_.pluck\" or \"_.where\" style callback, respectively.\n     * @param {Mixed} [thisArg] The `this` binding of `callback`.\n     * @returns {Mixed} Returns the key of the found element, else `undefined`.\n     * @example\n     *\n     * _.findKey({ 'a': 1, 'b': 2, 'c': 3, 'd': 4 }, function(num) { return num % 2 == 0; });\n     * // => 'b'\n     */\n    function findKey(collection, callback, thisArg) {\n      var result;\n      callback = lodash.createCallback(callback, thisArg);\n      forOwn(collection, function(value, key, collection) {\n        if (callback(value, key, collection)) {\n          result = key;\n          return false;\n        }\n      });\n      return result;\n    }\n\n    /**\n     * Iterates over `object`'s own and inherited enumerable properties, executing\n     * the `callback` for each property. The `callback` is bound to `thisArg` and\n     * invoked with three arguments; (value, key, object). Callbacks may exit iteration\n     * early by explicitly returning `false`.\n     *\n     * @static\n     * @memberOf _\n     * @type Function\n     * @category Objects\n     * @param {Object} object The object to iterate over.\n     * @param {Function} [callback=identity] The function called per iteration.\n     * @param {Mixed} [thisArg] The `this` binding of `callback`.\n     * @returns {Object} Returns `object`.\n     * @example\n     *\n     * function Dog(name) {\n     *   this.name = name;\n     * }\n     *\n     * Dog.prototype.bark = function() {\n     *   alert('Woof, woof!');\n     * };\n     *\n     * _.forIn(new Dog('Dagny'), function(value, key) {\n     *   alert(key);\n     * });\n     * // => alerts 'name' and 'bark' (order is not guaranteed)\n     */\n    var forIn = createIterator(eachIteratorOptions, forOwnIteratorOptions, {\n      'useHas': false\n    });\n\n    /**\n     * Iterates over an object's own enumerable properties, executing the `callback`\n     * for each property. The `callback` is bound to `thisArg` and invoked with three\n     * arguments; (value, key, object). Callbacks may exit iteration early by explicitly\n     * returning `false`.\n     *\n     * @static\n     * @memberOf _\n     * @type Function\n     * @category Objects\n     * @param {Object} object The object to iterate over.\n     * @param {Function} [callback=identity] The function called per iteration.\n     * @param {Mixed} [thisArg] The `this` binding of `callback`.\n     * @returns {Object} Returns `object`.\n     * @example\n     *\n     * _.forOwn({ '0': 'zero', '1': 'one', 'length': 2 }, function(num, key) {\n     *   alert(key);\n     * });\n     * // => alerts '0', '1', and 'length' (order is not guaranteed)\n     */\n    var forOwn = createIterator(eachIteratorOptions, forOwnIteratorOptions);\n\n    /**\n     * Creates a sorted array of all enumerable properties, own and inherited,\n     * of `object` that have function values.\n     *\n     * @static\n     * @memberOf _\n     * @alias methods\n     * @category Objects\n     * @param {Object} object The object to inspect.\n     * @returns {Array} Returns a new array of property names that have function values.\n     * @example\n     *\n     * _.functions(_);\n     * // => ['all', 'any', 'bind', 'bindAll', 'clone', 'compact', 'compose', ...]\n     */\n    function functions(object) {\n      var result = [];\n      forIn(object, function(value, key) {\n        if (isFunction(value)) {\n          result.push(key);\n        }\n      });\n      return result.sort();\n    }\n\n    /**\n     * Checks if the specified object `property` exists and is a direct property,\n     * instead of an inherited property.\n     *\n     * @static\n     * @memberOf _\n     * @category Objects\n     * @param {Object} object The object to check.\n     * @param {String} property The property to check for.\n     * @returns {Boolean} Returns `true` if key is a direct property, else `false`.\n     * @example\n     *\n     * _.has({ 'a': 1, 'b': 2, 'c': 3 }, 'b');\n     * // => true\n     */\n    function has(object, property) {\n      return object ? hasOwnProperty.call(object, property) : false;\n    }\n\n    /**\n     * Creates an object composed of the inverted keys and values of the given `object`.\n     *\n     * @static\n     * @memberOf _\n     * @category Objects\n     * @param {Object} object The object to invert.\n     * @returns {Object} Returns the created inverted object.\n     * @example\n     *\n     *  _.invert({ 'first': 'moe', 'second': 'larry' });\n     * // => { 'moe': 'first', 'larry': 'second' }\n     */\n    function invert(object) {\n      var index = -1,\n          props = keys(object),\n          length = props.length,\n          result = {};\n\n      while (++index < length) {\n        var key = props[index];\n        result[object[key]] = key;\n      }\n      return result;\n    }\n\n    /**\n     * Checks if `value` is a boolean value.\n     *\n     * @static\n     * @memberOf _\n     * @category Objects\n     * @param {Mixed} value The value to check.\n     * @returns {Boolean} Returns `true`, if the `value` is a boolean value, else `false`.\n     * @example\n     *\n     * _.isBoolean(null);\n     * // => false\n     */\n    function isBoolean(value) {\n      return value === true || value === false || toString.call(value) == boolClass;\n    }\n\n    /**\n     * Checks if `value` is a date.\n     *\n     * @static\n     * @memberOf _\n     * @category Objects\n     * @param {Mixed} value The value to check.\n     * @returns {Boolean} Returns `true`, if the `value` is a date, else `false`.\n     * @example\n     *\n     * _.isDate(new Date);\n     * // => true\n     */\n    function isDate(value) {\n      return value instanceof Date || toString.call(value) == dateClass;\n    }\n\n    /**\n     * Checks if `value` is a DOM element.\n     *\n     * @static\n     * @memberOf _\n     * @category Objects\n     * @param {Mixed} value The value to check.\n     * @returns {Boolean} Returns `true`, if the `value` is a DOM element, else `false`.\n     * @example\n     *\n     * _.isElement(document.body);\n     * // => true\n     */\n    function isElement(value) {\n      return value ? value.nodeType === 1 : false;\n    }\n\n    /**\n     * Checks if `value` is empty. Arrays, strings, or `arguments` objects with a\n     * length of `0` and objects with no own enumerable properties are considered\n     * \"empty\".\n     *\n     * @static\n     * @memberOf _\n     * @category Objects\n     * @param {Array|Object|String} value The value to inspect.\n     * @returns {Boolean} Returns `true`, if the `value` is empty, else `false`.\n     * @example\n     *\n     * _.isEmpty([1, 2, 3]);\n     * // => false\n     *\n     * _.isEmpty({});\n     * // => true\n     *\n     * _.isEmpty('');\n     * // => true\n     */\n    function isEmpty(value) {\n      var result = true;\n      if (!value) {\n        return result;\n      }\n      var className = toString.call(value),\n          length = value.length;\n\n      if ((className == arrayClass || className == stringClass ||\n          (support.argsClass ? className == argsClass : isArguments(value))) ||\n          (className == objectClass && typeof length == 'number' && isFunction(value.splice))) {\n        return !length;\n      }\n      forOwn(value, function() {\n        return (result = false);\n      });\n      return result;\n    }\n\n    /**\n     * Performs a deep comparison between two values to determine if they are\n     * equivalent to each other. If `callback` is passed, it will be executed to\n     * compare values. If `callback` returns `undefined`, comparisons will be handled\n     * by the method instead. The `callback` is bound to `thisArg` and invoked with\n     * two arguments; (a, b).\n     *\n     * @static\n     * @memberOf _\n     * @category Objects\n     * @param {Mixed} a The value to compare.\n     * @param {Mixed} b The other value to compare.\n     * @param {Function} [callback] The function to customize comparing values.\n     * @param {Mixed} [thisArg] The `this` binding of `callback`.\n     * @param- {Array} [stackA=[]] Tracks traversed `a` objects.\n     * @param- {Array} [stackB=[]] Tracks traversed `b` objects.\n     * @returns {Boolean} Returns `true`, if the values are equivalent, else `false`.\n     * @example\n     *\n     * var moe = { 'name': 'moe', 'age': 40 };\n     * var copy = { 'name': 'moe', 'age': 40 };\n     *\n     * moe == copy;\n     * // => false\n     *\n     * _.isEqual(moe, copy);\n     * // => true\n     *\n     * var words = ['hello', 'goodbye'];\n     * var otherWords = ['hi', 'goodbye'];\n     *\n     * _.isEqual(words, otherWords, function(a, b) {\n     *   var reGreet = /^(?:hello|hi)$/i,\n     *       aGreet = _.isString(a) && reGreet.test(a),\n     *       bGreet = _.isString(b) && reGreet.test(b);\n     *\n     *   return (aGreet || bGreet) ? (aGreet == bGreet) : undefined;\n     * });\n     * // => true\n     */\n    function isEqual(a, b, callback, thisArg, stackA, stackB) {\n      // used to indicate that when comparing objects, `a` has at least the properties of `b`\n      var whereIndicator = callback === indicatorObject;\n      if (callback && !whereIndicator) {\n        callback = (typeof thisArg == 'undefined')\n          ? callback\n          : lodash.createCallback(callback, thisArg, 2);\n\n        var result = callback(a, b);\n        if (typeof result != 'undefined') {\n          return !!result;\n        }\n      }\n      // exit early for identical values\n      if (a === b) {\n        // treat `+0` vs. `-0` as not equal\n        return a !== 0 || (1 / a == 1 / b);\n      }\n      var type = typeof a,\n          otherType = typeof b;\n\n      // exit early for unlike primitive values\n      if (a === a &&\n          (!a || (type != 'function' && type != 'object')) &&\n          (!b || (otherType != 'function' && otherType != 'object'))) {\n        return false;\n      }\n      // exit early for `null` and `undefined`, avoiding ES3's Function#call behavior\n      // http://es5.github.com/#x15.3.4.4\n      if (a == null || b == null) {\n        return a === b;\n      }\n      // compare [[Class]] names\n      var className = toString.call(a),\n          otherClass = toString.call(b);\n\n      if (className == argsClass) {\n        className = objectClass;\n      }\n      if (otherClass == argsClass) {\n        otherClass = objectClass;\n      }\n      if (className != otherClass) {\n        return false;\n      }\n      switch (className) {\n        case boolClass:\n        case dateClass:\n          // coerce dates and booleans to numbers, dates to milliseconds and booleans\n          // to `1` or `0`, treating invalid dates coerced to `NaN` as not equal\n          return +a == +b;\n\n        case numberClass:\n          // treat `NaN` vs. `NaN` as equal\n          return (a != +a)\n            ? b != +b\n            // but treat `+0` vs. `-0` as not equal\n            : (a == 0 ? (1 / a == 1 / b) : a == +b);\n\n        case regexpClass:\n        case stringClass:\n          // coerce regexes to strings (http://es5.github.com/#x15.10.6.4)\n          // treat string primitives and their corresponding object instances as equal\n          return a == String(b);\n      }\n      var isArr = className == arrayClass;\n      if (!isArr) {\n        // unwrap any `lodash` wrapped values\n        if (hasOwnProperty.call(a, '__wrapped__ ') || hasOwnProperty.call(b, '__wrapped__')) {\n          return isEqual(a.__wrapped__ || a, b.__wrapped__ || b, callback, thisArg, stackA, stackB);\n        }\n        // exit for functions and DOM nodes\n        if (className != objectClass || (!support.nodeClass && (isNode(a) || isNode(b)))) {\n          return false;\n        }\n        // in older versions of Opera, `arguments` objects have `Array` constructors\n        var ctorA = !support.argsObject && isArguments(a) ? Object : a.constructor,\n            ctorB = !support.argsObject && isArguments(b) ? Object : b.constructor;\n\n        // non `Object` object instances with different constructors are not equal\n        if (ctorA != ctorB && !(\n              isFunction(ctorA) && ctorA instanceof ctorA &&\n              isFunction(ctorB) && ctorB instanceof ctorB\n            )) {\n          return false;\n        }\n      }\n      // assume cyclic structures are equal\n      // the algorithm for detecting cyclic structures is adapted from ES 5.1\n      // section 15.12.3, abstract operation `JO` (http://es5.github.com/#x15.12.3)\n      stackA || (stackA = []);\n      stackB || (stackB = []);\n\n      var length = stackA.length;\n      while (length--) {\n        if (stackA[length] == a) {\n          return stackB[length] == b;\n        }\n      }\n      var size = 0;\n      result = true;\n\n      // add `a` and `b` to the stack of traversed objects\n      stackA.push(a);\n      stackB.push(b);\n\n      // recursively compare objects and arrays (susceptible to call stack limits)\n      if (isArr) {\n        length = a.length;\n        size = b.length;\n\n        // compare lengths to determine if a deep comparison is necessary\n        result = size == a.length;\n        if (!result && !whereIndicator) {\n          return result;\n        }\n        // deep compare the contents, ignoring non-numeric properties\n        while (size--) {\n          var index = length,\n              value = b[size];\n\n          if (whereIndicator) {\n            while (index--) {\n              if ((result = isEqual(a[index], value, callback, thisArg, stackA, stackB))) {\n                break;\n              }\n            }\n          } else if (!(result = isEqual(a[size], value, callback, thisArg, stackA, stackB))) {\n            break;\n          }\n        }\n        return result;\n      }\n      // deep compare objects using `forIn`, instead of `forOwn`, to avoid `Object.keys`\n      // which, in this case, is more costly\n      forIn(b, function(value, key, b) {\n        if (hasOwnProperty.call(b, key)) {\n          // count the number of properties.\n          size++;\n          // deep compare each property value.\n          return (result = hasOwnProperty.call(a, key) && isEqual(a[key], value, callback, thisArg, stackA, stackB));\n        }\n      });\n\n      if (result && !whereIndicator) {\n        // ensure both objects have the same number of properties\n        forIn(a, function(value, key, a) {\n          if (hasOwnProperty.call(a, key)) {\n            // `size` will be `-1` if `a` has more properties than `b`\n            return (result = --size > -1);\n          }\n        });\n      }\n      return result;\n    }\n\n    /**\n     * Checks if `value` is, or can be coerced to, a finite number.\n     *\n     * Note: This is not the same as native `isFinite`, which will return true for\n     * booleans and empty strings. See http://es5.github.com/#x15.1.2.5.\n     *\n     * @static\n     * @memberOf _\n     * @category Objects\n     * @param {Mixed} value The value to check.\n     * @returns {Boolean} Returns `true`, if the `value` is finite, else `false`.\n     * @example\n     *\n     * _.isFinite(-101);\n     * // => true\n     *\n     * _.isFinite('10');\n     * // => true\n     *\n     * _.isFinite(true);\n     * // => false\n     *\n     * _.isFinite('');\n     * // => false\n     *\n     * _.isFinite(Infinity);\n     * // => false\n     */\n    function isFinite(value) {\n      return nativeIsFinite(value) && !nativeIsNaN(parseFloat(value));\n    }\n\n    /**\n     * Checks if `value` is a function.\n     *\n     * @static\n     * @memberOf _\n     * @category Objects\n     * @param {Mixed} value The value to check.\n     * @returns {Boolean} Returns `true`, if the `value` is a function, else `false`.\n     * @example\n     *\n     * _.isFunction(_);\n     * // => true\n     */\n    function isFunction(value) {\n      return typeof value == 'function';\n    }\n    // fallback for older versions of Chrome and Safari\n    if (isFunction(/x/)) {\n      isFunction = function(value) {\n        return value instanceof Function || toString.call(value) == funcClass;\n      };\n    }\n\n    /**\n     * Checks if `value` is the language type of Object.\n     * (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)\n     *\n     * @static\n     * @memberOf _\n     * @category Objects\n     * @param {Mixed} value The value to check.\n     * @returns {Boolean} Returns `true`, if the `value` is an object, else `false`.\n     * @example\n     *\n     * _.isObject({});\n     * // => true\n     *\n     * _.isObject([1, 2, 3]);\n     * // => true\n     *\n     * _.isObject(1);\n     * // => false\n     */\n    function isObject(value) {\n      // check if the value is the ECMAScript language type of Object\n      // http://es5.github.com/#x8\n      // and avoid a V8 bug\n      // http://code.google.com/p/v8/issues/detail?id=2291\n      return value ? objectTypes[typeof value] : false;\n    }\n\n    /**\n     * Checks if `value` is `NaN`.\n     *\n     * Note: This is not the same as native `isNaN`, which will return `true` for\n     * `undefined` and other values. See http://es5.github.com/#x15.1.2.4.\n     *\n     * @static\n     * @memberOf _\n     * @category Objects\n     * @param {Mixed} value The value to check.\n     * @returns {Boolean} Returns `true`, if the `value` is `NaN`, else `false`.\n     * @example\n     *\n     * _.isNaN(NaN);\n     * // => true\n     *\n     * _.isNaN(new Number(NaN));\n     * // => true\n     *\n     * isNaN(undefined);\n     * // => true\n     *\n     * _.isNaN(undefined);\n     * // => false\n     */\n    function isNaN(value) {\n      // `NaN` as a primitive is the only value that is not equal to itself\n      // (perform the [[Class]] check first to avoid errors with some host objects in IE)\n      return isNumber(value) && value != +value\n    }\n\n    /**\n     * Checks if `value` is `null`.\n     *\n     * @static\n     * @memberOf _\n     * @category Objects\n     * @param {Mixed} value The value to check.\n     * @returns {Boolean} Returns `true`, if the `value` is `null`, else `false`.\n     * @example\n     *\n     * _.isNull(null);\n     * // => true\n     *\n     * _.isNull(undefined);\n     * // => false\n     */\n    function isNull(value) {\n      return value === null;\n    }\n\n    /**\n     * Checks if `value` is a number.\n     *\n     * @static\n     * @memberOf _\n     * @category Objects\n     * @param {Mixed} value The value to check.\n     * @returns {Boolean} Returns `true`, if the `value` is a number, else `false`.\n     * @example\n     *\n     * _.isNumber(8.4 * 5);\n     * // => true\n     */\n    function isNumber(value) {\n      return typeof value == 'number' || toString.call(value) == numberClass;\n    }\n\n    /**\n     * Checks if a given `value` is an object created by the `Object` constructor.\n     *\n     * @static\n     * @memberOf _\n     * @category Objects\n     * @param {Mixed} value The value to check.\n     * @returns {Boolean} Returns `true`, if `value` is a plain object, else `false`.\n     * @example\n     *\n     * function Stooge(name, age) {\n     *   this.name = name;\n     *   this.age = age;\n     * }\n     *\n     * _.isPlainObject(new Stooge('moe', 40));\n     * // => false\n     *\n     * _.isPlainObject([1, 2, 3]);\n     * // => false\n     *\n     * _.isPlainObject({ 'name': 'moe', 'age': 40 });\n     * // => true\n     */\n    var isPlainObject = !getPrototypeOf ? shimIsPlainObject : function(value) {\n      if (!(value && toString.call(value) == objectClass) || (!support.argsClass && isArguments(value))) {\n        return false;\n      }\n      var valueOf = value.valueOf,\n          objProto = typeof valueOf == 'function' && (objProto = getPrototypeOf(valueOf)) && getPrototypeOf(objProto);\n\n      return objProto\n        ? (value == objProto || getPrototypeOf(value) == objProto)\n        : shimIsPlainObject(value);\n    };\n\n    /**\n     * Checks if `value` is a regular expression.\n     *\n     * @static\n     * @memberOf _\n     * @category Objects\n     * @param {Mixed} value The value to check.\n     * @returns {Boolean} Returns `true`, if the `value` is a regular expression, else `false`.\n     * @example\n     *\n     * _.isRegExp(/moe/);\n     * // => true\n     */\n    function isRegExp(value) {\n      return value instanceof RegExp || toString.call(value) == regexpClass;\n    }\n\n    /**\n     * Checks if `value` is a string.\n     *\n     * @static\n     * @memberOf _\n     * @category Objects\n     * @param {Mixed} value The value to check.\n     * @returns {Boolean} Returns `true`, if the `value` is a string, else `false`.\n     * @example\n     *\n     * _.isString('moe');\n     * // => true\n     */\n    function isString(value) {\n      return typeof value == 'string' || toString.call(value) == stringClass;\n    }\n\n    /**\n     * Checks if `value` is `undefined`.\n     *\n     * @static\n     * @memberOf _\n     * @category Objects\n     * @param {Mixed} value The value to check.\n     * @returns {Boolean} Returns `true`, if the `value` is `undefined`, else `false`.\n     * @example\n     *\n     * _.isUndefined(void 0);\n     * // => true\n     */\n    function isUndefined(value) {\n      return typeof value == 'undefined';\n    }\n\n    /**\n     * Recursively merges own enumerable properties of the source object(s), that\n     * don't resolve to `undefined`, into the destination object. Subsequent sources\n     * will overwrite property assignments of previous sources. If a `callback` function\n     * is passed, it will be executed to produce the merged values of the destination\n     * and source properties. If `callback` returns `undefined`, merging will be\n     * handled by the method instead. The `callback` is bound to `thisArg` and\n     * invoked with two arguments; (objectValue, sourceValue).\n     *\n     * @static\n     * @memberOf _\n     * @category Objects\n     * @param {Object} object The destination object.\n     * @param {Object} [source1, source2, ...] The source objects.\n     * @param {Function} [callback] The function to customize merging properties.\n     * @param {Mixed} [thisArg] The `this` binding of `callback`.\n     * @param- {Object} [deepIndicator] Indicates that `stackA` and `stackB` are\n     *  arrays of traversed objects, instead of source objects.\n     * @param- {Array} [stackA=[]] Tracks traversed source objects.\n     * @param- {Array} [stackB=[]] Associates values with source counterparts.\n     * @returns {Object} Returns the destination object.\n     * @example\n     *\n     * var names = {\n     *   'stooges': [\n     *     { 'name': 'moe' },\n     *     { 'name': 'larry' }\n     *   ]\n     * };\n     *\n     * var ages = {\n     *   'stooges': [\n     *     { 'age': 40 },\n     *     { 'age': 50 }\n     *   ]\n     * };\n     *\n     * _.merge(names, ages);\n     * // => { 'stooges': [{ 'name': 'moe', 'age': 40 }, { 'name': 'larry', 'age': 50 }] }\n     *\n     * var food = {\n     *   'fruits': ['apple'],\n     *   'vegetables': ['beet']\n     * };\n     *\n     * var otherFood = {\n     *   'fruits': ['banana'],\n     *   'vegetables': ['carrot']\n     * };\n     *\n     * _.merge(food, otherFood, function(a, b) {\n     *   return _.isArray(a) ? a.concat(b) : undefined;\n     * });\n     * // => { 'fruits': ['apple', 'banana'], 'vegetables': ['beet', 'carrot] }\n     */\n    function merge(object, source, deepIndicator) {\n      var args = arguments,\n          index = 0,\n          length = 2;\n\n      if (!isObject(object)) {\n        return object;\n      }\n      if (deepIndicator === indicatorObject) {\n        var callback = args[3],\n            stackA = args[4],\n            stackB = args[5];\n      } else {\n        stackA = [];\n        stackB = [];\n\n        // allows working with `_.reduce` and `_.reduceRight` without\n        // using their `callback` arguments, `index|key` and `collection`\n        if (typeof deepIndicator != 'number') {\n          length = args.length;\n        }\n        if (length > 3 && typeof args[length - 2] == 'function') {\n          callback = lodash.createCallback(args[--length - 1], args[length--], 2);\n        } else if (length > 2 && typeof args[length - 1] == 'function') {\n          callback = args[--length];\n        }\n      }\n      while (++index < length) {\n        (isArray(args[index]) ? forEach : forOwn)(args[index], function(source, key) {\n          var found,\n              isArr,\n              result = source,\n              value = object[key];\n\n          if (source && ((isArr = isArray(source)) || isPlainObject(source))) {\n            // avoid merging previously merged cyclic sources\n            var stackLength = stackA.length;\n            while (stackLength--) {\n              if ((found = stackA[stackLength] == source)) {\n                value = stackB[stackLength];\n                break;\n              }\n            }\n            if (!found) {\n              value = isArr\n                ? (isArray(value) ? value : [])\n                : (isPlainObject(value) ? value : {});\n\n              if (callback) {\n                result = callback(value, source);\n                if (typeof result != 'undefined') {\n                  value = result;\n                }\n              }\n              // add `source` and associated `value` to the stack of traversed objects\n              stackA.push(source);\n              stackB.push(value);\n\n              // recursively merge objects and arrays (susceptible to call stack limits)\n              if (!callback) {\n                value = merge(value, source, indicatorObject, callback, stackA, stackB);\n              }\n            }\n          }\n          else {\n            if (callback) {\n              result = callback(value, source);\n              if (typeof result == 'undefined') {\n                result = source;\n              }\n            }\n            if (typeof result != 'undefined') {\n              value = result;\n            }\n          }\n          object[key] = value;\n        });\n      }\n      return object;\n    }\n\n    /**\n     * Creates a shallow clone of `object` excluding the specified properties.\n     * Property names may be specified as individual arguments or as arrays of\n     * property names. If a `callback` function is passed, it will be executed\n     * for each property in the `object`, omitting the properties `callback`\n     * returns truthy for. The `callback` is bound to `thisArg` and invoked\n     * with three arguments; (value, key, object).\n     *\n     * @static\n     * @memberOf _\n     * @category Objects\n     * @param {Object} object The source object.\n     * @param {Function|String} callback|[prop1, prop2, ...] The properties to omit\n     *  or the function called per iteration.\n     * @param {Mixed} [thisArg] The `this` binding of `callback`.\n     * @returns {Object} Returns an object without the omitted properties.\n     * @example\n     *\n     * _.omit({ 'name': 'moe', 'age': 40 }, 'age');\n     * // => { 'name': 'moe' }\n     *\n     * _.omit({ 'name': 'moe', 'age': 40 }, function(value) {\n     *   return typeof value == 'number';\n     * });\n     * // => { 'name': 'moe' }\n     */\n    function omit(object, callback, thisArg) {\n      var isFunc = typeof callback == 'function',\n          result = {};\n\n      if (isFunc) {\n        callback = lodash.createCallback(callback, thisArg);\n      } else {\n        var props = concat.apply(arrayRef, arguments);\n      }\n      forIn(object, function(value, key, object) {\n        if (isFunc\n              ? !callback(value, key, object)\n              : indexOf(props, key, 1) < 0\n            ) {\n          result[key] = value;\n        }\n      });\n      return result;\n    }\n\n    /**\n     * Creates a two dimensional array of the given object's key-value pairs,\n     * i.e. `[[key1, value1], [key2, value2]]`.\n     *\n     * @static\n     * @memberOf _\n     * @category Objects\n     * @param {Object} object The object to inspect.\n     * @returns {Array} Returns new array of key-value pairs.\n     * @example\n     *\n     * _.pairs({ 'moe': 30, 'larry': 40 });\n     * // => [['moe', 30], ['larry', 40]] (order is not guaranteed)\n     */\n    function pairs(object) {\n      var index = -1,\n          props = keys(object),\n          length = props.length,\n          result = Array(length);\n\n      while (++index < length) {\n        var key = props[index];\n        result[index] = [key, object[key]];\n      }\n      return result;\n    }\n\n    /**\n     * Creates a shallow clone of `object` composed of the specified properties.\n     * Property names may be specified as individual arguments or as arrays of property\n     * names. If `callback` is passed, it will be executed for each property in the\n     * `object`, picking the properties `callback` returns truthy for. The `callback`\n     * is bound to `thisArg` and invoked with three arguments; (value, key, object).\n     *\n     * @static\n     * @memberOf _\n     * @category Objects\n     * @param {Object} object The source object.\n     * @param {Array|Function|String} callback|[prop1, prop2, ...] The function called\n     *  per iteration or properties to pick, either as individual arguments or arrays.\n     * @param {Mixed} [thisArg] The `this` binding of `callback`.\n     * @returns {Object} Returns an object composed of the picked properties.\n     * @example\n     *\n     * _.pick({ 'name': 'moe', '_userid': 'moe1' }, 'name');\n     * // => { 'name': 'moe' }\n     *\n     * _.pick({ 'name': 'moe', '_userid': 'moe1' }, function(value, key) {\n     *   return key.charAt(0) != '_';\n     * });\n     * // => { 'name': 'moe' }\n     */\n    function pick(object, callback, thisArg) {\n      var result = {};\n      if (typeof callback != 'function') {\n        var index = 0,\n            props = concat.apply(arrayRef, arguments),\n            length = isObject(object) ? props.length : 0;\n\n        while (++index < length) {\n          var key = props[index];\n          if (key in object) {\n            result[key] = object[key];\n          }\n        }\n      } else {\n        callback = lodash.createCallback(callback, thisArg);\n        forIn(object, function(value, key, object) {\n          if (callback(value, key, object)) {\n            result[key] = value;\n          }\n        });\n      }\n      return result;\n    }\n\n    /**\n     * Creates an array composed of the own enumerable property values of `object`.\n     *\n     * @static\n     * @memberOf _\n     * @category Objects\n     * @param {Object} object The object to inspect.\n     * @returns {Array} Returns a new array of property values.\n     * @example\n     *\n     * _.values({ 'one': 1, 'two': 2, 'three': 3 });\n     * // => [1, 2, 3] (order is not guaranteed)\n     */\n    function values(object) {\n      var index = -1,\n          props = keys(object),\n          length = props.length,\n          result = Array(length);\n\n      while (++index < length) {\n        result[index] = object[props[index]];\n      }\n      return result;\n    }\n\n    /*--------------------------------------------------------------------------*/\n\n    /**\n     * Creates an array of elements from the specified indexes, or keys, of the\n     * `collection`. Indexes may be specified as individual arguments or as arrays\n     * of indexes.\n     *\n     * @static\n     * @memberOf _\n     * @category Collections\n     * @param {Array|Object|String} collection The collection to iterate over.\n     * @param {Array|Number|String} [index1, index2, ...] The indexes of\n     *  `collection` to retrieve, either as individual arguments or arrays.\n     * @returns {Array} Returns a new array of elements corresponding to the\n     *  provided indexes.\n     * @example\n     *\n     * _.at(['a', 'b', 'c', 'd', 'e'], [0, 2, 4]);\n     * // => ['a', 'c', 'e']\n     *\n     * _.at(['moe', 'larry', 'curly'], 0, 2);\n     * // => ['moe', 'curly']\n     */\n    function at(collection) {\n      var index = -1,\n          props = concat.apply(arrayRef, slice(arguments, 1)),\n          length = props.length,\n          result = Array(length);\n\n      if (support.unindexedChars && isString(collection)) {\n        collection = collection.split('');\n      }\n      while(++index < length) {\n        result[index] = collection[props[index]];\n      }\n      return result;\n    }\n\n    /**\n     * Checks if a given `target` element is present in a `collection` using strict\n     * equality for comparisons, i.e. `===`. If `fromIndex` is negative, it is used\n     * as the offset from the end of the collection.\n     *\n     * @static\n     * @memberOf _\n     * @alias include\n     * @category Collections\n     * @param {Array|Object|String} collection The collection to iterate over.\n     * @param {Mixed} target The value to check for.\n     * @param {Number} [fromIndex=0] The index to search from.\n     * @returns {Boolean} Returns `true` if the `target` element is found, else `false`.\n     * @example\n     *\n     * _.contains([1, 2, 3], 1);\n     * // => true\n     *\n     * _.contains([1, 2, 3], 1, 2);\n     * // => false\n     *\n     * _.contains({ 'name': 'moe', 'age': 40 }, 'moe');\n     * // => true\n     *\n     * _.contains('curly', 'ur');\n     * // => true\n     */\n    function contains(collection, target, fromIndex) {\n      var index = -1,\n          length = collection ? collection.length : 0,\n          result = false;\n\n      fromIndex = (fromIndex < 0 ? nativeMax(0, length + fromIndex) : fromIndex) || 0;\n      if (typeof length == 'number') {\n        result = (isString(collection)\n          ? collection.indexOf(target, fromIndex)\n          : indexOf(collection, target, fromIndex)\n        ) > -1;\n      } else {\n        each(collection, function(value) {\n          if (++index >= fromIndex) {\n            return !(result = value === target);\n          }\n        });\n      }\n      return result;\n    }\n\n    /**\n     * Creates an object composed of keys returned from running each element of the\n     * `collection` through the given `callback`. The corresponding value of each key\n     * is the number of times the key was returned by the `callback`. The `callback`\n     * is bound to `thisArg` and invoked with three arguments; (value, index|key, collection).\n     *\n     * If a property name is passed for `callback`, the created \"_.pluck\" style\n     * callback will return the property value of the given element.\n     *\n     * If an object is passed for `callback`, the created \"_.where\" style callback\n     * will return `true` for elements that have the properties of the given object,\n     * else `false`.\n     *\n     * @static\n     * @memberOf _\n     * @category Collections\n     * @param {Array|Object|String} collection The collection to iterate over.\n     * @param {Function|Object|String} [callback=identity] The function called per\n     *  iteration. If a property name or object is passed, it will be used to create\n     *  a \"_.pluck\" or \"_.where\" style callback, respectively.\n     * @param {Mixed} [thisArg] The `this` binding of `callback`.\n     * @returns {Object} Returns the composed aggregate object.\n     * @example\n     *\n     * _.countBy([4.3, 6.1, 6.4], function(num) { return Math.floor(num); });\n     * // => { '4': 1, '6': 2 }\n     *\n     * _.countBy([4.3, 6.1, 6.4], function(num) { return this.floor(num); }, Math);\n     * // => { '4': 1, '6': 2 }\n     *\n     * _.countBy(['one', 'two', 'three'], 'length');\n     * // => { '3': 2, '5': 1 }\n     */\n    function countBy(collection, callback, thisArg) {\n      var result = {};\n      callback = lodash.createCallback(callback, thisArg);\n\n      forEach(collection, function(value, key, collection) {\n        key = String(callback(value, key, collection));\n        (hasOwnProperty.call(result, key) ? result[key]++ : result[key] = 1);\n      });\n      return result;\n    }\n\n    /**\n     * Checks if the `callback` returns a truthy value for **all** elements of a\n     * `collection`. The `callback` is bound to `thisArg` and invoked with three\n     * arguments; (value, index|key, collection).\n     *\n     * If a property name is passed for `callback`, the created \"_.pluck\" style\n     * callback will return the property value of the given element.\n     *\n     * If an object is passed for `callback`, the created \"_.where\" style callback\n     * will return `true` for elements that have the properties of the given object,\n     * else `false`.\n     *\n     * @static\n     * @memberOf _\n     * @alias all\n     * @category Collections\n     * @param {Array|Object|String} collection The collection to iterate over.\n     * @param {Function|Object|String} [callback=identity] The function called per\n     *  iteration. If a property name or object is passed, it will be used to create\n     *  a \"_.pluck\" or \"_.where\" style callback, respectively.\n     * @param {Mixed} [thisArg] The `this` binding of `callback`.\n     * @returns {Boolean} Returns `true` if all elements pass the callback check,\n     *  else `false`.\n     * @example\n     *\n     * _.every([true, 1, null, 'yes'], Boolean);\n     * // => false\n     *\n     * var stooges = [\n     *   { 'name': 'moe', 'age': 40 },\n     *   { 'name': 'larry', 'age': 50 }\n     * ];\n     *\n     * // using \"_.pluck\" callback shorthand\n     * _.every(stooges, 'age');\n     * // => true\n     *\n     * // using \"_.where\" callback shorthand\n     * _.every(stooges, { 'age': 50 });\n     * // => false\n     */\n    function every(collection, callback, thisArg) {\n      var result = true;\n      callback = lodash.createCallback(callback, thisArg);\n\n      if (isArray(collection)) {\n        var index = -1,\n            length = collection.length;\n\n        while (++index < length) {\n          if (!(result = !!callback(collection[index], index, collection))) {\n            break;\n          }\n        }\n      } else {\n        each(collection, function(value, index, collection) {\n          return (result = !!callback(value, index, collection));\n        });\n      }\n      return result;\n    }\n\n    /**\n     * Examines each element in a `collection`, returning an array of all elements\n     * the `callback` returns truthy for. The `callback` is bound to `thisArg` and\n     * invoked with three arguments; (value, index|key, collection).\n     *\n     * If a property name is passed for `callback`, the created \"_.pluck\" style\n     * callback will return the property value of the given element.\n     *\n     * If an object is passed for `callback`, the created \"_.where\" style callback\n     * will return `true` for elements that have the properties of the given object,\n     * else `false`.\n     *\n     * @static\n     * @memberOf _\n     * @alias select\n     * @category Collections\n     * @param {Array|Object|String} collection The collection to iterate over.\n     * @param {Function|Object|String} [callback=identity] The function called per\n     *  iteration. If a property name or object is passed, it will be used to create\n     *  a \"_.pluck\" or \"_.where\" style callback, respectively.\n     * @param {Mixed} [thisArg] The `this` binding of `callback`.\n     * @returns {Array} Returns a new array of elements that passed the callback check.\n     * @example\n     *\n     * var evens = _.filter([1, 2, 3, 4, 5, 6], function(num) { return num % 2 == 0; });\n     * // => [2, 4, 6]\n     *\n     * var food = [\n     *   { 'name': 'apple',  'organic': false, 'type': 'fruit' },\n     *   { 'name': 'carrot', 'organic': true,  'type': 'vegetable' }\n     * ];\n     *\n     * // using \"_.pluck\" callback shorthand\n     * _.filter(food, 'organic');\n     * // => [{ 'name': 'carrot', 'organic': true, 'type': 'vegetable' }]\n     *\n     * // using \"_.where\" callback shorthand\n     * _.filter(food, { 'type': 'fruit' });\n     * // => [{ 'name': 'apple', 'organic': false, 'type': 'fruit' }]\n     */\n    function filter(collection, callback, thisArg) {\n      var result = [];\n      callback = lodash.createCallback(callback, thisArg);\n\n      if (isArray(collection)) {\n        var index = -1,\n            length = collection.length;\n\n        while (++index < length) {\n          var value = collection[index];\n          if (callback(value, index, collection)) {\n            result.push(value);\n          }\n        }\n      } else {\n        each(collection, function(value, index, collection) {\n          if (callback(value, index, collection)) {\n            result.push(value);\n          }\n        });\n      }\n      return result;\n    }\n\n    /**\n     * Examines each element in a `collection`, returning the first that the `callback`\n     * returns truthy for. The `callback` is bound to `thisArg` and invoked with three\n     * arguments; (value, index|key, collection).\n     *\n     * If a property name is passed for `callback`, the created \"_.pluck\" style\n     * callback will return the property value of the given element.\n     *\n     * If an object is passed for `callback`, the created \"_.where\" style callback\n     * will return `true` for elements that have the properties of the given object,\n     * else `false`.\n     *\n     * @static\n     * @memberOf _\n     * @alias detect\n     * @category Collections\n     * @param {Array|Object|String} collection The collection to iterate over.\n     * @param {Function|Object|String} [callback=identity] The function called per\n     *  iteration. If a property name or object is passed, it will be used to create\n     *  a \"_.pluck\" or \"_.where\" style callback, respectively.\n     * @param {Mixed} [thisArg] The `this` binding of `callback`.\n     * @returns {Mixed} Returns the found element, else `undefined`.\n     * @example\n     *\n     * _.find([1, 2, 3, 4], function(num) { return num % 2 == 0; });\n     * // => 2\n     *\n     * var food = [\n     *   { 'name': 'apple',  'organic': false, 'type': 'fruit' },\n     *   { 'name': 'banana', 'organic': true,  'type': 'fruit' },\n     *   { 'name': 'beet',   'organic': false, 'type': 'vegetable' }\n     * ];\n     *\n     * // using \"_.where\" callback shorthand\n     * _.find(food, { 'type': 'vegetable' });\n     * // => { 'name': 'beet', 'organic': false, 'type': 'vegetable' }\n     *\n     * // using \"_.pluck\" callback shorthand\n     * _.find(food, 'organic');\n     * // => { 'name': 'banana', 'organic': true, 'type': 'fruit' }\n     */\n    function find(collection, callback, thisArg) {\n      callback = lodash.createCallback(callback, thisArg);\n\n      if (isArray(collection)) {\n        var index = -1,\n            length = collection.length;\n\n        while (++index < length) {\n          var value = collection[index];\n          if (callback(value, index, collection)) {\n            return value;\n          }\n        }\n      } else {\n        var result;\n        each(collection, function(value, index, collection) {\n          if (callback(value, index, collection)) {\n            result = value;\n            return false;\n          }\n        });\n        return result;\n      }\n    }\n\n    /**\n     * Iterates over a `collection`, executing the `callback` for each element in\n     * the `collection`. The `callback` is bound to `thisArg` and invoked with three\n     * arguments; (value, index|key, collection). Callbacks may exit iteration early\n     * by explicitly returning `false`.\n     *\n     * @static\n     * @memberOf _\n     * @alias each\n     * @category Collections\n     * @param {Array|Object|String} collection The collection to iterate over.\n     * @param {Function} [callback=identity] The function called per iteration.\n     * @param {Mixed} [thisArg] The `this` binding of `callback`.\n     * @returns {Array|Object|String} Returns `collection`.\n     * @example\n     *\n     * _([1, 2, 3]).forEach(alert).join(',');\n     * // => alerts each number and returns '1,2,3'\n     *\n     * _.forEach({ 'one': 1, 'two': 2, 'three': 3 }, alert);\n     * // => alerts each number value (order is not guaranteed)\n     */\n    function forEach(collection, callback, thisArg) {\n      if (callback && typeof thisArg == 'undefined' && isArray(collection)) {\n        var index = -1,\n            length = collection.length;\n\n        while (++index < length) {\n          if (callback(collection[index], index, collection) === false) {\n            break;\n          }\n        }\n      } else {\n        each(collection, callback, thisArg);\n      }\n      return collection;\n    }\n\n    /**\n     * Creates an object composed of keys returned from running each element of the\n     * `collection` through the `callback`. The corresponding value of each key is\n     * an array of elements passed to `callback` that returned the key. The `callback`\n     * is bound to `thisArg` and invoked with three arguments; (value, index|key, collection).\n     *\n     * If a property name is passed for `callback`, the created \"_.pluck\" style\n     * callback will return the property value of the given element.\n     *\n     * If an object is passed for `callback`, the created \"_.where\" style callback\n     * will return `true` for elements that have the properties of the given object,\n     * else `false`\n     *\n     * @static\n     * @memberOf _\n     * @category Collections\n     * @param {Array|Object|String} collection The collection to iterate over.\n     * @param {Function|Object|String} [callback=identity] The function called per\n     *  iteration. If a property name or object is passed, it will be used to create\n     *  a \"_.pluck\" or \"_.where\" style callback, respectively.\n     * @param {Mixed} [thisArg] The `this` binding of `callback`.\n     * @returns {Object} Returns the composed aggregate object.\n     * @example\n     *\n     * _.groupBy([4.2, 6.1, 6.4], function(num) { return Math.floor(num); });\n     * // => { '4': [4.2], '6': [6.1, 6.4] }\n     *\n     * _.groupBy([4.2, 6.1, 6.4], function(num) { return this.floor(num); }, Math);\n     * // => { '4': [4.2], '6': [6.1, 6.4] }\n     *\n     * // using \"_.pluck\" callback shorthand\n     * _.groupBy(['one', 'two', 'three'], 'length');\n     * // => { '3': ['one', 'two'], '5': ['three'] }\n     */\n    function groupBy(collection, callback, thisArg) {\n      var result = {};\n      callback = lodash.createCallback(callback, thisArg);\n\n      forEach(collection, function(value, key, collection) {\n        key = String(callback(value, key, collection));\n        (hasOwnProperty.call(result, key) ? result[key] : result[key] = []).push(value);\n      });\n      return result;\n    }\n\n    /**\n     * Invokes the method named by `methodName` on each element in the `collection`,\n     * returning an array of the results of each invoked method. Additional arguments\n     * will be passed to each invoked method. If `methodName` is a function, it will\n     * be invoked for, and `this` bound to, each element in the `collection`.\n     *\n     * @static\n     * @memberOf _\n     * @category Collections\n     * @param {Array|Object|String} collection The collection to iterate over.\n     * @param {Function|String} methodName The name of the method to invoke or\n     *  the function invoked per iteration.\n     * @param {Mixed} [arg1, arg2, ...] Arguments to invoke the method with.\n     * @returns {Array} Returns a new array of the results of each invoked method.\n     * @example\n     *\n     * _.invoke([[5, 1, 7], [3, 2, 1]], 'sort');\n     * // => [[1, 5, 7], [1, 2, 3]]\n     *\n     * _.invoke([123, 456], String.prototype.split, '');\n     * // => [['1', '2', '3'], ['4', '5', '6']]\n     */\n    function invoke(collection, methodName) {\n      var args = slice(arguments, 2),\n          index = -1,\n          isFunc = typeof methodName == 'function',\n          length = collection ? collection.length : 0,\n          result = Array(typeof length == 'number' ? length : 0);\n\n      forEach(collection, function(value) {\n        result[++index] = (isFunc ? methodName : value[methodName]).apply(value, args);\n      });\n      return result;\n    }\n\n    /**\n     * Creates an array of values by running each element in the `collection`\n     * through the `callback`. The `callback` is bound to `thisArg` and invoked with\n     * three arguments; (value, index|key, collection).\n     *\n     * If a property name is passed for `callback`, the created \"_.pluck\" style\n     * callback will return the property value of the given element.\n     *\n     * If an object is passed for `callback`, the created \"_.where\" style callback\n     * will return `true` for elements that have the properties of the given object,\n     * else `false`.\n     *\n     * @static\n     * @memberOf _\n     * @alias collect\n     * @category Collections\n     * @param {Array|Object|String} collection The collection to iterate over.\n     * @param {Function|Object|String} [callback=identity] The function called per\n     *  iteration. If a property name or object is passed, it will be used to create\n     *  a \"_.pluck\" or \"_.where\" style callback, respectively.\n     * @param {Mixed} [thisArg] The `this` binding of `callback`.\n     * @returns {Array} Returns a new array of the results of each `callback` execution.\n     * @example\n     *\n     * _.map([1, 2, 3], function(num) { return num * 3; });\n     * // => [3, 6, 9]\n     *\n     * _.map({ 'one': 1, 'two': 2, 'three': 3 }, function(num) { return num * 3; });\n     * // => [3, 6, 9] (order is not guaranteed)\n     *\n     * var stooges = [\n     *   { 'name': 'moe', 'age': 40 },\n     *   { 'name': 'larry', 'age': 50 }\n     * ];\n     *\n     * // using \"_.pluck\" callback shorthand\n     * _.map(stooges, 'name');\n     * // => ['moe', 'larry']\n     */\n    function map(collection, callback, thisArg) {\n      var index = -1,\n          length = collection ? collection.length : 0,\n          result = Array(typeof length == 'number' ? length : 0);\n\n      callback = lodash.createCallback(callback, thisArg);\n      if (isArray(collection)) {\n        while (++index < length) {\n          result[index] = callback(collection[index], index, collection);\n        }\n      } else {\n        each(collection, function(value, key, collection) {\n          result[++index] = callback(value, key, collection);\n        });\n      }\n      return result;\n    }\n\n    /**\n     * Retrieves the maximum value of an `array`. If `callback` is passed,\n     * it will be executed for each value in the `array` to generate the\n     * criterion by which the value is ranked. The `callback` is bound to\n     * `thisArg` and invoked with three arguments; (value, index, collection).\n     *\n     * If a property name is passed for `callback`, the created \"_.pluck\" style\n     * callback will return the property value of the given element.\n     *\n     * If an object is passed for `callback`, the created \"_.where\" style callback\n     * will return `true` for elements that have the properties of the given object,\n     * else `false`.\n     *\n     * @static\n     * @memberOf _\n     * @category Collections\n     * @param {Array|Object|String} collection The collection to iterate over.\n     * @param {Function|Object|String} [callback=identity] The function called per\n     *  iteration. If a property name or object is passed, it will be used to create\n     *  a \"_.pluck\" or \"_.where\" style callback, respectively.\n     * @param {Mixed} [thisArg] The `this` binding of `callback`.\n     * @returns {Mixed} Returns the maximum value.\n     * @example\n     *\n     * _.max([4, 2, 8, 6]);\n     * // => 8\n     *\n     * var stooges = [\n     *   { 'name': 'moe', 'age': 40 },\n     *   { 'name': 'larry', 'age': 50 }\n     * ];\n     *\n     * _.max(stooges, function(stooge) { return stooge.age; });\n     * // => { 'name': 'larry', 'age': 50 };\n     *\n     * // using \"_.pluck\" callback shorthand\n     * _.max(stooges, 'age');\n     * // => { 'name': 'larry', 'age': 50 };\n     */\n    function max(collection, callback, thisArg) {\n      var computed = -Infinity,\n          result = computed;\n\n      if (!callback && isArray(collection)) {\n        var index = -1,\n            length = collection.length;\n\n        while (++index < length) {\n          var value = collection[index];\n          if (value > result) {\n            result = value;\n          }\n        }\n      } else {\n        callback = (!callback && isString(collection))\n          ? charAtCallback\n          : lodash.createCallback(callback, thisArg);\n\n        each(collection, function(value, index, collection) {\n          var current = callback(value, index, collection);\n          if (current > computed) {\n            computed = current;\n            result = value;\n          }\n        });\n      }\n      return result;\n    }\n\n    /**\n     * Retrieves the minimum value of an `array`. If `callback` is passed,\n     * it will be executed for each value in the `array` to generate the\n     * criterion by which the value is ranked. The `callback` is bound to `thisArg`\n     * and invoked with three arguments; (value, index, collection).\n     *\n     * If a property name is passed for `callback`, the created \"_.pluck\" style\n     * callback will return the property value of the given element.\n     *\n     * If an object is passed for `callback`, the created \"_.where\" style callback\n     * will return `true` for elements that have the properties of the given object,\n     * else `false`.\n     *\n     * @static\n     * @memberOf _\n     * @category Collections\n     * @param {Array|Object|String} collection The collection to iterate over.\n     * @param {Function|Object|String} [callback=identity] The function called per\n     *  iteration. If a property name or object is passed, it will be used to create\n     *  a \"_.pluck\" or \"_.where\" style callback, respectively.\n     * @param {Mixed} [thisArg] The `this` binding of `callback`.\n     * @returns {Mixed} Returns the minimum value.\n     * @example\n     *\n     * _.min([4, 2, 8, 6]);\n     * // => 2\n     *\n     * var stooges = [\n     *   { 'name': 'moe', 'age': 40 },\n     *   { 'name': 'larry', 'age': 50 }\n     * ];\n     *\n     * _.min(stooges, function(stooge) { return stooge.age; });\n     * // => { 'name': 'moe', 'age': 40 };\n     *\n     * // using \"_.pluck\" callback shorthand\n     * _.min(stooges, 'age');\n     * // => { 'name': 'moe', 'age': 40 };\n     */\n    function min(collection, callback, thisArg) {\n      var computed = Infinity,\n          result = computed;\n\n      if (!callback && isArray(collection)) {\n        var index = -1,\n            length = collection.length;\n\n        while (++index < length) {\n          var value = collection[index];\n          if (value < result) {\n            result = value;\n          }\n        }\n      } else {\n        callback = (!callback && isString(collection))\n          ? charAtCallback\n          : lodash.createCallback(callback, thisArg);\n\n        each(collection, function(value, index, collection) {\n          var current = callback(value, index, collection);\n          if (current < computed) {\n            computed = current;\n            result = value;\n          }\n        });\n      }\n      return result;\n    }\n\n    /**\n     * Retrieves the value of a specified property from all elements in the `collection`.\n     *\n     * @static\n     * @memberOf _\n     * @type Function\n     * @category Collections\n     * @param {Array|Object|String} collection The collection to iterate over.\n     * @param {String} property The property to pluck.\n     * @returns {Array} Returns a new array of property values.\n     * @example\n     *\n     * var stooges = [\n     *   { 'name': 'moe', 'age': 40 },\n     *   { 'name': 'larry', 'age': 50 }\n     * ];\n     *\n     * _.pluck(stooges, 'name');\n     * // => ['moe', 'larry']\n     */\n    var pluck = map;\n\n    /**\n     * Reduces a `collection` to a value that is the accumulated result of running\n     * each element in the `collection` through the `callback`, where each successive\n     * `callback` execution consumes the return value of the previous execution.\n     * If `accumulator` is not passed, the first element of the `collection` will be\n     * used as the initial `accumulator` value. The `callback` is bound to `thisArg`\n     * and invoked with four arguments; (accumulator, value, index|key, collection).\n     *\n     * @static\n     * @memberOf _\n     * @alias foldl, inject\n     * @category Collections\n     * @param {Array|Object|String} collection The collection to iterate over.\n     * @param {Function} [callback=identity] The function called per iteration.\n     * @param {Mixed} [accumulator] Initial value of the accumulator.\n     * @param {Mixed} [thisArg] The `this` binding of `callback`.\n     * @returns {Mixed} Returns the accumulated value.\n     * @example\n     *\n     * var sum = _.reduce([1, 2, 3], function(sum, num) {\n     *   return sum + num;\n     * });\n     * // => 6\n     *\n     * var mapped = _.reduce({ 'a': 1, 'b': 2, 'c': 3 }, function(result, num, key) {\n     *   result[key] = num * 3;\n     *   return result;\n     * }, {});\n     * // => { 'a': 3, 'b': 6, 'c': 9 }\n     */\n    function reduce(collection, callback, accumulator, thisArg) {\n      var noaccum = arguments.length < 3;\n      callback = lodash.createCallback(callback, thisArg, 4);\n\n      if (isArray(collection)) {\n        var index = -1,\n            length = collection.length;\n\n        if (noaccum) {\n          accumulator = collection[++index];\n        }\n        while (++index < length) {\n          accumulator = callback(accumulator, collection[index], index, collection);\n        }\n      } else {\n        each(collection, function(value, index, collection) {\n          accumulator = noaccum\n            ? (noaccum = false, value)\n            : callback(accumulator, value, index, collection)\n        });\n      }\n      return accumulator;\n    }\n\n    /**\n     * This method is similar to `_.reduce`, except that it iterates over a\n     * `collection` from right to left.\n     *\n     * @static\n     * @memberOf _\n     * @alias foldr\n     * @category Collections\n     * @param {Array|Object|String} collection The collection to iterate over.\n     * @param {Function} [callback=identity] The function called per iteration.\n     * @param {Mixed} [accumulator] Initial value of the accumulator.\n     * @param {Mixed} [thisArg] The `this` binding of `callback`.\n     * @returns {Mixed} Returns the accumulated value.\n     * @example\n     *\n     * var list = [[0, 1], [2, 3], [4, 5]];\n     * var flat = _.reduceRight(list, function(a, b) { return a.concat(b); }, []);\n     * // => [4, 5, 2, 3, 0, 1]\n     */\n    function reduceRight(collection, callback, accumulator, thisArg) {\n      var iterable = collection,\n          length = collection ? collection.length : 0,\n          noaccum = arguments.length < 3;\n\n      if (typeof length != 'number') {\n        var props = keys(collection);\n        length = props.length;\n      } else if (support.unindexedChars && isString(collection)) {\n        iterable = collection.split('');\n      }\n      callback = lodash.createCallback(callback, thisArg, 4);\n      forEach(collection, function(value, index, collection) {\n        index = props ? props[--length] : --length;\n        accumulator = noaccum\n          ? (noaccum = false, iterable[index])\n          : callback(accumulator, iterable[index], index, collection);\n      });\n      return accumulator;\n    }\n\n    /**\n     * The opposite of `_.filter`, this method returns the elements of a\n     * `collection` that `callback` does **not** return truthy for.\n     *\n     * If a property name is passed for `callback`, the created \"_.pluck\" style\n     * callback will return the property value of the given element.\n     *\n     * If an object is passed for `callback`, the created \"_.where\" style callback\n     * will return `true` for elements that have the properties of the given object,\n     * else `false`.\n     *\n     * @static\n     * @memberOf _\n     * @category Collections\n     * @param {Array|Object|String} collection The collection to iterate over.\n     * @param {Function|Object|String} [callback=identity] The function called per\n     *  iteration. If a property name or object is passed, it will be used to create\n     *  a \"_.pluck\" or \"_.where\" style callback, respectively.\n     * @param {Mixed} [thisArg] The `this` binding of `callback`.\n     * @returns {Array} Returns a new array of elements that did **not** pass the\n     *  callback check.\n     * @example\n     *\n     * var odds = _.reject([1, 2, 3, 4, 5, 6], function(num) { return num % 2 == 0; });\n     * // => [1, 3, 5]\n     *\n     * var food = [\n     *   { 'name': 'apple',  'organic': false, 'type': 'fruit' },\n     *   { 'name': 'carrot', 'organic': true,  'type': 'vegetable' }\n     * ];\n     *\n     * // using \"_.pluck\" callback shorthand\n     * _.reject(food, 'organic');\n     * // => [{ 'name': 'apple', 'organic': false, 'type': 'fruit' }]\n     *\n     * // using \"_.where\" callback shorthand\n     * _.reject(food, { 'type': 'fruit' });\n     * // => [{ 'name': 'carrot', 'organic': true, 'type': 'vegetable' }]\n     */\n    function reject(collection, callback, thisArg) {\n      callback = lodash.createCallback(callback, thisArg);\n      return filter(collection, function(value, index, collection) {\n        return !callback(value, index, collection);\n      });\n    }\n\n    /**\n     * Creates an array of shuffled `array` values, using a version of the\n     * Fisher-Yates shuffle. See http://en.wikipedia.org/wiki/Fisher-Yates_shuffle.\n     *\n     * @static\n     * @memberOf _\n     * @category Collections\n     * @param {Array|Object|String} collection The collection to shuffle.\n     * @returns {Array} Returns a new shuffled collection.\n     * @example\n     *\n     * _.shuffle([1, 2, 3, 4, 5, 6]);\n     * // => [4, 1, 6, 3, 5, 2]\n     */\n    function shuffle(collection) {\n      var index = -1,\n          length = collection ? collection.length : 0,\n          result = Array(typeof length == 'number' ? length : 0);\n\n      forEach(collection, function(value) {\n        var rand = floor(nativeRandom() * (++index + 1));\n        result[index] = result[rand];\n        result[rand] = value;\n      });\n      return result;\n    }\n\n    /**\n     * Gets the size of the `collection` by returning `collection.length` for arrays\n     * and array-like objects or the number of own enumerable properties for objects.\n     *\n     * @static\n     * @memberOf _\n     * @category Collections\n     * @param {Array|Object|String} collection The collection to inspect.\n     * @returns {Number} Returns `collection.length` or number of own enumerable properties.\n     * @example\n     *\n     * _.size([1, 2]);\n     * // => 2\n     *\n     * _.size({ 'one': 1, 'two': 2, 'three': 3 });\n     * // => 3\n     *\n     * _.size('curly');\n     * // => 5\n     */\n    function size(collection) {\n      var length = collection ? collection.length : 0;\n      return typeof length == 'number' ? length : keys(collection).length;\n    }\n\n    /**\n     * Checks if the `callback` returns a truthy value for **any** element of a\n     * `collection`. The function returns as soon as it finds passing value, and\n     * does not iterate over the entire `collection`. The `callback` is bound to\n     * `thisArg` and invoked with three arguments; (value, index|key, collection).\n     *\n     * If a property name is passed for `callback`, the created \"_.pluck\" style\n     * callback will return the property value of the given element.\n     *\n     * If an object is passed for `callback`, the created \"_.where\" style callback\n     * will return `true` for elements that have the properties of the given object,\n     * else `false`.\n     *\n     * @static\n     * @memberOf _\n     * @alias any\n     * @category Collections\n     * @param {Array|Object|String} collection The collection to iterate over.\n     * @param {Function|Object|String} [callback=identity] The function called per\n     *  iteration. If a property name or object is passed, it will be used to create\n     *  a \"_.pluck\" or \"_.where\" style callback, respectively.\n     * @param {Mixed} [thisArg] The `this` binding of `callback`.\n     * @returns {Boolean} Returns `true` if any element passes the callback check,\n     *  else `false`.\n     * @example\n     *\n     * _.some([null, 0, 'yes', false], Boolean);\n     * // => true\n     *\n     * var food = [\n     *   { 'name': 'apple',  'organic': false, 'type': 'fruit' },\n     *   { 'name': 'carrot', 'organic': true,  'type': 'vegetable' }\n     * ];\n     *\n     * // using \"_.pluck\" callback shorthand\n     * _.some(food, 'organic');\n     * // => true\n     *\n     * // using \"_.where\" callback shorthand\n     * _.some(food, { 'type': 'meat' });\n     * // => false\n     */\n    function some(collection, callback, thisArg) {\n      var result;\n      callback = lodash.createCallback(callback, thisArg);\n\n      if (isArray(collection)) {\n        var index = -1,\n            length = collection.length;\n\n        while (++index < length) {\n          if ((result = callback(collection[index], index, collection))) {\n            break;\n          }\n        }\n      } else {\n        each(collection, function(value, index, collection) {\n          return !(result = callback(value, index, collection));\n        });\n      }\n      return !!result;\n    }\n\n    /**\n     * Creates an array of elements, sorted in ascending order by the results of\n     * running each element in the `collection` through the `callback`. This method\n     * performs a stable sort, that is, it will preserve the original sort order of\n     * equal elements. The `callback` is bound to `thisArg` and invoked with three\n     * arguments; (value, index|key, collection).\n     *\n     * If a property name is passed for `callback`, the created \"_.pluck\" style\n     * callback will return the property value of the given element.\n     *\n     * If an object is passed for `callback`, the created \"_.where\" style callback\n     * will return `true` for elements that have the properties of the given object,\n     * else `false`.\n     *\n     * @static\n     * @memberOf _\n     * @category Collections\n     * @param {Array|Object|String} collection The collection to iterate over.\n     * @param {Function|Object|String} [callback=identity] The function called per\n     *  iteration. If a property name or object is passed, it will be used to create\n     *  a \"_.pluck\" or \"_.where\" style callback, respectively.\n     * @param {Mixed} [thisArg] The `this` binding of `callback`.\n     * @returns {Array} Returns a new array of sorted elements.\n     * @example\n     *\n     * _.sortBy([1, 2, 3], function(num) { return Math.sin(num); });\n     * // => [3, 1, 2]\n     *\n     * _.sortBy([1, 2, 3], function(num) { return this.sin(num); }, Math);\n     * // => [3, 1, 2]\n     *\n     * // using \"_.pluck\" callback shorthand\n     * _.sortBy(['banana', 'strawberry', 'apple'], 'length');\n     * // => ['apple', 'banana', 'strawberry']\n     */\n    function sortBy(collection, callback, thisArg) {\n      var index = -1,\n          length = collection ? collection.length : 0,\n          result = Array(typeof length == 'number' ? length : 0);\n\n      callback = lodash.createCallback(callback, thisArg);\n      forEach(collection, function(value, key, collection) {\n        result[++index] = {\n          'criteria': callback(value, key, collection),\n          'index': index,\n          'value': value\n        };\n      });\n\n      length = result.length;\n      result.sort(compareAscending);\n      while (length--) {\n        result[length] = result[length].value;\n      }\n      return result;\n    }\n\n    /**\n     * Converts the `collection` to an array.\n     *\n     * @static\n     * @memberOf _\n     * @category Collections\n     * @param {Array|Object|String} collection The collection to convert.\n     * @returns {Array} Returns the new converted array.\n     * @example\n     *\n     * (function() { return _.toArray(arguments).slice(1); })(1, 2, 3, 4);\n     * // => [2, 3, 4]\n     */\n    function toArray(collection) {\n      if (collection && typeof collection.length == 'number') {\n        return (support.unindexedChars && isString(collection))\n          ? collection.split('')\n          : slice(collection);\n      }\n      return values(collection);\n    }\n\n    /**\n     * Examines each element in a `collection`, returning an array of all elements\n     * that have the given `properties`. When checking `properties`, this method\n     * performs a deep comparison between values to determine if they are equivalent\n     * to each other.\n     *\n     * @static\n     * @memberOf _\n     * @type Function\n     * @category Collections\n     * @param {Array|Object|String} collection The collection to iterate over.\n     * @param {Object} properties The object of property values to filter by.\n     * @returns {Array} Returns a new array of elements that have the given `properties`.\n     * @example\n     *\n     * var stooges = [\n     *   { 'name': 'moe', 'age': 40 },\n     *   { 'name': 'larry', 'age': 50 }\n     * ];\n     *\n     * _.where(stooges, { 'age': 40 });\n     * // => [{ 'name': 'moe', 'age': 40 }]\n     */\n    var where = filter;\n\n    /*--------------------------------------------------------------------------*/\n\n    /**\n     * Creates an array with all falsey values of `array` removed. The values\n     * `false`, `null`, `0`, `\"\"`, `undefined` and `NaN` are all falsey.\n     *\n     * @static\n     * @memberOf _\n     * @category Arrays\n     * @param {Array} array The array to compact.\n     * @returns {Array} Returns a new filtered array.\n     * @example\n     *\n     * _.compact([0, 1, false, 2, '', 3]);\n     * // => [1, 2, 3]\n     */\n    function compact(array) {\n      var index = -1,\n          length = array ? array.length : 0,\n          result = [];\n\n      while (++index < length) {\n        var value = array[index];\n        if (value) {\n          result.push(value);\n        }\n      }\n      return result;\n    }\n\n    /**\n     * Creates an array of `array` elements not present in the other arrays\n     * using strict equality for comparisons, i.e. `===`.\n     *\n     * @static\n     * @memberOf _\n     * @category Arrays\n     * @param {Array} array The array to process.\n     * @param {Array} [array1, array2, ...] Arrays to check.\n     * @returns {Array} Returns a new array of `array` elements not present in the\n     *  other arrays.\n     * @example\n     *\n     * _.difference([1, 2, 3, 4, 5], [5, 2, 10]);\n     * // => [1, 3, 4]\n     */\n    function difference(array) {\n      var index = -1,\n          length = array ? array.length : 0,\n          flattened = concat.apply(arrayRef, arguments),\n          contains = cachedContains(flattened, length, 100),\n          result = [];\n\n      while (++index < length) {\n        var value = array[index];\n        if (!contains(value)) {\n          result.push(value);\n        }\n      }\n      return result;\n    }\n\n    /**\n     * This method is similar to `_.find`, except that it returns the index of\n     * the element that passes the callback check, instead of the element itself.\n     *\n     * @static\n     * @memberOf _\n     * @category Arrays\n     * @param {Array|Object|String} collection The collection to iterate over.\n     * @param {Function|Object|String} [callback=identity] The function called per\n     *  iteration. If a property name or object is passed, it will be used to create\n     *  a \"_.pluck\" or \"_.where\" style callback, respectively.\n     * @param {Mixed} [thisArg] The `this` binding of `callback`.\n     * @returns {Mixed} Returns the index of the found element, else `-1`.\n     * @example\n     *\n     * _.findIndex(['apple', 'banana', 'beet'], function(food) { return /^b/.test(food); });\n     * // => 1\n     */\n    function findIndex(collection, callback, thisArg) {\n      var index = -1,\n          length = collection ? collection.length : 0;\n\n      callback = lodash.createCallback(callback, thisArg);\n      while (++index < length) {\n        if (callback(collection[index], index, collection)) {\n          return index;\n        }\n      }\n      return -1;\n    }\n\n    /**\n     * Gets the first element of the `array`. If a number `n` is passed, the first\n     * `n` elements of the `array` are returned. If a `callback` function is passed,\n     * elements at the beginning of the array are returned as long as the `callback`\n     * returns truthy. The `callback` is bound to `thisArg` and invoked with three\n     * arguments; (value, index, array).\n     *\n     * If a property name is passed for `callback`, the created \"_.pluck\" style\n     * callback will return the property value of the given element.\n     *\n     * If an object is passed for `callback`, the created \"_.where\" style callback\n     * will return `true` for elements that have the properties of the given object,\n     * else `false`.\n     *\n     * @static\n     * @memberOf _\n     * @alias head, take\n     * @category Arrays\n     * @param {Array} array The array to query.\n     * @param {Function|Object|Number|String} [callback|n] The function called\n     *  per element or the number of elements to return. If a property name or\n     *  object is passed, it will be used to create a \"_.pluck\" or \"_.where\"\n     *  style callback, respectively.\n     * @param {Mixed} [thisArg] The `this` binding of `callback`.\n     * @returns {Mixed} Returns the first element(s) of `array`.\n     * @example\n     *\n     * _.first([1, 2, 3]);\n     * // => 1\n     *\n     * _.first([1, 2, 3], 2);\n     * // => [1, 2]\n     *\n     * _.first([1, 2, 3], function(num) {\n     *   return num < 3;\n     * });\n     * // => [1, 2]\n     *\n     * var food = [\n     *   { 'name': 'banana', 'organic': true },\n     *   { 'name': 'beet',   'organic': false },\n     * ];\n     *\n     * // using \"_.pluck\" callback shorthand\n     * _.first(food, 'organic');\n     * // => [{ 'name': 'banana', 'organic': true }]\n     *\n     * var food = [\n     *   { 'name': 'apple',  'type': 'fruit' },\n     *   { 'name': 'banana', 'type': 'fruit' },\n     *   { 'name': 'beet',   'type': 'vegetable' }\n     * ];\n     *\n     * // using \"_.where\" callback shorthand\n     * _.first(food, { 'type': 'fruit' });\n     * // => [{ 'name': 'apple', 'type': 'fruit' }, { 'name': 'banana', 'type': 'fruit' }]\n     */\n    function first(array, callback, thisArg) {\n      if (array) {\n        var n = 0,\n            length = array.length;\n\n        if (typeof callback != 'number' && callback != null) {\n          var index = -1;\n          callback = lodash.createCallback(callback, thisArg);\n          while (++index < length && callback(array[index], index, array)) {\n            n++;\n          }\n        } else {\n          n = callback;\n          if (n == null || thisArg) {\n            return array[0];\n          }\n        }\n        return slice(array, 0, nativeMin(nativeMax(0, n), length));\n      }\n    }\n\n    /**\n     * Flattens a nested array (the nesting can be to any depth). If `isShallow`\n     * is truthy, `array` will only be flattened a single level. If `callback`\n     * is passed, each element of `array` is passed through a callback` before\n     * flattening. The `callback` is bound to `thisArg` and invoked with three\n     * arguments; (value, index, array).\n     *\n     * If a property name is passed for `callback`, the created \"_.pluck\" style\n     * callback will return the property value of the given element.\n     *\n     * If an object is passed for `callback`, the created \"_.where\" style callback\n     * will return `true` for elements that have the properties of the given object,\n     * else `false`.\n     *\n     * @static\n     * @memberOf _\n     * @category Arrays\n     * @param {Array} array The array to compact.\n     * @param {Boolean} [isShallow=false] A flag to indicate only flattening a single level.\n     * @param {Function|Object|String} [callback=identity] The function called per\n     *  iteration. If a property name or object is passed, it will be used to create\n     *  a \"_.pluck\" or \"_.where\" style callback, respectively.\n     * @param {Mixed} [thisArg] The `this` binding of `callback`.\n     * @returns {Array} Returns a new flattened array.\n     * @example\n     *\n     * _.flatten([1, [2], [3, [[4]]]]);\n     * // => [1, 2, 3, 4];\n     *\n     * _.flatten([1, [2], [3, [[4]]]], true);\n     * // => [1, 2, 3, [[4]]];\n     *\n     * var stooges = [\n     *   { 'name': 'curly', 'quotes': ['Oh, a wise guy, eh?', 'Poifect!'] },\n     *   { 'name': 'moe', 'quotes': ['Spread out!', 'You knucklehead!'] }\n     * ];\n     *\n     * // using \"_.pluck\" callback shorthand\n     * _.flatten(stooges, 'quotes');\n     * // => ['Oh, a wise guy, eh?', 'Poifect!', 'Spread out!', 'You knucklehead!']\n     */\n    function flatten(array, isShallow, callback, thisArg) {\n      var index = -1,\n          length = array ? array.length : 0,\n          result = [];\n\n      // juggle arguments\n      if (typeof isShallow != 'boolean' && isShallow != null) {\n        thisArg = callback;\n        callback = isShallow;\n        isShallow = false;\n      }\n      if (callback != null) {\n        callback = lodash.createCallback(callback, thisArg);\n      }\n      while (++index < length) {\n        var value = array[index];\n        if (callback) {\n          value = callback(value, index, array);\n        }\n        // recursively flatten arrays (susceptible to call stack limits)\n        if (isArray(value)) {\n          push.apply(result, isShallow ? value : flatten(value));\n        } else {\n          result.push(value);\n        }\n      }\n      return result;\n    }\n\n    /**\n     * Gets the index at which the first occurrence of `value` is found using\n     * strict equality for comparisons, i.e. `===`. If the `array` is already\n     * sorted, passing `true` for `fromIndex` will run a faster binary search.\n     *\n     * @static\n     * @memberOf _\n     * @category Arrays\n     * @param {Array} array The array to search.\n     * @param {Mixed} value The value to search for.\n     * @param {Boolean|Number} [fromIndex=0] The index to search from or `true` to\n     *  perform a binary search on a sorted `array`.\n     * @returns {Number} Returns the index of the matched value or `-1`.\n     * @example\n     *\n     * _.indexOf([1, 2, 3, 1, 2, 3], 2);\n     * // => 1\n     *\n     * _.indexOf([1, 2, 3, 1, 2, 3], 2, 3);\n     * // => 4\n     *\n     * _.indexOf([1, 1, 2, 2, 3, 3], 2, true);\n     * // => 2\n     */\n    function indexOf(array, value, fromIndex) {\n      var index = -1,\n          length = array ? array.length : 0;\n\n      if (typeof fromIndex == 'number') {\n        index = (fromIndex < 0 ? nativeMax(0, length + fromIndex) : fromIndex || 0) - 1;\n      } else if (fromIndex) {\n        index = sortedIndex(array, value);\n        return array[index] === value ? index : -1;\n      }\n      while (++index < length) {\n        if (array[index] === value) {\n          return index;\n        }\n      }\n      return -1;\n    }\n\n    /**\n     * Gets all but the last element of `array`. If a number `n` is passed, the\n     * last `n` elements are excluded from the result. If a `callback` function\n     * is passed, elements at the end of the array are excluded from the result\n     * as long as the `callback` returns truthy. The `callback` is bound to\n     * `thisArg` and invoked with three arguments; (value, index, array).\n     *\n     * If a property name is passed for `callback`, the created \"_.pluck\" style\n     * callback will return the property value of the given element.\n     *\n     * If an object is passed for `callback`, the created \"_.where\" style callback\n     * will return `true` for elements that have the properties of the given object,\n     * else `false`.\n     *\n     * @static\n     * @memberOf _\n     * @category Arrays\n     * @param {Array} array The array to query.\n     * @param {Function|Object|Number|String} [callback|n=1] The function called\n     *  per element or the number of elements to exclude. If a property name or\n     *  object is passed, it will be used to create a \"_.pluck\" or \"_.where\"\n     *  style callback, respectively.\n     * @param {Mixed} [thisArg] The `this` binding of `callback`.\n     * @returns {Array} Returns a slice of `array`.\n     * @example\n     *\n     * _.initial([1, 2, 3]);\n     * // => [1, 2]\n     *\n     * _.initial([1, 2, 3], 2);\n     * // => [1]\n     *\n     * _.initial([1, 2, 3], function(num) {\n     *   return num > 1;\n     * });\n     * // => [1]\n     *\n     * var food = [\n     *   { 'name': 'beet',   'organic': false },\n     *   { 'name': 'carrot', 'organic': true }\n     * ];\n     *\n     * // using \"_.pluck\" callback shorthand\n     * _.initial(food, 'organic');\n     * // => [{ 'name': 'beet',   'organic': false }]\n     *\n     * var food = [\n     *   { 'name': 'banana', 'type': 'fruit' },\n     *   { 'name': 'beet',   'type': 'vegetable' },\n     *   { 'name': 'carrot', 'type': 'vegetable' }\n     * ];\n     *\n     * // using \"_.where\" callback shorthand\n     * _.initial(food, { 'type': 'vegetable' });\n     * // => [{ 'name': 'banana', 'type': 'fruit' }]\n     */\n    function initial(array, callback, thisArg) {\n      if (!array) {\n        return [];\n      }\n      var n = 0,\n          length = array.length;\n\n      if (typeof callback != 'number' && callback != null) {\n        var index = length;\n        callback = lodash.createCallback(callback, thisArg);\n        while (index-- && callback(array[index], index, array)) {\n          n++;\n        }\n      } else {\n        n = (callback == null || thisArg) ? 1 : callback || n;\n      }\n      return slice(array, 0, nativeMin(nativeMax(0, length - n), length));\n    }\n\n    /**\n     * Computes the intersection of all the passed-in arrays using strict equality\n     * for comparisons, i.e. `===`.\n     *\n     * @static\n     * @memberOf _\n     * @category Arrays\n     * @param {Array} [array1, array2, ...] Arrays to process.\n     * @returns {Array} Returns a new array of unique elements that are present\n     *  in **all** of the arrays.\n     * @example\n     *\n     * _.intersection([1, 2, 3], [101, 2, 1, 10], [2, 1]);\n     * // => [1, 2]\n     */\n    function intersection(array) {\n      var args = arguments,\n          argsLength = args.length,\n          cache = { '0': {} },\n          index = -1,\n          length = array ? array.length : 0,\n          isLarge = length >= 100,\n          result = [],\n          seen = result;\n\n      outer:\n      while (++index < length) {\n        var value = array[index];\n        if (isLarge) {\n          var key = String(value);\n          var inited = hasOwnProperty.call(cache[0], key)\n            ? !(seen = cache[0][key])\n            : (seen = cache[0][key] = []);\n        }\n        if (inited || indexOf(seen, value) < 0) {\n          if (isLarge) {\n            seen.push(value);\n          }\n          var argsIndex = argsLength;\n          while (--argsIndex) {\n            if (!(cache[argsIndex] || (cache[argsIndex] = cachedContains(args[argsIndex], 0, 100)))(value)) {\n              continue outer;\n            }\n          }\n          result.push(value);\n        }\n      }\n      return result;\n    }\n\n    /**\n     * Gets the last element of the `array`. If a number `n` is passed, the\n     * last `n` elements of the `array` are returned. If a `callback` function\n     * is passed, elements at the end of the array are returned as long as the\n     * `callback` returns truthy. The `callback` is bound to `thisArg` and\n     * invoked with three arguments;(value, index, array).\n     *\n     *\n     * If a property name is passed for `callback`, the created \"_.pluck\" style\n     * callback will return the property value of the given element.\n     *\n     * If an object is passed for `callback`, the created \"_.where\" style callback\n     * will return `true` for elements that have the properties of the given object,\n     * else `false`.\n     *\n     * @static\n     * @memberOf _\n     * @category Arrays\n     * @param {Array} array The array to query.\n     * @param {Function|Object|Number|String} [callback|n] The function called\n     *  per element or the number of elements to return. If a property name or\n     *  object is passed, it will be used to create a \"_.pluck\" or \"_.where\"\n     *  style callback, respectively.\n     * @param {Mixed} [thisArg] The `this` binding of `callback`.\n     * @returns {Mixed} Returns the last element(s) of `array`.\n     * @example\n     *\n     * _.last([1, 2, 3]);\n     * // => 3\n     *\n     * _.last([1, 2, 3], 2);\n     * // => [2, 3]\n     *\n     * _.last([1, 2, 3], function(num) {\n     *   return num > 1;\n     * });\n     * // => [2, 3]\n     *\n     * var food = [\n     *   { 'name': 'beet',   'organic': false },\n     *   { 'name': 'carrot', 'organic': true }\n     * ];\n     *\n     * // using \"_.pluck\" callback shorthand\n     * _.last(food, 'organic');\n     * // => [{ 'name': 'carrot', 'organic': true }]\n     *\n     * var food = [\n     *   { 'name': 'banana', 'type': 'fruit' },\n     *   { 'name': 'beet',   'type': 'vegetable' },\n     *   { 'name': 'carrot', 'type': 'vegetable' }\n     * ];\n     *\n     * // using \"_.where\" callback shorthand\n     * _.last(food, { 'type': 'vegetable' });\n     * // => [{ 'name': 'beet', 'type': 'vegetable' }, { 'name': 'carrot', 'type': 'vegetable' }]\n     */\n    function last(array, callback, thisArg) {\n      if (array) {\n        var n = 0,\n            length = array.length;\n\n        if (typeof callback != 'number' && callback != null) {\n          var index = length;\n          callback = lodash.createCallback(callback, thisArg);\n          while (index-- && callback(array[index], index, array)) {\n            n++;\n          }\n        } else {\n          n = callback;\n          if (n == null || thisArg) {\n            return array[length - 1];\n          }\n        }\n        return slice(array, nativeMax(0, length - n));\n      }\n    }\n\n    /**\n     * Gets the index at which the last occurrence of `value` is found using strict\n     * equality for comparisons, i.e. `===`. If `fromIndex` is negative, it is used\n     * as the offset from the end of the collection.\n     *\n     * @static\n     * @memberOf _\n     * @category Arrays\n     * @param {Array} array The array to search.\n     * @param {Mixed} value The value to search for.\n     * @param {Number} [fromIndex=array.length-1] The index to search from.\n     * @returns {Number} Returns the index of the matched value or `-1`.\n     * @example\n     *\n     * _.lastIndexOf([1, 2, 3, 1, 2, 3], 2);\n     * // => 4\n     *\n     * _.lastIndexOf([1, 2, 3, 1, 2, 3], 2, 3);\n     * // => 1\n     */\n    function lastIndexOf(array, value, fromIndex) {\n      var index = array ? array.length : 0;\n      if (typeof fromIndex == 'number') {\n        index = (fromIndex < 0 ? nativeMax(0, index + fromIndex) : nativeMin(fromIndex, index - 1)) + 1;\n      }\n      while (index--) {\n        if (array[index] === value) {\n          return index;\n        }\n      }\n      return -1;\n    }\n\n    /**\n     * Creates an array of numbers (positive and/or negative) progressing from\n     * `start` up to but not including `end`.\n     *\n     * @static\n     * @memberOf _\n     * @category Arrays\n     * @param {Number} [start=0] The start of the range.\n     * @param {Number} end The end of the range.\n     * @param {Number} [step=1] The value to increment or decrement by.\n     * @returns {Array} Returns a new range array.\n     * @example\n     *\n     * _.range(10);\n     * // => [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]\n     *\n     * _.range(1, 11);\n     * // => [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]\n     *\n     * _.range(0, 30, 5);\n     * // => [0, 5, 10, 15, 20, 25]\n     *\n     * _.range(0, -10, -1);\n     * // => [0, -1, -2, -3, -4, -5, -6, -7, -8, -9]\n     *\n     * _.range(0);\n     * // => []\n     */\n    function range(start, end, step) {\n      start = +start || 0;\n      step = +step || 1;\n\n      if (end == null) {\n        end = start;\n        start = 0;\n      }\n      // use `Array(length)` so V8 will avoid the slower \"dictionary\" mode\n      // http://youtu.be/XAqIpGU8ZZk#t=17m25s\n      var index = -1,\n          length = nativeMax(0, ceil((end - start) / step)),\n          result = Array(length);\n\n      while (++index < length) {\n        result[index] = start;\n        start += step;\n      }\n      return result;\n    }\n\n    /**\n     * The opposite of `_.initial`, this method gets all but the first value of\n     * `array`. If a number `n` is passed, the first `n` values are excluded from\n     * the result. If a `callback` function is passed, elements at the beginning\n     * of the array are excluded from the result as long as the `callback` returns\n     * truthy. The `callback` is bound to `thisArg` and invoked with three\n     * arguments; (value, index, array).\n     *\n     * If a property name is passed for `callback`, the created \"_.pluck\" style\n     * callback will return the property value of the given element.\n     *\n     * If an object is passed for `callback`, the created \"_.where\" style callback\n     * will return `true` for elements that have the properties of the given object,\n     * else `false`.\n     *\n     * @static\n     * @memberOf _\n     * @alias drop, tail\n     * @category Arrays\n     * @param {Array} array The array to query.\n     * @param {Function|Object|Number|String} [callback|n=1] The function called\n     *  per element or the number of elements to exclude. If a property name or\n     *  object is passed, it will be used to create a \"_.pluck\" or \"_.where\"\n     *  style callback, respectively.\n     * @param {Mixed} [thisArg] The `this` binding of `callback`.\n     * @returns {Array} Returns a slice of `array`.\n     * @example\n     *\n     * _.rest([1, 2, 3]);\n     * // => [2, 3]\n     *\n     * _.rest([1, 2, 3], 2);\n     * // => [3]\n     *\n     * _.rest([1, 2, 3], function(num) {\n     *   return num < 3;\n     * });\n     * // => [3]\n     *\n     * var food = [\n     *   { 'name': 'banana', 'organic': true },\n     *   { 'name': 'beet',   'organic': false },\n     * ];\n     *\n     * // using \"_.pluck\" callback shorthand\n     * _.rest(food, 'organic');\n     * // => [{ 'name': 'beet', 'organic': false }]\n     *\n     * var food = [\n     *   { 'name': 'apple',  'type': 'fruit' },\n     *   { 'name': 'banana', 'type': 'fruit' },\n     *   { 'name': 'beet',   'type': 'vegetable' }\n     * ];\n     *\n     * // using \"_.where\" callback shorthand\n     * _.rest(food, { 'type': 'fruit' });\n     * // => [{ 'name': 'beet', 'type': 'vegetable' }]\n     */\n    function rest(array, callback, thisArg) {\n      if (typeof callback != 'number' && callback != null) {\n        var n = 0,\n            index = -1,\n            length = array ? array.length : 0;\n\n        callback = lodash.createCallback(callback, thisArg);\n        while (++index < length && callback(array[index], index, array)) {\n          n++;\n        }\n      } else {\n        n = (callback == null || thisArg) ? 1 : nativeMax(0, callback);\n      }\n      return slice(array, n);\n    }\n\n    /**\n     * Uses a binary search to determine the smallest index at which the `value`\n     * should be inserted into `array` in order to maintain the sort order of the\n     * sorted `array`. If `callback` is passed, it will be executed for `value` and\n     * each element in `array` to compute their sort ranking. The `callback` is\n     * bound to `thisArg` and invoked with one argument; (value).\n     *\n     * If a property name is passed for `callback`, the created \"_.pluck\" style\n     * callback will return the property value of the given element.\n     *\n     * If an object is passed for `callback`, the created \"_.where\" style callback\n     * will return `true` for elements that have the properties of the given object,\n     * else `false`.\n     *\n     * @static\n     * @memberOf _\n     * @category Arrays\n     * @param {Array} array The array to iterate over.\n     * @param {Mixed} value The value to evaluate.\n     * @param {Function|Object|String} [callback=identity] The function called per\n     *  iteration. If a property name or object is passed, it will be used to create\n     *  a \"_.pluck\" or \"_.where\" style callback, respectively.\n     * @param {Mixed} [thisArg] The `this` binding of `callback`.\n     * @returns {Number} Returns the index at which the value should be inserted\n     *  into `array`.\n     * @example\n     *\n     * _.sortedIndex([20, 30, 50], 40);\n     * // => 2\n     *\n     * // using \"_.pluck\" callback shorthand\n     * _.sortedIndex([{ 'x': 20 }, { 'x': 30 }, { 'x': 50 }], { 'x': 40 }, 'x');\n     * // => 2\n     *\n     * var dict = {\n     *   'wordToNumber': { 'twenty': 20, 'thirty': 30, 'fourty': 40, 'fifty': 50 }\n     * };\n     *\n     * _.sortedIndex(['twenty', 'thirty', 'fifty'], 'fourty', function(word) {\n     *   return dict.wordToNumber[word];\n     * });\n     * // => 2\n     *\n     * _.sortedIndex(['twenty', 'thirty', 'fifty'], 'fourty', function(word) {\n     *   return this.wordToNumber[word];\n     * }, dict);\n     * // => 2\n     */\n    function sortedIndex(array, value, callback, thisArg) {\n      var low = 0,\n          high = array ? array.length : low;\n\n      // explicitly reference `identity` for better inlining in Firefox\n      callback = callback ? lodash.createCallback(callback, thisArg, 1) : identity;\n      value = callback(value);\n\n      while (low < high) {\n        var mid = (low + high) >>> 1;\n        (callback(array[mid]) < value)\n          ? low = mid + 1\n          : high = mid;\n      }\n      return low;\n    }\n\n    /**\n     * Computes the union of the passed-in arrays using strict equality for\n     * comparisons, i.e. `===`.\n     *\n     * @static\n     * @memberOf _\n     * @category Arrays\n     * @param {Array} [array1, array2, ...] Arrays to process.\n     * @returns {Array} Returns a new array of unique values, in order, that are\n     *  present in one or more of the arrays.\n     * @example\n     *\n     * _.union([1, 2, 3], [101, 2, 1, 10], [2, 1]);\n     * // => [1, 2, 3, 101, 10]\n     */\n    function union() {\n      return uniq(concat.apply(arrayRef, arguments));\n    }\n\n    /**\n     * Creates a duplicate-value-free version of the `array` using strict equality\n     * for comparisons, i.e. `===`. If the `array` is already sorted, passing `true`\n     * for `isSorted` will run a faster algorithm. If `callback` is passed, each\n     * element of `array` is passed through a callback` before uniqueness is computed.\n     * The `callback` is bound to `thisArg` and invoked with three arguments; (value, index, array).\n     *\n     * If a property name is passed for `callback`, the created \"_.pluck\" style\n     * callback will return the property value of the given element.\n     *\n     * If an object is passed for `callback`, the created \"_.where\" style callback\n     * will return `true` for elements that have the properties of the given object,\n     * else `false`.\n     *\n     * @static\n     * @memberOf _\n     * @alias unique\n     * @category Arrays\n     * @param {Array} array The array to process.\n     * @param {Boolean} [isSorted=false] A flag to indicate that the `array` is already sorted.\n     * @param {Function|Object|String} [callback=identity] The function called per\n     *  iteration. If a property name or object is passed, it will be used to create\n     *  a \"_.pluck\" or \"_.where\" style callback, respectively.\n     * @param {Mixed} [thisArg] The `this` binding of `callback`.\n     * @returns {Array} Returns a duplicate-value-free array.\n     * @example\n     *\n     * _.uniq([1, 2, 1, 3, 1]);\n     * // => [1, 2, 3]\n     *\n     * _.uniq([1, 1, 2, 2, 3], true);\n     * // => [1, 2, 3]\n     *\n     * _.uniq([1, 2, 1.5, 3, 2.5], function(num) { return Math.floor(num); });\n     * // => [1, 2, 3]\n     *\n     * _.uniq([1, 2, 1.5, 3, 2.5], function(num) { return this.floor(num); }, Math);\n     * // => [1, 2, 3]\n     *\n     * // using \"_.pluck\" callback shorthand\n     * _.uniq([{ 'x': 1 }, { 'x': 2 }, { 'x': 1 }], 'x');\n     * // => [{ 'x': 1 }, { 'x': 2 }]\n     */\n    function uniq(array, isSorted, callback, thisArg) {\n      var index = -1,\n          length = array ? array.length : 0,\n          result = [],\n          seen = result;\n\n      // juggle arguments\n      if (typeof isSorted != 'boolean' && isSorted != null) {\n        thisArg = callback;\n        callback = isSorted;\n        isSorted = false;\n      }\n      // init value cache for large arrays\n      var isLarge = !isSorted && length >= 75;\n      if (isLarge) {\n        var cache = {};\n      }\n      if (callback != null) {\n        seen = [];\n        callback = lodash.createCallback(callback, thisArg);\n      }\n      while (++index < length) {\n        var value = array[index],\n            computed = callback ? callback(value, index, array) : value;\n\n        if (isLarge) {\n          var key = String(computed);\n          var inited = hasOwnProperty.call(cache, key)\n            ? !(seen = cache[key])\n            : (seen = cache[key] = []);\n        }\n        if (isSorted\n              ? !index || seen[seen.length - 1] !== computed\n              : inited || indexOf(seen, computed) < 0\n            ) {\n          if (callback || isLarge) {\n            seen.push(computed);\n          }\n          result.push(value);\n        }\n      }\n      return result;\n    }\n\n    /**\n     * Creates an array with all occurrences of the passed values removed using\n     * strict equality for comparisons, i.e. `===`.\n     *\n     * @static\n     * @memberOf _\n     * @category Arrays\n     * @param {Array} array The array to filter.\n     * @param {Mixed} [value1, value2, ...] Values to remove.\n     * @returns {Array} Returns a new filtered array.\n     * @example\n     *\n     * _.without([1, 2, 1, 0, 3, 1, 4], 0, 1);\n     * // => [2, 3, 4]\n     */\n    function without(array) {\n      var index = -1,\n          length = array ? array.length : 0,\n          contains = cachedContains(arguments, 1, 30),\n          result = [];\n\n      while (++index < length) {\n        var value = array[index];\n        if (!contains(value)) {\n          result.push(value);\n        }\n      }\n      return result;\n    }\n\n    /**\n     * Groups the elements of each array at their corresponding indexes. Useful for\n     * separate data sources that are coordinated through matching array indexes.\n     * For a matrix of nested arrays, `_.zip.apply(...)` can transpose the matrix\n     * in a similar fashion.\n     *\n     * @static\n     * @memberOf _\n     * @category Arrays\n     * @param {Array} [array1, array2, ...] Arrays to process.\n     * @returns {Array} Returns a new array of grouped elements.\n     * @example\n     *\n     * _.zip(['moe', 'larry'], [30, 40], [true, false]);\n     * // => [['moe', 30, true], ['larry', 40, false]]\n     */\n    function zip(array) {\n      var index = -1,\n          length = array ? max(pluck(arguments, 'length')) : 0,\n          result = Array(length);\n\n      while (++index < length) {\n        result[index] = pluck(arguments, index);\n      }\n      return result;\n    }\n\n    /**\n     * Creates an object composed from arrays of `keys` and `values`. Pass either\n     * a single two dimensional array, i.e. `[[key1, value1], [key2, value2]]`, or\n     * two arrays, one of `keys` and one of corresponding `values`.\n     *\n     * @static\n     * @memberOf _\n     * @alias object\n     * @category Arrays\n     * @param {Array} keys The array of keys.\n     * @param {Array} [values=[]] The array of values.\n     * @returns {Object} Returns an object composed of the given keys and\n     *  corresponding values.\n     * @example\n     *\n     * _.zipObject(['moe', 'larry'], [30, 40]);\n     * // => { 'moe': 30, 'larry': 40 }\n     */\n    function zipObject(keys, values) {\n      var index = -1,\n          length = keys ? keys.length : 0,\n          result = {};\n\n      while (++index < length) {\n        var key = keys[index];\n        if (values) {\n          result[key] = values[index];\n        } else {\n          result[key[0]] = key[1];\n        }\n      }\n      return result;\n    }\n\n    /*--------------------------------------------------------------------------*/\n\n    /**\n     * If `n` is greater than `0`, a function is created that is restricted to\n     * executing `func`, with the `this` binding and arguments of the created\n     * function, only after it is called `n` times. If `n` is less than `1`,\n     * `func` is executed immediately, without a `this` binding or additional\n     * arguments, and its result is returned.\n     *\n     * @static\n     * @memberOf _\n     * @category Functions\n     * @param {Number} n The number of times the function must be called before\n     * it is executed.\n     * @param {Function} func The function to restrict.\n     * @returns {Function} Returns the new restricted function.\n     * @example\n     *\n     * var renderNotes = _.after(notes.length, render);\n     * _.forEach(notes, function(note) {\n     *   note.asyncSave({ 'success': renderNotes });\n     * });\n     * // `renderNotes` is run once, after all notes have saved\n     */\n    function after(n, func) {\n      if (n < 1) {\n        return func();\n      }\n      return function() {\n        if (--n < 1) {\n          return func.apply(this, arguments);\n        }\n      };\n    }\n\n    /**\n     * Creates a function that, when called, invokes `func` with the `this`\n     * binding of `thisArg` and prepends any additional `bind` arguments to those\n     * passed to the bound function.\n     *\n     * @static\n     * @memberOf _\n     * @category Functions\n     * @param {Function} func The function to bind.\n     * @param {Mixed} [thisArg] The `this` binding of `func`.\n     * @param {Mixed} [arg1, arg2, ...] Arguments to be partially applied.\n     * @returns {Function} Returns the new bound function.\n     * @example\n     *\n     * var func = function(greeting) {\n     *   return greeting + ' ' + this.name;\n     * };\n     *\n     * func = _.bind(func, { 'name': 'moe' }, 'hi');\n     * func();\n     * // => 'hi moe'\n     */\n    function bind(func, thisArg) {\n      // use `Function#bind` if it exists and is fast\n      // (in V8 `Function#bind` is slower except when partially applied)\n      return support.fastBind || (nativeBind && arguments.length > 2)\n        ? nativeBind.call.apply(nativeBind, arguments)\n        : createBound(func, thisArg, slice(arguments, 2));\n    }\n\n    /**\n     * Binds methods on `object` to `object`, overwriting the existing method.\n     * Method names may be specified as individual arguments or as arrays of method\n     * names. If no method names are provided, all the function properties of `object`\n     * will be bound.\n     *\n     * @static\n     * @memberOf _\n     * @category Functions\n     * @param {Object} object The object to bind and assign the bound methods to.\n     * @param {String} [methodName1, methodName2, ...] Method names on the object to bind.\n     * @returns {Object} Returns `object`.\n     * @example\n     *\n     * var view = {\n     *  'label': 'docs',\n     *  'onClick': function() { alert('clicked ' + this.label); }\n     * };\n     *\n     * _.bindAll(view);\n     * jQuery('#docs').on('click', view.onClick);\n     * // => alerts 'clicked docs', when the button is clicked\n     */\n    function bindAll(object) {\n      var funcs = concat.apply(arrayRef, arguments),\n          index = funcs.length > 1 ? 0 : (funcs = functions(object), -1),\n          length = funcs.length;\n\n      while (++index < length) {\n        var key = funcs[index];\n        object[key] = bind(object[key], object);\n      }\n      return object;\n    }\n\n    /**\n     * Creates a function that, when called, invokes the method at `object[key]`\n     * and prepends any additional `bindKey` arguments to those passed to the bound\n     * function. This method differs from `_.bind` by allowing bound functions to\n     * reference methods that will be redefined or don't yet exist.\n     * See http://michaux.ca/articles/lazy-function-definition-pattern.\n     *\n     * @static\n     * @memberOf _\n     * @category Functions\n     * @param {Object} object The object the method belongs to.\n     * @param {String} key The key of the method.\n     * @param {Mixed} [arg1, arg2, ...] Arguments to be partially applied.\n     * @returns {Function} Returns the new bound function.\n     * @example\n     *\n     * var object = {\n     *   'name': 'moe',\n     *   'greet': function(greeting) {\n     *     return greeting + ' ' + this.name;\n     *   }\n     * };\n     *\n     * var func = _.bindKey(object, 'greet', 'hi');\n     * func();\n     * // => 'hi moe'\n     *\n     * object.greet = function(greeting) {\n     *   return greeting + ', ' + this.name + '!';\n     * };\n     *\n     * func();\n     * // => 'hi, moe!'\n     */\n    function bindKey(object, key) {\n      return createBound(object, key, slice(arguments, 2), indicatorObject);\n    }\n\n    /**\n     * Creates a function that is the composition of the passed functions,\n     * where each function consumes the return value of the function that follows.\n     * For example, composing the functions `f()`, `g()`, and `h()` produces `f(g(h()))`.\n     * Each function is executed with the `this` binding of the composed function.\n     *\n     * @static\n     * @memberOf _\n     * @category Functions\n     * @param {Function} [func1, func2, ...] Functions to compose.\n     * @returns {Function} Returns the new composed function.\n     * @example\n     *\n     * var greet = function(name) { return 'hi ' + name; };\n     * var exclaim = function(statement) { return statement + '!'; };\n     * var welcome = _.compose(exclaim, greet);\n     * welcome('moe');\n     * // => 'hi moe!'\n     */\n    function compose() {\n      var funcs = arguments;\n      return function() {\n        var args = arguments,\n            length = funcs.length;\n\n        while (length--) {\n          args = [funcs[length].apply(this, args)];\n        }\n        return args[0];\n      };\n    }\n\n    /**\n     * Produces a callback bound to an optional `thisArg`. If `func` is a property\n     * name, the created callback will return the property value for a given element.\n     * If `func` is an object, the created callback will return `true` for elements\n     * that contain the equivalent object properties, otherwise it will return `false`.\n     *\n     * Note: All Lo-Dash methods, that accept a `callback` argument, use `_.createCallback`.\n     *\n     * @static\n     * @memberOf _\n     * @category Functions\n     * @param {Mixed} [func=identity] The value to convert to a callback.\n     * @param {Mixed} [thisArg] The `this` binding of the created callback.\n     * @param {Number} [argCount=3] The number of arguments the callback accepts.\n     * @returns {Function} Returns a callback function.\n     * @example\n     *\n     * var stooges = [\n     *   { 'name': 'moe', 'age': 40 },\n     *   { 'name': 'larry', 'age': 50 }\n     * ];\n     *\n     * // wrap to create custom callback shorthands\n     * _.createCallback = _.wrap(_.createCallback, function(func, callback, thisArg) {\n     *   var match = /^(.+?)__([gl]t)(.+)$/.exec(callback);\n     *   return !match ? func(callback, thisArg) : function(object) {\n     *     return match[2] == 'gt' ? object[match[1]] > match[3] : object[match[1]] < match[3];\n     *   };\n     * });\n     *\n     * _.filter(stooges, 'age__gt45');\n     * // => [{ 'name': 'larry', 'age': 50 }]\n     *\n     * // create mixins with support for \"_.pluck\" and \"_.where\" callback shorthands\n     * _.mixin({\n     *   'toLookup': function(collection, callback, thisArg) {\n     *     callback = _.createCallback(callback, thisArg);\n     *     return _.reduce(collection, function(result, value, index, collection) {\n     *       return (result[callback(value, index, collection)] = value, result);\n     *     }, {});\n     *   }\n     * });\n     *\n     * _.toLookup(stooges, 'name');\n     * // => { 'moe': { 'name': 'moe', 'age': 40 }, 'larry': { 'name': 'larry', 'age': 50 } }\n     */\n    function createCallback(func, thisArg, argCount) {\n      if (func == null) {\n        return identity;\n      }\n      var type = typeof func;\n      if (type != 'function') {\n        if (type != 'object') {\n          return function(object) {\n            return object[func];\n          };\n        }\n        var props = keys(func);\n        return function(object) {\n          var length = props.length,\n              result = false;\n          while (length--) {\n            if (!(result = isEqual(object[props[length]], func[props[length]], indicatorObject))) {\n              break;\n            }\n          }\n          return result;\n        };\n      }\n      if (typeof thisArg != 'undefined') {\n        if (argCount === 1) {\n          return function(value) {\n            return func.call(thisArg, value);\n          };\n        }\n        if (argCount === 2) {\n          return function(a, b) {\n            return func.call(thisArg, a, b);\n          };\n        }\n        if (argCount === 4) {\n          return function(accumulator, value, index, collection) {\n            return func.call(thisArg, accumulator, value, index, collection);\n          };\n        }\n        return function(value, index, collection) {\n          return func.call(thisArg, value, index, collection);\n        };\n      }\n      return func;\n    }\n\n    /**\n     * Creates a function that will delay the execution of `func` until after\n     * `wait` milliseconds have elapsed since the last time it was invoked. Pass\n     * `true` for `immediate` to cause debounce to invoke `func` on the leading,\n     * instead of the trailing, edge of the `wait` timeout. Subsequent calls to\n     * the debounced function will return the result of the last `func` call.\n     *\n     * @static\n     * @memberOf _\n     * @category Functions\n     * @param {Function} func The function to debounce.\n     * @param {Number} wait The number of milliseconds to delay.\n     * @param {Boolean} immediate A flag to indicate execution is on the leading\n     *  edge of the timeout.\n     * @returns {Function} Returns the new debounced function.\n     * @example\n     *\n     * var lazyLayout = _.debounce(calculateLayout, 300);\n     * jQuery(window).on('resize', lazyLayout);\n     */\n    function debounce(func, wait, immediate) {\n      var args,\n          result,\n          thisArg,\n          timeoutId;\n\n      function delayed() {\n        timeoutId = null;\n        if (!immediate) {\n          result = func.apply(thisArg, args);\n        }\n      }\n      return function() {\n        var isImmediate = immediate && !timeoutId;\n        args = arguments;\n        thisArg = this;\n\n        clearTimeout(timeoutId);\n        timeoutId = setTimeout(delayed, wait);\n\n        if (isImmediate) {\n          result = func.apply(thisArg, args);\n        }\n        return result;\n      };\n    }\n\n    /**\n     * Defers executing the `func` function until the current call stack has cleared.\n     * Additional arguments will be passed to `func` when it is invoked.\n     *\n     * @static\n     * @memberOf _\n     * @category Functions\n     * @param {Function} func The function to defer.\n     * @param {Mixed} [arg1, arg2, ...] Arguments to invoke the function with.\n     * @returns {Number} Returns the timer id.\n     * @example\n     *\n     * _.defer(function() { alert('deferred'); });\n     * // returns from the function before `alert` is called\n     */\n    function defer(func) {\n      var args = slice(arguments, 1);\n      return setTimeout(function() { func.apply(undefined, args); }, 1);\n    }\n    // use `setImmediate` if it's available in Node.js\n    if (isV8 && freeModule && typeof setImmediate == 'function') {\n      defer = bind(setImmediate, context);\n    }\n\n    /**\n     * Executes the `func` function after `wait` milliseconds. Additional arguments\n     * will be passed to `func` when it is invoked.\n     *\n     * @static\n     * @memberOf _\n     * @category Functions\n     * @param {Function} func The function to delay.\n     * @param {Number} wait The number of milliseconds to delay execution.\n     * @param {Mixed} [arg1, arg2, ...] Arguments to invoke the function with.\n     * @returns {Number} Returns the timer id.\n     * @example\n     *\n     * var log = _.bind(console.log, console);\n     * _.delay(log, 1000, 'logged later');\n     * // => 'logged later' (Appears after one second.)\n     */\n    function delay(func, wait) {\n      var args = slice(arguments, 2);\n      return setTimeout(function() { func.apply(undefined, args); }, wait);\n    }\n\n    /**\n     * Creates a function that memoizes the result of `func`. If `resolver` is\n     * passed, it will be used to determine the cache key for storing the result\n     * based on the arguments passed to the memoized function. By default, the first\n     * argument passed to the memoized function is used as the cache key. The `func`\n     * is executed with the `this` binding of the memoized function.\n     *\n     * @static\n     * @memberOf _\n     * @category Functions\n     * @param {Function} func The function to have its output memoized.\n     * @param {Function} [resolver] A function used to resolve the cache key.\n     * @returns {Function} Returns the new memoizing function.\n     * @example\n     *\n     * var fibonacci = _.memoize(function(n) {\n     *   return n < 2 ? n : fibonacci(n - 1) + fibonacci(n - 2);\n     * });\n     */\n    function memoize(func, resolver) {\n      var cache = {};\n      return function() {\n        var key = String(resolver ? resolver.apply(this, arguments) : arguments[0]);\n        return hasOwnProperty.call(cache, key)\n          ? cache[key]\n          : (cache[key] = func.apply(this, arguments));\n      };\n    }\n\n    /**\n     * Creates a function that is restricted to execute `func` once. Repeat calls to\n     * the function will return the value of the first call. The `func` is executed\n     * with the `this` binding of the created function.\n     *\n     * @static\n     * @memberOf _\n     * @category Functions\n     * @param {Function} func The function to restrict.\n     * @returns {Function} Returns the new restricted function.\n     * @example\n     *\n     * var initialize = _.once(createApplication);\n     * initialize();\n     * initialize();\n     * // `initialize` executes `createApplication` once\n     */\n    function once(func) {\n      var ran,\n          result;\n\n      return function() {\n        if (ran) {\n          return result;\n        }\n        ran = true;\n        result = func.apply(this, arguments);\n\n        // clear the `func` variable so the function may be garbage collected\n        func = null;\n        return result;\n      };\n    }\n\n    /**\n     * Creates a function that, when called, invokes `func` with any additional\n     * `partial` arguments prepended to those passed to the new function. This\n     * method is similar to `_.bind`, except it does **not** alter the `this` binding.\n     *\n     * @static\n     * @memberOf _\n     * @category Functions\n     * @param {Function} func The function to partially apply arguments to.\n     * @param {Mixed} [arg1, arg2, ...] Arguments to be partially applied.\n     * @returns {Function} Returns the new partially applied function.\n     * @example\n     *\n     * var greet = function(greeting, name) { return greeting + ' ' + name; };\n     * var hi = _.partial(greet, 'hi');\n     * hi('moe');\n     * // => 'hi moe'\n     */\n    function partial(func) {\n      return createBound(func, slice(arguments, 1));\n    }\n\n    /**\n     * This method is similar to `_.partial`, except that `partial` arguments are\n     * appended to those passed to the new function.\n     *\n     * @static\n     * @memberOf _\n     * @category Functions\n     * @param {Function} func The function to partially apply arguments to.\n     * @param {Mixed} [arg1, arg2, ...] Arguments to be partially applied.\n     * @returns {Function} Returns the new partially applied function.\n     * @example\n     *\n     * var defaultsDeep = _.partialRight(_.merge, _.defaults);\n     *\n     * var options = {\n     *   'variable': 'data',\n     *   'imports': { 'jq': $ }\n     * };\n     *\n     * defaultsDeep(options, _.templateSettings);\n     *\n     * options.variable\n     * // => 'data'\n     *\n     * options.imports\n     * // => { '_': _, 'jq': $ }\n     */\n    function partialRight(func) {\n      return createBound(func, slice(arguments, 1), null, indicatorObject);\n    }\n\n    /**\n     * Creates a function that, when executed, will only call the `func`\n     * function at most once per every `wait` milliseconds. If the throttled\n     * function is invoked more than once during the `wait` timeout, `func` will\n     * also be called on the trailing edge of the timeout. Subsequent calls to the\n     * throttled function will return the result of the last `func` call.\n     *\n     * @static\n     * @memberOf _\n     * @category Functions\n     * @param {Function} func The function to throttle.\n     * @param {Number} wait The number of milliseconds to throttle executions to.\n     * @returns {Function} Returns the new throttled function.\n     * @example\n     *\n     * var throttled = _.throttle(updatePosition, 100);\n     * jQuery(window).on('scroll', throttled);\n     */\n    function throttle(func, wait) {\n      var args,\n          result,\n          thisArg,\n          timeoutId,\n          lastCalled = 0;\n\n      function trailingCall() {\n        lastCalled = new Date;\n        timeoutId = null;\n        result = func.apply(thisArg, args);\n      }\n      return function() {\n        var now = new Date,\n            remaining = wait - (now - lastCalled);\n\n        args = arguments;\n        thisArg = this;\n\n        if (remaining <= 0) {\n          clearTimeout(timeoutId);\n          timeoutId = null;\n          lastCalled = now;\n          result = func.apply(thisArg, args);\n        }\n        else if (!timeoutId) {\n          timeoutId = setTimeout(trailingCall, remaining);\n        }\n        return result;\n      };\n    }\n\n    /**\n     * Creates a function that passes `value` to the `wrapper` function as its\n     * first argument. Additional arguments passed to the function are appended\n     * to those passed to the `wrapper` function. The `wrapper` is executed with\n     * the `this` binding of the created function.\n     *\n     * @static\n     * @memberOf _\n     * @category Functions\n     * @param {Mixed} value The value to wrap.\n     * @param {Function} wrapper The wrapper function.\n     * @returns {Function} Returns the new function.\n     * @example\n     *\n     * var hello = function(name) { return 'hello ' + name; };\n     * hello = _.wrap(hello, function(func) {\n     *   return 'before, ' + func('moe') + ', after';\n     * });\n     * hello();\n     * // => 'before, hello moe, after'\n     */\n    function wrap(value, wrapper) {\n      return function() {\n        var args = [value];\n        push.apply(args, arguments);\n        return wrapper.apply(this, args);\n      };\n    }\n\n    /*--------------------------------------------------------------------------*/\n\n    /**\n     * Converts the characters `&`, `<`, `>`, `\"`, and `'` in `string` to their\n     * corresponding HTML entities.\n     *\n     * @static\n     * @memberOf _\n     * @category Utilities\n     * @param {String} string The string to escape.\n     * @returns {String} Returns the escaped string.\n     * @example\n     *\n     * _.escape('Moe, Larry & Curly');\n     * // => 'Moe, Larry &amp; Curly'\n     */\n    function escape(string) {\n      return string == null ? '' : String(string).replace(reUnescapedHtml, escapeHtmlChar);\n    }\n\n    /**\n     * This function returns the first argument passed to it.\n     *\n     * @static\n     * @memberOf _\n     * @category Utilities\n     * @param {Mixed} value Any value.\n     * @returns {Mixed} Returns `value`.\n     * @example\n     *\n     * var moe = { 'name': 'moe' };\n     * moe === _.identity(moe);\n     * // => true\n     */\n    function identity(value) {\n      return value;\n    }\n\n    /**\n     * Adds functions properties of `object` to the `lodash` function and chainable\n     * wrapper.\n     *\n     * @static\n     * @memberOf _\n     * @category Utilities\n     * @param {Object} object The object of function properties to add to `lodash`.\n     * @example\n     *\n     * _.mixin({\n     *   'capitalize': function(string) {\n     *     return string.charAt(0).toUpperCase() + string.slice(1).toLowerCase();\n     *   }\n     * });\n     *\n     * _.capitalize('moe');\n     * // => 'Moe'\n     *\n     * _('moe').capitalize();\n     * // => 'Moe'\n     */\n    function mixin(object) {\n      forEach(functions(object), function(methodName) {\n        var func = lodash[methodName] = object[methodName];\n\n        lodash.prototype[methodName] = function() {\n          var value = this.__wrapped__,\n              args = [value];\n\n          push.apply(args, arguments);\n          var result = func.apply(lodash, args);\n          return (value && typeof value == 'object' && value == result)\n            ? this\n            : new lodashWrapper(result);\n        };\n      });\n    }\n\n    /**\n     * Reverts the '_' variable to its previous value and returns a reference to\n     * the `lodash` function.\n     *\n     * @static\n     * @memberOf _\n     * @category Utilities\n     * @returns {Function} Returns the `lodash` function.\n     * @example\n     *\n     * var lodash = _.noConflict();\n     */\n    function noConflict() {\n      context._ = oldDash;\n      return this;\n    }\n\n    /**\n     * Converts the given `value` into an integer of the specified `radix`.\n     *\n     * Note: This method avoids differences in native ES3 and ES5 `parseInt`\n     * implementations. See http://es5.github.com/#E.\n     *\n     * @static\n     * @memberOf _\n     * @category Utilities\n     * @param {Mixed} value The value to parse.\n     * @returns {Number} Returns the new integer value.\n     * @example\n     *\n     * _.parseInt('08');\n     * // => 8\n     */\n    var parseInt = nativeParseInt('08') == 8 ? nativeParseInt : function(value, radix) {\n      // Firefox and Opera still follow the ES3 specified implementation of `parseInt`\n      return nativeParseInt(isString(value) ? value.replace(reLeadingZeros, '') : value, radix || 0);\n    };\n\n    /**\n     * Produces a random number between `min` and `max` (inclusive). If only one\n     * argument is passed, a number between `0` and the given number will be returned.\n     *\n     * @static\n     * @memberOf _\n     * @category Utilities\n     * @param {Number} [min=0] The minimum possible value.\n     * @param {Number} [max=1] The maximum possible value.\n     * @returns {Number} Returns a random number.\n     * @example\n     *\n     * _.random(0, 5);\n     * // => a number between 0 and 5\n     *\n     * _.random(5);\n     * // => also a number between 0 and 5\n     */\n    function random(min, max) {\n      if (min == null && max == null) {\n        max = 1;\n      }\n      min = +min || 0;\n      if (max == null) {\n        max = min;\n        min = 0;\n      }\n      return min + floor(nativeRandom() * ((+max || 0) - min + 1));\n    }\n\n    /**\n     * Resolves the value of `property` on `object`. If `property` is a function,\n     * it will be invoked with the `this` binding of `object` and its result returned,\n     * else the property value is returned. If `object` is falsey, then `undefined`\n     * is returned.\n     *\n     * @static\n     * @memberOf _\n     * @category Utilities\n     * @param {Object} object The object to inspect.\n     * @param {String} property The property to get the value of.\n     * @returns {Mixed} Returns the resolved value.\n     * @example\n     *\n     * var object = {\n     *   'cheese': 'crumpets',\n     *   'stuff': function() {\n     *     return 'nonsense';\n     *   }\n     * };\n     *\n     * _.result(object, 'cheese');\n     * // => 'crumpets'\n     *\n     * _.result(object, 'stuff');\n     * // => 'nonsense'\n     */\n    function result(object, property) {\n      var value = object ? object[property] : undefined;\n      return isFunction(value) ? object[property]() : value;\n    }\n\n    /**\n     * A micro-templating method that handles arbitrary delimiters, preserves\n     * whitespace, and correctly escapes quotes within interpolated code.\n     *\n     * Note: In the development build, `_.template` utilizes sourceURLs for easier\n     * debugging. See http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/#toc-sourceurl\n     *\n     * Note: Lo-Dash may be used in Chrome extensions by either creating a `lodash csp`\n     * build and using precompiled templates, or loading Lo-Dash in a sandbox.\n     *\n     * For more information on precompiling templates see:\n     * http://lodash.com/#custom-builds\n     *\n     * For more information on Chrome extension sandboxes see:\n     * http://developer.chrome.com/stable/extensions/sandboxingEval.html\n     *\n     * @static\n     * @memberOf _\n     * @category Utilities\n     * @param {String} text The template text.\n     * @param {Obect} data The data object used to populate the text.\n     * @param {Object} options The options object.\n     *  escape - The \"escape\" delimiter regexp.\n     *  evaluate - The \"evaluate\" delimiter regexp.\n     *  interpolate - The \"interpolate\" delimiter regexp.\n     *  sourceURL - The sourceURL of the template's compiled source.\n     *  variable - The data object variable name.\n     * @returns {Function|String} Returns a compiled function when no `data` object\n     *  is given, else it returns the interpolated text.\n     * @example\n     *\n     * // using a compiled template\n     * var compiled = _.template('hello <%= name %>');\n     * compiled({ 'name': 'moe' });\n     * // => 'hello moe'\n     *\n     * var list = '<% _.forEach(people, function(name) { %><li><%= name %></li><% }); %>';\n     * _.template(list, { 'people': ['moe', 'larry'] });\n     * // => '<li>moe</li><li>larry</li>'\n     *\n     * // using the \"escape\" delimiter to escape HTML in data property values\n     * _.template('<b><%- value %></b>', { 'value': '<script>' });\n     * // => '<b>&lt;script&gt;</b>'\n     *\n     * // using the ES6 delimiter as an alternative to the default \"interpolate\" delimiter\n     * _.template('hello ${ name }', { 'name': 'curly' });\n     * // => 'hello curly'\n     *\n     * // using the internal `print` function in \"evaluate\" delimiters\n     * _.template('<% print(\"hello \" + epithet); %>!', { 'epithet': 'stooge' });\n     * // => 'hello stooge!'\n     *\n     * // using custom template delimiters\n     * _.templateSettings = {\n     *   'interpolate': /{{([\\s\\S]+?)}}/g\n     * };\n     *\n     * _.template('hello {{ name }}!', { 'name': 'mustache' });\n     * // => 'hello mustache!'\n     *\n     * // using the `sourceURL` option to specify a custom sourceURL for the template\n     * var compiled = _.template('hello <%= name %>', null, { 'sourceURL': '/basic/greeting.jst' });\n     * compiled(data);\n     * // => find the source of \"greeting.jst\" under the Sources tab or Resources panel of the web inspector\n     *\n     * // using the `variable` option to ensure a with-statement isn't used in the compiled template\n     * var compiled = _.template('hi <%= data.name %>!', null, { 'variable': 'data' });\n     * compiled.source;\n     * // => function(data) {\n     *   var __t, __p = '', __e = _.escape;\n     *   __p += 'hi ' + ((__t = ( data.name )) == null ? '' : __t) + '!';\n     *   return __p;\n     * }\n     *\n     * // using the `source` property to inline compiled templates for meaningful\n     * // line numbers in error messages and a stack trace\n     * fs.writeFileSync(path.join(cwd, 'jst.js'), '\\\n     *   var JST = {\\\n     *     \"main\": ' + _.template(mainText).source + '\\\n     *   };\\\n     * ');\n     */\n    function template(text, data, options) {\n      // based on John Resig's `tmpl` implementation\n      // http://ejohn.org/blog/javascript-micro-templating/\n      // and Laura Doktorova's doT.js\n      // https://github.com/olado/doT\n      var settings = lodash.templateSettings;\n      text || (text = '');\n\n      // avoid missing dependencies when `iteratorTemplate` is not defined\n      options = iteratorTemplate ? defaults({}, options, settings) : settings;\n\n      var imports = iteratorTemplate && defaults({}, options.imports, settings.imports),\n          importsKeys = iteratorTemplate ? keys(imports) : ['_'],\n          importsValues = iteratorTemplate ? values(imports) : [lodash];\n\n      var isEvaluating,\n          index = 0,\n          interpolate = options.interpolate || reNoMatch,\n          source = \"__p += '\";\n\n      // compile the regexp to match each delimiter\n      var reDelimiters = RegExp(\n        (options.escape || reNoMatch).source + '|' +\n        interpolate.source + '|' +\n        (interpolate === reInterpolate ? reEsTemplate : reNoMatch).source + '|' +\n        (options.evaluate || reNoMatch).source + '|$'\n      , 'g');\n\n      text.replace(reDelimiters, function(match, escapeValue, interpolateValue, esTemplateValue, evaluateValue, offset) {\n        interpolateValue || (interpolateValue = esTemplateValue);\n\n        // escape characters that cannot be included in string literals\n        source += text.slice(index, offset).replace(reUnescapedString, escapeStringChar);\n\n        // replace delimiters with snippets\n        if (escapeValue) {\n          source += \"' +\\n__e(\" + escapeValue + \") +\\n'\";\n        }\n        if (evaluateValue) {\n          isEvaluating = true;\n          source += \"';\\n\" + evaluateValue + \";\\n__p += '\";\n        }\n        if (interpolateValue) {\n          source += \"' +\\n((__t = (\" + interpolateValue + \")) == null ? '' : __t) +\\n'\";\n        }\n        index = offset + match.length;\n\n        // the JS engine embedded in Adobe products requires returning the `match`\n        // string in order to produce the correct `offset` value\n        return match;\n      });\n\n      source += \"';\\n\";\n\n      // if `variable` is not specified, wrap a with-statement around the generated\n      // code to add the data object to the top of the scope chain\n      var variable = options.variable,\n          hasVariable = variable;\n\n      if (!hasVariable) {\n        variable = 'obj';\n        source = 'with (' + variable + ') {\\n' + source + '\\n}\\n';\n      }\n      // cleanup code by stripping empty strings\n      source = (isEvaluating ? source.replace(reEmptyStringLeading, '') : source)\n        .replace(reEmptyStringMiddle, '$1')\n        .replace(reEmptyStringTrailing, '$1;');\n\n      // frame code as the function body\n      source = 'function(' + variable + ') {\\n' +\n        (hasVariable ? '' : variable + ' || (' + variable + ' = {});\\n') +\n        \"var __t, __p = '', __e = _.escape\" +\n        (isEvaluating\n          ? ', __j = Array.prototype.join;\\n' +\n            \"function print() { __p += __j.call(arguments, '') }\\n\"\n          : ';\\n'\n        ) +\n        source +\n        'return __p\\n}';\n\n      // Use a sourceURL for easier debugging and wrap in a multi-line comment to\n      // avoid issues with Narwhal, IE conditional compilation, and the JS engine\n      // embedded in Adobe products.\n      // http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/#toc-sourceurl\n      var sourceURL = '\\n/*\\n//@ sourceURL=' + (options.sourceURL || '/lodash/template/source[' + (templateCounter++) + ']') + '\\n*/';\n\n      try {\n        var result = Function(importsKeys, 'return ' + source + sourceURL).apply(undefined, importsValues);\n      } catch(e) {\n        e.source = source;\n        throw e;\n      }\n      if (data) {\n        return result(data);\n      }\n      // provide the compiled function's source via its `toString` method, in\n      // supported environments, or the `source` property as a convenience for\n      // inlining compiled templates during the build process\n      result.source = source;\n      return result;\n    }\n\n    /**\n     * Executes the `callback` function `n` times, returning an array of the results\n     * of each `callback` execution. The `callback` is bound to `thisArg` and invoked\n     * with one argument; (index).\n     *\n     * @static\n     * @memberOf _\n     * @category Utilities\n     * @param {Number} n The number of times to execute the callback.\n     * @param {Function} callback The function called per iteration.\n     * @param {Mixed} [thisArg] The `this` binding of `callback`.\n     * @returns {Array} Returns a new array of the results of each `callback` execution.\n     * @example\n     *\n     * var diceRolls = _.times(3, _.partial(_.random, 1, 6));\n     * // => [3, 6, 4]\n     *\n     * _.times(3, function(n) { mage.castSpell(n); });\n     * // => calls `mage.castSpell(n)` three times, passing `n` of `0`, `1`, and `2` respectively\n     *\n     * _.times(3, function(n) { this.cast(n); }, mage);\n     * // => also calls `mage.castSpell(n)` three times\n     */\n    function times(n, callback, thisArg) {\n      n = (n = +n) > -1 ? n : 0;\n      var index = -1,\n          result = Array(n);\n\n      callback = lodash.createCallback(callback, thisArg, 1);\n      while (++index < n) {\n        result[index] = callback(index);\n      }\n      return result;\n    }\n\n    /**\n     * The opposite of `_.escape`, this method converts the HTML entities\n     * `&amp;`, `&lt;`, `&gt;`, `&quot;`, and `&#39;` in `string` to their\n     * corresponding characters.\n     *\n     * @static\n     * @memberOf _\n     * @category Utilities\n     * @param {String} string The string to unescape.\n     * @returns {String} Returns the unescaped string.\n     * @example\n     *\n     * _.unescape('Moe, Larry &amp; Curly');\n     * // => 'Moe, Larry & Curly'\n     */\n    function unescape(string) {\n      return string == null ? '' : String(string).replace(reEscapedHtml, unescapeHtmlChar);\n    }\n\n    /**\n     * Generates a unique ID. If `prefix` is passed, the ID will be appended to it.\n     *\n     * @static\n     * @memberOf _\n     * @category Utilities\n     * @param {String} [prefix] The value to prefix the ID with.\n     * @returns {String} Returns the unique ID.\n     * @example\n     *\n     * _.uniqueId('contact_');\n     * // => 'contact_104'\n     *\n     * _.uniqueId();\n     * // => '105'\n     */\n    function uniqueId(prefix) {\n      var id = ++idCounter;\n      return String(prefix == null ? '' : prefix) + id;\n    }\n\n    /*--------------------------------------------------------------------------*/\n\n    /**\n     * Invokes `interceptor` with the `value` as the first argument, and then\n     * returns `value`. The purpose of this method is to \"tap into\" a method chain,\n     * in order to perform operations on intermediate results within the chain.\n     *\n     * @static\n     * @memberOf _\n     * @category Chaining\n     * @param {Mixed} value The value to pass to `interceptor`.\n     * @param {Function} interceptor The function to invoke.\n     * @returns {Mixed} Returns `value`.\n     * @example\n     *\n     * _([1, 2, 3, 4])\n     *  .filter(function(num) { return num % 2 == 0; })\n     *  .tap(alert)\n     *  .map(function(num) { return num * num; })\n     *  .value();\n     * // => // [2, 4] (alerted)\n     * // => [4, 16]\n     */\n    function tap(value, interceptor) {\n      interceptor(value);\n      return value;\n    }\n\n    /**\n     * Produces the `toString` result of the wrapped value.\n     *\n     * @name toString\n     * @memberOf _\n     * @category Chaining\n     * @returns {String} Returns the string result.\n     * @example\n     *\n     * _([1, 2, 3]).toString();\n     * // => '1,2,3'\n     */\n    function wrapperToString() {\n      return String(this.__wrapped__);\n    }\n\n    /**\n     * Extracts the wrapped value.\n     *\n     * @name valueOf\n     * @memberOf _\n     * @alias value\n     * @category Chaining\n     * @returns {Mixed} Returns the wrapped value.\n     * @example\n     *\n     * _([1, 2, 3]).valueOf();\n     * // => [1, 2, 3]\n     */\n    function wrapperValueOf() {\n      return this.__wrapped__;\n    }\n\n    /*--------------------------------------------------------------------------*/\n\n    // add functions that return wrapped values when chaining\n    lodash.after = after;\n    lodash.assign = assign;\n    lodash.at = at;\n    lodash.bind = bind;\n    lodash.bindAll = bindAll;\n    lodash.bindKey = bindKey;\n    lodash.compact = compact;\n    lodash.compose = compose;\n    lodash.countBy = countBy;\n    lodash.createCallback = createCallback;\n    lodash.debounce = debounce;\n    lodash.defaults = defaults;\n    lodash.defer = defer;\n    lodash.delay = delay;\n    lodash.difference = difference;\n    lodash.filter = filter;\n    lodash.flatten = flatten;\n    lodash.forEach = forEach;\n    lodash.forIn = forIn;\n    lodash.forOwn = forOwn;\n    lodash.functions = functions;\n    lodash.groupBy = groupBy;\n    lodash.initial = initial;\n    lodash.intersection = intersection;\n    lodash.invert = invert;\n    lodash.invoke = invoke;\n    lodash.keys = keys;\n    lodash.map = map;\n    lodash.max = max;\n    lodash.memoize = memoize;\n    lodash.merge = merge;\n    lodash.min = min;\n    lodash.omit = omit;\n    lodash.once = once;\n    lodash.pairs = pairs;\n    lodash.partial = partial;\n    lodash.partialRight = partialRight;\n    lodash.pick = pick;\n    lodash.pluck = pluck;\n    lodash.range = range;\n    lodash.reject = reject;\n    lodash.rest = rest;\n    lodash.shuffle = shuffle;\n    lodash.sortBy = sortBy;\n    lodash.tap = tap;\n    lodash.throttle = throttle;\n    lodash.times = times;\n    lodash.toArray = toArray;\n    lodash.union = union;\n    lodash.uniq = uniq;\n    lodash.values = values;\n    lodash.where = where;\n    lodash.without = without;\n    lodash.wrap = wrap;\n    lodash.zip = zip;\n    lodash.zipObject = zipObject;\n\n    // add aliases\n    lodash.collect = map;\n    lodash.drop = rest;\n    lodash.each = forEach;\n    lodash.extend = assign;\n    lodash.methods = functions;\n    lodash.object = zipObject;\n    lodash.select = filter;\n    lodash.tail = rest;\n    lodash.unique = uniq;\n\n    // add functions to `lodash.prototype`\n    mixin(lodash);\n\n    /*--------------------------------------------------------------------------*/\n\n    // add functions that return unwrapped values when chaining\n    lodash.clone = clone;\n    lodash.cloneDeep = cloneDeep;\n    lodash.contains = contains;\n    lodash.escape = escape;\n    lodash.every = every;\n    lodash.find = find;\n    lodash.findIndex = findIndex;\n    lodash.findKey = findKey;\n    lodash.has = has;\n    lodash.identity = identity;\n    lodash.indexOf = indexOf;\n    lodash.isArguments = isArguments;\n    lodash.isArray = isArray;\n    lodash.isBoolean = isBoolean;\n    lodash.isDate = isDate;\n    lodash.isElement = isElement;\n    lodash.isEmpty = isEmpty;\n    lodash.isEqual = isEqual;\n    lodash.isFinite = isFinite;\n    lodash.isFunction = isFunction;\n    lodash.isNaN = isNaN;\n    lodash.isNull = isNull;\n    lodash.isNumber = isNumber;\n    lodash.isObject = isObject;\n    lodash.isPlainObject = isPlainObject;\n    lodash.isRegExp = isRegExp;\n    lodash.isString = isString;\n    lodash.isUndefined = isUndefined;\n    lodash.lastIndexOf = lastIndexOf;\n    lodash.mixin = mixin;\n    lodash.noConflict = noConflict;\n    lodash.parseInt = parseInt;\n    lodash.random = random;\n    lodash.reduce = reduce;\n    lodash.reduceRight = reduceRight;\n    lodash.result = result;\n    lodash.runInContext = runInContext;\n    lodash.size = size;\n    lodash.some = some;\n    lodash.sortedIndex = sortedIndex;\n    lodash.template = template;\n    lodash.unescape = unescape;\n    lodash.uniqueId = uniqueId;\n\n    // add aliases\n    lodash.all = every;\n    lodash.any = some;\n    lodash.detect = find;\n    lodash.foldl = reduce;\n    lodash.foldr = reduceRight;\n    lodash.include = contains;\n    lodash.inject = reduce;\n\n    forOwn(lodash, function(func, methodName) {\n      if (!lodash.prototype[methodName]) {\n        lodash.prototype[methodName] = function() {\n          var args = [this.__wrapped__];\n          push.apply(args, arguments);\n          return func.apply(lodash, args);\n        };\n      }\n    });\n\n    /*--------------------------------------------------------------------------*/\n\n    // add functions capable of returning wrapped and unwrapped values when chaining\n    lodash.first = first;\n    lodash.last = last;\n\n    // add aliases\n    lodash.take = first;\n    lodash.head = first;\n\n    forOwn(lodash, function(func, methodName) {\n      if (!lodash.prototype[methodName]) {\n        lodash.prototype[methodName]= function(callback, thisArg) {\n          var result = func(this.__wrapped__, callback, thisArg);\n          return callback == null || (thisArg && typeof callback != 'function')\n            ? result\n            : new lodashWrapper(result);\n        };\n      }\n    });\n\n    /*--------------------------------------------------------------------------*/\n\n    /**\n     * The semantic version number.\n     *\n     * @static\n     * @memberOf _\n     * @type String\n     */\n    lodash.VERSION = '1.1.1';\n\n    // add \"Chaining\" functions to the wrapper\n    lodash.prototype.toString = wrapperToString;\n    lodash.prototype.value = wrapperValueOf;\n    lodash.prototype.valueOf = wrapperValueOf;\n\n    // add `Array` functions that return unwrapped values\n    each(['join', 'pop', 'shift'], function(methodName) {\n      var func = arrayRef[methodName];\n      lodash.prototype[methodName] = function() {\n        return func.apply(this.__wrapped__, arguments);\n      };\n    });\n\n    // add `Array` functions that return the wrapped value\n    each(['push', 'reverse', 'sort', 'unshift'], function(methodName) {\n      var func = arrayRef[methodName];\n      lodash.prototype[methodName] = function() {\n        func.apply(this.__wrapped__, arguments);\n        return this;\n      };\n    });\n\n    // add `Array` functions that return new wrapped values\n    each(['concat', 'slice', 'splice'], function(methodName) {\n      var func = arrayRef[methodName];\n      lodash.prototype[methodName] = function() {\n        return new lodashWrapper(func.apply(this.__wrapped__, arguments));\n      };\n    });\n\n    // avoid array-like object bugs with `Array#shift` and `Array#splice`\n    // in Firefox < 10 and IE < 9\n    if (!support.spliceObjects) {\n      each(['pop', 'shift', 'splice'], function(methodName) {\n        var func = arrayRef[methodName],\n            isSplice = methodName == 'splice';\n\n        lodash.prototype[methodName] = function() {\n          var value = this.__wrapped__,\n              result = func.apply(value, arguments);\n\n          if (value.length === 0) {\n            delete value[0];\n          }\n          return isSplice ? new lodashWrapper(result) : result;\n        };\n      });\n    }\n\n    // add pseudo private property to be used and removed during the build process\n    lodash._each = each;\n    lodash._iteratorTemplate = iteratorTemplate;\n    lodash._shimKeys = shimKeys;\n\n    return lodash;\n  }\n\n  /*--------------------------------------------------------------------------*/\n\n  // expose Lo-Dash\n  var _ = runInContext();\n\n  // some AMD build optimizers, like r.js, check for specific condition patterns like the following:\n  if (typeof define == 'function' && typeof define.amd == 'object' && define.amd) {\n    // Expose Lo-Dash to the global object even when an AMD loader is present in\n    // case Lo-Dash was injected by a third-party script and not intended to be\n    // loaded as a module. The global assignment can be reverted in the Lo-Dash\n    // module via its `noConflict()` method.\n    window._ = _;\n\n    // define as an anonymous module so, through path mapping, it can be\n    // referenced as the \"underscore\" module\n    define(function() {\n      return _;\n    });\n  }\n  // check for `exports` after `define` in case a build optimizer adds an `exports` object\n  else if (freeExports && !freeExports.nodeType) {\n    // in Node.js or RingoJS v0.8.0+\n    if (freeModule) {\n      (freeModule.exports = _)._ = _;\n    }\n    // in Narwhal or RingoJS v0.7.0-\n    else {\n      freeExports._ = _;\n    }\n  }\n  else {\n    // in a browser or Rhino\n    window._ = _;\n  }\n}(this));\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/json3/vendor/platform.js",
    "content": "/*!\n * Platform.js v1.0.0 <http://mths.be/platform>\n * Copyright 2010-2012 John-David Dalton <http://allyoucanleet.com/>\n * Available under MIT license <http://mths.be/mit>\n */\n;(function(window) {\n  'use strict';\n\n  /** Backup possible window/global object */\n  var oldWin = window;\n\n  /** Detect free variable `exports` */\n  var freeExports = typeof exports == 'object' && exports;\n\n  /** Detect free variable `global` */\n  var freeGlobal = typeof global == 'object' && global &&\n    (global == global.global ? (window = global) : global);\n\n  /** Opera regexp */\n  var reOpera = /Opera/;\n\n  /** Used to resolve a value's internal [[Class]] */\n  var toString = {}.toString;\n\n  /** Detect Java environment */\n  var java = /Java/.test(getClassOf(window.java)) && window.java;\n\n  /** A character to represent alpha */\n  var alpha = java ? 'a' : '\\u03b1';\n\n  /** A character to represent beta */\n  var beta = java ? 'b' : '\\u03b2';\n\n  /** Browser document object */\n  var doc = window.document || {};\n\n  /** Used to check for own properties of an object */\n  var hasOwnProperty = {}.hasOwnProperty;\n\n  /** Browser navigator object */\n  var nav = window.navigator || {};\n\n  /**\n   * Detect Opera browser\n   * http://www.howtocreate.co.uk/operaStuff/operaObject.html\n   * http://dev.opera.com/articles/view/opera-mini-web-content-authoring-guidelines/#operamini\n   */\n  var opera = window.operamini || window.opera;\n\n  /** Opera [[Class]] */\n  var operaClass = reOpera.test(operaClass = getClassOf(opera)) ? operaClass : (opera = null);\n\n  /** Possible global object */\n  var thisBinding = this;\n\n  /** Browser user agent string */\n  var userAgent = nav.userAgent || '';\n\n  /*--------------------------------------------------------------------------*/\n\n  /**\n   * Capitalizes a string value.\n   *\n   * @private\n   * @param {String} string The string to capitalize.\n   * @returns {String} The capitalized string.\n   */\n  function capitalize(string) {\n    string = String(string);\n    return string.charAt(0).toUpperCase() + string.slice(1);\n  }\n\n  /**\n   * An iteration utility for arrays and objects.\n   *\n   * @private\n   * @param {Array|Object} object The object to iterate over.\n   * @param {Function} callback The function called per iteration.\n   */\n  function each(object, callback) {\n    var index = -1,\n        length = object.length;\n\n    if (length == length >>> 0) {\n      while (++index < length) {\n        callback(object[index], index, object);\n      }\n    } else {\n      forOwn(object, callback);\n    }\n  }\n\n  /**\n   * Trim and conditionally capitalize string values.\n   *\n   * @private\n   * @param {String} string The string to format.\n   * @returns {String} The formatted string.\n   */\n  function format(string) {\n    string = trim(string);\n    return /^(?:webOS|i(?:OS|P))/.test(string)\n      ? string\n      : capitalize(string);\n  }\n\n  /**\n   * Iterates over an object's own properties, executing the `callback` for each.\n   *\n   * @private\n   * @param {Object} object The object to iterate over.\n   * @param {Function} callback The function executed per own property.\n   */\n  function forOwn(object, callback) {\n    for (var key in object) {\n      hasKey(object, key) && callback(object[key], key, object);\n    }\n  }\n\n  /**\n   * Gets the internal [[Class]] of a value.\n   *\n   * @private\n   * @param {Mixed} value The value.\n   * @returns {String} The [[Class]].\n   */\n  function getClassOf(value) {\n    return value == null\n      ? capitalize(value)\n      : toString.call(value).slice(8, -1);\n  }\n\n  /**\n   * Checks if an object has the specified key as a direct property.\n   *\n   * @private\n   * @param {Object} object The object to check.\n   * @param {String} key The key to check for.\n   * @returns {Boolean} Returns `true` if key is a direct property, else `false`.\n   */\n  function hasKey() {\n    // lazy define for others (not as accurate)\n    hasKey = function(object, key) {\n      var parent = object != null && (object.constructor || Object).prototype;\n      return !!parent && key in Object(object) && !(key in parent && object[key] === parent[key]);\n    };\n    // for modern browsers\n    if (getClassOf(hasOwnProperty) == 'Function') {\n      hasKey = function(object, key) {\n        return object != null && hasOwnProperty.call(object, key);\n      };\n    }\n    // for Safari 2\n    else if ({}.__proto__ == Object.prototype) {\n      hasKey = function(object, key) {\n        var result = false;\n        if (object != null) {\n          object = Object(object);\n          object.__proto__ = [object.__proto__, object.__proto__ = null, result = key in object][0];\n        }\n        return result;\n      };\n    }\n    return hasKey.apply(this, arguments);\n  }\n\n  /**\n   * Host objects can return type values that are different from their actual\n   * data type. The objects we are concerned with usually return non-primitive\n   * types of object, function, or unknown.\n   *\n   * @private\n   * @param {Mixed} object The owner of the property.\n   * @param {String} property The property to check.\n   * @returns {Boolean} Returns `true` if the property value is a non-primitive, else `false`.\n   */\n  function isHostType(object, property) {\n    var type = object != null ? typeof object[property] : 'number';\n    return !/^(?:boolean|number|string|undefined)$/.test(type) &&\n      (type == 'object' ? !!object[property] : true);\n  }\n\n  /**\n   * Prepares a string for use in a RegExp constructor by making hyphens and\n   * spaces optional.\n   *\n   * @private\n   * @param {String} string The string to qualify.\n   * @returns {String} The qualified string.\n   */\n  function qualify(string) {\n    return String(string).replace(/([ -])(?!$)/g, '$1?');\n  }\n\n  /**\n   * A bare-bones` Array#reduce` like utility function.\n   *\n   * @private\n   * @param {Array} array The array to iterate over.\n   * @param {Function} callback The function called per iteration.\n   * @param {Mixed} accumulator Initial value of the accumulator.\n   * @returns {Mixed} The accumulator.\n   */\n  function reduce(array, callback) {\n    var accumulator = null;\n    each(array, function(value, index) {\n      accumulator = callback(accumulator, value, index, array);\n    });\n    return accumulator;\n  }\n\n  /**\n   * Removes leading and trailing whitespace from a string.\n   *\n   * @private\n   * @param {String} string The string to trim.\n   * @returns {String} The trimmed string.\n   */\n  function trim(string) {\n    return String(string).replace(/^ +| +$/g, '');\n  }\n\n  /*--------------------------------------------------------------------------*/\n\n  /**\n   * Creates a new platform object.\n   *\n   * @memberOf platform\n   * @param {String} [ua = navigator.userAgent] The user agent string.\n   * @returns {Object} A platform object.\n   */\n  function parse(ua) {\n\n    ua || (ua = userAgent);\n\n    /** Temporary variable used over the script's lifetime */\n    var data;\n\n    /** The CPU architecture */\n    var arch = ua;\n\n    /** Platform description array */\n    var description = [];\n\n    /** Platform alpha/beta indicator */\n    var prerelease = null;\n\n    /** A flag to indicate that environment features should be used to resolve the platform */\n    var useFeatures = ua == userAgent;\n\n    /** The browser/environment version */\n    var version = useFeatures && opera && typeof opera.version == 'function' && opera.version();\n\n    /* Detectable layout engines (order is important) */\n    var layout = getLayout([\n      { 'label': 'WebKit', 'pattern': 'AppleWebKit' },\n      'iCab',\n      'Presto',\n      'NetFront',\n      'Tasman',\n      'Trident',\n      'KHTML',\n      'Gecko'\n    ]);\n\n    /* Detectable browser names (order is important) */\n    var name = getName([\n      'Adobe AIR',\n      'Arora',\n      'Avant Browser',\n      'Camino',\n      'Epiphany',\n      'Fennec',\n      'Flock',\n      'Galeon',\n      'GreenBrowser',\n      'iCab',\n      'Iceweasel',\n      'Iron',\n      'K-Meleon',\n      'Konqueror',\n      'Lunascape',\n      'Maxthon',\n      'Midori',\n      'Nook Browser',\n      'PhantomJS',\n      'Raven',\n      'Rekonq',\n      'RockMelt',\n      'SeaMonkey',\n      { 'label': 'Silk', 'pattern': '(?:Cloud9|Silk-Accelerated)' },\n      'Sleipnir',\n      'SlimBrowser',\n      'Sunrise',\n      'Swiftfox',\n      'WebPositive',\n      'Opera Mini',\n      'Opera',\n      'Chrome',\n      { 'label': 'Chrome Mobile', 'pattern': '(?:CriOS|CrMo)' },\n      { 'label': 'Firefox', 'pattern': '(?:Firefox|Minefield)' },\n      { 'label': 'IE', 'pattern': 'MSIE' },\n      'Safari'\n    ]);\n\n    /* Detectable products (order is important) */\n    var product = getProduct([\n      'BlackBerry',\n      { 'label': 'Galaxy S', 'pattern': 'GT-I9000' },\n      { 'label': 'Galaxy S2', 'pattern': 'GT-I9100' },\n      'Google TV',\n      'iPad',\n      'iPod',\n      'iPhone',\n      'Kindle',\n      { 'label': 'Kindle Fire', 'pattern': '(?:Cloud9|Silk-Accelerated)' },\n      'Nook',\n      'PlayBook',\n      'PlayStation Vita',\n      'TouchPad',\n      'Transformer',\n      'Xoom'\n    ]);\n\n    /* Detectable manufacturers */\n    var manufacturer = getManufacturer({\n      'Apple': { 'iPad': 1, 'iPhone': 1, 'iPod': 1 },\n      'Amazon': { 'Kindle': 1, 'Kindle Fire': 1 },\n      'Asus': { 'Transformer': 1 },\n      'Barnes & Noble': { 'Nook': 1 },\n      'BlackBerry': { 'PlayBook': 1 },\n      'Google': { 'Google TV': 1 },\n      'HP': { 'TouchPad': 1 },\n      'LG': { },\n      'Motorola': { 'Xoom': 1 },\n      'Nokia': { },\n      'Samsung': { 'Galaxy S': 1, 'Galaxy S2': 1 },\n      'Sony': { 'PlayStation Vita': 1 }\n    });\n\n    /* Detectable OSes (order is important) */\n    var os = getOS([\n      'Android',\n      'CentOS',\n      'Debian',\n      'Fedora',\n      'FreeBSD',\n      'Gentoo',\n      'Haiku',\n      'Kubuntu',\n      'Linux Mint',\n      'Red Hat',\n      'SuSE',\n      'Ubuntu',\n      'Xubuntu',\n      'Cygwin',\n      'Symbian OS',\n      'hpwOS',\n      'webOS ',\n      'webOS',\n      'Tablet OS',\n      'Linux',\n      'Mac OS X',\n      'Macintosh',\n      'Mac',\n      'Windows 98;',\n      'Windows '\n    ]);\n\n    /*------------------------------------------------------------------------*/\n\n    /**\n     * Picks the layout engine from an array of guesses.\n     *\n     * @private\n     * @param {Array} guesses An array of guesses.\n     * @returns {String|Null} The detected layout engine.\n     */\n    function getLayout(guesses) {\n      return reduce(guesses, function(result, guess) {\n        return result || RegExp('\\\\b' + (\n          guess.pattern || qualify(guess)\n        ) + '\\\\b', 'i').exec(ua) && (guess.label || guess);\n      });\n    }\n\n    /**\n     * Picks the manufacturer from an array of guesses.\n     *\n     * @private\n     * @param {Array} guesses An array of guesses.\n     * @returns {String|Null} The detected manufacturer.\n     */\n    function getManufacturer(guesses) {\n      return reduce(guesses, function(result, value, key) {\n        // lookup the manufacturer by product or scan the UA for the manufacturer\n        return result || (\n          value[product] ||\n          value[0/*Opera 9.25 fix*/, /^[a-z]+(?: +[a-z]+\\b)*/i.exec(product)] ||\n          RegExp('\\\\b' + (key.pattern || qualify(key)) + '(?:\\\\b|\\\\w*\\\\d)', 'i').exec(ua)\n        ) && (key.label || key);\n      });\n    }\n\n    /**\n     * Picks the browser name from an array of guesses.\n     *\n     * @private\n     * @param {Array} guesses An array of guesses.\n     * @returns {String|Null} The detected browser name.\n     */\n    function getName(guesses) {\n      return reduce(guesses, function(result, guess) {\n        return result || RegExp('\\\\b' + (\n          guess.pattern || qualify(guess)\n        ) + '\\\\b', 'i').exec(ua) && (guess.label || guess);\n      });\n    }\n\n    /**\n     * Picks the OS name from an array of guesses.\n     *\n     * @private\n     * @param {Array} guesses An array of guesses.\n     * @returns {String|Null} The detected OS name.\n     */\n    function getOS(guesses) {\n      return reduce(guesses, function(result, guess) {\n        var pattern = guess.pattern || qualify(guess);\n        if (!result && (result =\n            RegExp('\\\\b' + pattern + '(?:/[\\\\d.]+|[ \\\\w.]*)', 'i').exec(ua))) {\n          // platform tokens defined at\n          // http://msdn.microsoft.com/en-us/library/ms537503(VS.85).aspx\n          // http://web.archive.org/web/20081122053950/http://msdn.microsoft.com/en-us/library/ms537503(VS.85).aspx\n          data = {\n            '6.2':  '8',\n            '6.1':  'Server 2008 R2 / 7',\n            '6.0':  'Server 2008 / Vista',\n            '5.2':  'Server 2003 / XP 64-bit',\n            '5.1':  'XP',\n            '5.01': '2000 SP1',\n            '5.0':  '2000',\n            '4.0':  'NT',\n            '4.90': 'ME'\n          };\n          // detect Windows version from platform tokens\n          if (/^Win/i.test(result) &&\n              (data = data[0/*Opera 9.25 fix*/, /[\\d.]+$/.exec(result)])) {\n            result = 'Windows ' + data;\n          }\n          // correct character case and cleanup\n          result = format(String(result)\n            .replace(RegExp(pattern, 'i'), guess.label || guess)\n            .replace(/ ce$/i, ' CE')\n            .replace(/hpw/i, 'web')\n            .replace(/Macintosh/, 'Mac OS')\n            .replace(/_PowerPC/i, ' OS')\n            .replace(/(OS X) [^ \\d]+/i, '$1')\n            .replace(/\\/(\\d)/, ' $1')\n            .replace(/_/g, '.')\n            .replace(/(?: BePC|[ .]*fc[ \\d.]+)$/i, '')\n            .replace(/x86\\.64/gi, 'x86_64')\n            .split(' on ')[0]);\n        }\n        return result;\n      });\n    }\n\n    /**\n     * Picks the product name from an array of guesses.\n     *\n     * @private\n     * @param {Array} guesses An array of guesses.\n     * @returns {String|Null} The detected product name.\n     */\n    function getProduct(guesses) {\n      return reduce(guesses, function(result, guess) {\n        var pattern = guess.pattern || qualify(guess);\n        if (!result && (result =\n              RegExp('\\\\b' + pattern + ' *\\\\d+[.\\\\w_]*', 'i').exec(ua) ||\n              RegExp('\\\\b' + pattern + '(?:; *(?:[a-z]+[_-])?[a-z]+\\\\d+|[^ ();-]*)', 'i').exec(ua)\n            )) {\n          // split by forward slash and append product version if needed\n          if ((result = String(guess.label || result).split('/'))[1] && !/[\\d.]+/.test(result[0])) {\n            result[0] += ' ' + result[1];\n          }\n          // correct character case and cleanup\n          guess = guess.label || guess;\n          result = format(result[0]\n            .replace(RegExp(pattern, 'i'), guess)\n            .replace(RegExp('; *(?:' + guess + '[_-])?', 'i'), ' ')\n            .replace(RegExp('(' + guess + ')(\\\\w)', 'i'), '$1 $2'));\n        }\n        return result;\n      });\n    }\n\n    /**\n     * Resolves the version using an array of UA patterns.\n     *\n     * @private\n     * @param {Array} patterns An array of UA patterns.\n     * @returns {String|Null} The detected version.\n     */\n    function getVersion(patterns) {\n      return reduce(patterns, function(result, pattern) {\n        return result || (RegExp(pattern +\n          '(?:-[\\\\d.]+/|(?: for [\\\\w-]+)?[ /-])([\\\\d.]+[^ ();/_-]*)', 'i').exec(ua) || 0)[1] || null;\n      });\n    }\n\n    /*------------------------------------------------------------------------*/\n\n    /**\n     * Returns `platform.description` when the platform object is coerced to a string.\n     *\n     * @name toString\n     * @memberOf platform\n     * @returns {String} Returns `platform.description` if available, else an empty string.\n     */\n    function toStringPlatform() {\n      return this.description || '';\n    }\n\n    /*------------------------------------------------------------------------*/\n\n    // convert layout to an array so we can add extra details\n    layout && (layout = [layout]);\n\n    // detect product names that contain their manufacturer's name\n    if (manufacturer && !product) {\n      product = getProduct([manufacturer]);\n    }\n    // clean up Google TV\n    if ((data = /Google TV/.exec(product))) {\n      product = data[0];\n    }\n    // detect simulators\n    if (/\\bSimulator\\b/i.test(ua)) {\n      product = (product ? product + ' ' : '') + 'Simulator';\n    }\n    // detect iOS\n    if (/^iP/.test(product)) {\n      name || (name = 'Safari');\n      os = 'iOS' + ((data = / OS ([\\d_]+)/i.exec(ua))\n        ? ' ' + data[1].replace(/_/g, '.')\n        : '');\n    }\n    // detect Kubuntu\n    else if (name == 'Konqueror' && !/buntu/i.test(os)) {\n      os = 'Kubuntu';\n    }\n    // detect Android browsers\n    else if (manufacturer && manufacturer != 'Google' &&\n        /Chrome|Vita/.test(name + ';' + product)) {\n      name = 'Android Browser';\n      os = /Android/.test(os) ? os : 'Android';\n    }\n    // detect false positives for Firefox/Safari\n    else if (!name || (data = !/\\bMinefield\\b/i.test(ua) && /Firefox|Safari/.exec(name))) {\n      // escape the `/` for Firefox 1\n      if (name && !product && /[\\/,]|^[^(]+?\\)/.test(ua.slice(ua.indexOf(data + '/') + 8))) {\n        // clear name of false positives\n        name = null;\n      }\n      // reassign a generic name\n      if ((data = product || manufacturer || os) &&\n          (product || manufacturer || /Android|Symbian OS|Tablet OS|webOS/.test(os))) {\n        name = /[a-z]+(?: Hat)?/i.exec(/Android/.test(os) ? os : data) + ' Browser';\n      }\n    }\n    // detect non-Opera versions (order is important)\n    if (!version) {\n      version = getVersion([\n        '(?:Cloud9|CriOS|CrMo|Opera ?Mini|Raven|Silk(?!/[\\\\d.]+$))',\n        'Version',\n        qualify(name),\n        '(?:Firefox|Minefield|NetFront)'\n      ]);\n    }\n    // detect stubborn layout engines\n    if (layout == 'iCab' && parseFloat(version) > 3) {\n      layout = ['WebKit'];\n    } else if (data =\n        /Opera/.test(name) && 'Presto' ||\n        /\\b(?:Midori|Nook|Safari)\\b/i.test(ua) && 'WebKit' ||\n        !layout && /\\bMSIE\\b/i.test(ua) && (/^Mac/.test(os) ? 'Tasman' : 'Trident')) {\n      layout = [data];\n    }\n    // leverage environment features\n    if (useFeatures) {\n      // detect server-side environments\n      // Rhino has a global function while others have a global object\n      if (isHostType(window, 'global')) {\n        if (java) {\n          data = java.lang.System;\n          arch = data.getProperty('os.arch');\n          os = os || data.getProperty('os.name') + ' ' + data.getProperty('os.version');\n        }\n        if (typeof exports == 'object' && exports) {\n          // if `thisBinding` is the [ModuleScope]\n          if (thisBinding == oldWin && typeof system == 'object' && (data = [system])[0]) {\n            os || (os = data[0].os || null);\n            try {\n              data[1] = require('ringo/engine').version;\n              version = data[1].join('.');\n              name = 'RingoJS';\n            } catch(e) {\n              if (data[0].global == freeGlobal) {\n                name = 'Narwhal';\n              }\n            }\n          } else if (typeof process == 'object' && (data = process)) {\n            name = 'Node.js';\n            arch = data.arch;\n            os = data.platform;\n            version = /[\\d.]+/.exec(data.version)[0];\n          }\n        } else if (getClassOf(window.environment) == 'Environment') {\n          name = 'Rhino';\n        }\n      }\n      // detect Adobe AIR\n      else if (getClassOf(data = window.runtime) == 'ScriptBridgingProxyObject') {\n        name = 'Adobe AIR';\n        os = data.flash.system.Capabilities.os;\n      }\n      // detect PhantomJS\n      else if (getClassOf(data = window.phantom) == 'RuntimeObject') {\n        name = 'PhantomJS';\n        version = (data = data.version || null) && (data.major + '.' + data.minor + '.' + data.patch);\n      }\n      // detect IE compatibility modes\n      else if (typeof doc.documentMode == 'number' && (data = /\\bTrident\\/(\\d+)/i.exec(ua))) {\n        // we're in compatibility mode when the Trident version + 4 doesn't\n        // equal the document mode\n        version = [version, doc.documentMode];\n        if ((data = +data[1] + 4) != version[1]) {\n          description.push('IE ' + version[1] + ' mode');\n          layout[1] = '';\n          version[1] = data;\n        }\n        version = name == 'IE' ? String(version[1].toFixed(1)) : version[0];\n      }\n      os = os && format(os);\n    }\n    // detect prerelease phases\n    if (version && (data =\n        /(?:[ab]|dp|pre|[ab]\\d+pre)(?:\\d+\\+?)?$/i.exec(version) ||\n        /(?:alpha|beta)(?: ?\\d)?/i.exec(ua + ';' + (useFeatures && nav.appMinorVersion)) ||\n        /\\bMinefield\\b/i.test(ua) && 'a')) {\n      prerelease = /b/i.test(data) ? 'beta' : 'alpha';\n      version = version.replace(RegExp(data + '\\\\+?$'), '') +\n        (prerelease == 'beta' ? beta : alpha) + (/\\d+\\+?/.exec(data) || '');\n    }\n    // rename code name \"Fennec\"\n    if (name == 'Fennec') {\n      name = 'Firefox Mobile';\n    }\n    // obscure Maxthon's unreliable version\n    else if (name == 'Maxthon' && version) {\n      version = version.replace(/\\.[\\d.]+/, '.x');\n    }\n    // detect Silk desktop/accelerated modes\n    else if (name == 'Silk') {\n      if (!/Mobi/i.test(ua)) {\n        os = 'Android';\n        description.unshift('desktop mode');\n      }\n      if (/Accelerated *= *true/i.test(ua)) {\n        description.unshift('accelerated');\n      }\n    }\n    // detect Windows Phone desktop mode\n    else if (name == 'IE' && (data = (/; *(?:XBLWP|ZuneWP)(\\d+)/i.exec(ua) || 0)[1])) {\n      name += ' Mobile';\n      os = 'Windows Phone OS ' + data + '.x';\n      description.unshift('desktop mode');\n    }\n    // add mobile postfix\n    else if ((name == 'IE' || name && !product && !/Browser|Mobi/.test(name)) &&\n        (os == 'Windows CE' || /Mobi/i.test(ua))) {\n      name += ' Mobile';\n    }\n    // detect IE platform preview\n    else if (name == 'IE' && useFeatures && typeof external == 'object' && !external) {\n      description.unshift('platform preview');\n    }\n    // detect BlackBerry OS version\n    // http://docs.blackberry.com/en/developers/deliverables/18169/HTTP_headers_sent_by_BB_Browser_1234911_11.jsp\n    else if (/BlackBerry/.test(product) && (data =\n        (RegExp(product.replace(/ +/g, ' *') + '/([.\\\\d]+)', 'i').exec(ua) || 0)[1] ||\n        version)) {\n      os = 'Device Software ' + data;\n      version = null;\n    }\n    // detect Opera identifying/masking itself as another browser\n    // http://www.opera.com/support/kb/view/843/\n    else if (this != forOwn && (\n          (useFeatures && opera) ||\n          (/Opera/.test(name) && /\\b(?:MSIE|Firefox)\\b/i.test(ua)) ||\n          (name == 'Firefox' && /OS X (?:\\d+\\.){2,}/.test(os)) ||\n          (name == 'IE' && (\n            (os && !/^Win/.test(os) && version > 5.5) ||\n            /Windows XP/.test(os) && version > 8 ||\n            version == 8 && !/Trident/.test(ua)\n          ))\n        ) && !reOpera.test(data = parse.call(forOwn, ua.replace(reOpera, '') + ';')) && data.name) {\n\n      // when \"indentifying\", the UA contains both Opera and the other browser's name\n      data = 'ing as ' + data.name + ((data = data.version) ? ' ' + data : '');\n      if (reOpera.test(name)) {\n        if (/IE/.test(data) && os == 'Mac OS') {\n          os = null;\n        }\n        data = 'identify' + data;\n      }\n      // when \"masking\", the UA contains only the other browser's name\n      else {\n        data = 'mask' + data;\n        if (operaClass) {\n          name = format(operaClass.replace(/([a-z])([A-Z])/g, '$1 $2'));\n        } else {\n          name = 'Opera';\n        }\n        if (/IE/.test(data)) {\n          os = null;\n        }\n        if (!useFeatures) {\n          version = null;\n        }\n      }\n      layout = ['Presto'];\n      description.push(data);\n    }\n    // detect WebKit Nightly and approximate Chrome/Safari versions\n    if ((data = (/\\bAppleWebKit\\/([\\d.]+\\+?)/i.exec(ua) || 0)[1])) {\n      // correct build for numeric comparison\n      // (e.g. \"532.5\" becomes \"532.05\")\n      data = [parseFloat(data.replace(/\\.(\\d)$/, '.0$1')), data];\n      // nightly builds are postfixed with a `+`\n      if (name == 'Safari' && data[1].slice(-1) == '+') {\n        name = 'WebKit Nightly';\n        prerelease = 'alpha';\n        version = data[1].slice(0, -1);\n      }\n      // clear incorrect browser versions\n      else if (version == data[1] ||\n          version == (/\\bSafari\\/([\\d.]+\\+?)/i.exec(ua) || 0)[1]) {\n        version = null;\n      }\n      // use the full Chrome version when available\n      data = [data[0], (/\\bChrome\\/([\\d.]+)/i.exec(ua) || 0)[1]];\n\n      // detect JavaScriptCore\n      // http://stackoverflow.com/questions/6768474/how-can-i-detect-which-javascript-engine-v8-or-jsc-is-used-at-runtime-in-androi\n      if (!useFeatures || (/internal|\\n/i.test(toString.toString()) && !data[1])) {\n        layout[1] = 'like Safari';\n        data = (data = data[0], data < 400 ? 1 : data < 500 ? 2 : data < 526 ? 3 : data < 533 ? 4 : data < 534 ? '4+' : data < 535 ? 5 : '5');\n      } else {\n        layout[1] = 'like Chrome';\n        data = data[1] || (data = data[0], data < 530 ? 1 : data < 532 ? 2 : data < 532.05 ? 3 : data < 533 ? 4 : data < 534.03 ? 5 : data < 534.07 ? 6 : data < 534.10 ? 7 : data < 534.13 ? 8 : data < 534.16 ? 9 : data < 534.24 ? 10 : data < 534.30 ? 11 : data < 535.01 ? 12 : data < 535.02 ? '13+' : data < 535.07 ? 15 : data < 535.11 ? 16 : data < 535.19 ? 17 : data < 536.05 ? 18 : data < 536.10 ? 19 : data < 537.01 ? 20 : '21');\n      }\n      // add the postfix of \".x\" or \"+\" for approximate versions\n      layout[1] += ' ' + (data += typeof data == 'number' ? '.x' : /[.+]/.test(data) ? '' : '+');\n      // obscure version for some Safari 1-2 releases\n      if (name == 'Safari' && (!version || parseInt(version) > 45)) {\n        version = data;\n      }\n    }\n    // detect Opera desktop modes\n    if (name == 'Opera' &&  (data = /(?:zbov|zvav)$/.exec(os))) {\n      name += ' ';\n      description.unshift('desktop mode');\n      if (data == 'zvav') {\n        name += 'Mini';\n        version = null;\n      } else {\n        name += 'Mobile';\n      }\n    }\n    // detect Chrome desktop mode\n    else if (name == 'Safari' && /Chrome/.exec(layout[1])) {\n      description.unshift('desktop mode');\n      name = 'Chrome Mobile';\n      version = null;\n\n      if (/Mac OS X/.test(os)) {\n        manufacturer = 'Apple';\n        os = 'iOS 4.3+';\n      } else {\n        os = null;\n      }\n    }\n    // strip incorrect OS versions\n    if (version && version.indexOf(data = /[\\d.]+$/.exec(os)) == 0 &&\n        ua.indexOf('/' + data + '-') > -1) {\n      os = trim(os.replace(data, ''));\n    }\n    // add layout engine\n    if (layout && !/Avant|Nook/.test(name) && (\n        /Browser|Lunascape|Maxthon/.test(name) ||\n        /^(?:Adobe|Arora|Midori|Phantom|Rekonq|Rock|Sleipnir|Web)/.test(name) && layout[1])) {\n      // don't add layout details to description if they are falsey\n      (data = layout[layout.length - 1]) && description.push(data);\n    }\n    // combine contextual information\n    if (description.length) {\n      description = ['(' + description.join('; ') + ')'];\n    }\n    // append manufacturer\n    if (manufacturer && product && product.indexOf(manufacturer) < 0) {\n      description.push('on ' + manufacturer);\n    }\n    // append product\n    if (product) {\n      description.push((/^on /.test(description[description.length -1]) ? '' : 'on ') + product);\n    }\n    // parse OS into an object\n    if (os) {\n      data = / ([\\d.+]+)$/.exec(os);\n      os = {\n        'architecture': 32,\n        'family': data ? os.replace(data[0], '') : os,\n        'version': data ? data[1] : null,\n        'toString': function() {\n          var version = this.version;\n          return this.family + (version ? ' ' + version : '') + (this.architecture == 64 ? ' 64-bit' : '');\n        }\n      };\n    }\n    // add browser/OS architecture\n    if ((data = / (?:AMD|IA|Win|WOW|x86_|x)64\\b/i.exec(arch)) && !/\\bi686\\b/i.test(arch)) {\n      if (os) {\n        os.architecture = 64;\n        os.family = os.family.replace(data, '');\n      }\n      if (name && (/WOW64/i.test(ua) ||\n          (useFeatures && /\\w(?:86|32)$/.test(nav.cpuClass || nav.platform)))) {\n        description.unshift('32-bit');\n      }\n    }\n\n    ua || (ua = null);\n\n    /*------------------------------------------------------------------------*/\n\n    /**\n     * The platform object.\n     *\n     * @name platform\n     * @type Object\n     */\n    return {\n\n      /**\n       * The browser/environment version.\n       *\n       * @memberOf platform\n       * @type String|Null\n       */\n      'version': name && version && (description.unshift(version), version),\n\n      /**\n       * The name of the browser/environment.\n       *\n       * @memberOf platform\n       * @type String|Null\n       */\n      'name': name && (description.unshift(name), name),\n\n      /**\n       * The name of the operating system.\n       *\n       * @memberOf platform\n       * @type Object\n       */\n      'os': os\n        ? (name &&\n            !(os == String(os).split(' ')[0] && (os == name.split(' ')[0] || product)) &&\n              description.push(product ? '(' + os + ')' : 'on ' + os), os)\n        : {\n\n          /**\n           * The CPU architecture the OS is built for.\n           *\n           * @memberOf platform.os\n           * @type String|Null\n           */\n          'architecture': null,\n\n          /**\n           * The family of the OS.\n           *\n           * @memberOf platform.os\n           * @type String|Null\n           */\n          'family': null,\n\n          /**\n           * The version of the OS.\n           *\n           * @memberOf platform.os\n           * @type String|Null\n           */\n          'version': null,\n\n          /**\n           * Returns the OS string.\n           *\n           * @memberOf platform.os\n           * @returns {String} The OS string.\n           */\n          'toString': function() { return 'null'; }\n        },\n\n      /**\n       * The platform description.\n       *\n       * @memberOf platform\n       * @type String|Null\n       */\n      'description': description.length ? description.join(' ') : ua,\n\n      /**\n       * The name of the browser layout engine.\n       *\n       * @memberOf platform\n       * @type String|Null\n       */\n      'layout': layout && layout[0],\n\n      /**\n       * The name of the product's manufacturer.\n       *\n       * @memberOf platform\n       * @type String|Null\n       */\n      'manufacturer': manufacturer,\n\n      /**\n       * The alpha/beta release indicator.\n       *\n       * @memberOf platform\n       * @type String|Null\n       */\n      'prerelease': prerelease,\n\n      /**\n       * The name of the product hosting the browser.\n       *\n       * @memberOf platform\n       * @type String|Null\n       */\n      'product': product,\n\n      /**\n       * The browser's user agent string.\n       *\n       * @memberOf platform\n       * @type String|Null\n       */\n      'ua': ua,\n\n      // parses a user agent string into a platform object\n      'parse': parse,\n\n      // returns the platform description\n      'toString': toStringPlatform\n    };\n  }\n\n  /*--------------------------------------------------------------------------*/\n\n  // expose platform\n  // some AMD build optimizers, like r.js, check for specific condition patterns like the following:\n  if (typeof define == 'function' && typeof define.amd == 'object' && define.amd) {\n    // define as an anonymous module so, through path mapping, it can be aliased\n    define(function() {\n      return parse();\n    });\n  }\n  // check for `exports` after `define` in case a build optimizer adds an `exports` object\n  else if (freeExports) {\n    // in Narwhal, Node.js, or RingoJS\n    forOwn(parse(), function(value, key) {\n      freeExports[key] = value;\n    });\n  }\n  // in a browser or Rhino\n  else {\n    // use square bracket notation so Closure Compiler won't munge `platform`\n    // http://code.google.com/closure/compiler/docs/api-tutorial3.html#export\n    window['platform'] = parse();\n  }\n}(this));\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/json3/vendor/prototype.js",
    "content": "/*  Prototype JavaScript framework, version 1.6.1\n *  (c) 2005-2009 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.6.1',\n\n  Browser: (function(){\n    var ua = navigator.userAgent;\n    var isOpera = Object.prototype.toString.call(window.opera) == '[object Opera]';\n    return {\n      IE:             !!window.attachEvent && !isOpera,\n      Opera:          isOpera,\n      WebKit:         ua.indexOf('AppleWebKit/') > -1,\n      Gecko:          ua.indexOf('Gecko') > -1 && ua.indexOf('KHTML') === -1,\n      MobileSafari:   /Apple.*Mobile.*Safari/.test(ua)\n    }\n  })(),\n\n  BrowserFeatures: {\n    XPath: !!document.evaluate,\n    SelectorsAPI: !!document.querySelector,\n    ElementExtensions: (function() {\n      var constructor = window.Element || window.HTMLElement;\n      return !!(constructor && constructor.prototype);\n    })(),\n    SpecificElementExtensions: (function() {\n      if (typeof window.HTMLDivElement !== 'undefined')\n        return true;\n\n      var div = document.createElement('div');\n      var form = document.createElement('form');\n      var isSupported = false;\n\n      if (div['__proto__'] && (div['__proto__'] !== form['__proto__'])) {\n        isSupported = true;\n      }\n\n      div = form = null;\n\n      return isSupported;\n    })()\n  },\n\n  ScriptFragment: '<script[^>]*>([\\\\S\\\\s]*?)<\\/script>',\n  JSONFilter: /^\\/\\*-secure-([\\s\\S]*)\\*\\/\\s*$/,\n\n  emptyFunction: function() { },\n  K: function(x) { return x }\n};\n\nif (Prototype.Browser.MobileSafari)\n  Prototype.BrowserFeatures.SpecificElementExtensions = false;\n\n\nvar Abstract = { };\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/* Based on Alex Arnell's inheritance implementation. */\n\nvar Class = (function() {\n  function subclass() {};\n  function create() {\n    var parent = null, properties = $A(arguments);\n    if (Object.isFunction(properties[0]))\n      parent = properties.shift();\n\n    function klass() {\n      this.initialize.apply(this, arguments);\n    }\n\n    Object.extend(klass, Class.Methods);\n    klass.superclass = parent;\n    klass.subclasses = [];\n\n    if (parent) {\n      subclass.prototype = parent.prototype;\n      klass.prototype = new subclass;\n      parent.subclasses.push(klass);\n    }\n\n    for (var i = 0; i < properties.length; i++)\n      klass.addMethods(properties[i]);\n\n    if (!klass.prototype.initialize)\n      klass.prototype.initialize = Prototype.emptyFunction;\n\n    klass.prototype.constructor = klass;\n    return klass;\n  }\n\n  function addMethods(source) {\n    var ancestor   = this.superclass && this.superclass.prototype;\n    var properties = Object.keys(source);\n\n    if (!Object.keys({ toString: true }).length) {\n      if (source.toString != Object.prototype.toString)\n        properties.push(\"toString\");\n      if (source.valueOf != Object.prototype.valueOf)\n        properties.push(\"valueOf\");\n    }\n\n    for (var i = 0, length = properties.length; i < length; i++) {\n      var property = properties[i], value = source[property];\n      if (ancestor && Object.isFunction(value) &&\n          value.argumentNames().first() == \"$super\") {\n        var method = value;\n        value = (function(m) {\n          return function() { return ancestor[m].apply(this, arguments); };\n        })(property).wrap(method);\n\n        value.valueOf = method.valueOf.bind(method);\n        value.toString = method.toString.bind(method);\n      }\n      this.prototype[property] = value;\n    }\n\n    return this;\n  }\n\n  return {\n    create: create,\n    Methods: {\n      addMethods: addMethods\n    }\n  };\n})();\n(function() {\n\n  var _toString = Object.prototype.toString;\n\n  function extend(destination, source) {\n    for (var property in source)\n      destination[property] = source[property];\n    return destination;\n  }\n\n  function inspect(object) {\n    try {\n      if (isUndefined(object)) return 'undefined';\n      if (object === null) return 'null';\n      return object.inspect ? object.inspect() : String(object);\n    } catch (e) {\n      if (e instanceof RangeError) return '...';\n      throw e;\n    }\n  }\n\n  function toJSON(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\n    if (object === null) return 'null';\n    if (object.toJSON) return object.toJSON();\n    if (isElement(object)) return;\n\n    var results = [];\n    for (var property in object) {\n      var value = toJSON(object[property]);\n      if (!isUndefined(value))\n        results.push(property.toJSON() + ': ' + value);\n    }\n\n    return '{' + results.join(', ') + '}';\n  }\n\n  function toQueryString(object) {\n    return $H(object).toQueryString();\n  }\n\n  function toHTML(object) {\n    return object && object.toHTML ? object.toHTML() : String.interpret(object);\n  }\n\n  function keys(object) {\n    var results = [];\n    for (var property in object)\n      results.push(property);\n    return results;\n  }\n\n  function values(object) {\n    var results = [];\n    for (var property in object)\n      results.push(object[property]);\n    return results;\n  }\n\n  function clone(object) {\n    return extend({ }, object);\n  }\n\n  function isElement(object) {\n    return !!(object && object.nodeType == 1);\n  }\n\n  function isArray(object) {\n    return _toString.call(object) == \"[object Array]\";\n  }\n\n\n  function isHash(object) {\n    return object instanceof Hash;\n  }\n\n  function isFunction(object) {\n    return typeof object === \"function\";\n  }\n\n  function isString(object) {\n    return _toString.call(object) == \"[object String]\";\n  }\n\n  function isNumber(object) {\n    return _toString.call(object) == \"[object Number]\";\n  }\n\n  function isUndefined(object) {\n    return typeof object === \"undefined\";\n  }\n\n  extend(Object, {\n    extend:        extend,\n    inspect:       inspect,\n    toJSON:        toJSON,\n    toQueryString: toQueryString,\n    toHTML:        toHTML,\n    keys:          keys,\n    values:        values,\n    clone:         clone,\n    isElement:     isElement,\n    isArray:       isArray,\n    isHash:        isHash,\n    isFunction:    isFunction,\n    isString:      isString,\n    isNumber:      isNumber,\n    isUndefined:   isUndefined\n  });\n})();\nObject.extend(Function.prototype, (function() {\n  var slice = Array.prototype.slice;\n\n  function update(array, args) {\n    var arrayLength = array.length, length = args.length;\n    while (length--) array[arrayLength + length] = args[length];\n    return array;\n  }\n\n  function merge(array, args) {\n    array = slice.call(array, 0);\n    return update(array, args);\n  }\n\n  function argumentNames() {\n    var names = this.toString().match(/^[\\s\\(]*function[^(]*\\(([^)]*)\\)/)[1]\n      .replace(/\\/\\/.*?[\\r\\n]|\\/\\*(?:.|[\\r\\n])*?\\*\\//g, '')\n      .replace(/\\s+/g, '').split(',');\n    return names.length == 1 && !names[0] ? [] : names;\n  }\n\n  function bind(context) {\n    if (arguments.length < 2 && Object.isUndefined(arguments[0])) return this;\n    var __method = this, args = slice.call(arguments, 1);\n    return function() {\n      var a = merge(args, arguments);\n      return __method.apply(context, a);\n    }\n  }\n\n  function bindAsEventListener(context) {\n    var __method = this, args = slice.call(arguments, 1);\n    return function(event) {\n      var a = update([event || window.event], args);\n      return __method.apply(context, a);\n    }\n  }\n\n  function curry() {\n    if (!arguments.length) return this;\n    var __method = this, args = slice.call(arguments, 0);\n    return function() {\n      var a = merge(args, arguments);\n      return __method.apply(this, a);\n    }\n  }\n\n  function delay(timeout) {\n    var __method = this, args = slice.call(arguments, 1);\n    timeout = timeout * 1000\n    return window.setTimeout(function() {\n      return __method.apply(__method, args);\n    }, timeout);\n  }\n\n  function defer() {\n    var args = update([0.01], arguments);\n    return this.delay.apply(this, args);\n  }\n\n  function wrap(wrapper) {\n    var __method = this;\n    return function() {\n      var a = update([__method.bind(this)], arguments);\n      return wrapper.apply(this, a);\n    }\n  }\n\n  function methodize() {\n    if (this._methodized) return this._methodized;\n    var __method = this;\n    return this._methodized = function() {\n      var a = update([this], arguments);\n      return __method.apply(null, a);\n    };\n  }\n\n  return {\n    argumentNames:       argumentNames,\n    bind:                bind,\n    bindAsEventListener: bindAsEventListener,\n    curry:               curry,\n    delay:               delay,\n    defer:               defer,\n    wrap:                wrap,\n    methodize:           methodize\n  }\n})());\n\n\nDate.prototype.toJSON = function() {\n  return '\"' + this.getUTCFullYear() + '-' +\n    (this.getUTCMonth() + 1).toPaddedString(2) + '-' +\n    this.getUTCDate().toPaddedString(2) + 'T' +\n    this.getUTCHours().toPaddedString(2) + ':' +\n    this.getUTCMinutes().toPaddedString(2) + ':' +\n    this.getUTCSeconds().toPaddedString(2) + 'Z\"';\n};\n\n\nRegExp.prototype.match = RegExp.prototype.test;\n\nRegExp.escape = function(str) {\n  return String(str).replace(/([.*+?^=!:${}()|[\\]\\/\\\\])/g, '\\\\$1');\n};\nvar PeriodicalExecuter = Class.create({\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  execute: function() {\n    this.callback(this);\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.execute();\n        this.currentlyExecuting = false;\n      } catch(e) {\n        this.currentlyExecuting = false;\n        throw e;\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, (function() {\n\n  function prepareReplacement(replacement) {\n    if (Object.isFunction(replacement)) return replacement;\n    var template = new Template(replacement);\n    return function(match) { return template.evaluate(match) };\n  }\n\n  function gsub(pattern, replacement) {\n    var result = '', source = this, match;\n    replacement = prepareReplacement(replacement);\n\n    if (Object.isString(pattern))\n      pattern = RegExp.escape(pattern);\n\n    if (!(pattern.length || pattern.source)) {\n      replacement = replacement('');\n      return replacement + source.split('').join(replacement) + replacement;\n    }\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  function sub(pattern, replacement, count) {\n    replacement = prepareReplacement(replacement);\n    count = Object.isUndefined(count) ? 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  function scan(pattern, iterator) {\n    this.gsub(pattern, iterator);\n    return String(this);\n  }\n\n  function truncate(length, truncation) {\n    length = length || 30;\n    truncation = Object.isUndefined(truncation) ? '...' : truncation;\n    return this.length > length ?\n      this.slice(0, length - truncation.length) + truncation : String(this);\n  }\n\n  function strip() {\n    return this.replace(/^\\s+/, '').replace(/\\s+$/, '');\n  }\n\n  function stripTags() {\n    return this.replace(/<\\w+(\\s+(\"[^\"]*\"|'[^']*'|[^>])+)?>|<\\/\\w+>/gi, '');\n  }\n\n  function stripScripts() {\n    return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), '');\n  }\n\n  function extractScripts() {\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  function evalScripts() {\n    return this.extractScripts().map(function(script) { return eval(script) });\n  }\n\n  function escapeHTML() {\n    return this.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;');\n  }\n\n  function unescapeHTML() {\n    return this.stripTags().replace(/&lt;/g,'<').replace(/&gt;/g,'>').replace(/&amp;/g,'&');\n  }\n\n\n  function toQueryParams(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 (!Object.isArray(hash[key])) hash[key] = [hash[key]];\n          hash[key].push(value);\n        }\n        else hash[key] = value;\n      }\n      return hash;\n    });\n  }\n\n  function toArray() {\n    return this.split('');\n  }\n\n  function succ() {\n    return this.slice(0, this.length - 1) +\n      String.fromCharCode(this.charCodeAt(this.length - 1) + 1);\n  }\n\n  function times(count) {\n    return count < 1 ? '' : new Array(count + 1).join(this);\n  }\n\n  function camelize() {\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  function capitalize() {\n    return this.charAt(0).toUpperCase() + this.substring(1).toLowerCase();\n  }\n\n  function underscore() {\n    return this.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\n  function dasherize() {\n    return this.replace(/_/g, '-');\n  }\n\n  function inspect(useDoubleQuotes) {\n    var escapedString = this.replace(/[\\x00-\\x1f\\\\]/g, function(character) {\n      if (character in String.specialChar) {\n        return String.specialChar[character];\n      }\n      return '\\\\u00' + character.charCodeAt().toPaddedString(2, 16);\n    });\n    if (useDoubleQuotes) return '\"' + escapedString.replace(/\"/g, '\\\\\"') + '\"';\n    return \"'\" + escapedString.replace(/'/g, '\\\\\\'') + \"'\";\n  }\n\n  function toJSON() {\n    return this.inspect(true);\n  }\n\n  function unfilterJSON(filter) {\n    return this.replace(filter || Prototype.JSONFilter, '$1');\n  }\n\n  function isJSON() {\n    var str = this;\n    if (str.blank()) return false;\n    str = this.replace(/\\\\./g, '@').replace(/\"[^\"\\\\\\n\\r]*\"/g, '');\n    return (/^[,:{}\\[\\]0-9.\\-+Eaeflnr-u \\n\\r\\t]*$/).test(str);\n  }\n\n  function evalJSON(sanitize) {\n    var json = this.unfilterJSON();\n    try {\n      if (!sanitize || json.isJSON()) return eval('(' + json + ')');\n    } catch (e) { }\n    throw new SyntaxError('Badly formed JSON string: ' + this.inspect());\n  }\n\n  function include(pattern) {\n    return this.indexOf(pattern) > -1;\n  }\n\n  function startsWith(pattern) {\n    return this.indexOf(pattern) === 0;\n  }\n\n  function endsWith(pattern) {\n    var d = this.length - pattern.length;\n    return d >= 0 && this.lastIndexOf(pattern) === d;\n  }\n\n  function empty() {\n    return this == '';\n  }\n\n  function blank() {\n    return /^\\s*$/.test(this);\n  }\n\n  function interpolate(object, pattern) {\n    return new Template(this, pattern).evaluate(object);\n  }\n\n  return {\n    gsub:           gsub,\n    sub:            sub,\n    scan:           scan,\n    truncate:       truncate,\n    strip:          String.prototype.trim ? String.prototype.trim : strip,\n    stripTags:      stripTags,\n    stripScripts:   stripScripts,\n    extractScripts: extractScripts,\n    evalScripts:    evalScripts,\n    escapeHTML:     escapeHTML,\n    unescapeHTML:   unescapeHTML,\n    toQueryParams:  toQueryParams,\n    parseQuery:     toQueryParams,\n    toArray:        toArray,\n    succ:           succ,\n    times:          times,\n    camelize:       camelize,\n    capitalize:     capitalize,\n    underscore:     underscore,\n    dasherize:      dasherize,\n    inspect:        inspect,\n    toJSON:         toJSON,\n    unfilterJSON:   unfilterJSON,\n    isJSON:         isJSON,\n    evalJSON:       evalJSON,\n    include:        include,\n    startsWith:     startsWith,\n    endsWith:       endsWith,\n    empty:          empty,\n    blank:          blank,\n    interpolate:    interpolate\n  };\n})());\n\nvar Template = Class.create({\n  initialize: function(template, pattern) {\n    this.template = template.toString();\n    this.pattern = pattern || Template.Pattern;\n  },\n\n  evaluate: function(object) {\n    if (object && Object.isFunction(object.toTemplateReplacements))\n      object = object.toTemplateReplacements();\n\n    return this.template.gsub(this.pattern, function(match) {\n      if (object == null) return (match[1] + '');\n\n      var before = match[1] || '';\n      if (before == '\\\\') return match[2];\n\n      var ctx = object, expr = match[3];\n      var pattern = /^([^.[]+|\\[((?:.*?[^\\\\])?)\\])(\\.|\\[|$)/;\n      match = pattern.exec(expr);\n      if (match == null) return before;\n\n      while (match != null) {\n        var comp = match[1].startsWith('[') ? match[2].replace(/\\\\\\\\]/g, ']') : match[1];\n        ctx = ctx[comp];\n        if (null == ctx || '' == match[3]) break;\n        expr = expr.substring('[' == match[3] ? match[1].length : match[0].length);\n        match = pattern.exec(expr);\n      }\n\n      return before + String.interpret(ctx);\n    });\n  }\n});\nTemplate.Pattern = /(^|.|\\r|\\n)(#\\{(.*?)\\})/;\n\nvar $break = { };\n\nvar Enumerable = (function() {\n  function each(iterator, context) {\n    var index = 0;\n    try {\n      this._each(function(value) {\n        iterator.call(context, value, index++);\n      });\n    } catch (e) {\n      if (e != $break) throw e;\n    }\n    return this;\n  }\n\n  function eachSlice(number, iterator, context) {\n    var index = -number, slices = [], array = this.toArray();\n    if (number < 1) return array;\n    while ((index += number) < array.length)\n      slices.push(array.slice(index, index+number));\n    return slices.collect(iterator, context);\n  }\n\n  function all(iterator, context) {\n    iterator = iterator || Prototype.K;\n    var result = true;\n    this.each(function(value, index) {\n      result = result && !!iterator.call(context, value, index);\n      if (!result) throw $break;\n    });\n    return result;\n  }\n\n  function any(iterator, context) {\n    iterator = iterator || Prototype.K;\n    var result = false;\n    this.each(function(value, index) {\n      if (result = !!iterator.call(context, value, index))\n        throw $break;\n    });\n    return result;\n  }\n\n  function collect(iterator, context) {\n    iterator = iterator || Prototype.K;\n    var results = [];\n    this.each(function(value, index) {\n      results.push(iterator.call(context, value, index));\n    });\n    return results;\n  }\n\n  function detect(iterator, context) {\n    var result;\n    this.each(function(value, index) {\n      if (iterator.call(context, value, index)) {\n        result = value;\n        throw $break;\n      }\n    });\n    return result;\n  }\n\n  function findAll(iterator, context) {\n    var results = [];\n    this.each(function(value, index) {\n      if (iterator.call(context, value, index))\n        results.push(value);\n    });\n    return results;\n  }\n\n  function grep(filter, iterator, context) {\n    iterator = iterator || Prototype.K;\n    var results = [];\n\n    if (Object.isString(filter))\n      filter = new RegExp(RegExp.escape(filter));\n\n    this.each(function(value, index) {\n      if (filter.match(value))\n        results.push(iterator.call(context, value, index));\n    });\n    return results;\n  }\n\n  function include(object) {\n    if (Object.isFunction(this.indexOf))\n      if (this.indexOf(object) != -1) return true;\n\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  function inGroupsOf(number, fillWith) {\n    fillWith = Object.isUndefined(fillWith) ? null : fillWith;\n    return this.eachSlice(number, function(slice) {\n      while(slice.length < number) slice.push(fillWith);\n      return slice;\n    });\n  }\n\n  function inject(memo, iterator, context) {\n    this.each(function(value, index) {\n      memo = iterator.call(context, memo, value, index);\n    });\n    return memo;\n  }\n\n  function invoke(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  function max(iterator, context) {\n    iterator = iterator || Prototype.K;\n    var result;\n    this.each(function(value, index) {\n      value = iterator.call(context, value, index);\n      if (result == null || value >= result)\n        result = value;\n    });\n    return result;\n  }\n\n  function min(iterator, context) {\n    iterator = iterator || Prototype.K;\n    var result;\n    this.each(function(value, index) {\n      value = iterator.call(context, value, index);\n      if (result == null || value < result)\n        result = value;\n    });\n    return result;\n  }\n\n  function partition(iterator, context) {\n    iterator = iterator || Prototype.K;\n    var trues = [], falses = [];\n    this.each(function(value, index) {\n      (iterator.call(context, value, index) ?\n        trues : falses).push(value);\n    });\n    return [trues, falses];\n  }\n\n  function pluck(property) {\n    var results = [];\n    this.each(function(value) {\n      results.push(value[property]);\n    });\n    return results;\n  }\n\n  function reject(iterator, context) {\n    var results = [];\n    this.each(function(value, index) {\n      if (!iterator.call(context, value, index))\n        results.push(value);\n    });\n    return results;\n  }\n\n  function sortBy(iterator, context) {\n    return this.map(function(value, index) {\n      return {\n        value: value,\n        criteria: iterator.call(context, value, index)\n      };\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  function toArray() {\n    return this.map();\n  }\n\n  function zip() {\n    var iterator = Prototype.K, args = $A(arguments);\n    if (Object.isFunction(args.last()))\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  function size() {\n    return this.toArray().length;\n  }\n\n  function inspect() {\n    return '#<Enumerable:' + this.toArray().inspect() + '>';\n  }\n\n\n\n\n\n\n\n\n\n  return {\n    each:       each,\n    eachSlice:  eachSlice,\n    all:        all,\n    every:      all,\n    any:        any,\n    some:       any,\n    collect:    collect,\n    map:        collect,\n    detect:     detect,\n    findAll:    findAll,\n    select:     findAll,\n    filter:     findAll,\n    grep:       grep,\n    include:    include,\n    member:     include,\n    inGroupsOf: inGroupsOf,\n    inject:     inject,\n    invoke:     invoke,\n    max:        max,\n    min:        min,\n    partition:  partition,\n    pluck:      pluck,\n    reject:     reject,\n    sortBy:     sortBy,\n    toArray:    toArray,\n    entries:    toArray,\n    zip:        zip,\n    size:       size,\n    inspect:    inspect,\n    find:       detect\n  };\n})();\nfunction $A(iterable) {\n  if (!iterable) return [];\n  if ('toArray' in Object(iterable)) return iterable.toArray();\n  var length = iterable.length || 0, results = new Array(length);\n  while (length--) results[length] = iterable[length];\n  return results;\n}\n\nfunction $w(string) {\n  if (!Object.isString(string)) return [];\n  string = string.strip();\n  return string ? string.split(/\\s+/) : [];\n}\n\nArray.from = $A;\n\n\n(function() {\n  var arrayProto = Array.prototype,\n      slice = arrayProto.slice,\n      _each = arrayProto.forEach; // use native browser JS 1.6 implementation if available\n\n  function each(iterator) {\n    for (var i = 0, length = this.length; i < length; i++)\n      iterator(this[i]);\n  }\n  if (!_each) _each = each;\n\n  function clear() {\n    this.length = 0;\n    return this;\n  }\n\n  function first() {\n    return this[0];\n  }\n\n  function last() {\n    return this[this.length - 1];\n  }\n\n  function compact() {\n    return this.select(function(value) {\n      return value != null;\n    });\n  }\n\n  function flatten() {\n    return this.inject([], function(array, value) {\n      if (Object.isArray(value))\n        return array.concat(value.flatten());\n      array.push(value);\n      return array;\n    });\n  }\n\n  function without() {\n    var values = slice.call(arguments, 0);\n    return this.select(function(value) {\n      return !values.include(value);\n    });\n  }\n\n  function reverse(inline) {\n    return (inline !== false ? this : this.toArray())._reverse();\n  }\n\n  function uniq(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  function intersect(array) {\n    return this.uniq().findAll(function(item) {\n      return array.detect(function(value) { return item === value });\n    });\n  }\n\n\n  function clone() {\n    return slice.call(this, 0);\n  }\n\n  function size() {\n    return this.length;\n  }\n\n  function inspect() {\n    return '[' + this.map(Object.inspect).join(', ') + ']';\n  }\n\n  function toJSON() {\n    var results = [];\n    this.each(function(object) {\n      var value = Object.toJSON(object);\n      if (!Object.isUndefined(value)) results.push(value);\n    });\n    return '[' + results.join(', ') + ']';\n  }\n\n  function indexOf(item, i) {\n    i || (i = 0);\n    var length = this.length;\n    if (i < 0) i = length + i;\n    for (; i < length; i++)\n      if (this[i] === item) return i;\n    return -1;\n  }\n\n  function lastIndexOf(item, i) {\n    i = isNaN(i) ? this.length : (i < 0 ? this.length + i : i) + 1;\n    var n = this.slice(0, i).reverse().indexOf(item);\n    return (n < 0) ? n : i - n - 1;\n  }\n\n  function concat() {\n    var array = slice.call(this, 0), item;\n    for (var i = 0, length = arguments.length; i < length; i++) {\n      item = arguments[i];\n      if (Object.isArray(item) && !('callee' in item)) {\n        for (var j = 0, arrayLength = item.length; j < arrayLength; j++)\n          array.push(item[j]);\n      } else {\n        array.push(item);\n      }\n    }\n    return array;\n  }\n\n  Object.extend(arrayProto, Enumerable);\n\n  if (!arrayProto._reverse)\n    arrayProto._reverse = arrayProto.reverse;\n\n  Object.extend(arrayProto, {\n    _each:     _each,\n    clear:     clear,\n    first:     first,\n    last:      last,\n    compact:   compact,\n    flatten:   flatten,\n    without:   without,\n    reverse:   reverse,\n    uniq:      uniq,\n    intersect: intersect,\n    clone:     clone,\n    toArray:   clone,\n    size:      size,\n    inspect:   inspect,\n    toJSON:    toJSON\n  });\n\n  var CONCAT_ARGUMENTS_BUGGY = (function() {\n    return [].concat(arguments)[0][0] !== 1;\n  })(1,2)\n\n  if (CONCAT_ARGUMENTS_BUGGY) arrayProto.concat = concat;\n\n  if (!arrayProto.indexOf) arrayProto.indexOf = indexOf;\n  if (!arrayProto.lastIndexOf) arrayProto.lastIndexOf = lastIndexOf;\n})();\nfunction $H(object) {\n  return new Hash(object);\n};\n\nvar Hash = Class.create(Enumerable, (function() {\n  function initialize(object) {\n    this._object = Object.isHash(object) ? object.toObject() : Object.clone(object);\n  }\n\n  function _each(iterator) {\n    for (var key in this._object) {\n      var value = this._object[key], pair = [key, value];\n      pair.key = key;\n      pair.value = value;\n      iterator(pair);\n    }\n  }\n\n  function set(key, value) {\n    return this._object[key] = value;\n  }\n\n  function get(key) {\n    if (this._object[key] !== Object.prototype[key])\n      return this._object[key];\n  }\n\n  function unset(key) {\n    var value = this._object[key];\n    delete this._object[key];\n    return value;\n  }\n\n  function toObject() {\n    return Object.clone(this._object);\n  }\n\n  function keys() {\n    return this.pluck('key');\n  }\n\n  function values() {\n    return this.pluck('value');\n  }\n\n  function index(value) {\n    var match = this.detect(function(pair) {\n      return pair.value === value;\n    });\n    return match && match.key;\n  }\n\n  function merge(object) {\n    return this.clone().update(object);\n  }\n\n  function update(object) {\n    return new Hash(object).inject(this, function(result, pair) {\n      result.set(pair.key, pair.value);\n      return result;\n    });\n  }\n\n  function toQueryPair(key, value) {\n    if (Object.isUndefined(value)) return key;\n    return key + '=' + encodeURIComponent(String.interpret(value));\n  }\n\n  function toQueryString() {\n    return this.inject([], function(results, pair) {\n      var key = encodeURIComponent(pair.key), values = pair.value;\n\n      if (values && typeof values == 'object') {\n        if (Object.isArray(values))\n          return results.concat(values.map(toQueryPair.curry(key)));\n      } else results.push(toQueryPair(key, values));\n      return results;\n    }).join('&');\n  }\n\n  function inspect() {\n    return '#<Hash:{' + this.map(function(pair) {\n      return pair.map(Object.inspect).join(': ');\n    }).join(', ') + '}>';\n  }\n\n  function toJSON() {\n    return Object.toJSON(this.toObject());\n  }\n\n  function clone() {\n    return new Hash(this);\n  }\n\n  return {\n    initialize:             initialize,\n    _each:                  _each,\n    set:                    set,\n    get:                    get,\n    unset:                  unset,\n    toObject:               toObject,\n    toTemplateReplacements: toObject,\n    keys:                   keys,\n    values:                 values,\n    index:                  index,\n    merge:                  merge,\n    update:                 update,\n    toQueryString:          toQueryString,\n    inspect:                inspect,\n    toJSON:                 toJSON,\n    clone:                  clone\n  };\n})());\n\nHash.from = $H;\nObject.extend(Number.prototype, (function() {\n  function toColorPart() {\n    return this.toPaddedString(2, 16);\n  }\n\n  function succ() {\n    return this + 1;\n  }\n\n  function times(iterator, context) {\n    $R(0, this, true).each(iterator, context);\n    return this;\n  }\n\n  function toPaddedString(length, radix) {\n    var string = this.toString(radix || 10);\n    return '0'.times(length - string.length) + string;\n  }\n\n  function toJSON() {\n    return isFinite(this) ? this.toString() : 'null';\n  }\n\n  function abs() {\n    return Math.abs(this);\n  }\n\n  function round() {\n    return Math.round(this);\n  }\n\n  function ceil() {\n    return Math.ceil(this);\n  }\n\n  function floor() {\n    return Math.floor(this);\n  }\n\n  return {\n    toColorPart:    toColorPart,\n    succ:           succ,\n    times:          times,\n    toPaddedString: toPaddedString,\n    toJSON:         toJSON,\n    abs:            abs,\n    round:          round,\n    ceil:           ceil,\n    floor:          floor\n  };\n})());\n\nfunction $R(start, end, exclusive) {\n  return new ObjectRange(start, end, exclusive);\n}\n\nvar ObjectRange = Class.create(Enumerable, (function() {\n  function initialize(start, end, exclusive) {\n    this.start = start;\n    this.end = end;\n    this.exclusive = exclusive;\n  }\n\n  function _each(iterator) {\n    var value = this.start;\n    while (this.include(value)) {\n      iterator(value);\n      value = value.succ();\n    }\n  }\n\n  function include(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  return {\n    initialize: initialize,\n    _each:      _each,\n    include:    include\n  };\n})());\n\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 (Object.isFunction(responder[callback])) {\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() { Ajax.activeRequestCount++ },\n  onComplete: function() { Ajax.activeRequestCount-- }\n});\nAjax.Base = Class.create({\n  initialize: 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      evalJSON:     true,\n      evalJS:       true\n    };\n    Object.extend(this.options, options || { });\n\n    this.options.method = this.options.method.toLowerCase();\n\n    if (Object.isString(this.options.parameters))\n      this.options.parameters = this.options.parameters.toQueryParams();\n    else if (Object.isHash(this.options.parameters))\n      this.options.parameters = this.options.parameters.toObject();\n  }\n});\nAjax.Request = Class.create(Ajax.Base, {\n  _complete: false,\n\n  initialize: function($super, url, options) {\n    $super(options);\n    this.transport = Ajax.getTransport();\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      params['_method'] = this.method;\n      this.method = 'post';\n    }\n\n    this.parameters = params;\n\n    if (params = Object.toQueryString(params)) {\n      if (this.method == 'get')\n        this.url += (this.url.include('?') ? '&' : '?') + params;\n      else if (/Konqueror|Safari|KHTML/.test(navigator.userAgent))\n        params += '&_=';\n    }\n\n    try {\n      var response = new Ajax.Response(this);\n      if (this.options.onCreate) this.options.onCreate(response);\n      Ajax.Responders.dispatch('onCreate', this, response);\n\n      this.transport.open(this.method.toUpperCase(), this.url,\n        this.options.asynchronous);\n\n      if (this.options.asynchronous) this.respondToReadyState.bind(this).defer(1);\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    if (typeof this.options.requestHeaders == 'object') {\n      var extras = this.options.requestHeaders;\n\n      if (Object.isFunction(extras.push))\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    var status = this.getStatus();\n    return !status || (status >= 200 && status < 300);\n  },\n\n  getStatus: function() {\n    try {\n      return this.transport.status || 0;\n    } catch (e) { return 0 }\n  },\n\n  respondToReadyState: function(readyState) {\n    var state = Ajax.Request.Events[readyState], response = new Ajax.Response(this);\n\n    if (state == 'Complete') {\n      try {\n        this._complete = true;\n        (this.options['on' + response.status]\n         || this.options['on' + (this.success() ? 'Success' : 'Failure')]\n         || Prototype.emptyFunction)(response, response.headerJSON);\n      } catch (e) {\n        this.dispatchException(e);\n      }\n\n      var contentType = response.getHeader('Content-type');\n      if (this.options.evalJS == 'force'\n          || (this.options.evalJS && this.isSameOrigin() && contentType\n          && contentType.match(/^\\s*(text|application)\\/(x-)?(java|ecma)script(;.*)?\\s*$/i)))\n        this.evalResponse();\n    }\n\n    try {\n      (this.options['on' + state] || Prototype.emptyFunction)(response, response.headerJSON);\n      Ajax.Responders.dispatch('on' + state, this, response, response.headerJSON);\n    } catch (e) {\n      this.dispatchException(e);\n    }\n\n    if (state == 'Complete') {\n      this.transport.onreadystatechange = Prototype.emptyFunction;\n    }\n  },\n\n  isSameOrigin: function() {\n    var m = this.url.match(/^\\s*https?:\\/\\/[^\\/]*/);\n    return !m || (m[0] == '#{protocol}//#{domain}#{port}'.interpolate({\n      protocol: location.protocol,\n      domain: document.domain,\n      port: location.port ? ':' + location.port : ''\n    }));\n  },\n\n  getHeader: function(name) {\n    try {\n      return this.transport.getResponseHeader(name) || 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.Request.Events =\n  ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete'];\n\n\n\n\n\n\n\n\nAjax.Response = Class.create({\n  initialize: function(request){\n    this.request = request;\n    var transport  = this.transport  = request.transport,\n        readyState = this.readyState = transport.readyState;\n\n    if((readyState > 2 && !Prototype.Browser.IE) || readyState == 4) {\n      this.status       = this.getStatus();\n      this.statusText   = this.getStatusText();\n      this.responseText = String.interpret(transport.responseText);\n      this.headerJSON   = this._getHeaderJSON();\n    }\n\n    if(readyState == 4) {\n      var xml = transport.responseXML;\n      this.responseXML  = Object.isUndefined(xml) ? null : xml;\n      this.responseJSON = this._getResponseJSON();\n    }\n  },\n\n  status:      0,\n\n  statusText: '',\n\n  getStatus: Ajax.Request.prototype.getStatus,\n\n  getStatusText: function() {\n    try {\n      return this.transport.statusText || '';\n    } catch (e) { return '' }\n  },\n\n  getHeader: Ajax.Request.prototype.getHeader,\n\n  getAllHeaders: function() {\n    try {\n      return this.getAllResponseHeaders();\n    } catch (e) { return null }\n  },\n\n  getResponseHeader: function(name) {\n    return this.transport.getResponseHeader(name);\n  },\n\n  getAllResponseHeaders: function() {\n    return this.transport.getAllResponseHeaders();\n  },\n\n  _getHeaderJSON: function() {\n    var json = this.getHeader('X-JSON');\n    if (!json) return null;\n    json = decodeURIComponent(escape(json));\n    try {\n      return json.evalJSON(this.request.options.sanitizeJSON ||\n        !this.request.isSameOrigin());\n    } catch (e) {\n      this.request.dispatchException(e);\n    }\n  },\n\n  _getResponseJSON: function() {\n    var options = this.request.options;\n    if (!options.evalJSON || (options.evalJSON != 'force' &&\n      !(this.getHeader('Content-type') || '').include('application/json')) ||\n        this.responseText.blank())\n          return null;\n    try {\n      return this.responseText.evalJSON(options.sanitizeJSON ||\n        !this.request.isSameOrigin());\n    } catch (e) {\n      this.request.dispatchException(e);\n    }\n  }\n});\n\nAjax.Updater = Class.create(Ajax.Request, {\n  initialize: function($super, container, url, options) {\n    this.container = {\n      success: (container.success || container),\n      failure: (container.failure || (container.success ? null : container))\n    };\n\n    options = Object.clone(options);\n    var onComplete = options.onComplete;\n    options.onComplete = (function(response, json) {\n      this.updateContent(response.responseText);\n      if (Object.isFunction(onComplete)) onComplete(response, json);\n    }).bind(this);\n\n    $super(url, options);\n  },\n\n  updateContent: function(responseText) {\n    var receiver = this.container[this.success() ? 'success' : 'failure'],\n        options = this.options;\n\n    if (!options.evalScripts) responseText = responseText.stripScripts();\n\n    if (receiver = $(receiver)) {\n      if (options.insertion) {\n        if (Object.isString(options.insertion)) {\n          var insertion = { }; insertion[options.insertion] = responseText;\n          receiver.insert(insertion);\n        }\n        else options.insertion(receiver, responseText);\n      }\n      else receiver.update(responseText);\n    }\n  }\n});\n\nAjax.PeriodicalUpdater = Class.create(Ajax.Base, {\n  initialize: function($super, container, url, options) {\n    $super(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(response) {\n    if (this.options.decay) {\n      this.decay = (response.responseText == this.lastText ?\n        this.decay * this.options.decay : 1);\n\n      this.lastText = response.responseText;\n    }\n    this.timer = this.onTimerEvent.bind(this).delay(this.decay * this.frequency);\n  },\n\n  onTimerEvent: function() {\n    this.updater = new Ajax.Updater(this.container, this.url, this.options);\n  }\n});\n\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 (Object.isString(element))\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(Element.extend(query.snapshotItem(i)));\n    return results;\n  };\n}\n\n/*--------------------------------------------------------------------------*/\n\nif (!window.Node) var Node = { };\n\nif (!Node.ELEMENT_NODE) {\n  Object.extend(Node, {\n    ELEMENT_NODE: 1,\n    ATTRIBUTE_NODE: 2,\n    TEXT_NODE: 3,\n    CDATA_SECTION_NODE: 4,\n    ENTITY_REFERENCE_NODE: 5,\n    ENTITY_NODE: 6,\n    PROCESSING_INSTRUCTION_NODE: 7,\n    COMMENT_NODE: 8,\n    DOCUMENT_NODE: 9,\n    DOCUMENT_TYPE_NODE: 10,\n    DOCUMENT_FRAGMENT_NODE: 11,\n    NOTATION_NODE: 12\n  });\n}\n\n\n(function(global) {\n\n  var SETATTRIBUTE_IGNORES_NAME = (function(){\n    var elForm = document.createElement(\"form\");\n    var elInput = document.createElement(\"input\");\n    var root = document.documentElement;\n    elInput.setAttribute(\"name\", \"test\");\n    elForm.appendChild(elInput);\n    root.appendChild(elForm);\n    var isBuggy = elForm.elements\n      ? (typeof elForm.elements.test == \"undefined\")\n      : null;\n    root.removeChild(elForm);\n    elForm = elInput = null;\n    return isBuggy;\n  })();\n\n  var element = global.Element;\n  global.Element = function(tagName, attributes) {\n    attributes = attributes || { };\n    tagName = tagName.toLowerCase();\n    var cache = Element.cache;\n    if (SETATTRIBUTE_IGNORES_NAME && attributes.name) {\n      tagName = '<' + tagName + ' name=\"' + attributes.name + '\">';\n      delete attributes.name;\n      return Element.writeAttribute(document.createElement(tagName), attributes);\n    }\n    if (!cache[tagName]) cache[tagName] = Element.extend(document.createElement(tagName));\n    return Element.writeAttribute(cache[tagName].cloneNode(false), attributes);\n  };\n  Object.extend(global.Element, element || { });\n  if (element) global.Element.prototype = element.prototype;\n})(this);\n\nElement.cache = { };\nElement.idCounter = 1;\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\n  hide: function(element) {\n    element = $(element);\n    element.style.display = 'none';\n    return element;\n  },\n\n  show: function(element) {\n    element = $(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(){\n\n    var SELECT_ELEMENT_INNERHTML_BUGGY = (function(){\n      var el = document.createElement(\"select\"),\n          isBuggy = true;\n      el.innerHTML = \"<option value=\\\"test\\\">test</option>\";\n      if (el.options && el.options[0]) {\n        isBuggy = el.options[0].nodeName.toUpperCase() !== \"OPTION\";\n      }\n      el = null;\n      return isBuggy;\n    })();\n\n    var TABLE_ELEMENT_INNERHTML_BUGGY = (function(){\n      try {\n        var el = document.createElement(\"table\");\n        if (el && el.tBodies) {\n          el.innerHTML = \"<tbody><tr><td>test</td></tr></tbody>\";\n          var isBuggy = typeof el.tBodies[0] == \"undefined\";\n          el = null;\n          return isBuggy;\n        }\n      } catch (e) {\n        return true;\n      }\n    })();\n\n    var SCRIPT_ELEMENT_REJECTS_TEXTNODE_APPENDING = (function () {\n      var s = document.createElement(\"script\"),\n          isBuggy = false;\n      try {\n        s.appendChild(document.createTextNode(\"\"));\n        isBuggy = !s.firstChild ||\n          s.firstChild && s.firstChild.nodeType !== 3;\n      } catch (e) {\n        isBuggy = true;\n      }\n      s = null;\n      return isBuggy;\n    })();\n\n    function update(element, content) {\n      element = $(element);\n\n      if (content && content.toElement)\n        content = content.toElement();\n\n      if (Object.isElement(content))\n        return element.update().insert(content);\n\n      content = Object.toHTML(content);\n\n      var tagName = element.tagName.toUpperCase();\n\n      if (tagName === 'SCRIPT' && SCRIPT_ELEMENT_REJECTS_TEXTNODE_APPENDING) {\n        element.text = content;\n        return element;\n      }\n\n      if (SELECT_ELEMENT_INNERHTML_BUGGY || TABLE_ELEMENT_INNERHTML_BUGGY) {\n        if (tagName in Element._insertionTranslations.tags) {\n          while (element.firstChild) {\n            element.removeChild(element.firstChild);\n          }\n          Element._getContentFromAnonymousElement(tagName, content.stripScripts())\n            .each(function(node) {\n              element.appendChild(node)\n            });\n        }\n        else {\n          element.innerHTML = content.stripScripts();\n        }\n      }\n      else {\n        element.innerHTML = content.stripScripts();\n      }\n\n      content.evalScripts.bind(content).defer();\n      return element;\n    }\n\n    return update;\n  })(),\n\n  replace: function(element, content) {\n    element = $(element);\n    if (content && content.toElement) content = content.toElement();\n    else if (!Object.isElement(content)) {\n      content = Object.toHTML(content);\n      var range = element.ownerDocument.createRange();\n      range.selectNode(element);\n      content.evalScripts.bind(content).defer();\n      content = range.createContextualFragment(content.stripScripts());\n    }\n    element.parentNode.replaceChild(content, element);\n    return element;\n  },\n\n  insert: function(element, insertions) {\n    element = $(element);\n\n    if (Object.isString(insertions) || Object.isNumber(insertions) ||\n        Object.isElement(insertions) || (insertions && (insertions.toElement || insertions.toHTML)))\n          insertions = {bottom:insertions};\n\n    var content, insert, tagName, childNodes;\n\n    for (var position in insertions) {\n      content  = insertions[position];\n      position = position.toLowerCase();\n      insert = Element._insertionTranslations[position];\n\n      if (content && content.toElement) content = content.toElement();\n      if (Object.isElement(content)) {\n        insert(element, content);\n        continue;\n      }\n\n      content = Object.toHTML(content);\n\n      tagName = ((position == 'before' || position == 'after')\n        ? element.parentNode : element).tagName.toUpperCase();\n\n      childNodes = Element._getContentFromAnonymousElement(tagName, content.stripScripts());\n\n      if (position == 'top' || position == 'after') childNodes.reverse();\n      childNodes.each(insert.curry(element));\n\n      content.evalScripts.bind(content).defer();\n    }\n\n    return element;\n  },\n\n  wrap: function(element, wrapper, attributes) {\n    element = $(element);\n    if (Object.isElement(wrapper))\n      $(wrapper).writeAttribute(attributes || { });\n    else if (Object.isString(wrapper)) wrapper = new Element(wrapper, attributes);\n    else wrapper = new Element('div', wrapper);\n    if (element.parentNode)\n      element.parentNode.replaceChild(wrapper, element);\n    wrapper.appendChild(element);\n    return wrapper;\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(element, 'parentNode');\n  },\n\n  descendants: function(element) {\n    return Element.select(element, \"*\");\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(element, 'previousSibling');\n  },\n\n  nextSiblings: function(element) {\n    return Element.recursivelyCollect(element, 'nextSibling');\n  },\n\n  siblings: function(element) {\n    element = $(element);\n    return Element.previousSiblings(element).reverse()\n      .concat(Element.nextSiblings(element));\n  },\n\n  match: function(element, selector) {\n    if (Object.isString(selector))\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(element);\n    return Object.isNumber(expression) ? ancestors[expression] :\n      Selector.findElement(ancestors, expression, index);\n  },\n\n  down: function(element, expression, index) {\n    element = $(element);\n    if (arguments.length == 1) return Element.firstDescendant(element);\n    return Object.isNumber(expression) ? Element.descendants(element)[expression] :\n      Element.select(element, expression)[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(element);\n    return Object.isNumber(expression) ? previousSiblings[expression] :\n      Selector.findElement(previousSiblings, expression, index);\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(element);\n    return Object.isNumber(expression) ? nextSiblings[expression] :\n      Selector.findElement(nextSiblings, expression, index);\n  },\n\n\n  select: function(element) {\n    var args = Array.prototype.slice.call(arguments, 1);\n    return Selector.findChildElements(element, args);\n  },\n\n  adjacent: function(element) {\n    var args = Array.prototype.slice.call(arguments, 1);\n    return Selector.findChildElements(element.parentNode, args).without(element);\n  },\n\n  identify: function(element) {\n    element = $(element);\n    var id = Element.readAttribute(element, 'id');\n    if (id) return id;\n    do { id = 'anonymous_element_' + Element.idCounter++ } while ($(id));\n    Element.writeAttribute(element, 'id', id);\n    return id;\n  },\n\n  readAttribute: function(element, name) {\n    element = $(element);\n    if (Prototype.Browser.IE) {\n      var t = Element._attributeTranslations.read;\n      if (t.values[name]) return t.values[name](element, name);\n      if (t.names[name]) name = t.names[name];\n      if (name.include(':')) {\n        return (!element.attributes || !element.attributes[name]) ? null :\n         element.attributes[name].value;\n      }\n    }\n    return element.getAttribute(name);\n  },\n\n  writeAttribute: function(element, name, value) {\n    element = $(element);\n    var attributes = { }, t = Element._attributeTranslations.write;\n\n    if (typeof name == 'object') attributes = name;\n    else attributes[name] = Object.isUndefined(value) ? true : value;\n\n    for (var attr in attributes) {\n      name = t.names[attr] || attr;\n      value = attributes[attr];\n      if (t.values[attr]) name = t.values[attr](element, value);\n      if (value === false || value === null)\n        element.removeAttribute(name);\n      else if (value === true)\n        element.setAttribute(name, name);\n      else element.setAttribute(name, value);\n    }\n    return element;\n  },\n\n  getHeight: function(element) {\n    return Element.getDimensions(element).height;\n  },\n\n  getWidth: function(element) {\n    return Element.getDimensions(element).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    return (elementClassName.length > 0 && (elementClassName == className ||\n      new RegExp(\"(^|\\\\s)\" + className + \"(\\\\s|$)\").test(elementClassName)));\n  },\n\n  addClassName: function(element, className) {\n    if (!(element = $(element))) return;\n    if (!Element.hasClassName(element, className))\n      element.className += (element.className ? ' ' : '') + className;\n    return element;\n  },\n\n  removeClassName: function(element, className) {\n    if (!(element = $(element))) return;\n    element.className = element.className.replace(\n      new RegExp(\"(^|\\\\s+)\" + className + \"(\\\\s+|$)\"), ' ').strip();\n    return element;\n  },\n\n  toggleClassName: function(element, className) {\n    if (!(element = $(element))) return;\n    return Element[Element.hasClassName(element, className) ?\n      'removeClassName' : 'addClassName'](element, className);\n  },\n\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\n    if (element.compareDocumentPosition)\n      return (element.compareDocumentPosition(ancestor) & 8) === 8;\n\n    if (ancestor.contains)\n      return ancestor.contains(element) && ancestor !== element;\n\n    while (element = element.parentNode)\n      if (element == ancestor) return true;\n\n    return false;\n  },\n\n  scrollTo: function(element) {\n    element = $(element);\n    var pos = Element.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 || value == 'auto') {\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) {\n    element = $(element);\n    var elementStyle = element.style, match;\n    if (Object.isString(styles)) {\n      element.style.cssText += ';' + styles;\n      return styles.include('opacity') ?\n        element.setOpacity(styles.match(/opacity:\\s*(\\d?\\.?\\d*)/)[1]) : element;\n    }\n    for (var property in styles)\n      if (property == 'opacity') element.setOpacity(styles[property]);\n      else\n        elementStyle[(property == 'float' || property == 'cssFloat') ?\n          (Object.isUndefined(elementStyle.styleFloat) ? 'cssFloat' : 'styleFloat') :\n            property] = 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(element, 'display');\n    if (display != 'none' && display != null) // Safari bug\n      return {width: element.offsetWidth, height: element.offsetHeight};\n\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    if (originalPosition != 'fixed') // Switching fixed to absolute causes issues in Safari\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      if (Prototype.Browser.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.getStyle(element, 'overflow') || 'auto';\n    if (element._overflow !== '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  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 Element._returnOffset(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.toUpperCase() == 'BODY') break;\n        var p = Element.getStyle(element, 'position');\n        if (p !== 'static') break;\n      }\n    } while (element);\n    return Element._returnOffset(valueL, valueT);\n  },\n\n  absolutize: function(element) {\n    element = $(element);\n    if (Element.getStyle(element, 'position') == 'absolute') return element;\n\n    var offsets = Element.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    return element;\n  },\n\n  relativize: function(element) {\n    element = $(element);\n    if (Element.getStyle(element, 'position') == 'relative') return element;\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    return element;\n  },\n\n  cumulativeScrollOffset: 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 Element._returnOffset(valueL, valueT);\n  },\n\n  getOffsetParent: 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  viewportOffset: 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      if (element.offsetParent == document.body &&\n        Element.getStyle(element, 'position') == 'absolute') break;\n\n    } while (element = element.offsetParent);\n\n    element = forElement;\n    do {\n      if (!Prototype.Browser.Opera || (element.tagName && (element.tagName.toUpperCase() == 'BODY'))) {\n        valueT -= element.scrollTop  || 0;\n        valueL -= element.scrollLeft || 0;\n      }\n    } while (element = element.parentNode);\n\n    return Element._returnOffset(valueL, valueT);\n  },\n\n  clonePosition: function(element, source) {\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    source = $(source);\n    var p = Element.viewportOffset(source);\n\n    element = $(element);\n    var delta = [0, 0];\n    var parent = null;\n    if (Element.getStyle(element, 'position') == 'absolute') {\n      parent = Element.getOffsetParent(element);\n      delta = Element.viewportOffset(parent);\n    }\n\n    if (parent == document.body) {\n      delta[0] -= document.body.offsetLeft;\n      delta[1] -= document.body.offsetTop;\n    }\n\n    if (options.setLeft)   element.style.left  = (p[0] - delta[0] + options.offsetLeft) + 'px';\n    if (options.setTop)    element.style.top   = (p[1] - delta[1] + options.offsetTop) + 'px';\n    if (options.setWidth)  element.style.width = source.offsetWidth + 'px';\n    if (options.setHeight) element.style.height = source.offsetHeight + 'px';\n    return element;\n  }\n};\n\nObject.extend(Element.Methods, {\n  getElementsBySelector: Element.Methods.select,\n\n  childElements: Element.Methods.immediateDescendants\n});\n\nElement._attributeTranslations = {\n  write: {\n    names: {\n      className: 'class',\n      htmlFor:   'for'\n    },\n    values: { }\n  }\n};\n\nif (Prototype.Browser.Opera) {\n  Element.Methods.getStyle = Element.Methods.getStyle.wrap(\n    function(proceed, element, style) {\n      switch (style) {\n        case 'left': case 'top': case 'right': case 'bottom':\n          if (proceed(element, 'position') === 'static') return null;\n        case 'height': case 'width':\n          if (!Element.visible(element)) return null;\n\n          var dim = parseInt(proceed(element, style), 10);\n\n          if (dim !== element['offset' + style.capitalize()])\n            return dim + 'px';\n\n          var properties;\n          if (style === 'height') {\n            properties = ['border-top-width', 'padding-top',\n             'padding-bottom', 'border-bottom-width'];\n          }\n          else {\n            properties = ['border-left-width', 'padding-left',\n             'padding-right', 'border-right-width'];\n          }\n          return properties.inject(dim, function(memo, property) {\n            var val = proceed(element, property);\n            return val === null ? memo : memo - parseInt(val, 10);\n          }) + 'px';\n        default: return proceed(element, style);\n      }\n    }\n  );\n\n  Element.Methods.readAttribute = Element.Methods.readAttribute.wrap(\n    function(proceed, element, attribute) {\n      if (attribute === 'title') return element.title;\n      return proceed(element, attribute);\n    }\n  );\n}\n\nelse if (Prototype.Browser.IE) {\n  Element.Methods.getOffsetParent = Element.Methods.getOffsetParent.wrap(\n    function(proceed, element) {\n      element = $(element);\n      try { element.offsetParent }\n      catch(e) { return $(document.body) }\n      var position = element.getStyle('position');\n      if (position !== 'static') return proceed(element);\n      element.setStyle({ position: 'relative' });\n      var value = proceed(element);\n      element.setStyle({ position: position });\n      return value;\n    }\n  );\n\n  $w('positionedOffset viewportOffset').each(function(method) {\n    Element.Methods[method] = Element.Methods[method].wrap(\n      function(proceed, element) {\n        element = $(element);\n        try { element.offsetParent }\n        catch(e) { return Element._returnOffset(0,0) }\n        var position = element.getStyle('position');\n        if (position !== 'static') return proceed(element);\n        var offsetParent = element.getOffsetParent();\n        if (offsetParent && offsetParent.getStyle('position') === 'fixed')\n          offsetParent.setStyle({ zoom: 1 });\n        element.setStyle({ position: 'relative' });\n        var value = proceed(element);\n        element.setStyle({ position: position });\n        return value;\n      }\n    );\n  });\n\n  Element.Methods.cumulativeOffset = Element.Methods.cumulativeOffset.wrap(\n    function(proceed, element) {\n      try { element.offsetParent }\n      catch(e) { return Element._returnOffset(0,0) }\n      return proceed(element);\n    }\n  );\n\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    function stripAlpha(filter){\n      return filter.replace(/alpha\\([^\\)]*\\)/gi,'');\n    }\n    element = $(element);\n    var currentStyle = element.currentStyle;\n    if ((currentStyle && !currentStyle.hasLayout) ||\n      (!currentStyle && element.style.zoom == 'normal'))\n        element.style.zoom = 1;\n\n    var filter = element.getStyle('filter'), style = element.style;\n    if (value == 1 || value === '') {\n      (filter = stripAlpha(filter)) ?\n        style.filter = filter : style.removeAttribute('filter');\n      return element;\n    } else if (value < 0.00001) value = 0;\n    style.filter = stripAlpha(filter) +\n      'alpha(opacity=' + (value * 100) + ')';\n    return element;\n  };\n\n  Element._attributeTranslations = (function(){\n\n    var classProp = 'className';\n    var forProp = 'for';\n\n    var el = document.createElement('div');\n\n    el.setAttribute(classProp, 'x');\n\n    if (el.className !== 'x') {\n      el.setAttribute('class', 'x');\n      if (el.className === 'x') {\n        classProp = 'class';\n      }\n    }\n    el = null;\n\n    el = document.createElement('label');\n    el.setAttribute(forProp, 'x');\n    if (el.htmlFor !== 'x') {\n      el.setAttribute('htmlFor', 'x');\n      if (el.htmlFor === 'x') {\n        forProp = 'htmlFor';\n      }\n    }\n    el = null;\n\n    return {\n      read: {\n        names: {\n          'class':      classProp,\n          'className':  classProp,\n          'for':        forProp,\n          'htmlFor':    forProp\n        },\n        values: {\n          _getAttr: function(element, attribute) {\n            return element.getAttribute(attribute);\n          },\n          _getAttr2: function(element, attribute) {\n            return element.getAttribute(attribute, 2);\n          },\n          _getAttrNode: function(element, attribute) {\n            var node = element.getAttributeNode(attribute);\n            return node ? node.value : \"\";\n          },\n          _getEv: (function(){\n\n            var el = document.createElement('div');\n            el.onclick = Prototype.emptyFunction;\n            var value = el.getAttribute('onclick');\n            var f;\n\n            if (String(value).indexOf('{') > -1) {\n              f = function(element, attribute) {\n                attribute = element.getAttribute(attribute);\n                if (!attribute) return null;\n                attribute = attribute.toString();\n                attribute = attribute.split('{')[1];\n                attribute = attribute.split('}')[0];\n                return attribute.strip();\n              };\n            }\n            else if (value === '') {\n              f = function(element, attribute) {\n                attribute = element.getAttribute(attribute);\n                if (!attribute) return null;\n                return attribute.strip();\n              };\n            }\n            el = null;\n            return f;\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            return element.title;\n          }\n        }\n      }\n    }\n  })();\n\n  Element._attributeTranslations.write = {\n    names: Object.extend({\n      cellpadding: 'cellPadding',\n      cellspacing: 'cellSpacing'\n    }, Element._attributeTranslations.read.names),\n    values: {\n      checked: function(element, value) {\n        element.checked = !!value;\n      },\n\n      style: function(element, value) {\n        element.style.cssText = value ? value : '';\n      }\n    }\n  };\n\n  Element._attributeTranslations.has = {};\n\n  $w('colSpan rowSpan vAlign dateTime accessKey tabIndex ' +\n      'encType maxLength readOnly longDesc frameBorder').each(function(attr) {\n    Element._attributeTranslations.write.names[attr.toLowerCase()] = attr;\n    Element._attributeTranslations.has[attr.toLowerCase()] = attr;\n  });\n\n  (function(v) {\n    Object.extend(v, {\n      href:        v._getAttr2,\n      src:         v._getAttr2,\n      type:        v._getAttr,\n      action:      v._getAttrNode,\n      disabled:    v._flag,\n      checked:     v._flag,\n      readonly:    v._flag,\n      multiple:    v._flag,\n      onload:      v._getEv,\n      onunload:    v._getEv,\n      onclick:     v._getEv,\n      ondblclick:  v._getEv,\n      onmousedown: v._getEv,\n      onmouseup:   v._getEv,\n      onmouseover: v._getEv,\n      onmousemove: v._getEv,\n      onmouseout:  v._getEv,\n      onfocus:     v._getEv,\n      onblur:      v._getEv,\n      onkeypress:  v._getEv,\n      onkeydown:   v._getEv,\n      onkeyup:     v._getEv,\n      onsubmit:    v._getEv,\n      onreset:     v._getEv,\n      onselect:    v._getEv,\n      onchange:    v._getEv\n    });\n  })(Element._attributeTranslations.read.values);\n\n  if (Prototype.BrowserFeatures.ElementExtensions) {\n    (function() {\n      function _descendants(element) {\n        var nodes = element.getElementsByTagName('*'), results = [];\n        for (var i = 0, node; node = nodes[i]; i++)\n          if (node.tagName !== \"!\") // Filter out comment nodes.\n            results.push(node);\n        return results;\n      }\n\n      Element.Methods.down = function(element, expression, index) {\n        element = $(element);\n        if (arguments.length == 1) return element.firstDescendant();\n        return Object.isNumber(expression) ? _descendants(element)[expression] :\n          Element.select(element, expression)[index || 0];\n      }\n    })();\n  }\n\n}\n\nelse if (Prototype.Browser.Gecko && /rv:1\\.8\\.0/.test(navigator.userAgent)) {\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\nelse if (Prototype.Browser.WebKit) {\n  Element.Methods.setOpacity = function(element, value) {\n    element = $(element);\n    element.style.opacity = (value == 1 || value === '') ? '' :\n      (value < 0.00001) ? 0 : value;\n\n    if (value == 1)\n      if(element.tagName.toUpperCase() == 'IMG' && element.width) {\n        element.width++; element.width--;\n      } else try {\n        var n = document.createTextNode(' ');\n        element.appendChild(n);\n        element.removeChild(n);\n      } catch (e) { }\n\n    return element;\n  };\n\n  Element.Methods.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 Element._returnOffset(valueL, valueT);\n  };\n}\n\nif ('outerHTML' in document.documentElement) {\n  Element.Methods.replace = function(element, content) {\n    element = $(element);\n\n    if (content && content.toElement) content = content.toElement();\n    if (Object.isElement(content)) {\n      element.parentNode.replaceChild(content, element);\n      return element;\n    }\n\n    content = Object.toHTML(content);\n    var parent = element.parentNode, tagName = parent.tagName.toUpperCase();\n\n    if (Element._insertionTranslations.tags[tagName]) {\n      var nextSibling = element.next();\n      var fragments = Element._getContentFromAnonymousElement(tagName, content.stripScripts());\n      parent.removeChild(element);\n      if (nextSibling)\n        fragments.each(function(node) { parent.insertBefore(node, nextSibling) });\n      else\n        fragments.each(function(node) { parent.appendChild(node) });\n    }\n    else element.outerHTML = content.stripScripts();\n\n    content.evalScripts.bind(content).defer();\n    return element;\n  };\n}\n\nElement._returnOffset = function(l, t) {\n  var result = [l, t];\n  result.left = l;\n  result.top = t;\n  return result;\n};\n\nElement._getContentFromAnonymousElement = function(tagName, html) {\n  var div = new Element('div'), t = Element._insertionTranslations.tags[tagName];\n  if (t) {\n    div.innerHTML = t[0] + html + t[1];\n    t[2].times(function() { div = div.firstChild });\n  } else div.innerHTML = html;\n  return $A(div.childNodes);\n};\n\nElement._insertionTranslations = {\n  before: function(element, node) {\n    element.parentNode.insertBefore(node, element);\n  },\n  top: function(element, node) {\n    element.insertBefore(node, element.firstChild);\n  },\n  bottom: function(element, node) {\n    element.appendChild(node);\n  },\n  after: function(element, node) {\n    element.parentNode.insertBefore(node, element.nextSibling);\n  },\n  tags: {\n    TABLE:  ['<table>',                '</table>',                   1],\n    TBODY:  ['<table><tbody>',         '</tbody></table>',           2],\n    TR:     ['<table><tbody><tr>',     '</tr></tbody></table>',      3],\n    TD:     ['<table><tbody><tr><td>', '</td></tr></tbody></table>', 4],\n    SELECT: ['<select>',               '</select>',                  1]\n  }\n};\n\n(function() {\n  var tags = Element._insertionTranslations.tags;\n  Object.extend(tags, {\n    THEAD: tags.TBODY,\n    TFOOT: tags.TBODY,\n    TH:    tags.TD\n  });\n})();\n\nElement.Methods.Simulated = {\n  hasAttribute: function(element, attribute) {\n    attribute = Element._attributeTranslations.has[attribute] || attribute;\n    var node = $(element).getAttributeNode(attribute);\n    return !!(node && node.specified);\n  }\n};\n\nElement.Methods.ByTag = { };\n\nObject.extend(Element, Element.Methods);\n\n(function(div) {\n\n  if (!Prototype.BrowserFeatures.ElementExtensions && div['__proto__']) {\n    window.HTMLElement = { };\n    window.HTMLElement.prototype = div['__proto__'];\n    Prototype.BrowserFeatures.ElementExtensions = true;\n  }\n\n  div = null;\n\n})(document.createElement('div'))\n\nElement.extend = (function() {\n\n  function checkDeficiency(tagName) {\n    if (typeof window.Element != 'undefined') {\n      var proto = window.Element.prototype;\n      if (proto) {\n        var id = '_' + (Math.random()+'').slice(2);\n        var el = document.createElement(tagName);\n        proto[id] = 'x';\n        var isBuggy = (el[id] !== 'x');\n        delete proto[id];\n        el = null;\n        return isBuggy;\n      }\n    }\n    return false;\n  }\n\n  function extendElementWith(element, methods) {\n    for (var property in methods) {\n      var value = methods[property];\n      if (Object.isFunction(value) && !(property in element))\n        element[property] = value.methodize();\n    }\n  }\n\n  var HTMLOBJECTELEMENT_PROTOTYPE_BUGGY = checkDeficiency('object');\n\n  if (Prototype.BrowserFeatures.SpecificElementExtensions) {\n    if (HTMLOBJECTELEMENT_PROTOTYPE_BUGGY) {\n      return function(element) {\n        if (element && typeof element._extendedByPrototype == 'undefined') {\n          var t = element.tagName;\n          if (t && (/^(?:object|applet|embed)$/i.test(t))) {\n            extendElementWith(element, Element.Methods);\n            extendElementWith(element, Element.Methods.Simulated);\n            extendElementWith(element, Element.Methods.ByTag[t.toUpperCase()]);\n          }\n        }\n        return element;\n      }\n    }\n    return Prototype.K;\n  }\n\n  var Methods = { }, ByTag = Element.Methods.ByTag;\n\n  var extend = Object.extend(function(element) {\n    if (!element || typeof element._extendedByPrototype != 'undefined' ||\n        element.nodeType != 1 || element == window) return element;\n\n    var methods = Object.clone(Methods),\n        tagName = element.tagName.toUpperCase();\n\n    if (ByTag[tagName]) Object.extend(methods, ByTag[tagName]);\n\n    extendElementWith(element, methods);\n\n    element._extendedByPrototype = Prototype.emptyFunction;\n    return element;\n\n  }, {\n    refresh: function() {\n      if (!Prototype.BrowserFeatures.ElementExtensions) {\n        Object.extend(Methods, Element.Methods);\n        Object.extend(Methods, Element.Methods.Simulated);\n      }\n    }\n  });\n\n  extend.refresh();\n  return extend;\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 (Object.isArray(tagName)) 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    for (var property in methods) {\n      var value = methods[property];\n      if (!Object.isFunction(value)) continue;\n      if (!onlyIfAbsent || !(property in destination))\n        destination[property] = value.methodize();\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    var element = document.createElement(tagName);\n    var proto = element['__proto__'] || element.constructor.prototype;\n    element = null;\n    return proto;\n  }\n\n  var elementPrototype = window.HTMLElement ? HTMLElement.prototype :\n   Element.prototype;\n\n  if (F.ElementExtensions) {\n    copy(Element.Methods, elementPrototype);\n    copy(Element.Methods.Simulated, elementPrototype, true);\n  }\n\n  if (F.SpecificElementExtensions) {\n    for (var tag in Element.Methods.ByTag) {\n      var klass = findDOMClass(tag);\n      if (Object.isUndefined(klass)) continue;\n      copy(T[tag], klass.prototype);\n    }\n  }\n\n  Object.extend(Element, Element.Methods);\n  delete Element.ByTag;\n\n  if (Element.extend.refresh) Element.extend.refresh();\n  Element.cache = { };\n};\n\n\ndocument.viewport = {\n\n  getDimensions: function() {\n    return { width: this.getWidth(), height: this.getHeight() };\n  },\n\n  getScrollOffsets: function() {\n    return Element._returnOffset(\n      window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft,\n      window.pageYOffset || document.documentElement.scrollTop  || document.body.scrollTop);\n  }\n};\n\n(function(viewport) {\n  var B = Prototype.Browser, doc = document, element, property = {};\n\n  function getRootElement() {\n    if (B.WebKit && !doc.evaluate)\n      return document;\n\n    if (B.Opera && window.parseFloat(window.opera.version()) < 9.5)\n      return document.body;\n\n    return document.documentElement;\n  }\n\n  function define(D) {\n    if (!element) element = getRootElement();\n\n    property[D] = 'client' + D;\n\n    viewport['get' + D] = function() { return element[property[D]] };\n    return viewport['get' + D]();\n  }\n\n  viewport.getWidth  = define.curry('Width');\n\n  viewport.getHeight = define.curry('Height');\n})(document.viewport);\n\n\nElement.Storage = {\n  UID: 1\n};\n\nElement.addMethods({\n  getStorage: function(element) {\n    if (!(element = $(element))) return;\n\n    var uid;\n    if (element === window) {\n      uid = 0;\n    } else {\n      if (typeof element._prototypeUID === \"undefined\")\n        element._prototypeUID = [Element.Storage.UID++];\n      uid = element._prototypeUID[0];\n    }\n\n    if (!Element.Storage[uid])\n      Element.Storage[uid] = $H();\n\n    return Element.Storage[uid];\n  },\n\n  store: function(element, key, value) {\n    if (!(element = $(element))) return;\n\n    if (arguments.length === 2) {\n      Element.getStorage(element).update(key);\n    } else {\n      Element.getStorage(element).set(key, value);\n    }\n\n    return element;\n  },\n\n  retrieve: function(element, key, defaultValue) {\n    if (!(element = $(element))) return;\n    var hash = Element.getStorage(element), value = hash.get(key);\n\n    if (Object.isUndefined(value)) {\n      hash.set(key, defaultValue);\n      value = defaultValue;\n    }\n\n    return value;\n  },\n\n  clone: function(element, deep) {\n    if (!(element = $(element))) return;\n    var clone = element.cloneNode(deep);\n    clone._prototypeUID = void 0;\n    if (deep) {\n      var descendants = Element.select(clone, '*'),\n          i = descendants.length;\n      while (i--) {\n        descendants[i]._prototypeUID = void 0;\n      }\n    }\n    return Element.extend(clone);\n  }\n});\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  initialize: function(expression) {\n    this.expression = expression.strip();\n\n    if (this.shouldUseSelectorsAPI()) {\n      this.mode = 'selectorsAPI';\n    } else if (this.shouldUseXPath()) {\n      this.mode = 'xpath';\n      this.compileXPathMatcher();\n    } else {\n      this.mode = \"normal\";\n      this.compileMatcher();\n    }\n\n  },\n\n  shouldUseXPath: (function() {\n\n    var IS_DESCENDANT_SELECTOR_BUGGY = (function(){\n      var isBuggy = false;\n      if (document.evaluate && window.XPathResult) {\n        var el = document.createElement('div');\n        el.innerHTML = '<ul><li></li></ul><div><ul><li></li></ul></div>';\n\n        var xpath = \".//*[local-name()='ul' or local-name()='UL']\" +\n          \"//*[local-name()='li' or local-name()='LI']\";\n\n        var result = document.evaluate(xpath, el, null,\n          XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);\n\n        isBuggy = (result.snapshotLength !== 2);\n        el = null;\n      }\n      return isBuggy;\n    })();\n\n    return function() {\n      if (!Prototype.BrowserFeatures.XPath) return false;\n\n      var e = this.expression;\n\n      if (Prototype.Browser.WebKit &&\n       (e.include(\"-of-type\") || e.include(\":empty\")))\n        return false;\n\n      if ((/(\\[[\\w-]*?:|:checked)/).test(e))\n        return false;\n\n      if (IS_DESCENDANT_SELECTOR_BUGGY) return false;\n\n      return true;\n    }\n\n  })(),\n\n  shouldUseSelectorsAPI: function() {\n    if (!Prototype.BrowserFeatures.SelectorsAPI) return false;\n\n    if (Selector.CASE_INSENSITIVE_CLASS_NAMES) return false;\n\n    if (!Selector._div) Selector._div = new Element('div');\n\n    try {\n      Selector._div.querySelector(this.expression);\n    } catch(e) {\n      return false;\n    }\n\n    return true;\n  },\n\n  compileMatcher: function() {\n    var e = this.expression, ps = Selector.patterns, h = Selector.handlers,\n        c = Selector.criteria, le, p, m, len = ps.length, name;\n\n    if (Selector._cache[e]) {\n      this.matcher = Selector._cache[e];\n      return;\n    }\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 = 0; i<len; i++) {\n        p = ps[i].re;\n        name = ps[i].name;\n        if (m = e.match(p)) {\n          this.matcher.push(Object.isFunction(c[name]) ? c[name](m) :\n            new Template(c[name]).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, len = ps.length, name;\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 = 0; i<len; i++) {\n        name = ps[i].name;\n        if (m = e.match(ps[i].re)) {\n          this.matcher.push(Object.isFunction(x[name]) ? x[name](m) :\n            new Template(x[name]).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    var e = this.expression, results;\n\n    switch (this.mode) {\n      case 'selectorsAPI':\n        if (root !== document) {\n          var oldId = root.id, id = $(root).identify();\n          id = id.replace(/([\\.:])/g, \"\\\\$1\");\n          e = \"#\" + id + \" \" + e;\n        }\n\n        results = $A(root.querySelectorAll(e)).map(Element.extend);\n        root.id = oldId;\n\n        return results;\n      case 'xpath':\n        return document._getElementsByXPath(this.xpath, root);\n      default:\n       return this.matcher(root);\n    }\n  },\n\n  match: function(element) {\n    this.tokens = [];\n\n    var e = this.expression, ps = Selector.patterns, as = Selector.assertions;\n    var le, p, m, len = ps.length, name;\n\n    while (e && le !== e && (/\\S/).test(e)) {\n      le = e;\n      for (var i = 0; i<len; i++) {\n        p = ps[i].re;\n        name = ps[i].name;\n        if (m = e.match(p)) {\n          if (as[name]) {\n            this.tokens.push([name, Object.clone(m)]);\n            e = e.replace(m[0], '');\n          } else {\n            return this.findElements(document).include(element);\n          }\n        }\n      }\n    }\n\n    var match = true, name, matches;\n    for (var i = 0, token; token = this.tokens[i]; i++) {\n      name = token[0], matches = token[1];\n      if (!Selector.assertions[name](element, matches)) {\n        match = false; break;\n      }\n    }\n\n    return match;\n  },\n\n  toString: function() {\n    return this.expression;\n  },\n\n  inspect: function() {\n    return \"#<Selector:\" + this.expression.inspect() + \">\";\n  }\n});\n\nif (Prototype.BrowserFeatures.SelectorsAPI &&\n document.compatMode === 'BackCompat') {\n  Selector.CASE_INSENSITIVE_CLASS_NAMES = (function(){\n    var div = document.createElement('div'),\n     span = document.createElement('span');\n\n    div.id = \"prototype_test_id\";\n    span.className = 'Test';\n    div.appendChild(span);\n    var isIgnored = (div.querySelector('#prototype_test_id .test') !== null);\n    div = span = null;\n    return isIgnored;\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: function(m) {\n      m[1] = m[1].toLowerCase();\n      return new Template(\"[@#{1}]\").evaluate(m);\n    },\n    attr: function(m) {\n      m[1] = m[1].toLowerCase();\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 (Object.isFunction(h)) 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)]\",\n      'checked':     \"[@checked]\",\n      'disabled':    \"[(@disabled) and (@type!='hidden')]\",\n      'enabled':     \"[not(@disabled) and (@type!='hidden')]\",\n      'not': function(m) {\n        var e = m[6], p = Selector.patterns,\n            x = Selector.xpath, le, v, len = p.length, name;\n\n        var exclusion = [];\n        while (e && le != e && (/\\S/).test(e)) {\n          le = e;\n          for (var i = 0; i<len; i++) {\n            name = p[i].name\n            if (m = e.match(p[i].re)) {\n              v = Object.isFunction(x[name]) ? x[name](m) : new Template(x[name]).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); 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); 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    { name: 'laterSibling', re: /^\\s*~\\s*/ },\n    { name: 'child',        re: /^\\s*>\\s*/ },\n    { name: 'adjacent',     re: /^\\s*\\+\\s*/ },\n    { name: 'descendant',   re: /^\\s/ },\n\n    { name: 'tagName',      re: /^\\s*(\\*|[\\w\\-]+)(\\b|$)?/ },\n    { name: 'id',           re: /^#([\\w\\-\\*]+)(\\b|$)/ },\n    { name: 'className',    re: /^\\.([\\w\\-\\*]+)(\\b|$)/ },\n    { name: 'pseudo',       re: /^:((first|last|nth|nth-last|only)(-child|-of-type)|empty|checked|(en|dis)abled|not)(\\((.*?)\\))?(\\b|$|(?=\\s|[:+~>]))/ },\n    { name: 'attrPresence', re: /^\\[((?:[\\w-]+:)?[\\w-]+)\\]/ },\n    { name: 'attr',         re: /\\[((?:[\\w-]*:)?[\\w-]+)\\s*(?:([!^$*~|]?=)\\s*((['\"])([^\\4]*?)\\4|([^'\"][^\\]]*?)))?\\]/ }\n  ],\n\n  assertions: {\n    tagName: function(element, matches) {\n      return matches[1].toUpperCase() == element.tagName.toUpperCase();\n    },\n\n    className: function(element, matches) {\n      return Element.hasClassName(element, matches[1]);\n    },\n\n    id: function(element, matches) {\n      return element.id === matches[1];\n    },\n\n    attrPresence: function(element, matches) {\n      return Element.hasAttribute(element, matches[1]);\n    },\n\n    attr: function(element, matches) {\n      var nodeValue = Element.readAttribute(element, matches[1]);\n      return nodeValue && Selector.operators[matches[2]](nodeValue, matches[5] || matches[6]);\n    }\n  },\n\n  handlers: {\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    mark: function(nodes) {\n      var _true = Prototype.emptyFunction;\n      for (var i = 0, node; node = nodes[i]; i++)\n        node._countedByPrototype = _true;\n      return nodes;\n    },\n\n    unmark: (function(){\n\n      var PROPERTIES_ATTRIBUTES_MAP = (function(){\n        var el = document.createElement('div'),\n            isBuggy = false,\n            propName = '_countedByPrototype',\n            value = 'x'\n        el[propName] = value;\n        isBuggy = (el.getAttribute(propName) === value);\n        el = null;\n        return isBuggy;\n      })();\n\n      return PROPERTIES_ATTRIBUTES_MAP ?\n        function(nodes) {\n          for (var i = 0, node; node = nodes[i]; i++)\n            node.removeAttribute('_countedByPrototype');\n          return nodes;\n        } :\n        function(nodes) {\n          for (var i = 0, node; node = nodes[i]; i++)\n            node._countedByPrototype = void 0;\n          return nodes;\n        }\n    })(),\n\n    index: function(parentNode, reverse, ofType) {\n      parentNode._countedByPrototype = Prototype.emptyFunction;\n      if (reverse) {\n        for (var nodes = parentNode.childNodes, i = nodes.length - 1, j = 1; i >= 0; i--) {\n          var node = nodes[i];\n          if (node.nodeType == 1 && (!ofType || node._countedByPrototype)) 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._countedByPrototype)) node.nodeIndex = j++;\n      }\n    },\n\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 (typeof (n = nodes[i])._countedByPrototype == 'undefined') {\n          n._countedByPrototype = Prototype.emptyFunction;\n          results.push(Element.extend(n));\n        }\n      return Selector.handlers.unmark(results);\n    },\n\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, 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        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    tagName: function(nodes, root, tagName, combinator) {\n      var uTagName = tagName.toUpperCase();\n      var results = [], h = Selector.handlers;\n      if (nodes) {\n        if (combinator) {\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() === uTagName) 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\n      if (root == document) {\n        if (!targetNode) return [];\n        if (!nodes) return [targetNode];\n      } else {\n        if (!root.sourceIndex || root.sourceIndex < 1) {\n          var nodes = root.getElementsByTagName('*');\n          for (var j = 0, node; node = nodes[j]; j++) {\n            if (node.id === id) return [node];\n          }\n        }\n      }\n\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, combinator) {\n      if (!nodes) nodes = root.getElementsByTagName(\"*\");\n      if (nodes && combinator) nodes = this[combinator](nodes);\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, combinator) {\n      if (!nodes) nodes = root.getElementsByTagName(\"*\");\n      if (nodes && combinator) nodes = this[combinator](nodes);\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    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    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._countedByPrototype) {\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        if (node.tagName == '!' || node.firstChild) 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._countedByPrototype) 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 && (!node.type || node.type !== 'hidden'))\n          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 == v || nv && nv.startsWith(v); },\n    '$=': function(nv, v) { return nv == v || nv && nv.endsWith(v); },\n    '*=': function(nv, v) { return nv == v || nv && nv.include(v); },\n    '~=': function(nv, v) { return (' ' + nv + ' ').include(' ' + v + ' '); },\n    '|=': function(nv, v) { return ('-' + (nv || \"\").toUpperCase() +\n     '-').include('-' + (v || \"\").toUpperCase() + '-'); }\n  },\n\n  split: function(expression) {\n    var expressions = [];\n    expression.scan(/(([\\w#:.~>+()\\s-]+|\\*|\\[.*?\\])+)\\s*(,|$)/, function(m) {\n      expressions.push(m[1].strip());\n    });\n    return expressions;\n  },\n\n  matchElements: function(elements, expression) {\n    var matches = $$(expression), h = Selector.handlers;\n    h.mark(matches);\n    for (var i = 0, results = [], element; element = elements[i]; i++)\n      if (element._countedByPrototype) results.push(element);\n    h.unmark(matches);\n    return results;\n  },\n\n  findElement: function(elements, expression, index) {\n    if (Object.isNumber(expression)) {\n      index = expression; expression = false;\n    }\n    return Selector.matchElements(elements, expression || '*')[index || 0];\n  },\n\n  findChildElements: function(element, expressions) {\n    expressions = Selector.split(expressions.join(','));\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\nif (Prototype.Browser.IE) {\n  Object.extend(Selector.handlers, {\n    concat: function(a, b) {\n      for (var i = 0, node; node = b[i]; i++)\n        if (node.tagName !== \"!\") a.push(node);\n      return a;\n    }\n  });\n}\n\nfunction $$() {\n  return Selector.findChildElements(document, $A(arguments));\n}\n\nvar Form = {\n  reset: function(form) {\n    form = $(form);\n    form.reset();\n    return form;\n  },\n\n  serializeElements: function(elements, options) {\n    if (typeof options != 'object') options = { hash: !!options };\n    else if (Object.isUndefined(options.hash)) options.hash = true;\n    var key, value, submitted = false, submit = options.submit;\n\n    var data = elements.inject({ }, function(result, element) {\n      if (!element.disabled && element.name) {\n        key = element.name; value = $(element).getValue();\n        if (value != null && element.type != 'file' && (element.type != 'submit' || (!submitted &&\n            submit !== false && (!submit || key == submit) && (submitted = true)))) {\n          if (key in result) {\n            if (!Object.isArray(result[key])) result[key] = [result[key]];\n            result[key].push(value);\n          }\n          else result[key] = value;\n        }\n      }\n      return result;\n    });\n\n    return options.hash ? data : Object.toQueryString(data);\n  }\n};\n\nForm.Methods = {\n  serialize: function(form, options) {\n    return Form.serializeElements(Form.getElements(form), options);\n  },\n\n  getElements: function(form) {\n    var elements = $(form).getElementsByTagName('*'),\n        element,\n        arr = [ ],\n        serializers = Form.Element.Serializers;\n    for (var i = 0; element = elements[i]; i++) {\n      arr.push(element);\n    }\n    return arr.inject([], function(elements, child) {\n      if (serializers[child.tagName.toLowerCase()])\n        elements.push(Element.extend(child));\n      return elements;\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    var elements = $(form).getElements().findAll(function(element) {\n      return 'hidden' != element.type && !element.disabled;\n    });\n    var firstByIndex = elements.findAll(function(element) {\n      return element.hasAttribute('tabIndex') && element.tabIndex >= 0;\n    }).sortBy(function(element) { return element.tabIndex }).first();\n\n    return firstByIndex ? firstByIndex : elements.find(function(element) {\n      return /^(?:input|select|textarea)$/i.test(element.tagName);\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, action = form.readAttribute('action') || '';\n    if (action.blank()) action = window.location.href;\n    options.parameters = form.serialize(true);\n\n    if (params) {\n      if (Object.isString(params)) 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(action, options);\n  }\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\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 Object.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  setValue: function(element, value) {\n    element = $(element);\n    var method = element.tagName.toLowerCase();\n    Form.Element.Serializers[method](element, value);\n    return 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)$/i.test(element.type))))\n        element.select();\n    } catch (e) { }\n    return element;\n  },\n\n  disable: function(element) {\n    element = $(element);\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;\n\nvar $F = Form.Element.Methods.getValue;\n\n/*--------------------------------------------------------------------------*/\n\nForm.Element.Serializers = {\n  input: function(element, value) {\n    switch (element.type.toLowerCase()) {\n      case 'checkbox':\n      case 'radio':\n        return Form.Element.Serializers.inputSelector(element, value);\n      default:\n        return Form.Element.Serializers.textarea(element, value);\n    }\n  },\n\n  inputSelector: function(element, value) {\n    if (Object.isUndefined(value)) return element.checked ? element.value : null;\n    else element.checked = !!value;\n  },\n\n  textarea: function(element, value) {\n    if (Object.isUndefined(value)) return element.value;\n    else element.value = value;\n  },\n\n  select: function(element, value) {\n    if (Object.isUndefined(value))\n      return this[element.type == 'select-one' ?\n        'selectOne' : 'selectMany'](element);\n    else {\n      var opt, currentValue, single = !Object.isArray(value);\n      for (var i = 0, length = element.length; i < length; i++) {\n        opt = element.options[i];\n        currentValue = this.optionValue(opt);\n        if (single) {\n          if (currentValue == value) {\n            opt.selected = true;\n            return;\n          }\n        }\n        else opt.selected = value.include(currentValue);\n      }\n    }\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    return Element.extend(opt).hasAttribute('value') ? opt.value : opt.text;\n  }\n};\n\n/*--------------------------------------------------------------------------*/\n\n\nAbstract.TimedObserver = Class.create(PeriodicalExecuter, {\n  initialize: function($super, element, frequency, callback) {\n    $super(callback, frequency);\n    this.element   = $(element);\n    this.lastValue = this.getValue();\n  },\n\n  execute: function() {\n    var value = this.getValue();\n    if (Object.isString(this.lastValue) && Object.isString(value) ?\n        this.lastValue != value : String(this.lastValue) != String(value)) {\n      this.callback(this.element, value);\n      this.lastValue = value;\n    }\n  }\n});\n\nForm.Element.Observer = Class.create(Abstract.TimedObserver, {\n  getValue: function() {\n    return Form.Element.getValue(this.element);\n  }\n});\n\nForm.Observer = Class.create(Abstract.TimedObserver, {\n  getValue: function() {\n    return Form.serialize(this.element);\n  }\n});\n\n/*--------------------------------------------------------------------------*/\n\nAbstract.EventObserver = Class.create({\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, 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(Abstract.EventObserver, {\n  getValue: function() {\n    return Form.Element.getValue(this.element);\n  }\n});\n\nForm.EventObserver = Class.create(Abstract.EventObserver, {\n  getValue: function() {\n    return Form.serialize(this.element);\n  }\n});\n(function() {\n\n  var 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    KEY_INSERT:   45,\n\n    cache: {}\n  };\n\n  var docEl = document.documentElement;\n  var MOUSEENTER_MOUSELEAVE_EVENTS_SUPPORTED = 'onmouseenter' in docEl\n    && 'onmouseleave' in docEl;\n\n  var _isButton;\n  if (Prototype.Browser.IE) {\n    var buttonMap = { 0: 1, 1: 4, 2: 2 };\n    _isButton = function(event, code) {\n      return event.button === buttonMap[code];\n    };\n  } else if (Prototype.Browser.WebKit) {\n    _isButton = function(event, code) {\n      switch (code) {\n        case 0: return event.which == 1 && !event.metaKey;\n        case 1: return event.which == 1 && event.metaKey;\n        default: return false;\n      }\n    };\n  } else {\n    _isButton = function(event, code) {\n      return event.which ? (event.which === code + 1) : (event.button === code);\n    };\n  }\n\n  function isLeftClick(event)   { return _isButton(event, 0) }\n\n  function isMiddleClick(event) { return _isButton(event, 1) }\n\n  function isRightClick(event)  { return _isButton(event, 2) }\n\n  function element(event) {\n    event = Event.extend(event);\n\n    var node = event.target, type = event.type,\n     currentTarget = event.currentTarget;\n\n    if (currentTarget && currentTarget.tagName) {\n      if (type === 'load' || type === 'error' ||\n        (type === 'click' && currentTarget.tagName.toLowerCase() === 'input'\n          && currentTarget.type === 'radio'))\n            node = currentTarget;\n    }\n\n    if (node.nodeType == Node.TEXT_NODE)\n      node = node.parentNode;\n\n    return Element.extend(node);\n  }\n\n  function findElement(event, expression) {\n    var element = Event.element(event);\n    if (!expression) return element;\n    var elements = [element].concat(element.ancestors());\n    return Selector.findElement(elements, expression, 0);\n  }\n\n  function pointer(event) {\n    return { x: pointerX(event), y: pointerY(event) };\n  }\n\n  function pointerX(event) {\n    var docElement = document.documentElement,\n     body = document.body || { scrollLeft: 0 };\n\n    return event.pageX || (event.clientX +\n      (docElement.scrollLeft || body.scrollLeft) -\n      (docElement.clientLeft || 0));\n  }\n\n  function pointerY(event) {\n    var docElement = document.documentElement,\n     body = document.body || { scrollTop: 0 };\n\n    return  event.pageY || (event.clientY +\n       (docElement.scrollTop || body.scrollTop) -\n       (docElement.clientTop || 0));\n  }\n\n\n  function stop(event) {\n    Event.extend(event);\n    event.preventDefault();\n    event.stopPropagation();\n\n    event.stopped = true;\n  }\n\n  Event.Methods = {\n    isLeftClick: isLeftClick,\n    isMiddleClick: isMiddleClick,\n    isRightClick: isRightClick,\n\n    element: element,\n    findElement: findElement,\n\n    pointer: pointer,\n    pointerX: pointerX,\n    pointerY: pointerY,\n\n    stop: stop\n  };\n\n\n  var methods = Object.keys(Event.Methods).inject({ }, function(m, name) {\n    m[name] = Event.Methods[name].methodize();\n    return m;\n  });\n\n  if (Prototype.Browser.IE) {\n    function _relatedTarget(event) {\n      var element;\n      switch (event.type) {\n        case 'mouseover': element = event.fromElement; break;\n        case 'mouseout':  element = event.toElement;   break;\n        default: return null;\n      }\n      return Element.extend(element);\n    }\n\n    Object.extend(methods, {\n      stopPropagation: function() { this.cancelBubble = true },\n      preventDefault:  function() { this.returnValue = false },\n      inspect: function() { return '[object Event]' }\n    });\n\n    Event.extend = function(event, element) {\n      if (!event) return false;\n      if (event._extendedByPrototype) return event;\n\n      event._extendedByPrototype = Prototype.emptyFunction;\n      var pointer = Event.pointer(event);\n\n      Object.extend(event, {\n        target: event.srcElement || element,\n        relatedTarget: _relatedTarget(event),\n        pageX:  pointer.x,\n        pageY:  pointer.y\n      });\n\n      return Object.extend(event, methods);\n    };\n  } else {\n    Event.prototype = window.Event.prototype || document.createEvent('HTMLEvents').__proto__;\n    Object.extend(Event.prototype, methods);\n    Event.extend = Prototype.K;\n  }\n\n  function _createResponder(element, eventName, handler) {\n    var registry = Element.retrieve(element, 'prototype_event_registry');\n\n    if (Object.isUndefined(registry)) {\n      CACHE.push(element);\n      registry = Element.retrieve(element, 'prototype_event_registry', $H());\n    }\n\n    var respondersForEvent = registry.get(eventName);\n    if (Object.isUndefined(respondersForEvent)) {\n      respondersForEvent = [];\n      registry.set(eventName, respondersForEvent);\n    }\n\n    if (respondersForEvent.pluck('handler').include(handler)) return false;\n\n    var responder;\n    if (eventName.include(\":\")) {\n      responder = function(event) {\n        if (Object.isUndefined(event.eventName))\n          return false;\n\n        if (event.eventName !== eventName)\n          return false;\n\n        Event.extend(event, element);\n        handler.call(element, event);\n      };\n    } else {\n      if (!MOUSEENTER_MOUSELEAVE_EVENTS_SUPPORTED &&\n       (eventName === \"mouseenter\" || eventName === \"mouseleave\")) {\n        if (eventName === \"mouseenter\" || eventName === \"mouseleave\") {\n          responder = function(event) {\n            Event.extend(event, element);\n\n            var parent = event.relatedTarget;\n            while (parent && parent !== element) {\n              try { parent = parent.parentNode; }\n              catch(e) { parent = element; }\n            }\n\n            if (parent === element) return;\n\n            handler.call(element, event);\n          };\n        }\n      } else {\n        responder = function(event) {\n          Event.extend(event, element);\n          handler.call(element, event);\n        };\n      }\n    }\n\n    responder.handler = handler;\n    respondersForEvent.push(responder);\n    return responder;\n  }\n\n  function _destroyCache() {\n    for (var i = 0, length = CACHE.length; i < length; i++) {\n      Event.stopObserving(CACHE[i]);\n      CACHE[i] = null;\n    }\n  }\n\n  var CACHE = [];\n\n  if (Prototype.Browser.IE)\n    window.attachEvent('onunload', _destroyCache);\n\n  if (Prototype.Browser.WebKit)\n    window.addEventListener('unload', Prototype.emptyFunction, false);\n\n\n  var _getDOMEventName = Prototype.K;\n\n  if (!MOUSEENTER_MOUSELEAVE_EVENTS_SUPPORTED) {\n    _getDOMEventName = function(eventName) {\n      var translations = { mouseenter: \"mouseover\", mouseleave: \"mouseout\" };\n      return eventName in translations ? translations[eventName] : eventName;\n    };\n  }\n\n  function observe(element, eventName, handler) {\n    element = $(element);\n\n    var responder = _createResponder(element, eventName, handler);\n\n    if (!responder) return element;\n\n    if (eventName.include(':')) {\n      if (element.addEventListener)\n        element.addEventListener(\"dataavailable\", responder, false);\n      else {\n        element.attachEvent(\"ondataavailable\", responder);\n        element.attachEvent(\"onfilterchange\", responder);\n      }\n    } else {\n      var actualEventName = _getDOMEventName(eventName);\n\n      if (element.addEventListener)\n        element.addEventListener(actualEventName, responder, false);\n      else\n        element.attachEvent(\"on\" + actualEventName, responder);\n    }\n\n    return element;\n  }\n\n  function stopObserving(element, eventName, handler) {\n    element = $(element);\n\n    var registry = Element.retrieve(element, 'prototype_event_registry');\n\n    if (Object.isUndefined(registry)) return element;\n\n    if (eventName && !handler) {\n      var responders = registry.get(eventName);\n\n      if (Object.isUndefined(responders)) return element;\n\n      responders.each( function(r) {\n        Element.stopObserving(element, eventName, r.handler);\n      });\n      return element;\n    } else if (!eventName) {\n      registry.each( function(pair) {\n        var eventName = pair.key, responders = pair.value;\n\n        responders.each( function(r) {\n          Element.stopObserving(element, eventName, r.handler);\n        });\n      });\n      return element;\n    }\n\n    var responders = registry.get(eventName);\n\n    if (!responders) return;\n\n    var responder = responders.find( function(r) { return r.handler === handler; });\n    if (!responder) return element;\n\n    var actualEventName = _getDOMEventName(eventName);\n\n    if (eventName.include(':')) {\n      if (element.removeEventListener)\n        element.removeEventListener(\"dataavailable\", responder, false);\n      else {\n        element.detachEvent(\"ondataavailable\", responder);\n        element.detachEvent(\"onfilterchange\",  responder);\n      }\n    } else {\n      if (element.removeEventListener)\n        element.removeEventListener(actualEventName, responder, false);\n      else\n        element.detachEvent('on' + actualEventName, responder);\n    }\n\n    registry.set(eventName, responders.without(responder));\n\n    return element;\n  }\n\n  function fire(element, eventName, memo, bubble) {\n    element = $(element);\n\n    if (Object.isUndefined(bubble))\n      bubble = true;\n\n    if (element == document && document.createEvent && !element.dispatchEvent)\n      element = document.documentElement;\n\n    var event;\n    if (document.createEvent) {\n      event = document.createEvent('HTMLEvents');\n      event.initEvent('dataavailable', true, true);\n    } else {\n      event = document.createEventObject();\n      event.eventType = bubble ? 'ondataavailable' : 'onfilterchange';\n    }\n\n    event.eventName = eventName;\n    event.memo = memo || { };\n\n    if (document.createEvent)\n      element.dispatchEvent(event);\n    else\n      element.fireEvent(event.eventType, event);\n\n    return Event.extend(event);\n  }\n\n\n  Object.extend(Event, Event.Methods);\n\n  Object.extend(Event, {\n    fire:          fire,\n    observe:       observe,\n    stopObserving: stopObserving\n  });\n\n  Element.addMethods({\n    fire:          fire,\n\n    observe:       observe,\n\n    stopObserving: stopObserving\n  });\n\n  Object.extend(document, {\n    fire:          fire.methodize(),\n\n    observe:       observe.methodize(),\n\n    stopObserving: stopObserving.methodize(),\n\n    loaded:        false\n  });\n\n  if (window.Event) Object.extend(window.Event, Event);\n  else window.Event = Event;\n})();\n\n(function() {\n  /* Support for the DOMContentLoaded event is based on work by Dan Webb,\n     Matthias Miller, Dean Edwards, John Resig, and Diego Perini. */\n\n  var timer;\n\n  function fireContentLoadedEvent() {\n    if (document.loaded) return;\n    if (timer) window.clearTimeout(timer);\n    document.loaded = true;\n    document.fire('dom:loaded');\n  }\n\n  function checkReadyState() {\n    if (document.readyState === 'complete') {\n      document.stopObserving('readystatechange', checkReadyState);\n      fireContentLoadedEvent();\n    }\n  }\n\n  function pollDoScroll() {\n    try { document.documentElement.doScroll('left'); }\n    catch(e) {\n      timer = pollDoScroll.defer();\n      return;\n    }\n    fireContentLoadedEvent();\n  }\n\n  if (document.addEventListener) {\n    document.addEventListener('DOMContentLoaded', fireContentLoadedEvent, false);\n  } else {\n    document.observe('readystatechange', checkReadyState);\n    if (window == top)\n      timer = pollDoScroll.defer();\n  }\n\n  Event.observe(window, 'load', fireContentLoadedEvent);\n})();\n\nElement.addMethods();\n\n/*------------------------------- DEPRECATED -------------------------------*/\n\nHash.toQueryString = Object.toQueryString;\n\nvar Toggle = { display: Element.toggle };\n\nElement.Methods.childOf = Element.Methods.descendantOf;\n\nvar Insertion = {\n  Before: function(element, content) {\n    return Element.insert(element, {before:content});\n  },\n\n  Top: function(element, content) {\n    return Element.insert(element, {top:content});\n  },\n\n  Bottom: function(element, content) {\n    return Element.insert(element, {bottom:content});\n  },\n\n  After: function(element, content) {\n    return Element.insert(element, {after:content});\n  }\n};\n\nvar $continue = new Error('\"throw $continue\" is deprecated, use \"return\" instead');\n\nvar Position = {\n  includeScrollOffsets: false,\n\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  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 = Element.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 = Element.cumulativeScrollOffset(element);\n\n    this.xcomp = x + offsetcache[0] - this.deltaX;\n    this.ycomp = y + offsetcache[1] - this.deltaY;\n    this.offset = Element.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  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\n  cumulativeOffset: Element.Methods.cumulativeOffset,\n\n  positionedOffset: Element.Methods.positionedOffset,\n\n  absolutize: function(element) {\n    Position.prepare();\n    return Element.absolutize(element);\n  },\n\n  relativize: function(element) {\n    Position.prepare();\n    return Element.relativize(element);\n  },\n\n  realOffset: Element.Methods.cumulativeScrollOffset,\n\n  offsetParent: Element.Methods.getOffsetParent,\n\n  page: Element.Methods.viewportOffset,\n\n  clone: function(source, target, options) {\n    options = options || { };\n    return Element.clonePosition(target, source, options);\n  }\n};\n\n/*--------------------------------------------------------------------------*/\n\nif (!document.getElementsByClassName) document.getElementsByClassName = function(instanceMethods){\n  function iter(name) {\n    return name.blank() ? null : \"[contains(concat(' ', @class, ' '), ' \" + name + \" ')]\";\n  }\n\n  instanceMethods.getElementsByClassName = Prototype.BrowserFeatures.XPath ?\n  function(element, className) {\n    className = className.toString().strip();\n    var cond = /\\s/.test(className) ? $w(className).map(iter).join('') : iter(className);\n    return cond ? document._getElementsByXPath('.//*' + cond, element) : [];\n  } : function(element, className) {\n    className = className.toString().strip();\n    var elements = [], classNames = (/\\s/.test(className) ? $w(className) : null);\n    if (!classNames && !className) return elements;\n\n    var nodes = $(element).getElementsByTagName('*');\n    className = ' ' + className + ' ';\n\n    for (var i = 0, child, cn; child = nodes[i]; i++) {\n      if (child.className && (cn = ' ' + child.className + ' ') && (cn.include(className) ||\n          (classNames && classNames.all(function(name) {\n            return !name.toString().blank() && cn.include(' ' + name + ' ');\n          }))))\n        elements.push(Element.extend(child));\n    }\n    return elements;\n  };\n\n  return function(className, parentElement) {\n    return $(parentElement || document.body).getElementsByClassName(className);\n  };\n}(Element.Methods);\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\n/*--------------------------------------------------------------------------*/"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/json3/vendor/require.js",
    "content": "/** vim: et:ts=4:sw=4:sts=4\n * @license RequireJS 0.25.0 Copyright (c) 2010-2011, The Dojo Foundation All Rights Reserved.\n * Available via the MIT or new BSD license.\n * see: http://github.com/jrburke/requirejs for details\n */\n/*jslint strict: false, plusplus: false */\n/*global window: false, navigator: false, document: false, importScripts: false,\n  jQuery: false, clearInterval: false, setInterval: false, self: false,\n  setTimeout: false, opera: false */\n\nvar requirejs, require, define;\n(function () {\n    //Change this version number for each release.\n    var version = \"0.25.0\",\n        commentRegExp = /(\\/\\*([\\s\\S]*?)\\*\\/|\\/\\/(.*)$)/mg,\n        cjsRequireRegExp = /require\\([\"']([^'\"\\s]+)[\"']\\)/g,\n        currDirRegExp = /^\\.\\//,\n        jsSuffixRegExp = /\\.js$/,\n        ostring = Object.prototype.toString,\n        ap = Array.prototype,\n        aps = ap.slice,\n        apsp = ap.splice,\n        isBrowser = !!(typeof window !== \"undefined\" && navigator && document),\n        isWebWorker = !isBrowser && typeof importScripts !== \"undefined\",\n        //PS3 indicates loaded and complete, but need to wait for complete\n        //specifically. Sequence is \"loading\", \"loaded\", execution,\n        // then \"complete\". The UA check is unfortunate, but not sure how\n        //to feature test w/o causing perf issues.\n        readyRegExp = isBrowser && navigator.platform === 'PLAYSTATION 3' ?\n                      /^complete$/ : /^(complete|loaded)$/,\n        defContextName = \"_\",\n        //Oh the tragedy, detecting opera. See the usage of isOpera for reason.\n        isOpera = typeof opera !== \"undefined\" && opera.toString() === \"[object Opera]\",\n        reqWaitIdPrefix = \"_r@@\",\n        empty = {},\n        contexts = {},\n        globalDefQueue = [],\n        interactiveScript = null,\n        isDone = false,\n        checkLoadedDepth = 0,\n        useInteractive = false,\n        req, cfg = {}, currentlyAddingScript, s, head, baseElement, scripts, script,\n        src, subPath, mainScript, dataMain, i, scrollIntervalId, setReadyState, ctx,\n        jQueryCheck, checkLoadedTimeoutId;\n\n    function isFunction(it) {\n        return ostring.call(it) === \"[object Function]\";\n    }\n\n    function isArray(it) {\n        return ostring.call(it) === \"[object Array]\";\n    }\n\n    /**\n     * Simple function to mix in properties from source into target,\n     * but only if target does not already have a property of the same name.\n     * This is not robust in IE for transferring methods that match\n     * Object.prototype names, but the uses of mixin here seem unlikely to\n     * trigger a problem related to that.\n     */\n    function mixin(target, source, force) {\n        for (var prop in source) {\n            if (!(prop in empty) && (!(prop in target) || force)) {\n                target[prop] = source[prop];\n            }\n        }\n        return req;\n    }\n\n    /**\n     * Constructs an error with a pointer to an URL with more information.\n     * @param {String} id the error ID that maps to an ID on a web page.\n     * @param {String} message human readable error.\n     * @param {Error} [err] the original error, if there is one.\n     *\n     * @returns {Error}\n     */\n    function makeError(id, msg, err) {\n        var e = new Error(msg + '\\nhttp://requirejs.org/docs/errors.html#' + id);\n        if (err) {\n            e.originalError = err;\n        }\n        return e;\n    }\n\n    /**\n     * Used to set up package paths from a packagePaths or packages config object.\n     * @param {Object} pkgs the object to store the new package config\n     * @param {Array} currentPackages an array of packages to configure\n     * @param {String} [dir] a prefix dir to use.\n     */\n    function configurePackageDir(pkgs, currentPackages, dir) {\n        var i, location, pkgObj;\n\n        for (i = 0; (pkgObj = currentPackages[i]); i++) {\n            pkgObj = typeof pkgObj === \"string\" ? { name: pkgObj } : pkgObj;\n            location = pkgObj.location;\n\n            //Add dir to the path, but avoid paths that start with a slash\n            //or have a colon (indicates a protocol)\n            if (dir && (!location || (location.indexOf(\"/\") !== 0 && location.indexOf(\":\") === -1))) {\n                location = dir + \"/\" + (location || pkgObj.name);\n            }\n\n            //Create a brand new object on pkgs, since currentPackages can\n            //be passed in again, and config.pkgs is the internal transformed\n            //state for all package configs.\n            pkgs[pkgObj.name] = {\n                name: pkgObj.name,\n                location: location || pkgObj.name,\n                //Remove leading dot in main, so main paths are normalized,\n                //and remove any trailing .js, since different package\n                //envs have different conventions: some use a module name,\n                //some use a file name.\n                main: (pkgObj.main || \"main\")\n                      .replace(currDirRegExp, '')\n                      .replace(jsSuffixRegExp, '')\n            };\n        }\n    }\n\n    /**\n     * jQuery 1.4.3-1.5.x use a readyWait/ready() pairing to hold DOM\n     * ready callbacks, but jQuery 1.6 supports a holdReady() API instead.\n     * At some point remove the readyWait/ready() support and just stick\n     * with using holdReady.\n     */\n    function jQueryHoldReady($, shouldHold) {\n        if ($.holdReady) {\n            $.holdReady(shouldHold);\n        } else if (shouldHold) {\n            $.readyWait += 1;\n        } else {\n            $.ready(true);\n        }\n    }\n\n    if (typeof define !== \"undefined\") {\n        //If a define is already in play via another AMD loader,\n        //do not overwrite.\n        return;\n    }\n\n    if (typeof requirejs !== \"undefined\") {\n        if (isFunction(requirejs)) {\n            //Do not overwrite and existing requirejs instance.\n            return;\n        } else {\n            cfg = requirejs;\n            requirejs = undefined;\n        }\n    }\n\n    //Allow for a require config object\n    if (typeof require !== \"undefined\" && !isFunction(require)) {\n        //assume it is a config object.\n        cfg = require;\n        require = undefined;\n    }\n\n    /**\n     * Creates a new context for use in require and define calls.\n     * Handle most of the heavy lifting. Do not want to use an object\n     * with prototype here to avoid using \"this\" in require, in case it\n     * needs to be used in more super secure envs that do not want this.\n     * Also there should not be that many contexts in the page. Usually just\n     * one for the default context, but could be extra for multiversion cases\n     * or if a package needs a special context for a dependency that conflicts\n     * with the standard context.\n     */\n    function newContext(contextName) {\n        var context, resume,\n            config = {\n                waitSeconds: 7,\n                baseUrl: s.baseUrl || \"./\",\n                paths: {},\n                pkgs: {}\n            },\n            defQueue = [],\n            specified = {\n                \"require\": true,\n                \"exports\": true,\n                \"module\": true\n            },\n            urlMap = {},\n            defined = {},\n            loaded = {},\n            waiting = {},\n            waitAry = [],\n            waitIdCounter = 0,\n            managerCallbacks = {},\n            plugins = {},\n            pluginsQueue = {},\n            resumeDepth = 0,\n            normalizedWaiting = {};\n\n        /**\n         * Trims the . and .. from an array of path segments.\n         * It will keep a leading path segment if a .. will become\n         * the first path segment, to help with module name lookups,\n         * which act like paths, but can be remapped. But the end result,\n         * all paths that use this function should look normalized.\n         * NOTE: this method MODIFIES the input array.\n         * @param {Array} ary the array of path segments.\n         */\n        function trimDots(ary) {\n            var i, part;\n            for (i = 0; (part = ary[i]); i++) {\n                if (part === \".\") {\n                    ary.splice(i, 1);\n                    i -= 1;\n                } else if (part === \"..\") {\n                    if (i === 1 && (ary[2] === '..' || ary[0] === '..')) {\n                        //End of the line. Keep at least one non-dot\n                        //path segment at the front so it can be mapped\n                        //correctly to disk. Otherwise, there is likely\n                        //no path mapping for a path starting with '..'.\n                        //This can still fail, but catches the most reasonable\n                        //uses of ..\n                        break;\n                    } else if (i > 0) {\n                        ary.splice(i - 1, 2);\n                        i -= 2;\n                    }\n                }\n            }\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 pkgName, pkgConfig;\n\n            //Adjust any relative paths.\n            if (name.charAt(0) === \".\") {\n                //If have a base name, try to normalize against it,\n                //otherwise, assume it is a top-level require that will\n                //be relative to baseUrl in the end.\n                if (baseName) {\n                    if (config.pkgs[baseName]) {\n                        //If the baseName is a package name, then just treat it as one\n                        //name to concat the name with.\n                        baseName = [baseName];\n                    } else {\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                        baseName = baseName.split(\"/\");\n                        baseName = baseName.slice(0, baseName.length - 1);\n                    }\n\n                    name = baseName.concat(name.split(\"/\"));\n                    trimDots(name);\n\n                    //Some use of packages may use a . path to reference the\n                    //\"main\" module name, so normalize for that.\n                    pkgConfig = config.pkgs[(pkgName = name[0])];\n                    name = name.join(\"/\");\n                    if (pkgConfig && name === pkgName + '/' + pkgConfig.main) {\n                        name = pkgName;\n                    }\n                }\n            }\n            return name;\n        }\n\n        /**\n         * Creates a module mapping that includes plugin prefix, module\n         * name, and path. If parentModuleMap is provided it will\n         * also normalize the name via require.normalize()\n         *\n         * @param {String} name the module name\n         * @param {String} [parentModuleMap] parent module map\n         * for the module name, used to resolve relative names.\n         *\n         * @returns {Object}\n         */\n        function makeModuleMap(name, parentModuleMap) {\n            var index = name ? name.indexOf(\"!\") : -1,\n                prefix = null,\n                parentName = parentModuleMap ? parentModuleMap.name : null,\n                originalName = name,\n                normalizedName, url, pluginModule;\n\n            if (index !== -1) {\n                prefix = name.substring(0, index);\n                name = name.substring(index + 1, name.length);\n            }\n\n            if (prefix) {\n                prefix = normalize(prefix, parentName);\n            }\n\n            //Account for relative paths if there is a base name.\n            if (name) {\n                if (prefix) {\n                    pluginModule = defined[prefix];\n                    if (pluginModule) {\n                        //Plugin is loaded, use its normalize method, otherwise,\n                        //normalize name as usual.\n                        if (pluginModule.normalize) {\n                            normalizedName = pluginModule.normalize(name, function (name) {\n                                return normalize(name, parentName);\n                            });\n                        } else {\n                            normalizedName = normalize(name, parentName);\n                        }\n                    } else {\n                        //Plugin is not loaded yet, so do not normalize\n                        //the name, wait for plugin to load to see if\n                        //it has a normalize method. To avoid possible\n                        //ambiguity with relative names loaded from another\n                        //plugin, use the parent's name as part of this name.\n                        normalizedName = '__$p' + parentName + '@' + name;\n                    }\n                } else {\n                    normalizedName = normalize(name, parentName);\n                }\n\n                url = urlMap[normalizedName];\n                if (!url) {\n                    //Calculate url for the module, if it has a name.\n                    if (req.toModuleUrl) {\n                        //Special logic required for a particular engine,\n                        //like Node.\n                        url = req.toModuleUrl(context, normalizedName, parentModuleMap);\n                    } else {\n                        url = context.nameToUrl(normalizedName, null, parentModuleMap);\n                    }\n\n                    //Store the URL mapping for later.\n                    urlMap[normalizedName] = url;\n                }\n            }\n\n            return {\n                prefix: prefix,\n                name: normalizedName,\n                parentMap: parentModuleMap,\n                url: url,\n                originalName: originalName,\n                fullName: prefix ? prefix + \"!\" + normalizedName : normalizedName\n            };\n        }\n\n        /**\n         * Determine if priority loading is done. If so clear the priorityWait\n         */\n        function isPriorityDone() {\n            var priorityDone = true,\n                priorityWait = config.priorityWait,\n                priorityName, i;\n            if (priorityWait) {\n                for (i = 0; (priorityName = priorityWait[i]); i++) {\n                    if (!loaded[priorityName]) {\n                        priorityDone = false;\n                        break;\n                    }\n                }\n                if (priorityDone) {\n                    delete config.priorityWait;\n                }\n            }\n            return priorityDone;\n        }\n\n        /**\n         * Helper function that creates a setExports function for a \"module\"\n         * CommonJS dependency. Do this here to avoid creating a closure that\n         * is part of a loop.\n         */\n        function makeSetExports(moduleObj) {\n            return function (exports) {\n                moduleObj.exports = exports;\n            };\n        }\n\n        function makeContextModuleFunc(func, relModuleMap, enableBuildCallback) {\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 = [].concat(aps.call(arguments, 0)), lastArg;\n                if (enableBuildCallback &&\n                    isFunction((lastArg = args[args.length - 1]))) {\n                    lastArg.__requireJsBuild = true;\n                }\n                args.push(relModuleMap);\n                return func.apply(null, args);\n            };\n        }\n\n        /**\n         * Helper function that creates a require function object to give to\n         * modules that ask for it as a dependency. It needs to be specific\n         * per module because of the implication of path mappings that may\n         * need to be relative to the module name.\n         */\n        function makeRequire(relModuleMap, enableBuildCallback) {\n            var modRequire = makeContextModuleFunc(context.require, relModuleMap, enableBuildCallback);\n\n            mixin(modRequire, {\n                nameToUrl: makeContextModuleFunc(context.nameToUrl, relModuleMap),\n                toUrl: makeContextModuleFunc(context.toUrl, relModuleMap),\n                defined: makeContextModuleFunc(context.requireDefined, relModuleMap),\n                specified: makeContextModuleFunc(context.requireSpecified, relModuleMap),\n                ready: req.ready,\n                isBrowser: req.isBrowser\n            });\n            //Something used by node.\n            if (req.paths) {\n                modRequire.paths = req.paths;\n            }\n            return modRequire;\n        }\n\n        /**\n         * Used to update the normalized name for plugin-based dependencies\n         * after a plugin loads, since it can have its own normalization structure.\n         * @param {String} pluginName the normalized plugin module name.\n         */\n        function updateNormalizedNames(pluginName) {\n\n            var oldFullName, oldModuleMap, moduleMap, fullName, callbacks,\n                i, j, k, depArray, existingCallbacks,\n                maps = normalizedWaiting[pluginName];\n\n            if (maps) {\n                for (i = 0; (oldModuleMap = maps[i]); i++) {\n                    oldFullName = oldModuleMap.fullName;\n                    moduleMap = makeModuleMap(oldModuleMap.originalName, oldModuleMap.parentMap);\n                    fullName = moduleMap.fullName;\n                    //Callbacks could be undefined if the same plugin!name was\n                    //required twice in a row, so use empty array in that case.\n                    callbacks = managerCallbacks[oldFullName] || [];\n                    existingCallbacks = managerCallbacks[fullName];\n\n                    if (fullName !== oldFullName) {\n                        //Update the specified object, but only if it is already\n                        //in there. In sync environments, it may not be yet.\n                        if (oldFullName in specified) {\n                            delete specified[oldFullName];\n                            specified[fullName] = true;\n                        }\n\n                        //Update managerCallbacks to use the correct normalized name.\n                        //If there are already callbacks for the normalized name,\n                        //just add to them.\n                        if (existingCallbacks) {\n                            managerCallbacks[fullName] = existingCallbacks.concat(callbacks);\n                        } else {\n                            managerCallbacks[fullName] = callbacks;\n                        }\n                        delete managerCallbacks[oldFullName];\n\n                        //In each manager callback, update the normalized name in the depArray.\n                        for (j = 0; j < callbacks.length; j++) {\n                            depArray = callbacks[j].depArray;\n                            for (k = 0; k < depArray.length; k++) {\n                                if (depArray[k] === oldFullName) {\n                                    depArray[k] = fullName;\n                                }\n                            }\n                        }\n                    }\n                }\n            }\n\n            delete normalizedWaiting[pluginName];\n        }\n\n        /*\n         * Queues a dependency for checking after the loader is out of a\n         * \"paused\" state, for example while a script file is being loaded\n         * in the browser, where it may have many modules defined in it.\n         *\n         * depName will be fully qualified, no relative . or .. path.\n         */\n        function queueDependency(dep) {\n            //Make sure to load any plugin and associate the dependency\n            //with that plugin.\n            var prefix = dep.prefix,\n                fullName = dep.fullName;\n\n            //Do not bother if the depName is already in transit\n            if (specified[fullName] || fullName in defined) {\n                return;\n            }\n\n            if (prefix && !plugins[prefix]) {\n                //Queue up loading of the dependency, track it\n                //via context.plugins. Mark it as a plugin so\n                //that the build system will know to treat it\n                //special.\n                plugins[prefix] = undefined;\n\n                //Remember this dep that needs to have normaliztion done\n                //after the plugin loads.\n                (normalizedWaiting[prefix] || (normalizedWaiting[prefix] = []))\n                    .push(dep);\n\n                //Register an action to do once the plugin loads, to update\n                //all managerCallbacks to use a properly normalized module\n                //name.\n                (managerCallbacks[prefix] ||\n                (managerCallbacks[prefix] = [])).push({\n                    onDep: function (name, value) {\n                        if (name === prefix) {\n                            updateNormalizedNames(prefix);\n                        }\n                    }\n                });\n\n                queueDependency(makeModuleMap(prefix));\n            }\n\n            context.paused.push(dep);\n        }\n\n        function execManager(manager) {\n            var i, ret, waitingCallbacks, err,\n                cb = manager.callback,\n                fullName = manager.fullName,\n                args = [],\n                ary = manager.depArray;\n\n            //Call the callback to define the module, if necessary.\n            if (cb && isFunction(cb)) {\n                //Pull out the defined dependencies and pass the ordered\n                //values to the callback.\n                if (ary) {\n                    for (i = 0; i < ary.length; i++) {\n                        args.push(manager.deps[ary[i]]);\n                    }\n                }\n\n                try {\n                    ret = req.execCb(fullName, manager.callback, args, defined[fullName]);\n                } catch (e) {\n                    err = e;\n                }\n\n                if (fullName) {\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 (manager.cjsModule && manager.cjsModule.exports !== undefined) {\n                        ret = defined[fullName] = manager.cjsModule.exports;\n                    } else if (ret === undefined && manager.usingExports) {\n                        //exports already set the defined value.\n                        ret = defined[fullName];\n                    } else {\n                        //Use the return value from the function.\n                        defined[fullName] = ret;\n                    }\n                }\n            } else if (fullName) {\n                //May just be an object definition for the module. Only\n                //worry about defining if have a module name.\n                ret = defined[fullName] = cb;\n            }\n\n            //Clean up waiting. Do this before error calls, and before\n            //calling back waitingCallbacks, so that bookkeeping is correct\n            //in the event of an error and error is reported in correct order,\n            //since the waitingCallbacks will likely have errors if the\n            //onError function does not throw.\n            if (waiting[manager.waitId]) {\n                delete waiting[manager.waitId];\n                manager.isDone = true;\n                context.waitCount -= 1;\n                if (context.waitCount === 0) {\n                    //Clear the wait array used for cycles.\n                    waitAry = [];\n                }\n            }\n\n            if (err) {\n                err = makeError('defineerror', 'Error evaluating ' +\n                                'module \"' + fullName + '\" at location \"' +\n                                (fullName ? makeModuleMap(fullName).url : '') + '\":\\n' +\n                                err + '\\nfileName:' + (err.fileName || err.sourceURL) +\n                                '\\nlineNumber: ' + (err.lineNumber || err.line), err);\n                err.moduleName = fullName;\n                return req.onError(err);\n            }\n\n            if (fullName) {\n                //If anything was waiting for this module to be defined,\n                //notify them now.\n                waitingCallbacks = managerCallbacks[fullName];\n                if (waitingCallbacks) {\n                    for (i = 0; i < waitingCallbacks.length; i++) {\n                        waitingCallbacks[i].onDep(fullName, ret);\n                    }\n                    delete managerCallbacks[fullName];\n                }\n            }\n\n            return undefined;\n        }\n\n        function main(inName, depArray, callback, relModuleMap) {\n            var moduleMap = makeModuleMap(inName, relModuleMap),\n                name = moduleMap.name,\n                fullName = moduleMap.fullName,\n                uniques = {},\n                manager = {\n                    //Use a wait ID because some entries are anon\n                    //async require calls.\n                    waitId: name || reqWaitIdPrefix + (waitIdCounter++),\n                    depCount: 0,\n                    depMax: 0,\n                    prefix: moduleMap.prefix,\n                    name: name,\n                    fullName: fullName,\n                    deps: {},\n                    depArray: depArray,\n                    callback: callback,\n                    onDep: function (depName, value) {\n                        if (!(depName in manager.deps)) {\n                            manager.deps[depName] = value;\n                            manager.depCount += 1;\n                            if (manager.depCount === manager.depMax) {\n                                //All done, execute!\n                                execManager(manager);\n                            }\n                        }\n                    }\n                },\n                i, depArg, depName, cjsMod;\n\n            if (fullName) {\n                //If module already defined for context, or already loaded,\n                //then leave. Also leave if jQuery is registering but it does\n                //not match the desired version number in the config.\n                if (fullName in defined || loaded[fullName] === true ||\n                    (fullName === \"jquery\" && config.jQuery &&\n                     config.jQuery !== callback().fn.jquery)) {\n                    return;\n                }\n\n                //Set specified/loaded here for modules that are also loaded\n                //as part of a layer, where onScriptLoad is not fired\n                //for those cases. Do this after the inline define and\n                //dependency tracing is done.\n                specified[fullName] = true;\n                loaded[fullName] = true;\n\n                //If module is jQuery set up delaying its dom ready listeners.\n                if (fullName === \"jquery\" && callback) {\n                    jQueryCheck(callback());\n                }\n            }\n\n            //Add the dependencies to the deps field, and register for callbacks\n            //on the dependencies.\n            for (i = 0; i < depArray.length; i++) {\n                depArg = depArray[i];\n                //There could be cases like in IE, where a trailing comma will\n                //introduce a null dependency, so only treat a real dependency\n                //value as a dependency.\n                if (depArg) {\n                    //Split the dependency name into plugin and name parts\n                    depArg = makeModuleMap(depArg, (name ? moduleMap : relModuleMap));\n                    depName = depArg.fullName;\n\n                    //Fix the name in depArray to be just the name, since\n                    //that is how it will be called back later.\n                    depArray[i] = depName;\n\n                    //Fast path CommonJS standard dependencies.\n                    if (depName === \"require\") {\n                        manager.deps[depName] = makeRequire(moduleMap);\n                    } else if (depName === \"exports\") {\n                        //CommonJS module spec 1.1\n                        manager.deps[depName] = defined[fullName] = {};\n                        manager.usingExports = true;\n                    } else if (depName === \"module\") {\n                        //CommonJS module spec 1.1\n                        manager.cjsModule = cjsMod = manager.deps[depName] = {\n                            id: name,\n                            uri: name ? context.nameToUrl(name, null, relModuleMap) : undefined,\n                            exports: defined[fullName]\n                        };\n                        cjsMod.setExports = makeSetExports(cjsMod);\n                    } else if (depName in defined && !(depName in waiting)) {\n                        //Module already defined, no need to wait for it.\n                        manager.deps[depName] = defined[depName];\n                    } else if (!uniques[depName]) {\n\n                        //A dynamic dependency.\n                        manager.depMax += 1;\n\n                        queueDependency(depArg);\n\n                        //Register to get notification when dependency loads.\n                        (managerCallbacks[depName] ||\n                        (managerCallbacks[depName] = [])).push(manager);\n\n                        uniques[depName] = true;\n                    }\n                }\n            }\n\n            //Do not bother tracking the manager if it is all done.\n            if (manager.depCount === manager.depMax) {\n                //All done, execute!\n                execManager(manager);\n            } else {\n                waiting[manager.waitId] = manager;\n                waitAry.push(manager);\n                context.waitCount += 1;\n            }\n        }\n\n        /**\n         * Convenience method to call main for a define call that was put on\n         * hold in the defQueue.\n         */\n        function callDefMain(args) {\n            main.apply(null, args);\n            //Mark the module loaded. Must do it here in addition\n            //to doing it in define in case a script does\n            //not call define\n            loaded[args[0]] = true;\n        }\n\n        /**\n         * jQuery 1.4.3+ supports ways to hold off calling\n         * calling jQuery ready callbacks until all scripts are loaded. Be sure\n         * to track it if the capability exists.. Also, since jQuery 1.4.3 does\n         * not register as a module, need to do some global inference checking.\n         * Even if it does register as a module, not guaranteed to be the precise\n         * name of the global. If a jQuery is tracked for this context, then go\n         * ahead and register it as a module too, if not already in process.\n         */\n        jQueryCheck = function (jqCandidate) {\n            if (!context.jQuery) {\n                var $ = jqCandidate || (typeof jQuery !== \"undefined\" ? jQuery : null);\n\n                if ($) {\n                    //If a specific version of jQuery is wanted, make sure to only\n                    //use this jQuery if it matches.\n                    if (config.jQuery && $.fn.jquery !== config.jQuery) {\n                        return;\n                    }\n\n                    if (\"holdReady\" in $ || \"readyWait\" in $) {\n                        context.jQuery = $;\n\n                        //Manually create a \"jquery\" module entry if not one already\n                        //or in process. Note this could trigger an attempt at\n                        //a second jQuery registration, but does no harm since\n                        //the first one wins, and it is the same value anyway.\n                        callDefMain([\"jquery\", [], function () {\n                            return jQuery;\n                        }]);\n\n                        //Ask jQuery to hold DOM ready callbacks.\n                        if (context.scriptCount) {\n                            jQueryHoldReady($, true);\n                            context.jQueryIncremented = true;\n                        }\n                    }\n                }\n            }\n        };\n\n        function forceExec(manager, traced) {\n            if (manager.isDone) {\n                return undefined;\n            }\n\n            var fullName = manager.fullName,\n                depArray = manager.depArray,\n                depName, i;\n            if (fullName) {\n                if (traced[fullName]) {\n                    return defined[fullName];\n                }\n\n                traced[fullName] = true;\n            }\n\n            //forceExec all of its dependencies.\n            for (i = 0; i < depArray.length; i++) {\n                //Some array members may be null, like if a trailing comma\n                //IE, so do the explicit [i] access and check if it has a value.\n                depName = depArray[i];\n                if (depName) {\n                    if (!manager.deps[depName] && waiting[depName]) {\n                        manager.onDep(depName, forceExec(waiting[depName], traced));\n                    }\n                }\n            }\n\n            return fullName ? defined[fullName] : undefined;\n        }\n\n        /**\n         * Checks if all modules for a context are loaded, and if so, evaluates the\n         * new ones in right dependency order.\n         *\n         * @private\n         */\n        function checkLoaded() {\n            var waitInterval = config.waitSeconds * 1000,\n                //It is possible to disable the wait interval by using waitSeconds of 0.\n                expired = waitInterval && (context.startTime + waitInterval) < new Date().getTime(),\n                noLoads = \"\", hasLoadedProp = false, stillLoading = false, prop,\n                err, manager;\n\n            //If there are items still in the paused queue processing wait.\n            //This is particularly important in the sync case where each paused\n            //item is processed right away but there may be more waiting.\n            if (context.pausedCount > 0) {\n                return undefined;\n            }\n\n            //Determine if priority loading is done. If so clear the priority. If\n            //not, then do not check\n            if (config.priorityWait) {\n                if (isPriorityDone()) {\n                    //Call resume, since it could have\n                    //some waiting dependencies to trace.\n                    resume();\n                } else {\n                    return undefined;\n                }\n            }\n\n            //See if anything is still in flight.\n            for (prop in loaded) {\n                if (!(prop in empty)) {\n                    hasLoadedProp = true;\n                    if (!loaded[prop]) {\n                        if (expired) {\n                            noLoads += prop + \" \";\n                        } else {\n                            stillLoading = true;\n                            break;\n                        }\n                    }\n                }\n            }\n\n            //Check for exit conditions.\n            if (!hasLoadedProp && !context.waitCount) {\n                //If the loaded object had no items, then the rest of\n                //the work below does not need to be done.\n                return undefined;\n            }\n            if (expired && noLoads) {\n                //If wait time expired, throw error of unloaded modules.\n                err = makeError(\"timeout\", \"Load timeout for modules: \" + noLoads);\n                err.requireType = \"timeout\";\n                err.requireModules = noLoads;\n                return req.onError(err);\n            }\n            if (stillLoading || context.scriptCount) {\n                //Something is still waiting to load. Wait for it, but only\n                //if a timeout is not already in effect.\n                if ((isBrowser || isWebWorker) && !checkLoadedTimeoutId) {\n                    checkLoadedTimeoutId = setTimeout(function () {\n                        checkLoadedTimeoutId = 0;\n                        checkLoaded();\n                    }, 50);\n                }\n                return undefined;\n            }\n\n            //If still have items in the waiting cue, but all modules have\n            //been loaded, then it means there are some circular dependencies\n            //that need to be broken.\n            //However, as a waiting thing is fired, then it can add items to\n            //the waiting cue, and those items should not be fired yet, so\n            //make sure to redo the checkLoaded call after breaking a single\n            //cycle, if nothing else loaded then this logic will pick it up\n            //again.\n            if (context.waitCount) {\n                //Cycle through the waitAry, and call items in sequence.\n                for (i = 0; (manager = waitAry[i]); i++) {\n                    forceExec(manager, {});\n                }\n\n                //Only allow this recursion to a certain depth. Only\n                //triggered by errors in calling a module in which its\n                //modules waiting on it cannot finish loading, or some circular\n                //dependencies that then may add more dependencies.\n                //The value of 5 is a bit arbitrary. Hopefully just one extra\n                //pass, or two for the case of circular dependencies generating\n                //more work that gets resolved in the sync node case.\n                if (checkLoadedDepth < 5) {\n                    checkLoadedDepth += 1;\n                    checkLoaded();\n                }\n            }\n\n            checkLoadedDepth = 0;\n\n            //Check for DOM ready, and nothing is waiting across contexts.\n            req.checkReadyState();\n\n            return undefined;\n        }\n\n        function callPlugin(pluginName, dep) {\n            var name = dep.name,\n                fullName = dep.fullName,\n                load;\n\n            //Do not bother if plugin is already defined or being loaded.\n            if (fullName in defined || fullName in loaded) {\n                return;\n            }\n\n            if (!plugins[pluginName]) {\n                plugins[pluginName] = defined[pluginName];\n            }\n\n            //Only set loaded to false for tracking if it has not already been set.\n            if (!loaded[fullName]) {\n                loaded[fullName] = false;\n            }\n\n            load = function (ret) {\n                //Allow the build process to register plugin-loaded dependencies.\n                if (req.onPluginLoad) {\n                    req.onPluginLoad(context, pluginName, name, ret);\n                }\n\n                execManager({\n                    prefix: dep.prefix,\n                    name: dep.name,\n                    fullName: dep.fullName,\n                    callback: function () {\n                        return ret;\n                    }\n                });\n                loaded[fullName] = true;\n            };\n\n            //Allow plugins to load other code without having to know the\n            //context or how to \"complete\" the load.\n            load.fromText = function (moduleName, text) {\n                /*jslint evil: true */\n                var hasInteractive = useInteractive;\n\n                //Indicate a the module is in process of loading.\n                context.loaded[moduleName] = false;\n                context.scriptCount += 1;\n\n                //Turn off interactive script matching for IE for any define\n                //calls in the text, then turn it back on at the end.\n                if (hasInteractive) {\n                    useInteractive = false;\n                }\n\n                req.exec(text);\n\n                if (hasInteractive) {\n                    useInteractive = true;\n                }\n\n                //Support anonymous modules.\n                context.completeLoad(moduleName);\n            };\n\n            //Use parentName here since the plugin's name is not reliable,\n            //could be some weird string with no path that actually wants to\n            //reference the parentName's path.\n            plugins[pluginName].load(name, makeRequire(dep.parentMap, true), load, config);\n        }\n\n        function loadPaused(dep) {\n            //Renormalize dependency if its name was waiting on a plugin\n            //to load, which as since loaded.\n            if (dep.prefix && dep.name.indexOf('__$p') === 0 && defined[dep.prefix]) {\n                dep = makeModuleMap(dep.originalName, dep.parentMap);\n            }\n\n            var pluginName = dep.prefix,\n                fullName = dep.fullName,\n                urlFetched = context.urlFetched;\n\n            //Do not bother if the dependency has already been specified.\n            if (specified[fullName] || loaded[fullName]) {\n                return;\n            } else {\n                specified[fullName] = true;\n            }\n\n            if (pluginName) {\n                //If plugin not loaded, wait for it.\n                //set up callback list. if no list, then register\n                //managerCallback for that plugin.\n                if (defined[pluginName]) {\n                    callPlugin(pluginName, dep);\n                } else {\n                    if (!pluginsQueue[pluginName]) {\n                        pluginsQueue[pluginName] = [];\n                        (managerCallbacks[pluginName] ||\n                        (managerCallbacks[pluginName] = [])).push({\n                            onDep: function (name, value) {\n                                if (name === pluginName) {\n                                    var i, oldModuleMap, ary = pluginsQueue[pluginName];\n\n                                    //Now update all queued plugin actions.\n                                    for (i = 0; i < ary.length; i++) {\n                                        oldModuleMap = ary[i];\n                                        //Update the moduleMap since the\n                                        //module name may be normalized\n                                        //differently now.\n                                        callPlugin(pluginName,\n                                                   makeModuleMap(oldModuleMap.originalName, oldModuleMap.parentMap));\n                                    }\n                                    delete pluginsQueue[pluginName];\n                                }\n                            }\n                        });\n                    }\n                    pluginsQueue[pluginName].push(dep);\n                }\n            } else {\n                if (!urlFetched[dep.url]) {\n                    req.load(context, fullName, dep.url);\n                    urlFetched[dep.url] = true;\n                }\n            }\n        }\n\n        /**\n         * Resumes tracing of dependencies and then checks if everything is loaded.\n         */\n        resume = function () {\n            var args, i, p;\n\n            resumeDepth += 1;\n\n            if (context.scriptCount <= 0) {\n                //Synchronous envs will push the number below zero with the\n                //decrement above, be sure to set it back to zero for good measure.\n                //require() calls that also do not end up loading scripts could\n                //push the number negative too.\n                context.scriptCount = 0;\n            }\n\n            //Make sure any remaining defQueue items get properly processed.\n            while (defQueue.length) {\n                args = defQueue.shift();\n                if (args[0] === null) {\n                    return req.onError(makeError('mismatch', 'Mismatched anonymous define() module: ' + args[args.length - 1]));\n                } else {\n                    callDefMain(args);\n                }\n            }\n\n            //Skip the resume of paused dependencies\n            //if current context is in priority wait.\n            if (!config.priorityWait || isPriorityDone()) {\n                while (context.paused.length) {\n                    p = context.paused;\n                    context.pausedCount += p.length;\n                    //Reset paused list\n                    context.paused = [];\n\n                    for (i = 0; (args = p[i]); i++) {\n                        loadPaused(args);\n                    }\n                    //Move the start time for timeout forward.\n                    context.startTime = (new Date()).getTime();\n                    context.pausedCount -= p.length;\n                }\n            }\n\n            //Only check if loaded when resume depth is 1. It is likely that\n            //it is only greater than 1 in sync environments where a factory\n            //function also then calls the callback-style require. In those\n            //cases, the checkLoaded should not occur until the resume\n            //depth is back at the top level.\n            if (resumeDepth === 1) {\n                checkLoaded();\n            }\n\n            resumeDepth -= 1;\n\n            return undefined;\n        };\n\n        //Define the context object. Many of these fields are on here\n        //just to make debugging easier.\n        context = {\n            contextName: contextName,\n            config: config,\n            defQueue: defQueue,\n            waiting: waiting,\n            waitCount: 0,\n            specified: specified,\n            loaded: loaded,\n            urlMap: urlMap,\n            scriptCount: 0,\n            urlFetched: {},\n            defined: defined,\n            paused: [],\n            pausedCount: 0,\n            plugins: plugins,\n            managerCallbacks: managerCallbacks,\n            makeModuleMap: makeModuleMap,\n            normalize: normalize,\n            /**\n             * Set a configuration for the context.\n             * @param {Object} cfg config object to integrate.\n             */\n            configure: function (cfg) {\n                var paths, prop, packages, pkgs, packagePaths, requireWait;\n\n                //Make sure the baseUrl ends in a slash.\n                if (cfg.baseUrl) {\n                    if (cfg.baseUrl.charAt(cfg.baseUrl.length - 1) !== \"/\") {\n                        cfg.baseUrl += \"/\";\n                    }\n                }\n\n                //Save off the paths and packages since they require special processing,\n                //they are additive.\n                paths = config.paths;\n                packages = config.packages;\n                pkgs = config.pkgs;\n\n                //Mix in the config values, favoring the new values over\n                //existing ones in context.config.\n                mixin(config, cfg, true);\n\n                //Adjust paths if necessary.\n                if (cfg.paths) {\n                    for (prop in cfg.paths) {\n                        if (!(prop in empty)) {\n                            paths[prop] = cfg.paths[prop];\n                        }\n                    }\n                    config.paths = paths;\n                }\n\n                packagePaths = cfg.packagePaths;\n                if (packagePaths || cfg.packages) {\n                    //Convert packagePaths into a packages config.\n                    if (packagePaths) {\n                        for (prop in packagePaths) {\n                            if (!(prop in empty)) {\n                                configurePackageDir(pkgs, packagePaths[prop], prop);\n                            }\n                        }\n                    }\n\n                    //Adjust packages if necessary.\n                    if (cfg.packages) {\n                        configurePackageDir(pkgs, cfg.packages);\n                    }\n\n                    //Done with modifications, assing packages back to context config\n                    config.pkgs = pkgs;\n                }\n\n                //If priority loading is in effect, trigger the loads now\n                if (cfg.priority) {\n                    //Hold on to requireWait value, and reset it after done\n                    requireWait = context.requireWait;\n\n                    //Allow tracing some require calls to allow the fetching\n                    //of the priority config.\n                    context.requireWait = false;\n\n                    //But first, call resume to register any defined modules that may\n                    //be in a data-main built file before the priority config\n                    //call. Also grab any waiting define calls for this context.\n                    context.takeGlobalQueue();\n                    resume();\n\n                    context.require(cfg.priority);\n\n                    //Trigger a resume right away, for the case when\n                    //the script with the priority load is done as part\n                    //of a data-main call. In that case the normal resume\n                    //call will not happen because the scriptCount will be\n                    //at 1, since the script for data-main is being processed.\n                    resume();\n\n                    //Restore previous state.\n                    context.requireWait = requireWait;\n                    config.priorityWait = cfg.priority;\n                }\n\n                //If a deps array or a config callback is specified, then call\n                //require with those args. This is useful when require is defined as a\n                //config object before require.js is loaded.\n                if (cfg.deps || cfg.callback) {\n                    context.require(cfg.deps || [], cfg.callback);\n                }\n\n                //Set up ready callback, if asked. Useful when require is defined as a\n                //config object before require.js is loaded.\n                if (cfg.ready) {\n                    req.ready(cfg.ready);\n                }\n            },\n\n            requireDefined: function (moduleName, relModuleMap) {\n                return makeModuleMap(moduleName, relModuleMap).fullName in defined;\n            },\n\n            requireSpecified: function (moduleName, relModuleMap) {\n                return makeModuleMap(moduleName, relModuleMap).fullName in specified;\n            },\n\n            require: function (deps, callback, relModuleMap) {\n                var moduleName, fullName, moduleMap;\n                if (typeof deps === \"string\") {\n                    //Synchronous access to one module. If require.get is\n                    //available (as in the Node adapter), prefer that.\n                    //In this case deps is the moduleName and callback is\n                    //the relModuleMap\n                    if (req.get) {\n                        return req.get(context, deps, callback);\n                    }\n\n                    //Just return the module wanted. In this scenario, the\n                    //second arg (if passed) is just the relModuleMap.\n                    moduleName = deps;\n                    relModuleMap = callback;\n\n                    //Normalize module name, if it contains . or ..\n                    moduleMap = makeModuleMap(moduleName, relModuleMap);\n                    fullName = moduleMap.fullName;\n\n                    if (!(fullName in defined)) {\n                        return req.onError(makeError(\"notloaded\", \"Module name '\" +\n                                    moduleMap.fullName +\n                                    \"' has not been loaded yet for context: \" +\n                                    contextName));\n                    }\n                    return defined[fullName];\n                }\n\n                main(null, deps, callback, relModuleMap);\n\n                //If the require call does not trigger anything new to load,\n                //then resume the dependency processing.\n                if (!context.requireWait) {\n                    while (!context.scriptCount && context.paused.length) {\n                        //For built layers, there can be some defined\n                        //modules waiting for intake into the context,\n                        //in particular module plugins. Take them.\n                        context.takeGlobalQueue();\n                        resume();\n                    }\n                }\n                return undefined;\n            },\n\n            /**\n             * Internal method to transfer globalQueue items to this context's\n             * defQueue.\n             */\n            takeGlobalQueue: function () {\n                //Push all the globalDefQueue items into the context's defQueue\n                if (globalDefQueue.length) {\n                    //Array splice in the values since the context code has a\n                    //local var ref to defQueue, so cannot just reassign the one\n                    //on context.\n                    apsp.apply(context.defQueue,\n                               [context.defQueue.length - 1, 0].concat(globalDefQueue));\n                    globalDefQueue = [];\n                }\n            },\n\n            /**\n             * Internal method used by environment adapters to complete a load event.\n             * A load event could be a script load or just a load pass from a synchronous\n             * load call.\n             * @param {String} moduleName the name of the module to potentially complete.\n             */\n            completeLoad: function (moduleName) {\n                var args;\n\n                context.takeGlobalQueue();\n\n                while (defQueue.length) {\n                    args = defQueue.shift();\n\n                    if (args[0] === null) {\n                        args[0] = moduleName;\n                        break;\n                    } else if (args[0] === moduleName) {\n                        //Found matching define call for this script!\n                        break;\n                    } else {\n                        //Some other named define call, most likely the result\n                        //of a build layer that included many define calls.\n                        callDefMain(args);\n                        args = null;\n                    }\n                }\n                if (args) {\n                    callDefMain(args);\n                } else {\n                    //A script that does not call define(), so just simulate\n                    //the call for it. Special exception for jQuery dynamic load.\n                    callDefMain([moduleName, [],\n                                moduleName === \"jquery\" && typeof jQuery !== \"undefined\" ?\n                                function () {\n                                    return jQuery;\n                                } : null]);\n                }\n\n                //Mark the script as loaded. Note that this can be different from a\n                //moduleName that maps to a define call. This line is important\n                //for traditional browser scripts.\n                loaded[moduleName] = true;\n\n                //If a global jQuery is defined, check for it. Need to do it here\n                //instead of main() since stock jQuery does not register as\n                //a module via define.\n                jQueryCheck();\n\n                //Doing this scriptCount decrement branching because sync envs\n                //need to decrement after resume, otherwise it looks like\n                //loading is complete after the first dependency is fetched.\n                //For browsers, it works fine to decrement after, but it means\n                //the checkLoaded setTimeout 50 ms cost is taken. To avoid\n                //that cost, decrement beforehand.\n                if (req.isAsync) {\n                    context.scriptCount -= 1;\n                }\n                resume();\n                if (!req.isAsync) {\n                    context.scriptCount -= 1;\n                }\n            },\n\n            /**\n             * Converts a module name + .extension into an URL path.\n             * *Requires* the use of a module name. It does not support using\n             * plain URLs like nameToUrl.\n             */\n            toUrl: function (moduleNamePlusExt, relModuleMap) {\n                var index = moduleNamePlusExt.lastIndexOf(\".\"),\n                    ext = null;\n\n                if (index !== -1) {\n                    ext = moduleNamePlusExt.substring(index, moduleNamePlusExt.length);\n                    moduleNamePlusExt = moduleNamePlusExt.substring(0, index);\n                }\n\n                return context.nameToUrl(moduleNamePlusExt, ext, relModuleMap);\n            },\n\n            /**\n             * Converts a module name to a file path. Supports cases where\n             * moduleName may actually be just an URL.\n             */\n            nameToUrl: function (moduleName, ext, relModuleMap) {\n                var paths, pkgs, pkg, pkgPath, syms, i, parentModule, url,\n                    config = context.config;\n\n                //Normalize module name if have a base relative module name to work from.\n                moduleName = normalize(moduleName, relModuleMap && relModuleMap.fullName);\n\n                //If a colon is in the URL, it indicates a protocol is used and it is just\n                //an URL to a file, or if it starts with a slash or ends with .js, it is just a plain file.\n                //The slash is important for protocol-less URLs as well as full paths.\n                if (req.jsExtRegExp.test(moduleName)) {\n                    //Just a plain path, not module name lookup, so just return it.\n                    //Add extension if it is included. This is a bit wonky, only non-.js things pass\n                    //an extension, this method probably needs to be reworked.\n                    url = moduleName + (ext ? ext : \"\");\n                } else {\n                    //A module that needs to be converted to a path.\n                    paths = config.paths;\n                    pkgs = config.pkgs;\n\n                    syms = moduleName.split(\"/\");\n                    //For each module name segment, see if there is a path\n                    //registered for it. Start with most specific name\n                    //and work up from it.\n                    for (i = syms.length; i > 0; i--) {\n                        parentModule = syms.slice(0, i).join(\"/\");\n                        if (paths[parentModule]) {\n                            syms.splice(0, i, paths[parentModule]);\n                            break;\n                        } else if ((pkg = pkgs[parentModule])) {\n                            //If module name is just the package name, then looking\n                            //for the main module.\n                            if (moduleName === pkg.name) {\n                                pkgPath = pkg.location + '/' + pkg.main;\n                            } else {\n                                pkgPath = pkg.location;\n                            }\n                            syms.splice(0, i, pkgPath);\n                            break;\n                        }\n                    }\n\n                    //Join the path parts together, then figure out if baseUrl is needed.\n                    url = syms.join(\"/\") + (ext || \".js\");\n                    url = (url.charAt(0) === '/' || url.match(/^\\w+:/) ? \"\" : config.baseUrl) + url;\n                }\n\n                return config.urlArgs ? url +\n                                        ((url.indexOf('?') === -1 ? '?' : '&') +\n                                         config.urlArgs) : url;\n            }\n        };\n\n        //Make these visible on the context so can be called at the very\n        //end of the file to bootstrap\n        context.jQueryCheck = jQueryCheck;\n        context.resume = resume;\n\n        return context;\n    }\n\n    /**\n     * Main entry point.\n     *\n     * If the only argument to require is a string, then the module that\n     * is represented by that string is fetched for the appropriate context.\n     *\n     * If the first argument is an array, then it will be treated as an array\n     * of dependency string names to fetch. An optional function callback can\n     * be specified to execute when all of those dependencies are available.\n     *\n     * Make a local req variable to help Caja compliance (it assumes things\n     * on a require that are not standardized), and to give a short\n     * name for minification/local scope use.\n     */\n    req = requirejs = function (deps, callback) {\n\n        //Find the right context, use default\n        var contextName = defContextName,\n            context, config;\n\n        // Determine if have config object in the call.\n        if (!isArray(deps) && typeof deps !== \"string\") {\n            // deps is a config object\n            config = deps;\n            if (isArray(callback)) {\n                // Adjust args if there are dependencies\n                deps = callback;\n                callback = arguments[2];\n            } else {\n                deps = [];\n            }\n        }\n\n        if (config && config.context) {\n            contextName = config.context;\n        }\n\n        context = contexts[contextName] ||\n                  (contexts[contextName] = newContext(contextName));\n\n        if (config) {\n            context.configure(config);\n        }\n\n        return context.require(deps, callback);\n    };\n\n    /**\n     * Export require as a global, but only if it does not already exist.\n     */\n    if (typeof require === \"undefined\") {\n        require = req;\n    }\n\n    /**\n     * Global require.toUrl(), to match global require, mostly useful\n     * for debugging/work in the global space.\n     */\n    req.toUrl = function (moduleNamePlusExt) {\n        return contexts[defContextName].toUrl(moduleNamePlusExt);\n    };\n\n    req.version = version;\n    req.isArray = isArray;\n    req.isFunction = isFunction;\n    req.mixin = mixin;\n    //Used to filter out dependencies that are already paths.\n    req.jsExtRegExp = /^\\/|:|\\?|\\.js$/;\n    s = req.s = {\n        contexts: contexts,\n        //Stores a list of URLs that should not get async script tag treatment.\n        skipAsync: {},\n        isPageLoaded: !isBrowser,\n        readyCalls: []\n    };\n\n    req.isAsync = req.isBrowser = isBrowser;\n    if (isBrowser) {\n        head = s.head = document.getElementsByTagName(\"head\")[0];\n        //If BASE tag is in play, using appendChild is a problem for IE6.\n        //When that browser dies, this can be removed. Details in this jQuery bug:\n        //http://dev.jquery.com/ticket/2709\n        baseElement = document.getElementsByTagName(\"base\")[0];\n        if (baseElement) {\n            head = s.head = baseElement.parentNode;\n        }\n    }\n\n    /**\n     * Any errors that require explicitly generates will be passed to this\n     * function. Intercept/override it if you want custom error handling.\n     * @param {Error} err the error object.\n     */\n    req.onError = function (err) {\n        throw err;\n    };\n\n    /**\n     * Does the request to load a module for the browser case.\n     * Make this a separate function to allow other environments\n     * to override it.\n     *\n     * @param {Object} context the require context to find state.\n     * @param {String} moduleName the name of the module.\n     * @param {Object} url the URL to the module.\n     */\n    req.load = function (context, moduleName, url) {\n        var loaded = context.loaded;\n\n        isDone = false;\n\n        //Only set loaded to false for tracking if it has not already been set.\n        if (!loaded[moduleName]) {\n            loaded[moduleName] = false;\n        }\n\n        context.scriptCount += 1;\n        req.attach(url, context, moduleName);\n\n        //If tracking a jQuery, then make sure its ready callbacks\n        //are put on hold to prevent its ready callbacks from\n        //triggering too soon.\n        if (context.jQuery && !context.jQueryIncremented) {\n            jQueryHoldReady(context.jQuery, true);\n            context.jQueryIncremented = true;\n        }\n    };\n\n    function getInteractiveScript() {\n        var scripts, i, script;\n        if (interactiveScript && interactiveScript.readyState === 'interactive') {\n            return interactiveScript;\n        }\n\n        scripts = document.getElementsByTagName('script');\n        for (i = scripts.length - 1; i > -1 && (script = scripts[i]); i--) {\n            if (script.readyState === 'interactive') {\n                return (interactiveScript = script);\n            }\n        }\n\n        return null;\n    }\n\n    /**\n     * The function that handles definitions of modules. Differs from\n     * require() in that a string for the module should be the first argument,\n     * and the function to execute after dependencies are loaded should\n     * return a value to define the module corresponding to the first argument's\n     * name.\n     */\n    define = req.def = function (name, deps, callback) {\n        var node, context;\n\n        //Allow for anonymous functions\n        if (typeof name !== 'string') {\n            //Adjust args appropriately\n            callback = deps;\n            deps = name;\n            name = null;\n        }\n\n        //This module may not have dependencies\n        if (!req.isArray(deps)) {\n            callback = deps;\n            deps = [];\n        }\n\n        //If no name, and callback is a function, then figure out if it a\n        //CommonJS thing with dependencies.\n        if (!name && !deps.length && req.isFunction(callback)) {\n            //Remove comments from the callback string,\n            //look for require calls, and pull them into the dependencies,\n            //but only if there are function args.\n            if (callback.length) {\n                callback\n                    .toString()\n                    .replace(commentRegExp, \"\")\n                    .replace(cjsRequireRegExp, function (match, dep) {\n                        deps.push(dep);\n                    });\n\n                //May be a CommonJS thing even without require calls, but still\n                //could use exports, and module. Avoid doing exports and module\n                //work though if it just needs require.\n                //REQUIRES the function to expect the CommonJS variables in the\n                //order listed below.\n                deps = (callback.length === 1 ? [\"require\"] : [\"require\", \"exports\", \"module\"]).concat(deps);\n            }\n        }\n\n        //If in IE 6-8 and hit an anonymous define() call, do the interactive\n        //work.\n        if (useInteractive) {\n            node = currentlyAddingScript || getInteractiveScript();\n            if (!node) {\n                return req.onError(makeError(\"interactive\", \"No matching script interactive for \" + callback));\n            }\n            if (!name) {\n                name = node.getAttribute(\"data-requiremodule\");\n            }\n            context = contexts[node.getAttribute(\"data-requirecontext\")];\n        }\n\n        //Always save off evaluating the def call until the script onload handler.\n        //This allows multiple modules to be in a file without prematurely\n        //tracing dependencies, and allows for anonymous module support,\n        //where the module name is not known until the script onload event\n        //occurs. If no context, use the global queue, and get it processed\n        //in the onscript load callback.\n        (context ? context.defQueue : globalDefQueue).push([name, deps, callback]);\n\n        return undefined;\n    };\n\n    define.amd = {\n        multiversion: true,\n        plugins: true,\n        jQuery: true\n    };\n\n    /**\n     * Executes the text. Normally just uses eval, but can be modified\n     * to use a more environment specific call.\n     * @param {String} text the text to execute/evaluate.\n     */\n    req.exec = function (text) {\n        return eval(text);\n    };\n\n    /**\n     * Executes a module callack function. Broken out as a separate function\n     * solely to allow the build system to sequence the files in the built\n     * layer in the right sequence.\n     *\n     * @private\n     */\n    req.execCb = function (name, callback, args, exports) {\n        return callback.apply(exports, args);\n    };\n\n    /**\n     * callback for script loads, used to check status of loading.\n     *\n     * @param {Event} evt the event from the browser for the script\n     * that was loaded.\n     *\n     * @private\n     */\n    req.onScriptLoad = function (evt) {\n        //Using currentTarget instead of target for Firefox 2.0's sake. Not\n        //all old browsers will be supported, but this one was easy enough\n        //to support and still makes sense.\n        var node = evt.currentTarget || evt.srcElement, contextName, moduleName,\n            context;\n\n        if (evt.type === \"load\" || readyRegExp.test(node.readyState)) {\n            //Reset interactive script so a script node is not held onto for\n            //to long.\n            interactiveScript = null;\n\n            //Pull out the name of the module and the context.\n            contextName = node.getAttribute(\"data-requirecontext\");\n            moduleName = node.getAttribute(\"data-requiremodule\");\n            context = contexts[contextName];\n\n            contexts[contextName].completeLoad(moduleName);\n\n            //Clean up script binding. Favor detachEvent because of IE9\n            //issue, see attachEvent/addEventListener comment elsewhere\n            //in this file.\n            if (node.detachEvent && !isOpera) {\n                //Probably IE. If not it will throw an error, which will be\n                //useful to know.\n                node.detachEvent(\"onreadystatechange\", req.onScriptLoad);\n            } else {\n                node.removeEventListener(\"load\", req.onScriptLoad, false);\n            }\n        }\n    };\n\n    /**\n     * Attaches the script represented by the URL to the current\n     * environment. Right now only supports browser loading,\n     * but can be redefined in other environments to do the right thing.\n     * @param {String} url the url of the script to attach.\n     * @param {Object} context the context that wants the script.\n     * @param {moduleName} the name of the module that is associated with the script.\n     * @param {Function} [callback] optional callback, defaults to require.onScriptLoad\n     * @param {String} [type] optional type, defaults to text/javascript\n     */\n    req.attach = function (url, context, moduleName, callback, type) {\n        var node, loaded;\n        if (isBrowser) {\n            //In the browser so use a script tag\n            callback = callback || req.onScriptLoad;\n            node = context && context.config && context.config.xhtml ?\n                    document.createElementNS(\"http://www.w3.org/1999/xhtml\", \"html:script\") :\n                    document.createElement(\"script\");\n            node.type = type || \"text/javascript\";\n            node.charset = \"utf-8\";\n            //Use async so Gecko does not block on executing the script if something\n            //like a long-polling comet tag is being run first. Gecko likes\n            //to evaluate scripts in DOM order, even for dynamic scripts.\n            //It will fetch them async, but only evaluate the contents in DOM\n            //order, so a long-polling script tag can delay execution of scripts\n            //after it. But telling Gecko we expect async gets us the behavior\n            //we want -- execute it whenever it is finished downloading. Only\n            //Helps Firefox 3.6+\n            //Allow some URLs to not be fetched async. Mostly helps the order!\n            //plugin\n            node.async = !s.skipAsync[url];\n\n            if (context) {\n                node.setAttribute(\"data-requirecontext\", context.contextName);\n            }\n            node.setAttribute(\"data-requiremodule\", moduleName);\n\n            //Set up load listener. Test attachEvent first because IE9 has\n            //a subtle issue in its addEventListener and script onload firings\n            //that do not match the behavior of all other browsers with\n            //addEventListener support, which fire the onload event for a\n            //script right after the script execution. See:\n            //https://connect.microsoft.com/IE/feedback/details/648057/script-onload-event-is-not-fired-immediately-after-script-execution\n            //UNFORTUNATELY Opera implements attachEvent but does not follow the script\n            //script execution mode.\n            if (node.attachEvent && !isOpera) {\n                //Probably IE. IE (at least 6-8) do not fire\n                //script onload right after executing the script, so\n                //we cannot tie the anonymous define call to a name.\n                //However, IE reports the script as being in \"interactive\"\n                //readyState at the time of the define call.\n                useInteractive = true;\n                node.attachEvent(\"onreadystatechange\", callback);\n            } else {\n                node.addEventListener(\"load\", callback, false);\n            }\n            node.src = url;\n\n            //For some cache cases in IE 6-8, the script executes before the end\n            //of the appendChild execution, so to tie an anonymous define\n            //call to the module name (which is stored on the node), hold on\n            //to a reference to this node, but clear after the DOM insertion.\n            currentlyAddingScript = node;\n            if (baseElement) {\n                head.insertBefore(node, baseElement);\n            } else {\n                head.appendChild(node);\n            }\n            currentlyAddingScript = null;\n            return node;\n        } else if (isWebWorker) {\n            //In a web worker, use importScripts. This is not a very\n            //efficient use of importScripts, importScripts will block until\n            //its script is downloaded and evaluated. However, if web workers\n            //are in play, the expectation that a build has been done so that\n            //only one script needs to be loaded anyway. This may need to be\n            //reevaluated if other use cases become common.\n            loaded = context.loaded;\n            loaded[moduleName] = false;\n\n            importScripts(url);\n\n            //Account for anonymous modules\n            context.completeLoad(moduleName);\n        }\n        return null;\n    };\n\n    //Look for a data-main script attribute, which could also adjust the baseUrl.\n    if (isBrowser) {\n        //Figure out baseUrl. Get it from the script tag with require.js in it.\n        scripts = document.getElementsByTagName(\"script\");\n\n        for (i = scripts.length - 1; i > -1 && (script = scripts[i]); i--) {\n            //Set the \"head\" where we can append children by\n            //using the script's parent.\n            if (!head) {\n                head = script.parentNode;\n            }\n\n            //Look for a data-main attribute to set main script for the page\n            //to load. If it is there, the path to data main becomes the\n            //baseUrl, if it is not already set.\n            if ((dataMain = script.getAttribute('data-main'))) {\n                if (!cfg.baseUrl) {\n                    //Pull off the directory of data-main for use as the\n                    //baseUrl.\n                    src = dataMain.split('/');\n                    mainScript = src.pop();\n                    subPath = src.length ? src.join('/')  + '/' : './';\n\n                    //Set final config.\n                    cfg.baseUrl = subPath;\n                    //Strip off any trailing .js since dataMain is now\n                    //like a module name.\n                    dataMain = mainScript.replace(jsSuffixRegExp, '');\n                }\n\n                //Put the data-main script in the files to load.\n                cfg.deps = cfg.deps ? cfg.deps.concat(dataMain) : [dataMain];\n\n                break;\n            }\n        }\n    }\n\n    //Set baseUrl based on config.\n    s.baseUrl = cfg.baseUrl;\n\n    //****** START page load functionality ****************\n    /**\n     * Sets the page as loaded and triggers check for all modules loaded.\n     */\n    req.pageLoaded = function () {\n        if (!s.isPageLoaded) {\n            s.isPageLoaded = true;\n            if (scrollIntervalId) {\n                clearInterval(scrollIntervalId);\n            }\n\n            //Part of a fix for FF < 3.6 where readyState was not set to\n            //complete so libraries like jQuery that check for readyState\n            //after page load where not getting initialized correctly.\n            //Original approach suggested by Andrea Giammarchi:\n            //http://webreflection.blogspot.com/2009/11/195-chars-to-help-lazy-loading.html\n            //see other setReadyState reference for the rest of the fix.\n            if (setReadyState) {\n                document.readyState = \"complete\";\n            }\n\n            req.callReady();\n        }\n    };\n\n    //See if there is nothing waiting across contexts, and if not, trigger\n    //callReady.\n    req.checkReadyState = function () {\n        var contexts = s.contexts, prop;\n        for (prop in contexts) {\n            if (!(prop in empty)) {\n                if (contexts[prop].waitCount) {\n                    return;\n                }\n            }\n        }\n        s.isDone = true;\n        req.callReady();\n    };\n\n    /**\n     * Internal function that calls back any ready functions. If you are\n     * integrating RequireJS with another library without require.ready support,\n     * you can define this method to call your page ready code instead.\n     */\n    req.callReady = function () {\n        var callbacks = s.readyCalls, i, callback, contexts, context, prop;\n\n        if (s.isPageLoaded && s.isDone) {\n            if (callbacks.length) {\n                s.readyCalls = [];\n                for (i = 0; (callback = callbacks[i]); i++) {\n                    callback();\n                }\n            }\n\n            //If jQuery with DOM ready delayed, release it now.\n            contexts = s.contexts;\n            for (prop in contexts) {\n                if (!(prop in empty)) {\n                    context = contexts[prop];\n                    if (context.jQueryIncremented) {\n                        jQueryHoldReady(context.jQuery, false);\n                        context.jQueryIncremented = false;\n                    }\n                }\n            }\n        }\n    };\n\n    /**\n     * Registers functions to call when the page is loaded\n     */\n    req.ready = function (callback) {\n        if (s.isPageLoaded && s.isDone) {\n            callback();\n        } else {\n            s.readyCalls.push(callback);\n        }\n        return req;\n    };\n\n    if (isBrowser) {\n        if (document.addEventListener) {\n            //Standards. Hooray! Assumption here that if standards based,\n            //it knows about DOMContentLoaded.\n            document.addEventListener(\"DOMContentLoaded\", req.pageLoaded, false);\n            window.addEventListener(\"load\", req.pageLoaded, false);\n            //Part of FF < 3.6 readystate fix (see setReadyState refs for more info)\n            if (!document.readyState) {\n                setReadyState = true;\n                document.readyState = \"loading\";\n            }\n        } else if (window.attachEvent) {\n            window.attachEvent(\"onload\", req.pageLoaded);\n\n            //DOMContentLoaded approximation, as found by Diego Perini:\n            //http://javascript.nwbox.com/IEContentLoaded/\n            if (self === self.top) {\n                scrollIntervalId = setInterval(function () {\n                    try {\n                        //From this ticket:\n                        //http://bugs.dojotoolkit.org/ticket/11106,\n                        //In IE HTML Application (HTA), such as in a selenium test,\n                        //javascript in the iframe can't see anything outside\n                        //of it, so self===self.top is true, but the iframe is\n                        //not the top window and doScroll will be available\n                        //before document.body is set. Test document.body\n                        //before trying the doScroll trick.\n                        if (document.body) {\n                            document.documentElement.doScroll(\"left\");\n                            req.pageLoaded();\n                        }\n                    } catch (e) {}\n                }, 30);\n            }\n        }\n\n        //Check if document already complete, and if so, just trigger page load\n        //listeners. NOTE: does not work with Firefox before 3.6. To support\n        //those browsers, manually call require.pageLoaded().\n        if (document.readyState === \"complete\") {\n            req.pageLoaded();\n        }\n    }\n    //****** END page load functionality ****************\n\n    //Set up default context. If require was a configuration object, use that as base config.\n    req(cfg);\n\n    //If modules are built into require.js, then need to make sure dependencies are\n    //traced. Use a setTimeout in the browser world, to allow all the modules to register\n    //themselves. In a non-browser env, assume that modules are not built into require.js,\n    //which seems odd to do on the server.\n    if (req.isAsync && typeof setTimeout !== \"undefined\") {\n        ctx = s.contexts[(cfg.context || defContextName)];\n        //Indicate that the script that includes require() is still loading,\n        //so that require()'d dependencies are not traced until the end of the\n        //file is parsed (approximated via the setTimeout call).\n        ctx.requireWait = true;\n        setTimeout(function () {\n            ctx.requireWait = false;\n\n            //Any modules included with the require.js file will be in the\n            //global queue, assign them to this context.\n            ctx.takeGlobalQueue();\n\n            //Allow for jQuery to be loaded/already in the page, and if jQuery 1.4.3,\n            //make sure to hold onto it for readyWait triggering.\n            ctx.jQueryCheck();\n\n            if (!ctx.scriptCount) {\n                ctx.resume();\n            }\n            req.checkReadyState();\n        }, 0);\n    }\n}());"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/modernizr/.bower.json",
    "content": "{\n  \"name\": \"modernizr\",\n  \"homepage\": \"https://github.com/Modernizr/Modernizr\",\n  \"version\": \"2.7.0\",\n  \"_release\": \"2.7.0\",\n  \"_resolution\": {\n    \"type\": \"version\",\n    \"tag\": \"v2.7.0\",\n    \"commit\": \"71f8bc6e67b0f44b038957417e6e883c6fc53f36\"\n  },\n  \"_source\": \"https://github.com/Modernizr/Modernizr.git\",\n  \"_target\": \"2.7.0\",\n  \"_originalSource\": \"modernizr\"\n}"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/modernizr/.editorconfig",
    "content": "# editorconfig.org\nroot = true\n\n[*]\nindent_style = space\nindent_size = 2\nend_of_line = lf\ncharset = utf-8\ntrim_trailing_whitespace = true\ninsert_final_newline = true\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/modernizr/.travis.yml",
    "content": "language: node_js\nnode_js:\n  - 0.8\nbefore_script:\n  - npm install grunt\nscript: grunt travis --verbose"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/modernizr/feature-detects/a-download.js",
    "content": "\n// a[download] attribute\n// When used on an <a>, this attribute signifies that the resource it\n// points to should be downloaded by the browser rather than navigating to it.\n// http://developers.whatwg.org/links.html#downloading-resources\n// By Addy Osmani\n\nModernizr.addTest('adownload', 'download' in document.createElement('a'));\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/modernizr/feature-detects/audio-audiodata-api.js",
    "content": "// Mozilla Audio Data API\n// https://wiki.mozilla.org/Audio_Data_API\n// by Addy Osmani\nModernizr.addTest('audiodata', !!(window.Audio));\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/modernizr/feature-detects/audio-webaudio-api.js",
    "content": "// Web Audio API\n// https://dvcs.w3.org/hg/audio/raw-file/tip/webaudio/specification.html\n// By Addy Osmani\nModernizr.addTest('webaudio', !!(window.webkitAudioContext || window.AudioContext));\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/modernizr/feature-detects/battery-api.js",
    "content": "\n// Battery API\n// https://developer.mozilla.org/en/DOM/window.navigator.mozBattery\n// By: Paul Sayre\n\nModernizr.addTest('battery',\n\t!!Modernizr.prefixed('battery', navigator)\n);"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/modernizr/feature-detects/battery-level.js",
    "content": "\n// Low Battery Level\n// Enable a developer to remove CPU intensive CSS/JS when battery is low\n// developer.mozilla.org/en/DOM/window.navigator.mozBattery\n// By: Paul Sayre\n\nModernizr.addTest('lowbattery', function () {\n\tvar minLevel = 0.20,\n\t\tbattery = Modernizr.prefixed('battery', navigator);\n\treturn !!(battery && !battery.charging && battery.level <= minLevel);\n});\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/modernizr/feature-detects/blob-constructor.js",
    "content": "// Blob constructor\n// http://dev.w3.org/2006/webapi/FileAPI/#constructorBlob\n\nModernizr.addTest('blobconstructor', function () {\n    try {\n        return !!new Blob();\n    } catch (e) {\n        return false;\n    }\n});\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/modernizr/feature-detects/canvas-todataurl-type.js",
    "content": "// canvas.toDataURL type support\n// http://www.w3.org/TR/html5/the-canvas-element.html#dom-canvas-todataurl\n\n// This test is asynchronous. Watch out.\n\n(function () {\n\n    if (!Modernizr.canvas) {\n        return false;\n    }\n\n    var image = new Image(),\n        canvas = document.createElement('canvas'),\n        ctx = canvas.getContext('2d');\n\n    image.onload = function() {\n        ctx.drawImage(image, 0, 0);\n\n        Modernizr.addTest('todataurljpeg', function() {\n            return canvas.toDataURL('image/jpeg').indexOf('data:image/jpeg') === 0;\n        });\n        Modernizr.addTest('todataurlwebp', function() {\n            return canvas.toDataURL('image/webp').indexOf('data:image/webp') === 0;\n        });\n    };\n\n    image.src = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAACklEQVR4nGMAAQAABQABDQottAAAAABJRU5ErkJggg==';\n}());\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/modernizr/feature-detects/contenteditable.js",
    "content": "// contentEditable\n// http://www.whatwg.org/specs/web-apps/current-work/multipage/editing.html#contenteditable\n\n// this is known to false positive in some mobile browsers\n// here is a whitelist of verified working browsers:\n// https://github.com/NielsLeenheer/html5test/blob/549f6eac866aa861d9649a0707ff2c0157895706/scripts/engine.js#L2083\n\nModernizr.addTest('contenteditable',\n        'contentEditable' in document.documentElement);\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/modernizr/feature-detects/contentsecuritypolicy.js",
    "content": "// Test for (experimental) Content Security Policy 1.1 support.\n//\n// This feature is still quite experimental, but is available now in Chrome 22.\n// If the `SecurityPolicy` property is available, you can be sure the browser\n// supports CSP. If it's not available, the browser still might support an\n// earlier version of the CSP spec.\n//\n// Editor's Draft: https://dvcs.w3.org/hg/content-security-policy/raw-file/tip/csp-specification.dev.html\n\nModernizr.addTest('contentsecuritypolicy', 'SecurityPolicy' in document);\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/modernizr/feature-detects/contextmenu.js",
    "content": "// http://www.w3.org/TR/html5/interactive-elements.html#context-menus\n// Demo at http://thewebrocks.com/demos/context-menu/\nModernizr.addTest(\n  'contextmenu', \n  ('contextMenu' in document.documentElement && 'HTMLMenuItemElement' in window) \n);\n\n\n\n\n\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/modernizr/feature-detects/cookies.js",
    "content": "\n// by tauren\n// https://github.com/Modernizr/Modernizr/issues/191\n\nModernizr.addTest('cookies', function () {\n  // Quick test if browser has cookieEnabled host property\n  if (navigator.cookieEnabled) return true;\n  // Create cookie\n  document.cookie = \"cookietest=1\";\n  var ret = document.cookie.indexOf(\"cookietest=\") != -1;\n  // Delete cookie\n  document.cookie = \"cookietest=1; expires=Thu, 01-Jan-1970 00:00:01 GMT\";\n  return ret;\n});\n\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/modernizr/feature-detects/cors.js",
    "content": "// cors\n// By Theodoor van Donge\nModernizr.addTest('cors', !!(window.XMLHttpRequest && 'withCredentials' in new XMLHttpRequest()));"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/modernizr/feature-detects/css-backgroundposition-shorthand.js",
    "content": "/*\n    https://developer.mozilla.org/en/CSS/background-position\n    http://www.w3.org/TR/css3-background/#background-position\n\n    Example: http://jsfiddle.net/Blink/bBXvt/\n*/\n\n(function() {\n\n    var elem = document.createElement('a'),\n        eStyle = elem.style,\n        val = \"right 10px bottom 10px\";\n\n    Modernizr.addTest('bgpositionshorthand', function(){\n        eStyle.cssText = \"background-position: \" + val + \";\";\n        return (eStyle.backgroundPosition === val);\n    });\n\n}());\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/modernizr/feature-detects/css-backgroundposition-xy.js",
    "content": "/*\n\tAllan Lei https://github.com/allanlei\n\t\n\tCheck adapted from https://github.com/brandonaaron/jquery-cssHooks/blob/master/bgpos.js\n\t\n\tTest: http://jsfiddle.net/allanlei/R8AYS/\n*/\nModernizr.addTest('bgpositionxy', function() {\n    return Modernizr.testStyles('#modernizr {background-position: 3px 5px;}', function(elem) {\n        var cssStyleDeclaration = window.getComputedStyle ? getComputedStyle(elem, null) : elem.currentStyle;\n        var xSupport = (cssStyleDeclaration.backgroundPositionX == '3px') || (cssStyleDeclaration['background-position-x'] == '3px');\n        var ySupport = (cssStyleDeclaration.backgroundPositionY == '5px') || (cssStyleDeclaration['background-position-y'] == '5px');\n        return xSupport && ySupport;\n    });\n});"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/modernizr/feature-detects/css-backgroundrepeat.js",
    "content": "// developer.mozilla.org/en/CSS/background-repeat\n\n// test page: jsbin.com/uzesun/\n// http://jsfiddle.net/ryanseddon/yMLTQ/6/    \n\n(function(){\n\n\nfunction getBgRepeatValue(elem){\n    return (window.getComputedStyle ?\n             getComputedStyle(elem, null).getPropertyValue('background') :\n             elem.currentStyle['background']);\n}\n  \n\nModernizr.testStyles(' #modernizr { background-repeat: round; } ', function(elem, rule){ \n\n  Modernizr.addTest('bgrepeatround', getBgRepeatValue(elem) == 'round');\n\n});\n\n\n\nModernizr.testStyles(' #modernizr { background-repeat: space; } ', function(elem, rule){ \n\n  Modernizr.addTest('bgrepeatspace', getBgRepeatValue(elem) == 'space');\n\n});\n\n\n})();\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/modernizr/feature-detects/css-backgroundsizecover.js",
    "content": "\n// developer.mozilla.org/en/CSS/background-size\n\nModernizr.testStyles( '#modernizr{background-size:cover}', function( elem ) {\n\tvar style = window.getComputedStyle ?\n\t\twindow.getComputedStyle( elem, null )\n\t\t: elem.currentStyle;\n\t\t\n\tModernizr.addTest( 'bgsizecover', style.backgroundSize == 'cover' );\n});"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/modernizr/feature-detects/css-boxsizing.js",
    "content": "\n// developer.mozilla.org/en/CSS/box-sizing\n// github.com/Modernizr/Modernizr/issues/248\n\nModernizr.addTest(\"boxsizing\",function(){\n    return Modernizr.testAllProps(\"boxSizing\") && (document.documentMode === undefined || document.documentMode > 7);\n});\n\n\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/modernizr/feature-detects/css-calc.js",
    "content": "// Method of allowing calculated values for length units, i.e. width: calc(100%-3em) http://caniuse.com/#search=calc\n// By @calvein\n\nModernizr.addTest('csscalc', function() {\n    var prop = 'width:';\n    var value = 'calc(10px);';\n    var el = document.createElement('div');\n\n    el.style.cssText = prop + Modernizr._prefixes.join(value + prop);\n\n    return !!el.style.length;\n});\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/modernizr/feature-detects/css-cubicbezierrange.js",
    "content": "// cubic-bezier values can't be > 1 for Webkit until bug #45761 (https://bugs.webkit.org/show_bug.cgi?id=45761) is fixed\n// By @calvein\n\nModernizr.addTest('cubicbezierrange', function() {\n    var el = document.createElement('div');\n    el.style.cssText = Modernizr._prefixes.join('transition-timing-function' + ':cubic-bezier(1,0,0,1.1); ');\n    return !!el.style.length;\n});\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/modernizr/feature-detects/css-displayrunin.js",
    "content": "\n// by alanhogan\n\n// https://github.com/Modernizr/Modernizr/issues/198\n// http://css-tricks.com/596-run-in/\n\n\n\nModernizr.testStyles(' #modernizr { display: run-in; } ', function(elem, rule){ \n\n  var ret = (window.getComputedStyle ?\n         getComputedStyle(elem, null).getPropertyValue('display') :\n         elem.currentStyle['display']);\n\n  Modernizr.addTest('display-runin', ret == 'run-in');\n\n});\n\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/modernizr/feature-detects/css-displaytable.js",
    "content": "// display: table and table-cell test. (both are tested under one name \"table-cell\" )\n// By @scottjehl\n\n// all additional table display values are here: http://pastebin.com/Gk9PeVaQ though Scott has seen some IE false positives with that sort of weak detection.\n// more testing neccessary perhaps.\n\nModernizr.addTest( \"display-table\",function(){\n  \n  var doc   = window.document,\n      docElem = doc.documentElement,   \n      parent  = doc.createElement( \"div\" ),\n      child = doc.createElement( \"div\" ),\n      childb  = doc.createElement( \"div\" ),\n      ret;\n  \n  parent.style.cssText = \"display: table\";\n  child.style.cssText = childb.style.cssText = \"display: table-cell; padding: 10px\";    \n          \n  parent.appendChild( child );\n  parent.appendChild( childb );\n  docElem.insertBefore( parent, docElem.firstChild );\n  \n  ret = child.offsetLeft < childb.offsetLeft;\n  docElem.removeChild(parent);\n  return ret; \n});\n\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/modernizr/feature-detects/css-filters.js",
    "content": "// https://github.com/Modernizr/Modernizr/issues/615\n// documentMode is needed for false positives in oldIE, please see issue above\nModernizr.addTest('cssfilters', function() {\n    var el = document.createElement('div');\n    el.style.cssText = Modernizr._prefixes.join('filter' + ':blur(2px); ');\n    return !!el.style.length && ((document.documentMode === undefined || document.documentMode > 9));\n});"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/modernizr/feature-detects/css-hyphens.js",
    "content": "/* see http://davidnewton.ca/the-current-state-of-hyphenation-on-the-web\n   http://davidnewton.ca/demos/hyphenation/test.html\n\n\nThere are three tests:\n   1. csshyphens      - tests hyphens:auto actually adds hyphens to text\n   2. softhyphens     - tests that &shy; does its job\n   3. softhyphensfind - tests that in-browser Find functionality still works correctly with &shy;\n\nThese tests currently require document.body to be present\n\nHyphenation is language specific, sometimes.\n  See for more details: http://code.google.com/p/hyphenator/source/diff?spec=svn975&r=975&format=side&path=/trunk/Hyphenator.js#sc_svn975_313\n\nIf loading Hyphenator.js via Modernizr.load, be cautious of issue 158: http://code.google.com/p/hyphenator/issues/detail?id=158\n\nMore details at https://github.com/Modernizr/Modernizr/issues/312\n\n*/\n\n(function() {\n\n\tif (!document.body){\n\t\twindow.console && console.warn('document.body doesn\\'t exist. Modernizr hyphens test needs it.');\n\t\treturn;\n\t}\n\n\t// functional test of adding hyphens:auto\n\tfunction test_hyphens_css() {\n\t\ttry {\n\t\t\t/* create a div container and a span within that\n\t\t\t * these have to be appended to document.body, otherwise some browsers can give false negative */\n\t\t\tvar div = document.createElement('div'),\n\t\t\t\tspan = document.createElement('span'),\n\t\t\t\tdivStyle = div.style,\n\t\t\t\tspanHeight = 0,\n\t\t\t\tspanWidth = 0,\n\t\t\t\tresult = false,\n\t\t\t\tfirstChild = document.body.firstElementChild || document.body.firstChild;\n\n\t\t\tdiv.appendChild(span);\n\t\t\tspan.innerHTML = 'Bacon ipsum dolor sit amet jerky velit in culpa hamburger et. Laborum dolor proident, enim dolore duis commodo et strip steak. Salami anim et, veniam consectetur dolore qui tenderloin jowl velit sirloin. Et ad culpa, fatback cillum jowl ball tip ham hock nulla short ribs pariatur aute. Pig pancetta ham bresaola, ut boudin nostrud commodo flank esse cow tongue culpa. Pork belly bresaola enim pig, ea consectetur nisi. Fugiat officia turkey, ea cow jowl pariatur ullamco proident do laborum velit sausage. Magna biltong sint tri-tip commodo sed bacon, esse proident aliquip. Ullamco ham sint fugiat, velit in enim sed mollit nulla cow ut adipisicing nostrud consectetur. Proident dolore beef ribs, laborum nostrud meatball ea laboris rump cupidatat labore culpa. Shankle minim beef, velit sint cupidatat fugiat tenderloin pig et ball tip. Ut cow fatback salami, bacon ball tip et in shank strip steak bresaola. In ut pork belly sed mollit tri-tip magna culpa veniam, short ribs qui in andouille ham consequat. Dolore bacon t-bone, velit short ribs enim strip steak nulla. Voluptate labore ut, biltong swine irure jerky. Cupidatat excepteur aliquip salami dolore. Ball tip strip steak in pork dolor. Ad in esse biltong. Dolore tenderloin exercitation ad pork loin t-bone, dolore in chicken ball tip qui pig. Ut culpa tongue, sint ribeye dolore ex shank voluptate hamburger. Jowl et tempor, boudin pork chop labore ham hock drumstick consectetur tri-tip elit swine meatball chicken ground round. Proident shankle mollit dolore. Shoulder ut duis t-bone quis reprehenderit. Meatloaf dolore minim strip steak, laboris ea aute bacon beef ribs elit shank in veniam drumstick qui. Ex laboris meatball cow tongue pork belly. Ea ball tip reprehenderit pig, sed fatback boudin dolore flank aliquip laboris eu quis. Beef ribs duis beef, cow corned beef adipisicing commodo nisi deserunt exercitation. Cillum dolor t-bone spare ribs, ham hock est sirloin. Brisket irure meatloaf in, boudin pork belly sirloin ball tip. Sirloin sint irure nisi nostrud aliqua. Nostrud nulla aute, enim officia culpa ham hock. Aliqua reprehenderit dolore sunt nostrud sausage, ea boudin pork loin ut t-bone ham tempor. Tri-tip et pancetta drumstick laborum. Ham hock magna do nostrud in proident. Ex ground round fatback, venison non ribeye in.';\n\n\t\t\tdocument.body.insertBefore(div, firstChild);\n\n\t\t\t/* get size of unhyphenated text */\n\t\t\tdivStyle.cssText = 'position:absolute;top:0;left:0;width:5em;text-align:justify;text-justification:newspaper;';\n\t\t\tspanHeight = span.offsetHeight;\n\t\t\tspanWidth = span.offsetWidth;\n\n\t\t\t/* compare size with hyphenated text */\n\t\t\tdivStyle.cssText = 'position:absolute;top:0;left:0;width:5em;text-align:justify;'+\n\t\t\t\t\t\t\t\t\t\t\t\t 'text-justification:newspaper;'+\n\t\t\t\t\t\t\t\t\t\t\t\t Modernizr._prefixes.join('hyphens:auto; ');\n\n\t\t\tresult = (span.offsetHeight != spanHeight || span.offsetWidth != spanWidth);\n\n\t\t\t/* results and cleanup */\n\t\t\tdocument.body.removeChild(div);\n\t\t\tdiv.removeChild(span);\n\n\t\t\treturn result;\n\t\t} catch(e) {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\t// for the softhyphens test\n\tfunction test_hyphens(delimiter, testWidth) {\n\t\ttry {\n\t\t\t/* create a div container and a span within that\n\t\t\t * these have to be appended to document.body, otherwise some browsers can give false negative */\n\t\t\tvar div = document.createElement('div'),\n\t\t\t\tspan = document.createElement('span'),\n\t\t\t\tdivStyle = div.style,\n\t\t\t\tspanSize = 0,\n\t\t\t\tresult = false,\n\t\t\t\tresult1 = false,\n\t\t\t\tresult2 = false,\n\t\t\t\tfirstChild = document.body.firstElementChild || document.body.firstChild;\n\n\t\t\tdivStyle.cssText = 'position:absolute;top:0;left:0;overflow:visible;width:1.25em;';\n\t\t\tdiv.appendChild(span);\n\t\t\tdocument.body.insertBefore(div, firstChild);\n\n\n\t\t\t/* get height of unwrapped text */\n\t\t\tspan.innerHTML = 'mm';\n\t\t\tspanSize = span.offsetHeight;\n\n\t\t\t/* compare height w/ delimiter, to see if it wraps to new line */\n\t\t\tspan.innerHTML = 'm' + delimiter + 'm';\n\t\t\tresult1 = (span.offsetHeight > spanSize);\n\n\t\t\t/* if we're testing the width too (i.e. for soft-hyphen, not zws),\n\t\t\t * this is because tested Blackberry devices will wrap the text but not display the hyphen */\n\t\t\tif (testWidth) {\n\t\t\t\t/* get width of wrapped, non-hyphenated text */\n\t\t\t\tspan.innerHTML = 'm<br />m';\n\t\t\t\tspanSize = span.offsetWidth;\n\n\t\t\t\t/* compare width w/ wrapped w/ delimiter to see if hyphen is present */\n\t\t\t\tspan.innerHTML = 'm' + delimiter + 'm';\n\t\t\t\tresult2 = (span.offsetWidth > spanSize);\n\t\t\t} else {\n\t\t\t\tresult2 = true;\n\t\t\t}\n\n\t\t\t/* results and cleanup */\n\t\t\tif (result1 === true && result2 === true) { result = true; }\n\t\t\tdocument.body.removeChild(div);\n\t\t\tdiv.removeChild(span);\n\n\t\t\treturn result;\n\t\t} catch(e) {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\t// testing if in-browser Find functionality will work on hyphenated text\n\tfunction test_hyphens_find(delimiter) {\n\t\ttry {\n\t\t\t/* create a dummy input for resetting selection location, and a div container\n\t\t\t * these have to be appended to document.body, otherwise some browsers can give false negative\n\t\t\t * div container gets the doubled testword, separated by the delimiter\n\t\t\t * Note: giving a width to div gives false positive in iOS Safari */\n\t\t\tvar dummy = document.createElement('input'),\n\t\t\t\tdiv = document.createElement('div'),\n\t\t\t\ttestword = 'lebowski',\n\t\t\t\tresult = false,\n\t\t\t\ttextrange,\n\t\t\t\tfirstChild = document.body.firstElementChild || document.body.firstChild;\n\n\t\t\tdiv.innerHTML = testword + delimiter + testword;\n\n\t\t\tdocument.body.insertBefore(div, firstChild);\n\t\t\tdocument.body.insertBefore(dummy, div);\n\n\n\t\t\t/* reset the selection to the dummy input element, i.e. BEFORE the div container\n\t\t\t *   stackoverflow.com/questions/499126/jquery-set-cursor-position-in-text-area */\n\t\t\tif (dummy.setSelectionRange) {\n\t\t\t\tdummy.focus();\n\t\t\t\tdummy.setSelectionRange(0,0);\n\t\t\t} else if (dummy.createTextRange) {\n\t\t\t\ttextrange = dummy.createTextRange();\n\t\t\t\ttextrange.collapse(true);\n\t\t\t\ttextrange.moveEnd('character', 0);\n\t\t\t\ttextrange.moveStart('character', 0);\n\t\t\t\ttextrange.select();\n\t\t\t}\n\n\t\t\t/* try to find the doubled testword, without the delimiter */\n\t\t\tif (window.find) {\n\t\t\t\tresult = window.find(testword + testword);\n\t\t\t} else {\n\t\t\t\ttry {\n\t\t\t\t\ttextrange = window.self.document.body.createTextRange();\n\t\t\t\t\tresult = textrange.findText(testword + testword);\n\t\t\t\t} catch(e) {\n\t\t\t\t\tresult = false;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tdocument.body.removeChild(div);\n\t\t\tdocument.body.removeChild(dummy);\n\n\t\t\treturn result;\n\t\t} catch(e) {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\tModernizr.addTest(\"csshyphens\", function() {\n\n\t\tif (!Modernizr.testAllProps('hyphens')) return false;\n\n\t\t/* Chrome lies about its hyphens support so we need a more robust test\n\t\t\t\tcrbug.com/107111\n\t\t*/\n\t\ttry {\n\t\t\treturn test_hyphens_css();\n\t\t} catch(e) {\n\t\t\treturn false;\n\t\t}\n\t});\n\n\tModernizr.addTest(\"softhyphens\", function() {\n\t\ttry {\n\t\t\t// use numeric entity instead of &shy; in case it's XHTML\n\t\t\treturn test_hyphens('&#173;', true) && test_hyphens('&#8203;', false);\n\t\t} catch(e) {\n\t\t\treturn false;\n\t\t}\n\t});\n\n\tModernizr.addTest(\"softhyphensfind\", function() {\n\t\ttry {\n\t\t\treturn test_hyphens_find('&#173;') && test_hyphens_find('&#8203;');\n\t\t} catch(e) {\n\t\t\treturn false;\n\t\t}\n\t});\n\n})();\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/modernizr/feature-detects/css-lastchild.js",
    "content": "// last-child pseudo selector\n// https://github.com/Modernizr/Modernizr/pull/304\n\n\nModernizr.addTest('lastchild', function(){\n\n  return Modernizr.testStyles(\"#modernizr div {width:100px} #modernizr :last-child{width:200px;display:block}\", function (elem) {\n    return elem.lastChild.offsetWidth > elem.firstChild.offsetWidth;\n  }, 2);\n\n});\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/modernizr/feature-detects/css-mask.js",
    "content": "// this tests passes for webkit's proprietary `-webkit-mask` feature\n//   www.webkit.org/blog/181/css-masks/\n//   developer.apple.com/library/safari/#documentation/InternetWeb/Conceptual/SafariVisualEffectsProgGuide/Masks/Masks.html\n\n// it does not pass mozilla's implementation of `mask` for SVG\n\n//   developer.mozilla.org/en/CSS/mask\n//   developer.mozilla.org/En/Applying_SVG_effects_to_HTML_content\n\n// Can combine with clippaths for awesomeness: http://generic.cx/for/webkit/test.html\n\nModernizr.addTest('cssmask', Modernizr.testAllProps('maskRepeat'));\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/modernizr/feature-detects/css-mediaqueries.js",
    "content": "\n\nModernizr.addTest('mediaqueries', Modernizr.mq('only all'));"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/modernizr/feature-detects/css-objectfit.js",
    "content": "\n// dev.opera.com/articles/view/css3-object-fit-object-position/\n\nModernizr.addTest('object-fit',\n\t!!Modernizr.prefixed('objectFit')\n);"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/modernizr/feature-detects/css-overflow-scrolling.js",
    "content": "\n// johanbrook.com/browsers/native-momentum-scrolling-ios-5/\n// introduced in iOS5b2. Possible API may change...\n\nModernizr.addTest(\"overflowscrolling\",function(){\n    return Modernizr.testAllProps(\"overflowScrolling\");\n});\n\n\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/modernizr/feature-detects/css-pointerevents.js",
    "content": "\n// developer.mozilla.org/en/CSS/pointer-events\n\n// Test and project pages:\n// ausi.github.com/Feature-detection-technique-for-pointer-events/\n// github.com/ausi/Feature-detection-technique-for-pointer-events/wiki\n// github.com/Modernizr/Modernizr/issues/80\n\n\nModernizr.addTest('pointerevents', function(){\n    var element = document.createElement('x'),\n        documentElement = document.documentElement,\n        getComputedStyle = window.getComputedStyle,\n        supports;\n    if(!('pointerEvents' in element.style)){\n        return false;\n    }\n    element.style.pointerEvents = 'auto';\n    element.style.pointerEvents = 'x';\n    documentElement.appendChild(element);\n    supports = getComputedStyle &&\n        getComputedStyle(element, '').pointerEvents === 'auto';\n    documentElement.removeChild(element);\n    return !!supports;\n});\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/modernizr/feature-detects/css-positionsticky.js",
    "content": "// Sticky positioning - constrains an element to be positioned inside the\n// intersection of its container box, and the viewport.\nModernizr.addTest('csspositionsticky', function () {\n\n    var prop = 'position:';\n    var value = 'sticky';\n    var el = document.createElement('modernizr');\n    var mStyle = el.style;\n\n    mStyle.cssText = prop + Modernizr._prefixes.join(value + ';' + prop).slice(0, -prop.length);\n\n    return mStyle.position.indexOf(value) !== -1;\n});\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/modernizr/feature-detects/css-regions.js",
    "content": "// CSS Regions\n// http://www.w3.org/TR/css3-regions/\n// By: Mihai Balan\n\n// We start with a CSS parser test then we check page geometry to see if it's affected by regions\n// Later we might be able to retire the second part, as WebKit builds with the false positives die out\n\nModernizr.addTest('regions', function() {\n\n\t/* Get the 'flowFrom' property name available in the browser. Either default or vendor prefixed.\n\tIf the property name can't be found we'll get Boolean 'false' and fail quickly */\n\tvar flowFromProperty = Modernizr.prefixed(\"flowFrom\"),\n\t\tflowIntoProperty = Modernizr.prefixed(\"flowInto\");\n\n\tif (!flowFromProperty || !flowIntoProperty){\n\t\treturn false;\n\t}\n\n\t/* If CSS parsing is there, try to determine if regions actually work. */\n\tvar container\t\t= document.createElement('div'),\n\t\tcontent\t\t\t= document.createElement('div'),\n\t\tregion\t\t\t= document.createElement('div'),\n\n\t/* we create a random, unlikely to be generated flow number to make sure we don't\n\tclash with anything more vanilla, like 'flow', or 'article', or 'f1' */\n\tflowName = 'modernizr_flow_for_regions_check';\n\n\t/* First create a div with two adjacent divs inside it. The first will be the\n\tcontent, the second will be the region. To be able to distinguish between the two,\n\twe'll give the region a particular padding */\n\tcontent.innerText\t\t= 'M';\n\tcontainer.style.cssText\t= 'top: 150px; left: 150px; padding: 0px;';\n\tregion.style.cssText\t= 'width: 50px; height: 50px; padding: 42px;';\n\n\tregion.style[flowFromProperty] = flowName;\n\tcontainer.appendChild(content);\n\tcontainer.appendChild(region);\n\tdocument.documentElement.appendChild(container);\n\n\t/* Now compute the bounding client rect, before and after attempting to flow the\n\tcontent div in the region div. If regions are enabled, the after bounding rect\n\tshould reflect the padding of the region div.*/\n\tvar flowedRect, delta,\n\t\tplainRect = content.getBoundingClientRect();\n\n\n\tcontent.style[flowIntoProperty] = flowName;\n\tflowedRect = content.getBoundingClientRect();\n\n\tdelta = flowedRect.left - plainRect.left;\n\tdocument.documentElement.removeChild(container);\n\tcontent = region = container = undefined;\n\n\treturn (delta == 42);\n});\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/modernizr/feature-detects/css-remunit.js",
    "content": "\n// test by github.com/nsfmc\n\n// \"The 'rem' unit ('root em') is relative to the computed\n// value of the 'font-size' value of the root element.\"\n// http://www.w3.org/TR/css3-values/#relative0\n// you can test by checking if the prop was ditched\n\n// http://snook.ca/archives/html_and_css/font-size-with-rem\n\nModernizr.addTest('cssremunit', function(){\n\n  var div = document.createElement('div');\n  try {\n    div.style.fontSize = '3rem';\n  } catch(er){}\n  return (/rem/).test(div.style.fontSize);\n\n});\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/modernizr/feature-detects/css-resize.js",
    "content": "\n// Test for CSS 3 UI \"resize\" property\n// http://www.w3.org/TR/css3-ui/#resize\n// https://developer.mozilla.org/en/CSS/resize\n\nModernizr.addTest('cssresize', Modernizr.testAllProps('resize'));\n\n\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/modernizr/feature-detects/css-scrollbars.js",
    "content": "// Stylable scrollbars detection\nModernizr.addTest('cssscrollbar', function() {\n\n\tvar bool,\n\n\t\tstyles = \"#modernizr{overflow: scroll; width: 40px }#\" +\n\t\t\tModernizr._prefixes\n\t\t\t\t.join(\"scrollbar{width:0px}\"+' #modernizr::')\n\t\t\t\t.split('#')\n\t\t\t\t.slice(1)\n\t\t\t\t.join('#') + \"scrollbar{width:0px}\";\n\n\tModernizr.testStyles(styles, function(node) {\n\t\tbool = 'scrollWidth' in node && node.scrollWidth == 40;\n\t});\n\n\treturn bool;\n\n});\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/modernizr/feature-detects/css-subpixelfont.js",
    "content": "/*\n * Test for SubPixel Font Rendering\n * (to infer if GDI or DirectWrite is used on Windows)\n * Authors: @derSchepp, @gerritvanaaken, @rodneyrehm, @yatil, @ryanseddon\n * Web: https://github.com/gerritvanaaken/subpixeldetect\n */\nModernizr.addTest('subpixelfont', function() {\n    var bool,\n        styles = \"#modernizr{position: absolute; top: -10em; visibility:hidden; font: normal 10px arial;}#subpixel{float: left; font-size: 33.3333%;}\";\n    \n    // see https://github.com/Modernizr/Modernizr/blob/master/modernizr.js#L97\n    Modernizr.testStyles(styles, function(elem) {\n        var subpixel = elem.firstChild;\n\n        subpixel.innerHTML = 'This is a text written in Arial';\n\n        bool = window.getComputedStyle ?\n            window.getComputedStyle(subpixel, null).getPropertyValue(\"width\") !== '44px'\n            : false;\n    }, 1, ['subpixel']);\n\n    return bool;\n});\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/modernizr/feature-detects/css-supports.js",
    "content": "// http://dev.w3.org/csswg/css3-conditional/#at-supports\n// github.com/Modernizr/Modernizr/issues/648\n// Relies on the fact that a browser vendor should expose the CSSSupportsRule interface\n// http://dev.w3.org/csswg/css3-conditional/#the-csssupportsrule-interface\n\nModernizr.addTest(\"supports\",\"CSSSupportsRule\" in window);"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/modernizr/feature-detects/css-userselect.js",
    "content": "// -moz-user-select:none test.\n\n// by ryan seddon\n//https://github.com/Modernizr/Modernizr/issues/250\n\n\nModernizr.addTest(\"userselect\",function(){\n    return Modernizr.testAllProps(\"user-select\");\n});\n\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/modernizr/feature-detects/css-vhunit.js",
    "content": "// https://github.com/Modernizr/Modernizr/issues/572\n// Similar to http://jsfiddle.net/FWeinb/etnYC/\nModernizr.addTest('cssvhunit', function() {\n    var bool;\n    Modernizr.testStyles(\"#modernizr { height: 50vh; }\", function(elem, rule) {   \n        var height = parseInt(window.innerHeight/2,10),\n            compStyle = parseInt((window.getComputedStyle ?\n                      getComputedStyle(elem, null) :\n                      elem.currentStyle)[\"height\"],10);\n        \n        bool= (compStyle == height);\n    });\n    return bool;\n});"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/modernizr/feature-detects/css-vmaxunit.js",
    "content": "// https://github.com/Modernizr/Modernizr/issues/572\n// http://jsfiddle.net/glsee/JDsWQ/4/\nModernizr.addTest('cssvmaxunit', function(){\n    var bool;\n    Modernizr.testStyles(\"#modernizr { width: 50vmax; }\", function(elem, rule) {\n        var one_vw = window.innerWidth/100,\n            one_vh = window.innerHeight/100,\n            compWidth = parseInt((window.getComputedStyle ?\n                                  getComputedStyle(elem, null) :\n                                  elem.currentStyle)['width'],10);\n        bool = ( parseInt(Math.max(one_vw, one_vh)*50,10) == compWidth );\n    });\n    return bool;\n});"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/modernizr/feature-detects/css-vminunit.js",
    "content": "// https://github.com/Modernizr/Modernizr/issues/572\n// http://jsfiddle.net/glsee/JRmdq/8/\nModernizr.addTest('cssvminunit', function(){\n    var bool;\n    Modernizr.testStyles(\"#modernizr { width: 50vmin; }\", function(elem, rule) {\n        var one_vw = window.innerWidth/100,\n            one_vh = window.innerHeight/100,\n            compWidth = parseInt((window.getComputedStyle ?\n                                  getComputedStyle(elem, null) :\n                                  elem.currentStyle)['width'],10);\n        bool = ( parseInt(Math.min(one_vw, one_vh)*50,10) == compWidth );\n    });\n    return bool;\n});\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/modernizr/feature-detects/css-vwunit.js",
    "content": "// https://github.com/Modernizr/Modernizr/issues/572\n// http://jsfiddle.net/FWeinb/etnYC/\nModernizr.addTest('cssvwunit', function(){\n    var bool;\n    Modernizr.testStyles(\"#modernizr { width: 50vw; }\", function(elem, rule) {\n        var width = parseInt(window.innerWidth/2,10),\n            compStyle = parseInt((window.getComputedStyle ?\n                      getComputedStyle(elem, null) :\n                      elem.currentStyle)[\"width\"],10);\n        \n        bool= (compStyle == width);\n    });\n    return bool;\n});\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/modernizr/feature-detects/custom-protocol-handler.js",
    "content": "/*\n\tCustom protocol handler support\n\thttp://developers.whatwg.org/timers.html#custom-handlers\n\t\n\tAdded by @benschwarz\n*/\n\nModernizr.addTest('customprotocolhandler', function () {\n    return !!navigator.registerProtocolHandler;\n});\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/modernizr/feature-detects/dart.js",
    "content": "// Dart\n// By Theodoor van Donge\n\n// https://chromiumcodereview.appspot.com/9232049/\n\nModernizr.addTest('dart', !!Modernizr.prefixed('startDart', navigator));\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/modernizr/feature-detects/dataview-api.js",
    "content": "// DataView \n// https://developer.mozilla.org/en/JavaScript_typed_arrays/DataView\n// By Addy Osmani\nModernizr.addTest('dataview', (typeof DataView !== 'undefined' && 'getFloat64' in DataView.prototype));"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/modernizr/feature-detects/dom-classlist.js",
    "content": "// classList\n// https://developer.mozilla.org/en/DOM/element.classList\n// By Addy Osmani\nModernizr.addTest('classlist', 'classList' in document.documentElement);\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/modernizr/feature-detects/dom-createElement-attrs.js",
    "content": "// by james a rosen.\n// https://github.com/Modernizr/Modernizr/issues/258\n\nModernizr.addTest('createelement-attrs', function() {\n  try {\n    return document.createElement(\"<input name='test' />\").getAttribute('name') == 'test';\n  } catch(e) {\n    return false;\n  }\n});\n\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/modernizr/feature-detects/dom-dataset.js",
    "content": "\n// dataset API for data-* attributes\n// test by @phiggins42\n\nModernizr.addTest('dataset', function(){\n  var n = document.createElement(\"div\");\n  n.setAttribute(\"data-a-b\", \"c\");\n  return !!(n.dataset && n.dataset.aB === \"c\");\n});\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/modernizr/feature-detects/dom-microdata.js",
    "content": "// Microdata support\n// http://www.w3.org/TR/html5/microdata.html\n// By Addy Osmani\nModernizr.addTest('microdata', !!(document['getItems']));"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/modernizr/feature-detects/elem-datalist.js",
    "content": "\n\n// lol. we already have a test for datalist built in! silly you.\n\n\n// Helpful links while you're here, though..\n\n// http://css-tricks.com/15346-relevant-dropdowns-polyfill-for-datalist/\n// http://miketaylr.com/test/datalist.html\n// http://miketaylr.com/code/datalist.html\n\nModernizr.addTest('datalistelem', Modernizr.input.list );\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/modernizr/feature-detects/elem-details.js",
    "content": "// By @mathias, based on http://mths.be/axh\nModernizr.addTest('details', function() {\n    var doc = document,\n        el = doc.createElement('details'),\n        fake,\n        root,\n        diff;\n    if (!('open' in el)) { // return early if possible; thanks @aFarkas!\n        return false;\n    }\n    root = doc.body || (function() {\n        var de = doc.documentElement;\n        fake = true;\n        return de.insertBefore(doc.createElement('body'), de.firstElementChild || de.firstChild);\n    }());\n    el.innerHTML = '<summary>a</summary>b';\n    el.style.display = 'block';\n    root.appendChild(el);\n    diff = el.offsetHeight;\n    el.open = true;\n    diff = diff != el.offsetHeight;\n    root.removeChild(el);\n    fake && root.parentNode.removeChild(root);\n    return diff;\n});"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/modernizr/feature-detects/elem-output.js",
    "content": "// <output>\n// http://www.whatwg.org/specs/web-apps/current-work/multipage/the-button-element.html#the-output-element\n// by Addy Osmani\nModernizr.addTest('outputelem', 'value' in document.createElement('output'));\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/modernizr/feature-detects/elem-progress-meter.js",
    "content": "//By Stefan Wallin\n\n//tests for progressbar-support. All browsers that don't support progressbar returns undefined =)\nModernizr.addTest(\"progressbar\",function(){\n    return document.createElement('progress').max !== undefined;\n});\n\n//tests for meter-support. All browsers that don't support meters returns undefined =)\nModernizr.addTest(\"meter\",function(){\n    return document.createElement('meter').max !== undefined;\n});\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/modernizr/feature-detects/elem-ruby.js",
    "content": "// Browser support test for the HTML5 <ruby>, <rt> and <rp> elements\n// http://www.whatwg.org/specs/web-apps/current-work/multipage/text-level-semantics.html#the-ruby-element\n//\n// by @alrra\n\nModernizr.addTest('ruby', function () {\n\n    var ruby = document.createElement('ruby'),\n        rt = document.createElement('rt'),\n        rp = document.createElement('rp'),\n        docElement = document.documentElement,\n        displayStyleProperty = 'display',\n        fontSizeStyleProperty = 'fontSize'; // 'fontSize' - because it`s only used for IE6 and IE7\n\n    ruby.appendChild(rp);\n    ruby.appendChild(rt);\n    docElement.appendChild(ruby);\n\n    // browsers that support <ruby> hide the <rp> via \"display:none\"\n    if ( getStyle(rp, displayStyleProperty) == 'none' ||                                                       // for non-IE browsers\n    // but in IE browsers <rp> has \"display:inline\" so, the test needs other conditions:\n        getStyle(ruby, displayStyleProperty) == 'ruby' && getStyle(rt, displayStyleProperty) == 'ruby-text' || // for IE8 & IE9\n        getStyle(rp, fontSizeStyleProperty) == '6pt' && getStyle(rt, fontSizeStyleProperty) == '6pt' ) {       // for IE6 & IE7\n\n        cleanUp();\n        return true;\n\n    } else {\n        cleanUp();\n        return false;\n    }\n\n    function getStyle( element, styleProperty ) {\n        var result;\n\n        if ( window.getComputedStyle ) {     // for non-IE browsers\n            result = document.defaultView.getComputedStyle(element,null).getPropertyValue(styleProperty);\n        } else if ( element.currentStyle ) { // for IE\n            result = element.currentStyle[styleProperty];\n        }\n\n        return result;\n    }\n\n    function cleanUp() {\n        docElement.removeChild(ruby);\n        // the removed child node still exists in memory, so ...\n        ruby = null;\n        rt = null;\n        rp = null;\n    }\n\n});\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/modernizr/feature-detects/elem-time.js",
    "content": "// <time> element\n// http://www.whatwg.org/specs/web-apps/current-work/multipage/rendering.html#the-time-element-0\n// by Addy Osmani\nModernizr.addTest('time', 'valueAsDate' in document.createElement('time'));\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/modernizr/feature-detects/elem-track.js",
    "content": "// Track element + Timed Text Track API\n// http://www.w3.org/TR/html5/video.html#the-track-element\n// http://www.w3.org/TR/html5/media-elements.html#text-track-api\n//\n// While IE10 has implemented the track element, IE10 does not expose the underlying APIs to create timed text tracks by JS (really sad)\n// By Addy Osmani\nModernizr.addTest({\n\ttexttrackapi: (typeof (document.createElement('video').addTextTrack) === 'function'),\n\t// a more strict test for track including UI support: document.createElement('track').kind === 'subtitles'\n\ttrack: ('kind' in document.createElement('track'))\n});\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/modernizr/feature-detects/emoji.js",
    "content": "// Requires a Modernizr build with `canvastext` included\n// http://www.modernizr.com/download/#-canvas-canvastext\nModernizr.addTest('emoji', function() {\n  if (!Modernizr.canvastext) return false;\n  var node = document.createElement('canvas'),\n      ctx = node.getContext('2d');\n  ctx.textBaseline = 'top';\n  ctx.font = '32px Arial';\n  ctx.fillText('\\ud83d\\ude03', 0, 0); // \"smiling face with open mouth\" emoji\n  return ctx.getImageData(16, 16, 1, 1).data[0] !== 0;\n});"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/modernizr/feature-detects/es5-strictmode.js",
    "content": "// strict mode\n\n// test by @kangax\n\nModernizr.addTest('strictmode', function(){\n\treturn (function(){ \"use strict\"; return !this; })(); \n});"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/modernizr/feature-detects/event-deviceorientation-motion.js",
    "content": "//By Shi Chuan\n//Part of Device Access aspect of HTML5, same category as geolocation\n//W3C Editor's Draft at http://dev.w3.org/geo/api/spec-source-orientation.html\n//Implementation by iOS Safari at http://goo.gl/fhce3 and http://goo.gl/rLKz8\n\n\n//test for Device Motion Event support, returns boolean value true/false\nModernizr.addTest('devicemotion', ('DeviceMotionEvent' in window) );\n\n//test for Device Orientation Event support, returns boolean value true/false\nModernizr.addTest('deviceorientation', ('DeviceOrientationEvent' in window) );\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/modernizr/feature-detects/exif-orientation.js",
    "content": "// EXIF Orientation test\n\n// iOS looks at the EXIF Orientation flag in jpgs and rotates the image\n// accordingly. Looks like most desktop browsers just ignore this data.\n\n// description: www.impulseadventure.com/photo/exif-orientation.html\n\n// Bug trackers:\n//    bugzil.la/298619 (unimplemented)\n//    crbug.com/56845 (looks incomplete)\n//    webk.it/19688 (available upstream but its up all ports to turn on individually)\n//\n\n// detect by Paul Sayre\n\n\n(function(){\n\n  var img = new Image();\n\n  img.onerror = function() {\n      Modernizr.addTest('exif-orientation', function () { return false; });\n  };\n\n  img.onload = function() {\n      Modernizr.addTest('exif-orientation', function () { return img.width !== 2; });\n  };\n\n  // There may be a way to shrink this more, it's a 1x2 white jpg with the orientation flag set to 6\n  img.src = \"data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEAYABgAAD/4QAiRXhpZgAASUkqAAgAAAABABIBAwABAAAABgASAAAAAAD/2wBDAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQH/2wBDAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQH/wAARCAABAAIDASIAAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6/9oADAMBAAIRAxEAPwD+/iiiigD/2Q==\";\n\n})();\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/modernizr/feature-detects/file-api.js",
    "content": "/**\n * file tests for the File API specification\n *   Tests for objects specific to the File API W3C specification without\n *   being redundant (don't bother testing for Blob since it is assumed\n *   to be the File object's prototype.\n *\n *   Will fail in Safari 5 due to its lack of support for the standards\n *   defined FileReader object\n */\nModernizr.addTest('filereader', function () {\n    return !!(window.File && window.FileList && window.FileReader);\n});\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/modernizr/feature-detects/file-filesystem.js",
    "content": "// Filesystem API\n// dev.w3.org/2009/dap/file-system/file-dir-sys.html\n\n// The API will be present in Chrome incognito, but will throw an exception.\n// See crbug.com/93417\n//\n// By Eric Bidelman (@ebidel)\n\nModernizr.addTest('filesystem', !!Modernizr.prefixed('requestFileSystem', window));"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/modernizr/feature-detects/forms-fileinput.js",
    "content": "\n\n// Detects whether input type=\"file\" is available on the platform\n// E.g. iOS < 6 and some android version don't support this\n\n//  It's useful if you want to hide the upload feature of your app on devices that\n//  don't support it (iphone, ipad, etc).\n\nModernizr.addTest('fileinput', function() {\n    var elem = document.createElement('input');\n    elem.type = 'file';\n    return !elem.disabled;\n});\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/modernizr/feature-detects/forms-formattribute.js",
    "content": "// Detects whether input form=\"form_id\" is available on the platform\n// E.g. IE 10 (and below), don't support this\nModernizr.addTest(\"formattribute\", function() {\n\tvar form = document.createElement(\"form\"),\n\t\tinput = document.createElement(\"input\"),\n\t\tdiv = document.createElement(\"div\"),\n\t\tid = \"formtest\"+(new Date().getTime()),\n\t\tattr,\n\t\tbool = false;\n\n\t\tform.id = id;\n\n\t//IE6/7 confuses the form idl attribute and the form content attribute\n\tif(document.createAttribute){\n\t\tattr = document.createAttribute(\"form\");\n\t\tattr.nodeValue = id;\n\t\tinput.setAttributeNode(attr);\n\t\tdiv.appendChild(form);\n\t\tdiv.appendChild(input);\n\n\t\tdocument.documentElement.appendChild(div);\n\n\t\tbool = form.elements.length === 1 && input.form == form;\n\n\t\tdiv.parentNode.removeChild(div);\n\t}\n\n\treturn bool;\n});"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/modernizr/feature-detects/forms-inputnumber-l10n.js",
    "content": "// input[type=\"number\"] localized input/output\n// // Detects whether input type=\"number\" is capable of receiving and\n// // displaying localized numbers, e.g. with comma separator\n// // https://bugs.webkit.org/show_bug.cgi?id=42484\n// // Based on http://trac.webkit.org/browser/trunk/LayoutTests/fast/forms/script-tests/input-number-keyoperation.js?rev=80096#L9\n// // By Peter Janes\n\nModernizr.addTest('localizedNumber', function() {\n    var doc = document,\n        el = document.createElement('div'),\n        fake,\n        root,\n        input,\n        diff;\n    root = doc.body || (function() {\n        var de = doc.documentElement;\n        fake = true;\n        return de.insertBefore(doc.createElement('body'), de.firstElementChild || de.firstChild);\n    }());\n    el.innerHTML = '<input type=\"number\" value=\"1.0\" step=\"0.1\"/>';\n    input = el.childNodes[0];\n    root.appendChild(el);\n    input.focus();\n    try {\n        doc.execCommand('InsertText', false, '1,1');\n    } catch(e) { // prevent warnings in IE\n    }\n    diff = input.type === 'number' && input.valueAsNumber === 1.1 && input.checkValidity();\n    root.removeChild(el);\n    fake && root.parentNode.removeChild(root);\n    return diff;\n});\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/modernizr/feature-detects/forms-placeholder.js",
    "content": "// testing for placeholder attribute in inputs and textareas\n// re-using Modernizr.input if available\n\nModernizr.addTest('placeholder', function(){\n\n  return !!( 'placeholder' in ( Modernizr.input    || document.createElement('input')    ) && \n             'placeholder' in ( Modernizr.textarea || document.createElement('textarea') )\n           );\n\n});\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/modernizr/feature-detects/forms-speechinput.js",
    "content": "// speech input for inputs\n// by @alrra\n\n\n// `webkitSpeech` in elem \n// doesn`t work correctly in all versions of Chromium based browsers.\n//   It can return false even if they have support for speech i.imgur.com/2Y40n.png\n//  Testing with 'onwebkitspeechchange' seems to fix this problem\n\n// this detect only checks the webkit version because\n// the speech attribute is likely to be deprecated in favor of a JavaScript API.\n// http://lists.w3.org/Archives/Public/public-webapps/2011OctDec/att-1696/speechapi.html\n\n// FIXME: add support for detecting the new spec'd behavior\n\nModernizr.addTest('speechinput', function(){\n    var elem = document.createElement('input'); \n    return 'speech' in elem || 'onwebkitspeechchange' in elem; \n});"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/modernizr/feature-detects/forms-validation.js",
    "content": "// This implementation only tests support for interactive form validation.\n// To check validation for a specific type or a specific other constraint,\n// the test can be combined: \n//    - Modernizr.inputtypes.numer && Modernizr.formvalidation (browser supports rangeOverflow, typeMismatch etc. for type=number)\n//    - Modernizr.input.required && Modernizr.formvalidation (browser supports valueMissing)\n//\n(function(document, Modernizr){\n\n\nModernizr.formvalidationapi = false;\nModernizr.formvalidationmessage = false;\n\nModernizr.addTest('formvalidation', function(){\n    var form = document.createElement('form');\n    if ( !('checkValidity' in form) ) {\n        return false;\n    }\n    var body = document.body,\n\n    html = document.documentElement,\n\n    bodyFaked = false,\n\n    invaildFired = false,\n\n    input;\n\n    Modernizr.formvalidationapi = true;\n\n    // Prevent form from being submitted\n    form.onsubmit = function(e) {\n        //Opera does not validate form, if submit is prevented\n        if ( !window.opera ) {\n            e.preventDefault();\n        }\n        e.stopPropagation();\n    };\n\n    // Calling form.submit() doesn't trigger interactive validation, \n    // use a submit button instead\n    //older opera browsers need a name attribute\n    form.innerHTML = '<input name=\"modTest\" required><button></button>';\n\n    // FF4 doesn't trigger \"invalid\" event if form is not in the DOM tree\n    // Chrome throws error if invalid input is not visible when submitting \n    form.style.position = 'absolute';\n    form.style.top = '-99999em';\n\n    // We might in <head> in which case we need to create body manually\n    if ( !body ) {\n        bodyFaked = true;\n        body = document.createElement('body');\n        //avoid crashing IE8, if background image is used\n        body.style.background = \"\";\n        html.appendChild(body);\n    }\n\n    body.appendChild(form);\n\n    input = form.getElementsByTagName('input')[0];\t\n\n    // Record whether \"invalid\" event is fired\n    input.oninvalid = function(e) {\n        invaildFired = true;\n        e.preventDefault();\n        e.stopPropagation();\n    };\n\n    //Opera does not fully support the validationMessage property\n    Modernizr.formvalidationmessage = !!input.validationMessage;\n\n    // Submit form by clicking submit button\n    form.getElementsByTagName('button')[0].click();\n\n    // Don't forget to clean up\n    body.removeChild(form);\n    bodyFaked && html.removeChild(body);\n\n    return invaildFired;\n});\n\n\n})(document, window.Modernizr);"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/modernizr/feature-detects/fullscreen-api.js",
    "content": "Modernizr.addTest('fullscreen',function(){\n     for(var i = 0; i < Modernizr._domPrefixes.length; i++) {\n        if( document[Modernizr._domPrefixes[i].toLowerCase() + 'CancelFullScreen'])\n            return true;\n     }\n     return !!document['cancelFullScreen'] || false;\n});\n\n// http://developer.apple.com/library/safari/documentation/AudioVideo/Conceptual/Using_HTML5_Audio_Video/ControllingMediaWithJavaScript/ControllingMediaWithJavaScript.html#//apple_ref/doc/uid/TP40009523-CH3-SW20\n// https://developer.mozilla.org/en/API/Fullscreen\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/modernizr/feature-detects/gamepad.js",
    "content": "// GamePad API\n// https://dvcs.w3.org/hg/gamepad/raw-file/default/gamepad.html\n// By Eric Bidelman\n\n// FF has Gamepad API support only in special builds, but not in any release (even behind a flag)\n// Their current implementation has no way to feature detect, only events to bind to.\n//   http://www.html5rocks.com/en/tutorials/doodles/gamepad/#toc-featuredetect\n\n// but a patch will bring them up to date with the spec when it lands (and they'll pass this test)\n//   https://bugzilla.mozilla.org/show_bug.cgi?id=690935\n\nModernizr.addTest('gamepads', !!Modernizr.prefixed('getGamepads', navigator));\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/modernizr/feature-detects/getusermedia.js",
    "content": "// getUserMedia\n// http://www.whatwg.org/specs/web-apps/current-work/multipage/video-conferencing-and-peer-to-peer-communication.html\n// By Eric Bidelman\n\nModernizr.addTest('getusermedia', !!Modernizr.prefixed('getUserMedia', navigator));"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/modernizr/feature-detects/ie8compat.js",
    "content": "\n// IE8 compat mode aka Fake IE7\n// by Erich Ocean\n\n// In this case, IE8 will be acting as IE7. You may choose to remove features in this case.\n\n// related:\n// james.padolsey.com/javascript/detect-ie-in-js-using-conditional-comments/\n\nModernizr.addTest('ie8compat',function(){\n    return (!window.addEventListener && document.documentMode && document.documentMode === 7);\n});\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/modernizr/feature-detects/iframe-sandbox.js",
    "content": "// Test for `sandbox` attribute in iframes.\n//\n// Spec: http://www.whatwg.org/specs/web-apps/current-work/multipage/the-iframe-element.html#attr-iframe-sandbox\n\nModernizr.addTest('sandbox', 'sandbox' in document.createElement('iframe'));\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/modernizr/feature-detects/iframe-seamless.js",
    "content": "// Test for `seamless` attribute in iframes.\n//\n// Spec: http://www.whatwg.org/specs/web-apps/current-work/multipage/the-iframe-element.html#attr-iframe-seamless\n\nModernizr.addTest('seamless', 'seamless' in document.createElement('iframe'));\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/modernizr/feature-detects/iframe-srcdoc.js",
    "content": "// Test for `srcdoc` attribute in iframes.\n//\n// Spec: http://www.whatwg.org/specs/web-apps/current-work/multipage/the-iframe-element.html#attr-iframe-srcdoc\n\nModernizr.addTest('srcdoc', 'srcdoc' in document.createElement('iframe'));\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/modernizr/feature-detects/img-apng.js",
    "content": "// Animated PNG\n// http://en.wikipedia.org/wiki/APNG\n// By Addy Osmani\n(function () {\n\n    if (!Modernizr.canvas) return false;\n    \n    var image = new Image(),\n        canvas = document.createElement('canvas'),\n        ctx = canvas.getContext('2d');\n\n\n    image.onload = function () {\n        Modernizr.addTest('apng', function () {\n            if (typeof canvas.getContext == 'undefined') {\n                return false;\n            } else {\n                ctx.drawImage(image, 0, 0);\n                return ctx.getImageData(0, 0, 1, 1).data[3] === 0;\n            }\n        });\n    };\n\n    image.src = \"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAACGFjVEwAAAABAAAAAcMq2TYAAAANSURBVAiZY2BgYPgPAAEEAQB9ssjfAAAAGmZjVEwAAAAAAAAAAQAAAAEAAAAAAAAAAAD6A+gBAbNU+2sAAAARZmRBVAAAAAEImWNgYGBgAAAABQAB6MzFdgAAAABJRU5ErkJggg==\";\n\n}());\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/modernizr/feature-detects/img-webp.js",
    "content": "// code.google.com/speed/webp/\n// by rich bradshaw, ryan seddon, and paul irish\n\n\n// This test is asynchronous. Watch out.\n\n(function(){\n\n  var image = new Image();\n\n  image.onerror = function() {\n      Modernizr.addTest('webp', false);\n  };  \n  image.onload = function() {\n      Modernizr.addTest('webp', function() { return image.width == 1; });\n  };\n\n  image.src = 'data:image/webp;base64,UklGRiwAAABXRUJQVlA4ICAAAAAUAgCdASoBAAEAL/3+/3+CAB/AAAFzrNsAAP5QAAAAAA==';\n\n}());"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/modernizr/feature-detects/json.js",
    "content": "// native JSON support.\n// developer.mozilla.org/en/JSON\n\n// this will also succeed if you've loaded the JSON2.js polyfill ahead of time\n//   ... but that should be obvious. :)\n\nModernizr.addTest('json', !!window.JSON && !!JSON.parse);\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/modernizr/feature-detects/lists-reversed.js",
    "content": "\n// impressivewebs.com/reverse-ordered-lists-html5\n// polyfill: github.com/impressivewebs/HTML5-Reverse-Ordered-Lists\n\n\nModernizr.addTest('olreversed', 'reversed' in document.createElement('ol'));\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/modernizr/feature-detects/mathml.js",
    "content": "// MathML\n// http://www.w3.org/Math/ \n// By Addy Osmani\n// Based on work by Davide (@dpvc) and David (@davidcarlisle)\n// in https://github.com/mathjax/MathJax/issues/182\n\nModernizr.addTest('mathml', function(){\n\tvar hasMathML = false;\n\tif ( document.createElementNS ) {\n\tvar ns = \"http://www.w3.org/1998/Math/MathML\",\n\t    div = document.createElement(\"div\");\n\t    div.style.position = \"absolute\"; \n\tvar mfrac = div.appendChild(document.createElementNS(ns,\"math\"))\n\t               .appendChild(document.createElementNS(ns,\"mfrac\"));\n\tmfrac.appendChild(document.createElementNS(ns,\"mi\"))\n\t     .appendChild(document.createTextNode(\"xx\"));\n\tmfrac.appendChild(document.createElementNS(ns,\"mi\"))\n\t     .appendChild(document.createTextNode(\"yy\"));\n\tdocument.body.appendChild(div);\n\thasMathML = div.offsetHeight > div.offsetWidth;\n\t}\n\treturn hasMathML;\n});"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/modernizr/feature-detects/network-connection.js",
    "content": "// determining low-bandwidth via navigator.connection\n\n// There are two iterations of the navigator.connection interface:\n\n// The first is present in Android 2.2+ and only in the Browser (not WebView)\n// : docs.phonegap.com/en/1.2.0/phonegap_connection_connection.md.html#connection.type\n// : davidbcalhoun.com/2010/using-navigator-connection-android\n\n// The second is specced at dev.w3.org/2009/dap/netinfo/ and perhaps landing in WebKit\n// : bugs.webkit.org/show_bug.cgi?id=73528\n\n// unknown devices are assumed as fast\n// for more rigorous network testing, consider boomerang.js: github.com/bluesmoon/boomerang/\n\nModernizr.addTest('lowbandwidth', function() {\n\n  var connection = navigator.connection || { type: 0 }; // polyfill\n\n  return connection.type == 3 || // connection.CELL_2G\n      connection.type == 4 || // connection.CELL_3G\n      /^[23]g$/.test(connection.type); // string value in new spec\n});\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/modernizr/feature-detects/network-eventsource.js",
    "content": "\n// server sent events aka eventsource\n// dev.w3.org/html5/eventsource/\n\nModernizr.addTest('eventsource', !!window.EventSource);\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/modernizr/feature-detects/network-xhr2.js",
    "content": "\n\n// XML HTTP Request Level 2\n// www.w3.org/TR/XMLHttpRequest2/\n\n// Much more details at github.com/Modernizr/Modernizr/issues/385\n\n// all three of these details report consistently across all target browsers:\n//   !!(window.ProgressEvent);\n//   !!(window.FormData);\n//   window.XMLHttpRequest && \"withCredentials\" in new XMLHttpRequest;\n\nModernizr.addTest('xhr2', 'FormData' in window);\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/modernizr/feature-detects/notification.js",
    "content": "// Notifications\n// By Theodoor van Donge\n\n// window.webkitNotifications is only used by Chrome \n//\thttp://www.html5rocks.com/en/tutorials/notifications/quick/\n\n// window.Notification only exist in the draft specs \n//\thttp://dev.w3.org/2006/webapi/WebNotifications/publish/Notifications.html#idl-if-Notification\n\nModernizr.addTest('notification', !!Modernizr.prefixed('Notifications', window));"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/modernizr/feature-detects/performance.js",
    "content": "// Navigation Timing (Performance)\n// https://dvcs.w3.org/hg/webperf/raw-file/tip/specs/NavigationTiming/\n// http://www.html5rocks.com/en/tutorials/webperformance/basics/\n// By Scott Murphy (uxder)\nModernizr.addTest('performance', !!Modernizr.prefixed('performance', window));"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/modernizr/feature-detects/pointerlock-api.js",
    "content": "// https://developer.mozilla.org/en-US/docs/API/Pointer_Lock_API\n\nModernizr.addTest('pointerlock',!!Modernizr.prefixed('pointerLockElement', document));\n\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/modernizr/feature-detects/quota-management-api.js",
    "content": "// Quota Storage Management API\n// This API can be used to check how much quota an origin is using and request more\n\n// Currently only implemented in Chrome.\n// https://developers.google.com/chrome/whitepapers/storage\n// By Addy Osmani\n\nModernizr.addTest('quotamanagement', function(){\n  var storage = Modernizr.prefixed('StorageInfo', window);\n  return !!(storage && 'TEMPORARY' in storage && 'PERSISTENT' in storage);\n});\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/modernizr/feature-detects/requestanimationframe.js",
    "content": "\n// requestAnimationFrame\n// Offload animation repainting to browser for optimized performance. \n// http://dvcs.w3.org/hg/webperf/raw-file/tip/specs/RequestAnimationFrame/Overview.html\n// By Addy Osmani\n\nModernizr.addTest('raf', !!Modernizr.prefixed('requestAnimationFrame', window));"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/modernizr/feature-detects/script-async.js",
    "content": "// async script\n// By Theodoor van Donge\nModernizr.addTest('scriptasync', 'async' in document.createElement('script'));"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/modernizr/feature-detects/script-defer.js",
    "content": "// defer script\n// By Theodoor van Donge\nModernizr.addTest('scriptdefer', 'defer' in document.createElement('script'));"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/modernizr/feature-detects/style-scoped.js",
    "content": "// Browser support test for <style scoped>\n// http://www.w3.org/TR/html5/the-style-element.html#attr-style-scoped\n//\n// by @alrra\n\nModernizr.addTest( 'stylescoped', 'scoped' in document.createElement('style') );\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/modernizr/feature-detects/svg-filters.js",
    "content": "// Detect support for svg filters - http://www.w3.org/TR/SVG11/filters.html.\n// Should fail in Safari: http://stackoverflow.com/questions/9739955/feature-detecting-support-for-svg-filters.\n// detect by erik dahlstrom\n\nModernizr.addTest('svgfilters', function(){\n\tvar result = false;\n    try {\n      result = typeof SVGFEColorMatrixElement !== undefined &&\n               SVGFEColorMatrixElement.SVG_FECOLORMATRIX_TYPE_SATURATE == 2;\n    }\n    catch(e) {}\n    return result;\n});\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/modernizr/feature-detects/unicode.js",
    "content": "/**\n * Unicode special character support\n * \n * Detection is made by testing missing glyph box rendering against star character\n * If widths are the same, this \"probably\" means the browser didn't support the star character and rendered a glyph box instead\n * Just need to ensure the font characters have different widths\n * \n * Warning : positive Unicode support doesn't mean you can use it inside <title>, this seams more related to OS & Language packs\n */\nModernizr.addTest('unicode', function() {\n\t\n\t\n\tvar bool,\n\n\t\tmissingGlyph = document.createElement('span'),\n\t\t\n\t\tstar = document.createElement('span');\n\n\tModernizr.testStyles('#modernizr{font-family:Arial,sans;font-size:300em;}', function(node) {\n\n\t\tmissingGlyph.innerHTML = '&#5987';\n\t\tstar.innerHTML = '&#9734';\t\t\n\t\t\n\t\tnode.appendChild(missingGlyph);\n\t\tnode.appendChild(star);\n\t\t\n\t\tbool = 'offsetWidth' in missingGlyph && missingGlyph.offsetWidth !== star.offsetWidth;\n\t});\n\n\treturn bool;\n\n});"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/modernizr/feature-detects/url-data-uri.js",
    "content": "// data uri test.\n// https://github.com/Modernizr/Modernizr/issues/14\n\n// This test is asynchronous. Watch out.\n\n\n// in IE7 in HTTPS this can cause a Mixed Content security popup. \n//  github.com/Modernizr/Modernizr/issues/362\n// To avoid that you can create a new iframe and inject this.. perhaps..\n\n\n(function(){\n\n  var datauri = new Image();\n\n\n  datauri.onerror = function() {\n      Modernizr.addTest('datauri', function () { return false; });\n  };  \n  datauri.onload = function() {\n      Modernizr.addTest('datauri', function () { return (datauri.width == 1 && datauri.height == 1); });\n  };\n\n  datauri.src = \"data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///ywAAAAAAQABAAACAUwAOw==\";\n\n})();\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/modernizr/feature-detects/userdata.js",
    "content": "// test if IE userdata supported\n// msdn.microsoft.com/en-us/library/ms531424(v=vs.85).aspx\n// test by @stereobooster\n\nModernizr.addTest('userdata', function(){\n  return !!document.createElement('div').addBehavior;\n});\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/modernizr/feature-detects/vibration.js",
    "content": "// Vibration API\n// http://www.w3.org/TR/vibration/\n// https://developer.mozilla.org/en/DOM/window.navigator.mozVibrate\nModernizr.addTest('vibrate', !!Modernizr.prefixed('vibrate', navigator));"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/modernizr/feature-detects/web-intents.js",
    "content": "// Tests for the ability to use Web Intents (http://webintents.org).\n// By Eric Bidelman\n\nModernizr.addTest('webintents', function() {\n  return !!Modernizr.prefixed('startActivity', navigator);\n});\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/modernizr/feature-detects/webgl-extensions.js",
    "content": "\n// Grab the WebGL extensions currently supported and add to the Modernizr.webgl object\n// spec: www.khronos.org/registry/webgl/specs/latest/#5.13.14\n\n// based on code from ilmari heikkinen\n// code.google.com/p/graphics-detect/source/browse/js/detect.js\n\n\n(function(){\n\n    if (!Modernizr.webgl) return;\n\n    var canvas, ctx, exts;\n\n    try {\n        canvas  = document.createElement('canvas');\n        ctx     = canvas.getContext('webgl') || canvas.getContext('experimental-webgl');\n        exts    = ctx.getSupportedExtensions();\n    }\n    catch (e) {\n        return;\n    }\n\n    if (ctx === undefined) {\n        Modernizr.webgl = new Boolean(false);\n    }\n    else {\n        Modernizr.webgl = new Boolean(true);\n    }\n\n\n    for (var i = -1, len = exts.length; ++i < len; ){\n        Modernizr.webgl[exts[i]] = true;\n    }\n\n    // hack for addressing modernizr testsuite failures. sorry.\n    if (window.TEST && TEST.audvid){\n        TEST.audvid.push('webgl');\n    }\n\n    canvas = undefined;\n})();"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/modernizr/feature-detects/websockets-binary.js",
    "content": "\n// binaryType is truthy if there is support.. returns \"blob\" in new-ish chrome.\n// plus.google.com/115535723976198353696/posts/ERN6zYozENV\n\nModernizr.addTest('websocketsbinary', \n  !!(window.WebSocket && (new WebSocket('ws://.')).binaryType)\n);\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/modernizr/feature-detects/window-framed.js",
    "content": "\n// tests if page is iframed\n\n// github.com/Modernizr/Modernizr/issues/242\n\nModernizr.addTest('framed', function(){\n  return window.location != top.location;\n});\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/modernizr/feature-detects/workers-blobworkers.js",
    "content": "// by jussi-kalliokoski\n\n\n// This test is asynchronous. Watch out.\n\n// The test will potentially add garbage to console.\n\n(function(){\n  try {\n\n    // we're avoiding using Modernizr._domPrefixes as the prefix capitalization on\n    // these guys are notoriously peculiar.\n    var BlobBuilder = window.MozBlobBuilder || window.WebKitBlobBuilder || window.MSBlobBuilder || window.OBlobBuilder || window.BlobBuilder,\n        URL         = window.MozURL || window.webkitURL || window.MSURL || window.OURL || window.URL;\n\n    var data    = 'Modernizr',\n        bb      = new BlobBuilder();\n\n    bb.append('this.onmessage=function(e){postMessage(e.data)}');\n\n    var url     = URL.createObjectURL(bb.getBlob()),\n        worker  = new Worker(url);\n\n    bb = null;\n\n    worker.onmessage = function(e) {\n      worker.terminate();\n      URL.revokeObjectURL(url);\n      Modernizr.addTest('blobworkers', data === e.data);\n      worker = null;\n    };\n\n    // Just in case...\n    worker.onerror = function() {\n      Modernizr.addTest('blobworkers', false);\n      worker = null;\n    };\n\n    setTimeout(function() {\n        Modernizr.addTest('blobworkers', false);\n    }, 200);\n\n    worker.postMessage(data);\n\n  } catch (e) {\n    Modernizr.addTest('blobworkers', false);\n  }\n}());\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/modernizr/feature-detects/workers-dataworkers.js",
    "content": "// by jussi-kalliokoski\n\n\n// This test is asynchronous. Watch out.\n\n// The test will potentially add garbage to console.\n\n(function(){\n  try {\n    var data    = 'Modernizr',\n        worker  = new Worker('data:text/javascript;base64,dGhpcy5vbm1lc3NhZ2U9ZnVuY3Rpb24oZSl7cG9zdE1lc3NhZ2UoZS5kYXRhKX0=');\n\n    worker.onmessage = function(e) {\n      worker.terminate();\n      Modernizr.addTest('dataworkers', data === e.data);\n      worker = null;\n    };\n\n    // Just in case...\n    worker.onerror = function() {\n      Modernizr.addTest('dataworkers', false);\n      worker = null;\n    };\n\n    setTimeout(function() {\n        Modernizr.addTest('dataworkers', false);\n    }, 200);\n\n    worker.postMessage(data);\n\n  } catch (e) {\n    Modernizr.addTest('dataworkers', false);\n  }\n}());\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/modernizr/feature-detects/workers-sharedworkers.js",
    "content": "Modernizr.addTest('sharedworkers', function(){\n  return !!window.SharedWorker;\n});"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/modernizr/grunt.js",
    "content": "/*global module */\nmodule.exports = function( grunt ) {\n    'use strict';\n\n    grunt.initConfig({\n        meta: {\n          version: '2.7.0',\n          banner: '/*!\\n' +\n            ' * Modernizr v<%= meta.version %>\\n' +\n            ' * www.modernizr.com\\n *\\n' +\n            ' * Copyright (c) Faruk Ates, Paul Irish, Alex Sexton\\n' +\n            ' * Available under the BSD and MIT licenses: www.modernizr.com/license/\\n */'\n        },\n        qunit: {\n            files: ['test/index.html']\n        },\n        lint: {\n            files: [\n                'grunt.js',\n                'modernizr.js',\n                'feature-detects/*.js'\n            ]\n        },\n        min: {\n            dist: {\n                src: [\n                    '<banner:meta.banner>',\n                    'modernizr.js'\n                ],\n                dest: 'modernizr.min.js'\n            }\n        },\n        watch: {\n            files: '<config:lint.files>',\n            tasks: 'lint'\n        },\n        jshint: {\n            options: {\n                boss: true,\n                browser: true,\n                curly: false,\n                devel: true,\n                eqeqeq: false,\n                eqnull: true,\n                expr: true,\n                evil: true,\n                immed: false,\n                laxcomma: true,\n                newcap: false,\n                noarg: true,\n                smarttabs: true,\n                sub: true,\n                undef: true\n            },\n            globals: {\n                Modernizr: true,\n                DocumentTouch: true,\n                TEST: true,\n                SVGFEColorMatrixElement : true,\n                Blob: true\n            }\n        }\n    });\n\n    grunt.registerTask('default', 'min');\n\n    // Travis CI task.\n    grunt.registerTask('travis', 'qunit');\n};\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/modernizr/media/Modernizr 2 Logo.ai",
    "content": "%PDF-1.5\r%����\r\n1 0 obj\r<</Metadata 2 0 R/OCProperties<</D<</ON[5 0 R]/Order 6 0 R/RBGroups[]>>/OCGs[5 0 R]>>/Pages 3 0 R/Type/Catalog>>\rendobj\r2 0 obj\r<</Length 18095/Subtype/XML/Type/Metadata>>stream\r\n<?xpacket begin=\"﻿\" id=\"W5M0MpCehiHzreSzNTczkc9d\"?>\n<x:xmpmeta xmlns:x=\"adobe:ns:meta/\" x:xmptk=\"Adobe XMP Core 5.0-c060 61.134777, 2010/02/12-17:32:00        \">\n   <rdf:RDF xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\">\n      <rdf:Description rdf:about=\"\"\n            xmlns:xmp=\"http://ns.adobe.com/xap/1.0/\"\n            xmlns:xmpGImg=\"http://ns.adobe.com/xap/1.0/g/img/\">\n         <xmp:CreatorTool>Adobe Illustrator CS5</xmp:CreatorTool>\n         <xmp:CreateDate>2011-03-28T13:28:59+11:00</xmp:CreateDate>\n         <xmp:MetadataDate>2011-03-28T13:28:59+11:00</xmp:MetadataDate>\n         <xmp:ModifyDate>2011-03-28T13:28:59+11:00</xmp:ModifyDate>\n         <xmp:Thumbnails>\n            <rdf:Alt>\n               <rdf:li rdf:parseType=\"Resource\">\n                  <xmpGImg:width>256</xmpGImg:width>\n                  <xmpGImg:height>40</xmpGImg:height>\n                  <xmpGImg:format>JPEG</xmpGImg:format>\n                  <xmpGImg:image>/9j/4AAQSkZJRgABAgEBLAEsAAD/7QAsUGhvdG9zaG9wIDMuMAA4QklNA+0AAAAAABABLAAAAAEA&#xA;AQEsAAAAAQAB/+4ADkFkb2JlAGTAAAAAAf/bAIQABgQEBAUEBgUFBgkGBQYJCwgGBggLDAoKCwoK&#xA;DBAMDAwMDAwQDA4PEA8ODBMTFBQTExwbGxscHx8fHx8fHx8fHwEHBwcNDA0YEBAYGhURFRofHx8f&#xA;Hx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8f/8AAEQgAKAEAAwER&#xA;AAIRAQMRAf/EAaIAAAAHAQEBAQEAAAAAAAAAAAQFAwIGAQAHCAkKCwEAAgIDAQEBAQEAAAAAAAAA&#xA;AQACAwQFBgcICQoLEAACAQMDAgQCBgcDBAIGAnMBAgMRBAAFIRIxQVEGE2EicYEUMpGhBxWxQiPB&#xA;UtHhMxZi8CRygvElQzRTkqKyY3PCNUQnk6OzNhdUZHTD0uIIJoMJChgZhJRFRqS0VtNVKBry4/PE&#xA;1OT0ZXWFlaW1xdXl9WZ2hpamtsbW5vY3R1dnd4eXp7fH1+f3OEhYaHiImKi4yNjo+Ck5SVlpeYmZ&#xA;qbnJ2en5KjpKWmp6ipqqusra6voRAAICAQIDBQUEBQYECAMDbQEAAhEDBCESMUEFURNhIgZxgZEy&#xA;obHwFMHR4SNCFVJicvEzJDRDghaSUyWiY7LCB3PSNeJEgxdUkwgJChgZJjZFGidkdFU38qOzwygp&#xA;0+PzhJSktMTU5PRldYWVpbXF1eX1RlZmdoaWprbG1ub2R1dnd4eXp7fH1+f3OEhYaHiImKi4yNjo&#xA;+DlJWWl5iZmpucnZ6fkqOkpaanqKmqq6ytrq+v/aAAwDAQACEQMRAD8A9U4q7FXYq+TfzF/5TvXf&#xA;+YyX/iWZmL6Q+o9k/wCK4/6oTP8AJn/yZWj/APRz/wBQsuOX6S4/b/8Aic/83/dBJ/OU00PnfX3h&#xA;do3GpXdGQlT/AH79xhiLiHK0EQdNjBF+iP8AuQitE/M3zvo7L9W1WaWJf90XJ9eMjwpJyKj/AFSM&#xA;BxRLVqOx9Nl5wAPeNvueu+Svzz0fVpEstcjXTL1zxScEm2c+5O8Z/wBao98oniIeV7Q9nMmIcWI8&#xA;cft/b+NnqAIIBBqDuCOlMqebdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdi&#xA;rsVdirsVYv588+Wfk+ztbm5tZLpbqRolWJlUgqvKp5ZKMTI0HZdm9my1cjGJAoML/wChi9E/6tFz&#xA;/wAHHlngF3H+hXL/AD4/a8a8z6tFrHmHUNUijaKO9neZY2ILKHNaGmZEI0Keu0eA4sMYHcxFMi/J&#xA;n/yZWj/9HP8A1Cy5HL9JcDt//E5/5v8Augknnf8A5TTX/wDtpXf/ACffJQ5BzOzv8Wx/1I/cEkyT&#xA;mOxV6r+Un5qz6Vcw6FrcxfSZSEtbhzU27E7Asf8AdZ/4X5ZRlx9Q8x252KMgOXEPWOY7/wBv3voD&#xA;ruMxnhXYqwvz7+Z1h5Ou7W2urKW6a6jaRWiZVACtxoeWThAy5O37N7Inq4kxkBw97KNH1S11bSrT&#xA;U7U1t7yJJo/EBhWh9x0OQIp1ufDLFMwlziaXapqVtpmm3Wo3Tcbe0ieaU/5KCu3ucUYcRyTEI85G&#xA;mK+QvzOsPON3dW1rZS2rWsayM0rKwIZuNBxyc4GPN2faXZE9JEGUgeLuZpkHUOxV2KuxVjvnrzpa&#xA;+UNIh1K5tnuo5rhbYRxkKQWR3r8X/GPJRiZHZ2HZ3Z8tVkMIkChf3frT+GQSwpKBQOoYD5iuRcCQ&#xA;o0vxQ7FXYq7FXYq7FWOecPPug+UhZHVfV/052WL0UD0EfHm7VK7LzHSp9slGBPJ2Gh7Ny6ri8OvT&#xA;3sjyLr3Yq7FXYq7FXkf/ADkX/wAcTSP+Yl/+TeXYOb1Xsr/ez/q/peDZlPbuxVm35M/+TK0f/o5/&#xA;6hZcry/SXT9v/wCJz/zf90Ek87/8ppr/AP20rv8A5Pvkocg5nZ3+LY/6kfuCSZJzHYq7FX0h+Sfn&#xA;GTXPLjaddyc9Q0njEWY1Z4GB9JjXqRQqfkPHMPLCi+e+0GgGHNxx+me/x6/rei5W6B41+c9hDqHn&#xA;zylp89fRvHSCWnXjLcKjU+g5diOxeu7AyHHps0xziL+USnH5K6jc2kOq+T9Qal7olw/pKe8TsQ3H&#xA;2Em/+yGRyd/e4ntBiEjDUQ+nIPt/s+5d+dmqXMthpvlSwNb/AF24RGQf76RhStOgaQr9AOOMb33I&#xA;9n8IE5Z5/TjH2/2JV+UOmQaX5+806bb/ANzZqsCE9SI5ONT86YchsBye3Mxy6XDM85bsq88fmSmg&#xA;39voml2Tar5guwDFaISFQN9kuQCamleI7bkjIxhe/R1nZ3ZJzxOScuDFHqkd3+YH5oaDGNQ8yeWo&#xA;DpOxlks5PjiBNPjpJMNvcAe+S4InkXNh2Zos54MOU8f9Ic/sD0PRNc03WtKg1TT5RJZ3C8lY7EU2&#xA;ZWHYqdjlZFOh1GnnhmYTFSDz2f8ANPzRrmsXGn+RdGj1CC1bjLqFySIjvTkKPEApp8NWqfDLOAD6&#xA;nex7Gw4cYnqpmJl/COf3H7mK/mz5q8wXvlq30jzHo7aXqkd6lxHJG3qW00SxSoxRwWAKl1+Hkcni&#xA;AvYuz7E0eKGY5MM+OHDXcQbD2e81jT9G8vfpPUJPStLaBXkbqT8IAVR3ZjsBmOBbyOPBPLl4IC5E&#xA;sGtPPX5n6/F+kPLnly2TSWY+hJfSUklUGlV/eRAdPAj3OWGMRzLusnZ2iwHgzZZcfXhGw+wp55K/&#xA;ME63fXGi6vYtpHmG0HKWyckh0/njJp49PDcEjBKNb9HC7Q7M8GIyY5ceKXX9aC85/miPK/m6z0i4&#xA;s/Wsbi0+svLHVpvUYyrHGidDyeNRv44Y47Ft2g7H/M4JZBKpCVeXSyfgUb5a8z+cr6DVL3WtEXSr&#xA;OCD1tPjZiZHIDFhIa16AfsDIyAHItOr0mngYRx5OORNS7vh/axvQfzb80+YrD09D8u/WtVVyJ2L8&#xA;LSGPbiWdivJjv8NRk5Y6O5dhqexMOnl+9ycMOm3qPwROi/mX5qtfNVp5d85aRDYTX5C2lxbE8CzE&#xA;hOryhgzfDs2x7YDAVYLXqOycEsBzaeZkI8wf7B9ybfmZr9tpH6E9fS7XU/rd6sSfWkD+kxp+8jqD&#xA;RsjEXfucXsnTSy+JU5Q4Y3t18imvnDV/NenRWreXtIXVnkZxcK0gj4AAcTuVrXfBEDqXG0ODBkJ8&#xA;WfB3bWwnWvzO/MbRLI3uq+V4LS1DBPUe4BqzdAArEn6BlggCaBdxp+x9JmlwwymUv6rLdK826pc/&#xA;l9N5nvLFba6S0uLyO0qeLJErPGanejhQfpyHDvTq82ihHVDBGVx4hG/fz+TE7D82/Neu6XD/AIb8&#xA;um91MBjfSMWFrC3NgiBiU5sUAY/EOuTOMA7l2mXsTBgmfGycMOn849/fW+3J5H/ysXz3/wBX28/5&#xA;Gtl/hR7nqv5J0v8AqcfkgNW8z+YdYiji1TUJ72OJi0azOXCsRSorkowA5N+DR4cRuEREnuSvJOS7&#xA;FWbfkz/5MrR/+jn/AKhZcry/SXT9v/4nP/N/3QSTzv8A8ppr/wD20rv/AJPvkocg5nZ3+LY/6kfu&#xA;CSZJzHYq7FWd/krrL6d59s4uREOoK9rKP9Zeabf66LlWYel0ntBgGTSk9Y0f1/Y+msxHzl5H+an/&#xA;AJM3yR/zEwf9RaZdj5F6rsX/ABPP/VP+5Kp55/51P8zdG82J8Fhqg+p6mR0qAELN/sOLf7DBHeJD&#xA;Ds7/AArRzwfxQ9Ufx8/m35SH+LvzU1XzK/x6bog+p6ceql90DD/h3/2QxltEDvXW/wCC6GGH+PJ6&#xA;pfj5D4L/AMuf/Jqedf8AjIf+TxwS+kI7V/xLB7v0KX5fIlz+bnnC6vBW9gZ47YNQkRCXhyH+wRB8&#xA;jhn9IZdpnh0GGMfpPP31+u3ql5bW9zaTW1yoe2mjaOZW6FGBDA19sqeahMxkCOYeK/lrd3cX5V+c&#xA;BbOzQ24ujayGtRW3+IjwoAGy/IPUHr+1oROuw8XM8N/6ZmP5H21pF+XtnJCAJbiWeS5I6mQSsgr/&#xA;ALBFyGX6nU+0U5HVyB5ACvlf32lv/OQwH+DLI03/AEjHv/zwmyWDm5Hst/jEv6h++KF/Pee4TyRp&#xA;ESVEEtxH61DSpWFiqn8T9GDDzbfZuIOpmeoifvTu11b81IbaGG28s2C28aKkKreLxCKKKBv0pkKH&#xA;e4M8GiJJOWd/1Ur/AEF+YepeftF8x32kW+nrZfubp4LhHLwtyB5CtTQOclYAIcr8zpMelnhjOUuL&#xA;cXHqu8xxo/5++WldQyjTnYBhUVVbtlO/cEVGSj9BXSkjsvLX8/8A4h6Lrf8Axxr/AP5hpf8AiByl&#xA;5/B/eR94YH+QX/KCt/zGzf8AEUyzL9Tu/aX/ABr/ADR+lD/myq/42/L5qDkdRoT3oJ7Wn68lj5Ft&#xA;7E/xbU/1P97Nd+d3/TMf9tJf4ZHH19zH2e/yv/Cy9LmmighkmmcRwxKXkkY0VVUVJJPYDK3nYxJN&#xA;DmXkFlFcfmj5yN9OrDybokhWCJqgXEnXcf5fVvBaDvlx9A8y9XkI7N0/CP8AGMnP+iPx9vuej+dl&#xA;VfJOvKoAUabdgAbAAQPlcOYef7P/AMZx/wBeP+6CSfkuiL+W2klVALm5LkClT9ZkFT9AAyWX6i5v&#xA;b5/wyf8Am/7kPFv+VM/mV/1Z/wDp5tf+quZHix73sP5f0f8AP/2Mv1O/5Uz+ZX/Vn/6ebX/qrj4s&#xA;e9f5f0f8/wD2Mv1O/wCVM/mV/wBWf/p5tf8Aqrj4se9f5f0f8/8A2Mv1O/5Uz+ZX/Vn/AOnm1/6q&#xA;4+LHvX+X9H/P/wBjL9TKPyy/LLzvovnfTdT1PTfq9jb+v603r270528iL8KSMxqzAbDIZMgIoOs7&#xA;X7X02bTShCVyNdJfzgeoSvzV+Uv5g33mfV7210r1LW6vbmaCT6xbLyjklZlNGkBFQe4wxyRADlaL&#xA;tvSQwwjKfqjGIO0ug9yV/wDKmfzK/wCrP/082v8A1VyXix73J/l/R/z/APYy/U7/AJUz+ZX/AFZ/&#xA;+nm1/wCquPix71/l/R/z/wDYy/U7/lTP5lf9Wf8A6ebX/qrj4se9f5f0f8//AGMv1Jn5X/Kn8xdN&#xA;8y6VqE2klIbS8gmmYXNttGkis/2ZCfsg9BkZZIkFxtZ21pMmGcBPeUSPpl3e59GZivn7zrz/AOUv&#xA;MGreevK2qafa+tY6bPE97N6kacFS4V2PF2Vm+EV+EHLISABd/wBma3Fi02aEzUpg1sf5pDIPzF8r&#xA;t5l8pXumxKGvABNZVIH76PdRU7DkKrv45GEqNuD2VrPy+eMz9PI+4/i1P8tPKr+WfKVrY3EYjv5S&#xA;Z74Aq1JX/ZqtQeKgLse2GcrNsu19b+YzmQ+nkPd+N0p8leVtd03z/wCaNVvbX0rDUXJs5ucbcx6h&#xA;b7KsWXb+YDGRFBye0NZiyaXFjiblDnz7kN5z8keZLXzQnnLycY21MrwvrCQhVmAAFRUqp5KAGFR0&#xA;qDXDGQqi2aDtDDLD+X1F8HSXcgdU1b84fMlm2j2+gJoqXI9K7v5JRsjbNxNagH/JDHCBEb3bfhwd&#xA;n6eXiHJ4lco1+P0M28p+TdO8v+WF0JP38Tq/1yRhT1XlFJCR2BGwHhkJSs26bW6+efN4p2PTyrk8&#xA;/wBL0X8yPy+vrq10WxGveXrmQyQxcwroT9NVamx2INO2WExlz2Lvc2o0euiJZJeFlA380N530D82&#xA;vOWlQyXGnQ2tvFOrQaNHLH6m6ODPLJI6r8P2Qta/F0wwlGJbOztToNJkIEjIkbzo102AA/Fc3pPm&#xA;jynbeZPKraLdn0nKIYpgORimjHwt138D7ZTGVG3ntHrTp8/iR3/SGGaTqv5t+WLRNIu9AXXYLZfT&#xA;tL2CYKSiii8jRiae6g/rywiJ3unb58Og1EvEjk8InmCGR+UH/Ma91WbUfMcdvp2mtF6dvpMdJJA3&#xA;KokZwWoae/0DISro6/XDSQgIYSZzveXIe6vx70HrHlnXLj83tD8wQ23LSLOyeG5uecY4yFbkAcCw&#xA;c/3q9F75ISHAQ3YNZijoMmIn95KVgb/0fh0LM9Uhkn0y7hiHKWWGREWoFWZCAKnbrlbqMMgJgnoQ&#xA;xL8ovLms+X/KbWGr2/1a7NzJL6fNJPgZVANY2de3jk8hBOztO3NVjz5+PGbjwjv/AEqP5h+Wdc1f&#xA;zP5OvdOtvXtdKvTNfyc409OP1YGrR2UttG32QcMJAAs+y9ZixYc0ZmpTjUee+0v1t/mn5Z1vXP0F&#xA;+i7b6x9SvlnufjjTjGKfF+8Za/Rggav3I7H1ePD4nGa4oUOfP4O/N7SfOWsaHBpnlyD1o7hz+kQJ&#xA;I4m9NQCi1kdNmbrTww4yAd09h5tPiymeY1X07E7/AACR6DP+b2h6Tb6Xp/lCyjtbZeK/6TFyY9Wd&#xA;j6+7MdzhIiermamOgzZDOeaXEf6J/wCJZfInmjWPIOpwapYR2mu3lndwLZRSIy8nR0iAfmy/FUdW&#xA;yIoSdVE4cWqiYS4scZRN15i9qd+WWi6lovkjTdM1OH6vfW/r+tDyR6c7iR1+JCymqsDscchs2F7X&#xA;1EM2plOBuJr/AHIHV//Z</xmpGImg:image>\n               </rdf:li>\n            </rdf:Alt>\n         </xmp:Thumbnails>\n      </rdf:Description>\n      <rdf:Description rdf:about=\"\"\n            xmlns:photoshop=\"http://ns.adobe.com/photoshop/1.0/\">\n         <photoshop:ColorMode>3</photoshop:ColorMode>\n         <photoshop:ICCProfile>sRGB IEC61966-2.1</photoshop:ICCProfile>\n         <photoshop:TextLayers>\n            <rdf:Bag>\n               <rdf:li rdf:parseType=\"Resource\">\n                  <photoshop:LayerName>Modernizr</photoshop:LayerName>\n                  <photoshop:LayerText>Modernizr</photoshop:LayerText>\n               </rdf:li>\n            </rdf:Bag>\n         </photoshop:TextLayers>\n      </rdf:Description>\n      <rdf:Description rdf:about=\"\"\n            xmlns:dc=\"http://purl.org/dc/elements/1.1/\">\n         <dc:format>application/pdf</dc:format>\n         <dc:title>\n            <rdf:Alt>\n               <rdf:li xml:lang=\"x-default\">Modernizr 2 Logo</rdf:li>\n            </rdf:Alt>\n         </dc:title>\n      </rdf:Description>\n      <rdf:Description rdf:about=\"\"\n            xmlns:xmpMM=\"http://ns.adobe.com/xap/1.0/mm/\"\n            xmlns:stEvt=\"http://ns.adobe.com/xap/1.0/sType/ResourceEvent#\"\n            xmlns:stRef=\"http://ns.adobe.com/xap/1.0/sType/ResourceRef#\">\n         <xmpMM:InstanceID>uuid:d2ad3950-7c02-824a-aed8-40a8f4f3f557</xmpMM:InstanceID>\n         <xmpMM:DocumentID>xmp.did:03801174072068118083F1FA8E5E4F1F</xmpMM:DocumentID>\n         <xmpMM:OriginalDocumentID>xmp.did:F77F117407206811BB3F9C0632107F53</xmpMM:OriginalDocumentID>\n         <xmpMM:RenditionClass>proof:pdf</xmpMM:RenditionClass>\n         <xmpMM:History>\n            <rdf:Seq>\n               <rdf:li rdf:parseType=\"Resource\">\n                  <stEvt:action>created</stEvt:action>\n                  <stEvt:instanceID>xmp.iid:F77F117407206811BB3F9C0632107F53</stEvt:instanceID>\n                  <stEvt:when>2011-03-27T17:17:50-07:00</stEvt:when>\n                  <stEvt:softwareAgent>Adobe Photoshop CS5 Macintosh</stEvt:softwareAgent>\n               </rdf:li>\n               <rdf:li rdf:parseType=\"Resource\">\n                  <stEvt:action>saved</stEvt:action>\n                  <stEvt:instanceID>xmp.iid:F87F117407206811BB3F9C0632107F53</stEvt:instanceID>\n                  <stEvt:when>2011-03-27T17:18:53-07:00</stEvt:when>\n                  <stEvt:softwareAgent>Adobe Photoshop CS5 Macintosh</stEvt:softwareAgent>\n                  <stEvt:changed>/</stEvt:changed>\n               </rdf:li>\n               <rdf:li rdf:parseType=\"Resource\">\n                  <stEvt:action>saved</stEvt:action>\n                  <stEvt:instanceID>xmp.iid:F97F117407206811BB3F9C0632107F53</stEvt:instanceID>\n                  <stEvt:when>2011-03-27T18:02:32-07:00</stEvt:when>\n                  <stEvt:softwareAgent>Adobe Photoshop CS5 Macintosh</stEvt:softwareAgent>\n                  <stEvt:changed>/</stEvt:changed>\n               </rdf:li>\n               <rdf:li rdf:parseType=\"Resource\">\n                  <stEvt:action>saved</stEvt:action>\n                  <stEvt:instanceID>xmp.iid:FA7F117407206811BB3F9C0632107F53</stEvt:instanceID>\n                  <stEvt:when>2011-03-27T18:18:57-07:00</stEvt:when>\n                  <stEvt:softwareAgent>Adobe Photoshop CS5 Macintosh</stEvt:softwareAgent>\n                  <stEvt:changed>/</stEvt:changed>\n               </rdf:li>\n               <rdf:li rdf:parseType=\"Resource\">\n                  <stEvt:action>saved</stEvt:action>\n                  <stEvt:instanceID>xmp.iid:FB7F117407206811BB3F9C0632107F53</stEvt:instanceID>\n                  <stEvt:when>2011-03-27T18:25:21-07:00</stEvt:when>\n                  <stEvt:softwareAgent>Adobe Photoshop CS5 Macintosh</stEvt:softwareAgent>\n                  <stEvt:changed>/</stEvt:changed>\n               </rdf:li>\n               <rdf:li rdf:parseType=\"Resource\">\n                  <stEvt:action>saved</stEvt:action>\n                  <stEvt:instanceID>xmp.iid:FC7F117407206811BB3F9C0632107F53</stEvt:instanceID>\n                  <stEvt:when>2011-03-27T18:26:04-07:00</stEvt:when>\n                  <stEvt:softwareAgent>Adobe Photoshop CS5 Macintosh</stEvt:softwareAgent>\n                  <stEvt:changed>/</stEvt:changed>\n               </rdf:li>\n               <rdf:li rdf:parseType=\"Resource\">\n                  <stEvt:action>saved</stEvt:action>\n                  <stEvt:instanceID>xmp.iid:FD7F117407206811BB3F9C0632107F53</stEvt:instanceID>\n                  <stEvt:when>2011-03-27T18:37:06-07:00</stEvt:when>\n                  <stEvt:softwareAgent>Adobe Photoshop CS5 Macintosh</stEvt:softwareAgent>\n                  <stEvt:changed>/</stEvt:changed>\n               </rdf:li>\n               <rdf:li rdf:parseType=\"Resource\">\n                  <stEvt:action>converted</stEvt:action>\n                  <stEvt:parameters>from application/vnd.adobe.photoshop to application/pdf</stEvt:parameters>\n               </rdf:li>\n               <rdf:li rdf:parseType=\"Resource\">\n                  <stEvt:action>derived</stEvt:action>\n                  <stEvt:parameters>converted from application/vnd.adobe.photoshop to application/pdf</stEvt:parameters>\n               </rdf:li>\n               <rdf:li rdf:parseType=\"Resource\">\n                  <stEvt:action>saved</stEvt:action>\n                  <stEvt:instanceID>xmp.iid:FE7F117407206811BB3F9C0632107F53</stEvt:instanceID>\n                  <stEvt:when>2011-03-27T18:37:07-07:00</stEvt:when>\n                  <stEvt:softwareAgent>Adobe Photoshop CS5 Macintosh</stEvt:softwareAgent>\n                  <stEvt:changed>/</stEvt:changed>\n               </rdf:li>\n               <rdf:li rdf:parseType=\"Resource\">\n                  <stEvt:action>saved</stEvt:action>\n                  <stEvt:instanceID>xmp.iid:03801174072068118083F1FA8E5E4F1F</stEvt:instanceID>\n                  <stEvt:when>2011-03-28T13:28:58+11:00</stEvt:when>\n                  <stEvt:softwareAgent>Adobe Illustrator CS5</stEvt:softwareAgent>\n                  <stEvt:changed>/</stEvt:changed>\n               </rdf:li>\n            </rdf:Seq>\n         </xmpMM:History>\n         <xmpMM:DerivedFrom rdf:parseType=\"Resource\">\n            <stRef:instanceID>uuid:edd0f61a-a49d-1d49-acc4-68ea7894e484</stRef:instanceID>\n            <stRef:documentID>xmp.did:F77F117407206811BB3F9C0632107F53</stRef:documentID>\n            <stRef:originalDocumentID>xmp.did:F77F117407206811BB3F9C0632107F53</stRef:originalDocumentID>\n         </xmpMM:DerivedFrom>\n      </rdf:Description>\n      <rdf:Description rdf:about=\"\"\n            xmlns:pdf=\"http://ns.adobe.com/pdf/1.3/\">\n         <pdf:Producer>Adobe PDF library 9.90</pdf:Producer>\n      </rdf:Description>\n      <rdf:Description rdf:about=\"\"\n            xmlns:xmpTPg=\"http://ns.adobe.com/xap/1.0/t/pg/\"\n            xmlns:stDim=\"http://ns.adobe.com/xap/1.0/sType/Dimensions#\"\n            xmlns:xmpG=\"http://ns.adobe.com/xap/1.0/g/\">\n         <xmpTPg:NPages>1</xmpTPg:NPages>\n         <xmpTPg:HasVisibleTransparency>False</xmpTPg:HasVisibleTransparency>\n         <xmpTPg:HasVisibleOverprint>False</xmpTPg:HasVisibleOverprint>\n         <xmpTPg:MaxPageSize rdf:parseType=\"Resource\">\n            <stDim:w>600.000000</stDim:w>\n            <stDim:h>88.799805</stDim:h>\n            <stDim:unit>Pixels</stDim:unit>\n         </xmpTPg:MaxPageSize>\n         <xmpTPg:PlateNames>\n            <rdf:Seq>\n               <rdf:li>Cyan</rdf:li>\n               <rdf:li>Magenta</rdf:li>\n               <rdf:li>Yellow</rdf:li>\n            </rdf:Seq>\n         </xmpTPg:PlateNames>\n         <xmpTPg:SwatchGroups>\n            <rdf:Seq>\n               <rdf:li rdf:parseType=\"Resource\">\n                  <xmpG:groupName>Default Swatch Group</xmpG:groupName>\n                  <xmpG:groupType>0</xmpG:groupType>\n               </rdf:li>\n            </rdf:Seq>\n         </xmpTPg:SwatchGroups>\n      </rdf:Description>\n      <rdf:Description rdf:about=\"\"\n            xmlns:illustrator=\"http://ns.adobe.com/illustrator/1.0/\">\n         <illustrator:Type>Document</illustrator:Type>\n      </rdf:Description>\n   </rdf:RDF>\n</x:xmpmeta>\n                                                                                                    \n                                                                                                    \n                                                                                                    \n                                                                                                    \n                                                                                                    \n                                                                                                    \n                                                                                                    \n                                                                                                    \n                                                                                                    \n                                                                                                    \n                                                                                                    \n                                                                                                    \n                                                                                                    \n                                                                                                    \n                                                                                                    \n                                                                                                    \n                                                                                                    \n                                                                                                    \n                                                                                                    \n                                                                                                    \n                           \n<?xpacket end=\"w\"?>\rendstream\rendobj\r3 0 obj\r<</Count 1/Kids[7 0 R]/Type/Pages>>\rendobj\r7 0 obj\r<</ArtBox[0.0 1.36328 583.011 88.7998]/BleedBox[0.0 0.0 600.0 88.7998]/Contents 8 0 R/LastModified(D:20110328132859+11'00')/MediaBox[0.0 0.0 600.0 88.7998]/Parent 3 0 R/PieceInfo<</Illustrator 9 0 R>>/Resources<</ExtGState<</GS0 10 0 R>>/Properties<</MC0 5 0 R>>>>/Thumb 11 0 R/TrimBox[0.0 0.0 600.0 88.7998]/Type/Page>>\rendobj\r8 0 obj\r<</Filter/FlateDecode/Length 1080>>stream\r\nH��Vˎ$5\u0010��W��T�L�}e@�VhŁ\u000fh1��,���KD�Y��\u0006�K���|83\"�^~~u/�^�}�ë[ī\u0004'���߀��cy��\u0017q���|s\n,���\u0017ך��'���p��k\u0018{�}��1\f����\r��\u0013�<|\u0006�ŗ�m��|C�ƭ\"\b8V�����<��#�n)�#�T}Uz\u001b���|i�\u0000~#ry�\u001e�\u001e1�c���M|��\u001dmE��{M^\n���'��\u00078_U}����K\u000ep�o��(/�շ�l'�\u001c\u0007�&\u001f�^��h^bv�+.��:ܩ��L�\\>�\tV���H}\r�PZa�������Y}I-�Y\u00129�{�p1���u���#����B� ���F�_\u001cW\u0016\u001fS�a\u00184dM\u0006��(N�\u0015\u0014}G\u000e�j�\"\u000bB6e��u�}�\u0005z���#\u0019]�댫�pb�\n[R\u001e�LR���x\u0006���y\u0013\u00158�n�\u0007�B%��?˜�\u001b�\u0015���\\��\tf�i���\u0005�K��\u000b�G�DL�\u0010��&��\u001d�\u0007\r\u0013�n��K>k�\u001fk���9�\n��b�\u0017Q|\u001a*�6��\u001br���F���F\u001cu\u001e|Ek\"\"#b\u0000\u0003\u0015\f��\u0010|edt\u0018��\u001e�%�c�:��Z��&\b�Ҙᄧ�pT-A�-�O���\u001aM7E>۹��\u0006�C���h=k�^5��\u001a��I�p_�]�\u0002\nA\f##�y0�-¹b\rE������\f�N��6\t7p��6\u0002Rĵ�ߠc�㚪ǁ�k��\u0006ƦF��w\u0011Jq�gL\u0005�~h��[��B�_Ay\f�����X\"�H<��G\u0015�,�%\u0005������#�\u001c\u0010\b�D�\r�5�\rM��\r\u000e\u001ag7Eg\u0000\u0003�L�\u0019V�,p�\u0005FȐP\b8��� RW(,�\u001bH��N�Y�\r\u00185�ռ���\u0015U�CV��43�3���Z\r�wd�\u0011\u001d�\u000e)#AW7,P\fm!?��ī\u001c�-�\u001a[�&~�6�P�Ξ\b�t\u001e�\u0001\u0018Uf�Wd�v�1X� =�G\u001eIߟ�\u0004�*�Q�\u0001f�yt@Ԣ\u0014>����5�\r��=�9�R�)ER@5�9�8\u0006-�F�lF�1���\u00029'NOE�Y/\u000e��A�0eu\u001e���\u0019�T1�_�0�,����uw��\u0007gI�v\u001c�̶y�ٖA�4?dl\n�/��\u0011�-�\f\u001d�G�!�\u001cN��{�S:�\t\u000bZ��#��r\u0019\u0003�tg\\�f�g\bL�\u0016�\u0005\u0013d\u0003W��\u000e/�h��A��Gr�Z� \u001b\n���\u000b+����6�;a3F��\u0018\u000e�@��\u0003\u001ae�����\u0016�˞�\u001c�?~�����\u001f\u0001\u0006\u0000��0�\rendstream\rendobj\r11 0 obj\r<</BitsPerComponent 8/ColorSpace 12 0 R/Filter[/ASCII85Decode/FlateDecode]/Height 11/Length 217/Width 75>>stream\r\n8;X.*5o.B]#Xe'qAYk1P*4a@.!l]_ep/*-_RXPW`fG[D6f.h*1a7H@op([&VW*Y^*\nW0WFo2Q9;Fb+MFP43tonNU43q7k''P:'9+35\"AmKh.O9'J#%\\IT$_Z*W;Z'Oj7LaA\n9^>Zd/+=U[R&s-+Brt<DrD5OMUCQS3iH5`HV\"Ec'MamVcE^1X21/>.'Lp'%G5RL>:\n;0\"gleOf`E!,b_4ci~>\rendstream\rendobj\r12 0 obj\r[/Indexed/DeviceRGB 255 13 0 R]\rendobj\r13 0 obj\r<</Filter[/ASCII85Decode/FlateDecode]/Length 428>>stream\r\n8;X]O>EqN@%''O_@%e@?J;%+8(9e>X=MR6S?i^YgA3=].HDXF.R$lIL@\"pJ+EP(%0\nb]6ajmNZn*!='OQZeQ^Y*,=]?C.B+\\Ulg9dhD*\"iC[;*=3`oP1[!S^)?1)IZ4dup`\nE1r!/,*0[*9.aFIR2&b-C#s<Xl5FH@[<=!#6V)uDBXnIr.F>oRZ7Dl%MLY\\.?d>Mn\n6%Q2oYfNRF$$+ON<+]RUJmC0I<jlL.oXisZ;SYU[/7#<&37rclQKqeJe#,UF7Rgb1\nVNWFKf>nDZ4OTs0S!saG>GGKUlQ*Q?45:CI&4J'_2j<etJICj7e7nPMb=O6S7UOH<\nPO7r\\I.Hu&e0d&E<.')fERr/l+*W,)q^D*ai5<uuLX.7g/>$XKrcYp0n+Xl_nU*O(\nl[$6Nn+Z_Nq0]s7hs]`XX1nZ8&94a\\~>\rendstream\rendobj\r5 0 obj\r<</Intent 14 0 R/Name(Layer 1)/Type/OCG/Usage 15 0 R>>\rendobj\r14 0 obj\r[/View/Design]\rendobj\r15 0 obj\r<</CreatorInfo<</Creator(Adobe Illustrator 15.0)/Subtype/Artwork>>>>\rendobj\r10 0 obj\r<</AIS false/BM/Normal/CA 1.0/OP false/OPM 1/SA true/SMask/None/Type/ExtGState/ca 1.0/op false>>\rendobj\r9 0 obj\r<</LastModified(D:20110328132859+11'00')/Private 16 0 R>>\rendobj\r16 0 obj\r<</AIMetaData 17 0 R/AIPrivateData1 18 0 R/AIPrivateData2 19 0 R/ContainerVersion 11/CreatorVersion 15/NumBlock 2/RoundtripStreamType 1/RoundtripVersion 15>>\rendobj\r17 0 obj\r<</Length 969>>stream\r\n%!PS-Adobe-3.0 \r%%Creator: Adobe Illustrator(R) 15.0\r%%AI8_CreatorVersion: 15.0.2\r%%For: (Marc Edwards) ()\r%%Title: (Modernizr 2 Logo.pdf)\r%%CreationDate: 28/03/11 1:28 PM\r%%Canvassize: 16383\r%%BoundingBox: -1 1 584 89\r%%HiResBoundingBox: -0.000488 1.36328 583.0107 88.7998\r%%DocumentProcessColors: Cyan Magenta Yellow\r%AI5_FileFormat 11.0\r%AI12_BuildNumber: 399\r%AI3_ColorUsage: Color\r%AI7_ImageSettings: 0\r%%CMYKProcessColor: 1 1 1 1 ([Registration])\r%AI3_Cropmarks: 0 0 600 88.7998\r%AI3_TemplateBox: 299.5 44.5 299.5 44.5\r%AI3_TileBox: -103 -235.0996 680 323.8999\r%AI3_DocumentPreview: None\r%AI5_ArtSize: 14400 14400\r%AI5_RulerUnits: 6\r%AI9_ColorModel: 2\r%AI5_ArtFlags: 0 0 0 1 0 0 1 0 0\r%AI5_TargetResolution: 800\r%AI5_NumLayers: 1\r%AI9_OpenToView: -70.5 304 2 1572 1032 26 0 0 66 96 0 0 0 1 1 0 1 1 0 1\r%AI5_OpenViewLayers: 7\r%%PageOrigin:228 -28\r%AI7_GridSettings: 144 144 144 144 1 0 0.8 0.8 0.8 0.9 0.9 0.9\r%AI9_Flatten: 1\r%AI12_CMSettings: 00.MS\r%%EndComments\r\rendstream\rendobj\r18 0 obj\r<</Length 5017>>stream\r\n%%BoundingBox: -1 1 584 89\r%%HiResBoundingBox: -0.000488 1.36328 583.0107 88.7998\r%AI7_Thumbnail: 128 20 8\r%%BeginData: 4872 Hex Bytes\r%0000330000660000990000CC0033000033330033660033990033CC0033FF\r%0066000066330066660066990066CC0066FF009900009933009966009999\r%0099CC0099FF00CC0000CC3300CC6600CC9900CCCC00CCFF00FF3300FF66\r%00FF9900FFCC3300003300333300663300993300CC3300FF333300333333\r%3333663333993333CC3333FF3366003366333366663366993366CC3366FF\r%3399003399333399663399993399CC3399FF33CC0033CC3333CC6633CC99\r%33CCCC33CCFF33FF0033FF3333FF6633FF9933FFCC33FFFF660000660033\r%6600666600996600CC6600FF6633006633336633666633996633CC6633FF\r%6666006666336666666666996666CC6666FF669900669933669966669999\r%6699CC6699FF66CC0066CC3366CC6666CC9966CCCC66CCFF66FF0066FF33\r%66FF6666FF9966FFCC66FFFF9900009900339900669900999900CC9900FF\r%9933009933339933669933999933CC9933FF996600996633996666996699\r%9966CC9966FF9999009999339999669999999999CC9999FF99CC0099CC33\r%99CC6699CC9999CCCC99CCFF99FF0099FF3399FF6699FF9999FFCC99FFFF\r%CC0000CC0033CC0066CC0099CC00CCCC00FFCC3300CC3333CC3366CC3399\r%CC33CCCC33FFCC6600CC6633CC6666CC6699CC66CCCC66FFCC9900CC9933\r%CC9966CC9999CC99CCCC99FFCCCC00CCCC33CCCC66CCCC99CCCCCCCCCCFF\r%CCFF00CCFF33CCFF66CCFF99CCFFCCCCFFFFFF0033FF0066FF0099FF00CC\r%FF3300FF3333FF3366FF3399FF33CCFF33FFFF6600FF6633FF6666FF6699\r%FF66CCFF66FFFF9900FF9933FF9966FF9999FF99CCFF99FFFFCC00FFCC33\r%FFCC66FFCC99FFCCCCFFCCFFFFFF33FFFF66FFFF99FFFFCC110000001100\r%000011111111220000002200000022222222440000004400000044444444\r%550000005500000055555555770000007700000077777777880000008800\r%000088888888AA000000AA000000AAAAAAAABB000000BB000000BBBBBBBB\r%DD000000DD000000DDDDDDDDEE000000EE000000EEEEEEEE0000000000FF\r%00FF0000FFFFFF0000FF00FFFFFF00FFFFFF\r%524C45FD0CFFCA8EB78EB78EB7FFCA8EB794C3C4FD72FFA1958E948E9594\r%FFA1958E948E958E9BA1FD6FFFCA8EB794958EB7FFC48EB794958EB78E95\r%94CAFD6DFFA1948E958E948EFFA1948E958E948E958E948EC3FD6CFFCA8E\r%B794B78EB7FFC48EB794B78EB794B78EB78EBDCAFD6AFFA2948E958E9494\r%FFA1948E958E948E958E948E958E95A8FD63FFC49BC39BBD9BBD8E958EB7\r%8E95FFC48E958EB794958EB794958EB78EBDCBFD09FFCABD9BCBFD06FFCA\r%BD9BCBFD13FFCA9BFD1EFFCAA2FD16FF9A948E948E948E958E948E9494FF\r%A1948E948E958E948E958E948E958E9BFD09FFCA8E949BFD06FFA18E94A2\r%FD13FF9B94A8FD1DFF8E94A8FD15FFBD8EB794B78EB794B78EB78EB7FFCA\r%8EB78EB794B78EB794B78EB794B78ECAFD08FFCAB78EB7CBFD05FF94B78E\r%CAFD13FFC48EFD1EFFCAA2FD16FF9B948E958E948E958E948E9594FFA195\r%8E948E958E948E958E948E958E948EFD08FFCA8E9B8EC4FD04FFA1949B95\r%A8FD04FFCAA1C4A2FD07FFA1C3A1FFA194A8FD04FFCA9BC3A8FD05FFA8FF\r%A8C4CAFFA2FFFFC49BC4CAFFFFFFCAFFFFFFA8CAA2CAA2CAA2FFFFCBA2FF\r%CAC4FD06FFC38E958EB794958EB794958EB7FFC48EB794958EB794958EB7\r%94958EB794959BFD07FFA8B7A1BD94FD04FFBD9BCA8ECAFFFFFFC38E958E\r%B795FD04FFCB94B7949594C38EFFFFFFCBBD8EB794959BFFFFFFA1B7A195\r%8EFFCA959BBD94958EBDFFFFFFBD9BFFFFBD8E958EB78E95CAFFA195A1B7\r%8EFD06FF9B948E948E958E948E958E948EFFA1948E958E948E958E948E95\r%8E948E958E94A8FD06FFCA8EC4A294A2FFFFCA8EC4A294A2FFFF9B8EC4FF\r%FFA19494FFFFFF9494A1FFCBC48E95A8FFCA9B8ECAFFFFA1949BFFFFC38E\r%95A1CBFFCA8E94A1FFFFC38EC4FFFF949BFFFFA8CBA8FFA1949BFFFFC48E\r%95A1FFCAA2CAC4CAA2BD8EB78EB794B78EB794B78EB7FFC48EB794B78EB7\r%94B78EB794B78EB794B78ECAFD06FFCAB7A1FF8EC3FFFF9BB7FFCA8ECBFF\r%FF8EC4FD04FFC495A1FFC495A1FD04FFC48EFFFFCA8ECBFD04FFA1B7FFFF\r%A1B7CAFFFFFFCA95A2FD04FFB7A1FFFFBD9BFD06FFB794FFFFFFA1B7CAFF\r%FF8E948E958E948E958E948E958E948E958E9494FFA1948E958E948E958E\r%948E958E948E958E9494FD06FFCA8EC4FFC38EFFFF949BFFA194A2FFA194\r%A2FD05FF8E9BFFC38EFD05FFA195CAFF9B95A2CAA2CAA8C38ECAFFC38EFD\r%04FFCA8EC4FD04FF8EC4FFFF94BDFD05FF9B8ECBFFFFFFC48EFFFFFFB78E\r%958EB78E958EB794958EB794958EB78E95FFC48E958EB794958EB794958E\r%B794958EB78E95CAFD05FFCA95A1FFCA95A1CA8ECAFFCA8ECAFFC48EFD06\r%FFBD9BFF9BB7FD05FFC48EFFFFBD8EBD95BD94BD95BDA2FFA195FD04FFA8\r%B7C4FD04FF95A1FFFFBD9BFD04FFC48EC4FD04FFA1B7FFFFFF8E958E948E\r%958E948E958E948E958E948E9494FFA1948E948E958E948E958E948E958E\r%948E948ECAFD05FFCA8EC3FFFF9495949BFFFFA194A2FFA194A2FD05FF8E\r%C3FFC38EFD05FFA194A8FF9B94A8FFFFFFA8FD04FFC48EFD04FFCA8EC4FD\r%04FF8EC3FFFF949BFFFFFFCA8EBDFD05FFC38EFFFFFFB794B78EB794B78E\r%B794B78EB794B78EB78EB7FFCA8EB78EB794B78EB794B78EB794B78EB794\r%B7A1FD05FFCA95A1FFFFCA8EB7C4FFFFCA8ECAFFFF8EBDFD04FFA1B7C4FF\r%CAB7A1FD04FFC38EFFFFCA8EC4FD08FFA1B7FD04FFCAB7C4FD04FFB7A1FF\r%FFBD9BFFFFFF94BDFD06FFA1B7FFFFFF8E958E948E958E948E958E948E95\r%8E948E9594FFA1958E948E958E948E958E948E958E948E958EC3FD05FFCA\r%8EC3FFFFFF958EFFFFFFA195A8FFFFC48E9BA8CBA1949AFFFFFF94949BCB\r%A8BD8E94A8FFFF9B8EC4CAFFA2959BFFFFC48EFD04FFCA8ECAFD04FF8EC3\r%FFFF949BFFFF9B949BCAA1C4A1FFFFC38EFFFFFF9594B7949594B7949594\r%B7949594B7949594BDFFC48EB7949594B7949594B7949594B7949594B7A1\r%FD05FFCAB7A1FFFFFFA1C3FFFFFFCA8ECBFFFFFFC48E958EB79BFD05FF9B\r%B78E959BC494FD04FFC38EB794959BFFFFFFA1B7FD04FFCA95A2FD04FFB7\r%A1FFFFBD9BFFFFBD94958EB78E95CAFFA195FFFFFFCAFFA8FFCAFFA8FFCA\r%FFA8FFCAFFA8FFCAFFA8FFFFFFA8FFCAFFA8FFCAFFA8FFCAFFA8FFCAFFA8\r%FD07FFA8FD0BFFCAFD05FFA8CAA8FD07FFA8CAA8FD09FFA2CAA8FD05FFA8\r%FD05FFCAFD05FFA8FFFFFFA8FFFFFFA8FFCAFFA8FFCAFFFFFFCAFFFFFF\r%%EndData\r\rendstream\rendobj\r19 0 obj\r<</Length 21034>>stream\r\n%AI12_CompressedDatax�ݽ�Z2K�(��\u0000�\u0000*\n\u0002M\u000f���**N8�\f��\b��Z����ǾS�S�P=\u0000�y���u-o�.��T*���J8ԼN\u001c��]1!0l0\u0010\u000e�$�3\u001bK� ~\u001a<\u001e\u000e�ә�\u001eE��A.Ͱ���8�V\u001a�Di:\u0018�\n�\u0015���*�u�#�����\u001d�?�\u0006#Qxq3�\rE�j�\u0017���� \u001fl�?�̤�\u001eUQ\u0003�rg\u0006��\\�\u0015�\u001c\u0017�\n|.�<C\r:��:����5�\u0011r\u0002<+���`�Q\u001c��\u0010L@�`:�\n���>�\u0012���,òl*�\u000br��\u0011\u0000n:\u0007���l0�c��|\u000e~V\u001e��?�h֔�=q:-��ciZ\b��tF���\u0007��\u0004\u001f��p�w\u0000\b�nW\u0007C\u0011��ә\u00059\u000e�������`�?��tE���ϣ�B\u001b\u0003��\u0002\u0014\u0000�>�����\u000f<�\u0016g3�(�B$.�=��=�\u0011+�E��ď\u0001�\u0014 �KT�,�'?\u001d�\u001b�\u001c�˰�>$��F��\f���\u000e|>Ϥ��\u0014��?*�`4\n-Y!��\u0005��|>\u0013��ؠ�\u000bL.��E����@��\u0010<\u001f�D�$G��Z��T\n:���o��CQ�\u001d\rf��\fz��i�xb\b\u001d�~_\u001dv>��\u0000\u0000����#}�3���p>��S1\u0000�\u001b�?\"�2NFp1\u0011G7�\u0016�c\"��p\u00056\u0005�ǥ���\u0015� ����\t�3\u001aJN�+CFp\u0010\u0014\u0015|\u0016��\t\u0013w!\r>\u0006�\u0002\u000f��s�֤A_�P �����\u0011�����.��g3q�\f\u0001ةtF�\u0007˜]\u0003�ʨ_\u001a��)���\u0000L1\u0002�\u0019�?�w�g�\u0006~>������0[Mi0B0\u0003��M��\u001c��UM\u001a�'ǣ�q \"\u000b�\u001b�Ӄf���؛�jV\u001e蟮烙�t\u0006��# \u0018�$\u0006��c�U����e�\u001d���s�ie��8\u001cO\b�ړΨ\u001f��H\u0013w��agԑ���\u0006�1�\u000b�t�F:l��\u0007��%\u0013 \u0018�\tnbB�Ѐx�\u0001Qg�\u0019,\u000e�\u0011\u0016��3�����3wx�=�}R�(ͧ����x��5�Ҡ+��S��߁��0�\u0018�\u0004�bR\u001a�1����a��t\f���\f��\u0019\u000e\u0007\u001fRg�9��!�y�a���a�??��p0����x��H�Ao(^����\u001f'h�\u001a�\u0011�*A,��ގ&H�\b^v&\"�9����\u001a�t\u001b$0)c\u0013\tgᛗߠ�s�g(N\u0003�����\u0011�\u0012,\u0004\"O �:���%\u001aL�w~�`<��\u001e��.�M��E�Uv�o�t\u0015Pw�Ӏ�����?��\u0004>|���a�\u000b�\u0005�^�`\u001f\u001e�_\u0005Іw�\u000f$e��\u0013\b&\u0001/��{\bC���:�fg\b[��{��\u0006h�\u000b��4`Qj��@��!Qa�!a\u0003��t��\u00017Xd�8V~%3\u0016\u0002��)�\u0001��!\u0005��WU�\u0002��\u0013\b���w�N�m�C��H��\u001c�烹T�c�H#K^��as\fP�a�@�G�j��9C�\u001a�s���\u0007��\u0002ۄ�l0Y��\u0004\f}�\u000fN����t�3\u001fb�kM��\u001bV�H�\u0015�c���T\u0007�T��I����3\u0004\u0018VZw\f���\u0014<��\u000fI\u0014\u0015�x(�<\f\u0005\u0014U�m(\r�]\u001e��xb\u001c�m\u001f���t�\u001d\f\u0007�?׳\u000eZ�~Fv-�ƣ�����Y�\u001c4T<\r���2K�\u0014�g\u0012Ҍ\"��\u0019��A\u0002�\u0019��g����p�4�+�!_��L���#I��so���8��e��\u0000�X\u0007��H�Nw�l�鿡\u0013��}�oRaGo��\u0004+SRW�Y`\u0010\rA\u0005�\u0006��\fu4�_Y���´�6\u0014$���\u0013�yH�\u001e�߸w3�9��{�)\b�\u001dJc���w\u001a�1X�\u0003�(��mx������\u0018�^�qA.��\u0003��c��Ѫ;�� ��G*r\u0014Vf\u0018�{�b�}|��F��ű���'���,�7/\u0016�D2�}�����\u000e8\u001d\u000ez�����@��s�'b��rL�.�H�w�g.ˤ�LZV��5�v�:\u0013\u000f��O�Qɮ{���\rK��~�:\"�x��6O��\u001b�\u001f���\u0013\u0016�_6�?vc�b�\u0018Y����>4�~����:��F\u000b�������6�\u0015u�p>`VdYu�}\u001f\u001d7;\u0012L�L�����T�Uǣ��\n�uN�?&�54o��ȭ\t-e�S[�P\u0012�S�W\u0014��~������p�z��3bxk�?ql�]>�\u0012��x>\u001b\u000eFbp&��ꩲm9�I�o�:\u001c�qo8�\u0004{cd��'(�\u001fЕ)A=�ae��ԙ�P\u0013���X\nv;�Ψg�\u001f\u0019hR�����}0\u0014IR[[�}\u000ez�6-m{��,J���_�4A\u000eĩ�\u0013�:\u001c�%Gߗ��\u000b��\u0014\u001cL��h8�E�C�\\\u000f�|����y<�RQ��4\u001f�\t\\ƓcRsϕ����˹L\u0016�pyoNA��luF��'t�޻I\u000e�{\u0004F\b�M�C>b�tOk�\u0007��L�~\u0006���\u000f�\u0007;C��\u0011�G�������\u001aY,�Z��7�:��\u0003£�\u0007p\r�A\u0014\u000e�o]M����d�\u00036��*v��vz���ch҅�=s\u0003�ћ����6�?��B\u000e\u0005!�0˝�p�,��J��d�ȏ��ڑI��7-��d<�d��q�h>\u001bk,����\u0011��\u0003�\u0019�Q�v\u001d�bЖf��L�\u000f�?\u0004#�\u0013��Ѡ\u0007\u001b�*��J��\u001ep�@��I�&�B�����ب߀��\u001cK�k\u0014_\u0001]*\u000f�3]��R�\u000f����,`�`\"��\u000e�\u0017�A�_\"��v\u0002F`\rR�b>��Xq�\u001b�,�C���c���w�a_����XE��\u0004>��:5���,M�4��b��i�\u0003O�y��u<\u001d\\}\fd\u001c��}Hm�'���}*j�Ck���Z[�\u001cUܠv�񜤹�A�F�t.��\u001c\u001a�D�3<�rh����I���bˀl�4�\u0018�6*ז��R�\\�6,ܔ\u001c\u0017]\u0002�Β�֡)�;�\u0002�G�\u0002�TA���{��I<���Fg�1�|���x��\u0013((Q���\u00039l�`=���Tu�\u001b�z���`�!up�\u000b(��H\u0012;G��V��i?D\u0011\u001a��Y���Ւ=��?P���6j\u000f@&O��?g\u001dI�`Q�!)MApތ�d\u0013T��x:�D?�\b�\u001c�;�T��Y�7�\u0005q\b�uP���+�;J\\�g̜�\fSG����\u0003`���\u0017�V�\"�<\u001f�\f�)��a;�4���P��4�I��\u0000q\u0018\n\\��Q�6��/u�����\u001aw\u0019I\u0004�a*���Q\u001b3��~\u000f&]�;���a[�3\u001c�����\u0010��\u0000V\n��\u001f�7�Q�ဖ3�t�������^\u0012\u001d��V\u001f�s9\u0019wQ�O\u0010Q׺F� (z%dD�\u0014#�4\"�iRJ�y�U�dK�\u001e���ȑ�\u0017��n�\u0005\u0007#l�\"Ƶ�q����k[\u00189��Db\b\u001f�\u001d�Q����-\u001a��ݔ�~v�g\b\u000b�\u0002��èfj���7\u0001���?\u0013F�L\u001c\u001d)�a*���E��H�\u0007�#��\u0017A�Ϥ�\t�\u00002\"�\u001cu�a�\u0001lO{b\b`�)�\u0019��3:���fL8���\u0016��D�����\u00052\r�tޝ:�#H8�}�K�~1��ˇَ\u001d뙽4vs'��\u0007(�8�z��-�|�|38�|���H����l<��v\b��Q�4�\u0013�����\u001c���we\u0004�1)�\u0016�ݡ(�\r]��V��n[�,�r\u0019O�s�\u0006S\u0007����M��HN���!\u0011=\u0000)�\u0006NR��Ͷ4uxd�+,��>\u001f�\\:!\u0011���'��L���'�\u0001�F�\\$�(m#�\u000ef?��Y�Q\u0007&�P�Pߓ��=\u0001\u001c3�4��\u0017�dЅ!��S\u0014\u0001����_[\u0002��>���ag��E�!0��\t�0�W�%uqb\u001d�\u000e؇���\u001eljh��:��a�Q�\u0019��s�J3�m\u000e�\u0014�L{���v��L�=�;l�;���V�(���Ӎ\u000e҇\n˱ͧ�;��\u001e\fx�&�$zC���\u001f�9{&��\u0019�D��\t\u0007Kw�9���\u0019oo<\u0002�3��s\u0010�����ф\u0000�?��mNZ��\u0012Y�\u0004�/N\u0007\u001f#\u0017�a��\u001b;(y\u0006�7��`�\u0016�W����T�O;ǋ�\u0015!\u001e��,M\u0013\u001d��6R�F��\u0004��\u000fv�\u0004�\u0012hN��T\u0003 D$\u0003k��k���T�u�D�0���,�\u0015\"�Q�{?M\u0004*L�Ϭ���t�\\���$��\u000e�t6T����Q�chc�� ���\u0001��>\u0001\u0003H����\n\u0003(tC���.\u001d\u001b\u0001f���\u0007�\u0007D�8�v75\r�uSHܘ\u0015�̓��\u001d \u0013�.|\u0010�ĿD\u0007�ZgN��Ս�d⨚ ���d���.b���^��/ TG����ڐ�׍�~�\b�P��o�\u0011Q�\\�����\u001d�\u0010p��X\u0010ѽ\u0007��\u0004�u\u0003�\te]!?\u0010v\u000b��@�a�:\u0012�\u0001��a;T�����\u0006Z\u000b\u0013\"���\u001b89?\f>/��������\u001c�]\u001f��4�4\u001b�\u0002�Hj�ޝ�$�Һ\u000f�9��8\u0004T�ʁn�9�Łf�Y��o��\u000fr��\u0011�<�D��\u0007\u0017_b|:c��T�0\u0005Pַ�AmךG���t6\u0018)'zÁ����F��J�ןs�2U��|�V\u001a���\u000e��0\"9�\u001fij���H\u0019\"��r�1��Pi�3�KX�NMtr�\b\u0002��`�`H�\f�07��t�G��C��X�9Km�K�S\u0011\u000b�\u001b\u0017{I�Ҕ�\u0012�����Ӽ`5\u0016���=�'��l<\u001a�>��h;1�N\u001e���d\u0015~\f\u0002���]4n��_��ӽ]<e�\u001aה����\u001d|��Qw�z$�\u001d����\u0010,[�#\u0004=�\f���ϝJG��;s+\f}<�\u0018��$\u001f��r֑uV�ݰG=i����\u001e\u001c��BQ1��\u0011i�}X�����S�|B_��٧\u0018TԮ�T�\u0006\"���8\nN;!��\u0011yQK\u0010�,ؙ��J\u0006z��\u0005B1AX�\b$�5\u0002�3�\u0007'�0��QPD�\u0002�\b�\f�3\u0018�C\n\u0002Q<\bȴ���\u0000��\u0018���\u0001>��\u0004��?(�3���ɱ\u0011�y�\u0013u�xTƖ�\u000eF�6�Y\u0005{58~��\u000f����\u001beD3ި\u000b�{�`bU�\u001c�\u0004-��ʟ�3�\u001b:�B�@_���#��-gb\u0017���ً\u0011��i���ng�M:�\u00137\u0012p���̼*\t֫��Y�L�����34��>L�+�Ё<*\u0012��:3��s��\u001du\u0006C'\u001f�a��=�MU��tw\f7��\u0006\u0015��\b�\u0010ч\u0016���;�qQ�z\u0001leǎ\u0007\u0012�i-jG\u001c��.nlTx\u0005�\r�\u001a\u0017Mm��G�r�Ȏh���n�_�悳���y\u0003oP\u0004�:\u0001���9v���̬�!�֟0՘؃�����r��\u0012謞���g��@�;��B\"57\b<�U�f�Y����_�\u0019�\n\u0003�wd\f�ر\u001a���\u001e��(P/�K*�]��\u000b�ޑO��{t]:>Υ�\"��\bjl?���\u001d��I6\u0019;��\u000e>g\u0002�ħv/\u000b���R��_�\b\u00077�b�=_���_�u���þ����]e>CQ��\u0017J$��\u0002�Pl�{7\u0014=̇�\u0003x��΄b��u(~v_\u000e%�3�M�=D0�t�\u0014�LM��\u0019t���:�x�\u0017�9!�y��<�&ު������l�-�\u0002aI���\u001e�'�'����~��{�TǏ�VEz~dˏՇ����^��>ʎ\u0014,��\u0001���IR*\u0014o�\u001e�\u0012�D.\u0014�1�hT9��\u0012����Pt�=\fEg�\u0001\u001aZ�\u001cZ*~�>\u0015�#�Gx\u0018���Ɨ>�@\u0018\u000fi\u001az�*�[�keS#&9������+|�\r���CY\u001dFc*I;Ӗ�<̝��ԵLT�N���px\u0019�\u0000��&�)q�ϛ�R�>d�Fn\u001eۯ�6���HS��\u0011\r�����6!Uǒ���'�-���c����>�&\u001f��뭇&`�\u001d����~��tb�4��K�R�f��[��i\u0013R�\u0005�M=<��b��\u0016�Z�+�1\u0012v�vH��{�NE�ɧ\u001e*xUڌ5��gk5��~���[�t�Es�\u001a[�t맠 mnma�\u0018�2���J~b���݊qV���r���F���zI͘ۄ=�I�$\u00106�Ցf�ٝu\u001aҞ����푞W��3�3\u001di ����O�U\u001a��\u0001?�\u001e푦�\u000f����-ҵj'\u001d\b�В�zzY� ͬ�ӹ�\u0001\u0005�C���ont�0\u0016\u0002mmco�!~��\"�]�Zԑn&B�2����aѬE\u0003���a|��n[�Zo��+5;1#m\u001c��(H\u001f\u0012\u0011�H�i�yԑ\u0002��c},���ˬ=��y�����\"�\u0018�u*�@������ǚz��׍߹=�S�Q�\u001e�l��\u001c\u000f�u�0/F��g��7\u001a�2�b_��H\u001b���~{{�\u000e)H���ޔ:�VDlOhH�ػ�A���\u0012�;�I%�4\u00106��1~�JE��v�(R�>gؗ�[�\u000e)������\u0010>��\u0012����ME:\u0016\u000f\"\u001f4�g�[�Q�H\u0011����-�v?�<�C*I�u\u0005iW��\u0016M,�]\u0011d���YMG����PA�\u000b%\u0016��[�^�E~_+���tO2�4��C\\A���6!\r�?��c��0_|���\u0002⊭�?�\u0010҄U\u0014�'ԝ�43��R�bd�\u0007�J\\G\n299Mn�c�T\u00126\n�S�(\u0014c{��'�4iE�\t��=���$dB\u001a�\u0017�\u0018)���%c\u001a��x��-#=�m4�[9���s��7���,�o��O�/����ڎ��7CB�gb��T\u0014\u0016�~Z����\u0019�\u0006��X���^T���m�q�m\u001c\n<~k\u0015��\u0007l�� E{{�6��\u0019�6\u0010�y_b�Bw9گ+�E������^��g���\u000e�\u0014g�[�!ʯ�\u0018���,B{�foC�����\u0010\u000b�e\u001e�*ﭒ�ζnC{�[�BCoO��G�����m�T�Yߟ�w�J���&���}���b_�\u001f�Mou�=gٗ��8���y��vG��=dۙv��-�X���4�}'����3���:W�|���^s��k'T�����7?���\u001f�\u001e�N7�ߦ_G7;��G\u001a��i3�\u0015=�:U\u0004,�Hݰ��G!�~�/�5K>~6\f�N��ߦ�� av��K�������\u0015�ؾR,>�h��H�&V\u001cO�e鵿7\t\u0013�Y�Y,*��d�a)(I\u0007\\�09�*Uo\u000e�\u000fظ,?Vv\u0019x�VKE�W*\u0015��1���D��[x�z#��\b���\u0016��O~ds�v2|��f�,7�\u0002\u001b�~��\u001d\u0010�ﻚͺ�\u001c�u��\u0002�*`�\u0014�\u0006a-��[{̈́j�\\�\u0019�}�VE���\u000e���HS\u000f�t�k�~҄\u0014v1\r-[�)^R��b|18�А�9 �%�}�����#����TC*\u0018�����Ǝ��64�w-B\"M]o\u0004�:Zi��1T���(H��\u0004���\u001ei��\t[I$Z\u0003�x*Rl;P�\"ˡ�#��\u0018Њt����{:R��P�\u001b\b#��M\u001b�eV�\u000bq\u0005=���y��\u001d�0J�\u001dO\u0010S�\ro�M�\u001d�\u0016X�od�\u001e\"�ҭ��N�z*)�߹*b�O\u0016.*e�\u0015��o����I�\u0017E�P<D\u0013r=��F\b�\u0015��on�Q��.}H\n&��$\u001d\u000e�?h:���B�O\u0019Y�U�H�wr�8�j�M��\u0019V�t�˺�o��A�2Wy��d?�2`������'~6��#���8�G\u0000\u001cX2\u0010��{1�)�����\u000f��\u0001{��)�\t�K�J\\��Г#\u001c���*\u0013}����2>l�ێ�\u0019�Ǉ�J�\b�?W�\td3�c���_{��$��Edr}�L�M��|}�\bwb>�Eg���\t��!qbw{f�=L�9K�+���žsk\u000f\u001e(�Lw��\u0003�������a��̋;����\u0019[D�C|b@��\u001e�\u0007�~f���Q#@h]6���&�Jڪ|�Ϩ�Q:\u0002�\u001d�Qh���6��<�L��\u0014���R6|l�v��6<\f-\u00106\r�0�ĺ���?b��ܟDw'�4�5\u0002a�v��jS\u001e�=��VXq�}�<���l�x\u0007�\u0011Z\u001f\u0004{>��n�tu��`���U\u0010�Mߥa,��6����ɲ}c\u000b�;�\u0002��\"vd��&�u��=��n�\u0019t~�O\u0015���\u001d�=�\u0002]�,��$�c9hܩ�/�\">d\u0012d\u000f<eB�\u001f��\u0013��\u001b0>�\f4��\u0017#�Kز z\u0016���}/1O�A^\\�ia���\u00143NI��2%�9�y�s\u0016=�.\u0006����6&[�Ѩ1�[3IU�*�\u001b����׸��V݃��k\u0017���*\"V>�F��nĹK�\u0012�N�����}�4m���\u0019���W��a�\u0000z~o8*\u0016�.:?9�.*���Cr�Ӿ]\r0V�\u0012[v���\u0006f�P��EHK\u000b������Q�E��3��B�qe\u00143I4�\u0014S<[�\u001ff��k2\\���+U\b��c]7�����\u001fu�F���o�ut:Sw�c��m�+����V�*��\f�ԏ�\u001c���G=\u0010\u00166vN\u001bKQ���\u000b�S��xv#��B\u0015\u000b>��mk��\u001d\tx銛\u0014p�\b:}�o�Kӄ��qG\u0002a�mX��ߢf�S����2�G�����ܘ���$p�tw6���\u0018�@��\u001d���a�a^���\u001f�A[ _�&��h�v�ХٺW\u0001`���,���\b\u0000,����\u000b\u0000���b[vヱ�&���`���X��F�=��g�v񫺂�M?y]������`�Ԟ��\u0010\b�#��\u0012�#\u0016����Vb�\\�\u0006b\u0019\u00178��b�%�sb\\�\u0014#�ջ$l\u0014�ּxH\u001c}\t?'\u000ev��%K�(Z\u0019��\u001d\u0005n�\u0000w�,ڑ\u000b�֒n��\u0013�usF\u001dZ���C����˸7�\u0002XZ�\u0007d�S\t\u001f����0M's�D���!�\u0017D��?\u001f\b�_sb���9y���`T�\u000f\n͙I�\u0016\u000en�!\u0013��\u0018EGe�:\u0007�S_>3M�\u0018����sv\u0002�5a�6x��Ae�trnzЄ'��mp��rp�\u0017]��1'ON�۟Go4��ːq�#\u0006\u0014\b;s��wR\u000b\n\u0000��N-��\u0002\u0002\u0000�b��P���a�VG�e\u0011u�\u001b��>���ڬ�V�\u0005�׷��X�T�g�\u001f�1\u0013���U��^�|�\u001cU��C�%y��\u001c�U\b��ou\\/\u001e��\u0000�y�y��h�p���ѬE#&(�g|�p�}���L\u001cÉ�dT�\u000e�\u0014����\u0004<�|\u0018\u0018��&:1F۾E�V���f�\u0013\u0006]�\u00000�ݵ�v��e8��v�G%e��r\u000e\u00150(�N\u0012\rL�t�$��Y��\u001a��NF\\4��ۥ%\u001a�\u0017P+}i�N\u0012\r@�H49\"��\t\u0012\u0000�%��5%�\u0016�^�� ~{\u0005k�\u001a�@�1W8^d�3\u0014\u001c���E|��&I5�%>��\\d�l�LX��HH9:D���b�]�\u001b��T�ͳm\u000e�g^&�K�U\t^\u001dSϞ=jf�-]Ȫ{��\u0007�\u0000�]�\u0006��ٖ��\u0007;1������ٚ��J�Y3\u00065Q%�+\u001c�jO�b�+58ˆ@�P4�����\u0015������\u0006f\u0006���Z�\u000b\tO�\u0016l���y7�5<�4.V5����V��?ӣ\u00164m��n\b�\u001c�{����E�\u0016���9��ҫ��:kg+��\u0000��\u000f΀8[:�\b���#c���p���y/��0�Z��n�\u0017\u0016\"(�ڼ\u001b\u0016\">�\bJ\u0010`\t:�4S�}��)=\f�*�\n\u0011�9�I\u0019�Y���70\u0016\u0016�t�~~\f����\u000b�mG����5R,�<�\u0001�nU4�-/Z���)a��;����t�.\u0011\u001ca�[�//;#�/�?$Lے)r?�j�=8mKd�\u001a�1��5�����fG���e�ü�\u0018\u0017��k�\u0014\u0002�v�\u0017_�7\b�\u000b\u0013{���Ň�M?*�9\u0006���\u0007�g�\n��ػS��[\u001d\u000b�\u0013����Kt��yq)�b�\u0001���\u0013]\u0017Sm۲�2\u00078[n��6lu�����R�o\u001c�Vo��\u0015�A\u0017\b�&�.�AGd\f-�CG\u0006QY3��[\u0002�ɡsΠӳ\u0005�ˡ#��d�\u0011��K��9gБق���9g�9d\u000b�ʡsΠ#�\u0005�ɡsΠ3f\u000b.�C�A'�b���9g�!N^E\u000e�s\u0006�<\u00169tƀd��7�/�����u�\f�_\u000f]���N�\u0005n����s9��l��/\u001c\f�T6j��\u0012��斯Xr�\u0019�S��bZ�Nj^�9��\u001aif0����\u001c�����\u001c���aQ�g�\u0019�9�y|f��\u0012Do;���]����r��Ĩ'�M��!k^+(�iI�!t�b�\u001c\n\"[\u0016\u001e�A*˜͑�\u0012\u001e���*\u0018��ih�Q7��n~CAl�}����cl\u001dP��f%�%�y\u000f\u0005�JK �M0�Bf\b�d�\u0019Z^B����ؤB`W�K�7����n\u001e\u0012�I������Dئ����9�0�r�!\u001f$���5�I(�3��\u0010i�q�����R1Fw,��F�و�4Oy`���:�#��u�+��!�Ϡy���m�N+zj�HM�1��.1�5�\u0018��+ͳ�2J\u001e�[\f��<>�\bq2��G\u001e�Ƀ��\f8\"�\u000e�%��k���ܢ���\u001e��-\u0001~��O/\u0016��K��?�\t�\u00003:~��%\r�N8��%{Ɠ.[7�|�\u0019C�b��/� -(\u0000м�\u0019{xus����ng����z0�f\u0007.�\u001f��\u00030f\f�\u000e6��0\u0000؟�6W�\u0018�Wm�i4qK���\u0010���-'#\u000ef\u00185��v�\u001a׾+9<�\u0017h�q�,9��F�\\ЀR�\u0001YbG��S(�,��b_�\u001f3;�\u00139VF=��ɰu�r[D\t��%A�E��3��\u0011D\u000b�c_��\u0015�/���\u0015\u000ft�\\��t\u001e�:���q�\u001c3��\u0000\u000b��J�,��\u0019g�v#�m�|yd\u001c��\"\"V�ON\u001e\u0019��.o���1YIF�����A)I�xdt\u001e�9Y�##l\u0014\"\u001bvv\u001c)a<�\r'�=2T{��di�\f\f-\u0015�GwxOC��q�O\t��-�AIh�)#u\u0001�̉\u0007�L�[~\u001e�#�)9G�a\u0010u|��8FI$Mʲ�c咇�IY>�\u0006H��I,\\�L\"�6��\\\t\u0007�Y\u000f��\u001e�\r;�#gi1���\u0016�ʟ�?fϡ�\u001eC\u0017���P肇lA׼:w!\u001b�W�%�q���G\u0007���\u0000\u0011�:4\u0017���i��\u0014�\u00072r�|�\n���@Dv�\u001f>,�\u000fg��Ԍ�U��-{���|87\u001e[M>�|��9#�?\u001c�|8�\u0011����\u0011z2�\u0011��|8�\u001bAW�\u000f�\u0010\r���+ȇ#+\u0019�,�\u0015���1�挸U��Q�8W�\u000f�l�юuj��\n2��\u0006�\u0012K�9&\u0012@q�tK\u000f1�\u0000�_��\u0007z_{8��U\u0003�H��U�\u0013\u0018�%2��\t/�c4�]{c��p�α�P�EH��!���g�\u001d�v1�\"�A\u0011��6/��sə�r\\��e��ԥ����}���\u0014��[���.Ǩ��[���I��x�.��7��Vs\u001b0��v��\u0007�\u0015��\fmw��J�a��\u0017�oӢ�Y�,W\u0002�݆\u0016s��\u0011�g�*B�|\u001bԔ����\u0015�\u0002c�\u0004�[eF��*3R�V�������Tn-���T����T\u0004g��T\u0004e\u0015\u0019�({��\u001ahS\\\u001f5\u000b\u0016�å�����\u0015s@@X�a[Zگ%K\u0018\"\u0019n�\u001e�T8r\u0017�\u0012�c\u001c�W���.�U���RI��GR�\u0016�+}���� Ze*�\u001c\u0011�\u001e�t*\u001c�C��y/�h�u�T��5XB\u0018xK|2\u0006H��\b��J��_���\u000b_�&S���\u0000ȷ\u0003\u0019�kf��-��<�/\u0019v?\\�f��$6\u000fG8N��\"Q��[\u001e-��=���%�M�F� ���cPu���o���G�E�\\mdC�ϯkT\u0014�\u0011\b�\u0002�����\u000e\u0017����P\u0001�kT@�&�}s�A���e)�8m����wVٌ���d�U���\\���Eؕ�d�f�%�l�;�nm����d�Hw�ꛖa��>;%��&�HqQm\n��:N��gؽ:%���t�����T�����^\u001c��]\u001e^\u0011HM��P�ij�]�s��n{BK\u0001{pJv�`MH���^��\f��w�ե!�8 ��\u0005�z|\u001f'�T�����-��q�\f����iV�rM`�����7�{jw�.\u001aczi-�.�B\u001e J��7y\u00117\u001a���j�1u�¯�\u0011ӆ��;v\u000f��h���\u001fs��٣�Pj�\\�jBu<�{M�u�\u000em�j��\\�S{\\k�X\u000f��|}�U�3vin��_U%9����kn�-�\r�{z���\u0015G\fq}\u000e���%�ܽp>��Q��^�ͭ؈���ݥ�p\n��:#^��R���za�\u001b�gOt\"}��\u0002t�ŷ�l:;�§\u001f�C6��\u001d`�[*��.���~\u0018��tv>�@x��tv�th��6�Ύs\u0002+Ϧ�z�W�Mg\u0017H��\u0010o�tn1��ɦ�;��?{]&��8�r.\u001d�dd�l:���Ug��sFV�M��%���{-���Tt�l:��(`p\u0012�\"�ήK�i�����r�l*�,�Mg7ڝ�+˦�\u0003���0��.��&gd�l�E)�/�΅b+ʦ�˥�I1\u000f�tv�t�\u001c�%���4Osn���tv\u0002�X7a\u0015�tv�%خ\\i6�\u0011�����`6��<SOF\u0016Φ#gH=Zq�_\u0016̦��+��X0�� ��J�3�\u0016ͦ�\u001b\u0010q\u0007\u0011M)E�Z�\u0000�����%y'RvU1�\u0012��>|\u001dc\u0003�p[㢉O��¨]��^��v��zu�6���\u000botr�lK0)�(��¹&�{c\u0001t�[%�moS�I�lm#흪˹����%�\u0003u��r��%���(a\u001c��.a�\u0016����N\u001a-�\u0013�Ed�>2;�(ղ���\u0016�Y��Ŵx\u0018�*��2w\u0001/\u001e���a߅[�;��t+�={�2wd\u0016'�Н�4%J�;�\u001e�\u0005���z\u0014ͅ�|�*Y��Yn\u0002�+t�@�\u0007�\u000bD-�E�:]a���t5�u�y)\\.��s�\u001c��EB�&���\u001e���Fs�t��Sj�9Rŵ@\u001d=��kV\u001a�M�\u0012��-�\f�&뉓�\u0015�\f\u0007 ш�PF�x�����|�� ׼��.��t�h��#�#\u001a\n�����¹�K�\u0018��K ����\u0015\u001c�`(\u0006��f�=���Q#�\u0010��V�\u0005\n����\u001e��c`��\u0005=T`7'�~�\u0011Kb��z��=��K�T��F��Ft\u0003�mOػ���\u001eaR����t�\u0004ښ5��%_z�\\%Ӌ�d�\u001cY,3�v�\u0015\foWW��֔Ȱ��o�}������2�\u000e�1��\u000f��o\t��,V��`� 8\u000e!C�bUa��$2,q�\u000b��u\u0019�3�D�\u0005<�\u000bT��ͯl-�\f\tP��[�V�Λ6�l�;\"�ѶƝ��\u001bJ���*���'�T�[v\u0019�*�9���!?�[��\u0000\u001d�9�v�\nw^o5�=�.�؅ni��\\n��X˭�ڍ�݃�\u0013k�5Uҩ�����\u000b��G5�}�{�0\u001cO�,�+\fg��Z\f\u0005��'��9�\u000bw��J?���\u001aO��H\u001dƜ�d\r�A�[��\u001b��_˾��2���t�O����}\u001a�S�Z��S���j�\u0003�O\u000f�f��~U\u0002�o\u000f��C\u0012�=��WcW�%g\u0003�lWR��B�q�etU\fM^\u0005�c\u001a�_Ű+������U�݆����\u0005��Jy~s\\K\f=�N\u0017\u0005�{�\u001d2���B���{�N�\u0003X��j\u000f:L��z�5=Vʻo{�\u0002J;K�\u0015�VV�\u0011��tw��\u001cW}���F���\u0019hL%��m\u0004�J��I�\u0001e�ݠ?��X�9Ai}%���\b���6u�&�)�\f�iҔ\u000bK:R���:lk|!o�\u000f���I͇��o\f=\t\u000f���\u001f�s1�\u000e�Mu=-K��)��3�/�ܿ��k*�M�ݣ!�SS�\u0002�i�xM�՘�6]�\u0014i�p����Ə6RS>\\�H��j�\u0011\u0004��H�j�=� ͬo\\��vH\u0003a4V��õ�4EGZ����H��H�S�\\���\u0018'��-*Riz�\u001f�C\u001a\b˹�/�\u001bì�y\u0015=��LD�������u�3\"%\f�ef���r�\n1���M�\u0014��#�ҩGDD~,^��\\�oQ�F�!lR��m΃��+)BPF�V�xb�\u00162�P�Π��U1��)���փ.R�üU�����M�\\��,�=IOe�\"(z$�3���V�d�mS�+Yi�\bM�=����g�\u00165�\u0007��5&�k�\u001d�ݎ��{֝K4[�G��\u0017��\\/;\u000eU���Xcc����e����*L���u�\u001e}�\u000f��2�-\u0003�*�-�P\u0018��֕���<$֗��UVqo#�\u0001TW���Z�z\u001e\u001d��w��\u0005�ra��\u001c@��bnVK�1J˓�\u00184�Y�v����J�Nuu6rWX�2\u0011\u001e��;kg���D����\n��p\u0015�ꠑ3�yU�s\u0013sY\u0019�����ȷиf���F\u0011��\u0012����~�Ys�H�����er��.�\u001c��2,-��m�{\u000e<h㤦dqx�M\u0005$��t�h���9�ӵ�e�h�=�9�5Q�33H\u001ej�y\u0007F�W���\u0001��\u001d(���b��s\u0004�QO.\u0017��CB�%]�p»`\u0016�W��X+�o\u0016�qU�s\u0000mn��\u0005h�\u0003=\u0007�T\u001f�g\u0016��\u001c@E�SM \u001a\b\u0015�l��|d\u0001RD�%\u0007бF�k\u0016���B�U�\u0005H��%\u0007�)ǊJ\u000e�\u0015��md�Y�^s\u0000�6�ŭ��\u0016*ʷ`E6�E��\u0019�+-���UXQQ��w��DQ>�\u001c�������E+�y-ʧz��٢|��P��٢|��W.R��֫�:%�\u0016�ĺ��\u001b���Ȫ~d\u0015�U�\re_��w&\u0017���\u0002wC-P׏:�\u0015�\r���[&N�{]?笻\u0015�\r���-7���~��+���S�Εa��\u000b���w��\u0017\b{P�5�������Z����#�U�̑*���s\u001e�c�J\u001fu����-]\u0001D���<������E�����s!�@�G̙C]?�իj���#�u��7:�>�p]?C�����\u00127P\u0019��9�N\u0005VT��=�c\u0015u�������G���\u001eߢu��P�U�(7����G\u000f'�������,ǖ��瘞���W�%F��g�{]����9\r��WQ��9����곮\u001f-\u000b�8MX2�\u0001��\b����\u0007ѩ�����L]?��l��-X���-\u001e�z|��=\u0010U���渥�ަ#bOѶ\u001e��9\u0007�j���2\\����}\u001ez]����i)W���dƐ��#k]?w9���~�U�VS��-H�k=��/�ѭ�\u0015��S�����no���s-�G�0\u000b��sJ�x�������ٲ�V�o٬4oj\u000eq^�T]?g5�Ȭ_���Nm�,�E����¥��[֛e��\\=>�Y�\u000e1W6u�\u0016M�Wr\u0012���gX���~\u0018�\n����l�U�d9�|]?�@'�������ٮPle9O�U���-�\u00143��[خ�U׏&\u0003�~+�\u001e,9W�3�6�p]?�~��\u0007�POg[0!�vG^���sU?\u0017}�{B�cU?£�T]�\u0005t�\u0005��Qg\u0012\u001f�xήu���%�r��~Λ\u0003򎚷\u0007qf���\u0019}sP�\u0005Kć��Ut\u0018����4�vᙃ�w\u000e�7�-�l\u000e��&&\u001f\u0016LN��/{��jlD�\u0000�\th)P��QI�'�2F\u0010�Œ$�_\r\u000e��ݓ#.ww�o�q\u0013�OU��4;R(�\u001c�\f!GPh��\u0019b���b;�������C�f�=f+��$[�J\u0014����\u0011H��x�`k��\u0004�8>o����\u000f�b(~��gB��9\u001e�����;�bgC���7g�\u0012�\b�\u0018���/ݵ\u000b�����m_\t3�M��b��\"��$U���y�#͹Q+\u0010���\\d���D*��\f�vn%\u0006��E�<�~�zy�\bmo��\u001b��a1ܼ��l~~���������\u0017>N�7/�_���m5\u001104�OR�oxJp�Y \u001c:��܄�\r�\u000fO�c[\u0019��\u000b�/�NQ:i#�(>��\u0012�J\u001d�B�D,L*�X�\u0002r�ٷ�ר$�'b�X-#ME�c���![-�\u0016��{]��L�_3]��\u001aR���Vb{��'6Ym���K��ʶq�?6y!�Mʖq�\u0018J��E~t+14}���}9�v3\u0014�=O�\u0012ɭ\u0016ʸ-�6ʹd(\u001e=<D�NB�˵s�v{�^\u001c�\u0012GB?\u0014?�����a��ߜ��r�L>���\u0006�]�v\u0002�Ҡ��иڇ;���'�Z��r��z��?>��S�\u0017��l�{���\u00166�?3��0I�\u0015\tň��K܆_ԣ2����\u0018^/���\u0010I��\t�k#��\u0000)0����l2}�\u001e��\u001bӣӻ�\u0017�\u0002�����lT�G���\u0003,ī�FiO}UJ�/������8��\u0000���H}q�i/^a��C6Y����\u0000\u000bzJ⮕�zs\u0012s�\u0001zǷa+{�\u0001��(�2��Ë+\u000eI�\u0018W?�\u0012�\u0018�۱r<<�F���\\�#�`�]�1���F��� �YY �\u0012{\u001cj���\r���1��KN���-\u0006��Ow�\u0011�\u0018�<�\u001b�\u0006\u001fM��\f�$\u0000����\u001e\u001c� ,;����8d>�����F��8t�[\u001b�'�d����\"\u001f�Wwe[l�`/\u001b{\u001a�bz��\u0010\u0003���c���z�1�<��,\u001a!\u0017����h^�@M=T���UPY�&E��|���N�O�|YB!\u0000wI���\u0000����G�8E%O���;F�\u0004�SJ\u0006Q�����G\u0005b�WE��T��j�8ܛ@X��\u001b�:P��(\u0010\u001d}+o(K��+���1#\u000b\u001c6��c��u�\u0012�G_\u000fw��\u0006�_�)��p�\u001f�L�6�\u0017FG*lF/\u0010Q_���\u001dJ�}�O<���#���T9f��e���P*�r�j�r�ʑrSQ\u0018J�~\u0000�����0�%-wѧ\u0013��@\u0016���Ʌ��4\u0017\u001bNn��\u0013Ѣ\u0007aG�m\u001e\u0010���z�ڻ�F��(�y��{G�P�,\u0006!\u001c�U:�v��\u0014�H\u0006I��\\�T�~�h���\"\b��$_N<��X�{quV���e\u000f�J\f���\t�*FE����$�\u0018E���\u0010R�B �R\u0011\\��\u0001�S$RP�^\u0001\u000f#�U^�O��\\�\u0011C��Tf]�\r����1\u000b��\f)<����pmT�\u0012\u001bǟ*ϞG\u0015/�,�j�5\u0006�\u0010\u0004�a\f��\u0019���,Wy>��ժ\tYFn�]���F�MwO�x8�I��3\r\u001d6��I�\u0018i��\u0005�1���\u000e'\u001c�V�\u000eg��\u000e>����Y����\u001c�b��|�\u001c-l�˅@��.Ə+wE�����ۄ��u5��ޯ�7���������\u0003�w&%�@\u0013ޮ�L�]��\u001d\u0002I�4M\u0006�,��dg66\u0002��B��� �����s��\u001cp��Gɣ���`Z-\u000f�����@U٦��u\u0005���\u0014Y\u0016\u0004��i%6x�<�i�I;b^�\u00061\u001a���֯\u001a�Ng�\u0001����u!����U���\u0012R\u001c��qi¬W.�\u000e��/3��]�={�\u000ewN��|\f7�\u0016۟o�,\u0016\u001f�-�@@�H��(�:T�1���>\nŜ�ˬ\u0017\u001aW@mqP��D.�1c��\u0001����悘wN7���Zm���,��$\u000f�=\u0012��\u000fܱ��^\r�Ͷ�T��e�?�+]@;܃e����x幊���4��4��M鰵u�{8�K\u000f�v��~t��\u0000\"�6���+�\u0016����2�\u000f�ʰ*\u000b��L�Q[��\u0016��\u000b��?�aŮ�˽�\u0003�C_p�����W�h���\u0019�p$���ތ�b��؉Q�b#Hww\u0013���Sk�\u0018�n��|pzTO�$\u0010���b��\u001f�+�^�\"�\u0016^w\u001e\u001b��ڰu�\fM����t�ǧ\u000bp\u001c����nZ��(��\t�T*~o���LvkJe>�b��W-�`\u0017� W�`9<�@�ÀUF�l���}%����W�X\u001f[l���c��\r=�5�<���A��Rb��\u001en�cλ��\rŴ�\u0004����b\u001a.`Y\\i�Lh\u001c\u0011�6`��f\u0019�R�e5�L]WK�'mM�Ŝ�\nv�u~\u0019''�,\u0013��?�s\u000b_,W\f��*�u\u001d\u0006¡�v�\u000f%�+�Ȧk ��\u0014^%$d�]��1h\u0012\u000f%r��Pt0�\u000f%F����,6\u0005��H{A��mɗy���\u0014�\u000f�s\t¸f��Q�y�R-��oG7;_���S�\u0004f#�v�{Pe4��>\u0007���HB\u00010yӘ\u0011\u0016+n\n�x�:�;�9�\tU�2\u0017������uk��W�|��}����.3WoR�}o����\u0000Z�\u0012�\u0012�\t�\u000b���\u0012[Y �u�՞<R\u001b�Y,Lo�c�'4%�l\u000b�W�?8�\u001c$�J�\u0007��;\u0010�/a��ׅ-����p��f\u0011g�{��|1�\u0015���1�g������<�-4�3\u0010\u001d��\u001e�{��Ak�g��\u0015�v\r�K\u001e#��\fS�P��?A_Y�\u001d�C���#����\u000e�A.Bѷ�\\(�z����|��?��,*\u0000Tqk2V�\u0018�������\u0006�/̕�[��p��|\u0003�W\u000fv\u001b�r�j�Z��������\r����ႄim��;c`Yb��Xo��\u0005���e�}s��\u0014�.�����B�\u0018\u0012�\u0012�Bm\u0006ld?�kAn\u000b�}-�\u00051\u0013�o^�ׂ�+�ri�<��\u001a.�����__��1㻠�/�\u0005\u0017\u0017�0ޗ���B\u00114�_�s@9�UVe�Ȱ|��p~\u0014���G���j� �>9��\u000b[����娞y;?|���T�����\u0001�ʕ���J�`�\"To\u000e�\u000fή?��c\b�Y�[Ơ]���n���7��w`W.t��y��ǫ�]��Lբ����h��\u0011���*,Gg\u001b*\u0010^�\u0015��a�\u00178�����c\u000b\u001d':b��\u001f�iJ���W}�n���\u001f�\u0016��E6�\u0018�\u000b�@\u000f�K�*v�\u001c(�m���g�E���cJT`�36K��Q\b@A�:��9�Ӟ��\u000e����nn�^=�6���\u000e��BEv���M����N{Tm\u000f��G�Η\u0007�\u0006��x�:\r\u001d�--��Y�۶\"�A�)��!љ\\�1�)��y�#�R\u0015�;�\u0005�h4����\u0013��]^����/�[.0�xڑw�\u001f�x�S�UO<�v���ى���x��+������iW�c���[4Xǉ�U{���\u001a?�͐\u001c��P,b��1c��p���C\u0018A�n\b+����\"\u0013�=\u000e�b�Cb��L��\u0004*�l�t���4�\f�x�X�(\t >��\u0000�<�����������\u0000?[[�?����x�\u001c=��j5�\u0003`ŵt�\u0004 \u0010��o\u001ei \u0006\u0011\"�\u00013�\u001cg�\u0002�*�;\tas�\u0003��\u001c�j���(�����\u0018��˴�BI��j�`{��\u0006\u0012\u000eaGՍ�2>/:[�vz\u0017g(�q�T�GΏP\u0007��}x�����(:?~\u0015�\u001c<�@GS5x�\u0019\u0019;6R�e\u001e�\u0003�C��Ӧ�*���ź\u001a�{n<\u0017{��\u0014�\u0015��1�FM��Y���+K.��ֵ�\fu��\u0005Ge\u0012���\u001a\t�u\u0012\u0000���ӅF�{#\u0011b\u0004\u0011�$��\u0012��\u0011$(=�_U\u0012\u0018�L�e%ݫ@%��\u0006A���/����@\u0011\t\u0014�J�\u001eyJ�$�5�,D@�I\u0019����V���9�|��\u0019�>4NV��\u0015\u0010A*><�D�t7��)|\u0010�\u0010T\f�ވ�Q4\u0000&\t��G�\u000b�\u0011��\u001d\u0000���\u001dD��\"�׃^/)\u001a_v\u0018\t*\u0000rU:�`\u0016\u001c\u0006q;Pr�a�&�2���Ɏ 8g\u0010�\u0000��@x��\u001d��\u0000 \u0010v\u0004�����,�P�\u0000��l�\u0013�>\u00188\u0002�\u0001g\nۂ`<̆px\u0019�(\u0000:\u0007\u0017F\u0000\u0004K\u0005�\u000b1U��ŕx�Ap^(���y\u0015@f\u001d/.EZN�j�%C���rc$�4��r?���\u0017\u0006\t��\b�\\V�$\u0013T\u001e�ʦI/\f��@��R'�\u001axl�a��:v<��\\�I�ˎ\\O흕b2\bi?-\u0018@�\u000bH\u001dӎ���)��\u0007[��)�\u0012<� G�;2oVo�\n.�.u�vdlr�eu8�Sd�R��=|\u0017��\u0002==��Z�U\u0012v.�\u0011�\u0002�#�\u0013|�ޏ#�2!�%�D$�kFID�]c0X5O\b>��-�d:\u0015�_�D�t\u0001'+n)�8�Ä\u0012C\u0002\u0010�8�,l���YM﯇\u001fjR�)��8;z�^�\t��R�����/n�~ ��b�W\u001f{��\u000b�xa�7�ͧZc��=�\u0011��h�\u0013��'�W�\u0002��s-+\u000f%\u001d���z�! +\"\u0001\u0004\f��d�p[K|j��<�Y\u0015�e\u001b\b(\u0016��!S>��\u001dm���\u0017`\u00044/�ȗ\u0012Ƿ$��[\u000e�FΤM6�����7Z�71\"m��ɀQ���sX�T,�%�\b�����n\u0016>F[���J����$S��;��F^�jW�8C�ﹲ�cpQDOr��\\�z�%ޔ��{!���p�i9�<�v:l�+��\u000f�\u0014���!�~�\u0017�\u0007�@�,0l�6��#w�Y��8�§'NI�����c\u001e��\u0011�O�\u0014\u0006�'\u0011���+\f1��U���I���O���UO\u0003��[\u0007�}�7�}�x�\u001a\u0012�x)�og�a5-�'�H\u0018�@F|���>3Ջ�0��#P� �w�\u0007����dS�Qc��{=ᮧ���\u0005�_�\u000e#�é����RYĳ���7�Y��\u001d��ɶ\u0012kgշ�p^�Ӭe�\u0015��=�i���GX4m���z�4\u0001�\u0003_\u001f$\u0018F\n�&�`Ǆ�ϸ����<q�\u0005�<q�\ri�\u0013\u00183�\u0004:\f�(b��} �8�2�=N\u000e�g��\u001a<�\u0017bX�\n\u001b;�\u0013�K턃���NـzE]���禴r�c�{1�˧J\"6�'4�S�\u0011�V���}�7�7X5c�#s��Z�7\u0003��q��ʶ6��,����������D�\u001d�ِ���/9�����]��!���\u0014r������\u0007��<\u001f��B&���\u000fE�B\u001a|\fF�x`'�<:��Q\\�D�F�Ϭ<����,X\b&��K�ǹtY��b\u0010\u0017�O��l\u0010Wz��-y��!�N��.��k�����N��}�7G�E��\u001e����K��ʇX���'\n�cB�y�\u001a\u001d\\�C\t���Lgw�\u0010�\u0013~��<�&ު����I�\"\u000eI\u0006�c�{\u0014���\u001c������\u001dS\u001d?�Z\u0015���-?V\u001fn�{G{=<���K\u001ay�p�\u0001m�TA��\u000b+�\b����P$�Y�\u0012�wP�q\u0013F�i:�#'���iv�î\u001e�f\u000125��l�<�Bgk�!-����6f���!�~���ڎ�V��)\"�\u001dq���j�S�qFr\\\rH�E�3�\u0019�I-��\u0019�դ��~*B\\�`�)&V\u0016���\u001f��\u000b\u001bH�jH-&��a�\u00119�\u0004�Z\u0001+0Q\u0012s�0f����]���+.K(�\u001b��v��}:�l̵[\u001e�9r;j�J��rET4�\u0013�:�����J��������\u0014�^��?u9��G_�e��^F�r/�\u0006\u0013U���c<�1򚉇\u000bf�-�,\u0011�-��*i\u0007/\u0010^\u001c�-K��۽B��vs���=�\u001c�\u001c��d�����\n���7ڻ�.9�\u0011�\u000b\u001b���6�^ �}�+FV\t*�����֒�\u0004=%\u001f��?\nu\u001c\u0013�w\u000e�I���GZ�\u0001�\u0013��[\u0006)z\u001c�Zn\u000b��v�\u0004y��w�'��\u0001hר|���\u0018��X�j��e���?JB�����%�q���j>��h[�Ty>�ɟ�~�>\u0004��/>�*��d\u001e���{xz\u0003\n���}����]�p��z~��կl��\u0011�τKs���=\u000e�\u0002��Ԯ�\u000b/\u0017�H�xvR�\u000e��ar��\u0017+,sC\u0006�eBݘv\u0006���m)��(s\u0015UETs�����X �J�ש|w�`����]3U��a�\u000b�\u0014m\u001e�!|\u001d�n\u000eq���},\u0019u�aX,\u001c�K\rQA\u0015\u0006O\u0019�3\u001eeii�x�ծ:�$.8�\u0006\u0014R�̶\u0013\u0012ƨ,j)<Q�\f�\u0013\u001b��z��]�`4�&%V���t�\rL��x�m��;�\u0019/lx��\n���\u000f`\"%\u0015\u0013IQDE�ծ\b�X�v��C�d����g�w��9\u0011�L\u0012o�\u001b�״v�wisޗ��}j��f/wj>2\f�\"S\rD�\u0002\"�]�1p��>I�M�\u0011.1�#��z(\\��BZ{�\u0016\u0010���z��5N��B�rH�������m\u0005�7Ry��P��~�g\u000fRrp1���9V~\r+G��ꙸ�jw��J����@N�\b�(�a�;��J2�8\u000e�+u^\u0016:��O�\u0016u\"r\u0013�\b�$\u0011�\t�r&�H�\u0000zC�\u0000W6�Ip(`=Y%\u0002��(DH%u\"��|\u0013\u0007���Ig\u0012\u001c\u0014�G*\t���H� \u0002�\bț\u001b\u0014\u0017\u0012�\u001c˂\u0006��`\u0016�ל-x,�^\u0004(�x�v�i�JȀ�P\u0001(aVn ���e�\u0000�$ح�ˬ\b|\u000f�s\u001f�C�i\u0018�H|)R���@��.3�F��Ї@�\u0001\u0004�\u001ar�~�d�0���\u0005�[�\u0011}u;�m��\u0004���^A�\u0003�϶��0HS�����\u0011���\u0012�X�\u0015\u0004�\u0007\u000b�[.a�Ne�$g��{��\u0010��\\�\u0004���T�>���Uˬ\r�B��!\u0010���%6�99\u001el�V/� 2����hW+�F�v�/N�Xf=�:/��-\u001bkۮ<�4��m��:\u0006\u001e�J\u0018\u0014����#J�Mk\u001f)3��[����\u0019D=��:���a��r5�X=Qe�\u001aF=��(<�u��\u000f�x�>H���R\u0006PO͘�]rG溯aw�r�C�#\u0016��Aݑi�P@L8Le�\u0003`�md\u0013K��^b�q&%ڑ\u001d\u0005W/SZH�`#;�EpP��*MA�\\�;��\f�W�@<\u001b�\u0007R��$��\u001c�\u001e\u0012�\u001d�]�Ȼ����BL�\u0000V�f��M.ų��n�'��S:�'\u001f��\u0006�$�\u001b\t՟U���<���\u001f��F�W��vHwJ\u001e��ƣ��yJ\u001e��n j/�F+����\u0019=���yN�?����\u001f���G\u0010G}�\u0005��\u001d$\u001eX��\u0000�\u001c1�9�xG����Vru+��ty���[5[��c5@:&���.\b�\u000e^ lwe�/lU��tekl�\u0017�\u0006l�l]����+Ƶ��\u0015_ت�&��l�xakQ?�V�\u0015d���(B�ڎb�Ŗ�\t����F�_�;\f\u001a\u0006�zR�yה�9\u0010G�+n�hob\u0010G�)���B�W\u000b�H\u001f&p\f=�F\u001eaɵ$��/�+����x�-�\u0001�ó���\u0005\u0012aI]v��/ �b��R������RB�̽L�����Ap����\bC�\u0011\u0015\u00170�q��\u0001q��\u000e\u000f\u0015�\u0002��Q�\u0014�D��(n��\u0005�ݡ�}��\u0011\u0006���s��\u0003;�0:\tlWF}�\u00140\u0010\u000eÓkq6��\u0006�vQ�\u0018�\u001a�?�\u0014���,���f�A��\u0005�t\u001a����F7\u0010�m�\\4�\u0018\u0005���4+\u000fz��xԑ�\u0004\u000b���Y���\u001c,\u0004�mh�\u0013�@o�6��WQt�؆\u001e�\u0003l�\b���;0�.\u0002,ñ\\>\u0003ؙ|.�\u000b����\u0001�\u0003��\u0001V�\u001d��\u000f|9�\u000f_��� �\u0006ςO/l�\u000f���\n$X�e�T\u000ez�\b�|�\u000b�\u0010�\u0004��Y�\u000f6\u0002|�ɱ�`�$\u0003�\r��L�e9�\\����9x�� �y�'*ֆMO\u001a��@^`��|F��O�Kq��eu`�\u0001Pi�<�qY^�3)�a>X���O\u001a\u0016�\b\u0019�(�αL�M�B\u000e��e\u0000e:�aR���=Jg9\u0006�PHCWr�`:�gX\u0004\rȓO�y��=�Q�3<���g6�R)�\u0003P���C�GB�Ies��\u0010�\u0004@2�l\u0010���\u00035��,#�Y�Y�as\u001cP#'0,�f�\u0007�'�\u0011�#��\bN�gx�O�Gi.\rC�qL*������Q\u0002JA\u0003&����C\u0001\"qy&�\u0016����G��|\u0016�£\u0014��t^�\u0002���\u0011A\u0003�(�|�\u0007�� �I\u0003Wr�l:\b��|:���]�y�w\u0015��\u0002C��<9$\u0016}��v�#�\u001b�\u000fm\u001e\u0019\u0011��L.�A|���\u001cF 0|�x�fa}e�B\u0010z��\u000bY�A�I\u0001�`/�?�\u0000)��\u000e\u0004�ry\u0004DE�<��\u000eq����ph�A�T �w\u001d��H�\nD�iD�5R�Q�\fO�Q�g�,�\u0001�i���9\u0001~��E�e@��d\n�\"�\u0001��\u0014�;�A/��\u0000��s�MF`2�4<�\u0000\tr��\u0019��r��\u0005`3\u0010\"�#�>\u0017)\u0018d�0;�\u0013}\n���<\u0002Fe�{`\u0014\u0019x��E��\u0011v`[>ϡ%�e`��@ppB&�=�1�\u0000S6����`0i�:R,��pY�\u0001\b�\fB\u0007cP\u001f\u0011=6�\u0019�\u0018\b)�@��\u0014@ey>�=J\t)&���+\u0005��da��K{D��a$yxk󈠐�C�G��J�l�0ߚ�B���2��J�2L:\u0007l��.�.�R�6�qiMv�\u0007����������%�f����\u001e\u0001\u001f�,\u0012$<��bI��&\u000bP\f\u0002��Ұ4�,�C�\u0011ъŋN�{�Aӓ��\u001f�\u0002`�\f�\bh�f��\u00003��1x`�|:�&[e� ���#\u0002�y؈_��\u0005�\u0003)��\u0005�\u000e�<L\b�\u001a���$�_�K�\\+�\u0005R\u0004t�\u0016`w�\"�����\u0007!�EP�����\u0017@p�r�\u001f��@����\u0005X\u001f�\u0000�A�g�`\u0010�\u0019�q�\u0007�����9�\u0011�^N�M\f�\u0001Z\u0013 ���f�\\\nd%�\u001f6�\b\u0007py�i\u0016�2�\"�ʀ&\u0001��C�\u001f$+lN�\f���.\t��H�R��!��\rTm\u0001�0��\u0000>>��\u0005\u000f`�\u0004�@;L� ��a���z�\u0001:�,i`�\u001c\u0010�'��aJ�*��\u0002�6\u00015�A\"P��<⍔�=@�\u0001�r9^{��\u000e,��p<��\u0007B\u001a\u0016���dE���Ve\u0011\u0001�\u0007+W*��菀Ks|\n�\u0002\u0012�) n\nq�\u0000�J�a��\u0013|�V� \u0018�F\u0010�0��Z\u001b�B*�CB]\u001e��\u001d���y<\u000f�\u0013\u0000\u000e�\u0010�PAhL��љ\u0006u%\u000f���&\r҂�\u0000�0@U4\u000eu@*?��1�F\u0000���g�v��\u0015h��6��\u000b`�\u001cHALȴ,=`\rp�\f�\u0019l\u0005Y\u0001�/��\u0011_\u0003i��r�\u0003D�,(=�\u0013\u0001�m\u001e�\r�泠\u0001i\u000f\b���\u0004�<��Q�����G�s��hm�ު{��\u0007 �aM�dS\u0007id&\u001e\u0016V&�� �Av�s\u0019]v�s������\u001e�C{āB�!�U��S�\"\"�\u0000q~.�?\u0002S�\u0011\u0004\u0010\u0002*\u0010�\u0001!��G� S�h�5���̶�\\�%4�,��A��G<,q�3t\u001a�N:��\u001f\u0010#U\u001f�\u001e��\u0007\r�:+*\"b�@\n`�M\u001c�W\u001ak�\n\u0010�\u00019R��\u0019\r��]ӈz���\u0006��H4x\u0017h\u0014e{\u0019�gl�&\u0012`J7;\u001f��\u0019\f�z��v�\u0012���h<���\t�\t~H�t6����s�7z\u0002?Q��\u001d~Q\r�_�\u0007\u000f�\rendstream\rendobj\r6 0 obj\r[5 0 R]\rendobj\r20 0 obj\r<</CreationDate(D:20110328132859+11'00')/Creator(Adobe Illustrator CS5)/ModDate(D:20110328132859+11'00')/Producer(Adobe PDF library 9.90)/Title(Modernizr 2 Logo)>>\rendobj\rxref\r0 21\r0000000000 65535 f\r\n0000000016 00000 n\r\n0000000144 00000 n\r\n0000018316 00000 n\r\n0000000000 00000 f\r\n0000020771 00000 n\r\n0000048490 00000 n\r\n0000018367 00000 n\r\n0000018703 00000 n\r\n0000021070 00000 n\r\n0000020957 00000 n\r\n0000019852 00000 n\r\n0000020210 00000 n\r\n0000020258 00000 n\r\n0000020841 00000 n\r\n0000020872 00000 n\r\n0000021143 00000 n\r\n0000021317 00000 n\r\n0000022336 00000 n\r\n0000027404 00000 n\r\n0000048513 00000 n\r\ntrailer\r<</Size 21/Root 1 0 R/Info 20 0 R/ID[<8D44613111B047A982BB568568FC0997><DE399FA33D7D4432BF16917DBD7AD64E>]>>\rstartxref\r48693\r%%EOF\r"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/modernizr/modernizr.js",
    "content": "/*!\n * Modernizr v2.7.0\n * www.modernizr.com\n *\n * Copyright (c) Faruk Ates, Paul Irish, Alex Sexton\n * Available under the BSD and MIT licenses: www.modernizr.com/license/\n */\n\n/*\n * Modernizr tests which native CSS3 and HTML5 features are available in\n * the current UA and makes the results available to you in two ways:\n * as properties on a global Modernizr object, and as classes on the\n * <html> element. This information allows you to progressively enhance\n * your pages with a granular level of control over the experience.\n *\n * Modernizr has an optional (not included) conditional resource loader\n * called Modernizr.load(), based on Yepnope.js (yepnopejs.com).\n * To get a build that includes Modernizr.load(), as well as choosing\n * which tests to include, go to www.modernizr.com/download/\n *\n * Authors        Faruk Ates, Paul Irish, Alex Sexton\n * Contributors   Ryan Seddon, Ben Alman\n */\n\nwindow.Modernizr = (function( window, document, undefined ) {\n\n    var version = '2.7.0',\n\n    Modernizr = {},\n\n    /*>>cssclasses*/\n    // option for enabling the HTML classes to be added\n    enableClasses = true,\n    /*>>cssclasses*/\n\n    docElement = document.documentElement,\n\n    /**\n     * Create our \"modernizr\" element that we do most feature tests on.\n     */\n    mod = 'modernizr',\n    modElem = document.createElement(mod),\n    mStyle = modElem.style,\n\n    /**\n     * Create the input element for various Web Forms feature tests.\n     */\n    inputElem /*>>inputelem*/ = document.createElement('input') /*>>inputelem*/ ,\n\n    /*>>smile*/\n    smile = ':)',\n    /*>>smile*/\n\n    toString = {}.toString,\n\n    // TODO :: make the prefixes more granular\n    /*>>prefixes*/\n    // List of property values to set for css tests. See ticket #21\n    prefixes = ' -webkit- -moz- -o- -ms- '.split(' '),\n    /*>>prefixes*/\n\n    /*>>domprefixes*/\n    // Following spec is to expose vendor-specific style properties as:\n    //   elem.style.WebkitBorderRadius\n    // and the following would be incorrect:\n    //   elem.style.webkitBorderRadius\n\n    // Webkit ghosts their properties in lowercase but Opera & Moz do not.\n    // Microsoft uses a lowercase `ms` instead of the correct `Ms` in IE8+\n    //   erik.eae.net/archives/2008/03/10/21.48.10/\n\n    // More here: github.com/Modernizr/Modernizr/issues/issue/21\n    omPrefixes = 'Webkit Moz O ms',\n\n    cssomPrefixes = omPrefixes.split(' '),\n\n    domPrefixes = omPrefixes.toLowerCase().split(' '),\n    /*>>domprefixes*/\n\n    /*>>ns*/\n    ns = {'svg': 'http://www.w3.org/2000/svg'},\n    /*>>ns*/\n\n    tests = {},\n    inputs = {},\n    attrs = {},\n\n    classes = [],\n\n    slice = classes.slice,\n\n    featureName, // used in testing loop\n\n\n    /*>>teststyles*/\n    // Inject element with style element and some CSS rules\n    injectElementWithStyles = function( rule, callback, nodes, testnames ) {\n\n      var style, ret, node, docOverflow,\n          div = document.createElement('div'),\n          // After page load injecting a fake body doesn't work so check if body exists\n          body = document.body,\n          // IE6 and 7 won't return offsetWidth or offsetHeight unless it's in the body element, so we fake it.\n          fakeBody = body || document.createElement('body');\n\n      if ( parseInt(nodes, 10) ) {\n          // In order not to give false positives we create a node for each test\n          // This also allows the method to scale for unspecified uses\n          while ( nodes-- ) {\n              node = document.createElement('div');\n              node.id = testnames ? testnames[nodes] : mod + (nodes + 1);\n              div.appendChild(node);\n          }\n      }\n\n      // <style> elements in IE6-9 are considered 'NoScope' elements and therefore will be removed\n      // when injected with innerHTML. To get around this you need to prepend the 'NoScope' element\n      // with a 'scoped' element, in our case the soft-hyphen entity as it won't mess with our measurements.\n      // msdn.microsoft.com/en-us/library/ms533897%28VS.85%29.aspx\n      // Documents served as xml will throw if using &shy; so use xml friendly encoded version. See issue #277\n      style = ['&#173;','<style id=\"s', mod, '\">', rule, '</style>'].join('');\n      div.id = mod;\n      // IE6 will false positive on some tests due to the style element inside the test div somehow interfering offsetHeight, so insert it into body or fakebody.\n      // Opera will act all quirky when injecting elements in documentElement when page is served as xml, needs fakebody too. #270\n      (body ? div : fakeBody).innerHTML += style;\n      fakeBody.appendChild(div);\n      if ( !body ) {\n          //avoid crashing IE8, if background image is used\n          fakeBody.style.background = '';\n          //Safari 5.13/5.1.4 OSX stops loading if ::-webkit-scrollbar is used and scrollbars are visible\n          fakeBody.style.overflow = 'hidden';\n          docOverflow = docElement.style.overflow;\n          docElement.style.overflow = 'hidden';\n          docElement.appendChild(fakeBody);\n      }\n\n      ret = callback(div, rule);\n      // If this is done after page load we don't want to remove the body so check if body exists\n      if ( !body ) {\n          fakeBody.parentNode.removeChild(fakeBody);\n          docElement.style.overflow = docOverflow;\n      } else {\n          div.parentNode.removeChild(div);\n      }\n\n      return !!ret;\n\n    },\n    /*>>teststyles*/\n\n    /*>>mq*/\n    // adapted from matchMedia polyfill\n    // by Scott Jehl and Paul Irish\n    // gist.github.com/786768\n    testMediaQuery = function( mq ) {\n\n      var matchMedia = window.matchMedia || window.msMatchMedia;\n      if ( matchMedia ) {\n        return matchMedia(mq).matches;\n      }\n\n      var bool;\n\n      injectElementWithStyles('@media ' + mq + ' { #' + mod + ' { position: absolute; } }', function( node ) {\n        bool = (window.getComputedStyle ?\n                  getComputedStyle(node, null) :\n                  node.currentStyle)['position'] == 'absolute';\n      });\n\n      return bool;\n\n     },\n     /*>>mq*/\n\n\n    /*>>hasevent*/\n    //\n    // isEventSupported determines if a given element supports the given event\n    // kangax.github.com/iseventsupported/\n    //\n    // The following results are known incorrects:\n    //   Modernizr.hasEvent(\"webkitTransitionEnd\", elem) // false negative\n    //   Modernizr.hasEvent(\"textInput\") // in Webkit. github.com/Modernizr/Modernizr/issues/333\n    //   ...\n    isEventSupported = (function() {\n\n      var TAGNAMES = {\n        'select': 'input', 'change': 'input',\n        'submit': 'form', 'reset': 'form',\n        'error': 'img', 'load': 'img', 'abort': 'img'\n      };\n\n      function isEventSupported( eventName, element ) {\n\n        element = element || document.createElement(TAGNAMES[eventName] || 'div');\n        eventName = 'on' + eventName;\n\n        // When using `setAttribute`, IE skips \"unload\", WebKit skips \"unload\" and \"resize\", whereas `in` \"catches\" those\n        var isSupported = eventName in element;\n\n        if ( !isSupported ) {\n          // If it has no `setAttribute` (i.e. doesn't implement Node interface), try generic element\n          if ( !element.setAttribute ) {\n            element = document.createElement('div');\n          }\n          if ( element.setAttribute && element.removeAttribute ) {\n            element.setAttribute(eventName, '');\n            isSupported = is(element[eventName], 'function');\n\n            // If property was created, \"remove it\" (by setting value to `undefined`)\n            if ( !is(element[eventName], 'undefined') ) {\n              element[eventName] = undefined;\n            }\n            element.removeAttribute(eventName);\n          }\n        }\n\n        element = null;\n        return isSupported;\n      }\n      return isEventSupported;\n    })(),\n    /*>>hasevent*/\n\n    // TODO :: Add flag for hasownprop ? didn't last time\n\n    // hasOwnProperty shim by kangax needed for Safari 2.0 support\n    _hasOwnProperty = ({}).hasOwnProperty, hasOwnProp;\n\n    if ( !is(_hasOwnProperty, 'undefined') && !is(_hasOwnProperty.call, 'undefined') ) {\n      hasOwnProp = function (object, property) {\n        return _hasOwnProperty.call(object, property);\n      };\n    }\n    else {\n      hasOwnProp = function (object, property) { /* yes, this can give false positives/negatives, but most of the time we don't care about those */\n        return ((property in object) && is(object.constructor.prototype[property], 'undefined'));\n      };\n    }\n\n    // Adapted from ES5-shim https://github.com/kriskowal/es5-shim/blob/master/es5-shim.js\n    // es5.github.com/#x15.3.4.5\n\n    if (!Function.prototype.bind) {\n      Function.prototype.bind = function bind(that) {\n\n        var target = this;\n\n        if (typeof target != \"function\") {\n            throw new TypeError();\n        }\n\n        var args = slice.call(arguments, 1),\n            bound = function () {\n\n            if (this instanceof bound) {\n\n              var F = function(){};\n              F.prototype = target.prototype;\n              var self = new F();\n\n              var result = target.apply(\n                  self,\n                  args.concat(slice.call(arguments))\n              );\n              if (Object(result) === result) {\n                  return result;\n              }\n              return self;\n\n            } else {\n\n              return target.apply(\n                  that,\n                  args.concat(slice.call(arguments))\n              );\n\n            }\n\n        };\n\n        return bound;\n      };\n    }\n\n    /**\n     * setCss applies given styles to the Modernizr DOM node.\n     */\n    function setCss( str ) {\n        mStyle.cssText = str;\n    }\n\n    /**\n     * setCssAll extrapolates all vendor-specific css strings.\n     */\n    function setCssAll( str1, str2 ) {\n        return setCss(prefixes.join(str1 + ';') + ( str2 || '' ));\n    }\n\n    /**\n     * is returns a boolean for if typeof obj is exactly type.\n     */\n    function is( obj, type ) {\n        return typeof obj === type;\n    }\n\n    /**\n     * contains returns a boolean for if substr is found within str.\n     */\n    function contains( str, substr ) {\n        return !!~('' + str).indexOf(substr);\n    }\n\n    /*>>testprop*/\n\n    // testProps is a generic CSS / DOM property test.\n\n    // In testing support for a given CSS property, it's legit to test:\n    //    `elem.style[styleName] !== undefined`\n    // If the property is supported it will return an empty string,\n    // if unsupported it will return undefined.\n\n    // We'll take advantage of this quick test and skip setting a style\n    // on our modernizr element, but instead just testing undefined vs\n    // empty string.\n\n    // Because the testing of the CSS property names (with \"-\", as\n    // opposed to the camelCase DOM properties) is non-portable and\n    // non-standard but works in WebKit and IE (but not Gecko or Opera),\n    // we explicitly reject properties with dashes so that authors\n    // developing in WebKit or IE first don't end up with\n    // browser-specific content by accident.\n\n    function testProps( props, prefixed ) {\n        for ( var i in props ) {\n            var prop = props[i];\n            if ( !contains(prop, \"-\") && mStyle[prop] !== undefined ) {\n                return prefixed == 'pfx' ? prop : true;\n            }\n        }\n        return false;\n    }\n    /*>>testprop*/\n\n    // TODO :: add testDOMProps\n    /**\n     * testDOMProps is a generic DOM property test; if a browser supports\n     *   a certain property, it won't return undefined for it.\n     */\n    function testDOMProps( props, obj, elem ) {\n        for ( var i in props ) {\n            var item = obj[props[i]];\n            if ( item !== undefined) {\n\n                // return the property name as a string\n                if (elem === false) return props[i];\n\n                // let's bind a function\n                if (is(item, 'function')){\n                  // default to autobind unless override\n                  return item.bind(elem || obj);\n                }\n\n                // return the unbound function or obj or value\n                return item;\n            }\n        }\n        return false;\n    }\n\n    /*>>testallprops*/\n    /**\n     * testPropsAll tests a list of DOM properties we want to check against.\n     *   We specify literally ALL possible (known and/or likely) properties on\n     *   the element including the non-vendor prefixed one, for forward-\n     *   compatibility.\n     */\n    function testPropsAll( prop, prefixed, elem ) {\n\n        var ucProp  = prop.charAt(0).toUpperCase() + prop.slice(1),\n            props   = (prop + ' ' + cssomPrefixes.join(ucProp + ' ') + ucProp).split(' ');\n\n        // did they call .prefixed('boxSizing') or are we just testing a prop?\n        if(is(prefixed, \"string\") || is(prefixed, \"undefined\")) {\n          return testProps(props, prefixed);\n\n        // otherwise, they called .prefixed('requestAnimationFrame', window[, elem])\n        } else {\n          props = (prop + ' ' + (domPrefixes).join(ucProp + ' ') + ucProp).split(' ');\n          return testDOMProps(props, prefixed, elem);\n        }\n    }\n    /*>>testallprops*/\n\n\n    /**\n     * Tests\n     * -----\n     */\n\n    // The *new* flexbox\n    // dev.w3.org/csswg/css3-flexbox\n\n    tests['flexbox'] = function() {\n      return testPropsAll('flexWrap');\n    };\n\n    // The *old* flexbox\n    // www.w3.org/TR/2009/WD-css3-flexbox-20090723/\n\n    tests['flexboxlegacy'] = function() {\n        return testPropsAll('boxDirection');\n    };\n\n    // On the S60 and BB Storm, getContext exists, but always returns undefined\n    // so we actually have to call getContext() to verify\n    // github.com/Modernizr/Modernizr/issues/issue/97/\n\n    tests['canvas'] = function() {\n        var elem = document.createElement('canvas');\n        return !!(elem.getContext && elem.getContext('2d'));\n    };\n\n    tests['canvastext'] = function() {\n        return !!(Modernizr['canvas'] && is(document.createElement('canvas').getContext('2d').fillText, 'function'));\n    };\n\n    // webk.it/70117 is tracking a legit WebGL feature detect proposal\n\n    // We do a soft detect which may false positive in order to avoid\n    // an expensive context creation: bugzil.la/732441\n\n    tests['webgl'] = function() {\n        return !!window.WebGLRenderingContext;\n    };\n\n    /*\n     * The Modernizr.touch test only indicates if the browser supports\n     *    touch events, which does not necessarily reflect a touchscreen\n     *    device, as evidenced by tablets running Windows 7 or, alas,\n     *    the Palm Pre / WebOS (touch) phones.\n     *\n     * Additionally, Chrome (desktop) used to lie about its support on this,\n     *    but that has since been rectified: crbug.com/36415\n     *\n     * We also test for Firefox 4 Multitouch Support.\n     *\n     * For more info, see: modernizr.github.com/Modernizr/touch.html\n     */\n\n    tests['touch'] = function() {\n        var bool;\n\n        if(('ontouchstart' in window) || window.DocumentTouch && document instanceof DocumentTouch) {\n          bool = true;\n        } else {\n          injectElementWithStyles(['@media (',prefixes.join('touch-enabled),('),mod,')','{#modernizr{top:9px;position:absolute}}'].join(''), function( node ) {\n            bool = node.offsetTop === 9;\n          });\n        }\n\n        return bool;\n    };\n\n\n    // geolocation is often considered a trivial feature detect...\n    // Turns out, it's quite tricky to get right:\n    //\n    // Using !!navigator.geolocation does two things we don't want. It:\n    //   1. Leaks memory in IE9: github.com/Modernizr/Modernizr/issues/513\n    //   2. Disables page caching in WebKit: webk.it/43956\n    //\n    // Meanwhile, in Firefox < 8, an about:config setting could expose\n    // a false positive that would throw an exception: bugzil.la/688158\n\n    tests['geolocation'] = function() {\n        return 'geolocation' in navigator;\n    };\n\n\n    tests['postmessage'] = function() {\n      return !!window.postMessage;\n    };\n\n\n    // Chrome incognito mode used to throw an exception when using openDatabase\n    // It doesn't anymore.\n    tests['websqldatabase'] = function() {\n      return !!window.openDatabase;\n    };\n\n    // Vendors had inconsistent prefixing with the experimental Indexed DB:\n    // - Webkit's implementation is accessible through webkitIndexedDB\n    // - Firefox shipped moz_indexedDB before FF4b9, but since then has been mozIndexedDB\n    // For speed, we don't test the legacy (and beta-only) indexedDB\n    tests['indexedDB'] = function() {\n      return !!testPropsAll(\"indexedDB\", window);\n    };\n\n    // documentMode logic from YUI to filter out IE8 Compat Mode\n    //   which false positives.\n    tests['hashchange'] = function() {\n      return isEventSupported('hashchange', window) && (document.documentMode === undefined || document.documentMode > 7);\n    };\n\n    // Per 1.6:\n    // This used to be Modernizr.historymanagement but the longer\n    // name has been deprecated in favor of a shorter and property-matching one.\n    // The old API is still available in 1.6, but as of 2.0 will throw a warning,\n    // and in the first release thereafter disappear entirely.\n    tests['history'] = function() {\n      return !!(window.history && history.pushState);\n    };\n\n    tests['draganddrop'] = function() {\n        var div = document.createElement('div');\n        return ('draggable' in div) || ('ondragstart' in div && 'ondrop' in div);\n    };\n\n    // FF3.6 was EOL'ed on 4/24/12, but the ESR version of FF10\n    // will be supported until FF19 (2/12/13), at which time, ESR becomes FF17.\n    // FF10 still uses prefixes, so check for it until then.\n    // for more ESR info, see: mozilla.org/en-US/firefox/organizations/faq/\n    tests['websockets'] = function() {\n        return 'WebSocket' in window || 'MozWebSocket' in window;\n    };\n\n\n    // css-tricks.com/rgba-browser-support/\n    tests['rgba'] = function() {\n        // Set an rgba() color and check the returned value\n\n        setCss('background-color:rgba(150,255,150,.5)');\n\n        return contains(mStyle.backgroundColor, 'rgba');\n    };\n\n    tests['hsla'] = function() {\n        // Same as rgba(), in fact, browsers re-map hsla() to rgba() internally,\n        //   except IE9 who retains it as hsla\n\n        setCss('background-color:hsla(120,40%,100%,.5)');\n\n        return contains(mStyle.backgroundColor, 'rgba') || contains(mStyle.backgroundColor, 'hsla');\n    };\n\n    tests['multiplebgs'] = function() {\n        // Setting multiple images AND a color on the background shorthand property\n        //  and then querying the style.background property value for the number of\n        //  occurrences of \"url(\" is a reliable method for detecting ACTUAL support for this!\n\n        setCss('background:url(https://),url(https://),red url(https://)');\n\n        // If the UA supports multiple backgrounds, there should be three occurrences\n        //   of the string \"url(\" in the return value for elemStyle.background\n\n        return (/(url\\s*\\(.*?){3}/).test(mStyle.background);\n    };\n\n\n\n    // this will false positive in Opera Mini\n    //   github.com/Modernizr/Modernizr/issues/396\n\n    tests['backgroundsize'] = function() {\n        return testPropsAll('backgroundSize');\n    };\n\n    tests['borderimage'] = function() {\n        return testPropsAll('borderImage');\n    };\n\n\n    // Super comprehensive table about all the unique implementations of\n    // border-radius: muddledramblings.com/table-of-css3-border-radius-compliance\n\n    tests['borderradius'] = function() {\n        return testPropsAll('borderRadius');\n    };\n\n    // WebOS unfortunately false positives on this test.\n    tests['boxshadow'] = function() {\n        return testPropsAll('boxShadow');\n    };\n\n    // FF3.0 will false positive on this test\n    tests['textshadow'] = function() {\n        return document.createElement('div').style.textShadow === '';\n    };\n\n\n    tests['opacity'] = function() {\n        // Browsers that actually have CSS Opacity implemented have done so\n        //  according to spec, which means their return values are within the\n        //  range of [0.0,1.0] - including the leading zero.\n\n        setCssAll('opacity:.55');\n\n        // The non-literal . in this regex is intentional:\n        //   German Chrome returns this value as 0,55\n        // github.com/Modernizr/Modernizr/issues/#issue/59/comment/516632\n        return (/^0.55$/).test(mStyle.opacity);\n    };\n\n\n    // Note, Android < 4 will pass this test, but can only animate\n    //   a single property at a time\n    //   daneden.me/2011/12/putting-up-with-androids-bullshit/\n    tests['cssanimations'] = function() {\n        return testPropsAll('animationName');\n    };\n\n\n    tests['csscolumns'] = function() {\n        return testPropsAll('columnCount');\n    };\n\n\n    tests['cssgradients'] = function() {\n        /**\n         * For CSS Gradients syntax, please see:\n         * webkit.org/blog/175/introducing-css-gradients/\n         * developer.mozilla.org/en/CSS/-moz-linear-gradient\n         * developer.mozilla.org/en/CSS/-moz-radial-gradient\n         * dev.w3.org/csswg/css3-images/#gradients-\n         */\n\n        var str1 = 'background-image:',\n            str2 = 'gradient(linear,left top,right bottom,from(#9f9),to(white));',\n            str3 = 'linear-gradient(left top,#9f9, white);';\n\n        setCss(\n             // legacy webkit syntax (FIXME: remove when syntax not in use anymore)\n              (str1 + '-webkit- '.split(' ').join(str2 + str1) +\n             // standard syntax             // trailing 'background-image:'\n              prefixes.join(str3 + str1)).slice(0, -str1.length)\n        );\n\n        return contains(mStyle.backgroundImage, 'gradient');\n    };\n\n\n    tests['cssreflections'] = function() {\n        return testPropsAll('boxReflect');\n    };\n\n\n    tests['csstransforms'] = function() {\n        return !!testPropsAll('transform');\n    };\n\n\n    tests['csstransforms3d'] = function() {\n\n        var ret = !!testPropsAll('perspective');\n\n        // Webkit's 3D transforms are passed off to the browser's own graphics renderer.\n        //   It works fine in Safari on Leopard and Snow Leopard, but not in Chrome in\n        //   some conditions. As a result, Webkit typically recognizes the syntax but\n        //   will sometimes throw a false positive, thus we must do a more thorough check:\n        if ( ret && 'webkitPerspective' in docElement.style ) {\n\n          // Webkit allows this media query to succeed only if the feature is enabled.\n          // `@media (transform-3d),(-webkit-transform-3d){ ... }`\n          injectElementWithStyles('@media (transform-3d),(-webkit-transform-3d){#modernizr{left:9px;position:absolute;height:3px;}}', function( node, rule ) {\n            ret = node.offsetLeft === 9 && node.offsetHeight === 3;\n          });\n        }\n        return ret;\n    };\n\n\n    tests['csstransitions'] = function() {\n        return testPropsAll('transition');\n    };\n\n\n    /*>>fontface*/\n    // @font-face detection routine by Diego Perini\n    // javascript.nwbox.com/CSSSupport/\n\n    // false positives:\n    //   WebOS github.com/Modernizr/Modernizr/issues/342\n    //   WP7   github.com/Modernizr/Modernizr/issues/538\n    tests['fontface'] = function() {\n        var bool;\n\n        injectElementWithStyles('@font-face {font-family:\"font\";src:url(\"https://\")}', function( node, rule ) {\n          var style = document.getElementById('smodernizr'),\n              sheet = style.sheet || style.styleSheet,\n              cssText = sheet ? (sheet.cssRules && sheet.cssRules[0] ? sheet.cssRules[0].cssText : sheet.cssText || '') : '';\n\n          bool = /src/i.test(cssText) && cssText.indexOf(rule.split(' ')[0]) === 0;\n        });\n\n        return bool;\n    };\n    /*>>fontface*/\n\n    // CSS generated content detection\n    tests['generatedcontent'] = function() {\n        var bool;\n\n        injectElementWithStyles(['#',mod,'{font:0/0 a}#',mod,':after{content:\"',smile,'\";visibility:hidden;font:3px/1 a}'].join(''), function( node ) {\n          bool = node.offsetHeight >= 3;\n        });\n\n        return bool;\n    };\n\n\n\n    // These tests evaluate support of the video/audio elements, as well as\n    // testing what types of content they support.\n    //\n    // We're using the Boolean constructor here, so that we can extend the value\n    // e.g.  Modernizr.video     // true\n    //       Modernizr.video.ogg // 'probably'\n    //\n    // Codec values from : github.com/NielsLeenheer/html5test/blob/9106a8/index.html#L845\n    //                     thx to NielsLeenheer and zcorpan\n\n    // Note: in some older browsers, \"no\" was a return value instead of empty string.\n    //   It was live in FF3.5.0 and 3.5.1, but fixed in 3.5.2\n    //   It was also live in Safari 4.0.0 - 4.0.4, but fixed in 4.0.5\n\n    tests['video'] = function() {\n        var elem = document.createElement('video'),\n            bool = false;\n\n        // IE9 Running on Windows Server SKU can cause an exception to be thrown, bug #224\n        try {\n            if ( bool = !!elem.canPlayType ) {\n                bool      = new Boolean(bool);\n                bool.ogg  = elem.canPlayType('video/ogg; codecs=\"theora\"')      .replace(/^no$/,'');\n\n                // Without QuickTime, this value will be `undefined`. github.com/Modernizr/Modernizr/issues/546\n                bool.h264 = elem.canPlayType('video/mp4; codecs=\"avc1.42E01E\"') .replace(/^no$/,'');\n\n                bool.webm = elem.canPlayType('video/webm; codecs=\"vp8, vorbis\"').replace(/^no$/,'');\n            }\n\n        } catch(e) { }\n\n        return bool;\n    };\n\n    tests['audio'] = function() {\n        var elem = document.createElement('audio'),\n            bool = false;\n\n        try {\n            if ( bool = !!elem.canPlayType ) {\n                bool      = new Boolean(bool);\n                bool.ogg  = elem.canPlayType('audio/ogg; codecs=\"vorbis\"').replace(/^no$/,'');\n                bool.mp3  = elem.canPlayType('audio/mpeg;')               .replace(/^no$/,'');\n\n                // Mimetypes accepted:\n                //   developer.mozilla.org/En/Media_formats_supported_by_the_audio_and_video_elements\n                //   bit.ly/iphoneoscodecs\n                bool.wav  = elem.canPlayType('audio/wav; codecs=\"1\"')     .replace(/^no$/,'');\n                bool.m4a  = ( elem.canPlayType('audio/x-m4a;')            ||\n                              elem.canPlayType('audio/aac;'))             .replace(/^no$/,'');\n            }\n        } catch(e) { }\n\n        return bool;\n    };\n\n\n    // In FF4, if disabled, window.localStorage should === null.\n\n    // Normally, we could not test that directly and need to do a\n    //   `('localStorage' in window) && ` test first because otherwise Firefox will\n    //   throw bugzil.la/365772 if cookies are disabled\n\n    // Also in iOS5 Private Browsing mode, attempting to use localStorage.setItem\n    // will throw the exception:\n    //   QUOTA_EXCEEDED_ERRROR DOM Exception 22.\n    // Peculiarly, getItem and removeItem calls do not throw.\n\n    // Because we are forced to try/catch this, we'll go aggressive.\n\n    // Just FWIW: IE8 Compat mode supports these features completely:\n    //   www.quirksmode.org/dom/html5.html\n    // But IE8 doesn't support either with local files\n\n    tests['localstorage'] = function() {\n        try {\n            localStorage.setItem(mod, mod);\n            localStorage.removeItem(mod);\n            return true;\n        } catch(e) {\n            return false;\n        }\n    };\n\n    tests['sessionstorage'] = function() {\n        try {\n            sessionStorage.setItem(mod, mod);\n            sessionStorage.removeItem(mod);\n            return true;\n        } catch(e) {\n            return false;\n        }\n    };\n\n\n    tests['webworkers'] = function() {\n        return !!window.Worker;\n    };\n\n\n    tests['applicationcache'] = function() {\n        return !!window.applicationCache;\n    };\n\n\n    // Thanks to Erik Dahlstrom\n    tests['svg'] = function() {\n        return !!document.createElementNS && !!document.createElementNS(ns.svg, 'svg').createSVGRect;\n    };\n\n    // specifically for SVG inline in HTML, not within XHTML\n    // test page: paulirish.com/demo/inline-svg\n    tests['inlinesvg'] = function() {\n      var div = document.createElement('div');\n      div.innerHTML = '<svg/>';\n      return (div.firstChild && div.firstChild.namespaceURI) == ns.svg;\n    };\n\n    // SVG SMIL animation\n    tests['smil'] = function() {\n        return !!document.createElementNS && /SVGAnimate/.test(toString.call(document.createElementNS(ns.svg, 'animate')));\n    };\n\n    // This test is only for clip paths in SVG proper, not clip paths on HTML content\n    // demo: srufaculty.sru.edu/david.dailey/svg/newstuff/clipPath4.svg\n\n    // However read the comments to dig into applying SVG clippaths to HTML content here:\n    //   github.com/Modernizr/Modernizr/issues/213#issuecomment-1149491\n    tests['svgclippaths'] = function() {\n        return !!document.createElementNS && /SVGClipPath/.test(toString.call(document.createElementNS(ns.svg, 'clipPath')));\n    };\n\n    /*>>webforms*/\n    // input features and input types go directly onto the ret object, bypassing the tests loop.\n    // Hold this guy to execute in a moment.\n    function webforms() {\n        /*>>input*/\n        // Run through HTML5's new input attributes to see if the UA understands any.\n        // We're using f which is the <input> element created early on\n        // Mike Taylr has created a comprehensive resource for testing these attributes\n        //   when applied to all input types:\n        //   miketaylr.com/code/input-type-attr.html\n        // spec: www.whatwg.org/specs/web-apps/current-work/multipage/the-input-element.html#input-type-attr-summary\n\n        // Only input placeholder is tested while textarea's placeholder is not.\n        // Currently Safari 4 and Opera 11 have support only for the input placeholder\n        // Both tests are available in feature-detects/forms-placeholder.js\n        Modernizr['input'] = (function( props ) {\n            for ( var i = 0, len = props.length; i < len; i++ ) {\n                attrs[ props[i] ] = !!(props[i] in inputElem);\n            }\n            if (attrs.list){\n              // safari false positive's on datalist: webk.it/74252\n              // see also github.com/Modernizr/Modernizr/issues/146\n              attrs.list = !!(document.createElement('datalist') && window.HTMLDataListElement);\n            }\n            return attrs;\n        })('autocomplete autofocus list placeholder max min multiple pattern required step'.split(' '));\n        /*>>input*/\n\n        /*>>inputtypes*/\n        // Run through HTML5's new input types to see if the UA understands any.\n        //   This is put behind the tests runloop because it doesn't return a\n        //   true/false like all the other tests; instead, it returns an object\n        //   containing each input type with its corresponding true/false value\n\n        // Big thanks to @miketaylr for the html5 forms expertise. miketaylr.com/\n        Modernizr['inputtypes'] = (function(props) {\n\n            for ( var i = 0, bool, inputElemType, defaultView, len = props.length; i < len; i++ ) {\n\n                inputElem.setAttribute('type', inputElemType = props[i]);\n                bool = inputElem.type !== 'text';\n\n                // We first check to see if the type we give it sticks..\n                // If the type does, we feed it a textual value, which shouldn't be valid.\n                // If the value doesn't stick, we know there's input sanitization which infers a custom UI\n                if ( bool ) {\n\n                    inputElem.value         = smile;\n                    inputElem.style.cssText = 'position:absolute;visibility:hidden;';\n\n                    if ( /^range$/.test(inputElemType) && inputElem.style.WebkitAppearance !== undefined ) {\n\n                      docElement.appendChild(inputElem);\n                      defaultView = document.defaultView;\n\n                      // Safari 2-4 allows the smiley as a value, despite making a slider\n                      bool =  defaultView.getComputedStyle &&\n                              defaultView.getComputedStyle(inputElem, null).WebkitAppearance !== 'textfield' &&\n                              // Mobile android web browser has false positive, so must\n                              // check the height to see if the widget is actually there.\n                              (inputElem.offsetHeight !== 0);\n\n                      docElement.removeChild(inputElem);\n\n                    } else if ( /^(search|tel)$/.test(inputElemType) ){\n                      // Spec doesn't define any special parsing or detectable UI\n                      //   behaviors so we pass these through as true\n\n                      // Interestingly, opera fails the earlier test, so it doesn't\n                      //  even make it here.\n\n                    } else if ( /^(url|email)$/.test(inputElemType) ) {\n                      // Real url and email support comes with prebaked validation.\n                      bool = inputElem.checkValidity && inputElem.checkValidity() === false;\n\n                    } else {\n                      // If the upgraded input compontent rejects the :) text, we got a winner\n                      bool = inputElem.value != smile;\n                    }\n                }\n\n                inputs[ props[i] ] = !!bool;\n            }\n            return inputs;\n        })('search tel url email datetime date month week time datetime-local number range color'.split(' '));\n        /*>>inputtypes*/\n    }\n    /*>>webforms*/\n\n\n    // End of test definitions\n    // -----------------------\n\n\n\n    // Run through all tests and detect their support in the current UA.\n    // todo: hypothetically we could be doing an array of tests and use a basic loop here.\n    for ( var feature in tests ) {\n        if ( hasOwnProp(tests, feature) ) {\n            // run the test, throw the return value into the Modernizr,\n            //   then based on that boolean, define an appropriate className\n            //   and push it into an array of classes we'll join later.\n            featureName  = feature.toLowerCase();\n            Modernizr[featureName] = tests[feature]();\n\n            classes.push((Modernizr[featureName] ? '' : 'no-') + featureName);\n        }\n    }\n\n    /*>>webforms*/\n    // input tests need to run.\n    Modernizr.input || webforms();\n    /*>>webforms*/\n\n\n    /**\n     * addTest allows the user to define their own feature tests\n     * the result will be added onto the Modernizr object,\n     * as well as an appropriate className set on the html element\n     *\n     * @param feature - String naming the feature\n     * @param test - Function returning true if feature is supported, false if not\n     */\n     Modernizr.addTest = function ( feature, test ) {\n       if ( typeof feature == 'object' ) {\n         for ( var key in feature ) {\n           if ( hasOwnProp( feature, key ) ) {\n             Modernizr.addTest( key, feature[ key ] );\n           }\n         }\n       } else {\n\n         feature = feature.toLowerCase();\n\n         if ( Modernizr[feature] !== undefined ) {\n           // we're going to quit if you're trying to overwrite an existing test\n           // if we were to allow it, we'd do this:\n           //   var re = new RegExp(\"\\\\b(no-)?\" + feature + \"\\\\b\");\n           //   docElement.className = docElement.className.replace( re, '' );\n           // but, no rly, stuff 'em.\n           return Modernizr;\n         }\n\n         test = typeof test == 'function' ? test() : test;\n\n         if (typeof enableClasses !== \"undefined\" && enableClasses) {\n           docElement.className += ' ' + (test ? '' : 'no-') + feature;\n         }\n         Modernizr[feature] = test;\n\n       }\n\n       return Modernizr; // allow chaining.\n     };\n\n\n    // Reset modElem.cssText to nothing to reduce memory footprint.\n    setCss('');\n    modElem = inputElem = null;\n\n    /*>>shiv*/\n    /**\n     * @preserve HTML5 Shiv prev3.7.1 | @afarkas @jdalton @jon_neal @rem | MIT/GPL2 Licensed\n     */\n    ;(function(window, document) {\n        /*jshint evil:true */\n        /** version */\n        var version = '3.7.0';\n\n        /** Preset options */\n        var options = window.html5 || {};\n\n        /** Used to skip problem elements */\n        var reSkip = /^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i;\n\n        /** Not all elements can be cloned in IE **/\n        var saveClones = /^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i;\n\n        /** Detect whether the browser supports default html5 styles */\n        var supportsHtml5Styles;\n\n        /** Name of the expando, to work with multiple documents or to re-shiv one document */\n        var expando = '_html5shiv';\n\n        /** The id for the the documents expando */\n        var expanID = 0;\n\n        /** Cached data for each document */\n        var expandoData = {};\n\n        /** Detect whether the browser supports unknown elements */\n        var supportsUnknownElements;\n\n        (function() {\n          try {\n            var a = document.createElement('a');\n            a.innerHTML = '<xyz></xyz>';\n            //if the hidden property is implemented we can assume, that the browser supports basic HTML5 Styles\n            supportsHtml5Styles = ('hidden' in a);\n\n            supportsUnknownElements = a.childNodes.length == 1 || (function() {\n              // assign a false positive if unable to shiv\n              (document.createElement)('a');\n              var frag = document.createDocumentFragment();\n              return (\n                typeof frag.cloneNode == 'undefined' ||\n                typeof frag.createDocumentFragment == 'undefined' ||\n                typeof frag.createElement == 'undefined'\n              );\n            }());\n          } catch(e) {\n            // assign a false positive if detection fails => unable to shiv\n            supportsHtml5Styles = true;\n            supportsUnknownElements = true;\n          }\n\n        }());\n\n        /*--------------------------------------------------------------------------*/\n\n        /**\n         * Creates a style sheet with the given CSS text and adds it to the document.\n         * @private\n         * @param {Document} ownerDocument The document.\n         * @param {String} cssText The CSS text.\n         * @returns {StyleSheet} The style element.\n         */\n        function addStyleSheet(ownerDocument, cssText) {\n          var p = ownerDocument.createElement('p'),\n          parent = ownerDocument.getElementsByTagName('head')[0] || ownerDocument.documentElement;\n\n          p.innerHTML = 'x<style>' + cssText + '</style>';\n          return parent.insertBefore(p.lastChild, parent.firstChild);\n        }\n\n        /**\n         * Returns the value of `html5.elements` as an array.\n         * @private\n         * @returns {Array} An array of shived element node names.\n         */\n        function getElements() {\n          var elements = html5.elements;\n          return typeof elements == 'string' ? elements.split(' ') : elements;\n        }\n\n        /**\n         * Returns the data associated to the given document\n         * @private\n         * @param {Document} ownerDocument The document.\n         * @returns {Object} An object of data.\n         */\n        function getExpandoData(ownerDocument) {\n          var data = expandoData[ownerDocument[expando]];\n          if (!data) {\n            data = {};\n            expanID++;\n            ownerDocument[expando] = expanID;\n            expandoData[expanID] = data;\n          }\n          return data;\n        }\n\n        /**\n         * returns a shived element for the given nodeName and document\n         * @memberOf html5\n         * @param {String} nodeName name of the element\n         * @param {Document} ownerDocument The context document.\n         * @returns {Object} The shived element.\n         */\n        function createElement(nodeName, ownerDocument, data){\n          if (!ownerDocument) {\n            ownerDocument = document;\n          }\n          if(supportsUnknownElements){\n            return ownerDocument.createElement(nodeName);\n          }\n          if (!data) {\n            data = getExpandoData(ownerDocument);\n          }\n          var node;\n\n          if (data.cache[nodeName]) {\n            node = data.cache[nodeName].cloneNode();\n          } else if (saveClones.test(nodeName)) {\n            node = (data.cache[nodeName] = data.createElem(nodeName)).cloneNode();\n          } else {\n            node = data.createElem(nodeName);\n          }\n\n          // Avoid adding some elements to fragments in IE < 9 because\n          // * Attributes like `name` or `type` cannot be set/changed once an element\n          //   is inserted into a document/fragment\n          // * Link elements with `src` attributes that are inaccessible, as with\n          //   a 403 response, will cause the tab/window to crash\n          // * Script elements appended to fragments will execute when their `src`\n          //   or `text` property is set\n          return node.canHaveChildren && !reSkip.test(nodeName) && !node.tagUrn ? data.frag.appendChild(node) : node;\n        }\n\n        /**\n         * returns a shived DocumentFragment for the given document\n         * @memberOf html5\n         * @param {Document} ownerDocument The context document.\n         * @returns {Object} The shived DocumentFragment.\n         */\n        function createDocumentFragment(ownerDocument, data){\n          if (!ownerDocument) {\n            ownerDocument = document;\n          }\n          if(supportsUnknownElements){\n            return ownerDocument.createDocumentFragment();\n          }\n          data = data || getExpandoData(ownerDocument);\n          var clone = data.frag.cloneNode(),\n          i = 0,\n          elems = getElements(),\n          l = elems.length;\n          for(;i<l;i++){\n            clone.createElement(elems[i]);\n          }\n          return clone;\n        }\n\n        /**\n         * Shivs the `createElement` and `createDocumentFragment` methods of the document.\n         * @private\n         * @param {Document|DocumentFragment} ownerDocument The document.\n         * @param {Object} data of the document.\n         */\n        function shivMethods(ownerDocument, data) {\n          if (!data.cache) {\n            data.cache = {};\n            data.createElem = ownerDocument.createElement;\n            data.createFrag = ownerDocument.createDocumentFragment;\n            data.frag = data.createFrag();\n          }\n\n\n          ownerDocument.createElement = function(nodeName) {\n            //abort shiv\n            if (!html5.shivMethods) {\n              return data.createElem(nodeName);\n            }\n            return createElement(nodeName, ownerDocument, data);\n          };\n\n          ownerDocument.createDocumentFragment = Function('h,f', 'return function(){' +\n                                                          'var n=f.cloneNode(),c=n.createElement;' +\n                                                          'h.shivMethods&&(' +\n                                                          // unroll the `createElement` calls\n                                                          getElements().join().replace(/[\\w\\-]+/g, function(nodeName) {\n            data.createElem(nodeName);\n            data.frag.createElement(nodeName);\n            return 'c(\"' + nodeName + '\")';\n          }) +\n            ');return n}'\n                                                         )(html5, data.frag);\n        }\n\n        /*--------------------------------------------------------------------------*/\n\n        /**\n         * Shivs the given document.\n         * @memberOf html5\n         * @param {Document} ownerDocument The document to shiv.\n         * @returns {Document} The shived document.\n         */\n        function shivDocument(ownerDocument) {\n          if (!ownerDocument) {\n            ownerDocument = document;\n          }\n          var data = getExpandoData(ownerDocument);\n\n          if (html5.shivCSS && !supportsHtml5Styles && !data.hasCSS) {\n            data.hasCSS = !!addStyleSheet(ownerDocument,\n                                          // corrects block display not defined in IE6/7/8/9\n                                          'article,aside,dialog,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}' +\n                                            // adds styling not present in IE6/7/8/9\n                                            'mark{background:#FF0;color:#000}' +\n                                            // hides non-rendered elements\n                                            'template{display:none}'\n                                         );\n          }\n          if (!supportsUnknownElements) {\n            shivMethods(ownerDocument, data);\n          }\n          return ownerDocument;\n        }\n\n        /*--------------------------------------------------------------------------*/\n\n        /**\n         * The `html5` object is exposed so that more elements can be shived and\n         * existing shiving can be detected on iframes.\n         * @type Object\n         * @example\n         *\n         * // options can be changed before the script is included\n         * html5 = { 'elements': 'mark section', 'shivCSS': false, 'shivMethods': false };\n         */\n        var html5 = {\n\n          /**\n           * An array or space separated string of node names of the elements to shiv.\n           * @memberOf html5\n           * @type Array|String\n           */\n          'elements': options.elements || 'abbr article aside audio bdi canvas data datalist details dialog figcaption figure footer header hgroup main mark meter nav output progress section summary template time video',\n\n          /**\n           * current version of html5shiv\n           */\n          'version': version,\n\n          /**\n           * A flag to indicate that the HTML5 style sheet should be inserted.\n           * @memberOf html5\n           * @type Boolean\n           */\n          'shivCSS': (options.shivCSS !== false),\n\n          /**\n           * Is equal to true if a browser supports creating unknown/HTML5 elements\n           * @memberOf html5\n           * @type boolean\n           */\n          'supportsUnknownElements': supportsUnknownElements,\n\n          /**\n           * A flag to indicate that the document's `createElement` and `createDocumentFragment`\n           * methods should be overwritten.\n           * @memberOf html5\n           * @type Boolean\n           */\n          'shivMethods': (options.shivMethods !== false),\n\n          /**\n           * A string to describe the type of `html5` object (\"default\" or \"default print\").\n           * @memberOf html5\n           * @type String\n           */\n          'type': 'default',\n\n          // shivs the document according to the specified `html5` object options\n          'shivDocument': shivDocument,\n\n          //creates a shived element\n          createElement: createElement,\n\n          //creates a shived documentFragment\n          createDocumentFragment: createDocumentFragment\n        };\n\n        /*--------------------------------------------------------------------------*/\n\n        // expose html5\n        window.html5 = html5;\n\n        // shiv the document\n        shivDocument(document);\n\n    }(this, document));\n    /*>>shiv*/\n\n    // Assign private properties to the return object with prefix\n    Modernizr._version      = version;\n\n    // expose these for the plugin API. Look in the source for how to join() them against your input\n    /*>>prefixes*/\n    Modernizr._prefixes     = prefixes;\n    /*>>prefixes*/\n    /*>>domprefixes*/\n    Modernizr._domPrefixes  = domPrefixes;\n    Modernizr._cssomPrefixes  = cssomPrefixes;\n    /*>>domprefixes*/\n\n    /*>>mq*/\n    // Modernizr.mq tests a given media query, live against the current state of the window\n    // A few important notes:\n    //   * If a browser does not support media queries at all (eg. oldIE) the mq() will always return false\n    //   * A max-width or orientation query will be evaluated against the current state, which may change later.\n    //   * You must specify values. Eg. If you are testing support for the min-width media query use:\n    //       Modernizr.mq('(min-width:0)')\n    // usage:\n    // Modernizr.mq('only screen and (max-width:768)')\n    Modernizr.mq            = testMediaQuery;\n    /*>>mq*/\n\n    /*>>hasevent*/\n    // Modernizr.hasEvent() detects support for a given event, with an optional element to test on\n    // Modernizr.hasEvent('gesturestart', elem)\n    Modernizr.hasEvent      = isEventSupported;\n    /*>>hasevent*/\n\n    /*>>testprop*/\n    // Modernizr.testProp() investigates whether a given style property is recognized\n    // Note that the property names must be provided in the camelCase variant.\n    // Modernizr.testProp('pointerEvents')\n    Modernizr.testProp      = function(prop){\n        return testProps([prop]);\n    };\n    /*>>testprop*/\n\n    /*>>testallprops*/\n    // Modernizr.testAllProps() investigates whether a given style property,\n    //   or any of its vendor-prefixed variants, is recognized\n    // Note that the property names must be provided in the camelCase variant.\n    // Modernizr.testAllProps('boxSizing')\n    Modernizr.testAllProps  = testPropsAll;\n    /*>>testallprops*/\n\n\n    /*>>teststyles*/\n    // Modernizr.testStyles() allows you to add custom styles to the document and test an element afterwards\n    // Modernizr.testStyles('#modernizr { position:absolute }', function(elem, rule){ ... })\n    Modernizr.testStyles    = injectElementWithStyles;\n    /*>>teststyles*/\n\n\n    /*>>prefixed*/\n    // Modernizr.prefixed() returns the prefixed or nonprefixed property name variant of your input\n    // Modernizr.prefixed('boxSizing') // 'MozBoxSizing'\n\n    // Properties must be passed as dom-style camelcase, rather than `box-sizing` hypentated style.\n    // Return values will also be the camelCase variant, if you need to translate that to hypenated style use:\n    //\n    //     str.replace(/([A-Z])/g, function(str,m1){ return '-' + m1.toLowerCase(); }).replace(/^ms-/,'-ms-');\n\n    // If you're trying to ascertain which transition end event to bind to, you might do something like...\n    //\n    //     var transEndEventNames = {\n    //       'WebkitTransition' : 'webkitTransitionEnd',\n    //       'MozTransition'    : 'transitionend',\n    //       'OTransition'      : 'oTransitionEnd',\n    //       'msTransition'     : 'MSTransitionEnd',\n    //       'transition'       : 'transitionend'\n    //     },\n    //     transEndEventName = transEndEventNames[ Modernizr.prefixed('transition') ];\n\n    Modernizr.prefixed      = function(prop, obj, elem){\n      if(!obj) {\n        return testPropsAll(prop, 'pfx');\n      } else {\n        // Testing DOM property e.g. Modernizr.prefixed('requestAnimationFrame', window) // 'mozRequestAnimationFrame'\n        return testPropsAll(prop, obj, elem);\n      }\n    };\n    /*>>prefixed*/\n\n\n    /*>>cssclasses*/\n    // Remove \"no-js\" class from <html> element, if it exists:\n    docElement.className = docElement.className.replace(/(^|\\s)no-js(\\s|$)/, '$1$2') +\n\n                            // Add the new classes to the <html> element.\n                            (enableClasses ? ' js ' + classes.join(' ') : '');\n    /*>>cssclasses*/\n\n    return Modernizr;\n\n})(this, this.document);\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/modernizr/readme.md",
    "content": "Modernizr [![Build Status](https://secure.travis-ci.org/Modernizr/Modernizr.png?branch=master)](http://travis-ci.org/Modernizr/Modernizr)\n=========\n\n### a JavaScript library allowing you to use CSS3 & HTML5 while maintaining control over unsupported browsers \n\nModernizr tests which native CSS3 and HTML5 features are available in\nthe current UA and makes the results available to you in two ways:\nas properties on a global `Modernizr` object, and as classes on the\n`<html>` element. This information allows you to progressively enhance\nyour pages with a granular level of control over the experience.\n\nModernizr has an optional (*not included*) conditional resource loader\ncalled `Modernizr.load()`, based on Yepnope.js ([yepnopejs.com](http://yepnopejs.com/)).\nTo get a build that includes `Modernizr.load()`, as well as choosing\nwhich tests to include, go to [www.modernizr.com/download/](http://www.modernizr.com/download/)\n\n[Full documentation on modernizr.com/docs/](http://www.modernizr.com/docs/)\n\n* * *\n\nModernizr is dual-licensed under the [BSD and MIT licenses](http://www.modernizr.com/license/).\n\n[modernizr.com](http://www.modernizr.com/)\n\n\n#### Try it out: \n\nRun the test suite: [http://modernizr.github.com/Modernizr/test/](http://modernizr.github.com/Modernizr/test/)\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/modernizr/test/basic.html",
    "content": "<!DOCTYPE html>\n<html class=\"+no-js no-js- no-js i-has-no-js\">\n<head>\n  <meta charset=\"UTF-8\">\n  <title>Modernizr Test Suite</title>\n  <link rel=\"stylesheet\" href=\"qunit/qunit.css\">\n  <style>\n     body { margin-bottom: 150px;}\n     #testbed { font-family: Helvetica; color: #444; padding-bottom: 100px;}\n     #testbed button { margin: 30px; font-size: 13px;}\n     .data-notes, .offScreen { display:none;}\n     table { width: 100%;}\n     tbody tr:nth-child(even) td, tbody tr:nth-child(even) th {  border: 1px solid #ccc; border-left: 0; border-right: 0;}\n     table td:nth-child(even), table th:nth-child(even) { background: #e6e6e6;}\n     table tbody tr:hover td, table tbody tr:hover th { background: #e1e100!important;}\n     td.wrong { background:red!important;}\n     #html5section { visibility: hidden; }\n     h1 label { display:none;}\n     .output { padding: 0 0 0 16px;}\n     .output ul { margin: 0;}\n     .output li { color: #854747; }\n     .output li.yes{color:#090;}\n     .output li b{color:#000;}\n     .output {font:14px/1.3 Inconsolata,Consolas,monospace;\n                    -webkit-column-count: 5;\n                       -moz-column-count: 5;\n                            column-count: 5;}\n      .output + .output { border-top: 5px solid #ccc; }\n      textarea { width: 100%; min-height: 75px;}\n      #caniusetrigger { font-size: 38px; font-family: monospace; display:block; }\n  </style>\n\n  <script src=\"https://raw.github.com/Modernizr/Modernizr/master/modernizr.js\"></script>\n\n  <script>window.Modernizr || document.write('<script src=\"../modernizr.js\"><\\/script>')</script>\n\n  <script src=\"js/lib/polyfills.js\"></script>\n  <script src=\"js/lib/detect-global.js\"></script>\n  \n  <script src=\"qunit/qunit.js\"></script>\n  <script src=\"js/lib/jquery-1.7b2.js\"></script>\n  \n  <script src=\"js/setup.js\"></script>\n  \n  <script src=\"js/unit.js\"></script>\n</head>\n<body>\n  <h1 id=\"qunit-header\">Modernizr Test Suite</h1>\n  <h2 id=\"qunit-banner\"></h2>\n  <div id=\"qunit-testrunner-toolbar\"></div>\n  <h2 id=\"qunit-userAgent\"></h2>\n\n  <ol id=\"qunit-tests\"></ol>\n\n  <div id=\"mod-output\" class=output></div>\n  <div id=\"mod-feattest-output\" class=output></div>\n\n\n  <br>\n \n  <section><aside>this is an aside within a section</aside></section>\n  \n  \n</body>\n</html> \n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/modernizr/test/caniuse.html",
    "content": "<!DOCTYPE html>\n<!-- saved from url=(0025)http://tests.caniuse.com/ -->\n<html class=\" no-js\"><head><meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\"><title>WCIU test page</title>\n<meta charset=\"utf-8\">\n\n<!-- pull in latest modernizr -->\n<script src=\"../modernizr.js\"></script>\n\n<script src=\"./caniuse_files/jquery.min.js\"></script>\n<link rel=\"stylesheet\" type=\"text/css\" href=\"./caniuse_files/style.css\">\n\n<script>\n\nfunction setResult(id, result) {\n\t$('#' + id).addClass(result ? 'pass' : 'fail');\n}\n\n</script>\n\n</head><body><h2>The <a href=\"http://caniuse.com/\">When can I use...</a> test suite... <small>(originally from <a href=\"http://tests.caniuse.com/\">tests.caniuse.com</a>)</small></h2> \n<div id=\"intro\">\n\t<p>This is a basic test suite of various web technologies for the <a href=\"./caniuse_files/caniuse.html\">When Can I Use</a> website.</p>\n\t<p>It is used to quickly test basic support for features in upcoming browsers, rather than any full support of the feature's specification.</p>\n\t<p>Results on this page generally match the results as they appear on the When Can I Use site, but <strong>may not always</strong> due to a variety of circumstances (test may pass but support is actually buggy, not tested well enough, has alternative method, etc).</p>\n\t\n\t<p>Four different types of tests are used:</p>\n\t<dl>\n\t\t<dt>Auto</dt>\n\t\t<dd>Automated JS-based tests. (m) means <a href=\"http://modernizr.com/\">Modernizr</a> is used.</dd>\n\t\n\t\t<dt>Visual</dt>\n\t\t<dd>Requires visual confirmation/comparison to confirm</dd>\n\t\n\t\t<dt>Visual-square</dt>\n\t\t<dd>Test must create a 30x30px green (lime) square</dd>\n\t\n\t\t<dt>Interactive</dt>\n\t\t<dd>Requires interaction to confirm support</dd>\n\t</dl>\n\t\n\t<p>If you are interested in contributing tests you can contact me at: when (at) caniuse (dotcom).</p>\n\t\n</div>\n\n\n<div id=\"options\">\n<form action=\"http://tests.caniuse.com/?\" method=\"get\"><label for=\"browser_list\">Select browser to compare results with: </label><select id=\"ua\" name=\"ua\" autocomplete=\"false\"><option value=\"\">(none)</option><option value=\"and2.1\">Android Browser 2.1</option><option value=\"and2.2\">Android Browser 2.2</option><option value=\"and2.3\">Android Browser 2.3</option><option value=\"and3\">Android Browser 3</option><option value=\"chr10\">Chrome 10</option><option value=\"chr11\">Chrome 11</option><option value=\"chr12\">Chrome 12</option><option value=\"chr13\" selected=\"\">Chrome 13</option><option value=\"chr4\">Chrome 4</option><option value=\"chr5\">Chrome 5</option><option value=\"chr6\">Chrome 6</option><option value=\"chr7\">Chrome 7</option><option value=\"chr8\">Chrome 8</option><option value=\"chr9\">Chrome 9</option><option value=\"ff2\">Firefox 2</option><option value=\"ff3\">Firefox 3</option><option value=\"ff3.5\">Firefox 3.5</option><option value=\"ff3.6\">Firefox 3.6</option><option value=\"ff4\">Firefox 4</option><option value=\"ff5\">Firefox 5</option><option value=\"ff6\">Firefox 6</option><option value=\"ie10\">IE 10</option><option value=\"ie5.5\">IE 5.5</option><option value=\"ie6\">IE 6</option><option value=\"ie7\">IE 7</option><option value=\"ie8\">IE 8</option><option value=\"ie9\">IE 9</option><option value=\"ios3.2\">iOS Safari 3.2</option><option value=\"ios4.1\">iOS Safari 4.0-4.1</option><option value=\"ios4.2\">iOS Safari 4.2-4.3</option><option value=\"op10.1\">Opera 10.0-10.1</option><option value=\"op10.5\">Opera 10.5</option><option value=\"op10.6\">Opera 10.6</option><option value=\"op11\">Opera 11</option><option value=\"op11.1\">Opera 11.1</option><option value=\"op11.5\">Opera 11.5</option><option value=\"op12\">Opera 12</option><option value=\"op9\">Opera 9</option><option value=\"op9.6\">Opera 9.5-9.6</option><option value=\"omini5\">Opera Mini 5.0-6.0</option><option value=\"omob10\">Opera Mobile 10</option><option value=\"omob11\">Opera Mobile 11</option><option value=\"saf3.1\">Safari 3.1</option><option value=\"saf3.2\">Safari 3.2</option><option value=\"saf4\">Safari 4</option><option value=\"saf5\">Safari 5</option><option value=\"saf6\">Safari 6</option></select><div><label for=\"prefix\">Select CSS prefix to use (does not affect modernizr or non-CSS tests): </label><select id=\"prefix\" name=\"prefix\" autocomplete=\"false\"><option value=\"all\" selected=\"\">All combinations</option><option value=\"-webkit-\">-webkit-</option><option value=\"-moz-\">-moz-</option><option value=\"-ms-\">-ms-</option><option value=\"-o-\">-o-</option><option value=\"none\">(no prefix)</option></select><input id=\"opt_submit\" type=\"submit\" value=\"Go\"></div></form></div><table><caption>Tests</caption><thead><tr><th>Feature</th><th>chr13</th><th>Tests</th></tr></thead><tbody><tr><th><h3>Toolbar/context menu</h3><span class=\"links\">[<a href=\"http://caniuse.com/menu\">Table</a>] [<a href=\"http://tests.caniuse.com/?feat=menu&prefix=all\">Single feat</a>]</span></th><td class=\"current unknown\">&nbsp;</td><td>\n\n</td></tr>\n<tr><th><h3>Audio element</h3><span class=\"links\">[<a href=\"http://caniuse.com/audio\">Table</a>] [<a href=\"http://tests.caniuse.com/?feat=audio&prefix=all\">Single feat</a>]</span></th><td class=\"current pass\">&nbsp;</td><td>\n<div class=\"test_wrap\"><h3>Auto</h3><div id=\"audio0\" class=\"auto pass\"></div><script>\nsetResult('audio0', !!document.createElement('audio').canPlayType);\n</script><div class=\"info\">document.createElement('audio').canPlayType</div></div>\n\n<div class=\"test_wrap\"><h3>Interact</h3><div id=\"audio1\" class=\"interact\"></div><audio controls=\"\">\n <source src=\"mimeaud.php?type=.wav\">\n <source src=\"mimeaud.php?type=.mp3\">\n <source src=\"mimeaud.php?type=.ogg\">\n <source src=\"mimeaud.php?type=.aac\">\n <source src=\"mimeaud.php?type=.flac\">\n <source src=\"mimeaud.php?type=.wma\">\n Audio fail\n</audio>\n<div class=\"info\">Audio element with 6 different sources (with MIME set)</div></div>\n\n<div class=\"test_wrap\"><h3>Interact</h3><div id=\"audio2\" class=\"interact\"></div><audio controls=\"\">\n <source src=\"mimeaud.php?nomime=1&amp;type=.wav\">\n <source src=\"mimeaud.php?nomime=1&amp;type=.mp3\">\n <source src=\"mimeaud.php?nomime=1&amp;type=.ogg\">\n <source src=\"mimeaud.php?nomime=1&amp;type=.aac\">\n <source src=\"mimeaud.php?nomime=1&amp;type=.flac\">\n <source src=\"mimeaud.php?nomime=1&amp;type=.wma\">\n--&gt;\n Audio fail\n</audio>\n\n<div class=\"info\">Audio element with 6 different sources (no MIME set)</div></div>\n\n</td></tr>\n<tr><th><h3>CSS3 Background-image options</h3><span class=\"links\">[<a href=\"http://caniuse.com/background-img-opts\">Table</a>] [<a href=\"http://tests.caniuse.com/?feat=background-img-opts&prefix=all\">Single feat</a>]</span></th><td class=\"current pass\">&nbsp;</td><td>\n<div class=\"test_wrap\"><h3>Auto (m)</h3><div id=\"background-img-opts0\" class=\"auto pass\"></div><script>setResult('background-img-opts0', Modernizr.backgroundsize);</script><div class=\"info\">Modernizr test for: \"backgroundsize\"</div></div>\n\n<div class=\"test_wrap\"><h3>Visual-square</h3><div id=\"background-img-opts1\" class=\"visual-square\"></div><div class=\"square\"><div style=\"width:30px;height:30px;background:lime\">\n<div style=\"-webkit-background-clip:content-box;-moz-background-clip:content-box;-ms-background-clip:content-box;-o-background-clip:content-box;background-clip:content-box;padding:30px 30px 0 0;background-color:red\"></div>\n</div>\n</div><div class=\"info\">background-clip: content-box;</div></div>\n\n<div class=\"test_wrap\"><h3>Visual-square</h3><div id=\"background-img-opts2\" class=\"visual-square\"></div><div class=\"square\"><div style=\"width:30px;height:30px;background:lime\">\n<div style=\"-webkit-background-origin:content-box;-moz-background-origin:content-box;-ms-background-origin:content-box;-o-background-origin:content-box;background-origin:content-box;padding:30px 30px 0 0;background-image:url(caniuse_files/red30x30.png);background-repeat: no-repeat;\"></div>\n</div>\n</div><div class=\"info\">background-origin: content-box;</div></div>\n\n<div class=\"test_wrap\"><h3>Visual-square</h3><div id=\"background-img-opts2\" class=\"visual-square\"></div><div class=\"square\"><div style=\"-webkit-background-size:30px 30px;-moz-background-size:30px 30px;-ms-background-size:30px 30px;-o-background-size:30px 30px;background-size:30px 30px;background-image:url(caniuse_files/green5x5.png);background-repeat: no-repeat;width:30px;height:30px;\"></div>\n</div><div class=\"info\">background-size: 30px 30px;</div></div>\n\n</td></tr>\n<tr><th><h3>CSS3 Border images</h3><span class=\"links\">[<a href=\"http://caniuse.com/border-image\">Table</a>] [<a href=\"http://tests.caniuse.com/?feat=border-image&prefix=all\">Single feat</a>]</span></th><td class=\"current partial\">&nbsp;<span>-pre-</span></td><td>\n<div class=\"test_wrap\"><h3>Auto (m)</h3><div id=\"border-image0\" class=\"auto pass\"></div><script>setResult('border-image0', Modernizr.borderimage);</script><div class=\"info\">Modernizr test for: \"borderimage\"</div></div>\n\n<div class=\"test_wrap\"><h3>Visual-square</h3><div id=\"border-image1\" class=\"visual-square\"></div><div class=\"square\"><div style=\"border-width: 15px;\t-webkit-border-image-source: url(caniuse_files/green5x5.png);-moz-border-image-source: url(caniuse_files/green5x5.png);-ms-border-image-source: url(caniuse_files/green5x5.png);-o-border-image-source: url(caniuse_files/green5x5.png);border-image-source: url(caniuse_files/green5x5.png);-webkit-border-image-slice: 2;-moz-border-image-slice: 2;-ms-border-image-slice: 2;-o-border-image-slice: 2;border-image-slice: 2; width:0; height: 0;\"></div></div><div class=\"info\">Separate properties:\nborder-image-source: url(caniuse_files/green5x5.png);\nborder-image-slice: 2;</div></div>\n\n<div class=\"test_wrap\"><h3>Visual-square</h3><div id=\"border-image3\" class=\"visual-square\"></div><div class=\"square\"><div style=\"border-width: 15px;\t-webkit-border-image: url(caniuse_files/green5x5.png) 2;-moz-border-image: url(caniuse_files/green5x5.png) 2;-ms-border-image: url(caniuse_files/green5x5.png) 2;-o-border-image: url(caniuse_files/green5x5.png) 2;border-image: url(caniuse_files/green5x5.png) 2; width:0; height: 0;\"></div></div><div class=\"info\">Shorthand syntax: border-image: url(caniuse_files/green5x5.png) 2;</div></div>\n\n</td></tr>\n<tr><th><h3>CSS3 Border-radius (rounded corners)</h3><span class=\"links\">[<a href=\"http://caniuse.com/border-radius\">Table</a>] [<a href=\"http://tests.caniuse.com/?feat=border-radius&prefix=all\">Single feat</a>]</span></th><td class=\"current pass\">&nbsp;</td><td>\n<div class=\"test_wrap\"><h3>Auto (m)</h3><div id=\"border-radius0\" class=\"auto pass\"></div><script>setResult('border-radius0', Modernizr.borderradius);</script><div class=\"info\">Modernizr test for: \"borderradius\"</div></div>\n\n<div class=\"test_wrap\"><h3>Visual-square</h3><div id=\"border-radius1\" class=\"visual-square\"></div><div class=\"square\"><div style=\"width:30px; height:30px; overflow:hidden; position:relative;\">\n  <div style=\"background:lime; height: 40px; \"></div>\n  <div style=\"background:red; position:absolute; z-index:10; top: 0;\n              height: 400px; width: 400px;\n              -webkit-border-radius: 150px;\n-moz-border-radius: 150px;\n-ms-border-radius: 150px;\n-o-border-radius: 150px;\nborder-radius: 150px;\n\n\"></div>\n</div></div></div>\n\n</td></tr>\n<tr><th><h3>Canvas (basic support)</h3><span class=\"links\">[<a href=\"http://caniuse.com/canvas\">Table</a>] [<a href=\"http://tests.caniuse.com/?feat=canvas&prefix=all\">Single feat</a>]</span></th><td class=\"current pass\">&nbsp;</td><td>\n<div class=\"test_wrap\"><h3>Auto (m)</h3><div id=\"canvas0\" class=\"auto pass\"></div><script>setResult('canvas0', Modernizr.canvas);</script><div class=\"info\">Modernizr test for: \"canvas\"</div></div>\n\n<div class=\"test_wrap\"><h3>Visual-square</h3><div id=\"canvas1\" class=\"visual-square\"></div><div class=\"square\"><canvas width=\"30\" height=\"30\" style=\"background:red;\" id=\"canv_test\"></canvas>\n\n<script>\nvar canvas = $('#canv_test')[0], \n    ctx    = canvas.getContext && canvas.getContext('2d');\n\nif (ctx){\n  ctx.fillStyle = '#00ff00';\n  ctx.fillRect(0,0,100,40);\n}\n</script></div><div class=\"info\">Draw rect on canvas using fillStyle and fillRect</div></div>\n\n</td></tr>\n<tr><th><h3>classList (DOMTokenList )</h3><span class=\"links\">[<a href=\"http://caniuse.com/classlist\">Table</a>] [<a href=\"http://tests.caniuse.com/?feat=classlist&prefix=all\">Single feat</a>]</span></th><td class=\"current pass\">&nbsp;</td><td>\n<div class=\"test_wrap\"><h3>Auto</h3><div id=\"classlist0\" class=\"auto pass\"></div><script>\nsetResult('classlist0', \"classList\" in document.body);\n</script><div class=\"info\">\"classList\" in document.body</div></div>\n\n<div class=\"test_wrap\"><h3>Visual-square</h3><div id=\"classlist1\" class=\"visual-square\"></div><div class=\"square\"><div id=\"classlisttest\" class=\"pass\" style=\"width:30px;height:30px;\"></div>\n<script>\ntry{\n  document.getElementById('classlisttest').classList.remove('fail');\n  document.getElementById('classlisttest').classList.add('pass');\n}catch(e){}\n\n\n</script></div></div>\n\n</td></tr>\n<tr><th><h3>Cross-Origin Resource Sharing</h3><span class=\"links\">[<a href=\"http://caniuse.com/cors\">Table</a>] [<a href=\"http://tests.caniuse.com/?feat=cors&prefix=all\">Single feat</a>]</span></th><td class=\"current pass\">&nbsp;</td><td>\n<div class=\"test_wrap\"><h3>Auto</h3><div id=\"cors0\" class=\"auto pass\"></div><script>\n$(function() {\n\t$.get('http://a.deveria.com/tests/cors/true.php', function(data) {\n\t\tsetResult('cors0', data);\n\t});\n});\n\n</script><div class=\"info\">Instant XHR request on page that should permit it.</div></div>\n\n</td></tr>\n<tr><th><h3>CSS3 Animation</h3><span class=\"links\">[<a href=\"http://caniuse.com/css-animation\">Table</a>] [<a href=\"http://tests.caniuse.com/?feat=css-animation&prefix=all\">Single feat</a>]</span></th><td class=\"current pass\">&nbsp;<span>-pre-</span></td><td>\n<div class=\"test_wrap\"><h3>Auto (m)</h3><div id=\"css-animation0\" class=\"auto pass\"></div><script>setResult('css-animation0', Modernizr.cssanimations);</script><div class=\"info\">Modernizr test for: \"cssanimations\"</div></div>\n\n<div class=\"test_wrap\"><h3>Visual-square</h3><div id=\"css-animation1\" class=\"visual-square\"></div><div class=\"square\"><style>\n #css-animation1test {\n\t-webkit-animation: staylime 60s infinite;\n-moz-animation: staylime 60s infinite;\n-ms-animation: staylime 60s infinite;\n-o-animation: staylime 60s infinite;\nanimation: staylime 60s infinite;\n}\n\n@-webkit-keyframes staylime {\n\tfrom { background-color: lime; }\n\tto   { background-color: lime; }\n }\n@-moz-keyframes staylime {\n\tfrom { background-color: lime; }\n\tto   { background-color: lime; }\n }\n@-ms-keyframes staylime {\n\tfrom { background-color: lime; }\n\tto   { background-color: lime; }\n }\n@-o-keyframes staylime {\n\tfrom { background-color: lime; }\n\tto   { background-color: lime; }\n }\n@keyframes staylime {\n\tfrom { background-color: lime; }\n\tto   { background-color: lime; }\n }\n\n\n</style>\n\n<div id=\"css-animation1test\" style=\"width:30px;height:30px;\"></div></div><div class=\"info\">animation: staylime 60s infinite; \n\n@keyframes staylime {\n\tfrom { background-color: lime; }\n\tto   { background-color: lime; }\n }</div></div>\n\n</td></tr>\n<tr><th><h3>CSS3 Box-shadow</h3><span class=\"links\">[<a href=\"http://caniuse.com/css-boxshadow\">Table</a>] [<a href=\"http://tests.caniuse.com/?feat=css-boxshadow&prefix=all\">Single feat</a>]</span></th><td class=\"current pass\">&nbsp;</td><td>\n<div class=\"test_wrap\"><h3>Auto (m)</h3><div id=\"css-boxshadow0\" class=\"auto pass\"></div><script>setResult('css-boxshadow0', Modernizr.boxshadow);</script><div class=\"info\">Modernizr test for: \"boxshadow\"</div></div>\n\n<div class=\"test_wrap\"><h3>Visual-square</h3><div id=\"css-boxshadow1\" class=\"visual-square\"></div><div class=\"square\"><div style=\"background:red; width: 30px; height: 30px;\n            -webkit-box-shadow: inset lime 0px 0px 150px;\n-moz-box-shadow: inset lime 0px 0px 150px;\n-ms-box-shadow: inset lime 0px 0px 150px;\n-o-box-shadow: inset lime 0px 0px 150px;\nbox-shadow: inset lime 0px 0px 150px;\n \"></div>\n</div><div class=\"info\">Must be greenish, may not be entirely lime depending on the implementation.</div></div>\n\n</td></tr>\n<tr><th><h3>CSS position:fixed</h3><span class=\"links\">[<a href=\"http://caniuse.com/css-fixed\">Table</a>] [<a href=\"http://tests.caniuse.com/?feat=css-fixed&prefix=all\">Single feat</a>]</span></th><td class=\"current pass\">&nbsp;</td><td>\n\n<div class=\"test_wrap\"><h3>Interact</h3><div id=\"css-fixed1\" class=\"interact\"></div><a href=\"http://tests.caniuse.com/fixed.html\">Test here</a></div>\n\n</td></tr>\n<tr><th><h3>CSS Gradients</h3><span class=\"links\">[<a href=\"http://caniuse.com/css-gradients\">Table</a>] [<a href=\"http://tests.caniuse.com/?feat=css-gradients&prefix=all\">Single feat</a>]</span></th><td class=\"current pass\">&nbsp;<span>-pre-</span></td><td>\n<div class=\"test_wrap\"><h3>Auto (m)</h3><div id=\"css-gradients0\" class=\"auto pass\"></div><script>setResult('css-gradients0', Modernizr.cssgradients);</script><div class=\"info\">Modernizr test for: \"cssgradients\"</div></div>\n\n<div class=\"test_wrap\"><h3>Visual-square</h3><div id=\"css-gradients1\" class=\"visual-square\"></div><div class=\"square\"><div style=\"width:30px;height:30px;background-image: -webkit-linear-gradient(lime, lime);background-image: -moz-linear-gradient(lime, lime);background-image: -ms-linear-gradient(lime, lime);background-image: -o-linear-gradient(lime, lime);background-image: linear-gradient(lime, lime);\"></div></div><div class=\"info\">linear-gradient(lime, lime);</div></div>\n\n<div class=\"test_wrap\"><h3>Visual-square</h3><div id=\"css-gradients2\" class=\"visual-square\"></div><div class=\"square\"><div style=\"width:30px;height:30px;background-image:-webkit-radial-gradient(lime, lime);background-image:-moz-radial-gradient(lime, lime);background-image:-ms-radial-gradient(lime, lime);background-image:-o-radial-gradient(lime, lime);background-image:radial-gradient(lime, lime);\"></div></div><div class=\"info\">radial-gradient(lime, lime)</div></div>\n\n</td></tr>\n<tr><th><h3>CSS3 Opacity</h3><span class=\"links\">[<a href=\"http://caniuse.com/css-opacity\">Table</a>] [<a href=\"http://tests.caniuse.com/?feat=css-opacity&prefix=all\">Single feat</a>]</span></th><td class=\"current pass\">&nbsp;</td><td>\n<div class=\"test_wrap\"><h3>Auto (m)</h3><div id=\"css-opacity0\" class=\"auto pass\"></div><script>setResult('css-opacity0', Modernizr.opacity);</script><div class=\"info\">Modernizr test for: \"opacity\"</div></div>\n\n<div class=\"test_wrap\"><h3>Visual-square</h3><div id=\"css-opacity1\" class=\"visual-square\"></div><div class=\"square\"><div style=\"width:30px;height:30px;position:relative;background:lime\">\n\t<div style=\"width:30px;height:30px;background:red;-webkit-opacity:0;-moz-opacity:0;-ms-opacity:0;-o-opacity:0;opacity:0;\"></div></div>\n</div>\n</div><div class=\"info\">Test for opacity: 0</div>\n\n</td></tr>\n<tr><th><h3>CSS3 Text-shadow</h3><span class=\"links\">[<a href=\"http://caniuse.com/css-textshadow\">Table</a>] [<a href=\"http://tests.caniuse.com/?feat=css-textshadow&prefix=all\">Single feat</a>]</span></th><td class=\"current pass\">&nbsp;</td><td>\n<div class=\"test_wrap\"><h3>Auto (m)</h3><div id=\"css-textshadow0\" class=\"auto pass\"></div><script>setResult('css-textshadow0', Modernizr.textshadow);</script><div class=\"info\">Modernizr test for: \"textshadow\"</div></div>\n\n<div class=\"test_wrap\"><h3>Visual</h3><div id=\"css-textshadow1\" class=\"visual\"></div><div class=\"vis_test\"><div style=\"width:30px;height:30px;overflow:hidden\" id=\"css-textshadow1\">\n \n<div style=\"font:25px/25px Times New Roman, Times; color:white;-webkit-text-shadow:25px 0 3px lime;-moz-text-shadow:25px 0 3px lime;-ms-text-shadow:25px 0 3px lime;-o-text-shadow:25px 0 3px lime;text-shadow:25px 0 3px lime;position:relative; left:-25px;\">A</div>\n\n</div></div><div class=\"vis_ref\"><img src=\"./caniuse_files/text-shadow1.png\"></div><div class=\"info\">font-size: 25px;\ncolor: white;\ntext-shadow: 25px 0 3px lime; position: relative;\nleft: -25px;</div></div>\n\n<div class=\"test_wrap\"><h3>Visual</h3><div id=\"css-textshadow2\" class=\"visual\"></div><div class=\"vis_test\"><div style=\"width:40px;height:30px;overflow:hidden\" id=\"css-textshadow2\">\n <div style=\"font:25px/25px Times New Roman, Times; color:white; -webkit-text-shadow:25px 0 3px #0F0, 35px 0 3px #0C0, 45px 0 3px #090;-moz-text-shadow:25px 0 3px #0F0, 35px 0 3px #0C0, 45px 0 3px #090;-ms-text-shadow:25px 0 3px #0F0, 35px 0 3px #0C0, 45px 0 3px #090;-o-text-shadow:25px 0 3px #0F0, 35px 0 3px #0C0, 45px 0 3px #090;text-shadow:25px 0 3px #0F0, 35px 0 3px #0C0, 45px 0 3px #090; position:relative; left:-35px;\">A</div>\n</div>\n</div><div class=\"vis_ref\"><img src=\"./caniuse_files/text-shadow2.png\"></div><div class=\"info\">Multiple shadow test</div></div>\n\n</td></tr>\n<tr><th><h3>CSS3 Transitions</h3><span class=\"links\">[<a href=\"http://caniuse.com/css-transitions\">Table</a>] [<a href=\"http://tests.caniuse.com/?feat=css-transitions&prefix=all\">Single feat</a>]</span></th><td class=\"current pass\">&nbsp;<span>-pre-</span></td><td>\n<div class=\"test_wrap\"><h3>Auto (m)</h3><div id=\"css-transitions0\" class=\"auto pass\"></div><script>setResult('css-transitions0', Modernizr.csstransitions);</script><div class=\"info\">Modernizr test for: \"csstransitions\"</div></div>\n\n<div class=\"test_wrap\"><h3>Interact</h3><div id=\"css-transitions1\" class=\"interact\"></div><style>\n#css-transitions1wrap {\n\twidth: 30px;\n\theight: 30px;\n\tborder: 1px solid;\n\toverflow: hidden;\n\tmargin: 0 auto;\n}\n\n#css-transitions1test {\n\t-webkit-transition-property: left;\n\t-webkit-transition-duration: 3s;\n\t-webkit-transition-timing-function: cubic-bezier(0, 1, 1, 0);\n-moz-transition-property: left;\n\t-moz-transition-duration: 3s;\n\t-moz-transition-timing-function: cubic-bezier(0, 1, 1, 0);\n-ms-transition-property: left;\n\t-ms-transition-duration: 3s;\n\t-ms-transition-timing-function: cubic-bezier(0, 1, 1, 0);\n-o-transition-property: left;\n\t-o-transition-duration: 3s;\n\t-o-transition-timing-function: cubic-bezier(0, 1, 1, 0);\ntransition-property: left;\n\ttransition-duration: 3s;\n\ttransition-timing-function: cubic-bezier(0, 1, 1, 0);\n\tbackground-color: lime;\n\tposition: relative;\n\tleft: -30px;\n\ttop: 0;\n}\n\n#css-transitions1wrap:hover #css-transitions1test {\n\tleft: 30px;\n}\n\n</style>\n<div id=\"css-transitions1wrap\">\n\t<div id=\"css-transitions1test\" style=\"width:30px;height:30px;\"></div>\n</div><p class=\"condition\">Green square must (briefly) appear on hover</p><div class=\"info\">5 second transition from left to right using cubic-bezier(0, 1, 1, 0); </div></div>\n\n</td></tr>\n<tr><th><h3>CSS3 Colors</h3><span class=\"links\">[<a href=\"http://caniuse.com/css3-colors\">Table</a>] [<a href=\"http://tests.caniuse.com/?feat=css3-colors&prefix=all\">Single feat</a>]</span></th><td class=\"current pass\">&nbsp;</td><td>\n<div class=\"test_wrap\"><h3>Auto (m)</h3><div id=\"css3-colors0\" class=\"auto pass\"></div><script>setResult('css3-colors0', Modernizr.hsla);</script><div class=\"info\">Modernizr test for: \"hsla\"</div></div>\n\n<div class=\"test_wrap\"><h3>Visual-square</h3><div id=\"css3-colors1\" class=\"visual-square\"></div><div class=\"square\"><div style=\"background-color: red;      width: 30px; height: 30px; background-color: hsl(120, 100%, 50%);\"></div></div></div>\n\n<div class=\"test_wrap\"><h3>Visual-square</h3><div id=\"css3-colors2\" class=\"visual-square\"></div><div class=\"square\"><div style=\"background-color: red;      width: 30px; height: 30px; background-color: rgba(0, 255, 0, 1);\"></div></div></div>\n\n</td></tr>\n<tr><th><h3>dataset &amp; data-* attributes</h3><span class=\"links\">[<a href=\"http://caniuse.com/dataset\">Table</a>] [<a href=\"http://tests.caniuse.com/?feat=dataset&prefix=all\">Single feat</a>]</span></th><td class=\"current pass\">&nbsp;</td><td>\n<div class=\"test_wrap\"><h3>Auto</h3><div id=\"dataset0\" class=\"auto pass\" data-foo=\"bar\"></div><script>\nvar result = 'dataset' in document.body;\nif(result) {\nvar elem = document.getElementById('dataset0'); elem.setAttribute('data-foo', 'bar');\nresult = elem.dataset.foo == 'bar';\n}\nsetResult('dataset0', result);\n</script><div class=\"info\">Test for 'dataset' in document.body and getting the correct value returned from a data-foo attribute.</div></div>\n\n<div class=\"test_wrap\"><h3>Interact</h3><div id=\"dataset1\" class=\"interact\"></div><a href=\"http://trac.webkit.org/export/66582/trunk/LayoutTests/fast/dom/dataset.html\">Test here</a></div>\n\n</td></tr>\n<tr><th><h3>Details &amp; Summary elements</h3><span class=\"links\">[<a href=\"http://caniuse.com/details\">Table</a>] [<a href=\"http://tests.caniuse.com/?feat=details&prefix=all\">Single feat</a>]</span></th><td class=\"current pass\">&nbsp;</td><td>\n<div class=\"test_wrap\"><h3>Auto</h3><div id=\"details0\" class=\"auto pass\"></div><script>\nsetResult('details0', 'open' in document.createElement('details'));\n</script></div>\n\n<div class=\"test_wrap\"><h3>Interact</h3><div id=\"details1\" class=\"interact\"></div><details>\n    <summary>(summary button)</summary>\n    <p>(detail contents)</p>\n</details><p class=\"condition\">\"(detail contents)\" should be visible ONLY after clicking summary</p><div class=\"info\">Basic details element with summary and paragraph as children.</div></div>\n\n</td></tr>\n<tr><th><h3>Server-sent DOM events</h3><span class=\"links\">[<a href=\"http://caniuse.com/eventsource\">Table</a>] [<a href=\"http://tests.caniuse.com/?feat=eventsource&prefix=all\">Single feat</a>]</span></th><td class=\"current pass\">&nbsp;</td><td>\n<div class=\"test_wrap\"><h3>Auto</h3><div id=\"eventsource0\" class=\"auto pass\"></div><script>\nsetResult('eventsource0', typeof EventSource !== 'undefined');\n</script></div>\n\n</td></tr>\n<tr><th><h3>File API</h3><span class=\"links\">[<a href=\"http://caniuse.com/fileapi\">Table</a>] [<a href=\"http://tests.caniuse.com/?feat=fileapi&prefix=all\">Single feat</a>]</span></th><td class=\"current pass\">&nbsp;</td><td>\n<div class=\"test_wrap\"><h3>Auto</h3><div id=\"fileapi0\" class=\"auto pass\"></div><script>\nsetResult('fileapi0', !!window.FileReader);\n</script></div>\n\n</td></tr>\n<tr><th><h3>Flexible Box Layout Module</h3><span class=\"links\">[<a href=\"http://caniuse.com/flexbox\">Table</a>] [<a href=\"http://tests.caniuse.com/?feat=flexbox&prefix=all\">Single feat</a>]</span></th><td class=\"current pass\">&nbsp;<span>-pre-</span></td><td>\n<div class=\"test_wrap\"><h3>Auto (m)</h3><div id=\"flexbox0\" class=\"auto pass\"></div><script>setResult('flexbox0', Modernizr.flexbox);</script><div class=\"info\">Modernizr test for: \"flexbox\"</div></div>\n\n</td></tr>\n<tr><th><h3>@font-face Web fonts</h3><span class=\"links\">[<a href=\"http://caniuse.com/fontface\">Table</a>] [<a href=\"http://tests.caniuse.com/?feat=fontface&prefix=all\">Single feat</a>]</span></th><td class=\"current pass\">&nbsp;</td><td>\n<div class=\"test_wrap\"><h3>Auto (m)</h3><div id=\"fontface0\" class=\"auto pass\"></div><script>setResult('fontface0', Modernizr.fontface);</script><div class=\"info\">Modernizr test for: \"fontface\"</div></div>\n\n</td></tr>\n<tr><th><h3>Geolocation</h3><span class=\"links\">[<a href=\"http://caniuse.com/geolocation\">Table</a>] [<a href=\"http://tests.caniuse.com/?feat=geolocation&prefix=all\">Single feat</a>]</span></th><td class=\"current pass\">&nbsp;</td><td>\n<div class=\"test_wrap\"><h3>Auto (m)</h3><div id=\"geolocation0\" class=\"auto pass\"></div><script>setResult('geolocation0', Modernizr.geolocation);</script><div class=\"info\">Modernizr test for: \"geolocation\"</div></div>\n\n<div class=\"test_wrap\"><h3>Auto</h3><div id=\"geolocation1\" class=\"auto pass\"></div><script>\n(function() {\n\tvar result = false;\n\tvar geo = navigator.geolocation;\n\tif(geo) {\n\t\tresult = (\n\t\t\t\"getCurrentPosition\" in geo\n\t\t\t&& \"watchPosition\" in geo\n\t\t\t&& \"clearWatch\" in geo\n\t\t);\n\t}\n\tsetResult('geolocation1', result);\n}());\n</script><div class=\"info\">Test for getCurrentPosition, watchPosition and clearWatch in navigator.geolocation</div></div>\n\n<div class=\"test_wrap\"><h3>Interact</h3><div id=\"geolocation2\" class=\"interact\"></div><button id=\"geolocation2test\">Get location</button>\n<script>\n(function() {\n\tvar btn = document.getElementById('geolocation2test');\n\tif(!navigator.geolocation && !navigator.geolocation.getCurrentPosition) return false;\n\tbtn.onclick = function() {\n\t\tvar feat = document.getElementById('geolocation2');\n\t\tnavigator.geolocation.getCurrentPosition(function(pos) {\n\t\t\tfeat.innerHTML = '<p>Result:<br>LAT: ' + pos.coords.latitude + '<br>LON: ' + pos.coords.longitude + '</p>';\n\t\t}, function(error) {\n\t\t\tfeat.innerHTML = '<p>Error:' + error.message + '</p>';\n\t\t});\n\t\t\n\t\tfeat.innerHTML = '<p>Waiting for response...</p>';\n\t\t\n\t\treturn false;\n\t}\n})();\n\n</script><p class=\"condition\">Must provide LAT and LON info (may need to give permission first)</p><div class=\"info\">Test for navigator.geolocation.getCurrentPosition on which position.coords.latitude and position.coords.longitude are expected. </div></div>\n\n</td></tr>\n<tr><th><h3>getElementsByClassName</h3><span class=\"links\">[<a href=\"http://caniuse.com/getelementsbyclassname\">Table</a>] [<a href=\"http://tests.caniuse.com/?feat=getelementsbyclassname&prefix=all\">Single feat</a>]</span></th><td class=\"current pass\">&nbsp;</td><td>\n<div class=\"test_wrap\"><h3>Auto</h3><div id=\"getelementsbyclassname0\" class=\"auto pass\"></div><script>\nsetResult('getelementsbyclassname0', typeof document.getElementsByClassName === 'function')\n</script></div>\n\n<div class=\"test_wrap\"><h3>Visual-square</h3><div id=\"getelementsbyclassname1\" class=\"visual-square\"></div><div class=\"square\"><div style=\"width: 30px; height: 30px; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: lime; background-position: initial initial; background-repeat: initial initial; \" id=\"getelementsbyclassname1container\">\n\t<div id=\"getelementsbyclassname1test\">\n\t\t<div class=\"getelementsbyclassname1test\"></div>\n\t\t<div class=\"getelementsbyclassname1test altgetelementsbyclassname1test\"></div>\n\t\t<div class=\"altgetelementsbyclassname1test\"></div>\n\t</div>\n<script>\n(function() {\n\tif(document.getElementsByClassName) {\n\t\tvar elems = document.getElementsByClassName('getelementsbyclassname1test');\n\t\tvar from_id = document.getElementById('getelementsbyclassname1test').getElementsByTagName('*');\n\t\tif(elems.length && elems.length === 2) {\n\t\t\tif(elems[0] === from_id[0] && elems[1] === from_id[1]) {\n\t\t\t\tdocument.getElementById('getelementsbyclassname1container').style.background = 'lime';\n\t\t\t}\n\t\t}\n\t}\n}());\n</script></div><div class=\"info\">Test if two divs were correctly retrieved using getElementsByClassName</div></div>\n\n</div></td></tr>\n<tr><th><h3>Hashchange event</h3><span class=\"links\">[<a href=\"http://caniuse.com/hashchange\">Table</a>] [<a href=\"http://tests.caniuse.com/?feat=hashchange&prefix=all\">Single feat</a>]</span></th><td class=\"current pass\">&nbsp;</td><td>\n<div class=\"test_wrap\"><h3>Auto (m)</h3><div id=\"hashchange0\" class=\"auto pass\"></div><script>setResult('hashchange0', Modernizr.hashchange);</script><div class=\"info\">Modernizr test for: \"hashchange\"</div></div>\n\n<div class=\"test_wrap\"><h3>Visual-square</h3><div id=\"hashchange1\" class=\"visual-square\"></div><div class=\"square\"><iframe style=\"width:30px;height:30px;border:0\" src=\"./caniuse_files/hashchange.html\"></iframe></div><div class=\"info\">iframe with addEventListener('hashchange', function() {\n\tdocument.body.style.background = 'lime';\n}, false);\n</div></div>\n\n</td></tr>\n<tr><th><h3>Session history management</h3><span class=\"links\">[<a href=\"http://caniuse.com/history\">Table</a>] [<a href=\"http://tests.caniuse.com/?feat=history&prefix=all\">Single feat</a>]</span></th><td class=\"current pass\">&nbsp;</td><td>\n<div class=\"test_wrap\"><h3>Auto (m)</h3><div id=\"history0\" class=\"auto pass\"></div><script>setResult('history0', Modernizr.history);</script><div class=\"info\">Modernizr test for: \"history\"</div></div>\n\n<div class=\"test_wrap\"><h3>Auto</h3><div id=\"history1\" class=\"auto\"></div><iframe src=\"./caniuse_files/pushstate.html#history1\"  style=\"display:none\"></iframe><div class=\"info\">Test if history.pushState was successful</div></div>\n\n</td></tr>\n<tr><th><h3>IndexedDB</h3><span class=\"links\">[<a href=\"http://caniuse.com/indexeddb\">Table</a>] [<a href=\"http://tests.caniuse.com/?feat=indexeddb&prefix=all\">Single feat</a>]</span></th><td class=\"current pass\">&nbsp;</td><td>\n<div class=\"test_wrap\"><h3>Auto (m)</h3><div id=\"indexeddb0\" class=\"auto pass\"></div><script>setResult('indexeddb0', Modernizr.indexeddb);</script><div class=\"info\">Modernizr test for: \"indexeddb\"</div></div>\n\n</td></tr>\n<tr><th><h3>JSON parsing</h3><span class=\"links\">[<a href=\"http://caniuse.com/json\">Table</a>] [<a href=\"http://tests.caniuse.com/?feat=json&prefix=all\">Single feat</a>]</span></th><td class=\"current pass\">&nbsp;</td><td>\n<div class=\"test_wrap\"><h3>Auto</h3><div id=\"json0\" class=\"auto pass\"></div><script>\nsetResult('json0', 'JSON' in window)\n</script></div>\n\n<div class=\"test_wrap\"><h3>Auto</h3><div id=\"json1\" class=\"auto pass\"></div><script>\n(function() {\ntry {\nvar obj = {\n\tkey1: 'my_str',\n\tkey2: ['my', 'array'],\n\tkey3: {\n\t\tmy: 'object',\n\t\twith_numbers: [1, 2, 3, 4.5678],\n\t\tand_also: 9\n\t}\n};\n\nvar str = JSON.stringify(obj);\nif(typeof str === 'string') {\n\tvar new_obj = JSON.parse(str);\n\tif(\n\t\tnew_obj.key1 === 'my_str'\n\t\t&& new_obj.key2.length === 2\n\t\t&& new_obj.key2[1] === 'array'\n\t\t&& new_obj.key3.with_numbers[3] === 4.5678\n\t\t&& new_obj.key3.and_also === 9\n\t) {\n\t\tsetResult('json1', true);\n\t} else {\n\t\tsetResult('json1', false);\n\t}\n} else {\n\tsetResult('json1', false);\n}\n} catch(e){\nsetResult('json1', false);\n}\n}());\n</script><div class=\"info\">Create a JS object, convert to JSON string, convert back to object and compare.</div></div>\n\n</td></tr>\n<tr><th><h3>CSS3 Multiple backgrounds</h3><span class=\"links\">[<a href=\"http://caniuse.com/multibackgrounds\">Table</a>] [<a href=\"http://tests.caniuse.com/?feat=multibackgrounds&prefix=all\">Single feat</a>]</span></th><td class=\"current pass\">&nbsp;</td><td>\n<div class=\"test_wrap\"><h3>Auto (m)</h3><div id=\"multibackgrounds0\" class=\"auto pass\"></div><script>setResult('multibackgrounds0', Modernizr.multiplebgs);</script><div class=\"info\">Modernizr test for: \"multiplebgs\"</div></div>\n\n<div class=\"test_wrap\"><h3>Visual-square</h3><div id=\"multibackgrounds1\" class=\"visual-square\"></div><div class=\"square\"><div style=\"background-repeat: repeat-x; background-image: url(caniuse_files/green5x5.png), url(caniuse_files/green5x5.png), url(caniuse_files/green5x5.png), url(caniuse_files/green5x5.png), url(caniuse_files/green5x5.png), url(caniuse_files/green5x5.png); background-position: 0 0, 0 5px, 0 10px, 0 15px, 0 20px, 0 25px; width:30px;height:30px;\"></div></div><div class=\"info\">background-repeat: repeat-x;\nbackground-image: url(caniuse_files/green5x5.png), url(caniuse_files/green5x5.png), url(caniuse_files/green5x5.png), url(caniuse_files/green5x5.png), url(caniuse_files/green5x5.png), url(caniuse_files/green5x5.png);\nbackground-position: 0 0, 0 5px, 0 10px, 0 15px, 0 20px, 0 25px;</div></div>\n\n</td></tr>\n<tr><th><h3>CSS3 Multiple column layout</h3><span class=\"links\">[<a href=\"http://caniuse.com/multicolumn\">Table</a>] [<a href=\"http://tests.caniuse.com/?feat=multicolumn&prefix=all\">Single feat</a>]</span></th><td class=\"current pass\">&nbsp;<span>-pre-</span></td><td>\n<div class=\"test_wrap\"><h3>Auto (m)</h3><div id=\"multicolumn0\" class=\"auto pass\"></div><script>setResult('multicolumn0', Modernizr.csscolumns);</script><div class=\"info\">Modernizr test for: \"csscolumns\"</div></div>\n\n<div class=\"test_wrap\"><h3>Visual-square</h3><div id=\"multicolumn1\" class=\"visual-square\"></div><div class=\"square\"><div style=\"-webkit-column-width: 15px; -webkit-column-gap: 0;-moz-column-width: 15px; -moz-column-gap: 0;-ms-column-width: 15px; -ms-column-gap: 0;-o-column-width: 15px; -o-column-gap: 0;column-width: 15px; column-gap: 0; width:30px;height:30px;background:red;\">\n\t<div style=\"inline-block;width:15px;height:30px;background:lime;\"></div>\n\t<div style=\"inline-block;width:15px;height:30px;background:lime;\"></div>\n</div>\n</div><div class=\"info\">column-width: 15px;\ncolumn-gap: 0;</div></div>\n\n</td></tr>\n<tr><th><h3>Web Storage - name/value pairs</h3><span class=\"links\">[<a href=\"http://caniuse.com/namevalue-storage\">Table</a>] [<a href=\"http://tests.caniuse.com/?feat=namevalue-storage&prefix=all\">Single feat</a>]</span></th><td class=\"current pass\">&nbsp;</td><td>\n<div class=\"test_wrap\"><h3>Auto (m)</h3><div id=\"namevalue-storage0\" class=\"auto pass\"></div><script>setResult('namevalue-storage0', Modernizr.localstorage);</script><div class=\"info\">Modernizr test for: \"localstorage\"</div></div>\n\n<div class=\"test_wrap\"><h3>Auto</h3><div id=\"namevalue-storage1\" class=\"auto pass\"></div><script>\n(function() {\n\tvar result = false;\n\tif(window.localStorage) {\n\t\ttry {\n\t\t\tlocalStorage.setItem('foo', 'bar');\n\t\t\tif(localStorage.getItem('foo') === 'bar'\n\t\t\t\t&& localStorage['foo'] === 'bar'\n\t\t\t\t&& localStorage.foo === 'bar'\n\t\t\t) {\n\t\t\t\tlocalStorage.removeItem('foo');\n\t\t\t\tif(localStorage.getItem('foo') === null) {\n\t\t\t\t\tresult = true;\n\t\t\t\t}\n\t\t\t}\n\t\t} catch(e) {}\n\t}\n\tsetResult('namevalue-storage1', result);\n})();\n\n</script><div class=\"info\">Test if getItem, setItem and removeItem work.</div></div>\n\n</td></tr>\n<tr><th><h3>Web Notifications</h3><span class=\"links\">[<a href=\"http://caniuse.com/notifications\">Table</a>] [<a href=\"http://tests.caniuse.com/?feat=notifications&prefix=all\">Single feat</a>]</span></th><td class=\"current pass\">&nbsp;</td><td>\n<div class=\"test_wrap\"><h3>Auto</h3><div id=\"notifications0\" class=\"auto pass\"></div><script>\nsetResult('notifications0',\n\"webkitNotifications\" in window\n|| \"mozNotifications\" in window\n|| \"oNotifications\" in window\n|| \"msNotifications\" in window\n|| \"khtmlNotifications\" in window\n|| \"notifications\" in window\n);\n</script></div>\n\n</td></tr>\n<tr><th><h3>Offline web applications</h3><span class=\"links\">[<a href=\"http://caniuse.com/offline-apps\">Table</a>] [<a href=\"http://tests.caniuse.com/?feat=offline-apps&prefix=all\">Single feat</a>]</span></th><td class=\"current pass\">&nbsp;</td><td>\n<div class=\"test_wrap\"><h3>Auto (m)</h3><div id=\"offline-apps0\" class=\"auto pass\"></div><script>setResult('offline-apps0', Modernizr.applicationcache);</script><div class=\"info\">Modernizr test for: \"applicationcache\"</div></div>\n\n</td></tr>\n<tr><th><h3>querySelector/querySelectorAll</h3><span class=\"links\">[<a href=\"http://caniuse.com/queryselector\">Table</a>] [<a href=\"http://tests.caniuse.com/?feat=queryselector&prefix=all\">Single feat</a>]</span></th><td class=\"current pass\">&nbsp;</td><td>\n<div class=\"test_wrap\"><h3>Auto</h3><div id=\"queryselector0\" class=\"auto pass\"></div><script>\nsetResult('queryselector0', !!document.querySelectorAll && !!document.querySelector)\n</script></div>\n\n<div class=\"test_wrap\"><h3>Auto</h3><div id=\"queryselector1\" class=\"auto pass\"></div>\t<div id=\"queryselector1test\">\n\t\t<div data-foo=\"queryselector1\"></div>\n\t\t<div id=\"queryselector1target\"></div>\n\t\t<div class=\"altqueryselector1test\"></div>\n\t</div>\n<script>\n(function() {\n\tif(document.querySelector) {\n\t\tvar elem = document.querySelector('[data-foo=queryselector1] + *');\n\t\tvar target = document.getElementById('queryselector1target');\n\t\tsetResult('queryselector1', elem === target);\n\t}\n}());\n</script><div class=\"info\">querySelector test on selector '[data-foo=bar] + *'</div></div>\n\n<div class=\"test_wrap\"><h3>Auto</h3><div id=\"queryselector2\" class=\"auto pass\"></div>\t<div id=\"queryselector2test\">\n\t\t<div data-foo=\"queryselector2\"></div>\n\t\t<div id=\"queryselector2target\"></div>\n\t\t<div class=\"altqueryselector2test\"></div>\n\t</div>\n<script>\n(function() {\n\tif(document.querySelector) {\n\t\tvar elem = document.querySelector('[data-foo=queryselector2] + *');\n\t\tvar target = document.getElementById('queryselector2target');\n\t\tsetResult('queryselector2', elem === target);\n\t}\n}());\n</script><div class=\"info\">querySelectorAll test on selector '[data-foo=bar] + *'</div></div>\n\n</td></tr>\n<tr><th><h3>SVG (basic support)</h3><span class=\"links\">[<a href=\"http://caniuse.com/svg\">Table</a>] [<a href=\"http://tests.caniuse.com/?feat=svg&prefix=all\">Single feat</a>]</span></th><td class=\"current pass\">&nbsp;</td><td>\n<div class=\"test_wrap\"><h3>Auto (m)</h3><div id=\"svg0\" class=\"auto pass\"></div><script>setResult('svg0', Modernizr.svg);</script><div class=\"info\">Modernizr test for: \"svg\"</div></div>\n\n<div class=\"test_wrap\"><h3>Visual-square</h3><div id=\"svg1\" class=\"visual-square\"></div><div class=\"square\"><object type=\"image/svg+xml\" width=\"30\" height=\"30\" data=\"./caniuse_files/svg-img.svg\" style=\"overflow:visible\"> SVG fail\n</object></div><div class=\"info\">SVG in &lt;object&gt;</div></div>\n\n</td></tr>\n<tr><th><h3>SVG effects for HTML</h3><span class=\"links\">[<a href=\"http://caniuse.com/svg-html\">Table</a>] [<a href=\"http://tests.caniuse.com/?feat=svg-html&prefix=all\">Single feat</a>]</span></th><td class=\"current partial\">&nbsp;</td><td>\n\n<div class=\"test_wrap\"><h3>Visual</h3><div id=\"svg-html1\" class=\"visual\"></div><div class=\"vis_test\"> <object type=\"image/svg+xml\" width=\"60\" height=\"30\" data=\"http://tests.caniuse.com/blur-html.svg\"> SVG fail\n </object></div><div class=\"vis_ref\"><img src=\"./caniuse_files/svg-html-blur.png\"></div><p class=\"condition\">Text must appear blurry</p><div class=\"info\">SVG with feGaussianBlur filter on foreignObject</div></div>\n\n</td></tr>\n<tr><th><h3>Inline SVG in HTML5</h3><span class=\"links\">[<a href=\"http://caniuse.com/svg-html5\">Table</a>] [<a href=\"http://tests.caniuse.com/?feat=svg-html5&prefix=all\">Single feat</a>]</span></th><td class=\"current pass\">&nbsp;</td><td>\n<div class=\"test_wrap\"><h3>Auto (m)</h3><div id=\"svg-html50\" class=\"auto pass\"></div><script>setResult('svg-html50', Modernizr.inlinesvg);</script><div class=\"info\">Modernizr test for: \"inlinesvg\"</div></div>\n\n<div class=\"test_wrap\"><h3>Visual-square</h3><div id=\"svg-html51\" class=\"visual-square\"></div><div class=\"square\"><svg width=\"30\" height=\"30\" xmlns=\"http://www.w3.org/2000/svg\" style=\"background:red;\"> \n    <rect height=\"30\" width=\"30\" y=\"0\" x=\"0\" fill=\"#00ff00\"></rect> \n</svg>\n</div></div>\n\n</td></tr>\n<tr><th><h3>SVG SMIL animation</h3><span class=\"links\">[<a href=\"http://caniuse.com/svg-smil\">Table</a>] [<a href=\"http://tests.caniuse.com/?feat=svg-smil&prefix=all\">Single feat</a>]</span></th><td class=\"current pass\">&nbsp;</td><td>\n<div class=\"test_wrap\"><h3>Auto (m)</h3><div id=\"svg-smil0\" class=\"auto pass\"></div><script>setResult('svg-smil0', Modernizr.smil);</script><div class=\"info\">Modernizr test for: \"smil\"</div></div>\n\n<div class=\"test_wrap\"><h3>Visual-square</h3><div id=\"svg-smil1\" class=\"visual-square\"></div><div class=\"square\"><object type=\"image/svg+xml\" width=\"30\" height=\"30\" data=\"http://tests.caniuse.com/svg-animate.svg\" style=\"overflow:visible\"> SVG fail\n</object></div><div class=\"info\">SVG with animate element inside a rect</div></div>\n\n</td></tr>\n<tr><th><h3>Touch events</h3><span class=\"links\">[<a href=\"http://caniuse.com/touch\">Table</a>] [<a href=\"http://tests.caniuse.com/?feat=touch&prefix=all\">Single feat</a>]</span></th><td class=\"current unknown\">&nbsp;</td><td>\n<div class=\"test_wrap\"><h3>Auto (m)</h3><div id=\"touch0\" class=\"auto fail\"></div><script>setResult('touch0', Modernizr.touch);</script><div class=\"info\">Modernizr test for: \"touch\"</div></div>\n\n</td></tr>\n<tr><th><h3>CSS3 Transforms</h3><span class=\"links\">[<a href=\"http://caniuse.com/transforms2d\">Table</a>] [<a href=\"http://tests.caniuse.com/?feat=transforms2d&prefix=all\">Single feat</a>]</span></th><td class=\"current pass\">&nbsp;<span>-pre-</span></td><td>\n<div class=\"test_wrap\"><h3>Auto (m)</h3><div id=\"transforms2d0\" class=\"auto pass\"></div><script>setResult('transforms2d0', Modernizr.csstransforms);</script><div class=\"info\">Modernizr test for: \"csstransforms\"</div></div>\n\n<div class=\"test_wrap\"><h3>Visual-square</h3><div id=\"transforms2d1\" class=\"visual-square\"></div><div class=\"square\"><div style=\"width:30px;height:30px;background:red;overflow:hidden\">\n\t<div style=\"background:lime;width:30px;height:30px;position:relative;left:-30px;-webkit-transform: translate(30px);-moz-transform: translate(30px);-ms-transform: translate(30px);-o-transform: translate(30px);transform: translate(30px); \"></div>\n</div>\n</div><div class=\"info\">transform: translate(30px);</div></div>\n\n</td></tr>\n<tr><th><h3>CSS3 3D Transforms</h3><span class=\"links\">[<a href=\"http://caniuse.com/transforms3d\">Table</a>] [<a href=\"http://tests.caniuse.com/?feat=transforms3d&prefix=all\">Single feat</a>]</span></th><td class=\"current unknown\">&nbsp;</td><td>\n<div class=\"test_wrap\"><h3>Auto (m)</h3><div id=\"transforms3d0\" class=\"auto pass\"></div><script>setResult('transforms3d0', Modernizr.csstransforms3d);</script><div class=\"info\">Modernizr test for: \"csstransforms3d\"</div></div>\n\n<div class=\"test_wrap\"><h3>Visual-square</h3><div id=\"transforms3d1\" class=\"visual-square\"></div><div class=\"square\"><style>\n#transforms3d1container {\n\tbackground: red;\n\twidth: 30px;\n\theight: 30px;\n\toverflow: hidden;\n\t-webkit-perspective: 600;\n\t-webkit-perspective-origin: 0 200px;\n\t-moz-perspective: 600;\n\t-moz-perspective-origin: 0 200px;\n\t-ms-perspective: 600;\n\t-ms-perspective-origin: 0 200px;\n\t-o-perspective: 600;\n\t-o-perspective-origin: 0 200px;\n\tperspective: 600;\n\tperspective-origin: 0 200px;\n\n}\n\n#transforms3d1test { \n\twidth:400px; height:100px;\n\tbackground: lime;\n\tposition: relative;\n\ttop: 30px;\n\t-webkit-transform: translate3d(-234px, 0, 0) rotate3d(0, 1, 0, -70deg);\n\t-moz-transform: translate3d(-234px, 0, 0) rotate3d(0, 1, 0, -70deg);\n\t-ms-transform: translate3d(-234px, 0, 0) rotate3d(0, 1, 0, -70deg);\n\t-o-transform: translate3d(-234px, 0, 0) rotate3d(0, 1, 0, -70deg);\n\ttransform: translate3d(-234px, 0, 0) rotate3d(0, 1, 0, -70deg);\n\n}\n</style>\n<div id=\"transforms3d1container\">\n\t<div id=\"transforms3d1test\"></div>\n</div></div><div class=\"info\">Parent:\nperspective: 600;\nperspective-origin: 0 200px;\n\nChild:\n\ntransform: translate3d(-234px, 0, 0) rotate3d(0, 1, 0, -70deg);</div></div>\n\n</td></tr>\n<tr><th><h3>Video element</h3><span class=\"links\">[<a href=\"http://caniuse.com/video\">Table</a>] [<a href=\"http://tests.caniuse.com/?feat=video&prefix=all\">Single feat</a>]</span></th><td class=\"current pass\">&nbsp;</td><td>\n<div class=\"test_wrap\"><h3>Auto</h3><div id=\"video0\" class=\"auto pass\"></div><script>\nsetResult('video0', !!document.createElement('video').canPlayType);\n</script></div>\n\n<div class=\"test_wrap\"><h3>Interact</h3><div id=\"video1\" class=\"interact\"></div><video width=\"160\" height=\"120\" controls=\"\">\n\t<source src=\"video.mp4\" type=\"video/mp4\">\n\t<source src=\"video.ogv\" type=\"video/ogv\">\n\t<source src=\"video.webm\" type=\"video/webm\">\n</video><div class=\"info\">Video with controls and all three formats available.</div></div>\n\n<div class=\"test_wrap\"><h3>Interact</h3><div id=\"video2\" class=\"interact\"></div><video width=\"160\" height=\"120\" controls=\"\">\n\t<source src=\"mimevid.php?type=.mp4\" type=\"video/mp4\">\n\t<source src=\"mimevid.php?type=.ogv\" type=\"video/ogg\">\n\t<source src=\"mimevid.php?type=.webm\" type=\"video/webm\">\n</video><div class=\"info\">Video with controls and all three formats available (with MIME).</div></div>\n\n</td></tr>\n<tr><th><h3>Web Sockets</h3><span class=\"links\">[<a href=\"http://caniuse.com/websockets\">Table</a>] [<a href=\"http://tests.caniuse.com/?feat=websockets&prefix=all\">Single feat</a>]</span></th><td class=\"current pass\">&nbsp;</td><td>\n<div class=\"test_wrap\"><h3>Auto (m)</h3><div id=\"websockets0\" class=\"auto pass\"></div><script>setResult('websockets0', Modernizr.websockets);</script><div class=\"info\">Modernizr test for: \"websockets\"</div></div>\n\n</td></tr>\n<tr><th><h3>Web Workers</h3><span class=\"links\">[<a href=\"http://caniuse.com/webworkers\">Table</a>] [<a href=\"http://tests.caniuse.com/?feat=webworkers&prefix=all\">Single feat</a>]</span></th><td class=\"current pass\">&nbsp;</td><td>\n<div class=\"test_wrap\"><h3>Auto (m)</h3><div id=\"webworkers0\" class=\"auto pass\"></div><script>setResult('webworkers0', Modernizr.webworkers);</script><div class=\"info\">Modernizr test for: \"webworkers\"</div></div>\n\n<div class=\"test_wrap\"><h3>Auto</h3><div id=\"webworkers1\" class=\"auto pass\"></div><script>\n(function() {\n\ntry {\n\n\tvar w = new Worker('worker.js');\n\t\n\tw.onmessage = function (event) {\n\t  var success = (event.data && event.data === 'worker works');\n\t  setResult('webworkers1', success);\n\t}\n\t\n\tw.postMessage('');\n\n} catch(e) {\n\tsetResult('webworkers1', false);\n}\n\n}());\n</script><div class=\"info\">Create a new Worker using new Worker('worker.js');\n\nThen, test postMessage and onmessage event.</div></div>\n\n</td></tr>\n<tr><th><h3>Cross-document messaging</h3><span class=\"links\">[<a href=\"http://caniuse.com/x-doc-messaging\">Table</a>] [<a href=\"http://tests.caniuse.com/?feat=x-doc-messaging&prefix=all\">Single feat</a>]</span></th><td class=\"current pass\">&nbsp;</td><td>\n<div class=\"test_wrap\"><h3>Auto (m)</h3><div id=\"x-doc-messaging0\" class=\"auto pass\"></div><script>setResult('x-doc-messaging0', Modernizr.postmessage);</script><div class=\"info\">Modernizr test for: \"postmessage\"</div></div>\n\n</td></tr>\n<tr><th><h3>XMLHttpRequest 2</h3><span class=\"links\">[<a href=\"http://caniuse.com/xhr2\">Table</a>] [<a href=\"http://tests.caniuse.com/?feat=xhr2&prefix=all\">Single feat</a>]</span></th><td class=\"current pass\">&nbsp;</td><td>\n<div class=\"test_wrap\"><h3>Auto</h3><div id=\"xhr20\" class=\"auto pass\"></div><script>\nvar progEv = !!(window.ProgressEvent);\nvar fdata = !!(window.FormData);\nsetResult('xhr20', (progEv && fdata));\n</script></div>\n\n</td></tr>\n<tr><th><h3>XHTML served as application/xhtml+xml</h3><span class=\"links\">[<a href=\"http://caniuse.com/xhtml\">Table</a>] [<a href=\"http://tests.caniuse.com/?feat=xhtml&prefix=all\">Single feat</a>]</span></th><td class=\"current pass\">&nbsp;</td><td>\n<div class=\"test_wrap\"><h3>Auto</h3><div id=\"xhtml0\" class=\"auto pass\"></div><iframe src=\"./caniuse_files/xhtml.html\" width=\"15\" height=\"15\" style=\"display:none\"></iframe></div>\n\n</td></tr>\n<tr><th><h3>CSS Generated content</h3><span class=\"links\">[<a href=\"http://caniuse.com/css-gencontent\">Table</a>] [<a href=\"http://tests.caniuse.com/?feat=css-gencontent&prefix=all\">Single feat</a>]</span></th><td class=\"current pass\">&nbsp;</td><td>\n<div class=\"test_wrap\"><h3>Visual</h3><div id=\"css-gencontent0\" class=\"visual\"></div><div class=\"vis_test\"><style>\n#gencontent:before {\n content: 'A';\n}\n#gencontent:after {\n content: 'Z';\n}\n</style>\n<span id=\"gencontent\">-</span></div><div class=\"vis_ref\"><img src=\"./caniuse_files/before-after.png\"></div><div class=\"info\">Element with CSS: \n#gencontent:before {\n content: 'A';\n}\n#gencontent:after {\n content: 'Z';\n}</div></div>\n\n</td></tr>\n<tr><th><h3>CSS Table display</h3><span class=\"links\">[<a href=\"http://caniuse.com/css-table\">Table</a>] [<a href=\"http://tests.caniuse.com/?feat=css-table&prefix=all\">Single feat</a>]</span></th><td class=\"current pass\">&nbsp;</td><td>\n<div class=\"test_wrap\"><h3>Visual</h3><div id=\"css-table0\" class=\"visual\"></div><div class=\"vis_test\"><style>\n#table-test { display: table; }\n#table-test .table-tr { display: table-row; }\n#table-test .table-td { display: table-cell;border:1px solid; }\n</style>\n<div style=\"display:inline-block;vertical-align:middle\">\n<div id=\"table-test\">\n\t<div class=\"table-tr\">\n\t\t<div class=\"table-td\">topleft</div>\n\t\t<div class=\"table-td\">topright</div>\n\t</div>\n\t<div class=\"table-tr\">\n\t\t<div class=\"table-td\">bottomleft</div>\n\t\t<div class=\"table-td\">bottomright</div>\n\t</div>\n</div>\n</div></div><div class=\"vis_ref\"><img src=\"./caniuse_files/table.png\"></div><p class=\"condition\">Should be 2x2 table</p></div>\n\n</td></tr>\n<tr><th><h3>HTML5 form features</h3><span class=\"links\">[<a href=\"http://caniuse.com/forms\">Table</a>] [<a href=\"http://tests.caniuse.com/?feat=forms&prefix=all\">Single feat</a>]</span></th><td class=\"current partial\">&nbsp;</td><td>\n<div class=\"test_wrap\"><h3>Visual</h3><div id=\"forms0\" class=\"visual\"></div><div class=\"vis_test\"><input type=\"date\"><br><input type=\"time\"><br><input type=\"range\"><br><input type=\"number\"></div><p class=\"condition\">date/time/range/number widgets</p></div>\n\n</td></tr>\n<tr><th><h3>MathML</h3><span class=\"links\">[<a href=\"http://caniuse.com/mathml\">Table</a>] [<a href=\"http://tests.caniuse.com/?feat=mathml&prefix=all\">Single feat</a>]</span></th><td class=\"current unknown\">&nbsp;</td><td>\n<div class=\"test_wrap\"><h3>Visual</h3><div id=\"mathml0\" class=\"visual\"></div><div class=\"vis_test\"><iframe src=\"./caniuse_files/mathml.html\" width=\"210\" height=\"110\" style=\"border:0;\"></iframe></div><div class=\"vis_ref\"><img src=\"./caniuse_files/mathml_ref.png\"></div></div>\n\n</td></tr>\n<tr><th><h3>PNG alpha transparency</h3><span class=\"links\">[<a href=\"http://caniuse.com/png-alpha\">Table</a>] [<a href=\"http://tests.caniuse.com/?feat=png-alpha&prefix=all\">Single feat</a>]</span></th><td class=\"current pass\">&nbsp;</td><td>\n<div class=\"test_wrap\"><h3>Visual</h3><div id=\"png-alpha0\" class=\"visual\"></div><div class=\"vis_test\"><img src=\"./caniuse_files/alpha.png\" style=\"background-color:lime\"></div><div class=\"vis_ref\"><img src=\"./caniuse_files/png_alpha_result.png\"></div></div>\n\n</td></tr>\n<tr><th><h3>Ruby annotation</h3><span class=\"links\">[<a href=\"http://caniuse.com/ruby\">Table</a>] [<a href=\"http://tests.caniuse.com/?feat=ruby&prefix=all\">Single feat</a>]</span></th><td class=\"current partial\">&nbsp;</td><td>\n<div class=\"test_wrap\"><h3>Visual</h3><div id=\"ruby0\" class=\"visual\"></div><div class=\"vis_test\">\n<div style=\"display:inline-block;vertical-align:middle\">\n<ruby>(bottom1)<rt>(top1)</rt>(bottom2)<rt>(top2)</rt></ruby>\n</div></div><div class=\"vis_ref\"><img src=\"./caniuse_files/ruby.png\"></div><p class=\"condition\">Elements should be stacked on top of each other</p></div>\n\n</td></tr>\n<tr><th><h3>SVG filters</h3><span class=\"links\">[<a href=\"http://caniuse.com/svg-filters\">Table</a>] [<a href=\"http://tests.caniuse.com/?feat=svg-filters&prefix=all\">Single feat</a>]</span></th><td class=\"current pass\">&nbsp;</td><td>\n<div class=\"test_wrap\"><h3>Visual</h3><div id=\"svg-filters0\" class=\"visual\"></div><div class=\"vis_test\"><object data=\"http://tests.caniuse.com/blur.svg\" type=\"image/svg+xml\" height=\"70\" width=\"70\">\n\tobject SVG not supported\n</object>\n</div><div class=\"vis_ref\"><img src=\"./caniuse_files/svg_blur.png\"></div></div>\n\n<div class=\"test_wrap\"><h3>Visual-square</h3><div id=\"svg-filters1\" class=\"visual-square\"></div><div class=\"square\"><object type=\"image/svg+xml\" width=\"30\" height=\"30\" data=\"http://tests.caniuse.com/fecolormatrix.svg\" style=\"overflow:visible\"> SVG fail\n</object></div><p class=\"condition\">Must be green (not lime)</p><div class=\"info\">SVG with &lt;feColorMatrix type=\"hueRotate\" values=\"120\"/&gt;</div></div>\n\n<div class=\"test_wrap\"><h3>Visual-square</h3><div id=\"svg-filters2\" class=\"visual-square\"></div><div class=\"square\"><object type=\"image/svg+xml\" width=\"30\" height=\"30\" data=\"http://tests.caniuse.com/feflood.svg\" style=\"overflow:visible\"> SVG fail\n</object></div><div class=\"info\">SVG with &lt;feFlood flood-color=\"lime\"/&gt;</div></div>\n\n</td></tr>\n<tr><th><h3>CSS3 Word-wrap</h3><span class=\"links\">[<a href=\"http://caniuse.com/wordwrap\">Table</a>] [<a href=\"http://tests.caniuse.com/?feat=wordwrap&prefix=all\">Single feat</a>]</span></th><td class=\"current pass\">&nbsp;</td><td>\n<div class=\"test_wrap\"><h3>Visual</h3><div id=\"wordwrap0\" class=\"visual\"></div><div class=\"vis_test\"><style>\n#wordwraptest {\n  display: inline-block;\n  width: 30px;\n  word-wrap: break-word;\n}\n\n</style>\n<div id=\"wordwraptest\">abcdefghijklmnopqrstuvwxyz</div>\n\n\n</div><p class=\"condition\">Text should wrap</p></div>\n\n<div class=\"test_wrap\"><h3>Visual</h3><div id=\"wordwrap1\" class=\"visual\"></div><div class=\"vis_test\"><style>\n#wordwraptest2 {\n  display: inline-block;\n  width: 30px;\n  word-wrap: normal;\n}\n</style>\n\n<div id=\"wordwraptest2\">abcdefghijklmnopqrstuvwxyz</div>\n</div><p class=\"condition\">Text should overflow box</p></div>\n\n<div class=\"test_wrap\"><h3>Visual-square</h3><div id=\"wordwrap2\" class=\"visual-square\"></div><div class=\"square\"><div style=\"width:30px;height:30px;background:red;overflow:hidden\">\n\t<div style=\"color:lime;font-size:10px;line-height:10px;word-wrap:break-word;background:lime;\">abcdefghijklmnop</div>\n</div>\n</div><div class=\"info\">word-wrap: break-word;</div></div>\n\n</td></tr>\n<tr><th><h3>calc() as CSS unit value</h3><span class=\"links\">[<a href=\"http://caniuse.com/calc\">Table</a>] [<a href=\"http://tests.caniuse.com/?feat=calc&prefix=all\">Single feat</a>]</span></th><td class=\"current unknown\">&nbsp;</td><td>\n<div class=\"test_wrap\"><h3>Visual-square</h3><div id=\"calc0\" class=\"visual-square\"></div><div class=\"square\"><style>\n#calc0test {\n\twidth: 0px;\n\twidth: -webkit-calc(10px + 20px);\n\twidth: -moz-calc(10px + 20px);\n\twidth: -ms-calc(10px + 20px);\n\twidth: -o-calc(10px + 20px);\n\twidth: calc(10px + 20px);\n\theight: 30px;\n\tbackground: lime;\n}\n</style>\n<div id=\"calc0test\"></div>\n</div><div class=\"info\">width: calc(10px + 20px);</div></div>\n\n<div class=\"test_wrap\"><h3>Visual-square</h3><div id=\"calc2\" class=\"visual-square\"></div><div class=\"square\"><style>\n#calc2test {\nheight:-webkit-calc(60px - 100%); width:-webkit-calc((100% / 2) + 15px - 0.5em); border-right:-webkit-calc(0.5em) solid lime;\nheight:-moz-calc(60px - 100%); width:-moz-calc((100% / 2) + 15px - 0.5em); border-right:-moz-calc(0.5em) solid lime;\nheight:-ms-calc(60px - 100%); width:-ms-calc((100% / 2) + 15px - 0.5em); border-right:-ms-calc(0.5em) solid lime;\nheight:-o-calc(60px - 100%); width:-o-calc((100% / 2) + 15px - 0.5em); border-right:-o-calc(0.5em) solid lime;\nheight:calc(60px - 100%); width:calc((100% / 2) + 15px - 0.5em); border-right:calc(0.5em) solid lime;\n\nbackground: lime;\n}\n</style>\n<div id=\"calc2test\"></div>\n</div><div class=\"info\">height: calc(60px - 100%);\nwidth: calc((100% / 2) + 15px - 0.5em);\nborder-right: calc(0.5em) solid lime;</div></div>\n\n</td></tr>\n<tr><th><h3>CSS Grid Layout</h3><span class=\"links\">[<a href=\"http://caniuse.com/css-grid\">Table</a>] [<a href=\"http://tests.caniuse.com/?feat=css-grid&prefix=all\">Single feat</a>]</span></th><td class=\"current unknown\">&nbsp;</td><td>\n<div class=\"test_wrap\"><h3>Visual-square</h3><div id=\"css-grid0\" class=\"visual-square\"></div><div class=\"square\"><style>\n#css-grid0grid {\n\tdisplay: -webkit-grid; \tdisplay: -moz-grid; \tdisplay: -ms-grid; \tdisplay: -o-grid; \tdisplay: grid; \n\t-webkit-grid-columns: 15px 1fr; \t-moz-grid-columns: 15px 1fr; \t-ms-grid-columns: 15px 1fr; \t-o-grid-columns: 15px 1fr; \tgrid-columns: 15px 1fr; \n\t-webkit-grid-rows: 15px 15px; \t-moz-grid-rows: 15px 15px; \t-ms-grid-rows: 15px 15px; \t-o-grid-rows: 15px 15px; \tgrid-rows: 15px 15px; \n\n}\n\n#css-grid0grid > div {\n\tbackground: lime;\n}\n\n#css-grid0a {\n\t-webkit-grid-row: 1; \t-moz-grid-row: 1; \t-ms-grid-row: 1; \t-o-grid-row: 1; \tgrid-row: 1; \n\t-webkit-grid-column: 1; \t-moz-grid-column: 1; \t-ms-grid-column: 1; \t-o-grid-column: 1; \tgrid-column: 1; \n}\n\n#css-grid0b {\n\t-webkit-grid-row: 1; \t-moz-grid-row: 1; \t-ms-grid-row: 1; \t-o-grid-row: 1; \tgrid-row: 1; \n\t-webkit-grid-column: 2; \t-moz-grid-column: 2; \t-ms-grid-column: 2; \t-o-grid-column: 2; \tgrid-column: 2; \n}\n\n#css-grid0c {\n\t-webkit-grid-row: 2; \t-moz-grid-row: 2; \t-ms-grid-row: 2; \t-o-grid-row: 2; \tgrid-row: 2; \n\t-webkit-grid-column: 1; \t-moz-grid-column: 1; \t-ms-grid-column: 1; \t-o-grid-column: 1; \tgrid-column: 1; \n\t-webkit-grid-column-span: 2; \t-moz-grid-column-span: 2; \t-ms-grid-column-span: 2; \t-o-grid-column-span: 2; \tgrid-column-span: 2; \n}\n</style>\n\n<div id=\"css-grid0grid\">\n\t <div id=\"css-grid0a\"></div>\n\t <div id=\"css-grid0b\"></div>\n\t <div id=\"css-grid0c\"></div>\n</div>\n\n</div><div class=\"info\">Grid with two columns, two rows and three elements taking up space.</div></div>\n\n</td></tr>\n<tr><th><h3>CSS3 Media Queries</h3><span class=\"links\">[<a href=\"http://caniuse.com/css-mediaqueries\">Table</a>] [<a href=\"http://tests.caniuse.com/?feat=css-mediaqueries&prefix=all\">Single feat</a>]</span></th><td class=\"current pass\">&nbsp;</td><td>\n<div class=\"test_wrap\"><h3>Visual-square</h3><div id=\"css-mediaqueries0\" class=\"visual-square\"></div><div class=\"square\"><style>\n#mediaq1,#mediaq2,#mediaq3,#mediaq4 {\n background: red;\n float: left;\n width: 15px;\n height: 15px;\n}\n\n#mediaq3 {\n\tclear: left;\n}\n\n@media all and (min-width: 0px) {\n #mediaq1, #mediaq3 { background: lime; }\n}\n\n@media all and (max-width: 999999px) {\n #mediaq2, #mediaq4 { background: lime; }\n}\n\n\n@media all and (min-width: 999999px) {\n #mediaq3 { background: red; }\n}\n\n@media all and (max-width: 0px) {\n #mediaq4 { background: red; }\n}\n\n</style>\n\n<div id=\"mediaq1\"></div>\n<div id=\"mediaq2\"></div>\n<div id=\"mediaq3\"></div>\n<div id=\"mediaq4\"></div></div></div>\n\n</td></tr>\n<tr><th><h3>CSS 2.1 selectors</h3><span class=\"links\">[<a href=\"http://caniuse.com/css-sel2\">Table</a>] [<a href=\"http://tests.caniuse.com/?feat=css-sel2&prefix=all\">Single feat</a>]</span></th><td class=\"current pass\">&nbsp;</td><td>\n<div class=\"test_wrap\"><h3>Visual-square</h3><div id=\"css-sel20\" class=\"visual-square\"></div><div class=\"square\"><style>\n#css-sel20test div {\n\twidth: 30px;\n\theight: 30px;\n\tbackground: red;\n}\n\n#css-sel20test > div {\n\tbackground: lime;\n}\n</style>\n<div id=\"css-sel20test\">\n\t<div></div>\n</div>\n</div><div class=\"info\">Test for child ( &gt; )selector</div></div>\n\n<div class=\"test_wrap\"><h3>Visual-square</h3><div id=\"css-sel21\" class=\"visual-square\"></div><div class=\"square\"><style>\n#css-sel21test + div { background: lime; width:30px; height:30px;}\n</style>\n<div id=\"css-sel21test\"></div>\n<div></div>\n</div><div class=\"info\">Adjacent sibling selector test ( + )</div></div>\n\n<div class=\"test_wrap\"><h3>Visual-square</h3><div id=\"css-sel22\" class=\"visual-square\"></div><div class=\"square\"><style>\n#css-sel22test[role=\"none\"] { background: lime; width:30px; height:30px;}\n</style>\n<div id=\"css-sel22test\" role=\"none\"></div></div><div class=\"info\">Attribute selector ( [role=\"none\"] )</div></div>\n\n</td></tr>\n<tr><th><h3>CSS3 Box-sizing</h3><span class=\"links\">[<a href=\"http://caniuse.com/css3-boxsizing\">Table</a>] [<a href=\"http://tests.caniuse.com/?feat=css3-boxsizing&prefix=all\">Single feat</a>]</span></th><td class=\"current pass\">&nbsp;</td><td>\n<div class=\"test_wrap\"><h3>Visual-square</h3><div id=\"css3-boxsizing0\" class=\"visual-square\"></div><div class=\"square\"><style>\n#boxsizetest {\n   -webkit-box-sizing: border-box;\n-moz-box-sizing: border-box;\n-ms-box-sizing: border-box;\n-o-box-sizing: border-box;\nbox-sizing: border-box;\n    background: red;\n    border-left: 30px solid lime;\n    display: inline-block;\n    height: 30px;\n    width: 30px;\n}\n</style>\n<div id=\"boxsizetest\"></div>\n</div></div>\n\n</td></tr>\n<tr><th><h3>Data URLs</h3><span class=\"links\">[<a href=\"http://caniuse.com/datauri\">Table</a>] [<a href=\"http://tests.caniuse.com/?feat=datauri&prefix=all\">Single feat</a>]</span></th><td class=\"current pass\">&nbsp;</td><td>\n<div class=\"test_wrap\"><h3>Visual-square</h3><div id=\"datauri0\" class=\"visual-square\"></div><div class=\"square\"><div style=\"background-image: url(&#39;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAMAAAAoyzS7AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAAZQTFRFAP8AAAAAbwN%2BQwAAAAxJREFUeNpiYAAIMAAAAgABT21Z4QAAAABJRU5ErkJggg%3D%3D&#39;);width:30px;height:30px;\"></div></div><div class=\"info\">div with data URL as background image</div></div>\n\n</td></tr>\n<tr><th><h3>New semantic elements</h3><span class=\"links\">[<a href=\"http://caniuse.com/html5semantic\">Table</a>] [<a href=\"http://tests.caniuse.com/?feat=html5semantic&prefix=all\">Single feat</a>]</span></th><td class=\"current pass\">&nbsp;</td><td>\n<div class=\"test_wrap\"><h3>Visual-square</h3><div id=\"html5semantic0\" class=\"visual-square\"></div><div class=\"square\"><style>\n#html5semantic0test {\n\twidth: 30px;\n\theight: 30px;\n\tbackground: red;\n}\n\n#html5semantic0test * {\n\tbackground: lime;\n\theight: 4px;\n}\n\n#html5semantic0test section {\n\theight: 6px;\n}\n</style>\n\n<div id=\"html5semantic0test\">\n\t<section></section>\n\t<article></article>\n\t<aside></aside>\n\t<hgroup></hgroup>\n\t<header></header>\n\t<footer></footer>\n\t<nav></nav>\n</div></div><div class=\"info\">section, article, aside, hgroup, header, footer, nav tested for default \"block\" style.</div></div>\n\n</td></tr>\n<tr><th><h3>CSS inline-block</h3><span class=\"links\">[<a href=\"http://caniuse.com/inline-block\">Table</a>] [<a href=\"http://tests.caniuse.com/?feat=inline-block&prefix=all\">Single feat</a>]</span></th><td class=\"current pass\">&nbsp;</td><td>\n<div class=\"test_wrap\"><h3>Visual-square</h3><div id=\"inline-block0\" class=\"visual-square\"></div><div class=\"square\"><div style=\"background:lime;display:inline-block;width:15px;height:30px;\"></div><div style=\"background:lime;display:inline-block;width:15px;height:30px;\"></div></div></div>\n\n</td></tr>\n<tr><th><h3>CSS min/max-width/height</h3><span class=\"links\">[<a href=\"http://caniuse.com/minmaxwh\">Table</a>] [<a href=\"http://tests.caniuse.com/?feat=minmaxwh&prefix=all\">Single feat</a>]</span></th><td class=\"current pass\">&nbsp;</td><td>\n<div class=\"test_wrap\"><h3>Visual-square</h3><div id=\"minmaxwh0\" class=\"visual-square\"></div><div class=\"square\"><div style=\"width:200%;max-width:30px;height:30px;overflow:visible;background:lime\"></div></div></div>\n\n<div class=\"test_wrap\"><h3>Visual-square</h3><div id=\"minmaxwh1\" class=\"visual-square\"></div><div class=\"square\"><div style=\"width:0;min-width:30px;height:30px;background:lime\"></div></div></div>\n\n<div class=\"test_wrap\"><h3>Visual-square</h3><div id=\"minmaxwh2\" class=\"visual-square\"></div><div class=\"square\"><div style=\"height:100px;max-height:30px;width:30px;background:lime\"></div></div></div>\n\n<div class=\"test_wrap\"><h3>Visual-square</h3><div id=\"minmaxwh3\" class=\"visual-square\"></div><div class=\"square\"><div style=\"height:0;min-height:30px;width:30px;background:lime\"></div></div></div>\n\n</td></tr>\n<tr><th><h3>CSS3 object-fit/object-position</h3><span class=\"links\">[<a href=\"http://caniuse.com/object-fit\">Table</a>] [<a href=\"http://tests.caniuse.com/?feat=object-fit&prefix=all\">Single feat</a>]</span></th><td class=\"current unknown\">&nbsp;</td><td>\n<div class=\"test_wrap\"><h3>Visual-square</h3><div id=\"object-fit0\" class=\"visual-square\"></div><div class=\"square\"><style>\n#object-fit0test {\n\twidth: 30px;\n\theight: 30px;\n\tbackground: lime;\n\toverflow: hidden;\n}\n\n#object-fit0test img {\n\t-webkit-object-fit: contain;\n-moz-object-fit: contain;\n-ms-object-fit: contain;\n-o-object-fit: contain;\nobject-fit: contain;\n\n}\n</style>\n\n<div id=\"object-fit0test\">\n\t<img src=\"./caniuse_files/red30x30.png\" width=\"90\" height=\"30\">\n</div></div><div class=\"info\">object-fit: contain</div></div>\n\n<div class=\"test_wrap\"><h3>Visual-square</h3><div id=\"object-fit2\" class=\"visual-square\"></div><div class=\"square\"><style>\n#object-fit2test {\n\twidth: 30px;\n\theight: 30px;\n\tbackground: lime;\n\toverflow: hidden;\n}\n\n#object-fit2test img {\n\t-webkit-object-position: 30px 30px;\n-moz-object-position: 30px 30px;\n-ms-object-position: 30px 30px;\n-o-object-position: 30px 30px;\nobject-position: 30px 30px;\n\n}\n</style>\n\n<div id=\"object-fit2test\">\n\t<img src=\"./caniuse_files/red30x30.png\" width=\"30\" height=\"30\">\n</div>\n</div><div class=\"info\">object-position: 30px 30px;</div></div>\n\n</td></tr>\n<tr><th><h3>rem (root em) units</h3><span class=\"links\">[<a href=\"http://caniuse.com/rem\">Table</a>] [<a href=\"http://tests.caniuse.com/?feat=rem&prefix=all\">Single feat</a>]</span></th><td class=\"current pass\">&nbsp;</td><td>\n<div class=\"test_wrap\"><h3>Visual-square</h3><div id=\"rem0\" class=\"visual-square\"></div><div class=\"square\"><div style=\"background:red;width:30px;height:30px;position:relative;overflow:hidden;text-align:left\">\n\t<span style=\"font-size:1px;background:lime;color:lime;position:relative;left:-6px;line-height:30px;font-size:5rem;\">A</span>\n</div></div><div class=\"info\">span with single character and font-size: 5rem;</div></div>\n\n</td></tr>\n<tr><th><h3>SVG in CSS backgrounds</h3><span class=\"links\">[<a href=\"http://caniuse.com/svg-css\">Table</a>] [<a href=\"http://tests.caniuse.com/?feat=svg-css&prefix=all\">Single feat</a>]</span></th><td class=\"current pass\">&nbsp;</td><td>\n<div class=\"test_wrap\"><h3>Visual-square</h3><div id=\"svg-css0\" class=\"visual-square\"></div><div class=\"square\"><div style=\"width:30px;height:30px;background-image: url(caniuse_files/svg-img.svg)\"></div>\n\n</div></div>\n\n</td></tr>\n<tr><th><h3>SVG in HTML img element</h3><span class=\"links\">[<a href=\"http://caniuse.com/svg-img\">Table</a>] [<a href=\"http://tests.caniuse.com/?feat=svg-img&prefix=all\">Single feat</a>]</span></th><td class=\"current pass\">&nbsp;</td><td>\n<div class=\"test_wrap\"><h3>Visual-square</h3><div id=\"svg-img0\" class=\"visual-square\"></div><div class=\"square\"><img src=\"./caniuse_files/svg-img.svg\" width=\"30\" height=\"30\"></div></div>\n\n</td></tr>\n<tr><th><h3>contenteditable attribute (basic support)</h3><span class=\"links\">[<a href=\"http://caniuse.com/contenteditable\">Table</a>] [<a href=\"http://tests.caniuse.com/?feat=contenteditable&prefix=all\">Single feat</a>]</span></th><td class=\"current pass\">&nbsp;</td><td>\n<div class=\"test_wrap\"><h3>Interact</h3><div id=\"contenteditable0\" class=\"interact\"></div><div contenteditable=\"true\">\n<p>This element should be editable.</p>\n</div><div class=\"info\">Div element with attribute  contenteditable=\"true\"</div></div>\n\n</td></tr>\n<tr><th><h3>CSS3 selectors</h3><span class=\"links\">[<a href=\"http://caniuse.com/css-sel3\">Table</a>] [<a href=\"http://tests.caniuse.com/?feat=css-sel3&prefix=all\">Single feat</a>]</span></th><td class=\"current pass\">&nbsp;</td><td>\n<div class=\"test_wrap\"><h3>Interact</h3><div id=\"css-sel30\" class=\"interact\"></div><a href=\"http://tools.css3.info/selectors-test/test.html\" target=\"_blank\">Test here</a></div>\n\n</td></tr>\n<tr><th><h3>Drag and Drop</h3><span class=\"links\">[<a href=\"http://caniuse.com/dragndrop\">Table</a>] [<a href=\"http://tests.caniuse.com/?feat=dragndrop&prefix=all\">Single feat</a>]</span></th><td class=\"current pass\">&nbsp;</td><td>\n<div class=\"test_wrap\"><h3>Interact</h3><div id=\"dragndrop0\" class=\"interact\"></div><a href=\"http://html5demos.com/drag\">Test here</a></div>\n\n</td></tr>\n<tr><th><h3>WAI-ARIA Accessibility features</h3><span class=\"links\">[<a href=\"http://caniuse.com/wai-aria\">Table</a>] [<a href=\"http://tests.caniuse.com/?feat=wai-aria&prefix=all\">Single feat</a>]</span></th><td class=\"current partial\">&nbsp;</td><td>\n\n</td></tr>\n<tr><th><h3>Text API for Canvas</h3><span class=\"links\">[<a href=\"http://caniuse.com/canvas-text\">Table</a>] [<a href=\"http://tests.caniuse.com/?feat=canvas-text&prefix=all\">Single feat</a>]</span></th><td class=\"current pass\">&nbsp;</td><td>\n<div class=\"test_wrap\"><h3>Auto (m)</h3><div id=\"canvas-text0\" class=\"auto pass\"></div><script>setResult('canvas-text0', Modernizr.canvastext);</script><div class=\"info\">Modernizr test for: \"canvastext\"</div></div>\n\n</td></tr>\n<tr><th><h3>WebGL - 3D Canvas graphics</h3><span class=\"links\">[<a href=\"http://caniuse.com/webgl\">Table</a>] [<a href=\"http://tests.caniuse.com/?feat=webgl&prefix=all\">Single feat</a>]</span></th><td class=\"current partial\">&nbsp;</td><td>\n<div class=\"test_wrap\"><h3>Auto (m)</h3><div id=\"webgl0\" class=\"auto pass\"></div><script>setResult('webgl0', Modernizr.webgl);</script><div class=\"info\">Modernizr test for: \"webgl\"</div></div>\n\n<div class=\"test_wrap\"><h3>Visual-square</h3><div id=\"webgl1\" class=\"visual-square\"></div><div class=\"square\"><canvas width=\"30\" height=\"30\" style=\"background:red;\" id=\"webgl_canvas\"></canvas>\n<script>\nvar elem  = $('#webgl_canvas')[0], g;\ntry {\n    g     = elem.getContext && elem.getContext('experimental-webgl');\n} catch(e){};\n\nif (g){    \n  g.clearColor(0,1,0,1);\n  g.clear(g.COLOR_BUFFER_BIT);\n}\n</script>\n</div></div>\n\n</td></tr>\n<tr><th><h3>SVG fonts</h3><span class=\"links\">[<a href=\"http://caniuse.com/svg-fonts\">Table</a>] [<a href=\"http://tests.caniuse.com/?feat=svg-fonts&prefix=all\">Single feat</a>]</span></th><td class=\"current pass\">&nbsp;</td><td>\n<div class=\"test_wrap\"><h3>Visual</h3><div id=\"svg-fonts0\" class=\"visual\"></div><div class=\"vis_test\"><style>\n@font-face { \n  font-family: Windsong_svg; \n  src: url(caniuse_files/Windsong-webfont.svg#webfontuOn4Eelr) format(\"svg\");\n}\n#windsong_svg {\n\tfont: 18px Windsong_svg;\n\tmargin: 5px;\n}\n</style>\n<p id=\"windsong_svg\">Windsong font</p>\n</div><div class=\"vis_ref\"><img src=\"./caniuse_files/windsong_font.png\"></div></div>\n\n</td></tr>\n<tr><th><h3>TTF/OTF - TrueType and OpenType font support</h3><span class=\"links\">[<a href=\"http://caniuse.com/ttf\">Table</a>] [<a href=\"http://tests.caniuse.com/?feat=ttf&prefix=all\">Single feat</a>]</span></th><td class=\"current pass\">&nbsp;</td><td>\n<div class=\"test_wrap\"><h3>Visual</h3><div id=\"ttf0\" class=\"visual\"></div><div class=\"vis_test\"><style>\n@font-face {\n\tfont-family: 'Windsong_otf';\n\tsrc: url('caniuse_files/Windsong-webfont.otf');\n}\n\n#windsong_otf {\n\tfont: 18px Windsong_otf;\n\tmargin: 5px;\n}\n</style>\n<p id=\"windsong_otf\">Windsong font</p>\n</div><div class=\"vis_ref\"><img src=\"./caniuse_files/windsong_font.png\"></div><div class=\"info\">OTF font test</div></div>\n\n<div class=\"test_wrap\"><h3>Visual</h3><div id=\"ttf1\" class=\"visual\"></div><div class=\"vis_test\"><style>\n@font-face {\n\tfont-family: 'Windsong_ttf';\n\tsrc: url('caniuse_files/Windsong-webfont.ttf');\n}\n\n#windsong_ttf {\n\tfont: 18px Windsong_ttf;\n\tmargin: 5px;\n}\n</style>\n<p id=\"windsong_ttf\">Windsong font</p>\n</div><div class=\"vis_ref\"><img src=\"./caniuse_files/windsong_font.png\"></div><div class=\"info\">TTF font test</div></div>\n\n</td></tr>\n<tr><th><h3>WOFF - Web Open Font Format</h3><span class=\"links\">[<a href=\"http://caniuse.com/woff\">Table</a>] [<a href=\"http://tests.caniuse.com/?feat=woff&prefix=all\">Single feat</a>]</span></th><td class=\"current pass\">&nbsp;</td><td>\n<div class=\"test_wrap\"><h3>Visual</h3><div id=\"woff0\" class=\"visual\"></div><div class=\"vis_test\"><style>\n@font-face {\n\tfont-family: 'Windsong_woff';\n\tsrc: url('caniuse_files/Windsong-webfont.woff');\n}\n\n#windsong_woff {\n\tfont: 18px Windsong_woff;\n\tmargin: 5px;\n}\n</style>\n<p id=\"windsong_woff\">Windsong font</p>\n</div><div class=\"vis_ref\"><img src=\"./caniuse_files/windsong_font.png\"></div></div>\n\n</td></tr>\n<tr><th><h3>Progress &amp; Meter</h3><span class=\"links\">[<a href=\"http://caniuse.com/progressmeter\">Table</a>] [<a href=\"http://tests.caniuse.com/?feat=progressmeter&prefix=all\">Single feat</a>]</span></th><td class=\"current pass\">&nbsp;</td><td>\n<div class=\"test_wrap\"><h3>Visual</h3><div id=\"progressmeter0\" class=\"visual\"></div><div class=\"vis_test\"><div style=\"display:inline-block;vertical-align:middle\">\n<progress value=\"5\" max=\"10\">fail</progress>\n<meter value=\"5\" max=\"10\">fail</meter>\n</div></div><p class=\"condition\">Progress and meter widgets at 50%</p></div>\n\n</td></tr>\n<tr><th><h3>Datalist element</h3><span class=\"links\">[<a href=\"http://caniuse.com/datalist\">Table</a>] [<a href=\"http://tests.caniuse.com/?feat=datalist&prefix=all\">Single feat</a>]</span></th><td class=\"current unknown\">&nbsp;</td><td>\n<div class=\"test_wrap\"><h3>Interact</h3><div id=\"datalist0\" class=\"interact\"></div><input type=\"text\" list=\"mydatalist\">\n<datalist id=\"mydatalist\">\n<option value=\"foo\">foo</option>\n<option value=\"bar\">bar</option>\n<option value=\"foobar\">foobar</option>\n</datalist><p class=\"condition\">Show \"foo\" and \"foobar\" as options when \"f\" is entered</p></div>\n\n</td></tr>\n<tr><th><h3>Form validation</h3><span class=\"links\">[<a href=\"http://caniuse.com/form-validation\">Table</a>] [<a href=\"http://tests.caniuse.com/?feat=form-validation&prefix=all\">Single feat</a>]</span></th><td class=\"current pass\">&nbsp;</td><td>\n<div class=\"test_wrap\"><h3>Interact</h3><div id=\"form-validation0\" class=\"interact\"></div><iframe src=\"./caniuse_files/form_validation.html\" width=\"300\" height=\"80\"></iframe><p class=\"condition\">Form should show warning and NOT submit</p></div>\n\n</td></tr>\n<tr><th><h3>MPEG-4/H.264 video format</h3><span class=\"links\">[<a href=\"http://caniuse.com/mpeg4\">Table</a>] [<a href=\"http://tests.caniuse.com/?feat=mpeg4&prefix=all\">Single feat</a>]</span></th><td class=\"current fail\">&nbsp;</td><td>\n<div class=\"test_wrap\"><h3>Auto</h3><div id=\"mpeg40\" class=\"auto pass\"></div><script>\nvar v = document.createElement('video'); \nsetResult('mpeg40', !!(v.canPlayType && v.canPlayType('video/mp4; codecs=\"avc1.42E01E, mp4a.40.2\"').replace(/no/, '')));\n</script></div>\n\n<div class=\"test_wrap\"><h3>Interact</h3><div id=\"mpeg41\" class=\"interact\"></div><video src=\"video.mp4\" width=\"160\" height=\"120\" controls=\"\">fail</video><div class=\"info\">Video, no MIME, no type attribute.</div></div>\n\n<div class=\"test_wrap\"><h3>Interact</h3><div id=\"mpeg42\" class=\"interact\"></div><video width=\"160\" height=\"120\" controls=\"\">\n <source src=\"video.mp4\" type=\"video/ogg; codecs=&quot;theora, vorbis&quot;\">\n</video><div class=\"info\">Video with source element</div></div>\n\n<div class=\"test_wrap\"><h3>Interact</h3><div id=\"mpeg43\" class=\"interact\"></div><video width=\"160\" height=\"120\" controls=\"\">\n <source src=\"mimevid.php?type=.mp4\" type=\"video/mp4; codecs=&quot;avc1.42E01E, mp4a.40.2&quot;\">\n</video><div class=\"info\">Video with source element and MIME set</div></div>\n\n</td></tr>\n<tr><th><h3>Ogg/Theora video format</h3><span class=\"links\">[<a href=\"http://caniuse.com/ogv\">Table</a>] [<a href=\"http://tests.caniuse.com/?feat=ogv&prefix=all\">Single feat</a>]</span></th><td class=\"current pass\">&nbsp;</td><td>\n<div class=\"test_wrap\"><h3>Auto</h3><div id=\"ogv0\" class=\"auto pass\"></div><script>\nvar v = document.createElement('video'); \nsetResult('ogv0', !!(v.canPlayType && v.canPlayType('video/ogg; codecs=\"theora\"').replace(/no/, '')));\n</script></div>\n\n<div class=\"test_wrap\"><h3>Interact</h3><div id=\"ogv1\" class=\"interact\"></div><video src=\"video.ogv\" width=\"160\" height=\"120\" controls=\"\">fail</video><div class=\"info\">Video, no MIME, no type attribute.</div></div>\n\n<div class=\"test_wrap\"><h3>Interact</h3><div id=\"ogv2\" class=\"interact\"></div><video width=\"160\" height=\"120\" controls=\"\">\n <source src=\"mimevid.php?type=.ogv\" type=\"video/ogg; codecs=&quot;theora, vorbis&quot;\">\n</video><div class=\"info\">Video with source element and MIME set</div></div>\n\n<div class=\"test_wrap\"><h3>Interact</h3><div id=\"ogv3\" class=\"interact\"></div><video width=\"160\" height=\"120\" controls=\"\">\n <source src=\"video.ogv\" type=\"video/ogg; codecs=&quot;theora, vorbis&quot;\">\n</video><div class=\"info\">Video with source element</div></div>\n\n</td></tr>\n<tr><th><h3>WebM/VP8 video format</h3><span class=\"links\">[<a href=\"http://caniuse.com/webm\">Table</a>] [<a href=\"http://tests.caniuse.com/?feat=webm&prefix=all\">Single feat</a>]</span></th><td class=\"current pass\">&nbsp;</td><td>\n<div class=\"test_wrap\"><h3>Auto</h3><div id=\"webm0\" class=\"auto pass\"></div><script>\nvar v = document.createElement('video'); \nsetResult('webm0', !!(v.canPlayType && v.canPlayType('video/webm; codecs=\"vp8, vorbis\"').replace(/no/, '')));\n</script></div>\n\n<div class=\"test_wrap\"><h3>Interact</h3><div id=\"webm1\" class=\"interact\"></div><video src=\"video.webm\" width=\"160\" height=\"120\" controls=\"\">fail</video><div class=\"info\">Video, no MIME, no type attribute.</div></div>\n\n<div class=\"test_wrap\"><h3>Interact</h3><div id=\"webm2\" class=\"interact\"></div><video width=\"160\" height=\"120\" controls=\"\">\n <source src=\"video.webm\" type=\"video/ogg; codecs=&quot;theora, vorbis&quot;\">\n</video><div class=\"info\">Video with source element</div></div>\n\n<div class=\"test_wrap\"><h3>Interact</h3><div id=\"webm3\" class=\"interact\"></div><video width=\"160\" height=\"120\" controls=\"\">\n <source src=\"mimevid.php?type=.webm\" type=\"video/webm; codecs=&quot;vp8, vorbis&quot;\">\n</video><div class=\"info\">Video with source element and MIME set</div></div>\n\n</td></tr>\n<tr><th><h3>Animated PNG (APNG) [unoff]</h3><span class=\"links\">[<a href=\"http://caniuse.com/apng\">Table</a>] [<a href=\"http://tests.caniuse.com/?feat=apng&prefix=all\">Single feat</a>]</span></th><td class=\"current unknown\">&nbsp;</td><td>\n<div class=\"test_wrap\"><h3>Auto</h3><div id=\"apng0\" class=\"auto fail\"></div><script>\n(function() {\n\t// From: http://eligrey.com/blog/post/apng-feature-detection\n\tvar apngTest = new Image();\n\tvar canv = document.createElement(\"canvas\");\n\tvar apng_supported = null;\n\tif(canv.getContext && canv.getContext(\"2d\").drawImage) {\n\t\tvar ctx = canv.getContext(\"2d\");\n\t\tvar apng_supported = false;\n\t\tapngTest.onload = function () {\n\t\t\tctx.drawImage(apngTest, 0, 0);\n\t\t\tapng_supported = ( ctx.getImageData(0, 0, 1, 1).data[3] === 0 );\n\t\t\tsetResult('apng0', apng_supported);\n\t\t};\n\t\tapngTest.src = \"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAACGFjVEwAAAABAAAAAcMq2TYAAAANSURBVAiZY2BgYPgPAAEEAQB9ssjfAAAAGmZjVEwAAAAAAAAAAQAAAAEAAAAAAAAAAAD6A+gBAbNU+2sAAAARZmRBVAAAAAEImWNgYGBgAAAABQAB6MzFdgAAAABJRU5ErkJggg==\";\n\t} else {\n\t\tsetResult('apng0', false);\n\t}\n}());\n\n\n</script><div class=\"info\">Test for second frame using Canvas element </div></div>\n\n<div class=\"test_wrap\"><h3>Visual</h3><div id=\"apng1\" class=\"visual\"></div><div class=\"vis_test\"><img src=\"./caniuse_files/apng_test.png\" width=\"16\" height=\"16\"></div><p class=\"condition\">Must animate</p></div>\n\n</td></tr>\n<tr><th><h3>CSS Canvas Drawings [unoff]</h3><span class=\"links\">[<a href=\"http://caniuse.com/css-canvas\">Table</a>] [<a href=\"http://tests.caniuse.com/?feat=css-canvas&prefix=all\">Single feat</a>]</span></th><td class=\"current pass\">&nbsp;<span>-pre-</span></td><td>\n<div class=\"test_wrap\"><h3>Auto</h3><div id=\"css-canvas0\" class=\"auto pass\"></div><script>\nsetResult('css-canvas0', 'getCSSCanvasContext' in document)\n</script><div class=\"info\">'getCSSCanvasContext' in document</div></div>\n\n</td></tr>\n<tr><th><h3>CSS Reflections [unoff]</h3><span class=\"links\">[<a href=\"http://caniuse.com/css-reflections\">Table</a>] [<a href=\"http://tests.caniuse.com/?feat=css-reflections&prefix=all\">Single feat</a>]</span></th><td class=\"current pass\">&nbsp;<span>-pre-</span></td><td>\n<div class=\"test_wrap\"><h3>Auto (m)</h3><div id=\"css-reflections0\" class=\"auto pass\"></div><script>setResult('css-reflections0', Modernizr.cssreflections);</script><div class=\"info\">Modernizr test for: \"cssreflections\"</div></div>\n\n\n<div class=\"test_wrap\"><h3>Visual-square</h3><div id=\"reflections1\" class=\"visual-square\"></div><div class=\"square\">\n\n  <div style=\"width:30px; height:30px; overflow:hidden; position:relative; background:red;\">\n <div style=\"background: lime;\n            height: 30px;\n            position: relative;\n            top: -30px;\n            width: 30px;\n            -webkit-box-reflect: below 0;\n               -moz-box-reflect: below 0;\n                -ms-box-reflect: below 0;\n                 -o-box-reflect: below 0;\n                    box-reflect: below 0;\n            \"></div>\n\n</div></div></div>\n\n\n</td></tr>\n<tr><th><h3>Web SQL Database [unoff]</h3><span class=\"links\">[<a href=\"http://caniuse.com/sql-storage\">Table</a>] [<a href=\"http://tests.caniuse.com/?feat=sql-storage&prefix=all\">Single feat</a>]</span></th><td class=\"current pass\">&nbsp;</td><td>\n<div class=\"test_wrap\"><h3>Auto (m)</h3><div id=\"sql-storage0\" class=\"auto pass\"></div><script>setResult('sql-storage0', Modernizr.websqldatabase);</script><div class=\"info\">Modernizr test for: \"websqldatabase\"</div></div>\n\n</td></tr>\n<tr><th><h3>Stream API [unoff]</h3><span class=\"links\">[<a href=\"http://caniuse.com/stream\">Table</a>] [<a href=\"http://tests.caniuse.com/?feat=stream&prefix=all\">Single feat</a>]</span></th><td class=\"current unknown\">&nbsp;</td><td>\n<div class=\"test_wrap\"><h3>Auto</h3><div id=\"stream0\" class=\"auto fail\"></div><script>\nsetResult('stream0', \"getUserMedia\" in navigator);\n</script><div class=\"info\">Test for \"getUserMedia\" in navigator object</div></div>\n\n</td></tr>\n<tr><th><h3>CSS Masks [unoff]</h3><span class=\"links\">[<a href=\"http://caniuse.com/css-masks\">Table</a>] [<a href=\"http://tests.caniuse.com/?feat=css-masks&prefix=all\">Single feat</a>]</span></th><td class=\"current pass\">&nbsp;<span>-pre-</span></td><td>\n<div class=\"test_wrap\"><h3>Visual</h3><div id=\"css-masks0\" class=\"visual\"></div><div class=\"vis_test\"><style>\n#masktest {\n\t-webkit-mask-image: url(caniuse_files/alpha.png);\n-moz-mask-image: url(caniuse_files/alpha.png);\n-ms-mask-image: url(caniuse_files/alpha.png);\n-o-mask-image: url(caniuse_files/alpha.png);\nmask-image: url(caniuse_files/alpha.png);\n    background: black;\n    height: 16px;\n    width: 32px;\n    display: inline-block;\n    margin-left: -32px;\n}\n#masktestbg {\n    display: inline-block;\n\tbackground: lime;\n    height: 16px;\n    width: 32px;\n\tleft: -32px;\n}\n\n</style>\n<div id=\"masktestbg\"></div><div id=\"masktest\"></div>\n\n</div><div class=\"vis_ref\"><img src=\"./caniuse_files/png_alpha_result.png\"></div><div class=\"info\">mask-image: url(caniuse_files/alpha.png);</div></div>\n\n</td></tr>\n<tr><th><h3>CSS3 Text-overflow [unoff]</h3><span class=\"links\">[<a href=\"http://caniuse.com/text-overflow\">Table</a>] [<a href=\"http://tests.caniuse.com/?feat=text-overflow&prefix=all\">Single feat</a>]</span></th><td class=\"current pass\">&nbsp;</td><td>\n<div class=\"test_wrap\"><h3>Visual</h3><div id=\"text-overflow0\" class=\"visual\"></div><div class=\"vis_test\"><style>\n#textof {\n width: 4em;\n display: inline-block;\n overflow: hidden;\n font: 16px courier, monospace;\n-webkit-text-overflow: ellipsis; \n-moz-text-overflow: ellipsis; \n-ms-text-overflow: ellipsis; \n-o-text-overflow: ellipsis; \ntext-overflow: ellipsis; \n\n text-overflow: ellipsis; \n}\n</style>\n\n<div id=\"textof\">\nabcdefghijklmnopqrstuvwxyz\n</div></div><p class=\"condition\">Should end with ellipsis</p><div class=\"info\">text-overflow: ellipsis;</div></div>\n\n</td></tr>\n<tr><th><h3>CSS text-stroke [unoff]</h3><span class=\"links\">[<a href=\"http://caniuse.com/text-stroke\">Table</a>] [<a href=\"http://tests.caniuse.com/?feat=text-stroke&prefix=all\">Single feat</a>]</span></th><td class=\"current pass\">&nbsp;<span>-pre-</span></td><td>\n<div class=\"test_wrap\"><h3>Visual</h3><div id=\"text-stroke0\" class=\"visual\"></div><div class=\"vis_test\"><style>\n#textstroke {\n-webkit-text-stroke: 2px lime;\n-moz-text-stroke: 2px lime;\n-ms-text-stroke: 2px lime;\n-o-text-stroke: 2px lime;\ntext-stroke: 2px lime;\n\ncolor: #000;\nfont-size: 15px;\npadding: 5px;\nfont-family: Times New Roman, Times, serif;\n}\n</style>\n\n<div id=\"textstroke\">\ngreen stroked text\n</div></div><div class=\"vis_ref\"><img src=\"./caniuse_files/stroked-text.png\"></div><div class=\"info\">text-stroke: 2px lime;</div></div>\n\n</td></tr>\n<tr><th><h3>EOT - Embedded OpenType fonts [unoff]</h3><span class=\"links\">[<a href=\"http://caniuse.com/eot\">Table</a>] [<a href=\"http://tests.caniuse.com/?feat=eot&prefix=all\">Single feat</a>]</span></th><td class=\"current fail\">&nbsp;</td><td>\n<div class=\"test_wrap\"><h3>Visual</h3><div id=\"eot0\" class=\"visual\"></div><div class=\"vis_test\"><style>\n@font-face {\n\tfont-family: 'Windsong_eot';\n\tsrc: url('caniuse_files/Windsong-webfont.eot');\n}\n\n#windsong_eot {\n\tfont: 18px Windsong_eot;\n\tmargin: 5px;\n}\n</style>\n<p id=\"windsong_eot\">Windsong font</p>\n</div><div class=\"vis_ref\"><img src=\"./caniuse_files/windsong_font.png\"></div></div>\n\n</td></tr>\n<tr><th><h3>XHTML+SMIL animation [unoff]</h3><span class=\"links\">[<a href=\"http://caniuse.com/xhtmlsmil\">Table</a>] [<a href=\"http://tests.caniuse.com/?feat=xhtmlsmil&prefix=all\">Single feat</a>]</span></th><td class=\"current fail\">&nbsp;</td><td>\n\n</td></tr>\n</tbody></table>\n<p>Most tests by <a href=\"http://a.deveria.com/\">Alexis Deveria</a>, additional contributions by <a href=\"http://paulirish.com/\">Paul Irish</a></p>\n\n<script>\n(function() {\nvar gaJsHost = ((\"https:\" == document.location.protocol) ? \"https://ssl.\" : \"http://www.\");\ndocument.write(unescape(\"%3Cscript src='\" + gaJsHost + \"google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E\"));\n}());\n</script><script src=\"./caniuse_files/ga.js\" type=\"text/javascript\"></script>\n<script>\n(function() {\ntry {\nvar pageTracker = _gat._getTracker(\"UA-16085010-1\");\npageTracker._trackPageview();\n} catch(err) {}\n}());\n</script></body></html>"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/modernizr/test/caniuse_files/form_validation.html",
    "content": "<!DOCTYPE html>\n<!-- saved from url=(0045)http://tests.caniuse.com/form_validation.html -->\n<html><head><meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\"><script>\nif(location.href.indexOf('?') >= 0) {\n\tdocument.write('FAIL');\n}\n</script>\n\n</head><body><form action=\"http://tests.caniuse.com/form_validation.html?\" method=\"post\">\n\n<input type=\"url\" name=\"foo\" required=\"\">\n<input type=\"submit\" value=\"submit me!\">\n\n</form>\n</body></html>"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/modernizr/test/caniuse_files/ga.js",
    "content": "(function(){var k=void 0,aa=encodeURIComponent,l=String,o=Math,ba=\"push\",ca=\"cookie\",p=\"charAt\",q=\"indexOf\",da=\"getTime\",r=\"toString\",t=\"window\",v=\"length\",w=\"document\",x=\"split\",y=\"location\",ea=\"protocol\",fa=\"href\",z=\"substring\",A=\"join\",C=\"toLowerCase\";var ga=\"_gat\",ha=\"_gaq\",ia=\"4.9.4\",ja=\"_gaUserPrefs\",ka=\"ioo\",D=\"&\",E=\"=\",F=\"__utma=\",H=\"__utmb=\",la=\"__utmc=\",ma=\"__utmk=\",I=\"__utmv=\",J=\"__utmz=\",na=\"__utmx=\",oa=\"GASO=\";var pa=function(){var d=this,f=[],b=\"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_\";d.set=function(b){f[b]=!0};d.Sc=function(){for(var d=[],e=0;e<f[v];e++)f[e]&&(d[o.floor(e/6)]^=1<<e%6);for(e=0;e<d[v];e++)d[e]=b[p](d[e]||0);return d[A](\"\")+\"~\"}},qa=new pa;function K(d){qa.set(d)};var ra=function(d,f){var b=this;b.window=d;b.document=f;b.setTimeout=function(b,e){setTimeout(b,e)};b.Jb=function(b){return navigator.userAgent[q](b)>=0};b.Xc=function(){return b.Jb(\"Firefox\")&&![].reduce};b.Vc=function(){return L[t][ja]};b.Gc=function(){return L[t].external};b.Hc=function(){return L[t].performance||L[t].webkitPerformance};b.Ic=function(){return L[t].top==L[t]};b.Ya=function(b){var e=L[t]&&L[t].gaGlobal;if(b&&!e)e={},L[t].gaGlobal=e;return e};b.ec=function(b){L[w][y].href=b};b.qb=\nfunction(d){if(!d||!b.Jb(\"Firefox\"))return d;for(var d=d.replace(/\\n|\\r/g,\" \"),e=0,f=d[v];e<f;++e){var g=d.charCodeAt(e)&255;if(g==10||g==13)d=d[z](0,e)+\"?\"+d[z](e+1)}return d}},L=new ra(window,document);var sa=function(d){return function(f,b,h){d[f]=function(){K(b);return h.apply(d,arguments)};return h}},ta=function(d,f,b,h){d.addEventListener?d.addEventListener(f,b,!!h):d.attachEvent&&d.attachEvent(\"on\"+f,b)},ua=function(d){return Object.prototype[r].call(Object(d))==\"[object Array]\"},M=function(d){return k==d||\"-\"==d||\"\"==d},N=function(d,f,b){var h=\"-\",e;!M(d)&&!M(f)&&!M(b)&&(e=d[q](f),e>-1&&(b=d[q](b,e),b<0&&(b=d[v]),h=d[z](e+f[q](E)+1,b)));return h},xa=function(d){var f=!1,b=0,h,e;if(!M(d)){f=\n!0;for(h=0;h<d[v];h++)e=d[p](h),b+=\".\"==e?1:0,f=f&&b<=1&&(0==h&&\"-\"==e||\".0123456789\"[q](e)>-1)}return f},P=function(d,f){var b=aa;return b instanceof Function?f?encodeURI(d):b(d):(K(68),escape(d))},Q=function(d,f){var b=decodeURIComponent,h,d=d[x](\"+\")[A](\" \");if(b instanceof Function)try{h=f?decodeURI(d):b(d)}catch(e){K(17),h=unescape(d)}else K(68),h=unescape(d);return h},R=function(d,f){return d[q](f)>-1};\nfunction ya(d){if(!d||\"\"==d)return\"\";for(;d[p](0)[v]>0&&\" \\n\\r\\t\"[q](d[p](0))>-1;)d=d[z](1);for(;d[p](d[v]-1)[v]>0&&\" \\n\\r\\t\"[q](d[p](d[v]-1))>-1;)d=d[z](0,d[v]-1);return d}var T=function(d,f){d[ba]||K(94);d[d[v]]=f},za=function(d){var f=1,b=0,h;if(!M(d)){f=0;for(h=d[v]-1;h>=0;h--)b=d.charCodeAt(h),f=(f<<6&268435455)+b+(b<<14),b=f&266338304,f=b!=0?f^b>>21:f}return f},Aa=function(){return o.round(o.random()*2147483647)},Ba=function(){};var Ca=function(d,f){this.ib=d;this.jb=f},Da=function(){function d(b){for(var d=[],b=b[x](\",\"),e,f=0;f<b[v];f++)e=b[f][x](\":\"),d[ba](new Ca(e[0],e[1]));return d}var f=this;f.Ca=\"utm_campaign\";f.Da=\"utm_content\";f.Ea=\"utm_id\";f.Fa=\"utm_medium\";f.Ga=\"utm_nooverride\";f.Ha=\"utm_source\";f.Ia=\"utm_term\";f.Ja=\"gclid\";f.vc=\"dclid\";f.U=0;f.w=0;f.La=15768E6;f.Ma=18E5;f.s=63072E6;f.V=[];f.W=[];f.wc=\"cse\";f.xc=\"q\";f.Ta=50;f.J=d(\"daum:q,eniro:search_word,naver:query,pchome:q,images.google:q,google:q,yahoo:p,yahoo:q,msn:q,bing:q,aol:query,aol:encquery,aol:q,lycos:query,ask:q,altavista:q,netscape:query,cnn:query,about:terms,mamma:q,alltheweb:q,voila:rdata,virgilio:qs,live:q,baidu:wd,alice:qs,yandex:text,najdi:q,mama:query,seznam:q,search:q,wp:szukaj,onet:qt,szukacz:q,yam:k,kvasir:q,sesam:q,ozu:q,terra:query,mynet:q,ekolay:q,rambler:query,rambler:words\");\nf.f=\"/\";f.L=100;f.ga=\"/__utm.gif\";f.la=1;f.ma=1;f.u=\"|\";f.ka=1;f.Ka=1;f.Ua=1;f.b=\"auto\";f.B=1;f.Wb=10;f.zc=10;f.Ac=0.2;f.o=k};var Ea=function(d){function f(a,c,b,j){var i=\"\",d=0,i=N(a,\"2\"+c,\";\");if(!M(i)){a=i[q](\"^\"+b+\".\");if(a<0)return[\"\",0];i=i[z](a+b[v]+2);i[q](\"^\")>0&&(i=i[x](\"^\")[0]);b=i[x](\":\");i=b[1];d=parseInt(b[0],10);!j&&d<e.m&&(i=\"\")}M(i)&&(i=\"\");return[i,d]}function b(a,c){return\"^\"+[[c,a[1]][A](\".\"),a[0]][A](\":\")}function h(a){var c=new Date,a=new Date(c[da]()+a);return\"expires=\"+a.toGMTString()+\"; \"}var e=this,m=d;e.m=(new Date)[da]();var g=[F,H,la,J,I,na,oa];e.g=function(){var a=L[w][ca];return m.o?e.Nc(a,\nm.o):a};e.Nc=function(a,c){for(var b=[],j,i=0;i<g[v];i++)j=f(a,g[i],c)[0],M(j)||(b[b[v]]=g[i]+j+\";\");return b[A](\"\")};e.l=function(a,c,b){var j=b>0?h(b):\"\";m.o&&(c=e.Oc(L[w][ca],a,m.o,c,b),a=\"2\"+a,j=b>0?h(m.s):\"\");a+=c;a=L.qb(a);a[v]>2E3&&(K(69),a=a[z](0,2E3));j=a+\"; path=\"+m.f+\"; \"+j+e.hb();if(!V.pb())L[w].cookie=j};e.Oc=function(a,c,d,j,i){var g=\"\",i=i||m.s,j=b([j,e.m+i*1],d),g=N(a,\"2\"+c,\";\");if(!M(g))return a=b(f(a,c,d,!0),d),g=g[x](a)[A](\"\"),g=j+g;return j};e.hb=function(){return M(m.b)?\"\":\"domain=\"+\nm.b+\";\"}};var Fa=function(d){function f(a){a=ua(a)?a[A](\".\"):\"\";return M(a)?\"-\":a}function b(a,c){var n=[],b;if(!M(a)&&(n=a[x](\".\"),c))for(b=0;b<n[v];b++)xa(n[b])||(n[b]=\"-\");return n}function h(a,c,n){var b=i.I,j,d;for(j=0;j<b[v];j++)d=b[j][0],d+=M(c)?c:c+b[j][4],b[j][2](N(a,d,n))}var e,m,g,a,c,u,j,i=this,s,n=d;i.i=new Ea(d);i.Ba=function(){return k==s||s==i.K()};i.g=function(){return i.i.g()};i.ea=function(){return c?c:\"-\"};i.Pa=function(a){c=a};i.fa=function(a){s=xa(a)?a*1:\"-\"};i.da=function(){return f(u)};\ni.X=function(a){u=b(a)};i.yc=function(){i.i.l(I,\"\",-1)};i.Rb=function(){return s?s:\"-\"};i.hb=function(){return M(n.b)?\"\":\"domain=\"+n.b+\";\"};i.ba=function(){return f(e)};i.Na=function(a){e=b(a,1)};i.z=function(){return f(m)};i.$=function(a){m=b(a,1)};i.ca=function(){return f(g)};i.Oa=function(a){g=b(a,1)};i.qa=function(){return f(a)};i.ra=function(c){a=b(c);for(c=0;c<a[v];c++)c<4&&!xa(a[c])&&(a[c]=\"-\")};i.Fc=function(){return j};i.Dc=function(a){j=a};i.Qb=function(){e=[];m=[];g=[];a=[];c=k;u=[];s=\nk};i.K=function(){for(var a=\"\",c=0;c<i.I[v];c++)a+=i.I[c][1]();return za(a)};i.Z=function(a){var c=i.g(),n=!1;c&&(h(c,a,\";\"),i.fa(l(i.K())),n=!0);return n};i.Sb=function(a){h(a,\"\",D);i.fa(N(a,ma,D))};i.Tb=function(){var a=i.I,c=[],n;for(n=0;n<a[v];n++)T(c,a[n][0]+a[n][1]());T(c,ma+i.K());return c[A](D)};i.Ub=function(a,c){var b=i.I,j=n.f;i.Z(a);n.f=c;for(var d=0;d<b[v];d++)if(!M(b[d][1]()))b[d][3]();n.f=j};i.Qa=function(){i.i.l(F,i.ba(),n.s)};i.aa=function(){i.i.l(H,i.z(),n.Ma)};i.Ra=function(){i.i.l(la,\ni.ca(),0)};i.sa=function(){i.i.l(J,i.qa(),n.La)};i.Sa=function(){i.i.l(na,i.ea(),n.s)};i.Y=function(){i.i.l(I,i.da(),n.s)};i.Ec=function(){i.i.l(oa,i.Fc(),0)};i.I=[[F,i.ba,i.Na,i.Qa,\".\"],[H,i.z,i.$,i.aa,\"\"],[la,i.ca,i.Oa,i.Ra,\"\"],[na,i.ea,i.Pa,i.Sa,\"\"],[J,i.qa,i.ra,i.sa,\".\"],[I,i.da,i.X,i.Y,\".\"]]};var Ga=\"https:\"==L[w][y][ea]?\"https://ssl.google-analytics.com/\":\"http://www.google-analytics.com/\",Ha=Ga+\"p/__utm.gif\",Ja=function(){var d=this;d.Bb=function(f,b,h,e,m){b[v]<=2036||m?d.Aa(f+\"?\"+b,e):b[v]<=8192?L.Xc()?d.Aa(f+\"?\"+h+\"&err=ff2post&len=\"+b[v],e):d.fd(b,e):d.Aa(f+\"?\"+h+\"&err=len&max=8192&len=\"+b[v],e)};d.Aa=function(d,b){var h=new Image(1,1);h.src=d;h.onload=function(){h.onload=null;(b||Ba)()}};d.fd=function(f,b){d.ed(f,b)||d.Ob(f,b)};d.ed=function(d,b){var h,e=L[t].XDomainRequest;if(e)h=\nnew e,h.open(\"POST\",Ha);else if(e=L[t].XMLHttpRequest)e=new e,\"withCredentials\"in e&&(h=e,h.open(\"POST\",Ha,!0),h.setRequestHeader(\"Content-Type\",\"text/plain\"));if(h)return h.onreadystatechange=function(){h.readyState==4&&(b&&b(),h=null)},h.send(d),!0;return!1};d.Ob=function(f,b){var h=L[w];if(h.body){f=aa(f);try{var e=h.createElement('<iframe name=\"'+f+'\"></iframe>')}catch(m){e=h.createElement(\"iframe\"),e.name=f}e.height=\"0\";e.width=\"0\";e.style.display=\"none\";e.style.visibility=\"hidden\";var g=h[y],\ng=g[ea]+\"//\"+g.host+\"/favicon.ico\",g=Ga+\"u/post_iframe.html#\"+aa(g),a=function(){e.src=\"\";e.parentNode&&e.parentNode.removeChild(e)};ta(L[t],\"beforeunload\",a);var c=!1,u=0,j=function(){if(!c){try{if(u>9||e.contentWindow[y].host==h[y].host){c=!0;a();var d=L[t],g=\"beforeunload\",n=a;d.removeEventListener?d.removeEventListener(g,n,!1):d.detachEvent&&d.detachEvent(\"on\"+g,n);b&&b();return}}catch(f){}u++;L.setTimeout(j,200)}};ta(e,\"load\",j);h.body.appendChild(e);e.src=g}else L.setTimeout(function(){d.Ob(f,\nb)},100)}};var Ka=function(d){var f=this,b=d,h=new Fa(b),e=null,m=!V.pb(),g=function(){};f.Uc=function(){return\"https:\"==L[w][y][ea]?\"https://ssl.google-analytics.com/__utm.gif\":\"http://www.google-analytics.com/__utm.gif\"};f.A=function(a,c,d,j,i,s){e||(e=new Ja);var n=b.B,O=L[w][y];h.Z(d);var B=h.z()[x](\".\");if(B[1]<500||j){if(i){var S=(new Date)[da](),X;X=(S-B[3])*(b.Ac/1E3);X>=1&&(B[2]=o.min(o.floor(B[2]*1+X),b.zc),B[3]=S)}if(j||!i||B[2]>=1){!j&&i&&(B[2]=B[2]*1-1);j=B[1]*1+1;B[1]=j;i=\"utmwv=\"+ia;S=\"&utms=\"+\nj;X=\"&utmn=\"+Aa();j=i+\"e\"+S+X;a=i+S+X+(M(O.hostname)?\"\":\"&utmhn=\"+P(O.hostname))+(b.L==100?\"\":\"&utmsp=\"+P(b.L))+a;if(0==n||2==n)O=2==n?g:s||g,m&&e.Bb(b.ga,a,j,O,!0);if(1==n||2==n)c=\"&utmac=\"+c,j+=c,a+=c+\"&utmcc=\"+f.Tc(d),V.Ab&&(d=\"&aip=1\",j+=d,a+=d),a+=\"&utmu=\"+qa.Sc(),m&&e.Bb(f.Uc(),a,j,s)}}h.$(B[A](\".\"));h.aa()};f.Tc=function(a){for(var c=[],b=[F,J,I,na],d=h.g(),i,g=0;g<b[v];g++)if(i=N(d,b[g]+a,\";\"),!M(i)){if(b[g]==I){i=i[x](a+\".\")[1][x](\"|\")[0];if(M(i))continue;i=a+\".\"+i}T(c,b[g]+i+\";\")}return P(c[A](\"+\"))}};var W=function(){var d=this;d.N=[];d.Va=function(f){for(var b,h=d.N,e=0;e<h[v];e++)b=f==h[e].q?h[e]:b;return b};d.Xb=function(f,b,h,e,m,g,a,c){var u=d.Va(f);k==u?(u=new W.Wc(f,b,h,e,m,g,a,c),T(d.N,u)):(u.tb=b,u.zb=h,u.yb=e,u.wb=m,u.ub=g,u.xb=a,u.vb=c);return u}};W.Qc=function(d,f,b,h,e,m){var g=this;g.Fb=d;g.va=f;g.n=b;g.Cb=h;g.Db=e;g.Eb=m;g.ha=function(){return\"&\"+[\"utmt=item\",\"tid=\"+P(g.Fb),\"ipc=\"+P(g.va),\"ipn=\"+P(g.n),\"iva=\"+P(g.Cb),\"ipr=\"+P(g.Db),\"iqt=\"+P(g.Eb)][A](\"&utm\")}};\nW.Wc=function(d,f,b,h,e,m,g,a){var c=this;c.q=d;c.tb=f;c.zb=b;c.yb=h;c.wb=e;c.ub=m;c.xb=g;c.vb=a;c.M=[];c.Vb=function(a,b,d,g,n){var e=c.Rc(a),f=c.q;k==e?T(c.M,new W.Qc(f,a,b,d,g,n)):(e.Fb=f,e.va=a,e.n=b,e.Cb=d,e.Db=g,e.Eb=n)};c.Rc=function(a){for(var b,d=c.M,g=0;g<d[v];g++)b=a==d[g].va?d[g]:b;return b};c.ha=function(){return\"&\"+[\"utmt=tran\",\"id=\"+P(c.q),\"st=\"+P(c.tb),\"to=\"+P(c.zb),\"tx=\"+P(c.yb),\"sp=\"+P(c.wb),\"ci=\"+P(c.ub),\"rg=\"+P(c.xb),\"co=\"+P(c.vb)][A](\"&utmt\")}};var La=function(d){function f(){var b,a,c;a=\"ShockwaveFlash\";var d=\"$version\",j=L[t].navigator;if((j=j?j.plugins:k)&&j[v]>0)for(b=0;b<j[v]&&!c;b++)a=j[b],R(a.name,\"Shockwave Flash\")&&(c=a.description[x](\"Shockwave Flash \")[1]);else{a=a+\".\"+a;try{b=new ActiveXObject(a+\".7\"),c=b.GetVariable(d)}catch(e){}if(!c)try{b=new ActiveXObject(a+\".6\"),c=\"WIN 6,0,21,0\",b.we=\"always\",c=b.GetVariable(d)}catch(f){}if(!c)try{b=new ActiveXObject(a),c=b.GetVariable(d)}catch(n){}c&&(c=c[x](\" \")[1][x](\",\"),c=c[0]+\".\"+\nc[1]+\" r\"+c[2])}return c?c:h}var b=this,h=\"-\",e=L[t].screen,m=L[t].navigator;b.Nb=e?e.width+\"x\"+e.height:h;b.Mb=e?e.colorDepth+\"-bit\":h;b.cd=P(L[w].characterSet?L[w].characterSet:L[w].charset?L[w].charset:h);b.Lb=(m&&m.language?m.language:m&&m.browserLanguage?m.browserLanguage:h)[C]();b.Kb=m&&m.javaEnabled()?1:0;b.dd=d?f():h;b.dc=function(){return D+\"utm\"+[\"cs=\"+P(b.cd),\"sr=\"+b.Nb,\"sc=\"+b.Mb,\"ul=\"+b.Lb,\"je=\"+b.Kb,\"fl=\"+P(b.dd)][A](\"&utm\")};b.cc=function(){for(var d=L[t].navigator,a=L[t].history[v],\nd=d.appName+d.version+b.Lb+d.platform+d.userAgent+b.Kb+b.Nb+b.Mb+(L[w][ca]?L[w][ca]:\"\")+(L[w].referrer?L[w].referrer:\"\"),c=d[v];a>0;)d+=a--^c++;return za(d)}};var Z=function(d,f,b,h){function e(a){var c=\"\",c=a[x](\"://\")[1][C]();R(c,\"/\")&&(c=c[x](\"/\")[0]);return c}var m=h,g=this;g.a=d;g.ob=f;g.m=b;g.mb=function(a){var c=g.ua();return new Z.v(N(a,m.Ea+E,D),N(a,m.Ha+E,D),N(a,m.Ja+E,D),g.R(a,m.Ca,\"(not set)\"),g.R(a,m.Fa,\"(not set)\"),g.R(a,m.Ia,c&&!M(c.G)?Q(c.G):k),g.R(a,m.Da,k),N(a,m.vc+E,D))};g.nb=function(a){var c=e(a),b;b=a;var d=\"\";b=b[x](\"://\")[1][C]();R(b,\"/\")&&(b=b[x](\"/\")[1],R(b,\"?\")&&(d=b[x](\"?\")[0]));b=d;if(R(c,\"google\")&&(a=a[x](\"?\")[A](D),R(a,D+\nm.xc+E)&&b==m.wc))return!0;return!1};g.ua=function(){var a,c=g.ob,b,d=m.J;if(!M(c)&&\"0\"!=c&&R(c,\"://\")&&!g.nb(c)){a=e(c);for(var i=0;i<d[v];i++)if(b=d[i],R(a,b.ib[C]())&&(c=c[x](\"?\")[A](D),R(c,D+b.jb+E)))return a=c[x](D+b.jb+E)[1],R(a,D)&&(a=a[x](D)[0]),new Z.v(k,b.ib,k,\"(organic)\",\"organic\",a,k,k)}};g.R=function(a,c,b){a=N(a,c+E,D);return b=!M(a)?Q(a):!M(b)?b:\"-\"};g.Bc=function(a){var c=m.V,b=!1;if(a&&\"organic\"==a.P)for(var a=Q(a.G)[C](),d=0;d<c[v];d++)b=b||c[d][C]()==a;return b};g.lb=function(){var a=\n\"\",c=\"\",a=g.ob;if(!M(a)&&\"0\"!=a&&R(a,\"://\")&&!g.nb(a))return a=a[x](\"://\")[1],R(a,\"/\")&&(c=a[z](a[q](\"/\")),c=c[x](\"?\")[0],a=a[x](\"/\")[0][C]()),0==a[q](\"www.\")&&(a=a[z](4)),new Z.v(k,a,k,\"(referral)\",\"referral\",k,c,k)};g.kb=function(a){var c=\"\";m.U&&(c=a&&a.hash?a[fa][z](a[fa][q](\"#\")):\"\",c=\"\"!=c?c+D:c);c+=a.search;return c};g.ta=function(){return new Z.v(k,\"(direct)\",k,\"(direct)\",\"(none)\",k,k,k)};g.Cc=function(a){var c=!1,b=m.W;if(a&&\"referral\"==a.P)for(var a=P(a.Q)[C](),d=0;d<b[v];d++)c=c||R(a,b[d][C]());\nreturn c};g.h=function(a){return k!=a&&a.fb()};g.te=function(a){var a=N(a,J+g.a+\".\",\";\"),c=a[x](\".\"),a=new Z.v;a.gb(c.slice(4)[A](\".\"));if(!g.h(a))return!0;c=L[w][y];c=g.kb(c);c=g.mb(c);g.h(c)||(c=g.ua(),g.h(c)||(c=g.lb()));return g.h(c)&&a.H()[C]()!=c.H()[C]()};g.Pb=function(a,c){if(m.Ka){var b=\"\",d=\"-\",e,f=0,n,h,B=g.a;if(a){h=a.g();b=g.kb(L[w][y]);if(m.w&&a.Ba()&&(d=Q(a.qa()),!M(d)&&!R(d,\";\"))){a.ra(d);a.sa();return}d=N(h,J+B+\".\",\";\");e=g.mb(b);if(g.h(e)&&(b=N(b,m.Ga+E,D),\"1\"==b&&!M(d)))return;\nif(!g.h(e)){e=g.ua();b=g.Bc(e);if(!M(d)&&b)return;b&&(e=g.ta())}if(!g.h(e)&&c){e=g.lb();b=g.Cc(e);if(!M(d)&&b)return;b&&(e=g.ta())}g.h(e)||M(d)&&c&&(e=g.ta());if(g.h(e)&&(M(d)||(f=d[x](\".\"),n=new Z.v,n.gb(f.slice(4)[A](\".\")),n=n.H()[C]()==e.H()[C](),f=f[3]*1),!n||c))h=N(h,F+B+\".\",\";\"),n=h.lastIndexOf(\".\"),h=n>9?h[z](n+1)*1:0,f++,h=0==h?1:h,a.ra([B,g.m,h,f,e.H()][A](\".\")),a.sa()}}}};\nZ.v=function(d,f,b,h,e,m,g,a){var c=this;c.q=d;c.Q=f;c.ya=b;c.n=h;c.P=e;c.G=m;c.Gb=g;c.xa=a;c.H=function(){var a=[],b=[[\"cid\",c.q],[\"csr\",c.Q],[\"gclid\",c.ya],[\"ccn\",c.n],[\"cmd\",c.P],[\"ctr\",c.G],[\"cct\",c.Gb],[\"dclid\",c.xa]],d,e;if(c.fb())for(d=0;d<b[v];d++)M(b[d][1])||(e=b[d][1][x](\"+\")[A](\"%20\"),e=e[x](\" \")[A](\"%20\"),T(a,\"utm\"+b[d][0]+E+e));return L.qb(a[A](\"|\"))};c.fb=function(){return!(M(c.q)&&M(c.Q)&&M(c.ya)&&M(c.xa))};c.gb=function(a){var b=function(b){return Q(N(a,\"utm\"+b+E,\"|\"))};c.q=b(\"cid\");\nc.Q=b(\"csr\");c.ya=b(\"gclid\");c.n=b(\"ccn\");c.P=b(\"cmd\");c.G=b(\"ctr\");c.Gb=b(\"cct\");c.xa=b(\"dclid\")}};var Ma=function(d,f,b,h){var e=this,m=f,g=E,a=d,c=h;e.S=b;e.wa=\"\";e.r={};e.$b=function(){var a;a=N(e.S.g(),I+m+\".\",\";\")[x](m+\".\")[1];if(!M(a)){a=a[x](\"|\");var b=e.r,c=a[1],d;if(!M(c))for(var c=c[x](\",\"),n=0;n<c[v];n++)d=c[n],M(d)||(d=d[x](g),d[v]==4&&(b[d[0]]=[Q(d[1]),Q(d[2]),1]));e.wa=Q(a[0]);e.T()}};e.T=function(){e.Pc();var a=P(e.wa),b,c,d=\"\";for(b in e.r)(c=e.r[b])&&1===c[2]&&(d+=b+g+P(c[0])+g+P(c[1])+g+1+\",\");M(d)||(a+=\"|\"+d);M(a)?e.S.yc():(e.S.X(m+\".\"+a),e.S.Y())};e.bc=function(a){e.wa=a;e.T()};\ne.ac=function(b,c,d,g){1!=g&&2!=g&&3!=g&&(g=3);var n=!1;if(c&&d&&b>0&&b<=a.Ta){var f=P(c),h=P(d);f[v]+h[v]<=64&&(e.r[b]=[c,d,g],e.T(),n=!0)}return n};e.Zb=function(a){if((a=e.r[a])&&1===a[2])return a[1]};e.Yb=function(a){var b=e.r;b[a]&&(delete b[a],e.T())};e.Pc=function(){c.t(8);c.t(9);c.t(11);var a=e.r,b,d;for(d in a)if(b=a[d])c.j(8,d,b[0]),c.j(9,d,b[1]),(b=b[2])&&3!=b&&c.j(11,d,\"\"+b)}};var Na=function(){function d(a,b,c,d){k==g[a]&&(g[a]={});k==g[a][b]&&(g[a][b]=[]);g[a][b][c]=d}function f(a,b,c){if(k!=g[a]&&k!=g[a][b])return g[a][b][c]}function b(a,b){if(k!=g[a]&&k!=g[a][b]){g[a][b]=k;var c=!0,d;for(d=0;d<u[v];d++)if(k!=g[a][u[d]]){c=!1;break}c&&(g[a]=k)}}function h(a){var b=\"\",c=!1,d,e;for(d=0;d<u[v];d++)if(e=a[u[d]],k!=e){c&&(b+=u[d]);for(var c=[],g=k,f=k,f=0;f<e[v];f++)if(k!=e[f]){g=\"\";f!=S&&k==e[f-1]&&(g+=f[r]()+n);var h;h=e[f];for(var O=\"\",m=k,U=k,wa=k,m=0;m<h[v];m++)U=h[p](m),\nwa=B[U],O+=k!=wa?wa:U;h=O;g+=h;T(c,g)}e=j+c[A](s)+i;b+=e;c=!1}else c=!0;return b}var e=this,m=sa(e),g={},a=\"k\",c=\"v\",u=[a,c],j=\"(\",i=\")\",s=\"*\",n=\"!\",O=\"'\",B={};B[O]=\"'0\";B[i]=\"'1\";B[s]=\"'2\";B[n]=\"'3\";var S=1;e.Yc=function(a){return k!=g[a]};e.C=function(){var a=\"\",b;for(b in g)k!=g[b]&&(a+=b[r]()+h(g[b]));return a};e.hc=function(a){if(a==k)return e.C();var b=a.C(),c;for(c in g)k!=g[c]&&!a.Yc(c)&&(b+=c[r]()+h(g[c]));return b};e.j=m(\"_setKey\",89,function(b,c,n){if(typeof n!=\"string\")return!1;d(b,a,\nc,n);return!0});e.ja=m(\"_setValue\",90,function(a,b,n){if(typeof n!=\"number\"&&(k==Number||!(n instanceof Number))||o.round(n)!=n||n==NaN||n==Infinity)return!1;d(a,c,b,n[r]());return!0});e.fc=m(\"_getKey\",87,function(b,c){return f(b,a,c)});e.gc=m(\"_getValue\",88,function(a,b){return f(a,c,b)});e.t=m(\"_clearKey\",85,function(c){b(c,a)});e.ia=m(\"_clearValue\",86,function(a){b(a,c)})};var Oa=function(d,f){var b=this,h=sa(b);b.ze=f;b.gd=d;b.Za=h(\"_trackEvent\",91,function(d,h,g){return f.Za(b.gd,d,h,g)})};var Pa=function(d,f){var b=this,h=L.Gc(),e=L.Hc(),m=10;b.rb=new Na;b.Kc=function(){var b,a=\"timing\",c=\"onloadT\";h&&h[c]!=k&&h.isValidLoadTime?b=h[c]:e&&e[a]&&(b=e[a].loadEventStart-e[a].fetchStart);return b};b.Mc=function(){return d.D()&&d.Xa()%100<m};b.Lc=function(){var e=\"&utmt=event&utme=\"+P(b.rb.C())+d.na();f.A(e,d.p,d.a,!1,!0)};b.Jc=function(b){b=o.min(o.floor(b/100),5E3);return b>0?b+\"00\":\"0\"};b.sb=function(){var d=b.Kc();if(d==k||isNaN(d))return!1;if(d<=0)return!0;if(d>2147483648)return!1;\nvar a=b.rb;a.t(14);a.ia(14);var c=b.Jc(d);a.j(14,1,c)&&a.ja(14,1,d)&&b.Lc();h&&h.isValidLoadTime!=k&&h.setPageReadyTime();return!1};b.Wa=function(){if(!b.Mc())return!1;if(!L.Ic())return!1;b.sb()&&ta(L[t],\"load\",b.sb,!1);return!0}};var $=function(){};$.Zc=function(d){var f=\"gaso=\",b=L[w][y].hash;d=b&&1==b[q](f)?N(b,f,D):(b=L[t].name)&&0<=b[q](f)?N(b,f,D):N(d.g(),oa,\";\");return d};$.ad=function(d,f){var b=(f||\"www\")+\".google.com\",b=\"https://\"+b+\"/analytics/reporting/overlay_js?gaso=\"+d+D+Aa(),h=\"_gasojs\",e=L[w].createElement(\"script\");e.type=\"text/javascript\";e.src=b;if(h)e.id=h;(L[w].getElementsByTagName(\"head\")[0]||L[w].getElementsByTagName(\"body\")[0]).appendChild(e)};\n$.load=function(d,f){if(!$.$c){var b=$.Zc(f),h=b&&b.match(/^(?:\\|([-0-9a-z.]{1,30})\\|)?([-.\\w]{10,1200})$/i);if(h)f.Dc(b),f.Ec(),V._gasoDomain=d.b,V._gasoCPath=d.f,$.ad(h[2],h[1]);$.$c=!0}};var Qa=function(d,f,b){function h(){if(\"auto\"==j.b){var a=L[w].domain;\"www.\"==a[z](0,4)&&(a=a[z](4));j.b=a}j.b=j.b[C]()}function e(){h();var a=j.b,b=a[q](\"www.google.\")*a[q](\".google.\")*a[q](\"google.\");return b||\"/\"!=j.f||a[q](\"google.org\")>-1}function m(b,c,d){if(M(b)||M(c)||M(d))return\"-\";b=N(b,F+a.a+\".\",c);M(b)||(b=b[x](\".\"),b[5]=\"\"+(b[5]?b[5]*1+1:1),b[3]=b[4],b[4]=d,b=b[A](\".\"));return b}function g(){return\"file:\"!=L[w][y][ea]&&e()}var a=this,c=sa(a),u=k,j=new Da,i=!1,s=k;a.n=d;a.m=o.round((new Date)[da]()/\n1E3);a.p=f||\"UA-XXXXX-X\";a.ab=L[w].referrer;a.oa=k;a.d=k;a.F=!1;a.O=k;a.e=k;a.bb=k;a.pa=k;a.a=k;a.k=k;j.o=b?P(b):k;a.eb=!1;a.mc=function(){return Aa()^a.O.cc()&2147483647};a.lc=function(){if(!j.b||\"\"==j.b||\"none\"==j.b)return j.b=\"\",1;h();return j.Ua?za(j.b):1};a.kc=function(a,b){if(M(a))a=\"-\";else{b+=j.f&&\"/\"!=j.f?j.f:\"\";var c=a[q](b),a=c>=0&&c<=8?\"0\":\"[\"==a[p](0)&&\"]\"==a[p](a[v]-1)?\"-\":a}return a};a.na=function(b){var c=\"\";c+=j.ka?a.O.dc():\"\";c+=j.la&&!M(L[w].title)?\"&utmdt=\"+P(L[w].title):\"\";var d;\nd=L.Ya(!0);if(!d.hid)d.hid=Aa();d=d.hid;c+=\"&utmhid=\"+d+\"&utmr=\"+P(l(a.oa))+\"&utmp=\"+P(a.pc(b));return c};a.pc=function(a){var b=L[w][y];a&&K(13);return a=k!=a&&\"\"!=a?P(a,!0):P(b.pathname+b.search,!0)};a.uc=function(b){if(a.D()){var c=\"\";a.e!=k&&a.e.C()[v]>0&&(c+=\"&utme=\"+P(a.e.C()));c+=a.na(b);u.A(c,a.p,a.a)}};a.jc=function(){var b=new Fa(j);return b.Z(a.a)?b.Tb():k};a.cb=c(\"_getLinkerUrl\",52,function(b,c){var d=b[x](\"#\"),e=b,f=a.jc();if(f)if(c&&1>=d[v])e+=\"#\"+f;else if(!c||1>=d[v])1>=d[v]?e+=(R(b,\n\"?\")?D:\"?\")+f:e=d[0]+(R(b,\"?\")?D:\"?\")+f+\"#\"+d[1];return e});a.nc=function(){var b=a.m,c=a.k,d=c.g(),e=a.a+\"\",f=L.Ya(),g,h=R(d,F+e+\".\"),i=R(d,H+e),u=R(d,la+e),s,G=[],Y=\"\",Ia=!1,d=M(d)?\"\":d;if(j.w&&!a.eb){g=L[w][y]&&L[w][y].hash?L[w][y][fa][z](L[w][y][fa][q](\"#\")):\"\";j.U&&!M(g)&&(Y=g+D);Y+=L[w][y].search;if(!M(Y)&&R(Y,F))c.Sb(Y),c.Ba()||c.Qb(),s=c.ba(),a.eb=!0;g=c.ea;var va=c.Pa,U=c.Sa;M(g())||(va(Q(g())),R(g(),\";\")||U());g=c.da;va=c.X;U=c.Y;M(g())||(va(g()),R(g(),\";\")||U())}M(s)?h?(s=!i||!u)?(s=m(d,\n\";\",l(b)),a.F=!0):(s=N(d,F+e+\".\",\";\"),G=N(d,H+e,\";\")[x](\".\")):(s=[e,a.mc(),b,b,b,1][A](\".\"),Ia=a.F=!0):M(c.z())||M(c.ca())?(s=m(Y,D,l(b)),a.F=!0):(G=c.z()[x](\".\"),e=G[0]);s=s[x](\".\");L[t]&&f&&f.dh==e&&!j.o&&(s[4]=f.sid?f.sid:s[4],Ia&&(s[3]=f.sid?f.sid:s[4],f.vid&&(b=f.vid[x](\".\"),s[1]=b[0],s[2]=b[1])));c.Na(s[A](\".\"));G[0]=e;G[1]=G[1]?G[1]:0;G[2]=k!=G[2]?G[2]:j.Wb;G[3]=G[3]?G[3]:s[4];c.$(G[A](\".\"));c.Oa(e);M(c.Rb())||c.fa(c.K());c.Qa();c.aa();c.Ra()};a.oc=function(){u=new Ka(j)};a.getName=c(\"_getName\",\n58,function(){return a.n});a.c=c(\"_initData\",2,function(){var b;if(!i){if(!a.O)a.O=new La(j.ma);a.a=a.lc();a.k=new Fa(j);a.e=new Na;s=new Ma(j,l(a.a),a.k,a.e);a.oc()}if(g()){if(!i)a.oa=a.kc(a.ab,L[w].domain),b=new Z(l(a.a),a.oa,a.m,j);a.nc(b);s.$b()}if(!i)g()&&b.Pb(a.k,a.F),a.bb=new Na,$.load(j,a.k),i=!0});a.Xa=c(\"_visitCode\",54,function(){a.c();var b=N(a.k.g(),F+a.a+\".\",\";\"),b=b[x](\".\");return b[v]<4?\"\":b[1]});a.qd=c(\"_cookiePathCopy\",30,function(b){a.c();a.k&&a.k.Ub(a.a,b)});a.D=function(){return a.Xa()%\n1E4<j.L*100};a.re=c(\"_trackPageview\",1,function(b){if(g())a.c(),a.uc(b),a.F=!1});a.se=c(\"_trackTrans\",18,function(){var b=a.a,c=[],d,e,f;a.c();if(a.d&&a.D()){for(d=0;d<a.d.N[v];d++){e=a.d.N[d];T(c,e.ha());for(f=0;f<e.M[v];f++)T(c,e.M[f].ha())}for(d=0;d<c[v];d++)u.A(c[d],a.p,b,!0)}});a.me=c(\"_setTrans\",20,function(){var b,c,d,e;b=L[w].getElementById?L[w].getElementById(\"utmtrans\"):L[w].utmform&&L[w].utmform.utmtrans?L[w].utmform.utmtrans:k;a.c();if(b&&b.value){a.d=new W;e=b.value[x](\"UTM:\");j.u=!j.u||\n\"\"==j.u?\"|\":j.u;for(b=0;b<e[v];b++){e[b]=ya(e[b]);c=e[b][x](j.u);for(d=0;d<c[v];d++)c[d]=ya(c[d]);\"T\"==c[0]?a.$a(c[1],c[2],c[3],c[4],c[5],c[6],c[7],c[8]):\"I\"==c[0]&&a.ic(c[1],c[2],c[3],c[4],c[5],c[6])}}});a.$a=c(\"_addTrans\",21,function(b,c,d,e,f,g,h,i){a.d=a.d?a.d:new W;return a.d.Xb(b,c,d,e,f,g,h,i)});a.ic=c(\"_addItem\",19,function(b,c,d,e,f,g){var h;a.d=a.d?a.d:new W;(h=a.d.Va(b))||(h=a.$a(b,\"\",\"\",\"\",\"\",\"\",\"\",\"\"));h.Vb(c,d,e,f,g)});a.oe=c(\"_setVar\",22,function(b){b&&\"\"!=b&&e()&&(a.c(),s.bc(b),a.D()&&\nu.A(\"&utmt=var\",a.p,a.a))});a.Yd=c(\"_setCustomVar\",10,function(b,c,d,e){a.c();return s.ac(b,c,d,e)});a.td=c(\"_deleteCustomVar\",35,function(b){a.c();s.Yb(b)});a.Cd=c(\"_getVisitorCustomVar\",50,function(b){a.c();return s.Zb(b)});a.fe=c(\"_setMaxCustomVariables\",71,function(a){j.Ta=a});a.link=c(\"_link\",101,function(b,c){j.w&&b&&(a.c(),L.ec(a.cb(b,c)))});a.Fd=c(\"_linkByPost\",102,function(b,c){if(j.w&&b&&b.action)a.c(),b.action=a.cb(b.action,c)});a.pe=c(\"_setXKey\",83,function(b,c,d){a.e.j(b,c,d)});a.qe=\nc(\"_setXValue\",84,function(b,c,d){a.e.ja(b,c,d)});a.Dd=c(\"_getXKey\",76,function(b,c){return a.e.fc(b,c)});a.Ed=c(\"_getXValue\",77,function(b,c){return a.e.gc(b,c)});a.od=c(\"_clearXKey\",72,function(b){a.e.t(b)});a.pd=c(\"_clearXValue\",73,function(b){a.e.ia(b)});a.sd=c(\"_createXObj\",75,function(){a.c();return new Na});a.qc=c(\"_sendXEvent\",78,function(b){var c=\"\";a.c();a.D()&&(c+=\"&utmt=event&utme=\"+P(a.e.hc(b))+a.na(),u.A(c,a.p,a.a,!1,!0))});a.rd=c(\"_createEventTracker\",74,function(b){a.c();return new Oa(b,\na)});a.Za=c(\"_trackEvent\",4,function(b,c,d,e){a.c();var f=a.bb;k!=b&&k!=c&&\"\"!=b&&\"\"!=c?(f.t(5),f.ia(5),(b=f.j(5,1,b)&&f.j(5,2,c)&&(k==d||f.j(5,3,d))&&(k==e||f.ja(5,1,e)))&&a.qc(f)):b=!1;return b});a.Wa=c(\"_trackPageLoadTime\",100,function(){a.c();if(!a.pa)a.pa=new Pa(a,u);return a.pa.Wa()});a.wd=function(){return j};a.ae=c(\"_setDomainName\",6,function(a){j.b=a});a.kd=c(\"_addOrganic\",14,function(a,b,c){j.J.splice(c?0:j.J[v],0,new Ca(a,b))});a.nd=c(\"_clearOrganic\",70,function(){j.J=[]});a.hd=c(\"_addIgnoredOrganic\",\n15,function(a){T(j.V,a)});a.ld=c(\"_clearIgnoredOrganic\",97,function(){j.V=[]});a.jd=c(\"_addIgnoredRef\",31,function(a){T(j.W,a)});a.md=c(\"_clearIgnoredRef\",32,function(){j.W=[]});a.Id=c(\"_setAllowHash\",8,function(a){j.Ua=a?1:0});a.Td=c(\"_setCampaignTrack\",36,function(a){j.Ka=a?1:0});a.Ud=c(\"_setClientInfo\",66,function(a){j.ka=a?1:0});a.vd=c(\"_getClientInfo\",53,function(){return j.ka});a.Vd=c(\"_setCookiePath\",9,function(a){j.f=a});a.ne=c(\"_setTransactionDelim\",82,function(a){j.u=a});a.Xd=c(\"_setCookieTimeout\",\n25,function(b){a.rc(b*1E3)});a.rc=c(\"_setCampaignCookieTimeout\",29,function(a){j.La=a});a.Zd=c(\"_setDetectFlash\",61,function(a){j.ma=a?1:0});a.xd=c(\"_getDetectFlash\",65,function(){return j.ma});a.$d=c(\"_setDetectTitle\",62,function(a){j.la=a?1:0});a.yd=c(\"_getDetectTitle\",56,function(){return j.la});a.ce=c(\"_setLocalGifPath\",46,function(a){j.ga=a});a.zd=c(\"_getLocalGifPath\",57,function(){return j.ga});a.ee=c(\"_setLocalServerMode\",92,function(){j.B=0});a.ie=c(\"_setRemoteServerMode\",63,function(){j.B=\n1});a.de=c(\"_setLocalRemoteServerMode\",47,function(){j.B=2});a.Ad=c(\"_getServiceMode\",59,function(){return j.B});a.je=c(\"_setSampleRate\",45,function(a){j.L=a});a.ke=c(\"_setSessionTimeout\",27,function(b){a.sc(b*1E3)});a.sc=c(\"_setSessionCookieTimeout\",26,function(a){j.Ma=a});a.Jd=c(\"_setAllowLinker\",11,function(a){j.w=a?1:0});a.Hd=c(\"_setAllowAnchor\",7,function(a){j.U=a?1:0});a.Qd=c(\"_setCampNameKey\",41,function(a){j.Ca=a});a.Md=c(\"_setCampContentKey\",38,function(a){j.Da=a});a.Nd=c(\"_setCampIdKey\",\n39,function(a){j.Ea=a});a.Od=c(\"_setCampMediumKey\",40,function(a){j.Fa=a});a.Pd=c(\"_setCampNOKey\",42,function(a){j.Ga=a});a.Rd=c(\"_setCampSourceKey\",43,function(a){j.Ha=a});a.Sd=c(\"_setCampTermKey\",44,function(a){j.Ia=a});a.Ld=c(\"_setCampCIdKey\",37,function(a){j.Ja=a});a.ud=c(\"_getAccount\",64,function(){return a.p});a.Gd=c(\"_setAccount\",3,function(b){a.p=b});a.ge=c(\"_setNamespace\",48,function(a){j.o=a?P(a):k});a.Bd=c(\"_getVersion\",60,function(){return ia});a.Kd=c(\"_setAutoTrackOutbound\",79,Ba);a.le=\nc(\"_setTrackOutboundSubdomains\",81,Ba);a.be=c(\"_setHrefExamineLimit\",80,Ba);a.he=c(\"_setReferrerOverride\",49,function(b){a.ab=b});a.Wd=c(\"_setCookiePersistence\",24,function(b){a.tc(b)});a.tc=c(\"_setVisitorCookieTimeout\",28,function(a){j.s=a})};var Ra=function(){var d=this,f=sa(d);d.Ab=!1;d.Ib={};d.bd=0;d._gasoDomain=k;d._gasoCPath=k;d.ve=f(\"_getTracker\",0,function(b,f){return d.za(b,k,f)});d.za=f(\"_createTracker\",55,function(b,d,e){d&&K(23);e&&K(67);d==k&&(d=\"~\"+V.bd++);return V.Ib[d]=new Qa(d,b,e)});d.Hb=f(\"_getTrackerByName\",51,function(b){b=b||\"\";return V.Ib[b]||V.za(k,b)});d.pb=function(){var b=L.Vc();return b&&b[ka]&&b[ka]()};d.ue=f(\"_anonymizeIp\",16,function(){d.Ab=!0})};var Ta=function(){var d=this,f=sa(d);d.xe=f(\"_createAsyncTracker\",33,function(b,d){return V.za(b,d||\"\")});d.ye=f(\"_getAsyncTracker\",34,function(b){return V.Hb(b)});d.push=function(){K(5);for(var b=arguments,d=0,e=0;e<b[v];e++)try{if(typeof b[e]===\"function\")b[e]();else{var f=\"\",g=b[e][0],a=g.lastIndexOf(\".\");a>0&&(f=g[z](0,a),g=g[z](a+1));var c=f==ga?V:f==ha?Sa:V.Hb(f);c[g].apply(c,b[e].slice(1))}}catch(u){d++}return d}};var V=new Ra;var Ua=L[t][ga];Ua&&typeof Ua._getTracker==\"function\"?V=Ua:L[t][ga]=V;var Sa=new Ta;a:{var Va=L[t][ha],Wa=!1;if(Va&&typeof Va[ba]==\"function\"&&(Wa=ua(Va),!Wa))break a;L[t][ha]=Sa;Wa&&Sa[ba].apply(Sa,Va)};})();\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/modernizr/test/caniuse_files/hashchange.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n\t<meta charset=\"utf-8\" />\n\t<title>hashchange test</title>\n</head>\n<body style=\"background:red;overflow:hidden;\">\n<script>\naddEventListener('hashchange', function() {\n\tdocument.body.style.background = 'lime';\n}, false);\n\nlocation.hash = Math.random();\n</script>\n</body>\n</html>\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/modernizr/test/caniuse_files/mathml.html",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.1 plus MathML 2.0//EN\" \"http://www.w3.org/Math/DTD/mathml2/xhtml-math11-f.dtd\"><html xmlns=\"http://www.w3.org/1999/xhtml\" xmlns:html=\"http://www.w3.org/1999/xhtml\">\n<head>\n\t<meta http-equiv=\"content-type\" content=\"text/html; charset=utf-8\" />\n\t<title>Untitled</title>\n</head>\n<body>\n<math xmlns=\"http://www.w3.org/1998/Math/MathML\">\n<mrow>\n  <mi>k</mi>\n  <mo>=</mo>\n  <mfrac>\n    <mrow>\n      <mfrac>\n         <mrow>\n          <msup>\n            <mo>∂</mo>\n            <mn>2</mn>\n          </msup>\n          <mi>z</mi>\n        </mrow>\n        <mrow>\n          <mo>∂</mo>\n          <msup>\n            <mi>x</mi>\n            <mn>2</mn>\n          </msup>\n        </mrow>\n      </mfrac>\n      <mfrac>\n        <mrow>\n          <msup>\n            <mo>∂</mo>\n            <mn>2</mn>\n          </msup>\n          <mi>z</mi>\n        </mrow>\n        <mrow>\n          <mo>∂</mo>\n          <msup>\n            <mi>y</mi>\n            <mn>2</mn>\n          </msup>\n        </mrow>\n      </mfrac>\n      <mo>-</mo>\n      <msup>\n        <mrow>\n          <mo>(</mo>\n          <mfrac>\n            <mrow>\n              <msup>\n                <mo>∂</mo>\n                <mn>2</mn>\n              </msup>\n              <mi>z</mi>\n            </mrow>\n            <mrow>\n              <mo>∂</mo>\n              <mi>x</mi>\n              <mo>∂</mo>\n              <mi>y</mi>\n              </mrow>\n          </mfrac>\n          <mo>)</mo>\n        </mrow>\n        <mn>2</mn>\n      </msup>\n    </mrow>\n    <mrow>\n      <msup>\n        <mrow>\n          <mo>(</mo>\n          <mn>1</mn>\n          <mo>+</mo>\n          <msup>\n            <mrow>\n              <mo>(</mo>\n              <mfrac>\n                <mrow>\n                  <mo>∂</mo>\n                  <mi>z</mi>\n                </mrow>\n                <mrow>\n                  <mo>∂</mo>\n                  <mi>x</mi>\n                </mrow>\n              </mfrac>\n              <mo>)</mo>\n            </mrow>\n            <mn>2</mn>\n          </msup>\n          <mo>+</mo>\n          <msup>\n            <mrow>\n              <mo>(</mo>\n              <mfrac>\n                <mrow>\n                  <mo>∂</mo>\n                  <mi>z</mi>\n                </mrow>\n                <mrow>\n                  <mo>∂</mo>\n                  <mi>y</mi>\n                </mrow>\n              </mfrac>\n              <mo>)</mo>\n            </mrow>\n            <mn>2</mn>\n          </msup>\n          <mo>)</mo>\n        </mrow>\n        <mn>2</mn>\n      </msup>\n    </mrow>\n  </mfrac>\n</mrow>\n</math>\n</body>\n</html>"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/modernizr/test/caniuse_files/pushstate.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n\t<meta charset=\"utf-8\" />\n\t<title>popstate event test</title>\n</head>\n<body>\n\n<script>\n\n(function() {\n\tvar test_id;\n\t\n\tfunction showResult(r) {\n\t\tif(test_id && window.parent.setResult) {\n\t\t\tparent.setResult(test_id, r);\n\t\t} else {\n\t\t\talert(r);\n\t\t}\n\t}\n\t\n\tif(location.hash.length) {\n\t\ttest_id = location.hash.substr(1);\n\t}\n\t\n\tif(history.pushState) {\n\t\tvar rand = Math.random();\n\t\tsetTimeout(function() {\n\t\t\thistory.pushState({foo: 'bar'}, \"title\", './' + rand);\n\t\t\tvar result = (location.href.indexOf(rand) > -1);\n\t\t\tshowResult(result);\n\t\t}, 100);\n\t} \n\t\n})();\n\n</script>\n\n</body>\n</html>\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/modernizr/test/caniuse_files/style.css",
    "content": "body {\n\tfont-family: \"Lucida Grande\", Lucida, Verdana, sans-serif;\n\tfont-size: 12px;\n}\n\na {\n\ttext-decoration: none;\n}\na:hover {\n\ttext-decoration: underline;\n}\n\ntable, tr, th, td {\n\tborder: 1px solid #AAA;\n}\n\ntable {\n\tmargin-top: 1em;\n\twidth: 100%;\n}\n\ntbody th {\n\ttext-align: left;\n\tfont-size: 14px;\n\twidth: 200px;\n}\n\nth h3 {\n\tmargin: 3px;\n\tfont-size: 12px;\n}\n\nth span.links {\n\tfont-size: 10px;\n}\n\ndt {\n\tfont-weight: bold;\n}\n\ntr:hover > th,\ntr:hover > td + td { background-color: #FFC; }\n\ndiv.test_wrap {\n\tdisplay: -moz-inline-stack;\n\tdisplay: inline-block;\n\tborder: 1px solid #CCC;\n\ttext-align: center;\n\tvertical-align: top;\n\tmin-height: 50px;\n\tmargin-right: 5px;\n\tbackground: white;\n\tposition: relative;\n}\n\ndiv.test_wrap h3 {\n\ttext-align: center;\n\tmargin: 2px;\n\tfont-size: 10px;\n}\n\ndiv.auto {\n\tdisplay: -moz-inline-stack;\n\tdisplay: inline-block;\n\tborder: 1px solid;\n\twidth: 30px;\n\theight: 30px;\n}\n\ndiv.square {\n\tdisplay: -moz-inline-stack;\n\tdisplay: inline-block;\n\tborder: 1px solid;\n\twidth: 30px;\n\theight: 30px;\n\tbackground: red;\n}\n\ndiv.info {\n\tdisplay: none;\n\tposition: absolute;\n\ttop: 100%;\n\tz-index: 2;\n\tleft: 0;\n\tbackground: white;\n\tpadding: 2px;\n\tmin-width: 300px;\n\tborder: 1px solid;\n\ttext-align: left;\n}\n\ndiv.test_wrap:hover > div.info {\n\tdisplay: block;\n}\n\n\ndiv.vis_test {\n\tdisplay: -moz-inline-stack;\n\tdisplay: inline-block;\n}\n\ndiv.vis_ref {\n\tdisplay: -moz-inline-stack;\n\tdisplay: inline-block;\n\tborder-left: 1px dashed black;\n\tmargin-left: 5px;\n\tpadding-left: 5px;\n\tvertical-align: top;\n}\n\np.condition {\n\tfont-style: italic;\n\tmargin: 2px;\n\tclear: both;\n}\n\n.pass {\n  background: lime;\n}\n\n.fail {\n  background: red;\n}\n\n.partial {\n  background: yellow;\n}\n\n.unknown {\n  background: #aaa;\n}\n\n.current span {\n    border-radius: 6px;\n    -moz-border-radius: 6px;\n    background: none repeat scroll 0 0 #E6EA69;\n    color: black;\n    float: right;\n    font-size: 8px;\n    padding: 0 1px;\n}\n\n#intro, #options {\n\twidth: 400px;\n\tbackground: #EEE;\n\tborder-radius: 10px;\n\tpadding: 5px 10px;\n\tmargin: 10px;\n\tfloat: left;\n}\n\n#intro dt::after {\n\tcontent: ':';\n}\n\n#intro dd {\n\tmargin-bottom: 1em;\n}\n\n#opt_submit {\n\tdisplay: block;\n\tmargin: 10px;\n}\n\n#options label {\n\tdisplay: block;\n\tmargin: 5px;\n}"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/modernizr/test/caniuse_files/svg-img.svg.1",
    "content": "<?xml version=\"1.0\"?>\n<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 30 30\"> \n    <rect fill=\"#00ff00\" x=\"0\" y=\"0\" width=\"30\" height=\"30\"> \n</rect>\n</svg>"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/modernizr/test/caniuse_files/xhtml.html",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\"><html xmlns=\"http://www.w3.org/1999/xhtml\">\n<head>\n\t<meta http-equiv=\"content-type\" content=\"text/html; charset=utf-8\" />\n\t<title>Untitled</title>\n</head>\n<body><p>true</p>\t\n\t<script>\n\t<![CDATA[\n\twindow.parent.setResult('xhtml0', document.body.firstChild.textContent == 'true');\n\t]]>\n\t</script>\n</body>\n</html>"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/modernizr/test/index.html",
    "content": "<!DOCTYPE html>\n<html class=\"+no-js no-js- no-js i-has-no-js\">\n<head>\n  <meta charset=\"UTF-8\">\n  <title>Modernizr Test Suite</title>\n  <link rel=\"stylesheet\" href=\"qunit/qunit.css\">\n  <style>\n     body { margin-bottom: 150px;}\n     #testbed { font-family: Helvetica; color: #444; padding-bottom: 100px;}\n     #testbed button { margin: 30px; font-size: 13px;}\n     .data-notes, .offScreen { display:none;}\n     table { width: 100%;}\n     tbody tr:nth-child(even) td, tbody tr:nth-child(even) th {  border: 1px solid #ccc; border-left: 0; border-right: 0;}\n     table td:nth-child(even), table th:nth-child(even) { background: #e6e6e6;}\n     table tbody tr:hover td, table tbody tr:hover th { background: #e1e100!important;}\n     td.wrong { background:red!important;}\n     #html5section { visibility: hidden; }\n     h1 label { display:none;}\n     .output { padding: 0 0 0 16px;}\n     .output ul { margin: 0;}\n     .output li { color: #854747; }\n     .output li.yes{color:#090;}\n     .output li b{color:#000;}\n     .output {font:14px/1.3 Inconsolata,Consolas,monospace;\n                    -webkit-column-count: 5;\n                       -moz-column-count: 5;\n                            column-count: 5;}\n      .output + .output { border-top: 5px solid #ccc; }\n      textarea { width: 100%; min-height: 75px;}\n      #caniusetrigger { font-size: 38px; font-family: monospace; display:block; }\n  </style>\n\n\n  <script>window.Modernizr || document.write('<script src=\"../modernizr.js\"><\\/script>')</script>\n\n  <script src=\"https://raw.github.com/Modernizr/Modernizr/master/modernizr.js\"></script>\n\n  <script src=\"js/lib/polyfills.js\"></script>\n  <script src=\"js/lib/detect-global.js\"></script>\n\n  <script src=\"qunit/qunit.js\"></script>\n  <script src=\"js/lib/jquery-1.7b2.js\"></script>\n\n  <script src=\"js/lib/jsonselect.js\"></script>\n  <script src=\"js/lib/uaparser.js\"></script>\n  <script src=\"js/lib/github.js\"></script>\n\n  <script src=\"js/setup.js\"></script>\n\n  <script src=\"js/unit.js\"></script>\n  <script src=\"js/unit-caniuse.js\"></script>\n</head>\n<body>\n  <h1 id=\"qunit-header\">Modernizr Test Suite</h1>\n  <h2 id=\"qunit-banner\"></h2>\n  <div id=\"qunit-testrunner-toolbar\"></div>\n  <h2 id=\"qunit-userAgent\"></h2>\n\n  <ol id=\"qunit-tests\"></ol>\n\n  <div id=\"mod-output\" class=output></div>\n  <div id=\"mod-feattest-output\" class=output></div>\n\n\n  <br>\n\n  <section><aside>this is an aside within a section</aside></section>\n\n\n\n\n  <h5>JSON.stringify(Modernizr)</h5>\n  <textarea></textarea>\n  <a href=\"#\"   id=\"caniusetrigger\"\n                onclick=\"return revealreftests(this)\"\n                title=\"add a #caniuse hash to this page to make this automatic\"\n                >Show the Ref Tests from Caniuse and Modernizr</a>\n\n\n  <script src=\"js/dumpdata.js\"></script>\n  <script>\n    function revealreftests(a){\n\n        if (!a) a = document.getElementById('caniusetrigger');\n        a.parentNode && a.parentNode.removeChild(a);\n\n        var iframe = document.createElement('iframe');\n        iframe.src = 'caniuse.html';\n        iframe.style.cssText = 'width: 100%; height: 7000px; border: 15px double #F0C; \\\n                                -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; ';\n        document.body.appendChild(iframe);\n\n        return false;\n    }\n\n    if (location.hash.replace(/^#/,'') == 'caniuse'){\n        setTimeout(revealreftests, 100);\n    }\n\n  </script>\n\n\n</body>\n</html>\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/modernizr/test/js/basic.html",
    "content": "<!DOCTYPE html>\n<html class=\"+no-js no-js- no-js i-has-no-js\">\n<head>\n  <meta charset=\"UTF-8\">\n  <title>Modernizr Test Suite</title>\n  <link rel=\"stylesheet\" href=\"qunit/qunit.css\">\n  <style>\n     body { margin-bottom: 150px;}\n     #testbed { font-family: Helvetica; color: #444; padding-bottom: 100px;}\n     #testbed button { margin: 30px; font-size: 13px;}\n     .data-notes, .offScreen { display:none;}\n     table { width: 100%;}\n     tbody tr:nth-child(even) td, tbody tr:nth-child(even) th {  border: 1px solid #ccc; border-left: 0; border-right: 0;}\n     table td:nth-child(even), table th:nth-child(even) { background: #e6e6e6;}\n     table tbody tr:hover td, table tbody tr:hover th { background: #e1e100!important;}\n     td.wrong { background:red!important;}\n     #html5section { visibility: hidden; }\n     h1 label { display:none;}\n     .output { padding: 0 0 0 16px;}\n     .output ul { margin: 0;}\n     .output li { color: #854747; }\n     .output li.yes{color:#090;}\n     .output li b{color:#000;}\n     .output {font:14px/1.3 Inconsolata,Consolas,monospace;\n                    -webkit-column-count: 5;\n                       -moz-column-count: 5;\n                            column-count: 5;}\n      .output + .output { border-top: 5px solid #ccc; }\n      textarea { width: 100%; min-height: 75px;}\n      #caniusetrigger { font-size: 38px; font-family: monospace; display:block; }\n  </style>\n\n  <script src=\"https://raw.github.com/Modernizr/Modernizr/master/modernizr.js\"></script>\n\n  <script>window.Modernizr || document.write('<script src=\"../modernizr.js\"><\\/script>'); console.log(\"Loading in the /js folder *trollface*\")</script>\n\n  <script src=\"js/lib/polyfills.js\"></script>\n  <script src=\"js/lib/detect-global.js\"></script>\n  \n  <script src=\"qunit/qunit.js\"></script>\n  <script src=\"js/lib/jquery-1.7b2.js\"></script>\n  \n  <script src=\"js/setup.js\"></script>\n  \n  <script src=\"js/unit.js\"></script>\n</head>\n<body>\n  <h1 id=\"qunit-header\">Modernizr Test Suite</h1>\n  <h2 id=\"qunit-banner\"></h2>\n  <div id=\"qunit-testrunner-toolbar\"></div>\n  <h2 id=\"qunit-userAgent\"></h2>\n\n  <ol id=\"qunit-tests\"></ol>\n\n  <div id=\"mod-output\" class=output></div>\n  <div id=\"mod-feattest-output\" class=output></div>\n\n\n  <br>\n \n  <section><aside>this is an aside within a section</aside></section>\n  \n  \n</body>\n</html> \n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/modernizr/test/js/dumpdata.js",
    "content": "function dumpModernizr(){\n  var str = '';\n  dumpModernizr.old = dumpModernizr.old || {};\n\n    for (var prop in Modernizr) {\n\n      // skip previously done ones.\n      if (dumpModernizr.old[prop]) continue;\n      else dumpModernizr.old[prop] = true;\n\n      if (typeof Modernizr[prop] === 'function') continue;\n      // skip unit test items\n      if (/^test/.test(prop)) continue;\n\n      if (~TEST.inputs.indexOf(prop)) {\n        str += '<li><b>'+prop+'{}</b><ul>';\n        for (var field in Modernizr[prop]) {\n          str += '<li class=\"' + (Modernizr[prop][field] ? 'yes' : '') + '\">' + field + ': ' + Modernizr[prop][field] + '</li>';\n        }\n        str += '</ul></li>';\n      } else {\n        str += '<li  id=\"'+prop+'\" class=\"' + (Modernizr[prop] ? 'yes' : '') + '\">' + prop + ': ' + Modernizr[prop] + '</li>';\n      }\n  }\n  return str;\n}\n\n\nfunction grabFeatDetects(){\n  // thx github.js\n  $.getScript('https://api.github.com/repos/Modernizr/Modernizr/git/trees/master?recursive=1&callback=processTree');\n}\n\n\nfunction processTree(data){\n  var filenames = [];\n\n  for (var i = 0; i < data.data.tree.length; i++){\n    var file = data.data.tree[i];\n    var match = file.path.match(/^feature-detects\\/(.*)/);\n    if (!match) continue;\n\n    var relpath = location.host == \"modernizr.github.com\" ?\n                    '../modernizr-git/' : '../';\n\n    filenames.push(relpath + match[0]);\n  }\n\n  var jqxhrs = filenames.map(function(filename){\n    return jQuery.getScript(filename);\n  });\n\n  jQuery.when.apply(jQuery, jqxhrs).done(resultsToDOM);\n\n}\n\nfunction resultsToDOM(){\n\n  var modOutput = document.createElement('div'),\n      ref = document.getElementById('qunit-testresult') || document.getElementById('qunit-tests');\n\n  modOutput.className = 'output';\n  modOutput.innerHTML = dumpModernizr();\n\n  ref.parentNode.insertBefore(modOutput, ref);\n\n  // Modernizr object as text\n  document.getElementsByTagName('textarea')[0].innerHTML = JSON.stringify(Modernizr);\n\n}\n\n/* uno    */ resultsToDOM();\n/* dos    */ grabFeatDetects();\n/* tres   */ setTimeout(resultsToDOM,  5e3);\n/* quatro */ setTimeout(resultsToDOM, 15e3);\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/modernizr/test/js/lib/detect-global.js",
    "content": "// https://github.com/kangax/detect-global\n\n// tweaked to run without a UI.\n\n(function () {\n    function getPropertyDescriptors(object) {\n      var props = { };\n      for (var prop in object) {\n        \n        // nerfing for firefox who goes crazy over some objects like sessionStorage\n        try {\n          \n          props[prop] = {\n            type:  typeof object[prop],\n            value: object[prop]\n          };\n          \n        } catch(e){\n          props[prop] = {}; \n        }\n      }\n      return props;\n    }\n    \n    function getCleanWindow() {\n      var elIframe = document.createElement('iframe');\n      elIframe.style.display = 'none';\n      \n      var ref = document.getElementsByTagName('script')[0];\n      ref.parentNode.insertBefore(elIframe, ref);\n      \n      elIframe.src = 'about:blank';\n      return elIframe.contentWindow;\n    }\n    \n    function appendControl(el, name) {\n      var elCheckbox = document.createElement('input');\n      elCheckbox.type = 'checkbox';\n      elCheckbox.checked = true;\n      elCheckbox.id = '__' + name;\n      \n      var elLabel = document.createElement('label');\n      elLabel.htmlFor = '__' + name;\n      elLabel.innerHTML = 'Exclude ' + name + ' properties?';\n      elLabel.style.marginLeft = '0.5em';\n      \n      var elWrapper = document.createElement('p');\n      elWrapper.style.marginBottom = '0.5em';\n      \n      elWrapper.appendChild(elCheckbox);\n      elWrapper.appendChild(elLabel);\n\n      el.appendChild(elWrapper);\n    }\n    \n    function appendAnalyze(el) {\n      var elAnalyze = document.createElement('button');\n      elAnalyze.id = '__analyze';\n      elAnalyze.innerHTML = 'Analyze';\n      elAnalyze.style.marginTop = '1em';\n      el.appendChild(elAnalyze);\n    }\n    \n    function appendCancel(el) {\n      var elCancel = document.createElement('a');\n      elCancel.href = '#';\n      elCancel.innerHTML = 'Cancel';\n      elCancel.style.cssText = 'color:#eee;margin-left:0.5em;';\n      elCancel.onclick = function() {\n        el.parentNode.removeChild(el);\n        return false; \n      };\n      el.appendChild(elCancel);\n    }\n    \n    function initConfigPopup() {\n      var el = document.createElement('div');\n      \n      el.style.cssText =  'position:fixed; left:10px; top:10px; width:300px; background:rgba(50,50,50,0.9);' +\n                          '-moz-border-radius:10px; padding:1em; color: #eee; text-align: left;' +\n                          'font-family: \"Helvetica Neue\", Verdana, Arial, sans serif; z-index: 99999;';\n      \n      for (var prop in propSets) {\n        appendControl(el, prop);\n      }\n      \n      appendAnalyze(el);\n      appendCancel(el);\n      \n      var ref = document.getElementsByTagName('script')[0];\n      ref.parentNode.insertBefore(el, ref);\n    }\n    \n    function getPropsCount(object) {\n      var count = 0;\n      for (var prop in object) {\n        count++;\n      }\n      return count;\n    }\n    \n    function shouldDeleteProperty(propToCheck) {\n      for (var prop in propSets) {\n        var elCheckbox = document.getElementById('__' + prop);\n        var isPropInSet = propSets[prop].indexOf(propToCheck) > -1;\n        if (isPropInSet && (elCheckbox ? elCheckbox.checked : true) ) {\n          return true;\n        }\n      }\n    }\n    \n    function analyze() {\n      var global = (function(){ return this; })(),\n          globalProps = getPropertyDescriptors(global),\n          cleanWindow = getCleanWindow();\n          \n      for (var prop in cleanWindow) {\n        if (globalProps[prop]) {\n          delete globalProps[prop];\n        }\n      }\n      for (var prop in globalProps) {\n        if (shouldDeleteProperty(prop)) {\n          delete globalProps[prop];\n        }\n      }\n      \n      window.__globalsCount = getPropsCount(globalProps);\n      window.__globals      = globalProps;\n      \n      window.console && console.log('Total number of global properties: ' + __globalsCount);\n      window.console && console.dir(__globals);\n    }\n    \n    var propSets = {\n      'Prototype':        '$$ $A $F $H $R $break $continue $w Abstract Ajax Class Enumerable Element Field Form ' +\n                          'Hash Insertion ObjectRange PeriodicalExecuter Position Prototype Selector Template Toggle Try'.split(' '),\n                        \n      'Scriptaculous':    'Autocompleter Builder Control Draggable Draggables Droppables Effect Sortable SortableObserver Sound Scriptaculous'.split(' '),\n      'Firebug':          'loadFirebugConsole console _getFirebugConsoleElement _FirebugConsole _FirebugCommandLine _firebug'.split(' '),\n      'Mozilla':          'Components XPCNativeWrapper XPCSafeJSObjectWrapper getInterface netscape GetWeakReference GeckoActiveXObject'.split(' '),\n      'GoogleAnalytics':  'gaJsHost gaGlobal _gat _gaq pageTracker'.split(' '),\n      'lazyGlobals':      'onhashchange'.split(' ')\n    };\n    \n    // initConfigPopup(); // disable because we're going UI-less.\n    \n    var analyzeElem = document.getElementById('__analyze');\n    analyzeElem && (analyzeElem.onclick = analyze);\n    \n    analyze(); // and assign total added globals to window.__globalsCount\n    \n})();"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/modernizr/test/js/lib/jquery-1.7b2.js",
    "content": "/*!\n * jQuery JavaScript Library v1.7b2\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 Oct 13 21:12:55 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// 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// 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// 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.7b2\",\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\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\" ).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.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 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\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 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// 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, 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\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.\nif ( typeof define === \"function\" && define.amd && define.amd.jQuery ) {\n\tdefine( \"jquery\", [], function () { return jQuery; } );\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\treturn deferred.done.apply( deferred, arguments ).fail.apply( deferred, arguments );\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 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\ttestElementParent,\n\t\ttestElement,\n\t\ttestElementStyle,\n\t\ttds,\n\t\tevents,\n\t\teventName,\n\t\ti,\n\t\tisSupported,\n\t\toffsetSupport;\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'/><nav></nav>\";\n\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 unknown elements (like HTML5 elems) are handled appropriately\n\t\tunknownElems: !!div.getElementsByTagName( \"nav\" ).length,\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() {\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.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 don't want to do body-related feature tests on frameset\n\t// documents, which lack a body. So we use\n\t// document.getElementsByTagName(\"body\")[0], which is undefined in\n\t// frameset documents, while document.body isn’t. (7398)\n\tbody = document.getElementsByTagName(\"body\")[ 0 ];\n\t// We use our own, invisible, body unless the body is already present\n\t// in which case we use a div (#9239)\n\ttestElement = document.createElement( body ? \"div\" : \"body\" );\n\ttestElementStyle = {\n\t\tvisibility: \"hidden\",\n\t\twidth: 0,\n\t\theight: 0,\n\t\tborder: 0,\n\t\tmargin: 0,\n\t\tbackground: \"none\"\n\t};\n\tif ( body ) {\n\t\tjQuery.extend( testElementStyle, {\n\t\t\tposition: \"absolute\",\n\t\t\tleft: \"-999px\",\n\t\t\ttop: \"-999px\"\n\t\t});\n\t}\n\tfor ( i in testElementStyle ) {\n\t\ttestElement.style[ i ] = testElementStyle[ i ];\n\t}\n\ttestElement.appendChild( div );\n\ttestElementParent = body || documentElement;\n\ttestElementParent.insertBefore( testElement, testElementParent.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\ttestElement.innerHTML = \"\";\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\t// Determine fixed-position support early\n\ttestElement.style.position = \"static\";\n\ttestElement.style.top = \"0px\";\n\ttestElement.style.marginTop = \"1px\";\n\toffsetSupport = (function( body, container ) {\n\n\t\tvar outer, inner, table, td, supports,\n\t\t\tbodyMarginTop = parseFloat( body.style.marginTop ) || 0,\n\t\t\tptlm = \"position:absolute;top:0;left:0;width:1px;height:1px;margin:0;\",\n\t\t\tstyle = \"style='\" + ptlm + \"border:5px solid #000;padding:0;'\",\n\t\t\thtml = \"<div \" + style + \"><div></div></div>\" +\n\t\t\t\t\t\t\t\"<table \" + style + \" cellpadding='0' cellspacing='0'>\" +\n\t\t\t\t\t\t\t\"<tr><td></td></tr></table>\";\n\n\t\tcontainer.style.cssText = ptlm + \"border:0;visibility:hidden\";\n\n\t\tcontainer.innerHTML = html;\n\t\tbody.insertBefore( container, body.firstChild );\n\t\touter = container.firstChild;\n\t\tinner = outer.firstChild;\n\t\ttd = outer.nextSibling.firstChild.firstChild;\n\n\t\tsupports = {\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\tsupports.supportsFixedPosition = (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\tsupports.subtractsBorderForOverflowNotVisible = (inner.offsetTop === -5);\n\t\tsupports.doesNotIncludeMarginInBodyOffset = (body.offsetTop !== bodyMarginTop);\n\n\t\treturn supports;\n\n\t})( testElement, div );\n\n\tjQuery.extend( support, offsetSupport );\n\ttestElementParent.removeChild( testElement );\n\n\t// Null connected elements to avoid leaks in IE\n\ttestElement = fragment = select = opt = body = marginDiv = div = input = null;\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])/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 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[ 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 || !cache[id] || (!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[ 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// 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\tthisCache = 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// 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\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[ 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\n\t\t\tthisCache = pvt ? cache[ id ] : cache[ id ].data;\n\n\t\t\tif ( thisCache ) {\n\n\t\t\t\t// Support space separated names\n\t\t\t\tif ( jQuery.isArray( name ) ) {\n\t\t\t\t\tname = name;\n\t\t\t\t} else if ( 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\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\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[ 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 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 $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\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\trunner = {};\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\", runner );\n\t\t\tfn.call( elem, function() {\n\t\t\t\tjQuery.dequeue( elem, type );\n\t\t\t}, runner );\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, runner ) {\n\t\t\tvar timeout = setTimeout( next, time );\n\t\t\trunner.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\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\tfor ( var i = 0, l = this.length; 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,\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 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\n\tattr: function( elem, name, value, pass ) {\n\t\tvar nType = 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 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\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 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 && (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 ( elem.nodeType === 1 ) {\n\t\t\tattrNames = (value || \"\").split( rspace );\n\t\t\tl = attrNames.length;\n\n\t\t\tfor ( ; i < l; i++ ) {\n\t\t\t\tname = attrNames[ i ].toLowerCase();\n\n\t\t\t\t// See #9699 for explanation of this approach (setting first, then removal)\n\t\t\t\tjQuery.attr( elem, name, \"\" );\n\t\t\t\telem.removeAttribute( name );\n\n\t\t\t\t// Set corresponding property to false for boolean attributes\n\t\t\t\tif ( rboolean.test( name ) && (propName = jQuery.propFix[ name ] || name) in elem ) {\n\t\t\t\t\telem[ propName ] = false;\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 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\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 ( !jQuery.support.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// 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 rnamespaces = /\\.(.*)$/,\n\trformElems = /^(?:textarea|input|select)$/i,\n\trperiod = /\\./g,\n\trspaces = / /g,\n\trescape = /[^\\w\\s.|`]/g,\n\trtypenamespace = /^([^\\.]*)?(?:\\.(.+))?$/,\n\trhoverHack = /\\bhover(\\.\\S+)?/,\n\trkeyEvent = /^key/,\n\trmouseEvent = /^(?:mouse|contextmenu)|click/,\n\trquickIs = /^([\\w\\-]+)?(?:#([\\w\\-]+))?(?:\\.([\\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      4         5\n\t\t\t// [ _, tag, id, class, attrName, attrValue ]\n\t\t\tquick[1] = ( quick[1] || \"\" ).toLowerCase();\n\t\t\tquick[3] = quick[3] && new RegExp( \"\\\\b\" + quick[3] + \"\\\\b\" );\n\t\t}\n\t\treturn quick;\n\t},\n\tquickIs = function( elem, m ) {\n\t\treturn (\n\t\t\t(!m[1] || elem.nodeName.toLowerCase() === m[1]) &&\n\t\t\t(!m[2] || elem.id === m[2]) &&\n\t\t\t(!m[3] || m[3].test( elem.className )) &&\n\t\t\t(!m[4] || elem.getAttribute( m[4] ) == m[5])\n\t\t);\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.handle.apply( eventHandle.elem, arguments ) :\n\t\t\t\t\tundefined;\n\t\t\t};\n\t\t\t// Add elem as a property of the handle fn to prevent a memory leak with IE non-native events\n\t\t\teventHandle.elem = elem;\n\t\t}\n\n\t\t// Handle multiple events separated by a space\n\t\t// jQuery(...).bind(\"mouseover mouseout\", fn);\n\t\ttypes = types.replace( rhoverHack, \"mouseover$1 mouseout$1\" ).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\tnamespace: namespaces.join(\".\")\n\t\t\t}, handleObjIn );\n\n\t\t\t// Delegated event; pre-analyze selector so it's processed quickly on event dispatch\n\t\t\tif ( selector ) {\n\t\t\t\thandleObj.quick = quickParse( selector );\n\t\t\t\tif ( !handleObj.quick && jQuery.expr.match.POS.test( selector ) ) {\n\t\t\t\t\thandleObj.isPositional = true;\n\t\t\t\t}\n\t\t\t}\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 ) {\n\n\t\tvar elemData = jQuery.hasData( elem ) && jQuery._data( elem ),\n\t\t\tt, tns, type, 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// For removal, types can be an Event object\n\t\tif ( types && types.type && types.handler ) {\n\t\t\thandler = types.handler;\n\t\t\ttypes = types.type;\n\t\t\tselector = types.selector;\n\t\t}\n\n\t\t// Once for each type.namespace in types; type may be omitted\n\t\ttypes = (types || \"\").replace( rhoverHack, \"mouseover$1 mouseout$1\" ).split(\" \");\n\t\tfor ( t = 0; t < types.length; t++ ) {\n\t\t\ttns = rtypenamespace.exec( types[t] ) || [];\n\t\t\ttype = 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\tnamespaces = namespaces? \".\" + namespaces : \"\";\n\t\t\t\tfor ( j in events ) {\n\t\t\t\t\tjQuery.event.remove( elem, j + namespaces, handler, selector );\n\t\t\t\t}\n\t\t\t\treturn;\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// Only need to loop for special events or selective removal\n\t\t\tif ( handler || namespaces || selector || special.remove ) {\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 ( !handler || handler.guid === handleObj.guid ) {\n\t\t\t\t\t\tif ( !namespaces || namespaces.test( handleObj.namespace ) ) {\n\t\t\t\t\t\t\tif ( !selector || selector === handleObj.selector || selector === \"**\" && handleObj.selector ) {\n\t\t\t\t\t\t\t\teventType.splice( j--, 1 );\n\n\t\t\t\t\t\t\t\tif ( handleObj.selector ) {\n\t\t\t\t\t\t\t\t\teventType.delegateCount--;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif ( special.remove ) {\n\t\t\t\t\t\t\t\t\tspecial.remove.call( elem, handleObj );\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// Removing all events\n\t\t\t\teventType.length = 0;\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\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// 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}\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\tevent.stopPropagation();\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 );\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\told = null;\n\t\t\tfor ( cur = elem.parentNode; 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; 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\thandle = ontype && cur[ ontype ];\n\t\t\tif ( handle && jQuery.acceptData( cur ) ) {\n\t\t\t\thandle.apply( cur, data );\n\t\t\t}\n\n\t\t\tif ( event.isPropagationStopped() ) {\n\t\t\t\tbreak;\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 ( !event.isDefaultPrevented() ) {\n\n\t\t\tif ( (!special._default || special._default.call( elem.ownerDocument, event, 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\thandle: 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\thandlerQueue = [],\n\t\t\ti, cur, selMatch, matches, handleObj, sel, hit, related;\n\n\t\t// Use the fix-ed jQuery.Event rather than the (read-only) native event\n\t\targs[0] = event;\n\n\t\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\tfor ( cur = event.target; cur != this; cur = cur.parentNode || this ) {\n\t\t\t\tselMatch = {};\n\t\t\t\tmatches = [];\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\t\t\t\t\thit = selMatch[ sel ];\n\n\t\t\t\t\tif ( handleObj.isPositional ) {\n\t\t\t\t\t\t// Since .is() does not work for positionals; see http://jsfiddle.net/eJ4yd/3/\n\t\t\t\t\t\thit = ( hit || (selMatch[ sel ] = jQuery( sel )) ).index( cur ) >= 0;\n\t\t\t\t\t} else if ( hit === undefined ) {\n\t\t\t\t\t\thit = selMatch[ sel ] = ( handleObj.quick ? quickIs( cur, handleObj.quick ) : jQuery( cur ).is( sel ) );\n\t\t\t\t\t}\n\t\t\t\t\tif ( hit ) {\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// Copy the remaining (bound) handlers in case they're changed\n\t\thandlers = handlers.slice( delegateCount );\n\n\t\t// Run delegates first; they may want to stop propagation beneath us\n\t\tevent.delegateTarget = this;\n\t\tfor ( i = 0; i < handlerQueue.length && !event.isPropagationStopped(); i++ ) {\n\t\t\tmatched = handlerQueue[ i ];\n\t\t\tdispatch( matched.elem, event, matched.matches, args );\n\t\t}\n\t\tdelete event.delegateTarget;\n\n\t\t// Run non-delegated handlers for this level\n\t\tif ( handlers.length ) {\n\t\t\tdispatch( this, event, handlers, args );\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 layerX layerY offsetX offsetY pageX pageY screenX screenY toElement wheelDelta\".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\tfocus: {\n\t\t\tdelegateType: \"focusin\",\n\t\t\tnoBubble: true\n\t\t},\n\t\tblur: {\n\t\t\tdelegateType: \"focusout\",\n\t\t\tnoBubble: true\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.handle.call( elem, e );\n\t\t}\n\t\tif ( e.isDefaultPrevented() ) {\n\t\t\tevent.preventDefault();\n\t\t}\n\t}\n};\n\n// Run jQuery handler functions; called from jQuery.event.handle\nfunction dispatch( target, event, handlers, args ) {\n\tvar run_all = !event.exclusive && !event.namespace,\n\t\tspecialHandle = ( jQuery.event.special[ event.type ] || {} ).handle,\n\t\tj, handleObj, ret;\n\n\tevent.currentTarget = target;\n\tfor ( j = 0; j < handlers.length && !event.isImmediatePropagationStopped(); j++ ) {\n\t\thandleObj = handlers[ j ];\n\n\t\t// Triggered event must either 1) be non-exclusive and have no namespace, or\n\t\t// 2) have namespace(s) a subset or equal to those in the bound event (both can have no namespace).\n\t\tif ( run_all || (!event.namespace && !handleObj.namespace) || event.namespace_re && event.namespace_re.test( handleObj.namespace ) ) {\n\n\t\t\t// Pass in a reference to the handler function itself\n\t\t\t// So that we can later remove it\n\t\t\tevent.handler = handleObj.handler;\n\t\t\tevent.data = handleObj.data;\n\t\t\tevent.handleObj = handleObj;\n\n\t\t\tret = ( specialHandle || handleObj.handler ).apply( target, args );\n\n\t\t\tif ( ret !== undefined ) {\n\t\t\t\tevent.result = ret;\n\t\t\t\tif ( ret === false ) {\n\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\tevent.stopPropagation();\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 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 ] = jQuery.event.special[ fix ] = {\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\toldType, ret;\n\n\t\t\t// For a real mouseover/out, always call the handler; for\n\t\t\t// 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 || handleObj.origType === event.type || (related !== target && !jQuery.contains( target, related )) ) {\n\t\t\t\toldType = event.type;\n\t\t\t\tevent.type = handleObj.origType;\n\t\t\t\tret = handleObj.handler.apply( this, arguments );\n\t\t\t\tevent.type = oldType;\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// Form was submitted, bubble the event up the tree\n\t\t\t\t\t\tif ( this.parentNode ) {\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 ) {\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 ) {\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\tjQuery.event.remove( event.delegateTarget || this, 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 ) {\n\t\t\t// ( event )  native or jQuery.Event\n\t\t\treturn this.off( types.type, types.handler, types.selector );\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.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\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 \"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 ) {\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\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\nfunction createSafeFragment( document ) {\n\tvar nodeNames = (\n\t\t\"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\t).split( \" \" ),\n\tsafeFrag = document.createDocumentFragment();\n\n\tif ( safeFrag.createElement ) {\n\t\twhile ( nodeNames.length ) {\n\t\t\tsafeFrag.createElement(\n\t\t\t\tnodeNames.pop()\n\t\t\t);\n\t\t}\n\t}\n\treturn safeFrag;\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\trnoInnerhtml = /<(?:script|style)/i,\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\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\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\" && !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\n  // nodes may contain either an explicit document object,\n  // a jQuery collection or context object.\n  // If nodes[0] contains a valid object to assign to doc\n  if ( nodes && nodes[0] ) {\n    doc = nodes[0].ownerDocument || nodes[0];\n  }\n\n  // 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\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 ( 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\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\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\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\n\t// Start with offset property\n\tvar val = name === \"width\" ? elem.offsetWidth : elem.offsetHeight,\n\t\twhich = name === \"width\" ? cssWidth : cssHeight;\n\n\tif ( val > 0 ) {\n\t\tif ( extra !== \"border\" ) {\n\t\t\tjQuery.each( which, function() {\n\t\t\t\tif ( !extra ) {\n\t\t\t\t\tval -= parseFloat( jQuery.css( elem, \"padding\" + this ) ) || 0;\n\t\t\t\t}\n\t\t\t\tif ( extra === \"margin\" ) {\n\t\t\t\t\tval += parseFloat( jQuery.css( elem, extra + this ) ) || 0;\n\t\t\t\t} else {\n\t\t\t\t\tval -= parseFloat( jQuery.css( elem, \"border\" + this + \"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\tjQuery.each( which, function() {\n\t\t\tval += parseFloat( jQuery.css( elem, \"padding\" + this ) ) || 0;\n\t\t\tif ( extra !== \"padding\" ) {\n\t\t\t\tval += parseFloat( jQuery.css( elem, \"border\" + this + \"Width\" ) ) || 0;\n\t\t\t}\n\t\t\tif ( extra === \"margin\" ) {\n\t\t\t\tval += parseFloat( jQuery.css( elem, extra + this ) ) || 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.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// 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\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\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 === \"none\" || ( 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\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 i,\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, i ) {\n\t\t\t\tvar runner = data[ i ];\n\t\t\t\tjQuery.removeData( elem, i, true );\n\t\t\t\trunner.stop( gotoEnd );\n\t\t\t}\n\n\t\t\tif ( type == null ) {\n\t\t\t\tfor ( i in data ) {\n\t\t\t\t\tif ( data[ i ].stop && i.indexOf(\".run\") === i.length - 4 ) {\n\t\t\t\t\t\tstopQueue( this, data, i );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else if ( data[ i = type + \".run\" ] && data[ i ].stop ){\n\t\t\t\tstopQueue( this, data, i );\n\t\t\t}\n\n\t\t\tfor ( i = timers.length; i--; ) {\n\t\t\t\tif ( timers[ i ].elem === this && (type == null || timers[ i ].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[ i ]( true );\n\t\t\t\t\t} else {\n\t\t\t\t\t\ttimers[ i ].saveState();\n\t\t\t\t\t}\n\t\t\t\t\thadTimers = true;\n\t\t\t\t\ttimers.splice( i, 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) );\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\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\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.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\njQuery.each(\n\t( \"doesAddBorderForTableAndCells doesNotAddBorder \" +\n\t\t\"doesNotIncludeMarginInBodyOffset subtractsBorderForOverflowNotVisible \" +\n\t\t\"supportsFixedPosition\" ).split(\" \"), function( i, prop ) {\n\n\tjQuery.offset[ prop ] = jQuery.support[ prop ];\n});\n\njQuery.extend( jQuery.offset, {\n\n\tbodyOffset: function( body ) {\n\t\tvar top = body.offsetTop,\n\t\t\tleft = body.offsetLeft;\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\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// Expose jQuery to the global object\nwindow.jQuery = window.$ = jQuery;\n})(window);\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/modernizr/test/js/lib/jsonselect.js",
    "content": "/*! Copyright (c) 2011, Lloyd Hilaiel, ISC License */\n/*\n * This is the JSONSelect reference implementation, in javascript.\n */\n(function(exports) {\n\n    var // localize references\n    toString = Object.prototype.toString;\n\n    function jsonParse(str) {\n      try {\n          if(JSON && JSON.parse){\n              return JSON.parse(str);\n          }\n          return (new Function(\"return \" + str))();\n      } catch(e) {\n        te(\"ijs\");\n      }\n    }\n\n    // emitted error codes.\n    var errorCodes = {\n        \"ijs\": \"invalid json string\",\n        \"mpc\": \"multiple pseudo classes (:xxx) not allowed\",\n        \"mepf\": \"malformed expression in pseudo-function\",\n        \"nmi\": \"multiple ids not allowed\",\n        \"se\": \"selector expected\",\n        \"sra\": \"string required after '.'\",\n        \"uc\": \"unrecognized char\",\n        \"ujs\": \"unclosed json string\",\n        \"upc\": \"unrecognized pseudo class\"\n    };\n\n    // throw an error message\n    function te(ec) {\n        throw new Error(errorCodes[ec]);\n    }\n\n    // THE LEXER\n    var toks = {\n        psc: 1, // pseudo class\n        psf: 2, // pseudo class function\n        typ: 3, // type\n        str: 4 // string\n    };\n\n    var pat = /^(?:([\\r\\n\\t\\ ]+)|([*.,>])|(string|boolean|null|array|object|number)|(:(?:root|first-child|last-child|only-child))|(:(?:nth-child|nth-last-child))|(:\\w+)|(\\\"(?:[^\\\\]|\\\\[^\\\"])*\\\")|(\\\")|((?:[_a-zA-Z]|[^\\0-\\0177]|\\\\[^\\r\\n\\f0-9a-fA-F])(?:[_a-zA-Z0-9\\-]|[^\\u0000-\\u0177]|(?:\\\\[^\\r\\n\\f0-9a-fA-F]))*))/;\n    var exprPat = /^\\s*\\(\\s*(?:([+\\-]?)([0-9]*)n\\s*(?:([+\\-])\\s*([0-9]))?|(odd|even)|([+\\-]?[0-9]+))\\s*\\)/;\n    var lex = function (str, off) {\n        if (!off) off = 0;\n        var m = pat.exec(str.substr(off));\n        if (!m) return undefined;\n        off+=m[0].length;\n        var a;\n        if (m[1]) a = [off, \" \"];\n        else if (m[2]) a = [off, m[0]];\n        else if (m[3]) a = [off, toks.typ, m[0]];\n        else if (m[4]) a = [off, toks.psc, m[0]];\n        else if (m[5]) a = [off, toks.psf, m[0]];\n        else if (m[6]) te(\"upc\");\n        else if (m[7]) a = [off, toks.str, jsonParse(m[0])];\n        else if (m[8]) te(\"ujs\");\n        else if (m[9]) a = [off, toks.str, m[0].replace(/\\\\([^\\r\\n\\f0-9a-fA-F])/g,\"$1\")];\n        return a;\n    };\n\n    // THE PARSER\n\n    var parse = function (str) {\n        var a = [], off = 0, am;\n\n        while (true) {\n            var s = parse_selector(str, off);\n            a.push(s[1]);\n            s = lex(str, off = s[0]);\n            if (s && s[1] === \" \") s = lex(str, off = s[0]);\n            if (!s) break;\n            // now we've parsed a selector, and have something else...\n            if (s[1] === \">\") {\n                a.push(\">\");\n                off = s[0];\n            } else if (s[1] === \",\") {\n                if (am === undefined) am = [ \",\", a ];\n                else am.push(a);\n                a = [];\n                off = s[0];\n            }\n        }\n        if (am) am.push(a);\n        return am ? am : a;\n    };\n\n    var parse_selector = function(str, off) {\n        var soff = off;\n        var s = { };\n        var l = lex(str, off);\n        // skip space\n        if (l && l[1] === \" \") { soff = off = l[0]; l = lex(str, off); }\n        if (l && l[1] === toks.typ) {\n            s.type = l[2];\n            l = lex(str, (off = l[0]));\n        } else if (l && l[1] === \"*\") {\n            // don't bother representing the universal sel, '*' in the\n            // parse tree, cause it's the default\n            l = lex(str, (off = l[0]));\n        }\n\n        // now support either an id or a pc\n        while (true) {\n            if (l === undefined) {\n                break;\n            } else if (l[1] === \".\") {\n                l = lex(str, (off = l[0]));\n                if (!l || l[1] !== toks.str) te(\"sra\");\n                if (s.id) te(\"nmi\");\n                s.id = l[2];\n            } else if (l[1] === toks.psc) {\n                if (s.pc || s.pf) te(\"mpc\");\n                // collapse first-child and last-child into nth-child expressions\n                if (l[2] === \":first-child\") {\n                    s.pf = \":nth-child\";\n                    s.a = 0;\n                    s.b = 1;\n                } else if (l[2] === \":last-child\") {\n                    s.pf = \":nth-last-child\";\n                    s.a = 0;\n                    s.b = 1;\n                } else {\n                    s.pc = l[2];\n                }\n            } else if (l[1] === toks.psf) {\n                if (s.pc || s.pf ) te(\"mpc\");\n                s.pf = l[2];\n                var m = exprPat.exec(str.substr(l[0]));\n                if (!m) te(\"mepf\");\n                if (m[5]) {\n                    s.a = 2;\n                    s.b = (m[5] === \"odd\") ? 1 : 0;\n                } else if (m[6]) {\n                    s.a = 0;\n                    s.b = parseInt(m[6], 10);\n                } else {\n                    s.a = parseInt((m[1] ? m[1] : \"+\") + (m[2] ? m[2] : \"1\"),10);\n                    s.b = m[3] ? parseInt(m[3] + m[4],10) : 0;\n                }\n                l[0] += m[0].length;\n            } else {\n                break;\n            }\n            l = lex(str, (off = l[0]));\n        }\n\n        // now if we didn't actually parse anything it's an error\n        if (soff === off) te(\"se\");\n\n        return [off, s];\n    };\n\n    // THE EVALUATOR\n\n    function isArray(o) {\n        return Array.isArray ? Array.isArray(o) : \n          toString.call(o) === \"[object Array]\";\n    }\n\n    function mytypeof(o) {\n        if (o === null) return \"null\";\n        var to = typeof o;\n        if (to === \"object\" && isArray(o)) to = \"array\";\n        return to;\n    }\n\n    function mn(node, sel, id, num, tot) {\n        var sels = [];\n        var cs = (sel[0] === \">\") ? sel[1] : sel[0];\n        var m = true, mod;\n        if (cs.type) m = m && (cs.type === mytypeof(node));\n        if (cs.id)   m = m && (cs.id === id);\n        if (m && cs.pf) {\n            if (cs.pf === \":nth-last-child\") num = tot - num;\n            else num++;\n            if (cs.a === 0) {\n                m = cs.b === num;\n            } else {\n                mod = ((num - cs.b) % cs.a);\n\n                m = (!mod && ((num*cs.a + cs.b) >= 0));\n            }\n        }\n\n        // should we repeat this selector for descendants?\n        if (sel[0] !== \">\" && sel[0].pc !== \":root\") sels.push(sel);\n\n        if (m) {\n            // is there a fragment that we should pass down?\n            if (sel[0] === \">\") { if (sel.length > 2) { m = false; sels.push(sel.slice(2)); } }\n            else if (sel.length > 1) { m = false; sels.push(sel.slice(1)); }\n        }\n\n        return [m, sels];\n    }\n\n    function forEach(sel, obj, fun, id, num, tot) {\n        var a = (sel[0] === \",\") ? sel.slice(1) : [sel],\n        a0 = [],\n        call = false,\n        i = 0, j = 0, l = 0, k, x;\n        for (i = 0; i < a.length; i++) {\n            x = mn(obj, a[i], id, num, tot);\n            if (x[0]) {\n                call = true;\n            }\n            for (j = 0; j < x[1].length; j++) {\n                a0.push(x[1][j]);\n            }\n        }\n        if (a0.length && typeof obj === \"object\") {\n            if (a0.length >= 1) {\n                a0.unshift(\",\");\n            }\n            if (isArray(obj)) {\n                for (i = 0; i < obj.length; i++) {\n                    forEach(a0, obj[i], fun, undefined, i, obj.length);\n                }\n            } else {\n                // it's a shame to do this for :last-child and other\n                // properties which count from the end when we don't\n                // even know if they're present.  Also, the stream\n                // parser is going to be pissed.\n                l = 0;\n                for (k in obj) {\n                    if (obj.hasOwnProperty(k)) {\n                        l++;\n                    }\n                }\n                i = 0;\n                for (k in obj) {\n                    if (obj.hasOwnProperty(k)) {\n                        forEach(a0, obj[k], fun, k, i++, l);\n                    }\n                }\n            }\n        }\n        if (call && fun) {\n            fun(obj);\n        }\n    }\n\n    function match(sel, obj) {\n        var a = [];\n        forEach(sel, obj, function(x) {\n            a.push(x);\n        });\n        return a;\n    }\n\n    function compile(sel) {\n        return {\n            sel: parse(sel),\n            match: function(obj){\n                return match(this.sel, obj);\n            },\n            forEach: function(obj, fun) {\n                return forEach(this.sel, obj, fun);\n            }\n        };\n    }\n\n    exports._lex = lex;\n    exports._parse = parse;\n    exports.match = function (sel, obj) {\n        return compile(sel).match(obj);\n    };\n    exports.forEach = function(sel, obj, fun) {\n        return compile(sel).forEach(obj, fun);\n    };\n    exports.compile = compile;\n})(typeof exports === \"undefined\" ? (window.JSONSelect = {}) : exports);\n\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/modernizr/test/js/lib/polyfills.js",
    "content": "\n// Array.prototype.indexOf  polyfill\nif (!Array.prototype.indexOf){\n  Array.prototype.indexOf = function(searchElement /*, fromIndex */)\n  {\n    \"use strict\";\n\n    if (this === void 0 || this === null)\n      throw new TypeError();\n\n    var t = Object(this);\n    var len = t.length >>> 0;\n    if (len === 0)\n      return -1;\n\n    var n = 0;\n    if (arguments.length > 0)\n    {\n      n = Number(arguments[1]);\n      if (n !== n) // shortcut for verifying if it's NaN\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\n    if (n >= len)\n      return -1;\n\n    var k = n >= 0\n          ? n\n          : Math.max(len - Math.abs(n), 0);\n\n    for (; k < len; k++)\n    {\n      if (k in t && t[k] === searchElement)\n        return k;\n    }\n    return -1;\n  };\n}\n\n\n// Object.keys()\nif (!Object.keys) Object.keys = function(o){\n  if (o !== Object(o)) throw new TypeError('Object.keys called on non-object');\n  var ret=[], p;\n  for (p in o) if(Object.prototype.hasOwnProperty.call(o,p)) ret.push(p);\n  return ret;\n};\n\n\n\nif (!Array.prototype.map)\n{\n  Array.prototype.map = function(fun /*, thisp */)\n  {\n    \"use strict\";\n\n    if (this === void 0 || this === null)\n      throw new TypeError();\n\n    var t = Object(this);\n    var len = t.length >>> 0;\n    if (typeof fun !== \"function\")\n      throw new TypeError();\n\n    var res = new Array(len);\n    var thisp = arguments[1];\n    for (var i = 0; i < len; i++)\n    {\n      if (i in t)\n        res[i] = fun.call(thisp, t[i], i, t);\n    }\n\n    return res;\n  };\n}\n\n\n\n\n/*!\n    http://www.JSON.org/json2.js\n    2011-10-19\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 code should be minified before deployment.\n    See http://javascript.crockford.com/jsmin.html\n\n*/\nvar JSON;if(!JSON){JSON={}}(function(){function f(n){return n<10?\"0\"+n:n}if(typeof Date.prototype.toJSON!==\"function\"){Date.prototype.toJSON=function(key){return isFinite(this.valueOf())?this.getUTCFullYear()+\"-\"+f(this.getUTCMonth()+1)+\"-\"+f(this.getUTCDate())+\"T\"+f(this.getUTCHours())+\":\"+f(this.getUTCMinutes())+\":\"+f(this.getUTCSeconds())+\"Z\":null};String.prototype.toJSON=Number.prototype.toJSON=Boolean.prototype.toJSON=function(key){return this.valueOf()}}var cx=/[\\u0000\\u00ad\\u0600-\\u0604\\u070f\\u17b4\\u17b5\\u200c-\\u200f\\u2028-\\u202f\\u2060-\\u206f\\ufeff\\ufff0-\\uffff]/g,escapable=/[\\\\\\\"\\x00-\\x1f\\x7f-\\x9f\\u00ad\\u0600-\\u0604\\u070f\\u17b4\\u17b5\\u200c-\\u200f\\u2028-\\u202f\\u2060-\\u206f\\ufeff\\ufff0-\\uffff]/g,gap,indent,meta={\"\\b\":\"\\\\b\",\"\\t\":\"\\\\t\",\"\\n\":\"\\\\n\",\"\\f\":\"\\\\f\",\"\\r\":\"\\\\r\",'\"':'\\\\\"',\"\\\\\":\"\\\\\\\\\"},rep;function quote(string){escapable.lastIndex=0;return escapable.test(string)?'\"'+string.replace(escapable,function(a){var c=meta[a];return typeof c===\"string\"?c:\"\\\\u\"+(\"0000\"+a.charCodeAt(0).toString(16)).slice(-4)})+'\"':'\"'+string+'\"'}function str(key,holder){var i,k,v,length,mind=gap,partial,value=holder[key];if(value&&typeof value===\"object\"&&typeof value.toJSON===\"function\"){value=value.toJSON(key)}if(typeof rep===\"function\"){value=rep.call(holder,key,value)}switch(typeof value){case\"string\":return quote(value);case\"number\":return isFinite(value)?String(value):\"null\";case\"boolean\":case\"null\":return String(value);case\"object\":if(!value){return\"null\"}gap+=indent;partial=[];if(Object.prototype.toString.apply(value)===\"[object Array]\"){length=value.length;for(i=0;i<length;i+=1){partial[i]=str(i,value)||\"null\"}v=partial.length===0?\"[]\":gap?\"[\\n\"+gap+partial.join(\",\\n\"+gap)+\"\\n\"+mind+\"]\":\"[\"+partial.join(\",\")+\"]\";gap=mind;return v}if(rep&&typeof rep===\"object\"){length=rep.length;for(i=0;i<length;i+=1){if(typeof rep[i]===\"string\"){k=rep[i];v=str(k,value);if(v){partial.push(quote(k)+(gap?\": \":\":\")+v)}}}}else{for(k in value){if(Object.prototype.hasOwnProperty.call(value,k)){v=str(k,value);if(v){partial.push(quote(k)+(gap?\": \":\":\")+v)}}}}v=partial.length===0?\"{}\":gap?\"{\\n\"+gap+partial.join(\",\\n\"+gap)+\"\\n\"+mind+\"}\":\"{\"+partial.join(\",\")+\"}\";gap=mind;return v}}if(typeof JSON.stringify!==\"function\"){JSON.stringify=function(value,replacer,space){var i;gap=\"\";indent=\"\";if(typeof space===\"number\"){for(i=0;i<space;i+=1){indent+=\" \"}}else{if(typeof space===\"string\"){indent=space}}rep=replacer;if(replacer&&typeof replacer!==\"function\"&&(typeof replacer!==\"object\"||typeof replacer.length!==\"number\")){throw new Error(\"JSON.stringify\")}return str(\"\",{\"\":value})}}if(typeof JSON.parse!==\"function\"){JSON.parse=function(text,reviver){var j;function walk(holder,key){var k,v,value=holder[key];if(value&&typeof value===\"object\"){for(k in value){if(Object.prototype.hasOwnProperty.call(value,k)){v=walk(value,k);if(v!==undefined){value[k]=v}else{delete value[k]}}}}return reviver.call(holder,key,value)}text=String(text);cx.lastIndex=0;if(cx.test(text)){text=text.replace(cx,function(a){return\"\\\\u\"+(\"0000\"+a.charCodeAt(0).toString(16)).slice(-4)})}if(/^[\\],:{}\\s]*$/.test(text.replace(/\\\\(?:[\"\\\\\\/bfnrt]|u[0-9a-fA-F]{4})/g,\"@\").replace(/\"[^\"\\\\\\n\\r]*\"|true|false|null|-?\\d+(?:\\.\\d*)?(?:[eE][+\\-]?\\d+)?/g,\"]\").replace(/(?:^|:|,)(?:\\s*\\[)+/g,\"\"))){j=eval(\"(\"+text+\")\");return typeof reviver===\"function\"?walk({\"\":j},\"\"):j}throw new SyntaxError(\"JSON.parse\")}}}());\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/modernizr/test/js/lib/uaparser.js",
    "content": "// uaparser by lindsey simon,\n// ported to node by tobie\n// https://github.com/tobie/ua-parser/\n\n// browserized by paul irish\n\n(function(exports){\n\n  exports.uaparse = parse;\n  \n  function parse(ua) {\n    for (var i=0; i < parsers.length; i++) {\n      var result = parsers[i](ua);\n      if (result) { return result; }\n    }\n    return new UserAgent();\n  }\n\n  function UserAgent(family) {\n    this.family = family || 'Other';\n  }\n\n  UserAgent.prototype.toVersionString = function() {\n    var output = '';\n    if (this.major != null) {\n      output += this.major;\n      if (this.minor != null) {\n        output += '.' + this.minor;\n        if (this.patch != null) {\n          output += '.' + this.patch;\n        }\n      }\n    }\n    return output;\n  };\n\n  UserAgent.prototype.toString = function() {\n    var suffix = this.toVersionString();\n    if (suffix) { suffix = ' ' + suffix; }\n    return this.family + suffix;\n  };\n  \n  \n  var regexes = [\n      {\"pattern\":\"^(Opera)/(\\\\d+)\\\\.(\\\\d+) \\\\(Nintendo Wii\",\n       \"v1_replacement\":null,\n       \"family_replacement\":\"Wii\"},\n      {\"pattern\":\"(Namoroka|Shiretoko|Minefield)/(\\\\d+)\\\\.(\\\\d+)\\\\.(\\\\d+(?:pre)?)\",\n       \"v1_replacement\":null,\n       \"family_replacement\":\"Firefox ($1)\"},\n      {\"pattern\":\"(Namoroka|Shiretoko|Minefield)/(\\\\d+)\\\\.(\\\\d+)([ab]\\\\d+[a-z]*)?\",\n       \"v1_replacement\":null,\n       \"family_replacement\":\"Firefox ($1)\"},\n      {\"pattern\":\"(SeaMonkey|Fennec|Camino)/(\\\\d+)\\\\.(\\\\d+)([ab]?\\\\d+[a-z]*)\",\n       \"v1_replacement\":null,\n       \"family_replacement\":null},\n      {\"pattern\":\"(Flock)/(\\\\d+)\\\\.(\\\\d+)(b\\\\d+?)\",\n       \"v1_replacement\":null,\n       \"family_replacement\":null},\n      {\"pattern\":\"(Fennec)/(\\\\d+)\\\\.(\\\\d+)(pre)\",\n       \"v1_replacement\":null,\n       \"family_replacement\":null},\n      {\"pattern\":\"(Navigator)/(\\\\d+)\\\\.(\\\\d+)\\\\.(\\\\d+)\",\n       \"v1_replacement\":null,\n       \"family_replacement\":\"Netscape\"},\n      {\"pattern\":\"(Navigator)/(\\\\d+)\\\\.(\\\\d+)([ab]\\\\d+)\",\n       \"v1_replacement\":null,\n       \"family_replacement\":\"Netscape\"},\n      {\"pattern\":\"(Netscape6)/(\\\\d+)\\\\.(\\\\d+)\\\\.(\\\\d+)\",\n       \"v1_replacement\":null,\n       \"family_replacement\":\"Netscape\"},\n      {\"pattern\":\"(MyIBrow)/(\\\\d+)\\\\.(\\\\d+)\",\n       \"v1_replacement\":null,\n       \"family_replacement\":\"My Internet Browser\"},\n      {\"pattern\":\"(Firefox).*Tablet browser (\\\\d+)\\\\.(\\\\d+)\\\\.(\\\\d+)\",\n       \"v1_replacement\":null,\n       \"family_replacement\":\"MicroB\"},\n      {\"pattern\":\"(Opera)/9.80.*Version\\\\/(\\\\d+)\\\\.(\\\\d+)(?:\\\\.(\\\\d+))?\",\n       \"v1_replacement\":null,\n       \"family_replacement\":null},\n      {\"pattern\":\"(Firefox)/(\\\\d+)\\\\.(\\\\d+)\\\\.(\\\\d+(?:pre)?) \\\\(Swiftfox\\\\)\",\n       \"v1_replacement\":null,\n       \"family_replacement\":\"Swiftfox\"},\n      {\"pattern\":\"(Firefox)/(\\\\d+)\\\\.(\\\\d+)([ab]\\\\d+[a-z]*)? \\\\(Swiftfox\\\\)\",\n       \"v1_replacement\":null,\n       \"family_replacement\":\"Swiftfox\"},\n      {\"pattern\":\"(konqueror)/(\\\\d+)\\\\.(\\\\d+)\\\\.(\\\\d+)\",\n       \"v1_replacement\":null,\n       \"family_replacement\":\"Konqueror\"},\n      {\"pattern\":\"(Jasmine|ANTGalio|Midori|Fresco|Lobo|Maxthon|Lynx|OmniWeb|Dillo|Camino|Demeter|Fluid|Fennec|Shiira|Sunrise|Chrome|Flock|Netscape|Lunascape|Epiphany|WebPilot|Vodafone|NetFront|Konqueror|SeaMonkey|Kazehakase|Vienna|Iceape|Iceweasel|IceWeasel|Iron|K-Meleon|Sleipnir|Galeon|GranParadiso|Opera Mini|iCab|NetNewsWire|Iron|Iris)/(\\\\d+)\\\\.(\\\\d+)\\\\.(\\\\d+)\",\n       \"v1_replacement\":null,\n       \"family_replacement\":null},\n      {\"pattern\":\"(Bolt|Jasmine|Maxthon|Lynx|Arora|IBrowse|Dillo|Camino|Shiira|Fennec|Phoenix|Chrome|Flock|Netscape|Lunascape|Epiphany|WebPilot|Opera Mini|Opera|Vodafone|NetFront|Konqueror|SeaMonkey|Kazehakase|Vienna|Iceape|Iceweasel|IceWeasel|Iron|K-Meleon|Sleipnir|Galeon|GranParadiso|iCab|NetNewsWire|Iron|Space Bison|Stainless|Orca)/(\\\\d+)\\\\.(\\\\d+)\",\n       \"v1_replacement\":null,\n       \"family_replacement\":null},\n      {\"pattern\":\"(iRider|Crazy Browser|SkipStone|iCab|Lunascape|Sleipnir|Maemo Browser) (\\\\d+)\\\\.(\\\\d+)\\\\.(\\\\d+)\",\n       \"v1_replacement\":null,\n       \"family_replacement\":null},\n      {\"pattern\":\"(iCab|Lunascape|Opera|Android) (\\\\d+)\\\\.(\\\\d+)\",\n       \"v1_replacement\":null,\n       \"family_replacement\":null},\n      {\"pattern\":\"(IEMobile) (\\\\d+)\\\\.(\\\\d+)\",\n       \"v1_replacement\":null,\n       \"family_replacement\":\"IE Mobile\"},\n      {\"pattern\":\"(Firefox)/(\\\\d+)\\\\.(\\\\d+)\\\\.(\\\\d+)\",\n       \"v1_replacement\":null,\n       \"family_replacement\":null},\n      {\"pattern\":\"(Firefox)/(\\\\d+)\\\\.(\\\\d+)(pre|[ab]\\\\d+[a-z]*)?\",\n       \"v1_replacement\":null,\n       \"family_replacement\":null},\n      {\"pattern\":\"(Obigo|OBIGO)[^\\\\d]*(\\\\d+)(?:.(\\\\d+))?\",\n       \"v1_replacement\":null,\n       \"family_replacement\":\"Obigo\"},\n      {\"pattern\":\"(MAXTHON|Maxthon) (\\\\d+)\\\\.(\\\\d+)\",\n       \"v1_replacement\":null,\n       \"family_replacement\":\"Maxthon\"},\n      {\"pattern\":\"(Maxthon|MyIE2|Uzbl|Shiira)\",\n       \"v1_replacement\":\"0\",\n       \"family_replacement\":null},\n      {\"pattern\":\"(PLAYSTATION) (\\\\d+)\",\n       \"v1_replacement\":null,\n       \"family_replacement\":\"PlayStation\"},\n      {\"pattern\":\"(PlayStation Portable)[^\\\\d]+(\\\\d+).(\\\\d+)\",\n       \"v1_replacement\":null,\n       \"family_replacement\":null},\n      {\"pattern\":\"(BrowseX) \\\\((\\\\d+)\\\\.(\\\\d+)\\\\.(\\\\d+)\",\n       \"v1_replacement\":null,\n       \"family_replacement\":null},\n      {\"pattern\":\"(Opera)/(\\\\d+)\\\\.(\\\\d+).*Opera Mobi\",\n       \"v1_replacement\":null,\n       \"family_replacement\":\"Opera Mobile\"},\n      {\"pattern\":\"(POLARIS)/(\\\\d+)\\\\.(\\\\d+)\",\n       \"v1_replacement\":null,\n       \"family_replacement\":\"Polaris\"},\n      {\"pattern\":\"(BonEcho)/(\\\\d+)\\\\.(\\\\d+)\\\\.(\\\\d+)\",\n       \"v1_replacement\":null,\n       \"family_replacement\":\"Bon Echo\"},\n      {\"pattern\":\"(iPhone) OS (\\\\d+)_(\\\\d+)(?:_(\\\\d+))?\",\n       \"v1_replacement\":null,\n       \"family_replacement\":null},\n      {\"pattern\":\"(Avant)\",\n       \"v1_replacement\":\"1\",\n       \"family_replacement\":null},\n      {\"pattern\":\"(Nokia)[EN]?(\\\\d+)\",\n       \"v1_replacement\":null,\n       \"family_replacement\":null},\n      {\"pattern\":\"(Black[bB]erry)(\\\\d+)\",\n       \"v1_replacement\":null,\n       \"family_replacement\":\"Blackberry\"},\n      {\"pattern\":\"(OmniWeb)/v(\\\\d+)\\\\.(\\\\d+)\",\n       \"v1_replacement\":null,\n       \"family_replacement\":null},\n      {\"pattern\":\"(Blazer)/(\\\\d+)\\\\.(\\\\d+)\",\n       \"v1_replacement\":null,\n       \"family_replacement\":\"Palm Blazer\"},\n      {\"pattern\":\"(Pre)/(\\\\d+)\\\\.(\\\\d+)\",\n       \"v1_replacement\":null,\n       \"family_replacement\":\"Palm Pre\"},\n      {\"pattern\":\"(Links) \\\\((\\\\d+)\\\\.(\\\\d+)\",\n       \"v1_replacement\":null,\n       \"family_replacement\":null},\n      {\"pattern\":\"(QtWeb) Internet Browser/(\\\\d+)\\\\.(\\\\d+)\",\n       \"v1_replacement\":null,\n       \"family_replacement\":null},\n      {\"pattern\":\"(Version)/(\\\\d+)\\\\.(\\\\d+)(?:\\\\.(\\\\d+))?.*Safari/\",\n       \"v1_replacement\":null,\n       \"family_replacement\":\"Safari\"},\n      {\"pattern\":\"(OLPC)/Update(\\\\d+)\\\\.(\\\\d+)\",\n       \"v1_replacement\":null,\n       \"family_replacement\":null},\n      {\"pattern\":\"(OLPC)/Update()\\\\.(\\\\d+)\",\n       \"v1_replacement\":\"0\",\n       \"family_replacement\":null},\n      {\"pattern\":\"(SamsungSGHi560)\",\n       \"v1_replacement\":null,\n       \"family_replacement\":\"Samsung SGHi560\"},\n      {\"pattern\":\"^(SonyEricssonK800i)\",\n       \"v1_replacement\":null,\n       \"family_replacement\":\"Sony Ericsson K800i\"},\n      {\"pattern\":\"(Teleca Q7)\",\n       \"v1_replacement\":null,\n       \"family_replacement\":null},\n      {\"pattern\":\"(MSIE) (\\\\d+)\\\\.(\\\\d+)\",\n       \"v1_replacement\":null,\n       \"family_replacement\":\"IE\"}\n\n  ];\n  \n  var parsers = regexes.map(function(obj) {\n    var regexp = new RegExp(obj.pattern),\n        famRep = obj.family_replacement,\n        v1Rep = obj.v1_replacement;\n\n    function parser(ua) {\n      var m = ua.match(regexp);\n\n      if (!m) { return null; }\n\n      var familly = famRep ? famRep.replace('$1', m[1]) : m[1];\n\n      var obj = new UserAgent(familly);\n      obj.major = parseInt(v1Rep ? v1Rep : m[2]);\n      obj.minor = m[3] ? parseInt(m[3]) : null;\n      obj.patch = m[4] ? parseInt(m[4]) : null;\n\n      return obj;\n    }\n\n    return parser;\n  });\n  \n  \n})(window);\n\n\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/modernizr/test/js/setup.js",
    "content": "\n// Avoid `console` errors in browsers that lack a console\nif (!(window.console && console.log)) {\n    (function() {\n        var noop = function() {};\n        var methods = ['assert', 'clear', 'count', 'debug', 'dir', 'dirxml', 'error', 'exception', 'group', 'groupCollapsed', 'groupEnd', 'info', 'log', 'markTimeline', 'profile', 'profileEnd', 'markTimeline', 'table', 'time', 'timeEnd', 'timeStamp', 'trace', 'warn'];\n        var length = methods.length;\n        var console = window.console = {};\n        while (length--) {\n            console[methods[length]] = noop;\n        }\n    }());\n}\n\n// test helper object\nwindow.TEST = {\n  // note some unique members of the Modernizr object\n  inputs    : ['input','inputtypes', 'textarea'],\n  audvid    : ['video','audio'],\n  API       : ['addTest', 'mq', 'hasEvent', 'testProp', 'testAllProps', 'testStyles', '_prefixes', '_domPrefixes', '_cssomPrefixes', 'prefixed'],\n  extraclass: ['js'],\n  privates  : ['_enableHTML5','_version','_fontfaceready'],\n  deprecated : [\n                { oldish : 'crosswindowmessaging', newish : 'postmessage'},\n                { oldish : 'historymanagement', newish : 'history'},\n              ],\n\n  // utility methods\n  inArray: function(elem, array) {\n      if (array.indexOf) {\n          return array.indexOf(elem);\n      }\n      for (var i = 0, length = array.length; i < length; i++) {\n          if (array[i] === elem) {\n              return i;\n          }\n      }\n      return -1;\n  },\n  trim : function(str){\n    return str.replace(/^\\s*/, \"\").replace(/\\s*$/, \"\");\n  }\n};\n\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/modernizr/test/js/unit-caniuse.js",
    "content": "\n\nvar myscript = document.createElement('script'),\n    ref = document.getElementsByTagName('script')[0];\n\nmyscript.src = 'http://caniuse.com/jsonp.php?callback=caniusecb';\n\nsetTimeout(function(){\n  ref.parentNode.insertBefore(myscript, ref);\n}, 100);\n\n// mapping Modernizr terms over to caniuse terms\nvar map = {\n  audio : 'audio',\n  borderimage : 'border-image',\n  borderradius : 'border-radius',\n  canvas : 'canvas',\n  canvastext : 'canvas-text',\n  cssanimations : 'css-animation',\n  boxshadow : 'css-boxshadow',\n  cssgradients : 'css-gradients',\n  opacity : 'css-opacity',\n  cssreflections : 'css-reflections',\n  textshadow : 'css-textshadow',\n  csstransitions : 'css-transitions',\n  hsla : 'css3-colors',\n  rgba : 'css3-colors',\n  draganddrop : 'dragndrop',\n  flexbox : 'flexbox',\n  fontface : 'fontface',\n  geolocation : 'geolocation',\n  hashchange : 'hashchange',\n  history : 'history',\n  indexeddb : 'indexeddb',\n  multiplebgs : 'multibackgrounds',\n  csscolumns : 'multicolumn',\n  localstorage : 'namevalue-storage',\n  applicationcache : 'offline-apps',\n  websqldatabase : 'sql-storage',\n  svg : 'svg',\n  touch : 'touch',\n  csstransforms : 'transforms2d',\n  csstransforms3d : 'transforms3d',\n  video: 'video',\n  webgl: 'webgl',\n  websockets : 'websockets',\n  webworkers : 'webworkers',\n  postmessage : 'x-doc-messaging'\n};\n\nwindow.caniusecb = function(scriptdata) {\n\n  window.doo = scriptdata;\n\n  // quit if JSONSelect didn't make it.\n  if (!window.JSONSelect) return;\n\n  var testdata     = scriptdata.data,\n\n      // parse the current UA with uaparser\n      ua           = uaparse(navigator.userAgent),\n\n      // match the UA from uaparser into the browser used by caniuse\n      browserKey   = JSONSelect.match('.agents .browser', scriptdata).indexOf(ua.family),\n      currBrowser  = Object.keys(scriptdata.agents)[browserKey];\n\n  // So Phantom doesn't kill the caniuse.com matching exit out as it's useless anyway within PhantomJS\n  if(navigator.userAgent.indexOf(\"PhantomJS\") != -1) {\n    return;\n  }\n\n  // translate 'y' 'n' or 'a' into a boolean that Modernizr uses\n  function bool(ciuresult){\n    if (ciuresult == 'y' || ciuresult == 'a') return true;\n    // 'p' is for polyfill\n    if (ciuresult == 'n' || ciuresult == 'p') return false;\n    throw 'unknown return value from can i use';\n  }\n\n  function testify(o){\n\n    var ciubool = bool(o.ciuresult);\n\n    // caniuse says audio/video are yes/no, Modernizr has more detail which we'll dumb down.\n    if (~TEST.audvid.indexOf(o.feature))\n      o.result = !!o.result;\n\n    // if caniuse gave us a 'partial', lets let it pass with a note.\n    if (o.ciuresult == 'a'){\n      return ok(true,\n        o.browser + o.version + ': Caniuse reported partial support for ' + o.ciufeature +\n        '. So.. Modernizr\\'s ' + o.result + ' is good enough...'\n      );\n    }\n\n\n    // change the *documented* false positives\n    if ((o.feature == 'textshadow' && o.browser == 'firefox' && o.version == 3)\n        && ciubool == false\n    ) {\n      ciubool = o.fp = true;\n    }\n\n    // where we actually do most our assertions\n    equal(o.result, ciubool,\n      o.browser + o.version + ': Caniuse result for ' + o.ciufeature +\n      ' matches Modernizr\\'s ' + (o.fp ? '*false positive*' : 'result') + ' for ' + o.feature\n    );\n  }\n\n\n  module('caniuse.com data matches', {\n      setup:function() {\n      },\n      teardown:function() {\n      }\n  });\n\n\n  test(\"we match caniuse data\", function() {\n\n    for (var feature in Modernizr){\n\n      var ciufeatname = map[feature];\n\n      if (ciufeatname === undefined) continue;\n\n      var ciufeatdata = testdata[ciufeatname];\n\n      if (ciufeatdata === undefined) throw 'unknown key of caniusedata';\n\n      // get results for this feature for all versions of this browser\n      var browserResults = ciufeatdata.stats[currBrowser];\n\n      // let's get our versions in order..\n      var minorver   = ua.minor &&                                  // caniuse doesn't use two digit minors\n                       ua.minor.toString().replace(/(\\d)\\d$/,'$1'), // but opera does.\n\n          majorminor = (ua.major + '.' + minorver)\n                          // opera gets grouped in some cases by caniuse\n                          .replace(/(9\\.(6|5))/ , ua.family == 'opera' ? '9.5-9.6'   : \"$1\")\n                          .replace(/(10\\.(0|1))/, ua.family == 'opera' ? '10.0-10.1' : \"$1\"),\n\n          mmResult   = browserResults[majorminor],\n          mResult    = browserResults[ua.major];\n\n\n      // check it against the major.minor: eg. FF 3.6\n      if (mmResult && mmResult != 'u'){ // 'y' 'n' or 'a'\n\n        // data ends w/ ` x` if its still prefixed in the imp\n        mmResult = mmResult.replace(' x','');\n\n        // match it against our data.\n        testify({ feature     : feature\n                , ciufeature  : ciufeatname\n                , result      : Modernizr[feature]\n                , ciuresult   : mmResult\n                , browser     : currBrowser\n                , version     : majorminor\n        });\n\n        continue; // don't check the major version\n      }\n\n      // check it against just the major version: eg. FF 3\n      if (mResult){\n\n        // unknown support from caniuse... He would probably like to know our data, though!\n        if (mResult == 'u') continue;\n\n        // data ends w/ ` x` if its still prefixed in the imp\n        mResult = mResult.replace(' x','');\n\n        testify({ feature     : feature\n                , ciufeature  : ciufeatname\n                , result      : Modernizr[feature]\n                , ciuresult   : mResult\n                , browser     : currBrowser\n                , version     : ua.major\n        });\n\n\n      }\n\n    } // for in loop\n\n  }); // eo test()\n\n\n}; // eo caniusecallback()\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/modernizr/test/js/unit.js",
    "content": "QUnit.begin = function() {\n\tconsole.log(\"Starting test suite\");\n\tconsole.log(\"================================================\\n\");\n};\n\nQUnit.moduleDone = function(opts) {\n\tif(opts.failed === 0) {\n\t\tconsole.log(\"\\u2714 All tests passed in '\"+opts.name+\"' module\");\n\t} else {\n\t\tconsole.log(\"\\u2716 \"+ opts.failed +\" tests failed in '\"+opts.name+\"' module\");\n\t}\n};\n\nQUnit.done = function(opts) {\n\tconsole.log(\"\\n================================================\");\n\tconsole.log(\"Tests completed in \"+opts.runtime+\" milliseconds\");\n\tconsole.log(opts.passed + \" tests of \"+opts.total+\" passed, \"+opts.failed+\" failed.\");\n};\n\nmodule('Basics', {\n    setup:function() {\n    },\n    teardown:function() {\n    }\n});\n\ntest(\"globals set up\", function() {\n\n\tok(window.Modernizr, 'global modernizr object created');\n\n});\n\ntest(\"bind is implemented\", function() {\n\n  ok(Function.prototype.bind, 'bind is a member of Function.prototype');\n\n  var a = function(){\n      return this.modernizr;\n  };\n  a = a.bind({modernizr: 'just awsome'});\n\n  equal(\"just awsome\", a(), 'bind works as expected');\n\n\n  // thank you webkit layoutTests\n\n\n  var result;\n\n  function F(x, y)\n  {\n      result = this + \" -> x:\" + x + \", y:\" + y;\n  }\n\n  G = F.bind(\"'a'\", \"'b'\");\n  H = G.bind(\"'Cannot rebind this!'\", \"'c'\");\n\n  G(1,2);\n  equal(result, \"\\'a\\' -> x:\\'b\\', y:1\");\n  H(1,2);\n  equal(result, \"\\'a\\' -> x:\\'b\\', y:\\'c\\'\");\n\n  var f = new F(1,2);\n  equal(result, \"[object Object] -> x:1, y:2\");\n  var g = new G(1,2);\n  equal(result, \"[object Object] -> x:\\'b\\', y:1\");\n  var h = new H(1,2);\n  equal(result, \"[object Object] -> x:\\'b\\', y:\\'c\\'\");\n\n  ok(f instanceof F, \"f instanceof F\");\n  ok(g instanceof F, \"g instanceof F\");\n  ok(h instanceof F, \"h instanceof F\");\n\n  // Bound functions don't have a 'prototype' property.\n  ok(\"prototype\" in F, '\"prototype\" in F');\n\n  // The object passed to bind as 'this' must be callable.\n  raises(function(){\n    Function.bind.call(undefined);\n  });\n\n  // Objects that allow call but not construct can be bound, but should throw if used with new.\n  var abcAt = String.prototype.charAt.bind(\"abc\");\n  equal(abcAt(1), \"b\", 'Objects that allow call but not construct can be bound...');\n\n  equal(1, Function.bind.length, 'it exists');\n\n\n});\n\n\n\ntest(\"document.documentElement is valid and correct\",1, function() {\n\tequal(document.documentElement,document.getElementsByTagName('html')[0]);\n});\n\n\ntest(\"no-js class is gone.\", function() {\n\n\tok(!/(?:^|\\s)no-js(?:^|\\s)/.test(document.documentElement.className),\n\t   'no-js class is gone');\n\n\tok(/(?:^|\\s)js(?:^|\\s)/.test(document.documentElement.className),\n\t   'html.js class is present');\n\n\tok(/(?:^|\\s)\\+no-js(?:\\s|$)/.test(document.documentElement.className),\n\t   'html.+no-js class is still present');\n\n\tok(/(?:^|\\s)no-js-(?:\\s|$)/.test(document.documentElement.className),\n\t   'html.no-js- class is still present');\n\n\tok(/(?:^|\\s)i-has-no-js(?:\\s|$)/.test(document.documentElement.className),\n\t   'html.i-has-no-js class is still present');\n\n\tif (document.querySelector){\n\t  ok(document.querySelector('html.js') == document.documentElement,\n\t     \"document.querySelector('html.js') matches.\");\n\t}\n});\n\ntest('html shim worked', function(){\n  expect(2);\n\n  // the exact test we use in the script\n  var elem = document.getElementsByTagName(\"section\")[0];\n  elem.id = \"html5section\";\n\n  ok( elem.childNodes.length === 1 , 'unknown elements dont collapse');\n\n  elem.style.color = 'red';\n  ok( /red|#ff0000/i.test(elem.style.color), 'unknown elements are styleable')\n\n});\n\n\nmodule('Modernizr classes and bools', {\n    setup:function() {\n    },\n    teardown:function() {\n    }\n});\n\n\ntest('html classes are looking good',function(){\n\n  var classes = TEST.trim(document.documentElement.className).split(/\\s+/);\n\n  var modprops = Object.keys(Modernizr),\n      newprops = modprops;\n\n  // decrement for the properties that are private\n  for (var i = -1, len = TEST.privates.length; ++i < len; ){\n    var item = TEST.privates[i];\n    equal(-1, TEST.inArray(item, classes), 'private Modernizr object '+ item +'should not have matching classes');\n    equal(-1, TEST.inArray('no-' + item, classes), 'private Modernizr object no-'+item+' should not have matching classes');\n  }\n\n  // decrement for the non-boolean objects\n//  for (var i = -1, len = TEST.inputs.length; ++i < len; ){\n//    if (Modernizr[TEST.inputs[i]] != undefined) newprops--;\n//  }\n\n  // TODO decrement for the extraclasses\n\n  // decrement for deprecated ones.\n  $.each( TEST.deprecated, function(key, val){\n    newprops.splice(  TEST.inArray(item, newprops), 1);\n  });\n\n\n  //equal(classes,newprops,'equal number of classes and global object props');\n\n  if (classes.length !== newprops){\n    //window.console && console.log(classes, newprops);\n\n  }\n\n  for (var i = 0, len = classes.length, aclass; i <len; i++){\n    aclass = classes[i];\n\n    // Skip js related classes.\n    if (/^(?:js|\\+no-js|no-js-|i-has-no-js)$/.test(aclass)) continue;\n\n    if (aclass.indexOf('no-') === 0){\n      aclass = aclass.replace('no-','');\n\n      equal(Modernizr[aclass], false,\n            aclass + ' is correctly false in the classes and object')\n\n    } else {\n      equal(Modernizr[aclass], true,\n             aclass + ' is correctly true in the classes and object')\n    }\n  }\n\n\n  for (var i = 0, len = classes.length, aclass; i <len; i++){\n    equal(classes[i],classes[i].toLowerCase(),'all classes are lowerCase.');\n  }\n\n  // Remove fake no-js classes before test.\n  var docElClass = document.documentElement.className;\n  $.each(['\\\\+no-js', 'no-js-', 'i-has-no-js'], function(i, fakeClass) {\n    docElClass = docElClass.replace(new RegExp('(^|\\\\s)' + fakeClass + '(\\\\s|$)', 'g'), '$1$2');\n  });\n  equal(/[^\\s]no-/.test(docElClass), false, 'whitespace between all classes.');\n\n\n})\n\n\ntest('Modernizr properties are looking good',function(){\n\n  var count  = 0,\n      nobool = TEST.API.concat(TEST.inputs)\n                       .concat(TEST.audvid)\n                       .concat(TEST.privates)\n                       .concat(['textarea']); // due to forms-placeholder.js test\n\n  for (var prop in window.Modernizr){\n    if (Modernizr.hasOwnProperty(prop)){\n\n      if (TEST.inArray(prop,nobool) >= 0) continue;\n\n      ok(Modernizr[prop] === true || Modernizr[prop] === false,\n        'Modernizr.'+prop+' is a straight up boolean');\n\n\n      equal(prop,prop.toLowerCase(),'all properties are lowerCase.')\n    }\n  }\n})\n\n\n\ntest('Modernizr.audio and Modernizr.video',function(){\n\n  for (var i = -1, len = TEST.audvid.length; ++i < len;){\n    var prop = TEST.audvid[i];\n\n    if (Modernizr[prop].toString() == 'true'){\n\n      ok(Modernizr[prop],                             'Modernizr.'+prop+' is truthy.');\n      equal(Modernizr[prop] == true,true,            'Modernizr.'+prop+' is == true')\n      equal(typeof Modernizr[prop] === 'object',true,'Moderizr.'+prop+' is truly an object');\n      equal(Modernizr[prop] !== true,true,           'Modernizr.'+prop+' is !== true')\n\n    } else {\n\n      equal(Modernizr[prop] != true,true,            'Modernizr.'+prop+' is != true')\n    }\n  }\n\n\n});\n\n\ntest('Modernizr results match expected values',function(){\n\n  // i'm bringing over a few tests from inside Modernizr.js\n  equal(!!document.createElement('canvas').getContext,Modernizr.canvas,'canvas test consistent');\n\n  equal(!!window.Worker,Modernizr.webworkers,'web workers test consistent')\n\n});\n\n\n\nmodule('Modernizr\\'s API methods', {\n    setup:function() {\n    },\n    teardown:function() {\n    }\n});\n\ntest('Modernizr.addTest()',22,function(){\n\n  var docEl = document.documentElement;\n\n\n  Modernizr.addTest('testtrue',function(){\n    return true;\n  });\n\n  Modernizr.addTest('testtruthy',function(){\n    return 100;\n  });\n\n  Modernizr.addTest('testfalse',function(){\n    return false;\n  });\n\n  Modernizr.addTest('testfalsy',function(){\n    return undefined;\n  });\n\n  ok(docEl.className.indexOf(' testtrue') >= 0,'positive class added');\n  equal(Modernizr.testtrue,true,'positive prop added');\n\n  ok(docEl.className.indexOf(' testtruthy') >= 0,'positive class added');\n  equal(Modernizr.testtruthy,100,'truthy value is not casted to straight boolean');\n\n  ok(docEl.className.indexOf(' no-testfalse') >= 0,'negative class added');\n  equal(Modernizr.testfalse,false,'negative prop added');\n\n  ok(docEl.className.indexOf(' no-testfalsy') >= 0,'negative class added');\n  equal(Modernizr.testfalsy,undefined,'falsy value is not casted to straight boolean');\n\n\n\n  Modernizr.addTest('testcamelCase',function(){\n     return true;\n   });\n\n  ok(docEl.className.indexOf(' testcamelCase') === -1,\n     'camelCase test name toLowerCase()\\'d');\n\n\n  // okay new signature for this API! woo\n\n  Modernizr.addTest('testboolfalse', false);\n\n  ok(~docEl.className.indexOf(' no-testboolfalse'), 'Modernizr.addTest(feature, bool): negative class added');\n  equal(Modernizr.testboolfalse, false, 'Modernizr.addTest(feature, bool): negative prop added');\n\n\n\n  Modernizr.addTest('testbooltrue', true);\n\n  ok(~docEl.className.indexOf(' testbooltrue'), 'Modernizr.addTest(feature, bool): positive class added');\n  equal(Modernizr.testbooltrue, true, 'Modernizr.addTest(feature, bool): positive prop added');\n\n\n\n  Modernizr.addTest({'testobjboolfalse': false,\n                     'testobjbooltrue' : true   });\n\n  ok(~docEl.className.indexOf(' no-testobjboolfalse'), 'Modernizr.addTest({feature: bool}): negative class added');\n  equal(Modernizr.testobjboolfalse, false, 'Modernizr.addTest({feature: bool}): negative prop added');\n\n  ok(~docEl.className.indexOf(' testobjbooltrue'), 'Modernizr.addTest({feature: bool}): positive class added');\n  equal(Modernizr.testobjbooltrue, true, 'Modernizr.addTest({feature: bool}): positive prop added');\n\n\n\n\n  Modernizr.addTest({'testobjfnfalse': function(){ return false },\n                     'testobjfntrue' : function(){ return true }   });\n\n\n  ok(~docEl.className.indexOf(' no-testobjfnfalse'), 'Modernizr.addTest({feature: bool}): negative class added');\n  equal(Modernizr.testobjfnfalse, false, 'Modernizr.addTest({feature: bool}): negative prop added');\n\n  ok(~docEl.className.indexOf(' testobjfntrue'), 'Modernizr.addTest({feature: bool}): positive class added');\n  equal(Modernizr.testobjfntrue, true, 'Modernizr.addTest({feature: bool}): positive prop added');\n\n\n  Modernizr\n    .addTest('testchainone', true)\n    .addTest({ testchaintwo: true })\n    .addTest('testchainthree', function(){ return true; });\n\n  ok( Modernizr.testchainone == Modernizr.testchaintwo == Modernizr.testchainthree, 'addTest is chainable');\n\n\n}); // eo addTest\n\n\n\n\n\ntest('Modernizr.mq: media query testing',function(){\n\n  var $html = $('html');\n  $.mobile = {};\n\n  // from jquery mobile\n\n  $.mobile.media = (function() {\n  \t// TODO: use window.matchMedia once at least one UA implements it\n  \tvar cache = {},\n  \t\ttestDiv = $( \"<div id='jquery-mediatest'>\" ),\n  \t\tfakeBody = $( \"<body>\" ).append( testDiv );\n\n  \treturn function( query ) {\n  \t\tif ( !( query in cache ) ) {\n  \t\t\tvar styleBlock = document.createElement('style'),\n          \t\tcssrule = \"@media \" + query + \" { #jquery-mediatest { position:absolute; } }\";\n  \t        //must set type for IE!\n  \t        styleBlock.type = \"text/css\";\n  \t        if (styleBlock.styleSheet){\n  \t          styleBlock.styleSheet.cssText = cssrule;\n  \t        }\n  \t        else {\n  \t          styleBlock.appendChild(document.createTextNode(cssrule));\n  \t        }\n\n  \t\t\t$html.prepend( fakeBody ).prepend( styleBlock );\n  \t\t\tcache[ query ] = testDiv.css( \"position\" ) === \"absolute\";\n  \t\t\tfakeBody.add( styleBlock ).remove();\n  \t\t}\n  \t\treturn cache[ query ];\n  \t};\n  })();\n\n\n  ok(Modernizr.mq,'Modernizr.mq() doesn\\' freak out.');\n\n  equal($.mobile.media('only screen'), Modernizr.mq('only screen'),'screen media query matches jQuery mobile\\'s result');\n\n  equal(Modernizr.mq('only all'), Modernizr.mq('only all'), 'Cache hit matches');\n\n\n});\n\n\n\n\ntest('Modernizr.hasEvent()',function(){\n\n  ok(typeof Modernizr.hasEvent == 'function','Modernizr.hasEvent() is a function');\n\n\n  equal(Modernizr.hasEvent('click'), true,'click event is supported');\n\n  equal(Modernizr.hasEvent('modernizrcustomevent'), false,'random event is definitely not supported');\n\n  /* works fine in webkit but not gecko\n  equal(  Modernizr.hasEvent('resize', window),\n          !Modernizr.hasEvent('resize', document.createElement('div')),\n          'Resize is supported in window but not a div, typically...');\n  */\n\n});\n\n\n\n\n\ntest('Modernizr.testStyles()',function(){\n\n  equal(typeof Modernizr.testStyles, 'function','Modernizr.testStyles() is a function');\n\n  var style = '#modernizr{ width: 9px; height: 4px; font-size: 0; color: papayawhip; }';\n\n  Modernizr.testStyles(style, function(elem, rule){\n      equal(style, rule, 'rule passsed back matches what i gave it.')\n      equal(elem.offsetWidth, 9, 'width was set through the style');\n      equal(elem.offsetHeight, 4, 'height was set through the style');\n      equal(elem.id, 'modernizr', 'element is indeed the modernizr element');\n  });\n\n});\n\n\ntest('Modernizr._[properties]',function(){\n\n  equal(6, Modernizr._prefixes.length, 'Modernizr._prefixes has 6 items');\n\n  equal(4, Modernizr._domPrefixes.length, 'Modernizr.domPrefixes has 4 items');\n\n});\n\ntest('Modernizr.testProp()',function(){\n\n  equal(true, Modernizr.testProp('margin'), 'Everyone supports margin');\n\n  equal(false, Modernizr.testProp('happiness'), 'Nobody supports the happiness style. :(');\n  equal(true, Modernizr.testProp('fontSize'), 'Everyone supports fontSize');\n  equal(false, Modernizr.testProp('font-size'), 'Nobody supports font-size');\n\n  equal('pointerEvents' in  document.createElement('div').style,\n         Modernizr.testProp('pointerEvents'),\n         'results for `pointer-events` are consistent with a homegrown feature test');\n\n});\n\n\n\ntest('Modernizr.testAllProps()',function(){\n\n  equal(true, Modernizr.testAllProps('margin'), 'Everyone supports margin');\n\n  equal(false, Modernizr.testAllProps('happiness'), 'Nobody supports the happiness style. :(');\n  equal(true, Modernizr.testAllProps('fontSize'), 'Everyone supports fontSize');\n  equal(false, Modernizr.testAllProps('font-size'), 'Nobody supports font-size');\n\n  equal(Modernizr.csstransitions, Modernizr.testAllProps('transition'), 'Modernizr result matches API result: csstransitions');\n\n  equal(Modernizr.csscolumns, Modernizr.testAllProps('columnCount'), 'Modernizr result matches API result: csscolumns')\n\n});\n\n\n\n\n\n\ntest('Modernizr.prefixed() - css and DOM resolving', function(){\n  // https://gist.github.com/523692\n\n  function gimmePrefix(prop, obj){\n    var prefixes = ['Moz','Khtml','Webkit','O','ms'],\n        domPrefixes = ['moz','khtml','webkit','o','ms'],\n        elem     = document.createElement('div'),\n        upper    = prop.charAt(0).toUpperCase() + prop.slice(1);\n\n    if(!obj) {\n      if (prop in elem.style)\n        return prop;\n\n      for (var len = prefixes.length; len--; ){\n        if ((prefixes[len] + upper)  in elem.style)\n          return (prefixes[len] + upper);\n      }\n    } else {\n      if (prop in obj)\n        return prop;\n\n      for (var len = domPrefixes.length; len--; ){\n        if ((domPrefixes[len] + upper)  in obj)\n          return (domPrefixes[len] + upper);\n      }\n    }\n\n\n    return false;\n  }\n\n  var propArr = ['transition', 'backgroundSize', 'boxSizing', 'borderImage',\n                 'borderRadius', 'boxShadow', 'columnCount'];\n\n  var domPropArr = [{ 'prop': 'requestAnimationFrame',  'obj': window },\n                    { 'prop': 'querySelectorAll',       'obj': document },\n                    { 'prop': 'matchesSelector',        'obj': document.createElement('div') }];\n\n  for (var i = -1, len = propArr.length; ++i < len; ){\n    var prop = propArr[i];\n    equal(Modernizr.prefixed(prop), gimmePrefix(prop), 'results for ' + prop + ' match the homebaked prefix finder');\n  }\n\n  for (var i = -1, len = domPropArr.length; ++i < len; ){\n    var prop = domPropArr[i];\n    ok(!!~Modernizr.prefixed(prop.prop, prop.obj, false).toString().indexOf(gimmePrefix(prop.prop, prop.obj)), 'results for ' + prop.prop + ' match the homebaked prefix finder');\n  }\n\n\n\n\n});\n\n\n// FIXME: so a few of these are whitelisting for webkit. i'd like to improve that.\ntest('Modernizr.prefixed autobind', function(){\n\n  var rAFName;\n\n  // quick sniff to find the local rAF prefixed name.\n  var vendors = ['ms', 'moz', 'webkit', 'o'];\n  for(var x = 0; x < vendors.length && !rAFName; ++x) {\n    rAFName = window[vendors[x]+'RequestAnimationFrame'] && vendors[x]+'RequestAnimationFrame';\n  }\n\n  if (rAFName){\n    // rAF returns a function\n    equal(\n      'function',\n      typeof Modernizr.prefixed('requestAnimationFrame', window),\n      \"Modernizr.prefixed('requestAnimationFrame', window) returns a function\")\n\n    // unless we false it to a string\n    equal(\n      rAFName,\n      Modernizr.prefixed('requestAnimationFrame', window, false),\n      \"Modernizr.prefixed('requestAnimationFrame', window, false) returns a string (the prop name)\")\n\n  }\n\n  if (document.body.webkitMatchesSelector || document.body.mozMatchesSelector){\n\n    var fn = Modernizr.prefixed('matchesSelector', HTMLElement.prototype, document.body);\n\n    //returns function\n    equal(\n      'function',\n      typeof fn,\n      \"Modernizr.prefixed('matchesSelector', HTMLElement.prototype, document.body) returns a function\");\n\n      // fn scoping\n    equal(\n      true,\n      fn('body'),\n      \"Modernizr.prefixed('matchesSelector', HTMLElement.prototype, document.body) is scoped to the body\")\n\n  }\n\n  // Webkit only: are there other objects that are prefixed?\n  if (window.webkitNotifications){\n    // should be an object.\n\n    equal(\n      'object',\n      typeof Modernizr.prefixed('Notifications', window),\n      \"Modernizr.prefixed('Notifications') returns an object\");\n\n  }\n\n  // Webkit only:\n  if (typeof document.webkitIsFullScreen !== 'undefined'){\n    // boolean\n\n    equal(\n      'boolean',\n      typeof Modernizr.prefixed('isFullScreen', document),\n      \"Modernizr.prefixed('isFullScreen') returns a boolean\");\n  }\n\n\n\n  // Moz only:\n  if (typeof document.mozFullScreen !== 'undefined'){\n    // boolean\n\n    equal(\n      'boolean',\n      typeof Modernizr.prefixed('fullScreen', document),\n      \"Modernizr.prefixed('fullScreen') returns a boolean\");\n  }\n\n\n  // Webkit-only.. takes advantage of Webkit's mixed case of prefixes\n  if (document.body.style.WebkitAnimation){\n    // string\n\n    equal(\n      'string',\n      typeof Modernizr.prefixed('animation', document.body.style),\n      \"Modernizr.prefixed('animation', document.body.style) returns value of that, as a string\");\n\n    equal(\n      animationStyle.toLowerCase(),\n      Modernizr.prefixed('animation', document.body.style, false).toLowerCase(),\n      \"Modernizr.prefixed('animation', document.body.style, false) returns the (case-normalized) name of the property: webkitanimation\");\n\n  }\n\n  equal(\n    false,\n    Modernizr.prefixed('doSomethingAmazing$#$', window),\n    \"Modernizr.prefixed('doSomethingAmazing$#$', window) : Gobbledygook with prefixed(str,obj) returns false\");\n\n  equal(\n    false,\n    Modernizr.prefixed('doSomethingAmazing$#$', window, document.body),\n    \"Modernizr.prefixed('doSomethingAmazing$#$', window) : Gobbledygook with prefixed(str,obj, scope) returns false\");\n\n\n  equal(\n    false,\n    Modernizr.prefixed('doSomethingAmazing$#$', window, false),\n    \"Modernizr.prefixed('doSomethingAmazing$#$', window) : Gobbledygook with prefixed(str,obj, false) returns false\");\n\n\n});\n\n\n\n\n\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/modernizr/test/qunit/qunit.css",
    "content": "/**\n * QUnit v1.9.0 - A JavaScript Unit Testing Framework\n *\n * http://docs.jquery.com/QUnit\n *\n * Copyright (c) 2012 John Resig, Jörn Zaefferer\n * Dual licensed under the MIT (MIT-LICENSE.txt)\n * or GPL (GPL-LICENSE.txt) licenses.\n */\n\n/** Font Family and Sizes */\n\n#qunit-tests, #qunit-header, #qunit-banner, #qunit-testrunner-toolbar, #qunit-userAgent, #qunit-testresult {\n\tfont-family: \"Helvetica Neue Light\", \"HelveticaNeue-Light\", \"Helvetica Neue\", Calibri, Helvetica, Arial, sans-serif;\n}\n\n#qunit-testrunner-toolbar, #qunit-userAgent, #qunit-testresult, #qunit-tests li { font-size: small; }\n#qunit-tests { font-size: smaller; }\n\n\n/** Resets */\n\n#qunit-tests, #qunit-tests ol, #qunit-header, #qunit-banner, #qunit-userAgent, #qunit-testresult {\n\tmargin: 0;\n\tpadding: 0;\n}\n\n\n/** Header */\n\n#qunit-header {\n\tpadding: 0.5em 0 0.5em 1em;\n\n\tcolor: #8699a4;\n\tbackground-color: #0d3349;\n\n\tfont-size: 1.5em;\n\tline-height: 1em;\n\tfont-weight: normal;\n\n\tborder-radius: 5px 5px 0 0;\n\t-moz-border-radius: 5px 5px 0 0;\n\t-webkit-border-top-right-radius: 5px;\n\t-webkit-border-top-left-radius: 5px;\n}\n\n#qunit-header a {\n\ttext-decoration: none;\n\tcolor: #c2ccd1;\n}\n\n#qunit-header a:hover,\n#qunit-header a:focus {\n\tcolor: #fff;\n}\n\n#qunit-testrunner-toolbar label {\n\tdisplay: inline-block;\n\tpadding: 0 .5em 0 .1em;\n}\n\n#qunit-banner {\n\theight: 5px;\n}\n\n#qunit-testrunner-toolbar {\n\tpadding: 0.5em 0 0.5em 2em;\n\tcolor: #5E740B;\n\tbackground-color: #eee;\n}\n\n#qunit-userAgent {\n\tpadding: 0.5em 0 0.5em 2.5em;\n\tbackground-color: #2b81af;\n\tcolor: #fff;\n\ttext-shadow: rgba(0, 0, 0, 0.5) 2px 2px 1px;\n}\n\n\n/** Tests: Pass/Fail */\n\n#qunit-tests {\n\tlist-style-position: inside;\n}\n\n#qunit-tests li {\n\tpadding: 0.4em 0.5em 0.4em 2.5em;\n\tborder-bottom: 1px solid #fff;\n\tlist-style-position: inside;\n}\n\n#qunit-tests.hidepass li.pass, #qunit-tests.hidepass li.running  {\n\tdisplay: none;\n}\n\n#qunit-tests li strong {\n\tcursor: pointer;\n}\n\n#qunit-tests li a {\n\tpadding: 0.5em;\n\tcolor: #c2ccd1;\n\ttext-decoration: none;\n}\n#qunit-tests li a:hover,\n#qunit-tests li a:focus {\n\tcolor: #000;\n}\n\n#qunit-tests ol {\n\tmargin-top: 0.5em;\n\tpadding: 0.5em;\n\n\tbackground-color: #fff;\n\n\tborder-radius: 5px;\n\t-moz-border-radius: 5px;\n\t-webkit-border-radius: 5px;\n}\n\n#qunit-tests table {\n\tborder-collapse: collapse;\n\tmargin-top: .2em;\n}\n\n#qunit-tests th {\n\ttext-align: right;\n\tvertical-align: top;\n\tpadding: 0 .5em 0 0;\n}\n\n#qunit-tests td {\n\tvertical-align: top;\n}\n\n#qunit-tests pre {\n\tmargin: 0;\n\twhite-space: pre-wrap;\n\tword-wrap: break-word;\n}\n\n#qunit-tests del {\n\tbackground-color: #e0f2be;\n\tcolor: #374e0c;\n\ttext-decoration: none;\n}\n\n#qunit-tests ins {\n\tbackground-color: #ffcaca;\n\tcolor: #500;\n\ttext-decoration: none;\n}\n\n/*** Test Counts */\n\n#qunit-tests b.counts                       { color: black; }\n#qunit-tests b.passed                       { color: #5E740B; }\n#qunit-tests b.failed                       { color: #710909; }\n\n#qunit-tests li li {\n\tpadding: 5px;\n\tbackground-color: #fff;\n\tborder-bottom: none;\n\tlist-style-position: inside;\n}\n\n/*** Passing Styles */\n\n#qunit-tests li li.pass {\n\tcolor: #3c510c;\n\tbackground-color: #fff;\n\tborder-left: 10px solid #C6E746;\n}\n\n#qunit-tests .pass                          { color: #528CE0; background-color: #D2E0E6; }\n#qunit-tests .pass .test-name               { color: #366097; }\n\n#qunit-tests .pass .test-actual,\n#qunit-tests .pass .test-expected           { color: #999999; }\n\n#qunit-banner.qunit-pass                    { background-color: #C6E746; }\n\n/*** Failing Styles */\n\n#qunit-tests li li.fail {\n\tcolor: #710909;\n\tbackground-color: #fff;\n\tborder-left: 10px solid #EE5757;\n\twhite-space: pre;\n}\n\n#qunit-tests > li:last-child {\n\tborder-radius: 0 0 5px 5px;\n\t-moz-border-radius: 0 0 5px 5px;\n\t-webkit-border-bottom-right-radius: 5px;\n\t-webkit-border-bottom-left-radius: 5px;\n}\n\n#qunit-tests .fail                          { color: #000000; background-color: #EE5757; }\n#qunit-tests .fail .test-name,\n#qunit-tests .fail .module-name             { color: #000000; }\n\n#qunit-tests .fail .test-actual             { color: #EE5757; }\n#qunit-tests .fail .test-expected           { color: green;   }\n\n#qunit-banner.qunit-fail                    { background-color: #EE5757; }\n\n\n/** Result */\n\n#qunit-testresult {\n\tpadding: 0.5em 0.5em 0.5em 2.5em;\n\n\tcolor: #2b81af;\n\tbackground-color: #D2E0E6;\n\n\tborder-bottom: 1px solid white;\n}\n#qunit-testresult .module-name {\n\tfont-weight: bold;\n}\n\n/** Fixture */\n\n#qunit-fixture {\n\tposition: absolute;\n\ttop: -10000px;\n\tleft: -10000px;\n\twidth: 1000px;\n\theight: 1000px;\n}\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/modernizr/test/qunit/qunit.js",
    "content": "/**\n * QUnit v1.9.0 - A JavaScript Unit Testing Framework\n *\n * http://docs.jquery.com/QUnit\n *\n * Copyright (c) 2012 John Resig, Jörn Zaefferer\n * Dual licensed under the MIT (MIT-LICENSE.txt)\n * or GPL (GPL-LICENSE.txt) licenses.\n */\n\n(function( window ) {\n\nvar QUnit,\n\tconfig,\n\tonErrorFnPrev,\n\ttestId = 0,\n\tfileName = (sourceFromStacktrace( 0 ) || \"\" ).replace(/(:\\d+)+\\)?/, \"\").replace(/.+\\//, \"\"),\n\ttoString = Object.prototype.toString,\n\thasOwn = Object.prototype.hasOwnProperty,\n\tdefined = {\n\tsetTimeout: typeof window.setTimeout !== \"undefined\",\n\tsessionStorage: (function() {\n\t\tvar x = \"qunit-test-string\";\n\t\ttry {\n\t\t\tsessionStorage.setItem( x, x );\n\t\t\tsessionStorage.removeItem( x );\n\t\t\treturn true;\n\t\t} catch( e ) {\n\t\t\treturn false;\n\t\t}\n\t}())\n};\n\nfunction Test( settings ) {\n\textend( this, settings );\n\tthis.assertions = [];\n\tthis.testNumber = ++Test.count;\n}\n\nTest.count = 0;\n\nTest.prototype = {\n\tinit: function() {\n\t\tvar a, b, li,\n        tests = id( \"qunit-tests\" );\n\n\t\tif ( tests ) {\n\t\t\tb = document.createElement( \"strong\" );\n\t\t\tb.innerHTML = this.name;\n\n\t\t\t// `a` initialized at top of scope\n\t\t\ta = document.createElement( \"a\" );\n\t\t\ta.innerHTML = \"Rerun\";\n\t\t\ta.href = QUnit.url({ testNumber: this.testNumber });\n\n\t\t\tli = document.createElement( \"li\" );\n\t\t\tli.appendChild( b );\n\t\t\tli.appendChild( a );\n\t\t\tli.className = \"running\";\n\t\t\tli.id = this.id = \"qunit-test-output\" + testId++;\n\n\t\t\ttests.appendChild( li );\n\t\t}\n\t},\n\tsetup: function() {\n\t\tif ( this.module !== config.previousModule ) {\n\t\t\tif ( config.previousModule ) {\n\t\t\t\trunLoggingCallbacks( \"moduleDone\", QUnit, {\n\t\t\t\t\tname: config.previousModule,\n\t\t\t\t\tfailed: config.moduleStats.bad,\n\t\t\t\t\tpassed: config.moduleStats.all - config.moduleStats.bad,\n\t\t\t\t\ttotal: config.moduleStats.all\n\t\t\t\t});\n\t\t\t}\n\t\t\tconfig.previousModule = this.module;\n\t\t\tconfig.moduleStats = { all: 0, bad: 0 };\n\t\t\trunLoggingCallbacks( \"moduleStart\", QUnit, {\n\t\t\t\tname: this.module\n\t\t\t});\n\t\t} else if ( config.autorun ) {\n\t\t\trunLoggingCallbacks( \"moduleStart\", QUnit, {\n\t\t\t\tname: this.module\n\t\t\t});\n\t\t}\n\n\t\tconfig.current = this;\n\n\t\tthis.testEnvironment = extend({\n\t\t\tsetup: function() {},\n\t\t\tteardown: function() {}\n\t\t}, this.moduleTestEnvironment );\n\n\t\trunLoggingCallbacks( \"testStart\", QUnit, {\n\t\t\tname: this.testName,\n\t\t\tmodule: this.module\n\t\t});\n\n\t\t// allow utility functions to access the current test environment\n\t\t// TODO why??\n\t\tQUnit.current_testEnvironment = this.testEnvironment;\n\n\t\tif ( !config.pollution ) {\n\t\t\tsaveGlobal();\n\t\t}\n\t\tif ( config.notrycatch ) {\n\t\t\tthis.testEnvironment.setup.call( this.testEnvironment );\n\t\t\treturn;\n\t\t}\n\t\ttry {\n\t\t\tthis.testEnvironment.setup.call( this.testEnvironment );\n\t\t} catch( e ) {\n\t\t\tQUnit.pushFailure( \"Setup failed on \" + this.testName + \": \" + e.message, extractStacktrace( e, 1 ) );\n\t\t}\n\t},\n\trun: function() {\n\t\tconfig.current = this;\n\n\t\tvar running = id( \"qunit-testresult\" );\n\n\t\tif ( running ) {\n\t\t\trunning.innerHTML = \"Running: <br/>\" + this.name;\n\t\t}\n\n\t\tif ( this.async ) {\n\t\t\tQUnit.stop();\n\t\t}\n\n\t\tif ( config.notrycatch ) {\n\t\t\tthis.callback.call( this.testEnvironment, QUnit.assert );\n\t\t\treturn;\n\t\t}\n\n\t\ttry {\n\t\t\tthis.callback.call( this.testEnvironment, QUnit.assert );\n\t\t} catch( e ) {\n\t\t\tQUnit.pushFailure( \"Died on test #\" + (this.assertions.length + 1) + \" \" + this.stack + \": \" + e.message, extractStacktrace( e, 0 ) );\n\t\t\t// else next test will carry the responsibility\n\t\t\tsaveGlobal();\n\n\t\t\t// Restart the tests if they're blocking\n\t\t\tif ( config.blocking ) {\n\t\t\t\tQUnit.start();\n\t\t\t}\n\t\t}\n\t},\n\tteardown: function() {\n\t\tconfig.current = this;\n\t\tif ( config.notrycatch ) {\n\t\t\tthis.testEnvironment.teardown.call( this.testEnvironment );\n\t\t\treturn;\n\t\t} else {\n\t\t\ttry {\n\t\t\t\tthis.testEnvironment.teardown.call( this.testEnvironment );\n\t\t\t} catch( e ) {\n\t\t\t\tQUnit.pushFailure( \"Teardown failed on \" + this.testName + \": \" + e.message, extractStacktrace( e, 1 ) );\n\t\t\t}\n\t\t}\n\t\tcheckPollution();\n\t},\n\tfinish: function() {\n\t\tconfig.current = this;\n\t\tif ( config.requireExpects && this.expected == null ) {\n\t\t\tQUnit.pushFailure( \"Expected number of assertions to be defined, but expect() was not called.\", this.stack );\n\t\t} else if ( this.expected != null && this.expected != this.assertions.length ) {\n\t\t\tQUnit.pushFailure( \"Expected \" + this.expected + \" assertions, but \" + this.assertions.length + \" were run\", this.stack );\n\t\t} else if ( this.expected == null && !this.assertions.length ) {\n\t\t\tQUnit.pushFailure( \"Expected at least one assertion, but none were run - call expect(0) to accept zero assertions.\", this.stack );\n\t\t}\n\n\t\tvar assertion, a, b, i, li, ol,\n\t\t\ttest = this,\n\t\t\tgood = 0,\n\t\t\tbad = 0,\n\t\t\ttests = id( \"qunit-tests\" );\n\n\t\tconfig.stats.all += this.assertions.length;\n\t\tconfig.moduleStats.all += this.assertions.length;\n\n\t\tif ( tests ) {\n\t\t\tol = document.createElement( \"ol\" );\n\n\t\t\tfor ( i = 0; i < this.assertions.length; i++ ) {\n\t\t\t\tassertion = this.assertions[i];\n\n\t\t\t\tli = document.createElement( \"li\" );\n\t\t\t\tli.className = assertion.result ? \"pass\" : \"fail\";\n\t\t\t\tli.innerHTML = assertion.message || ( assertion.result ? \"okay\" : \"failed\" );\n\t\t\t\tol.appendChild( li );\n\n\t\t\t\tif ( assertion.result ) {\n\t\t\t\t\tgood++;\n\t\t\t\t} else {\n\t\t\t\t\tbad++;\n\t\t\t\t\tconfig.stats.bad++;\n\t\t\t\t\tconfig.moduleStats.bad++;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// store result when possible\n\t\t\tif ( QUnit.config.reorder && defined.sessionStorage ) {\n\t\t\t\tif ( bad ) {\n\t\t\t\t\tsessionStorage.setItem( \"qunit-test-\" + this.module + \"-\" + this.testName, bad );\n\t\t\t\t} else {\n\t\t\t\t\tsessionStorage.removeItem( \"qunit-test-\" + this.module + \"-\" + this.testName );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( bad === 0 ) {\n\t\t\t\tol.style.display = \"none\";\n\t\t\t}\n\n\t\t\t// `b` initialized at top of scope\n\t\t\tb = document.createElement( \"strong\" );\n\t\t\tb.innerHTML = this.name + \" <b class='counts'>(<b class='failed'>\" + bad + \"</b>, <b class='passed'>\" + good + \"</b>, \" + this.assertions.length + \")</b>\";\n\n\t\t\taddEvent(b, \"click\", function() {\n\t\t\t\tvar next = b.nextSibling.nextSibling,\n\t\t\t\t\tdisplay = next.style.display;\n\t\t\t\tnext.style.display = display === \"none\" ? \"block\" : \"none\";\n\t\t\t});\n\n\t\t\taddEvent(b, \"dblclick\", function( e ) {\n\t\t\t\tvar target = e && e.target ? e.target : window.event.srcElement;\n\t\t\t\tif ( target.nodeName.toLowerCase() == \"span\" || target.nodeName.toLowerCase() == \"b\" ) {\n\t\t\t\t\ttarget = target.parentNode;\n\t\t\t\t}\n\t\t\t\tif ( window.location && target.nodeName.toLowerCase() === \"strong\" ) {\n\t\t\t\t\twindow.location = QUnit.url({ testNumber: test.testNumber });\n\t\t\t\t}\n\t\t\t});\n\n\t\t\t// `li` initialized at top of scope\n\t\t\tli = id( this.id );\n\t\t\tli.className = bad ? \"fail\" : \"pass\";\n\t\t\tli.removeChild( li.firstChild );\n\t\t\ta = li.firstChild;\n\t\t\tli.appendChild( b );\n\t\t\tli.appendChild ( a );\n\t\t\tli.appendChild( ol );\n\n\t\t} else {\n\t\t\tfor ( i = 0; i < this.assertions.length; i++ ) {\n\t\t\t\tif ( !this.assertions[i].result ) {\n\t\t\t\t\tbad++;\n\t\t\t\t\tconfig.stats.bad++;\n\t\t\t\t\tconfig.moduleStats.bad++;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\trunLoggingCallbacks( \"testDone\", QUnit, {\n\t\t\tname: this.testName,\n\t\t\tmodule: this.module,\n\t\t\tfailed: bad,\n\t\t\tpassed: this.assertions.length - bad,\n\t\t\ttotal: this.assertions.length\n\t\t});\n\n\t\tQUnit.reset();\n\n\t\tconfig.current = undefined;\n\t},\n\n\tqueue: function() {\n\t\tvar bad,\n\t\t\ttest = this;\n\n\t\tsynchronize(function() {\n\t\t\ttest.init();\n\t\t});\n\t\tfunction run() {\n\t\t\t// each of these can by async\n\t\t\tsynchronize(function() {\n\t\t\t\ttest.setup();\n\t\t\t});\n\t\t\tsynchronize(function() {\n\t\t\t\ttest.run();\n\t\t\t});\n\t\t\tsynchronize(function() {\n\t\t\t\ttest.teardown();\n\t\t\t});\n\t\t\tsynchronize(function() {\n\t\t\t\ttest.finish();\n\t\t\t});\n\t\t}\n\n\t\t// `bad` initialized at top of scope\n\t\t// defer when previous test run passed, if storage is available\n\t\tbad = QUnit.config.reorder && defined.sessionStorage &&\n\t\t\t\t\t\t+sessionStorage.getItem( \"qunit-test-\" + this.module + \"-\" + this.testName );\n\n\t\tif ( bad ) {\n\t\t\trun();\n\t\t} else {\n\t\t\tsynchronize( run, true );\n\t\t}\n\t}\n};\n\n// Root QUnit object.\n// `QUnit` initialized at top of scope\nQUnit = {\n\n\t// call on start of module test to prepend name to all tests\n\tmodule: function( name, testEnvironment ) {\n\t\tconfig.currentModule = name;\n\t\tconfig.currentModuleTestEnviroment = testEnvironment;\n\t},\n\n\tasyncTest: function( testName, expected, callback ) {\n\t\tif ( arguments.length === 2 ) {\n\t\t\tcallback = expected;\n\t\t\texpected = null;\n\t\t}\n\n\t\tQUnit.test( testName, expected, callback, true );\n\t},\n\n\ttest: function( testName, expected, callback, async ) {\n\t\tvar test,\n\t\t\tname = \"<span class='test-name'>\" + escapeInnerText( testName ) + \"</span>\";\n\n\t\tif ( arguments.length === 2 ) {\n\t\t\tcallback = expected;\n\t\t\texpected = null;\n\t\t}\n\n\t\tif ( config.currentModule ) {\n\t\t\tname = \"<span class='module-name'>\" + config.currentModule + \"</span>: \" + name;\n\t\t}\n\n\t\ttest = new Test({\n\t\t\tname: name,\n\t\t\ttestName: testName,\n\t\t\texpected: expected,\n\t\t\tasync: async,\n\t\t\tcallback: callback,\n\t\t\tmodule: config.currentModule,\n\t\t\tmoduleTestEnvironment: config.currentModuleTestEnviroment,\n\t\t\tstack: sourceFromStacktrace( 2 )\n\t\t});\n\n\t\tif ( !validTest( test ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\ttest.queue();\n\t},\n\n\t// Specify the number of expected assertions to gurantee that failed test (no assertions are run at all) don't slip through.\n\texpect: function( asserts ) {\n\t\tconfig.current.expected = asserts;\n\t},\n\n\tstart: function( count ) {\n\t\tconfig.semaphore -= count || 1;\n\t\t// don't start until equal number of stop-calls\n\t\tif ( config.semaphore > 0 ) {\n\t\t\treturn;\n\t\t}\n\t\t// ignore if start is called more often then stop\n\t\tif ( config.semaphore < 0 ) {\n\t\t\tconfig.semaphore = 0;\n\t\t}\n\t\t// A slight delay, to avoid any current callbacks\n\t\tif ( defined.setTimeout ) {\n\t\t\twindow.setTimeout(function() {\n\t\t\t\tif ( config.semaphore > 0 ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tif ( config.timeout ) {\n\t\t\t\t\tclearTimeout( config.timeout );\n\t\t\t\t}\n\n\t\t\t\tconfig.blocking = false;\n\t\t\t\tprocess( true );\n\t\t\t}, 13);\n\t\t} else {\n\t\t\tconfig.blocking = false;\n\t\t\tprocess( true );\n\t\t}\n\t},\n\n\tstop: function( count ) {\n\t\tconfig.semaphore += count || 1;\n\t\tconfig.blocking = true;\n\n\t\tif ( config.testTimeout && defined.setTimeout ) {\n\t\t\tclearTimeout( config.timeout );\n\t\t\tconfig.timeout = window.setTimeout(function() {\n\t\t\t\tQUnit.ok( false, \"Test timed out\" );\n\t\t\t\tconfig.semaphore = 1;\n\t\t\t\tQUnit.start();\n\t\t\t}, config.testTimeout );\n\t\t}\n\t}\n};\n\n// Asssert helpers\n// All of these must call either QUnit.push() or manually do:\n// - runLoggingCallbacks( \"log\", .. );\n// - config.current.assertions.push({ .. });\nQUnit.assert = {\n\t/**\n\t * Asserts rough true-ish result.\n\t * @name ok\n\t * @function\n\t * @example ok( \"asdfasdf\".length > 5, \"There must be at least 5 chars\" );\n\t */\n\tok: function( result, msg ) {\n\t\tif ( !config.current ) {\n\t\t\tthrow new Error( \"ok() assertion outside test context, was \" + sourceFromStacktrace(2) );\n\t\t}\n\t\tresult = !!result;\n\n\t\tvar source,\n\t\t\tdetails = {\n\t\t\t\tresult: result,\n\t\t\t\tmessage: msg\n\t\t\t};\n\n\t\tmsg = escapeInnerText( msg || (result ? \"okay\" : \"failed\" ) );\n\t\tmsg = \"<span class='test-message'>\" + msg + \"</span>\";\n\n\t\tif ( !result ) {\n\t\t\tsource = sourceFromStacktrace( 2 );\n\t\t\tif ( source ) {\n\t\t\t\tdetails.source = source;\n\t\t\t\tmsg += \"<table><tr class='test-source'><th>Source: </th><td><pre>\" + escapeInnerText( source ) + \"</pre></td></tr></table>\";\n\t\t\t}\n\t\t}\n\t\trunLoggingCallbacks( \"log\", QUnit, details );\n\t\tconfig.current.assertions.push({\n\t\t\tresult: result,\n\t\t\tmessage: msg\n\t\t});\n\t},\n\n\t/**\n\t * Assert that the first two arguments are equal, with an optional message.\n\t * Prints out both actual and expected values.\n\t * @name equal\n\t * @function\n\t * @example equal( format( \"Received {0} bytes.\", 2), \"Received 2 bytes.\", \"format() replaces {0} with next argument\" );\n\t */\n\tequal: function( actual, expected, message ) {\n\t\tQUnit.push( expected == actual, actual, expected, message );\n\t},\n\n\t/**\n\t * @name notEqual\n\t * @function\n\t */\n\tnotEqual: function( actual, expected, message ) {\n\t\tQUnit.push( expected != actual, actual, expected, message );\n\t},\n\n\t/**\n\t * @name deepEqual\n\t * @function\n\t */\n\tdeepEqual: function( actual, expected, message ) {\n\t\tQUnit.push( QUnit.equiv(actual, expected), actual, expected, message );\n\t},\n\n\t/**\n\t * @name notDeepEqual\n\t * @function\n\t */\n\tnotDeepEqual: function( actual, expected, message ) {\n\t\tQUnit.push( !QUnit.equiv(actual, expected), actual, expected, message );\n\t},\n\n\t/**\n\t * @name strictEqual\n\t * @function\n\t */\n\tstrictEqual: function( actual, expected, message ) {\n\t\tQUnit.push( expected === actual, actual, expected, message );\n\t},\n\n\t/**\n\t * @name notStrictEqual\n\t * @function\n\t */\n\tnotStrictEqual: function( actual, expected, message ) {\n\t\tQUnit.push( expected !== actual, actual, expected, message );\n\t},\n\n\tthrows: function( block, expected, message ) {\n\t\tvar actual,\n\t\t\tok = false;\n\n\t\t// 'expected' is optional\n\t\tif ( typeof expected === \"string\" ) {\n\t\t\tmessage = expected;\n\t\t\texpected = null;\n\t\t}\n\n\t\tconfig.current.ignoreGlobalErrors = true;\n\t\ttry {\n\t\t\tblock.call( config.current.testEnvironment );\n\t\t} catch (e) {\n\t\t\tactual = e;\n\t\t}\n\t\tconfig.current.ignoreGlobalErrors = false;\n\n\t\tif ( actual ) {\n\t\t\t// we don't want to validate thrown error\n\t\t\tif ( !expected ) {\n\t\t\t\tok = true;\n\t\t\t// expected is a regexp\n\t\t\t} else if ( QUnit.objectType( expected ) === \"regexp\" ) {\n\t\t\t\tok = expected.test( actual );\n\t\t\t// expected is a constructor\n\t\t\t} else if ( actual instanceof expected ) {\n\t\t\t\tok = true;\n\t\t\t// expected is a validation function which returns true is validation passed\n\t\t\t} else if ( expected.call( {}, actual ) === true ) {\n\t\t\t\tok = true;\n\t\t\t}\n\n\t\t\tQUnit.push( ok, actual, null, message );\n\t\t} else {\n\t\t\tQUnit.pushFailure( message, null, 'No exception was thrown.' );\n\t\t}\n\t}\n};\n\n/**\n * @deprecate since 1.8.0\n * Kept assertion helpers in root for backwards compatibility\n */\nextend( QUnit, QUnit.assert );\n\n/**\n * @deprecated since 1.9.0\n * Kept global \"raises()\" for backwards compatibility\n */\nQUnit.raises = QUnit.assert.throws;\n\n/**\n * @deprecated since 1.0.0, replaced with error pushes since 1.3.0\n * Kept to avoid TypeErrors for undefined methods.\n */\nQUnit.equals = function() {\n\tQUnit.push( false, false, false, \"QUnit.equals has been deprecated since 2009 (e88049a0), use QUnit.equal instead\" );\n};\nQUnit.same = function() {\n\tQUnit.push( false, false, false, \"QUnit.same has been deprecated since 2009 (e88049a0), use QUnit.deepEqual instead\" );\n};\n\n// We want access to the constructor's prototype\n(function() {\n\tfunction F() {}\n\tF.prototype = QUnit;\n\tQUnit = new F();\n\t// Make F QUnit's constructor so that we can add to the prototype later\n\tQUnit.constructor = F;\n}());\n\n/**\n * Config object: Maintain internal state\n * Later exposed as QUnit.config\n * `config` initialized at top of scope\n */\nconfig = {\n\t// The queue of tests to run\n\tqueue: [],\n\n\t// block until document ready\n\tblocking: true,\n\n\t// when enabled, show only failing tests\n\t// gets persisted through sessionStorage and can be changed in UI via checkbox\n\thidepassed: false,\n\n\t// by default, run previously failed tests first\n\t// very useful in combination with \"Hide passed tests\" checked\n\treorder: true,\n\n\t// by default, modify document.title when suite is done\n\taltertitle: true,\n\n\t// when enabled, all tests must call expect()\n\trequireExpects: false,\n\n\t// add checkboxes that are persisted in the query-string\n\t// when enabled, the id is set to `true` as a `QUnit.config` property\n\turlConfig: [\n\t\t{\n\t\t\tid: \"noglobals\",\n\t\t\tlabel: \"Check for Globals\",\n\t\t\ttooltip: \"Enabling this will test if any test introduces new properties on the `window` object. Stored as query-strings.\"\n\t\t},\n\t\t{\n\t\t\tid: \"notrycatch\",\n\t\t\tlabel: \"No try-catch\",\n\t\t\ttooltip: \"Enabling this will run tests outside of a try-catch block. Makes debugging exceptions in IE reasonable. Stored as query-strings.\"\n\t\t}\n\t],\n\n\t// logging callback queues\n\tbegin: [],\n\tdone: [],\n\tlog: [],\n\ttestStart: [],\n\ttestDone: [],\n\tmoduleStart: [],\n\tmoduleDone: []\n};\n\n// Initialize more QUnit.config and QUnit.urlParams\n(function() {\n\tvar i,\n\t\tlocation = window.location || { search: \"\", protocol: \"file:\" },\n\t\tparams = location.search.slice( 1 ).split( \"&\" ),\n\t\tlength = params.length,\n\t\turlParams = {},\n\t\tcurrent;\n\n\tif ( params[ 0 ] ) {\n\t\tfor ( i = 0; i < length; i++ ) {\n\t\t\tcurrent = params[ i ].split( \"=\" );\n\t\t\tcurrent[ 0 ] = decodeURIComponent( current[ 0 ] );\n\t\t\t// allow just a key to turn on a flag, e.g., test.html?noglobals\n\t\t\tcurrent[ 1 ] = current[ 1 ] ? decodeURIComponent( current[ 1 ] ) : true;\n\t\t\turlParams[ current[ 0 ] ] = current[ 1 ];\n\t\t}\n\t}\n\n\tQUnit.urlParams = urlParams;\n\n\t// String search anywhere in moduleName+testName\n\tconfig.filter = urlParams.filter;\n\n\t// Exact match of the module name\n\tconfig.module = urlParams.module;\n\n\tconfig.testNumber = parseInt( urlParams.testNumber, 10 ) || null;\n\n\t// Figure out if we're running the tests from a server or not\n\tQUnit.isLocal = location.protocol === \"file:\";\n}());\n\n// Export global variables, unless an 'exports' object exists,\n// in that case we assume we're in CommonJS (dealt with on the bottom of the script)\nif ( typeof exports === \"undefined\" ) {\n\textend( window, QUnit );\n\n\t// Expose QUnit object\n\twindow.QUnit = QUnit;\n}\n\n// Extend QUnit object,\n// these after set here because they should not be exposed as global functions\nextend( QUnit, {\n\tconfig: config,\n\n\t// Initialize the configuration options\n\tinit: function() {\n\t\textend( config, {\n\t\t\tstats: { all: 0, bad: 0 },\n\t\t\tmoduleStats: { all: 0, bad: 0 },\n\t\t\tstarted: +new Date(),\n\t\t\tupdateRate: 1000,\n\t\t\tblocking: false,\n\t\t\tautostart: true,\n\t\t\tautorun: false,\n\t\t\tfilter: \"\",\n\t\t\tqueue: [],\n\t\t\tsemaphore: 0\n\t\t});\n\n\t\tvar tests, banner, result,\n\t\t\tqunit = id( \"qunit\" );\n\n\t\tif ( qunit ) {\n\t\t\tqunit.innerHTML =\n\t\t\t\t\"<h1 id='qunit-header'>\" + escapeInnerText( document.title ) + \"</h1>\" +\n\t\t\t\t\"<h2 id='qunit-banner'></h2>\" +\n\t\t\t\t\"<div id='qunit-testrunner-toolbar'></div>\" +\n\t\t\t\t\"<h2 id='qunit-userAgent'></h2>\" +\n\t\t\t\t\"<ol id='qunit-tests'></ol>\";\n\t\t}\n\n\t\ttests = id( \"qunit-tests\" );\n\t\tbanner = id( \"qunit-banner\" );\n\t\tresult = id( \"qunit-testresult\" );\n\n\t\tif ( tests ) {\n\t\t\ttests.innerHTML = \"\";\n\t\t}\n\n\t\tif ( banner ) {\n\t\t\tbanner.className = \"\";\n\t\t}\n\n\t\tif ( result ) {\n\t\t\tresult.parentNode.removeChild( result );\n\t\t}\n\n\t\tif ( tests ) {\n\t\t\tresult = document.createElement( \"p\" );\n\t\t\tresult.id = \"qunit-testresult\";\n\t\t\tresult.className = \"result\";\n\t\t\ttests.parentNode.insertBefore( result, tests );\n\t\t\tresult.innerHTML = \"Running...<br/>&nbsp;\";\n\t\t}\n\t},\n\n\t// Resets the test setup. Useful for tests that modify the DOM.\n\t// If jQuery is available, uses jQuery's html(), otherwise just innerHTML.\n\treset: function() {\n\t\tvar fixture;\n\n\t\tif ( window.jQuery ) {\n\t\t\tjQuery( \"#qunit-fixture\" ).html( config.fixture );\n\t\t} else {\n\t\t\tfixture = id( \"qunit-fixture\" );\n\t\t\tif ( fixture ) {\n\t\t\t\tfixture.innerHTML = config.fixture;\n\t\t\t}\n\t\t}\n\t},\n\n\t// Trigger an event on an element.\n\t// @example triggerEvent( document.body, \"click\" );\n\ttriggerEvent: function( elem, type, event ) {\n\t\tif ( document.createEvent ) {\n\t\t\tevent = document.createEvent( \"MouseEvents\" );\n\t\t\tevent.initMouseEvent(type, true, true, elem.ownerDocument.defaultView,\n\t\t\t\t0, 0, 0, 0, 0, false, false, false, false, 0, null);\n\n\t\t\telem.dispatchEvent( event );\n\t\t} else if ( elem.fireEvent ) {\n\t\t\telem.fireEvent( \"on\" + type );\n\t\t}\n\t},\n\n\t// Safe object type checking\n\tis: function( type, obj ) {\n\t\treturn QUnit.objectType( obj ) == type;\n\t},\n\n\tobjectType: function( obj ) {\n\t\tif ( typeof obj === \"undefined\" ) {\n\t\t\t\treturn \"undefined\";\n\t\t// consider: typeof null === object\n\t\t}\n\t\tif ( obj === null ) {\n\t\t\t\treturn \"null\";\n\t\t}\n\n\t\tvar type = toString.call( obj ).match(/^\\[object\\s(.*)\\]$/)[1] || \"\";\n\n\t\tswitch ( type ) {\n\t\t\tcase \"Number\":\n\t\t\t\tif ( isNaN(obj) ) {\n\t\t\t\t\treturn \"nan\";\n\t\t\t\t}\n\t\t\t\treturn \"number\";\n\t\t\tcase \"String\":\n\t\t\tcase \"Boolean\":\n\t\t\tcase \"Array\":\n\t\t\tcase \"Date\":\n\t\t\tcase \"RegExp\":\n\t\t\tcase \"Function\":\n\t\t\t\treturn type.toLowerCase();\n\t\t}\n\t\tif ( typeof obj === \"object\" ) {\n\t\t\treturn \"object\";\n\t\t}\n\t\treturn undefined;\n\t},\n\n\tpush: function( result, actual, expected, message ) {\n\t\tif ( !config.current ) {\n\t\t\tthrow new Error( \"assertion outside test context, was \" + sourceFromStacktrace() );\n\t\t}\n\n\t\tvar output, source,\n\t\t\tdetails = {\n\t\t\t\tresult: result,\n\t\t\t\tmessage: message,\n\t\t\t\tactual: actual,\n\t\t\t\texpected: expected\n\t\t\t};\n\n\t\tmessage = escapeInnerText( message ) || ( result ? \"okay\" : \"failed\" );\n\t\tmessage = \"<span class='test-message'>\" + message + \"</span>\";\n\t\toutput = message;\n\n\t\tif ( !result ) {\n\t\t\texpected = escapeInnerText( QUnit.jsDump.parse(expected) );\n\t\t\tactual = escapeInnerText( QUnit.jsDump.parse(actual) );\n\t\t\toutput += \"<table><tr class='test-expected'><th>Expected: </th><td><pre>\" + expected + \"</pre></td></tr>\";\n\n\t\t\tif ( actual != expected ) {\n\t\t\t\toutput += \"<tr class='test-actual'><th>Result: </th><td><pre>\" + actual + \"</pre></td></tr>\";\n\t\t\t\toutput += \"<tr class='test-diff'><th>Diff: </th><td><pre>\" + QUnit.diff( expected, actual ) + \"</pre></td></tr>\";\n\t\t\t}\n\n\t\t\tsource = sourceFromStacktrace();\n\n\t\t\tif ( source ) {\n\t\t\t\tdetails.source = source;\n\t\t\t\toutput += \"<tr class='test-source'><th>Source: </th><td><pre>\" + escapeInnerText( source ) + \"</pre></td></tr>\";\n\t\t\t}\n\n\t\t\toutput += \"</table>\";\n\t\t}\n\n\t\trunLoggingCallbacks( \"log\", QUnit, details );\n\n\t\tconfig.current.assertions.push({\n\t\t\tresult: !!result,\n\t\t\tmessage: output\n\t\t});\n\t},\n\n\tpushFailure: function( message, source, actual ) {\n\t\tif ( !config.current ) {\n\t\t\tthrow new Error( \"pushFailure() assertion outside test context, was \" + sourceFromStacktrace(2) );\n\t\t}\n\n\t\tvar output,\n\t\t\tdetails = {\n\t\t\t\tresult: false,\n\t\t\t\tmessage: message\n\t\t\t};\n\n\t\tmessage = escapeInnerText( message ) || \"error\";\n\t\tmessage = \"<span class='test-message'>\" + message + \"</span>\";\n\t\toutput = message;\n\n\t\toutput += \"<table>\";\n\n\t\tif ( actual ) {\n\t\t\toutput += \"<tr class='test-actual'><th>Result: </th><td><pre>\" + escapeInnerText( actual ) + \"</pre></td></tr>\";\n\t\t}\n\n\t\tif ( source ) {\n\t\t\tdetails.source = source;\n\t\t\toutput += \"<tr class='test-source'><th>Source: </th><td><pre>\" + escapeInnerText( source ) + \"</pre></td></tr>\";\n\t\t}\n\n\t\toutput += \"</table>\";\n\n\t\trunLoggingCallbacks( \"log\", QUnit, details );\n\n\t\tconfig.current.assertions.push({\n\t\t\tresult: false,\n\t\t\tmessage: output\n\t\t});\n\t},\n\n\turl: function( params ) {\n\t\tparams = extend( extend( {}, QUnit.urlParams ), params );\n\t\tvar key,\n\t\t\tquerystring = \"?\";\n\n\t\tfor ( key in params ) {\n\t\t\tif ( !hasOwn.call( params, key ) ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tquerystring += encodeURIComponent( key ) + \"=\" +\n\t\t\t\tencodeURIComponent( params[ key ] ) + \"&\";\n\t\t}\n\t\treturn window.location.pathname + querystring.slice( 0, -1 );\n\t},\n\n\textend: extend,\n\tid: id,\n\taddEvent: addEvent\n\t// load, equiv, jsDump, diff: Attached later\n});\n\n/**\n * @deprecated: Created for backwards compatibility with test runner that set the hook function\n * into QUnit.{hook}, instead of invoking it and passing the hook function.\n * QUnit.constructor is set to the empty F() above so that we can add to it's prototype here.\n * Doing this allows us to tell if the following methods have been overwritten on the actual\n * QUnit object.\n */\nextend( QUnit.constructor.prototype, {\n\n\t// Logging callbacks; all receive a single argument with the listed properties\n\t// run test/logs.html for any related changes\n\tbegin: registerLoggingCallback( \"begin\" ),\n\n\t// done: { failed, passed, total, runtime }\n\tdone: registerLoggingCallback( \"done\" ),\n\n\t// log: { result, actual, expected, message }\n\tlog: registerLoggingCallback( \"log\" ),\n\n\t// testStart: { name }\n\ttestStart: registerLoggingCallback( \"testStart\" ),\n\n\t// testDone: { name, failed, passed, total }\n\ttestDone: registerLoggingCallback( \"testDone\" ),\n\n\t// moduleStart: { name }\n\tmoduleStart: registerLoggingCallback( \"moduleStart\" ),\n\n\t// moduleDone: { name, failed, passed, total }\n\tmoduleDone: registerLoggingCallback( \"moduleDone\" )\n});\n\nif ( typeof document === \"undefined\" || document.readyState === \"complete\" ) {\n\tconfig.autorun = true;\n}\n\nQUnit.load = function() {\n\trunLoggingCallbacks( \"begin\", QUnit, {} );\n\n\t// Initialize the config, saving the execution queue\n\tvar banner, filter, i, label, len, main, ol, toolbar, userAgent, val, urlConfigCheckboxes,\n\t\turlConfigHtml = \"\",\n\t\toldconfig = extend( {}, config );\n\n\tQUnit.init();\n\textend(config, oldconfig);\n\n\tconfig.blocking = false;\n\n\tlen = config.urlConfig.length;\n\n\tfor ( i = 0; i < len; i++ ) {\n\t\tval = config.urlConfig[i];\n\t\tif ( typeof val === \"string\" ) {\n\t\t\tval = {\n\t\t\t\tid: val,\n\t\t\t\tlabel: val,\n\t\t\t\ttooltip: \"[no tooltip available]\"\n\t\t\t};\n\t\t}\n\t\tconfig[ val.id ] = QUnit.urlParams[ val.id ];\n\t\turlConfigHtml += \"<input id='qunit-urlconfig-\" + val.id + \"' name='\" + val.id + \"' type='checkbox'\" + ( config[ val.id ] ? \" checked='checked'\" : \"\" ) + \" title='\" + val.tooltip + \"'><label for='qunit-urlconfig-\" + val.id + \"' title='\" + val.tooltip + \"'>\" + val.label + \"</label>\";\n\t}\n\n\t// `userAgent` initialized at top of scope\n\tuserAgent = id( \"qunit-userAgent\" );\n\tif ( userAgent ) {\n\t\tuserAgent.innerHTML = navigator.userAgent;\n\t}\n\n\t// `banner` initialized at top of scope\n\tbanner = id( \"qunit-header\" );\n\tif ( banner ) {\n\t\tbanner.innerHTML = \"<a href='\" + QUnit.url({ filter: undefined, module: undefined, testNumber: undefined }) + \"'>\" + banner.innerHTML + \"</a> \";\n\t}\n\n\t// `toolbar` initialized at top of scope\n\ttoolbar = id( \"qunit-testrunner-toolbar\" );\n\tif ( toolbar ) {\n\t\t// `filter` initialized at top of scope\n\t\tfilter = document.createElement( \"input\" );\n\t\tfilter.type = \"checkbox\";\n\t\tfilter.id = \"qunit-filter-pass\";\n\n\t\taddEvent( filter, \"click\", function() {\n\t\t\tvar tmp,\n\t\t\t\tol = document.getElementById( \"qunit-tests\" );\n\n\t\t\tif ( filter.checked ) {\n\t\t\t\tol.className = ol.className + \" hidepass\";\n\t\t\t} else {\n\t\t\t\ttmp = \" \" + ol.className.replace( /[\\n\\t\\r]/g, \" \" ) + \" \";\n\t\t\t\tol.className = tmp.replace( / hidepass /, \" \" );\n\t\t\t}\n\t\t\tif ( defined.sessionStorage ) {\n\t\t\t\tif (filter.checked) {\n\t\t\t\t\tsessionStorage.setItem( \"qunit-filter-passed-tests\", \"true\" );\n\t\t\t\t} else {\n\t\t\t\t\tsessionStorage.removeItem( \"qunit-filter-passed-tests\" );\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\tif ( config.hidepassed || defined.sessionStorage && sessionStorage.getItem( \"qunit-filter-passed-tests\" ) ) {\n\t\t\tfilter.checked = true;\n\t\t\t// `ol` initialized at top of scope\n\t\t\tol = document.getElementById( \"qunit-tests\" );\n\t\t\tol.className = ol.className + \" hidepass\";\n\t\t}\n\t\ttoolbar.appendChild( filter );\n\n\t\t// `label` initialized at top of scope\n\t\tlabel = document.createElement( \"label\" );\n\t\tlabel.setAttribute( \"for\", \"qunit-filter-pass\" );\n\t\tlabel.setAttribute( \"title\", \"Only show tests and assertons that fail. Stored in sessionStorage.\" );\n\t\tlabel.innerHTML = \"Hide passed tests\";\n\t\ttoolbar.appendChild( label );\n\n\t\turlConfigCheckboxes = document.createElement( 'span' );\n\t\turlConfigCheckboxes.innerHTML = urlConfigHtml;\n\t\taddEvent( urlConfigCheckboxes, \"change\", function( event ) {\n\t\t\tvar params = {};\n\t\t\tparams[ event.target.name ] = event.target.checked ? true : undefined;\n\t\t\twindow.location = QUnit.url( params );\n\t\t});\n\t\ttoolbar.appendChild( urlConfigCheckboxes );\n\t}\n\n\t// `main` initialized at top of scope\n\tmain = id( \"qunit-fixture\" );\n\tif ( main ) {\n\t\tconfig.fixture = main.innerHTML;\n\t}\n\n\tif ( config.autostart ) {\n\t\tQUnit.start();\n\t}\n};\n\naddEvent( window, \"load\", QUnit.load );\n\n// `onErrorFnPrev` initialized at top of scope\n// Preserve other handlers\nonErrorFnPrev = window.onerror;\n\n// Cover uncaught exceptions\n// Returning true will surpress the default browser handler,\n// returning false will let it run.\nwindow.onerror = function ( error, filePath, linerNr ) {\n\tvar ret = false;\n\tif ( onErrorFnPrev ) {\n\t\tret = onErrorFnPrev( error, filePath, linerNr );\n\t}\n\n\t// Treat return value as window.onerror itself does,\n\t// Only do our handling if not surpressed.\n\tif ( ret !== true ) {\n\t\tif ( QUnit.config.current ) {\n\t\t\tif ( QUnit.config.current.ignoreGlobalErrors ) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\tQUnit.pushFailure( error, filePath + \":\" + linerNr );\n\t\t} else {\n\t\t\tQUnit.test( \"global failure\", function() {\n\t\t\t\tQUnit.pushFailure( error, filePath + \":\" + linerNr );\n\t\t\t});\n\t\t}\n\t\treturn false;\n\t}\n\n\treturn ret;\n};\n\nfunction done() {\n\tconfig.autorun = true;\n\n\t// Log the last module results\n\tif ( config.currentModule ) {\n\t\trunLoggingCallbacks( \"moduleDone\", QUnit, {\n\t\t\tname: config.currentModule,\n\t\t\tfailed: config.moduleStats.bad,\n\t\t\tpassed: config.moduleStats.all - config.moduleStats.bad,\n\t\t\ttotal: config.moduleStats.all\n\t\t});\n\t}\n\n\tvar i, key,\n\t\tbanner = id( \"qunit-banner\" ),\n\t\ttests = id( \"qunit-tests\" ),\n\t\truntime = +new Date() - config.started,\n\t\tpassed = config.stats.all - config.stats.bad,\n\t\thtml = [\n\t\t\t\"Tests completed in \",\n\t\t\truntime,\n\t\t\t\" milliseconds.<br/>\",\n\t\t\t\"<span class='passed'>\",\n\t\t\tpassed,\n\t\t\t\"</span> tests of <span class='total'>\",\n\t\t\tconfig.stats.all,\n\t\t\t\"</span> passed, <span class='failed'>\",\n\t\t\tconfig.stats.bad,\n\t\t\t\"</span> failed.\"\n\t\t].join( \"\" );\n\n\tif ( banner ) {\n\t\tbanner.className = ( config.stats.bad ? \"qunit-fail\" : \"qunit-pass\" );\n\t}\n\n\tif ( tests ) {\n\t\tid( \"qunit-testresult\" ).innerHTML = html;\n\t}\n\n\tif ( config.altertitle && typeof document !== \"undefined\" && document.title ) {\n\t\t// show ✖ for good, ✔ for bad suite result in title\n\t\t// use escape sequences in case file gets loaded with non-utf-8-charset\n\t\tdocument.title = [\n\t\t\t( config.stats.bad ? \"\\u2716\" : \"\\u2714\" ),\n\t\t\tdocument.title.replace( /^[\\u2714\\u2716] /i, \"\" )\n\t\t].join( \" \" );\n\t}\n\n\t// clear own sessionStorage items if all tests passed\n\tif ( config.reorder && defined.sessionStorage && config.stats.bad === 0 ) {\n\t\t// `key` & `i` initialized at top of scope\n\t\tfor ( i = 0; i < sessionStorage.length; i++ ) {\n\t\t\tkey = sessionStorage.key( i++ );\n\t\t\tif ( key.indexOf( \"qunit-test-\" ) === 0 ) {\n\t\t\t\tsessionStorage.removeItem( key );\n\t\t\t}\n\t\t}\n\t}\n\n\trunLoggingCallbacks( \"done\", QUnit, {\n\t\tfailed: config.stats.bad,\n\t\tpassed: passed,\n\t\ttotal: config.stats.all,\n\t\truntime: runtime\n\t});\n}\n\n/** @return Boolean: true if this test should be ran */\nfunction validTest( test ) {\n\tvar include,\n\t\tfilter = config.filter && config.filter.toLowerCase(),\n\t\tmodule = config.module && config.module.toLowerCase(),\n\t\tfullName = (test.module + \": \" + test.testName).toLowerCase();\n\n\tif ( config.testNumber ) {\n\t\treturn test.testNumber === config.testNumber;\n\t}\n\n\tif ( module && ( !test.module || test.module.toLowerCase() !== module ) ) {\n\t\treturn false;\n\t}\n\n\tif ( !filter ) {\n\t\treturn true;\n\t}\n\n\tinclude = filter.charAt( 0 ) !== \"!\";\n\tif ( !include ) {\n\t\tfilter = filter.slice( 1 );\n\t}\n\n\t// If the filter matches, we need to honour include\n\tif ( fullName.indexOf( filter ) !== -1 ) {\n\t\treturn include;\n\t}\n\n\t// Otherwise, do the opposite\n\treturn !include;\n}\n\n// so far supports only Firefox, Chrome and Opera (buggy), Safari (for real exceptions)\n// Later Safari and IE10 are supposed to support error.stack as well\n// See also https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error/Stack\nfunction extractStacktrace( e, offset ) {\n\toffset = offset === undefined ? 3 : offset;\n\n\tvar stack, include, i, regex;\n\n\tif ( e.stacktrace ) {\n\t\t// Opera\n\t\treturn e.stacktrace.split( \"\\n\" )[ offset + 3 ];\n\t} else if ( e.stack ) {\n\t\t// Firefox, Chrome\n\t\tstack = e.stack.split( \"\\n\" );\n\t\tif (/^error$/i.test( stack[0] ) ) {\n\t\t\tstack.shift();\n\t\t}\n\t\tif ( fileName ) {\n\t\t\tinclude = [];\n\t\t\tfor ( i = offset; i < stack.length; i++ ) {\n\t\t\t\tif ( stack[ i ].indexOf( fileName ) != -1 ) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tinclude.push( stack[ i ] );\n\t\t\t}\n\t\t\tif ( include.length ) {\n\t\t\t\treturn include.join( \"\\n\" );\n\t\t\t}\n\t\t}\n\t\treturn stack[ offset ];\n\t} else if ( e.sourceURL ) {\n\t\t// Safari, PhantomJS\n\t\t// hopefully one day Safari provides actual stacktraces\n\t\t// exclude useless self-reference for generated Error objects\n\t\tif ( /qunit.js$/.test( e.sourceURL ) ) {\n\t\t\treturn;\n\t\t}\n\t\t// for actual exceptions, this is useful\n\t\treturn e.sourceURL + \":\" + e.line;\n\t}\n}\nfunction sourceFromStacktrace( offset ) {\n\ttry {\n\t\tthrow new Error();\n\t} catch ( e ) {\n\t\treturn extractStacktrace( e, offset );\n\t}\n}\n\nfunction escapeInnerText( s ) {\n\tif ( !s ) {\n\t\treturn \"\";\n\t}\n\ts = s + \"\";\n\treturn s.replace( /[\\&<>]/g, function( s ) {\n\t\tswitch( s ) {\n\t\t\tcase \"&\": return \"&amp;\";\n\t\t\tcase \"<\": return \"&lt;\";\n\t\t\tcase \">\": return \"&gt;\";\n\t\t\tdefault: return s;\n\t\t}\n\t});\n}\n\nfunction synchronize( callback, last ) {\n\tconfig.queue.push( callback );\n\n\tif ( config.autorun && !config.blocking ) {\n\t\tprocess( last );\n\t}\n}\n\nfunction process( last ) {\n\tfunction next() {\n\t\tprocess( last );\n\t}\n\tvar start = new Date().getTime();\n\tconfig.depth = config.depth ? config.depth + 1 : 1;\n\n\twhile ( config.queue.length && !config.blocking ) {\n\t\tif ( !defined.setTimeout || config.updateRate <= 0 || ( ( new Date().getTime() - start ) < config.updateRate ) ) {\n\t\t\tconfig.queue.shift()();\n\t\t} else {\n\t\t\twindow.setTimeout( next, 13 );\n\t\t\tbreak;\n\t\t}\n\t}\n\tconfig.depth--;\n\tif ( last && !config.blocking && !config.queue.length && config.depth === 0 ) {\n\t\tdone();\n\t}\n}\n\nfunction saveGlobal() {\n\tconfig.pollution = [];\n\n\tif ( config.noglobals ) {\n\t\tfor ( var key in window ) {\n\t\t\t// in Opera sometimes DOM element ids show up here, ignore them\n\t\t\tif ( !hasOwn.call( window, key ) || /^qunit-test-output/.test( key ) ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tconfig.pollution.push( key );\n\t\t}\n\t}\n}\n\nfunction checkPollution( name ) {\n\tvar newGlobals,\n\t\tdeletedGlobals,\n\t\told = config.pollution;\n\n\tsaveGlobal();\n\n\tnewGlobals = diff( config.pollution, old );\n\tif ( newGlobals.length > 0 ) {\n\t\tQUnit.pushFailure( \"Introduced global variable(s): \" + newGlobals.join(\", \") );\n\t}\n\n\tdeletedGlobals = diff( old, config.pollution );\n\tif ( deletedGlobals.length > 0 ) {\n\t\tQUnit.pushFailure( \"Deleted global variable(s): \" + deletedGlobals.join(\", \") );\n\t}\n}\n\n// returns a new Array with the elements that are in a but not in b\nfunction diff( a, b ) {\n\tvar i, j,\n\t\tresult = a.slice();\n\n\tfor ( i = 0; i < result.length; i++ ) {\n\t\tfor ( j = 0; j < b.length; j++ ) {\n\t\t\tif ( result[i] === b[j] ) {\n\t\t\t\tresult.splice( i, 1 );\n\t\t\t\ti--;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\treturn result;\n}\n\nfunction extend( a, b ) {\n\tfor ( var prop in b ) {\n\t\tif ( b[ prop ] === undefined ) {\n\t\t\tdelete a[ prop ];\n\n\t\t// Avoid \"Member not found\" error in IE8 caused by setting window.constructor\n\t\t} else if ( prop !== \"constructor\" || a !== window ) {\n\t\t\ta[ prop ] = b[ prop ];\n\t\t}\n\t}\n\n\treturn a;\n}\n\nfunction addEvent( elem, type, fn ) {\n\tif ( elem.addEventListener ) {\n\t\telem.addEventListener( type, fn, false );\n\t} else if ( elem.attachEvent ) {\n\t\telem.attachEvent( \"on\" + type, fn );\n\t} else {\n\t\tfn();\n\t}\n}\n\nfunction id( name ) {\n\treturn !!( typeof document !== \"undefined\" && document && document.getElementById ) &&\n\t\tdocument.getElementById( name );\n}\n\nfunction registerLoggingCallback( key ) {\n\treturn function( callback ) {\n\t\tconfig[key].push( callback );\n\t};\n}\n\n// Supports deprecated method of completely overwriting logging callbacks\nfunction runLoggingCallbacks( key, scope, args ) {\n\t//debugger;\n\tvar i, callbacks;\n\tif ( QUnit.hasOwnProperty( key ) ) {\n\t\tQUnit[ key ].call(scope, args );\n\t} else {\n\t\tcallbacks = config[ key ];\n\t\tfor ( i = 0; i < callbacks.length; i++ ) {\n\t\t\tcallbacks[ i ].call( scope, args );\n\t\t}\n\t}\n}\n\n// Test for equality any JavaScript type.\n// Author: Philippe Rathé <prathe@gmail.com>\nQUnit.equiv = (function() {\n\n\t// Call the o related callback with the given arguments.\n\tfunction bindCallbacks( o, callbacks, args ) {\n\t\tvar prop = QUnit.objectType( o );\n\t\tif ( prop ) {\n\t\t\tif ( QUnit.objectType( callbacks[ prop ] ) === \"function\" ) {\n\t\t\t\treturn callbacks[ prop ].apply( callbacks, args );\n\t\t\t} else {\n\t\t\t\treturn callbacks[ prop ]; // or undefined\n\t\t\t}\n\t\t}\n\t}\n\n\t// the real equiv function\n\tvar innerEquiv,\n\t\t// stack to decide between skip/abort functions\n\t\tcallers = [],\n\t\t// stack to avoiding loops from circular referencing\n\t\tparents = [],\n\n\t\tgetProto = Object.getPrototypeOf || function ( obj ) {\n\t\t\treturn obj.__proto__;\n\t\t},\n\t\tcallbacks = (function () {\n\n\t\t\t// for string, boolean, number and null\n\t\t\tfunction useStrictEquality( b, a ) {\n\t\t\t\tif ( b instanceof a.constructor || a instanceof b.constructor ) {\n\t\t\t\t\t// to catch short annotaion VS 'new' annotation of a\n\t\t\t\t\t// declaration\n\t\t\t\t\t// e.g. var i = 1;\n\t\t\t\t\t// var j = new Number(1);\n\t\t\t\t\treturn a == b;\n\t\t\t\t} else {\n\t\t\t\t\treturn a === b;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\t\"string\": useStrictEquality,\n\t\t\t\t\"boolean\": useStrictEquality,\n\t\t\t\t\"number\": useStrictEquality,\n\t\t\t\t\"null\": useStrictEquality,\n\t\t\t\t\"undefined\": useStrictEquality,\n\n\t\t\t\t\"nan\": function( b ) {\n\t\t\t\t\treturn isNaN( b );\n\t\t\t\t},\n\n\t\t\t\t\"date\": function( b, a ) {\n\t\t\t\t\treturn QUnit.objectType( b ) === \"date\" && a.valueOf() === b.valueOf();\n\t\t\t\t},\n\n\t\t\t\t\"regexp\": function( b, a ) {\n\t\t\t\t\treturn QUnit.objectType( b ) === \"regexp\" &&\n\t\t\t\t\t\t// the regex itself\n\t\t\t\t\t\ta.source === b.source &&\n\t\t\t\t\t\t// and its modifers\n\t\t\t\t\t\ta.global === b.global &&\n\t\t\t\t\t\t// (gmi) ...\n\t\t\t\t\t\ta.ignoreCase === b.ignoreCase &&\n\t\t\t\t\t\ta.multiline === b.multiline;\n\t\t\t\t},\n\n\t\t\t\t// - skip when the property is a method of an instance (OOP)\n\t\t\t\t// - abort otherwise,\n\t\t\t\t// initial === would have catch identical references anyway\n\t\t\t\t\"function\": function() {\n\t\t\t\t\tvar caller = callers[callers.length - 1];\n\t\t\t\t\treturn caller !== Object && typeof caller !== \"undefined\";\n\t\t\t\t},\n\n\t\t\t\t\"array\": function( b, a ) {\n\t\t\t\t\tvar i, j, len, loop;\n\n\t\t\t\t\t// b could be an object literal here\n\t\t\t\t\tif ( QUnit.objectType( b ) !== \"array\" ) {\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\n\t\t\t\t\tlen = a.length;\n\t\t\t\t\tif ( len !== b.length ) {\n\t\t\t\t\t\t// safe and faster\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\n\t\t\t\t\t// track reference to avoid circular references\n\t\t\t\t\tparents.push( a );\n\t\t\t\t\tfor ( i = 0; i < len; i++ ) {\n\t\t\t\t\t\tloop = false;\n\t\t\t\t\t\tfor ( j = 0; j < parents.length; j++ ) {\n\t\t\t\t\t\t\tif ( parents[j] === a[i] ) {\n\t\t\t\t\t\t\t\tloop = true;// dont rewalk array\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif ( !loop && !innerEquiv(a[i], b[i]) ) {\n\t\t\t\t\t\t\tparents.pop();\n\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tparents.pop();\n\t\t\t\t\treturn true;\n\t\t\t\t},\n\n\t\t\t\t\"object\": function( b, a ) {\n\t\t\t\t\tvar i, j, loop,\n\t\t\t\t\t\t// Default to true\n\t\t\t\t\t\teq = true,\n\t\t\t\t\t\taProperties = [],\n\t\t\t\t\t\tbProperties = [];\n\n\t\t\t\t\t// comparing constructors is more strict than using\n\t\t\t\t\t// instanceof\n\t\t\t\t\tif ( a.constructor !== b.constructor ) {\n\t\t\t\t\t\t// Allow objects with no prototype to be equivalent to\n\t\t\t\t\t\t// objects with Object as their constructor.\n\t\t\t\t\t\tif ( !(( getProto(a) === null && getProto(b) === Object.prototype ) ||\n\t\t\t\t\t\t\t( getProto(b) === null && getProto(a) === Object.prototype ) ) ) {\n\t\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// stack constructor before traversing properties\n\t\t\t\t\tcallers.push( a.constructor );\n\t\t\t\t\t// track reference to avoid circular references\n\t\t\t\t\tparents.push( a );\n\n\t\t\t\t\tfor ( i in a ) { // be strict: don't ensures hasOwnProperty\n\t\t\t\t\t\t\t\t\t// and go deep\n\t\t\t\t\t\tloop = false;\n\t\t\t\t\t\tfor ( j = 0; j < parents.length; j++ ) {\n\t\t\t\t\t\t\tif ( parents[j] === a[i] ) {\n\t\t\t\t\t\t\t\t// don't go down the same path twice\n\t\t\t\t\t\t\t\tloop = true;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\taProperties.push(i); // collect a's properties\n\n\t\t\t\t\t\tif (!loop && !innerEquiv( a[i], b[i] ) ) {\n\t\t\t\t\t\t\teq = false;\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\tcallers.pop(); // unstack, we are done\n\t\t\t\t\tparents.pop();\n\n\t\t\t\t\tfor ( i in b ) {\n\t\t\t\t\t\tbProperties.push( i ); // collect b's properties\n\t\t\t\t\t}\n\n\t\t\t\t\t// Ensures identical properties name\n\t\t\t\t\treturn eq && innerEquiv( aProperties.sort(), bProperties.sort() );\n\t\t\t\t}\n\t\t\t};\n\t\t}());\n\n\tinnerEquiv = function() { // can take multiple arguments\n\t\tvar args = [].slice.apply( arguments );\n\t\tif ( args.length < 2 ) {\n\t\t\treturn true; // end transition\n\t\t}\n\n\t\treturn (function( a, b ) {\n\t\t\tif ( a === b ) {\n\t\t\t\treturn true; // catch the most you can\n\t\t\t} else if ( a === null || b === null || typeof a === \"undefined\" ||\n\t\t\t\t\ttypeof b === \"undefined\" ||\n\t\t\t\t\tQUnit.objectType(a) !== QUnit.objectType(b) ) {\n\t\t\t\treturn false; // don't lose time with error prone cases\n\t\t\t} else {\n\t\t\t\treturn bindCallbacks(a, callbacks, [ b, a ]);\n\t\t\t}\n\n\t\t\t// apply transition with (1..n) arguments\n\t\t}( args[0], args[1] ) && arguments.callee.apply( this, args.splice(1, args.length - 1 )) );\n\t};\n\n\treturn innerEquiv;\n}());\n\n/**\n * jsDump Copyright (c) 2008 Ariel Flesler - aflesler(at)gmail(dot)com |\n * http://flesler.blogspot.com Licensed under BSD\n * (http://www.opensource.org/licenses/bsd-license.php) Date: 5/15/2008\n *\n * @projectDescription Advanced and extensible data dumping for Javascript.\n * @version 1.0.0\n * @author Ariel Flesler\n * @link {http://flesler.blogspot.com/2008/05/jsdump-pretty-dump-of-any-javascript.html}\n */\nQUnit.jsDump = (function() {\n\tfunction quote( str ) {\n\t\treturn '\"' + str.toString().replace( /\"/g, '\\\\\"' ) + '\"';\n\t}\n\tfunction literal( o ) {\n\t\treturn o + \"\";\n\t}\n\tfunction join( pre, arr, post ) {\n\t\tvar s = jsDump.separator(),\n\t\t\tbase = jsDump.indent(),\n\t\t\tinner = jsDump.indent(1);\n\t\tif ( arr.join ) {\n\t\t\tarr = arr.join( \",\" + s + inner );\n\t\t}\n\t\tif ( !arr ) {\n\t\t\treturn pre + post;\n\t\t}\n\t\treturn [ pre, inner + arr, base + post ].join(s);\n\t}\n\tfunction array( arr, stack ) {\n\t\tvar i = arr.length, ret = new Array(i);\n\t\tthis.up();\n\t\twhile ( i-- ) {\n\t\t\tret[i] = this.parse( arr[i] , undefined , stack);\n\t\t}\n\t\tthis.down();\n\t\treturn join( \"[\", ret, \"]\" );\n\t}\n\n\tvar reName = /^function (\\w+)/,\n\t\tjsDump = {\n\t\t\tparse: function( obj, type, stack ) { //type is used mostly internally, you can fix a (custom)type in advance\n\t\t\t\tstack = stack || [ ];\n\t\t\t\tvar inStack, res,\n\t\t\t\t\tparser = this.parsers[ type || this.typeOf(obj) ];\n\n\t\t\t\ttype = typeof parser;\n\t\t\t\tinStack = inArray( obj, stack );\n\n\t\t\t\tif ( inStack != -1 ) {\n\t\t\t\t\treturn \"recursion(\" + (inStack - stack.length) + \")\";\n\t\t\t\t}\n\t\t\t\t//else\n\t\t\t\tif ( type == \"function\" )  {\n\t\t\t\t\tstack.push( obj );\n\t\t\t\t\tres = parser.call( this, obj, stack );\n\t\t\t\t\tstack.pop();\n\t\t\t\t\treturn res;\n\t\t\t\t}\n\t\t\t\t// else\n\t\t\t\treturn ( type == \"string\" ) ? parser : this.parsers.error;\n\t\t\t},\n\t\t\ttypeOf: function( obj ) {\n\t\t\t\tvar type;\n\t\t\t\tif ( obj === null ) {\n\t\t\t\t\ttype = \"null\";\n\t\t\t\t} else if ( typeof obj === \"undefined\" ) {\n\t\t\t\t\ttype = \"undefined\";\n\t\t\t\t} else if ( QUnit.is( \"regexp\", obj) ) {\n\t\t\t\t\ttype = \"regexp\";\n\t\t\t\t} else if ( QUnit.is( \"date\", obj) ) {\n\t\t\t\t\ttype = \"date\";\n\t\t\t\t} else if ( QUnit.is( \"function\", obj) ) {\n\t\t\t\t\ttype = \"function\";\n\t\t\t\t} else if ( typeof obj.setInterval !== undefined && typeof obj.document !== \"undefined\" && typeof obj.nodeType === \"undefined\" ) {\n\t\t\t\t\ttype = \"window\";\n\t\t\t\t} else if ( obj.nodeType === 9 ) {\n\t\t\t\t\ttype = \"document\";\n\t\t\t\t} else if ( obj.nodeType ) {\n\t\t\t\t\ttype = \"node\";\n\t\t\t\t} else if (\n\t\t\t\t\t// native arrays\n\t\t\t\t\ttoString.call( obj ) === \"[object Array]\" ||\n\t\t\t\t\t// NodeList objects\n\t\t\t\t\t( typeof obj.length === \"number\" && typeof obj.item !== \"undefined\" && ( obj.length ? obj.item(0) === obj[0] : ( obj.item( 0 ) === null && typeof obj[0] === \"undefined\" ) ) )\n\t\t\t\t) {\n\t\t\t\t\ttype = \"array\";\n\t\t\t\t} else {\n\t\t\t\t\ttype = typeof obj;\n\t\t\t\t}\n\t\t\t\treturn type;\n\t\t\t},\n\t\t\tseparator: function() {\n\t\t\t\treturn this.multiline ?\tthis.HTML ? \"<br />\" : \"\\n\" : this.HTML ? \"&nbsp;\" : \" \";\n\t\t\t},\n\t\t\tindent: function( extra ) {// extra can be a number, shortcut for increasing-calling-decreasing\n\t\t\t\tif ( !this.multiline ) {\n\t\t\t\t\treturn \"\";\n\t\t\t\t}\n\t\t\t\tvar chr = this.indentChar;\n\t\t\t\tif ( this.HTML ) {\n\t\t\t\t\tchr = chr.replace( /\\t/g, \"   \" ).replace( / /g, \"&nbsp;\" );\n\t\t\t\t}\n\t\t\t\treturn new Array( this._depth_ + (extra||0) ).join(chr);\n\t\t\t},\n\t\t\tup: function( a ) {\n\t\t\t\tthis._depth_ += a || 1;\n\t\t\t},\n\t\t\tdown: function( a ) {\n\t\t\t\tthis._depth_ -= a || 1;\n\t\t\t},\n\t\t\tsetParser: function( name, parser ) {\n\t\t\t\tthis.parsers[name] = parser;\n\t\t\t},\n\t\t\t// The next 3 are exposed so you can use them\n\t\t\tquote: quote,\n\t\t\tliteral: literal,\n\t\t\tjoin: join,\n\t\t\t//\n\t\t\t_depth_: 1,\n\t\t\t// This is the list of parsers, to modify them, use jsDump.setParser\n\t\t\tparsers: {\n\t\t\t\twindow: \"[Window]\",\n\t\t\t\tdocument: \"[Document]\",\n\t\t\t\terror: \"[ERROR]\", //when no parser is found, shouldn\"t happen\n\t\t\t\tunknown: \"[Unknown]\",\n\t\t\t\t\"null\": \"null\",\n\t\t\t\t\"undefined\": \"undefined\",\n\t\t\t\t\"function\": function( fn ) {\n\t\t\t\t\tvar ret = \"function\",\n\t\t\t\t\t\tname = \"name\" in fn ? fn.name : (reName.exec(fn) || [])[1];//functions never have name in IE\n\n\t\t\t\t\tif ( name ) {\n\t\t\t\t\t\tret += \" \" + name;\n\t\t\t\t\t}\n\t\t\t\t\tret += \"( \";\n\n\t\t\t\t\tret = [ ret, QUnit.jsDump.parse( fn, \"functionArgs\" ), \"){\" ].join( \"\" );\n\t\t\t\t\treturn join( ret, QUnit.jsDump.parse(fn,\"functionCode\" ), \"}\" );\n\t\t\t\t},\n\t\t\t\tarray: array,\n\t\t\t\tnodelist: array,\n\t\t\t\t\"arguments\": array,\n\t\t\t\tobject: function( map, stack ) {\n\t\t\t\t\tvar ret = [ ], keys, key, val, i;\n\t\t\t\t\tQUnit.jsDump.up();\n\t\t\t\t\tif ( Object.keys ) {\n\t\t\t\t\t\tkeys = Object.keys( map );\n\t\t\t\t\t} else {\n\t\t\t\t\t\tkeys = [];\n\t\t\t\t\t\tfor ( key in map ) {\n\t\t\t\t\t\t\tkeys.push( key );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tkeys.sort();\n\t\t\t\t\tfor ( i = 0; i < keys.length; i++ ) {\n\t\t\t\t\t\tkey = keys[ i ];\n\t\t\t\t\t\tval = map[ key ];\n\t\t\t\t\t\tret.push( QUnit.jsDump.parse( key, \"key\" ) + \": \" + QUnit.jsDump.parse( val, undefined, stack ) );\n\t\t\t\t\t}\n\t\t\t\t\tQUnit.jsDump.down();\n\t\t\t\t\treturn join( \"{\", ret, \"}\" );\n\t\t\t\t},\n\t\t\t\tnode: function( node ) {\n\t\t\t\t\tvar a, val,\n\t\t\t\t\t\topen = QUnit.jsDump.HTML ? \"&lt;\" : \"<\",\n\t\t\t\t\t\tclose = QUnit.jsDump.HTML ? \"&gt;\" : \">\",\n\t\t\t\t\t\ttag = node.nodeName.toLowerCase(),\n\t\t\t\t\t\tret = open + tag;\n\n\t\t\t\t\tfor ( a in QUnit.jsDump.DOMAttrs ) {\n\t\t\t\t\t\tval = node[ QUnit.jsDump.DOMAttrs[a] ];\n\t\t\t\t\t\tif ( val ) {\n\t\t\t\t\t\t\tret += \" \" + a + \"=\" + QUnit.jsDump.parse( val, \"attribute\" );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\treturn ret + close + open + \"/\" + tag + close;\n\t\t\t\t},\n\t\t\t\tfunctionArgs: function( fn ) {//function calls it internally, it's the arguments part of the function\n\t\t\t\t\tvar args,\n\t\t\t\t\t\tl = fn.length;\n\n\t\t\t\t\tif ( !l ) {\n\t\t\t\t\t\treturn \"\";\n\t\t\t\t\t}\n\n\t\t\t\t\targs = new Array(l);\n\t\t\t\t\twhile ( l-- ) {\n\t\t\t\t\t\targs[l] = String.fromCharCode(97+l);//97 is 'a'\n\t\t\t\t\t}\n\t\t\t\t\treturn \" \" + args.join( \", \" ) + \" \";\n\t\t\t\t},\n\t\t\t\tkey: quote, //object calls it internally, the key part of an item in a map\n\t\t\t\tfunctionCode: \"[code]\", //function calls it internally, it's the content of the function\n\t\t\t\tattribute: quote, //node calls it internally, it's an html attribute value\n\t\t\t\tstring: quote,\n\t\t\t\tdate: quote,\n\t\t\t\tregexp: literal, //regex\n\t\t\t\tnumber: literal,\n\t\t\t\t\"boolean\": literal\n\t\t\t},\n\t\t\tDOMAttrs: {\n\t\t\t\t//attributes to dump from nodes, name=>realName\n\t\t\t\tid: \"id\",\n\t\t\t\tname: \"name\",\n\t\t\t\t\"class\": \"className\"\n\t\t\t},\n\t\t\tHTML: false,//if true, entities are escaped ( <, >, \\t, space and \\n )\n\t\t\tindentChar: \"  \",//indentation unit\n\t\t\tmultiline: true //if true, items in a collection, are separated by a \\n, else just a space.\n\t\t};\n\n\treturn jsDump;\n}());\n\n// from Sizzle.js\nfunction getText( elems ) {\n\tvar i, elem,\n\t\tret = \"\";\n\n\tfor ( 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 += getText( elem.childNodes );\n\t\t}\n\t}\n\n\treturn ret;\n}\n\n// from jquery.js\nfunction inArray( elem, array ) {\n\tif ( array.indexOf ) {\n\t\treturn array.indexOf( elem );\n\t}\n\n\tfor ( var i = 0, length = array.length; i < length; i++ ) {\n\t\tif ( array[ i ] === elem ) {\n\t\t\treturn i;\n\t\t}\n\t}\n\n\treturn -1;\n}\n\n/*\n * Javascript Diff Algorithm\n *  By John Resig (http://ejohn.org/)\n *  Modified by Chu Alan \"sprite\"\n *\n * Released under the MIT license.\n *\n * More Info:\n *  http://ejohn.org/projects/javascript-diff-algorithm/\n *\n * Usage: QUnit.diff(expected, actual)\n *\n * QUnit.diff( \"the quick brown fox jumped over\", \"the quick fox jumps over\" ) == \"the  quick <del>brown </del> fox <del>jumped </del><ins>jumps </ins> over\"\n */\nQUnit.diff = (function() {\n\tfunction diff( o, n ) {\n\t\tvar i,\n\t\t\tns = {},\n\t\t\tos = {};\n\n\t\tfor ( i = 0; i < n.length; i++ ) {\n\t\t\tif ( ns[ n[i] ] == null ) {\n\t\t\t\tns[ n[i] ] = {\n\t\t\t\t\trows: [],\n\t\t\t\t\to: null\n\t\t\t\t};\n\t\t\t}\n\t\t\tns[ n[i] ].rows.push( i );\n\t\t}\n\n\t\tfor ( i = 0; i < o.length; i++ ) {\n\t\t\tif ( os[ o[i] ] == null ) {\n\t\t\t\tos[ o[i] ] = {\n\t\t\t\t\trows: [],\n\t\t\t\t\tn: null\n\t\t\t\t};\n\t\t\t}\n\t\t\tos[ o[i] ].rows.push( i );\n\t\t}\n\n\t\tfor ( i in ns ) {\n\t\t\tif ( !hasOwn.call( ns, i ) ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif ( ns[i].rows.length == 1 && typeof os[i] != \"undefined\" && os[i].rows.length == 1 ) {\n\t\t\t\tn[ ns[i].rows[0] ] = {\n\t\t\t\t\ttext: n[ ns[i].rows[0] ],\n\t\t\t\t\trow: os[i].rows[0]\n\t\t\t\t};\n\t\t\t\to[ os[i].rows[0] ] = {\n\t\t\t\t\ttext: o[ os[i].rows[0] ],\n\t\t\t\t\trow: ns[i].rows[0]\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\n\t\tfor ( i = 0; i < n.length - 1; i++ ) {\n\t\t\tif ( n[i].text != null && n[ i + 1 ].text == null && n[i].row + 1 < o.length && o[ n[i].row + 1 ].text == null &&\n\t\t\t\t\t\tn[ i + 1 ] == o[ n[i].row + 1 ] ) {\n\n\t\t\t\tn[ i + 1 ] = {\n\t\t\t\t\ttext: n[ i + 1 ],\n\t\t\t\t\trow: n[i].row + 1\n\t\t\t\t};\n\t\t\t\to[ n[i].row + 1 ] = {\n\t\t\t\t\ttext: o[ n[i].row + 1 ],\n\t\t\t\t\trow: i + 1\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\n\t\tfor ( i = n.length - 1; i > 0; i-- ) {\n\t\t\tif ( n[i].text != null && n[ i - 1 ].text == null && n[i].row > 0 && o[ n[i].row - 1 ].text == null &&\n\t\t\t\t\t\tn[ i - 1 ] == o[ n[i].row - 1 ]) {\n\n\t\t\t\tn[ i - 1 ] = {\n\t\t\t\t\ttext: n[ i - 1 ],\n\t\t\t\t\trow: n[i].row - 1\n\t\t\t\t};\n\t\t\t\to[ n[i].row - 1 ] = {\n\t\t\t\t\ttext: o[ n[i].row - 1 ],\n\t\t\t\t\trow: i - 1\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\n\t\treturn {\n\t\t\to: o,\n\t\t\tn: n\n\t\t};\n\t}\n\n\treturn function( o, n ) {\n\t\to = o.replace( /\\s+$/, \"\" );\n\t\tn = n.replace( /\\s+$/, \"\" );\n\n\t\tvar i, pre,\n\t\t\tstr = \"\",\n\t\t\tout = diff( o === \"\" ? [] : o.split(/\\s+/), n === \"\" ? [] : n.split(/\\s+/) ),\n\t\t\toSpace = o.match(/\\s+/g),\n\t\t\tnSpace = n.match(/\\s+/g);\n\n\t\tif ( oSpace == null ) {\n\t\t\toSpace = [ \" \" ];\n\t\t}\n\t\telse {\n\t\t\toSpace.push( \" \" );\n\t\t}\n\n\t\tif ( nSpace == null ) {\n\t\t\tnSpace = [ \" \" ];\n\t\t}\n\t\telse {\n\t\t\tnSpace.push( \" \" );\n\t\t}\n\n\t\tif ( out.n.length === 0 ) {\n\t\t\tfor ( i = 0; i < out.o.length; i++ ) {\n\t\t\t\tstr += \"<del>\" + out.o[i] + oSpace[i] + \"</del>\";\n\t\t\t}\n\t\t}\n\t\telse {\n\t\t\tif ( out.n[0].text == null ) {\n\t\t\t\tfor ( n = 0; n < out.o.length && out.o[n].text == null; n++ ) {\n\t\t\t\t\tstr += \"<del>\" + out.o[n] + oSpace[n] + \"</del>\";\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfor ( i = 0; i < out.n.length; i++ ) {\n\t\t\t\tif (out.n[i].text == null) {\n\t\t\t\t\tstr += \"<ins>\" + out.n[i] + nSpace[i] + \"</ins>\";\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\t// `pre` initialized at top of scope\n\t\t\t\t\tpre = \"\";\n\n\t\t\t\t\tfor ( n = out.n[i].row + 1; n < out.o.length && out.o[n].text == null; n++ ) {\n\t\t\t\t\t\tpre += \"<del>\" + out.o[n] + oSpace[n] + \"</del>\";\n\t\t\t\t\t}\n\t\t\t\t\tstr += \" \" + out.n[i].text + nSpace[i] + pre;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn str;\n\t};\n}());\n\n// for CommonJS enviroments, export everything\nif ( typeof exports !== \"undefined\" ) {\n\textend(exports, QUnit);\n}\n\n// get at whatever the global object is, like window in browsers\n}( (function() {return this;}.call()) ));\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/modernizr/test/qunit/run-qunit.js",
    "content": "/**\n* Wait until the test condition is true or a timeout occurs. Useful for waiting\n* on a server response or for a ui change (fadeIn, etc.) to occur.\n*\n* @param testFx javascript condition that evaluates to a boolean,\n* it can be passed in as a string (e.g.: \"1 == 1\" or \"$('#bar').is(':visible')\" or\n* as a callback function.\n* @param onReady what to do when testFx condition is fulfilled,\n* it can be passed in as a string (e.g.: \"1 == 1\" or \"$('#bar').is(':visible')\" or\n* as a callback function.\n* @param timeOutMillis the max amount of time to wait. If not specified, 3 sec is used.\n*/\nfunction waitFor(testFx, onReady, timeOutMillis) {\n    var maxtimeOutMillis = timeOutMillis ? timeOutMillis : 3001, //< Default Max Timout is 3s\n        start = new Date().getTime(),\n        condition = false,\n        interval = setInterval(function() {\n            if ( (new Date().getTime() - start < maxtimeOutMillis) && !condition ) {\n                // If not time-out yet and condition not yet fulfilled\n                condition = (typeof(testFx) === \"string\" ? eval(testFx) : testFx()); //< defensive code\n            } else {\n                if(!condition) {\n                    // If condition still not fulfilled (timeout but condition is 'false')\n                    console.log(\"'waitFor()' timeout\");\n                    phantom.exit(1);\n                } else {\n                    // Condition fulfilled (timeout and/or condition is 'true')\n                    typeof(onReady) === \"string\" ? eval(onReady) : onReady(); //< Do what it's supposed to do once the condition is fulfilled\n                    clearInterval(interval); //< Stop this interval\n                }\n            }\n        }, 100); //< repeat check every 250ms\n};\n\n\nif (phantom.args.length === 0 || phantom.args.length > 2) {\n    console.log('Usage: run-qunit.js URL');\n    phantom.exit();\n}\n\nvar page = new WebPage();\n\n// Route \"console.log()\" calls from within the Page context to the main Phantom context (i.e. current \"this\")\npage.onConsoleMessage = function(msg) {\n    console.log(msg);\n};\n\npage.open(phantom.args[0], function(status){\n    if (status !== \"success\") {\n        console.log(\"Unable to access network\");\n        phantom.exit();\n    } else {\n        waitFor(function(){\n            return page.evaluate(function(){\n                var el = document.getElementById('qunit-testresult');\n                if (el && el.innerText.match('completed')) {\n                    return true;\n                }\n                return false;\n            });\n        }, function(){\n            var failedNum = page.evaluate(function(){\n                var el = document.getElementById('qunit-testresult');\n                try {\n                    return el.getElementsByClassName('failed')[0].innerHTML;\n                } catch (e) { }\n                return 10000;\n            });\n            phantom.exit((parseInt(failedNum, 10) > 0) ? 1 : 0);\n        });\n    }\n});"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/ng-file-upload/.bower.json",
    "content": "{\n  \"name\": \"angular-file-upload\",\n  \"main\": \"angular-file-upload.js\",\n  \"version\": \"3.0.2\",\n  \"homepage\": \"https://github.com/danialfarid/angular-file-upload\",\n  \"authors\": [\n    \"danialf <danial.farid@gmail.com>\"\n  ],\n  \"description\": \"Lightweight Angular JS directive to upload files. Support drag&drop, progress and abort\",\n  \"license\": \"MIT\",\n  \"_release\": \"3.0.2\",\n  \"_resolution\": {\n    \"type\": \"version\",\n    \"tag\": \"3.0.2\",\n    \"commit\": \"a189b55583ae91c955adf037ccecb90cc2f24797\"\n  },\n  \"_source\": \"https://github.com/danialfarid/angular-file-upload-bower.git\",\n  \"_target\": \"3.0.2\",\n  \"_originalSource\": \"ng-file-upload\"\n}"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/ng-file-upload/FileAPI.js",
    "content": "/*! FileAPI 2.0.7 - BSD | git://github.com/mailru/FileAPI.git\n * FileAPI — a set of  javascript tools for working with files. Multiupload, drag'n'drop and chunked file upload. Images: crop, resize and auto orientation by EXIF.\n */\n\n/*\n * JavaScript Canvas to Blob 2.0.5\n * https://github.com/blueimp/JavaScript-Canvas-to-Blob\n *\n * Copyright 2012, Sebastian Tschan\n * https://blueimp.net\n *\n * Licensed under the MIT license:\n * http://www.opensource.org/licenses/MIT\n *\n * Based on stackoverflow user Stoive's code snippet:\n * http://stackoverflow.com/q/4998908\n */\n\n/*jslint nomen: true, regexp: true */\n/*global window, atob, Blob, ArrayBuffer, Uint8Array */\n\n(function (window) {\n    'use strict';\n    var CanvasPrototype = window.HTMLCanvasElement &&\n            window.HTMLCanvasElement.prototype,\n        hasBlobConstructor = window.Blob && (function () {\n            try {\n                return Boolean(new Blob());\n            } catch (e) {\n                return false;\n            }\n        }()),\n        hasArrayBufferViewSupport = hasBlobConstructor && window.Uint8Array &&\n            (function () {\n                try {\n                    return new Blob([new Uint8Array(100)]).size === 100;\n                } catch (e) {\n                    return false;\n                }\n            }()),\n        BlobBuilder = window.BlobBuilder || window.WebKitBlobBuilder ||\n            window.MozBlobBuilder || window.MSBlobBuilder,\n        dataURLtoBlob = (hasBlobConstructor || BlobBuilder) && window.atob &&\n            window.ArrayBuffer && window.Uint8Array && function (dataURI) {\n                var byteString,\n                    arrayBuffer,\n                    intArray,\n                    i,\n                    mimeString,\n                    bb;\n                if (dataURI.split(',')[0].indexOf('base64') >= 0) {\n                    // Convert base64 to raw binary data held in a string:\n                    byteString = atob(dataURI.split(',')[1]);\n                } else {\n                    // Convert base64/URLEncoded data component to raw binary data:\n                    byteString = decodeURIComponent(dataURI.split(',')[1]);\n                }\n                // Write the bytes of the string to an ArrayBuffer:\n                arrayBuffer = new ArrayBuffer(byteString.length);\n                intArray = new Uint8Array(arrayBuffer);\n                for (i = 0; i < byteString.length; i += 1) {\n                    intArray[i] = byteString.charCodeAt(i);\n                }\n                // Separate out the mime component:\n                mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0];\n                // Write the ArrayBuffer (or ArrayBufferView) to a blob:\n                if (hasBlobConstructor) {\n                    return new Blob(\n                        [hasArrayBufferViewSupport ? intArray : arrayBuffer],\n                        {type: mimeString}\n                    );\n                }\n                bb = new BlobBuilder();\n                bb.append(arrayBuffer);\n                return bb.getBlob(mimeString);\n            };\n    if (window.HTMLCanvasElement && !CanvasPrototype.toBlob) {\n        if (CanvasPrototype.mozGetAsFile) {\n            CanvasPrototype.toBlob = function (callback, type, quality) {\n                if (quality && CanvasPrototype.toDataURL && dataURLtoBlob) {\n                    callback(dataURLtoBlob(this.toDataURL(type, quality)));\n                } else {\n                    callback(this.mozGetAsFile('blob', type));\n                }\n            };\n        } else if (CanvasPrototype.toDataURL && dataURLtoBlob) {\n            CanvasPrototype.toBlob = function (callback, type, quality) {\n                callback(dataURLtoBlob(this.toDataURL(type, quality)));\n            };\n        }\n    }\n    window.dataURLtoBlob = dataURLtoBlob;\n})(window);\n\n/*jslint evil: true */\n/*global window, URL, webkitURL, ActiveXObject */\n\n(function (window, undef){\n\t'use strict';\n\n\tvar\n\t\tgid = 1,\n\t\tnoop = function (){},\n\n\t\tdocument = window.document,\n\t\tdoctype = document.doctype || {},\n\t\tuserAgent = window.navigator.userAgent,\n\n\t\t// https://github.com/blueimp/JavaScript-Load-Image/blob/master/load-image.js#L48\n\t\tapiURL = (window.createObjectURL && window) || (window.URL && URL.revokeObjectURL && URL) || (window.webkitURL && webkitURL),\n\n\t\tBlob = window.Blob,\n\t\tFile = window.File,\n\t\tFileReader = window.FileReader,\n\t\tFormData = window.FormData,\n\n\n\t\tXMLHttpRequest = window.XMLHttpRequest,\n\t\tjQuery = window.jQuery,\n\n\t\thtml5 =    !!(File && (FileReader && (window.Uint8Array || FormData || XMLHttpRequest.prototype.sendAsBinary)))\n\t\t\t\t&& !(/safari\\//i.test(userAgent) && !/chrome\\//i.test(userAgent) && /windows/i.test(userAgent)), // BugFix: https://github.com/mailru/FileAPI/issues/25\n\n\t\tcors = html5 && ('withCredentials' in (new XMLHttpRequest)),\n\n\t\tchunked = html5 && !!Blob && !!(Blob.prototype.webkitSlice || Blob.prototype.mozSlice || Blob.prototype.slice),\n\n\t\t// https://github.com/blueimp/JavaScript-Canvas-to-Blob\n\t\tdataURLtoBlob = window.dataURLtoBlob,\n\n\n\t\t_rimg = /img/i,\n\t\t_rcanvas = /canvas/i,\n\t\t_rimgcanvas = /img|canvas/i,\n\t\t_rinput = /input/i,\n\t\t_rdata = /^data:[^,]+,/,\n\n\t\t_toString = {}.toString,\n\n\n\t\tMath = window.Math,\n\n\t\t_SIZE_CONST = function (pow){\n\t\t\tpow = new window.Number(Math.pow(1024, pow));\n\t\t\tpow.from = function (sz){ return Math.round(sz * this); };\n\t\t\treturn\tpow;\n\t\t},\n\n\t\t_elEvents = {}, // element event listeners\n\t\t_infoReader = [], // list of file info processors\n\n\t\t_readerEvents = 'abort progress error load loadend',\n\t\t_xhrPropsExport = 'status statusText readyState response responseXML responseText responseBody'.split(' '),\n\n\t\tcurrentTarget = 'currentTarget', // for minimize\n\t\tpreventDefault = 'preventDefault', // and this too\n\n\t\t_isArray = function (ar) {\n\t\t\treturn\tar && ('length' in ar);\n\t\t},\n\n\t\t/**\n\t\t * Iterate over a object or array\n\t\t */\n\t\t_each = function (obj, fn, ctx){\n\t\t\tif( obj ){\n\t\t\t\tif( _isArray(obj) ){\n\t\t\t\t\tfor( var i = 0, n = obj.length; i < n; i++ ){\n\t\t\t\t\t\tif( i in obj ){\n\t\t\t\t\t\t\tfn.call(ctx, obj[i], i, obj);\n\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\tfor( var key in obj ){\n\t\t\t\t\t\tif( obj.hasOwnProperty(key) ){\n\t\t\t\t\t\t\tfn.call(ctx, obj[key], key, obj);\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/**\n\t\t * Merge the contents of two or more objects together into the first object\n\t\t */\n\t\t_extend = function (dst){\n\t\t\tvar args = arguments, i = 1, _ext = function (val, key){ dst[key] = val; };\n\t\t\tfor( ; i < args.length; i++ ){\n\t\t\t\t_each(args[i], _ext);\n\t\t\t}\n\t\t\treturn  dst;\n\t\t},\n\n\t\t/**\n\t\t * Add event listener\n\t\t */\n\t\t_on = function (el, type, fn){\n\t\t\tif( el ){\n\t\t\t\tvar uid = api.uid(el);\n\n\t\t\t\tif( !_elEvents[uid] ){\n\t\t\t\t\t_elEvents[uid] = {};\n\t\t\t\t}\n\n\t\t\t\tvar isFileReader = (FileReader && el) && (el instanceof FileReader);\n\t\t\t\t_each(type.split(/\\s+/), function (type){\n\t\t\t\t\tif( jQuery && !isFileReader){\n\t\t\t\t\t\tjQuery.event.add(el, type, fn);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif( !_elEvents[uid][type] ){\n\t\t\t\t\t\t\t_elEvents[uid][type] = [];\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t_elEvents[uid][type].push(fn);\n\n\t\t\t\t\t\tif( el.addEventListener ){ el.addEventListener(type, fn, false); }\n\t\t\t\t\t\telse if( el.attachEvent ){ el.attachEvent('on'+type, fn); }\n\t\t\t\t\t\telse { el['on'+type] = fn; }\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t},\n\n\n\t\t/**\n\t\t * Remove event listener\n\t\t */\n\t\t_off = function (el, type, fn){\n\t\t\tif( el ){\n\t\t\t\tvar uid = api.uid(el), events = _elEvents[uid] || {};\n\n\t\t\t\tvar isFileReader = (FileReader && el) && (el instanceof FileReader);\n\t\t\t\t_each(type.split(/\\s+/), function (type){\n\t\t\t\t\tif( jQuery && !isFileReader){\n\t\t\t\t\t\tjQuery.event.remove(el, type, fn);\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\tvar fns = events[type] || [], i = fns.length;\n\n\t\t\t\t\t\twhile( i-- ){\n\t\t\t\t\t\t\tif( fns[i] === fn ){\n\t\t\t\t\t\t\t\tfns.splice(i, 1);\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\n\t\t\t\t\t\tif( el.addEventListener ){ el.removeEventListener(type, fn, false); }\n\t\t\t\t\t\telse if( el.detachEvent ){ el.detachEvent('on'+type, fn); }\n\t\t\t\t\t\telse { el['on'+type] = null; }\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t},\n\n\n\t\t_one = function(el, type, fn){\n\t\t\t_on(el, type, function _(evt){\n\t\t\t\t_off(el, type, _);\n\t\t\t\tfn(evt);\n\t\t\t});\n\t\t},\n\n\n\t\t_fixEvent = function (evt){\n\t\t\tif( !evt.target ){ evt.target = window.event && window.event.srcElement || document; }\n\t\t\tif( evt.target.nodeType === 3 ){ evt.target = evt.target.parentNode; }\n\t\t\treturn  evt;\n\t\t},\n\n\n\t\t_supportInputAttr = function (attr){\n\t\t\tvar input = document.createElement('input');\n\t\t\tinput.setAttribute('type', \"file\");\n\t\t\treturn attr in input;\n\t\t},\n\n\t\t/**\n\t\t * FileAPI (core object)\n\t\t */\n\t\tapi = {\n\t\t\tversion: '2.0.7',\n\n\t\t\tcors: false,\n\t\t\thtml5: true,\n\t\t\tmedia: false,\n\t\t\tformData: true,\n\t\t\tmultiPassResize: true,\n\n\t\t\tdebug: false,\n\t\t\tpingUrl: false,\n\t\t\tmultiFlash: false,\n\t\t\tflashAbortTimeout: 0,\n\t\t\twithCredentials: true,\n\n\t\t\tstaticPath: './dist/',\n\n\t\t\tflashUrl: 0, // @default: './FileAPI.flash.swf'\n\t\t\tflashImageUrl: 0, // @default: './FileAPI.flash.image.swf'\n\n\t\t\tpostNameConcat: function (name, idx){\n\t\t\t\treturn\tname + (idx != null ? '['+ idx +']' : '');\n\t\t\t},\n\n\t\t\text2mime: {\n\t\t\t\t  jpg:\t'image/jpeg'\n\t\t\t\t, tif:\t'image/tiff'\n\t\t\t\t, txt:\t'text/plain'\n\t\t\t},\n\n\t\t\t// Fallback for flash\n\t\t\taccept: {\n\t\t\t\t  'image/*': 'art bm bmp dwg dxf cbr cbz fif fpx gif ico iefs jfif jpe jpeg jpg jps jut mcf nap nif pbm pcx pgm pict pm png pnm qif qtif ras rast rf rp svf tga tif tiff xbm xbm xpm xwd'\n\t\t\t\t, 'audio/*': 'm4a flac aac rm mpa wav wma ogg mp3 mp2 m3u mod amf dmf dsm far gdm imf it m15 med okt s3m stm sfx ult uni xm sid ac3 dts cue aif aiff wpl ape mac mpc mpp shn wv nsf spc gym adplug adx dsp adp ymf ast afc hps xs'\n\t\t\t\t, 'video/*': 'm4v 3gp nsv ts ty strm rm rmvb m3u ifo mov qt divx xvid bivx vob nrg img iso pva wmv asf asx ogm m2v avi bin dat dvr-ms mpg mpeg mp4 mkv avc vp3 svq3 nuv viv dv fli flv wpl'\n\t\t\t},\n\n\t\t\tuploadRetry : 0,\n\t\t\tnetworkDownRetryTimeout : 5000, // milliseconds, don't flood when network is down\n\n\t\t\tchunkSize : 0,\n\t\t\tchunkUploadRetry : 0,\n\t\t\tchunkNetworkDownRetryTimeout : 2000, // milliseconds, don't flood when network is down\n\n\t\t\tKB: _SIZE_CONST(1),\n\t\t\tMB: _SIZE_CONST(2),\n\t\t\tGB: _SIZE_CONST(3),\n\t\t\tTB: _SIZE_CONST(4),\n\n\t\t\tEMPTY_PNG: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAC0lEQVQIW2NkAAIAAAoAAggA9GkAAAAASUVORK5CYII=',\n\n\t\t\texpando: 'fileapi' + (new Date).getTime(),\n\n\t\t\tuid: function (obj){\n\t\t\t\treturn\tobj\n\t\t\t\t\t? (obj[api.expando] = obj[api.expando] || api.uid())\n\t\t\t\t\t: (++gid, api.expando + gid)\n\t\t\t\t;\n\t\t\t},\n\n\t\t\tlog: function (){\n\t\t\t\t// ngf fix for IE8 #1071\n\t\t\t\tif( api.debug && api._supportConsoleLog ){\n\t\t\t\t\tif( api._supportConsoleLogApply ){\n\t\t\t\t\t\tconsole.log.apply(console, arguments);\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\tconsole.log([].join.call(arguments, ' '));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\n\t\t\t/**\n\t\t\t * Create new image\n\t\t\t *\n\t\t\t * @param {String} [src]\n\t\t\t * @param {Function} [fn]   1. error -- boolean, 2. img -- Image element\n\t\t\t * @returns {HTMLElement}\n\t\t\t */\n\t\t\tnewImage: function (src, fn){\n\t\t\t\tvar img = document.createElement('img');\n\t\t\t\tif( fn ){\n\t\t\t\t\tapi.event.one(img, 'error load', function (evt){\n\t\t\t\t\t\tfn(evt.type == 'error', img);\n\t\t\t\t\t\timg = null;\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\timg.src = src;\n\t\t\t\treturn\timg;\n\t\t\t},\n\n\t\t\t/**\n\t\t\t * Get XHR\n\t\t\t * @returns {XMLHttpRequest}\n\t\t\t */\n\t\t\tgetXHR: function (){\n\t\t\t\tvar xhr;\n\n\t\t\t\tif( XMLHttpRequest ){\n\t\t\t\t\txhr = new XMLHttpRequest;\n\t\t\t\t}\n\t\t\t\telse if( window.ActiveXObject ){\n\t\t\t\t\ttry {\n\t\t\t\t\t\txhr = new ActiveXObject('MSXML2.XMLHttp.3.0');\n\t\t\t\t\t} catch (e) {\n\t\t\t\t\t\txhr = new ActiveXObject('Microsoft.XMLHTTP');\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn  xhr;\n\t\t\t},\n\n\t\t\tisArray: _isArray,\n\n\t\t\tsupport: {\n\t\t\t\tdnd:     cors && ('ondrop' in document.createElement('div')),\n\t\t\t\tcors:    cors,\n\t\t\t\thtml5:   html5,\n\t\t\t\tchunked: chunked,\n\t\t\t\tdataURI: true,\n\t\t\t\taccept:   _supportInputAttr('accept'),\n\t\t\t\tmultiple: _supportInputAttr('multiple')\n\t\t\t},\n\n\t\t\tevent: {\n\t\t\t\t  on: _on\n\t\t\t\t, off: _off\n\t\t\t\t, one: _one\n\t\t\t\t, fix: _fixEvent\n\t\t\t},\n\n\n\t\t\tthrottle: function(fn, delay) {\n\t\t\t\tvar id, args;\n\n\t\t\t\treturn function _throttle(){\n\t\t\t\t\targs = arguments;\n\n\t\t\t\t\tif( !id ){\n\t\t\t\t\t\tfn.apply(window, args);\n\t\t\t\t\t\tid = setTimeout(function (){\n\t\t\t\t\t\t\tid = 0;\n\t\t\t\t\t\t\tfn.apply(window, args);\n\t\t\t\t\t\t}, delay);\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\t},\n\n\n\t\t\tF: function (){},\n\n\n\t\t\tparseJSON: function (str){\n\t\t\t\tvar json;\n\t\t\t\tif( window.JSON && JSON.parse ){\n\t\t\t\t\tjson = JSON.parse(str);\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tjson = (new Function('return ('+str.replace(/([\\r\\n])/g, '\\\\$1')+');'))();\n\t\t\t\t}\n\t\t\t\treturn json;\n\t\t\t},\n\n\n\t\t\ttrim: function (str){\n\t\t\t\tstr = String(str);\n\t\t\t\treturn\tstr.trim ? str.trim() : str.replace(/^\\s+|\\s+$/g, '');\n\t\t\t},\n\n\t\t\t/**\n\t\t\t * Simple Defer\n\t\t\t * @return\t{Object}\n\t\t\t */\n\t\t\tdefer: function (){\n\t\t\t\tvar\n\t\t\t\t\t  list = []\n\t\t\t\t\t, result\n\t\t\t\t\t, error\n\t\t\t\t\t, defer = {\n\t\t\t\t\t\tresolve: function (err, res){\n\t\t\t\t\t\t\tdefer.resolve = noop;\n\t\t\t\t\t\t\terror\t= err || false;\n\t\t\t\t\t\t\tresult\t= res;\n\n\t\t\t\t\t\t\twhile( res = list.shift() ){\n\t\t\t\t\t\t\t\tres(error, result);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\n\t\t\t\t\t\tthen: function (fn){\n\t\t\t\t\t\t\tif( error !== undef ){\n\t\t\t\t\t\t\t\tfn(error, result);\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tlist.push(fn);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t};\n\n\t\t\t\treturn\tdefer;\n\t\t\t},\n\n\t\t\tqueue: function (fn){\n\t\t\t\tvar\n\t\t\t\t\t  _idx = 0\n\t\t\t\t\t, _length = 0\n\t\t\t\t\t, _fail = false\n\t\t\t\t\t, _end = false\n\t\t\t\t\t, queue = {\n\t\t\t\t\t\tinc: function (){\n\t\t\t\t\t\t\t_length++;\n\t\t\t\t\t\t},\n\n\t\t\t\t\t\tnext: function (){\n\t\t\t\t\t\t\t_idx++;\n\t\t\t\t\t\t\tsetTimeout(queue.check, 0);\n\t\t\t\t\t\t},\n\n\t\t\t\t\t\tcheck: function (){\n\t\t\t\t\t\t\t(_idx >= _length) && !_fail && queue.end();\n\t\t\t\t\t\t},\n\n\t\t\t\t\t\tisFail: function (){\n\t\t\t\t\t\t\treturn _fail;\n\t\t\t\t\t\t},\n\n\t\t\t\t\t\tfail: function (){\n\t\t\t\t\t\t\t!_fail && fn(_fail = true);\n\t\t\t\t\t\t},\n\n\t\t\t\t\t\tend: function (){\n\t\t\t\t\t\t\tif( !_end ){\n\t\t\t\t\t\t\t\t_end = true;\n\t\t\t\t\t\t\t\tfn();\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 queue;\n\t\t\t},\n\n\n\t\t\t/**\n\t\t\t * For each object\n\t\t\t *\n\t\t\t * @param\t{Object|Array}\tobj\n\t\t\t * @param\t{Function}\t\tfn\n\t\t\t * @param\t{*}\t\t\t\t[ctx]\n\t\t\t */\n\t\t\teach: _each,\n\n\n\t\t\t/**\n\t\t\t * Async for\n\t\t\t * @param {Array} array\n\t\t\t * @param {Function} callback\n\t\t\t */\n\t\t\tafor: function (array, callback){\n\t\t\t\tvar i = 0, n = array.length;\n\n\t\t\t\tif( _isArray(array) && n-- ){\n\t\t\t\t\t(function _next(){\n\t\t\t\t\t\tcallback(n != i && _next, array[i], i++);\n\t\t\t\t\t})();\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tcallback(false);\n\t\t\t\t}\n\t\t\t},\n\n\n\t\t\t/**\n\t\t\t * Merge the contents of two or more objects together into the first object\n\t\t\t *\n\t\t\t * @param\t{Object}\tdst\n\t\t\t * @return\t{Object}\n\t\t\t */\n\t\t\textend: _extend,\n\n\n\t\t\t/**\n\t\t\t * Is file?\n\t\t\t * @param  {File}  file\n\t\t\t * @return {Boolean}\n\t\t\t */\n\t\t\tisFile: function (file){\n\t\t\t\treturn _toString.call(file) === '[object File]';\n\t\t\t},\n\n\n\t\t\t/**\n\t\t\t * Is blob?\n\t\t\t * @param   {Blob}  blob\n\t\t\t * @returns {Boolean}\n\t\t\t */\n\t\t\tisBlob: function (blob) {\n\t\t\t\treturn this.isFile(blob) || (_toString.call(blob) === '[object Blob]');\n\t\t\t},\n\n\n\t\t\t/**\n\t\t\t * Is canvas element\n\t\t\t *\n\t\t\t * @param\t{HTMLElement}\tel\n\t\t\t * @return\t{Boolean}\n\t\t\t */\n\t\t\tisCanvas: function (el){\n\t\t\t\treturn\tel && _rcanvas.test(el.nodeName);\n\t\t\t},\n\n\n\t\t\tgetFilesFilter: function (filter){\n\t\t\t\tfilter = typeof filter == 'string' ? filter : (filter.getAttribute && filter.getAttribute('accept') || '');\n\t\t\t\treturn\tfilter ? new RegExp('('+ filter.replace(/\\./g, '\\\\.').replace(/,/g, '|') +')$', 'i') : /./;\n\t\t\t},\n\n\n\n\t\t\t/**\n\t\t\t * Read as DataURL\n\t\t\t *\n\t\t\t * @param {File|Element} file\n\t\t\t * @param {Function} fn\n\t\t\t */\n\t\t\treadAsDataURL: function (file, fn){\n\t\t\t\tif( api.isCanvas(file) ){\n\t\t\t\t\t_emit(file, fn, 'load', api.toDataURL(file));\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\t_readAs(file, fn, 'DataURL');\n\t\t\t\t}\n\t\t\t},\n\n\n\t\t\t/**\n\t\t\t * Read as Binary string\n\t\t\t *\n\t\t\t * @param {File} file\n\t\t\t * @param {Function} fn\n\t\t\t */\n\t\t\treadAsBinaryString: function (file, fn){\n\t\t\t\tif( _hasSupportReadAs('BinaryString') ){\n\t\t\t\t\t_readAs(file, fn, 'BinaryString');\n\t\t\t\t} else {\n\t\t\t\t\t// Hello IE10!\n\t\t\t\t\t_readAs(file, function (evt){\n\t\t\t\t\t\tif( evt.type == 'load' ){\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t// dataURL -> binaryString\n\t\t\t\t\t\t\t\tevt.result = api.toBinaryString(evt.result);\n\t\t\t\t\t\t\t} catch (e){\n\t\t\t\t\t\t\t\tevt.type = 'error';\n\t\t\t\t\t\t\t\tevt.message = e.toString();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tfn(evt);\n\t\t\t\t\t}, 'DataURL');\n\t\t\t\t}\n\t\t\t},\n\n\n\t\t\t/**\n\t\t\t * Read as ArrayBuffer\n\t\t\t *\n\t\t\t * @param {File} file\n\t\t\t * @param {Function} fn\n\t\t\t */\n\t\t\treadAsArrayBuffer: function(file, fn){\n\t\t\t\t_readAs(file, fn, 'ArrayBuffer');\n\t\t\t},\n\n\n\t\t\t/**\n\t\t\t * Read as text\n\t\t\t *\n\t\t\t * @param {File} file\n\t\t\t * @param {String} encoding\n\t\t\t * @param {Function} [fn]\n\t\t\t */\n\t\t\treadAsText: function(file, encoding, fn){\n\t\t\t\tif( !fn ){\n\t\t\t\t\tfn\t= encoding;\n\t\t\t\t\tencoding = 'utf-8';\n\t\t\t\t}\n\n\t\t\t\t_readAs(file, fn, 'Text', encoding);\n\t\t\t},\n\n\n\t\t\t/**\n\t\t\t * Convert image or canvas to DataURL\n\t\t\t *\n\t\t\t * @param   {Element}  el      Image or Canvas element\n\t\t\t * @param   {String}   [type]  mime-type\n\t\t\t * @return  {String}\n\t\t\t */\n\t\t\ttoDataURL: function (el, type){\n\t\t\t\tif( typeof el == 'string' ){\n\t\t\t\t\treturn  el;\n\t\t\t\t}\n\t\t\t\telse if( el.toDataURL ){\n\t\t\t\t\treturn  el.toDataURL(type || 'image/png');\n\t\t\t\t}\n\t\t\t},\n\n\n\t\t\t/**\n\t\t\t * Canvert string, image or canvas to binary string\n\t\t\t *\n\t\t\t * @param   {String|Element} val\n\t\t\t * @return  {String}\n\t\t\t */\n\t\t\ttoBinaryString: function (val){\n\t\t\t\treturn  window.atob(api.toDataURL(val).replace(_rdata, ''));\n\t\t\t},\n\n\n\t\t\t/**\n\t\t\t * Read file or DataURL as ImageElement\n\t\t\t *\n\t\t\t * @param\t{File|String}\tfile\n\t\t\t * @param\t{Function}\t\tfn\n\t\t\t * @param\t{Boolean}\t\t[progress]\n\t\t\t */\n\t\t\treadAsImage: function (file, fn, progress){\n\t\t\t\tif( api.isFile(file) ){\n\t\t\t\t\tif( apiURL ){\n\t\t\t\t\t\t/** @namespace apiURL.createObjectURL */\n\t\t\t\t\t\tvar data = apiURL.createObjectURL(file);\n\t\t\t\t\t\tif( data === undef ){\n\t\t\t\t\t\t\t_emit(file, fn, 'error');\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse {\n\t\t\t\t\t\t\tapi.readAsImage(data, fn, progress);\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\tapi.readAsDataURL(file, function (evt){\n\t\t\t\t\t\t\tif( evt.type == 'load' ){\n\t\t\t\t\t\t\t\tapi.readAsImage(evt.result, fn, progress);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse if( progress || evt.type == 'error' ){\n\t\t\t\t\t\t\t\t_emit(file, fn, evt, null, { loaded: evt.loaded, total: evt.total });\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\telse if( api.isCanvas(file) ){\n\t\t\t\t\t_emit(file, fn, 'load', file);\n\t\t\t\t}\n\t\t\t\telse if( _rimg.test(file.nodeName) ){\n\t\t\t\t\tif( file.complete ){\n\t\t\t\t\t\t_emit(file, fn, 'load', file);\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\tvar events = 'error abort load';\n\t\t\t\t\t\t_one(file, events, function _fn(evt){\n\t\t\t\t\t\t\tif( evt.type == 'load' && apiURL ){\n\t\t\t\t\t\t\t\t/** @namespace apiURL.revokeObjectURL */\n\t\t\t\t\t\t\t\tapiURL.revokeObjectURL(file.src);\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t_off(file, events, _fn);\n\t\t\t\t\t\t\t_emit(file, fn, evt, file);\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse if( file.iframe ){\n\t\t\t\t\t_emit(file, fn, { type: 'error' });\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\t// Created image\n\t\t\t\t\tvar img = api.newImage(file.dataURL || file);\n\t\t\t\t\tapi.readAsImage(img, fn, progress);\n\t\t\t\t}\n\t\t\t},\n\n\n\t\t\t/**\n\t\t\t * Make file by name\n\t\t\t *\n\t\t\t * @param\t{String}\tname\n\t\t\t * @return\t{Array}\n\t\t\t */\n\t\t\tcheckFileObj: function (name){\n\t\t\t\tvar file = {}, accept = api.accept;\n\n\t\t\t\tif( typeof name == 'object' ){\n\t\t\t\t\tfile = name;\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tfile.name = (name + '').split(/\\\\|\\//g).pop();\n\t\t\t\t}\n\n\t\t\t\tif( file.type == null ){\n\t\t\t\t\tfile.type = file.name.split('.').pop();\n\t\t\t\t}\n\n\t\t\t\t_each(accept, function (ext, type){\n\t\t\t\t\text = new RegExp(ext.replace(/\\s/g, '|'), 'i');\n\t\t\t\t\tif( ext.test(file.type) || api.ext2mime[file.type] ){\n\t\t\t\t\t\tfile.type = api.ext2mime[file.type] || (type.split('/')[0] +'/'+ file.type);\n\t\t\t\t\t}\n\t\t\t\t});\n\n\t\t\t\treturn\tfile;\n\t\t\t},\n\n\n\t\t\t/**\n\t\t\t * Get drop files\n\t\t\t *\n\t\t\t * @param\t{Event}\tevt\n\t\t\t * @param\t{Function} callback\n\t\t\t */\n\t\t\tgetDropFiles: function (evt, callback){\n\t\t\t\tvar\n\t\t\t\t\t  files = []\n\t\t\t\t\t, dataTransfer = _getDataTransfer(evt)\n\t\t\t\t\t, entrySupport = _isArray(dataTransfer.items) && dataTransfer.items[0] && _getAsEntry(dataTransfer.items[0])\n\t\t\t\t\t, queue = api.queue(function (){ callback(files); })\n\t\t\t\t;\n\n\t\t\t\t_each((entrySupport ? dataTransfer.items : dataTransfer.files) || [], function (item){\n\t\t\t\t\tqueue.inc();\n\n\t\t\t\t\ttry {\n\t\t\t\t\t\tif( entrySupport ){\n\t\t\t\t\t\t\t_readEntryAsFiles(item, function (err, entryFiles){\n\t\t\t\t\t\t\t\tif( err ){\n\t\t\t\t\t\t\t\t\tapi.log('[err] getDropFiles:', err);\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tfiles.push.apply(files, entryFiles);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tqueue.next();\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\t_isRegularFile(item, function (yes){\n\t\t\t\t\t\t\t\tyes && files.push(item);\n\t\t\t\t\t\t\t\tqueue.next();\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\tcatch( err ){\n\t\t\t\t\t\tqueue.next();\n\t\t\t\t\t\tapi.log('[err] getDropFiles: ', err);\n\t\t\t\t\t}\n\t\t\t\t});\n\n\t\t\t\tqueue.check();\n\t\t\t},\n\n\n\t\t\t/**\n\t\t\t * Get file list\n\t\t\t *\n\t\t\t * @param\t{HTMLInputElement|Event}\tinput\n\t\t\t * @param\t{String|Function}\t[filter]\n\t\t\t * @param\t{Function}\t\t\t[callback]\n\t\t\t * @return\t{Array|Null}\n\t\t\t */\n\t\t\tgetFiles: function (input, filter, callback){\n\t\t\t\tvar files = [];\n\n\t\t\t\tif( callback ){\n\t\t\t\t\tapi.filterFiles(api.getFiles(input), filter, callback);\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\n\t\t\t\tif( input.jquery ){\n\t\t\t\t\t// jQuery object\n\t\t\t\t\tinput.each(function (){\n\t\t\t\t\t\tfiles = files.concat(api.getFiles(this));\n\t\t\t\t\t});\n\t\t\t\t\tinput\t= files;\n\t\t\t\t\tfiles\t= [];\n\t\t\t\t}\n\n\t\t\t\tif( typeof filter == 'string' ){\n\t\t\t\t\tfilter\t= api.getFilesFilter(filter);\n\t\t\t\t}\n\n\t\t\t\tif( input.originalEvent ){\n\t\t\t\t\t// jQuery event\n\t\t\t\t\tinput = _fixEvent(input.originalEvent);\n\t\t\t\t}\n\t\t\t\telse if( input.srcElement ){\n\t\t\t\t\t// IE Event\n\t\t\t\t\tinput = _fixEvent(input);\n\t\t\t\t}\n\n\n\t\t\t\tif( input.dataTransfer ){\n\t\t\t\t\t// Drag'n'Drop\n\t\t\t\t\tinput = input.dataTransfer;\n\t\t\t\t}\n\t\t\t\telse if( input.target ){\n\t\t\t\t\t// Event\n\t\t\t\t\tinput = input.target;\n\t\t\t\t}\n\n\t\t\t\tif( input.files ){\n\t\t\t\t\t// Input[type=\"file\"]\n\t\t\t\t\tfiles = input.files;\n\n\t\t\t\t\tif( !html5 ){\n\t\t\t\t\t\t// Partial support for file api\n\t\t\t\t\t\tfiles[0].blob\t= input;\n\t\t\t\t\t\tfiles[0].iframe\t= true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse if( !html5 && isInputFile(input) ){\n\t\t\t\t\tif( api.trim(input.value) ){\n\t\t\t\t\t\tfiles = [api.checkFileObj(input.value)];\n\t\t\t\t\t\tfiles[0].blob   = input;\n\t\t\t\t\t\tfiles[0].iframe = true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse if( _isArray(input) ){\n\t\t\t\t\tfiles\t= input;\n\t\t\t\t}\n\n\t\t\t\treturn\tapi.filter(files, function (file){ return !filter || filter.test(file.name); });\n\t\t\t},\n\n\n\t\t\t/**\n\t\t\t * Get total file size\n\t\t\t * @param\t{Array}\tfiles\n\t\t\t * @return\t{Number}\n\t\t\t */\n\t\t\tgetTotalSize: function (files){\n\t\t\t\tvar size = 0, i = files && files.length;\n\t\t\t\twhile( i-- ){\n\t\t\t\t\tsize += files[i].size;\n\t\t\t\t}\n\t\t\t\treturn\tsize;\n\t\t\t},\n\n\n\t\t\t/**\n\t\t\t * Get image information\n\t\t\t *\n\t\t\t * @param\t{File}\t\tfile\n\t\t\t * @param\t{Function}\tfn\n\t\t\t */\n\t\t\tgetInfo: function (file, fn){\n\t\t\t\tvar info = {}, readers = _infoReader.concat();\n\n\t\t\t\tif( api.isFile(file) ){\n\t\t\t\t\t(function _next(){\n\t\t\t\t\t\tvar reader = readers.shift();\n\t\t\t\t\t\tif( reader ){\n\t\t\t\t\t\t\tif( reader.test(file.type) ){\n\t\t\t\t\t\t\t\treader(file, function (err, res){\n\t\t\t\t\t\t\t\t\tif( err ){\n\t\t\t\t\t\t\t\t\t\tfn(err);\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\t_extend(info, res);\n\t\t\t\t\t\t\t\t\t\t_next();\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\telse {\n\t\t\t\t\t\t\t\t_next();\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\tfn(false, info);\n\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\tfn('not_support_info', info);\n\t\t\t\t}\n\t\t\t},\n\n\n\t\t\t/**\n\t\t\t * Add information reader\n\t\t\t *\n\t\t\t * @param {RegExp} mime\n\t\t\t * @param {Function} fn\n\t\t\t */\n\t\t\taddInfoReader: function (mime, fn){\n\t\t\t\tfn.test = function (type){ return mime.test(type); };\n\t\t\t\t_infoReader.push(fn);\n\t\t\t},\n\n\n\t\t\t/**\n\t\t\t * Filter of array\n\t\t\t *\n\t\t\t * @param\t{Array}\t\tinput\n\t\t\t * @param\t{Function}\tfn\n\t\t\t * @return\t{Array}\n\t\t\t */\n\t\t\tfilter: function (input, fn){\n\t\t\t\tvar result = [], i = 0, n = input.length, val;\n\n\t\t\t\tfor( ; i < n; i++ ){\n\t\t\t\t\tif( i in input ){\n\t\t\t\t\t\tval = input[i];\n\t\t\t\t\t\tif( fn.call(val, val, i, input) ){\n\t\t\t\t\t\t\tresult.push(val);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn\tresult;\n\t\t\t},\n\n\n\t\t\t/**\n\t\t\t * Filter files\n\t\t\t *\n\t\t\t * @param\t{Array}\t\tfiles\n\t\t\t * @param\t{Function}\teachFn\n\t\t\t * @param\t{Function}\tresultFn\n\t\t\t */\n\t\t\tfilterFiles: function (files, eachFn, resultFn){\n\t\t\t\tif( files.length ){\n\t\t\t\t\t// HTML5 or Flash\n\t\t\t\t\tvar queue = files.concat(), file, result = [], deleted = [];\n\n\t\t\t\t\t(function _next(){\n\t\t\t\t\t\tif( queue.length ){\n\t\t\t\t\t\t\tfile = queue.shift();\n\t\t\t\t\t\t\tapi.getInfo(file, function (err, info){\n\t\t\t\t\t\t\t\t(eachFn(file, err ? false : info) ? result : deleted).push(file);\n\t\t\t\t\t\t\t\t_next();\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\tresultFn(result, deleted);\n\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\tresultFn([], files);\n\t\t\t\t}\n\t\t\t},\n\n\n\t\t\tupload: function (options){\n\t\t\t\toptions = _extend({\n\t\t\t\t\t  jsonp: 'callback'\n\t\t\t\t\t, prepare: api.F\n\t\t\t\t\t, beforeupload: api.F\n\t\t\t\t\t, upload: api.F\n\t\t\t\t\t, fileupload: api.F\n\t\t\t\t\t, fileprogress: api.F\n\t\t\t\t\t, filecomplete: api.F\n\t\t\t\t\t, progress: api.F\n\t\t\t\t\t, complete: api.F\n\t\t\t\t\t, pause: api.F\n\t\t\t\t\t, imageOriginal: true\n\t\t\t\t\t, chunkSize: api.chunkSize\n\t\t\t\t\t, chunkUploadRetry: api.chunkUploadRetry\n\t\t\t\t\t, uploadRetry: api.uploadRetry\n\t\t\t\t}, options);\n\n\n\t\t\t\tif( options.imageAutoOrientation && !options.imageTransform ){\n\t\t\t\t\toptions.imageTransform = { rotate: 'auto' };\n\t\t\t\t}\n\n\n\t\t\t\tvar\n\t\t\t\t\t  proxyXHR = new api.XHR(options)\n\t\t\t\t\t, dataArray = this._getFilesDataArray(options.files)\n\t\t\t\t\t, _this = this\n\t\t\t\t\t, _total = 0\n\t\t\t\t\t, _loaded = 0\n\t\t\t\t\t, _nextFile\n\t\t\t\t\t, _complete = false\n\t\t\t\t;\n\n\n\t\t\t\t// calc total size\n\t\t\t\t_each(dataArray, function (data){\n\t\t\t\t\t_total += data.size;\n\t\t\t\t});\n\n\t\t\t\t// Array of files\n\t\t\t\tproxyXHR.files = [];\n\t\t\t\t_each(dataArray, function (data){\n\t\t\t\t\tproxyXHR.files.push(data.file);\n\t\t\t\t});\n\n\t\t\t\t// Set upload status props\n\t\t\t\tproxyXHR.total\t= _total;\n\t\t\t\tproxyXHR.loaded\t= 0;\n\t\t\t\tproxyXHR.filesLeft = dataArray.length;\n\n\t\t\t\t// emit \"beforeupload\"  event\n\t\t\t\toptions.beforeupload(proxyXHR, options);\n\n\t\t\t\t// Upload by file\n\t\t\t\t_nextFile = function (){\n\t\t\t\t\tvar\n\t\t\t\t\t\t  data = dataArray.shift()\n\t\t\t\t\t\t, _file = data && data.file\n\t\t\t\t\t\t, _fileLoaded = false\n\t\t\t\t\t\t, _fileOptions = _simpleClone(options)\n\t\t\t\t\t;\n\n\t\t\t\t\tproxyXHR.filesLeft = dataArray.length;\n\n\t\t\t\t\tif( _file && _file.name === api.expando ){\n\t\t\t\t\t\t_file = null;\n\t\t\t\t\t\tapi.log('[warn] FileAPI.upload() — called without files');\n\t\t\t\t\t}\n\n\t\t\t\t\tif( ( proxyXHR.statusText != 'abort' || proxyXHR.current ) && data ){\n\t\t\t\t\t\t// Mark active job\n\t\t\t\t\t\t_complete = false;\n\n\t\t\t\t\t\t// Set current upload file\n\t\t\t\t\t\tproxyXHR.currentFile = _file;\n\n\t\t\t\t\t\t// Prepare file options\n\t\t\t\t\t\tif (_file && options.prepare(_file, _fileOptions) === false) {\n\t\t\t\t\t\t\t_nextFile.call(_this);\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t\t_fileOptions.file = _file;\n\n\t\t\t\t\t\t_this._getFormData(_fileOptions, data, function (form){\n\t\t\t\t\t\t\tif( !_loaded ){\n\t\t\t\t\t\t\t\t// emit \"upload\" event\n\t\t\t\t\t\t\t\toptions.upload(proxyXHR, options);\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tvar xhr = new api.XHR(_extend({}, _fileOptions, {\n\n\t\t\t\t\t\t\t\tupload: _file ? function (){\n\t\t\t\t\t\t\t\t\t// emit \"fileupload\" event\n\t\t\t\t\t\t\t\t\toptions.fileupload(_file, xhr, _fileOptions);\n\t\t\t\t\t\t\t\t} : noop,\n\n\t\t\t\t\t\t\t\tprogress: _file ? function (evt){\n\t\t\t\t\t\t\t\t\tif( !_fileLoaded ){\n\t\t\t\t\t\t\t\t\t\t// For ignore the double calls.\n\t\t\t\t\t\t\t\t\t\t_fileLoaded = (evt.loaded === evt.total);\n\n\t\t\t\t\t\t\t\t\t\t// emit \"fileprogress\" event\n\t\t\t\t\t\t\t\t\t\toptions.fileprogress({\n\t\t\t\t\t\t\t\t\t\t\t  type:   'progress'\n\t\t\t\t\t\t\t\t\t\t\t, total:  data.total = evt.total\n\t\t\t\t\t\t\t\t\t\t\t, loaded: data.loaded = evt.loaded\n\t\t\t\t\t\t\t\t\t\t}, _file, xhr, _fileOptions);\n\n\t\t\t\t\t\t\t\t\t\t// emit \"progress\" event\n\t\t\t\t\t\t\t\t\t\toptions.progress({\n\t\t\t\t\t\t\t\t\t\t\t  type:   'progress'\n\t\t\t\t\t\t\t\t\t\t\t, total:  _total\n\t\t\t\t\t\t\t\t\t\t\t, loaded: proxyXHR.loaded = (_loaded + data.size * (evt.loaded/evt.total))|0\n\t\t\t\t\t\t\t\t\t\t}, _file, xhr, _fileOptions);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t} : noop,\n\n\t\t\t\t\t\t\t\tcomplete: function (err){\n\t\t\t\t\t\t\t\t\t_each(_xhrPropsExport, function (name){\n\t\t\t\t\t\t\t\t\t\tproxyXHR[name] = xhr[name];\n\t\t\t\t\t\t\t\t\t});\n\n\t\t\t\t\t\t\t\t\tif( _file ){\n\t\t\t\t\t\t\t\t\t\tdata.total = (data.total || data.size);\n\t\t\t\t\t\t\t\t\t\tdata.loaded\t= data.total;\n\n\t\t\t\t\t\t\t\t\t\tif( !err ) {\n\t\t\t\t\t\t\t\t\t\t\t// emulate 100% \"progress\"\n\t\t\t\t\t\t\t\t\t\t\tthis.progress(data);\n\n\t\t\t\t\t\t\t\t\t\t\t// fixed throttle event\n\t\t\t\t\t\t\t\t\t\t\t_fileLoaded = true;\n\n\t\t\t\t\t\t\t\t\t\t\t// bytes loaded\n\t\t\t\t\t\t\t\t\t\t\t_loaded += data.size; // data.size != data.total, it's desirable fix this\n\t\t\t\t\t\t\t\t\t\t\tproxyXHR.loaded = _loaded;\n\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t// emit \"filecomplete\" event\n\t\t\t\t\t\t\t\t\t\toptions.filecomplete(err, xhr, _file, _fileOptions);\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t// upload next file\n\t\t\t\t\t\t\t\t\tsetTimeout(function () {_nextFile.call(_this);}, 0);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t})); // xhr\n\n\n\t\t\t\t\t\t\t// ...\n\t\t\t\t\t\t\tproxyXHR.abort = function (current){\n\t\t\t\t\t\t\t\tif (!current) { dataArray.length = 0; }\n\t\t\t\t\t\t\t\tthis.current = current;\n\t\t\t\t\t\t\t\txhr.abort();\n\t\t\t\t\t\t\t};\n\n\t\t\t\t\t\t\t// Start upload\n\t\t\t\t\t\t\txhr.send(form);\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\tvar successful = proxyXHR.status == 200 || proxyXHR.status == 201 || proxyXHR.status == 204;\n\t\t\t\t\t\toptions.complete(successful ? false : (proxyXHR.statusText || 'error'), proxyXHR, options);\n\t\t\t\t\t\t// Mark done state\n\t\t\t\t\t\t_complete = true;\n\t\t\t\t\t}\n\t\t\t\t};\n\n\n\t\t\t\t// Next tick\n\t\t\t\tsetTimeout(_nextFile, 0);\n\n\n\t\t\t\t// Append more files to the existing request\n\t\t\t\t// first - add them to the queue head/tail\n\t\t\t\tproxyXHR.append = function (files, first) {\n\t\t\t\t\tfiles = api._getFilesDataArray([].concat(files));\n\n\t\t\t\t\t_each(files, function (data) {\n\t\t\t\t\t\t_total += data.size;\n\t\t\t\t\t\tproxyXHR.files.push(data.file);\n\t\t\t\t\t\tif (first) {\n\t\t\t\t\t\t\tdataArray.unshift(data);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tdataArray.push(data);\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\n\t\t\t\t\tproxyXHR.statusText = \"\";\n\n\t\t\t\t\tif( _complete ){\n\t\t\t\t\t\t_nextFile.call(_this);\n\t\t\t\t\t}\n\t\t\t\t};\n\n\n\t\t\t\t// Removes file from queue by file reference and returns it\n\t\t\t\tproxyXHR.remove = function (file) {\n\t\t\t\t    var i = dataArray.length, _file;\n\t\t\t\t    while( i-- ){\n\t\t\t\t\t\tif( dataArray[i].file == file ){\n\t\t\t\t\t\t\t_file = dataArray.splice(i, 1);\n\t\t\t\t\t\t\t_total -= _file.size;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\treturn\t_file;\n\t\t\t\t};\n\n\t\t\t\treturn proxyXHR;\n\t\t\t},\n\n\n\t\t\t_getFilesDataArray: function (data){\n\t\t\t\tvar files = [], oFiles = {};\n\n\t\t\t\tif( isInputFile(data) ){\n\t\t\t\t\tvar tmp = api.getFiles(data);\n\t\t\t\t\toFiles[data.name || 'file'] = data.getAttribute('multiple') !== null ? tmp : tmp[0];\n\t\t\t\t}\n\t\t\t\telse if( _isArray(data) && isInputFile(data[0]) ){\n\t\t\t\t\t_each(data, function (input){\n\t\t\t\t\t\toFiles[input.name || 'file'] = api.getFiles(input);\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\toFiles = data;\n\t\t\t\t}\n\n\t\t\t\t_each(oFiles, function add(file, name){\n\t\t\t\t\tif( _isArray(file) ){\n\t\t\t\t\t\t_each(file, function (file){\n\t\t\t\t\t\t\tadd(file, name);\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t\telse if( file && (file.name || file.image) ){\n\t\t\t\t\t\tfiles.push({\n\t\t\t\t\t\t\t  name: name\n\t\t\t\t\t\t\t, file: file\n\t\t\t\t\t\t\t, size: file.size\n\t\t\t\t\t\t\t, total: file.size\n\t\t\t\t\t\t\t, loaded: 0\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t});\n\n\t\t\t\tif( !files.length ){\n\t\t\t\t\t// Create fake `file` object\n\t\t\t\t\tfiles.push({ file: { name: api.expando } });\n\t\t\t\t}\n\n\t\t\t\treturn\tfiles;\n\t\t\t},\n\n\n\t\t\t_getFormData: function (options, data, fn){\n\t\t\t\tvar\n\t\t\t\t\t  file = data.file\n\t\t\t\t\t, name = data.name\n\t\t\t\t\t, filename = file.name\n\t\t\t\t\t, filetype = file.type\n\t\t\t\t\t, trans = api.support.transform && options.imageTransform\n\t\t\t\t\t, Form = new api.Form\n\t\t\t\t\t, queue = api.queue(function (){ fn(Form); })\n\t\t\t\t\t, isOrignTrans = trans && _isOriginTransform(trans)\n\t\t\t\t\t, postNameConcat = api.postNameConcat\n\t\t\t\t;\n\n\t\t\t\t// Append data\n\t\t\t\t_each(options.data, function add(val, name){\n\t\t\t\t\tif( typeof val == 'object' ){\n\t\t\t\t\t\t_each(val, function (v, i){\n\t\t\t\t\t\t\tadd(v, postNameConcat(name, 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\tForm.append(name, val);\n\t\t\t\t\t}\n\t\t\t\t});\n\n\t\t\t\t(function _addFile(file/**Object*/){\n\t\t\t\t\tif( file.image ){ // This is a FileAPI.Image\n\t\t\t\t\t\tqueue.inc();\n\n\t\t\t\t\t\tfile.toData(function (err, image){\n\t\t\t\t\t\t\t// @todo: error\n\t\t\t\t\t\t\tfilename = filename || (new Date).getTime()+'.png';\n\n\t\t\t\t\t\t\t_addFile(image);\n\t\t\t\t\t\t\tqueue.next();\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t\telse if( api.Image && trans && (/^image/.test(file.type) || _rimgcanvas.test(file.nodeName)) ){\n\t\t\t\t\t\tqueue.inc();\n\n\t\t\t\t\t\tif( isOrignTrans ){\n\t\t\t\t\t\t\t// Convert to array for transform function\n\t\t\t\t\t\t\ttrans = [trans];\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tapi.Image.transform(file, trans, options.imageAutoOrientation, function (err, images){\n\t\t\t\t\t\t\tif( isOrignTrans && !err ){\n\t\t\t\t\t\t\t\tif( !dataURLtoBlob && !api.flashEngine ){\n\t\t\t\t\t\t\t\t\t// Canvas.toBlob or Flash not supported, use multipart\n\t\t\t\t\t\t\t\t\tForm.multipart = true;\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\tForm.append(name, images[0], filename,  trans[0].type || filetype);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse {\n\t\t\t\t\t\t\t\tvar addOrigin = 0;\n\n\t\t\t\t\t\t\t\tif( !err ){\n\t\t\t\t\t\t\t\t\t_each(images, function (image, idx){\n\t\t\t\t\t\t\t\t\t\tif( !dataURLtoBlob && !api.flashEngine ){\n\t\t\t\t\t\t\t\t\t\t\tForm.multipart = true;\n\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\tif( !trans[idx].postName ){\n\t\t\t\t\t\t\t\t\t\t\taddOrigin = 1;\n\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\tForm.append(trans[idx].postName || postNameConcat(name, idx), image, filename, trans[idx].type || filetype);\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\tif( err || options.imageOriginal ){\n\t\t\t\t\t\t\t\t\tForm.append(postNameConcat(name, (addOrigin ? 'original' : null)), file, filename, filetype);\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\tqueue.next();\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t\telse if( filename !== api.expando ){\n\t\t\t\t\t\tForm.append(name, file, filename);\n\t\t\t\t\t}\n\t\t\t\t})(file);\n\n\t\t\t\tqueue.check();\n\t\t\t},\n\n\n\t\t\treset: function (inp, notRemove){\n\t\t\t\tvar parent, clone;\n\n\t\t\t\tif( jQuery ){\n\t\t\t\t\tclone = jQuery(inp).clone(true).insertBefore(inp).val('')[0];\n\t\t\t\t\tif( !notRemove ){\n\t\t\t\t\t\tjQuery(inp).remove();\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tparent  = inp.parentNode;\n\t\t\t\t\tclone   = parent.insertBefore(inp.cloneNode(true), inp);\n\t\t\t\t\tclone.value = '';\n\n\t\t\t\t\tif( !notRemove ){\n\t\t\t\t\t\tparent.removeChild(inp);\n\t\t\t\t\t}\n\n\t\t\t\t\t_each(_elEvents[api.uid(inp)], function (fns, type){\n\t\t\t\t\t\t_each(fns, function (fn){\n\t\t\t\t\t\t\t_off(inp, type, fn);\n\t\t\t\t\t\t\t_on(clone, type, fn);\n\t\t\t\t\t\t});\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\treturn  clone;\n\t\t\t},\n\n\n\t\t\t/**\n\t\t\t * Load remote file\n\t\t\t *\n\t\t\t * @param   {String}    url\n\t\t\t * @param   {Function}  fn\n\t\t\t * @return  {XMLHttpRequest}\n\t\t\t */\n\t\t\tload: function (url, fn){\n\t\t\t\tvar xhr = api.getXHR();\n\t\t\t\tif( xhr ){\n\t\t\t\t\txhr.open('GET', url, true);\n\n\t\t\t\t\tif( xhr.overrideMimeType ){\n\t\t\t\t        xhr.overrideMimeType('text/plain; charset=x-user-defined');\n\t\t\t\t\t}\n\n\t\t\t\t\t_on(xhr, 'progress', function (/**Event*/evt){\n\t\t\t\t\t\t/** @namespace evt.lengthComputable */\n\t\t\t\t\t\tif( evt.lengthComputable ){\n\t\t\t\t\t\t\tfn({ type: evt.type, loaded: evt.loaded, total: evt.total }, xhr);\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\n\t\t\t\t\txhr.onreadystatechange = function(){\n\t\t\t\t\t\tif( xhr.readyState == 4 ){\n\t\t\t\t\t\t\txhr.onreadystatechange = null;\n\t\t\t\t\t\t\tif( xhr.status == 200 ){\n\t\t\t\t\t\t\t\turl = url.split('/');\n\t\t\t\t\t\t\t\t/** @namespace xhr.responseBody */\n\t\t\t\t\t\t\t\tvar file = {\n\t\t\t\t\t\t\t\t      name: url[url.length-1]\n\t\t\t\t\t\t\t\t\t, size: xhr.getResponseHeader('Content-Length')\n\t\t\t\t\t\t\t\t\t, type: xhr.getResponseHeader('Content-Type')\n\t\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\t\tfile.dataURL = 'data:'+file.type+';base64,' + api.encode64(xhr.responseBody || xhr.responseText);\n\t\t\t\t\t\t\t\tfn({ type: 'load', result: file }, xhr);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse {\n\t\t\t\t\t\t\t\tfn({ type: 'error' }, xhr);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t    }\n\t\t\t\t\t};\n\t\t\t\t    xhr.send(null);\n\t\t\t\t} else {\n\t\t\t\t\tfn({ type: 'error' });\n\t\t\t\t}\n\n\t\t\t\treturn  xhr;\n\t\t\t},\n\n\t\t\tencode64: function (str){\n\t\t\t\tvar b64 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=', outStr = '', i = 0;\n\n\t\t\t\tif( typeof str !== 'string' ){\n\t\t\t\t\tstr\t= String(str);\n\t\t\t\t}\n\n\t\t\t\twhile( i < str.length ){\n\t\t\t\t\t//all three \"& 0xff\" added below are there to fix a known bug\n\t\t\t\t\t//with bytes returned by xhr.responseText\n\t\t\t\t\tvar\n\t\t\t\t\t\t  byte1 = str.charCodeAt(i++) & 0xff\n\t\t\t\t\t\t, byte2 = str.charCodeAt(i++) & 0xff\n\t\t\t\t\t\t, byte3 = str.charCodeAt(i++) & 0xff\n\t\t\t\t\t\t, enc1 = byte1 >> 2\n\t\t\t\t\t\t, enc2 = ((byte1 & 3) << 4) | (byte2 >> 4)\n\t\t\t\t\t\t, enc3, enc4\n\t\t\t\t\t;\n\n\t\t\t\t\tif( isNaN(byte2) ){\n\t\t\t\t\t\tenc3 = enc4 = 64;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tenc3 = ((byte2 & 15) << 2) | (byte3 >> 6);\n\t\t\t\t\t\tenc4 = isNaN(byte3) ? 64 : byte3 & 63;\n\t\t\t\t\t}\n\n\t\t\t\t\toutStr += b64.charAt(enc1) + b64.charAt(enc2) + b64.charAt(enc3) + b64.charAt(enc4);\n\t\t\t\t}\n\n\t\t\t\treturn  outStr;\n\t\t\t}\n\n\t\t} // api\n\t;\n\n\n\tfunction _emit(target, fn, name, res, ext){\n\t\tvar evt = {\n\t\t\t  type:\t\tname.type || name\n\t\t\t, target:\ttarget\n\t\t\t, result:\tres\n\t\t};\n\t\t_extend(evt, ext);\n\t\tfn(evt);\n\t}\n\n\n\tfunction _hasSupportReadAs(as){\n\t\treturn\tFileReader && !!FileReader.prototype['readAs'+as];\n\t}\n\n\n\tfunction _readAs(file, fn, as, encoding){\n\t\tif( api.isBlob(file) && _hasSupportReadAs(as) ){\n\t\t\tvar Reader = new FileReader;\n\n\t\t\t// Add event listener\n\t\t\t_on(Reader, _readerEvents, function _fn(evt){\n\t\t\t\tvar type = evt.type;\n\t\t\t\tif( type == 'progress' ){\n\t\t\t\t\t_emit(file, fn, evt, evt.target.result, { loaded: evt.loaded, total: evt.total });\n\t\t\t\t}\n\t\t\t\telse if( type == 'loadend' ){\n\t\t\t\t\t_off(Reader, _readerEvents, _fn);\n\t\t\t\t\tReader = null;\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\t_emit(file, fn, evt, evt.target.result);\n\t\t\t\t}\n\t\t\t});\n\n\n\t\t\ttry {\n\t\t\t\t// ReadAs ...\n\t\t\t\tif( encoding ){\n\t\t\t\t\tReader['readAs'+as](file, encoding);\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tReader['readAs'+as](file);\n\t\t\t\t}\n\t\t\t}\n\t\t\tcatch (err){\n\t\t\t\t_emit(file, fn, 'error', undef, { error: err.toString() });\n\t\t\t}\n\t\t}\n\t\telse {\n\t\t\t_emit(file, fn, 'error', undef, { error: 'FileReader_not_support_'+as });\n\t\t}\n\t}\n\n\n\tfunction _isRegularFile(file, callback){\n\t\t// http://stackoverflow.com/questions/8856628/detecting-folders-directories-in-javascript-filelist-objects\n\t\tif( !file.type && (file.size % 4096) === 0 && (file.size <= 102400) ){\n\t\t\tif( FileReader ){\n\t\t\t\ttry {\n\t\t\t\t\tvar Reader = new FileReader();\n\n\t\t\t\t\t_one(Reader, _readerEvents, function (evt){\n\t\t\t\t\t\tvar isFile = evt.type != 'error';\n\t\t\t\t\t\tcallback(isFile);\n\t\t\t\t\t\tif( isFile ){\n\t\t\t\t\t\t\tReader.abort();\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\n\t\t\t\t\tReader.readAsDataURL(file);\n\t\t\t\t} catch( err ){\n\t\t\t\t\tcallback(false);\n\t\t\t\t}\n\t\t\t}\n\t\t\telse {\n\t\t\t\tcallback(null);\n\t\t\t}\n\t\t}\n\t\telse {\n\t\t\tcallback(true);\n\t\t}\n\t}\n\n\n\tfunction _getAsEntry(item){\n\t\tvar entry;\n\t\tif( item.getAsEntry ){ entry = item.getAsEntry(); }\n\t\telse if( item.webkitGetAsEntry ){ entry = item.webkitGetAsEntry(); }\n\t\treturn\tentry;\n\t}\n\n\n\tfunction _readEntryAsFiles(entry, callback){\n\t\tif( !entry ){\n\t\t\t// error\n\t\t\tcallback('invalid entry');\n\t\t}\n\t\telse if( entry.isFile ){\n\t\t\t// Read as file\n\t\t\tentry.file(function(file){\n\t\t\t\t// success\n\t\t\t\tfile.fullPath = entry.fullPath;\n\t\t\t\tcallback(false, [file]);\n\t\t\t}, function (err){\n\t\t\t\t// error\n\t\t\t\tcallback('FileError.code: '+err.code);\n\t\t\t});\n\t\t}\n\t\telse if( entry.isDirectory ){\n\t\t\tvar reader = entry.createReader(), result = [];\n\n\t\t\treader.readEntries(function(entries){\n\t\t\t\t// success\n\t\t\t\tapi.afor(entries, function (next, entry){\n\t\t\t\t\t_readEntryAsFiles(entry, function (err, files){\n\t\t\t\t\t\tif( err ){\n\t\t\t\t\t\t\tapi.log(err);\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse {\n\t\t\t\t\t\t\tresult = result.concat(files);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif( next ){\n\t\t\t\t\t\t\tnext();\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse {\n\t\t\t\t\t\t\tcallback(false, result);\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t});\n\t\t\t}, function (err){\n\t\t\t\t// error\n\t\t\t\tcallback('directory_reader: ' + err);\n\t\t\t});\n\t\t}\n\t\telse {\n\t\t\t_readEntryAsFiles(_getAsEntry(entry), callback);\n\t\t}\n\t}\n\n\n\tfunction _simpleClone(obj){\n\t\tvar copy = {};\n\t\t_each(obj, function (val, key){\n\t\t\tif( val && (typeof val === 'object') && (val.nodeType === void 0) ){\n\t\t\t\tval = _extend({}, val);\n\t\t\t}\n\t\t\tcopy[key] = val;\n\t\t});\n\t\treturn\tcopy;\n\t}\n\n\n\tfunction isInputFile(el){\n\t\treturn\t_rinput.test(el && el.tagName);\n\t}\n\n\n\tfunction _getDataTransfer(evt){\n\t\treturn\t(evt.originalEvent || evt || '').dataTransfer || {};\n\t}\n\n\n\tfunction _isOriginTransform(trans){\n\t\tvar key;\n\t\tfor( key in trans ){\n\t\t\tif( trans.hasOwnProperty(key) ){\n\t\t\t\tif( !(trans[key] instanceof Object || key === 'overlay' || key === 'filter') ){\n\t\t\t\t\treturn\ttrue;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn\tfalse;\n\t}\n\n\n\t// Add default image info reader\n\tapi.addInfoReader(/^image/, function (file/**File*/, callback/**Function*/){\n\t\tif( !file.__dimensions ){\n\t\t\tvar defer = file.__dimensions = api.defer();\n\n\t\t\tapi.readAsImage(file, function (evt){\n\t\t\t\tvar img = evt.target;\n\t\t\t\tdefer.resolve(evt.type == 'load' ? false : 'error', {\n\t\t\t\t\t  width:  img.width\n\t\t\t\t\t, height: img.height\n\t\t\t\t});\n                img.src = api.EMPTY_PNG;\n\t\t\t\timg = null;\n\t\t\t});\n\t\t}\n\n\t\tfile.__dimensions.then(callback);\n\t});\n\n\n\t/**\n\t * Drag'n'Drop special event\n\t *\n\t * @param\t{HTMLElement}\tel\n\t * @param\t{Function}\t\tonHover\n\t * @param\t{Function}\t\tonDrop\n\t */\n\tapi.event.dnd = function (el, onHover, onDrop){\n\t\tvar _id, _type;\n\n\t\tif( !onDrop ){\n\t\t\tonDrop = onHover;\n\t\t\tonHover = api.F;\n\t\t}\n\n\t\tif( FileReader ){\n\t\t\t// Hover\n\t\t\t_on(el, 'dragenter dragleave dragover', onHover.ff = onHover.ff || function (evt){\n\t\t\t\tvar\n\t\t\t\t\t  types = _getDataTransfer(evt).types\n\t\t\t\t\t, i = types && types.length\n\t\t\t\t\t, debounceTrigger = false\n\t\t\t\t;\n\n\t\t\t\twhile( i-- ){\n\t\t\t\t\tif( ~types[i].indexOf('File') ){\n\t\t\t\t\t\tevt[preventDefault]();\n\n\t\t\t\t\t\tif( _type !== evt.type ){\n\t\t\t\t\t\t\t_type = evt.type; // Store current type of event\n\n\t\t\t\t\t\t\tif( _type != 'dragleave' ){\n\t\t\t\t\t\t\t\tonHover.call(evt[currentTarget], true, evt);\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tdebounceTrigger = true;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tbreak; // exit from \"while\"\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif( debounceTrigger ){\n\t\t\t\t\tclearTimeout(_id);\n\t\t\t\t\t_id = setTimeout(function (){\n\t\t\t\t\t\tonHover.call(evt[currentTarget], _type != 'dragleave', evt);\n\t\t\t\t\t}, 50);\n\t\t\t\t}\n\t\t\t});\n\n\n\t\t\t// Drop\n\t\t\t_on(el, 'drop', onDrop.ff = onDrop.ff || function (evt){\n\t\t\t\tevt[preventDefault]();\n\n\t\t\t\t_type = 0;\n\t\t\t\tonHover.call(evt[currentTarget], false, evt);\n\n\t\t\t\tapi.getDropFiles(evt, function (files){\n\t\t\t\t\tonDrop.call(evt[currentTarget], files, evt);\n\t\t\t\t});\n\t\t\t});\n\t\t}\n\t\telse {\n\t\t\tapi.log(\"Drag'n'Drop -- not supported\");\n\t\t}\n\t};\n\n\n\t/**\n\t * Remove drag'n'drop\n\t * @param\t{HTMLElement}\tel\n\t * @param\t{Function}\t\tonHover\n\t * @param\t{Function}\t\tonDrop\n\t */\n\tapi.event.dnd.off = function (el, onHover, onDrop){\n\t\t_off(el, 'dragenter dragleave dragover', onHover.ff);\n\t\t_off(el, 'drop', onDrop.ff);\n\t};\n\n\n\t// Support jQuery\n\tif( jQuery && !jQuery.fn.dnd ){\n\t\tjQuery.fn.dnd = function (onHover, onDrop){\n\t\t\treturn this.each(function (){\n\t\t\t\tapi.event.dnd(this, onHover, onDrop);\n\t\t\t});\n\t\t};\n\n\t\tjQuery.fn.offdnd = function (onHover, onDrop){\n\t\t\treturn this.each(function (){\n\t\t\t\tapi.event.dnd.off(this, onHover, onDrop);\n\t\t\t});\n\t\t};\n\t}\n\n\t// @export\n\twindow.FileAPI  = _extend(api, window.FileAPI);\n\n\n\t// Debug info\n\tapi.log('FileAPI: ' + api.version);\n\tapi.log('protocol: ' + window.location.protocol);\n\tapi.log('doctype: [' + doctype.name + '] ' + doctype.publicId + ' ' + doctype.systemId);\n\n\n\t// @detect 'x-ua-compatible'\n\t_each(document.getElementsByTagName('meta'), function (meta){\n\t\tif( /x-ua-compatible/i.test(meta.getAttribute('http-equiv')) ){\n\t\t\tapi.log('meta.http-equiv: ' + meta.getAttribute('content'));\n\t\t}\n\t});\n\n\n\t// configuration\n\ttry {\n\t\tapi._supportConsoleLog = !!console.log;\n\t\tapi._supportConsoleLogApply = !!console.log.apply;\n\t} catch (err) {}\n\n\tif( !api.flashUrl ){ api.flashUrl = api.staticPath + 'FileAPI.flash.swf'; }\n\tif( !api.flashImageUrl ){ api.flashImageUrl = api.staticPath + 'FileAPI.flash.image.swf'; }\n\tif( !api.flashWebcamUrl ){ api.flashWebcamUrl = api.staticPath + 'FileAPI.flash.camera.swf'; }\n})(window, void 0);\n\n/*global window, FileAPI, document */\n\n(function (api, document, undef) {\n\t'use strict';\n\n\tvar\n\t\tmin = Math.min,\n\t\tround = Math.round,\n\t\tgetCanvas = function () { return document.createElement('canvas'); },\n\t\tsupport = false,\n\t\texifOrientation = {\n\t\t\t  8:\t270\n\t\t\t, 3:\t180\n\t\t\t, 6:\t90\n\t\t\t, 7:\t270\n\t\t\t, 4:\t180\n\t\t\t, 5:\t90\n\t\t}\n\t;\n\n\ttry {\n\t\tsupport = getCanvas().toDataURL('image/png').indexOf('data:image/png') > -1;\n\t}\n\tcatch (e){}\n\n\n\tfunction Image(file){\n\t\tif( file instanceof Image ){\n\t\t\tvar img = new Image(file.file);\n\t\t\tapi.extend(img.matrix, file.matrix);\n\t\t\treturn\timg;\n\t\t}\n\t\telse if( !(this instanceof Image) ){\n\t\t\treturn\tnew Image(file);\n\t\t}\n\n\t\tthis.file   = file;\n\t\tthis.size   = file.size || 100;\n\n\t\tthis.matrix\t= {\n\t\t\tsx: 0,\n\t\t\tsy: 0,\n\t\t\tsw: 0,\n\t\t\tsh: 0,\n\t\t\tdx: 0,\n\t\t\tdy: 0,\n\t\t\tdw: 0,\n\t\t\tdh: 0,\n\t\t\tresize: 0, // min, max OR preview\n\t\t\tdeg: 0,\n\t\t\tquality: 1, // jpeg quality\n\t\t\tfilter: 0\n\t\t};\n\t}\n\n\n\tImage.prototype = {\n\t\timage: true,\n\t\tconstructor: Image,\n\n\t\tset: function (attrs){\n\t\t\tapi.extend(this.matrix, attrs);\n\t\t\treturn\tthis;\n\t\t},\n\n\t\tcrop: function (x, y, w, h){\n\t\t\tif( w === undef ){\n\t\t\t\tw\t= x;\n\t\t\t\th\t= y;\n\t\t\t\tx = y = 0;\n\t\t\t}\n\t\t\treturn\tthis.set({ sx: x, sy: y, sw: w, sh: h || w });\n\t\t},\n\n\t\tresize: function (w, h, strategy){\n\t\t\tif( /min|max/.test(h) ){\n\t\t\t\tstrategy = h;\n\t\t\t\th = w;\n\t\t\t}\n\n\t\t\treturn\tthis.set({ dw: w, dh: h || w, resize: strategy });\n\t\t},\n\n\t\tpreview: function (w, h){\n\t\t\treturn\tthis.resize(w, h || w, 'preview');\n\t\t},\n\n\t\trotate: function (deg){\n\t\t\treturn\tthis.set({ deg: deg });\n\t\t},\n\n\t\tfilter: function (filter){\n\t\t\treturn\tthis.set({ filter: filter });\n\t\t},\n\n\t\toverlay: function (images){\n\t\t\treturn\tthis.set({ overlay: images });\n\t\t},\n\n\t\tclone: function (){\n\t\t\treturn\tnew Image(this);\n\t\t},\n\n\t\t_load: function (image, fn){\n\t\t\tvar self = this;\n\n\t\t\tif( /img|video/i.test(image.nodeName) ){\n\t\t\t\tfn.call(self, null, image);\n\t\t\t}\n\t\t\telse {\n\t\t\t\tapi.readAsImage(image, function (evt){\n\t\t\t\t\tfn.call(self, evt.type != 'load', evt.result);\n\t\t\t\t});\n\t\t\t}\n\t\t},\n\n\t\t_apply: function (image, fn){\n\t\t\tvar\n\t\t\t\t  canvas = getCanvas()\n\t\t\t\t, m = this.getMatrix(image)\n\t\t\t\t, ctx = canvas.getContext('2d')\n\t\t\t\t, width = image.videoWidth || image.width\n\t\t\t\t, height = image.videoHeight || image.height\n\t\t\t\t, deg = m.deg\n\t\t\t\t, dw = m.dw\n\t\t\t\t, dh = m.dh\n\t\t\t\t, w = width\n\t\t\t\t, h = height\n\t\t\t\t, filter = m.filter\n\t\t\t\t, copy // canvas copy\n\t\t\t\t, buffer = image\n\t\t\t\t, overlay = m.overlay\n\t\t\t\t, queue = api.queue(function (){ image.src = api.EMPTY_PNG; fn(false, canvas); })\n\t\t\t\t, renderImageToCanvas = api.renderImageToCanvas\n\t\t\t;\n\n\t\t\t// Normalize angle\n\t\t\tdeg = deg - Math.floor(deg/360)*360;\n\n\t\t\t// For `renderImageToCanvas`\n\t\t\timage._type = this.file.type;\n\n\t\t\twhile(m.multipass && min(w/dw, h/dh) > 2 ){\n\t\t\t\tw = (w/2 + 0.5)|0;\n\t\t\t\th = (h/2 + 0.5)|0;\n\n\t\t\t\tcopy = getCanvas();\n\t\t\t\tcopy.width  = w;\n\t\t\t\tcopy.height = h;\n\n\t\t\t\tif( buffer !== image ){\n\t\t\t\t\trenderImageToCanvas(copy, buffer, 0, 0, buffer.width, buffer.height, 0, 0, w, h);\n\t\t\t\t\tbuffer = copy;\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tbuffer = copy;\n\t\t\t\t\trenderImageToCanvas(buffer, image, m.sx, m.sy, m.sw, m.sh, 0, 0, w, h);\n\t\t\t\t\tm.sx = m.sy = m.sw = m.sh = 0;\n\t\t\t\t}\n\t\t\t}\n\n\n\t\t\tcanvas.width  = (deg % 180) ? dh : dw;\n\t\t\tcanvas.height = (deg % 180) ? dw : dh;\n\n\t\t\tcanvas.type = m.type;\n\t\t\tcanvas.quality = m.quality;\n\n\t\t\tctx.rotate(deg * Math.PI / 180);\n\t\t\trenderImageToCanvas(ctx.canvas, buffer\n\t\t\t\t, m.sx, m.sy\n\t\t\t\t, m.sw || buffer.width\n\t\t\t\t, m.sh || buffer.height\n\t\t\t\t, (deg == 180 || deg == 270 ? -dw : 0)\n\t\t\t\t, (deg == 90 || deg == 180 ? -dh : 0)\n\t\t\t\t, dw, dh\n\t\t\t);\n\t\t\tdw = canvas.width;\n\t\t\tdh = canvas.height;\n\n\t\t\t// Apply overlay\n\t\t\toverlay && api.each([].concat(overlay), function (over){\n\t\t\t\tqueue.inc();\n\t\t\t\t// preload\n\t\t\t\tvar img = new window.Image, fn = function (){\n\t\t\t\t\tvar\n\t\t\t\t\t\t  x = over.x|0\n\t\t\t\t\t\t, y = over.y|0\n\t\t\t\t\t\t, w = over.w || img.width\n\t\t\t\t\t\t, h = over.h || img.height\n\t\t\t\t\t\t, rel = over.rel\n\t\t\t\t\t;\n\n\t\t\t\t\t// center  |  right  |  left\n\t\t\t\t\tx = (rel == 1 || rel == 4 || rel == 7) ? (dw - w + x)/2 : (rel == 2 || rel == 5 || rel == 8 ? dw - (w + x) : x);\n\n\t\t\t\t\t// center  |  bottom  |  top\n\t\t\t\t\ty = (rel == 3 || rel == 4 || rel == 5) ? (dh - h + y)/2 : (rel >= 6 ? dh - (h + y) : y);\n\n\t\t\t\t\tapi.event.off(img, 'error load abort', fn);\n\n\t\t\t\t\ttry {\n\t\t\t\t\t\tctx.globalAlpha = over.opacity || 1;\n\t\t\t\t\t\tctx.drawImage(img, x, y, w, h);\n\t\t\t\t\t}\n\t\t\t\t\tcatch (er){}\n\n\t\t\t\t\tqueue.next();\n\t\t\t\t};\n\n\t\t\t\tapi.event.on(img, 'error load abort', fn);\n\t\t\t\timg.src = over.src;\n\n\t\t\t\tif( img.complete ){\n\t\t\t\t\tfn();\n\t\t\t\t}\n\t\t\t});\n\n\t\t\tif( filter ){\n\t\t\t\tqueue.inc();\n\t\t\t\tImage.applyFilter(canvas, filter, queue.next);\n\t\t\t}\n\n\t\t\tqueue.check();\n\t\t},\n\n\t\tgetMatrix: function (image){\n\t\t\tvar\n\t\t\t\t  m  = api.extend({}, this.matrix)\n\t\t\t\t, sw = m.sw = m.sw || image.videoWidth || image.naturalWidth ||  image.width\n\t\t\t\t, sh = m.sh = m.sh || image.videoHeight || image.naturalHeight || image.height\n\t\t\t\t, dw = m.dw = m.dw || sw\n\t\t\t\t, dh = m.dh = m.dh || sh\n\t\t\t\t, sf = sw/sh, df = dw/dh\n\t\t\t\t, strategy = m.resize\n\t\t\t;\n\n\t\t\tif( strategy == 'preview' ){\n\t\t\t\tif( dw != sw || dh != sh ){\n\t\t\t\t\t// Make preview\n\t\t\t\t\tvar w, h;\n\n\t\t\t\t\tif( df >= sf ){\n\t\t\t\t\t\tw\t= sw;\n\t\t\t\t\t\th\t= w / df;\n\t\t\t\t\t} else {\n\t\t\t\t\t\th\t= sh;\n\t\t\t\t\t\tw\t= h * df;\n\t\t\t\t\t}\n\n\t\t\t\t\tif( w != sw || h != sh ){\n\t\t\t\t\t\tm.sx\t= ~~((sw - w)/2);\n\t\t\t\t\t\tm.sy\t= ~~((sh - h)/2);\n\t\t\t\t\t\tsw\t\t= w;\n\t\t\t\t\t\tsh\t\t= h;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\telse if( strategy ){\n\t\t\t\tif( !(sw > dw || sh > dh) ){\n\t\t\t\t\tdw = sw;\n\t\t\t\t\tdh = sh;\n\t\t\t\t}\n\t\t\t\telse if( strategy == 'min' ){\n\t\t\t\t\tdw = round(sf < df ? min(sw, dw) : dh*sf);\n\t\t\t\t\tdh = round(sf < df ? dw/sf : min(sh, dh));\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tdw = round(sf >= df ? min(sw, dw) : dh*sf);\n\t\t\t\t\tdh = round(sf >= df ? dw/sf : min(sh, dh));\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tm.sw = sw;\n\t\t\tm.sh = sh;\n\t\t\tm.dw = dw;\n\t\t\tm.dh = dh;\n\t\t\tm.multipass = api.multiPassResize;\n\t\t\treturn\tm;\n\t\t},\n\n\t\t_trans: function (fn){\n\t\t\tthis._load(this.file, function (err, image){\n\t\t\t\tif( err ){\n\t\t\t\t\tfn(err);\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tthis._apply(image, fn);\n\t\t\t\t\t} catch (err){\n\t\t\t\t\t\tapi.log('[err] FileAPI.Image.fn._apply:', err);\n\t\t\t\t\t\tfn(err);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t},\n\n\n\t\tget: function (fn){\n\t\t\tif( api.support.transform ){\n\t\t\t\tvar _this = this, matrix = _this.matrix;\n\n\t\t\t\tif( matrix.deg == 'auto' ){\n\t\t\t\t\tapi.getInfo(_this.file, function (err, info){\n\t\t\t\t\t\t// rotate by exif orientation\n\t\t\t\t\t\tmatrix.deg = exifOrientation[info && info.exif && info.exif.Orientation] || 0;\n\t\t\t\t\t\t_this._trans(fn);\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\t_this._trans(fn);\n\t\t\t\t}\n\t\t\t}\n\t\t\telse {\n\t\t\t\tfn('not_support_transform');\n\t\t\t}\n\n\t\t\treturn this;\n\t\t},\n\n\n\t\ttoData: function (fn){\n\t\t\treturn this.get(fn);\n\t\t}\n\n\t};\n\n\n\tImage.exifOrientation = exifOrientation;\n\n\n\tImage.transform = function (file, transform, autoOrientation, fn){\n\t\tfunction _transform(err, img){\n\t\t\t// img -- info object\n\t\t\tvar\n\t\t\t\t  images = {}\n\t\t\t\t, queue = api.queue(function (err){\n\t\t\t\t\tfn(err, images);\n\t\t\t\t})\n\t\t\t;\n\n\t\t\tif( !err ){\n\t\t\t\tapi.each(transform, function (params, name){\n\t\t\t\t\tif( !queue.isFail() ){\n\t\t\t\t\t\tvar ImgTrans = new Image(img.nodeType ? img : file), isFn = typeof params == 'function';\n\n\t\t\t\t\t\tif( isFn ){\n\t\t\t\t\t\t\tparams(img, ImgTrans);\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse if( params.width ){\n\t\t\t\t\t\t\tImgTrans[params.preview ? 'preview' : 'resize'](params.width, params.height, params.strategy);\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse {\n\t\t\t\t\t\t\tif( params.maxWidth && (img.width > params.maxWidth || img.height > params.maxHeight) ){\n\t\t\t\t\t\t\t\tImgTrans.resize(params.maxWidth, params.maxHeight, 'max');\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif( params.crop ){\n\t\t\t\t\t\t\tvar crop = params.crop;\n\t\t\t\t\t\t\tImgTrans.crop(crop.x|0, crop.y|0, crop.w || crop.width, crop.h || crop.height);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif( params.rotate === undef && autoOrientation ){\n\t\t\t\t\t\t\tparams.rotate = 'auto';\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tImgTrans.set({ type: ImgTrans.matrix.type || params.type || file.type || 'image/png' });\n\n\t\t\t\t\t\tif( !isFn ){\n\t\t\t\t\t\t\tImgTrans.set({\n\t\t\t\t\t\t\t\t  deg: params.rotate\n\t\t\t\t\t\t\t\t, overlay: params.overlay\n\t\t\t\t\t\t\t\t, filter: params.filter\n\t\t\t\t\t\t\t\t, quality: params.quality || 1\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tqueue.inc();\n\t\t\t\t\t\tImgTrans.toData(function (err, image){\n\t\t\t\t\t\t\tif( err ){\n\t\t\t\t\t\t\t\tqueue.fail();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse {\n\t\t\t\t\t\t\t\timages[name] = image;\n\t\t\t\t\t\t\t\tqueue.next();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t\telse {\n\t\t\t\tqueue.fail();\n\t\t\t}\n\t\t}\n\n\n\t\t// @todo: Оло-ло, нужно рефакторить это место\n\t\tif( file.width ){\n\t\t\t_transform(false, file);\n\t\t} else {\n\t\t\tapi.getInfo(file, _transform);\n\t\t}\n\t};\n\n\n\t// @const\n\tapi.each(['TOP', 'CENTER', 'BOTTOM'], function (x, i){\n\t\tapi.each(['LEFT', 'CENTER', 'RIGHT'], function (y, j){\n\t\t\tImage[x+'_'+y] = i*3 + j;\n\t\t\tImage[y+'_'+x] = i*3 + j;\n\t\t});\n\t});\n\n\n\t/**\n\t * Trabsform element to canvas\n\t *\n\t * @param    {Image|HTMLVideoElement}   el\n\t * @returns  {Canvas}\n\t */\n\tImage.toCanvas = function(el){\n\t\tvar canvas\t\t= document.createElement('canvas');\n\t\tcanvas.width\t= el.videoWidth || el.width;\n\t\tcanvas.height\t= el.videoHeight || el.height;\n\t\tcanvas.getContext('2d').drawImage(el, 0, 0);\n\t\treturn\tcanvas;\n\t};\n\n\n\t/**\n\t * Create image from DataURL\n\t * @param  {String}  dataURL\n\t * @param  {Object}  size\n\t * @param  {Function}  callback\n\t */\n\tImage.fromDataURL = function (dataURL, size, callback){\n\t\tvar img = api.newImage(dataURL);\n\t\tapi.extend(img, size);\n\t\tcallback(img);\n\t};\n\n\n\t/**\n\t * Apply filter (caman.js)\n\t *\n\t * @param  {Canvas|Image}   canvas\n\t * @param  {String|Function}  filter\n\t * @param  {Function}  doneFn\n\t */\n\tImage.applyFilter = function (canvas, filter, doneFn){\n\t\tif( typeof filter == 'function' ){\n\t\t\tfilter(canvas, doneFn);\n\t\t}\n\t\telse if( window.Caman ){\n\t\t\t// http://camanjs.com/guides/\n\t\t\twindow.Caman(canvas.tagName == 'IMG' ? Image.toCanvas(canvas) : canvas, function (){\n\t\t\t\tif( typeof filter == 'string' ){\n\t\t\t\t\tthis[filter]();\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tapi.each(filter, function (val, method){\n\t\t\t\t\t\tthis[method](val);\n\t\t\t\t\t}, this);\n\t\t\t\t}\n\t\t\t\tthis.render(doneFn);\n\t\t\t});\n\t\t}\n\t};\n\n\n\t/**\n\t * For load-image-ios.js\n\t */\n\tapi.renderImageToCanvas = function (canvas, img, sx, sy, sw, sh, dx, dy, dw, dh){\n\t\ttry {\n\t\t\treturn canvas.getContext('2d').drawImage(img, sx, sy, sw, sh, dx, dy, dw, dh);\n\t\t} catch (ex) {\n\t\t\tapi.log('renderImageToCanvas failed');\n\t\t\tthrow ex;\n\t\t}\n\t};\n\n\n\t// @export\n\tapi.support.canvas = api.support.transform = support;\n\tapi.Image = Image;\n})(FileAPI, document);\n\n/*\n * JavaScript Load Image iOS scaling fixes 1.0.3\n * https://github.com/blueimp/JavaScript-Load-Image\n *\n * Copyright 2013, Sebastian Tschan\n * https://blueimp.net\n *\n * iOS image scaling fixes based on\n * https://github.com/stomita/ios-imagefile-megapixel\n *\n * Licensed under the MIT license:\n * http://www.opensource.org/licenses/MIT\n */\n\n/*jslint nomen: true, bitwise: true */\n/*global FileAPI, window, document */\n\n(function (factory) {\n\t'use strict';\n\tfactory(FileAPI);\n}(function (loadImage) {\n    'use strict';\n\n    // Only apply fixes on the iOS platform:\n    if (!window.navigator || !window.navigator.platform ||\n             !(/iP(hone|od|ad)/).test(window.navigator.platform)) {\n        return;\n    }\n\n    var originalRenderMethod = loadImage.renderImageToCanvas;\n\n    // Detects subsampling in JPEG images:\n    loadImage.detectSubsampling = function (img) {\n        var canvas,\n            context;\n        if (img.width * img.height > 1024 * 1024) { // only consider mexapixel images\n            canvas = document.createElement('canvas');\n            canvas.width = canvas.height = 1;\n            context = canvas.getContext('2d');\n            context.drawImage(img, -img.width + 1, 0);\n            // subsampled image becomes half smaller in rendering size.\n            // check alpha channel value to confirm image is covering edge pixel or not.\n            // if alpha value is 0 image is not covering, hence subsampled.\n            return context.getImageData(0, 0, 1, 1).data[3] === 0;\n        }\n        return false;\n    };\n\n    // Detects vertical squash in JPEG images:\n    loadImage.detectVerticalSquash = function (img, subsampled) {\n        var naturalHeight = img.naturalHeight || img.height,\n            canvas = document.createElement('canvas'),\n            context = canvas.getContext('2d'),\n            data,\n            sy,\n            ey,\n            py,\n            alpha;\n        if (subsampled) {\n            naturalHeight /= 2;\n        }\n        canvas.width = 1;\n        canvas.height = naturalHeight;\n        context.drawImage(img, 0, 0);\n        data = context.getImageData(0, 0, 1, naturalHeight).data;\n        // search image edge pixel position in case it is squashed vertically:\n        sy = 0;\n        ey = naturalHeight;\n        py = naturalHeight;\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        return (py / naturalHeight) || 1;\n    };\n\n    // Renders image to canvas while working around iOS image scaling bugs:\n    // https://github.com/blueimp/JavaScript-Load-Image/issues/13\n    loadImage.renderImageToCanvas = function (\n        canvas,\n        img,\n        sourceX,\n        sourceY,\n        sourceWidth,\n        sourceHeight,\n        destX,\n        destY,\n        destWidth,\n        destHeight\n    ) {\n        if (img._type === 'image/jpeg') {\n            var context = canvas.getContext('2d'),\n                tmpCanvas = document.createElement('canvas'),\n                tileSize = 1024,\n                tmpContext = tmpCanvas.getContext('2d'),\n                subsampled,\n                vertSquashRatio,\n                tileX,\n                tileY;\n            tmpCanvas.width = tileSize;\n            tmpCanvas.height = tileSize;\n            context.save();\n            subsampled = loadImage.detectSubsampling(img);\n            if (subsampled) {\n                sourceX /= 2;\n                sourceY /= 2;\n                sourceWidth /= 2;\n                sourceHeight /= 2;\n            }\n            vertSquashRatio = loadImage.detectVerticalSquash(img, subsampled);\n            if (subsampled || vertSquashRatio !== 1) {\n                sourceY *= vertSquashRatio;\n                destWidth = Math.ceil(tileSize * destWidth / sourceWidth);\n                destHeight = Math.ceil(\n                    tileSize * destHeight / sourceHeight / vertSquashRatio\n                );\n                destY = 0;\n                tileY = 0;\n                while (tileY < sourceHeight) {\n                    destX = 0;\n                    tileX = 0;\n                    while (tileX < sourceWidth) {\n                        tmpContext.clearRect(0, 0, tileSize, tileSize);\n                        tmpContext.drawImage(\n                            img,\n                            sourceX,\n                            sourceY,\n                            sourceWidth,\n                            sourceHeight,\n                            -tileX,\n                            -tileY,\n                            sourceWidth,\n                            sourceHeight\n                        );\n                        context.drawImage(\n                            tmpCanvas,\n                            0,\n                            0,\n                            tileSize,\n                            tileSize,\n                            destX,\n                            destY,\n                            destWidth,\n                            destHeight\n                        );\n                        tileX += tileSize;\n                        destX += destWidth;\n                    }\n                    tileY += tileSize;\n                    destY += destHeight;\n                }\n                context.restore();\n                return canvas;\n            }\n        }\n        return originalRenderMethod(\n            canvas,\n            img,\n            sourceX,\n            sourceY,\n            sourceWidth,\n            sourceHeight,\n            destX,\n            destY,\n            destWidth,\n            destHeight\n        );\n    };\n\n}));\n\n/*global window, FileAPI */\n\n(function (api, window){\n\t\"use strict\";\n\n\tvar\n\t\t  document = window.document\n\t\t, FormData = window.FormData\n\t\t, Form = function (){ this.items = []; }\n\t\t, encodeURIComponent = window.encodeURIComponent\n\t;\n\n\n\tForm.prototype = {\n\n\t\tappend: function (name, blob, file, type){\n\t\t\tthis.items.push({\n\t\t\t\t  name: name\n\t\t\t\t, blob: blob && blob.blob || (blob == void 0 ? '' : blob)\n\t\t\t\t, file: blob && (file || blob.name)\n\t\t\t\t, type:\tblob && (type || blob.type)\n\t\t\t});\n\t\t},\n\n\t\teach: function (fn){\n\t\t\tvar i = 0, n = this.items.length;\n\t\t\tfor( ; i < n; i++ ){\n\t\t\t\tfn.call(this, this.items[i]);\n\t\t\t}\n\t\t},\n\n\t\ttoData: function (fn, options){\n\t\t    // allow chunked transfer if we have only one file to send\n\t\t    // flag is used below and in XHR._send\n\t\t    options._chunked = api.support.chunked && options.chunkSize > 0 && api.filter(this.items, function (item){ return item.file; }).length == 1;\n\n\t\t\tif( !api.support.html5 ){\n\t\t\t\tapi.log('FileAPI.Form.toHtmlData');\n\t\t\t\tthis.toHtmlData(fn);\n\t\t\t}\n\t\t\telse if( !api.formData || this.multipart || !FormData ){\n\t\t\t\tapi.log('FileAPI.Form.toMultipartData');\n\t\t\t\tthis.toMultipartData(fn);\n\t\t\t}\n\t\t\telse if( options._chunked ){\n\t\t\t\tapi.log('FileAPI.Form.toPlainData');\n\t\t\t\tthis.toPlainData(fn);\n\t\t\t}\n\t\t\telse {\n\t\t\t\tapi.log('FileAPI.Form.toFormData');\n\t\t\t\tthis.toFormData(fn);\n\t\t\t}\n\t\t},\n\n\t\t_to: function (data, complete, next, arg){\n\t\t\tvar queue = api.queue(function (){\n\t\t\t\tcomplete(data);\n\t\t\t});\n\n\t\t\tthis.each(function (file){\n\t\t\t\tnext(file, data, queue, arg);\n\t\t\t});\n\n\t\t\tqueue.check();\n\t\t},\n\n\n\t\ttoHtmlData: function (fn){\n\t\t\tthis._to(document.createDocumentFragment(), fn, function (file, data/**DocumentFragment*/){\n\t\t\t\tvar blob = file.blob, hidden;\n\n\t\t\t\tif( file.file ){\n\t\t\t\t\tapi.reset(blob, true);\n\t\t\t\t\t// set new name\n\t\t\t\t\tblob.name = file.name;\n\t\t\t\t\tblob.disabled = false;\n\t\t\t\t\tdata.appendChild(blob);\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\thidden = document.createElement('input');\n\t\t\t\t\thidden.name  = file.name;\n\t\t\t\t\thidden.type  = 'hidden';\n\t\t\t\t\thidden.value = blob;\n\t\t\t\t\tdata.appendChild(hidden);\n\t\t\t\t}\n\t\t\t});\n\t\t},\n\n\t\ttoPlainData: function (fn){\n\t\t\tthis._to({}, fn, function (file, data, queue){\n\t\t\t\tif( file.file ){\n\t\t\t\t\tdata.type = file.file;\n\t\t\t\t}\n\n\t\t\t\tif( file.blob.toBlob ){\n\t\t\t\t    // canvas\n\t\t\t\t\tqueue.inc();\n\t\t\t\t\t_convertFile(file, function (file, blob){\n\t\t\t\t\t\tdata.name = file.name;\n\t\t\t\t\t\tdata.file = blob;\n\t\t\t\t\t\tdata.size = blob.length;\n\t\t\t\t\t\tdata.type = file.type;\n\t\t\t\t\t\tqueue.next();\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\telse if( file.file ){\n\t\t\t\t    // file\n\t\t\t\t\tdata.name = file.blob.name;\n\t\t\t\t\tdata.file = file.blob;\n\t\t\t\t\tdata.size = file.blob.size;\n\t\t\t\t\tdata.type = file.type;\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t    // additional data\n\t\t\t\t    if( !data.params ){\n\t\t\t\t        data.params = [];\n\t\t\t\t    }\n\t\t\t\t    data.params.push(encodeURIComponent(file.name) +\"=\"+ encodeURIComponent(file.blob));\n\t\t\t\t}\n\n\t\t\t\tdata.start = -1;\n\t\t\t\tdata.end = data.file && data.file.FileAPIReadPosition || -1;\n\t\t\t\tdata.retry = 0;\n\t\t\t});\n\t\t},\n\n\t\ttoFormData: function (fn){\n\t\t\tthis._to(new FormData, fn, function (file, data, queue){\n\t\t\t\tif( file.blob && file.blob.toBlob ){\n\t\t\t\t\tqueue.inc();\n\t\t\t\t\t_convertFile(file, function (file, blob){\n\t\t\t\t\t\tdata.append(file.name, blob, file.file);\n\t\t\t\t\t\tqueue.next();\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\telse if( file.file ){\n\t\t\t\t\tdata.append(file.name, file.blob, file.file);\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tdata.append(file.name, file.blob);\n\t\t\t\t}\n\n\t\t\t\tif( file.file ){\n\t\t\t\t\tdata.append('_'+file.name, file.file);\n\t\t\t\t}\n\t\t\t});\n\t\t},\n\n\n\t\ttoMultipartData: function (fn){\n\t\t\tthis._to([], fn, function (file, data, queue, boundary){\n\t\t\t\tqueue.inc();\n\t\t\t\t_convertFile(file, function (file, blob){\n\t\t\t\t\tdata.push(\n\t\t\t\t\t\t  '--_' + boundary + ('\\r\\nContent-Disposition: form-data; name=\"'+ file.name +'\"'+ (file.file ? '; filename=\"'+ encodeURIComponent(file.file) +'\"' : '')\n\t\t\t\t\t\t+ (file.file ? '\\r\\nContent-Type: '+ (file.type || 'application/octet-stream') : '')\n\t\t\t\t\t\t+ '\\r\\n'\n\t\t\t\t\t\t+ '\\r\\n'+ (file.file ? blob : encodeURIComponent(blob))\n\t\t\t\t\t\t+ '\\r\\n')\n\t\t\t\t\t);\n\t\t\t\t\tqueue.next();\n\t\t\t\t}, true);\n\t\t\t}, api.expando);\n\t\t}\n\t};\n\n\n\tfunction _convertFile(file, fn, useBinaryString){\n\t\tvar blob = file.blob, filename = file.file;\n\n\t\tif( filename ){\n\t\t\tif( !blob.toDataURL ){\n\t\t\t\t// The Blob is not an image.\n\t\t\t\tapi.readAsBinaryString(blob, function (evt){\n\t\t\t\t\tif( evt.type == 'load' ){\n\t\t\t\t\t\tfn(file, evt.result);\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tvar\n\t\t\t\t  mime = { 'image/jpeg': '.jpe?g', 'image/png': '.png' }\n\t\t\t\t, type = mime[file.type] ? file.type : 'image/png'\n\t\t\t\t, ext  = mime[type] || '.png'\n\t\t\t\t, quality = blob.quality || 1\n\t\t\t;\n\n\t\t\tif( !filename.match(new RegExp(ext+'$', 'i')) ){\n\t\t\t\t// Does not change the current extension, but add a new one.\n\t\t\t\tfilename += ext.replace('?', '');\n\t\t\t}\n\n\t\t\tfile.file = filename;\n\t\t\tfile.type = type;\n\n\t\t\tif( !useBinaryString && blob.toBlob ){\n\t\t\t\tblob.toBlob(function (blob){\n\t\t\t\t\tfn(file, blob);\n\t\t\t\t}, type, quality);\n\t\t\t}\n\t\t\telse {\n\t\t\t\tfn(file, api.toBinaryString(blob.toDataURL(type, quality)));\n\t\t\t}\n\t\t}\n\t\telse {\n\t\t\tfn(file, blob);\n\t\t}\n\t}\n\n\n\t// @export\n\tapi.Form = Form;\n})(FileAPI, window);\n\n/*global window, FileAPI, Uint8Array */\n\n(function (window, api){\n\t\"use strict\";\n\n\tvar\n\t\t  noop = function (){}\n\t\t, document = window.document\n\n\t\t, XHR = function (options){\n\t\t\tthis.uid = api.uid();\n\t\t\tthis.xhr = {\n\t\t\t\t  abort: noop\n\t\t\t\t, getResponseHeader: noop\n\t\t\t\t, getAllResponseHeaders: noop\n\t\t\t};\n\t\t\tthis.options = options;\n\t\t},\n\n\t\t_xhrResponsePostfix = { '': 1, XML: 1, Text: 1, Body: 1 }\n\t;\n\n\n\tXHR.prototype = {\n\t\tstatus: 0,\n\t\tstatusText: '',\n\t\tconstructor: XHR,\n\n\t\tgetResponseHeader: function (name){\n\t\t\treturn this.xhr.getResponseHeader(name);\n\t\t},\n\n\t\tgetAllResponseHeaders: function (){\n\t\t\treturn this.xhr.getAllResponseHeaders() || {};\n\t\t},\n\n\t\tend: function (status, statusText){\n\t\t\tvar _this = this, options = _this.options;\n\n\t\t\t_this.end\t\t=\n\t\t\t_this.abort\t\t= noop;\n\t\t\t_this.status\t= status;\n\n\t\t\tif( statusText ){\n\t\t\t\t_this.statusText = statusText;\n\t\t\t}\n\n\t\t\tapi.log('xhr.end:', status, statusText);\n\t\t\toptions.complete(status == 200 || status == 201 ? false : _this.statusText || 'unknown', _this);\n\n\t\t\tif( _this.xhr && _this.xhr.node ){\n\t\t\t\tsetTimeout(function (){\n\t\t\t\t\tvar node = _this.xhr.node;\n\t\t\t\t\ttry { node.parentNode.removeChild(node); } catch (e){}\n\t\t\t\t\ttry { delete window[_this.uid]; } catch (e){}\n\t\t\t\t\twindow[_this.uid] = _this.xhr.node = null;\n\t\t\t\t}, 9);\n\t\t\t}\n\t\t},\n\n\t\tabort: function (){\n\t\t\tthis.end(0, 'abort');\n\n\t\t\tif( this.xhr ){\n\t\t\t\tthis.xhr.aborted = true;\n\t\t\t\tthis.xhr.abort();\n\t\t\t}\n\t\t},\n\n\t\tsend: function (FormData){\n\t\t\tvar _this = this, options = this.options;\n\n\t\t\tFormData.toData(function (data){\n\t\t\t\t// Start uploading\n\t\t\t\toptions.upload(options, _this);\n\t\t\t\t_this._send.call(_this, options, data);\n\t\t\t}, options);\n\t\t},\n\n\t\t_send: function (options, data){\n\t\t\tvar _this = this, xhr, uid = _this.uid, onloadFuncName = _this.uid + \"Load\", url = options.url;\n\n\t\t\tapi.log('XHR._send:', data);\n\n\t\t\tif( !options.cache ){\n\t\t\t\t// No cache\n\t\t\t\turl += (~url.indexOf('?') ? '&' : '?') + api.uid();\n\t\t\t}\n\n\t\t\tif( data.nodeName ){\n\t\t\t\tvar jsonp = options.jsonp;\n\n\t\t\t\t// prepare callback in GET\n\t\t\t\turl = url.replace(/([a-z]+)=(\\?)/i, '$1='+uid);\n\n\t\t\t\t// legacy\n\t\t\t\toptions.upload(options, _this);\n\n\t\t\t\tvar\n\t\t\t\t\tonPostMessage = function (evt){\n\t\t\t\t\t\tif( ~url.indexOf(evt.origin) ){\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\tvar result = api.parseJSON(evt.data);\n\t\t\t\t\t\t\t\tif( result.id == uid ){\n\t\t\t\t\t\t\t\t\tcomplete(result.status, result.statusText, result.response);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} catch( err ){\n\t\t\t\t\t\t\t\tcomplete(0, err.message);\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// jsonp-callack\n\t\t\t\t\tcomplete = window[uid] = function (status, statusText, response){\n\t\t\t\t\t\t_this.readyState\t= 4;\n\t\t\t\t\t\t_this.responseText\t= response;\n\t\t\t\t\t\t_this.end(status, statusText);\n\n\t\t\t\t\t\tapi.event.off(window, 'message', onPostMessage);\n\t\t\t\t\t\twindow[uid] = xhr = transport = window[onloadFuncName] = null;\n\t\t\t\t\t}\n\t\t\t\t;\n\n\t\t\t\t_this.xhr.abort = function (){\n\t\t\t\t\ttry {\n\t\t\t\t\t\tif( transport.stop ){ transport.stop(); }\n\t\t\t\t\t\telse if( transport.contentWindow.stop ){ transport.contentWindow.stop(); }\n\t\t\t\t\t\telse { transport.contentWindow.document.execCommand('Stop'); }\n\t\t\t\t\t}\n\t\t\t\t\tcatch (er) {}\n\t\t\t\t\tcomplete(0, \"abort\");\n\t\t\t\t};\n\n\t\t\t\tapi.event.on(window, 'message', onPostMessage);\n\n\t\t\t\twindow[onloadFuncName] = function (){\n\t\t\t\t\ttry {\n\t\t\t\t\t\tvar\n\t\t\t\t\t\t\t  win = transport.contentWindow\n\t\t\t\t\t\t\t, doc = win.document\n\t\t\t\t\t\t\t, result = win.result || api.parseJSON(doc.body.innerHTML)\n\t\t\t\t\t\t;\n\t\t\t\t\t\tcomplete(result.status, result.statusText, result.response);\n\t\t\t\t\t} catch (e){\n\t\t\t\t\t\tapi.log('[transport.onload]', e);\n\t\t\t\t\t}\n\t\t\t\t};\n\n\t\t\t\txhr = document.createElement('div');\n\t\t\t\txhr.innerHTML = '<form target=\"'+ uid +'\" action=\"'+ url +'\" method=\"POST\" enctype=\"multipart/form-data\" style=\"position: absolute; top: -1000px; overflow: hidden; width: 1px; height: 1px;\">'\n\t\t\t\t\t\t\t+ '<iframe name=\"'+ uid +'\" src=\"javascript:false;\" onload=\"' + onloadFuncName + '()\"></iframe>'\n\t\t\t\t\t\t\t+ (jsonp && (options.url.indexOf('=?') < 0) ? '<input value=\"'+ uid +'\" name=\"'+jsonp+'\" type=\"hidden\"/>' : '')\n\t\t\t\t\t\t\t+ '</form>'\n\t\t\t\t;\n\n\t\t\t\t// get form-data & transport\n\t\t\t\tvar\n\t\t\t\t\t  form = xhr.getElementsByTagName('form')[0]\n\t\t\t\t\t, transport = xhr.getElementsByTagName('iframe')[0]\n\t\t\t\t;\n\n\t\t\t\tform.appendChild(data);\n\n\t\t\t\tapi.log(form.parentNode.innerHTML);\n\n\t\t\t\t// append to DOM\n\t\t\t\tdocument.body.appendChild(xhr);\n\n\t\t\t\t// keep a reference to node-transport\n\t\t\t\t_this.xhr.node = xhr;\n\n\t\t\t\t// send\n\t\t\t\t_this.readyState = 2; // loaded\n\t\t\t\tform.submit();\n\t\t\t\tform = null;\n\t\t\t}\n\t\t\telse {\n\t\t\t\t// Clean url\n\t\t\t\turl = url.replace(/([a-z]+)=(\\?)&?/i, '');\n\n\t\t\t\t// html5\n\t\t\t\tif (this.xhr && this.xhr.aborted) {\n\t\t\t\t\tapi.log(\"Error: already aborted\");\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\txhr = _this.xhr = api.getXHR();\n\n\t\t\t\tif (data.params) {\n\t\t\t\t\turl += (url.indexOf('?') < 0 ? \"?\" : \"&\") + data.params.join(\"&\");\n\t\t\t\t}\n\n\t\t\t\txhr.open('POST', url, true);\n\n\t\t\t\tif( api.withCredentials ){\n\t\t\t\t\txhr.withCredentials = \"true\";\n\t\t\t\t}\n\n\t\t\t\tif( !options.headers || !options.headers['X-Requested-With'] ){\n\t\t\t\t\txhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');\n\t\t\t\t}\n\n\t\t\t\tapi.each(options.headers, function (val, key){\n\t\t\t\t\txhr.setRequestHeader(key, val);\n\t\t\t\t});\n\n\n\t\t\t\tif ( options._chunked ) {\n\t\t\t\t\t// chunked upload\n\t\t\t\t\tif( xhr.upload ){\n\t\t\t\t\t\txhr.upload.addEventListener('progress', api.throttle(function (/**Event*/evt){\n\t\t\t\t\t\t\tif (!data.retry) {\n\t\t\t\t\t\t\t\t// show progress only for correct chunk uploads\n\t\t\t\t\t\t\t\toptions.progress({\n\t\t\t\t\t\t\t\t\t  type:\t\t\tevt.type\n\t\t\t\t\t\t\t\t\t, total:\t\tdata.size\n\t\t\t\t\t\t\t\t\t, loaded:\t\tdata.start + evt.loaded\n\t\t\t\t\t\t\t\t\t, totalSize:\tdata.size\n\t\t\t\t\t\t\t\t}, _this, options);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}, 100), false);\n\t\t\t\t\t}\n\n\t\t\t\t\txhr.onreadystatechange = function (){\n\t\t\t\t\t\tvar lkb = parseInt(xhr.getResponseHeader('X-Last-Known-Byte'), 10);\n\n\t\t\t\t\t\t_this.status     = xhr.status;\n\t\t\t\t\t\t_this.statusText = xhr.statusText;\n\t\t\t\t\t\t_this.readyState = xhr.readyState;\n\n\t\t\t\t\t\tif( xhr.readyState == 4 ){\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\tfor( var k in _xhrResponsePostfix ){\n\t\t\t\t\t\t\t\t\t_this['response'+k]  = xhr['response'+k];\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}catch(_){}\n\t\t\t\t\t\t\txhr.onreadystatechange = null;\n\n\t\t\t\t\t\t\tif (!xhr.status || xhr.status - 201 > 0) {\n\t\t\t\t\t\t\t\tapi.log(\"Error: \" + xhr.status);\n\t\t\t\t\t\t\t\t// some kind of error\n\t\t\t\t\t\t\t\t// 0 - connection fail or timeout, if xhr.aborted is true, then it's not recoverable user action\n\t\t\t\t\t\t\t\t// up - server error\n\t\t\t\t\t\t\t\tif (((!xhr.status && !xhr.aborted) || 500 == xhr.status || 416 == xhr.status) && ++data.retry <= options.chunkUploadRetry) {\n\t\t\t\t\t\t\t\t\t// let's try again the same chunk\n\t\t\t\t\t\t\t\t\t// only applicable for recoverable error codes 500 && 416\n\t\t\t\t\t\t\t\t\tvar delay = xhr.status ? 0 : api.chunkNetworkDownRetryTimeout;\n\n\t\t\t\t\t\t\t\t\t// inform about recoverable problems\n\t\t\t\t\t\t\t\t\toptions.pause(data.file, options);\n\n\t\t\t\t\t\t\t\t\t// smart restart if server reports about the last known byte\n\t\t\t\t\t\t\t\t\tapi.log(\"X-Last-Known-Byte: \" + lkb);\n\t\t\t\t\t\t\t\t\tif (lkb) {\n\t\t\t\t\t\t\t\t\t\tdata.end = lkb;\n\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\tdata.end = data.start - 1;\n\t\t\t\t\t\t\t\t\t\tif (416 == xhr.status) {\n\t\t\t\t\t\t\t\t\t\t\tdata.end = data.end - options.chunkSize;\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\tsetTimeout(function () {\n\t\t\t\t\t\t\t\t\t\t_this._send(options, data);\n\t\t\t\t\t\t\t\t\t}, delay);\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t// no mo retries\n\t\t\t\t\t\t\t\t\t_this.end(xhr.status);\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\t// success\n\t\t\t\t\t\t\t\tdata.retry = 0;\n\n\t\t\t\t\t\t\t\tif (data.end == data.size - 1) {\n\t\t\t\t\t\t\t\t\t// finished\n\t\t\t\t\t\t\t\t\t_this.end(xhr.status);\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t// next chunk\n\n\t\t\t\t\t\t\t\t\t// shift position if server reports about the last known byte\n\t\t\t\t\t\t\t\t\tapi.log(\"X-Last-Known-Byte: \" + lkb);\n\t\t\t\t\t\t\t\t\tif (lkb) {\n\t\t\t\t\t\t\t\t\t\tdata.end = lkb;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tdata.file.FileAPIReadPosition = data.end;\n\n\t\t\t\t\t\t\t\t\tsetTimeout(function () {\n\t\t\t\t\t\t\t\t\t\t_this._send(options, data);\n\t\t\t\t\t\t\t\t\t}, 0);\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\txhr = null;\n\t\t\t\t\t\t}\n\t\t\t\t\t};\n\n\t\t\t\t\tdata.start = data.end + 1;\n\t\t\t\t\tdata.end = Math.max(Math.min(data.start + options.chunkSize, data.size) - 1, data.start);\n\n\t\t\t\t\t// Retrieve a slice of file\n\t\t\t\t\tvar\n\t\t\t\t\t\t  file = data.file\n\t\t\t\t\t\t, slice = (file.slice || file.mozSlice || file.webkitSlice).call(file, data.start, data.end + 1)\n\t\t\t\t\t;\n\n\t\t\t\t\tif( data.size && !slice.size ){\n\t\t\t\t\t\tsetTimeout(function (){\n\t\t\t\t\t\t\t_this.end(-1);\n\t\t\t\t\t\t});\n\t\t\t\t\t} else {\n\t\t\t\t\t\txhr.setRequestHeader(\"Content-Range\", \"bytes \" + data.start + \"-\" + data.end + \"/\" + data.size);\n\t\t\t\t\t\txhr.setRequestHeader(\"Content-Disposition\", 'attachment; filename=' + encodeURIComponent(data.name));\n\t\t\t\t\t\txhr.setRequestHeader(\"Content-Type\", data.type || \"application/octet-stream\");\n\n\t\t\t\t\t\txhr.send(slice);\n\t\t\t\t\t}\n\n\t\t\t\t\tfile = slice = null;\n\t\t\t\t} else {\n\t\t\t\t\t// single piece upload\n\t\t\t\t\tif( xhr.upload ){\n\t\t\t\t\t\t// https://github.com/blueimp/jQuery-File-Upload/wiki/Fixing-Safari-hanging-on-very-high-speed-connections-%281Gbps%29\n\t\t\t\t\t\txhr.upload.addEventListener('progress', api.throttle(function (/**Event*/evt){\n\t\t\t\t\t\t\toptions.progress(evt, _this, options);\n\t\t\t\t\t\t}, 100), false);\n\t\t\t\t\t}\n\n\t\t\t\t\txhr.onreadystatechange = function (){\n\t\t\t\t\t\t_this.status     = xhr.status;\n\t\t\t\t\t\t_this.statusText = xhr.statusText;\n\t\t\t\t\t\t_this.readyState = xhr.readyState;\n\n\t\t\t\t\t\tif( xhr.readyState == 4 ){\n\t\t\t\t\t\t\tfor( var k in _xhrResponsePostfix ){\n\t\t\t\t\t\t\t\t_this['response'+k]  = xhr['response'+k];\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\txhr.onreadystatechange = null;\n\n\t\t\t\t\t\t\tif (!xhr.status || xhr.status > 201) {\n\t\t\t\t\t\t\t\tapi.log(\"Error: \" + xhr.status);\n\t\t\t\t\t\t\t\tif (((!xhr.status && !xhr.aborted) || 500 == xhr.status) && (options.retry || 0) < options.uploadRetry) {\n\t\t\t\t\t\t\t\t\toptions.retry = (options.retry || 0) + 1;\n\t\t\t\t\t\t\t\t\tvar delay = api.networkDownRetryTimeout;\n\n\t\t\t\t\t\t\t\t\t// inform about recoverable problems\n\t\t\t\t\t\t\t\t\toptions.pause(options.file, options);\n\n\t\t\t\t\t\t\t\t\tsetTimeout(function () {\n\t\t\t\t\t\t\t\t\t\t_this._send(options, data);\n\t\t\t\t\t\t\t\t\t}, delay);\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t//success\n\t\t\t\t\t\t\t\t\t_this.end(xhr.status);\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\t//success\n\t\t\t\t\t\t\t\t_this.end(xhr.status);\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\txhr = null;\n\t\t\t\t\t\t}\n\t\t\t\t\t};\n\n\t\t\t\t\tif( api.isArray(data) ){\n\t\t\t\t\t\t// multipart\n\t\t\t\t\t\txhr.setRequestHeader('Content-Type', 'multipart/form-data; boundary=_'+api.expando);\n\t\t\t\t\t\tvar rawData = data.join('') +'--_'+ api.expando +'--';\n\n\t\t\t\t\t\t/** @namespace  xhr.sendAsBinary  https://developer.mozilla.org/ru/XMLHttpRequest#Sending_binary_content */\n\t\t\t\t\t\tif( xhr.sendAsBinary ){\n\t\t\t\t\t\t\txhr.sendAsBinary(rawData);\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse {\n\t\t\t\t\t\t\tvar bytes = Array.prototype.map.call(rawData, function(c){ return c.charCodeAt(0) & 0xff; });\n\t\t\t\t\t\t\txhr.send(new Uint8Array(bytes).buffer);\n\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// FormData\n\t\t\t\t\t\txhr.send(data);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t};\n\n\n\t// @export\n\tapi.XHR = XHR;\n})(window, FileAPI);\n\n/**\n * @class\tFileAPI.Camera\n * @author\tRubaXa\t<trash@rubaxa.org>\n * @support\tChrome 21+, FF 18+, Opera 12+\n */\n\n/*global window, FileAPI, jQuery */\n/** @namespace LocalMediaStream -- https://developer.mozilla.org/en-US/docs/WebRTC/MediaStream_API#LocalMediaStream */\n(function (window, api){\n\t\"use strict\";\n\n\tvar\n\t\tURL = window.URL || window.webkitURL,\n\n\t\tdocument = window.document,\n\t\tnavigator = window.navigator,\n\n\t\tgetMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia,\n\n\t\thtml5 = !!getMedia\n\t;\n\n\n\t// Support \"media\"\n\tapi.support.media = html5;\n\n\n\tvar Camera = function (video){\n\t\tthis.video = video;\n\t};\n\n\n\tCamera.prototype = {\n\t\tisActive: function (){\n\t\t\treturn\t!!this._active;\n\t\t},\n\n\n\t\t/**\n\t\t * Start camera streaming\n\t\t * @param\t{Function}\tcallback\n\t\t */\n\t\tstart: function (callback){\n\t\t\tvar\n\t\t\t\t  _this = this\n\t\t\t\t, video = _this.video\n\t\t\t\t, _successId\n\t\t\t\t, _failId\n\t\t\t\t, _complete = function (err){\n\t\t\t\t\t_this._active = !err;\n\t\t\t\t\tclearTimeout(_failId);\n\t\t\t\t\tclearTimeout(_successId);\n//\t\t\t\t\tapi.event.off(video, 'loadedmetadata', _complete);\n\t\t\t\t\tcallback && callback(err, _this);\n\t\t\t\t}\n\t\t\t;\n\n\t\t\tgetMedia.call(navigator, { video: true }, function (stream/**LocalMediaStream*/){\n\t\t\t\t// Success\n\t\t\t\t_this.stream = stream;\n\n//\t\t\t\tapi.event.on(video, 'loadedmetadata', function (){\n//\t\t\t\t\t_complete(null);\n//\t\t\t\t});\n\n\t\t\t\t// Set camera stream\n\t\t\t\tvideo.src = URL.createObjectURL(stream);\n\n\t\t\t\t// Note: onloadedmetadata doesn't fire in Chrome when using it with getUserMedia.\n\t\t\t\t// See crbug.com/110938.\n\t\t\t\t_successId = setInterval(function (){\n\t\t\t\t\tif( _detectVideoSignal(video) ){\n\t\t\t\t\t\t_complete(null);\n\t\t\t\t\t}\n\t\t\t\t}, 1000);\n\n\t\t\t\t_failId = setTimeout(function (){\n\t\t\t\t\t_complete('timeout');\n\t\t\t\t}, 5000);\n\n\t\t\t\t// Go-go-go!\n\t\t\t\tvideo.play();\n\t\t\t}, _complete/*error*/);\n\t\t},\n\n\n\t\t/**\n\t\t * Stop camera streaming\n\t\t */\n\t\tstop: function (){\n\t\t\ttry {\n\t\t\t\tthis._active = false;\n\t\t\t\tthis.video.pause();\n\t\t\t\tthis.stream.stop();\n\t\t\t} catch( err ){ }\n\t\t},\n\n\n\t\t/**\n\t\t * Create screenshot\n\t\t * @return {FileAPI.Camera.Shot}\n\t\t */\n\t\tshot: function (){\n\t\t\treturn\tnew Shot(this.video);\n\t\t}\n\t};\n\n\n\t/**\n\t * Get camera element from container\n\t *\n\t * @static\n\t * @param\t{HTMLElement}\tel\n\t * @return\t{Camera}\n\t */\n\tCamera.get = function (el){\n\t\treturn\tnew Camera(el.firstChild);\n\t};\n\n\n\t/**\n\t * Publish camera element into container\n\t *\n\t * @static\n\t * @param\t{HTMLElement}\tel\n\t * @param\t{Object}\t\toptions\n\t * @param\t{Function}\t\t[callback]\n\t */\n\tCamera.publish = function (el, options, callback){\n\t\tif( typeof options == 'function' ){\n\t\t\tcallback = options;\n\t\t\toptions = {};\n\t\t}\n\n\t\t// Dimensions of \"camera\"\n\t\toptions = api.extend({}, {\n\t\t\t  width:\t'100%'\n\t\t\t, height:\t'100%'\n\t\t\t, start:\ttrue\n\t\t}, options);\n\n\n\t\tif( el.jquery ){\n\t\t\t// Extract first element, from jQuery collection\n\t\t\tel = el[0];\n\t\t}\n\n\n\t\tvar doneFn = function (err){\n\t\t\tif( err ){\n\t\t\t\tcallback(err);\n\t\t\t}\n\t\t\telse {\n\t\t\t\t// Get camera\n\t\t\t\tvar cam = Camera.get(el);\n\t\t\t\tif( options.start ){\n\t\t\t\t\tcam.start(callback);\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tcallback(null, cam);\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\n\n\t\tel.style.width\t= _px(options.width);\n\t\tel.style.height\t= _px(options.height);\n\n\n\t\tif( api.html5 && html5 ){\n\t\t\t// Create video element\n\t\t\tvar video = document.createElement('video');\n\n\t\t\t// Set dimensions\n\t\t\tvideo.style.width\t= _px(options.width);\n\t\t\tvideo.style.height\t= _px(options.height);\n\n\t\t\t// Clean container\n\t\t\tif( window.jQuery ){\n\t\t\t\tjQuery(el).empty();\n\t\t\t} else {\n\t\t\t\tel.innerHTML = '';\n\t\t\t}\n\n\t\t\t// Add \"camera\" to container\n\t\t\tel.appendChild(video);\n\n\t\t\t// end\n\t\t\tdoneFn();\n\t\t}\n\t\telse {\n\t\t\tCamera.fallback(el, options, doneFn);\n\t\t}\n\t};\n\n\n\tCamera.fallback = function (el, options, callback){\n\t\tcallback('not_support_camera');\n\t};\n\n\n\t/**\n\t * @class\tFileAPI.Camera.Shot\n\t */\n\tvar Shot = function (video){\n\t\tvar canvas\t= video.nodeName ? api.Image.toCanvas(video) : video;\n\t\tvar shot\t= api.Image(canvas);\n\t\tshot.type\t= 'image/png';\n\t\tshot.width\t= canvas.width;\n\t\tshot.height\t= canvas.height;\n\t\tshot.size\t= canvas.width * canvas.height * 4;\n\t\treturn\tshot;\n\t};\n\n\n\t/**\n\t * Add \"px\" postfix, if value is a number\n\t *\n\t * @private\n\t * @param\t{*}  val\n\t * @return\t{String}\n\t */\n\tfunction _px(val){\n\t\treturn\tval >= 0 ? val + 'px' : val;\n\t}\n\n\n\t/**\n\t * @private\n\t * @param\t{HTMLVideoElement} video\n\t * @return\t{Boolean}\n\t */\n\tfunction _detectVideoSignal(video){\n\t\tvar canvas = document.createElement('canvas'), ctx, res = false;\n\t\ttry {\n\t\t\tctx = canvas.getContext('2d');\n\t\t\tctx.drawImage(video, 0, 0, 1, 1);\n\t\t\tres = ctx.getImageData(0, 0, 1, 1).data[4] != 255;\n\t\t}\n\t\tcatch( e ){}\n\t\treturn\tres;\n\t}\n\n\n\t// @export\n\tCamera.Shot\t= Shot;\n\tapi.Camera\t= Camera;\n})(window, FileAPI);\n\n/**\n * FileAPI fallback to Flash\n *\n * @flash-developer  \"Vladimir Demidov\" <v.demidov@corp.mail.ru>\n */\n\n/*global window, ActiveXObject, FileAPI */\n(function (window, jQuery, api) {\n\t\"use strict\";\n\n\tvar\n\t\t  document = window.document\n\t\t, location = window.location\n\t\t, navigator = window.navigator\n\t\t, _each = api.each\n\t;\n\n\n\tapi.support.flash = (function (){\n\t\tvar mime = navigator.mimeTypes, has = false;\n\n\t\tif( navigator.plugins && typeof navigator.plugins['Shockwave Flash'] == 'object' ){\n\t\t\thas\t= navigator.plugins['Shockwave Flash'].description && !(mime && mime['application/x-shockwave-flash'] && !mime['application/x-shockwave-flash'].enabledPlugin);\n\t\t}\n\t\telse {\n\t\t\ttry {\n\t\t\t\thas\t= !!(window.ActiveXObject && new ActiveXObject('ShockwaveFlash.ShockwaveFlash'));\n\t\t\t}\n\t\t\tcatch(er){\n\t\t\t\tapi.log('Flash -- does not supported.');\n\t\t\t}\n\t\t}\n\n\t\tif( has && /^file:/i.test(location) ){\n\t\t\tapi.log('[warn] Flash does not work on `file:` protocol.');\n\t\t}\n\n\t\treturn\thas;\n\t})();\n\n\n\t   api.support.flash\n\t&& (0\n\t\t|| !api.html5 || !api.support.html5\n\t\t|| (api.cors && !api.support.cors)\n\t\t|| (api.media && !api.support.media)\n\t)\n\t&& (function (){\n\t\tvar\n\t\t\t  _attr  = api.uid()\n\t\t\t, _retry = 0\n\t\t\t, _files = {}\n\t\t\t, _rhttp = /^https?:/i\n\n\t\t\t, flash = {\n\t\t\t\t_fn: {},\n\n\n\t\t\t\t/**\n\t\t\t\t * Publish flash-object\n\t\t\t\t *\n\t\t\t\t * @param {HTMLElement} el\n\t\t\t\t * @param {String} id\n\t\t\t\t * @param {Object} [opts]\n\t\t\t\t */\n\t\t\t\tpublish: function (el, id, opts){\n\t\t\t\t\topts = opts || {};\n\t\t\t\t\tel.innerHTML = _makeFlashHTML({\n\t\t\t\t\t\tid: id\n\t\t\t\t\t\t, src: _getUrl(api.flashUrl, 'r=' + api.version)\n//\t\t\t\t\t\t, src: _getUrl('http://v.demidov.boom.corp.mail.ru/uploaderfileapi/FlashFileAPI.swf?1')\n\t\t\t\t\t\t, wmode: opts.camera ? '' : 'transparent'\n\t\t\t\t\t\t, flashvars: 'callback=' + (opts.onEvent || 'FileAPI.Flash.onEvent')\n\t\t\t\t\t\t+ '&flashId='+ id\n\t\t\t\t\t\t+ '&storeKey='+ navigator.userAgent.match(/\\d/ig).join('') +'_'+ api.version\n\t\t\t\t\t\t+ (flash.isReady || (api.pingUrl ? '&ping='+api.pingUrl : ''))\n\t\t\t\t\t\t+ '&timeout='+api.flashAbortTimeout\n\t\t\t\t\t\t+ (opts.camera ? '&useCamera=' + _getUrl(api.flashWebcamUrl) : '')\n\t\t\t\t\t\t+ '&debug='+(api.debug?\"1\":\"\")\n\t\t\t\t\t}, opts);\n\t\t\t\t},\n\n\n\t\t\t\t/**\n\t\t\t\t * Initialization & preload flash object\n\t\t\t\t */\n\t\t\t\tinit: function (){\n\t\t\t\t\tvar child = document.body && document.body.firstChild;\n\n\t\t\t\t\tif( child ){\n\t\t\t\t\t\tdo {\n\t\t\t\t\t\t\tif( child.nodeType == 1 ){\n\t\t\t\t\t\t\t\tapi.log('FlashAPI.state: awaiting');\n\n\t\t\t\t\t\t\t\tvar dummy = document.createElement('div');\n\n\t\t\t\t\t\t\t\tdummy.id = '_' + _attr;\n\n\t\t\t\t\t\t\t\t_css(dummy, {\n\t\t\t\t\t\t\t\t\t  top: 1\n\t\t\t\t\t\t\t\t\t, right: 1\n\t\t\t\t\t\t\t\t\t, width: 5\n\t\t\t\t\t\t\t\t\t, height: 5\n\t\t\t\t\t\t\t\t\t, position: 'absolute'\n\t\t\t\t\t\t\t\t\t, zIndex: 1e6+'' // set max zIndex\n\t\t\t\t\t\t\t\t});\n\n\t\t\t\t\t\t\t\tchild.parentNode.insertBefore(dummy, child);\n\t\t\t\t\t\t\t\tflash.publish(dummy, _attr);\n\n\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\twhile( child = child.nextSibling );\n\t\t\t\t\t}\n\n\t\t\t\t\tif( _retry < 10 ){\n\t\t\t\t\t\tsetTimeout(flash.init, ++_retry*50);\n\t\t\t\t\t}\n\t\t\t\t},\n\n\n\t\t\t\tready: function (){\n\t\t\t\t\tapi.log('FlashAPI.state: ready');\n\n\t\t\t\t\tflash.ready = api.F;\n\t\t\t\t\tflash.isReady = true;\n\t\t\t\t\tflash.patch();\n\t\t\t\t\tflash.patchCamera && flash.patchCamera();\n\t\t\t\t\tapi.event.on(document, 'mouseover', flash.mouseover);\n\t\t\t\t\tapi.event.on(document, 'click', function (evt){\n\t\t\t\t\t\tif( flash.mouseover(evt) ){\n\t\t\t\t\t\t\tevt.preventDefault\n\t\t\t\t\t\t\t\t? evt.preventDefault()\n\t\t\t\t\t\t\t\t: (evt.returnValue = 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\n\t\t\t\tgetEl: function (){\n\t\t\t\t\treturn\tdocument.getElementById('_'+_attr);\n\t\t\t\t},\n\n\n\t\t\t\tgetWrapper: function (node){\n\t\t\t\t\tdo {\n\t\t\t\t\t\tif( /js-fileapi-wrapper/.test(node.className) ){\n\t\t\t\t\t\t\treturn\tnode;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\twhile( (node = node.parentNode) && (node !== document.body) );\n\t\t\t\t},\n\t\t\t\t\n\t\t\t\tdisableMouseover: false,\n\n\t\t\t\tmouseover: function (evt){\n\t\t\t\t\tif (!flash.disableMouseover) {\n\t\t\t\t\t\tvar target = api.event.fix(evt).target;\n\t\n\t\t\t\t\t\tif( /input/i.test(target.nodeName) && target.type == 'file' && !target.disabled ){\n\t\t\t\t\t\t\tvar\n\t\t\t\t\t\t\t\t  state = target.getAttribute(_attr)\n\t\t\t\t\t\t\t\t, wrapper = flash.getWrapper(target)\n\t\t\t\t\t\t\t;\n\t\n\t\t\t\t\t\t\tif( api.multiFlash ){\n\t\t\t\t\t\t\t\t// check state:\n\t\t\t\t\t\t\t\t//   i — published\n\t\t\t\t\t\t\t\t//   i — initialization\n\t\t\t\t\t\t\t\t//   r — ready\n\t\t\t\t\t\t\t\tif( state == 'i' || state == 'r' ){\n\t\t\t\t\t\t\t\t\t// publish fail\n\t\t\t\t\t\t\t\t\treturn\tfalse;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\telse if( state != 'p' ){\n\t\t\t\t\t\t\t\t\t// set \"init\" state\n\t\t\t\t\t\t\t\t\ttarget.setAttribute(_attr, 'i');\n\t\n\t\t\t\t\t\t\t\t\tvar dummy = document.createElement('div');\n\t\n\t\t\t\t\t\t\t\t\tif( !wrapper ){\n\t\t\t\t\t\t\t\t\t\tapi.log('[err] FlashAPI.mouseover: js-fileapi-wrapper not found');\n\t\t\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t\t\t}\n\t\n\t\t\t\t\t\t\t\t\t_css(dummy, {\n\t\t\t\t\t\t\t\t\t\t  top:    0\n\t\t\t\t\t\t\t\t\t\t, left:   0\n\t\t\t\t\t\t\t\t\t\t, width:  target.offsetWidth\n\t\t\t\t\t\t\t\t\t\t, height: target.offsetHeight\n\t\t\t\t\t\t\t\t\t\t, zIndex: 1e6+'' // set max zIndex\n\t\t\t\t\t\t\t\t\t\t, position: 'absolute'\n\t\t\t\t\t\t\t\t\t});\n\t\n\t\t\t\t\t\t\t\t\twrapper.appendChild(dummy);\n\t\t\t\t\t\t\t\t\tflash.publish(dummy, api.uid());\n\t\n\t\t\t\t\t\t\t\t\t// set \"publish\" state\n\t\t\t\t\t\t\t\t\ttarget.setAttribute(_attr, 'p');\n\t\t\t\t\t\t\t\t}\n\t\n\t\t\t\t\t\t\t\treturn\ttrue;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse if( wrapper ){\n\t\t\t\t\t\t\t\t// Use one flash element\n\t\t\t\t\t\t\t\tvar box = _getDimensions(wrapper);\n\t\t\t\t\t\t\t\t_css(flash.getEl(), box);\n\t\n\t\t\t\t\t\t\t\t// Set current input\n\t\t\t\t\t\t\t\tflash.curInp = target;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse if( !/object|embed/i.test(target.nodeName) ){\n\t\t\t\t\t\t\t_css(flash.getEl(), { top: 1, left: 1, width: 5, height: 5 });\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t},\n\n\t\t\t\tonEvent: function (evt){\n\t\t\t\t\tvar type = evt.type;\n\t\t\t\t\t\n\t\t\t\t\tif( type == 'ready' ){\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t// set \"ready\" state\n\t\t\t\t\t\t\tflash.getInput(evt.flashId).setAttribute(_attr, 'r');\n\t\t\t\t\t\t} catch (e){\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tflash.ready();\n\t\t\t\t\t\tsetTimeout(function (){ flash.mouseenter(evt); }, 50);\n\t\t\t\t\t\treturn\ttrue;\n\t\t\t\t\t}\n\t\t\t\t\telse if( type === 'ping' ){\n\t\t\t\t\t\tapi.log('(flash -> js).ping:', [evt.status, evt.savedStatus], evt.error);\n\t\t\t\t\t}\n\t\t\t\t\telse if( type === 'log' ){\n\t\t\t\t\t\tapi.log('(flash -> js).log:', evt.target);\n\t\t\t\t\t}\n\t\t\t\t\telse if( type in flash ){\n\t\t\t\t\t\tsetTimeout(function (){\n\t\t\t\t\t\t\tapi.log('FlashAPI.event.'+evt.type+':', evt);\n\t\t\t\t\t\t\tflash[type](evt);\n\t\t\t\t\t\t}, 1);\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tmouseDown: function(evt) {\n\t\t\t\t\tflash.disableMouseover = true;\n\t\t\t\t},\n\t\t\t\tcancel: function(evt) {\n\t\t\t\t\tflash.disableMouseover = false;\n\t\t\t\t},\n\t\t\t\tmouseenter: function (evt){\n\t\t\t\t\tvar node = flash.getInput(evt.flashId);\n\n\t\t\t\t\tif( node ){\n\t\t\t\t\t\t// Set multiple mode\n\t\t\t\t\t\tflash.cmd(evt, 'multiple', node.getAttribute('multiple') != null);\n\n\n\t\t\t\t\t\t// Set files filter\n\t\t\t\t\t\tvar accept = [], exts = {};\n\n\t\t\t\t\t\t_each((node.getAttribute('accept') || '').split(/,\\s*/), function (mime){\n\t\t\t\t\t\t\tapi.accept[mime] && _each(api.accept[mime].split(' '), function (ext){\n\t\t\t\t\t\t\t\texts[ext] = 1;\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t});\n\n\t\t\t\t\t\t_each(exts, function (i, ext){\n\t\t\t\t\t\t\taccept.push( ext );\n\t\t\t\t\t\t});\n\n\t\t\t\t\t\tflash.cmd(evt, 'accept', accept.length ? accept.join(',')+','+accept.join(',').toUpperCase() : '*');\n\t\t\t\t\t}\n\t\t\t\t},\n\n\n\t\t\t\tget: function (id){\n\t\t\t\t\treturn\tdocument[id] || window[id] || document.embeds[id];\n\t\t\t\t},\n\n\n\t\t\t\tgetInput: function (id){\n\t\t\t\t\tif( api.multiFlash ){\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tvar node = flash.getWrapper(flash.get(id));\n\t\t\t\t\t\t\tif( node ){\n\t\t\t\t\t\t\t\treturn node.getElementsByTagName('input')[0];\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} catch (e){\n\t\t\t\t\t\t\tapi.log('[err] Can not find \"input\" by flashId:', id, e);\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\treturn\tflash.curInp;\n\t\t\t\t\t}\n\t\t\t\t},\n\n\n\t\t\t\tselect: function (evt){\n\t\t\t\t\ttry {\n\t\t\t\t\t\tvar\n\t\t\t\t\t\t\t  inp = flash.getInput(evt.flashId)\n\t\t\t\t\t\t\t, uid = api.uid(inp)\n\t\t\t\t\t\t\t, files = evt.target.files\n\t\t\t\t\t\t\t, event\n\t\t\t\t\t\t;\n\t\t\t\t\t\t_each(files, function (file){\n\t\t\t\t\t\t\tapi.checkFileObj(file);\n\t\t\t\t\t\t});\n\t\n\t\t\t\t\t\t_files[uid] = files;\n\t\n\t\t\t\t\t\tif( document.createEvent ){\n\t\t\t\t\t\t\tevent = document.createEvent('Event');\n\t\t\t\t\t\t\tevent.files = files;\n\t\t\t\t\t\t\tevent.initEvent('change', true, true);\n\t\t\t\t\t\t\tinp.dispatchEvent(event);\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse if( jQuery ){\n\t\t\t\t\t\t\tjQuery(inp).trigger({ type: 'change', files: files });\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse {\n\t\t\t\t\t\t\tevent = document.createEventObject();\n\t\t\t\t\t\t\tevent.files = files;\n\t\t\t\t\t\t\tinp.fireEvent('onchange', event);\n\t\t\t\t\t\t}\n\t\t\t\t\t} finally {\n\t\t\t\t\t\tflash.disableMouseover = false;\n\t\t\t\t\t}\n\t\t\t\t},\n\n\t\t\t\tinterval: null,\n\t\t\t\tcmd: function (id, name, data, last) {\n\t\t\t\t\tif (flash.uploadInProgress && flash.readInProgress) {\n\t\t\t\t\t\tsetTimeout(function() {\n\t\t\t\t\t\t\tflash.cmd(id, name, data, last);\n\t\t\t\t\t\t}, 100);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tthis.cmdFn(id, name, data, last);\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\t\n\t\t\t\tcmdFn: function(id, name, data, last) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tapi.log('(js -> flash).'+name+':', data);\n\t\t\t\t\t\treturn flash.get(id.flashId || id).cmd(name, data);\n\t\t\t\t\t} catch (e){\n\t\t\t\t\t\tapi.log('(js -> flash).onError:', e);\n\t\t\t\t\t\tif( !last ){\n\t\t\t\t\t\t\t// try again\n\t\t\t\t\t\t\tsetTimeout(function (){ flash.cmd(id, name, data, true); }, 50);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t},\n\n\t\t\t\tpatch: function (){\n\t\t\t\t\tapi.flashEngine = true;\n\n\t\t\t\t\t// FileAPI\n\t\t\t\t\t_inherit(api, {\n\t\t\t\t\t\treadAsDataURL: function (file, callback){\n\t\t\t\t\t\t\tif( _isHtmlFile(file) ){\n\t\t\t\t\t\t\t\tthis.parent.apply(this, arguments);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse {\n\t\t\t\t\t\t\t\tapi.log('FlashAPI.readAsBase64');\n\t\t\t\t\t\t\t\tflash.readInProgress = true;\n\t\t\t\t\t\t\t\tflash.cmd(file, 'readAsBase64', {\n\t\t\t\t\t\t\t\t\tid: file.id,\n\t\t\t\t\t\t\t\t\tcallback: _wrap(function _(err, base64){\n\t\t\t\t\t\t\t\t\t\tflash.readInProgress = false;\n\t\t\t\t\t\t\t\t\t\t_unwrap(_);\n\n\t\t\t\t\t\t\t\t\t\tapi.log('FlashAPI.readAsBase64:', err);\n\n\t\t\t\t\t\t\t\t\t\tcallback({\n\t\t\t\t\t\t\t\t\t\t\t  type: err ? 'error' : 'load'\n\t\t\t\t\t\t\t\t\t\t\t, error: err\n\t\t\t\t\t\t\t\t\t\t\t, result: 'data:'+ file.type +';base64,'+ base64\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\treadAsText: function (file, encoding, callback){\n\t\t\t\t\t\t\tif( callback ){\n\t\t\t\t\t\t\t\tapi.log('[warn] FlashAPI.readAsText not supported `encoding` param');\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tcallback = encoding;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tapi.readAsDataURL(file, function (evt){\n\t\t\t\t\t\t\t\tif( evt.type == 'load' ){\n\t\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\t\tevt.result = window.atob(evt.result.split(';base64,')[1]);\n\t\t\t\t\t\t\t\t\t} catch( err ){\n\t\t\t\t\t\t\t\t\t\tevt.type = 'error';\n\t\t\t\t\t\t\t\t\t\tevt.error = err.toString();\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\tcallback(evt);\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\tgetFiles: function (input, filter, callback){\n\t\t\t\t\t\t\tif( callback ){\n\t\t\t\t\t\t\t\tapi.filterFiles(api.getFiles(input), filter, callback);\n\t\t\t\t\t\t\t\treturn null;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tvar files = api.isArray(input) ? input : _files[api.uid(input.target || input.srcElement || input)];\n\n\n\t\t\t\t\t\t\tif( !files ){\n\t\t\t\t\t\t\t\t// Файлов нету, вызываем родительский метод\n\t\t\t\t\t\t\t\treturn\tthis.parent.apply(this, arguments);\n\t\t\t\t\t\t\t}\n\n\n\t\t\t\t\t\t\tif( filter ){\n\t\t\t\t\t\t\t\tfilter\t= api.getFilesFilter(filter);\n\t\t\t\t\t\t\t\tfiles\t= api.filter(files, function (file){ return filter.test(file.name); });\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\treturn\tfiles;\n\t\t\t\t\t\t},\n\n\n\t\t\t\t\t\tgetInfo: function (file, fn){\n\t\t\t\t\t\t\tif( _isHtmlFile(file) ){\n\t\t\t\t\t\t\t\tthis.parent.apply(this, arguments);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse if( file.isShot ){\n\t\t\t\t\t\t\t\tfn(null, file.info = {\n\t\t\t\t\t\t\t\t\twidth: file.width,\n\t\t\t\t\t\t\t\t\theight: file.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\telse {\n\t\t\t\t\t\t\t\tif( !file.__info ){\n\t\t\t\t\t\t\t\t\tvar defer = file.__info = api.defer();\n\n//\t\t\t\t\t\t\t\t\tflash.cmd(file, 'getFileInfo', {\n//\t\t\t\t\t\t\t\t\t\t  id: file.id\n//\t\t\t\t\t\t\t\t\t\t, callback: _wrap(function _(err, info){\n//\t\t\t\t\t\t\t\t\t\t\t_unwrap(_);\n//\t\t\t\t\t\t\t\t\t\t\tdefer.resolve(err, file.info = info);\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\tdefer.resolve(null, file.info = null);\n\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\tfile.__info.then(fn);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\n\n\t\t\t\t\t// FileAPI.Image\n\t\t\t\t\tapi.support.transform = true;\n\t\t\t\t\tapi.Image && _inherit(api.Image.prototype, {\n\t\t\t\t\t\tget: function (fn, scaleMode){\n\t\t\t\t\t\t\tthis.set({ scaleMode: scaleMode || 'noScale' }); // noScale, exactFit\n\t\t\t\t\t\t\treturn this.parent(fn);\n\t\t\t\t\t\t},\n\n\t\t\t\t\t\t_load: function (file, fn){\n\t\t\t\t\t\t\tapi.log('FlashAPI.Image._load:', file);\n\n\t\t\t\t\t\t\tif( _isHtmlFile(file) ){\n\t\t\t\t\t\t\t\tthis.parent.apply(this, arguments);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse {\n\t\t\t\t\t\t\t\tvar _this = this;\n\t\t\t\t\t\t\t\tapi.getInfo(file, function (err){\n\t\t\t\t\t\t\t\t\tfn.call(_this, err, file);\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_apply: function (file, fn){\n\t\t\t\t\t\t\tapi.log('FlashAPI.Image._apply:', file);\n\n\t\t\t\t\t\t\tif( _isHtmlFile(file) ){\n\t\t\t\t\t\t\t\tthis.parent.apply(this, arguments);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse {\n\t\t\t\t\t\t\t\tvar m = this.getMatrix(file.info), doneFn = fn;\n\n\t\t\t\t\t\t\t\tflash.cmd(file, 'imageTransform', {\n\t\t\t\t\t\t\t\t\t  id: file.id\n\t\t\t\t\t\t\t\t\t, matrix: m\n\t\t\t\t\t\t\t\t\t, callback: _wrap(function _(err, base64){\n\t\t\t\t\t\t\t\t\t\tapi.log('FlashAPI.Image._apply.callback:', err);\n\t\t\t\t\t\t\t\t\t\t_unwrap(_);\n\n\t\t\t\t\t\t\t\t\t\tif( err ){\n\t\t\t\t\t\t\t\t\t\t\tdoneFn(err);\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\telse if( !api.support.html5 && (!api.support.dataURI || base64.length > 3e4) ){\n\t\t\t\t\t\t\t\t\t\t\t_makeFlashImage({\n\t\t\t\t\t\t\t\t\t\t\t\t  width:\t(m.deg % 180) ? m.dh : m.dw\n\t\t\t\t\t\t\t\t\t\t\t\t, height:\t(m.deg % 180) ? m.dw : m.dh\n\t\t\t\t\t\t\t\t\t\t\t\t, scale:\tm.scaleMode\n\t\t\t\t\t\t\t\t\t\t\t}, base64, doneFn);\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\telse {\n\t\t\t\t\t\t\t\t\t\t\tif( m.filter ){\n\t\t\t\t\t\t\t\t\t\t\t\tdoneFn = function (err, img){\n\t\t\t\t\t\t\t\t\t\t\t\t\tif( err ){\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tfn(err);\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\telse {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tapi.Image.applyFilter(img, m.filter, function (){\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tfn(err, this.canvas);\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};\n\t\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t\tapi.newImage('data:'+ file.type +';base64,'+ base64, doneFn);\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\ttoData: function (fn){\n\t\t\t\t\t\t\tvar\n\t\t\t\t\t\t\t\t  file = this.file\n\t\t\t\t\t\t\t\t, info = file.info\n\t\t\t\t\t\t\t\t, matrix = this.getMatrix(info)\n\t\t\t\t\t\t\t;\n\t\t\t\t\t\t\tapi.log('FlashAPI.Image.toData');\n\n\t\t\t\t\t\t\tif( _isHtmlFile(file) ){\n\t\t\t\t\t\t\t\tthis.parent.apply(this, arguments);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse {\n\t\t\t\t\t\t\t\tif( matrix.deg == 'auto' ){\n\t\t\t\t\t\t\t\t\tmatrix.deg = api.Image.exifOrientation[info && info.exif && info.exif.Orientation] || 0;\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\tfn.call(this, !file.info, {\n\t\t\t\t\t\t\t\t\t  id:\t\tfile.id\n\t\t\t\t\t\t\t\t\t, flashId:\tfile.flashId\n\t\t\t\t\t\t\t\t\t, name:\t\tfile.name\n\t\t\t\t\t\t\t\t\t, type:\t\tfile.type\n\t\t\t\t\t\t\t\t\t, matrix:\tmatrix\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\n\n\t\t\t\t\tapi.Image && _inherit(api.Image, {\n\t\t\t\t\t\tfromDataURL: function (dataURL, size, callback){\n\t\t\t\t\t\t\tif( !api.support.dataURI || dataURL.length > 3e4 ){\n\t\t\t\t\t\t\t\t_makeFlashImage(\n\t\t\t\t\t\t\t\t\t  api.extend({ scale: 'exactFit' }, size)\n\t\t\t\t\t\t\t\t\t, dataURL.replace(/^data:[^,]+,/, '')\n\t\t\t\t\t\t\t\t\t, function (err, el){ callback(el); }\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\tthis.parent(dataURL, size, callback);\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// FileAPI.Form\n\t\t\t\t\t_inherit(api.Form.prototype, {\n\t\t\t\t\t\ttoData: function (fn){\n\t\t\t\t\t\t\tvar items = this.items, i = items.length;\n\n\t\t\t\t\t\t\tfor( ; i--; ){\n\t\t\t\t\t\t\t\tif( items[i].file && _isHtmlFile(items[i].blob) ){\n\t\t\t\t\t\t\t\t\treturn this.parent.apply(this, arguments);\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\tapi.log('FlashAPI.Form.toData');\n\t\t\t\t\t\t\tfn(items);\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\n\n\t\t\t\t\t// FileAPI.XHR\n\t\t\t\t\t_inherit(api.XHR.prototype, {\n\t\t\t\t\t\t_send: function (options, formData){\n\t\t\t\t\t\t\tif(\n\t\t\t\t\t\t\t\t   formData.nodeName\n\t\t\t\t\t\t\t\t|| formData.append && api.support.html5\n\t\t\t\t\t\t\t\t|| api.isArray(formData) && (typeof formData[0] === 'string')\n\t\t\t\t\t\t\t){\n\t\t\t\t\t\t\t\t// HTML5, Multipart or IFrame\n\t\t\t\t\t\t\t\treturn\tthis.parent.apply(this, arguments);\n\t\t\t\t\t\t\t}\n\n\n\t\t\t\t\t\t\tvar\n\t\t\t\t\t\t\t\t  data = {}\n\t\t\t\t\t\t\t\t, files = {}\n\t\t\t\t\t\t\t\t, _this = this\n\t\t\t\t\t\t\t\t, flashId\n\t\t\t\t\t\t\t\t, fileId\n\t\t\t\t\t\t\t;\n\n\t\t\t\t\t\t\t_each(formData, function (item){\n\t\t\t\t\t\t\t\tif( item.file ){\n\t\t\t\t\t\t\t\t\tfiles[item.name] = item = _getFileDescr(item.blob);\n\t\t\t\t\t\t\t\t\tfileId  = item.id;\n\t\t\t\t\t\t\t\t\tflashId = item.flashId;\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\tdata[item.name] = item.blob;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t});\n\n\t\t\t\t\t\t\tif( !fileId ){\n\t\t\t\t\t\t\t\tflashId = _attr;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tif( !flashId ){\n\t\t\t\t\t\t\t\tapi.log('[err] FlashAPI._send: flashId -- undefined');\n\t\t\t\t\t\t\t\treturn this.parent.apply(this, arguments);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse {\n\t\t\t\t\t\t\t\tapi.log('FlashAPI.XHR._send: '+ flashId +' -> '+ fileId);\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t_this.xhr = {\n\t\t\t\t\t\t\t\theaders: {},\n\t\t\t\t\t\t\t\tabort: function (){ flash.uploadInProgress = false; flash.cmd(flashId, 'abort', { id: fileId }); },\n\t\t\t\t\t\t\t\tgetResponseHeader: function (name){ return this.headers[name]; },\n\t\t\t\t\t\t\t\tgetAllResponseHeaders: function (){ return this.headers; }\n\t\t\t\t\t\t\t};\n\n\t\t\t\t\t\t\tvar queue = api.queue(function (){\n\t\t\t\t\t\t\t\tflash.uploadInProgress = true;\n\t\t\t\t\t\t\t\tflash.cmd(flashId, 'upload', {\n\t\t\t\t\t\t\t\t\t  url: _getUrl(options.url.replace(/([a-z]+)=(\\?)&?/i, ''))\n\t\t\t\t\t\t\t\t\t, data: data\n\t\t\t\t\t\t\t\t\t, files: fileId ? files : null\n\t\t\t\t\t\t\t\t\t, headers: options.headers || {}\n\t\t\t\t\t\t\t\t\t, callback: _wrap(function upload(evt){\n\t\t\t\t\t\t\t\t\t\tvar type = evt.type, result = evt.result;\n\n\t\t\t\t\t\t\t\t\t\tapi.log('FlashAPI.upload.'+type);\n\n\t\t\t\t\t\t\t\t\t\tif( type == 'progress' ){\n\t\t\t\t\t\t\t\t\t\t\tevt.loaded = Math.min(evt.loaded, evt.total); // @todo fixme\n\t\t\t\t\t\t\t\t\t\t\tevt.lengthComputable = true;\n\t\t\t\t\t\t\t\t\t\t\toptions.progress(evt);\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\telse if( type == 'complete' ){\n\t\t\t\t\t\t\t\t\t\t\tflash.uploadInProgress = false;\n\t\t\t\t\t\t\t\t\t\t\t_unwrap(upload);\n\n\t\t\t\t\t\t\t\t\t\t\tif( typeof result == 'string' ){\n\t\t\t\t\t\t\t\t\t\t\t\t_this.responseText\t= result.replace(/%22/g, \"\\\"\").replace(/%5c/g, \"\\\\\").replace(/%26/g, \"&\").replace(/%25/g, \"%\");\n\t\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t\t_this.end(evt.status || 200);\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\telse if( type == 'abort' || type == 'error' ){\n\t\t\t\t\t\t\t\t\t\t\tflash.uploadInProgress = false;\n\t\t\t\t\t\t\t\t\t\t\t_this.end(evt.status || 0, evt.message);\n\t\t\t\t\t\t\t\t\t\t\t_unwrap(upload);\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\n\n\t\t\t\t\t\t\t// #2174: FileReference.load() call while FileReference.upload() or vice versa\n\t\t\t\t\t\t\t_each(files, function (file){\n\t\t\t\t\t\t\t\tqueue.inc();\n\t\t\t\t\t\t\t\tapi.getInfo(file, queue.next);\n\t\t\t\t\t\t\t});\n\n\t\t\t\t\t\t\tqueue.check();\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\n\t\tfunction _makeFlashHTML(opts){\n\t\t\treturn ('<object id=\"#id#\" classid=\"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000\" width=\"'+(opts.width || '100%')+'\" height=\"'+(opts.height || '100%')+'\">'\n\t\t\t\t+ '<param name=\"movie\" value=\"#src#\" />'\n\t\t\t\t+ '<param name=\"flashvars\" value=\"#flashvars#\" />'\n\t\t\t\t+ '<param name=\"swliveconnect\" value=\"true\" />'\n\t\t\t\t+ '<param name=\"allowscriptaccess\" value=\"always\" />'\n\t\t\t\t+ '<param name=\"allownetworking\" value=\"all\" />'\n\t\t\t\t+ '<param name=\"menu\" value=\"false\" />'\n\t\t\t\t+ '<param name=\"wmode\" value=\"#wmode#\" />'\n\t\t\t\t+ '<embed flashvars=\"#flashvars#\" swliveconnect=\"true\" allownetworking=\"all\" allowscriptaccess=\"always\" name=\"#id#\" src=\"#src#\" width=\"'+(opts.width || '100%')+'\" height=\"'+(opts.height || '100%')+'\" menu=\"false\" wmode=\"transparent\" type=\"application/x-shockwave-flash\"></embed>'\n\t\t\t\t+ '</object>').replace(/#(\\w+)#/ig, function (a, name){ return opts[name]; })\n\t\t\t;\n\t\t}\n\n\n\t\tfunction _css(el, css){\n\t\t\tif( el && el.style ){\n\t\t\t\tvar key, val;\n\t\t\t\tfor( key in css ){\n\t\t\t\t\tval = css[key];\n\t\t\t\t\tif( typeof val == 'number' ){\n\t\t\t\t\t\tval += 'px';\n\t\t\t\t\t}\n\t\t\t\t\ttry { el.style[key] = val; } catch (e) {}\n\t\t\t\t}\n\t\t\t\t\n\t\t\t}\n\t\t}\n\n\n\t\tfunction _inherit(obj, methods){\n\t\t\t_each(methods, function (fn, name){\n\t\t\t\tvar prev = obj[name];\n\t\t\t\tobj[name] = function (){\n\t\t\t\t\tthis.parent = prev;\n\t\t\t\t\treturn fn.apply(this, arguments);\n\t\t\t\t};\n\t\t\t});\n\t\t}\n\n\t\tfunction _isHtmlFile(file){\n\t\t\treturn\tfile && !file.flashId;\n\t\t}\n\n\t\tfunction _wrap(fn){\n\t\t\tvar id = fn.wid = api.uid();\n\t\t\tflash._fn[id] = fn;\n\t\t\treturn\t'FileAPI.Flash._fn.'+id;\n\t\t}\n\n\n\t\tfunction _unwrap(fn){\n\t\t\ttry {\n\t\t\t\tflash._fn[fn.wid] = null;\n\t\t\t\tdelete\tflash._fn[fn.wid];\n\t\t\t}\n\t\t\tcatch(e){}\n\t\t}\n\n\n\t\tfunction _getUrl(url, params){\n\t\t\tif( !_rhttp.test(url) ){\n\t\t\t\tif( /^\\.\\//.test(url) || '/' != url.charAt(0) ){\n\t\t\t\t\tvar path = location.pathname;\n\t\t\t\t\tpath = path.substr(0, path.lastIndexOf('/'));\n\t\t\t\t\turl = (path +'/'+ url).replace('/./', '/');\n\t\t\t\t}\n\n\t\t\t\tif( '//' != url.substr(0, 2) ){\n\t\t\t\t\turl = '//' + location.host + url;\n\t\t\t\t}\n\n\t\t\t\tif( !_rhttp.test(url) ){\n\t\t\t\t\turl = location.protocol + url;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif( params ){\n\t\t\t\turl += (/\\?/.test(url) ? '&' : '?') + params;\n\t\t\t}\n\n\t\t\treturn\turl;\n\t\t}\n\n\n\t\tfunction _makeFlashImage(opts, base64, fn){\n\t\t\tvar\n\t\t\t\t  key\n\t\t\t\t, flashId = api.uid()\n\t\t\t\t, el = document.createElement('div')\n\t\t\t\t, attempts = 10\n\t\t\t;\n\n\t\t\tfor( key in opts ){\n\t\t\t\tel.setAttribute(key, opts[key]);\n\t\t\t\tel[key] = opts[key];\n\t\t\t}\n\n\t\t\t_css(el, opts);\n\n\t\t\topts.width\t= '100%';\n\t\t\topts.height\t= '100%';\n\n\t\t\tel.innerHTML = _makeFlashHTML(api.extend({\n\t\t\t\t  id: flashId\n\t\t\t\t, src: _getUrl(api.flashImageUrl, 'r='+ api.uid())\n\t\t\t\t, wmode: 'opaque'\n\t\t\t\t, flashvars: 'scale='+ opts.scale +'&callback='+_wrap(function _(){\n\t\t\t\t\t_unwrap(_);\n\t\t\t\t\tif( --attempts > 0 ){\n\t\t\t\t\t\t_setImage();\n\t\t\t\t\t}\n\t\t\t\t\treturn true;\n\t\t\t\t})\n\t\t\t}, opts));\n\n\t\t\tfunction _setImage(){\n\t\t\t\ttry {\n\t\t\t\t\t// Get flash-object by id\n\t\t\t\t\tvar img = flash.get(flashId);\n\t\t\t\t\timg.setImage(base64);\n\t\t\t\t} catch (e){\n\t\t\t\t\tapi.log('[err] FlashAPI.Preview.setImage -- can not set \"base64\":', e);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfn(false, el);\n\t\t\tel = null;\n\t\t}\n\n\n\t\tfunction _getFileDescr(file){\n\t\t\treturn\t{\n\t\t\t\t  id: file.id\n\t\t\t\t, name: file.name\n\t\t\t\t, matrix: file.matrix\n\t\t\t\t, flashId: file.flashId\n\t\t\t};\n\t\t}\n\n\n\t\tfunction _getDimensions(el){\n\t\t\tvar\n\t\t\t\t  box = el.getBoundingClientRect()\n\t\t\t\t, body = document.body\n\t\t\t\t, docEl = (el && el.ownerDocument).documentElement\n\t\t\t;\n\t\t\t\n\t\t\tfunction getOffset(obj) {\n\t\t\t    var left, top;\n\t\t\t    left = top = 0;\n\t\t\t    if (obj.offsetParent) {\n\t\t\t        do {\n\t\t\t            left += obj.offsetLeft;\n\t\t\t            top  += obj.offsetTop;\n\t\t\t        } while (obj = obj.offsetParent);\n\t\t\t    }\n\t\t\t    return {\n\t\t\t        left : left,\n\t\t\t        top : top\n\t\t\t    };\n\t\t\t};\n\t\t\t\n\t\t\treturn {\n\t\t\t\t  top:\t\tgetOffset(el).top\n\t\t\t\t, left:\t\tgetOffset(el).left\n\t\t\t\t, width:\tel.offsetWidth\n\t\t\t\t, height:\tel.offsetHeight\n\t\t\t};\n\t\t}\n\n\t\t// @export\n\t\tapi.Flash = flash;\n\n\n\t\t// Check dataURI support\n\t\tapi.newImage('data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///ywAAAAAAQABAAACAUwAOw==', function (err, img){\n\t\t\tapi.support.dataURI = !(img.width != 1 || img.height != 1);\n\t\t\tflash.init();\n\t\t});\n\t})();\n})(window, window.jQuery, FileAPI);\n\n/**\n * FileAPI fallback to Flash\n *\n * @flash-developer  \"Vladimir Demidov\" <v.demidov@corp.mail.ru>\n */\n\n/*global window, FileAPI */\n(function (window, jQuery, api) {\n    \"use strict\";\n\n    var _each = api.each,\n        _cameraQueue = [];\n\n\n    if (api.support.flash && (api.media && !api.support.media)) {\n        (function () {\n\n            function _wrap(fn) {\n                var id = fn.wid = api.uid();\n                api.Flash._fn[id] = fn;\n                return 'FileAPI.Flash._fn.' + id;\n            }\n\n\n            function _unwrap(fn) {\n                try {\n                    api.Flash._fn[fn.wid] = null;\n                    delete api.Flash._fn[fn.wid];\n                } catch (e) {\n                }\n            }\n\n            var flash = api.Flash;\n            api.extend(api.Flash, {\n\n                patchCamera: function () {\n                    api.Camera.fallback = function (el, options, callback) {\n                        var camId = api.uid();\n                        api.log('FlashAPI.Camera.publish: ' + camId);\n                        flash.publish(el, camId, api.extend(options, {\n                            camera: true,\n                            onEvent: _wrap(function _(evt) {\n                                if (evt.type === 'camera') {\n                                    _unwrap(_);\n\n                                    if (evt.error) {\n                                        api.log('FlashAPI.Camera.publish.error: ' + evt.error);\n                                        callback(evt.error);\n                                    } else {\n                                        api.log('FlashAPI.Camera.publish.success: ' + camId);\n                                        callback(null);\n                                    }\n                                }\n                            })\n                        }));\n                    };\n                    // Run\n                    _each(_cameraQueue, function (args) {\n                        api.Camera.fallback.apply(api.Camera, args);\n                    });\n                    _cameraQueue = [];\n\n\n                    // FileAPI.Camera:proto\n                    api.extend(api.Camera.prototype, {\n                        _id: function () {\n                            return this.video.id;\n                        },\n\n                        start: function (callback) {\n                            var _this = this;\n                            flash.cmd(this._id(), 'camera.on', {\n                                callback: _wrap(function _(evt) {\n                                    _unwrap(_);\n\n                                    if (evt.error) {\n                                        api.log('FlashAPI.camera.on.error: ' + evt.error);\n                                        callback(evt.error, _this);\n                                    } else {\n                                        api.log('FlashAPI.camera.on.success: ' + _this._id());\n                                        _this._active = true;\n                                        callback(null, _this);\n                                    }\n                                })\n                            });\n                        },\n\n                        stop: function () {\n                            this._active = false;\n                            flash.cmd(this._id(), 'camera.off');\n                        },\n\n                        shot: function () {\n                            api.log('FlashAPI.Camera.shot:', this._id());\n\n                            var shot = api.Flash.cmd(this._id(), 'shot', {});\n                            shot.type = 'image/png';\n                            shot.flashId = this._id();\n                            shot.isShot = true;\n\n                            return new api.Camera.Shot(shot);\n                        }\n                    });\n                }\n            });\n\n            api.Camera.fallback = function () {\n                _cameraQueue.push(arguments);\n            };\n\n        }());\n    }\n}(window, window.jQuery, FileAPI));\nif( typeof define === \"function\" && define.amd ){ define(\"FileAPI\", [], function (){ return FileAPI; }); }\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/ng-file-upload/LICENSE",
    "content": "The MIT License (MIT)\n\nCopyright (c) 2013 danialfarid\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 of\nthe Software, and to permit persons to whom the Software is furnished to do so,\nsubject 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, FITNESS\nFOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\nCOPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\nIN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\nCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/ng-file-upload/README.md",
    "content": "# angular-file-upload-bower\n\nbower distribution of [angular-file-upload](https://github.com/danialfarid/angular-file-upload).\nAll issues and pull request must be sumbitted to [angular-file-upload](https://github.com/danialfarid/angular-file-upload)\n\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/ng-file-upload/bower.json",
    "content": "{\n  \"name\": \"ng-file-upload\",\n  \"main\": \"ng-file-upload.js\",\n  \"homepage\": \"https://github.com/danialfarid/ng-file-upload\",\n  \"dependencies\": {\n    \"angular\": \">1.2.0\"\n  },\n  \"authors\": [\n    \"danialf <danial.farid@gmail.com>\"\n  ],\n  \"description\": \"Lightweight Angular JS directive to upload files. Support drag&drop, paste image, progress and abort\",\n  \"ignore\": [],\n  \"license\": \"MIT\"\n }\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/ng-file-upload/ng-file-upload-all.js",
    "content": "/**!\n * AngularJS file upload directives and services. Supports: file upload/drop/paste, resume, cancel/abort,\n * progress, resize, thumbnail, preview, validation and CORS\n * FileAPI Flash shim for old browsers not supporting FormData\n * @author  Danial  <danial.farid@gmail.com>\n * @version 12.2.13\n */\n\n(function () {\n  /** @namespace FileAPI.noContentTimeout */\n\n  function patchXHR(fnName, newFn) {\n    window.XMLHttpRequest.prototype[fnName] = newFn(window.XMLHttpRequest.prototype[fnName]);\n  }\n\n  function redefineProp(xhr, prop, fn) {\n    try {\n      Object.defineProperty(xhr, prop, {get: fn});\n    } catch (e) {/*ignore*/\n    }\n  }\n\n  if (!window.FileAPI) {\n    window.FileAPI = {};\n  }\n\n  if (!window.XMLHttpRequest) {\n    throw 'AJAX is not supported. XMLHttpRequest is not defined.';\n  }\n\n  FileAPI.shouldLoad = !window.FormData || FileAPI.forceLoad;\n  if (FileAPI.shouldLoad) {\n    var initializeUploadListener = function (xhr) {\n      if (!xhr.__listeners) {\n        if (!xhr.upload) xhr.upload = {};\n        xhr.__listeners = [];\n        var origAddEventListener = xhr.upload.addEventListener;\n        xhr.upload.addEventListener = function (t, fn) {\n          xhr.__listeners[t] = fn;\n          if (origAddEventListener) origAddEventListener.apply(this, arguments);\n        };\n      }\n    };\n\n    patchXHR('open', function (orig) {\n      return function (m, url, b) {\n        initializeUploadListener(this);\n        this.__url = url;\n        try {\n          orig.apply(this, [m, url, b]);\n        } catch (e) {\n          if (e.message.indexOf('Access is denied') > -1) {\n            this.__origError = e;\n            orig.apply(this, [m, '_fix_for_ie_crossdomain__', b]);\n          }\n        }\n      };\n    });\n\n    patchXHR('getResponseHeader', function (orig) {\n      return function (h) {\n        return this.__fileApiXHR && this.__fileApiXHR.getResponseHeader ? this.__fileApiXHR.getResponseHeader(h) : (orig == null ? null : orig.apply(this, [h]));\n      };\n    });\n\n    patchXHR('getAllResponseHeaders', function (orig) {\n      return function () {\n        return this.__fileApiXHR && this.__fileApiXHR.getAllResponseHeaders ? this.__fileApiXHR.getAllResponseHeaders() : (orig == null ? null : orig.apply(this));\n      };\n    });\n\n    patchXHR('abort', function (orig) {\n      return function () {\n        return this.__fileApiXHR && this.__fileApiXHR.abort ? this.__fileApiXHR.abort() : (orig == null ? null : orig.apply(this));\n      };\n    });\n\n    patchXHR('setRequestHeader', function (orig) {\n      return function (header, value) {\n        if (header === '__setXHR_') {\n          initializeUploadListener(this);\n          var val = value(this);\n          // fix for angular < 1.2.0\n          if (val instanceof Function) {\n            val(this);\n          }\n        } else {\n          this.__requestHeaders = this.__requestHeaders || {};\n          this.__requestHeaders[header] = value;\n          orig.apply(this, arguments);\n        }\n      };\n    });\n\n    patchXHR('send', function (orig) {\n      return function () {\n        var xhr = this;\n        if (arguments[0] && arguments[0].__isFileAPIShim) {\n          var formData = arguments[0];\n          var config = {\n            url: xhr.__url,\n            jsonp: false, //removes the callback form param\n            cache: true, //removes the ?fileapiXXX in the url\n            complete: function (err, fileApiXHR) {\n              if (err && angular.isString(err) && err.indexOf('#2174') !== -1) {\n                // this error seems to be fine the file is being uploaded properly.\n                err = null;\n              }\n              xhr.__completed = true;\n              if (!err && xhr.__listeners.load)\n                xhr.__listeners.load({\n                  type: 'load',\n                  loaded: xhr.__loaded,\n                  total: xhr.__total,\n                  target: xhr,\n                  lengthComputable: true\n                });\n              if (!err && xhr.__listeners.loadend)\n                xhr.__listeners.loadend({\n                  type: 'loadend',\n                  loaded: xhr.__loaded,\n                  total: xhr.__total,\n                  target: xhr,\n                  lengthComputable: true\n                });\n              if (err === 'abort' && xhr.__listeners.abort)\n                xhr.__listeners.abort({\n                  type: 'abort',\n                  loaded: xhr.__loaded,\n                  total: xhr.__total,\n                  target: xhr,\n                  lengthComputable: true\n                });\n              if (fileApiXHR.status !== undefined) redefineProp(xhr, 'status', function () {\n                return (fileApiXHR.status === 0 && err && err !== 'abort') ? 500 : fileApiXHR.status;\n              });\n              if (fileApiXHR.statusText !== undefined) redefineProp(xhr, 'statusText', function () {\n                return fileApiXHR.statusText;\n              });\n              redefineProp(xhr, 'readyState', function () {\n                return 4;\n              });\n              if (fileApiXHR.response !== undefined) redefineProp(xhr, 'response', function () {\n                return fileApiXHR.response;\n              });\n              var resp = fileApiXHR.responseText || (err && fileApiXHR.status === 0 && err !== 'abort' ? err : undefined);\n              redefineProp(xhr, 'responseText', function () {\n                return resp;\n              });\n              redefineProp(xhr, 'response', function () {\n                return resp;\n              });\n              if (err) redefineProp(xhr, 'err', function () {\n                return err;\n              });\n              xhr.__fileApiXHR = fileApiXHR;\n              if (xhr.onreadystatechange) xhr.onreadystatechange();\n              if (xhr.onload) xhr.onload();\n            },\n            progress: function (e) {\n              e.target = xhr;\n              if (xhr.__listeners.progress) xhr.__listeners.progress(e);\n              xhr.__total = e.total;\n              xhr.__loaded = e.loaded;\n              if (e.total === e.loaded) {\n                // fix flash issue that doesn't call complete if there is no response text from the server\n                var _this = this;\n                setTimeout(function () {\n                  if (!xhr.__completed) {\n                    xhr.getAllResponseHeaders = function () {\n                    };\n                    _this.complete(null, {status: 204, statusText: 'No Content'});\n                  }\n                }, FileAPI.noContentTimeout || 10000);\n              }\n            },\n            headers: xhr.__requestHeaders\n          };\n          config.data = {};\n          config.files = {};\n          for (var i = 0; i < formData.data.length; i++) {\n            var item = formData.data[i];\n            if (item.val != null && item.val.name != null && item.val.size != null && item.val.type != null) {\n              config.files[item.key] = item.val;\n            } else {\n              config.data[item.key] = item.val;\n            }\n          }\n\n          setTimeout(function () {\n            if (!FileAPI.hasFlash) {\n              throw 'Adode Flash Player need to be installed. To check ahead use \"FileAPI.hasFlash\"';\n            }\n            xhr.__fileApiXHR = FileAPI.upload(config);\n          }, 1);\n        } else {\n          if (this.__origError) {\n            throw this.__origError;\n          }\n          orig.apply(xhr, arguments);\n        }\n      };\n    });\n    window.XMLHttpRequest.__isFileAPIShim = true;\n    window.FormData = FormData = function () {\n      return {\n        append: function (key, val, name) {\n          if (val.__isFileAPIBlobShim) {\n            val = val.data[0];\n          }\n          this.data.push({\n            key: key,\n            val: val,\n            name: name\n          });\n        },\n        data: [],\n        __isFileAPIShim: true\n      };\n    };\n\n    window.Blob = Blob = function (b) {\n      return {\n        data: b,\n        __isFileAPIBlobShim: true\n      };\n    };\n  }\n\n})();\n\n(function () {\n  /** @namespace FileAPI.forceLoad */\n  /** @namespace window.FileAPI.jsUrl */\n  /** @namespace window.FileAPI.jsPath */\n\n  function isInputTypeFile(elem) {\n    return elem[0].tagName.toLowerCase() === 'input' && elem.attr('type') && elem.attr('type').toLowerCase() === 'file';\n  }\n\n  function hasFlash() {\n    try {\n      var fo = new ActiveXObject('ShockwaveFlash.ShockwaveFlash');\n      if (fo) return true;\n    } catch (e) {\n      if (navigator.mimeTypes['application/x-shockwave-flash'] !== undefined) return true;\n    }\n    return false;\n  }\n\n  function getOffset(obj) {\n    var left = 0, top = 0;\n\n    if (window.jQuery) {\n      return jQuery(obj).offset();\n    }\n\n    if (obj.offsetParent) {\n      do {\n        left += (obj.offsetLeft - obj.scrollLeft);\n        top += (obj.offsetTop - obj.scrollTop);\n        obj = obj.offsetParent;\n      } while (obj);\n    }\n    return {\n      left: left,\n      top: top\n    };\n  }\n\n  if (FileAPI.shouldLoad) {\n    FileAPI.hasFlash = hasFlash();\n\n    //load FileAPI\n    if (FileAPI.forceLoad) {\n      FileAPI.html5 = false;\n    }\n\n    if (!FileAPI.upload) {\n      var jsUrl, basePath, script = document.createElement('script'), allScripts = document.getElementsByTagName('script'), i, index, src;\n      if (window.FileAPI.jsUrl) {\n        jsUrl = window.FileAPI.jsUrl;\n      } else if (window.FileAPI.jsPath) {\n        basePath = window.FileAPI.jsPath;\n      } else {\n        for (i = 0; i < allScripts.length; i++) {\n          src = allScripts[i].src;\n          index = src.search(/\\/ng\\-file\\-upload[\\-a-zA-z0-9\\.]*\\.js/);\n          if (index > -1) {\n            basePath = src.substring(0, index + 1);\n            break;\n          }\n        }\n      }\n\n      if (FileAPI.staticPath == null) FileAPI.staticPath = basePath;\n      script.setAttribute('src', jsUrl || basePath + 'FileAPI.min.js');\n      document.getElementsByTagName('head')[0].appendChild(script);\n    }\n\n    FileAPI.ngfFixIE = function (elem, fileElem, changeFn) {\n      if (!hasFlash()) {\n        throw 'Adode Flash Player need to be installed. To check ahead use \"FileAPI.hasFlash\"';\n      }\n      var fixInputStyle = function () {\n        var label = fileElem.parent();\n        if (elem.attr('disabled')) {\n          if (label) label.removeClass('js-fileapi-wrapper');\n        } else {\n          if (!fileElem.attr('__ngf_flash_')) {\n            fileElem.unbind('change');\n            fileElem.unbind('click');\n            fileElem.bind('change', function (evt) {\n              fileApiChangeFn.apply(this, [evt]);\n              changeFn.apply(this, [evt]);\n            });\n            fileElem.attr('__ngf_flash_', 'true');\n          }\n          label.addClass('js-fileapi-wrapper');\n          if (!isInputTypeFile(elem)) {\n            label.css('position', 'absolute')\n              .css('top', getOffset(elem[0]).top + 'px').css('left', getOffset(elem[0]).left + 'px')\n              .css('width', elem[0].offsetWidth + 'px').css('height', elem[0].offsetHeight + 'px')\n              .css('filter', 'alpha(opacity=0)').css('display', elem.css('display'))\n              .css('overflow', 'hidden').css('z-index', '900000')\n              .css('visibility', 'visible');\n            fileElem.css('width', elem[0].offsetWidth + 'px').css('height', elem[0].offsetHeight + 'px')\n              .css('position', 'absolute').css('top', '0px').css('left', '0px');\n          }\n        }\n      };\n\n      elem.bind('mouseenter', fixInputStyle);\n\n      var fileApiChangeFn = function (evt) {\n        var files = FileAPI.getFiles(evt);\n        //just a double check for #233\n        for (var i = 0; i < files.length; i++) {\n          if (files[i].size === undefined) files[i].size = 0;\n          if (files[i].name === undefined) files[i].name = 'file';\n          if (files[i].type === undefined) files[i].type = 'undefined';\n        }\n        if (!evt.target) {\n          evt.target = {};\n        }\n        evt.target.files = files;\n        // if evt.target.files is not writable use helper field\n        if (evt.target.files !== files) {\n          evt.__files_ = files;\n        }\n        (evt.__files_ || evt.target.files).item = function (i) {\n          return (evt.__files_ || evt.target.files)[i] || null;\n        };\n      };\n    };\n\n    FileAPI.disableFileInput = function (elem, disable) {\n      if (disable) {\n        elem.removeClass('js-fileapi-wrapper');\n      } else {\n        elem.addClass('js-fileapi-wrapper');\n      }\n    };\n  }\n})();\n\nif (!window.FileReader) {\n  window.FileReader = function () {\n    var _this = this, loadStarted = false;\n    this.listeners = {};\n    this.addEventListener = function (type, fn) {\n      _this.listeners[type] = _this.listeners[type] || [];\n      _this.listeners[type].push(fn);\n    };\n    this.removeEventListener = function (type, fn) {\n      if (_this.listeners[type]) _this.listeners[type].splice(_this.listeners[type].indexOf(fn), 1);\n    };\n    this.dispatchEvent = function (evt) {\n      var list = _this.listeners[evt.type];\n      if (list) {\n        for (var i = 0; i < list.length; i++) {\n          list[i].call(_this, evt);\n        }\n      }\n    };\n    this.onabort = this.onerror = this.onload = this.onloadstart = this.onloadend = this.onprogress = null;\n\n    var constructEvent = function (type, evt) {\n      var e = {type: type, target: _this, loaded: evt.loaded, total: evt.total, error: evt.error};\n      if (evt.result != null) e.target.result = evt.result;\n      return e;\n    };\n    var listener = function (evt) {\n      if (!loadStarted) {\n        loadStarted = true;\n        if (_this.onloadstart) _this.onloadstart(constructEvent('loadstart', evt));\n      }\n      var e;\n      if (evt.type === 'load') {\n        if (_this.onloadend) _this.onloadend(constructEvent('loadend', evt));\n        e = constructEvent('load', evt);\n        if (_this.onload) _this.onload(e);\n        _this.dispatchEvent(e);\n      } else if (evt.type === 'progress') {\n        e = constructEvent('progress', evt);\n        if (_this.onprogress) _this.onprogress(e);\n        _this.dispatchEvent(e);\n      } else {\n        e = constructEvent('error', evt);\n        if (_this.onerror) _this.onerror(e);\n        _this.dispatchEvent(e);\n      }\n    };\n    this.readAsDataURL = function (file) {\n      FileAPI.readAsDataURL(file, listener);\n    };\n    this.readAsText = function (file) {\n      FileAPI.readAsText(file, listener);\n    };\n  };\n}\n\n/**!\n * AngularJS file upload directives and services. Supoorts: file upload/drop/paste, resume, cancel/abort,\n * progress, resize, thumbnail, preview, validation and CORS\n * @author  Danial  <danial.farid@gmail.com>\n * @version 12.2.13\n */\n\nif (window.XMLHttpRequest && !(window.FileAPI && FileAPI.shouldLoad)) {\n  window.XMLHttpRequest.prototype.setRequestHeader = (function (orig) {\n    return function (header, value) {\n      if (header === '__setXHR_') {\n        var val = value(this);\n        // fix for angular < 1.2.0\n        if (val instanceof Function) {\n          val(this);\n        }\n      } else {\n        orig.apply(this, arguments);\n      }\n    };\n  })(window.XMLHttpRequest.prototype.setRequestHeader);\n}\n\nvar ngFileUpload = angular.module('ngFileUpload', []);\n\nngFileUpload.version = '12.2.13';\n\nngFileUpload.service('UploadBase', ['$http', '$q', '$timeout', function ($http, $q, $timeout) {\n  var upload = this;\n  upload.promisesCount = 0;\n\n  this.isResumeSupported = function () {\n    return window.Blob && window.Blob.prototype.slice;\n  };\n\n  var resumeSupported = this.isResumeSupported();\n\n  function sendHttp(config) {\n    config.method = config.method || 'POST';\n    config.headers = config.headers || {};\n\n    var deferred = config._deferred = config._deferred || $q.defer();\n    var promise = deferred.promise;\n\n    function notifyProgress(e) {\n      if (deferred.notify) {\n        deferred.notify(e);\n      }\n      if (promise.progressFunc) {\n        $timeout(function () {\n          promise.progressFunc(e);\n        });\n      }\n    }\n\n    function getNotifyEvent(n) {\n      if (config._start != null && resumeSupported) {\n        return {\n          loaded: n.loaded + config._start,\n          total: (config._file && config._file.size) || n.total,\n          type: n.type, config: config,\n          lengthComputable: true, target: n.target\n        };\n      } else {\n        return n;\n      }\n    }\n\n    if (!config.disableProgress) {\n      config.headers.__setXHR_ = function () {\n        return function (xhr) {\n          if (!xhr || !xhr.upload || !xhr.upload.addEventListener) return;\n          config.__XHR = xhr;\n          if (config.xhrFn) config.xhrFn(xhr);\n          xhr.upload.addEventListener('progress', function (e) {\n            e.config = config;\n            notifyProgress(getNotifyEvent(e));\n          }, false);\n          //fix for firefox not firing upload progress end, also IE8-9\n          xhr.upload.addEventListener('load', function (e) {\n            if (e.lengthComputable) {\n              e.config = config;\n              notifyProgress(getNotifyEvent(e));\n            }\n          }, false);\n        };\n      };\n    }\n\n    function uploadWithAngular() {\n      $http(config).then(function (r) {\n          if (resumeSupported && config._chunkSize && !config._finished && config._file) {\n            var fileSize = config._file && config._file.size || 0;\n            notifyProgress({\n                loaded: Math.min(config._end, fileSize),\n                total: fileSize,\n                config: config,\n                type: 'progress'\n              }\n            );\n            upload.upload(config, true);\n          } else {\n            if (config._finished) delete config._finished;\n            deferred.resolve(r);\n          }\n        }, function (e) {\n          deferred.reject(e);\n        }, function (n) {\n          deferred.notify(n);\n        }\n      );\n    }\n\n    if (!resumeSupported) {\n      uploadWithAngular();\n    } else if (config._chunkSize && config._end && !config._finished) {\n      config._start = config._end;\n      config._end += config._chunkSize;\n      uploadWithAngular();\n    } else if (config.resumeSizeUrl) {\n      $http.get(config.resumeSizeUrl).then(function (resp) {\n        if (config.resumeSizeResponseReader) {\n          config._start = config.resumeSizeResponseReader(resp.data);\n        } else {\n          config._start = parseInt((resp.data.size == null ? resp.data : resp.data.size).toString());\n        }\n        if (config._chunkSize) {\n          config._end = config._start + config._chunkSize;\n        }\n        uploadWithAngular();\n      }, function (e) {\n        throw e;\n      });\n    } else if (config.resumeSize) {\n      config.resumeSize().then(function (size) {\n        config._start = size;\n        if (config._chunkSize) {\n          config._end = config._start + config._chunkSize;\n        }\n        uploadWithAngular();\n      }, function (e) {\n        throw e;\n      });\n    } else {\n      if (config._chunkSize) {\n        config._start = 0;\n        config._end = config._start + config._chunkSize;\n      }\n      uploadWithAngular();\n    }\n\n\n    promise.success = function (fn) {\n      promise.then(function (response) {\n        fn(response.data, response.status, response.headers, config);\n      });\n      return promise;\n    };\n\n    promise.error = function (fn) {\n      promise.then(null, function (response) {\n        fn(response.data, response.status, response.headers, config);\n      });\n      return promise;\n    };\n\n    promise.progress = function (fn) {\n      promise.progressFunc = fn;\n      promise.then(null, null, function (n) {\n        fn(n);\n      });\n      return promise;\n    };\n    promise.abort = promise.pause = function () {\n      if (config.__XHR) {\n        $timeout(function () {\n          config.__XHR.abort();\n        });\n      }\n      return promise;\n    };\n    promise.xhr = function (fn) {\n      config.xhrFn = (function (origXhrFn) {\n        return function () {\n          if (origXhrFn) origXhrFn.apply(promise, arguments);\n          fn.apply(promise, arguments);\n        };\n      })(config.xhrFn);\n      return promise;\n    };\n\n    upload.promisesCount++;\n    if (promise['finally'] && promise['finally'] instanceof Function) {\n      promise['finally'](function () {\n        upload.promisesCount--;\n      });\n    }\n    return promise;\n  }\n\n  this.isUploadInProgress = function () {\n    return upload.promisesCount > 0;\n  };\n\n  this.rename = function (file, name) {\n    file.ngfName = name;\n    return file;\n  };\n\n  this.jsonBlob = function (val) {\n    if (val != null && !angular.isString(val)) {\n      val = JSON.stringify(val);\n    }\n    var blob = new window.Blob([val], {type: 'application/json'});\n    blob._ngfBlob = true;\n    return blob;\n  };\n\n  this.json = function (val) {\n    return angular.toJson(val);\n  };\n\n  function copy(obj) {\n    var clone = {};\n    for (var key in obj) {\n      if (obj.hasOwnProperty(key)) {\n        clone[key] = obj[key];\n      }\n    }\n    return clone;\n  }\n\n  this.isFile = function (file) {\n    return file != null && (file instanceof window.Blob || (file.flashId && file.name && file.size));\n  };\n\n  this.upload = function (config, internal) {\n    function toResumeFile(file, formData) {\n      if (file._ngfBlob) return file;\n      config._file = config._file || file;\n      if (config._start != null && resumeSupported) {\n        if (config._end && config._end >= file.size) {\n          config._finished = true;\n          config._end = file.size;\n        }\n        var slice = file.slice(config._start, config._end || file.size);\n        slice.name = file.name;\n        slice.ngfName = file.ngfName;\n        if (config._chunkSize) {\n          formData.append('_chunkSize', config._chunkSize);\n          formData.append('_currentChunkSize', config._end - config._start);\n          formData.append('_chunkNumber', Math.floor(config._start / config._chunkSize));\n          formData.append('_totalSize', config._file.size);\n        }\n        return slice;\n      }\n      return file;\n    }\n\n    function addFieldToFormData(formData, val, key) {\n      if (val !== undefined) {\n        if (angular.isDate(val)) {\n          val = val.toISOString();\n        }\n        if (angular.isString(val)) {\n          formData.append(key, val);\n        } else if (upload.isFile(val)) {\n          var file = toResumeFile(val, formData);\n          var split = key.split(',');\n          if (split[1]) {\n            file.ngfName = split[1].replace(/^\\s+|\\s+$/g, '');\n            key = split[0];\n          }\n          config._fileKey = config._fileKey || key;\n          formData.append(key, file, file.ngfName || file.name);\n        } else {\n          if (angular.isObject(val)) {\n            if (val.$$ngfCircularDetection) throw 'ngFileUpload: Circular reference in config.data. Make sure specified data for Upload.upload() has no circular reference: ' + key;\n\n            val.$$ngfCircularDetection = true;\n            try {\n              for (var k in val) {\n                if (val.hasOwnProperty(k) && k !== '$$ngfCircularDetection') {\n                  var objectKey = config.objectKey == null ? '[i]' : config.objectKey;\n                  if (val.length && parseInt(k) > -1) {\n                    objectKey = config.arrayKey == null ? objectKey : config.arrayKey;\n                  }\n                  addFieldToFormData(formData, val[k], key + objectKey.replace(/[ik]/g, k));\n                }\n              }\n            } finally {\n              delete val.$$ngfCircularDetection;\n            }\n          } else {\n            formData.append(key, val);\n          }\n        }\n      }\n    }\n\n    function digestConfig() {\n      config._chunkSize = upload.translateScalars(config.resumeChunkSize);\n      config._chunkSize = config._chunkSize ? parseInt(config._chunkSize.toString()) : null;\n\n      config.headers = config.headers || {};\n      config.headers['Content-Type'] = undefined;\n      config.transformRequest = config.transformRequest ?\n        (angular.isArray(config.transformRequest) ?\n          config.transformRequest : [config.transformRequest]) : [];\n      config.transformRequest.push(function (data) {\n        var formData = new window.FormData(), key;\n        data = data || config.fields || {};\n        if (config.file) {\n          data.file = config.file;\n        }\n        for (key in data) {\n          if (data.hasOwnProperty(key)) {\n            var val = data[key];\n            if (config.formDataAppender) {\n              config.formDataAppender(formData, key, val);\n            } else {\n              addFieldToFormData(formData, val, key);\n            }\n          }\n        }\n\n        return formData;\n      });\n    }\n\n    if (!internal) config = copy(config);\n    if (!config._isDigested) {\n      config._isDigested = true;\n      digestConfig();\n    }\n\n    return sendHttp(config);\n  };\n\n  this.http = function (config) {\n    config = copy(config);\n    config.transformRequest = config.transformRequest || function (data) {\n        if ((window.ArrayBuffer && data instanceof window.ArrayBuffer) || data instanceof window.Blob) {\n          return data;\n        }\n        return $http.defaults.transformRequest[0].apply(this, arguments);\n      };\n    config._chunkSize = upload.translateScalars(config.resumeChunkSize);\n    config._chunkSize = config._chunkSize ? parseInt(config._chunkSize.toString()) : null;\n\n    return sendHttp(config);\n  };\n\n  this.translateScalars = function (str) {\n    if (angular.isString(str)) {\n      if (str.search(/kb/i) === str.length - 2) {\n        return parseFloat(str.substring(0, str.length - 2) * 1024);\n      } else if (str.search(/mb/i) === str.length - 2) {\n        return parseFloat(str.substring(0, str.length - 2) * 1048576);\n      } else if (str.search(/gb/i) === str.length - 2) {\n        return parseFloat(str.substring(0, str.length - 2) * 1073741824);\n      } else if (str.search(/b/i) === str.length - 1) {\n        return parseFloat(str.substring(0, str.length - 1));\n      } else if (str.search(/s/i) === str.length - 1) {\n        return parseFloat(str.substring(0, str.length - 1));\n      } else if (str.search(/m/i) === str.length - 1) {\n        return parseFloat(str.substring(0, str.length - 1) * 60);\n      } else if (str.search(/h/i) === str.length - 1) {\n        return parseFloat(str.substring(0, str.length - 1) * 3600);\n      }\n    }\n    return str;\n  };\n\n  this.urlToBlob = function(url) {\n    var defer = $q.defer();\n    $http({url: url, method: 'get', responseType: 'arraybuffer'}).then(function (resp) {\n      var arrayBufferView = new Uint8Array(resp.data);\n      var type = resp.headers('content-type') || 'image/WebP';\n      var blob = new window.Blob([arrayBufferView], {type: type});\n      var matches = url.match(/.*\\/(.+?)(\\?.*)?$/);\n      if (matches.length > 1) {\n        blob.name = matches[1];\n      }\n      defer.resolve(blob);\n    }, function (e) {\n      defer.reject(e);\n    });\n    return defer.promise;\n  };\n\n  this.setDefaults = function (defaults) {\n    this.defaults = defaults || {};\n  };\n\n  this.defaults = {};\n  this.version = ngFileUpload.version;\n}\n\n]);\n\nngFileUpload.service('Upload', ['$parse', '$timeout', '$compile', '$q', 'UploadExif', function ($parse, $timeout, $compile, $q, UploadExif) {\n  var upload = UploadExif;\n  upload.getAttrWithDefaults = function (attr, name) {\n    if (attr[name] != null) return attr[name];\n    var def = upload.defaults[name];\n    return (def == null ? def : (angular.isString(def) ? def : JSON.stringify(def)));\n  };\n\n  upload.attrGetter = function (name, attr, scope, params) {\n    var attrVal = this.getAttrWithDefaults(attr, name);\n    if (scope) {\n      try {\n        if (params) {\n          return $parse(attrVal)(scope, params);\n        } else {\n          return $parse(attrVal)(scope);\n        }\n      } catch (e) {\n        // hangle string value without single qoute\n        if (name.search(/min|max|pattern/i)) {\n          return attrVal;\n        } else {\n          throw e;\n        }\n      }\n    } else {\n      return attrVal;\n    }\n  };\n\n  upload.shouldUpdateOn = function (type, attr, scope) {\n    var modelOptions = upload.attrGetter('ngfModelOptions', attr, scope);\n    if (modelOptions && modelOptions.updateOn) {\n      return modelOptions.updateOn.split(' ').indexOf(type) > -1;\n    }\n    return true;\n  };\n\n  upload.emptyPromise = function () {\n    var d = $q.defer();\n    var args = arguments;\n    $timeout(function () {\n      d.resolve.apply(d, args);\n    });\n    return d.promise;\n  };\n\n  upload.rejectPromise = function () {\n    var d = $q.defer();\n    var args = arguments;\n    $timeout(function () {\n      d.reject.apply(d, args);\n    });\n    return d.promise;\n  };\n\n  upload.happyPromise = function (promise, data) {\n    var d = $q.defer();\n    promise.then(function (result) {\n      d.resolve(result);\n    }, function (error) {\n      $timeout(function () {\n        throw error;\n      });\n      d.resolve(data);\n    });\n    return d.promise;\n  };\n\n  function applyExifRotations(files, attr, scope) {\n    var promises = [upload.emptyPromise()];\n    angular.forEach(files, function (f, i) {\n      if (f.type.indexOf('image/jpeg') === 0 && upload.attrGetter('ngfFixOrientation', attr, scope, {$file: f})) {\n        promises.push(upload.happyPromise(upload.applyExifRotation(f), f).then(function (fixedFile) {\n          files.splice(i, 1, fixedFile);\n        }));\n      }\n    });\n    return $q.all(promises);\n  }\n\n  function resizeFile(files, attr, scope, ngModel) {\n    var resizeVal = upload.attrGetter('ngfResize', attr, scope);\n    if (!resizeVal || !upload.isResizeSupported() || !files.length) return upload.emptyPromise();\n    if (resizeVal instanceof Function) {\n      var defer = $q.defer();\n      return resizeVal(files).then(function (p) {\n        resizeWithParams(p, files, attr, scope, ngModel).then(function (r) {\n          defer.resolve(r);\n        }, function (e) {\n          defer.reject(e);\n        });\n      }, function (e) {\n        defer.reject(e);\n      });\n    } else {\n      return resizeWithParams(resizeVal, files, attr, scope, ngModel);\n    }\n  }\n\n  function resizeWithParams(params, files, attr, scope, ngModel) {\n    var promises = [upload.emptyPromise()];\n\n    function handleFile(f, i) {\n      if (f.type.indexOf('image') === 0) {\n        if (params.pattern && !upload.validatePattern(f, params.pattern)) return;\n        params.resizeIf = function (width, height) {\n          return upload.attrGetter('ngfResizeIf', attr, scope,\n            {$width: width, $height: height, $file: f});\n        };\n        var promise = upload.resize(f, params);\n        promises.push(promise);\n        promise.then(function (resizedFile) {\n          files.splice(i, 1, resizedFile);\n        }, function (e) {\n          f.$error = 'resize';\n          (f.$errorMessages = (f.$errorMessages || {})).resize = true;\n          f.$errorParam = (e ? (e.message ? e.message : e) + ': ' : '') + (f && f.name);\n          ngModel.$ngfValidations.push({name: 'resize', valid: false});\n          upload.applyModelValidation(ngModel, files);\n        });\n      }\n    }\n\n    for (var i = 0; i < files.length; i++) {\n      handleFile(files[i], i);\n    }\n    return $q.all(promises);\n  }\n\n  upload.updateModel = function (ngModel, attr, scope, fileChange, files, evt, noDelay) {\n    function update(files, invalidFiles, newFiles, dupFiles, isSingleModel) {\n      attr.$$ngfPrevValidFiles = files;\n      attr.$$ngfPrevInvalidFiles = invalidFiles;\n      var file = files && files.length ? files[0] : null;\n      var invalidFile = invalidFiles && invalidFiles.length ? invalidFiles[0] : null;\n\n      if (ngModel) {\n        upload.applyModelValidation(ngModel, files);\n        ngModel.$setViewValue(isSingleModel ? file : files);\n      }\n\n      if (fileChange) {\n        $parse(fileChange)(scope, {\n          $files: files,\n          $file: file,\n          $newFiles: newFiles,\n          $duplicateFiles: dupFiles,\n          $invalidFiles: invalidFiles,\n          $invalidFile: invalidFile,\n          $event: evt\n        });\n      }\n\n      var invalidModel = upload.attrGetter('ngfModelInvalid', attr);\n      if (invalidModel) {\n        $timeout(function () {\n          $parse(invalidModel).assign(scope, isSingleModel ? invalidFile : invalidFiles);\n        });\n      }\n      $timeout(function () {\n        // scope apply changes\n      });\n    }\n\n    var allNewFiles, dupFiles = [], prevValidFiles, prevInvalidFiles,\n      invalids = [], valids = [];\n\n    function removeDuplicates() {\n      function equals(f1, f2) {\n        return f1.name === f2.name && (f1.$ngfOrigSize || f1.size) === (f2.$ngfOrigSize || f2.size) &&\n          f1.type === f2.type;\n      }\n\n      function isInPrevFiles(f) {\n        var j;\n        for (j = 0; j < prevValidFiles.length; j++) {\n          if (equals(f, prevValidFiles[j])) {\n            return true;\n          }\n        }\n        for (j = 0; j < prevInvalidFiles.length; j++) {\n          if (equals(f, prevInvalidFiles[j])) {\n            return true;\n          }\n        }\n        return false;\n      }\n\n      if (files) {\n        allNewFiles = [];\n        dupFiles = [];\n        for (var i = 0; i < files.length; i++) {\n          if (isInPrevFiles(files[i])) {\n            dupFiles.push(files[i]);\n          } else {\n            allNewFiles.push(files[i]);\n          }\n        }\n      }\n    }\n\n    function toArray(v) {\n      return angular.isArray(v) ? v : [v];\n    }\n\n    function resizeAndUpdate() {\n      function updateModel() {\n        $timeout(function () {\n          update(keep ? prevValidFiles.concat(valids) : valids,\n            keep ? prevInvalidFiles.concat(invalids) : invalids,\n            files, dupFiles, isSingleModel);\n        }, options && options.debounce ? options.debounce.change || options.debounce : 0);\n      }\n\n      var resizingFiles = validateAfterResize ? allNewFiles : valids;\n      resizeFile(resizingFiles, attr, scope, ngModel).then(function () {\n        if (validateAfterResize) {\n          upload.validate(allNewFiles, keep ? prevValidFiles.length : 0, ngModel, attr, scope)\n            .then(function (validationResult) {\n              valids = validationResult.validsFiles;\n              invalids = validationResult.invalidsFiles;\n              updateModel();\n            });\n        } else {\n          updateModel();\n        }\n      }, function () {\n        for (var i = 0; i < resizingFiles.length; i++) {\n          var f = resizingFiles[i];\n          if (f.$error === 'resize') {\n            var index = valids.indexOf(f);\n            if (index > -1) {\n              valids.splice(index, 1);\n              invalids.push(f);\n            }\n            updateModel();\n          }\n        }\n      });\n    }\n\n    prevValidFiles = attr.$$ngfPrevValidFiles || [];\n    prevInvalidFiles = attr.$$ngfPrevInvalidFiles || [];\n    if (ngModel && ngModel.$modelValue) {\n      prevValidFiles = toArray(ngModel.$modelValue);\n    }\n\n    var keep = upload.attrGetter('ngfKeep', attr, scope);\n    allNewFiles = (files || []).slice(0);\n    if (keep === 'distinct' || upload.attrGetter('ngfKeepDistinct', attr, scope) === true) {\n      removeDuplicates(attr, scope);\n    }\n\n    var isSingleModel = !keep && !upload.attrGetter('ngfMultiple', attr, scope) && !upload.attrGetter('multiple', attr);\n\n    if (keep && !allNewFiles.length) return;\n\n    upload.attrGetter('ngfBeforeModelChange', attr, scope, {\n      $files: files,\n      $file: files && files.length ? files[0] : null,\n      $newFiles: allNewFiles,\n      $duplicateFiles: dupFiles,\n      $event: evt\n    });\n\n    var validateAfterResize = upload.attrGetter('ngfValidateAfterResize', attr, scope);\n\n    var options = upload.attrGetter('ngfModelOptions', attr, scope);\n    upload.validate(allNewFiles, keep ? prevValidFiles.length : 0, ngModel, attr, scope)\n      .then(function (validationResult) {\n      if (noDelay) {\n        update(allNewFiles, [], files, dupFiles, isSingleModel);\n      } else {\n        if ((!options || !options.allowInvalid) && !validateAfterResize) {\n          valids = validationResult.validFiles;\n          invalids = validationResult.invalidFiles;\n        } else {\n          valids = allNewFiles;\n        }\n        if (upload.attrGetter('ngfFixOrientation', attr, scope) && upload.isExifSupported()) {\n          applyExifRotations(valids, attr, scope).then(function () {\n            resizeAndUpdate();\n          });\n        } else {\n          resizeAndUpdate();\n        }\n      }\n    });\n  };\n\n  return upload;\n}]);\n\nngFileUpload.directive('ngfSelect', ['$parse', '$timeout', '$compile', 'Upload', function ($parse, $timeout, $compile, Upload) {\n  var generatedElems = [];\n\n  function isDelayedClickSupported(ua) {\n    // fix for android native browser < 4.4 and safari windows\n    var m = ua.match(/Android[^\\d]*(\\d+)\\.(\\d+)/);\n    if (m && m.length > 2) {\n      var v = Upload.defaults.androidFixMinorVersion || 4;\n      return parseInt(m[1]) < 4 || (parseInt(m[1]) === v && parseInt(m[2]) < v);\n    }\n\n    // safari on windows\n    return ua.indexOf('Chrome') === -1 && /.*Windows.*Safari.*/.test(ua);\n  }\n\n  function linkFileSelect(scope, elem, attr, ngModel, $parse, $timeout, $compile, upload) {\n    /** @namespace attr.ngfSelect */\n    /** @namespace attr.ngfChange */\n    /** @namespace attr.ngModel */\n    /** @namespace attr.ngfModelOptions */\n    /** @namespace attr.ngfMultiple */\n    /** @namespace attr.ngfCapture */\n    /** @namespace attr.ngfValidate */\n    /** @namespace attr.ngfKeep */\n    var attrGetter = function (name, scope) {\n      return upload.attrGetter(name, attr, scope);\n    };\n\n    function isInputTypeFile() {\n      return elem[0].tagName.toLowerCase() === 'input' && attr.type && attr.type.toLowerCase() === 'file';\n    }\n\n    function fileChangeAttr() {\n      return attrGetter('ngfChange') || attrGetter('ngfSelect');\n    }\n\n    function changeFn(evt) {\n      if (upload.shouldUpdateOn('change', attr, scope)) {\n        var fileList = evt.__files_ || (evt.target && evt.target.files), files = [];\n        /* Handle duplicate call in  IE11 */\n        if (!fileList) return;\n        for (var i = 0; i < fileList.length; i++) {\n          files.push(fileList[i]);\n        }\n        upload.updateModel(ngModel, attr, scope, fileChangeAttr(),\n          files.length ? files : null, evt);\n      }\n    }\n\n    upload.registerModelChangeValidator(ngModel, attr, scope);\n\n    var unwatches = [];\n    if (attrGetter('ngfMultiple')) {\n      unwatches.push(scope.$watch(attrGetter('ngfMultiple'), function () {\n        fileElem.attr('multiple', attrGetter('ngfMultiple', scope));\n      }));\n    }\n    if (attrGetter('ngfCapture')) {\n      unwatches.push(scope.$watch(attrGetter('ngfCapture'), function () {\n        fileElem.attr('capture', attrGetter('ngfCapture', scope));\n      }));\n    }\n    if (attrGetter('ngfAccept')) {\n      unwatches.push(scope.$watch(attrGetter('ngfAccept'), function () {\n        fileElem.attr('accept', attrGetter('ngfAccept', scope));\n      }));\n    }\n    unwatches.push(attr.$observe('accept', function () {\n      fileElem.attr('accept', attrGetter('accept'));\n    }));\n    function bindAttrToFileInput(fileElem, label) {\n      function updateId(val) {\n        fileElem.attr('id', 'ngf-' + val);\n        label.attr('id', 'ngf-label-' + val);\n      }\n\n      for (var i = 0; i < elem[0].attributes.length; i++) {\n        var attribute = elem[0].attributes[i];\n        if (attribute.name !== 'type' && attribute.name !== 'class' && attribute.name !== 'style') {\n          if (attribute.name === 'id') {\n            updateId(attribute.value);\n            unwatches.push(attr.$observe('id', updateId));\n          } else {\n            fileElem.attr(attribute.name, (!attribute.value && (attribute.name === 'required' ||\n            attribute.name === 'multiple')) ? attribute.name : attribute.value);\n          }\n        }\n      }\n    }\n\n    function createFileInput() {\n      if (isInputTypeFile()) {\n        return elem;\n      }\n\n      var fileElem = angular.element('<input type=\"file\">');\n\n      var label = angular.element('<label>upload</label>');\n      label.css('visibility', 'hidden').css('position', 'absolute').css('overflow', 'hidden')\n        .css('width', '0px').css('height', '0px').css('border', 'none')\n        .css('margin', '0px').css('padding', '0px').attr('tabindex', '-1');\n      bindAttrToFileInput(fileElem, label);\n\n      generatedElems.push({el: elem, ref: label});\n\n      document.body.appendChild(label.append(fileElem)[0]);\n\n      return fileElem;\n    }\n\n    function clickHandler(evt) {\n      if (elem.attr('disabled')) return false;\n      if (attrGetter('ngfSelectDisabled', scope)) return;\n\n      var r = detectSwipe(evt);\n      // prevent the click if it is a swipe\n      if (r != null) return r;\n\n      resetModel(evt);\n\n      // fix for md when the element is removed from the DOM and added back #460\n      try {\n        if (!isInputTypeFile() && !document.body.contains(fileElem[0])) {\n          generatedElems.push({el: elem, ref: fileElem.parent()});\n          document.body.appendChild(fileElem.parent()[0]);\n          fileElem.bind('change', changeFn);\n        }\n      } catch (e) {/*ignore*/\n      }\n\n      if (isDelayedClickSupported(navigator.userAgent)) {\n        setTimeout(function () {\n          fileElem[0].click();\n        }, 0);\n      } else {\n        fileElem[0].click();\n      }\n\n      return false;\n    }\n\n\n    var initialTouchStartY = 0;\n    var initialTouchStartX = 0;\n\n    function detectSwipe(evt) {\n      var touches = evt.changedTouches || (evt.originalEvent && evt.originalEvent.changedTouches);\n      if (touches) {\n        if (evt.type === 'touchstart') {\n          initialTouchStartX = touches[0].clientX;\n          initialTouchStartY = touches[0].clientY;\n          return true; // don't block event default\n        } else {\n          // prevent scroll from triggering event\n          if (evt.type === 'touchend') {\n            var currentX = touches[0].clientX;\n            var currentY = touches[0].clientY;\n            if ((Math.abs(currentX - initialTouchStartX) > 20) ||\n              (Math.abs(currentY - initialTouchStartY) > 20)) {\n              evt.stopPropagation();\n              evt.preventDefault();\n              return false;\n            }\n          }\n          return true;\n        }\n      }\n    }\n\n    var fileElem = elem;\n\n    function resetModel(evt) {\n      if (upload.shouldUpdateOn('click', attr, scope) && fileElem.val()) {\n        fileElem.val(null);\n        upload.updateModel(ngModel, attr, scope, fileChangeAttr(), null, evt, true);\n      }\n    }\n\n    if (!isInputTypeFile()) {\n      fileElem = createFileInput();\n    }\n    fileElem.bind('change', changeFn);\n\n    if (!isInputTypeFile()) {\n      elem.bind('click touchstart touchend', clickHandler);\n    } else {\n      elem.bind('click', resetModel);\n    }\n\n    function ie10SameFileSelectFix(evt) {\n      if (fileElem && !fileElem.attr('__ngf_ie10_Fix_')) {\n        if (!fileElem[0].parentNode) {\n          fileElem = null;\n          return;\n        }\n        evt.preventDefault();\n        evt.stopPropagation();\n        fileElem.unbind('click');\n        var clone = fileElem.clone();\n        fileElem.replaceWith(clone);\n        fileElem = clone;\n        fileElem.attr('__ngf_ie10_Fix_', 'true');\n        fileElem.bind('change', changeFn);\n        fileElem.bind('click', ie10SameFileSelectFix);\n        fileElem[0].click();\n        return false;\n      } else {\n        fileElem.removeAttr('__ngf_ie10_Fix_');\n      }\n    }\n\n    if (navigator.appVersion.indexOf('MSIE 10') !== -1) {\n      fileElem.bind('click', ie10SameFileSelectFix);\n    }\n\n    if (ngModel) ngModel.$formatters.push(function (val) {\n      if (val == null || val.length === 0) {\n        if (fileElem.val()) {\n          fileElem.val(null);\n        }\n      }\n      return val;\n    });\n\n    scope.$on('$destroy', function () {\n      if (!isInputTypeFile()) fileElem.parent().remove();\n      angular.forEach(unwatches, function (unwatch) {\n        unwatch();\n      });\n    });\n\n    $timeout(function () {\n      for (var i = 0; i < generatedElems.length; i++) {\n        var g = generatedElems[i];\n        if (!document.body.contains(g.el[0])) {\n          generatedElems.splice(i, 1);\n          g.ref.remove();\n        }\n      }\n    });\n\n    if (window.FileAPI && window.FileAPI.ngfFixIE) {\n      window.FileAPI.ngfFixIE(elem, fileElem, changeFn);\n    }\n  }\n\n  return {\n    restrict: 'AEC',\n    require: '?ngModel',\n    link: function (scope, elem, attr, ngModel) {\n      linkFileSelect(scope, elem, attr, ngModel, $parse, $timeout, $compile, Upload);\n    }\n  };\n}]);\n\n(function () {\n\n  ngFileUpload.service('UploadDataUrl', ['UploadBase', '$timeout', '$q', function (UploadBase, $timeout, $q) {\n    var upload = UploadBase;\n    upload.base64DataUrl = function (file) {\n      if (angular.isArray(file)) {\n        var d = $q.defer(), count = 0;\n        angular.forEach(file, function (f) {\n          upload.dataUrl(f, true)['finally'](function () {\n            count++;\n            if (count === file.length) {\n              var urls = [];\n              angular.forEach(file, function (ff) {\n                urls.push(ff.$ngfDataUrl);\n              });\n              d.resolve(urls, file);\n            }\n          });\n        });\n        return d.promise;\n      } else {\n        return upload.dataUrl(file, true);\n      }\n    };\n    upload.dataUrl = function (file, disallowObjectUrl) {\n      if (!file) return upload.emptyPromise(file, file);\n      if ((disallowObjectUrl && file.$ngfDataUrl != null) || (!disallowObjectUrl && file.$ngfBlobUrl != null)) {\n        return upload.emptyPromise(disallowObjectUrl ? file.$ngfDataUrl : file.$ngfBlobUrl, file);\n      }\n      var p = disallowObjectUrl ? file.$$ngfDataUrlPromise : file.$$ngfBlobUrlPromise;\n      if (p) return p;\n\n      var deferred = $q.defer();\n      $timeout(function () {\n        if (window.FileReader && file &&\n          (!window.FileAPI || navigator.userAgent.indexOf('MSIE 8') === -1 || file.size < 20000) &&\n          (!window.FileAPI || navigator.userAgent.indexOf('MSIE 9') === -1 || file.size < 4000000)) {\n          //prefer URL.createObjectURL for handling refrences to files of all sizes\n          //since it doesn´t build a large string in memory\n          var URL = window.URL || window.webkitURL;\n          if (URL && URL.createObjectURL && !disallowObjectUrl) {\n            var url;\n            try {\n              url = URL.createObjectURL(file);\n            } catch (e) {\n              $timeout(function () {\n                file.$ngfBlobUrl = '';\n                deferred.reject();\n              });\n              return;\n            }\n            $timeout(function () {\n              file.$ngfBlobUrl = url;\n              if (url) {\n                deferred.resolve(url, file);\n                upload.blobUrls = upload.blobUrls || [];\n                upload.blobUrlsTotalSize = upload.blobUrlsTotalSize || 0;\n                upload.blobUrls.push({url: url, size: file.size});\n                upload.blobUrlsTotalSize += file.size || 0;\n                var maxMemory = upload.defaults.blobUrlsMaxMemory || 268435456;\n                var maxLength = upload.defaults.blobUrlsMaxQueueSize || 200;\n                while ((upload.blobUrlsTotalSize > maxMemory || upload.blobUrls.length > maxLength) && upload.blobUrls.length > 1) {\n                  var obj = upload.blobUrls.splice(0, 1)[0];\n                  URL.revokeObjectURL(obj.url);\n                  upload.blobUrlsTotalSize -= obj.size;\n                }\n              }\n            });\n          } else {\n            var fileReader = new FileReader();\n            fileReader.onload = function (e) {\n              $timeout(function () {\n                file.$ngfDataUrl = e.target.result;\n                deferred.resolve(e.target.result, file);\n                $timeout(function () {\n                  delete file.$ngfDataUrl;\n                }, 1000);\n              });\n            };\n            fileReader.onerror = function () {\n              $timeout(function () {\n                file.$ngfDataUrl = '';\n                deferred.reject();\n              });\n            };\n            fileReader.readAsDataURL(file);\n          }\n        } else {\n          $timeout(function () {\n            file[disallowObjectUrl ? '$ngfDataUrl' : '$ngfBlobUrl'] = '';\n            deferred.reject();\n          });\n        }\n      });\n\n      if (disallowObjectUrl) {\n        p = file.$$ngfDataUrlPromise = deferred.promise;\n      } else {\n        p = file.$$ngfBlobUrlPromise = deferred.promise;\n      }\n      p['finally'](function () {\n        delete file[disallowObjectUrl ? '$$ngfDataUrlPromise' : '$$ngfBlobUrlPromise'];\n      });\n      return p;\n    };\n    return upload;\n  }]);\n\n  function getTagType(el) {\n    if (el.tagName.toLowerCase() === 'img') return 'image';\n    if (el.tagName.toLowerCase() === 'audio') return 'audio';\n    if (el.tagName.toLowerCase() === 'video') return 'video';\n    return /./;\n  }\n\n  function linkFileDirective(Upload, $timeout, scope, elem, attr, directiveName, resizeParams, isBackground) {\n    function constructDataUrl(file) {\n      var disallowObjectUrl = Upload.attrGetter('ngfNoObjectUrl', attr, scope);\n      Upload.dataUrl(file, disallowObjectUrl)['finally'](function () {\n        $timeout(function () {\n          var src = (disallowObjectUrl ? file.$ngfDataUrl : file.$ngfBlobUrl) || file.$ngfDataUrl;\n          if (isBackground) {\n            elem.css('background-image', 'url(\\'' + (src || '') + '\\')');\n          } else {\n            elem.attr('src', src);\n          }\n          if (src) {\n            elem.removeClass('ng-hide');\n          } else {\n            elem.addClass('ng-hide');\n          }\n        });\n      });\n    }\n\n    $timeout(function () {\n      var unwatch = scope.$watch(attr[directiveName], function (file) {\n        var size = resizeParams;\n        if (directiveName === 'ngfThumbnail') {\n          if (!size) {\n            size = {\n              width: elem[0].naturalWidth || elem[0].clientWidth,\n              height: elem[0].naturalHeight || elem[0].clientHeight\n            };\n          }\n          if (size.width === 0 && window.getComputedStyle) {\n            var style = getComputedStyle(elem[0]);\n            if (style.width && style.width.indexOf('px') > -1 && style.height && style.height.indexOf('px') > -1) {\n              size = {\n                width: parseInt(style.width.slice(0, -2)),\n                height: parseInt(style.height.slice(0, -2))\n              };\n            }\n          }\n        }\n\n        if (angular.isString(file)) {\n          elem.removeClass('ng-hide');\n          if (isBackground) {\n            return elem.css('background-image', 'url(\\'' + file + '\\')');\n          } else {\n            return elem.attr('src', file);\n          }\n        }\n        if (file && file.type && file.type.search(getTagType(elem[0])) === 0 &&\n          (!isBackground || file.type.indexOf('image') === 0)) {\n          if (size && Upload.isResizeSupported()) {\n            size.resizeIf = function (width, height) {\n              return Upload.attrGetter('ngfResizeIf', attr, scope,\n                {$width: width, $height: height, $file: file});\n            };\n            Upload.resize(file, size).then(\n              function (f) {\n                constructDataUrl(f);\n              }, function (e) {\n                throw e;\n              }\n            );\n          } else {\n            constructDataUrl(file);\n          }\n        } else {\n          elem.addClass('ng-hide');\n        }\n      });\n\n      scope.$on('$destroy', function () {\n        unwatch();\n      });\n    });\n  }\n\n\n  /** @namespace attr.ngfSrc */\n  /** @namespace attr.ngfNoObjectUrl */\n  ngFileUpload.directive('ngfSrc', ['Upload', '$timeout', function (Upload, $timeout) {\n    return {\n      restrict: 'AE',\n      link: function (scope, elem, attr) {\n        linkFileDirective(Upload, $timeout, scope, elem, attr, 'ngfSrc',\n          Upload.attrGetter('ngfResize', attr, scope), false);\n      }\n    };\n  }]);\n\n  /** @namespace attr.ngfBackground */\n  /** @namespace attr.ngfNoObjectUrl */\n  ngFileUpload.directive('ngfBackground', ['Upload', '$timeout', function (Upload, $timeout) {\n    return {\n      restrict: 'AE',\n      link: function (scope, elem, attr) {\n        linkFileDirective(Upload, $timeout, scope, elem, attr, 'ngfBackground',\n          Upload.attrGetter('ngfResize', attr, scope), true);\n      }\n    };\n  }]);\n\n  /** @namespace attr.ngfThumbnail */\n  /** @namespace attr.ngfAsBackground */\n  /** @namespace attr.ngfSize */\n  /** @namespace attr.ngfNoObjectUrl */\n  ngFileUpload.directive('ngfThumbnail', ['Upload', '$timeout', function (Upload, $timeout) {\n    return {\n      restrict: 'AE',\n      link: function (scope, elem, attr) {\n        var size = Upload.attrGetter('ngfSize', attr, scope);\n        linkFileDirective(Upload, $timeout, scope, elem, attr, 'ngfThumbnail', size,\n          Upload.attrGetter('ngfAsBackground', attr, scope));\n      }\n    };\n  }]);\n\n  ngFileUpload.config(['$compileProvider', function ($compileProvider) {\n    if ($compileProvider.imgSrcSanitizationWhitelist) $compileProvider.imgSrcSanitizationWhitelist(/^\\s*(https?|ftp|mailto|tel|webcal|local|file|data|blob):/);\n    if ($compileProvider.aHrefSanitizationWhitelist) $compileProvider.aHrefSanitizationWhitelist(/^\\s*(https?|ftp|mailto|tel|webcal|local|file|data|blob):/);\n  }]);\n\n  ngFileUpload.filter('ngfDataUrl', ['UploadDataUrl', '$sce', function (UploadDataUrl, $sce) {\n    return function (file, disallowObjectUrl, trustedUrl) {\n      if (angular.isString(file)) {\n        return $sce.trustAsResourceUrl(file);\n      }\n      var src = file && ((disallowObjectUrl ? file.$ngfDataUrl : file.$ngfBlobUrl) || file.$ngfDataUrl);\n      if (file && !src) {\n        if (!file.$ngfDataUrlFilterInProgress && angular.isObject(file)) {\n          file.$ngfDataUrlFilterInProgress = true;\n          UploadDataUrl.dataUrl(file, disallowObjectUrl);\n        }\n        return '';\n      }\n      if (file) delete file.$ngfDataUrlFilterInProgress;\n      return (file && src ? (trustedUrl ? $sce.trustAsResourceUrl(src) : src) : file) || '';\n    };\n  }]);\n\n})();\n\nngFileUpload.service('UploadValidate', ['UploadDataUrl', '$q', '$timeout', function (UploadDataUrl, $q, $timeout) {\n  var upload = UploadDataUrl;\n\n  function globStringToRegex(str) {\n    var regexp = '', excludes = [];\n    if (str.length > 2 && str[0] === '/' && str[str.length - 1] === '/') {\n      regexp = str.substring(1, str.length - 1);\n    } else {\n      var split = str.split(',');\n      if (split.length > 1) {\n        for (var i = 0; i < split.length; i++) {\n          var r = globStringToRegex(split[i]);\n          if (r.regexp) {\n            regexp += '(' + r.regexp + ')';\n            if (i < split.length - 1) {\n              regexp += '|';\n            }\n          } else {\n            excludes = excludes.concat(r.excludes);\n          }\n        }\n      } else {\n        if (str.indexOf('!') === 0) {\n          excludes.push('^((?!' + globStringToRegex(str.substring(1)).regexp + ').)*$');\n        } else {\n          if (str.indexOf('.') === 0) {\n            str = '*' + str;\n          }\n          regexp = '^' + str.replace(new RegExp('[.\\\\\\\\+*?\\\\[\\\\^\\\\]$(){}=!<>|:\\\\-]', 'g'), '\\\\$&') + '$';\n          regexp = regexp.replace(/\\\\\\*/g, '.*').replace(/\\\\\\?/g, '.');\n        }\n      }\n    }\n    return {regexp: regexp, excludes: excludes};\n  }\n\n  upload.validatePattern = function (file, val) {\n    if (!val) {\n      return true;\n    }\n    var pattern = globStringToRegex(val), valid = true;\n    if (pattern.regexp && pattern.regexp.length) {\n      var regexp = new RegExp(pattern.regexp, 'i');\n      valid = (file.type != null && regexp.test(file.type)) ||\n        (file.name != null && regexp.test(file.name));\n    }\n    var len = pattern.excludes.length;\n    while (len--) {\n      var exclude = new RegExp(pattern.excludes[len], 'i');\n      valid = valid && (file.type == null || exclude.test(file.type)) &&\n        (file.name == null || exclude.test(file.name));\n    }\n    return valid;\n  };\n\n  upload.ratioToFloat = function (val) {\n    var r = val.toString(), xIndex = r.search(/[x:]/i);\n    if (xIndex > -1) {\n      r = parseFloat(r.substring(0, xIndex)) / parseFloat(r.substring(xIndex + 1));\n    } else {\n      r = parseFloat(r);\n    }\n    return r;\n  };\n\n  upload.registerModelChangeValidator = function (ngModel, attr, scope) {\n    if (ngModel) {\n      ngModel.$formatters.push(function (files) {\n        if (ngModel.$dirty) {\n          var filesArray = files;\n          if (files && !angular.isArray(files)) {\n            filesArray = [files];\n          }\n          upload.validate(filesArray, 0, ngModel, attr, scope).then(function () {\n            upload.applyModelValidation(ngModel, filesArray);\n          });\n        }\n        return files;\n      });\n    }\n  };\n\n  function markModelAsDirty(ngModel, files) {\n    if (files != null && !ngModel.$dirty) {\n      if (ngModel.$setDirty) {\n        ngModel.$setDirty();\n      } else {\n        ngModel.$dirty = true;\n      }\n    }\n  }\n\n  upload.applyModelValidation = function (ngModel, files) {\n    markModelAsDirty(ngModel, files);\n    angular.forEach(ngModel.$ngfValidations, function (validation) {\n      ngModel.$setValidity(validation.name, validation.valid);\n    });\n  };\n\n  upload.getValidationAttr = function (attr, scope, name, validationName, file) {\n    var dName = 'ngf' + name[0].toUpperCase() + name.substr(1);\n    var val = upload.attrGetter(dName, attr, scope, {$file: file});\n    if (val == null) {\n      val = upload.attrGetter('ngfValidate', attr, scope, {$file: file});\n      if (val) {\n        var split = (validationName || name).split('.');\n        val = val[split[0]];\n        if (split.length > 1) {\n          val = val && val[split[1]];\n        }\n      }\n    }\n    return val;\n  };\n\n  upload.validate = function (files, prevLength, ngModel, attr, scope) {\n    ngModel = ngModel || {};\n    ngModel.$ngfValidations = ngModel.$ngfValidations || [];\n\n    angular.forEach(ngModel.$ngfValidations, function (v) {\n      v.valid = true;\n    });\n\n    var attrGetter = function (name, params) {\n      return upload.attrGetter(name, attr, scope, params);\n    };\n\n    var ignoredErrors = (upload.attrGetter('ngfIgnoreInvalid', attr, scope) || '').split(' ');\n    var runAllValidation = upload.attrGetter('ngfRunAllValidations', attr, scope);\n\n    if (files == null || files.length === 0) {\n      return upload.emptyPromise({'validFiles': files, 'invalidFiles': []});\n    }\n\n    files = files.length === undefined ? [files] : files.slice(0);\n    var invalidFiles = [];\n\n    function validateSync(name, validationName, fn) {\n      if (files) {\n        var i = files.length, valid = null;\n        while (i--) {\n          var file = files[i];\n          if (file) {\n            var val = upload.getValidationAttr(attr, scope, name, validationName, file);\n            if (val != null) {\n              if (!fn(file, val, i)) {\n                if (ignoredErrors.indexOf(name) === -1) {\n                  file.$error = name;\n                  (file.$errorMessages = (file.$errorMessages || {}))[name] = true;\n                  file.$errorParam = val;\n                  if (invalidFiles.indexOf(file) === -1) {\n                    invalidFiles.push(file);\n                  }\n                  if (!runAllValidation) {\n                    files.splice(i, 1);\n                  }\n                  valid = false;\n                } else {\n                  files.splice(i, 1);\n                }\n              }\n            }\n          }\n        }\n        if (valid !== null) {\n          ngModel.$ngfValidations.push({name: name, valid: valid});\n        }\n      }\n    }\n\n    validateSync('pattern', null, upload.validatePattern);\n    validateSync('minSize', 'size.min', function (file, val) {\n      return file.size + 0.1 >= upload.translateScalars(val);\n    });\n    validateSync('maxSize', 'size.max', function (file, val) {\n      return file.size - 0.1 <= upload.translateScalars(val);\n    });\n    var totalSize = 0;\n    validateSync('maxTotalSize', null, function (file, val) {\n      totalSize += file.size;\n      if (totalSize > upload.translateScalars(val)) {\n        files.splice(0, files.length);\n        return false;\n      }\n      return true;\n    });\n\n    validateSync('validateFn', null, function (file, r) {\n      return r === true || r === null || r === '';\n    });\n\n    if (!files.length) {\n      return upload.emptyPromise({'validFiles': [], 'invalidFiles': invalidFiles});\n    }\n\n    function validateAsync(name, validationName, type, asyncFn, fn) {\n      function resolveResult(defer, file, val) {\n        function resolveInternal(fn) {\n          if (fn()) {\n            if (ignoredErrors.indexOf(name) === -1) {\n              file.$error = name;\n              (file.$errorMessages = (file.$errorMessages || {}))[name] = true;\n              file.$errorParam = val;\n              if (invalidFiles.indexOf(file) === -1) {\n                invalidFiles.push(file);\n              }\n              if (!runAllValidation) {\n                var i = files.indexOf(file);\n                if (i > -1) files.splice(i, 1);\n              }\n              defer.resolve(false);\n            } else {\n              var j = files.indexOf(file);\n              if (j > -1) files.splice(j, 1);\n              defer.resolve(true);\n            }\n          } else {\n            defer.resolve(true);\n          }\n        }\n\n        if (val != null) {\n          asyncFn(file, val).then(function (d) {\n            resolveInternal(function () {\n              return !fn(d, val);\n            });\n          }, function () {\n            resolveInternal(function () {\n              return attrGetter('ngfValidateForce', {$file: file});\n            });\n          });\n        } else {\n          defer.resolve(true);\n        }\n      }\n\n      var promises = [upload.emptyPromise(true)];\n      if (files) {\n        files = files.length === undefined ? [files] : files;\n        angular.forEach(files, function (file) {\n          var defer = $q.defer();\n          promises.push(defer.promise);\n          if (type && (file.type == null || file.type.search(type) !== 0)) {\n            defer.resolve(true);\n            return;\n          }\n          if (name === 'dimensions' && upload.attrGetter('ngfDimensions', attr) != null) {\n            upload.imageDimensions(file).then(function (d) {\n              resolveResult(defer, file,\n                attrGetter('ngfDimensions', {$file: file, $width: d.width, $height: d.height}));\n            }, function () {\n              defer.resolve(false);\n            });\n          } else if (name === 'duration' && upload.attrGetter('ngfDuration', attr) != null) {\n            upload.mediaDuration(file).then(function (d) {\n              resolveResult(defer, file,\n                attrGetter('ngfDuration', {$file: file, $duration: d}));\n            }, function () {\n              defer.resolve(false);\n            });\n          } else {\n            resolveResult(defer, file,\n              upload.getValidationAttr(attr, scope, name, validationName, file));\n          }\n        });\n      }\n      var deffer = $q.defer();\n      $q.all(promises).then(function (values) {\n        var isValid = true;\n        for (var i = 0; i < values.length; i++) {\n          if (!values[i]) {\n            isValid = false;\n            break;\n          }\n        }\n        ngModel.$ngfValidations.push({name: name, valid: isValid});\n        deffer.resolve(isValid);\n      });\n      return deffer.promise;\n    }\n\n    var deffer = $q.defer();\n    var promises = [];\n\n    promises.push(validateAsync('maxHeight', 'height.max', /image/,\n      this.imageDimensions, function (d, val) {\n        return d.height <= val;\n      }));\n    promises.push(validateAsync('minHeight', 'height.min', /image/,\n      this.imageDimensions, function (d, val) {\n        return d.height >= val;\n      }));\n    promises.push(validateAsync('maxWidth', 'width.max', /image/,\n      this.imageDimensions, function (d, val) {\n        return d.width <= val;\n      }));\n    promises.push(validateAsync('minWidth', 'width.min', /image/,\n      this.imageDimensions, function (d, val) {\n        return d.width >= val;\n      }));\n    promises.push(validateAsync('dimensions', null, /image/,\n      function (file, val) {\n        return upload.emptyPromise(val);\n      }, function (r) {\n        return r;\n      }));\n    promises.push(validateAsync('ratio', null, /image/,\n      this.imageDimensions, function (d, val) {\n        var split = val.toString().split(','), valid = false;\n        for (var i = 0; i < split.length; i++) {\n          if (Math.abs((d.width / d.height) - upload.ratioToFloat(split[i])) < 0.01) {\n            valid = true;\n          }\n        }\n        return valid;\n      }));\n    promises.push(validateAsync('maxRatio', 'ratio.max', /image/,\n      this.imageDimensions, function (d, val) {\n        return (d.width / d.height) - upload.ratioToFloat(val) < 0.0001;\n      }));\n    promises.push(validateAsync('minRatio', 'ratio.min', /image/,\n      this.imageDimensions, function (d, val) {\n        return (d.width / d.height) - upload.ratioToFloat(val) > -0.0001;\n      }));\n    promises.push(validateAsync('maxDuration', 'duration.max', /audio|video/,\n      this.mediaDuration, function (d, val) {\n        return d <= upload.translateScalars(val);\n      }));\n    promises.push(validateAsync('minDuration', 'duration.min', /audio|video/,\n      this.mediaDuration, function (d, val) {\n        return d >= upload.translateScalars(val);\n      }));\n    promises.push(validateAsync('duration', null, /audio|video/,\n      function (file, val) {\n        return upload.emptyPromise(val);\n      }, function (r) {\n        return r;\n      }));\n\n    promises.push(validateAsync('validateAsyncFn', null, null,\n      function (file, val) {\n        return val;\n      }, function (r) {\n        return r === true || r === null || r === '';\n      }));\n\n    $q.all(promises).then(function () {\n\n      if (runAllValidation) {\n        for (var i = 0; i < files.length; i++) {\n          var file = files[i];\n          if (file.$error) {\n            files.splice(i--, 1);\n          }\n        }\n      }\n\n      runAllValidation = false;\n      validateSync('maxFiles', null, function (file, val, i) {\n        return prevLength + i < val;\n      });\n\n      deffer.resolve({'validFiles': files, 'invalidFiles': invalidFiles});\n    });\n    return deffer.promise;\n  };\n\n  upload.imageDimensions = function (file) {\n    if (file.$ngfWidth && file.$ngfHeight) {\n      var d = $q.defer();\n      $timeout(function () {\n        d.resolve({width: file.$ngfWidth, height: file.$ngfHeight});\n      });\n      return d.promise;\n    }\n    if (file.$ngfDimensionPromise) return file.$ngfDimensionPromise;\n\n    var deferred = $q.defer();\n    $timeout(function () {\n      if (file.type.indexOf('image') !== 0) {\n        deferred.reject('not image');\n        return;\n      }\n      upload.dataUrl(file).then(function (dataUrl) {\n        var img = angular.element('<img>').attr('src', dataUrl)\n          .css('visibility', 'hidden').css('position', 'fixed')\n          .css('max-width', 'none !important').css('max-height', 'none !important');\n\n        function success() {\n          var width = img[0].naturalWidth || img[0].clientWidth;\n          var height = img[0].naturalHeight || img[0].clientHeight;\n          img.remove();\n          file.$ngfWidth = width;\n          file.$ngfHeight = height;\n          deferred.resolve({width: width, height: height});\n        }\n\n        function error() {\n          img.remove();\n          deferred.reject('load error');\n        }\n\n        img.on('load', success);\n        img.on('error', error);\n\n        var secondsCounter = 0;\n        function checkLoadErrorInCaseOfNoCallback() {\n          $timeout(function () {\n            if (img[0].parentNode) {\n              if (img[0].clientWidth) {\n                success();\n              } else if (secondsCounter++ > 10) {\n                error();\n              } else {\n                checkLoadErrorInCaseOfNoCallback();\n              }\n            }\n          }, 1000);\n        }\n\n        checkLoadErrorInCaseOfNoCallback();\n\n        angular.element(document.getElementsByTagName('body')[0]).append(img);\n      }, function () {\n        deferred.reject('load error');\n      });\n    });\n\n    file.$ngfDimensionPromise = deferred.promise;\n    file.$ngfDimensionPromise['finally'](function () {\n      delete file.$ngfDimensionPromise;\n    });\n    return file.$ngfDimensionPromise;\n  };\n\n  upload.mediaDuration = function (file) {\n    if (file.$ngfDuration) {\n      var d = $q.defer();\n      $timeout(function () {\n        d.resolve(file.$ngfDuration);\n      });\n      return d.promise;\n    }\n    if (file.$ngfDurationPromise) return file.$ngfDurationPromise;\n\n    var deferred = $q.defer();\n    $timeout(function () {\n      if (file.type.indexOf('audio') !== 0 && file.type.indexOf('video') !== 0) {\n        deferred.reject('not media');\n        return;\n      }\n      upload.dataUrl(file).then(function (dataUrl) {\n        var el = angular.element(file.type.indexOf('audio') === 0 ? '<audio>' : '<video>')\n          .attr('src', dataUrl).css('visibility', 'none').css('position', 'fixed');\n\n        function success() {\n          var duration = el[0].duration;\n          file.$ngfDuration = duration;\n          el.remove();\n          deferred.resolve(duration);\n        }\n\n        function error() {\n          el.remove();\n          deferred.reject('load error');\n        }\n\n        el.on('loadedmetadata', success);\n        el.on('error', error);\n        var count = 0;\n\n        function checkLoadError() {\n          $timeout(function () {\n            if (el[0].parentNode) {\n              if (el[0].duration) {\n                success();\n              } else if (count > 10) {\n                error();\n              } else {\n                checkLoadError();\n              }\n            }\n          }, 1000);\n        }\n\n        checkLoadError();\n\n        angular.element(document.body).append(el);\n      }, function () {\n        deferred.reject('load error');\n      });\n    });\n\n    file.$ngfDurationPromise = deferred.promise;\n    file.$ngfDurationPromise['finally'](function () {\n      delete file.$ngfDurationPromise;\n    });\n    return file.$ngfDurationPromise;\n  };\n  return upload;\n}\n]);\n\nngFileUpload.service('UploadResize', ['UploadValidate', '$q', function (UploadValidate, $q) {\n  var upload = UploadValidate;\n\n  /**\n   * Conserve aspect ratio of the original region. Useful when shrinking/enlarging\n   * images to fit into a certain area.\n   * Source:  http://stackoverflow.com/a/14731922\n   *\n   * @param {Number} srcWidth Source area width\n   * @param {Number} srcHeight Source area height\n   * @param {Number} maxWidth Nestable area maximum available width\n   * @param {Number} maxHeight Nestable area maximum available height\n   * @return {Object} { width, height }\n   */\n  var calculateAspectRatioFit = function (srcWidth, srcHeight, maxWidth, maxHeight, centerCrop) {\n    var ratio = centerCrop ? Math.max(maxWidth / srcWidth, maxHeight / srcHeight) :\n      Math.min(maxWidth / srcWidth, maxHeight / srcHeight);\n    return {\n      width: srcWidth * ratio, height: srcHeight * ratio,\n      marginX: srcWidth * ratio - maxWidth, marginY: srcHeight * ratio - maxHeight\n    };\n  };\n\n  // Extracted from https://github.com/romelgomez/angular-firebase-image-upload/blob/master/app/scripts/fileUpload.js#L89\n  var resize = function (imagen, width, height, quality, type, ratio, centerCrop, resizeIf) {\n    var deferred = $q.defer();\n    var canvasElement = document.createElement('canvas');\n    var imageElement = document.createElement('img');\n    imageElement.setAttribute('style', 'visibility:hidden;position:fixed;z-index:-100000');\n    document.body.appendChild(imageElement);\n\n    imageElement.onload = function () {\n      var imgWidth = imageElement.width, imgHeight = imageElement.height;\n      imageElement.parentNode.removeChild(imageElement);\n      if (resizeIf != null && resizeIf(imgWidth, imgHeight) === false) {\n        deferred.reject('resizeIf');\n        return;\n      }\n      try {\n        if (ratio) {\n          var ratioFloat = upload.ratioToFloat(ratio);\n          var imgRatio = imgWidth / imgHeight;\n          if (imgRatio < ratioFloat) {\n            width = imgWidth;\n            height = width / ratioFloat;\n          } else {\n            height = imgHeight;\n            width = height * ratioFloat;\n          }\n        }\n        if (!width) {\n          width = imgWidth;\n        }\n        if (!height) {\n          height = imgHeight;\n        }\n        var dimensions = calculateAspectRatioFit(imgWidth, imgHeight, width, height, centerCrop);\n        canvasElement.width = Math.min(dimensions.width, width);\n        canvasElement.height = Math.min(dimensions.height, height);\n        var context = canvasElement.getContext('2d');\n        context.drawImage(imageElement,\n          Math.min(0, -dimensions.marginX / 2), Math.min(0, -dimensions.marginY / 2),\n          dimensions.width, dimensions.height);\n        deferred.resolve(canvasElement.toDataURL(type || 'image/WebP', quality || 0.934));\n      } catch (e) {\n        deferred.reject(e);\n      }\n    };\n    imageElement.onerror = function () {\n      imageElement.parentNode.removeChild(imageElement);\n      deferred.reject();\n    };\n    imageElement.src = imagen;\n    return deferred.promise;\n  };\n\n  upload.dataUrltoBlob = function (dataurl, name, origSize) {\n    var arr = dataurl.split(','), mime = arr[0].match(/:(.*?);/)[1],\n      bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n);\n    while (n--) {\n      u8arr[n] = bstr.charCodeAt(n);\n    }\n    var blob = new window.Blob([u8arr], {type: mime});\n    blob.name = name;\n    blob.$ngfOrigSize = origSize;\n    return blob;\n  };\n\n  upload.isResizeSupported = function () {\n    var elem = document.createElement('canvas');\n    return window.atob && elem.getContext && elem.getContext('2d') && window.Blob;\n  };\n\n  if (upload.isResizeSupported()) {\n    // add name getter to the blob constructor prototype\n    Object.defineProperty(window.Blob.prototype, 'name', {\n      get: function () {\n        return this.$ngfName;\n      },\n      set: function (v) {\n        this.$ngfName = v;\n      },\n      configurable: true\n    });\n  }\n\n  upload.resize = function (file, options) {\n    if (file.type.indexOf('image') !== 0) return upload.emptyPromise(file);\n\n    var deferred = $q.defer();\n    upload.dataUrl(file, true).then(function (url) {\n      resize(url, options.width, options.height, options.quality, options.type || file.type,\n        options.ratio, options.centerCrop, options.resizeIf)\n        .then(function (dataUrl) {\n          if (file.type === 'image/jpeg' && options.restoreExif !== false) {\n            try {\n              dataUrl = upload.restoreExif(url, dataUrl);\n            } catch (e) {\n              setTimeout(function () {throw e;}, 1);\n            }\n          }\n          try {\n            var blob = upload.dataUrltoBlob(dataUrl, file.name, file.size);\n            deferred.resolve(blob);\n          } catch (e) {\n            deferred.reject(e);\n          }\n        }, function (r) {\n          if (r === 'resizeIf') {\n            deferred.resolve(file);\n          }\n          deferred.reject(r);\n        });\n    }, function (e) {\n      deferred.reject(e);\n    });\n    return deferred.promise;\n  };\n\n  return upload;\n}]);\n\n(function () {\n  ngFileUpload.directive('ngfDrop', ['$parse', '$timeout', '$window', 'Upload', '$http', '$q',\n    function ($parse, $timeout, $window, Upload, $http, $q) {\n      return {\n        restrict: 'AEC',\n        require: '?ngModel',\n        link: function (scope, elem, attr, ngModel) {\n          linkDrop(scope, elem, attr, ngModel, $parse, $timeout, $window, Upload, $http, $q);\n        }\n      };\n    }]);\n\n  ngFileUpload.directive('ngfNoFileDrop', function () {\n    return function (scope, elem) {\n      if (dropAvailable()) elem.css('display', 'none');\n    };\n  });\n\n  ngFileUpload.directive('ngfDropAvailable', ['$parse', '$timeout', 'Upload', function ($parse, $timeout, Upload) {\n    return function (scope, elem, attr) {\n      if (dropAvailable()) {\n        var model = $parse(Upload.attrGetter('ngfDropAvailable', attr));\n        $timeout(function () {\n          model(scope);\n          if (model.assign) {\n            model.assign(scope, true);\n          }\n        });\n      }\n    };\n  }]);\n\n  function linkDrop(scope, elem, attr, ngModel, $parse, $timeout, $window, upload, $http, $q) {\n    var available = dropAvailable();\n\n    var attrGetter = function (name, scope, params) {\n      return upload.attrGetter(name, attr, scope, params);\n    };\n\n    if (attrGetter('dropAvailable')) {\n      $timeout(function () {\n        if (scope[attrGetter('dropAvailable')]) {\n          scope[attrGetter('dropAvailable')].value = available;\n        } else {\n          scope[attrGetter('dropAvailable')] = available;\n        }\n      });\n    }\n    if (!available) {\n      if (attrGetter('ngfHideOnDropNotAvailable', scope) === true) {\n        elem.css('display', 'none');\n      }\n      return;\n    }\n\n    function isDisabled() {\n      return elem.attr('disabled') || attrGetter('ngfDropDisabled', scope);\n    }\n\n    if (attrGetter('ngfSelect') == null) {\n      upload.registerModelChangeValidator(ngModel, attr, scope);\n    }\n\n    var leaveTimeout = null;\n    var stopPropagation = $parse(attrGetter('ngfStopPropagation'));\n    var dragOverDelay = 1;\n    var actualDragOverClass;\n\n    elem[0].addEventListener('dragover', function (evt) {\n      if (isDisabled() || !upload.shouldUpdateOn('drop', attr, scope)) return;\n      evt.preventDefault();\n      if (stopPropagation(scope)) evt.stopPropagation();\n      // handling dragover events from the Chrome download bar\n      if (navigator.userAgent.indexOf('Chrome') > -1) {\n        var b = evt.dataTransfer.effectAllowed;\n        evt.dataTransfer.dropEffect = ('move' === b || 'linkMove' === b) ? 'move' : 'copy';\n      }\n      $timeout.cancel(leaveTimeout);\n      if (!actualDragOverClass) {\n        actualDragOverClass = 'C';\n        calculateDragOverClass(scope, attr, evt, function (clazz) {\n          actualDragOverClass = clazz;\n          elem.addClass(actualDragOverClass);\n          attrGetter('ngfDrag', scope, {$isDragging: true, $class: actualDragOverClass, $event: evt});\n        });\n      }\n    }, false);\n    elem[0].addEventListener('dragenter', function (evt) {\n      if (isDisabled() || !upload.shouldUpdateOn('drop', attr, scope)) return;\n      evt.preventDefault();\n      if (stopPropagation(scope)) evt.stopPropagation();\n    }, false);\n    elem[0].addEventListener('dragleave', function (evt) {\n      if (isDisabled() || !upload.shouldUpdateOn('drop', attr, scope)) return;\n      evt.preventDefault();\n      if (stopPropagation(scope)) evt.stopPropagation();\n      leaveTimeout = $timeout(function () {\n        if (actualDragOverClass) elem.removeClass(actualDragOverClass);\n        actualDragOverClass = null;\n        attrGetter('ngfDrag', scope, {$isDragging: false, $event: evt});\n      }, dragOverDelay || 100);\n    }, false);\n    elem[0].addEventListener('drop', function (evt) {\n      if (isDisabled() || !upload.shouldUpdateOn('drop', attr, scope)) return;\n      evt.preventDefault();\n      if (stopPropagation(scope)) evt.stopPropagation();\n      if (actualDragOverClass) elem.removeClass(actualDragOverClass);\n      actualDragOverClass = null;\n      extractFilesAndUpdateModel(evt.dataTransfer, evt, 'dropUrl');\n    }, false);\n    elem[0].addEventListener('paste', function (evt) {\n      if (navigator.userAgent.toLowerCase().indexOf('firefox') > -1 &&\n        attrGetter('ngfEnableFirefoxPaste', scope)) {\n        evt.preventDefault();\n      }\n      if (isDisabled() || !upload.shouldUpdateOn('paste', attr, scope)) return;\n      extractFilesAndUpdateModel(evt.clipboardData || evt.originalEvent.clipboardData, evt, 'pasteUrl');\n    }, false);\n\n    if (navigator.userAgent.toLowerCase().indexOf('firefox') > -1 &&\n      attrGetter('ngfEnableFirefoxPaste', scope)) {\n      elem.attr('contenteditable', true);\n      elem.on('keypress', function (e) {\n        if (!e.metaKey && !e.ctrlKey) {\n          e.preventDefault();\n        }\n      });\n    }\n\n    function extractFilesAndUpdateModel(source, evt, updateOnType) {\n      if (!source) return;\n      // html needs to be calculated on the same process otherwise the data will be wiped\n      // after promise resolve or setTimeout.\n      var html;\n      try {\n        html = source && source.getData && source.getData('text/html');\n      } catch (e) {/* Fix IE11 that throw error calling getData */\n      }\n      extractFiles(source.items, source.files, attrGetter('ngfAllowDir', scope) !== false,\n        attrGetter('multiple') || attrGetter('ngfMultiple', scope)).then(function (files) {\n        if (files.length) {\n          updateModel(files, evt);\n        } else {\n          extractFilesFromHtml(updateOnType, html).then(function (files) {\n            updateModel(files, evt);\n          });\n        }\n      });\n    }\n\n    function updateModel(files, evt) {\n      upload.updateModel(ngModel, attr, scope, attrGetter('ngfChange') || attrGetter('ngfDrop'), files, evt);\n    }\n\n    function extractFilesFromHtml(updateOn, html) {\n      if (!upload.shouldUpdateOn(updateOn, attr, scope) || typeof html !== 'string') return upload.rejectPromise([]);\n      var urls = [];\n      html.replace(/<(img src|img [^>]* src) *=\\\"([^\\\"]*)\\\"/gi, function (m, n, src) {\n        urls.push(src);\n      });\n      var promises = [], files = [];\n      if (urls.length) {\n        angular.forEach(urls, function (url) {\n          promises.push(upload.urlToBlob(url).then(function (blob) {\n            files.push(blob);\n          }));\n        });\n        var defer = $q.defer();\n        $q.all(promises).then(function () {\n          defer.resolve(files);\n        }, function (e) {\n          defer.reject(e);\n        });\n        return defer.promise;\n      }\n      return upload.emptyPromise();\n    }\n\n    function calculateDragOverClass(scope, attr, evt, callback) {\n      var obj = attrGetter('ngfDragOverClass', scope, {$event: evt}), dClass = 'dragover';\n      if (angular.isString(obj)) {\n        dClass = obj;\n      } else if (obj) {\n        if (obj.delay) dragOverDelay = obj.delay;\n        if (obj.accept || obj.reject) {\n          var items = evt.dataTransfer.items;\n          if (items == null || !items.length) {\n            dClass = obj.accept;\n          } else {\n            var pattern = obj.pattern || attrGetter('ngfPattern', scope, {$event: evt});\n            var len = items.length;\n            while (len--) {\n              if (!upload.validatePattern(items[len], pattern)) {\n                dClass = obj.reject;\n                break;\n              } else {\n                dClass = obj.accept;\n              }\n            }\n          }\n        }\n      }\n      callback(dClass);\n    }\n\n    function extractFiles(items, fileList, allowDir, multiple) {\n      var maxFiles = upload.getValidationAttr(attr, scope, 'maxFiles');\n      if (maxFiles == null) {\n        maxFiles = Number.MAX_VALUE;\n      }\n      var maxTotalSize = upload.getValidationAttr(attr, scope, 'maxTotalSize');\n      if (maxTotalSize == null) {\n        maxTotalSize = Number.MAX_VALUE;\n      }\n      var includeDir = attrGetter('ngfIncludeDir', scope);\n      var files = [], totalSize = 0;\n\n      function traverseFileTree(entry, path) {\n        var defer = $q.defer();\n        if (entry != null) {\n          if (entry.isDirectory) {\n            var promises = [upload.emptyPromise()];\n            if (includeDir) {\n              var file = {type: 'directory'};\n              file.name = file.path = (path || '') + entry.name;\n              files.push(file);\n            }\n            var dirReader = entry.createReader();\n            var entries = [];\n            var readEntries = function () {\n              dirReader.readEntries(function (results) {\n                try {\n                  if (!results.length) {\n                    angular.forEach(entries.slice(0), function (e) {\n                      if (files.length <= maxFiles && totalSize <= maxTotalSize) {\n                        promises.push(traverseFileTree(e, (path ? path : '') + entry.name + '/'));\n                      }\n                    });\n                    $q.all(promises).then(function () {\n                      defer.resolve();\n                    }, function (e) {\n                      defer.reject(e);\n                    });\n                  } else {\n                    entries = entries.concat(Array.prototype.slice.call(results || [], 0));\n                    readEntries();\n                  }\n                } catch (e) {\n                  defer.reject(e);\n                }\n              }, function (e) {\n                defer.reject(e);\n              });\n            };\n            readEntries();\n          } else {\n            entry.file(function (file) {\n              try {\n                file.path = (path ? path : '') + file.name;\n                if (includeDir) {\n                  file = upload.rename(file, file.path);\n                }\n                files.push(file);\n                totalSize += file.size;\n                defer.resolve();\n              } catch (e) {\n                defer.reject(e);\n              }\n            }, function (e) {\n              defer.reject(e);\n            });\n          }\n        }\n        return defer.promise;\n      }\n\n      var promises = [upload.emptyPromise()];\n\n      if (items && items.length > 0 && $window.location.protocol !== 'file:') {\n        for (var i = 0; i < items.length; i++) {\n          if (items[i].webkitGetAsEntry && items[i].webkitGetAsEntry() && items[i].webkitGetAsEntry().isDirectory) {\n            var entry = items[i].webkitGetAsEntry();\n            if (entry.isDirectory && !allowDir) {\n              continue;\n            }\n            if (entry != null) {\n              promises.push(traverseFileTree(entry));\n            }\n          } else {\n            var f = items[i].getAsFile();\n            if (f != null) {\n              files.push(f);\n              totalSize += f.size;\n            }\n          }\n          if (files.length > maxFiles || totalSize > maxTotalSize ||\n            (!multiple && files.length > 0)) break;\n        }\n      } else {\n        if (fileList != null) {\n          for (var j = 0; j < fileList.length; j++) {\n            var file = fileList.item(j);\n            if (file.type || file.size > 0) {\n              files.push(file);\n              totalSize += file.size;\n            }\n            if (files.length > maxFiles || totalSize > maxTotalSize ||\n              (!multiple && files.length > 0)) break;\n          }\n        }\n      }\n\n      var defer = $q.defer();\n      $q.all(promises).then(function () {\n        if (!multiple && !includeDir && files.length) {\n          var i = 0;\n          while (files[i] && files[i].type === 'directory') i++;\n          defer.resolve([files[i]]);\n        } else {\n          defer.resolve(files);\n        }\n      }, function (e) {\n        defer.reject(e);\n      });\n\n      return defer.promise;\n    }\n  }\n\n  function dropAvailable() {\n    var div = document.createElement('div');\n    return ('draggable' in div) && ('ondrop' in div) && !/Edge\\/12./i.test(navigator.userAgent);\n  }\n\n})();\n\n// customized version of https://github.com/exif-js/exif-js\nngFileUpload.service('UploadExif', ['UploadResize', '$q', function (UploadResize, $q) {\n  var upload = UploadResize;\n\n  upload.isExifSupported = function () {\n    return window.FileReader && new FileReader().readAsArrayBuffer && upload.isResizeSupported();\n  };\n\n  function applyTransform(ctx, orientation, width, height) {\n    switch (orientation) {\n      case 2:\n        return ctx.transform(-1, 0, 0, 1, width, 0);\n      case 3:\n        return ctx.transform(-1, 0, 0, -1, width, height);\n      case 4:\n        return ctx.transform(1, 0, 0, -1, 0, height);\n      case 5:\n        return ctx.transform(0, 1, 1, 0, 0, 0);\n      case 6:\n        return ctx.transform(0, 1, -1, 0, height, 0);\n      case 7:\n        return ctx.transform(0, -1, -1, 0, height, width);\n      case 8:\n        return ctx.transform(0, -1, 1, 0, 0, width);\n    }\n  }\n\n  upload.readOrientation = function (file) {\n    var defer = $q.defer();\n    var reader = new FileReader();\n    var slicedFile = file.slice ? file.slice(0, 64 * 1024) : file;\n    reader.readAsArrayBuffer(slicedFile);\n    reader.onerror = function (e) {\n      return defer.reject(e);\n    };\n    reader.onload = function (e) {\n      var result = {orientation: 1};\n      var view = new DataView(this.result);\n      if (view.getUint16(0, false) !== 0xFFD8) return defer.resolve(result);\n\n      var length = view.byteLength,\n        offset = 2;\n      while (offset < length) {\n        var marker = view.getUint16(offset, false);\n        offset += 2;\n        if (marker === 0xFFE1) {\n          if (view.getUint32(offset += 2, false) !== 0x45786966) return defer.resolve(result);\n\n          var little = view.getUint16(offset += 6, false) === 0x4949;\n          offset += view.getUint32(offset + 4, little);\n          var tags = view.getUint16(offset, little);\n          offset += 2;\n          for (var i = 0; i < tags; i++)\n            if (view.getUint16(offset + (i * 12), little) === 0x0112) {\n              var orientation = view.getUint16(offset + (i * 12) + 8, little);\n              if (orientation >= 2 && orientation <= 8) {\n                view.setUint16(offset + (i * 12) + 8, 1, little);\n                result.fixedArrayBuffer = e.target.result;\n              }\n              result.orientation = orientation;\n              return defer.resolve(result);\n            }\n        } else if ((marker & 0xFF00) !== 0xFF00) break;\n        else offset += view.getUint16(offset, false);\n      }\n      return defer.resolve(result);\n    };\n    return defer.promise;\n  };\n\n  function arrayBufferToBase64(buffer) {\n    var binary = '';\n    var bytes = new Uint8Array(buffer);\n    var len = bytes.byteLength;\n    for (var i = 0; i < len; i++) {\n      binary += String.fromCharCode(bytes[i]);\n    }\n    return window.btoa(binary);\n  }\n\n  upload.applyExifRotation = function (file) {\n    if (file.type.indexOf('image/jpeg') !== 0) {\n      return upload.emptyPromise(file);\n    }\n\n    var deferred = $q.defer();\n    upload.readOrientation(file).then(function (result) {\n      if (result.orientation < 2 || result.orientation > 8) {\n        return deferred.resolve(file);\n      }\n      upload.dataUrl(file, true).then(function (url) {\n        var canvas = document.createElement('canvas');\n        var img = document.createElement('img');\n\n        img.onload = function () {\n          try {\n            canvas.width = result.orientation > 4 ? img.height : img.width;\n            canvas.height = result.orientation > 4 ? img.width : img.height;\n            var ctx = canvas.getContext('2d');\n            applyTransform(ctx, result.orientation, img.width, img.height);\n            ctx.drawImage(img, 0, 0);\n            var dataUrl = canvas.toDataURL(file.type || 'image/WebP', 0.934);\n            dataUrl = upload.restoreExif(arrayBufferToBase64(result.fixedArrayBuffer), dataUrl);\n            var blob = upload.dataUrltoBlob(dataUrl, file.name);\n            deferred.resolve(blob);\n          } catch (e) {\n            return deferred.reject(e);\n          }\n        };\n        img.onerror = function () {\n          deferred.reject();\n        };\n        img.src = url;\n      }, function (e) {\n        deferred.reject(e);\n      });\n    }, function (e) {\n      deferred.reject(e);\n    });\n    return deferred.promise;\n  };\n\n  upload.restoreExif = function (orig, resized) {\n    var ExifRestorer = {};\n\n    ExifRestorer.KEY_STR = 'ABCDEFGHIJKLMNOP' +\n      'QRSTUVWXYZabcdef' +\n      'ghijklmnopqrstuv' +\n      'wxyz0123456789+/' +\n      '=';\n\n    ExifRestorer.encode64 = function (input) {\n      var output = '',\n        chr1, chr2, chr3 = '',\n        enc1, enc2, enc3, enc4 = '',\n        i = 0;\n\n      do {\n        chr1 = input[i++];\n        chr2 = input[i++];\n        chr3 = input[i++];\n\n        enc1 = chr1 >> 2;\n        enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);\n        enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);\n        enc4 = chr3 & 63;\n\n        if (isNaN(chr2)) {\n          enc3 = enc4 = 64;\n        } else if (isNaN(chr3)) {\n          enc4 = 64;\n        }\n\n        output = output +\n          this.KEY_STR.charAt(enc1) +\n          this.KEY_STR.charAt(enc2) +\n          this.KEY_STR.charAt(enc3) +\n          this.KEY_STR.charAt(enc4);\n        chr1 = chr2 = chr3 = '';\n        enc1 = enc2 = enc3 = enc4 = '';\n      } while (i < input.length);\n\n      return output;\n    };\n\n    ExifRestorer.restore = function (origFileBase64, resizedFileBase64) {\n      if (origFileBase64.match('data:image/jpeg;base64,')) {\n        origFileBase64 = origFileBase64.replace('data:image/jpeg;base64,', '');\n      }\n\n      var rawImage = this.decode64(origFileBase64);\n      var segments = this.slice2Segments(rawImage);\n\n      var image = this.exifManipulation(resizedFileBase64, segments);\n\n      return 'data:image/jpeg;base64,' + this.encode64(image);\n    };\n\n\n    ExifRestorer.exifManipulation = function (resizedFileBase64, segments) {\n      var exifArray = this.getExifArray(segments),\n        newImageArray = this.insertExif(resizedFileBase64, exifArray);\n      return new Uint8Array(newImageArray);\n    };\n\n\n    ExifRestorer.getExifArray = function (segments) {\n      var seg;\n      for (var x = 0; x < segments.length; x++) {\n        seg = segments[x];\n        if (seg[0] === 255 & seg[1] === 225) //(ff e1)\n        {\n          return seg;\n        }\n      }\n      return [];\n    };\n\n\n    ExifRestorer.insertExif = function (resizedFileBase64, exifArray) {\n      var imageData = resizedFileBase64.replace('data:image/jpeg;base64,', ''),\n        buf = this.decode64(imageData),\n        separatePoint = buf.indexOf(255, 3),\n        mae = buf.slice(0, separatePoint),\n        ato = buf.slice(separatePoint),\n        array = mae;\n\n      array = array.concat(exifArray);\n      array = array.concat(ato);\n      return array;\n    };\n\n\n    ExifRestorer.slice2Segments = function (rawImageArray) {\n      var head = 0,\n        segments = [];\n\n      while (1) {\n        if (rawImageArray[head] === 255 & rawImageArray[head + 1] === 218) {\n          break;\n        }\n        if (rawImageArray[head] === 255 & rawImageArray[head + 1] === 216) {\n          head += 2;\n        }\n        else {\n          var length = rawImageArray[head + 2] * 256 + rawImageArray[head + 3],\n            endPoint = head + length + 2,\n            seg = rawImageArray.slice(head, endPoint);\n          segments.push(seg);\n          head = endPoint;\n        }\n        if (head > rawImageArray.length) {\n          break;\n        }\n      }\n\n      return segments;\n    };\n\n\n    ExifRestorer.decode64 = function (input) {\n      var chr1, chr2, chr3 = '',\n        enc1, enc2, enc3, enc4 = '',\n        i = 0,\n        buf = [];\n\n      // remove all characters that are not A-Z, a-z, 0-9, +, /, or =\n      var base64test = /[^A-Za-z0-9\\+\\/\\=]/g;\n      if (base64test.exec(input)) {\n        console.log('There were invalid base64 characters in the input text.\\n' +\n          'Valid base64 characters are A-Z, a-z, 0-9, ' + ', ' / ',and \"=\"\\n' +\n          'Expect errors in decoding.');\n      }\n      input = input.replace(/[^A-Za-z0-9\\+\\/\\=]/g, '');\n\n      do {\n        enc1 = this.KEY_STR.indexOf(input.charAt(i++));\n        enc2 = this.KEY_STR.indexOf(input.charAt(i++));\n        enc3 = this.KEY_STR.indexOf(input.charAt(i++));\n        enc4 = this.KEY_STR.indexOf(input.charAt(i++));\n\n        chr1 = (enc1 << 2) | (enc2 >> 4);\n        chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);\n        chr3 = ((enc3 & 3) << 6) | enc4;\n\n        buf.push(chr1);\n\n        if (enc3 !== 64) {\n          buf.push(chr2);\n        }\n        if (enc4 !== 64) {\n          buf.push(chr3);\n        }\n\n        chr1 = chr2 = chr3 = '';\n        enc1 = enc2 = enc3 = enc4 = '';\n\n      } while (i < input.length);\n\n      return buf;\n    };\n\n    return ExifRestorer.restore(orig, resized);  //<= EXIF\n  };\n\n  return upload;\n}]);\n\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/ng-file-upload/ng-file-upload-shim.js",
    "content": "/**!\n * AngularJS file upload directives and services. Supports: file upload/drop/paste, resume, cancel/abort,\n * progress, resize, thumbnail, preview, validation and CORS\n * FileAPI Flash shim for old browsers not supporting FormData\n * @author  Danial  <danial.farid@gmail.com>\n * @version 12.2.13\n */\n\n(function () {\n  /** @namespace FileAPI.noContentTimeout */\n\n  function patchXHR(fnName, newFn) {\n    window.XMLHttpRequest.prototype[fnName] = newFn(window.XMLHttpRequest.prototype[fnName]);\n  }\n\n  function redefineProp(xhr, prop, fn) {\n    try {\n      Object.defineProperty(xhr, prop, {get: fn});\n    } catch (e) {/*ignore*/\n    }\n  }\n\n  if (!window.FileAPI) {\n    window.FileAPI = {};\n  }\n\n  if (!window.XMLHttpRequest) {\n    throw 'AJAX is not supported. XMLHttpRequest is not defined.';\n  }\n\n  FileAPI.shouldLoad = !window.FormData || FileAPI.forceLoad;\n  if (FileAPI.shouldLoad) {\n    var initializeUploadListener = function (xhr) {\n      if (!xhr.__listeners) {\n        if (!xhr.upload) xhr.upload = {};\n        xhr.__listeners = [];\n        var origAddEventListener = xhr.upload.addEventListener;\n        xhr.upload.addEventListener = function (t, fn) {\n          xhr.__listeners[t] = fn;\n          if (origAddEventListener) origAddEventListener.apply(this, arguments);\n        };\n      }\n    };\n\n    patchXHR('open', function (orig) {\n      return function (m, url, b) {\n        initializeUploadListener(this);\n        this.__url = url;\n        try {\n          orig.apply(this, [m, url, b]);\n        } catch (e) {\n          if (e.message.indexOf('Access is denied') > -1) {\n            this.__origError = e;\n            orig.apply(this, [m, '_fix_for_ie_crossdomain__', b]);\n          }\n        }\n      };\n    });\n\n    patchXHR('getResponseHeader', function (orig) {\n      return function (h) {\n        return this.__fileApiXHR && this.__fileApiXHR.getResponseHeader ? this.__fileApiXHR.getResponseHeader(h) : (orig == null ? null : orig.apply(this, [h]));\n      };\n    });\n\n    patchXHR('getAllResponseHeaders', function (orig) {\n      return function () {\n        return this.__fileApiXHR && this.__fileApiXHR.getAllResponseHeaders ? this.__fileApiXHR.getAllResponseHeaders() : (orig == null ? null : orig.apply(this));\n      };\n    });\n\n    patchXHR('abort', function (orig) {\n      return function () {\n        return this.__fileApiXHR && this.__fileApiXHR.abort ? this.__fileApiXHR.abort() : (orig == null ? null : orig.apply(this));\n      };\n    });\n\n    patchXHR('setRequestHeader', function (orig) {\n      return function (header, value) {\n        if (header === '__setXHR_') {\n          initializeUploadListener(this);\n          var val = value(this);\n          // fix for angular < 1.2.0\n          if (val instanceof Function) {\n            val(this);\n          }\n        } else {\n          this.__requestHeaders = this.__requestHeaders || {};\n          this.__requestHeaders[header] = value;\n          orig.apply(this, arguments);\n        }\n      };\n    });\n\n    patchXHR('send', function (orig) {\n      return function () {\n        var xhr = this;\n        if (arguments[0] && arguments[0].__isFileAPIShim) {\n          var formData = arguments[0];\n          var config = {\n            url: xhr.__url,\n            jsonp: false, //removes the callback form param\n            cache: true, //removes the ?fileapiXXX in the url\n            complete: function (err, fileApiXHR) {\n              if (err && angular.isString(err) && err.indexOf('#2174') !== -1) {\n                // this error seems to be fine the file is being uploaded properly.\n                err = null;\n              }\n              xhr.__completed = true;\n              if (!err && xhr.__listeners.load)\n                xhr.__listeners.load({\n                  type: 'load',\n                  loaded: xhr.__loaded,\n                  total: xhr.__total,\n                  target: xhr,\n                  lengthComputable: true\n                });\n              if (!err && xhr.__listeners.loadend)\n                xhr.__listeners.loadend({\n                  type: 'loadend',\n                  loaded: xhr.__loaded,\n                  total: xhr.__total,\n                  target: xhr,\n                  lengthComputable: true\n                });\n              if (err === 'abort' && xhr.__listeners.abort)\n                xhr.__listeners.abort({\n                  type: 'abort',\n                  loaded: xhr.__loaded,\n                  total: xhr.__total,\n                  target: xhr,\n                  lengthComputable: true\n                });\n              if (fileApiXHR.status !== undefined) redefineProp(xhr, 'status', function () {\n                return (fileApiXHR.status === 0 && err && err !== 'abort') ? 500 : fileApiXHR.status;\n              });\n              if (fileApiXHR.statusText !== undefined) redefineProp(xhr, 'statusText', function () {\n                return fileApiXHR.statusText;\n              });\n              redefineProp(xhr, 'readyState', function () {\n                return 4;\n              });\n              if (fileApiXHR.response !== undefined) redefineProp(xhr, 'response', function () {\n                return fileApiXHR.response;\n              });\n              var resp = fileApiXHR.responseText || (err && fileApiXHR.status === 0 && err !== 'abort' ? err : undefined);\n              redefineProp(xhr, 'responseText', function () {\n                return resp;\n              });\n              redefineProp(xhr, 'response', function () {\n                return resp;\n              });\n              if (err) redefineProp(xhr, 'err', function () {\n                return err;\n              });\n              xhr.__fileApiXHR = fileApiXHR;\n              if (xhr.onreadystatechange) xhr.onreadystatechange();\n              if (xhr.onload) xhr.onload();\n            },\n            progress: function (e) {\n              e.target = xhr;\n              if (xhr.__listeners.progress) xhr.__listeners.progress(e);\n              xhr.__total = e.total;\n              xhr.__loaded = e.loaded;\n              if (e.total === e.loaded) {\n                // fix flash issue that doesn't call complete if there is no response text from the server\n                var _this = this;\n                setTimeout(function () {\n                  if (!xhr.__completed) {\n                    xhr.getAllResponseHeaders = function () {\n                    };\n                    _this.complete(null, {status: 204, statusText: 'No Content'});\n                  }\n                }, FileAPI.noContentTimeout || 10000);\n              }\n            },\n            headers: xhr.__requestHeaders\n          };\n          config.data = {};\n          config.files = {};\n          for (var i = 0; i < formData.data.length; i++) {\n            var item = formData.data[i];\n            if (item.val != null && item.val.name != null && item.val.size != null && item.val.type != null) {\n              config.files[item.key] = item.val;\n            } else {\n              config.data[item.key] = item.val;\n            }\n          }\n\n          setTimeout(function () {\n            if (!FileAPI.hasFlash) {\n              throw 'Adode Flash Player need to be installed. To check ahead use \"FileAPI.hasFlash\"';\n            }\n            xhr.__fileApiXHR = FileAPI.upload(config);\n          }, 1);\n        } else {\n          if (this.__origError) {\n            throw this.__origError;\n          }\n          orig.apply(xhr, arguments);\n        }\n      };\n    });\n    window.XMLHttpRequest.__isFileAPIShim = true;\n    window.FormData = FormData = function () {\n      return {\n        append: function (key, val, name) {\n          if (val.__isFileAPIBlobShim) {\n            val = val.data[0];\n          }\n          this.data.push({\n            key: key,\n            val: val,\n            name: name\n          });\n        },\n        data: [],\n        __isFileAPIShim: true\n      };\n    };\n\n    window.Blob = Blob = function (b) {\n      return {\n        data: b,\n        __isFileAPIBlobShim: true\n      };\n    };\n  }\n\n})();\n\n(function () {\n  /** @namespace FileAPI.forceLoad */\n  /** @namespace window.FileAPI.jsUrl */\n  /** @namespace window.FileAPI.jsPath */\n\n  function isInputTypeFile(elem) {\n    return elem[0].tagName.toLowerCase() === 'input' && elem.attr('type') && elem.attr('type').toLowerCase() === 'file';\n  }\n\n  function hasFlash() {\n    try {\n      var fo = new ActiveXObject('ShockwaveFlash.ShockwaveFlash');\n      if (fo) return true;\n    } catch (e) {\n      if (navigator.mimeTypes['application/x-shockwave-flash'] !== undefined) return true;\n    }\n    return false;\n  }\n\n  function getOffset(obj) {\n    var left = 0, top = 0;\n\n    if (window.jQuery) {\n      return jQuery(obj).offset();\n    }\n\n    if (obj.offsetParent) {\n      do {\n        left += (obj.offsetLeft - obj.scrollLeft);\n        top += (obj.offsetTop - obj.scrollTop);\n        obj = obj.offsetParent;\n      } while (obj);\n    }\n    return {\n      left: left,\n      top: top\n    };\n  }\n\n  if (FileAPI.shouldLoad) {\n    FileAPI.hasFlash = hasFlash();\n\n    //load FileAPI\n    if (FileAPI.forceLoad) {\n      FileAPI.html5 = false;\n    }\n\n    if (!FileAPI.upload) {\n      var jsUrl, basePath, script = document.createElement('script'), allScripts = document.getElementsByTagName('script'), i, index, src;\n      if (window.FileAPI.jsUrl) {\n        jsUrl = window.FileAPI.jsUrl;\n      } else if (window.FileAPI.jsPath) {\n        basePath = window.FileAPI.jsPath;\n      } else {\n        for (i = 0; i < allScripts.length; i++) {\n          src = allScripts[i].src;\n          index = src.search(/\\/ng\\-file\\-upload[\\-a-zA-z0-9\\.]*\\.js/);\n          if (index > -1) {\n            basePath = src.substring(0, index + 1);\n            break;\n          }\n        }\n      }\n\n      if (FileAPI.staticPath == null) FileAPI.staticPath = basePath;\n      script.setAttribute('src', jsUrl || basePath + 'FileAPI.min.js');\n      document.getElementsByTagName('head')[0].appendChild(script);\n    }\n\n    FileAPI.ngfFixIE = function (elem, fileElem, changeFn) {\n      if (!hasFlash()) {\n        throw 'Adode Flash Player need to be installed. To check ahead use \"FileAPI.hasFlash\"';\n      }\n      var fixInputStyle = function () {\n        var label = fileElem.parent();\n        if (elem.attr('disabled')) {\n          if (label) label.removeClass('js-fileapi-wrapper');\n        } else {\n          if (!fileElem.attr('__ngf_flash_')) {\n            fileElem.unbind('change');\n            fileElem.unbind('click');\n            fileElem.bind('change', function (evt) {\n              fileApiChangeFn.apply(this, [evt]);\n              changeFn.apply(this, [evt]);\n            });\n            fileElem.attr('__ngf_flash_', 'true');\n          }\n          label.addClass('js-fileapi-wrapper');\n          if (!isInputTypeFile(elem)) {\n            label.css('position', 'absolute')\n              .css('top', getOffset(elem[0]).top + 'px').css('left', getOffset(elem[0]).left + 'px')\n              .css('width', elem[0].offsetWidth + 'px').css('height', elem[0].offsetHeight + 'px')\n              .css('filter', 'alpha(opacity=0)').css('display', elem.css('display'))\n              .css('overflow', 'hidden').css('z-index', '900000')\n              .css('visibility', 'visible');\n            fileElem.css('width', elem[0].offsetWidth + 'px').css('height', elem[0].offsetHeight + 'px')\n              .css('position', 'absolute').css('top', '0px').css('left', '0px');\n          }\n        }\n      };\n\n      elem.bind('mouseenter', fixInputStyle);\n\n      var fileApiChangeFn = function (evt) {\n        var files = FileAPI.getFiles(evt);\n        //just a double check for #233\n        for (var i = 0; i < files.length; i++) {\n          if (files[i].size === undefined) files[i].size = 0;\n          if (files[i].name === undefined) files[i].name = 'file';\n          if (files[i].type === undefined) files[i].type = 'undefined';\n        }\n        if (!evt.target) {\n          evt.target = {};\n        }\n        evt.target.files = files;\n        // if evt.target.files is not writable use helper field\n        if (evt.target.files !== files) {\n          evt.__files_ = files;\n        }\n        (evt.__files_ || evt.target.files).item = function (i) {\n          return (evt.__files_ || evt.target.files)[i] || null;\n        };\n      };\n    };\n\n    FileAPI.disableFileInput = function (elem, disable) {\n      if (disable) {\n        elem.removeClass('js-fileapi-wrapper');\n      } else {\n        elem.addClass('js-fileapi-wrapper');\n      }\n    };\n  }\n})();\n\nif (!window.FileReader) {\n  window.FileReader = function () {\n    var _this = this, loadStarted = false;\n    this.listeners = {};\n    this.addEventListener = function (type, fn) {\n      _this.listeners[type] = _this.listeners[type] || [];\n      _this.listeners[type].push(fn);\n    };\n    this.removeEventListener = function (type, fn) {\n      if (_this.listeners[type]) _this.listeners[type].splice(_this.listeners[type].indexOf(fn), 1);\n    };\n    this.dispatchEvent = function (evt) {\n      var list = _this.listeners[evt.type];\n      if (list) {\n        for (var i = 0; i < list.length; i++) {\n          list[i].call(_this, evt);\n        }\n      }\n    };\n    this.onabort = this.onerror = this.onload = this.onloadstart = this.onloadend = this.onprogress = null;\n\n    var constructEvent = function (type, evt) {\n      var e = {type: type, target: _this, loaded: evt.loaded, total: evt.total, error: evt.error};\n      if (evt.result != null) e.target.result = evt.result;\n      return e;\n    };\n    var listener = function (evt) {\n      if (!loadStarted) {\n        loadStarted = true;\n        if (_this.onloadstart) _this.onloadstart(constructEvent('loadstart', evt));\n      }\n      var e;\n      if (evt.type === 'load') {\n        if (_this.onloadend) _this.onloadend(constructEvent('loadend', evt));\n        e = constructEvent('load', evt);\n        if (_this.onload) _this.onload(e);\n        _this.dispatchEvent(e);\n      } else if (evt.type === 'progress') {\n        e = constructEvent('progress', evt);\n        if (_this.onprogress) _this.onprogress(e);\n        _this.dispatchEvent(e);\n      } else {\n        e = constructEvent('error', evt);\n        if (_this.onerror) _this.onerror(e);\n        _this.dispatchEvent(e);\n      }\n    };\n    this.readAsDataURL = function (file) {\n      FileAPI.readAsDataURL(file, listener);\n    };\n    this.readAsText = function (file) {\n      FileAPI.readAsText(file, listener);\n    };\n  };\n}\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/ng-file-upload/ng-file-upload.js",
    "content": "/**!\n * AngularJS file upload directives and services. Supoorts: file upload/drop/paste, resume, cancel/abort,\n * progress, resize, thumbnail, preview, validation and CORS\n * @author  Danial  <danial.farid@gmail.com>\n * @version 12.2.13\n */\n\nif (window.XMLHttpRequest && !(window.FileAPI && FileAPI.shouldLoad)) {\n  window.XMLHttpRequest.prototype.setRequestHeader = (function (orig) {\n    return function (header, value) {\n      if (header === '__setXHR_') {\n        var val = value(this);\n        // fix for angular < 1.2.0\n        if (val instanceof Function) {\n          val(this);\n        }\n      } else {\n        orig.apply(this, arguments);\n      }\n    };\n  })(window.XMLHttpRequest.prototype.setRequestHeader);\n}\n\nvar ngFileUpload = angular.module('ngFileUpload', []);\n\nngFileUpload.version = '12.2.13';\n\nngFileUpload.service('UploadBase', ['$http', '$q', '$timeout', function ($http, $q, $timeout) {\n  var upload = this;\n  upload.promisesCount = 0;\n\n  this.isResumeSupported = function () {\n    return window.Blob && window.Blob.prototype.slice;\n  };\n\n  var resumeSupported = this.isResumeSupported();\n\n  function sendHttp(config) {\n    config.method = config.method || 'POST';\n    config.headers = config.headers || {};\n\n    var deferred = config._deferred = config._deferred || $q.defer();\n    var promise = deferred.promise;\n\n    function notifyProgress(e) {\n      if (deferred.notify) {\n        deferred.notify(e);\n      }\n      if (promise.progressFunc) {\n        $timeout(function () {\n          promise.progressFunc(e);\n        });\n      }\n    }\n\n    function getNotifyEvent(n) {\n      if (config._start != null && resumeSupported) {\n        return {\n          loaded: n.loaded + config._start,\n          total: (config._file && config._file.size) || n.total,\n          type: n.type, config: config,\n          lengthComputable: true, target: n.target\n        };\n      } else {\n        return n;\n      }\n    }\n\n    if (!config.disableProgress) {\n      config.headers.__setXHR_ = function () {\n        return function (xhr) {\n          if (!xhr || !xhr.upload || !xhr.upload.addEventListener) return;\n          config.__XHR = xhr;\n          if (config.xhrFn) config.xhrFn(xhr);\n          xhr.upload.addEventListener('progress', function (e) {\n            e.config = config;\n            notifyProgress(getNotifyEvent(e));\n          }, false);\n          //fix for firefox not firing upload progress end, also IE8-9\n          xhr.upload.addEventListener('load', function (e) {\n            if (e.lengthComputable) {\n              e.config = config;\n              notifyProgress(getNotifyEvent(e));\n            }\n          }, false);\n        };\n      };\n    }\n\n    function uploadWithAngular() {\n      $http(config).then(function (r) {\n          if (resumeSupported && config._chunkSize && !config._finished && config._file) {\n            var fileSize = config._file && config._file.size || 0;\n            notifyProgress({\n                loaded: Math.min(config._end, fileSize),\n                total: fileSize,\n                config: config,\n                type: 'progress'\n              }\n            );\n            upload.upload(config, true);\n          } else {\n            if (config._finished) delete config._finished;\n            deferred.resolve(r);\n          }\n        }, function (e) {\n          deferred.reject(e);\n        }, function (n) {\n          deferred.notify(n);\n        }\n      );\n    }\n\n    if (!resumeSupported) {\n      uploadWithAngular();\n    } else if (config._chunkSize && config._end && !config._finished) {\n      config._start = config._end;\n      config._end += config._chunkSize;\n      uploadWithAngular();\n    } else if (config.resumeSizeUrl) {\n      $http.get(config.resumeSizeUrl).then(function (resp) {\n        if (config.resumeSizeResponseReader) {\n          config._start = config.resumeSizeResponseReader(resp.data);\n        } else {\n          config._start = parseInt((resp.data.size == null ? resp.data : resp.data.size).toString());\n        }\n        if (config._chunkSize) {\n          config._end = config._start + config._chunkSize;\n        }\n        uploadWithAngular();\n      }, function (e) {\n        throw e;\n      });\n    } else if (config.resumeSize) {\n      config.resumeSize().then(function (size) {\n        config._start = size;\n        if (config._chunkSize) {\n          config._end = config._start + config._chunkSize;\n        }\n        uploadWithAngular();\n      }, function (e) {\n        throw e;\n      });\n    } else {\n      if (config._chunkSize) {\n        config._start = 0;\n        config._end = config._start + config._chunkSize;\n      }\n      uploadWithAngular();\n    }\n\n\n    promise.success = function (fn) {\n      promise.then(function (response) {\n        fn(response.data, response.status, response.headers, config);\n      });\n      return promise;\n    };\n\n    promise.error = function (fn) {\n      promise.then(null, function (response) {\n        fn(response.data, response.status, response.headers, config);\n      });\n      return promise;\n    };\n\n    promise.progress = function (fn) {\n      promise.progressFunc = fn;\n      promise.then(null, null, function (n) {\n        fn(n);\n      });\n      return promise;\n    };\n    promise.abort = promise.pause = function () {\n      if (config.__XHR) {\n        $timeout(function () {\n          config.__XHR.abort();\n        });\n      }\n      return promise;\n    };\n    promise.xhr = function (fn) {\n      config.xhrFn = (function (origXhrFn) {\n        return function () {\n          if (origXhrFn) origXhrFn.apply(promise, arguments);\n          fn.apply(promise, arguments);\n        };\n      })(config.xhrFn);\n      return promise;\n    };\n\n    upload.promisesCount++;\n    if (promise['finally'] && promise['finally'] instanceof Function) {\n      promise['finally'](function () {\n        upload.promisesCount--;\n      });\n    }\n    return promise;\n  }\n\n  this.isUploadInProgress = function () {\n    return upload.promisesCount > 0;\n  };\n\n  this.rename = function (file, name) {\n    file.ngfName = name;\n    return file;\n  };\n\n  this.jsonBlob = function (val) {\n    if (val != null && !angular.isString(val)) {\n      val = JSON.stringify(val);\n    }\n    var blob = new window.Blob([val], {type: 'application/json'});\n    blob._ngfBlob = true;\n    return blob;\n  };\n\n  this.json = function (val) {\n    return angular.toJson(val);\n  };\n\n  function copy(obj) {\n    var clone = {};\n    for (var key in obj) {\n      if (obj.hasOwnProperty(key)) {\n        clone[key] = obj[key];\n      }\n    }\n    return clone;\n  }\n\n  this.isFile = function (file) {\n    return file != null && (file instanceof window.Blob || (file.flashId && file.name && file.size));\n  };\n\n  this.upload = function (config, internal) {\n    function toResumeFile(file, formData) {\n      if (file._ngfBlob) return file;\n      config._file = config._file || file;\n      if (config._start != null && resumeSupported) {\n        if (config._end && config._end >= file.size) {\n          config._finished = true;\n          config._end = file.size;\n        }\n        var slice = file.slice(config._start, config._end || file.size);\n        slice.name = file.name;\n        slice.ngfName = file.ngfName;\n        if (config._chunkSize) {\n          formData.append('_chunkSize', config._chunkSize);\n          formData.append('_currentChunkSize', config._end - config._start);\n          formData.append('_chunkNumber', Math.floor(config._start / config._chunkSize));\n          formData.append('_totalSize', config._file.size);\n        }\n        return slice;\n      }\n      return file;\n    }\n\n    function addFieldToFormData(formData, val, key) {\n      if (val !== undefined) {\n        if (angular.isDate(val)) {\n          val = val.toISOString();\n        }\n        if (angular.isString(val)) {\n          formData.append(key, val);\n        } else if (upload.isFile(val)) {\n          var file = toResumeFile(val, formData);\n          var split = key.split(',');\n          if (split[1]) {\n            file.ngfName = split[1].replace(/^\\s+|\\s+$/g, '');\n            key = split[0];\n          }\n          config._fileKey = config._fileKey || key;\n          formData.append(key, file, file.ngfName || file.name);\n        } else {\n          if (angular.isObject(val)) {\n            if (val.$$ngfCircularDetection) throw 'ngFileUpload: Circular reference in config.data. Make sure specified data for Upload.upload() has no circular reference: ' + key;\n\n            val.$$ngfCircularDetection = true;\n            try {\n              for (var k in val) {\n                if (val.hasOwnProperty(k) && k !== '$$ngfCircularDetection') {\n                  var objectKey = config.objectKey == null ? '[i]' : config.objectKey;\n                  if (val.length && parseInt(k) > -1) {\n                    objectKey = config.arrayKey == null ? objectKey : config.arrayKey;\n                  }\n                  addFieldToFormData(formData, val[k], key + objectKey.replace(/[ik]/g, k));\n                }\n              }\n            } finally {\n              delete val.$$ngfCircularDetection;\n            }\n          } else {\n            formData.append(key, val);\n          }\n        }\n      }\n    }\n\n    function digestConfig() {\n      config._chunkSize = upload.translateScalars(config.resumeChunkSize);\n      config._chunkSize = config._chunkSize ? parseInt(config._chunkSize.toString()) : null;\n\n      config.headers = config.headers || {};\n      config.headers['Content-Type'] = undefined;\n      config.transformRequest = config.transformRequest ?\n        (angular.isArray(config.transformRequest) ?\n          config.transformRequest : [config.transformRequest]) : [];\n      config.transformRequest.push(function (data) {\n        var formData = new window.FormData(), key;\n        data = data || config.fields || {};\n        if (config.file) {\n          data.file = config.file;\n        }\n        for (key in data) {\n          if (data.hasOwnProperty(key)) {\n            var val = data[key];\n            if (config.formDataAppender) {\n              config.formDataAppender(formData, key, val);\n            } else {\n              addFieldToFormData(formData, val, key);\n            }\n          }\n        }\n\n        return formData;\n      });\n    }\n\n    if (!internal) config = copy(config);\n    if (!config._isDigested) {\n      config._isDigested = true;\n      digestConfig();\n    }\n\n    return sendHttp(config);\n  };\n\n  this.http = function (config) {\n    config = copy(config);\n    config.transformRequest = config.transformRequest || function (data) {\n        if ((window.ArrayBuffer && data instanceof window.ArrayBuffer) || data instanceof window.Blob) {\n          return data;\n        }\n        return $http.defaults.transformRequest[0].apply(this, arguments);\n      };\n    config._chunkSize = upload.translateScalars(config.resumeChunkSize);\n    config._chunkSize = config._chunkSize ? parseInt(config._chunkSize.toString()) : null;\n\n    return sendHttp(config);\n  };\n\n  this.translateScalars = function (str) {\n    if (angular.isString(str)) {\n      if (str.search(/kb/i) === str.length - 2) {\n        return parseFloat(str.substring(0, str.length - 2) * 1024);\n      } else if (str.search(/mb/i) === str.length - 2) {\n        return parseFloat(str.substring(0, str.length - 2) * 1048576);\n      } else if (str.search(/gb/i) === str.length - 2) {\n        return parseFloat(str.substring(0, str.length - 2) * 1073741824);\n      } else if (str.search(/b/i) === str.length - 1) {\n        return parseFloat(str.substring(0, str.length - 1));\n      } else if (str.search(/s/i) === str.length - 1) {\n        return parseFloat(str.substring(0, str.length - 1));\n      } else if (str.search(/m/i) === str.length - 1) {\n        return parseFloat(str.substring(0, str.length - 1) * 60);\n      } else if (str.search(/h/i) === str.length - 1) {\n        return parseFloat(str.substring(0, str.length - 1) * 3600);\n      }\n    }\n    return str;\n  };\n\n  this.urlToBlob = function(url) {\n    var defer = $q.defer();\n    $http({url: url, method: 'get', responseType: 'arraybuffer'}).then(function (resp) {\n      var arrayBufferView = new Uint8Array(resp.data);\n      var type = resp.headers('content-type') || 'image/WebP';\n      var blob = new window.Blob([arrayBufferView], {type: type});\n      var matches = url.match(/.*\\/(.+?)(\\?.*)?$/);\n      if (matches.length > 1) {\n        blob.name = matches[1];\n      }\n      defer.resolve(blob);\n    }, function (e) {\n      defer.reject(e);\n    });\n    return defer.promise;\n  };\n\n  this.setDefaults = function (defaults) {\n    this.defaults = defaults || {};\n  };\n\n  this.defaults = {};\n  this.version = ngFileUpload.version;\n}\n\n]);\n\nngFileUpload.service('Upload', ['$parse', '$timeout', '$compile', '$q', 'UploadExif', function ($parse, $timeout, $compile, $q, UploadExif) {\n  var upload = UploadExif;\n  upload.getAttrWithDefaults = function (attr, name) {\n    if (attr[name] != null) return attr[name];\n    var def = upload.defaults[name];\n    return (def == null ? def : (angular.isString(def) ? def : JSON.stringify(def)));\n  };\n\n  upload.attrGetter = function (name, attr, scope, params) {\n    var attrVal = this.getAttrWithDefaults(attr, name);\n    if (scope) {\n      try {\n        if (params) {\n          return $parse(attrVal)(scope, params);\n        } else {\n          return $parse(attrVal)(scope);\n        }\n      } catch (e) {\n        // hangle string value without single qoute\n        if (name.search(/min|max|pattern/i)) {\n          return attrVal;\n        } else {\n          throw e;\n        }\n      }\n    } else {\n      return attrVal;\n    }\n  };\n\n  upload.shouldUpdateOn = function (type, attr, scope) {\n    var modelOptions = upload.attrGetter('ngfModelOptions', attr, scope);\n    if (modelOptions && modelOptions.updateOn) {\n      return modelOptions.updateOn.split(' ').indexOf(type) > -1;\n    }\n    return true;\n  };\n\n  upload.emptyPromise = function () {\n    var d = $q.defer();\n    var args = arguments;\n    $timeout(function () {\n      d.resolve.apply(d, args);\n    });\n    return d.promise;\n  };\n\n  upload.rejectPromise = function () {\n    var d = $q.defer();\n    var args = arguments;\n    $timeout(function () {\n      d.reject.apply(d, args);\n    });\n    return d.promise;\n  };\n\n  upload.happyPromise = function (promise, data) {\n    var d = $q.defer();\n    promise.then(function (result) {\n      d.resolve(result);\n    }, function (error) {\n      $timeout(function () {\n        throw error;\n      });\n      d.resolve(data);\n    });\n    return d.promise;\n  };\n\n  function applyExifRotations(files, attr, scope) {\n    var promises = [upload.emptyPromise()];\n    angular.forEach(files, function (f, i) {\n      if (f.type.indexOf('image/jpeg') === 0 && upload.attrGetter('ngfFixOrientation', attr, scope, {$file: f})) {\n        promises.push(upload.happyPromise(upload.applyExifRotation(f), f).then(function (fixedFile) {\n          files.splice(i, 1, fixedFile);\n        }));\n      }\n    });\n    return $q.all(promises);\n  }\n\n  function resizeFile(files, attr, scope, ngModel) {\n    var resizeVal = upload.attrGetter('ngfResize', attr, scope);\n    if (!resizeVal || !upload.isResizeSupported() || !files.length) return upload.emptyPromise();\n    if (resizeVal instanceof Function) {\n      var defer = $q.defer();\n      return resizeVal(files).then(function (p) {\n        resizeWithParams(p, files, attr, scope, ngModel).then(function (r) {\n          defer.resolve(r);\n        }, function (e) {\n          defer.reject(e);\n        });\n      }, function (e) {\n        defer.reject(e);\n      });\n    } else {\n      return resizeWithParams(resizeVal, files, attr, scope, ngModel);\n    }\n  }\n\n  function resizeWithParams(params, files, attr, scope, ngModel) {\n    var promises = [upload.emptyPromise()];\n\n    function handleFile(f, i) {\n      if (f.type.indexOf('image') === 0) {\n        if (params.pattern && !upload.validatePattern(f, params.pattern)) return;\n        params.resizeIf = function (width, height) {\n          return upload.attrGetter('ngfResizeIf', attr, scope,\n            {$width: width, $height: height, $file: f});\n        };\n        var promise = upload.resize(f, params);\n        promises.push(promise);\n        promise.then(function (resizedFile) {\n          files.splice(i, 1, resizedFile);\n        }, function (e) {\n          f.$error = 'resize';\n          (f.$errorMessages = (f.$errorMessages || {})).resize = true;\n          f.$errorParam = (e ? (e.message ? e.message : e) + ': ' : '') + (f && f.name);\n          ngModel.$ngfValidations.push({name: 'resize', valid: false});\n          upload.applyModelValidation(ngModel, files);\n        });\n      }\n    }\n\n    for (var i = 0; i < files.length; i++) {\n      handleFile(files[i], i);\n    }\n    return $q.all(promises);\n  }\n\n  upload.updateModel = function (ngModel, attr, scope, fileChange, files, evt, noDelay) {\n    function update(files, invalidFiles, newFiles, dupFiles, isSingleModel) {\n      attr.$$ngfPrevValidFiles = files;\n      attr.$$ngfPrevInvalidFiles = invalidFiles;\n      var file = files && files.length ? files[0] : null;\n      var invalidFile = invalidFiles && invalidFiles.length ? invalidFiles[0] : null;\n\n      if (ngModel) {\n        upload.applyModelValidation(ngModel, files);\n        ngModel.$setViewValue(isSingleModel ? file : files);\n      }\n\n      if (fileChange) {\n        $parse(fileChange)(scope, {\n          $files: files,\n          $file: file,\n          $newFiles: newFiles,\n          $duplicateFiles: dupFiles,\n          $invalidFiles: invalidFiles,\n          $invalidFile: invalidFile,\n          $event: evt\n        });\n      }\n\n      var invalidModel = upload.attrGetter('ngfModelInvalid', attr);\n      if (invalidModel) {\n        $timeout(function () {\n          $parse(invalidModel).assign(scope, isSingleModel ? invalidFile : invalidFiles);\n        });\n      }\n      $timeout(function () {\n        // scope apply changes\n      });\n    }\n\n    var allNewFiles, dupFiles = [], prevValidFiles, prevInvalidFiles,\n      invalids = [], valids = [];\n\n    function removeDuplicates() {\n      function equals(f1, f2) {\n        return f1.name === f2.name && (f1.$ngfOrigSize || f1.size) === (f2.$ngfOrigSize || f2.size) &&\n          f1.type === f2.type;\n      }\n\n      function isInPrevFiles(f) {\n        var j;\n        for (j = 0; j < prevValidFiles.length; j++) {\n          if (equals(f, prevValidFiles[j])) {\n            return true;\n          }\n        }\n        for (j = 0; j < prevInvalidFiles.length; j++) {\n          if (equals(f, prevInvalidFiles[j])) {\n            return true;\n          }\n        }\n        return false;\n      }\n\n      if (files) {\n        allNewFiles = [];\n        dupFiles = [];\n        for (var i = 0; i < files.length; i++) {\n          if (isInPrevFiles(files[i])) {\n            dupFiles.push(files[i]);\n          } else {\n            allNewFiles.push(files[i]);\n          }\n        }\n      }\n    }\n\n    function toArray(v) {\n      return angular.isArray(v) ? v : [v];\n    }\n\n    function resizeAndUpdate() {\n      function updateModel() {\n        $timeout(function () {\n          update(keep ? prevValidFiles.concat(valids) : valids,\n            keep ? prevInvalidFiles.concat(invalids) : invalids,\n            files, dupFiles, isSingleModel);\n        }, options && options.debounce ? options.debounce.change || options.debounce : 0);\n      }\n\n      var resizingFiles = validateAfterResize ? allNewFiles : valids;\n      resizeFile(resizingFiles, attr, scope, ngModel).then(function () {\n        if (validateAfterResize) {\n          upload.validate(allNewFiles, keep ? prevValidFiles.length : 0, ngModel, attr, scope)\n            .then(function (validationResult) {\n              valids = validationResult.validsFiles;\n              invalids = validationResult.invalidsFiles;\n              updateModel();\n            });\n        } else {\n          updateModel();\n        }\n      }, function () {\n        for (var i = 0; i < resizingFiles.length; i++) {\n          var f = resizingFiles[i];\n          if (f.$error === 'resize') {\n            var index = valids.indexOf(f);\n            if (index > -1) {\n              valids.splice(index, 1);\n              invalids.push(f);\n            }\n            updateModel();\n          }\n        }\n      });\n    }\n\n    prevValidFiles = attr.$$ngfPrevValidFiles || [];\n    prevInvalidFiles = attr.$$ngfPrevInvalidFiles || [];\n    if (ngModel && ngModel.$modelValue) {\n      prevValidFiles = toArray(ngModel.$modelValue);\n    }\n\n    var keep = upload.attrGetter('ngfKeep', attr, scope);\n    allNewFiles = (files || []).slice(0);\n    if (keep === 'distinct' || upload.attrGetter('ngfKeepDistinct', attr, scope) === true) {\n      removeDuplicates(attr, scope);\n    }\n\n    var isSingleModel = !keep && !upload.attrGetter('ngfMultiple', attr, scope) && !upload.attrGetter('multiple', attr);\n\n    if (keep && !allNewFiles.length) return;\n\n    upload.attrGetter('ngfBeforeModelChange', attr, scope, {\n      $files: files,\n      $file: files && files.length ? files[0] : null,\n      $newFiles: allNewFiles,\n      $duplicateFiles: dupFiles,\n      $event: evt\n    });\n\n    var validateAfterResize = upload.attrGetter('ngfValidateAfterResize', attr, scope);\n\n    var options = upload.attrGetter('ngfModelOptions', attr, scope);\n    upload.validate(allNewFiles, keep ? prevValidFiles.length : 0, ngModel, attr, scope)\n      .then(function (validationResult) {\n      if (noDelay) {\n        update(allNewFiles, [], files, dupFiles, isSingleModel);\n      } else {\n        if ((!options || !options.allowInvalid) && !validateAfterResize) {\n          valids = validationResult.validFiles;\n          invalids = validationResult.invalidFiles;\n        } else {\n          valids = allNewFiles;\n        }\n        if (upload.attrGetter('ngfFixOrientation', attr, scope) && upload.isExifSupported()) {\n          applyExifRotations(valids, attr, scope).then(function () {\n            resizeAndUpdate();\n          });\n        } else {\n          resizeAndUpdate();\n        }\n      }\n    });\n  };\n\n  return upload;\n}]);\n\nngFileUpload.directive('ngfSelect', ['$parse', '$timeout', '$compile', 'Upload', function ($parse, $timeout, $compile, Upload) {\n  var generatedElems = [];\n\n  function isDelayedClickSupported(ua) {\n    // fix for android native browser < 4.4 and safari windows\n    var m = ua.match(/Android[^\\d]*(\\d+)\\.(\\d+)/);\n    if (m && m.length > 2) {\n      var v = Upload.defaults.androidFixMinorVersion || 4;\n      return parseInt(m[1]) < 4 || (parseInt(m[1]) === v && parseInt(m[2]) < v);\n    }\n\n    // safari on windows\n    return ua.indexOf('Chrome') === -1 && /.*Windows.*Safari.*/.test(ua);\n  }\n\n  function linkFileSelect(scope, elem, attr, ngModel, $parse, $timeout, $compile, upload) {\n    /** @namespace attr.ngfSelect */\n    /** @namespace attr.ngfChange */\n    /** @namespace attr.ngModel */\n    /** @namespace attr.ngfModelOptions */\n    /** @namespace attr.ngfMultiple */\n    /** @namespace attr.ngfCapture */\n    /** @namespace attr.ngfValidate */\n    /** @namespace attr.ngfKeep */\n    var attrGetter = function (name, scope) {\n      return upload.attrGetter(name, attr, scope);\n    };\n\n    function isInputTypeFile() {\n      return elem[0].tagName.toLowerCase() === 'input' && attr.type && attr.type.toLowerCase() === 'file';\n    }\n\n    function fileChangeAttr() {\n      return attrGetter('ngfChange') || attrGetter('ngfSelect');\n    }\n\n    function changeFn(evt) {\n      if (upload.shouldUpdateOn('change', attr, scope)) {\n        var fileList = evt.__files_ || (evt.target && evt.target.files), files = [];\n        /* Handle duplicate call in  IE11 */\n        if (!fileList) return;\n        for (var i = 0; i < fileList.length; i++) {\n          files.push(fileList[i]);\n        }\n        upload.updateModel(ngModel, attr, scope, fileChangeAttr(),\n          files.length ? files : null, evt);\n      }\n    }\n\n    upload.registerModelChangeValidator(ngModel, attr, scope);\n\n    var unwatches = [];\n    if (attrGetter('ngfMultiple')) {\n      unwatches.push(scope.$watch(attrGetter('ngfMultiple'), function () {\n        fileElem.attr('multiple', attrGetter('ngfMultiple', scope));\n      }));\n    }\n    if (attrGetter('ngfCapture')) {\n      unwatches.push(scope.$watch(attrGetter('ngfCapture'), function () {\n        fileElem.attr('capture', attrGetter('ngfCapture', scope));\n      }));\n    }\n    if (attrGetter('ngfAccept')) {\n      unwatches.push(scope.$watch(attrGetter('ngfAccept'), function () {\n        fileElem.attr('accept', attrGetter('ngfAccept', scope));\n      }));\n    }\n    unwatches.push(attr.$observe('accept', function () {\n      fileElem.attr('accept', attrGetter('accept'));\n    }));\n    function bindAttrToFileInput(fileElem, label) {\n      function updateId(val) {\n        fileElem.attr('id', 'ngf-' + val);\n        label.attr('id', 'ngf-label-' + val);\n      }\n\n      for (var i = 0; i < elem[0].attributes.length; i++) {\n        var attribute = elem[0].attributes[i];\n        if (attribute.name !== 'type' && attribute.name !== 'class' && attribute.name !== 'style') {\n          if (attribute.name === 'id') {\n            updateId(attribute.value);\n            unwatches.push(attr.$observe('id', updateId));\n          } else {\n            fileElem.attr(attribute.name, (!attribute.value && (attribute.name === 'required' ||\n            attribute.name === 'multiple')) ? attribute.name : attribute.value);\n          }\n        }\n      }\n    }\n\n    function createFileInput() {\n      if (isInputTypeFile()) {\n        return elem;\n      }\n\n      var fileElem = angular.element('<input type=\"file\">');\n\n      var label = angular.element('<label>upload</label>');\n      label.css('visibility', 'hidden').css('position', 'absolute').css('overflow', 'hidden')\n        .css('width', '0px').css('height', '0px').css('border', 'none')\n        .css('margin', '0px').css('padding', '0px').attr('tabindex', '-1');\n      bindAttrToFileInput(fileElem, label);\n\n      generatedElems.push({el: elem, ref: label});\n\n      document.body.appendChild(label.append(fileElem)[0]);\n\n      return fileElem;\n    }\n\n    function clickHandler(evt) {\n      if (elem.attr('disabled')) return false;\n      if (attrGetter('ngfSelectDisabled', scope)) return;\n\n      var r = detectSwipe(evt);\n      // prevent the click if it is a swipe\n      if (r != null) return r;\n\n      resetModel(evt);\n\n      // fix for md when the element is removed from the DOM and added back #460\n      try {\n        if (!isInputTypeFile() && !document.body.contains(fileElem[0])) {\n          generatedElems.push({el: elem, ref: fileElem.parent()});\n          document.body.appendChild(fileElem.parent()[0]);\n          fileElem.bind('change', changeFn);\n        }\n      } catch (e) {/*ignore*/\n      }\n\n      if (isDelayedClickSupported(navigator.userAgent)) {\n        setTimeout(function () {\n          fileElem[0].click();\n        }, 0);\n      } else {\n        fileElem[0].click();\n      }\n\n      return false;\n    }\n\n\n    var initialTouchStartY = 0;\n    var initialTouchStartX = 0;\n\n    function detectSwipe(evt) {\n      var touches = evt.changedTouches || (evt.originalEvent && evt.originalEvent.changedTouches);\n      if (touches) {\n        if (evt.type === 'touchstart') {\n          initialTouchStartX = touches[0].clientX;\n          initialTouchStartY = touches[0].clientY;\n          return true; // don't block event default\n        } else {\n          // prevent scroll from triggering event\n          if (evt.type === 'touchend') {\n            var currentX = touches[0].clientX;\n            var currentY = touches[0].clientY;\n            if ((Math.abs(currentX - initialTouchStartX) > 20) ||\n              (Math.abs(currentY - initialTouchStartY) > 20)) {\n              evt.stopPropagation();\n              evt.preventDefault();\n              return false;\n            }\n          }\n          return true;\n        }\n      }\n    }\n\n    var fileElem = elem;\n\n    function resetModel(evt) {\n      if (upload.shouldUpdateOn('click', attr, scope) && fileElem.val()) {\n        fileElem.val(null);\n        upload.updateModel(ngModel, attr, scope, fileChangeAttr(), null, evt, true);\n      }\n    }\n\n    if (!isInputTypeFile()) {\n      fileElem = createFileInput();\n    }\n    fileElem.bind('change', changeFn);\n\n    if (!isInputTypeFile()) {\n      elem.bind('click touchstart touchend', clickHandler);\n    } else {\n      elem.bind('click', resetModel);\n    }\n\n    function ie10SameFileSelectFix(evt) {\n      if (fileElem && !fileElem.attr('__ngf_ie10_Fix_')) {\n        if (!fileElem[0].parentNode) {\n          fileElem = null;\n          return;\n        }\n        evt.preventDefault();\n        evt.stopPropagation();\n        fileElem.unbind('click');\n        var clone = fileElem.clone();\n        fileElem.replaceWith(clone);\n        fileElem = clone;\n        fileElem.attr('__ngf_ie10_Fix_', 'true');\n        fileElem.bind('change', changeFn);\n        fileElem.bind('click', ie10SameFileSelectFix);\n        fileElem[0].click();\n        return false;\n      } else {\n        fileElem.removeAttr('__ngf_ie10_Fix_');\n      }\n    }\n\n    if (navigator.appVersion.indexOf('MSIE 10') !== -1) {\n      fileElem.bind('click', ie10SameFileSelectFix);\n    }\n\n    if (ngModel) ngModel.$formatters.push(function (val) {\n      if (val == null || val.length === 0) {\n        if (fileElem.val()) {\n          fileElem.val(null);\n        }\n      }\n      return val;\n    });\n\n    scope.$on('$destroy', function () {\n      if (!isInputTypeFile()) fileElem.parent().remove();\n      angular.forEach(unwatches, function (unwatch) {\n        unwatch();\n      });\n    });\n\n    $timeout(function () {\n      for (var i = 0; i < generatedElems.length; i++) {\n        var g = generatedElems[i];\n        if (!document.body.contains(g.el[0])) {\n          generatedElems.splice(i, 1);\n          g.ref.remove();\n        }\n      }\n    });\n\n    if (window.FileAPI && window.FileAPI.ngfFixIE) {\n      window.FileAPI.ngfFixIE(elem, fileElem, changeFn);\n    }\n  }\n\n  return {\n    restrict: 'AEC',\n    require: '?ngModel',\n    link: function (scope, elem, attr, ngModel) {\n      linkFileSelect(scope, elem, attr, ngModel, $parse, $timeout, $compile, Upload);\n    }\n  };\n}]);\n\n(function () {\n\n  ngFileUpload.service('UploadDataUrl', ['UploadBase', '$timeout', '$q', function (UploadBase, $timeout, $q) {\n    var upload = UploadBase;\n    upload.base64DataUrl = function (file) {\n      if (angular.isArray(file)) {\n        var d = $q.defer(), count = 0;\n        angular.forEach(file, function (f) {\n          upload.dataUrl(f, true)['finally'](function () {\n            count++;\n            if (count === file.length) {\n              var urls = [];\n              angular.forEach(file, function (ff) {\n                urls.push(ff.$ngfDataUrl);\n              });\n              d.resolve(urls, file);\n            }\n          });\n        });\n        return d.promise;\n      } else {\n        return upload.dataUrl(file, true);\n      }\n    };\n    upload.dataUrl = function (file, disallowObjectUrl) {\n      if (!file) return upload.emptyPromise(file, file);\n      if ((disallowObjectUrl && file.$ngfDataUrl != null) || (!disallowObjectUrl && file.$ngfBlobUrl != null)) {\n        return upload.emptyPromise(disallowObjectUrl ? file.$ngfDataUrl : file.$ngfBlobUrl, file);\n      }\n      var p = disallowObjectUrl ? file.$$ngfDataUrlPromise : file.$$ngfBlobUrlPromise;\n      if (p) return p;\n\n      var deferred = $q.defer();\n      $timeout(function () {\n        if (window.FileReader && file &&\n          (!window.FileAPI || navigator.userAgent.indexOf('MSIE 8') === -1 || file.size < 20000) &&\n          (!window.FileAPI || navigator.userAgent.indexOf('MSIE 9') === -1 || file.size < 4000000)) {\n          //prefer URL.createObjectURL for handling refrences to files of all sizes\n          //since it doesn´t build a large string in memory\n          var URL = window.URL || window.webkitURL;\n          if (URL && URL.createObjectURL && !disallowObjectUrl) {\n            var url;\n            try {\n              url = URL.createObjectURL(file);\n            } catch (e) {\n              $timeout(function () {\n                file.$ngfBlobUrl = '';\n                deferred.reject();\n              });\n              return;\n            }\n            $timeout(function () {\n              file.$ngfBlobUrl = url;\n              if (url) {\n                deferred.resolve(url, file);\n                upload.blobUrls = upload.blobUrls || [];\n                upload.blobUrlsTotalSize = upload.blobUrlsTotalSize || 0;\n                upload.blobUrls.push({url: url, size: file.size});\n                upload.blobUrlsTotalSize += file.size || 0;\n                var maxMemory = upload.defaults.blobUrlsMaxMemory || 268435456;\n                var maxLength = upload.defaults.blobUrlsMaxQueueSize || 200;\n                while ((upload.blobUrlsTotalSize > maxMemory || upload.blobUrls.length > maxLength) && upload.blobUrls.length > 1) {\n                  var obj = upload.blobUrls.splice(0, 1)[0];\n                  URL.revokeObjectURL(obj.url);\n                  upload.blobUrlsTotalSize -= obj.size;\n                }\n              }\n            });\n          } else {\n            var fileReader = new FileReader();\n            fileReader.onload = function (e) {\n              $timeout(function () {\n                file.$ngfDataUrl = e.target.result;\n                deferred.resolve(e.target.result, file);\n                $timeout(function () {\n                  delete file.$ngfDataUrl;\n                }, 1000);\n              });\n            };\n            fileReader.onerror = function () {\n              $timeout(function () {\n                file.$ngfDataUrl = '';\n                deferred.reject();\n              });\n            };\n            fileReader.readAsDataURL(file);\n          }\n        } else {\n          $timeout(function () {\n            file[disallowObjectUrl ? '$ngfDataUrl' : '$ngfBlobUrl'] = '';\n            deferred.reject();\n          });\n        }\n      });\n\n      if (disallowObjectUrl) {\n        p = file.$$ngfDataUrlPromise = deferred.promise;\n      } else {\n        p = file.$$ngfBlobUrlPromise = deferred.promise;\n      }\n      p['finally'](function () {\n        delete file[disallowObjectUrl ? '$$ngfDataUrlPromise' : '$$ngfBlobUrlPromise'];\n      });\n      return p;\n    };\n    return upload;\n  }]);\n\n  function getTagType(el) {\n    if (el.tagName.toLowerCase() === 'img') return 'image';\n    if (el.tagName.toLowerCase() === 'audio') return 'audio';\n    if (el.tagName.toLowerCase() === 'video') return 'video';\n    return /./;\n  }\n\n  function linkFileDirective(Upload, $timeout, scope, elem, attr, directiveName, resizeParams, isBackground) {\n    function constructDataUrl(file) {\n      var disallowObjectUrl = Upload.attrGetter('ngfNoObjectUrl', attr, scope);\n      Upload.dataUrl(file, disallowObjectUrl)['finally'](function () {\n        $timeout(function () {\n          var src = (disallowObjectUrl ? file.$ngfDataUrl : file.$ngfBlobUrl) || file.$ngfDataUrl;\n          if (isBackground) {\n            elem.css('background-image', 'url(\\'' + (src || '') + '\\')');\n          } else {\n            elem.attr('src', src);\n          }\n          if (src) {\n            elem.removeClass('ng-hide');\n          } else {\n            elem.addClass('ng-hide');\n          }\n        });\n      });\n    }\n\n    $timeout(function () {\n      var unwatch = scope.$watch(attr[directiveName], function (file) {\n        var size = resizeParams;\n        if (directiveName === 'ngfThumbnail') {\n          if (!size) {\n            size = {\n              width: elem[0].naturalWidth || elem[0].clientWidth,\n              height: elem[0].naturalHeight || elem[0].clientHeight\n            };\n          }\n          if (size.width === 0 && window.getComputedStyle) {\n            var style = getComputedStyle(elem[0]);\n            if (style.width && style.width.indexOf('px') > -1 && style.height && style.height.indexOf('px') > -1) {\n              size = {\n                width: parseInt(style.width.slice(0, -2)),\n                height: parseInt(style.height.slice(0, -2))\n              };\n            }\n          }\n        }\n\n        if (angular.isString(file)) {\n          elem.removeClass('ng-hide');\n          if (isBackground) {\n            return elem.css('background-image', 'url(\\'' + file + '\\')');\n          } else {\n            return elem.attr('src', file);\n          }\n        }\n        if (file && file.type && file.type.search(getTagType(elem[0])) === 0 &&\n          (!isBackground || file.type.indexOf('image') === 0)) {\n          if (size && Upload.isResizeSupported()) {\n            size.resizeIf = function (width, height) {\n              return Upload.attrGetter('ngfResizeIf', attr, scope,\n                {$width: width, $height: height, $file: file});\n            };\n            Upload.resize(file, size).then(\n              function (f) {\n                constructDataUrl(f);\n              }, function (e) {\n                throw e;\n              }\n            );\n          } else {\n            constructDataUrl(file);\n          }\n        } else {\n          elem.addClass('ng-hide');\n        }\n      });\n\n      scope.$on('$destroy', function () {\n        unwatch();\n      });\n    });\n  }\n\n\n  /** @namespace attr.ngfSrc */\n  /** @namespace attr.ngfNoObjectUrl */\n  ngFileUpload.directive('ngfSrc', ['Upload', '$timeout', function (Upload, $timeout) {\n    return {\n      restrict: 'AE',\n      link: function (scope, elem, attr) {\n        linkFileDirective(Upload, $timeout, scope, elem, attr, 'ngfSrc',\n          Upload.attrGetter('ngfResize', attr, scope), false);\n      }\n    };\n  }]);\n\n  /** @namespace attr.ngfBackground */\n  /** @namespace attr.ngfNoObjectUrl */\n  ngFileUpload.directive('ngfBackground', ['Upload', '$timeout', function (Upload, $timeout) {\n    return {\n      restrict: 'AE',\n      link: function (scope, elem, attr) {\n        linkFileDirective(Upload, $timeout, scope, elem, attr, 'ngfBackground',\n          Upload.attrGetter('ngfResize', attr, scope), true);\n      }\n    };\n  }]);\n\n  /** @namespace attr.ngfThumbnail */\n  /** @namespace attr.ngfAsBackground */\n  /** @namespace attr.ngfSize */\n  /** @namespace attr.ngfNoObjectUrl */\n  ngFileUpload.directive('ngfThumbnail', ['Upload', '$timeout', function (Upload, $timeout) {\n    return {\n      restrict: 'AE',\n      link: function (scope, elem, attr) {\n        var size = Upload.attrGetter('ngfSize', attr, scope);\n        linkFileDirective(Upload, $timeout, scope, elem, attr, 'ngfThumbnail', size,\n          Upload.attrGetter('ngfAsBackground', attr, scope));\n      }\n    };\n  }]);\n\n  ngFileUpload.config(['$compileProvider', function ($compileProvider) {\n    if ($compileProvider.imgSrcSanitizationWhitelist) $compileProvider.imgSrcSanitizationWhitelist(/^\\s*(https?|ftp|mailto|tel|webcal|local|file|data|blob):/);\n    if ($compileProvider.aHrefSanitizationWhitelist) $compileProvider.aHrefSanitizationWhitelist(/^\\s*(https?|ftp|mailto|tel|webcal|local|file|data|blob):/);\n  }]);\n\n  ngFileUpload.filter('ngfDataUrl', ['UploadDataUrl', '$sce', function (UploadDataUrl, $sce) {\n    return function (file, disallowObjectUrl, trustedUrl) {\n      if (angular.isString(file)) {\n        return $sce.trustAsResourceUrl(file);\n      }\n      var src = file && ((disallowObjectUrl ? file.$ngfDataUrl : file.$ngfBlobUrl) || file.$ngfDataUrl);\n      if (file && !src) {\n        if (!file.$ngfDataUrlFilterInProgress && angular.isObject(file)) {\n          file.$ngfDataUrlFilterInProgress = true;\n          UploadDataUrl.dataUrl(file, disallowObjectUrl);\n        }\n        return '';\n      }\n      if (file) delete file.$ngfDataUrlFilterInProgress;\n      return (file && src ? (trustedUrl ? $sce.trustAsResourceUrl(src) : src) : file) || '';\n    };\n  }]);\n\n})();\n\nngFileUpload.service('UploadValidate', ['UploadDataUrl', '$q', '$timeout', function (UploadDataUrl, $q, $timeout) {\n  var upload = UploadDataUrl;\n\n  function globStringToRegex(str) {\n    var regexp = '', excludes = [];\n    if (str.length > 2 && str[0] === '/' && str[str.length - 1] === '/') {\n      regexp = str.substring(1, str.length - 1);\n    } else {\n      var split = str.split(',');\n      if (split.length > 1) {\n        for (var i = 0; i < split.length; i++) {\n          var r = globStringToRegex(split[i]);\n          if (r.regexp) {\n            regexp += '(' + r.regexp + ')';\n            if (i < split.length - 1) {\n              regexp += '|';\n            }\n          } else {\n            excludes = excludes.concat(r.excludes);\n          }\n        }\n      } else {\n        if (str.indexOf('!') === 0) {\n          excludes.push('^((?!' + globStringToRegex(str.substring(1)).regexp + ').)*$');\n        } else {\n          if (str.indexOf('.') === 0) {\n            str = '*' + str;\n          }\n          regexp = '^' + str.replace(new RegExp('[.\\\\\\\\+*?\\\\[\\\\^\\\\]$(){}=!<>|:\\\\-]', 'g'), '\\\\$&') + '$';\n          regexp = regexp.replace(/\\\\\\*/g, '.*').replace(/\\\\\\?/g, '.');\n        }\n      }\n    }\n    return {regexp: regexp, excludes: excludes};\n  }\n\n  upload.validatePattern = function (file, val) {\n    if (!val) {\n      return true;\n    }\n    var pattern = globStringToRegex(val), valid = true;\n    if (pattern.regexp && pattern.regexp.length) {\n      var regexp = new RegExp(pattern.regexp, 'i');\n      valid = (file.type != null && regexp.test(file.type)) ||\n        (file.name != null && regexp.test(file.name));\n    }\n    var len = pattern.excludes.length;\n    while (len--) {\n      var exclude = new RegExp(pattern.excludes[len], 'i');\n      valid = valid && (file.type == null || exclude.test(file.type)) &&\n        (file.name == null || exclude.test(file.name));\n    }\n    return valid;\n  };\n\n  upload.ratioToFloat = function (val) {\n    var r = val.toString(), xIndex = r.search(/[x:]/i);\n    if (xIndex > -1) {\n      r = parseFloat(r.substring(0, xIndex)) / parseFloat(r.substring(xIndex + 1));\n    } else {\n      r = parseFloat(r);\n    }\n    return r;\n  };\n\n  upload.registerModelChangeValidator = function (ngModel, attr, scope) {\n    if (ngModel) {\n      ngModel.$formatters.push(function (files) {\n        if (ngModel.$dirty) {\n          var filesArray = files;\n          if (files && !angular.isArray(files)) {\n            filesArray = [files];\n          }\n          upload.validate(filesArray, 0, ngModel, attr, scope).then(function () {\n            upload.applyModelValidation(ngModel, filesArray);\n          });\n        }\n        return files;\n      });\n    }\n  };\n\n  function markModelAsDirty(ngModel, files) {\n    if (files != null && !ngModel.$dirty) {\n      if (ngModel.$setDirty) {\n        ngModel.$setDirty();\n      } else {\n        ngModel.$dirty = true;\n      }\n    }\n  }\n\n  upload.applyModelValidation = function (ngModel, files) {\n    markModelAsDirty(ngModel, files);\n    angular.forEach(ngModel.$ngfValidations, function (validation) {\n      ngModel.$setValidity(validation.name, validation.valid);\n    });\n  };\n\n  upload.getValidationAttr = function (attr, scope, name, validationName, file) {\n    var dName = 'ngf' + name[0].toUpperCase() + name.substr(1);\n    var val = upload.attrGetter(dName, attr, scope, {$file: file});\n    if (val == null) {\n      val = upload.attrGetter('ngfValidate', attr, scope, {$file: file});\n      if (val) {\n        var split = (validationName || name).split('.');\n        val = val[split[0]];\n        if (split.length > 1) {\n          val = val && val[split[1]];\n        }\n      }\n    }\n    return val;\n  };\n\n  upload.validate = function (files, prevLength, ngModel, attr, scope) {\n    ngModel = ngModel || {};\n    ngModel.$ngfValidations = ngModel.$ngfValidations || [];\n\n    angular.forEach(ngModel.$ngfValidations, function (v) {\n      v.valid = true;\n    });\n\n    var attrGetter = function (name, params) {\n      return upload.attrGetter(name, attr, scope, params);\n    };\n\n    var ignoredErrors = (upload.attrGetter('ngfIgnoreInvalid', attr, scope) || '').split(' ');\n    var runAllValidation = upload.attrGetter('ngfRunAllValidations', attr, scope);\n\n    if (files == null || files.length === 0) {\n      return upload.emptyPromise({'validFiles': files, 'invalidFiles': []});\n    }\n\n    files = files.length === undefined ? [files] : files.slice(0);\n    var invalidFiles = [];\n\n    function validateSync(name, validationName, fn) {\n      if (files) {\n        var i = files.length, valid = null;\n        while (i--) {\n          var file = files[i];\n          if (file) {\n            var val = upload.getValidationAttr(attr, scope, name, validationName, file);\n            if (val != null) {\n              if (!fn(file, val, i)) {\n                if (ignoredErrors.indexOf(name) === -1) {\n                  file.$error = name;\n                  (file.$errorMessages = (file.$errorMessages || {}))[name] = true;\n                  file.$errorParam = val;\n                  if (invalidFiles.indexOf(file) === -1) {\n                    invalidFiles.push(file);\n                  }\n                  if (!runAllValidation) {\n                    files.splice(i, 1);\n                  }\n                  valid = false;\n                } else {\n                  files.splice(i, 1);\n                }\n              }\n            }\n          }\n        }\n        if (valid !== null) {\n          ngModel.$ngfValidations.push({name: name, valid: valid});\n        }\n      }\n    }\n\n    validateSync('pattern', null, upload.validatePattern);\n    validateSync('minSize', 'size.min', function (file, val) {\n      return file.size + 0.1 >= upload.translateScalars(val);\n    });\n    validateSync('maxSize', 'size.max', function (file, val) {\n      return file.size - 0.1 <= upload.translateScalars(val);\n    });\n    var totalSize = 0;\n    validateSync('maxTotalSize', null, function (file, val) {\n      totalSize += file.size;\n      if (totalSize > upload.translateScalars(val)) {\n        files.splice(0, files.length);\n        return false;\n      }\n      return true;\n    });\n\n    validateSync('validateFn', null, function (file, r) {\n      return r === true || r === null || r === '';\n    });\n\n    if (!files.length) {\n      return upload.emptyPromise({'validFiles': [], 'invalidFiles': invalidFiles});\n    }\n\n    function validateAsync(name, validationName, type, asyncFn, fn) {\n      function resolveResult(defer, file, val) {\n        function resolveInternal(fn) {\n          if (fn()) {\n            if (ignoredErrors.indexOf(name) === -1) {\n              file.$error = name;\n              (file.$errorMessages = (file.$errorMessages || {}))[name] = true;\n              file.$errorParam = val;\n              if (invalidFiles.indexOf(file) === -1) {\n                invalidFiles.push(file);\n              }\n              if (!runAllValidation) {\n                var i = files.indexOf(file);\n                if (i > -1) files.splice(i, 1);\n              }\n              defer.resolve(false);\n            } else {\n              var j = files.indexOf(file);\n              if (j > -1) files.splice(j, 1);\n              defer.resolve(true);\n            }\n          } else {\n            defer.resolve(true);\n          }\n        }\n\n        if (val != null) {\n          asyncFn(file, val).then(function (d) {\n            resolveInternal(function () {\n              return !fn(d, val);\n            });\n          }, function () {\n            resolveInternal(function () {\n              return attrGetter('ngfValidateForce', {$file: file});\n            });\n          });\n        } else {\n          defer.resolve(true);\n        }\n      }\n\n      var promises = [upload.emptyPromise(true)];\n      if (files) {\n        files = files.length === undefined ? [files] : files;\n        angular.forEach(files, function (file) {\n          var defer = $q.defer();\n          promises.push(defer.promise);\n          if (type && (file.type == null || file.type.search(type) !== 0)) {\n            defer.resolve(true);\n            return;\n          }\n          if (name === 'dimensions' && upload.attrGetter('ngfDimensions', attr) != null) {\n            upload.imageDimensions(file).then(function (d) {\n              resolveResult(defer, file,\n                attrGetter('ngfDimensions', {$file: file, $width: d.width, $height: d.height}));\n            }, function () {\n              defer.resolve(false);\n            });\n          } else if (name === 'duration' && upload.attrGetter('ngfDuration', attr) != null) {\n            upload.mediaDuration(file).then(function (d) {\n              resolveResult(defer, file,\n                attrGetter('ngfDuration', {$file: file, $duration: d}));\n            }, function () {\n              defer.resolve(false);\n            });\n          } else {\n            resolveResult(defer, file,\n              upload.getValidationAttr(attr, scope, name, validationName, file));\n          }\n        });\n      }\n      var deffer = $q.defer();\n      $q.all(promises).then(function (values) {\n        var isValid = true;\n        for (var i = 0; i < values.length; i++) {\n          if (!values[i]) {\n            isValid = false;\n            break;\n          }\n        }\n        ngModel.$ngfValidations.push({name: name, valid: isValid});\n        deffer.resolve(isValid);\n      });\n      return deffer.promise;\n    }\n\n    var deffer = $q.defer();\n    var promises = [];\n\n    promises.push(validateAsync('maxHeight', 'height.max', /image/,\n      this.imageDimensions, function (d, val) {\n        return d.height <= val;\n      }));\n    promises.push(validateAsync('minHeight', 'height.min', /image/,\n      this.imageDimensions, function (d, val) {\n        return d.height >= val;\n      }));\n    promises.push(validateAsync('maxWidth', 'width.max', /image/,\n      this.imageDimensions, function (d, val) {\n        return d.width <= val;\n      }));\n    promises.push(validateAsync('minWidth', 'width.min', /image/,\n      this.imageDimensions, function (d, val) {\n        return d.width >= val;\n      }));\n    promises.push(validateAsync('dimensions', null, /image/,\n      function (file, val) {\n        return upload.emptyPromise(val);\n      }, function (r) {\n        return r;\n      }));\n    promises.push(validateAsync('ratio', null, /image/,\n      this.imageDimensions, function (d, val) {\n        var split = val.toString().split(','), valid = false;\n        for (var i = 0; i < split.length; i++) {\n          if (Math.abs((d.width / d.height) - upload.ratioToFloat(split[i])) < 0.01) {\n            valid = true;\n          }\n        }\n        return valid;\n      }));\n    promises.push(validateAsync('maxRatio', 'ratio.max', /image/,\n      this.imageDimensions, function (d, val) {\n        return (d.width / d.height) - upload.ratioToFloat(val) < 0.0001;\n      }));\n    promises.push(validateAsync('minRatio', 'ratio.min', /image/,\n      this.imageDimensions, function (d, val) {\n        return (d.width / d.height) - upload.ratioToFloat(val) > -0.0001;\n      }));\n    promises.push(validateAsync('maxDuration', 'duration.max', /audio|video/,\n      this.mediaDuration, function (d, val) {\n        return d <= upload.translateScalars(val);\n      }));\n    promises.push(validateAsync('minDuration', 'duration.min', /audio|video/,\n      this.mediaDuration, function (d, val) {\n        return d >= upload.translateScalars(val);\n      }));\n    promises.push(validateAsync('duration', null, /audio|video/,\n      function (file, val) {\n        return upload.emptyPromise(val);\n      }, function (r) {\n        return r;\n      }));\n\n    promises.push(validateAsync('validateAsyncFn', null, null,\n      function (file, val) {\n        return val;\n      }, function (r) {\n        return r === true || r === null || r === '';\n      }));\n\n    $q.all(promises).then(function () {\n\n      if (runAllValidation) {\n        for (var i = 0; i < files.length; i++) {\n          var file = files[i];\n          if (file.$error) {\n            files.splice(i--, 1);\n          }\n        }\n      }\n\n      runAllValidation = false;\n      validateSync('maxFiles', null, function (file, val, i) {\n        return prevLength + i < val;\n      });\n\n      deffer.resolve({'validFiles': files, 'invalidFiles': invalidFiles});\n    });\n    return deffer.promise;\n  };\n\n  upload.imageDimensions = function (file) {\n    if (file.$ngfWidth && file.$ngfHeight) {\n      var d = $q.defer();\n      $timeout(function () {\n        d.resolve({width: file.$ngfWidth, height: file.$ngfHeight});\n      });\n      return d.promise;\n    }\n    if (file.$ngfDimensionPromise) return file.$ngfDimensionPromise;\n\n    var deferred = $q.defer();\n    $timeout(function () {\n      if (file.type.indexOf('image') !== 0) {\n        deferred.reject('not image');\n        return;\n      }\n      upload.dataUrl(file).then(function (dataUrl) {\n        var img = angular.element('<img>').attr('src', dataUrl)\n          .css('visibility', 'hidden').css('position', 'fixed')\n          .css('max-width', 'none !important').css('max-height', 'none !important');\n\n        function success() {\n          var width = img[0].naturalWidth || img[0].clientWidth;\n          var height = img[0].naturalHeight || img[0].clientHeight;\n          img.remove();\n          file.$ngfWidth = width;\n          file.$ngfHeight = height;\n          deferred.resolve({width: width, height: height});\n        }\n\n        function error() {\n          img.remove();\n          deferred.reject('load error');\n        }\n\n        img.on('load', success);\n        img.on('error', error);\n\n        var secondsCounter = 0;\n        function checkLoadErrorInCaseOfNoCallback() {\n          $timeout(function () {\n            if (img[0].parentNode) {\n              if (img[0].clientWidth) {\n                success();\n              } else if (secondsCounter++ > 10) {\n                error();\n              } else {\n                checkLoadErrorInCaseOfNoCallback();\n              }\n            }\n          }, 1000);\n        }\n\n        checkLoadErrorInCaseOfNoCallback();\n\n        angular.element(document.getElementsByTagName('body')[0]).append(img);\n      }, function () {\n        deferred.reject('load error');\n      });\n    });\n\n    file.$ngfDimensionPromise = deferred.promise;\n    file.$ngfDimensionPromise['finally'](function () {\n      delete file.$ngfDimensionPromise;\n    });\n    return file.$ngfDimensionPromise;\n  };\n\n  upload.mediaDuration = function (file) {\n    if (file.$ngfDuration) {\n      var d = $q.defer();\n      $timeout(function () {\n        d.resolve(file.$ngfDuration);\n      });\n      return d.promise;\n    }\n    if (file.$ngfDurationPromise) return file.$ngfDurationPromise;\n\n    var deferred = $q.defer();\n    $timeout(function () {\n      if (file.type.indexOf('audio') !== 0 && file.type.indexOf('video') !== 0) {\n        deferred.reject('not media');\n        return;\n      }\n      upload.dataUrl(file).then(function (dataUrl) {\n        var el = angular.element(file.type.indexOf('audio') === 0 ? '<audio>' : '<video>')\n          .attr('src', dataUrl).css('visibility', 'none').css('position', 'fixed');\n\n        function success() {\n          var duration = el[0].duration;\n          file.$ngfDuration = duration;\n          el.remove();\n          deferred.resolve(duration);\n        }\n\n        function error() {\n          el.remove();\n          deferred.reject('load error');\n        }\n\n        el.on('loadedmetadata', success);\n        el.on('error', error);\n        var count = 0;\n\n        function checkLoadError() {\n          $timeout(function () {\n            if (el[0].parentNode) {\n              if (el[0].duration) {\n                success();\n              } else if (count > 10) {\n                error();\n              } else {\n                checkLoadError();\n              }\n            }\n          }, 1000);\n        }\n\n        checkLoadError();\n\n        angular.element(document.body).append(el);\n      }, function () {\n        deferred.reject('load error');\n      });\n    });\n\n    file.$ngfDurationPromise = deferred.promise;\n    file.$ngfDurationPromise['finally'](function () {\n      delete file.$ngfDurationPromise;\n    });\n    return file.$ngfDurationPromise;\n  };\n  return upload;\n}\n]);\n\nngFileUpload.service('UploadResize', ['UploadValidate', '$q', function (UploadValidate, $q) {\n  var upload = UploadValidate;\n\n  /**\n   * Conserve aspect ratio of the original region. Useful when shrinking/enlarging\n   * images to fit into a certain area.\n   * Source:  http://stackoverflow.com/a/14731922\n   *\n   * @param {Number} srcWidth Source area width\n   * @param {Number} srcHeight Source area height\n   * @param {Number} maxWidth Nestable area maximum available width\n   * @param {Number} maxHeight Nestable area maximum available height\n   * @return {Object} { width, height }\n   */\n  var calculateAspectRatioFit = function (srcWidth, srcHeight, maxWidth, maxHeight, centerCrop) {\n    var ratio = centerCrop ? Math.max(maxWidth / srcWidth, maxHeight / srcHeight) :\n      Math.min(maxWidth / srcWidth, maxHeight / srcHeight);\n    return {\n      width: srcWidth * ratio, height: srcHeight * ratio,\n      marginX: srcWidth * ratio - maxWidth, marginY: srcHeight * ratio - maxHeight\n    };\n  };\n\n  // Extracted from https://github.com/romelgomez/angular-firebase-image-upload/blob/master/app/scripts/fileUpload.js#L89\n  var resize = function (imagen, width, height, quality, type, ratio, centerCrop, resizeIf) {\n    var deferred = $q.defer();\n    var canvasElement = document.createElement('canvas');\n    var imageElement = document.createElement('img');\n    imageElement.setAttribute('style', 'visibility:hidden;position:fixed;z-index:-100000');\n    document.body.appendChild(imageElement);\n\n    imageElement.onload = function () {\n      var imgWidth = imageElement.width, imgHeight = imageElement.height;\n      imageElement.parentNode.removeChild(imageElement);\n      if (resizeIf != null && resizeIf(imgWidth, imgHeight) === false) {\n        deferred.reject('resizeIf');\n        return;\n      }\n      try {\n        if (ratio) {\n          var ratioFloat = upload.ratioToFloat(ratio);\n          var imgRatio = imgWidth / imgHeight;\n          if (imgRatio < ratioFloat) {\n            width = imgWidth;\n            height = width / ratioFloat;\n          } else {\n            height = imgHeight;\n            width = height * ratioFloat;\n          }\n        }\n        if (!width) {\n          width = imgWidth;\n        }\n        if (!height) {\n          height = imgHeight;\n        }\n        var dimensions = calculateAspectRatioFit(imgWidth, imgHeight, width, height, centerCrop);\n        canvasElement.width = Math.min(dimensions.width, width);\n        canvasElement.height = Math.min(dimensions.height, height);\n        var context = canvasElement.getContext('2d');\n        context.drawImage(imageElement,\n          Math.min(0, -dimensions.marginX / 2), Math.min(0, -dimensions.marginY / 2),\n          dimensions.width, dimensions.height);\n        deferred.resolve(canvasElement.toDataURL(type || 'image/WebP', quality || 0.934));\n      } catch (e) {\n        deferred.reject(e);\n      }\n    };\n    imageElement.onerror = function () {\n      imageElement.parentNode.removeChild(imageElement);\n      deferred.reject();\n    };\n    imageElement.src = imagen;\n    return deferred.promise;\n  };\n\n  upload.dataUrltoBlob = function (dataurl, name, origSize) {\n    var arr = dataurl.split(','), mime = arr[0].match(/:(.*?);/)[1],\n      bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n);\n    while (n--) {\n      u8arr[n] = bstr.charCodeAt(n);\n    }\n    var blob = new window.Blob([u8arr], {type: mime});\n    blob.name = name;\n    blob.$ngfOrigSize = origSize;\n    return blob;\n  };\n\n  upload.isResizeSupported = function () {\n    var elem = document.createElement('canvas');\n    return window.atob && elem.getContext && elem.getContext('2d') && window.Blob;\n  };\n\n  if (upload.isResizeSupported()) {\n    // add name getter to the blob constructor prototype\n    Object.defineProperty(window.Blob.prototype, 'name', {\n      get: function () {\n        return this.$ngfName;\n      },\n      set: function (v) {\n        this.$ngfName = v;\n      },\n      configurable: true\n    });\n  }\n\n  upload.resize = function (file, options) {\n    if (file.type.indexOf('image') !== 0) return upload.emptyPromise(file);\n\n    var deferred = $q.defer();\n    upload.dataUrl(file, true).then(function (url) {\n      resize(url, options.width, options.height, options.quality, options.type || file.type,\n        options.ratio, options.centerCrop, options.resizeIf)\n        .then(function (dataUrl) {\n          if (file.type === 'image/jpeg' && options.restoreExif !== false) {\n            try {\n              dataUrl = upload.restoreExif(url, dataUrl);\n            } catch (e) {\n              setTimeout(function () {throw e;}, 1);\n            }\n          }\n          try {\n            var blob = upload.dataUrltoBlob(dataUrl, file.name, file.size);\n            deferred.resolve(blob);\n          } catch (e) {\n            deferred.reject(e);\n          }\n        }, function (r) {\n          if (r === 'resizeIf') {\n            deferred.resolve(file);\n          }\n          deferred.reject(r);\n        });\n    }, function (e) {\n      deferred.reject(e);\n    });\n    return deferred.promise;\n  };\n\n  return upload;\n}]);\n\n(function () {\n  ngFileUpload.directive('ngfDrop', ['$parse', '$timeout', '$window', 'Upload', '$http', '$q',\n    function ($parse, $timeout, $window, Upload, $http, $q) {\n      return {\n        restrict: 'AEC',\n        require: '?ngModel',\n        link: function (scope, elem, attr, ngModel) {\n          linkDrop(scope, elem, attr, ngModel, $parse, $timeout, $window, Upload, $http, $q);\n        }\n      };\n    }]);\n\n  ngFileUpload.directive('ngfNoFileDrop', function () {\n    return function (scope, elem) {\n      if (dropAvailable()) elem.css('display', 'none');\n    };\n  });\n\n  ngFileUpload.directive('ngfDropAvailable', ['$parse', '$timeout', 'Upload', function ($parse, $timeout, Upload) {\n    return function (scope, elem, attr) {\n      if (dropAvailable()) {\n        var model = $parse(Upload.attrGetter('ngfDropAvailable', attr));\n        $timeout(function () {\n          model(scope);\n          if (model.assign) {\n            model.assign(scope, true);\n          }\n        });\n      }\n    };\n  }]);\n\n  function linkDrop(scope, elem, attr, ngModel, $parse, $timeout, $window, upload, $http, $q) {\n    var available = dropAvailable();\n\n    var attrGetter = function (name, scope, params) {\n      return upload.attrGetter(name, attr, scope, params);\n    };\n\n    if (attrGetter('dropAvailable')) {\n      $timeout(function () {\n        if (scope[attrGetter('dropAvailable')]) {\n          scope[attrGetter('dropAvailable')].value = available;\n        } else {\n          scope[attrGetter('dropAvailable')] = available;\n        }\n      });\n    }\n    if (!available) {\n      if (attrGetter('ngfHideOnDropNotAvailable', scope) === true) {\n        elem.css('display', 'none');\n      }\n      return;\n    }\n\n    function isDisabled() {\n      return elem.attr('disabled') || attrGetter('ngfDropDisabled', scope);\n    }\n\n    if (attrGetter('ngfSelect') == null) {\n      upload.registerModelChangeValidator(ngModel, attr, scope);\n    }\n\n    var leaveTimeout = null;\n    var stopPropagation = $parse(attrGetter('ngfStopPropagation'));\n    var dragOverDelay = 1;\n    var actualDragOverClass;\n\n    elem[0].addEventListener('dragover', function (evt) {\n      if (isDisabled() || !upload.shouldUpdateOn('drop', attr, scope)) return;\n      evt.preventDefault();\n      if (stopPropagation(scope)) evt.stopPropagation();\n      // handling dragover events from the Chrome download bar\n      if (navigator.userAgent.indexOf('Chrome') > -1) {\n        var b = evt.dataTransfer.effectAllowed;\n        evt.dataTransfer.dropEffect = ('move' === b || 'linkMove' === b) ? 'move' : 'copy';\n      }\n      $timeout.cancel(leaveTimeout);\n      if (!actualDragOverClass) {\n        actualDragOverClass = 'C';\n        calculateDragOverClass(scope, attr, evt, function (clazz) {\n          actualDragOverClass = clazz;\n          elem.addClass(actualDragOverClass);\n          attrGetter('ngfDrag', scope, {$isDragging: true, $class: actualDragOverClass, $event: evt});\n        });\n      }\n    }, false);\n    elem[0].addEventListener('dragenter', function (evt) {\n      if (isDisabled() || !upload.shouldUpdateOn('drop', attr, scope)) return;\n      evt.preventDefault();\n      if (stopPropagation(scope)) evt.stopPropagation();\n    }, false);\n    elem[0].addEventListener('dragleave', function (evt) {\n      if (isDisabled() || !upload.shouldUpdateOn('drop', attr, scope)) return;\n      evt.preventDefault();\n      if (stopPropagation(scope)) evt.stopPropagation();\n      leaveTimeout = $timeout(function () {\n        if (actualDragOverClass) elem.removeClass(actualDragOverClass);\n        actualDragOverClass = null;\n        attrGetter('ngfDrag', scope, {$isDragging: false, $event: evt});\n      }, dragOverDelay || 100);\n    }, false);\n    elem[0].addEventListener('drop', function (evt) {\n      if (isDisabled() || !upload.shouldUpdateOn('drop', attr, scope)) return;\n      evt.preventDefault();\n      if (stopPropagation(scope)) evt.stopPropagation();\n      if (actualDragOverClass) elem.removeClass(actualDragOverClass);\n      actualDragOverClass = null;\n      extractFilesAndUpdateModel(evt.dataTransfer, evt, 'dropUrl');\n    }, false);\n    elem[0].addEventListener('paste', function (evt) {\n      if (navigator.userAgent.toLowerCase().indexOf('firefox') > -1 &&\n        attrGetter('ngfEnableFirefoxPaste', scope)) {\n        evt.preventDefault();\n      }\n      if (isDisabled() || !upload.shouldUpdateOn('paste', attr, scope)) return;\n      extractFilesAndUpdateModel(evt.clipboardData || evt.originalEvent.clipboardData, evt, 'pasteUrl');\n    }, false);\n\n    if (navigator.userAgent.toLowerCase().indexOf('firefox') > -1 &&\n      attrGetter('ngfEnableFirefoxPaste', scope)) {\n      elem.attr('contenteditable', true);\n      elem.on('keypress', function (e) {\n        if (!e.metaKey && !e.ctrlKey) {\n          e.preventDefault();\n        }\n      });\n    }\n\n    function extractFilesAndUpdateModel(source, evt, updateOnType) {\n      if (!source) return;\n      // html needs to be calculated on the same process otherwise the data will be wiped\n      // after promise resolve or setTimeout.\n      var html;\n      try {\n        html = source && source.getData && source.getData('text/html');\n      } catch (e) {/* Fix IE11 that throw error calling getData */\n      }\n      extractFiles(source.items, source.files, attrGetter('ngfAllowDir', scope) !== false,\n        attrGetter('multiple') || attrGetter('ngfMultiple', scope)).then(function (files) {\n        if (files.length) {\n          updateModel(files, evt);\n        } else {\n          extractFilesFromHtml(updateOnType, html).then(function (files) {\n            updateModel(files, evt);\n          });\n        }\n      });\n    }\n\n    function updateModel(files, evt) {\n      upload.updateModel(ngModel, attr, scope, attrGetter('ngfChange') || attrGetter('ngfDrop'), files, evt);\n    }\n\n    function extractFilesFromHtml(updateOn, html) {\n      if (!upload.shouldUpdateOn(updateOn, attr, scope) || typeof html !== 'string') return upload.rejectPromise([]);\n      var urls = [];\n      html.replace(/<(img src|img [^>]* src) *=\\\"([^\\\"]*)\\\"/gi, function (m, n, src) {\n        urls.push(src);\n      });\n      var promises = [], files = [];\n      if (urls.length) {\n        angular.forEach(urls, function (url) {\n          promises.push(upload.urlToBlob(url).then(function (blob) {\n            files.push(blob);\n          }));\n        });\n        var defer = $q.defer();\n        $q.all(promises).then(function () {\n          defer.resolve(files);\n        }, function (e) {\n          defer.reject(e);\n        });\n        return defer.promise;\n      }\n      return upload.emptyPromise();\n    }\n\n    function calculateDragOverClass(scope, attr, evt, callback) {\n      var obj = attrGetter('ngfDragOverClass', scope, {$event: evt}), dClass = 'dragover';\n      if (angular.isString(obj)) {\n        dClass = obj;\n      } else if (obj) {\n        if (obj.delay) dragOverDelay = obj.delay;\n        if (obj.accept || obj.reject) {\n          var items = evt.dataTransfer.items;\n          if (items == null || !items.length) {\n            dClass = obj.accept;\n          } else {\n            var pattern = obj.pattern || attrGetter('ngfPattern', scope, {$event: evt});\n            var len = items.length;\n            while (len--) {\n              if (!upload.validatePattern(items[len], pattern)) {\n                dClass = obj.reject;\n                break;\n              } else {\n                dClass = obj.accept;\n              }\n            }\n          }\n        }\n      }\n      callback(dClass);\n    }\n\n    function extractFiles(items, fileList, allowDir, multiple) {\n      var maxFiles = upload.getValidationAttr(attr, scope, 'maxFiles');\n      if (maxFiles == null) {\n        maxFiles = Number.MAX_VALUE;\n      }\n      var maxTotalSize = upload.getValidationAttr(attr, scope, 'maxTotalSize');\n      if (maxTotalSize == null) {\n        maxTotalSize = Number.MAX_VALUE;\n      }\n      var includeDir = attrGetter('ngfIncludeDir', scope);\n      var files = [], totalSize = 0;\n\n      function traverseFileTree(entry, path) {\n        var defer = $q.defer();\n        if (entry != null) {\n          if (entry.isDirectory) {\n            var promises = [upload.emptyPromise()];\n            if (includeDir) {\n              var file = {type: 'directory'};\n              file.name = file.path = (path || '') + entry.name;\n              files.push(file);\n            }\n            var dirReader = entry.createReader();\n            var entries = [];\n            var readEntries = function () {\n              dirReader.readEntries(function (results) {\n                try {\n                  if (!results.length) {\n                    angular.forEach(entries.slice(0), function (e) {\n                      if (files.length <= maxFiles && totalSize <= maxTotalSize) {\n                        promises.push(traverseFileTree(e, (path ? path : '') + entry.name + '/'));\n                      }\n                    });\n                    $q.all(promises).then(function () {\n                      defer.resolve();\n                    }, function (e) {\n                      defer.reject(e);\n                    });\n                  } else {\n                    entries = entries.concat(Array.prototype.slice.call(results || [], 0));\n                    readEntries();\n                  }\n                } catch (e) {\n                  defer.reject(e);\n                }\n              }, function (e) {\n                defer.reject(e);\n              });\n            };\n            readEntries();\n          } else {\n            entry.file(function (file) {\n              try {\n                file.path = (path ? path : '') + file.name;\n                if (includeDir) {\n                  file = upload.rename(file, file.path);\n                }\n                files.push(file);\n                totalSize += file.size;\n                defer.resolve();\n              } catch (e) {\n                defer.reject(e);\n              }\n            }, function (e) {\n              defer.reject(e);\n            });\n          }\n        }\n        return defer.promise;\n      }\n\n      var promises = [upload.emptyPromise()];\n\n      if (items && items.length > 0 && $window.location.protocol !== 'file:') {\n        for (var i = 0; i < items.length; i++) {\n          if (items[i].webkitGetAsEntry && items[i].webkitGetAsEntry() && items[i].webkitGetAsEntry().isDirectory) {\n            var entry = items[i].webkitGetAsEntry();\n            if (entry.isDirectory && !allowDir) {\n              continue;\n            }\n            if (entry != null) {\n              promises.push(traverseFileTree(entry));\n            }\n          } else {\n            var f = items[i].getAsFile();\n            if (f != null) {\n              files.push(f);\n              totalSize += f.size;\n            }\n          }\n          if (files.length > maxFiles || totalSize > maxTotalSize ||\n            (!multiple && files.length > 0)) break;\n        }\n      } else {\n        if (fileList != null) {\n          for (var j = 0; j < fileList.length; j++) {\n            var file = fileList.item(j);\n            if (file.type || file.size > 0) {\n              files.push(file);\n              totalSize += file.size;\n            }\n            if (files.length > maxFiles || totalSize > maxTotalSize ||\n              (!multiple && files.length > 0)) break;\n          }\n        }\n      }\n\n      var defer = $q.defer();\n      $q.all(promises).then(function () {\n        if (!multiple && !includeDir && files.length) {\n          var i = 0;\n          while (files[i] && files[i].type === 'directory') i++;\n          defer.resolve([files[i]]);\n        } else {\n          defer.resolve(files);\n        }\n      }, function (e) {\n        defer.reject(e);\n      });\n\n      return defer.promise;\n    }\n  }\n\n  function dropAvailable() {\n    var div = document.createElement('div');\n    return ('draggable' in div) && ('ondrop' in div) && !/Edge\\/12./i.test(navigator.userAgent);\n  }\n\n})();\n\n// customized version of https://github.com/exif-js/exif-js\nngFileUpload.service('UploadExif', ['UploadResize', '$q', function (UploadResize, $q) {\n  var upload = UploadResize;\n\n  upload.isExifSupported = function () {\n    return window.FileReader && new FileReader().readAsArrayBuffer && upload.isResizeSupported();\n  };\n\n  function applyTransform(ctx, orientation, width, height) {\n    switch (orientation) {\n      case 2:\n        return ctx.transform(-1, 0, 0, 1, width, 0);\n      case 3:\n        return ctx.transform(-1, 0, 0, -1, width, height);\n      case 4:\n        return ctx.transform(1, 0, 0, -1, 0, height);\n      case 5:\n        return ctx.transform(0, 1, 1, 0, 0, 0);\n      case 6:\n        return ctx.transform(0, 1, -1, 0, height, 0);\n      case 7:\n        return ctx.transform(0, -1, -1, 0, height, width);\n      case 8:\n        return ctx.transform(0, -1, 1, 0, 0, width);\n    }\n  }\n\n  upload.readOrientation = function (file) {\n    var defer = $q.defer();\n    var reader = new FileReader();\n    var slicedFile = file.slice ? file.slice(0, 64 * 1024) : file;\n    reader.readAsArrayBuffer(slicedFile);\n    reader.onerror = function (e) {\n      return defer.reject(e);\n    };\n    reader.onload = function (e) {\n      var result = {orientation: 1};\n      var view = new DataView(this.result);\n      if (view.getUint16(0, false) !== 0xFFD8) return defer.resolve(result);\n\n      var length = view.byteLength,\n        offset = 2;\n      while (offset < length) {\n        var marker = view.getUint16(offset, false);\n        offset += 2;\n        if (marker === 0xFFE1) {\n          if (view.getUint32(offset += 2, false) !== 0x45786966) return defer.resolve(result);\n\n          var little = view.getUint16(offset += 6, false) === 0x4949;\n          offset += view.getUint32(offset + 4, little);\n          var tags = view.getUint16(offset, little);\n          offset += 2;\n          for (var i = 0; i < tags; i++)\n            if (view.getUint16(offset + (i * 12), little) === 0x0112) {\n              var orientation = view.getUint16(offset + (i * 12) + 8, little);\n              if (orientation >= 2 && orientation <= 8) {\n                view.setUint16(offset + (i * 12) + 8, 1, little);\n                result.fixedArrayBuffer = e.target.result;\n              }\n              result.orientation = orientation;\n              return defer.resolve(result);\n            }\n        } else if ((marker & 0xFF00) !== 0xFF00) break;\n        else offset += view.getUint16(offset, false);\n      }\n      return defer.resolve(result);\n    };\n    return defer.promise;\n  };\n\n  function arrayBufferToBase64(buffer) {\n    var binary = '';\n    var bytes = new Uint8Array(buffer);\n    var len = bytes.byteLength;\n    for (var i = 0; i < len; i++) {\n      binary += String.fromCharCode(bytes[i]);\n    }\n    return window.btoa(binary);\n  }\n\n  upload.applyExifRotation = function (file) {\n    if (file.type.indexOf('image/jpeg') !== 0) {\n      return upload.emptyPromise(file);\n    }\n\n    var deferred = $q.defer();\n    upload.readOrientation(file).then(function (result) {\n      if (result.orientation < 2 || result.orientation > 8) {\n        return deferred.resolve(file);\n      }\n      upload.dataUrl(file, true).then(function (url) {\n        var canvas = document.createElement('canvas');\n        var img = document.createElement('img');\n\n        img.onload = function () {\n          try {\n            canvas.width = result.orientation > 4 ? img.height : img.width;\n            canvas.height = result.orientation > 4 ? img.width : img.height;\n            var ctx = canvas.getContext('2d');\n            applyTransform(ctx, result.orientation, img.width, img.height);\n            ctx.drawImage(img, 0, 0);\n            var dataUrl = canvas.toDataURL(file.type || 'image/WebP', 0.934);\n            dataUrl = upload.restoreExif(arrayBufferToBase64(result.fixedArrayBuffer), dataUrl);\n            var blob = upload.dataUrltoBlob(dataUrl, file.name);\n            deferred.resolve(blob);\n          } catch (e) {\n            return deferred.reject(e);\n          }\n        };\n        img.onerror = function () {\n          deferred.reject();\n        };\n        img.src = url;\n      }, function (e) {\n        deferred.reject(e);\n      });\n    }, function (e) {\n      deferred.reject(e);\n    });\n    return deferred.promise;\n  };\n\n  upload.restoreExif = function (orig, resized) {\n    var ExifRestorer = {};\n\n    ExifRestorer.KEY_STR = 'ABCDEFGHIJKLMNOP' +\n      'QRSTUVWXYZabcdef' +\n      'ghijklmnopqrstuv' +\n      'wxyz0123456789+/' +\n      '=';\n\n    ExifRestorer.encode64 = function (input) {\n      var output = '',\n        chr1, chr2, chr3 = '',\n        enc1, enc2, enc3, enc4 = '',\n        i = 0;\n\n      do {\n        chr1 = input[i++];\n        chr2 = input[i++];\n        chr3 = input[i++];\n\n        enc1 = chr1 >> 2;\n        enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);\n        enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);\n        enc4 = chr3 & 63;\n\n        if (isNaN(chr2)) {\n          enc3 = enc4 = 64;\n        } else if (isNaN(chr3)) {\n          enc4 = 64;\n        }\n\n        output = output +\n          this.KEY_STR.charAt(enc1) +\n          this.KEY_STR.charAt(enc2) +\n          this.KEY_STR.charAt(enc3) +\n          this.KEY_STR.charAt(enc4);\n        chr1 = chr2 = chr3 = '';\n        enc1 = enc2 = enc3 = enc4 = '';\n      } while (i < input.length);\n\n      return output;\n    };\n\n    ExifRestorer.restore = function (origFileBase64, resizedFileBase64) {\n      if (origFileBase64.match('data:image/jpeg;base64,')) {\n        origFileBase64 = origFileBase64.replace('data:image/jpeg;base64,', '');\n      }\n\n      var rawImage = this.decode64(origFileBase64);\n      var segments = this.slice2Segments(rawImage);\n\n      var image = this.exifManipulation(resizedFileBase64, segments);\n\n      return 'data:image/jpeg;base64,' + this.encode64(image);\n    };\n\n\n    ExifRestorer.exifManipulation = function (resizedFileBase64, segments) {\n      var exifArray = this.getExifArray(segments),\n        newImageArray = this.insertExif(resizedFileBase64, exifArray);\n      return new Uint8Array(newImageArray);\n    };\n\n\n    ExifRestorer.getExifArray = function (segments) {\n      var seg;\n      for (var x = 0; x < segments.length; x++) {\n        seg = segments[x];\n        if (seg[0] === 255 & seg[1] === 225) //(ff e1)\n        {\n          return seg;\n        }\n      }\n      return [];\n    };\n\n\n    ExifRestorer.insertExif = function (resizedFileBase64, exifArray) {\n      var imageData = resizedFileBase64.replace('data:image/jpeg;base64,', ''),\n        buf = this.decode64(imageData),\n        separatePoint = buf.indexOf(255, 3),\n        mae = buf.slice(0, separatePoint),\n        ato = buf.slice(separatePoint),\n        array = mae;\n\n      array = array.concat(exifArray);\n      array = array.concat(ato);\n      return array;\n    };\n\n\n    ExifRestorer.slice2Segments = function (rawImageArray) {\n      var head = 0,\n        segments = [];\n\n      while (1) {\n        if (rawImageArray[head] === 255 & rawImageArray[head + 1] === 218) {\n          break;\n        }\n        if (rawImageArray[head] === 255 & rawImageArray[head + 1] === 216) {\n          head += 2;\n        }\n        else {\n          var length = rawImageArray[head + 2] * 256 + rawImageArray[head + 3],\n            endPoint = head + length + 2,\n            seg = rawImageArray.slice(head, endPoint);\n          segments.push(seg);\n          head = endPoint;\n        }\n        if (head > rawImageArray.length) {\n          break;\n        }\n      }\n\n      return segments;\n    };\n\n\n    ExifRestorer.decode64 = function (input) {\n      var chr1, chr2, chr3 = '',\n        enc1, enc2, enc3, enc4 = '',\n        i = 0,\n        buf = [];\n\n      // remove all characters that are not A-Z, a-z, 0-9, +, /, or =\n      var base64test = /[^A-Za-z0-9\\+\\/\\=]/g;\n      if (base64test.exec(input)) {\n        console.log('There were invalid base64 characters in the input text.\\n' +\n          'Valid base64 characters are A-Z, a-z, 0-9, ' + ', ' / ',and \"=\"\\n' +\n          'Expect errors in decoding.');\n      }\n      input = input.replace(/[^A-Za-z0-9\\+\\/\\=]/g, '');\n\n      do {\n        enc1 = this.KEY_STR.indexOf(input.charAt(i++));\n        enc2 = this.KEY_STR.indexOf(input.charAt(i++));\n        enc3 = this.KEY_STR.indexOf(input.charAt(i++));\n        enc4 = this.KEY_STR.indexOf(input.charAt(i++));\n\n        chr1 = (enc1 << 2) | (enc2 >> 4);\n        chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);\n        chr3 = ((enc3 & 3) << 6) | enc4;\n\n        buf.push(chr1);\n\n        if (enc3 !== 64) {\n          buf.push(chr2);\n        }\n        if (enc4 !== 64) {\n          buf.push(chr3);\n        }\n\n        chr1 = chr2 = chr3 = '';\n        enc1 = enc2 = enc3 = enc4 = '';\n\n      } while (i < input.length);\n\n      return buf;\n    };\n\n    return ExifRestorer.restore(orig, resized);  //<= EXIF\n  };\n\n  return upload;\n}]);\n\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/ng-file-upload/package.js",
    "content": "Package.describe({\n  name: \"danialf:ng-file-upload\",\n  \"version\": \"12.2.13\",\n  summary: \"Lightweight Angular directive to upload files with optional FileAPI shim for cross browser support\",\n  git: \"https://github.com/danialfarid/ng-file-upload.git\"\n});\n\nPackage.onUse(function (api) {\n  api.use('angular:angular@1.2.0', 'client');\n  api.addFiles('ng-file-upload-all.js', 'client');\n});\n\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/sass-bootstrap/.bower.json",
    "content": "{\n  \"name\": \"sass-bootstrap\",\n  \"version\": \"3.0.0\",\n  \"main\": [\n    \"./dist/js/bootstrap.js\",\n    \"./dist/css/bootstrap.css\"\n  ],\n  \"ignore\": [\n    \"**/.*\"\n  ],\n  \"dependencies\": {\n    \"jquery\": \">= 1.9.0\"\n  },\n  \"homepage\": \"https://github.com/jlong/sass-bootstrap\",\n  \"_release\": \"3.0.0\",\n  \"_resolution\": {\n    \"type\": \"version\",\n    \"tag\": \"v3.0.0\",\n    \"commit\": \"a7388cfd69bedc23bcc56043e0db263027463882\"\n  },\n  \"_source\": \"https://github.com/jlong/sass-bootstrap.git\",\n  \"_target\": \"3.0.0\",\n  \"_originalSource\": \"sass-bootstrap\"\n}"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/sass-bootstrap/CNAME",
    "content": "getbootstrap.com\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/sass-bootstrap/CONTRIBUTING.md",
    "content": "# Contributing to Bootstrap\n\nLooking to contribute something to Bootstrap? **Here's how you can help.**\n\n\n\n## Reporting issues\n\nWe only accept issues that are bug reports or feature requests. Bugs must be isolated and reproducible problems that we can fix within the Bootstrap core. Please read the following guidelines before opening any issue.\n\n1. **Search for existing issues.** We get a lot of duplicate issues, and you'd help us out a lot by first checking if someone else has reported the same issue. Moreover, the issue may have already been resolved with a fix available.\n2. **Create an isolated and reproducible test case.** Be sure the problem exists in Bootstrap's code with a [reduced test case](http://css-tricks.com/reduced-test-cases/) that should be included in each bug report.\n3. **Include a live example.** Make use of jsFiddle or jsBin to share your isolated test cases.\n4. **Share as much information as possible.** Include operating system and version, browser and version, version of Bootstrap, customized or vanilla build, etc. where appropriate. Also include steps to reproduce the bug.\n\n\n\n## Key branches\n\n- `master` is the latest, deployed version.\n- `gh-pages` is the hosted docs (not to be used for pull requests).\n- `*-wip` is the official work in progress branch for the next release.\n\n\n\n## Pull requests\n\n- Try to submit pull requests against the latest `*-wip` branch for easier merging\n- CSS changes must be done in .less files first, never just the compiled files\n- If modifying the .less files, always recompile and commit the compiled files bootstrap.css and bootstrap.min.css\n- Try not to pollute your pull request with unintended changes--keep them simple and small\n- Try to share which browsers your code has been tested in before submitting a pull request\n\n\n\n## Coding standards\n\n### HTML\n\n- Two spaces for indentation, never tabs\n- Double quotes only, never single quotes\n- Always use proper indentation\n- Use tags and elements appropriate for an HTML5 doctype (e.g., self-closing tags)\n\n### CSS\n\n- Adhere to the [Recess CSS property order](http://markdotto.com/2011/11/29/css-property-order/)\n- Multiple-line approach (one property and value per line)\n- Always a space after a property's colon (.e.g, `display: block;` and not `display:block;`)\n- End all lines with a semi-colon\n- For multiple, comma-separated selectors, place each selector on its own line\n- Attribute selectors, like `input[type=\"text\"]` should always wrap the attribute's value in double quotes, for consistency and safety (see this [blog post on unquoted attribute values](http://mathiasbynens.be/notes/unquoted-attribute-values) that can lead to XSS attacks).\n\n### JS\n\n- No semicolons\n- Comma first\n- 2 spaces (no tabs)\n- strict mode\n- \"Attractive\"\n\n\n\n## License\n\nBy contributing your code, you agree to license your contribution under the terms of the APLv2: https://github.com/twbs/bootstrap/blob/master/LICENSE\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/sass-bootstrap/Gemfile",
    "content": "source 'https://rubygems.org'\n\ngem 'rake'\ngem 'sass', '~>3.2'\ngem 'rb-fsevent'\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/sass-bootstrap/Gruntfile.js",
    "content": "/* jshint node: true */\n\nmodule.exports = function(grunt) {\n  \"use strict\";\n\n  // Project configuration.\n  grunt.initConfig({\n\n    // Metadata.\n    pkg: grunt.file.readJSON('package.json'),\n    banner: '/**\\n' +\n              '* <%= pkg.name %>.js v<%= pkg.version %> by @fat and @mdo\\n' +\n              '* Copyright <%= grunt.template.today(\"yyyy\") %> <%= pkg.author %>\\n' +\n              '* <%= _.pluck(pkg.licenses, \"url\").join(\", \") %>\\n' +\n              '*/\\n',\n    jqueryCheck: 'if (!jQuery) { throw new Error(\\\"Bootstrap requires jQuery\\\") }\\n\\n',\n\n    // Task configuration.\n    clean: {\n      dist: ['dist']\n    },\n\n    jshint: {\n      options: {\n        jshintrc: 'js/.jshintrc'\n      },\n      gruntfile: {\n        src: 'Gruntfile.js'\n      },\n      src: {\n        src: ['js/*.js']\n      },\n      test: {\n        src: ['js/tests/unit/*.js']\n      }\n    },\n\n    concat: {\n      options: {\n        banner: '<%= banner %><%= jqueryCheck %>',\n        stripBanners: false\n      },\n      bootstrap: {\n        src: [\n          'js/transition.js',\n          'js/alert.js',\n          'js/button.js',\n          'js/carousel.js',\n          'js/collapse.js',\n          'js/dropdown.js',\n          'js/modal.js',\n          'js/tooltip.js',\n          'js/popover.js',\n          'js/scrollspy.js',\n          'js/tab.js',\n          'js/affix.js'\n        ],\n        dest: 'dist/js/<%= pkg.name %>.js'\n      }\n    },\n\n    uglify: {\n      options: {\n        banner: '<%= banner %>'\n      },\n      bootstrap: {\n        src: ['<%= concat.bootstrap.dest %>'],\n        dest: 'dist/js/<%= pkg.name %>.min.js'\n      }\n    },\n\n    recess: {\n      options: {\n        compile: true\n      },\n      bootstrap: {\n        src: ['less/bootstrap.less'],\n        dest: 'dist/css/<%= pkg.name %>.css'\n      },\n      min: {\n        options: {\n          compress: true\n        },\n        src: ['less/bootstrap.less'],\n        dest: 'dist/css/<%= pkg.name %>.min.css'\n      },\n      theme: {\n        src: ['less/theme.less'],\n        dest: 'dist/css/<%= pkg.name %>-theme.css'\n      },\n      theme_min: {\n        options: {\n          compress: true\n        },\n        src: ['less/theme.less'],\n        dest: 'dist/css/<%= pkg.name %>-theme.min.css'\n      }\n    },\n\n    copy: {\n      fonts: {\n        expand: true,\n        src: [\"fonts/*\"],\n        dest: 'dist/'\n      }\n    },\n\n    qunit: {\n      options: {\n        inject: 'js/tests/unit/phantom.js'\n      },\n      files: ['js/tests/*.html']\n    },\n\n    connect: {\n      server: {\n        options: {\n          port: 3000,\n          base: '.'\n        }\n      }\n    },\n\n    jekyll: {\n      docs: {}\n    },\n\n    validation: {\n      options: {\n        reset: true\n      },\n      files: {\n        src: [\"_gh_pages/**/*.html\"]\n      }\n    },\n\n    watch: {\n      src: {\n        files: '<%= jshint.src.src %>',\n        tasks: ['jshint:src', 'qunit']\n      },\n      test: {\n        files: '<%= jshint.test.src %>',\n        tasks: ['jshint:test', 'qunit']\n      },\n      recess: {\n        files: 'less/*.less',\n        tasks: ['recess']\n      }\n    }\n  });\n\n\n  // These plugins provide necessary tasks.\n  grunt.loadNpmTasks('grunt-contrib-clean');\n  grunt.loadNpmTasks('grunt-contrib-concat');\n  grunt.loadNpmTasks('grunt-contrib-connect');\n  grunt.loadNpmTasks('grunt-contrib-copy');\n  grunt.loadNpmTasks('grunt-contrib-jshint');\n  grunt.loadNpmTasks('grunt-contrib-qunit');\n  grunt.loadNpmTasks('grunt-contrib-uglify');\n  grunt.loadNpmTasks('grunt-contrib-watch');\n  grunt.loadNpmTasks('grunt-html-validation');\n  grunt.loadNpmTasks('grunt-jekyll');\n  grunt.loadNpmTasks('grunt-recess');\n  grunt.loadNpmTasks('browserstack-runner');\n\n  // Docs HTML validation task\n  grunt.registerTask('validate-html', ['jekyll', 'validation']);\n\n  // Test task.\n  var testSubtasks = ['dist-css', 'jshint', 'qunit', 'validate-html'];\n  // Only run BrowserStack tests under Travis\n  if (process.env.TRAVIS) {\n    // Only run BrowserStack tests if this is a mainline commit in twbs/bootstrap, or you have your own BrowserStack key\n    if ((process.env.TRAVIS_REPO_SLUG === 'twbs/bootstrap' && process.env.TRAVIS_PULL_REQUEST === 'false') || process.env.TWBS_HAVE_OWN_BROWSERSTACK_KEY) {\n      testSubtasks.push('browserstack_runner');\n    }\n  }\n  grunt.registerTask('test', testSubtasks);\n\n  // JS distribution task.\n  grunt.registerTask('dist-js', ['concat', 'uglify']);\n\n  // CSS distribution task.\n  grunt.registerTask('dist-css', ['recess']);\n\n  // Fonts distribution task.\n  grunt.registerTask('dist-fonts', ['copy']);\n\n  // Full distribution task.\n  grunt.registerTask('dist', ['clean', 'dist-css', 'dist-fonts', 'dist-js']);\n\n  // Default task.\n  grunt.registerTask('default', ['test', 'dist', 'build-customizer']);\n\n  // task for building customizer\n  grunt.registerTask('build-customizer', 'Add scripts/less files to customizer.', function () {\n    var fs = require('fs')\n\n    function getFiles(type) {\n      var files = {}\n      fs.readdirSync(type)\n        .filter(function (path) {\n          return type == 'fonts' ? true : new RegExp('\\\\.' + type + '$').test(path)\n        })\n        .forEach(function (path) {\n          return files[path] = fs.readFileSync(type + '/' + path, 'utf8')\n        })\n      return 'var __' + type + ' = ' + JSON.stringify(files) + '\\n'\n    }\n\n    var customize = fs.readFileSync('customize.html', 'utf-8')\n    var files = getFiles('js') + getFiles('less') + getFiles('fonts')\n    fs.writeFileSync('assets/js/raw-files.js', files)\n  });\n};"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/sass-bootstrap/LICENSE",
    "content": "                                 Apache License\n                           Version 2.0, January 2004\n                        http://www.apache.org/licenses/\n\n   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n   1. Definitions.\n\n      \"License\" shall mean the terms and conditions for use, reproduction,\n      and distribution as defined by Sections 1 through 9 of this document.\n\n      \"Licensor\" shall mean the copyright owner or entity authorized by\n      the copyright owner that is granting the License.\n\n      \"Legal Entity\" shall mean the union of the acting entity and all\n      other entities that control, are controlled by, or are under common\n      control with that entity. For the purposes of this definition,\n      \"control\" means (i) the power, direct or indirect, to cause the\n      direction or management of such entity, whether by contract or\n      otherwise, or (ii) ownership of fifty percent (50%) or more of the\n      outstanding shares, or (iii) beneficial ownership of such entity.\n\n      \"You\" (or \"Your\") shall mean an individual or Legal Entity\n      exercising permissions granted by this License.\n\n      \"Source\" form shall mean the preferred form for making modifications,\n      including but not limited to software source code, documentation\n      source, and configuration files.\n\n      \"Object\" form shall mean any form resulting from mechanical\n      transformation or translation of a Source form, including but\n      not limited to compiled object code, generated documentation,\n      and conversions to other media types.\n\n      \"Work\" shall mean the work of authorship, whether in Source or\n      Object form, made available under the License, as indicated by a\n      copyright notice that is included in or attached to the work\n      (an example is provided in the Appendix below).\n\n      \"Derivative Works\" shall mean any work, whether in Source or Object\n      form, that is based on (or derived from) the Work and for which the\n      editorial revisions, annotations, elaborations, or other modifications\n      represent, as a whole, an original work of authorship. For the purposes\n      of this License, Derivative Works shall not include works that remain\n      separable from, or merely link (or bind by name) to the interfaces of,\n      the Work and Derivative Works thereof.\n\n      \"Contribution\" shall mean any work of authorship, including\n      the original version of the Work and any modifications or additions\n      to that Work or Derivative Works thereof, that is intentionally\n      submitted to Licensor for inclusion in the Work by the copyright owner\n      or by an individual or Legal Entity authorized to submit on behalf of\n      the copyright owner. For the purposes of this definition, \"submitted\"\n      means any form of electronic, verbal, or written communication sent\n      to the Licensor or its representatives, including but not limited to\n      communication on electronic mailing lists, source code control systems,\n      and issue tracking systems that are managed by, or on behalf of, the\n      Licensor for the purpose of discussing and improving the Work, but\n      excluding communication that is conspicuously marked or otherwise\n      designated in writing by the copyright owner as \"Not a Contribution.\"\n\n      \"Contributor\" shall mean Licensor and any individual or Legal Entity\n      on behalf of whom a Contribution has been received by Licensor and\n      subsequently incorporated within the Work.\n\n   2. Grant of Copyright License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      copyright license to reproduce, prepare Derivative Works of,\n      publicly display, publicly perform, sublicense, and distribute the\n      Work and such Derivative Works in Source or Object form.\n\n   3. Grant of Patent License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      (except as stated in this section) patent license to make, have made,\n      use, offer to sell, sell, import, and otherwise transfer the Work,\n      where such license applies only to those patent claims licensable\n      by such Contributor that are necessarily infringed by their\n      Contribution(s) alone or by combination of their Contribution(s)\n      with the Work to which such Contribution(s) was submitted. If You\n      institute patent litigation against any entity (including a\n      cross-claim or counterclaim in a lawsuit) alleging that the Work\n      or a Contribution incorporated within the Work constitutes direct\n      or contributory patent infringement, then any patent licenses\n      granted to You under this License for that Work shall terminate\n      as of the date such litigation is filed.\n\n   4. Redistribution. You may reproduce and distribute copies of the\n      Work or Derivative Works thereof in any medium, with or without\n      modifications, and in Source or Object form, provided that You\n      meet the following conditions:\n\n      (a) You must give any other recipients of the Work or\n          Derivative Works a copy of this License; and\n\n      (b) You must cause any modified files to carry prominent notices\n          stating that You changed the files; and\n\n      (c) You must retain, in the Source form of any Derivative Works\n          that You distribute, all copyright, patent, trademark, and\n          attribution notices from the Source form of the Work,\n          excluding those notices that do not pertain to any part of\n          the Derivative Works; and\n\n      (d) If the Work includes a \"NOTICE\" text file as part of its\n          distribution, then any Derivative Works that You distribute must\n          include a readable copy of the attribution notices contained\n          within such NOTICE file, excluding those notices that do not\n          pertain to any part of the Derivative Works, in at least one\n          of the following places: within a NOTICE text file distributed\n          as part of the Derivative Works; within the Source form or\n          documentation, if provided along with the Derivative Works; or,\n          within a display generated by the Derivative Works, if and\n          wherever such third-party notices normally appear. The contents\n          of the NOTICE file are for informational purposes only and\n          do not modify the License. You may add Your own attribution\n          notices within Derivative Works that You distribute, alongside\n          or as an addendum to the NOTICE text from the Work, provided\n          that such additional attribution notices cannot be construed\n          as modifying the License.\n\n      You may add Your own copyright statement to Your modifications and\n      may provide additional or different license terms and conditions\n      for use, reproduction, or distribution of Your modifications, or\n      for any such Derivative Works as a whole, provided Your use,\n      reproduction, and distribution of the Work otherwise complies with\n      the conditions stated in this License.\n\n   5. Submission of Contributions. Unless You explicitly state otherwise,\n      any Contribution intentionally submitted for inclusion in the Work\n      by You to the Licensor shall be under the terms and conditions of\n      this License, without any additional terms or conditions.\n      Notwithstanding the above, nothing herein shall supersede or modify\n      the terms of any separate license agreement you may have executed\n      with Licensor regarding such Contributions.\n\n   6. Trademarks. This License does not grant permission to use the trade\n      names, trademarks, service marks, or product names of the Licensor,\n      except as required for reasonable and customary use in describing the\n      origin of the Work and reproducing the content of the NOTICE file.\n\n   7. Disclaimer of Warranty. Unless required by applicable law or\n      agreed to in writing, Licensor provides the Work (and each\n      Contributor provides its Contributions) on an \"AS IS\" BASIS,\n      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n      implied, including, without limitation, any warranties or conditions\n      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n      PARTICULAR PURPOSE. You are solely responsible for determining the\n      appropriateness of using or redistributing the Work and assume any\n      risks associated with Your exercise of permissions under this License.\n\n   8. Limitation of Liability. In no event and under no legal theory,\n      whether in tort (including negligence), contract, or otherwise,\n      unless required by applicable law (such as deliberate and grossly\n      negligent acts) or agreed to in writing, shall any Contributor be\n      liable to You for damages, including any direct, indirect, special,\n      incidental, or consequential damages of any character arising as a\n      result of this License or out of the use or inability to use the\n      Work (including but not limited to damages for loss of goodwill,\n      work stoppage, computer failure or malfunction, or any and all\n      other commercial damages or losses), even if such Contributor\n      has been advised of the possibility of such damages.\n\n   9. Accepting Warranty or Additional Liability. While redistributing\n      the Work or Derivative Works thereof, You may choose to offer,\n      and charge a fee for, acceptance of support, warranty, indemnity,\n      or other liability obligations and/or rights consistent with this\n      License. However, in accepting such obligations, You may act only\n      on Your own behalf and on Your sole responsibility, not on behalf\n      of any other Contributor, and only if You agree to indemnify,\n      defend, and hold each Contributor harmless for any liability\n      incurred by, or claims asserted against, such Contributor by reason\n      of your accepting any such warranty or additional liability.\n\n   END OF TERMS AND CONDITIONS\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/sass-bootstrap/README.md",
    "content": "# [Sass Bootstrap v3.0.0](http://getbootstrap.com) [![Build Status](https://secure.travis-ci.org/twbs/bootstrap.png)](http://travis-ci.org/twbs/bootstrap)\n\nBootstrap is a sleek, intuitive, and powerful front-end framework for faster and easier web development, created and maintained by [Mark Otto](http://twitter.com/mdo) and [Jacob Thornton](http://twitter.com/fat).\n\nThis is the Sass version of Bootstrap. A port of Bootsrap from Less to Sass. This project is focused on being a 1:1 port of the original. Please do not submit issues or pull requests for issues with Bootstrap itself. Those should be pushed upstream in the Less version.\n\nTo get started, check out [http://getbootstrap.com](http://getbootstrap.com)!\n\n\n\n## Quick start\n\nThree quick start options are available:\n\n* [Download the latest release](https://github.com/jlong/sass-twitter-bootstrap/zipball/master).\n* Clone the repo: `git clone git://github.com/jlong/sass-twitter-bootstrap.git`.\n* Install with [Bower](http://bower.io): `bower install --save sass-bootstrap`.\n\n\n\n## Usage\n\nYou can use the Sass Bootstrap by dropping the compiled CSS into any new project and start cranking.\n\nBecause SASS always outputs standard css, just link to the final output like normal:\n\n`<link rel=\"stylesheet\" type=\"text/css\" href=\"./dist/css/bootstrap.css\">`\n\nFor more info, refer to the docs!\n\n\n\n## Basic modification\n\nYou can learn more about Sass at:\n\n[sass-lang.com](http://sass-lang.com)\n\nSass runs as a local GEM on your system. You can run `sass --watch lib/bootstrap.scss:dist/css/bootstrap.css`\n\n\n\n## Bugs and feature requests\n\nPlease do not submit issues or pull requests for issues with Bootstrap itself. Those should be pushed upstream in the Less version. [Please open a new issue](https://github.com/twbs/bootstrap/issues). Before opening any issue, please search for existing issues and read the [Issue Guidelines](https://github.com/necolas/issue-guidelines), written by [Nicolas Gallagher](https://github.com/necolas/).\n\nYou may use [this JS Bin](http://jsbin.com/aKiCIDO/1/edit) as a template for your bug reports.\n\n\n\n## Documentation\n\nBootstrap's documentation, included in this repo in the root directory, is built with [Jekyll](http://jekyllrb.com) and publicly hosted on GitHub Pages at [http://getbootstrap.com](http://getbootstrap.com). The docs may also be run locally.\n\n### Running documentation locally\n\n1. If necessary, [install Jekyll](http://jekyllrb.com/docs/installation) (requires v1.x).\n2. From the root `/bootstrap` directory, run `jekyll serve` in the command line.\n  - **Windows users:** run `chcp 65001` first to change the command prompt's character encoding ([code page](http://en.wikipedia.org/wiki/Windows_code_page)) to UTF-8 so Jekyll runs without errors.\n3. Open [http://localhost:9001](http://localhost:9001) in your browser, and voilà.\n\nLearn more about using Jekyll by reading their [documentation](http://jekyllrb.com/docs/home/).\n\n### Documentation for previous releases\n\nDocumentation for v2.3.2 has been made available for the time being at [http://getbootstrap.com/2.3.2/](http://getbootstrap.com/2.3.2/) while folks transition to Bootstrap 3.\n\n[Previous releases](https://github.com/twbs/bootstrap/releases) and their documentation are also available for download.\n\n\n\n## Compiling CSS and JavaScript\n\nBootstrap uses [Grunt](http://gruntjs.com/) with convenient methods for working with the framework. It's how we compile our code, run tests, and more. To use it, install the required dependencies as directed and then run some Grunt commands.\n\n### Install Grunt\n\nFrom the command line:\n\n1. Install `grunt-cli` globally with `npm install -g grunt-cli`.\n2. Install the [necessary local dependencies](package.json) via `npm install`\n\nWhen completed, you'll be able to run the various Grunt commands provided from the command line.\n\n**Unfamiliar with `npm`? Don't have node installed?** That's a-okay. npm stands for [node packaged modules](http://npmjs.org/) and is a way to manage development dependencies through node.js. [Download and install node.js](http://nodejs.org/download/) before proceeding.\n\n### Available Grunt commands\n\n#### Build - `grunt`\nRun `grunt` to run tests locally and compile the CSS and JavaScript into `/dist`. **Requires [recess](https://github.com/twitter/recess) and [uglify-js](https://github.com/mishoo/UglifyJS).**\n\n#### Only compile CSS and JavaScript - `grunt dist`\n`grunt dist` creates the `/dist` directory with compiled files. **Requires [recess](https://github.com/twitter/recess) and [uglify-js](https://github.com/mishoo/UglifyJS).**\n\n#### Tests - `grunt test`\nRuns jshint and qunit tests headlessly in [phantomjs](https://github.com/ariya/phantomjs/) (used for CI). **Requires [phantomjs](https://github.com/ariya/phantomjs/).**\n\n#### Watch - `grunt watch`\nThis is a convenience method for watching just Less files and automatically building them whenever you save.\n\n### Troubleshooting dependencies\n\nShould you encounter problems with installing dependencies or running Grunt commands, uninstall all previous dependency versions (global and local). Then, rerun `npm install`.\n\n\n\n## Contributing\n\nPlease read through our guidelines for contributing to Bootstrap. Included are directions for opening issues, coding standards, and notes on development.\n\nMore over, if your pull request contains JavaScript patches or features, you must include relevant unit tests. All HTML and CSS should conform to the [Code Guide](http://github.com/mdo/code-guide), maintained by [Mark Otto](http://github.com/mdo).\n\nEditor preferences are available in the [editor config](.editorconfig) for easy use in common text editors. Read more and download plugins at [http://editorconfig.org](http://editorconfig.org).\n\n\n\n## Community\n\nKeep track of development and community news.\n\n* Follow [@twbootstrap on Twitter](http://twitter.com/twbootstrap).\n* Read and subscribe to the [The Official Bootstrap Blog](http://blog.getbootstrap.com).\n* Have a question that's not a feature request or bug report? [Ask on the mailing list.](http://groups.google.com/group/twitter-bootstrap)\n* Chat with fellow Bootstrappers in IRC. On the `irc.freenode.net` server, in the `##twitter-bootstrap` channel.\n\n\n\n\n## Versioning\n\nFor transparency and insight into our release cycle, and for striving to maintain backward compatibility, Bootstrap will be maintained under the Semantic Versioning guidelines as much as possible.\n\nReleases will be numbered with the following format:\n\n`<major>.<minor>.<patch>`\n\nAnd constructed with the following guidelines:\n\n* Breaking backward compatibility bumps the major (and resets the minor and patch)\n* New additions without breaking backward compatibility bumps the minor (and resets the patch)\n* Bug fixes and misc changes bumps the patch\n\nFor more information on SemVer, please visit [http://semver.org/](http://semver.org/).\n\n\n\n## SASS: Developers\n\nWe have included a Rakefile with convenience methods for working with the SASS Bootstrap library.\n\n+ **build** - `rake build`\nThis will run the less compiler on the bootstrap lib and regenerate the docs dir.\nThe lessc compiler is required for this command to run.\n\n+ **watch** - `rake watch`\nThis is a convenience method for watching your Sass files and automatically building them whenever you save.\n\n\n\n## Authors\n\n**Mark Otto**\n\n+ [http://twitter.com/mdo](http://twitter.com/mdo)\n+ [http://github.com/mdo](http://github.com/mdo)\n\n**Jacob Thornton**\n\n+ [http://twitter.com/fat](http://twitter.com/fat)\n+ [http://github.com/fat](http://github.com/fat)\n\n\n\n## SASS: Conversion less to Sass\n\nThe Twitter Bootstrap was lovingly converted to Sass by:\n\n**John W. Long**\n\n+ http://twitter.com/johnwlong\n+ http://github.com/jlong\n\n**Jeremy Hinegardner**\n\n+ http://twitter.com/copiousfreetime\n+ http://github.com/copiousfreetime\n\n**m5o**\n\n+ http://twitter.com/m5o\n+ http://github.com/m5o\n\n**smt**\n\n+ http://twitter.com/tudorstudio\n+ http://github.com/smt\n\nAnd [others](https://github.com/jlong/sass-twitter-bootstrap/contributors)\n\n\n\n## SASS: Conversion Quick Tips\n\n* replace @ with $\n* replace . with @include for mixins\n* replace `spin` with `adjust-hue`\n* add !default to variable definitions\n* replace #gradient > .vertical with @include gradient-vertical\n* replace #grid > .style with @include grid-style\n* use grid-core and grid-fluid mixins instead of #grid > .core and #grid > .fluid\n* use font-shorthand instead of #font > .shorthand\n* replace fadein with fade-in\n* move @import for reset below mixins, because it uses tab-focus mixin in bootstrap.scss\n* explicitly provide .clearfix, .hide-text and .input-block-level for compatibility with LESS output\n* pass grid-* mixin arguments to generators, because otherwise the generator mixins will use the default variables pull transition definition into variable\n\n\n\n## Sass: Installation via Composer\n\nIf you already use Composer, the php dependency manager, installing\nsass-twitter-bootstrap is as simple as typing :\n```shell\ncomposer.phar require jlong/sass-twitter-bootstrap:x.y.z\n```\nThis will install version x.y.z from packagist.org\n\nYou'll probably want to make sure you get minor updates, like this:\n```shell\ncomposer.phar require jlong/sass-twitter-bootstrap:~x.y.z\n```\nor like this:\n```shell\ncomposer.phar require jlong/sass-twitter-bootstrap:x.y.*\n```\n\n\n\n## Copyright and license\n\nCopyright 2012 Twitter, Inc under [the Apache 2.0 license](LICENSE).\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/sass-bootstrap/Rakefile",
    "content": "require 'rubygems'\nrequire 'bundler'\nbegin\n  Bundler.setup(:default, :development)\nrescue Bundler::BundlerError => e\n  $stderr.puts e.message\n  $stderr.puts \"Run `bundle install` to install missing gems\"\n  exit e.status_code\nend\nrequire 'rake'\n\nBOOTSTRAP_CSS = \"bootstrap.css\"\nBOOTSTRAP_MIN_CSS = \"bootstrap.min.css\"\nBOOTSTRAP_THEME_CSS = \"bootstrap-theme.css\"\nBOOTSTRAP_THEME_MIN_CSS = \"bootstrap-theme.min.css\"\n\nSASS_COMMAND = \"sass --precision 16 --load-path lib --style\"\n\ntask BOOTSTRAP_CSS do |target|\n  sh \"#{SASS_COMMAND} expanded lib/bootstrap.scss:dist/css/#{target}\"\nend\n\ntask BOOTSTRAP_MIN_CSS do |target|\n  sh \"#{SASS_COMMAND} compressed lib/bootstrap.scss:dist/css/#{target}\"\nend\n\ntask BOOTSTRAP_THEME_CSS do |target|\n  sh \"#{SASS_COMMAND} expanded lib/_theme.scss:dist/css/#{target}\"\nend\n\ntask BOOTSTRAP_THEME_MIN_CSS do |target|\n  sh \"#{SASS_COMMAND} compressed lib/_theme.scss:dist/css/#{target}\"\nend\n\n\ndesc \"build regular and compressed versions of bootstrap\"\ntask :build => [BOOTSTRAP_CSS, BOOTSTRAP_MIN_CSS, BOOTSTRAP_THEME_CSS, BOOTSTRAP_THEME_MIN_CSS]\n\ndesc \"rebuild regular version of bootstrap when modifications are made\"\ntask :watch do\n  sh \"#{SASS_COMMAND} expanded --watch lib/bootstrap.scss:dist/css/#{BOOTSTRAP_CSS}\"\nend\n\ntask :default => :build\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/sass-bootstrap/_config.yml",
    "content": "# Dependencies\nmarkdown:         rdiscount\npygments:         true\n\n# Permalinks\npermalink:        pretty\n\n# Server\ndestination:      ./_gh_pages\nexclude:          [\".editorconfig\", \".gitignore\", \".ruby-version\", \"bower.json\", \"composer.json\", \"CONTRIBUTING.md\", \"CNAME\", \"LICENSE\", \"Gruntfile.js\", \"package.json\", \"node_modules\", \"README.md\", \"less\"]\nport:             9001\n\n# Custom vars\nrepo:             https://github.com/twbs/bootstrap\ndownload:         https://github.com/twbs/bootstrap/archive/v3.0.0.zip\ndownload_dist:    https://github.com/twbs/bootstrap/releases/download/v3.0.0/bootstrap-3.0.0-dist.zip\n\nblog:             http://blog.getbootstrap.com\nexpo:             http://expo.getbootstrap.com\n\ncdn_css:          //netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css\ncdn_theme_css:    //netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap-theme.min.css\ncdn_js:           //netdna.bootstrapcdn.com/bootstrap/3.0.0/js/bootstrap.min.js\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/sass-bootstrap/_includes/ads.html",
    "content": "<div id=\"carbonads-container\"><div class=\"carbonad\"><div id=\"azcarbon\"></div><script>var z = document.createElement(\"script\"); z.async = true; z.src = \"http://engine.carbonads.com/z/32341/azcarbon_2_1_0_HORIZ\"; var s = document.getElementsByTagName(\"script\")[0]; s.parentNode.insertBefore(z, s);</script></div></div>\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/sass-bootstrap/_includes/footer.html",
    "content": "<!-- Bootstrap core JavaScript\n================================================== -->\n<!-- Placed at the end of the document so the pages load faster -->\n<script src=\"{{ page.base_url }}assets/js/jquery.js\"></script>\n<script src=\"{{ page.base_url }}dist/js/bootstrap.js\"></script>\n\n<script src=\"http://platform.twitter.com/widgets.js\"></script>\n<script src=\"{{ page.base_url }}assets/js/holder.js\"></script>\n\n<script src=\"{{ page.base_url }}assets/js/application.js\"></script>\n\n{% if page.slug == \"customize\" %}\n<script src=\"{{ page.base_url }}assets/js/less.js\"></script>\n<script src=\"{{ page.base_url }}assets/js/jszip.js\"></script>\n<script src=\"{{ page.base_url }}assets/js/uglify.js\"></script>\n<script src=\"{{ page.base_url }}assets/js/filesaver.js\"></script>\n<script src=\"{{ page.base_url }}assets/js/raw-files.js\"></script>\n<script src=\"{{ page.base_url }}assets/js/customizer.js\"></script>\n{% endif %}\n\n<!-- Analytics\n================================================== -->\n<script>\n  var _gauges = _gauges || [];\n  (function() {\n    var t   = document.createElement('script');\n    t.async = true;\n    t.id    = 'gauges-tracker';\n    t.setAttribute('data-site-id', '4f0dc9fef5a1f55508000013');\n    t.src = '//secure.gaug.es/track.js';\n    var s = document.getElementsByTagName('script')[0];\n    s.parentNode.insertBefore(t, s);\n  })();\n</script>\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/sass-bootstrap/_includes/header.html",
    "content": "<meta charset=\"utf-8\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n<meta name=\"description\" content=\"\">\n<meta name=\"author\" content=\"\">\n\n<title>\n  {% if page.title == \"Bootstrap\" %}\n    {{ page.title }}\n  {% else if %}\n    {{ page.title }} &middot; Bootstrap\n  {% endif %}\n</title>\n\n<!-- Bootstrap core CSS -->\n<link href=\"{{ page.base_url }}dist/css/bootstrap.css\" rel=\"stylesheet\">\n\n<!-- Documentation extras -->\n<link href=\"{{ page.base_url }}assets/css/docs.css\" rel=\"stylesheet\">\n<link href=\"{{ page.base_url }}assets/css/pygments-manni.css\" rel=\"stylesheet\">\n\n<!-- HTML5 shim and Respond.js IE8 support of HTML5 elements and media queries -->\n<!--[if lt IE 9]>\n  <script src=\"{{ page.base_url }}assets/js/html5shiv.js\"></script>\n  <script src=\"{{ page.base_url }}assets/js/respond.min.js\"></script>\n<![endif]-->\n\n<!-- Favicons -->\n<link rel=\"apple-touch-icon-precomposed\" sizes=\"144x144\" href=\"{{ page.base_url }}assets/ico/apple-touch-icon-144-precomposed.png\">\n<link rel=\"apple-touch-icon-precomposed\" sizes=\"114x114\" href=\"{{ page.base_url }}assets/ico/apple-touch-icon-114-precomposed.png\">\n  <link rel=\"apple-touch-icon-precomposed\" sizes=\"72x72\" href=\"{{ page.base_url }}assets/ico/apple-touch-icon-72-precomposed.png\">\n                <link rel=\"apple-touch-icon-precomposed\" href=\"{{ page.base_url }}assets/ico/apple-touch-icon-57-precomposed.png\">\n                               <link rel=\"shortcut icon\" href=\"{{ page.base_url }}assets/ico/favicon.png\">\n\n<script>\n  var _gaq = _gaq || [];\n  _gaq.push(['_setAccount', 'UA-146052-10']);\n  _gaq.push(['_trackPageview']);\n  (function() {\n    var ga = document.createElement('script'); ga.async = true;\n    ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';\n    var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);\n  })();\n</script>\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/sass-bootstrap/_includes/nav-components.html",
    "content": "<li>\n  <a href=\"#glyphicons\">Glyphicons</a>\n  <ul class=\"nav\">\n    <li><a href=\"#glyphicons-glyphs\">Available glyphs</a></li>\n    <li><a href=\"#glyphicons-how-to-use\">How to use</a></li>\n    <li><a href=\"#glyphicons-examples\">Examples</a></li>\n  </ul>\n</li>\n<li>\n  <a href=\"#dropdowns\">Dropdowns</a>\n  <ul class=\"nav\">\n    <li><a href=\"#dropdowns-example\">Example</a></li>\n    <li><a href=\"#dropdowns-alignment\">Alignment options</a></li>\n    <li><a href=\"#dropdowns-headers\">Headers</a></li>\n    <li><a href=\"#dropdowns-disabled\">Disabled menu items</a></li>\n  </ul>\n</li>\n<li>\n  <a href=\"#btn-groups\">Button groups</a>\n  <ul class=\"nav\">\n    <li><a href=\"#btn-groups-single\">Basic example</a></li>\n    <li><a href=\"#btn-groups-toolbar\">Button toolbar</a></li>\n    <li><a href=\"#btn-groups-sizing\">Sizing</a></li>\n    <li><a href=\"#btn-groups-nested\">Nesting</a></li>\n    <li><a href=\"#btn-groups-vertical\">Vertical variation</a></li>\n    <li><a href=\"#btn-groups-justified\">Justified link variation</a></li>\n  </ul>\n</li>\n<li>\n  <a href=\"#btn-dropdowns\">Button dropdowns</a>\n  <ul class=\"nav\">\n    <li><a href=\"#btn-dropdowns-single\">Single button dropdowns</a></li>\n    <li><a href=\"#btn-dropdowns-split\">Split button dropdowns</a></li>\n    <li><a href=\"#btn-dropdowns-sizing\">Sizing</a></li>\n    <li><a href=\"#btn-dropdowns-dropup\">Dropup variation</a></li>\n  </ul>\n</li>\n<li>\n  <a href=\"#input-groups\">Input groups</a>\n  <ul class=\"nav\">\n    <li><a href=\"#input-groups-basic\">Basic example</a></li>\n    <li><a href=\"#input-groups-sizing\">Sizing</a></li>\n    <li><a href=\"#input-groups-checkboxes-radios\">Checkbox and radios addons</a></li>\n    <li><a href=\"#input-groups-buttons\">Button addons</a></li>\n    <li><a href=\"#input-groups-buttons-dropdowns\">Buttons with dropdowns</a></li>\n    <li><a href=\"#input-groups-buttons-segmented\">Segmented buttons</a></li>\n  </ul>\n</li>\n<li>\n  <a href=\"#nav\">Navs</a>\n  <ul class=\"nav\">\n    <li><a href=\"#nav-tabs\">Tabs</a></li>\n    <li><a href=\"#nav-pills\">Pills</a></li>\n    <li><a href=\"#nav-justified\">Justified nav</a></li>\n    <li><a href=\"#nav-disabled-links\">Disabled links</a></li>\n    <li><a href=\"#nav-alignment\">Alignment options</a></li>\n    <li><a href=\"#nav-dropdowns\">Using dropdowns</a></li>\n  </ul>\n</li>\n<li>\n  <a href=\"#navbar\">Navbar</a>\n  <ul class=\"nav\">\n    <li><a href=\"#navbar-default\">Default navbar</a></li>\n    <li><a href=\"#navbar-buttons\">Buttons</a></li>\n    <li><a href=\"#navbar-text\">Text</a></li>\n    <li><a href=\"#navbar-links\">Non-nav links</a></li>\n    <li><a href=\"#navbar-component-alignment\">Component alignment</a></li>\n    <li><a href=\"#navbar-fixed-top\">Fixed to top</a></li>\n    <li><a href=\"#navbar-fixed-bottom\">Fixed to bottom</a></li>\n    <li><a href=\"#navbar-static-top\">Static top</a></li>\n    <li><a href=\"#navbar-inverted\">Inverted navbar</a></li>\n  </ul>\n</li>\n<li><a href=\"#breadcrumbs\">Breadcrumbs</a></li>\n<li>\n  <a href=\"#pagination\">Pagination</a>\n  <ul class=\"nav\">\n    <li><a href=\"#pagination-default\">Default pagination</a></li>\n    <li><a href=\"#pagination-pager\">Pager</a></li>\n  </ul>\n</li>\n<li><a href=\"#labels\">Labels</a></li>\n<li><a href=\"#badges\">Badges</a></li>\n<li><a href=\"#jumbotron\">Jumbotron</a></li>\n<li><a href=\"#page-header\">Page header</a></li>\n<li>\n  <a href=\"#thumbnails\">Thumbnails</a>\n  <ul class=\"nav\">\n    <li><a href=\"#thumbnails-default\">Default example</a></li>\n    <li><a href=\"#thumbnails-custom-content\">Custom content</a></li>\n  </ul>\n</li>\n<li>\n  <a href=\"#alerts\">Alerts</a>\n  <ul class=\"nav\">\n    <li><a href=\"#alerts-examples\">Examples</a></li>\n    <li><a href=\"#alerts-dismissable\">Dismissable alerts</a></li>\n    <li><a href=\"#alerts-links\">Links in alerts</a></li>\n  </ul>\n</li>\n<li>\n  <a href=\"#progress\">Progress bars</a>\n  <ul class=\"nav\">\n    <li><a href=\"#progress-basic\">Basic example</a></li>\n    <li><a href=\"#progress-alternatives\">Contextual alternatives</a></li>\n    <li><a href=\"#progress-striped\">Striped</a></li>\n    <li><a href=\"#progress-animated\">Animated</a></li>\n    <li><a href=\"#progress-stacked\">Stacked</a></li>\n  </ul>\n</li>\n<li>\n  <a href=\"#media\">Media object</a>\n  <ul class=\"nav\">\n    <li><a href=\"#media-default\">Default media</a></li>\n    <li><a href=\"#media-list\">Media list</a></li>\n  </ul>\n</li>\n<li>\n  <a href=\"#list-group\">List group</a>\n  <ul class=\"nav\">\n    <li><a href=\"#list-group-basic\">Basic example</a></li>\n    <li><a href=\"#list-group-badges\">Badges</a></li>\n    <li><a href=\"#list-group-linked\">Linked items</a></li>\n    <li><a href=\"#list-group-custom-content\">Custom content</a></li>\n  </ul>\n</li>\n<li>\n  <a href=\"#panels\">Panels</a>\n  <ul class=\"nav\">\n    <li><a href=\"#panels-basic\">Basic example</a></li>\n    <li><a href=\"#panels-heading\">Panel with heading</a></li>\n    <li><a href=\"#panels-alternatives\">Contextual alternatives</a></li>\n    <li><a href=\"#panels-tables\">With tables</a>\n    <li><a href=\"#panels-list-group\">With list groups</a>\n  </ul>\n</li>\n<li><a href=\"#wells\">Wells</a></li>\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/sass-bootstrap/_includes/nav-css.html",
    "content": "<li>\n  <a href=\"#overview\">Overview</a>\n  <ul class=\"nav\">\n    <li><a href=\"#overview-doctype\">HTML5 doctype</a></li>\n    <li><a href=\"#overview-mobile\">Mobile first</a></li>\n    <li><a href=\"#overview-responsive-images\">Responsive images</a></li>\n    <li><a href=\"#overview-type-links\">Typography and links</a></li>\n    <li><a href=\"#overview-normalize\">Normalize</a></li>\n    <li><a href=\"#overview-container\">Containers</a></li>\n  </ul>\n</li>\n<li>\n  <a href=\"#grid\">Grid system</a>\n  <ul class=\"nav\">\n    <li><a href=\"#grid-media-queries\">Media queries</a></li>\n    <li><a href=\"#grid-options\">Grid options</a></li>\n    <li><a href=\"#grid-example-basic\">Ex: Stacked-to-horizonal</a></li>\n    <li><a href=\"#grid-example-mixed\">Ex: Mobile and desktops</a></li>\n    <li><a href=\"#grid-example-mixed-complete\">Ex: Mobile, tablet, desktops</a></li>\n    <li><a href=\"#grid-responsive-resets\">Responsive column resets</a></li>\n    <li><a href=\"#grid-offsetting\">Offsetting columns</a></li>\n    <li><a href=\"#grid-nesting\">Nesting columns</a></li>\n    <li><a href=\"#grid-column-ordering\">Column ordering</a></li>\n    <li><a href=\"#grid-less\">LESS mixins and variables</a></li>\n  </ul>\n</li>\n<li>\n  <a href=\"#type\">Typography</a>\n  <ul class=\"nav\">\n    <li><a href=\"#type-headings\">Headings</a></li>\n    <li><a href=\"#type-body-copy\">Body copy</a></li>\n    <li><a href=\"#type-emphasis\">Emphasis</a></li>\n    <li><a href=\"#type-abbreviations\">Abbreviations</a></li>\n    <li><a href=\"#type-addresses\">Addresses</a></li>\n    <li><a href=\"#type-blockquotes\">Blockquotes</a></li>\n    <li><a href=\"#type-lists\">Lists</a></li>\n  </ul>\n</li>\n<li><a href=\"#code\">Code</a></li>\n<li>\n  <a href=\"#tables\">Tables</a>\n  <ul class=\"nav\">\n    <li><a href=\"#tables-example\">Basic example</a></li>\n    <li><a href=\"#tables-striped\">Striped rows</a></li>\n    <li><a href=\"#tables-bordered\">Bordered table</a></li>\n    <li><a href=\"#tables-hover-rows\">Hover rows</a></li>\n    <li><a href=\"#tables-condensed\">Condensed table</a></li>\n    <li><a href=\"#tables-contextual-classes\">Contextual classes</a></li>\n    <li><a href=\"#tables-responsive\">Responsive tables</a></li>\n  </ul>\n</li>\n<li>\n  <a href=\"#forms\">Forms</a>\n  <ul class=\"nav\">\n    <li><a href=\"#forms-example\">Basic example</a></li>\n    <li><a href=\"#forms-inline\">Inline form</a></li>\n    <li><a href=\"#forms-horizontal\">Horizontal form</a></li>\n    <li><a href=\"#forms-controls\">Supported controls</a></li>\n    <li><a href=\"#forms-controls-static\">Static control</a></li>\n    <li><a href=\"#forms-control-states\">Control states</a></li>\n    <li><a href=\"#forms-control-sizes\">Control sizing</a></li>\n    <li><a href=\"#forms-help-text\">Help text</a></li>\n  </ul>\n</li>\n<li>\n  <a href=\"#buttons\">Buttons</a>\n  <ul class=\"nav\">\n    <li><a href=\"#buttons-options\">Options</a></li>\n    <li><a href=\"#buttons-sizes\">Sizes</a></li>\n    <li><a href=\"#buttons-disabled\">Disabled state</a></li>\n    <li><a href=\"#buttons-tags\">Button tags</a></li>\n  </ul>\n</li>\n<li>\n  <a href=\"#images\">Images</a>\n</li>\n<li>\n  <a href=\"#helper-classes\">Helper classes</a>\n</li>\n<li>\n  <a href=\"#responsive-utilities\">Responsive utilities</a>\n  <ul class=\"nav\">\n    <li><a href=\"#responsive-utilities-classes\">Available classes</a></li>\n    <li><a href=\"#responsive-utilities-print\">Print classes</a></li>\n    <li><a href=\"#responsive-utilities-tests\">Test cases</a></li>\n  </ul>\n</li>\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/sass-bootstrap/_includes/nav-customize.html",
    "content": "<li>\n  <a href=\"#less\">LESS components</a>\n</li>\n<li>\n  <a href=\"#plugins\">jQuery plugins</a>\n</li>\n<li>\n  <a href=\"#less-variables\">LESS variables</a>\n  <ul class=\"nav\">\n    <li><a href=\"#variables-basics\">Basics</a></li>\n    <li><a href=\"#variables-buttons\">Buttons</a></li>\n    <li><a href=\"#variables-form-states\">Form states</a></li>\n    <li><a href=\"#variables-alerts\">Alerts</a></li>\n    <li><a href=\"#variables-navbar\">Navbar</a></li>\n    <li><a href=\"#variables-nav\">Nav</a></li>\n    <li><a href=\"#variables-tables\">Tables</a></li>\n    <li><a href=\"#variables-forms\">Forms</a></li>\n    <li><a href=\"#variables-dropdowns\">Dropdowns</a></li>\n    <li><a href=\"#variables-panels-wells\">Panels and wells</a></li>\n    <li><a href=\"#variables-accordion\">Accordion</a></li>\n    <li><a href=\"#variables-badges\">Badges</a></li>\n    <li><a href=\"#variables-breadcrumbs\">Breadcrumbs</a></li>\n    <li><a href=\"#variables-jumbotron\">Jumbotron</a></li>\n    <li><a href=\"#variables-modals\">Modals</a></li>\n    <li><a href=\"#variables-carousel\">Carousel</a></li>\n    <li><a href=\"#variables-list-group\">List group</a></li>\n    <li><a href=\"#variables-thumbnails\">Thumbnails</a></li>\n    <li><a href=\"#variables-progress\">Progress bars</a></li>\n    <li><a href=\"#variables-pagination\">Pagination</a></li>\n    <li><a href=\"#variables-pager\">Pager</a></li>\n    <li><a href=\"#variables-labels\">Labels</a></li>\n    <li><a href=\"#variables-tooltips-popovers\">Tooltips and popovers</a></li>\n    <li><a href=\"#variables-close\">Close button</a></li>\n    <li><a href=\"#variables-type\">Type</a></li>\n    <li><a href=\"#variables-other\">Other</a></li>\n  </ul>\n</li>\n<li>\n  <a href=\"#download\">Download</a>\n</li>\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/sass-bootstrap/_includes/nav-getting-started.html",
    "content": "<li>\n  <a href=\"#download\">Download Bootstrap</a>\n  <ul class=\"nav\">\n    <li><a href=\"#download-compiled\">Compiled CSS, JS, and fonts</a></li>\n    <li><a href=\"#download-additional\">Additional downloads</a></li>\n    <li><a href=\"#download-cdn\">Bootstrap CDN</a></li>\n  </ul>\n</li>\n<li>\n  <a href=\"#whats-included\">What's included</a>\n</li>\n<li>\n  <a href=\"#template\">Basic template</a>\n</li>\n<li>\n  <a href=\"#examples\">Examples</a>\n</li>\n<li>\n  <a href=\"#disable-responsive\">Disabling responsiveness</a>\n</li>\n<li>\n  <a href=\"#migration\">Migrating from 2.x to 3.0</a>\n  <ul class=\"nav\">\n    <li><a href=\"#migration-classes\">Major class changes</a></li>\n    <li><a href=\"#migration-new\">What's new</a></li>\n    <li><a href=\"#migration-dropped\">What's removed</a></li>\n    <li><a href=\"#migration-notes\">Additional notes</a></li>\n  </ul>\n</li>\n<li>\n  <a href=\"#browsers\">Browser support</a>\n</li>\n<li>\n  <a href=\"#third-parties\">Third party support</a>\n</li>\n<li>\n  <a href=\"#accessibility\">Accessibility</a>\n</li>\n<li>\n  <a href=\"#license-faqs\">License FAQs</a>\n</li>\n<li>\n  <a href=\"#customizing\">Customizing Bootstrap</a>\n</li>\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/sass-bootstrap/_includes/nav-javascript.html",
    "content": "<li>\n  <a href=\"#js-overview\">Overview</a>\n  <ul class=\"nav\">\n    <li><a href=\"#js-individual-compiled\">Individual or compiled</a></li>\n    <li><a href=\"#js-data-attrs\">Data attributes</a></li>\n    <li><a href=\"#js-programmatic-api\">Programmatic API</a></li>\n    <li><a href=\"#js-noconflict\">No conflict</a></li>\n    <li><a href=\"#js-events\">Events</a></li>\n  </ul>\n</li>\n<li><a href=\"#transitions\">Transitions</a></li>\n<li>\n  <a href=\"#modals\">Modal</a>\n  <ul class=\"nav\">\n    <li><a href=\"#modals-examples\">Examples</a></li>\n    <li><a href=\"#modals-usage\">Usage</a></li>\n  </ul>\n</li>\n<li>\n  <a href=\"#dropdowns\">Dropdown</a>\n  <ul class=\"nav\">\n    <li><a href=\"#dropdowns-examples\">Examples</a></li>\n    <li><a href=\"#dropdowns-usage\">Usage</a></li>\n  </ul>\n</li>\n<li>\n  <a href=\"#scrollspy\">Scrollspy</a>\n  <ul class=\"nav\">\n    <li><a href=\"#scrollspy-examples\">Examples</a></li>\n    <li><a href=\"#scrollspy-usage\">Usage</a></li>\n  </ul>\n</li>\n<li>\n  <a href=\"#tabs\">Tab</a>\n  <ul class=\"nav\">\n    <li><a href=\"#tabs-examples\">Examples</a></li>\n    <li><a href=\"#tabs-usage\">Usage</a></li>\n  </ul>\n</li>\n<li>\n  <a href=\"#tooltips\">Tooltip</a>\n  <ul class=\"nav\">\n    <li><a href=\"#tooltips-examples\">Examples</a></li>\n    <li><a href=\"#tooltips-usage\">Usage</a></li>\n  </ul>\n</li>\n<li>\n  <a href=\"#popovers\">Popover</a>\n  <ul class=\"nav\">\n    <li><a href=\"#popovers-examples\">Examples</a></li>\n    <li><a href=\"#popovers-usage\">Usage</a></li>\n  </ul>\n</li>\n<li>\n  <a href=\"#alerts\">Alert</a>\n  <ul class=\"nav\">\n    <li><a href=\"#alerts-examples\">Examples</a></li>\n    <li><a href=\"#alerts-usage\">Usage</a></li>\n  </ul>\n</li>\n<li>\n  <a href=\"#buttons\">Button</a>\n  <ul class=\"nav\">\n    <li><a href=\"#buttons-examples\">Examples</a></li>\n    <li><a href=\"#buttons-usage\">Usage</a></li>\n  </ul>\n</li>\n<li>\n  <a href=\"#collapse\">Collapse</a>\n  <ul class=\"nav\">\n    <li><a href=\"#collapse-examples\">Examples</a></li>\n    <li><a href=\"#collapse-usage\">Usage</a></li>\n  </ul>\n</li>\n<li>\n  <a href=\"#carousel\">Carousel</a>\n  <ul class=\"nav\">\n    <li><a href=\"#carousel-examples\">Examples</a></li>\n    <li><a href=\"#carousel-usage\">Usage</a></li>\n  </ul>\n</li>\n<li>\n  <a href=\"#affix\">Affix</a>\n  <ul class=\"nav\">\n    <li><a href=\"#affix-examples\">Examples</a></li>\n    <li><a href=\"#affix-usage\">Usage</a></li>\n  </ul>\n</li>\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/sass-bootstrap/_includes/nav-main.html",
    "content": "<header class=\"navbar navbar-inverse navbar-fixed-top bs-docs-nav\" role=\"banner\">\n  <div class=\"container\">\n    <div class=\"navbar-header\">\n      <button class=\"navbar-toggle\" type=\"button\" data-toggle=\"collapse\" data-target=\".bs-navbar-collapse\">\n        <span class=\"sr-only\">Toggle navigation</span>\n        <span class=\"icon-bar\"></span>\n        <span class=\"icon-bar\"></span>\n        <span class=\"icon-bar\"></span>\n      </button>\n      <a href=\"{{ page.base_url }}\" class=\"navbar-brand\">Bootstrap</a>\n    </div>\n    <nav class=\"collapse navbar-collapse bs-navbar-collapse\" role=\"navigation\">\n      <ul class=\"nav navbar-nav\">\n        <li{% if page.slug == \"getting-started\" %} class=\"active\"{% endif %}>\n          <a href=\"{{ page.base_url }}getting-started\">Getting started</a>\n        </li>\n        <li{% if page.slug == \"css\" %} class=\"active\"{% endif %}>\n          <a href=\"{{ page.base_url }}css\">CSS</a>\n        </li>\n        <li{% if page.slug == \"components\" %} class=\"active\"{% endif %}>\n          <a href=\"{{ page.base_url }}components\">Components</a>\n        </li>\n        <li{% if page.slug == \"js\" %} class=\"active\"{% endif %}>\n          <a href=\"{{ page.base_url }}javascript\">JavaScript</a>\n        </li>\n        <li{% if page.slug == \"customize\" %} class=\"active\"{% endif %}>\n          <a href=\"{{ page.base_url }}customize\">Customize</a>\n        </li>\n      </ul>\n    </nav>\n  </div>\n</header>\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/sass-bootstrap/_includes/old-bs-docs.html",
    "content": "<div class=\"bs-old-docs\">\n  <div class=\"container\">\n    <strong>\n      <a href=\"{{ page.base_url }}2.3.2/\">Looking for Bootstrap 2.3.2 docs?</a>\n    </strong>\n    We've moved it to a new home while we push forward with Bootstrap 3. <a href=\"http://blog.getbootstrap.com/\">Read the blog</a> for details.\n  </div>\n</div>\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/sass-bootstrap/_includes/social-buttons.html",
    "content": "<div class=\"bs-social\">\n  <ul class=\"bs-social-buttons\">\n    <li>\n      <iframe class=\"github-btn\" src=\"http://ghbtns.com/github-btn.html?user=twbs&amp;repo=bootstrap&amp;type=watch&amp;count=true\" width=\"100\" height=\"20\" title=\"Star on GitHub\"></iframe>\n    </li>\n    <li>\n      <iframe class=\"github-btn\" src=\"http://ghbtns.com/github-btn.html?user=twbs&amp;repo=bootstrap&amp;type=fork&amp;count=true\" width=\"102\" height=\"20\" title=\"Fork on GitHub\"></iframe>\n    </li>\n    <li class=\"follow-btn\">\n      <a href=\"https://twitter.com/twbootstrap\" class=\"twitter-follow-button\" data-link-color=\"#0069D6\" data-show-count=\"true\">Follow @twbootstrap</a>\n    </li>\n    <li class=\"tweet-btn\">\n      <a href=\"https://twitter.com/share\" class=\"twitter-share-button\" data-url=\"http://getbootstrap.com/\" data-count=\"horizontal\" data-via=\"twbootstrap\" data-related=\"mdo:Creator of Twitter Bootstrap\">Tweet</a>\n    </li>\n  </ul>\n</div>\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/sass-bootstrap/_layouts/default.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n  <head>\n    <!-- Meta, title, CSS, favicons, etc. -->\n    {% include header.html %}\n    <!-- Place anything custom after this. -->\n  </head>\n  <body>\n    <a class=\"sr-only\" href=\"#content\">Skip navigation</a>\n\n    <!-- Docs master nav -->\n    {% include nav-main.html %}\n\n    <!-- Docs page layout -->\n    <div class=\"bs-header\" id=\"content\">\n      <div class=\"container\">\n        <h1>{{ page.title }}</h1>\n        <p>{{ page.lead }}</p>\n        {% include ads.html %}\n      </div>\n    </div>\n\n    <!-- Callout for the old docs link -->\n    {% include old-bs-docs.html %}\n\n    <div class=\"container bs-docs-container\">\n      <div class=\"row\">\n        <div class=\"col-md-3\">\n          <div class=\"bs-sidebar hidden-print\" role=\"complementary\">\n            <ul class=\"nav bs-sidenav\">\n              {% if page.slug == \"getting-started\" %}\n                {% include nav-getting-started.html %}\n              {% elsif page.slug == \"css\" %}\n                {% include nav-css.html %}\n              {% elsif page.slug == \"components\" %}\n                {% include nav-components.html %}\n              {% elsif page.slug == \"js\" %}\n                {% include nav-javascript.html %}\n              {% elsif page.slug == \"customize\" %}\n                {% include nav-customize.html %}\n              {% endif %}\n            </ul>\n          </div>\n        </div>\n        <div class=\"col-md-9\" role=\"main\">\n          {{ content }}\n        </div>\n      </div>\n\n    </div>\n\n    <!-- Footer\n    ================================================== -->\n    <footer class=\"bs-footer\" role=\"contentinfo\">\n      <div class=\"container\">\n        {% include social-buttons.html %}\n\n        <p>Designed and built with all the love in the world by <a href=\"http://twitter.com/mdo\" target=\"_blank\">@mdo</a> and <a href=\"http://twitter.com/fat\" target=\"_blank\">@fat</a>.</p>\n        <p>Code licensed under <a href=\"http://www.apache.org/licenses/LICENSE-2.0\" target=\"_blank\">Apache License v2.0</a>, documentation under <a href=\"http://creativecommons.org/licenses/by/3.0/\">CC BY 3.0</a>.</p>\n        <ul class=\"footer-links\">\n          <li><a href=\"{{ page.base_url }}2.3.2/\">Bootstrap 2.3.2 docs</a></li>\n          <li class=\"muted\">&middot;</li>\n          <li><a href=\"{{ site.blog }}\">Blog</a></li>\n          <li class=\"muted\">&middot;</li>\n          <li><a href=\"{{ site.repo }}/issues?state=open\">Issues</a></li>\n          <li class=\"muted\">&middot;</li>\n          <li><a href=\"{{ site.repo }}/releases\">Releases</a></li>\n        </ul>\n      </div>\n    </footer>\n\n    <!-- JS and analytics only. -->\n    {% include footer.html %}\n\n  </body>\n</html>\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/sass-bootstrap/_layouts/home.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n  <head>\n    <!-- Meta, title, CSS, favicons, etc. -->\n    {% include header.html %}\n    <!-- Place anything custom after this. -->\n  </head>\n  <body class=\"bs-docs-home\">\n    <a class=\"sr-only\" href=\"#content\">Skip navigation</a>\n\n    <!-- Docs master nav -->\n    {% include nav-main.html %}\n\n    <!-- Page content of course! -->\n    {{ content }}\n\n    <footer class=\"container\" role=\"contentinfo\">\n      {% include social-buttons.html %}\n\n      <ul class=\"bs-masthead-links\">\n        <li class=\"current-version\">\n          Currently v3.0.0\n        </li>\n        <li>\n          <a href=\"{{ page.base_url }}2.3.2/\">Bootstrap 2.3.2 docs</a>\n        </li>\n        <li>\n          <a href=\"{{ site.repo }}\" onclick=\"_gaq.push(['_trackEvent', 'Jumbotron actions', 'Jumbotron links', 'GitHub project']);\">GitHub project</a>\n        </li>\n        <li>\n          <a href=\"{{ page.base_url }}getting-started/#examples\" onclick=\"_gaq.push(['_trackEvent', 'Jumbotron actions', 'Jumbotron links', 'Examples']);\">Examples</a>\n        </li>\n        <li>\n          <a href=\"{{ page.base_url }}components/#glyphicons\" onclick=\"_gaq.push(['_trackEvent', 'Jumbotron actions', 'Jumbotron links', 'Glyphicons']);\">Glyphicons</a>\n        </li>\n        <li>\n          <a href=\"{{ site.expo }}\" onclick=\"_gaq.push(['_trackEvent', 'Jumbotron actions', 'Jumbotron links', 'Expo']);\">Expo</a>\n        </li>\n      </ul>\n    </footer>\n\n    <!-- JS and analytics only. -->\n    {% include footer.html %}\n\n  </body>\n</html>\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/sass-bootstrap/assets/css/docs.css",
    "content": "/*\n * Bootstrap Documentation\n * Special styles for presenting Bootstrap's documentation and code examples.\n *\n * Table of contents:\n *\n * Scaffolding\n * Main navigation\n * Footer\n * Social buttons\n * Homepage\n * Page headers\n * Old docs callout\n * Ads\n * Side navigation\n * Docs sections\n * Callouts\n * Grid styles\n * Examples\n * Code snippets (highlight)\n * Responsive tests\n * Glyphicons\n * Customizer\n * Miscellaneous\n */\n\n\n/*\n * Scaffolding\n *\n * Update the basics of our documents to prep for docs content.\n */\n\nbody {\n  position: relative; /* For scrollyspy */\n  padding-top: 50px; /* Account for fixed navbar */\n}\n\n/* Keep code small in tables on account of limited space */\n.table code {\n  font-size: 13px;\n  font-weight: normal;\n}\n\n/* Outline button for use within the docs */\n.btn-outline {\n  color: #563d7c;\n  background-color: #fff;\n  border-color: #e5e5e5;\n}\n.btn-outline:hover,\n.btn-outline:focus,\n.btn-outline:active {\n  color: #fff;\n  background-color: #563d7c;\n  border-color: #563d7c;\n}\n\n/* Inverted outline button (white on dark) */\n.btn-outline-inverse {\n  color: #fff;\n  background-color: transparent;\n  border-color: #cdbfe3;\n}\n.btn-outline-inverse:hover,\n.btn-outline-inverse:focus,\n.btn-outline-inverse:active {\n  color: #563d7c;\n  text-shadow: none;\n  background-color: #fff;\n  border-color: #fff;\n}\n\n\n/*\n * Main navigation\n *\n * Turn the `.navbar` at the top of the docs purple.\n */\n\n.bs-docs-nav {\n  text-shadow: 0 -1px 0 rgba(0,0,0,.15);\n  background-color: #563d7c;\n  border-color: #463265;\n  box-shadow: 0 1px 0 rgba(255,255,255,.1);\n}\n.bs-docs-nav .navbar-collapse {\n  border-color: #463265;\n}\n.bs-docs-nav .navbar-brand {\n  color: #fff;\n}\n.bs-docs-nav .navbar-nav > li > a {\n  color: #cdbfe3;\n}\n.bs-docs-nav .navbar-nav > li > a:hover {\n  color: #fff;\n}\n.bs-docs-nav .navbar-nav > .active > a,\n.bs-docs-nav .navbar-nav > .active > a:hover {\n  color: #fff;\n  background-color: #463265;\n}\n.bs-docs-nav .navbar-toggle {\n  border-color: #563d7c;\n}\n.bs-docs-nav .navbar-toggle:hover {\n  background-color: #463265;\n  border-color: #463265;\n}\n\n\n/*\n * Footer\n *\n * Separated section of content at the bottom of all pages, save the homepage.\n */\n\n.bs-footer {\n  padding-top: 40px;\n  padding-bottom: 30px;\n  margin-top: 100px;\n  color: #777;\n  text-align: center;\n  border-top: 1px solid #e5e5e5;\n}\n.footer-links {\n  margin: 10px 0;\n  padding-left: 0;\n}\n.footer-links li {\n  display: inline;\n  padding: 0 2px;\n}\n.footer-links li:first-child {\n  padding-left: 0;\n}\n\n@media (min-width: 768px) {\n  .bs-footer {\n    text-align: left;\n  }\n  .bs-footer p {\n    margin-bottom: 0;\n  }\n}\n\n\n/*\n * Social buttons\n *\n * Twitter and GitHub social action buttons (for homepage and footer).\n */\n\n.bs-social {\n  margin-top: 20px;\n  margin-bottom: 20px;\n  text-align: center;\n}\n.bs-social-buttons {\n  display: inline-block;\n  margin-bottom: 0;\n  padding-left: 0;\n  list-style: none;\n}\n.bs-social-buttons li {\n  display: inline-block;\n  line-height: 1;\n  padding: 5px 8px;\n}\n.bs-social-buttons .twitter-follow-button {\n  width: 225px !important;\n}\n.bs-social-buttons .twitter-share-button {\n  width: 98px !important;\n}\n/* Style the GitHub buttons via CSS instead of inline attributes */\n.github-btn {\n  border: 0;\n  overflow: hidden;\n}\n\n@media screen and (min-width: 768px) {\n  .bs-social {\n    text-align: left;\n  }\n  .bs-social-buttons li:first-child {\n    padding-left: 0;\n  }\n}\n\n\n/*\n * Topography, yo!\n *\n * Apply the map background via base64 and relevant colors where we need 'em.\n */\n\n.bs-docs-home,\n.bs-header {\n  color: #cdbfe3;\n  background-color: #563d7c;\n  background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAA+gAAAPoAgMAAAAwzTx3AAAACVBMVEVXPX1dQ4FdRIIPRg84AACjV0lEQVR4AZyZQa7cOg5FDwMTCDLSQJ738C2DS+DA3k/QK8n4r7KBR1zAtF2NHzFVfoaN6+iI4hULpoeDBaA/uogBA0jYYYeTirPuZ2mRTkrFBPC6l2CBBRuQlKYpLXUhIQH2MwFgcImpw1jguMXUcCFQWH1JjcZSFGCJJex1FtJJWSFqEWFgsIHpOlflrqMeaMkeCFRB6pALHLdI2D5KQrPpcICd5wHs4mYqSRV9ylNIeH1dA0So2ZNOgrK3o9t+f7wHWCxw0CNgfpDo5g4HHvgJfqC0T8HM/jzFREwHsMEGQwO0aGt5Rxc1OdmuKkwPNpY4uE3j+CRR6WHBgR0AnsLVesD77Cv8soalGWiAWRBKuhSaHAsd2qrSrGCscHQJbxIVp9xpr0OxBP79Mc1KG8a4rX077QRIGBqAqLVE5aAHkDDFSN6LfaJZYYWjhSNJuyUJldRkV2bg0GfCLPpXdJJi1xMTZIrgF3SXNStBwq2j96d7oS5w9Ngk0a2bZKs6/4aH/ayBOvoolzfeW7Zk3Jp7jd3RZKrgHQg0Jn9apzxkheMpmTq9SxwmFkw8LOFMOwMOLPWJu89Fz4SiG0Nfth4gLu1+CW/FrlvYCsddotF0AE1V4pBMnNpnT/BgBy134Yjo/XyCy+ahm9XUsq9zE+Oz2FUSYCscPRz0mHxKKqsWlhx4AsjctFHfDMTe3F7G3VaItiiZSG0gAwzxPYrdL0WwwEEL611ll0ysLM6xuFTkrkUfbBBwtCG8FXtqbxsoT73g1eQ0is7ZlnWscHRJyGZ2HpJRzMms7e3Sx7qWu0ZLc6xWda05z1uexHKqtdWcSCfOW/OeKxw9UqPIpyTZsBJpzpR20VswJX6sQ0dhdINXnhDEGdKzXZXROIfOYa5w9BiAZZ8sZTKYOI6FhSXs5xnI2LXccaS+P8VuBm+6JEpDHXtIAZNuhuLsP0N8geMWE76ZEri7Uq31yV5CSzhRT6/lXgyHVm1Dj27w9ekZaalSUyZ0QXubLZ3/NQeAfoQBruNTYkGt9eRQ+29JLXYlfkICfsJ5Bj2iu9wUk64pyTuv6DoRr2ZK8r/lqPSc4Odz9roEC/0jsdSSnlgq5672qoN3dAu5+2z/hxdC974hhIfF+3VS9r/n4FR67JAnf5RgOFXuGkWCB5NdiccDxTu6EBPGfTES4HHvR403i28uYAscVgL1T/5RUtCTyVRya7Y5tFtsQnpG34/l7omCqetMPqFLkBoVE8UCxyUOje9FMtnYmAySVElX2gWuGdk/oV8oTTucgq3QgWzos6GPyzF1BrDCcQmX7kUyvgVJqtTjwlGzsWEh6/+/6Cl3twd6v7jVt+8NOhLXaVrgaGNL6W4xYTAZhMW11LW8Jjub9rZPaW8b0VTuG7oS39BFKSpds7jeWOBoof3qHhsMBmnhrdS1vBzTBkfKaB7h3bfHB3R/Qc9Ghfc+HVjheBrR/lESxmSo1BUemMpggwl48hJy4ymDb5lxoc8X9NF7FRO/oVjgeDGIfJForgaJSh2JqOphqEFjPz+giyP000SBiXt0hQtYMyS0raEvcPSoccdTornKagd6vkKbHhZ6cXKqr3qg6+XLK/ro6KLznlCE7igWOF4MgvNFkoQxyuW8D5oDC5fPKUPgvaPTDdMbgA/o2QmsNC2h5L2jYYWjYq8csVfKnpIgnDQ2Zi/ISntayOc8UPQfMEM8crN39IvchE72hI5HR7PCAcCe+KHpfWocwmIjnNldriJrCRH4bUfdn1mfat3+Bn30FT+Fj2KFAzmyJxr3fXsyCGNabOVyENCgyjgSy+7vlvda15DnX6HPbmHb433pAoeeJlvw0Bp+SIYxKZezju61XTBhvqW6oWd9xxPdYT7Ro/lcnbo2ChQLHOjpUp46v0mc9PIHA6eFmgQH7+usj/nahI1+U+8GHuhch6jT56viBQ4VpKZIS9S75LtCtvIHfzrrJA3X3qZ19hyzXDsgdeVfoZMoxBxgKBY4+mOP9oa3SdiQP8yns37Po2lvAxd7H7MqwET0hp6v6LPXUKE7igWOftezvdfvEotvfxh971VCJ6m9rbOPNuaSuojy8S6qCbRC7oXz7AZXOPpTd9kEzJtklj+QzeAV1RtqbxP77TmuxbhpnDcTDOy9m+uFA6TQBbrA0W9aosH7TTKM4QyCh8H/A2lqZPFoA9r60yfAFJHHHT2Yr+hky+6A0MjnhAWOtiTbxmDxkORGPjp4+PXfP8xqZcn+krijs+OpV2l3oE25lEC+wAMshT4K04MVjl4NapEfdegMJzbCsI4DX3yxlcWzK99g+UC380AerSFe0Ud/B9o2wK1dnkIHh4Aljr56PZWwVnMbuRGTcPxu8H/49bssPtov5flA768bNMTW3w4MBSl9X7hTm2CCNoUVjufmqD65S2KzGBYbm56m+A2/jUmQcDRTfke3C7ofHXNeEa7DMBS40APNF0scTgs7tAPdJGWNm3688OMfAPjxG/5UWzxLpQb6I3p7q5DCFFO23Sqf6AYudFX+EsdGDw9qym6SUbuCfmHw68efQge+UCNr2VrWV3Rvl3d1qmIarfONF/TAhK6aX+KYGsKpthcs6isJ02JU98uoO/zkS+j8rNbQAmbrJl7RZ8/FKX/A+u420Si6gBS6tjpY4WBo4WFnwsurL2ZtCcTGILEydn5e0IfhkOCqrzaiFqPnghPQZJGC7Mu1TeG4ogMDVjjIa997qPNo1jgYRjX+ibb1//CroYfBbAPWiO6RN3Q78YBu8d2kdKLzjp6wwFH61oPJreZV4sS0mATB9oaOeh3V10d0lfVzv+8W7wJCNaTYsLiiB6xwELRKqVbUomSSZPlDAQr9pxy+0PmW6Svq5B5OR++3HPJzqQudIBG6BaxwlM7yVnh59YekdkNqWW9q4tTS8JNJlkxfHYJ7TMT0iBrPeJS6n8dthoKB0B1Y4bA+qaqQeU1YEJuRTqqP1eZW6eeLjaHtQvVFvKJb8npduMG8l/rewMGu6MGEJQ6/m8gOfiuSsJh2b+HV0vAFf9gYqi1vizX0RoK+dJO3mCCLdzRNe/IZnSSBdY7siy5bkVhY+UOToPj1+8dvJoPtf5ycS47jOg9GTUCaa+DaxF0Fl6CBvb9/qT+QL3VANqNOywbuA4Gk6JRFis8I13A3Qe+hxOQCsj5yECzf/jarXAT0H0ynTY4seeTQEBJ8PZm+pF6S//Kf0nj9YFoL6TE4X/B3LffKUF1zyLDUJIqUnNAJgm5zFPsXNYuQKIc829v0bRX9v/8pb003EQmGmDwRvMjpW+GDYKg5+lGazj+hD2Hx7HMQK8x6iCuaDIOfL/1Q0fnmRvHXCOWrBmbNhkp9XX8Ku6MpqPes2nBkD/IRhzOPBCHNDNji7XC5+OcHdMZIrkCfoFsey5fNmiXoWgr37nNB1ijoTzhCEMcuiWLXLBkGuj7MR1Mcc4Hu77UsFkNV9PrULMEpZMIX/4RuDziCiNz4O+9ZVIIOO+apOOZndAPdZY6K95/Qe1nInHNj8zP6+Sf6PkcsPfXff1+U/tk9bb6muOKYycOvgRPFiKl9XMp6ps2S07UImfiFZmkl0L3JERTwFcqCZANSGzK7+ZS7A1R6WkSng40XvkKv1o3cl4nvcS3R8y3btjliMsxjGiSX/nkzWQJOILlYYSfosYPNvMB9mlzt88GLX6BbQd/gAD1pG1O8ICYaZP+9bP6CzpwR0ZlN6PC7sCO0k3OzKpY5C/q5z8FXd89vUNFVsondXJH2jM6AjG7OIC9w5bEs+agwpKY8TeglZL/HQRd4tYL6ZJHR7CC/UtGvhD7jtvAlv+u5+/q9fbmW5gpdGe2Avs9BwGhmK0gBTfrL5vky+8+a1rb71rjJ5cadAjor1ScGWBRbEVZDauqjd17QdzkIgSe5ubTQ7b+O0svsP2ZF//mNApLtp2CUxVlpqeI5oESfWmT7jj4fcGRLmZNCX4HofDQjlFca97QK6JJ20EsdWXlG6CqQip9C71/QY6JmnyMW60ARyx6vn3l0nRSr6D0Gz5zoGmNAL8WjBZ1iEXknOvVr9Jzn9wccRFbym1SjFN35Oil2FPST/8GSa6lofNa4K091OE880i5zfolOrAL0bY7UH3lrd7ID7IoVUvM0WQn6p5DNUOgeNz2SszbX6CdpA13bEpwV+lHQ9zlw5qWHu6IDufbPXLZvo7Kn2N/mJEKGjnx56+tTPxhorvld/Yff0GdA3+eQkeIpJy0bmkjoays+Wu6prl3FppkzloCVRtvKTvyWb7bXJo/v6COg73MEL+vC+lAlFCf0Opr5bIzMFTDMpbRJGZSKzvoFnfNzvruI3Pwb+lnQNzkIqpD3ekPc7xP6soPPl9k/YysKg+m0oomLvFlBx7qp6Jwe0+32BX1mr9V3OThjYGimGjaps5a3N6jXmmHTUl+xiSsXxFTQa4nOhTSP8QX9z3jRfMIhq5shRIFj5N+8mfqjToAZS1HI5KUdbY2O1qkt1+zmVCJrA3084CBb21Pm31O+p79OitXsqVMRS2zKyAWtAjQ/k/w/q0AxRaVE1rmJvsfBlLN2yPV74vJ0pjA0mc1kXXq8kIsVjuDZXcqFsOTVeim6NXrPSdR9DmzhmTvknOoMtS+2MKUdJftPDBUjkw+/RmLN2QvmIK0ma3TLHZ97HKCnk0kME/PzfgmJ92RzRrsblIFrwSZXz2IVvUunkWgLfY+DKdklCeZfv11C0vA0vJYu8ydv1C9G2birDRtXYQYq3k2is0I/K/omB+g9a1yNjAU4eQpbYOIPpjTGHON/bqcZqdr/jSVRPUMpcPMlesuVnuMhRy9lvCQHWWTGKXHTZ/BMrKDHBHnaRNZsAWLqdlPh6fw7+pHRtzlcBPUo4gLJslTwsWx6hIIP+42W5nwqAJm9lSpgVHw7Ttk0W+h7HKCPonxxNBXfMIHpwxwRY3wnRl6TIuSEeHqpAgarH02/EfA3dI8O4iMO589QDS5+40RKJ/8gIhExC7JPpp0PbNH3xiivgVRzXez9iO+tJnvYtT/imNQEVB8Dwk4SOf45nfhIFIABVK4Jrf0Y5VpHxb8vdgsb6v439Ecco0ypUUQS0rHgm5ANPBN0Pqj9rzy9lgZydie/j8BpOa6KfoK+zwH6WYxNPRztHitObeb4RLzaOad8sMgttqTgeYbWkFDOoKt7vtdxwDT/CccoDdX1z2Y0Iw32knvW2JsiydXkqSf+rAqeQlm1mOdcMCvR/co8e8YxVols/Cw5o1Q58NonhZpsmvxBEfVq1M+q4Ckga2+PvUcxmQWdetpHHCyynCOZMsK9Qe8IPbKYYkdV1IsrZ15dIJocujx2Iqcl8q1dU0/7jGNw+BfP7TZhNI+3DSsB0YmkFlHns7WW41CaPPYcfWhRHaRLcTzjOJlZHig1tqR2hN6y/WJZIfjCcudV1poSnNYzy0xfBibmM45Wu86DdkyxFCJJFV2L5Sj8LFRsjVeZ1wQMp1U1MXpYa4JOG/ojjkY5RlEMOXXBG6ro6KIYha81/6livUY7GBGd1hnsEue/pM0ma+1yaEqRt3B38/Go4xL6RVGEOXAVvbGDKup8NNR6ac6P4sc55typpBr2OQif55PCouHjs76iiN6dbRsbXaFreBF1yPSjQUVRDL4TdLu01j6HpnyUypllkg6iXtF56crld+AqOl7A/zl7gxVXct9/Ww4laLKqP7j2vWzmKvxbvHt9IbmfXEovD3OVL+N8EA9K5TTtGuY0p09UVU9sy7IsSyeO6Ou/f9SflSOrtmDHCkfo5nOqWeBgbunb+SzUE5Kn2Cq6D5xUA1xF5/HtMtQvf+z6LX1hHdFt7DEY1URc4JBIPw3UtfKWdf1N9I6jBzvETtD5egfa5Z/5v2aJzfbX9bonRCf6IgcdbLfauWrflNVygt4C2jMgdYqOFRn+8m1m80BNT4tmK7LwYRF9jaMGGtYhAtR+NpgarQ4fMqX5Hb+iI8ku/nJ9qOnNE91PTcFRTdYVDolASdUCBkzRyw4Kkt0MwztKgsNXdNwh8Jc/eWyuyUvTX/oMFAr/bY1DImo1iKhVjpF3auNk+nCkRPKhiZ1ffFR03Yl5FcSsbyC9NNurtoaCJ/oKBw7M4JV4aOUG/yF6PNePvNNRc4L1E3TnfNNTyc3ramZD6GJVs2Hfa6voCxzFtX57SefHANtc50ZF9ySJGsHvJ+gbRnqLVHLZ+jEdVLq3qdkSj4saXMscNbPExs3KKGn4j4rekSMBSUXZAkTvtDCp5PQdyJhzekZawOyt7o1FDjoaHSII6OocJMRhVkS9G62l18FOZ97BBvqDjCcy5rg0gsnbxqtBvcYhjDpIumFzccPdb+xQjGA+9A/MNCjCij6gswYbXYN9sy50Z5gA0+/Wr3SFA2Of99v5O68Gt9eNbVgnUe29cY7u8D1d1Oga7JttOnLbMDTCjMnVB5Ki2xIH9s/0yRrL1qEfRNK444MtziPpcUVF58wSUO852Kcdi6w5Didng9/AM4RpgSMhcHuKMN8PO1p/2fG5CUSelXc9Xk1JJ4PMVwz2NtFHfosdZ5u5gLzlBvoCh/58yaXCc/eNPgIuEVKjc6ncX52wcYbO3vOv8fqwNpTpi5OQHnHL12Bw5AKH0XHDOww+kmWyUGaLjm0XSJPSO2l2SnCWpI6TnhvNhE6fExsWiZePscRh4yQdcy0uJxHdo7rGW87sh8iGDoacKrqNJeii6LjjNvUc0B0cJRaB/lD/PQffiSIYMRTpkuOGiNOEywIZd4aH3V7QMR9Cxx0xww8fFk2xBdzOTNTATE9Hza84eDlFNvwJEXglAmGCacJlf78jkABtInRsT1DHuc6AfNtMkDU0/1KD8cRKvtUSB68GEehUinBSP5BOaiD9FFINtmRno9QD2v++JIn7tN0S3e0oA8frxs4ax3mqHOpUqgd9ht+9pkskHXO4aG5odqDDnQQd50Nf6Zd1oWvNVs30Gpy+xMELItSp2E7JHQ8ql12zxk1v30HqNwTRQDHCVfIHja5Hf1gmS+LFodYL+gLHmUjVqb0Gg4WwXD3UNdpZarKwN1qWTT9GbXQ94mpKkTVOh7GsZr7/Ese5SOfrBEPz6A6/8bD9gXVx2Av7MYCuqQGNjsHR7WKbhb+gi1hTKN9/kaOK8KY4/E+R7SzFgt6qnD+WkY0uH6gTy0ZHzp6L+Ux6WtgwTIqhvsRxLtIGGu1e3U0FTfFi6oYa9eWkD1p1sE6sfb3GOjW7PNpEf2XzbMDy/gsc5yIHG22+pA7o0V7ggn03p5sGFcUEjf0Z7plpTi9HFewterulNiX6IkedFN54AQ5zVpupsV7WLUeiC0WH2nK83zEpq+GvZzFe8YpOgpMAkxUOXk4dykv2CnZehtUIP6kt6fc8SDoYtdgwK8kB8wUejMPvTH15ftUAkzWOYvtudSzDTomSdoNxnW1kDlmcI7U79fv8MxJ9kxtWZ1OI/pkJT8/hRkVf4ODVaaTzOoTViQ6pzTz1z8HZDcdO7nq2jwzL7dp28Ne68Z8zq8RW2fimBW2BA1dwaUaJEJZzDEGqI0tM1NlNI77dmC1wyJF7heZns33OdIDn6OdpdVc4Si/az7Mv397WIslzaemW3GtupXvQiif6V206oNt4d/bFR0Vf5ajuPD2Qo9XH+wo0Oq8h7SKjSS3MOZtNEEL/1HPfobefj0rpWuOgEkZNEuVFHFxYcKzTSlIxBBpNfsNx9XtB3LWd9n2eclTo5diPIsDYf4C+wFFUcfAlj/LtEp0RCiqBkQ7irhGsKrby1Fb0YfYoLXfMjzehN2uDSkp24e110K9xFDNy1LS1EC3oKFY68dNrpLK4POV11LhvT3RqhbBAqzeytZDauPM+EF7gwNdXjnN4FQ36kbG3qizhptWFQwTu4+B4bBVdr9Yx1hvZDvaLir7GcZ534Xz63Gv+uPsUUZEj3XvYVt3PUXejtorOWq1E72z09xP8Igd/WYv9UhQijrNbim1UT2VCntqaW0GPv6C3iT7M2ej14i1XOPhLbn4zGBcisP3bfSCidUiy5ez2z7/zmnfisWNEjn/jKczH+d1sY5mV2ugVfZHDzqogFy8+Xg1pYRHCPTw32AVq/34ryfBDX0Yr6X/7c15/Rd/tIXSefXm9ALDGYXz8Bnkvopa9docy9aFYLwnMvtzpfvkz/070PCXyxdfNTZxAWY3+vtH5aksc5TwN5DeK3hC/U1PRd3Pr+Rk5q/4gsXJWr83OMp4TwZUNmucYxuXhtiuZ45DMD+gLHOUOG+Q7RP3/GxBhrTjZ8PmWCvniDuI30yb5/93sKdLGXLlh+SI317jq1E/Xux7jZ/QVjtoVGtoA8UZRgu07Ddk9PXJzJeNamMwDZnNPLYSudSss2fRbzq/lPlvnQxGy82XjNGmZDzbzGgdFznXfrlZKETekPJJnP5Wxsmt8mzwQLezyeP5uIOJE9u4/3J9Sx+5z9yXDRGnEIJPXnYN7jaOKUPcxmtZTRC2PkguaghN9/4+2RX7ZjzxPKe9lzgOXP2DP533rLs3OL7+XTYg1jp9FhjYRJYI9L+2+WFb/EHrYlceUZuZ8oetry0Lm1+9aWbONy8MCBWbeLFG49bTEUWc8WAIQ2fJHRwrLdtPnVPMl0Yd9GI8pfVmid5Q9mB/554+6D3YgmAD+FVwDwIG1wlHnw6Al8JLPbNOAEf49o/8RyNsn+pc13PND6PAeRXrzrv+mlSDFeZ3zPu3h6oyu9ddXOKoIjoR7+d0ucz0RpGTnrXp+fJvon8YMDFdzoWfEXJ+Cd9l7mLp9fm9aBfUXci7W8eJLHG9F+qtIs0QfWRBWLd2JPkc3e3DjsXG1ec8x/i+G+80u3+ZC90LeQM4zIPcljrci+xsRmR3Q8dLHRH8gxKwRHbaLj9mKs92zQY9hVxm+0knv8vTh0NPxf7HA8V4k3qKz0Ix0fFgU9Hmb23NXYqJzDe25K+n3jKHy+9Nh/IUsM/GeHEfdwo4FjrcibbxHlwMuX2bYwPH9PtFj3sPtaZNPdAYCaa/iufTVHNeezqxvTQGMnUqvZNHnA9Gpv+V4/Wa6EOoZ0JDI0yhAnJTyIWZbbBN9zHtIDQud4V8ttcVk/werHUFpIsaUVq6BhVT8nqOOB2SQKObBkIismpa5mOWSrej6gk7RNXF5bkohbPArRzFP6hCczYglxW85XtFxIpz2cCO67fA9Tqp36Huuv+E5yYTGhzZkEV5x+dYbSvakjjonbxxj/i1HRT+pm7un7Uv0zhidxuhctxB61+ia++X0nGiGwBInw+f+yWkLp9GxpteCME02wfnvOU7QR00kohUP0YM7a2HOZJLN9lP0jQ+KTACoKW3OcAqziOyyNfo+K/RpxzQnwPZ7DhtVpKZZ19gOI/qwYKK57Rx9S3QXeuA9fFhq+JususnfmOTohkaHte9ZJETFxn/PcYJ+lIdtaToTfWBppiAAoH9baPp+om9CH3Q1ILRKIaPTf2vOdvMQ7WtJW8+SZkscJyJt8GE8vdxQyWfYxtRAO1NSd/uU7p1vv18meheMPqZeqx+csztnLKboSxFN5nBkLHBUESb50tXKqWWFkDA6fQf6bmMTusUx/7zocK418KHz8kygiJlspNpzUJS6ljjORMrVBkU0trEVGKfo3XLyGmfozPDKrslh29+Tl8z4KxzvRHi9iGi7EHEVFf0rh4PQ50fOEj9qckNX5vGm9xnWy3J+jUPPeS8SRSRaAN2l8I3oHy/o8yMbQbB7dXAGvjHo/SSvvkx9B+kaB88HvRHpKSK3okY7l80Dnx7+gt5xfElXC+7WypYviR5eVDsWeG3wdm2Bw34W2SDSpGY3Bts3os9ziR/mRnSd4dkZFXpAaU+uewCxHltN8ptJdvDrbQscP4uIgiJAl01M9P0/9IYGuQo98/Qdw8SsZnYNZihldeqaY+PGAk5AX+Qw/6tIGxAZRJeo/x096xbbkIiM2OAOzvtSAeysOMbZKdXWOOi1/DFEL0c4gu23F/TrW3QasUdg3+50ZEZ5hQNBIk4pX+Sgr/rs6hBJd3szRGm1gn45RW/DaKhpXmdQ7anxxQLbLOBEXbAtcpj9XcQhshf0YBcAOlPqJTqOpvKIBE1cdk+si6Hi4NnciL7CIYBTEVe4cw3T2MmxE71PdG7zE71WG263jLGsV+DJARV33CVDPbetcIjkjcgN5y3oWAwTulX0/Sf0DRaNDHhO+WeDvSHA4B6TQ9ndEm2Rg0kcaq9j3CGCS9mEFgvojOOzEkwJmqPWGbyPVIwbDbQFjoHXIQF9aLSwdFdylMpqFb1P9KAIlXWLvw12nDS/QUphLDDQFjg0v5yL5DtFMS7bW/Q2Kvo+0XcLWJtlit7OBztGfHFVeS0gtsLR+VmvInJm8FNa7IOjEb3ZGXqf8AZ0WHM8kc1rx4I2/5AsjlTOa4XDS3+pIrQoG85Ig6MZ0I9T9I3o0LroQX6u51ogP4kH5zbWtVzh0IffijD7Y4NcQcfOdkUPoXe96FYPPkbmx2G1Oxj2dTmjuY1pMZY47uV4dBVBvFljzlZxoAukUUp0s3kyGfWjt+p26Zkj5652JQ0zb4d2pjS3YRt6gcM05HZMi4hb2ks3Z3rrvaDnoY8x0cOIruKrGIi0aFRe/87sVZyd6bX598+/f7Kca460BQ41lD7MQ/K6E08LNljt4Ej0KSN0brR8mKOcbjNcjt2/O3U4X4fHGv55PNu9m2ukrXLwrkY3OZYPAxY10DcaRkOUJ+hmHzongaeXaWc/jXGvDqjQ7oz9sTxXOGyRA+tOiuiFakjsBnScndxQevkV3Se6XLi0y+naA6+ffgtShNqMvsoa02p3jQO5NoqetiiZl4AOp6HQ9ZkT9G2iq+5354vB37LxF3VNwhRxijSfe/ChvdZFDrYcD4RwMmBJU6qMgQ2gHUNsONH7f+g2ULA/ao/fCWn9TQfIk6CmyItdme4WObh/xfqb6CRNIlCfsAp3LH+HnrfZxfL+u9DDnP4H8u2AJHCrNokOfSveRuhLHDWOeCtZCfFPWFOHibLjA/CkNZvoSB30kVHgjUMt+Toh0V3LFt2YyKbB3q0LfZGjpoWiCQkDmzPYqEn3Et0qul7/Q306MD2TdDuvcF1rLmuoIx1fF/oSh+H1S6hBk9LpFOGWfYs04IkkdJR6uKpP99MEsEF0vnk9RTmJdU10GYiLHPRLF/9nQzgeDHUsVqVAGib6RKfz4KLlBms6cxh7tVmJzrSa15KJkPtuaxy1uAf/ze74RpGhjy6acYJO9+vs/vpgnKj4Bki8Bz09qS+16fiptNIUXOFo7Ij8Quo4UjPScaDHV3SmJlP333Ow93Lngm7xgt5TX1rMW35V9FUOmGf8QqrBWWv0iOMMnRUu1Qe6Nh9wSkC+1Qba1w1TREF/pWPpQ+gcKQscEimKsYjsJTtJRzCPaITu/6E/cu6b6Ar3dQYC6gjQSblxJzojoj4Vogp0yi1wOIxR+rl4RTESHbZcIBO0ijc+sMJW92861QvbxyRKdNqy9XTu5xTfhN7piV/kYG0F/hZXG9VSCq67TtAlInR194M2hecNsH4pPuVqwc9WE/rOfeZFjk2vcObTxsNpKWG5/oruE91uZrdEd8X3Yb+hIyYD7wencV2TPUzPmi6AnV/ZGoeMoqIdXjQPLSXuH8ULetPZvXEMoQsaidrhZx7FiEe3KCtxom8WrI6yyIGj9WX6wrtUS6kN1J17Qf/UHpHQ88jIocanRRxQV/IoHa+afk90Fzpr4qxyDOOiX7/12gMLugXqzp2jmwE92OODQWI7ds887J6OtlIYUfOGNHy34eRa4dDr1Ax8vfYTGon83Wab1AfQv17Qe6r04Gqn59Imp91AXlVGU0lnKE/d3pizZ5HD0w6iSNTZpp4sc8YGz5kX6B8FPRONHqWgwSb0PR+kaMNbu5UBKp3Rxpzm9sYq5YscXTMiRM6z26cIBlGYv6IPu76gt+zxTgto04jp3FLF/gRXyPM+t+O5fAnHEbNFjhY86shDm3x2RUe9z0RHLvILxa/sy8HFnuZiZ52e83z/m+6jTYqHjY1BmmscXqMu/eVE2ThF33EEAv/WJvoD8h+0YDoXe6wnjhr5b6JqPlA5oI2NQZprHDfTyzBlEyVYHInonQdfBlcEYVbQkcYfKx5sFxu3/uM0vILopnzaijVd4ziGBuDbiylgie5CH0K3HaWPmOdf6j6QST+A7lP6APLxatEPos9Tsrs03t3utyWOeykJ8TaXV0GHQZjoHeic3T6Ni+7Q4n3D+jkm4Z20LzMJ0b9UJ0O92O//W+Wge+809ug9ugs9GLzW9ZpE14IS6bWBvpfMDMfrXEz0eVx4ODJzH6sc3KOvZT5TgutNeGqEvjMX+SZtnC/K9demTzSg99NSk5yjgD7Num5jYyKSRQ7aQO9LeL9WDazoub1P56mlymuZkynypVEquGRpI4861BWz5TTmOiWXOJx3oMSw36DnHgVc5moj5hloA8efdPCuURcdnI95Xu2CBEfRrDMvwxKHBuDPEqfoTnRtymmjJNH5+dAilTufaiyeBaEBr29I36F+DredHXyNQ56jxtPCmi5/Rt+I7qiYzJmIa88neiv7gJjWhH0r6fChNP55buzt/M7WOHT++8jH8YwNLy9qjujd2DkDwPZF9K79N9YWi2rM3DAX7RLVnXT4022is4OvcGhdEXpcVQxgLeg0aTajStqp5z7LV7XLfmtCth0mLE6CvRbcv2Z6BxVy5dJtgUMl2R2PluHzI7pseKGzcBr13Dc/L3T1gBbYQcacduN8IdE5yEWe5Xu7BJY4WqDLtUC/+wndpdPUexmgtLGfP/h5orsySfUaDMnRTnRT2sLp1GLezQUOHLaKUiflZ/SN6I0lZ7W/irlN9wY6DzdIEvnxb7Rg6wspbS+zrS5wqF4oFtsp+B6dKCF0yXfTZCVkKvioDinel2UEGKzT3uXPHI3HjRY48n2cBkT8hM5SaW4NGzk4bvqNJSvdkMoYXaYKJFRD932D3ic6jhsdixxStfXYxc/ojIkIHAhhiQv9gPO95Fgqr3g3RzGRF3Tk8tREIfI1DjfZAgMOw5/R1Sib9B12C1TYhAo+tZbQCcPvwUcuvc0LOj/UzHHYLlY5biZb4MbQ9J9Mmjbgh08hZPHTYH/UlIiv6aW8RLre8qUE5yeVDTahS2iJQ19wC6mJN2tebmPWaRpbzFhGfKeC5wHlhiXry2A/cNYTG9KtNrqiiJqEFjk0rCRFg/pVhLdzKmzql4xp+YKC94Gd/bLOrkm9k7mX6Fv0jI7t9bBVDtgCXXrovUjH36Cw9Xb0wE1q8XN7j7vgbOz684Z1RlGEpgyunPoXODKoKdR//y6y1Wk9Delh9P6Eqa9/szmdGSpfvTIHW985KDvIh04Xsb+tcOhgDbVWey9ChRNQ2GiYjvyGf4SfYmoR3ogWCTf01HdoL2AN6iZ03XSNI7IfYpp+J1Ijs8YUYcM4slpec6gj9/POCZttSfeZom4G7AW5r1hZCuHGCxz5v5ruJxGL4iNupTZkU8NqZf3H2KGRNQttIqiq+DrTY975GX0twcZY4HDjJLj/KNKLjzjRPdE1b88c8ezvLA1TS58xu1ZIVWsCya2UBNdIGBw5CxxdHw+J+DsR7oMKg+j89uu8zYzyjqgEXJi5stStnWUVhXkwqHh/zaEhwmrVEjn4NZuoaJtUdBv5wyt6pCo7m6vrNNdyguSmMa+bdjVzqljgwHDPuAC31LZFJje+zW9w/251C7cRrJxHnVj8fN174BZVe0VHlu6hZMZrHOb4XyIbRuK9Np6G3Q2RatnliG7j/Dx2Y0pVXtWQ7RlOzYuxF4o03Fc5OqZ4iJzXn+DLVnT0e2khylHJUzGVy6MYfeNsxCrHYBP6KkdAQ0DkOC8gfopeUIpnHaWn0WCng50FS9XgRKc5p9Egh+Yax4CGgEgUE5N/ITq1eSN6OZ9XZ/bzwX7nu0UWUqkDXd+b0McSB2JgBkX4vKP23Pfo4xwdkWUebO29kg++W0cJCZKnW4LobY2jSRQiXl+IY7Fu8KVwnKLL0kAtP7zAKbnsQanw8UoukwfovsYhMYm4mhIymhn5ZF2t5OlB1wN6z8JcJMaLYV1Ssg1tBf2OwbIBfVvjoBtrs+3chEqZcYIuzM5Nxf01/P5eRl37Wy7s3IwOfojn5Ine1zhY8a7bxsdRBj8LeqpVoveyFKn7akQn+XGPNNK78OqHhAr0fYED84LM/tLJ+Fz+RONwdqvo2BO5VVXbznR7aBbI0/l7/RBWv0T/LQfeFSJtnC4s8BNUA0YxO3z9fmqjE/0+8JAmBq2+dqzhdeHbEV78lgMh1xDp1t6WW2Eskjghrrco6G4IdfI4QT8GmDQ6lJgA3ecGBV2/9vF7DrS8RDoD80/7Cl8fYY4420x0pN2tMaueJGBS87YMxNxqoyPZxsjcIQsc5UBgZIWh9zKc4jSLsSp4RdfAd9xAMR8bSNgXtbor6L1YJ070NQ5n14Oj81TmRnYwqrZVRa/nMkR+f47uXpvzDspQOop8mdI1rBN9jWP7hUiO8yPbhxlX/BR96OS6IEV4S13PKr50bTY5ofgFsWugn/sSh5QKkpO9F6EJeGPlAZ4vkPsgGMinNrmB0G9HYXKKWC/ovXRWYStWY42DlkCrp87OPSRi56R+MJyMqw5xd+O6laQ3tibN1DaYjD3KoDgMh436AodEOkXGexG+qgfHF3JkFXQ5VrlurY4yMmFxMmpGSg6KYE6SfYEj5+F8TR6zfN9VpOt6CSXpmbSSdRTV//188UerBjIN6PoYpX1w82xf4ChGkHqZ/lprT7DLIxNA6F2gZcMaMVjmpbrfe7kpVuNRcxNiUNzYzy1WOGiNpW6hCOJb7lG65p0eh8DcOoCOgk1nFVxyo5EbEG1oQzHvBE++bsOGHkscbdAIwmlyCGR736pCYjwFbkb0HaH/pdElAfKbpX1OdEGx6htN8DZWOKoR1LhiUDuUcV7Hq+NHmNCd6LLozhrdeb92g+cyiK6SGNWeE21b4qhGkBcRbH+ieQ4S0DXXseeuK5B6qzY6D6OhLqB0I9EhrG8H/czXODaIlDIPYKy/uJc+W3LwUbkOZMB8XUVGjWiVsVDQvRq81C62rXFwm98VCjbeep9phvP1aRZqcyDRkfdUkCWZWmRL0ETt1i3RezV4s8GFvsLRjYuj4tzwM8ufP2pQQcvBDfSey+6oK/5Wp2zm/N8s0XeR8oMHNowXOMxoBEUV6ecmDRVWDWYRenI0nfdgOEFPYfgwbgYRC6FHxmL66yFFWjS/5KjG3KgiAvhhuHOwh9Bpwqdj1fO2wR0mzDfwAvhE39MF0fPx/CmjaoGDloA2OCVCpvPhHq+DXctVJ3pmXONmW6efGuOc5Q6A3kY+rvwc+mOBo0ksX50izjNyCtrG4vN1sAtdDsEvoQ8B5Kux/a2THB9o5pbosPX5M+eNFY5WOuzOvZ4N5WamHIc7mh2DvQt91t39tlw/Ooe60RYI3umexY7nf13obvRYsOi/GFY4WrFJdq66elHIDSsYNHsKjAya9dnoX0JHwA/Vdfqpj3y1gRLXI3MtaSOFHvHAG/oah9MSlQiqtvNx3Pm5kziVbiT6NiPHrjMfU6Yb6kRH1xcHzvbNFhO6+lLU7k4tv8Sxcf1RRfg4LqsRvJ3dkNuf3XSgd9agzJVEAL2EJqBP3bTQFbq2bduo2p0nK5Y4OledVWQkFmWwPEez40T2hJ+9/VPoL2fGnUcxO8nNh77AaGNTewfnAXpL8sV/z6HW4HERjBGWyyI7t+vY7J7oylvwJXQGTlFp7QLTDRnRP63YzTY1+SZy9Fw6Qxc4EGrmaXYaRWj+kr1h4ZGDP9HjGRd8fRrTjZVTOa+HnBIafYwmmVas25ZVH7Ktq6ukLXIwPY0WGxTBC1f2g4oug0DTr3Q1ZZXMlQTWsS1QSMSBo29Ge2bRpioYN+XtKgP9LtZFDhZFLyK0wAp72abECbf0Jn4g3+tWSrsceWRDDZo4rO8x6wZt+qqH+Sg7AdyraUscRm9vo0h7G9N4fy2h6gPobej0Q6JbOYSJjIiwaaox14a/2L7c605WX+Jg9klpoBdLz1lpDTOw/hmLF6GbfZ+j40LE/lGMa1k0u42GlQC7e7vXs+QrHIjp1kS7l8X0cUsrkG0ctcdr0Tbb6pGpRDbrp2Wc9KiTfwp9f91G2j5t1LqHbLm+xtH5JwOxG2M8acPr0Uc5BpToyik6J/bNWJq3ojNjR6nGOaf1SN3lROaGhSzfJY4df4a+sBQJfMMsTtI0UTu+faJfLdG77eAriINpRpq6ozxzykehUAF1d/7g2m2FQzcPWFIQwXjWYNHfDgZ4c3u0DZ91nRJ9FzqY6aIPeCGkv+WZizZl4dy40xnO7BYLHJrfYPFgbcx1Fd26IOUwHTLdJm2e5X2i9zN0aUXdg1bS0Nw2v4FMsHdwAWGc6voCB2YDuHcbd76qDlI569eDo0H0T53gFvr+alOIEHl0juSPObf1zKHo5q/WHNahscLBOUFZJ5l81ssYxbO9Dvad6N8v6NvZl76xcXDOVIe0hzR7t16tOdY2bWONA3NCRu9KRFLnJk0LDnaidwvNbXaVW3U/M6da2ufJrPu6pshoQ1NoVGuuYY7yRY5Oa5DnfDU9dHt7BAODnei7DXs8F1qXiT4YXEN0ptQsXtqwmHfSX6s153ciLHJEzglHOee72fkr66OuCY3ociaOy8NaHJbocXYfuTW42GQVnL2NPlt7aoSclF/j71qscbwUT+1FJOy02ZkAmuhTM4+LDDCh2zg35risPuoORLfhc4y3mzn3aGoc9bHIwRMr9HkwHkKp0OrjIndFKrpdZZIBfZyhD22vlLzEWrlFM3/27W6dO+P30gxrHJ2bRoyCkrHV1MuOFGJqj87zHHjjDwH8Fb1bKyFScGC1MWe3NmDS6B3Kvul9kaMFLHwshMQylC9Hk8lpwlqgP52xo82yTjZN+dn/rSbBY+wDz4ViHh5PGz5g0sA1R+fqEgcNHs4OEOGRqYYzFD5puOyKJ7pqz+slJrq18c6Ya6+Zg6RE4jnUlaHJGXuBnRRhLHBoqoBddisiHXCwZDXSqefkV5rexK95x5boVtFr7EPNIRbThpdJY0GT5s55XdcKx+CKk3MiYgTaOA8wlZPcqZjnnLTNZcv8VaL7uTHnVMjcbpRzbkyDeTSZNEwpzctXOIqIm1HETq1vz6StsudYHGH6Ej+fKBM9GNtNdGwFp4JnVITbnNdvfjOnY4rzev5yhQMitIkg0k8sGvoUZTMJfXpXvm1P9PEevVt/QdetZcX3ZyfrZY1zL4uKRQ6I0CaSyGlu1pYJmjc8JpXTbg8LovvZc52bgkTXredQz3wHB7V7IT/GGge3xmkTSaTOyNy915zhkpFPcpvowxLdYagXzxzK99N51FPPpb2COGqgSuEtceiqCYAp0qoIi920XDMOLbhe0d8cOetakRG9xWR1k5672ZF1gZjERczPa5kDIrSJIHImcLD6+02SmwZoXIQelugnFo123onu8LA8/2sxgWXHBnQamFc59CFmP7D3IhAYas3cI+9aro+LnroLvZ+hByK3oTA8wyrGNOKO2xHWIsntgK9olYPX4AL3ZxGmO5/toI1X15pVQkKXMivXyBqmnIcmpfTc/E9nDpLcA56pdQ6SMJ9wLi8ocmBYMd15NkFTnF87Qz9roIZdFedyS3pu2rE1qW6d19c5GMVVRDajyD2eigWF76XioV7lQyb61Hv4WNlZw8YY9kR1uNERRS9aHy/z+hpHLfEmkVFF9EjGHw2p+MF7KL/rVaj75bE16/UEDmt/tIKeC08dc8vIlTtmtxfyBQ68CPOKpIhcCXok7BlRy/vBxFBzzSrUuFhH9bHyksiRWOo+YbB7aOIcyKk8rCzeVjhKvkVxyDRFtF8br8uX18L3bUxPaqKPi+1yLp51zZ7oLH3LwX78xzmfd+OgRxic5vcFjjv6W5T8Aw6RUiUKFYUdT5XlfYJejTk9rcO/legbTjIPLZLZ6DxhqautcORhQbUDtyUg0utZN1k082f+sivJ6ZdtRG9CP2rYCE8g9kR3y8FOD3U2+kh1tc7BDeuh0YeBx8je/XV5PFCsRjIxwftcsxJdW0HBqD2FOXWMUibm0mDvfEs2OiyaZY6DE6KXaBlF2YqPzT455Xykaasdtx3ooSnM9e4YlKEP1t3SHOwS4PTO4MF1Dhq63JjST+QIGVUrZs4cvUsLDf9e0F3l9niKQ3/hMTxUmGPaArudNvpBhHWOeJ0Q9YBhfeK8ojemPZNlnRN7mDwVbVxt3xI9qGZC6MmA/rhhsPvgnC58B/kyB/30GLjmyNBYRLA6D3N1PsdkPOwhdPsAurLOAXTYwI0HVDI23+/D7lW933BsL2ydwzkhdmoNFcnuVQQVWifCPe63iaMVO9Ejt4r95YzQaERnrSSEXNgdEQU0abRuPW6rHEzLPEqCKNn9G0XKnqAF4+O1MX55WJjQx1y/wD8+8vYNJjwPoFPPVT3WhcOcsrHOMWALNLLJAvQqgqnM+ss6ttlFnyc6p+YsW9/KEoB+C5lMnL0Yc8KDCascEKGvGoqsvYjgaJNjspdrPdF9ojeh7/qY/hB6TeqLPqG5mPPUcRY612KZIxhcFlWRbVgPVBO80ePV06d2TYt0ohvQ9aK3is5gT6j4EnYux121afoyh1RSLeEtE8WLI5eg/JcWOT4/Ev2roEsxuBrIiS4PJ1U81NUN4SLVpvFFDog4J94Ns0IxABn2z8TmWsgC/fME3TL6x7aKbqOoeMfdac05GdpY5dhPE/o4ZwWKMBitp4CHZTz8l37Z/0PvQMcldC8Ao1TCQmisqPuJgypWOYIiqISs0RynSetantC/57scCiP5TP/UZxv7X9G3etASsxtW3vdsdPlmS+OtcgyI4K6RqvEkf7FeS4ewNdGEptBvoNvP6OV4Leb4YJmzdBO8GrJ9lYOLZPSUTtXo564GC7g4XXO9PYQe9g30/ld08e6Y4zVLqUvRhq232hY52uBymeZvqsYhljq71W1xbUA+8uzNA+jbz+jM1Sh0u6tLAahFRV/kaHSSMOwi83+pZ1d0LIyxbO3zxMsCupqa5s3OxCIH/qjoixxevIJc62rjor+b2PPDXLZeTO8CdJrVr+hsapo3vWpjRgdScpEDOmLUtAA9rd/9jfv6VguqDbtmM1yEznj0H9GhrLZXX+i5K32NQ3MCRLwYbL02QD6ObXlPM/4jTxhfzC3R7QzdeVgU6OMFvVclV9EXOFIxwn4o+qGqRoTfMnZVD/nSd7vZxTagB6RpyPqQdYfXfUUPGPL16mscqAHbeKeqH14tWWaR87A04z+F3id6JHp/QW8aM44pmejV1utoTF77GofDUMSwoh006i4x2kh23A0lLr6FHjMcfjRm6ajoCnQP9HKst+q6LgDEK9Y4ei34R3NSIbxFNWKhpXNzgTPIl0dupXwIHe1S0TtO9QN9r+idOrxeY40D3+TOeYr6garxNPUuT55fLEm/5im9lI5XdG2c+Y/owZpUL6+yxEHzKPhL6oczFV+Hb4bUXNPDNP3xo6V0f0Ef5CF6z8MrpAMOL1/jcBbeqLU+BvK5+iu6pMthzw+hd6JvJwqK/tgo6Bvc6aADF66+xtHpva+7OKkfqgnIE1bwo2QN7m5SeNEmOpQQLmxA9B/QN05c9YoljhbGrSM0CKPjgjFQ1caoxww/LU29h03wHLW9ou9E+xt6LxNXHeoLHPR2ne/iDFPKkTg1nMfLMcPvPBJ0AboMjoLe62Zjs/NjefGX0lC+xIHDUQ1o3AGKKXAS5ep0Cbvc6ype9wyCuVoTuhmegffa6majn5ZawBqgnwz1FQ65GshALmlgPzVlmfYcNZ9UZP/WZvn5JmEOQxphXjX49hf0N7N6izWOQZdf5dLLaG+snW9t+l0xHyK75m/nWQhFiQrCC3obJV8I0VOKR0jH+dS2xuFqvMpFY6CqeDQhKvy3QA1m5SwQOqNWeYN4iw4pnGkpL4GcGSsct1NDocMY0KnUOBvsvA7WYJ6jvlsXuvNNGGP4Hp1/rQq+mhNLHOcLQQySmAC9DlQK8e+f+fdrJmU6r2SGgfcWnc70is6t5yWObvb2WDtOGvq7VuZTWH56dv14fs+sMcdLyQOB3s/Rt4Jet54XOLh3+26QbPIp1MdSDMPskb/40kKRjgovz0jWIb32O3SZE7HCQdu3DhLGAXJTtR46wfdP9Mu33APM4l31XKnlXNH9LTrNCR8LHNzMeR0kjP48P4x8ZxeQbsNQ33D0op/pOeYblOFBdJESfRRy0S1wtHH+ZXGQDIt3R9DbvX4LF/R3kz+sYZTvdcSE0SU5ztE7N9bqEGuxxMEwhXeDJN7mXGDS+FHRv9ML2gRH9ETqydaB7kCX1E55fu++wkED8O0gUfbmXnUU4+Nd5EC/PpQ5WHJldit5VaPEgWzv0PvraLstcNCQfT9IlEbqNKsOipdW9K+sRjc5zme3xhTiWLi9R/eiY6Xk1jg8qyScDpJhLlNcv3l/Uc1dvuUeyD59hm6B5PYl5gvWAA9woQoHFm5rHDdWE+MVOGXuGn0/X0L/Z97PEZ0eQK9mvEPTsYK9AX2TBCb0VHKxxOGDoVknaVuU/K1N8Z+vbzU60skh3qOib2pRBP+8Q3cyHzeaE77GgVOijWg4CD1sNNpa769cvvyrFsXUfYrurMCHBwTQUVBG1MgZ1yS6wAEn7mu2PwmmLdB/BNd6/Z/HvClqf5yiMxSpRTYHsOOk4L8zU6ASI61wHJLHh16CbEIxzHzvy7//XY/Cra5+Tf8czHSi8xkb6liMGk21l63U0yWrr3GE5KkRamjVPoVCIqqn/+zX/xov/dO/fzSSbgzQjrfoUNJ01VX0/q48Q1/i8FE9yjUmK8vuMHvYP9/Z+KXhy5TtzCN+jt618uI/OrZ3Usrf2NEtVjhQQPV0YaWXkwWoh6tD6/r3+23VsKOszc7R95zR6URgUh0aRa/k5mscUQ78xUlMVuaMSyX7x9jBa7tjZdKCwf+kI7q/rLz2M3SL89KbtzWOwS+Lb8YHMkmizHNeHO/UvD6Q/R3KDpd2BqCu8Ob41XZm/9/grV3i4KconyI7soKi0aHT+fe8j/Rc8sQ5uuViim+CNIk0tqNkBkJ/X+GoOyL86lJkowgbnb/gdculCdqm3D9n26B7iSnv6cmg9tJSEf19hcMOVPwq390OESx5viShfFTsBlhVSc9l3QpCzbWu5iUbr2WQGga8xOgdaFgqKn/zCof2LO5UlzXW2pXqXCLfz1dHr7ueOAsblBzS2lt+wpXcZjSe5sFLAN14bFt03IFY4nBpDAnjBZjgQyfNWy5LPRJBv8oLEeJ503sQSp/wGTrVzEtyX8SFFHvonTkXKxzWaw0bBlycilwlgeZEj6ddfdM9jzuh6COYarCnkq49lKHS5SoBDQscPD1V9+v6uciXJGg4XUvVAA1z3T4qFKfgDRN77aH8rurFlLZLHH5aUAN3UCpfiHzrn/ixSz1Fj0b3qFAleC2sF5c+VrmbvUjUZ9ltiUO5EHj/4+XkXLMmr7LG9VEsVgx2v8OiaYGxAQLKK9dqlE8xEo4gvKTv2ljgqNYcFcQRRpFM8nHNT/BB3+lHoEVzUHsBhPLRRht8CZpw54YXp1b1999y1HGHJTy6KUXkadV3Dhv6qxRaVqOjI+NZ7L1nOdm2V3QOm4Pzmx72a45q8nnGiKDGYBH5lDa9jzxPq4ACZLxUo590EAngV25b+Vgn+njJko3Por//kgPPYU90WkvNzCnyzVlYCZiEThWrRj+LbGH7KLlF3YBF4yfRPQo4k6D9loPW3Hg3fXqWqAprU6FxYN30oCueOHlvNGPf93fZ1V2eLSh4oKOjExzf8wKH2SHldH8XlbblhukuEQ4sl0P0Ykweo0bXx5h7tjxEWavml/fvP384LLhzcX7hyM0SR9ocx+v0iU35IRFlgxaExFzoXQMeja659848C2gS1btoY658r2Z87/0HdCwXVjh8TOlUUfEmjVmKfKDeEmICLqybxkZv90yadD9bt8ac3cz+SeuAMX3v0TmZuq1wyHmPw7L1GhKJp8gX4hJK/D/Kzd30PtBzh8iNwtoWcA30byAz7fWLKZNX6BUWOAKdN84GSZPI1EXN7NOcIWoZC/HAcVP4aI5xOjh5++HW1de/CNvsFZ2qjPdY4RhchJUmSTKJbE+RruM+d8+pbZ/oGw+e+lCvf7miHgfIYil2Za/wc3TMVygXs8ChJ7w50sFSin2KzGw7LdS6eX55oqdDGI1u5SovlWUztEkJZOsVncOmxmEtcEBjMZE+b4MynO0/xNDshr2+baIHGl0bEPGa0/sojdFUOyJdHv3NIu/coJFKXeDQCOFEVftJivgU0RbioITPWw1k09UGxHzdWnAZ13yNvY0rNucjiUq02JlBI3N1gcPshm+z6eXrnpYKKDadUrVdYrnHOW+VvsGbHHM5MGBJV/uuP49+flmiM6qNCFW7kfO2wGFKpGRHnO3F2J2G0BRBMk0m59Bxfal3OeYOPZPrJ3ZEuUnDNdRzntAcyc873ssxsd3nl7/AYYeekmdSzYsTJM3fMUXK4X8tHISuNMqyejLfAkhaAEVbImPLEEvNE/iudnstrcuKCPPdVzgsmJqWe9z0JjZTXq2JjuU1jKSHxnxa8GVy4/n7ieLDtAc4tgvQO0mxIoIbqF6xwmEDg6pMCwjaUH7GKdIZwa+uPWenTTaVlhP682U/OMXkS91t9AtikAKkCeCjNHlR8f57jimIrqjuoy5KEWWIvTKdfXoAZmJBFd8c2GVtQU1DpMhQir2NXQpeyhLPZmbF8+zgsmN/z1FTHoYZs3InXtY6+Mic7k16RhmIppU3NOimiAaA5ZJVI1Pft/ZmZt7ND7ND87qfFfQXVrVnkq3F7zk42bjE6EFmDpo+y/hkYvMjVcr8xac6Q5hJvXWt3Aa6XK3FFRM9vqz9Tz5t3bqU+C49t65afYGjLD+1LqERwmo2+0RvIzc276aRvk10uEZVFUYYXMRwk2B+V83Gp/nTp6006dWtE3kT6PawnCluCxwctRqpxfRkkmOhC0nv1Mx2oW9pYEz9DrdkGaIusOPpkR3f2ny6YEIEbclA5PdIfqUWXuCwAzmXa+7FclrBp8iswFNOTPaJHurB+mI6MdCQtNRC6A/NT1dEXGGcdsicLd1uKxxyrmrnM4nq5VpitfGhtCKYdMK2iT7QxdXfMZm9XbwNt/HQyvdDSliNGiVDx5k9q0Zf4MiqGoMu3dMMa21s9kTfuB8029wnuspdIXDMObrPF29ja+Mh1fSRMuyrDAxjk3MLYoEjX+qWk+3bohcS4Vkx66al0GcbuaYTQH8TydaioF8eysbzJbuolmYUfp3dsN+xwJHv5Bq59r7ohUR2nhCckG2iW1MnkJHBVU6JmajoU2iTC6hsUWL5fcS7yW0scCCd73k1U5SpCxd6MmE757tN+1j9XdwwadDs5LI20Xehyzh41QwhSFwYAX2Fg0mca8h7PZ6zNxsfbrvxNHBoKfRQlq18NArqa8f9dMXeTOjWZ4KHqqRwUvnGVasu3XqFg/ZfDXmvuzZTZJvoqMmrpdDDpxtAE7u44cOTGgIB0B/d5NukC6icVD7eeiYPW+Ao9t8b1ahG7M3iY7NorGrRtRR6bLZjYu+s8acWz6CDij4emzzabZRDZTgRFNVdg9G+wkH7j6qxXuP5jvvHZqMmdwkbPtFFqy7LMNFD7X1i08553bWP0abkaX/3v1k0SxzFwH2vGpttlug7p8p9Ohu6xaSFQ7aGRfvrVqmsuTYlL6zMTbCWcO1+erDWFziqgcvn1pqqfoo+nujaNezZRK47JsD5JRs+Zh4jBPmUYw5plRdpzXh9gQOej47KUKeVdNsZuiV6Gy6zXfdi3/XxF/T4sqOFzZRVNAGZXM9PyWX1tfg9hxSPy0Eve4AXhnSz2D/8HXo0VASJl2Ta8R597B9PKK3+eonB0+2qikSln2OFQ2Ml1KvmD9YaYL9uY+8f7Rz9akOzWxvIHo9jmG/RbXQ5qNTv9+JwzS/UB1fstBRXOCSnc2RMtnynNpbrdN+u5+j9w8am2L8cm2zAtydO5/xwecg9hapReOFW85y97GUtcCBVffZPlHzmPtZUjNvlDP2/LttGV+yfzArN7T82+6zs+v08C9om+ijKIftSZJPXeX2Fw+zGc2WD4WZ8/hyFo/8nEq/otn/NrTM8FZs0f2/2br2Nf2Z/p9DtNa+DQ6eXTaUFjvxtSETv6FlIi5tjsf0nsqdJA/RPt/A5urkl0xD0X5udIVQxzwU+JCSGmqiYB3nrptIKB07jSERlxLKrcTd488vMem5bQY9PVebU5gcS27cwj/fNrgLE/zwuf7jc85NEJvBD1hiLBQ69D0VoKzLD4RRpFxu7Xo/o47u30Vm8VOUMsBtWbFjcePiY5yTbsHZ2knEwowHJM2nAAgdDGE5zkATfsHu7PAYXrfOm4TYeu2tzIqc3HFK22+vKhTewQPoGnl+lVV4LEDbMbwscxhLWZ0u9juePrTV7jG6D36K8a/smQzZVUm5EMWj15FK1Pjl3mOa85KhBo9c9qAUOG29F6iB5ioxHbJrCcuxM71p0GbJ5Dr9zwXV7HadUPJlJKpA1ryxDGS1clzHt9xx4/rkILdHYmo3vfcOyZAJanyrAredemtbrUMuDP3gp/93d/JZOhhxQxOlAqMb88XsOzh+nIjYQ0eltjM+JSH+Q2+7XNkK+CnPL9Tq3evmjvtXcm8u5gejV79JPb9Pi9xw/oOPV5dOKz72VWnGbxfbRbHSpq1taVEwG0mpAFA+p+OAuaUXfkZ4KJhrvs8BR96miSjDdaW829s/eLI1A+eBG//I25kkOwbks2df1S3DB+b/7MPrrZZG8R2/jPNHdAgeHghRpuTqsrjZi/9omIbZ/9/bfF+I23FyIguZhfx5Cw3jVXq2jTxC9+lid98CNFjg4f5yLbDyuMPa5YLdgzGA0i+99myYNqjV0/alLeOjxd2aVOUaeDXxBB06XTF2zL3BQ9/upiDOH/3OhG9afJIqf8DYe0d12LVuklWhboLF4lkW/7Fqj3pO6jXP0na/ksGl+z4HucOrQwvffRrOYC93dXKHox2Tt08Z7eqkNOfJrEbHsELX2ng84H5pwT9GZG59hAwsc1H/nbsxGJ9ret0sbstS1xd81t/U2nCl+h7VThd5p41RXMvPfV/TAkf66gFvgKG5+PxEZdKJtfnnIaIOJ0D9aG4H5PmTEl3doUUo44qRMTTFQ0IU0mLUY1wJHcfNv9nrBDBr71uwRXK/P/er9y+e8vsNh4PIP1v5YTfE3B7h7QR9qzTdafoEDj4PV+c4MGt2bPbRoxXI7vru3oc0XvcGWS5H6amj0kugQ7e3lDYBOLa9rhaMcmYi/i8TW2vjuiSj/khR8tIFie53Tut8RsnxaEPsY7886Ex1aHtcKRw43Ksb3FuDWbHxuNL9aWPh/Cl4LN464wPEv6eModebep8G6naNDy/Na4MDwonY4twCn3R9fbs7sG230axuxu3Wenh6wpQ8eBmzgAy1zZOon0SNl7SxB8gIHqzpI9G8izabbGbt/c+E2LfhuYc7btUQPnk1ozIUIZ6rY+6ldrsHTaO3xWuDQt/5+iEDEn3b/1WTDC6dbfG/exj4Xn9wgNAwAnJgQ3xwCfq8+nDhdjRH9bKgvcGTfqkOEIgwCiH7R2vSuThxtPPrWLJwedE1s49Vv1hC9K174cOB6i/foL+26wKH+9n6IUET7Fo/ddID96VfxyyO6t9FZnaQjGXCHFoq08e4waD00Av7vVhJSwzp1oNd2XeDId/XzIQIRbUy7PbraRn6VqeW6287d0EC8ZpzUcdYtaknCd65GNXljKjruy61wsAfFGxEGAfRm386P3iymlts0DoQ0UOkdNsBEVzP+lKXdPLgcEzrTTN5H9owFDvjSfPwsEtsMDrROO/Z7m/cabfB0Pm1uZk5tNfD7eJvp+kgmcbchdD0ku8kKB0qmdJ40eCOyb2180ZA9zC+P7m2Esx87zJfGl+vmGI8/5GmHP0/cA8YwLeAFjhfr7x52fycSbexu44OGbFi/mrRcl8Jmyud6aJYFQaoR9nr1umAfUHUs9LXAgeyVrvM2woII7f5mceXpxmHxMRfrFgh/1xSDxPCXmYJyole/IQps18sHlm4VvY38c4GDFndPxXJ7L7I12y+aaUx27NRy3gbC39XZgf7vTEsQT3SU/5MR9E45Rdk5DqJjHljgwBo38sP+RqRbbG3sl4cjs5nbd39qTMcBvlHQLw/VNVTCN8/Ea3fEgpaL2dfEvReLTj9WOPRmOK+jG1CEdr+NPsM580xRvzx2l4/GongHG6sffQtdS3mxNpxGrBdqMYp758IXunCBQyKdGVeSAH+B3b/ZtyEZfaSWK5som2F9/WWqDbFZR85cpBgpT62lssXdoT53PGyBQ5LBVEav+/oUCbdP2fBPV/SXtFxDdbZg3b1d+Teuyr9TY94PuKTPBjvRNxxo2tEzFjh0B+b+1KMogiXPmIfNe8ajuX17G7vPg1BRy8luQp/BYZdEx/IKeb797WB3oqeVuEN+gSMdneV8YBGh3d/sI+85h3pvFr0hkZQaG+hXhcVtyl288Wl5eIUBgcZbtYx8ddiqO76eBQ6ZflOcXtb3Ir2NK+4ZF4unlgvsuVf0D53V3Sb40NMyuOpWl9nROGVZ46o1N6J3EC5waNNerjR+jOJc8mw2Ljz6crXRfX4jJaNhIK37F9B1MFSJk/yeipkLA3NYCESXjutEb8NWOLTGYp6/IpLxG7L7bVweqEzz1ca+tRFNN+feWobFfCoEtk9005j0QN0K2vWOaX4neuq4DeiC/SWH0KPm+Ysq4hay+93CHqh6+e0WucOMYMaKrsDn/VliCnOQ5zlQBsQwyzbRc4jyhbutcMhC3NQDtWG7V5GbHRJpttsjPxCXx9ZGaIeZ5xzaWavvFqo/gsM996xpF0DBdK0lcPJ2FDQU0AqHOl839cB2qyIoyhNt9Gb77Lk51OdId4vZGDfIVfT5jQ0dDA268nlESI/n8pfbTm4a80RvY4FDPlJkGHKKMOA4ZPfPY/ppP39YzGa30ZAGqqJ/C33mSuj1lEAee96IbkE/hdDTANAPXbHAoawdyDDUyuJ5S3NKImOzL8tMr19NCn5g9QJ0FSgW+kwztj9f8NCGFI4DuhG9n6AzWKbBPl/gmCKbNfVA5KmiiEbYFLGx2YdJd4Z9N9s3rF7wLcOOz0j/Ng8MDBxdPXAItA2i+yl6x1ZMXn2BQ4FOPGPlRQRzdLeYuvxDlD4uDyn4TasXyAH9e6Jbm919NJx0x9HfWjmgDaIHlqo9x7suX+CYIko+56UaLDUszkRGs2sq4Yv157zeZ1Oeo0vNXa2Zc3bLtNYqBlXTggfRB5ycXgNm2gJHFmPICZHKk29vTSJ7s0s6Vq7zy9DCLYjeK7rKFIfKZt4QSdc0K3FCQ03a5BzM6Mbx1cbvOZSeJzhSAyIIhJgtJfSHyev7ZfH05w+vngE+78tUprjrYBReXVWwNHMT3dF4Teg4Nkr9PX7PIfSBDEMaSUTY8va92T7TjCmT0rcNmTRbzQBM9KvKFD8VzG4dKyx1d+kqojeiGzYvBUj033IAPczRNYpIF0wzjepvBeJfHprblMYB1yD6ZeJPY06htF3RcvfJsiGiFuhD4h3aHUfE8cD4PYdZU21u6+9FdmTVH5uNrLt8NX+6KhUvyIUSdMscIV868qy1mxJLt1B3n+ilBJbQcyhsUOf1LX/NMdGnGJe/VSTyJOxEj0wK+PVcwVvM2Tozw6B8nAD+mH0rOUhwATMHzp52mO0v6I5Ry2qz9S1/x0F0ZB5uLyLZDcc80rVnjfXvObc9V/HaAUNwBHZFr/bPY2r2/lzjtVzAyPB+8luv6DwHgGqzoVmM6L/keKK7VK5FPxNJG0FLHiW8nf04ZpMPhEq2ey45pZy0+aI8kmPTxltuiG9mQhcN0Xsarmg2rQIq+q84nujaEjEfPlKk3QP7KLIAJvr2H7OMlOGTe/4WnnVPEShiJf3qtnMB082FnptFRN8Z6tzRk4lu/ZccQvcUkWU9pojLAwAOTetu9q2h3uSkpQ1vfm83umZxqqtp+ZLHnJG5fOK9oIeVvE/zL/XY6PZ7DtN3tcHhK2Xbc6RuPP/c22iyUS7fMnLcxoYZFbH5gztDsuFDeYuyDYkeFX1wTaeVSUidEf3XHGZNGyKaWrpEdH+KzPeTQpuD/aqFwLRoOKNydmcND9nwrkYLvQkL1PeC3gYtXPNQv6/oCxzWtCsA10daFwHtqrGqRefl+zljRRvP6a0uX1KEsWP+HOzaaPZ8E6BvQMdpjh0+e52S7hX9dxwFXU+dEI7jQ0x3K+Pln1m4sA0NdtWD5CUR7HtO8GnDd6QqshB6xgbQkPV6jOdumd2P22gLHOYnIjg1XUXm3NZnmdZvM8/BvnPlRs2LMPAWNsEjlxkt7ma70NPvzOVLp5bDNtV8YWyeLnDY9tJRWopsFMG8jHrZGuxGP3zx1WR+VFcuePoq2ijopVZlSYAujpjvQvRfcxA9x0PL7dwisskas5ZDOX1WqvNcr5bu5sng6vPpfdZkn+gY8DyVTC3iardG9P57DqLrTSSi2td6dk5DT8jgTN3bkHn6bn9cpn0I3Lb0xCvNJbbhUKl2h1MCt5RQ4zey/56D6DIPUwRhSyhegI302V/lvhjb6akLvrSP1HI4BOdC30SsdbVknUOdLginnSr0X3EU9NlyfxOBL1mHUW1L63Y7SxHVaw4kVcjNxpR9V9GzeTnUWcClov+Wo6BPG0dLizgRGdhBeDZjfw7+kN63oyabcqrm4wneBuuyj6bnmwvMhF7OUljJ6TiI/muORJe1d9dI0+eKiA0NVQU43lSwZtPry2zhxT2W+enUctmY0Vg4VoNQiMahDtU525zo8XuOiS6tgQ71VmRX+TUPbRPKte4T/XVccmdtflpaDo059QTQETeFMAmiD6EzFcHvOTQt2IZX3ikCzZgquoWOYdphzVwvjxQqvJyFud2k5dCY3Z4reMzp7V2YBGrSDa5a2/g9R4ay8R9SxHM+hBnEyBGY5bs+WV+0BbZTVcaLQ902G67WGtwqaDVMovogib7CIRGaRiNFtiLSFQfk/LK1cRw2zksMHZPjnllYRhsc6rYpXRvFB48Et1Eqn+yzzZknpS1wSAT2AawIiNBSloKX5tJcna/yas/eFTFzmGuwN+rtTd4PPagxae5zqOsLPNiTbXD0+grHFJFhya079d0qopiIGzWXunt2QKKj8nR7Gt5180XbcPllcDs1PRpatLxF7yscMofRe3qK2J72MP0sbeRJr4niP6Gji3R55pjoQ5uvO1Sc1Hp6NHJPluhQXPsCh0SwLS3rN5U1N+2aadWVJ71umlTmEGaEfr00bkP/wUSTotCvslzyTfYfikO4EZ22TixwTGOAFoY2cXN8VBG9d7vHfW55qh2nfST0/TThq48c7MyTa6aZkcfYzI5jlBReejWg73DnLHBIk2C7+2B8dRUZ03LxQU9Rqm0zJ/oxvNSR1WBPC1OX7CE9MOuI6t0YRF3QERK/wCF3dljjMZqeHt8SrzNKwZubphkbzRI98uXbnVOcjwlfo4hyXYB4b8ydDKIOTm7YVOgrHFNEN5tvekfN9y6RBpGNhx18mMs8nehQc/LPwIydGC0UAMD3aDgRU8JEosbTCd0mehZfXuCQQayWVAY33fBQp+PbhDkrPNyySJgVdBxThZ/Gp3huMeuKdE+rG1qSsnYc1/FCVyO4rXDohbVpVFwr3AbA9x36sNypG9AhPViM6j7saQ50wXMe2FVPZa/oAR8T1wMj0TOp4QKH6IvT03BVkZHH2ZSbfNIQnW+JauE3Nbg5Z1+hD0vrZeDNi0JsFT0PPaxwbCf+L68iYcawF5zT6s92d6EPrjh5CUTwdZc0bMhPw/dzqwqxDaJ3Hv9f4NDDgj2lFxFagNIktFO0TGaaKL4Aq5gJ3jn5zpkNum+U75kEQ0JwVOhtFjjyMABOrkQV6SnCDGlS8Wk+C3jnUH/5kty41XiE0BXy1ogeZvgoI+mIrmuBI+QTwFF5rw4mZu1CMyDSEbu7FrxH+ZLiSZh5ofdpYWubUMMguPIqy/Wd6HzGCsdAwME9eSDCm+ipqOUh06oLPb1J/bTc3ETh1vgeuX3gGsM4w1UVYkFvfM0FDkbYtLss1CrSKJLWlc5uaAdMIduC3k/LMM19Jmq5/zcSvekbSdGO5Qu6NdAH7v97DuaCUOa6sCpCbwiK8ShDoFwkmmLVI+K0DFPkH566D6piNwN6nBzo2IhuYOu/5dDl52eo8SGKqASTkjX3dJHY0D/wGRgZPZv8/2/tbHbl1nW0LQUWEKyRB/I8wyBXoTM4czZg38/CdyVruLGvsrGKqAf14o3aKOFTn052qoq2H+uPokhKHNoewrh9DVArAR0TdPkm3uSQj8+JiFRi5fbXdbILBDql+dnB9HIzsmJk6Lm+okHU/EjQaWihAW3vciA4f12sQ/mlDZzd0IWMc/jpujnAO/rG+spSzDv6Lum/Fzi4zex1bYoyEKNukkTQISO2DAUl/5aqjEQPSzLNKOcNfmiqj/NtDvV9OOciGyLCRfD1UPQ2JI+5er3boTYj0fGTGEXzrBs6C+6OMeB9DmkNLaYi7bWhHFrpZRh6fwEfSLZC1v+qfaYLemie9Qn69nJ8ayxx8F9cQkuXn1aVq/H3oTgg17UI8T1NB6Bd0NMYh8gEvT2vX69Y4KCENhxPcyAiQSeWStDwWrmecOvcxlQPehvkpsM3TtBHYfgjge4KBw2XWnIRrtn013wGujarkEHhyd0VvdNontc464lOUx29DH8nKxw8GTRawvJBYBW/Bp8p+ln0QeQMHLW7sKTjGuhFORrW4s02vCescPCUyGrRVVCnQWFlZ29MJ02uxY/ouruMXQxmoNsqkUIYgx4ktMRBqV5TivG8NTMWTQpzKFON/q0VNTA/+vin6N0B2ZHXl7LOwYzgr0tmg2mS0kSnFcmVEE/uOnTjD+68AF/wtnQJSBeznMzrHHr+MQUc4qysVEHXY6XkzoPAVQFivhN03lbYvdxvdpkDGT+oggtg8JYClYSi+GH3uMUQsbaL9YbGzRfm/8JnLOqsTa9zMCPEJCvhRD3u2LVr0X0n6aNMbCx8Ee+cvy/vBBOrN9vBTpyWdY7TW4odsmAlsGuz7tDmnvejVjXMljA3G/rzJfncxjDg1b7KwVM371x4QE26OicAcMfDaguPoMo9MOaddF7Qyz6b2xji2c1c5bDXVb2F+TmA+gvsK6g7YYNMSKq8UdRa6QfLBhqv191GXNmjnP+/OOrE5HDTuAbpZPhULsPERt5nMsse/ATUfA+KjpTsvqL9rXPwazM5zAsNGyNDDR9d+S5vgBmJHbPgJ4ruRxSrbYhSr2UO/UnIJeaFhs2MfHIAsT1J9lsaexNrZf6Xjn+JrmqXzhiuuy9zMFPJveYFPR70doWL4dJCFHo+a9pTKu2d1IQzdD0DW3GOBQ7X92SCmRc3RFC00om82bh+Kl1HZpRkit5kbHJ0PQNb71IXOA5rmjLK3vRz5KgS7+mkCUt6pr/nicKZgwrPF0f3x2GCXOfwbhDa3+bcvGhHt7km0Fg2bX7k3QpqaegID7p8x6mt6xz+RnZEbrv6oTdusxvhuxUYmGSYZMgKwctfx4QuaHWrHNZSOiK3XT20QupkxGFYR2OhWZAL/yxQhy7Xh16H0hlr1jnc+OWnMcy0RUUf9kr8yKkdYiaIpOdBdp7E0fWanOs1ljmCTJbkp7pv72Y+EQXNf7nJOr3xzKSyZ9dX7VNhuF5hV6xydLzXVESHq/sxImatK9RN2QxKNUDXsamqwDa7/TEWOdiq49jI+/Hdvu2aOMo073B0NNBmOU3oQyLQp43uXOPgWCZcssPHDS/NtBZ008kA3wSdxkmtbK6sKvo+vX8bixwhCd3ptPFGV2cZKZ/7aVu7gmMoA11jtWboNnadixwcAoqIV58LOZ8dZwECCTFlpUmtODqrwX26q9S12tc4Oh0SkdtBDgj1NIHDRzn1f62sfGoo+gDnWwRAhGucxZFijaNpChh1750PEL4uxWX6usyti/qgk2NmEHR+QmoCQc84QWc6FjgG45BaAr36rJZtGD/LlbKjqqMq2ENt5QXjkqBzye7oOKpqtdcFjpMHy7FKFOp5ad6s2YCs5qgqD4aBA78DR8fRxNGDZ7uynAscMOwisk0HB3nO+Yh/JCwATDfa/Q7AeRJF3wWdBmwx3ecKB5dSEUjmxb7f/DRWXTk3uNqQRo8c6NyjCXr+6TwtljhYMwZ6CSbl+7mNnmvHTnPPZuNvOZ3c0YlBdHRrxcdY4kC7ZrG0AzIv6kXVrYVL0qj8jtV4HXR3a3+CnvEFju51ea5xNBoLIvftXT0jqdlszoDAKfbhNpttw5L3T9CNqI0FDowIGyJxP76reV8tYV1AMLo1uDrvp+lGyO7ow9H19txsiQMbEYYRu7Sj+3q1MciJ2wvRdnBxGs91apfvboAbPImgG9KxxtHR+fcUsQYlk7Cjy4jChN5o/U1aM3P8MdSsS8NA28vASUf3hlzHEkd7jZnpsumnfq7XdSGj6O2lmn0jm1GQx2kMdAjIcFCjxgydzi3lXOIgHVS+MFw1RBW/EDSNZsclWZ8Joxvdgcfh3HGtQNBbfpwxYI6e0lLaAscoxMA23CNGfj8kyAVRR8cluZ4y7J6i1FAleUSUNyDmP9LEsWpVdNrM8azBusARxMCOk4hHvj2kaujRht5zwG6X9ypC7/EktjNeVN1nwM4oMB0KEp3zbYOWuMDRs188rdp7dhk1+tByEN4Yi1AdfIdVTRXY2+xkH4GrcggzC3Y1ZRDWCNv7HGbzDdz0zuIngmvYZrBfNFcY0WJBt33SrnsVL10kkxS5b7PvgC1wmM13oAJiBoIXaX7BXq6NpSpQQ0dUuSJwdvZfJimiYzk6s/oSB965iEg9eWzuSf9mL5ffedFd86opoGuoKE5GzLmbrQ3qZONzgYOYFCIS6GquPFFJHIY2i2GlSKBGZWGZB4oeCoNrGS1k09Wvo3OPBY60/lWejXGSayiXxhEGXOeEXFTpxgtLHYAoihycOMGIcaHp6neG3sYKB3F3iNDmLP2vR4+yoTkPreP++J1UhJMrX0OOVaDnNF3lBHNDp8QCRyFkR4IxNCqqWTXulhfPVhR+Plk2ykRnBx0lphe+2bA/VpmX5uj9TQ5QGhfe9GACnsvcQxiLQIev+K9lLwknyMHf+RCgd3Zfqhx9Nh9P2wJHvl0+7eQtsWB/ykYcAnXk+ox2dTMNbExlLOeyZ6SlhcfnwLuGr9a0W73Jgalh0zQcrcxFGgtV9fJrY9rVkRR0tiLZHSSCnUY7Sirq542HRLzNQeNomg5lE5FQGhKwQ4JCaUWGmj5Fb3wLej5JeBud9at3OYoEzaISdRGxrJagy4k61dlhYhwWdBo8iZ3z6qAb6Ww03d7m4BYlRQpZgbzBUkBnvJuz96IGy1qkrzfQ5QAj1BJBB0E2X4gJWeDIXhEojxIUX22JbOi1zNjpwIyDoNM/Qc+mDnrOVn+1RGnI1ZWwaxyDVQ72vOF99TgPIitwnVF0Heap6MFrEXQe1NC77blRGryUa50jRRr1ICJM3DW4y07LQvWktHO2Vr8K6CgFdfwVnWFas49PYizqWOeI0vIjjFp1mP9ZQ07CbDfQqWf31+RpQa/ZRC625g2dY2ysA9lYd65zcMTQ8ZwWqitjZwLkZWbo1K576UYRdPYd6YaO3oudNGDuAtCsclTWUUTWq8JOh41b9Bq+ykOePsfDGzrTZS7Wwyk9I/ciBztH10U6x2qaQNPOq+haDndsQh7GUJw6QJeMkUNnN7R7LescmziwCA3TYVfLIejN0Wtovx95K0Xv7sXUQK/8NhSTrq5lnWOT+U9Emh5RRfV07EWKruPvKQOwXLC571o39Bzk77r6OodG0TbmK52cuGYgYuiUi1dgW6MbVWAei2HonMQofclvWGFd5WCgRKQGT6sBN47uiWiukGM3QafjAcgcn+jcDfXMvBZUcaxjjUMD5HcRafLG+MjQTY9DudaYDzRYS5VZoxVuX0DXNJltcI121Ut2MRY4iK3mIrx2P4gFk5ajX03Y/aha0HEu0BwQT8WkC7p0jVPVkyMAXeWoGtQf3BuDqSS6EvRGZxb3GDuq1l/E6WoAS2z2nyWo6xig15DxdF/jkLm/SU+8VC3x9Q7DKNZHLyHou3gduMkT+xemM1xJqeRN1wVJtMZRtWXwdtqQxqIZ8JIG9Lmn1pjlS7iGL/WGRK3sEq/M1Xnv3HErSxySyzJefZ5OC8FiAKmKnr+ax7dr2isq48wadfQNgFG80Nu4YysrHGoOG6Smz2bi2xagN9D5gVc7P5MXwUZYWhsdvcGoV7SPCZtZ4WDfV7cGj3oNn5aZMelWXZSzfpfxq8ks5YX1q1SvXRIEgqWWOAbPLucrMYIgx41B1w1CRfJnc6c6iu8yS6d2dHO1WOIYtFgc3Cgs6h0d3Rx033QEUnePppMB2JWaajfoNUB/kwN0VnS+36CfsTrE36nqgkiLMtchTzJDZz5OCUfnNuyELHGMQurAc2L8kc8IuAxZZyspRf13mq3ubEwEgMp0dBoZlxwrHJwAFfk4eq82DAj0LtaVSYsPd8FRbUSh2MQGXQjaBXrGDeFnuMCBiEadKUkrjs4wquhtEvNLH5TVnaGzJwq6jAq9xhO95bWZr1c4xixcWHxwHB3vtwa6t/hT/uuwRBezsLPNt0w40SLRT0k6NBY4TKTphoJ1EfW4Do2c5bfeo1tY4IOqcpK3oPkeIVYnvIva4IFjgcNEuoxRXpPiZ9+GoCMProVxuknD0TUY5BCclugAY3da4RhuCGEGkhdo6C3Oouj8mCX4TRF2DRLhPyUSrnISbyIxLK5wDB6cC9nE5Oid9izoXIBF5h27r/KCP0pov8DBqjOdY2Jf4QgR8Syj/I2ImENAt+nsnlwvLikbdjoA/QL0jsvBycbKEscuIt2k+VtaXZui7zq03JXDRuXd9xousVHsZWcXAO+FFQ4VCZmY+NvQ6xS9K9I71d5AZ8HHj+hroKMtLHPsarGy/2zD0fnW0W/c6Lx0FRWf26o/Ijhir0MO9V/iwBLo47O9LOlwc3S9txWMFH7LDrrus6CIPncSoyKR/G2FQ0W6Nhlu6qEuIaxadfdhhSdJC8CTsQ1Llj7N2ThRmafLyljhwLvMwo/sIojoRNLgBd3EpGhUq8VD7BohKC0+3XHqaIjQBRc4dENSgBhgHF1jFxw97mMjPenE4AYW8wAVB8fLZlpd4tj8BtyaTzzAqc3RofDi3c8ThO3iL+Qw2yt6w3tqgQMfBx0K5rmF6O+OjoSjzxfxjQtptIPa1kLC2ntJDwLcLccKR+V7nxKsnbCc5ja+XX6PPsyw5mkL6tAlTpc8DnupI3/BORwLHNVbBc9j7YTltHnjUeIOXUzJuveOqJ8n0eTUjCjHc7DMy8QKB+3VtT++0OdGd3R0QOYJzP2kmqHd0oZkWvaLwzTDDQrNAgeuqprFf9ZFKm1cL2Id1iWv8wiP7iqg74LeJskvesljzPk8tbwlDp68+UgULuK0w46QAUMceQv+ahRBD0GXNM/5B/nkK3ucuHkscRBKz7ioY42WxqXC0f01M1DBI9+Fs+qbkP1xYsAa+9QcSrzEsctxYHdBZRtkEAzTOE2Jppy+zANdntb9y9DvOh7TgRdBXeBga1wW2M0APJy3gW57EPxtJoum6Jt1btNLqN6DfPL4yR/4ndUFjpG3P/7n8rotm4uEeDhavG6V3/mKqc7Ru17BcqdyBH2e4l4k7rcucKSI5yJ1Ees8YTlbJc5FV0zwuB1pcBltnDpQZ67l0OwdJ3baBY7w1jBT/2CWmqaTqUSb7UQJegXdVTGZnl82Vg5ythBqUJc4iAN1QN/YV8QGejJITdWY5I8mxYGic0+bJ/W6CclXxDAvcPTJyO8iIEtnlwwkNhlbpRP9cdawzXRB97T+fEoaOvTYscCRusAM0EVCNQIdq9wG7HvJjf3UrkpwN/QSCuF5F9FFY4Ej5ewLETkuqwjGVtA1fQejkrdBZsYGutmi7In1mMZ4+c2ZJpoFjpSzLoJI3vUER18b6O6kz6ik/85ZSHKettnoJlfrclLzsNPS3udIOW+UiFBBnuGDoUwVXC3aCjh1cRc/HOS15TR5Jh66PfglIU1b4hg+K5wi0k1H47JdVjR8PyPXs33KriHbDlyHtvj8K1v3kZ+gzK1whD1wGyISloMY6QY6PWBWmsZXDUmOl0gOHNriySK0ccY8ytwKh5+CeBZEZECzXVzZKOgiaeT5VUt0gpSqhAXZ/buCoMJ0Ur6gzK1wdCFiQkKk+ZaKrqZIlsn388P16uB0fdCHQE66fVZ448wQ+hsn1C9wbNyXliki2yS+rNFy2PE97vdTI1sn6BIWZBMZN+QEbElA0wYLkX2Fg81yrR9EuiW4s3QnO/mv5x2dKza8+1qiczF7UbNTAxtvm2bbFzjyUtKsVGSXkcwPEwJ9XqT3VtAr6MBKtdsdqSqUX5LTbUsc0kfbmIv4QQD8MSt20fYcjEFvs8SwfmUSKAF5PjWTtsAxSMKszcRFzB2QW9DQ7CoGUBmMEx2N3vi4h2toIeaB1GgWOIbsyR/FRAKR7g9h0/kz5d6w9osQ6BzT6YQtvLPrYfxcOqfLFY5InYArmQj2XevSgULrVXb5qEUre6Lji8XDuIyhh664UrqOFY69NFGQTSRkcWbtuCk6Q3+y+3NELjkD9F2vjBCkdvGu5ozs5wscneh+PvQ+4h1SEgBUrzDYeY40zDzAExh0vbJK9eIfBwIs/2KFo+FnyLDoIt6sRYHVb0J3Hmow9NTIpO+CHn5lxHwUCGbjf79Yr4/SVzgqlsL8wkVkMHPIZknZ9ACi19rvOQU3ergk+T1Or/bqBt2U/vj88/kSY7vCkcNlB8VE+jRvFzq0KbjYJkbWvZzQ23JKI78xjjLRbF6QZxL3wN+l/FMIF2hLHEGgZB0m4pEJTnlOTiCSvL0sulohgR4pVOI5FYdXu9nVc/7+8VXKR2HcqyscOTRWSEykoTlMj0jiG/+ZrfRqotfxNIUTveCLBOeIlBwP7B9fhMHW8S6HDvHdRXit8gyKSZv2zqm/Jd8KO4Qs3rUbeqiOjuf10d5L+VNIbBoLHCnHlqGJEOxQZzXpnUCKJycY2b8P0DXJL6W5/zA64K/yXe2fDLP7CkcloxQZqFXkYIHknLdvw8MQEz27SaK3ieOVt/jGvJAz2xfBcH2BI+UKisURpV4iUv8Ht/O71n3T1UEnyzUx0SUcnUU5ZWNw/CzZ4jHJLnEE6Tw4QyXUdP/ar4uwx3x9OgvwDDKfc++Z99Ghl8Rpbc+mni0+p/P6PkfuVmEnI0UTIhSG4VMf7r696xqZzOea2pmbuNDlrsk/SqHF7zlUv82B+V52EGuoiMToucPGfXtPNNC7ok9dyUOeBst9zm3f5Ted/30O2kre/dDaRGS6xRL37V1sq/FA3yZZrStuZhpRMUQhrKP8LFk+8tJthSPbCqNNuKeumqN8K+y+veueZ2ePGK8v9wluuni5JKlBTut09nwZ73OgDhRNWH+qCEbIyVbY/WGwoBOgx17nyO+l2R8WrAQ603p29tQHFzjyXaUmCAhIu5uefStsNupJGYJeNZkp33euUkMay8FVsmeD/js/jRWOwmJ395PJEFHl2LfC/Ast9RYdeVReC3nKiU3RP5jplziamvXm59abk4KN91N0Liup/nN4osGTdtEjzo8X9A56dvZkXeDIFUWKhCDZwR9xU9PNmfUb4lGH5r2QCK9uqhzvgAy2X1z5MxcwSxwtBWyrMtStRR3X53Fq87kN9OboDLy6EazOAKA/gBnnMvRjhaM+3Q9320mt5ntitWt65nxuA72C10Fv9Evd/q+0tAn675QdCxypVqd2WRVJB0qIkZ27/VjZc4sd9J2Pg80gr2c/CNHRf6ZsrHAgsFsWsG5J4wydlnmP3ttQdIJW8j+rsuri5TUJYbyifzDnvcuBgoV+STn+EwrVDd1UbCvi1Bigd0l8xvJarlY1wDFAH6/oP9Bv3+RgvnER2TwK5AzdQhDnZwB30FHbQPdxBAd4Lg46IzyzW13gyB1aRFwZtYSoho6E3tLN51s+X7XUUfOjbjXdAui/CuUrR7IFjlEyULI/Ra5juIgupit2dq32NkXHfLgnetU0cbNdWUmyMUH/VUpb4MA8nO9r48B+Lclk6DXqqauMMUfPDSbQB/MOUv72uDoGd0FndqtrHP1hHK6INKs8j1NtVHYLC1K1G1K9oLOAwoVKaf0+GNwTnUUrs9sCR2qViKgG4HGqmpjA++N1Xf8V4x0CVdE5n1vR27DWz1/7Ez0evDK7LXE0EZkc7Lorere0UhbV5Ogl0XNNLQms5nklDjnlmZQUySuz2wJHapWjji2NJ76x6CJiUjk8q2Qbhg7nQ8+k5zJ4qWS9/pvsYiDYQE9emd3e5+BgmdHKlu0SKBMJVzGpoD6tdioM94fKXgibClbZjYUbfzXQk1fWbgscadbYs6lwSIOLgGdqVgurab9lCm+gsxciTkQHdlTUWM2J2RI9eWXttsJRXCTZXGTzOHMPcpnJ74qeVlf18DjCIpeZ3xKkcqkvndiXOFxk5jBUmo9y+Kjxpcuz4sJ5W0eBUkLIG9CSKU5PL/ot6PVNDtC7iew+TAHrdtnGUD9T5kcKbXiJmm04yWG2N5BXqeRg+VCdZrzPQf6DqKXlfq0/OpiBJJehhYpMc/QBuny7JyWJ9EEWlyDO5AT9h6zYy1jgKGVPnb+OinLtnp9Ukbt13e1HOfqm6JzYRPdhDNEZZMfUTGcHfYEDkZIiHvwOCi3b+/Mx249CvCa6hefELAGdxEcyCQ5y/f9WdW6BQ0Twa7FZgbHXsxXylNP9KGqhs1inWN7ZYf8dLykpBgrqh6pzCxwpkgPEyIYJl6PUiz7Z9ImpHv1W0fdbdAl2l53i0LMos7ODvi9x7CWNG6Mg4pXRNPmC12tY7k+VboZuv/NzwVrIBkojSI7ODvoCh4mEd0FvOf6Lg+qZ5F+doE/96MV1Dn/URO90dtAXOFRk6mpZx80HdXhSFEfXEBWP6ylSxDLfCn6BKfUh6CsciKT1XnW9+UjskYTcyL/voGtgkkdzSWGkO5klckFa6eygL3EEhswdESfrRirFcoPUYasX0HWjf5ZTVtdsxHQ1xP4R9BWOUToinfylTiYFSGHVjF8UnsTR9+klTUneE73y6Yegr3CMnBG1NXrfjmmlXyesk/23mKLHbIjzKJMOet6fFv+R6AsciKR5Y5YQtFsXpJ1m2olDu2vz1UsJRdf8DhrHqJ+37LbpMcK091VQZONNDtDZr0FEfmEoLbRF1tNDXqr2+8GtBN0vmZ7kXIckTBjxBy//j/iUvMuBdSNFGiLN+vJk+j11/76yEAkRTXQGX3uO8zV+wFcxURjfBwKPFp+VP5Y42KJE37ibyC/7WKY2SwvIamKUoeibXb2iKGtWDMZj0jaNhE5b1VjgSBXJRbyThHZ0P8OmzU4fYPmMu4ehH/5aLy7Hec1babLz+udpka3jbQ5FbwUR7yQSUOifnp7qN4qaokEf82tew3Q7HD+TiTZzJPVjgK8rHLkmyKZSEfFO4p6LnhwUVqwLqsw5Ohg+t8PO0qg/mMQu/E/J/29lgSPHzPEUGYh4J5Gn8zw1ln+qAXiLHjbYSTJRMlKUOqRffXxlzW9lhWOjqbAy4somYh83jTXVVUeoHksUgKG3oX9TLj5uYtTk3n/+/Zd29SYHsfRhIs1F/Om6Oirpx12VOWI/DL0j5roXU5uEvvMl11ng2POSw0RqmIg/nU7R4S0eZW6Obk7AojYS3YYr5OnvPZY4gqaiIow9KhI+U2hn94AdaB293zplnFTRE4yfSYTmCscofSJSh4t4iKl1djs7uc7R1emlz1ZuOABH6fn7h78Vgm2FgzUwItzfRzSvmOqnBXhnR5lz9Ca1Ev/Xyq2x+inHuKLUkDGiLnHgRt7yL/3RzNvOfrFByBcN9OLoZtZC2s1zDbeEhuJzZJPAMWWBI3sJf+1TQxZyguvjnHZ27LGOngKXHVJy2iCPdSovyRcnnaItcdBLVAQS96mndHcQs87OChL0ePVkvEbR93id7fKET6xeEKbac+t+gYPu4SK2gzgf4FlTq+ju6KG3oM4Z7od+mnid1UuXG15s/SxwMECkiNA0Ex/yxB5graL0qxT2RWtReVcEWbmhwjf5ol4jVf19gQPrNrEjNoBjReHb6z9X0e/9lISkJsvAPfpwVzkevCaQOhi2l+QAscDBi8IIQtHzvzV3cPVT+XYf51p+fo+OxDnxFyXKgVvIj+pY4GCAYHbgGDHkZRphc1EalWQPt2Pm4g7dVKYuLR49lsn8ukKSMq5wMBkyLZRycuIf1jj3vrq0q8s50sRNMzq/ovc5euMZLWodPXbkzH68/qgvcXTpJZWQCTclADTUYswT2hBfUeEfakiUkCg0E5dWQ2FvPUpP7Gswr2eJFQ5mBF4a609Eaij63P1Z9Dm6aR2ljbOkkXyGvinw4XmncPe+Bo6FvJwFjhKlSS8pnCyAyKF12eboJdz1fKS9qLH74uhcevjQBAN6bAEEJ9oljsqLyvbCnq6vp5mtpqEOtm4lh3nPezi6Z/20Fs/KjIhQSOqVD7jEkY9VeGk0VUT0uFA+9cKtJCavkgQl0WetJpAGTCMJiAiVxc81kn+Bo6WBg14iR3PtNuLcoVd1n070nGZBr9M2s+kHmseesEjKmT3/WuJAOya/Ceq3OPSJSMzQ5cv+Hnqb+leLKTomW92LHIOmotm7fKGaVXGTb0hPuKCjFwaq6hfgfq55Y86uyTV5O0sc6P1yVi+9Wl/0DJ1fi+WMHdLKbnb1C2jDND1VjM1t4mtWFzgKql+K8KmMupS4Q+fn9fUc0bRj9Ak6YgGPDksbAddEvufkzk/aAodmq6hcnPxkjVvlRW7Qy+nokd5ujNFD87KdGoZ1ashBoqPCB5ac61Uz7e9z4KCfklXPG9qZAs9kmqN7joUB+iig0xQBH6VdUc+XOUJ9o/OampCgnTglExT1Nge5SFMSEcJnS2etNkOfeJu/ondB30G6hoRJDj2coqunaWTdYr07Bm70bYGD9WBKNkTIxxhy0FC/RS/h6HkxZuZdF1KmD+5UNuisw+uZ5HLmaT1XOPKHpLNxkSHJ77cpOk/a1WDVQcdyhJPuZBVgnb2yYaAH+45sMte1xKEa4KYRLrtowtsc3behU/hpNQvQ0bMYnv3YI5S6UHRwbF5f4hANMP8nRy1XHcDm6BIbAzqLSTYEQa8xQ9czskDv89MeVjhUAyz97yI7aFN0OZ0M9AE628Dc4ii36E3QN781XWaFo8bLKjc3Ml0kZEdxih7W50GXyBe36SOoDb4qusvQclY4WnmxaeVvXER67xy9vzR8GkhXdAbfNiaGGlv0E5vP2O9+myscXY6HchHMTvfokqMK9E3Q0TbgE3Sd3FKOS1WEfKRb4MiYEsaQ+LsIl5+iSyX1GfrI8Z7G5+gJMEVvRZ0qUW/q2xySbQ+DEiJdRbY5uj4pfwarTZ6sDI55dXQUWRs4UwypI8qTPR7/XuBg0wYqRNgzd/T7cY7X3UodoOcfjOL1IrgPdJYvOk+mmIRPnwUt+IgFDjZtGLxDzrnTF3iDLjFwjZY2yit6ZD9gbtJtZj+rBnRGQFxs8CGPFQ42bfJ7uR0fGfq9UsMgWgfojNLpcqQRu5Nkz1xvMGW54AoHB0lWRErndnhKxD26NdBSuWckerZGEqNrzDJijs5j94IWroJrHGTfzbFEI/MrOvAtup/IXLnn/kTfxYbCmHXeoNdR6CSs1HWWWOAg57Iub8g/yQh5h+4HAVfu2UuURJfuLnuLc3S0PHb1DrfVr3Bw+CEiHPGg97tDl0wyoI+SGYJAj0JCyVP0kim6GHdLPVV7zbLAkbetegDLIckOmYQVHeugtXheNYv2Vjpq2p5atl6nzdC7mvSH3pJqXONonKmxMz4F73OX8aEb+om9wfMCVHYKa9lwkAZdtlcCKS2bbOTME5MvcZzUByLlGKQmwLCluq+GO1FkVxdfgaij4RbfWWXMnHscPWwzEwUW++/7HIyNfIW7BuY+KjNSZNcnbsIefMEg2kvkGJQWBD9zz49DAF27z1YoZ3s12tdrgQOvbeZ+z5HHOAk67dTYDx4Zv6D2Df8cZRvodm5InS5o/Fg19qCOeCCucOC6jJ3eDxbCeU3R+XWDQlynBgPvN3xjfIlEH5b2YIK+uZcRHSatkmOFg6ejf9oQK7miqsTzmMFAXKcIfIpa2jhB30FP5246xnwFb5adrjPbEgfTQooMvxyZuwPt1JSpU2+C/pXSvY5yDfFw5qTVenKFmDrYcNPOrXXQW+KQLuyDLLPhMdpAO/UjGeUmMhXVyINOdCth50oECbYxQR9/y6GkN13iKNy/T4MBg1htNXaoFmd7pjjv1HGATsQxTS+IBbdCMkLR5v0E6AUOGitW+d1vroxmb7fXEEykPGbUIfZ0UgEiOt+81V5+zgJxFjjKQdq3adBz870hTzHnYQYEfeb6BfQt0WU2mKMzt+v6SB92iYMTsk1poClr9C/X9WAFnYu5Vksl3tFbgWqOzgDvub9AWeAAYNdjxW1acE/WebBfQ4fgrjUaFQy6bs3O0ZPJtUVBaQsc4uTGRzYtiEg11R0MHgiNiRU7twcdw8a06AJU0jLlX5CvcOioXMekpYjIpTEanuYa9YkWfxQ2fEHfTdTQbTCXf3bI1zh01BizloKIpGWQukYA0zktfpClKgwdUS/h8XWnaxb1XORQfSFMpE1Sw6NC62l7PKyonWc5RmlD+3oAOCtD3HLB5Z8ny7ZVjlBnI6/PNkGvVzC4igBKOS2+XKUXRfeQB0dH7aFccOWtG+QLHOgoLkK31Z9CzpTqnZ2PcozP1+ToOhM5+u5Zuo7hjW6Rg2PPTMQ7SRi5DyyHBLRnlErWLOgddCVzdF+oVG/Mqxwt+E5FvJNM4vMOD+imsx/jeLT4Iegb6N6LKPgXGquXBY5Gi5Hvpp2kW6ow7120glxV5/9Oftqf6IH4DJ0l121Z4DjlO+93NkcbuWeboxW08Uw/2EuDZn+i796LHD3l78qxzsF3LpJQJ5edZeZpeu+Ueh4f2QZHaxv6PLig0W/u2/oSB8WD0K4wsGBv3y0Bpnc0UtQEvhYcZwex3NQzM96393qucVAw4FPaOAzs4FpuCaA0HYhbJkXnFpz5A6IXNk9Lu2/uZY2DwrYNamrP55dRtl4Ft96GV0R3qw3/zrFuMN2Hoc/gdq9ALVx+gcP6VoZOXhpJJiCVsTT/voZ1duz94s93MF3pcUfzJh35vzk0j73AQWH4RRnBaG8g5EmiY1tnb/LvHOorLoeWQXmCLq5D83IuctRLRAKHBwx8krtf5cBESMOPKY8WfxCoqOiziq3i2D4tbaxxHFe9govkiwZHmm44OZhsn7hlgEElUpXPKmmaMrzP57b7Ua4vcgQTFZ4+Ov234tqap5PQFu+2sKzz48oLWtqcNpvbOmQJNhvk2irHwUhY2cbjJJ9h44Plu8UMYfqDtHie6yZjkM5RSZZg00HuXOGgDjmgmXWmLgGbvisc/vBV9BQTbUiLBygsaC2mA3wdhHrMB7k2ljhQhzjOGidEMQjXF/LgBxfJTq3FUxksW4hDtPMw+mSUG7xC0dk8bfECB4a9vEP3btdtaGz0rmcDOCctvp2sqIJTZx1dq0JDvDbzk5OCtrDAUcBB1dbCjoacVNFOaXCi0PGg+TM02GArGG/WeWfn6NmJn5yM0+9ziJXpaqibUpruN2lYYd4stRVJR2RpNpMiURjm5cc2cicEVxVEVSpWOHJCPEvS0EVUNdJZgVRJVfR35hFKV0+Z4DEbw7z+2B81PIXfbC/2XQ76LRdq+DpY4DZpDxL/uHKQy+oeWSeW/0g2X0/MCIbunT1/3Liotw2eZomjnLL6ziQPoWuhwczAsBJ5Gx3k1CnE0mw2rDZd0GGYnfLp+cTdHrTCMZiumIH8SAuMnAwrDHNXkSq3zq47kKmT7Y7uLf7w9bq3eKyAdYlDenANLmc7vaQ9aKEzKVWOHE9PlYryjF4zb/EtWLR2e5tu+z0WOChX7g2xZ+f7+zuHcqIyUuXpICdy1uIP3VgYid6usAqVoy9m3hviBhsrHJSWewXusdARQW+rkSaafBH5T+/serwpcFXQTw4jtTmrcVVrG7apu8BRtNC+NtMFUIA7nT33vAZ6xyly0EgN0DjQUfUIbirduzoXst29tsKhpWp6C0TwymJToZ50rRP85ge+6PTGp2mnklWPLo9SyE1z2jbYcFjg0EL7UuvSi0g8l4EXql3WYspOm2d/tmIaaJoqGIvMSZznj1S8Qk32upO/L3BIkfY1VA3ikUugmJXC5Hnkf42/ZjaEGqKaKxPtCcPOduKCNcoxoLWuXmKBY7794iLZp1LDOrHMZiNA4Z4M8SVAagxgPGCihkUGUHsHXze5PCaiBY6/b+VPRXKEO0sbjx39dlLtLLN8iKe2WMOjypLaQ9oyZhVeTsin5slWywoHhWlnIkLXy/O9c5hrkbi0h5k+R/ViFe6MYToKUulETjCSezI2POlXOFSkmIh0zhydjscfDMVtPGeoIEzZ9hHJyvgar8ADaELqS8zZErxgEzUhEgscUhoi8hUiWamR2wk8YP4vKzJE0I9zqsQrRM5w3Bj0NmQHM8DtnpWLEIkFDjdk7Ei7yFayn0cuDS5yV/K/fXZyp63p2Fnh2ZsdQN5kmdls6GQMWeGQIhGAJtIw8uZm+RWPracTxwlSZIikz/E+MNBsNdUrsx9avr5OvqoLHCbC03QT2Ujl1ktjiZRrcJo7OD4cD512JYMKg5WaIDuhJNbZZbFaVzi8j1RuoyKk8Bs1ypmLSgY3JmodQOpEBd1lZ0Wjw4K1sOaY8M7etBO8yzExX+nFyBWYQ1zL6Y3NjWz0BCnTjUyhpwTheKJfW77sEAo4vVmPFQ4pvtOBCHuEUXo5uGR28kZzV0vNOfOdtq3zJITlQrXdQIdjuI9YrHBoCZxBVISTBlIoJI76gD7HOYTtoFoqRQZ46gmIayC/IQl0eGryvsKhZccHwf2Tc0sjs27UPIBkFAb2Z3NvBWn+trWMbJ1DSTM9BhLYF2yck2VIW+DQYhu6XIh01b0cKViDY53P0mjuL2ECXMXNVb51nuhUFeg76EA3rqdd4U2Oou4xbfIOc1jMth7lTPWfMOlGxT96fDoru8v80FGuw6TZ6agqR9/4mJA7xN/l4JzI0i57e57G9fl/uWbHYlyjBBXfPVYAdKrIfaN2S6ah1iQf4pseA/g2R7me1VNPxuSZSKmlZXfPPs1eWy8HFd9ucrKBGHpYLSlU2lB9lGrWIV5HgbrAUVMAI+hMJKEfnaRTuU8zdCOj5dTXS+djNzN31NZeDN2PkzET2wKHm77/KtLTiz2Pe84uTbUnOG/kmKFDid/vMJ9QwNBZBH3PP93hf4XDnVK8cKZ9lKiDA+XgiGdm4JFD/w16mIUddPmQME0/I8+SVyxwuCvSxJ3neZg/XV2icI6yMbdZtQs6jbrzCehUvKLrVoaEevLFAoeUQ/UfdTndM92GdHUyMtTSmNtmJ0s3Hbf3CXozdDNYNj96YoHDB6JjKjJqdpIkhGiU+uwGuRxT73QBYYvMtmVZxHZDt8QgrHN4dyscWkjwZCL5rh7gdHWEsveQcgWvJUfX5HGbdofk3lWiTQJmyyboCxxaGps+JpLvKlId0PoaTHo1zZPpUndO0IO5zdF3RaeGPWBW1zUrHDZAYBFVkfgW2XOUazw0KYlG48Dkzv1Fo+OLyg7A39FDCOzIyBOjnFxggQNfojP/zipzkVFGK1EzQg0Mqj3qeI5zsmcPh9oJN/5ydMRZybo9fzeNZoEDN4x2vlrLrf2MOrZvqa6jXJbIJlSyI1iCHql1jhl+A93s+R18ygKHeFHlc9v0VMujh3xLhZwtDFQOHIF/EZJRtK/zyP0t9O4pKXS/dIVD3Ipprm24yF5LL6MO37poOV2komJV7enjPV0SVmJHH8WTvzRL0r/Aka0DSdn1EZFWouX4UH1kDXItNW1n+szczKJ02Rsw9GJ772O2Vfweh51+zl6fijx6yJbjQ/ORtX9/05jbaGf6zOKRH3xyh67jHMxDpvUFDvNl1b1cRMpDJBVZH1kf75GM/zjV+TOzEksiR0dA0fOy6o8iXAsc7uztGf9SpI7H+LDL3EuF9hLMbcK++4mrbKWV8L0oBGgh3nFcG1zh0KsecvC3iPQcH9KqZXpS6obMbbDLdXDq3zQfrGTENm3OO04hAzGgKxwelIgPt4rstezffKPYAP9vKVHJJtaGPNCmV8cvnF6p6KN0R6f2xO2O1XsvZYFDmqRMDHWYSGwlRIPP8vH/vkpPVbaEbBKDTmW0YCtNgMgrPhBgXDCwSHSSZ7ZRVji4vajI1g9b2dtjfKiE5lF+l9/lMWi25OUAHkOvxIKUyiOqHS7MdYDvxc4EOoe8LXBo62047Eif20psZfQyGnYKylf5+MwhfshKuRu6bjd4quyu7tIEJHp+Lw5MYlJY4aiTKJquImOrY69DQu6zfJby+VCQSohJsDm6b5u0UzE7CJr0WkOEyDtNMNwKh4d9MQOpSA6NG4uXH//mlz8+S/lKtbiLSbA6um+bMBwOmNSxNhBSnTfR6fkLHPZsOHlXFRl7zgqsMD5+fCX6o7unIismwTom6I2P6e54lDCxW5iVxr+BTp9f4OgsdVF7cdVApNexp/Zb9pLf/Cy/Qf+ZqmHV5EExQe9aFxfjQ9XZrZdJWo0AnaluhQMLAumCdOsrr5pTwtjKTvDC7/LzBX2vT78C+hdPpMWznV7cLGSIl+a6yQVAZ0tygUOSNh5pz8MWwK32WlLxD0JRf5UPQR9VsrXqE3m8isx5+cJkiNdBSl9hBx3dboEj5VUH6+JjniKtjF5HLyOVDkcvqevQv6bodGuf73WIbwAlByW7Fuj599scoNNTUhXVyIK9xGN8SEDQfzLC/0TDpX8l9ST5maBbrH5Muzro2IrQTBY4Uq6Gdjw1BETOhrVks95Q4lKl+UbPdY0Gsscs5R1MWjhyVLu6Hl+HAreD/vjRAkeVl0oPkSii8S1SopVAj2Vy+67+hya753RB//IlOTfwz/WgWenq2XWlVNAJDl/g8LigAy+XjkgdvaoKj0rzzV2+HuhdM/jSDnNHws8N8IILmnjVHFHm6NnayjpHaKMLTYY6ao4PiEj5+PzxWXohKW5luQl6e3ExOW8Sc/RSdfav4f3iBf3IV7zAQc+TPTQ6CWu9VH1l64X1y59Sdo7gFW83MUk84K8BpBXOnhS356tYGSVAr/n9Aofrv41Yc8wftcRWU/XdHP3PV+5bE03EBoNsnjzgk5y4FT6QbB6SNKmNv6HvuhGywIGtUMchpmh2GEavJRroWjiOkzFuox7A9N3QHL50COs5zjFH8r2UIBkrZYFjIMcGIcEM6OJbGbnE78XR+U32K9AD9DpJCxi+S9DyUizv+FrK7ugLHDlBsM67OD4lyMEyHlr/9rBjTtA5qa2KM5Sje7Fdgl6aZ7+4Q69vc8iQc0muAIaYozy0/v6wY07Qa6IzxmF4vEX3mNWNgTKoMEPvRdHr2xziejqef564/tUrajxERtoxZYXvhpO0EeP7OO/rSis9p+VFNE7XRxbd6m4LHIUuctL+Uo+Ogm9ItDoilztASdlAHxLBxuQ+KzoZc542a49ziq6z7LbAwWtvTLjkO6CMraYm8BCps0yI7CRyR+ZoKyrs+vlOxU/Qq6IvcMiREISzPFc9WVL/e+j8ho7M/oqONKbDu84uqeJoN23ysgy9L3BYkn+Cl7jIw3pdR9TSHJ0rgM5ZrKDPCKClkGJ3mlYSI1vVaL8FDqLAXQtqwUX2rRb2Vxz9FPR4fSzWkvfj3HU+Z1+mpZihN14v6G9zcBS9akFp0CS+LPpD7e++rV2vK38XTG7MKaDnL2YFA0vaVhJro9d4yTpX9AWO4ifndI4dusZzofRQ+0s4+kHy8+d3OIxyca40HeJpoFifNmW7Q48FDtWUaSnEFSTdt0iJMhw9aLWgZ29XdPUjcxOtZPAaJYghmqJroxgLHOJnC8WL2+N5RGnZUqqjtyEb/ljXqjZmdx51dJxFcnWSrX6Orvv8Y4EDy4plrj1eErhlS6lF0cVYjCa3idN4qN11jt4KV9mzw08GeA71FvQFDomPvPLpUg+o56uHVPRamicOhSwKju7y0Lsm/Zmjd7YNctrOjjNDL47+JgdO2qQgSOuA+v7VkbrvJp49+Y2dKMbJ966leqsHnZ3ilG8Zf3iHHgX0FQ6OlWFPGk+o42RL/rulaEy1RxVXsmHzEw+0dXbst9y5Ph6y3KPzfRkrHIUFyYn2kZ5QtNCzbHXExi/VAwZZXJt6qTN01240KVQvOa2POu7Qu6IvcJAipQ2xhD4zNT704F7L6GR7GebofeEYxcn3hi6byo5O66k5u92gh65axwpHtgpJF8C5tvhZR6tjL4PFoQ5i7ZIgLnGIcdBzis6EFGW/Q1d7UYkFDpxSJGNpV8t/fexa5Aguo3bosVpU2jZHZ9TxkGuepudG1hvo+wIHu7VNdv6H7Pe0R0vRrWzA6innblT2gmYGmiPY/+cqUERS5UZWfxP9PQ5EukfIMQ/3sjdEpItxL3ZdmkzItWih49XL3IXQ5DP0Munm6E02URc40IVDI+QG3hkZvri9iGwWkkDeN5RMPpyWs/iBOaiDhJrM0atGfL7HAbq0TGyYqJ/Xo5OMppsc6N2gECtMD58+vF9F1hyDQKK30N/jQESXJPTgPO6jlc4h6rrhr0enRpoRQKdJeGZ7uQoSDPGjZteZoXdHf5MD9KYjLgec0ElUhEdA8ECVRpnj98c1cnKREnYEL0PPnlvgdUzRN/X03Bc5mrnxsjnIRQIRHpoVAyNJNXQ2yPUhaBHqOcIM3dPxNMWn6PqKFzhGEnhTZAmUmmVpiHTNDIPDR31aS3U/FQBl38wLmCF+K111mnv0BY4U0ZucstBM+0ZNsPxQLWL8vmEj902RYnvlzbyAwWplyxwBc3RNexBLHIPX4AoXOU6eg85mJwUOTcXATjsf1EncG78abkitIyf2VqTebLOHpx5LHFHq9EgQCBubyLzOvGHhQzrADpQdE6Tt0ad1hvic2LkQ533O0Vc4dhdxK2JnJ1Vj1jSxRoDOBx7/SmnuGkjbDfIjFFrL6egd9CWOFOmmbGahaTc84mi42CfUi5t2quoVYADIAE/Z8xqjohaShVXmdRZgKb/CsVtAtb+2SjAS58lLzJroJsHFmlJ5wBoDvGeUiDqq7gVzJaJfkatrHPt8I5tJuZVSxcuBc4ZRLKg/1qzW1f3sZgZ4/UUeTp+h0ZpxWdG5dVvj4CIzmcGxHSks405luOJVUFfe1TXZmC+BCHJouWLHcmqW712ys/Q1jp3GPynXqAFjHTrb1KI9u2FJ1a6uwLNRjkZZc8Wu1odNhoMytNMscHQkrUDJpGP2Jba50V+qDghjorlTle5TwqK1a59pU8NErHFsL1HnPjraIcFtgp4XEyt8GBWPRlXqNQFj0dpG8QNGA3TC0Jc4NtwxbGDQrQurIdAZi8QK7z7/4rHu1g5+8bpojRe9ZPB3TXQykC9wpIj2N6pFdcFdfufoJ04RdQDn6BtP4F2dj/YMvayDpPjIMEWVwU2iLHCkiKbv0Wrh425VBDqVLmc3xQSdn1tXhyyTBiWddRbylnGs0VjgSBHrlfKKMR1ZxxT08/lnyGRs6LoKkCt+/PtPtufMkeXr9S7nFQ/OoV7imB2FIooKkESxKTqgRKpxOUMnfNu7+o9/ysfXc7zoT+82azH0ahCXOMTU0obVjj4l85ehE6qRTR6xKfpZ/OT2P/n/OUtsZff1egOiK/oKhxjYTmtc2jbRWhy9hhxhhNQEXVZkdRA/VB4BNR2NZjNZbFiKvsDhjoameoDavTOhEtO9U5XWd+yPf0hmhWcgybPqG+jNVcFkVpV1gQMRBik7wCB0jUAD1TOA6d6MclzK0bmCxiX+Q9hcLc+kfn5MBwOKfLfAgUjjQ2lbRx7nw1V8+mhY6DiHhM0u6DyLt+RVgDnfAFaazUdrBnhFX+MgYEZbJ0Erp9gPrcVvuDOgR2pOsD6JXmeA6Axy2e5LKaAn67Pa2PfyPHsLHGJat9TulfBILk5yGUFvkIR48INJwZ6AuhcMctR+pIEqr/2sNvB0UUNZ5iCzhDWfE1TWuYeic14b/fCQzmboXa1cDHL5DsgA2V4tIxXlJ9y8scgxLME0Ih2riXQScEDf2dn0A+3C0eNFtTzp4kRLpjJHOCG7uDyBK9QLHGBoJ8GAQ1wLVz+1QXVq4cgvNNMghBS0b4ZGKp3OvpWMQISBkZP0u/ZKFziapWOm5/AZv8Hr3De20U6Ct8szOTrQ/anDlkJnzywqD/QqZz9KcvXxkhS9LHF0GYl382Ujml5OFtIdn8ogAP20xVedWYLhnfKVemyiD43Vbd8SPEfDhWmBAwgu7yJNzyNiRpIdH3K3NgvLOwxdjjlL9VXSG9UH+uAtdu5e43UBebKB/jYHf3oulUCEnQDWWaqn1iFL5e5G2HB0bT3/yu9/ljpaGqOZhJA4Th4D58gFDh2w9ApDbrmr2xBfYdgm3LwG33m1I0EH0TGOcW7URFebk1Rs8LDHWOIow9Ix++FyA5Hgq45QZWY/iLHKwJDiAx3JwFn6yxh3nDnOgc4c7L4IYg9tb3OYDlytx4hIl0mJd48KR278er26h52GznwoY9wR7XxktYpMaqXbmaBGYabHULPA4ZlDkOdeiKAg5P1596hwtPdLHAnaUHTZnmCM49TXr7LXsSV6OWUEk4gVhvEVDrch+AkriMikzuZnopN+CoVZPMC1UjRA+19LEver7AX0xlDBDrdt7CxwzFPlhKpGu/2Gd8+BL41IUlDrqdUOOuYkxjh+dHzPbh30XLOZmq7O6SscUhDhK0bLkN8MGVz2UgkibEMV2XaaE00vrGBClffzeeufhWRJWjoP1RV9gWMiomNq55eYVRKrneiHbGSpIgt7fdUsK7EXUuk85kei78bWWHyEPv8ah4nwU5YM4pqX34JFsP0h53Qb+zEEnWmZSq8nj/mjbCWao+eFD5C4zRqHichFCf4Xkc1TLDBZ0ethv7TJByuYTqXrdFB+lPZIeipsoIQr6iscUnQIo9IuMzcpWvp/0AzD9gAuapVgPBY5v93XqZYfnzXRja1Rgfr8axwuguaJd2cQoIe+oAv2vTQ103CiGNDsz7zumTGnS6hCcXQuxWiq6CscNilMrABHaXrajPp6lU5PzLcQBLXR3y8m5fGs+I+/+XiFowuBO5gsclCajKHyDSeMl8Z7VQ8/hq0ovAVUWY73ZFZ6GmB+wyP2xS9SX3oBSZ9/hYOy8Yd+jp4SnnYDv846Sjkx09DSLhnfj8EisuatvlizCPovEp5aoeso+hIHpSOid8R63xUdqa00xp9DZzfCTq68d/6I4P4fnzQJeZBfdfQ0xHvh+RRticOzOIVKBGek0YdEqudDpqjNbsfFUIfz+ChpyP3gG622X490gFN0T6u7xqGtaP979uVzehYJcWmYJXed3VIJp5EK+m+vOtDLmMW+tOHoaxxmzpMbXkwmsxNoMl6D0SWVJmqYnq5jeKL/klbp6PU2VIqywCEvRc4kybyIQxYW9HXRkvIwBFWa2pn9nJ7eZSDL7bSvScrRRG+Knh5g0n4EfYGDl2KunUfRt+vodeQAX1Oyku8re3CeYoulVtFHKZ8pQjmunJMTvcqXxyipF57e6Rc5VI0clrYWUUfnsNIHPlajyuxGlNehjHtpoMvqJG1PoBdJtZLDxiXXoaxw6OsbGn+moqHuICjtmSWc1UVDBFOjHc9ZFZ1Hy/QsoO/mAga5oi9xeN6F6fS5P9Gp0hTpZcfAmqO3mp+JsGYgc3Qi6QW9S6VPJ/hFDj70w34RVRF+cQ18G7GSkpDHanOz5Cpz9Do2klBT6V645BIHHyLS3RkXEXR/NPQEHezLVGa3P/8+Sl5Jwo7xHP/SIYB8nF+1bHLMSo1b9AWOYqcgI46oPBppYV9cuAe5fjnK9N+vkkmGP/M3XI94gZzXHX0vn090iX3xAsASh47Ym2zvqCitNi96kJU8fb1oEdlFMb+Uf9IqxnWIEkltLgQ9B0qO1RD/Cy9cconD4mmQFw//E/8dT0XfH0M8v2mlxAOYxMqcXktjGTkRfGiF7nnV8eOzlT2t5m0gc4O+wCFX2JDX7Z723/EiImfFpQ7PU6bLl+wgfr2mTWr/OUuK1JFOcqfmlSx1fGTUD+/zGLfoCxzeFCp1IIfRBCLiyXKW5MIil6f35sLk+i6PPbUAPdetaLLYLfO1XI/a+flAj3zY8KRlvHnwVjgQmY99e9YSIlhjsj6yNTMYZ3aNb6bjmRrnx2d+NljpcbjxH92fuvIRf5eebqKuxJCC4NLOvcKBiI99iOagjQg1z5ELOQWDvn/T1uBlfxJPmXY75oHH/jLs3O8rr8JzuYHONyEWOO5FsmLrQIQ9r3Yyu31/CnqUDwlT+ipbovPaOMg8HeCrOLX++CyR6JD5EkW2nhY4fMYTTQCRjb86KSzzgRMkGz3oo/yUMKXfoGM9GaXnT/78Q/NhB0ISwBv4NTzDxRKHdplwTYB8ZukeSLwy2Z2IjM72/UD/LRkYfoKO9Siw5n38qzsQZ/nIeR992I3RICG1wqEio8gWNJ8xcuwFhMZSfCudn+e09EsyMHyUluh4zOXStlzoe/mf+d1vkjl1I9fFOg++wjEX6SaSXjMgcPoxKzfQv3u3tOCq4e+BQQMHqkqq5x9fpSW6Kqo6JkgMyLXCMRfZJyL4qTLG53gs6J8vLmb1FR3dJaOB25n1ToUeo3zkpIFD0ixPX+PBj//EAsdcJKborwfNnPnTKKHoeZkzdyUSvQ7QG7uS7cKHql1pMP79kmUmnNw9TmuUY4FjKlLHHB0H0/pULAaXaKU/0NNU10rq5A90cQQ6sk3k0jfnuJrGrK+cAvCdUqukjucD79T3OfzNEEbHl4yMFTVpS5mLdRh3yOXmZ+ovz2EY9I1rVkaLB/uf19VOHXr+LlOaDWospOJtDusPPF0X9QBbHtaEOpiR0iRr6LwgQefqwWx+idvgb3rxa6SOg1ONLCne5HB0IsJVH66Cvr/YHh9UM/Sd9XepaiY72FWvV1Y2nsIbXCV8ZNfzWgljfpvD0TXwEoefVgSdnTWs0fTAViLRCaZ/7Je/Wk6YIVji4D73h2kL31M10uSCUCwbtOu3OBzdTkvOy3dBD3bWcpamJadn71/RJU1SkAAwp7Sc4R6VjrKyufc9J/SdeXkmwPo+RxkqYmnWn307BD1XH9Tg9nf0DfSW6JKtoY3CCH+mVvfgR0XFrHL4xlLjkJD8sr7BMUc/uBkiqToLejYdDj7piv71NE5Hom+JXgYEAx3sol2m/bY06i1Rk9aPtG0cabbEYSLZIaLYkSrEr26YFbnkq+tH1NHLrxx7c87bfzzQu2hnweBVz+T3c9qD/K9ZEEmoiiFjicNESLtCqRK1jAsJFf3o0VwhPXsTvUSGwP54Zlqpwkfj1ZhAAg+5qOlzDJSUBQ4T8VKHitShWUPjr+i9MHkNQ5cMr9I0pdv2Oblmxl/icBEvJsJ2YcHapujlN92hJHr+pHnix+fkRlOW8KZ5hnVdzq9x0AOmIqEiJWqA/lS9QtF/GvooYYkfGeCP1xn4VKd3dUhC1ZdF9xoH8UEzES7Ieu149na+HRJCM5qhd8KXdMOc3VoST0qiBx/aWeAx2mSpCxzlVoRvSd90PpRXMXQimHGJP0sT9D3Rd3yZqPZSOcrvChA9Dwzk51NWTsmoCxz3IqWZCOjoxAhmXOJPyTD2keho5HGMZKaaGwmTTksfzo94URzgpOgrHHxoItAhMgQ9Rdv/jc65xQVb6olixg7O/KgAyULMv/WA/rrIIVbLGxc9enjlGcpm6B8TdFViD5RSbuGKjTzCMfz0ZqAXOHgHM5GOCOJsjezZBIai/3B09qZQ1JjXQzROU77kgG0GST0XZlvh4KdzEc3gqOhBE1D0OpAGHf98UNslWaGsebIuNlN019OAthUOAEyEu9Vhbho7HPyDZ/pGl21+QSevBcOW5TnwbHXBb59KfdNxblvhSJKZyEm8hTrnRKl8pOj7Hfom1ofGMUGzzs4zX8+ogXaS3Q20RQ5uXIe3unj5mpFEqzAW0MWPT50poclv9Xy+azAwbqqgvc0xeJxJhrRDNSzMvnDYyWqKXvoDPVSEwbrUmHZ2jTQ/kcKN5UVBW+CI/Goi0okeVeWyTtHrAJ1m8DO3ntE2bYreJp2dHs8fAYoeILbAIcepWqvDmMGvWOzDwXvgro5eei5aBR1tjohsvzkLWv6gqTQ9zG6Bo1l7ERE0SkQaSgHo4mj8V/TN0Zmrqp1kAE1CVqqfeZ2TbPlggYO+OxXpXLIKv6ADGoYeic4Ce9PAR47LHnra3YtiL8sZvgtJi7HCcUl4tIlgGEVk5LXhoAmglCr6eKBzfjTPhdmlkyPnol5tnG7ZAnKzguNcaSsLHM8ut/MLcb7etZlLeuvd0TPoYzzQQ9E3BuSmG+Yo421cZK/y2Rmrzb///PsPx7nS0xY4CkHoahqIciIypK0TWwEH6CnzQJeNlp/pciI3RqPJkZEpW+2TFKblP59Z7700etoSh1xVzeRN3JTQqEEnvJWOT39T9PJYwjZsqNWnHX4sjdUMUPEMgv2HuMIyyioH605EZB5Ul9hN0FvSYufikoreEr2SpqsO943o+oG9BQbCP8/MNbVg/Vjj4GYapsu6siHSBb3x60TnN46+PdBHVm3XLoy9ZdMPEJVnbCTk+/GZc1twmwUOao4+gCyTAbNYB72CEDifUwOjgZ5CP7OGuh0CyA7GZqtqbwBEgj49L3ZOrlziYP/Kzt/kMSsiu1qOQlJPUJ11bN/onQ6b6EEkRLfk2NxZgf246Q/8D8oO+iIHPYIfSRwwX7GmJhaZ3Beg14FzwQ9JHfQTL/AaHjavpg4uU2yLbpDkIL2sOuhLHJoWSlVIFGxRXWnnvGHQi6Lz+D/xAvdNFfaxfE7zM5fLl6bj66AvcEgysN3Ph64scHQG6/kdCjxIoDeuXT6yTZOgrEgJRefJPYqSrl5KoqeCuMiBcdbtn1Xc8ar6L2zwD/yDNkGvcGTPr8POdCbU0XRWRWdp96GZCHXfbYlDD/fQ78rFzeksNHYWH4bO1SLRt+cPw4d43cJAUsN4crxk0/FXZiJUwQWOqg2RF1KsH9EcMRzk7Q1dTujJ5r/T2bteGXQqy9A742Ues1p+O/oaB+qZ2/N19NQzepJjhr5zqWwDucRkm4nVTiuVq5pHr3pB/8aw9DPRqeElDkRkYDQRdscHv8GZ50EDevtG/2TuS/T0vWnqCJghQH7ceDP0kUK/cFEFHaE1jqbWMbVz8ZkqiQ1dLmlAz4H383WFnc2/EtWL7vMUTXTXZTU69xs9VcJE72KJf5vjfwF77wcpLxPbrwAAAABJRU5ErkJggg==);\n}\n\n\n/*\n * Homepage\n *\n * Tweaks to the custom homepage and the masthead (main jumbotron).\n */\n\n /* Masthead (headings and download button) */\n .bs-masthead {\n  position: relative;\n  padding: 30px 15px;\n  text-align: center;\n  text-shadow: 0 1px 0 rgba(0,0,0,.15);\n}\n.bs-masthead h1 {\n  font-size: 50px;\n  line-height: 1;\n  color: #fff;\n}\n.bs-masthead .btn-outline {\n  margin-top: 20px;\n  margin-bottom: 20px;\n  padding: 18px 24px;\n  font-size: 21px;\n}\n\n/* Links to project-level content like the repo, Expo, etc */\n.bs-masthead-links {\n  margin-top: 20px;\n  margin-bottom: 20px;\n  padding: 0 15px;\n  list-style: none;\n  text-align: center;\n}\n.bs-masthead-links li {\n  display: inline;\n}\n.bs-masthead-links li + li {\n  margin-left: 20px;\n}\n.bs-masthead-links a {\n  color: #fff;\n}\n\n@media screen and (min-width: 768px) {\n  .bs-masthead {\n    text-align: left;\n    padding-top:    140px;\n    padding-bottom: 140px;\n  }\n  .bs-masthead h1 {\n    font-size: 100px;\n  }\n  .bs-masthead .lead {\n    margin-right: 25%;\n    font-size: 30px;\n  }\n  .bs-masthead-links {\n    padding: 0;\n    text-align: left;\n  }\n}\n\n\n/*\n * Page headers\n *\n * Jumbotron-esque headers at the top of every page that's not the homepage.\n */\n\n\n/* Page headers */\n.bs-header {\n  padding: 30px 15px 40px; /* side padding builds on .container 15px, so 30px */\n  font-size: 16px;\n  text-align: center;\n  text-shadow: 0 1px 0 rgba(0,0,0,.15);\n}\n.bs-header h1 {\n  color: #fff;\n}\n.bs-header p {\n  font-weight: 300;\n  line-height: 1.5;\n}\n.bs-header .container {\n  position: relative;\n}\n\n@media screen and (min-width: 768px) {\n  .bs-header {\n    font-size: 21px;\n    text-align: left;\n  }\n  .bs-header h1 {\n    font-size: 60px;\n    line-height: 1;\n  }\n}\n\n@media screen and (min-width: 992px) {\n  .bs-header h1,\n  .bs-header p {\n    margin-right: 380px;\n  }\n}\n\n\n/*\n * Carbon ads\n *\n * Single display ad that shows on all pages (except homepage) in page headers.\n * The hella `!important` is required for any pre-set property.\n */\n\n.carbonad {\n  width: auto !important;\n  margin: 50px -30px -40px !important;\n  padding: 20px !important;\n  overflow: hidden; /* clearfix */\n  height: auto !important;\n  font-size: 13px !important;\n  line-height: 16px !important;\n  text-align: left;\n  background: #463265 !important;\n  border: 0 !important;\n  box-shadow: inset 0 3px 5px rgba(0,0,0,.075);\n}\n.carbonad-img {\n  margin: 0 !important;\n}\n.carbonad-text,\n.carbonad-tag {\n  float: none !important;\n  display: block !important;\n  width: auto !important;\n  height: auto !important;\n  margin-left: 145px !important;\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif !important;\n}\n.carbonad-text {\n  padding-top: 0 !important;\n}\n.carbonad-tag {\n  color: #cdbfe3 !important;\n  text-align: left !important;\n}\n.carbonad-text a,\n.carbonad-tag a {\n  color: #fff !important;\n}\n.carbonad #azcarbon > img {\n  display: none; /* hide what I assume are tracking images */\n}\n\n@media screen and (min-width: 768px) {\n  .carbonad {\n    margin: 0 !important;\n    border-radius: 4px;\n    box-shadow: inset 0 3px 5px rgba(0,0,0,.075), 0 1px 0 rgba(255,255,255,.1);\n  }\n}\n\n@media screen and (min-width: 992px) {\n  .carbonad {\n    position: absolute;\n    top: 20px;\n    right: 0;\n    padding: 15px !important;\n    width: 330px !important;\n    min-height: 132px;\n  }\n}\n\n\n/*\n * Callout for 2.3.2 docs\n *\n * Only appears below page headers (not on the homepage). The homepage gets its\n * own link with the masthead links.\n */\n\n.bs-old-docs {\n  padding: 15px 20px;\n  color: #777;\n  background-color: #fafafa;\n  border-top: 1px solid #fff;\n  border-bottom: 1px solid #e5e5e5;\n}\n.bs-old-docs strong {\n  color: #555;\n}\n\n\n/*\n * Side navigation\n *\n * Scrollspy and affixed enhanced navigation to highlight sections and secondary\n * sections of docs content.\n */\n\n/* By default it's not affixed in mobile views, so undo that */\n.bs-sidebar.affix {\n  position: static;\n}\n\n/* First level of nav */\n.bs-sidenav {\n  margin-top: 30px;\n  margin-bottom: 30px;\n  padding-top:    10px;\n  padding-bottom: 10px;\n  text-shadow: 0 1px 0 #fff;\n  background-color: #f7f5fa;\n  border-radius: 5px;\n}\n\n/* All levels of nav */\n.bs-sidebar .nav > li > a {\n  display: block;\n  color: #716b7a;\n  padding: 5px 20px;\n}\n.bs-sidebar .nav > li > a:hover,\n.bs-sidebar .nav > li > a:focus {\n  text-decoration: none;\n  background-color: #e5e3e9;\n  border-right: 1px solid #dbd8e0;\n}\n.bs-sidebar .nav > .active > a,\n.bs-sidebar .nav > .active:hover > a,\n.bs-sidebar .nav > .active:focus > a {\n  font-weight: bold;\n  color: #563d7c;\n  background-color: transparent;\n  border-right: 1px solid #563d7c;\n}\n\n/* Nav: second level (shown on .active) */\n.bs-sidebar .nav .nav {\n  display: none; /* Hide by default, but at >768px, show it */\n  margin-bottom: 8px;\n}\n.bs-sidebar .nav .nav > li > a {\n  padding-top:    3px;\n  padding-bottom: 3px;\n  padding-left: 30px;\n  font-size: 90%;\n}\n\n/* Show and affix the side nav when space allows it */\n@media screen and (min-width: 992px) {\n  .bs-sidebar .nav > .active > ul {\n    display: block;\n  }\n  /* Widen the fixed sidebar */\n  .bs-sidebar.affix,\n  .bs-sidebar.affix-bottom {\n    width: 213px;\n  }\n  .bs-sidebar.affix {\n    position: fixed; /* Undo the static from mobile first approach */\n    top: 80px;\n  }\n  .bs-sidebar.affix-bottom {\n    position: absolute; /* Undo the static from mobile first approach */\n  }\n  .bs-sidebar.affix-bottom .bs-sidenav,\n  .bs-sidebar.affix .bs-sidenav {\n    margin-top: 0;\n    margin-bottom: 0;\n  }\n}\n@media screen and (min-width: 1200px) {\n  /* Widen the fixed sidebar again */\n  .bs-sidebar.affix-bottom,\n  .bs-sidebar.affix {\n    width: 263px;\n  }\n}\n\n\n/*\n * Docs sections\n *\n * Content blocks for each component or feature.\n */\n\n/* Space things out */\n.bs-docs-section + .bs-docs-section {\n  padding-top: 40px;\n}\n\n/* Janky fix for preventing navbar from overlapping */\nh1[id] {\n  padding-top: 80px;\n  margin-top: -45px;\n}\n\n\n/*\n * Callouts\n *\n * Not quite alerts, but custom and helpful notes for folks reading the docs.\n * Requires a base and modifier class.\n */\n\n/* Common styles for all types */\n.bs-callout {\n  margin: 20px 0;\n  padding: 15px 30px 15px 15px;\n  border-left: 5px solid #eee;\n}\n.bs-callout h4 {\n  margin-top: 0;\n}\n.bs-callout p:last-child {\n  margin-bottom: 0;\n}\n.bs-callout code,\n.bs-callout .highlight {\n  background-color: #fff;\n}\n\n/* Variations */\n.bs-callout-danger {\n  background-color: #fcf2f2;\n  border-color: #dFb5b4;\n}\n.bs-callout-warning {\n  background-color: #fefbed;\n  border-color: #f1e7bc;\n}\n.bs-callout-info {\n  background-color: #f0f7fd;\n  border-color: #d0e3f0;\n}\n\n\n/*\n * Grid examples\n *\n * Highlight the grid columns within the docs so folks can see their padding,\n * alignment, sizing, etc.\n */\n\n.show-grid {\n  margin-bottom: 15px;\n}\n.show-grid [class^=\"col-\"] {\n  padding-top: 10px;\n  padding-bottom: 10px;\n  background-color: #eee;\n  border: 1px solid #ddd;\n  background-color: rgba(86,61,124,.15);\n  border: 1px solid rgba(86,61,124,.2);\n}\n\n\n/*\n * Examples\n *\n * Isolated sections of example content for each component or feature. Usually\n * followed by a code snippet.\n */\n\n.bs-example {\n  position: relative;\n  padding: 45px 15px 15px;\n  margin: 0 -15px 15px;\n  background-color: #fafafa;\n  box-shadow: inset 0 3px 6px rgba(0,0,0,.05);\n  border-color: #e5e5e5 #eee #eee;\n  border-style: solid;\n  border-width: 1px 0;\n}\n/* Echo out a label for the example */\n.bs-example:after {\n  content: \"Example\";\n  position: absolute;\n  top:  15px;\n  left: 15px;\n  font-size: 12px;\n  font-weight: bold;\n  color: #bbb;\n  text-transform: uppercase;\n  letter-spacing: 1px;\n}\n\n/* Tweak display of the code snippets when following an example */\n.bs-example + .highlight {\n  margin: -15px -15px 15px;\n  border-radius: 0;\n  border-width: 0 0 1px;\n}\n\n/* Make the examples and snippets not full-width */\n@media screen and (min-width: 768px) {\n  .bs-example {\n    margin-left: 0;\n    margin-right: 0;\n    background-color: #fff;\n    border-width: 1px;\n    border-color: #ddd;\n    border-radius: 4px 4px 0 0;\n    box-shadow: none;\n  }\n  .bs-example + .highlight {\n    margin-top: -16px;\n    margin-left: 0;\n    margin-right: 0;\n    border-width: 1px;\n    border-bottom-left-radius: 4px;\n    border-bottom-right-radius: 4px;\n  }\n}\n\n/* Tweak content of examples for optimum awesome */\n.bs-example > p:last-child,\n.bs-example > ul:last-child,\n.bs-example > ol:last-child,\n.bs-example > blockquote:last-child,\n.bs-example > .form-control:last-child,\n.bs-example > .table:last-child,\n.bs-example > .navbar:last-child,\n.bs-example > .jumbotron:last-child,\n.bs-example > .alert:last-child,\n.bs-example > .panel:last-child,\n.bs-example > .list-group:last-child,\n.bs-example > .well:last-child,\n.bs-example > .progress:last-child,\n.bs-example > .table-responsive:last-child > .table {\n  margin-bottom: 0;\n}\n.bs-example > p > .close {\n  float: none;\n}\n\n/* Typography */\n.bs-example-type .table td:last-child {\n  color: #999;\n  vertical-align: middle;\n}\n.bs-example-type .table td {\n  padding: 15px 0;\n  border-color: #eee;\n}\n.bs-example-type .table tr:first-child td {\n  border-top: 0;\n}\n.bs-example-type h1,\n.bs-example-type h2,\n.bs-example-type h3,\n.bs-example-type h4,\n.bs-example-type h5,\n.bs-example-type h6 {\n  margin: 0;\n}\n\n/* Images */\n.bs-example > .img-circle,\n.bs-example > .img-rounded,\n.bs-example > .img-thumbnail {\n  margin: 5px;\n}\n\n/* Buttons */\n.bs-example > .btn,\n.bs-example > .btn-group {\n  margin-top: 5px;\n  margin-bottom: 5px;\n}\n.bs-example > .btn-toolbar + .btn-toolbar {\n  margin-top: 10px;\n}\n\n/* Forms */\n.bs-example-control-sizing select,\n.bs-example-control-sizing input[type=\"text\"] + input[type=\"text\"] {\n  margin-top: 10px;\n}\n.bs-example-form .input-group {\n  margin-bottom: 10px;\n}\n.bs-example > textarea.form-control {\n  resize: vertical;\n}\n\n/* List groups */\n.bs-example > .list-group {\n  max-width: 400px;\n}\n\n/* Navbars */\n.bs-example .navbar:last-child {\n  margin-bottom: 0;\n}\n.bs-navbar-top-example,\n.bs-navbar-bottom-example {\n  z-index: 1;\n  padding: 0;\n  overflow: hidden; /* cut the drop shadows off */\n}\n.bs-navbar-top-example .navbar-header,\n.bs-navbar-bottom-example .navbar-header {\n  margin-left: 0;\n}\n.bs-navbar-top-example .navbar-fixed-top,\n.bs-navbar-bottom-example .navbar-fixed-bottom {\n  position: relative;\n  margin-left: 0;\n  margin-right: 0;\n}\n.bs-navbar-top-example {\n  padding-bottom: 45px;\n}\n.bs-navbar-top-example:after {\n  top: auto;\n  bottom: 15px;\n}\n.bs-navbar-top-example .navbar-fixed-top {\n  top: -1px;\n}\n.bs-navbar-bottom-example {\n  padding-top: 45px;\n}\n.bs-navbar-bottom-example .navbar-fixed-bottom {\n  bottom: -1px;\n}\n.bs-navbar-bottom-example .navbar {\n  margin-bottom: 0;\n}\n@media (min-width: 768px) {\n  .bs-navbar-top-example .navbar-fixed-top,\n  .bs-navbar-bottom-example .navbar-fixed-bottom {\n    position: absolute;\n  }\n  .bs-navbar-top-example {\n    border-radius: 0 0 4px 4px;\n  }\n  .bs-navbar-bottom-example {\n    border-radius: 4px 4px 0 0;\n  }\n}\n\n/* Pagination */\n.bs-example .pagination {\n  margin-top: 10px;\n  margin-bottom: 10px;\n}\n\n/* Pager */\n.bs-example > .pager {\n  margin-top: 0;\n}\n\n/* Example modals */\n.bs-example-modal {\n  background-color: #f5f5f5;\n}\n.bs-example-modal .modal {\n  position: relative;\n  top: auto;\n  right: auto;\n  left: auto;\n  bottom: auto;\n  z-index: 1;\n  display: block;\n}\n.bs-example-modal .modal-dialog {\n  left: auto;\n  margin-left: auto;\n  margin-right: auto;\n}\n\n/* Example dropdowns */\n.bs-example > .dropdown > .dropdown-menu {\n  position: static;\n  display: block;\n  margin-bottom: 5px;\n}\n\n/* Example tabbable tabs */\n.bs-example-tabs .nav-tabs {\n  margin-bottom: 15px;\n}\n\n/* Tooltips */\n.bs-example-tooltips {\n  text-align: center;\n}\n.bs-example-tooltips > .btn {\n  margin-top: 5px;\n  margin-bottom: 5px;\n}\n\n/* Popovers */\n.bs-example-popover {\n  padding-bottom: 24px;\n  background-color: #f9f9f9;\n}\n.bs-example-popover .popover {\n  position: relative;\n  display: block;\n  float: left;\n  width: 260px;\n  margin: 20px;\n}\n\n/* Scrollspy demo on fixed height div */\n.scrollspy-example {\n  position: relative;\n  height: 200px;\n  margin-top: 10px;\n  overflow: auto;\n}\n\n\n/*\n * Code snippets\n *\n * Generated via Pygments and Jekyll, these are snippets of HTML, CSS, and JS.\n */\n\n.highlight {\n  display: none; /* hidden by default, until >480px */\n  padding: 9px 14px;\n  margin-bottom: 14px;\n  background-color: #f7f7f9;\n  border: 1px solid #e1e1e8;\n  border-radius: 4px;\n}\n.highlight pre {\n  padding: 0;\n  margin-top: 0;\n  margin-bottom: 0;\n  background-color: transparent;\n  border: 0;\n  white-space: nowrap;\n}\n.highlight pre code {\n  font-size: inherit;\n  color: #333; /* Effectively the base text color */\n}\n.highlight pre .lineno {\n  display: inline-block;\n  width: 22px;\n  padding-right: 5px;\n  margin-right: 10px;\n  text-align: right;\n  color: #bebec5;\n}\n\n/* Show code snippets when we have the space */\n@media screen and (min-width: 481px) {\n  .highlight {\n    display: block;\n  }\n}\n\n\n/*\n * Responsive tests\n *\n * Generate a set of tests to show the responsive utilities in action.\n */\n\n/* Responsive (scrollable) doc tables */\n.table-responsive .highlight pre {\n  white-space: normal;\n}\n\n/* Utility classes table  */\n.bs-table th small,\n.responsive-utilities th small {\n  display: block;\n  font-weight: normal;\n  color: #999;\n}\n.responsive-utilities tbody th {\n  font-weight: normal;\n}\n.responsive-utilities td {\n  text-align: center;\n}\n.responsive-utilities td.is-visible {\n  color: #468847;\n  background-color: #dff0d8 !important;\n}\n.responsive-utilities td.is-hidden {\n  color: #ccc;\n  background-color: #f9f9f9 !important;\n}\n\n/* Responsive tests */\n.responsive-utilities-test {\n  margin-top: 5px;\n}\n.responsive-utilities-test .col-xs-6 {\n  margin-bottom: 10px;\n}\n.responsive-utilities-test span {\n  padding: 15px 10px;\n  font-size: 14px;\n  font-weight: bold;\n  line-height: 1.1;\n  text-align: center;\n  border-radius: 4px;\n}\n.visible-on .col-xs-6 .hidden-xs,\n.visible-on .col-xs-6 .hidden-sm,\n.visible-on .col-xs-6 .hidden-md,\n.visible-on .col-xs-6 .hidden-lg,\n.hidden-on .col-xs-6 .visible-xs,\n.hidden-on .col-xs-6 .visible-sm,\n.hidden-on .col-xs-6 .visible-md,\n.hidden-on .col-xs-6 .visible-lg {\n  color: #999;\n  border: 1px solid #ddd;\n}\n.visible-on .col-xs-6 .visible-xs,\n.visible-on .col-xs-6 .visible-sm,\n.visible-on .col-xs-6 .visible-md,\n.visible-on .col-xs-6 .visible-lg,\n.hidden-on .col-xs-6 .hidden-xs,\n.hidden-on .col-xs-6 .hidden-sm,\n.hidden-on .col-xs-6 .hidden-md,\n.hidden-on .col-xs-6 .hidden-lg {\n  color: #468847;\n  background-color: #dff0d8;\n  border: 1px solid #d6e9c6;\n}\n\n\n/*\n * Glyphicons\n *\n * Special styles for displaying the icons and their classes in the docs.\n */\n\n.bs-glyphicons {\n  padding-left: 0;\n  padding-bottom: 1px;\n  margin-bottom: 20px;\n  list-style: none;\n  overflow: hidden;\n}\n.bs-glyphicons li {\n  float: left;\n  width: 25%;\n  height: 115px;\n  padding: 10px;\n  margin: 0 -1px -1px 0;\n  font-size: 12px;\n  line-height: 1.4;\n  text-align: center;\n  border: 1px solid #ddd;\n}\n.bs-glyphicons .glyphicon {\n  display: block;\n  margin: 5px auto 10px;\n  font-size: 24px;\n}\n.bs-glyphicons li:hover {\n  background-color: rgba(86,61,124,.1);\n}\n\n@media (min-width: 768px) {\n  .bs-glyphicons li {\n    width: 12.5%;\n  }\n}\n\n\n/*\n * Customizer\n *\n * Since this is so form control heavy, we have quite a few styles to customize\n * the display of inputs, headings, and more. Also included are all the download\n * buttons and actions.\n */\n\n.bs-customizer .toggle {\n  float: right;\n  margin-top: 85px; /* On account of ghetto navbar fix */\n}\n\n/* Headings and form contrls */\n.bs-customizer label {\n  margin-top: 10px;\n  font-weight: 500;\n  color: #444;\n}\n.bs-customizer h2 {\n  margin-top: 0;\n  margin-bottom: 5px;\n  padding-top: 30px;\n}\n.bs-customizer h4 {\n  margin-top: 15px;\n}\n.bs-customizer input[type=\"text\"] {\n  font-family: Menlo, Monaco, Consolas, \"Courier New\", monospace;\n  background-color: #fafafa;\n}\n.bs-customizer .help-block {\n  font-size: 12px;\n}\n\n/* For the variables, use regular weight */\n#less-section label {\n  font-weight: normal;\n}\n\n/* Downloads */\n.bs-customize-download .btn-outline {\n  padding: 20px;\n}\n\n/* Error handling */\n.bs-customizer-alert {\n  position: fixed;\n  top: 51px;\n  left: 0;\n  right: 0;\n  z-index: 1030;\n  padding: 15px 0;\n  color: #fff;\n  background-color: #d9534f;\n  box-shadow: inset 0 1px 0 rgba(255,255,255,.25);\n  border-bottom: 1px solid #b94441;\n}\n.bs-customizer-alert .close {\n  margin-top: -4px;\n  font-size: 24px;\n}\n.bs-customizer-alert p {\n  margin-bottom: 0;\n}\n.bs-customizer-alert .glyphicon {\n  margin-right: 5px;\n}\n.bs-customizer-alert pre {\n  margin: 10px 0 0;\n  color: #fff;\n  background-color: #a83c3a;\n  border-color: #973634;\n  box-shadow: inset 0 2px 4px rgba(0,0,0,.05), 0 1px 0 rgba(255,255,255,.1);\n}\n\n\n/*\n * Miscellaneous\n *\n * Odds and ends for optimum docs display.\n */\n\n/* Examples gallery: space out content better */\n.bs-examples h4 {\n  margin-bottom: 5px;\n}\n.bs-examples p {\n  margin-bottom: 20px;\n}\n\n/* Pseudo :focus state for showing how it looks in the docs */\n#focusedInput {\n  border-color: rgba(82,168,236,.8);\n  outline: 0;\n  outline: thin dotted \\9; /* IE6-9 */\n  -moz-box-shadow: 0 0 8px rgba(82,168,236,.6);\n       box-shadow: 0 0 8px rgba(82,168,236,.6);\n}\n\n/* Better spacing on download options in getting started */\n.bs-docs-dl-options h4 {\n  margin-top: 15px;\n  margin-bottom: 5px;\n}\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/sass-bootstrap/assets/css/pygments-manni.css",
    "content": ".hll { background-color: #ffffcc }\n /*{ background: #f0f3f3; }*/\n.c { color: #999; } /* Comment */\n.err { color: #AA0000; background-color: #FFAAAA } /* Error */\n.k { color: #006699; } /* Keyword */\n.o { color: #555555 } /* Operator */\n.cm { color: #0099FF; font-style: italic } /* Comment.Multiline */\n.cp { color: #009999 } /* Comment.Preproc */\n.c1 { color: #999; } /* Comment.Single */\n.cs { color: #999; } /* Comment.Special */\n.gd { background-color: #FFCCCC; border: 1px solid #CC0000 } /* Generic.Deleted */\n.ge { font-style: italic } /* Generic.Emph */\n.gr { color: #FF0000 } /* Generic.Error */\n.gh { color: #003300; } /* Generic.Heading */\n.gi { background-color: #CCFFCC; border: 1px solid #00CC00 } /* Generic.Inserted */\n.go { color: #AAAAAA } /* Generic.Output */\n.gp { color: #000099; } /* Generic.Prompt */\n.gs { } /* Generic.Strong */\n.gu { color: #003300; } /* Generic.Subheading */\n.gt { color: #99CC66 } /* Generic.Traceback */\n.kc { color: #006699; } /* Keyword.Constant */\n.kd { color: #006699; } /* Keyword.Declaration */\n.kn { color: #006699; } /* Keyword.Namespace */\n.kp { color: #006699 } /* Keyword.Pseudo */\n.kr { color: #006699; } /* Keyword.Reserved */\n.kt { color: #007788; } /* Keyword.Type */\n.m { color: #FF6600 } /* Literal.Number */\n.s { color: #d44950 } /* Literal.String */\n.na { color: #4f9fcf } /* Name.Attribute */\n.nb { color: #336666 } /* Name.Builtin */\n.nc { color: #00AA88; } /* Name.Class */\n.no { color: #336600 } /* Name.Constant */\n.nd { color: #9999FF } /* Name.Decorator */\n.ni { color: #999999; } /* Name.Entity */\n.ne { color: #CC0000; } /* Name.Exception */\n.nf { color: #CC00FF } /* Name.Function */\n.nl { color: #9999FF } /* Name.Label */\n.nn { color: #00CCFF; } /* Name.Namespace */\n.nt { color: #2f6f9f; } /* Name.Tag */\n.nv { color: #003333 } /* Name.Variable */\n.ow { color: #000000; } /* Operator.Word */\n.w { color: #bbbbbb } /* Text.Whitespace */\n.mf { color: #FF6600 } /* Literal.Number.Float */\n.mh { color: #FF6600 } /* Literal.Number.Hex */\n.mi { color: #FF6600 } /* Literal.Number.Integer */\n.mo { color: #FF6600 } /* Literal.Number.Oct */\n.sb { color: #CC3300 } /* Literal.String.Backtick */\n.sc { color: #CC3300 } /* Literal.String.Char */\n.sd { color: #CC3300; font-style: italic } /* Literal.String.Doc */\n.s2 { color: #CC3300 } /* Literal.String.Double */\n.se { color: #CC3300; } /* Literal.String.Escape */\n.sh { color: #CC3300 } /* Literal.String.Heredoc */\n.si { color: #AA0000 } /* Literal.String.Interpol */\n.sx { color: #CC3300 } /* Literal.String.Other */\n.sr { color: #33AAAA } /* Literal.String.Regex */\n.s1 { color: #CC3300 } /* Literal.String.Single */\n.ss { color: #FFCC33 } /* Literal.String.Symbol */\n.bp { color: #336666 } /* Name.Builtin.Pseudo */\n.vc { color: #003333 } /* Name.Variable.Class */\n.vg { color: #003333 } /* Name.Variable.Global */\n.vi { color: #003333 } /* Name.Variable.Instance */\n.il { color: #FF6600 } /* Literal.Number.Integer.Long */\n\n.css .o,\n.css .o + .nt,\n.css .nt + .nt { color: #999; }\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/sass-bootstrap/assets/js/application.js",
    "content": "// NOTICE!! DO NOT USE ANY OF THIS JAVASCRIPT\n// IT'S ALL JUST JUNK FOR OUR DOCS!\n// ++++++++++++++++++++++++++++++++++++++++++\n\n!function ($) {\n\n  $(function(){\n\n    var $window = $(window)\n    var $body   = $(document.body)\n\n    var navHeight = $('.navbar').outerHeight(true) + 10\n\n    $body.scrollspy({\n      target: '.bs-sidebar',\n      offset: navHeight\n    })\n\n    $window.on('load', function () {\n      $body.scrollspy('refresh')\n    })\n\n    $('.bs-docs-container [href=#]').click(function (e) {\n      e.preventDefault()\n    })\n\n    // back to top\n    setTimeout(function () {\n      var $sideBar = $('.bs-sidebar')\n\n      $sideBar.affix({\n        offset: {\n          top: function () {\n            var offsetTop      = $sideBar.offset().top\n            var sideBarMargin  = parseInt($sideBar.children(0).css('margin-top'), 10)\n            var navOuterHeight = $('.bs-docs-nav').height()\n\n            return (this.top = offsetTop - navOuterHeight - sideBarMargin)\n          }\n        , bottom: function () {\n            return (this.bottom = $('.bs-footer').outerHeight(true))\n          }\n        }\n      })\n    }, 100)\n\n    setTimeout(function () {\n      $('.bs-top').affix()\n    }, 100)\n\n    // tooltip demo\n    $('.tooltip-demo').tooltip({\n      selector: \"[data-toggle=tooltip]\",\n      container: \"body\"\n    })\n\n    $('.tooltip-test').tooltip()\n    $('.popover-test').popover()\n\n    $('.bs-docs-navbar').tooltip({\n      selector: \"a[data-toggle=tooltip]\",\n      container: \".bs-docs-navbar .nav\"\n    })\n\n    // popover demo\n    $(\"[data-toggle=popover]\")\n      .popover()\n\n    // button state demo\n    $('#fat-btn')\n      .click(function () {\n        var btn = $(this)\n        btn.button('loading')\n        setTimeout(function () {\n          btn.button('reset')\n        }, 3000)\n      })\n\n    // carousel demo\n    $('.bs-docs-carousel-example').carousel()\n})\n\n}(window.jQuery)\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/sass-bootstrap/assets/js/customizer.js",
    "content": "window.onload = function () { // wait for load in a dumb way because B-0\n  var cw = '/*!\\n * Bootstrap v3.0.0\\n *\\n * Copyright 2013 Twitter, Inc\\n * Licensed under the Apache License v2.0\\n * http://www.apache.org/licenses/LICENSE-2.0\\n *\\n * Designed and built with all the love in the world @twitter by @mdo and @fat.\\n */\\n\\n'\n\n  function showError(msg, err) {\n    $('<div id=\"bsCustomizerAlert\" class=\"bs-customizer-alert\">\\\n        <div class=\"container\">\\\n          <a href=\"#bsCustomizerAlert\" data-dismiss=\"alert\" class=\"close pull-right\">&times;</a>\\\n          <p class=\"bs-customizer-alert-text\"><span class=\"glyphicon glyphicon-warning-sign\"></span>' + msg + '</p>' +\n          (err.extract ? '<pre class=\"bs-customizer-alert-extract\">' + err.extract.join('\\n') + '</pre>' : '') + '\\\n        </div>\\\n      </div>').appendTo('body').alert()\n    throw err\n  }\n\n  function showCallout(msg, showUpTop) {\n    var callout = $('<div class=\"bs-callout bs-callout-danger\">\\\n       <h4>Attention!</h4>\\\n      <p>' + msg + '</p>\\\n    </div>')\n\n    if (showUpTop) {\n      callout.appendTo('.bs-docs-container')\n    } else {\n      callout.insertAfter('.bs-customize-download')\n    }\n  }\n\n  function getQueryParam(key) {\n    key = key.replace(/[*+?^$.\\[\\]{}()|\\\\\\/]/g, \"\\\\$&\"); // escape RegEx meta chars\n    var match = location.search.match(new RegExp(\"[?&]\"+key+\"=([^&]+)(&|$)\"));\n    return match && decodeURIComponent(match[1].replace(/\\+/g, \" \"));\n  }\n\n  function createGist(configData) {\n    var data = {\n      \"description\": \"Bootstrap Customizer Config\",\n      \"public\": true,\n      \"files\": {\n        \"config.json\": {\n          \"content\": JSON.stringify(configData, null, 2)\n        }\n      }\n    }\n    $.ajax({\n      url: 'https://api.github.com/gists',\n      type: 'POST',\n      dataType: 'json',\n      data: JSON.stringify(data)\n    })\n    .success(function(result) {\n      history.replaceState(false, document.title, window.location.origin + window.location.pathname + '?id=' + result.id)\n    })\n    .error(function(err) {\n      showError('<strong>Ruh roh!</strong> Could not save gist file, configuration not saved.', err)\n    })\n  }\n\n  function getCustomizerData() {\n    var vars = {}\n\n    $('#less-variables-section input')\n        .each(function () {\n          $(this).val() && (vars[ $(this).prev().text() ] = $(this).val())\n        })\n\n    var data = {\n      vars: vars,\n      css: $('#less-section input:checked')  .map(function () { return this.value }).toArray(),\n      js:  $('#plugin-section input:checked').map(function () { return this.value }).toArray()\n    }\n\n    if ($.isEmptyObject(data.vars) && !data.css.length && !data.js.length) return\n\n    return data\n  }\n\n  function parseUrl() {\n    var id = getQueryParam('id')\n\n    if (!id) return\n\n    $.ajax({\n      url: 'https://api.github.com/gists/' + id,\n      type: 'GET',\n      dataType: 'json'\n    })\n    .success(function(result) {\n      var data = JSON.parse(result.files['config.json'].content)\n      if (data.js) {\n        $('#plugin-section input').each(function () {\n          $(this).prop('checked', ~$.inArray(this.value, data.js))\n        })\n      }\n      if (data.css) {\n        $('#less-section input').each(function () {\n          $(this).prop('checked', ~$.inArray(this.value, data.css))\n        })\n      }\n      if (data.vars) {\n        for (var i in data.vars) {\n          $('input[data-var=\"' + i + '\"]').val(data.vars[i])\n        }\n      }\n    })\n    .error(function(err) {\n      showError('Error fetching bootstrap config file', err)\n    })\n  }\n\n  function generateZip(css, js, fonts, complete) {\n    if (!css && !js) return showError('<strong>Ruh roh!</strong> No Bootstrap files selected.', new Error('no Bootstrap'))\n\n    var zip = new JSZip()\n\n    if (css) {\n      var cssFolder = zip.folder('css')\n      for (var fileName in css) {\n        cssFolder.file(fileName, css[fileName])\n      }\n    }\n\n    if (js) {\n      var jsFolder = zip.folder('js')\n      for (var fileName in js) {\n        jsFolder.file(fileName, js[fileName])\n      }\n    }\n\n    if (fonts) {\n      var fontsFolder = zip.folder('fonts')\n      for (var fileName in fonts) {\n        fontsFolder.file(fileName, fonts[fileName])\n      }\n    }\n\n    var content = zip.generate({type:\"blob\"})\n\n    complete(content)\n  }\n\n  function generateCustomCSS(vars) {\n    var result = ''\n\n    for (var key in vars) {\n      result += key + ': ' + vars[key] + ';\\n'\n    }\n\n    return result + '\\n\\n'\n  }\n\n  function generateFonts() {\n    var glyphicons = $('#less-section [value=\"glyphicons.less\"]:checked')\n    if (glyphicons.length) {\n      return __fonts\n    }\n  }\n\n  function generateCSS() {\n    var $checked = $('#less-section input:checked')\n\n    if (!$checked.length) return false\n\n    var result = {}\n    var vars = {}\n    var css = ''\n\n    $('#less-variables-section input')\n        .each(function () {\n          $(this).val() && (vars[ $(this).prev().text() ] = $(this).val())\n        })\n\n    css += __less['variables.less']\n    if (vars) css += generateCustomCSS(vars)\n    css += __less['mixins.less']\n    css += __less['normalize.less']\n    css += __less['scaffolding.less']\n    css += $checked\n      .map(function () { return __less[this.value] })\n      .toArray()\n      .join('\\n')\n\n    css = css.replace(/@import[^\\n]*/gi, '') //strip any imports\n\n    try {\n      var parser = new less.Parser({\n          paths: ['variables.less', 'mixins.less']\n        , optimization: 0\n        , filename: 'bootstrap.css'\n      }).parse(css, function (err, tree) {\n        if (err) {\n          return showError('<strong>Ruh roh!</strong> Could not parse less files.', err)\n        }\n        result = {\n          'bootstrap.css'     : cw + tree.toCSS(),\n          'bootstrap.min.css' : cw + tree.toCSS({ compress: true })\n        }\n      })\n    } catch (err) {\n      return showError('<strong>Ruh roh!</strong> Could not parse less files.', err)\n    }\n\n    return result\n  }\n\n  function generateJavascript() {\n    var $checked = $('#plugin-section input:checked')\n    if (!$checked.length) return false\n\n    var js = $checked\n      .map(function () { return __js[this.value] })\n      .toArray()\n      .join('\\n')\n\n    return {\n      'bootstrap.js': js,\n      'bootstrap.min.js': cw + uglify(js)\n    }\n  }\n\n  var inputsComponent = $('#less-section input')\n  var inputsPlugin    = $('#plugin-section input')\n  var inputsVariables = $('#less-variables-section input')\n\n  $('#less-section .toggle').on('click', function (e) {\n    e.preventDefault()\n    inputsComponent.prop('checked', !inputsComponent.is(':checked'))\n  })\n\n  $('#plugin-section .toggle').on('click', function (e) {\n    e.preventDefault()\n    inputsPlugin.prop('checked', !inputsPlugin.is(':checked'))\n  })\n\n  $('#less-variables-section .toggle').on('click', function (e) {\n    e.preventDefault()\n    inputsVariables.val('')\n  })\n\n  $('[data-dependencies]').on('click', function () {\n    if (!$(this).is(':checked')) return\n    var dependencies = this.getAttribute('data-dependencies')\n    if (!dependencies) return\n    dependencies = dependencies.split(',')\n    for (var i = 0; i < dependencies.length; i++) {\n      var dependency = $('[value=\"' + dependencies[i] + '\"]')\n      dependency && dependency.prop('checked', true)\n    }\n  })\n\n  $('[data-dependents]').on('click', function () {\n    if ($(this).is(':checked')) return\n    var dependents = this.getAttribute('data-dependents')\n    if (!dependents) return\n    dependents = dependents.split(',')\n    for (var i = 0; i < dependents.length; i++) {\n      var dependent = $('[value=\"' + dependents[i] + '\"]')\n      dependent && dependent.prop('checked', false)\n    }\n  })\n\n  var $compileBtn = $('#btn-compile')\n  var $downloadBtn = $('#btn-download')\n\n  $compileBtn.on('click', function (e) {\n    e.preventDefault()\n\n    $compileBtn.attr('disabled', 'disabled')\n\n    generateZip(generateCSS(), generateJavascript(), generateFonts(), function (blob) {\n      $compileBtn.removeAttr('disabled')\n      saveAs(blob, \"bootstrap.zip\")\n      createGist(getCustomizerData())\n    })\n  })\n\n  // browser support alerts\n  if (!window.URL && navigator.userAgent.toLowerCase().indexOf('safari') != -1) {\n    showCallout(\"Looks like you're using safari, which sadly doesn't have the best support\\\n                 for HTML5 blobs. Because of this your file will be downloaded with the name <code>\\\"untitled\\\"</code>.\\\n                 However, if you check your downloads folder, just rename this <code>\\\"untitled\\\"</code> file\\\n                 to <code>\\\"bootstrap.zip\\\"</code> and you should be good to go!\")\n  } else if (!window.URL && !window.webkitURL) {\n    $('.bs-docs-section, .bs-sidebar').css('display', 'none')\n\n    showCallout(\"Looks like your current browser doesn't support the Bootstrap Customizer. Please take a second\\\n                to <a href=\\\"https://www.google.com/intl/en/chrome/browser/\\\"> upgrade to a more modern browser</a>.\", true)\n  }\n\n  parseUrl()\n}\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/sass-bootstrap/assets/js/filesaver.js",
    "content": "/* Blob.js\n * A Blob implementation.\n * 2013-06-20\n *\n * By Eli Grey, http://eligrey.com\n * By Devin Samarin, https://github.com/eboyjr\n * License: X11/MIT\n *   See LICENSE.md\n */\n\n/*global self, unescape */\n/*jslint bitwise: true, regexp: true, confusion: true, es5: true, vars: true, white: true,\n  plusplus: true */\n\n/*! @source http://purl.eligrey.com/github/Blob.js/blob/master/Blob.js */\n\nif (typeof Blob !== \"function\" || typeof URL === \"undefined\")\nif (typeof Blob === \"function\" && typeof webkitURL !== \"undefined\") self.URL = webkitURL;\nelse var Blob = (function (view) {\n  \"use strict\";\n\n  var BlobBuilder = view.BlobBuilder || view.WebKitBlobBuilder || view.MozBlobBuilder || view.MSBlobBuilder || (function(view) {\n    var\n        get_class = function(object) {\n        return Object.prototype.toString.call(object).match(/^\\[object\\s(.*)\\]$/)[1];\n      }\n      , FakeBlobBuilder = function BlobBuilder() {\n        this.data = [];\n      }\n      , FakeBlob = function Blob(data, type, encoding) {\n        this.data = data;\n        this.size = data.length;\n        this.type = type;\n        this.encoding = encoding;\n      }\n      , FBB_proto = FakeBlobBuilder.prototype\n      , FB_proto = FakeBlob.prototype\n      , FileReaderSync = view.FileReaderSync\n      , FileException = function(type) {\n        this.code = this[this.name = type];\n      }\n      , file_ex_codes = (\n          \"NOT_FOUND_ERR SECURITY_ERR ABORT_ERR NOT_READABLE_ERR ENCODING_ERR \"\n        + \"NO_MODIFICATION_ALLOWED_ERR INVALID_STATE_ERR SYNTAX_ERR\"\n      ).split(\" \")\n      , file_ex_code = file_ex_codes.length\n      , real_URL = view.URL || view.webkitURL || view\n      , real_create_object_URL = real_URL.createObjectURL\n      , real_revoke_object_URL = real_URL.revokeObjectURL\n      , URL = real_URL\n      , btoa = view.btoa\n      , atob = view.atob\n\n      , ArrayBuffer = view.ArrayBuffer\n      , Uint8Array = view.Uint8Array\n    ;\n    FakeBlob.fake = FB_proto.fake = true;\n    while (file_ex_code--) {\n      FileException.prototype[file_ex_codes[file_ex_code]] = file_ex_code + 1;\n    }\n    if (!real_URL.createObjectURL) {\n      URL = view.URL = {};\n    }\n    URL.createObjectURL = function(blob) {\n      var\n          type = blob.type\n        , data_URI_header\n      ;\n      if (type === null) {\n        type = \"application/octet-stream\";\n      }\n      if (blob instanceof FakeBlob) {\n        data_URI_header = \"data:\" + type;\n        if (blob.encoding === \"base64\") {\n          return data_URI_header + \";base64,\" + blob.data;\n        } else if (blob.encoding === \"URI\") {\n          return data_URI_header + \",\" + decodeURIComponent(blob.data);\n        } if (btoa) {\n          return data_URI_header + \";base64,\" + btoa(blob.data);\n        } else {\n          return data_URI_header + \",\" + encodeURIComponent(blob.data);\n        }\n      } else if (real_create_object_URL) {\n        return real_create_object_URL.call(real_URL, blob);\n      }\n    };\n    URL.revokeObjectURL = function(object_URL) {\n      if (object_URL.substring(0, 5) !== \"data:\" && real_revoke_object_URL) {\n        real_revoke_object_URL.call(real_URL, object_URL);\n      }\n    };\n    FBB_proto.append = function(data/*, endings*/) {\n      var bb = this.data;\n      // decode data to a binary string\n      if (Uint8Array && (data instanceof ArrayBuffer || data instanceof Uint8Array)) {\n        var\n            str = \"\"\n          , buf = new Uint8Array(data)\n          , i = 0\n          , buf_len = buf.length\n        ;\n        for (; i < buf_len; i++) {\n          str += String.fromCharCode(buf[i]);\n        }\n        bb.push(str);\n      } else if (get_class(data) === \"Blob\" || get_class(data) === \"File\") {\n        if (FileReaderSync) {\n          var fr = new FileReaderSync;\n          bb.push(fr.readAsBinaryString(data));\n        } else {\n          // async FileReader won't work as BlobBuilder is sync\n          throw new FileException(\"NOT_READABLE_ERR\");\n        }\n      } else if (data instanceof FakeBlob) {\n        if (data.encoding === \"base64\" && atob) {\n          bb.push(atob(data.data));\n        } else if (data.encoding === \"URI\") {\n          bb.push(decodeURIComponent(data.data));\n        } else if (data.encoding === \"raw\") {\n          bb.push(data.data);\n        }\n      } else {\n        if (typeof data !== \"string\") {\n          data += \"\"; // convert unsupported types to strings\n        }\n        // decode UTF-16 to binary string\n        bb.push(unescape(encodeURIComponent(data)));\n      }\n    };\n    FBB_proto.getBlob = function(type) {\n      if (!arguments.length) {\n        type = null;\n      }\n      return new FakeBlob(this.data.join(\"\"), type, \"raw\");\n    };\n    FBB_proto.toString = function() {\n      return \"[object BlobBuilder]\";\n    };\n    FB_proto.slice = function(start, end, type) {\n      var args = arguments.length;\n      if (args < 3) {\n        type = null;\n      }\n      return new FakeBlob(\n          this.data.slice(start, args > 1 ? end : this.data.length)\n        , type\n        , this.encoding\n      );\n    };\n    FB_proto.toString = function() {\n      return \"[object Blob]\";\n    };\n    return FakeBlobBuilder;\n  }(view));\n\n  return function Blob(blobParts, options) {\n    var type = options ? (options.type || \"\") : \"\";\n    var builder = new BlobBuilder();\n    if (blobParts) {\n      for (var i = 0, len = blobParts.length; i < len; i++) {\n        builder.append(blobParts[i]);\n      }\n    }\n    return builder.getBlob(type);\n  };\n}(self));\n\n/*! @source http://purl.eligrey.com/github/FileSaver.js/blob/master/FileSaver.js */\nvar saveAs=saveAs||(navigator.msSaveOrOpenBlob&&navigator.msSaveOrOpenBlob.bind(navigator))||(function(h){\"use strict\";var r=h.document,l=function(){return h.URL||h.webkitURL||h},e=h.URL||h.webkitURL||h,n=r.createElementNS(\"http://www.w3.org/1999/xhtml\",\"a\"),g=!h.externalHost&&\"download\" in n,j=function(t){var s=r.createEvent(\"MouseEvents\");s.initMouseEvent(\"click\",true,false,h,0,0,0,0,0,false,false,false,false,0,null);t.dispatchEvent(s)},o=h.webkitRequestFileSystem,p=h.requestFileSystem||o||h.mozRequestFileSystem,m=function(s){(h.setImmediate||h.setTimeout)(function(){throw s},0)},c=\"application/octet-stream\",k=0,b=[],i=function(){var t=b.length;while(t--){var s=b[t];if(typeof s===\"string\"){e.revokeObjectURL(s)}else{s.remove()}}b.length=0},q=function(t,s,w){s=[].concat(s);var v=s.length;while(v--){var x=t[\"on\"+s[v]];if(typeof x===\"function\"){try{x.call(t,w||t)}catch(u){m(u)}}}},f=function(t,u){var v=this,B=t.type,E=false,x,w,s=function(){var F=l().createObjectURL(t);b.push(F);return F},A=function(){q(v,\"writestart progress write writeend\".split(\" \"))},D=function(){if(E||!x){x=s(t)}if(w){w.location.href=x}else{window.open(x,\"_blank\")}v.readyState=v.DONE;A()},z=function(F){return function(){if(v.readyState!==v.DONE){return F.apply(this,arguments)}}},y={create:true,exclusive:false},C;v.readyState=v.INIT;if(!u){u=\"download\"}if(g){x=s(t);n.href=x;n.download=u;j(n);v.readyState=v.DONE;A();return}if(h.chrome&&B&&B!==c){C=t.slice||t.webkitSlice;t=C.call(t,0,t.size,c);E=true}if(o&&u!==\"download\"){u+=\".download\"}if(B===c||o){w=h}if(!p){D();return}k+=t.size;p(h.TEMPORARY,k,z(function(F){F.root.getDirectory(\"saved\",y,z(function(G){var H=function(){G.getFile(u,y,z(function(I){I.createWriter(z(function(J){J.onwriteend=function(K){w.location.href=I.toURL();b.push(I);v.readyState=v.DONE;q(v,\"writeend\",K)};J.onerror=function(){var K=J.error;if(K.code!==K.ABORT_ERR){D()}};\"writestart progress write abort\".split(\" \").forEach(function(K){J[\"on\"+K]=v[\"on\"+K]});J.write(t);v.abort=function(){J.abort();v.readyState=v.DONE};v.readyState=v.WRITING}),D)}),D)};G.getFile(u,{create:false},z(function(I){I.remove();H()}),z(function(I){if(I.code===I.NOT_FOUND_ERR){H()}else{D()}}))}),D)}),D)},d=f.prototype,a=function(s,t){return new f(s,t)};d.abort=function(){var s=this;s.readyState=s.DONE;q(s,\"abort\")};d.readyState=d.INIT=0;d.WRITING=1;d.DONE=2;d.error=d.onwritestart=d.onprogress=d.onwrite=d.onabort=d.onerror=d.onwriteend=null;h.addEventListener(\"unload\",i,false);return a}(self));"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/sass-bootstrap/assets/js/holder.js",
    "content": "/*\n\nHolder - 2.0 - client side image placeholders\n(c) 2012-2013 Ivan Malopinsky / http://imsky.co\n\nProvided under the Apache 2.0 License: http://www.apache.org/licenses/LICENSE-2.0\nCommercial use requires attribution.\n\n*/\n\nvar Holder = Holder || {};\n(function (app, win) {\n\nvar preempted = false,\nfallback = false,\ncanvas = document.createElement('canvas');\n\n//getElementsByClassName polyfill\ndocument.getElementsByClassName||(document.getElementsByClassName=function(e){var t=document,n,r,i,s=[];if(t.querySelectorAll)return t.querySelectorAll(\".\"+e);if(t.evaluate){r=\".//*[contains(concat(' ', @class, ' '), ' \"+e+\" ')]\",n=t.evaluate(r,t,null,0,null);while(i=n.iterateNext())s.push(i)}else{n=t.getElementsByTagName(\"*\"),r=new RegExp(\"(^|\\\\s)\"+e+\"(\\\\s|$)\");for(i=0;i<n.length;i++)r.test(n[i].className)&&s.push(n[i])}return s})\n\n//getComputedStyle polyfill\nwindow.getComputedStyle||(window.getComputedStyle=function(e,t){return this.el=e,this.getPropertyValue=function(t){var n=/(\\-([a-z]){1})/g;return t==\"float\"&&(t=\"styleFloat\"),n.test(t)&&(t=t.replace(n,function(){return arguments[2].toUpperCase()})),e.currentStyle[t]?e.currentStyle[t]:null},this})\n\n//http://javascript.nwbox.com/ContentLoaded by Diego Perini with modifications\nfunction contentLoaded(n,t){var l=\"complete\",s=\"readystatechange\",u=!1,h=u,c=!0,i=n.document,a=i.documentElement,e=i.addEventListener?\"addEventListener\":\"attachEvent\",v=i.addEventListener?\"removeEventListener\":\"detachEvent\",f=i.addEventListener?\"\":\"on\",r=function(e){(e.type!=s||i.readyState==l)&&((e.type==\"load\"?n:i)[v](f+e.type,r,u),!h&&(h=!0)&&t.call(n,null))},o=function(){try{a.doScroll(\"left\")}catch(n){setTimeout(o,50);return}r(\"poll\")};if(i.readyState==l)t.call(n,\"lazy\");else{if(i.createEventObject&&a.doScroll){try{c=!n.frameElement}catch(y){}c&&o()}i[e](f+\"DOMContentLoaded\",r,u),i[e](f+s,r,u),n[e](f+\"load\",r,u)}};\n\n//https://gist.github.com/991057 by Jed Schmidt with modifications\nfunction selector(a){\n\ta=a.match(/^(\\W)?(.*)/);var b=document[\"getElement\"+(a[1]?a[1]==\"#\"?\"ById\":\"sByClassName\":\"sByTagName\")](a[2]);\n\tvar ret=[];\tb!=null&&(b.length?ret=b:b.length==0?ret=b:ret=[b]);\treturn ret;\n}\n\n//shallow object property extend\nfunction extend(a,b){var c={};for(var d in a)c[d]=a[d];for(var e in b)c[e]=b[e];return c}\n\n//hasOwnProperty polyfill\nif (!Object.prototype.hasOwnProperty)\n\tObject.prototype.hasOwnProperty = function(prop) {\n\t\tvar proto = this.__proto__ || this.constructor.prototype;\n\t\treturn (prop in this) && (!(prop in proto) || proto[prop] !== this[prop]);\n\t}\n\nfunction text_size(width, height, template) {\n\theight = parseInt(height,10);\n\twidth = parseInt(width,10);\n\tvar bigSide = Math.max(height, width)\n\tvar smallSide = Math.min(height, width)\n\tvar scale = 1 / 12;\n\tvar newHeight = Math.min(smallSide * 0.75, 0.75 * bigSide * scale);\n\treturn {\n\t\theight: Math.round(Math.max(template.size, newHeight))\n\t}\n}\n\nfunction draw(ctx, dimensions, template, ratio) {\n\tvar ts = text_size(dimensions.width, dimensions.height, template);\n\tvar text_height = ts.height;\n\tvar width = dimensions.width * ratio,\n\t\theight = dimensions.height * ratio;\n\tvar font = template.font ? template.font : \"sans-serif\";\n\tcanvas.width = width;\n\tcanvas.height = height;\n\tctx.textAlign = \"center\";\n\tctx.textBaseline = \"middle\";\n\tctx.fillStyle = template.background;\n\tctx.fillRect(0, 0, width, height);\n\tctx.fillStyle = template.foreground;\n\tctx.font = \"bold \" + text_height + \"px \" + font;\n\tvar text = template.text ? template.text : (Math.floor(dimensions.width) + \"x\" + Math.floor(dimensions.height));\n\tvar text_width = ctx.measureText(text).width;\n\tif (text_width / width >= 0.75) {\n\t\ttext_height = Math.floor(text_height * 0.75 * (width/text_width));\n\t}\n\t//Resetting font size if necessary\n\tctx.font = \"bold \" + (text_height * ratio) + \"px \" + font;\n\tctx.fillText(text, (width / 2), (height / 2), width);\n\treturn canvas.toDataURL(\"image/png\");\n}\n\nfunction render(mode, el, holder, src) {\n\tvar dimensions = holder.dimensions,\n\t\ttheme = holder.theme,\n\t\ttext = holder.text ? decodeURIComponent(holder.text) : holder.text;\n\tvar dimensions_caption = dimensions.width + \"x\" + dimensions.height;\n\ttheme = (text ? extend(theme, {\n\t\ttext: text\n\t}) : theme);\n\ttheme = (holder.font ? extend(theme, {\n\t\tfont: holder.font\n\t}) : theme);\n\tif (mode == \"image\") {\n\t\tel.setAttribute(\"data-src\", src);\n\t\tel.setAttribute(\"alt\", text ? text : theme.text ? theme.text + \" [\" + dimensions_caption + \"]\" : dimensions_caption);\n\t\tif (fallback || !holder.auto) {\n\t\t\tel.style.width = dimensions.width + \"px\";\n\t\t\tel.style.height = dimensions.height + \"px\";\n\t\t}\n\t\tif (fallback) {\n\t\t\tel.style.backgroundColor = theme.background;\n\t\t} else {\n\t\t\tel.setAttribute(\"src\", draw(ctx, dimensions, theme, ratio));\n\t\t}\n\t} else if (mode == \"background\") {\n\t\tif (!fallback) {\n\t\t\tel.style.backgroundImage = \"url(\" + draw(ctx, dimensions, theme, ratio) + \")\";\n\t\t\tel.style.backgroundSize = dimensions.width + \"px \" + dimensions.height + \"px\";\n\t\t}\n\t} else if (mode == \"fluid\") {\n\t\tel.setAttribute(\"data-src\", src);\n\t\tel.setAttribute(\"alt\", text ? text : theme.text ? theme.text + \" [\" + dimensions_caption + \"]\" : dimensions_caption);\n\t\tif (dimensions.height.substr(-1) == \"%\") {\n\t\t\tel.style.height = dimensions.height\n\t\t} else {\n\t\t\tel.style.height = dimensions.height + \"px\"\n\t\t}\n\t\tif (dimensions.width.substr(-1) == \"%\") {\n\t\t\tel.style.width = dimensions.width\n\t\t} else {\n\t\t\tel.style.width = dimensions.width + \"px\"\n\t\t}\n\t\tif (el.style.display == \"inline\" || el.style.display == \"\") {\n\t\t\tel.style.display = \"block\";\n\t\t}\n\t\tif (fallback) {\n\t\t\tel.style.backgroundColor = theme.background;\n\t\t} else {\n\t\t\tel.holderData = holder;\n\t\t\tfluid_images.push(el);\n\t\t\tfluid_update(el);\n\t\t}\n\t}\n};\n\nfunction fluid_update(element) {\n\tvar images;\n\tif (element.nodeType == null) {\n\t\timages = fluid_images;\n\t} else {\n\t\timages = [element]\n\t}\n\tfor (i in images) {\n\t\tvar el = images[i]\n\t\tif (el.holderData) {\n\t\t\tvar holder = el.holderData;\n\t\t\tel.setAttribute(\"src\", draw(ctx, {\n\t\t\t\theight: el.clientHeight,\n\t\t\t\twidth: el.clientWidth\n\t\t\t}, holder.theme, ratio));\n\t\t}\n\t}\n}\n\nfunction parse_flags(flags, options) {\n\n\tvar ret = {\n\t\ttheme: settings.themes.gray\n\t}, render = false;\n\n\tfor (sl = flags.length, j = 0; j < sl; j++) {\n\t\tvar flag = flags[j];\n\t\tif (app.flags.dimensions.match(flag)) {\n\t\t\trender = true;\n\t\t\tret.dimensions = app.flags.dimensions.output(flag);\n\t\t} else if (app.flags.fluid.match(flag)) {\n\t\t\trender = true;\n\t\t\tret.dimensions = app.flags.fluid.output(flag);\n\t\t\tret.fluid = true;\n\t\t} else if (app.flags.colors.match(flag)) {\n\t\t\tret.theme = app.flags.colors.output(flag);\n\t\t} else if (options.themes[flag]) {\n\t\t\t//If a theme is specified, it will override custom colors\n\t\t\tret.theme = options.themes[flag];\n\t\t} else if (app.flags.text.match(flag)) {\n\t\t\tret.text = app.flags.text.output(flag);\n\t\t} else if (app.flags.font.match(flag)) {\n\t\t\tret.font = app.flags.font.output(flag);\n\t\t} else if (app.flags.auto.match(flag)) {\n\t\t\tret.auto = true;\n\t\t}\n\t}\n\n\treturn render ? ret : false;\n\n};\n\n\n\nif (!canvas.getContext) {\n\tfallback = true;\n} else {\n\tif (canvas.toDataURL(\"image/png\")\n\t\t.indexOf(\"data:image/png\") < 0) {\n\t\t//Android doesn't support data URI\n\t\tfallback = true;\n\t} else {\n\t\tvar ctx = canvas.getContext(\"2d\");\n\t}\n}\n\nvar dpr = 1, bsr = 1;\n\t\nif(!fallback){\n    dpr = window.devicePixelRatio || 1,\n    bsr = ctx.webkitBackingStorePixelRatio || ctx.mozBackingStorePixelRatio || ctx.msBackingStorePixelRatio || ctx.oBackingStorePixelRatio || ctx.backingStorePixelRatio || 1;\n}\n\nvar ratio = dpr / bsr;\n\nvar fluid_images = [];\n\nvar settings = {\n\tdomain: \"holder.js\",\n\timages: \"img\",\n\tbgnodes: \".holderjs\",\n\tthemes: {\n\t\t\"gray\": {\n\t\t\tbackground: \"#eee\",\n\t\t\tforeground: \"#aaa\",\n\t\t\tsize: 12\n\t\t},\n\t\t\"social\": {\n\t\t\tbackground: \"#3a5a97\",\n\t\t\tforeground: \"#fff\",\n\t\t\tsize: 12\n\t\t},\n\t\t\"industrial\": {\n\t\t\tbackground: \"#434A52\",\n\t\t\tforeground: \"#C2F200\",\n\t\t\tsize: 12\n\t\t}\n\t},\n\tstylesheet: \".holderjs-fluid {font-size:16px;font-weight:bold;text-align:center;font-family:sans-serif;margin:0}\"\n};\n\n\napp.flags = {\n\tdimensions: {\n\t\tregex: /^(\\d+)x(\\d+)$/,\n\t\toutput: function (val) {\n\t\t\tvar exec = this.regex.exec(val);\n\t\t\treturn {\n\t\t\t\twidth: +exec[1],\n\t\t\t\theight: +exec[2]\n\t\t\t}\n\t\t}\n\t},\n\tfluid: {\n\t\tregex: /^([0-9%]+)x([0-9%]+)$/,\n\t\toutput: function (val) {\n\t\t\tvar exec = this.regex.exec(val);\n\t\t\treturn {\n\t\t\t\twidth: exec[1],\n\t\t\t\theight: exec[2]\n\t\t\t}\n\t\t}\n\t},\n\tcolors: {\n\t\tregex: /#([0-9a-f]{3,})\\:#([0-9a-f]{3,})/i,\n\t\toutput: function (val) {\n\t\t\tvar exec = this.regex.exec(val);\n\t\t\treturn {\n\t\t\t\tsize: settings.themes.gray.size,\n\t\t\t\tforeground: \"#\" + exec[2],\n\t\t\t\tbackground: \"#\" + exec[1]\n\t\t\t}\n\t\t}\n\t},\n\ttext: {\n\t\tregex: /text\\:(.*)/,\n\t\toutput: function (val) {\n\t\t\treturn this.regex.exec(val)[1];\n\t\t}\n\t},\n\tfont: {\n\t\tregex: /font\\:(.*)/,\n\t\toutput: function (val) {\n\t\t\treturn this.regex.exec(val)[1];\n\t\t}\n\t},\n\tauto: {\n\t\tregex: /^auto$/\n\t}\n}\n\nfor (var flag in app.flags) {\n\tif (!app.flags.hasOwnProperty(flag)) continue;\n\tapp.flags[flag].match = function (val) {\n\t\treturn val.match(this.regex)\n\t}\n}\n\napp.add_theme = function (name, theme) {\n\tname != null && theme != null && (settings.themes[name] = theme);\n\treturn app;\n};\n\napp.add_image = function (src, el) {\n\tvar node = selector(el);\n\tif (node.length) {\n\t\tfor (var i = 0, l = node.length; i < l; i++) {\n\t\t\tvar img = document.createElement(\"img\")\n\t\t\timg.setAttribute(\"data-src\", src);\n\t\t\tnode[i].appendChild(img);\n\t\t}\n\t}\n\treturn app;\n};\n\napp.run = function (o) {\n\tvar options = extend(settings, o),\n\t    images = [], imageNodes = [], bgnodes = [];\n\t    \n\tif(typeof(options.images) == \"string\"){\n\t    imageNodes = selector(options.images);\n\t}\n\telse if (window.NodeList && options.images instanceof window.NodeList) {\n\t\timageNodes = options.images;\n\t} else if (window.Node && options.images instanceof window.Node) {\n\t\timageNodes = [options.images];\n\t}\n\n\tif(typeof(options.bgnodes) == \"string\"){\n\t    bgnodes = selector(options.bgnodes);\n\t} else if (window.NodeList && options.elements instanceof window.NodeList) {\n\t\tbgnodes = options.bgnodes;\n\t} else if (window.Node && options.bgnodes instanceof window.Node) {\n\t\tbgnodes = [options.bgnodes];\n\t}\n\n\tpreempted = true;\n\n\tfor (i = 0, l = imageNodes.length; i < l; i++) images.push(imageNodes[i]);\n\n\tvar holdercss = document.getElementById(\"holderjs-style\");\n\tif (!holdercss) {\n\t\tholdercss = document.createElement(\"style\");\n\t\tholdercss.setAttribute(\"id\", \"holderjs-style\");\n\t\tholdercss.type = \"text/css\";\n\t\tdocument.getElementsByTagName(\"head\")[0].appendChild(holdercss);\n\t}\n\t\n\tif (!options.nocss) {\n\t    if (holdercss.styleSheet) {\n\t\t    holdercss.styleSheet.cssText += options.stylesheet;\n\t    } else {\n\t\t    holdercss.appendChild(document.createTextNode(options.stylesheet));\n\t    }\n\t}\n\n\tvar cssregex = new RegExp(options.domain + \"\\/(.*?)\\\"?\\\\)\");\n\n\tfor (var l = bgnodes.length, i = 0; i < l; i++) {\n\t\tvar src = window.getComputedStyle(bgnodes[i], null)\n\t\t\t.getPropertyValue(\"background-image\");\n\t\tvar flags = src.match(cssregex);\n\t\tvar bgsrc = bgnodes[i].getAttribute(\"data-background-src\");\n\n\t\tif (flags) {\n\t\t\tvar holder = parse_flags(flags[1].split(\"/\"), options);\n\t\t\tif (holder) {\n\t\t\t\trender(\"background\", bgnodes[i], holder, src);\n\t\t\t}\n\t\t}\n\t\telse if(bgsrc != null){\n\t\t    var holder = parse_flags(bgsrc.substr(bgsrc.lastIndexOf(options.domain) + options.domain.length + 1)\n\t\t\t\t.split(\"/\"), options);\n\t\t    if(holder){\n\t\t\trender(\"background\", bgnodes[i], holder, src);\n\t\t    }\n\t\t}\n\t}\n\n\tfor (l = images.length, i = 0; i < l; i++) {\n\t    \n\t\tvar attr_src = attr_data_src = src = null;\n\t\t\n\t\ttry{\n\t\t    attr_src = images[i].getAttribute(\"src\");\n\t\t    attr_datasrc = images[i].getAttribute(\"data-src\");\n\t\t}catch(e){}\n\t\t\t\t\n\t\tif (attr_datasrc == null && !! attr_src && attr_src.indexOf(options.domain) >= 0) {\n\t\t\tsrc = attr_src;\n\t\t} else if ( !! attr_datasrc && attr_datasrc.indexOf(options.domain) >= 0) {\n\t\t\tsrc = attr_datasrc;\n\t\t}\n\t\t\n\t\tif (src) {\n\t\t\tvar holder = parse_flags(src.substr(src.lastIndexOf(options.domain) + options.domain.length + 1)\n\t\t\t\t.split(\"/\"), options);\n\t\t\tif (holder) {\n\t\t\t\tif (holder.fluid) {\n\t\t\t\t\trender(\"fluid\", images[i], holder, src)\n\t\t\t\t} else {\n\t\t\t\t\trender(\"image\", images[i], holder, src);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn app;\n};\n\ncontentLoaded(win, function () {\n\tif (window.addEventListener) {\n\t\twindow.addEventListener(\"resize\", fluid_update, false);\n\t\twindow.addEventListener(\"orientationchange\", fluid_update, false);\n\t} else {\n\t\twindow.attachEvent(\"onresize\", fluid_update)\n\t}\n\tpreempted || app.run();\n});\n\nif (typeof define === \"function\" && define.amd) {\n\tdefine(\"Holder\", [], function () {\n\t\treturn app;\n\t});\n}\n\n})(Holder, window);\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/sass-bootstrap/assets/js/html5shiv.js",
    "content": "/*\n HTML5 Shiv v3.6.2pre | @afarkas @jdalton @jon_neal @rem | MIT/GPL2 Licensed\n*/\n(function(l,f){function m(){var a=e.elements;return\"string\"==typeof a?a.split(\" \"):a}function i(a){var b=n[a[o]];b||(b={},h++,a[o]=h,n[h]=b);return b}function p(a,b,c){b||(b=f);if(g)return b.createElement(a);c||(c=i(b));b=c.cache[a]?c.cache[a].cloneNode():r.test(a)?(c.cache[a]=c.createElem(a)).cloneNode():c.createElem(a);return b.canHaveChildren&&!s.test(a)?c.frag.appendChild(b):b}function t(a,b){if(!b.cache)b.cache={},b.createElem=a.createElement,b.createFrag=a.createDocumentFragment,b.frag=b.createFrag();\na.createElement=function(c){return!e.shivMethods?b.createElem(c):p(c,a,b)};a.createDocumentFragment=Function(\"h,f\",\"return function(){var n=f.cloneNode(),c=n.createElement;h.shivMethods&&(\"+m().join().replace(/\\w+/g,function(a){b.createElem(a);b.frag.createElement(a);return'c(\"'+a+'\")'})+\");return n}\")(e,b.frag)}function q(a){a||(a=f);var b=i(a);if(e.shivCSS&&!j&&!b.hasCSS){var c,d=a;c=d.createElement(\"p\");d=d.getElementsByTagName(\"head\")[0]||d.documentElement;c.innerHTML=\"x<style>article,aside,figcaption,figure,footer,header,hgroup,nav,section{display:block}mark{background:#FF0;color:#000}</style>\";\nc=d.insertBefore(c.lastChild,d.firstChild);b.hasCSS=!!c}g||t(a,b);return a}var k=l.html5||{},s=/^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i,r=/^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i,j,o=\"_html5shiv\",h=0,n={},g;(function(){try{var a=f.createElement(\"a\");a.innerHTML=\"<xyz></xyz>\";j=\"hidden\"in a;var b;if(!(b=1==a.childNodes.length)){f.createElement(\"a\");var c=f.createDocumentFragment();b=\"undefined\"==typeof c.cloneNode||\n\"undefined\"==typeof c.createDocumentFragment||\"undefined\"==typeof c.createElement}g=b}catch(d){g=j=!0}})();var e={elements:k.elements||\"abbr article aside audio bdi canvas data datalist details figcaption figure footer header hgroup mark meter nav output progress section summary time video\",version:\"3.6.2pre\",shivCSS:!1!==k.shivCSS,supportsUnknownElements:g,shivMethods:!1!==k.shivMethods,type:\"default\",shivDocument:q,createElement:p,createDocumentFragment:function(a,b){a||(a=f);if(g)return a.createDocumentFragment();\nfor(var b=b||i(a),c=b.frag.cloneNode(),d=0,e=m(),h=e.length;d<h;d++)c.createElement(e[d]);return c}};l.html5=e;q(f)})(this,document);\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/sass-bootstrap/assets/js/jquery.js",
    "content": "/*! jQuery v1.10.2 | (c) 2005, 2013 jQuery Foundation, Inc. | jquery.org/license\n//@ sourceMappingURL=jquery-1.10.2.min.map\n*/\n(function(e,t){var n,r,i=typeof t,o=e.location,a=e.document,s=a.documentElement,l=e.jQuery,u=e.$,c={},p=[],f=\"1.10.2\",d=p.concat,h=p.push,g=p.slice,m=p.indexOf,y=c.toString,v=c.hasOwnProperty,b=f.trim,x=function(e,t){return new x.fn.init(e,t,r)},w=/[+-]?(?:\\d*\\.|)\\d+(?:[eE][+-]?\\d+|)/.source,T=/\\S+/g,C=/^[\\s\\uFEFF\\xA0]+|[\\s\\uFEFF\\xA0]+$/g,N=/^(?:\\s*(<[\\w\\W]+>)[^>]*|#([\\w-]*))$/,k=/^<(\\w+)\\s*\\/?>(?:<\\/\\1>|)$/,E=/^[\\],:{}\\s]*$/,S=/(?:^|:|,)(?:\\s*\\[)+/g,A=/\\\\(?:[\"\\\\\\/bfnrt]|u[\\da-fA-F]{4})/g,j=/\"[^\"\\\\\\r\\n]*\"|true|false|null|-?(?:\\d+\\.|)\\d+(?:[eE][+-]?\\d+|)/g,D=/^-ms-/,L=/-([\\da-z])/gi,H=function(e,t){return t.toUpperCase()},q=function(e){(a.addEventListener||\"load\"===e.type||\"complete\"===a.readyState)&&(_(),x.ready())},_=function(){a.addEventListener?(a.removeEventListener(\"DOMContentLoaded\",q,!1),e.removeEventListener(\"load\",q,!1)):(a.detachEvent(\"onreadystatechange\",q),e.detachEvent(\"onload\",q))};x.fn=x.prototype={jquery:f,constructor:x,init:function(e,n,r){var i,o;if(!e)return this;if(\"string\"==typeof e){if(i=\"<\"===e.charAt(0)&&\">\"===e.charAt(e.length-1)&&e.length>=3?[null,e,null]:N.exec(e),!i||!i[1]&&n)return!n||n.jquery?(n||r).find(e):this.constructor(n).find(e);if(i[1]){if(n=n instanceof x?n[0]:n,x.merge(this,x.parseHTML(i[1],n&&n.nodeType?n.ownerDocument||n:a,!0)),k.test(i[1])&&x.isPlainObject(n))for(i in n)x.isFunction(this[i])?this[i](n[i]):this.attr(i,n[i]);return this}if(o=a.getElementById(i[2]),o&&o.parentNode){if(o.id!==i[2])return r.find(e);this.length=1,this[0]=o}return this.context=a,this.selector=e,this}return e.nodeType?(this.context=this[0]=e,this.length=1,this):x.isFunction(e)?r.ready(e):(e.selector!==t&&(this.selector=e.selector,this.context=e.context),x.makeArray(e,this))},selector:\"\",length:0,toArray:function(){return g.call(this)},get:function(e){return null==e?this.toArray():0>e?this[this.length+e]:this[e]},pushStack:function(e){var t=x.merge(this.constructor(),e);return t.prevObject=this,t.context=this.context,t},each:function(e,t){return x.each(this,e,t)},ready:function(e){return x.ready.promise().done(e),this},slice:function(){return this.pushStack(g.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(e){var t=this.length,n=+e+(0>e?t:0);return this.pushStack(n>=0&&t>n?[this[n]]:[])},map:function(e){return this.pushStack(x.map(this,function(t,n){return e.call(t,n,t)}))},end:function(){return this.prevObject||this.constructor(null)},push:h,sort:[].sort,splice:[].splice},x.fn.init.prototype=x.fn,x.extend=x.fn.extend=function(){var e,n,r,i,o,a,s=arguments[0]||{},l=1,u=arguments.length,c=!1;for(\"boolean\"==typeof s&&(c=s,s=arguments[1]||{},l=2),\"object\"==typeof s||x.isFunction(s)||(s={}),u===l&&(s=this,--l);u>l;l++)if(null!=(o=arguments[l]))for(i in o)e=s[i],r=o[i],s!==r&&(c&&r&&(x.isPlainObject(r)||(n=x.isArray(r)))?(n?(n=!1,a=e&&x.isArray(e)?e:[]):a=e&&x.isPlainObject(e)?e:{},s[i]=x.extend(c,a,r)):r!==t&&(s[i]=r));return s},x.extend({expando:\"jQuery\"+(f+Math.random()).replace(/\\D/g,\"\"),noConflict:function(t){return e.$===x&&(e.$=u),t&&e.jQuery===x&&(e.jQuery=l),x},isReady:!1,readyWait:1,holdReady:function(e){e?x.readyWait++:x.ready(!0)},ready:function(e){if(e===!0?!--x.readyWait:!x.isReady){if(!a.body)return setTimeout(x.ready);x.isReady=!0,e!==!0&&--x.readyWait>0||(n.resolveWith(a,[x]),x.fn.trigger&&x(a).trigger(\"ready\").off(\"ready\"))}},isFunction:function(e){return\"function\"===x.type(e)},isArray:Array.isArray||function(e){return\"array\"===x.type(e)},isWindow:function(e){return null!=e&&e==e.window},isNumeric:function(e){return!isNaN(parseFloat(e))&&isFinite(e)},type:function(e){return null==e?e+\"\":\"object\"==typeof e||\"function\"==typeof e?c[y.call(e)]||\"object\":typeof e},isPlainObject:function(e){var n;if(!e||\"object\"!==x.type(e)||e.nodeType||x.isWindow(e))return!1;try{if(e.constructor&&!v.call(e,\"constructor\")&&!v.call(e.constructor.prototype,\"isPrototypeOf\"))return!1}catch(r){return!1}if(x.support.ownLast)for(n in e)return v.call(e,n);for(n in e);return n===t||v.call(e,n)},isEmptyObject:function(e){var t;for(t in e)return!1;return!0},error:function(e){throw Error(e)},parseHTML:function(e,t,n){if(!e||\"string\"!=typeof e)return null;\"boolean\"==typeof t&&(n=t,t=!1),t=t||a;var r=k.exec(e),i=!n&&[];return r?[t.createElement(r[1])]:(r=x.buildFragment([e],t,i),i&&x(i).remove(),x.merge([],r.childNodes))},parseJSON:function(n){return e.JSON&&e.JSON.parse?e.JSON.parse(n):null===n?n:\"string\"==typeof n&&(n=x.trim(n),n&&E.test(n.replace(A,\"@\").replace(j,\"]\").replace(S,\"\")))?Function(\"return \"+n)():(x.error(\"Invalid JSON: \"+n),t)},parseXML:function(n){var r,i;if(!n||\"string\"!=typeof n)return null;try{e.DOMParser?(i=new DOMParser,r=i.parseFromString(n,\"text/xml\")):(r=new ActiveXObject(\"Microsoft.XMLDOM\"),r.async=\"false\",r.loadXML(n))}catch(o){r=t}return r&&r.documentElement&&!r.getElementsByTagName(\"parsererror\").length||x.error(\"Invalid XML: \"+n),r},noop:function(){},globalEval:function(t){t&&x.trim(t)&&(e.execScript||function(t){e.eval.call(e,t)})(t)},camelCase:function(e){return e.replace(D,\"ms-\").replace(L,H)},nodeName:function(e,t){return e.nodeName&&e.nodeName.toLowerCase()===t.toLowerCase()},each:function(e,t,n){var r,i=0,o=e.length,a=M(e);if(n){if(a){for(;o>i;i++)if(r=t.apply(e[i],n),r===!1)break}else for(i in e)if(r=t.apply(e[i],n),r===!1)break}else if(a){for(;o>i;i++)if(r=t.call(e[i],i,e[i]),r===!1)break}else for(i in e)if(r=t.call(e[i],i,e[i]),r===!1)break;return e},trim:b&&!b.call(\"\\ufeff\\u00a0\")?function(e){return null==e?\"\":b.call(e)}:function(e){return null==e?\"\":(e+\"\").replace(C,\"\")},makeArray:function(e,t){var n=t||[];return null!=e&&(M(Object(e))?x.merge(n,\"string\"==typeof e?[e]:e):h.call(n,e)),n},inArray:function(e,t,n){var r;if(t){if(m)return m.call(t,e,n);for(r=t.length,n=n?0>n?Math.max(0,r+n):n:0;r>n;n++)if(n in t&&t[n]===e)return n}return-1},merge:function(e,n){var r=n.length,i=e.length,o=0;if(\"number\"==typeof r)for(;r>o;o++)e[i++]=n[o];else while(n[o]!==t)e[i++]=n[o++];return e.length=i,e},grep:function(e,t,n){var r,i=[],o=0,a=e.length;for(n=!!n;a>o;o++)r=!!t(e[o],o),n!==r&&i.push(e[o]);return i},map:function(e,t,n){var r,i=0,o=e.length,a=M(e),s=[];if(a)for(;o>i;i++)r=t(e[i],i,n),null!=r&&(s[s.length]=r);else for(i in e)r=t(e[i],i,n),null!=r&&(s[s.length]=r);return d.apply([],s)},guid:1,proxy:function(e,n){var r,i,o;return\"string\"==typeof n&&(o=e[n],n=e,e=o),x.isFunction(e)?(r=g.call(arguments,2),i=function(){return e.apply(n||this,r.concat(g.call(arguments)))},i.guid=e.guid=e.guid||x.guid++,i):t},access:function(e,n,r,i,o,a,s){var l=0,u=e.length,c=null==r;if(\"object\"===x.type(r)){o=!0;for(l in r)x.access(e,n,l,r[l],!0,a,s)}else if(i!==t&&(o=!0,x.isFunction(i)||(s=!0),c&&(s?(n.call(e,i),n=null):(c=n,n=function(e,t,n){return c.call(x(e),n)})),n))for(;u>l;l++)n(e[l],r,s?i:i.call(e[l],l,n(e[l],r)));return o?e:c?n.call(e):u?n(e[0],r):a},now:function(){return(new Date).getTime()},swap:function(e,t,n,r){var i,o,a={};for(o in t)a[o]=e.style[o],e.style[o]=t[o];i=n.apply(e,r||[]);for(o in t)e.style[o]=a[o];return i}}),x.ready.promise=function(t){if(!n)if(n=x.Deferred(),\"complete\"===a.readyState)setTimeout(x.ready);else if(a.addEventListener)a.addEventListener(\"DOMContentLoaded\",q,!1),e.addEventListener(\"load\",q,!1);else{a.attachEvent(\"onreadystatechange\",q),e.attachEvent(\"onload\",q);var r=!1;try{r=null==e.frameElement&&a.documentElement}catch(i){}r&&r.doScroll&&function o(){if(!x.isReady){try{r.doScroll(\"left\")}catch(e){return setTimeout(o,50)}_(),x.ready()}}()}return n.promise(t)},x.each(\"Boolean Number String Function Array Date RegExp Object Error\".split(\" \"),function(e,t){c[\"[object \"+t+\"]\"]=t.toLowerCase()});function M(e){var t=e.length,n=x.type(e);return x.isWindow(e)?!1:1===e.nodeType&&t?!0:\"array\"===n||\"function\"!==n&&(0===t||\"number\"==typeof t&&t>0&&t-1 in e)}r=x(a),function(e,t){var n,r,i,o,a,s,l,u,c,p,f,d,h,g,m,y,v,b=\"sizzle\"+-new Date,w=e.document,T=0,C=0,N=st(),k=st(),E=st(),S=!1,A=function(e,t){return e===t?(S=!0,0):0},j=typeof t,D=1<<31,L={}.hasOwnProperty,H=[],q=H.pop,_=H.push,M=H.push,O=H.slice,F=H.indexOf||function(e){var t=0,n=this.length;for(;n>t;t++)if(this[t]===e)return t;return-1},B=\"checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped\",P=\"[\\\\x20\\\\t\\\\r\\\\n\\\\f]\",R=\"(?:\\\\\\\\.|[\\\\w-]|[^\\\\x00-\\\\xa0])+\",W=R.replace(\"w\",\"w#\"),$=\"\\\\[\"+P+\"*(\"+R+\")\"+P+\"*(?:([*^$|!~]?=)\"+P+\"*(?:(['\\\"])((?:\\\\\\\\.|[^\\\\\\\\])*?)\\\\3|(\"+W+\")|)|)\"+P+\"*\\\\]\",I=\":(\"+R+\")(?:\\\\(((['\\\"])((?:\\\\\\\\.|[^\\\\\\\\])*?)\\\\3|((?:\\\\\\\\.|[^\\\\\\\\()[\\\\]]|\"+$.replace(3,8)+\")*)|.*)\\\\)|)\",z=RegExp(\"^\"+P+\"+|((?:^|[^\\\\\\\\])(?:\\\\\\\\.)*)\"+P+\"+$\",\"g\"),X=RegExp(\"^\"+P+\"*,\"+P+\"*\"),U=RegExp(\"^\"+P+\"*([>+~]|\"+P+\")\"+P+\"*\"),V=RegExp(P+\"*[+~]\"),Y=RegExp(\"=\"+P+\"*([^\\\\]'\\\"]*)\"+P+\"*\\\\]\",\"g\"),J=RegExp(I),G=RegExp(\"^\"+W+\"$\"),Q={ID:RegExp(\"^#(\"+R+\")\"),CLASS:RegExp(\"^\\\\.(\"+R+\")\"),TAG:RegExp(\"^(\"+R.replace(\"w\",\"w*\")+\")\"),ATTR:RegExp(\"^\"+$),PSEUDO:RegExp(\"^\"+I),CHILD:RegExp(\"^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\\\(\"+P+\"*(even|odd|(([+-]|)(\\\\d*)n|)\"+P+\"*(?:([+-]|)\"+P+\"*(\\\\d+)|))\"+P+\"*\\\\)|)\",\"i\"),bool:RegExp(\"^(?:\"+B+\")$\",\"i\"),needsContext:RegExp(\"^\"+P+\"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\\\(\"+P+\"*((?:-\\\\d)?\\\\d*)\"+P+\"*\\\\)|)(?=[^-]|$)\",\"i\")},K=/^[^{]+\\{\\s*\\[native \\w/,Z=/^(?:#([\\w-]+)|(\\w+)|\\.([\\w-]+))$/,et=/^(?:input|select|textarea|button)$/i,tt=/^h\\d$/i,nt=/'|\\\\/g,rt=RegExp(\"\\\\\\\\([\\\\da-f]{1,6}\"+P+\"?|(\"+P+\")|.)\",\"ig\"),it=function(e,t,n){var r=\"0x\"+t-65536;return r!==r||n?t:0>r?String.fromCharCode(r+65536):String.fromCharCode(55296|r>>10,56320|1023&r)};try{M.apply(H=O.call(w.childNodes),w.childNodes),H[w.childNodes.length].nodeType}catch(ot){M={apply:H.length?function(e,t){_.apply(e,O.call(t))}:function(e,t){var n=e.length,r=0;while(e[n++]=t[r++]);e.length=n-1}}}function at(e,t,n,i){var o,a,s,l,u,c,d,m,y,x;if((t?t.ownerDocument||t:w)!==f&&p(t),t=t||f,n=n||[],!e||\"string\"!=typeof e)return n;if(1!==(l=t.nodeType)&&9!==l)return[];if(h&&!i){if(o=Z.exec(e))if(s=o[1]){if(9===l){if(a=t.getElementById(s),!a||!a.parentNode)return n;if(a.id===s)return n.push(a),n}else if(t.ownerDocument&&(a=t.ownerDocument.getElementById(s))&&v(t,a)&&a.id===s)return n.push(a),n}else{if(o[2])return M.apply(n,t.getElementsByTagName(e)),n;if((s=o[3])&&r.getElementsByClassName&&t.getElementsByClassName)return M.apply(n,t.getElementsByClassName(s)),n}if(r.qsa&&(!g||!g.test(e))){if(m=d=b,y=t,x=9===l&&e,1===l&&\"object\"!==t.nodeName.toLowerCase()){c=mt(e),(d=t.getAttribute(\"id\"))?m=d.replace(nt,\"\\\\$&\"):t.setAttribute(\"id\",m),m=\"[id='\"+m+\"'] \",u=c.length;while(u--)c[u]=m+yt(c[u]);y=V.test(e)&&t.parentNode||t,x=c.join(\",\")}if(x)try{return M.apply(n,y.querySelectorAll(x)),n}catch(T){}finally{d||t.removeAttribute(\"id\")}}}return kt(e.replace(z,\"$1\"),t,n,i)}function st(){var e=[];function t(n,r){return e.push(n+=\" \")>o.cacheLength&&delete t[e.shift()],t[n]=r}return t}function lt(e){return e[b]=!0,e}function ut(e){var t=f.createElement(\"div\");try{return!!e(t)}catch(n){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function ct(e,t){var n=e.split(\"|\"),r=e.length;while(r--)o.attrHandle[n[r]]=t}function pt(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&(~t.sourceIndex||D)-(~e.sourceIndex||D);if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function ft(e){return function(t){var n=t.nodeName.toLowerCase();return\"input\"===n&&t.type===e}}function dt(e){return function(t){var n=t.nodeName.toLowerCase();return(\"input\"===n||\"button\"===n)&&t.type===e}}function ht(e){return lt(function(t){return t=+t,lt(function(n,r){var i,o=e([],n.length,t),a=o.length;while(a--)n[i=o[a]]&&(n[i]=!(r[i]=n[i]))})})}s=at.isXML=function(e){var t=e&&(e.ownerDocument||e).documentElement;return t?\"HTML\"!==t.nodeName:!1},r=at.support={},p=at.setDocument=function(e){var n=e?e.ownerDocument||e:w,i=n.defaultView;return n!==f&&9===n.nodeType&&n.documentElement?(f=n,d=n.documentElement,h=!s(n),i&&i.attachEvent&&i!==i.top&&i.attachEvent(\"onbeforeunload\",function(){p()}),r.attributes=ut(function(e){return e.className=\"i\",!e.getAttribute(\"className\")}),r.getElementsByTagName=ut(function(e){return e.appendChild(n.createComment(\"\")),!e.getElementsByTagName(\"*\").length}),r.getElementsByClassName=ut(function(e){return e.innerHTML=\"<div class='a'></div><div class='a i'></div>\",e.firstChild.className=\"i\",2===e.getElementsByClassName(\"i\").length}),r.getById=ut(function(e){return d.appendChild(e).id=b,!n.getElementsByName||!n.getElementsByName(b).length}),r.getById?(o.find.ID=function(e,t){if(typeof t.getElementById!==j&&h){var n=t.getElementById(e);return n&&n.parentNode?[n]:[]}},o.filter.ID=function(e){var t=e.replace(rt,it);return function(e){return e.getAttribute(\"id\")===t}}):(delete o.find.ID,o.filter.ID=function(e){var t=e.replace(rt,it);return function(e){var n=typeof e.getAttributeNode!==j&&e.getAttributeNode(\"id\");return n&&n.value===t}}),o.find.TAG=r.getElementsByTagName?function(e,n){return typeof n.getElementsByTagName!==j?n.getElementsByTagName(e):t}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if(\"*\"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},o.find.CLASS=r.getElementsByClassName&&function(e,n){return typeof n.getElementsByClassName!==j&&h?n.getElementsByClassName(e):t},m=[],g=[],(r.qsa=K.test(n.querySelectorAll))&&(ut(function(e){e.innerHTML=\"<select><option selected=''></option></select>\",e.querySelectorAll(\"[selected]\").length||g.push(\"\\\\[\"+P+\"*(?:value|\"+B+\")\"),e.querySelectorAll(\":checked\").length||g.push(\":checked\")}),ut(function(e){var t=n.createElement(\"input\");t.setAttribute(\"type\",\"hidden\"),e.appendChild(t).setAttribute(\"t\",\"\"),e.querySelectorAll(\"[t^='']\").length&&g.push(\"[*^$]=\"+P+\"*(?:''|\\\"\\\")\"),e.querySelectorAll(\":enabled\").length||g.push(\":enabled\",\":disabled\"),e.querySelectorAll(\"*,:x\"),g.push(\",.*:\")})),(r.matchesSelector=K.test(y=d.webkitMatchesSelector||d.mozMatchesSelector||d.oMatchesSelector||d.msMatchesSelector))&&ut(function(e){r.disconnectedMatch=y.call(e,\"div\"),y.call(e,\"[s!='']:x\"),m.push(\"!=\",I)}),g=g.length&&RegExp(g.join(\"|\")),m=m.length&&RegExp(m.join(\"|\")),v=K.test(d.contains)||d.compareDocumentPosition?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},A=d.compareDocumentPosition?function(e,t){if(e===t)return S=!0,0;var i=t.compareDocumentPosition&&e.compareDocumentPosition&&e.compareDocumentPosition(t);return i?1&i||!r.sortDetached&&t.compareDocumentPosition(e)===i?e===n||v(w,e)?-1:t===n||v(w,t)?1:c?F.call(c,e)-F.call(c,t):0:4&i?-1:1:e.compareDocumentPosition?-1:1}:function(e,t){var r,i=0,o=e.parentNode,a=t.parentNode,s=[e],l=[t];if(e===t)return S=!0,0;if(!o||!a)return e===n?-1:t===n?1:o?-1:a?1:c?F.call(c,e)-F.call(c,t):0;if(o===a)return pt(e,t);r=e;while(r=r.parentNode)s.unshift(r);r=t;while(r=r.parentNode)l.unshift(r);while(s[i]===l[i])i++;return i?pt(s[i],l[i]):s[i]===w?-1:l[i]===w?1:0},n):f},at.matches=function(e,t){return at(e,null,null,t)},at.matchesSelector=function(e,t){if((e.ownerDocument||e)!==f&&p(e),t=t.replace(Y,\"='$1']\"),!(!r.matchesSelector||!h||m&&m.test(t)||g&&g.test(t)))try{var n=y.call(e,t);if(n||r.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(i){}return at(t,f,null,[e]).length>0},at.contains=function(e,t){return(e.ownerDocument||e)!==f&&p(e),v(e,t)},at.attr=function(e,n){(e.ownerDocument||e)!==f&&p(e);var i=o.attrHandle[n.toLowerCase()],a=i&&L.call(o.attrHandle,n.toLowerCase())?i(e,n,!h):t;return a===t?r.attributes||!h?e.getAttribute(n):(a=e.getAttributeNode(n))&&a.specified?a.value:null:a},at.error=function(e){throw Error(\"Syntax error, unrecognized expression: \"+e)},at.uniqueSort=function(e){var t,n=[],i=0,o=0;if(S=!r.detectDuplicates,c=!r.sortStable&&e.slice(0),e.sort(A),S){while(t=e[o++])t===e[o]&&(i=n.push(o));while(i--)e.splice(n[i],1)}return e},a=at.getText=function(e){var t,n=\"\",r=0,i=e.nodeType;if(i){if(1===i||9===i||11===i){if(\"string\"==typeof e.textContent)return e.textContent;for(e=e.firstChild;e;e=e.nextSibling)n+=a(e)}else if(3===i||4===i)return e.nodeValue}else for(;t=e[r];r++)n+=a(t);return n},o=at.selectors={cacheLength:50,createPseudo:lt,match:Q,attrHandle:{},find:{},relative:{\">\":{dir:\"parentNode\",first:!0},\" \":{dir:\"parentNode\"},\"+\":{dir:\"previousSibling\",first:!0},\"~\":{dir:\"previousSibling\"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(rt,it),e[3]=(e[4]||e[5]||\"\").replace(rt,it),\"~=\"===e[2]&&(e[3]=\" \"+e[3]+\" \"),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),\"nth\"===e[1].slice(0,3)?(e[3]||at.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*(\"even\"===e[3]||\"odd\"===e[3])),e[5]=+(e[7]+e[8]||\"odd\"===e[3])):e[3]&&at.error(e[0]),e},PSEUDO:function(e){var n,r=!e[5]&&e[2];return Q.CHILD.test(e[0])?null:(e[3]&&e[4]!==t?e[2]=e[4]:r&&J.test(r)&&(n=mt(r,!0))&&(n=r.indexOf(\")\",r.length-n)-r.length)&&(e[0]=e[0].slice(0,n),e[2]=r.slice(0,n)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(rt,it).toLowerCase();return\"*\"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=N[e+\" \"];return t||(t=RegExp(\"(^|\"+P+\")\"+e+\"(\"+P+\"|$)\"))&&N(e,function(e){return t.test(\"string\"==typeof e.className&&e.className||typeof e.getAttribute!==j&&e.getAttribute(\"class\")||\"\")})},ATTR:function(e,t,n){return function(r){var i=at.attr(r,e);return null==i?\"!=\"===t:t?(i+=\"\",\"=\"===t?i===n:\"!=\"===t?i!==n:\"^=\"===t?n&&0===i.indexOf(n):\"*=\"===t?n&&i.indexOf(n)>-1:\"$=\"===t?n&&i.slice(-n.length)===n:\"~=\"===t?(\" \"+i+\" \").indexOf(n)>-1:\"|=\"===t?i===n||i.slice(0,n.length+1)===n+\"-\":!1):!0}},CHILD:function(e,t,n,r,i){var o=\"nth\"!==e.slice(0,3),a=\"last\"!==e.slice(-4),s=\"of-type\"===t;return 1===r&&0===i?function(e){return!!e.parentNode}:function(t,n,l){var u,c,p,f,d,h,g=o!==a?\"nextSibling\":\"previousSibling\",m=t.parentNode,y=s&&t.nodeName.toLowerCase(),v=!l&&!s;if(m){if(o){while(g){p=t;while(p=p[g])if(s?p.nodeName.toLowerCase()===y:1===p.nodeType)return!1;h=g=\"only\"===e&&!h&&\"nextSibling\"}return!0}if(h=[a?m.firstChild:m.lastChild],a&&v){c=m[b]||(m[b]={}),u=c[e]||[],d=u[0]===T&&u[1],f=u[0]===T&&u[2],p=d&&m.childNodes[d];while(p=++d&&p&&p[g]||(f=d=0)||h.pop())if(1===p.nodeType&&++f&&p===t){c[e]=[T,d,f];break}}else if(v&&(u=(t[b]||(t[b]={}))[e])&&u[0]===T)f=u[1];else while(p=++d&&p&&p[g]||(f=d=0)||h.pop())if((s?p.nodeName.toLowerCase()===y:1===p.nodeType)&&++f&&(v&&((p[b]||(p[b]={}))[e]=[T,f]),p===t))break;return f-=i,f===r||0===f%r&&f/r>=0}}},PSEUDO:function(e,t){var n,r=o.pseudos[e]||o.setFilters[e.toLowerCase()]||at.error(\"unsupported pseudo: \"+e);return r[b]?r(t):r.length>1?(n=[e,e,\"\",t],o.setFilters.hasOwnProperty(e.toLowerCase())?lt(function(e,n){var i,o=r(e,t),a=o.length;while(a--)i=F.call(e,o[a]),e[i]=!(n[i]=o[a])}):function(e){return r(e,0,n)}):r}},pseudos:{not:lt(function(e){var t=[],n=[],r=l(e.replace(z,\"$1\"));return r[b]?lt(function(e,t,n,i){var o,a=r(e,null,i,[]),s=e.length;while(s--)(o=a[s])&&(e[s]=!(t[s]=o))}):function(e,i,o){return t[0]=e,r(t,null,o,n),!n.pop()}}),has:lt(function(e){return function(t){return at(e,t).length>0}}),contains:lt(function(e){return function(t){return(t.textContent||t.innerText||a(t)).indexOf(e)>-1}}),lang:lt(function(e){return G.test(e||\"\")||at.error(\"unsupported lang: \"+e),e=e.replace(rt,it).toLowerCase(),function(t){var n;do if(n=h?t.lang:t.getAttribute(\"xml:lang\")||t.getAttribute(\"lang\"))return n=n.toLowerCase(),n===e||0===n.indexOf(e+\"-\");while((t=t.parentNode)&&1===t.nodeType);return!1}}),target:function(t){var n=e.location&&e.location.hash;return n&&n.slice(1)===t.id},root:function(e){return e===d},focus:function(e){return e===f.activeElement&&(!f.hasFocus||f.hasFocus())&&!!(e.type||e.href||~e.tabIndex)},enabled:function(e){return e.disabled===!1},disabled:function(e){return e.disabled===!0},checked:function(e){var t=e.nodeName.toLowerCase();return\"input\"===t&&!!e.checked||\"option\"===t&&!!e.selected},selected:function(e){return e.parentNode&&e.parentNode.selectedIndex,e.selected===!0},empty:function(e){for(e=e.firstChild;e;e=e.nextSibling)if(e.nodeName>\"@\"||3===e.nodeType||4===e.nodeType)return!1;return!0},parent:function(e){return!o.pseudos.empty(e)},header:function(e){return tt.test(e.nodeName)},input:function(e){return et.test(e.nodeName)},button:function(e){var t=e.nodeName.toLowerCase();return\"input\"===t&&\"button\"===e.type||\"button\"===t},text:function(e){var t;return\"input\"===e.nodeName.toLowerCase()&&\"text\"===e.type&&(null==(t=e.getAttribute(\"type\"))||t.toLowerCase()===e.type)},first:ht(function(){return[0]}),last:ht(function(e,t){return[t-1]}),eq:ht(function(e,t,n){return[0>n?n+t:n]}),even:ht(function(e,t){var n=0;for(;t>n;n+=2)e.push(n);return e}),odd:ht(function(e,t){var n=1;for(;t>n;n+=2)e.push(n);return e}),lt:ht(function(e,t,n){var r=0>n?n+t:n;for(;--r>=0;)e.push(r);return e}),gt:ht(function(e,t,n){var r=0>n?n+t:n;for(;t>++r;)e.push(r);return e})}},o.pseudos.nth=o.pseudos.eq;for(n in{radio:!0,checkbox:!0,file:!0,password:!0,image:!0})o.pseudos[n]=ft(n);for(n in{submit:!0,reset:!0})o.pseudos[n]=dt(n);function gt(){}gt.prototype=o.filters=o.pseudos,o.setFilters=new gt;function mt(e,t){var n,r,i,a,s,l,u,c=k[e+\" \"];if(c)return t?0:c.slice(0);s=e,l=[],u=o.preFilter;while(s){(!n||(r=X.exec(s)))&&(r&&(s=s.slice(r[0].length)||s),l.push(i=[])),n=!1,(r=U.exec(s))&&(n=r.shift(),i.push({value:n,type:r[0].replace(z,\" \")}),s=s.slice(n.length));for(a in o.filter)!(r=Q[a].exec(s))||u[a]&&!(r=u[a](r))||(n=r.shift(),i.push({value:n,type:a,matches:r}),s=s.slice(n.length));if(!n)break}return t?s.length:s?at.error(e):k(e,l).slice(0)}function yt(e){var t=0,n=e.length,r=\"\";for(;n>t;t++)r+=e[t].value;return r}function vt(e,t,n){var r=t.dir,o=n&&\"parentNode\"===r,a=C++;return t.first?function(t,n,i){while(t=t[r])if(1===t.nodeType||o)return e(t,n,i)}:function(t,n,s){var l,u,c,p=T+\" \"+a;if(s){while(t=t[r])if((1===t.nodeType||o)&&e(t,n,s))return!0}else while(t=t[r])if(1===t.nodeType||o)if(c=t[b]||(t[b]={}),(u=c[r])&&u[0]===p){if((l=u[1])===!0||l===i)return l===!0}else if(u=c[r]=[p],u[1]=e(t,n,s)||i,u[1]===!0)return!0}}function bt(e){return e.length>1?function(t,n,r){var i=e.length;while(i--)if(!e[i](t,n,r))return!1;return!0}:e[0]}function xt(e,t,n,r,i){var o,a=[],s=0,l=e.length,u=null!=t;for(;l>s;s++)(o=e[s])&&(!n||n(o,r,i))&&(a.push(o),u&&t.push(s));return a}function wt(e,t,n,r,i,o){return r&&!r[b]&&(r=wt(r)),i&&!i[b]&&(i=wt(i,o)),lt(function(o,a,s,l){var u,c,p,f=[],d=[],h=a.length,g=o||Nt(t||\"*\",s.nodeType?[s]:s,[]),m=!e||!o&&t?g:xt(g,f,e,s,l),y=n?i||(o?e:h||r)?[]:a:m;if(n&&n(m,y,s,l),r){u=xt(y,d),r(u,[],s,l),c=u.length;while(c--)(p=u[c])&&(y[d[c]]=!(m[d[c]]=p))}if(o){if(i||e){if(i){u=[],c=y.length;while(c--)(p=y[c])&&u.push(m[c]=p);i(null,y=[],u,l)}c=y.length;while(c--)(p=y[c])&&(u=i?F.call(o,p):f[c])>-1&&(o[u]=!(a[u]=p))}}else y=xt(y===a?y.splice(h,y.length):y),i?i(null,a,y,l):M.apply(a,y)})}function Tt(e){var t,n,r,i=e.length,a=o.relative[e[0].type],s=a||o.relative[\" \"],l=a?1:0,c=vt(function(e){return e===t},s,!0),p=vt(function(e){return F.call(t,e)>-1},s,!0),f=[function(e,n,r){return!a&&(r||n!==u)||((t=n).nodeType?c(e,n,r):p(e,n,r))}];for(;i>l;l++)if(n=o.relative[e[l].type])f=[vt(bt(f),n)];else{if(n=o.filter[e[l].type].apply(null,e[l].matches),n[b]){for(r=++l;i>r;r++)if(o.relative[e[r].type])break;return wt(l>1&&bt(f),l>1&&yt(e.slice(0,l-1).concat({value:\" \"===e[l-2].type?\"*\":\"\"})).replace(z,\"$1\"),n,r>l&&Tt(e.slice(l,r)),i>r&&Tt(e=e.slice(r)),i>r&&yt(e))}f.push(n)}return bt(f)}function Ct(e,t){var n=0,r=t.length>0,a=e.length>0,s=function(s,l,c,p,d){var h,g,m,y=[],v=0,b=\"0\",x=s&&[],w=null!=d,C=u,N=s||a&&o.find.TAG(\"*\",d&&l.parentNode||l),k=T+=null==C?1:Math.random()||.1;for(w&&(u=l!==f&&l,i=n);null!=(h=N[b]);b++){if(a&&h){g=0;while(m=e[g++])if(m(h,l,c)){p.push(h);break}w&&(T=k,i=++n)}r&&((h=!m&&h)&&v--,s&&x.push(h))}if(v+=b,r&&b!==v){g=0;while(m=t[g++])m(x,y,l,c);if(s){if(v>0)while(b--)x[b]||y[b]||(y[b]=q.call(p));y=xt(y)}M.apply(p,y),w&&!s&&y.length>0&&v+t.length>1&&at.uniqueSort(p)}return w&&(T=k,u=C),x};return r?lt(s):s}l=at.compile=function(e,t){var n,r=[],i=[],o=E[e+\" \"];if(!o){t||(t=mt(e)),n=t.length;while(n--)o=Tt(t[n]),o[b]?r.push(o):i.push(o);o=E(e,Ct(i,r))}return o};function Nt(e,t,n){var r=0,i=t.length;for(;i>r;r++)at(e,t[r],n);return n}function kt(e,t,n,i){var a,s,u,c,p,f=mt(e);if(!i&&1===f.length){if(s=f[0]=f[0].slice(0),s.length>2&&\"ID\"===(u=s[0]).type&&r.getById&&9===t.nodeType&&h&&o.relative[s[1].type]){if(t=(o.find.ID(u.matches[0].replace(rt,it),t)||[])[0],!t)return n;e=e.slice(s.shift().value.length)}a=Q.needsContext.test(e)?0:s.length;while(a--){if(u=s[a],o.relative[c=u.type])break;if((p=o.find[c])&&(i=p(u.matches[0].replace(rt,it),V.test(s[0].type)&&t.parentNode||t))){if(s.splice(a,1),e=i.length&&yt(s),!e)return M.apply(n,i),n;break}}}return l(e,f)(i,t,!h,n,V.test(e)),n}r.sortStable=b.split(\"\").sort(A).join(\"\")===b,r.detectDuplicates=S,p(),r.sortDetached=ut(function(e){return 1&e.compareDocumentPosition(f.createElement(\"div\"))}),ut(function(e){return e.innerHTML=\"<a href='#'></a>\",\"#\"===e.firstChild.getAttribute(\"href\")})||ct(\"type|href|height|width\",function(e,n,r){return r?t:e.getAttribute(n,\"type\"===n.toLowerCase()?1:2)}),r.attributes&&ut(function(e){return e.innerHTML=\"<input/>\",e.firstChild.setAttribute(\"value\",\"\"),\"\"===e.firstChild.getAttribute(\"value\")})||ct(\"value\",function(e,n,r){return r||\"input\"!==e.nodeName.toLowerCase()?t:e.defaultValue}),ut(function(e){return null==e.getAttribute(\"disabled\")})||ct(B,function(e,n,r){var i;return r?t:(i=e.getAttributeNode(n))&&i.specified?i.value:e[n]===!0?n.toLowerCase():null}),x.find=at,x.expr=at.selectors,x.expr[\":\"]=x.expr.pseudos,x.unique=at.uniqueSort,x.text=at.getText,x.isXMLDoc=at.isXML,x.contains=at.contains}(e);var O={};function F(e){var t=O[e]={};return x.each(e.match(T)||[],function(e,n){t[n]=!0}),t}x.Callbacks=function(e){e=\"string\"==typeof e?O[e]||F(e):x.extend({},e);var n,r,i,o,a,s,l=[],u=!e.once&&[],c=function(t){for(r=e.memory&&t,i=!0,a=s||0,s=0,o=l.length,n=!0;l&&o>a;a++)if(l[a].apply(t[0],t[1])===!1&&e.stopOnFalse){r=!1;break}n=!1,l&&(u?u.length&&c(u.shift()):r?l=[]:p.disable())},p={add:function(){if(l){var t=l.length;(function i(t){x.each(t,function(t,n){var r=x.type(n);\"function\"===r?e.unique&&p.has(n)||l.push(n):n&&n.length&&\"string\"!==r&&i(n)})})(arguments),n?o=l.length:r&&(s=t,c(r))}return this},remove:function(){return l&&x.each(arguments,function(e,t){var r;while((r=x.inArray(t,l,r))>-1)l.splice(r,1),n&&(o>=r&&o--,a>=r&&a--)}),this},has:function(e){return e?x.inArray(e,l)>-1:!(!l||!l.length)},empty:function(){return l=[],o=0,this},disable:function(){return l=u=r=t,this},disabled:function(){return!l},lock:function(){return u=t,r||p.disable(),this},locked:function(){return!u},fireWith:function(e,t){return!l||i&&!u||(t=t||[],t=[e,t.slice?t.slice():t],n?u.push(t):c(t)),this},fire:function(){return p.fireWith(this,arguments),this},fired:function(){return!!i}};return p},x.extend({Deferred:function(e){var t=[[\"resolve\",\"done\",x.Callbacks(\"once memory\"),\"resolved\"],[\"reject\",\"fail\",x.Callbacks(\"once memory\"),\"rejected\"],[\"notify\",\"progress\",x.Callbacks(\"memory\")]],n=\"pending\",r={state:function(){return n},always:function(){return i.done(arguments).fail(arguments),this},then:function(){var e=arguments;return x.Deferred(function(n){x.each(t,function(t,o){var a=o[0],s=x.isFunction(e[t])&&e[t];i[o[1]](function(){var e=s&&s.apply(this,arguments);e&&x.isFunction(e.promise)?e.promise().done(n.resolve).fail(n.reject).progress(n.notify):n[a+\"With\"](this===r?n.promise():this,s?[e]:arguments)})}),e=null}).promise()},promise:function(e){return null!=e?x.extend(e,r):r}},i={};return r.pipe=r.then,x.each(t,function(e,o){var a=o[2],s=o[3];r[o[1]]=a.add,s&&a.add(function(){n=s},t[1^e][2].disable,t[2][2].lock),i[o[0]]=function(){return i[o[0]+\"With\"](this===i?r:this,arguments),this},i[o[0]+\"With\"]=a.fireWith}),r.promise(i),e&&e.call(i,i),i},when:function(e){var t=0,n=g.call(arguments),r=n.length,i=1!==r||e&&x.isFunction(e.promise)?r:0,o=1===i?e:x.Deferred(),a=function(e,t,n){return function(r){t[e]=this,n[e]=arguments.length>1?g.call(arguments):r,n===s?o.notifyWith(t,n):--i||o.resolveWith(t,n)}},s,l,u;if(r>1)for(s=Array(r),l=Array(r),u=Array(r);r>t;t++)n[t]&&x.isFunction(n[t].promise)?n[t].promise().done(a(t,u,n)).fail(o.reject).progress(a(t,l,s)):--i;return i||o.resolveWith(u,n),o.promise()}}),x.support=function(t){var n,r,o,s,l,u,c,p,f,d=a.createElement(\"div\");if(d.setAttribute(\"className\",\"t\"),d.innerHTML=\"  <link/><table></table><a href='/a'>a</a><input type='checkbox'/>\",n=d.getElementsByTagName(\"*\")||[],r=d.getElementsByTagName(\"a\")[0],!r||!r.style||!n.length)return t;s=a.createElement(\"select\"),u=s.appendChild(a.createElement(\"option\")),o=d.getElementsByTagName(\"input\")[0],r.style.cssText=\"top:1px;float:left;opacity:.5\",t.getSetAttribute=\"t\"!==d.className,t.leadingWhitespace=3===d.firstChild.nodeType,t.tbody=!d.getElementsByTagName(\"tbody\").length,t.htmlSerialize=!!d.getElementsByTagName(\"link\").length,t.style=/top/.test(r.getAttribute(\"style\")),t.hrefNormalized=\"/a\"===r.getAttribute(\"href\"),t.opacity=/^0.5/.test(r.style.opacity),t.cssFloat=!!r.style.cssFloat,t.checkOn=!!o.value,t.optSelected=u.selected,t.enctype=!!a.createElement(\"form\").enctype,t.html5Clone=\"<:nav></:nav>\"!==a.createElement(\"nav\").cloneNode(!0).outerHTML,t.inlineBlockNeedsLayout=!1,t.shrinkWrapBlocks=!1,t.pixelPosition=!1,t.deleteExpando=!0,t.noCloneEvent=!0,t.reliableMarginRight=!0,t.boxSizingReliable=!0,o.checked=!0,t.noCloneChecked=o.cloneNode(!0).checked,s.disabled=!0,t.optDisabled=!u.disabled;try{delete d.test}catch(h){t.deleteExpando=!1}o=a.createElement(\"input\"),o.setAttribute(\"value\",\"\"),t.input=\"\"===o.getAttribute(\"value\"),o.value=\"t\",o.setAttribute(\"type\",\"radio\"),t.radioValue=\"t\"===o.value,o.setAttribute(\"checked\",\"t\"),o.setAttribute(\"name\",\"t\"),l=a.createDocumentFragment(),l.appendChild(o),t.appendChecked=o.checked,t.checkClone=l.cloneNode(!0).cloneNode(!0).lastChild.checked,d.attachEvent&&(d.attachEvent(\"onclick\",function(){t.noCloneEvent=!1}),d.cloneNode(!0).click());for(f in{submit:!0,change:!0,focusin:!0})d.setAttribute(c=\"on\"+f,\"t\"),t[f+\"Bubbles\"]=c in e||d.attributes[c].expando===!1;d.style.backgroundClip=\"content-box\",d.cloneNode(!0).style.backgroundClip=\"\",t.clearCloneStyle=\"content-box\"===d.style.backgroundClip;for(f in x(t))break;return t.ownLast=\"0\"!==f,x(function(){var n,r,o,s=\"padding:0;margin:0;border:0;display:block;box-sizing:content-box;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;\",l=a.getElementsByTagName(\"body\")[0];l&&(n=a.createElement(\"div\"),n.style.cssText=\"border:0;width:0;height:0;position:absolute;top:0;left:-9999px;margin-top:1px\",l.appendChild(n).appendChild(d),d.innerHTML=\"<table><tr><td></td><td>t</td></tr></table>\",o=d.getElementsByTagName(\"td\"),o[0].style.cssText=\"padding:0;margin:0;border:0;display:none\",p=0===o[0].offsetHeight,o[0].style.display=\"\",o[1].style.display=\"none\",t.reliableHiddenOffsets=p&&0===o[0].offsetHeight,d.innerHTML=\"\",d.style.cssText=\"box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%;\",x.swap(l,null!=l.style.zoom?{zoom:1}:{},function(){t.boxSizing=4===d.offsetWidth}),e.getComputedStyle&&(t.pixelPosition=\"1%\"!==(e.getComputedStyle(d,null)||{}).top,t.boxSizingReliable=\"4px\"===(e.getComputedStyle(d,null)||{width:\"4px\"}).width,r=d.appendChild(a.createElement(\"div\")),r.style.cssText=d.style.cssText=s,r.style.marginRight=r.style.width=\"0\",d.style.width=\"1px\",t.reliableMarginRight=!parseFloat((e.getComputedStyle(r,null)||{}).marginRight)),typeof d.style.zoom!==i&&(d.innerHTML=\"\",d.style.cssText=s+\"width:1px;padding:1px;display:inline;zoom:1\",t.inlineBlockNeedsLayout=3===d.offsetWidth,d.style.display=\"block\",d.innerHTML=\"<div></div>\",d.firstChild.style.width=\"5px\",t.shrinkWrapBlocks=3!==d.offsetWidth,t.inlineBlockNeedsLayout&&(l.style.zoom=1)),l.removeChild(n),n=d=o=r=null)}),n=s=l=u=r=o=null,t\n}({});var B=/(?:\\{[\\s\\S]*\\}|\\[[\\s\\S]*\\])$/,P=/([A-Z])/g;function R(e,n,r,i){if(x.acceptData(e)){var o,a,s=x.expando,l=e.nodeType,u=l?x.cache:e,c=l?e[s]:e[s]&&s;if(c&&u[c]&&(i||u[c].data)||r!==t||\"string\"!=typeof n)return c||(c=l?e[s]=p.pop()||x.guid++:s),u[c]||(u[c]=l?{}:{toJSON:x.noop}),(\"object\"==typeof n||\"function\"==typeof n)&&(i?u[c]=x.extend(u[c],n):u[c].data=x.extend(u[c].data,n)),a=u[c],i||(a.data||(a.data={}),a=a.data),r!==t&&(a[x.camelCase(n)]=r),\"string\"==typeof n?(o=a[n],null==o&&(o=a[x.camelCase(n)])):o=a,o}}function W(e,t,n){if(x.acceptData(e)){var r,i,o=e.nodeType,a=o?x.cache:e,s=o?e[x.expando]:x.expando;if(a[s]){if(t&&(r=n?a[s]:a[s].data)){x.isArray(t)?t=t.concat(x.map(t,x.camelCase)):t in r?t=[t]:(t=x.camelCase(t),t=t in r?[t]:t.split(\" \")),i=t.length;while(i--)delete r[t[i]];if(n?!I(r):!x.isEmptyObject(r))return}(n||(delete a[s].data,I(a[s])))&&(o?x.cleanData([e],!0):x.support.deleteExpando||a!=a.window?delete a[s]:a[s]=null)}}}x.extend({cache:{},noData:{applet:!0,embed:!0,object:\"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000\"},hasData:function(e){return e=e.nodeType?x.cache[e[x.expando]]:e[x.expando],!!e&&!I(e)},data:function(e,t,n){return R(e,t,n)},removeData:function(e,t){return W(e,t)},_data:function(e,t,n){return R(e,t,n,!0)},_removeData:function(e,t){return W(e,t,!0)},acceptData:function(e){if(e.nodeType&&1!==e.nodeType&&9!==e.nodeType)return!1;var t=e.nodeName&&x.noData[e.nodeName.toLowerCase()];return!t||t!==!0&&e.getAttribute(\"classid\")===t}}),x.fn.extend({data:function(e,n){var r,i,o=null,a=0,s=this[0];if(e===t){if(this.length&&(o=x.data(s),1===s.nodeType&&!x._data(s,\"parsedAttrs\"))){for(r=s.attributes;r.length>a;a++)i=r[a].name,0===i.indexOf(\"data-\")&&(i=x.camelCase(i.slice(5)),$(s,i,o[i]));x._data(s,\"parsedAttrs\",!0)}return o}return\"object\"==typeof e?this.each(function(){x.data(this,e)}):arguments.length>1?this.each(function(){x.data(this,e,n)}):s?$(s,e,x.data(s,e)):null},removeData:function(e){return this.each(function(){x.removeData(this,e)})}});function $(e,n,r){if(r===t&&1===e.nodeType){var i=\"data-\"+n.replace(P,\"-$1\").toLowerCase();if(r=e.getAttribute(i),\"string\"==typeof r){try{r=\"true\"===r?!0:\"false\"===r?!1:\"null\"===r?null:+r+\"\"===r?+r:B.test(r)?x.parseJSON(r):r}catch(o){}x.data(e,n,r)}else r=t}return r}function I(e){var t;for(t in e)if((\"data\"!==t||!x.isEmptyObject(e[t]))&&\"toJSON\"!==t)return!1;return!0}x.extend({queue:function(e,n,r){var i;return e?(n=(n||\"fx\")+\"queue\",i=x._data(e,n),r&&(!i||x.isArray(r)?i=x._data(e,n,x.makeArray(r)):i.push(r)),i||[]):t},dequeue:function(e,t){t=t||\"fx\";var n=x.queue(e,t),r=n.length,i=n.shift(),o=x._queueHooks(e,t),a=function(){x.dequeue(e,t)};\"inprogress\"===i&&(i=n.shift(),r--),i&&(\"fx\"===t&&n.unshift(\"inprogress\"),delete o.stop,i.call(e,a,o)),!r&&o&&o.empty.fire()},_queueHooks:function(e,t){var n=t+\"queueHooks\";return x._data(e,n)||x._data(e,n,{empty:x.Callbacks(\"once memory\").add(function(){x._removeData(e,t+\"queue\"),x._removeData(e,n)})})}}),x.fn.extend({queue:function(e,n){var r=2;return\"string\"!=typeof e&&(n=e,e=\"fx\",r--),r>arguments.length?x.queue(this[0],e):n===t?this:this.each(function(){var t=x.queue(this,e,n);x._queueHooks(this,e),\"fx\"===e&&\"inprogress\"!==t[0]&&x.dequeue(this,e)})},dequeue:function(e){return this.each(function(){x.dequeue(this,e)})},delay:function(e,t){return e=x.fx?x.fx.speeds[e]||e:e,t=t||\"fx\",this.queue(t,function(t,n){var r=setTimeout(t,e);n.stop=function(){clearTimeout(r)}})},clearQueue:function(e){return this.queue(e||\"fx\",[])},promise:function(e,n){var r,i=1,o=x.Deferred(),a=this,s=this.length,l=function(){--i||o.resolveWith(a,[a])};\"string\"!=typeof e&&(n=e,e=t),e=e||\"fx\";while(s--)r=x._data(a[s],e+\"queueHooks\"),r&&r.empty&&(i++,r.empty.add(l));return l(),o.promise(n)}});var z,X,U=/[\\t\\r\\n\\f]/g,V=/\\r/g,Y=/^(?:input|select|textarea|button|object)$/i,J=/^(?:a|area)$/i,G=/^(?:checked|selected)$/i,Q=x.support.getSetAttribute,K=x.support.input;x.fn.extend({attr:function(e,t){return x.access(this,x.attr,e,t,arguments.length>1)},removeAttr:function(e){return this.each(function(){x.removeAttr(this,e)})},prop:function(e,t){return x.access(this,x.prop,e,t,arguments.length>1)},removeProp:function(e){return e=x.propFix[e]||e,this.each(function(){try{this[e]=t,delete this[e]}catch(n){}})},addClass:function(e){var t,n,r,i,o,a=0,s=this.length,l=\"string\"==typeof e&&e;if(x.isFunction(e))return this.each(function(t){x(this).addClass(e.call(this,t,this.className))});if(l)for(t=(e||\"\").match(T)||[];s>a;a++)if(n=this[a],r=1===n.nodeType&&(n.className?(\" \"+n.className+\" \").replace(U,\" \"):\" \")){o=0;while(i=t[o++])0>r.indexOf(\" \"+i+\" \")&&(r+=i+\" \");n.className=x.trim(r)}return this},removeClass:function(e){var t,n,r,i,o,a=0,s=this.length,l=0===arguments.length||\"string\"==typeof e&&e;if(x.isFunction(e))return this.each(function(t){x(this).removeClass(e.call(this,t,this.className))});if(l)for(t=(e||\"\").match(T)||[];s>a;a++)if(n=this[a],r=1===n.nodeType&&(n.className?(\" \"+n.className+\" \").replace(U,\" \"):\"\")){o=0;while(i=t[o++])while(r.indexOf(\" \"+i+\" \")>=0)r=r.replace(\" \"+i+\" \",\" \");n.className=e?x.trim(r):\"\"}return this},toggleClass:function(e,t){var n=typeof e;return\"boolean\"==typeof t&&\"string\"===n?t?this.addClass(e):this.removeClass(e):x.isFunction(e)?this.each(function(n){x(this).toggleClass(e.call(this,n,this.className,t),t)}):this.each(function(){if(\"string\"===n){var t,r=0,o=x(this),a=e.match(T)||[];while(t=a[r++])o.hasClass(t)?o.removeClass(t):o.addClass(t)}else(n===i||\"boolean\"===n)&&(this.className&&x._data(this,\"__className__\",this.className),this.className=this.className||e===!1?\"\":x._data(this,\"__className__\")||\"\")})},hasClass:function(e){var t=\" \"+e+\" \",n=0,r=this.length;for(;r>n;n++)if(1===this[n].nodeType&&(\" \"+this[n].className+\" \").replace(U,\" \").indexOf(t)>=0)return!0;return!1},val:function(e){var n,r,i,o=this[0];{if(arguments.length)return i=x.isFunction(e),this.each(function(n){var o;1===this.nodeType&&(o=i?e.call(this,n,x(this).val()):e,null==o?o=\"\":\"number\"==typeof o?o+=\"\":x.isArray(o)&&(o=x.map(o,function(e){return null==e?\"\":e+\"\"})),r=x.valHooks[this.type]||x.valHooks[this.nodeName.toLowerCase()],r&&\"set\"in r&&r.set(this,o,\"value\")!==t||(this.value=o))});if(o)return r=x.valHooks[o.type]||x.valHooks[o.nodeName.toLowerCase()],r&&\"get\"in r&&(n=r.get(o,\"value\"))!==t?n:(n=o.value,\"string\"==typeof n?n.replace(V,\"\"):null==n?\"\":n)}}}),x.extend({valHooks:{option:{get:function(e){var t=x.find.attr(e,\"value\");return null!=t?t:e.text}},select:{get:function(e){var t,n,r=e.options,i=e.selectedIndex,o=\"select-one\"===e.type||0>i,a=o?null:[],s=o?i+1:r.length,l=0>i?s:o?i:0;for(;s>l;l++)if(n=r[l],!(!n.selected&&l!==i||(x.support.optDisabled?n.disabled:null!==n.getAttribute(\"disabled\"))||n.parentNode.disabled&&x.nodeName(n.parentNode,\"optgroup\"))){if(t=x(n).val(),o)return t;a.push(t)}return a},set:function(e,t){var n,r,i=e.options,o=x.makeArray(t),a=i.length;while(a--)r=i[a],(r.selected=x.inArray(x(r).val(),o)>=0)&&(n=!0);return n||(e.selectedIndex=-1),o}}},attr:function(e,n,r){var o,a,s=e.nodeType;if(e&&3!==s&&8!==s&&2!==s)return typeof e.getAttribute===i?x.prop(e,n,r):(1===s&&x.isXMLDoc(e)||(n=n.toLowerCase(),o=x.attrHooks[n]||(x.expr.match.bool.test(n)?X:z)),r===t?o&&\"get\"in o&&null!==(a=o.get(e,n))?a:(a=x.find.attr(e,n),null==a?t:a):null!==r?o&&\"set\"in o&&(a=o.set(e,r,n))!==t?a:(e.setAttribute(n,r+\"\"),r):(x.removeAttr(e,n),t))},removeAttr:function(e,t){var n,r,i=0,o=t&&t.match(T);if(o&&1===e.nodeType)while(n=o[i++])r=x.propFix[n]||n,x.expr.match.bool.test(n)?K&&Q||!G.test(n)?e[r]=!1:e[x.camelCase(\"default-\"+n)]=e[r]=!1:x.attr(e,n,\"\"),e.removeAttribute(Q?n:r)},attrHooks:{type:{set:function(e,t){if(!x.support.radioValue&&\"radio\"===t&&x.nodeName(e,\"input\")){var n=e.value;return e.setAttribute(\"type\",t),n&&(e.value=n),t}}}},propFix:{\"for\":\"htmlFor\",\"class\":\"className\"},prop:function(e,n,r){var i,o,a,s=e.nodeType;if(e&&3!==s&&8!==s&&2!==s)return a=1!==s||!x.isXMLDoc(e),a&&(n=x.propFix[n]||n,o=x.propHooks[n]),r!==t?o&&\"set\"in o&&(i=o.set(e,r,n))!==t?i:e[n]=r:o&&\"get\"in o&&null!==(i=o.get(e,n))?i:e[n]},propHooks:{tabIndex:{get:function(e){var t=x.find.attr(e,\"tabindex\");return t?parseInt(t,10):Y.test(e.nodeName)||J.test(e.nodeName)&&e.href?0:-1}}}}),X={set:function(e,t,n){return t===!1?x.removeAttr(e,n):K&&Q||!G.test(n)?e.setAttribute(!Q&&x.propFix[n]||n,n):e[x.camelCase(\"default-\"+n)]=e[n]=!0,n}},x.each(x.expr.match.bool.source.match(/\\w+/g),function(e,n){var r=x.expr.attrHandle[n]||x.find.attr;x.expr.attrHandle[n]=K&&Q||!G.test(n)?function(e,n,i){var o=x.expr.attrHandle[n],a=i?t:(x.expr.attrHandle[n]=t)!=r(e,n,i)?n.toLowerCase():null;return x.expr.attrHandle[n]=o,a}:function(e,n,r){return r?t:e[x.camelCase(\"default-\"+n)]?n.toLowerCase():null}}),K&&Q||(x.attrHooks.value={set:function(e,n,r){return x.nodeName(e,\"input\")?(e.defaultValue=n,t):z&&z.set(e,n,r)}}),Q||(z={set:function(e,n,r){var i=e.getAttributeNode(r);return i||e.setAttributeNode(i=e.ownerDocument.createAttribute(r)),i.value=n+=\"\",\"value\"===r||n===e.getAttribute(r)?n:t}},x.expr.attrHandle.id=x.expr.attrHandle.name=x.expr.attrHandle.coords=function(e,n,r){var i;return r?t:(i=e.getAttributeNode(n))&&\"\"!==i.value?i.value:null},x.valHooks.button={get:function(e,n){var r=e.getAttributeNode(n);return r&&r.specified?r.value:t},set:z.set},x.attrHooks.contenteditable={set:function(e,t,n){z.set(e,\"\"===t?!1:t,n)}},x.each([\"width\",\"height\"],function(e,n){x.attrHooks[n]={set:function(e,r){return\"\"===r?(e.setAttribute(n,\"auto\"),r):t}}})),x.support.hrefNormalized||x.each([\"href\",\"src\"],function(e,t){x.propHooks[t]={get:function(e){return e.getAttribute(t,4)}}}),x.support.style||(x.attrHooks.style={get:function(e){return e.style.cssText||t},set:function(e,t){return e.style.cssText=t+\"\"}}),x.support.optSelected||(x.propHooks.selected={get:function(e){var t=e.parentNode;return t&&(t.selectedIndex,t.parentNode&&t.parentNode.selectedIndex),null}}),x.each([\"tabIndex\",\"readOnly\",\"maxLength\",\"cellSpacing\",\"cellPadding\",\"rowSpan\",\"colSpan\",\"useMap\",\"frameBorder\",\"contentEditable\"],function(){x.propFix[this.toLowerCase()]=this}),x.support.enctype||(x.propFix.enctype=\"encoding\"),x.each([\"radio\",\"checkbox\"],function(){x.valHooks[this]={set:function(e,n){return x.isArray(n)?e.checked=x.inArray(x(e).val(),n)>=0:t}},x.support.checkOn||(x.valHooks[this].get=function(e){return null===e.getAttribute(\"value\")?\"on\":e.value})});var Z=/^(?:input|select|textarea)$/i,et=/^key/,tt=/^(?:mouse|contextmenu)|click/,nt=/^(?:focusinfocus|focusoutblur)$/,rt=/^([^.]*)(?:\\.(.+)|)$/;function it(){return!0}function ot(){return!1}function at(){try{return a.activeElement}catch(e){}}x.event={global:{},add:function(e,n,r,o,a){var s,l,u,c,p,f,d,h,g,m,y,v=x._data(e);if(v){r.handler&&(c=r,r=c.handler,a=c.selector),r.guid||(r.guid=x.guid++),(l=v.events)||(l=v.events={}),(f=v.handle)||(f=v.handle=function(e){return typeof x===i||e&&x.event.triggered===e.type?t:x.event.dispatch.apply(f.elem,arguments)},f.elem=e),n=(n||\"\").match(T)||[\"\"],u=n.length;while(u--)s=rt.exec(n[u])||[],g=y=s[1],m=(s[2]||\"\").split(\".\").sort(),g&&(p=x.event.special[g]||{},g=(a?p.delegateType:p.bindType)||g,p=x.event.special[g]||{},d=x.extend({type:g,origType:y,data:o,handler:r,guid:r.guid,selector:a,needsContext:a&&x.expr.match.needsContext.test(a),namespace:m.join(\".\")},c),(h=l[g])||(h=l[g]=[],h.delegateCount=0,p.setup&&p.setup.call(e,o,m,f)!==!1||(e.addEventListener?e.addEventListener(g,f,!1):e.attachEvent&&e.attachEvent(\"on\"+g,f))),p.add&&(p.add.call(e,d),d.handler.guid||(d.handler.guid=r.guid)),a?h.splice(h.delegateCount++,0,d):h.push(d),x.event.global[g]=!0);e=null}},remove:function(e,t,n,r,i){var o,a,s,l,u,c,p,f,d,h,g,m=x.hasData(e)&&x._data(e);if(m&&(c=m.events)){t=(t||\"\").match(T)||[\"\"],u=t.length;while(u--)if(s=rt.exec(t[u])||[],d=g=s[1],h=(s[2]||\"\").split(\".\").sort(),d){p=x.event.special[d]||{},d=(r?p.delegateType:p.bindType)||d,f=c[d]||[],s=s[2]&&RegExp(\"(^|\\\\.)\"+h.join(\"\\\\.(?:.*\\\\.|)\")+\"(\\\\.|$)\"),l=o=f.length;while(o--)a=f[o],!i&&g!==a.origType||n&&n.guid!==a.guid||s&&!s.test(a.namespace)||r&&r!==a.selector&&(\"**\"!==r||!a.selector)||(f.splice(o,1),a.selector&&f.delegateCount--,p.remove&&p.remove.call(e,a));l&&!f.length&&(p.teardown&&p.teardown.call(e,h,m.handle)!==!1||x.removeEvent(e,d,m.handle),delete c[d])}else for(d in c)x.event.remove(e,d+t[u],n,r,!0);x.isEmptyObject(c)&&(delete m.handle,x._removeData(e,\"events\"))}},trigger:function(n,r,i,o){var s,l,u,c,p,f,d,h=[i||a],g=v.call(n,\"type\")?n.type:n,m=v.call(n,\"namespace\")?n.namespace.split(\".\"):[];if(u=f=i=i||a,3!==i.nodeType&&8!==i.nodeType&&!nt.test(g+x.event.triggered)&&(g.indexOf(\".\")>=0&&(m=g.split(\".\"),g=m.shift(),m.sort()),l=0>g.indexOf(\":\")&&\"on\"+g,n=n[x.expando]?n:new x.Event(g,\"object\"==typeof n&&n),n.isTrigger=o?2:3,n.namespace=m.join(\".\"),n.namespace_re=n.namespace?RegExp(\"(^|\\\\.)\"+m.join(\"\\\\.(?:.*\\\\.|)\")+\"(\\\\.|$)\"):null,n.result=t,n.target||(n.target=i),r=null==r?[n]:x.makeArray(r,[n]),p=x.event.special[g]||{},o||!p.trigger||p.trigger.apply(i,r)!==!1)){if(!o&&!p.noBubble&&!x.isWindow(i)){for(c=p.delegateType||g,nt.test(c+g)||(u=u.parentNode);u;u=u.parentNode)h.push(u),f=u;f===(i.ownerDocument||a)&&h.push(f.defaultView||f.parentWindow||e)}d=0;while((u=h[d++])&&!n.isPropagationStopped())n.type=d>1?c:p.bindType||g,s=(x._data(u,\"events\")||{})[n.type]&&x._data(u,\"handle\"),s&&s.apply(u,r),s=l&&u[l],s&&x.acceptData(u)&&s.apply&&s.apply(u,r)===!1&&n.preventDefault();if(n.type=g,!o&&!n.isDefaultPrevented()&&(!p._default||p._default.apply(h.pop(),r)===!1)&&x.acceptData(i)&&l&&i[g]&&!x.isWindow(i)){f=i[l],f&&(i[l]=null),x.event.triggered=g;try{i[g]()}catch(y){}x.event.triggered=t,f&&(i[l]=f)}return n.result}},dispatch:function(e){e=x.event.fix(e);var n,r,i,o,a,s=[],l=g.call(arguments),u=(x._data(this,\"events\")||{})[e.type]||[],c=x.event.special[e.type]||{};if(l[0]=e,e.delegateTarget=this,!c.preDispatch||c.preDispatch.call(this,e)!==!1){s=x.event.handlers.call(this,e,u),n=0;while((o=s[n++])&&!e.isPropagationStopped()){e.currentTarget=o.elem,a=0;while((i=o.handlers[a++])&&!e.isImmediatePropagationStopped())(!e.namespace_re||e.namespace_re.test(i.namespace))&&(e.handleObj=i,e.data=i.data,r=((x.event.special[i.origType]||{}).handle||i.handler).apply(o.elem,l),r!==t&&(e.result=r)===!1&&(e.preventDefault(),e.stopPropagation()))}return c.postDispatch&&c.postDispatch.call(this,e),e.result}},handlers:function(e,n){var r,i,o,a,s=[],l=n.delegateCount,u=e.target;if(l&&u.nodeType&&(!e.button||\"click\"!==e.type))for(;u!=this;u=u.parentNode||this)if(1===u.nodeType&&(u.disabled!==!0||\"click\"!==e.type)){for(o=[],a=0;l>a;a++)i=n[a],r=i.selector+\" \",o[r]===t&&(o[r]=i.needsContext?x(r,this).index(u)>=0:x.find(r,this,null,[u]).length),o[r]&&o.push(i);o.length&&s.push({elem:u,handlers:o})}return n.length>l&&s.push({elem:this,handlers:n.slice(l)}),s},fix:function(e){if(e[x.expando])return e;var t,n,r,i=e.type,o=e,s=this.fixHooks[i];s||(this.fixHooks[i]=s=tt.test(i)?this.mouseHooks:et.test(i)?this.keyHooks:{}),r=s.props?this.props.concat(s.props):this.props,e=new x.Event(o),t=r.length;while(t--)n=r[t],e[n]=o[n];return e.target||(e.target=o.srcElement||a),3===e.target.nodeType&&(e.target=e.target.parentNode),e.metaKey=!!e.metaKey,s.filter?s.filter(e,o):e},props:\"altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which\".split(\" \"),fixHooks:{},keyHooks:{props:\"char charCode key keyCode\".split(\" \"),filter:function(e,t){return null==e.which&&(e.which=null!=t.charCode?t.charCode:t.keyCode),e}},mouseHooks:{props:\"button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement\".split(\" \"),filter:function(e,n){var r,i,o,s=n.button,l=n.fromElement;return null==e.pageX&&null!=n.clientX&&(i=e.target.ownerDocument||a,o=i.documentElement,r=i.body,e.pageX=n.clientX+(o&&o.scrollLeft||r&&r.scrollLeft||0)-(o&&o.clientLeft||r&&r.clientLeft||0),e.pageY=n.clientY+(o&&o.scrollTop||r&&r.scrollTop||0)-(o&&o.clientTop||r&&r.clientTop||0)),!e.relatedTarget&&l&&(e.relatedTarget=l===e.target?n.toElement:l),e.which||s===t||(e.which=1&s?1:2&s?3:4&s?2:0),e}},special:{load:{noBubble:!0},focus:{trigger:function(){if(this!==at()&&this.focus)try{return this.focus(),!1}catch(e){}},delegateType:\"focusin\"},blur:{trigger:function(){return this===at()&&this.blur?(this.blur(),!1):t},delegateType:\"focusout\"},click:{trigger:function(){return x.nodeName(this,\"input\")&&\"checkbox\"===this.type&&this.click?(this.click(),!1):t},_default:function(e){return x.nodeName(e.target,\"a\")}},beforeunload:{postDispatch:function(e){e.result!==t&&(e.originalEvent.returnValue=e.result)}}},simulate:function(e,t,n,r){var i=x.extend(new x.Event,n,{type:e,isSimulated:!0,originalEvent:{}});r?x.event.trigger(i,null,t):x.event.dispatch.call(t,i),i.isDefaultPrevented()&&n.preventDefault()}},x.removeEvent=a.removeEventListener?function(e,t,n){e.removeEventListener&&e.removeEventListener(t,n,!1)}:function(e,t,n){var r=\"on\"+t;e.detachEvent&&(typeof e[r]===i&&(e[r]=null),e.detachEvent(r,n))},x.Event=function(e,n){return this instanceof x.Event?(e&&e.type?(this.originalEvent=e,this.type=e.type,this.isDefaultPrevented=e.defaultPrevented||e.returnValue===!1||e.getPreventDefault&&e.getPreventDefault()?it:ot):this.type=e,n&&x.extend(this,n),this.timeStamp=e&&e.timeStamp||x.now(),this[x.expando]=!0,t):new x.Event(e,n)},x.Event.prototype={isDefaultPrevented:ot,isPropagationStopped:ot,isImmediatePropagationStopped:ot,preventDefault:function(){var e=this.originalEvent;this.isDefaultPrevented=it,e&&(e.preventDefault?e.preventDefault():e.returnValue=!1)},stopPropagation:function(){var e=this.originalEvent;this.isPropagationStopped=it,e&&(e.stopPropagation&&e.stopPropagation(),e.cancelBubble=!0)},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=it,this.stopPropagation()}},x.each({mouseenter:\"mouseover\",mouseleave:\"mouseout\"},function(e,t){x.event.special[e]={delegateType:t,bindType:t,handle:function(e){var n,r=this,i=e.relatedTarget,o=e.handleObj;return(!i||i!==r&&!x.contains(r,i))&&(e.type=o.origType,n=o.handler.apply(this,arguments),e.type=t),n}}}),x.support.submitBubbles||(x.event.special.submit={setup:function(){return x.nodeName(this,\"form\")?!1:(x.event.add(this,\"click._submit keypress._submit\",function(e){var n=e.target,r=x.nodeName(n,\"input\")||x.nodeName(n,\"button\")?n.form:t;r&&!x._data(r,\"submitBubbles\")&&(x.event.add(r,\"submit._submit\",function(e){e._submit_bubble=!0}),x._data(r,\"submitBubbles\",!0))}),t)},postDispatch:function(e){e._submit_bubble&&(delete e._submit_bubble,this.parentNode&&!e.isTrigger&&x.event.simulate(\"submit\",this.parentNode,e,!0))},teardown:function(){return x.nodeName(this,\"form\")?!1:(x.event.remove(this,\"._submit\"),t)}}),x.support.changeBubbles||(x.event.special.change={setup:function(){return Z.test(this.nodeName)?((\"checkbox\"===this.type||\"radio\"===this.type)&&(x.event.add(this,\"propertychange._change\",function(e){\"checked\"===e.originalEvent.propertyName&&(this._just_changed=!0)}),x.event.add(this,\"click._change\",function(e){this._just_changed&&!e.isTrigger&&(this._just_changed=!1),x.event.simulate(\"change\",this,e,!0)})),!1):(x.event.add(this,\"beforeactivate._change\",function(e){var t=e.target;Z.test(t.nodeName)&&!x._data(t,\"changeBubbles\")&&(x.event.add(t,\"change._change\",function(e){!this.parentNode||e.isSimulated||e.isTrigger||x.event.simulate(\"change\",this.parentNode,e,!0)}),x._data(t,\"changeBubbles\",!0))}),t)},handle:function(e){var n=e.target;return this!==n||e.isSimulated||e.isTrigger||\"radio\"!==n.type&&\"checkbox\"!==n.type?e.handleObj.handler.apply(this,arguments):t},teardown:function(){return x.event.remove(this,\"._change\"),!Z.test(this.nodeName)}}),x.support.focusinBubbles||x.each({focus:\"focusin\",blur:\"focusout\"},function(e,t){var n=0,r=function(e){x.event.simulate(t,e.target,x.event.fix(e),!0)};x.event.special[t]={setup:function(){0===n++&&a.addEventListener(e,r,!0)},teardown:function(){0===--n&&a.removeEventListener(e,r,!0)}}}),x.fn.extend({on:function(e,n,r,i,o){var a,s;if(\"object\"==typeof e){\"string\"!=typeof n&&(r=r||n,n=t);for(a in e)this.on(a,n,r,e[a],o);return this}if(null==r&&null==i?(i=n,r=n=t):null==i&&(\"string\"==typeof n?(i=r,r=t):(i=r,r=n,n=t)),i===!1)i=ot;else if(!i)return this;return 1===o&&(s=i,i=function(e){return x().off(e),s.apply(this,arguments)},i.guid=s.guid||(s.guid=x.guid++)),this.each(function(){x.event.add(this,e,i,r,n)})},one:function(e,t,n,r){return this.on(e,t,n,r,1)},off:function(e,n,r){var i,o;if(e&&e.preventDefault&&e.handleObj)return i=e.handleObj,x(e.delegateTarget).off(i.namespace?i.origType+\".\"+i.namespace:i.origType,i.selector,i.handler),this;if(\"object\"==typeof e){for(o in e)this.off(o,n,e[o]);return this}return(n===!1||\"function\"==typeof n)&&(r=n,n=t),r===!1&&(r=ot),this.each(function(){x.event.remove(this,e,r,n)})},trigger:function(e,t){return this.each(function(){x.event.trigger(e,t,this)})},triggerHandler:function(e,n){var r=this[0];return r?x.event.trigger(e,n,r,!0):t}});var st=/^.[^:#\\[\\.,]*$/,lt=/^(?:parents|prev(?:Until|All))/,ut=x.expr.match.needsContext,ct={children:!0,contents:!0,next:!0,prev:!0};x.fn.extend({find:function(e){var t,n=[],r=this,i=r.length;if(\"string\"!=typeof e)return this.pushStack(x(e).filter(function(){for(t=0;i>t;t++)if(x.contains(r[t],this))return!0}));for(t=0;i>t;t++)x.find(e,r[t],n);return n=this.pushStack(i>1?x.unique(n):n),n.selector=this.selector?this.selector+\" \"+e:e,n},has:function(e){var t,n=x(e,this),r=n.length;return this.filter(function(){for(t=0;r>t;t++)if(x.contains(this,n[t]))return!0})},not:function(e){return this.pushStack(ft(this,e||[],!0))},filter:function(e){return this.pushStack(ft(this,e||[],!1))},is:function(e){return!!ft(this,\"string\"==typeof e&&ut.test(e)?x(e):e||[],!1).length},closest:function(e,t){var n,r=0,i=this.length,o=[],a=ut.test(e)||\"string\"!=typeof e?x(e,t||this.context):0;for(;i>r;r++)for(n=this[r];n&&n!==t;n=n.parentNode)if(11>n.nodeType&&(a?a.index(n)>-1:1===n.nodeType&&x.find.matchesSelector(n,e))){n=o.push(n);break}return this.pushStack(o.length>1?x.unique(o):o)},index:function(e){return e?\"string\"==typeof e?x.inArray(this[0],x(e)):x.inArray(e.jquery?e[0]:e,this):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(e,t){var n=\"string\"==typeof e?x(e,t):x.makeArray(e&&e.nodeType?[e]:e),r=x.merge(this.get(),n);return this.pushStack(x.unique(r))},addBack:function(e){return this.add(null==e?this.prevObject:this.prevObject.filter(e))}});function pt(e,t){do e=e[t];while(e&&1!==e.nodeType);return e}x.each({parent:function(e){var t=e.parentNode;return t&&11!==t.nodeType?t:null},parents:function(e){return x.dir(e,\"parentNode\")},parentsUntil:function(e,t,n){return x.dir(e,\"parentNode\",n)},next:function(e){return pt(e,\"nextSibling\")},prev:function(e){return pt(e,\"previousSibling\")},nextAll:function(e){return x.dir(e,\"nextSibling\")},prevAll:function(e){return x.dir(e,\"previousSibling\")},nextUntil:function(e,t,n){return x.dir(e,\"nextSibling\",n)},prevUntil:function(e,t,n){return x.dir(e,\"previousSibling\",n)},siblings:function(e){return x.sibling((e.parentNode||{}).firstChild,e)},children:function(e){return x.sibling(e.firstChild)},contents:function(e){return x.nodeName(e,\"iframe\")?e.contentDocument||e.contentWindow.document:x.merge([],e.childNodes)}},function(e,t){x.fn[e]=function(n,r){var i=x.map(this,t,n);return\"Until\"!==e.slice(-5)&&(r=n),r&&\"string\"==typeof r&&(i=x.filter(r,i)),this.length>1&&(ct[e]||(i=x.unique(i)),lt.test(e)&&(i=i.reverse())),this.pushStack(i)}}),x.extend({filter:function(e,t,n){var r=t[0];return n&&(e=\":not(\"+e+\")\"),1===t.length&&1===r.nodeType?x.find.matchesSelector(r,e)?[r]:[]:x.find.matches(e,x.grep(t,function(e){return 1===e.nodeType}))},dir:function(e,n,r){var i=[],o=e[n];while(o&&9!==o.nodeType&&(r===t||1!==o.nodeType||!x(o).is(r)))1===o.nodeType&&i.push(o),o=o[n];return i},sibling:function(e,t){var n=[];for(;e;e=e.nextSibling)1===e.nodeType&&e!==t&&n.push(e);return n}});function ft(e,t,n){if(x.isFunction(t))return x.grep(e,function(e,r){return!!t.call(e,r,e)!==n});if(t.nodeType)return x.grep(e,function(e){return e===t!==n});if(\"string\"==typeof t){if(st.test(t))return x.filter(t,e,n);t=x.filter(t,e)}return x.grep(e,function(e){return x.inArray(e,t)>=0!==n})}function dt(e){var t=ht.split(\"|\"),n=e.createDocumentFragment();if(n.createElement)while(t.length)n.createElement(t.pop());return n}var ht=\"abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video\",gt=/ jQuery\\d+=\"(?:null|\\d+)\"/g,mt=RegExp(\"<(?:\"+ht+\")[\\\\s/>]\",\"i\"),yt=/^\\s+/,vt=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\\w:]+)[^>]*)\\/>/gi,bt=/<([\\w:]+)/,xt=/<tbody/i,wt=/<|&#?\\w+;/,Tt=/<(?:script|style|link)/i,Ct=/^(?:checkbox|radio)$/i,Nt=/checked\\s*(?:[^=]|=\\s*.checked.)/i,kt=/^$|\\/(?:java|ecma)script/i,Et=/^true\\/(.*)/,St=/^\\s*<!(?:\\[CDATA\\[|--)|(?:\\]\\]|--)>\\s*$/g,At={option:[1,\"<select multiple='multiple'>\",\"</select>\"],legend:[1,\"<fieldset>\",\"</fieldset>\"],area:[1,\"<map>\",\"</map>\"],param:[1,\"<object>\",\"</object>\"],thead:[1,\"<table>\",\"</table>\"],tr:[2,\"<table><tbody>\",\"</tbody></table>\"],col:[2,\"<table><tbody></tbody><colgroup>\",\"</colgroup></table>\"],td:[3,\"<table><tbody><tr>\",\"</tr></tbody></table>\"],_default:x.support.htmlSerialize?[0,\"\",\"\"]:[1,\"X<div>\",\"</div>\"]},jt=dt(a),Dt=jt.appendChild(a.createElement(\"div\"));At.optgroup=At.option,At.tbody=At.tfoot=At.colgroup=At.caption=At.thead,At.th=At.td,x.fn.extend({text:function(e){return x.access(this,function(e){return e===t?x.text(this):this.empty().append((this[0]&&this[0].ownerDocument||a).createTextNode(e))},null,e,arguments.length)},append:function(){return this.domManip(arguments,function(e){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var t=Lt(this,e);t.appendChild(e)}})},prepend:function(){return this.domManip(arguments,function(e){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var t=Lt(this,e);t.insertBefore(e,t.firstChild)}})},before:function(){return this.domManip(arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this)})},after:function(){return this.domManip(arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this.nextSibling)})},remove:function(e,t){var n,r=e?x.filter(e,this):this,i=0;for(;null!=(n=r[i]);i++)t||1!==n.nodeType||x.cleanData(Ft(n)),n.parentNode&&(t&&x.contains(n.ownerDocument,n)&&_t(Ft(n,\"script\")),n.parentNode.removeChild(n));return this},empty:function(){var e,t=0;for(;null!=(e=this[t]);t++){1===e.nodeType&&x.cleanData(Ft(e,!1));while(e.firstChild)e.removeChild(e.firstChild);e.options&&x.nodeName(e,\"select\")&&(e.options.length=0)}return this},clone:function(e,t){return e=null==e?!1:e,t=null==t?e:t,this.map(function(){return x.clone(this,e,t)})},html:function(e){return x.access(this,function(e){var n=this[0]||{},r=0,i=this.length;if(e===t)return 1===n.nodeType?n.innerHTML.replace(gt,\"\"):t;if(!(\"string\"!=typeof e||Tt.test(e)||!x.support.htmlSerialize&&mt.test(e)||!x.support.leadingWhitespace&&yt.test(e)||At[(bt.exec(e)||[\"\",\"\"])[1].toLowerCase()])){e=e.replace(vt,\"<$1></$2>\");try{for(;i>r;r++)n=this[r]||{},1===n.nodeType&&(x.cleanData(Ft(n,!1)),n.innerHTML=e);n=0}catch(o){}}n&&this.empty().append(e)},null,e,arguments.length)},replaceWith:function(){var e=x.map(this,function(e){return[e.nextSibling,e.parentNode]}),t=0;return this.domManip(arguments,function(n){var r=e[t++],i=e[t++];i&&(r&&r.parentNode!==i&&(r=this.nextSibling),x(this).remove(),i.insertBefore(n,r))},!0),t?this:this.remove()},detach:function(e){return this.remove(e,!0)},domManip:function(e,t,n){e=d.apply([],e);var r,i,o,a,s,l,u=0,c=this.length,p=this,f=c-1,h=e[0],g=x.isFunction(h);if(g||!(1>=c||\"string\"!=typeof h||x.support.checkClone)&&Nt.test(h))return this.each(function(r){var i=p.eq(r);g&&(e[0]=h.call(this,r,i.html())),i.domManip(e,t,n)});if(c&&(l=x.buildFragment(e,this[0].ownerDocument,!1,!n&&this),r=l.firstChild,1===l.childNodes.length&&(l=r),r)){for(a=x.map(Ft(l,\"script\"),Ht),o=a.length;c>u;u++)i=l,u!==f&&(i=x.clone(i,!0,!0),o&&x.merge(a,Ft(i,\"script\"))),t.call(this[u],i,u);if(o)for(s=a[a.length-1].ownerDocument,x.map(a,qt),u=0;o>u;u++)i=a[u],kt.test(i.type||\"\")&&!x._data(i,\"globalEval\")&&x.contains(s,i)&&(i.src?x._evalUrl(i.src):x.globalEval((i.text||i.textContent||i.innerHTML||\"\").replace(St,\"\")));l=r=null}return this}});function Lt(e,t){return x.nodeName(e,\"table\")&&x.nodeName(1===t.nodeType?t:t.firstChild,\"tr\")?e.getElementsByTagName(\"tbody\")[0]||e.appendChild(e.ownerDocument.createElement(\"tbody\")):e}function Ht(e){return e.type=(null!==x.find.attr(e,\"type\"))+\"/\"+e.type,e}function qt(e){var t=Et.exec(e.type);return t?e.type=t[1]:e.removeAttribute(\"type\"),e}function _t(e,t){var n,r=0;for(;null!=(n=e[r]);r++)x._data(n,\"globalEval\",!t||x._data(t[r],\"globalEval\"))}function Mt(e,t){if(1===t.nodeType&&x.hasData(e)){var n,r,i,o=x._data(e),a=x._data(t,o),s=o.events;if(s){delete a.handle,a.events={};for(n in s)for(r=0,i=s[n].length;i>r;r++)x.event.add(t,n,s[n][r])}a.data&&(a.data=x.extend({},a.data))}}function Ot(e,t){var n,r,i;if(1===t.nodeType){if(n=t.nodeName.toLowerCase(),!x.support.noCloneEvent&&t[x.expando]){i=x._data(t);for(r in i.events)x.removeEvent(t,r,i.handle);t.removeAttribute(x.expando)}\"script\"===n&&t.text!==e.text?(Ht(t).text=e.text,qt(t)):\"object\"===n?(t.parentNode&&(t.outerHTML=e.outerHTML),x.support.html5Clone&&e.innerHTML&&!x.trim(t.innerHTML)&&(t.innerHTML=e.innerHTML)):\"input\"===n&&Ct.test(e.type)?(t.defaultChecked=t.checked=e.checked,t.value!==e.value&&(t.value=e.value)):\"option\"===n?t.defaultSelected=t.selected=e.defaultSelected:(\"input\"===n||\"textarea\"===n)&&(t.defaultValue=e.defaultValue)}}x.each({appendTo:\"append\",prependTo:\"prepend\",insertBefore:\"before\",insertAfter:\"after\",replaceAll:\"replaceWith\"},function(e,t){x.fn[e]=function(e){var n,r=0,i=[],o=x(e),a=o.length-1;for(;a>=r;r++)n=r===a?this:this.clone(!0),x(o[r])[t](n),h.apply(i,n.get());return this.pushStack(i)}});function Ft(e,n){var r,o,a=0,s=typeof e.getElementsByTagName!==i?e.getElementsByTagName(n||\"*\"):typeof e.querySelectorAll!==i?e.querySelectorAll(n||\"*\"):t;if(!s)for(s=[],r=e.childNodes||e;null!=(o=r[a]);a++)!n||x.nodeName(o,n)?s.push(o):x.merge(s,Ft(o,n));return n===t||n&&x.nodeName(e,n)?x.merge([e],s):s}function Bt(e){Ct.test(e.type)&&(e.defaultChecked=e.checked)}x.extend({clone:function(e,t,n){var r,i,o,a,s,l=x.contains(e.ownerDocument,e);if(x.support.html5Clone||x.isXMLDoc(e)||!mt.test(\"<\"+e.nodeName+\">\")?o=e.cloneNode(!0):(Dt.innerHTML=e.outerHTML,Dt.removeChild(o=Dt.firstChild)),!(x.support.noCloneEvent&&x.support.noCloneChecked||1!==e.nodeType&&11!==e.nodeType||x.isXMLDoc(e)))for(r=Ft(o),s=Ft(e),a=0;null!=(i=s[a]);++a)r[a]&&Ot(i,r[a]);if(t)if(n)for(s=s||Ft(e),r=r||Ft(o),a=0;null!=(i=s[a]);a++)Mt(i,r[a]);else Mt(e,o);return r=Ft(o,\"script\"),r.length>0&&_t(r,!l&&Ft(e,\"script\")),r=s=i=null,o},buildFragment:function(e,t,n,r){var i,o,a,s,l,u,c,p=e.length,f=dt(t),d=[],h=0;for(;p>h;h++)if(o=e[h],o||0===o)if(\"object\"===x.type(o))x.merge(d,o.nodeType?[o]:o);else if(wt.test(o)){s=s||f.appendChild(t.createElement(\"div\")),l=(bt.exec(o)||[\"\",\"\"])[1].toLowerCase(),c=At[l]||At._default,s.innerHTML=c[1]+o.replace(vt,\"<$1></$2>\")+c[2],i=c[0];while(i--)s=s.lastChild;if(!x.support.leadingWhitespace&&yt.test(o)&&d.push(t.createTextNode(yt.exec(o)[0])),!x.support.tbody){o=\"table\"!==l||xt.test(o)?\"<table>\"!==c[1]||xt.test(o)?0:s:s.firstChild,i=o&&o.childNodes.length;while(i--)x.nodeName(u=o.childNodes[i],\"tbody\")&&!u.childNodes.length&&o.removeChild(u)}x.merge(d,s.childNodes),s.textContent=\"\";while(s.firstChild)s.removeChild(s.firstChild);s=f.lastChild}else d.push(t.createTextNode(o));s&&f.removeChild(s),x.support.appendChecked||x.grep(Ft(d,\"input\"),Bt),h=0;while(o=d[h++])if((!r||-1===x.inArray(o,r))&&(a=x.contains(o.ownerDocument,o),s=Ft(f.appendChild(o),\"script\"),a&&_t(s),n)){i=0;while(o=s[i++])kt.test(o.type||\"\")&&n.push(o)}return s=null,f},cleanData:function(e,t){var n,r,o,a,s=0,l=x.expando,u=x.cache,c=x.support.deleteExpando,f=x.event.special;for(;null!=(n=e[s]);s++)if((t||x.acceptData(n))&&(o=n[l],a=o&&u[o])){if(a.events)for(r in a.events)f[r]?x.event.remove(n,r):x.removeEvent(n,r,a.handle);\nu[o]&&(delete u[o],c?delete n[l]:typeof n.removeAttribute!==i?n.removeAttribute(l):n[l]=null,p.push(o))}},_evalUrl:function(e){return x.ajax({url:e,type:\"GET\",dataType:\"script\",async:!1,global:!1,\"throws\":!0})}}),x.fn.extend({wrapAll:function(e){if(x.isFunction(e))return this.each(function(t){x(this).wrapAll(e.call(this,t))});if(this[0]){var t=x(e,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&t.insertBefore(this[0]),t.map(function(){var e=this;while(e.firstChild&&1===e.firstChild.nodeType)e=e.firstChild;return e}).append(this)}return this},wrapInner:function(e){return x.isFunction(e)?this.each(function(t){x(this).wrapInner(e.call(this,t))}):this.each(function(){var t=x(this),n=t.contents();n.length?n.wrapAll(e):t.append(e)})},wrap:function(e){var t=x.isFunction(e);return this.each(function(n){x(this).wrapAll(t?e.call(this,n):e)})},unwrap:function(){return this.parent().each(function(){x.nodeName(this,\"body\")||x(this).replaceWith(this.childNodes)}).end()}});var Pt,Rt,Wt,$t=/alpha\\([^)]*\\)/i,It=/opacity\\s*=\\s*([^)]*)/,zt=/^(top|right|bottom|left)$/,Xt=/^(none|table(?!-c[ea]).+)/,Ut=/^margin/,Vt=RegExp(\"^(\"+w+\")(.*)$\",\"i\"),Yt=RegExp(\"^(\"+w+\")(?!px)[a-z%]+$\",\"i\"),Jt=RegExp(\"^([+-])=(\"+w+\")\",\"i\"),Gt={BODY:\"block\"},Qt={position:\"absolute\",visibility:\"hidden\",display:\"block\"},Kt={letterSpacing:0,fontWeight:400},Zt=[\"Top\",\"Right\",\"Bottom\",\"Left\"],en=[\"Webkit\",\"O\",\"Moz\",\"ms\"];function tn(e,t){if(t in e)return t;var n=t.charAt(0).toUpperCase()+t.slice(1),r=t,i=en.length;while(i--)if(t=en[i]+n,t in e)return t;return r}function nn(e,t){return e=t||e,\"none\"===x.css(e,\"display\")||!x.contains(e.ownerDocument,e)}function rn(e,t){var n,r,i,o=[],a=0,s=e.length;for(;s>a;a++)r=e[a],r.style&&(o[a]=x._data(r,\"olddisplay\"),n=r.style.display,t?(o[a]||\"none\"!==n||(r.style.display=\"\"),\"\"===r.style.display&&nn(r)&&(o[a]=x._data(r,\"olddisplay\",ln(r.nodeName)))):o[a]||(i=nn(r),(n&&\"none\"!==n||!i)&&x._data(r,\"olddisplay\",i?n:x.css(r,\"display\"))));for(a=0;s>a;a++)r=e[a],r.style&&(t&&\"none\"!==r.style.display&&\"\"!==r.style.display||(r.style.display=t?o[a]||\"\":\"none\"));return e}x.fn.extend({css:function(e,n){return x.access(this,function(e,n,r){var i,o,a={},s=0;if(x.isArray(n)){for(o=Rt(e),i=n.length;i>s;s++)a[n[s]]=x.css(e,n[s],!1,o);return a}return r!==t?x.style(e,n,r):x.css(e,n)},e,n,arguments.length>1)},show:function(){return rn(this,!0)},hide:function(){return rn(this)},toggle:function(e){return\"boolean\"==typeof e?e?this.show():this.hide():this.each(function(){nn(this)?x(this).show():x(this).hide()})}}),x.extend({cssHooks:{opacity:{get:function(e,t){if(t){var n=Wt(e,\"opacity\");return\"\"===n?\"1\":n}}}},cssNumber:{columnCount:!0,fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{\"float\":x.support.cssFloat?\"cssFloat\":\"styleFloat\"},style:function(e,n,r,i){if(e&&3!==e.nodeType&&8!==e.nodeType&&e.style){var o,a,s,l=x.camelCase(n),u=e.style;if(n=x.cssProps[l]||(x.cssProps[l]=tn(u,l)),s=x.cssHooks[n]||x.cssHooks[l],r===t)return s&&\"get\"in s&&(o=s.get(e,!1,i))!==t?o:u[n];if(a=typeof r,\"string\"===a&&(o=Jt.exec(r))&&(r=(o[1]+1)*o[2]+parseFloat(x.css(e,n)),a=\"number\"),!(null==r||\"number\"===a&&isNaN(r)||(\"number\"!==a||x.cssNumber[l]||(r+=\"px\"),x.support.clearCloneStyle||\"\"!==r||0!==n.indexOf(\"background\")||(u[n]=\"inherit\"),s&&\"set\"in s&&(r=s.set(e,r,i))===t)))try{u[n]=r}catch(c){}}},css:function(e,n,r,i){var o,a,s,l=x.camelCase(n);return n=x.cssProps[l]||(x.cssProps[l]=tn(e.style,l)),s=x.cssHooks[n]||x.cssHooks[l],s&&\"get\"in s&&(a=s.get(e,!0,r)),a===t&&(a=Wt(e,n,i)),\"normal\"===a&&n in Kt&&(a=Kt[n]),\"\"===r||r?(o=parseFloat(a),r===!0||x.isNumeric(o)?o||0:a):a}}),e.getComputedStyle?(Rt=function(t){return e.getComputedStyle(t,null)},Wt=function(e,n,r){var i,o,a,s=r||Rt(e),l=s?s.getPropertyValue(n)||s[n]:t,u=e.style;return s&&(\"\"!==l||x.contains(e.ownerDocument,e)||(l=x.style(e,n)),Yt.test(l)&&Ut.test(n)&&(i=u.width,o=u.minWidth,a=u.maxWidth,u.minWidth=u.maxWidth=u.width=l,l=s.width,u.width=i,u.minWidth=o,u.maxWidth=a)),l}):a.documentElement.currentStyle&&(Rt=function(e){return e.currentStyle},Wt=function(e,n,r){var i,o,a,s=r||Rt(e),l=s?s[n]:t,u=e.style;return null==l&&u&&u[n]&&(l=u[n]),Yt.test(l)&&!zt.test(n)&&(i=u.left,o=e.runtimeStyle,a=o&&o.left,a&&(o.left=e.currentStyle.left),u.left=\"fontSize\"===n?\"1em\":l,l=u.pixelLeft+\"px\",u.left=i,a&&(o.left=a)),\"\"===l?\"auto\":l});function on(e,t,n){var r=Vt.exec(t);return r?Math.max(0,r[1]-(n||0))+(r[2]||\"px\"):t}function an(e,t,n,r,i){var o=n===(r?\"border\":\"content\")?4:\"width\"===t?1:0,a=0;for(;4>o;o+=2)\"margin\"===n&&(a+=x.css(e,n+Zt[o],!0,i)),r?(\"content\"===n&&(a-=x.css(e,\"padding\"+Zt[o],!0,i)),\"margin\"!==n&&(a-=x.css(e,\"border\"+Zt[o]+\"Width\",!0,i))):(a+=x.css(e,\"padding\"+Zt[o],!0,i),\"padding\"!==n&&(a+=x.css(e,\"border\"+Zt[o]+\"Width\",!0,i)));return a}function sn(e,t,n){var r=!0,i=\"width\"===t?e.offsetWidth:e.offsetHeight,o=Rt(e),a=x.support.boxSizing&&\"border-box\"===x.css(e,\"boxSizing\",!1,o);if(0>=i||null==i){if(i=Wt(e,t,o),(0>i||null==i)&&(i=e.style[t]),Yt.test(i))return i;r=a&&(x.support.boxSizingReliable||i===e.style[t]),i=parseFloat(i)||0}return i+an(e,t,n||(a?\"border\":\"content\"),r,o)+\"px\"}function ln(e){var t=a,n=Gt[e];return n||(n=un(e,t),\"none\"!==n&&n||(Pt=(Pt||x(\"<iframe frameborder='0' width='0' height='0'/>\").css(\"cssText\",\"display:block !important\")).appendTo(t.documentElement),t=(Pt[0].contentWindow||Pt[0].contentDocument).document,t.write(\"<!doctype html><html><body>\"),t.close(),n=un(e,t),Pt.detach()),Gt[e]=n),n}function un(e,t){var n=x(t.createElement(e)).appendTo(t.body),r=x.css(n[0],\"display\");return n.remove(),r}x.each([\"height\",\"width\"],function(e,n){x.cssHooks[n]={get:function(e,r,i){return r?0===e.offsetWidth&&Xt.test(x.css(e,\"display\"))?x.swap(e,Qt,function(){return sn(e,n,i)}):sn(e,n,i):t},set:function(e,t,r){var i=r&&Rt(e);return on(e,t,r?an(e,n,r,x.support.boxSizing&&\"border-box\"===x.css(e,\"boxSizing\",!1,i),i):0)}}}),x.support.opacity||(x.cssHooks.opacity={get:function(e,t){return It.test((t&&e.currentStyle?e.currentStyle.filter:e.style.filter)||\"\")?.01*parseFloat(RegExp.$1)+\"\":t?\"1\":\"\"},set:function(e,t){var n=e.style,r=e.currentStyle,i=x.isNumeric(t)?\"alpha(opacity=\"+100*t+\")\":\"\",o=r&&r.filter||n.filter||\"\";n.zoom=1,(t>=1||\"\"===t)&&\"\"===x.trim(o.replace($t,\"\"))&&n.removeAttribute&&(n.removeAttribute(\"filter\"),\"\"===t||r&&!r.filter)||(n.filter=$t.test(o)?o.replace($t,i):o+\" \"+i)}}),x(function(){x.support.reliableMarginRight||(x.cssHooks.marginRight={get:function(e,n){return n?x.swap(e,{display:\"inline-block\"},Wt,[e,\"marginRight\"]):t}}),!x.support.pixelPosition&&x.fn.position&&x.each([\"top\",\"left\"],function(e,n){x.cssHooks[n]={get:function(e,r){return r?(r=Wt(e,n),Yt.test(r)?x(e).position()[n]+\"px\":r):t}}})}),x.expr&&x.expr.filters&&(x.expr.filters.hidden=function(e){return 0>=e.offsetWidth&&0>=e.offsetHeight||!x.support.reliableHiddenOffsets&&\"none\"===(e.style&&e.style.display||x.css(e,\"display\"))},x.expr.filters.visible=function(e){return!x.expr.filters.hidden(e)}),x.each({margin:\"\",padding:\"\",border:\"Width\"},function(e,t){x.cssHooks[e+t]={expand:function(n){var r=0,i={},o=\"string\"==typeof n?n.split(\" \"):[n];for(;4>r;r++)i[e+Zt[r]+t]=o[r]||o[r-2]||o[0];return i}},Ut.test(e)||(x.cssHooks[e+t].set=on)});var cn=/%20/g,pn=/\\[\\]$/,fn=/\\r?\\n/g,dn=/^(?:submit|button|image|reset|file)$/i,hn=/^(?:input|select|textarea|keygen)/i;x.fn.extend({serialize:function(){return x.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var e=x.prop(this,\"elements\");return e?x.makeArray(e):this}).filter(function(){var e=this.type;return this.name&&!x(this).is(\":disabled\")&&hn.test(this.nodeName)&&!dn.test(e)&&(this.checked||!Ct.test(e))}).map(function(e,t){var n=x(this).val();return null==n?null:x.isArray(n)?x.map(n,function(e){return{name:t.name,value:e.replace(fn,\"\\r\\n\")}}):{name:t.name,value:n.replace(fn,\"\\r\\n\")}}).get()}}),x.param=function(e,n){var r,i=[],o=function(e,t){t=x.isFunction(t)?t():null==t?\"\":t,i[i.length]=encodeURIComponent(e)+\"=\"+encodeURIComponent(t)};if(n===t&&(n=x.ajaxSettings&&x.ajaxSettings.traditional),x.isArray(e)||e.jquery&&!x.isPlainObject(e))x.each(e,function(){o(this.name,this.value)});else for(r in e)gn(r,e[r],n,o);return i.join(\"&\").replace(cn,\"+\")};function gn(e,t,n,r){var i;if(x.isArray(t))x.each(t,function(t,i){n||pn.test(e)?r(e,i):gn(e+\"[\"+(\"object\"==typeof i?t:\"\")+\"]\",i,n,r)});else if(n||\"object\"!==x.type(t))r(e,t);else for(i in t)gn(e+\"[\"+i+\"]\",t[i],n,r)}x.each(\"blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error contextmenu\".split(\" \"),function(e,t){x.fn[t]=function(e,n){return arguments.length>0?this.on(t,null,e,n):this.trigger(t)}}),x.fn.extend({hover:function(e,t){return this.mouseenter(e).mouseleave(t||e)},bind:function(e,t,n){return this.on(e,null,t,n)},unbind:function(e,t){return this.off(e,null,t)},delegate:function(e,t,n,r){return this.on(t,e,n,r)},undelegate:function(e,t,n){return 1===arguments.length?this.off(e,\"**\"):this.off(t,e||\"**\",n)}});var mn,yn,vn=x.now(),bn=/\\?/,xn=/#.*$/,wn=/([?&])_=[^&]*/,Tn=/^(.*?):[ \\t]*([^\\r\\n]*)\\r?$/gm,Cn=/^(?:about|app|app-storage|.+-extension|file|res|widget):$/,Nn=/^(?:GET|HEAD)$/,kn=/^\\/\\//,En=/^([\\w.+-]+:)(?:\\/\\/([^\\/?#:]*)(?::(\\d+)|)|)/,Sn=x.fn.load,An={},jn={},Dn=\"*/\".concat(\"*\");try{yn=o.href}catch(Ln){yn=a.createElement(\"a\"),yn.href=\"\",yn=yn.href}mn=En.exec(yn.toLowerCase())||[];function Hn(e){return function(t,n){\"string\"!=typeof t&&(n=t,t=\"*\");var r,i=0,o=t.toLowerCase().match(T)||[];if(x.isFunction(n))while(r=o[i++])\"+\"===r[0]?(r=r.slice(1)||\"*\",(e[r]=e[r]||[]).unshift(n)):(e[r]=e[r]||[]).push(n)}}function qn(e,n,r,i){var o={},a=e===jn;function s(l){var u;return o[l]=!0,x.each(e[l]||[],function(e,l){var c=l(n,r,i);return\"string\"!=typeof c||a||o[c]?a?!(u=c):t:(n.dataTypes.unshift(c),s(c),!1)}),u}return s(n.dataTypes[0])||!o[\"*\"]&&s(\"*\")}function _n(e,n){var r,i,o=x.ajaxSettings.flatOptions||{};for(i in n)n[i]!==t&&((o[i]?e:r||(r={}))[i]=n[i]);return r&&x.extend(!0,e,r),e}x.fn.load=function(e,n,r){if(\"string\"!=typeof e&&Sn)return Sn.apply(this,arguments);var i,o,a,s=this,l=e.indexOf(\" \");return l>=0&&(i=e.slice(l,e.length),e=e.slice(0,l)),x.isFunction(n)?(r=n,n=t):n&&\"object\"==typeof n&&(a=\"POST\"),s.length>0&&x.ajax({url:e,type:a,dataType:\"html\",data:n}).done(function(e){o=arguments,s.html(i?x(\"<div>\").append(x.parseHTML(e)).find(i):e)}).complete(r&&function(e,t){s.each(r,o||[e.responseText,t,e])}),this},x.each([\"ajaxStart\",\"ajaxStop\",\"ajaxComplete\",\"ajaxError\",\"ajaxSuccess\",\"ajaxSend\"],function(e,t){x.fn[t]=function(e){return this.on(t,e)}}),x.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:yn,type:\"GET\",isLocal:Cn.test(mn[1]),global:!0,processData:!0,async:!0,contentType:\"application/x-www-form-urlencoded; charset=UTF-8\",accepts:{\"*\":Dn,text:\"text/plain\",html:\"text/html\",xml:\"application/xml, text/xml\",json:\"application/json, text/javascript\"},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:\"responseXML\",text:\"responseText\",json:\"responseJSON\"},converters:{\"* text\":String,\"text html\":!0,\"text json\":x.parseJSON,\"text xml\":x.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(e,t){return t?_n(_n(e,x.ajaxSettings),t):_n(x.ajaxSettings,e)},ajaxPrefilter:Hn(An),ajaxTransport:Hn(jn),ajax:function(e,n){\"object\"==typeof e&&(n=e,e=t),n=n||{};var r,i,o,a,s,l,u,c,p=x.ajaxSetup({},n),f=p.context||p,d=p.context&&(f.nodeType||f.jquery)?x(f):x.event,h=x.Deferred(),g=x.Callbacks(\"once memory\"),m=p.statusCode||{},y={},v={},b=0,w=\"canceled\",C={readyState:0,getResponseHeader:function(e){var t;if(2===b){if(!c){c={};while(t=Tn.exec(a))c[t[1].toLowerCase()]=t[2]}t=c[e.toLowerCase()]}return null==t?null:t},getAllResponseHeaders:function(){return 2===b?a:null},setRequestHeader:function(e,t){var n=e.toLowerCase();return b||(e=v[n]=v[n]||e,y[e]=t),this},overrideMimeType:function(e){return b||(p.mimeType=e),this},statusCode:function(e){var t;if(e)if(2>b)for(t in e)m[t]=[m[t],e[t]];else C.always(e[C.status]);return this},abort:function(e){var t=e||w;return u&&u.abort(t),k(0,t),this}};if(h.promise(C).complete=g.add,C.success=C.done,C.error=C.fail,p.url=((e||p.url||yn)+\"\").replace(xn,\"\").replace(kn,mn[1]+\"//\"),p.type=n.method||n.type||p.method||p.type,p.dataTypes=x.trim(p.dataType||\"*\").toLowerCase().match(T)||[\"\"],null==p.crossDomain&&(r=En.exec(p.url.toLowerCase()),p.crossDomain=!(!r||r[1]===mn[1]&&r[2]===mn[2]&&(r[3]||(\"http:\"===r[1]?\"80\":\"443\"))===(mn[3]||(\"http:\"===mn[1]?\"80\":\"443\")))),p.data&&p.processData&&\"string\"!=typeof p.data&&(p.data=x.param(p.data,p.traditional)),qn(An,p,n,C),2===b)return C;l=p.global,l&&0===x.active++&&x.event.trigger(\"ajaxStart\"),p.type=p.type.toUpperCase(),p.hasContent=!Nn.test(p.type),o=p.url,p.hasContent||(p.data&&(o=p.url+=(bn.test(o)?\"&\":\"?\")+p.data,delete p.data),p.cache===!1&&(p.url=wn.test(o)?o.replace(wn,\"$1_=\"+vn++):o+(bn.test(o)?\"&\":\"?\")+\"_=\"+vn++)),p.ifModified&&(x.lastModified[o]&&C.setRequestHeader(\"If-Modified-Since\",x.lastModified[o]),x.etag[o]&&C.setRequestHeader(\"If-None-Match\",x.etag[o])),(p.data&&p.hasContent&&p.contentType!==!1||n.contentType)&&C.setRequestHeader(\"Content-Type\",p.contentType),C.setRequestHeader(\"Accept\",p.dataTypes[0]&&p.accepts[p.dataTypes[0]]?p.accepts[p.dataTypes[0]]+(\"*\"!==p.dataTypes[0]?\", \"+Dn+\"; q=0.01\":\"\"):p.accepts[\"*\"]);for(i in p.headers)C.setRequestHeader(i,p.headers[i]);if(p.beforeSend&&(p.beforeSend.call(f,C,p)===!1||2===b))return C.abort();w=\"abort\";for(i in{success:1,error:1,complete:1})C[i](p[i]);if(u=qn(jn,p,n,C)){C.readyState=1,l&&d.trigger(\"ajaxSend\",[C,p]),p.async&&p.timeout>0&&(s=setTimeout(function(){C.abort(\"timeout\")},p.timeout));try{b=1,u.send(y,k)}catch(N){if(!(2>b))throw N;k(-1,N)}}else k(-1,\"No Transport\");function k(e,n,r,i){var c,y,v,w,T,N=n;2!==b&&(b=2,s&&clearTimeout(s),u=t,a=i||\"\",C.readyState=e>0?4:0,c=e>=200&&300>e||304===e,r&&(w=Mn(p,C,r)),w=On(p,w,C,c),c?(p.ifModified&&(T=C.getResponseHeader(\"Last-Modified\"),T&&(x.lastModified[o]=T),T=C.getResponseHeader(\"etag\"),T&&(x.etag[o]=T)),204===e||\"HEAD\"===p.type?N=\"nocontent\":304===e?N=\"notmodified\":(N=w.state,y=w.data,v=w.error,c=!v)):(v=N,(e||!N)&&(N=\"error\",0>e&&(e=0))),C.status=e,C.statusText=(n||N)+\"\",c?h.resolveWith(f,[y,N,C]):h.rejectWith(f,[C,N,v]),C.statusCode(m),m=t,l&&d.trigger(c?\"ajaxSuccess\":\"ajaxError\",[C,p,c?y:v]),g.fireWith(f,[C,N]),l&&(d.trigger(\"ajaxComplete\",[C,p]),--x.active||x.event.trigger(\"ajaxStop\")))}return C},getJSON:function(e,t,n){return x.get(e,t,n,\"json\")},getScript:function(e,n){return x.get(e,t,n,\"script\")}}),x.each([\"get\",\"post\"],function(e,n){x[n]=function(e,r,i,o){return x.isFunction(r)&&(o=o||i,i=r,r=t),x.ajax({url:e,type:n,dataType:o,data:r,success:i})}});function Mn(e,n,r){var i,o,a,s,l=e.contents,u=e.dataTypes;while(\"*\"===u[0])u.shift(),o===t&&(o=e.mimeType||n.getResponseHeader(\"Content-Type\"));if(o)for(s in l)if(l[s]&&l[s].test(o)){u.unshift(s);break}if(u[0]in r)a=u[0];else{for(s in r){if(!u[0]||e.converters[s+\" \"+u[0]]){a=s;break}i||(i=s)}a=a||i}return a?(a!==u[0]&&u.unshift(a),r[a]):t}function On(e,t,n,r){var i,o,a,s,l,u={},c=e.dataTypes.slice();if(c[1])for(a in e.converters)u[a.toLowerCase()]=e.converters[a];o=c.shift();while(o)if(e.responseFields[o]&&(n[e.responseFields[o]]=t),!l&&r&&e.dataFilter&&(t=e.dataFilter(t,e.dataType)),l=o,o=c.shift())if(\"*\"===o)o=l;else if(\"*\"!==l&&l!==o){if(a=u[l+\" \"+o]||u[\"* \"+o],!a)for(i in u)if(s=i.split(\" \"),s[1]===o&&(a=u[l+\" \"+s[0]]||u[\"* \"+s[0]])){a===!0?a=u[i]:u[i]!==!0&&(o=s[0],c.unshift(s[1]));break}if(a!==!0)if(a&&e[\"throws\"])t=a(t);else try{t=a(t)}catch(p){return{state:\"parsererror\",error:a?p:\"No conversion from \"+l+\" to \"+o}}}return{state:\"success\",data:t}}x.ajaxSetup({accepts:{script:\"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript\"},contents:{script:/(?:java|ecma)script/},converters:{\"text script\":function(e){return x.globalEval(e),e}}}),x.ajaxPrefilter(\"script\",function(e){e.cache===t&&(e.cache=!1),e.crossDomain&&(e.type=\"GET\",e.global=!1)}),x.ajaxTransport(\"script\",function(e){if(e.crossDomain){var n,r=a.head||x(\"head\")[0]||a.documentElement;return{send:function(t,i){n=a.createElement(\"script\"),n.async=!0,e.scriptCharset&&(n.charset=e.scriptCharset),n.src=e.url,n.onload=n.onreadystatechange=function(e,t){(t||!n.readyState||/loaded|complete/.test(n.readyState))&&(n.onload=n.onreadystatechange=null,n.parentNode&&n.parentNode.removeChild(n),n=null,t||i(200,\"success\"))},r.insertBefore(n,r.firstChild)},abort:function(){n&&n.onload(t,!0)}}}});var Fn=[],Bn=/(=)\\?(?=&|$)|\\?\\?/;x.ajaxSetup({jsonp:\"callback\",jsonpCallback:function(){var e=Fn.pop()||x.expando+\"_\"+vn++;return this[e]=!0,e}}),x.ajaxPrefilter(\"json jsonp\",function(n,r,i){var o,a,s,l=n.jsonp!==!1&&(Bn.test(n.url)?\"url\":\"string\"==typeof n.data&&!(n.contentType||\"\").indexOf(\"application/x-www-form-urlencoded\")&&Bn.test(n.data)&&\"data\");return l||\"jsonp\"===n.dataTypes[0]?(o=n.jsonpCallback=x.isFunction(n.jsonpCallback)?n.jsonpCallback():n.jsonpCallback,l?n[l]=n[l].replace(Bn,\"$1\"+o):n.jsonp!==!1&&(n.url+=(bn.test(n.url)?\"&\":\"?\")+n.jsonp+\"=\"+o),n.converters[\"script json\"]=function(){return s||x.error(o+\" was not called\"),s[0]},n.dataTypes[0]=\"json\",a=e[o],e[o]=function(){s=arguments},i.always(function(){e[o]=a,n[o]&&(n.jsonpCallback=r.jsonpCallback,Fn.push(o)),s&&x.isFunction(a)&&a(s[0]),s=a=t}),\"script\"):t});var Pn,Rn,Wn=0,$n=e.ActiveXObject&&function(){var e;for(e in Pn)Pn[e](t,!0)};function In(){try{return new e.XMLHttpRequest}catch(t){}}function zn(){try{return new e.ActiveXObject(\"Microsoft.XMLHTTP\")}catch(t){}}x.ajaxSettings.xhr=e.ActiveXObject?function(){return!this.isLocal&&In()||zn()}:In,Rn=x.ajaxSettings.xhr(),x.support.cors=!!Rn&&\"withCredentials\"in Rn,Rn=x.support.ajax=!!Rn,Rn&&x.ajaxTransport(function(n){if(!n.crossDomain||x.support.cors){var r;return{send:function(i,o){var a,s,l=n.xhr();if(n.username?l.open(n.type,n.url,n.async,n.username,n.password):l.open(n.type,n.url,n.async),n.xhrFields)for(s in n.xhrFields)l[s]=n.xhrFields[s];n.mimeType&&l.overrideMimeType&&l.overrideMimeType(n.mimeType),n.crossDomain||i[\"X-Requested-With\"]||(i[\"X-Requested-With\"]=\"XMLHttpRequest\");try{for(s in i)l.setRequestHeader(s,i[s])}catch(u){}l.send(n.hasContent&&n.data||null),r=function(e,i){var s,u,c,p;try{if(r&&(i||4===l.readyState))if(r=t,a&&(l.onreadystatechange=x.noop,$n&&delete Pn[a]),i)4!==l.readyState&&l.abort();else{p={},s=l.status,u=l.getAllResponseHeaders(),\"string\"==typeof l.responseText&&(p.text=l.responseText);try{c=l.statusText}catch(f){c=\"\"}s||!n.isLocal||n.crossDomain?1223===s&&(s=204):s=p.text?200:404}}catch(d){i||o(-1,d)}p&&o(s,c,p,u)},n.async?4===l.readyState?setTimeout(r):(a=++Wn,$n&&(Pn||(Pn={},x(e).unload($n)),Pn[a]=r),l.onreadystatechange=r):r()},abort:function(){r&&r(t,!0)}}}});var Xn,Un,Vn=/^(?:toggle|show|hide)$/,Yn=RegExp(\"^(?:([+-])=|)(\"+w+\")([a-z%]*)$\",\"i\"),Jn=/queueHooks$/,Gn=[nr],Qn={\"*\":[function(e,t){var n=this.createTween(e,t),r=n.cur(),i=Yn.exec(t),o=i&&i[3]||(x.cssNumber[e]?\"\":\"px\"),a=(x.cssNumber[e]||\"px\"!==o&&+r)&&Yn.exec(x.css(n.elem,e)),s=1,l=20;if(a&&a[3]!==o){o=o||a[3],i=i||[],a=+r||1;do s=s||\".5\",a/=s,x.style(n.elem,e,a+o);while(s!==(s=n.cur()/r)&&1!==s&&--l)}return i&&(a=n.start=+a||+r||0,n.unit=o,n.end=i[1]?a+(i[1]+1)*i[2]:+i[2]),n}]};function Kn(){return setTimeout(function(){Xn=t}),Xn=x.now()}function Zn(e,t,n){var r,i=(Qn[t]||[]).concat(Qn[\"*\"]),o=0,a=i.length;for(;a>o;o++)if(r=i[o].call(n,t,e))return r}function er(e,t,n){var r,i,o=0,a=Gn.length,s=x.Deferred().always(function(){delete l.elem}),l=function(){if(i)return!1;var t=Xn||Kn(),n=Math.max(0,u.startTime+u.duration-t),r=n/u.duration||0,o=1-r,a=0,l=u.tweens.length;for(;l>a;a++)u.tweens[a].run(o);return s.notifyWith(e,[u,o,n]),1>o&&l?n:(s.resolveWith(e,[u]),!1)},u=s.promise({elem:e,props:x.extend({},t),opts:x.extend(!0,{specialEasing:{}},n),originalProperties:t,originalOptions:n,startTime:Xn||Kn(),duration:n.duration,tweens:[],createTween:function(t,n){var r=x.Tween(e,u.opts,t,n,u.opts.specialEasing[t]||u.opts.easing);return u.tweens.push(r),r},stop:function(t){var n=0,r=t?u.tweens.length:0;if(i)return this;for(i=!0;r>n;n++)u.tweens[n].run(1);return t?s.resolveWith(e,[u,t]):s.rejectWith(e,[u,t]),this}}),c=u.props;for(tr(c,u.opts.specialEasing);a>o;o++)if(r=Gn[o].call(u,e,c,u.opts))return r;return x.map(c,Zn,u),x.isFunction(u.opts.start)&&u.opts.start.call(e,u),x.fx.timer(x.extend(l,{elem:e,anim:u,queue:u.opts.queue})),u.progress(u.opts.progress).done(u.opts.done,u.opts.complete).fail(u.opts.fail).always(u.opts.always)}function tr(e,t){var n,r,i,o,a;for(n in e)if(r=x.camelCase(n),i=t[r],o=e[n],x.isArray(o)&&(i=o[1],o=e[n]=o[0]),n!==r&&(e[r]=o,delete e[n]),a=x.cssHooks[r],a&&\"expand\"in a){o=a.expand(o),delete e[r];for(n in o)n in e||(e[n]=o[n],t[n]=i)}else t[r]=i}x.Animation=x.extend(er,{tweener:function(e,t){x.isFunction(e)?(t=e,e=[\"*\"]):e=e.split(\" \");var n,r=0,i=e.length;for(;i>r;r++)n=e[r],Qn[n]=Qn[n]||[],Qn[n].unshift(t)},prefilter:function(e,t){t?Gn.unshift(e):Gn.push(e)}});function nr(e,t,n){var r,i,o,a,s,l,u=this,c={},p=e.style,f=e.nodeType&&nn(e),d=x._data(e,\"fxshow\");n.queue||(s=x._queueHooks(e,\"fx\"),null==s.unqueued&&(s.unqueued=0,l=s.empty.fire,s.empty.fire=function(){s.unqueued||l()}),s.unqueued++,u.always(function(){u.always(function(){s.unqueued--,x.queue(e,\"fx\").length||s.empty.fire()})})),1===e.nodeType&&(\"height\"in t||\"width\"in t)&&(n.overflow=[p.overflow,p.overflowX,p.overflowY],\"inline\"===x.css(e,\"display\")&&\"none\"===x.css(e,\"float\")&&(x.support.inlineBlockNeedsLayout&&\"inline\"!==ln(e.nodeName)?p.zoom=1:p.display=\"inline-block\")),n.overflow&&(p.overflow=\"hidden\",x.support.shrinkWrapBlocks||u.always(function(){p.overflow=n.overflow[0],p.overflowX=n.overflow[1],p.overflowY=n.overflow[2]}));for(r in t)if(i=t[r],Vn.exec(i)){if(delete t[r],o=o||\"toggle\"===i,i===(f?\"hide\":\"show\"))continue;c[r]=d&&d[r]||x.style(e,r)}if(!x.isEmptyObject(c)){d?\"hidden\"in d&&(f=d.hidden):d=x._data(e,\"fxshow\",{}),o&&(d.hidden=!f),f?x(e).show():u.done(function(){x(e).hide()}),u.done(function(){var t;x._removeData(e,\"fxshow\");for(t in c)x.style(e,t,c[t])});for(r in c)a=Zn(f?d[r]:0,r,u),r in d||(d[r]=a.start,f&&(a.end=a.start,a.start=\"width\"===r||\"height\"===r?1:0))}}function rr(e,t,n,r,i){return new rr.prototype.init(e,t,n,r,i)}x.Tween=rr,rr.prototype={constructor:rr,init:function(e,t,n,r,i,o){this.elem=e,this.prop=n,this.easing=i||\"swing\",this.options=t,this.start=this.now=this.cur(),this.end=r,this.unit=o||(x.cssNumber[n]?\"\":\"px\")},cur:function(){var e=rr.propHooks[this.prop];return e&&e.get?e.get(this):rr.propHooks._default.get(this)},run:function(e){var t,n=rr.propHooks[this.prop];return this.pos=t=this.options.duration?x.easing[this.easing](e,this.options.duration*e,0,1,this.options.duration):e,this.now=(this.end-this.start)*t+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),n&&n.set?n.set(this):rr.propHooks._default.set(this),this}},rr.prototype.init.prototype=rr.prototype,rr.propHooks={_default:{get:function(e){var t;return null==e.elem[e.prop]||e.elem.style&&null!=e.elem.style[e.prop]?(t=x.css(e.elem,e.prop,\"\"),t&&\"auto\"!==t?t:0):e.elem[e.prop]},set:function(e){x.fx.step[e.prop]?x.fx.step[e.prop](e):e.elem.style&&(null!=e.elem.style[x.cssProps[e.prop]]||x.cssHooks[e.prop])?x.style(e.elem,e.prop,e.now+e.unit):e.elem[e.prop]=e.now}}},rr.propHooks.scrollTop=rr.propHooks.scrollLeft={set:function(e){e.elem.nodeType&&e.elem.parentNode&&(e.elem[e.prop]=e.now)}},x.each([\"toggle\",\"show\",\"hide\"],function(e,t){var n=x.fn[t];x.fn[t]=function(e,r,i){return null==e||\"boolean\"==typeof e?n.apply(this,arguments):this.animate(ir(t,!0),e,r,i)}}),x.fn.extend({fadeTo:function(e,t,n,r){return this.filter(nn).css(\"opacity\",0).show().end().animate({opacity:t},e,n,r)},animate:function(e,t,n,r){var i=x.isEmptyObject(e),o=x.speed(t,n,r),a=function(){var t=er(this,x.extend({},e),o);(i||x._data(this,\"finish\"))&&t.stop(!0)};return a.finish=a,i||o.queue===!1?this.each(a):this.queue(o.queue,a)},stop:function(e,n,r){var i=function(e){var t=e.stop;delete e.stop,t(r)};return\"string\"!=typeof e&&(r=n,n=e,e=t),n&&e!==!1&&this.queue(e||\"fx\",[]),this.each(function(){var t=!0,n=null!=e&&e+\"queueHooks\",o=x.timers,a=x._data(this);if(n)a[n]&&a[n].stop&&i(a[n]);else for(n in a)a[n]&&a[n].stop&&Jn.test(n)&&i(a[n]);for(n=o.length;n--;)o[n].elem!==this||null!=e&&o[n].queue!==e||(o[n].anim.stop(r),t=!1,o.splice(n,1));(t||!r)&&x.dequeue(this,e)})},finish:function(e){return e!==!1&&(e=e||\"fx\"),this.each(function(){var t,n=x._data(this),r=n[e+\"queue\"],i=n[e+\"queueHooks\"],o=x.timers,a=r?r.length:0;for(n.finish=!0,x.queue(this,e,[]),i&&i.stop&&i.stop.call(this,!0),t=o.length;t--;)o[t].elem===this&&o[t].queue===e&&(o[t].anim.stop(!0),o.splice(t,1));for(t=0;a>t;t++)r[t]&&r[t].finish&&r[t].finish.call(this);delete n.finish})}});function ir(e,t){var n,r={height:e},i=0;for(t=t?1:0;4>i;i+=2-t)n=Zt[i],r[\"margin\"+n]=r[\"padding\"+n]=e;return t&&(r.opacity=r.width=e),r}x.each({slideDown:ir(\"show\"),slideUp:ir(\"hide\"),slideToggle:ir(\"toggle\"),fadeIn:{opacity:\"show\"},fadeOut:{opacity:\"hide\"},fadeToggle:{opacity:\"toggle\"}},function(e,t){x.fn[e]=function(e,n,r){return this.animate(t,e,n,r)}}),x.speed=function(e,t,n){var r=e&&\"object\"==typeof e?x.extend({},e):{complete:n||!n&&t||x.isFunction(e)&&e,duration:e,easing:n&&t||t&&!x.isFunction(t)&&t};return r.duration=x.fx.off?0:\"number\"==typeof r.duration?r.duration:r.duration in x.fx.speeds?x.fx.speeds[r.duration]:x.fx.speeds._default,(null==r.queue||r.queue===!0)&&(r.queue=\"fx\"),r.old=r.complete,r.complete=function(){x.isFunction(r.old)&&r.old.call(this),r.queue&&x.dequeue(this,r.queue)},r},x.easing={linear:function(e){return e},swing:function(e){return.5-Math.cos(e*Math.PI)/2}},x.timers=[],x.fx=rr.prototype.init,x.fx.tick=function(){var e,n=x.timers,r=0;for(Xn=x.now();n.length>r;r++)e=n[r],e()||n[r]!==e||n.splice(r--,1);n.length||x.fx.stop(),Xn=t},x.fx.timer=function(e){e()&&x.timers.push(e)&&x.fx.start()},x.fx.interval=13,x.fx.start=function(){Un||(Un=setInterval(x.fx.tick,x.fx.interval))},x.fx.stop=function(){clearInterval(Un),Un=null},x.fx.speeds={slow:600,fast:200,_default:400},x.fx.step={},x.expr&&x.expr.filters&&(x.expr.filters.animated=function(e){return x.grep(x.timers,function(t){return e===t.elem}).length}),x.fn.offset=function(e){if(arguments.length)return e===t?this:this.each(function(t){x.offset.setOffset(this,e,t)});var n,r,o={top:0,left:0},a=this[0],s=a&&a.ownerDocument;if(s)return n=s.documentElement,x.contains(n,a)?(typeof a.getBoundingClientRect!==i&&(o=a.getBoundingClientRect()),r=or(s),{top:o.top+(r.pageYOffset||n.scrollTop)-(n.clientTop||0),left:o.left+(r.pageXOffset||n.scrollLeft)-(n.clientLeft||0)}):o},x.offset={setOffset:function(e,t,n){var r=x.css(e,\"position\");\"static\"===r&&(e.style.position=\"relative\");var i=x(e),o=i.offset(),a=x.css(e,\"top\"),s=x.css(e,\"left\"),l=(\"absolute\"===r||\"fixed\"===r)&&x.inArray(\"auto\",[a,s])>-1,u={},c={},p,f;l?(c=i.position(),p=c.top,f=c.left):(p=parseFloat(a)||0,f=parseFloat(s)||0),x.isFunction(t)&&(t=t.call(e,n,o)),null!=t.top&&(u.top=t.top-o.top+p),null!=t.left&&(u.left=t.left-o.left+f),\"using\"in t?t.using.call(e,u):i.css(u)}},x.fn.extend({position:function(){if(this[0]){var e,t,n={top:0,left:0},r=this[0];return\"fixed\"===x.css(r,\"position\")?t=r.getBoundingClientRect():(e=this.offsetParent(),t=this.offset(),x.nodeName(e[0],\"html\")||(n=e.offset()),n.top+=x.css(e[0],\"borderTopWidth\",!0),n.left+=x.css(e[0],\"borderLeftWidth\",!0)),{top:t.top-n.top-x.css(r,\"marginTop\",!0),left:t.left-n.left-x.css(r,\"marginLeft\",!0)}}},offsetParent:function(){return this.map(function(){var e=this.offsetParent||s;while(e&&!x.nodeName(e,\"html\")&&\"static\"===x.css(e,\"position\"))e=e.offsetParent;return e||s})}}),x.each({scrollLeft:\"pageXOffset\",scrollTop:\"pageYOffset\"},function(e,n){var r=/Y/.test(n);x.fn[e]=function(i){return x.access(this,function(e,i,o){var a=or(e);return o===t?a?n in a?a[n]:a.document.documentElement[i]:e[i]:(a?a.scrollTo(r?x(a).scrollLeft():o,r?o:x(a).scrollTop()):e[i]=o,t)},e,i,arguments.length,null)}});function or(e){return x.isWindow(e)?e:9===e.nodeType?e.defaultView||e.parentWindow:!1}x.each({Height:\"height\",Width:\"width\"},function(e,n){x.each({padding:\"inner\"+e,content:n,\"\":\"outer\"+e},function(r,i){x.fn[i]=function(i,o){var a=arguments.length&&(r||\"boolean\"!=typeof i),s=r||(i===!0||o===!0?\"margin\":\"border\");return x.access(this,function(n,r,i){var o;return x.isWindow(n)?n.document.documentElement[\"client\"+e]:9===n.nodeType?(o=n.documentElement,Math.max(n.body[\"scroll\"+e],o[\"scroll\"+e],n.body[\"offset\"+e],o[\"offset\"+e],o[\"client\"+e])):i===t?x.css(n,r,s):x.style(n,r,i,s)},n,a?i:t,a,null)}})}),x.fn.size=function(){return this.length},x.fn.andSelf=x.fn.addBack,\"object\"==typeof module&&module&&\"object\"==typeof module.exports?module.exports=x:(e.jQuery=e.$=x,\"function\"==typeof define&&define.amd&&define(\"jquery\",[],function(){return x}))})(window);"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/sass-bootstrap/assets/js/jszip.js",
    "content": "/**\n\nJSZip - A Javascript class for generating and reading zip files\n<http://stuartk.com/jszip>\n\n(c) 2009-2012 Stuart Knightley <stuart [at] stuartk.com>\nDual licenced under the MIT license or GPLv3. See LICENSE.markdown.\n\nUsage:\n   zip = new JSZip();\n   zip.file(\"hello.txt\", \"Hello, World!\").file(\"tempfile\", \"nothing\");\n   zip.folder(\"images\").file(\"smile.gif\", base64Data, {base64: true});\n   zip.file(\"Xmas.txt\", \"Ho ho ho !\", {date : new Date(\"December 25, 2007 00:00:01\")});\n   zip.remove(\"tempfile\");\n\n   base64zip = zip.generate();\n\n**/\n\"use strict\";\n\n/**\n * Representation a of zip file in js\n * @constructor\n * @param {String=|ArrayBuffer=|Uint8Array=|Buffer=} data the data to load, if any (optional).\n * @param {Object=} options the options for creating this objects (optional).\n */\nvar JSZip = function(data, options) {\n   // object containing the files :\n   // {\n   //   \"folder/\" : {...},\n   //   \"folder/data.txt\" : {...}\n   // }\n   this.files = {};\n\n   // Where we are in the hierarchy\n   this.root = \"\";\n\n   if (data) {\n      this.load(data, options);\n   }\n};\n\nJSZip.signature = {\n   LOCAL_FILE_HEADER : \"\\x50\\x4b\\x03\\x04\",\n   CENTRAL_FILE_HEADER : \"\\x50\\x4b\\x01\\x02\",\n   CENTRAL_DIRECTORY_END : \"\\x50\\x4b\\x05\\x06\",\n   ZIP64_CENTRAL_DIRECTORY_LOCATOR : \"\\x50\\x4b\\x06\\x07\",\n   ZIP64_CENTRAL_DIRECTORY_END : \"\\x50\\x4b\\x06\\x06\",\n   DATA_DESCRIPTOR : \"\\x50\\x4b\\x07\\x08\"\n};\n\n// Default properties for a new file\nJSZip.defaults = {\n   base64: false,\n   binary: false,\n   dir: false,\n   date: null,\n   compression: null\n};\n\n\nJSZip.prototype = (function () {\n\n   /**\n    * Returns the raw data of a ZipObject, decompress the content if necessary.\n    * @param {ZipObject} file the file to use.\n    * @return {String|ArrayBuffer|Uint8Array|Buffer} the data.\n    */\n   var getRawData = function (file) {\n      if (file._data instanceof JSZip.CompressedObject) {\n         file._data = file._data.getContent();\n         file.options.binary = true;\n         file.options.base64 = false;\n\n         if (JSZip.utils.getTypeOf(file._data) === \"uint8array\") {\n            var copy = file._data;\n            // when reading an arraybuffer, the CompressedObject mechanism will keep it and subarray() a Uint8Array.\n            // if we request a file in the same format, we might get the same Uint8Array or its ArrayBuffer (the original zip file).\n            file._data = new Uint8Array(copy.length);\n            // with an empty Uint8Array, Opera fails with a \"Offset larger than array size\"\n            if (copy.length !== 0) {\n               file._data.set(copy, 0);\n            }\n         }\n      }\n      return file._data;\n   };\n\n   /**\n    * Returns the data of a ZipObject in a binary form. If the content is an unicode string, encode it.\n    * @param {ZipObject} file the file to use.\n    * @return {String|ArrayBuffer|Uint8Array|Buffer} the data.\n    */\n   var getBinaryData = function (file) {\n      var result = getRawData(file), type = JSZip.utils.getTypeOf(result);\n      if (type === \"string\") {\n         if (!file.options.binary) {\n            // unicode text !\n            // unicode string => binary string is a painful process, check if we can avoid it.\n            if (JSZip.support.uint8array && typeof TextEncoder === \"function\") {\n               return TextEncoder(\"utf-8\").encode(result);\n            }\n            if (JSZip.support.nodebuffer) {\n               return new Buffer(result, \"utf-8\");\n            }\n         }\n         return file.asBinary();\n      }\n      return result;\n   }\n\n   /**\n    * Transform this._data into a string.\n    * @param {function} filter a function String -> String, applied if not null on the result.\n    * @return {String} the string representing this._data.\n    */\n   var dataToString = function (asUTF8) {\n      var result = getRawData(this);\n      if (result === null || typeof result === \"undefined\") {\n         return \"\";\n      }\n      // if the data is a base64 string, we decode it before checking the encoding !\n      if (this.options.base64) {\n         result = JSZip.base64.decode(result);\n      }\n      if (asUTF8 && this.options.binary) {\n         // JSZip.prototype.utf8decode supports arrays as input\n         // skip to array => string step, utf8decode will do it.\n         result = JSZip.prototype.utf8decode(result);\n      } else {\n         // no utf8 transformation, do the array => string step.\n         result = JSZip.utils.transformTo(\"string\", result);\n      }\n\n      if (!asUTF8 && !this.options.binary) {\n         result = JSZip.prototype.utf8encode(result);\n      }\n      return result;\n   };\n   /**\n    * A simple object representing a file in the zip file.\n    * @constructor\n    * @param {string} name the name of the file\n    * @param {String|ArrayBuffer|Uint8Array|Buffer} data the data\n    * @param {Object} options the options of the file\n    */\n   var ZipObject = function (name, data, options) {\n      this.name = name;\n      this._data = data;\n      this.options = options;\n   };\n\n   ZipObject.prototype = {\n      /**\n       * Return the content as UTF8 string.\n       * @return {string} the UTF8 string.\n       */\n      asText : function () {\n         return dataToString.call(this, true);\n      },\n      /**\n       * Returns the binary content.\n       * @return {string} the content as binary.\n       */\n      asBinary : function () {\n         return dataToString.call(this, false);\n      },\n      /**\n       * Returns the content as a nodejs Buffer.\n       * @return {Buffer} the content as a Buffer.\n       */\n      asNodeBuffer : function () {\n         var result = getBinaryData(this);\n         return JSZip.utils.transformTo(\"nodebuffer\", result);\n      },\n      /**\n       * Returns the content as an Uint8Array.\n       * @return {Uint8Array} the content as an Uint8Array.\n       */\n      asUint8Array : function () {\n         var result = getBinaryData(this);\n         return JSZip.utils.transformTo(\"uint8array\", result);\n      },\n      /**\n       * Returns the content as an ArrayBuffer.\n       * @return {ArrayBuffer} the content as an ArrayBufer.\n       */\n      asArrayBuffer : function () {\n         return this.asUint8Array().buffer;\n      }\n   };\n\n   /**\n    * Transform an integer into a string in hexadecimal.\n    * @private\n    * @param {number} dec the number to convert.\n    * @param {number} bytes the number of bytes to generate.\n    * @returns {string} the result.\n    */\n   var decToHex = function(dec, bytes) {\n      var hex = \"\", i;\n      for(i = 0; i < bytes; i++) {\n         hex += String.fromCharCode(dec&0xff);\n         dec=dec>>>8;\n      }\n      return hex;\n   };\n\n   /**\n    * Merge the objects passed as parameters into a new one.\n    * @private\n    * @param {...Object} var_args All objects to merge.\n    * @return {Object} a new object with the data of the others.\n    */\n   var extend = function () {\n      var result = {}, i, attr;\n      for (i = 0; i < arguments.length; i++) { // arguments is not enumerable in some browsers\n         for (attr in arguments[i]) {\n            if (arguments[i].hasOwnProperty(attr) && typeof result[attr] === \"undefined\") {\n               result[attr] = arguments[i][attr];\n            }\n         }\n      }\n      return result;\n   };\n\n   /**\n    * Transforms the (incomplete) options from the user into the complete\n    * set of options to create a file.\n    * @private\n    * @param {Object} o the options from the user.\n    * @return {Object} the complete set of options.\n    */\n   var prepareFileAttrs = function (o) {\n      o = o || {};\n      if (o.base64 === true && o.binary == null) {\n         o.binary = true;\n      }\n      o = extend(o, JSZip.defaults);\n      o.date = o.date || new Date();\n      if (o.compression !== null) o.compression = o.compression.toUpperCase();\n\n      return o;\n   };\n\n   /**\n    * Add a file in the current folder.\n    * @private\n    * @param {string} name the name of the file\n    * @param {String|ArrayBuffer|Uint8Array|Buffer} data the data of the file\n    * @param {Object} o the options of the file\n    * @return {Object} the new file.\n    */\n   var fileAdd = function (name, data, o) {\n      // be sure sub folders exist\n      var parent = parentFolder(name), dataType = JSZip.utils.getTypeOf(data);\n      if (parent) {\n         folderAdd.call(this, parent);\n      }\n\n      o = prepareFileAttrs(o);\n\n      if (o.dir || data === null || typeof data === \"undefined\") {\n         o.base64 = false;\n         o.binary = false;\n         data = null;\n      } else if (dataType === \"string\") {\n         if (o.binary && !o.base64) {\n            // optimizedBinaryString == true means that the file has already been filtered with a 0xFF mask\n            if (o.optimizedBinaryString !== true) {\n               // this is a string, not in a base64 format.\n               // Be sure that this is a correct \"binary string\"\n               data = JSZip.utils.string2binary(data);\n            }\n         }\n      } else { // arraybuffer, uint8array, ...\n         o.base64 = false;\n         o.binary = true;\n\n         if (!dataType && !(data instanceof JSZip.CompressedObject)) {\n            throw new Error(\"The data of '\" + name + \"' is in an unsupported format !\");\n         }\n\n         // special case : it's way easier to work with Uint8Array than with ArrayBuffer\n         if (dataType === \"arraybuffer\") {\n            data = JSZip.utils.transformTo(\"uint8array\", data);\n         }\n      }\n\n      return this.files[name] = new ZipObject(name, data, o);\n   };\n\n\n   /**\n    * Find the parent folder of the path.\n    * @private\n    * @param {string} path the path to use\n    * @return {string} the parent folder, or \"\"\n    */\n   var parentFolder = function (path) {\n      if (path.slice(-1) == '/') {\n         path = path.substring(0, path.length - 1);\n      }\n      var lastSlash = path.lastIndexOf('/');\n      return (lastSlash > 0) ? path.substring(0, lastSlash) : \"\";\n   };\n\n   /**\n    * Add a (sub) folder in the current folder.\n    * @private\n    * @param {string} name the folder's name\n    * @return {Object} the new folder.\n    */\n   var folderAdd = function (name) {\n      // Check the name ends with a /\n      if (name.slice(-1) != \"/\") {\n         name += \"/\"; // IE doesn't like substr(-1)\n      }\n\n      // Does this folder already exist?\n      if (!this.files[name]) {\n         fileAdd.call(this, name, null, {dir:true});\n      }\n      return this.files[name];\n   };\n\n   /**\n    * Generate a JSZip.CompressedObject for a given zipOject.\n    * @param {ZipObject} file the object to read.\n    * @param {JSZip.compression} compression the compression to use.\n    * @return {JSZip.CompressedObject} the compressed result.\n    */\n   var generateCompressedObjectFrom = function (file, compression) {\n      var result = new JSZip.CompressedObject(), content;\n\n      // the data has not been decompressed, we might reuse things !\n      if (file._data instanceof JSZip.CompressedObject) {\n         result.uncompressedSize = file._data.uncompressedSize;\n         result.crc32 = file._data.crc32;\n\n         if (result.uncompressedSize === 0 || file.options.dir) {\n            compression = JSZip.compressions['STORE'];\n            result.compressedContent = \"\";\n            result.crc32 = 0;\n         } else if (file._data.compressionMethod === compression.magic) {\n            result.compressedContent = file._data.getCompressedContent();\n         } else {\n            content = file._data.getContent()\n            // need to decompress / recompress\n            result.compressedContent = compression.compress(JSZip.utils.transformTo(compression.compressInputType, content));\n         }\n      } else {\n         // have uncompressed data\n         content = getBinaryData(file);\n         if (!content || content.length === 0 || file.options.dir) {\n            compression = JSZip.compressions['STORE'];\n            content = \"\";\n         }\n         result.uncompressedSize = content.length;\n         result.crc32 = this.crc32(content);\n         result.compressedContent = compression.compress(JSZip.utils.transformTo(compression.compressInputType, content));\n      }\n\n      result.compressedSize = result.compressedContent.length;\n      result.compressionMethod = compression.magic;\n\n      return result;\n   };\n\n   /**\n    * Generate the various parts used in the construction of the final zip file.\n    * @param {string} name the file name.\n    * @param {ZipObject} file the file content.\n    * @param {JSZip.CompressedObject} compressedObject the compressed object.\n    * @param {number} offset the current offset from the start of the zip file.\n    * @return {object} the zip parts.\n    */\n   var generateZipParts = function(name, file, compressedObject, offset) {\n      var data = compressedObject.compressedContent,\n          utfEncodedFileName = this.utf8encode(file.name),\n          useUTF8 = utfEncodedFileName !== file.name,\n          o       = file.options,\n          dosTime,\n          dosDate;\n\n      // date\n      // @see http://www.delorie.com/djgpp/doc/rbinter/it/52/13.html\n      // @see http://www.delorie.com/djgpp/doc/rbinter/it/65/16.html\n      // @see http://www.delorie.com/djgpp/doc/rbinter/it/66/16.html\n\n      dosTime = o.date.getHours();\n      dosTime = dosTime << 6;\n      dosTime = dosTime | o.date.getMinutes();\n      dosTime = dosTime << 5;\n      dosTime = dosTime | o.date.getSeconds() / 2;\n\n      dosDate = o.date.getFullYear() - 1980;\n      dosDate = dosDate << 4;\n      dosDate = dosDate | (o.date.getMonth() + 1);\n      dosDate = dosDate << 5;\n      dosDate = dosDate | o.date.getDate();\n\n\n      var header = \"\";\n\n      // version needed to extract\n      header += \"\\x0A\\x00\";\n      // general purpose bit flag\n      // set bit 11 if utf8\n      header += useUTF8 ? \"\\x00\\x08\" : \"\\x00\\x00\";\n      // compression method\n      header += compressedObject.compressionMethod;\n      // last mod file time\n      header += decToHex(dosTime, 2);\n      // last mod file date\n      header += decToHex(dosDate, 2);\n      // crc-32\n      header += decToHex(compressedObject.crc32, 4);\n      // compressed size\n      header += decToHex(compressedObject.compressedSize, 4);\n      // uncompressed size\n      header += decToHex(compressedObject.uncompressedSize, 4);\n      // file name length\n      header += decToHex(utfEncodedFileName.length, 2);\n      // extra field length\n      header += \"\\x00\\x00\";\n\n\n      var fileRecord = JSZip.signature.LOCAL_FILE_HEADER + header + utfEncodedFileName;\n\n      var dirRecord = JSZip.signature.CENTRAL_FILE_HEADER +\n      // version made by (00: DOS)\n      \"\\x14\\x00\" +\n      // file header (common to file and central directory)\n      header +\n      // file comment length\n      \"\\x00\\x00\" +\n      // disk number start\n      \"\\x00\\x00\" +\n      // internal file attributes TODO\n      \"\\x00\\x00\" +\n      // external file attributes\n      (file.options.dir===true?\"\\x10\\x00\\x00\\x00\":\"\\x00\\x00\\x00\\x00\")+\n      // relative offset of local header\n      decToHex(offset, 4) +\n      // file name\n      utfEncodedFileName;\n\n\n      return {\n         fileRecord : fileRecord,\n         dirRecord : dirRecord,\n         compressedObject : compressedObject\n      };\n   };\n\n   /**\n    * An object to write any content to a string.\n    * @constructor\n    */\n   var StringWriter = function () {\n      this.data = [];\n   };\n   StringWriter.prototype = {\n      /**\n       * Append any content to the current string.\n       * @param {Object} input the content to add.\n       */\n      append : function (input) {\n         input = JSZip.utils.transformTo(\"string\", input);\n         this.data.push(input);\n      },\n      /**\n       * Finalize the construction an return the result.\n       * @return {string} the generated string.\n       */\n      finalize : function () {\n         return this.data.join(\"\");\n      }\n   };\n   /**\n    * An object to write any content to an Uint8Array.\n    * @constructor\n    * @param {number} length The length of the array.\n    */\n   var Uint8ArrayWriter = function (length) {\n      this.data = new Uint8Array(length);\n      this.index = 0;\n   };\n   Uint8ArrayWriter.prototype = {\n      /**\n       * Append any content to the current array.\n       * @param {Object} input the content to add.\n       */\n      append : function (input) {\n         if (input.length !== 0) {\n            // with an empty Uint8Array, Opera fails with a \"Offset larger than array size\"\n            input = JSZip.utils.transformTo(\"uint8array\", input);\n            this.data.set(input, this.index);\n            this.index += input.length;\n         }\n      },\n      /**\n       * Finalize the construction an return the result.\n       * @return {Uint8Array} the generated array.\n       */\n      finalize : function () {\n         return this.data;\n      }\n   };\n\n   // return the actual prototype of JSZip\n   return {\n      /**\n       * Read an existing zip and merge the data in the current JSZip object.\n       * The implementation is in jszip-load.js, don't forget to include it.\n       * @param {String|ArrayBuffer|Uint8Array|Buffer} stream  The stream to load\n       * @param {Object} options Options for loading the stream.\n       *  options.base64 : is the stream in base64 ? default : false\n       * @return {JSZip} the current JSZip object\n       */\n      load : function (stream, options) {\n         throw new Error(\"Load method is not defined. Is the file jszip-load.js included ?\");\n      },\n\n      /**\n       * Filter nested files/folders with the specified function.\n       * @param {Function} search the predicate to use :\n       * function (relativePath, file) {...}\n       * It takes 2 arguments : the relative path and the file.\n       * @return {Array} An array of matching elements.\n       */\n      filter : function (search) {\n         var result = [], filename, relativePath, file, fileClone;\n         for (filename in this.files) {\n            if ( !this.files.hasOwnProperty(filename) ) { continue; }\n            file = this.files[filename];\n            // return a new object, don't let the user mess with our internal objects :)\n            fileClone = new ZipObject(file.name, file._data, extend(file.options));\n            relativePath = filename.slice(this.root.length, filename.length);\n            if (filename.slice(0, this.root.length) === this.root && // the file is in the current root\n                search(relativePath, fileClone)) { // and the file matches the function\n               result.push(fileClone);\n            }\n         }\n         return result;\n      },\n\n      /**\n       * Add a file to the zip file, or search a file.\n       * @param   {string|RegExp} name The name of the file to add (if data is defined),\n       * the name of the file to find (if no data) or a regex to match files.\n       * @param   {String|ArrayBuffer|Uint8Array|Buffer} data  The file data, either raw or base64 encoded\n       * @param   {Object} o     File options\n       * @return  {JSZip|Object|Array} this JSZip object (when adding a file),\n       * a file (when searching by string) or an array of files (when searching by regex).\n       */\n      file : function(name, data, o) {\n         if (arguments.length === 1) {\n            if (name instanceof RegExp) {\n               var regexp = name;\n               return this.filter(function(relativePath, file) {\n                  return !file.options.dir && regexp.test(relativePath);\n               });\n            } else { // text\n               return this.filter(function (relativePath, file) {\n                  return !file.options.dir && relativePath === name;\n               })[0]||null;\n            }\n         } else { // more than one argument : we have data !\n            name = this.root+name;\n            fileAdd.call(this, name, data, o);\n         }\n         return this;\n      },\n\n      /**\n       * Add a directory to the zip file, or search.\n       * @param   {String|RegExp} arg The name of the directory to add, or a regex to search folders.\n       * @return  {JSZip} an object with the new directory as the root, or an array containing matching folders.\n       */\n      folder : function(arg) {\n         if (!arg) {\n            return this;\n         }\n\n         if (arg instanceof RegExp) {\n            return this.filter(function(relativePath, file) {\n               return file.options.dir && arg.test(relativePath);\n            });\n         }\n\n         // else, name is a new folder\n         var name = this.root + arg;\n         var newFolder = folderAdd.call(this, name);\n\n         // Allow chaining by returning a new object with this folder as the root\n         var ret = this.clone();\n         ret.root = newFolder.name;\n         return ret;\n      },\n\n      /**\n       * Delete a file, or a directory and all sub-files, from the zip\n       * @param {string} name the name of the file to delete\n       * @return {JSZip} this JSZip object\n       */\n      remove : function(name) {\n         name = this.root + name;\n         var file = this.files[name];\n         if (!file) {\n            // Look for any folders\n            if (name.slice(-1) != \"/\") {\n               name += \"/\";\n            }\n            file = this.files[name];\n         }\n\n         if (file) {\n            if (!file.options.dir) {\n               // file\n               delete this.files[name];\n            } else {\n               // folder\n               var kids = this.filter(function (relativePath, file) {\n                  return file.name.slice(0, name.length) === name;\n               });\n               for (var i = 0; i < kids.length; i++) {\n                  delete this.files[kids[i].name];\n               }\n            }\n         }\n\n         return this;\n      },\n\n      /**\n       * Generate the complete zip file\n       * @param {Object} options the options to generate the zip file :\n       * - base64, (deprecated, use type instead) true to generate base64.\n       * - compression, \"STORE\" by default.\n       * - type, \"base64\" by default. Values are : string, base64, uint8array, arraybuffer, blob.\n       * @return {String|Uint8Array|ArrayBuffer|Buffer|Blob} the zip file\n       */\n      generate : function(options) {\n         options = extend(options || {}, {\n            base64 : true,\n            compression : \"STORE\",\n            type : \"base64\"\n         });\n\n         JSZip.utils.checkSupport(options.type);\n\n         var zipData = [], localDirLength = 0, centralDirLength = 0, writer, i;\n\n\n         // first, generate all the zip parts.\n         for (var name in this.files) {\n            if ( !this.files.hasOwnProperty(name) ) { continue; }\n            var file = this.files[name];\n\n            var compressionName = file.compression || options.compression.toUpperCase();\n            var compression = JSZip.compressions[compressionName];\n            if (!compression) {\n               throw new Error(compressionName + \" is not a valid compression method !\");\n            }\n\n            var compressedObject = generateCompressedObjectFrom.call(this, file, compression);\n\n            var zipPart = generateZipParts.call(this, name, file, compressedObject, localDirLength);\n            localDirLength += zipPart.fileRecord.length + compressedObject.compressedSize;\n            centralDirLength += zipPart.dirRecord.length;\n            zipData.push(zipPart);\n         }\n\n         var dirEnd = \"\";\n\n         // end of central dir signature\n         dirEnd = JSZip.signature.CENTRAL_DIRECTORY_END +\n         // number of this disk\n         \"\\x00\\x00\" +\n         // number of the disk with the start of the central directory\n         \"\\x00\\x00\" +\n         // total number of entries in the central directory on this disk\n         decToHex(zipData.length, 2) +\n         // total number of entries in the central directory\n         decToHex(zipData.length, 2) +\n         // size of the central directory   4 bytes\n         decToHex(centralDirLength, 4) +\n         // offset of start of central directory with respect to the starting disk number\n         decToHex(localDirLength, 4) +\n         // .ZIP file comment length\n         \"\\x00\\x00\";\n\n\n         // we have all the parts (and the total length)\n         // time to create a writer !\n         switch(options.type.toLowerCase()) {\n            case \"uint8array\" :\n            case \"arraybuffer\" :\n            case \"blob\" :\n            case \"nodebuffer\" :\n               writer = new Uint8ArrayWriter(localDirLength + centralDirLength + dirEnd.length);\n               break;\n            case \"base64\" :\n            default : // case \"string\" :\n               writer = new StringWriter(localDirLength + centralDirLength + dirEnd.length);\n               break;\n         }\n\n         for (i = 0; i < zipData.length; i++) {\n            writer.append(zipData[i].fileRecord);\n            writer.append(zipData[i].compressedObject.compressedContent);\n         }\n         for (i = 0; i < zipData.length; i++) {\n            writer.append(zipData[i].dirRecord);\n         }\n\n         writer.append(dirEnd);\n\n         var zip = writer.finalize();\n\n\n\n         switch(options.type.toLowerCase()) {\n            // case \"zip is an Uint8Array\"\n            case \"uint8array\" :\n            case \"arraybuffer\" :\n            case \"nodebuffer\" :\n               return JSZip.utils.transformTo(options.type.toLowerCase(), zip);\n            case \"blob\" :\n               return JSZip.utils.arrayBuffer2Blob(JSZip.utils.transformTo(\"arraybuffer\", zip));\n\n            // case \"zip is a string\"\n            case \"base64\" :\n               return (options.base64) ? JSZip.base64.encode(zip) : zip;\n            default : // case \"string\" :\n               return zip;\n         }\n      },\n\n      /**\n       *\n       *  Javascript crc32\n       *  http://www.webtoolkit.info/\n       *\n       */\n      crc32 : function crc32(input, crc) {\n         if (typeof input === \"undefined\" || !input.length) {\n            return 0;\n         }\n\n         var isArray = JSZip.utils.getTypeOf(input) !== \"string\";\n\n         var table = [\n            0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA,\n            0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3,\n            0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988,\n            0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91,\n            0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE,\n            0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,\n            0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC,\n            0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5,\n            0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172,\n            0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B,\n            0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940,\n            0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,\n            0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116,\n            0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F,\n            0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924,\n            0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D,\n            0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A,\n            0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,\n            0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818,\n            0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01,\n            0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E,\n            0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457,\n            0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C,\n            0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,\n            0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2,\n            0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB,\n            0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0,\n            0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9,\n            0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086,\n            0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,\n            0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4,\n            0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD,\n            0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A,\n            0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683,\n            0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8,\n            0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,\n            0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE,\n            0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7,\n            0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC,\n            0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5,\n            0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252,\n            0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,\n            0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60,\n            0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79,\n            0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236,\n            0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F,\n            0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04,\n            0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,\n            0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A,\n            0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713,\n            0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38,\n            0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21,\n            0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E,\n            0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,\n            0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C,\n            0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45,\n            0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2,\n            0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB,\n            0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0,\n            0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,\n            0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6,\n            0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF,\n            0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94,\n            0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D\n         ];\n\n         if (typeof(crc) == \"undefined\") { crc = 0; }\n         var x = 0;\n         var y = 0;\n         var byte = 0;\n\n         crc = crc ^ (-1);\n         for( var i = 0, iTop = input.length; i < iTop; i++ ) {\n            byte = isArray ? input[i] : input.charCodeAt(i);\n            y = ( crc ^ byte ) & 0xFF;\n            x = table[y];\n            crc = ( crc >>> 8 ) ^ x;\n         }\n\n         return crc ^ (-1);\n      },\n\n      // Inspired by http://my.opera.com/GreyWyvern/blog/show.dml/1725165\n      clone : function() {\n         var newObj = new JSZip();\n         for (var i in this) {\n            if (typeof this[i] !== \"function\") {\n               newObj[i] = this[i];\n            }\n         }\n         return newObj;\n      },\n\n\n      /**\n       * http://www.webtoolkit.info/javascript-utf8.html\n       */\n      utf8encode : function (string) {\n         // TextEncoder + Uint8Array to binary string is faster than checking every bytes on long strings.\n         // http://jsperf.com/utf8encode-vs-textencoder\n         // On short strings (file names for example), the TextEncoder API is (currently) slower.\n         if (JSZip.support.uint8array && typeof TextEncoder === \"function\") {\n            var u8 = TextEncoder(\"utf-8\").encode(string);\n            return JSZip.utils.transformTo(\"string\", u8);\n         }\n         if (JSZip.support.nodebuffer) {\n            return JSZip.utils.transformTo(\"string\", new Buffer(string, \"utf-8\"));\n         }\n\n         // array.join may be slower than string concatenation but generates less objects (less time spent garbage collecting).\n         // See also http://jsperf.com/array-direct-assignment-vs-push/31\n         var result = [], resIndex = 0;\n\n         for (var n = 0; n < string.length; n++) {\n\n            var c = string.charCodeAt(n);\n\n            if (c < 128) {\n               result[resIndex++] = String.fromCharCode(c);\n            } else if ((c > 127) && (c < 2048)) {\n               result[resIndex++] = String.fromCharCode((c >> 6) | 192);\n               result[resIndex++] = String.fromCharCode((c & 63) | 128);\n            } else {\n               result[resIndex++] = String.fromCharCode((c >> 12) | 224);\n               result[resIndex++] = String.fromCharCode(((c >> 6) & 63) | 128);\n               result[resIndex++] = String.fromCharCode((c & 63) | 128);\n            }\n\n         }\n\n         return result.join(\"\");\n      },\n\n      /**\n       * http://www.webtoolkit.info/javascript-utf8.html\n       */\n      utf8decode : function (input) {\n         var result = [], resIndex = 0;\n         var type = JSZip.utils.getTypeOf(input);\n         var isArray = type !== \"string\";\n         var i = 0;\n         var c = 0, c1 = 0, c2 = 0, c3 = 0;\n\n         // check if we can use the TextDecoder API\n         // see http://encoding.spec.whatwg.org/#api\n         if (JSZip.support.uint8array && typeof TextDecoder === \"function\") {\n            return TextDecoder(\"utf-8\").decode(\n               JSZip.utils.transformTo(\"uint8array\", input)\n            );\n         }\n         if (JSZip.support.nodebuffer) {\n            return JSZip.utils.transformTo(\"nodebuffer\", input).toString(\"utf-8\");\n         }\n\n         while ( i < input.length ) {\n\n            c = isArray ? input[i] : input.charCodeAt(i);\n\n            if (c < 128) {\n               result[resIndex++] = String.fromCharCode(c);\n               i++;\n            } else if ((c > 191) && (c < 224)) {\n               c2 = isArray ? input[i+1] : input.charCodeAt(i+1);\n               result[resIndex++] = String.fromCharCode(((c & 31) << 6) | (c2 & 63));\n               i += 2;\n            } else {\n               c2 = isArray ? input[i+1] : input.charCodeAt(i+1);\n               c3 = isArray ? input[i+2] : input.charCodeAt(i+2);\n               result[resIndex++] = String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));\n               i += 3;\n            }\n\n         }\n\n         return result.join(\"\");\n      }\n   };\n}());\n\n/*\n * Compression methods\n * This object is filled in as follow :\n * name : {\n *    magic // the 2 bytes indentifying the compression method\n *    compress // function, take the uncompressed content and return it compressed.\n *    uncompress // function, take the compressed content and return it uncompressed.\n *    compressInputType // string, the type accepted by the compress method. null to accept everything.\n *    uncompressInputType // string, the type accepted by the uncompress method. null to accept everything.\n * }\n *\n * STORE is the default compression method, so it's included in this file.\n * Other methods should go to separated files : the user wants modularity.\n */\nJSZip.compressions = {\n   \"STORE\" : {\n      magic : \"\\x00\\x00\",\n      compress : function (content) {\n         return content; // no compression\n      },\n      uncompress : function (content) {\n         return content; // no compression\n      },\n      compressInputType : null,\n      uncompressInputType : null\n   }\n};\n\n/*\n * List features that require a modern browser, and if the current browser support them.\n */\nJSZip.support = {\n   // contains true if JSZip can read/generate ArrayBuffer, false otherwise.\n   arraybuffer : (function(){\n      return typeof ArrayBuffer !== \"undefined\" && typeof Uint8Array !== \"undefined\";\n   })(),\n   // contains true if JSZip can read/generate nodejs Buffer, false otherwise.\n   nodebuffer : (function(){\n      return typeof Buffer !== \"undefined\";\n   })(),\n   // contains true if JSZip can read/generate Uint8Array, false otherwise.\n   uint8array : (function(){\n      return typeof Uint8Array !== \"undefined\";\n   })(),\n   // contains true if JSZip can read/generate Blob, false otherwise.\n   blob : (function(){\n      // the spec started with BlobBuilder then replaced it with a construtor for Blob.\n      // Result : we have browsers that :\n      // * know the BlobBuilder (but with prefix)\n      // * know the Blob constructor\n      // * know about Blob but not about how to build them\n      // About the \"=== 0\" test : if given the wrong type, it may be converted to a string.\n      // Instead of an empty content, we will get \"[object Uint8Array]\" for example.\n      if (typeof ArrayBuffer === \"undefined\") {\n         return false;\n      }\n      var buffer = new ArrayBuffer(0);\n      try {\n         return new Blob([buffer], { type: \"application/zip\" }).size === 0;\n      }\n      catch(e) {}\n\n      try {\n         var builder = new (window.BlobBuilder || window.WebKitBlobBuilder ||\n                            window.MozBlobBuilder || window.MSBlobBuilder)();\n         builder.append(buffer);\n         return builder.getBlob('application/zip').size === 0;\n      }\n      catch(e) {}\n\n      return false;\n   })()\n};\n\n(function () {\n   JSZip.utils = {\n      /**\n       * Convert a string to a \"binary string\" : a string containing only char codes between 0 and 255.\n       * @param {string} str the string to transform.\n       * @return {String} the binary string.\n       */\n      string2binary : function (str) {\n         var result = \"\";\n         for (var i = 0; i < str.length; i++) {\n            result += String.fromCharCode(str.charCodeAt(i) & 0xff);\n         }\n         return result;\n      },\n      /**\n       * Create a Uint8Array from the string.\n       * @param {string} str the string to transform.\n       * @return {Uint8Array} the typed array.\n       * @throws {Error} an Error if the browser doesn't support the requested feature.\n       * @deprecated : use JSZip.utils.transformTo instead.\n       */\n      string2Uint8Array : function (str) {\n         return JSZip.utils.transformTo(\"uint8array\", str);\n      },\n\n      /**\n       * Create a string from the Uint8Array.\n       * @param {Uint8Array} array the array to transform.\n       * @return {string} the string.\n       * @throws {Error} an Error if the browser doesn't support the requested feature.\n       * @deprecated : use JSZip.utils.transformTo instead.\n       */\n      uint8Array2String : function (array) {\n         return JSZip.utils.transformTo(\"string\", array);\n      },\n      /**\n       * Create a blob from the given ArrayBuffer.\n       * @param {ArrayBuffer} buffer the buffer to transform.\n       * @return {Blob} the result.\n       * @throws {Error} an Error if the browser doesn't support the requested feature.\n       */\n      arrayBuffer2Blob : function (buffer) {\n         JSZip.utils.checkSupport(\"blob\");\n\n         try {\n            // Blob constructor\n            return new Blob([buffer], { type: \"application/zip\" });\n         }\n         catch(e) {}\n\n         try {\n            // deprecated, browser only, old way\n            var builder = new (window.BlobBuilder || window.WebKitBlobBuilder ||\n                               window.MozBlobBuilder || window.MSBlobBuilder)();\n            builder.append(buffer);\n            return builder.getBlob('application/zip');\n         }\n         catch(e) {}\n\n         // well, fuck ?!\n         throw new Error(\"Bug : can't construct the Blob.\");\n      },\n      /**\n       * Create a blob from the given string.\n       * @param {string} str the string to transform.\n       * @return {Blob} the result.\n       * @throws {Error} an Error if the browser doesn't support the requested feature.\n       */\n      string2Blob : function (str) {\n         var buffer = JSZip.utils.transformTo(\"arraybuffer\", str);\n         return JSZip.utils.arrayBuffer2Blob(buffer);\n      }\n   };\n\n   /**\n    * The identity function.\n    * @param {Object} input the input.\n    * @return {Object} the same input.\n    */\n   function identity(input) {\n      return input;\n   };\n\n   /**\n    * Fill in an array with a string.\n    * @param {String} str the string to use.\n    * @param {Array|ArrayBuffer|Uint8Array|Buffer} array the array to fill in (will be mutated).\n    * @return {Array|ArrayBuffer|Uint8Array|Buffer} the updated array.\n    */\n   function stringToArrayLike(str, array) {\n      for (var i = 0; i < str.length; ++i) {\n         array[i] = str.charCodeAt(i) & 0xFF;\n      }\n      return array;\n   };\n\n   /**\n    * Transform an array-like object to a string.\n    * @param {Array|ArrayBuffer|Uint8Array|Buffer} array the array to transform.\n    * @return {String} the result.\n    */\n   function arrayLikeToString(array) {\n      // Performances notes :\n      // --------------------\n      // String.fromCharCode.apply(null, array) is the fastest, see\n      // see http://jsperf.com/converting-a-uint8array-to-a-string/2\n      // but the stack is limited (and we can get huge arrays !).\n      //\n      // result += String.fromCharCode(array[i]); generate too many strings !\n      //\n      // This code is inspired by http://jsperf.com/arraybuffer-to-string-apply-performance/2\n      var chunk = 65536;\n      var result = [], len = array.length, type = JSZip.utils.getTypeOf(array), k = 0;\n\n      while (k < len && chunk > 1) {\n         try {\n            if (type === \"array\" || type === \"nodebuffer\") {\n               result.push(String.fromCharCode.apply(null, array.slice(k, Math.max(k + chunk, len))));\n            } else {\n               result.push(String.fromCharCode.apply(null, array.subarray(k, k + chunk)));\n            }\n            k += chunk;\n         } catch (e) {\n            chunk = Math.floor(chunk / 2);\n         }\n      }\n      return result.join(\"\");\n   };\n\n   /**\n    * Copy the data from an array-like to an other array-like.\n    * @param {Array|ArrayBuffer|Uint8Array|Buffer} arrayFrom the origin array.\n    * @param {Array|ArrayBuffer|Uint8Array|Buffer} arrayTo the destination array which will be mutated.\n    * @return {Array|ArrayBuffer|Uint8Array|Buffer} the updated destination array.\n    */\n   function arrayLikeToArrayLike(arrayFrom, arrayTo) {\n      for(var i = 0; i < arrayFrom.length; i++) {\n         arrayTo[i] = arrayFrom[i];\n      }\n      return arrayTo;\n   };\n\n   // a matrix containing functions to transform everything into everything.\n   var transform = {};\n\n   // string to ?\n   transform[\"string\"] = {\n      \"string\" : identity,\n      \"array\" : function (input) {\n         return stringToArrayLike(input, new Array(input.length));\n      },\n      \"arraybuffer\" : function (input) {\n         return transform[\"string\"][\"uint8array\"](input).buffer;\n      },\n      \"uint8array\" : function (input) {\n         return stringToArrayLike(input, new Uint8Array(input.length));\n      },\n      \"nodebuffer\" : function (input) {\n         return stringToArrayLike(input, new Buffer(input.length));\n      }\n   };\n\n   // array to ?\n   transform[\"array\"] = {\n      \"string\" : arrayLikeToString,\n      \"array\" : identity,\n      \"arraybuffer\" : function (input) {\n         return (new Uint8Array(input)).buffer;\n      },\n      \"uint8array\" : function (input) {\n         return new Uint8Array(input);\n      },\n      \"nodebuffer\" : function (input) {\n         return new Buffer(input);\n      }\n   };\n\n   // arraybuffer to ?\n   transform[\"arraybuffer\"] = {\n      \"string\" : function (input) {\n         return arrayLikeToString(new Uint8Array(input));\n      },\n      \"array\" : function (input) {\n         return arrayLikeToArrayLike(new Uint8Array(input), new Array(input.byteLength));\n      },\n      \"arraybuffer\" : identity,\n      \"uint8array\" : function (input) {\n         return new Uint8Array(input);\n      },\n      \"nodebuffer\" : function (input) {\n         return new Buffer(new Uint8Array(input));\n      }\n   };\n\n   // uint8array to ?\n   transform[\"uint8array\"] = {\n      \"string\" : arrayLikeToString,\n      \"array\" : function (input) {\n         return arrayLikeToArrayLike(input, new Array(input.length));\n      },\n      \"arraybuffer\" : function (input) {\n         return input.buffer;\n      },\n      \"uint8array\" : identity,\n      \"nodebuffer\" : function(input) {\n         return new Buffer(input);\n      }\n   };\n\n   // nodebuffer to ?\n   transform[\"nodebuffer\"] = {\n      \"string\" : arrayLikeToString,\n      \"array\" : function (input) {\n         return arrayLikeToArrayLike(input, new Array(input.length));\n      },\n      \"arraybuffer\" : function (input) {\n         return transform[\"nodebuffer\"][\"uint8array\"](input).buffer;\n      },\n      \"uint8array\" : function (input) {\n         return arrayLikeToArrayLike(input, new Uint8Array(input.length));\n      },\n      \"nodebuffer\" : identity\n   };\n\n   /**\n    * Transform an input into any type.\n    * The supported output type are : string, array, uint8array, arraybuffer, nodebuffer.\n    * If no output type is specified, the unmodified input will be returned.\n    * @param {String} outputType the output type.\n    * @param {String|Array|ArrayBuffer|Uint8Array|Buffer} input the input to convert.\n    * @throws {Error} an Error if the browser doesn't support the requested output type.\n    */\n   JSZip.utils.transformTo = function (outputType, input) {\n      if (!input) {\n         // undefined, null, etc\n         // an empty string won't harm.\n         input = \"\";\n      }\n      if (!outputType) {\n         return input;\n      }\n      JSZip.utils.checkSupport(outputType);\n      var inputType = JSZip.utils.getTypeOf(input);\n      var result = transform[inputType][outputType](input);\n      return result;\n   };\n\n   /**\n    * Return the type of the input.\n    * The type will be in a format valid for JSZip.utils.transformTo : string, array, uint8array, arraybuffer.\n    * @param {Object} input the input to identify.\n    * @return {String} the (lowercase) type of the input.\n    */\n   JSZip.utils.getTypeOf = function (input) {\n      if (typeof input === \"string\") {\n         return \"string\";\n      }\n      if (input instanceof Array) {\n         return \"array\";\n      }\n      if (JSZip.support.nodebuffer && Buffer.isBuffer(input)) {\n         return \"nodebuffer\";\n      }\n      if (JSZip.support.uint8array && input instanceof Uint8Array) {\n         return \"uint8array\";\n      }\n      if (JSZip.support.arraybuffer && input instanceof ArrayBuffer) {\n         return \"arraybuffer\";\n      }\n   };\n\n   /**\n    * Throw an exception if the type is not supported.\n    * @param {String} type the type to check.\n    * @throws {Error} an Error if the browser doesn't support the requested type.\n    */\n   JSZip.utils.checkSupport = function (type) {\n      var supported = true;\n      switch (type.toLowerCase()) {\n         case \"uint8array\":\n            supported = JSZip.support.uint8array;\n         break;\n         case \"arraybuffer\":\n            supported = JSZip.support.arraybuffer;\n         break;\n         case \"nodebuffer\":\n            supported = JSZip.support.nodebuffer;\n         break;\n         case \"blob\":\n            supported = JSZip.support.blob;\n         break;\n      }\n      if (!supported) {\n         throw new Error(type + \" is not supported by this browser\");\n      }\n   };\n\n\n})();\n\n(function (){\n   /**\n    * Represents an entry in the zip.\n    * The content may or may not be compressed.\n    * @constructor\n    */\n   JSZip.CompressedObject = function () {\n         this.compressedSize = 0;\n         this.uncompressedSize = 0;\n         this.crc32 = 0;\n         this.compressionMethod = null;\n         this.compressedContent = null;\n   };\n\n   JSZip.CompressedObject.prototype = {\n      /**\n       * Return the decompressed content in an unspecified format.\n       * The format will depend on the decompressor.\n       * @return {Object} the decompressed content.\n       */\n      getContent : function () {\n         return null; // see implementation\n      },\n      /**\n       * Return the compressed content in an unspecified format.\n       * The format will depend on the compressed conten source.\n       * @return {Object} the compressed content.\n       */\n      getCompressedContent : function () {\n         return null; // see implementation\n      }\n   };\n})();\n\n/**\n *\n *  Base64 encode / decode\n *  http://www.webtoolkit.info/\n *\n *  Hacked so that it doesn't utf8 en/decode everything\n **/\nJSZip.base64 = (function() {\n   // private property\n   var _keyStr = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=\";\n\n   return {\n      // public method for encoding\n      encode : function(input, utf8) {\n         var output = \"\";\n         var chr1, chr2, chr3, enc1, enc2, enc3, enc4;\n         var i = 0;\n\n         while (i < input.length) {\n\n            chr1 = input.charCodeAt(i++);\n            chr2 = input.charCodeAt(i++);\n            chr3 = input.charCodeAt(i++);\n\n            enc1 = chr1 >> 2;\n            enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);\n            enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);\n            enc4 = chr3 & 63;\n\n            if (isNaN(chr2)) {\n               enc3 = enc4 = 64;\n            } else if (isNaN(chr3)) {\n               enc4 = 64;\n            }\n\n            output = output +\n               _keyStr.charAt(enc1) + _keyStr.charAt(enc2) +\n               _keyStr.charAt(enc3) + _keyStr.charAt(enc4);\n\n         }\n\n         return output;\n      },\n\n      // public method for decoding\n      decode : function(input, utf8) {\n         var output = \"\";\n         var chr1, chr2, chr3;\n         var enc1, enc2, enc3, enc4;\n         var i = 0;\n\n         input = input.replace(/[^A-Za-z0-9\\+\\/\\=]/g, \"\");\n\n         while (i < input.length) {\n\n            enc1 = _keyStr.indexOf(input.charAt(i++));\n            enc2 = _keyStr.indexOf(input.charAt(i++));\n            enc3 = _keyStr.indexOf(input.charAt(i++));\n            enc4 = _keyStr.indexOf(input.charAt(i++));\n\n            chr1 = (enc1 << 2) | (enc2 >> 4);\n            chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);\n            chr3 = ((enc3 & 3) << 6) | enc4;\n\n            output = output + String.fromCharCode(chr1);\n\n            if (enc3 != 64) {\n               output = output + String.fromCharCode(chr2);\n            }\n            if (enc4 != 64) {\n               output = output + String.fromCharCode(chr3);\n            }\n\n         }\n\n         return output;\n\n      }\n   };\n}());\n\n// enforcing Stuk's coding style\n// vim: set shiftwidth=3 softtabstop=3:"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/sass-bootstrap/assets/js/less.js",
    "content": "//\n// LESS - Leaner CSS v1.3.3\n// http://lesscss.org\n//\n// Copyright (c) 2009-2013, Alexis Sellier\n// Licensed under the Apache 2.0 License.\n//\n(function(e,t){function n(t){return e.less[t.split(\"/\")[1]]}function f(){r.env===\"development\"?(r.optimization=0,r.watchTimer=setInterval(function(){r.watchMode&&g(function(e,t,n,r,i){t&&S(t.toCSS(),r,i.lastModified)})},r.poll)):r.optimization=3}function m(){var e=document.getElementsByTagName(\"style\");for(var t=0;t<e.length;t++)e[t].type.match(p)&&(new r.Parser({filename:document.location.href.replace(/#.*$/,\"\"),dumpLineNumbers:r.dumpLineNumbers})).parse(e[t].innerHTML||\"\",function(n,r){var i=r.toCSS(),s=e[t];s.type=\"text/css\",s.styleSheet?s.styleSheet.cssText=i:s.innerHTML=i})}function g(e,t){for(var n=0;n<r.sheets.length;n++)w(r.sheets[n],e,t,r.sheets.length-(n+1))}function y(e,t){var n=b(e),r=b(t),i,s,o,u,a=\"\";if(n.hostPart!==r.hostPart)return\"\";s=Math.max(r.directories.length,n.directories.length);for(i=0;i<s;i++)if(r.directories[i]!==n.directories[i])break;u=r.directories.slice(i),o=n.directories.slice(i);for(i=0;i<u.length-1;i++)a+=\"../\";for(i=0;i<o.length-1;i++)a+=o[i]+\"/\";return a}function b(e,t){var n=/^((?:[a-z-]+:)?\\/\\/(?:[^\\/\\?#]*\\/)|([\\/\\\\]))?((?:[^\\/\\\\\\?#]*[\\/\\\\])*)([^\\/\\\\\\?#]*)([#\\?].*)?$/,r=e.match(n),i={},s=[],o,u;if(!r)throw new Error(\"Could not parse sheet href - '\"+e+\"'\");if(!r[1]||r[2]){u=t.match(n);if(!u)throw new Error(\"Could not parse page url - '\"+t+\"'\");r[1]=u[1],r[2]||(r[3]=u[3]+r[3])}if(r[3]){s=r[3].replace(\"\\\\\",\"/\").split(\"/\");for(o=0;o<s.length;o++)s[o]===\"..\"&&o>0&&(s.splice(o-1,2),o-=2)}return i.hostPart=r[1],i.directories=s,i.path=r[1]+s.join(\"/\"),i.fileUrl=i.path+(r[4]||\"\"),i.url=i.fileUrl+(r[5]||\"\"),i}function w(t,n,i,s){var o=t.contents||{},u=t.files||{},a=b(t.href,e.location.href),f=a.url,c=l&&l.getItem(f),h=l&&l.getItem(f+\":timestamp\"),p={css:c,timestamp:h},d;r.relativeUrls?r.rootpath?t.entryPath?d=b(r.rootpath+y(a.path,t.entryPath)).path:d=r.rootpath:d=a.path:r.rootpath?d=r.rootpath:t.entryPath?d=t.entryPath:d=a.path,x(f,t.type,function(e,l){v+=e.replace(/@import .+?;/ig,\"\");if(!i&&p&&l&&(new Date(l)).valueOf()===(new Date(p.timestamp)).valueOf())S(p.css,t),n(null,null,e,t,{local:!0,remaining:s},f);else try{o[f]=e,(new r.Parser({optimization:r.optimization,paths:[a.path],entryPath:t.entryPath||a.path,mime:t.type,filename:f,rootpath:d,relativeUrls:t.relativeUrls,contents:o,files:u,dumpLineNumbers:r.dumpLineNumbers})).parse(e,function(r,i){if(r)return k(r,f);try{n(r,i,e,t,{local:!1,lastModified:l,remaining:s},f),N(document.getElementById(\"less-error-message:\"+E(f)))}catch(r){k(r,f)}})}catch(c){k(c,f)}},function(e,t){throw new Error(\"Couldn't load \"+t+\" (\"+e+\")\")})}function E(e){return e.replace(/^[a-z]+:\\/\\/?[^\\/]+/,\"\").replace(/^\\//,\"\").replace(/\\.[a-zA-Z]+$/,\"\").replace(/[^\\.\\w-]+/g,\"-\").replace(/\\./g,\":\")}function S(e,t,n){var r,i=t.href||\"\",s=\"less:\"+(t.title||E(i));if((r=document.getElementById(s))===null){r=document.createElement(\"style\"),r.type=\"text/css\",t.media&&(r.media=t.media),r.id=s;var o=t&&t.nextSibling||null;(o||document.getElementsByTagName(\"head\")[0]).parentNode.insertBefore(r,o)}if(r.styleSheet)try{r.styleSheet.cssText=e}catch(u){throw new Error(\"Couldn't reassign styleSheet.cssText.\")}else(function(e){r.childNodes.length>0?r.firstChild.nodeValue!==e.nodeValue&&r.replaceChild(e,r.firstChild):r.appendChild(e)})(document.createTextNode(e));if(n&&l){C(\"saving \"+i+\" to cache.\");try{l.setItem(i,e),l.setItem(i+\":timestamp\",n)}catch(u){C(\"failed to save\")}}}function x(e,t,n,i){function a(t,n,r){t.status>=200&&t.status<300?n(t.responseText,t.getResponseHeader(\"Last-Modified\")):typeof r==\"function\"&&r(t.status,e)}var s=T(),u=o?r.fileAsync:r.async;typeof s.overrideMimeType==\"function\"&&s.overrideMimeType(\"text/css\"),s.open(\"GET\",e,u),s.setRequestHeader(\"Accept\",t||\"text/x-less, text/css; q=0.9, */*; q=0.5\"),s.send(null),o&&!r.fileAsync?s.status===0||s.status>=200&&s.status<300?n(s.responseText):i(s.status,e):u?s.onreadystatechange=function(){s.readyState==4&&a(s,n,i)}:a(s,n,i)}function T(){if(e.XMLHttpRequest)return new XMLHttpRequest;try{return new ActiveXObject(\"MSXML2.XMLHTTP.3.0\")}catch(t){return C(\"browser doesn't support AJAX.\"),null}}function N(e){return e&&e.parentNode.removeChild(e)}function C(e){r.env==\"development\"&&typeof console!=\"undefined\"&&console.log(\"less: \"+e)}function k(e,t){var n=\"less-error-message:\"+E(t),i='<li><label>{line}</label><pre class=\"{class}\">{content}</pre></li>',s=document.createElement(\"div\"),o,u,a=[],f=e.filename||t,l=f.match(/([^\\/]+(\\?.*)?)$/)[1];s.id=n,s.className=\"less-error-message\",u=\"<h3>\"+(e.message||\"There is an error in your .less file\")+\"</h3>\"+'<p>in <a href=\"'+f+'\">'+l+\"</a> \";var c=function(e,t,n){e.extract[t]&&a.push(i.replace(/\\{line\\}/,parseInt(e.line)+(t-1)).replace(/\\{class\\}/,n).replace(/\\{content\\}/,e.extract[t]))};e.stack?u+=\"<br/>\"+e.stack.split(\"\\n\").slice(1).join(\"<br/>\"):e.extract&&(c(e,0,\"\"),c(e,1,\"line\"),c(e,2,\"\"),u+=\"on line \"+e.line+\", column \"+(e.column+1)+\":</p>\"+\"<ul>\"+a.join(\"\")+\"</ul>\"),s.innerHTML=u,S([\".less-error-message ul, .less-error-message li {\",\"list-style-type: none;\",\"margin-right: 15px;\",\"padding: 4px 0;\",\"margin: 0;\",\"}\",\".less-error-message label {\",\"font-size: 12px;\",\"margin-right: 15px;\",\"padding: 4px 0;\",\"color: #cc7777;\",\"}\",\".less-error-message pre {\",\"color: #dd6666;\",\"padding: 4px 0;\",\"margin: 0;\",\"display: inline-block;\",\"}\",\".less-error-message pre.line {\",\"color: #ff0000;\",\"}\",\".less-error-message h3 {\",\"font-size: 20px;\",\"font-weight: bold;\",\"padding: 15px 0 5px 0;\",\"margin: 0;\",\"}\",\".less-error-message a {\",\"color: #10a\",\"}\",\".less-error-message .error {\",\"color: red;\",\"font-weight: bold;\",\"padding-bottom: 2px;\",\"border-bottom: 1px dashed red;\",\"}\"].join(\"\\n\"),{title:\"error-message\"}),s.style.cssText=[\"font-family: Arial, sans-serif\",\"border: 1px solid #e00\",\"background-color: #eee\",\"border-radius: 5px\",\"-webkit-border-radius: 5px\",\"-moz-border-radius: 5px\",\"color: #e00\",\"padding: 15px\",\"margin-bottom: 15px\"].join(\";\"),r.env==\"development\"&&(o=setInterval(function(){document.body&&(document.getElementById(n)?document.body.replaceChild(s,document.getElementById(n)):document.body.insertBefore(s,document.body.firstChild),clearInterval(o))},10))}Array.isArray||(Array.isArray=function(e){return Object.prototype.toString.call(e)===\"[object Array]\"||e instanceof Array}),Array.prototype.forEach||(Array.prototype.forEach=function(e,t){var n=this.length>>>0;for(var r=0;r<n;r++)r in this&&e.call(t,this[r],r,this)}),Array.prototype.map||(Array.prototype.map=function(e){var t=this.length>>>0,n=new Array(t),r=arguments[1];for(var i=0;i<t;i++)i in this&&(n[i]=e.call(r,this[i],i,this));return n}),Array.prototype.filter||(Array.prototype.filter=function(e){var t=[],n=arguments[1];for(var r=0;r<this.length;r++)e.call(n,this[r])&&t.push(this[r]);return t}),Array.prototype.reduce||(Array.prototype.reduce=function(e){var t=this.length>>>0,n=0;if(t===0&&arguments.length===1)throw new TypeError;if(arguments.length>=2)var r=arguments[1];else do{if(n in this){r=this[n++];break}if(++n>=t)throw new TypeError}while(!0);for(;n<t;n++)n in this&&(r=e.call(null,r,this[n],n,this));return r}),Array.prototype.indexOf||(Array.prototype.indexOf=function(e){var t=this.length,n=arguments[1]||0;if(!t)return-1;if(n>=t)return-1;n<0&&(n+=t);for(;n<t;n++){if(!Object.prototype.hasOwnProperty.call(this,n))continue;if(e===this[n])return n}return-1}),Object.keys||(Object.keys=function(e){var t=[];for(var n in e)Object.prototype.hasOwnProperty.call(e,n)&&t.push(n);return t}),String.prototype.trim||(String.prototype.trim=function(){return String(this).replace(/^\\s\\s*/,\"\").replace(/\\s\\s*$/,\"\")});var r,i,s;typeof environment==\"object\"&&{}.toString.call(environment)===\"[object Environment]\"?(typeof e==\"undefined\"?r={}:r=e.less={},i=r.tree={},r.mode=\"rhino\"):typeof e==\"undefined\"?(r=exports,i=n(\"./tree\"),r.mode=\"node\"):(typeof e.less==\"undefined\"&&(e.less={}),r=e.less,i=e.less.tree={},r.mode=\"browser\"),r.Parser=function(t){function g(){a=c[u],f=o,h=o}function y(){c[u]=a,o=f,h=o}function b(){o>h&&(c[u]=c[u].slice(o-h),h=o)}function w(e){var t=e.charCodeAt(0);return t===32||t===10||t===9}function E(e){var t,n,r,i,a;if(e instanceof Function)return e.call(p.parsers);if(typeof e==\"string\")t=s.charAt(o)===e?e:null,r=1,b();else{b();if(!(t=e.exec(c[u])))return null;r=t[0].length}if(t)return S(r),typeof t==\"string\"?t:t.length===1?t[0]:t}function S(e){var t=o,n=u,r=o+c[u].length,i=o+=e;while(o<r){if(!w(s.charAt(o)))break;o++}return c[u]=c[u].slice(e+(o-i)),h=o,c[u].length===0&&u<c.length-1&&u++,t!==o||n!==u}function x(e,t){var n=E(e);if(!!n)return n;T(t||(typeof e==\"string\"?\"expected '\"+e+\"' got '\"+s.charAt(o)+\"'\":\"unexpected token\"))}function T(e,t){var n=new Error(e);throw n.index=o,n.type=t||\"Syntax\",n}function N(e){return typeof e==\"string\"?s.charAt(o)===e:e.test(c[u])?!0:!1}function C(e,t){return e.filename&&t.filename&&e.filename!==t.filename?p.imports.contents[e.filename]:s}function k(e,t){for(var n=e,r=-1;n>=0&&t.charAt(n)!==\"\\n\";n--)r++;return{line:typeof e==\"number\"?(t.slice(0,e).match(/\\n/g)||\"\").length:null,column:r}}function L(e){return r.mode===\"browser\"||r.mode===\"rhino\"?e.filename:n(\"path\").resolve(e.filename)}function A(e,t,n){return{lineNumber:k(e,t).line+1,fileName:L(n)}}function O(e,t){var n=C(e,t),r=k(e.index,n),i=r.line,s=r.column,o=n.split(\"\\n\");this.type=e.type||\"Syntax\",this.message=e.message,this.filename=e.filename||t.filename,this.index=e.index,this.line=typeof i==\"number\"?i+1:null,this.callLine=e.call&&k(e.call,n).line+1,this.callExtract=o[k(e.call,n).line],this.stack=e.stack,this.column=s,this.extract=[o[i-1],o[i],o[i+1]]}var s,o,u,a,f,l,c,h,p,d=this,t=t||{};t.contents||(t.contents={}),t.rootpath=t.rootpath||\"\",t.files||(t.files={});var v=function(){},m=this.imports={paths:t.paths||[],queue:[],files:t.files,contents:t.contents,mime:t.mime,error:null,push:function(e,n){var i=this;this.queue.push(e),r.Parser.importer(e,this.paths,function(t,r,s){i.queue.splice(i.queue.indexOf(e),1);var o=s in i.files;i.files[s]=r,t&&!i.error&&(i.error=t),n(t,r,o),i.queue.length===0&&v(i.error)},t)}};return this.env=t=t||{},this.optimization=\"optimization\"in this.env?this.env.optimization:1,this.env.filename=this.env.filename||null,p={imports:m,parse:function(e,a){var f,d,m,g,y,b,w=[],S,x=null;o=u=h=l=0,s=e.replace(/\\r\\n/g,\"\\n\"),s=s.replace(/^\\uFEFF/,\"\"),c=function(e){var n=0,r=/(?:@\\{[\\w-]+\\}|[^\"'`\\{\\}\\/\\(\\)\\\\])+/g,i=/\\/\\*(?:[^*]|\\*+[^\\/*])*\\*+\\/|\\/\\/.*/g,o=/\"((?:[^\"\\\\\\r\\n]|\\\\.)*)\"|'((?:[^'\\\\\\r\\n]|\\\\.)*)'|`((?:[^`]|\\\\.)*)`/g,u=0,a,f=e[0],l;for(var c=0,h,p;c<s.length;){r.lastIndex=c,(a=r.exec(s))&&a.index===c&&(c+=a[0].length,f.push(a[0])),h=s.charAt(c),i.lastIndex=o.lastIndex=c;if(a=o.exec(s))if(a.index===c){c+=a[0].length,f.push(a[0]);continue}if(!l&&h===\"/\"){p=s.charAt(c+1);if(p===\"/\"||p===\"*\")if(a=i.exec(s))if(a.index===c){c+=a[0].length,f.push(a[0]);continue}}switch(h){case\"{\":if(!l){u++,f.push(h);break};case\"}\":if(!l){u--,f.push(h),e[++n]=f=[];break};case\"(\":if(!l){l=!0,f.push(h);break};case\")\":if(l){l=!1,f.push(h);break};default:f.push(h)}c++}return u!=0&&(x=new O({index:c-1,type:\"Parse\",message:u>0?\"missing closing `}`\":\"missing opening `{`\",filename:t.filename},t)),e.map(function(e){return e.join(\"\")})}([[]]);if(x)return a(x,t);try{f=new i.Ruleset([],E(this.parsers.primary)),f.root=!0}catch(T){return a(new O(T,t))}f.toCSS=function(e){var s,o,u;return function(s,o){var u=[],a;s=s||{},typeof o==\"object\"&&!Array.isArray(o)&&(o=Object.keys(o).map(function(e){var t=o[e];return t instanceof i.Value||(t instanceof i.Expression||(t=new i.Expression([t])),t=new i.Value([t])),new i.Rule(\"@\"+e,t,!1,0)}),u=[new i.Ruleset(null,o)]);try{var f=e.call(this,{frames:u}).toCSS([],{compress:s.compress||!1,dumpLineNumbers:t.dumpLineNumbers})}catch(l){throw new O(l,t)}if(a=p.imports.error)throw a instanceof O?a:new O(a,t);return s.yuicompress&&r.mode===\"node\"?n(\"ycssmin\").cssmin(f):s.compress?f.replace(/(\\s)+/g,\"$1\"):f}}(f.eval);if(o<s.length-1){o=l,b=s.split(\"\\n\"),y=(s.slice(0,o).match(/\\n/g)||\"\").length+1;for(var N=o,C=-1;N>=0&&s.charAt(N)!==\"\\n\";N--)C++;x={type:\"Parse\",message:\"Syntax Error on line \"+y,index:o,filename:t.filename,line:y,column:C,extract:[b[y-2],b[y-1],b[y]]}}this.imports.queue.length>0?v=function(e){e=x||e,e?a(e):a(null,f)}:a(x,f)},parsers:{primary:function(){var e,t=[];while((e=E(this.mixin.definition)||E(this.rule)||E(this.ruleset)||E(this.mixin.call)||E(this.comment)||E(this.directive))||E(/^[\\s\\n]+/)||E(/^;+/))e&&t.push(e);return t},comment:function(){var e;if(s.charAt(o)!==\"/\")return;if(s.charAt(o+1)===\"/\")return new i.Comment(E(/^\\/\\/.*/),!0);if(e=E(/^\\/\\*(?:[^*]|\\*+[^\\/*])*\\*+\\/\\n?/))return new i.Comment(e)},entities:{quoted:function(){var e,t=o,n;s.charAt(t)===\"~\"&&(t++,n=!0);if(s.charAt(t)!=='\"'&&s.charAt(t)!==\"'\")return;n&&E(\"~\");if(e=E(/^\"((?:[^\"\\\\\\r\\n]|\\\\.)*)\"|'((?:[^'\\\\\\r\\n]|\\\\.)*)'/))return new i.Quoted(e[0],e[1]||e[2],n)},keyword:function(){var e;if(e=E(/^[_A-Za-z-][_A-Za-z0-9-]*/))return i.colors.hasOwnProperty(e)?new i.Color(i.colors[e].slice(1)):new i.Keyword(e)},call:function(){var e,n,r,s,a=o;if(!(e=/^([\\w-]+|%|progid:[\\w\\.]+)\\(/.exec(c[u])))return;e=e[1],n=e.toLowerCase();if(n===\"url\")return null;o+=e.length;if(n===\"alpha\"){s=E(this.alpha);if(typeof s!=\"undefined\")return s}E(\"(\"),r=E(this.entities.arguments);if(!E(\")\"))return;if(e)return new i.Call(e,r,a,t.filename)},arguments:function(){var e=[],t;while(t=E(this.entities.assignment)||E(this.expression)){e.push(t);if(!E(\",\"))break}return e},literal:function(){return E(this.entities.ratio)||E(this.entities.dimension)||E(this.entities.color)||E(this.entities.quoted)||E(this.entities.unicodeDescriptor)},assignment:function(){var e,t;if((e=E(/^\\w+(?=\\s?=)/i))&&E(\"=\")&&(t=E(this.entity)))return new i.Assignment(e,t)},url:function(){var e;if(s.charAt(o)!==\"u\"||!E(/^url\\(/))return;return e=E(this.entities.quoted)||E(this.entities.variable)||E(/^(?:(?:\\\\[\\(\\)'\"])|[^\\(\\)'\"])+/)||\"\",x(\")\"),new i.URL(e.value!=null||e instanceof i.Variable?e:new i.Anonymous(e),t.rootpath)},variable:function(){var e,n=o;if(s.charAt(o)===\"@\"&&(e=E(/^@@?[\\w-]+/)))return new i.Variable(e,n,t.filename)},variableCurly:function(){var e,n,r=o;if(s.charAt(o)===\"@\"&&(n=E(/^@\\{([\\w-]+)\\}/)))return new i.Variable(\"@\"+n[1],r,t.filename)},color:function(){var e;if(s.charAt(o)===\"#\"&&(e=E(/^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})/)))return new i.Color(e[1])},dimension:function(){var e,t=s.charCodeAt(o);if(t>57||t<43||t===47||t==44)return;if(e=E(/^([+-]?\\d*\\.?\\d+)(px|%|em|pc|ex|in|deg|s|ms|pt|cm|mm|rad|grad|turn|dpi|dpcm|dppx|rem|vw|vh|vmin|vm|ch)?/))return new i.Dimension(e[1],e[2])},ratio:function(){var e,t=s.charCodeAt(o);if(t>57||t<48)return;if(e=E(/^(\\d+\\/\\d+)/))return new i.Ratio(e[1])},unicodeDescriptor:function(){var e;if(e=E(/^U\\+[0-9a-fA-F?]+(\\-[0-9a-fA-F?]+)?/))return new i.UnicodeDescriptor(e[0])},javascript:function(){var e,t=o,n;s.charAt(t)===\"~\"&&(t++,n=!0);if(s.charAt(t)!==\"`\")return;n&&E(\"~\");if(e=E(/^`([^`]*)`/))return new i.JavaScript(e[1],o,n)}},variable:function(){var e;if(s.charAt(o)===\"@\"&&(e=E(/^(@[\\w-]+)\\s*:/)))return e[1]},shorthand:function(){var e,t;if(!N(/^[@\\w.%-]+\\/[@\\w.-]+/))return;g();if((e=E(this.entity))&&E(\"/\")&&(t=E(this.entity)))return new i.Shorthand(e,t);y()},mixin:{call:function(){var e=[],n,r,u=[],a=[],f,l,c,h,p,d,v,m=o,b=s.charAt(o),w,S,C=!1;if(b!==\".\"&&b!==\"#\")return;g();while(n=E(/^[#.](?:[\\w-]|\\\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+/))e.push(new i.Element(r,n,o)),r=E(\">\");if(E(\"(\")){p=[];while(c=E(this.expression)){h=null,S=c;if(c.value.length==1){var k=c.value[0];k instanceof i.Variable&&E(\":\")&&(p.length>0&&(d&&T(\"Cannot mix ; and , as delimiter types\"),v=!0),S=x(this.expression),h=w=k.name)}p.push(S),a.push({name:h,value:S});if(E(\",\"))continue;if(E(\";\")||d)v&&T(\"Cannot mix ; and , as delimiter types\"),d=!0,p.length>1&&(S=new i.Value(p)),u.push({name:w,value:S}),w=null,p=[],v=!1}x(\")\")}f=d?u:a,E(this.important)&&(C=!0);if(e.length>0&&(E(\";\")||N(\"}\")))return new i.mixin.Call(e,f,m,t.filename,C);y()},definition:function(){var e,t=[],n,r,u,a,f,c=!1;if(s.charAt(o)!==\".\"&&s.charAt(o)!==\"#\"||N(/^[^{]*\\}/))return;g();if(n=E(/^([#.](?:[\\w-]|\\\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+)\\s*\\(/)){e=n[1];do{E(this.comment);if(s.charAt(o)===\".\"&&E(/^\\.{3}/)){c=!0,t.push({variadic:!0});break}if(!(u=E(this.entities.variable)||E(this.entities.literal)||E(this.entities.keyword)))break;if(u instanceof i.Variable)if(E(\":\"))a=x(this.expression,\"expected expression\"),t.push({name:u.name,value:a});else{if(E(/^\\.{3}/)){t.push({name:u.name,variadic:!0}),c=!0;break}t.push({name:u.name})}else t.push({value:u})}while(E(\",\")||E(\";\"));E(\")\")||(l=o,y()),E(this.comment),E(/^when/)&&(f=x(this.conditions,\"expected condition\")),r=E(this.block);if(r)return new i.mixin.Definition(e,t,r,f,c);y()}}},entity:function(){return E(this.entities.literal)||E(this.entities.variable)||E(this.entities.url)||E(this.entities.call)||E(this.entities.keyword)||E(this.entities.javascript)||E(this.comment)},end:function(){return E(\";\")||N(\"}\")},alpha:function(){var e;if(!E(/^\\(opacity=/i))return;if(e=E(/^\\d+/)||E(this.entities.variable))return x(\")\"),new i.Alpha(e)},element:function(){var e,t,n,r;n=E(this.combinator),e=E(/^(?:\\d+\\.\\d+|\\d+)%/)||E(/^(?:[.#]?|:*)(?:[\\w-]|[^\\x00-\\x9f]|\\\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+/)||E(\"*\")||E(\"&\")||E(this.attribute)||E(/^\\([^()@]+\\)/)||E(/^[\\.#](?=@)/)||E(this.entities.variableCurly),e||E(\"(\")&&(r=E(this.entities.variableCurly)||E(this.entities.variable)||E(this.selector))&&E(\")\")&&(e=new i.Paren(r));if(e)return new i.Element(n,e,o)},combinator:function(){var e,t=s.charAt(o);if(t===\">\"||t===\"+\"||t===\"~\"||t===\"|\"){o++;while(s.charAt(o).match(/\\s/))o++;return new i.Combinator(t)}return s.charAt(o-1).match(/\\s/)?new i.Combinator(\" \"):new i.Combinator(null)},selector:function(){var e,t,n=[],r,u;if(E(\"(\"))return e=E(this.entity),E(\")\")?new i.Selector([new i.Element(\"\",e,o)]):null;while(t=E(this.element)){r=s.charAt(o),n.push(t);if(r===\"{\"||r===\"}\"||r===\";\"||r===\",\"||r===\")\")break}if(n.length>0)return new i.Selector(n)},attribute:function(){var e=\"\",t,n,r;if(!E(\"[\"))return;if(t=E(/^(?:[_A-Za-z0-9-]|\\\\.)+/)||E(this.entities.quoted))(r=E(/^[|~*$^]?=/))&&(n=E(this.entities.quoted)||E(/^[\\w-]+/))?e=[t,r,n.toCSS?n.toCSS():n].join(\"\"):e=t;if(!E(\"]\"))return;if(e)return\"[\"+e+\"]\"},block:function(){var e;if(E(\"{\")&&(e=E(this.primary))&&E(\"}\"))return e},ruleset:function(){var e=[],n,r,u,a;g(),t.dumpLineNumbers&&(a=A(o,s,t));while(n=E(this.selector)){e.push(n),E(this.comment);if(!E(\",\"))break;E(this.comment)}if(e.length>0&&(r=E(this.block))){var f=new i.Ruleset(e,r,t.strictImports);return t.dumpLineNumbers&&(f.debugInfo=a),f}l=o,y()},rule:function(){var e,t,n=s.charAt(o),r,a;g();if(n===\".\"||n===\"#\"||n===\"&\")return;if(e=E(this.variable)||E(this.property)){e.charAt(0)!=\"@\"&&(a=/^([^@+\\/'\"*`(;{}-]*);/.exec(c[u]))?(o+=a[0].length-1,t=new i.Anonymous(a[1])):e===\"font\"?t=E(this.font):t=E(this.value),r=E(this.important);if(t&&E(this.end))return new i.Rule(e,t,r,f);l=o,y()}},\"import\":function(){var e,n,r=o;g();var s=E(/^@import(?:-(once))?\\s+/);if(s&&(e=E(this.entities.quoted)||E(this.entities.url))){n=E(this.mediaFeatures);if(E(\";\"))return new i.Import(e,m,n,s[1]===\"once\",r,t.rootpath)}y()},mediaFeature:function(){var e,t,n=[];do if(e=E(this.entities.keyword))n.push(e);else if(E(\"(\")){t=E(this.property),e=E(this.entity);if(!E(\")\"))return null;if(t&&e)n.push(new i.Paren(new i.Rule(t,e,null,o,!0)));else{if(!e)return null;n.push(new i.Paren(e))}}while(e);if(n.length>0)return new i.Expression(n)},mediaFeatures:function(){var e,t=[];do if(e=E(this.mediaFeature)){t.push(e);if(!E(\",\"))break}else if(e=E(this.entities.variable)){t.push(e);if(!E(\",\"))break}while(e);return t.length>0?t:null},media:function(){var e,n,r,u;t.dumpLineNumbers&&(u=A(o,s,t));if(E(/^@media/)){e=E(this.mediaFeatures);if(n=E(this.block))return r=new i.Media(n,e),t.dumpLineNumbers&&(r.debugInfo=u),r}},directive:function(){var e,n,r,u,a,f,l,c,h,p;if(s.charAt(o)!==\"@\")return;if(n=E(this[\"import\"])||E(this.media))return n;g(),e=E(/^@[a-z-]+/);if(!e)return;l=e,e.charAt(1)==\"-\"&&e.indexOf(\"-\",2)>0&&(l=\"@\"+e.slice(e.indexOf(\"-\",2)+1));switch(l){case\"@font-face\":c=!0;break;case\"@viewport\":case\"@top-left\":case\"@top-left-corner\":case\"@top-center\":case\"@top-right\":case\"@top-right-corner\":case\"@bottom-left\":case\"@bottom-left-corner\":case\"@bottom-center\":case\"@bottom-right\":case\"@bottom-right-corner\":case\"@left-top\":case\"@left-middle\":case\"@left-bottom\":case\"@right-top\":case\"@right-middle\":case\"@right-bottom\":c=!0;break;case\"@page\":case\"@document\":case\"@supports\":case\"@keyframes\":c=!0,h=!0;break;case\"@namespace\":p=!0}h&&(e+=\" \"+(E(/^[^{]+/)||\"\").trim());if(c){if(r=E(this.block))return new i.Directive(e,r)}else if((n=p?E(this.expression):E(this.entity))&&E(\";\")){var d=new i.Directive(e,n);return t.dumpLineNumbers&&(d.debugInfo=A(o,s,t)),d}y()},font:function(){var e=[],t=[],n,r,s,o;while(o=E(this.shorthand)||E(this.entity))t.push(o);e.push(new i.Expression(t));if(E(\",\"))while(o=E(this.expression)){e.push(o);if(!E(\",\"))break}return new i.Value(e)},value:function(){var e,t=[],n;while(e=E(this.expression)){t.push(e);if(!E(\",\"))break}if(t.length>0)return new i.Value(t)},important:function(){if(s.charAt(o)===\"!\")return E(/^! *important/)},sub:function(){var e;if(E(\"(\")&&(e=E(this.expression))&&E(\")\"))return e},multiplication:function(){var e,t,n,r;if(e=E(this.operand)){while(!N(/^\\/[*\\/]/)&&(n=E(\"/\")||E(\"*\"))&&(t=E(this.operand)))r=new i.Operation(n,[r||e,t]);return r||e}},addition:function(){var e,t,n,r;if(e=E(this.multiplication)){while((n=E(/^[-+]\\s+/)||!w(s.charAt(o-1))&&(E(\"+\")||E(\"-\")))&&(t=E(this.multiplication)))r=new i.Operation(n,[r||e,t]);return r||e}},conditions:function(){var e,t,n=o,r;if(e=E(this.condition)){while(E(\",\")&&(t=E(this.condition)))r=new i.Condition(\"or\",r||e,t,n);return r||e}},condition:function(){var e,t,n,r,s=o,u=!1;E(/^not/)&&(u=!0),x(\"(\");if(e=E(this.addition)||E(this.entities.keyword)||E(this.entities.quoted))return(r=E(/^(?:>=|=<|[<=>])/))?(t=E(this.addition)||E(this.entities.keyword)||E(this.entities.quoted))?n=new i.Condition(r,e,t,s,u):T(\"expected expression\"):n=new i.Condition(\"=\",e,new i.Keyword(\"true\"),s,u),x(\")\"),E(/^and/)?new i.Condition(\"and\",n,E(this.condition)):n},operand:function(){var e,t=s.charAt(o+1);s.charAt(o)===\"-\"&&(t===\"@\"||t===\"(\")&&(e=E(\"-\"));var n=E(this.sub)||E(this.entities.dimension)||E(this.entities.color)||E(this.entities.variable)||E(this.entities.call);return e?new i.Operation(\"*\",[new i.Dimension(-1),n]):n},expression:function(){var e,t,n=[],r;while(e=E(this.addition)||E(this.entity))n.push(e);if(n.length>0)return new i.Expression(n)},property:function(){var e;if(e=E(/^(\\*?-?[_a-z0-9-]+)\\s*:/))return e[1]}}}};if(r.mode===\"browser\"||r.mode===\"rhino\")r.Parser.importer=function(e,t,n,r){!/^([a-z-]+:)?\\//.test(e)&&t.length>0&&(e=t[0]+e),w({href:e,title:e,type:r.mime,contents:r.contents,files:r.files,rootpath:r.rootpath,entryPath:r.entryPath,relativeUrls:r.relativeUrls},function(e,i,s,o,u,a){e&&typeof r.errback==\"function\"?r.errback.call(null,a,t,n,r):n.call(null,e,i,a)},!0)};(function(e){function t(t){return e.functions.hsla(t.h,t.s,t.l,t.a)}function n(t,n){return t instanceof e.Dimension&&t.unit==\"%\"?parseFloat(t.value*n/100):r(t)}function r(t){if(t instanceof e.Dimension)return parseFloat(t.unit==\"%\"?t.value/100:t.value);if(typeof t==\"number\")return t;throw{error:\"RuntimeError\",message:\"color functions take numbers as parameters\"}}function i(e){return Math.min(1,Math.max(0,e))}e.functions={rgb:function(e,t,n){return this.rgba(e,t,n,1)},rgba:function(t,i,s,o){var u=[t,i,s].map(function(e){return n(e,256)});return o=r(o),new e.Color(u,o)},hsl:function(e,t,n){return this.hsla(e,t,n,1)},hsla:function(e,t,n,i){function u(e){return e=e<0?e+1:e>1?e-1:e,e*6<1?o+(s-o)*e*6:e*2<1?s:e*3<2?o+(s-o)*(2/3-e)*6:o}e=r(e)%360/360,t=r(t),n=r(n),i=r(i);var s=n<=.5?n*(t+1):n+t-n*t,o=n*2-s;return this.rgba(u(e+1/3)*255,u(e)*255,u(e-1/3)*255,i)},hsv:function(e,t,n){return this.hsva(e,t,n,1)},hsva:function(e,t,n,i){e=r(e)%360/360*360,t=r(t),n=r(n),i=r(i);var s,o;s=Math.floor(e/60%6),o=e/60-s;var u=[n,n*(1-t),n*(1-o*t),n*(1-(1-o)*t)],a=[[0,3,1],[2,0,1],[1,0,3],[1,2,0],[3,1,0],[0,1,2]];return this.rgba(u[a[s][0]]*255,u[a[s][1]]*255,u[a[s][2]]*255,i)},hue:function(t){return new e.Dimension(Math.round(t.toHSL().h))},saturation:function(t){return new e.Dimension(Math.round(t.toHSL().s*100),\"%\")},lightness:function(t){return new e.Dimension(Math.round(t.toHSL().l*100),\"%\")},red:function(t){return new e.Dimension(t.rgb[0])},green:function(t){return new e.Dimension(t.rgb[1])},blue:function(t){return new e.Dimension(t.rgb[2])},alpha:function(t){return new e.Dimension(t.toHSL().a)},luma:function(t){return new e.Dimension(Math.round((.2126*(t.rgb[0]/255)+.7152*(t.rgb[1]/255)+.0722*(t.rgb[2]/255))*t.alpha*100),\"%\")},saturate:function(e,n){var r=e.toHSL();return r.s+=n.value/100,r.s=i(r.s),t(r)},desaturate:function(e,n){var r=e.toHSL();return r.s-=n.value/100,r.s=i(r.s),t(r)},lighten:function(e,n){var r=e.toHSL();return r.l+=n.value/100,r.l=i(r.l),t(r)},darken:function(e,n){var r=e.toHSL();return r.l-=n.value/100,r.l=i(r.l),t(r)},fadein:function(e,n){var r=e.toHSL();return r.a+=n.value/100,r.a=i(r.a),t(r)},fadeout:function(e,n){var r=e.toHSL();return r.a-=n.value/100,r.a=i(r.a),t(r)},fade:function(e,n){var r=e.toHSL();return r.a=n.value/100,r.a=i(r.a),t(r)},spin:function(e,n){var r=e.toHSL(),i=(r.h+n.value)%360;return r.h=i<0?360+i:i,t(r)},mix:function(t,n,r){r||(r=new e.Dimension(50));var i=r.value/100,s=i*2-1,o=t.toHSL().a-n.toHSL().a,u=((s*o==-1?s:(s+o)/(1+s*o))+1)/2,a=1-u,f=[t.rgb[0]*u+n.rgb[0]*a,t.rgb[1]*u+n.rgb[1]*a,t.rgb[2]*u+n.rgb[2]*a],l=t.alpha*i+n.alpha*(1-i);return new e.Color(f,l)},greyscale:function(t){return this.desaturate(t,new e.Dimension(100))},contrast:function(e,t,n,r){return e.rgb?(typeof n==\"undefined\"&&(n=this.rgba(255,255,255,1)),typeof t==\"undefined\"&&(t=this.rgba(0,0,0,1)),typeof r==\"undefined\"?r=.43:r=r.value,(.2126*(e.rgb[0]/255)+.7152*(e.rgb[1]/255)+.0722*(e.rgb[2]/255))*e.alpha<r?n:t):null},e:function(t){return new e.Anonymous(t instanceof e.JavaScript?t.evaluated:t)},escape:function(t){return new e.Anonymous(encodeURI(t.value).replace(/=/g,\"%3D\").replace(/:/g,\"%3A\").replace(/#/g,\"%23\").replace(/;/g,\"%3B\").replace(/\\(/g,\"%28\").replace(/\\)/g,\"%29\"))},\"%\":function(t){var n=Array.prototype.slice.call(arguments,1),r=t.value;for(var i=0;i<n.length;i++)r=r.replace(/%[sda]/i,function(e){var t=e.match(/s/i)?n[i].value:n[i].toCSS();return e.match(/[A-Z]$/)?encodeURIComponent(t):t});return r=r.replace(/%%/g,\"%\"),new e.Quoted('\"'+r+'\"',r)},unit:function(t,n){return new e.Dimension(t.value,n?n.toCSS():\"\")},round:function(e,t){var n=typeof t==\"undefined\"?0:t.value;return this._math(function(e){return e.toFixed(n)},e)},ceil:function(e){return this._math(Math.ceil,e)},floor:function(e){return this._math(Math.floor,e)},_math:function(t,n){if(n instanceof e.Dimension)return new e.Dimension(t(parseFloat(n.value)),n.unit);if(typeof n==\"number\")return t(n);throw{type:\"Argument\",message:\"argument must be a number\"}},argb:function(t){return new e.Anonymous(t.toARGB())},percentage:function(t){return new e.Dimension(t.value*100,\"%\")},color:function(t){if(t instanceof e.Quoted)return new e.Color(t.value.slice(1));throw{type:\"Argument\",message:\"argument must be a string\"}},iscolor:function(t){return this._isa(t,e.Color)},isnumber:function(t){return this._isa(t,e.Dimension)},isstring:function(t){return this._isa(t,e.Quoted)},iskeyword:function(t){return this._isa(t,e.Keyword)},isurl:function(t){return this._isa(t,e.URL)},ispixel:function(t){return t instanceof e.Dimension&&t.unit===\"px\"?e.True:e.False},ispercentage:function(t){return t instanceof e.Dimension&&t.unit===\"%\"?e.True:e.False},isem:function(t){return t instanceof e.Dimension&&t.unit===\"em\"?e.True:e.False},_isa:function(t,n){return t instanceof n?e.True:e.False},multiply:function(e,t){var n=e.rgb[0]*t.rgb[0]/255,r=e.rgb[1]*t.rgb[1]/255,i=e.rgb[2]*t.rgb[2]/255;return this.rgb(n,r,i)},screen:function(e,t){var n=255-(255-e.rgb[0])*(255-t.rgb[0])/255,r=255-(255-e.rgb[1])*(255-t.rgb[1])/255,i=255-(255-e.rgb[2])*(255-t.rgb[2])/255;return this.rgb(n,r,i)},overlay:function(e,t){var n=e.rgb[0]<128?2*e.rgb[0]*t.rgb[0]/255:255-2*(255-e.rgb[0])*(255-t.rgb[0])/255,r=e.rgb[1]<128?2*e.rgb[1]*t.rgb[1]/255:255-2*(255-e.rgb[1])*(255-t.rgb[1])/255,i=e.rgb[2]<128?2*e.rgb[2]*t.rgb[2]/255:255-2*(255-e.rgb[2])*(255-t.rgb[2])/255;return this.rgb(n,r,i)},softlight:function(e,t){var n=t.rgb[0]*e.rgb[0]/255,r=n+e.rgb[0]*(255-(255-e.rgb[0])*(255-t.rgb[0])/255-n)/255;n=t.rgb[1]*e.rgb[1]/255;var i=n+e.rgb[1]*(255-(255-e.rgb[1])*(255-t.rgb[1])/255-n)/255;n=t.rgb[2]*e.rgb[2]/255;var s=n+e.rgb[2]*(255-(255-e.rgb[2])*(255-t.rgb[2])/255-n)/255;return this.rgb(r,i,s)},hardlight:function(e,t){var n=t.rgb[0]<128?2*t.rgb[0]*e.rgb[0]/255:255-2*(255-t.rgb[0])*(255-e.rgb[0])/255,r=t.rgb[1]<128?2*t.rgb[1]*e.rgb[1]/255:255-2*(255-t.rgb[1])*(255-e.rgb[1])/255,i=t.rgb[2]<128?2*t.rgb[2]*e.rgb[2]/255:255-2*(255-t.rgb[2])*(255-e.rgb[2])/255;return this.rgb(n,r,i)},difference:function(e,t){var n=Math.abs(e.rgb[0]-t.rgb[0]),r=Math.abs(e.rgb[1]-t.rgb[1]),i=Math.abs(e.rgb[2]-t.rgb[2]);return this.rgb(n,r,i)},exclusion:function(e,t){var n=e.rgb[0]+t.rgb[0]*(255-e.rgb[0]-e.rgb[0])/255,r=e.rgb[1]+t.rgb[1]*(255-e.rgb[1]-e.rgb[1])/255,i=e.rgb[2]+t.rgb[2]*(255-e.rgb[2]-e.rgb[2])/255;return this.rgb(n,r,i)},average:function(e,t){var n=(e.rgb[0]+t.rgb[0])/2,r=(e.rgb[1]+t.rgb[1])/2,i=(e.rgb[2]+t.rgb[2])/2;return this.rgb(n,r,i)},negation:function(e,t){var n=255-Math.abs(255-t.rgb[0]-e.rgb[0]),r=255-Math.abs(255-t.rgb[1]-e.rgb[1]),i=255-Math.abs(255-t.rgb[2]-e.rgb[2]);return this.rgb(n,r,i)},tint:function(e,t){return this.mix(this.rgb(255,255,255),e,t)},shade:function(e,t){return this.mix(this.rgb(0,0,0),e,t)}}})(n(\"./tree\")),function(e){e.colors={aliceblue:\"#f0f8ff\",antiquewhite:\"#faebd7\",aqua:\"#00ffff\",aquamarine:\"#7fffd4\",azure:\"#f0ffff\",beige:\"#f5f5dc\",bisque:\"#ffe4c4\",black:\"#000000\",blanchedalmond:\"#ffebcd\",blue:\"#0000ff\",blueviolet:\"#8a2be2\",brown:\"#a52a2a\",burlywood:\"#deb887\",cadetblue:\"#5f9ea0\",chartreuse:\"#7fff00\",chocolate:\"#d2691e\",coral:\"#ff7f50\",cornflowerblue:\"#6495ed\",cornsilk:\"#fff8dc\",crimson:\"#dc143c\",cyan:\"#00ffff\",darkblue:\"#00008b\",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:\"#ff00ff\",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:\"#778899\",lightslategrey:\"#778899\",lightsteelblue:\"#b0c4de\",lightyellow:\"#ffffe0\",lime:\"#00ff00\",limegreen:\"#32cd32\",linen:\"#faf0e6\",magenta:\"#ff00ff\",maroon:\"#800000\",mediumaquamarine:\"#66cdaa\",mediumblue:\"#0000cd\",mediumorchid:\"#ba55d3\",mediumpurple:\"#9370d8\",mediumseagreen:\"#3cb371\",mediumslateblue:\"#7b68ee\",mediumspringgreen:\"#00fa9a\",mediumturquoise:\"#48d1cc\",mediumvioletred:\"#c71585\",midnightblue:\"#191970\",mintcream:\"#f5fffa\",mistyrose:\"#ffe4e1\",moccasin:\"#ffe4b5\",navajowhite:\"#ffdead\",navy:\"#000080\",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:\"#ff0000\",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:\"#ffffff\",whitesmoke:\"#f5f5f5\",yellow:\"#ffff00\",yellowgreen\n:\"#9acd32\"}}(n(\"./tree\")),function(e){e.Alpha=function(e){this.value=e},e.Alpha.prototype={toCSS:function(){return\"alpha(opacity=\"+(this.value.toCSS?this.value.toCSS():this.value)+\")\"},eval:function(e){return this.value.eval&&(this.value=this.value.eval(e)),this}}}(n(\"../tree\")),function(e){e.Anonymous=function(e){this.value=e.value||e},e.Anonymous.prototype={toCSS:function(){return this.value},eval:function(){return this},compare:function(e){if(!e.toCSS)return-1;var t=this.toCSS(),n=e.toCSS();return t===n?0:t<n?-1:1}}}(n(\"../tree\")),function(e){e.Assignment=function(e,t){this.key=e,this.value=t},e.Assignment.prototype={toCSS:function(){return this.key+\"=\"+(this.value.toCSS?this.value.toCSS():this.value)},eval:function(t){return this.value.eval?new e.Assignment(this.key,this.value.eval(t)):this}}}(n(\"../tree\")),function(e){e.Call=function(e,t,n,r){this.name=e,this.args=t,this.index=n,this.filename=r},e.Call.prototype={eval:function(t){var n=this.args.map(function(e){return e.eval(t)}),r;if(this.name in e.functions)try{r=e.functions[this.name].apply(e.functions,n);if(r!=null)return r}catch(i){throw{type:i.type||\"Runtime\",message:\"error evaluating function `\"+this.name+\"`\"+(i.message?\": \"+i.message:\"\"),index:this.index,filename:this.filename}}return new e.Anonymous(this.name+\"(\"+n.map(function(e){return e.toCSS(t)}).join(\", \")+\")\")},toCSS:function(e){return this.eval(e).toCSS()}}}(n(\"../tree\")),function(e){e.Color=function(e,t){Array.isArray(e)?this.rgb=e:e.length==6?this.rgb=e.match(/.{2}/g).map(function(e){return parseInt(e,16)}):this.rgb=e.split(\"\").map(function(e){return parseInt(e+e,16)}),this.alpha=typeof t==\"number\"?t:1},e.Color.prototype={eval:function(){return this},toCSS:function(){return this.alpha<1?\"rgba(\"+this.rgb.map(function(e){return Math.round(e)}).concat(this.alpha).join(\", \")+\")\":\"#\"+this.rgb.map(function(e){return e=Math.round(e),e=(e>255?255:e<0?0:e).toString(16),e.length===1?\"0\"+e:e}).join(\"\")},operate:function(t,n){var r=[];n instanceof e.Color||(n=n.toColor());for(var i=0;i<3;i++)r[i]=e.operate(t,this.rgb[i],n.rgb[i]);return new e.Color(r,this.alpha+n.alpha)},toHSL:function(){var e=this.rgb[0]/255,t=this.rgb[1]/255,n=this.rgb[2]/255,r=this.alpha,i=Math.max(e,t,n),s=Math.min(e,t,n),o,u,a=(i+s)/2,f=i-s;if(i===s)o=u=0;else{u=a>.5?f/(2-i-s):f/(i+s);switch(i){case e:o=(t-n)/f+(t<n?6:0);break;case t:o=(n-e)/f+2;break;case n:o=(e-t)/f+4}o/=6}return{h:o*360,s:u,l:a,a:r}},toARGB:function(){var e=[Math.round(this.alpha*255)].concat(this.rgb);return\"#\"+e.map(function(e){return e=Math.round(e),e=(e>255?255:e<0?0:e).toString(16),e.length===1?\"0\"+e:e}).join(\"\")},compare:function(e){return e.rgb?e.rgb[0]===this.rgb[0]&&e.rgb[1]===this.rgb[1]&&e.rgb[2]===this.rgb[2]&&e.alpha===this.alpha?0:-1:-1}}}(n(\"../tree\")),function(e){e.Comment=function(e,t){this.value=e,this.silent=!!t},e.Comment.prototype={toCSS:function(e){return e.compress?\"\":this.value},eval:function(){return this}}}(n(\"../tree\")),function(e){e.Condition=function(e,t,n,r,i){this.op=e.trim(),this.lvalue=t,this.rvalue=n,this.index=r,this.negate=i},e.Condition.prototype.eval=function(e){var t=this.lvalue.eval(e),n=this.rvalue.eval(e),r=this.index,i,i=function(e){switch(e){case\"and\":return t&&n;case\"or\":return t||n;default:if(t.compare)i=t.compare(n);else{if(!n.compare)throw{type:\"Type\",message:\"Unable to perform comparison\",index:r};i=n.compare(t)}switch(i){case-1:return e===\"<\"||e===\"=<\";case 0:return e===\"=\"||e===\">=\"||e===\"=<\";case 1:return e===\">\"||e===\">=\"}}}(this.op);return this.negate?!i:i}}(n(\"../tree\")),function(e){e.Dimension=function(e,t){this.value=parseFloat(e),this.unit=t||null},e.Dimension.prototype={eval:function(){return this},toColor:function(){return new e.Color([this.value,this.value,this.value])},toCSS:function(){var e=this.value+this.unit;return e},operate:function(t,n){return new e.Dimension(e.operate(t,this.value,n.value),this.unit||n.unit)},compare:function(t){return t instanceof e.Dimension?t.value>this.value?-1:t.value<this.value?1:t.unit&&this.unit!==t.unit?-1:0:-1}}}(n(\"../tree\")),function(e){e.Directive=function(t,n){this.name=t,Array.isArray(n)?(this.ruleset=new e.Ruleset([],n),this.ruleset.allowImports=!0):this.value=n},e.Directive.prototype={toCSS:function(e,t){return this.ruleset?(this.ruleset.root=!0,this.name+(t.compress?\"{\":\" {\\n  \")+this.ruleset.toCSS(e,t).trim().replace(/\\n/g,\"\\n  \")+(t.compress?\"}\":\"\\n}\\n\")):this.name+\" \"+this.value.toCSS()+\";\\n\"},eval:function(t){var n=this;return this.ruleset&&(t.frames.unshift(this),n=new e.Directive(this.name),n.ruleset=this.ruleset.eval(t),t.frames.shift()),n},variable:function(t){return e.Ruleset.prototype.variable.call(this.ruleset,t)},find:function(){return e.Ruleset.prototype.find.apply(this.ruleset,arguments)},rulesets:function(){return e.Ruleset.prototype.rulesets.apply(this.ruleset)}}}(n(\"../tree\")),function(e){e.Element=function(t,n,r){this.combinator=t instanceof e.Combinator?t:new e.Combinator(t),typeof n==\"string\"?this.value=n.trim():n?this.value=n:this.value=\"\",this.index=r},e.Element.prototype.eval=function(t){return new e.Element(this.combinator,this.value.eval?this.value.eval(t):this.value,this.index)},e.Element.prototype.toCSS=function(e){var t=this.value.toCSS?this.value.toCSS(e):this.value;return t==\"\"&&this.combinator.value.charAt(0)==\"&\"?\"\":this.combinator.toCSS(e||{})+t},e.Combinator=function(e){e===\" \"?this.value=\" \":this.value=e?e.trim():\"\"},e.Combinator.prototype.toCSS=function(e){return{\"\":\"\",\" \":\" \",\":\":\" :\",\"+\":e.compress?\"+\":\" + \",\"~\":e.compress?\"~\":\" ~ \",\">\":e.compress?\">\":\" > \",\"|\":e.compress?\"|\":\" | \"}[this.value]}}(n(\"../tree\")),function(e){e.Expression=function(e){this.value=e},e.Expression.prototype={eval:function(t){return this.value.length>1?new e.Expression(this.value.map(function(e){return e.eval(t)})):this.value.length===1?this.value[0].eval(t):this},toCSS:function(e){return this.value.map(function(t){return t.toCSS?t.toCSS(e):\"\"}).join(\" \")}}}(n(\"../tree\")),function(e){e.Import=function(t,n,r,i,s,o){var u=this;this.once=i,this.index=s,this._path=t,this.features=r&&new e.Value(r),this.rootpath=o,t instanceof e.Quoted?this.path=/(\\.[a-z]*$)|([\\?;].*)$/.test(t.value)?t.value:t.value+\".less\":this.path=t.value.value||t.value,this.css=/css([\\?;].*)?$/.test(this.path),this.css||n.push(this.path,function(t,n,r){t&&(t.index=s),r&&u.once&&(u.skip=r),u.root=n||new e.Ruleset([],[])})},e.Import.prototype={toCSS:function(e){var t=this.features?\" \"+this.features.toCSS(e):\"\";return this.css?(typeof this._path.value==\"string\"&&!/^(?:[a-z-]+:|\\/)/.test(this._path.value)&&(this._path.value=this.rootpath+this._path.value),\"@import \"+this._path.toCSS()+t+\";\\n\"):\"\"},eval:function(t){var n,r=this.features&&this.features.eval(t);return this.skip?[]:this.css?this:(n=new e.Ruleset([],this.root.rules.slice(0)),n.evalImports(t),this.features?new e.Media(n.rules,this.features.value):n.rules)}}}(n(\"../tree\")),function(e){e.JavaScript=function(e,t,n){this.escaped=n,this.expression=e,this.index=t},e.JavaScript.prototype={eval:function(t){var n,r=this,i={},s=this.expression.replace(/@\\{([\\w-]+)\\}/g,function(n,i){return e.jsify((new e.Variable(\"@\"+i,r.index)).eval(t))});try{s=new Function(\"return (\"+s+\")\")}catch(o){throw{message:\"JavaScript evaluation error: `\"+s+\"`\",index:this.index}}for(var u in t.frames[0].variables())i[u.slice(1)]={value:t.frames[0].variables()[u].value,toJS:function(){return this.value.eval(t).toCSS()}};try{n=s.call(i)}catch(o){throw{message:\"JavaScript evaluation error: '\"+o.name+\": \"+o.message+\"'\",index:this.index}}return typeof n==\"string\"?new e.Quoted('\"'+n+'\"',n,this.escaped,this.index):Array.isArray(n)?new e.Anonymous(n.join(\", \")):new e.Anonymous(n)}}}(n(\"../tree\")),function(e){e.Keyword=function(e){this.value=e},e.Keyword.prototype={eval:function(){return this},toCSS:function(){return this.value},compare:function(t){return t instanceof e.Keyword?t.value===this.value?0:1:-1}},e.True=new e.Keyword(\"true\"),e.False=new e.Keyword(\"false\")}(n(\"../tree\")),function(e){e.Media=function(t,n){var r=this.emptySelectors();this.features=new e.Value(n),this.ruleset=new e.Ruleset(r,t),this.ruleset.allowImports=!0},e.Media.prototype={toCSS:function(e,t){var n=this.features.toCSS(t);return this.ruleset.root=e.length===0||e[0].multiMedia,\"@media \"+n+(t.compress?\"{\":\" {\\n  \")+this.ruleset.toCSS(e,t).trim().replace(/\\n/g,\"\\n  \")+(t.compress?\"}\":\"\\n}\\n\")},eval:function(t){t.mediaBlocks||(t.mediaBlocks=[],t.mediaPath=[]);var n=new e.Media([],[]);return this.debugInfo&&(this.ruleset.debugInfo=this.debugInfo,n.debugInfo=this.debugInfo),n.features=this.features.eval(t),t.mediaPath.push(n),t.mediaBlocks.push(n),t.frames.unshift(this.ruleset),n.ruleset=this.ruleset.eval(t),t.frames.shift(),t.mediaPath.pop(),t.mediaPath.length===0?n.evalTop(t):n.evalNested(t)},variable:function(t){return e.Ruleset.prototype.variable.call(this.ruleset,t)},find:function(){return e.Ruleset.prototype.find.apply(this.ruleset,arguments)},rulesets:function(){return e.Ruleset.prototype.rulesets.apply(this.ruleset)},emptySelectors:function(){var t=new e.Element(\"\",\"&\",0);return[new e.Selector([t])]},evalTop:function(t){var n=this;if(t.mediaBlocks.length>1){var r=this.emptySelectors();n=new e.Ruleset(r,t.mediaBlocks),n.multiMedia=!0}return delete t.mediaBlocks,delete t.mediaPath,n},evalNested:function(t){var n,r,i=t.mediaPath.concat([this]);for(n=0;n<i.length;n++)r=i[n].features instanceof e.Value?i[n].features.value:i[n].features,i[n]=Array.isArray(r)?r:[r];return this.features=new e.Value(this.permute(i).map(function(t){t=t.map(function(t){return t.toCSS?t:new e.Anonymous(t)});for(n=t.length-1;n>0;n--)t.splice(n,0,new e.Anonymous(\"and\"));return new e.Expression(t)})),new e.Ruleset([],[])},permute:function(e){if(e.length===0)return[];if(e.length===1)return e[0];var t=[],n=this.permute(e.slice(1));for(var r=0;r<n.length;r++)for(var i=0;i<e[0].length;i++)t.push([e[0][i]].concat(n[r]));return t},bubbleSelectors:function(t){this.ruleset=new e.Ruleset(t.slice(0),[this.ruleset])}}}(n(\"../tree\")),function(e){e.mixin={},e.mixin.Call=function(t,n,r,i,s){this.selector=new e.Selector(t),this.arguments=n,this.index=r,this.filename=i,this.important=s},e.mixin.Call.prototype={eval:function(t){var n,r,i,s=[],o=!1,u,a,f,l,c;i=this.arguments&&this.arguments.map(function(e){return{name:e.name,value:e.value.eval(t)}});for(u=0;u<t.frames.length;u++)if((n=t.frames[u].find(this.selector)).length>0){c=!0;for(a=0;a<n.length;a++){r=n[a],l=!1;for(f=0;f<t.frames.length;f++)if(!(r instanceof e.mixin.Definition)&&r===(t.frames[f].originalRuleset||t.frames[f])){l=!0;break}if(l)continue;if(r.matchArgs(i,t)){if(!r.matchCondition||r.matchCondition(i,t))try{Array.prototype.push.apply(s,r.eval(t,i,this.important).rules)}catch(h){throw{message:h.message,index:this.index,filename:this.filename,stack:h.stack}}o=!0}}if(o)return s}throw c?{type:\"Runtime\",message:\"No matching definition was found for `\"+this.selector.toCSS().trim()+\"(\"+(i?i.map(function(e){var t=\"\";return e.name&&(t+=e.name+\":\"),e.value.toCSS?t+=e.value.toCSS():t+=\"???\",t}).join(\", \"):\"\")+\")`\",index:this.index,filename:this.filename}:{type:\"Name\",message:this.selector.toCSS().trim()+\" is undefined\",index:this.index,filename:this.filename}}},e.mixin.Definition=function(t,n,r,i,s){this.name=t,this.selectors=[new e.Selector([new e.Element(null,t)])],this.params=n,this.condition=i,this.variadic=s,this.arity=n.length,this.rules=r,this._lookups={},this.required=n.reduce(function(e,t){return!t.name||t.name&&!t.value?e+1:e},0),this.parent=e.Ruleset.prototype,this.frames=[]},e.mixin.Definition.prototype={toCSS:function(){return\"\"},variable:function(e){return this.parent.variable.call(this,e)},variables:function(){return this.parent.variables.call(this)},find:function(){return this.parent.find.apply(this,arguments)},rulesets:function(){return this.parent.rulesets.apply(this)},evalParams:function(t,n,r,i){var s=new e.Ruleset(null,[]),o,u,a=this.params.slice(0),f,l,c,h,p,d;if(r){r=r.slice(0);for(f=0;f<r.length;f++){u=r[f];if(h=u&&u.name){p=!1;for(l=0;l<a.length;l++)if(!i[l]&&h===a[l].name){i[l]=u.value.eval(t),s.rules.unshift(new e.Rule(h,u.value.eval(t))),p=!0;break}if(p){r.splice(f,1),f--;continue}throw{type:\"Runtime\",message:\"Named argument for \"+this.name+\" \"+r[f].name+\" not found\"}}}}d=0;for(f=0;f<a.length;f++){if(i[f])continue;u=r&&r[d];if(h=a[f].name)if(a[f].variadic&&r){o=[];for(l=d;l<r.length;l++)o.push(r[l].value.eval(t));s.rules.unshift(new e.Rule(h,(new e.Expression(o)).eval(t)))}else{c=u&&u.value;if(c)c=c.eval(t);else{if(!a[f].value)throw{type:\"Runtime\",message:\"wrong number of arguments for \"+this.name+\" (\"+r.length+\" for \"+this.arity+\")\"};c=a[f].value.eval(n)}s.rules.unshift(new e.Rule(h,c)),i[f]=c}if(a[f].variadic&&r)for(l=d;l<r.length;l++)i[l]=r[l].value.eval(t);d++}return s},eval:function(t,n,r){var i=[],s=this.frames.concat(t.frames),o=this.evalParams(t,{frames:s},n,i),u,a,f,l;return o.rules.unshift(new e.Rule(\"@arguments\",(new e.Expression(i)).eval(t))),a=r?this.parent.makeImportant.apply(this).rules:this.rules.slice(0),l=(new e.Ruleset(null,a)).eval({frames:[this,o].concat(s)}),l.originalRuleset=this,l},matchCondition:function(e,t){return this.condition&&!this.condition.eval({frames:[this.evalParams(t,{frames:this.frames.concat(t.frames)},e,[])].concat(t.frames)})?!1:!0},matchArgs:function(e,t){var n=e&&e.length||0,r,i;if(!this.variadic){if(n<this.required)return!1;if(n>this.params.length)return!1;if(this.required>0&&n>this.params.length)return!1}r=Math.min(n,this.arity);for(var s=0;s<r;s++)if(!this.params[s].name&&!this.params[s].variadic&&e[s].value.eval(t).toCSS()!=this.params[s].value.eval(t).toCSS())return!1;return!0}}}(n(\"../tree\")),function(e){e.Operation=function(e,t){this.op=e.trim(),this.operands=t},e.Operation.prototype.eval=function(t){var n=this.operands[0].eval(t),r=this.operands[1].eval(t),i;if(n instanceof e.Dimension&&r instanceof e.Color){if(this.op!==\"*\"&&this.op!==\"+\")throw{name:\"OperationError\",message:\"Can't substract or divide a color from a number\"};i=r,r=n,n=i}if(!n.operate)throw{name:\"OperationError\",message:\"Operation on an invalid type\"};return n.operate(this.op,r)},e.operate=function(e,t,n){switch(e){case\"+\":return t+n;case\"-\":return t-n;case\"*\":return t*n;case\"/\":return t/n}}}(n(\"../tree\")),function(e){e.Paren=function(e){this.value=e},e.Paren.prototype={toCSS:function(e){return\"(\"+this.value.toCSS(e)+\")\"},eval:function(t){return new e.Paren(this.value.eval(t))}}}(n(\"../tree\")),function(e){e.Quoted=function(e,t,n,r){this.escaped=n,this.value=t||\"\",this.quote=e.charAt(0),this.index=r},e.Quoted.prototype={toCSS:function(){return this.escaped?this.value:this.quote+this.value+this.quote},eval:function(t){var n=this,r=this.value.replace(/`([^`]+)`/g,function(r,i){return(new e.JavaScript(i,n.index,!0)).eval(t).value}).replace(/@\\{([\\w-]+)\\}/g,function(r,i){var s=(new e.Variable(\"@\"+i,n.index)).eval(t);return s instanceof e.Quoted?s.value:s.toCSS()});return new e.Quoted(this.quote+r+this.quote,r,this.escaped,this.index)},compare:function(e){if(!e.toCSS)return-1;var t=this.toCSS(),n=e.toCSS();return t===n?0:t<n?-1:1}}}(n(\"../tree\")),function(e){e.Ratio=function(e){this.value=e},e.Ratio.prototype={toCSS:function(e){return this.value},eval:function(){return this}}}(n(\"../tree\")),function(e){e.Rule=function(t,n,r,i,s){this.name=t,this.value=n instanceof e.Value?n:new e.Value([n]),this.important=r?\" \"+r.trim():\"\",this.index=i,this.inline=s||!1,t.charAt(0)===\"@\"?this.variable=!0:this.variable=!1},e.Rule.prototype.toCSS=function(e){return this.variable?\"\":this.name+(e.compress?\":\":\": \")+this.value.toCSS(e)+this.important+(this.inline?\"\":\";\")},e.Rule.prototype.eval=function(t){return new e.Rule(this.name,this.value.eval(t),this.important,this.index,this.inline)},e.Rule.prototype.makeImportant=function(){return new e.Rule(this.name,this.value,\"!important\",this.index,this.inline)},e.Shorthand=function(e,t){this.a=e,this.b=t},e.Shorthand.prototype={toCSS:function(e){return this.a.toCSS(e)+\"/\"+this.b.toCSS(e)},eval:function(){return this}}}(n(\"../tree\")),function(e){e.Ruleset=function(e,t,n){this.selectors=e,this.rules=t,this._lookups={},this.strictImports=n},e.Ruleset.prototype={eval:function(t){var n=this.selectors&&this.selectors.map(function(e){return e.eval(t)}),r=new e.Ruleset(n,this.rules.slice(0),this.strictImports),i;r.originalRuleset=this,r.root=this.root,r.allowImports=this.allowImports,this.debugInfo&&(r.debugInfo=this.debugInfo),t.frames.unshift(r),(r.root||r.allowImports||!r.strictImports)&&r.evalImports(t);for(var s=0;s<r.rules.length;s++)r.rules[s]instanceof e.mixin.Definition&&(r.rules[s].frames=t.frames.slice(0));var o=t.mediaBlocks&&t.mediaBlocks.length||0;for(var s=0;s<r.rules.length;s++)r.rules[s]instanceof e.mixin.Call&&(i=r.rules[s].eval(t),r.rules.splice.apply(r.rules,[s,1].concat(i)),s+=i.length-1,r.resetCache());for(var s=0,u;s<r.rules.length;s++)u=r.rules[s],u instanceof e.mixin.Definition||(r.rules[s]=u.eval?u.eval(t):u);t.frames.shift();if(t.mediaBlocks)for(var s=o;s<t.mediaBlocks.length;s++)t.mediaBlocks[s].bubbleSelectors(n);return r},evalImports:function(t){var n,r;for(n=0;n<this.rules.length;n++)this.rules[n]instanceof e.Import&&(r=this.rules[n].eval(t),typeof r.length==\"number\"?(this.rules.splice.apply(this.rules,[n,1].concat(r)),n+=r.length-1):this.rules.splice(n,1,r),this.resetCache())},makeImportant:function(){return new e.Ruleset(this.selectors,this.rules.map(function(e){return e.makeImportant?e.makeImportant():e}),this.strictImports)},matchArgs:function(e){return!e||e.length===0},resetCache:function(){this._rulesets=null,this._variables=null,this._lookups={}},variables:function(){return this._variables?this._variables:this._variables=this.rules.reduce(function(t,n){return n instanceof e.Rule&&n.variable===!0&&(t[n.name]=n),t},{})},variable:function(e){return this.variables()[e]},rulesets:function(){return this._rulesets?this._rulesets:this._rulesets=this.rules.filter(function(t){return t instanceof e.Ruleset||t instanceof e.mixin.Definition})},find:function(t,n){n=n||this;var r=[],i,s,o=t.toCSS();return o in this._lookups?this._lookups[o]:(this.rulesets().forEach(function(i){if(i!==n)for(var o=0;o<i.selectors.length;o++)if(s=t.match(i.selectors[o])){t.elements.length>i.selectors[o].elements.length?Array.prototype.push.apply(r,i.find(new e.Selector(t.elements.slice(1)),n)):r.push(i);break}}),this._lookups[o]=r)},toCSS:function(t,n){var r=[],i=[],s=[],o=[],u=[],a,f,l;this.root||this.joinSelectors(u,t,this.selectors);for(var c=0;c<this.rules.length;c++){l=this.rules[c];if(l.rules||l instanceof e.Media)o.push(l.toCSS(u,n));else if(l instanceof e.Directive){var h=l.toCSS(u,n);if(l.name===\"@charset\"){if(n.charset){l.debugInfo&&(o.push(e.debugInfo(n,l)),o.push((new e.Comment(\"/* \"+h.replace(/\\n/g,\"\")+\" */\\n\")).toCSS(n)));continue}n.charset=!0}o.push(h)}else l instanceof e.Comment?l.silent||(this.root?o.push(l.toCSS(n)):i.push(l.toCSS(n))):l.toCSS&&!l.variable?i.push(l.toCSS(n)):l.value&&!l.variable&&i.push(l.value.toString())}o=o.join(\"\");if(this.root)r.push(i.join(n.compress?\"\":\"\\n\"));else if(i.length>0){f=e.debugInfo(n,this),a=u.map(function(e){return e.map(function(e){return e.toCSS(n)}).join(\"\").trim()}).join(n.compress?\",\":\",\\n\");for(var c=i.length-1;c>=0;c--)s.indexOf(i[c])===-1&&s.unshift(i[c]);i=s,r.push(f+a+(n.compress?\"{\":\" {\\n  \")+i.join(n.compress?\"\":\"\\n  \")+(n.compress?\"}\":\"\\n}\\n\"))}return r.push(o),r.join(\"\")+(n.compress?\"\\n\":\"\")},joinSelectors:function(e,t,n){for(var r=0;r<n.length;r++)this.joinSelector(e,t,n[r])},joinSelector:function(t,n,r){var i,s,o,u,a,f,l,c,h,p,d,v,m,g,y;for(i=0;i<r.elements.length;i++)f=r.elements[i],f.value===\"&\"&&(u=!0);if(!u){if(n.length>0)for(i=0;i<n.length;i++)t.push(n[i].concat(r));else t.push([r]);return}g=[],a=[[]];for(i=0;i<r.elements.length;i++){f=r.elements[i];if(f.value!==\"&\")g.push(f);else{y=[],g.length>0&&this.mergeElementsOnToSelectors(g,a);for(s=0;s<a.length;s++){l=a[s];if(n.length==0)l.length>0&&(l[0].elements=l[0].elements.slice(0),l[0].elements.push(new e.Element(f.combinator,\"\",0))),y.push(l);else for(o=0;o<n.length;o++)c=n[o],h=[],p=[],v=!0,l.length>0?(h=l.slice(0),m=h.pop(),d=new e.Selector(m.elements.slice(0)),v=!1):d=new e.Selector([]),c.length>1&&(p=p.concat(c.slice(1))),c.length>0&&(v=!1,d.elements.push(new e.Element(f.combinator,c[0].elements[0].value,0)),d.elements=d.elements.concat(c[0].elements.slice(1))),v||h.push(d),h=h.concat(p),y.push(h)}a=y,g=[]}}g.length>0&&this.mergeElementsOnToSelectors(g,a);for(i=0;i<a.length;i++)t.push(a[i])},mergeElementsOnToSelectors:function(t,n){var r,i;if(n.length==0){n.push([new e.Selector(t)]);return}for(r=0;r<n.length;r++)i=n[r],i.length>0?i[i.length-1]=new e.Selector(i[i.length-1].elements.concat(t)):i.push(new e.Selector(t))}}}(n(\"../tree\")),function(e){e.Selector=function(e){this.elements=e},e.Selector.prototype.match=function(e){var t=this.elements,n=t.length,r,i,s,o;r=e.elements.slice(e.elements.length&&e.elements[0].value===\"&\"?1:0),i=r.length,s=Math.min(n,i);if(i===0||n<i)return!1;for(o=0;o<s;o++)if(t[o].value!==r[o].value)return!1;return!0},e.Selector.prototype.eval=function(t){return new e.Selector(this.elements.map(function(e){return e.eval(t)}))},e.Selector.prototype.toCSS=function(e){return this._css?this._css:(this.elements[0].combinator.value===\"\"?this._css=\" \":this._css=\"\",this._css+=this.elements.map(function(t){return typeof t==\"string\"?\" \"+t.trim():t.toCSS(e)}).join(\"\"),this._css)}}(n(\"../tree\")),function(e){e.UnicodeDescriptor=function(e){this.value=e},e.UnicodeDescriptor.prototype={toCSS:function(e){return this.value},eval:function(){return this}}}(n(\"../tree\")),function(e){e.URL=function(e,t){this.value=e,this.rootpath=t},e.URL.prototype={toCSS:function(){return\"url(\"+this.value.toCSS()+\")\"},eval:function(t){var n=this.value.eval(t),r;return typeof n.value==\"string\"&&!/^(?:[a-z-]+:|\\/)/.test(n.value)&&(r=this.rootpath,n.quote||(r=r.replace(/[\\(\\)'\"\\s]/g,function(e){return\"\\\\\"+e})),n.value=r+n.value),new e.URL(n,this.rootpath)}}}(n(\"../tree\")),function(e){e.Value=function(e){this.value=e,this.is=\"value\"},e.Value.prototype={eval:function(t){return this.value.length===1?this.value[0].eval(t):new e.Value(this.value.map(function(e){return e.eval(t)}))},toCSS:function(e){return this.value.map(function(t){return t.toCSS(e)}).join(e.compress?\",\":\", \")}}}(n(\"../tree\")),function(e){e.Variable=function(e,t,n){this.name=e,this.index=t,this.file=n},e.Variable.prototype={eval:function(t){var n,r,i=this.name;i.indexOf(\"@@\")==0&&(i=\"@\"+(new e.Variable(i.slice(1))).eval(t).value);if(this.evaluating)throw{type:\"Name\",message:\"Recursive variable definition for \"+i,filename:this.file,index:this.index};this.evaluating=!0;if(n=e.find(t.frames,function(e){if(r=e.variable(i))return r.value.eval(t)}))return this.evaluating=!1,n;throw{type:\"Name\",message:\"variable \"+i+\" is undefined\",filename:this.file,index:this.index}}}}(n(\"../tree\")),function(e){e.debugInfo=function(t,n){var r=\"\";if(t.dumpLineNumbers&&!t.compress)switch(t.dumpLineNumbers){case\"comments\":r=e.debugInfo.asComment(n);break;case\"mediaquery\":r=e.debugInfo.asMediaQuery(n);break;case\"all\":r=e.debugInfo.asComment(n)+e.debugInfo.asMediaQuery(n)}return r},e.debugInfo.asComment=function(e){return\"/* line \"+e.debugInfo.lineNumber+\", \"+e.debugInfo.fileName+\" */\\n\"},e.debugInfo.asMediaQuery=function(e){return\"@media -sass-debug-info{filename{font-family:\"+(\"file://\"+e.debugInfo.fileName).replace(/[\\/:.]/g,\"\\\\$&\")+\"}line{font-family:\\\\00003\"+e.debugInfo.lineNumber+\"}}\\n\"},e.find=function(e,t){for(var n=0,r;n<e.length;n++)if(r=t.call(e,e[n]))return r;return null},e.jsify=function(e){return Array.isArray(e.value)&&e.value.length>1?\"[\"+e.value.map(function(e){return e.toCSS(!1)}).join(\", \")+\"]\":e.toCSS(!1)}}(n(\"./tree\"));var o=/^(file|chrome(-extension)?|resource|qrc|app):/.test(location.protocol);r.env=r.env||(location.hostname==\"127.0.0.1\"||location.hostname==\"0.0.0.0\"||location.hostname==\"localhost\"||location.port.length>0||o?\"development\":\"production\"),r.async=r.async||!1,r.fileAsync=r.fileAsync||!1,r.poll=r.poll||(o?1e3:1500);if(r.functions)for(var u in r.functions)r.tree.functions[u]=r.functions[u];var a=/!dumpLineNumbers:(comments|mediaquery|all)/.exec(location.hash);a&&(r.dumpLineNumbers=a[1]),r.watch=function(){return r.watchMode||(r.env=\"development\",f()),this.watchMode=!0},r.unwatch=function(){return clearInterval(r.watchTimer),this.watchMode=!1},/!watch/.test(location.hash)&&r.watch();var l=null;if(r.env!=\"development\")try{l=typeof e.localStorage==\"undefined\"?null:e.localStorage}catch(c){}var h=document.getElementsByTagName(\"link\"),p=/^text\\/(x-)?less$/;r.sheets=[];for(var d=0;d<h.length;d++)(h[d].rel===\"stylesheet/less\"||h[d].rel.match(/stylesheet/)&&h[d].type.match(p))&&r.sheets.push(h[d]);var v=\"\";r.modifyVars=function(e){var t=v;for(name in e)t+=(name.slice(0,1)===\"@\"?\"\":\"@\")+name+\": \"+(e[name].slice(-1)===\";\"?e[name]:e[name]+\";\");(new r.Parser).parse(t,function(e,t){S(t.toCSS(),r.sheets[r.sheets.length-1])})},r.refresh=function(e){var t,n;t=n=new Date,g(function(e,r,i,s,o){o.local?C(\"loading \"+s.href+\" from cache.\"):(C(\"parsed \"+s.href+\" successfully.\"),S(r.toCSS(),s,o.lastModified)),C(\"css for \"+s.href+\" generated in \"+(new Date-n)+\"ms\"),o.remaining===0&&C(\"css generated in \"+(new Date-t)+\"ms\"),n=new Date},e),m()},r.refreshStyles=m,r.refresh(r.env===\"development\"),typeof define==\"function\"&&define.amd&&define(\"less\",[],function(){return r})})(window);"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/sass-bootstrap/assets/js/raw-files.js",
    "content": "var __js = {\"affix.js\":\"/* ========================================================================\\n * Bootstrap: affix.js v3.0.0\\n * http://twbs.github.com/bootstrap/javascript.html#affix\\n * ========================================================================\\n * Copyright 2012 Twitter, Inc.\\n *\\n * Licensed under the Apache License, Version 2.0 (the \\\"License\\\");\\n * you may not use this file except in compliance with the License.\\n * You may obtain a copy of the License at\\n *\\n * http://www.apache.org/licenses/LICENSE-2.0\\n *\\n * Unless required by applicable law or agreed to in writing, software\\n * distributed under the License is distributed on an \\\"AS IS\\\" BASIS,\\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\\n * See the License for the specific language governing permissions and\\n * limitations under the License.\\n * ======================================================================== */\\n\\n\\n+function ($) { \\\"use strict\\\";\\n\\n  // AFFIX CLASS DEFINITION\\n  // ======================\\n\\n  var Affix = function (element, options) {\\n    this.options = $.extend({}, Affix.DEFAULTS, options)\\n    this.$window = $(window)\\n      .on('scroll.bs.affix.data-api', $.proxy(this.checkPosition, this))\\n      .on('click.bs.affix.data-api',  $.proxy(this.checkPositionWithEventLoop, this))\\n\\n    this.$element = $(element)\\n    this.affixed  =\\n    this.unpin    = null\\n\\n    this.checkPosition()\\n  }\\n\\n  Affix.RESET = 'affix affix-top affix-bottom'\\n\\n  Affix.DEFAULTS = {\\n    offset: 0\\n  }\\n\\n  Affix.prototype.checkPositionWithEventLoop = function () {\\n    setTimeout($.proxy(this.checkPosition, this), 1)\\n  }\\n\\n  Affix.prototype.checkPosition = function () {\\n    if (!this.$element.is(':visible')) return\\n\\n    var scrollHeight = $(document).height()\\n    var scrollTop    = this.$window.scrollTop()\\n    var position     = this.$element.offset()\\n    var offset       = this.options.offset\\n    var offsetTop    = offset.top\\n    var offsetBottom = offset.bottom\\n\\n    if (typeof offset != 'object')         offsetBottom = offsetTop = offset\\n    if (typeof offsetTop == 'function')    offsetTop    = offset.top()\\n    if (typeof offsetBottom == 'function') offsetBottom = offset.bottom()\\n\\n    var affix = this.unpin   != null && (scrollTop + this.unpin <= position.top) ? false :\\n                offsetBottom != null && (position.top + this.$element.height() >= scrollHeight - offsetBottom) ? 'bottom' :\\n                offsetTop    != null && (scrollTop <= offsetTop) ? 'top' : false\\n\\n    if (this.affixed === affix) return\\n    if (this.unpin) this.$element.css('top', '')\\n\\n    this.affixed = affix\\n    this.unpin   = affix == 'bottom' ? position.top - scrollTop : null\\n\\n    this.$element.removeClass(Affix.RESET).addClass('affix' + (affix ? '-' + affix : ''))\\n\\n    if (affix == 'bottom') {\\n      this.$element.offset({ top: document.body.offsetHeight - offsetBottom - this.$element.height() })\\n    }\\n  }\\n\\n\\n  // AFFIX PLUGIN DEFINITION\\n  // =======================\\n\\n  var old = $.fn.affix\\n\\n  $.fn.affix = function (option) {\\n    return this.each(function () {\\n      var $this   = $(this)\\n      var data    = $this.data('bs.affix')\\n      var options = typeof option == 'object' && option\\n\\n      if (!data) $this.data('bs.affix', (data = new Affix(this, options)))\\n      if (typeof option == 'string') data[option]()\\n    })\\n  }\\n\\n  $.fn.affix.Constructor = Affix\\n\\n\\n  // AFFIX NO CONFLICT\\n  // =================\\n\\n  $.fn.affix.noConflict = function () {\\n    $.fn.affix = old\\n    return this\\n  }\\n\\n\\n  // AFFIX DATA-API\\n  // ==============\\n\\n  $(window).on('load', function () {\\n    $('[data-spy=\\\"affix\\\"]').each(function () {\\n      var $spy = $(this)\\n      var data = $spy.data()\\n\\n      data.offset = data.offset || {}\\n\\n      if (data.offsetBottom) data.offset.bottom = data.offsetBottom\\n      if (data.offsetTop)    data.offset.top    = data.offsetTop\\n\\n      $spy.affix(data)\\n    })\\n  })\\n\\n}(window.jQuery);\\n\",\"alert.js\":\"/* ========================================================================\\n * Bootstrap: alert.js v3.0.0\\n * http://twbs.github.com/bootstrap/javascript.html#alerts\\n * ========================================================================\\n * Copyright 2013 Twitter, Inc.\\n *\\n * Licensed under the Apache License, Version 2.0 (the \\\"License\\\");\\n * you may not use this file except in compliance with the License.\\n * You may obtain a copy of the License at\\n *\\n * http://www.apache.org/licenses/LICENSE-2.0\\n *\\n * Unless required by applicable law or agreed to in writing, software\\n * distributed under the License is distributed on an \\\"AS IS\\\" BASIS,\\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\\n * See the License for the specific language governing permissions and\\n * limitations under the License.\\n * ======================================================================== */\\n\\n\\n+function ($) { \\\"use strict\\\";\\n\\n  // ALERT CLASS DEFINITION\\n  // ======================\\n\\n  var dismiss = '[data-dismiss=\\\"alert\\\"]'\\n  var Alert   = function (el) {\\n    $(el).on('click', dismiss, this.close)\\n  }\\n\\n  Alert.prototype.close = function (e) {\\n    var $this    = $(this)\\n    var selector = $this.attr('data-target')\\n\\n    if (!selector) {\\n      selector = $this.attr('href')\\n      selector = selector && selector.replace(/.*(?=#[^\\\\s]*$)/, '') // strip for ie7\\n    }\\n\\n    var $parent = $(selector)\\n\\n    if (e) e.preventDefault()\\n\\n    if (!$parent.length) {\\n      $parent = $this.hasClass('alert') ? $this : $this.parent()\\n    }\\n\\n    $parent.trigger(e = $.Event('close.bs.alert'))\\n\\n    if (e.isDefaultPrevented()) return\\n\\n    $parent.removeClass('in')\\n\\n    function removeElement() {\\n      $parent.trigger('closed.bs.alert').remove()\\n    }\\n\\n    $.support.transition && $parent.hasClass('fade') ?\\n      $parent\\n        .one($.support.transition.end, removeElement)\\n        .emulateTransitionEnd(150) :\\n      removeElement()\\n  }\\n\\n\\n  // ALERT PLUGIN DEFINITION\\n  // =======================\\n\\n  var old = $.fn.alert\\n\\n  $.fn.alert = function (option) {\\n    return this.each(function () {\\n      var $this = $(this)\\n      var data  = $this.data('bs.alert')\\n\\n      if (!data) $this.data('bs.alert', (data = new Alert(this)))\\n      if (typeof option == 'string') data[option].call($this)\\n    })\\n  }\\n\\n  $.fn.alert.Constructor = Alert\\n\\n\\n  // ALERT NO CONFLICT\\n  // =================\\n\\n  $.fn.alert.noConflict = function () {\\n    $.fn.alert = old\\n    return this\\n  }\\n\\n\\n  // ALERT DATA-API\\n  // ==============\\n\\n  $(document).on('click.bs.alert.data-api', dismiss, Alert.prototype.close)\\n\\n}(window.jQuery);\\n\",\"button.js\":\"/* ========================================================================\\n * Bootstrap: button.js v3.0.0\\n * http://twbs.github.com/bootstrap/javascript.html#buttons\\n * ========================================================================\\n * Copyright 2013 Twitter, Inc.\\n *\\n * Licensed under the Apache License, Version 2.0 (the \\\"License\\\");\\n * you may not use this file except in compliance with the License.\\n * You may obtain a copy of the License at\\n *\\n * http://www.apache.org/licenses/LICENSE-2.0\\n *\\n * Unless required by applicable law or agreed to in writing, software\\n * distributed under the License is distributed on an \\\"AS IS\\\" BASIS,\\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\\n * See the License for the specific language governing permissions and\\n * limitations under the License.\\n * ======================================================================== */\\n\\n\\n+function ($) { \\\"use strict\\\";\\n\\n  // BUTTON PUBLIC CLASS DEFINITION\\n  // ==============================\\n\\n  var Button = function (element, options) {\\n    this.$element = $(element)\\n    this.options  = $.extend({}, Button.DEFAULTS, options)\\n  }\\n\\n  Button.DEFAULTS = {\\n    loadingText: 'loading...'\\n  }\\n\\n  Button.prototype.setState = function (state) {\\n    var d    = 'disabled'\\n    var $el  = this.$element\\n    var val  = $el.is('input') ? 'val' : 'html'\\n    var data = $el.data()\\n\\n    state = state + 'Text'\\n\\n    if (!data.resetText) $el.data('resetText', $el[val]())\\n\\n    $el[val](data[state] || this.options[state])\\n\\n    // push to event loop to allow forms to submit\\n    setTimeout(function () {\\n      state == 'loadingText' ?\\n        $el.addClass(d).attr(d, d) :\\n        $el.removeClass(d).removeAttr(d);\\n    }, 0)\\n  }\\n\\n  Button.prototype.toggle = function () {\\n    var $parent = this.$element.closest('[data-toggle=\\\"buttons\\\"]')\\n\\n    if ($parent.length) {\\n      var $input = this.$element.find('input')\\n        .prop('checked', !this.$element.hasClass('active'))\\n        .trigger('change')\\n      if ($input.prop('type') === 'radio') $parent.find('.active').removeClass('active')\\n    }\\n\\n    this.$element.toggleClass('active')\\n  }\\n\\n\\n  // BUTTON PLUGIN DEFINITION\\n  // ========================\\n\\n  var old = $.fn.button\\n\\n  $.fn.button = function (option) {\\n    return this.each(function () {\\n      var $this   = $(this)\\n      var data    = $this.data('bs.button')\\n      var options = typeof option == 'object' && option\\n\\n      if (!data) $this.data('bs.button', (data = new Button(this, options)))\\n\\n      if (option == 'toggle') data.toggle()\\n      else if (option) data.setState(option)\\n    })\\n  }\\n\\n  $.fn.button.Constructor = Button\\n\\n\\n  // BUTTON NO CONFLICT\\n  // ==================\\n\\n  $.fn.button.noConflict = function () {\\n    $.fn.button = old\\n    return this\\n  }\\n\\n\\n  // BUTTON DATA-API\\n  // ===============\\n\\n  $(document).on('click.bs.button.data-api', '[data-toggle^=button]', function (e) {\\n    var $btn = $(e.target)\\n    if (!$btn.hasClass('btn')) $btn = $btn.closest('.btn')\\n    $btn.button('toggle')\\n    e.preventDefault()\\n  })\\n\\n}(window.jQuery);\\n\",\"carousel.js\":\"/* ========================================================================\\n * Bootstrap: carousel.js v3.0.0\\n * http://twbs.github.com/bootstrap/javascript.html#carousel\\n * ========================================================================\\n * Copyright 2012 Twitter, Inc.\\n *\\n * Licensed under the Apache License, Version 2.0 (the \\\"License\\\");\\n * you may not use this file except in compliance with the License.\\n * You may obtain a copy of the License at\\n *\\n * http://www.apache.org/licenses/LICENSE-2.0\\n *\\n * Unless required by applicable law or agreed to in writing, software\\n * distributed under the License is distributed on an \\\"AS IS\\\" BASIS,\\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\\n * See the License for the specific language governing permissions and\\n * limitations under the License.\\n * ======================================================================== */\\n\\n\\n+function ($) { \\\"use strict\\\";\\n\\n  // CAROUSEL CLASS DEFINITION\\n  // =========================\\n\\n  var Carousel = function (element, options) {\\n    this.$element    = $(element)\\n    this.$indicators = this.$element.find('.carousel-indicators')\\n    this.options     = options\\n    this.paused      =\\n    this.sliding     =\\n    this.interval    =\\n    this.$active     =\\n    this.$items      = null\\n\\n    this.options.pause == 'hover' && this.$element\\n      .on('mouseenter', $.proxy(this.pause, this))\\n      .on('mouseleave', $.proxy(this.cycle, this))\\n  }\\n\\n  Carousel.DEFAULTS = {\\n    interval: 5000\\n  , pause: 'hover'\\n  , wrap: true\\n  }\\n\\n  Carousel.prototype.cycle =  function (e) {\\n    e || (this.paused = false)\\n\\n    this.interval && clearInterval(this.interval)\\n\\n    this.options.interval\\n      && !this.paused\\n      && (this.interval = setInterval($.proxy(this.next, this), this.options.interval))\\n\\n    return this\\n  }\\n\\n  Carousel.prototype.getActiveIndex = function () {\\n    this.$active = this.$element.find('.item.active')\\n    this.$items  = this.$active.parent().children()\\n\\n    return this.$items.index(this.$active)\\n  }\\n\\n  Carousel.prototype.to = function (pos) {\\n    var that        = this\\n    var activeIndex = this.getActiveIndex()\\n\\n    if (pos > (this.$items.length - 1) || pos < 0) return\\n\\n    if (this.sliding)       return this.$element.one('slid', function () { that.to(pos) })\\n    if (activeIndex == pos) return this.pause().cycle()\\n\\n    return this.slide(pos > activeIndex ? 'next' : 'prev', $(this.$items[pos]))\\n  }\\n\\n  Carousel.prototype.pause = function (e) {\\n    e || (this.paused = true)\\n\\n    if (this.$element.find('.next, .prev').length && $.support.transition.end) {\\n      this.$element.trigger($.support.transition.end)\\n      this.cycle(true)\\n    }\\n\\n    this.interval = clearInterval(this.interval)\\n\\n    return this\\n  }\\n\\n  Carousel.prototype.next = function () {\\n    if (this.sliding) return\\n    return this.slide('next')\\n  }\\n\\n  Carousel.prototype.prev = function () {\\n    if (this.sliding) return\\n    return this.slide('prev')\\n  }\\n\\n  Carousel.prototype.slide = function (type, next) {\\n    var $active   = this.$element.find('.item.active')\\n    var $next     = next || $active[type]()\\n    var isCycling = this.interval\\n    var direction = type == 'next' ? 'left' : 'right'\\n    var fallback  = type == 'next' ? 'first' : 'last'\\n    var that      = this\\n\\n    if (!$next.length) {\\n      if (!this.options.wrap) return\\n      $next = this.$element.find('.item')[fallback]()\\n    }\\n\\n    this.sliding = true\\n\\n    isCycling && this.pause()\\n\\n    var e = $.Event('slide.bs.carousel', { relatedTarget: $next[0], direction: direction })\\n\\n    if ($next.hasClass('active')) return\\n\\n    if (this.$indicators.length) {\\n      this.$indicators.find('.active').removeClass('active')\\n      this.$element.one('slid', function () {\\n        var $nextIndicator = $(that.$indicators.children()[that.getActiveIndex()])\\n        $nextIndicator && $nextIndicator.addClass('active')\\n      })\\n    }\\n\\n    if ($.support.transition && this.$element.hasClass('slide')) {\\n      this.$element.trigger(e)\\n      if (e.isDefaultPrevented()) return\\n      $next.addClass(type)\\n      $next[0].offsetWidth // force reflow\\n      $active.addClass(direction)\\n      $next.addClass(direction)\\n      $active\\n        .one($.support.transition.end, function () {\\n          $next.removeClass([type, direction].join(' ')).addClass('active')\\n          $active.removeClass(['active', direction].join(' '))\\n          that.sliding = false\\n          setTimeout(function () { that.$element.trigger('slid') }, 0)\\n        })\\n        .emulateTransitionEnd(600)\\n    } else {\\n      this.$element.trigger(e)\\n      if (e.isDefaultPrevented()) return\\n      $active.removeClass('active')\\n      $next.addClass('active')\\n      this.sliding = false\\n      this.$element.trigger('slid')\\n    }\\n\\n    isCycling && this.cycle()\\n\\n    return this\\n  }\\n\\n\\n  // CAROUSEL PLUGIN DEFINITION\\n  // ==========================\\n\\n  var old = $.fn.carousel\\n\\n  $.fn.carousel = function (option) {\\n    return this.each(function () {\\n      var $this   = $(this)\\n      var data    = $this.data('bs.carousel')\\n      var options = $.extend({}, Carousel.DEFAULTS, $this.data(), typeof option == 'object' && option)\\n      var action  = typeof option == 'string' ? option : options.slide\\n\\n      if (!data) $this.data('bs.carousel', (data = new Carousel(this, options)))\\n      if (typeof option == 'number') data.to(option)\\n      else if (action) data[action]()\\n      else if (options.interval) data.pause().cycle()\\n    })\\n  }\\n\\n  $.fn.carousel.Constructor = Carousel\\n\\n\\n  // CAROUSEL NO CONFLICT\\n  // ====================\\n\\n  $.fn.carousel.noConflict = function () {\\n    $.fn.carousel = old\\n    return this\\n  }\\n\\n\\n  // CAROUSEL DATA-API\\n  // =================\\n\\n  $(document).on('click.bs.carousel.data-api', '[data-slide], [data-slide-to]', function (e) {\\n    var $this   = $(this), href\\n    var $target = $($this.attr('data-target') || (href = $this.attr('href')) && href.replace(/.*(?=#[^\\\\s]+$)/, '')) //strip for ie7\\n    var options = $.extend({}, $target.data(), $this.data())\\n    var slideIndex = $this.attr('data-slide-to')\\n    if (slideIndex) options.interval = false\\n\\n    $target.carousel(options)\\n\\n    if (slideIndex = $this.attr('data-slide-to')) {\\n      $target.data('bs.carousel').to(slideIndex)\\n    }\\n\\n    e.preventDefault()\\n  })\\n\\n  $(window).on('load', function () {\\n    $('[data-ride=\\\"carousel\\\"]').each(function () {\\n      var $carousel = $(this)\\n      $carousel.carousel($carousel.data())\\n    })\\n  })\\n\\n}(window.jQuery);\\n\",\"collapse.js\":\"/* ========================================================================\\n * Bootstrap: collapse.js v3.0.0\\n * http://twbs.github.com/bootstrap/javascript.html#collapse\\n * ========================================================================\\n * Copyright 2012 Twitter, Inc.\\n *\\n * Licensed under the Apache License, Version 2.0 (the \\\"License\\\");\\n * you may not use this file except in compliance with the License.\\n * You may obtain a copy of the License at\\n *\\n * http://www.apache.org/licenses/LICENSE-2.0\\n *\\n * Unless required by applicable law or agreed to in writing, software\\n * distributed under the License is distributed on an \\\"AS IS\\\" BASIS,\\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\\n * See the License for the specific language governing permissions and\\n * limitations under the License.\\n * ======================================================================== */\\n\\n\\n+function ($) { \\\"use strict\\\";\\n\\n  // COLLAPSE PUBLIC CLASS DEFINITION\\n  // ================================\\n\\n  var Collapse = function (element, options) {\\n    this.$element      = $(element)\\n    this.options       = $.extend({}, Collapse.DEFAULTS, options)\\n    this.transitioning = null\\n\\n    if (this.options.parent) this.$parent = $(this.options.parent)\\n    if (this.options.toggle) this.toggle()\\n  }\\n\\n  Collapse.DEFAULTS = {\\n    toggle: true\\n  }\\n\\n  Collapse.prototype.dimension = function () {\\n    var hasWidth = this.$element.hasClass('width')\\n    return hasWidth ? 'width' : 'height'\\n  }\\n\\n  Collapse.prototype.show = function () {\\n    if (this.transitioning || this.$element.hasClass('in')) return\\n\\n    var startEvent = $.Event('show.bs.collapse')\\n    this.$element.trigger(startEvent)\\n    if (startEvent.isDefaultPrevented()) return\\n\\n    var actives = this.$parent && this.$parent.find('> .panel > .in')\\n\\n    if (actives && actives.length) {\\n      var hasData = actives.data('bs.collapse')\\n      if (hasData && hasData.transitioning) return\\n      actives.collapse('hide')\\n      hasData || actives.data('bs.collapse', null)\\n    }\\n\\n    var dimension = this.dimension()\\n\\n    this.$element\\n      .removeClass('collapse')\\n      .addClass('collapsing')\\n      [dimension](0)\\n\\n    this.transitioning = 1\\n\\n    var complete = function () {\\n      this.$element\\n        .removeClass('collapsing')\\n        .addClass('in')\\n        [dimension]('auto')\\n      this.transitioning = 0\\n      this.$element.trigger('shown.bs.collapse')\\n    }\\n\\n    if (!$.support.transition) return complete.call(this)\\n\\n    var scrollSize = $.camelCase(['scroll', dimension].join('-'))\\n\\n    this.$element\\n      .one($.support.transition.end, $.proxy(complete, this))\\n      .emulateTransitionEnd(350)\\n      [dimension](this.$element[0][scrollSize])\\n  }\\n\\n  Collapse.prototype.hide = function () {\\n    if (this.transitioning || !this.$element.hasClass('in')) return\\n\\n    var startEvent = $.Event('hide.bs.collapse')\\n    this.$element.trigger(startEvent)\\n    if (startEvent.isDefaultPrevented()) return\\n\\n    var dimension = this.dimension()\\n\\n    this.$element\\n      [dimension](this.$element[dimension]())\\n      [0].offsetHeight\\n\\n    this.$element\\n      .addClass('collapsing')\\n      .removeClass('collapse')\\n      .removeClass('in')\\n\\n    this.transitioning = 1\\n\\n    var complete = function () {\\n      this.transitioning = 0\\n      this.$element\\n        .trigger('hidden.bs.collapse')\\n        .removeClass('collapsing')\\n        .addClass('collapse')\\n    }\\n\\n    if (!$.support.transition) return complete.call(this)\\n\\n    this.$element\\n      [dimension](0)\\n      .one($.support.transition.end, $.proxy(complete, this))\\n      .emulateTransitionEnd(350)\\n  }\\n\\n  Collapse.prototype.toggle = function () {\\n    this[this.$element.hasClass('in') ? 'hide' : 'show']()\\n  }\\n\\n\\n  // COLLAPSE PLUGIN DEFINITION\\n  // ==========================\\n\\n  var old = $.fn.collapse\\n\\n  $.fn.collapse = function (option) {\\n    return this.each(function () {\\n      var $this   = $(this)\\n      var data    = $this.data('bs.collapse')\\n      var options = $.extend({}, Collapse.DEFAULTS, $this.data(), typeof option == 'object' && option)\\n\\n      if (!data) $this.data('bs.collapse', (data = new Collapse(this, options)))\\n      if (typeof option == 'string') data[option]()\\n    })\\n  }\\n\\n  $.fn.collapse.Constructor = Collapse\\n\\n\\n  // COLLAPSE NO CONFLICT\\n  // ====================\\n\\n  $.fn.collapse.noConflict = function () {\\n    $.fn.collapse = old\\n    return this\\n  }\\n\\n\\n  // COLLAPSE DATA-API\\n  // =================\\n\\n  $(document).on('click.bs.collapse.data-api', '[data-toggle=collapse]', function (e) {\\n    var $this   = $(this), href\\n    var target  = $this.attr('data-target')\\n        || e.preventDefault()\\n        || (href = $this.attr('href')) && href.replace(/.*(?=#[^\\\\s]+$)/, '') //strip for ie7\\n    var $target = $(target)\\n    var data    = $target.data('bs.collapse')\\n    var option  = data ? 'toggle' : $this.data()\\n    var parent  = $this.attr('data-parent')\\n    var $parent = parent && $(parent)\\n\\n    if (!data || !data.transitioning) {\\n      if ($parent) $parent.find('[data-toggle=collapse][data-parent=\\\"' + parent + '\\\"]').not($this).addClass('collapsed')\\n      $this[$target.hasClass('in') ? 'addClass' : 'removeClass']('collapsed')\\n    }\\n\\n    $target.collapse(option)\\n  })\\n\\n}(window.jQuery);\\n\",\"dropdown.js\":\"/* ========================================================================\\n * Bootstrap: dropdown.js v3.0.0\\n * http://twbs.github.com/bootstrap/javascript.html#dropdowns\\n * ========================================================================\\n * Copyright 2012 Twitter, Inc.\\n *\\n * Licensed under the Apache License, Version 2.0 (the \\\"License\\\");\\n * you may not use this file except in compliance with the License.\\n * You may obtain a copy of the License at\\n *\\n * http://www.apache.org/licenses/LICENSE-2.0\\n *\\n * Unless required by applicable law or agreed to in writing, software\\n * distributed under the License is distributed on an \\\"AS IS\\\" BASIS,\\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\\n * See the License for the specific language governing permissions and\\n * limitations under the License.\\n * ======================================================================== */\\n\\n\\n+function ($) { \\\"use strict\\\";\\n\\n  // DROPDOWN CLASS DEFINITION\\n  // =========================\\n\\n  var backdrop = '.dropdown-backdrop'\\n  var toggle   = '[data-toggle=dropdown]'\\n  var Dropdown = function (element) {\\n    var $el = $(element).on('click.bs.dropdown', this.toggle)\\n  }\\n\\n  Dropdown.prototype.toggle = function (e) {\\n    var $this = $(this)\\n\\n    if ($this.is('.disabled, :disabled')) return\\n\\n    var $parent  = getParent($this)\\n    var isActive = $parent.hasClass('open')\\n\\n    clearMenus()\\n\\n    if (!isActive) {\\n      if ('ontouchstart' in document.documentElement && !$parent.closest('.navbar-nav').length) {\\n        // if mobile we we use a backdrop because click events don't delegate\\n        $('<div class=\\\"dropdown-backdrop\\\"/>').insertAfter($(this)).on('click', clearMenus)\\n      }\\n\\n      $parent.trigger(e = $.Event('show.bs.dropdown'))\\n\\n      if (e.isDefaultPrevented()) return\\n\\n      $parent\\n        .toggleClass('open')\\n        .trigger('shown.bs.dropdown')\\n\\n      $this.focus()\\n    }\\n\\n    return false\\n  }\\n\\n  Dropdown.prototype.keydown = function (e) {\\n    if (!/(38|40|27)/.test(e.keyCode)) return\\n\\n    var $this = $(this)\\n\\n    e.preventDefault()\\n    e.stopPropagation()\\n\\n    if ($this.is('.disabled, :disabled')) return\\n\\n    var $parent  = getParent($this)\\n    var isActive = $parent.hasClass('open')\\n\\n    if (!isActive || (isActive && e.keyCode == 27)) {\\n      if (e.which == 27) $parent.find(toggle).focus()\\n      return $this.click()\\n    }\\n\\n    var $items = $('[role=menu] li:not(.divider):visible a', $parent)\\n\\n    if (!$items.length) return\\n\\n    var index = $items.index($items.filter(':focus'))\\n\\n    if (e.keyCode == 38 && index > 0)                 index--                        // up\\n    if (e.keyCode == 40 && index < $items.length - 1) index++                        // down\\n    if (!~index)                                      index=0\\n\\n    $items.eq(index).focus()\\n  }\\n\\n  function clearMenus() {\\n    $(backdrop).remove()\\n    $(toggle).each(function (e) {\\n      var $parent = getParent($(this))\\n      if (!$parent.hasClass('open')) return\\n      $parent.trigger(e = $.Event('hide.bs.dropdown'))\\n      if (e.isDefaultPrevented()) return\\n      $parent.removeClass('open').trigger('hidden.bs.dropdown')\\n    })\\n  }\\n\\n  function getParent($this) {\\n    var selector = $this.attr('data-target')\\n\\n    if (!selector) {\\n      selector = $this.attr('href')\\n      selector = selector && /#/.test(selector) && selector.replace(/.*(?=#[^\\\\s]*$)/, '') //strip for ie7\\n    }\\n\\n    var $parent = selector && $(selector)\\n\\n    return $parent && $parent.length ? $parent : $this.parent()\\n  }\\n\\n\\n  // DROPDOWN PLUGIN DEFINITION\\n  // ==========================\\n\\n  var old = $.fn.dropdown\\n\\n  $.fn.dropdown = function (option) {\\n    return this.each(function () {\\n      var $this = $(this)\\n      var data  = $this.data('dropdown')\\n\\n      if (!data) $this.data('dropdown', (data = new Dropdown(this)))\\n      if (typeof option == 'string') data[option].call($this)\\n    })\\n  }\\n\\n  $.fn.dropdown.Constructor = Dropdown\\n\\n\\n  // DROPDOWN NO CONFLICT\\n  // ====================\\n\\n  $.fn.dropdown.noConflict = function () {\\n    $.fn.dropdown = old\\n    return this\\n  }\\n\\n\\n  // APPLY TO STANDARD DROPDOWN ELEMENTS\\n  // ===================================\\n\\n  $(document)\\n    .on('click.bs.dropdown.data-api', clearMenus)\\n    .on('click.bs.dropdown.data-api', '.dropdown form', function (e) { e.stopPropagation() })\\n    .on('click.bs.dropdown.data-api'  , toggle, Dropdown.prototype.toggle)\\n    .on('keydown.bs.dropdown.data-api', toggle + ', [role=menu]' , Dropdown.prototype.keydown)\\n\\n}(window.jQuery);\\n\",\"modal.js\":\"/* ========================================================================\\n * Bootstrap: modal.js v3.0.0\\n * http://twbs.github.com/bootstrap/javascript.html#modals\\n * ========================================================================\\n * Copyright 2012 Twitter, Inc.\\n *\\n * Licensed under the Apache License, Version 2.0 (the \\\"License\\\");\\n * you may not use this file except in compliance with the License.\\n * You may obtain a copy of the License at\\n *\\n * http://www.apache.org/licenses/LICENSE-2.0\\n *\\n * Unless required by applicable law or agreed to in writing, software\\n * distributed under the License is distributed on an \\\"AS IS\\\" BASIS,\\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\\n * See the License for the specific language governing permissions and\\n * limitations under the License.\\n * ======================================================================== */\\n\\n\\n+function ($) { \\\"use strict\\\";\\n\\n  // MODAL CLASS DEFINITION\\n  // ======================\\n\\n  var Modal = function (element, options) {\\n    this.options   = options\\n    this.$element  = $(element)\\n    this.$backdrop =\\n    this.isShown   = null\\n\\n    if (this.options.remote) this.$element.load(this.options.remote)\\n  }\\n\\n  Modal.DEFAULTS = {\\n      backdrop: true\\n    , keyboard: true\\n    , show: true\\n  }\\n\\n  Modal.prototype.toggle = function (_relatedTarget) {\\n    return this[!this.isShown ? 'show' : 'hide'](_relatedTarget)\\n  }\\n\\n  Modal.prototype.show = function (_relatedTarget) {\\n    var that = this\\n    var e    = $.Event('show.bs.modal', { relatedTarget: _relatedTarget })\\n\\n    this.$element.trigger(e)\\n\\n    if (this.isShown || e.isDefaultPrevented()) return\\n\\n    this.isShown = true\\n\\n    this.escape()\\n\\n    this.$element.on('click.dismiss.modal', '[data-dismiss=\\\"modal\\\"]', $.proxy(this.hide, this))\\n\\n    this.backdrop(function () {\\n      var transition = $.support.transition && that.$element.hasClass('fade')\\n\\n      if (!that.$element.parent().length) {\\n        that.$element.appendTo(document.body) // don't move modals dom position\\n      }\\n\\n      that.$element.show()\\n\\n      if (transition) {\\n        that.$element[0].offsetWidth // force reflow\\n      }\\n\\n      that.$element\\n        .addClass('in')\\n        .attr('aria-hidden', false)\\n\\n      that.enforceFocus()\\n\\n      var e = $.Event('shown.bs.modal', { relatedTarget: _relatedTarget })\\n\\n      transition ?\\n        that.$element.find('.modal-dialog') // wait for modal to slide in\\n          .one($.support.transition.end, function () {\\n            that.$element.focus().trigger(e)\\n          })\\n          .emulateTransitionEnd(300) :\\n        that.$element.focus().trigger(e)\\n    })\\n  }\\n\\n  Modal.prototype.hide = function (e) {\\n    if (e) e.preventDefault()\\n\\n    e = $.Event('hide.bs.modal')\\n\\n    this.$element.trigger(e)\\n\\n    if (!this.isShown || e.isDefaultPrevented()) return\\n\\n    this.isShown = false\\n\\n    this.escape()\\n\\n    $(document).off('focusin.bs.modal')\\n\\n    this.$element\\n      .removeClass('in')\\n      .attr('aria-hidden', true)\\n      .off('click.dismiss.modal')\\n\\n    $.support.transition && this.$element.hasClass('fade') ?\\n      this.$element\\n        .one($.support.transition.end, $.proxy(this.hideModal, this))\\n        .emulateTransitionEnd(300) :\\n      this.hideModal()\\n  }\\n\\n  Modal.prototype.enforceFocus = function () {\\n    $(document)\\n      .off('focusin.bs.modal') // guard against infinite focus loop\\n      .on('focusin.bs.modal', $.proxy(function (e) {\\n        if (this.$element[0] !== e.target && !this.$element.has(e.target).length) {\\n          this.$element.focus()\\n        }\\n      }, this))\\n  }\\n\\n  Modal.prototype.escape = function () {\\n    if (this.isShown && this.options.keyboard) {\\n      this.$element.on('keyup.dismiss.bs.modal', $.proxy(function (e) {\\n        e.which == 27 && this.hide()\\n      }, this))\\n    } else if (!this.isShown) {\\n      this.$element.off('keyup.dismiss.bs.modal')\\n    }\\n  }\\n\\n  Modal.prototype.hideModal = function () {\\n    var that = this\\n    this.$element.hide()\\n    this.backdrop(function () {\\n      that.removeBackdrop()\\n      that.$element.trigger('hidden.bs.modal')\\n    })\\n  }\\n\\n  Modal.prototype.removeBackdrop = function () {\\n    this.$backdrop && this.$backdrop.remove()\\n    this.$backdrop = null\\n  }\\n\\n  Modal.prototype.backdrop = function (callback) {\\n    var that    = this\\n    var animate = this.$element.hasClass('fade') ? 'fade' : ''\\n\\n    if (this.isShown && this.options.backdrop) {\\n      var doAnimate = $.support.transition && animate\\n\\n      this.$backdrop = $('<div class=\\\"modal-backdrop ' + animate + '\\\" />')\\n        .appendTo(document.body)\\n\\n      this.$element.on('click.dismiss.modal', $.proxy(function (e) {\\n        if (e.target !== e.currentTarget) return\\n        this.options.backdrop == 'static'\\n          ? this.$element[0].focus.call(this.$element[0])\\n          : this.hide.call(this)\\n      }, this))\\n\\n      if (doAnimate) this.$backdrop[0].offsetWidth // force reflow\\n\\n      this.$backdrop.addClass('in')\\n\\n      if (!callback) return\\n\\n      doAnimate ?\\n        this.$backdrop\\n          .one($.support.transition.end, callback)\\n          .emulateTransitionEnd(150) :\\n        callback()\\n\\n    } else if (!this.isShown && this.$backdrop) {\\n      this.$backdrop.removeClass('in')\\n\\n      $.support.transition && this.$element.hasClass('fade')?\\n        this.$backdrop\\n          .one($.support.transition.end, callback)\\n          .emulateTransitionEnd(150) :\\n        callback()\\n\\n    } else if (callback) {\\n      callback()\\n    }\\n  }\\n\\n\\n  // MODAL PLUGIN DEFINITION\\n  // =======================\\n\\n  var old = $.fn.modal\\n\\n  $.fn.modal = function (option, _relatedTarget) {\\n    return this.each(function () {\\n      var $this   = $(this)\\n      var data    = $this.data('bs.modal')\\n      var options = $.extend({}, Modal.DEFAULTS, $this.data(), typeof option == 'object' && option)\\n\\n      if (!data) $this.data('bs.modal', (data = new Modal(this, options)))\\n      if (typeof option == 'string') data[option](_relatedTarget)\\n      else if (options.show) data.show(_relatedTarget)\\n    })\\n  }\\n\\n  $.fn.modal.Constructor = Modal\\n\\n\\n  // MODAL NO CONFLICT\\n  // =================\\n\\n  $.fn.modal.noConflict = function () {\\n    $.fn.modal = old\\n    return this\\n  }\\n\\n\\n  // MODAL DATA-API\\n  // ==============\\n\\n  $(document).on('click.bs.modal.data-api', '[data-toggle=\\\"modal\\\"]', function (e) {\\n    var $this   = $(this)\\n    var href    = $this.attr('href')\\n    var $target = $($this.attr('data-target') || (href && href.replace(/.*(?=#[^\\\\s]+$)/, ''))) //strip for ie7\\n    var option  = $target.data('modal') ? 'toggle' : $.extend({ remote: !/#/.test(href) && href }, $target.data(), $this.data())\\n\\n    e.preventDefault()\\n\\n    $target\\n      .modal(option, this)\\n      .one('hide', function () {\\n        $this.is(':visible') && $this.focus()\\n      })\\n  })\\n\\n  $(document)\\n    .on('show.bs.modal',  '.modal', function () { $(document.body).addClass('modal-open') })\\n    .on('hidden.bs.modal', '.modal', function () { $(document.body).removeClass('modal-open') })\\n\\n}(window.jQuery);\\n\",\"popover.js\":\"/* ========================================================================\\n * Bootstrap: popover.js v3.0.0\\n * http://twbs.github.com/bootstrap/javascript.html#popovers\\n * ========================================================================\\n * Copyright 2012 Twitter, Inc.\\n *\\n * Licensed under the Apache License, Version 2.0 (the \\\"License\\\");\\n * you may not use this file except in compliance with the License.\\n * You may obtain a copy of the License at\\n *\\n * http://www.apache.org/licenses/LICENSE-2.0\\n *\\n * Unless required by applicable law or agreed to in writing, software\\n * distributed under the License is distributed on an \\\"AS IS\\\" BASIS,\\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\\n * See the License for the specific language governing permissions and\\n * limitations under the License.\\n * ======================================================================== */\\n\\n\\n+function ($) { \\\"use strict\\\";\\n\\n  // POPOVER PUBLIC CLASS DEFINITION\\n  // ===============================\\n\\n  var Popover = function (element, options) {\\n    this.init('popover', element, options)\\n  }\\n\\n  if (!$.fn.tooltip) throw new Error('Popover requires tooltip.js')\\n\\n  Popover.DEFAULTS = $.extend({} , $.fn.tooltip.Constructor.DEFAULTS, {\\n    placement: 'right'\\n  , trigger: 'click'\\n  , content: ''\\n  , template: '<div class=\\\"popover\\\"><div class=\\\"arrow\\\"></div><h3 class=\\\"popover-title\\\"></h3><div class=\\\"popover-content\\\"></div></div>'\\n  })\\n\\n\\n  // NOTE: POPOVER EXTENDS tooltip.js\\n  // ================================\\n\\n  Popover.prototype = $.extend({}, $.fn.tooltip.Constructor.prototype)\\n\\n  Popover.prototype.constructor = Popover\\n\\n  Popover.prototype.getDefaults = function () {\\n    return Popover.DEFAULTS\\n  }\\n\\n  Popover.prototype.setContent = function () {\\n    var $tip    = this.tip()\\n    var title   = this.getTitle()\\n    var content = this.getContent()\\n\\n    $tip.find('.popover-title')[this.options.html ? 'html' : 'text'](title)\\n    $tip.find('.popover-content')[this.options.html ? 'html' : 'text'](content)\\n\\n    $tip.removeClass('fade top bottom left right in')\\n\\n    // IE8 doesn't accept hiding via the `:empty` pseudo selector, we have to do\\n    // this manually by checking the contents.\\n    if (!$tip.find('.popover-title').html()) $tip.find('.popover-title').hide()\\n  }\\n\\n  Popover.prototype.hasContent = function () {\\n    return this.getTitle() || this.getContent()\\n  }\\n\\n  Popover.prototype.getContent = function () {\\n    var $e = this.$element\\n    var o  = this.options\\n\\n    return $e.attr('data-content')\\n      || (typeof o.content == 'function' ?\\n            o.content.call($e[0]) :\\n            o.content)\\n  }\\n\\n  Popover.prototype.arrow = function () {\\n    return this.$arrow = this.$arrow || this.tip().find('.arrow')\\n  }\\n\\n  Popover.prototype.tip = function () {\\n    if (!this.$tip) this.$tip = $(this.options.template)\\n    return this.$tip\\n  }\\n\\n\\n  // POPOVER PLUGIN DEFINITION\\n  // =========================\\n\\n  var old = $.fn.popover\\n\\n  $.fn.popover = function (option) {\\n    return this.each(function () {\\n      var $this   = $(this)\\n      var data    = $this.data('bs.popover')\\n      var options = typeof option == 'object' && option\\n\\n      if (!data) $this.data('bs.popover', (data = new Popover(this, options)))\\n      if (typeof option == 'string') data[option]()\\n    })\\n  }\\n\\n  $.fn.popover.Constructor = Popover\\n\\n\\n  // POPOVER NO CONFLICT\\n  // ===================\\n\\n  $.fn.popover.noConflict = function () {\\n    $.fn.popover = old\\n    return this\\n  }\\n\\n}(window.jQuery);\\n\",\"scrollspy.js\":\"/* ========================================================================\\n * Bootstrap: scrollspy.js v3.0.0\\n * http://twbs.github.com/bootstrap/javascript.html#scrollspy\\n * ========================================================================\\n * Copyright 2012 Twitter, Inc.\\n *\\n * Licensed under the Apache License, Version 2.0 (the \\\"License\\\");\\n * you may not use this file except in compliance with the License.\\n * You may obtain a copy of the License at\\n *\\n * http://www.apache.org/licenses/LICENSE-2.0\\n *\\n * Unless required by applicable law or agreed to in writing, software\\n * distributed under the License is distributed on an \\\"AS IS\\\" BASIS,\\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\\n * See the License for the specific language governing permissions and\\n * limitations under the License.\\n * ======================================================================== */\\n\\n\\n+function ($) { \\\"use strict\\\";\\n\\n  // SCROLLSPY CLASS DEFINITION\\n  // ==========================\\n\\n  function ScrollSpy(element, options) {\\n    var href\\n    var process  = $.proxy(this.process, this)\\n\\n    this.$element       = $(element).is('body') ? $(window) : $(element)\\n    this.$body          = $('body')\\n    this.$scrollElement = this.$element.on('scroll.bs.scroll-spy.data-api', process)\\n    this.options        = $.extend({}, ScrollSpy.DEFAULTS, options)\\n    this.selector       = (this.options.target\\n      || ((href = $(element).attr('href')) && href.replace(/.*(?=#[^\\\\s]+$)/, '')) //strip for ie7\\n      || '') + ' .nav li > a'\\n    this.offsets        = $([])\\n    this.targets        = $([])\\n    this.activeTarget   = null\\n\\n    this.refresh()\\n    this.process()\\n  }\\n\\n  ScrollSpy.DEFAULTS = {\\n    offset: 10\\n  }\\n\\n  ScrollSpy.prototype.refresh = function () {\\n    var offsetMethod = this.$element[0] == window ? 'offset' : 'position'\\n\\n    this.offsets = $([])\\n    this.targets = $([])\\n\\n    var self     = this\\n    var $targets = this.$body\\n      .find(this.selector)\\n      .map(function () {\\n        var $el   = $(this)\\n        var href  = $el.data('target') || $el.attr('href')\\n        var $href = /^#\\\\w/.test(href) && $(href)\\n\\n        return ($href\\n          && $href.length\\n          && [[ $href[offsetMethod]().top + (!$.isWindow(self.$scrollElement.get(0)) && self.$scrollElement.scrollTop()), href ]]) || null\\n      })\\n      .sort(function (a, b) { return a[0] - b[0] })\\n      .each(function () {\\n        self.offsets.push(this[0])\\n        self.targets.push(this[1])\\n      })\\n  }\\n\\n  ScrollSpy.prototype.process = function () {\\n    var scrollTop    = this.$scrollElement.scrollTop() + this.options.offset\\n    var scrollHeight = this.$scrollElement[0].scrollHeight || this.$body[0].scrollHeight\\n    var maxScroll    = scrollHeight - this.$scrollElement.height()\\n    var offsets      = this.offsets\\n    var targets      = this.targets\\n    var activeTarget = this.activeTarget\\n    var i\\n\\n    if (scrollTop >= maxScroll) {\\n      return activeTarget != (i = targets.last()[0]) && this.activate(i)\\n    }\\n\\n    for (i = offsets.length; i--;) {\\n      activeTarget != targets[i]\\n        && scrollTop >= offsets[i]\\n        && (!offsets[i + 1] || scrollTop <= offsets[i + 1])\\n        && this.activate( targets[i] )\\n    }\\n  }\\n\\n  ScrollSpy.prototype.activate = function (target) {\\n    this.activeTarget = target\\n\\n    $(this.selector)\\n      .parents('.active')\\n      .removeClass('active')\\n\\n    var selector = this.selector\\n      + '[data-target=\\\"' + target + '\\\"],'\\n      + this.selector + '[href=\\\"' + target + '\\\"]'\\n\\n    var active = $(selector)\\n      .parents('li')\\n      .addClass('active')\\n\\n    if (active.parent('.dropdown-menu').length)  {\\n      active = active\\n        .closest('li.dropdown')\\n        .addClass('active')\\n    }\\n\\n    active.trigger('activate')\\n  }\\n\\n\\n  // SCROLLSPY PLUGIN DEFINITION\\n  // ===========================\\n\\n  var old = $.fn.scrollspy\\n\\n  $.fn.scrollspy = function (option) {\\n    return this.each(function () {\\n      var $this   = $(this)\\n      var data    = $this.data('bs.scrollspy')\\n      var options = typeof option == 'object' && option\\n\\n      if (!data) $this.data('bs.scrollspy', (data = new ScrollSpy(this, options)))\\n      if (typeof option == 'string') data[option]()\\n    })\\n  }\\n\\n  $.fn.scrollspy.Constructor = ScrollSpy\\n\\n\\n  // SCROLLSPY NO CONFLICT\\n  // =====================\\n\\n  $.fn.scrollspy.noConflict = function () {\\n    $.fn.scrollspy = old\\n    return this\\n  }\\n\\n\\n  // SCROLLSPY DATA-API\\n  // ==================\\n\\n  $(window).on('load', function () {\\n    $('[data-spy=\\\"scroll\\\"]').each(function () {\\n      var $spy = $(this)\\n      $spy.scrollspy($spy.data())\\n    })\\n  })\\n\\n}(window.jQuery);\\n\",\"tab.js\":\"/* ========================================================================\\n * Bootstrap: tab.js v3.0.0\\n * http://twbs.github.com/bootstrap/javascript.html#tabs\\n * ========================================================================\\n * Copyright 2012 Twitter, Inc.\\n *\\n * Licensed under the Apache License, Version 2.0 (the \\\"License\\\");\\n * you may not use this file except in compliance with the License.\\n * You may obtain a copy of the License at\\n *\\n * http://www.apache.org/licenses/LICENSE-2.0\\n *\\n * Unless required by applicable law or agreed to in writing, software\\n * distributed under the License is distributed on an \\\"AS IS\\\" BASIS,\\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\\n * See the License for the specific language governing permissions and\\n * limitations under the License.\\n * ======================================================================== */\\n\\n\\n+function ($) { \\\"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.attr('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}(window.jQuery);\\n\",\"tooltip.js\":\"/* ========================================================================\\n * Bootstrap: tooltip.js v3.0.0\\n * http://twbs.github.com/bootstrap/javascript.html#tooltip\\n * Inspired by the original jQuery.tipsy by Jason Frame\\n * ========================================================================\\n * Copyright 2012 Twitter, Inc.\\n *\\n * Licensed under the Apache License, Version 2.0 (the \\\"License\\\");\\n * you may not use this file except in compliance with the License.\\n * You may obtain a copy of the License at\\n *\\n * http://www.apache.org/licenses/LICENSE-2.0\\n *\\n * Unless required by applicable law or agreed to in writing, software\\n * distributed under the License is distributed on an \\\"AS IS\\\" BASIS,\\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\\n * See the License for the specific language governing permissions and\\n * limitations under the License.\\n * ======================================================================== */\\n\\n\\n+function ($) { \\\"use strict\\\";\\n\\n  // TOOLTIP PUBLIC CLASS DEFINITION\\n  // ===============================\\n\\n  var Tooltip = function (element, options) {\\n    this.type       =\\n    this.options    =\\n    this.enabled    =\\n    this.timeout    =\\n    this.hoverState =\\n    this.$element   = null\\n\\n    this.init('tooltip', element, options)\\n  }\\n\\n  Tooltip.DEFAULTS = {\\n    animation: true\\n  , placement: 'top'\\n  , selector: false\\n  , template: '<div class=\\\"tooltip\\\"><div class=\\\"tooltip-arrow\\\"></div><div class=\\\"tooltip-inner\\\"></div></div>'\\n  , trigger: 'hover focus'\\n  , title: ''\\n  , delay: 0\\n  , html: false\\n  , container: false\\n  }\\n\\n  Tooltip.prototype.init = function (type, element, options) {\\n    this.enabled  = true\\n    this.type     = type\\n    this.$element = $(element)\\n    this.options  = this.getOptions(options)\\n\\n    var triggers = this.options.trigger.split(' ')\\n\\n    for (var i = triggers.length; i--;) {\\n      var trigger = triggers[i]\\n\\n      if (trigger == 'click') {\\n        this.$element.on('click.' + this.type, this.options.selector, $.proxy(this.toggle, this))\\n      } else if (trigger != 'manual') {\\n        var eventIn  = trigger == 'hover' ? 'mouseenter' : 'focus'\\n        var eventOut = trigger == 'hover' ? 'mouseleave' : 'blur'\\n\\n        this.$element.on(eventIn  + '.' + this.type, this.options.selector, $.proxy(this.enter, this))\\n        this.$element.on(eventOut + '.' + this.type, this.options.selector, $.proxy(this.leave, this))\\n      }\\n    }\\n\\n    this.options.selector ?\\n      (this._options = $.extend({}, this.options, { trigger: 'manual', selector: '' })) :\\n      this.fixTitle()\\n  }\\n\\n  Tooltip.prototype.getDefaults = function () {\\n    return Tooltip.DEFAULTS\\n  }\\n\\n  Tooltip.prototype.getOptions = function (options) {\\n    options = $.extend({}, this.getDefaults(), this.$element.data(), options)\\n\\n    if (options.delay && typeof options.delay == 'number') {\\n      options.delay = {\\n        show: options.delay\\n      , hide: options.delay\\n      }\\n    }\\n\\n    return options\\n  }\\n\\n  Tooltip.prototype.getDelegateOptions = function () {\\n    var options  = {}\\n    var defaults = this.getDefaults()\\n\\n    this._options && $.each(this._options, function (key, value) {\\n      if (defaults[key] != value) options[key] = value\\n    })\\n\\n    return options\\n  }\\n\\n  Tooltip.prototype.enter = function (obj) {\\n    var self = obj instanceof this.constructor ?\\n      obj : $(obj.currentTarget)[this.type](this.getDelegateOptions()).data('bs.' + this.type)\\n\\n    clearTimeout(self.timeout)\\n\\n    self.hoverState = 'in'\\n\\n    if (!self.options.delay || !self.options.delay.show) return self.show()\\n\\n    self.timeout = setTimeout(function () {\\n      if (self.hoverState == 'in') self.show()\\n    }, self.options.delay.show)\\n  }\\n\\n  Tooltip.prototype.leave = function (obj) {\\n    var self = obj instanceof this.constructor ?\\n      obj : $(obj.currentTarget)[this.type](this.getDelegateOptions()).data('bs.' + this.type)\\n\\n    clearTimeout(self.timeout)\\n\\n    self.hoverState = 'out'\\n\\n    if (!self.options.delay || !self.options.delay.hide) return self.hide()\\n\\n    self.timeout = setTimeout(function () {\\n      if (self.hoverState == 'out') self.hide()\\n    }, self.options.delay.hide)\\n  }\\n\\n  Tooltip.prototype.show = function () {\\n    var e = $.Event('show.bs.'+ this.type)\\n\\n    if (this.hasContent() && this.enabled) {\\n      this.$element.trigger(e)\\n\\n      if (e.isDefaultPrevented()) return\\n\\n      var $tip = this.tip()\\n\\n      this.setContent()\\n\\n      if (this.options.animation) $tip.addClass('fade')\\n\\n      var placement = typeof this.options.placement == 'function' ?\\n        this.options.placement.call(this, $tip[0], this.$element[0]) :\\n        this.options.placement\\n\\n      var autoToken = /\\\\s?auto?\\\\s?/i\\n      var autoPlace = autoToken.test(placement)\\n      if (autoPlace) placement = placement.replace(autoToken, '') || 'top'\\n\\n      $tip\\n        .detach()\\n        .css({ top: 0, left: 0, display: 'block' })\\n        .addClass(placement)\\n\\n      this.options.container ? $tip.appendTo(this.options.container) : $tip.insertAfter(this.$element)\\n\\n      var pos          = this.getPosition()\\n      var actualWidth  = $tip[0].offsetWidth\\n      var actualHeight = $tip[0].offsetHeight\\n\\n      if (autoPlace) {\\n        var $parent = this.$element.parent()\\n\\n        var orgPlacement = placement\\n        var docScroll    = document.documentElement.scrollTop || document.body.scrollTop\\n        var parentWidth  = this.options.container == 'body' ? window.innerWidth  : $parent.outerWidth()\\n        var parentHeight = this.options.container == 'body' ? window.innerHeight : $parent.outerHeight()\\n        var parentLeft   = this.options.container == 'body' ? 0 : $parent.offset().left\\n\\n        placement = placement == 'bottom' && pos.top   + pos.height  + actualHeight - docScroll > parentHeight  ? 'top'    :\\n                    placement == 'top'    && pos.top   - docScroll   - actualHeight < 0                         ? 'bottom' :\\n                    placement == 'right'  && pos.right + actualWidth > parentWidth                              ? 'left'   :\\n                    placement == 'left'   && pos.left  - actualWidth < parentLeft                               ? 'right'  :\\n                    placement\\n\\n        $tip\\n          .removeClass(orgPlacement)\\n          .addClass(placement)\\n      }\\n\\n      var calculatedOffset = this.getCalculatedOffset(placement, pos, actualWidth, actualHeight)\\n\\n      this.applyPlacement(calculatedOffset, placement)\\n      this.$element.trigger('shown.bs.' + this.type)\\n    }\\n  }\\n\\n  Tooltip.prototype.applyPlacement = function(offset, placement) {\\n    var replace\\n    var $tip   = this.tip()\\n    var width  = $tip[0].offsetWidth\\n    var height = $tip[0].offsetHeight\\n\\n    // manually read margins because getBoundingClientRect includes difference\\n    var marginTop = parseInt($tip.css('margin-top'), 10)\\n    var marginLeft = parseInt($tip.css('margin-left'), 10)\\n\\n    // we must check for NaN for ie 8/9\\n    if (isNaN(marginTop))  marginTop  = 0\\n    if (isNaN(marginLeft)) marginLeft = 0\\n\\n    offset.top  = offset.top  + marginTop\\n    offset.left = offset.left + marginLeft\\n\\n    $tip\\n      .offset(offset)\\n      .addClass('in')\\n\\n    // check to see if placing tip in new offset caused the tip to resize itself\\n    var actualWidth  = $tip[0].offsetWidth\\n    var actualHeight = $tip[0].offsetHeight\\n\\n    if (placement == 'top' && actualHeight != height) {\\n      replace = true\\n      offset.top = offset.top + height - actualHeight\\n    }\\n\\n    if (/bottom|top/.test(placement)) {\\n      var delta = 0\\n\\n      if (offset.left < 0) {\\n        delta       = offset.left * -2\\n        offset.left = 0\\n\\n        $tip.offset(offset)\\n\\n        actualWidth  = $tip[0].offsetWidth\\n        actualHeight = $tip[0].offsetHeight\\n      }\\n\\n      this.replaceArrow(delta - width + actualWidth, actualWidth, 'left')\\n    } else {\\n      this.replaceArrow(actualHeight - height, actualHeight, 'top')\\n    }\\n\\n    if (replace) $tip.offset(offset)\\n  }\\n\\n  Tooltip.prototype.replaceArrow = function(delta, dimension, position) {\\n    this.arrow().css(position, delta ? (50 * (1 - delta / dimension) + \\\"%\\\") : '')\\n  }\\n\\n  Tooltip.prototype.setContent = function () {\\n    var $tip  = this.tip()\\n    var title = this.getTitle()\\n\\n    $tip.find('.tooltip-inner')[this.options.html ? 'html' : 'text'](title)\\n    $tip.removeClass('fade in top bottom left right')\\n  }\\n\\n  Tooltip.prototype.hide = function () {\\n    var that = this\\n    var $tip = this.tip()\\n    var e    = $.Event('hide.bs.' + this.type)\\n\\n    function complete() {\\n      if (that.hoverState != 'in') $tip.detach()\\n    }\\n\\n    this.$element.trigger(e)\\n\\n    if (e.isDefaultPrevented()) return\\n\\n    $tip.removeClass('in')\\n\\n    $.support.transition && this.$tip.hasClass('fade') ?\\n      $tip\\n        .one($.support.transition.end, complete)\\n        .emulateTransitionEnd(150) :\\n      complete()\\n\\n    this.$element.trigger('hidden.bs.' + this.type)\\n\\n    return this\\n  }\\n\\n  Tooltip.prototype.fixTitle = function () {\\n    var $e = this.$element\\n    if ($e.attr('title') || typeof($e.attr('data-original-title')) != 'string') {\\n      $e.attr('data-original-title', $e.attr('title') || '').attr('title', '')\\n    }\\n  }\\n\\n  Tooltip.prototype.hasContent = function () {\\n    return this.getTitle()\\n  }\\n\\n  Tooltip.prototype.getPosition = function () {\\n    var el = this.$element[0]\\n    return $.extend({}, (typeof el.getBoundingClientRect == 'function') ? el.getBoundingClientRect() : {\\n      width: el.offsetWidth\\n    , height: el.offsetHeight\\n    }, this.$element.offset())\\n  }\\n\\n  Tooltip.prototype.getCalculatedOffset = function (placement, pos, actualWidth, actualHeight) {\\n    return placement == 'bottom' ? { top: pos.top + pos.height,   left: pos.left + pos.width / 2 - actualWidth / 2  } :\\n           placement == 'top'    ? { top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2  } :\\n           placement == 'left'   ? { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth } :\\n        /* placement == 'right' */ { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width   }\\n  }\\n\\n  Tooltip.prototype.getTitle = function () {\\n    var title\\n    var $e = this.$element\\n    var o  = this.options\\n\\n    title = $e.attr('data-original-title')\\n      || (typeof o.title == 'function' ? o.title.call($e[0]) :  o.title)\\n\\n    return title\\n  }\\n\\n  Tooltip.prototype.tip = function () {\\n    return this.$tip = this.$tip || $(this.options.template)\\n  }\\n\\n  Tooltip.prototype.arrow = function () {\\n    return this.$arrow = this.$arrow || this.tip().find('.tooltip-arrow')\\n  }\\n\\n  Tooltip.prototype.validate = function () {\\n    if (!this.$element[0].parentNode) {\\n      this.hide()\\n      this.$element = null\\n      this.options  = null\\n    }\\n  }\\n\\n  Tooltip.prototype.enable = function () {\\n    this.enabled = true\\n  }\\n\\n  Tooltip.prototype.disable = function () {\\n    this.enabled = false\\n  }\\n\\n  Tooltip.prototype.toggleEnabled = function () {\\n    this.enabled = !this.enabled\\n  }\\n\\n  Tooltip.prototype.toggle = function (e) {\\n    var self = e ? $(e.currentTarget)[this.type](this.getDelegateOptions()).data('bs.' + this.type) : this\\n    self.tip().hasClass('in') ? self.leave(self) : self.enter(self)\\n  }\\n\\n  Tooltip.prototype.destroy = function () {\\n    this.hide().$element.off('.' + this.type).removeData('bs.' + this.type)\\n  }\\n\\n\\n  // TOOLTIP PLUGIN DEFINITION\\n  // =========================\\n\\n  var old = $.fn.tooltip\\n\\n  $.fn.tooltip = function (option) {\\n    return this.each(function () {\\n      var $this   = $(this)\\n      var data    = $this.data('bs.tooltip')\\n      var options = typeof option == 'object' && option\\n\\n      if (!data) $this.data('bs.tooltip', (data = new Tooltip(this, options)))\\n      if (typeof option == 'string') data[option]()\\n    })\\n  }\\n\\n  $.fn.tooltip.Constructor = Tooltip\\n\\n\\n  // TOOLTIP NO CONFLICT\\n  // ===================\\n\\n  $.fn.tooltip.noConflict = function () {\\n    $.fn.tooltip = old\\n    return this\\n  }\\n\\n}(window.jQuery);\\n\",\"transition.js\":\"/* ========================================================================\\n * Bootstrap: transition.js v3.0.0\\n * http://twbs.github.com/bootstrap/javascript.html#transitions\\n * ========================================================================\\n * Copyright 2013 Twitter, Inc.\\n *\\n * Licensed under the Apache License, Version 2.0 (the \\\"License\\\");\\n * you may not use this file except in compliance with the License.\\n * You may obtain a copy of the License at\\n *\\n * http://www.apache.org/licenses/LICENSE-2.0\\n *\\n * Unless required by applicable law or agreed to in writing, software\\n * distributed under the License is distributed on an \\\"AS IS\\\" BASIS,\\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\\n * See the License for the specific language governing permissions and\\n * limitations under the License.\\n * ======================================================================== */\\n\\n\\n+function ($) { \\\"use strict\\\";\\n\\n  // CSS TRANSITION SUPPORT (Shoutout: http://www.modernizr.com/)\\n  // ============================================================\\n\\n  function transitionEnd() {\\n    var el = document.createElement('bootstrap')\\n\\n    var transEndEventNames = {\\n      'WebkitTransition' : 'webkitTransitionEnd'\\n    , 'MozTransition'    : 'transitionend'\\n    , 'OTransition'      : 'oTransitionEnd otransitionend'\\n    , 'transition'       : 'transitionend'\\n    }\\n\\n    for (var name in transEndEventNames) {\\n      if (el.style[name] !== undefined) {\\n        return { end: transEndEventNames[name] }\\n      }\\n    }\\n  }\\n\\n  // http://blog.alexmaccaw.com/css-transitions\\n  $.fn.emulateTransitionEnd = function (duration) {\\n    var called = false, $el = this\\n    $(this).one($.support.transition.end, function () { called = true })\\n    var callback = function () { if (!called) $($el).trigger($.support.transition.end) }\\n    setTimeout(callback, duration)\\n    return this\\n  }\\n\\n  $(function () {\\n    $.support.transition = transitionEnd()\\n  })\\n\\n}(window.jQuery);\\n\"}\nvar __less = {\"alerts.less\":\"//\\n// Alerts\\n// --------------------------------------------------\\n\\n\\n// Base styles\\n// -------------------------\\n\\n.alert {\\n  padding: @alert-padding;\\n  margin-bottom: @line-height-computed;\\n  border: 1px solid transparent;\\n  border-radius: @alert-border-radius;\\n\\n  // Headings for larger alerts\\n  h4 {\\n    margin-top: 0;\\n    // Specified for the h4 to prevent conflicts of changing @headingsColor\\n    color: inherit;\\n  }\\n  // Provide class for links that match alerts\\n  .alert-link {\\n    font-weight: @alert-link-font-weight;\\n  }\\n\\n  // Improve alignment and spacing of inner content\\n  > p,\\n  > ul {\\n    margin-bottom: 0;\\n  }\\n  > p + p {\\n    margin-top: 5px;\\n  }\\n}\\n\\n// Dismissable alerts\\n//\\n// Expand the right padding and account for the close button's positioning.\\n\\n.alert-dismissable {\\n padding-right: (@alert-padding + 20);\\n\\n  // Adjust close link position\\n  .close {\\n    position: relative;\\n    top: -2px;\\n    right: -21px;\\n    color: inherit;\\n  }\\n}\\n\\n// Alternate styles\\n//\\n// Generate contextual modifier classes for colorizing the alert.\\n\\n.alert-success {\\n  .alert-variant(@alert-success-bg; @alert-success-border; @alert-success-text);\\n}\\n.alert-info {\\n  .alert-variant(@alert-info-bg; @alert-info-border; @alert-info-text);\\n}\\n.alert-warning {\\n  .alert-variant(@alert-warning-bg; @alert-warning-border; @alert-warning-text);\\n}\\n.alert-danger {\\n  .alert-variant(@alert-danger-bg; @alert-danger-border; @alert-danger-text);\\n}\\n\",\"badges.less\":\"//\\n// Badges\\n// --------------------------------------------------\\n\\n\\n// Base classes\\n.badge {\\n  display: inline-block;\\n  min-width: 10px;\\n  padding: 3px 7px;\\n  font-size: @font-size-small;\\n  font-weight: @badge-font-weight;\\n  color: @badge-color;\\n  line-height: @badge-line-height;\\n  vertical-align: baseline;\\n  white-space: nowrap;\\n  text-align: center;\\n  background-color: @badge-bg;\\n  border-radius: @badge-border-radius;\\n\\n  // Empty badges collapse automatically (not available in IE8)\\n  &:empty {\\n    display: none;\\n  }\\n}\\n\\n// Hover state, but only for links\\na.badge {\\n  &:hover,\\n  &:focus {\\n    color: @badge-link-hover-color;\\n    text-decoration: none;\\n    cursor: pointer;\\n  }\\n}\\n\\n// Quick fix for labels/badges in buttons\\n.btn .badge {\\n  position: relative;\\n  top: -1px;\\n}\\n\\n// Account for counters in navs\\na.list-group-item.active > .badge,\\n.nav-pills > .active > a > .badge {\\n  color: @badge-active-color;\\n  background-color: @badge-active-bg;\\n}\\n.nav-pills > li > a > .badge {\\n  margin-left: 3px;\\n}\\n\",\"bootstrap.less\":\"/*!\\n * Bootstrap v3.0.0\\n *\\n * Copyright 2013 Twitter, Inc\\n * Licensed under the Apache License v2.0\\n * http://www.apache.org/licenses/LICENSE-2.0\\n *\\n * Designed and built with all the love in the world by @mdo and @fat.\\n */\\n\\n// Core variables and mixins\\n@import \\\"variables.less\\\";\\n@import \\\"mixins.less\\\";\\n\\n// Reset\\n@import \\\"normalize.less\\\";\\n@import \\\"print.less\\\";\\n\\n// Core CSS\\n@import \\\"scaffolding.less\\\";\\n@import \\\"type.less\\\";\\n@import \\\"code.less\\\";\\n@import \\\"grid.less\\\";\\n@import \\\"tables.less\\\";\\n@import \\\"forms.less\\\";\\n@import \\\"buttons.less\\\";\\n\\n// Components\\n@import \\\"component-animations.less\\\";\\n@import \\\"glyphicons.less\\\";\\n@import \\\"dropdowns.less\\\";\\n@import \\\"button-groups.less\\\";\\n@import \\\"input-groups.less\\\";\\n@import \\\"navs.less\\\";\\n@import \\\"navbar.less\\\";\\n@import \\\"breadcrumbs.less\\\";\\n@import \\\"pagination.less\\\";\\n@import \\\"pager.less\\\";\\n@import \\\"labels.less\\\";\\n@import \\\"badges.less\\\";\\n@import \\\"jumbotron.less\\\";\\n@import \\\"thumbnails.less\\\";\\n@import \\\"alerts.less\\\";\\n@import \\\"progress-bars.less\\\";\\n@import \\\"media.less\\\";\\n@import \\\"list-group.less\\\";\\n@import \\\"panels.less\\\";\\n@import \\\"wells.less\\\";\\n@import \\\"close.less\\\";\\n\\n// Components w/ JavaScript\\n@import \\\"modals.less\\\";\\n@import \\\"tooltip.less\\\";\\n@import \\\"popovers.less\\\";\\n@import \\\"carousel.less\\\";\\n\\n// Utility classes\\n@import \\\"utilities.less\\\";\\n@import \\\"responsive-utilities.less\\\";\\n\",\"breadcrumbs.less\":\"//\\n// Breadcrumbs\\n// --------------------------------------------------\\n\\n\\n.breadcrumb {\\n  padding: 8px 15px;\\n  margin-bottom: @line-height-computed;\\n  list-style: none;\\n  background-color: @breadcrumb-bg;\\n  border-radius: @border-radius-base;\\n  > li {\\n    display: inline-block;\\n    &+li:before {\\n      content: \\\"/\\\\00a0\\\"; // Unicode space added since inline-block means non-collapsing white-space\\n      padding: 0 5px;\\n      color: @breadcrumb-color;\\n    }\\n  }\\n  > .active {\\n    color: @breadcrumb-active-color;\\n  }\\n}\\n\",\"button-groups.less\":\"//\\n// Button groups\\n// --------------------------------------------------\\n\\n// Button carets\\n//\\n// Match the button text color to the arrow/caret for indicating dropdown-ness.\\n\\n.caret {\\n  .btn-default & {\\n    border-top-color: @btn-default-color;\\n  }\\n  .btn-primary &,\\n  .btn-success &,\\n  .btn-warning &,\\n  .btn-danger &,\\n  .btn-info & {\\n    border-top-color: #fff;\\n  }\\n}\\n.dropup {\\n  & .btn-default .caret {\\n    border-bottom-color: @btn-default-color;\\n  }\\n  .btn-primary,\\n  .btn-success,\\n  .btn-warning,\\n  .btn-danger,\\n  .btn-info {\\n   .caret {\\n      border-bottom-color: #fff;\\n    }\\n  }\\n}\\n\\n// Make the div behave like a button\\n.btn-group,\\n.btn-group-vertical {\\n  position: relative;\\n  display: inline-block;\\n  vertical-align: middle; // match .btn alignment given font-size hack above\\n  > .btn {\\n    position: relative;\\n    float: left;\\n    // Bring the \\\"active\\\" button to the front\\n    &:hover,\\n    &:focus,\\n    &:active,\\n    &.active {\\n      z-index: 2;\\n    }\\n    &:focus {\\n      // Remove focus outline when dropdown JS adds it after closing the menu\\n      outline: none;\\n    }\\n  }\\n}\\n\\n// Prevent double borders when buttons are next to each other\\n.btn-group {\\n  .btn + .btn,\\n  .btn + .btn-group,\\n  .btn-group + .btn,\\n  .btn-group + .btn-group {\\n    margin-left: -1px;\\n  }\\n}\\n\\n// Optional: Group multiple button groups together for a toolbar\\n.btn-toolbar {\\n  .clearfix();\\n\\n  .btn-group {\\n    float: left;\\n  }\\n  // Space out series of button groups\\n  > .btn,\\n  > .btn-group {\\n    + .btn,\\n    + .btn-group {\\n      margin-left: 5px;\\n    }\\n  }\\n}\\n\\n.btn-group > .btn:not(:first-child):not(:last-child):not(.dropdown-toggle) {\\n  border-radius: 0;\\n}\\n\\n// Set corners individual because sometimes a single button can be in a .btn-group and we need :first-child and :last-child to both match\\n.btn-group > .btn:first-child {\\n  margin-left: 0;\\n  &:not(:last-child):not(.dropdown-toggle) {\\n    .border-right-radius(0);\\n  }\\n}\\n// Need .dropdown-toggle since :last-child doesn't apply given a .dropdown-menu immediately after it\\n.btn-group > .btn:last-child:not(:first-child),\\n.btn-group > .dropdown-toggle:not(:first-child) {\\n  .border-left-radius(0);\\n}\\n\\n// Custom edits for including btn-groups within btn-groups (useful for including dropdown buttons within a btn-group)\\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 {\\n  > .btn:last-child,\\n  > .dropdown-toggle {\\n    .border-right-radius(0);\\n  }\\n}\\n.btn-group > .btn-group:last-child > .btn:first-child {\\n  .border-left-radius(0);\\n}\\n\\n// On active and open, don't show outline\\n.btn-group .dropdown-toggle:active,\\n.btn-group.open .dropdown-toggle {\\n  outline: 0;\\n}\\n\\n\\n// Sizing\\n//\\n// Remix the default button sizing classes into new ones for easier manipulation.\\n\\n.btn-group-xs > .btn { .btn-xs(); }\\n.btn-group-sm > .btn { .btn-sm(); }\\n.btn-group-lg > .btn { .btn-lg(); }\\n\\n\\n// Split button dropdowns\\n// ----------------------\\n\\n// Give the line between buttons some depth\\n.btn-group > .btn + .dropdown-toggle {\\n  padding-left: 8px;\\n  padding-right: 8px;\\n}\\n.btn-group > .btn-lg + .dropdown-toggle {\\n  padding-left: 12px;\\n  padding-right: 12px;\\n}\\n\\n// The clickable button for toggling the menu\\n// Remove the gradient and set the same inset shadow as the :active state\\n.btn-group.open .dropdown-toggle {\\n  .box-shadow(inset 0 3px 5px rgba(0,0,0,.125));\\n}\\n\\n\\n// Reposition the caret\\n.btn .caret {\\n  margin-left: 0;\\n}\\n// Carets in other button sizes\\n.btn-lg .caret {\\n  border-width: @caret-width-large @caret-width-large 0;\\n  border-bottom-width: 0;\\n}\\n// Upside down carets for .dropup\\n.dropup .btn-lg .caret {\\n  border-width: 0 @caret-width-large @caret-width-large;\\n}\\n\\n\\n// Vertical button groups\\n// ----------------------\\n\\n.btn-group-vertical {\\n  > .btn,\\n  > .btn-group {\\n    display: block;\\n    float: none;\\n    width: 100%;\\n    max-width: 100%;\\n  }\\n\\n  // Clear floats so dropdown menus can be properly placed\\n  > .btn-group {\\n    .clearfix();\\n    > .btn {\\n      float: none;\\n    }\\n  }\\n\\n  > .btn + .btn,\\n  > .btn + .btn-group,\\n  > .btn-group + .btn,\\n  > .btn-group + .btn-group {\\n    margin-top: -1px;\\n    margin-left: 0;\\n  }\\n}\\n\\n.btn-group-vertical > .btn {\\n  &:not(:first-child):not(:last-child) {\\n    border-radius: 0;\\n  }\\n  &:first-child:not(:last-child) {\\n    border-top-right-radius: @border-radius-base;\\n    .border-bottom-radius(0);\\n  }\\n  &:last-child:not(:first-child) {\\n    border-bottom-left-radius: @border-radius-base;\\n    .border-top-radius(0);\\n  }\\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 {\\n  > .btn:last-child,\\n  > .dropdown-toggle {\\n    .border-bottom-radius(0);\\n  }\\n}\\n.btn-group-vertical > .btn-group:last-child > .btn:first-child {\\n  .border-top-radius(0);\\n}\\n\\n\\n\\n// Justified button groups\\n// ----------------------\\n\\n.btn-group-justified {\\n  display: table;\\n  width: 100%;\\n  table-layout: fixed;\\n  border-collapse: separate;\\n  .btn {\\n    float: none;\\n    display: table-cell;\\n    width: 1%;\\n  }\\n}\\n\\n\\n// Checkbox and radio options\\n[data-toggle=\\\"buttons\\\"] > .btn > input[type=\\\"radio\\\"],\\n[data-toggle=\\\"buttons\\\"] > .btn > input[type=\\\"checkbox\\\"] {\\n  display: none;\\n}\\n\",\"buttons.less\":\"//\\n// Buttons\\n// --------------------------------------------------\\n\\n\\n// Base styles\\n// --------------------------------------------------\\n\\n// Core styles\\n.btn {\\n  display: inline-block;\\n  padding: @padding-base-vertical @padding-base-horizontal;\\n  margin-bottom: 0; // For input.btn\\n  font-size: @font-size-base;\\n  font-weight: @btn-font-weight;\\n  line-height: @line-height-base;\\n  text-align: center;\\n  vertical-align: middle;\\n  cursor: pointer;\\n  border: 1px solid transparent;\\n  border-radius: @border-radius-base;\\n  white-space: nowrap;\\n  .user-select(none);\\n\\n  &:focus {\\n    .tab-focus();\\n  }\\n\\n  &:hover,\\n  &:focus {\\n    color: @btn-default-color;\\n    text-decoration: none;\\n  }\\n\\n  &:active,\\n  &.active {\\n    outline: 0;\\n    background-image: none;\\n    .box-shadow(inset 0 3px 5px rgba(0,0,0,.125));\\n  }\\n\\n  &.disabled,\\n  &[disabled],\\n  fieldset[disabled] & {\\n    cursor: not-allowed;\\n    pointer-events: none; // Future-proof disabling of clicks\\n    .opacity(.65);\\n    .box-shadow(none);\\n  }\\n\\n}\\n\\n\\n// Alternate buttons\\n// --------------------------------------------------\\n\\n.btn-default {\\n  .button-variant(@btn-default-color; @btn-default-bg; @btn-default-border);\\n}\\n.btn-primary {\\n  .button-variant(@btn-primary-color; @btn-primary-bg; @btn-primary-border);\\n}\\n// Warning appears as orange\\n.btn-warning {\\n  .button-variant(@btn-warning-color; @btn-warning-bg; @btn-warning-border);\\n}\\n// Danger and error appear as red\\n.btn-danger {\\n  .button-variant(@btn-danger-color; @btn-danger-bg; @btn-danger-border);\\n}\\n// Success appears as green\\n.btn-success {\\n  .button-variant(@btn-success-color; @btn-success-bg; @btn-success-border);\\n}\\n// Info appears as blue-green\\n.btn-info {\\n  .button-variant(@btn-info-color; @btn-info-bg; @btn-info-border);\\n}\\n\\n\\n// Link buttons\\n// -------------------------\\n\\n// Make a button look and behave like a link\\n.btn-link {\\n  color: @link-color;\\n  font-weight: normal;\\n  cursor: pointer;\\n  border-radius: 0;\\n\\n  &,\\n  &:active,\\n  &[disabled],\\n  fieldset[disabled] & {\\n    background-color: transparent;\\n    .box-shadow(none);\\n  }\\n  &,\\n  &:hover,\\n  &:focus,\\n  &:active {\\n    border-color: transparent;\\n  }\\n  &:hover,\\n  &:focus {\\n    color: @link-hover-color;\\n    text-decoration: underline;\\n    background-color: transparent;\\n  }\\n  &[disabled],\\n  fieldset[disabled] & {\\n    &:hover,\\n    &:focus {\\n      color: @btn-link-disabled-color;\\n      text-decoration: none;\\n    }\\n  }\\n}\\n\\n\\n// Button Sizes\\n// --------------------------------------------------\\n\\n.btn-lg {\\n  // line-height: ensure even-numbered height of button next to large input\\n  .button-size(@padding-large-vertical; @padding-large-horizontal; @font-size-large; @line-height-large; @border-radius-large);\\n}\\n.btn-sm,\\n.btn-xs {\\n  // line-height: ensure proper height of button next to small input\\n  .button-size(@padding-small-vertical; @padding-small-horizontal; @font-size-small; @line-height-small; @border-radius-small);\\n}\\n.btn-xs {\\n  padding: 1px 5px;\\n}\\n\\n\\n// Block button\\n// --------------------------------------------------\\n\\n.btn-block {\\n  display: block;\\n  width: 100%;\\n  padding-left: 0;\\n  padding-right: 0;\\n}\\n\\n// Vertically space out multiple block buttons\\n.btn-block + .btn-block {\\n  margin-top: 5px;\\n}\\n\\n// Specificity overrides\\ninput[type=\\\"submit\\\"],\\ninput[type=\\\"reset\\\"],\\ninput[type=\\\"button\\\"] {\\n  &.btn-block {\\n    width: 100%;\\n  }\\n}\\n\",\"carousel.less\":\"//\\n// Carousel\\n// --------------------------------------------------\\n\\n\\n// Wrapper for the slide container and indicators\\n.carousel {\\n  position: relative;\\n}\\n\\n.carousel-inner {\\n  position: relative;\\n  overflow: hidden;\\n  width: 100%;\\n\\n  > .item {\\n    display: none;\\n    position: relative;\\n    .transition(.6s ease-in-out left);\\n\\n    // Account for jankitude on images\\n    > img,\\n    > a > img {\\n      .img-responsive();\\n      line-height: 1;\\n    }\\n  }\\n\\n  > .active,\\n  > .next,\\n  > .prev { display: block; }\\n\\n  > .active {\\n    left: 0;\\n  }\\n\\n  > .next,\\n  > .prev {\\n    position: absolute;\\n    top: 0;\\n    width: 100%;\\n  }\\n\\n  > .next {\\n    left: 100%;\\n  }\\n  > .prev {\\n    left: -100%;\\n  }\\n  > .next.left,\\n  > .prev.right {\\n    left: 0;\\n  }\\n\\n  > .active.left {\\n    left: -100%;\\n  }\\n  > .active.right {\\n    left: 100%;\\n  }\\n\\n}\\n\\n// Left/right controls for nav\\n// ---------------------------\\n\\n.carousel-control {\\n  position: absolute;\\n  top: 0;\\n  left: 0;\\n  bottom: 0;\\n  width: @carousel-control-width;\\n  .opacity(@carousel-control-opacity);\\n  font-size: @carousel-control-font-size;\\n  color: @carousel-control-color;\\n  text-align: center;\\n  text-shadow: @carousel-text-shadow;\\n  // We can't have this transition here because webkit cancels the carousel\\n  // animation if you trip this while in the middle of another animation.\\n\\n  // Set gradients for backgrounds\\n  &.left {\\n    #gradient > .horizontal(@start-color: rgba(0,0,0,.5); @end-color: rgba(0,0,0,.0001));\\n  }\\n  &.right {\\n    left: auto;\\n    right: 0;\\n    #gradient > .horizontal(@start-color: rgba(0,0,0,.0001); @end-color: rgba(0,0,0,.5));\\n  }\\n\\n  // Hover/focus state\\n  &:hover,\\n  &:focus {\\n    color: @carousel-control-color;\\n    text-decoration: none;\\n    .opacity(.9);\\n  }\\n\\n  // Toggles\\n  .icon-prev,\\n  .icon-next,\\n  .glyphicon-chevron-left,\\n  .glyphicon-chevron-right {\\n    position: absolute;\\n    top: 50%;\\n    left: 50%;\\n    z-index: 5;\\n    display: inline-block;\\n  }\\n  .icon-prev,\\n  .icon-next {\\n    width:  20px;\\n    height: 20px;\\n    margin-top: -10px;\\n    margin-left: -10px;\\n    font-family: serif;\\n  }\\n\\n  .icon-prev {\\n    &:before {\\n      content: '\\\\2039';// SINGLE LEFT-POINTING ANGLE QUOTATION MARK (U+2039)\\n    }\\n  }\\n  .icon-next {\\n    &:before {\\n      content: '\\\\203a';// SINGLE RIGHT-POINTING ANGLE QUOTATION MARK (U+203A)\\n    }\\n  }\\n}\\n\\n// Optional indicator pips\\n//\\n// Add an unordered list with the following class and add a list item for each\\n// slide your carousel holds.\\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  li {\\n    display: inline-block;\\n    width:  10px;\\n    height: 10px;\\n    margin: 1px;\\n    text-indent: -999px;\\n    border: 1px solid @carousel-indicator-border-color;\\n    border-radius: 10px;\\n    cursor: pointer;\\n  }\\n  .active {\\n    margin: 0;\\n    width:  12px;\\n    height: 12px;\\n    background-color: @carousel-indicator-active-bg;\\n  }\\n}\\n\\n// Optional captions\\n// -----------------------------\\n// Hidden by default for smaller viewports\\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: @carousel-caption-color;\\n  text-align: center;\\n  text-shadow: @carousel-text-shadow;\\n  & .btn {\\n    text-shadow: none; // No shadow for button elements in carousel-caption\\n  }\\n}\\n\\n\\n// Scale up controls for tablets and up\\n@media screen and (min-width: @screen-tablet) {\\n\\n  // Scale up the controls a smidge\\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\\n  // Show and left align the captions\\n  .carousel-caption {\\n    left: 20%;\\n    right: 20%;\\n    padding-bottom: 30px;\\n  }\\n\\n  // Move up the indicators\\n  .carousel-indicators {\\n    bottom: 20px;\\n  }\\n}\\n\",\"close.less\":\"//\\n// Close icons\\n// --------------------------------------------------\\n\\n\\n.close {\\n  float: right;\\n  font-size: (@font-size-base * 1.5);\\n  font-weight: @close-font-weight;\\n  line-height: 1;\\n  color: @close-color;\\n  text-shadow: @close-text-shadow;\\n  .opacity(.2);\\n\\n  &:hover,\\n  &:focus {\\n    color: @close-color;\\n    text-decoration: none;\\n    cursor: pointer;\\n    .opacity(.5);\\n  }\\n\\n  // Additional properties for button version\\n  // iOS requires the button element instead of an anchor tag.\\n  // If you want the anchor version, it requires `href=\\\"#\\\"`.\\n  button& {\\n    padding: 0;\\n    cursor: pointer;\\n    background: transparent;\\n    border: 0;\\n    -webkit-appearance: none;\\n  }\\n}\\n\",\"code.less\":\"//\\n// Code (inline and blocK)\\n// --------------------------------------------------\\n\\n\\n// Inline and block code styles\\ncode,\\npre {\\n  font-family: @font-family-monospace;\\n}\\n\\n// Inline code\\ncode {\\n  padding: 2px 4px;\\n  font-size: 90%;\\n  color: @code-color;\\n  background-color: @code-bg;\\n  white-space: nowrap;\\n  border-radius: @border-radius-base;\\n}\\n\\n// Blocks of code\\npre {\\n  display: block;\\n  padding: ((@line-height-computed - 1) / 2);\\n  margin: 0 0 (@line-height-computed / 2);\\n  font-size: (@font-size-base - 1); // 14px to 13px\\n  line-height: @line-height-base;\\n  word-break: break-all;\\n  word-wrap: break-word;\\n  color: @pre-color;\\n  background-color: @pre-bg;\\n  border: 1px solid @pre-border-color;\\n  border-radius: @border-radius-base;\\n\\n  // Make prettyprint styles more spaced out for readability\\n  &.prettyprint {\\n    margin-bottom: @line-height-computed;\\n  }\\n\\n  // Account for some code outputs that place code tags in pre tags\\n  code {\\n    padding: 0;\\n    font-size: inherit;\\n    color: inherit;\\n    white-space: pre-wrap;\\n    background-color: transparent;\\n    border: 0;\\n  }\\n}\\n\\n// Enable scrollable blocks of code\\n.pre-scrollable {\\n  max-height: @pre-scrollable-max-height;\\n  overflow-y: scroll;\\n}\\n\",\"component-animations.less\":\"//\\n// Component animations\\n// --------------------------------------------------\\n\\n// Heads up!\\n//\\n// We don't use the `.opacity()` mixin here since it causes a bug with text\\n// fields in IE7-8. Source: https://github.com/twitter/bootstrap/pull/3552.\\n\\n.fade {\\n  opacity: 0;\\n  .transition(opacity .15s linear);\\n  &.in {\\n    opacity: 1;\\n  }\\n}\\n\\n.collapse {\\n  display: none;\\n  &.in {\\n    display: block;\\n  }\\n}\\n.collapsing {\\n  position: relative;\\n  height: 0;\\n  overflow: hidden;\\n  .transition(height .35s ease);\\n}\\n\",\"dropdowns.less\":\"//\\n// Dropdown menus\\n// --------------------------------------------------\\n\\n\\n// Dropdown arrow/caret\\n.caret {\\n  display: inline-block;\\n  width: 0;\\n  height: 0;\\n  margin-left: 2px;\\n  vertical-align: middle;\\n  border-top:   @caret-width-base solid @dropdown-caret-color;\\n  border-right: @caret-width-base solid transparent;\\n  border-left:  @caret-width-base solid transparent;\\n  // Firefox fix for https://github.com/twbs/bootstrap/issues/9538. Once fixed,\\n  // we can just straight up remove this.\\n  border-bottom: 0 dotted;\\n  content: \\\"\\\";\\n}\\n\\n// The dropdown wrapper (div)\\n.dropdown {\\n  position: relative;\\n}\\n\\n// Prevent the focus on the dropdown toggle when closing dropdowns\\n.dropdown-toggle:focus {\\n  outline: 0;\\n}\\n\\n// The dropdown menu (ul)\\n.dropdown-menu {\\n  position: absolute;\\n  top: 100%;\\n  left: 0;\\n  z-index: @zindex-dropdown;\\n  display: none; // none by default, but block on \\\"open\\\" of the menu\\n  float: left;\\n  min-width: 160px;\\n  padding: 5px 0;\\n  margin: 2px 0 0; // override default ul\\n  list-style: none;\\n  font-size: @font-size-base;\\n  background-color: @dropdown-bg;\\n  border: 1px solid @dropdown-fallback-border; // IE8 fallback\\n  border: 1px solid @dropdown-border;\\n  border-radius: @border-radius-base;\\n  .box-shadow(0 6px 12px rgba(0,0,0,.175));\\n  background-clip: padding-box;\\n\\n  // Aligns the dropdown menu to right\\n  &.pull-right {\\n    right: 0;\\n    left: auto;\\n  }\\n\\n  // Dividers (basically an hr) within the dropdown\\n  .divider {\\n    .nav-divider(@dropdown-divider-bg);\\n  }\\n\\n  // Links within the dropdown menu\\n  > li > a {\\n    display: block;\\n    padding: 3px 20px;\\n    clear: both;\\n    font-weight: normal;\\n    line-height: @line-height-base;\\n    color: @dropdown-link-color;\\n    white-space: nowrap; // prevent links from randomly breaking onto new lines\\n  }\\n}\\n\\n// Hover/Focus state\\n.dropdown-menu > li > a {\\n  &:hover,\\n  &:focus {\\n    text-decoration: none;\\n    color: @dropdown-link-hover-color;\\n    background-color: @dropdown-link-hover-bg;\\n  }\\n}\\n\\n// Active state\\n.dropdown-menu > .active > a {\\n  &,\\n  &:hover,\\n  &:focus {\\n    color: @dropdown-link-active-color;\\n    text-decoration: none;\\n    outline: 0;\\n    background-color: @dropdown-link-active-bg;\\n  }\\n}\\n\\n// Disabled state\\n//\\n// Gray out text and ensure the hover/focus state remains gray\\n\\n.dropdown-menu > .disabled > a {\\n  &,\\n  &:hover,\\n  &:focus {\\n    color: @dropdown-link-disabled-color;\\n  }\\n}\\n// Nuke hover/focus effects\\n.dropdown-menu > .disabled > a {\\n  &:hover,\\n  &:focus {\\n    text-decoration: none;\\n    background-color: transparent;\\n    background-image: none; // Remove CSS gradient\\n    .reset-filter();\\n    cursor: not-allowed;\\n  }\\n}\\n\\n// Open state for the dropdown\\n.open {\\n  // Show the menu\\n  > .dropdown-menu {\\n    display: block;\\n  }\\n\\n  // Remove the outline when :focus is triggered\\n  > a {\\n    outline: 0;\\n  }\\n}\\n\\n// Dropdown section headers\\n.dropdown-header {\\n  display: block;\\n  padding: 3px 20px;\\n  font-size: @font-size-small;\\n  line-height: @line-height-base;\\n  color: @dropdown-header-color;\\n}\\n\\n// Backdrop to catch body clicks on mobile, etc.\\n.dropdown-backdrop {\\n  position: fixed;\\n  left: 0;\\n  right: 0;\\n  bottom: 0;\\n  top: 0;\\n  z-index: @zindex-dropdown - 10;\\n}\\n\\n// Right aligned dropdowns\\n.pull-right > .dropdown-menu {\\n  right: 0;\\n  left: auto;\\n}\\n\\n// Allow for dropdowns to go bottom up (aka, dropup-menu)\\n//\\n// Just add .dropup after the standard .dropdown class and you're set, bro.\\n// TODO: abstract this so that the navbar fixed styles are not placed here?\\n\\n.dropup,\\n.navbar-fixed-bottom .dropdown {\\n  // Reverse the caret\\n  .caret {\\n    // Firefox fix for https://github.com/twbs/bootstrap/issues/9538. Once this\\n    // gets fixed, restore `border-top: 0;`.\\n    border-top: 0 dotted;\\n    border-bottom: 4px solid @dropdown-caret-color;\\n    content: \\\"\\\";\\n  }\\n  // Different positioning for bottom up menu\\n  .dropdown-menu {\\n    top: auto;\\n    bottom: 100%;\\n    margin-bottom: 1px;\\n  }\\n}\\n\\n\\n// Component alignment\\n//\\n// Reiterate per navbar.less and the modified component alignment there.\\n\\n@media (min-width: @grid-float-breakpoint) {\\n  .navbar-right {\\n    .dropdown-menu {\\n      .pull-right > .dropdown-menu();\\n    }\\n  }\\n}\\n\\n\",\"forms.less\":\"//\\n// Forms\\n// --------------------------------------------------\\n\\n\\n// Normalize non-controls\\n//\\n// Restyle and baseline non-control form elements.\\n\\nfieldset {\\n  padding: 0;\\n  margin: 0;\\n  border: 0;\\n}\\n\\nlegend {\\n  display: block;\\n  width: 100%;\\n  padding: 0;\\n  margin-bottom: @line-height-computed;\\n  font-size: (@font-size-base * 1.5);\\n  line-height: inherit;\\n  color: @legend-color;\\n  border: 0;\\n  border-bottom: 1px solid @legend-border-color;\\n}\\n\\nlabel {\\n  display: inline-block;\\n  margin-bottom: 5px;\\n  font-weight: bold;\\n}\\n\\n\\n// Normalize form controls\\n\\n// Override content-box in Normalize (* isn't specific enough)\\ninput[type=\\\"search\\\"] {\\n  .box-sizing(border-box);\\n}\\n\\n// Position radios and checkboxes better\\ninput[type=\\\"radio\\\"],\\ninput[type=\\\"checkbox\\\"] {\\n  margin: 4px 0 0;\\n  margin-top: 1px \\\\9; /* IE8-9 */\\n  line-height: normal;\\n}\\n\\n// Set the height of select and file controls to match text inputs\\ninput[type=\\\"file\\\"] {\\n  display: block;\\n}\\n\\n// Make multiple select elements height not fixed\\nselect[multiple],\\nselect[size] {\\n  height: auto;\\n}\\n\\n// Fix optgroup Firefox bug per https://github.com/twbs/bootstrap/issues/7611\\nselect optgroup {\\n  font-size: inherit;\\n  font-style: inherit;\\n  font-family: inherit;\\n}\\n\\n// Focus for select, file, radio, and checkbox\\ninput[type=\\\"file\\\"]:focus,\\ninput[type=\\\"radio\\\"]:focus,\\ninput[type=\\\"checkbox\\\"]:focus {\\n  .tab-focus();\\n}\\n\\n// Fix for Chrome number input\\n// Setting certain font-sizes causes the `I` bar to appear on hover of the bottom increment button.\\n// See https://github.com/twbs/bootstrap/issues/8350 for more.\\ninput[type=\\\"number\\\"] {\\n  &::-webkit-outer-spin-button,\\n  &::-webkit-inner-spin-button {\\n    height: auto;\\n  }\\n}\\n\\n\\n// Placeholder\\n//\\n// Placeholder text gets special styles because when browsers invalidate entire\\n// lines if it doesn't understand a selector/\\n.form-control {\\n  .placeholder();\\n}\\n\\n\\n// Common form controls\\n//\\n// Shared size and type resets for form controls. Apply `.form-control` to any\\n// of the following form controls:\\n//\\n// select\\n// textarea\\n// input[type=\\\"text\\\"]\\n// input[type=\\\"password\\\"]\\n// input[type=\\\"datetime\\\"]\\n// input[type=\\\"datetime-local\\\"]\\n// input[type=\\\"date\\\"]\\n// input[type=\\\"month\\\"]\\n// input[type=\\\"time\\\"]\\n// input[type=\\\"week\\\"]\\n// input[type=\\\"number\\\"]\\n// input[type=\\\"email\\\"]\\n// input[type=\\\"url\\\"]\\n// input[type=\\\"search\\\"]\\n// input[type=\\\"tel\\\"]\\n// input[type=\\\"color\\\"]\\n\\n.form-control {\\n  display: block;\\n  width: 100%;\\n  height: @input-height-base; // Make inputs at least the height of their button counterpart (base line-height + padding + border)\\n  padding: @padding-base-vertical @padding-base-horizontal;\\n  font-size: @font-size-base;\\n  line-height: @line-height-base;\\n  color: @input-color;\\n  vertical-align: middle;\\n  background-color: @input-bg;\\n  border: 1px solid @input-border;\\n  border-radius: @input-border-radius;\\n  .box-shadow(inset 0 1px 1px rgba(0,0,0,.075));\\n  .transition(~\\\"border-color ease-in-out .15s, box-shadow ease-in-out .15s\\\");\\n\\n  // Customize the `:focus` state to imitate native WebKit styles.\\n  .form-control-focus();\\n\\n  // Disabled and read-only inputs\\n  // Note: HTML5 says that controls under a fieldset > legend:first-child won't\\n  // be disabled if the fieldset is disabled. Due to implementation difficulty,\\n  // we don't honor that edge case; we style them as disabled anyway.\\n  &[disabled],\\n  &[readonly],\\n  fieldset[disabled] & {\\n    cursor: not-allowed;\\n    background-color: @input-bg-disabled;\\n  }\\n\\n  // Reset height for `textarea`s\\n  textarea& {\\n    height: auto;\\n  }\\n}\\n\\n\\n// Form groups\\n//\\n// Designed to help with the organization and spacing of vertical forms. For\\n// horizontal forms, use the predefined grid classes.\\n\\n.form-group {\\n  margin-bottom: 15px;\\n}\\n\\n\\n// Checkboxes and radios\\n//\\n// Indent the labels to position radios/checkboxes as hanging controls.\\n\\n.radio,\\n.checkbox {\\n  display: block;\\n  min-height: @line-height-computed; // clear the floating input if there is no label text\\n  margin-top: 10px;\\n  margin-bottom: 10px;\\n  padding-left: 20px;\\n  vertical-align: middle;\\n  label {\\n    display: inline;\\n    margin-bottom: 0;\\n    font-weight: normal;\\n    cursor: pointer;\\n  }\\n}\\n.radio input[type=\\\"radio\\\"],\\n.radio-inline input[type=\\\"radio\\\"],\\n.checkbox input[type=\\\"checkbox\\\"],\\n.checkbox-inline input[type=\\\"checkbox\\\"] {\\n  float: left;\\n  margin-left: -20px;\\n}\\n.radio + .radio,\\n.checkbox + .checkbox {\\n  margin-top: -5px; // Move up sibling radios or checkboxes for tighter spacing\\n}\\n\\n// Radios and checkboxes on same line\\n.radio-inline,\\n.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.radio-inline + .radio-inline,\\n.checkbox-inline + .checkbox-inline {\\n  margin-top: 0;\\n  margin-left: 10px; // space out consecutive inline controls\\n}\\n\\n// Apply same disabled cursor tweak as for inputs\\n//\\n// Note: Neither radios nor checkboxes can be readonly.\\ninput[type=\\\"radio\\\"],\\ninput[type=\\\"checkbox\\\"],\\n.radio,\\n.radio-inline,\\n.checkbox,\\n.checkbox-inline {\\n  &[disabled],\\n  fieldset[disabled] & {\\n    cursor: not-allowed;\\n  }\\n}\\n\\n// Form control sizing\\n.input-sm {\\n  .input-size(@input-height-small; @padding-small-vertical; @padding-small-horizontal; @font-size-small; @line-height-small; @border-radius-small);\\n}\\n\\n.input-lg {\\n  .input-size(@input-height-large; @padding-large-vertical; @padding-large-horizontal; @font-size-large; @line-height-large; @border-radius-large);\\n}\\n\\n\\n// Form control feedback states\\n//\\n// Apply contextual and semantic states to individual form controls.\\n\\n// Warning\\n.has-warning {\\n  .form-control-validation(@state-warning-text; @state-warning-text; @state-warning-bg);\\n}\\n// Error\\n.has-error {\\n  .form-control-validation(@state-danger-text; @state-danger-text; @state-danger-bg);\\n}\\n// Success\\n.has-success {\\n  .form-control-validation(@state-success-text; @state-success-text; @state-success-bg);\\n}\\n\\n\\n// Static form control text\\n//\\n// Apply class to a `p` element to make any string of text align with labels in\\n// a horizontal form layout.\\n\\n.form-control-static {\\n  margin-bottom: 0; // Remove default margin from `p`\\n  padding-top: (@padding-base-vertical + 1);\\n}\\n\\n\\n// Help text\\n//\\n// Apply to any element you wish to create light text for placement immediately\\n// below a form control. Use for general help, formatting, or instructional text.\\n\\n.help-block {\\n  display: block; // account for any element using help-block\\n  margin-top: 5px;\\n  margin-bottom: 10px;\\n  color: lighten(@text-color, 25%); // lighten the text some for contrast\\n}\\n\\n\\n\\n// Inline forms\\n//\\n// Make forms appear inline(-block) by adding the `.form-inline` class. Inline\\n// forms begin stacked on extra small (mobile) devices and then go inline when\\n// viewports reach <768px.\\n//\\n// Requires wrapping inputs and labels with `.form-group` for proper display of\\n// default HTML form controls and our custom form controls (e.g., input groups).\\n//\\n// Heads up! This is mixin-ed into `.navbar-form` in navbars.less.\\n\\n.form-inline {\\n\\n  // Kick in the inline\\n  @media (min-width: @screen-tablet) {\\n    // Inline-block all the things for \\\"inline\\\"\\n    .form-group  {\\n      display: inline-block;\\n      margin-bottom: 0;\\n      vertical-align: middle;\\n    }\\n\\n    // In navbar-form, allow folks to *not* use `.form-group`\\n    .form-control {\\n      display: inline-block;\\n    }\\n\\n    // Remove default margin on radios/checkboxes that were used for stacking, and\\n    // then undo the floating of radios and checkboxes to match (which also avoids\\n    // a bug in WebKit: https://github.com/twbs/bootstrap/issues/1969).\\n    .radio,\\n    .checkbox {\\n      display: inline-block;\\n      margin-top: 0;\\n      margin-bottom: 0;\\n      padding-left: 0;\\n    }\\n    .radio input[type=\\\"radio\\\"],\\n    .checkbox input[type=\\\"checkbox\\\"] {\\n      float: none;\\n      margin-left: 0;\\n    }\\n  }\\n}\\n\\n\\n// Horizontal forms\\n//\\n// Horizontal forms are built on grid classes and allow you to create forms with\\n// labels on the left and inputs on the right.\\n\\n.form-horizontal {\\n\\n  // Consistent vertical alignment of labels, radios, and checkboxes\\n  .control-label,\\n  .radio,\\n  .checkbox,\\n  .radio-inline,\\n  .checkbox-inline {\\n    margin-top: 0;\\n    margin-bottom: 0;\\n    padding-top: (@padding-base-vertical + 1); // Default padding plus a border\\n  }\\n\\n  // Make form groups behave like rows\\n  .form-group {\\n    .make-row();\\n  }\\n\\n  // Only right align form labels here when the columns stop stacking\\n  @media (min-width: @screen-tablet) {\\n    .control-label {\\n      text-align: right;\\n    }\\n  }\\n}\\n\",\"glyphicons.less\":\"//\\n// Glyphicons for Bootstrap\\n//\\n// Since icons are fonts, they can be placed anywhere text is placed and are\\n// thus automatically sized to match the surrounding child. To use, create an\\n// inline element with the appropriate classes, like so:\\n//\\n// <a href=\\\"#\\\"><span class=\\\"glyphicon glyphicon-star\\\"></span> Star</a>\\n\\n// Import the fonts\\n@font-face {\\n  font-family: 'Glyphicons Halflings';\\n  src: url('@{icon-font-path}@{icon-font-name}.eot');\\n  src: url('@{icon-font-path}@{icon-font-name}.eot?#iefix') format('embedded-opentype'),\\n       url('@{icon-font-path}@{icon-font-name}.woff') format('woff'),\\n       url('@{icon-font-path}@{icon-font-name}.ttf') format('truetype'),\\n       url('@{icon-font-path}@{icon-font-name}.svg#glyphicons-halflingsregular') format('svg');\\n}\\n\\n// Catchall baseclass\\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  -webkit-font-smoothing: antialiased;\\n}\\n\\n// Individual icons\\n.glyphicon-asterisk               { &:before { content: \\\"\\\\2a\\\"; } }\\n.glyphicon-plus                   { &:before { content: \\\"\\\\2b\\\"; } }\\n.glyphicon-euro                   { &:before { content: \\\"\\\\20ac\\\"; } }\\n.glyphicon-minus                  { &:before { content: \\\"\\\\2212\\\"; } }\\n.glyphicon-cloud                  { &:before { content: \\\"\\\\2601\\\"; } }\\n.glyphicon-envelope               { &:before { content: \\\"\\\\2709\\\"; } }\\n.glyphicon-pencil                 { &:before { content: \\\"\\\\270f\\\"; } }\\n.glyphicon-glass                  { &:before { content: \\\"\\\\e001\\\"; } }\\n.glyphicon-music                  { &:before { content: \\\"\\\\e002\\\"; } }\\n.glyphicon-search                 { &:before { content: \\\"\\\\e003\\\"; } }\\n.glyphicon-heart                  { &:before { content: \\\"\\\\e005\\\"; } }\\n.glyphicon-star                   { &:before { content: \\\"\\\\e006\\\"; } }\\n.glyphicon-star-empty             { &:before { content: \\\"\\\\e007\\\"; } }\\n.glyphicon-user                   { &:before { content: \\\"\\\\e008\\\"; } }\\n.glyphicon-film                   { &:before { content: \\\"\\\\e009\\\"; } }\\n.glyphicon-th-large               { &:before { content: \\\"\\\\e010\\\"; } }\\n.glyphicon-th                     { &:before { content: \\\"\\\\e011\\\"; } }\\n.glyphicon-th-list                { &:before { content: \\\"\\\\e012\\\"; } }\\n.glyphicon-ok                     { &:before { content: \\\"\\\\e013\\\"; } }\\n.glyphicon-remove                 { &:before { content: \\\"\\\\e014\\\"; } }\\n.glyphicon-zoom-in                { &:before { content: \\\"\\\\e015\\\"; } }\\n.glyphicon-zoom-out               { &:before { content: \\\"\\\\e016\\\"; } }\\n.glyphicon-off                    { &:before { content: \\\"\\\\e017\\\"; } }\\n.glyphicon-signal                 { &:before { content: \\\"\\\\e018\\\"; } }\\n.glyphicon-cog                    { &:before { content: \\\"\\\\e019\\\"; } }\\n.glyphicon-trash                  { &:before { content: \\\"\\\\e020\\\"; } }\\n.glyphicon-home                   { &:before { content: \\\"\\\\e021\\\"; } }\\n.glyphicon-file                   { &:before { content: \\\"\\\\e022\\\"; } }\\n.glyphicon-time                   { &:before { content: \\\"\\\\e023\\\"; } }\\n.glyphicon-road                   { &:before { content: \\\"\\\\e024\\\"; } }\\n.glyphicon-download-alt           { &:before { content: \\\"\\\\e025\\\"; } }\\n.glyphicon-download               { &:before { content: \\\"\\\\e026\\\"; } }\\n.glyphicon-upload                 { &:before { content: \\\"\\\\e027\\\"; } }\\n.glyphicon-inbox                  { &:before { content: \\\"\\\\e028\\\"; } }\\n.glyphicon-play-circle            { &:before { content: \\\"\\\\e029\\\"; } }\\n.glyphicon-repeat                 { &:before { content: \\\"\\\\e030\\\"; } }\\n.glyphicon-refresh                { &:before { content: \\\"\\\\e031\\\"; } }\\n.glyphicon-list-alt               { &:before { content: \\\"\\\\e032\\\"; } }\\n.glyphicon-flag                   { &:before { content: \\\"\\\\e034\\\"; } }\\n.glyphicon-headphones             { &:before { content: \\\"\\\\e035\\\"; } }\\n.glyphicon-volume-off             { &:before { content: \\\"\\\\e036\\\"; } }\\n.glyphicon-volume-down            { &:before { content: \\\"\\\\e037\\\"; } }\\n.glyphicon-volume-up              { &:before { content: \\\"\\\\e038\\\"; } }\\n.glyphicon-qrcode                 { &:before { content: \\\"\\\\e039\\\"; } }\\n.glyphicon-barcode                { &:before { content: \\\"\\\\e040\\\"; } }\\n.glyphicon-tag                    { &:before { content: \\\"\\\\e041\\\"; } }\\n.glyphicon-tags                   { &:before { content: \\\"\\\\e042\\\"; } }\\n.glyphicon-book                   { &:before { content: \\\"\\\\e043\\\"; } }\\n.glyphicon-print                  { &:before { content: \\\"\\\\e045\\\"; } }\\n.glyphicon-font                   { &:before { content: \\\"\\\\e047\\\"; } }\\n.glyphicon-bold                   { &:before { content: \\\"\\\\e048\\\"; } }\\n.glyphicon-italic                 { &:before { content: \\\"\\\\e049\\\"; } }\\n.glyphicon-text-height            { &:before { content: \\\"\\\\e050\\\"; } }\\n.glyphicon-text-width             { &:before { content: \\\"\\\\e051\\\"; } }\\n.glyphicon-align-left             { &:before { content: \\\"\\\\e052\\\"; } }\\n.glyphicon-align-center           { &:before { content: \\\"\\\\e053\\\"; } }\\n.glyphicon-align-right            { &:before { content: \\\"\\\\e054\\\"; } }\\n.glyphicon-align-justify          { &:before { content: \\\"\\\\e055\\\"; } }\\n.glyphicon-list                   { &:before { content: \\\"\\\\e056\\\"; } }\\n.glyphicon-indent-left            { &:before { content: \\\"\\\\e057\\\"; } }\\n.glyphicon-indent-right           { &:before { content: \\\"\\\\e058\\\"; } }\\n.glyphicon-facetime-video         { &:before { content: \\\"\\\\e059\\\"; } }\\n.glyphicon-picture                { &:before { content: \\\"\\\\e060\\\"; } }\\n.glyphicon-map-marker             { &:before { content: \\\"\\\\e062\\\"; } }\\n.glyphicon-adjust                 { &:before { content: \\\"\\\\e063\\\"; } }\\n.glyphicon-tint                   { &:before { content: \\\"\\\\e064\\\"; } }\\n.glyphicon-edit                   { &:before { content: \\\"\\\\e065\\\"; } }\\n.glyphicon-share                  { &:before { content: \\\"\\\\e066\\\"; } }\\n.glyphicon-check                  { &:before { content: \\\"\\\\e067\\\"; } }\\n.glyphicon-move                   { &:before { content: \\\"\\\\e068\\\"; } }\\n.glyphicon-step-backward          { &:before { content: \\\"\\\\e069\\\"; } }\\n.glyphicon-fast-backward          { &:before { content: \\\"\\\\e070\\\"; } }\\n.glyphicon-backward               { &:before { content: \\\"\\\\e071\\\"; } }\\n.glyphicon-play                   { &:before { content: \\\"\\\\e072\\\"; } }\\n.glyphicon-pause                  { &:before { content: \\\"\\\\e073\\\"; } }\\n.glyphicon-stop                   { &:before { content: \\\"\\\\e074\\\"; } }\\n.glyphicon-forward                { &:before { content: \\\"\\\\e075\\\"; } }\\n.glyphicon-fast-forward           { &:before { content: \\\"\\\\e076\\\"; } }\\n.glyphicon-step-forward           { &:before { content: \\\"\\\\e077\\\"; } }\\n.glyphicon-eject                  { &:before { content: \\\"\\\\e078\\\"; } }\\n.glyphicon-chevron-left           { &:before { content: \\\"\\\\e079\\\"; } }\\n.glyphicon-chevron-right          { &:before { content: \\\"\\\\e080\\\"; } }\\n.glyphicon-plus-sign              { &:before { content: \\\"\\\\e081\\\"; } }\\n.glyphicon-minus-sign             { &:before { content: \\\"\\\\e082\\\"; } }\\n.glyphicon-remove-sign            { &:before { content: \\\"\\\\e083\\\"; } }\\n.glyphicon-ok-sign                { &:before { content: \\\"\\\\e084\\\"; } }\\n.glyphicon-question-sign          { &:before { content: \\\"\\\\e085\\\"; } }\\n.glyphicon-info-sign              { &:before { content: \\\"\\\\e086\\\"; } }\\n.glyphicon-screenshot             { &:before { content: \\\"\\\\e087\\\"; } }\\n.glyphicon-remove-circle          { &:before { content: \\\"\\\\e088\\\"; } }\\n.glyphicon-ok-circle              { &:before { content: \\\"\\\\e089\\\"; } }\\n.glyphicon-ban-circle             { &:before { content: \\\"\\\\e090\\\"; } }\\n.glyphicon-arrow-left             { &:before { content: \\\"\\\\e091\\\"; } }\\n.glyphicon-arrow-right            { &:before { content: \\\"\\\\e092\\\"; } }\\n.glyphicon-arrow-up               { &:before { content: \\\"\\\\e093\\\"; } }\\n.glyphicon-arrow-down             { &:before { content: \\\"\\\\e094\\\"; } }\\n.glyphicon-share-alt              { &:before { content: \\\"\\\\e095\\\"; } }\\n.glyphicon-resize-full            { &:before { content: \\\"\\\\e096\\\"; } }\\n.glyphicon-resize-small           { &:before { content: \\\"\\\\e097\\\"; } }\\n.glyphicon-exclamation-sign       { &:before { content: \\\"\\\\e101\\\"; } }\\n.glyphicon-gift                   { &:before { content: \\\"\\\\e102\\\"; } }\\n.glyphicon-leaf                   { &:before { content: \\\"\\\\e103\\\"; } }\\n.glyphicon-eye-open               { &:before { content: \\\"\\\\e105\\\"; } }\\n.glyphicon-eye-close              { &:before { content: \\\"\\\\e106\\\"; } }\\n.glyphicon-warning-sign           { &:before { content: \\\"\\\\e107\\\"; } }\\n.glyphicon-plane                  { &:before { content: \\\"\\\\e108\\\"; } }\\n.glyphicon-random                 { &:before { content: \\\"\\\\e110\\\"; } }\\n.glyphicon-comment                { &:before { content: \\\"\\\\e111\\\"; } }\\n.glyphicon-magnet                 { &:before { content: \\\"\\\\e112\\\"; } }\\n.glyphicon-chevron-up             { &:before { content: \\\"\\\\e113\\\"; } }\\n.glyphicon-chevron-down           { &:before { content: \\\"\\\\e114\\\"; } }\\n.glyphicon-retweet                { &:before { content: \\\"\\\\e115\\\"; } }\\n.glyphicon-shopping-cart          { &:before { content: \\\"\\\\e116\\\"; } }\\n.glyphicon-folder-close           { &:before { content: \\\"\\\\e117\\\"; } }\\n.glyphicon-folder-open            { &:before { content: \\\"\\\\e118\\\"; } }\\n.glyphicon-resize-vertical        { &:before { content: \\\"\\\\e119\\\"; } }\\n.glyphicon-resize-horizontal      { &:before { content: \\\"\\\\e120\\\"; } }\\n.glyphicon-hdd                    { &:before { content: \\\"\\\\e121\\\"; } }\\n.glyphicon-bullhorn               { &:before { content: \\\"\\\\e122\\\"; } }\\n.glyphicon-certificate            { &:before { content: \\\"\\\\e124\\\"; } }\\n.glyphicon-thumbs-up              { &:before { content: \\\"\\\\e125\\\"; } }\\n.glyphicon-thumbs-down            { &:before { content: \\\"\\\\e126\\\"; } }\\n.glyphicon-hand-right             { &:before { content: \\\"\\\\e127\\\"; } }\\n.glyphicon-hand-left              { &:before { content: \\\"\\\\e128\\\"; } }\\n.glyphicon-hand-up                { &:before { content: \\\"\\\\e129\\\"; } }\\n.glyphicon-hand-down              { &:before { content: \\\"\\\\e130\\\"; } }\\n.glyphicon-circle-arrow-right     { &:before { content: \\\"\\\\e131\\\"; } }\\n.glyphicon-circle-arrow-left      { &:before { content: \\\"\\\\e132\\\"; } }\\n.glyphicon-circle-arrow-up        { &:before { content: \\\"\\\\e133\\\"; } }\\n.glyphicon-circle-arrow-down      { &:before { content: \\\"\\\\e134\\\"; } }\\n.glyphicon-globe                  { &:before { content: \\\"\\\\e135\\\"; } }\\n.glyphicon-tasks                  { &:before { content: \\\"\\\\e137\\\"; } }\\n.glyphicon-filter                 { &:before { content: \\\"\\\\e138\\\"; } }\\n.glyphicon-fullscreen             { &:before { content: \\\"\\\\e140\\\"; } }\\n.glyphicon-dashboard              { &:before { content: \\\"\\\\e141\\\"; } }\\n.glyphicon-heart-empty            { &:before { content: \\\"\\\\e143\\\"; } }\\n.glyphicon-link                   { &:before { content: \\\"\\\\e144\\\"; } }\\n.glyphicon-phone                  { &:before { content: \\\"\\\\e145\\\"; } }\\n.glyphicon-usd                    { &:before { content: \\\"\\\\e148\\\"; } }\\n.glyphicon-gbp                    { &:before { content: \\\"\\\\e149\\\"; } }\\n.glyphicon-sort                   { &:before { content: \\\"\\\\e150\\\"; } }\\n.glyphicon-sort-by-alphabet       { &:before { content: \\\"\\\\e151\\\"; } }\\n.glyphicon-sort-by-alphabet-alt   { &:before { content: \\\"\\\\e152\\\"; } }\\n.glyphicon-sort-by-order          { &:before { content: \\\"\\\\e153\\\"; } }\\n.glyphicon-sort-by-order-alt      { &:before { content: \\\"\\\\e154\\\"; } }\\n.glyphicon-sort-by-attributes     { &:before { content: \\\"\\\\e155\\\"; } }\\n.glyphicon-sort-by-attributes-alt { &:before { content: \\\"\\\\e156\\\"; } }\\n.glyphicon-unchecked              { &:before { content: \\\"\\\\e157\\\"; } }\\n.glyphicon-expand                 { &:before { content: \\\"\\\\e158\\\"; } }\\n.glyphicon-collapse-down          { &:before { content: \\\"\\\\e159\\\"; } }\\n.glyphicon-collapse-up            { &:before { content: \\\"\\\\e160\\\"; } }\\n.glyphicon-log-in                 { &:before { content: \\\"\\\\e161\\\"; } }\\n.glyphicon-flash                  { &:before { content: \\\"\\\\e162\\\"; } }\\n.glyphicon-log-out                { &:before { content: \\\"\\\\e163\\\"; } }\\n.glyphicon-new-window             { &:before { content: \\\"\\\\e164\\\"; } }\\n.glyphicon-record                 { &:before { content: \\\"\\\\e165\\\"; } }\\n.glyphicon-save                   { &:before { content: \\\"\\\\e166\\\"; } }\\n.glyphicon-open                   { &:before { content: \\\"\\\\e167\\\"; } }\\n.glyphicon-saved                  { &:before { content: \\\"\\\\e168\\\"; } }\\n.glyphicon-import                 { &:before { content: \\\"\\\\e169\\\"; } }\\n.glyphicon-export                 { &:before { content: \\\"\\\\e170\\\"; } }\\n.glyphicon-send                   { &:before { content: \\\"\\\\e171\\\"; } }\\n.glyphicon-floppy-disk            { &:before { content: \\\"\\\\e172\\\"; } }\\n.glyphicon-floppy-saved           { &:before { content: \\\"\\\\e173\\\"; } }\\n.glyphicon-floppy-remove          { &:before { content: \\\"\\\\e174\\\"; } }\\n.glyphicon-floppy-save            { &:before { content: \\\"\\\\e175\\\"; } }\\n.glyphicon-floppy-open            { &:before { content: \\\"\\\\e176\\\"; } }\\n.glyphicon-credit-card            { &:before { content: \\\"\\\\e177\\\"; } }\\n.glyphicon-transfer               { &:before { content: \\\"\\\\e178\\\"; } }\\n.glyphicon-cutlery                { &:before { content: \\\"\\\\e179\\\"; } }\\n.glyphicon-header                 { &:before { content: \\\"\\\\e180\\\"; } }\\n.glyphicon-compressed             { &:before { content: \\\"\\\\e181\\\"; } }\\n.glyphicon-earphone               { &:before { content: \\\"\\\\e182\\\"; } }\\n.glyphicon-phone-alt              { &:before { content: \\\"\\\\e183\\\"; } }\\n.glyphicon-tower                  { &:before { content: \\\"\\\\e184\\\"; } }\\n.glyphicon-stats                  { &:before { content: \\\"\\\\e185\\\"; } }\\n.glyphicon-sd-video               { &:before { content: \\\"\\\\e186\\\"; } }\\n.glyphicon-hd-video               { &:before { content: \\\"\\\\e187\\\"; } }\\n.glyphicon-subtitles              { &:before { content: \\\"\\\\e188\\\"; } }\\n.glyphicon-sound-stereo           { &:before { content: \\\"\\\\e189\\\"; } }\\n.glyphicon-sound-dolby            { &:before { content: \\\"\\\\e190\\\"; } }\\n.glyphicon-sound-5-1              { &:before { content: \\\"\\\\e191\\\"; } }\\n.glyphicon-sound-6-1              { &:before { content: \\\"\\\\e192\\\"; } }\\n.glyphicon-sound-7-1              { &:before { content: \\\"\\\\e193\\\"; } }\\n.glyphicon-copyright-mark         { &:before { content: \\\"\\\\e194\\\"; } }\\n.glyphicon-registration-mark      { &:before { content: \\\"\\\\e195\\\"; } }\\n.glyphicon-cloud-download         { &:before { content: \\\"\\\\e197\\\"; } }\\n.glyphicon-cloud-upload           { &:before { content: \\\"\\\\e198\\\"; } }\\n.glyphicon-tree-conifer           { &:before { content: \\\"\\\\e199\\\"; } }\\n.glyphicon-tree-deciduous         { &:before { content: \\\"\\\\e200\\\"; } }\\n.glyphicon-briefcase              { &:before { content: \\\"\\\\1f4bc\\\"; } }\\n.glyphicon-calendar               { &:before { content: \\\"\\\\1f4c5\\\"; } }\\n.glyphicon-pushpin                { &:before { content: \\\"\\\\1f4cc\\\"; } }\\n.glyphicon-paperclip              { &:before { content: \\\"\\\\1f4ce\\\"; } }\\n.glyphicon-camera                 { &:before { content: \\\"\\\\1f4f7\\\"; } }\\n.glyphicon-lock                   { &:before { content: \\\"\\\\1f512\\\"; } }\\n.glyphicon-bell                   { &:before { content: \\\"\\\\1f514\\\"; } }\\n.glyphicon-bookmark               { &:before { content: \\\"\\\\1f516\\\"; } }\\n.glyphicon-fire                   { &:before { content: \\\"\\\\1f525\\\"; } }\\n.glyphicon-wrench                 { &:before { content: \\\"\\\\1f527\\\"; } }\\n\",\"grid.less\":\"//\\n// Grid system\\n// --------------------------------------------------\\n\\n\\n// Set the container width, and override it for fixed navbars in media queries\\n.container {\\n  .container-fixed();\\n}\\n\\n// mobile first defaults\\n.row {\\n  .make-row();\\n}\\n\\n// Common styles for small and large grid columns\\n.col-xs-1,\\n.col-xs-2,\\n.col-xs-3,\\n.col-xs-4,\\n.col-xs-5,\\n.col-xs-6,\\n.col-xs-7,\\n.col-xs-8,\\n.col-xs-9,\\n.col-xs-10,\\n.col-xs-11,\\n.col-xs-12,\\n.col-sm-1,\\n.col-sm-2,\\n.col-sm-3,\\n.col-sm-4,\\n.col-sm-5,\\n.col-sm-6,\\n.col-sm-7,\\n.col-sm-8,\\n.col-sm-9,\\n.col-sm-10,\\n.col-sm-11,\\n.col-sm-12,\\n.col-md-1,\\n.col-md-2,\\n.col-md-3,\\n.col-md-4,\\n.col-md-5,\\n.col-md-6,\\n.col-md-7,\\n.col-md-8,\\n.col-md-9,\\n.col-md-10,\\n.col-md-11,\\n.col-md-12,\\n.col-lg-1,\\n.col-lg-2,\\n.col-lg-3,\\n.col-lg-4,\\n.col-lg-5,\\n.col-lg-6,\\n.col-lg-7,\\n.col-lg-8,\\n.col-lg-9,\\n.col-lg-10,\\n.col-lg-11,\\n.col-lg-12 {\\n  position: relative;\\n  // Prevent columns from collapsing when empty\\n  min-height: 1px;\\n  // Inner gutter via padding\\n  padding-left:  (@grid-gutter-width / 2);\\n  padding-right: (@grid-gutter-width / 2);\\n}\\n\\n\\n// Extra small grid\\n//\\n// Grid classes for extra small devices like smartphones. No offset, push, or\\n// pull classes are present here due to the size of the target.\\n//\\n// Note that `.col-xs-12` doesn't get floated on purpose—there's no need since\\n// it's full-width.\\n\\n.col-xs-1,\\n.col-xs-2,\\n.col-xs-3,\\n.col-xs-4,\\n.col-xs-5,\\n.col-xs-6,\\n.col-xs-7,\\n.col-xs-8,\\n.col-xs-9,\\n.col-xs-10,\\n.col-xs-11 {\\n  float: left;\\n}\\n.col-xs-1  { width: percentage((1 / @grid-columns)); }\\n.col-xs-2  { width: percentage((2 / @grid-columns)); }\\n.col-xs-3  { width: percentage((3 / @grid-columns)); }\\n.col-xs-4  { width: percentage((4 / @grid-columns)); }\\n.col-xs-5  { width: percentage((5 / @grid-columns)); }\\n.col-xs-6  { width: percentage((6 / @grid-columns)); }\\n.col-xs-7  { width: percentage((7 / @grid-columns)); }\\n.col-xs-8  { width: percentage((8 / @grid-columns)); }\\n.col-xs-9  { width: percentage((9 / @grid-columns)); }\\n.col-xs-10 { width: percentage((10/ @grid-columns)); }\\n.col-xs-11 { width: percentage((11/ @grid-columns)); }\\n.col-xs-12 { width: 100%; }\\n\\n\\n// Small grid\\n//\\n// Columns, offsets, pushes, and pulls for the small device range, from phones\\n// to tablets.\\n//\\n// Note that `.col-sm-12` doesn't get floated on purpose—there's no need since\\n// it's full-width.\\n\\n@media (min-width: @screen-tablet) {\\n  .container {\\n    max-width: @container-tablet;\\n  }\\n\\n  .col-sm-1,\\n  .col-sm-2,\\n  .col-sm-3,\\n  .col-sm-4,\\n  .col-sm-5,\\n  .col-sm-6,\\n  .col-sm-7,\\n  .col-sm-8,\\n  .col-sm-9,\\n  .col-sm-10,\\n  .col-sm-11 {\\n    float: left;\\n  }\\n  .col-sm-1  { width: percentage((1 / @grid-columns)); }\\n  .col-sm-2  { width: percentage((2 / @grid-columns)); }\\n  .col-sm-3  { width: percentage((3 / @grid-columns)); }\\n  .col-sm-4  { width: percentage((4 / @grid-columns)); }\\n  .col-sm-5  { width: percentage((5 / @grid-columns)); }\\n  .col-sm-6  { width: percentage((6 / @grid-columns)); }\\n  .col-sm-7  { width: percentage((7 / @grid-columns)); }\\n  .col-sm-8  { width: percentage((8 / @grid-columns)); }\\n  .col-sm-9  { width: percentage((9 / @grid-columns)); }\\n  .col-sm-10 { width: percentage((10/ @grid-columns)); }\\n  .col-sm-11 { width: percentage((11/ @grid-columns)); }\\n  .col-sm-12 { width: 100%; }\\n\\n  // Push and pull columns for source order changes\\n  .col-sm-push-1  { left: percentage((1 / @grid-columns)); }\\n  .col-sm-push-2  { left: percentage((2 / @grid-columns)); }\\n  .col-sm-push-3  { left: percentage((3 / @grid-columns)); }\\n  .col-sm-push-4  { left: percentage((4 / @grid-columns)); }\\n  .col-sm-push-5  { left: percentage((5 / @grid-columns)); }\\n  .col-sm-push-6  { left: percentage((6 / @grid-columns)); }\\n  .col-sm-push-7  { left: percentage((7 / @grid-columns)); }\\n  .col-sm-push-8  { left: percentage((8 / @grid-columns)); }\\n  .col-sm-push-9  { left: percentage((9 / @grid-columns)); }\\n  .col-sm-push-10 { left: percentage((10/ @grid-columns)); }\\n  .col-sm-push-11 { left: percentage((11/ @grid-columns)); }\\n\\n  .col-sm-pull-1  { right: percentage((1 / @grid-columns)); }\\n  .col-sm-pull-2  { right: percentage((2 / @grid-columns)); }\\n  .col-sm-pull-3  { right: percentage((3 / @grid-columns)); }\\n  .col-sm-pull-4  { right: percentage((4 / @grid-columns)); }\\n  .col-sm-pull-5  { right: percentage((5 / @grid-columns)); }\\n  .col-sm-pull-6  { right: percentage((6 / @grid-columns)); }\\n  .col-sm-pull-7  { right: percentage((7 / @grid-columns)); }\\n  .col-sm-pull-8  { right: percentage((8 / @grid-columns)); }\\n  .col-sm-pull-9  { right: percentage((9 / @grid-columns)); }\\n  .col-sm-pull-10 { right: percentage((10/ @grid-columns)); }\\n  .col-sm-pull-11 { right: percentage((11/ @grid-columns)); }\\n\\n  // Offsets\\n  .col-sm-offset-1  { margin-left: percentage((1 / @grid-columns)); }\\n  .col-sm-offset-2  { margin-left: percentage((2 / @grid-columns)); }\\n  .col-sm-offset-3  { margin-left: percentage((3 / @grid-columns)); }\\n  .col-sm-offset-4  { margin-left: percentage((4 / @grid-columns)); }\\n  .col-sm-offset-5  { margin-left: percentage((5 / @grid-columns)); }\\n  .col-sm-offset-6  { margin-left: percentage((6 / @grid-columns)); }\\n  .col-sm-offset-7  { margin-left: percentage((7 / @grid-columns)); }\\n  .col-sm-offset-8  { margin-left: percentage((8 / @grid-columns)); }\\n  .col-sm-offset-9  { margin-left: percentage((9 / @grid-columns)); }\\n  .col-sm-offset-10 { margin-left: percentage((10/ @grid-columns)); }\\n  .col-sm-offset-11 { margin-left: percentage((11/ @grid-columns)); }\\n}\\n\\n\\n// Medium grid\\n//\\n// Columns, offsets, pushes, and pulls for the desktop device range.\\n//\\n// Note that `.col-md-12` doesn't get floated on purpose—there's no need since\\n// it's full-width.\\n\\n@media (min-width: @screen-desktop) {\\n  .container {\\n    max-width: @container-desktop;\\n  }\\n  .col-md-1,\\n  .col-md-2,\\n  .col-md-3,\\n  .col-md-4,\\n  .col-md-5,\\n  .col-md-6,\\n  .col-md-7,\\n  .col-md-8,\\n  .col-md-9,\\n  .col-md-10,\\n  .col-md-11 {\\n    float: left;\\n  }\\n  .col-md-1  { width: percentage((1 / @grid-columns)); }\\n  .col-md-2  { width: percentage((2 / @grid-columns)); }\\n  .col-md-3  { width: percentage((3 / @grid-columns)); }\\n  .col-md-4  { width: percentage((4 / @grid-columns)); }\\n  .col-md-5  { width: percentage((5 / @grid-columns)); }\\n  .col-md-6  { width: percentage((6 / @grid-columns)); }\\n  .col-md-7  { width: percentage((7 / @grid-columns)); }\\n  .col-md-8  { width: percentage((8 / @grid-columns)); }\\n  .col-md-9  { width: percentage((9 / @grid-columns)); }\\n  .col-md-10 { width: percentage((10/ @grid-columns)); }\\n  .col-md-11 { width: percentage((11/ @grid-columns)); }\\n  .col-md-12 { width: 100%; }\\n\\n  // Push and pull columns for source order changes\\n  .col-md-push-0  { left: auto; }\\n  .col-md-push-1  { left: percentage((1 / @grid-columns)); }\\n  .col-md-push-2  { left: percentage((2 / @grid-columns)); }\\n  .col-md-push-3  { left: percentage((3 / @grid-columns)); }\\n  .col-md-push-4  { left: percentage((4 / @grid-columns)); }\\n  .col-md-push-5  { left: percentage((5 / @grid-columns)); }\\n  .col-md-push-6  { left: percentage((6 / @grid-columns)); }\\n  .col-md-push-7  { left: percentage((7 / @grid-columns)); }\\n  .col-md-push-8  { left: percentage((8 / @grid-columns)); }\\n  .col-md-push-9  { left: percentage((9 / @grid-columns)); }\\n  .col-md-push-10 { left: percentage((10/ @grid-columns)); }\\n  .col-md-push-11 { left: percentage((11/ @grid-columns)); }\\n\\n  .col-md-pull-0  { right: auto; }\\n  .col-md-pull-1  { right: percentage((1 / @grid-columns)); }\\n  .col-md-pull-2  { right: percentage((2 / @grid-columns)); }\\n  .col-md-pull-3  { right: percentage((3 / @grid-columns)); }\\n  .col-md-pull-4  { right: percentage((4 / @grid-columns)); }\\n  .col-md-pull-5  { right: percentage((5 / @grid-columns)); }\\n  .col-md-pull-6  { right: percentage((6 / @grid-columns)); }\\n  .col-md-pull-7  { right: percentage((7 / @grid-columns)); }\\n  .col-md-pull-8  { right: percentage((8 / @grid-columns)); }\\n  .col-md-pull-9  { right: percentage((9 / @grid-columns)); }\\n  .col-md-pull-10 { right: percentage((10/ @grid-columns)); }\\n  .col-md-pull-11 { right: percentage((11/ @grid-columns)); }\\n\\n  // Offsets\\n  .col-md-offset-0  { margin-left: 0; }\\n  .col-md-offset-1  { margin-left: percentage((1 / @grid-columns)); }\\n  .col-md-offset-2  { margin-left: percentage((2 / @grid-columns)); }\\n  .col-md-offset-3  { margin-left: percentage((3 / @grid-columns)); }\\n  .col-md-offset-4  { margin-left: percentage((4 / @grid-columns)); }\\n  .col-md-offset-5  { margin-left: percentage((5 / @grid-columns)); }\\n  .col-md-offset-6  { margin-left: percentage((6 / @grid-columns)); }\\n  .col-md-offset-7  { margin-left: percentage((7 / @grid-columns)); }\\n  .col-md-offset-8  { margin-left: percentage((8 / @grid-columns)); }\\n  .col-md-offset-9  { margin-left: percentage((9 / @grid-columns)); }\\n  .col-md-offset-10 { margin-left: percentage((10/ @grid-columns)); }\\n  .col-md-offset-11 { margin-left: percentage((11/ @grid-columns)); }\\n}\\n\\n\\n// Large grid\\n//\\n// Columns, offsets, pushes, and pulls for the large desktop device range.\\n//\\n// Note that `.col-lg-12` doesn't get floated on purpose—there's no need since\\n// it's full-width.\\n\\n@media (min-width: @screen-lg-desktop) {\\n  .container {\\n    max-width: @container-lg-desktop;\\n  }\\n\\n  .col-lg-1,\\n  .col-lg-2,\\n  .col-lg-3,\\n  .col-lg-4,\\n  .col-lg-5,\\n  .col-lg-6,\\n  .col-lg-7,\\n  .col-lg-8,\\n  .col-lg-9,\\n  .col-lg-10,\\n  .col-lg-11 {\\n    float: left;\\n  }\\n  .col-lg-1  { width: percentage((1 / @grid-columns)); }\\n  .col-lg-2  { width: percentage((2 / @grid-columns)); }\\n  .col-lg-3  { width: percentage((3 / @grid-columns)); }\\n  .col-lg-4  { width: percentage((4 / @grid-columns)); }\\n  .col-lg-5  { width: percentage((5 / @grid-columns)); }\\n  .col-lg-6  { width: percentage((6 / @grid-columns)); }\\n  .col-lg-7  { width: percentage((7 / @grid-columns)); }\\n  .col-lg-8  { width: percentage((8 / @grid-columns)); }\\n  .col-lg-9  { width: percentage((9 / @grid-columns)); }\\n  .col-lg-10 { width: percentage((10/ @grid-columns)); }\\n  .col-lg-11 { width: percentage((11/ @grid-columns)); }\\n  .col-lg-12 { width: 100%; }\\n\\n  // Push and pull columns for source order changes\\n  .col-lg-push-0  { left: auto; }\\n  .col-lg-push-1  { left: percentage((1 / @grid-columns)); }\\n  .col-lg-push-2  { left: percentage((2 / @grid-columns)); }\\n  .col-lg-push-3  { left: percentage((3 / @grid-columns)); }\\n  .col-lg-push-4  { left: percentage((4 / @grid-columns)); }\\n  .col-lg-push-5  { left: percentage((5 / @grid-columns)); }\\n  .col-lg-push-6  { left: percentage((6 / @grid-columns)); }\\n  .col-lg-push-7  { left: percentage((7 / @grid-columns)); }\\n  .col-lg-push-8  { left: percentage((8 / @grid-columns)); }\\n  .col-lg-push-9  { left: percentage((9 / @grid-columns)); }\\n  .col-lg-push-10 { left: percentage((10/ @grid-columns)); }\\n  .col-lg-push-11 { left: percentage((11/ @grid-columns)); }\\n\\n  .col-lg-pull-0  { right: auto; }\\n  .col-lg-pull-1  { right: percentage((1 / @grid-columns)); }\\n  .col-lg-pull-2  { right: percentage((2 / @grid-columns)); }\\n  .col-lg-pull-3  { right: percentage((3 / @grid-columns)); }\\n  .col-lg-pull-4  { right: percentage((4 / @grid-columns)); }\\n  .col-lg-pull-5  { right: percentage((5 / @grid-columns)); }\\n  .col-lg-pull-6  { right: percentage((6 / @grid-columns)); }\\n  .col-lg-pull-7  { right: percentage((7 / @grid-columns)); }\\n  .col-lg-pull-8  { right: percentage((8 / @grid-columns)); }\\n  .col-lg-pull-9  { right: percentage((9 / @grid-columns)); }\\n  .col-lg-pull-10 { right: percentage((10/ @grid-columns)); }\\n  .col-lg-pull-11 { right: percentage((11/ @grid-columns)); }\\n\\n  // Offsets\\n  .col-lg-offset-0  { margin-left: 0; }\\n  .col-lg-offset-1  { margin-left: percentage((1 / @grid-columns)); }\\n  .col-lg-offset-2  { margin-left: percentage((2 / @grid-columns)); }\\n  .col-lg-offset-3  { margin-left: percentage((3 / @grid-columns)); }\\n  .col-lg-offset-4  { margin-left: percentage((4 / @grid-columns)); }\\n  .col-lg-offset-5  { margin-left: percentage((5 / @grid-columns)); }\\n  .col-lg-offset-6  { margin-left: percentage((6 / @grid-columns)); }\\n  .col-lg-offset-7  { margin-left: percentage((7 / @grid-columns)); }\\n  .col-lg-offset-8  { margin-left: percentage((8 / @grid-columns)); }\\n  .col-lg-offset-9  { margin-left: percentage((9 / @grid-columns)); }\\n  .col-lg-offset-10 { margin-left: percentage((10/ @grid-columns)); }\\n  .col-lg-offset-11 { margin-left: percentage((11/ @grid-columns)); }\\n}\\n\",\"input-groups.less\":\"//\\n// Input groups\\n// --------------------------------------------------\\n\\n// Base styles\\n// -------------------------\\n.input-group {\\n  position: relative; // For dropdowns\\n  display: table;\\n  border-collapse: separate; // prevent input groups from inheriting border styles from table cells when placed within a table\\n\\n  // Undo padding and float of grid classes\\n  &.col {\\n    float: none;\\n    padding-left: 0;\\n    padding-right: 0;\\n  }\\n\\n  .form-control {\\n    width: 100%;\\n    margin-bottom: 0;\\n  }\\n}\\n\\n// Sizing options\\n//\\n// Remix the default form control sizing classes into new ones for easier\\n// manipulation.\\n\\n.input-group-lg > .form-control,\\n.input-group-lg > .input-group-addon,\\n.input-group-lg > .input-group-btn > .btn { .input-lg(); }\\n.input-group-sm > .form-control,\\n.input-group-sm > .input-group-addon,\\n.input-group-sm > .input-group-btn > .btn { .input-sm(); }\\n\\n\\n// Display as table-cell\\n// -------------------------\\n.input-group-addon,\\n.input-group-btn,\\n.input-group .form-control {\\n  display: table-cell;\\n\\n  &:not(:first-child):not(:last-child) {\\n    border-radius: 0;\\n  }\\n}\\n// Addon and addon wrapper for buttons\\n.input-group-addon,\\n.input-group-btn {\\n  width: 1%;\\n  white-space: nowrap;\\n  vertical-align: middle; // Match the inputs\\n}\\n\\n// Text input groups\\n// -------------------------\\n.input-group-addon {\\n  padding: @padding-base-vertical @padding-base-horizontal;\\n  font-size: @font-size-base;\\n  font-weight: normal;\\n  line-height: 1;\\n  text-align: center;\\n  background-color: @input-group-addon-bg;\\n  border: 1px solid @input-group-addon-border-color;\\n  border-radius: @border-radius-base;\\n\\n  // Sizing\\n  &.input-sm {\\n    padding: @padding-small-vertical @padding-small-horizontal;\\n    font-size: @font-size-small;\\n    border-radius: @border-radius-small;\\n  }\\n  &.input-lg {\\n    padding: @padding-large-vertical @padding-large-horizontal;\\n    font-size: @font-size-large;\\n    border-radius: @border-radius-large;\\n  }\\n\\n  // Nuke default margins from checkboxes and radios to vertically center within.\\n  input[type=\\\"radio\\\"],\\n  input[type=\\\"checkbox\\\"] {\\n    margin-top: 0;\\n  }\\n}\\n\\n// Reset rounded corners\\n.input-group .form-control:first-child,\\n.input-group-addon:first-child,\\n.input-group-btn:first-child > .btn,\\n.input-group-btn:first-child > .dropdown-toggle,\\n.input-group-btn:last-child > .btn:not(:last-child):not(.dropdown-toggle) {\\n  .border-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 > .dropdown-toggle,\\n.input-group-btn:first-child > .btn:not(:first-child) {\\n  .border-left-radius(0);\\n}\\n.input-group-addon:last-child {\\n  border-left: 0;\\n}\\n\\n// Button input groups\\n// -------------------------\\n.input-group-btn {\\n  position: relative;\\n  white-space: nowrap;\\n}\\n.input-group-btn > .btn {\\n  position: relative;\\n  // Jankily prevent input button groups from wrapping\\n  + .btn {\\n    margin-left: -4px;\\n  }\\n  // Bring the \\\"active\\\" button to the front\\n  &:hover,\\n  &:active {\\n    z-index: 2;\\n  }\\n}\\n\",\"jumbotron.less\":\"//\\n// Jumbotron\\n// --------------------------------------------------\\n\\n\\n.jumbotron {\\n  padding: @jumbotron-padding;\\n  margin-bottom: @jumbotron-padding;\\n  font-size: (@font-size-base * 1.5);\\n  font-weight: 200;\\n  line-height: (@line-height-base * 1.5);\\n  color: @jumbotron-color;\\n  background-color: @jumbotron-bg;\\n\\n  h1 {\\n    line-height: 1;\\n    color: @jumbotron-heading-color;\\n  }\\n  p {\\n    line-height: 1.4;\\n  }\\n\\n  .container & {\\n    border-radius: @border-radius-large; // Only round corners at higher resolutions if contained in a container\\n  }\\n\\n  @media screen and (min-width: @screen-tablet) {\\n    padding-top:    (@jumbotron-padding * 1.6);\\n    padding-bottom: (@jumbotron-padding * 1.6);\\n\\n    .container & {\\n      padding-left:  (@jumbotron-padding * 2);\\n      padding-right: (@jumbotron-padding * 2);\\n    }\\n\\n    h1 {\\n      font-size: (@font-size-base * 4.5);\\n    }\\n  }\\n}\\n\",\"labels.less\":\"//\\n// Labels\\n// --------------------------------------------------\\n\\n.label {\\n  display: inline;\\n  padding: .2em .6em .3em;\\n  font-size: 75%;\\n  font-weight: bold;\\n  line-height: 1;\\n  color: @label-color;\\n  text-align: center;\\n  white-space: nowrap;\\n  vertical-align: baseline;\\n  border-radius: .25em;\\n\\n  // Add hover effects, but only for links\\n  &[href] {\\n    &:hover,\\n    &:focus {\\n      color: @label-link-hover-color;\\n      text-decoration: none;\\n      cursor: pointer;\\n    }\\n  }\\n\\n  // Empty labels collapse automatically (not available in IE8)\\n  &:empty {\\n    display: none;\\n  }\\n}\\n\\n// Colors\\n// Contextual variations (linked labels get darker on :hover)\\n\\n.label-default {\\n  .label-variant(@label-default-bg);\\n}\\n\\n.label-primary {\\n  .label-variant(@label-primary-bg);\\n}\\n\\n.label-success {\\n  .label-variant(@label-success-bg);\\n}\\n\\n.label-info {\\n  .label-variant(@label-info-bg);\\n}\\n\\n.label-warning {\\n  .label-variant(@label-warning-bg);\\n}\\n\\n.label-danger {\\n  .label-variant(@label-danger-bg);\\n}\\n\",\"list-group.less\":\"//\\n// List groups\\n// --------------------------------------------------\\n\\n// Base class\\n//\\n// Easily usable on <ul>, <ol>, or <div>.\\n.list-group {\\n  // No need to set list-style: none; since .list-group-item is block level\\n  margin-bottom: 20px;\\n  padding-left: 0; // reset padding because ul and ol\\n}\\n\\n// Individual list items\\n// -------------------------\\n\\n.list-group-item {\\n  position: relative;\\n  display: block;\\n  padding: 10px 15px;\\n  // Place the border on the list items and negative margin up for better styling\\n  margin-bottom: -1px;\\n  background-color: @list-group-bg;\\n  border: 1px solid @list-group-border;\\n\\n  // Round the first and last items\\n  &:first-child {\\n    .border-top-radius(@list-group-border-radius);\\n  }\\n  &:last-child {\\n    margin-bottom: 0;\\n    .border-bottom-radius(@list-group-border-radius);\\n  }\\n\\n  // Align badges within list items\\n  > .badge {\\n    float: right;\\n  }\\n  > .badge + .badge {\\n    margin-right: 5px;\\n  }\\n\\n  // Linked list items\\n  a& {\\n    color: @list-group-link-color;\\n\\n    .list-group-item-heading {\\n      color: @list-group-link-heading-color;\\n    }\\n\\n    // Hover state\\n    &:hover,\\n    &:focus {\\n      text-decoration: none;\\n      background-color: @list-group-hover-bg;\\n    }\\n  }\\n\\n  // Active class on item itself, not parent\\n  &.active,\\n  &.active:hover,\\n  &.active:focus {\\n    z-index: 2; // Place active items above their siblings for proper border styling\\n    color: @list-group-active-color;\\n    background-color: @list-group-active-bg;\\n    border-color: @list-group-active-border;\\n\\n    // Force color to inherit for custom content\\n    .list-group-item-heading {\\n      color: inherit;\\n    }\\n    .list-group-item-text {\\n      color: lighten(@list-group-active-bg, 40%);\\n    }\\n  }\\n}\\n\\n// Custom content options\\n// -------------------------\\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\",\"media.less\":\"// Media objects\\n// Source: http://stubbornella.org/content/?p=497\\n// --------------------------------------------------\\n\\n\\n// Common styles\\n// -------------------------\\n\\n// Clear the floats\\n.media,\\n.media-body {\\n  overflow: hidden;\\n  zoom: 1;\\n}\\n\\n// Proper spacing between instances of .media\\n.media,\\n.media .media {\\n  margin-top: 15px;\\n}\\n.media:first-child {\\n  margin-top: 0;\\n}\\n\\n// For images and videos, set to block\\n.media-object {\\n  display: block;\\n}\\n\\n// Reset margins on headings for tighter default spacing\\n.media-heading {\\n  margin: 0 0 5px;\\n}\\n\\n\\n// Media image alignment\\n// -------------------------\\n\\n.media {\\n  > .pull-left {\\n    margin-right: 10px;\\n  }\\n  > .pull-right {\\n    margin-left: 10px;\\n  }\\n}\\n\\n\\n// Media list variation\\n// -------------------------\\n\\n// Undo default ul/ol styles\\n.media-list {\\n  padding-left: 0;\\n  list-style: none;\\n}\\n\",\"mixins.less\":\"//\\n// Mixins\\n// --------------------------------------------------\\n\\n\\n// Utilities\\n// -------------------------\\n\\n// Clearfix\\n// Source: http://nicolasgallagher.com/micro-clearfix-hack/\\n//\\n// For modern browsers\\n// 1. The space content is one way to avoid an Opera bug when the\\n//    contenteditable attribute is included anywhere else in the document.\\n//    Otherwise it causes space to appear at the top and bottom of elements\\n//    that are clearfixed.\\n// 2. The use of `table` rather than `block` is only necessary if using\\n//    `:before` to contain the top-margins of child elements.\\n.clearfix() {\\n  &:before,\\n  &:after {\\n    content: \\\" \\\"; /* 1 */\\n    display: table; /* 2 */\\n  }\\n  &:after {\\n    clear: both;\\n  }\\n}\\n\\n// Webkit-style focus\\n.tab-focus() {\\n  // Default\\n  outline: thin dotted #333;\\n  // Webkit\\n  outline: 5px auto -webkit-focus-ring-color;\\n  outline-offset: -2px;\\n}\\n\\n// Center-align a block level element\\n.center-block() {\\n  display: block;\\n  margin-left: auto;\\n  margin-right: auto;\\n}\\n\\n// Sizing shortcuts\\n.size(@width; @height) {\\n  width: @width;\\n  height: @height;\\n}\\n.square(@size) {\\n  .size(@size; @size);\\n}\\n\\n// Placeholder text\\n.placeholder(@color: @input-color-placeholder) {\\n  &:-moz-placeholder            { color: @color; } // Firefox 4-18\\n  &::-moz-placeholder           { color: @color; } // Firefox 19+\\n  &:-ms-input-placeholder       { color: @color; } // Internet Explorer 10+\\n  &::-webkit-input-placeholder  { color: @color; } // Safari and Chrome\\n}\\n\\n// Text overflow\\n// Requires inline-block or block for proper styling\\n.text-overflow() {\\n  overflow: hidden;\\n  text-overflow: ellipsis;\\n  white-space: nowrap;\\n}\\n\\n// CSS image replacement\\n// Source: https://github.com/h5bp/html5-boilerplate/commit/aa0396eae757\\n.hide-text() {\\n  font: ~\\\"0/0\\\" a;\\n  color: transparent;\\n  text-shadow: none;\\n  background-color: transparent;\\n  border: 0;\\n}\\n\\n\\n\\n// CSS3 PROPERTIES\\n// --------------------------------------------------\\n\\n// Single side border-radius\\n.border-top-radius(@radius) {\\n  border-top-right-radius: @radius;\\n   border-top-left-radius: @radius;\\n}\\n.border-right-radius(@radius) {\\n  border-bottom-right-radius: @radius;\\n     border-top-right-radius: @radius;\\n}\\n.border-bottom-radius(@radius) {\\n  border-bottom-right-radius: @radius;\\n   border-bottom-left-radius: @radius;\\n}\\n.border-left-radius(@radius) {\\n  border-bottom-left-radius: @radius;\\n     border-top-left-radius: @radius;\\n}\\n\\n// Drop shadows\\n.box-shadow(@shadow) {\\n  -webkit-box-shadow: @shadow; // iOS <4.3 & Android <4.1\\n          box-shadow: @shadow;\\n}\\n\\n// Transitions\\n.transition(@transition) {\\n  -webkit-transition: @transition;\\n          transition: @transition;\\n}\\n.transition-delay(@transition-delay) {\\n  -webkit-transition-delay: @transition-delay;\\n          transition-delay: @transition-delay;\\n}\\n.transition-duration(@transition-duration) {\\n  -webkit-transition-duration: @transition-duration;\\n          transition-duration: @transition-duration;\\n}\\n.transition-transform(@transition) {\\n  -webkit-transition: -webkit-transform @transition;\\n     -moz-transition: -moz-transform @transition;\\n       -o-transition: -o-transform @transition;\\n          transition: transform @transition;\\n}\\n\\n// Transformations\\n.rotate(@degrees) {\\n  -webkit-transform: rotate(@degrees);\\n      -ms-transform: rotate(@degrees); // IE9+\\n          transform: rotate(@degrees);\\n}\\n.scale(@ratio) {\\n  -webkit-transform: scale(@ratio);\\n      -ms-transform: scale(@ratio); // IE9+\\n          transform: scale(@ratio);\\n}\\n.translate(@x; @y) {\\n  -webkit-transform: translate(@x, @y);\\n      -ms-transform: translate(@x, @y); // IE9+\\n          transform: translate(@x, @y);\\n}\\n.skew(@x; @y) {\\n  -webkit-transform: skew(@x, @y);\\n      -ms-transform: skewX(@x) skewY(@y); // See https://github.com/twbs/bootstrap/issues/4885; IE9+\\n          transform: skew(@x, @y);\\n}\\n.translate3d(@x; @y; @z) {\\n  -webkit-transform: translate3d(@x, @y, @z);\\n          transform: translate3d(@x, @y, @z);\\n}\\n\\n// Backface visibility\\n// Prevent browsers from flickering when using CSS 3D transforms.\\n// Default value is `visible`, but can be changed to `hidden`\\n// See git pull https://github.com/dannykeane/bootstrap.git backface-visibility for examples\\n.backface-visibility(@visibility){\\n  -webkit-backface-visibility: @visibility;\\n     -moz-backface-visibility: @visibility;\\n          backface-visibility: @visibility;\\n}\\n\\n// Box sizing\\n.box-sizing(@boxmodel) {\\n  -webkit-box-sizing: @boxmodel;\\n     -moz-box-sizing: @boxmodel;\\n          box-sizing: @boxmodel;\\n}\\n\\n// User select\\n// For selecting text on the page\\n.user-select(@select) {\\n  -webkit-user-select: @select;\\n     -moz-user-select: @select;\\n      -ms-user-select: @select; // IE10+\\n       -o-user-select: @select;\\n          user-select: @select;\\n}\\n\\n// Resize anything\\n.resizable(@direction) {\\n  resize: @direction; // Options: horizontal, vertical, both\\n  overflow: auto; // Safari fix\\n}\\n\\n// CSS3 Content Columns\\n.content-columns(@column-count; @column-gap: @grid-gutter-width) {\\n  -webkit-column-count: @column-count;\\n     -moz-column-count: @column-count;\\n          column-count: @column-count;\\n  -webkit-column-gap: @column-gap;\\n     -moz-column-gap: @column-gap;\\n          column-gap: @column-gap;\\n}\\n\\n// Optional hyphenation\\n.hyphens(@mode: auto) {\\n  word-wrap: break-word;\\n  -webkit-hyphens: @mode;\\n     -moz-hyphens: @mode;\\n      -ms-hyphens: @mode; // IE10+\\n       -o-hyphens: @mode;\\n          hyphens: @mode;\\n}\\n\\n// Opacity\\n.opacity(@opacity) {\\n  opacity: @opacity;\\n  // IE8 filter\\n  @opacity-ie: (@opacity * 100);\\n  filter: ~\\\"alpha(opacity=@{opacity-ie})\\\";\\n}\\n\\n\\n\\n// GRADIENTS\\n// --------------------------------------------------\\n\\n#gradient {\\n\\n  // Horizontal gradient, from left to right\\n  //\\n  // Creates two color stops, start and end, by specifying a color and position for each color stop.\\n  // Color stops are not available in IE9 and below.\\n  .horizontal(@start-color: #555; @end-color: #333; @start-percent: 0%; @end-percent: 100%) {\\n    background-image: -webkit-gradient(linear, @start-percent top, @end-percent top, from(@start-color), to(@end-color)); // Safari 4+, Chrome 2+\\n    background-image: -webkit-linear-gradient(left, color-stop(@start-color @start-percent), color-stop(@end-color @end-percent)); // Safari 5.1+, Chrome 10+\\n    background-image: -moz-linear-gradient(left, @start-color @start-percent, @end-color @end-percent); // FF 3.6+\\n    background-image:  linear-gradient(to right, @start-color @start-percent, @end-color @end-percent); // Standard, IE10\\n    background-repeat: repeat-x;\\n    filter: e(%(\\\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=1)\\\",argb(@start-color),argb(@end-color))); // IE9 and down\\n  }\\n\\n  // Vertical gradient, from top to bottom\\n  //\\n  // Creates two color stops, start and end, by specifying a color and position for each color stop.\\n  // Color stops are not available in IE9 and below.\\n  .vertical(@start-color: #555; @end-color: #333; @start-percent: 0%; @end-percent: 100%) {\\n    background-image: -webkit-gradient(linear, left @start-percent, left @end-percent, from(@start-color), to(@end-color)); // Safari 4+, Chrome 2+\\n    background-image: -webkit-linear-gradient(top, @start-color, @start-percent, @end-color, @end-percent); // Safari 5.1+, Chrome 10+\\n    background-image:  -moz-linear-gradient(top, @start-color @start-percent, @end-color @end-percent); // FF 3.6+\\n    background-image: linear-gradient(to bottom, @start-color @start-percent, @end-color @end-percent); // Standard, IE10\\n    background-repeat: repeat-x;\\n    filter: e(%(\\\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=0)\\\",argb(@start-color),argb(@end-color))); // IE9 and down\\n  }\\n\\n  .directional(@start-color: #555; @end-color: #333; @deg: 45deg) {\\n    background-repeat: repeat-x;\\n    background-image: -webkit-linear-gradient(@deg, @start-color, @end-color); // Safari 5.1+, Chrome 10+\\n    background-image: -moz-linear-gradient(@deg, @start-color, @end-color); // FF 3.6+\\n    background-image: linear-gradient(@deg, @start-color, @end-color); // Standard, IE10\\n  }\\n  .horizontal-three-colors(@start-color: #00b3ee; @mid-color: #7a43b6; @color-stop: 50%; @end-color: #c3325f) {\\n    background-image: -webkit-gradient(left, linear, 0 0, 0 100%, from(@start-color), color-stop(@color-stop, @mid-color), to(@end-color));\\n    background-image: -webkit-linear-gradient(left, @start-color, @mid-color @color-stop, @end-color);\\n    background-image: -moz-linear-gradient(left, @start-color, @mid-color @color-stop, @end-color);\\n    background-image: linear-gradient(to right, @start-color, @mid-color @color-stop, @end-color);\\n    background-repeat: no-repeat;\\n    filter: e(%(\\\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=1)\\\",argb(@start-color),argb(@end-color))); // IE9 and down, gets no color-stop at all for proper fallback\\n  }\\n  .vertical-three-colors(@start-color: #00b3ee; @mid-color: #7a43b6; @color-stop: 50%; @end-color: #c3325f) {\\n    background-image: -webkit-gradient(linear, 0 0, 0 100%, from(@start-color), color-stop(@color-stop, @mid-color), to(@end-color));\\n    background-image: -webkit-linear-gradient(@start-color, @mid-color @color-stop, @end-color);\\n    background-image: -moz-linear-gradient(top, @start-color, @mid-color @color-stop, @end-color);\\n    background-image: linear-gradient(@start-color, @mid-color @color-stop, @end-color);\\n    background-repeat: no-repeat;\\n    filter: e(%(\\\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=0)\\\",argb(@start-color),argb(@end-color))); // IE9 and down, gets no color-stop at all for proper fallback\\n  }\\n  .radial(@inner-color: #555; @outer-color: #333) {\\n    background-image: -webkit-gradient(radial, center center, 0, center center, 460, from(@inner-color), to(@outer-color));\\n    background-image: -webkit-radial-gradient(circle, @inner-color, @outer-color);\\n    background-image: -moz-radial-gradient(circle, @inner-color, @outer-color);\\n    background-image: radial-gradient(circle, @inner-color, @outer-color);\\n    background-repeat: no-repeat;\\n  }\\n  .striped(@color: #555; @angle: 45deg) {\\n    background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(.25, rgba(255,255,255,.15)), color-stop(.25, transparent), color-stop(.5, transparent), color-stop(.5, rgba(255,255,255,.15)), color-stop(.75, rgba(255,255,255,.15)), color-stop(.75, transparent), to(transparent));\\n    background-image: -webkit-linear-gradient(@angle, 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: -moz-linear-gradient(@angle, 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(@angle, 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}\\n\\n// Reset filters for IE\\n//\\n// When you need to remove a gradient background, do not forget to use this to reset\\n// the IE filter for IE9 and below.\\n.reset-filter() {\\n  filter: e(%(\\\"progid:DXImageTransform.Microsoft.gradient(enabled = false)\\\"));\\n}\\n\\n\\n\\n// Retina images\\n//\\n// Short retina mixin for setting background-image and -size\\n\\n.img-retina(@file-1x; @file-2x; @width-1x; @height-1x) {\\n  background-image: url(\\\"@{file-1x}\\\");\\n\\n  @media\\n  only screen and (-webkit-min-device-pixel-ratio: 2),\\n  only screen and (   min--moz-device-pixel-ratio: 2),\\n  only screen and (     -o-min-device-pixel-ratio: 2/1),\\n  only screen and (        min-device-pixel-ratio: 2),\\n  only screen and (                min-resolution: 192dpi),\\n  only screen and (                min-resolution: 2dppx) {\\n    background-image: url(\\\"@{file-2x}\\\");\\n    background-size: @width-1x @height-1x;\\n  }\\n}\\n\\n\\n// Responsive image\\n//\\n// Keep images from scaling beyond the width of their parents.\\n\\n.img-responsive(@display: block;) {\\n  display: @display;\\n  max-width: 100%; // Part 1: Set a maximum relative to the parent\\n  height: auto; // Part 2: Scale the height according to the width, otherwise you get stretching\\n}\\n\\n\\n// COMPONENT MIXINS\\n// --------------------------------------------------\\n\\n// Horizontal dividers\\n// -------------------------\\n// Dividers (basically an hr) within dropdowns and nav lists\\n.nav-divider(@color: #e5e5e5) {\\n  height: 1px;\\n  margin: ((@line-height-computed / 2) - 1) 0;\\n  overflow: hidden;\\n  background-color: @color;\\n}\\n\\n// Panels\\n// -------------------------\\n.panel-variant(@border; @heading-text-color; @heading-bg-color; @heading-border;) {\\n  border-color: @border;\\n  & > .panel-heading {\\n    color: @heading-text-color;\\n    background-color: @heading-bg-color;\\n    border-color: @heading-border;\\n    + .panel-collapse .panel-body {\\n      border-top-color: @border;\\n    }\\n  }\\n  & > .panel-footer {\\n    + .panel-collapse .panel-body {\\n      border-bottom-color: @border;\\n    }\\n  }\\n}\\n\\n// Alerts\\n// -------------------------\\n.alert-variant(@background; @border; @text-color) {\\n  background-color: @background;\\n  border-color: @border;\\n  color: @text-color;\\n  hr {\\n    border-top-color: darken(@border, 5%);\\n  }\\n  .alert-link {\\n    color: darken(@text-color, 10%);\\n  }\\n}\\n\\n// Tables\\n// -------------------------\\n.table-row-variant(@state; @background; @border) {\\n  // Exact selectors below required to override `.table-striped` and prevent\\n  // inheritance to nested tables.\\n  .table > thead > tr,\\n  .table > tbody > tr,\\n  .table > tfoot > tr {\\n    > td.@{state},\\n    > th.@{state},\\n    &.@{state} > td,\\n    &.@{state} > th {\\n      background-color: @background;\\n      border-color: @border;\\n    }\\n  }\\n\\n  // Hover states for `.table-hover`\\n  // Note: this is not available for cells or rows within `thead` or `tfoot`.\\n  .table-hover > tbody > tr {\\n    > td.@{state}:hover,\\n    > th.@{state}:hover,\\n    &.@{state}:hover > td {\\n      background-color: darken(@background, 5%);\\n      border-color: darken(@border, 5%);\\n    }\\n  }\\n}\\n\\n// Button variants\\n// -------------------------\\n// Easily pump out default styles, as well as :hover, :focus, :active,\\n// and disabled options for all buttons\\n.button-variant(@color; @background; @border) {\\n  color: @color;\\n  background-color: @background;\\n  border-color: @border;\\n\\n  &:hover,\\n  &:focus,\\n  &:active,\\n  &.active,\\n  .open .dropdown-toggle& {\\n    color: @color;\\n    background-color: darken(@background, 8%);\\n        border-color: darken(@border, 12%);\\n  }\\n  &:active,\\n  &.active,\\n  .open .dropdown-toggle& {\\n    background-image: none;\\n  }\\n  &.disabled,\\n  &[disabled],\\n  fieldset[disabled] & {\\n    &,\\n    &:hover,\\n    &:focus,\\n    &:active,\\n    &.active {\\n      background-color: @background;\\n          border-color: @border\\n    }\\n  }\\n}\\n\\n// Button sizes\\n// -------------------------\\n.button-size(@padding-vertical; @padding-horizontal; @font-size; @line-height; @border-radius) {\\n  padding: @padding-vertical @padding-horizontal;\\n  font-size: @font-size;\\n  line-height: @line-height;\\n  border-radius: @border-radius;\\n}\\n\\n// Pagination\\n// -------------------------\\n.pagination-size(@padding-vertical; @padding-horizontal; @font-size; @border-radius) {\\n  > li {\\n    > a,\\n    > span {\\n      padding: @padding-vertical @padding-horizontal;\\n      font-size: @font-size;\\n    }\\n    &:first-child {\\n      > a,\\n      > span {\\n        .border-left-radius(@border-radius);\\n      }\\n    }\\n    &:last-child {\\n      > a,\\n      > span {\\n        .border-right-radius(@border-radius);\\n      }\\n    }\\n  }\\n}\\n\\n// Labels\\n// -------------------------\\n.label-variant(@color) {\\n  background-color: @color;\\n  &[href] {\\n    &:hover,\\n    &:focus {\\n      background-color: darken(@color, 10%);\\n    }\\n  }\\n}\\n\\n// Navbar vertical align\\n// -------------------------\\n// Vertically center elements in the navbar.\\n// Example: an element has a height of 30px, so write out `.navbar-vertical-align(30px);` to calculate the appropriate top margin.\\n.navbar-vertical-align(@element-height) {\\n  margin-top: ((@navbar-height - @element-height) / 2);\\n  margin-bottom: ((@navbar-height - @element-height) / 2);\\n}\\n\\n// Progress bars\\n// -------------------------\\n.progress-bar-variant(@color) {\\n  background-color: @color;\\n  .progress-striped & {\\n    #gradient > .striped(@color);\\n  }\\n}\\n\\n// Responsive utilities\\n// -------------------------\\n// More easily include all the states for responsive-utilities.less.\\n.responsive-visibility() {\\n  display: block !important;\\n  tr& { display: table-row !important; }\\n  th&,\\n  td& { display: table-cell !important; }\\n}\\n\\n.responsive-invisibility() {\\n  display: none !important;\\n  tr& { display: none !important; }\\n  th&,\\n  td& { display: none !important; }\\n}\\n\\n// Grid System\\n// -----------\\n\\n// Centered container element\\n.container-fixed() {\\n  margin-right: auto;\\n  margin-left: auto;\\n  padding-left:  (@grid-gutter-width / 2);\\n  padding-right: (@grid-gutter-width / 2);\\n  .clearfix();\\n}\\n\\n// Creates a wrapper for a series of columns\\n.make-row(@gutter: @grid-gutter-width) {\\n  margin-left:  (@gutter / -2);\\n  margin-right: (@gutter / -2);\\n  .clearfix();\\n}\\n\\n// Generate the extra small columns\\n.make-xs-column(@columns; @gutter: @grid-gutter-width) {\\n  position: relative;\\n  float: left;\\n  width: percentage((@columns / @grid-columns));\\n  // Prevent columns from collapsing when empty\\n  min-height: 1px;\\n  // Inner gutter via padding\\n  padding-left:  (@gutter / 2);\\n  padding-right: (@gutter / 2);\\n}\\n\\n// Generate the small columns\\n.make-sm-column(@columns; @gutter: @grid-gutter-width) {\\n  position: relative;\\n  // Prevent columns from collapsing when empty\\n  min-height: 1px;\\n  // Inner gutter via padding\\n  padding-left:  (@gutter / 2);\\n  padding-right: (@gutter / 2);\\n\\n  // Calculate width based on number of columns available\\n  @media (min-width: @screen-sm) {\\n    float: left;\\n    width: percentage((@columns / @grid-columns));\\n  }\\n}\\n\\n// Generate the small column offsets\\n.make-sm-column-offset(@columns) {\\n  @media (min-width: @screen-sm) {\\n    margin-left: percentage((@columns / @grid-columns));\\n  }\\n}\\n.make-sm-column-push(@columns) {\\n  @media (min-width: @screen-sm) {\\n    left: percentage((@columns / @grid-columns));\\n  }\\n}\\n.make-sm-column-pull(@columns) {\\n  @media (min-width: @screen-sm) {\\n    right: percentage((@columns / @grid-columns));\\n  }\\n}\\n\\n// Generate the medium columns\\n.make-md-column(@columns; @gutter: @grid-gutter-width) {\\n  position: relative;\\n  // Prevent columns from collapsing when empty\\n  min-height: 1px;\\n  // Inner gutter via padding\\n  padding-left:  (@gutter / 2);\\n  padding-right: (@gutter / 2);\\n\\n  // Calculate width based on number of columns available\\n  @media (min-width: @screen-md) {\\n    float: left;\\n    width: percentage((@columns / @grid-columns));\\n  }\\n}\\n\\n// Generate the large column offsets\\n.make-md-column-offset(@columns) {\\n  @media (min-width: @screen-md) {\\n    margin-left: percentage((@columns / @grid-columns));\\n  }\\n}\\n.make-md-column-push(@columns) {\\n  @media (min-width: @screen-md) {\\n    left: percentage((@columns / @grid-columns));\\n  }\\n}\\n.make-md-column-pull(@columns) {\\n  @media (min-width: @screen-md) {\\n    right: percentage((@columns / @grid-columns));\\n  }\\n}\\n\\n// Generate the large columns\\n.make-lg-column(@columns; @gutter: @grid-gutter-width) {\\n  position: relative;\\n  // Prevent columns from collapsing when empty\\n  min-height: 1px;\\n  // Inner gutter via padding\\n  padding-left:  (@gutter / 2);\\n  padding-right: (@gutter / 2);\\n\\n  // Calculate width based on number of columns available\\n  @media (min-width: @screen-lg) {\\n    float: left;\\n    width: percentage((@columns / @grid-columns));\\n  }\\n}\\n\\n// Generate the large column offsets\\n.make-lg-column-offset(@columns) {\\n  @media (min-width: @screen-lg) {\\n    margin-left: percentage((@columns / @grid-columns));\\n  }\\n}\\n.make-lg-column-push(@columns) {\\n  @media (min-width: @screen-lg) {\\n    left: percentage((@columns / @grid-columns));\\n  }\\n}\\n.make-lg-column-pull(@columns) {\\n  @media (min-width: @screen-lg) {\\n    right: percentage((@columns / @grid-columns));\\n  }\\n}\\n\\n\\n// Form validation states\\n//\\n// Used in forms.less to generate the form validation CSS for warnings, errors,\\n// and successes.\\n\\n.form-control-validation(@text-color: #555; @border-color: #ccc; @background-color: #f5f5f5) {\\n  // Color the label and help text\\n  .help-block,\\n  .control-label {\\n    color: @text-color;\\n  }\\n  // Set the border and box shadow on specific inputs to match\\n  .form-control {\\n    border-color: @border-color;\\n    .box-shadow(inset 0 1px 1px rgba(0,0,0,.075)); // Redeclare so transitions work\\n    &:focus {\\n      border-color: darken(@border-color, 10%);\\n      @shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 6px lighten(@border-color, 20%);\\n      .box-shadow(@shadow);\\n    }\\n  }\\n  // Set validation states also for addons\\n  .input-group-addon {\\n    color: @text-color;\\n    border-color: @border-color;\\n    background-color: @background-color;\\n  }\\n}\\n\\n// Form control focus state\\n//\\n// Generate a customized focus state and for any input with the specified color,\\n// which defaults to the `@input-focus-border` variable.\\n//\\n// We highly encourage you to not customize the default value, but instead use\\n// this to tweak colors on an as-needed basis. This aesthetic change is based on\\n// WebKit's default styles, but applicable to a wider range of browsers. Its\\n// usability and accessibility should be taken into account with any change.\\n//\\n// Example usage: change the default blue border and shadow to white for better\\n// contrast against a dark gray background.\\n\\n.form-control-focus(@color: @input-border-focus) {\\n  @color-rgba: rgba(red(@color), green(@color), blue(@color), .6);\\n  &:focus {\\n    border-color: @color;\\n    outline: 0;\\n    .box-shadow(~\\\"inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px @{color-rgba}\\\");\\n  }\\n}\\n\\n// Form control sizing\\n//\\n// Relative text size, padding, and border-radii changes for form controls. For\\n// horizontal sizing, wrap controls in the predefined grid classes. `<select>`\\n// element gets special love because it's special, and that's a fact!\\n\\n.input-size(@input-height; @padding-vertical; @padding-horizontal; @font-size; @line-height; @border-radius) {\\n  height: @input-height;\\n  padding: @padding-vertical @padding-horizontal;\\n  font-size: @font-size;\\n  line-height: @line-height;\\n  border-radius: @border-radius;\\n\\n  select& {\\n    height: @input-height;\\n    line-height: @input-height;\\n  }\\n\\n  textarea& {\\n    height: auto;\\n  }\\n}\\n\",\"modals.less\":\"//\\n// Modals\\n// --------------------------------------------------\\n\\n// .modal-open      - body class for killing the scroll\\n// .modal           - container to scroll within\\n// .modal-dialog    - positioning shell for the actual modal\\n// .modal-content   - actual modal w/ bg and corners and shit\\n\\n// Kill the scroll on the body\\n.modal-open {\\n  overflow: hidden;\\n\\n\\n  // Account for hiding of scrollbar\\n  body&,\\n  .navbar-fixed-top,\\n  .navbar-fixed-bottom {\\n    margin-right: 15px\\n  }\\n}\\n\\n// Container that the modal scrolls within\\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: @zindex-modal-background;\\n\\n  // When fading in the modal, animate it to slide down\\n  &.fade .modal-dialog {\\n    .translate(0, -25%);\\n    .transition-transform(~\\\"0.3s ease-out\\\");\\n  }\\n  &.in .modal-dialog { .translate(0, 0)}\\n}\\n\\n// Shell div to position the modal with bottom padding\\n.modal-dialog {\\n  margin-left: auto;\\n  margin-right: auto;\\n  width: auto;\\n  padding: 10px;\\n  z-index: (@zindex-modal-background + 10);\\n}\\n\\n// Actual modal\\n.modal-content {\\n  position: relative;\\n  background-color: @modal-content-bg;\\n  border: 1px solid @modal-content-fallback-border-color; //old browsers fallback (ie8 etc)\\n  border: 1px solid @modal-content-border-color;\\n  border-radius: @border-radius-large;\\n  .box-shadow(0 3px 9px rgba(0,0,0,.5));\\n  background-clip: padding-box;\\n  // Remove focus outline from opened modal\\n  outline: none;\\n}\\n\\n// Modal background\\n.modal-backdrop {\\n  position: fixed;\\n  top: 0;\\n  right: 0;\\n  bottom: 0;\\n  left: 0;\\n  z-index: (@zindex-modal-background - 10);\\n  background-color: @modal-backdrop-bg;\\n  // Fade for backdrop\\n  &.fade { .opacity(0); }\\n  &.in { .opacity(.5); }\\n}\\n\\n// Modal header\\n// Top section of the modal w/ title and dismiss\\n.modal-header {\\n  padding: @modal-title-padding;\\n  border-bottom: 1px solid @modal-header-border-color;\\n  min-height: (@modal-title-padding + @modal-title-line-height);\\n}\\n// Close icon\\n.modal-header .close {\\n  margin-top: -2px;\\n}\\n\\n// Title text within header\\n.modal-title {\\n  margin: 0;\\n  line-height: @modal-title-line-height;\\n}\\n\\n// Modal body\\n// Where all modal content resides (sibling of .modal-header and .modal-footer)\\n.modal-body {\\n  position: relative;\\n  padding: @modal-inner-padding;\\n}\\n\\n// Footer (for actions)\\n.modal-footer {\\n  margin-top: 15px;\\n  padding: (@modal-inner-padding - 1) @modal-inner-padding @modal-inner-padding;\\n  text-align: right; // right align buttons\\n  border-top: 1px solid @modal-footer-border-color;\\n  .clearfix(); // clear it in case folks use .pull-* classes on buttons\\n\\n  // Properly space out buttons\\n  .btn + .btn {\\n    margin-left: 5px;\\n    margin-bottom: 0; // account for input[type=\\\"submit\\\"] which gets the bottom margin like all other inputs\\n  }\\n  // but override that for button groups\\n  .btn-group .btn + .btn {\\n    margin-left: -1px;\\n  }\\n  // and override it for block buttons as well\\n  .btn-block + .btn-block {\\n    margin-left: 0;\\n  }\\n}\\n\\n// Scale up the modal\\n@media screen and (min-width: @screen-tablet) {\\n\\n  .modal-dialog {\\n    left: 50%;\\n    right: auto;\\n    width: 600px;\\n    padding-top: 30px;\\n    padding-bottom: 30px;\\n  }\\n  .modal-content {\\n    .box-shadow(0 5px 15px rgba(0,0,0,.5));\\n  }\\n\\n}\\n\",\"navbar.less\":\"//\\n// Navbars\\n// --------------------------------------------------\\n\\n\\n// Wrapper and base class\\n//\\n// Provide a static navbar from which we expand to create full-width, fixed, and\\n// other navbar variations.\\n\\n.navbar {\\n  position: relative;\\n  z-index: @zindex-navbar;\\n  min-height: @navbar-height; // Ensure a navbar always shows (e.g., without a .navbar-brand in collapsed mode)\\n  margin-bottom: @navbar-margin-bottom;\\n  border: 1px solid transparent;\\n\\n  // Prevent floats from breaking the navbar\\n  .clearfix();\\n\\n  @media (min-width: @grid-float-breakpoint) {\\n    border-radius: @navbar-border-radius;\\n  }\\n}\\n\\n\\n// Navbar heading\\n//\\n// Groups `.navbar-brand` and `.navbar-toggle` into a single component for easy\\n// styling of responsive aspects.\\n\\n.navbar-header {\\n  .clearfix();\\n\\n  @media (min-width: @grid-float-breakpoint) {\\n    float: left;\\n  }\\n}\\n\\n\\n// Navbar collapse (body)\\n//\\n// Group your navbar content into this for easy collapsing and expanding across\\n// various device sizes. By default, this content is collapsed when <768px, but\\n// will expand past that for a horizontal display.\\n//\\n// To start (on mobile devices) the navbar links, forms, and buttons are stacked\\n// vertically and include a `max-height` to overflow in case you have too much\\n// content for the user's viewport.\\n\\n.navbar-collapse {\\n  max-height: 340px;\\n  overflow-x: visible;\\n  padding-right: @navbar-padding-horizontal;\\n  padding-left:  @navbar-padding-horizontal;\\n  border-top: 1px solid transparent;\\n  box-shadow: inset 0 1px 0 rgba(255,255,255,.1);\\n  .clearfix();\\n  -webkit-overflow-scrolling: touch;\\n\\n  &.in {\\n    overflow-y: auto;\\n  }\\n\\n  @media (min-width: @grid-float-breakpoint) {\\n    width: auto;\\n    border-top: 0;\\n    box-shadow: none;\\n\\n    &.collapse {\\n      display: block !important;\\n      height: auto !important;\\n      padding-bottom: 0; // Override default setting\\n      overflow: visible !important;\\n    }\\n\\n    &.in {\\n      overflow-y: visible;\\n    }\\n\\n    // Account for first and last children spacing\\n    .navbar-nav.navbar-left:first-child {\\n      margin-left: -@navbar-padding-horizontal;\\n    }\\n    .navbar-nav.navbar-right:last-child {\\n      margin-right: -@navbar-padding-horizontal;\\n    }\\n    .navbar-text:last-child {\\n      margin-right: 0;\\n    }\\n  }\\n}\\n\\n\\n// Both navbar header and collapse\\n//\\n// When a container is present, change the behavior of the header and collapse.\\n\\n.container > .navbar-header,\\n.container > .navbar-collapse {\\n  margin-right: -@navbar-padding-horizontal;\\n  margin-left:  -@navbar-padding-horizontal;\\n\\n  @media (min-width: @grid-float-breakpoint) {\\n    margin-right: 0;\\n    margin-left:  0;\\n  }\\n}\\n\\n\\n//\\n// Navbar alignment options\\n//\\n// Display the navbar across the entirity of the page or fixed it to the top or\\n// bottom of the page.\\n\\n// Static top (unfixed, but 100% wide) navbar\\n.navbar-static-top {\\n  border-width: 0 0 1px;\\n  @media (min-width: @grid-float-breakpoint) {\\n    border-radius: 0;\\n  }\\n}\\n\\n// Fix the top/bottom navbars when screen real estate supports it\\n.navbar-fixed-top,\\n.navbar-fixed-bottom {\\n  position: fixed;\\n  right: 0;\\n  left: 0;\\n  border-width: 0 0 1px;\\n\\n  // Undo the rounded corners\\n  @media (min-width: @grid-float-breakpoint) {\\n    border-radius: 0;\\n  }\\n}\\n.navbar-fixed-top {\\n  z-index: @zindex-navbar-fixed;\\n  top: 0;\\n}\\n.navbar-fixed-bottom {\\n  bottom: 0;\\n  margin-bottom: 0; // override .navbar defaults\\n}\\n\\n\\n// Brand/project name\\n\\n.navbar-brand {\\n  float: left;\\n  padding: @navbar-padding-vertical @navbar-padding-horizontal;\\n  font-size: @font-size-large;\\n  line-height: @line-height-computed;\\n  &:hover,\\n  &:focus {\\n    text-decoration: none;\\n  }\\n\\n  @media (min-width: @grid-float-breakpoint) {\\n    .navbar > .container & {\\n      margin-left: -@navbar-padding-horizontal;\\n    }\\n  }\\n}\\n\\n\\n// Navbar toggle\\n//\\n// Custom button for toggling the `.navbar-collapse`, powered by the collapse\\n// JavaScript plugin.\\n\\n.navbar-toggle {\\n  position: relative;\\n  float: right;\\n  margin-right: @navbar-padding-horizontal;\\n  padding: 9px 10px;\\n  .navbar-vertical-align(34px);\\n  background-color: transparent;\\n  border: 1px solid transparent;\\n  border-radius: @border-radius-base;\\n\\n  // Bars\\n  .icon-bar {\\n    display: block;\\n    width: 22px;\\n    height: 2px;\\n    border-radius: 1px;\\n  }\\n  .icon-bar + .icon-bar {\\n    margin-top: 4px;\\n  }\\n\\n  @media (min-width: @grid-float-breakpoint) {\\n    display: none;\\n  }\\n}\\n\\n\\n// Navbar nav links\\n//\\n// Builds on top of the `.nav` components with it's own modifier class to make\\n// the nav the full height of the horizontal nav (above 768px).\\n\\n.navbar-nav {\\n  margin: (@navbar-padding-vertical / 2) -@navbar-padding-horizontal;\\n\\n  > li > a {\\n    padding-top:    10px;\\n    padding-bottom: 10px;\\n    line-height: @line-height-computed;\\n  }\\n\\n  @media (max-width: @screen-xs-max) {\\n    // Dropdowns get custom display when collapsed\\n    .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      > li > a,\\n      .dropdown-header {\\n        padding: 5px 15px 5px 25px;\\n      }\\n      > li > a {\\n        line-height: @line-height-computed;\\n        &:hover,\\n        &:focus {\\n          background-image: none;\\n        }\\n      }\\n    }\\n  }\\n\\n  // Uncollapse the nav\\n  @media (min-width: @grid-float-breakpoint) {\\n    float: left;\\n    margin: 0;\\n\\n    > li {\\n      float: left;\\n      > a {\\n        padding-top: ((@navbar-height - @line-height-computed) / 2);\\n        padding-bottom: ((@navbar-height - @line-height-computed) / 2);\\n      }\\n    }\\n  }\\n\\n}\\n\\n\\n// Component alignment\\n//\\n// Repurpose the pull utilities as their own navbar utilities to avoid specifity\\n// issues with parents and chaining. Only do this when the navbar is uncollapsed\\n// though so that navbar contents properly stack and align in mobile.\\n\\n@media (min-width: @grid-float-breakpoint) {\\n  .navbar-left  { .pull-left(); }\\n  .navbar-right { .pull-right(); }\\n}\\n\\n\\n// Navbar form\\n//\\n// Extension of the `.form-inline` with some extra flavor for optimum display in\\n// our navbars.\\n\\n.navbar-form {\\n  margin-left: -@navbar-padding-horizontal;\\n  margin-right: -@navbar-padding-horizontal;\\n  padding: 10px @navbar-padding-horizontal;\\n  border-top: 1px solid transparent;\\n  border-bottom: 1px solid transparent;\\n  @shadow: inset 0 1px 0 rgba(255,255,255,.1), 0 1px 0 rgba(255,255,255,.1);\\n  .box-shadow(@shadow);\\n\\n  // Mixin behavior for optimum display\\n  .form-inline();\\n\\n  .form-group {\\n    @media (max-width: @screen-xs-max) {\\n      margin-bottom: 5px;\\n    }\\n  }\\n\\n  // Vertically center in expanded, horizontal navbar\\n  .navbar-vertical-align(@input-height-base);\\n\\n  // Undo 100% width for pull classes\\n  @media (min-width: @grid-float-breakpoint) {\\n    width: auto;\\n    border: 0;\\n    margin-left: 0;\\n    margin-right: 0;\\n    padding-top: 0;\\n    padding-bottom: 0;\\n    .box-shadow(none);\\n  }\\n}\\n\\n\\n// Dropdown menus\\n\\n// Menu position and menu carets\\n.navbar-nav > li > .dropdown-menu {\\n  margin-top: 0;\\n  .border-top-radius(0);\\n}\\n// Menu position and menu caret support for dropups via extra dropup class\\n.navbar-fixed-bottom .navbar-nav > li > .dropdown-menu {\\n  .border-bottom-radius(0);\\n}\\n\\n// Right aligned menus need alt position\\n.navbar-nav.pull-right > li > .dropdown-menu,\\n.navbar-nav > li > .dropdown-menu.pull-right {\\n  left: auto;\\n  right: 0;\\n}\\n\\n\\n// Buttons in navbars\\n//\\n// Vertically center a button within a navbar (when *not* in a form).\\n\\n.navbar-btn {\\n  .navbar-vertical-align(@input-height-base);\\n}\\n\\n\\n// Text in navbars\\n//\\n// Add a class to make any element properly align itself vertically within the navbars.\\n\\n.navbar-text {\\n  float: left;\\n  .navbar-vertical-align(@line-height-computed);\\n\\n  @media (min-width: @grid-float-breakpoint) {\\n    margin-left: @navbar-padding-horizontal;\\n    margin-right: @navbar-padding-horizontal;\\n  }\\n}\\n\\n// Alternate navbars\\n// --------------------------------------------------\\n\\n// Default navbar\\n.navbar-default {\\n  background-color: @navbar-default-bg;\\n  border-color: @navbar-default-border;\\n\\n  .navbar-brand {\\n    color: @navbar-default-brand-color;\\n    &:hover,\\n    &:focus {\\n      color: @navbar-default-brand-hover-color;\\n      background-color: @navbar-default-brand-hover-bg;\\n    }\\n  }\\n\\n  .navbar-text {\\n    color: @navbar-default-color;\\n  }\\n\\n  .navbar-nav {\\n    > li > a {\\n      color: @navbar-default-link-color;\\n\\n      &:hover,\\n      &:focus {\\n        color: @navbar-default-link-hover-color;\\n        background-color: @navbar-default-link-hover-bg;\\n      }\\n    }\\n    > .active > a {\\n      &,\\n      &:hover,\\n      &:focus {\\n        color: @navbar-default-link-active-color;\\n        background-color: @navbar-default-link-active-bg;\\n      }\\n    }\\n    > .disabled > a {\\n      &,\\n      &:hover,\\n      &:focus {\\n        color: @navbar-default-link-disabled-color;\\n        background-color: @navbar-default-link-disabled-bg;\\n      }\\n    }\\n  }\\n\\n  .navbar-toggle {\\n    border-color: @navbar-default-toggle-border-color;\\n    &:hover,\\n    &:focus {\\n      background-color: @navbar-default-toggle-hover-bg;\\n    }\\n    .icon-bar {\\n      background-color: @navbar-default-toggle-icon-bar-bg;\\n    }\\n  }\\n\\n  .navbar-collapse,\\n  .navbar-form {\\n    border-color: darken(@navbar-default-bg, 7%);\\n  }\\n\\n  // Dropdown menu items and carets\\n  .navbar-nav {\\n    // Caret should match text color on hover\\n    > .dropdown > a:hover .caret,\\n    > .dropdown > a:focus .caret {\\n      border-top-color: @navbar-default-link-hover-color;\\n      border-bottom-color: @navbar-default-link-hover-color;\\n    }\\n\\n    // Remove background color from open dropdown\\n    > .open > a {\\n      &,\\n      &:hover,\\n      &:focus {\\n        background-color: @navbar-default-link-active-bg;\\n        color: @navbar-default-link-active-color;\\n        .caret {\\n          border-top-color: @navbar-default-link-active-color;\\n          border-bottom-color: @navbar-default-link-active-color;\\n        }\\n      }\\n    }\\n    > .dropdown > a .caret {\\n      border-top-color: @navbar-default-link-color;\\n      border-bottom-color: @navbar-default-link-color;\\n    }\\n\\n\\n    @media (max-width: @screen-xs-max) {\\n      // Dropdowns get custom display when collapsed\\n      .open .dropdown-menu {\\n        > li > a {\\n          color: @navbar-default-link-color;\\n          &:hover,\\n          &:focus {\\n            color: @navbar-default-link-hover-color;\\n            background-color: @navbar-default-link-hover-bg;\\n          }\\n        }\\n        > .active > a {\\n          &,\\n          &:hover,\\n          &:focus {\\n            color: @navbar-default-link-active-color;\\n            background-color: @navbar-default-link-active-bg;\\n          }\\n        }\\n        > .disabled > a {\\n          &,\\n          &:hover,\\n          &:focus {\\n            color: @navbar-default-link-disabled-color;\\n            background-color: @navbar-default-link-disabled-bg;\\n          }\\n        }\\n      }\\n    }\\n  }\\n\\n\\n  // Links in navbars\\n  //\\n  // Add a class to ensure links outside the navbar nav are colored correctly.\\n\\n  .navbar-link {\\n    color: @navbar-default-link-color;\\n    &:hover {\\n      color: @navbar-default-link-hover-color;\\n    }\\n  }\\n\\n}\\n\\n// Inverse navbar\\n\\n.navbar-inverse {\\n  background-color: @navbar-inverse-bg;\\n  border-color: @navbar-inverse-border;\\n\\n  .navbar-brand {\\n    color: @navbar-inverse-brand-color;\\n    &:hover,\\n    &:focus {\\n      color: @navbar-inverse-brand-hover-color;\\n      background-color: @navbar-inverse-brand-hover-bg;\\n    }\\n  }\\n\\n  .navbar-text {\\n    color: @navbar-inverse-color;\\n  }\\n\\n  .navbar-nav {\\n    > li > a {\\n      color: @navbar-inverse-link-color;\\n\\n      &:hover,\\n      &:focus {\\n        color: @navbar-inverse-link-hover-color;\\n        background-color: @navbar-inverse-link-hover-bg;\\n      }\\n    }\\n    > .active > a {\\n      &,\\n      &:hover,\\n      &:focus {\\n        color: @navbar-inverse-link-active-color;\\n        background-color: @navbar-inverse-link-active-bg;\\n      }\\n    }\\n    > .disabled > a {\\n      &,\\n      &:hover,\\n      &:focus {\\n        color: @navbar-inverse-link-disabled-color;\\n        background-color: @navbar-inverse-link-disabled-bg;\\n      }\\n    }\\n  }\\n\\n  // Darken the responsive nav toggle\\n  .navbar-toggle {\\n    border-color: @navbar-inverse-toggle-border-color;\\n    &:hover,\\n    &:focus {\\n      background-color: @navbar-inverse-toggle-hover-bg;\\n    }\\n    .icon-bar {\\n      background-color: @navbar-inverse-toggle-icon-bar-bg;\\n    }\\n  }\\n\\n  .navbar-collapse,\\n  .navbar-form {\\n    border-color: darken(@navbar-inverse-bg, 7%);\\n  }\\n\\n  // Dropdowns\\n  .navbar-nav {\\n    > .open > a {\\n      &,\\n      &:hover,\\n      &:focus {\\n        background-color: @navbar-inverse-link-active-bg;\\n        color: @navbar-inverse-link-active-color;\\n      }\\n    }\\n    > .dropdown > a:hover .caret {\\n      border-top-color: @navbar-inverse-link-hover-color;\\n      border-bottom-color: @navbar-inverse-link-hover-color;\\n    }\\n    > .dropdown > a .caret {\\n      border-top-color: @navbar-inverse-link-color;\\n      border-bottom-color: @navbar-inverse-link-color;\\n    }\\n    > .open > a {\\n      &,\\n      &:hover,\\n      &:focus {\\n        .caret {\\n          border-top-color: @navbar-inverse-link-active-color;\\n          border-bottom-color: @navbar-inverse-link-active-color;\\n        }\\n      }\\n    }\\n\\n    @media (max-width: @screen-xs-max) {\\n      // Dropdowns get custom display\\n      .open .dropdown-menu {\\n        > .dropdown-header {\\n          border-color: @navbar-inverse-border;\\n        }\\n        > li > a {\\n          color: @navbar-inverse-link-color;\\n          &:hover,\\n          &:focus {\\n            color: @navbar-inverse-link-hover-color;\\n            background-color: @navbar-inverse-link-hover-bg;\\n          }\\n        }\\n        > .active > a {\\n          &,\\n          &:hover,\\n          &:focus {\\n            color: @navbar-inverse-link-active-color;\\n            background-color: @navbar-inverse-link-active-bg;\\n          }\\n        }\\n        > .disabled > a {\\n          &,\\n          &:hover,\\n          &:focus {\\n            color: @navbar-inverse-link-disabled-color;\\n            background-color: @navbar-inverse-link-disabled-bg;\\n          }\\n        }\\n      }\\n    }\\n  }\\n\\n  .navbar-link {\\n    color: @navbar-inverse-link-color;\\n    &:hover {\\n      color: @navbar-inverse-link-hover-color;\\n    }\\n  }\\n\\n}\\n\",\"navs.less\":\"//\\n// Navs\\n// --------------------------------------------------\\n\\n\\n// Base class\\n// --------------------------------------------------\\n\\n.nav {\\n  margin-bottom: 0;\\n  padding-left: 0; // Override default ul/ol\\n  list-style: none;\\n  .clearfix();\\n\\n  > li {\\n    position: relative;\\n    display: block;\\n\\n    > a {\\n      position: relative;\\n      display: block;\\n      padding: @nav-link-padding;\\n      &:hover,\\n      &:focus {\\n        text-decoration: none;\\n        background-color: @nav-link-hover-bg;\\n      }\\n    }\\n\\n    // Disabled state sets text to gray and nukes hover/tab effects\\n    &.disabled > a {\\n      color: @nav-disabled-link-color;\\n\\n      &:hover,\\n      &:focus {\\n        color: @nav-disabled-link-hover-color;\\n        text-decoration: none;\\n        background-color: transparent;\\n        cursor: not-allowed;\\n      }\\n    }\\n  }\\n\\n  // Open dropdowns\\n  .open > a {\\n    &,\\n    &:hover,\\n    &:focus {\\n      background-color: @nav-link-hover-bg;\\n      border-color: @link-color;\\n    }\\n  }\\n\\n  // Dividers (basically an hr) within the dropdown\\n  .nav-divider {\\n    .nav-divider();\\n  }\\n\\n  // Prevent IE8 from misplacing imgs\\n  // See https://github.com/h5bp/html5-boilerplate/issues/984#issuecomment-3985989\\n  > li > a > img {\\n    max-width: none;\\n  }\\n}\\n\\n\\n// Tabs\\n// -------------------------\\n\\n// Give the tabs something to sit on\\n.nav-tabs {\\n  border-bottom: 1px solid @nav-tabs-border-color;\\n  > li {\\n    float: left;\\n    // Make the list-items overlay the bottom border\\n    margin-bottom: -1px;\\n\\n    // Actual tabs (as links)\\n    > a {\\n      margin-right: 2px;\\n      line-height: @line-height-base;\\n      border: 1px solid transparent;\\n      border-radius: @border-radius-base @border-radius-base 0 0;\\n      &:hover {\\n        border-color: @nav-tabs-link-hover-border-color @nav-tabs-link-hover-border-color @nav-tabs-border-color;\\n      }\\n    }\\n\\n    // Active state, and it's :hover to override normal :hover\\n    &.active > a {\\n      &,\\n      &:hover,\\n      &:focus {\\n        color: @nav-tabs-active-link-hover-color;\\n        background-color: @nav-tabs-active-link-hover-bg;\\n        border: 1px solid @nav-tabs-active-link-hover-border-color;\\n        border-bottom-color: transparent;\\n        cursor: default;\\n      }\\n    }\\n  }\\n  // pulling this in mainly for less shorthand\\n  &.nav-justified {\\n    .nav-justified();\\n    .nav-tabs-justified();\\n  }\\n}\\n\\n\\n// Pills\\n// -------------------------\\n.nav-pills {\\n  > li {\\n    float: left;\\n\\n    // Links rendered as pills\\n    > a {\\n      border-radius: 5px;\\n    }\\n    + li {\\n      margin-left: 2px;\\n    }\\n\\n    // Active state\\n    &.active > a {\\n      &,\\n      &:hover,\\n      &:focus {\\n        color: @nav-pills-active-link-hover-color;\\n        background-color: @nav-pills-active-link-hover-bg;\\n      }\\n    }\\n  }\\n}\\n\\n\\n// Stacked pills\\n.nav-stacked {\\n  > li {\\n    float: none;\\n    + li {\\n      margin-top: 2px;\\n      margin-left: 0; // no need for this gap between nav items\\n    }\\n  }\\n}\\n\\n\\n// Nav variations\\n// --------------------------------------------------\\n\\n// Justified nav links\\n// -------------------------\\n\\n.nav-justified {\\n  width: 100%;\\n\\n  > li {\\n    float: none;\\n     > a {\\n      text-align: center;\\n    }\\n  }\\n\\n  @media (min-width: @screen-sm) {\\n    > li {\\n      display: table-cell;\\n      width: 1%;\\n    }\\n  }\\n}\\n\\n// Move borders to anchors instead of bottom of list\\n.nav-tabs-justified {\\n  border-bottom: 0;\\n  > li > a {\\n    border-bottom: 1px solid @nav-tabs-justified-link-border-color;\\n\\n    // Override margin from .nav-tabs\\n    margin-right: 0;\\n  }\\n  > .active > a {\\n    border-bottom-color: @nav-tabs-justified-active-link-border-color;\\n  }\\n}\\n\\n\\n// Tabbable tabs\\n// -------------------------\\n\\n// Clear any floats\\n.tabbable {\\n  .clearfix();\\n}\\n\\n// Show/hide tabbable areas\\n.tab-content > .tab-pane,\\n.pill-content > .pill-pane {\\n  display: none;\\n}\\n.tab-content,\\n.pill-content {\\n  > .active {\\n    display: block;\\n  }\\n}\\n\\n\\n\\n// Dropdowns\\n// -------------------------\\n\\n// Make dropdown carets use link color in navs\\n.nav .caret {\\n  border-top-color: @link-color;\\n  border-bottom-color: @link-color;\\n}\\n.nav a:hover .caret {\\n  border-top-color: @link-hover-color;\\n  border-bottom-color: @link-hover-color;\\n}\\n\\n// Specific dropdowns\\n.nav-tabs .dropdown-menu {\\n  // make dropdown border overlap tab border\\n  margin-top: -1px;\\n  // Remove the top rounded corners here since there is a hard edge above the menu\\n  .border-top-radius(0);\\n}\\n\",\"normalize.less\":\"/*! normalize.css v2.1.0 | MIT License | git.io/normalize */\\n\\n// ==========================================================================\\n// HTML5 display definitions\\n// ==========================================================================\\n\\n//\\n// Correct `block` display not defined in IE 8/9.\\n//\\n\\narticle,\\naside,\\ndetails,\\nfigcaption,\\nfigure,\\nfooter,\\nheader,\\nhgroup,\\nmain,\\nnav,\\nsection,\\nsummary {\\n  display: block;\\n}\\n\\n//\\n// Correct `inline-block` display not defined in IE 8/9.\\n//\\n\\naudio,\\ncanvas,\\nvideo {\\n  display: inline-block;\\n}\\n\\n//\\n// Prevent modern browsers from displaying `audio` without controls.\\n// Remove excess height in iOS 5 devices.\\n//\\n\\naudio:not([controls]) {\\n  display: none;\\n  height: 0;\\n}\\n\\n//\\n// Address styling not present in IE 8/9.\\n//\\n\\n[hidden] {\\n  display: none;\\n}\\n\\n// ==========================================================================\\n// Base\\n// ==========================================================================\\n\\n//\\n// 1. Set default font family to sans-serif.\\n// 2. Prevent iOS text size adjust after orientation change, without disabling\\n//    user zoom.\\n//\\n\\nhtml {\\n  font-family: sans-serif; // 1\\n  -webkit-text-size-adjust: 100%; // 2\\n  -ms-text-size-adjust: 100%; // 2\\n}\\n\\n//\\n// Remove default margin.\\n//\\n\\nbody {\\n  margin: 0;\\n}\\n\\n// ==========================================================================\\n// Links\\n// ==========================================================================\\n\\n//\\n// Address `outline` inconsistency between Chrome and other browsers.\\n//\\n\\na:focus {\\n  outline: thin dotted;\\n}\\n\\n//\\n// Improve readability when focused and also mouse hovered in all browsers.\\n//\\n\\na:active,\\na:hover {\\n  outline: 0;\\n}\\n\\n// ==========================================================================\\n// Typography\\n// ==========================================================================\\n\\n//\\n// Address variable `h1` font-size and margin within `section` and `article`\\n// contexts in Firefox 4+, Safari 5, and Chrome.\\n//\\n\\nh1 {\\n  font-size: 2em;\\n  margin: 0.67em 0;\\n}\\n\\n//\\n// Address styling not present in IE 8/9, Safari 5, and Chrome.\\n//\\n\\nabbr[title] {\\n  border-bottom: 1px dotted;\\n}\\n\\n//\\n// Address style set to `bolder` in Firefox 4+, Safari 5, and Chrome.\\n//\\n\\nb,\\nstrong {\\n  font-weight: bold;\\n}\\n\\n//\\n// Address styling not present in Safari 5 and Chrome.\\n//\\n\\ndfn {\\n  font-style: italic;\\n}\\n\\n//\\n// Address differences between Firefox and other browsers.\\n//\\n\\nhr {\\n  -moz-box-sizing: content-box;\\n  box-sizing: content-box;\\n  height: 0;\\n}\\n\\n//\\n// Address styling not present in IE 8/9.\\n//\\n\\nmark {\\n  background: #ff0;\\n  color: #000;\\n}\\n\\n//\\n// Correct font family set oddly in Safari 5 and Chrome.\\n//\\n\\ncode,\\nkbd,\\npre,\\nsamp {\\n  font-family: monospace, serif;\\n  font-size: 1em;\\n}\\n\\n//\\n// Improve readability of pre-formatted text in all browsers.\\n//\\n\\npre {\\n  white-space: pre-wrap;\\n}\\n\\n//\\n// Set consistent quote types.\\n//\\n\\nq {\\n  quotes: \\\"\\\\201C\\\" \\\"\\\\201D\\\" \\\"\\\\2018\\\" \\\"\\\\2019\\\";\\n}\\n\\n//\\n// Address inconsistent and variable font size in all browsers.\\n//\\n\\nsmall {\\n  font-size: 80%;\\n}\\n\\n//\\n// Prevent `sub` and `sup` affecting `line-height` in all browsers.\\n//\\n\\nsub,\\nsup {\\n  font-size: 75%;\\n  line-height: 0;\\n  position: relative;\\n  vertical-align: baseline;\\n}\\n\\nsup {\\n  top: -0.5em;\\n}\\n\\nsub {\\n  bottom: -0.25em;\\n}\\n\\n// ==========================================================================\\n// Embedded content\\n// ==========================================================================\\n\\n//\\n// Remove border when inside `a` element in IE 8/9.\\n//\\n\\nimg {\\n  border: 0;\\n}\\n\\n//\\n// Correct overflow displayed oddly in IE 9.\\n//\\n\\nsvg:not(:root) {\\n  overflow: hidden;\\n}\\n\\n// ==========================================================================\\n// Figures\\n// ==========================================================================\\n\\n//\\n// Address margin not present in IE 8/9 and Safari 5.\\n//\\n\\nfigure {\\n  margin: 0;\\n}\\n\\n// ==========================================================================\\n// Forms\\n// ==========================================================================\\n\\n//\\n// Define consistent border, margin, and padding.\\n//\\n\\nfieldset {\\n  border: 1px solid #c0c0c0;\\n  margin: 0 2px;\\n  padding: 0.35em 0.625em 0.75em;\\n}\\n\\n//\\n// 1. Correct `color` not being inherited in IE 8/9.\\n// 2. Remove padding so people aren't caught out if they zero out fieldsets.\\n//\\n\\nlegend {\\n  border: 0; // 1\\n  padding: 0; // 2\\n}\\n\\n//\\n// 1. Correct font family not being inherited in all browsers.\\n// 2. Correct font size not being inherited in all browsers.\\n// 3. Address margins set differently in Firefox 4+, Safari 5, and Chrome.\\n//\\n\\nbutton,\\ninput,\\nselect,\\ntextarea {\\n  font-family: inherit; // 1\\n  font-size: 100%; // 2\\n  margin: 0; // 3\\n}\\n\\n//\\n// Address Firefox 4+ setting `line-height` on `input` using `!important` in\\n// the UA stylesheet.\\n//\\n\\nbutton,\\ninput {\\n  line-height: normal;\\n}\\n\\n//\\n// Address inconsistent `text-transform` inheritance for `button` and `select`.\\n// All other form control elements do not inherit `text-transform` values.\\n// Correct `button` style inheritance in Chrome, Safari 5+, and IE 8+.\\n// Correct `select` style inheritance in Firefox 4+ and Opera.\\n//\\n\\nbutton,\\nselect {\\n  text-transform: none;\\n}\\n\\n//\\n// 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio`\\n//    and `video` controls.\\n// 2. Correct inability to style clickable `input` types in iOS.\\n// 3. Improve usability and consistency of cursor style between image-type\\n//    `input` and others.\\n//\\n\\nbutton,\\nhtml input[type=\\\"button\\\"], // 1\\ninput[type=\\\"reset\\\"],\\ninput[type=\\\"submit\\\"] {\\n  -webkit-appearance: button; // 2\\n  cursor: pointer; // 3\\n}\\n\\n//\\n// Re-set default cursor for disabled elements.\\n//\\n\\nbutton[disabled],\\nhtml input[disabled] {\\n  cursor: default;\\n}\\n\\n//\\n// 1. Address box sizing set to `content-box` in IE 8/9.\\n// 2. Remove excess padding in IE 8/9.\\n//\\n\\ninput[type=\\\"checkbox\\\"],\\ninput[type=\\\"radio\\\"] {\\n  box-sizing: border-box; // 1\\n  padding: 0; // 2\\n}\\n\\n//\\n// 1. Address `appearance` set to `searchfield` in Safari 5 and Chrome.\\n// 2. Address `box-sizing` set to `border-box` in Safari 5 and Chrome\\n//    (include `-moz` to future-proof).\\n//\\n\\ninput[type=\\\"search\\\"] {\\n  -webkit-appearance: textfield; // 1\\n  -moz-box-sizing: content-box;\\n  -webkit-box-sizing: content-box; // 2\\n  box-sizing: content-box;\\n}\\n\\n//\\n// Remove inner padding and search cancel button in Safari 5 and Chrome\\n// on OS X.\\n//\\n\\ninput[type=\\\"search\\\"]::-webkit-search-cancel-button,\\ninput[type=\\\"search\\\"]::-webkit-search-decoration {\\n  -webkit-appearance: none;\\n}\\n\\n//\\n// Remove inner padding and border in Firefox 4+.\\n//\\n\\nbutton::-moz-focus-inner,\\ninput::-moz-focus-inner {\\n  border: 0;\\n  padding: 0;\\n}\\n\\n//\\n// 1. Remove default vertical scrollbar in IE 8/9.\\n// 2. Improve readability and alignment in all browsers.\\n//\\n\\ntextarea {\\n  overflow: auto; // 1\\n  vertical-align: top; // 2\\n}\\n\\n// ==========================================================================\\n// Tables\\n// ==========================================================================\\n\\n//\\n// Remove most spacing between table cells.\\n//\\n\\ntable {\\n  border-collapse: collapse;\\n  border-spacing: 0;\\n}\\n\",\"pager.less\":\"//\\n// Pager pagination\\n// --------------------------------------------------\\n\\n\\n.pager {\\n  padding-left: 0;\\n  margin: @line-height-computed 0;\\n  list-style: none;\\n  text-align: center;\\n  .clearfix();\\n  li {\\n    display: inline;\\n    > a,\\n    > span {\\n      display: inline-block;\\n      padding: 5px 14px;\\n      background-color: @pagination-bg;\\n      border: 1px solid @pagination-border;\\n      border-radius: @pager-border-radius;\\n    }\\n\\n    > a:hover,\\n    > a:focus {\\n      text-decoration: none;\\n      background-color: @pagination-hover-bg;\\n    }\\n  }\\n\\n  .next {\\n    > a,\\n    > span {\\n      float: right;\\n    }\\n  }\\n\\n  .previous {\\n    > a,\\n    > span {\\n      float: left;\\n    }\\n  }\\n\\n  .disabled {\\n    > a,\\n    > a:hover,\\n    > a:focus,\\n    > span {\\n      color: @pager-disabled-color;\\n      background-color: @pagination-bg;\\n      cursor: not-allowed;\\n    }\\n  }\\n\\n}\\n\",\"pagination.less\":\"//\\n// Pagination (multiple pages)\\n// --------------------------------------------------\\n.pagination {\\n  display: inline-block;\\n  padding-left: 0;\\n  margin: @line-height-computed 0;\\n  border-radius: @border-radius-base;\\n\\n  > li {\\n    display: inline; // Remove list-style and block-level defaults\\n    > a,\\n    > span {\\n      position: relative;\\n      float: left; // Collapse white-space\\n      padding: @padding-base-vertical @padding-base-horizontal;\\n      line-height: @line-height-base;\\n      text-decoration: none;\\n      background-color: @pagination-bg;\\n      border: 1px solid @pagination-border;\\n      margin-left: -1px;\\n    }\\n    &:first-child {\\n      > a,\\n      > span {\\n        margin-left: 0;\\n        .border-left-radius(@border-radius-base);\\n      }\\n    }\\n    &:last-child {\\n      > a,\\n      > span {\\n        .border-right-radius(@border-radius-base);\\n      }\\n    }\\n  }\\n\\n  > li > a,\\n  > li > span {\\n    &:hover,\\n    &:focus {\\n      background-color: @pagination-hover-bg;\\n    }\\n  }\\n\\n  > .active > a,\\n  > .active > span {\\n    &,\\n    &:hover,\\n    &:focus {\\n      z-index: 2;\\n      color: @pagination-active-color;\\n      background-color: @pagination-active-bg;\\n      border-color: @pagination-active-bg;\\n      cursor: default;\\n    }\\n  }\\n\\n  > .disabled {\\n    > span,\\n    > a,\\n    > a:hover,\\n    > a:focus {\\n      color: @pagination-disabled-color;\\n      background-color: @pagination-bg;\\n      border-color: @pagination-border;\\n      cursor: not-allowed;\\n    }\\n  }\\n}\\n\\n// Sizing\\n// --------------------------------------------------\\n\\n// Large\\n.pagination-lg {\\n  .pagination-size(@padding-large-vertical; @padding-large-horizontal; @font-size-large; @border-radius-large);\\n}\\n\\n// Small\\n.pagination-sm {\\n  .pagination-size(@padding-small-vertical; @padding-small-horizontal; @font-size-small; @border-radius-small);\\n}\\n\",\"panels.less\":\"//\\n// Panels\\n// --------------------------------------------------\\n\\n\\n// Base class\\n.panel {\\n  margin-bottom: @line-height-computed;\\n  background-color: @panel-bg;\\n  border: 1px solid transparent;\\n  border-radius: @panel-border-radius;\\n  .box-shadow(0 1px 1px rgba(0,0,0,.05));\\n}\\n\\n// Panel contents\\n.panel-body {\\n  padding: 15px;\\n  .clearfix();\\n}\\n\\n\\n// List groups in panels\\n//\\n// By default, space out list group content from panel headings to account for\\n// any kind of custom content between the two.\\n\\n.panel {\\n  > .list-group {\\n    margin-bottom: 0;\\n\\n    .list-group-item {\\n      border-width: 1px 0;\\n\\n      // Remove border radius for top one\\n      &:first-child {\\n        .border-top-radius(0);\\n      }\\n      // But keep it for the last one\\n      &:last-child {\\n        border-bottom: 0;\\n      }\\n    }\\n  }\\n}\\n// Collapse space between when there's no additional content.\\n.panel-heading + .list-group {\\n  .list-group-item:first-child {\\n    border-top-width: 0;\\n  }\\n}\\n\\n\\n// Tables in panels\\n//\\n// Place a non-bordered `.table` within a panel (not within a `.panel-body`) and\\n// watch it go full width.\\n\\n.panel {\\n  > .table {\\n    margin-bottom: 0;\\n  }\\n  > .panel-body + .table {\\n    border-top: 1px solid @table-border-color;\\n  }\\n}\\n\\n\\n// Optional heading\\n.panel-heading {\\n  padding: 10px 15px;\\n  border-bottom: 1px solid transparent;\\n  .border-top-radius(@panel-border-radius - 1);\\n}\\n\\n// Within heading, strip any `h*` tag of it's default margins for spacing.\\n.panel-title {\\n  margin-top: 0;\\n  margin-bottom: 0;\\n  font-size: ceil((@font-size-base * 1.125));\\n  > a {\\n    color: inherit;\\n  }\\n}\\n\\n// Optional footer (stays gray in every modifier class)\\n.panel-footer {\\n  padding: 10px 15px;\\n  background-color: @panel-footer-bg;\\n  border-top: 1px solid @panel-inner-border;\\n  .border-bottom-radius(@panel-border-radius - 1);\\n}\\n\\n\\n// Collapsable panels (aka, accordion)\\n//\\n// Wrap a series of panels in `.panel-group` to turn them into an accordion with\\n// the help of our collapse JavaScript plugin.\\n\\n.panel-group {\\n  // Tighten up margin so it's only between panels\\n  .panel {\\n    margin-bottom: 0;\\n    border-radius: @panel-border-radius;\\n    overflow: hidden; // crop contents when collapsed\\n    + .panel {\\n      margin-top: 5px;\\n    }\\n  }\\n\\n  .panel-heading {\\n    border-bottom: 0;\\n    + .panel-collapse .panel-body {\\n      border-top: 1px solid @panel-inner-border;\\n    }\\n  }\\n  .panel-footer {\\n    border-top: 0;\\n    + .panel-collapse .panel-body {\\n      border-bottom: 1px solid @panel-inner-border;\\n    }\\n  }\\n\\n  // New subcomponent for wrapping collapsable content for proper animations\\n  .panel-collapse {\\n\\n  }\\n}\\n\\n\\n// Contextual variations\\n.panel-default {\\n  .panel-variant(@panel-default-border; @panel-default-text; @panel-default-heading-bg; @panel-default-border);\\n}\\n.panel-primary {\\n  .panel-variant(@panel-primary-border; @panel-primary-text; @panel-primary-heading-bg; @panel-primary-border);\\n}\\n.panel-success {\\n  .panel-variant(@panel-success-border; @panel-success-text; @panel-success-heading-bg; @panel-success-border);\\n}\\n.panel-warning {\\n  .panel-variant(@panel-warning-border; @panel-warning-text; @panel-warning-heading-bg; @panel-warning-border);\\n}\\n.panel-danger {\\n  .panel-variant(@panel-danger-border; @panel-danger-text; @panel-danger-heading-bg; @panel-danger-border);\\n}\\n.panel-info {\\n  .panel-variant(@panel-info-border; @panel-info-text; @panel-info-heading-bg; @panel-info-border);\\n}\\n\",\"popovers.less\":\"//\\n// Popovers\\n// --------------------------------------------------\\n\\n\\n.popover {\\n  position: absolute;\\n  top: 0;\\n  left: 0;\\n  z-index: @zindex-popover;\\n  display: none;\\n  max-width: @popover-max-width;\\n  padding: 1px;\\n  text-align: left; // Reset given new insertion method\\n  background-color: @popover-bg;\\n  background-clip: padding-box;\\n  border: 1px solid @popover-fallback-border-color;\\n  border: 1px solid @popover-border-color;\\n  border-radius: @border-radius-large;\\n  .box-shadow(0 5px 10px rgba(0,0,0,.2));\\n\\n  // Overrides for proper insertion\\n  white-space: normal;\\n\\n  // Offset the popover to account for the popover arrow\\n  &.top     { margin-top: -10px; }\\n  &.right   { margin-left: 10px; }\\n  &.bottom  { margin-top: 10px; }\\n  &.left    { margin-left: -10px; }\\n}\\n\\n.popover-title {\\n  margin: 0; // reset heading margin\\n  padding: 8px 14px;\\n  font-size: @font-size-base;\\n  font-weight: normal;\\n  line-height: 18px;\\n  background-color: @popover-title-bg;\\n  border-bottom: 1px solid darken(@popover-title-bg, 5%);\\n  border-radius: 5px 5px 0 0;\\n}\\n\\n.popover-content {\\n  padding: 9px 14px;\\n}\\n\\n// Arrows\\n//\\n// .arrow is outer, .arrow:after is inner\\n\\n.popover .arrow {\\n  &,\\n  &:after {\\n    position: absolute;\\n    display: block;\\n    width: 0;\\n    height: 0;\\n    border-color: transparent;\\n    border-style: solid;\\n  }\\n}\\n.popover .arrow {\\n  border-width: @popover-arrow-outer-width;\\n}\\n.popover .arrow:after {\\n  border-width: @popover-arrow-width;\\n  content: \\\"\\\";\\n}\\n\\n.popover {\\n  &.top .arrow {\\n    left: 50%;\\n    margin-left: -@popover-arrow-outer-width;\\n    border-bottom-width: 0;\\n    border-top-color: @popover-arrow-outer-fallback-color; // IE8 fallback\\n    border-top-color: @popover-arrow-outer-color;\\n    bottom: -@popover-arrow-outer-width;\\n    &:after {\\n      content: \\\" \\\";\\n      bottom: 1px;\\n      margin-left: -@popover-arrow-width;\\n      border-bottom-width: 0;\\n      border-top-color: @popover-arrow-color;\\n    }\\n  }\\n  &.right .arrow {\\n    top: 50%;\\n    left: -@popover-arrow-outer-width;\\n    margin-top: -@popover-arrow-outer-width;\\n    border-left-width: 0;\\n    border-right-color: @popover-arrow-outer-fallback-color; // IE8 fallback\\n    border-right-color: @popover-arrow-outer-color;\\n    &:after {\\n      content: \\\" \\\";\\n      left: 1px;\\n      bottom: -@popover-arrow-width;\\n      border-left-width: 0;\\n      border-right-color: @popover-arrow-color;\\n    }\\n  }\\n  &.bottom .arrow {\\n    left: 50%;\\n    margin-left: -@popover-arrow-outer-width;\\n    border-top-width: 0;\\n    border-bottom-color: @popover-arrow-outer-fallback-color; // IE8 fallback\\n    border-bottom-color: @popover-arrow-outer-color;\\n    top: -@popover-arrow-outer-width;\\n    &:after {\\n      content: \\\" \\\";\\n      top: 1px;\\n      margin-left: -@popover-arrow-width;\\n      border-top-width: 0;\\n      border-bottom-color: @popover-arrow-color;\\n    }\\n  }\\n\\n  &.left .arrow {\\n    top: 50%;\\n    right: -@popover-arrow-outer-width;\\n    margin-top: -@popover-arrow-outer-width;\\n    border-right-width: 0;\\n    border-left-color: @popover-arrow-outer-fallback-color; // IE8 fallback\\n    border-left-color: @popover-arrow-outer-color;\\n    &:after {\\n      content: \\\" \\\";\\n      right: 1px;\\n      border-right-width: 0;\\n      border-left-color: @popover-arrow-color;\\n      bottom: -@popover-arrow-width;\\n    }\\n  }\\n\\n}\\n\",\"print.less\":\"//\\n// Basic print styles\\n// --------------------------------------------------\\n// Source: https://github.com/h5bp/html5-boilerplate/blob/master/css/main.css\\n\\n@media print {\\n\\n  * {\\n    text-shadow: none !important;\\n    color: #000 !important; // Black prints faster: h5bp.com/s\\n    background: transparent !important;\\n    box-shadow: none !important;\\n  }\\n\\n  a,\\n  a:visited {\\n    text-decoration: underline;\\n  }\\n\\n  a[href]:after {\\n    content: \\\" (\\\" attr(href) \\\")\\\";\\n  }\\n\\n  abbr[title]:after {\\n    content: \\\" (\\\" attr(title) \\\")\\\";\\n  }\\n\\n  // Don't show links for images, or javascript/internal links\\n  .ir a:after,\\n  a[href^=\\\"javascript:\\\"]:after,\\n  a[href^=\\\"#\\\"]:after {\\n    content: \\\"\\\";\\n  }\\n\\n  pre,\\n  blockquote {\\n    border: 1px solid #999;\\n    page-break-inside: avoid;\\n  }\\n\\n  thead {\\n    display: table-header-group; // h5bp.com/t\\n  }\\n\\n  tr,\\n  img {\\n    page-break-inside: avoid;\\n  }\\n\\n  img {\\n    max-width: 100% !important;\\n  }\\n\\n  @page {\\n    margin: 2cm .5cm;\\n  }\\n\\n  p,\\n  h2,\\n  h3 {\\n    orphans: 3;\\n    widows: 3;\\n  }\\n\\n  h2,\\n  h3 {\\n    page-break-after: avoid;\\n  }\\n\\n  // Bootstrap components\\n  .navbar {\\n    display: none;\\n  }\\n  .table {\\n    td,\\n    th {\\n      background-color: #fff !important;\\n    }\\n  }\\n  .btn,\\n  .dropup > .btn {\\n    > .caret {\\n      border-top-color: #000 !important;\\n    }\\n  }\\n  .label {\\n    border: 1px solid #000;\\n  }\\n\\n  .table {\\n    border-collapse: collapse !important;\\n  }\\n  .table-bordered {\\n    th,\\n    td {\\n      border: 1px solid #ddd !important;\\n    }\\n  }\\n\\n}\\n\",\"progress-bars.less\":\"//\\n// Progress bars\\n// --------------------------------------------------\\n\\n\\n// Bar animations\\n// -------------------------\\n\\n// Webkit\\n@-webkit-keyframes progress-bar-stripes {\\n  from  { background-position: 40px 0; }\\n  to    { background-position: 0 0; }\\n}\\n\\n// Firefox\\n@-moz-keyframes progress-bar-stripes {\\n  from  { background-position: 40px 0; }\\n  to    { background-position: 0 0; }\\n}\\n\\n// Opera\\n@-o-keyframes progress-bar-stripes {\\n  from  { background-position: 0 0; }\\n  to    { background-position: 40px 0; }\\n}\\n\\n// Spec and IE10+\\n@keyframes progress-bar-stripes {\\n  from  { background-position: 40px 0; }\\n  to    { background-position: 0 0; }\\n}\\n\\n\\n\\n// Bar itself\\n// -------------------------\\n\\n// Outer container\\n.progress {\\n  overflow: hidden;\\n  height: @line-height-computed;\\n  margin-bottom: @line-height-computed;\\n  background-color: @progress-bg;\\n  border-radius: @border-radius-base;\\n  .box-shadow(inset 0 1px 2px rgba(0,0,0,.1));\\n}\\n\\n// Bar of progress\\n.progress-bar {\\n  float: left;\\n  width: 0%;\\n  height: 100%;\\n  font-size: @font-size-small;\\n  color: @progress-bar-color;\\n  text-align: center;\\n  background-color: @progress-bar-bg;\\n  .box-shadow(inset 0 -1px 0 rgba(0,0,0,.15));\\n  .transition(width .6s ease);\\n}\\n\\n// Striped bars\\n.progress-striped .progress-bar {\\n  #gradient > .striped(@progress-bar-bg);\\n  background-size: 40px 40px;\\n}\\n\\n// Call animation for the active one\\n.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\\n\\n\\n// Variations\\n// -------------------------\\n\\n.progress-bar-success {\\n  .progress-bar-variant(@progress-bar-success-bg);\\n}\\n\\n.progress-bar-info {\\n  .progress-bar-variant(@progress-bar-info-bg);\\n}\\n\\n.progress-bar-warning {\\n  .progress-bar-variant(@progress-bar-warning-bg);\\n}\\n\\n.progress-bar-danger {\\n  .progress-bar-variant(@progress-bar-danger-bg);\\n}\\n\",\"responsive-utilities.less\":\"//\\n// Responsive: Utility classes\\n// --------------------------------------------------\\n\\n\\n// IE10 Metro responsive\\n// Required for Windows 8 Metro split-screen snapping with IE10\\n//\\n// Source: http://timkadlec.com/2012/10/ie10-snap-mode-and-responsive-design/\\n@-ms-viewport{\\n  width: device-width;\\n}\\n\\n// IE10 on Windows Phone 8\\n// IE10 on WP8 doesn't report CSS pixels, but actual device pixels. In\\n// other words, say on a Lumia, you'll get 768px as the device width,\\n// meaning users will see the tablet styles and not phone styles.\\n//\\n// Alternatively you can override this with JS (see source below), but\\n// we won't be doing that here given our limited scope.\\n//\\n// Source: http://timkadlec.com/2013/01/windows-phone-8-and-device-width/\\n@media screen and (max-width: 400px) {\\n  @-ms-viewport{\\n    width: 320px;\\n  }\\n}\\n\\n// Hide from screenreaders and browsers\\n// Credit: HTML5 Boilerplate\\n.hidden {\\n  display: none !important;\\n  visibility: hidden !important;\\n}\\n\\n// Visibility utilities\\n\\n.visible-xs {\\n  .responsive-invisibility();\\n  @media (max-width: @screen-xs-max) {\\n    .responsive-visibility();\\n  }\\n  &.visible-sm {\\n    @media (min-width: @screen-sm) and (max-width: @screen-sm-max) {\\n      .responsive-visibility();\\n    }\\n  }\\n  &.visible-md {\\n    @media (min-width: @screen-md) and (max-width: @screen-md-max) {\\n      .responsive-visibility();\\n    }    \\n  }\\n  &.visible-lg {\\n    @media (min-width: @screen-lg) {\\n      .responsive-visibility();\\n    }    \\n  }\\n}\\n.visible-sm {\\n  .responsive-invisibility();\\n  &.visible-xs {\\n    @media (max-width: @screen-xs-max) {\\n      .responsive-visibility();\\n    }    \\n  }\\n  @media (min-width: @screen-sm) and (max-width: @screen-sm-max) {\\n    .responsive-visibility();\\n  }\\n  &.visible-md {\\n    @media (min-width: @screen-md) and (max-width: @screen-md-max) {\\n      .responsive-visibility();\\n    }    \\n  }\\n  &.visible-lg {\\n    @media (min-width: @screen-lg) {\\n      .responsive-visibility();\\n    }    \\n  }\\n}\\n.visible-md {\\n  .responsive-invisibility();\\n  &.visible-xs {\\n    @media (max-width: @screen-xs-max) {\\n      .responsive-visibility();\\n    }    \\n  }\\n  &.visible-sm {\\n    @media (min-width: @screen-sm) and (max-width: @screen-sm-max) {\\n      .responsive-visibility();\\n    }\\n  }\\n  @media (min-width: @screen-md) and (max-width: @screen-md-max) {\\n    .responsive-visibility();\\n  }\\n  &.visible-lg {\\n    @media (min-width: @screen-lg) {\\n      .responsive-visibility();\\n    }    \\n  }\\n}\\n.visible-lg {\\n  .responsive-invisibility();\\n  &.visible-xs {\\n    @media (max-width: @screen-xs-max) {\\n      .responsive-visibility();\\n    }    \\n  }\\n  &.visible-sm {\\n    @media (min-width: @screen-sm) and (max-width: @screen-sm-max) {\\n      .responsive-visibility();\\n    }\\n  }\\n  &.visible-md {\\n    @media (min-width: @screen-md) and (max-width: @screen-md-max) {\\n      .responsive-visibility();\\n    }    \\n  }\\n  @media (min-width: @screen-lg) {\\n    .responsive-visibility();\\n  }\\n}\\n\\n.hidden-xs {\\n  .responsive-visibility();\\n  @media (max-width: @screen-xs-max) {\\n    .responsive-invisibility();\\n  }\\n  &.hidden-sm {\\n    @media (min-width: @screen-sm) and (max-width: @screen-sm-max) {\\n      .responsive-invisibility();\\n    }    \\n  }\\n  &.hidden-md {\\n    @media (min-width: @screen-md) and (max-width: @screen-md-max) {\\n      .responsive-invisibility();\\n    }    \\n  }\\n  &.hidden-lg {\\n    @media (min-width: @screen-lg) {\\n      .responsive-invisibility();\\n    }    \\n  }\\n}\\n.hidden-sm {\\n  .responsive-visibility();\\n  &.hidden-xs {\\n    @media (max-width: @screen-xs-max) {\\n      .responsive-invisibility();\\n    }\\n  }\\n  @media (min-width: @screen-sm) and (max-width: @screen-sm-max) {\\n    .responsive-invisibility();\\n  }\\n  &.hidden-md {\\n    @media (min-width: @screen-md) and (max-width: @screen-md-max) {\\n      .responsive-invisibility();\\n    }    \\n  }\\n  &.hidden-lg {\\n    @media (min-width: @screen-lg) {\\n      .responsive-invisibility();\\n    }    \\n  }\\n}\\n.hidden-md {\\n  .responsive-visibility();\\n  &.hidden-xs {\\n    @media (max-width: @screen-xs-max) {\\n      .responsive-invisibility();\\n    }    \\n  }\\n  &.hidden-sm {\\n    @media (min-width: @screen-sm) and (max-width: @screen-sm-max) {\\n      .responsive-invisibility();\\n    }    \\n  }\\n  @media (min-width: @screen-md) and (max-width: @screen-md-max) {\\n    .responsive-invisibility();\\n  }\\n  &.hidden-lg {\\n    @media (min-width: @screen-lg) {\\n      .responsive-invisibility();\\n    }    \\n  }\\n}\\n.hidden-lg {\\n  .responsive-visibility();\\n  &.hidden-xs {\\n    @media (max-width: @screen-xs-max) {\\n      .responsive-invisibility();\\n    }    \\n  }\\n  &.hidden-sm {\\n    @media (min-width: @screen-sm) and (max-width: @screen-sm-max) {\\n      .responsive-invisibility();\\n    }    \\n  }\\n  &.hidden-md {\\n    @media (min-width: @screen-md) and (max-width: @screen-md-max) {\\n      .responsive-invisibility();\\n    }    \\n  }\\n  @media (min-width: @screen-lg) {\\n    .responsive-invisibility();\\n  }\\n}\\n\\n// Print utilities\\n.visible-print {\\n  .responsive-invisibility();\\n}\\n\\n@media print {\\n  .visible-print {\\n    .responsive-visibility();\\n  }\\n  .hidden-print {\\n    .responsive-invisibility();\\n  }\\n}\\n\",\"scaffolding.less\":\"//\\n// Scaffolding\\n// --------------------------------------------------\\n\\n\\n// Reset the box-sizing\\n\\n*,\\n*:before,\\n*:after {\\n  .box-sizing(border-box);\\n}\\n\\n\\n// Body reset\\n\\nhtml {\\n  font-size: 62.5%;\\n  -webkit-tap-highlight-color: rgba(0,0,0,0);\\n}\\n\\nbody {\\n  font-family: @font-family-base;\\n  font-size: @font-size-base;\\n  line-height: @line-height-base;\\n  color: @text-color;\\n  background-color: @body-bg;\\n}\\n\\n// Reset fonts for relevant elements\\ninput,\\nbutton,\\nselect,\\ntextarea {\\n  font-family: inherit;\\n  font-size: inherit;\\n  line-height: inherit;\\n}\\n\\n// Reset unusual Firefox-on-Android default style.\\n//\\n// See https://github.com/necolas/normalize.css/issues/214\\n\\nbutton,\\ninput,\\nselect[multiple],\\ntextarea {\\n  background-image: none;\\n}\\n\\n\\n// Links\\n\\na {\\n  color: @link-color;\\n  text-decoration: none;\\n\\n  &:hover,\\n  &:focus {\\n    color: @link-hover-color;\\n    text-decoration: underline;\\n  }\\n\\n  &:focus {\\n    .tab-focus();\\n  }\\n}\\n\\n\\n// Images\\n\\nimg {\\n  vertical-align: middle;\\n}\\n\\n// Responsive images (ensure images don't scale beyond their parents)\\n.img-responsive {\\n  .img-responsive();\\n}\\n\\n// Rounded corners\\n.img-rounded {\\n  border-radius: @border-radius-large;\\n}\\n\\n// Image thumbnails\\n//\\n// Heads up! This is mixin-ed into thumbnails.less for `.thumbnail`.\\n.img-thumbnail {\\n  padding: @thumbnail-padding;\\n  line-height: @line-height-base;\\n  background-color: @thumbnail-bg;\\n  border: 1px solid @thumbnail-border;\\n  border-radius: @thumbnail-border-radius;\\n  .transition(all .2s ease-in-out);\\n\\n  // Keep them at most 100% wide\\n  .img-responsive(inline-block);\\n}\\n\\n// Perfect circle\\n.img-circle {\\n  border-radius: 50%; // set radius in percents\\n}\\n\\n\\n// Horizontal rules\\n\\nhr {\\n  margin-top:    @line-height-computed;\\n  margin-bottom: @line-height-computed;\\n  border: 0;\\n  border-top: 1px solid @hr-border;\\n}\\n\\n\\n// Only display content to screen readers\\n//\\n// See: http://a11yproject.com/posts/how-to-hide-content/\\n\\n.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\",\"tables.less\":\"//\\n// Tables\\n// --------------------------------------------------\\n\\n\\ntable {\\n  max-width: 100%;\\n  background-color: @table-bg;\\n}\\nth {\\n  text-align: left;\\n}\\n\\n\\n// Baseline styles\\n\\n.table {\\n  width: 100%;\\n  margin-bottom: @line-height-computed;\\n  // Cells\\n  thead,\\n  tbody,\\n  tfoot {\\n    > tr {\\n      > th,\\n      > td {\\n        padding: @table-cell-padding;\\n        line-height: @line-height-base;\\n        vertical-align: top;\\n        border-top: 1px solid @table-border-color;\\n      }\\n    }\\n  }\\n  // Bottom align for column headings\\n  thead > tr > th {\\n    vertical-align: bottom;\\n    border-bottom: 2px solid @table-border-color;\\n  }\\n  // Remove top border from thead by default\\n  caption + thead,\\n  colgroup + thead,\\n  thead:first-child {\\n    tr:first-child {\\n      th, td {\\n        border-top: 0;\\n      }\\n    }\\n  }\\n  // Account for multiple tbody instances\\n  tbody + tbody {\\n    border-top: 2px solid @table-border-color;\\n  }\\n\\n  // Nesting\\n  .table {\\n    background-color: @body-bg;\\n  }\\n}\\n\\n\\n// Condensed table w/ half padding\\n\\n.table-condensed {\\n  thead,\\n  tbody,\\n  tfoot {\\n    > tr {\\n      > th,\\n      > td {\\n        padding: @table-condensed-cell-padding;\\n      }\\n    }\\n  }\\n}\\n\\n\\n// Bordered version\\n//\\n// Add borders all around the table and between all the columns.\\n\\n.table-bordered {\\n  border: 1px solid @table-border-color;\\n  > thead,\\n  > tbody,\\n  > tfoot {\\n    > tr {\\n      > th,\\n      > td {\\n        border: 1px solid @table-border-color;\\n      }\\n    }\\n  }\\n  > thead {\\n    > tr {\\n      > th,\\n      > td {\\n        border-bottom-width: 2px;\\n      }\\n    }\\n  }\\n}\\n\\n\\n// Zebra-striping\\n//\\n// Default zebra-stripe styles (alternating gray and transparent backgrounds)\\n\\n.table-striped {\\n  > tbody {\\n    > tr:nth-child(odd) {\\n      > td,\\n      > th {\\n        background-color: @table-bg-accent;\\n      }\\n    }\\n  }\\n}\\n\\n\\n// Hover effect\\n//\\n// Placed here since it has to come after the potential zebra striping\\n\\n.table-hover {\\n  > tbody {\\n    > tr:hover {\\n      > td,\\n      > th {\\n        background-color: @table-bg-hover;\\n      }\\n    }\\n  }\\n}\\n\\n\\n// Table cell sizing\\n//\\n// Reset default table behavior\\n\\ntable col[class*=\\\"col-\\\"] {\\n  float: none;\\n  display: table-column;\\n}\\ntable {\\n  td,\\n  th {\\n    &[class*=\\\"col-\\\"] {\\n      float: none;\\n      display: table-cell;\\n    }\\n  }\\n}\\n\\n\\n// Table backgrounds\\n//\\n// Exact selectors below required to override `.table-striped` and prevent\\n// inheritance to nested tables.\\n\\n.table > thead > tr,\\n.table > tbody > tr,\\n.table > tfoot > tr {\\n  > td.active,\\n  > th.active,\\n  &.active > td,\\n  &.active > th  {\\n    background-color: @table-bg-active;\\n  }\\n}\\n\\n// Generate the contextual variants\\n.table-row-variant(success; @state-success-bg; @state-success-border);\\n.table-row-variant(danger; @state-danger-bg; @state-danger-border);\\n.table-row-variant(warning; @state-warning-bg; @state-warning-border);\\n\\n\\n// Responsive tables\\n//\\n// Wrap your tables in `.table-scrollable` and we'll make them mobile friendly\\n// by enabling horizontal scrolling. Only applies <768px. Everything above that\\n// will display normally.\\n\\n@media (max-width: @screen-sm) {\\n  .table-responsive {\\n    width: 100%;\\n    margin-bottom: 15px;\\n    overflow-y: hidden;\\n    overflow-x: scroll;\\n    border: 1px solid @table-border-color;\\n\\n    // Tighten up spacing and give a background color\\n    > .table {\\n      margin-bottom: 0;\\n      background-color: #fff;\\n\\n      // Ensure the content doesn't wrap\\n      > thead,\\n      > tbody,\\n      > tfoot {\\n        > tr {\\n          > th,\\n          > td {\\n            white-space: nowrap;\\n          }\\n        }\\n      }\\n    }\\n\\n    // Special overrides for the bordered tables\\n    > .table-bordered {\\n      border: 0;\\n\\n      // Nuke the appropriate borders so that the parent can handle them\\n      > thead,\\n      > tbody,\\n      > tfoot {\\n        > tr {\\n          > th:first-child,\\n          > td:first-child {\\n            border-left: 0;\\n          }\\n          > th:last-child,\\n          > td:last-child {\\n            border-right: 0;\\n          }\\n        }\\n        > tr:last-child {\\n          > th,\\n          > td {\\n            border-bottom: 0;\\n          }\\n        }\\n      }\\n    }\\n  }\\n}\\n\",\"theme.less\":\"\\n//\\n// Load core variables and mixins\\n// --------------------------------------------------\\n\\n@import \\\"variables.less\\\";\\n@import \\\"mixins.less\\\";\\n\\n\\n\\n//\\n// Buttons\\n// --------------------------------------------------\\n\\n// Common styles\\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  @shadow: inset 0 1px 0 rgba(255,255,255,.15), 0 1px 1px rgba(0,0,0,.075);\\n  .box-shadow(@shadow);\\n\\n  // Reset the shadow\\n  &:active,\\n  &.active {\\n    .box-shadow(inset 0 3px 5px rgba(0,0,0,.125));\\n  }\\n}\\n\\n// Mixin for generating new styles\\n.btn-styles(@btn-color: #555;) {\\n  #gradient > .vertical(@start-color: @btn-color; @end-color: darken(@btn-color, 10%));\\n  border-color: darken(@btn-color, 12%);\\n\\n  &:active,\\n  &.active {\\n    background-color: darken(@btn-color, 10%);\\n    border-color: darken(@btn-color, 12%);\\n  }\\n}\\n\\n// Common styles\\n.btn {\\n  // Remove the gradient for the pressed/active state\\n  &:active,\\n  &.active {\\n    background-image: none;\\n  }\\n}\\n\\n// Apply the mixin to the buttons\\n.btn-default { .btn-styles(@btn-default-bg;); text-shadow: 0 1px 0 #fff; border-color: #ccc; }\\n.btn-primary { .btn-styles(@btn-primary-bg); }\\n.btn-success { .btn-styles(@btn-success-bg); }\\n.btn-warning { .btn-styles(@btn-warning-bg); }\\n.btn-danger  { .btn-styles(@btn-danger-bg); }\\n.btn-info    { .btn-styles(@btn-info-bg); }\\n\\n\\n\\n//\\n// Images\\n// --------------------------------------------------\\n\\n.thumbnail,\\n.img-thumbnail {\\n  .box-shadow(0 1px 2px rgba(0,0,0,.075));\\n}\\n\\n\\n\\n//\\n// Dropdowns\\n// --------------------------------------------------\\n\\n.dropdown-menu > li > a:hover,\\n.dropdown-menu > li > a:focus,\\n.dropdown-menu > .active > a,\\n.dropdown-menu > .active > a:hover,\\n.dropdown-menu > .active > a:focus {\\n  #gradient > .vertical(@start-color: @dropdown-link-hover-bg; @end-color: darken(@dropdown-link-hover-bg, 5%));\\n  background-color: darken(@dropdown-link-hover-bg, 5%);\\n}\\n\\n\\n\\n//\\n// Navbar\\n// --------------------------------------------------\\n\\n// Basic navbar\\n.navbar {\\n  #gradient > .vertical(@start-color: lighten(@navbar-default-bg, 10%); @end-color: @navbar-default-bg;);\\n  border-radius: @navbar-border-radius;\\n  @shadow: inset 0 1px 0 rgba(255,255,255,.15), 0 1px 5px rgba(0,0,0,.075);\\n  .box-shadow(@shadow);\\n\\n  .navbar-nav > .active > a {\\n    background-color: @navbar-default-bg;\\n  }\\n}\\n.navbar-brand,\\n.navbar-nav > li > a {\\n  text-shadow: 0 1px 0 rgba(255,255,255,.25);\\n}\\n\\n// Inverted navbar\\n.navbar-inverse {\\n  #gradient > .vertical(@start-color: lighten(@navbar-inverse-bg, 10%); @end-color: @navbar-inverse-bg;);\\n\\n  .navbar-nav > .active > a {\\n    background-color: @navbar-inverse-bg;\\n  }\\n\\n  .navbar-brand,\\n  .navbar-nav > li > a {\\n    text-shadow: 0 -1px 0 rgba(0,0,0,.25);\\n  }\\n}\\n\\n// Undo rounded corners in static and fixed navbars\\n.navbar-static-top,\\n.navbar-fixed-top,\\n.navbar-fixed-bottom {\\n  border-radius: 0;\\n}\\n\\n\\n\\n//\\n// Alerts\\n// --------------------------------------------------\\n\\n// Common styles\\n.alert {\\n  text-shadow: 0 1px 0 rgba(255,255,255,.2);\\n  @shadow: inset 0 1px 0 rgba(255,255,255,.25), 0 1px 2px rgba(0,0,0,.05);\\n  .box-shadow(@shadow);\\n}\\n\\n// Mixin for generating new styles\\n.alert-styles(@color) {\\n  #gradient > .vertical(@start-color: @color; @end-color: darken(@color, 7.5%));\\n  border-color: darken(@color, 15%);\\n}\\n\\n// Apply the mixin to the alerts\\n.alert-success    { .alert-styles(@alert-success-bg); }\\n.alert-info       { .alert-styles(@alert-info-bg); }\\n.alert-warning    { .alert-styles(@alert-warning-bg); }\\n.alert-danger     { .alert-styles(@alert-danger-bg); }\\n\\n\\n\\n//\\n// Progress bars\\n// --------------------------------------------------\\n\\n// Give the progress background some depth\\n.progress {\\n  #gradient > .vertical(@start-color: darken(@progress-bg, 4%); @end-color: @progress-bg;)\\n}\\n\\n// Mixin for generating new styles\\n.progress-bar-styles(@color) {\\n  #gradient > .vertical(@start-color: @color; @end-color: darken(@color, 10%));\\n}\\n\\n// Apply the mixin to the progress bars\\n.progress-bar            { .progress-bar-styles(@progress-bar-bg); }\\n.progress-bar-success    { .progress-bar-styles(@progress-bar-success-bg); }\\n.progress-bar-info       { .progress-bar-styles(@progress-bar-info-bg); }\\n.progress-bar-warning    { .progress-bar-styles(@progress-bar-warning-bg); }\\n.progress-bar-danger     { .progress-bar-styles(@progress-bar-danger-bg); }\\n\\n\\n\\n//\\n// List groups\\n// --------------------------------------------------\\n\\n.list-group {\\n  border-radius: @border-radius-base;\\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 darken(@list-group-active-bg, 10%);\\n  #gradient > .vertical(@start-color: @list-group-active-bg; @end-color: darken(@list-group-active-bg, 7.5%));\\n  border-color: darken(@list-group-active-border, 7.5%);\\n}\\n\\n\\n\\n//\\n// Panels\\n// --------------------------------------------------\\n\\n// Common styles\\n.panel {\\n  .box-shadow(0 1px 2px rgba(0,0,0,.05));\\n}\\n\\n// Mixin for generating new styles\\n.panel-heading-styles(@color) {\\n  #gradient > .vertical(@start-color: @color; @end-color: darken(@color, 5%));\\n}\\n\\n// Apply the mixin to the panel headings only\\n.panel-default > .panel-heading   { .panel-heading-styles(@panel-default-heading-bg); }\\n.panel-primary > .panel-heading   { .panel-heading-styles(@panel-primary-heading-bg); }\\n.panel-success > .panel-heading   { .panel-heading-styles(@panel-success-heading-bg); }\\n.panel-info > .panel-heading      { .panel-heading-styles(@panel-info-heading-bg); }\\n.panel-warning > .panel-heading   { .panel-heading-styles(@panel-warning-heading-bg); }\\n.panel-danger > .panel-heading    { .panel-heading-styles(@panel-danger-heading-bg); }\\n\\n\\n\\n//\\n// Wells\\n// --------------------------------------------------\\n\\n.well {\\n  #gradient > .vertical(@start-color: darken(@well-bg, 5%); @end-color: @well-bg;);\\n  border-color: darken(@well-bg, 10%);\\n  @shadow: inset 0 1px 3px rgba(0,0,0,.05), 0 1px 0 rgba(255,255,255,.1);\\n  .box-shadow(@shadow);\\n}\\n\",\"thumbnails.less\":\"//\\n// Thumbnails\\n// --------------------------------------------------\\n\\n\\n// Mixin and adjust the regular image class\\n.thumbnail {\\n  .img-thumbnail();\\n  display: block; // Override the inline-block from `.img-thumbnail`\\n\\n  > img {\\n    .img-responsive();\\n  }\\n}\\n\\n\\n// Add a hover state for linked versions only\\na.thumbnail:hover,\\na.thumbnail:focus {\\n  border-color: @link-color;\\n}\\n\\n// Images and captions\\n.thumbnail > img {\\n  margin-left: auto;\\n  margin-right: auto;\\n}\\n.thumbnail .caption {\\n  padding: @thumbnail-caption-padding;\\n  color: @thumbnail-caption-color;\\n}\\n\",\"tooltip.less\":\"//\\n// Tooltips\\n// --------------------------------------------------\\n\\n\\n// Base class\\n.tooltip {\\n  position: absolute;\\n  z-index: @zindex-tooltip;\\n  display: block;\\n  visibility: visible;\\n  font-size: @font-size-small;\\n  line-height: 1.4;\\n  .opacity(0);\\n\\n  &.in     { .opacity(.9); }\\n  &.top    { margin-top:  -3px; padding: 5px 0; }\\n  &.right  { margin-left:  3px; padding: 0 5px; }\\n  &.bottom { margin-top:   3px; padding: 5px 0; }\\n  &.left   { margin-left: -3px; padding: 0 5px; }\\n}\\n\\n// Wrapper for the tooltip content\\n.tooltip-inner {\\n  max-width: @tooltip-max-width;\\n  padding: 3px 8px;\\n  color: @tooltip-color;\\n  text-align: center;\\n  text-decoration: none;\\n  background-color: @tooltip-bg;\\n  border-radius: @border-radius-base;\\n}\\n\\n// Arrows\\n.tooltip-arrow {\\n  position: absolute;\\n  width: 0;\\n  height: 0;\\n  border-color: transparent;\\n  border-style: solid;\\n}\\n.tooltip {\\n  &.top .tooltip-arrow {\\n    bottom: 0;\\n    left: 50%;\\n    margin-left: -@tooltip-arrow-width;\\n    border-width: @tooltip-arrow-width @tooltip-arrow-width 0;\\n    border-top-color: @tooltip-arrow-color;\\n  }\\n  &.top-left .tooltip-arrow {\\n    bottom: 0;\\n    left: 5px;\\n    border-width: @tooltip-arrow-width @tooltip-arrow-width 0;\\n    border-top-color: @tooltip-arrow-color;\\n  }\\n  &.top-right .tooltip-arrow {\\n    bottom: 0;\\n    right: 5px;\\n    border-width: @tooltip-arrow-width @tooltip-arrow-width 0;\\n    border-top-color: @tooltip-arrow-color;\\n  }\\n  &.right .tooltip-arrow {\\n    top: 50%;\\n    left: 0;\\n    margin-top: -@tooltip-arrow-width;\\n    border-width: @tooltip-arrow-width @tooltip-arrow-width @tooltip-arrow-width 0;\\n    border-right-color: @tooltip-arrow-color;\\n  }\\n  &.left .tooltip-arrow {\\n    top: 50%;\\n    right: 0;\\n    margin-top: -@tooltip-arrow-width;\\n    border-width: @tooltip-arrow-width 0 @tooltip-arrow-width @tooltip-arrow-width;\\n    border-left-color: @tooltip-arrow-color;\\n  }\\n  &.bottom .tooltip-arrow {\\n    top: 0;\\n    left: 50%;\\n    margin-left: -@tooltip-arrow-width;\\n    border-width: 0 @tooltip-arrow-width @tooltip-arrow-width;\\n    border-bottom-color: @tooltip-arrow-color;\\n  }\\n  &.bottom-left .tooltip-arrow {\\n    top: 0;\\n    left: 5px;\\n    border-width: 0 @tooltip-arrow-width @tooltip-arrow-width;\\n    border-bottom-color: @tooltip-arrow-color;\\n  }\\n  &.bottom-right .tooltip-arrow {\\n    top: 0;\\n    right: 5px;\\n    border-width: 0 @tooltip-arrow-width @tooltip-arrow-width;\\n    border-bottom-color: @tooltip-arrow-color;\\n  }\\n}\\n\",\"type.less\":\"//\\n// Typography\\n// --------------------------------------------------\\n\\n\\n// Body text\\n// -------------------------\\n\\np {\\n  margin: 0 0 (@line-height-computed / 2);\\n}\\n.lead {\\n  margin-bottom: @line-height-computed;\\n  font-size: (@font-size-base * 1.15);\\n  font-weight: 200;\\n  line-height: 1.4;\\n\\n  @media (min-width: 768px) {\\n    font-size: (@font-size-base * 1.5);\\n  }\\n}\\n\\n\\n// Emphasis & misc\\n// -------------------------\\n\\n// Ex: 14px base font * 85% = about 12px\\nsmall   { font-size: 85%; }\\n\\n// Undo browser default styling\\ncite    { font-style: normal; }\\n\\n// Contextual emphasis\\n.text-muted          { color: @text-muted; }\\n.text-primary        { color: @brand-primary; }\\n.text-warning        { color: @state-warning-text; }\\n.text-danger         { color: @state-danger-text; }\\n.text-success        { color: @state-success-text; }\\n.text-info           { color: @state-info-text; }\\n\\n// Alignment\\n.text-left           { text-align: left; }\\n.text-right          { text-align: right; }\\n.text-center         { text-align: center; }\\n\\n\\n// Headings\\n// -------------------------\\n\\nh1, h2, h3, h4, h5, h6,\\n.h1, .h2, .h3, .h4, .h5, .h6 {\\n  font-family: @headings-font-family;\\n  font-weight: @headings-font-weight;\\n  line-height: @headings-line-height;\\n  small {\\n    font-weight: normal;\\n    line-height: 1;\\n    color: @headings-small-color;\\n  }\\n}\\n\\nh1,\\nh2,\\nh3 {\\n  margin-top: @line-height-computed;\\n  margin-bottom: (@line-height-computed / 2);\\n}\\nh4,\\nh5,\\nh6 {\\n  margin-top: (@line-height-computed / 2);\\n  margin-bottom: (@line-height-computed / 2);\\n}\\n\\nh1, .h1 { font-size: floor(@font-size-base * 2.60); } // ~36px\\nh2, .h2 { font-size: floor(@font-size-base * 2.15); } // ~30px\\nh3, .h3 { font-size: ceil(@font-size-base * 1.70); } // ~24px\\nh4, .h4 { font-size: ceil(@font-size-base * 1.25); } // ~18px\\nh5, .h5 { font-size:  @font-size-base; }\\nh6, .h6 { font-size: ceil(@font-size-base * 0.85); } // ~12px\\n\\nh1 small, .h1 small { font-size: ceil(@font-size-base * 1.70); } // ~24px\\nh2 small, .h2 small { font-size: ceil(@font-size-base * 1.25); } // ~18px\\nh3 small, .h3 small,\\nh4 small, .h4 small { font-size: @font-size-base; }\\n\\n\\n// Page header\\n// -------------------------\\n\\n.page-header {\\n  padding-bottom: ((@line-height-computed / 2) - 1);\\n  margin: (@line-height-computed * 2) 0 @line-height-computed;\\n  border-bottom: 1px solid @page-header-border-color;\\n}\\n\\n\\n\\n// Lists\\n// --------------------------------------------------\\n\\n// Unordered and Ordered lists\\nul,\\nol {\\n  margin-top: 0;\\n  margin-bottom: (@line-height-computed / 2);\\n  ul,\\n  ol{\\n    margin-bottom: 0;\\n  }\\n}\\n\\n// List options\\n\\n// Unstyled keeps list items block level, just removes default browser padding and list-style\\n.list-unstyled {\\n  padding-left: 0;\\n  list-style: none;\\n}\\n// Inline turns list items into inline-block\\n.list-inline {\\n  .list-unstyled();\\n  > li {\\n    display: inline-block;\\n    padding-left: 5px;\\n    padding-right: 5px;\\n  }\\n}\\n\\n// Description Lists\\ndl {\\n  margin-bottom: @line-height-computed;\\n}\\ndt,\\ndd {\\n  line-height: @line-height-base;\\n}\\ndt {\\n  font-weight: bold;\\n}\\ndd {\\n  margin-left: 0; // Undo browser default\\n}\\n\\n// Horizontal description lists\\n//\\n// Defaults to being stacked without any of the below styles applied, until the\\n// grid breakpoint is reached (default of ~768px).\\n\\n@media (min-width: @grid-float-breakpoint) {\\n  .dl-horizontal {\\n    dt {\\n      float: left;\\n      width: (@component-offset-horizontal - 20);\\n      clear: left;\\n      text-align: right;\\n      .text-overflow();\\n    }\\n    dd {\\n      margin-left: @component-offset-horizontal;\\n      .clearfix(); // Clear the floated `dt` if an empty `dd` is present\\n    }\\n  }\\n}\\n\\n// MISC\\n// ----\\n\\n// Abbreviations and acronyms\\nabbr[title],\\n// Added data-* attribute to help out our tooltip plugin, per https://github.com/twbs/bootstrap/issues/5257\\nabbr[data-original-title] {\\n  cursor: help;\\n  border-bottom: 1px dotted @abbr-border-color;\\n}\\nabbr.initialism {\\n  font-size: 90%;\\n  text-transform: uppercase;\\n}\\n\\n// Blockquotes\\nblockquote {\\n  padding: (@line-height-computed / 2) @line-height-computed;\\n  margin: 0 0 @line-height-computed;\\n  border-left: 5px solid @blockquote-border-color;\\n  p {\\n    font-size: (@font-size-base * 1.25);\\n    font-weight: 300;\\n    line-height: 1.25;\\n  }\\n  p:last-child {\\n    margin-bottom: 0;\\n  }\\n  small {\\n    display: block;\\n    line-height: @line-height-base;\\n    color: @blockquote-small-color;\\n    &:before {\\n      content: '\\\\2014 \\\\00A0';// EM DASH, NBSP\\n    }\\n  }\\n\\n  // Float right with text-align: right\\n  &.pull-right {\\n    padding-right: 15px;\\n    padding-left: 0;\\n    border-right: 5px solid @blockquote-border-color;\\n    border-left: 0;\\n    p,\\n    small {\\n      text-align: right;\\n    }\\n    small {\\n      &:before {\\n        content: '';\\n      }\\n      &:after {\\n        content: '\\\\00A0 \\\\2014';// NBSP, EM DASH\\n      }\\n    }\\n  }\\n}\\n\\n// Quotes\\nq:before,\\nq:after,\\nblockquote:before,\\nblockquote:after {\\n  content: \\\"\\\";\\n}\\n\\n// Addresses\\naddress {\\n  display: block;\\n  margin-bottom: @line-height-computed;\\n  font-style: normal;\\n  line-height: @line-height-base;\\n}\\n\",\"utilities.less\":\"//\\n// Utility classes\\n// --------------------------------------------------\\n\\n\\n// Floats\\n// -------------------------\\n\\n.clearfix {\\n  .clearfix();\\n}\\n.pull-right {\\n  float: right !important;\\n}\\n.pull-left {\\n  float: left !important;\\n}\\n\\n\\n// Toggling content\\n// -------------------------\\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  .hide-text();\\n}\\n\\n\\n// For Affix plugin\\n// -------------------------\\n\\n.affix {\\n  position: fixed;\\n}\\n\",\"variables.less\":\"//\\n// Variables\\n// --------------------------------------------------\\n\\n\\n// Global values\\n// --------------------------------------------------\\n\\n// Grays\\n// -------------------------\\n\\n@gray-darker:            lighten(#000, 13.5%); // #222\\n@gray-dark:              lighten(#000, 20%);   // #333\\n@gray:                   lighten(#000, 33.5%); // #555\\n@gray-light:             lighten(#000, 60%);   // #999\\n@gray-lighter:           lighten(#000, 93.5%); // #eee\\n\\n// Brand colors\\n// -------------------------\\n\\n@brand-primary:         #428bca;\\n@brand-success:         #5cb85c;\\n@brand-warning:         #f0ad4e;\\n@brand-danger:          #d9534f;\\n@brand-info:            #5bc0de;\\n\\n// Scaffolding\\n// -------------------------\\n\\n@body-bg:               #fff;\\n@text-color:            @gray-dark;\\n\\n// Links\\n// -------------------------\\n\\n@link-color:            @brand-primary;\\n@link-hover-color:      darken(@link-color, 15%);\\n\\n// Typography\\n// -------------------------\\n\\n@font-family-sans-serif:  \\\"Helvetica Neue\\\", Helvetica, Arial, sans-serif;\\n@font-family-serif:       Georgia, \\\"Times New Roman\\\", Times, serif;\\n@font-family-monospace:   Monaco, Menlo, Consolas, \\\"Courier New\\\", monospace;\\n@font-family-base:        @font-family-sans-serif;\\n\\n@font-size-base:          14px;\\n@font-size-large:         ceil(@font-size-base * 1.25); // ~18px\\n@font-size-small:         ceil(@font-size-base * 0.85); // ~12px\\n\\n@line-height-base:        1.428571429; // 20/14\\n@line-height-computed:    floor(@font-size-base * @line-height-base); // ~20px\\n\\n@headings-font-family:    @font-family-base;\\n@headings-font-weight:    500;\\n@headings-line-height:    1.1;\\n\\n// Iconography\\n// -------------------------\\n\\n@icon-font-path:          \\\"../fonts/\\\";\\n@icon-font-name:          \\\"glyphicons-halflings-regular\\\";\\n\\n\\n// Components\\n// -------------------------\\n// Based on 14px font-size and 1.428 line-height (~20px to start)\\n\\n@padding-base-vertical:          6px;\\n@padding-base-horizontal:        12px;\\n\\n@padding-large-vertical:         10px;\\n@padding-large-horizontal:       16px;\\n\\n@padding-small-vertical:         5px;\\n@padding-small-horizontal:       10px;\\n\\n@line-height-large:              1.33;\\n@line-height-small:              1.5;\\n\\n@border-radius-base:             4px;\\n@border-radius-large:            6px;\\n@border-radius-small:            3px;\\n\\n@component-active-bg:            @brand-primary;\\n\\n@caret-width-base:               4px;\\n@caret-width-large:              5px;\\n\\n// Tables\\n// -------------------------\\n\\n@table-cell-padding:                 8px;\\n@table-condensed-cell-padding:       5px;\\n\\n@table-bg:                           transparent; // overall background-color\\n@table-bg-accent:                    #f9f9f9; // for striping\\n@table-bg-hover:                     #f5f5f5;\\n@table-bg-active:                    @table-bg-hover;\\n\\n@table-border-color:                 #ddd; // table and cell border\\n\\n\\n// Buttons\\n// -------------------------\\n\\n@btn-font-weight:                normal;\\n\\n@btn-default-color:              #333;\\n@btn-default-bg:                 #fff;\\n@btn-default-border:             #ccc;\\n\\n@btn-primary-color:              #fff;\\n@btn-primary-bg:                 @brand-primary;\\n@btn-primary-border:             darken(@btn-primary-bg, 5%);\\n\\n@btn-success-color:              #fff;\\n@btn-success-bg:                 @brand-success;\\n@btn-success-border:             darken(@btn-success-bg, 5%);\\n\\n@btn-warning-color:              #fff;\\n@btn-warning-bg:                 @brand-warning;\\n@btn-warning-border:             darken(@btn-warning-bg, 5%);\\n\\n@btn-danger-color:               #fff;\\n@btn-danger-bg:                  @brand-danger;\\n@btn-danger-border:              darken(@btn-danger-bg, 5%);\\n\\n@btn-info-color:                 #fff;\\n@btn-info-bg:                    @brand-info;\\n@btn-info-border:                darken(@btn-info-bg, 5%);\\n\\n@btn-link-disabled-color:        @gray-light;\\n\\n\\n// Forms\\n// -------------------------\\n\\n@input-bg:                       #fff;\\n@input-bg-disabled:              @gray-lighter;\\n\\n@input-color:                    @gray;\\n@input-border:                   #ccc;\\n@input-border-radius:            @border-radius-base;\\n@input-border-focus:             #66afe9;\\n\\n@input-color-placeholder:        @gray-light;\\n\\n@input-height-base:              (@line-height-computed + (@padding-base-vertical * 2) + 2);\\n@input-height-large:             (floor(@font-size-large * @line-height-large) + (@padding-large-vertical * 2) + 2);\\n@input-height-small:             (floor(@font-size-small * @line-height-small) + (@padding-small-vertical * 2) + 2);\\n\\n@legend-color:                   @gray-dark;\\n@legend-border-color:            #e5e5e5;\\n\\n@input-group-addon-bg:           @gray-lighter;\\n@input-group-addon-border-color: @input-border;\\n\\n\\n// Dropdowns\\n// -------------------------\\n\\n@dropdown-bg:                    #fff;\\n@dropdown-border:                rgba(0,0,0,.15);\\n@dropdown-fallback-border:       #ccc;\\n@dropdown-divider-bg:            #e5e5e5;\\n\\n@dropdown-link-active-color:     #fff;\\n@dropdown-link-active-bg:        @component-active-bg;\\n\\n@dropdown-link-color:            @gray-dark;\\n@dropdown-link-hover-color:      #fff;\\n@dropdown-link-hover-bg:         @dropdown-link-active-bg;\\n\\n@dropdown-link-disabled-color:   @gray-light;\\n\\n@dropdown-header-color:          @gray-light;\\n\\n@dropdown-caret-color:           #000;\\n\\n\\n// COMPONENT VARIABLES\\n// --------------------------------------------------\\n\\n\\n// Z-index master list\\n// -------------------------\\n// Used for a bird's eye view of components dependent on the z-axis\\n// Try to avoid customizing these :)\\n\\n@zindex-navbar:            1000;\\n@zindex-dropdown:          1000;\\n@zindex-popover:           1010;\\n@zindex-tooltip:           1030;\\n@zindex-navbar-fixed:      1030;\\n@zindex-modal-background:  1040;\\n@zindex-modal:             1050;\\n\\n// Media queries breakpoints\\n// --------------------------------------------------\\n\\n// Extra small screen / phone\\n@screen-xs:                  480px;\\n@screen-phone:               @screen-xs;\\n\\n// Small screen / tablet\\n@screen-sm:                  768px;\\n@screen-tablet:              @screen-sm;\\n\\n// Medium screen / desktop\\n@screen-md:                  992px;\\n@screen-desktop:             @screen-md;\\n\\n// Large screen / wide desktop\\n@screen-lg:                  1200px;\\n@screen-lg-desktop:          @screen-lg;\\n\\n// So media queries don't overlap when required, provide a maximum\\n@screen-xs-max:              (@screen-sm - 1);\\n@screen-sm-max:              (@screen-md - 1);\\n@screen-md-max:              (@screen-lg - 1);\\n\\n\\n// Grid system\\n// --------------------------------------------------\\n\\n// Number of columns in the grid system\\n@grid-columns:              12;\\n// Padding, to be divided by two and applied to the left and right of all columns\\n@grid-gutter-width:         30px;\\n// Point at which the navbar stops collapsing\\n@grid-float-breakpoint:     @screen-tablet;\\n\\n\\n// Navbar\\n// -------------------------\\n\\n// Basics of a navbar\\n@navbar-height:                    50px;\\n@navbar-margin-bottom:             @line-height-computed;\\n@navbar-default-color:             #777;\\n@navbar-default-bg:                #f8f8f8;\\n@navbar-default-border:            darken(@navbar-default-bg, 6.5%);\\n@navbar-border-radius:             @border-radius-base;\\n@navbar-padding-horizontal:        floor(@grid-gutter-width / 2);\\n@navbar-padding-vertical:          ((@navbar-height - @line-height-computed) / 2);\\n\\n// Navbar links\\n@navbar-default-link-color:                #777;\\n@navbar-default-link-hover-color:          #333;\\n@navbar-default-link-hover-bg:             transparent;\\n@navbar-default-link-active-color:         #555;\\n@navbar-default-link-active-bg:            darken(@navbar-default-bg, 6.5%);\\n@navbar-default-link-disabled-color:       #ccc;\\n@navbar-default-link-disabled-bg:          transparent;\\n\\n// Navbar brand label\\n@navbar-default-brand-color:               @navbar-default-link-color;\\n@navbar-default-brand-hover-color:         darken(@navbar-default-link-color, 10%);\\n@navbar-default-brand-hover-bg:            transparent;\\n\\n// Navbar toggle\\n@navbar-default-toggle-hover-bg:           #ddd;\\n@navbar-default-toggle-icon-bar-bg:        #ccc;\\n@navbar-default-toggle-border-color:       #ddd;\\n\\n\\n// Inverted navbar\\n//\\n// Reset inverted navbar basics\\n@navbar-inverse-color:                      @gray-light;\\n@navbar-inverse-bg:                         #222;\\n@navbar-inverse-border:                     darken(@navbar-inverse-bg, 10%);\\n\\n// Inverted navbar links\\n@navbar-inverse-link-color:                 @gray-light;\\n@navbar-inverse-link-hover-color:           #fff;\\n@navbar-inverse-link-hover-bg:              transparent;\\n@navbar-inverse-link-active-color:          @navbar-inverse-link-hover-color;\\n@navbar-inverse-link-active-bg:             darken(@navbar-inverse-bg, 10%);\\n@navbar-inverse-link-disabled-color:        #444;\\n@navbar-inverse-link-disabled-bg:           transparent;\\n\\n// Inverted navbar brand label\\n@navbar-inverse-brand-color:                @navbar-inverse-link-color;\\n@navbar-inverse-brand-hover-color:          #fff;\\n@navbar-inverse-brand-hover-bg:             transparent;\\n\\n// Inverted navbar search\\n// Normal navbar needs no special styles or vars\\n@navbar-inverse-search-bg:                  lighten(@navbar-inverse-bg, 25%);\\n@navbar-inverse-search-bg-focus:            #fff;\\n@navbar-inverse-search-border:              @navbar-inverse-bg;\\n@navbar-inverse-search-placeholder-color:   #ccc;\\n\\n// Inverted navbar toggle\\n@navbar-inverse-toggle-hover-bg:            #333;\\n@navbar-inverse-toggle-icon-bar-bg:         #fff;\\n@navbar-inverse-toggle-border-color:        #333;\\n\\n\\n// Navs\\n// -------------------------\\n\\n@nav-link-padding:                          10px 15px;\\n@nav-link-hover-bg:                         @gray-lighter;\\n\\n@nav-disabled-link-color:                   @gray-light;\\n@nav-disabled-link-hover-color:             @gray-light;\\n\\n@nav-open-link-hover-color:                 #fff;\\n@nav-open-caret-border-color:               #fff;\\n\\n// Tabs\\n@nav-tabs-border-color:                     #ddd;\\n\\n@nav-tabs-link-hover-border-color:          @gray-lighter;\\n\\n@nav-tabs-active-link-hover-bg:             @body-bg;\\n@nav-tabs-active-link-hover-color:          @gray;\\n@nav-tabs-active-link-hover-border-color:   #ddd;\\n\\n@nav-tabs-justified-link-border-color:            #ddd;\\n@nav-tabs-justified-active-link-border-color:     @body-bg;\\n\\n// Pills\\n@nav-pills-active-link-hover-bg:            @component-active-bg;\\n@nav-pills-active-link-hover-color:         #fff;\\n\\n\\n// Pagination\\n// -------------------------\\n\\n@pagination-bg:                        #fff;\\n@pagination-border:                    #ddd;\\n\\n@pagination-hover-bg:                  @gray-lighter;\\n\\n@pagination-active-bg:                 @brand-primary;\\n@pagination-active-color:              #fff;\\n\\n@pagination-disabled-color:            @gray-light;\\n\\n\\n// Pager\\n// -------------------------\\n\\n@pager-border-radius:                  15px;\\n@pager-disabled-color:                 @gray-light;\\n\\n\\n// Jumbotron\\n// -------------------------\\n\\n@jumbotron-padding:              30px;\\n@jumbotron-color:                inherit;\\n@jumbotron-bg:                   @gray-lighter;\\n\\n@jumbotron-heading-color:        inherit;\\n\\n\\n// Form states and alerts\\n// -------------------------\\n\\n@state-warning-text:             #c09853;\\n@state-warning-bg:               #fcf8e3;\\n@state-warning-border:           darken(spin(@state-warning-bg, -10), 3%);\\n\\n@state-danger-text:              #b94a48;\\n@state-danger-bg:                #f2dede;\\n@state-danger-border:            darken(spin(@state-danger-bg, -10), 3%);\\n\\n@state-success-text:             #468847;\\n@state-success-bg:               #dff0d8;\\n@state-success-border:           darken(spin(@state-success-bg, -10), 5%);\\n\\n@state-info-text:                #3a87ad;\\n@state-info-bg:                  #d9edf7;\\n@state-info-border:              darken(spin(@state-info-bg, -10), 7%);\\n\\n\\n// Tooltips\\n// -------------------------\\n@tooltip-max-width:           200px;\\n@tooltip-color:               #fff;\\n@tooltip-bg:                  #000;\\n\\n@tooltip-arrow-width:         5px;\\n@tooltip-arrow-color:         @tooltip-bg;\\n\\n\\n// Popovers\\n// -------------------------\\n@popover-bg:                          #fff;\\n@popover-max-width:                   276px;\\n@popover-border-color:                rgba(0,0,0,.2);\\n@popover-fallback-border-color:       #ccc;\\n\\n@popover-title-bg:                    darken(@popover-bg, 3%);\\n\\n@popover-arrow-width:                 10px;\\n@popover-arrow-color:                 #fff;\\n\\n@popover-arrow-outer-width:           (@popover-arrow-width + 1);\\n@popover-arrow-outer-color:           rgba(0,0,0,.25);\\n@popover-arrow-outer-fallback-color:  #999;\\n\\n\\n// Labels\\n// -------------------------\\n\\n@label-default-bg:            @gray-light;\\n@label-primary-bg:            @brand-primary;\\n@label-success-bg:            @brand-success;\\n@label-info-bg:               @brand-info;\\n@label-warning-bg:            @brand-warning;\\n@label-danger-bg:             @brand-danger;\\n\\n@label-color:                 #fff;\\n@label-link-hover-color:      #fff;\\n\\n\\n// Modals\\n// -------------------------\\n@modal-inner-padding:         20px;\\n\\n@modal-title-padding:         15px;\\n@modal-title-line-height:     @line-height-base;\\n\\n@modal-content-bg:                             #fff;\\n@modal-content-border-color:                   rgba(0,0,0,.2);\\n@modal-content-fallback-border-color:          #999;\\n\\n@modal-backdrop-bg:           #000;\\n@modal-header-border-color:   #e5e5e5;\\n@modal-footer-border-color:   @modal-header-border-color;\\n\\n\\n// Alerts\\n// -------------------------\\n@alert-padding:               15px;\\n@alert-border-radius:         @border-radius-base;\\n@alert-link-font-weight:      bold;\\n\\n@alert-success-bg:            @state-success-bg;\\n@alert-success-text:          @state-success-text;\\n@alert-success-border:        @state-success-border;\\n\\n@alert-info-bg:               @state-info-bg;\\n@alert-info-text:             @state-info-text;\\n@alert-info-border:           @state-info-border;\\n\\n@alert-warning-bg:            @state-warning-bg;\\n@alert-warning-text:          @state-warning-text;\\n@alert-warning-border:        @state-warning-border;\\n\\n@alert-danger-bg:             @state-danger-bg;\\n@alert-danger-text:           @state-danger-text;\\n@alert-danger-border:         @state-danger-border;\\n\\n\\n// Progress bars\\n// -------------------------\\n@progress-bg:                 #f5f5f5;\\n@progress-bar-color:          #fff;\\n\\n@progress-bar-bg:             @brand-primary;\\n@progress-bar-success-bg:     @brand-success;\\n@progress-bar-warning-bg:     @brand-warning;\\n@progress-bar-danger-bg:      @brand-danger;\\n@progress-bar-info-bg:        @brand-info;\\n\\n\\n// List group\\n// -------------------------\\n@list-group-bg:               #fff;\\n@list-group-border:           #ddd;\\n@list-group-border-radius:    @border-radius-base;\\n\\n@list-group-hover-bg:         #f5f5f5;\\n@list-group-active-color:     #fff;\\n@list-group-active-bg:        @component-active-bg;\\n@list-group-active-border:    @list-group-active-bg;\\n\\n@list-group-link-color:          #555;\\n@list-group-link-heading-color:  #333;\\n\\n\\n// Panels\\n// -------------------------\\n@panel-bg:                    #fff;\\n@panel-inner-border:          #ddd;\\n@panel-border-radius:         @border-radius-base;\\n@panel-footer-bg:             #f5f5f5;\\n\\n@panel-default-text:          @gray-dark;\\n@panel-default-border:        #ddd;\\n@panel-default-heading-bg:    #f5f5f5;\\n\\n@panel-primary-text:          #fff;\\n@panel-primary-border:        @brand-primary;\\n@panel-primary-heading-bg:    @brand-primary;\\n\\n@panel-success-text:          @state-success-text;\\n@panel-success-border:        @state-success-border;\\n@panel-success-heading-bg:    @state-success-bg;\\n\\n@panel-warning-text:          @state-warning-text;\\n@panel-warning-border:        @state-warning-border;\\n@panel-warning-heading-bg:    @state-warning-bg;\\n\\n@panel-danger-text:           @state-danger-text;\\n@panel-danger-border:         @state-danger-border;\\n@panel-danger-heading-bg:     @state-danger-bg;\\n\\n@panel-info-text:             @state-info-text;\\n@panel-info-border:           @state-info-border;\\n@panel-info-heading-bg:       @state-info-bg;\\n\\n\\n// Thumbnails\\n// -------------------------\\n@thumbnail-padding:           4px;\\n@thumbnail-bg:                @body-bg;\\n@thumbnail-border:            #ddd;\\n@thumbnail-border-radius:     @border-radius-base;\\n\\n@thumbnail-caption-color:     @text-color;\\n@thumbnail-caption-padding:   9px;\\n\\n\\n// Wells\\n// -------------------------\\n@well-bg:                     #f5f5f5;\\n\\n\\n// Badges\\n// -------------------------\\n@badge-color:                 #fff;\\n@badge-link-hover-color:      #fff;\\n@badge-bg:                    @gray-light;\\n\\n@badge-active-color:          @link-color;\\n@badge-active-bg:             #fff;\\n\\n@badge-font-weight:           bold;\\n@badge-line-height:           1;\\n@badge-border-radius:         10px;\\n\\n\\n// Breadcrumbs\\n// -------------------------\\n@breadcrumb-bg:               #f5f5f5;\\n@breadcrumb-color:            #ccc;\\n@breadcrumb-active-color:     @gray-light;\\n\\n\\n// Carousel\\n// ------------------------\\n\\n@carousel-text-shadow:                        0 1px 2px rgba(0,0,0,.6);\\n\\n@carousel-control-color:                      #fff;\\n@carousel-control-width:                      15%;\\n@carousel-control-opacity:                    .5;\\n@carousel-control-font-size:                  20px;\\n\\n@carousel-indicator-active-bg:                #fff;\\n@carousel-indicator-border-color:             #fff;\\n\\n@carousel-caption-color:                      #fff;\\n\\n\\n// Close\\n// ------------------------\\n@close-color:                 #000;\\n@close-font-weight:           bold;\\n@close-text-shadow:           0 1px 0 #fff;\\n\\n\\n// Code\\n// ------------------------\\n@code-color:                  #c7254e;\\n@code-bg:                     #f9f2f4;\\n\\n@pre-bg:                      #f5f5f5;\\n@pre-color:                   @gray-dark;\\n@pre-border-color:            #ccc;\\n@pre-scrollable-max-height:   340px;\\n\\n// Type\\n// ------------------------\\n@text-muted:                  @gray-light;\\n@abbr-border-color:           @gray-light;\\n@headings-small-color:        @gray-light;\\n@blockquote-small-color:      @gray-light;\\n@blockquote-border-color:     @gray-lighter;\\n@page-header-border-color:    @gray-lighter;\\n\\n// Miscellaneous\\n// -------------------------\\n\\n// Hr border color\\n@hr-border:                   @gray-lighter;\\n\\n// Horizontal forms & lists\\n@component-offset-horizontal: 180px;\\n\\n\\n// Container sizes\\n// --------------------------------------------------\\n\\n// Small screen / tablet\\n@container-tablet:            ((720px + @grid-gutter-width));\\n\\n// Medium screen / desktop\\n@container-desktop:           ((940px + @grid-gutter-width));\\n\\n// Large screen / wide desktop\\n@container-lg-desktop:        ((1140px + @grid-gutter-width));\\n\",\"wells.less\":\"//\\n// Wells\\n// --------------------------------------------------\\n\\n\\n// Base class\\n.well {\\n  min-height: 20px;\\n  padding: 19px;\\n  margin-bottom: 20px;\\n  background-color: @well-bg;\\n  border: 1px solid darken(@well-bg, 7%);\\n  border-radius: @border-radius-base;\\n  .box-shadow(inset 0 1px 1px rgba(0,0,0,.05));\\n  blockquote {\\n    border-color: #ddd;\\n    border-color: rgba(0,0,0,.15);\\n  }\\n}\\n\\n// Sizes\\n.well-lg {\\n  padding: 24px;\\n  border-radius: @border-radius-large;\\n}\\n.well-sm {\\n  padding: 9px;\\n  border-radius: @border-radius-small;\\n}\\n\"}\nvar __fonts = {\"glyphicons-halflings-regular.eot\":\"�6\\u0000\\u0000�5\\u0000\\u0000\\u0002\\u0000\\u0002\\u0000\\u0004\\u0000\\u0000\\u0000\\u0000\\u0000\\u0005\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0001\\u0000�\\u0001\\u0000\\u0000\\u0004\\u0000LP\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0002\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0001\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000��\\u0018\\u0002\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000(\\u0000G\\u0000L\\u0000Y\\u0000P\\u0000H\\u0000I\\u0000C\\u0000O\\u0000N\\u0000S\\u0000 \\u0000H\\u0000a\\u0000l\\u0000f\\u0000l\\u0000i\\u0000n\\u0000g\\u0000s\\u0000\\u0000\\u0000\\u000e\\u0000R\\u0000e\\u0000g\\u0000u\\u0000l\\u0000a\\u0000r\\u0000\\u0000\\u0000x\\u0000V\\u0000e\\u0000r\\u0000s\\u0000i\\u0000o\\u0000n\\u0000 \\u00001\\u0000.\\u00000\\u00000\\u00001\\u0000;\\u0000P\\u0000S\\u0000 \\u00000\\u00000\\u00001\\u0000.\\u00000\\u00000\\u00001\\u0000;\\u0000h\\u0000o\\u0000t\\u0000c\\u0000o\\u0000n\\u0000v\\u0000 \\u00001\\u0000.\\u00000\\u0000.\\u00007\\u00000\\u0000;\\u0000m\\u0000a\\u0000k\\u0000e\\u0000o\\u0000t\\u0000f\\u0000.\\u0000l\\u0000i\\u0000b\\u00002\\u0000.\\u00005\\u0000.\\u00005\\u00008\\u00003\\u00002\\u00009\\u0000\\u0000\\u00008\\u0000G\\u0000L\\u0000Y\\u0000P\\u0000H\\u0000I\\u0000C\\u0000O\\u0000N\\u0000S\\u0000 \\u0000H\\u0000a\\u0000l\\u0000f\\u0000l\\u0000i\\u0000n\\u0000g\\u0000s\\u0000 \\u0000R\\u0000e\\u0000g\\u0000u\\u0000l\\u0000a\\u0000r\\u0000\\u0000\\u0000\\u0000\\u0000BSGP\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0003\\u0000w�\\u00005s\\u00005y\\u0000-�\\u0012�����\\u0011՟(tۊK��\\u0010D��'P\\u000b�M�\\n�\\u0000B�j\\u001e���beJ2cc��LF\\u001e1+�WEeuJ\\u0019��e�~m��%���W��*�IzI\\u0017�\\u0004sL��\\tx\\n\\n��4�xїPS��-Uu�T\\f�E��F�\\u0003\\u0003��?ͬ\\tԯ�4�\\rʨg��\\u001cq �e�$�{��-+�\\u0012\\u00021u\\u0001�\\u0006���{���S��\\\"!E�B&/\\r���L��\\u0002�E�\\u0005�K�\\u0015�7f��Ү�|�'�=����j��p��E�A_B�@��*�\\u001d?~���\\r�\\u00169�&\\u0005�I���v���@\\u0017e��r��\\u0001�>Mo<�LX���\\u0004�%���a>˒ �\\u0002�jp\\u001d?P�;�_��\\b��iƶ� <��}LbX�Ue1\\u0012�L\\u0011\\f\\t�!�;���\\f\\f�\\u0006�\\tD\\u000b�^%� �\\tPP��\\u0015A�@��\\u0002�5\\u000e����K\\u000ea�lӴğ�a!\\u0010������|Zh�\\u0010��FFI�0�E�F\\\"đ������'Mո�\\u00069\\u0004�@�)�\\f1A�����ȶ���р���<\\u0001�\\f�\\u001e\\u0015��,�@��A�\\tpA��Cϲ�\\\\�.�\\u0000\\u0010mȤ�Ix���\\u0006��sS\\n\\b\\\"�r�r}�n\\u0019N�����~lQ��o�`>�t��\\u0016��鰅\\u0006��׶������\\u00125����\\fX`\\n­\\u0001g\\u00129K��\\u0003� �g\\u0002�\\u0005]�s �z\\u0005T0%j��kT���g̙0\\\"�\\u0004Y\\u001cVg��\\u0013@\\u000e��)��\\u0001>aF\\bc\\u0000!t\\u0000z�\\u0000��\\u0014�=\\u0006V��k���@op^v�?�J��=f���0[7��@��}�t\\u0001��\\\\��\\u0015��}��\\u001cv\\\\|f\\u0019\\u000f{�y�?=\\u001f�1\\\"f����\\u000fx���Hxx�i�\\u000f8�k�PY�8��\\u0007~Ú��\\u001d�\\u000e�7@�(:3v�𰬨X�X+(\\u000b\\u0017�\\u0002�����F\\u000bj\\u001a�\\u0016�19�\\b�\\u0013�'(m�}��\\f�\\u000f�e\\u000e�\\u000b��C��Œ�=��\\u0004&�\\f�\\u0014�e\\ny\\u0006\\u0019��E\\u0006��B\\u0000�(�2���E?\\u0001xv5�ki{P\\\"�I�G�kXLP�ŀE�>G��[�|q!�c�+o0�\\na�\\u0004�~�\\\\��\\u0019;��!\\u0011�!�+�\\u001d�uX1�H�\\\"����������\\b�U94%��`����)��y�\\u001f\\u00061�*����/\\u0018��:>\\\\g�@�<H��HܶW��~}�����:�\\u0015�h\\u000bf\\u001b���lZ�4�Y��\\u000b�Ζ��?\\u001czU��\\u0002���AUq:�>x�����Z��.]�\\u0006�A��\\u0004��ҁ�K��/\\n�{[\\u00178�]�b�.q~���2�D�oR�zK��oGl���{E��\\u0001\\u001a��\\u000b9��\\t�E\\r�ZR�\\u0013}3\\u0012QO��Е6��C�).�R���%\\bOy\\u000e����r\\n�#\\u0015��Q��V?l��G�I��V�\\tT.�R���t\\r\\u001c\\u0011�ދ����mݯ�mb�v\\u0001\\u0000�vtO\\u000fn#<�u\\u001c�9��\\u0017p3:��\\u0011�)�%�\\u001e�Tz��\\u0003�\\u0012\\u0016\\u001a��c\\u001a��\\fB\\u0004W�c\\u000b������\\ncFvEZ�O�Ik��\\u0010M\\u0010\\u0014�Y�u\\u000fj%[�(\\u00110i�\\u0011\\u0003�>)�aQy}�vb2��'*�b�G��\\r���~\\t�5�s�'����\\u0002�å�vx\\u001e\\u00118\\u0007)#7J\\f��\\r\\u0002���@IƠ�\\u000b\\u0016�`�S\\u0017(E�˖\\u0016B��!\\u000e\\u0001\\u0002$<\\u0015�\\u0000sm���{э� �����!`x뚢\\\"ZaB3����\\u0004x��W��[\\u0004׃���j\\u0010\\u0006\\u0002ƃh�%pt\\u0004K\\u0001�[�d���\\bC$U\\u0014C@\\\\)�A~\\u0014q�\\u0005����\\u0013�\\u0019/�\\u0016@\\u0005\\u0018\\u0001zn�2\\u0011�\\u0016e?9�ڟ�N�ظQ�91��Ba����a�0�#�\\u001cژ.3\\u000e���\\u0018����������+z%�\\u0010Ԇ�\\b��\\u001a\\u001fEڔs�A\\u0017\\u0012\\u001a\\u001c\\u000b\\r�\\u0012U�|\\u001a�h��@��إs5S8*v0\\u0018\\u001cD�����U�\\u001dYm\\u0007���I���s���:��Dt��Xr�/���0[L\\r\\u001b\\u0006N�\\t���\\u0005�I���Ċ$a����pp���\\u0003MNʢ7��tD�I'al�Y\\\"4\\u0017��X\\t�r��[�{\\u001d_�\\u0012MW� \\u0015X1�<��c��)�L\\u0019|���S\\u0000�Q��͖�V�\\u0019��F��\\u0002F��\\u0004\\u0016\\u0001t\\u001bu��4d��r\\u0018-Mv�M�u�S���\\u00178�91c���\\nÒ`�\\fAI��#\\\\�*p�X�׼�)���4%>��\\u001a�bm�]�5��5�N\\u0017=G���\\u0000\\u0001#�r���96#R\\u0003���\\u0015\\nYi���\\f�\\u0006+\\u0007\\u000bf\\u0000'F5\\f8@\\u0004�x�4���K���.��- 2��:�Q\\u0003\\t�4<y\\nʃ9i\\u0004��\\u001f�V3:��<\\u00167>܏\\u0004�\\u00175\\u0001\\f�2\\u001c\\u001a�X\\u001eC�7\\u0010`M-��j�\\n\\u0000>;~�L��5�n�H\\u0013��HF4�K߹�Y�p��r�\\u0002ws�4�݌F�۝��F�:�\\u00070Ӣ\\u0001�L[f|��\\u0006��\\u0006��J�����֠:\\u0013h�$�I\\u0001��ry(*�u&\\u001d~K�e��`�\\f��73)\\u0010�W�$ %ض����p�@\\u0013C�\\\\�r|S�\\u0012\\\"�\\u001a�E\\\"\\u0018���0i�r\\u0002O�Dh�md#$4E\\u001b��@J��\\\"����T\\u0017�\\u001f(��L�9ٴ�N�CxM�����\\r�}D�-�BI��rx�\\u001c\\b�)\\\\)\\u0001�gU�J�i����u�O�\\u00151T\\u0007>�|��>J��D��bs�-�@\\u0016�\\u0010E�@�\\u0013]�8�������B��𴼅�ږ��\\u000b�X�_3\\u0010�U\\n\\b�\\f�dD�ǁ�_� ��\\u0005���\\f\\u0004�t��\\u0001��K�4\\u0010n,�D�\\u001f���\\\"6��@\\u0005���뇂\\u0005� ��F\\u001e�m�`Y�\\u0012\\u0004�6�\\u0016'3¨�\\u001f�\\u00162l�\\u0004p\\u000fM\\u0003�`<�hW�\\\"��P�@����\\u0019\\t(J(�^�3��O�y�Lq����]\\u0012(D��R�r\\u0019c�{e����\\\\3P\\u0016!}\\u0010\\\"��ǼVt�)w���\\u00194?��u~�D��\\u001a��U2]�\\u00190�OVF�6-���M��)���eY�l.H��Rψ_�A��J�\\u000bʻ\\u0018Y�\\u000e咓oIF��Zt:\\u0013�٬��\\u0013·�����h\\\"\\u0012\\u0006B������&���\\\"�ny󘋉A��-���x#�~6�շ��hX�����{�9A�\\\"�5io�rj�{�H8�)��IZ^м\\u0004�ĳ@.@�ΓF\\u001e.���\\u001c\\u001c\\u0019R�K�A�D �d\\u0011��\\u0001�Q\\u0010�,�\\f���a\\u0004[\\u001aq�g�@�\\t�D_���#E�u�)�R1��B]F\\n�u�V\\u0003�����G{\\u000e�����\\u001a�\\u0004��x\\f�\\u001e]ε(@\\u0018\\u0001m�\\rl\\u0011���f�����P�:�H���\\u0000s�,i\\u0014�����Q>2�\\\"d[\\r(�\\u0010� ��\\f/�uҏ�bS�L\\u0011˳�.\\u001b�\\\"�:�\\u0018A�U@�p��ֽR\\u0001�E���{�\\u001f�\\u001bB\\u001b��H���ƥ�!\\u0005I���a�\\u000b-w\\\"�)w%���᜙�����\\u001brw��ͳ�\\u000er�6��!�1�Y��\\u0000˘\\u0016LT�p��x��\\u0018�r�\\u0006�8\\u0014]\\u0005�\\u0011>҈\\u0004��S<h�yj�C\\u0013�\\u0015���]��K�ŀĬ&\\\\v�C`�b�#a���[]�I���F\\\\k൥�X]��`�e�MX�\\u0013dT�2��f���}����^n�N��$��@�ٚ��z��R\\u0012:�q\\\"S��Y�\\b�0��J�/��թY3\\u001a�ę�Ů�#�q��\\u001fY\\u0015\\u0018�s�����|HJܢ�ǔ0�ق�\\u0004�v�8�4��Ñ���Q\\u0011\\u001bv�y��PѡC�;�Μ{\\u0002x8`3G��fN����[V�߾\\u000eP�\\t�U�\\u0013\\u0006�]]�JO��6\\u000e��r�_t~o��>\\\"�#^�m�ꤾ�\\u0014�B\\\\\\r��i�&U�=��Q\\u001d�1ğ,?�t&r,@l�5Aی�J��6\\\\��\\u0007�w��x7I�\\u0013\\\\`n�sKpʴ\\b�݀׼\\u0014\\f�2\\u000bL�\\u0005\\u0000��\\b'�M3\\b��\\u000f���Ki[v&V\\u0002�tF�TH�\\nrx�\\u0001��TUY�Ee�}\\u0001���\\u0005$\\u0016W�\\u0007=�\\u0013\\u0001X/�}%�K�D\\u001a\\u0013��*��:�D\\u0000=K\\u0012�_�����`�D�#�[��J�Q�l�$\\t\\u0006��z�\\u0000s/�\\u0002��\\u001f\\u001e�q��J����I+\\u0010�X��,�$\\t�g�f`��%�Q�6�\\\"\\u0018@t��N\\\"9\\u001e()y\\u0015�\\u001b.B��� L��*�6�o^4�4Y��e-ҫ��z\\u0005_�|���~�nM7�\\u000e�ڌ�Tg�\\r\\n�`�΋d�\\u000e\\u0007kbr�ؐ����\\u0018�\\u000f�f�\\u0013v\\u001c��/$}%)�-ė��R�\\n\\u0007�&\\rH|&�X�$\\u000e\\t\\r;c�+s-�A�Ј>>;_�?-�1hG*\\u0010��\\u0016@��Urȳ�ˊ73�6h)����\\u0018�� O���\\u0000.�M2�>j\\u0000j=B¦�1�M��XB`L�Ѱ\\u000b>x\\u0005���\\rd���b\\u0016N\\u0012\\t�X�\\u0011K�\\u0012�n,\\u0013ཫW{퓙��;�ߴ�p[�j)^��`z�\\b�WI֮�\\u0007����p�h�4?Ϳ��eS�ڃ\\f��\\u00184+v\\u001f{�1��X�PBX���\\u000bq��EsG�\\u001b��p?g\\u0006���i{Ә�M�t����ꛖ���\\f�c��8;$<�\\\\3Q���\\u001eZ\\u0005�\\rld\\u0001v��f܆\\\"�\\u0001��c�\\u0001�ž��\\b��\\\\\\\"Z�\\u0018�T)U��Z�l��U\\u0016A'h�E�,ԁ�.A=��\\u0005t���\\u0010F�DRl�s�\\u000b�)ș�`/\\\";�\\f.��2��\\u001b\\u001d]b�\\u0010P�cB��ro�*[��\\t\\u0000��B� K|e��40\\u001f��M\\n�2B�\\u0014�f1���1\\u0004y��������R<\\\"�F�I�\\u0002'�V���P��\\u0012�N�ɣ���\\nPF\\u00158\\b`�j\\\"jm�����\\u0016\\u000f� gxD�A\\t�ڝH�u*W�X_����9q�[��L\\u0006\\u0005\\bi�u\\fN�9v@pkvmR��sS��(�\\u0001�\\u0002\\u001c@ص\\u0003\\rۙ\\u0010\\u0014��\\u0018��bqL�\\u0016$� \\u001b�Ũ!\\u001a�\\u0019�g\\u0005�X\\u0002Y�d�� ?ȩ�\\u001a�D|'���C�#ru�\\b\\u0011*(n�o�5\\u001b\\u0016\\u0004������\\\"x�c\\u0006!B���i��2��쫳\\u0018������\\u001f�D\\\\C�\\u0015\\u0006�E�=���z��J��k��)\\u0015��\\u0013gY�]�e���0��#��\\u0016`�P\\\"�{\\u0000��\\u0019�����Q]b\\u000fڝPb��\\u001ajB�!�\\u0001Zlv;�\\\"禥N��[\\\",�\\u001a0yԺ�#u-\\r�\\u0019\\r��\\u0001\\u001fG�\\u001d���!����\\u0001�.��\\u0001�\\u0011n�b���FX\\t�&�\\u001b�t�\\u001c!2�]6H�GH\\u000f<\\u0012��\\u0000\\u0014\\u0004\\u001ehC��K4N\\u0004��\\\"\\u0019��7�\\t�|2�~�����'h��\\u0013�A$�\\u0007\\u000bVTv����Y����\\n=<�\\u0012I�\\u0016\\u0003##\\u0012��!L$�����[%��'R���F�!.Ŝ��|��m9�('\\u0018�%�\\nt�P+�l�w\\u00118D�1\\u0013\\u001d����g\\u001a� �\\fWޏ�Y1\\u0016��lb�\\t��\\u001f�(���5V\\u001a�zk���1m�\\u0017����ֻ\\u0000\\u0010-���\\r�I�����6�\\t\\u001a\\u0010A9\\u001ex���?;gHɬ�{)\\u0006\\r �G�)�� ��Np�Ȁ�\\nO\\u0002\\u00199S���%<�E)\\u0018��<O�L�BLx\\u001c�A���01\\u0002}¬h\\u0000-=�n�\\u0010e\\u0016C\\b�#0c��k���-\\u0000\\u001b��b�!:f�\\u001dT3,(mС�q��=؃�c�����\\u0007��1�*T\\u000bilO\\u001b�)`�\\u0016h{�\\u0011M]N�%�\\n��~*&\\u001e�W�$�=7\\u001d8�Mƴ\\u0017�\\u0013d\\n\\u00114\\u0014tZ\\u0000��3Ք�3jđ�\\u001d\\u0014\\u0014�\\u0005an*��P�\\u00146�\\u0011�¢2J$Ң(LP@c��R\\u0000#@$��\\u0014�h7Nzpq@ព�;ac�\\u0002�H[�\\u0014w\\u000bh�v\\\"c�\\u0003����3s\\u001d\\u0017�+\\u0019֒\\b�` \\u001c�6S�v� ~\\u000f\\tTt�r�\\r�HS1eRO܁\\u0013�\\u0012(X�\\u0015��`]\\u0015��eC\\u0016�\\u0019\\u001f 4x�h �@���\\u000bE�\\u0011r@�x�\\u000bJX��Y%�47�d@FX�Q����(�ٓ{A\\u0001<�!\\u0004^!F�y�\\u000e ��%=�!\\b��b\\u0010��k8���\\u0002�P�y\\u001dW\\u0013\\u001arrqKy˻E\\\\��ث��ո��T\\u001d�B��h�\\u0001\\tCwI�!\\u0000|Dj7\\\\��i\\u000e�U�*\\u0003��J��wR\\n�G�:��R�M��b�H��\\u0010n\\u0003|�wi�\\u0013�ڠ\\u0013\\u0006��*���g*~\\\\���G���SvY��T�j����@\\u001dV\\b\\u0001\\u0017�q\\u0016T��f�*��ER��\\u0018T��\\u0003P��\\fnt8\\u0001�,�ά\\u000e��e�A��2bP\\f�����-���\\rU00\\u0005�f4\\u0013\\u0004O�\\u0017N8\\t�0\\u0001'C�#��\\u0017�\\u001f\\u0006'\\\"\\u0007Wv;�\\u001a�� �L\\n�]C0Y\\u001a��>�Ly�|w\\u0017�x.���\\u001e�3#\\u0004\\\"V�\\u0019�\\u0013�ʵKI�Z �a��\\u0014\\u001eh��[P�Ȃ=�̘Aa���%�[\\u0010\\u0019(�P�'R\\u0013\\u0011�D�8\\u0004c�\\r\\u001dPMn+jc�\\u0010�̛�3sh�[�t��8(\\u0010C�3<#`e�\\u001f�h�up#��5�A\\u0014\\u0010a\\u000bυ�)&\\u0000DO����֐��/ޘZ�)��=)���D'n_\\u001f�߼�BG\\u0003��Y�\\\\lZ����@�0\\u001b!\\u001d�ӕ!C��DFi�`(\\\"\\u0014ؽ5�\\u001c����9ZGG4�?��W\\u001eあ�\\u0013M��'i�?9���l*���FV�H\\u001c}��P�׊JM�Η[|�bdM\\u001fL(L\\u000eԕ�(��И_�\\u0004\\\\\\u0016.��2\\t��B\\b���\\r��I?\\u0002w\\u0000��\\u0007Tw\\u0011�\\u001d����2\\u0004g�`�\\u0001\\u0018\\u0000�:\\u000f\\u0000\\u0001\\u0004��\\u0000�kQ��}\\u0003$�U�\\u001a��\\u0007�\\u0003z��\\u0018�>�\\u0002\\u0016/H\\nP@f}�\\u0018��2(A\\f����\\u0011\\n\\u0005ߚ�%��ꑓ,q3)�Ί\\u0007�\\u0011���jh�����hw\\u0006�V�v�\\u0007\\u0018�VQ\\u0012���\\\\!` tX5\\u0014���^��B\\u0013/\\u000e�')�0�t3�~�\\u0001\\f\\u0012�����$�\\u001b\\t����4��\\u000fwV\\t2�(�5�\\u0004[��\\f�\\u0007��R�\\u0015u\\nſ��\\u0010\\u000e\\u0001[s~-b|�P\\u001f�Q{\\u001a�?˺JT�1��[�5k���> ZN��w&�|�r�>��d\\u0017��\\u0013;Ũ8��^V �\\u0011���0ú\\u0016Z\\u0013\\\"d&[,�nY\\\"}\\u0012|)�\\u0006�n6����(4S������u\\u0011\\b|[�L6���\\u0001\\u0005t�c\\u0006\\fDD��K���i�\\nK��t\\u001d�\\u001e2\\b*�\\n�2���eZ�\\u0000\\u0011\\f͗7�4\\tQ�M��\\u0005iq��HT�\\u0018y�Y�\\u001c�(9�T�����a-kpx�d\\r[\\fN�y�~O�q�^\\u0007�lqQ\\u0017�0Z�\\u000b��\\u001a�\\u0019d��a-�1�\\u0000s� �#����\\u001c�#̨g\\f�|]��\\u00126�\\u0019�$\\bdǌ�?~tM\\u0012�\\r�� 褺�\\u001c\\u0003���ܵ��6cƳ5e�����\\u001f�\\u001cXU\\u001b�8GE�\\u0016\\u0012���v�?ch�V�K'��C\\u001b�$�ΧS�A��`�n��\\u000fJw�Z��'��\\u0013'ztO\\u0001��G\\u0013\\u0012�\\u001cl\\u0005\\u0003\\u001b\\u0011\\u0003\\u001dĈ\\u0003��[D��Q�+�q\\n�B�\\n\\u001e9\\u0002\\u0001Ô�<\\u0014�\\u0013\\u0014\\u0016?l\\\\幠�$�s\\bsb'\\u001e���<\\u0017��W�1��0DL�\\u00196�+\\u0004Ak���\\u0013=���m\\u001e\\r�\\u0016\\u0010�_G��v�\\u00125p�,�s�n\\u001c\\u000e���\\u0006.����Q\\u0011aR�PD+<�3�lM\\b�5_BԆA��N��p\\u001a��H\\n�\\u0000��<�.\\u0003\\u0000�������|[P\\u000e\\u0012\\tZ��m�\\u001a�X\\u000f%-6�t��g�\\u0000@@\\u001b��z�&���mL��\\u0001�3���<Q@ͷ�n�H\\u0001�Ɏ�q����4����Q\\b�;&:��\\n�=�bU\\u001a`�[�MJo��,�� @I�|'e��M�^H�cf\\u0007���$�P\\u0001�\\u0004d \\u0011lǧC&�ڦw�2\\u0005w�pu�l��^n�ƣ�Šp��T�\\fm\\u0011��˰��\\u0003��\\\\߀\\u0006\\u0015\\u0011�hb=rA�.us�4���O\\u0011�i�;�P�\\u0011�m9Jؕ0���I\\u000b�}�\\u0000u)Ǆ��\\b�\\u0013�rT:B�!�\\t3��(\\n��*\\u001c�l�U\\u001d/8\\n=�>\\u001a'\\u0019t]�\\u0016���]�i�\\u000e�ulz�\\u001f$��\\u0010|�H\\u001c\\u000b\\u0011�n3�0�v?�yU�t{Ċ�)¶\\u0001U�0��~\\u0005O[}\\u0007�\\u0000\\\"��\\u0015\\u0004�\\u0010)����\\u0010 ٓ�'j�\\u000e�k��MCX�\\u0011<-�\\u0003�����/p����G�?\\u000bl�\\n�9 4�F\\u000e��~���u\\u0011�u�h+�+�cH�\\u0014���녙Q�&�t֢�x�q�t+�_Q$T\\u0003\\u0012^\\u0003؇��`u�O��d�Qp]����� �!H\\u0019舰�\\u001cŶ�SJT��J�y��g\\u0018�xh\\u001f!\\u0019�8G\\u000eb*�<\\u0006���\\u0003T\\u000b�h}���\\\"�N4bx�#$�\\t|�͑�a���P�l�I\\u0002\\f��:W`��\\bL�U�\\fMK�\\u0007������bTs(S��\\u000e����\\b�p�~�U1�p�.7���\\n\\u0013N���\\u0010٨��D�ޛ�h�AXa���\\n@+\\u0016Ά\\u0013�-'����\\u000b�6O]�TU<1�\\u0012����q��\\u0011�\\u001ew�$������=ҼL��\\u0016����3�\\u0016fi�+���M�\\u001f\\u0010p�6�œ6�����{L���󿒎E�\\u001b;0�\\u0014�~pN\\u0006\\u0019���\\u0000lZ��$��N����ж����b���i�)��y��^M�\\u0003\\\\\\u001d�\\u000f\\u0003�D\\u0016����\\ndּ��\\u0003Pe�\\u0018#6��AX4�̆�[��;�Ek�7�l-\\u0002��bG��\\u001fV��0������\\u0019r�)*r���\\u000e�:�Gw6�U�\\u001dI>j�\\u0017���#q��R��H{�U곎�!BR\\\"����3x\\\"3��\\u0019�ޗm0>=�&����\\u000fB@�J��\\n��k��̪ts0p~\\tT�a�h�B����!�s[\\u0007\\r1yκ \\t�VJ3\\u0016!\\u001dz���\\tTP\\u0005\\b�\\u001a\\b�LI:�\\f\\u001a���q�\\u0019�s/�C��O��-�\\u0019�\\u001d��\\u0012!�񅺀��L�21��y\\u0014���؂�F��\\f䤣['��'��V��Dz��\\u001bd\\u0014�Ϗӆ��\\u0006�p�\\u0012��.��Ek\\u001a\\u000f��ʤI$����|�e�\\u0013��\\u001c�\\\\\\u0017��T���\\u001a'��H>;Y\\n��\\u0001�\\u0015:+UC�7\\u000e����c�\\u0011u�@ʸ�.��x�~�J\\u0019�+I�\\\"\\u0002F�H��8��N���k���\\u0000\\\"�u\\u0002p���Mo\\u0003z��\\u0006G䰦r{;���Dz\\u000b���Uw�R�pRr`��{l��\\u0016�s>˲$@��)��.\\u0003x-�t���\\u001e�a\\\"�N�\\f�^��~&@᧧��<�K�\\u0003������,���R��\\u0010\\u0010��P\\u0014ږ��\\u0012�鯌Ԭk\\r\\n���9��P\\u001eS4�ͳ\\f\\u001ab�n�\\b�\\u001cZq��d\\u0010�#\\u001d-���C\\t�\\u001e�xz\\u001b�W6>\\u001d�\\u0001/��\\u001b�-�Q���N����k�s��wl^��Ў���FV\\u0003���\\u0006�Y�������\\u0005��'C?\\u0003���xB�o܉�Q\\nM�?�~��U\\u0014j�a�\\u001fSӯ��\\u001f�s5�\\t�{Y�2\\u0002�aF܈\\u0018:\\u001cJ\\u001e�\\u0012s�Ҵ@W�\\u0006�i[\\u0014�'O���vW�B�\\u00156�}{I�5����\\u001a��k�r�(�4\\u0016�u-�0\\u000f�7\\bH�X�\\t%$�هAd�?[��h\\\\<\\u0012�\\bn�\\u000b��_\\u001bʩX�V\\u0006�3/�\\u00132sE�\\u001e�u9�����\\u001b\\u0016�>�\\b^O��5��QkF��&%Y0c[\\u0019���kO�����&��\\u0004c�f�hi�1����3_���3�}wa\\u001cjiA$t�\\u0018��\\u0013��\\u000f�ۀ�z\\u0002��'\\b$\\u0010�0�,N����R\\u0010�HJ(�%�B�ܼ�v5�|�̱Xx,��L��@H�^���G#������q;�_�\\u0003�uJ��g�*�W���\\n��f#�;0//Z�\\u0015���U�~�n6�+��$zv}\\u000e.�\\u00030.\\u0003=\\u001d�\\n�&�p\\u000b�����ῼ|��f&\\u0003s܇�b\\b��9��.\\u0005�A��=�`�\\u001a��\\u0010D\\u0015��\\u0018���\\u0005��`*\\u0000�\\u0010y�R���p\\u0004���.2�謅�?�\\u001a�0t���hZ3˷e5�,�i��޾0�Qe���;�\\u0003���,\\u0019b��\\u0013����� �т�\\u001f��)Q@�.և�@��(ښz.�1E�>������ J|W[+\\u0019U\\\"�\\\"A\\u000b�\\u0012�*�\\u0001�w�]yS�AH>�>ȟ�˩ѠF,\\u0004\\u001e\\u000e�#�/즊\\u000e�w�\\n��k~Y��H��\\u0010l�eu�H\\u0000�\\u0019x\\u0003}+\\u000b\\u0019p8'[���U��ܥ��\\u0012V�\\u0001�\\u000e#\\u0002��\\u00136����\\u0001�0(Δr���XS��6YB���m%\\u000b\\u001dM��ӃY�\\u000f67��x�-nh�'*�,R�*����\\t\\u001a\\u0017;\\u001f\\u0013��|�6\\r%U�C\\u0017r�c��2�\\u0003�*y�E�Ǟ+��xk�\\u000f�*�\\u0003�Z��^0N�A�o���*ZY�\\u001e5u���C?\\u00010 0\\r\\u000f2�����P��\\u0001\\f\\u0018G�\\b�X2z6P3��\\u0002Դ�1�S��`�\\u000b�|&|\\u0005ӀiE�����A��)���k��0N\\u0006�\\u0000\\u001c���j�D�܉� �@��������}�~\\u0014�w\\u0017��U�,rq\\u0000t\\u0015�¤S>^0$rI)\\u001fV�rqú��\\u0012�y\\u0014���7���\\u0005E��n\\u0019\\fU�wi��!u%b����\\u0002���^��I�O�\\u0000\\u0000��ǐ��Ǒ��cI���Ѿd��C����N];\\\"T��\\u0010�\\u001aB�)�8$�V� �Fk?�\\u001d\\u001f\\u0010��2�HO\\u0012\\u001e\\u0016�>��Ќ�\\t����c&���ȗ�%�\\u0014Z�:�h�\\n���>��p%��\\u0019H�$zd��fn(=\\\"\\u001b��\\u0005\\u001e�\\u0010������^��Ӊ�Y�+D�\\u0004<�*;�\\u001c{�+Zy\\fl���B\\u00120���ȁ\\u001b!���\\tޝ��O\\u0012d�\\\"R����g�a��\\u0017H����\\fIҶig����u�*�x\\u0013�x���\\u0010\\\\�\\u0012����j&>��\\u0003c�5�〸��\\u0003͔\\u0015?�M\\u0012l��n�,\\u001d㳅\\u0007z�8\\u0014��jpZ{c,�\\nS9<�,\\tЬS·�����Ҕ�gP37\\u0012B�xW\\u0005_�\\\\�M���b���\\n���:-\\b��\\u0018!��\\u0004�� ]1�\\u0010D�EԦ��<�`讏�\\u0011F�v����L\\ny|�e�2&}���ڛ��\\u0017\\u0012��R��\\b��{I�~�|�\\u000e�\\u00021\\u001dN���5߮N\\u0006h��(f\\f1Hl\\u0011��V8@\\u001b\\u0003E�\\u0017)+�eeR\\n���h�Z\\t\\u0015�[��V�PgR��fU�\\f�i\\u0011��\\u001eE(\\u00014\\\"�c�l�\\\"E�B�����`�2��|\\u000bÆ@�#�*qS��&�\\n\\u0002�\\u0011@�7�\\u001e\\u0001[|��<�\\t��j-�H���t*/��I����\\b6q��8Z`��b[���Y'P�H�\\r�W�\\b\\u001f'4D딴\\u00135��F�c�P��j�פ���\\u000ed��\\u0012\\\"ũRXrg\\u0010I�7π\\u0012�r���7ϔ0�F��\\r�\\\"\\u0004\\u0002�p2h���\\u0000ADy�p���P��\\n�\\\\'�\\u000f\\u001a�T\\u0004\\u000b�\\u0005�&�\\u0017\\u0001���\\u0015sv\\u000f9.+.���\\u0015L�pi�ߤv��Hbȩ��E�T��fe�閹�\\u0010D\\u0010Y��� �+��ΰ�H\\u0012۹\\u001a\\n�\\u0005��\\u0006#K4xB�2�(D�?�}\\u0000iS|�\\u0007fVWx�����\\u0015����e������J�Ε\\u0010p+g��ز���x��C�A�e��xT��Hq�ggл�^#\\u0000�i�ov�\\u0018W���G�\\u0010�k���\\n�2��F�٨)�1�?��t����\\u0000\\nÜ��p��t�?�د�\\\"�\\rIV~W�g�7\\u001bb�t*\\n̯��C�R�r\\t�D�~�*��\\u0006\\u0002G�P\\u0012�%Fo�1�(\\u001dH��%\\bY�\\b��Z���H�\\u001e^X V�r�(�\\u000bd��G���;�4$�t*��e�b�<L�\\u0002N.�\\u0002�\\u000b���\\u0004��C\\u0000EЪʂ�\\u001d�~]�3��J\\u001a��o\\\\TXo\\f\\u0006�����@< PރHD��?�?��?��\\u0011��Pn\\u0013/�\\b\\u0001\\r\\u0002\\rA�\\u001f��)(\\\"\\u0007!�JP \\u001a�\\u0003y�\\u000e\\\\ �6U|I)��x��{pN\\u0019K���\\nO���\\u0005�t�,��a#�7�\\u00046B�_d��\\u000e��'Rr;�]ʉ��H�Q4?\\u0016\\u0004M�\\b���\\b�X?~�\\u000f��\\\"�Rը�<��+˙�7\\nu�xS\\b�����Qy{C\\u001b0\\u0016�*j��\\u0010\\\"���ݼ��ŶQi1�F0���e�R�\\u0011X�� ɂ�QB�J�<��e�_�M\\tE��?O�\\u0004a�\\u0017�[>���m\\\\E�\\u0002l��&\\u001a���{J��\\u0018��\\u0017\\u0003\\u0005A�\\r�\\b��j\\u001c�\\u001e�.�#�<2j}�ҕJ:B�ZK?7\\u0011�6�\\u0011�D\\u0011D�&�B_a/�\\u0004\\u001f#��Q�\\u0018\\u0003��\\u001b�M`���N�`�\\u0018P�o\\u0001��\\u0016�$_\\f\\b�q�V�\\u00079�K1��\\u0000=\\u0010��9)\\u0013�~7\\u001f>��Go�TX���\\u0010\\nTc�*����!��a\\u0013���?\\u001d�X��X\\u0003�\\u001fC O�4�\\\"�!�\\u001e�j��\\u0014i���աE;�3��\\u0000�XM\\u0018\\ta�HԞ]\\tĽ�͵E�\\u0011\\u0002�湔L�D�&��\\r\\\"\\u001c^\\u0014�}�\\u0013�)\\u0014�a*�+����Vt@�jg9a�����C�}��\\r%X*+�A\\u0002��&\\u000b\\f��>�U��R�)�c�\\u001a|M+�-��#@<b��&-떨C\\u0019Am��\\u00034�$ye2J\\u001f[6Ψ�Q��k����*���\\u0018���U\\b��᡾}Đ'Uz��\\u0006�\\u0004�x�*\\t�\\u001e\\u000fW'���p(�J\\u001e\\u0014�z��dX�$����Ȣ�Q�&0n��\\u0005EYs�(n\\u0006����*�%\\f��\\u0003���L�=�>�\\\\��\\u001f�\\u0004�\\u001f\\u0002+Ӕ�W\\u0000�l1��ԑ5�S��Ρ�\\u0003:ȓ/�\\u0015d\\u001cd\\u00032�@#FU\\u0006�2\\u0011�ɺ\\\"��47]�83�\\u001f\\b��\\u0018dl���\\u0004X��f�24��g�\\u0013�(%\\u0010����\\u0016[\\n}5��\\\"�\\u0007�5��'u�\\u000bK��\\tR*#�x�ۙX#G!�t�bH���w�\\u0011�\\u001d�v��Ѱ���t��B�T�\\u0019�t\\b���>����F\\u0002�\\u0014]\\rp^2�����e\\u0012p@X�w9\\u0004a�n�X��)\\u0002@F��\\u0002@� �h>J&mAع!�u=���}T\\u0011\\u001d\\u0011�QW��3A�M@�C����\\\\���\\u0013\\\"���F�����d+����\\u0002�O�Q�\\u0015\\u0012\\u0017�B�����q&��ռ\\b�W�\\u0016���:5�sz%)�\\t\\u0017y�R#�\\u000b����|Rƾr%\\u0017�fr�_\\u0007\\u0006\\r��yE�-\\u0006�\\u0019�p&�_�7D���4��w@�\\\"ݰ0�U�Yb\\u001f�!�(�epQ�~\\\"�V\\nvQ�߷�q\\\\y�6\\u0013\\u0001�G\\u0019YR�_\\n\\u0016�U�\\u0012������ݐ���\\u000eoP؁cZ&�\\n�4\\u0019\\u0010�\\u0002Rf{`��P\\u001ah��;N�\\u000b�\\u0010�H(�\\u0016T����\\b7^��ΕZ�\\r��n�[��\\u0011������\\u0004x�.��_3��O���D\\u001b���\\rE�F\\\"D��(�33��tu��\\u0016ᒯu�t\\u0000\\u0016\\u0011��\\u0015`Rh��a�Z�(DJ\\u001d�$\\u0004l�0���A\\t��H2�\\\"�^H\\\"�y1���e\\u0011�@-�oo��jΛ��]�\\u001c�~!�H��\\u000f�l\\u0014]S�3���3V�\\u0006YX�\\u0010�\\u000b\\u000e�C�g�~� AG�I6�\\u000e����ם�3\\u0006B�Zc���ĉ\\u0001��\\u0005��#Lv�-C�P,V�@���+�ԘáQL�\\u0019s\\n�$�E�ϖa,A\\u0003�#R\\u0010�\\u000b���\\u0001�fW�d�R�60�\\u0019�C\\u0001���\\t�i\\t�d\\u0019f����T:H\\u0001����'�\\tg�\\\"P�4� I9��U^�@�%2E.���h�\\u0004�\\u0012E\\b\\u000f�:��h\\u001e\\u0010�\\u0000|�\\n\\u0014��հ����!O:��:f��Ŏ��\\f��hs\\u0018\\u001f��>\\f2�E<qIΒ�\\u0016F�w\\n��^h\\u001e�\\u0012\\u0002�cHd���HE�[\\u000bM��t)�Z9�\\u000bDT=�L�cN�XJ\\u0010�D˴�����4\\f��#~%4z�K�\\u0000����o)݉ ��۩0]�P-�\\u0006�+�p���2g<�ߧ�}�,`�n�I��{�_�'F\\u000e���\\u0003�c5\\u00008̩�\\u0014��@ܲ|\\u0016��\\\\N\\u001b4T����X������%�c\\u0010�kx\\b6D,\\u0013fXU\\u0011h\\\\\\nw��9�R5`h��2�ܶ��b�\\u0018�\\u0005\\u0018v��O���3�Q=�ԛ�\\u0012\\nQ>���}�\\u0013���vn�rQ�V��l\\u0010�\\u0005\\u0005֎�F��\\u0003�\\u0005e\\u0007�J���\\u0019K���(d�l����u0����@U�^\\u001d���_~��B\\u0003\\u0015�r��.�\\u0011�*h�E{\\u0000�X\\u000fI�������x9>��g\\u0018�c�����}���~�\\u000f>nN�\\u0012̥Z��d�d\\u000e�a��+3D�6wp;\\u0000�a�O��\\u0000E�~*�Mͪ�\\u001d\\\\��������G�G]>lyN��a�D�JI%B,G\\u0002\\u0007�,���K��͸3�t��2��4\\u0001�l�G@���\\u0001{������\\u0003k\\u001c���\\u0000\\u0018�\\u0000d?�\\u001c�$.�\\u0010CD���0���\\u0000��7d:[�����>\\u000e}��\\u001b\\f�\\u0014)_蒾3˒]�\\t��[\\u0003\\u0018��ӝ7���\\u000e\\f\\u0003��#;�>�\\u0005PO��f\\u0007\\r�c\\u0015���&�\\u000fa\\u0007ul��h\\b=�w\\u0017\\u0013�!�X�œ@w�/�z�]��Yaw\\u0012�[�t�f���$��E��\\\\�.��-�vW�!��\\u0000��^�J����26\\u001e\\u001f�U����in����h����%���\\u0014+\\u0006\\bW�;���n\\\"1\\u0014]�C�?`��\\u001c�,i(�����\\u0018-����+G�օ1�L����;��3QͿs'\\u00029�@��ѭ�N>�]aӡ�&�6\\t�G\\u0007\\r2��`\\u0002QIB\\u0010�N�\\u0003\\u0000�R\\tw�\\u0001c�\\u001a\\u000b4\\u001fR��>\\u000f\\u0012\\u0011�ʚ�\\u0010M�v\\u0011��.�u�'3��ʉ\\u000b:�o\\u0011\\u0003\\\"��Zg?�%��h�\\u001f�����~�Hg\\u0005���٬$%���&]�\\u0006�'gFOa�̓q4nx<\\u001b�>\\\"J\\u0019�r��\\u0007Ϣu��G^��}�\\u0012����\\u0012�A�����5c��B��Z�X�b�\\u0019��'�nQi0�3�anL'�u�e[\\u0006\\u0007�<Hm%./��1K0�m��[ک�\\f\\u00163��;=\\\\@�:xh �f�M>1�Q/u\\u0018\\u0002�0G����\\fab�-�_j�!7\\u0013Ƿ�2Gng���u\\u0001\\\"�#��GRc�\\u0019�����+�+�I�\\u0010��2�;�W���]n)�\\u0016D��\\u001d&���3=�!ض�7�yș>\\f�\\u0011ߊ��:�W/-\\u0017\\u001c�\\u0015Q6qW,WEn�\\tVL�_N\\u0019�|YkكZ�z��T�n,P<8x���9��A�I\\u0015I��\\u001e�-b(<�i��.I�;\\u0000��\\u000e�m\\u0000I�^�\\u000f��/0\\u001c\\u0000�񀐄}ۂ{P�E7.���3{�H��[^`<J�/S���\\u0014��R�!�\\u0004F�R��;�8��0wO\\r���\\u0016U.��\\u0000g�#T��<\\u0013ɭ����o\\u0000��@_��E����N��\\u000eG�L��}.8�v�\\u001aC�u�M�L��a�3Ӣ���I\\u001d8�\\u001d�HZ�u�������@1\\u000bF��\\u0003�H&L�$�\\t&��\\u0011�\\\"�0��3R)�(�\\r\\u0012\\u0011��]�p\\t*\\u0006�t:\\u0017�\\u000f<��\\u001f��1�&�w'\\u001f�\\r�S���\\u000f\\u0006L�}07M��\\bp�۠r\\u001b�\\u0014�;^�\\r��g_�-\\u0000\\u000fhŜ���6��+\\r�\\u0006\\u0013[��\\b\\u0017.����S!һK\\\\u��EQ`\\nbW8\\u0001%�l�\\tB�x��\\u00038$;K\\u0006{k�B�\\u001dc\\\"��`gr:;)e��M�����\\u0007ၢ%W����Sv$j�Z�?9\\u0000d�\\u000e���$-m2�p��+��ě\\u0011�\\u0005>Qu5q�|�2\\u0000��?\\u000f�\\\\�**!��� �S�%YiQC��U|\\r�&gy�V\\u001e��\\\\\\u000ba[u��Щ\\u00135��W\\b\\fݖ�����\\u0004���@�����=���=�t\\u00059(Z\\u0015�*\\u000b<�U��D���j)�\\u000b\\u001d\\\\j\\u0017�\\u000b�C��B/�ts�|U�v��zUL\\u001b�EB�\\\"��\\u000bz`{8)\\f���Z�q(�E��\\u0007\\\"uE��e\\u001c\\u0005E��\\u0016�\\u0010[�\\u001af�\\u0005�p)��K�L�R���M�A�+lG\\u0015۔$�\\u0014%�լ��5��,���\\u000bZ�@*Y�\\u0007���ͦ\\u0014��P�f��\\u00161\\u0006F�t\\u00012\\u0011�Imm�\\u0005����~��M�\\u0013�w`\\u000bxJ�\\u000e# ���\\u0000�ErH2t��F�.�\\u0012\\u0000�VPEl�*O\\u0005�ɪ;\\u0010\\u0007�\\u0014ai<��(*�\\\"RF�'��~�UO*W�e��pچ6K\\u0012|��Рv2�{��.6\\u001e�jNq��\\t�\\u0006:I���y\\u000eg\\u0019��L�\\u0019.�������\\u0010�:�\\u0007\\\\���,���`\\u000e0\\u000bx���`)\\u0016S �\\u0014��\\u001b@zw\\u0016QE�n�^/\\u0017!�\\u0018?\\u000f�\\u000b�ƅ�Q��\\u001ae\\u0016r\\n���\\u0013��� ��*\\u000b;����&�\\\"T�H�ϥ�\\u0007hP \\u0010��CQĎ4ON\\u0006=����\\u001e�zc�\\u001c\\\"~\\u0013\\u000e\\u001at�E&X!u\\u0005%�r���E�\\u0011�A�02t�\\u0016\\bs�\\u0002F\\u0002)\\u00106E8����\\u0010�c=\\u000e�\\u001b\\u0010��j0 ��j�\\f6���\\u001e\\u0004׊\\u001a#�X\\u0001:�H\\u0013hD�)�\\u0005\\u0012�!����\\u0016\\u0000V0�C@\\b\\u00187 ���\\u0006�\\u001e\\u0000S�\\u001c�c\\u000e�4\\u0000�\\u0007�#�[@�ac\\u0004|\\u0013�'��@m��\\u000107\\u0005�\\u000fP\\u0015p6�\\u001d\\u0000�\\u0006�\\u0014�`A�\\u0006X\\u000e\\u0001-���\\n0m�c(E\\u001e��\\u0001�:\\u0000��*\\u0019��w��8X\\u0001u��T\\u0002�Aʤ\\u0015�\\u0000\\u0004�\\u001c�\\u0000<�~ E18v��n�\\b�?$\\u0010�X(\\\\n�^\\u001f�\\t��3�Zp\\u0001��<\\\\4�\\u0002D�u\\u0012\\t��e�\\u0000���q(�8mn\\u001c)6\\b�p\\u0001�P\\u0001s0\\u0001\\u0013 \\u0000��\\u0002��\\u0004�\\u0000\\u0007Հ\\u000f+\\u0000\\u0018R\\u0000(�\\u0000I(\\u0000�P\\u0000�`\\u0001'�;\\u000f\\u0000s\\u001c\\u0000�0\\u0001�T9|T9|L9dL9TD9>@8� \\u0018Y\\r\\f$Ɔ\\u000f��@``�0@�0@V,@\\\"(@\\u0004$C|H���\\f��\\u000b����c\\n�@\\u0015b�)\\u0005\\u0000c�\\u0000�\\f\\u0018�\\n\\u0018�\\n\\u0018�\\u0002\\u0018��1+�b\\u001b��\\u000fA�'A��\\u0003`��\\u0001��\\u0002�@\\u0003:�y�\\u0001٘\\u0006�`\\u001a\\u0019�n�\\u0001��\\u0006~ \\u0018X�`�\\u0001c�\\u0005n\\u0000\\u0014X\\u0000I`\\u0001\\u000fp\\u0003f�\\u0005ݰ\\u0015v@MY\\u0000�d\\u0002�p\\tU�\\u001a�\\u0001���6/�2\\f��\\u001f\\u001cGA\\n�D\\u001f/q\\u001bb���\\u001e��j\\u001b�m�L�=\\u0013\\u0018�L]L��\\u0013;/R@�\\u001c\\u000eq@�\\u0014���5C1�\\u0019���d�b\\rه�f\\u001c\\u001d�gvؼ�\\u0005� ,90�����\\u0002/�~}�O�o�淊��#;�#�\\u001dڜs��g\\u0014\\u0017����a]��{0\\u0012ـ��\\u0006� 4/\\u0001�x\\u000bK�P^\\u0002r�\\u0010\\u0017�t�\\u0002ՠc�\\u0003\\u001dH\\u0016�@�R\\u0005b�%ԁ\\u001a�\\b��=#\\u0001�\\b\\u0010H@yB\\u0003��\\u001bπ�l\\u0006\\u0013`.�\\u0001T�\\n%�E.\\u0000��\\u0001��}�\\u0003ب\\u001c�@�*\\u0004Di�ɘ�$\\u0019�1\\u0004w��yv�ݳV�8\\u0003�\\u0010�07�\\u0013�F�H�.���\\u0018�Ɵ8��J�\\u001f@\\u0000\\u0000\\u0001\\u0003\\u0001`\\u0000\\u0000\\u0015�'��\\u0010�`\\u0004\\\\LT���\\u0002A\\u0018p\\u0012Bs�)r�!�\\n�(\\n\\u0003�\\u0004i�`\",\"glyphicons-halflings-regular.svg\":\"<?xml version=\\\"1.0\\\" standalone=\\\"no\\\"?>\\n<!DOCTYPE svg PUBLIC \\\"-//W3C//DTD SVG 1.1//EN\\\" \\\"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\\\" >\\n<svg xmlns=\\\"http://www.w3.org/2000/svg\\\">\\n<metadata></metadata>\\n<defs>\\n<font id=\\\"glyphicons_halflingsregular\\\" horiz-adv-x=\\\"1200\\\" >\\n<font-face units-per-em=\\\"1200\\\" ascent=\\\"960\\\" descent=\\\"-240\\\" />\\n<missing-glyph horiz-adv-x=\\\"500\\\" />\\n<glyph />\\n<glyph />\\n<glyph unicode=\\\" \\\" />\\n<glyph unicode=\\\"*\\\" d=\\\"M1100 500h-259l183 -183l-141 -141l-183 183v-259h-200v259l-183 -183l-141 141l183 183h-259v200h259l-183 183l141 141l183 -183v259h200v-259l183 183l141 -141l-183 -183h259v-200z\\\" />\\n<glyph unicode=\\\"+\\\" d=\\\"M1100 400h-400v-400h-300v400h-400v300h400v400h300v-400h400v-300z\\\" />\\n<glyph unicode=\\\"&#xa0;\\\" />\\n<glyph unicode=\\\"&#x2000;\\\" horiz-adv-x=\\\"652\\\" />\\n<glyph unicode=\\\"&#x2001;\\\" horiz-adv-x=\\\"1304\\\" />\\n<glyph unicode=\\\"&#x2002;\\\" horiz-adv-x=\\\"652\\\" />\\n<glyph unicode=\\\"&#x2003;\\\" horiz-adv-x=\\\"1304\\\" />\\n<glyph unicode=\\\"&#x2004;\\\" horiz-adv-x=\\\"434\\\" />\\n<glyph unicode=\\\"&#x2005;\\\" horiz-adv-x=\\\"326\\\" />\\n<glyph unicode=\\\"&#x2006;\\\" horiz-adv-x=\\\"217\\\" />\\n<glyph unicode=\\\"&#x2007;\\\" horiz-adv-x=\\\"217\\\" />\\n<glyph unicode=\\\"&#x2008;\\\" horiz-adv-x=\\\"163\\\" />\\n<glyph unicode=\\\"&#x2009;\\\" horiz-adv-x=\\\"260\\\" />\\n<glyph unicode=\\\"&#x200a;\\\" horiz-adv-x=\\\"72\\\" />\\n<glyph unicode=\\\"&#x202f;\\\" horiz-adv-x=\\\"260\\\" />\\n<glyph unicode=\\\"&#x205f;\\\" horiz-adv-x=\\\"326\\\" />\\n<glyph unicode=\\\"&#x20ac;\\\" d=\\\"M800 500h-300q9 -74 33 -132t52.5 -91t62 -54.5t59 -29t46.5 -7.5q29 0 66 13t75 37t63.5 67.5t25.5 96.5h174q-31 -172 -128 -278q-107 -117 -274 -117q-205 0 -324 158q-36 46 -69 131.5t-45 205.5h-217l100 100h113q0 47 5 100h-218l100 100h135q37 167 112 257 q117 141 297 141q242 0 354 -189q60 -103 66 -209h-181q0 55 -25.5 99t-63.5 68t-75 36.5t-67 12.5q-24 0 -52.5 -10t-62.5 -32t-65.5 -67t-50.5 -107h379l-100 -100h-300q-6 -46 -6 -100h406z\\\" />\\n<glyph unicode=\\\"&#x2212;\\\" d=\\\"M1100 700h-900v-300h900v300z\\\" />\\n<glyph unicode=\\\"&#x2601;\\\" d=\\\"M178 300h750q120 0 205 86t85 208q0 120 -85 206.5t-205 86.5q-46 0 -90 -14q-44 97 -134.5 156.5t-200.5 59.5q-152 0 -260 -107.5t-108 -260.5q0 -25 2 -37q-66 -14 -108.5 -67.5t-42.5 -122.5q0 -80 56.5 -137t135.5 -57z\\\" />\\n<glyph unicode=\\\"&#x2709;\\\" d=\\\"M1200 1100h-1200l600 -603zM300 600l-300 -300v600zM1200 900v-600l-300 300zM800 500l400 -400h-1200l400 400l200 -200z\\\" />\\n<glyph unicode=\\\"&#x270f;\\\" d=\\\"M1101 889l99 92q13 13 13 32.5t-13 33.5l-153 153q-15 13 -33 13t-33 -13l-94 -97zM401 189l614 614l-214 214l-614 -614zM-13 -13l333 112l-223 223z\\\" />\\n<glyph unicode=\\\"&#xe000;\\\" horiz-adv-x=\\\"500\\\" d=\\\"M0 0z\\\" />\\n<glyph unicode=\\\"&#xe001;\\\" d=\\\"M700 100h300v-100h-800v100h300v550l-500 550h1200l-500 -550v-550z\\\" />\\n<glyph unicode=\\\"&#xe002;\\\" d=\\\"M1000 934v-521q-64 16 -138 -7q-79 -26 -122.5 -83t-25.5 -111q17 -55 85.5 -75.5t147.5 4.5q70 23 111.5 63.5t41.5 95.5v881q0 10 -7 15.5t-17 2.5l-752 -193q-10 -3 -17 -12.5t-7 -19.5v-689q-64 17 -138 -7q-79 -25 -122.5 -82t-25.5 -112t86 -75.5t147 5.5 q65 21 109 69t44 90v606z\\\" />\\n<glyph unicode=\\\"&#xe003;\\\" d=\\\"M913 432l300 -300q7 -8 7 -18t-7 -18l-109 -109q-8 -7 -18 -7t-18 7l-300 300q-119 -78 -261 -78q-200 0 -342 142t-142 342t142 342t342 142t342 -142t142 -342q0 -142 -78 -261zM176 693q0 -136 97 -233t234 -97t233.5 96.5t96.5 233.5t-96.5 233.5t-233.5 96.5 t-234 -97t-97 -233z\\\" />\\n<glyph unicode=\\\"&#xe005;\\\" d=\\\"M649 949q48 69 109.5 105t121.5 38t118.5 -20.5t102.5 -64t71 -100.5t27 -123q0 -57 -33.5 -117.5t-94 -124.5t-126.5 -127.5t-150 -152.5t-146 -174q-62 85 -145.5 174t-149.5 152.5t-126.5 127.5t-94 124.5t-33.5 117.5q0 64 28 123t73 100.5t104.5 64t119 20.5 t120 -38.5t104.5 -104.5z\\\" />\\n<glyph unicode=\\\"&#xe006;\\\" d=\\\"M791 522l145 -449l-384 275l-382 -275l146 447l-388 280h479l146 400h2l146 -400h472zM168 71l2 1z\\\" />\\n<glyph unicode=\\\"&#xe007;\\\" d=\\\"M791 522l145 -449l-384 275l-382 -275l146 447l-388 280h479l146 400h2l146 -400h472zM747 331l-74 229l193 140h-235l-77 211l-78 -211h-239l196 -142l-73 -226l192 140zM168 71l2 1z\\\" />\\n<glyph unicode=\\\"&#xe008;\\\" d=\\\"M1200 143v-143h-1200v143l400 257v100q-37 0 -68.5 74.5t-31.5 125.5v200q0 124 88 212t212 88t212 -88t88 -212v-200q0 -51 -31.5 -125.5t-68.5 -74.5v-100z\\\" />\\n<glyph unicode=\\\"&#xe009;\\\" d=\\\"M1200 1100v-1100h-1200v1100h1200zM200 1000h-100v-100h100v100zM900 1000h-600v-400h600v400zM1100 1000h-100v-100h100v100zM200 800h-100v-100h100v100zM1100 800h-100v-100h100v100zM200 600h-100v-100h100v100zM1100 600h-100v-100h100v100zM900 500h-600v-400h600 v400zM200 400h-100v-100h100v100zM1100 400h-100v-100h100v100zM200 200h-100v-100h100v100zM1100 200h-100v-100h100v100z\\\" />\\n<glyph unicode=\\\"&#xe010;\\\" d=\\\"M500 1050v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5v400q0 21 14.5 35.5t35.5 14.5h400q21 0 35.5 -14.5t14.5 -35.5zM1100 1050v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5v400q0 21 14.5 35.5t35.5 14.5h400 q21 0 35.5 -14.5t14.5 -35.5zM500 450v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5v400q0 21 14.5 35.5t35.5 14.5h400q21 0 35.5 -14.5t14.5 -35.5zM1100 450v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5v400 q0 21 14.5 35.5t35.5 14.5h400q21 0 35.5 -14.5t14.5 -35.5z\\\" />\\n<glyph unicode=\\\"&#xe011;\\\" d=\\\"M300 1050v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5h200q21 0 35.5 -14.5t14.5 -35.5zM700 1050v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5h200 q21 0 35.5 -14.5t14.5 -35.5zM1100 1050v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5h200q21 0 35.5 -14.5t14.5 -35.5zM300 650v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v200 q0 21 14.5 35.5t35.5 14.5h200q21 0 35.5 -14.5t14.5 -35.5zM700 650v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5h200q21 0 35.5 -14.5t14.5 -35.5zM1100 650v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200 q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5h200q21 0 35.5 -14.5t14.5 -35.5zM300 250v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5h200q21 0 35.5 -14.5t14.5 -35.5zM700 250v-200 q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5h200q21 0 35.5 -14.5t14.5 -35.5zM1100 250v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5h200q21 0 35.5 -14.5 t14.5 -35.5z\\\" />\\n<glyph unicode=\\\"&#xe012;\\\" d=\\\"M300 1050v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5h200q21 0 35.5 -14.5t14.5 -35.5zM1200 1050v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-700q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5h700 q21 0 35.5 -14.5t14.5 -35.5zM300 450v200q0 21 -14.5 35.5t-35.5 14.5h-200q-21 0 -35.5 -14.5t-14.5 -35.5v-200q0 -21 14.5 -35.5t35.5 -14.5h200q21 0 35.5 14.5t14.5 35.5zM1200 650v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-700q-21 0 -35.5 14.5t-14.5 35.5v200 q0 21 14.5 35.5t35.5 14.5h700q21 0 35.5 -14.5t14.5 -35.5zM300 250v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5h200q21 0 35.5 -14.5t14.5 -35.5zM1200 250v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-700 q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5h700q21 0 35.5 -14.5t14.5 -35.5z\\\" />\\n<glyph unicode=\\\"&#xe013;\\\" d=\\\"M448 34l818 820l-212 212l-607 -607l-206 207l-212 -212z\\\" />\\n<glyph unicode=\\\"&#xe014;\\\" d=\\\"M882 106l-282 282l-282 -282l-212 212l282 282l-282 282l212 212l282 -282l282 282l212 -212l-282 -282l282 -282z\\\" />\\n<glyph unicode=\\\"&#xe015;\\\" d=\\\"M913 432l300 -300q7 -8 7 -18t-7 -18l-109 -109q-8 -7 -18 -7t-18 7l-300 300q-119 -78 -261 -78q-200 0 -342 142t-142 342t142 342t342 142t342 -142t142 -342q0 -142 -78 -261zM507 363q137 0 233.5 96.5t96.5 233.5t-96.5 233.5t-233.5 96.5t-234 -97t-97 -233 t97 -233t234 -97zM600 800h100v-200h-100v-100h-200v100h-100v200h100v100h200v-100z\\\" />\\n<glyph unicode=\\\"&#xe016;\\\" d=\\\"M913 432l300 -299q7 -7 7 -18t-7 -18l-109 -109q-8 -8 -18 -8t-18 8l-300 299q-120 -77 -261 -77q-200 0 -342 142t-142 342t142 342t342 142t342 -142t142 -342q0 -141 -78 -262zM176 694q0 -136 97 -233t234 -97t233.5 97t96.5 233t-96.5 233t-233.5 97t-234 -97 t-97 -233zM300 801v-200h400v200h-400z\\\" />\\n<glyph unicode=\\\"&#xe017;\\\" d=\\\"M700 750v400q0 21 -14.5 35.5t-35.5 14.5h-100q-21 0 -35.5 -14.5t-14.5 -35.5v-400q0 -21 14.5 -35.5t35.5 -14.5h100q21 0 35.5 14.5t14.5 35.5zM800 975v166q167 -62 272 -210t105 -331q0 -118 -45.5 -224.5t-123 -184t-184 -123t-224.5 -45.5t-224.5 45.5t-184 123 t-123 184t-45.5 224.5q0 183 105 331t272 210v-166q-103 -55 -165 -155t-62 -220q0 -177 125 -302t302 -125t302 125t125 302q0 120 -62 220t-165 155z\\\" />\\n<glyph unicode=\\\"&#xe018;\\\" d=\\\"M1200 1h-200v1200h200v-1200zM900 1h-200v800h200v-800zM600 1h-200v500h200v-500zM300 301h-200v-300h200v300z\\\" />\\n<glyph unicode=\\\"&#xe019;\\\" d=\\\"M488 183l38 -151q40 -5 74 -5q27 0 74 5l38 151l6 2q46 13 93 39l5 3l134 -81q56 44 104 105l-80 134l3 5q24 44 39 93l1 6l152 38q5 40 5 74q0 28 -5 73l-152 38l-1 6q-16 51 -39 93l-3 5l80 134q-44 58 -104 105l-134 -81l-5 3q-45 25 -93 39l-6 1l-38 152q-40 5 -74 5 q-27 0 -74 -5l-38 -152l-5 -1q-50 -14 -94 -39l-5 -3l-133 81q-59 -47 -105 -105l80 -134l-3 -5q-25 -47 -38 -93l-2 -6l-151 -38q-6 -48 -6 -73q0 -33 6 -74l151 -38l2 -6q14 -49 38 -93l3 -5l-80 -134q45 -59 105 -105l133 81l5 -3q45 -26 94 -39zM600 815q89 0 152 -63 t63 -151q0 -89 -63 -152t-152 -63t-152 63t-63 152q0 88 63 151t152 63z\\\" />\\n<glyph unicode=\\\"&#xe020;\\\" d=\\\"M900 1100h275q10 0 17.5 -7.5t7.5 -17.5v-50q0 -11 -7 -18t-18 -7h-1050q-11 0 -18 7t-7 18v50q0 10 7.5 17.5t17.5 7.5h275v100q0 41 29.5 70.5t70.5 29.5h300q41 0 70.5 -29.5t29.5 -70.5v-100zM800 1100v100h-300v-100h300zM200 900h900v-800q0 -41 -29.5 -71 t-70.5 -30h-700q-41 0 -70.5 30t-29.5 71v800zM300 100h100v700h-100v-700zM500 100h100v700h-100v-700zM700 100h100v700h-100v-700zM900 100h100v700h-100v-700z\\\" />\\n<glyph unicode=\\\"&#xe021;\\\" d=\\\"M1301 601h-200v-600h-300v400h-300v-400h-300v600h-200l656 644z\\\" />\\n<glyph unicode=\\\"&#xe022;\\\" d=\\\"M600 700h400v-675q0 -11 -7 -18t-18 -7h-850q-11 0 -18 7t-7 18v1150q0 11 7 18t18 7h475v-500zM1000 800h-300v300z\\\" />\\n<glyph unicode=\\\"&#xe023;\\\" d=\\\"M600 1196q162 0 299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299t80 299t217 217t299 80zM600 1014q-171 0 -292.5 -121.5t-121.5 -292.5t121.5 -292.5t292.5 -121.5t292.5 121.5t121.5 292.5t-121.5 292.5t-292.5 121.5zM600 600h200 v-100h-300v400h100v-300z\\\" />\\n<glyph unicode=\\\"&#xe024;\\\" d=\\\"M721 400h-242l-40 -400h-539l431 1200h209l-21 -300h162l-20 300h208l431 -1200h-538zM712 500l-27 300h-170l-27 -300h224z\\\" />\\n<glyph unicode=\\\"&#xe025;\\\" d=\\\"M1100 400v-400h-1100v400h490l-290 300h200v500h300v-500h200l-290 -300h490zM988 300h-175v-100h175v100z\\\" />\\n<glyph unicode=\\\"&#xe026;\\\" d=\\\"M600 1199q122 0 233 -47.5t191 -127.5t127.5 -191t47.5 -233t-47.5 -233t-127.5 -191t-191 -127.5t-233 -47.5t-233 47.5t-191 127.5t-127.5 191t-47.5 233t47.5 233t127.5 191t191 127.5t233 47.5zM600 1012q-170 0 -291 -121t-121 -291t121 -291t291 -121t291 121 t121 291t-121 291t-291 121zM700 600h150l-250 -300l-250 300h150v300h200v-300z\\\" />\\n<glyph unicode=\\\"&#xe027;\\\" d=\\\"M600 1196q162 0 299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299t80 299t217 217t299 80zM600 1014q-171 0 -292.5 -121.5t-121.5 -292.5t121.5 -292.5t292.5 -121.5t292.5 121.5t121.5 292.5t-121.5 292.5t-292.5 121.5zM850 600h-150 v-300h-200v300h-150l250 300z\\\" />\\n<glyph unicode=\\\"&#xe028;\\\" d=\\\"M0 500l200 700h800q199 -700 200 -700v-475q0 -11 -7 -18t-18 -7h-1150q-11 0 -18 7t-7 18v475zM903 1000h-606l-97 -500h200l50 -200h300l50 200h200z\\\" />\\n<glyph unicode=\\\"&#xe029;\\\" d=\\\"M600 1196q162 0 299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299t80 299t217 217t299 80zM600 1014q-171 0 -292.5 -121.5t-121.5 -292.5q0 -172 121.5 -293t292.5 -121t292.5 121t121.5 293q0 171 -121.5 292.5t-292.5 121.5zM797 598 l-297 -201v401z\\\" />\\n<glyph unicode=\\\"&#xe030;\\\" d=\\\"M1177 600h-150q0 -177 -125 -302t-302 -125t-302 125t-125 302t125 302t302 125q136 0 246 -81l-146 -146h400v400l-145 -145q-157 122 -355 122q-118 0 -224.5 -45.5t-184 -123t-123 -184t-45.5 -224.5t45.5 -224.5t123 -184t184 -123t224.5 -45.5t224.5 45.5t184 123 t123 184t45.5 224.5z\\\" />\\n<glyph unicode=\\\"&#xe031;\\\" d=\\\"M700 800l147 147q-112 80 -247 80q-177 0 -302 -125t-125 -302h-150q0 118 45.5 224.5t123 184t184 123t224.5 45.5q198 0 355 -122l145 145v-400h-400zM500 400l-147 -147q112 -80 247 -80q177 0 302 125t125 302h150q0 -118 -45.5 -224.5t-123 -184t-184 -123 t-224.5 -45.5q-198 0 -355 122l-145 -145v400h400z\\\" />\\n<glyph unicode=\\\"&#xe032;\\\" d=\\\"M100 1200v-1200h1100v1200h-1100zM1100 100h-900v900h900v-900zM400 800h-100v100h100v-100zM1000 800h-500v100h500v-100zM400 600h-100v100h100v-100zM1000 600h-500v100h500v-100zM400 400h-100v100h100v-100zM1000 400h-500v100h500v-100zM400 200h-100v100h100v-100 zM1000 300h-500v-100h500v100z\\\" />\\n<glyph unicode=\\\"&#xe034;\\\" d=\\\"M200 0h-100v1100h100v-1100zM1100 600v500q-40 -81 -101.5 -115.5t-127.5 -29.5t-138 25t-139.5 40t-125.5 25t-103 -29.5t-65 -115.5v-500q60 60 127.5 84t127.5 17.5t122 -23t119 -30t110 -11t103 42t91 120.5z\\\" />\\n<glyph unicode=\\\"&#xe035;\\\" d=\\\"M1200 275v300q0 116 -49.5 227t-131 192.5t-192.5 131t-227 49.5t-227 -49.5t-192.5 -131t-131 -192.5t-49.5 -227v-300q0 -11 7 -18t18 -7h50q11 0 18 7t7 18v300q0 127 70.5 231.5t184.5 161.5t245 57t245 -57t184.5 -161.5t70.5 -231.5v-300q0 -11 7 -18t18 -7h50 q11 0 18 7t7 18zM400 480v-460q0 -8 -6 -14t-14 -6h-160q-8 0 -14 6t-6 14v460q0 8 6 14t14 6h160q8 0 14 -6t6 -14zM1000 480v-460q0 -8 -6 -14t-14 -6h-160q-8 0 -14 6t-6 14v460q0 8 6 14t14 6h160q8 0 14 -6t6 -14z\\\" />\\n<glyph unicode=\\\"&#xe036;\\\" d=\\\"M0 800v-400h300l300 -200v800l-300 -200h-300zM971 600l141 -141l-71 -71l-141 141l-141 -141l-71 71l141 141l-141 141l71 71l141 -141l141 141l71 -71z\\\" />\\n<glyph unicode=\\\"&#xe037;\\\" d=\\\"M0 800v-400h300l300 -200v800l-300 -200h-300zM700 857l69 53q111 -135 111 -310q0 -169 -106 -302l-67 54q86 110 86 248q0 146 -93 257z\\\" />\\n<glyph unicode=\\\"&#xe038;\\\" d=\\\"M974 186l6 8q142 178 142 405q0 230 -144 408l-6 8l-83 -64l7 -8q123 -151 123 -344q0 -189 -119 -339l-7 -8zM300 801l300 200v-800l-300 200h-300v400h300zM702 858l69 53q111 -135 111 -310q0 -170 -106 -303l-67 55q86 110 86 248q0 145 -93 257z\\\" />\\n<glyph unicode=\\\"&#xe039;\\\" d=\\\"M100 700h400v100h100v100h-100v300h-500v-600h100v100zM1200 700v500h-600v-200h100v-300h200v-300h300v200h-200v100h200zM100 1100h300v-300h-300v300zM800 800v300h300v-300h-300zM200 900h100v100h-100v-100zM900 1000h100v-100h-100v100zM300 600h-100v-100h-200 v-500h500v500h-200v100zM900 200v-100h-200v100h-100v100h100v200h-200v100h300v-300h200v-100h-100zM400 400v-300h-300v300h300zM300 200h-100v100h100v-100zM1100 300h100v-100h-100v100zM600 100h100v-100h-100v100zM1200 100v-100h-300v100h300z\\\" />\\n<glyph unicode=\\\"&#xe040;\\\" d=\\\"M100 1200h-100v-1000h100v1000zM300 200h-100v1000h100v-1000zM700 200h-200v1000h200v-1000zM900 200h-100v1000h100v-1000zM1200 1200v-1000h-200v1000h200zM400 100v-100h-300v100h300zM500 91h100v-91h-100v91zM700 91h100v-91h-100v91zM1100 91v-91h-200v91h200z \\\" />\\n<glyph unicode=\\\"&#xe041;\\\" d=\\\"M1200 500l-500 -500l-699 700v475q0 10 7.5 17.5t17.5 7.5h474zM320 882q29 29 29 71t-29 71q-30 30 -71.5 30t-71.5 -30q-29 -29 -29 -71t29 -71q30 -30 71.5 -30t71.5 30z\\\" />\\n<glyph unicode=\\\"&#xe042;\\\" d=\\\"M1201 500l-500 -500l-699 700v475q0 11 7 18t18 7h474zM1501 500l-500 -500l-50 50l450 450l-700 700h100zM320 882q30 29 30 71t-30 71q-29 30 -71 30t-71 -30q-30 -29 -30 -71t30 -71q29 -30 71 -30t71 30z\\\" />\\n<glyph unicode=\\\"&#xe043;\\\" d=\\\"M1200 1200v-1000l-100 -100v1000h-750l-100 -100h750v-1000h-900v1025l175 175h925z\\\" />\\n<glyph unicode=\\\"&#xe045;\\\" d=\\\"M947 829l-94 346q-2 11 -10 18t-18 7h-450q-10 0 -18 -7t-10 -18l-94 -346l40 -124h592zM1200 800v-700h-200v200h-800v-200h-200v700h200l100 -200h600l100 200h200zM881 176l38 -152q2 -10 -3.5 -17t-15.5 -7h-600q-10 0 -15.5 7t-3.5 17l38 152q2 10 11.5 17t19.5 7 h500q10 0 19.5 -7t11.5 -17z\\\" />\\n<glyph unicode=\\\"&#xe047;\\\" d=\\\"M1200 0v66q-34 1 -74 43q-18 19 -33 42t-21 37l-6 13l-385 998h-93l-399 -1006q-24 -48 -52 -75q-12 -12 -33 -25t-36 -20l-15 -7v-66h365v66q-41 0 -72 11t-49 38t1 71l92 234h391l82 -222q16 -45 -5.5 -88.5t-74.5 -43.5v-66h417zM416 521l178 457l46 -140l116 -317 h-340z\\\" />\\n<glyph unicode=\\\"&#xe048;\\\" d=\\\"M100 1199h471q120 0 213 -88t93 -228q0 -55 -11.5 -101.5t-28 -74t-33.5 -47.5t-28 -28l-12 -7q8 -3 21.5 -9t48 -31.5t60.5 -58t47.5 -91.5t21.5 -129q0 -84 -59 -156.5t-142 -111t-162 -38.5h-500v89q41 7 70.5 32.5t29.5 65.5v827q0 28 -1 39.5t-5.5 26t-15.5 21 t-29 14t-49 14.5v70zM400 1079v-379h139q76 0 130 61.5t54 138.5q0 82 -84 130.5t-239 48.5zM400 200h161q89 0 153 48.5t64 132.5q0 90 -62.5 154.5t-156.5 64.5h-159v-400z\\\" />\\n<glyph unicode=\\\"&#xe049;\\\" d=\\\"M877 1200l2 -57q-33 -8 -62 -25.5t-46 -37t-29.5 -38t-17.5 -30.5l-5 -12l-128 -825q-10 -52 14 -82t95 -36v-57h-500v57q77 7 134.5 40.5t65.5 80.5l173 849q10 56 -10 74t-91 37q-6 1 -10.5 2.5t-9.5 2.5v57h425z\\\" />\\n<glyph unicode=\\\"&#xe050;\\\" d=\\\"M1150 1200h150v-300h-50q0 29 -8 48.5t-18.5 30t-33.5 15t-39.5 5.5t-50.5 1h-200v-850l100 -50v-100h-400v100l100 50v850h-200q-34 0 -50.5 -1t-40 -5.5t-33.5 -15t-18.5 -30t-8.5 -48.5h-49v300h150h700zM100 1000v-800h75l-125 -167l-125 167h75v800h-75l125 167 l125 -167h-75z\\\" />\\n<glyph unicode=\\\"&#xe051;\\\" d=\\\"M950 1201h150v-300h-50q0 29 -8 48.5t-18 30t-33.5 15t-40 5.5t-50.5 1h-200v-650l100 -50v-100h-400v100l100 50v650h-200q-34 0 -50.5 -1t-39.5 -5.5t-33.5 -15t-18.5 -30t-8 -48.5h-50v300h150h700zM200 101h800v75l167 -125l-167 -125v75h-800v-75l-167 125l167 125 v-75z\\\" />\\n<glyph unicode=\\\"&#xe052;\\\" d=\\\"M700 950v100q0 21 -14.5 35.5t-35.5 14.5h-600q-21 0 -35.5 -14.5t-14.5 -35.5v-100q0 -20 14.5 -35t35.5 -15h600q21 0 35.5 15t14.5 35zM1100 650v100q0 21 -14.5 35.5t-35.5 14.5h-1000q-21 0 -35.5 -14.5t-14.5 -35.5v-100q0 -20 14.5 -35t35.5 -15h1000 q21 0 35.5 15t14.5 35zM900 350v100q0 21 -14.5 35.5t-35.5 14.5h-800q-21 0 -35.5 -14.5t-14.5 -35.5v-100q0 -20 14.5 -35t35.5 -15h800q21 0 35.5 15t14.5 35zM1200 50v100q0 21 -14.5 35.5t-35.5 14.5h-1100q-21 0 -35.5 -14.5t-14.5 -35.5v-100q0 -20 14.5 -35 t35.5 -15h1100q21 0 35.5 15t14.5 35z\\\" />\\n<glyph unicode=\\\"&#xe053;\\\" d=\\\"M1000 950v100q0 21 -14.5 35.5t-35.5 14.5h-700q-21 0 -35.5 -14.5t-14.5 -35.5v-100q0 -20 14.5 -35t35.5 -15h700q21 0 35.5 15t14.5 35zM1200 650v100q0 21 -14.5 35.5t-35.5 14.5h-1100q-21 0 -35.5 -14.5t-14.5 -35.5v-100q0 -20 14.5 -35t35.5 -15h1100 q21 0 35.5 15t14.5 35zM1000 350v100q0 21 -14.5 35.5t-35.5 14.5h-700q-21 0 -35.5 -14.5t-14.5 -35.5v-100q0 -20 14.5 -35t35.5 -15h700q21 0 35.5 15t14.5 35zM1200 50v100q0 21 -14.5 35.5t-35.5 14.5h-1100q-21 0 -35.5 -14.5t-14.5 -35.5v-100q0 -20 14.5 -35 t35.5 -15h1100q21 0 35.5 15t14.5 35z\\\" />\\n<glyph unicode=\\\"&#xe054;\\\" d=\\\"M500 950v100q0 21 14.5 35.5t35.5 14.5h600q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-600q-21 0 -35.5 15t-14.5 35zM100 650v100q0 21 14.5 35.5t35.5 14.5h1000q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-1000q-21 0 -35.5 15 t-14.5 35zM300 350v100q0 21 14.5 35.5t35.5 14.5h800q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-800q-21 0 -35.5 15t-14.5 35zM0 50v100q0 21 14.5 35.5t35.5 14.5h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-1100 q-21 0 -35.5 15t-14.5 35z\\\" />\\n<glyph unicode=\\\"&#xe055;\\\" d=\\\"M0 950v100q0 21 14.5 35.5t35.5 14.5h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-1100q-21 0 -35.5 15t-14.5 35zM0 650v100q0 21 14.5 35.5t35.5 14.5h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-1100q-21 0 -35.5 15 t-14.5 35zM0 350v100q0 21 14.5 35.5t35.5 14.5h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-1100q-21 0 -35.5 15t-14.5 35zM0 50v100q0 21 14.5 35.5t35.5 14.5h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-1100 q-21 0 -35.5 15t-14.5 35z\\\" />\\n<glyph unicode=\\\"&#xe056;\\\" d=\\\"M0 950v100q0 21 14.5 35.5t35.5 14.5h100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-100q-21 0 -35.5 15t-14.5 35zM300 950v100q0 21 14.5 35.5t35.5 14.5h800q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-800q-21 0 -35.5 15 t-14.5 35zM0 650v100q0 21 14.5 35.5t35.5 14.5h100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-100q-21 0 -35.5 15t-14.5 35zM300 650v100q0 21 14.5 35.5t35.5 14.5h800q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-800 q-21 0 -35.5 15t-14.5 35zM0 350v100q0 21 14.5 35.5t35.5 14.5h100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-100q-21 0 -35.5 15t-14.5 35zM300 350v100q0 21 14.5 35.5t35.5 14.5h800q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15 h-800q-21 0 -35.5 15t-14.5 35zM0 50v100q0 21 14.5 35.5t35.5 14.5h100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-100q-21 0 -35.5 15t-14.5 35zM300 50v100q0 21 14.5 35.5t35.5 14.5h800q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15 h-800q-21 0 -35.5 15t-14.5 35z\\\" />\\n<glyph unicode=\\\"&#xe057;\\\" d=\\\"M400 1100h-100v-1100h100v1100zM700 950v100q0 21 -15 35.5t-35 14.5h-100q-21 0 -35.5 -14.5t-14.5 -35.5v-100q0 -20 14.5 -35t35.5 -15h100q20 0 35 15t15 35zM1100 650v100q0 21 -15 35.5t-35 14.5h-500q-21 0 -35.5 -14.5t-14.5 -35.5v-100q0 -20 14.5 -35t35.5 -15 h500q20 0 35 15t15 35zM100 425v75h-201v100h201v75l166 -125zM900 350v100q0 21 -15 35.5t-35 14.5h-300q-21 0 -35.5 -14.5t-14.5 -35.5v-100q0 -20 14.5 -35t35.5 -15h300q20 0 35 15t15 35zM1200 50v100q0 21 -15 35.5t-35 14.5h-600q-21 0 -35.5 -14.5t-14.5 -35.5 v-100q0 -20 14.5 -35t35.5 -15h600q20 0 35 15t15 35z\\\" />\\n<glyph unicode=\\\"&#xe058;\\\" d=\\\"M201 950v100q0 21 -15 35.5t-35 14.5h-100q-21 0 -35.5 -14.5t-14.5 -35.5v-100q0 -20 14.5 -35t35.5 -15h100q20 0 35 15t15 35zM801 1100h100v-1100h-100v1100zM601 650v100q0 21 -15 35.5t-35 14.5h-500q-21 0 -35.5 -14.5t-14.5 -35.5v-100q0 -20 14.5 -35t35.5 -15 h500q20 0 35 15t15 35zM1101 425v75h200v100h-200v75l-167 -125zM401 350v100q0 21 -15 35.5t-35 14.5h-300q-21 0 -35.5 -14.5t-14.5 -35.5v-100q0 -20 14.5 -35t35.5 -15h300q20 0 35 15t15 35zM701 50v100q0 21 -15 35.5t-35 14.5h-600q-21 0 -35.5 -14.5t-14.5 -35.5 v-100q0 -20 14.5 -35t35.5 -15h600q20 0 35 15t15 35z\\\" />\\n<glyph unicode=\\\"&#xe059;\\\" d=\\\"M900 925v-650q0 -31 -22 -53t-53 -22h-750q-31 0 -53 22t-22 53v650q0 31 22 53t53 22h750q31 0 53 -22t22 -53zM1200 300l-300 300l300 300v-600z\\\" />\\n<glyph unicode=\\\"&#xe060;\\\" d=\\\"M1200 1056v-1012q0 -18 -12.5 -31t-31.5 -13h-1112q-18 0 -31 13t-13 31v1012q0 18 13 31t31 13h1112q19 0 31.5 -13t12.5 -31zM1100 1000h-1000v-737l247 182l298 -131l-74 156l293 318l236 -288v500zM476 750q0 -56 -39 -95t-95 -39t-95 39t-39 95t39 95t95 39t95 -39 t39 -95z\\\" />\\n<glyph unicode=\\\"&#xe062;\\\" d=\\\"M600 1213q123 0 227 -63t164.5 -169.5t60.5 -229.5t-73 -272q-73 -114 -166.5 -237t-150.5 -189l-57 -66q-10 9 -27 26t-66.5 70.5t-96 109t-104 135.5t-100.5 155q-63 139 -63 262q0 124 60.5 231.5t165 172t226.5 64.5zM599 514q107 0 182.5 75.5t75.5 182.5t-75.5 182 t-182.5 75t-182 -75.5t-75 -181.5q0 -107 75.5 -182.5t181.5 -75.5z\\\" />\\n<glyph unicode=\\\"&#xe063;\\\" d=\\\"M600 1199q122 0 233 -47.5t191 -127.5t127.5 -191t47.5 -233t-47.5 -233t-127.5 -191t-191 -127.5t-233 -47.5t-233 47.5t-191 127.5t-127.5 191t-47.5 233t47.5 233t127.5 191t191 127.5t233 47.5zM600 173v854q-176 0 -301.5 -125t-125.5 -302t125.5 -302t301.5 -125z \\\" />\\n<glyph unicode=\\\"&#xe064;\\\" d=\\\"M554 1295q21 -71 57.5 -142.5t76 -130.5t83 -118.5t82 -117t70 -116t50 -125.5t18.5 -136q0 -89 -39 -165.5t-102 -126.5t-140 -79.5t-156 -33.5q-114 6 -211.5 53t-161.5 138.5t-64 210.5q0 94 34 186t88.5 172.5t112 159t115 177t87.5 194.5zM455 296q-7 6 -18 17 t-34 48t-33 77q-15 73 -14 143.5t10 122.5l9 51q-92 -110 -119.5 -185t-12.5 -156q14 -82 59.5 -136t136.5 -80z\\\" />\\n<glyph unicode=\\\"&#xe065;\\\" d=\\\"M1108 902l113 113l-21 85l-92 28l-113 -113zM1100 625v-225q0 -165 -117.5 -282.5t-282.5 -117.5h-300q-165 0 -282.5 117.5t-117.5 282.5v300q0 165 117.5 282.5t282.5 117.5q366 -6 397 -14l-186 -186h-311q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5 t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5v125zM436 341l161 50l412 412l-114 113l-405 -405z\\\" />\\n<glyph unicode=\\\"&#xe066;\\\" d=\\\"M1100 453v-53q0 -165 -117.5 -282.5t-282.5 -117.5h-300q-165 0 -282.5 117.5t-117.5 282.5v300q0 165 117.5 282.5t282.5 117.5h261l2 -80q-133 -32 -218 -120h-145q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5z M813 431l360 324l-359 318v-216q-7 0 -19 -1t-48 -8t-69.5 -18.5t-76.5 -37t-76.5 -59t-62 -88t-39.5 -121.5q30 38 81.5 64t103 35.5t99 14t77.5 3.5l29 -1v-209z\\\" />\\n<glyph unicode=\\\"&#xe067;\\\" d=\\\"M1100 569v-169q0 -165 -117.5 -282.5t-282.5 -117.5h-300q-165 0 -282.5 117.5t-117.5 282.5v300q0 165 117.5 282.5t282.5 117.5h300q60 0 127 -23l-178 -177h-349q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5v69z M625 348l566 567l-136 137l-430 -431l-147 147l-136 -136z\\\" />\\n<glyph unicode=\\\"&#xe068;\\\" d=\\\"M900 303v198h-200v-200h195l-295 -300l-300 300h200v200h-200v-198l-300 300l300 296v-198h200v200h-200l300 300l295 -300h-195v-200h200v198l300 -296z\\\" />\\n<glyph unicode=\\\"&#xe069;\\\" d=\\\"M900 0l-500 488v-438q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v1000q0 21 14.5 35.5t35.5 14.5h100q21 0 35.5 -14.5t14.5 -35.5v-437l500 487v-1100z\\\" />\\n<glyph unicode=\\\"&#xe070;\\\" d=\\\"M1200 0l-500 488v-488l-500 488v-438q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v1000q0 21 14.5 35.5t35.5 14.5h100q21 0 35.5 -14.5t14.5 -35.5v-437l500 487v-487l500 487v-1100z\\\" />\\n<glyph unicode=\\\"&#xe071;\\\" d=\\\"M1200 0l-500 488v-488l-564 550l564 550v-487l500 487v-1100z\\\" />\\n<glyph unicode=\\\"&#xe072;\\\" d=\\\"M1100 550l-900 550v-1100z\\\" />\\n<glyph unicode=\\\"&#xe073;\\\" d=\\\"M500 150v800q0 21 -14.5 35.5t-35.5 14.5h-200q-21 0 -35.5 -14.5t-14.5 -35.5v-800q0 -21 14.5 -35.5t35.5 -14.5h200q21 0 35.5 14.5t14.5 35.5zM900 150v800q0 21 -14.5 35.5t-35.5 14.5h-200q-21 0 -35.5 -14.5t-14.5 -35.5v-800q0 -21 14.5 -35.5t35.5 -14.5h200 q21 0 35.5 14.5t14.5 35.5z\\\" />\\n<glyph unicode=\\\"&#xe074;\\\" d=\\\"M1100 150v800q0 21 -14.5 35.5t-35.5 14.5h-800q-21 0 -35.5 -14.5t-14.5 -35.5v-800q0 -20 14.5 -35t35.5 -15h800q21 0 35.5 15t14.5 35z\\\" />\\n<glyph unicode=\\\"&#xe075;\\\" d=\\\"M500 0v488l-500 -488v1100l500 -487v487l564 -550z\\\" />\\n<glyph unicode=\\\"&#xe076;\\\" d=\\\"M1050 1100h100q21 0 35.5 -14.5t14.5 -35.5v-1000q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v438l-500 -488v488l-500 -488v1100l500 -487v487l500 -487v437q0 21 14.5 35.5t35.5 14.5z\\\" />\\n<glyph unicode=\\\"&#xe077;\\\" d=\\\"M850 1100h100q21 0 35.5 -14.5t14.5 -35.5v-1000q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v438l-500 -488v1100l500 -487v437q0 21 14.5 35.5t35.5 14.5z\\\" />\\n<glyph unicode=\\\"&#xe078;\\\" d=\\\"M650 1064l-550 -564h1100zM1200 350v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-1000q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5h1000q21 0 35.5 -14.5t14.5 -35.5z\\\" />\\n<glyph unicode=\\\"&#xe079;\\\" d=\\\"M777 7l240 240l-353 353l353 353l-240 240l-592 -594z\\\" />\\n<glyph unicode=\\\"&#xe080;\\\" d=\\\"M513 -46l-241 240l353 353l-353 353l241 240l572 -571l21 -22l-1 -1v-1z\\\" />\\n<glyph unicode=\\\"&#xe081;\\\" d=\\\"M600 1197q162 0 299.5 -80t217.5 -217.5t80 -299.5t-80 -299.5t-217.5 -217.5t-299.5 -80t-299.5 80t-217.5 217.5t-80 299.5t80 299.5t217.5 217.5t299.5 80zM500 900v-200h-200v-200h200v-200h200v200h200v200h-200v200h-200z\\\" />\\n<glyph unicode=\\\"&#xe082;\\\" d=\\\"M600 1197q162 0 299.5 -80t217.5 -217.5t80 -299.5t-80 -299.5t-217.5 -217.5t-299.5 -80t-299.5 80t-217.5 217.5t-80 299.5t80 299.5t217.5 217.5t299.5 80zM300 700v-200h600v200h-600z\\\" />\\n<glyph unicode=\\\"&#xe083;\\\" d=\\\"M600 1197q162 0 299.5 -80t217.5 -217.5t80 -299.5t-80 -299.5t-217.5 -217.5t-299.5 -80t-299.5 80t-217.5 217.5t-80 299.5t80 299.5t217.5 217.5t299.5 80zM247 741l141 -141l-142 -141l213 -213l141 142l141 -142l213 213l-142 141l142 141l-213 212l-141 -141 l-141 142z\\\" />\\n<glyph unicode=\\\"&#xe084;\\\" d=\\\"M600 1197q162 0 299.5 -80t217.5 -217.5t80 -299.5t-80 -299.5t-217.5 -217.5t-299.5 -80t-299.5 80t-217.5 217.5t-80 299.5t80 299.5t217.5 217.5t299.5 80zM546 623l-102 102l-174 -174l276 -277l411 411l-175 174z\\\" />\\n<glyph unicode=\\\"&#xe085;\\\" d=\\\"M600 1197q162 0 299.5 -80t217.5 -217.5t80 -299.5t-80 -299.5t-217.5 -217.5t-299.5 -80t-299.5 80t-217.5 217.5t-80 299.5t80 299.5t217.5 217.5t299.5 80zM500 500h200q5 3 14 8t31.5 25.5t39.5 45.5t31 69t14 94q0 51 -17.5 89t-42 58t-58.5 32t-58.5 15t-51.5 3 q-105 0 -172 -56t-67 -183h144q4 0 11.5 -1t11 -1t6.5 3t3 9t1 11t3.5 8.5t3.5 6t5.5 4t6.5 2.5t9 1.5t9 0.5h11.5h12.5q19 0 30 -10t11 -26q0 -22 -4 -28t-27 -22q-5 -1 -12.5 -3t-27 -13.5t-34 -27t-26.5 -46t-11 -68.5zM500 400v-100h200v100h-200z\\\" />\\n<glyph unicode=\\\"&#xe086;\\\" d=\\\"M600 1197q162 0 299.5 -80t217.5 -217.5t80 -299.5t-80 -299.5t-217.5 -217.5t-299.5 -80t-299.5 80t-217.5 217.5t-80 299.5t80 299.5t217.5 217.5t299.5 80zM500 900v-100h200v100h-200zM400 700v-100h100v-200h-100v-100h400v100h-100v300h-300z\\\" />\\n<glyph unicode=\\\"&#xe087;\\\" d=\\\"M1200 700v-200h-203q-25 -102 -116.5 -186t-180.5 -117v-197h-200v197q-140 27 -208 102.5t-98 200.5h-194v200h194q15 60 36 104.5t55.5 86t88 69t126.5 40.5v200h200v-200q54 -20 113 -60t112.5 -105.5t71.5 -134.5h203zM700 500v-206q149 48 201 206h-201v200h200 q-25 74 -76 127.5t-124 76.5v-204h-200v203q-75 -24 -130 -77.5t-79 -125.5h209v-200h-210q24 -73 79.5 -127.5t130.5 -78.5v206h200z\\\" />\\n<glyph unicode=\\\"&#xe088;\\\" d=\\\"M600 1196q162 0 299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299t80 299t217 217t299 80zM600 1014q-171 0 -292.5 -121.5t-121.5 -292.5t121.5 -292.5t292.5 -121.5t292.5 121.5t121.5 292.5t-121.5 292.5t-292.5 121.5zM844 735 l-135 -135l135 -135l-109 -109l-135 135l-135 -135l-109 109l135 135l-135 135l109 109l135 -135l135 135z\\\" />\\n<glyph unicode=\\\"&#xe089;\\\" d=\\\"M600 1196q162 0 299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299t80 299t217 217t299 80zM600 1014q-171 0 -292.5 -121.5t-121.5 -292.5t121.5 -292.5t292.5 -121.5t292.5 121.5t121.5 292.5t-121.5 292.5t-292.5 121.5zM896 654 l-346 -345l-228 228l141 141l87 -87l204 205z\\\" />\\n<glyph unicode=\\\"&#xe090;\\\" d=\\\"M600 1196q162 0 299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299t80 299t217 217t299 80zM248 385l568 567q-100 62 -216 62q-171 0 -292.5 -121.5t-121.5 -292.5q0 -115 62 -215zM955 809l-564 -564q97 -59 209 -59q171 0 292.5 121.5 t121.5 292.5q0 112 -59 209z\\\" />\\n<glyph unicode=\\\"&#xe091;\\\" d=\\\"M1200 400h-600v-301l-600 448l600 453v-300h600v-300z\\\" />\\n<glyph unicode=\\\"&#xe092;\\\" d=\\\"M600 400h-600v300h600v300l600 -453l-600 -448v301z\\\" />\\n<glyph unicode=\\\"&#xe093;\\\" d=\\\"M1098 600h-298v-600h-300v600h-296l450 600z\\\" />\\n<glyph unicode=\\\"&#xe094;\\\" d=\\\"M998 600l-449 -600l-445 600h296v600h300v-600h298z\\\" />\\n<glyph unicode=\\\"&#xe095;\\\" d=\\\"M600 199v301q-95 -2 -183 -20t-170 -52t-147 -92.5t-100 -135.5q6 132 41 238.5t103.5 193t184 138t271.5 59.5v271l600 -453z\\\" />\\n<glyph unicode=\\\"&#xe096;\\\" d=\\\"M1200 1200h-400l129 -129l-294 -294l142 -142l294 294l129 -129v400zM565 423l-294 -294l129 -129h-400v400l129 -129l294 294z\\\" />\\n<glyph unicode=\\\"&#xe097;\\\" d=\\\"M871 730l129 -130h-400v400l129 -129l295 295l142 -141zM200 600h400v-400l-129 130l-295 -295l-142 141l295 295z\\\" />\\n<glyph unicode=\\\"&#xe101;\\\" d=\\\"M600 1177q118 0 224.5 -45.5t184 -123t123 -184t45.5 -224.5t-45.5 -224.5t-123 -184t-184 -123t-224.5 -45.5t-224.5 45.5t-184 123t-123 184t-45.5 224.5t45.5 224.5t123 184t184 123t224.5 45.5zM686 549l58 302q4 20 -8 34.5t-33 14.5h-207q-20 0 -32 -14.5t-8 -34.5 l58 -302q4 -20 21.5 -34.5t37.5 -14.5h54q20 0 37.5 14.5t21.5 34.5zM700 400h-200v-100h200v100z\\\" />\\n<glyph unicode=\\\"&#xe102;\\\" d=\\\"M1200 900h-111v6t-1 15t-3 18l-34 172q-11 39 -41.5 63t-69.5 24q-32 0 -61 -17l-239 -144q-22 -13 -40 -35q-19 24 -40 36l-238 144q-33 18 -62 18q-39 0 -69.5 -23t-40.5 -61l-35 -177q-2 -8 -3 -18t-1 -15v-6h-111v-100h100v-200h400v300h200v-300h400v200h100v100z M731 900l202 197q5 -12 12 -32.5t23 -64t25 -72t7 -28.5h-269zM481 900h-281q-3 0 14 48t35 96l18 47zM100 0h400v400h-400v-400zM700 400h400v-400h-400v400z\\\" />\\n<glyph unicode=\\\"&#xe103;\\\" d=\\\"M0 121l216 193q-9 53 -13 83t-5.5 94t9 113t38.5 114t74 124q47 60 99.5 102.5t103 68t127.5 48t145.5 37.5t184.5 43.5t220 58.5q0 -189 -22 -343t-59 -258t-89 -181.5t-108.5 -120t-122 -68t-125.5 -30t-121.5 -1.5t-107.5 12.5t-87.5 17t-56.5 7.5l-99 -55l-201 -202 v143zM692 611q70 38 118.5 69.5t102 79t99 111.5t86.5 148q22 50 24 60t-6 19q-7 5 -17 5t-26.5 -14.5t-33.5 -39.5q-35 -51 -113.5 -108.5t-139.5 -89.5l-61 -32q-369 -197 -458 -401q-48 -111 -28.5 -117.5t86.5 76.5q55 66 367 234z\\\" />\\n<glyph unicode=\\\"&#xe105;\\\" d=\\\"M1261 600l-26 -40q-6 -10 -20 -30t-49 -63.5t-74.5 -85.5t-97 -90t-116.5 -83.5t-132.5 -59t-145.5 -23.5t-145.5 23.5t-132.5 59t-116.5 83.5t-97 90t-74.5 85.5t-49 63.5t-20 30l-26 40l26 40q6 10 20 30t49 63.5t74.5 85.5t97 90t116.5 83.5t132.5 59t145.5 23.5 t145.5 -23.5t132.5 -59t116.5 -83.5t97 -90t74.5 -85.5t49 -63.5t20 -30zM600 240q64 0 123.5 20t100.5 45.5t85.5 71.5t66.5 75.5t58 81.5t47 66q-1 1 -28.5 37.5t-42 55t-43.5 53t-57.5 63.5t-58.5 54q49 -74 49 -163q0 -124 -88 -212t-212 -88t-212 88t-88 212 q0 85 46 158q-102 -87 -226 -258q7 -10 40.5 -58t56 -78.5t68 -77.5t87.5 -75t103 -49.5t125 -21.5zM484 762l-107 -106q49 -124 154 -191l105 105q-37 24 -75 72t-57 84z\\\" />\\n<glyph unicode=\\\"&#xe106;\\\" d=\\\"M906 1200l-314 -1200h-148l37 143q-82 21 -165 71.5t-140 102t-109.5 112t-72 88.5t-29.5 43l-26 40l26 40q6 10 20 30t49 63.5t74.5 85.5t97 90t116.5 83.5t132.5 59t145.5 23.5q61 0 121 -17l37 142h148zM1261 600l-26 -40q-7 -12 -25.5 -38t-63.5 -79.5t-95.5 -102.5 t-124 -100t-146.5 -79l38 145q22 15 44.5 34t46 44t40.5 44t41 50.5t33.5 43.5t33 44t24.5 34q-97 127 -140 175l39 146q67 -54 131.5 -125.5t87.5 -103.5t36 -52zM513 264l37 141q-107 18 -178.5 101.5t-71.5 193.5q0 85 46 158q-102 -87 -226 -258q210 -282 393 -336z M484 762l-107 -106q49 -124 154 -191l47 47l23 87q-30 28 -59 69t-44 68z\\\" />\\n<glyph unicode=\\\"&#xe107;\\\" d=\\\"M-47 0h1294q37 0 50.5 35.5t-7.5 67.5l-642 1056q-20 33 -48 36t-48 -29l-642 -1066q-21 -32 -7.5 -66t50.5 -34zM700 200v100h-200v-100h-345l445 723l445 -723h-345zM700 700h-200v-100l100 -300l100 300v100z\\\" />\\n<glyph unicode=\\\"&#xe108;\\\" d=\\\"M800 711l363 -325q15 -14 26 -38.5t11 -44.5v-41q0 -20 -12 -26.5t-29 5.5l-359 249v-263q100 -91 100 -113v-64q0 -21 -13 -29t-32 1l-94 78h-222l-94 -78q-19 -9 -32 -1t-13 29v64q0 22 100 113v263l-359 -249q-17 -12 -29 -5.5t-12 26.5v41q0 20 11 44.5t26 38.5 l363 325v339q0 62 44 106t106 44t106 -44t44 -106v-339z\\\" />\\n<glyph unicode=\\\"&#xe110;\\\" d=\\\"M941 800l-600 -600h-341v200h259l600 600h241v198l300 -295l-300 -300v197h-159zM381 678l141 142l-181 180h-341v-200h259zM1100 598l300 -295l-300 -300v197h-241l-181 181l141 142l122 -123h159v198z\\\" />\\n<glyph unicode=\\\"&#xe111;\\\" d=\\\"M100 1100h1000q41 0 70.5 -29.5t29.5 -70.5v-600q0 -41 -29.5 -70.5t-70.5 -29.5h-596l-304 -300v300h-100q-41 0 -70.5 29.5t-29.5 70.5v600q0 41 29.5 70.5t70.5 29.5z\\\" />\\n<glyph unicode=\\\"&#xe112;\\\" d=\\\"M400 900h-300v300h300v-300zM1100 900h-300v300h300v-300zM1100 800v-200q0 -42 -3 -83t-15 -104t-31.5 -116t-58 -109.5t-89 -96.5t-129 -65.5t-174.5 -25.5t-174.5 25.5t-129 65.5t-89 96.5t-58 109.5t-31.5 116t-15 104t-3 83v200h300v-250q0 -113 6 -145 q17 -92 102 -117q39 -11 92 -11q37 0 66.5 5.5t50 15.5t36 24t24 31.5t14 37.5t7 42t2.5 45t0 47v25v250h300z\\\" />\\n<glyph unicode=\\\"&#xe113;\\\" d=\\\"M902 184l226 227l-578 579l-580 -579l227 -227l352 353z\\\" />\\n<glyph unicode=\\\"&#xe114;\\\" d=\\\"M650 218l578 579l-226 227l-353 -353l-352 353l-227 -227z\\\" />\\n<glyph unicode=\\\"&#xe115;\\\" d=\\\"M1198 400v600h-796l215 -200h381v-400h-198l299 -283l299 283h-200zM-198 700l299 283l300 -283h-203v-400h385l215 -200h-800v600h-196z\\\" />\\n<glyph unicode=\\\"&#xe116;\\\" d=\\\"M1050 1200h94q20 0 35 -14.5t15 -35.5t-15 -35.5t-35 -14.5h-54l-201 -961q-2 -4 -6 -10.5t-19 -17.5t-33 -11h-31v-50q0 -20 -14.5 -35t-35.5 -15t-35.5 15t-14.5 35v50h-300v-50q0 -20 -14.5 -35t-35.5 -15t-35.5 15t-14.5 35v50h-50q-21 0 -35.5 15t-14.5 35 q0 21 14.5 35.5t35.5 14.5h535l48 200h-633q-32 0 -54.5 21t-27.5 43l-100 475q-5 24 10 42q14 19 39 19h896l38 162q5 17 18.5 27.5t30.5 10.5z\\\" />\\n<glyph unicode=\\\"&#xe117;\\\" d=\\\"M1200 1000v-100h-1200v100h200q0 41 29.5 70.5t70.5 29.5h300q41 0 70.5 -29.5t29.5 -70.5h500zM0 800h1200v-800h-1200v800z\\\" />\\n<glyph unicode=\\\"&#xe118;\\\" d=\\\"M201 800l-200 -400v600h200q0 41 29.5 70.5t70.5 29.5h300q41 0 70.5 -29.5t29.5 -70.5h500v-200h-1000zM1501 700l-300 -700h-1200l300 700h1200z\\\" />\\n<glyph unicode=\\\"&#xe119;\\\" d=\\\"M302 300h198v600h-198l298 300l298 -300h-198v-600h198l-298 -300z\\\" />\\n<glyph unicode=\\\"&#xe120;\\\" d=\\\"M900 303v197h-600v-197l-300 297l300 298v-198h600v198l300 -298z\\\" />\\n<glyph unicode=\\\"&#xe121;\\\" d=\\\"M31 400l172 739q5 22 23 41.5t38 19.5h672q19 0 37.5 -22.5t23.5 -45.5l172 -732h-1138zM100 300h1000q41 0 70.5 -29.5t29.5 -70.5v-100q0 -41 -29.5 -70.5t-70.5 -29.5h-1000q-41 0 -70.5 29.5t-29.5 70.5v100q0 41 29.5 70.5t70.5 29.5zM900 200h-100v-100h100v100z M1100 200h-100v-100h100v100z\\\" />\\n<glyph unicode=\\\"&#xe122;\\\" d=\\\"M1100 200v850q0 21 14.5 35.5t35.5 14.5q20 0 35 -14.5t15 -35.5v-850q0 -20 -15 -35t-35 -15q-21 0 -35.5 15t-14.5 35zM325 800l675 250v-850l-675 200h-38l47 -276q2 -12 -3 -17.5t-11 -6t-21 -0.5h-8h-83q-20 0 -34.5 14t-18.5 35q-56 337 -56 351v250v5 q0 13 0.5 18.5t2.5 13t8 10.5t15 3h200zM-101 600v50q0 24 25 49t50 38l25 13v-250l-11 5.5t-24 14t-30 21.5t-24 27.5t-11 31.5z\\\" />\\n<glyph unicode=\\\"&#xe124;\\\" d=\\\"M445 1180l-45 -233l-224 78l78 -225l-233 -44l179 -156l-179 -155l233 -45l-78 -224l224 78l45 -233l155 179l155 -179l45 233l224 -78l-78 224l234 45l-180 155l180 156l-234 44l78 225l-224 -78l-45 233l-155 -180z\\\" />\\n<glyph unicode=\\\"&#xe125;\\\" d=\\\"M700 1200h-50q-27 0 -51 -20t-38 -48l-96 -198l-145 -196q-20 -26 -20 -63v-400q0 -75 100 -75h61q123 -100 139 -100h250q46 0 83 57l238 344q29 31 29 74v100q0 44 -30.5 84.5t-69.5 40.5h-328q28 118 28 125v150q0 44 -30.5 84.5t-69.5 40.5zM700 925l-50 -225h450 v-125l-250 -375h-214l-136 100h-100v375l150 212l100 213h50v-175zM0 800v-600h200v600h-200z\\\" />\\n<glyph unicode=\\\"&#xe126;\\\" d=\\\"M700 0h-50q-27 0 -51 20t-38 48l-96 198l-145 196q-20 26 -20 63v400q0 75 100 75h61q123 100 139 100h250q46 0 83 -57l238 -344q29 -31 29 -74v-100q0 -44 -30.5 -84.5t-69.5 -40.5h-328q28 -118 28 -125v-150q0 -44 -30.5 -84.5t-69.5 -40.5zM200 400h-200v600h200 v-600zM700 275l-50 225h450v125l-250 375h-214l-136 -100h-100v-375l150 -212l100 -213h50v175z\\\" />\\n<glyph unicode=\\\"&#xe127;\\\" d=\\\"M364 873l362 230q14 6 25 6q17 0 29 -12l109 -112q14 -14 14 -34q0 -18 -11 -32l-85 -121h302q85 0 138.5 -38t53.5 -110t-54.5 -111t-138.5 -39h-107l-130 -339q-7 -22 -20.5 -41.5t-28.5 -19.5h-341q-7 0 -90 81t-83 94v525q0 17 14 35.5t28 28.5zM408 792v-503 l100 -89h293l131 339q6 21 19.5 41t28.5 20h203q16 0 25 15t9 36q0 20 -9 34.5t-25 14.5h-457h-6.5h-7.5t-6.5 0.5t-6 1t-5 1.5t-5.5 2.5t-4 4t-4 5.5q-5 12 -5 20q0 14 10 27l147 183l-86 83zM208 200h-200v600h200v-600z\\\" />\\n<glyph unicode=\\\"&#xe128;\\\" d=\\\"M475 1104l365 -230q7 -4 16.5 -10.5t26 -26t16.5 -36.5v-526q0 -13 -85.5 -93.5t-93.5 -80.5h-342q-15 0 -28.5 20t-19.5 41l-131 339h-106q-84 0 -139 39t-55 111t54 110t139 37h302l-85 121q-11 16 -11 32q0 21 14 34l109 113q13 12 29 12q11 0 25 -6zM370 946 l145 -184q10 -11 10 -26q0 -11 -5 -20q-1 -3 -3.5 -5.5l-4 -4t-5 -2.5t-5.5 -1.5t-6.5 -1t-6.5 -0.5h-7.5h-6.5h-476v-100h222q15 0 28.5 -20.5t19.5 -40.5l131 -339h293l106 89v502l-342 237zM1199 201h-200v600h200v-600z\\\" />\\n<glyph unicode=\\\"&#xe129;\\\" d=\\\"M1100 473v342q0 15 -20 28.5t-41 19.5l-339 131v106q0 84 -39 139t-111 55t-110 -53.5t-38 -138.5v-302l-121 84q-15 12 -33.5 11.5t-32.5 -13.5l-112 -110q-22 -22 -6 -53l230 -363q4 -6 10.5 -15.5t26 -25t36.5 -15.5h525q13 0 94 83t81 90zM911 400h-503l-236 339 l83 86l183 -146q22 -18 47 -5q3 1 5.5 3.5l4 4t2.5 5t1.5 5.5t1 6.5t0.5 6v7.5v7v456q0 22 25 31t50 -0.5t25 -30.5v-202q0 -16 20 -29.5t41 -19.5l339 -130v-294zM1000 200v-200h-600v200h600z\\\" />\\n<glyph unicode=\\\"&#xe130;\\\" d=\\\"M305 1104v200h600v-200h-600zM605 310l339 131q20 6 40.5 19.5t20.5 28.5v342q0 7 -81 90t-94 83h-525q-17 0 -35.5 -14t-28.5 -28l-10 -15l-230 -362q-15 -31 7 -53l112 -110q13 -13 32 -13.5t34 10.5l121 85l-1 -302q0 -84 38.5 -138t110.5 -54t111 55t39 139v106z M905 804v-294l-340 -130q-20 -6 -40 -20t-20 -29v-202q0 -22 -25 -31t-50 0t-25 31v456v14.5t-1.5 11.5t-5 12t-9.5 7q-24 13 -46 -5l-184 -146l-83 86l237 339h503z\\\" />\\n<glyph unicode=\\\"&#xe131;\\\" d=\\\"M603 1195q162 0 299.5 -80t217.5 -218t80 -300t-80 -299.5t-217.5 -217.5t-299.5 -80t-300 80t-218 217.5t-80 299.5q0 122 47.5 232.5t127.5 190.5t190.5 127.5t232.5 47.5zM598 701h-298v-201h300l-2 -194l402 294l-402 298v-197z\\\" />\\n<glyph unicode=\\\"&#xe132;\\\" d=\\\"M597 1195q122 0 232.5 -47.5t190.5 -127.5t127.5 -190.5t47.5 -232.5q0 -162 -80 -299.5t-218 -217.5t-300 -80t-299.5 80t-217.5 217.5t-80 299.5q0 122 47.5 232.5t127.5 190.5t190.5 127.5t231.5 47.5zM200 600l400 -294v194h302v201h-300v197z\\\" />\\n<glyph unicode=\\\"&#xe133;\\\" d=\\\"M603 1195q121 0 231.5 -47.5t190.5 -127.5t127.5 -190.5t47.5 -232.5q0 -162 -80 -299.5t-217.5 -217.5t-299.5 -80t-300 80t-218 217.5t-80 299.5q0 122 47.5 232.5t127.5 190.5t190.5 127.5t232.5 47.5zM300 600h200v-300h200v300h200l-300 400z\\\" />\\n<glyph unicode=\\\"&#xe134;\\\" d=\\\"M603 1195q121 0 231.5 -47.5t190.5 -127.5t127.5 -190.5t47.5 -232.5q0 -162 -80 -299.5t-217.5 -217.5t-299.5 -80t-300 80t-218 217.5t-80 299.5q0 122 47.5 232.5t127.5 190.5t190.5 127.5t232.5 47.5zM500 900v-300h-200l300 -400l300 400h-200v300h-200z\\\" />\\n<glyph unicode=\\\"&#xe135;\\\" d=\\\"M603 1195q121 0 231.5 -47.5t190.5 -127.5t127.5 -190.5t47.5 -232.5q0 -162 -80 -299.5t-217.5 -217.5t-299.5 -80t-300 80t-218 217.5t-80 299.5q0 122 47.5 232.5t127.5 190.5t190.5 127.5t232.5 47.5zM627 1101q-15 -12 -36.5 -21t-34.5 -12t-44 -8t-39 -6 q-15 -3 -45.5 0.5t-45.5 -2.5q-21 -7 -52 -26.5t-34 -34.5q-3 -11 6.5 -22.5t8.5 -18.5q-3 -34 -27.5 -90.5t-29.5 -79.5q-8 -33 5.5 -92.5t7.5 -87.5q0 -9 17 -44t16 -60q12 0 23 -5.5t23 -15t20 -13.5q24 -12 108 -42q22 -8 53 -31.5t59.5 -38.5t57.5 -11q8 -18 -15 -55 t-20 -57q42 -71 87 -80q0 -6 -3 -15.5t-3.5 -14.5t4.5 -17q102 -2 221 112q30 29 47 47t34.5 49t20.5 62q-14 9 -37 9.5t-36 7.5q-14 7 -49 15t-52 19q-9 0 -39.5 -0.5t-46.5 -1.5t-39 -6.5t-39 -16.5q-50 -35 -66 -12q-4 2 -3.5 25.5t0.5 25.5q-6 13 -26.5 17t-24.5 7 q2 22 -2 41t-16.5 28t-38.5 -20q-23 -25 -42 4q-19 28 -8 58q6 16 22 22q6 -1 26 -1.5t33.5 -4t19.5 -13.5q12 -19 32 -37.5t34 -27.5l14 -8q0 3 9.5 39.5t5.5 57.5q-4 23 14.5 44.5t22.5 31.5q5 14 10 35t8.5 31t15.5 22.5t34 21.5q-6 18 10 37q8 0 23.5 -1.5t24.5 -1.5 t20.5 4.5t20.5 15.5q-10 23 -30.5 42.5t-38 30t-49 26.5t-43.5 23q11 41 1 44q31 -13 58.5 -14.5t39.5 3.5l11 4q6 36 -17 53.5t-64 28.5t-56 23q-19 -3 -37 0zM613 994q0 -18 8 -42.5t16.5 -44t9.5 -23.5q-9 2 -31 5t-36 5t-32 8t-30 14q3 12 16 30t16 25q10 -10 18.5 -10 t14 6t14.5 14.5t16 12.5z\\\" />\\n<glyph unicode=\\\"&#xe137;\\\" horiz-adv-x=\\\"1220\\\" d=\\\"M100 1196h1000q41 0 70.5 -29.5t29.5 -70.5v-100q0 -41 -29.5 -70.5t-70.5 -29.5h-1000q-41 0 -70.5 29.5t-29.5 70.5v100q0 41 29.5 70.5t70.5 29.5zM1100 1096h-200v-100h200v100zM100 796h1000q41 0 70.5 -29.5t29.5 -70.5v-100q0 -41 -29.5 -70.5t-70.5 -29.5h-1000 q-41 0 -70.5 29.5t-29.5 70.5v100q0 41 29.5 70.5t70.5 29.5zM1100 696h-500v-100h500v100zM100 396h1000q41 0 70.5 -29.5t29.5 -70.5v-100q0 -41 -29.5 -70.5t-70.5 -29.5h-1000q-41 0 -70.5 29.5t-29.5 70.5v100q0 41 29.5 70.5t70.5 29.5zM1100 296h-300v-100h300v100z \\\" />\\n<glyph unicode=\\\"&#xe138;\\\" d=\\\"M1100 1200v-100h-1000v100h1000zM150 1000h900l-350 -500v-300l-200 -200v500z\\\" />\\n<glyph unicode=\\\"&#xe140;\\\" d=\\\"M329 729l142 142l-200 200l129 129h-400v-400l129 129zM1200 1200v-400l-129 129l-200 -200l-142 142l200 200l-129 129h400zM271 129l129 -129h-400v400l129 -129l200 200l142 -142zM1071 271l129 129v-400h-400l129 129l-200 200l142 142z\\\" />\\n<glyph unicode=\\\"&#xe141;\\\" d=\\\"M596 1192q162 0 299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299t80 299t217 217t299 80zM596 1010q-171 0 -292.5 -121.5t-121.5 -292.5q0 -172 121.5 -293t292.5 -121t292.5 121t121.5 293q0 171 -121.5 292.5t-292.5 121.5zM455 905 q22 0 38 -16t16 -39t-16 -39t-38 -16q-23 0 -39 16.5t-16 38.5t16 38.5t39 16.5zM708 821l1 1q-9 14 -9 28q0 22 16 38.5t39 16.5q22 0 38 -16t16 -39t-16 -39t-38 -16q-14 0 -29 10l-55 -145q17 -22 17 -51q0 -36 -25.5 -61.5t-61.5 -25.5t-61.5 25.5t-25.5 61.5 q0 32 20.5 56.5t51.5 29.5zM855 709q23 0 38.5 -15.5t15.5 -38.5t-16 -39t-38 -16q-23 0 -39 16t-16 39q0 22 16 38t39 16zM345 709q23 0 39 -16t16 -38q0 -23 -16 -39t-39 -16q-22 0 -38 16t-16 39t15.5 38.5t38.5 15.5z\\\" />\\n<glyph unicode=\\\"&#xe143;\\\" d=\\\"M649 54l-16 22q-90 125 -293 323q-71 70 -104.5 105.5t-77 89.5t-61 99t-17.5 91q0 131 98.5 229.5t230.5 98.5q143 0 241 -129q103 129 246 129q129 0 226 -98.5t97 -229.5q0 -46 -17.5 -91t-61 -99t-77 -89.5t-104.5 -105.5q-203 -198 -293 -323zM844 524l12 12 q64 62 97.5 97t64.5 79t31 72q0 71 -48 119t-105 48q-74 0 -132 -82l-118 -171l-114 174q-51 79 -123 79q-60 0 -109.5 -49t-49.5 -118q0 -27 30.5 -70t61.5 -75.5t95 -94.5l22 -22q93 -90 190 -201q82 92 195 203z\\\" />\\n<glyph unicode=\\\"&#xe144;\\\" d=\\\"M476 406l19 -17l105 105l-212 212l389 389l247 -247l-95 -96l18 -18q46 -46 77 -99l29 29q35 35 62.5 88t27.5 96q0 93 -66 159l-141 141q-66 66 -159 66q-95 0 -159 -66l-283 -283q-66 -64 -66 -159q0 -93 66 -159zM123 193l141 -141q66 -66 159 -66q95 0 159 66 l283 283q66 66 66 159t-66 159l-141 141q-12 12 -19 17l-105 -105l212 -212l-389 -389l-247 248l95 95l-18 18q-46 45 -75 101l-55 -55q-66 -66 -66 -159q0 -94 66 -160z\\\" />\\n<glyph unicode=\\\"&#xe145;\\\" d=\\\"M200 100v953q0 21 30 46t81 48t129 38t163 15t162 -15t127 -38t79 -48t29 -46v-953q0 -41 -29.5 -70.5t-70.5 -29.5h-600q-41 0 -70.5 29.5t-29.5 70.5zM900 1000h-600v-700h600v700zM600 46q43 0 73.5 30.5t30.5 73.5t-30.5 73.5t-73.5 30.5t-73.5 -30.5t-30.5 -73.5 t30.5 -73.5t73.5 -30.5z\\\" />\\n<glyph unicode=\\\"&#xe148;\\\" d=\\\"M700 1029v-307l64 -14q34 -7 64 -16.5t70 -31.5t67.5 -52t47.5 -80.5t20 -112.5q0 -139 -89 -224t-244 -96v-77h-100v78q-152 17 -237 104q-40 40 -52.5 93.5t-15.5 139.5h139q5 -77 48.5 -126.5t117.5 -64.5v335l-27 7q-46 14 -79 26.5t-72 36t-62.5 52t-40 72.5 t-16.5 99q0 92 44 159.5t109 101t144 40.5v78h100v-79q38 -4 72.5 -13.5t75.5 -31.5t71 -53.5t51.5 -84t24.5 -118.5h-159q-8 72 -35 109.5t-101 50.5zM600 755v274q-61 -8 -97.5 -37.5t-36.5 -102.5q0 -29 8 -51t16.5 -34t29.5 -22.5t31 -13.5t38 -10q7 -2 11 -3zM700 548 v-311q170 18 170 151q0 64 -44 99.5t-126 60.5z\\\" />\\n<glyph unicode=\\\"&#xe149;\\\" d=\\\"M866 300l50 -147q-41 -25 -80.5 -36.5t-59 -13t-61.5 -1.5q-23 0 -128 33t-155 29q-39 -4 -82 -17t-66 -25l-24 -11l-55 145l16.5 11t15.5 10t13.5 9.5t14.5 12t14.5 14t17.5 18.5q48 55 54 126.5t-30 142.5h-221v100h166q-24 49 -44 104q-10 26 -14.5 55.5t-3 72.5 t25 90t68.5 87q97 88 263 88q129 0 230 -89t101 -208h-153q0 52 -34 89.5t-74 51.5t-76 14q-37 0 -79 -14.5t-62 -35.5q-41 -44 -41 -101q0 -11 2.5 -24.5t5.5 -24t9.5 -26.5t10.5 -25t14 -27.5t14 -25.5t15.5 -27t13.5 -24h242v-100h-197q8 -50 -2.5 -115t-31.5 -94 q-41 -59 -99 -113q35 11 84 18t70 7q32 1 102 -16t104 -17q76 0 136 30z\\\" />\\n<glyph unicode=\\\"&#xe150;\\\" d=\\\"M300 0l298 300h-198v900h-200v-900h-198zM900 1200l298 -300h-198v-900h-200v900h-198z\\\" />\\n<glyph unicode=\\\"&#xe151;\\\" d=\\\"M400 300h198l-298 -300l-298 300h198v900h200v-900zM1000 1200v-500h-100v100h-100v-100h-100v500h300zM901 1100h-100v-200h100v200zM700 500h300v-200h-99v-100h-100v100h99v100h-200v100zM800 100h200v-100h-300v200h100v-100z\\\" />\\n<glyph unicode=\\\"&#xe152;\\\" d=\\\"M400 300h198l-298 -300l-298 300h198v900h200v-900zM1000 1200v-200h-99v-100h-100v100h99v100h-200v100h300zM800 800h200v-100h-300v200h100v-100zM700 500h300v-500h-100v100h-100v-100h-100v500zM801 200h100v200h-100v-200z\\\" />\\n<glyph unicode=\\\"&#xe153;\\\" d=\\\"M300 0l298 300h-198v900h-200v-900h-198zM900 1100h-100v100h200v-500h-100v400zM1100 500v-500h-100v100h-200v400h300zM1001 400h-100v-200h100v200z\\\" />\\n<glyph unicode=\\\"&#xe154;\\\" d=\\\"M300 0l298 300h-198v900h-200v-900h-198zM1100 1200v-500h-100v100h-200v400h300zM1001 1100h-100v-200h100v200zM900 400h-100v100h200v-500h-100v400z\\\" />\\n<glyph unicode=\\\"&#xe155;\\\" d=\\\"M300 0l298 300h-198v900h-200v-900h-198zM900 1000h-200v200h200v-200zM1000 700h-300v200h300v-200zM1100 400h-400v200h400v-200zM1200 100h-500v200h500v-200z\\\" />\\n<glyph unicode=\\\"&#xe156;\\\" d=\\\"M300 0l298 300h-198v900h-200v-900h-198zM1200 1000h-500v200h500v-200zM1100 700h-400v200h400v-200zM1000 400h-300v200h300v-200zM900 100h-200v200h200v-200z\\\" />\\n<glyph unicode=\\\"&#xe157;\\\" d=\\\"M400 1100h300q162 0 281 -118.5t119 -281.5v-300q0 -165 -118.5 -282.5t-281.5 -117.5h-300q-165 0 -282.5 117.5t-117.5 282.5v300q0 165 117.5 282.5t282.5 117.5zM800 900h-500q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5 t29.5 70.5v500q0 41 -29.5 70.5t-70.5 29.5z\\\" />\\n<glyph unicode=\\\"&#xe158;\\\" d=\\\"M700 0h-300q-163 0 -281.5 117.5t-118.5 282.5v300q0 163 119 281.5t281 118.5h300q165 0 282.5 -117.5t117.5 -282.5v-300q0 -165 -117.5 -282.5t-282.5 -117.5zM800 900h-500q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5 t29.5 70.5v500q0 41 -29.5 70.5t-70.5 29.5zM400 800v-500l333 250z\\\" />\\n<glyph unicode=\\\"&#xe159;\\\" d=\\\"M0 400v300q0 163 117.5 281.5t282.5 118.5h300q163 0 281.5 -119t118.5 -281v-300q0 -165 -117.5 -282.5t-282.5 -117.5h-300q-165 0 -282.5 117.5t-117.5 282.5zM900 300v500q0 41 -29.5 70.5t-70.5 29.5h-500q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5 t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5zM800 700h-500l250 -333z\\\" />\\n<glyph unicode=\\\"&#xe160;\\\" d=\\\"M1100 700v-300q0 -162 -118.5 -281t-281.5 -119h-300q-165 0 -282.5 118.5t-117.5 281.5v300q0 165 117.5 282.5t282.5 117.5h300q165 0 282.5 -117.5t117.5 -282.5zM900 300v500q0 41 -29.5 70.5t-70.5 29.5h-500q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5 t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5zM550 733l-250 -333h500z\\\" />\\n<glyph unicode=\\\"&#xe161;\\\" d=\\\"M500 1100h400q165 0 282.5 -117.5t117.5 -282.5v-300q0 -165 -117.5 -282.5t-282.5 -117.5h-400v200h500q41 0 70.5 29.5t29.5 70.5v500q0 41 -29.5 70.5t-70.5 29.5h-500v200zM700 550l-400 -350v200h-300v300h300v200z\\\" />\\n<glyph unicode=\\\"&#xe162;\\\" d=\\\"M403 2l9 -1q13 0 26 16l538 630q15 19 6 36q-8 18 -32 16h-300q1 4 78 219.5t79 227.5q2 17 -6 27l-8 8h-9q-16 0 -25 -15q-4 -5 -98.5 -111.5t-228 -257t-209.5 -238.5q-17 -19 -7 -40q10 -19 32 -19h302q-155 -438 -160 -458q-5 -21 4 -32z\\\" />\\n<glyph unicode=\\\"&#xe163;\\\" d=\\\"M800 200h-500q-41 0 -70.5 29.5t-29.5 70.5v500q0 41 29.5 70.5t70.5 29.5h500v185q-14 4 -114 7.5t-193 5.5l-93 2q-165 0 -282.5 -117.5t-117.5 -282.5v-300q0 -165 117.5 -282.5t282.5 -117.5h300q47 0 100 15v185zM900 200v200h-300v300h300v200l400 -350z\\\" />\\n<glyph unicode=\\\"&#xe164;\\\" d=\\\"M1200 700l-149 149l-342 -353l-213 213l353 342l-149 149h500v-500zM1022 571l-122 -123v-148q0 -41 -29.5 -70.5t-70.5 -29.5h-500q-41 0 -70.5 29.5t-29.5 70.5v500q0 41 29.5 70.5t70.5 29.5h156l118 122l-74 78h-100q-165 0 -282.5 -117.5t-117.5 -282.5v-300 q0 -165 117.5 -282.5t282.5 -117.5h300q163 0 281.5 117.5t118.5 282.5v98z\\\" />\\n<glyph unicode=\\\"&#xe165;\\\" d=\\\"M600 1196q162 0 299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299t80 299t217 217t299 80zM600 1014q-171 0 -292.5 -121.5t-121.5 -292.5t121.5 -292.5t292.5 -121.5t292.5 121.5t121.5 292.5t-121.5 292.5t-292.5 121.5zM600 794 q80 0 137 -57t57 -137t-57 -137t-137 -57t-137 57t-57 137t57 137t137 57z\\\" />\\n<glyph unicode=\\\"&#xe166;\\\" d=\\\"M700 800v400h-300v-400h-300l445 -500l450 500h-295zM25 300h1048q11 0 19 -7.5t8 -17.5v-275h-1100v275q0 11 7 18t18 7zM1000 200h-100v-50h100v50z\\\" />\\n<glyph unicode=\\\"&#xe167;\\\" d=\\\"M400 700v-300h300v300h295l-445 500l-450 -500h300zM25 300h1048q11 0 19 -7.5t8 -17.5v-275h-1100v275q0 11 7 18t18 7zM1000 200h-100v-50h100v50z\\\" />\\n<glyph unicode=\\\"&#xe168;\\\" d=\\\"M405 400l596 596l-154 155l-442 -442l-150 151l-155 -155zM25 300h1048q11 0 19 -7.5t8 -17.5v-275h-1100v275q0 11 7 18t18 7zM1000 200h-100v-50h100v50z\\\" />\\n<glyph unicode=\\\"&#xe169;\\\" d=\\\"M409 1103l-97 97l-212 -212l97 -98zM650 861l-149 149l-212 -212l149 -149l-238 -248h700v699zM25 300h1048q11 0 19 -7.5t8 -17.5v-275h-1100v275q0 11 7 18t18 7zM1000 200h-100v-50h100v50z\\\" />\\n<glyph unicode=\\\"&#xe170;\\\" d=\\\"M539 950l-149 -149l212 -212l149 148l248 -237v700h-699zM297 709l-97 -97l212 -212l98 97zM25 300h1048q11 0 19 -7.5t8 -17.5v-275h-1100v275q0 11 7 18t18 7zM1000 200h-100v-50h100v50z\\\" />\\n<glyph unicode=\\\"&#xe171;\\\" d=\\\"M1200 1199v-1079l-475 272l-310 -393v416h-392zM1166 1148l-672 -712v-226z\\\" />\\n<glyph unicode=\\\"&#xe172;\\\" d=\\\"M1100 1000v-850q0 -21 -15 -35.5t-35 -14.5h-150v400h-700v-400h-150q-21 0 -35.5 14.5t-14.5 35.5v1000q0 20 14.5 35t35.5 15h250v-300h500v300h100zM700 1200h-100v-200h100v200z\\\" />\\n<glyph unicode=\\\"&#xe173;\\\" d=\\\"M578 500h-378v-400h-150q-21 0 -35.5 14.5t-14.5 35.5v1000q0 20 14.5 35t35.5 15h250v-300h500v300h100l200 -200v-218l-276 -275l-120 120zM700 1200h-100v-200h100v200zM1300 538l-475 -476l-244 244l123 123l120 -120l353 352z\\\" />\\n<glyph unicode=\\\"&#xe174;\\\" d=\\\"M529 500h-329v-400h-150q-21 0 -35.5 14.5t-14.5 35.5v1000q0 20 14.5 35t35.5 15h250v-300h500v300h100l200 -200v-269l-103 -103l-170 170zM700 1200h-100v-200h100v200zM1167 6l-170 170l-170 -170l-127 127l170 170l-170 170l127 127l170 -170l170 170l127 -128 l-170 -169l170 -170z\\\" />\\n<glyph unicode=\\\"&#xe175;\\\" d=\\\"M700 500h-500v-400h-150q-21 0 -35.5 14.5t-14.5 35.5v1000q0 20 14.5 35t35.5 15h250v-300h500v300h100l200 -200v-300h-400v-200zM700 1000h-100v200h100v-200zM1000 600h-200v-300h-200l300 -300l300 300h-200v300z\\\" />\\n<glyph unicode=\\\"&#xe176;\\\" d=\\\"M602 500h-402v-400h-150q-21 0 -35.5 14.5t-14.5 35.5v1000q0 20 14.5 35t35.5 15h250v-300h500v300h100l200 -200v-402l-200 200zM700 1000h-100v200h100v-200zM1000 300h200l-300 300l-300 -300h200v-300h200v300z\\\" />\\n<glyph unicode=\\\"&#xe177;\\\" d=\\\"M1200 900v150q0 21 -14.5 35.5t-35.5 14.5h-1100q-21 0 -35.5 -14.5t-14.5 -35.5v-150h1200zM0 800v-550q0 -21 14.5 -35.5t35.5 -14.5h1100q21 0 35.5 14.5t14.5 35.5v550h-1200zM100 500h400v-200h-400v200z\\\" />\\n<glyph unicode=\\\"&#xe178;\\\" d=\\\"M500 1000h400v198l300 -298l-300 -298v198h-400v200zM100 800v200h100v-200h-100zM400 800h-100v200h100v-200zM700 300h-400v-198l-300 298l300 298v-198h400v-200zM800 500h100v-200h-100v200zM1000 500v-200h100v200h-100z\\\" />\\n<glyph unicode=\\\"&#xe179;\\\" d=\\\"M1200 50v1106q0 31 -18 40.5t-44 -7.5l-276 -117q-25 -16 -43.5 -50.5t-18.5 -65.5v-359q0 -29 10.5 -55.5t25 -43t29 -28.5t25.5 -18l10 -5v-397q0 -21 14.5 -35.5t35.5 -14.5h200q21 0 35.5 14.5t14.5 35.5zM550 1200l50 -100v-400l-100 -203v-447q0 -21 -14.5 -35.5 t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v447l-100 203v400l50 100l50 -100v-300h100v300l50 100l50 -100v-300h100v300z\\\" />\\n<glyph unicode=\\\"&#xe180;\\\" d=\\\"M1100 106v888q0 22 25 34.5t50 13.5l25 2v56h-400v-56q75 0 87.5 -6t12.5 -44v-394h-500v394q0 38 12.5 44t87.5 6v56h-400v-56q4 0 11 -0.5t24 -3t30 -7t24 -15t11 -24.5v-888q0 -22 -25 -34.5t-50 -13.5l-25 -2v-56h400v56q-75 0 -87.5 6t-12.5 44v394h500v-394 q0 -38 -12.5 -44t-87.5 -6v-56h400v56q-4 0 -11 0.5t-24 3t-30 7t-24 15t-11 24.5z\\\" />\\n<glyph unicode=\\\"&#xe181;\\\" d=\\\"M675 1000l-100 100h-375l-100 -100h400l200 -200v-98l295 98h105v200h-425zM500 300v500q0 41 -29.5 70.5t-70.5 29.5h-300q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5t70.5 -29.5h300q41 0 70.5 29.5t29.5 70.5zM100 800h300v-200h-300v200zM700 565l400 133 v-163l-400 -133v163zM100 500h300v-200h-300v200zM805 300l295 98v-298h-425l-100 -100h-375l-100 100h400l200 200h105z\\\" />\\n<glyph unicode=\\\"&#xe182;\\\" d=\\\"M179 1169l-162 -162q-1 -11 -0.5 -32.5t16 -90t46.5 -140t104 -177.5t175 -208q103 -103 207.5 -176t180 -103.5t137 -47t92.5 -16.5l31 1l163 162q16 17 13 40.5t-22 37.5l-192 136q-19 14 -45 12t-42 -19l-119 -118q-143 103 -267 227q-126 126 -227 268l118 118 q17 17 20 41.5t-11 44.5l-139 194q-14 19 -36.5 22t-40.5 -14z\\\" />\\n<glyph unicode=\\\"&#xe183;\\\" d=\\\"M1200 712v200q-6 8 -19 20.5t-63 45t-112 57t-171 45t-235 20.5q-92 0 -175 -10.5t-141.5 -27t-108.5 -36.5t-81.5 -40t-53.5 -36.5t-31 -27.5l-9 -10v-200q0 -21 14.5 -33.5t34.5 -8.5l202 33q20 4 34.5 21t14.5 38v146q141 24 300 24t300 -24v-146q0 -21 14.5 -38 t34.5 -21l202 -33q20 -4 34.5 8.5t14.5 33.5zM800 650l365 -303q14 -14 24.5 -39.5t10.5 -45.5v-212q0 -21 -15 -35.5t-35 -14.5h-1100q-21 0 -35.5 14.5t-14.5 35.5v212q0 20 10.5 45.5t24.5 39.5l365 303v50q0 4 1 10.5t12 22.5t30 28.5t60 23t97 10.5t97 -10t60 -23.5 t30 -27.5t12 -24l1 -10v-50z\\\" />\\n<glyph unicode=\\\"&#xe184;\\\" d=\\\"M175 200h950l-125 150v250l100 100v400h-100v-200h-100v200h-200v-200h-100v200h-200v-200h-100v200h-100v-400l100 -100v-250zM1200 100v-100h-1100v100h1100z\\\" />\\n<glyph unicode=\\\"&#xe185;\\\" d=\\\"M600 1100h100q41 0 70.5 -29.5t29.5 -70.5v-1000h-300v1000q0 41 29.5 70.5t70.5 29.5zM1000 800h100q41 0 70.5 -29.5t29.5 -70.5v-700h-300v700q0 41 29.5 70.5t70.5 29.5zM400 0v400q0 41 -29.5 70.5t-70.5 29.5h-100q-41 0 -70.5 -29.5t-29.5 -70.5v-400h300z\\\" />\\n<glyph unicode=\\\"&#xe186;\\\" d=\\\"M1200 800v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212v500q0 124 88 212t212 88h700q124 0 212 -88t88 -212zM1000 900h-900v-700h900v700zM200 800v-300h200v-100h-200v-100h300v300h-200v100h200v100h-300zM800 800h-200v-500h200v100h100v300h-100 v100zM800 700v-300h-100v300h100z\\\" />\\n<glyph unicode=\\\"&#xe187;\\\" d=\\\"M1200 800v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212v500q0 124 88 212t212 88h700q124 0 212 -88t88 -212zM1000 900h-900v-700h900v700zM400 600h-100v200h-100v-500h100v200h100v-200h100v500h-100v-200zM800 800h-200v-500h200v100h100v300h-100 v100zM800 700v-300h-100v300h100z\\\" />\\n<glyph unicode=\\\"&#xe188;\\\" d=\\\"M1200 800v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212v500q0 124 88 212t212 88h700q124 0 212 -88t88 -212zM1000 900h-900v-700h900v700zM200 800v-500h300v100h-200v300h200v100h-300zM600 800v-500h300v100h-200v300h200v100h-300z\\\" />\\n<glyph unicode=\\\"&#xe189;\\\" d=\\\"M1200 800v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212v500q0 124 88 212t212 88h700q124 0 212 -88t88 -212zM1000 900h-900v-700h900v700zM500 700l-300 -150l300 -150v300zM600 400l300 150l-300 150v-300z\\\" />\\n<glyph unicode=\\\"&#xe190;\\\" d=\\\"M1200 800v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212v500q0 124 88 212t212 88h700q124 0 212 -88t88 -212zM1000 900h-900v-700h900v700zM900 800v-500h-700v500h700zM300 400h130q41 0 68 42t27 107t-28.5 108t-66.5 43h-130v-300zM800 700h-130 q-38 0 -66.5 -43t-28.5 -108t27 -107t68 -42h130v300z\\\" />\\n<glyph unicode=\\\"&#xe191;\\\" d=\\\"M1200 800v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212v500q0 124 88 212t212 88h700q124 0 212 -88t88 -212zM1000 900h-900v-700h900v700zM200 800v-300h200v-100h-200v-100h300v300h-200v100h200v100h-300zM800 300h100v500h-200v-100h100v-400z M601 300h100v100h-100v-100z\\\" />\\n<glyph unicode=\\\"&#xe192;\\\" d=\\\"M1200 800v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212v500q0 124 88 212t212 88h700q124 0 212 -88t88 -212zM1000 900h-900v-700h900v700zM300 700v100h-100v-500h300v400h-200zM800 300h100v500h-200v-100h100v-400zM401 400h-100v200h100v-200z M601 300h100v100h-100v-100z\\\" />\\n<glyph unicode=\\\"&#xe193;\\\" d=\\\"M200 1100h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212v500q0 124 88 212t212 88zM1000 900h-900v-700h900v700zM400 700h-200v100h300v-300h-99v-100h-100v100h99v200zM800 700h-100v100h200v-500h-100v400zM201 400h100v-100 h-100v100zM701 300h-100v100h100v-100z\\\" />\\n<glyph unicode=\\\"&#xe194;\\\" d=\\\"M600 1196q162 0 299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299t80 299t217 217t299 80zM600 1014q-171 0 -292.5 -121.5t-121.5 -292.5t121.5 -292.5t292.5 -121.5t292.5 121.5t121.5 292.5t-121.5 292.5t-292.5 121.5zM800 700h-300 v-200h300v-100h-300l-100 100v200l100 100h300v-100z\\\" />\\n<glyph unicode=\\\"&#xe195;\\\" d=\\\"M596 1196q162 0 299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299t80 299t217 217t299 80zM596 1014q-171 0 -292.5 -121.5t-121.5 -292.5t121.5 -292.5t292.5 -121.5t292.5 121.5t121.5 292.5t-121.5 292.5t-292.5 121.5zM800 700v-100 h-100v100h-200v-100h200v-100h-200v-100h-100v400h300zM800 400h-100v100h100v-100z\\\" />\\n<glyph unicode=\\\"&#xe197;\\\" d=\\\"M800 300h128q120 0 205 86t85 208q0 120 -85 206.5t-205 86.5q-46 0 -90 -14q-44 97 -134.5 156.5t-200.5 59.5q-152 0 -260 -107.5t-108 -260.5q0 -25 2 -37q-66 -14 -108.5 -67.5t-42.5 -122.5q0 -80 56.5 -137t135.5 -57h222v300h400v-300zM700 200h200l-300 -300 l-300 300h200v300h200v-300z\\\" />\\n<glyph unicode=\\\"&#xe198;\\\" d=\\\"M600 714l403 -403q94 26 154.5 104t60.5 178q0 121 -85 207.5t-205 86.5q-46 0 -90 -14q-44 97 -134.5 156.5t-200.5 59.5q-152 0 -260 -107.5t-108 -260.5q0 -25 2 -37q-66 -14 -108.5 -67.5t-42.5 -122.5q0 -80 56.5 -137t135.5 -57h8zM700 -100h-200v300h-200l300 300 l300 -300h-200v-300z\\\" />\\n<glyph unicode=\\\"&#xe199;\\\" d=\\\"M700 200h400l-270 300h170l-270 300h170l-300 333l-300 -333h170l-270 -300h170l-270 -300h400v-155l-75 -45h350l-75 45v155z\\\" />\\n<glyph unicode=\\\"&#xe200;\\\" d=\\\"M700 45v306q46 -30 100 -30q74 0 126.5 52.5t52.5 126.5q0 24 -9 55q50 32 79.5 83t29.5 112q0 90 -61.5 155.5t-150.5 71.5q-26 89 -99.5 145.5t-167.5 56.5q-116 0 -197.5 -81.5t-81.5 -197.5q0 -4 1 -12t1 -11q-14 2 -23 2q-74 0 -126.5 -52.5t-52.5 -126.5 q0 -53 28.5 -97t75.5 -65q-4 -16 -4 -38q0 -74 52.5 -126.5t126.5 -52.5q56 0 100 30v-306l-75 -45h350z\\\" />\\n<glyph unicode=\\\"&#x1f4bc;\\\" d=\\\"M800 1000h300q41 0 70.5 -29.5t29.5 -70.5v-400h-500v100h-200v-100h-500v400q0 41 29.5 70.5t70.5 29.5h300v100q0 41 29.5 70.5t70.5 29.5h200q41 0 70.5 -29.5t29.5 -70.5v-100zM500 1000h200v100h-200v-100zM1200 400v-200q0 -41 -29.5 -70.5t-70.5 -29.5h-1000 q-41 0 -70.5 29.5t-29.5 70.5v200h1200z\\\" />\\n<glyph unicode=\\\"&#x1f4c5;\\\" d=\\\"M1100 900v150q0 21 -14.5 35.5t-35.5 14.5h-150v100h-100v-100h-500v100h-100v-100h-150q-21 0 -35.5 -14.5t-14.5 -35.5v-150h1100zM0 800v-750q0 -20 14.5 -35t35.5 -15h1000q21 0 35.5 15t14.5 35v750h-1100zM100 600h100v-100h-100v100zM300 600h100v-100h-100v100z M500 600h100v-100h-100v100zM700 600h100v-100h-100v100zM900 600h100v-100h-100v100zM100 400h100v-100h-100v100zM300 400h100v-100h-100v100zM500 400h100v-100h-100v100zM700 400h100v-100h-100v100zM900 400h100v-100h-100v100zM100 200h100v-100h-100v100zM300 200 h100v-100h-100v100zM500 200h100v-100h-100v100zM700 200h100v-100h-100v100zM900 200h100v-100h-100v100z\\\" />\\n<glyph unicode=\\\"&#x1f4cc;\\\" d=\\\"M902 1185l283 -282q15 -15 15 -36t-15 -35q-14 -15 -35 -15t-35 15l-36 35l-279 -267v-300l-212 210l-208 -207l-380 -303l303 380l207 208l-210 212h300l267 279l-35 36q-15 14 -15 35t15 35q14 15 35 15t35 -15z\\\" />\\n<glyph unicode=\\\"&#x1f4ce;\\\" d=\\\"M518 119l69 -60l517 511q67 67 95 157t11 183q-16 87 -67 154t-130 103q-69 33 -152 33q-107 0 -197 -55q-40 -24 -111 -95l-512 -512q-68 -68 -81 -163t35 -173q35 -57 94 -89t129 -32q63 0 119 28q33 16 65 40.5t52.5 45.5t59.5 64q40 44 57 61l394 394q35 35 47 84 t-3 96q-27 87 -117 104q-20 2 -29 2q-46 0 -79.5 -17t-67.5 -51l-388 -396l-7 -7l69 -67l377 373q20 22 39 38q23 23 50 23q38 0 53 -36q16 -39 -20 -75l-547 -547q-52 -52 -125 -52q-55 0 -100 33t-54 96q-5 35 2.5 66t31.5 63t42 50t56 54q24 21 44 41l348 348 q52 52 82.5 79.5t84 54t107.5 26.5q25 0 48 -4q95 -17 154 -94.5t51 -175.5q-7 -101 -98 -192l-252 -249l-253 -256z\\\" />\\n<glyph unicode=\\\"&#x1f4f7;\\\" d=\\\"M1200 200v600q0 41 -29.5 70.5t-70.5 29.5h-150q-4 8 -11.5 21.5t-33 48t-53 61t-69 48t-83.5 21.5h-200q-41 0 -82 -20.5t-70 -50t-52 -59t-34 -50.5l-12 -20h-150q-41 0 -70.5 -29.5t-29.5 -70.5v-600q0 -41 29.5 -70.5t70.5 -29.5h1000q41 0 70.5 29.5t29.5 70.5z M1000 700h-100v100h100v-100zM844 500q0 -100 -72 -172t-172 -72t-172 72t-72 172t72 172t172 72t172 -72t72 -172zM706 500q0 44 -31 75t-75 31t-75 -31t-31 -75t31 -75t75 -31t75 31t31 75z\\\" />\\n<glyph unicode=\\\"&#x1f512;\\\" d=\\\"M900 800h100q41 0 70.5 -29.5t29.5 -70.5v-600q0 -41 -29.5 -70.5t-70.5 -29.5h-900q-41 0 -70.5 29.5t-29.5 70.5v600q0 41 29.5 70.5t70.5 29.5h100v200q0 82 59 141t141 59h300q82 0 141 -59t59 -141v-200zM400 800h300v150q0 21 -14.5 35.5t-35.5 14.5h-200 q-21 0 -35.5 -14.5t-14.5 -35.5v-150z\\\" />\\n<glyph unicode=\\\"&#x1f514;\\\" d=\\\"M1062 400h17q20 0 33.5 -14.5t13.5 -35.5q0 -20 -13 -40t-31 -27q-22 -9 -63 -23t-167.5 -37t-251.5 -23t-245.5 20.5t-178.5 41.5l-58 20q-18 7 -31 27.5t-13 40.5q0 21 13.5 35.5t33.5 14.5h17l118 173l63 327q15 77 76 140t144 83l-18 32q-6 19 3 32t29 13h94 q20 0 29 -10.5t3 -29.5l-18 -37q83 -19 144 -82.5t76 -140.5l63 -327zM600 104q-54 0 -103 6q12 -49 40 -79.5t63 -30.5t63 30.5t39 79.5q-48 -6 -102 -6z\\\" />\\n<glyph unicode=\\\"&#x1f516;\\\" d=\\\"M200 0l450 444l450 -443v1150q0 20 -14.5 35t-35.5 15h-800q-21 0 -35.5 -15t-14.5 -35v-1151z\\\" />\\n<glyph unicode=\\\"&#x1f525;\\\" d=\\\"M400 755q2 -12 8 -41.5t8 -43t6 -39.5t3.5 -39.5t-1 -33.5t-6 -31.5t-13.5 -24t-21 -20.5t-31 -12q-38 -10 -67 13t-40.5 61.5t-15 81.5t10.5 75q-52 -46 -83.5 -101t-39 -107t-7.5 -85t5 -63q9 -56 44 -119.5t105 -108.5q31 -21 64 -16t62 23.5t57 49.5t48 61.5t35 60.5 q32 66 39 184.5t-13 157.5q79 -80 122 -164t26 -184q-5 -33 -20.5 -69.5t-37.5 -80.5q-10 -19 -14.5 -29t-12 -26t-9 -23.5t-3 -19t2.5 -15.5t11 -9.5t19.5 -5t30.5 2.5t42 8q57 20 91 34t87.5 44.5t87 64t65.5 88.5t47 122q38 172 -44.5 341.5t-246.5 278.5q22 -44 43 -129 q39 -159 -32 -154q-15 2 -33 9q-79 33 -120.5 100t-44 175.5t48.5 257.5q-13 -8 -34 -23.5t-72.5 -66.5t-88.5 -105.5t-60 -138t-8 -166.5z\\\" />\\n<glyph unicode=\\\"&#x1f527;\\\" d=\\\"M948 778l251 126q13 -175 -151 -267q-123 -70 -253 -23l-596 -596q-15 -16 -36.5 -16t-36.5 16l-111 110q-15 15 -15 36.5t15 37.5l600 599q-33 101 6 201.5t135 154.5q164 92 306 -9l-259 -138z\\\" />\\n</font>\\n</defs></svg> \",\"glyphicons-halflings-regular.ttf\":\"\\u0000\\u0001\\u0000\\u0000\\u0000\\u000f\\u0000�\\u0000\\u0003\\u0000pFFTMh+�\\r\\u0000\\u0000\\u0000�\\u0000\\u0000\\u0000\\u001cGDEF\\u0001\\b\\u0000\\u0004\\u0000\\u0000\\u0001\\u0018\\u0000\\u0000\\u0000 OS/2i\\u001el�\\u0000\\u0000\\u00018\\u0000\\u0000\\u0000`cmap�/V�\\u0000\\u0000\\u0001�\\u0000\\u0000\\u0005.cvt \\u0000(\\u0002�\\u0000\\u0000\\u0006�\\u0000\\u0000\\u0000\\u0004gasp��\\u0000\\u0003\\u0000\\u0000\\u0006�\\u0000\\u0000\\u0000\\bglyf\\u0001��\\u0016\\u0000\\u0000\\u0006�\\u0000\\u0000[Xhead\\u00008=�\\u0000\\u0000b,\\u0000\\u0000\\u00006hhea\\n�\\u0004x\\u0000\\u0000bd\\u0000\\u0000\\u0000$hmtx�\\u000e\\u0012p\\u0000\\u0000b�\\u0000\\u0000\\u0002�loca���@\\u0000\\u0000ep\\u0000\\u0000\\u0001�maxp\\u0001.\\u0000�\\u0000\\u0000g(\\u0000\\u0000\\u0000 nameԖ��\\u0000\\u0000gH\\u0000\\u0000\\u0003|post�cQw\\u0000\\u0000j�\\u0000\\u0000\\bywebfK)Q�\\u0000\\u0000s@\\u0000\\u0000\\u0000\\u0006\\u0000\\u0000\\u0000\\u0001\\u0000\\u0000\\u0000\\u0000�=��\\u0000\\u0000\\u0000\\u0000��\\u0017�\\u0000\\u0000\\u0000\\u0000����\\u0000\\u0001\\u0000\\u0000\\u0000\\u000e\\u0000\\u0000\\u0000\\u0018\\u0000\\u0000\\u0000\\u0000\\u0000\\u0002\\u0000\\u0001\\u0000\\u0001\\u0000�\\u0000\\u0001\\u0000\\u0004\\u0000\\u0000\\u0000\\u0002\\u0000\\u0000\\u0000\\u0003\\u0004�\\u0001�\\u0000\\u0005\\u0000\\u0004\\u0003\\f\\u0002�\\u0000\\u0000\\u0000Z\\u0003\\f\\u0002�\\u0000\\u0000\\u0001�\\u00002\\u0002�\\u0000\\u0000\\u0000\\u0000\\u0005\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0002\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000UKWN\\u0000@\\u0000 ��\\u0005x��\\u0000\\u001c\\u0005�\\u0000\\f\\u0000\\u0000\\u0000\\u0001\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000 \\u0000\\u0001\\u0000\\u0000\\u0000\\u0005\\u0000\\u0000\\u0000\\u0003\\u0000\\u0000\\u0000,\\u0000\\u0000\\u0000\\n\\u0000\\u0000\\u0001�\\u0000\\u0001\\u0000\\u0000\\u0000\\u0000\\u0004(\\u0000\\u0003\\u0000\\u0001\\u0000\\u0000\\u0000,\\u0000\\u0003\\u0000\\n\\u0000\\u0000\\u0001�\\u0000\\u0004\\u0001p\\u0000\\u0000\\u0000X\\u0000@\\u0000\\u0005\\u0000\\u0018\\u0000 \\u0000+\\u0000� \\n / _ �\\\"\\u0012&\\u0001'\\t'\\u000f�\\u0003�\\t�\\u0019�)�2�9�C�E�I�Y�`�i�y�����\\u0003�\\b�\\u0019�\\\"�)�5�8�A�E�I�Y�i�y�������\\u0000��\\u0000\\u0000\\u0000 \\u0000*\\u0000� \\u0000 / _ �\\\"\\u0012&\\u0001'\\t'\\u000f�\\u0000�\\u0005�\\u0010� �0�4�@�E�G�P�`�b�p�����\\u0001�\\u0005�\\u0010� �$�0�7�@�C�H�P�`�p�������\\u0000�������f�\\u0007��ߴ�h�\\u0003�\\u0015�\\u000e�\\t \\u0019 \\u0018 \\u0012 \\f \\u0006 \\u0005\\u001f�\\u001f�\\u001f�\\u001f�\\u001f�\\u001f�\\u001f�\\u001f�\\u001f�\\u001fu\\u001ft\\u001fm\\u001fg\\u001ff\\u001f`\\u001f_\\u001fX\\u001fW\\u001fU\\u001fO\\u001fI\\u001fC\\u001f=\\u001f7\\u001f6\\u001e�\\u0000\\u0001\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\f\\u0000\\u0000\\u0000\\u0000\\u0002�\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u00005\\u0000\\u0000\\u0000 \\u0000\\u0000\\u0000 \\u0000\\u0000\\u0000\\u0003\\u0000\\u0000\\u0000*\\u0000\\u0000\\u0000+\\u0000\\u0000\\u0000\\u0004\\u0000\\u0000\\u0000�\\u0000\\u0000\\u0000�\\u0000\\u0000\\u0000\\u0006\\u0000\\u0000 \\u0000\\u0000\\u0000 \\n\\u0000\\u0000\\u0000\\u0007\\u0000\\u0000 /\\u0000\\u0000 /\\u0000\\u0000\\u0000\\u0012\\u0000\\u0000 _\\u0000\\u0000 _\\u0000\\u0000\\u0000\\u0013\\u0000\\u0000 �\\u0000\\u0000 �\\u0000\\u0000\\u0000\\u0014\\u0000\\u0000\\\"\\u0012\\u0000\\u0000\\\"\\u0012\\u0000\\u0000\\u0000\\u0015\\u0000\\u0000&\\u0001\\u0000\\u0000&\\u0001\\u0000\\u0000\\u0000\\u0016\\u0000\\u0000'\\t\\u0000\\u0000'\\t\\u0000\\u0000\\u0000\\u0017\\u0000\\u0000'\\u000f\\u0000\\u0000'\\u000f\\u0000\\u0000\\u0000\\u0018\\u0000\\u0000�\\u0000\\u0000\\u0000�\\u0003\\u0000\\u0000\\u0000\\u0019\\u0000\\u0000�\\u0005\\u0000\\u0000�\\t\\u0000\\u0000\\u0000\\u001d\\u0000\\u0000�\\u0010\\u0000\\u0000�\\u0019\\u0000\\u0000\\u0000\\\"\\u0000\\u0000� \\u0000\\u0000�)\\u0000\\u0000\\u0000,\\u0000\\u0000�0\\u0000\\u0000�2\\u0000\\u0000\\u00006\\u0000\\u0000�4\\u0000\\u0000�9\\u0000\\u0000\\u00009\\u0000\\u0000�@\\u0000\\u0000�C\\u0000\\u0000\\u0000?\\u0000\\u0000�E\\u0000\\u0000�E\\u0000\\u0000\\u0000C\\u0000\\u0000�G\\u0000\\u0000�I\\u0000\\u0000\\u0000D\\u0000\\u0000�P\\u0000\\u0000�Y\\u0000\\u0000\\u0000G\\u0000\\u0000�`\\u0000\\u0000�`\\u0000\\u0000\\u0000Q\\u0000\\u0000�b\\u0000\\u0000�i\\u0000\\u0000\\u0000R\\u0000\\u0000�p\\u0000\\u0000�y\\u0000\\u0000\\u0000Z\\u0000\\u0000��\\u0000\\u0000��\\u0000\\u0000\\u0000d\\u0000\\u0000��\\u0000\\u0000��\\u0000\\u0000\\u0000n\\u0000\\u0000�\\u0001\\u0000\\u0000�\\u0003\\u0000\\u0000\\u0000v\\u0000\\u0000�\\u0005\\u0000\\u0000�\\b\\u0000\\u0000\\u0000y\\u0000\\u0000�\\u0010\\u0000\\u0000�\\u0019\\u0000\\u0000\\u0000}\\u0000\\u0000� \\u0000\\u0000�\\\"\\u0000\\u0000\\u0000�\\u0000\\u0000�$\\u0000\\u0000�)\\u0000\\u0000\\u0000�\\u0000\\u0000�0\\u0000\\u0000�5\\u0000\\u0000\\u0000�\\u0000\\u0000�7\\u0000\\u0000�8\\u0000\\u0000\\u0000�\\u0000\\u0000�@\\u0000\\u0000�A\\u0000\\u0000\\u0000�\\u0000\\u0000�C\\u0000\\u0000�E\\u0000\\u0000\\u0000�\\u0000\\u0000�H\\u0000\\u0000�I\\u0000\\u0000\\u0000�\\u0000\\u0000�P\\u0000\\u0000�Y\\u0000\\u0000\\u0000�\\u0000\\u0000�`\\u0000\\u0000�i\\u0000\\u0000\\u0000�\\u0000\\u0000�p\\u0000\\u0000�y\\u0000\\u0000\\u0000�\\u0000\\u0000��\\u0000\\u0000��\\u0000\\u0000\\u0000�\\u0000\\u0000��\\u0000\\u0000��\\u0000\\u0000\\u0000�\\u0000\\u0000��\\u0000\\u0000��\\u0000\\u0000\\u0000�\\u0000\\u0000�\\u0000\\u0000\\u0000�\\u0000\\u0000\\u0000\\u0000�\\u0000\\u0001��\\u0000\\u0001��\\u0000\\u0000\\u0000�\\u0000\\u0001��\\u0000\\u0001��\\u0000\\u0000\\u0000�\\u0000\\u0001��\\u0000\\u0001��\\u0000\\u0000\\u0000�\\u0000\\u0001��\\u0000\\u0001��\\u0000\\u0000\\u0000�\\u0000\\u0001��\\u0000\\u0001��\\u0000\\u0000\\u0000�\\u0000\\u0001�\\u0012\\u0000\\u0001�\\u0012\\u0000\\u0000\\u0000�\\u0000\\u0001�\\u0014\\u0000\\u0001�\\u0014\\u0000\\u0000\\u0000�\\u0000\\u0001�\\u0016\\u0000\\u0001�\\u0016\\u0000\\u0000\\u0000�\\u0000\\u0001�%\\u0000\\u0001�%\\u0000\\u0000\\u0000�\\u0000\\u0001�'\\u0000\\u0001�'\\u0000\\u0000\\u0000�\\u0000\\u0000\\u0001\\u0006\\u0000\\u0000\\u0001\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0001\\u0002\\u0000\\u0000\\u0000\\u0002\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0001\\u0000\\u0000\\u0003\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0004\\u0005\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0006\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0014\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000(\\u0002�\\u0000\\u0000\\u0000\\u0001��\\u0000\\u0002\\u0000\\u0002\\u0000(\\u0000\\u0000\\u0001h\\u0003 \\u0000\\u0003\\u0000\\u0007\\u0000.�\\u0001\\u0000/<�\\u0007\\u0004\\u0000�2�\\u0006\\u0005�<�\\u0003\\u0002\\u0000�2\\u0000�\\u0003\\u0000/<�\\u0005\\u0004\\u0000�2�\\u0007\\u0006\\u0001�<�\\u0001\\u0002\\u0000�23\\u0011!\\u0011%3\\u0011#(\\u0001@����\\u0003 ��(\\u0002�\\u0000\\u0001\\u0000d\\u0000d\\u0004L\\u0004L\\u0000\\u0017\\u0000\\u0000\\u0001!\\u0017\\u0007'\\u0011#\\u0011\\u0007'7!5!'7\\u0017\\u00113\\u00117\\u0017\\u0007!\\u0004L�����ȷ����\\u0001\\u0003���ȷ��\\u0001\\u0003\\u0001𷍷��\\u0001\\u0003���ȷ��\\u0001\\u0003�����\\u0000\\u0000\\u0000\\u0000\\u0001\\u0000\\u0000\\u0000\\u0000\\u0004L\\u0004L\\u0000\\u000b\\u0000\\u0000\\u0001!\\u0011!\\u0011!\\u0011!\\u0011!\\u0011!\\u0004L�p���p\\u0001�\\u0001,\\u0001�\\u0001��p\\u0001�\\u0001,\\u0001��p\\u0000\\u0001\\u0000d\\u0000\\u0005\\u0004�\\u0004�\\u00007\\u0000\\u0000\\u0001!\\u001e\\u000432>\\u000253\\u0006\\u0007\\u0006#\\\"'.\\u0001'#7347#7367632\\u0017\\u0016\\u0017#4.\\u0002#\\\"\\u000e\\u0002\\u0007!\\u0007!\\u0006\\u0015!\\u0003 ��\\t09C3\\u0015\\u001dJL3�\\u001fak��w$B\\f�dq\\u0005�d�%Ku��p<\\u0006�3LJ\\u001e\\u00189D?\\u0013\\u0001{d��\\u0006\\u0001�\\u0001�JtB+\\u000f\\u001a0W5�ju�.�xd/5d�Z��gj7X0\\u0019\\u0014,Z>d.6\\u0000\\u0001\\u0000�\\u0001�\\u0004L\\u0002�\\u0000\\u0003\\u0000\\u0000\\u0001!\\u0011!\\u0004L�|\\u0003�\\u0002���\\u0000\\u0001��\\u0001,\\u0004�\\u0004A\\u0000\\u0016\\u0000\\u0000\\u0013!2654&#\\\"\\u0007.\\u0001#\\\"\\u0006\\u0015\\u0014\\u0017\\u000e\\u0001\\u0015\\u0014\\u0016�\\u0002�x��x.,,�n��\\u0002BUq\\u0001,�zx�\\u000eawי\\u0019\\f\\u000ekEPr\\u0000\\u0000\\u0000\\u0000\\u0004\\u0000\\u0000\\u0000d\\u0004�\\u0004L\\u0000\\u0002\\u0000\\u0005\\u0000\\b\\u0000\\r\\u0000\\u0000\\u0001!\\u0001%\\u0001\\u0011!\\u0011\\u0001\\u0007\\u0001!\\u0001\\u0017\\u0004��P\\u0002X����\\u0004���d\\u0001��P\\u0001��\\u0004L��g��\\u0002X��\\u0001,d�p\\u0001��\\u0000\\u0000\\u0003����\\u0004�\\u0004�\\u0000\\t\\u0000\\r\\u0000\\u0010\\u0000\\u0000\\u0001764/\\u0001&\\\"\\u000f\\u0001\\t\\u0001'\\u0001\\u0003%'\\u0004Mc\\r\\r�\\u000f$\\u000f^�\\u001a\\u0002f����\\u0001M�\\u0003y\\\\\\r'\\u000e�\\r\\ra�n\\u0002f����`p�\\u0000\\u0000\\u0000\\u0000\\u0001\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u00001\\u0000\\u0000\\u0001\\u0000\\u0000\\u0000\\u0000\\u0004�\\u0004�\\u0000\\t\\u0000\\u0000%!\\u0015!5!\\u0011\\u0001!\\u0001\\u0002�\\u0001,��\\u0001,�\\f\\u0004��\\fddd\\u0002&\\u0002&��\\u0000\\u0000\\u0001\\u0000\\u000e\\u0000\\b\\u0004L\\u0004�\\u0000 \\u0000\\u0000\\u0001\\u0011&\\u0007\\u000e\\u0001\\u0017\\u001e\\u00017>\\u00015\\u00114&\\u0007\\u0005\\u000e\\u0001\\u0015\\u0011&\\u0007\\u000e\\u0001\\u001e\\u00017>\\u00015\\u0011\\u0003�@JOW\\u0012\\u0011�OFS\\u000e\\n�\\u0010\\n\\u000e@JOW$�OAX\\u0003���\\u0010\\u0017\\u001ar67)\\u0019\\u0017Q7\\u0003q\\n\\u000b\\u0003�\\u0003\\u0013\\n�O\\u0011\\u0018\\u0019rn)\\u001a\\u0015`*\\u0002^\\u0000\\u0002\\u0000\\u0017��\\u0004�\\u0004�\\u0000\\u0013\\u0000\\u001b\\u0000\\u0000\\t\\u0001\\u0016\\u0014\\u000f\\u0001\\u0006\\\"'\\u0001\\u0006#\\\"\\u0000\\u0010\\u0000 \\u0000\\u0015\\u0014\\u0000\\u0010\\u0016 6\\u0010& \\u0003�\\u0001,\\u0007\\u0007m\\b\\u0014\\b��w����\\u0001\\u001c\\u0001�\\u0001\\u001c���\\u0001\\u0012����\\u0001���\\b\\u0014\\bm\\u0007\\u0007\\u0001,N\\u0001\\u001c\\u0001�\\u0001\\u001c��Ȏ\\u0001\\u0016����\\u0001\\u0012�\\u0000\\u0001\\u0000d\\u0000X\\u0004�\\u0004D\\u0000\\u0019\\u0000\\u0000\\u0001>\\u0002\\u001e\\u0002\\u0015\\u0014\\u000e\\u0003\\u0007.\\u000454>\\u0002\\u001e\\u0001\\u0002�0{xuX6Cy��>>��yC8Zwwy\\u0003�EH\\u0004-Sv@9y��UU��y9@vS-\\u0004I\\u0000\\u0000\\u0000\\u0002��\\u0000G\\u0004�\\u0004�\\u0000\\n\\u0000\\f\\u0000\\u0000\\u0001\\u0013\\t\\u0001\\u0013\\u0001!\\u00133\\u0013!\\u00017\\u0003\\u0017�������|\\u0001ߒ\\u0002�\\u0001��\\u0013\\u0002\\u0002\\n�?\\u0001\\u0013��\\u0001�\\u0001\\u0018\\u0001��p�'\\u0001\\u0000\\u0003��\\u0000G\\u0004�\\u0004�\\u0000\\n\\u0000\\u0014\\u0000\\u0016\\u0000\\u0000\\u0001\\u0013\\t\\u0001\\u0013\\u0001!\\u00133\\u0013!\\u0001'7#'\\u0007#\\u0017\\u00077\\u00017\\u0003\\u0017�������|\\u0001ߒ\\u0002�\\u0001��VJ��MN��I���\\u0002\\u0002\\n�?\\u0001\\u0013��\\u0001�\\u0001\\u0018\\u0001��p�+���ӎ���o\\u0001\\u0000\\u0001\\u0000\\u0000\\u0000\\u0000\\u0004�\\u0004�\\u0000\\u0013\\u0000\\u0000%\\u0015!5\\u00015\\\"&=\\u0001462\\u0016\\u001d\\u0001\\u0014\\u0006#\\u0015\\u0004��P\\u0001�%?���?%���\\u0001\\u0001d�3�|��|�3�d\\u0000\\r\\u0000\\u0000\\u0000\\u0000\\u0004�\\u0004L\\u0000\\u0003\\u0000\\u0007\\u0000\\u000b\\u0000\\u000f\\u0000\\u0013\\u0000\\u0017\\u0000\\u001b\\u0000\\u001f\\u0000#\\u0000'\\u0000+\\u0000/\\u00003\\u0000\\u0000\\u0001\\u0011!\\u0011\\u0017#\\u00153%!\\u0011!\\u0013#\\u00153\\u0005#\\u00153%#\\u00153\\u0005#\\u00153%#\\u00153#!\\u0011!\\u0001#\\u00153%#\\u00153\\u0005#\\u00153%#\\u00153\\u0004��P�dd\\u0002���\\u0002X�dd�|dd\\u0003�dd�|dd\\u0003�dd���\\u0002X�Ddd\\u0003�dd�|dd\\u0003�dd\\u0004L��\\u0004Lddd�p\\u0001�ddddddddd�p\\u0001,ddddddd\\u0000\\u0004\\u0000\\u0000\\u0000\\u0000\\u0004L\\u0004L\\u0000\\u000f\\u0000\\u001f\\u0000/\\u0000?\\u0000\\u0000\\u0001\\u0011\\u0014\\u0006#!\\\"&5\\u0011463!2\\u0016\\u0005\\u0011\\u0014\\u0006#!\\\"&5\\u0011463!2\\u0016\\u0001\\u0011\\u0014\\u0006#!\\\"&5\\u0011463!2\\u0016\\u0005\\u0011\\u0014\\u0006#!\\\"&5\\u0011463!2\\u0016\\u0001�\\u001d\\u0015�p\\u0015\\u001d\\u001d\\u0015\\u0001�\\u0015\\u001d\\u0002X\\u001d\\u0015�p\\u0015\\u001d\\u001d\\u0015\\u0001�\\u0015\\u001d��\\u001d\\u0015�p\\u0015\\u001d\\u001d\\u0015\\u0001�\\u0015\\u001d\\u0002X\\u001d\\u0015�p\\u0015\\u001d\\u001d\\u0015\\u0001�\\u0015\\u001d\\u0004\\u001a�p\\u0015\\u001d\\u001d\\u0015\\u0001�\\u0015\\u001d\\u001d\\u0015�p\\u0015\\u001d\\u001d\\u0015\\u0001�\\u0015\\u001d\\u001d���p\\u0015\\u001d\\u001d\\u0015\\u0001�\\u0015\\u001d\\u001d\\u0015�p\\u0015\\u001d\\u001d\\u0015\\u0001�\\u0015\\u001d\\u001d\\u0000\\u0000\\u0000\\t\\u0000\\u0000\\u0000\\u0000\\u0004L\\u0004L\\u0000\\u000f\\u0000\\u001f\\u0000/\\u0000?\\u0000O\\u0000_\\u0000o\\u0000\\u0000�\\u0000\\u0000\\u0001\\u0015\\u0014\\u0006+\\u0001\\\"&=\\u000146;\\u00012\\u0016\\u0005\\u0015\\u0014\\u0006+\\u0001\\\"&=\\u000146;\\u00012\\u0016\\u0005\\u0015\\u0014\\u0006+\\u0001\\\"&=\\u000146;\\u00012\\u0016\\u0001\\u0015\\u0014\\u0006+\\u0001\\\"&=\\u000146;\\u00012\\u0016\\u0005\\u0015\\u0014\\u0006+\\u0001\\\"&=\\u000146;\\u00012\\u0016\\u0005\\u0015\\u0014\\u0006+\\u0001\\\"&=\\u000146;\\u00012\\u0016\\u0001\\u0015\\u0014\\u0006+\\u0001\\\"&=\\u000146;\\u00012\\u0016\\u0005\\u0015\\u0014\\u0006+\\u0001\\\"&=\\u000146;\\u00012\\u0016\\u0005\\u0015\\u0014\\u0006+\\u0001\\\"&=\\u000146;\\u00012\\u0016\\u0001,\\u001d\\u0015�\\u0015\\u001d\\u001d\\u0015�\\u0015\\u001d\\u0001�\\u001d\\u0015�\\u0015\\u001d\\u001d\\u0015�\\u0015\\u001d\\u0001�\\u001d\\u0015�\\u0015\\u001d\\u001d\\u0015�\\u0015\\u001d��\\u001d\\u0015�\\u0015\\u001d\\u001d\\u0015�\\u0015\\u001d\\u0001�\\u001d\\u0015�\\u0015\\u001d\\u001d\\u0015�\\u0015\\u001d\\u0001�\\u001d\\u0015�\\u0015\\u001d\\u001d\\u0015�\\u0015\\u001d��\\u001d\\u0015�\\u0015\\u001d\\u001d\\u0015�\\u0015\\u001d\\u0001�\\u001d\\u0015�\\u0015\\u001d\\u001d\\u0015�\\u0015\\u001d\\u0001�\\u001d\\u0015�\\u0015\\u001d\\u001d\\u0015�\\u0015\\u001d\\u0004\\u001a�\\u0015\\u001d\\u001d\\u0015�\\u0015\\u001d\\u001d\\u0015�\\u0015\\u001d\\u001d\\u0015�\\u0015\\u001d\\u001d\\u0015�\\u0015\\u001d\\u001d\\u0015�\\u0015\\u001d\\u001d�[�\\u0015\\u001d\\u001d\\u0015�\\u0015\\u001d\\u001d\\u0015�\\u0015\\u001d\\u001d\\u0015�\\u0015\\u001d\\u001d\\u0015�\\u0015\\u001d\\u001d\\u0015�\\u0015\\u001d\\u001d�[�\\u0015\\u001d\\u001d\\u0015�\\u0015\\u001d\\u001d\\u0015�\\u0015\\u001d\\u001d\\u0015�\\u0015\\u001d\\u001d\\u0015�\\u0015\\u001d\\u001d\\u0015�\\u0015\\u001d\\u001d\\u0000\\u0000\\u0006\\u0000\\u0000\\u0000\\u0000\\u0004�\\u0004L\\u0000\\u000f\\u0000\\u001f\\u0000/\\u0000?\\u0000O\\u0000_\\u0000\\u0000\\u0001\\u0015\\u0014\\u0006+\\u0001\\\"&=\\u000146;\\u00012\\u0016\\u0005\\u0015\\u0014\\u0006#!\\\"&=\\u0001463!2\\u0016\\u000154&+\\u0001\\\"\\u0006\\u001d\\u0001\\u0014\\u0016;\\u000126%\\u0015\\u0014\\u0006#!\\\"&=\\u0001463!2\\u0016\\u0001\\u0015\\u0014\\u0006+\\u0001\\\"&=\\u000146;\\u00012\\u0016\\u0005\\u0015\\u0014\\u0006#!\\\"&=\\u0001463!2\\u0016\\u0001,\\u001d\\u0015�\\u0015\\u001d\\u001d\\u0015�\\u0015\\u001d\\u0003�\\u001d\\u0015�D\\u0015\\u001d\\u001d\\u0015\\u0002�\\u0015\\u001d�|\\u001d\\u0015�\\u0015\\u001d\\u001d\\u0015�\\u0015\\u001d\\u0003�\\u001d\\u0015�D\\u0015\\u001d\\u001d\\u0015\\u0002�\\u0015\\u001d�|\\u001d\\u0015�\\u0015\\u001d\\u001d\\u0015�\\u0015\\u001d\\u0003�\\u001d\\u0015�D\\u0015\\u001d\\u001d\\u0015\\u0002�\\u0015\\u001d\\u0004\\u001a�\\u0015\\u001d\\u001d\\u0015�\\u0015\\u001d\\u001d\\u0015�\\u0015\\u001d\\u001d\\u0015�\\u0015\\u001d\\u001d���\\u0015\\u001d\\u001d\\u0015�\\u0015\\u001d\\u001d��\\u0015\\u001d\\u001d\\u0015�\\u0015\\u001d\\u001d�[�\\u0015\\u001d\\u001d\\u0015�\\u0015\\u001d\\u001d\\u0015�\\u0015\\u001d\\u001d\\u0015�\\u0015\\u001d\\u001d\\u0000\\u0000\\u0000\\u0000\\u0001\\u0000\\u001d\\u0000\\\"\\u0004�\\u0004*\\u0000\\u0005\\u0000\\u0000%\\u0001'\\u0001'\\u0007\\u0001�\\u00032�����\\\"\\u00034�����\\u0000\\u0000\\u0000\\u0000\\u0001\\u0000j\\u0000j\\u0004F\\u0004F\\u0000\\u000b\\u0000\\u0000%\\t\\u0001'\\t\\u00017\\t\\u0001\\u0017\\t\\u0001\\u0003r�����\\u0001\\u001a���\\u0001\\u001a\\u0001\\u001a���\\u0001\\u001aj\\u0001\\u001a���\\u0001\\u001a\\u0001\\u001a���\\u0001\\u001a�����\\u0000\\u0000\\u0003\\u0000\\u0017��\\u0004�\\u0004�\\u0000\\u0013\\u0000\\u001b\\u0000'\\u0000\\u0000\\t\\u0001\\u0016\\u0014\\u000f\\u0001\\u0006\\\"'\\u0001\\u0006#\\\"\\u0000\\u0010\\u0000 \\u0000\\u0015\\u0014\\u0004 6\\u0010& \\u0006\\u0010%3\\u0015#\\u0015#5#5353\\u0003�\\u0001,\\u0007\\u0007m\\b\\u0014\\b��w����\\u0001\\u001c\\u0001�\\u0001\\u001c��\\u0001\\u0012�����\\u0001�dd�dd�\\u0001���\\b\\u0014\\bm\\u0007\\u0007\\u0001,N\\u0001\\u001c\\u0001�\\u0001\\u001c��Ȏ��\\u0001\\u0012������dd�d\\u0000\\u0000\\u0003\\u0000\\u0017��\\u0004�\\u0004�\\u0000\\u0013\\u0000\\u001b\\u0000\\u001f\\u0000\\u0000\\t\\u0001\\u0016\\u0014\\u000f\\u0001\\u0006\\\"'\\u0001\\u0006#\\\"\\u0000\\u0010\\u0000 \\u0000\\u0015\\u0014\\u0000\\u0010\\u0016 6\\u0010& \\u0007\\u0015!5\\u0003�\\u0001,\\u0007\\u0007m\\b\\u0014\\b��x����\\u0001\\u001c\\u0001�\\u0001\\u001c���\\u0001\\u0012����F\\u0001�\\u0001���\\u0007\\u0016\\u0007m\\b\\b\\u0001+M\\u0001\\u001c\\u0001�\\u0001\\u001c��ȍ\\u0001\\u0015����\\u0001\\u0010����\\u0000\\u0002\\u0000\\u0017\\u0000\\u0017\\u0004�\\u0004�\\u0000\\u000f\\u0000+\\u0000\\u0000\\u0001\\u00114&+\\u0001\\\"\\u0006\\u0015\\u0011\\u0014\\u0016;\\u00012675\\u0016\\u0012\\u0015\\u0014\\u000e\\u0002\\\".\\u000254\\u00127\\u0015\\u000e\\u0001\\u0015\\u0014\\u0016 654&\\u0002�\\u001d\\u0015d\\u0015\\u001d\\u001d\\u0015d\\u0015\\u001dd��[���՛[ҧg|�\\u0001b�|\\u0002�\\u0001�\\u0015\\u001d\\u001d\\u0015�p\\u0015\\u001d\\u001d��>�طv՛[[��v�\\u0001(>�7�x����x�\\u0000\\u0000\\u0000\\u0004\\u0000d\\u0000\\u0001\\u0004�\\u0004�\\u0000\\u0003\\u0000\\u0007\\u0000\\u000b\\u0000\\u000f\\u0000\\u0000%#\\u00113\\u0001#\\u00113\\u0001#\\u00113\\u0005#\\u00113\\u0004���������������\\u0001\\u0004��P\\u0003 ��\\u0001����\\u0000\\u0000\\u0000\\u0002\\u0000\\u001a\\u0000\\u001b\\u0004�\\u0004�\\u0000G\\u0000Q\\u0000\\u0000%\\u0017\\u001632?\\u00026?\\u0001\\u001767'76?\\u0002654/\\u0002&/\\u00017&'\\u0007'&/\\u0002&#\\\"\\u000f\\u0002\\u0006\\u000f\\u0001'\\u0006\\u0007\\u0017\\u0007\\u0006\\u000f\\u0002\\u0006\\u0015\\u0014\\u001f\\u0002\\u0016\\u001f\\u0001\\u0007\\u0016\\u00177\\u0017\\u0016\\u0017\\u00122\\u0016\\u0015\\u0014\\u0006\\\"&54\\u0001�&(\\\"\\u001b/&\\u0006./\\u0005�80P\\u0003\\u0018\\u000f\\u0001�\\u0005\\u0005�\\u0001\\u0010\\u0017\\u0003P,<�\\u0005-0\\u0006&(\\\"\\u001b/&\\u00052,\\u0005�;.P\\u0003\\u0019\\r\\u0002�\\u0006\\u0006�\\u0002\\u000e\\u0018\\u0003P-<�\\u0005-1\\u001c�~~�~��\\u0005\\u0005�\\u0002\\r\\u001a\\u0003Q,=�\\u0005,1\\u0006&(\\\"\\u001c-&\\u00063*\\u0005�:/Q\\u0003\\u0019\\u000e\\u0001�\\u0005\\u0005�\\u0001\\u000e\\u0019\\u0003Q/:�\\u0005/.\\u0006&0\\u0019!)&\\u00061,\\u0005�;.Q\\u0003\\u001a\\r\\u0002v~XY~~YX\\u0000\\u0000\\u0007\\u0000d��\\u0004�\\u0005\\u0014\\u0000\\u0019\\u0000\\u001d\\u0000'\\u0000+\\u0000/\\u00003\\u00007\\u0000\\u0000\\u0001!2\\u0016\\u001d\\u0001\\u0014\\u0006#!\\\"&=\\u0001463!5463!2\\u0016\\u0015\\u00075!\\u0015\\u0005!\\u0011\\u0014\\u0006#!\\\"&5;\\u0001\\u0011#\\u00133\\u0011#\\u00133\\u0011#\\u00133\\u0011#\\u0003�\\u0001\\u0013\\n\\u000f\\u000e\\u000b��\\u000b\\u000e\\u000f\\n\\u0001\\u0013;)\\u0001,);d����\\u0003�;)�D);ddd�dd�dd�dd\\u0004L\\u000f\\n2\\u000b\\u000e\\u000e\\u000b2\\n\\u000fd);;)ddd���)<<)\\u0002��D\\u0002��D\\u0002��D\\u0002�\\u0000\\u0000\\u0000\\u0001\\u0000\\u0001\\u0000\\u0001\\u0005\\u0015\\u0004�\\u0000\\n\\u0000\\u0000\\u0001#\\u0011!\\u0011!\\u0011!\\u0011#\\u0001\\u0005\\u0015��������\\u0002�\\u0002Y��\\u0001��p\\u0002X\\u0002�\\u0000\\u0000\\u0000\\u0000\\u0002\\u0000d\\u0000\\u0000\\u0003�\\u0004�\\u0000\\u000e\\u0000\\u0011\\u0000\\u0000\\u0001!\\u0011\\u0014\\u0006#!\\\"&5\\u0011463!\\u0001!\\u0011\\u0002X\\u0001�\\u000e\\u000b��\\u000b\\u000e\\u000e\\u000b\\u0001�\\u0001���\\u0002��]\\u000b\\u000e\\u000e\\u000b\\u0004~\\u000b\\u000e�p\\u0001,\\u0000\\u0003\\u0000\\u0004\\u0000\\u0004\\u0004�\\u0004�\\u0000\\u000b\\u0000\\u0013\\u0000\\u0019\\u0000\\u0000\\u0000 \\u0004\\u0012\\u0010\\u0002\\u0004 $\\u0002\\u0010\\u0012\\u0004 \\u0006\\u0010\\u0016 6\\u0010\\u00053\\u0015!\\u00113\\u0001�\\u0001D\\u0001\\u0012�������\\u0002_����\\u0001V��b���d\\u0004�������\\u0001\\u0012\\u0001D\\u0001\\u0012\\u0016�����\\u0001V�d\\u0001�\\u0000\\u0002��\\u0000\\u0000\\u0005\\u0014\\u0004�\\u0000\\u000b\\u0000\\u000f\\u0000\\u0000\\u0001#\\u0003!\\u00013\\u00033\\u00033\\u0001!\\u000b\\u0001#\\u0003\\u0002��(��\\u0001��\\u0015�\\u0014�\\u0001���2\\u001b�\\u001b\\u0001��p\\u0004���\\u0001,�P\\u0001�\\u0001,��\\u0000\\u0000\\u0002\\u0000\\u0000\\u0000\\u0000\\u0004L\\u0004�\\u0000\\u000b\\u0000\\u000f\\u0000\\u0000\\u0001\\u0011!\\u0011!\\u00013\\u0011!\\u00113\\u0001\\u0005#\\u00153\\u0004L��\\u0001����\\u0001,���\\u0001z��\\u0001��p\\u0001�\\u0001,\\u0001��\\f��dd\\u0000\\u0000\\u0000\\u0003\\u0000\\u0001\\u0000\\u0001\\u0004�\\u0004�\\u0000\\u000f\\u0000\\u0017\\u0000\\u001e\\u0000\\u0000\\u00002\\u001e\\u0002\\u0014\\u000e\\u0002\\\".\\u00024>\\u0001\\u0004 \\u0006\\u0010\\u0016 6\\u0010\\u00053\\u000b\\u00013\\u00113\\u0001��ޠ__���ޠ__�\\u0002\\u0002����\\u0001T��Ȗ����\\u0004�_���ޠ__���ޠ\\\\�����\\u0001T���\\u0001,\\u0001,\\u0000\\u0000\\u0003\\u0000\\u0004\\u0000\\u0004\\u0004�\\u0004�\\u0000\\u000b\\u0000\\u0013\\u0000\\u001a\\u0000\\u0000\\u0000 \\u0004\\u0012\\u0010\\u0002\\u0004 $\\u0002\\u0010\\u0012\\u0004 \\u0006\\u0010\\u0016 6\\u0010\\u0007#\\u0011#\\u0011#\\u0013\\u0001�\\u0001D\\u0001\\u0012�������\\u0002_����\\u0001V���Ȗ�\\u0004�������\\u0001\\u0012\\u0001D\\u0001\\u0012\\u0016�����\\u0001V���\\u0001,\\u0001,\\u0000\\u0000\\u0002\\u0000\\u0000\\u0000\\u0000\\u0004�\\u0004�\\u0000\\f\\u0000\\u0014\\u0000\\u0000\\u0011\\u0013!\\u00123\\u0011\\u0014\\u0006#!\\\"&5\\u0001!\\u00033\\u0017!73�\\u0003 �\\u0001\\u000e\\u000b��\\u000b\\u000e\\u0003���a�2\\u0001,2�\\u0001�\\u0002��D�%\\u000b\\u000e\\u000e\\u000b\\u0003��\\f��\\u0000\\u0000\\u0000\\u0000\\u0003\\u0000\\u0004\\u0000\\u0004\\u0004�\\u0004�\\u0000\\u000b\\u0000\\u0015\\u0000\\u0018\\u0000\\u0000\\u0000 \\u0004\\u0012\\u0010\\u0002\\u0004 $\\u0002\\u0010\\u0012\\u0004 \\u0006\\u0015\\u0014\\u0016 654\\u0007\\u0005\\u0011\\u0001�\\u0001D\\u0001\\u0012�������\\u0002_����\\u0001V����\\u0004�������\\u0001\\u0012\\u0001D\\u0001\\u0012\\u0016����򬫭�\\u0001�\\u0000\\u0001\\u0000\\u0017\\u0000\\u0017\\u0004�\\u0004�\\u0000\\u001c\\u0000\\u0000\\u0001#\\u0014\\u0006 &\\u0010632\\u0017\\u0007!\\u0011\\u0007&#\\\"\\u000e\\u0002\\u0014\\u001e\\u00022>\\u0002\\u0004���������n�\\u0001����v՛[[���՛[\\u0002X���\\u0001b�Q�\\u0001��z[���՛[[��\\u0000\\u0002\\u0000\\u0017\\u0000\\u0000\\u0004�\\u0004�\\u0000\\u0010\\u0000!\\u0000\\u0000\\u00017&#\\\"\\u0006\\u0015#4>\\u000232\\u00177\\u0011\\u0001\\u0007\\u001632653\\u0014\\u000e\\u0002#\\\"'\\u0007\\u0011\\u0002��p����[��vƝ����p����[��vƝ�\\u0003 �P��v՛[z��p�p�P��v՛[z�\\u0001�\\u0000\\u0000\\u0000\\n\\u0000d\\u0000\\u0000\\u0004�\\u0004�\\u0000\\u0003\\u0000\\u0007\\u0000\\u000b\\u0000\\u000f\\u0000\\u0013\\u0000\\u0017\\u0000\\u001b\\u0000\\u001f\\u0000#\\u0000'\\u0000\\u0000\\u0013\\u0011!\\u0011\\u0003!\\u0011!\\u0005#53\\u0005!5!\\u0001#53\\u0005!5!\\u0001#53\\u0005!5!\\u0001#53)\\u0001\\u0015!d\\u0004Ld�|\\u0003��Ddd\\u0002X�\\f\\u0001���dd\\u0002X�\\f\\u0001���dd\\u0002X�\\f\\u0001���dd\\u0002X�\\f\\u0001�\\u0004��P\\u0004���\\u0003��ddd��ddd��ddd��dd\\u0000\\u0002\\u0000d\\u0000\\u0000\\u0004L\\u0004L\\u0000\\u0003\\u0000\\u0015\\u0000\\u00003#\\u00113\\u0001\\u0011\\u000e\\u0001.\\u0003\\u0006\\u0007\\u0011>\\u0001\\u001e\\u0002>\\u0001�dd\\u0003�({���tZ\\u0014<�x|rjd\\u0004L�\\f\\u0001�QE\\n((\\nEQ�\\f<0\\r!\\u001b\\u0005O\\u0000\\u0000\\u0000\\u0003\\u0000\\u0000\\u0000\\u0000\\u0004�\\u0004�\\u0000!\\u00001\\u0000A\\u0000\\u0000\\u0001\\u00114.\\u0002\\\"\\u000e\\u0002\\u0015\\u0011\\u0014\\u0016;\\u0001265\\u00114>\\u0001 \\u001e\\u0001\\u0015\\u0011\\u0014\\u0016;\\u000126%\\u0011\\u0014\\u0006+\\u0001\\\"&5\\u001146;\\u00012\\u0016\\u0005\\u0011\\u0014\\u0006+\\u0001\\\"&5\\u001146;\\u00012\\u0016\\u0004�c���ޣc\\u000e\\u000b2\\u000b\\u000e��\\u0001\\u0006��\\u000e\\u000b2\\u000b\\u000e��\\f\\b�\\b\\f\\f\\b�\\b\\f\\u0002X\\f\\b�\\b\\f\\f\\b�\\b\\f\\u0001\\u0013\\u0001,tޣcc��t��\\u000b\\u000e\\u000e\\u000b\\u0001,�rr���\\u000b\\u000e\\u000e��4\\b\\f\\f\\b\\u0001�\\b\\f\\f\\b�4\\b\\f\\f\\b\\u0001�\\b\\f\\f\\u0000\\u0000\\u0000\\u0002\\u0000\\u0000\\u0000�\\u0004X\\u0003�\\u0000\\u0005\\u0000\\u0011\\u0000\\u0000\\u0019\\u0001!\\u0005\\u0011\\r\\u0001\\u0017\\u0007'\\u0007'7'7\\u00177\\u0017\\u0001,\\u0001,��\\u0002��G��G��G��G\\u0003 �p�\\u0003 �ȍG��G��G��G\\u0000\\u0000\\u0000\\u0000\\u0002\\u0000\\u0000\\u0000�\\u0003p\\u0003�\\u0000\\u0005\\u0000\\u000f\\u0000\\u0000\\u0019\\u0001!\\u0005\\u0011\\u0005%7\\u0016\\u0015\\u0014\\u0007'654\\u0001,\\u0001,��\\u0001�EojCV\\u0003 �p�\\u0003 �95����6n��\\u0000\\u0000\\u0003\\u0000\\u0000\\u0000�\\u0004b\\u0003�\\u0000\\r\\u0000\\u0013\\u0000\\u001d\\u0000\\u0000%7654/\\u0001\\u0007\\u0017\\u0016\\u0015\\u0014\\u000f\\u0001\\u0001%\\u0011%!\\u0011%7\\u0016\\u0015\\u0014\\u0007'654\\u0003�\\u0006��\\u0006S\\u0007{w\\u0007��\\u0001,����\\u0002�EojCV�\\b����\\b@\\b����\\b\\u0002%����\\u0001�95����7n��\\u0000\\u0000\\u0000\\r\\u0000\\u0000\\u0000\\u0000\\u0004�\\u0004�\\u0000\\t\\u0000\\u0015\\u0000\\u0019\\u0000\\u001d\\u0000!\\u0000%\\u0000-\\u0000;\\u0000?\\u0000C\\u0000G\\u0000K\\u0000O\\u0000\\u0000\\u0013!535#\\u0011!\\u00113%\\u0011!\\u00153\\u00113\\u0011!5#5\\u0001!\\u0011)\\u0001\\u0011!\\u0011%35#!3\\u0015#\\u0001#\\u0015#\\u0011!\\u0011#\\u0001\\u0015#5#535#5!\\u00113\\u0015%\\u0011!\\u0011\\u0017#53!3\\u0015#\\u00053\\u0015#%\\u0015!5d\\u0001�dd�\\fd\\u0004L��d�\\u0001,��|\\u0001,��\\u0002�\\u0001,�|dd\\u0002�dd��d�\\u0001��\\u0002X�dd�\\u0001,������dd\\u0003 dd�\\fdd\\u0002X��\\u0002�dd\\u0001,��d\\u0001�������d\\u0001���\\u0001,��ddd��d�\\f\\u0001���ddd�d��d���\\u0001,�ddddddd\\u0000\\u0000\\t\\u0000\\u0000\\u0000\\u0000\\u0004�\\u0004�\\u0000\\u0003\\u0000\\u0007\\u0000\\u000b\\u0000\\u000f\\u0000\\u0013\\u0000\\u0017\\u0000\\u001b\\u0000\\u001f\\u0000#\\u0000\\u0000\\u0013#\\u0011;\\u0001#\\u00113\\u0001#\\u00113\\u0013#\\u00113!\\u0011#\\u0011\\u0001\\u0015!5\\u00053\\u0015#73\\u0015#%\\u0015#5ddd�dd\\u0001����dd\\u0001,�����\\u0001�dd�dd\\u0001��\\u0004��\\u0018\\u0003��\\u0018\\u0003��\\u0018\\u0003��\\u0018\\u0003���dd\\t[[[[[[\\u0000\\u0000\\u0000\\u0000\\u0002\\u0000\\u0001\\u0000\\u0000\\u0004�\\u0004�\\u0000\\u0007\\u0000\\u0013\\u0000\\u0000\\t\\u0002\\u0011463!\\u000364'&\\\"\\u0007\\u0006\\u0014\\u0017\\u00162\\u0004��\\f�E\\u000f\\n\\u0001ڴ\\u001d\\u001d\\u001eS\\u001e\\u001d\\u001d\\u001eS\\u0001��\\f\\u0002�\\u0001�\\n\\u000f��\\u001dT\\u001d\\u001e\\u001e\\u001dT\\u001d\\u001e\\u0000\\u0003\\u0000\\u0002\\u0000\\u0000\\u0005�\\u0004�\\u0000\\u0007\\u0000\\r\\u0000\\u0019\\u0000\\u0000\\t\\u0002\\u0011463!\\t\\u0001'\\t\\u00013\\u000164'&\\\"\\u0007\\u0006\\u0014\\u0017\\u00162\\u0004��\\f�E\\u000e\\u000b\\u0001�\\u0003��\\f2\\u0001��Dd�\\u001f\\u001e\\u001e\\u001dT\\u001d\\u001e\\u001e\\u001dT\\u0001��\\f\\u0002�\\u0001�\\u000b\\u000e�D�\\f2\\u0001�\\u0002���\\u001dT\\u001d\\u001e\\u001e\\u001dT\\u001d\\u001e\\u0000\\u0001\\u0000d\\u0000\\u0000\\u0004�\\u0004�\\u0000\\n\\u0000\\u0000\\u0001\\u0011\\u0007\\u0011!\\u0007!\\u0011!\\u00117\\u0004�d�\\u0012d\\u0002��|�\\u0004��\\u0018d\\u0003�d�\\u0018\\u0004\\u0001�\\u0000\\u0000\\u0000\\u0000\\u0003\\u0000\\u0000\\u0000\\u0000\\u0004�\\u0004�\\u0000\\u000b\\u0000\\u0017\\u0000'\\u0000\\u0000\\u0001\\u0003.\\u0001#!\\\"\\u0006\\u0007\\u0003\\u0017!%\\u0011#5!\\u0015#\\u00113\\u0017!7\\u0003\\u0017\\u0016\\u0006#!\\\"&?\\u0001>\\u00013!2\\u0016\\u0003�^\\u0002\\u0010\\n�>\\n\\u0010\\u0002^(\\u0002P\\u0001;�����d\\u0002Xdw&\\u0002\\u000b\\n��\\n\\u000b\\u0002&\\u0002\\u0013\\n\\u0001�\\n\\u0013\\u0003=\\u0001Z\\u000b\\u000e\\u000e\\u000b��|_�D��\\u0002������\\n\\u000e\\u000e\\n�\\n\\u000e\\u000e\\u0000\\u0000\\u0000\\u0000\\u0002\\u00005\\u0000\\u0000\\u0004�\\u0004�\\u0000\\u001e\\u0000\\\"\\u0000\\u0000!5&'.\\u0001/\\u0001\\u0001#\\u0001\\u0006\\u0007\\u000e\\u0001\\u000f\\u0001\\u0015!5\\\".\\u0001?\\u0001!\\u0017\\u0016\\u0006#\\u0015\\u0001\\u0013\\u0017\\u0013\\u0004�\\\"(\\u0012\\u001e\\u0006\\u0006�]�q\\u0018\\u001c\\f*\\u000f\\u000f\\u0001m)>$\\u0013\\\\\\u0001�R\\u0010+5���.tB\\u0001*\\u0013.\\u000e\\r\\u0003��\\u00120\\u001b\\f\\u001a\\u0007\\u0007BB\\u00166,��-WB\\u0002\\t\\u0001Ɍ��\\u0000\\u0000\\u0000\\u0003\\u0000d\\u0000\\u0000\\u0003�\\u0004�\\u0000 \\u0000(\\u00001\\u0000\\u0000\\u0013!2\\u0016\\u0015\\u0014\\u000e\\u0002\\u000f\\u0001\\u001e\\u0004\\u0015\\u0014\\u000e\\u0001#!5>\\u00015\\u00114.\\u0003'\\u0005\\u001132654&\\u000332654&+\\u0001d\\u0001�x�\\u0017!\\\"\\u000b\\f\\b\\u001bE4+v�O�\\f);\\u0002\\t\\u0016$\\u001f\\u0001,�Ll���Y�}^�\\u0004���7]7(\\b\\u0007\\u0003\\f3AvFT�MY\\u00073(\\u0003;\\u001c\\u0017\\u001d\\r\\u000f\\u00072��{MRa��aTZ�\\u0000\\u0000\\u0000\\u0001\\u0000�\\u0000\\u0000\\u0003o\\u0004�\\u0000\\u0019\\u0000\\u0000\\u0001\\u0017\\u000e\\u0003\\u000f\\u0001\\u0003\\u0006\\u0016\\u0017\\u0015!5>\\u00017\\u00136&'.\\u0001'5\\u0003m\\u0002!:\\\"\\u0019\\u0005\\u0005�\\n0G�\\fMs\\b�\\n(G\\u0006\\t\\u0005\\u0004�9\\b#'%\\f\\f��4<\\u000699\\u0007C/\\u0003Q8$\\u0013\\u0001\\u0003\\u00019\\u0000\\u0000\\u0002��\\u0000\\u0000\\u0005\\u0014\\u0004�\\u0000\\u001b\\u0000%\\u0000\\u0000\\u00013\\u0011#4.\\u0003+\\u0001\\u0011\\u0017\\u0015!57\\u0011#\\\"\\u000e\\u0003\\u0015#\\u00113\\u0005\\u00113\\u0007'3\\u0011#7\\u0017\\u0004~�2\\u0010\\u0015.!\\\"�d�pd�\\\"!/\\u0014\\u00111���K}}KK}}\\u0004���\\u001d'\\u0015\\t\\u0002��2dd2\\u0003R\\u0002\\t\\u0015'\\u001d\\u0001,��১\\u0003 ��\\u0000\\u0000\\u0000\\u0002\\u0000!��\\u0004�\\u0004�\\u0000\\u001b\\u0000%\\u0000\\u0000\\u00013\\u0011#4.\\u0003+\\u0001\\u0011\\u0017\\u0015!57\\u0011#\\\"\\u000e\\u0003\\u0015#\\u00113\\u0003!5\\u0017\\u00075!\\u0015'7\\u0003��2\\u0010\\u0014/!\\\"�d�pd�\\\"!.\\u0015\\u00102�2\\u0003 ���১\\u0004���\\u001d'\\u0015\\t\\u0002�v2dd2\\u0002�\\u0002\\t\\u0015'\\u001d\\u0001,��K}}KK}}\\u0000\\u0000\\u0000\\u0004\\u0000\\u0000\\u0000\\u0000\\u0004�\\u0004L\\u0000\\u000f\\u0000\\u001f\\u0000/\\u0000?\\u0000\\u0000\\u000154&#!\\\"\\u0006\\u001d\\u0001\\u0014\\u00163!26\\u000154&#!\\\"\\u0006\\u001d\\u0001\\u0014\\u00163!26\\u000354&#!\\\"\\u0006\\u001d\\u0001\\u0014\\u00163!26\\u000154&#!\\\"\\u0006\\u001d\\u0001\\u0014\\u00163!26\\u0002�\\u001d\\u0015��\\u0015\\u001d\\u001d\\u0015\\u0002X\\u0015\\u001d\\u0001�\\u001d\\u0015�\\u0018\\u0015\\u001d\\u001d\\u0015\\u0003�\\u0015\\u001d�\\u001d\\u0015��\\u0015\\u001d\\u001d\\u0015\\u0003 \\u0015\\u001d\\u0001,\\u001d\\u0015��\\u0015\\u001d\\u001d\\u0015\\u0004L\\u0015\\u001d\\u0003�d\\u0015\\u001d\\u001d\\u0015d\\u0014\\u001e\\u001e��d\\u0015\\u001d\\u001d\\u0015d\\u0014\\u001e\\u001e��d\\u0015\\u001d\\u001d\\u0015d\\u0014\\u001e\\u001e��d\\u0015\\u001d\\u001d\\u0015d\\u0014\\u001e\\u001e\\u0000\\u0000\\u0004\\u0000\\u0000\\u0000\\u0000\\u0004�\\u0004L\\u0000\\u000f\\u0000\\u001f\\u0000/\\u0000?\\u0000\\u0000\\u000154&#!\\\"\\u0006\\u001d\\u0001\\u0014\\u00163!26\\u001354&#!\\\"\\u0006\\u001d\\u0001\\u0014\\u00163!26\\u000354&#!\\\"\\u0006\\u001d\\u0001\\u0014\\u00163!26\\u001354&#!\\\"\\u0006\\u001d\\u0001\\u0014\\u00163!26\\u0003�\\u001d\\u0015�D\\u0015\\u001d\\u001d\\u0015\\u0002�\\u0015\\u001d�\\u001d\\u0015��\\u0015\\u001d\\u001d\\u0015\\u0004L\\u0015\\u001d�\\u001d\\u0015�D\\u0015\\u001d\\u001d\\u0015\\u0002�\\u0015\\u001d�\\u001d\\u0015��\\u0015\\u001d\\u001d\\u0015\\u0004L\\u0015\\u001d\\u0003�d\\u0015\\u001d\\u001d\\u0015d\\u0014\\u001e\\u001e��d\\u0015\\u001d\\u001d\\u0015d\\u0014\\u001e\\u001e��d\\u0015\\u001d\\u001d\\u0015d\\u0014\\u001e\\u001e��d\\u0015\\u001d\\u001d\\u0015d\\u0014\\u001e\\u001e\\u0000\\u0000\\u0000\\u0000\\u0004\\u0000\\u0000\\u0000\\u0000\\u0004�\\u0004L\\u0000\\u000f\\u0000\\u001f\\u0000/\\u0000?\\u0000\\u0000\\u00015463!2\\u0016\\u001d\\u0001\\u0014\\u0006#!\\\"&\\u00015463!2\\u0016\\u001d\\u0001\\u0014\\u0006#!\\\"&\\u00135463!2\\u0016\\u001d\\u0001\\u0014\\u0006#!\\\"&\\u00015463!2\\u0016\\u001d\\u0001\\u0014\\u0006#!\\\"&\\u0001�\\u001d\\u0015\\u0002X\\u0015\\u001d\\u001d\\u0015��\\u0015\\u001d�p\\u001d\\u0015\\u0003�\\u0015\\u001d\\u001d\\u0015�\\u0018\\u0015\\u001d�\\u001d\\u0015\\u0003 \\u0015\\u001d\\u001d\\u0015��\\u0015\\u001d��\\u001d\\u0015\\u0004L\\u0015\\u001d\\u001d\\u0015��\\u0015\\u001d\\u0003�d\\u0015\\u001d\\u001d\\u0015d\\u0014\\u001e\\u001e��d\\u0015\\u001d\\u001d\\u0015d\\u0014\\u001e\\u001e��d\\u0015\\u001d\\u001d\\u0015d\\u0014\\u001e\\u001e��d\\u0015\\u001d\\u001d\\u0015d\\u0014\\u001e\\u001e\\u0000\\u0000\\u0004\\u0000\\u0000\\u0000\\u0000\\u0004�\\u0004L\\u0000\\u000f\\u0000\\u001f\\u0000/\\u0000?\\u0000\\u0000\\u00115463!2\\u0016\\u001d\\u0001\\u0014\\u0006#!\\\"&\\u00115463!2\\u0016\\u001d\\u0001\\u0014\\u0006#!\\\"&\\u00115463!2\\u0016\\u001d\\u0001\\u0014\\u0006#!\\\"&\\u00115463!2\\u0016\\u001d\\u0001\\u0014\\u0006#!\\\"&\\u001d\\u0015\\u0004L\\u0015\\u001d\\u001d\\u0015��\\u0015\\u001d\\u001d\\u0015\\u0004L\\u0015\\u001d\\u001d\\u0015��\\u0015\\u001d\\u001d\\u0015\\u0004L\\u0015\\u001d\\u001d\\u0015��\\u0015\\u001d\\u001d\\u0015\\u0004L\\u0015\\u001d\\u001d\\u0015��\\u0015\\u001d\\u0003�d\\u0015\\u001d\\u001d\\u0015d\\u0014\\u001e\\u001e��d\\u0015\\u001d\\u001d\\u0015d\\u0014\\u001e\\u001e��d\\u0015\\u001d\\u001d\\u0015d\\u0014\\u001e\\u001e��d\\u0015\\u001d\\u001d\\u0015d\\u0014\\u001e\\u001e\\u0000\\b\\u0000\\u0000\\u0000\\u0000\\u0004�\\u0004L\\u0000\\u000f\\u0000\\u001f\\u0000/\\u0000?\\u0000O\\u0000_\\u0000o\\u0000\\u0000\\u0000\\u0011546;\\u00012\\u0016\\u001d\\u0001\\u0014\\u0006+\\u0001\\\"&%5463!2\\u0016\\u001d\\u0001\\u0014\\u0006#!\\\"&\\u0001546;\\u00012\\u0016\\u001d\\u0001\\u0014\\u0006+\\u0001\\\"&%5463!2\\u0016\\u001d\\u0001\\u0014\\u0006#!\\\"&\\u0001546;\\u00012\\u0016\\u001d\\u0001\\u0014\\u0006+\\u0001\\\"&%5463!2\\u0016\\u001d\\u0001\\u0014\\u0006#!\\\"&\\u0001546;\\u00012\\u0016\\u001d\\u0001\\u0014\\u0006+\\u0001\\\"&%5463!2\\u0016\\u001d\\u0001\\u0014\\u0006#!\\\"&\\u001d\\u0015d\\u0015\\u001d\\u001d\\u0015d\\u0015\\u001d\\u0001,\\u001d\\u0015\\u0003 \\u0015\\u001d\\u001d\\u0015��\\u0015\\u001d��\\u001d\\u0015d\\u0015\\u001d\\u001d\\u0015d\\u0015\\u001d\\u0001,\\u001d\\u0015\\u0003 \\u0015\\u001d\\u001d\\u0015��\\u0015\\u001d��\\u001d\\u0015d\\u0015\\u001d\\u001d\\u0015d\\u0015\\u001d\\u0001,\\u001d\\u0015\\u0003 \\u0015\\u001d\\u001d\\u0015��\\u0015\\u001d��\\u001d\\u0015d\\u0015\\u001d\\u001d\\u0015d\\u0015\\u001d\\u0001,\\u001d\\u0015\\u0003 \\u0015\\u001d\\u001d\\u0015��\\u0015\\u001d\\u0003�d\\u0015\\u001d\\u001d\\u0015d\\u0014\\u001e\\u001e\\u0014d\\u0015\\u001d\\u001d\\u0015d\\u0014\\u001e\\u001e��d\\u0015\\u001d\\u001d\\u0015d\\u0014\\u001e\\u001e\\u0014d\\u0015\\u001d\\u001d\\u0015d\\u0014\\u001e\\u001e��d\\u0015\\u001d\\u001d\\u0015d\\u0014\\u001e\\u001e\\u0014d\\u0015\\u001d\\u001d\\u0015d\\u0014\\u001e\\u001e��d\\u0015\\u001d\\u001d\\u0015d\\u0014\\u001e\\u001e\\u0014d\\u0015\\u001d\\u001d\\u0015d\\u0014\\u001e\\u001e\\u0000\\u0000\\u0000\\u0006��\\u0000\\u0000\\u0004�\\u0004L\\u0000\\u0003\\u0000\\u0013\\u0000#\\u0000*\\u0000:\\u0000J\\u0000\\u0000\\u0001#\\u00113\\u000154&+\\u0001\\\"\\u0006\\u001d\\u0001\\u0014\\u0016;\\u000126\\u000154&#!\\\"\\u0006\\u001d\\u0001\\u0014\\u00163!26\\u00055#535\\u0017\\u000554&#!\\\"\\u0006\\u001d\\u0001\\u0014\\u00163!26\\u000154&#!\\\"\\u0006\\u001d\\u0001\\u0014\\u00163!26\\u0001�dd\\u0001,\\u001e\\u0014d\\u0015\\u001d\\u001d\\u0015d\\u0014\\u001e\\u0001�\\u001e\\u0014�\\f\\u0015\\u001d\\u001d\\u0015\\u0001�\\u0014\\u001e�\\u0018�ɦ\\u0002z\\u001e\\u0014��\\u0015\\u001d\\u001d\\u0015\\u0001,\\u0014\\u001e\\u0001,\\u001e\\u0014��\\u0015\\u001d\\u001d\\u0015\\u0002X\\u0014\\u001e\\u0004L��\\u0003�d\\u0015\\u001d\\u001d\\u0015d\\u0014\\u001e\\u001e��d\\u0015\\u001d\\u001d\\u0015d\\u0014\\u001e\\u001e�KdK}�d\\u0015\\u001d\\u001d\\u0015d\\u0014\\u001e\\u001e��d\\u0015\\u001d\\u001d\\u0015d\\u0014\\u001e\\u001e\\u0000\\u0000\\u0000\\u0006\\u0000\\u0001\\u0000\\u0000\\u0005\\u0015\\u0004L\\u0000\\u000f\\u0000\\u0013\\u0000#\\u0000*\\u0000:\\u0000J\\u0000\\u0000\\u001354&+\\u0001\\\"\\u0006\\u001d\\u0001\\u0014\\u0016;\\u000126%3\\u0011#\\u000354&#!\\\"\\u0006\\u001d\\u0001\\u0014\\u00163!26\\u0005535#5\\u0007\\u000554&#!\\\"\\u0006\\u001d\\u0001\\u0014\\u00163!26\\u000154&#!\\\"\\u0006\\u001d\\u0001\\u0014\\u00163!26�\\u001e\\u0014d\\u0015\\u001d\\u001d\\u0015d\\u0014\\u001e\\u0002Xdd�\\u001e\\u0014�\\f\\u0015\\u001d\\u001d\\u0015\\u0001�\\u0014\\u001e\\u0001��ȧ��\\u001e\\u0014��\\u0015\\u001d\\u001d\\u0015\\u0001,\\u0014\\u001e\\u0001,\\u001e\\u0014��\\u0015\\u001d\\u001d\\u0015\\u0002X\\u0014\\u001e\\u0003�d\\u0015\\u001d\\u001d\\u0015d\\u0014\\u001e\\u001e���\\u0002�d\\u0015\\u001d\\u001d\\u0015d\\u0014\\u001e\\u001e�KdK}�d\\u0015\\u001d\\u001d\\u0015d\\u0014\\u001e\\u001e��d\\u0015\\u001d\\u001d\\u0015d\\u0014\\u001e\\u001e\\u0000\\u0000\\u0002\\u0000\\u0000\\u0000�\\u0004�\\u0003�\\u0000\\u000f\\u0000\\u0012\\u0000\\u0000\\u0001\\u0011\\u0014\\u0006#!\\\"&5\\u0011463!2\\u0016\\t\\u0002\\u0003�,\\u001f�\\u0012\\u001f,,\\u001f\\u0002�\\u001f,\\u0001,��\\u0001,\\u0003��v\\u001f,,\\u001f\\u0002�\\u001f,,�p\\u0001,\\u0001,\\u0000\\u0000\\u0000\\u0000\\u0003\\u0000\\u0000\\u0000\\u0000\\u0004�\\u0004L\\u0000\\u000f\\u0000\\u0017\\u0000\\u001f\\u0000\\u0000\\u0001\\u0011\\u0014\\u0006#!\\\"&5\\u0011463!2\\u0016\\u0007!\\u00117\\u0005'\\u0001\\u0013\\u0000\\u0014\\u0006\\\"&462\\u0004�\\u0019\\u0013��\\u0012\\u001a\\u001a\\u0012\\u0004X\\u0013\\u0019d�\\u0018�\\u0001*J\\u0001%���NpNNp\\u0004 �\\f\\u0012\\u001a\\u001a\\u0012\\u0003�\\u0012\\u001a\\u001aJ�\\u001f���\\u0001>��\\u00012pNNpN\\u0000\\u0000\\u0002\\u0000���\\u0004\\u001c\\u0004�\\u0000\\u0014\\u0000\\u001e\\u0000\\u0000\\u00012\\u001e\\u0001\\u0014\\u0007\\u000e\\u0001\\u000f\\u0001.\\u0004'&54>\\u0001\\u0013264&\\\"\\u0006\\u0015\\u0014\\u0016\\u0002X{�yII�99\\n\\\"c]s+?y�yk��֖�\\u0004�~���r�BB\\t\\\"ko�K�{|ׁ�E�֖�jk�\\u0000\\u0002\\u0000\\u0001\\u0000\\u0001\\u0004�\\u0004�\\u0000\\u000f\\u0000\\u0015\\u0000\\u0000\\u00002\\u001e\\u0002\\u0014\\u000e\\u0002\\\".\\u00024>\\u0001\\u0001\\u0011\\\"\\u0006\\u0010\\u0016\\u0001��ޠ__���ޠ__�\\u0001X���\\u0004�_���ޠ__���ޠ�]\\u0003V����\\u0000\\u0000\\u0000\\u0002\\u0000u\\u0000\\u0004\\u0003�\\u0005\\u000f\\u0000\\u0016\\u0000%\\u0000\\u0000\\u0001\\u001e\\u0006\\u0015\\u0014\\u000e\\u0002\\u0007.\\u000254>\\u0003\\u0003.\\u0002'&6?\\u0001\\u000e\\u0001\\u0017\\u001e\\u0001\\u0017\\u0002*\\u0015IOWM?%N~�OrÀDmssE\\u0007\\u0016.\\n\\u000f\\u0002\\t\\t\\\\7\\u000f\\u000e[[\\u0005\\u000fG�vwsu�EY�d;\\u0004\\u0006^�w^�����y\\u0006\\u0016J(I�43n�QRl\\u001a\\u0000\\u0000\\u0003\\u0000\\u0000\\u0000\\u0000\\u0004�\\u0004h\\u0000\\u0004\\u0000!\\u0000&\\u0000\\u0000\\u00017/\\u0001\\u0007\\u0013\\u0015\\u0014\\u0006#!\\\"&5\\u0011463\\u0004\\u0017\\u0007!\\\"\\u0006\\u0015\\u0011\\u0014\\u00163!26=\\u0001\\u00057\\u0001'\\u0001\\u0004Tq\\u0015\\\\qi���ԥ���\\u0001n\\u001f���);;)\\u0001�);�0�\\u0001�r�k\\u0003�qU\\u001cq�z�����\\u0001,��\\u0006\\b�;)�\\f);;)}T2\\u0001�q�k\\u0000\\u0000\\u0000\\u0002\\u0000\\u0000\\u0000\\u0000\\u0004�\\u0004L\\u0000\\u001c\\u0000.\\u0000\\u0000\\u0001\\u0015\\u0014\\u0006#!\\\"&5\\u0011463!\\u0017\\u0006\\u0007#\\\"\\u0006\\u0015\\u0011\\u0014\\u00163!265'\\t\\u0001\\u0015\\\"\\u000e\\u0005\\u0007>\\u0003\\u001f\\u0001\\u0004L���ԥ���\\u0001\\u0005\\u0002�U�);;)\\u0001�);W\\u0001h��\\u0007\\u0018HCVC9\\u000b\\u001egg_\\u001e\\u001d\\u0001�5����\\u0001,��P X;)�\\f);;)�\\u0001D\\u0001>�\\u0002\\u000e\\u00173CmC&4\\u0013\\t\\u0001\\u0001\\u0000\\u0000\\u0000\\u0000\\u0002\\u0000\\u0000\\u0000\\u0000\\u0004�\\u0004L\\u0000\\u001d\\u0000#\\u0000\\u0000\\u0001\\u0015\\u0014\\u0006#!\\\"&5\\u0011463!2\\u0017\\u0007!\\\"\\u0006\\u0015\\u0011\\u0014\\u00163!26=\\u0001\\u0005\\u0001'\\u0001'\\u0007\\u0004L���ԥ���\\u0001,<C���);;)\\u0001�);��\\u00026��R��\\u00029�����\\u0001,��\\u0017�;)�\\f);;)E\\u0015\\u00027��Q��\\u0000\\u0001\\u0000\\u0000\\u0000\\u0001\\u0004�\\u0004�\\u0000\\u0017\\u0000\\u0000\\u00015#\\u00153\\t\\u000135#\\u0015\\t\\u0001\\u001535#\\t\\u0001#\\u001535\\u0001\\u0003�����������\\u0001,��\\u0001,\\u0001'��\\u0001,\\u0001/����\\u0001,��\\u0001,\\u0001(��\\u0001,������\\u0000\\u0000\\u0000\\u0001\\u0000�\\u0000\\u0000\\u0003�\\u0004L\\u0000\\u0013\\u0000\\u0000!\\u0001\\u0011\\u0014\\u0006+\\u0001\\\"&5\\u001146;\\u00012\\u0016\\u0015\\u0011\\u0001\\u0003��\\f\\u001d\\u0015d\\u0015\\u001d\\u001d\\u0015d\\u0015\\u001d\\u0001�\\u0001��J\\u0015\\u001d\\u001d\\u0015\\u0003�\\u0015\\u001d\\u001d\\u0015�K\\u0001�\\u0000\\u0001\\u0000\\u0000\\u0000\\u0000\\u0004�\\u0004L\\u0000\\u0017\\u0000\\u0000!\\u0001\\u0011\\u0001\\u0011\\u0014\\u0006+\\u0001\\\"&5\\u001146;\\u00012\\u0016\\u0015\\u0011\\u0001\\u0011\\u0001\\u0004��\\f�\\f\\u001d\\u0015d\\u0015\\u001d\\u001d\\u0015d\\u0015\\u001d\\u0001�\\u0001�\\u0001��\\u0018\\u0001��J\\u0015\\u001d\\u001d\\u0015\\u0003�\\u0015\\u001d\\u001d\\u0015�K\\u0001��\\u0019\\u0001�\\u0000\\u0001\\u0000�\\u0000\\u0000\\u0004�\\u0004L\\u0000\\u0006\\u0000\\u0000!\\u0001\\u0011\\t\\u0001\\u0011\\u0001\\u0004��\\f��\\u00024\\u0001�\\u0001��\\u0018\\u0002&\\u0002&�\\u0019\\u0001�\\u0000\\u0000\\u0001\\u0000�\\u0000\\u0000\\u0004L\\u0004L\\u0000\\u0002\\u0000\\u0000\\t\\u0001\\u0011\\u0004L�|\\u0002&\\u0002&��\\u0000\\u0000\\u0002\\u0000�\\u0000d\\u0003�\\u0003�\\u0000\\u000f\\u0000\\u001f\\u0000\\u0000%\\u00114&+\\u0001\\\"\\u0006\\u0015\\u0011\\u0014\\u0016;\\u000126%\\u00114&+\\u0001\\\"\\u0006\\u0015\\u0011\\u0014\\u0016;\\u000126\\u0001�\\u001d\\u0015�\\u0015\\u001d\\u001d\\u0015�\\u0015\\u001d\\u0001�\\u001d\\u0015�\\u0015\\u001d\\u001d\\u0015�\\u0015\\u001d�\\u0003 \\u0015\\u001d\\u001d\\u0015��\\u0015\\u001d\\u001d\\u0015\\u0003 \\u0015\\u001d\\u001d\\u0015��\\u0015\\u001d\\u001d\\u0000\\u0001\\u0000�\\u0000d\\u0004L\\u0003�\\u0000\\u000f\\u0000\\u0000%\\u00114&#!\\\"\\u0006\\u0015\\u0011\\u0014\\u00163!26\\u0004L\\u001d\\u0015��\\u0015\\u001d\\u001d\\u0015\\u0003 \\u0015\\u001d�\\u0003 \\u0015\\u001d\\u001d\\u0015��\\u0014\\u001e\\u001e\\u0000\\u0001\\u0000\\u0000\\u0000\\u0000\\u0004(\\u0004L\\u0000\\u0006\\u0000\\u0000!\\u0011\\u0001\\u0011\\u0001\\u0011\\u0001\\u0001��\\f\\u0001�\\u00024\\u0001��\\u0018\\u0004L�\\u0019\\u0001���\\u0000\\u0000\\u0000\\u0000\\u0001\\u0000\\u0000\\u0000\\u0000\\u0004�\\u0004L\\u0000\\u0017\\u0000\\u0000\\u000132\\u0016\\u0015\\u0011\\u0014\\u0006+\\u0001\\\"&5\\u0011\\u0001\\u0011\\u0001\\u0011\\u0001\\u0011\\u0001\\u001146\\u0004\\u001ad\\u0015\\u001d\\u001d\\u0015d\\u0015\\u001d�\\f�\\f\\u0001�\\u0001�\\u001d\\u0004L\\u001d\\u0015�\\u0018\\u0015\\u001d\\u001d\\u0015\\u0001��\\u0018\\u0001��\\u0018\\u0004L�\\u0019\\u0001��\\u0019\\u0001�\\u0015\\u001d\\u0000\\u0000\\u0001\\u0001,\\u0000\\u0000\\u0003�\\u0004L\\u0000\\u0013\\u0000\\u0000\\u000132\\u0016\\u0015\\u0011\\u0014\\u0006+\\u0001\\\"&5\\u0011\\u0001\\u0011\\u0001\\u001146\\u0003Rd\\u0015\\u001d\\u001d\\u0015d\\u0015\\u001d�\\f\\u0001�\\u001d\\u0004L\\u001d\\u0015�\\u0018\\u0015\\u001d\\u001d\\u0015\\u0001��\\u0018\\u0004L�\\u0019\\u0001�\\u0015\\u001d\\u0000\\u0000\\u0002\\u0000d\\u0000�\\u0004�\\u0004(\\u0000\\u0002\\u0000\\u0012\\u0000\\u0000\\t\\u0001!\\u001d\\u0001\\u0014\\u0006#!\\\"&=\\u0001463!2\\u0016\\u0002���\\u0004L\\u001d\\u0015�\\u0018\\u0015\\u001d\\u001d\\u0015\\u0003�\\u0015\\u001d\\u0004(�̖d\\u0015\\u001d\\u001d\\u0015d\\u0015\\u001d\\u001d\\u0000\\u0000\\u0001\\u0000�\\u0000\\u0007\\u0003�\\u0004�\\u0000\\u0005\\u0000\\u0000%7\\t\\u0001'\\u0001\\u0003\\t���\\u0001a���\\u0007�\\u0001a\\u0001a���\\u0000\\u0000\\u0001\\u0001\\u0010��\\u0004R\\u0004t\\u0000\\b\\u0000\\u0000\\u0005'\\t\\u00017\\u0001\\u0017\\u0007\\u0015\\u0002\\u0001�\\u0001a���\\u0002<\\u0015\\u0001.�\\u0001a\\u0001a���\\u0016\\u0001\\u0001\\u0000\\u0000\\u0002\\u0000\\u0003\\u0000\\u0003\\u0004�\\u0004�\\u0000\\u000b\\u0000\\u0017\\u0000\\u0000\\u0000 \\u0004\\u0012\\u0010\\u0002\\u0004 $\\u0002\\u0010\\u0012\\u0005\\u0015#\\u00153\\u00153535#5\\u0001�\\u0001D\\u0001\\u0013��������\\u0001Q�����\\u0004��������\\u0001\\u0013\\u0001D\\u0001\\u0013�������\\u0000\\u0000\\u0002\\u0000\\u0003\\u0000\\u0003\\u0004�\\u0004�\\u0000\\u000b\\u0000\\u000f\\u0000\\u0000\\u0000 \\u0004\\u0012\\u0010\\u0002\\u0004 $\\u0002\\u0010\\u0012\\u0013\\u0015!5\\u0001�\\u0001D\\u0001\\u0013���������\\u0002X\\u0004��������\\u0001\\u0013\\u0001D\\u0001\\u0013����\\u0000\\u0002\\u0000\\u0003\\u0000\\u0003\\u0004�\\u0004�\\u0000\\u000b\\u0000\\u0017\\u0000\\u0000\\u0000 \\u0004\\u0012\\u0010\\u0002\\u0004 $\\u0002\\u0010\\u0012\\u0013\\u0017\\u0007\\u00177\\u00177'7'\\u0007'\\u0001�\\u0001D\\u0001\\u0013��������T��Ս�Վ�Ս�\\u0004��������\\u0001\\u0013\\u0001D\\u0001\\u0013�؍�Վ�Ս�ԍ�\\u0000\\u0000\\u0000\\u0002\\u0000\\u0003\\u0000\\u0003\\u0004�\\u0004�\\u0000\\u000b\\u0000\\u0011\\u0000\\u0000\\u0000 \\u0004\\u0012\\u0010\\u0002\\u0004 $\\u0002\\u0010\\u0012\\u0001'\\u0007\\t\\u0001'\\u0001�\\u0001D\\u0001\\u0013��������\\u0001f�\\u0001\\u0014\\u0001��\\u0004��������\\u0001\\u0013\\u0001D\\u0001\\u0013�bf���\\u0001��\\u0000\\u0000\\u0000\\u0000\\u0003\\u0000\\u0003\\u0000\\u0003\\u0004�\\u0004�\\u0000\\u000b\\u00006\\u0000:\\u0000\\u0000\\u0000 \\u0004\\u0012\\u0010\\u0002\\u0004 $\\u0002\\u0010\\u0012\\u00013>\\u000454.\\u0003#\\\"\\u0006\\u001532\\u0016264>\\u0005:\\u000132\\u0016\\u0015\\u0014\\u0006\\u0007\\u000e\\u0004\\u0017\\u001535\\u0001�\\u0001D\\u0001\\u0013��������\\u0001Q�\\u0005\\u0012-\\\"\\u001c#1D1\\u001bi��\\u0004\\u000f\\u0007\\u0006\\u0002\\u0005\\u0002\\t\\u0004\\u000e\\u0004\\u0013\\u0003\\u0013\\u0016\\b\\u0017\\u0005\\u000f'\\u001d\\u0018\\u0001�\\u0004��������\\u0001\\u0013\\u0001D\\u0001\\u0013��\\u0003\\n)2X23L(\\u0018\\u0006p\\u0002\\u0006\\f\\n\\u0007\\u0005\\u0003\\u0002\\u0001\\u0014\\u0010\\u0016\\f\\u0010\\u0001\\u0004\\u0017\\u001f=�dd\\u0000\\u0000\\u0003\\u0000\\u0003\\u0000\\u0003\\u0004�\\u0004�\\u0000\\u000b\\u0000\\u000f\\u0000\\u0019\\u0000\\u0000\\u0000 \\u0004\\u0012\\u0010\\u0002\\u0004 $\\u0002\\u0010\\u0012\\u0005\\u001535\\u0005\\u00153\\u0015#\\u0015!5#\\u0011\\u0001�\\u0001D\\u0001\\u0013��������\\u0001Q���dd\\u0001�d\\u0004��������\\u0001\\u0013\\u0001D\\u0001\\u0013�dd�d�dd\\u0001,\\u0000\\u0000\\u0000\\u0000\\u0002\\u0000\\u0000\\u0000\\u0000\\u0004�\\u0004�\\u0000\\u001a\\u00001\\u0000\\u0000\\u0001\\u0015#\\u000e\\u0001\\u0007\\u0015#5.\\u0001'#53>\\u0003753\\u0015\\u001e\\u0002\\u0017\\u0005\\u001567#53.\\u0001'\\u0015#5\\u000e\\u0001\\u00073\\u0015#\\u001e\\u0001\\u00175\\u0004��\\u0019�YȌ�\\u001e��\\u000f*EkI�6vk\\u0012�ו4��\\u0019fI�Kn\\u0018��\\u0018oK\\u0002��f�!��\\u001b�}�<YS7\\r��\\u0014P�E��0��Jk\\u0017��\\u0018kH�Im\\u0018�\\u0000\\u0003\\u0000\\u0004\\u0000\\u0004\\u0004�\\u0004�\\u0000\\u000b\\u0000\\u0013\\u0000\\u001f\\u0000\\u0000\\u0000 \\u0004\\u0012\\u0010\\u0002\\u0004 $\\u0002\\u0010\\u0012\\u0004 \\u0006\\u0010\\u0016 6\\u0010\\u000f\\u0001\\u0017\\u0007'\\u0007'7'7\\u00177\\u0001�\\u0001D\\u0001\\u0012�������\\u0002_����\\u0001V󪇇m��m��m��\\u0004�������\\u0001\\u0012\\u0001D\\u0001\\u0012\\u0016�����\\u0001V$��m��m��m��\\u0000\\u0003\\u0000\\u0004\\u0000\\u0004\\u0004�\\u0004�\\u0000\\u000b\\u0000\\u0013\\u0000\\u0019\\u0000\\u0000\\u0000 \\u0004\\u0012\\u0010\\u0002\\u0004 $\\u0002\\u0010\\u0012\\u0004 \\u0006\\u0010\\u0016 6\\u0010\\u0007\\u0001'7\\u00177\\u0001�\\u0001D\\u0001\\u0012�������\\u0002_����\\u0001V�v����W�\\u0004�������\\u0001\\u0012\\u0001D\\u0001\\u0012\\u0016�����\\u0001Vu����W�\\u0000\\u0003\\u0000\\u0004\\u0000\\u0004\\u0004�\\u0004�\\u0000\\u000b\\u0000\\u0013\\u0000\\u001b\\u0000\\u0000\\u0000 \\u0004\\u0012\\u0010\\u0002\\u0004 $\\u0002\\u0010\\u0012\\u0013\\u0001&#\\\"\\u0006\\u0015\\u0014\\t\\u0001\\u001632654\\u0001�\\u0001D\\u0001\\u0012�������T\\u00028dt��\\u0003\\u0001��ap��\\u0004�������\\u0001\\u0012\\u0001D\\u0001\\u0012�u\\u00027>��s\\u0001D��;��p\\u0000\\u0000\\u0000\\u0001\\u0000\\u0000\\u0000c\\u0004�\\u0003�\\u0000\\u0006\\u0000\\u0000\\u0001!\\u0011\\t\\u0001\\u0011!\\u0004�����\\u0002X\\u0002X\\u0001���\\u0001�\\u0001���\\u0000\\u0000\\u0000\\u0000\\u0001\\u0000\\u0000\\u0000c\\u0004�\\u0003�\\u0000\\u0006\\u0000\\u0000\\u0001!\\u0011!\\u0011\\t\\u0001\\u0002X��\\u0002X\\u0002X��\\u0001�\\u0001,\\u0001,�;�@\\u0000\\u0000\\u0000\\u0000\\u0001\\u0000�\\u0000\\u0000\\u0004J\\u0004�\\u0000\\u0006\\u0000\\u0000\\u0001!\\u0011!\\u0011!\\u0001\\u0004J������\\u0001�\\u0002X��\\u0002X\\u0002X\\u0000\\u0000\\u0001\\u0000h\\u0000\\u0000\\u0003�\\u0004�\\u0000\\u0006\\u0000\\u0000\\t\\u0002!\\u0011!\\u0011\\u0003��?�C\\u0001(\\u0001,\\u0002X��\\u0002X\\u0002X��\\u0000\\u0001\\u0000\\u0000\\u0000�\\u0004�\\u0004L\\u0000\\r\\u0000\\u0000%\\u0011\\u000e\\u0003\\u0007>\\u00037\\u0011\\u0001\\u0002X_���#\\u0006F���\\u0002X�\\u0001-\\u0002$DuM�խg\\b\\u0001\\u000f�;\\u0000\\u0000\\u0002\\u0000\\u0000\\u0000\\u0000\\u0004�\\u0004�\\u0000\\u0006\\u0000\\r\\u0000\\u0000\\u0001!\\u0017\\u0001\\u0017\\u0001\\u0017\\t\\u0001\\u0017!\\u0011\\u0017\\u0001\\u0004��p��ڎ\\u0001&����ځ�p�\\u0001&\\u0004���ڎ\\u0001&����ځ\\u0001��\\u0001&\\u0000\\u0000\\u0000\\u0002\\u0000\\\"\\u0000#\\u0004�\\u0004�\\u0000\\u0006\\u0000\\r\\u0000\\u0000\\u0001\\u0017!\\u0011\\u0017\\u0001\\u0017\\u0001!\\u0011'\\u0001'\\u0001\\u0003g��p�\\u0001'��:\\u0001���َ\\u0001'\\u0002ڂ\\u0001��\\u0001'��W�p��ٍ\\u0001'\\u0000\\u0003\\u0000\\u0017\\u0000\\u0017\\u0004�\\u0004�\\u0000\\u000f\\u0000\\u001f\\u0000#\\u0000\\u0000\\u00002\\u001e\\u0002\\u0014\\u000e\\u0002\\\".\\u00024>\\u0001\\u0001\\u00136&+\\u0001\\\"\\u0006\\u0017\\u0013\\u001e\\u0001;\\u000126\\u0017#\\u00153\\u0001��՛[[���՛[[�\\u0001�:\\u0004\\u0018\\u0015�\\u0014\\u0018\\u0004:\\u0004#\\u00146\\u0014#\\u0012��\\u0004�[���՛[[���՛��\\u0001.\\u0014\\u001d\\u001d\\u0014��\\u0014\\u001d\\u001d�d\\u0000\\u0005\\u0000\\u0000\\u0000\\u0000\\u0004�\\u0004�\\u0000&\\u0000-\\u00003\\u00007\\u0000;\\u0000\\u0000\\u0001#<\\u0001&/\\u0001.\\u0001#\\\"\\u000f\\u0001\\u0006\\u0007&/\\u0001&#\\\"\\u0006\\u000f\\u0001\\u000e\\u0001\\u0014\\u0015#\\u00153\\u0015!\\u00113\\u0011!53%7\\u001e\\u0003#)\\u0001\\\"6?\\u0001\\u0003!\\u0011)\\u0002\\u0011!\\u0004�o\\u0002\\u0002\\\"\\u000b=' \\u001d�\\u0016\\u0012\\u0013\\u0015�!\\u001d'=\\n#\\u0002\\u0002od\\u0001��\\u0001�d�+�\\u0005\\u000e \\u0012\\u0002����\\u0003\\\"\\u0012\\u0012�\\u0001��p\\u0002X\\u0001��p\\u0003�\\u0001\\n\\u0014\\b�'0\\u0011�\\r\\u0016\\u0018\\f�\\u0012.&�\\b\\u0014\\n\\u0001d�\\u0001,���d�\\f)W9`0/��\\u0001��p\\u0000\\u0000\\u0000\\u0000\\u0002\\u0000\\u0000��\\u0004�\\u0004�\\u0000\\u001b\\u00002\\u0000\\u000057.\\u0002>\\u00017>\\u00057\\u0014\\u0002\\u000e\\u0004.\\u0002#\\u000f\\u0001\\u0001>\\u00037>\\u0001'&\\\"\\u0006\\u0007\\u000e\\u0001\\u000f\\u0001\\u0004\\u0007\\u0006\\u001676�\\t\\b\\u0003\\u00158./ie���h,Jhq�x{\\\\S\\u000fc�\\u0002�Fak[)\\u0016\\u0004\\b\\u0007\\u0014!\\u0011#�==��Y0'C7y�5<�b�;<U3-\\u001e9\\u001e���ЛU3\\t\\u0006\\u0013\\u000f7�\\u0002y&?_�T2\\u0014\\t\\u0005\\u001d\\u00193s  ��o\\rSB\\u0000\\u0000\\u0000\\u0003��\\u0000}\\u0004�\\u00043\\u0000!\\u0000?\\u0000G\\u0000\\u0000\\u0001\\u0007\\u000e\\u0006\\\".\\u0005/\\u00017>\\u00062\\u001e\\u0005\\u0017\\u00002>\\u00047.\\u0004'\\u0016\\u0015\\u0014\\u0006\\\"&547\\u0006\\u0007\\u001e\\u0004\\u0013\\u0007\\u0016\\u00177.\\u0001'\\u0004�\\u001a\\u0006\\u001cFOsv���vsOF\\u001c\\u0006\\u001a\\u001a\\u0006\\u001cFOsv���vsOF\\u001c\\u0006�E�wRY,H\\u000b\\u00017\\u001d:9\\u001e1���.f|\\u0007C-[TFk1ii%L\\u0013\\u0002X(\\n(WT`G//G`TW(\\n((\\n(WT`G//G`TW(\\n�p(3\\\\;h\\u000e\\u0001I%E:\\u0019JY|��|UIW�\\n`=^8\\u0001�j|Ci\\u0018`$\\u0000\\u0004��\\u0000\\u0000\\u0004�\\u0004�\\u0000\\u0016\\u0000.\\u00008\\u0000A\\u0000\\u0000\\t\\u0001#7.\\u0004/\\u00017>\\u000632\\u00177\\u0001\\u0007\\u000e\\u0004\\u00077>\\u00067&'7\\u001e\\u0002\\u0017\\u00017.\\u0001547\\u0006\\u0007\\u0012\\u0013\\u0007\\u0016\\u0017?\\u0001.\\u0001'\\u0003��Ɣ%R�ri'\\n\\u001a\\u001a\\u0006\\u001cFOsv�H=<%\\u0001�\\u001a\\u0007%Ze�I&\\u0016-/\\\"0\\u0013/\\u0001a+'C�.\\r�.%k�.f|Қk1i/\\u0017\\u001e:\\u000f\\u0004��P�\\u0015egy8\\u000f((\\n(WT`G/\\u0011���(\\f4kbf\\u001c�\\u000f&2&?\\u0018@\\u00020�6�@\\u0014���\\u0012�nUIW���\\u0001�j|C/W\\u001cR\\u001b\\u0000\\u0000\\u0000\\u0003��\\u0000\\u0000\\u0005\\u0012\\u0004�\\u0000\\u000b\\u0000\\u0012\\u0000\\u0017\\u0000\\u0000#!26'\\u0001.\\u0001\\u0007\\u0001\\u0006\\u0016%5#\\u0015!\\t\\u0002#\\u0015\\u001b\\u0001/\\u0005\\u000e%\\u001b\\u0015�~\\u00148\\u0014�~\\u0015\\u001b\\u0003\\u0010���\\u0001�\\u0001����ddG \\u0004 !\\u0006 �� D�dd\\u0002��-\\u0001�d��\\u0001,\\u0000\\u0000\\u0001\\u0000d\\u0000\\u0015\\u0004�\\u0004�\\u0000)\\u0000\\u0000\\t\\u0001\\u001e\\u0001\\u001d\\u0001\\u0014\\u0006'%\\u0011\\u0016\\u001d\\u0001\\u0014\\u0006/\\u0001#\\u0007\\u0006&=\\u000147\\u0011\\u0005\\u0006&=\\u0001467\\u0001\\u0011462\\u0016\\u0015\\u0003 \\u0001k\\u000f\\u0016\\u0018\\u0011��d\\u001a\\u0013^�^\\u0013\\u001ad��\\u0011\\u0018\\u0016\\u000f\\u0001kX|X\\u0002���\\u000e1\\u0014)\\u0014\\r\\f���[\\u0016@\\u0015\\u0010\\tNN\\t\\u0010\\u0015@\\u0016[\\u0001\\u0007�\\f\\r\\u0014)\\u00141\\u000e\\u0001E\\u0001S>XX>\\u0000\\u0003\\u0000\\u0000\\u0000\\u0003\\u0005x\\u0004�\\u0000\\n\\u0000\\u0010\\u0000\\u0019\\u0000\\u0000\\t\\u0001!5!\\u000135\\t\\u00015\\u00057'!\\u0015!\\u0005\\t\\u00015#'7\\u00173\\u0003�����\\u0001\\u0003\\u0002X�\\u0001,���1����\\u0001\\u0003\\u0003I\\u0001,�����z�\\u0003 ���\\u0002X������z��������ŵ�{\\u0000\\u0001\\u0000\\u0000\\u0000\\u0000\\u0004�\\u0004L\\u0000\\u0012\\u0000\\u0000\\u0013!2\\u0016\\u0015\\u0011\\u0014\\u0006#!\\u0001\\u0011#\\\"&5\\u001146d\\u0003�);;)����d);;\\u0004L;)��);��\\u0001,;)\\u0002X);\\u0000\\u0000\\u0000\\u0003\\u0000d\\u0000\\u0000\\u0004L\\u0004�\\u0000\\u0003\\u0000\\u0007\\u0000-\\u0000\\u0000\\u0001!\\u0011!\\u0001!\\u0011!\\u0011\\u0015\\u0014\\u000e\\u0005\\\".\\u0005=\\u0001!\\u0015\\u0014\\u0017\\u0016\\u0017\\u001632>\\u0006'4=\\u0001\\u0001���\\u0001,\\u0002���\\u0001,\\u0006\\u0018'Me���eM'\\u0018\\u0006\\u0001,\\u0006\\u0011U'5%;)\\u001f\\u0011\\u000b\\u0003\\u0002\\u0001\\u0003�\\u0001,��\\u0001,�p�*R~jqP33Pqj~R*��q \\\\\\u0019\\u000b\\u000b\\u0014\\u001c#(,.\\u0018\\u0011\\b�\\u0000\\u0000\\u0001��\\u0000�\\u0004h\\u0003�\\u0000\\u0005\\u0000\\u0000%7\\t\\u0001\\u0017\\u0001\\u0003�������\\u0001`��\\u0002C���\\u0001a\\u0000\\u0000\\u0001\\u0000F\\u0000�\\u0004�\\u0004\\u0000\\u0000\\u0005\\u0000\\u0000%\\u0001'\\t\\u0001\\u0007\\u0002�\\u0002B�������\\u0002C���\\u0001a�\\u0000\\u0000\\u0002�:\\u0000d\\u0005v\\u0003�\\u0000\\b\\u0000\\u0011\\u0000\\u0000\\u0001\\u0011!\\u0017!\\u0011#\\t\\u0004#\\u0011!\\u0017!\\u0011\\u0004����\\u0001}�\\u0001+\\u0001+��\\u0001+\\u0001,�\\u0001����\\u0001�\\u0002X��p��\\u0001\\u001b\\u0001,\\u0001\\u001b���p�\\u0002X\\u0000\\u0000\\u0000\\u0000\\u0001\\u0000\\u0012\\u0000\\u0000\\u0004�\\u0004�\\u00002\\u0000\\u0000\\u000132\\u0016\\u0014\\u0006+\\u0001\\u0003\\u000e\\u0002+\\u0001\\u0015\\u0014\\u0006\\\"&=\\u0001!\\u0015\\u0014\\u0006\\\"&=\\u0001#\\\"&5463!7!\\\"&'\\u0003&763!7>\\u0001\\u0004\\u001a^\\u0014\\u001e\\u001e\\u00146�\\u0002\\b\\u001e\\u0012\\u001f\\u001d*\\u001d��\\u001d*\\u001d2\\u0015\\u001d\\u001d\\u0015\\u0002\\u00170�� -\\u0005d\\u0005\\u000f\\u000e\\u0019\\u0003�&\\u0005\\u001b\\u0004�\\u001d*\\u001d�?\\u0004\\r\\u00162\\u0014\\u001e\\u001e\\u001422\\u0014\\u001e\\u001e\\u00142\\u001e\\u0014\\u0015\\u001d�*\\u0016\\u0001�\\u0018\\u0012\\u0013�\\u0011\\u0015\\u0000\\u0000\\u0000\\u0002\\u0000\\u0000\\u0000\\u0000\\u0004�\\u0004L\\u0000\\u000b\\u0000\\u000f\\u0000\\u0000\\u0001\\u0015!53463!2\\u0016\\u0015\\u0005!\\u0011!\\u0004��P�;)\\u0001,);�D\\u0004��P\\u0003�dd);;)���\\u0000\\u0002\\u0000\\u0001\\u0000\\u0000\\u0005�\\u0004L\\u0000\\f\\u0000\\u0010\\u0000\\u0000\\u0013\\u0003\\u00113463!2\\u0016\\u0015!\\u0015\\u0005\\u0001!\\u0001���;)\\u0001,);\\u0001�\\u0001,���P\\u0001,\\u0003 �p\\u0002X);;)�d�D\\u0002�\\u0000\\u0001\\u0001.\\u0000\\u0000\\u0003�\\u0004�\\u0000\\t\\u0000\\u0000\\u00013\\u0011#\\t\\u0001#\\u00113\\u0001\\u0001.��\\u0001*\\u0001*����\\u0001,\\u0002X\\u0001,������\\u0000\\u0001\\u0000\\u0000\\u0001/\\u0004�\\u0003�\\u0000\\t\\u0000\\u0000\\u00015!\\u0015\\t\\u0001\\u0015!5\\u0001\\u0003�����\\u0001,\\u0002X\\u0001,\\u0001/��\\u0001)\\u0001*����\\u0000\\u0004\\u0000\\u0000\\u0000\\u0000\\u0004�\\u0004�\\u0000\\t\\u0000\\u0019\\u0000\\u001d\\u0000!\\u0000\\u0000\\u001b\\u0001>\\u00013!2\\u0016\\u0017\\u0013\\u0005!2\\u0016\\u001d\\u0001\\u0014\\u0006#!\\\"&=\\u000146\\u0005#\\u001537#\\u00153\\u001f�\\u0005$\\u0014\\u0002�\\u0013%\\u0005���\\u0003�);;)�\\u0018);;\\u0003Idd�dd\\u0001�\\u0002�\\u0016'-\\u0017�$d;)d);;)d);dddd\\u0000\\u0000\\u0000\\u0003��\\u0000d\\u0004�\\u0004L\\u0000\\r\\u0000'\\u00003\\u0000\\u0000%\\u00114632\\u0016\\u0015\\u0011\\u0014\\u0006#\\\"&\\u0001%\\u0011%#\\u0013\\u0016\\u000e\\u0001#\\\"+\\u0001\\\"&'\\u0002=\\u0001454>\\u00023\\u0007546?\\u0001\\u0015.\\u0004\\u0004L\\u001d\\u0015\\u0014\\u001e\\u001e\\u0014\\u0015\\u001d��\\u0002��]&/\\u0002\\n\\f\\u000f\\u0005\\u0003S\\u0014\\u001d\\u00048\\u0001\\u0004\\f\\t�2\\u0019\\u0019\\u0004\\u000e\\\"\\u001a\\u0016�\\u0003R\\u0015\\u001d\\u001d\\u0015��\\u0014\\u001e\\u001e\\u0002l������\\f\\u000b\\u0001\\u001c\\u0015\\u0001Q\\u000e�\\u0002\\u0003\\r\\u000b\\u000f\\u0006�2\\u00182\\r\\r�\\u0002\\u0007\\u0015\\u0016!\\u0000\\u0000\\u0001\\u0000\\u0015\\u0000\\u0015\\u0004�\\u0004�\\u0000\\u0017\\u0000\\u0000\\u0001\\u0007'\\u0017\\u0007\\u0017\\u0007\\u0017\\u00077\\u00177\\u00177\\u0017'7'7'7\\u0007'\\u0007\\u0001�-�N鳳�N�-��-�N괴�N�-�\\u0004��N�,��-�N鳳�N�-��,�N��\\u0000\\u0003\\u0000\\u0000\\u0000d\\u0004�\\u0004�\\u0000\\u001e\\u0000*\\u0000.\\u0000\\u0000\\u0001#\\\"\\u0006\\u000f\\u0002\\u0006\\u0015\\u0011\\u0014;\\u0001\\u0016;\\u000127\\u00136=\\u00014&#!6=\\u00014&\\u0003\\u0007!\\u0015\\u0003#'#\\u0011?\\u00013\\u0001\\u00113\\u0011\\u0002�2\\u001b0\\u000e`�\\u0014d={\\u0010�.%�\\u001d='��\\u001c='2\\u0001��ֈd�d2�D�\\u0004�(\\u001c��\\u001a%�pKd9\\u0001X\\u001f+d,Qv\\u0007�,Q���}��d\\u0001w������\\u0002X\\u0000\\u0003\\u0000\\u0000\\u0000\\u0000\\u0004�\\u0004L\\u0000\\u001e\\u0000\\\"\\u0000.\\u0000\\u0000!#\\\"&/\\u0002&5\\u00114;\\u00016;\\u00012\\u0017\\u0013\\u0016\\u001d\\u0001\\u0014\\u0006#!\\u0016\\u001d\\u0001\\u0014\\u0006\\u0001#\\u00113\\u0001'!5\\u0003#\\u0007#\\u0011\\u001f\\u00013\\u0002�2\\u001b0\\u000e`�\\u0014d={\\u0010�.%�\\u001d='��\\u001c=����\\u0001�2\\u0001��ֈd�d2(\\u001c��\\u001a%\\u0001�Kd9��\\u001f+d,Qv\\u0007�,Q\\u0001�\\u0002X�+�}\\u0001wd����\\u0000\\u0000\\u0000\\u0003\\u0000\\b\\u0000d\\u0005\\u0015\\u0004U\\u0000\\u001e\\u0000=\\u0000A\\u0000\\u0000\\u0001%632\\u001f\\u0001\\u0016\\u0015\\u0014\\u000f\\u0001!2\\u0016\\u0014\\u0006+\\u0001\\u0003\\u000e\\u0001#!\\\"&5\\u0011467\\u0017\\u0011\\u0017!\\u0013>\\u0001;\\u00012654&#!*\\u0002.\\u0004'&54?\\u0001'\\u0001#\\u00113\\u0001l\\u0001j\\u000e\\u000b\\u0011\\fm\\u000e\\u000bU\\u0001.UkmTk�\\u0007\\u001b\\u000f��\\u0007�\\u001c\\u000e:d\\u0001%�\\u0006\\u001b\\u000f�\\u0010\\u0012\\u0012\\u0010�7\\u0001\\u000b\\u0004\\t\\u0003\\u0007\\u0004\\u0004\\u0002\\u0005\\n�V����\\u0003i�\\u0006\\fp\\u000e\\u0014\\u0012\\u000eyL�N��\\u0016'�\\r\\u0002\\r\\u0011%\\nH�\\tY\\u0001S\\u0015(\\u001e\\u0015\\u0014\\u001d\\u0001\\u0001\\u0002\\u0003\\u0005\\u0003\\f\\b\\u000e\\r�S��\\u0002X\\u0000\\u0000\\u0000\\u0003��\\u0000e\\u0004�\\u0004V\\u0000\\u001e\\u00008\\u0000<\\u0000\\u0000\\u0001\\u0005\\u001e\\u0002\\u0015\\u0011\\u0014\\u0006#!\\\"&'\\u0003#\\\"&46\\u0017!'&54?\\u0001632\\u0007\\u0017\\u0016\\u0015\\u0014\\u0007\\u000e\\u0005*\\u0001#!\\u001532\\u0016\\u0017\\u0013!7\\u0011%\\u0001#\\u00113\\u0001�\\u0001m\\u0007\\u0013!�\\b��\\u000f\\u001b\\u0006�jTnlU\\u0001.U\\u000b\\u000em\\r\\u0010\\u000b[�\\n\\u0005\\u0001\\u0005\\u0003\\u0007\\u0004\\t\\u0004\\u000b\\u0001�$�\\u000f\\u001b\\u0006�\\u0001%j��\\u0002���\\u0004P�\\u0004\\r'\\u0011��\\r�(\\u0015\\u0001SN�L\\u0001y\\u0010\\u0010\\u0015\\rq\\f��\\u000b\\u000f\\u000b\\t\\u0003\\u0005\\u0003\\u0002\\u0001\\u0001d)\\u0014��Y\\u0001����\\u0002X\\u0000\\u0000\\u0003\\u0000a\\u0000\\u0000\\u0004L\\u0005\\u000e\\u0000\\u001b\\u00006\\u0000:\\u0000\\u0000\\u0001\\u00114&'%54&\\\"\\u0006\\u0015\\u0011'&\\u0006\\u000f\\u0001\\u0006\\u0017\\u0013\\u001e\\u00023!26\\u0007!\\u00037\\u0017\\u00167>\\u0005<\\u00015\\u001146\\u0016\\u001d\\u0001\\u0014\\u0016\\u0017\\u0005\\u0019\\u0001\\u0015!5\\u0004L(\\u0015��N�Ly\\u000f%\\u000ep\\u0016\\u0010�\\u0004\\r'\\u0011\\u0002\\r\\r���\\t�S�\\u0016\\u0019\\u0003\\u0005\\u0003\\u0002\\u0001\\u000122(\\u0015\\u0001S��\\u0001�\\u0001V\\u000f\\u001b\\u0006�jTnkU��T\\f\\u0001\\rn\\u0016\\u001f��\\u0006\\u0013\\u001f�B\\u0001SV�\\u0012\\r\\u0001\\u0005\\u0003\\u0007\\u0004\\t\\u0003\\f\\u0001\\u0001�\\u0016\\u0012\\u0013\\u0015�\\u0010\\u001b\\u0006�������\\u0000\\u0003\\u0000\\u0001\\u0000\\n\\u0003�\\u0005\\u0018\\u0000\\u0003\\u0000\\u001f\\u00006\\u0000\\u0000\\u00015!\\u0015\\u0001%>\\u00015\\u00114&#!\\\"\\u0006\\u000f\\u0001\\u0003\\u0006\\u001f\\u0001\\u001e\\u0001?\\u0001\\u0003\\u0014\\u0016265\\u0001\\u0011\\u0005\\u000e\\u0001\\u001d\\u0001\\u0014\\u0006&5\\u0011<\\u0001.\\u0001'&\\u000f\\u0001'\\u0013!\\u00011\\u0002X��\\u0001S\\u0014)�\\r��\\u0011%\\n\\n�\\u000f\\u0016p\\r&\\u000fy\\u0001M�N\\u0001,��\\u0014(22\\u0003\\u0007\\u0006\\u0018\\u0016�S�\\u0001�\\u0004P�����\\u0006\\u001b\\u000f\\u0001V\\u0007�\\u001c\\u000e\\u000f��\\u001f\\u0016n\\r\\u0001\\u000bU��TlnT\\u0002X�ڂ\\u0006\\u001c\\u000f�\\u0016\\u0012\\u0012\\u0016\\u0001�\\u000b\\u0007\\u0010\\b\\u0003\\r\\u0012�V\\u0001S\\u0000\\u0000\\u0002\\u0000\\u0005\\u0000\\u0000\\u0004�\\u0004�\\u0000\\u000e\\u0000\\u0015\\u0000\\u0000\\u00012\\u0004\\u0012\\u0010\\u0002\\u0004 $\\u000254>\\u0002\\u0013!\\u0015!\\u0007\\t\\u0001\\u0002[�\\u0001\\u0013���������_��u��\\u0001,\\u0002\\u0001��n\\u0004��������\\u0001\\u0013�zݠ_�\\u0012��\\u0001&\\u0001*\\u0000\\u0000\\u0000\\u0002\\u0000\\u0000\\u0000\\u0000\\u0004�\\u0004�\\u0000\\u0010\\u0000\\u0017\\u0000\\u0000\\u00012\\u001e\\u0002\\u0015\\u0014\\u0002\\u0004 $\\u000254>\\u0002\\t\\u00015!5!5\\u0002Uzݠ_��������_����\\u0001�\\u0001.��\\u0004�_��z���\\u0001\\u0013�zݠ_�������\\u0000\\u0002\\u0000\\u0005\\u0000\\u0000\\u0004�\\u0004�\\u0000\\u0010\\u0000\\u0017\\u0000\\u0000\\u00012\\u001e\\u0002\\u0015\\u0014\\u0002\\u0004 $\\u000254>\\u0002\\u00033\\u00113\\u00113\\u0001\\u0002[yݠ_��������_�ݵ�����\\u0004�_��z���\\u0001\\u0013�zݠ_����\\u0001,\\u0001�\\u0000\\u0000\\u0002\\u0000\\u0005\\u0000\\u0000\\u0004�\\u0004�\\u0000\\u0010\\u0000\\u0017\\u0000\\u0000\\u00012\\u001e\\u0002\\u0015\\u0014\\u0002\\u0004 $\\u000254>\\u0002\\u0013\\u0011#\\t\\u0001#\\u0011\\u0002[yݠ_��������_��\\u0013�\\u0001,\\u0001,�\\u0004�_��z���\\u0001\\u0013�zݠ_�����p\\u0001�\\u0001,\\u0000\\u0000\\u0000\\u0003\\u0000\\u0005\\u0000\\u0000\\u0004�\\u0004�\\u0000\\u0010\\u0000�\\u0000�\\u0000\\u0000\\u00012\\u001e\\u0002\\u0015\\u0014\\u0002\\u0004 $\\u000254>\\u0002\\u0017\\u000e\\u0003\\u0007\\u0006&\\u0007\\u000e\\u0001\\u0007\\u0006\\u0016\\u0007\\u000e\\u0001\\u0007\\u0006\\u0016\\u0007\\u0014\\u0016\\u00072\\u001e\\u0001\\u0017\\u0016\\u0017\\u001e\\u00027\\u0016\\u0006\\u0017\\u0016\\u0017\\u0014\\u000e\\u0001\\u0017\\u00167>\\u00027.\\u0001'.\\u0001'\\\"\\u000e\\u0002\\u0007\\u0006'&65.\\u0001'6.\\u0001\\u0007\\u0006'&767\\u001e\\u0002\\u0017\\u001e\\u0001\\u001f\\u000146'&67>\\u00037&72\\u0016267.\\u0003'6'\\u001e\\u0001?\\u00016.\\u0001'\\u0006\\u0007\\u0014\\u001e\\u0001\\u0017.\\u0003'>\\u00017\\u00162>\\u0001\\u0002[yݠ_��������_�ݒ\\u000f+\\u001a>\\b\\u000f=\\u000f\\u0015>\\u0003\\u0003\\u0013\\u0001\\u00031\\u0005\\b\\u001b\\u0006\\\"\\u0001\\f\\u0016\\u0018\\b\\u0018T\\u0016>9\\u001d\\b.\\u0003*-\\u0006\\u0001\\u0005fw\\u001e\\\"#\\u0003\\u000e.\\r\\u000eF\\u0011\\t= .\\u00102\\u0010\\u0004\\u0001\\u0006)\\u0004\\u0002\\b\\u0019\\u001a\\u0017\\u0013\\u0013\\u000b\\u0006\\u0010\\u0006(\\u001b\\u0006\\f(\\u000e\\u000e\\u0013\\u0004\\u0004%\\u0004\\u0005\\n\\u0007\\u0018\\u0016\\u0006\\u0010\\b\\u001f\\u0012\\u0017\\t\\n)#?\\f\\u000b\\n\\u001f7\\f\\u000b\\u0006.R\\u000f\\u0013 \\u0010\\u0011\\u0001\\t,\\u001c$\\f\\u0003\\u001a\\u0003\\n\\u0011\\u000b\\u0012\\u0004�_��z���\\u0001\\u0013�zݠ_^\\f\\u0012\\u0006\\n\\u0001\\u0003\\u0007\\u0006\\u0007'\\u000f\\u000b\\u0017\\u0007\\\"q\\u0017!w\\u001c\\tF\\u0019\\u000b\\u0013\\u0004\\f\\u001e\\b/\\u001e\\u0004\\u0012J\\u0014G\\t\\u0006\\u0013\\n\\f\\u0002r\\u001d$>\\u001f\\t\\u0001\\u0007\\u0007\\u0010\\u000b\\u0001\\u0002\\u000b\\u000b#\\u0017\\u0002/\\u0002\\r\\b\\u0003\\u0016&\\u0012\\u001d\\u0019\\u001d\\u001c\\u001e\\u0010\\u0006\\u0001\\u0001\\u0007\\n\\u0013%\\t\\b\\u0003I\\u0015\\u0017+\\n\\u000e*\\u0014\\u0019\\t\\u0012\\u0013\\u0003\\t\\u000b\\u0017'\\u0015 \\u0007)\\u0003\\r\\u0003\\u0005\\u0004$#\\u0016\\f\\u0003h\\u00121'\\u0004\\u0002\\u0006\\u0004\\f\\b\\f$\\u0007\\n\\f\\u0011\\u0000\\u0000\\u0000\\u0000\\u0006\\u0000\\u0000\\u0000`\\u0004�\\u0004�\\u0000\\u000f\\u0000\\u0013\\u0000#\\u0000'\\u00007\\u0000;\\u0000\\u0000\\u0013!2\\u0016\\u001d\\u0001\\u0014\\u0006#!\\\"&=\\u000146\\u0005#\\u00153\\u0005!2\\u0016\\u001d\\u0001\\u0014\\u0006#!\\\"&=\\u000146\\u0005!\\u0015!\\u0005!2\\u0016\\u001d\\u0001\\u0014\\u0006#!\\\"&=\\u000146\\u0005!\\u0015!d\\u0003�);;)�\\u0018);;\\u0004\\u0011���\\u0018\\u0003�);;)�\\u0018);;\\u0004\\u0011�\\f\\u0001��\\u0018\\u0003�);;)�\\u0018);;\\u0004\\u0011��\\u0001,\\u0004�;)d);;)d);dd�;)d);;)d);dd�;)d);;)d);dd\\u0000\\u0000\\u0000\\u0002\\u0000d\\u0000\\u0000\\u0004L\\u0004�\\u0000\\u0003\\u0000\\t\\u0000\\u0000\\u0001\\u0015!5\\u0017!\\u0001\\u0011\\u0007\\u0011\\u0004L�\\u00182\\u0003����\\u0004�dd��\\f���\\u0001�\\u0000\\u0004\\u0000\\u0000\\u0000\\u0000\\u0004�\\u0004�\\u0000\\u0006\\u0000\\r\\u0000\\u0014\\u0000\\u001b\\u0000\\u0000\\u00017'7!\\u00117\\u0001\\u0011'\\u0007'7'\\u0001\\u0017!\\u0011\\u00177\\u0017\\u00057\\u0011!7'7\\u0001I�ȁ�p�\\u0004/�Ȏȁ����p�Ȏ\\u0002X��p�Ȏ\\u0002َȁ�p�\\u0001\\u000f�p�Ȏȁ�с\\u0001��Ȏ:��p�Ȏ\\u0000\\u0000\\u0006\\u0000\\u0000\\u0000\\u0000\\u0004�\\u0004�\\u0000\\u000b\\u0000\\u0015\\u0000\\u001f\\u00008\\u0000B\\u0000L\\u0000\\u0000\\u0000 \\u0004\\u0012\\u0010\\u0002\\u0004 $\\u0002\\u0010\\u0012\\u0004 \\u0006\\u0015\\u0014\\u0016 654%2\\u0016\\u0014\\u0006#\\\"&46\\u00057&54632\\u0016\\u0014\\u0006#\\\"'\\u0007\\u0016\\u0015\\u0014\\u0006\\\"&546762\\u0016\\u0014\\u0006#\\\"&54$2\\u0016\\u0015\\u0014\\u0006#\\\"&4\\u0001�\\u0001D\\u0001\\u0012�������\\u0002_����\\u0001V���\\u0016  \\u0016\\u0017  \\u0001\\u0014\\u0001\\t \\u0017\\u0016  \\u0016\\u000e\\u000f7\\u00113H3)\\u001f�.\\u001f \\u0016\\u0017 �\\\".  \\u0017\\u0016 \\u0004�������\\u0001\\u0012\\u0001D\\u0001\\u0012\\u0016����򬫊 . !,!T\\u0001\\u000e\\u000e\\u0016! . \\n�\\u0016\\u001d$33$ 1\\u0005\\u000e\\u001f.  \\u0017\\u0016  \\u0016\\u0017  .\\u0000\\u0000\\u0002\\u0000P\\u00006\\u0004�\\u0004X\\u0000\\u0019\\u00003\\u0000\\u0000%'&'.\\u000354632\\u0017632\\u0016\\u0015\\u0014\\u000e\\u0002\\u0007\\u0006\\u0007\\u00137>\\u000254&#\\\"\\u000f\\u0001'&#\\\"\\u0006\\u0015\\u0014\\u001e\\u0001\\u001f\\u0001\\u0016\\u00176\\u0002�\\u0010Z�GCW#ń�bg���#WCG�Z�\\f@C>`9J:vr3H<c=>@\\u0016]aR6\\u0016}�FGlZ.�Ł�Ń.ZlGF�}\\u0001�\\f>FX\\u001cG`R��ObE\\u001bVA>\\u0016Zo\\\\\\u0000\\u0000\\u0000\\u0002\\u00009��\\u0004w\\u0004�\\u0000\\u0019\\u00002\\u0000\\u0000\\u0001\\u00177'\\u0001\\u0017\\u0007\\u0017\\u0016\\u00177>\\u000154/\\u0001&#\\\"\\u0007\\u0001\\u0006\\u0015\\u0014\\u0017\\u0003\\u0017\\u0016327\\u000164/\\u0001&'\\u0007\\u0017\\u0001'7'&'\\u0007\\u0006\\u0015\\u0014\\u0001�\\u0013i�\\u0001��_\\u0012.\\u001f\\u001d#7B�B]_@��BBԍB]_@\\u0001\\u001bBB�\\f\\u0007i��{�_\\u0012.\\u001d7B\\u0001�\\u0011i�\\u0001��`\\u0012.5\\u001d#j+]B�BB��@_]B���BB\\u0001\\u001bB�B�\\f\\u0005i��{�_\\u0012-87B]^\\u0000\\u0000\\u0000\\u0000\\u0003\\u0000�\\u0000\\u0000\\u0003�\\u0004�\\u0000\\u0011\\u0000\\u0015\\u0000\\u001d\\u0000\\u00007\\u00114>\\u00022\\u001e\\u0002\\u0015\\u0011\\u0014\\u0006#!\\\"&\\u0001!\\u0011!\\u0004264&\\\"\\u0006\\u0014�<f���d:;)��);\\u0002���\\u0002X��V==V=d\\u0003�\\u00152.\\u001e\\u001e.2\\u0015�G);;\\u0003��D�=V==V\\u0000\\u0000\\u0003\\u0001'\\u0000\\u0012\\u0004\\t\\u0004�\\u0000/\\u0000;\\u0000A\\u0000\\u0000\\u0001\\u0011\\u0017\\u001e\\u0004\\u0015\\u0014\\u0006\\u0007\\u0015#5&'.\\u0001'3\\u001e\\u0001\\u0017\\u0011'.\\u000454>\\u0001753\\u0015\\u001e\\u0004\\u0017#.\\u0001\\u0003\\u0011\\u000e\\u0001\\u0015\\u0014\\u001e\\u0003\\u0017\\u0016\\u0017\\u0011654&\\u0002�@\\\"<P7(��d�U(\\u0019\\u0003�\\u0005WJ\\u001b.BN/!X�Od&ER<+\\u0003�\\b6�=I\\u0010\\u0011*\\u0014\\u001c\\u0007h�X\\u0004\\u0005��\\u000e\\u0007\\u0013,<e>��\\u000bMN\\u0011W(kVMc\\u000f\\u0001O\\u0007\\u000e\\u0019/9X7\\\\�C\\u0007NO\\u0004\\u0013,?iBHK��\\u0001\\u0012\\b;I\\u001d,\\u0018\\u0015\\u0006\\u0007\\u0002���\\u0012�@G\\u0000\\u0001\\u0000d\\u0000f\\u0003�\\u0004�\\u0000H\\u0000\\u0000\\u0001\\u0017\\u000e\\u0002#\\\"&\\u0007\\u000e\\u0001\\u000f\\u0001'>\\u00057>\\u0001'#53&'.\\u0001>\\u00017632\\u0016\\u0015#4.\\u0001#\\\"\\u0006\\u0007\\u0006\\u0015\\u0014\\u001e\\u0006\\u00173\\u0015#\\u0016\\u0006\\u0007\\u0006\\u0007>\\u000136\\u001632\\u0003b2)O'*\\u0017�2'V\\u0017\\u00187\\u0006\\u0015\\n\\u0011\\f\\u0011\\t0\\f$ݦ\\u0018\\u0014\\n\\t\\u0003/-a��ʙDP$%T\\u0014)\\u0005\\u0006\\r\\b\\u0014\\b\\u0017\\u0002��\\b\\u0015\\u0015):#b\\u0015 �\\\"L\\u0001,�\\u0019\\u0017\\u0003B\\u0004\\u0004\\u001a\\f\\u000b�\\u0004\\u000e\\u0006\\r\\u000b\\u0011\\n7�Gd17\\u001a;V^(X�w4K\\u001c\\u001d\\u0015,9\\u000b\\u001b\\u0015 \\u0012%\\u000e(\\u0004d2�\\u001d;6\\u000b\\u000e\\u0001\\\"\\u0000\\u0000\\u0000\\u0000\\u0002\\u0000\\u0002\\u0000\\u0000\\u0004�\\u0004�\\u0000\\u0006\\u0000\\r\\u0000\\u0000!\\u0001#\\u0011#\\u0011#\\t\\u0001#\\u0011#\\u0011#\\u0001,\\u0001*���\\u0003�\\u0001*���\\u0001,\\u0003��|\\u0003����|\\u0003�\\u0000\\u0000\\u0000\\u0005\\u0000\\u0002\\u0000\\u0000\\u0003�\\u0004�\\u0000\\u0006\\u0000\\u000e\\u0000\\u0012\\u0000\\u001c\\u0000\\\"\\u0000\\u0000\\u00013\\t\\u00013\\u00113!\\u0011#5#\\u0015#\\u0011\\u0017#\\u00153\\u0003!\\u0015#\\u0015#535#\\u00133\\u0015!53\\u0001��������\\u0002Xddd�dd�\\u0001,cdc�d���d\\u0001,��\\u0001,\\u0003��\\fdd\\u0001�d��p�ddd��d�\\u0000\\u0005\\u0000\\u0002\\u0000\\u0000\\u0003�\\u0004�\\u0000\\u0006\\u0000\\u0010\\u0000\\u0016\\u0000\\u001e\\u0000\\\"\\u0000\\u0000\\u00013\\t\\u00013\\u00113!\\u0015#\\u0015#535#5\\u00133\\u0015!53\\u0003!\\u0011#5#\\u0015#735#\\u0001��������\\u0002Xcdc�d���dd\\u0001,dddedd\\u0001,��\\u0001,\\u0003��dddd�pd��p�\\fdd��\\u0000\\u0000\\u0004\\u0000\\u0002\\u0000\\u0000\\u0004L\\u0004�\\u0000\\u0006\\u0000\\f\\u0000\\u0012\\u0000\\u0016\\u0000\\u0000!\\u0001#\\u0011#\\u0011#\\u0001#53\\u0011#\\u0017\\u0011#5#\\u0011\\u0017#\\u00153\\u0001,\\u0001*���\\u0003�d�d�d��dd\\u0001,\\u0003��|\\u0003 d�\\f��\\fd\\u0001�d�\\u0000\\u0004\\u0000\\u0002\\u0000\\u0000\\u0004L\\u0004�\\u0000\\u0006\\u0000\\f\\u0000\\u0010\\u0000\\u0016\\u0000\\u0000!\\u0001#\\u0011#\\u0011#\\u0001\\u0011#5#\\u0011\\u0017#\\u00153\\u0003#53\\u0011#\\u0001,\\u0001*���\\u0004Jd��dded�d\\u0001,\\u0003��|\\u0003��\\fd\\u0001�d��\\fd�\\f\\u0000\\u0000\\u0000\\u0000\\u0005\\u0000\\u0002\\u0000\\u0000\\u0004�\\u0004�\\u0000\\u0006\\u0000\\n\\u0000\\u000e\\u0000\\u0012\\u0000\\u0016\\u0000\\u0000!\\u0001#\\u0011#\\u0011#\\u0001#53\\u0013!5!\\u0013!5!\\u0013!5!\\u0001,\\u0001*���\\u0003���d��\\u0001,d�p\\u0001�d�\\f\\u0001�\\u0001,\\u0003��|\\u0002���\\f��\\f��\\f�\\u0000\\u0000\\u0000\\u0000\\u0005\\u0000\\u0002\\u0000\\u0000\\u0004�\\u0004�\\u0000\\u0006\\u0000\\n\\u0000\\u000e\\u0000\\u0012\\u0000\\u0016\\u0000\\u0000!\\u0001#\\u0011#\\u0011#\\u0001!5!\\u0003!5!\\u0003!5!\\u0003#53\\u0001,\\u0001*���\\u0004��\\f\\u0001�d�p\\u0001�d��\\u0001,d��\\u0001,\\u0003��|\\u0002���\\f��\\f��\\f�\\u0000\\u0000\\u0000\\u0000\\u0002\\u0000\\u0000\\u0000\\u0000\\u0004L\\u0004L\\u0000\\u000f\\u0000\\u001f\\u0000\\u0000\\u0001!2\\u0016\\u0015\\u0011\\u0014\\u0006#!\\\"&5\\u001146\\u0005!\\\"\\u0006\\u0015\\u0011\\u0014\\u00163!265\\u00114&\\u0001�\\u0001,�����ԥ��\\u00025�\\f);;)\\u0001�);;\\u0004L���ԥ���\\u0001,���;)�\\f);;)\\u0001�);\\u0000\\u0000\\u0000\\u0000\\u0003\\u0000\\u0000\\u0000\\u0000\\u0004L\\u0004L\\u0000\\u000f\\u0000\\u001f\\u0000\\\"\\u0000\\u0000)\\u0001\\\"&5\\u0011463!2\\u0016\\u0015\\u0011\\u0014\\u0006\\u0003!\\\"\\u0006\\u0015\\u0011\\u0014\\u00163!265\\u00114&\\u0005\\u0011%\\u0002��ԣ���\\u0001,���A�\\f);;)\\u0001�);;�G\\u0001M��\\u0001,�����ԥ�\\u0003�;)�\\f);;)\\u0001�);d�\\f�\\u0000\\u0003\\u0000\\u0000\\u0000\\u0000\\u0004L\\u0004L\\u0000\\u000f\\u0000\\u001f\\u0000\\\"\\u0000\\u0000\\u0019\\u0001463!2\\u0016\\u0015\\u0011\\u0014\\u0006#!\\\"&%\\u00114&#!\\\"\\u0006\\u0015\\u0011\\u0014\\u00163!26\\u0003!\\u0013��\\u0001,�����ԥ�\\u0003�;)�\\f);;)\\u0001�);d�\\f�\\u0001�\\u0001,�����ԥ��A\\u0001�);;)�\\f);;\\u0001���\\u0000\\u0003\\u0000\\u0000\\u0000\\u0000\\u0004L\\u0004L\\u0000\\u000f\\u0000\\u001f\\u0000\\\"\\u0000\\u0000\\u0001\\u0011\\u0014\\u0006#!\\\"&5\\u0011463!2\\u0016\\u0003\\u00114&#!\\\"\\u0006\\u0015\\u0011\\u0014\\u00163!26\\u0001\\u0003!\\u0004L���ԥ���\\u0001,���;)�\\f);;)\\u0001�);���\\u0001�\\u0002��Ԣ���\\u0001,�����\\u0001�);;)�\\f);;\\u0001���\\u0000\\u0000\\u0002\\u0000\\u0000\\u0000\\u0000\\u0005\\u0014\\u0004L\\u0000\\u0013\\u0000\\u001a\\u0000\\u0000\\u0001!2\\u0016\\u0015\\u0011\\u0014\\u0006#!5!265\\u00114&#!\\u0013\\u00015!\\u0011!5\\u0001�\\u0001������p\\u0001�);;)�\\f��p��\\u0001,\\u0004L���ԥ��;)\\u0001�);�����\\u0001,�\\u0000\\u0000\\u0001\\u0000�\\u0000\\u0001\\u0003�\\u0004�\\u0000\\u001f\\u0000\\u0000%\\u001727\\u00016'&\\u0007!6\\u001276/\\u0001#\\\"\\u0007\\u000e\\u0001\\u0000\\u0007\\u0006\\u0017\\u00163!\\u0002\\u0007\\u0006\\u0017\\u0001�\\t\\r\\r\\u0002\\u001a\\u000f\\t\\b\\u0018��\\u0001�\\u0002\\u0002\\b\\b\\t\\u0010\\t\\u0004���L\\u0011\\n\\n\\u0016\\u0001.�\\u0005\\u0005\\t\\u0002\\u0001\\u0010\\u0002v\\u0013\\u0011\\u0012\\u0002\\u0004\\u0001�\\f\\u0011\\n\\b\\u000f\\u0005���X\\u0013\\u0015\\u0013�J\\u0014\\u0015\\u000b\\u0000\\u0000\\u0000\\u0000\\u0002\\u0000\\u0000\\u0000\\u0000\\u0005\\u0014\\u0004L\\u0000\\u0018\\u0000\\u001f\\u0000\\u0000%!\\\"&5\\u0011463!5.\\u0001/\\u0001\\\"\\u0006\\u0015\\u0011\\u0014\\u00163!2?\\u00015!\\u0011!5\\u0001\\u0003 �\\f);;)\\u0001�\\u000e�]]����\\u0001,/5d��\\u0001,\\u0001��;)\\u0001�);�\\u0004\\u0007\\u0002\\u0002���ԥ�\\u000f��\\u0001,���\\u0000\\u0000\\u0002\\u0000\\u0000\\u0000\\u0000\\u0004�\\u0004�\\u0000\\u0006\\u0000$\\u0000\\u0000\\u0001'\\u0001'\\u0001'!\\u0003\\u0007\\u0015\\u0014\\u0006#!\\\"&5\\u001146;\\u00017'#\\\"\\u0006\\u0015\\u0011\\u0014\\u00163!26=\\u0001\\u0004�����\\u0001a�\\u0001��z;)�\\f);;)�vJd����\\u0001,��\\u0002�����\\u0001V���{�);;)\\u0001�);zN���ԥ���b\\u0000\\u0000\\u0000\\u0003\\u0000\\u0004\\u0000\\u0004\\u0004�\\u0004�\\u0000\\u000b\\u0000\\u0013\\u0000\\u001b\\u0000\\u0000\\u0000 \\u0004\\u0012\\u0010\\u0002\\u0004 $\\u0002\\u0010\\u0012\\u0004 \\u0006\\u0010\\u0016 6\\u0010$2\\u0016\\u0014\\u0006\\\"&4\\u0001�\\u0001D\\u0001\\u0012�������\\u0002_����\\u0001V��\\u0012�rr�r\\u0004�������\\u0001\\u0012\\u0001D\\u0001\\u0012\\u0016�����\\u0001V\\u0017r�rr�\\u0000\\u0000\\u0000\\u0000\\u0003\\u0000\\u0000\\u0000\\u0000\\u0004L\\u0004�\\u0000\\u0006\\u0000\\u0010\\u0000\\u0014\\u0000\\u0000\\u0001\\u0011!\\u0011!\\t\\u0002!2\\u0016\\u0015\\u0011!\\u001146\\u0005#\\u00153\\u0002�����\\u0001�\\u0001��6\\u0004\\u0018\\u000b\\u0010��\\u000e\\u0003�dd\\u0003 \\u0001��p�\\f\\u0001��\\f\\u000f\\n��\\u0001\\u0013\\u000b\\u000ed2\\u0000\\u0000\\u0003\\u0000\\u0000\\u0000\\u0000\\u0004L\\u0004�\\u0000\\u0006\\u0000\\u0010\\u0000\\u0014\\u0000\\u0000\\u0001\\u0011!\\u0011!\\t\\u0001\\u0003!2\\u0016\\u0015\\u0011!\\u001146\\u0005#\\u00153\\u0001�\\u0001,\\u0001'�C�>K\\u0004\\u0018\\u000b\\u0010��\\u000e\\u0003�dd\\u0002���\\u0001,\\u0001��\\f�p\\u000f\\n��\\u0001\\u0013\\u000b\\u000ed2\\u0000\\u0000\\u0003\\u0000\\u0000\\u0000\\u0000\\u0004L\\u0004\\u0000\\u0005\\u0000\\u000f\\u0000\\u0013\\u0000\\u0000\\t\\u0001'\\u0001'\\u0007\\u0003!2\\u0016\\u0015\\u0011!\\u001146\\u0005#\\u00153\\u0001�\\u0002T��F��K\\u0004\\u0018\\u000b\\u0010��\\u000e\\u0003�dd\\u0001�\\u0002T��F���k\\u000f\\n��\\u0001\\u0013\\u000b\\u000ed2\\u0000\\u0004\\u0000\\u0000\\u0000\\u0000\\u0004L\\u0004�\\u0000\\u0003\\u0000\\n\\u0000\\u0014\\u0000\\u0018\\u0000\\u0000\\u0001'\\u0007\\u0017\\u0005'\\u0007\\u0017\\u0007!\\u0011\\u0001!2\\u0016\\u0015\\u0011!\\u001146\\u0005#\\u00153\\u0001�a�a\\u0001ŕԕ�\\u0002���\\u0004\\u0018\\u000b\\u0010��\\u000e\\u0003�dd\\u0004Oa�b\\u001d�ԕ�\\u0002���\\u000f\\n��\\u0001\\u0013\\u000b\\u000ed2\\u0000\\u0000\\u0004\\u0000\\u0000\\u0000\\u0000\\u0004L\\u0004�\\u0000\\u0006\\u0000\\n\\u0000\\u0014\\u0000\\u0018\\u0000\\u0000\\u0001\\u0007\\u00177\\u0017\\u0011!\\u0003\\u0007\\u00177\\u0005!2\\u0016\\u0015\\u0011!\\u001146\\u0005#\\u00153\\u0002\\u001b�ԕ��E\\u0003a�b�\\u001b\\u0004\\u0018\\u000b\\u0010��\\u000e\\u0003�dd\\u0003��Ԕ�\\u0002��\\u0015a�a�\\u000f\\n��\\u0001\\u0013\\u000b\\u000ed2\\u0000\\u0000\\u0000\\u0002\\u0000\\u0017��\\u0004�\\u0004�\\u0000\\u0005\\u0000\\b\\u0000\\u0000\\u0001\\u0011\\t\\u0001\\u0011!\\t\\u0001\\u0015\\u0004��%���x\\u0004w�`\\u0004���\\u0001\\u0010�w\\u0001�\\u0002��8�\\u0000\\u0002\\u0000\\u0000\\u0000d\\u0004L\\u0004�\\u0000\\u0015\\u0000\\u0019\\u0000\\u0000\\u0001\\u0011\\u0014\\u0006+\\u0001\\u0011!\\u0011#\\\"&5\\u001146;\\u0001\\u0011!\\u00113+\\u0001\\u00153\\u0004L\\u001e\\u0014��D�\\u0015\\u001d\\u001d\\u0015�\\u0001�d�dd\\u0003���\\u0015\\u001d\\u0001��p\\u001d\\u0015\\u0003�\\u0014\\u001e��\\u0001,�\\u0000\\u0000\\u0000\\u0003\\u0000\\u0000\\u0000>\\u0005\\u0014\\u0004�\\u0000\\u0013\\u0000\\u0017\\u0000\\u001d\\u0000\\u0000\\u0001!\\u0011#\\\"&5\\u001146;\\u0001\\u0011!\\u00113\\u0017\\u0015\\u0001'\\u0003#\\u00153\\t\\u0001'7\\u0017\\u0001\\u0002B���\\u0015\\u001d\\u001d\\u0015�\\u0001�d���x\\u0004dd\\u0002X�%�{x\\u0001a\\u0001��p\\u001d\\u0015\\u0003�\\u0014\\u001e��\\u0001,����x\\u0002=��2�$�{x\\u0001`\\u0000\\u0003\\u0000\\u0000\\u0000\\u0006\\u0005\\u000e\\u0004�\\u0000\\u0013\\u0000\\u0017\\u0000#\\u0000\\u0000\\u0001!\\u0011#\\\"&5\\u001146;\\u0001\\u0011!\\u00113\\u0017\\u0011\\u0007'\\u0003#\\u00153\\u0001'\\u0007'7'7\\u00177\\u0017\\u0007\\u0017\\u0002\\u0011���\\u0015\\u001d\\u001d\\u0015�\\u0001�d�g�dd\\u0001Ӫ�������\\u0001��p\\u001d\\u0015\\u0003�\\u0014\\u001e��\\u0001,���g�\\u0001���\\u001e���������\\u0000\\u0000\\u0000\\u0000\\u0003\\u0000\\u0000\\u0000\\u0000\\u0004�\\u0004�\\u0000\\u0012\\u0000\\u0016\\u0000\\u001d\\u0000\\u0000\\u0001!\\u0011#\\\"&5\\u001146;\\u0001\\u0011!\\u00113\\u0017\\u0011!\\u0011#53\\u0001#\\u0011#\\t\\u0001#\\u0002��\\f�\\u0015\\u001d\\u001d\\u0015�\\u0001�d��pdd\\u0001,��\\u0001,\\u0001,�\\u0001��p\\u001d\\u0015\\u0003�\\u0014\\u001e��\\u0001,���\\u0001,�������\\u0001,\\u0000\\u0000\\u0003\\u0000\\u0000\\u0000\\u0000\\u0004�\\u0004�\\u0000\\u0012\\u0000\\u0016\\u0000\\u001d\\u0000\\u0000\\u0001!\\u0011#\\\"&5\\u001146;\\u0001\\u0011!\\u00113\\u0017\\u0011/\\u0001#53\\u00013\\t\\u00013\\u00113\\u0002Z�n�\\u0015\\u001d\\u001d\\u0015�\\u0001�d���dd\\u0001,�������\\u0001��p\\u001d\\u0015\\u0003�\\u0014\\u001e��\\u0001,��n����|\\u0001,����\\u0000\\u0000\\u0003\\u0000\\u0000\\u0000�\\u0004�\\u0004L\\u0000\\t\\u0000\\u0013\\u0000\\u0017\\u0000\\u0000\\u000154&#!\\\"\\u0006\\u001d\\u0002\\u0011\\u0014\\u00163!265\\u0011\\u0001!\\u0015!\\u0004�\\u001d\\u0015��\\u0015\\u001d\\u001d\\u0015\\u0004L\\u0015\\u001d��\\u0001��p\\u0003��\\u0015\\u001d\\u001d\\u0015�d��\\u0015\\u001d\\u001d\\u0015\\u0002&���\\u0000\\u0000\\u0000\\u0000\\u0006\\u0000\\u0000\\u0000f\\u0004�\\u0004�\\u0000\\u0006\\u0000\\n\\u0000\\u000e\\u0000\\u0015\\u0000\\u0019\\u0000\\u001d\\u0000\\u0000\\u0001!5\\t\\u00015)\\u000153\\u00153#53\\u0001!\\u0015\\t\\u0001\\u0015!;\\u0001\\u0015#7\\u001535\\u0001�\\u0001�\\u0001,���p�pd�dd\\u0001,�p��\\u0001,\\u0001�ddd�d\\u0003�����������D�\\u0001*\\u0001*�����\\u0000\\u0002\\u0000d\\u0000\\u0000\\u0004�\\u0004�\\u0000\\u0016\\u0000/\\u0000\\u0000%\\u00114&\\u0007\\u0005\\u000e\\u0001\\u0015\\u0011\\u0014\\u001e\\u0002\\u001f\\u0001\\u0011\\u0014\\u0016;\\u000126\\u0001\\u0017\\u0011\\u0007\\u0011\\u0014\\u0006+\\u0001\\\"&5\\u0011'\\u00117\\u0017\\u00113\\u00117\\u0017\\u00113\\u0011\\u0004�$\\u001a��\\u0019%\\u0015\\u001d\\u001d\\u000b\\n\\u001d\\u0015�\\u0015\\u001d�v2d\\u001d\\u0015�\\u0015\\u001dd22d22d2\\u0004R\\u001f\\u0013\\u0011u\\u0010E\\u001f��\\u001d5!\\u0018\\u0006\\u0005�s\\u0015\\u001d\\u001d\\u0004�d�p��A\\u0015\\u001d\\u001d\\u0015\\u0001��\\u0001�dd��\\u0001,dd��\\u0001,\\u0000\\u0000\\u0000\\u0000\\u0001\\u0000d\\u0000\\u0000\\u0004�\\u0004L\\u00003\\u0000\\u0000%\\u001146?\\u00015!\\u00152\\u0016\\u0015\\u0011!\\u00114635!\\u00152\\u001e\\u0003\\u0015\\u0011\\u0014\\u0006\\u000f\\u0001\\u0015!5\\\"&5\\u0011!\\u0011\\u0014\\u0006#\\u0015!5\\\".\\u0003\\u0004L2\\u0019\\u0019�pK\\u0019�\\f\\u0019K�p\\u0004\\u000e\\\"\\u001a\\u00162\\u0019\\u0019\\u0001�K\\u0019\\u0001�\\u0019K\\u0001�\\u0004\\u000e\\\"\\u001a\\u0016j\\u0003x\\u0016\\u0019\\u0001\\u000288\\f&�v\\u0001�&\\f88\\u0001\\u0005\\t\\u0015\\u000e��\\u0016\\u0019\\u0001\\u000288\\f&\\u0001��v&\\f88\\u0001\\u0005\\t\\u0015\\u0000\\u0000\\u0000\\u0006\\u0000\\u0000\\u0000\\u0000\\u0004L\\u0004L\\u0000\\t\\u0000\\u0019\\u0000\\u001d\\u0000!\\u0000%\\u0000.\\u0000\\u0000\\u0001'!\\u0007!\\u0017\\u0015%35\\u0001\\u00114&#!\\\"\\u0006\\u0015\\u0011\\u0014\\u00163!26\\u0001!\\u0015!\\u0005%\\u0015\\u0005%!\\u0015)\\u0001%\\u0011!\\u0007!'!7\\u0002�d��d\\u0001��\\u0001'i��;)��);;)\\u0001,);�p\\u0001,��\\u0002X\\u0001��p��\\u0001,��\\u0002�\\u0001'�Wd��d\\u0001��\\u0003�dd�bb��D\\u0001�);;)�\\f);;\\u0002\\u001d�#���b�b��dd�\\u0000\\u0001\\u0000\\u0010\\u0000\\u0010\\u0004�\\u0004�\\u0000!\\u0000\\u0000\\u0013\\u0007\\u0006\\u001e\\u0003\\u0017\\u001e\\u00033?\\u00016&/\\u0001&\\u0006\\u000f\\u0001&'&'7>\\u0001/\\u0001.\\u0001��\\u0001\\u0001\\u001f>�fgї{\\u001f\\u001f�\\u0010\\u0006\\u0013�\\u00134\\u0010w�|~ev\\u0011\\u0006\\u000e�\\u000e-\\u0004��\\u000b+���fg�=!\\u0001�\\u0011/\\u000e�\\u000e\\u0004\\u0011vg|~�v\\u00111\\u0014�\\u0013\\u0006\\u0000\\u0002\\u0000\\u0000\\u0000\\u0000\\u0004�\\u0004L\\u0000\\\"\\u0000@\\u0000\\u0000\\u00015.\\u0004#\\\"\\u000e\\u0004\\u000f\\u0001\\u0015\\u0014\\u0016?\\u0001>\\u0001=\\u00016 \\u0017\\u0015\\u0014\\u0016\\u001f\\u0001\\u00166\\u0005\\u0001\\u001e\\u0001\\u001d\\u0001\\u0014\\u0006#!\\\"&=\\u0001467\\u000154>\\u00032\\u001e\\u0002\\u001f\\u0001\\u0004�\\u0006\\u001ad|�~\\\\�ud?,\\t\\t\\u001d\\u0014�\\u0014\\u001d�\\u0001>�\\u001d\\u0014�\\u0014\\u001d�p\\u0001m\\u000e\\u0015\\u001e\\u0014��\\u0015\\u001d\\u0015\\u000e\\u0001m\\u0002\\u0016&RpR&\\u0016\\u0001\\u0001\\u0002��\\b\\u0019A1)\\u0015!((!\\u000b\\n�\\u0015\\u0019\\u0004!\\u0004\\\"\\u0015�\\u0018\\u0018�\\u0015\\\"\\u0004!\\u0004\\u0019)��\\u000e3\\u0014�\\u0015\\u001d\\u001d\\u0015�\\u00143\\u000e\\u0001/2\\u0004\\r \\u0019\\u0015\\u0014\\u001b\\u001c\\n\\n\\u0000\\u0000\\u0000\\u0000\\u0002\\u0000d\\u0000\\u0000\\u0004�\\u0004L\\u0000\\u0015\\u0000\\u0019\\u0000\\u00007!'57\\u0011#\\u0015#5#\\u0015#5#\\u0015#5#\\u0011\\u0017\\u0015\\u0005\\u0015!5�\\u0003�}ddd�d�ddd\\u0003���Ȗ�d\\u0001��������pd��dd\\u0000\\u0000\\u0000\\u0003\\u0000d\\u0000\\u0000\\u0004�\\u0004L\\u0000\\t\\u0000\\u0013\\u0000\\u001d\\u0000\\u0000\\u000132\\u0016\\u0015\\u0011!\\u001146\\u000132\\u0016\\u0015\\u0011!\\u001146\\u0001\\u00114&+\\u0001\\\"\\u0006\\u0015\\u0011\\u0002Xd);��;\\u0001�d);��;��;)d);\\u0004L;)�\\u0018\\u0003�);��;)�D\\u0002�);��\\u0001�);;)�p\\u0000\\u0000\\u0000\\u0000\\u0005��\\u0000\\u0000\\u0004�\\u0004L\\u0000\\u000f\\u0000\\u0013\\u0000\\u001f\\u0000'\\u0000+\\u0000\\u0000\\u0001\\u0011\\u0014\\u0006#!\\\"&5\\u0011463!2\\u0016\\u0007!\\u0011!\\u0001\\u00113\\u0015#\\u0015!\\u0011#535!#\\u0011353\\u0011#1\\u0011#\\u0011\\u0004��|�D|��|\\u0002�|���|\\u0003�����\\u0001,��\\u0001,��ddd\\u0003 �\\f|��|\\u0001�|��\\u0018�D\\u0002X��dd\\u0001,dd�\\fd\\u0001,��\\u0001,\\u0000\\u0000\\u0005��\\u0000\\u0000\\u0004�\\u0004L\\u0000\\u000f\\u0000\\u0013\\u0000\\u001f\\u0000'\\u0000+\\u0000\\u0000\\u0001\\u0011\\u0014\\u0006#!\\\"&5\\u0011463!2\\u0016\\u0007!\\u0011!\\u0001#5#\\u0011353\\u00153\\u0011#!#\\u0011353\\u0011#1\\u0011#\\u0011\\u0004��|�D|��|\\u0002�|���|\\u0003���dddddd\\u0001���ddd\\u0003 �\\f|��|\\u0001�|��\\u0018�D\\u0001���\\f��\\u0001��\\fd\\u0001,��\\u0001,\\u0000\\u0000\\u0000\\u0004��\\u0000\\u0000\\u0004�\\u0004L\\u0000\\u000f\\u0000\\u0013\\u0000\\u001b\\u0000#\\u0000\\u0000\\u0001\\u0011\\u0014\\u0006#!\\\"&5\\u0011463!2\\u0016\\u0007!\\u0011!\\u0001\\u0011!5#\\u0011353\\u0011!5#\\u001135\\u0004��|�D|��|\\u0002�|���|\\u0003���\\u0001,��d\\u0001,��\\u0003 �\\f|��|\\u0001�|��\\u0018�D\\u0002X�\\fd\\u0001,d�\\fd\\u0001,d\\u0000\\u0004��\\u0000\\u0000\\u0004�\\u0004L\\u0000\\u000f\\u0000\\u0013\\u0000\\u0016\\u0000\\u0019\\u0000\\u0000\\u0001\\u0011\\u0014\\u0006#!\\\"&5\\u0011463!2\\u0016\\u0007!\\u0011!\\u0001\\r\\u00013-\\u0001\\u0004��|�D|��|\\u0002�|���|\\u0003��\\f��\\u0001,d\\u0001,��\\u0003 �\\f|��|\\u0001�|��\\u0018�D\\u0001𖖖�\\u0000\\u0000\\u0000\\u0005��\\u0000\\u0000\\u0004�\\u0004L\\u0000\\u000f\\u0000\\u0013\\u0000\\u0017\\u0000\\u001f\\u0000'\\u0000\\u0000\\u0001\\u0011\\u0014\\u0006#!\\\"&5\\u0011463!2\\u0016\\u0007!\\u0011!\\u0003\\u0011!\\u0011\\u00133264&+\\u0001!#\\\"\\u0006\\u0014\\u0016;\\u0001\\u0004��|�D|��|\\u0002�|���|\\u0003�d�Dd�)69&�\\u0001��&96)�\\u0003 �\\f|��|\\u0001�|��\\u0018�D\\u0002X�\\f\\u0001��pT�VV�T\\u0000\\u0000\\u0000\\u0000\\u0005��\\u0000\\u0000\\u0004�\\u0004L\\u0000\\u000f\\u0000\\u0013\\u0000\\u001f\\u0000%\\u0000)\\u0000\\u0000\\u0001\\u0011\\u0014\\u0006#!\\\"&5\\u0011463!2\\u0016\\u0007!\\u0011!\\u0001\\u00113\\u0015#\\u0015!\\u0011#535\\u00013\\u0011#\\u00153\\u000335#\\u0004��|�D|��|\\u0002�|���|\\u0003�����\\u0001,��\\u0001,d�d�dd\\u0003 �\\f|��|\\u0001�|��\\u0018�D\\u0002X��dd\\u0001,dd�\\f\\u0001�d�pd\\u0000\\u0000\\u0000\\u0000\\u0006��\\u0000\\u0000\\u0004�\\u0004L\\u0000\\u000f\\u0000\\u0013\\u0000\\u0019\\u0000\\u001f\\u0000#\\u0000'\\u0000\\u0000\\u0001\\u0011\\u0014\\u0006#!\\\"&5\\u0011463!2\\u0016\\u0007!\\u0011!\\u00015#\\u0011!\\u0011\\u00013\\u0011#\\u00153\\u0001#53\\u001335#\\u0004��|�D|��|\\u0002�|���|\\u0003��Dd\\u0001,\\u0001,d�d�qdd�dd\\u0003 �\\f|��|\\u0001�|��\\u0018�D\\u0001�d�\\f\\u0001��p\\u0001�d�����d\\u0000\\u0000\\u0000\\u0006��\\u0000\\u0000\\u0004�\\u0004L\\u0000\\u000f\\u0000\\u0013\\u0000\\u001d\\u0000#\\u0000'\\u0000+\\u0000\\u0000\\u0013!2\\u0016\\u0015\\u0011\\u0014\\u0006#!\\\"&5\\u001146\\u0005!\\u0011!\\u0001#5!\\u0011#\\u0015#53%#53\\u0011#%3\\u0015#!#53�\\u0002�|��|�D|��\\u0003��|\\u0003����\\u0001,cdc\\u0001�d�d��dd\\u0001�dd\\u0004L�|�\\f|��|\\u0001�|���D\\u0001�d��dd�d�\\fddd\\u0000\\u0000\\u0000\\u0003\\u0000\\u0004\\u0000\\u0004\\u0004�\\u0004�\\u0000\\u000b\\u0000\\u0013\\u0000\\u001d\\u0000\\u0000\\u0000 \\u0004\\u0012\\u0010\\u0002\\u0004 $\\u0002\\u0010\\u0012\\u0004 \\u0006\\u0010\\u0016 6\\u0010\\u0007!\\u0015!\\u0015!'57!\\u0001�\\u0001D\\u0001\\u0012�������\\u0002_����\\u0001V����\\u0001,��dd\\u0001,\\u0004�������\\u0001\\u0012\\u0001D\\u0001\\u0012\\u0016�����\\u0001VG�dd�d\\u0000\\u0000\\u0004\\u0000\\u0000\\u0000\\u0004\\u0004�\\u0004�\\u0000\\u000b\\u0000\\u0013\\u0000 \\u0000$\\u0000\\u0000\\u0000 \\u0004\\u0012\\u0010\\u0002\\u0004 $\\u0002\\u0010\\u0012\\u0004 \\u0006\\u0010\\u0016 6\\u0010\\u0007\\u0015#5#\\u00153\\u0015#\\u0015#\\u0011!\\u0013#53\\u0001�\\u0001D\\u0001\\u0012�������\\u0002_����\\u0001V��d���d\\u0001,ddd\\u0004�������\\u0001\\u0012\\u0001D\\u0001\\u0012\\u0016�����\\u0001VGddddd\\u0001��pd\\u0000\\u0000\\u0000\\u0000\\u0002����\\u0004�\\u0004A\\u0000\\u001a\\u0000!\\u0000\\u0000\\u000132654&#\\\"\\u0007.\\u0001#\\\"\\u0006\\u0015\\u0014\\u0017\\u000e\\u0001\\u0015\\u0014\\u0016;\\u0001\\u0011!\\u00033\\t\\u00013\\u00113\\u0003 �x��x.,,�n��\\u0002BUqO�\\u0001�d�������\\u0001,�zx�\\u000eawי\\u0019\\f\\u000ekEPr\\u0001,�p��\\u0001,\\u0001,\\u0000\\u0002����\\u0004�\\u0004A\\u0000\\u0018\\u0000\\u001f\\u0000\\u0000\\t\\u0001>\\u000154&#\\\"\\u0007.\\u0001#\\\"\\u0006\\u0015\\u0014\\u0017\\u000e\\u0001\\u0015\\u0014\\u0016;\\u0001\\u0001#\\u0011#\\t\\u0001#\\u0002X\\u0001�^y�x.,,�n��\\u0002BUqO\\b\\u0002\\u0002��\\u0001,\\u0001,�\\u0002��m\\u001a�dy�\\u000eawי\\u0019\\f\\u000ekEPr�p\\u0001,\\u0001,��\\u0000\\u0000\\u0001\\u0000d\\u0000\\u0000\\u0004L\\u0004m\\u0000\\u0010\\u0000\\u0000%!\\u00013\\u00013\\t\\u00013\\u00013\\u0001!\\u0015\\u0007!'\\u0002�\\u0001����������Ԫ�����\\u0001�K\\u0001^K�\\u0001,\\u0001,\\u0001M�����ԛ--\\u0000\\u0000\\u0000\\u0000\\u0001\\u0000y\\u0000\\u0000\\u00047\\u0004�\\u0000)\\u0000\\u0000%\\u0011\\u001632654'>\\u000154&'.\\u0001#\\\"\\u0006\\u0015\\u0014\\u0016\\u0015&#\\\"\\u0006\\u0015\\u0014\\u0016\\u0017\\u0006\\u0015\\u0014\\u0016327\\u0011\\u0007!\\u0002�.6Ji\\t2;{Y\\u001a�^t�\\u0002\\u000e\\tJi9/\\u0004iJ8,K\\u0001^-\\u00012\\u001eiJ\\u0018\\u001f f=Z�\\u0006Yq�t\\u0004\\u0010\\u0003\\u0002iJ5X\\u0015\\u0010\\u0016Ji\\u001e��-\\u0000\\u0000\\u0000\\u0003\\u0000\\u0000\\u0000d\\u0004�\\u0004�\\u0000\\u0017\\u0000\\u001b\\u0000%\\u0000\\u0000\\u0001!2\\u0016\\u0015\\u0011!5#\\u0015!\\u0011463!546;\\u00012\\u0016\\u0015\\u000535#\\u0001\\u0015\\u0014\\u0006#!\\\"&=\\u0001\\u0003 \\u0001,);�\\f��\\f;)\\u0001,;)�);����\\u0002�;)�\\u0018);\\u0003�;)�pdd\\u0001�);d);;)dd�D�);;)�\\u0000\\u0000\\u0011\\u0000\\u0000\\u0000\\u0000\\u0004L\\u0004�\\u0000\\u0011\\u0000\\u001b\\u0000\\u001f\\u0000#\\u0000'\\u0000+\\u0000/\\u00003\\u00007\\u0000;\\u0000?\\u0000C\\u0000G\\u0000K\\u0000O\\u0000S\\u0000W\\u0000\\u0000\\u000154&+\\u00015#\\u0015!5#\\u0015#\\\"\\u0006\\u001d\\u0002\\u0011\\u0014\\u00163!265\\u0011\\u00053\\u0015#73\\u0015#73\\u0015#73\\u0015#73\\u0015#\\u00053\\u0015#73\\u0015#73\\u0015#73\\u0015#73\\u0015#\\u00053\\u0015#73\\u0015#73\\u0015#73\\u0015#73\\u0015#\\u0004L\\u001d\\u0015�d�\\fd�\\u0015\\u001d\\u001d\\u0015\\u0003�\\u0015\\u001d�\\u0018dd�dd�dd�dd�dd��dd�dd�dd�dd�dd��dd�dd�dd�dd�dd\\u0003��\\u0015\\u001ddddd\\u001d\\u0015�d�\\u0012\\u0014\\u001e\\u001e\\u0014\\u0002��ddddddddddddddddddddddddddddd\\u0000\\u0000\\u0000\\u0001\\u0000\\u0000\\u0000\\u0000\\u0004�\\u0004�\\u0000\\u0018\\u0000\\u0000\\t\\u0001\\u0016\\u0014\\u0007\\u0006\\\"/\\u0001\\u0001\\u0011'\\u0007\\t\\u00017'!\\u0001'&4762\\u0003�\\u0001\\u001b\\u000f\\u000f\\u000e*\\u000e$������\\u0001/��\\u0001,\\u0001\\u000b#\\u000f\\u000f\\u000e*\\u0004���\\u000f*\\u000e\\u000f\\u000f#��������\\u0001|��\\u0001\\u0017$\\u000e*\\u000e\\u000f\\u0000\\u0000\\u0000\\u0000\\u0001��\\u0000;\\u0004�\\u0004�\\u0000O\\u0000\\u0000%\\u0017\\u0001>\\u0001'.\\u0001'&#\\\"\\u0007\\u0006\\u0007\\u0001\\u000e\\u0001\\u0017\\u001e\\u0001327>\\u0002767\\u0001>\\u0001'&'&#\\\"\\u0006\\u0007\\u0001\\u0007\\u0017\\u000167632\\u0017\\u0016\\u0007\\u0001\\u0006#\\\"&'&>\\u0002767\\u0001>\\u000232\\u0017\\u001e\\u0001\\u0007\\u0006\\u000f\\u0001\\u0003\\u0002\\u0006E\\u0002\\u0005C8\\u0011\\u0010fOESkZ(G�\\u0000D\\u001a0#vF?8!@)'(\\u0011\\u0001�#\\u0018\\u000f\\u001bZ\\u0014\\t.C\\\"�|\\u0007E\\u0001y\\u0014\\u0013\\u0017\\u001b&\\u000f\\u0010$��4I7Z\\t\\u0005\\u000f0$&\\u0018\\u0014\\u0001\\\\4=k6\\u0019\\u0017_v\\b\\u0007[��w<\\u0001�C�]W�$!7\\u0018G�\\u0000D�N9@\\u001c\\u00101*+,\\u0011\\u0001�#b/W\\u0011\\u0002\\\"\\\"�t\\u0007C\\u0001u\\u0016\\u0010\\u0017$'$��4B?#>@$$\\u0015\\u0014\\u0001\\\\475\\u0004\\u0011�be[��\\u0000\\u0000\\u0000\\u0004\\u0000\\u0000\\u0000d\\u0004�\\u0004L\\u0000\\u001d\\u0000!\\u0000)\\u00001\\u0000\\u0000%\\u00114&+\\u0001.\\u0004+\\u0001\\\"\\u000e\\u0002\\u000f\\u0001#\\\"\\u0006\\u0015\\u0011\\u0014\\u00163!26\\u0003#53\\u0006\\u0014\\u0006\\\"&462\\u00124&\\\"\\u0006\\u0014\\u00162\\u0004�;)�\\u0004\\u000f37S*�)R:.\\u000b\\f�);;)\\u0003�);�dd��Ȑ��\\u0006>X>>X�\\u0002X);\\b\\u001bE5+);;\\u0015\\u0014;)��);;\\u0002\\u001dd�Ȑ�Ȑ��X>>X>\\u0000\\u0000\\u0000\\u0002\\u0000\\u0000\\u0000\\u0000\\u0004L\\u0004�\\u0000\\u0019\\u0000#\\u0000\\u0000\\u000132\\u0016\\u0015\\u0011\\u0014\\u0006#!\\\"&5\\u001146;\\u00015463!2\\u0016\\u0015\\u0005!54&+\\u0001\\\"\\u0006\\u0015\\u0003�d);;)�|);;)dvR\\u0001,Rv�\\f\\u0001,\\u001d\\u0015�\\u0015\\u001d\\u0003 ;)��);;)\\u0002X);�RvvRȖ\\u0015\\u001d\\u001d\\u0015\\u0000\\u0000\\u0000\\u0002\\u0000J\\u0000\\u0000\\u0004f\\u0004�\\u0000'\\u0000/\\u0000\\u0000\\u000132\\u0016\\u0015\\u0014\\u0006\\u0007\\u000e\\u0002\\\"&/\\u0001.\\u0001546;\\u00017\\u0013>\\u00017'&6;\\u00012\\u0016\\u000f\\u0001\\u001e\\u0001\\u0017\\u0013\\u0000\\\"'\\u001e\\u0001267\\u0004&\\u0011\\u0014\\u001b\\u001a\\u0012\\u0016R���::\\u0012\\u001a\\u001b\\u0014\\u0011v?\\u000fzS\\u0012\\u0006\\u0012\\u0014^\\u0014\\u0012\\u0006\\u0012Sz\\u000f?��l1\\f8F8\\u000b\\u0001�\\u001d\\u0015\\u0014(\\u0007\\t\\u001c.)\\u0015\\u0014\\u0007)\\u0014\\u0015\\u001d�\\u0001GM~\\u0014 \\u0013\\u001a\\u0015\\u0013%\\u0013M���+\\u00061==1\\u0000\\u0000\\u0001\\u0000�\\u0000\\u0000\\u0004L\\u0004�\\u0000\\n\\u0000\\u00003\\t\\u0001\\u00114&#!\\\"\\u0006\\u0015�\\u0001�\\u0001�\\u001d\\u0015��\\u0015\\u001d\\u0001��E\\u0004~\\u0014\\u001e\\u001e\\u0014\\u0000\\u0000\\u0000\\u0001\\u0000o\\u0000\\f\\u0004D\\u0004�\\u0000H\\u0000\\u0000\\u0001\\u001e\\u0003\\u000e\\u0004\\u0007\\u0006.\\u00027\\u000e\\u0002\\u0014\\u0017\\u001e\\u0001\\u0017\\u0016>\\u00037>\\u0001'\\u001e\\u0001\\u0007\\u000e\\u0001\\u0007\\u000e\\u0004\\u001e\\u0001>\\u00017>\\u000476\\u0002'\\u0016\\u0017\\u0016'&'.\\u00027\\u000e\\u0004\\u0001�\\u0002\\f\\u0004\\b\\u0001\\u0001\\u000b\\u0010\\u001a\\u0012&:\\u0017\\u0007\\u000e4?\\u000f\\u0005\\tFF\\u001fB:8(\\u000f \\u000e\\u0014OV\\u0011\\u0005\\u001f\\u0016\\n\\t\\u000f\\u0003\\u0003\\b\\u000e\\u0019$\\u00189DkC@\\u000f&��\\u0016\\u0015'G\\u000f\\u0012OS\\u00053\\r*gJ.\\u0002�\\f;\\u001b4\\u001b(\\u0017\\u0019\\u0010\\u0004\\n.MV .nhB\\u001e8-\\u0015\\n%>=\\u001eB�'P�d!I,\\u0013\\u0014 \\u000f\\u0017\\b\\u000b\\u0001\\u0004\\u0006\\u0014\\u001c=CnC�\\u0001Sm,U�\\u0005\\u0002\\u0007!�ٕ\\b\\u001ffm�\\u0000\\u0001\\u0000\\u0000\\u0000\\u0002\\u0004�\\u0004�\\u0000\\u0014\\u0000\\u0000\\u00017\\u0016\\u0007\\u0006'\\u0001\\u0006\\\"/\\u0001&47\\u0001&676\\u0017\\u0005\\u0003��\\r�{���\\u000f+\\u000fo\\u000f\\u000f\\u0002X!N`����\\u0003\\n~�\\\\F/��\\u0010\\u0010n\\u000f+\\u0010\\u0002We�6\\\\e�\\u0000\\u0000\\u0000\\u0001\\u0000\\u0000\\u0000\\u0001\\u0000A\\u0002(��_\\u000f<�\\u0000\\u001f\\u0004�\\u0000\\u0000\\u0000\\u0000����\\u0000\\u0000\\u0000\\u0000�����:��\\u0005�\\u0005\\u0018\\u0000\\u0000\\u0000\\b\\u0000\\u0002\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0001\\u0000\\u0000\\u0005���\\u0000\\u0000\\u0005\\u0018�:��\\u0005�\\u0000\\u0001\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000�\\u0001�\\u0000(\\u0004�\\u0000\\u0000\\u0004�\\u0000\\u0000\\u0004�\\u0000\\u0000\\u0004�\\u0000d\\u0004�\\u0000\\u0000\\u0004�\\u0000\\u0000\\u0002�\\u0000\\u0000\\u0005\\u0018\\u0000\\u0000\\u0002�\\u0000\\u0000\\u0005\\u0018\\u0000\\u0000\\u0001�\\u0000\\u0000\\u0001F\\u0000\\u0000\\u0000�\\u0000\\u0000\\u0000�\\u0000\\u0000\\u0000�\\u0000\\u0000\\u0001\\u0004\\u0000\\u0000\\u0000H\\u0000\\u0000\\u0001\\u0004\\u0000\\u0000\\u0001F\\u0000\\u0000\\u0004�\\u0000d\\u0004�\\u0000�\\u0004���\\u0004�\\u0000\\u0000\\u0004���\\u0001�\\u0000\\u0000\\u0004�\\u0000\\u0000\\u0004�\\u0000\\u000e\\u0004�\\u0000\\u0017\\u0004�\\u0000d\\u0004���\\u0004���\\u0004�\\u0000\\u0000\\u0004�\\u0000\\u0000\\u0004�\\u0000\\u0000\\u0004�\\u0000\\u0000\\u0004�\\u0000\\u0000\\u0004�\\u0000\\u001d\\u0004�\\u0000j\\u0004�\\u0000\\u0017\\u0004�\\u0000\\u0017\\u0004�\\u0000\\u0017\\u0004�\\u0000d\\u0004�\\u0000\\u001a\\u0004�\\u0000d\\u0004�\\u0000\\u0001\\u0004�\\u0000d\\u0004�\\u0000\\u0004\\u0004���\\u0004�\\u0000\\u0000\\u0004�\\u0000\\u0001\\u0004�\\u0000\\u0004\\u0004�\\u0000\\u0000\\u0004�\\u0000\\u0004\\u0004�\\u0000\\u0017\\u0004�\\u0000\\u0017\\u0004�\\u0000d\\u0004�\\u0000d\\u0004�\\u0000\\u0000\\u0004�\\u0000\\u0000\\u0004�\\u0000\\u0000\\u0004�\\u0000\\u0000\\u0004�\\u0000\\u0000\\u0004�\\u0000\\u0000\\u0004�\\u0000\\u0001\\u0004�\\u0000\\u0002\\u0004�\\u0000d\\u0004�\\u0000\\u0000\\u0004�\\u00005\\u0004�\\u0000d\\u0004�\\u0000�\\u0004���\\u0004�\\u0000!\\u0004�\\u0000\\u0000\\u0004�\\u0000\\u0000\\u0004�\\u0000\\u0000\\u0004�\\u0000\\u0000\\u0004�\\u0000\\u0000\\u0004���\\u0004�\\u0000\\u0001\\u0004�\\u0000\\u0000\\u0004�\\u0000\\u0000\\u0004�\\u0000�\\u0004�\\u0000\\u0001\\u0004�\\u0000u\\u0004�\\u0000\\u0000\\u0004�\\u0000\\u0000\\u0004�\\u0000\\u0000\\u0004�\\u0000\\u0000\\u0004�\\u0000�\\u0004�\\u0000\\u0000\\u0004�\\u0000�\\u0004�\\u0000�\\u0004�\\u0000�\\u0004�\\u0000�\\u0004�\\u0000\\u0000\\u0004�\\u0000\\u0000\\u0004�\\u0001,\\u0004�\\u0000d\\u0004�\\u0000�\\u0004�\\u0001\\u0010\\u0004�\\u0000\\u0003\\u0004�\\u0000\\u0003\\u0004�\\u0000\\u0003\\u0004�\\u0000\\u0003\\u0004�\\u0000\\u0003\\u0004�\\u0000\\u0003\\u0004�\\u0000\\u0000\\u0004�\\u0000\\u0004\\u0004�\\u0000\\u0004\\u0004�\\u0000\\u0004\\u0004�\\u0000\\u0000\\u0004�\\u0000\\u0000\\u0004�\\u0000�\\u0004�\\u0000h\\u0004�\\u0000\\u0000\\u0004�\\u0000\\u0000\\u0004�\\u0000\\\"\\u0004�\\u0000\\u0017\\u0004�\\u0000\\u0000\\u0004�\\u0000\\u0000\\u0004���\\u0004���\\u0004���\\u0004�\\u0000d\\u0004�\\u0000\\u0000\\u0004�\\u0000\\u0000\\u0004�\\u0000d\\u0004���\\u0004�\\u0000F\\u0004��:\\u0004�\\u0000\\u0012\\u0004�\\u0000\\u0000\\u0004�\\u0000\\u0001\\u0004�\\u0001.\\u0004�\\u0000\\u0000\\u0004�\\u0000\\u0000\\u0004���\\u0004�\\u0000\\u0015\\u0004�\\u0000\\u0000\\u0004�\\u0000\\u0000\\u0004�\\u0000\\b\\u0004���\\u0004�\\u0000a\\u0004�\\u0000\\u0001\\u0004�\\u0000\\u0005\\u0004�\\u0000\\u0000\\u0004�\\u0000\\u0005\\u0004�\\u0000\\u0005\\u0004�\\u0000\\u0005\\u0004�\\u0000\\u0000\\u0004�\\u0000d\\u0000\\u0000\\u0000\\u0000\\u0000P\\u00009\\u0000�\\u0001'\\u0000d\\u0000\\u0002\\u0000\\u0002\\u0000\\u0002\\u0000\\u0002\\u0000\\u0002\\u0000\\u0002\\u0000\\u0002\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000�\\u0000\\u0000\\u0000\\u0000\\u0000\\u0004\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0017\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000d\\u0000d\\u0000\\u0000\\u0000\\u0010\\u0000\\u0000\\u0000d\\u0000d����������������\\u0000\\u0004\\u0000\\u0000����\\u0000d\\u0000y\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000��\\u0000\\u0000\\u0000\\u0000\\u0000J\\u0000�\\u0000o\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000*\\u0000*\\u0000*\\u0000*\\u0000V\\u0000p\\u0000p\\u0000p\\u0000p\\u0000p\\u0000p\\u0000p\\u0000p\\u0000p\\u0000p\\u0000p\\u0000p\\u0000p\\u0000p\\u0000p\\u0000�\\u0000�\\u0000�\\u0001\\u001a\\u0001B\\u0001J\\u0001b\\u0001�\\u0001�\\u0001�\\u0002\\u001c\\u0002N\\u0002n\\u0002�\\u0003&\\u0003�\\u0004f\\u0004z\\u0004�\\u0004�\\u0005\\u001c\\u0005^\\u0005�\\u0005�\\u0006P\\u0006j\\u0006�\\u0006�\\u0006�\\u0007\\u0006\\u0007<\\u0007r\\u0007�\\u0007�\\u0007�\\b0\\bz\\b�\\t\\u0000\\t&\\tF\\t|\\t�\\n8\\n^\\n�\\n�\\n�\\u000b.\\u000bx\\u000b�\\u000b�\\f\\u001a\\fv\\f�\\r.\\r�\\u000e2\\u000e�\\u000f\\b\\u000f.\\u000ff\\u000f�\\u000f�\\u000f�\\u0010>\\u0010�\\u0010�\\u0010�\\u0011\\u000e\\u00118\\u0011N\\u0011\\\\\\u0011�\\u0011�\\u0011�\\u0011�\\u0012\\u000e\\u00120\\u0012D\\u0012\\\\\\u0012�\\u0012�\\u0012�\\u0013\\n\\u0013b\\u0013�\\u0013�\\u0014\\u001a\\u0014P\\u0014�\\u0014�\\u0014�\\u0014�\\u0014�\\u0014�\\u0015\\u001c\\u0015>\\u0015x\\u0015�\\u0016&\\u0016�\\u0016�\\u0017$\\u0017f\\u0017�\\u0017�\\u0018\\u0000\\u0018\\u0014\\u0018(\\u0018P\\u0018�\\u0018�\\u0018�\\u0018�\\u0019\\n\\u0019B\\u0019�\\u0019�\\u001a\\u0004\\u001aL\\u001a�\\u001b\\n\\u001bd\\u001b�\\u001b�\\u001c\\u0018\\u001cD\\u001cr\\u001dX\\u001d�\\u001d�\\u001e\\u0002\\u001ex\\u001e�\\u001f\\u001c\\u001fN\\u001f� \\u0016 4 l � � �!$!R!�!�!�\\\"0\\\"^\\\"�\\\"�#\\b#@#j#�#�#�$\\u001c$6$`$�$�%\\b%<%f%�%�&2&�&�'\\u001c'D'x'�(\\u0000(:(l(�(�)6)|)�)�*.*d*�*�+\\u0002+�+�,2,|,�,�-\\u0016-�-�\\u0000\\u0001\\u0000\\u0000\\u0000�\\u0000�\\u0000\\u0011\\u0000\\u0000\\u0000\\u0000\\u0000\\u0002\\u0000\\u0000\\u0000\\u0001\\u0000\\u0001\\u0000\\u0000\\u0000@\\u0000.\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u000f\\u0000�\\u0000\\u0001\\u0000\\u0000\\u0000\\u0000\\u0000\\u0013\\u0000\\u0012\\u0000\\u0000\\u0000\\u0003\\u0000\\u0001\\u0004\\t\\u0000\\u0000\\u0000j\\u0000\\u0012\\u0000\\u0003\\u0000\\u0001\\u0004\\t\\u0000\\u0001\\u0000(\\u0000|\\u0000\\u0003\\u0000\\u0001\\u0004\\t\\u0000\\u0002\\u0000\\u000e\\u0000�\\u0000\\u0003\\u0000\\u0001\\u0004\\t\\u0000\\u0003\\u0000L\\u0000�\\u0000\\u0003\\u0000\\u0001\\u0004\\t\\u0000\\u0004\\u00008\\u0000�\\u0000\\u0003\\u0000\\u0001\\u0004\\t\\u0000\\u0005\\u0000x\\u00016\\u0000\\u0003\\u0000\\u0001\\u0004\\t\\u0000\\u0006\\u00006\\u0001�\\u0000\\u0003\\u0000\\u0001\\u0004\\t\\u0000\\b\\u0000\\u0016\\u0001�\\u0000\\u0003\\u0000\\u0001\\u0004\\t\\u0000\\t\\u0000\\u0016\\u0001�\\u0000\\u0003\\u0000\\u0001\\u0004\\t\\u0000\\u000b\\u0000$\\u0002\\u0010\\u0000\\u0003\\u0000\\u0001\\u0004\\t\\u0000\\f\\u0000$\\u00024\\u0000\\u0003\\u0000\\u0001\\u0004\\t\\u0000\\u0013\\u0000$\\u0002X\\u0000\\u0003\\u0000\\u0001\\u0004\\t\\u0000�\\u0000\\u0016\\u0002|\\u0000\\u0003\\u0000\\u0001\\u0004\\t\\u0000�\\u00000\\u0002�www.glyphicons.com\\u0000C\\u0000o\\u0000p\\u0000y\\u0000r\\u0000i\\u0000g\\u0000h\\u0000t\\u0000 \\u0000�\\u0000 \\u00002\\u00000\\u00001\\u00003\\u0000 \\u0000b\\u0000y\\u0000 \\u0000J\\u0000a\\u0000n\\u0000 \\u0000K\\u0000o\\u0000v\\u0000a\\u0000r\\u0000i\\u0000k\\u0000.\\u0000 \\u0000A\\u0000l\\u0000l\\u0000 \\u0000r\\u0000i\\u0000g\\u0000h\\u0000t\\u0000s\\u0000 \\u0000r\\u0000e\\u0000s\\u0000e\\u0000r\\u0000v\\u0000e\\u0000d\\u0000.\\u0000G\\u0000L\\u0000Y\\u0000P\\u0000H\\u0000I\\u0000C\\u0000O\\u0000N\\u0000S\\u0000 \\u0000H\\u0000a\\u0000l\\u0000f\\u0000l\\u0000i\\u0000n\\u0000g\\u0000s\\u0000R\\u0000e\\u0000g\\u0000u\\u0000l\\u0000a\\u0000r\\u00001\\u0000.\\u00000\\u00000\\u00001\\u0000;\\u0000U\\u0000K\\u0000W\\u0000N\\u0000;\\u0000G\\u0000L\\u0000Y\\u0000P\\u0000H\\u0000I\\u0000C\\u0000O\\u0000N\\u0000S\\u0000H\\u0000a\\u0000l\\u0000f\\u0000l\\u0000i\\u0000n\\u0000g\\u0000s\\u0000-\\u0000R\\u0000e\\u0000g\\u0000u\\u0000l\\u0000a\\u0000r\\u0000G\\u0000L\\u0000Y\\u0000P\\u0000H\\u0000I\\u0000C\\u0000O\\u0000N\\u0000S\\u0000 \\u0000H\\u0000a\\u0000l\\u0000f\\u0000l\\u0000i\\u0000n\\u0000g\\u0000s\\u0000 \\u0000R\\u0000e\\u0000g\\u0000u\\u0000l\\u0000a\\u0000r\\u0000V\\u0000e\\u0000r\\u0000s\\u0000i\\u0000o\\u0000n\\u0000 \\u00001\\u0000.\\u00000\\u00000\\u00001\\u0000;\\u0000P\\u0000S\\u0000 \\u00000\\u00000\\u00001\\u0000.\\u00000\\u00000\\u00001\\u0000;\\u0000h\\u0000o\\u0000t\\u0000c\\u0000o\\u0000n\\u0000v\\u0000 \\u00001\\u0000.\\u00000\\u0000.\\u00007\\u00000\\u0000;\\u0000m\\u0000a\\u0000k\\u0000e\\u0000o\\u0000t\\u0000f\\u0000.\\u0000l\\u0000i\\u0000b\\u00002\\u0000.\\u00005\\u0000.\\u00005\\u00008\\u00003\\u00002\\u00009\\u0000G\\u0000L\\u0000Y\\u0000P\\u0000H\\u0000I\\u0000C\\u0000O\\u0000N\\u0000S\\u0000H\\u0000a\\u0000l\\u0000f\\u0000l\\u0000i\\u0000n\\u0000g\\u0000s\\u0000-\\u0000R\\u0000e\\u0000g\\u0000u\\u0000l\\u0000a\\u0000r\\u0000J\\u0000a\\u0000n\\u0000 \\u0000K\\u0000o\\u0000v\\u0000a\\u0000r\\u0000i\\u0000k\\u0000J\\u0000a\\u0000n\\u0000 \\u0000K\\u0000o\\u0000v\\u0000a\\u0000r\\u0000i\\u0000k\\u0000w\\u0000w\\u0000w\\u0000.\\u0000g\\u0000l\\u0000y\\u0000p\\u0000h\\u0000i\\u0000c\\u0000o\\u0000n\\u0000s\\u0000.\\u0000c\\u0000o\\u0000m\\u0000w\\u0000w\\u0000w\\u0000.\\u0000g\\u0000l\\u0000y\\u0000p\\u0000h\\u0000i\\u0000c\\u0000o\\u0000n\\u0000s\\u0000.\\u0000c\\u0000o\\u0000m\\u0000w\\u0000w\\u0000w\\u0000.\\u0000g\\u0000l\\u0000y\\u0000p\\u0000h\\u0000i\\u0000c\\u0000o\\u0000n\\u0000s\\u0000.\\u0000c\\u0000o\\u0000m\\u0000W\\u0000e\\u0000b\\u0000f\\u0000o\\u0000n\\u0000t\\u0000 \\u00001\\u0000.\\u00000\\u0000M\\u0000o\\u0000n\\u0000 \\u0000J\\u0000u\\u0000l\\u0000 \\u0000 \\u00001\\u0000 \\u00000\\u00005\\u0000:\\u00002\\u00006\\u0000:\\u00000\\u00000\\u0000 \\u00002\\u00000\\u00001\\u00003\\u0000\\u0002\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000��\\u00002\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000�\\u0000\\u0000\\u0001\\u0002\\u0001\\u0003\\u0000\\u0003\\u0000\\r\\u0000\\u000e\\u0001\\u0004\\u0001\\u0005\\u0001\\u0006\\u0001\\u0007\\u0001\\b\\u0001\\t\\u0001\\n\\u0001\\u000b\\u0001\\f\\u0001\\r\\u0001\\u000e\\u0001\\u000f\\u0001\\u0010\\u0001\\u0011\\u0001\\u0012\\u0000�\\u0001\\u0013\\u0001\\u0014\\u0001\\u0015\\u0001\\u0016\\u0001\\u0017\\u0001\\u0018\\u0001\\u0019\\u0001\\u001a\\u0001\\u001b\\u0001\\u001c\\u0001\\u001d\\u0001\\u001e\\u0001\\u001f\\u0001 \\u0001!\\u0001\\\"\\u0001#\\u0001$\\u0001%\\u0001&\\u0001'\\u0001(\\u0001)\\u0001*\\u0001+\\u0001,\\u0001-\\u0001.\\u0001/\\u00010\\u00011\\u00012\\u00013\\u00014\\u00015\\u00016\\u00017\\u00018\\u00019\\u0001:\\u0001;\\u0001<\\u0001=\\u0001>\\u0001?\\u0001@\\u0001A\\u0001B\\u0001C\\u0001D\\u0001E\\u0001F\\u0001G\\u0001H\\u0001I\\u0001J\\u0001K\\u0001L\\u0001M\\u0001N\\u0001O\\u0001P\\u0001Q\\u0001R\\u0001S\\u0001T\\u0001U\\u0001V\\u0001W\\u0001X\\u0001Y\\u0001Z\\u0001[\\u0001\\\\\\u0001]\\u0001^\\u0001_\\u0001`\\u0001a\\u0001b\\u0001c\\u0001d\\u0001e\\u0001f\\u0001g\\u0001h\\u0001i\\u0001j\\u0001k\\u0001l\\u0001m\\u0001n\\u0001o\\u0001p\\u0001q\\u0001r\\u0001s\\u0001t\\u0001u\\u0001v\\u0001w\\u0001x\\u0001y\\u0001z\\u0001{\\u0001|\\u0001}\\u0001~\\u0001\\u0001�\\u0001�\\u0001�\\u0001�\\u0001�\\u0001�\\u0001�\\u0001�\\u0001�\\u0001�\\u0001�\\u0001�\\u0001�\\u0001�\\u0001�\\u0001�\\u0001�\\u0001�\\u0001�\\u0001�\\u0001�\\u0001�\\u0001�\\u0001�\\u0001�\\u0001�\\u0001�\\u0001�\\u0001�\\u0001�\\u0001�\\u0001�\\u0001�\\u0001�\\u0001�\\u0001�\\u0001�\\u0001�\\u0001�\\u0001�\\u0001�\\u0001�\\u0001�\\u0001�\\u0001�\\u0001�\\u0001�\\u0001�\\u0001�\\u0001�\\u0001�\\u0001�\\u0001�\\u0001�\\u0001�\\u0001�\\u0001�\\u0001�\\u0001�\\u0001�\\u0001�\\u0001�\\u0001�\\u0001�\\u0001�\\u0001�\\u0001�\\u0001�\\u0001�\\u0001�\\u0001�\\u0001�\\u0001�\\u0001�\\u0001�\\u0001�\\u0001�\\u0001�\\u0001�\\u0001�\\u0001�\\u0001�\\u0001�\\u0001�\\u0001�\\u0001�\\u0001�\\u0001�\\u0006glyph1\\u0006glyph2\\u0007uni00A0\\u0007uni2000\\u0007uni2001\\u0007uni2002\\u0007uni2003\\u0007uni2004\\u0007uni2005\\u0007uni2006\\u0007uni2007\\u0007uni2008\\u0007uni2009\\u0007uni200A\\u0007uni202F\\u0007uni205F\\u0004Euro\\u0007uni2601\\u0007uni2709\\u0007uni270F\\u0007uniE000\\u0007uniE001\\u0007uniE002\\u0007uniE003\\u0007uniE005\\u0007uniE006\\u0007uniE007\\u0007uniE008\\u0007uniE009\\u0007uniE010\\u0007uniE011\\u0007uniE012\\u0007uniE013\\u0007uniE014\\u0007uniE015\\u0007uniE016\\u0007uniE017\\u0007uniE018\\u0007uniE019\\u0007uniE020\\u0007uniE021\\u0007uniE022\\u0007uniE023\\u0007uniE024\\u0007uniE025\\u0007uniE026\\u0007uniE027\\u0007uniE028\\u0007uniE029\\u0007uniE030\\u0007uniE031\\u0007uniE032\\u0007uniE034\\u0007uniE035\\u0007uniE036\\u0007uniE037\\u0007uniE038\\u0007uniE039\\u0007uniE040\\u0007uniE041\\u0007uniE042\\u0007uniE043\\u0007uniE045\\u0007uniE047\\u0007uniE048\\u0007uniE049\\u0007uniE050\\u0007uniE051\\u0007uniE052\\u0007uniE053\\u0007uniE054\\u0007uniE055\\u0007uniE056\\u0007uniE057\\u0007uniE058\\u0007uniE059\\u0007uniE060\\u0007uniE062\\u0007uniE063\\u0007uniE064\\u0007uniE065\\u0007uniE066\\u0007uniE067\\u0007uniE068\\u0007uniE069\\u0007uniE070\\u0007uniE071\\u0007uniE072\\u0007uniE073\\u0007uniE074\\u0007uniE075\\u0007uniE076\\u0007uniE077\\u0007uniE078\\u0007uniE079\\u0007uniE080\\u0007uniE081\\u0007uniE082\\u0007uniE083\\u0007uniE084\\u0007uniE085\\u0007uniE086\\u0007uniE087\\u0007uniE088\\u0007uniE089\\u0007uniE090\\u0007uniE091\\u0007uniE092\\u0007uniE093\\u0007uniE094\\u0007uniE095\\u0007uniE096\\u0007uniE097\\u0007uniE101\\u0007uniE102\\u0007uniE103\\u0007uniE105\\u0007uniE106\\u0007uniE107\\u0007uniE108\\u0007uniE110\\u0007uniE111\\u0007uniE112\\u0007uniE113\\u0007uniE114\\u0007uniE115\\u0007uniE116\\u0007uniE117\\u0007uniE118\\u0007uniE119\\u0007uniE120\\u0007uniE121\\u0007uniE122\\u0007uniE124\\u0007uniE125\\u0007uniE126\\u0007uniE127\\u0007uniE128\\u0007uniE129\\u0007uniE130\\u0007uniE131\\u0007uniE132\\u0007uniE133\\u0007uniE134\\u0007uniE135\\u0007uniE137\\u0007uniE138\\u0007uniE140\\u0007uniE141\\u0007uniE143\\u0007uniE144\\u0007uniE145\\u0007uniE148\\u0007uniE149\\u0007uniE150\\u0007uniE151\\u0007uniE152\\u0007uniE153\\u0007uniE154\\u0007uniE155\\u0007uniE156\\u0007uniE157\\u0007uniE158\\u0007uniE159\\u0007uniE160\\u0007uniE161\\u0007uniE162\\u0007uniE163\\u0007uniE164\\u0007uniE165\\u0007uniE166\\u0007uniE167\\u0007uniE168\\u0007uniE169\\u0007uniE170\\u0007uniE171\\u0007uniE172\\u0007uniE173\\u0007uniE174\\u0007uniE175\\u0007uniE176\\u0007uniE177\\u0007uniE178\\u0007uniE179\\u0007uniE180\\u0007uniE181\\u0007uniE182\\u0007uniE183\\u0007uniE184\\u0007uniE185\\u0007uniE186\\u0007uniE187\\u0007uniE188\\u0007uniE189\\u0007uniE190\\u0007uniE191\\u0007uniE192\\u0007uniE193\\u0007uniE194\\u0007uniE195\\u0007uniE197\\u0007uniE198\\u0007uniE199\\u0007uniE200\\u0006u1F4BC\\u0006u1F4C5\\u0006u1F4CC\\u0006u1F4CE\\u0006u1F4F7\\u0006u1F512\\u0006u1F514\\u0006u1F516\\u0006u1F525\\u0006u1F527\\u0000\\u0000\\u0000\\u0000\\u0001Q�K(\\u0000\\u0000\",\"glyphicons-halflings-regular.woff\":\"wOFF\\u0000\\u0001\\u0000\\u0000\\u0000\\u0000@@\\u0000\\u000f\\u0000\\u0000\\u0000\\u0000sH\\u0000\\u0001\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000FFTM\\u0000\\u0000\\u0001X\\u0000\\u0000\\u0000\\u001c\\u0000\\u0000\\u0000\\u001ch+�\\rGDEF\\u0000\\u0000\\u0001t\\u0000\\u0000\\u0000\\u001e\\u0000\\u0000\\u0000 \\u0001\\b\\u0000\\u0004OS/2\\u0000\\u0000\\u0001�\\u0000\\u0000\\u0000F\\u0000\\u0000\\u0000`i\\u001el�cmap\\u0000\\u0000\\u0001�\\u0000\\u0000\\u0002~\\u0000\\u0000\\u0005.�/V�cvt \\u0000\\u0000\\u0004\\\\\\u0000\\u0000\\u0000\\u0004\\u0000\\u0000\\u0000\\u0004\\u0000(\\u0002�gasp\\u0000\\u0000\\u0004`\\u0000\\u0000\\u0000\\b\\u0000\\u0000\\u0000\\b��\\u0000\\u0003glyf\\u0000\\u0000\\u0004h\\u0000\\u00003�\\u0000\\u0000[X\\u0001��\\u0016head\\u0000\\u00008,\\u0000\\u0000\\u00004\\u0000\\u0000\\u00006\\u00008=�hhea\\u0000\\u00008`\\u0000\\u0000\\u0000\\u001f\\u0000\\u0000\\u0000$\\n�\\u0004xhmtx\\u0000\\u00008�\\u0000\\u0000\\u0001\\u0013\\u0000\\u0000\\u0002��\\u000e\\u0012ploca\\u0000\\u00009�\\u0000\\u0000\\u0001�\\u0000\\u0000\\u0001����@maxp\\u0000\\u0000;@\\u0000\\u0000\\u0000 \\u0000\\u0000\\u0000 \\u0001.\\u0000�name\\u0000\\u0000;`\\u0000\\u0000\\u0001�\\u0000\\u0000\\u0003|Ԗ��post\\u0000\\u0000<�\\u0000\\u0000\\u0003R\\u0000\\u0000\\by�cQwwebf\\u0000\\u0000@8\\u0000\\u0000\\u0000\\u0006\\u0000\\u0000\\u0000\\u0006K)Q�\\u0000\\u0000\\u0000\\u0001\\u0000\\u0000\\u0000\\u0000�=��\\u0000\\u0000\\u0000\\u0000��\\u0017�\\u0000\\u0000\\u0000\\u0000����x�c`d``�\\u0003b\\t\\u0006\\u0010`b`\\u0004�[@�\\u0002�1\\u0000\\u0000\\r�\\u0001\\r\\u0000\\u0000x�c`fid��������t���!\\nB3.a0b�\\u0001�\\u0003�\\u0010�\\t�\\u001d�\\u001d�������?k��/\\f2�S\\u0018x�HJ\\u0014\\u0018\\u0018\\u0001A�\\u000b�\\u0000\\u0000x�͓?LSQ\\u0018�ϣ-PB���t�{� \\u00150�\\u0010�0\\u0018K*�N��\\u0011\\\\h�A\\u00194\\fj����`\\u001cX\\u00101\\u001aYM�t�Ѹ����\\u0000�\\u0007NN�h����n]�\\\\L|ɯ��n��;}�+�\\u0018�\\b9J���\\u001e\\u0002&D�p5\\b�#��h0��q�xM\\u000b,:�b�l�����d[��g\\u001a$\\\"qII��Ƞ�eX\\n2!E����˒F�VS��v��\\u0001\\u001d�a-���hI�uQ��P.�\\u000e\\u0016\\u001d�\\u0019{v��$!V��Wr�yDƸ���ʜ,h�1M��V�֬�4��:�E��9]�%�sy��^������Ǜ\\u00177\\\"�Mk���6e[l���j\\u001b3e���4�f�|3_�\\u0017�a��+撹`�M�L�qs֜1'M���1�5��^���O�z�Qu�r�\\u0017>\\u0019�{_\\u001d�ӽ(�R���\\u0015�/��]\\u001e$�I\\u000f�ӫ\\u001e4\\u0002��\\u0007M@[�A3��{p�n���C(q�Oќ\\u001dq�9H'\\bא�YB��LI7�a��{� 3�\\u001c�3\\u001f��=์�\\u0002�\\tz�L0���\\u0007��)2�|��LJ��\\u001c=G����\\u000bd��2��M�:_��Yk�y������ivVv�\\r����7i�W�칟f�\\u0000�m��u��\\u000e����ߥG���fu�\\u001f�쮮�C���u~D����Oiw�E��4��2�K`\\u000b\\u001epھ?\\t\\u0001���B����\\u0010�\\u001d�*\\u0004xO��\\u0000\\u001f\\u0010�H�\\u0000\\u001f��\\u0010�\\u0013�\\u001c\\u0002|�\\u000f�\\u0000kt&\\u0004X�����gԃ*7�{�5�c��h\\f��Q�w��o��\\r�\\u0014�H\\u0000\\u0000\\u0000(\\u0002�\\u0000\\u0000\\u0000\\u0001��\\u0000\\u0002xڵ|\\t`Tչ�=w��Y2���m&���L\\u0002�\\u0004f23@H�a\\u0013\\b�\\u0016Q\\u0011pD\\u0001��\\u001a@\\u0010\\u0015qm� \\u0005�`��\\n\\u0005�HQ�`_��^Զj�U�����V���k+d.���;�L\\u0016���{���9�;���wη�˰L%Ð[�2�cD&�\\u001ca�G\\u001c\\u0015y�|�9���#�r,\\\\2�q�X��GE\\u0003�\\u001cq����Cq\\u0004b\\u000e%\\u0019����_���\\u000f*��\\u0019¤�\\u0014��712�Vd1��;�PR�+����9����MZ��M/���҄�\\\\\\u0012�\\\\����c�\\u001f�\\u0003�kF����\\u0000�E��ZH\\u001b\\tï-{��P\\\\\\u0004���a&����X����\\f��_\\u001e���?\\u0019�I�!�LĢ�G��DX��\\u0015\\u0015Q1H\\nW�u\\u0018\\u0007\\u000f\\u001b\\u0015��\\u0013�b�K\\u0017,���U\\u0015��wS+�3��\\u0002\\u0013�<�i�\\b����\\t��a�\\u001b\\\\dmJ�0�\\u001d�;\\u001a\\u0007ڊ\\u0006ω\\u001fZr�7\\\"\\u0007W����}s7�t��d��Bwxn}*�\\u0000�T��7�ǁ��O|S�:n#{\\\\�`��OI�?�_�x\\u0018ƥD\\u0013񚠿\\\\�\\u0010�Ar�V\\\"�=G�OV\\u001f8�:\\u0012\\u000e?���ﰍ�V����V?k]���;\\u000b-֥c���d�_�o\\u0007ڱ���1��\\u001a\\t\\u0010 \\u001f\\u0011�J��/Me���\\u001d|�֑\\\"m���6�oJ�f��mN�'�\\u0014�Ue\\u0018��g�?�_�_b�\\u0000�\\u000e����j\\u0012,�\\u0011#\\t\\u0011.\\u0010�'ݘ���Va��\\u0015���N?��I���\\\\�\\u001f����_й�>�����k\\\\���dǹ�o\\u0007�L@��o\\u001c�\\\"{��;? a�\\u0002\\u0018ZR�\\u0014\\u001bd��3X���\\u0001_\\u001ca���\\u0011\\u0014�D��d=�;j��\\u0000t��2��s#'L��t<2e�\\f�)m7Y����)W5sϤ�a��V&�U���$��d�^�\\\\��\\u0014GA���UE��\\u0001�<��|�c���N��\\u00143��x�6b(\\u000f\\u0011�) G\\u0019#�\\u0019��,a\\u000f�q[IX\\u0014������U�U�\\u000f�\\u0004X����\\u0013�����'\\u0004h\\r��D��'�e�\\u001f��ģ����P��o3�\\u001f�\\u0014B��Y\\u001f+���\\u0018��5pC�G\\u0006�]}gsbԚ�����m\\\\3j��U��pϏ��\\u001f4�u��5��st֬��ܻf���\\u0019���@Z����q�v����\\u0000T����⊹\\u0014����ڽچǴu䷏���w:],k�\\u001a�K;O��\\u0014��J�\\b�@7\\f7�g.�P�\\u001f\\u0012����\\u0007�6{��\\u001fM��_?\\u001d�c��>������~���_�n#9|�\\u0002>\\u00006 ��`\\u001d�ID=^�6�%�Y�\\u0016hh�g{C`˖-�����u������\\u0014�8}���mf�\\u0006pd\\u0018�R�τ��L5\\u0013C~Q\\u001c�_�\\u0005`���,�u��\\u000f�I�gخ\\n�w<��m���u�\\u0014���������\\u000f��K��&`[�E��?�\\tg.�\\u001c��7\\u001b�X�4 v�O�<\\b���)Q����K�/x%�E�z%�&y��ܻ��+��E�׹Ͻ�mW(\\u0000ԍ}���������l��Hn�@��_-\\u0001L�����~�+��=\\u001cH[�ם\\u001f���ዲW�\\u001e�k�'�\\fc���\\\\��Kq�\\r���\\u0001�\\u0004�\\r0�<P�\\b�.���s(�m�J��x�\\u001e\\u0007����K��Qz[��{_L\\u000f]�x�r�S~\\u0000H8&\\u0000�($�\\u001fsю�7�Q�����\\u001dz�%�\\u0012~,?\\u0016��\\u0000�,#I\\u001a�l$�J��v��\\u0014�\\u0003)��Β�%=o;�\\n��\\u001e2 Կ\\u0014��\\f0�\\u00031�/���x,\\u001e��DHo�\\u0005�\\t�\\u001f�\\u000f���d8�R����ϰN�\\u001b�'(\\u001e�_,�DXCs�_���D\\u001a\\u000bw��[�\\u0007�䑁����D$\\u0010J'���oU\\u0015e #�;am��J\\n���K�C��d��\\u0004AŖG�x�3)Q]�\\f\\u0015\\u0018��WJ���!���kw���[��}s���.��\\u0017ױ���,�^{��V(�j�/���g����.^|n�Ju�\\u0014C����Zߙ��\\u0011#��\\u0000?�]U���\\u001f��\\u001b�Tr\\u0001�Q\\u00162EL1�����c����'\\u0016m`\\u0013\\rDN$C�\\u0004\\\\�k��`5I\\u0006Cb(\\b��r\\u001bk���A�E\\u0003\\\\J�R�SJD��\\u0004��\\u0019��4�\\u0005���\\u000bV�\\u0017W\\u0007\\r�j�����r\\u00056�uA�:������\\u0007�A�\\rz\\r!\\u001a\\u0016\\u001e��L�\\n���\\r��Yk\\u00017uЈ\\u0007�ACJ��_t���\\u000b��l~\\u00117-\\\\��\\u0010\\u001e���\\f\\n\\u001ab\\u0003�\\u0007�WO�\\n�:dk!7�z��Bu�\\u0010\\u001c\\\\�T\\u0005\\rC���i\\\\Q>ۺ������if�V�˗�v�\\r:��K\\u0012R�8#Y�fy\\\\���\\u0018W$A�\\n�Z���b�?n#q�lV���f��D\\\\�U$\\\\U�Be��X[�\\u001e\\r7:W�?��f���Vs�dKU��Vaa�\\u0007U#FT�H\\u001d���s\\u0015�\\u000b\\u0012�\\u001e�\\u0019\\f�����ᑊ�aL�6�\\u001a�NAy`�ٍ\\f\\u001dS�\\u0018��7���jչB\\u0011n�f�f5w\\u001eF\\u001c�o��\\u000eh�z��כ�(���x��\\u000f񇀯\\\\�{1e����e\\u0015���Ü�\\u0019%�$\\u0005x�\\u00052�8���>юk����ޠ\\u001d��32�3m!���\\u000fu�\\u0010'��|��\\u001f\\u0004%\\u001bt��\\f#�\\u0001Wʿ��)$������}����\\u001fɑ7����ɑ��h��b�+*�$\\f��\\u0005P�;�Ϻ���A2\\u0011��b\\u0004�\\u0016T>�_��U\\u0012V���]G�tYI\\u00174\\u000b`\\t\\u0014�>\\u0003�A�<\\u0002\\u0010d�\\u0007O�>V��5����f\\u0000\\u001c#�_x�\\r7�ɜXV;���d槚����\\u001d*��\\bO�}�\\u0017\\u001f@�����[�?}E?\\u0018�~�\\u0015\\t��\\u001d�ؕ��m���#-��2\\u000e���eY�(\\\\LV�1�+�\\u0019\\u0001\\u000e�`�r\\u000f��.P�$\\u001cU�\\u0005dD-����R������]b\\n���Y�D�qE���~�\\u000f�\\u0007�F�\\u000e>{�l��Ȯ�%�\\u0015nCYЎ\\u0016��8� \\u001a�n\\u001f\\u000b�,�s�E�\\u001b� >��1Ҷ��S��\\u0012�T�\\u0019VJXS�a�]��p�k7Ca�\\u0019\\u0005�� \\u001a�~0(��$؃�\\u0006&�1\\u0018y��E\\u0007{|[�C�]܁k��'������ʶM��\\u001c6{�V��[�\\u0019���\\f����\\u0019\\u0017p(\\u0007�*�l\\u0014��#��������B�\\u0018�j�R-�Bz�\\u0017]�2\\u000f�c�F\\u0015���܃�>P=���cb(/\\u001cV\\u0012�\\f�����z���^�vc�Cw�u�xh���K\\u0000\\u0003\\u0004<m����4f�f\\u001918_)\\u0016�P~���q��\\u0010�**\\r#,�QV\\u001a��SO�|${\\u001fp��\\u0015.HT��uϷ�������FX\\\"��M �?l���\\u001fX���Y��m��\\u0006�+|\\u0007ԇ���:��\\u0016�獕+߸�޽��`E�\\u001a\\u001es�\\u0019}n�|3w\\u000et&X+\\u000b�\\\"8��,��\\u0003�\\u0007\\\"\\r�\\u0010��Om\\u001a�)�Ǖi-0_T5�\\u0019��ŵPX�\\f,!�\\u0004�(�`>��Hۘۖ����1,�Б�<�X��c:\\u001d�/��\\u0001��\\u000b$\\u0013\\u0013H��%�\\f l�\\u0004\\u001c`�u��~a��f�!�]%�� h@�G\\u0014�\\u000f��~x�h�ȼ�_~iG\\u001e\\u001b\\u0000ᢒ6l��\\u0003���n�v�s|\\f\\u0012��\\n\\u0013`\\u00061��=�\\u0002]`\\\"�ЌK\\u0001�\\reN,�P$X�\\u001c\\n(q @�\\b�|��\\nhv`\\u001d��Lʨx�8� \\u0005�]\\u0019�a\\r�\\u0013~�_Sh�i\\u0016`%�T\\\\�;�Q��cc\\u001dړ�\\u0014-��R�\\u0012k����\\u0003n,�/\\\"ww`5\\u0012��T��b�`\\bHgpdSz�❊Ej����h��G��w�f�'��A�\\u001c0������\\u001f�\\u00059iSU<�\\bb���|{g\\u0001w.�w�X*e����y�d�\\u0017Ѫ7�T&s��P�\\\\4�eO\\u0014�;�1�F�9���f���B\\n��\\u001b�M;������\\u0000=\\u0000�\\u0013ޣ��QFg�Q�>Fra>�0aV���i�(9\\u0001��V���C\\u0016��\\n�=\\u0016��s�!]k\\u0018� \\u000eѡ���$��Tڙb?�\\\\w\\u0004���Υ:\\u000bxr��Y\\u0013P\\u001e˸�\\u0011.B@�\\u0018DNV\\u0002\\u000e�\\u0011`\\u001a�<�졒���\\u0013T����c�&��dg�U�SI-2�\\n\\u0003�Z\\u0015dͦ�~��\\r�.\\u0013�`rqud.Nv��u7�G�*{\\\\U�m_7Y�&<���S<��</g\\u0018%\\u001e\\fEH5!~b\\u0010�Ć�[\\u001e!\\rDA4$��]|{y��g0h�\\\\��((�\\f��Ȳ��\\n�u�����qm���\\u001d�d�+b���v:\\u0007\\u0017[�D��ѓ\\b���As\\u001aY#9�U�'�\\u0006������*ѱ�BU\\u0012Ċ��x8\\u0003=��I\\u0017�B�#F���~\\u001aHR�׫ +�fK^񘚁��L�,U���SQJ�_i�u��o^s����⏴5y}�2O�,��Z���:�\\u001a1V�Ֆ��|�\\u0018�\\u001eX;i��έ\\u000bfν������\\r�\\u0005�i���\\u0011���%�$�J uBqn\\u0019�\\f//\\u0014�{M��i�I��=k�\\u001cg0\\n|��<(`�t��f�a�0qT57mh��pd\\u0018�՞��rŰ�0�%��k\\u0003�\\u0003�'\\u001d �9\\u001ct��\\u0018���̯�\\u0011�K\\u0011�\\u001cfjKJ-W�ݎ!;��\\u0013��{\\\"�P���$#�y8�JE���Q\\nyq��`�>�l�>:���\\u0017�-`\\u0003}a��\\u0012�Q�\\u000f%�\\u0017�Mwuw�\\u0011�\\u001e�\\u0011Ep\\b\\u0016f��f�\\u0015�d\\u001fʹy�X\\u0006��/����A_\\u0002r7�\\u0012��\\u0013���/)G�0���\\u0002�u�Ig\\u0001�q�$�\\n7\\u001fЛ2(\\n{�K���o���\\u000b�)����s_r�/���\\u0012������a����W,����\\u0012��0�Zk��]_R�~A��Nu�E��NuU��Nu�\\u0006������ގ^x������+��\\u0016�y����I�F�\\f�@M-�\\u000f}�/˻}&8\\u0001z\\u000e��^I\\u000e���Q���!��pyW�\\u001f�\\u0005z�\\u0000f83�Z���>���Q�\\u001a�,|���\\n\\b\\tw�J�|n�B}�\\u0017ܾ΂ӧ�a��G\\u001d�Q\\u0018*@��z���u�?��|bj���\\u0015&�\\u0001u\\u0019A����/Wo�*zH��\\u000b�D���u��K�\\u0000���^����Kt�^�����c���R�t{�\\u001dtx\\u001b��\\u001b0���pi�Y\\u001a\\u000e�����\\u001a}�{2�J�<\\n�t�nuw�@MԟP�\\u0017\\u001a�QI!D\\\\\\fz�j\\u0012��\\u0015�.�w\\u0016\\u00159�fW!(S� \\u0003&������-�'��e�\\u0016,�.�qB����w�z�\\u0003\\u0012��Ɉ��.Ɨ�/��\\u000f]!Q\\u001fqS%'�q0�\\\\�DM\\u0010c�\\u001e�y��kƏ���a��\\u001b��}`Ú7�,}���w<ο����o_���Fc����L���u��/=\\u0006��,}���Y\\u001f���CB\\u001c�\\u0006���c�4�_���\\u001b�y=7\\u001b�v*��dx��P��3��$�۴��\\\"l(�h 4�)�\\u0003��S�Lj\\bL^�Ĕ�?�w���o\\u001f#z\\\"&\\u001bk4^��Y��V���Һ��;\\u001f\\u001cs��T-o����y����';�\\u0018<\\u0013*�o��-�1m��Eٱ9��\\u0002���\\u0004�\\u000b\\u0000��K�\\u0019 ^\\u0016\\u0015ݣ��XG�$\\t\\u0011~�\\n��\\u0015�?������>�6Y^�\\u0003�4��ȅ�Zm�7����R��\\u0015�JVhw��V\\t�#C�\\u000fj�P���{f��^�-e�~���\\u001f%LD�Wts�l\\u0010�ݭ�A��ʭ�Xϕ\\u0012���y�}`��l�s�-�N���Q�G\\r3�n��\\u0006����gq�Z֜��~2�Կ�Z�بe��5.#!L\\u0017>�\\u0000\\u001f/ZC=����\\u0006�/��\\u0012\\u001e1���t\\u0017)γ�����\\u001ef�}'���\\\\\\u0016�1\\u0012�|D���a\\u001a��}ؘ+\\u0011�K10]�\\u0004݅�\\u0011#�q�mT�����A�\\u0003���~���S��Sp]yJ�٨�����s7B_��RH/\\u0007��\\u0000��%G\\u000e\\\\ ��\\tY��+i\\u0013ɟ���4�\\u0003`�\\u0003�A�\\\\�\\u0005\\ta\\u0015���\\u0015R�\\u000fg`\\u001a(Lc\\u0006D�5�F\\u0011�����\\u0007��a1����\\b,�t\\f�JeR�F�N��\\u0012�\\u0015�}��N��\\u001d��/W\\u0010zi�`�S�\\u0014�?g����W�`�\\u0002�Ӭ2�?$���yI.@��w|\\u0013�\\r�\\u0016���%1$h��$��&�\\u0017e)�tF�zi�T=&/PBg���y�\\u000b�����>�}��$���0����(\\u001c���,�+�ʉ#��\\f\\u000eD=���3�o�P����vd�#.��\\u0019����\\u000e��%i~����Sd�_���_�\\u0002�8�8�/��O��@-L��\\u001c�E�%#\\u000b���Ǝ�H$S��\\u0007g+\\u000b+\\u0018�?�?K��\\u001e\\u001eXA�I\\u0003�\\u0006%,u������kǵ�{��i*����~��\\u001a���jO���p]���\\u000b�#ls\\u001fX�\\u0011\\u001a\\u001f�\\\"~.Y��r2�\\f����fn��֦Mom�c_��d�:6mfz����\\u0006,MH�޽�g�a�&���\\u0005�p�a�#���.���&@��\\t9V������\\u0019X\\u000b$j�0�2�� Zy\\u0019׫�D\\u0017���K�CF\\u000f)^�`\\u001bo\\u0013\\r��\\u001ay+��\\\\�<Y���\\u0005�﨤�ę����XSe���\\u001e�`1�\\u0002�\\u0012��c�\\u0013^.�{4�ꉯ�w�F\\u0000��\\u0007<����~PCW\\u0019��}Y\\u0002}Z���-\\u001bПSDS�$����?�)d�X=���$\\u001f+\\u000bR\\\"\\t��\\u0014ʠ\\u0006�\\u000b�;η�Z��5�W\\u001f��8a\\u001b0f�x5Ѻԩ�z{�i�p�xu���7�,�m\\\"{\\\\]�_9y�����\\u0011��H櫪{��c�_\\f��:a��ګ\\u0005K�V�/+�E��Ii��\\u0013[�#󊡈\\u0003\\u000f=�,�w�XJEN�-6&�/l�U{�\\u000f���v�\\u0006���A��{�U�k&\\u0011\\u001a�p\\u001b\\t�X��nm&;4u���8�~mA����4���M�v�v2:�Z�g\\u0007[2k��T�5��!�\\u001d�oO�ǌ\\u001e\\f\\u001bj�\\\"?&'�\\u000e���X\\u001b3��&F$�ûV\\u001b��}\\r�g\\u0002�O��B�\\t��Z��\\u000e9�}\\u000b��\\u0002\\f}V�gd�\\\"wVk�F�J\\u0012�\\u0006N��\\u0019�\\u001d�(��\\u001chFI\\u00074C��6�\\rc\\u001f��n��gd\\u0010[1��I\\u001b�z��<b�js�ؠ�\\u0000�D��\\u0007Yq�(�[���l&���\\u000fhg��;\\u0012��3����\\u0011i�Gt>�3~~3�9\\u0003��/C�B���L_\\rm�\\u001c\\u000e��w7�\\u0010{f\\u0003�\\u001aڤ��Z6h�n\\\"!�]�1��T��{kӮ\\u0004\\u0015���GP�c�\\u0016������kw�o\\u000e�\\u000b�_�\\u000b���ߝp�������t�)�'\\u0012q{�n�M8ޗB)���\\u0019D�޵h�� �j���6b\\u0010�\\u0012��\\u0006z���\\u0012�z�c����W�r��9�Q�\\\"g�Ʋ���P���<  >Q��:��eoCg8�*��W\\u0004k��M���+w:��qj<r\\u001b�ɝw(4�і�)��9#����&��ո�IK՜a�\\u0007W_z�&��k�忀����(�ē\\u0011��$녤���\\u0011�o#\\u0004�����ơv\\u000f/\\u001a<��;�<N\\u001a\\u001a�^|�\\u0013���%<��\\u0015��^{�\\fۍ��cc\\u0017,������n����N�r��Ш䚗�#�]��vĬ� �0�K�k���\\u00153\\u001a\\\\��+��`�\\r�Ό����0v{Y���n˟шr��O����|\\f,�\\u0006f\\u001c�U�\\u001a�#B5 i��\\u0004����I0Ʋ)\\u0012I���]�9\\u0001\\u000b&��P2v����ڶ��>el�������{WM�&|��$�Ç�����=�h�8jе3�.\\u001d�xq���6W�*�̜?��z���s*1Z��^k��]W{���\\u000f�\\u0019^8�\\u001a�\\u0016�5~�A���yC�o��\\u001b��`~\\u0005�C_\\u0018�K;�e\\u0011f(F�@\\u0019\\u0007�ig0N\\n��E�N\\u0006CIX�\\t���ȉ\\u001dj\\u0000f\\nq�j��\\u0016�����!SW_��\\u001b\\u0011 �(\\u0012\\u0003so�6>�\\u0019T]>�UM\\u0016\\f\\f��/���\\u0004�n�.��\\u0004t�Z�\\r�a s�t��k�ںz�؜�_i�Y�pQ�V[0\\u001al(\\u0018��3��Ė�n��M�}˱?�Yr\\u001c:S=�dz1\\u001d�o�^��\\u000f�:�D��\\u000fzl\\b�\\u0014��\\u0013\\u0000�C1�~��T\\u000b�@��^�\\u001e�N���9���#/���} \\nǕ�e�����e�1��W�A�B\\n\\r\\u0010��H$:���R>��b(��\\u001e�j�\\u0017\\r�4&\\u001d\\u0002='���������6O�Cۙ*r�{��(��t\\u0014xldi��f�g�\\u000f�C�U�|�����zFJv���F�4�s-\\u0011?��C�\\u0010+\\u0019Cf�77�S��\\u0013V��\\u0019\\u0013c�� �!�X�H�B2�H�\\u0000W~�K1���~� �����lK\\u000f��<�r���o�o��)�,�_e�O��u�����W���������LL��5�ï�F)�\\u001c\\u001ay�C�����7��~0\\t�P�UlsUm66B�50\\u000e7H�\\tT.��/���#���=��To\\b��\\u0011=ȇ��$l(\\bM���\\u001f?yӤP�\\u0001n\\u001d�B�@mU��\\f�\\u0011,,�+���\\u0003��_�bj,6uŒ��\\u0007�\\u0017W�]Wh6�K���H�#�\\\"4{�����[�����L�\\u0007��Q���d��>dG�_��,��\\u001d˜�_��Ln�����l�ﵧ�=\\u001f�aG}�*��\\u0018\\u0003\\u0019Τ�V��y4�ơ�d�\\u001by?��\\u000fw�����Sd \\u0019��O�\\u0018~�����\\u000fH\\u001b۬j-�\\u001fI1\\b�b폀;JCl\\u0017h�\\u001f\\u0000:Eu[\\u0006-\\u0019��\\u000e$t\\r�T�g�=\\u001a%I0OB\\\\0����/�����i6��,�\\u000e@��\\u0000o��������\\u0006\\t)�f-��\\r\\n�|;�u6���(�\\u0014Տ>��U\\u0007x�o\\n���\\u000e)G\\u0017l��ڀf\\u0019��I\\t�����z\\nTz4�7;��iNj�\\u0007z�Sx\\u000f޵`漋sd_U$�(䴚yUO��4��1T�\\\\\\u0003\\u0000R4+��\\b0�\\u0006=?\\u001e#>F�J%�S��\\u00002��)�m�\\u0015(c��}\\u0004P�\\u001a��\\r�~\\\\A炂^\\u0005\\u001a��5I�ɓ�J��o����8S��N�.�W�\\u0018f\\u0017%�WzH�p�{\\\\\\u0001�Х_�\\u0013��\\u0000���Ll���\\u0013\\u001a$�+R�Uz�\\u0017M\\n�yG�we�&�3!��\\u000e��%3�ʃ\\u0018���<V\\u0018b4bC,4���1\\u0011\\u0006��H\\u0011\\u001eMP\\u001c+���9�t��`5k��\\u0004n���\\u000f%����ha!o-/���tj�\\u001f����\\u0017;\\u000f���\\u00163)��4�E��7�\\fj� ���\\u0015%\\u000f&�0\\u0012�k����F\\u0017C`��L�HʨX���a��\\u0006}0������'0h�.��˱c�k~��'�.�{WN����&��\\u0018]�R��>f\\u0000�~���������\\\"�J@?�~��8Q�8��h 1\\u0002�\\b{<Z<�:�;U��~1\\u0012��[\\u0017ҾWR\\u0017��\\u0013\\u0017�~8�#\\u0015M�\\u0006۽���O�\\u0002Z���0�\\\\:0\\u0015��*�\\bO����n��\\u0014Y��\\u0016�\\bL�n_-Ɖ\\u0001\\u001f\\u0005(_��zVK��#�2�NO��BJ���~G)�]\\t��\\u001fU�\\\\�FJǇ�\\u0001>��n|p��\\u0007��n�*�=��\\u0016]\\u001f�`\\u001d��Y�O\\u001dͩ\\t\\u0000K�\\u0012�\\t�d�\\u0001���%e���ꩢH}�\\u0003X���\\u0000�(�z+Yb5;,ˬ�Y$2k鲙K7��6���L�ux�\\u0004�7\\u0014�^�;�v-I̼�\\u0013y�\\u0015L�fc\\u0007��g\\r�\\u0016��i]��6Y{�\\u0013ڛ��;\\u0002��5�5d�T���^BXN�,y��\\u0017gt��.^��7��6\\u001b�0�\\u0019\\u0001}\\u0010|�������\\u000e�$dE�\\u0012:G�\\\\D�0\\u0000z����R��\\u0000��7d��R\\u000e�i\\u0007lņ���\\\\~+��l]�o7_��$\\u0010\\u0001\\u00106�f�U��5H`�v�=\\u000b��Գ|~ȑ�4���\\u0012�1�����ۥ�\\u0015�o}�l3\\u001b94�I�ʭ={\\r��y\\u001dq�Y��I���I���\\r\\u0005��w�\\b\\u0005A3F��EW��pI�\\u0003J�\\b\\f�'�9<�P�\\u000b\\f�T)i�B�kl\\u0001k��N1a�����\\u0019?����Po<\\u001aE��^z����n�,�͙\\u0016���S�m7�J�i$3f?��׻�Y\\bQQ�~�^lؠ�A�(�]4q��\\u0002�*\\u0005��:G\\u0002�\\u001e ��a��\\u0014�\\u0012���\\u001e`\\u0012�\\u0010�TI\\u0001�\\u0019��Z�FB.�\\f�\\u0014\\u001b2�]�7?�\\u0019�����Ӓ\\u001f��!��&Òz�]\\u0019�r�����\\u0019��?����y\\u0016���F^�i;J=���\\u0019�p���\\u0000��\\u0006C��\\u0015���!�Y��q���f�\\u0019\\f݉�s� c�X\\u0002�f-[\\\\�\\\\���`O^���_���\\u001b��w']��c�r��\\u001e����b�]���As�>A�d@��:\\b��t���ơ.��\\u0006�f\\u0014gg�[Y(\\u0000\\\\�\\u0018�ֈ��\\u001f������N?��9q�d\\u000e����0G*\\u0006H��p��~^E�u�P1G���\\u0012�.]����B'xX�\\u000b\\u0018u5=���%ݰ\\u001ffv��.��l�\\u001db`.e�n�\\u0018�\\u0011P�|l�c���J��Y�T�\\u000fw\\b\\u001aB�\\u0004�\\u0012�D�u2�f����P��$�b�$:Ȓ\\u0011.�\\b!�A͐At\\u0003`x\\u0004��'ZߗV��\\u0006\\u0016����lR=ǹ\\b7D�+6�\\u0013�� �`��~�7/�\\r\\u0018d ¢U�r?g��[�:�ue\\u0011{��\\u0013C\\u0015��\\u0015\\u0016�.��`7T\\u0016\\u001b,�V���\\u0003�`\\u0012\\u000b<\\u0006{^�S6���\\r\\u0016��4i1\\u001b\\\"�m�2��\\u0018�%\\u0015\\u0016��39�ξ\\u0004�gq\\u001aL\\u0004�$�lfY,_!+�J�c\\u000b�.��˫���\\t�q` �,�JoE})臢�LX��/��l~\\u001e�\\t:���\\u0012��@�hr\\u0005�*\\u001d/�\\u0003M�\\u0001�B���\\u0019�rH*\\u0013��|N�+�\\u001e\\u000bw�sH�g\\r�%�R!�,���{]��X\\u001e��\\\\C�\\u0005��G+飩�\\u0001�ϳT���;`:\\u0017�x�.�ޏ�i�C�z�zśl>zF�7����`\\u001e\\u0019��Y\\u0010�6j{AR�k��\\r�2G�Bߊ\\u001b�^\\u0004\\u0014\\r�\\u0001V\\u0013u�QoKR\\u0016�\\u000e\\u0005����U������p��/�Q7�͙��z1��[��Ko�\\u0017G�<\\\\/��\\u001f�����̥ �\\u001a��+e5\\u0007P�R�%$�ƭ߇ĬQ�H&2U�5\\u0015�-����+8\\u0002�oy��<rY\\u0019q\\u0013c��7V[�\\u0011�:VU��H)\\u0016i��2,��_!c�ѲH�\\u0012Vf\\u0012�գ��i��[\\u0011�U�\\r\\u0011������\\b��T&���o\\u0006�\\u00165�P0\\u0014�h7d�rb�� �`��Ͷ \\u0013t\\u0017#�k��`\\u001f��}uܨ9��\\u001b�,�y�}'�sF�{u�Q��Q���M\\u0018޺2v��\\u001b��Gz�_0=�����q�΍����N�\\u001f�{븱��&?�ԏm.\\u00197���S\\u0016�)�}U�g�m�Q>\\u0019v�S~\\u0015�#�\\r�\\u001d\\u0019G\\u001a�\\u0002\\u0019���P�\\u0014X�`\\u0015rh\\u0015&\\t�t\\u001b\\u0012e\\u0002,\\u0001g(!��Z�A\\u001e��\\r�H�ןl��x�\\r#�?66v�+R�ظ�\\\".���b\\u0015o���p�\\u0017�;#q������F��#o��Q�\\u0006\\\\�\\u001b?�W\\u0004|��78\\u0007\\rM6^?O�\\u0011��=\\u0016\\u000e�\\u0019/�$\\u001d��F��\\u001b��Y����\\u0011�v\\u001fx\\\"5\\\\���m��wf��ͮKqߗ�\\u0011�/\\u0012�:ǡ��lz�V�E\\u0000��\\u0018'�5�c�a�Ӽj\\u0019\\u0013\\u0007\\r�x��z1XJ\\u001d!�\\u0019�P\\u000f</�#�s�v#\\u001fPIv�[�F�����<�+��Y���W�9\\u0013�#�����\\rSR�1�G\\f���K\\u001c�\\u001bow\\fp���\\u001ch�\\u0005��V�\\u0015\\u001eqS�W\\u000e�'Mv̩\\\\:{ҍ62E�\\u0016V\\u000fkN^��(q�\\u0014�\\u0015nX�x�D�\\u0012q�Վ��\\u000b$�Ⱦ��v>0r\\u001c��,���?�\\\\Ms\\rY�\\b�/\\u0017�\\u0017�M��ǰ\\u0017�:e=\\r�ٍ��3�1���k\\u0011��\\u0004�6�0Z5%4@~3\\u001a�-\\u0017$\\r��aq\\u0018\\u0007[*�{��m2rՃ\\u0016<s�+;GO�\\b�tW\\t��<w��~z2O����\\u0017Je_-o\\\"�m�2���E\\u0016�V�j�7;L�-�RC�E���U6\\u001f]U3��+�����2g�Zɧ�\\u001b��\\t�����G�*��Y߱B��\\f�~\\u0002A<��z��@O`�n�|}�\\u0003�\\fz\\r�\\f�\\u0018@�q2%��J0�Mӌ��C�\\u001e^N�[�bq�+�v5i\\u0003�T{����/���G�7�nT1�9��>و���\\u0002<j�d��=ڳ3\\u001e=�5�^����\\u0006�A \\t�r��j&E��ޔ�jO�w�b��4�\\ryJ�&ڞ\\u0005����\\u000fnap�el����P4���F��Xe)�\\u00022\\u0000�Qj/x�\\\\x]�8\\n9\\u0003��@a�\\u00040���Â����:M2r�DG�'�.�\\t��.,U�z��]�4\\u0000M���U�-�})l��e�N\\u0016��\\b.\\u0003\\u0018��Ć�`�=�\\u0015�]jRN&��\\u0013�Gm\\u001f�������e�q=�\\u0002s2j���S���f�1��;_)�\\u000e�K\\u0015��U�\\u0016�^-\\t�\\u0000���>��^\\u0004��U9mi��$l���z�\\bn��.\\u0006J^��^!�n\\u000b{�;��S\\\\_\\f\\u0012����N^E��k��k���^�|,�W{�S��d�ދ�?J�@b���_�m�\\f4���হ\\bE�c\\u0017��Я��\\u0018q(q��6l\\u0007�!\\u0003\\u0004�\\u0017jZ�\\u001c\\u001b5�,�K���o�\\u001d�po�O�\\f\\u0010\\u0019%b((*\\tg2Q\\r+),��\\b�{L\\u0001�.�m��|��f�+\\u0000�O�l^��n�_����a2yHd� \\u0018Ybg[]\\u000e'˓#\\u0016�)�&�����%��\\tn��ŋ�?\\u0005��.��1���t\\r�>qeYzY�����X\\u001dO�VO�C��E�ջh�>ݠ��g��\\u0002��a��99I��\\u0014�sS����ځ�Ȃ���ѻ�#��uBJo�������So����_Y���0�59�´�a�8ޚ��V���J�\\u0015w>:��\\\\�g�\\u0015���J,ϝs�:���\\\\4��O\\u0014���#�\\u0001�^\\\"':\\u0013|��~阕;��b�'#p���f��\\u0013�ٚ�^\\u0011&ps.P\\u001a�\\ri����90u�:�\\u0014��\\u001f�{��&ܹB��z����|B\\u001b�cW.D���ܥ�}|��4\\u0007 ߅#G��Q�c,�\\u0002�D��I\\u000f�;\\u0017t, '�wl��=޹=\\u00076?eA�B/\\u0014���a�\\u0007���94��Ǵ\\u0013\\u0007���\\u0014z��\\u0018!��p\\u0000L+�%�\\u000b�;�\\u0006\\\\�I���\\\\��\\u001b(���\\u0012��\\fC\\u0013���\\u0012߮\\u0005�W�����|�ȥ�Į�\\\"{���COy:Eq���\\u000b���;����;�\\u0006\\u0012ܭ�s�H�ށ�ڋ(�\\u0001�s��1uKOUw�h�[����\\u000b����q�\\u001e�d��8�V\\u0017Jʄm�\\u001e�\\u0006�}���{�\\u0002\\u0017֮&\\u000b`�s���ίf�T-�U`�|ږA�f���ӖC�m���s��:�\\u0017�[���=�\\u0011�:p���_�F��n>@\\u001eS;}��{�s��~\\\"����\\u0013\\t\\u0019ǭ[����Yr��B�j�Β�\\rvd6q�q���j�\\u00152�\\u0014;W[��NfK\\u0018ݔ֧���+��n�=��yư�\\u001a)5�wb�]\\u0002��qη�&�_:�G�i�;R�34�\\u0013�沾�E\\u0000�pF\\u0007���A\\u000f0\\u0000XE�>�!�z�����J\\u0017p!@o\\u0011*tT�kїg�Ӎ;��\\u0007U5=Z\\u000f��D1�kO�\\u0007�\\u0013�!�i��cKI6�\\u0010\\u0018�+�.��|�\\n\\u000e|{E��qa\\u0000�7�h\\\"\\\"n��\\u0017�h����K]�;�cJ��޸R`\\u0010�ۡ6�\\r��W��h���J�\\u0013�ꔉ�2]{՚�q\\u0014�DRv����ǡ\\u0004ַ~\\u0001^tw<�\\u0006��M��B�eb�f)���Ј\\t<!m\\u0013\\u000bɅ��>Y­�\\u0014\\u0012v�PKPk%�\\u0006-C�\\u0012�(Y;\\u001f�>&�j���Lֿ�D�:��\\u0012#\\u001e!ETd)\\u0000c�[�@OM@\\u0012\\u0002�TE\\u0002��.�$٧S\\u0018�hSIhqz?��\\u000e*� \\u0011��]�4�\\u0002�S\\u0005�/��>'S\\u001f�o�0~9�\\t�U�\\u000f<��Bu��6\\u0014\\u0003�쌝�\\u0006�\\u0014F�\\\\�\\u0001�G\\u001f\\u0017k \\tL\\u0006\\u0001b\\u0005��\\u0006�\\r�D�������\\u0016����kKK��\\u001b\\\\?v��WmY���V���\\u0015� ~�^��G�t,���:��uT[\\u001f���֛׭���\\u0018�>�2��\\u0010˙���\\u0011�_n�m��\\f�\\nXG\\u0012e2\\\\�\\u0012OBȄӳN�$���(2\\u001a�n(J�;���g�L5��F��\\u0015�w\\u0013��D/�0ˬ�ύ\\u0013H��e�'8�ez�C\\b��y�W\\r����J�lR�B^�˥�\\n\\n\\u001e��ᲰJ{�\\u001asӝ\\u0005\\u001dTG���B�]\\\\b2u}c��O���\\u0012��f\\u0012����C�\\u0004`�#�\\u000bw�2�t)n��cꎋ��Q�\\t��.^�|{ \\u000bϨ����V�is���z�\\u001aĀ:���9�\\u0006u�a�]����*\\f�V�bt�\\u000e;͡\\u0011�{\\u000b�=\\t�7\\u0017ҿ^�g_�B\\u001c4g\\u0010�Ը�w���\\u001a\\u0002�\\f�޾.=\\u001a�F����U��p���������a9�\\u0000�\\u0002@�9kC�A\\u0016�g꿎\\u0007�2�k���%x��w����\\u0007\\u000fx�_0@ݦ\\u000b\\r���G1�j�RC��Ȝ��\\u0002�?\\u001e��\\u00006��?իMOV\\u0017��f>�\\r\\\"���~R��}���\\u000b;�_�q�)��m�\\u0003�r��Q5�(�N���O����Ԇ�İ�\\u0006raCpX�jC�D�7s���\\u001bf��k\\u0001̍�2^�x>�����\\u000b9\\r��Ͼ�ըi��r�\\u0007\\u001e��o/��\\t����@]\\u0002��\\u0001�@]\\u0002w��������\\u0018�'F0A\\b�(}��f��A���)�+t9�\\u0005��\\u0003������(d��v�L�R�\\u0010z:R��PG\\u0010(����\\u0011Ru|:��xK&砇���B\\u000e+�!\\tW6劖��ٝ�\\u0018\\u0011���3.��&��y~��2���m�����Q�I:�X��;��\\\\�;u��3KB�\\u0017�˟^�M�)YD��\\u0011�󫒨�q��Ǖ���\\u0003�Sާ^%]�����.�)��V��e�z�o[Y���l���gSy,�Q[�W�eE�Skz4���\\u001f���=M�2̪\\t(DWP\\tj{�=�ǁ\\u0000�\\u001e�?@��?\\u0005��̛H��I�w�`נA�\\u000e�\\u0006`%�]8_\\u0003\\u000e=�8D�\\u000feP�HzX�#�!\\u0016M:D�=\\u001eILXl�֮��hۼ;�f��\\t��U��'\\f\\rCS�HԷxBAi٢���\\u001b�Y��\\u001d��c\\u0017O�7Kvτ�>�\\u0017�2z��\\u0017\\\"gvt��\\u001af�92_d�{o\\u0004tVv}�\\rLaT��e�:Qm��\\\"\\u0010�\\b�\\u0007��s(\\u0000�\\u000f�j3�\\\\J�ViN\\u0011C�\\u000e趢���\\u0011�=��1�����\\u0003q�\\u0012��g?\\u0013���W�a\\n�\\u000e��;�;I:\\u000br>\\u0019�\\u001fY�����U��N-\\u0003'�\\u0003����/���~k�@�v�h(�&\\u0018g3�dH!�`M2\\u0011�\\u001e$�6�u��B�s���FR��7�m�~|�S;k\\u001b`����k\\u001do�R{��{���\\u0015P�F���;L-�\\u0003hc\\n��`\\u001a`�\\u0002'�A���\\u0001\\u0003ճIP�0y�F�D��I棴\\\"~�\\r\\u001eg��Wz|DČ\\u0006�0�\\u0015F\\ru�\\u0017M\\u00193c���q\\u001a3�h��ul�PedU��A\\u001e�\\u0017؊纍�Q��:q\\fY�v��A��\\\"�^���\\\\�`\\u001b\\\\\\u0011,p��j��&\\n�\\u001bZ��k;ӫF�ˣ�]?��\\n%Y�@4y��\\u0012��\\u0001\\u0003�\\bra�\\u001c\\u0007[^��!�\\\"wz�rE\\b�56��GVTH\\b,\\u0019�\\u001d�\\u0016�t���{|{\\u0016u�*�?��ϊ����� r�X� 6d��:i�\\b?\\tR[���Œ3\\u0006�UӇG̖\\u001dȺ���\\u0000�nS��TC}s}}���ry�c�\\u0003����\\u0003N���B\\tuڴ\\u000f�R=����B���zʠ���yIP2�y%P\\u0002h\\fx\\u001d�?��Ixz+\\b9�+�\\\\Y�-���Nom��RV�mM���2�yU�i\\u000b7˰�4���褫\\u001e�-H��\\r�}�Ŕ�|�%=>�p\\u0017\\u00179=��\\u0017�6|�����hm��5�ip����8�.[����C,C�\\u000e5��6w�h,�TIn��-y�%�&�w���$W�u�$���@Ð��!��������r���Tr���w����\\u0018~=�%:Wnc,�h�O4��㬼h��I+����\\u001e=�\\u001c8ӊ��>�k���\\u0004\\u001b��\\u001e\\f�BM���\\u0016>�\\u0010���\\u0019\\u001c.�֚\\u0006�`\\u001c;��q��J[��=e�C(���6�˳\\u0016V\\u0014\\f\\u001b�t�H[����H�q6��\\u0019B,��\\u0013\\\"�g�����J��Λ\\\"�f�E����\\u001bz� �\\u0014���5�\\u000fMݟRƇ]�2��g&��]R7j��CdƲ���\\u0004VT\\u001e|w{^��e��\\u001a��G�\\u0007��0�\\u0011\\r!��\\u0000L}\\u0012�9(\\u000bܱK��Z�!}�6�v���6+��k���L��\\\\7�:}�n_n\\u001bhg��t:q�M�2��\\u0003�\\u0016��x�c`d```dpdҘ11���+�<�\\u0006�\\b��o�����V����e�\\u0000r9\\u0018�@�\\u0000��\\u000e�x�c`d``���\\u000b���o��2�]\\u0006�\\b\\n�\\u0001\\u0000��\\u00070\\u0000x�c�������\\u0001\\t���L=\\f\\f�\\u0012\\b�q\\u0013\\u0010�100܄��@>\\u000b���� 9��\\u0013,\\u001b�����3�\\u0017��|@,\\u000eQ�\\u0007\\u0004��\\rò@�\\u0005U+��� \\u0005�\\u0019�4\\u000bЌ9P=�\\u0010>�͂�/\\u0005�=0}LHjL���\\u0015H+b��6T/Ll\\n�_�E�\\t(�\\u0001e�@\\u0012\\u0003bF\\u001d��;�l\\u0001 ͌\\u0003��Ƃ�W\\u0010>\\u0003�\\u0019H|%��an=\\f����\\u0002\\u0014\\u000f���\\u001b��\\u0002�B�0a�C��(�>\\u000e�X\\\"�ϬPqV8>\\u00021�\\u0001\\u0004\\u0002\\u0018,\\u0019N0�\\u0003yL(\\u0010\\u0001n�I\\u0016$\\u0011q\\u0006T�\\u00026K\\u0000��?\\u0007\\u0015�t����\\u0013P�\\u0012��?�D/�\\u0013\\f�\\f\\f\\u0000t\\f��\\u0000x�c``Ђ�0�\\u0002��\\u0000�9�/�R�N�^�I��\\u0018/0�b�a�c�c:Ƭ���%���e\\u000e�\\u0003V\\u0019�8�\\u0006�_l\\u0001lYl=l\\u0007؞���۰\\u0017��b?���À��c\\u0011'\\u0003�\\u001a�\\u001bg\\r�\\u000f.\\u000b�8�I\\\\k�>p�qWp/�~�#�S�s�W���ψo\\u001e?\\u0007�\\u001e\\u001a�\\f�\\u0003�\\u0004�\\u0004�\\u0004\\u000e\\b�\\u0011�\\u0013�\\u0010�\\u0013�\\u0011�\\u0011\\\\!�O��\\u0010�����P�P��\\u001a�{�\\\\�I�S���H�\\u0004�t��\\u0013�\\\"rB���\\u000fQ\\u0019Q;�\\n�kbjb=b_�U���g���`�\\u0010�А\\b��%�C���'I.I'�\\t�{�X�|��IsI�H��~##!�\\\"S$\\u001b!�I��\\u001c�\\\\��1y\\u0019y?�u\\nb\\n&\\n9\\nK\\u0014�(|STQ\\fRlSܧ�M�@)Ni��\\u0019e\\u000ee\\u0007�,�)�{�ߨȨ��$�LS��ʡj���:G񅚑Z��\\u001eu\\u0019u\\u0017�\\n�=\\u001a\\f\\u001aV\\u001a9\\u001a�4>i�i�hn�������եuB�I�A{���N��&��b�M�k\\u0000c�yi\\u0000\\u0000\\u0000\\u0000\\u0001\\u0000\\u0000\\u0000�\\u0000�\\u0000\\u0011\\u0000\\u0000\\u0000\\u0000\\u0000\\u0002\\u0000\\u0000\\u0000\\u0001\\u0000\\u0001\\u0000\\u0000\\u0000@\\u0000.\\u0000\\u0000\\u0000\\u0000xڭ��N�@\\u0014�O\\u000b\\u001a�F�$��p�Ʀ� �ʸ\\u0010��h\\u0014]\\nB�\\u0014Jl���\\u0014>�\\u001b7.\\\\�\\u0004�\\u001e>�\\u000b��aD�,��ff��=�̝[\\u0000��\\u0019\\u001a�/�\\u0005�\\u0011h�\\u0018�K���a\\t��u��^q\\u0004�xR\\u001cE\\u0016\\u001f�'p�e\\u0014O\\\"�=*�BB{S\\u001c#�+�Ƣ>�x���8N>U����U�+,�.\\fC�v{��S�ھY�Z؄�\\u000ez��\\u0003\\u001b\\r\\u00040�����$VH\\u0015�5P�9�\\\\w��\\t��\\r�|�!\\u0007_�j\\\\k\\\\��/�����PB\\u0001�<�\\u0000�8��@/\\u0017u\\u000e��6s\\u000e��q͈8%�LK֒�1O/3/?�������o+0F�N�=|��d\\u000f�k*I���;ڠ2@U껃\\f\\u0013k��hѵIO��3*N���&�rd��\\u0014r���/5>\\u001a��d�˯�aݎ��gTP��4eVYa�\\\"\\u001a\\fz��zZ��\\u001b2.���:{��,z:�?~\\u0002�m�{x�m�Ւ�U\\u0000E�^IH�\\u0004ww���ҍ'C\\u000f��N\\u0012\\bI\\b\\f\\u0010,����[pww��!x\\u0004 �k���]]�g�3U_Mk\\\\k����V����_�\\u0016�\\u0018�\\u001aߚܚ�\\u0004\\u0016c\\\"�X�%X��X��La\\u0019�e9�o��\\n��J��*��j��\\u001a��Z��:��z��\\u0006l�Fl�&l�fl�\\u0016l�Vl�6�\\t\\u0005\\u001dJ*j\\u001a��ؖ�؞\\u001dؑ�ؙ�Lc�]�3̮����������þ���\\u001c��\\u001c��\\u001c¡\\u001c��\\u001c��\\u001c��\\u001cñ\\u001c�������ɜ�tf0�S9�Y��l�0�3�Ǚ��\\bgs\\u000e�2��8�\\u000b���X��\\\\¥\\\\��\\\\��\\\\��\\\\õ\\\\���������­����������ý���<��<��<£<��<��<��<ó<�������˼«���,�\\r��-��\\u001d��=��\\u0003>�#>�\\u0013>�3>�\\u000b��+��\\u001b��;��\\u0007~�'~�\\u0017~�7~�\\u000f��8}���32�b���������-��[�\\u001d�t+�v\\u001b���ܩ�-�\\u0007[\\rO��̛3�����\\u001f7��\\u001f�}D�G�}D�G�����}/�{y����؉�؉����؋�؋��^a��W�+�\\u0015�\\n{���^a�c�c�c�c�c�c�c�c�c��S�)픾��Sz��|������+�W��|Oe��=���^e��W۩��vj;���Nm����i|Wc����k�5�\\u001a{���^�^�^�^�^�^�^�^�^�^�^�^�^�^�^�^�^�^oЋ����;����\\u001e�����:������:�����d�3�;���:������9z�����9z����]������9:���ߔ��qʱ�{�~���7��~���7��~���7�=\\u001dG��qt\\u001c\\u001dG��qt\\u001c\\u001dG��qt\\u001c\\u001dG��qt\\u001c\\u001dG��qt\\u001c\\u001dG��qt\\u001c\\u001dG��qt\\u001c\\u001dG��qt\\u001c\\u001dG�\\u0019�۳�\\u001bt��o?q$�崡�\\u0019�\\u0006����\\f7��J1�r0��\\u0014�`�\\u0001\\n�-|\\u0000\\u0000\\u0000\\u0001Q�K(\\u0000\\u0000\"}\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/sass-bootstrap/assets/js/uglify.js",
    "content": "/** @license uglifyweb Copyright (c) 2011, The Dojo Foundation All Rights Reserved.\n * The parts that are unique to this repo (not much, just some wrapper code) are\n * released under the new BSD and MIT licenses.\n *\n * This file includes UglifyJS and some parts of es5-shim, both which have\n * their own licenses:\n *\n * https://github.com/mishoo/UglifyJS (BSD)\n * https://github.com/kriskowal/es5-shim (MIT)\n *\n * More info on the project: https://github.com/jrburke/uglifyweb\n */\n\n(function(){var a=Object.prototype.toString,b=\"a\"[0]!=\"a\",c=function(a){if(a==null)throw new TypeError;return b&&typeof a==\"string\"&&a?a.split(\"\"):Object(a)};Array.prototype.forEach||(Array.prototype.forEach=function(a){var b=c(this),d=arguments[1],e=0,f=b.length>>>0;while(e<f)e in b&&a.call(d,b[e],e,b),e++}),Array.prototype.reduce||(Array.prototype.reduce=function(a){var b=c(this),d=b.length>>>0;if(!d&&arguments.length==1)throw new TypeError;var e=0,f;if(arguments.length<2){do{if(e in b){f=b[e++];break}if(++e>=d)throw new TypeError}while(!0)}else f=arguments[1];for(;e<d;e++)e in b&&(f=a.call(void 0,f,b[e],e,b));return f});var d,e,f;(function(){function g(a,b){if(a&&a.charAt(0)===\".\"&&b){b=b.split(\"/\"),b=b.slice(0,b.length-1),a=b.concat(a.split(\"/\"));var c,d;for(c=0;d=a[c];c++)if(d===\".\")a.splice(c,1),c-=1;else if(d===\"..\")if(c!==1||a[2]!==\"..\"&&a[0]!==\"..\")c>0&&(a.splice(c-1,2),c-=2);else break;a=a.join(\"/\")}return a}function h(a,d){return function(){return c.apply(null,b.call(arguments,0).concat([a,d]))}}function i(a){return function(b){return g(b,a)}}function j(b){return function(c){a[b]=c}}function k(b,c){var d,e,f=b.indexOf(\"!\");return f!==-1?(d=g(b.slice(0,f),c),b=b.slice(f+1),e=a[d],e&&e.normalize?b=e.normalize(b,i(c)):b=g(b,c)):b=g(b,c),{f:d?d+\"!\"+b:b,n:b,p:e}}function l(b,c,d,e){var f=[],g,i,l,m,n,o;e||(e=b);if(typeof d==\"function\"){if(c)for(m=0;m<c.length;m++)o=k(c[m],e),l=o.f,l===\"require\"?f[m]=h(b):l===\"exports\"?(f[m]=a[b]={},g=!0):l===\"module\"?i=f[m]={id:b,uri:\"\",exports:a[b]}:l in a?f[m]=a[l]:o.p&&(o.p.load(o.n,h(e,!0),j(l),{}),f[m]=a[l]);n=d.apply(a[b],f),b&&(i&&i.exports!==undefined?a[b]=i.exports:g||(a[b]=n))}else b&&(a[b]=d)}var a={},b=[].slice,c;if(typeof f==\"function\")return;d=c=function(b,d,e,f){return typeof b==\"string\"?a[k(b,d).f]:(b.splice||(d.splice?(b=d,d=arguments[2]):b=[]),f?l(null,b,d,e):setTimeout(function(){l(null,b,d,e)},15),c)},c.config=function(){return c},e||(e=c),f=function(a,b,c){b.splice||(c=b,b=[]),l(a,b,c)},f.amd={}})(),f(\"almond\",function(){}),f(\"lib/parse-js\",[\"require\",\"exports\",\"module\"],function(a,b,c){function r(a){return q.letter.test(a)}function s(a){return a=a.charCodeAt(0),a>=48&&a<=57}function t(a){return s(a)||r(a)}function u(a){return q.non_spacing_mark.test(a)||q.space_combining_mark.test(a)}function v(a){return q.connector_punctuation.test(a)}function w(a){return a==\"$\"||a==\"_\"||r(a)}function x(a){return w(a)||u(a)||s(a)||v(a)||a==\"‌\"||a==\"‍\"}function y(a){if(i.test(a))return parseInt(a.substr(2),16);if(j.test(a))return parseInt(a.substr(1),8);if(k.test(a))return parseFloat(a)}function z(a,b,c,d){this.message=a,this.line=b,this.col=c,this.pos=d,this.stack=(new Error).stack}function A(a,b,c,d){throw new z(a,b,c,d)}function B(a,b,c){return a.type==b&&(c==null||a.value==c)}function D(a){function c(){return b.text.charAt(b.pos)}function e(a,c){var d=b.text.charAt(b.pos++);if(a&&!d)throw C;return d==\"\\n\"?(b.newline_before=b.newline_before||!c,++b.line,b.col=0):++b.col,d}function i(){return!b.peek()}function j(a,c){var d=b.text.indexOf(a,b.pos);if(c&&d==-1)throw C;return d}function k(){b.tokline=b.line,b.tokcol=b.col,b.tokpos=b.pos}function p(a,c,d){b.regex_allowed=a==\"operator\"&&!S(F,c)||a==\"keyword\"&&S(f,c)||a==\"punc\"&&S(n,c);var e={type:a,value:c,line:b.tokline,col:b.tokcol,pos:b.tokpos,nlb:b.newline_before};return d||(e.comments_before=b.comments_before,b.comments_before=[]),b.newline_before=!1,e}function q(){while(S(m,c()))e()}function r(a){var b=\"\",d=c(),f=0;while(d&&a(d,f++))b+=e(),d=c();return b}function u(a){A(a,b.tokline,b.tokcol,b.tokpos)}function v(a){var b=!1,c=!1,d=!1,e=a==\".\",f=r(function(f,g){return f==\"x\"||f==\"X\"?d?!1:d=!0:!!d||f!=\"E\"&&f!=\"e\"?f==\"-\"?c||g==0&&!a?!0:!1:f==\"+\"?c:(c=!1,f==\".\"?!e&&!d?e=!0:!1:t(f)):b?!1:b=c=!0});a&&(f=a+f);var g=y(f);if(!isNaN(g))return p(\"num\",g);u(\"Invalid syntax: \"+f)}function z(a){var b=e(!0,a);switch(b){case\"n\":return\"\\n\";case\"r\":return\"\\r\";case\"t\":return\"\\t\";case\"b\":return\"\\b\";case\"v\":return\"\u000b\";case\"f\":return\"\\f\";case\"0\":return\"\\0\";case\"x\":return String.fromCharCode(B(2));case\"u\":return String.fromCharCode(B(4));case\"\\n\":return\"\";default:return b}}function B(a){var b=0;for(;a>0;--a){var c=parseInt(e(!0),16);isNaN(c)&&u(\"Invalid hex-character pattern in string\"),b=b<<4|c}return b}function D(){return N(\"Unterminated string constant\",function(){var a=e(),b=\"\";for(;;){var c=e(!0);if(c==\"\\\\\"){var d=0,f=null;c=r(function(a){if(a>=\"0\"&&a<=\"7\"){if(!f)return f=a,++d;if(f<=\"3\"&&d<=2)return++d;if(f>=\"4\"&&d<=1)return++d}return!1}),d>0?c=String.fromCharCode(parseInt(c,8)):c=z(!0)}else if(c==a)break;b+=c}return p(\"string\",b)})}function E(){e();var a=j(\"\\n\"),c;return a==-1?(c=b.text.substr(b.pos),b.pos=b.text.length):(c=b.text.substring(b.pos,a),b.pos=a),p(\"comment1\",c,!0)}function G(){return e(),N(\"Unterminated multiline comment\",function(){var a=j(\"*/\",!0),c=b.text.substring(b.pos,a),d=p(\"comment2\",c,!0);return b.pos=a+2,b.line+=c.split(\"\\n\").length-1,b.newline_before=c.indexOf(\"\\n\")>=0,/^@cc_on/i.test(c)&&(T(\"WARNING: at line \"+b.line),T('*** Found \"conditional comment\": '+c),T(\"*** UglifyJS DISCARDS ALL COMMENTS.  This means your code might no longer work properly in Internet Explorer.\")),d})}function H(){var a=!1,b=\"\",d;while((d=c())!=null)if(!a)if(d==\"\\\\\")a=!0,e();else if(x(d))b+=e();else break;else d!=\"u\"&&u(\"Expecting UnicodeEscapeSequence -- uXXXX\"),d=z(),x(d)||u(\"Unicode char: \"+d.charCodeAt(0)+\" is not valid in identifier\"),b+=d,a=!1;return b}function I(a){return N(\"Unterminated regular expression\",function(){var b=!1,c,d=!1;while(c=e(!0))if(b)a+=\"\\\\\"+c,b=!1;else if(c==\"[\")d=!0,a+=c;else if(c==\"]\"&&d)d=!1,a+=c;else{if(c==\"/\"&&!d)break;c==\"\\\\\"?b=!0:a+=c}var f=H();return p(\"regexp\",[a,f])})}function J(a){function b(a){if(!c())return a;var d=a+c();return S(l,d)?(e(),b(d)):a}return p(\"operator\",b(a||e()))}function K(){e();var a=b.regex_allowed;switch(c()){case\"/\":return b.comments_before.push(E()),b.regex_allowed=a,O();case\"*\":return b.comments_before.push(G()),b.regex_allowed=a,O()}return b.regex_allowed?I(\"\"):J(\"/\")}function L(){return e(),s(c())?v(\".\"):p(\"punc\",\".\")}function M(){var a=H();return S(d,a)?S(l,a)?p(\"operator\",a):S(g,a)?p(\"atom\",a):p(\"keyword\",a):p(\"name\",a)}function N(a,b){try{return b()}catch(c){if(c===C)u(a);else throw c}}function O(a){if(a!=null)return I(a);q(),k();var b=c();if(!b)return p(\"eof\");if(s(b))return v();if(b=='\"'||b==\"'\")return D();if(S(o,b))return p(\"punc\",e());if(b==\".\")return L();if(b==\"/\")return K();if(S(h,b))return J();if(b==\"\\\\\"||w(b))return M();u(\"Unexpected character '\"+b+\"'\")}var b={text:a.replace(/\\r\\n?|[\\n\\u2028\\u2029]/g,\"\\n\").replace(/^\\uFEFF/,\"\"),pos:0,tokpos:0,line:0,tokline:0,col:0,tokcol:0,newline_before:!1,regex_allowed:!1,comments_before:[]};return O.context=function(a){return a&&(b=a),b},O}function K(a,b,c){this.name=a,this.start=b,this.end=c}function L(a,b,c){function e(a,b){return B(d.token,a,b)}function f(){return d.peeked||(d.peeked=d.input())}function g(){return d.prev=d.token,d.peeked?(d.token=d.peeked,d.peeked=null):d.token=d.input(),d.token}function h(){return d.prev}function i(a,b,c,e){var f=d.input.context();A(a,b!=null?b:f.tokline,c!=null?c:f.tokcol,e!=null?e:f.tokpos)}function j(a,b){i(b,a.line,a.col)}function k(a){a==null&&(a=d.token),j(a,\"Unexpected token: \"+a.type+\" (\"+a.value+\")\")}function l(a,b){if(e(a,b))return g();j(d.token,\"Unexpected token \"+d.token.type+\", expected \"+a)}function m(a){return l(\"punc\",a)}function n(){return!b&&(d.token.nlb||e(\"eof\")||e(\"punc\",\"}\"))}function o(){e(\"punc\",\";\")?g():n()||k()}function p(){return P(arguments)}function q(){m(\"(\");var a=bk();return m(\")\"),a}function r(a,b,c){return a instanceof K?a:new K(a,b,c)}function s(a){return c?function(){var b=d.token,c=a.apply(this,arguments);return c[0]=r(c[0],b,h()),c}:a}function u(a){d.labels.push(a);var c=d.token,e=t();return b&&!S(I,e[0])&&k(c),d.labels.pop(),p(\"label\",a,e)}function v(){return p(\"stat\",N(bk,o))}function w(a){var b;return n()||(b=e(\"name\")?d.token.value:null),b!=null?(g(),R(b,d.labels)||i(\"Label \"+b+\" without matching loop or statement\")):d.in_loop==0&&i(a+\" not inside a loop or switch\"),o(),p(a,b)}function x(){m(\"(\");var a=null;if(!e(\"punc\",\";\")){a=e(\"keyword\",\"var\")?(g(),V(!0)):bk(!0,!0);if(e(\"operator\",\"in\"))return z(a)}return y(a)}function y(a){m(\";\");var b=e(\"punc\",\";\")?null:bk();m(\";\");var c=e(\"punc\",\")\")?null:bk();return m(\")\"),p(\"for\",a,b,c,bl(t))}function z(a){var b=a[0]==\"var\"?p(\"name\",a[1][0]):a;g();var c=bk();return m(\")\"),p(\"for-in\",a,b,c,bl(t))}function L(){var a=q(),b=t(),c;return e(\"keyword\",\"else\")&&(g(),c=t()),p(\"if\",a,b,c)}function O(){m(\"{\");var a=[];while(!e(\"punc\",\"}\"))e(\"eof\")&&k(),a.push(t());return g(),a}function T(){var a=O(),b,c;if(e(\"keyword\",\"catch\")){g(),m(\"(\"),e(\"name\")||i(\"Name expected\");var f=d.token.value;g(),m(\")\"),b=[f,O()]}return e(\"keyword\",\"finally\")&&(g(),c=O()),!b&&!c&&i(\"Missing catch/finally blocks\"),p(\"try\",a,b,c)}function U(a){var b=[];for(;;){e(\"name\")||k();var c=d.token.value;g(),e(\"operator\",\"=\")?(g(),b.push([c,bk(!1,a)])):b.push([c]);if(!e(\"punc\",\",\"))break;g()}return b}function V(a){return p(\"var\",U(a))}function W(){return p(\"const\",U())}function X(){var a=Y(!1),b;return e(\"punc\",\"(\")?(g(),b=Z(\")\")):b=[],bc(p(\"new\",a,b),!0)}function Z(a,b,c){var d=!0,f=[];while(!e(\"punc\",a)){d?d=!1:m(\",\");if(b&&e(\"punc\",a))break;e(\"punc\",\",\")&&c?f.push([\"atom\",\"undefined\"]):f.push(bk(!1))}return g(),f}function $(){return p(\"array\",Z(\"]\",!b,!0))}function _(){var a=!0,c=[];while(!e(\"punc\",\"}\")){a?a=!1:m(\",\");if(!b&&e(\"punc\",\"}\"))break;var f=d.token.type,h=ba();f!=\"name\"||h!=\"get\"&&h!=\"set\"||!!e(\"punc\",\":\")?(m(\":\"),c.push([h,bk(!1)])):c.push([bb(),C(!1),h])}return g(),p(\"object\",c)}function ba(){switch(d.token.type){case\"num\":case\"string\":return N(d.token.value,g)}return bb()}function bb(){switch(d.token.type){case\"name\":case\"operator\":case\"keyword\":case\"atom\":return N(d.token.value,g);default:k()}}function bc(a,b){return e(\"punc\",\".\")?(g(),bc(p(\"dot\",a,bb()),b)):e(\"punc\",\"[\")?(g(),bc(p(\"sub\",a,N(bk,M(m,\"]\"))),b)):b&&e(\"punc\",\"(\")?(g(),bc(p(\"call\",a,Z(\")\")),!0)):a}function bd(a){if(e(\"operator\")&&S(E,d.token.value))return be(\"unary-prefix\",N(d.token.value,g),bd(a));var b=Y(a);while(e(\"operator\")&&S(F,d.token.value)&&!d.token.nlb)b=be(\"unary-postfix\",d.token.value,b),g();return b}function be(a,b,c){return(b==\"++\"||b==\"--\")&&!bi(c)&&i(\"Invalid use of \"+b+\" operator\"),p(a,b,c)}function bf(a,b,c){var f=e(\"operator\")?d.token.value:null;f&&f==\"in\"&&c&&(f=null);var h=f!=null?H[f]:null;if(h!=null&&h>b){g();var i=bf(bd(!0),h,c);return bf(p(\"binary\",f,a,i),b,c)}return a}function bg(a){return bf(bd(!0),0,a)}function bh(a){var b=bg(a);if(e(\"operator\",\"?\")){g();var c=bk(!1);return m(\":\"),p(\"conditional\",b,c,bk(!1,a))}return b}function bi(a){if(!b)return!0;switch(a[0]+\"\"){case\"dot\":case\"sub\":case\"new\":case\"call\":return!0;case\"name\":return a[1]!=\"this\"}}function bj(a){var b=bh(a),c=d.token.value;if(e(\"operator\")&&S(G,c)){if(bi(b))return g(),p(\"assign\",G[c],b,bj(a));i(\"Invalid assignment\")}return b}function bl(a){try{return++d.in_loop,a()}finally{--d.in_loop}}var d={input:typeof a==\"string\"?D(a,!0):a,token:null,prev:null,peeked:null,in_function:0,in_loop:0,labels:[]};d.token=g();var t=s(function(){if(e(\"operator\",\"/\")||e(\"operator\",\"/=\"))d.peeked=null,d.token=d.input(d.token.value.substr(1));switch(d.token.type){case\"num\":case\"string\":case\"regexp\":case\"operator\":case\"atom\":return v();case\"name\":return B(f(),\"punc\",\":\")?u(N(d.token.value,g,g)):v();case\"punc\":switch(d.token.value){case\"{\":return p(\"block\",O());case\"[\":case\"(\":return v();case\";\":return g(),p(\"block\");default:k()};case\"keyword\":switch(N(d.token.value,g)){case\"break\":return w(\"break\");case\"continue\":return w(\"continue\");case\"debugger\":return o(),p(\"debugger\");case\"do\":return function(a){return l(\"keyword\",\"while\"),p(\"do\",N(q,o),a)}(bl(t));case\"for\":return x();case\"function\":return C(!0);case\"if\":return L();case\"return\":return d.in_function==0&&i(\"'return' outside of function\"),p(\"return\",e(\"punc\",\";\")?(g(),null):n()?null:N(bk,o));case\"switch\":return p(\"switch\",q(),Q());case\"throw\":return d.token.nlb&&i(\"Illegal newline after 'throw'\"),p(\"throw\",N(bk,o));case\"try\":return T();case\"var\":return N(V,o);case\"const\":return N(W,o);case\"while\":return p(\"while\",q(),bl(t));case\"with\":return p(\"with\",q(),t());default:k()}}}),C=s(function(a){var b=e(\"name\")?N(d.token.value,g):null;return a&&!b&&k(),m(\"(\"),p(a?\"defun\":\"function\",b,function(a,b){while(!e(\"punc\",\")\"))a?a=!1:m(\",\"),e(\"name\")||k(),b.push(d.token.value),g();return g(),b}(!0,[]),function(){++d.in_function;var a=d.in_loop;d.in_loop=0;var b=O();return--d.in_function,d.in_loop=a,b}())}),Q=M(bl,function(){m(\"{\");var a=[],b=null;while(!e(\"punc\",\"}\"))e(\"eof\")&&k(),e(\"keyword\",\"case\")?(g(),b=[],a.push([bk(),b]),m(\":\")):e(\"keyword\",\"default\")?(g(),m(\":\"),b=[],a.push([null,b])):(b||k(),b.push(t()));return g(),a}),Y=s(function(a){if(e(\"operator\",\"new\"))return g(),X();if(e(\"punc\")){switch(d.token.value){case\"(\":return g(),bc(N(bk,M(m,\")\")),a);case\"[\":return g(),bc($(),a);case\"{\":return g(),bc(_(),a)}k()}if(e(\"keyword\",\"function\"))return g(),bc(C(!1),a);if(S(J,d.token.type)){var b=d.token.type==\"regexp\"?p(\"regexp\",d.token.value[0],d.token.value[1]):p(d.token.type,d.token.value);return bc(N(b,g),a)}k()}),bk=s(function(a,b){arguments.length==0&&(a=!0);var c=bj(b);return a&&e(\"punc\",\",\")?(g(),p(\"seq\",c,bk(!0,b))):c});return p(\"toplevel\",function(a){while(!e(\"eof\"))a.push(t());return a}([]))}function M(a){var b=P(arguments,1);return function(){return a.apply(this,b.concat(P(arguments)))}}function N(a){a instanceof Function&&(a=a());for(var b=1,c=arguments.length;--c>0;++b)arguments[b]();return a}function O(a){var b={};for(var c=0;c<a.length;++c)b[a[c]]=!0;return b}function P(a,b){return Array.prototype.slice.call(a,b||0)}function Q(a){return a.split(\"\")}function R(a,b){for(var c=b.length;--c>=0;)if(b[c]===a)return!0;return!1}function S(a,b){return Object.prototype.hasOwnProperty.call(a,b)}var d=O([\"break\",\"case\",\"catch\",\"const\",\"continue\",\"default\",\"delete\",\"do\",\"else\",\"finally\",\"for\",\"function\",\"if\",\"in\",\"instanceof\",\"new\",\"return\",\"switch\",\"throw\",\"try\",\"typeof\",\"var\",\"void\",\"while\",\"with\"]),e=O([\"abstract\",\"boolean\",\"byte\",\"char\",\"class\",\"debugger\",\"double\",\"enum\",\"export\",\"extends\",\"final\",\"float\",\"goto\",\"implements\",\"import\",\"int\",\"interface\",\"long\",\"native\",\"package\",\"private\",\"protected\",\"public\",\"short\",\"static\",\"super\",\"synchronized\",\"throws\",\"transient\",\"volatile\"]),f=O([\"return\",\"new\",\"delete\",\"throw\",\"else\",\"case\"]),g=O([\"false\",\"null\",\"true\",\"undefined\"]),h=O(Q(\"+-*&%=<>!?|~^\")),i=/^0x[0-9a-f]+$/i,j=/^0[0-7]+$/,k=/^\\d*\\.?\\d*(?:e[+-]?\\d*(?:\\d\\.?|\\.?\\d)\\d*)?$/i,l=O([\"in\",\"instanceof\",\"typeof\",\"new\",\"void\",\"delete\",\"++\",\"--\",\"+\",\"-\",\"!\",\"~\",\"&\",\"|\",\"^\",\"*\",\"/\",\"%\",\">>\",\"<<\",\">>>\",\"<\",\">\",\"<=\",\">=\",\"==\",\"===\",\"!=\",\"!==\",\"?\",\"=\",\"+=\",\"-=\",\"/=\",\"*=\",\"%=\",\">>=\",\"<<=\",\">>>=\",\"|=\",\"^=\",\"&=\",\"&&\",\"||\"]),m=O(Q(\"  \\n\\r\\t\\f\u000b​᠎             　\")),n=O(Q(\"[{}(,.;:\")),o=O(Q(\"[]{}(),;:\")),p=O(Q(\"gmsiy\")),q={letter:new RegExp(\"[\\\\u0041-\\\\u005A\\\\u0061-\\\\u007A\\\\u00AA\\\\u00B5\\\\u00BA\\\\u00C0-\\\\u00D6\\\\u00D8-\\\\u00F6\\\\u00F8-\\\\u02C1\\\\u02C6-\\\\u02D1\\\\u02E0-\\\\u02E4\\\\u02EC\\\\u02EE\\\\u0370-\\\\u0374\\\\u0376\\\\u0377\\\\u037A-\\\\u037D\\\\u0386\\\\u0388-\\\\u038A\\\\u038C\\\\u038E-\\\\u03A1\\\\u03A3-\\\\u03F5\\\\u03F7-\\\\u0481\\\\u048A-\\\\u0523\\\\u0531-\\\\u0556\\\\u0559\\\\u0561-\\\\u0587\\\\u05D0-\\\\u05EA\\\\u05F0-\\\\u05F2\\\\u0621-\\\\u064A\\\\u066E\\\\u066F\\\\u0671-\\\\u06D3\\\\u06D5\\\\u06E5\\\\u06E6\\\\u06EE\\\\u06EF\\\\u06FA-\\\\u06FC\\\\u06FF\\\\u0710\\\\u0712-\\\\u072F\\\\u074D-\\\\u07A5\\\\u07B1\\\\u07CA-\\\\u07EA\\\\u07F4\\\\u07F5\\\\u07FA\\\\u0904-\\\\u0939\\\\u093D\\\\u0950\\\\u0958-\\\\u0961\\\\u0971\\\\u0972\\\\u097B-\\\\u097F\\\\u0985-\\\\u098C\\\\u098F\\\\u0990\\\\u0993-\\\\u09A8\\\\u09AA-\\\\u09B0\\\\u09B2\\\\u09B6-\\\\u09B9\\\\u09BD\\\\u09CE\\\\u09DC\\\\u09DD\\\\u09DF-\\\\u09E1\\\\u09F0\\\\u09F1\\\\u0A05-\\\\u0A0A\\\\u0A0F\\\\u0A10\\\\u0A13-\\\\u0A28\\\\u0A2A-\\\\u0A30\\\\u0A32\\\\u0A33\\\\u0A35\\\\u0A36\\\\u0A38\\\\u0A39\\\\u0A59-\\\\u0A5C\\\\u0A5E\\\\u0A72-\\\\u0A74\\\\u0A85-\\\\u0A8D\\\\u0A8F-\\\\u0A91\\\\u0A93-\\\\u0AA8\\\\u0AAA-\\\\u0AB0\\\\u0AB2\\\\u0AB3\\\\u0AB5-\\\\u0AB9\\\\u0ABD\\\\u0AD0\\\\u0AE0\\\\u0AE1\\\\u0B05-\\\\u0B0C\\\\u0B0F\\\\u0B10\\\\u0B13-\\\\u0B28\\\\u0B2A-\\\\u0B30\\\\u0B32\\\\u0B33\\\\u0B35-\\\\u0B39\\\\u0B3D\\\\u0B5C\\\\u0B5D\\\\u0B5F-\\\\u0B61\\\\u0B71\\\\u0B83\\\\u0B85-\\\\u0B8A\\\\u0B8E-\\\\u0B90\\\\u0B92-\\\\u0B95\\\\u0B99\\\\u0B9A\\\\u0B9C\\\\u0B9E\\\\u0B9F\\\\u0BA3\\\\u0BA4\\\\u0BA8-\\\\u0BAA\\\\u0BAE-\\\\u0BB9\\\\u0BD0\\\\u0C05-\\\\u0C0C\\\\u0C0E-\\\\u0C10\\\\u0C12-\\\\u0C28\\\\u0C2A-\\\\u0C33\\\\u0C35-\\\\u0C39\\\\u0C3D\\\\u0C58\\\\u0C59\\\\u0C60\\\\u0C61\\\\u0C85-\\\\u0C8C\\\\u0C8E-\\\\u0C90\\\\u0C92-\\\\u0CA8\\\\u0CAA-\\\\u0CB3\\\\u0CB5-\\\\u0CB9\\\\u0CBD\\\\u0CDE\\\\u0CE0\\\\u0CE1\\\\u0D05-\\\\u0D0C\\\\u0D0E-\\\\u0D10\\\\u0D12-\\\\u0D28\\\\u0D2A-\\\\u0D39\\\\u0D3D\\\\u0D60\\\\u0D61\\\\u0D7A-\\\\u0D7F\\\\u0D85-\\\\u0D96\\\\u0D9A-\\\\u0DB1\\\\u0DB3-\\\\u0DBB\\\\u0DBD\\\\u0DC0-\\\\u0DC6\\\\u0E01-\\\\u0E30\\\\u0E32\\\\u0E33\\\\u0E40-\\\\u0E46\\\\u0E81\\\\u0E82\\\\u0E84\\\\u0E87\\\\u0E88\\\\u0E8A\\\\u0E8D\\\\u0E94-\\\\u0E97\\\\u0E99-\\\\u0E9F\\\\u0EA1-\\\\u0EA3\\\\u0EA5\\\\u0EA7\\\\u0EAA\\\\u0EAB\\\\u0EAD-\\\\u0EB0\\\\u0EB2\\\\u0EB3\\\\u0EBD\\\\u0EC0-\\\\u0EC4\\\\u0EC6\\\\u0EDC\\\\u0EDD\\\\u0F00\\\\u0F40-\\\\u0F47\\\\u0F49-\\\\u0F6C\\\\u0F88-\\\\u0F8B\\\\u1000-\\\\u102A\\\\u103F\\\\u1050-\\\\u1055\\\\u105A-\\\\u105D\\\\u1061\\\\u1065\\\\u1066\\\\u106E-\\\\u1070\\\\u1075-\\\\u1081\\\\u108E\\\\u10A0-\\\\u10C5\\\\u10D0-\\\\u10FA\\\\u10FC\\\\u1100-\\\\u1159\\\\u115F-\\\\u11A2\\\\u11A8-\\\\u11F9\\\\u1200-\\\\u1248\\\\u124A-\\\\u124D\\\\u1250-\\\\u1256\\\\u1258\\\\u125A-\\\\u125D\\\\u1260-\\\\u1288\\\\u128A-\\\\u128D\\\\u1290-\\\\u12B0\\\\u12B2-\\\\u12B5\\\\u12B8-\\\\u12BE\\\\u12C0\\\\u12C2-\\\\u12C5\\\\u12C8-\\\\u12D6\\\\u12D8-\\\\u1310\\\\u1312-\\\\u1315\\\\u1318-\\\\u135A\\\\u1380-\\\\u138F\\\\u13A0-\\\\u13F4\\\\u1401-\\\\u166C\\\\u166F-\\\\u1676\\\\u1681-\\\\u169A\\\\u16A0-\\\\u16EA\\\\u1700-\\\\u170C\\\\u170E-\\\\u1711\\\\u1720-\\\\u1731\\\\u1740-\\\\u1751\\\\u1760-\\\\u176C\\\\u176E-\\\\u1770\\\\u1780-\\\\u17B3\\\\u17D7\\\\u17DC\\\\u1820-\\\\u1877\\\\u1880-\\\\u18A8\\\\u18AA\\\\u1900-\\\\u191C\\\\u1950-\\\\u196D\\\\u1970-\\\\u1974\\\\u1980-\\\\u19A9\\\\u19C1-\\\\u19C7\\\\u1A00-\\\\u1A16\\\\u1B05-\\\\u1B33\\\\u1B45-\\\\u1B4B\\\\u1B83-\\\\u1BA0\\\\u1BAE\\\\u1BAF\\\\u1C00-\\\\u1C23\\\\u1C4D-\\\\u1C4F\\\\u1C5A-\\\\u1C7D\\\\u1D00-\\\\u1DBF\\\\u1E00-\\\\u1F15\\\\u1F18-\\\\u1F1D\\\\u1F20-\\\\u1F45\\\\u1F48-\\\\u1F4D\\\\u1F50-\\\\u1F57\\\\u1F59\\\\u1F5B\\\\u1F5D\\\\u1F5F-\\\\u1F7D\\\\u1F80-\\\\u1FB4\\\\u1FB6-\\\\u1FBC\\\\u1FBE\\\\u1FC2-\\\\u1FC4\\\\u1FC6-\\\\u1FCC\\\\u1FD0-\\\\u1FD3\\\\u1FD6-\\\\u1FDB\\\\u1FE0-\\\\u1FEC\\\\u1FF2-\\\\u1FF4\\\\u1FF6-\\\\u1FFC\\\\u2071\\\\u207F\\\\u2090-\\\\u2094\\\\u2102\\\\u2107\\\\u210A-\\\\u2113\\\\u2115\\\\u2119-\\\\u211D\\\\u2124\\\\u2126\\\\u2128\\\\u212A-\\\\u212D\\\\u212F-\\\\u2139\\\\u213C-\\\\u213F\\\\u2145-\\\\u2149\\\\u214E\\\\u2183\\\\u2184\\\\u2C00-\\\\u2C2E\\\\u2C30-\\\\u2C5E\\\\u2C60-\\\\u2C6F\\\\u2C71-\\\\u2C7D\\\\u2C80-\\\\u2CE4\\\\u2D00-\\\\u2D25\\\\u2D30-\\\\u2D65\\\\u2D6F\\\\u2D80-\\\\u2D96\\\\u2DA0-\\\\u2DA6\\\\u2DA8-\\\\u2DAE\\\\u2DB0-\\\\u2DB6\\\\u2DB8-\\\\u2DBE\\\\u2DC0-\\\\u2DC6\\\\u2DC8-\\\\u2DCE\\\\u2DD0-\\\\u2DD6\\\\u2DD8-\\\\u2DDE\\\\u2E2F\\\\u3005\\\\u3006\\\\u3031-\\\\u3035\\\\u303B\\\\u303C\\\\u3041-\\\\u3096\\\\u309D-\\\\u309F\\\\u30A1-\\\\u30FA\\\\u30FC-\\\\u30FF\\\\u3105-\\\\u312D\\\\u3131-\\\\u318E\\\\u31A0-\\\\u31B7\\\\u31F0-\\\\u31FF\\\\u3400\\\\u4DB5\\\\u4E00\\\\u9FC3\\\\uA000-\\\\uA48C\\\\uA500-\\\\uA60C\\\\uA610-\\\\uA61F\\\\uA62A\\\\uA62B\\\\uA640-\\\\uA65F\\\\uA662-\\\\uA66E\\\\uA67F-\\\\uA697\\\\uA717-\\\\uA71F\\\\uA722-\\\\uA788\\\\uA78B\\\\uA78C\\\\uA7FB-\\\\uA801\\\\uA803-\\\\uA805\\\\uA807-\\\\uA80A\\\\uA80C-\\\\uA822\\\\uA840-\\\\uA873\\\\uA882-\\\\uA8B3\\\\uA90A-\\\\uA925\\\\uA930-\\\\uA946\\\\uAA00-\\\\uAA28\\\\uAA40-\\\\uAA42\\\\uAA44-\\\\uAA4B\\\\uAC00\\\\uD7A3\\\\uF900-\\\\uFA2D\\\\uFA30-\\\\uFA6A\\\\uFA70-\\\\uFAD9\\\\uFB00-\\\\uFB06\\\\uFB13-\\\\uFB17\\\\uFB1D\\\\uFB1F-\\\\uFB28\\\\uFB2A-\\\\uFB36\\\\uFB38-\\\\uFB3C\\\\uFB3E\\\\uFB40\\\\uFB41\\\\uFB43\\\\uFB44\\\\uFB46-\\\\uFBB1\\\\uFBD3-\\\\uFD3D\\\\uFD50-\\\\uFD8F\\\\uFD92-\\\\uFDC7\\\\uFDF0-\\\\uFDFB\\\\uFE70-\\\\uFE74\\\\uFE76-\\\\uFEFC\\\\uFF21-\\\\uFF3A\\\\uFF41-\\\\uFF5A\\\\uFF66-\\\\uFFBE\\\\uFFC2-\\\\uFFC7\\\\uFFCA-\\\\uFFCF\\\\uFFD2-\\\\uFFD7\\\\uFFDA-\\\\uFFDC]\"),non_spacing_mark:new RegExp(\"[\\\\u0300-\\\\u036F\\\\u0483-\\\\u0487\\\\u0591-\\\\u05BD\\\\u05BF\\\\u05C1\\\\u05C2\\\\u05C4\\\\u05C5\\\\u05C7\\\\u0610-\\\\u061A\\\\u064B-\\\\u065E\\\\u0670\\\\u06D6-\\\\u06DC\\\\u06DF-\\\\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\\\\u09C1-\\\\u09C4\\\\u09CD\\\\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\\\\u0B3F\\\\u0B41-\\\\u0B44\\\\u0B4D\\\\u0B56\\\\u0B62\\\\u0B63\\\\u0B82\\\\u0BC0\\\\u0BCD\\\\u0C3E-\\\\u0C40\\\\u0C46-\\\\u0C48\\\\u0C4A-\\\\u0C4D\\\\u0C55\\\\u0C56\\\\u0C62\\\\u0C63\\\\u0CBC\\\\u0CBF\\\\u0CC6\\\\u0CCC\\\\u0CCD\\\\u0CE2\\\\u0CE3\\\\u0D41-\\\\u0D44\\\\u0D4D\\\\u0D62\\\\u0D63\\\\u0DCA\\\\u0DD2-\\\\u0DD4\\\\u0DD6\\\\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\\\\u20D0-\\\\u20DC\\\\u20E1\\\\u20E5-\\\\u20F0\\\\u2CEF-\\\\u2CF1\\\\u2DE0-\\\\u2DFF\\\\u302A-\\\\u302F\\\\u3099\\\\u309A\\\\uA66F\\\\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\\\\uFB1E\\\\uFE00-\\\\uFE0F\\\\uFE20-\\\\uFE26]\"),space_combining_mark:new RegExp(\"[\\\\u0903\\\\u093E-\\\\u0940\\\\u0949-\\\\u094C\\\\u094E\\\\u0982\\\\u0983\\\\u09BE-\\\\u09C0\\\\u09C7\\\\u09C8\\\\u09CB\\\\u09CC\\\\u09D7\\\\u0A03\\\\u0A3E-\\\\u0A40\\\\u0A83\\\\u0ABE-\\\\u0AC0\\\\u0AC9\\\\u0ACB\\\\u0ACC\\\\u0B02\\\\u0B03\\\\u0B3E\\\\u0B40\\\\u0B47\\\\u0B48\\\\u0B4B\\\\u0B4C\\\\u0B57\\\\u0BBE\\\\u0BBF\\\\u0BC1\\\\u0BC2\\\\u0BC6-\\\\u0BC8\\\\u0BCA-\\\\u0BCC\\\\u0BD7\\\\u0C01-\\\\u0C03\\\\u0C41-\\\\u0C44\\\\u0C82\\\\u0C83\\\\u0CBE\\\\u0CC0-\\\\u0CC4\\\\u0CC7\\\\u0CC8\\\\u0CCA\\\\u0CCB\\\\u0CD5\\\\u0CD6\\\\u0D02\\\\u0D03\\\\u0D3E-\\\\u0D40\\\\u0D46-\\\\u0D48\\\\u0D4A-\\\\u0D4C\\\\u0D57\\\\u0D82\\\\u0D83\\\\u0DCF-\\\\u0DD1\\\\u0DD8-\\\\u0DDF\\\\u0DF2\\\\u0DF3\\\\u0F3E\\\\u0F3F\\\\u0F7F\\\\u102B\\\\u102C\\\\u1031\\\\u1038\\\\u103B\\\\u103C\\\\u1056\\\\u1057\\\\u1062-\\\\u1064\\\\u1067-\\\\u106D\\\\u1083\\\\u1084\\\\u1087-\\\\u108C\\\\u108F\\\\u109A-\\\\u109C\\\\u17B6\\\\u17BE-\\\\u17C5\\\\u17C7\\\\u17C8\\\\u1923-\\\\u1926\\\\u1929-\\\\u192B\\\\u1930\\\\u1931\\\\u1933-\\\\u1938\\\\u19B0-\\\\u19C0\\\\u19C8\\\\u19C9\\\\u1A19-\\\\u1A1B\\\\u1A55\\\\u1A57\\\\u1A61\\\\u1A63\\\\u1A64\\\\u1A6D-\\\\u1A72\\\\u1B04\\\\u1B35\\\\u1B3B\\\\u1B3D-\\\\u1B41\\\\u1B43\\\\u1B44\\\\u1B82\\\\u1BA1\\\\u1BA6\\\\u1BA7\\\\u1BAA\\\\u1C24-\\\\u1C2B\\\\u1C34\\\\u1C35\\\\u1CE1\\\\u1CF2\\\\uA823\\\\uA824\\\\uA827\\\\uA880\\\\uA881\\\\uA8B4-\\\\uA8C3\\\\uA952\\\\uA953\\\\uA983\\\\uA9B4\\\\uA9B5\\\\uA9BA\\\\uA9BB\\\\uA9BD-\\\\uA9C0\\\\uAA2F\\\\uAA30\\\\uAA33\\\\uAA34\\\\uAA4D\\\\uAA7B\\\\uABE3\\\\uABE4\\\\uABE6\\\\uABE7\\\\uABE9\\\\uABEA\\\\uABEC]\"),connector_punctuation:new RegExp(\"[\\\\u005F\\\\u203F\\\\u2040\\\\u2054\\\\uFE33\\\\uFE34\\\\uFE4D-\\\\uFE4F\\\\uFF3F]\")};z.prototype.toString=function(){return this.message+\" (line: \"+this.line+\", col: \"+this.col+\", pos: \"+this.pos+\")\"+\"\\n\\n\"+this.stack};var C={},E=O([\"typeof\",\"void\",\"delete\",\"--\",\"++\",\"!\",\"~\",\"-\",\"+\"]),F=O([\"--\",\"++\"]),G=function(a,b,c){while(c<a.length)b[a[c]]=a[c].substr(0,a[c].length-1),c++;return b}([\"+=\",\"-=\",\"/=\",\"*=\",\"%=\",\">>=\",\"<<=\",\">>>=\",\"|=\",\"^=\",\"&=\"],{\"=\":!0},0),H=function(a,b){for(var c=0,d=1;c<a.length;++c,++d){var e=a[c];for(var f=0;f<e.length;++f)b[e[f]]=d}return b}([[\"||\"],[\"&&\"],[\"|\"],[\"^\"],[\"&\"],[\"==\",\"===\",\"!=\",\"!==\"],[\"<\",\">\",\"<=\",\">=\",\"in\",\"instanceof\"],[\">>\",\"<<\",\">>>\"],[\"+\",\"-\"],[\"*\",\"/\",\"%\"]],{}),I=O([\"for\",\"do\",\"while\",\"switch\"]),J=O([\"atom\",\"num\",\"string\",\"regexp\",\"name\"]);K.prototype.toString=function(){return this.name};var T=function(){};b.tokenizer=D,b.parse=L,b.slice=P,b.curry=M,b.member=R,b.array_to_hash=O,b.PRECEDENCE=H,b.KEYWORDS_ATOM=g,b.RESERVED_WORDS=e,b.KEYWORDS=d,b.ATOMIC_START_TOKEN=J,b.OPERATORS=l,b.is_alphanumeric_char=t,b.set_logger=function(a){T=a}}),f(\"lib/process\",[\"require\",\"exports\",\"module\",\"./parse-js\"],function(a,b,c){function i(){function a(a){return[this[0],K(a,function(a){var b=[a[0]];return a.length>1&&(b[1]=g(a[1])),b})]}function b(a){var b=[this[0]];return a!=null&&b.push(K(a,g)),b}function g(a){if(a==null)return null;try{f.push(a);var b=a[0],e=d[b];if(e){var g=e.apply(a,a.slice(1));if(g!=null)return g}return e=c[b],e.apply(a,a.slice(1))}finally{f.pop()}}function h(a){if(a==null)return null;try{return f.push(a),c[a[0]].apply(a,a.slice(1))}finally{f.pop()}}function i(a,b){var c={},e;for(e in a)J(a,e)&&(c[e]=d[e],d[e]=a[e]);var f=b();for(e in c)J(c,e)&&(c[e]?d[e]=c[e]:delete d[e]);return f}var c={string:function(a){return[this[0],a]},num:function(a){return[this[0],a]},name:function(a){return[this[0],a]},toplevel:function(a){return[this[0],K(a,g)]},block:b,splice:b,\"var\":a,\"const\":a,\"try\":function(a,b,c){return[this[0],K(a,g),b!=null?[b[0],K(b[1],g)]:null,c!=null?K(c,g):null]},\"throw\":function(a){return[this[0],g(a)]},\"new\":function(a,b){return[this[0],g(a),K(b,g)]},\"switch\":function(a,b){return[this[0],g(a),K(b,function(a){return[a[0]?g(a[0]):null,K(a[1],g)]})]},\"break\":function(a){return[this[0],a]},\"continue\":function(a){return[this[0],a]},conditional:function(a,b,c){return[this[0],g(a),g(b),g(c)]},assign:function(a,b,c){return[this[0],a,g(b),g(c)]},dot:function(a){return[this[0],g(a)].concat(e(arguments,1))},call:function(a,b){return[this[0],g(a),K(b,g)]},\"function\":function(a,b,c){return[this[0],a,b.slice(),K(c,g)]},defun:function(a,b,c){return[this[0],a,b.slice(),K(c,g)]},\"if\":function(a,b,c){return[this[0],g(a),g(b),g(c)]},\"for\":function(a,b,c,d){return[this[0],g(a),g(b),g(c),g(d)]},\"for-in\":function(a,b,c,d){return[this[0],g(a),g(b),g(c),g(d)]},\"while\":function(a,b){return[this[0],g(a),g(b)]},\"do\":function(a,b){return[this[0],g(a),g(b)]},\"return\":function(a){return[this[0],g(a)]},binary:function(a,b,c){return[this[0],a,g(b),g(c)]},\"unary-prefix\":function(a,b){return[this[0],a,g(b)]},\"unary-postfix\":function(a,b){return[this[0],a,g(b)]},sub:function(a,b){return[this[0],g(a),g(b)]},object:function(a){return[this[0],K(a,function(a){return a.length==2?[a[0],g(a[1])]:[a[0],g(a[1]),a[2]]})]},regexp:function(a,b){return[this[0],a,b]},array:function(a){return[this[0],K(a,g)]},stat:function(a){return[this[0],g(a)]},seq:function(){return[this[0]].concat(K(e(arguments),g))},label:function(a,b){return[this[0],a,g(b)]},\"with\":function(a,b){return[this[0],g(a),g(b)]},atom:function(a){return[this[0],a]}},d={},f=[];return{walk:g,dive:h,with_walkers:i,parent:function(){return f[f.length-2]},stack:function(){return f}}}function j(a){this.names={},this.mangled={},this.rev_mangled={},this.cname=-1,this.refs={},this.uses_with=!1,this.uses_eval=!1,this.parent=a,this.children=[],a?(this.level=a.level+1,a.children.push(this)):this.level=0}function l(a){function f(a){b=new j(b);var c=b.body=a();return c.scope=b,b=b.parent,c}function g(a,c){return b.define(a,c)}function h(a){b.refs[a]=!0}function k(a,b,c){var e=this[0]==\"defun\";return[this[0],e?g(a,\"defun\"):a,b,f(function(){return e||g(a,\"lambda\"),K(b,function(a){g(a,\"arg\")}),K(c,d)})]}function l(a){return function(b){K(b,function(b){g(b[0],a),b[1]&&h(b[0])})}}var b=null,c=i(),d=c.walk,e=[];return f(function(){function i(a,b){for(b=a.children.length;--b>=0;)i(a.children[b]);for(b in a.refs)if(J(a.refs,b))for(var c=a.has(b),d=a;d;d=d.parent){d.refs[b]=c;if(d===c)break}}var f=c.with_walkers({\"function\":k,defun:k,label:function(a,b){g(a,\"label\")},\"break\":function(a){a&&h(a)},\"continue\":function(a){a&&h(a)},\"with\":function(a,c){for(var d=b;d;d=d.parent)d.uses_with=!0},\"var\":l(\"var\"),\"const\":l(\"const\"),\"try\":function(a,b,c){if(b!=null)return[this[0],K(a,d),[g(b[0],\"catch\"),K(b[1],d)],c!=null?K(c,d):null]},name:function(a){a==\"eval\"&&e.push(b),h(a)}},function(){return d(a)});return K(e,function(a){if(!a.has(\"eval\"))while(a)a.uses_eval=!0,a=a.parent}),i(b),f})}function m(a,b){function g(a,c){return!b.toplevel&&!e.parent?a:b.except&&f(a,b.except)?a:e.get_mangled(a,c)}function h(a){if(b.defines)return!e.has(a)&&J(b.defines,a)?b.defines[a]:null}function j(a,b,c){var f=this[0]==\"defun\",h;return a&&(f?a=g(a):(h={},!e.uses_eval&&!e.uses_with?a=h[a]=e.next_mangled():h[a]=a)),c=k(c.scope,function(){return b=K(b,function(a){return g(a)}),K(c,d)},h),[this[0],a,b,c]}function k(a,b,c){var d=e;e=a;if(c)for(var f in c)J(c,f)&&a.set_mangle(f,c[f]);for(var f in a.names)J(a.names,f)&&g(f,!0);var h=b();return h.scope=a,e=d,h}function m(a){return[this[0],K(a,function(a){return[g(a[0]),d(a[1])]})]}var c=i(),d=c.walk,e;return b=b||{},c.with_walkers({\"function\":j,defun:function(){var a=j.apply(this,arguments);switch(c.parent()[0]){case\"toplevel\":case\"function\":case\"defun\":return K.at_top(a)}return a},label:function(a,b){return[this[0],g(a),d(b)]},\"break\":function(a){if(a)return[this[0],g(a)]},\"continue\":function(a){if(a)return[this[0],g(a)]},\"var\":m,\"const\":m,name:function(a){return h(a)||[this[0],g(a)]},\"try\":function(a,b,c){return[this[0],K(a,d),b!=null?[g(b[0]),K(b[1],d)]:null,c!=null?K(c,d):null]},toplevel:function(a){var b=this;return k(b.scope,function(){return[b[0],K(a,d)]})}},function(){return d(l(a))})}function o(a,b){return E(a).length>E(b[0]==\"stat\"?b[1]:b).length?b:a}function p(a){return a[0]==\"block\"&&a[1]&&a[1].length>0?a[1][a[1].length-1]:a}function q(a){if(a)switch(p(a)[0]){case\"return\":case\"break\":case\"continue\":case\"throw\":return!0}}function r(a){return a[0]==\"unary-prefix\"&&f(a[1],[\"!\",\"delete\"])||a[0]==\"binary\"&&f(a[1],[\"in\",\"instanceof\",\"==\",\"!=\",\"===\",\"!==\",\"<\",\"<=\",\">=\",\">\"])||a[0]==\"binary\"&&f(a[1],[\"&&\",\"||\"])&&r(a[2])&&r(a[3])||a[0]==\"conditional\"&&r(a[2])&&r(a[3])||a[0]==\"assign\"&&a[1]===!0&&r(a[3])||a[0]==\"seq\"&&r(a[a.length-1])}function s(a){return!a||a[0]==\"block\"&&(!a[1]||a[1].length==0)}function t(a){return a[0]==\"string\"||a[0]==\"unary-prefix\"&&a[1]==\"typeof\"||a[0]==\"binary\"&&a[1]==\"+\"&&(t(a[2])||t(a[3]))}function v(a){s(a)||n(\"Dropping unreachable code: \"+E(a,!0))}function w(a){function d(a){a=K(a,c);for(var b=0;b<a.length;++b){var e=a[b];if(e[0]!=\"if\")continue;if(e[3]&&c(e[3]))continue;var f=c(e[2]);if(!q(f))continue;var g=c(e[1]),h=a.slice(b+1),i=h.length==1?h[0]:[\"block\",h],j=a.slice(0,b).concat([[e[0],g,f,i]]);return d(j)}return a}function e(a,b,c){return c=d(c),[this[0],a,b,c]}function f(a){return[this[0],a!=null?d(a):null]}var b=i(),c=b.walk;return b.with_walkers({defun:e,\"function\":e,block:f,splice:f,toplevel:function(a){return[this[0],d(a)]},\"try\":function(a,b,c){return[this[0],d(a),b!=null?[b[0],d(b[1])]:null,c!=null?d(c):null]}},function(){return c(a)})}function x(a,b){function g(){throw e}function h(){throw f}function j(){return b.call(this,this,c,g,h)}function k(a){if(a==\"++\"||a==\"--\")return j.apply(this,arguments)}var c=i(),d=c.walk,e={},f={};return c.with_walkers({\"try\":j,\"throw\":j,\"return\":j,\"new\":j,\"switch\":j,\"break\":j,\"continue\":j,assign:j,call:j,\"if\":j,\"for\":j,\"for-in\":j,\"while\":j,\"do\":j,\"return\":j,\"unary-prefix\":k,\"unary-postfix\":k,defun:j},function(){for(;;)try{d(a);break}catch(b){if(b===e)break;if(b===f)continue;throw b}})}function y(a){function e(a,b){var e=d;d=b,a=K(a,c);var f={},g=K(b.names,function(a,c){return a!=\"var\"?K.skip:b.references(c)?(f[c]=!0,[c]):K.skip});return g.length>0&&(x([\"block\",a],function(a,b,c,d){if(a[0]==\"assign\"&&a[1]===!0&&a[2][0]==\"name\"&&J(f,a[2][1])){for(var e=g.length;--e>=0;)if(g[e][0]==a[2][1]){g[e][1]&&c(),g[e][1]=a[3],g.push(g.splice(e,1)[0]);break}var h=b.parent();if(h[0]==\"seq\"){var i=h[2];i.unshift(0,h.length),h.splice.apply(h,i)}else h[0]==\"stat\"?h.splice(0,h.length,\"block\"):c();d()}c()}),a.unshift([\"var\",g])),d=e,a}function f(a){var c=null;for(var d=a.length;--d>=0;){var e=a[d];if(!e[1])continue;e=[\"assign\",!0,[\"name\",e[0]],e[1]],c==null?c=e:c=[\"seq\",e,c]}return c==null?b.parent()[0]==\"for-in\"?[\"name\",a[0][0]]:K.skip:[\"stat\",c]}function g(a){return[this[0],e(a,this.scope)]}var b=i(),c=b.walk,d;return b.with_walkers({\"function\":function(a,b,c){for(var d=b.length;--d>=0&&!c.scope.references(b[d]);)b.pop();return c.scope.references(a)||(a=null),[this[0],a,b,e(c,c.scope)]},defun:function(a,b,c){if(!d.references(a))return K.skip;for(var f=b.length;--f>=0&&!c.scope.references(b[f]);)b.pop();return[this[0],a,b,e(c,c.scope)]},\"var\":f,toplevel:g},function(){return c(l(a))})}function z(a,b){function h(a){var c=[\"unary-prefix\",\"!\",a];switch(a[0]){case\"unary-prefix\":return a[1]==\"!\"&&r(a[2])?a[2]:c;case\"seq\":return a=e(a),a[a.length-1]=h(a[a.length-1]),a;case\"conditional\":return o(c,[\"conditional\",a[1],h(a[2]),h(a[3])]);case\"binary\":var d=a[1],f=a[2],g=a[3];if(!b.keep_comps)switch(d){case\"<=\":return[\"binary\",\">\",f,g];case\"<\":return[\"binary\",\">=\",f,g];case\">=\":return[\"binary\",\"<\",f,g];case\">\":return[\"binary\",\"<=\",f,g]}switch(d){case\"==\":return[\"binary\",\"!=\",f,g];case\"!=\":return[\"binary\",\"==\",f,g];case\"===\":return[\"binary\",\"!==\",f,g];case\"!==\":return[\"binary\",\"===\",f,g];case\"&&\":return o(c,[\"binary\",\"||\",h(f),h(g)]);case\"||\":return o(c,[\"binary\",\"&&\",h(f),h(g)])}}return c}function j(a,b,c){var d=function(){return a[0]==\"unary-prefix\"&&a[1]==\"!\"?c?[\"conditional\",a[2],c,b]:[\"binary\",\"||\",a[2],b]:c?o([\"conditional\",a,b,c],[\"conditional\",h(a),c,b]):[\"binary\",\"&&\",a,b]};return u(a,function(a,d){return v(d?c:b),d?b:c},d)}function k(a,b){var c=g;g=a;var d=b();return d.scope=a,g=c,d}function m(a){return a!=null&&a[0]==\"block\"&&a[1]&&(a[1].length==1?a=a[1][0]:a[1].length==0&&(a=[\"block\"])),a}function p(a,b,c){var d=this[0]==\"defun\";return c=k(c.scope,function(){var b=t(c,\"lambda\");return!d&&a&&!g.references(a)&&(a=null),b}),[this[0],a,b,c]}function t(a,c){return a=K(a,d),a=a.reduce(function(a,b){return b[0]==\"block\"?b[1]&&a.push.apply(a,b[1]):a.push(b),a},[]),a=function(b,c){return a.forEach(function(a){c&&(a[0]==\"var\"&&c[0]==\"var\"||a[0]==\"const\"&&c[0]==\"const\")?c[1]=c[1].concat(a[1]):(b.push(a),c=a)}),b}([]),b.dead_code&&(a=function(c,d){return a.forEach(function(a){d?a[0]==\"function\"||a[0]==\"defun\"?c.push(a):a[0]==\"var\"||a[0]==\"const\"?(b.no_warnings||n(\"Variables declared in unreachable code\"),a[1]=K(a[1],function(a){return a[1]&&!b.no_warnings&&v([\"assign\",!0,[\"name\",a[0]],a[1]]),[a[0]]}),c.push(a)):b.no_warnings||v(a):(c.push(a),f(a[0],[\"return\",\"throw\",\"break\",\"continue\"])&&(d=!0))}),c}([])),b.make_seqs&&(a=function(b,c){return a.forEach(function(a){c&&c[0]==\"stat\"&&a[0]==\"stat\"?c[1]=[\"seq\",c[1],a[1]]:(b.push(a),c=a)}),b.length>=2&&b[b.length-2][0]==\"stat\"&&(b[b.length-1][0]==\"return\"||b[b.length-1][0]==\"throw\")&&b[b.length-1][1]&&b.splice(b.length-2,2,[b[b.length-1][0],[\"seq\",b[b.length-2][1],b[b.length-1][1]]]),b}([])),a}function x(a,b,c){return u(a,function(a,e){return e?(b=d(b),v(c),b||[\"block\"]):(c=d(c),v(b),c||[\"block\"])},function(){return y(a,b,c)})}function y(a,b,c){a=d(a),b=d(b),c=d(c),s(b)?(a=h(a),b=c,c=null):s(c)?c=null:function(){var d=E(a),e=h(a),f=E(e);if(f.length<d.length){var g=b;b=c,c=g,a=e}}();if(s(c)&&s(b))return[\"stat\",a];var e=[\"if\",a,b,c];return b[0]==\"if\"&&s(b[3])&&s(c)?e=o(e,d([\"if\",[\"binary\",\"&&\",a,b[1]],b[2]])):b[0]==\"stat\"?c?c[0]==\"stat\"&&(e=o(e,[\"stat\",j(a,b[1],c[1])])):e=o(e,[\"stat\",j(a,b[1])]):c&&b[0]==c[0]&&(b[0]==\"return\"||b[0]==\"throw\")&&b[1]&&c[1]?e=o(e,[b[0],j(a,b[1],c[1])]):c&&q(b)?(e=[[\"if\",a,b]],c[0]==\"block\"?c[1]&&(e=e.concat(c[1])):e.push(c),e=d([\"block\",e])):b&&q(c)&&(e=[[\"if\",h(a),c]],b[0]==\"block\"?b[1]&&(e=e.concat(b[1])):e.push(b),e=d([\"block\",e])),e}function z(a,b){return u(a,function(a,c){return c?[\"for\",null,null,null,d(b)]:(v(b),[\"block\"])})}b=H(b,{make_seqs:!0,dead_code:!0,no_warnings:!1,keep_comps:!0});var c=i(),d=c.walk,g;return c.with_walkers({sub:function(a,b){if(b[0]==\"string\"){var c=b[1];if(I(c))return[\"dot\",d(a),c];if(/^[1-9][0-9]*$/.test(c)||c===\"0\")return[\"sub\",d(a),[\"num\",parseInt(c,10)]]}},\"if\":x,toplevel:function(a){return[\"toplevel\",k(this.scope,function(){return t(a)})]},\"switch\":function(a,b){var c=b.length-1;return[\"switch\",d(a),K(b,function(a,b){var e=t(a[1]);if(b==c&&e.length>0){var f=e[e.length-1];f[0]==\"break\"&&!f[1]&&e.pop()}return[a[0]?d(a[0]):null,e]})]},\"function\":p,defun:p,block:function(a){if(a)return m([\"block\",t(a)])},binary:function(a,b,c){return u([\"binary\",a,d(b),d(c)],function(a){return o(d(a),this)},function(){return function(){if(a!=\"==\"&&a!=\"!=\")return;var e=d(b),f=d(c);return e&&e[0]==\"unary-prefix\"&&e[1]==\"!\"&&e[2][0]==\"num\"?b=[\"num\",+!e[2][1]]:f&&f[0]==\"unary-prefix\"&&f[1]==\"!\"&&f[2][0]==\"num\"&&(c=[\"num\",+!f[2][1]]),[\"binary\",a,b,c]}()||this})},conditional:function(a,b,c){return j(d(a),d(b),d(c))},\"try\":function(a,b,c){return[\"try\",t(a),b!=null?[b[0],t(b[1])]:null,c!=null?t(c):null]},\"unary-prefix\":function(a,b){b=d(b);var c=[\"unary-prefix\",a,b];return a==\"!\"&&(c=o(c,h(b))),u(c,function(a,b){return d(a)},function(){return c})},name:function(a){switch(a){case\"true\":return[\"unary-prefix\",\"!\",[\"num\",0]];case\"false\":return[\"unary-prefix\",\"!\",[\"num\",1]]}},\"while\":z,assign:function(a,b,c){b=d(b),c=d(c);var e=[\"+\",\"-\",\"/\",\"*\",\"%\",\">>\",\"<<\",\">>>\",\"|\",\"^\",\"&\"];return a===!0&&b[0]===\"name\"&&c[0]===\"binary\"&&~e.indexOf(c[1])&&c[2][0]===\"name\"&&c[2][1]===b[1]?[this[0],c[1],b,c[3]]:[this[0],a,b,c]}},function(){for(var b=0;b<2;++b)a=w(a),a=l(a),a=d(a);return a})}function B(a,b){var c=0,d=0;return a=a.replace(/[\\\\\\b\\f\\n\\r\\t\\x22\\x27\\u2028\\u2029\\0]/g,function(a){switch(a){case\"\\\\\":return\"\\\\\\\\\";case\"\\b\":return\"\\\\b\";case\"\\f\":return\"\\\\f\";case\"\\n\":return\"\\\\n\";case\"\\r\":return\"\\\\r\";case\"\\t\":return\"\\\\t\";case\"\\u2028\":return\"\\\\u2028\";case\"\\u2029\":return\"\\\\u2029\";case'\"':return++c,'\"';case\"'\":return++d,\"'\";case\"\\0\":return\"\\\\0\"}return a}),b&&(a=C(a)),c>d?\"'\"+a.replace(/\\x27/g,\"\\\\'\")+\"'\":'\"'+a.replace(/\\x22/g,'\\\\\"')+'\"'}function C(a){return a.replace(/[\\u0080-\\uffff]/g,function(a){var b=a.charCodeAt(0).toString(16);while(b.length<4)b=\"0\"+b;return\"\\\\u\"+b})}function E(a,b){function m(a){var c=B(a,b.ascii_only);return b.inline_script&&(c=c.replace(/<\\x2fscript([>/\\t\\n\\f\\r ])/gi,\"<\\\\/script$1\")),c}function n(a){return a=a.toString(),b.ascii_only&&(a=C(a)),a}function o(a){return a==null&&(a=\"\"),c&&(a=G(\" \",b.indent_start+j*b.indent_level)+a),a}function p(a,b){b==null&&(b=1),j+=b;try{return a.apply(null,e(arguments,1))}finally{j-=b}}function q(a){if(c)return a.join(\" \");var b=[];for(var d=0;d<a.length;++d){var e=a[d+1];b.push(a[d]),e&&(/[a-z0-9_\\x24]$/i.test(a[d].toString())&&/^[a-z0-9_\\x24]/i.test(e.toString())||/[\\+\\-]$/.test(a[d].toString())&&/^[\\+\\-]/.test(e.toString()))&&b.push(\" \")}return b.join(\"\")}function r(a){return a.join(\",\"+l)}function t(a){var b=y(a);for(var c=1;c<arguments.length;++c){var d=arguments[c];if(d instanceof Function&&d(a)||a[0]==d)return\"(\"+b+\")\"}return b}function u(a){if(a.length==1)return a[0];if(a.length==2){var b=a[1];return a=a[0],a.length>b.length?b:a}return u([a[0],u(a.slice(1))])}function v(a){if(a[0]==\"function\"||a[0]==\"object\"){var b=e(x.stack()),c=b.pop(),d=b.pop();while(d){if(d[0]==\"stat\")return!0;if((d[0]==\"seq\"||d[0]==\"call\"||d[0]==\"dot\"||d[0]==\"sub\"||d[0]==\"conditional\")&&d[1]===c||(d[0]==\"binary\"||d[0]==\"assign\"||d[0]==\"unary-postfix\")&&d[2]===c)c=d,d=b.pop();else return!1}}return!J(A,a[0])}function w(a){var b=a.toString(10),c=[b.replace(/^0\\./,\".\")],d;return Math.floor(a)===a?(a<0?c.push(\"-0x\"+(-a).toString(16).toLowerCase(),\"-0\"+(-a).toString(8)):c.push(\"0x\"+a.toString(16).toLowerCase(),\"0\"+a.toString(8)),(d=/^(.*?)(0+)$/.exec(a))&&c.push(d[1]+\"e\"+d[2].length)):(d=/^0?\\.(0+)(.*)$/.exec(a))&&c.push(d[2]+\"e-\"+(d[1].length+d[2].length),b.substr(b.indexOf(\".\"))),u(c)}function z(a){if(a==null)return\";\";if(a[0]==\"do\")return N([a]);var b=a;for(;;){var c=b[0];if(c==\"if\"){if(!b[3])return y([\"block\",[a]]);b=b[3]}else if(c==\"while\"||c==\"do\")b=b[2];else if(c==\"for\"||c==\"for-in\")b=b[4];else break}return y(a)}function E(a,b,c,d){var e=d||\"function\";return a&&(e+=\" \"+n(a)),e+=\"(\"+r(K(b,n))+\")\",e=q([e,N(c)]),v(this)?\"(\"+e+\")\":e}function F(a){switch(a[0]){case\"with\":case\"while\":return s(a[2]);case\"for\":case\"for-in\":return s(a[4]);case\"if\":if(s(a[2])&&!a[3])return!0;if(a[3])return s(a[3])?!0:F(a[3]);return F(a[2])}}function L(a,b){for(var d=[],e=a.length-1,f=0;f<=e;++f){var g=a[f],h=y(g);h!=\";\"&&(!c&&f==e&&!F(g)&&(h=h.replace(/;+\\s*$/,\"\")),d.push(h))}return b?d:K(d,o)}function M(a){var b=a.length;return b==0?\"{}\":\"{\"+k+K(a,function(a,d){var e=a[1].length>0,f=p(function(){return o(a[0]?q([\"case\",y(a[0])+\":\"]):\"default:\")},.5)+(e?k+p(function(){return L(a[1]).join(k)}):\"\");return!c&&e&&d<b-1&&(f+=\";\"),f}).join(k)+k+o(\"}\")}function N(a){return a?a.length==0?\"{}\":\"{\"+k+p(function(){return L(a).join(k)})+k+o(\"}\"):\";\"}function O(a){var b=a[0],c=a[1];return c!=null&&(b=q([n(b),\"=\",t(c,\"seq\")])),b}b=H(b,{indent_start:0,indent_level:4,quote_keys:!1,space_colon:!1,beautify:!1,ascii_only:!1,inline_script:!1});var c=!!b.beautify,j=0,k=c?\"\\n\":\"\",l=c?\" \":\"\",x=i(),y=x.walk;return x.with_walkers({string:m,num:w,name:n,toplevel:function(a){return L(a).join(k+k)},splice:function(a){var b=x.parent();return J(D,b)?N.apply(this,arguments):K(L(a,!0),function(a,b){return b>0?o(a):a}).join(k)},block:N,\"var\":function(a){return\"var \"+r(K(a,O))+\";\"},\"const\":function(a){return\"const \"+r(K(a,O))+\";\"},\"try\":function(a,b,c){var d=[\"try\",N(a)];return b&&d.push(\"catch\",\"(\"+b[0]+\")\",N(b[1])),c&&d.push(\"finally\",N(c)),q(d)},\"throw\":function(a){return q([\"throw\",y(a)])+\";\"},\"new\":function(a,b){return b=b.length>0?\"(\"+r(K(b,function(a){return t(a,\"seq\")}))+\")\":\"\",q([\"new\",t(a,\"seq\",\"binary\",\"conditional\",\"assign\",function(a){var b=i(),c={};try{b.with_walkers({call:function(){throw c},\"function\":function(){return this}},function(){b.walk(a)})}catch(d){if(d===c)return!0;throw d}})+b])},\"switch\":function(a,b){return q([\"switch\",\"(\"+y(a)+\")\",M(b)])},\"break\":function(a){var b=\"break\";return a!=null&&(b+=\" \"+n(a)),b+\";\"},\"continue\":function(a){var b=\"continue\";return a!=null&&(b+=\" \"+n(a)),b+\";\"},conditional:function(a,b,c){return q([t(a,\"assign\",\"seq\",\"conditional\"),\"?\",t(b,\"seq\"),\":\",t(c,\"seq\")])},assign:function(a,b,c){return a&&a!==!0?a+=\"=\":a=\"=\",q([y(b),a,t(c,\"seq\")])},dot:function(a){var b=y(a),c=1;a[0]==\"num\"?/\\./.test(a[1])||(b+=\".\"):v(a)&&(b=\"(\"+b+\")\");while(c<arguments.length)b+=\".\"+n(arguments[c++]);return b},call:function(a,b){var c=y(a);return c.charAt(0)!=\"(\"&&v(a)&&(c=\"(\"+c+\")\"),c+\"(\"+r(K(b,function(a){return t(a,\"seq\")}))+\")\"},\"function\":E,defun:E,\"if\":function(a,b,c){var d=[\"if\",\"(\"+y(a)+\")\",c?z(b):y(b)];return c&&d.push(\"else\",y(c)),q(d)},\"for\":function(a,b,c,d){var e=[\"for\"];a=(a!=null?y(a):\"\").replace(/;*\\s*$/,\";\"+l),b=(b!=null?y(b):\"\").replace(/;*\\s*$/,\";\"+l),c=(c!=null?y(c):\"\").replace(/;*\\s*$/,\"\");var f=a+b+c;return f==\"; ; \"&&(f=\";;\"),e.push(\"(\"+f+\")\",y(d)),q(e)},\"for-in\":function(a,b,c,d){return q([\"for\",\"(\"+(a?y(a).replace(/;+$/,\"\"):y(b)),\"in\",y(c)+\")\",y(d)])},\"while\":function(a,b){return q([\"while\",\"(\"+y(a)+\")\",y(b)])},\"do\":function(a,b){return q([\"do\",y(b),\"while\",\"(\"+y(a)+\")\"])+\";\"},\"return\":function(a){var b=[\"return\"];return a!=null&&b.push(y(a)),q(b)+\";\"},binary:function(a,d,e){var h=y(d),i=y(e);if(f(d[0],[\"assign\",\"conditional\",\"seq\"])||d[0]==\"binary\"&&g[a]>g[d[1]]||d[0]==\"function\"&&v(this))h=\"(\"+h+\")\";return f(e[0],[\"assign\",\"conditional\",\"seq\"])||e[0]==\"binary\"&&g[a]>=g[e[1]]&&(e[1]!=a||!f(a,[\"&&\",\"||\",\"*\"]))?i=\"(\"+i+\")\":!c&&b.inline_script&&(a==\"<\"||a==\"<<\")&&e[0]==\"regexp\"&&/^script/i.test(e[1])&&(i=\" \"+i),q([h,a,i])},\"unary-prefix\":function(a,b){var c=y(b);return b[0]==\"num\"||b[0]==\"unary-prefix\"&&!J(h,a+b[1])||!v(b)||(c=\"(\"+c+\")\"),a+(d.is_alphanumeric_char(a.charAt(0))?\" \":\"\")+c},\"unary-postfix\":function(a,b){var c=y(b);return b[0]==\"num\"||b[0]==\"unary-postfix\"&&!J(h,a+b[1])||!v(b)||(c=\"(\"+c+\")\"),c+a},sub:function(a,b){var c=y(a);return v(a)&&(c=\"(\"+c+\")\"),c+\"[\"+y(b)+\"]\"},object:function(a){var d=v(this);if(a.length==0)return d?\"({})\":\"{}\";var e=\"{\"+k+p(function(){return K(a,function(a){if(a.length==3)return o(E(a[0],a[1][2],a[1][3],a[2]));var d=a[0],e=t(a[1],\"seq\");return b.quote_keys?d=m(d):(typeof d==\"number\"||!c&&+d+\"\"==d)&&parseFloat(d)>=0?d=w(+d):I(d)||(d=m(d)),o(q(c&&b.space_colon?[d,\":\",e]:[d+\":\",e]))}).join(\",\"+k)})+k+o(\"}\");return d?\"(\"+e+\")\":e},regexp:function(a,b){return\"/\"+a+\"/\"+b},array:function(a){return a.length==0?\"[]\":q([\"[\",r(K(a,function(b,d){return!c&&b[0]==\"atom\"&&b[1]==\"undefined\"?d===a.length-1?\",\":\"\":t(b,\"seq\")})),\"]\"])},stat:function(a){return y(a).replace(/;*\\s*$/,\";\")},seq:function(){return r(K(e(arguments),y))},label:function(a,b){return q([n(a),\":\",y(b)])},\"with\":function(a,b){return q([\"with\",\"(\"+y(a)+\")\",y(b)])},atom:function(a){return n(a)}},function(){return y(a)})}function F(a,b){var c=[0];return d.parse(function(){function h(a){return a.pos-f}function i(a){f=a.pos,c.push(f)}function j(){var a=e.apply(this,arguments);c:{if(g&&g.type==\"keyword\")break c;if(h(a)>b)switch(a.type){case\"keyword\":case\"atom\":case\"name\":case\"punc\":i(a);break c}}return g=a,a}var e=d.tokenizer(a),f=0,g;return j.context=function(){return e.context.apply(this,arguments)},j}()),c.map(function(b,d){return a.substring(b,c[d+1]||a.length)}).join(\"\\n\")}function G(a,b){if(b>0){if(b==1)return a;var c=G(a,b>>1);return c+=c,b&1&&(c+=a),c}return\"\"}function H(a,b){var c={};a===!0&&(a={});for(var d in b)J(b,d)&&(c[d]=a&&J(a,d)?a[d]:b[d]);return c}function I(a){return/^[a-z_$][a-z0-9_$]*$/i.test(a)&&a!=\"this\"&&!J(d.KEYWORDS_ATOM,a)&&!J(d.RESERVED_WORDS,a)&&!J(d.KEYWORDS,a)}function J(a,b){return Object.prototype.hasOwnProperty.call(a,b)}var d=a(\"./parse-js\"),e=d.slice,f=d.member,g=d.PRECEDENCE,h=d.OPERATORS,k=function(){var a=\"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ$_\";return function(b){var c=\"\";do c=a.charAt(b%54)+c,b=Math.floor(b/54);while(b>0);return c}}();j.prototype={has:function(a){for(var b=this;b;b=b.parent)if(J(b.names,a))return b},has_mangled:function(a){for(var b=this;b;b=b.parent)if(J(b.rev_mangled,a))return b},toJSON:function(){return{names:this.names,uses_eval:this.uses_eval,uses_with:this.uses_with}},next_mangled:function(){for(;;){var a=k(++this.cname),b;b=this.has_mangled(a);if(b&&this.refs[b.rev_mangled[a]]===b)continue;b=this.has(a);if(b&&b!==this&&this.refs[a]===b&&!b.has_mangled(a))continue;if(J(this.refs,a)&&this.refs[a]==null)continue;if(!I(a))continue;return a}},set_mangle:function(a,b){return this.rev_mangled[b]=a,this.mangled[a]=b},get_mangled:function(a,b){if(this.uses_eval||this.uses_with)return a;var c=this.has(a);return c?J(c.mangled,a)?c.mangled[a]:b?c.set_mangle(a,c.next_mangled()):a:a},references:function(a){return a&&!this.parent||this.uses_with||this.uses_eval||this.refs[a]},define:function(a,b){if(a!=null){if(b==\"var\"||!J(this.names,a))this.names[a]=b||\"var\";return a}}};var n=function(){},u=function(){function b(c){switch(c[0]){case\"string\":case\"num\":return c[1];case\"name\":case\"atom\":switch(c[1]){case\"true\":return!0;case\"false\":return!1;case\"null\":return null}break;case\"unary-prefix\":switch(c[1]){case\"!\":return!b(c[2]);case\"typeof\":return typeof b(c[2]);case\"~\":return~b(c[2]);case\"-\":return-b(c[2]);case\"+\":return+b(c[2])}break;case\"binary\":var d=c[2],e=c[3];switch(c[1]){case\"&&\":return b(d)&&b(e);case\"||\":return b(d)||b(e);case\"|\":return b(d)|b(e);case\"&\":return b(d)&b(e);case\"^\":return b(d)^b(e);case\"+\":return b(d)+b(e);case\"*\":return b(d)*b(e);case\"/\":return b(d)/b(e);case\"%\":return b(d)%b(e);case\"-\":return b(d)-b(e);case\"<<\":return b(d)<<b(e);case\">>\":return b(d)>>b(e);case\">>>\":return b(d)>>>b(e);case\"==\":return b(d)==b(e);case\"===\":return b(d)===b(e);case\"!=\":return b(d)!=b(e);case\"!==\":return b(d)!==b(e);case\"<\":return b(d)<b(e);case\"<=\":return b(d)<=b(e);case\">\":return b(d)>b(e);case\">=\":return b(d)>=b(e);case\"in\":return b(d)in b(e);case\"instanceof\":return b(d)instanceof b(e)}}throw a}var a={};return function(c,d,e){try{var f=b(c),g;switch(typeof f){case\"string\":g=[\"string\",f];break;case\"number\":g=[\"num\",f];break;case\"boolean\":g=[\"name\",String(f)];break;default:throw new Error(\"Can't handle constant of type: \"+typeof f)}return d.call(c,g,f)}catch(h){if(h===a){if(c[0]!=\"binary\"||c[1]!=\"===\"&&c[1]!=\"!==\"||!(t(c[2])&&t(c[3])||r(c[2])&&r(c[3]))){if(e&&c[0]==\"binary\"&&(c[1]==\"||\"||c[1]==\"&&\"))try{var i=b(c[2]);c=c[1]==\"&&\"&&(i?c[3]:i)||c[1]==\"||\"&&(i?i:c[3])||c}catch(j){}}else c[1]=c[1].substr(0,2);return e?e.call(c,c):null}throw h}}}(),A=d.array_to_hash([\"name\",\"array\",\"object\",\"string\",\"dot\",\"sub\",\"call\",\"regexp\",\"defun\"]),D=d.array_to_hash([\"if\",\"while\",\"do\",\"for\",\"for-in\",\"with\"]),K;(function(){function b(a){this.v=a}function c(a){this.v=a}K=function(d,e,f){function j(){var j=e.call(f,d[i],i);j instanceof b?(j=j.v,j instanceof c?h.push.apply(h,j.v):h.push(j)):j!=a&&(j instanceof c?g.push.apply(g,j.v):g.push(j))}var g=[],h=[],i;if(d instanceof Array)for(i=0;i<d.length;++i)j();else for(i in d)J(d,i)&&j();return h.concat(g)},K.at_top=function(a){return new b(a)},K.splice=function(a){return new c(a)};var a=K.skip={}})(),b.ast_walker=i,b.ast_mangle=m,b.ast_squeeze=z,b.ast_lift_variables=y,b.gen_code=E,b.ast_add_scope=l,b.set_logger=function(a){n=a},b.make_string=B,b.split_lines=F,b.MAP=K}),f(\"uglify-js\",[\"require\",\"exports\",\"module\",\"./lib/parse-js\",\"./lib/process\"],function(a,b,c){function d(a,b){b||(b={});var c=d.parser,e=d.uglify,f=c.parse(a,b.strict_semicolons);f=e.ast_mangle(f,b.mangle_options),f=e.ast_squeeze(f,b.squeeze_options);var g=e.gen_code(f,b.gen_options);return g}d.parser=a(\"./lib/parse-js\"),d.uglify=a(\"./lib/process\"),c.exports=d}),f(\"lib/squeeze-more\",[\"require\",\"exports\",\"module\",\"./parse-js\",\"./process\"],function(a,b,c){function l(a){function f(a,b){var c=d,e;return d=a,e=b(),d=c,e}function g(a,b,d){return[this[0],a,b,f(d.scope,h(i,d,c))]}var b=e.ast_walker(),c=b.walk,d;return b.with_walkers({toplevel:function(a){return[this[0],f(this.scope,h(i,a,c))]},\"function\":g,defun:g,\"new\":function(a,b){if(a[0]==\"name\"&&a[1]==\"Array\"&&!d.has(\"Array\"))return b.length!=1?[\"array\",b]:c([\"call\",[\"name\",\"Array\"],b])},call:function(a,b){if(a[0]==\"dot\"&&a[2]==\"toString\"&&b.length==0)return[\"binary\",\"+\",a[1],[\"string\",\"\"]];if(a[0]==\"name\"&&a[1]==\"Array\"&&b.length!=1&&!d.has(\"Array\"))return[\"array\",b]}},function(){return c(e.ast_add_scope(a))})}var d=a(\"./parse-js\"),e=a(\"./process\"),f=d.slice,g=d.member,h=d.curry,i=e.MAP,j=d.PRECEDENCE,k=d.OPERATORS;b.ast_squeeze_more=l});if(!this.uglify){var g=this;e([\"uglify-js\",\"lib/process\",\"lib/squeeze-more\"],function(a,b,c){b.ast_squeeze_more=c.ast_squeeze_more,g.uglify=a;var d=g.define;typeof d==\"function\"&&d.amd&&d(\"uglifyweb\",function(){return a})},null,!0)}})()"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/sass-bootstrap/bower.json",
    "content": "{\n  \"name\": \"sass-bootstrap\",\n  \"version\": \"3.0.0\",\n  \"main\": [\"./dist/js/bootstrap.js\", \"./dist/css/bootstrap.css\"],\n  \"ignore\": [\n      \"**/.*\"\n  ],\n  \"dependencies\": {\n    \"jquery\": \">= 1.9.0\"\n  }\n}\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/sass-bootstrap/browserstack.json",
    "content": "{\n  \"username\": \"--secure--\",\n  \"key\": \"--secure--\",\n  \"test_path\": \"js/tests/index.html\",\n  \"browsers\":  [\n    {\n      \"browser\": \"firefox\",\n      \"browser_version\": \"latest\",\n      \"os\": \"OS X\",\n      \"os_version\": \"Mountain Lion\"\n    },\n    {\n      \"browser\": \"safari\",\n      \"browser_version\": \"latest\",\n      \"os\": \"OS X\",\n      \"os_version\": \"Mountain Lion\"\n    },\n    {\n      \"browser\": \"chrome\",\n      \"browser_version\": \"latest\",\n      \"os\": \"OS X\",\n      \"os_version\": \"Mountain Lion\"\n    },\n    {\n      \"browser\": \"firefox\",\n      \"browser_version\": \"latest\",\n      \"os\": \"Windows\",\n      \"os_version\": \"7\"\n    },\n    {\n      \"browser\": \"chrome\",\n      \"browser_version\": \"latest\",\n      \"os\": \"Windows\",\n      \"os_version\": \"7\"\n    }\n  ]\n}\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/sass-bootstrap/components.html",
    "content": "---\nlayout: default\ntitle: Components\nslug: components\nlead: \"Over a dozen reusable components built to provide iconography, dropdowns, navigation, alerts, popovers, and much more.\"\nbase_url: \"../\"\n---\n\n\n  <!-- Glyphicons\n  ================================================== -->\n  <div class=\"bs-docs-section\">\n    <div class=\"page-header\">\n      <h1 id=\"glyphicons\">Glyphicons</h1>\n    </div>\n\n    <h2 id=\"glyphicons-glyphs\">Available glyphs</h2>\n    <p>Includes 180 glyphs in font format from the Glyphicon Halflings set. <a href=\"http://glyphicons.com/\">Glyphicons</a> Halflings are normally not available for free, but their creator has made them available for Bootstrap free of cost. As a thank you, we only ask that you to include a link back to <a href=\"http://glyphicons.com/\">Glyphicons</a> whenever possible.</p>\n    <ul class=\"bs-glyphicons\">\n      <li><span class=\"glyphicon glyphicon-adjust\"></span> .glyphicon .glyphicon-adjust</li>\n      <li><span class=\"glyphicon glyphicon-align-center\"></span> .glyphicon .glyphicon-align-center</li>\n      <li><span class=\"glyphicon glyphicon-align-justify\"></span> .glyphicon .glyphicon-align-justify</li>\n      <li><span class=\"glyphicon glyphicon-align-left\"></span> .glyphicon .glyphicon-align-left</li>\n      <li><span class=\"glyphicon glyphicon-align-right\"></span> .glyphicon .glyphicon-align-right</li>\n      <li><span class=\"glyphicon glyphicon-arrow-down\"></span> .glyphicon .glyphicon-arrow-down</li>\n      <li><span class=\"glyphicon glyphicon-arrow-left\"></span> .glyphicon .glyphicon-arrow-left</li>\n      <li><span class=\"glyphicon glyphicon-arrow-right\"></span> .glyphicon .glyphicon-arrow-right</li>\n      <li><span class=\"glyphicon glyphicon-arrow-up\"></span> .glyphicon .glyphicon-arrow-up</li>\n      <li><span class=\"glyphicon glyphicon-asterisk\"></span> .glyphicon .glyphicon-asterisk</li>\n      <li><span class=\"glyphicon glyphicon-backward\"></span> .glyphicon .glyphicon-backward</li>\n      <li><span class=\"glyphicon glyphicon-ban-circle\"></span> .glyphicon .glyphicon-ban-circle</li>\n      <li><span class=\"glyphicon glyphicon-barcode\"></span> .glyphicon .glyphicon-barcode</li>\n      <li><span class=\"glyphicon glyphicon-bell\"></span> .glyphicon .glyphicon-bell</li>\n      <li><span class=\"glyphicon glyphicon-bold\"></span> .glyphicon .glyphicon-bold</li>\n      <li><span class=\"glyphicon glyphicon-book\"></span> .glyphicon .glyphicon-book</li>\n      <li><span class=\"glyphicon glyphicon-bookmark\"></span> .glyphicon .glyphicon-bookmark</li>\n      <li><span class=\"glyphicon glyphicon-briefcase\"></span> .glyphicon .glyphicon-briefcase</li>\n      <li><span class=\"glyphicon glyphicon-bullhorn\"></span> .glyphicon .glyphicon-bullhorn</li>\n      <li><span class=\"glyphicon glyphicon-calendar\"></span> .glyphicon .glyphicon-calendar</li>\n      <li><span class=\"glyphicon glyphicon-camera\"></span> .glyphicon .glyphicon-camera</li>\n      <li><span class=\"glyphicon glyphicon-certificate\"></span> .glyphicon .glyphicon-certificate</li>\n      <li><span class=\"glyphicon glyphicon-check\"></span> .glyphicon .glyphicon-check</li>\n      <li><span class=\"glyphicon glyphicon-chevron-down\"></span> .glyphicon .glyphicon-chevron-down</li>\n      <li><span class=\"glyphicon glyphicon-chevron-left\"></span> .glyphicon .glyphicon-chevron-left</li>\n      <li><span class=\"glyphicon glyphicon-chevron-right\"></span> .glyphicon .glyphicon-chevron-right</li>\n      <li><span class=\"glyphicon glyphicon-chevron-up\"></span> .glyphicon .glyphicon-chevron-up</li>\n      <li><span class=\"glyphicon glyphicon-circle-arrow-down\"></span> .glyphicon .glyphicon-circle-arrow-down</li>\n      <li><span class=\"glyphicon glyphicon-circle-arrow-left\"></span> .glyphicon .glyphicon-circle-arrow-left</li>\n      <li><span class=\"glyphicon glyphicon-circle-arrow-right\"></span> .glyphicon .glyphicon-circle-arrow-right</li>\n      <li><span class=\"glyphicon glyphicon-circle-arrow-up\"></span> .glyphicon .glyphicon-circle-arrow-up</li>\n      <li><span class=\"glyphicon glyphicon-cloud\"></span> .glyphicon .glyphicon-cloud</li>\n      <li><span class=\"glyphicon glyphicon-cloud-download\"></span> .glyphicon .glyphicon-cloud-download</li>\n      <li><span class=\"glyphicon glyphicon-cloud-upload\"></span> .glyphicon .glyphicon-cloud-upload</li>\n      <li><span class=\"glyphicon glyphicon-cog\"></span> .glyphicon .glyphicon-cog</li>\n      <li><span class=\"glyphicon glyphicon-collapse-down\"></span> .glyphicon .glyphicon-collapse-down</li>\n      <li><span class=\"glyphicon glyphicon-collapse-up\"></span> .glyphicon .glyphicon-collapse-up</li>\n      <li><span class=\"glyphicon glyphicon-comment\"></span> .glyphicon .glyphicon-comment</li>\n      <li><span class=\"glyphicon glyphicon-compressed\"></span> .glyphicon .glyphicon-compressed</li>\n      <li><span class=\"glyphicon glyphicon-copyright-mark\"></span> .glyphicon .glyphicon-copyright-mark</li>\n      <li><span class=\"glyphicon glyphicon-credit-card\"></span> .glyphicon .glyphicon-credit-card</li>\n      <li><span class=\"glyphicon glyphicon-cutlery\"></span> .glyphicon .glyphicon-cutlery</li>\n      <li><span class=\"glyphicon glyphicon-dashboard\"></span> .glyphicon .glyphicon-dashboard</li>\n      <li><span class=\"glyphicon glyphicon-download\"></span> .glyphicon .glyphicon-download</li>\n      <li><span class=\"glyphicon glyphicon-download-alt\"></span> .glyphicon .glyphicon-download-alt</li>\n      <li><span class=\"glyphicon glyphicon-earphone\"></span> .glyphicon .glyphicon-earphone</li>\n      <li><span class=\"glyphicon glyphicon-edit\"></span> .glyphicon .glyphicon-edit</li>\n      <li><span class=\"glyphicon glyphicon-eject\"></span> .glyphicon .glyphicon-eject</li>\n      <li><span class=\"glyphicon glyphicon-envelope\"></span> .glyphicon .glyphicon-envelope</li>\n      <li><span class=\"glyphicon glyphicon-euro\"></span> .glyphicon .glyphicon-euro</li>\n      <li><span class=\"glyphicon glyphicon-exclamation-sign\"></span> .glyphicon .glyphicon-exclamation-sign</li>\n      <li><span class=\"glyphicon glyphicon-expand\"></span> .glyphicon .glyphicon-expand</li>\n      <li><span class=\"glyphicon glyphicon-export\"></span> .glyphicon .glyphicon-export</li>\n      <li><span class=\"glyphicon glyphicon-eye-close\"></span> .glyphicon .glyphicon-eye-close</li>\n      <li><span class=\"glyphicon glyphicon-eye-open\"></span> .glyphicon .glyphicon-eye-open</li>\n      <li><span class=\"glyphicon glyphicon-facetime-video\"></span> .glyphicon .glyphicon-facetime-video</li>\n      <li><span class=\"glyphicon glyphicon-fast-backward\"></span> .glyphicon .glyphicon-fast-backward</li>\n      <li><span class=\"glyphicon glyphicon-fast-forward\"></span> .glyphicon .glyphicon-fast-forward</li>\n      <li><span class=\"glyphicon glyphicon-file\"></span> .glyphicon .glyphicon-file</li>\n      <li><span class=\"glyphicon glyphicon-film\"></span> .glyphicon .glyphicon-film</li>\n      <li><span class=\"glyphicon glyphicon-filter\"></span> .glyphicon .glyphicon-filter</li>\n      <li><span class=\"glyphicon glyphicon-fire\"></span> .glyphicon .glyphicon-fire</li>\n      <li><span class=\"glyphicon glyphicon-flag\"></span> .glyphicon .glyphicon-flag</li>\n      <li><span class=\"glyphicon glyphicon-flash\"></span> .glyphicon .glyphicon-flash</li>\n      <li><span class=\"glyphicon glyphicon-floppy-disk\"></span> .glyphicon .glyphicon-floppy-disk</li>\n      <li><span class=\"glyphicon glyphicon-floppy-open\"></span> .glyphicon .glyphicon-floppy-open</li>\n      <li><span class=\"glyphicon glyphicon-floppy-remove\"></span> .glyphicon .glyphicon-floppy-remove</li>\n      <li><span class=\"glyphicon glyphicon-floppy-save\"></span> .glyphicon .glyphicon-floppy-save</li>\n      <li><span class=\"glyphicon glyphicon-floppy-saved\"></span> .glyphicon .glyphicon-floppy-saved</li>\n      <li><span class=\"glyphicon glyphicon-folder-close\"></span> .glyphicon .glyphicon-folder-close</li>\n      <li><span class=\"glyphicon glyphicon-folder-open\"></span> .glyphicon .glyphicon-folder-open</li>\n      <li><span class=\"glyphicon glyphicon-font\"></span> .glyphicon .glyphicon-font</li>\n      <li><span class=\"glyphicon glyphicon-forward\"></span> .glyphicon .glyphicon-forward</li>\n      <li><span class=\"glyphicon glyphicon-fullscreen\"></span> .glyphicon .glyphicon-fullscreen</li>\n      <li><span class=\"glyphicon glyphicon-gbp\"></span> .glyphicon .glyphicon-gbp</li>\n      <li><span class=\"glyphicon glyphicon-gift\"></span> .glyphicon .glyphicon-gift</li>\n      <li><span class=\"glyphicon glyphicon-glass\"></span> .glyphicon .glyphicon-glass</li>\n      <li><span class=\"glyphicon glyphicon-globe\"></span> .glyphicon .glyphicon-globe</li>\n      <li><span class=\"glyphicon glyphicon-hand-down\"></span> .glyphicon .glyphicon-hand-down</li>\n      <li><span class=\"glyphicon glyphicon-hand-left\"></span> .glyphicon .glyphicon-hand-left</li>\n      <li><span class=\"glyphicon glyphicon-hand-right\"></span> .glyphicon .glyphicon-hand-right</li>\n      <li><span class=\"glyphicon glyphicon-hand-up\"></span> .glyphicon .glyphicon-hand-up</li>\n      <li><span class=\"glyphicon glyphicon-hd-video\"></span> .glyphicon .glyphicon-hd-video</li>\n      <li><span class=\"glyphicon glyphicon-hdd\"></span> .glyphicon .glyphicon-hdd</li>\n      <li><span class=\"glyphicon glyphicon-header\"></span> .glyphicon .glyphicon-header</li>\n      <li><span class=\"glyphicon glyphicon-headphones\"></span> .glyphicon .glyphicon-headphones</li>\n      <li><span class=\"glyphicon glyphicon-heart\"></span> .glyphicon .glyphicon-heart</li>\n      <li><span class=\"glyphicon glyphicon-heart-empty\"></span> .glyphicon .glyphicon-heart-empty</li>\n      <li><span class=\"glyphicon glyphicon-home\"></span> .glyphicon .glyphicon-home</li>\n      <li><span class=\"glyphicon glyphicon-import\"></span> .glyphicon .glyphicon-import</li>\n      <li><span class=\"glyphicon glyphicon-inbox\"></span> .glyphicon .glyphicon-inbox</li>\n      <li><span class=\"glyphicon glyphicon-indent-left\"></span> .glyphicon .glyphicon-indent-left</li>\n      <li><span class=\"glyphicon glyphicon-indent-right\"></span> .glyphicon .glyphicon-indent-right</li>\n      <li><span class=\"glyphicon glyphicon-info-sign\"></span> .glyphicon .glyphicon-info-sign</li>\n      <li><span class=\"glyphicon glyphicon-italic\"></span> .glyphicon .glyphicon-italic</li>\n      <li><span class=\"glyphicon glyphicon-leaf\"></span> .glyphicon .glyphicon-leaf</li>\n      <li><span class=\"glyphicon glyphicon-link\"></span> .glyphicon .glyphicon-link</li>\n      <li><span class=\"glyphicon glyphicon-list\"></span> .glyphicon .glyphicon-list</li>\n      <li><span class=\"glyphicon glyphicon-list-alt\"></span> .glyphicon .glyphicon-list-alt</li>\n      <li><span class=\"glyphicon glyphicon-lock\"></span> .glyphicon .glyphicon-lock</li>\n      <li><span class=\"glyphicon glyphicon-log-in\"></span> .glyphicon .glyphicon-log-in</li>\n      <li><span class=\"glyphicon glyphicon-log-out\"></span> .glyphicon .glyphicon-log-out</li>\n      <li><span class=\"glyphicon glyphicon-magnet\"></span> .glyphicon .glyphicon-magnet</li>\n      <li><span class=\"glyphicon glyphicon-map-marker\"></span> .glyphicon .glyphicon-map-marker</li>\n      <li><span class=\"glyphicon glyphicon-minus\"></span> .glyphicon .glyphicon-minus</li>\n      <li><span class=\"glyphicon glyphicon-minus-sign\"></span> .glyphicon .glyphicon-minus-sign</li>\n      <li><span class=\"glyphicon glyphicon-move\"></span> .glyphicon .glyphicon-move</li>\n      <li><span class=\"glyphicon glyphicon-music\"></span> .glyphicon .glyphicon-music</li>\n      <li><span class=\"glyphicon glyphicon-new-window\"></span> .glyphicon .glyphicon-new-window</li>\n      <li><span class=\"glyphicon glyphicon-off\"></span> .glyphicon .glyphicon-off</li>\n      <li><span class=\"glyphicon glyphicon-ok\"></span> .glyphicon .glyphicon-ok</li>\n      <li><span class=\"glyphicon glyphicon-ok-circle\"></span> .glyphicon .glyphicon-ok-circle</li>\n      <li><span class=\"glyphicon glyphicon-ok-sign\"></span> .glyphicon .glyphicon-ok-sign</li>\n      <li><span class=\"glyphicon glyphicon-open\"></span> .glyphicon .glyphicon-open</li>\n      <li><span class=\"glyphicon glyphicon-paperclip\"></span> .glyphicon .glyphicon-paperclip</li>\n      <li><span class=\"glyphicon glyphicon-pause\"></span> .glyphicon .glyphicon-pause</li>\n      <li><span class=\"glyphicon glyphicon-pencil\"></span> .glyphicon .glyphicon-pencil</li>\n      <li><span class=\"glyphicon glyphicon-phone\"></span> .glyphicon .glyphicon-phone</li>\n      <li><span class=\"glyphicon glyphicon-phone-alt\"></span> .glyphicon .glyphicon-phone-alt</li>\n      <li><span class=\"glyphicon glyphicon-picture\"></span> .glyphicon .glyphicon-picture</li>\n      <li><span class=\"glyphicon glyphicon-plane\"></span> .glyphicon .glyphicon-plane</li>\n      <li><span class=\"glyphicon glyphicon-play\"></span> .glyphicon .glyphicon-play</li>\n      <li><span class=\"glyphicon glyphicon-play-circle\"></span> .glyphicon .glyphicon-play-circle</li>\n      <li><span class=\"glyphicon glyphicon-plus\"></span> .glyphicon .glyphicon-plus</li>\n      <li><span class=\"glyphicon glyphicon-plus-sign\"></span> .glyphicon .glyphicon-plus-sign</li>\n      <li><span class=\"glyphicon glyphicon-print\"></span> .glyphicon .glyphicon-print</li>\n      <li><span class=\"glyphicon glyphicon-pushpin\"></span> .glyphicon .glyphicon-pushpin</li>\n      <li><span class=\"glyphicon glyphicon-qrcode\"></span> .glyphicon .glyphicon-qrcode</li>\n      <li><span class=\"glyphicon glyphicon-question-sign\"></span> .glyphicon .glyphicon-question-sign</li>\n      <li><span class=\"glyphicon glyphicon-random\"></span> .glyphicon .glyphicon-random</li>\n      <li><span class=\"glyphicon glyphicon-record\"></span> .glyphicon .glyphicon-record</li>\n      <li><span class=\"glyphicon glyphicon-refresh\"></span> .glyphicon .glyphicon-refresh</li>\n      <li><span class=\"glyphicon glyphicon-registration-mark\"></span> .glyphicon .glyphicon-registration-mark</li>\n      <li><span class=\"glyphicon glyphicon-remove\"></span> .glyphicon .glyphicon-remove</li>\n      <li><span class=\"glyphicon glyphicon-remove-circle\"></span> .glyphicon .glyphicon-remove-circle</li>\n      <li><span class=\"glyphicon glyphicon-remove-sign\"></span> .glyphicon .glyphicon-remove-sign</li>\n      <li><span class=\"glyphicon glyphicon-repeat\"></span> .glyphicon .glyphicon-repeat</li>\n      <li><span class=\"glyphicon glyphicon-resize-full\"></span> .glyphicon .glyphicon-resize-full</li>\n      <li><span class=\"glyphicon glyphicon-resize-horizontal\"></span> .glyphicon .glyphicon-resize-horizontal</li>\n      <li><span class=\"glyphicon glyphicon-resize-small\"></span> .glyphicon .glyphicon-resize-small</li>\n      <li><span class=\"glyphicon glyphicon-resize-vertical\"></span> .glyphicon .glyphicon-resize-vertical</li>\n      <li><span class=\"glyphicon glyphicon-retweet\"></span> .glyphicon .glyphicon-retweet</li>\n      <li><span class=\"glyphicon glyphicon-road\"></span> .glyphicon .glyphicon-road</li>\n      <li><span class=\"glyphicon glyphicon-save\"></span> .glyphicon .glyphicon-save</li>\n      <li><span class=\"glyphicon glyphicon-saved\"></span> .glyphicon .glyphicon-saved</li>\n      <li><span class=\"glyphicon glyphicon-screenshot\"></span> .glyphicon .glyphicon-screenshot</li>\n      <li><span class=\"glyphicon glyphicon-sd-video\"></span> .glyphicon .glyphicon-sd-video</li>\n      <li><span class=\"glyphicon glyphicon-search\"></span> .glyphicon .glyphicon-search</li>\n      <li><span class=\"glyphicon glyphicon-send\"></span> .glyphicon .glyphicon-send</li>\n      <li><span class=\"glyphicon glyphicon-share\"></span> .glyphicon .glyphicon-share</li>\n      <li><span class=\"glyphicon glyphicon-share-alt\"></span> .glyphicon .glyphicon-share-alt</li>\n      <li><span class=\"glyphicon glyphicon-shopping-cart\"></span> .glyphicon .glyphicon-shopping-cart</li>\n      <li><span class=\"glyphicon glyphicon-signal\"></span> .glyphicon .glyphicon-signal</li>\n      <li><span class=\"glyphicon glyphicon-sort\"></span> .glyphicon .glyphicon-sort</li>\n      <li><span class=\"glyphicon glyphicon-sort-by-alphabet\"></span> .glyphicon .glyphicon-sort-by-alphabet</li>\n      <li><span class=\"glyphicon glyphicon-sort-by-alphabet-alt\"></span> .glyphicon .glyphicon-sort-by-alphabet-alt</li>\n      <li><span class=\"glyphicon glyphicon-sort-by-attributes\"></span> .glyphicon .glyphicon-sort-by-attributes</li>\n      <li><span class=\"glyphicon glyphicon-sort-by-attributes-alt\"></span> .glyphicon .glyphicon-sort-by-attributes-alt</li>\n      <li><span class=\"glyphicon glyphicon-sort-by-order\"></span> .glyphicon .glyphicon-sort-by-order</li>\n      <li><span class=\"glyphicon glyphicon-sort-by-order-alt\"></span> .glyphicon .glyphicon-sort-by-order-alt</li>\n      <li><span class=\"glyphicon glyphicon-sound-5-1\"></span> .glyphicon .glyphicon-sound-5-1</li>\n      <li><span class=\"glyphicon glyphicon-sound-6-1\"></span> .glyphicon .glyphicon-sound-6-1</li>\n      <li><span class=\"glyphicon glyphicon-sound-7-1\"></span> .glyphicon .glyphicon-sound-7-1</li>\n      <li><span class=\"glyphicon glyphicon-sound-dolby\"></span> .glyphicon .glyphicon-sound-dolby</li>\n      <li><span class=\"glyphicon glyphicon-sound-stereo\"></span> .glyphicon .glyphicon-sound-stereo</li>\n      <li><span class=\"glyphicon glyphicon-star\"></span> .glyphicon .glyphicon-star</li>\n      <li><span class=\"glyphicon glyphicon-star-empty\"></span> .glyphicon .glyphicon-star-empty</li>\n      <li><span class=\"glyphicon glyphicon-stats\"></span> .glyphicon .glyphicon-stats</li>\n      <li><span class=\"glyphicon glyphicon-step-backward\"></span> .glyphicon .glyphicon-step-backward</li>\n      <li><span class=\"glyphicon glyphicon-step-forward\"></span> .glyphicon .glyphicon-step-forward</li>\n      <li><span class=\"glyphicon glyphicon-stop\"></span> .glyphicon .glyphicon-stop</li>\n      <li><span class=\"glyphicon glyphicon-subtitles\"></span> .glyphicon .glyphicon-subtitles</li>\n      <li><span class=\"glyphicon glyphicon-tag\"></span> .glyphicon .glyphicon-tag</li>\n      <li><span class=\"glyphicon glyphicon-tags\"></span> .glyphicon .glyphicon-tags</li>\n      <li><span class=\"glyphicon glyphicon-tasks\"></span> .glyphicon .glyphicon-tasks</li>\n      <li><span class=\"glyphicon glyphicon-text-height\"></span> .glyphicon .glyphicon-text-height</li>\n      <li><span class=\"glyphicon glyphicon-text-width\"></span> .glyphicon .glyphicon-text-width</li>\n      <li><span class=\"glyphicon glyphicon-th\"></span> .glyphicon .glyphicon-th</li>\n      <li><span class=\"glyphicon glyphicon-th-large\"></span> .glyphicon .glyphicon-th-large</li>\n      <li><span class=\"glyphicon glyphicon-th-list\"></span> .glyphicon .glyphicon-th-list</li>\n      <li><span class=\"glyphicon glyphicon-thumbs-down\"></span> .glyphicon .glyphicon-thumbs-down</li>\n      <li><span class=\"glyphicon glyphicon-thumbs-up\"></span> .glyphicon .glyphicon-thumbs-up</li>\n      <li><span class=\"glyphicon glyphicon-time\"></span> .glyphicon .glyphicon-time</li>\n      <li><span class=\"glyphicon glyphicon-tint\"></span> .glyphicon .glyphicon-tint</li>\n      <li><span class=\"glyphicon glyphicon-tower\"></span> .glyphicon .glyphicon-tower</li>\n      <li><span class=\"glyphicon glyphicon-transfer\"></span> .glyphicon .glyphicon-transfer</li>\n      <li><span class=\"glyphicon glyphicon-trash\"></span> .glyphicon .glyphicon-trash</li>\n      <li><span class=\"glyphicon glyphicon-tree-conifer\"></span> .glyphicon .glyphicon-tree-conifer</li>\n      <li><span class=\"glyphicon glyphicon-tree-deciduous\"></span> .glyphicon .glyphicon-tree-deciduous</li>\n      <li><span class=\"glyphicon glyphicon-unchecked\"></span> .glyphicon .glyphicon-unchecked</li>\n      <li><span class=\"glyphicon glyphicon-upload\"></span> .glyphicon .glyphicon-upload</li>\n      <li><span class=\"glyphicon glyphicon-usd\"></span> .glyphicon .glyphicon-usd</li>\n      <li><span class=\"glyphicon glyphicon-user\"></span> .glyphicon .glyphicon-user</li>\n      <li><span class=\"glyphicon glyphicon-volume-down\"></span> .glyphicon .glyphicon-volume-down</li>\n      <li><span class=\"glyphicon glyphicon-volume-off\"></span> .glyphicon .glyphicon-volume-off</li>\n      <li><span class=\"glyphicon glyphicon-volume-up\"></span> .glyphicon .glyphicon-volume-up</li>\n      <li><span class=\"glyphicon glyphicon-warning-sign\"></span> .glyphicon .glyphicon-warning-sign</li>\n      <li><span class=\"glyphicon glyphicon-wrench\"></span> .glyphicon .glyphicon-wrench</li>\n      <li><span class=\"glyphicon glyphicon-zoom-in\"></span> .glyphicon .glyphicon-zoom-in</li>\n      <li><span class=\"glyphicon glyphicon-zoom-out\"></span> .glyphicon .glyphicon-zoom-out</li>\n    </ul>\n\n\n    <h2 id=\"glyphicons-how-to-use\">How to use</h2>\n    <p>For performance reasons, all icons require a base class and individual icon class. To use, place the following code just about anywhere. Be sure to leave a space between the icon and text for proper padding.</p>\n{% highlight html %}\n<span class=\"glyphicon glyphicon-search\"></span>\n{% endhighlight %}\n\n\n    <h2 id=\"glyphicons-examples\">Examples</h2>\n    <p>Use them in buttons, button groups for a toolbar, navigation, or prepended form inputs.</p>\n    <div class=\"bs-example\">\n      <div class=\"btn-toolbar\">\n        <div class=\"btn-group\">\n          <button type=\"button\" class=\"btn btn-default\"><span class=\"glyphicon glyphicon-align-left\"></span></button>\n          <button type=\"button\" class=\"btn btn-default\"><span class=\"glyphicon glyphicon-align-center\"></span></button>\n          <button type=\"button\" class=\"btn btn-default\"><span class=\"glyphicon glyphicon-align-right\"></span></button>\n          <button type=\"button\" class=\"btn btn-default\"><span class=\"glyphicon glyphicon-align-justify\"></span></button>\n        </div>\n      </div>\n      <div class=\"btn-toolbar\">\n        <button type=\"button\" class=\"btn btn-default btn-lg\"><span class=\"glyphicon glyphicon-star\"></span> Star</button>\n        <button type=\"button\" class=\"btn btn-default\"><span class=\"glyphicon glyphicon-star\"></span> Star</button>\n        <button type=\"button\" class=\"btn btn-default btn-sm\"><span class=\"glyphicon glyphicon-star\"></span> Star</button>\n        <button type=\"button\" class=\"btn btn-default btn-xs\"><span class=\"glyphicon glyphicon-star\"></span> Star</button>\n      </div>\n    </div>\n{% highlight html %}\n<button type=\"button\" class=\"btn btn-default btn-lg\">\n  <span class=\"glyphicon glyphicon-star\"></span> Star\n</button>\n{% endhighlight %}\n\n  </div>\n\n\n  <!-- Dropdowns\n  ================================================== -->\n  <div class=\"bs-docs-section\">\n    <div class=\"page-header\">\n      <h1 id=\"dropdowns\">Dropdowns</h1>\n    </div>\n    <p class=\"lead\">Toggleable, contextual menu for displaying lists of links. Made interactive with the <a href=\"../javascript/#dropdowns\">dropdown JavaScript plugin</a>.</p>\n\n    <h3 id=\"dropdowns-example\">Example</h3>\n    <p>Wrap the dropdown's trigger and the dropdown menu within <code>.dropdown</code>, or another element that declares <code>position: relative;</code>. Then add the menu's HTML.</p>\n    <div class=\"bs-example\">\n      <div class=\"dropdown clearfix\">\n        <a id=\"dropdownMenu1\" href=\"#\" role=\"button\" class=\"sr-only dropdown-toggle\" data-toggle=\"dropdown\">Dropdown <b class=\"caret\"></b></a>\n        <ul class=\"dropdown-menu\" role=\"menu\" aria-labelledby=\"dropdownMenu1\">\n          <li role=\"presentation\"><a role=\"menuitem\" tabindex=\"-1\" href=\"#\">Action</a></li>\n          <li role=\"presentation\"><a role=\"menuitem\" tabindex=\"-1\" href=\"#\">Another action</a></li>\n          <li role=\"presentation\"><a role=\"menuitem\" tabindex=\"-1\" href=\"#\">Something else here</a></li>\n          <li role=\"presentation\" class=\"divider\"></li>\n          <li role=\"presentation\"><a role=\"menuitem\" tabindex=\"-1\" href=\"#\">Separated link</a></li>\n        </ul>\n      </div>\n    </div><!-- /example -->\n{% highlight html %}\n<div class=\"dropdown\">\n  <!-- Link or button to toggle dropdown -->\n  <ul class=\"dropdown-menu\" role=\"menu\" aria-labelledby=\"dropdownMenu1\">\n    <li role=\"presentation\"><a role=\"menuitem\" tabindex=\"-1\" href=\"#\">Action</a></li>\n    <li role=\"presentation\"><a role=\"menuitem\" tabindex=\"-1\" href=\"#\">Another action</a></li>\n    <li role=\"presentation\"><a role=\"menuitem\" tabindex=\"-1\" href=\"#\">Something else here</a></li>\n    <li role=\"presentation\" class=\"divider\"></li>\n    <li role=\"presentation\"><a role=\"menuitem\" tabindex=\"-1\" href=\"#\">Separated link</a></li>\n  </ul>\n</div>\n{% endhighlight %}\n\n    <h3 id=\"dropdowns-alignment\">Alignment options</h3>\n    <p>Add <code>.pull-right</code> to a <code>.dropdown-menu</code> to right align the dropdown menu.</p>\n{% highlight html %}\n<ul class=\"dropdown-menu pull-right\" role=\"menu\" aria-labelledby=\"dLabel\">\n  ...\n</ul>\n{% endhighlight %}\n\n    <h3 id=\"dropdowns-headers\">Headers</h3>\n    <p>Add a header to label sections of actions in any dropdown menu.</p>\n    <div class=\"bs-example\">\n      <div class=\"dropdown clearfix\">\n        <a id=\"dropdownMenu2\" href=\"#\" role=\"button\" class=\"sr-only dropdown-toggle\" data-toggle=\"dropdown\">Dropdown <b class=\"caret\"></b></a>\n        <ul class=\"dropdown-menu\" role=\"menu\" aria-labelledby=\"dropdownMenu2\">\n          <li role=\"presentation\" class=\"dropdown-header\">Dropdown header</li>\n          <li role=\"presentation\"><a role=\"menuitem\" tabindex=\"-1\" href=\"#\">Action</a></li>\n          <li role=\"presentation\"><a role=\"menuitem\" tabindex=\"-1\" href=\"#\">Another action</a></li>\n          <li role=\"presentation\"><a role=\"menuitem\" tabindex=\"-1\" href=\"#\">Something else here</a></li>\n          <li role=\"presentation\" class=\"divider\"></li>\n          <li role=\"presentation\" class=\"dropdown-header\">Dropdown header</li>\n          <li role=\"presentation\"><a role=\"menuitem\" tabindex=\"-1\" href=\"#\">Separated link</a></li>\n        </ul>\n      </div>\n    </div><!-- /example -->\n{% highlight html %}\n<ul class=\"dropdown-menu\" role=\"menu\" aria-labelledby=\"dropdownMenu2\">\n  <li role=\"presentation\" class=\"dropdown-header\">Dropdown header</li>\n  ...\n  <li role=\"presentation\" class=\"divider\"></li>\n  <li role=\"presentation\" class=\"dropdown-header\">Dropdown header</li>\n  ...\n</ul>\n{% endhighlight %}\n\n    <h3 id=\"dropdowns-disabled\">Disabled menu items</h3>\n    <p>Add <code>.disabled</code> to a <code>&lt;li&gt;</code> in the dropdown to disable the link.</p>\n    <div class=\"bs-example\">\n      <div class=\"dropdown clearfix\">\n        <a id=\"dropdownMenu3\" href=\"#\" role=\"button\" class=\"sr-only dropdown-toggle\" data-toggle=\"dropdown\">Dropdown <b class=\"caret\"></b></a>\n        <ul class=\"dropdown-menu\" role=\"menu\" aria-labelledby=\"dropdownMenu3\">\n          <li role=\"presentation\"><a role=\"menuitem\" tabindex=\"-1\" href=\"#\">Regular link</a></li>\n          <li role=\"presentation\" class=\"disabled\"><a role=\"menuitem\" tabindex=\"-1\" href=\"#\">Disabled link</a></li>\n          <li role=\"presentation\"><a role=\"menuitem\" tabindex=\"-1\" href=\"#\">Another link</a></li>\n        </ul>\n      </div>\n    </div><!-- /example -->\n{% highlight html %}\n<ul class=\"dropdown-menu\" role=\"menu\" aria-labelledby=\"dropdownMenu3\">\n  <li role=\"presentation\"><a role=\"menuitem\" tabindex=\"-1\" href=\"#\">Regular link</a></li>\n  <li role=\"presentation\" class=\"disabled\"><a role=\"menuitem\" tabindex=\"-1\" href=\"#\">Disabled link</a></li>\n  <li role=\"presentation\"><a role=\"menuitem\" tabindex=\"-1\" href=\"#\">Another link</a></li>\n</ul>\n{% endhighlight %}\n  </div>\n\n\n\n  <!-- Button Groups\n  ================================================== -->\n  <div class=\"bs-docs-section\">\n    <div class=\"page-header\">\n      <h1 id=\"btn-groups\">Button groups</h1>\n    </div>\n    <p class=\"lead\">Group a series of buttons together on a single line with the button group. Add on optional JavaScript radio and checkbox style behavior with <a href=\"../javascript/#buttons\">our buttons plugin</a>.</p>\n\n    <div class=\"bs-callout bs-callout-info\">\n      <h4>Tooltips &amp; popovers in button groups require special setting</h4>\n      <p>When using tooltips or popovers on elements within a <code>.btn-group</code>, you'll have to specify the option <code>container: 'body'</code> to avoid unwanted side effects (such as the element growing wider and/or losing its rounded corners when the tooltip or popover is triggered).</p>\n    </div>\n\n    <h3 id=\"btn-groups-single\">Basic example</h3>\n    <p>Wrap a series of buttons with <code>.btn</code> in <code>.btn-group</code>.</p>\n    <div class=\"bs-example\">\n      <div class=\"btn-group\" style=\"margin: 9px 0 5px;\">\n        <button type=\"button\" class=\"btn btn-default\">Left</button>\n        <button type=\"button\" class=\"btn btn-default\">Middle</button>\n        <button type=\"button\" class=\"btn btn-default\">Right</button>\n      </div>\n    </div>\n{% highlight html %}\n<div class=\"btn-group\">\n  <button type=\"button\" class=\"btn btn-default\">Left</button>\n  <button type=\"button\" class=\"btn btn-default\">Middle</button>\n  <button type=\"button\" class=\"btn btn-default\">Right</button>\n</div>\n{% endhighlight %}\n\n    <h3 id=\"btn-groups-toolbar\">Button toolbar</h3>\n    <p>Combine sets of <code>&lt;div class=\"btn-group\"&gt;</code> into a <code>&lt;div class=\"btn-toolbar\"&gt;</code> for more complex components.</p>\n    <div class=\"bs-example\">\n      <div class=\"btn-toolbar\" style=\"margin: 0;\">\n        <div class=\"btn-group\">\n          <button type=\"button\" class=\"btn btn-default\">1</button>\n          <button type=\"button\" class=\"btn btn-default\">2</button>\n          <button type=\"button\" class=\"btn btn-default\">3</button>\n          <button type=\"button\" class=\"btn btn-default\">4</button>\n        </div>\n        <div class=\"btn-group\">\n          <button type=\"button\" class=\"btn btn-default\">5</button>\n          <button type=\"button\" class=\"btn btn-default\">6</button>\n          <button type=\"button\" class=\"btn btn-default\">7</button>\n        </div>\n        <div class=\"btn-group\">\n          <button type=\"button\" class=\"btn btn-default\">8</button>\n        </div>\n      </div>\n    </div>\n{% highlight html %}\n<div class=\"btn-toolbar\">\n  <div class=\"btn-group\">...</div>\n  <div class=\"btn-group\">...</div>\n  <div class=\"btn-group\">...</div>\n</div>\n{% endhighlight %}\n\n    <h3 id=\"btn-groups-sizing\">Sizing</h3>\n    <p>Instead of applying button sizing classes to every button in a group, just add <code>.btn-group-*</code> to the <code>.btn-group</code>.</p>\n    <div class=\"bs-example\">\n      <div class=\"btn-toolbar\">\n        <div class=\"btn-group btn-group-lg\">\n          <button type=\"button\" class=\"btn btn-default\">Left</button>\n          <button type=\"button\" class=\"btn btn-default\">Middle</button>\n          <button type=\"button\" class=\"btn btn-default\">Right</button>\n        </div>\n      </div>\n      <div class=\"btn-toolbar\">\n        <div class=\"btn-group\">\n          <button type=\"button\" class=\"btn btn-default\">Left</button>\n          <button type=\"button\" class=\"btn btn-default\">Middle</button>\n          <button type=\"button\" class=\"btn btn-default\">Right</button>\n        </div>\n      </div>\n      <div class=\"btn-toolbar\">\n        <div class=\"btn-group btn-group-sm\">\n          <button type=\"button\" class=\"btn btn-default\">Left</button>\n          <button type=\"button\" class=\"btn btn-default\">Middle</button>\n          <button type=\"button\" class=\"btn btn-default\">Right</button>\n        </div>\n      </div>\n      <div class=\"btn-toolbar\">\n        <div class=\"btn-group btn-group-xs\">\n          <button type=\"button\" class=\"btn btn-default\">Left</button>\n          <button type=\"button\" class=\"btn btn-default\">Middle</button>\n          <button type=\"button\" class=\"btn btn-default\">Right</button>\n        </div>\n      </div>\n    </div>\n{% highlight html %}\n<div class=\"btn-group btn-group-lg\">...</div>\n<div class=\"btn-group\">...</div>\n<div class=\"btn-group btn-group-sm\">...</div>\n<div class=\"btn-group btn-group-xs\">...</div>\n{% endhighlight %}\n\n    <h3 id=\"btn-groups-nested\">Nesting</h3>\n    <p>Place a <code>.btn-group</code> within another <code>.btn-group</code> when you want dropdown menus mixed with a series of buttons.</p>\n    <div class=\"bs-example\">\n      <div class=\"btn-group\">\n        <button type=\"button\" class=\"btn btn-default\">1</button>\n        <button type=\"button\" class=\"btn btn-default\">2</button>\n\n        <div class=\"btn-group\">\n          <button id=\"btnGroupDrop1\" type=\"button\" class=\"btn btn-default dropdown-toggle\" data-toggle=\"dropdown\">\n            Dropdown\n            <span class=\"caret\"></span>\n          </button>\n          <ul class=\"dropdown-menu\" role=\"menu\" aria-labelledby=\"btnGroupDrop1\">\n            <li><a href=\"#\">Dropdown link</a></li>\n            <li><a href=\"#\">Dropdown link</a></li>\n          </ul>\n        </div>\n      </div>\n    </div>\n{% highlight html %}\n<div class=\"btn-group\">\n  <button type=\"button\" class=\"btn btn-default\">1</button>\n  <button type=\"button\" class=\"btn btn-default\">2</button>\n\n  <div class=\"btn-group\">\n    <button type=\"button\" class=\"btn btn-default dropdown-toggle\" data-toggle=\"dropdown\">\n      Dropdown\n      <span class=\"caret\"></span>\n    </button>\n    <ul class=\"dropdown-menu\">\n      <li><a href=\"#\">Dropdown link</a></li>\n      <li><a href=\"#\">Dropdown link</a></li>\n    </ul>\n  </div>\n</div>\n{% endhighlight %}\n\n    <h3 id=\"btn-groups-vertical\">Vertical variation</h3>\n    <p>Make a set of buttons appear vertically stacked rather than horizontally.</p>\n    <div class=\"bs-example\">\n      <div class=\"btn-group-vertical\">\n        <button type=\"button\" class=\"btn btn-default\">Button</button>\n        <button type=\"button\" class=\"btn btn-default\">Button</button>\n        <div class=\"btn-group\">\n          <button id=\"btnGroupVerticalDrop1\" type=\"button\" class=\"btn btn-default dropdown-toggle\" data-toggle=\"dropdown\">\n            Dropdown\n            <span class=\"caret\"></span>\n          </button>\n          <ul class=\"dropdown-menu\" role=\"menu\" aria-labelledby=\"btnGroupVerticalDrop1\">\n            <li><a href=\"#\">Dropdown link</a></li>\n            <li><a href=\"#\">Dropdown link</a></li>\n          </ul>\n        </div>\n        <button type=\"button\" class=\"btn btn-default\">Button</button>\n        <button type=\"button\" class=\"btn btn-default\">Button</button>\n        <div class=\"btn-group\">\n          <button id=\"btnGroupVerticalDrop2\" type=\"button\" class=\"btn btn-default dropdown-toggle\" data-toggle=\"dropdown\">\n            Dropdown\n            <span class=\"caret\"></span>\n          </button>\n          <ul class=\"dropdown-menu\" role=\"menu\" aria-labelledby=\"btnGroupVerticalDrop2\">\n            <li><a href=\"#\">Dropdown link</a></li>\n            <li><a href=\"#\">Dropdown link</a></li>\n          </ul>\n        </div>\n        <div class=\"btn-group\">\n          <button id=\"btnGroupVerticalDrop3\" type=\"button\" class=\"btn btn-default dropdown-toggle\" data-toggle=\"dropdown\">\n            Dropdown\n            <span class=\"caret\"></span>\n          </button>\n          <ul class=\"dropdown-menu\" role=\"menu\" aria-labelledby=\"btnGroupVerticalDrop3\">\n            <li><a href=\"#\">Dropdown link</a></li>\n            <li><a href=\"#\">Dropdown link</a></li>\n          </ul>\n        </div>\n        <div class=\"btn-group\">\n          <button id=\"btnGroupVerticalDrop4\" type=\"button\" class=\"btn btn-default dropdown-toggle\" data-toggle=\"dropdown\">\n            Dropdown\n            <span class=\"caret\"></span>\n          </button>\n          <ul class=\"dropdown-menu\" role=\"menu\" aria-labelledby=\"btnGroupVerticalDrop4\">\n            <li><a href=\"#\">Dropdown link</a></li>\n            <li><a href=\"#\">Dropdown link</a></li>\n          </ul>\n        </div>\n      </div>\n    </div>\n{% highlight html %}\n<div class=\"btn-group-vertical\">\n  ...\n</div>\n{% endhighlight %}\n\n    <h3 id=\"btn-groups-justified\">Justified link variation</h3>\n    <p>Make a group of buttons stretch at the same size to span the entire width of its parent.</p>\n\n    <div class=\"bs-callout bs-callout-warning\">\n      <h4>Element-specific usage</h4>\n      <p>This only works with <code>&lt;a&gt;</code> elements as the <code>&lt;button&gt;</code> doesn't pick up these styles.</p>\n    </div>\n\n    <div class=\"bs-example\">\n      <div class=\"btn-group btn-group-justified\">\n        <a href=\"#\" class=\"btn btn-default\">Left</a>\n        <a href=\"#\" class=\"btn btn-default\">Middle</a>\n        <a href=\"#\" class=\"btn btn-default\">Right</a>\n      </div>\n    </div>\n{% highlight html %}\n<div class=\"btn-group btn-group-justified\">\n  ...\n</div>\n{% endhighlight %}\n\n  </div>\n\n\n\n  <!-- Split button dropdowns\n  ================================================== -->\n  <div class=\"bs-docs-section\">\n    <div class=\"page-header\">\n      <h1 id=\"btn-dropdowns\">Button dropdowns</h1>\n    </div>\n    <p class=\"lead\">Use any button to trigger a dropdown menu by placing it within a <code>.btn-group</code> and providing the proper menu markup.</p>\n\n    <div class=\"bs-callout bs-callout-danger\">\n      <h4>Plugin dependency</h4>\n      <p>Button dropdowns require the <a href=\"../javascript/#dropdowns\">dropdown plugin</a> to be included in your version of Bootstrap.</p>\n    </div>\n\n    <h3 id=\"btn-dropdowns-single\">Single button dropdowns</h3>\n    <p>Turn a button into a dropdown toggle with some basic markup changes.</p>\n    <div class=\"bs-example\">\n      <div class=\"btn-group\">\n        <button type=\"button\" class=\"btn btn-default dropdown-toggle\" data-toggle=\"dropdown\">Default <span class=\"caret\"></span></button>\n        <ul class=\"dropdown-menu\" role=\"menu\">\n          <li><a href=\"#\">Action</a></li>\n          <li><a href=\"#\">Another action</a></li>\n          <li><a href=\"#\">Something else here</a></li>\n          <li class=\"divider\"></li>\n          <li><a href=\"#\">Separated link</a></li>\n        </ul>\n      </div><!-- /btn-group -->\n      <div class=\"btn-group\">\n        <button type=\"button\" class=\"btn btn-primary dropdown-toggle\" data-toggle=\"dropdown\">Primary <span class=\"caret\"></span></button>\n        <ul class=\"dropdown-menu\" role=\"menu\">\n          <li><a href=\"#\">Action</a></li>\n          <li><a href=\"#\">Another action</a></li>\n          <li><a href=\"#\">Something else here</a></li>\n          <li class=\"divider\"></li>\n          <li><a href=\"#\">Separated link</a></li>\n        </ul>\n      </div><!-- /btn-group -->\n      <div class=\"btn-group\">\n        <button type=\"button\" class=\"btn btn-success dropdown-toggle\" data-toggle=\"dropdown\">Success <span class=\"caret\"></span></button>\n        <ul class=\"dropdown-menu\" role=\"menu\">\n          <li><a href=\"#\">Action</a></li>\n          <li><a href=\"#\">Another action</a></li>\n          <li><a href=\"#\">Something else here</a></li>\n          <li class=\"divider\"></li>\n          <li><a href=\"#\">Separated link</a></li>\n        </ul>\n      </div><!-- /btn-group -->\n      <div class=\"btn-group\">\n        <button type=\"button\" class=\"btn btn-info dropdown-toggle\" data-toggle=\"dropdown\">Info <span class=\"caret\"></span></button>\n        <ul class=\"dropdown-menu\" role=\"menu\">\n          <li><a href=\"#\">Action</a></li>\n          <li><a href=\"#\">Another action</a></li>\n          <li><a href=\"#\">Something else here</a></li>\n          <li class=\"divider\"></li>\n          <li><a href=\"#\">Separated link</a></li>\n        </ul>\n      </div><!-- /btn-group -->\n      <div class=\"btn-group\">\n        <button type=\"button\" class=\"btn btn-warning dropdown-toggle\" data-toggle=\"dropdown\">Warning <span class=\"caret\"></span></button>\n        <ul class=\"dropdown-menu\" role=\"menu\">\n          <li><a href=\"#\">Action</a></li>\n          <li><a href=\"#\">Another action</a></li>\n          <li><a href=\"#\">Something else here</a></li>\n          <li class=\"divider\"></li>\n          <li><a href=\"#\">Separated link</a></li>\n        </ul>\n      </div><!-- /btn-group -->\n      <div class=\"btn-group\">\n        <button type=\"button\" class=\"btn btn-danger dropdown-toggle\" data-toggle=\"dropdown\">Danger <span class=\"caret\"></span></button>\n        <ul class=\"dropdown-menu\" role=\"menu\">\n          <li><a href=\"#\">Action</a></li>\n          <li><a href=\"#\">Another action</a></li>\n          <li><a href=\"#\">Something else here</a></li>\n          <li class=\"divider\"></li>\n          <li><a href=\"#\">Separated link</a></li>\n        </ul>\n      </div><!-- /btn-group -->\n    </div>\n{% highlight html %}\n<!-- Single button -->\n<div class=\"btn-group\">\n  <button type=\"button\" class=\"btn btn-default dropdown-toggle\" data-toggle=\"dropdown\">\n    Action <span class=\"caret\"></span>\n  </button>\n  <ul class=\"dropdown-menu\" role=\"menu\">\n    <li><a href=\"#\">Action</a></li>\n    <li><a href=\"#\">Another action</a></li>\n    <li><a href=\"#\">Something else here</a></li>\n    <li class=\"divider\"></li>\n    <li><a href=\"#\">Separated link</a></li>\n  </ul>\n</div>\n{% endhighlight %}\n\n    <h3 id=\"btn-dropdowns-split\">Split button dropdowns</h3>\n    <p>Similarly, create split button dropdowns with the same markup changes, only with a separate button.</p>\n    <div class=\"bs-example\">\n      <div class=\"btn-group\">\n        <button type=\"button\" class=\"btn btn-default\">Default</button>\n        <button type=\"button\" class=\"btn btn-default dropdown-toggle\" data-toggle=\"dropdown\"><span class=\"caret\"></span></button>\n        <ul class=\"dropdown-menu\" role=\"menu\">\n          <li><a href=\"#\">Action</a></li>\n          <li><a href=\"#\">Another action</a></li>\n          <li><a href=\"#\">Something else here</a></li>\n          <li class=\"divider\"></li>\n          <li><a href=\"#\">Separated link</a></li>\n        </ul>\n      </div><!-- /btn-group -->\n      <div class=\"btn-group\">\n        <button type=\"button\" class=\"btn btn-primary\">Primary</button>\n        <button type=\"button\" class=\"btn btn-primary dropdown-toggle\" data-toggle=\"dropdown\"><span class=\"caret\"></span></button>\n        <ul class=\"dropdown-menu\" role=\"menu\">\n          <li><a href=\"#\">Action</a></li>\n          <li><a href=\"#\">Another action</a></li>\n          <li><a href=\"#\">Something else here</a></li>\n          <li class=\"divider\"></li>\n          <li><a href=\"#\">Separated link</a></li>\n        </ul>\n      </div><!-- /btn-group -->\n      <div class=\"btn-group\">\n        <button type=\"button\" class=\"btn btn-success\">Success</button>\n        <button type=\"button\" class=\"btn btn-success dropdown-toggle\" data-toggle=\"dropdown\"><span class=\"caret\"></span></button>\n        <ul class=\"dropdown-menu\" role=\"menu\">\n          <li><a href=\"#\">Action</a></li>\n          <li><a href=\"#\">Another action</a></li>\n          <li><a href=\"#\">Something else here</a></li>\n          <li class=\"divider\"></li>\n          <li><a href=\"#\">Separated link</a></li>\n        </ul>\n      </div><!-- /btn-group -->\n      <div class=\"btn-group\">\n        <button type=\"button\" class=\"btn btn-info\">Info</button>\n        <button type=\"button\" class=\"btn btn-info dropdown-toggle\" data-toggle=\"dropdown\"><span class=\"caret\"></span></button>\n        <ul class=\"dropdown-menu\" role=\"menu\">\n          <li><a href=\"#\">Action</a></li>\n          <li><a href=\"#\">Another action</a></li>\n          <li><a href=\"#\">Something else here</a></li>\n          <li class=\"divider\"></li>\n          <li><a href=\"#\">Separated link</a></li>\n        </ul>\n      </div><!-- /btn-group -->\n      <div class=\"btn-group\">\n        <button type=\"button\" class=\"btn btn-warning\">Warning</button>\n        <button type=\"button\" class=\"btn btn-warning dropdown-toggle\" data-toggle=\"dropdown\"><span class=\"caret\"></span></button>\n        <ul class=\"dropdown-menu\" role=\"menu\">\n          <li><a href=\"#\">Action</a></li>\n          <li><a href=\"#\">Another action</a></li>\n          <li><a href=\"#\">Something else here</a></li>\n          <li class=\"divider\"></li>\n          <li><a href=\"#\">Separated link</a></li>\n        </ul>\n      </div><!-- /btn-group -->\n      <div class=\"btn-group\">\n        <button type=\"button\" class=\"btn btn-danger\">Danger</button>\n        <button type=\"button\" class=\"btn btn-danger dropdown-toggle\" data-toggle=\"dropdown\"><span class=\"caret\"></span></button>\n        <ul class=\"dropdown-menu\" role=\"menu\">\n          <li><a href=\"#\">Action</a></li>\n          <li><a href=\"#\">Another action</a></li>\n          <li><a href=\"#\">Something else here</a></li>\n          <li class=\"divider\"></li>\n          <li><a href=\"#\">Separated link</a></li>\n        </ul>\n      </div><!-- /btn-group -->\n    </div>\n{% highlight html %}\n<!-- Split button -->\n<div class=\"btn-group\">\n  <button type=\"button\" class=\"btn btn-danger\">Action</button>\n  <button type=\"button\" class=\"btn btn-danger dropdown-toggle\" data-toggle=\"dropdown\">\n    <span class=\"caret\"></span>\n  </button>\n  <ul class=\"dropdown-menu\" role=\"menu\">\n    <li><a href=\"#\">Action</a></li>\n    <li><a href=\"#\">Another action</a></li>\n    <li><a href=\"#\">Something else here</a></li>\n    <li class=\"divider\"></li>\n    <li><a href=\"#\">Separated link</a></li>\n  </ul>\n</div>\n{% endhighlight %}\n\n    <h3 id=\"btn-dropdowns-sizing\">Sizing</h3>\n    <p>Button dropdowns work with buttons of all sizes.</p>\n    <div class=\"bs-example\">\n      <div class=\"btn-toolbar\">\n        <div class=\"btn-group\">\n          <button class=\"btn btn-default btn-lg dropdown-toggle\" type=\"button\" data-toggle=\"dropdown\">\n            Large button <span class=\"caret\"></span>\n          </button>\n          <ul class=\"dropdown-menu\" role=\"menu\">\n            <li><a href=\"#\">Action</a></li>\n            <li><a href=\"#\">Another action</a></li>\n            <li><a href=\"#\">Something else here</a></li>\n            <li class=\"divider\"></li>\n            <li><a href=\"#\">Separated link</a></li>\n          </ul>\n        </div><!-- /btn-group -->\n      </div><!-- /btn-toolbar -->\n      <div class=\"btn-toolbar\">\n        <div class=\"btn-group\">\n          <button class=\"btn btn-default btn-sm dropdown-toggle\" type=\"button\" data-toggle=\"dropdown\">\n            Small button <span class=\"caret\"></span>\n          </button>\n          <ul class=\"dropdown-menu\" role=\"menu\">\n            <li><a href=\"#\">Action</a></li>\n            <li><a href=\"#\">Another action</a></li>\n            <li><a href=\"#\">Something else here</a></li>\n            <li class=\"divider\"></li>\n            <li><a href=\"#\">Separated link</a></li>\n          </ul>\n        </div><!-- /btn-group -->\n      </div><!-- /btn-toolbar -->\n      <div class=\"btn-toolbar\">\n        <div class=\"btn-group\">\n          <button class=\"btn btn-default btn-xs dropdown-toggle\" type=\"button\" data-toggle=\"dropdown\">\n            Extra small button <span class=\"caret\"></span>\n          </button>\n          <ul class=\"dropdown-menu\" role=\"menu\">\n            <li><a href=\"#\">Action</a></li>\n            <li><a href=\"#\">Another action</a></li>\n            <li><a href=\"#\">Something else here</a></li>\n            <li class=\"divider\"></li>\n            <li><a href=\"#\">Separated link</a></li>\n          </ul>\n        </div><!-- /btn-group -->\n      </div><!-- /btn-toolbar -->\n    </div><!-- /example -->\n{% highlight html %}\n<!-- Large button group -->\n<div class=\"btn-group\">\n  <button class=\"btn btn-default btn-lg dropdown-toggle\" type=\"button\" data-toggle=\"dropdown\">\n    Large button <span class=\"caret\"></span>\n  </button>\n  <ul class=\"dropdown-menu\">\n    ...\n  </ul>\n</div>\n\n<!-- Small button group -->\n<div class=\"btn-group\">\n  <button class=\"btn btn-default btn-sm dropdown-toggle\" type=\"button\" data-toggle=\"dropdown\">\n    Small button <span class=\"caret\"></span>\n  </button>\n  <ul class=\"dropdown-menu\">\n    ...\n  </ul>\n</div>\n\n<!-- Extra small button group -->\n<div class=\"btn-group\">\n  <button class=\"btn btn-default btn-xs dropdown-toggle\" type=\"button\" data-toggle=\"dropdown\">\n    Extra small button <span class=\"caret\"></span>\n  </button>\n  <ul class=\"dropdown-menu\">\n    ...\n  </ul>\n</div>\n{% endhighlight %}\n\n    <h3 id=\"btn-dropdowns-dropup\">Dropup variation</h3>\n    <p>Trigger dropdown menus above elements by adding <code>.dropup</code> to the parent.</p>\n    <div class=\"bs-example\">\n      <div class=\"btn-toolbar\">\n        <div class=\"btn-group dropup\">\n          <button type=\"button\" class=\"btn btn-default\">Dropup</button>\n          <button type=\"button\" class=\"btn btn-default dropdown-toggle\" data-toggle=\"dropdown\"><span class=\"caret\"></span></button>\n          <ul class=\"dropdown-menu\" role=\"menu\">\n            <li><a href=\"#\">Action</a></li>\n            <li><a href=\"#\">Another action</a></li>\n            <li><a href=\"#\">Something else here</a></li>\n            <li class=\"divider\"></li>\n            <li><a href=\"#\">Separated link</a></li>\n          </ul>\n        </div><!-- /btn-group -->\n        <div class=\"btn-group dropup\">\n          <button type=\"button\" class=\"btn btn-primary\">Right dropup</button>\n          <button type=\"button\" class=\"btn btn-primary dropdown-toggle\" data-toggle=\"dropdown\"><span class=\"caret\"></span></button>\n          <ul class=\"dropdown-menu pull-right\" role=\"menu\">\n            <li><a href=\"#\">Action</a></li>\n            <li><a href=\"#\">Another action</a></li>\n            <li><a href=\"#\">Something else here</a></li>\n            <li class=\"divider\"></li>\n            <li><a href=\"#\">Separated link</a></li>\n          </ul>\n        </div><!-- /btn-group -->\n      </div>\n    </div><!-- /example -->\n{% highlight html %}\n<div class=\"btn-group dropup\">\n  <button type=\"button\" class=\"btn btn-default\">Dropup</button>\n  <button type=\"button\" class=\"btn btn-default dropdown-toggle\" data-toggle=\"dropdown\">\n    <span class=\"caret\"></span>\n  </button>\n  <ul class=\"dropdown-menu\">\n    <!-- Dropdown menu links -->\n  </ul>\n</div>\n{% endhighlight %}\n\n  </div>\n\n\n\n\n  <!-- Input groups\n  ================================================== -->\n  <div class=\"bs-docs-section\">\n    <div class=\"page-header\">\n      <h1 id=\"input-groups\">Input groups</h1>\n    </div>\n    <p class=\"lead\">Extend form controls by adding text or buttons before, after, or on both sides of any text-based input. Use <code>.input-group</code> with an <code>.input-group-addon</code> to prepend or append elements to a <code>.form-control</code>.</p>\n\n    <div class=\"bs-callout bs-callout-danger\">\n      <h4>Cross-browser compatibility</h4>\n      <p>Avoid using <code>&lt;select&gt;</code> elements here as they cannot be fully styled in WebKit browsers.</p>\n    </div>\n    <div class=\"bs-callout bs-callout-info\">\n      <h4>Tooltips &amp; popovers in input groups require special setting</h4>\n      <p>When using tooltips or popovers on elements within an <code>.input-group</code>, you'll have to specify the option <code>container: 'body'</code> to avoid unwanted side effects (such as the element growing wider and/or losing its rounded corners when the tooltip or popover is triggered).</p>\n    </div>\n\n    <h2 id=\"input-groups-basic\">Basic example</h2>\n    <form class=\"bs-example bs-example-form\" role=\"form\">\n      <div class=\"input-group\">\n        <span class=\"input-group-addon\">@</span>\n        <input type=\"text\" class=\"form-control\" placeholder=\"Username\">\n      </div>\n      <br>\n      <div class=\"input-group\">\n        <input type=\"text\" class=\"form-control\">\n        <span class=\"input-group-addon\">.00</span>\n      </div>\n      <br>\n      <div class=\"input-group\">\n        <span class=\"input-group-addon\">$</span>\n        <input type=\"text\" class=\"form-control\">\n        <span class=\"input-group-addon\">.00</span>\n      </div>\n    </form>\n{% highlight html %}\n<div class=\"input-group\">\n  <span class=\"input-group-addon\">@</span>\n  <input type=\"text\" class=\"form-control\" placeholder=\"Username\">\n</div>\n\n<div class=\"input-group\">\n  <input type=\"text\" class=\"form-control\">\n  <span class=\"input-group-addon\">.00</span>\n</div>\n\n<div class=\"input-group\">\n  <span class=\"input-group-addon\">$</span>\n  <input type=\"text\" class=\"form-control\">\n  <span class=\"input-group-addon\">.00</span>\n</div>\n{% endhighlight %}\n\n\n    <h2 id=\"input-groups-sizing\">Sizing</h2>\n    <p>Add the relative form sizing classes to the <code>.input-group</code> itself and contents within will automatically resize—no need for repeating the form control size classes on each element.</p>\n    <form class=\"bs-example bs-example-form\" role=\"form\">\n      <div class=\"input-group input-group-lg\">\n        <span class=\"input-group-addon\">@</span>\n        <input type=\"text\" class=\"form-control\" placeholder=\"Username\">\n      </div>\n      <br>\n      <div class=\"input-group\">\n        <span class=\"input-group-addon\">@</span>\n        <input type=\"text\" class=\"form-control\" placeholder=\"Username\">\n      </div>\n      <br>\n      <div class=\"input-group input-group-sm\">\n        <span class=\"input-group-addon\">@</span>\n        <input type=\"text\" class=\"form-control\" placeholder=\"Username\">\n      </div>\n    </form>\n{% highlight html %}\n<div class=\"input-group input-group-lg\">\n  <span class=\"input-group-addon\">@</span>\n  <input type=\"text\" class=\"form-control input-lg\" placeholder=\"Username\">\n</div>\n\n<div class=\"input-group\">\n  <span class=\"input-group-addon\">@</span>\n  <input type=\"text\" class=\"form-control\" placeholder=\"Username\">\n</div>\n\n<div class=\"input-group input-group-sm\">\n  <span class=\"input-group-addon\">@</span>\n  <input type=\"text\" class=\"form-control\" placeholder=\"Username\">\n</div>\n{% endhighlight %}\n\n\n    <h2 id=\"input-groups-checkboxes-radios\">Checkboxes and radio addons</h2>\n    <p>Place any checkbox or radio option within an input group's addon instead of text.</p>\n    <form class=\"bs-example bs-example-form\">\n      <div class=\"row\">\n        <div class=\"col-lg-6\">\n          <div class=\"input-group\">\n            <span class=\"input-group-addon\">\n              <input type=\"checkbox\">\n            </span>\n            <input type=\"text\" class=\"form-control\">\n          </div><!-- /input-group -->\n        </div><!-- /.col-lg-6 -->\n        <div class=\"col-lg-6\">\n          <div class=\"input-group\">\n            <span class=\"input-group-addon\">\n              <input type=\"radio\">\n            </span>\n            <input type=\"text\" class=\"form-control\">\n          </div><!-- /input-group -->\n        </div><!-- /.col-lg-6 -->\n      </div><!-- /.row -->\n    </form>\n{% highlight html %}\n<div class=\"row\">\n  <div class=\"col-lg-6\">\n    <div class=\"input-group\">\n      <span class=\"input-group-addon\">\n        <input type=\"checkbox\">\n      </span>\n      <input type=\"text\" class=\"form-control\">\n    </div><!-- /input-group -->\n  </div><!-- /.col-lg-6 -->\n  <div class=\"col-lg-6\">\n    <div class=\"input-group\">\n      <span class=\"input-group-addon\">\n        <input type=\"radio\">\n      </span>\n      <input type=\"text\" class=\"form-control\">\n    </div><!-- /input-group -->\n  </div><!-- /.col-lg-6 -->\n</div><!-- /.row -->\n{% endhighlight %}\n\n\n    <h2 id=\"input-groups-buttons\">Button addons</h2>\n    <p>Buttons in input groups are a bit different and require one extra level of nesting. Instead of <code>.input-group-addon</code>, you'll need to use <code>.input-group-btn</code> to wrap the buttons. This is required due to default browser styles that cannot be overridden.</p>\n    <form class=\"bs-example bs-example-form\">\n      <div class=\"row\">\n        <div class=\"col-lg-6\">\n          <div class=\"input-group\">\n            <span class=\"input-group-btn\">\n              <button class=\"btn btn-default\" type=\"button\">Go!</button>\n            </span>\n            <input type=\"text\" class=\"form-control\">\n          </div><!-- /input-group -->\n        </div><!-- /.col-lg-6 -->\n        <div class=\"col-lg-6\">\n          <div class=\"input-group\">\n            <input type=\"text\" class=\"form-control\">\n            <span class=\"input-group-btn\">\n              <button class=\"btn btn-default\" type=\"button\">Go!</button>\n            </span>\n          </div><!-- /input-group -->\n        </div><!-- /.col-lg-6 -->\n      </div><!-- /.row -->\n    </form>\n{% highlight html %}\n<div class=\"row\">\n  <div class=\"col-lg-6\">\n    <div class=\"input-group\">\n      <span class=\"input-group-btn\">\n        <button class=\"btn btn-default\" type=\"button\">Go!</button>\n      </span>\n      <input type=\"text\" class=\"form-control\">\n    </div><!-- /input-group -->\n  </div><!-- /.col-lg-6 -->\n  <div class=\"col-lg-6\">\n    <div class=\"input-group\">\n      <input type=\"text\" class=\"form-control\">\n      <span class=\"input-group-btn\">\n        <button class=\"btn btn-default\" type=\"button\">Go!</button>\n      </span>\n    </div><!-- /input-group -->\n  </div><!-- /.col-lg-6 -->\n</div><!-- /.row -->\n{% endhighlight %}\n\n    <h2 id=\"input-groups-buttons-dropdowns\">Buttons with dropdowns</h2>\n    <p></p>\n    <form class=\"bs-example bs-example-form\" role=\"form\">\n      <div class=\"row\">\n        <div class=\"col-lg-6\">\n          <div class=\"input-group\">\n            <div class=\"input-group-btn\">\n              <button type=\"button\" class=\"btn btn-default dropdown-toggle\" data-toggle=\"dropdown\">Action <span class=\"caret\"></span></button>\n              <ul class=\"dropdown-menu\" role=\"menu\">\n                <li><a href=\"#\">Action</a></li>\n                <li><a href=\"#\">Another action</a></li>\n                <li><a href=\"#\">Something else here</a></li>\n                <li class=\"divider\"></li>\n                <li><a href=\"#\">Separated link</a></li>\n              </ul>\n            </div><!-- /btn-group -->\n            <input type=\"text\" class=\"form-control\">\n          </div><!-- /input-group -->\n        </div><!-- /.col-lg-6 -->\n        <div class=\"col-lg-6\">\n          <div class=\"input-group\">\n            <input type=\"text\" class=\"form-control\">\n            <div class=\"input-group-btn\">\n              <button type=\"button\" class=\"btn btn-default dropdown-toggle\" data-toggle=\"dropdown\">Action <span class=\"caret\"></span></button>\n              <ul class=\"dropdown-menu pull-right\" role=\"menu\">\n                <li><a href=\"#\">Action</a></li>\n                <li><a href=\"#\">Another action</a></li>\n                <li><a href=\"#\">Something else here</a></li>\n                <li class=\"divider\"></li>\n                <li><a href=\"#\">Separated link</a></li>\n              </ul>\n            </div><!-- /btn-group -->\n          </div><!-- /input-group -->\n        </div><!-- /.col-lg-6 -->\n      </div><!-- /.row -->\n    </form>\n{% highlight html %}\n<div class=\"row\">\n  <div class=\"col-lg-6\">\n    <div class=\"input-group\">\n      <div class=\"input-group-btn\">\n        <button type=\"button\" class=\"btn btn-default dropdown-toggle\" data-toggle=\"dropdown\">Action <span class=\"caret\"></span></button>\n        <ul class=\"dropdown-menu\">\n          <li><a href=\"#\">Action</a></li>\n          <li><a href=\"#\">Another action</a></li>\n          <li><a href=\"#\">Something else here</a></li>\n          <li class=\"divider\"></li>\n          <li><a href=\"#\">Separated link</a></li>\n        </ul>\n      </div><!-- /btn-group -->\n      <input type=\"text\" class=\"form-control\">\n    </div><!-- /input-group -->\n  </div><!-- /.col-lg-6 -->\n  <div class=\"col-lg-6\">\n    <div class=\"input-group\">\n      <input type=\"text\" class=\"form-control\">\n      <div class=\"input-group-btn\">\n        <button type=\"button\" class=\"btn btn-default dropdown-toggle\" data-toggle=\"dropdown\">Action <span class=\"caret\"></span></button>\n        <ul class=\"dropdown-menu pull-right\">\n          <li><a href=\"#\">Action</a></li>\n          <li><a href=\"#\">Another action</a></li>\n          <li><a href=\"#\">Something else here</a></li>\n          <li class=\"divider\"></li>\n          <li><a href=\"#\">Separated link</a></li>\n        </ul>\n      </div><!-- /btn-group -->\n    </div><!-- /input-group -->\n  </div><!-- /.col-lg-6 -->\n</div><!-- /.row -->\n{% endhighlight %}\n\n    <h2 id=\"input-groups-buttons-segmented\">Segmented buttons</h2>\n    <form class=\"bs-example bs-example-form\" role=\"form\">\n      <div class=\"row\">\n        <div class=\"col-lg-6\">\n          <div class=\"input-group\">\n            <div class=\"input-group-btn\">\n              <button type=\"button\" class=\"btn btn-default\" tabindex=\"-1\">Action</button>\n              <button type=\"button\" class=\"btn btn-default dropdown-toggle\" data-toggle=\"dropdown\" tabindex=\"-1\">\n                <span class=\"caret\"></span>\n              </button>\n              <ul class=\"dropdown-menu\" role=\"menu\">\n                <li><a href=\"#\">Action</a></li>\n                <li><a href=\"#\">Another action</a></li>\n                <li><a href=\"#\">Something else here</a></li>\n                <li class=\"divider\"></li>\n                <li><a href=\"#\">Separated link</a></li>\n              </ul>\n            </div>\n            <input type=\"text\" class=\"form-control\">\n          </div><!-- /.input-group -->\n        </div><!-- /.col-lg-6 -->\n        <div class=\"col-lg-6\">\n          <div class=\"input-group\">\n            <input type=\"text\" class=\"form-control\">\n            <div class=\"input-group-btn\">\n              <button type=\"button\" class=\"btn btn-default\" tabindex=\"-1\">Action</button>\n              <button type=\"button\" class=\"btn btn-default dropdown-toggle\" data-toggle=\"dropdown\" tabindex=\"-1\">\n                <span class=\"caret\"></span>\n              </button>\n              <ul class=\"dropdown-menu pull-right\" role=\"menu\">\n                <li><a href=\"#\">Action</a></li>\n                <li><a href=\"#\">Another action</a></li>\n                <li><a href=\"#\">Something else here</a></li>\n                <li class=\"divider\"></li>\n                <li><a href=\"#\">Separated link</a></li>\n              </ul>\n            </div>\n          </div><!-- /.input-group -->\n        </div><!-- /.col-lg-6 -->\n      </div><!-- /.row -->\n    </form>\n{% highlight html %}\n<div class=\"input-group\">\n  <div class=\"input-group-btn\">\n    <!-- Button and dropdown menu -->\n  </div>\n  <input type=\"text\" class=\"form-control\">\n</div>\n\n<div class=\"input-group\">\n  <input type=\"text\" class=\"form-control\">\n  <div class=\"input-group-btn btn-group\">\n    <!-- Button and dropdown menu -->\n  </div>\n</div>\n{% endhighlight %}\n\n</div>\n\n\n\n  <!-- Navs\n  ================================================== -->\n  <div class=\"bs-docs-section\">\n    <div class=\"page-header\">\n      <h1 id=\"nav\">Navs</h1>\n    </div>\n\n    <p class=\"lead\">Navs available in Bootstrap have shared markup, starting with the base <code>.nav</code> class, as well as shared states. Swap modifier classes to switch between each style.</p>\n\n    <h2 id=\"nav-tabs\">Tabs</h2>\n    <p>Note the <code>.nav-tabs</code> class requires the <code>.nav</code> base class.</p>\n    <div class=\"bs-example\">\n      <ul class=\"nav nav-tabs\">\n        <li class=\"active\"><a href=\"#\">Home</a></li>\n        <li><a href=\"#\">Profile</a></li>\n        <li><a href=\"#\">Messages</a></li>\n      </ul>\n    </div>\n{% highlight html %}\n<ul class=\"nav nav-tabs\">\n  <li class=\"active\"><a href=\"#\">Home</a></li>\n  <li><a href=\"#\">Profile</a></li>\n  <li><a href=\"#\">Messages</a></li>\n</ul>\n{% endhighlight %}\n\n    <h2 id=\"nav-pills\">Pills</h2>\n    <p>Take that same HTML, but use <code>.nav-pills</code> instead:</p>\n    <div class=\"bs-example\">\n      <ul class=\"nav nav-pills\">\n        <li class=\"active\"><a href=\"#\">Home</a></li>\n        <li><a href=\"#\">Profile</a></li>\n        <li><a href=\"#\">Messages</a></li>\n      </ul>\n    </div>\n{% highlight html %}\n<ul class=\"nav nav-pills\">\n  <li class=\"active\"><a href=\"#\">Home</a></li>\n  <li><a href=\"#\">Profile</a></li>\n  <li><a href=\"#\">Messages</a></li>\n</ul>\n{% endhighlight %}\n    <p>Pills are also vertically stackable. Just add <code>.nav-stacked</code>.</p>\n    <div class=\"bs-example\">\n      <ul class=\"nav nav-pills nav-stacked\" style=\"max-width: 300px;\">\n        <li class=\"active\"><a href=\"#\">Home</a></li>\n        <li><a href=\"#\">Profile</a></li>\n        <li><a href=\"#\">Messages</a></li>\n      </ul>\n    </div>\n{% highlight html %}\n<ul class=\"nav nav-pills nav-stacked\">\n  ...\n</ul>\n{% endhighlight %}\n\n\n    <h2 id=\"nav-justified\">Justified</h2>\n    <p>Easily make tabs or pills equal widths of their parent with <code>.nav-justified</code>.</p>\n    <div class=\"bs-example\">\n      <ul class=\"nav nav-tabs nav-justified\">\n        <li class=\"active\"><a href=\"#\">Home</a></li>\n        <li><a href=\"#\">Profile</a></li>\n        <li><a href=\"#\">Messages</a></li>\n      </ul>\n      <br>\n      <ul class=\"nav nav-pills nav-justified\">\n        <li class=\"active\"><a href=\"#\">Home</a></li>\n        <li><a href=\"#\">Profile</a></li>\n        <li><a href=\"#\">Messages</a></li>\n      </ul>\n    </div>\n{% highlight html %}\n<ul class=\"nav nav-tabs nav-justified\">\n  ...\n</ul>\n<ul class=\"nav nav-pills nav-justified\">\n  ...\n</ul>\n{% endhighlight %}\n\n\n    <h2 id=\"nav-disabled-links\">Disabled links</h2>\n    <p>For any nav component (tabs, pills, or list), add <code>.disabled</code> for <strong>gray links and no hover effects</strong>.</p>\n\n    <div class=\"bs-callout bs-callout-warning\">\n      <h4>Link functionality not impacted</h4>\n      <p>This class will only change the <code>&lt;a&gt;</code>'s appearance, not its functionality. Use custom JavaScript to disable links here.</p>\n    </div>\n\n    <div class=\"bs-example\">\n      <ul class=\"nav nav-pills\">\n        <li><a href=\"#\">Clickable link</a></li>\n        <li><a href=\"#\">Clickable link</a></li>\n        <li class=\"disabled\"><a href=\"#\">Disabled link</a></li>\n      </ul>\n    </div>\n{% highlight html %}\n<ul class=\"nav nav-pills\">\n  ...\n  <li class=\"disabled\"><a href=\"#\">Disabled link</a></li>\n  ...\n</ul>\n{% endhighlight %}\n\n\n    <h2 id=\"nav-dropdowns\">Using dropdowns</h2>\n    <p>Add dropdown menus with a little extra HTML and the <a href=\"../javascript/#dropdowns\">dropdowns JavaScript plugin</a>.</p>\n\n    <h3>Tabs with dropdowns</h3>\n    <div class=\"bs-example\">\n  <ul class=\"nav nav-tabs\">\n    <li class=\"active\"><a href=\"#\">Home</a></li>\n    <li><a href=\"#\">Help</a></li>\n    <li class=\"dropdown\">\n      <a class=\"dropdown-toggle\" data-toggle=\"dropdown\" href=\"#\">\n        Dropdown <span class=\"caret\"></span>\n      </a>\n      <ul class=\"dropdown-menu\" role=\"menu\">\n        <li><a href=\"#\">Action</a></li>\n        <li><a href=\"#\">Another action</a></li>\n        <li><a href=\"#\">Something else here</a></li>\n        <li class=\"divider\"></li>\n        <li><a href=\"#\">Separated link</a></li>\n      </ul>\n    </li>\n  </ul>\n    </div>\n{% highlight html %}\n<ul class=\"nav nav-tabs\">\n  ...\n  <li class=\"dropdown\">\n    <a class=\"dropdown-toggle\" data-toggle=\"dropdown\" href=\"#\">\n      Dropdown <span class=\"caret\"></span>\n    </a>\n    <ul class=\"dropdown-menu\">\n      ...\n    </ul>\n  </li>\n  ...\n</ul>\n{% endhighlight %}\n\n    <h3>Pills with dropdowns</h3>\n    <div class=\"bs-example\">\n      <ul class=\"nav nav-pills\">\n        <li class=\"active\"><a href=\"#\">Home</a></li>\n        <li><a href=\"#\">Help</a></li>\n        <li class=\"dropdown\">\n          <a class=\"dropdown-toggle\" data-toggle=\"dropdown\" href=\"#\">\n            Dropdown <span class=\"caret\"></span>\n          </a>\n          <ul class=\"dropdown-menu\" role=\"menu\">\n            <li><a href=\"#\">Action</a></li>\n            <li><a href=\"#\">Another action</a></li>\n            <li><a href=\"#\">Something else here</a></li>\n            <li class=\"divider\"></li>\n            <li><a href=\"#\">Separated link</a></li>\n          </ul>\n        </li>\n      </ul>\n    </div><!-- /example -->\n{% highlight html %}\n<ul class=\"nav nav-pills\">\n  ...\n  <li class=\"dropdown\">\n    <a class=\"dropdown-toggle\" data-toggle=\"dropdown\" href=\"#\">\n      Dropdown <span class=\"caret\"></span>\n    </a>\n    <ul class=\"dropdown-menu\">\n      ...\n    </ul>\n  </li>\n  ...\n</ul>\n{% endhighlight %}\n\n  </div>\n\n\n\n  <!-- Navbar\n  ================================================== -->\n  <div class=\"bs-docs-section\">\n    <div class=\"page-header\">\n      <h1 id=\"navbar\">Navbar</h1>\n    </div>\n\n    <h2 id=\"navbar-default\">Default navbar</h2>\n    <p>Navbars are responsive meta components that serve as navigation headers for your application or site. They begin collapsed (and are toggleable) in mobile views and become horizontal as the available viewport width increases.</p>\n\n    <div class=\"bs-callout bs-callout-info\">\n      <h4>Customize the collapsing point</h4>\n      <p>Depending on the content in your navbar, you might need to change the point at which your navbar switches between collapsed and horizontal mode. Customize the <code>@grid-float-breakpoint</code> variable or add your own media query.</p>\n    </div>\n\n    <div class=\"bs-example\">\n      <nav class=\"navbar navbar-default\" role=\"navigation\">\n        <!-- Brand and toggle get grouped for better mobile display -->\n        <div class=\"navbar-header\">\n          <button type=\"button\" class=\"navbar-toggle\" data-toggle=\"collapse\" data-target=\".navbar-ex1-collapse\">\n            <span class=\"sr-only\">Toggle navigation</span>\n            <span class=\"icon-bar\"></span>\n            <span class=\"icon-bar\"></span>\n            <span class=\"icon-bar\"></span>\n          </button>\n          <a class=\"navbar-brand\" href=\"#\">Brand</a>\n        </div>\n\n        <!-- Collect the nav links, forms, and other content for toggling -->\n        <div class=\"collapse navbar-collapse navbar-ex1-collapse\">\n          <ul class=\"nav navbar-nav\">\n            <li class=\"active\"><a href=\"#\">Link</a></li>\n            <li><a href=\"#\">Link</a></li>\n            <li class=\"dropdown\">\n              <a href=\"#\" class=\"dropdown-toggle\" data-toggle=\"dropdown\">Dropdown <b class=\"caret\"></b></a>\n              <ul class=\"dropdown-menu\" role=\"menu\">\n                <li><a href=\"#\">Action</a></li>\n                <li><a href=\"#\">Another action</a></li>\n                <li><a href=\"#\">Something else here</a></li>\n                <li><a href=\"#\">Separated link</a></li>\n                <li><a href=\"#\">One more separated link</a></li>\n              </ul>\n            </li>\n          </ul>\n          <form class=\"navbar-form navbar-left\" role=\"search\">\n            <div class=\"form-group\">\n              <input type=\"text\" class=\"form-control\" placeholder=\"Search\">\n            </div>\n            <button type=\"submit\" class=\"btn btn-default\">Submit</button>\n          </form>\n          <ul class=\"nav navbar-nav navbar-right\">\n            <li><a href=\"#\">Link</a></li>\n            <li class=\"dropdown\">\n              <a href=\"#\" class=\"dropdown-toggle\" data-toggle=\"dropdown\">Dropdown <b class=\"caret\"></b></a>\n              <ul class=\"dropdown-menu\" role=\"menu\">\n                <li><a href=\"#\">Action</a></li>\n                <li><a href=\"#\">Another action</a></li>\n                <li><a href=\"#\">Something else here</a></li>\n                <li><a href=\"#\">Separated link</a></li>\n              </ul>\n            </li>\n          </ul>\n        </div><!-- /.navbar-collapse -->\n      </nav>\n    </div>\n{% highlight html %}\n<nav class=\"navbar navbar-default\" role=\"navigation\">\n  <!-- Brand and toggle get grouped for better mobile display -->\n  <div class=\"navbar-header\">\n    <button type=\"button\" class=\"navbar-toggle\" data-toggle=\"collapse\" data-target=\".navbar-ex1-collapse\">\n      <span class=\"sr-only\">Toggle navigation</span>\n      <span class=\"icon-bar\"></span>\n      <span class=\"icon-bar\"></span>\n      <span class=\"icon-bar\"></span>\n    </button>\n    <a class=\"navbar-brand\" href=\"#\">Brand</a>\n  </div>\n\n  <!-- Collect the nav links, forms, and other content for toggling -->\n  <div class=\"collapse navbar-collapse navbar-ex1-collapse\">\n    <ul class=\"nav navbar-nav\">\n      <li class=\"active\"><a href=\"#\">Link</a></li>\n      <li><a href=\"#\">Link</a></li>\n      <li class=\"dropdown\">\n        <a href=\"#\" class=\"dropdown-toggle\" data-toggle=\"dropdown\">Dropdown <b class=\"caret\"></b></a>\n        <ul class=\"dropdown-menu\">\n          <li><a href=\"#\">Action</a></li>\n          <li><a href=\"#\">Another action</a></li>\n          <li><a href=\"#\">Something else here</a></li>\n          <li><a href=\"#\">Separated link</a></li>\n          <li><a href=\"#\">One more separated link</a></li>\n        </ul>\n      </li>\n    </ul>\n    <form class=\"navbar-form navbar-left\" role=\"search\">\n      <div class=\"form-group\">\n        <input type=\"text\" class=\"form-control\" placeholder=\"Search\">\n      </div>\n      <button type=\"submit\" class=\"btn btn-default\">Submit</button>\n    </form>\n    <ul class=\"nav navbar-nav navbar-right\">\n      <li><a href=\"#\">Link</a></li>\n      <li class=\"dropdown\">\n        <a href=\"#\" class=\"dropdown-toggle\" data-toggle=\"dropdown\">Dropdown <b class=\"caret\"></b></a>\n        <ul class=\"dropdown-menu\">\n          <li><a href=\"#\">Action</a></li>\n          <li><a href=\"#\">Another action</a></li>\n          <li><a href=\"#\">Something else here</a></li>\n          <li><a href=\"#\">Separated link</a></li>\n        </ul>\n      </li>\n    </ul>\n  </div><!-- /.navbar-collapse -->\n</nav>\n{% endhighlight %}\n\n<div class=\"bs-callout bs-callout-danger\">\n  <h4>Plugin dependency</h4>\n  <p>The responsive navbar requires the <a href=\"../javascript/#collapse\">collapse plugin</a> to be included in your version of Bootstrap.</p>\n</div>\n\n<div class=\"bs-callout bs-callout-warning\">\n  <h4>Make navbars accessible</h4>\n  <p>Be sure to add a <code>role=\"navigation\"</code> to every navbar to help with accessibility.</p>\n</div>\n\n\n    <h2 id=\"navbar-buttons\">Buttons</h2>\n    <p>For buttons not residing in a <code>&lt;form&gt;</code>, add this class to vertically center buttons within a navbar.</p>\n    <div class=\"bs-example\">\n      <nav class=\"navbar navbar-default\" role=\"navigation\">\n        <div class=\"navbar-header\">\n          <button type=\"button\" class=\"navbar-toggle\" data-toggle=\"collapse\" data-target=\".navbar-ex2-collapse\">\n            <span class=\"sr-only\">Toggle navigation</span>\n            <span class=\"icon-bar\"></span>\n            <span class=\"icon-bar\"></span>\n            <span class=\"icon-bar\"></span>\n          </button>\n          <a class=\"navbar-brand\" href=\"#\">Brand</a>\n        </div>\n        <div class=\"collapse navbar-collapse navbar-ex2-collapse\">\n          <button type=\"button\" class=\"btn btn-default navbar-btn\">Sign in</button>\n        </div>\n      </nav>\n    </div>\n{% highlight html %}\n<button type=\"button\" class=\"btn btn-default navbar-btn\">Sign in</button>\n{% endhighlight %}\n\n\n    <h2 id=\"navbar-text\">Text</h2>\n    <p>Wrap strings of text in an element with <code>.navbar-text</code>, usually on a <code>&lt;p&gt;</code> tag for proper leading and color.</p>\n    <div class=\"bs-example\">\n      <nav class=\"navbar navbar-default\" role=\"navigation\">\n        <div class=\"navbar-header\">\n          <button type=\"button\" class=\"navbar-toggle\" data-toggle=\"collapse\" data-target=\".navbar-ex3-collapse\">\n            <span class=\"sr-only\">Toggle navigation</span>\n            <span class=\"icon-bar\"></span>\n            <span class=\"icon-bar\"></span>\n            <span class=\"icon-bar\"></span>\n          </button>\n          <a class=\"navbar-brand\" href=\"#\">Brand</a>\n        </div>\n        <div class=\"collapse navbar-collapse navbar-ex3-collapse\">\n          <p class=\"navbar-text\">Signed in as Mark Otto</p>\n        </div>\n      </nav>\n    </div>\n{% highlight html %}\n<p class=\"navbar-text\">Signed in as Mark Otto</p>\n{% endhighlight %}\n\n\n    <h2 id=\"navbar-links\">Non-nav links</h2>\n    <p>For folks using standard links that are not within the regular navbar navigation component, use the <code>.navbar-link</code> class to add the proper colors for the default and inverse navbar options.</p>\n    <div class=\"bs-example\">\n      <nav class=\"navbar navbar-default\" role=\"navigation\">\n        <div class=\"navbar-header\">\n          <button type=\"button\" class=\"navbar-toggle\" data-toggle=\"collapse\" data-target=\".navbar-ex4-collapse\">\n            <span class=\"sr-only\">Toggle navigation</span>\n            <span class=\"icon-bar\"></span>\n            <span class=\"icon-bar\"></span>\n            <span class=\"icon-bar\"></span>\n          </button>\n          <a class=\"navbar-brand\" href=\"#\">Brand</a>\n        </div>\n        <div class=\"collapse navbar-collapse navbar-ex4-collapse\">\n          <p class=\"navbar-text pull-right\">Signed in as <a href=\"#\" class=\"navbar-link\">Mark Otto</a></p>\n        </div>\n      </nav>\n    </div>\n{% highlight html %}\n<p class=\"navbar-text pull-right\">Signed in as <a href=\"#\" class=\"navbar-link\">Mark Otto</a></p>\n{% endhighlight %}\n\n\n    <h2 id=\"navbar-component-alignment\">Component alignment</h2>\n    <p>Align nav links, forms, buttons, or text, using the <code>.navbar-left</code> or <code>.navbar-right</code> utility classes. Both classes will add a CSS float in the specified direction. For example, to align nav links, put them in a separate <code>&lt;ul&gt;</code> with the respective utility class applied.</p>\n    <p>These classes are mixin-ed versions of <code>.pull-left</code> and <code>.pull-right</code>, but they're scoped to media queries for easier handling of navbar components across device sizes.</p>\n\n\n    <h2 id=\"navbar-fixed-top\">Fixed to top</h2>\n    <p>Add <code>.navbar-fixed-top</code>.</p>\n    <div class=\"bs-example bs-navbar-top-example\">\n      <nav class=\"navbar navbar-default navbar-fixed-top\" role=\"navigation\">\n        <!-- Brand and toggle get grouped for better mobile display -->\n        <div class=\"navbar-header\">\n          <button type=\"button\" class=\"navbar-toggle\" data-toggle=\"collapse\" data-target=\".navbar-ex5-collapse\">\n            <span class=\"sr-only\">Toggle navigation</span>\n            <span class=\"icon-bar\"></span>\n            <span class=\"icon-bar\"></span>\n            <span class=\"icon-bar\"></span>\n          </button>\n          <a class=\"navbar-brand\" href=\"#\">Brand</a>\n        </div>\n\n        <!-- Collect the nav links, forms, and other content for toggling -->\n        <div class=\"collapse navbar-collapse navbar-ex5-collapse\">\n          <ul class=\"nav navbar-nav\">\n            <li class=\"active\"><a href=\"#\">Home</a></li>\n            <li><a href=\"#\">Link</a></li>\n            <li><a href=\"#\">Link</a></li>\n          </ul>\n        </div><!-- /.navbar-collapse -->\n      </nav>\n    </div><!-- /example -->\n{% highlight html %}\n<nav class=\"navbar navbar-default navbar-fixed-top\" role=\"navigation\">\n  ...\n</nav>\n{% endhighlight %}\n\n    <div class=\"bs-callout bs-callout-danger\">\n      <h4>Body padding required</h4>\n      <p>The fixed navbar will overlay your other content, unless you add <code>padding</code> to the top of the <code>&lt;body&gt;</code>. Try out your own values or use our snippet below. Tip: By default, the navbar is 50px high.</p>\n{% highlight css %}\nbody { padding-top: 70px; }\n{% endhighlight %}\n      <p>Make sure to include this <strong>after</strong> the core Bootstrap CSS.</p>\n    </div>\n\n\n    <h2 id=\"navbar-fixed-bottom\">Fixed to bottom</h2>\n    <p>Add <code>.navbar-fixed-bottom</code> instead.</p>\n    <div class=\"bs-example bs-navbar-bottom-example\">\n      <nav class=\"navbar navbar-default navbar-fixed-bottom\" role=\"navigation\">\n        <!-- Brand and toggle get grouped for better mobile display -->\n        <div class=\"navbar-header\">\n          <button type=\"button\" class=\"navbar-toggle\" data-toggle=\"collapse\" data-target=\".navbar-ex6-collapse\">\n            <span class=\"sr-only\">Toggle navigation</span>\n            <span class=\"icon-bar\"></span>\n            <span class=\"icon-bar\"></span>\n            <span class=\"icon-bar\"></span>\n          </button>\n          <a class=\"navbar-brand\" href=\"#\">Brand</a>\n        </div>\n\n        <!-- Collect the nav links, forms, and other content for toggling -->\n        <div class=\"collapse navbar-collapse navbar-ex6-collapse\">\n          <ul class=\"nav navbar-nav\">\n            <li class=\"active\"><a href=\"#\">Home</a></li>\n            <li><a href=\"#\">Link</a></li>\n            <li><a href=\"#\">Link</a></li>\n          </ul>\n        </div><!-- /.navbar-collapse -->\n      </nav>\n    </div><!-- /example -->\n{% highlight html %}\n<nav class=\"navbar navbar-default navbar-fixed-bottom\" role=\"navigation\">\n  ...\n</nav>\n{% endhighlight %}\n\n    <div class=\"bs-callout bs-callout-danger\">\n      <h4>Body padding required</h4>\n      <p>The fixed navbar will overlay your other content, unless you add <code>padding</code> to the bottom of the <code>&lt;body&gt;</code>. Try out your own values or use our snippet below. Tip: By default, the navbar is 50px high.</p>\n{% highlight css %}\nbody { padding-bottom: 70px; }\n{% endhighlight %}\n      <p>Make sure to include this <strong>after</strong> the core Bootstrap CSS.</p>\n    </div>\n\n\n    <h2 id=\"navbar-static-top\">Static top</h2>\n    <p>Create a full-width navbar that scrolls away with the page by adding <code>.navbar-static-top</code>. Unlike the <code>.navbar-fixed-*</code> classes, you do not need to change any padding on the <code>body</code>.</p>\n    <div class=\"bs-example bs-navbar-top-example\">\n      <nav class=\"navbar navbar-default navbar-static-top\" role=\"navigation\">\n        <!-- Brand and toggle get grouped for better mobile display -->\n        <div class=\"navbar-header\">\n          <button type=\"button\" class=\"navbar-toggle\" data-toggle=\"collapse\" data-target=\".navbar-ex7-collapse\">\n            <span class=\"sr-only\">Toggle navigation</span>\n            <span class=\"icon-bar\"></span>\n            <span class=\"icon-bar\"></span>\n            <span class=\"icon-bar\"></span>\n          </button>\n          <a class=\"navbar-brand\" href=\"#\">Brand</a>\n        </div>\n\n        <!-- Collect the nav links, forms, and other content for toggling -->\n        <div class=\"collapse navbar-collapse navbar-ex7-collapse\">\n          <ul class=\"nav navbar-nav\">\n            <li class=\"active\"><a href=\"#\">Home</a></li>\n            <li><a href=\"#\">Link</a></li>\n            <li><a href=\"#\">Link</a></li>\n          </ul>\n        </div><!-- /.navbar-collapse -->\n      </nav>\n    </div><!-- /example -->\n{% highlight html %}\n<nav class=\"navbar navbar-default navbar-static-top\" role=\"navigation\">\n  ...\n</nav>\n{% endhighlight %}\n\n\n    <h2 id=\"navbar-inverted\">Inverted navbar</h2>\n    <p>Modify the look of the navbar by adding <code>.navbar-inverse</code>.</p>\n    <div class=\"bs-example\">\n      <nav class=\"navbar navbar-inverse\" role=\"navigation\">\n        <!-- Brand and toggle get grouped for better mobile display -->\n        <div class=\"navbar-header\">\n          <button type=\"button\" class=\"navbar-toggle\" data-toggle=\"collapse\" data-target=\".navbar-ex8-collapse\">\n            <span class=\"sr-only\">Toggle navigation</span>\n            <span class=\"icon-bar\"></span>\n            <span class=\"icon-bar\"></span>\n            <span class=\"icon-bar\"></span>\n          </button>\n          <a class=\"navbar-brand\" href=\"#\">Brand</a>\n        </div>\n\n        <!-- Collect the nav links, forms, and other content for toggling -->\n        <div class=\"collapse navbar-collapse navbar-ex8-collapse\">\n          <ul class=\"nav navbar-nav\">\n            <li class=\"active\"><a href=\"#\">Home</a></li>\n            <li><a href=\"#\">Link</a></li>\n            <li><a href=\"#\">Link</a></li>\n          </ul>\n        </div><!-- /.navbar-collapse -->\n      </nav>\n    </div><!-- /example -->\n{% highlight html %}\n<nav class=\"navbar navbar-inverse\" role=\"navigation\">\n  ...\n</nav>\n{% endhighlight %}\n\n  </div>\n\n\n\n  <!-- Breadcrumbs\n  ================================================== -->\n  <div class=\"bs-docs-section\">\n    <div class=\"page-header\">\n      <h1 id=\"breadcrumbs\">Breadcrumbs <small></small></h1>\n    </div>\n    <p class=\"lead\">Indicate the current page's location within a navigational hierarchy.</p>\n    <p>Separators are automatically added in CSS through <code>:before</code> and <code>content</code>.</p>\n    <div class=\"bs-example\">\n      <ol class=\"breadcrumb\">\n        <li class=\"active\">Home</li>\n      </ol>\n      <ol class=\"breadcrumb\">\n        <li><a href=\"#\">Home</a></li>\n        <li class=\"active\">Library</li>\n      </ol>\n      <ol class=\"breadcrumb\" style=\"margin-bottom: 5px;\">\n        <li><a href=\"#\">Home</a></li>\n        <li><a href=\"#\">Library</a></li>\n        <li class=\"active\">Data</li>\n      </ol>\n    </div>\n{% highlight html %}\n<ol class=\"breadcrumb\">\n  <li><a href=\"#\">Home</a></li>\n  <li><a href=\"#\">Library</a></li>\n  <li class=\"active\">Data</li>\n</ol>\n{% endhighlight %}\n  </div>\n\n\n\n  <!-- Pagination\n  ================================================== -->\n  <div class=\"bs-docs-section\">\n    <div class=\"page-header\">\n      <h1 id=\"pagination\">Pagination</h1>\n    </div>\n    <p class=\"lead\">Provide pagination links for your site or app with the multi-page pagination component, or the simpler <a href=\"#pagination-pager\">pager alternative</a>.</p>\n\n    <h2 id=\"pagination-default\">Default pagination</h2>\n    <p>Simple pagination inspired by Rdio, great for apps and search results. The large block is hard to miss, easily scalable, and provides large click areas.</p>\n    <div class=\"bs-example\">\n      <ul class=\"pagination\">\n        <li><a href=\"#\">&laquo;</a></li>\n        <li><a href=\"#\">1</a></li>\n        <li><a href=\"#\">2</a></li>\n        <li><a href=\"#\">3</a></li>\n        <li><a href=\"#\">4</a></li>\n        <li><a href=\"#\">5</a></li>\n        <li><a href=\"#\">&raquo;</a></li>\n      </ul>\n    </div>\n{% highlight html %}\n<ul class=\"pagination\">\n  <li><a href=\"#\">&laquo;</a></li>\n  <li><a href=\"#\">1</a></li>\n  <li><a href=\"#\">2</a></li>\n  <li><a href=\"#\">3</a></li>\n  <li><a href=\"#\">4</a></li>\n  <li><a href=\"#\">5</a></li>\n  <li><a href=\"#\">&raquo;</a></li>\n</ul>\n{% endhighlight %}\n\n    <h3>Disabled and active states</h3>\n    <p>Links are customizable for different circumstances. Use <code>.disabled</code> for unclickable links and <code>.active</code> to indicate the current page.</p>\n    <div class=\"bs-example\">\n      <ul class=\"pagination\">\n        <li class=\"disabled\"><a href=\"#\">&laquo;</a></li>\n        <li class=\"active\"><a href=\"#\">1 <span class=\"sr-only\">(current)</span></a></li>\n        <li><a href=\"#\">2</a></li>\n        <li><a href=\"#\">3</a></li>\n        <li><a href=\"#\">4</a></li>\n        <li><a href=\"#\">5</a></li>\n        <li><a href=\"#\">&raquo;</a></li>\n     </ul>\n    </div>\n{% highlight html %}\n<ul class=\"pagination\">\n  <li class=\"disabled\"><a href=\"#\">&laquo;</a></li>\n  <li class=\"active\"><a href=\"#\">1 <span class=\"sr-only\">(current)</span></a></li>\n  ...\n</ul>\n{% endhighlight %}\n    <p>You can optionally swap out active or disabled anchors for <code>&lt;span&gt;</code> to remove click functionality while retaining intended styles.</p>\n{% highlight html %}\n<ul class=\"pagination\">\n  <li class=\"disabled\"><span>&laquo;</span></li>\n  <li class=\"active\"><span>1 <span class=\"sr-only\">(current)</span></span></li>\n  ...\n</ul>\n{% endhighlight %}\n\n\n    <h3>Sizing</h3>\n    <p>Fancy larger or smaller pagination? Add <code>.pagination-lg</code> or <code>.pagination-sm</code> for additional sizes.</p>\n    <div class=\"bs-example\">\n      <div>\n        <ul class=\"pagination pagination-lg\">\n          <li><a href=\"#\">&laquo;</a></li>\n          <li><a href=\"#\">1</a></li>\n          <li><a href=\"#\">2</a></li>\n          <li><a href=\"#\">3</a></li>\n          <li><a href=\"#\">4</a></li>\n          <li><a href=\"#\">5</a></li>\n          <li><a href=\"#\">&raquo;</a></li>\n        </ul>\n      </div>\n      <div>\n        <ul class=\"pagination\">\n          <li><a href=\"#\">&laquo;</a></li>\n          <li><a href=\"#\">1</a></li>\n          <li><a href=\"#\">2</a></li>\n          <li><a href=\"#\">3</a></li>\n          <li><a href=\"#\">4</a></li>\n          <li><a href=\"#\">5</a></li>\n          <li><a href=\"#\">&raquo;</a></li>\n        </ul>\n      </div>\n      <div>\n        <ul class=\"pagination pagination-sm\">\n          <li><a href=\"#\">&laquo;</a></li>\n          <li><a href=\"#\">1</a></li>\n          <li><a href=\"#\">2</a></li>\n          <li><a href=\"#\">3</a></li>\n          <li><a href=\"#\">4</a></li>\n          <li><a href=\"#\">5</a></li>\n          <li><a href=\"#\">&raquo;</a></li>\n        </ul>\n      </div>\n    </div>\n{% highlight html %}\n<ul class=\"pagination pagination-lg\">...</ul>\n<ul class=\"pagination\">...</ul>\n<ul class=\"pagination pagination-sm\">...</ul>\n{% endhighlight %}\n\n\n    <h2 id=\"pagination-pager\">Pager</h2>\n    <p>Quick previous and next links for simple pagination implementations with light markup and styles. It's great for simple sites like blogs or magazines.</p>\n\n    <h3>Default example</h3>\n    <p>By default, the pager centers links.</p>\n    <div class=\"bs-example\">\n      <ul class=\"pager\">\n        <li><a href=\"#\">Previous</a></li>\n        <li><a href=\"#\">Next</a></li>\n      </ul>\n    </div>\n{% highlight html %}\n<ul class=\"pager\">\n  <li><a href=\"#\">Previous</a></li>\n  <li><a href=\"#\">Next</a></li>\n</ul>\n{% endhighlight %}\n\n    <h3>Aligned links</h3>\n    <p>Alternatively, you can align each link to the sides:</p>\n    <div class=\"bs-example\">\n      <ul class=\"pager\">\n        <li class=\"previous\"><a href=\"#\">&larr; Older</a></li>\n        <li class=\"next\"><a href=\"#\">Newer &rarr;</a></li>\n      </ul>\n    </div>\n{% highlight html %}\n<ul class=\"pager\">\n  <li class=\"previous\"><a href=\"#\">&larr; Older</a></li>\n  <li class=\"next\"><a href=\"#\">Newer &rarr;</a></li>\n</ul>\n{% endhighlight %}\n\n\n    <h3>Optional disabled state</h3>\n    <p>Pager links also use the general <code>.disabled</code> utility class from the pagination.</p>\n    <div class=\"bs-example\">\n      <ul class=\"pager\">\n        <li class=\"previous disabled\"><a href=\"#\">&larr; Older</a></li>\n        <li class=\"next\"><a href=\"#\">Newer &rarr;</a></li>\n      </ul>\n    </div>\n{% highlight html %}\n<ul class=\"pager\">\n  <li class=\"previous disabled\"><a href=\"#\">&larr; Older</a></li>\n  <li class=\"next\"><a href=\"#\">Newer &rarr;</a></li>\n</ul>\n{% endhighlight %}\n  </div>\n\n\n\n  <!-- Labels\n  ================================================== -->\n  <div class=\"bs-docs-section\">\n    <div class=\"page-header\">\n      <h1 id=\"labels\">Labels</h1>\n    </div>\n    <p class=\"lead\"></p>\n\n    <h3>Example</h3>\n    <div class=\"bs-example\">\n      <h1>Example heading <span class=\"label label-default\">New</span></h1>\n      <h2>Example heading <span class=\"label label-default\">New</span></h2>\n      <h3>Example heading <span class=\"label label-default\">New</span></h3>\n      <h4>Example heading <span class=\"label label-default\">New</span></h4>\n      <h5>Example heading <span class=\"label label-default\">New</span></h5>\n      <h6>Example heading <span class=\"label label-default\">New</span></h6>\n    </div>\n{% highlight html %}\n<h3>Example heading <span class=\"label label-default\">New</span></h3>\n{% endhighlight %}\n\n    <h3>Available variations</h3>\n    <p>Add any of the below mentioned modifier classes to change the appearance of a label.</p>\n    <div class=\"bs-example\">\n      <span class=\"label label-default\">Default</span>\n      <span class=\"label label-primary\">Primary</span>\n      <span class=\"label label-success\">Success</span>\n      <span class=\"label label-info\">Info</span>\n      <span class=\"label label-warning\">Warning</span>\n      <span class=\"label label-danger\">Danger</span>\n    </div>\n{% highlight html %}\n<span class=\"label label-default\">Default</span>\n<span class=\"label label-primary\">Primary</span>\n<span class=\"label label-success\">Success</span>\n<span class=\"label label-info\">Info</span>\n<span class=\"label label-warning\">Warning</span>\n<span class=\"label label-danger\">Danger</span>\n{% endhighlight %}\n\n  </div>\n\n\n\n  <!-- Badges\n  ================================================== -->\n  <div class=\"bs-docs-section\">\n    <div class=\"page-header\">\n      <h1 id=\"badges\">Badges</h1>\n    </div>\n    <p class=\"lead\">Easily highlight new or unread items by adding a <code>&lt;span class=\"badge\"&gt;</code> to links, Bootstrap navs, and more.</p>\n\n    <div class=\"bs-example\">\n      <a href=\"#\">Inbox <span class=\"badge\">42</span></a>\n    </div>\n{% highlight html %}\n<a href=\"#\">Inbox <span class=\"badge\">42</span></a>\n{% endhighlight %}\n\n    <h4>Self collapsing</h4>\n    <p>When there are no new or unread items, badges will simply collapse (via CSS's <code>:empty</code> selector) provided no content exists within.</p>\n\n    <div class=\"bs-callout bs-callout-danger\">\n      <h4>Cross-browser compatibility</h4>\n      <p>Badges won't self collapse in Internet Explorer 8 because it lacks support for the <code>:empty</code> selector.</p>\n    </div>\n\n    <h4>Adapts to active nav states</h4>\n    <p>Built-in styles are included for placing badges in active states in pill and list navigations.</p>\n    <div class=\"bs-example\">\n      <ul class=\"nav nav-pills\">\n        <li class=\"active\"><a href=\"#\">Home <span class=\"badge\">42</span></a></li>\n        <li><a href=\"#\">Profile</a></li>\n        <li><a href=\"#\">Messages <span class=\"badge\">3</span></a></li>\n      </ul>\n      <br>\n      <ul class=\"nav nav-pills nav-stacked\" style=\"max-width: 260px;\">\n        <li class=\"active\">\n          <a href=\"#\">\n            <span class=\"badge pull-right\">42</span>\n            Home\n          </a>\n        </li>\n        <li><a href=\"#\">Profile</a></li>\n        <li>\n          <a href=\"#\">\n            <span class=\"badge pull-right\">3</span>\n            Messages\n          </a>\n        </li>\n      </ul>\n    </div>\n{% highlight html %}\n<ul class=\"nav nav-pills nav-stacked\">\n  <li class=\"active\">\n    <a href=\"#\">\n      <span class=\"badge pull-right\">42</span>\n      Home\n    </a>\n  </li>\n  ...\n</ul>\n{% endhighlight %}\n  </div>\n\n\n\n  <!-- Jumbotron\n  ================================================== -->\n  <div class=\"bs-docs-section\">\n    <div class=\"page-header\">\n      <h1 id=\"jumbotron\">Jumbotron</h1>\n    </div>\n    <p>A lightweight, flexible component that can optional extend the entire viewport to showcase key content on your site. To make the jumbotron full width, don't include it within a <code>.container</code>. Placing it within a container will keep it at the width of the rest of your content and provide rounded corners.</p>\n    <div class=\"bs-example\">\n      <div class=\"jumbotron\">\n        <div class=\"container\">\n          <h1>Hello, world!</h1>\n          <p>This is a simple hero unit, a simple jumbotron-style component for calling extra attention to featured content or information.</p>\n          <p><a class=\"btn btn-primary btn-lg\">Learn more</a></p>\n        </div>\n      </div>\n    </div>\n{% highlight html %}\n<div class=\"jumbotron\">\n  <div class=\"container\">\n    <h1>Hello, world!</h1>\n    <p>...</p>\n    <p><a class=\"btn btn-primary btn-lg\">Learn more</a></p>\n  </div>\n</div>\n{% endhighlight %}\n  </div>\n\n\n\n  <!-- Page header\n  ================================================== -->\n  <div class=\"bs-docs-section\">\n    <div class=\"page-header\">\n      <h1 id=\"page-header\">Page header</h1>\n    </div>\n    <p>A simple shell for an <code>h1</code> to appropriately space out and segment sections of content on a page. It can utilize the <code>h1</code>'s default <code>small</code> element, as well as most other components (with additional styles).</p>\n    <div class=\"bs-example\">\n      <div class=\"page-header\">\n        <h1>Example page header <small>Subtext for header</small></h1>\n      </div>\n    </div>\n{% highlight html %}\n<div class=\"page-header\">\n  <h1>Example page header <small>Subtext for header</small></h1>\n</div>\n{% endhighlight %}\n  </div>\n\n\n\n  <!-- Thumbnails\n  ================================================== -->\n  <div class=\"bs-docs-section\">\n    <div class=\"page-header\">\n      <h1 id=\"thumbnails\">Thumbnails</h1>\n    </div>\n    <p class=\"lead\">Extend Bootstrap's <a href=\"../css/#grid\">grid system</a> with the thumbnail component to easily display grids of images, videos, text, and more.</p>\n\n    <h3 id=\"thumbnails-default\">Default example</h3>\n    <p>By default, Bootstrap's thumbnails are designed to showcase linked images with minimal required markup.</p>\n    <div class=\"bs-example\">\n      <div class=\"row\">\n        <div class=\"col-sm-6 col-md-3\">\n          <a href=\"#\" class=\"thumbnail\">\n            <img data-src=\"holder.js/100%x180\" alt=\"Generic placeholder thumbnail\" src=\"data:image/png;base64,\">\n          </a>\n        </div>\n        <div class=\"col-sm-6 col-md-3\">\n          <a href=\"#\" class=\"thumbnail\">\n            <img data-src=\"holder.js/100%x180\" alt=\"Generic placeholder thumbnail\" src=\"data:image/png;base64,\">\n          </a>\n        </div>\n        <div class=\"col-sm-6 col-md-3\">\n          <a href=\"#\" class=\"thumbnail\">\n            <img data-src=\"holder.js/100%x180\" alt=\"Generic placeholder thumbnail\" src=\"data:image/png;base64,\">\n          </a>\n        </div>\n        <div class=\"col-sm-6 col-md-3\">\n          <a href=\"#\" class=\"thumbnail\">\n            <img data-src=\"holder.js/100%x180\" alt=\"Generic placeholder thumbnail\" src=\"data:image/png;base64,\">\n          </a>\n        </div>\n      </div>\n    </div><!-- /.bs-example -->\n{% highlight html %}\n<div class=\"row\">\n  <div class=\"col-sm-6 col-md-3\">\n    <a href=\"#\" class=\"thumbnail\">\n      <img data-src=\"holder.js/100%x180\" alt=\"...\">\n    </a>\n  </div>\n  ...\n</div>\n{% endhighlight %}\n\n    <h3 id=\"thumbnails-custom-content\">Custom content</h3>\n    <p>With a bit of extra markup, it's possible to add any kind of HTML content like headings, paragraphs, or buttons into thumbnails.</p>\n    <div class=\"bs-example\">\n      <div class=\"row\">\n        <div class=\"col-sm-6 col-md-3\">\n          <div class=\"thumbnail\">\n            <img data-src=\"holder.js/300x200\" alt=\"Generic placeholder thumbnail\" src=\"data:image/png;base64,\">\n            <div class=\"caption\">\n              <h3>Thumbnail label</h3>\n              <p>Cras justo odio, dapibus ac facilisis in, egestas eget quam. Donec id elit non mi porta gravida at eget metus. Nullam id dolor id nibh ultricies vehicula ut id elit.</p>\n              <p><a href=\"#\" class=\"btn btn-primary\">Button</a> <a href=\"#\" class=\"btn btn-default\">Button</a></p>\n            </div>\n          </div>\n        </div>\n        <div class=\"col-sm-6 col-md-3\">\n          <div class=\"thumbnail\">\n            <img data-src=\"holder.js/300x200\" alt=\"Generic placeholder thumbnail\" src=\"data:image/png;base64,\">\n            <div class=\"caption\">\n              <h3>Thumbnail label</h3>\n              <p>Cras justo odio, dapibus ac facilisis in, egestas eget quam. Donec id elit non mi porta gravida at eget metus. Nullam id dolor id nibh ultricies vehicula ut id elit.</p>\n              <p><a href=\"#\" class=\"btn btn-primary\">Button</a> <a href=\"#\" class=\"btn btn-default\">Button</a></p>\n            </div>\n          </div>\n        </div>\n        <div class=\"col-sm-6 col-md-3\">\n          <div class=\"thumbnail\">\n            <img data-src=\"holder.js/300x200\" alt=\"Generic placeholder thumbnail\" src=\"data:image/png;base64,\">\n            <div class=\"caption\">\n              <h3>Thumbnail label</h3>\n              <p>Cras justo odio, dapibus ac facilisis in, egestas eget quam. Donec id elit non mi porta gravida at eget metus. Nullam id dolor id nibh ultricies vehicula ut id elit.</p>\n              <p><a href=\"#\" class=\"btn btn-primary\">Button</a> <a href=\"#\" class=\"btn btn-default\">Button</a></p>\n            </div>\n          </div>\n        </div>\n      </div>\n    </div><!-- /.bs-example -->\n{% highlight html %}\n<div class=\"row\">\n  <div class=\"col-sm-6 col-md-3\">\n    <div class=\"thumbnail\">\n      <img data-src=\"holder.js/300x200\" alt=\"...\">\n      <div class=\"caption\">\n        <h3>Thumbnail label</h3>\n        <p>...</p>\n        <p><a href=\"#\" class=\"btn btn-primary\">Button</a> <a href=\"#\" class=\"btn btn-default\">Button</a></p>\n      </div>\n    </div>\n  </div>\n</div>\n{% endhighlight %}\n  </div>\n\n\n\n\n  <!-- Alerts\n  ================================================== -->\n  <div class=\"bs-docs-section\">\n    <div class=\"page-header\">\n      <h1 id=\"alerts\">Alerts</h1>\n    </div>\n    <p class=\"lead\">Provide contextual feedback messages for typical user actions with the handful of available and flexible alert messages. For inline dismissal, use the <a href=\"../javascript/#js-alerts\">alerts jQuery plugin</a>.</p>\n\n    <h2 id=\"alerts-examples\">Examples</h2>\n    <p>Wrap any text and an optional dismiss button in <code>.alert</code> and one of the four contextual classes (e.g., <code>.alert-success</code>) for basic alert messages.</p>\n\n    <div class=\"bs-callout bs-callout-info\">\n      <h4>No default class</h4>\n      <p>Alerts don't have default classes, only base and modifier classes. A default gray alert doesn't make too much sense, so you're required to specify a type via contextual class. Choose from success, info, warning, or danger.</p>\n    </div>\n\n    <div class=\"bs-example\">\n      <div class=\"alert alert-success\">\n        <strong>Well done!</strong> You successfully read this important alert message.\n      </div>\n      <div class=\"alert alert-info\">\n        <strong>Heads up!</strong> This alert needs your attention, but it's not super important.\n      </div>\n      <div class=\"alert alert-warning\">\n        <strong>Warning!</strong> Best check yo self, you're not looking too good.\n      </div>\n      <div class=\"alert alert-danger\">\n        <strong>Oh snap!</strong> Change a few things up and try submitting again.\n      </div>\n    </div>\n{% highlight html %}\n<div class=\"alert alert-success\">...</div>\n<div class=\"alert alert-info\">...</div>\n<div class=\"alert alert-warning\">...</div>\n<div class=\"alert alert-danger\">...</div>\n{% endhighlight %}\n\n    <h2 id=\"alerts-dismissable\">Dismissable alerts</h2>\n    <p>Build on any alert by adding an optional <code>.alert-dismissable</code> and close button.</p>\n    <div class=\"bs-example\">\n      <div class=\"alert alert-dismissable\">\n        <button type=\"button\" class=\"close\" data-dismiss=\"alert\" aria-hidden=\"true\">&times;</button>\n        <strong>Warning!</strong> Best check yo self, you're not looking too good.\n      </div>\n    </div>\n{% highlight html %}\n<div class=\"alert alert-dismissable\">\n  <button type=\"button\" class=\"close\" data-dismiss=\"alert\" aria-hidden=\"true\">&times;</button>\n  <strong>Warning!</strong> Best check yo self, you're not looking too good.\n</div>\n{% endhighlight %}\n\n    <div class=\"bs-callout bs-callout-warning\">\n      <h4>Ensure proper behavior across all devices</h4>\n      <p>Be sure to use the <code>&lt;button&gt;</code> element with the <code>data-dismiss=\"alert\"</code> data attribute.</p>\n    </div>\n\n    <h2 id=\"alerts-links\">Links in alerts</h2>\n    <p>Use the <code>.alert-link</code> utility class to quickly provide matching colored links within any alert.</p>\n    <div class=\"bs-example\">\n      <div class=\"alert alert-success\">\n        <strong>Well done!</strong> You successfully read <a href=\"#\" class=\"alert-link\">this important alert message</a>.\n      </div>\n      <div class=\"alert alert-info\">\n        <strong>Heads up!</strong> This <a href=\"#\" class=\"alert-link\">alert needs your attention</a>, but it's not super important.\n      </div>\n      <div class=\"alert alert-warning\">\n        <strong>Warning!</strong> Best check yo self, you're <a href=\"#\" class=\"alert-link\">not looking too good</a>.\n      </div>\n      <div class=\"alert alert-danger\">\n        <strong>Oh snap!</strong> <a href=\"#\" class=\"alert-link\">Change a few things up</a> and try submitting again.\n      </div>\n    </div>\n{% highlight html %}\n<div class=\"alert alert-success\">\n  <a href=\"#\" class=\"alert-link\">...</a>\n</div>\n<div class=\"alert alert-info\">\n  <a href=\"#\" class=\"alert-link\">...</a>\n</div>\n<div class=\"alert alert-warning\">\n  <a href=\"#\" class=\"alert-link\">...</a>\n</div>\n<div class=\"alert alert-danger\">\n  <a href=\"#\" class=\"alert-link\">...</a>\n</div>\n{% endhighlight %}\n  </div>\n\n\n\n\n  <!-- Progress bars\n  ================================================== -->\n  <div class=\"bs-docs-section\">\n    <div class=\"page-header\">\n      <h1 id=\"progress\">Progress bars</h1>\n    </div>\n    <p class=\"lead\">Provide up-to-date feedback on the progress of a workflow or action with simple yet flexible progress bars.</p>\n\n    <div class=\"bs-callout bs-callout-danger\">\n      <h4>Cross-browser compatibility</h4>\n      <p>Progress bars use CSS3 transitions and animations to achieve some of their effects. These features are not supported in Internet Explorer 9 and below or older versions of Firefox. Opera 12 does not support animations.</p>\n    </div>\n\n    <h3 id=\"progress-basic\">Basic example</h3>\n    <p>Default progress bar.</p>\n    <div class=\"bs-example\">\n      <div class=\"progress\">\n        <div class=\"progress-bar\" role=\"progressbar\" aria-valuenow=\"60\" aria-valuemin=\"0\" aria-valuemax=\"100\" style=\"width: 60%;\">\n          <span class=\"sr-only\">60% Complete</span>\n        </div>\n      </div>\n    </div>\n{% highlight html %}\n<div class=\"progress\">\n  <div class=\"progress-bar\" role=\"progressbar\" aria-valuenow=\"60\" aria-valuemin=\"0\" aria-valuemax=\"100\" style=\"width: 60%;\">\n    <span class=\"sr-only\">60% Complete</span>\n  </div>\n</div>\n{% endhighlight %}\n\n    <h3 id=\"progress-alternatives\">Contextual alternatives</h3>\n    <p>Progress bars use some of the same button and alert classes for consistent styles.</p>\n    <div class=\"bs-example\">\n      <div class=\"progress\">\n        <div class=\"progress-bar progress-bar-success\" role=\"progressbar\" aria-valuenow=\"40\" aria-valuemin=\"0\" aria-valuemax=\"100\" style=\"width: 40%\">\n          <span class=\"sr-only\">40% Complete (success)</span>\n        </div>\n      </div>\n      <div class=\"progress\">\n        <div class=\"progress-bar progress-bar-info\" role=\"progressbar\" aria-valuenow=\"20\" aria-valuemin=\"0\" aria-valuemax=\"100\" style=\"width: 20%\">\n          <span class=\"sr-only\">20% Complete</span>\n        </div>\n      </div>\n      <div class=\"progress\">\n        <div class=\"progress-bar progress-bar-warning\" role=\"progressbar\" aria-valuenow=\"60\" aria-valuemin=\"0\" aria-valuemax=\"100\" style=\"width: 60%\">\n          <span class=\"sr-only\">60% Complete (warning)</span>\n        </div>\n      </div>\n      <div class=\"progress\">\n        <div class=\"progress-bar progress-bar-danger\" role=\"progressbar\" aria-valuenow=\"80\" aria-valuemin=\"0\" aria-valuemax=\"100\" style=\"width: 80%\">\n          <span class=\"sr-only\">80% Complete (danger)</span>\n        </div>\n      </div>\n    </div>\n{% highlight html %}\n<div class=\"progress\">\n  <div class=\"progress-bar progress-bar-success\" role=\"progressbar\" aria-valuenow=\"40\" aria-valuemin=\"0\" aria-valuemax=\"100\" style=\"width: 40%\">\n    <span class=\"sr-only\">40% Complete (success)</span>\n  </div>\n</div>\n<div class=\"progress\">\n  <div class=\"progress-bar progress-bar-info\" role=\"progressbar\" aria-valuenow=\"20\" aria-valuemin=\"0\" aria-valuemax=\"100\" style=\"width: 20%\">\n    <span class=\"sr-only\">20% Complete</span>\n  </div>\n</div>\n<div class=\"progress\">\n  <div class=\"progress-bar progress-bar-warning\" role=\"progressbar\" aria-valuenow=\"60\" aria-valuemin=\"0\" aria-valuemax=\"100\" style=\"width: 60%\">\n    <span class=\"sr-only\">60% Complete (warning)</span>\n  </div>\n</div>\n<div class=\"progress\">\n  <div class=\"progress-bar progress-bar-danger\" role=\"progressbar\" aria-valuenow=\"80\" aria-valuemin=\"0\" aria-valuemax=\"100\" style=\"width: 80%\">\n    <span class=\"sr-only\">80% Complete</span>\n  </div>\n</div>\n{% endhighlight %}\n\n    <h3 id=\"progress-striped\">Striped</h3>\n    <p>Uses a gradient to create a striped effect. Not available in IE8.</p>\n    <div class=\"bs-example\">\n      <div class=\"progress progress-striped\" >\n        <div class=\"progress-bar progress-bar-success\" role=\"progressbar\" aria-valuenow=\"40\" aria-valuemin=\"0\" aria-valuemax=\"100\" style=\"width: 40%\">\n          <span class=\"sr-only\">40% Complete (success)</span>\n        </div>\n      </div>\n      <div class=\"progress progress-striped\">\n        <div class=\"progress-bar progress-bar-info\" role=\"progressbar\" aria-valuenow=\"20\" aria-valuemin=\"0\" aria-valuemax=\"100\" style=\"width: 20%\">\n          <span class=\"sr-only\">20% Complete</span>\n        </div>\n      </div>\n      <div class=\"progress progress-striped\">\n        <div class=\"progress-bar progress-bar-warning\" role=\"progressbar\" aria-valuenow=\"60\" aria-valuemin=\"0\" aria-valuemax=\"100\" style=\"width: 60%\">\n          <span class=\"sr-only\">60% Complete (warning)</span>\n        </div>\n      </div>\n      <div class=\"progress progress-striped\">\n        <div class=\"progress-bar progress-bar-danger\" role=\"progressbar\" aria-valuenow=\"80\" aria-valuemin=\"0\" aria-valuemax=\"100\" style=\"width: 80%\">\n          <span class=\"sr-only\">80% Complete (danger)</span>\n        </div>\n      </div>\n    </div>\n{% highlight html %}\n<div class=\"progress progress-striped\">\n  <div class=\"progress-bar progress-bar-success\" role=\"progressbar\" aria-valuenow=\"40\" aria-valuemin=\"0\" aria-valuemax=\"100\" style=\"width: 40%\">\n    <span class=\"sr-only\">40% Complete (success)</span>\n  </div>\n</div>\n<div class=\"progress progress-striped\">\n  <div class=\"progress-bar progress-bar-info\" role=\"progressbar\" aria-valuenow=\"20\" aria-valuemin=\"0\" aria-valuemax=\"100\" style=\"width: 20%\">\n    <span class=\"sr-only\">20% Complete</span>\n  </div>\n</div>\n<div class=\"progress progress-striped\">\n  <div class=\"progress-bar progress-bar-warning\" role=\"progressbar\" aria-valuenow=\"60\" aria-valuemin=\"0\" aria-valuemax=\"100\" style=\"width: 60%\">\n    <span class=\"sr-only\">60% Complete (warning)</span>\n  </div>\n</div>\n<div class=\"progress progress-striped\">\n  <div class=\"progress-bar progress-bar-danger\" role=\"progressbar\" aria-valuenow=\"80\" aria-valuemin=\"0\" aria-valuemax=\"100\" style=\"width: 80%\">\n    <span class=\"sr-only\">80% Complete (danger)</span>\n  </div>\n</div>\n{% endhighlight %}\n\n    <h3 id=\"progress-animated\">Animated</h3>\n    <p>Add <code>.active</code> to <code>.progress-striped</code> to animate the stripes right to left. Not available in all versions of IE.</p>\n    <div class=\"bs-example\">\n      <div class=\"progress progress-striped active\">\n        <div class=\"progress-bar\" role=\"progressbar\" aria-valuenow=\"45\" aria-valuemin=\"0\" aria-valuemax=\"100\" style=\"width: 45%\"><span class=\"sr-only\">45% Complete</span></div>\n      </div>\n    </div>\n{% highlight html %}\n<div class=\"progress progress-striped active\">\n  <div class=\"progress-bar\"  role=\"progressbar\" aria-valuenow=\"45\" aria-valuemin=\"0\" aria-valuemax=\"100\" style=\"width: 45%\">\n    <span class=\"sr-only\">45% Complete</span>\n  </div>\n</div>\n{% endhighlight %}\n\n    <h3 id=\"progress-stacked\">Stacked</h3>\n    <p>Place multiple bars into the same <code>.progress</code> to stack them.</p>\n    <div class=\"bs-example\">\n      <div class=\"progress\">\n        <div class=\"progress-bar progress-bar-success\" style=\"width: 35%\">\n          <span class=\"sr-only\">35% Complete (success)</span>\n        </div>\n        <div class=\"progress-bar progress-bar-warning\" style=\"width: 20%\">\n          <span class=\"sr-only\">20% Complete (warning)</span>\n        </div>\n        <div class=\"progress-bar progress-bar-danger\" style=\"width: 10%\">\n          <span class=\"sr-only\">10% Complete (danger)</span>\n        </div>\n      </div>\n    </div>\n{% highlight html %}\n<div class=\"progress\">\n  <div class=\"progress-bar progress-bar-success\" style=\"width: 35%\">\n    <span class=\"sr-only\">35% Complete (success)</span>\n  </div>\n  <div class=\"progress-bar progress-bar-warning\" style=\"width: 20%\">\n    <span class=\"sr-only\">20% Complete (warning)</span>\n  </div>\n  <div class=\"progress-bar progress-bar-danger\" style=\"width: 10%\">\n    <span class=\"sr-only\">10% Complete (danger)</span>\n  </div>\n</div>\n{% endhighlight %}\n  </div>\n\n\n\n\n  <!-- Media object\n  ================================================== -->\n  <div class=\"bs-docs-section\">\n    <div class=\"page-header\">\n      <h1 id=\"media\">Media object</h1>\n    </div>\n    <p class=\"lead\">Abstract object styles for building various types of components (like blog comments, Tweets, etc) that feature a left- or right-aligned image alongside textual content.</p>\n\n    <h3 id=\"media-default\">Default media</h3>\n    <p>The default media allow to float a media object (images, video, audio) to the left or right of a content block.</p>\n    <div class=\"bs-example\">\n      <div class=\"media\">\n        <a class=\"pull-left\" href=\"#\">\n          <img class=\"media-object\" data-src=\"holder.js/64x64\" alt=\"Generic placeholder image\" src=\"data:image/png;base64,\">\n        </a>\n        <div class=\"media-body\">\n          <h4 class=\"media-heading\">Media heading</h4>\n          Cras sit amet nibh libero, in gravida nulla. Nulla vel metus scelerisque ante sollicitudin commodo. Cras purus odio, vestibulum in vulputate at, tempus viverra turpis. Fusce condimentum nunc ac nisi vulputate fringilla. Donec lacinia congue felis in faucibus.\n        </div>\n      </div>\n      <div class=\"media\">\n        <a class=\"pull-left\" href=\"#\">\n          <img class=\"media-object\" data-src=\"holder.js/64x64\" alt=\"Generic placeholder image\" src=\"data:image/png;base64,\">\n        </a>\n        <div class=\"media-body\">\n          <h4 class=\"media-heading\">Media heading</h4>\n          Cras sit amet nibh libero, in gravida nulla. Nulla vel metus scelerisque ante sollicitudin commodo. Cras purus odio, vestibulum in vulputate at, tempus viverra turpis. Fusce condimentum nunc ac nisi vulputate fringilla. Donec lacinia congue felis in faucibus.\n          <div class=\"media\">\n            <a class=\"pull-left\" href=\"#\">\n              <img class=\"media-object\" data-src=\"holder.js/64x64\" alt=\"Generic placeholder image\" src=\"data:image/png;base64,\">\n            </a>\n            <div class=\"media-body\">\n              <h4 class=\"media-heading\">Media heading</h4>\n              Cras sit amet nibh libero, in gravida nulla. Nulla vel metus scelerisque ante sollicitudin commodo. Cras purus odio, vestibulum in vulputate at, tempus viverra turpis. Fusce condimentum nunc ac nisi vulputate fringilla. Donec lacinia congue felis in faucibus.\n            </div>\n          </div>\n        </div>\n      </div>\n    </div><!-- /.bs-example -->\n{% highlight html %}\n<div class=\"media\">\n  <a class=\"pull-left\" href=\"#\">\n    <img class=\"media-object\" src=\"...\" alt=\"...\">\n  </a>\n  <div class=\"media-body\">\n    <h4 class=\"media-heading\">Media heading</h4>\n    ...\n  </div>\n</div>\n{% endhighlight %}\n\n    <h3 id=\"media-list\">Media list</h3>\n    <p>With a bit of extra markup, you can use media inside list (useful for comment threads or articles lists).</p>\n    <div class=\"bs-example\">\n      <ul class=\"media-list\">\n        <li class=\"media\">\n          <a class=\"pull-left\" href=\"#\">\n            <img class=\"media-object\" data-src=\"holder.js/64x64\" alt=\"Generic placeholder image\" src=\"data:image/png;base64,\">\n          </a>\n          <div class=\"media-body\">\n            <h4 class=\"media-heading\">Media heading</h4>\n            <p>Cras sit amet nibh libero, in gravida nulla. Nulla vel metus scelerisque ante sollicitudin commodo. Cras purus odio, vestibulum in vulputate at, tempus viverra turpis.</p>\n            <!-- Nested media object -->\n            <div class=\"media\">\n              <a class=\"pull-left\" href=\"#\">\n                <img class=\"media-object\" data-src=\"holder.js/64x64\" alt=\"Generic placeholder image\" src=\"data:image/png;base64,\">\n              </a>\n              <div class=\"media-body\">\n                <h4 class=\"media-heading\">Nested media heading</h4>\n                Cras sit amet nibh libero, in gravida nulla. Nulla vel metus scelerisque ante sollicitudin commodo. Cras purus odio, vestibulum in vulputate at, tempus viverra turpis.\n                <!-- Nested media object -->\n                <div class=\"media\">\n                  <a class=\"pull-left\" href=\"#\">\n                    <img class=\"media-object\" data-src=\"holder.js/64x64\" alt=\"Generic placeholder image\" src=\"data:image/png;base64,\">\n                  </a>\n                  <div class=\"media-body\">\n                    <h4 class=\"media-heading\">Nested media heading</h4>\n                    Cras sit amet nibh libero, in gravida nulla. Nulla vel metus scelerisque ante sollicitudin commodo. Cras purus odio, vestibulum in vulputate at, tempus viverra turpis.\n                  </div>\n                </div>\n              </div>\n            </div>\n            <!-- Nested media object -->\n            <div class=\"media\">\n              <a class=\"pull-left\" href=\"#\">\n                <img class=\"media-object\" data-src=\"holder.js/64x64\" alt=\"Generic placeholder image\" src=\"data:image/png;base64,\">\n              </a>\n              <div class=\"media-body\">\n                <h4 class=\"media-heading\">Nested media heading</h4>\n                Cras sit amet nibh libero, in gravida nulla. Nulla vel metus scelerisque ante sollicitudin commodo. Cras purus odio, vestibulum in vulputate at, tempus viverra turpis.\n              </div>\n            </div>\n          </div>\n        </li>\n        <li class=\"media\">\n          <a class=\"pull-right\" href=\"#\">\n            <img class=\"media-object\" data-src=\"holder.js/64x64\" alt=\"Generic placeholder image\" src=\"data:image/png;base64,\">\n          </a>\n          <div class=\"media-body\">\n            <h4 class=\"media-heading\">Media heading</h4>\n            Cras sit amet nibh libero, in gravida nulla. Nulla vel metus scelerisque ante sollicitudin commodo. Cras purus odio, vestibulum in vulputate at, tempus viverra turpis.\n          </div>\n        </li>\n      </ul>\n    </div>\n{% highlight html %}\n<ul class=\"media-list\">\n  <li class=\"media\">\n    <a class=\"pull-left\" href=\"#\">\n      <img class=\"media-object\" src=\"...\" alt=\"...\">\n    </a>\n    <div class=\"media-body\">\n      <h4 class=\"media-heading\">Media heading</h4>\n      ...\n    </div>\n  </li>\n</ul>\n{% endhighlight %}\n  </div>\n\n\n\n  <!-- List group\n  ================================================== -->\n  <div class=\"bs-docs-section\">\n    <div class=\"page-header\">\n      <h1 id=\"list-group\">List group</h1>\n    </div>\n    <p class=\"lead\">List groups are a flexible and powerful component for displaying not only simple lists of elements, but complex ones with custom content.</p>\n\n    <h3 id=\"list-group-basic\">Basic example</h3>\n    <p>The most basic list group is simply an unordered list with list items, and the proper classes. Build upon it with the options that follow, or your own CSS as needed.</p>\n    <div class=\"bs-example\">\n      <ul class=\"list-group\">\n        <li class=\"list-group-item\">Cras justo odio</li>\n        <li class=\"list-group-item\">Dapibus ac facilisis in</li>\n        <li class=\"list-group-item\">Morbi leo risus</li>\n        <li class=\"list-group-item\">Porta ac consectetur ac</li>\n        <li class=\"list-group-item\">Vestibulum at eros</li>\n      </ul>\n    </div>\n{% highlight html %}\n<ul class=\"list-group\">\n  <li class=\"list-group-item\">Cras justo odio</li>\n  <li class=\"list-group-item\">Dapibus ac facilisis in</li>\n  <li class=\"list-group-item\">Morbi leo risus</li>\n  <li class=\"list-group-item\">Porta ac consectetur ac</li>\n  <li class=\"list-group-item\">Vestibulum at eros</li>\n</ul>\n{% endhighlight %}\n\n    <h3 id=\"list-group-badges\">Badges</h3>\n    <p>Add the badges component to any list group item and it will automatically be positioned on the right.</p>\n    <div class=\"bs-example\">\n      <ul class=\"list-group\">\n        <li class=\"list-group-item\">\n          <span class=\"badge\">14</span>\n          Cras justo odio\n        </li>\n        <li class=\"list-group-item\">\n          <span class=\"badge\">2</span>\n          Dapibus ac facilisis in\n        </li>\n        <li class=\"list-group-item\">\n          <span class=\"badge\">1</span>\n          Morbi leo risus\n        </li>\n      </ul>\n    </div>\n{% highlight html %}\n<ul class=\"list-group\">\n  <li class=\"list-group-item\">\n    <span class=\"badge\">14</span>\n    Cras justo odio\n  </li>\n</ul>\n{% endhighlight %}\n\n    <h3 id=\"list-group-linked\">Linked items</h3>\n    <p>Linkify list group items by using anchor tags instead of list items (that also means a parent <code>&lt;div&gt;</code> instead of an <code>&lt;ul&gt;</code>). No need for individual parents around each element.</p>\n    <div class=\"bs-example\">\n      <div class=\"list-group\">\n        <a href=\"#\" class=\"list-group-item active\">\n          Cras justo odio\n        </a>\n        <a href=\"#\" class=\"list-group-item\">Dapibus ac facilisis in</a>\n        <a href=\"#\" class=\"list-group-item\">Morbi leo risus</a>\n        <a href=\"#\" class=\"list-group-item\">Porta ac consectetur ac</a>\n        <a href=\"#\" class=\"list-group-item\">Vestibulum at eros</a>\n      </div>\n    </div>\n{% highlight html %}\n<div class=\"list-group\">\n  <a href=\"#\" class=\"list-group-item active\">\n    Cras justo odio\n  </a>\n  <a href=\"#\" class=\"list-group-item\">Dapibus ac facilisis in</a>\n  <a href=\"#\" class=\"list-group-item\">Morbi leo risus</a>\n  <a href=\"#\" class=\"list-group-item\">Porta ac consectetur ac</a>\n  <a href=\"#\" class=\"list-group-item\">Vestibulum at eros</a>\n</div>\n{% endhighlight %}\n\n    <h3 id=\"list-group-custom-content\">Custom content</h3>\n    <p>Add nearly any HTML within, even for linked list groups like the one below.</p>\n    <div class=\"bs-example\">\n      <div class=\"list-group\">\n        <a href=\"#\" class=\"list-group-item active\">\n          <h4 class=\"list-group-item-heading\">List group item heading</h4>\n          <p class=\"list-group-item-text\">Donec id elit non mi porta gravida at eget metus. Maecenas sed diam eget risus varius blandit.</p>\n        </a>\n        <a href=\"#\" class=\"list-group-item\">\n          <h4 class=\"list-group-item-heading\">List group item heading</h4>\n          <p class=\"list-group-item-text\">Donec id elit non mi porta gravida at eget metus. Maecenas sed diam eget risus varius blandit.</p>\n        </a>\n        <a href=\"#\" class=\"list-group-item\">\n          <h4 class=\"list-group-item-heading\">List group item heading</h4>\n          <p class=\"list-group-item-text\">Donec id elit non mi porta gravida at eget metus. Maecenas sed diam eget risus varius blandit.</p>\n        </a>\n      </div>\n    </div>\n{% highlight html %}\n<div class=\"list-group\">\n  <a href=\"#\" class=\"list-group-item active\">\n    <h4 class=\"list-group-item-heading\">List group item heading</h4>\n    <p class=\"list-group-item-text\">...</p>\n  </a>\n</div>\n{% endhighlight %}\n  </div>\n\n\n\n\n  <!-- Panels\n  ================================================== -->\n  <div class=\"bs-docs-section\">\n    <div class=\"page-header\">\n      <h1 id=\"panels\">Panels</h1>\n    </div>\n    <p class=\"lead\">While not always necessary, sometimes you need to put your DOM in a box. For those situations, try the panel component.</p>\n\n    <h3 id=\"panels-basic\">Basic example</h3>\n    <p>By default, all the <code>.panel</code> does is apply some basic border and padding to contain some content.</p>\n    <div class=\"bs-example\">\n      <div class=\"panel panel-default\">\n        <div class=\"panel-body\">\n          Basic panel example\n        </div>\n      </div>\n    </div>\n{% highlight html %}\n<div class=\"panel panel-default\">\n  <div class=\"panel-body\">\n    Basic panel example\n  </div>\n</div>\n{% endhighlight %}\n\n    <h3 id=\"panels-heading\">Panel with heading</h3>\n    <p>Easily add a heading container to your panel with <code>.panel-heading</code>. You may also include any <code>&lt;h1&gt;</code>-<code>&lt;h6&gt;</code> with a <code>.panel-title</code> class to add a pre-styled heading.</p>\n    <div class=\"bs-example\">\n      <div class=\"panel panel-default\">\n        <div class=\"panel-heading\">Panel heading without title</div>\n        <div class=\"panel-body\">\n          Panel content\n        </div>\n      </div>\n      <div class=\"panel panel-default\">\n        <div class=\"panel-heading\">\n          <h3 class=\"panel-title\">Panel title</h3>\n        </div>\n        <div class=\"panel-body\">\n          Panel content\n        </div>\n      </div>\n    </div>\n{% highlight html %}\n<div class=\"panel panel-default\">\n  <div class=\"panel-heading\">Panel heading without title</div>\n  <div class=\"panel-body\">\n    Panel content\n  </div>\n</div>\n\n<div class=\"panel panel-default\">\n  <div class=\"panel-heading\">\n    <h3 class=\"panel-title\">Panel title</h3>\n  </div>\n  <div class=\"panel-body\">\n    Panel content\n  </div>\n</div>\n{% endhighlight %}\n\n    <h3 id=\"panels-footer\">Panel with footer</h3>\n    <p>Wrap buttons or secondary text in <code>.panel-footer</code>. Note that panel footers <strong>do not</strong> inherit colors and borders when using contextual variations as they are not meant to be in the foreground.</p>\n    <div class=\"bs-example\">\n      <div class=\"panel panel-default\">\n        <div class=\"panel-body\">\n          Panel content\n        </div>\n        <div class=\"panel-footer\">Panel footer</div>\n      </div>\n    </div>\n{% highlight html %}\n<div class=\"panel panel-default\">\n  <div class=\"panel-body\">\n    Panel content\n  </div>\n  <div class=\"panel-footer\">Panel footer</div>\n</div>\n{% endhighlight %}\n\n    <h3 id=\"panels-alternatives\">Contextual alternatives</h3>\n    <p>Like other components, easily make a panel more meaningful to a particular context by adding any of the contextual state classes.</p>\n    <div class=\"bs-example\">\n      <div class=\"panel panel-primary\">\n        <div class=\"panel-heading\">\n          <h3 class=\"panel-title\">Panel title</h3>\n        </div>\n        <div class=\"panel-body\">\n          Panel content\n        </div>\n      </div>\n      <div class=\"panel panel-success\">\n        <div class=\"panel-heading\">\n          <h3 class=\"panel-title\">Panel title</h3>\n        </div>\n        <div class=\"panel-body\">\n          Panel content\n        </div>\n      </div>\n      <div class=\"panel panel-info\">\n        <div class=\"panel-heading\">\n          <h3 class=\"panel-title\">Panel title</h3>\n        </div>\n        <div class=\"panel-body\">\n          Panel content\n        </div>\n      </div>\n      <div class=\"panel panel-warning\">\n        <div class=\"panel-heading\">\n          <h3 class=\"panel-title\">Panel title</h3>\n        </div>\n        <div class=\"panel-body\">\n          Panel content\n        </div>\n      </div>\n      <div class=\"panel panel-danger\">\n        <div class=\"panel-heading\">\n          <h3 class=\"panel-title\">Panel title</h3>\n        </div>\n        <div class=\"panel-body\">\n          Panel content\n        </div>\n      </div>\n    </div>\n{% highlight html %}\n<div class=\"panel panel-primary\">...</div>\n<div class=\"panel panel-success\">...</div>\n<div class=\"panel panel-info\">...</div>\n<div class=\"panel panel-warning\">...</div>\n<div class=\"panel panel-danger\">...</div>\n{% endhighlight %}\n\n    <h3 id=\"panels-tables\">With tables</h3>\n    <p>Add any non-bordered <code>.table</code> within a panel for a seamless design. If there is a <code>.panel-body</code>, we add an extra border to the top of the table for separation.</p>\n    <div class=\"bs-example\">\n      <div class=\"panel panel-default\">\n        <!-- Default panel contents -->\n        <div class=\"panel-heading\">Panel heading</div>\n        <div class=\"panel-body\">\n          <p>Some default panel content here. Nulla vitae elit libero, a pharetra augue. Aenean lacinia bibendum nulla sed consectetur. Aenean eu leo quam. Pellentesque ornare sem lacinia quam venenatis vestibulum. Nullam id dolor id nibh ultricies vehicula ut id elit.</p>\n        </div>\n\n        <!-- Table -->\n        <table class=\"table\">\n          <thead>\n            <tr>\n              <th>#</th>\n              <th>First Name</th>\n              <th>Last Name</th>\n              <th>Username</th>\n            </tr>\n          </thead>\n          <tbody>\n            <tr>\n              <td>1</td>\n              <td>Mark</td>\n              <td>Otto</td>\n              <td>@mdo</td>\n            </tr>\n            <tr>\n              <td>2</td>\n              <td>Jacob</td>\n              <td>Thornton</td>\n              <td>@fat</td>\n            </tr>\n            <tr>\n              <td>3</td>\n              <td>Larry</td>\n              <td>the Bird</td>\n              <td>@twitter</td>\n            </tr>\n          </tbody>\n        </table>\n      </div>\n    </div>\n{% highlight html %}\n<div class=\"panel panel-default\">\n  <!-- Default panel contents -->\n  <div class=\"panel-heading\">Panel heading</div>\n  <div class=\"panel-body\">\n    <p>...</p>\n  </div>\n\n  <!-- Table -->\n  <table class=\"table\">\n    ...\n  </table>\n</div>\n{% endhighlight %}\n\n    <p>If there is no panel body, the component moves from panel header to table without interruption.</p>\n    <div class=\"bs-example\">\n      <div class=\"panel panel-default\">\n        <!-- Default panel contents -->\n        <div class=\"panel-heading\">Panel heading</div>\n\n        <!-- Table -->\n        <table class=\"table\">\n          <thead>\n            <tr>\n              <th>#</th>\n              <th>First Name</th>\n              <th>Last Name</th>\n              <th>Username</th>\n            </tr>\n          </thead>\n          <tbody>\n            <tr>\n              <td>1</td>\n              <td>Mark</td>\n              <td>Otto</td>\n              <td>@mdo</td>\n            </tr>\n            <tr>\n              <td>2</td>\n              <td>Jacob</td>\n              <td>Thornton</td>\n              <td>@fat</td>\n            </tr>\n            <tr>\n              <td>3</td>\n              <td>Larry</td>\n              <td>the Bird</td>\n              <td>@twitter</td>\n            </tr>\n          </tbody>\n        </table>\n      </div>\n    </div>\n{% highlight html %}\n<div class=\"panel panel-default\">\n  <!-- Default panel contents -->\n  <div class=\"panel-heading\">Panel heading</div>\n\n  <!-- Table -->\n  <table class=\"table\">\n    ...\n  </table>\n</div>\n{% endhighlight %}\n\n\n\n    <h3 id=\"panels-list-group\">With list groups</h3>\n    <p>Easily include full-width <a href=\"#list-group\">list groups</a> within any panel.</p>\n    <div class=\"bs-example\">\n      <div class=\"panel panel-default\">\n        <!-- Default panel contents -->\n        <div class=\"panel-heading\">Panel heading</div>\n        <div class=\"panel-body\">\n          <p>Some default panel content here. Nulla vitae elit libero, a pharetra augue. Aenean lacinia bibendum nulla sed consectetur. Aenean eu leo quam. Pellentesque ornare sem lacinia quam venenatis vestibulum. Nullam id dolor id nibh ultricies vehicula ut id elit.</p>\n        </div>\n\n        <!-- List group -->\n        <ul class=\"list-group\">\n          <li class=\"list-group-item\">Cras justo odio</li>\n          <li class=\"list-group-item\">Dapibus ac facilisis in</li>\n          <li class=\"list-group-item\">Morbi leo risus</li>\n          <li class=\"list-group-item\">Porta ac consectetur ac</li>\n          <li class=\"list-group-item\">Vestibulum at eros</li>\n        </ul>\n      </div>\n    </div>\n{% highlight html %}\n<div class=\"panel panel-default\">\n  <!-- Default panel contents -->\n  <div class=\"panel-heading\">Panel heading</div>\n  <div class=\"panel-body\">\n    <p>...</p>\n  </div>\n\n  <!-- List group -->\n  <ul class=\"list-group\">\n    <li class=\"list-group-item\">Cras justo odio</li>\n    <li class=\"list-group-item\">Dapibus ac facilisis in</li>\n    <li class=\"list-group-item\">Morbi leo risus</li>\n    <li class=\"list-group-item\">Porta ac consectetur ac</li>\n    <li class=\"list-group-item\">Vestibulum at eros</li>\n  </ul>\n</div>\n{% endhighlight %}\n\n  </div>\n\n\n\n\n\n  <!-- Wells\n  ================================================== -->\n  <div class=\"bs-docs-section\">\n    <div class=\"page-header\">\n      <h1 id=\"wells\">Wells</h1>\n    </div>\n\n    <h3>Default well</h3>\n    <p>Use the well as a simple effect on an element to give it an inset effect.</p>\n    <div class=\"bs-example\">\n      <div class=\"well\">\n        Look, I'm in a well!\n      </div>\n    </div>\n{% highlight html %}\n<div class=\"well\">...</div>\n{% endhighlight %}\n    <h3>Optional classes</h3>\n    <p>Control padding and rounded corners with two optional modifier classes.</p>\n    <div class=\"bs-example\">\n      <div class=\"well well-lg\">\n        Look, I'm in a large well!\n      </div>\n    </div>\n{% highlight html %}\n<div class=\"well well-lg\">...</div>\n{% endhighlight %}\n\n    <div class=\"bs-example\">\n      <div class=\"well well-sm\">\n        Look, I'm in a small well!\n      </div>\n    </div>\n{% highlight html %}\n<div class=\"well well-sm\">...</div>\n{% endhighlight %}\n  </div>\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/sass-bootstrap/composer.json",
    "content": "{\n    \"name\": \"jlong/sass-twitter-bootstrap\"\n  , \"description\": \"A sass port of the sleek, intuitive, and powerful front-end framework for faster and easier web development.\"\n  , \"keywords\": [\"bootstrap\", \"css\", \"sass\"]\n  , \"homepage\": \"http://github.com/jlong/sass-twitter-bootstrap/\"\n  , \"authors\": [\n      {\n        \"name\": \"John W. Long\"\n      },\n      {\n        \"name\": \"Mark Otto\",\n        \"email\": \"markdotto@gmail.com\"\n      },\n      {\n        \"name\": \"Jacob Thornton\",\n        \"email\": \"jacobthornton@gmail.com\"\n      }\n    ]\n  , \"support\": {\n      \"issues\": \"https://github.com/twbs/bootstrap/issues\"\n    }\n  , \"license\": \"Apache-2.0\"\n}\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/sass-bootstrap/css.html",
    "content": "---\nlayout: default\ntitle: CSS\nslug: css\nlead: \"Global CSS settings, fundamental HTML elements styled and enhanced with extensible classes, and an advanced grid system.\"\nbase_url: \"../\"\n---\n\n\n  <!-- Global Bootstrap settings\n  ================================================== -->\n  <div class=\"bs-docs-section\">\n    <div class=\"page-header\">\n      <h1 id=\"overview\">Overview</h1>\n    </div>\n    <p class=\"lead\">Get the lowdown on the key pieces of Bootstrap's infrastructure, including our approach to better, faster, stronger web development.</p>\n\n    <h3 id=\"overview-doctype\">HTML5 doctype</h3>\n    <p>Bootstrap makes use of certain HTML elements and CSS properties that require the use of the HTML5 doctype. Include it at the beginning of all your projects.</p>\n{% highlight html %}\n<!DOCTYPE html>\n<html lang=\"en\">\n  ...\n</html>\n{% endhighlight %}\n\n    <h3 id=\"overview-mobile\">Mobile first</h3>\n    <p>With Bootstrap 2, we added optional mobile friendly styles for key aspects of the framework. With Bootstrap 3, we've rewritten the project to be mobile friendly from the start. Instead of adding on optional mobile styles, they're baked right into the core. In fact, <strong>Bootstrap is mobile first</strong>. Mobile first styles can be found throughout the entire library instead of in separate files.</p>\n    <p>To ensure proper rendering and touch zooming, <strong>add the viewport meta tag</strong> to your <code>&lt;head&gt;</code>.</p>\n{% highlight html %}\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n{% endhighlight %}\n    <p>You can disable zooming capabilities on mobile devices by adding <code>user-scalable=no</code> to the viewport meta tag. This disables zooming, meaning users are only able to scroll, and results in your site feeling a bit more like a native application. Overall we don't recommend this on every site, so use caution!</p>\n{% highlight html %}\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no\">\n{% endhighlight %}\n\n    <h3 id=\"overview-responsive-images\">Responsive images</h3>\n    <p>Images in Bootstrap 3 can be made responsive-friendly via the addition of the <code>.img-responsive</code> class. This applies <code>max-width: 100%;</code> and <code>height: auto;</code> to the image so that it scales nicely to the parent element.</p>\n{% highlight html %}\n<img src=\"...\" class=\"img-responsive\" alt=\"Responsive image\">\n{% endhighlight %}\n\n    <h3 id=\"overview-type-links\">Typography and links</h3>\n    <p>Bootstrap sets basic global display, typography, and link styles. Specifically, we:</p>\n    <ul>\n      <li>Remove <code>margin</code> on the body</li>\n      <li>Set <code>background-color: white;</code> on the <code>body</code></li>\n      <li>Use the <code>@font-family-base</code>, <code>@font-size-base</code>, and <code>@line-height-base</code> attributes as our typographic base</li>\n      <li>Set the global link color via <code>@link-color</code> and apply link underlines only on <code>:hover</code></li>\n    </ul>\n    <p>These styles can be found within <code>scaffolding.less</code>.</p>\n\n    <h3 id=\"overview-normalize\">Normalize</h3>\n    <p>For improved cross-browser rendering, we use <a href=\"http://necolas.github.io/normalize.css/\" target=\"_blank\">Normalize</a>, a project by <a href=\"http://twitter.com/necolas\" target=\"_blank\">Nicolas Gallagher</a> and <a href=\"http://twitter.com/jon_neal\" target=\"_blank\">Jonathan Neal</a>.</p>\n\n    <h3 id=\"overview-container\">Containers</h3>\n    <p>Easily center a page's contents by wrapping its contents in a <code>.container</code>. Containers set <code>max-width</code> at various media query breakpoints to match our grid system.</p>\n{% highlight html %}\n<div class=\"container\">\n  ...\n</div>\n{% endhighlight %}\n  </div>\n\n\n\n  <!-- Grid system\n  ================================================== -->\n  <div class=\"bs-docs-section\">\n    <div class=\"page-header\">\n      <h1 id=\"grid\">Grid system</h1>\n    </div>\n    <p class=\"lead\">Bootstrap includes a responsive, mobile first fluid grid system that appropriately scales up to 12 columns as the device or viewport size increases. It includes <a href=\"#grid-example-basic\">predefined classes</a> for easy layout options, as well as powerful <a href=\"#grid-less\">mixins for generating more semantic layouts</a>.</p>\n\n    <h3 id=\"grid-media-queries\">Media queries</h3>\n    <p>We use the following media queries to create the key breakpoints in our grid system.</p>\n{% highlight css %}\n/* Extra small devices (phones, up to 480px) */\n/* No media query since this is the default in Bootstrap */\n\n/* Small devices (tablets, 768px and up) */\n@media (min-width: @screen-tablet) { ... }\n\n/* Medium devices (desktops, 992px and up) */\n@media (min-width: @screen-desktop) { ... }\n\n/* Large devices (large desktops, 1200px and up) */\n@media (min-width: @screen-large-desktop) { ... }\n{% endhighlight %}\n    <p>We occasionally expand on these media queries to include a <code>max-width</code> to limit CSS to a narrower set of devices.</p>\n{% highlight css %}\n@media (max-width: @screen-phone-max) { ... }\n@media (min-width: @screen-tablet) and (max-width: @screen-tablet-max) { ... }\n@media (min-width: @screen-desktop) and (max-width: @screen-desktop-max) { ... }\n@media (min-width: @screen-large-desktop) { ... }\n{% endhighlight %}\n\n    <h3 id=\"grid-options\">Grid options</h3>\n    <p>See how aspects of the Bootstrap grid system work across multiple devices with a handy table.</p>\n    <div class=\"table-responsive\">\n      <table class=\"table table-bordered table-striped\">\n        <thead>\n          <tr>\n            <th></th>\n            <th>\n              Extra small devices\n              <small>Phones (&lt;768px)</small>\n            </th>\n            <th>\n              Small devices\n              <small>Tablets (&ge;768px)</small>\n            </th>\n            <th>\n              Medium devices\n              <small>Desktops (&ge;992px)</small>\n            </th>\n            <th>\n              Large devices\n              <small>Desktops (&ge;1200px)</small>\n            </th>\n          </tr>\n        </thead>\n        <tbody>\n          <tr>\n            <th>Grid behavior</th>\n            <td>Horizontal at all times</td>\n            <td colspan=\"3\">Collapsed to start, horizontal above breakpoints</td>\n          </tr>\n          <tr>\n            <th>Max container width</th>\n            <td>None (auto)</td>\n            <td>750px</td>\n            <td>970px</td>\n            <td>1170px</td>\n          </tr>\n          <tr>\n            <th>Class prefix</th>\n            <td><code>.col-xs-</code></td>\n            <td><code>.col-sm-</code></td>\n            <td><code>.col-md-</code></td>\n            <td><code>.col-lg-</code></td>\n          </tr>\n          <tr>\n            <th># of columns</th>\n            <td colspan=\"4\">12</td>\n          </tr>\n          <tr>\n            <th>Max column width</th>\n            <td class=\"text-muted\">Auto</td>\n            <td>60px</td>\n            <td>78px</td>\n            <td>95px</td>\n          </tr>\n          <tr>\n            <th>Gutter width</th>\n            <td colspan=\"4\">30px (15px on each side of a column)</td>\n          </tr>\n          <tr>\n            <th>Nestable</th>\n            <td colspan=\"4\">Yes</td>\n          </tr>\n          <tr>\n            <th>Offsets</th>\n            <td colspan=\"1\" class=\"text-muted\">N/A</td>\n            <td colspan=\"3\">Yes</td>\n          </tr>\n          <tr>\n            <th>Column ordering</th>\n            <td class=\"text-muted\">N/A</td>\n            <td colspan=\"3\">Yes</td>\n          </tr>\n        </tbody>\n      </table>\n    </div>\n\n    <h3 id=\"grid-example-basic\">Example: Stacked-to-horizontal</h3>\n    <p>Using a single set of <code>.col-md-*</code> grid classes, you can create a basic grid system that starts out stacked on mobile devices and tablet devices (the extra small to small range) before becoming horizontal on desktop (medium) devices.</p>\n    <div class=\"bs-docs-grid\">\n      <div class=\"row show-grid\">\n        <div class=\"col-md-1\">.col-md-1</div>\n        <div class=\"col-md-1\">.col-md-1</div>\n        <div class=\"col-md-1\">.col-md-1</div>\n        <div class=\"col-md-1\">.col-md-1</div>\n        <div class=\"col-md-1\">.col-md-1</div>\n        <div class=\"col-md-1\">.col-md-1</div>\n        <div class=\"col-md-1\">.col-md-1</div>\n        <div class=\"col-md-1\">.col-md-1</div>\n        <div class=\"col-md-1\">.col-md-1</div>\n        <div class=\"col-md-1\">.col-md-1</div>\n        <div class=\"col-md-1\">.col-md-1</div>\n        <div class=\"col-md-1\">.col-md-1</div>\n      </div>\n      <div class=\"row show-grid\">\n        <div class=\"col-md-8\">.col-md-8</div>\n        <div class=\"col-md-4\">.col-md-4</div>\n      </div>\n      <div class=\"row show-grid\">\n        <div class=\"col-md-4\">.col-md-4</div>\n        <div class=\"col-md-4\">.col-md-4</div>\n        <div class=\"col-md-4\">.col-md-4</div>\n      </div>\n      <div class=\"row show-grid\">\n        <div class=\"col-md-6\">.col-md-6</div>\n        <div class=\"col-md-6\">.col-md-6</div>\n      </div>\n    </div>\n{% highlight html %}\n<div class=\"row\">\n  <div class=\"col-md-1\">.col-md-1</div>\n  <div class=\"col-md-1\">.col-md-1</div>\n  <div class=\"col-md-1\">.col-md-1</div>\n  <div class=\"col-md-1\">.col-md-1</div>\n  <div class=\"col-md-1\">.col-md-1</div>\n  <div class=\"col-md-1\">.col-md-1</div>\n  <div class=\"col-md-1\">.col-md-1</div>\n  <div class=\"col-md-1\">.col-md-1</div>\n  <div class=\"col-md-1\">.col-md-1</div>\n  <div class=\"col-md-1\">.col-md-1</div>\n  <div class=\"col-md-1\">.col-md-1</div>\n  <div class=\"col-md-1\">.col-md-1</div>\n</div>\n<div class=\"row\">\n  <div class=\"col-md-8\">.col-md-8</div>\n  <div class=\"col-md-4\">.col-md-4</div>\n</div>\n<div class=\"row\">\n  <div class=\"col-md-4\">.col-md-4</div>\n  <div class=\"col-md-4\">.col-md-4</div>\n  <div class=\"col-md-4\">.col-md-4</div>\n</div>\n<div class=\"row\">\n  <div class=\"col-md-6\">.col-md-6</div>\n  <div class=\"col-md-6\">.col-md-6</div>\n</div>\n{% endhighlight %}\n\n    <h3 id=\"grid-example-mixed\">Example: Mobile and desktop</h3>\n    <p>Don't want your columns to simply stack in smaller devices? Use the extra small and medium device grid classes by adding <code>.col-xs-*</code> <code>.col-md-*</code> to your columns. See the example below for a better idea of how it all works.</p>\n    <div class=\"bs-docs-grid\">\n      <div class=\"row show-grid\">\n        <div class=\"col-xs-12 col-md-8\">.col-xs-12 col-md-8</div>\n        <div class=\"col-xs-6 col-md-4\">.col-xs-6 .col-md-4</div>\n      </div>\n      <div class=\"row show-grid\">\n        <div class=\"col-xs-6 col-md-4\">.col-xs-6 .col-md-4</div>\n        <div class=\"col-xs-6 col-md-4\">.col-xs-6 .col-md-4</div>\n        <div class=\"col-xs-6 col-md-4\">.col-xs-6 .col-md-4</div>\n      </div>\n      <div class=\"row show-grid\">\n        <div class=\"col-xs-6\">.col-xs-6</div>\n        <div class=\"col-xs-6\">.col-xs-6</div>\n      </div>\n    </div>\n{% highlight html %}\n<!-- Stack the columns on mobile by making one full-width and the other half-width -->\n<div class=\"row\">\n  <div class=\"col-xs-12 col-md-8\">.col-xs-12 col-md-8</div>\n  <div class=\"col-xs-6 col-md-4\">.col-xs-6 .col-md-4</div>\n</div>\n\n<!-- Columns start at 50% wide on mobile and bump up to 33.3% wide on desktop -->\n<div class=\"row\">\n  <div class=\"col-xs-6 col-md-4\">.col-xs-6 .col-md-4</div>\n  <div class=\"col-xs-6 col-md-4\">.col-xs-6 .col-md-4</div>\n  <div class=\"col-xs-6 col-md-4\">.col-xs-6 .col-md-4</div>\n</div>\n\n<!-- Columns are always 50% wide, on mobile and desktop -->\n<div class=\"row\">\n  <div class=\"col-xs-6\">.col-xs-6</div>\n  <div class=\"col-xs-6\">.col-xs-6</div>\n</div>\n{% endhighlight %}\n\n    <h3 id=\"grid-example-mixed-complete\">Example: Mobile, tablet, desktops</h3>\n    <p>Build on the previous example by creating even more dynamic and powerful layouts with tablet <code>.col-sm-*</code> classes.</p>\n    <div class=\"bs-docs-grid\">\n      <div class=\"row show-grid\">\n        <div class=\"col-xs-12 col-sm-6 col-md-8\">.col-xs-12 .col-sm-6 .col-md-8</div>\n        <div class=\"col-xs-6 col-sm-6 col-md-4\">.col-xs-6 .col-sm-6 .col-md-4</div>\n      </div>\n      <div class=\"row show-grid\">\n        <div class=\"col-xs-6 col-sm-4 col-md-4\">.col-xs-6 .col-sm-4 .col-md-4</div>\n        <div class=\"col-xs-6 col-sm-4 col-md-4\">.col-xs-6 .col-sm-4 .col-md-4</div>\n        <!-- Optional: clear the XS cols if their content doesn't match in height -->\n        <div class=\"clearfix visible-xs\"></div>\n        <div class=\"col-xs-6 col-sm-4 col-md-4\">.col-xs-6 .col-sm-4 .col-md-4</div>\n      </div>\n    </div>\n{% highlight html %}\n<div class=\"row\">\n  <div class=\"col-xs-12 col-sm-6 col-md-8\">.col-xs-12 .col-sm-6 .col-md-8</div>\n  <div class=\"col-xs-6 col-sm-6 col-md-4\">.col-xs-6 .col-sm-6 .col-md-4</div>\n</div>\n<div class=\"row\">\n  <div class=\"col-xs-6 col-sm-4 col-md-4\">.col-xs-6 .col-sm-4 .col-md-4</div>\n  <div class=\"col-xs-6 col-sm-4 col-md-4\">.col-xs-6 .col-sm-4 .col-md-4</div>\n  <!-- Optional: clear the XS cols if their content doesn't match in height -->\n  <div class=\"clearfix visible-xs\"></div>\n  <div class=\"col-xs-6 col-sm-4 col-md-4\">.col-xs-6 .col-sm-4 .col-md-4</div>\n</div>\n{% endhighlight %}\n\n    <h3 id=\"grid-responsive-resets\">Responsive column resets</h3>\n    <p>With the four tiers of grids available you're bound to run into issues where, at certain breakpoints, your columns don't clear quite right as one is taller than the other. To fix that, use a combination of a <code>.clearfix</code> and our <a href=\"../css#responsive-utilities\">responsive utility classes</a>.</p>\n{% highlight html %}\n<div class=\"row\">\n  <div class=\"col-xs-6 col-sm-3\">.col-xs-6 .col-sm-3</div>\n  <div class=\"col-xs-6 col-sm-3\">.col-xs-6 .col-sm-3</div>\n\n  <!-- Add the extra clearfix for only the required viewport -->\n  <div class=\"clearfix visible-xs\"></div>\n\n  <div class=\"col-xs-6 col-sm-3\">.col-xs-6 .col-sm-3</div>\n  <div class=\"col-xs-6 col-sm-3\">.col-xs-6 .col-sm-3</div>\n</div>\n{% endhighlight %}\n    <p>In addition to column clearing at responsive breakpoints, you may need to <strong>reset offsets, pushes, or pulls</strong>. Those resets are available for medium and large grid tiers only, since they start only at the (second) small grid tier.</p>\n{% highlight html %}\n<div class=\"row\">\n  <div class=\"col-sm-5 col-md-6\">.col-sm-5 .col-md-6</div>\n  <div class=\"col-sm-5 col-sm-offset-2 col-md-6 col-md-offset-0\">.col-sm-5 .col-sm-offset-2 .col-md-6 .col-md-offset-0</div>\n</div>\n\n<div class=\"row\">\n  <div class=\"col-sm-6 col-md-5 col-lg-6\">.col-sm-6 .col-md-5 .col-lg-6</div>\n  <div class=\"col-sm-6 col-md-5 col-md-offset-2 col-lg-6 col-lg-offset-0\">.col-sm-6 .col-md-5 .col-md-offset-2 .col-lg-6 .col-lg-offset-0</div>\n</div>\n{% endhighlight %}\n\n\n    <h3 id=\"grid-offsetting\">Offsetting columns</h3>\n    <p>Move columns to the right using <code>.col-md-offset-*</code> classes. These classes increase the left margin of a column by <code>*</code> columns. For example, <code>.col-md-offset-4</code> moves <code>.col-md-4</code> over four columns.</p>\n    <div class=\"bs-docs-grid\">\n      <div class=\"row show-grid\">\n        <div class=\"col-md-4\">.col-md-4</div>\n        <div class=\"col-md-4 col-md-offset-4\">.col-md-4 .col-md-offset-4</div>\n      </div>\n      <div class=\"row show-grid\">\n        <div class=\"col-md-3 col-md-offset-3\">.col-md-3 .col-md-offset-3</div>\n        <div class=\"col-md-3 col-md-offset-3\">.col-md-3 .col-md-offset-3</div>\n      </div>\n      <div class=\"row show-grid\">\n        <div class=\"col-md-6 col-md-offset-3\">.col-md-6 .col-md-offset-3</div>\n      </div>\n    </div>\n{% highlight html %}\n<div class=\"row\">\n  <div class=\"col-md-4\">.col-md-4</div>\n  <div class=\"col-md-4 col-md-offset-4\">.col-md-4 .col-md-offset-4</div>\n</div>\n<div class=\"row\">\n  <div class=\"col-md-3 col-md-offset-3\">.col-md-3 .col-md-offset-3</div>\n  <div class=\"col-md-3 col-md-offset-3\">.col-md-3 .col-md-offset-3</div>\n</div>\n<div class=\"row\">\n  <div class=\"col-md-6 col-md-offset-3\">.col-md-6 .col-md-offset-3</div>\n</div>\n{% endhighlight %}\n\n\n    <h3 id=\"grid-nesting\">Nesting columns</h3>\n    <p>To nest your content with the default grid, add a new <code>.row</code> and set of <code>.col-md-*</code> columns within an existing <code>.col-md-*</code> column. Nested rows should include a set of columns that add up to 12.</p>\n    <div class=\"row show-grid\">\n      <div class=\"col-md-9\">\n        Level 1: .col-md-9\n        <div class=\"row show-grid\">\n          <div class=\"col-md-6\">\n            Level 2: .col-md-6\n          </div>\n          <div class=\"col-md-6\">\n            Level 2: .col-md-6\n          </div>\n        </div>\n      </div>\n    </div>\n{% highlight html %}\n<div class=\"row\">\n  <div class=\"col-md-9\">\n    Level 1: .col-md-9\n    <div class=\"row\">\n      <div class=\"col-md-6\">\n        Level 2: .col-md-6\n      </div>\n      <div class=\"col-md-6\">\n        Level 2: .col-md-6\n      </div>\n    </div>\n  </div>\n</div>\n{% endhighlight %}\n\n    <h3 id=\"grid-column-ordering\">Column ordering</h3>\n    <p>Easily change the order of our built-in grid columns with <code>.col-md-push-*</code> and <code>.col-md-pull-*</code> modifier classes.</p>\n    <div class=\"row show-grid\">\n      <div class=\"col-md-9 col-md-push-3\">.col-md-9 .col-md-push-3</div>\n      <div class=\"col-md-3 col-md-pull-9\">.col-md-3 .col-md-pull-9</div>\n    </div>\n\n{% highlight html %}\n<div class=\"row\">\n  <div class=\"col-md-9 col-md-push-3\">.col-md-9 .col-md-push-3</div>\n  <div class=\"col-md-3 col-md-pull-9\">.col-md-3 .col-md-pull-9</div>\n</div>\n{% endhighlight %}\n\n    <h3 id=\"grid-less\">LESS mixins and variables</h3>\n    <p>In addition to <a href=\"#grid-example-basic\">prebuilt grid classes</a> for fast layouts, Bootstrap includes LESS variables and mixins for quickly generating your own simple, semantic layouts.</p>\n\n    <h4>Variables</h4>\n    <p>Variables determine the number of columns, the gutter width, and the media query point at which to begin floating columns. We use these to generate the predefined grid classes documented above, as well as for the custom mixins listed below.</p>\n{% highlight css %}\n@grid-columns:              12;\n@grid-gutter-width:         30px;\n@grid-float-breakpoint:     768px;\n{% endhighlight %}\n\n    <h4>Mixins</h4>\n    <p>Mixins are used in conjunction with the grid variables to generate semantic CSS for individual grid columns.</p>\n{% highlight css %}\n// Creates a wrapper for a series of columns\n.make-row(@gutter: @grid-gutter-width) {\n  // Then clear the floated columns\n  .clearfix();\n\n  @media (min-width: @screen-small) {\n    margin-left:  (@gutter / -2);\n    margin-right: (@gutter / -2);\n  }\n\n  // Negative margin nested rows out to align the content of columns\n  .row {\n    margin-left:  (@gutter / -2);\n    margin-right: (@gutter / -2);\n  }\n}\n\n// Generate the extra small columns\n.make-xs-column(@columns; @gutter: @grid-gutter-width) {\n  position: relative;\n  // Prevent columns from collapsing when empty\n  min-height: 1px;\n  // Inner gutter via padding\n  padding-left:  (@gutter / 2);\n  padding-right: (@gutter / 2);\n\n  // Calculate width based on number of columns available\n  @media (min-width: @grid-float-breakpoint) {\n    float: left;\n    width: percentage((@columns / @grid-columns));\n  }\n}\n\n// Generate the small columns\n.make-sm-column(@columns; @gutter: @grid-gutter-width) {\n  position: relative;\n  // Prevent columns from collapsing when empty\n  min-height: 1px;\n  // Inner gutter via padding\n  padding-left:  (@gutter / 2);\n  padding-right: (@gutter / 2);\n\n  // Calculate width based on number of columns available\n  @media (min-width: @screen-small) {\n    float: left;\n    width: percentage((@columns / @grid-columns));\n  }\n}\n\n// Generate the small column offsets\n.make-sm-column-offset(@columns) {\n  @media (min-width: @screen-small) {\n    margin-left: percentage((@columns / @grid-columns));\n  }\n}\n.make-sm-column-push(@columns) {\n  @media (min-width: @screen-small) {\n    left: percentage((@columns / @grid-columns));\n  }\n}\n.make-sm-column-pull(@columns) {\n  @media (min-width: @screen-small) {\n    right: percentage((@columns / @grid-columns));\n  }\n}\n\n// Generate the medium columns\n.make-md-column(@columns; @gutter: @grid-gutter-width) {\n  position: relative;\n  // Prevent columns from collapsing when empty\n  min-height: 1px;\n  // Inner gutter via padding\n  padding-left:  (@gutter / 2);\n  padding-right: (@gutter / 2);\n\n  // Calculate width based on number of columns available\n  @media (min-width: @screen-medium) {\n    float: left;\n    width: percentage((@columns / @grid-columns));\n  }\n}\n\n// Generate the large column offsets\n.make-md-column-offset(@columns) {\n  @media (min-width: @screen-medium) {\n    margin-left: percentage((@columns / @grid-columns));\n  }\n}\n.make-md-column-push(@columns) {\n  @media (min-width: @screen-medium) {\n    left: percentage((@columns / @grid-columns));\n  }\n}\n.make-md-column-pull(@columns) {\n  @media (min-width: @screen-medium) {\n    right: percentage((@columns / @grid-columns));\n  }\n}\n\n// Generate the large columns\n.make-lg-column(@columns; @gutter: @grid-gutter-width) {\n  position: relative;\n  // Prevent columns from collapsing when empty\n  min-height: 1px;\n  // Inner gutter via padding\n  padding-left:  (@gutter / 2);\n  padding-right: (@gutter / 2);\n\n  // Calculate width based on number of columns available\n  @media (min-width: @screen-large) {\n    float: left;\n    width: percentage((@columns / @grid-columns));\n  }\n}\n\n// Generate the large column offsets\n.make-lg-column-offset(@columns) {\n  @media (min-width: @screen-large) {\n    margin-left: percentage((@columns / @grid-columns));\n  }\n}\n.make-lg-column-push(@columns) {\n  @media (min-width: @screen-large) {\n    left: percentage((@columns / @grid-columns));\n  }\n}\n.make-lg-column-pull(@columns) {\n  @media (min-width: @screen-large) {\n    right: percentage((@columns / @grid-columns));\n  }\n}\n{% endhighlight %}\n\n    <h4>Example usage</h4>\n    <p>You can modify the variables to your own custom values, or just use the mixins with their default values. Here's an example of using the default settings to create a two-column layout with a gap between.</p>\n{% highlight css %}\n.wrapper {\n  .make-row();\n}\n.content-main {\n  .make-lg-column(8);\n}\n.content-secondary {\n  .make-lg-column(3);\n  .make-lg-column-offset(1);\n}\n{% endhighlight %}\n{% highlight html %}\n<div class=\"wrapper\">\n  <div class=\"content-main\">...</div>\n  <div class=\"content-secondary\">...</div>\n</div>\n{% endhighlight %}\n\n  </div>\n\n\n\n\n  <!-- Typography\n  ================================================== -->\n  <div class=\"bs-docs-section\">\n    <div class=\"page-header\">\n      <h1 id=\"type\">Typography</h1>\n    </div>\n\n    <!-- Headings -->\n    <h2 id=\"type-headings\">Headings</h2>\n    <p>All HTML headings, <code>&lt;h1&gt;</code> through <code>&lt;h6&gt;</code> are available.</p>\n\n    <div class=\"bs-example bs-example-type\">\n      <table class=\"table\">\n        <tbody>\n          <tr>\n            <td><h1>h1. Bootstrap heading</h1></td>\n            <td>Semibold 36px</td>\n          </tr>\n          <tr>\n            <td><h2>h2. Bootstrap heading</h2></td>\n            <td>Semibold 30px</td>\n          </tr>\n          <tr>\n            <td><h3>h3. Bootstrap heading</h3></td>\n            <td>Semibold 24px</td>\n          </tr>\n          <tr>\n            <td><h4>h4. Bootstrap heading</h4></td>\n            <td>Semibold 18px</td>\n          </tr>\n          <tr>\n            <td><h5>h5. Bootstrap heading</h5></td>\n            <td>Semibold 14px</td>\n          </tr>\n          <tr>\n            <td><h6>h6. Bootstrap heading</h6></td>\n            <td>Semibold 12px</td>\n          </tr>\n        </tbody>\n      </table>\n    </div>\n{% highlight html %}\n<h1>...</h1>\n<h2>...</h2>\n<h3>...</h3>\n<h4>...</h4>\n<h5>...</h5>\n<h6>...</h6>\n{% endhighlight %}\n\n    <!-- Body copy -->\n    <h2 id=\"type-body-copy\">Body copy</h2>\n    <p>Bootstrap's global default <code>font-size</code> is <strong>14px</strong>, with a <code>line-height</code> of <strong>1.428</strong>. This is applied to the <code>&lt;body&gt;</code> and all paragraphs. In addition, <code>&lt;p&gt;</code> (paragraphs) receive a bottom margin of half their computed line-height (10px by default).</p>\n    <div class=\"bs-example\">\n      <p>Nullam quis risus eget urna mollis ornare vel eu leo. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Nullam id dolor id nibh ultricies vehicula.</p>\n      <p>Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec ullamcorper nulla non metus auctor fringilla. Duis mollis, est non commodo luctus, nisi erat porttitor ligula, eget lacinia odio sem nec elit. Donec ullamcorper nulla non metus auctor fringilla.</p>\n      <p>Maecenas sed diam eget risus varius blandit sit amet non magna. Donec id elit non mi porta gravida at eget metus. Duis mollis, est non commodo luctus, nisi erat porttitor ligula, eget lacinia odio sem nec elit.</p>\n    </div>\n{% highlight html %}\n<p>...</p>\n{% endhighlight %}\n\n    <!-- Body copy .lead -->\n    <h3>Lead body copy</h3>\n    <p>Make a paragraph stand out by adding <code>.lead</code>.</p>\n    <div class=\"bs-example\">\n      <p class=\"lead\">Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor. Duis mollis, est non commodo luctus.</p>\n    </div>\n{% highlight html %}\n<p class=\"lead\">...</p>\n{% endhighlight %}\n\n    <!-- Using LESS -->\n    <h3>Built with Less</h3>\n    <p>The typographic scale is based on two LESS variables in <strong>variables.less</strong>: <code>@font-size-base</code> and <code>@line-height-base</code>. The first is the base font-size used throughout and the second is the base line-height. We use those variables and some simple math to create the margins, paddings, and line-heights of all our type and more. Customize them and Bootstrap adapts.</p>\n\n\n    <!-- Emphasis -->\n    <h2 id=\"type-emphasis\">Emphasis</h2>\n    <p>Make use of HTML's default emphasis tags with lightweight styles.</p>\n\n    <h3>Small text</h3>\n    <p>For de-emphasizing inline or blocks of text, use the <code>&lt;small&gt;</code> tag to set text at 85% the size of the parent. Heading elements receive their own <code>font-size</code> for nested <code>&lt;small&gt;</code> elements.</p>\n    <div class=\"bs-example\">\n      <p><small>This line of text is meant to be treated as fine print.</small></p>\n    </div>\n{% highlight html %}\n<small>This line of text is meant to be treated as fine print.</small>\n{% endhighlight %}\n\n\n    <h3>Bold</h3>\n    <p>For emphasizing a snippet of text with a heavier font-weight.</p>\n    <div class=\"bs-example\">\n      <p>The following snippet of text is <strong>rendered as bold text</strong>.</p>\n    </div>\n{% highlight html %}\n<strong>rendered as bold text</strong>\n{% endhighlight %}\n\n    <h3>Italics</h3>\n    <p>For emphasizing a snippet of text with italics.</p>\n    <div class=\"bs-example\">\n      <p>The following snippet of text is <em>rendered as italicized text</em>.</p>\n    </div>\n{% highlight html %}\n<em>rendered as italicized text</em>\n{% endhighlight %}\n\n    <div class=\"bs-callout bs-callout-info\">\n      <h4>Alternate elements</h4>\n      <p>Feel free to use <code>&lt;b&gt;</code> and <code>&lt;i&gt;</code> in HTML5. <code>&lt;b&gt;</code> is meant to highlight words or phrases without conveying additional importance while <code>&lt;i&gt;</code> is mostly for voice, technical terms, etc.</p>\n    </div>\n\n    <h3>Alignment classes</h3>\n    <p>Easily realign text to components with text alignment classes.</p>\n    <div class=\"bs-example\">\n      <p class=\"text-left\">Left aligned text.</p>\n      <p class=\"text-center\">Center aligned text.</p>\n      <p class=\"text-right\">Right aligned text.</p>\n    </div>\n{% highlight html %}\n<p class=\"text-left\">Left aligned text.</p>\n<p class=\"text-center\">Center aligned text.</p>\n<p class=\"text-right\">Right aligned text.</p>\n{% endhighlight %}\n\n    <h3>Emphasis classes</h3>\n    <p>Convey meaning through color with a handful of emphasis utility classes.</p>\n    <div class=\"bs-example\">\n      <p class=\"text-muted\">Fusce dapibus, tellus ac cursus commodo, tortor mauris nibh.</p>\n      <p class=\"text-primary\">Nullam id dolor id nibh ultricies vehicula ut id elit.</p>\n      <p class=\"text-success\">Duis mollis, est non commodo luctus, nisi erat porttitor ligula.</p>\n      <p class=\"text-info\">Maecenas sed diam eget risus varius blandit sit amet non magna.</p>\n      <p class=\"text-warning\">Etiam porta sem malesuada magna mollis euismod.</p>\n      <p class=\"text-danger\">Donec ullamcorper nulla non metus auctor fringilla.</p>\n    </div>\n{% highlight html %}\n<p class=\"text-muted\">...</p>\n<p class=\"text-primary\">...</p>\n<p class=\"text-success\">...</p>\n<p class=\"text-info\">...</p>\n<p class=\"text-warning\">...</p>\n<p class=\"text-danger\">...</p>\n{% endhighlight %}\n\n\n    <!-- Abbreviations -->\n    <h2 id=\"type-abbreviations\">Abbreviations</h2>\n    <p>Stylized implementation of HTML's <code>&lt;abbr&gt;</code> element for abbreviations and acronyms to show the expanded version on hover. Abbreviations with a <code>title</code> attribute have a light dotted bottom border and a help cursor on hover, providing additional context on hover.</p>\n\n    <h3>Basic abbreviation</h3>\n    <p>For expanded text on long hover of an abbreviation, include the <code>title</code> attribute with the <code>&lt;abbr&gt;</code> element.</p>\n    <div class=\"bs-example\">\n      <p>An abbreviation of the word attribute is <abbr title=\"attribute\">attr</abbr>.</p>\n    </div>\n{% highlight html %}\n<abbr title=\"attribute\">attr</abbr>\n{% endhighlight %}\n\n    <h3>Initialism</h3>\n    <p>Add <code>.initialism</code> to an abbreviation for a slightly smaller font-size.</p>\n    <div class=\"bs-example\">\n      <p><abbr title=\"HyperText Markup Language\" class=\"initialism\">HTML</abbr> is the best thing since sliced bread.</p>\n    </div>\n{% highlight html %}\n<abbr title=\"HyperText Markup Language\" class=\"initialism\">HTML</abbr>\n{% endhighlight %}\n\n\n    <!-- Addresses -->\n    <h2 id=\"type-addresses\">Addresses</h2>\n    <p>Present contact information for the nearest ancestor or the entire body of work. Preserve formatting by ending all lines with <code>&lt;br&gt;</code>.</p>\n    <div class=\"bs-example\">\n      <address>\n        <strong>Twitter, Inc.</strong><br>\n        795 Folsom Ave, Suite 600<br>\n        San Francisco, CA 94107<br>\n        <abbr title=\"Phone\">P:</abbr> (123) 456-7890\n      </address>\n      <address>\n        <strong>Full Name</strong><br>\n        <a href=\"mailto:#\">first.last@example.com</a>\n      </address>\n    </div>\n{% highlight html %}\n<address>\n  <strong>Twitter, Inc.</strong><br>\n  795 Folsom Ave, Suite 600<br>\n  San Francisco, CA 94107<br>\n  <abbr title=\"Phone\">P:</abbr> (123) 456-7890\n</address>\n\n<address>\n  <strong>Full Name</strong><br>\n  <a href=\"mailto:#\">first.last@example.com</a>\n</address>\n{% endhighlight %}\n\n\n    <!-- Blockquotes -->\n    <h2 id=\"type-blockquotes\">Blockquotes</h2>\n    <p>For quoting blocks of content from another source within your document.</p>\n\n    <h3>Default blockquote</h3>\n    <p>Wrap <code>&lt;blockquote&gt;</code> around any <abbr title=\"HyperText Markup Language\">HTML</abbr> as the quote. For straight quotes, we recommend a <code>&lt;p&gt;</code>.</p>\n    <div class=\"bs-example\">\n      <blockquote>\n        <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer posuere erat a ante.</p>\n      </blockquote>\n    </div>\n{% highlight html %}\n<blockquote>\n  <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer posuere erat a ante.</p>\n</blockquote>\n{% endhighlight %}\n\n    <h3>Blockquote options</h3>\n    <p>Style and content changes for simple variations on a standard <code>&lt;blockquote&gt;</code>.</p>\n\n    <h4>Naming a source</h4>\n    <p>Add <code>&lt;small&gt;</code> tag for identifying the source. Wrap the name of the source work in <code>&lt;cite&gt;</code>.</p>\n    <div class=\"bs-example\">\n      <blockquote>\n        <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer posuere erat a ante.</p>\n        <small>Someone famous in <cite title=\"Source Title\">Source Title</cite></small>\n      </blockquote>\n    </div>\n{% highlight html %}\n<blockquote>\n  <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer posuere erat a ante.</p>\n  <small>Someone famous in <cite title=\"Source Title\">Source Title</cite></small>\n</blockquote>\n{% endhighlight %}\n\n    <h4>Alternate displays</h4>\n    <p>Use <code>.pull-right</code> for a floated, right-aligned blockquote.</p>\n    <div class=\"bs-example\" style=\"overflow: hidden;\">\n      <blockquote class=\"pull-right\">\n        <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer posuere erat a ante.</p>\n        <small>Someone famous in <cite title=\"Source Title\">Source Title</cite></small>\n      </blockquote>\n    </div>\n{% highlight html %}\n<blockquote class=\"pull-right\">\n  ...\n</blockquote>\n{% endhighlight %}\n\n\n    <!-- Lists -->\n    <h2 id=\"type-lists\">Lists</h2>\n\n    <h3>Unordered</h3>\n    <p>A list of items in which the order does <em>not</em> explicitly matter.</p>\n    <div class=\"bs-example\">\n      <ul>\n        <li>Lorem ipsum dolor sit amet</li>\n        <li>Consectetur adipiscing elit</li>\n        <li>Integer molestie lorem at massa</li>\n        <li>Facilisis in pretium nisl aliquet</li>\n        <li>Nulla volutpat aliquam velit\n          <ul>\n            <li>Phasellus iaculis neque</li>\n            <li>Purus sodales ultricies</li>\n            <li>Vestibulum laoreet porttitor sem</li>\n            <li>Ac tristique libero volutpat at</li>\n          </ul>\n        </li>\n        <li>Faucibus porta lacus fringilla vel</li>\n        <li>Aenean sit amet erat nunc</li>\n        <li>Eget porttitor lorem</li>\n      </ul>\n    </div>\n{% highlight html %}\n<ul>\n  <li>...</li>\n</ul>\n{% endhighlight %}\n\n    <h3>Ordered</h3>\n    <p>A list of items in which the order <em>does</em> explicitly matter.</p>\n    <div class=\"bs-example\">\n      <ol>\n        <li>Lorem ipsum dolor sit amet</li>\n        <li>Consectetur adipiscing elit</li>\n        <li>Integer molestie lorem at massa</li>\n        <li>Facilisis in pretium nisl aliquet</li>\n        <li>Nulla volutpat aliquam velit</li>\n        <li>Faucibus porta lacus fringilla vel</li>\n        <li>Aenean sit amet erat nunc</li>\n        <li>Eget porttitor lorem</li>\n      </ol>\n    </div>\n{% highlight html %}\n<ol>\n  <li>...</li>\n</ol>\n{% endhighlight %}\n\n    <h3>Unstyled</h3>\n    <p>Remove the default <code>list-style</code> and left margin on list items (immediate children only). <strong>This only applies to immediate children list items</strong>, meaning you will need to add the class for any nested lists as well.</p>\n    <div class=\"bs-example\">\n      <ul class=\"list-unstyled\">\n        <li>Lorem ipsum dolor sit amet</li>\n        <li>Consectetur adipiscing elit</li>\n        <li>Integer molestie lorem at massa</li>\n        <li>Facilisis in pretium nisl aliquet</li>\n        <li>Nulla volutpat aliquam velit\n          <ul>\n            <li>Phasellus iaculis neque</li>\n            <li>Purus sodales ultricies</li>\n            <li>Vestibulum laoreet porttitor sem</li>\n            <li>Ac tristique libero volutpat at</li>\n          </ul>\n        </li>\n        <li>Faucibus porta lacus fringilla vel</li>\n        <li>Aenean sit amet erat nunc</li>\n        <li>Eget porttitor lorem</li>\n      </ul>\n    </div>\n{% highlight html %}\n<ul class=\"list-unstyled\">\n  <li>...</li>\n</ul>\n{% endhighlight %}\n\n    <h3>Inline</h3>\n    <p>Place all list items on a single line with <code>display: inline-block;</code> and some light padding.</p>\n    <div class=\"bs-example\">\n      <ul class=\"list-inline\">\n        <li>Lorem ipsum</li>\n        <li>Phasellus iaculis</li>\n        <li>Nulla volutpat</li>\n      </ul>\n    </div>\n{% highlight html %}\n<ul class=\"list-inline\">\n  <li>...</li>\n</ul>\n{% endhighlight %}\n\n    <h3>Description</h3>\n    <p>A list of terms with their associated descriptions.</p>\n    <div class=\"bs-example\">\n      <dl>\n        <dt>Description lists</dt>\n        <dd>A description list is perfect for defining terms.</dd>\n        <dt>Euismod</dt>\n        <dd>Vestibulum id ligula porta felis euismod semper eget lacinia odio sem nec elit.</dd>\n        <dd>Donec id elit non mi porta gravida at eget metus.</dd>\n        <dt>Malesuada porta</dt>\n        <dd>Etiam porta sem malesuada magna mollis euismod.</dd>\n      </dl>\n    </div>\n{% highlight html %}\n<dl>\n  <dt>...</dt>\n  <dd>...</dd>\n</dl>\n{% endhighlight %}\n\n    <h4>Horizontal description</h4>\n    <p>Make terms and descriptions in <code>&lt;dl&gt;</code> line up side-by-side. Starts off stacked like default <code>&lt;dl&gt;</code>s, but when the navbar expands, so do these.</p>\n    <div class=\"bs-example\">\n      <dl class=\"dl-horizontal\">\n        <dt>Description lists</dt>\n        <dd>A description list is perfect for defining terms.</dd>\n        <dt>Euismod</dt>\n        <dd>Vestibulum id ligula porta felis euismod semper eget lacinia odio sem nec elit.</dd>\n        <dd>Donec id elit non mi porta gravida at eget metus.</dd>\n        <dt>Malesuada porta</dt>\n        <dd>Etiam porta sem malesuada magna mollis euismod.</dd>\n        <dt>Felis euismod semper eget lacinia</dt>\n        <dd>Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus.</dd>\n      </dl>\n    </div>\n{% highlight html %}\n<dl class=\"dl-horizontal\">\n  <dt>...</dt>\n  <dd>...</dd>\n</dl>\n{% endhighlight %}\n\n    <div class=\"bs-callout bs-callout-info\">\n      <h4>Auto-truncating</h4>\n      <p>Horizontal description lists will truncate terms that are too long to fit in the left column with <code>text-overflow</code>. In narrower viewports, they will change to the default stacked layout.</p>\n    </div>\n  </div>\n\n\n  <!-- Code\n  ================================================== -->\n  <div class=\"bs-docs-section\">\n    <div class=\"page-header\">\n      <h1 id=\"code\">Code</h1>\n    </div>\n\n    <h2>Inline</h2>\n    <p>Wrap inline snippets of code with <code>&lt;code&gt;</code>.</p>\n<div class=\"bs-example\">\n  For example, <code>&lt;section&gt;</code> should be wrapped as inline.\n</div>\n{% highlight html %}\nFor example, <code>&lt;section&gt;</code> should be wrapped as inline.\n{% endhighlight %}\n\n    <h2>Basic block</h2>\n    <p>Use <code>&lt;pre&gt;</code> for multiple lines of code. Be sure to escape any angle brackets in the code for proper rendering.</p>\n<div class=\"bs-example\">\n  <pre>&lt;p&gt;Sample text here...&lt;/p&gt;</pre>\n</div>\n{% highlight html %}\n<pre>&lt;p&gt;Sample text here...&lt;/p&gt;</pre>\n{% endhighlight %}\n\n    <p>You may optionally add the <code>.pre-scrollable</code> class, which will set a max-height of 350px and provide a y-axis scrollbar.</p>\n  </div>\n\n\n\n  <!-- Tables\n  ================================================== -->\n  <div class=\"bs-docs-section\">\n    <div class=\"page-header\">\n      <h1 id=\"tables\">Tables</h1>\n    </div>\n\n    <h2 id=\"tables-example\">Basic example</h2>\n    <p>For basic styling&mdash;light padding and only horizontal dividers&mdash;add the base class <code>.table</code> to any <code>&lt;table&gt;</code>. It may seem super redundant, but given the widespread use of tables for other plugins like calendars and date pickers, we've opted to isolate our custom table styles.</p>\n    <div class=\"bs-example\">\n      <table class=\"table\">\n        <thead>\n          <tr>\n            <th>#</th>\n            <th>First Name</th>\n            <th>Last Name</th>\n            <th>Username</th>\n          </tr>\n        </thead>\n        <tbody>\n          <tr>\n            <td>1</td>\n            <td>Mark</td>\n            <td>Otto</td>\n            <td>@mdo</td>\n          </tr>\n          <tr>\n            <td>2</td>\n            <td>Jacob</td>\n            <td>Thornton</td>\n            <td>@fat</td>\n          </tr>\n          <tr>\n            <td>3</td>\n            <td>Larry</td>\n            <td>the Bird</td>\n            <td>@twitter</td>\n          </tr>\n        </tbody>\n      </table>\n    </div><!-- /example -->\n{% highlight html %}\n<table class=\"table\">\n  ...\n</table>\n{% endhighlight %}\n\n\n    <h2 id=\"tables-striped\">Striped rows</h2>\n    <p>Use <code>.table-striped</code> to add zebra-striping to any table row within the <code>&lt;tbody&gt;</code>.</p>\n    <div class=\"bs-callout bs-callout-danger\">\n      <h4>Cross-browser compatibility</h4>\n      <p>Striped tables are styled via the <code>:nth-child</code> CSS selector, which is not available in Internet Explorer 8.</p>\n    </div>\n    <div class=\"bs-example\">\n      <table class=\"table table-striped\">\n        <thead>\n          <tr>\n            <th>#</th>\n            <th>First Name</th>\n            <th>Last Name</th>\n            <th>Username</th>\n          </tr>\n        </thead>\n        <tbody>\n          <tr>\n            <td>1</td>\n            <td>Mark</td>\n            <td>Otto</td>\n            <td>@mdo</td>\n          </tr>\n          <tr>\n            <td>2</td>\n            <td>Jacob</td>\n            <td>Thornton</td>\n            <td>@fat</td>\n          </tr>\n          <tr>\n            <td>3</td>\n            <td>Larry</td>\n            <td>the Bird</td>\n            <td>@twitter</td>\n          </tr>\n        </tbody>\n      </table>\n    </div><!-- /example -->\n{% highlight html %}\n<table class=\"table table-striped\">\n  ...\n</table>\n{% endhighlight %}\n\n\n    <h2 id=\"tables-bordered\">Bordered table</h2>\n    <p>Add <code>.table-bordered</code> for borders on all sides of the table and cells.</p>\n    <div class=\"bs-example\">\n      <table class=\"table table-bordered\">\n        <thead>\n          <tr>\n            <th>#</th>\n            <th>First Name</th>\n            <th>Last Name</th>\n            <th>Username</th>\n          </tr>\n        </thead>\n        <tbody>\n          <tr>\n            <td rowspan=\"2\">1</td>\n            <td>Mark</td>\n            <td>Otto</td>\n            <td>@mdo</td>\n          </tr>\n          <tr>\n            <td>Mark</td>\n            <td>Otto</td>\n            <td>@TwBootstrap</td>\n          </tr>\n          <tr>\n            <td>2</td>\n            <td>Jacob</td>\n            <td>Thornton</td>\n            <td>@fat</td>\n          </tr>\n          <tr>\n            <td>3</td>\n            <td colspan=\"2\">Larry the Bird</td>\n            <td>@twitter</td>\n          </tr>\n        </tbody>\n      </table>\n    </div><!-- /example -->\n{% highlight html %}\n<table class=\"table table-bordered\">\n  ...\n</table>\n{% endhighlight %}\n\n\n    <h2 id=\"tables-hover-rows\">Hover rows</h2>\n    <p>Add <code>.table-hover</code> to enable a hover state on table rows within a <code>&lt;tbody&gt;</code>.</p>\n    <div class=\"bs-example\">\n      <table class=\"table table-hover\">\n        <thead>\n          <tr>\n            <th>#</th>\n            <th>First Name</th>\n            <th>Last Name</th>\n            <th>Username</th>\n          </tr>\n        </thead>\n        <tbody>\n          <tr>\n            <td>1</td>\n            <td>Mark</td>\n            <td>Otto</td>\n            <td>@mdo</td>\n          </tr>\n          <tr>\n            <td>2</td>\n            <td>Jacob</td>\n            <td>Thornton</td>\n            <td>@fat</td>\n          </tr>\n          <tr>\n            <td>3</td>\n            <td colspan=\"2\">Larry the Bird</td>\n            <td>@twitter</td>\n          </tr>\n        </tbody>\n      </table>\n    </div><!-- /example -->\n{% highlight html %}\n<table class=\"table table-hover\">\n  ...\n</table>\n{% endhighlight %}\n\n\n    <h2 id=\"tables-condensed\">Condensed table</h2>\n    <p>Add <code>.table-condensed</code> to make tables more compact by cutting cell padding in half.</p>\n    <div class=\"bs-example\">\n      <table class=\"table table-condensed\">\n        <thead>\n          <tr>\n            <th>#</th>\n            <th>First Name</th>\n            <th>Last Name</th>\n            <th>Username</th>\n          </tr>\n        </thead>\n        <tbody>\n          <tr>\n            <td>1</td>\n            <td>Mark</td>\n            <td>Otto</td>\n            <td>@mdo</td>\n          </tr>\n          <tr>\n            <td>2</td>\n            <td>Jacob</td>\n            <td>Thornton</td>\n            <td>@fat</td>\n          </tr>\n          <tr>\n            <td>3</td>\n            <td colspan=\"2\">Larry the Bird</td>\n            <td>@twitter</td>\n          </tr>\n        </tbody>\n      </table>\n    </div><!-- /example -->\n{% highlight html %}\n<table class=\"table table-condensed\">\n  ...\n</table>\n{% endhighlight %}\n\n\n    <h2 id=\"tables-contextual-classes\">Contextual classes</h2>\n    <p>Use contextual classes to color table rows or individual cells.</p>\n    <div class=\"table-responsive\">\n      <table class=\"table table-bordered table-striped\">\n        <colgroup>\n          <col class=\"col-lg-1\">\n          <col class=\"col-lg-7\">\n        </colgroup>\n        <thead>\n          <tr>\n            <th>Class</th>\n            <th>Description</th>\n          </tr>\n        </thead>\n        <tbody>\n          <tr>\n            <td>\n              <code>.active</code>\n            </td>\n            <td>Applies the hover color to a particular row or cell</td>\n          </tr>\n          <tr>\n            <td>\n              <code>.success</code>\n            </td>\n            <td>Indicates a successful or positive action</td>\n          </tr>\n          <tr>\n            <td>\n              <code>.warning</code>\n            </td>\n            <td>Indicates a warning that might need attention</td>\n          </tr>\n          <tr>\n            <td>\n              <code>.danger</code>\n            </td>\n            <td>Indicates a dangerous or potentially negative action</td>\n          </tr>\n        </tbody>\n      </table>\n    </div>\n    <div class=\"bs-example\">\n      <table class=\"table\">\n        <thead>\n          <tr>\n            <th>#</th>\n            <th>Column heading</th>\n            <th>Column heading</th>\n            <th>Column heading</th>\n          </tr>\n        </thead>\n        <tbody>\n          <tr class=\"active\">\n            <td>1</td>\n            <td>Column content</td>\n            <td>Column content</td>\n            <td>Column content</td>\n          </tr>\n          <tr>\n            <td>2</td>\n            <td>Column content</td>\n            <td>Column content</td>\n            <td>Column content</td>\n          </tr>\n          <tr class=\"success\">\n            <td>3</td>\n            <td>Column content</td>\n            <td>Column content</td>\n            <td>Column content</td>\n          </tr>\n          <tr>\n            <td>4</td>\n            <td>Column content</td>\n            <td>Column content</td>\n            <td>Column content</td>\n          </tr>\n          <tr class=\"warning\">\n            <td>5</td>\n            <td>Column content</td>\n            <td>Column content</td>\n            <td>Column content</td>\n          </tr>\n          <tr>\n            <td>6</td>\n            <td>Column content</td>\n            <td>Column content</td>\n            <td>Column content</td>\n          </tr>\n          <tr class=\"danger\">\n            <td>7</td>\n            <td>Column content</td>\n            <td>Column content</td>\n            <td>Column content</td>\n          </tr>\n        </tbody>\n      </table>\n    </div><!-- /example -->\n{% highlight html %}\n<!-- On rows -->\n<tr class=\"active\">...</tr>\n<tr class=\"success\">...</tr>\n<tr class=\"warning\">...</tr>\n<tr class=\"danger\">...</tr>\n\n<!-- On cells (`td` or `th`) -->\n<tr>\n  <td class=\"active\">...</td>\n  <td class=\"success\">...</td>\n  <td class=\"warning\">...</td>\n  <td class=\"danger\">...</td>\n</tr>\n{% endhighlight %}\n\n\n    <h2 id=\"tables-responsive\">Responsive tables</h2>\n    <p>Create responsive tables by wrapping any <code>.table</code> in <code>.table-responsive</code> to make them scroll horizontally up to small devices (under 768px). When viewing on anything larger than 768px wide, you will not see any difference in these tables.</p>\n    <div class=\"bs-example\">\n      <div class=\"table-responsive\">\n        <table class=\"table\">\n          <thead>\n            <tr>\n              <th>#</th>\n              <th>Table heading</th>\n              <th>Table heading</th>\n              <th>Table heading</th>\n              <th>Table heading</th>\n              <th>Table heading</th>\n              <th>Table heading</th>\n            </tr>\n          </thead>\n          <tbody>\n            <tr>\n              <td>1</td>\n              <td>Table cell</td>\n              <td>Table cell</td>\n              <td>Table cell</td>\n              <td>Table cell</td>\n              <td>Table cell</td>\n              <td>Table cell</td>\n            </tr>\n            <tr>\n              <td>2</td>\n              <td>Table cell</td>\n              <td>Table cell</td>\n              <td>Table cell</td>\n              <td>Table cell</td>\n              <td>Table cell</td>\n              <td>Table cell</td>\n            </tr>\n            <tr>\n              <td>3</td>\n              <td>Table cell</td>\n              <td>Table cell</td>\n              <td>Table cell</td>\n              <td>Table cell</td>\n              <td>Table cell</td>\n              <td>Table cell</td>\n            </tr>\n          </tbody>\n        </table>\n      </div><!-- /.table-responsive -->\n\n      <div class=\"table-responsive\">\n        <table class=\"table table-bordered\">\n          <thead>\n            <tr>\n              <th>#</th>\n              <th>Table heading</th>\n              <th>Table heading</th>\n              <th>Table heading</th>\n              <th>Table heading</th>\n              <th>Table heading</th>\n              <th>Table heading</th>\n            </tr>\n          </thead>\n          <tbody>\n            <tr>\n              <td>1</td>\n              <td>Table cell</td>\n              <td>Table cell</td>\n              <td>Table cell</td>\n              <td>Table cell</td>\n              <td>Table cell</td>\n              <td>Table cell</td>\n            </tr>\n            <tr>\n              <td>2</td>\n              <td>Table cell</td>\n              <td>Table cell</td>\n              <td>Table cell</td>\n              <td>Table cell</td>\n              <td>Table cell</td>\n              <td>Table cell</td>\n            </tr>\n            <tr>\n              <td>3</td>\n              <td>Table cell</td>\n              <td>Table cell</td>\n              <td>Table cell</td>\n              <td>Table cell</td>\n              <td>Table cell</td>\n              <td>Table cell</td>\n            </tr>\n          </tbody>\n        </table>\n      </div><!-- /.table-responsive -->\n    </div><!-- /example -->\n{% highlight html %}\n<div class=\"table-responsive\">\n  <table class=\"table\">\n    ...\n  </table>\n</div>\n{% endhighlight %}\n\n  </div>\n\n\n\n  <!-- Forms\n  ================================================== -->\n  <div class=\"bs-docs-section\">\n    <div class=\"page-header\">\n      <h1 id=\"forms\">Forms</h1>\n    </div>\n\n    <h2 id=\"forms-example\">Basic example</h2>\n    <p>Individual form controls automatically receive some global styling. All textual <code>&lt;input&gt;</code>, <code>&lt;textarea&gt;</code>, and <code>&lt;select&gt;</code> elements with <code>.form-control</code> are set to <code>width: 100%;</code> by default. Wrap labels and controls in <code>.form-group</code> for optimum spacing.</p>\n    <form class=\"bs-example\" role=\"form\">\n      <div class=\"form-group\">\n        <label for=\"exampleInputEmail1\">Email address</label>\n        <input type=\"email\" class=\"form-control\" id=\"exampleInputEmail1\" placeholder=\"Enter email\">\n      </div>\n      <div class=\"form-group\">\n        <label for=\"exampleInputPassword1\">Password</label>\n        <input type=\"password\" class=\"form-control\" id=\"exampleInputPassword1\" placeholder=\"Password\">\n      </div>\n      <div class=\"form-group\">\n        <label for=\"exampleInputFile\">File input</label>\n        <input type=\"file\" id=\"exampleInputFile\">\n        <p class=\"help-block\">Example block-level help text here.</p>\n      </div>\n      <div class=\"checkbox\">\n        <label>\n          <input type=\"checkbox\"> Check me out\n        </label>\n      </div>\n      <button type=\"submit\" class=\"btn btn-default\">Submit</button>\n    </form><!-- /example -->\n{% highlight html %}\n<form role=\"form\">\n  <div class=\"form-group\">\n    <label for=\"exampleInputEmail1\">Email address</label>\n    <input type=\"email\" class=\"form-control\" id=\"exampleInputEmail1\" placeholder=\"Enter email\">\n  </div>\n  <div class=\"form-group\">\n    <label for=\"exampleInputPassword1\">Password</label>\n    <input type=\"password\" class=\"form-control\" id=\"exampleInputPassword1\" placeholder=\"Password\">\n  </div>\n  <div class=\"form-group\">\n    <label for=\"exampleInputFile\">File input</label>\n    <input type=\"file\" id=\"exampleInputFile\">\n    <p class=\"help-block\">Example block-level help text here.</p>\n  </div>\n  <div class=\"checkbox\">\n    <label>\n      <input type=\"checkbox\"> Check me out\n    </label>\n  </div>\n  <button type=\"submit\" class=\"btn btn-default\">Submit</button>\n</form>\n{% endhighlight %}\n\n\n    <h2 id=\"forms-inline\">Inline form</h2>\n    <p>Add <code>.form-inline</code> for left-aligned and inline-block controls for a compact layout.</p>\n    <div class=\"bs-callout bs-callout-danger\">\n      <h4>Requires custom widths</h4>\n      <p>Inputs, selects, and textareas are 100% wide by default in Bootstrap. To use the inline form, you'll have to set a width on the form controls used within.</p>\n    </div>\n    <div class=\"bs-callout bs-callout-danger\">\n      <h4>Always add labels</h4>\n      <p>Screen readers will have trouble with your forms if you don't include a label for every input. For these inline forms, you can hide the labels using the <code>.sr-only</code> class.</p>\n    </div>\n    <form class=\"bs-example form-inline\" role=\"form\">\n      <div class=\"form-group\">\n        <label class=\"sr-only\" for=\"exampleInputEmail2\">Email address</label>\n        <input type=\"email\" class=\"form-control\" id=\"exampleInputEmail2\" placeholder=\"Enter email\">\n      </div>\n      <div class=\"form-group\">\n        <label class=\"sr-only\" for=\"exampleInputPassword2\">Password</label>\n        <input type=\"password\" class=\"form-control\" id=\"exampleInputPassword2\" placeholder=\"Password\">\n      </div>\n      <div class=\"checkbox\">\n        <label>\n          <input type=\"checkbox\"> Remember me\n        </label>\n      </div>\n      <button type=\"submit\" class=\"btn btn-default\">Sign in</button>\n    </form><!-- /example -->\n{% highlight html %}\n<form class=\"form-inline\" role=\"form\">\n  <div class=\"form-group\">\n    <label class=\"sr-only\" for=\"exampleInputEmail2\">Email address</label>\n    <input type=\"email\" class=\"form-control\" id=\"exampleInputEmail2\" placeholder=\"Enter email\">\n  </div>\n  <div class=\"form-group\">\n    <label class=\"sr-only\" for=\"exampleInputPassword2\">Password</label>\n    <input type=\"password\" class=\"form-control\" id=\"exampleInputPassword2\" placeholder=\"Password\">\n  </div>\n  <div class=\"checkbox\">\n    <label>\n      <input type=\"checkbox\"> Remember me\n    </label>\n  </div>\n  <button type=\"submit\" class=\"btn btn-default\">Sign in</button>\n</form>\n{% endhighlight %}\n\n\n    <h2 id=\"forms-horizontal\">Horizontal form</h2>\n    <p>Use Bootstrap's predefined grid classes to align labels and groups of form controls in a horizontal layout by adding <code>.form-horizontal</code> to the form. Doing so changes <code>.form-group</code>s to behave as grid rows, so no need for <code>.row</code>.</p>\n    <form class=\"bs-example form-horizontal\">\n      <div class=\"form-group\">\n        <label for=\"inputEmail1\" class=\"col-lg-2 control-label\">Email</label>\n        <div class=\"col-lg-10\">\n          <input type=\"email\" class=\"form-control\" id=\"inputEmail1\" placeholder=\"Email\">\n        </div>\n      </div>\n      <div class=\"form-group\">\n        <label for=\"inputPassword1\" class=\"col-lg-2 control-label\">Password</label>\n        <div class=\"col-lg-10\">\n          <input type=\"password\" class=\"form-control\" id=\"inputPassword1\" placeholder=\"Password\">\n        </div>\n      </div>\n      <div class=\"form-group\">\n        <div class=\"col-lg-offset-2 col-lg-10\">\n          <div class=\"checkbox\">\n            <label>\n              <input type=\"checkbox\"> Remember me\n            </label>\n          </div>\n        </div>\n      </div>\n      <div class=\"form-group\">\n        <div class=\"col-lg-offset-2 col-lg-10\">\n          <button type=\"submit\" class=\"btn btn-default\">Sign in</button>\n        </div>\n      </div>\n    </form>\n{% highlight html %}\n<form class=\"form-horizontal\" role=\"form\">\n  <div class=\"form-group\">\n    <label for=\"inputEmail1\" class=\"col-lg-2 control-label\">Email</label>\n    <div class=\"col-lg-10\">\n      <input type=\"email\" class=\"form-control\" id=\"inputEmail1\" placeholder=\"Email\">\n    </div>\n  </div>\n  <div class=\"form-group\">\n    <label for=\"inputPassword1\" class=\"col-lg-2 control-label\">Password</label>\n    <div class=\"col-lg-10\">\n      <input type=\"password\" class=\"form-control\" id=\"inputPassword1\" placeholder=\"Password\">\n    </div>\n  </div>\n  <div class=\"form-group\">\n    <div class=\"col-lg-offset-2 col-lg-10\">\n      <div class=\"checkbox\">\n        <label>\n          <input type=\"checkbox\"> Remember me\n        </label>\n      </div>\n    </div>\n  </div>\n  <div class=\"form-group\">\n    <div class=\"col-lg-offset-2 col-lg-10\">\n      <button type=\"submit\" class=\"btn btn-default\">Sign in</button>\n    </div>\n  </div>\n</form>\n{% endhighlight %}\n\n\n    <h2 id=\"forms-controls\">Supported controls</h2>\n    <p>Examples of standard form controls supported in an example form layout.</p>\n\n    <h3>Inputs</h3>\n    <p>Most common form control, text-based input fields. Includes support for all HTML5 types: <code>text</code>, <code>password</code>, <code>datetime</code>, <code>datetime-local</code>, <code>date</code>, <code>month</code>, <code>time</code>, <code>week</code>, <code>number</code>, <code>email</code>, <code>url</code>, <code>search</code>, <code>tel</code>, and <code>color</code>.</p>\n    <div class=\"bs-callout bs-callout-danger\">\n      <h4>Type declaration required</h4>\n      <p>Inputs will only be fully styled if their <code>type</code> is properly declared.</p>\n    </div>\n    <form class=\"bs-example\">\n      <input type=\"text\" class=\"form-control\" placeholder=\"Text input\">\n    </form>\n{% highlight html %}\n<input type=\"text\" class=\"form-control\" placeholder=\"Text input\">\n{% endhighlight %}\n\n    <h3>Textarea</h3>\n    <p>Form control which supports multiple lines of text. Change <code>rows</code> attribute as necessary.</p>\n    <form class=\"bs-example\">\n      <textarea class=\"form-control\" rows=\"3\"></textarea>\n    </form>\n{% highlight html %}\n<textarea class=\"form-control\" rows=\"3\"></textarea>\n{% endhighlight %}\n\n    <h3>Checkboxes and radios</h3>\n    <p>Checkboxes are for selecting one or several options in a list while radios are for selecting one option from many.</p>\n    <h4>Default (stacked)</h4>\n    <form class=\"bs-example\">\n      <div class=\"checkbox\">\n        <label>\n          <input type=\"checkbox\" value=\"\">\n          Option one is this and that&mdash;be sure to include why it's great\n        </label>\n      </div>\n      <br>\n      <div class=\"radio\">\n        <label>\n          <input type=\"radio\" name=\"optionsRadios\" id=\"optionsRadios1\" value=\"option1\" checked>\n          Option one is this and that&mdash;be sure to include why it's great\n        </label>\n      </div>\n      <div class=\"radio\">\n        <label>\n          <input type=\"radio\" name=\"optionsRadios\" id=\"optionsRadios2\" value=\"option2\">\n          Option two can be something else and selecting it will deselect option one\n        </label>\n      </div>\n    </form>\n{% highlight html %}\n<div class=\"checkbox\">\n  <label>\n    <input type=\"checkbox\" value=\"\">\n    Option one is this and that&mdash;be sure to include why it's great\n  </label>\n</div>\n\n<div class=\"radio\">\n  <label>\n    <input type=\"radio\" name=\"optionsRadios\" id=\"optionsRadios1\" value=\"option1\" checked>\n    Option one is this and that&mdash;be sure to include why it's great\n  </label>\n</div>\n<div class=\"radio\">\n  <label>\n    <input type=\"radio\" name=\"optionsRadios\" id=\"optionsRadios2\" value=\"option2\">\n    Option two can be something else and selecting it will deselect option one\n  </label>\n</div>\n{% endhighlight %}\n\n    <h4>Inline checkboxes</h4>\n    <p>Use <code>.checkbox-inline</code> or <code>.radio-inline</code> class to a series of checkboxes or radios for controls appear on the same line.</p>\n    <form class=\"bs-example\">\n      <label class=\"checkbox-inline\">\n        <input type=\"checkbox\" id=\"inlineCheckbox1\" value=\"option1\"> 1\n      </label>\n      <label class=\"checkbox-inline\">\n        <input type=\"checkbox\" id=\"inlineCheckbox2\" value=\"option2\"> 2\n      </label>\n      <label class=\"checkbox-inline\">\n        <input type=\"checkbox\" id=\"inlineCheckbox3\" value=\"option3\"> 3\n      </label>\n    </form>\n{% highlight html %}\n<label class=\"checkbox-inline\">\n  <input type=\"checkbox\" id=\"inlineCheckbox1\" value=\"option1\"> 1\n</label>\n<label class=\"checkbox-inline\">\n  <input type=\"checkbox\" id=\"inlineCheckbox2\" value=\"option2\"> 2\n</label>\n<label class=\"checkbox-inline\">\n  <input type=\"checkbox\" id=\"inlineCheckbox3\" value=\"option3\"> 3\n</label>\n{% endhighlight %}\n\n    <h3>Selects</h3>\n    <p>Use the default option, or add <code>multiple</code> to show multiple options at once.</p>\n    <form class=\"bs-example\">\n      <select class=\"form-control\">\n        <option>1</option>\n        <option>2</option>\n        <option>3</option>\n        <option>4</option>\n        <option>5</option>\n      </select>\n      <br>\n      <select multiple class=\"form-control\">\n        <option>1</option>\n        <option>2</option>\n        <option>3</option>\n        <option>4</option>\n        <option>5</option>\n      </select>\n    </form>\n{% highlight html %}\n<select class=\"form-control\">\n  <option>1</option>\n  <option>2</option>\n  <option>3</option>\n  <option>4</option>\n  <option>5</option>\n</select>\n\n<select multiple class=\"form-control\">\n  <option>1</option>\n  <option>2</option>\n  <option>3</option>\n  <option>4</option>\n  <option>5</option>\n</select>\n{% endhighlight %}\n\n\n    <h2 id=\"forms-controls-static\">Static control</h2>\n    <p>When you need to place plain text next to a form label within a horizontal form, use the <code>.form-control-static</code> class on a <code>&lt;p&gt;</code>.</p>\n    <form class=\"bs-example form-horizontal\">\n      <div class=\"form-group\">\n        <label class=\"col-lg-2 control-label\">Email</label>\n        <div class=\"col-lg-10\">\n          <p class=\"form-control-static\">email@example.com</p>\n        </div>\n      </div>\n      <div class=\"form-group\">\n        <label for=\"inputPassword\" class=\"col-lg-2 control-label\">Password</label>\n        <div class=\"col-lg-10\">\n          <input type=\"password\" class=\"form-control\" id=\"inputPassword\" placeholder=\"Password\">\n        </div>\n      </div>\n    </form>\n{% highlight html %}\n<form class=\"form-horizontal\" role=\"form\">\n  <div class=\"form-group\">\n    <label class=\"col-lg-2 control-label\">Email</label>\n    <div class=\"col-lg-10\">\n      <p class=\"form-control-static\">email@example.com</p>\n    </div>\n  </div>\n  <div class=\"form-group\">\n    <label for=\"inputPassword\" class=\"col-lg-2 control-label\">Password</label>\n    <div class=\"col-lg-10\">\n      <input type=\"password\" class=\"form-control\" id=\"inputPassword\" placeholder=\"Password\">\n    </div>\n  </div>\n</form>\n{% endhighlight %}\n\n\n    <h2 id=\"forms-control-states\">Form states</h2>\n    <p>Provide feedback to users or visitors with basic feedback states on form controls and labels.</p>\n\n    <h3 id=\"forms-input-focus\">Input focus</h3>\n    <p>We remove the default <code>outline</code> styles on some form controls and apply a <code>box-shadow</code> in its place for <code>:focus</code>.</p>\n    <form class=\"bs-example\">\n      <input class=\"form-control\" id=\"focusedInput\" type=\"text\" value=\"This is focused...\">\n    </form>\n{% highlight html %}\n<input class=\"form-control\" id=\"focusedInput\" type=\"text\" value=\"This is focused...\">\n{% endhighlight %}\n\n    <h3 id=\"forms-disabled-inputs\">Disabled inputs</h3>\n    <p>Add the <code>disabled</code> attribute on an input to prevent user input and trigger a slightly different look.</p>\n    <form class=\"bs-example\">\n      <input class=\"form-control\" id=\"disabledInput\" type=\"text\" placeholder=\"Disabled input here…\" disabled>\n    </form>\n{% highlight html %}\n<input class=\"form-control\" id=\"disabledInput\" type=\"text\" placeholder=\"Disabled input here...\" disabled>\n{% endhighlight %}\n\n    <h3 id=\"forms-disabled-fieldsets\">Disabled fieldsets</h3>\n    <p>Add the <code>disabled</code> attribute to a <code>&lt;fieldset&gt;</code> to disable all the controls within the <code>&lt;fieldset&gt;</code> at once.</p>\n\n    <div class=\"bs-callout bs-callout-warning\">\n      <h4>Link functionality of <code>&lt;a&gt;</code> not impacted</h4>\n      <p>This class will only change the appearance of <code>&lt;a class=\"btn btn-default\"&gt;</code> buttons, not their functionality. Use custom JavaScript to disable links here.</p>\n    </div>\n\n    <div class=\"bs-callout bs-callout-danger\">\n      <h4>Cross-browser compatibility</h4>\n      <p>While Bootstrap will apply these styles in all browsers, Internet Explorer 9 and below don't actually support the <code>disabled</code> attribute on a <code>&lt;fieldset&gt;</code>. Use custom JavaScript to disable the fieldset in these browsers.</p>\n    </div>\n\n    <form class=\"bs-example\">\n      <fieldset disabled>\n        <div class=\"form-group\">\n          <label for=\"disabledTextInput\">Disabled input</label>\n          <input type=\"text\" id=\"disabledTextInput\" class=\"form-control\" placeholder=\"Disabled input\">\n        </div>\n        <div class=\"form-group\">\n          <label for=\"disabledSelect\">Disabled select menu</label>\n          <select id=\"disabledSelect\" class=\"form-control\">\n            <option>Disabled select</option>\n          </select>\n        </div>\n        <div class=\"checkbox\">\n          <label>\n            <input type=\"checkbox\"> Can't check this\n          </label>\n        </div>\n        <button type=\"submit\" class=\"btn btn-primary\">Submit</button>\n      </fieldset>\n    </form>\n{% highlight html %}\n<form class=\"form-inline\" role=\"form\">\n  <fieldset disabled>\n    <div class=\"form-group\">\n      <label for=\"disabledTextInput\">Disabled input</label>\n      <input type=\"text\" id=\"disabledTextInput\" class=\"form-control\" placeholder=\"Disabled input\">\n    </div>\n    <div class=\"form-group\">\n      <label for=\"disabledSelect\">Disabled select menu</label>\n      <select id=\"disabledSelect\" class=\"form-control\">\n        <option>Disabled select</option>\n      </select>\n    </div>\n    <div class=\"checkbox\">\n      <label>\n        <input type=\"checkbox\"> Can't check this\n      </label>\n    </div>\n    <button type=\"submit\" class=\"btn btn-primary\">Submit</button>\n  </fieldset>\n</form>\n{% endhighlight %}\n\n    <h3 id=\"forms-validation\">Validation states</h3>\n    <p>Bootstrap includes validation styles for error, warning, and success states on form controls. To use, add <code>.has-warning</code>, <code>.has-error</code>, or <code>.has-success</code> to the parent element. Any <code>.control-label</code>, <code>.form-control</code>, and <code>.help-block</code> within that element will receive the validation styles.</p>\n\n    <form class=\"bs-example\">\n      <div class=\"form-group has-success\">\n        <label class=\"control-label\" for=\"inputSuccess\">Input with success</label>\n        <input type=\"text\" class=\"form-control\" id=\"inputSuccess\">\n      </div>\n      <div class=\"form-group has-warning\">\n        <label class=\"control-label\" for=\"inputWarning\">Input with warning</label>\n        <input type=\"text\" class=\"form-control\" id=\"inputWarning\">\n      </div>\n      <div class=\"form-group has-error\">\n        <label class=\"control-label\" for=\"inputError\">Input with error</label>\n        <input type=\"text\" class=\"form-control\" id=\"inputError\">\n      </div>\n    </form>\n{% highlight html %}\n<div class=\"form-group has-success\">\n  <label class=\"control-label\" for=\"inputSuccess\">Input with success</label>\n  <input type=\"text\" class=\"form-control\" id=\"inputSuccess\">\n</div>\n<div class=\"form-group has-warning\">\n  <label class=\"control-label\" for=\"inputWarning\">Input with warning</label>\n  <input type=\"text\" class=\"form-control\" id=\"inputWarning\">\n</div>\n<div class=\"form-group has-error\">\n  <label class=\"control-label\" for=\"inputError\">Input with error</label>\n  <input type=\"text\" class=\"form-control\" id=\"inputError\">\n</div>\n{% endhighlight %}\n\n\n    <h2 id=\"forms-control-sizes\">Control sizing</h2>\n    <p>Set heights using classes like <code>.input-lg</code>, and set widths using grid column classes like <code>.col-lg-*</code>.</p>\n\n    <h3>Height sizing</h3>\n    <p>Create larger or smaller form controls that match button sizes.</p>\n    <form class=\"bs-example bs-example-control-sizing\">\n      <div class=\"controls docs-input-sizes\">\n        <input class=\"form-control input-lg\" type=\"text\" placeholder=\".input-lg\">\n        <input type=\"text\" class=\"form-control\" placeholder=\"Default input\">\n        <input class=\"form-control input-sm\" type=\"text\" placeholder=\".input-sm\">\n\n        <select class=\"form-control input-lg\">\n          <option value=\"\">.input-lg</option>\n        </select>\n        <select class=\"form-control\">\n          <option value=\"\">Default select</option>\n        </select>\n        <select class=\"form-control input-sm\">\n          <option value=\"\">.input-sm</option>\n        </select>\n      </div>\n    </form>\n{% highlight html %}\n<input class=\"form-control input-lg\" type=\"text\" placeholder=\".input-lg\">\n<input class=\"form-control\" type=\"text\" placeholder=\"Default input\">\n<input class=\"form-control input-sm\" type=\"text\" placeholder=\".input-sm\">\n\n<select class=\"form-control input-lg\">...</select>\n<select class=\"form-control\">...</select>\n<select class=\"form-control input-sm\">...</select>\n{% endhighlight %}\n\n    <h3>Column sizing</h3>\n    <p>Wrap inputs in grid columns, or any custom parent element, to easily enforce desired widths.</p>\n    <form class=\"bs-example\" style=\"padding-bottom: 15px;\">\n      <div class=\"row\">\n        <div class=\"col-lg-2\">\n          <input type=\"text\" class=\"form-control\" placeholder=\".col-lg-2\">\n        </div>\n        <div class=\"col-lg-3\">\n          <input type=\"text\" class=\"form-control\" placeholder=\".col-lg-3\">\n        </div>\n        <div class=\"col-lg-4\">\n          <input type=\"text\" class=\"form-control\" placeholder=\".col-lg-4\">\n        </div>\n      </div>\n    </form>\n{% highlight html %}\n<div class=\"row\">\n  <div class=\"col-lg-2\">\n    <input type=\"text\" class=\"form-control\" placeholder=\".col-lg-2\">\n  </div>\n  <div class=\"col-lg-3\">\n    <input type=\"text\" class=\"form-control\" placeholder=\".col-lg-3\">\n  </div>\n  <div class=\"col-lg-4\">\n    <input type=\"text\" class=\"form-control\" placeholder=\".col-lg-4\">\n  </div>\n</div>\n{% endhighlight %}\n\n    <h2 id=\"forms-help-text\">Help text</h2>\n    <p>Block level help text for form controls.</p>\n    <form class=\"bs-example\">\n      <input type=\"text\" class=\"form-control\">\n      <span class=\"help-block\">A block of help text that breaks onto a new line and may extend beyond one line.</span>\n    </form>\n{% highlight html %}\n<span class=\"help-block\">A block of help text that breaks onto a new line and may extend beyond one line.</span>\n{% endhighlight %}\n\n  </div>\n\n\n\n  <!-- Buttons\n  ================================================== -->\n  <div class=\"bs-docs-section\">\n    <div class=\"page-header\">\n      <h1 id=\"buttons\">Buttons</h1>\n    </div>\n\n    <h2 id=\"buttons-options\">Options</h2>\n    <p>Use any of the available button classes to quickly create a styled button.</p>\n    <div class=\"bs-example\">\n      <button type=\"button\" class=\"btn btn-default\">Default</button>\n      <button type=\"button\" class=\"btn btn-primary\">Primary</button>\n      <button type=\"button\" class=\"btn btn-success\">Success</button>\n      <button type=\"button\" class=\"btn btn-info\">Info</button>\n      <button type=\"button\" class=\"btn btn-warning\">Warning</button>\n      <button type=\"button\" class=\"btn btn-danger\">Danger</button>\n      <button type=\"button\" class=\"btn btn-link\">Link</button>\n    </div>\n{% highlight html %}\n<!-- Standard gray button with gradient -->\n<button type=\"button\" class=\"btn btn-default\">Default</button>\n\n<!-- Provides extra visual weight and identifies the primary action in a set of buttons -->\n<button type=\"button\" class=\"btn btn-primary\">Primary</button>\n\n<!-- Indicates a successful or positive action -->\n<button type=\"button\" class=\"btn btn-success\">Success</button>\n\n<!-- Contextual button for informational alert messages -->\n<button type=\"button\" class=\"btn btn-info\">Info</button>\n\n<!-- Indicates caution should be taken with this action -->\n<button type=\"button\" class=\"btn btn-warning\">Warning</button>\n\n<!-- Indicates a dangerous or potentially negative action -->\n<button type=\"button\" class=\"btn btn-danger\">Danger</button>\n\n<!-- Deemphasize a button by making it look like a link while maintaining button behavior -->\n<button type=\"button\" class=\"btn btn-link\">Link</button>\n{% endhighlight %}\n\n    <h2 id=\"buttons-sizes\">Sizes</h2>\n    <p>Fancy larger or smaller buttons? Add <code>.btn-lg</code>, <code>.btn-sm</code>, or <code>.btn-xs</code> for additional sizes.</p>\n    <div class=\"bs-example\">\n      <p>\n        <button type=\"button\" class=\"btn btn-primary btn-lg\">Large button</button>\n        <button type=\"button\" class=\"btn btn-default btn-lg\">Large button</button>\n      </p>\n      <p>\n        <button type=\"button\" class=\"btn btn-primary\">Default button</button>\n        <button type=\"button\" class=\"btn btn-default\">Default button</button>\n      </p>\n      <p>\n        <button type=\"button\" class=\"btn btn-primary btn-sm\">Small button</button>\n        <button type=\"button\" class=\"btn btn-default btn-sm\">Small button</button>\n      </p>\n      <p>\n        <button type=\"button\" class=\"btn btn-primary btn-xs\">Extra small button</button>\n        <button type=\"button\" class=\"btn btn-default btn-xs\">Extra small button</button>\n      </p>\n    </div>\n{% highlight html %}\n<p>\n  <button type=\"button\" class=\"btn btn-primary btn-lg\">Large button</button>\n  <button type=\"button\" class=\"btn btn-default btn-lg\">Large button</button>\n</p>\n<p>\n  <button type=\"button\" class=\"btn btn-primary\">Default button</button>\n  <button type=\"button\" class=\"btn btn-default\">Default button</button>\n</p>\n<p>\n  <button type=\"button\" class=\"btn btn-primary btn-sm\">Small button</button>\n  <button type=\"button\" class=\"btn btn-default btn-sm\">Small button</button>\n</p>\n<p>\n  <button type=\"button\" class=\"btn btn-primary btn-xs\">Extra small button</button>\n  <button type=\"button\" class=\"btn btn-default btn-xs\">Extra small button</button>\n</p>\n{% endhighlight %}\n\n    <p>Create block level buttons&mdash;those that span the full width of a parent&mdash; by adding <code>.btn-block</code>.</p>\n    <div class=\"bs-example\">\n      <div class=\"well\" style=\"max-width: 400px; margin: 0 auto 10px;\">\n        <button type=\"button\" class=\"btn btn-primary btn-lg btn-block\">Block level button</button>\n        <button type=\"button\" class=\"btn btn-default btn-lg btn-block\">Block level button</button>\n      </div>\n    </div>\n{% highlight html %}\n<button type=\"button\" class=\"btn btn-primary btn-lg btn-block\">Block level button</button>\n<button type=\"button\" class=\"btn btn-default btn-lg btn-block\">Block level button</button>\n{% endhighlight %}\n\n\n    <h2 id=\"buttons-disabled\">Disabled state</h2>\n    <p>Make buttons look unclickable by fading them back 50%.</p>\n\n    <h3>Button element</h3>\n    <p>Add the <code>disabled</code> attribute to <code>&lt;button&gt;</code> buttons.</p>\n    <p class=\"bs-example\">\n      <button type=\"button\" class=\"btn btn-primary btn-lg\" disabled=\"disabled\">Primary button</button>\n      <button type=\"button\" class=\"btn btn-default btn-lg\" disabled=\"disabled\">Button</button>\n    </p>\n{% highlight html %}\n<button type=\"button\" class=\"btn btn-lg btn-primary\" disabled=\"disabled\">Primary button</button>\n<button type=\"button\" class=\"btn btn-default btn-lg\" disabled=\"disabled\">Button</button>\n{% endhighlight %}\n\n    <div class=\"bs-callout bs-callout-danger\">\n      <h4>Cross-browser compatibility</h4>\n      <p>If you add the <code>disabled</code> attribute to a <code>&lt;button&gt;</code>, Internet Explorer 9 and below will render text gray with a nasty text-shadow that we cannot fix.</p>\n    </div>\n\n    <h3>Anchor element</h3>\n    <p>Add the <code>.disabled</code> class to <code>&lt;a&gt;</code> buttons.</p>\n    <p class=\"bs-example\">\n      <a href=\"#\" class=\"btn btn-primary btn-lg disabled\">Primary link</a>\n      <a href=\"#\" class=\"btn btn-default btn-lg disabled\">Link</a>\n    </p>\n{% highlight html %}\n<a href=\"#\" class=\"btn btn-primary btn-lg disabled\">Primary link</a>\n<a href=\"#\" class=\"btn btn-default btn-lg disabled\">Link</a>\n{% endhighlight %}\n    <p>\n      We use <code>.disabled</code> as a utility class here, similar to the common <code>.active</code> class, so no prefix is required.\n    </p>\n    <div class=\"bs-callout bs-callout-warning\">\n      <h4>Link functionality not impacted</h4>\n      <p>This class will only change the <code>&lt;a&gt;</code>'s appearance, not its functionality. Use custom JavaScript to disable links here.</p>\n    </div>\n\n\n    <h2 id=\"buttons-tags\">Button tags</h2>\n    <p>Use the button classes on an <code>&lt;a&gt;</code>, <code>&lt;button&gt;</code>, or <code>&lt;input&gt;</code> element.</p>\n    <form class=\"bs-example\">\n      <a class=\"btn btn-default\" href=\"#\">Link</a>\n      <button class=\"btn btn-default\" type=\"submit\">Button</button>\n      <input class=\"btn btn-default\" type=\"button\" value=\"Input\">\n      <input class=\"btn btn-default\" type=\"submit\" value=\"Submit\">\n    </form>\n{% highlight html %}\n<a class=\"btn btn-default\" href=\"#\">Link</a>\n<button class=\"btn btn-default\" type=\"submit\">Button</button>\n<input class=\"btn btn-default\" type=\"button\" value=\"Input\">\n<input class=\"btn btn-default\" type=\"submit\" value=\"Submit\">\n{% endhighlight %}\n\n    <div class=\"bs-callout bs-callout-warning\">\n      <h4>Cross-browser rendering</h4>\n      <p>As a best practice, <strong>we highly recommend using the <code>&lt;button&gt;</code> element whenever possible</strong> to ensure matching cross-browser rendering.</p>\n      <p>Among other things, there's <a href=\"https://bugzilla.mozilla.org/show_bug.cgi?id=697451\">a Firefox bug</a> that prevents us from setting the <code>line-height</code> of <code>&lt;input&gt;</code>-based buttons, causing them to not exactly match the height of other buttons on Firefox.</p>\n    </div>\n\n  </div>\n\n\n\n  <!-- Images\n  ================================================== -->\n  <div class=\"bs-docs-section\">\n    <div class=\"page-header\">\n      <h1 id=\"images\">Images</h1>\n    </div>\n\n    <p>Add classes to an <code>&lt;img&gt;</code> element to easily style images in any project.</p>\n    <div class=\"bs-callout bs-callout-danger\">\n      <h4>Cross-browser compatibility</h4>\n      <p>Keep in mind that Internet Explorer 8 lacks support for rounded corners.</p>\n    </div>\n    <div class=\"bs-example bs-example-images\">\n      <img data-src=\"holder.js/140x140\" src=\"data:image/png;base64,\" class=\"img-rounded\" alt=\"A generic square placeholder image with rounded corners\">\n      <img data-src=\"holder.js/140x140\" src=\"data:image/png;base64,\" class=\"img-circle\" alt=\"A generic square placeholder image where only the portion within the circle circumscribed about said square is visible\">\n      <img data-src=\"holder.js/140x140\" src=\"data:image/png;base64,\" class=\"img-thumbnail\" alt=\"A generic square placeholder image with a white border around it, making it resemble a photograph taken with an old instant camera\">\n    </div>\n{% highlight html %}\n<img src=\"...\" alt=\"...\" class=\"img-rounded\">\n<img src=\"...\" alt=\"...\" class=\"img-circle\">\n<img src=\"...\" alt=\"...\" class=\"img-thumbnail\">\n{% endhighlight %}\n\n    <div class=\"bs-callout bs-callout-warning\">\n      <h4>Responsive images</h4>\n      <p>Looking for how to make images more responsive? <a href=\"../css#overview-responsive-images\">Check out the responsive images section</a> up top.</p>\n    </div>\n\n  </div>\n\n\n  <!-- Helpers\n  ================================================== -->\n  <div class=\"bs-docs-section\">\n    <div class=\"page-header\">\n      <h1 id=\"helper-classes\">Helper classes</h1>\n    </div>\n\n    <h3>Close icon</h3>\n    <p>Use the generic close icon for dismissing content like modals and alerts.</p>\n    <div class=\"bs-example\">\n      <p><button type=\"button\" class=\"close\" aria-hidden=\"true\">&times;</button></p>\n    </div>\n{% highlight html %}\n<button type=\"button\" class=\"close\" aria-hidden=\"true\">&times;</button>\n{% endhighlight %}\n\n    <h3>.pull-left</h3>\n    <p>Float an element left with a class. Can also be used as a mixin.</p>\n{% highlight html %}\n<div class=\"pull-left\">...</div>\n{% endhighlight %}\n{% highlight css %}\n.pull-left {\n  float: left !important;\n}\n{% endhighlight %}\n\n    <h3>.pull-right</h3>\n    <p>Float an element right with a class. Can also be used as a mixin.</p>\n{% highlight html %}\n<div class=\"pull-right\">...</div>\n{% endhighlight %}\n{% highlight css %}\n.pull-right {\n  float: right !important;\n}\n{% endhighlight %}\n\n    <h3>.clearfix</h3>\n    <p>Clear the <code>float</code> on any element. Utilizes <a href=\"http://nicolasgallagher.com/micro-clearfix-hack/\">the micro clearfix</a> as popularized by Nicolas Gallagher. Can also be used as a mixin.</p>\n{% highlight html %}\n<div class=\"clearfix\">...</div>\n{% endhighlight %}\n{% highlight css %}\n// Mixin\n.clearfix() {\n  &:before,\n  &:after {\n    content: \" \";\n    display: table;\n  }\n  &:after {\n    clear: both;\n  }\n}\n\n// Usage\n.element {\n  .clearfix();\n}\n{% endhighlight %}\n\n    <h3>.sr-only</h3>\n    <p>Hide an element to all users <em>except</em> screen readers. Necessary for following <a href=\"{{ page.base_url }}getting-started#accessibility\">accessibility best practices</a>.</p>\n{% highlight html %}\n<a class=\"sr-only\" href=\"#content\">Skip to content</a>\n{% endhighlight %}\n  </div>\n\n  <!-- Responsive utilities\n  ================================================== -->\n  <div class=\"bs-docs-section\" id=\"responsive-utilities\">\n    <div class=\"page-header\">\n      <h1>Responsive utilities</h1>\n    </div>\n    <p class=\"lead\">For faster mobile-friendly development, use these utility classes for showing and hiding content by device via media query. Also included are utility classes for toggling content when printed.</p>\n    <p>Try to use these on a limited basis and avoid creating entirely different versions of the same site. Instead, use them to complement each device's presentation. <strong>Responsive utilities are currently only available for block and table toggling.</strong> Use with inline and table elements is currently not supported.</p>\n\n\n    <h2 id=\"responsive-utilities-classes\">Available classes</h2>\n    <p>Use a single or combination of the available classes for toggling content across viewport breakpoints.</p>\n    <div class=\"table-responsive\">\n      <table class=\"table table-bordered table-striped responsive-utilities\">\n        <thead>\n          <tr>\n            <th></th>\n            <th>\n              Extra small devices\n              <small>Phones (&lt;768px)</small>\n            </th>\n            <th>\n              Small devices\n              <small>Tablets (&ge;768px)</small>\n            </th>\n            <th>\n              Medium devices\n              <small>Desktops (&ge;992px)</small>\n            </th>\n            <th>\n              Large devices\n              <small>Desktops (&ge;1200px)</small>\n            </th>\n          </tr>\n        </thead>\n        <tbody>\n          <tr>\n            <th><code>.visible-xs</code></th>\n            <td class=\"is-visible\">Visible</td>\n            <td class=\"is-hidden\">Hidden</td>\n            <td class=\"is-hidden\">Hidden</td>\n            <td class=\"is-hidden\">Hidden</td>\n          </tr>\n          <tr>\n            <th><code>.visible-sm</code></th>\n            <td class=\"is-hidden\">Hidden</td>\n            <td class=\"is-visible\">Visible</td>\n            <td class=\"is-hidden\">Hidden</td>\n            <td class=\"is-hidden\">Hidden</td>\n          </tr>\n          <tr>\n            <th><code>.visible-md</code></th>\n            <td class=\"is-hidden\">Hidden</td>\n            <td class=\"is-hidden\">Hidden</td>\n            <td class=\"is-visible\">Visible</td>\n            <td class=\"is-hidden\">Hidden</td>\n          </tr>\n          <tr>\n            <th><code>.visible-lg</code></th>\n            <td class=\"is-hidden\">Hidden</td>\n            <td class=\"is-hidden\">Hidden</td>\n            <td class=\"is-hidden\">Hidden</td>\n            <td class=\"is-visible\">Visible</td>\n          </tr>\n        </tbody>\n        <tbody>\n          <tr>\n            <th><code>.hidden-xs</code></th>\n            <td class=\"is-hidden\">Hidden</td>\n            <td class=\"is-visible\">Visible</td>\n            <td class=\"is-visible\">Visible</td>\n            <td class=\"is-visible\">Visible</td>\n          </tr>\n          <tr>\n            <th><code>.hidden-sm</code></th>\n            <td class=\"is-visible\">Visible</td>\n            <td class=\"is-hidden\">Hidden</td>\n            <td class=\"is-visible\">Visible</td>\n            <td class=\"is-visible\">Visible</td>\n          </tr>\n          <tr>\n            <th><code>.hidden-md</code></th>\n            <td class=\"is-visible\">Visible</td>\n            <td class=\"is-visible\">Visible</td>\n            <td class=\"is-hidden\">Hidden</td>\n            <td class=\"is-visible\">Visible</td>\n          </tr>\n          <tr>\n            <th><code>.hidden-lg</code></th>\n            <td class=\"is-visible\">Visible</td>\n            <td class=\"is-visible\">Visible</td>\n            <td class=\"is-visible\">Visible</td>\n            <td class=\"is-hidden\">Hidden</td>\n          </tr>\n        </tbody>\n      </table>\n    </div>\n\n\n    <h2 id=\"responsive-utilities-print\">Print classes</h2>\n    <p>Similar to the regular responsive classes, use these for toggling content for print.</p>\n    <div class=\"table-responsive\">\n      <table class=\"table table-bordered table-striped responsive-utilities\">\n        <thead>\n          <tr>\n            <th>Class</th>\n            <th>Browser</th>\n            <th>Print</th>\n          </tr>\n        </thead>\n        <tbody>\n          <tr>\n            <th><code>.visible-print</code></th>\n            <td class=\"is-hidden\">Hidden</td>\n            <td class=\"is-visible\">Visible</td>\n          </tr>\n          <tr>\n            <th><code>.hidden-print</code></th>\n            <td class=\"is-visible\">Visible</td>\n            <td class=\"is-hidden\">Hidden</td>\n          </tr>\n        </tbody>\n      </table>\n    </div>\n\n\n    <h2 id=\"responsive-utilities-tests\">Test cases</h2>\n    <p>Resize your browser or load on different devices to test the responsive utility classes.</p>\n\n    <h3>Visible on...</h3>\n    <p>Green checkmarks indicate the element <strong>is visible</strong> in your current viewport.</p>\n    <div class=\"row responsive-utilities-test visible-on\">\n      <div class=\"col-xs-6 col-sm-3\">\n        <span class=\"hidden-xs\">Extra small</span>\n        <span class=\"visible-xs\">&#10004; Visible on x-small</span>\n      </div>\n      <div class=\"col-xs-6 col-sm-3\">\n        <span class=\"hidden-sm\">Small</span>\n        <span class=\"visible-sm\">&#10004; Visible on small</span>\n      </div>\n      <div class=\"clearfix visible-xs\"></div>\n      <div class=\"col-xs-6 col-sm-3\">\n        <span class=\"hidden-md\">Medium</span>\n        <span class=\"visible-md\">&#10004; Visible on medium</span>\n      </div>\n      <div class=\"col-xs-6 col-sm-3\">\n        <span class=\"hidden-lg\">Large</span>\n        <span class=\"visible-lg\">&#10004; Visible on large</span>\n      </div>\n    </div>\n    <div class=\"row responsive-utilities-test visible-on\">\n      <div class=\"col-xs-6 col-sm-6\">\n        <span class=\"hidden-xs hidden-sm\">Extra small and small</span>\n        <span class=\"visible-xs visible-sm\">&#10004; Visible on x-small and small</span>\n      </div>\n      <div class=\"col-xs-6 col-sm-6\">\n        <span class=\"hidden-md hidden-lg\">Medium and large</span>\n        <span class=\"visible-md visible-lg\">&#10004; Visible on medium and large</span>\n      </div>\n      <div class=\"clearfix visible-xs\"></div>\n      <div class=\"col-xs-6 col-sm-6\">\n        <span class=\"hidden-xs hidden-md\">Extra small and medium</span>\n        <span class=\"visible-xs visible-md\">&#10004; Visible on x-small and medium</span>\n      </div>\n      <div class=\"col-xs-6 col-sm-6\">\n        <span class=\"hidden-sm hidden-lg\">Small and large</span>\n        <span class=\"visible-sm visible-lg\">&#10004; Visible on small and large</span>\n      </div>\n      <div class=\"clearfix visible-xs\"></div>\n      <div class=\"col-xs-6 col-sm-6\">\n        <span class=\"hidden-xs hidden-lg\">Extra small and large</span>\n        <span class=\"visible-xs visible-lg\">&#10004; Visible on x-small and large</span>\n      </div>\n      <div class=\"col-xs-6 col-sm-6\">\n        <span class=\"hidden-sm hidden-md\">Small and medium</span>\n        <span class=\"visible-sm visible-md\">&#10004; Visible on small and medium</span>\n      </div>\n    </div>\n\n    <h3>Hidden on...</h3>\n    <p>Here, green checkmarks indicate the element <strong>is hidden</strong> in your current viewport.</p>\n    <div class=\"row responsive-utilities-test hidden-on\">\n      <div class=\"col-xs-6 col-sm-3\">\n        <span class=\"visible-xs\">Extra small</span>\n        <span class=\"hidden-xs\">&#10004; Hidden on x-small</span>\n      </div>\n      <div class=\"col-xs-6 col-sm-3\">\n        <span class=\"visible-sm\">Small</span>\n        <span class=\"hidden-sm\">&#10004; Hidden on small</span>\n      </div>\n      <div class=\"clearfix visible-xs\"></div>\n      <div class=\"col-xs-6 col-sm-3\">\n        <span class=\"visible-md\">Medium</span>\n        <span class=\"hidden-md\">&#10004; Hidden on medium</span>\n      </div>\n      <div class=\"col-xs-6 col-sm-3\">\n        <span class=\"visible-lg\">Large</span>\n        <span class=\"hidden-lg\">&#10004; Hidden on large</span>\n      </div>\n    </div>\n    <div class=\"row responsive-utilities-test hidden-on\">\n      <div class=\"col-xs-6 col-sm-6\">\n        <span class=\"visible-xs visible-sm\">Extra small and small</span>\n        <span class=\"hidden-xs hidden-sm\">&#10004; Hidden on x-small and small</span>\n      </div>\n      <div class=\"col-xs-6 col-sm-6\">\n        <span class=\"visible-md visible-lg\">Medium and large</span>\n        <span class=\"hidden-md hidden-lg\">&#10004; Hidden on medium and large</span>\n      </div>\n      <div class=\"clearfix visible-xs\"></div>\n      <div class=\"col-xs-6 col-sm-6\">\n        <span class=\"visible-xs visible-md\">Extra small and medium</span>\n        <span class=\"hidden-xs hidden-md\">&#10004; Hidden on x-small and medium</span>\n      </div>\n      <div class=\"col-xs-6 col-sm-6\">\n        <span class=\"visible-sm visible-lg\">Small and large</span>\n        <span class=\"hidden-sm hidden-lg\">&#10004; Hidden on small and large</span>\n      </div>\n      <div class=\"clearfix visible-xs\"></div>\n      <div class=\"col-xs-6 col-sm-6\">\n        <span class=\"visible-xs visible-lg\">Extra small and large</span>\n        <span class=\"hidden-xs hidden-lg\">&#10004; Hidden on x-small and large</span>\n      </div>\n      <div class=\"col-xs-6 col-sm-6\">\n        <span class=\"visible-sm visible-md\">Small and medium</span>\n        <span class=\"hidden-sm hidden-md\">&#10004; Hidden on small and medium</span>\n      </div>\n    </div>\n\n  </div>\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/sass-bootstrap/customize.html",
    "content": "---\nlayout: default\ntitle: Customize and download\nslug: customize\nlead: Customize Bootstrap's components, LESS variables, and jQuery plugins to get your very own version.\nbase_url: \"../\"\n---\n\n<!-- Customizer form -->\n<form class=\"bs-customizer\" role=\"form\">\n  <div class=\"bs-docs-section\" id=\"less-section\">\n    <div class=\"page-header\">\n      <button class=\"btn btn-default toggle\" type=\"button\">Toggle all</button>\n      <h1 id=\"less\">LESS files</h1>\n    </div>\n    <p class=\"lead\">Choose which LESS files to compile into your custom build of Bootstrap. Not sure which files to use? Read through the <a href=\"../css/\">CSS</a> and <a href=\"../components/\">Components</a> pages in the docs</p>\n\n    <div class=\"row\">\n      <div class=\"col-xs-6 col-sm-4\">\n        <h3>Common CSS</h3>\n        <div class=\"checkbox\">\n          <label>\n            <input type=\"checkbox\" checked value=\"print.less\">\n            Print media styles\n          </label>\n        </div>\n        <div class=\"checkbox\">\n          <label>\n            <input type=\"checkbox\" checked value=\"type.less\">\n            Typography\n          </label>\n        </div>\n        <div class=\"checkbox\">\n          <label>\n            <input type=\"checkbox\" checked value=\"code.less\">\n            Code\n          </label>\n        </div>\n        <div class=\"checkbox\">\n          <label>\n            <input type=\"checkbox\" checked value=\"grid.less\">\n            Grid system\n          </label>\n        </div>\n        <div class=\"checkbox\">\n          <label>\n            <input type=\"checkbox\" checked value=\"tables.less\">\n            Tables\n          </label>\n        </div>\n        <div class=\"checkbox\">\n          <label>\n            <input type=\"checkbox\" checked value=\"forms.less\" data-dependents=\"navbar.less,input-groups.less\">\n            Forms\n          </label>\n        </div>\n        <div class=\"checkbox\">\n          <label>\n            <input type=\"checkbox\" checked value=\"buttons.less\">\n            Buttons\n          </label>\n        </div>\n      </div><!-- .col-xs-6 .col-sm-4 -->\n\n      <div class=\"col-xs-6 col-sm-4\">\n        <h3>Components</h3>\n        <div class=\"checkbox\">\n          <label>\n            <input type=\"checkbox\" checked value=\"glyphicons.less\">\n            Glyphicons\n          </label>\n        </div>\n        <div class=\"checkbox\">\n          <label>\n            <input type=\"checkbox\" checked value=\"button-groups.less\" data-dependency=\"buttons.less\">\n            Button groups\n          </label>\n        </div>\n        <div class=\"checkbox\">\n          <label>\n            <input type=\"checkbox\" checked value=\"input-groups.less\" data-dependency=\"forms.less\">\n            Input groups\n          </label>\n        </div>\n        <div class=\"checkbox\">\n          <label>\n            <input type=\"checkbox\" checked value=\"navs.less\" data-dependents=\"navbar.less\">\n            Navs\n          </label>\n        </div>\n        <div class=\"checkbox\">\n          <label>\n            <input type=\"checkbox\" checked value=\"navbar.less\" data-dependencies=\"forms.less,utilities.less,navs.less\">\n            Navbar\n          </label>\n        </div>\n        <div class=\"checkbox\">\n          <label>\n            <input type=\"checkbox\" checked value=\"breadcrumbs.less\">\n            Breadcrumbs\n          </label>\n        </div>\n        <div class=\"checkbox\">\n          <label>\n            <input type=\"checkbox\" checked value=\"pagination.less\">\n            Pagination\n          </label>\n        </div>\n        <div class=\"checkbox\">\n          <label>\n            <input type=\"checkbox\" checked value=\"pager.less\">\n            Pager\n          </label>\n        </div>\n        <div class=\"checkbox\">\n          <label>\n            <input type=\"checkbox\" checked value=\"labels.less\">\n            Labels\n          </label>\n        </div>\n        <div class=\"checkbox\">\n          <label>\n            <input type=\"checkbox\" checked value=\"badges.less\">\n            Badges\n          </label>\n        </div>\n        <div class=\"checkbox\">\n          <label>\n            <input type=\"checkbox\" checked value=\"jumbotron.less\">\n            Jumbotron\n          </label>\n        </div>\n        <div class=\"checkbox\">\n          <label>\n            <input type=\"checkbox\" checked value=\"thumbnails.less\">\n            Thumbnails\n          </label>\n        </div>\n        <div class=\"checkbox\">\n          <label>\n            <input type=\"checkbox\" checked value=\"alerts.less\">\n            Alerts\n          </label>\n        </div>\n        <div class=\"checkbox\">\n          <label>\n            <input type=\"checkbox\" checked value=\"progress-bars.less\">\n            Progress bars\n          </label>\n        </div>\n        <div class=\"checkbox\">\n          <label>\n            <input type=\"checkbox\" checked value=\"media.less\">\n            Media items\n          </label>\n        </div>\n        <div class=\"checkbox\">\n          <label>\n            <input type=\"checkbox\" checked value=\"list-group.less\">\n            List groups\n          </label>\n        </div>\n        <div class=\"checkbox\">\n          <label>\n            <input type=\"checkbox\" checked value=\"panels.less\">\n            Panels\n          </label>\n        </div>\n        <div class=\"checkbox\">\n          <label>\n            <input type=\"checkbox\" checked value=\"wells.less\">\n            Wells\n          </label>\n        </div>\n        <div class=\"checkbox\">\n          <label>\n            <input type=\"checkbox\" checked value=\"close.less\">\n            Close icon\n          </label>\n        </div>\n      </div><!-- .col-xs-6 .col-sm-4 -->\n\n      <div class=\"col-xs-6 col-sm-4\">\n        <h3>JavaScript components</h3>\n        <div class=\"checkbox\">\n          <label>\n            <input type=\"checkbox\" checked value=\"dropdowns.less\">\n            Dropdowns\n          </label>\n        </div>\n        <div class=\"checkbox\">\n          <label>\n            <input type=\"checkbox\" checked value=\"tooltip.less\">\n            Tooltips\n          </label>\n        </div>\n        <div class=\"checkbox\">\n          <label>\n            <input type=\"checkbox\" checked value=\"popovers.less\">\n            Popovers\n          </label>\n        </div>\n        <div class=\"checkbox\">\n          <label>\n            <input type=\"checkbox\" checked value=\"modals.less\">\n            Modals\n          </label>\n        </div>\n        <div class=\"checkbox\">\n          <label>\n            <input type=\"checkbox\" checked value=\"carousel.less\">\n            Carousel\n          </label>\n        </div>\n\n        <h3>Utilities</h3>\n        <div class=\"checkbox\">\n          <label>\n            <input type=\"checkbox\" checked value=\"utilities.less\" data-dependents=\"navbar.less\">\n            Basic utilities\n          </label>\n        </div>\n        <div class=\"checkbox\">\n          <label>\n            <input type=\"checkbox\" checked value=\"responsive-utilities.less\">\n            Responsive utilities\n          </label>\n        </div>\n        <div class=\"checkbox\">\n          <label>\n            <input type=\"checkbox\" checked value=\"component-animations.less\">\n            Component animations (for JS)\n          </label>\n        </div>\n      </div><!-- .col-xs-6 .col-sm-4 -->\n    </div><!-- /.row -->\n  </div>\n\n\n\n  <div class=\"bs-docs-section\" id=\"plugin-section\">\n    <div class=\"page-header\">\n      <button class=\"btn btn-default toggle\" type=\"button\">Toggle all</button>\n      <h1 id=\"plugins\">jQuery plugins</h1>\n    </div>\n    <p class=\"lead\">Choose which jQuery plugins should be included in your custom JavaScript files. Unsure what to include? Read the <a href=\"../javascript/\">JavaScript</a> page in the docs.</p>\n    <div class=\"row\">\n      <div class=\"col-lg-6\">\n        <h4>Linked to components</h4>\n        <div class=\"checkbox\">\n          <label>\n            <input type=\"checkbox\" checked value=\"alert.js\">\n            Alert dismissal\n          </label>\n        </div>\n        <div class=\"checkbox\">\n          <label>\n            <input type=\"checkbox\" checked value=\"button.js\">\n            Advanced buttons\n          </label>\n        </div>\n        <div class=\"checkbox\">\n          <label>\n            <input type=\"checkbox\" checked value=\"carousel.js\">\n            Carousel functionality\n          </label>\n        </div>\n        <div class=\"checkbox\">\n          <label>\n            <input type=\"checkbox\" checked value=\"dropdown.js\">\n            Dropdowns\n          </label>\n        </div>\n        <div class=\"checkbox\">\n          <label>\n            <input type=\"checkbox\" checked value=\"modal.js\">\n            Modals\n          </label>\n        </div>\n        <div class=\"checkbox\">\n          <label>\n            <input type=\"checkbox\" checked value=\"tooltip.js\">\n            Tooltips\n          </label>\n        </div>\n        <div class=\"checkbox\">\n          <label>\n            <input type=\"checkbox\" checked value=\"popover.js\" data-dependency=\"tooltip.js\">\n            Popovers <small>(requires Tooltips)</small>\n          </label>\n        </div>\n        <div class=\"checkbox\">\n          <label>\n            <input type=\"checkbox\" checked value=\"tab.js\">\n            Togglable tabs\n          </label>\n        </div>\n      </div>\n      <div class=\"col-lg-6\">\n        <h4>Magic</h4>\n        <div class=\"checkbox\">\n          <label>\n            <input type=\"checkbox\" checked value=\"affix.js\">\n            Affix\n          </label>\n        </div>\n        <div class=\"checkbox\">\n          <label>\n            <input type=\"checkbox\" checked value=\"collapse.js\">\n            Collapse\n          </label>\n        </div>\n        <div class=\"checkbox\">\n          <label>\n            <input type=\"checkbox\" checked value=\"scrollspy.js\">\n            Scrollspy\n          </label>\n        </div>\n        <div class=\"checkbox\">\n          <label>\n            <input type=\"checkbox\" checked value=\"transition.js\">\n            Transitions <small>(required for any kind of animation)</small>\n          </label>\n        </div>\n      </div>\n    </div>\n\n    <div class=\"bs-callout bs-callout-info\">\n      <h4>Produces two files</h4>\n      <p>All checked plugins will be compiled into a readable <code>bootstrap.js</code> and a minified <code>bootstrap.min.js</code>. We recommend you use the minified version in production.</p>\n    </div>\n\n    <div class=\"bs-callout bs-callout-danger\">\n      <h4>jQuery required</h4>\n      <p>All plugins require the latest version of <a href=\"http://jquery.com/\" target=\"_blank\">jQuery</a> to be included.</p>\n    </div>\n  </div>\n\n\n\n  <div class=\"bs-docs-section\" id=\"less-variables-section\">\n    <div class=\"page-header\">\n      <button class=\"btn btn-default toggle\" type=\"button\">Reset to defaults</button>\n      <h1 id=\"less-variables\">LESS variables</h1>\n    </div>\n    <p class=\"lead\">Customize LESS variables to define colors, sizes and more inside your custom CSS stylesheets.</p>\n\n    <h2 id=\"variables-basics\">Basics</h2>\n\n    <h3>Body background</h3>\n    <div class=\"row\">\n      <div class=\"col-lg-6\">\n        <label>@body-bg</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"#fff\" data-var=\"@body-bg\">\n        <p class=\"help-block\">Background color applied to <code>&lt;body&gt;</code>.</p>\n      </div>\n    </div>\n\n    <h3>Typography</h3>\n    <div class=\"row\">\n      <div class=\"col-lg-6\">\n        <label>@font-family-sans-serif</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"'Helvetica Neue', Helvetica, Arial, sans-serif\" data-var=\"@font-family-sans-serif\">\n        <p class=\"help-block\">Default sans-serif fonts.</p>\n        <label>@font-family-serif</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"Georgia, 'Times New Roman', Times, serif\" data-var=\"@font-family-serif\">\n        <p class=\"help-block\">Default serif fonts.</p>\n        <label>@font-family-monospace</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"Monaco, Menlo, Consolas, 'Courier New', monospace\" data-var=\"@font-family-monospace\">\n        <p class=\"help-block\">Default monospace fonts for <code>&lt;code&gt;</code> and <code>&lt;pre&gt;</code>.</p>\n      </div>\n      <div class=\"col-lg-6\">\n        <label>@font-family-base</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"@font-family-sans-serif\" data-var=\"@font-family-base\">\n        <p class=\"help-block\">Used to globally set font-family in Bootstrap.</p>\n        <label>@font-size-base</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"14px\" data-var=\"@font-size-base\">\n        <p class=\"help-block\">Used to calculate font-size throughout Bootstrap.</p>\n        <label>@line-height-base</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"1.428571429\" data-var=\"@line-height-base\">\n        <p class=\"help-block\">Used to calculate line-height throughout Bootstrap.</p>\n      </div>\n    </div>\n\n    <h3>Code blocks</h3>\n    <div class=\"row\">\n      <div class=\"col-lg-6\">\n        <label>@code-color</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"#c7254e\" data-var=\"@code-color\">\n        <label>@code-bg</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"#f9f2f4\" data-var=\"@code-bg\">\n      </div>\n      <div class=\"col-lg-6\">\n        <label>@pre-color</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"@gray-dark\" data-var=\"@pre-color\">\n        <label>@pre-bg</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"#f5f5f5\" data-var=\"@pre-bg\">\n        <label>@pre-border-color</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"#ccc\" data-var=\"@pre-border-color\">\n      </div>\n    </div>\n\n    <h4>Headings</h4>\n    <div class=\"row\">\n      <div class=\"col-lg-6\">\n        <label>@headings-font-family</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"@font-family-base\" data-var=\"@headings-font-family\">\n        <p class=\"help-block\">Choose a separate font-family for headings.</p>\n        <label>@headings-font-weight</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"500\" data-var=\"@headings-font-weight\">\n        <p class=\"help-block\">Choose a separate font-weight for headings.</p>\n      </div>\n      <div class=\"col-lg-6\">\n        <label>@headings-line-height</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"1.1\" data-var=\"@headings-line-height\">\n        <p class=\"help-block\">Choose a separate line-height for headings.</p>\n      </div>\n    </div>\n\n    <h3>Colors</h3>\n    <div class=\"row\">\n      <div class=\"col-lg-6\">\n        <p>Define custom colors used in several contexts.</p>\n        <label>@brand-primary</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"#428bca\" data-var=\"@brand-primary\">\n        <p class=\"help-block\">Used for primary buttons, panels and more.</p>\n        <label>@brand-success</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"#5cb85c\" data-var=\"@brand-success\">\n        <p class=\"help-block\">Used to indicate success.</p>\n        <label>@brand-warning</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"#f0ad4e\" data-var=\"@brand-warning\">\n        <p class=\"help-block\">Used to indicate a warning.</p>\n        <label>@brand-danger</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"#d9534f\" data-var=\"@brand-danger\">\n        <p class=\"help-block\">Used to indicate danger.</p>\n        <label>@brand-info</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"#5bc0de\" data-var=\"@brand-info\">\n        <p class=\"help-block\">Used to indicate informational content.</p>\n      </div>\n      <div class=\"col-lg-6\">\n        <p>Define your preferred colors for standard text and links.</p>\n        <label>@text-color</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"@gray-dark\" data-var=\"@text-color\">\n        <p class=\"help-block\">Global color set on the body.</p>\n        <label>@link-color</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"@brand-primary\" data-var=\"@link-color\">\n        <p class=\"help-block\">Global link color for text.</p>\n        <label>@link-color-hover</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"darken(@link-color, 15%)\" data-var=\"@link-color-hover\">\n        <p class=\"help-block\">Automatically darken links on hover via color function.</p>\n      </div>\n    </div>\n\n    <h3>Media queries breakpoints</h3>\n    <p>Define the breakpoints at which your layout will change, adapting to different screen sizes.</p>\n    <div class=\"row\">\n      <div class=\"col-xs-6\">\n        <label>@screen-xs</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"480px\" data-var=\"@screen-xs\">\n        <label>@screen-sm</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"768px\" data-var=\"@screen-sm\">\n      </div>\n      <div class=\"col-xs-6\">\n        <label>@screen-md</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"992px\" data-var=\"@screen-md\">\n        <label>@screen-lg</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"1200px\" data-var=\"@screen-lg\">\n      </div>\n    </div>\n\n    <h3>Container sizes</h3>\n    <p>Define the maximum width of <code>.container</code> for different screen sizes.</p>\n    <div class=\"row\">\n      <div class=\"col-xs-6 col-sm-4\">\n        <label>@container-tablet</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"728px\" data-var=\"@container-tablet\">\n        <p class=\"help-block\">For <code>@screen-sm</code> and up.</p>\n      </div>\n      <div class=\"col-xs-6 col-sm-4\">\n        <label>@container-desktop</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"940px\" data-var=\"@container-desktop\">\n        <p class=\"help-block\">For <code>@screen-md</code> and up.</p>\n      </div>\n      <div class=\"clearfix visible-xs\"></div>\n      <div class=\"col-xs-6 col-sm-4\">\n        <label>@container-lg-desktop</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"1170px\" data-var=\"@container-lg-desktop\">\n        <p class=\"help-block\">For <code>@screen-lg</code> and up.</p>\n      </div>\n    </div>\n\n    <h3>Grid system</h3>\n    <p>Define your custom responsive grid.</p>\n    <div class=\"row\">\n<!--\n  Temporarily removed until mixins are restored in v3.1\n      <div class=\"col-xs-6 col-sm-4\">\n        <label>@grid-columns</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"12\" data-var=\"@grid-columns\">\n        <p class=\"help-block\">Number of columns in the grid.</p>\n      </div>\n -->\n      <div class=\"col-xs-6 col-sm-4\">\n        <label>@grid-gutter-width</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"30px\" data-var=\"@grid-gutter-width\">\n        <p class=\"help-block\">Padding between columns.</p>\n      </div>\n      <div class=\"clearfix visible-xs\"></div>\n      <div class=\"col-xs-6 col-sm-4\">\n        <label>@grid-float-breakpoint</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"@screen-sm\" data-var=\"@grid-float-breakpoint\">\n        <p class=\"help-block\">Point at which the navbar stops collapsing.</p>\n      </div>\n    </div>\n\n    <h3>Components</h3>\n    <p>Define common padding and border radius sizes and more.</p>\n    <div class=\"row\">\n      <div class=\"col-lg-6\">\n        <h4>Padding</h4>\n        <label>@padding-base-vertical</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"8px\" data-var=\"@padding-base-vertical\">\n        <label>@padding-base-horizontal</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"12px\" data-var=\"@padding-base-horizontal\">\n        <label>@padding-large-vertical</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"14px\" data-var=\"@padding-large-vertical\">\n        <label>@padding-large-horizontal</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"16px\" data-var=\"@padding-large-horizontal\">\n        <label>@padding-small-vertical</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"5px\" data-var=\"@padding-small-vertical\">\n        <label>@padding-small-horizontal</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"10px\" data-var=\"@padding-small-horizontal\">\n      </div>\n      <div class=\"col-lg-6\">\n        <h4>Border radius sizes</h4>\n        <label>@border-radius-base</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"4px\" data-var=\"@border-radius-base\">\n        <label>@border-radius-large</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"6px\" data-var=\"@border-radius-large\">\n        <label>@border-radius-small</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"3px\" data-var=\"@border-radius-small\">\n        <h4>Active background color</h4>\n        <label>@component-active-bg</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"@brand-primary\" data-var=\"@component-active-bg\">\n        <p class=\"help-block\">Used for active or hovered items in places like navs or dropdowns.</p>\n      </div>\n    </div>\n\n    <h2 id=\"variables-buttons\">Buttons</h2>\n    <p>For each of Bootstrap's buttons, define text, background and border color.</p>\n    <div class=\"row\">\n      <div class=\"col-lg-6\">\n        <h4>Default</h4>\n        <label>@btn-default-color</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"#fff\" data-var=\"@btn-default-color\">\n        <label>@btn-default-bg</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"#474949\" data-var=\"@btn-default-bg\">\n        <label>@btn-default-border</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"@btn-default-bg\" data-var=\"@btn-default-border\">\n        <h4>Primary</h4>\n        <label>@btn-primary-color</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"@btn-default-color\" data-var=\"@btn-primary-color\">\n        <label>@btn-primary-bg</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"@brand-primary\" data-var=\"@btn-primary-bg\">\n        <label>@btn-primary-border</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"@btn-primary-bg\" data-var=\"@btn-primary-border\">\n        <h4>Info</h4>\n        <label>@btn-info-color</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"@btn-default-color\" data-var=\"@btn-info-color\">\n        <label>@btn-info-bg</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"@brand-info\" data-var=\"@btn-info-bg\">\n        <label>@btn-info-border</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"@btn-info-bg\" data-var=\"@btn-info-border\">\n        <h4>Button hover</h4>\n        <label>@btn-hover-color</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"@btn-default-color\" data-var=\"@btn-hover-color\">\n      </div>\n      <div class=\"col-lg-6\">\n        <h4>Success</h4>\n        <label>@btn-success-color</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"@btn-default-color\" data-var=\"@btn-success-color\">\n        <label>@btn-success-bg</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"@brand-success\" data-var=\"@btn-success-bg\">\n        <label>@btn-success-border</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"@btn-success-bg\" data-var=\"@btn-success-border\">\n        <h4>Warning</h4>\n        <label>@btn-warning-color</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"@btn-default-color\" data-var=\"@btn-warning-color\">\n        <label>@btn-warning-bg</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"@brand-warning\" data-var=\"@btn-warning-bg\">\n        <label>@btn-warning-border</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"@btn-warning-bg\" data-var=\"@btn-warning-border\">\n        <h4>Danger</h4>\n        <label>@btn-danger-color</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"@btn-default-color\" data-var=\"@btn-danger-color\">\n        <label>@btn-danger-bg</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"@brand-danger\" data-var=\"@btn-danger-bg\">\n        <label>@btn-danger-border</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"@btn-danger-bg\" data-var=\"@btn-danger-border\">\n      </div>\n    </div>\n\n    <h2 id=\"variables-form-states\">Form states and alerts</h2>\n    <p>Define colors for form feedback states and, by default, alerts.</p>\n    <div class=\"row\">\n      <div class=\"col-lg-6\">\n        <h4>Success</h4>\n        <label>@state-success-text</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"#468847\" data-var=\"@state-success-text\">\n        <label>@state-success-bg</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"#dff0d8\" data-var=\"@state-success-bg\">\n        <label>@state-success-border</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"darken(spin(@state-success-bg, -10), 5%)\" data-var=\"@state-success-border\">\n        <h4>Warning</h4>\n        <label>@state-warning-text</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"#c09853\" data-var=\"@state-warning-text\">\n        <label>@state-warning-bg</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"#fcf8e3\" data-var=\"@state-warning-bg\">\n        <label>@state-warning-border</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"darken(spin(@state-warning-bg, -10), 3%)\" data-var=\"@state-warning-border\">\n      </div>\n      <div class=\"col-lg-6\">\n        <h4>Danger</h4>\n        <label>@state-danger-text</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"#b94a48\" data-var=\"@state-danger-text\">\n        <label>@state-danger-bg</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"#f2dede\" data-var=\"@state-danger-bg\">\n        <label>@state-danger-border</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"darken(spin(@state-danger-bg, -10), 3%)\" data-var=\"@state-danger-border\">\n        <h4>Info</h4>\n        <label>@state-info-text</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"#3a87ad\" data-var=\"@state-info-text\">\n        <label>@state-info-bg</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"#d9edf7\" data-var=\"@state-info-bg\">\n        <label>@state-info-border</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"darken(spin(@state-info-bg, -10), 7%)\" data-var=\"@state-info-border\">\n      </div>\n    </div>\n\n    <h2 id=\"variables-alerts\">Alerts</h2>\n    <p>Define alert colors, border radius, and padding.</p>\n    <h4>Border radius</h4>\n    <label>@alert-padding</label>\n    <input type=\"text\" class=\"form-control\" placeholder=\"15px\" data-var=\"@alert-padding\">\n    <label>@alert-border-radius</label>\n    <input type=\"text\" class=\"form-control\" placeholder=\"@border-radius-base\" data-var=\"@alert-border-radius\">\n    <div class=\"row\">\n      <div class=\"col-lg-6\">\n        <h4>Default (Warning)</h4>\n        <label>@alert-text</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"@state-warning-text\" data-var=\"@alert-text\">\n        <label>@alert-bg</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"@state-warning-bg\" data-var=\"@alert-bg\">\n        <label>@alert-border</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"@state-warning-border\" data-var=\"@alert-border\">\n        <h4>Success</h4>\n        <label>@alert-success-text</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"@state-success-text\" data-var=\"@alert-success-text\">\n        <label>@alert-success-bg</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"@state-success-bg\" data-var=\"@alert-success-bg\">\n        <label>@alert-success-border</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"@state-success-border\" data-var=\"@alert-success-border\">\n      </div>\n      <div class=\"col-lg-6\">\n        <h4>Danger</h4>\n        <label>@alert-danger-text</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"@state-danger-text\" data-var=\"@alert-danger-text\">\n        <label>@alert-danger-bg</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"@state-danger-bg\" data-var=\"@alert-danger-bg\">\n        <label>@alert-danger-border</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"@state-danger-border\" data-var=\"@alert-danger-border\">\n        <h4>Info</h4>\n        <label>@alert-info-text</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"@state-info-text\" data-var=\"@alert-info-text\">\n        <label>@alert-info-bg</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"@state-info-bg\" data-var=\"@alert-info-bg\">\n        <label>@alert-info-border</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"@state-info-border\" data-var=\"@alert-info-border\">\n      </div>\n    </div>\n\n    <h2 id=\"variables-navbar\">Navbar</h2>\n    <div class=\"row\">\n      <div class=\"col-lg-6\">\n        <h3>Default navbar</h3>\n        <h4>Basics</h4>\n        <label>@navbar-height</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"50px\" data-var=\"@navbar-height\">\n        <label>@navbar-margin-bottom</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"@line-height-computed\" data-var=\"@navbar-margin-bottom\">\n        <label>@navbar-default-color</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"#777\" data-var=\"@navbar-default-color\">\n        <label>@navbar-default-bg</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"#eee\" data-var=\"@navbar-default-bg\">\n        <label>@navbar-border-radius</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"@border-radius-base\" data-var=\"@navbar-border-radius\">\n        <h4>Links</h4>\n        <label>@navbar-default-link-color</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"#777\" data-var=\"@navbar-default-link-color\">\n        <label>@navbar-default-link-hover-color</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"#333\" data-var=\"@navbar-default-link-hover-color\">\n        <label>@navbar-default-link-hover-bg</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"transparent\" data-var=\"@navbar-default-link-hover-bg\">\n        <label>@navbar-default-link-active-color</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"#555\" data-var=\"@navbar-default-link-active-color\">\n        <label>@navbar-default-link-active-bg</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"darken(@navbar-bg, 10%)\" data-var=\"@navbar-default-link-active-bg\">\n        <label>@navbar-default-link-disabled-color</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"#ccc\" data-var=\"@navbar-default-link-disabled-color\">\n        <label>@navbar-default-link-disabled-bg</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"transparent\" data-var=\"@navbar-default-link-disabled-bg\">\n        <h4>Brand</h4>\n        <label>@navbar-default-brand-color</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"@navbar-link-color\" data-var=\"@navbar-default-brand-color\">\n        <label>@navbar-default-brand-hover-color</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"darken(@navbar-link-color, 10%)\" data-var=\"@navbar-default-brand-hover-color\">\n        <label>@navbar-default-brand-hover-bg</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"transparent\" data-var=\"@navbar-default-brand-hover-bg\">\n        <h4>Toggle</h4>\n        <label>@navbar-default-toggle-hover-bg</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"#ddd\" data-var=\"@navbar-default-toggle-hover-bg\">\n        <label>@navbar-default-toggle-icon-bar-bg</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"#ccc\" data-var=\"@navbar-default-toggle-icon-bar-bg\">\n        <label>@navbar-default-toggle-border-color</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"#ddd\" data-var=\"@navbar-default-toggle-border-color\">\n      </div>\n      <div class=\"col-lg-6\">\n        <h3>Inverted navbar</h3>\n        <h4>Basics</h4>\n        <label>@navbar-inverse-color</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"@gray-light\" data-var=\"@navbar-inverse-color\">\n        <label>@navbar-inverse-bg</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"#222\" data-var=\"@navbar-inverse-bg\">\n        <h4>Links</h4>\n        <label>@navbar-inverse-link-color</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"@gray-light\" data-var=\"@navbar-inverse-link-color\">\n        <label>@navbar-inverse-link-hover-color</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"#fff\" data-var=\"@navbar-inverse-link-hover-color\">\n        <label>@navbar-inverse-link-hover-bg</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"transparent\" data-var=\"@navbar-inverse-link-hover-bg\">\n        <label>@navbar-inverse-link-active-color</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"@navbar-inverse-link-hover-color\" data-var=\"@navbar-inverse-link-active-color\">\n        <label>@navbar-inverse-link-active-bg</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"darken(@navbar-inverse-bg, 10%)\" data-var=\"@navbar-inverse-link-active-bg\">\n        <label>@navbar-inverse-link-disabled-color</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"#444\" data-var=\"@navbar-inverse-link-disabled-color\">\n        <label>@navbar-inverse-link-disabled-bg</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"transparent\" data-var=\"@navbar-inverse-link-disabled-bg\">\n        <h4>Brand</h4>\n        <label>@navbar-inverse-brand-color</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"@navbar-inverse-link-color\" data-var=\"@navbar-inverse-brand-color\">\n        <label>@navbar-inverse-brand-hover-color</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"#fff\" data-var=\"@navbar-inverse-brand-hover-color\">\n        <label>@navbar-inverse-brand-hover-bg</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"transparent\" data-var=\"@navbar-inverse-brand-hover-bg\">\n        <h4>Toggle</h4>\n        <label>@navbar-inverse-toggle-hover-bg</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"#333\" data-var=\"@navbar-inverse-toggle-hover-bg\">\n        <label>@navbar-inverse-toggle-icon-bar-bg</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"#fff\" data-var=\"@navbar-inverse-toggle-icon-bar-bg\">\n        <label>@navbar-inverse-toggle-border-color</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"#333\" data-var=\"@navbar-inverse-toggle-border-color\">\n      </div>\n    </div>\n\n\n    <h2 id=\"variables-nav\">Nav</h2>\n\n    <h3>Default nav</h3>\n    <div class=\"row\">\n      <div class=\"col-lg-6\">\n        <h4>Common values</h4>\n        <label>@nav-link-padding</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"10px 15px\" data-var=\"@nav-link-padding\">\n        <label>@nav-link-hover-bg</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"@gray-lighter\" data-var=\"@nav-link-hover-bg\">\n        <label>@nav-disabled-link-color</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"@gray-light\" data-var=\"@nav-disabled-link-color\">\n        <label>@nav-disabled-link-hover-color</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"@gray-light\" data-var=\"@nav-disabled-link-hover-color\">\n        <label>@nav-open-link-hover-color</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"#fff\" data-var=\"@nav-open-link-hover-color\">\n        <label>@nav-open-caret-border-color</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"@fff\" data-var=\"@nav-open-caret-border-color\">\n\n        <h4>Pills</h4>\n        <label>@nav-pills-active-link-hover-color</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"@fff\" data-var=\"@nav-pills-active-link-hover-color\">\n        <label>@nav-pills-active-link-hover-bg</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"@component-active-bg\" data-var=\"@nav-pills-active-link-hover-bg\">\n      </div>\n      <div class=\"col-lg-6\">\n        <h4>Tabs</h4>\n        <label>@nav-tabs-border-color</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"@ddd\" data-var=\"@nav-tabs-border-color\">\n        <label>@nav-tabs-link-hover-border-color</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"@gray-lighter\" data-var=\"@nav-tabs-link-hover-border-color\">\n        <label>@nav-tabs-active-link-hover-color</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"@gray\" data-var=\"@nav-tabs-active-link-hover-color\">\n        <label>@nav-tabs-active-link-hover-bg</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"@body-bg\" data-var=\"@nav-tabs-active-link-hover-bg\">\n        <label>@nav-tabs-active-link-hover-border-color</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"#ddd\" data-var=\"@nav-tabs-active-link-hover-border-color\">\n        <label>@nav-tabs-justified-link-border-color</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"#ddd\" data-var=\"@nav-tabs-justified-link-border-color\">\n        <label>@nav-tabs-justified-active-link-border-color</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"@body-bg\" data-var=\"@nav-tabs-justified-active-link-border-color\">\n      </div>\n    </div>\n\n\n    <h2 id=\"variables-tables\">Tables</h2>\n    <div class=\"row\">\n      <div class=\"col-lg-6\">\n        <label>@table-bg</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"transparent\" data-var=\"@table-bg\">\n        <p class=\"help-block\">Default background color used for all tables.</p>\n        <label>@table-bg-accent</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"#f9f9f9\" data-var=\"@table-bg-accent\">\n        <p class=\"help-block\">Background color used for <code>.table-striped</code>.</p>\n      </div>\n      <div class=\"col-lg-6\">\n        <label>@table-bg-hover</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"#f5f5f5\" data-var=\"@table-bg-hover\">\n        <p class=\"help-block\">Background color used for <code>.table-hover</code>.</p>\n        <label>@table-border-color</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"#ddd\" data-var=\"@table-border-color\">\n        <p class=\"help-block\">Border color for table and cell borders.</p>\n      </div>\n    </div>\n\n    <h2 id=\"variables-forms\">Forms</h2>\n    <div class=\"row\">\n      <div class=\"col-lg-6\">\n        <h3>Inputs</h3>\n        <label>@input-color</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"@gray\" data-var=\"@input-color\">\n        <p class=\"help-block\">Text color for <code>&lt;input&gt;</code>s</p>\n        <label>@input-bg</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"#fff\" data-var=\"@input-bg\">\n        <p class=\"help-block\"><code>&lt;input&gt;</code> background color</p>\n        <label>@input-border</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"#ccc\" data-var=\"@input-border\">\n        <p class=\"help-block\"><code>&lt;input&gt;</code> border color</p>\n        <label>@input-border-radius</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"@border-radius-base\" data-var=\"@input-border-radius\">\n        <p class=\"help-block\"><code>&lt;input&gt;</code> border radius</p>\n        <label>@input-bg-disabled</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"@gray-lighter\" data-var=\"@input-bg-disabled\">\n        <p class=\"help-block\"><code>&lt;input disabled&gt;</code> background color</p>\n      </div>\n      <div class=\"col-lg-6\">\n        <h3>Placeholder</h3>\n        <label>@input-color-placeholder</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"@gray-light\" data-var=\"@input-color-placeholder\">\n        <p class=\"help-block\">Placeholder text color</p>\n\n        <h3>Legend</h3>\n        <label>@legend-color</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"@gray\" data-var=\"@legend-color\">\n        <label>@legend-border-color</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"#e5e5e5\" data-var=\"@legend-border-color\">\n\n        <h3>Input groups</h3>\n        <label>@input-group-addon-bg</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"@gray-lighter\" data-var=\"@input-group-addon-bg\">\n        <p class=\"help-block\">Background color for textual input addons</p>\n        <label>@input-group-addon-border-color</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"@input-border\" data-var=\"@input-group-addon-border-color\">\n        <p class=\"help-block\">Border color for textual input addons</p>\n      </div>\n    </div>\n\n    <h2 id=\"variables-dropdowns\">Dropdowns</h2>\n    <div class=\"row\">\n      <div class=\"col-lg-6\">\n        <h3>Dropdown menu</h3>\n        <label>@dropdown-bg</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"#fff\" data-var=\"@dropdown-bg\">\n        <p class=\"help-block\">Dropdown menu background color</p>\n        <label>@dropdown-border</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"rgba(0,0,0,.15)\" data-var=\"@dropdown-border\">\n        <p class=\"help-block\">Dropdown menu border color</p>\n        <label>@dropdown-fallback-border</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"#ccc\" data-var=\"@dropdown-fallback-border\">\n        <p class=\"help-block\">Dropdown menu border color <strong>for IE8</strong></p>\n        <label>@dropdown-caret-color</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"@dropdown-caret-color\" data-var=\"@dropdown-caret-color\">\n        <p class=\"help-block\">Indicator arrow for showing an element has a dropdown</p>\n        <label>@dropdown-divider-bg</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"#e5e5e5\" data-var=\"@dropdown-divider-bg\">\n        <p class=\"help-block\">Dropdown divider top border color</p>\n        <label>@dropdown-header-color</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"@gray-light\" data-var=\"@dropdown-header-color\">\n        <p class=\"help-block\">Text color for headers within dropdown menus</p>\n      </div>\n      <div class=\"col-lg-6\">\n        <h3>Dropdown items</h3>\n        <label>@dropdown-link-color</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"@gray-dark\" data-var=\"@dropdown-link-color\">\n        <p class=\"help-block\">Dropdown text color</p>\n\n        <label>@dropdown-link-hover-color</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"#fff\" data-var=\"@dropdown-link-hover-color\">\n        <p class=\"help-block\">Hovered dropdown menu entry text color</p>\n        <label>@dropdown-link-hover-bg</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"#fff\" data-var=\"@dropdown-link-hover-bg\">\n        <p class=\"help-block\">Hovered dropdown menu entry text color</p>\n\n        <label>@dropdown-link-active-color</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"#fff\" data-var=\"@dropdown-link-active-color\">\n        <p class=\"help-block\">Active dropdown menu entry text color</p>\n        <label>@dropdown-link-active-bg</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"@component-active-bg\" data-var=\"@dropdown-link-active-bg\">\n        <p class=\"help-block\">Active dropdown menu entry background color</p>\n\n        <label>@dropdown-link-disabled-color</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"@dropdown-link-disabled-color\" data-var=\"@dropdown-link-disabled-color\">\n        <p class=\"help-block\">Disabled dropdown menu entry background color</p>\n      </div>\n    </div>\n\n    <h2 id=\"variables-panels-wells\">Panels and wells</h2>\n    <h3>Common panel styles</h3>\n    <div class=\"row\">\n      <div class=\"col-lg-6\">\n        <label>@panel-bg</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"#fff\" data-var=\"@panel-bg\">\n        <label>@panel-inner-border</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"#ddd\" data-var=\"@panel-inner-border\">\n        <p class=\"help-block\">Border color for elements within panels</p>\n      </div>\n      <div class=\"col-lg-6\">\n        <label>@panel-border-radius</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"@border-radius-base\" data-var=\"@panel-border-radius\">\n        <label>@panel-footer-bg</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"#f5f5f5\" data-var=\"@panel-footer-bg\">\n      </div>\n    </div>\n    <h3>Contextual panel colors</h3>\n    <div class=\"row\">\n      <div class=\"col-lg-6\">\n        <h4>Default</h4>\n        <label>@panel-default-text</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"@gray-dark\" data-var=\"@panel-default-text\">\n        <label>@panel-default-border</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"#ddd\" data-var=\"@panel-default-border\">\n        <label>@panel-default-heading-bg</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"#f5f5f5\" data-var=\"@panel-default-heading-bg\">\n        <h4>Primary</h4>\n        <label>@panel-primary-text</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"#fff\" data-var=\"@panel-primary-text\">\n        <label>@panel-primary-border</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"@brand-primary\" data-var=\"@panel-primary-border\">\n        <label>@panel-primary-heading-bg</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"@brand-primary\" data-var=\"@panel-primary-heading-bg\">\n        <h4>Success</h4>\n        <label>@panel-success-text</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"@state-success-text\" data-var=\"@panel-success-text\">\n        <label>@panel-success-border</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"@state-success-border\" data-var=\"@panel-success-border\">\n        <label>@panel-success-heading-bg</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"@state-success-bg\" data-var=\"@panel-success-heading-bg\">\n      </div>\n      <div class=\"col-lg-6\">\n        <h4>Info</h4>\n        <label>@panel-info-text</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"@state-info-text\" data-var=\"@panel-info-text\">\n        <label>@panel-info-border</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"@state-info-border\" data-var=\"@panel-info-border\">\n        <label>@panel-info-heading-bg</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"@state-info-bg\" data-var=\"@panel-info-heading-bg\">\n        <h4>Warning</h4>\n        <label>@panel-warning-text</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"@state-warning-text\" data-var=\"@panel-warning-text\">\n        <label>@panel-warning-border</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"@state-warning-border\" data-var=\"@panel-warning-border\">\n        <label>@panel-warning-heading-bg</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"@state-warning-bg\" data-var=\"@panel-warning-heading-bg\">\n        <h4>Danger</h4>\n        <label>@panel-danger-text</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"@state-danger-text\" data-var=\"@panel-danger-text\">\n        <label>@panel-danger-border</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"@state-danger-border\" data-var=\"@panel-danger-border\">\n        <label>@panel-danger-heading-bg</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"@state-danger-bg\" data-var=\"@panel-danger-heading-bg\">\n      </div>\n    </div>\n\n    <h3>Wells</h3>\n    <label>@well-bg</label>\n    <input type=\"text\" class=\"form-control\" placeholder=\"#f5f5f5\" data-var=\"@well-bg\">\n\n    <h2 id=\"variables-accordion\">Accordion</h2>\n    <label>@accordion-border-bg</label>\n    <input type=\"text\" class=\"form-control\" placeholder=\"#e5e5e5\" data-var=\"@accordion-border-bg\">\n\n    <h2 id=\"variables-badges\">Badges</h2>\n    <div class=\"row\">\n      <div class=\"col-lg-6\">\n        <label>@badge-color</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"#fff\" data-var=\"@badge-color\">\n        <p>Badge text color</p>\n        <label>@badge-bg</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"@gray-light\" data-var=\"@badge-bg\">\n        <p>Badge background color</p>\n        <label>@badge-link-hover-color</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"#fff\" data-var=\"@badge-link-hover-color\">\n        <p>Linked badge text color on hover</p>\n      </div>\n      <div class=\"col-lg-6\">\n        <label>@badge-active-color</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"@link-color\" data-var=\"@badge-active-color\">\n        <p>Badge text color in active nav link</p>\n        <label>@badge-active-bg</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"#fff\" data-var=\"@badge-active-bg\">\n        <p>Badge text color in active nav link</p>\n      </div>\n    </div>\n\n    <h2 id=\"variables-breadcrumbs\">Breadcrumbs</h2>\n    <div class=\"row\">\n      <div class=\"col-lg-4\">\n        <label>@breadcrumb-color</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"#ccc\" data-var=\"@breadcrumb-color\">\n        <p>Breadcrumb text color</p>\n      </div>\n      <div class=\"col-lg-4\">\n        <label>@breadcrumb-bg</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"#f5f5f5\" data-var=\"@breadcrumb-bg\">\n        <p>Breadcrumb background color</p>\n      </div>\n      <div class=\"col-lg-4\">\n        <label>@breadcrumb-active-color</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"@gray-light\" data-var=\"@breadcrumb-active-color\">\n        <p>Text color of current page in the breadcrumb</p>\n      </div>\n    </div>\n\n    <h2 id=\"variables-jumbotron\">Jumbotron</h2>\n    <div class=\"row\">\n      <div class=\"col-lg-3\">\n        <label>@jumbotron-padding</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"30px\" data-var=\"@jumbotron-padding\">\n      </div>\n      <div class=\"col-lg-3\">\n        <label>@jumbotron-bg</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"@gray-lighter\" data-var=\"@jumbotron-bg\">\n      </div>\n      <div class=\"col-lg-3\">\n        <label>@jumbotron-color</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"inherit\" data-var=\"@jumbotron-color\">\n      </div>\n      <div class=\"col-lg-3\">\n        <label>@jumbotron-heading-color</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"inherit\" data-var=\"@jumbotron-heading-color\">\n      </div>\n    </div>\n\n    <h2 id=\"variables-modals\">Modals</h2>\n    <div class=\"row\">\n      <div class=\"col-lg-4\">\n        <label>@modal-inner-padding</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"20px\" data-var=\"@modal-inner-padding\">\n        <p class=\"help-block\">Padding applied to the modal body</p>\n      </div>\n      <div class=\"col-lg-4\">\n        <label>@modal-title-padding</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"15px\" data-var=\"@modal-title-padding\">\n        <p class=\"help-block\">Padding applied to the modal title</p>\n      </div>\n      <div class=\"col-lg-4\">\n        <label>@modal-title-line-height</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"@line-height-base\" data-var=\"@modal-title-line-height\">\n        <p class=\"help-block\">Modal title line-height</p>\n      </div>\n      <div class=\"col-lg-4\">\n        <label>@modal-content-bg</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"#fff\" data-var=\"@modal-content-bg\">\n        <p class=\"help-block\">Background color of modal content area</p>\n      </div>\n      <div class=\"col-lg-4\">\n        <label>@modal-content-border-color</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"rgba(0,0,0,.2)\" data-var=\"@modal-content-border-color\">\n        <p class=\"help-block\">Modal content border color</p>\n      </div>\n      <div class=\"col-lg-4\">\n        <label>@modal-content-fallback-border-color</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"#999\" data-var=\"@modal-content-fallback-border-color\">\n        <p class=\"help-block\">Modal content border color <strong>for IE8</strong></p>\n      </div>\n      <div class=\"col-lg-4\">\n        <label>@modal-backdrop-bg</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"#000\" data-var=\"@modal-backdrop-bg\">\n        <p class=\"help-block\">Modal backdrop background color</p>\n      </div>\n      <div class=\"col-lg-4\">\n        <label>@modal-header-border-color</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"#e5e5e5\" data-var=\"@modal-header-border-color\">\n        <p class=\"help-block\">Modal header border color</p>\n      </div>\n      <div class=\"col-lg-4\">\n        <label>@modal-footer-border-color</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"@modal-header-border-color\" data-var=\"@modal-footer-border-color\">\n        <p class=\"help-block\">Modal footer border color</p>\n      </div>\n    </div>\n\n    <h2 id=\"variables-carousel\">Carousel</h2>\n    <label>@carousel-text-shadow</label>\n    <input type=\"text\" class=\"form-control\" placeholder=\"0 1px 2px rgba(0,0,0,.6)\" data-var=\"@carousel-text-shadow\">\n    <label>@carousel-control-color</label>\n    <input type=\"text\" class=\"form-control\" placeholder=\"#fff\" data-var=\"@carousel-control-color\">\n    <label>@carousel-indicator-border-color</label>\n    <input type=\"text\" class=\"form-control\" placeholder=\"#fff\" data-var=\"@carousel-indicator-border-color\">\n    <label>@carousel-indicator-active-bg</label>\n    <input type=\"text\" class=\"form-control\" placeholder=\"#fff\" data-var=\"@carousel-indicator-active-bg\">\n    <label>@carousel-caption-color</label>\n    <input type=\"text\" class=\"form-control\" placeholder=\"#fff\" data-var=\"@carousel-caption-color\">\n\n    <h2 id=\"variables-list-group\">List group</h2>\n    <h3>Background</h3>\n    <div class=\"row\">\n      <div class=\"col-lg-4\">\n        <label>@list-group-bg</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"#fff\" data-var=\"@list-group-bg\">\n        <p class=\"help-block\">Default background color</p>\n      </div>\n      <div class=\"col-lg-4\">\n        <label>@list-group-hover-bg</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"#f5f5f5\" data-var=\"@list-group-hover-bg\">\n        <p class=\"help-block\">Background color of single list elements on hover</p>\n      </div>\n      <div class=\"col-lg-4\">\n        <label>@list-group-active-bg</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"@component-active-bg\" data-var=\"@list-group-active-bg\">\n        <p class=\"help-block\">Background color of active list elements</p>\n      </div>\n    </div>\n    <h3>Borders</h3>\n    <div class=\"row\">\n      <div class=\"col-lg-4\">\n        <label>@list-group-border</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"#ddd\" data-var=\"@list-group-border\">\n        <p class=\"help-block\">Default border color</p>\n      </div>\n      <div class=\"col-lg-4\">\n        <label>@list-group-border-radius</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"@border-radius-base\" data-var=\"@list-group-border-radius\">\n        <p class=\"help-block\">List group border radius</p>\n      </div>\n      <div class=\"col-lg-4\">\n        <label>@list-group-active-border</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"@list-group-active-bg\" data-var=\"@list-group-active-border\">\n        <p class=\"help-block\">Border color of active list elements</p>\n      </div>\n    </div>\n    <label>@list-group-active-color</label>\n    <input type=\"text\" class=\"form-control\" placeholder=\"#fff\" data-var=\"@list-group-active-color\">\n    <p class=\"help-block\">Text color of active list elements</p>\n    <h2 id=\"variables-thumbnails\">Thumbnails</h2>\n    <div class=\"row\">\n      <div class=\"col-lg-6\">\n        <label>@thumbnail-padding</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"4px\" data-var=\"@thumbnail-padding\">\n        <p class=\"help-block\">Padding around the thumbnail image</p>\n        <label>@thumbnail-bg</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"@body-bg\" data-var=\"@thumbnail-bg\">\n        <p class=\"help-block\">Thumbnail background color</p>\n        <label>@thumbnail-border</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"#ddd\" data-var=\"@thumbnail-border\">\n        <p class=\"help-block\">Thumbnail border color</p>\n        <label>@thumbnail-border-radius</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"@border-radius-base\" data-var=\"@thumbnail-border-radius\">\n        <p class=\"help-block\">Thumbnail border radius</p>\n      </div>\n      <div class=\"col-lg-6\">\n        <label>@thumbnail-caption-padding</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"@text-color\" data-var=\"@thumbnail-caption-padding\">\n        <p class=\"help-block\">Padding around the thumbnail caption</p>\n        <label>@thumbnail-caption-color</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"@text-color\" data-var=\"@thumbnail-caption-color\">\n        <p class=\"help-block\">Custom text color for thumbnail captions</p>\n      </div>\n    </div>\n    <h2 id=\"variables-progress\">Progress bars</h2>\n    <div class=\"row\">\n      <div class=\"col-lg-4\">\n        <label>@progress-bg</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"#f5f5f5\" data-var=\"@progress-bg\">\n        <p class=\"help-block\">Background color of the whole progress component</p>\n      </div>\n      <div class=\"col-lg-4\">\n        <label>@progress-bar-bg</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"@brand-primary\" data-var=\"@progress-bar-bg\">\n        <p class=\"help-block\">Default progress bar color</p>\n      </div>\n      <div class=\"col-lg-4\">\n        <label>@progress-bar-success-bg</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"@brand-success\" data-var=\"@progress-bar-success-bg\">\n        <p class=\"help-block\">Success progress bar color</p>\n      </div>\n    </div>\n    <div class=\"row\">\n      <div class=\"col-lg-4\">\n        <label>@progress-bar-warning-bg</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"@brand-warning\" data-var=\"@progress-bar-warning-bg\">\n        <p class=\"help-block\">Warning progress bar color</p>\n      </div>\n      <div class=\"col-lg-4\">\n        <label>@progress-bar-danger-bg</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"@brand-danger\" data-var=\"@progress-bar-danger-bg\">\n        <p class=\"help-block\">Danger progress bar color</p>\n      </div>\n      <div class=\"col-lg-4\">\n        <label>@progress-bar-info-bg</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"@brand-info\" data-var=\"@progress-bar-info-bg\">\n        <p class=\"help-block\">Info progress bar color</p>\n      </div>\n      <div class=\"col-lg-4\">\n        <label>@progress-bar-color</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"#fff\" data-var=\"@progress-bar-color\">\n        <p class=\"help-block\">Info progress bar text color</p>\n      </div>\n      <div class=\"col-lg-4\">\n        <label>@progress-bar-text-shadow</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"0 -1px 0 rgba(0,0,0,.25)\" data-var=\"@progress-bar-text-shadow\">\n        <p class=\"help-block\">Info progress bar text shadow</p>\n      </div>\n    </div>\n    <h2 id=\"variables-pagination\">Pagination</h2>\n    <div class=\"row\">\n      <div class=\"col-lg-4\">\n        <label>@pagination-bg</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"#fff\" data-var=\"@pagination-bg\">\n        <p class=\"help-block\">Background color</p>\n      </div>\n      <div class=\"col-lg-4\">\n        <label>@pagination-border</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"#ddd\" data-var=\"@pagination-border\">\n        <p class=\"help-block\">Border color</p>\n      </div>\n      <div class=\"col-lg-4\">\n        <label>@pagination-active-bg</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"@brand-primary\" data-var=\"@pagination-active-bg\">\n        <p class=\"help-block\">Active background color</p>\n      </div>\n      <div class=\"col-lg-4\">\n        <label>@pagination-active-color</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"#fff\" data-var=\"@pagination-active-color\">\n        <p class=\"help-block\">Active text color</p>\n      </div>\n      <div class=\"col-lg-4\">\n        <label>@pagination-disabled-color</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"@gray-light\" data-var=\"@pagination-disabled-color\">\n        <p class=\"help-block\">Disabled text color</p>\n      </div>\n    </div>\n    <h2 id=\"variables-pager\">Pager</h2>\n    <div class=\"row\">\n      <div class=\"col-lg-4\">\n        <label>@pager-border-radius</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"15px\" data-var=\"@pager-border-radius\">\n        <p class=\"help-block\">Pager border radius</p>\n      </div>\n      <div class=\"col-lg-4\">\n        <label>@pager-disabled-color</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"@gray-light\" data-var=\"@pager-disabled-color\">\n        <p class=\"help-block\">Pager disabled state color</p>\n      </div>\n    </div>\n\n    <h2 id=\"variables-labels\">Labels</h2>\n    <div class=\"row\">\n      <div class=\"col-lg-6\">\n        <label>@label-default-bg</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"@gray-light\" data-var=\"@label-default-bg\">\n        <p class=\"help-block\">Default label background color</p>\n        <label>@label-primary-bg</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"@brand-primary\" data-var=\"@label-primary-bg\">\n        <p class=\"help-block\">Primary label background color</p>\n        <label>@label-success-bg</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"@brand-success\" data-var=\"@label-success-bg\">\n        <p class=\"help-block\">Success label background color</p>\n      </div>\n      <div class=\"col-lg-6\">\n        <label>@label-info-bg</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"@brand-info\" data-var=\"@label-info-bg\">\n        <p class=\"help-block\">Info label background color</p>\n        <label>@label-warning-bg</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"@brand-warning\" data-var=\"@label-warning-bg\">\n        <p class=\"help-block\">Warning label background color</p>\n        <label>@label-danger-bg</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"@brand-danger\" data-var=\"@label-danger-bg\">\n        <p class=\"help-block\">Danger label background color</p>\n      </div>\n    </div>\n    <h2 id=\"variables-tooltips-popovers\">Tooltips and popovers</h2>\n    <h3>Tooltip styles</h3>\n    <div class=\"row\">\n      <div class=\"col-lg-6\">\n        <label>@tooltip-color</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"#fff\" data-var=\"@tooltip-color\">\n        <p class=\"help-block\">Tooltip text color</p>\n        <label>@tooltip-bg</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"rgba(0,0,0,.9)\" data-var=\"@tooltip-bg\">\n        <p class=\"help-block\">Tooltip background color</p>\n      </div>\n      <div class=\"col-lg-6\">\n        <label>@tooltip-arrow-width</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"5px\" data-var=\"@tooltip-arrow-width\">\n        <p class=\"help-block\">Tooltip arrow width</p>\n        <label>@tooltip-arrow-color</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"@tooltip-bg\" data-var=\"@tooltip-arrow-color\">\n        <p class=\"help-block\">Tooltip arrow color</p>\n      </div>\n      <div class=\"col-lg-6\">\n        <label>@tooltip-max-width</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"200px\" data-var=\"@tooltip-max-width\">\n        <p class=\"help-block\">Tooltip max width</p>\n      </div>\n    </div>\n    <h3>Popover styles</h3>\n    <div class=\"row\">\n      <div class=\"col-lg-6\">\n        <label>@popover-bg</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"#fff\" data-var=\"@popover-bg\">\n        <p class=\"help-block\">Popover body background color</p>\n        <label>@popover-title-bg</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"darken(@popover-bg, 3%)\" data-var=\"@popover-title-bg\">\n        <p class=\"help-block\">Popover title background color</p>\n      </div>\n      <div class=\"col-lg-6\">\n        <label>@popover-arrow-width</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"10px\" data-var=\"@popover-arrow-width\">\n        <p class=\"help-block\">Popover arrow width</p>\n        <label>@popover-arrow-color</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"#fff\" data-var=\"@popover-arrow-color\">\n        <p class=\"help-block\">Popover arrow color</p>\n      </div>\n    </div>\n    <div class=\"row\">\n      <div class=\"col-lg-6\">\n        <label>@popover-arrow-outer-width</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"(@popover-arrow-width 1)\" data-var=\"@popover-arrow-outer-width\">\n        <p class=\"help-block\">Popover outer arrow width</p>\n      </div>\n      <div class=\"col-lg-6\">\n        <label>@popover-arrow-outer-color</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"rgba(0,0,0,.25)\" data-var=\"@popover-arrow-outer-color\">\n        <p class=\"help-block\">Popover outer arrow color</p>\n      </div>\n      <div class=\"col-lg-6\">\n        <label>@popover-arrow-outer-fallback-color</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"#999\" data-var=\"@popover-arrow-outer-fallback-color\">\n        <p class=\"help-block\">Popover outer arrow fallback color</p>\n      </div>\n    </div>\n    <div class=\"row\">\n      <div class=\"col-lg-6\">\n        <label>@popover-max-width</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"276px\" data-var=\"@popover-max-width\">\n        <p class=\"help-block\">Popover maximum width</p>\n      </div>\n      <div class=\"col-lg-6\">\n        <label>@popover-border-color</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"rgba(0,0,0,.2)\" data-var=\"@popover-border-color\">\n        <p class=\"help-block\">Popover border color</p>\n      </div>\n      <div class=\"col-lg-6\">\n        <label>@popover-fallback-border-color</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"#ccc\" data-var=\"@popover-fallback-border-color\">\n        <p class=\"help-block\">Popover fallback border color</p>\n      </div>\n    </div>\n\n    <h2 id=\"variables-close\">Close button</h2>\n    <div class=\"row\">\n      <div class=\"col-lg-6\">\n        <label>@close-color</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"#000\" data-var=\"@close-color\">\n      </div>\n      <div class=\"col-lg-6\">\n      <label>@close-text-shadow</label>\n      <input type=\"text\" class=\"form-control\" placeholder=\"0 1px 0 #fff\" data-var=\"@close-text-shadow\">\n      </div>\n    </div>\n\n    <h2 id=\"variables-type\">Type</h2>\n    <div class=\"row\">\n      <div class=\"col-lg-6\">\n        <label>@text-muted</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"@gray-light\" data-var=\"@text-muted\">\n        <p class=\"help-block\">Text muted color</p>\n      </div>\n      <div class=\"col-lg-6\">\n        <label>@abbr-border-color</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"@gray-light\" data-var=\"@abbr-border-color\">\n        <p class=\"help-block\">Abbreviations and acronyms border color</p>\n      </div>\n      <div class=\"col-lg-6\">\n        <label>@headings-small-color</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"@gray-light\" data-var=\"@headings-small-color\">\n        <p class=\"help-block\">Headings small color</p>\n      </div>\n      <div class=\"col-lg-6\">\n        <label>@blockquote-small-color</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"@gray-light\" data-var=\"@blockquote-small-color\">\n        <p class=\"help-block\">Blockquote small color</p>\n      </div>\n      <div class=\"col-lg-6\">\n        <label>@blockquote-border-color</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"@gray-lighter\" data-var=\"@blockquote-border-color\">\n        <p class=\"help-block\">Blockquote border color</p>\n      </div>\n      <div class=\"col-lg-6\">\n        <label>@page-header-border-color</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"@gray-lighter\" data-var=\"@page-header-border-color\">\n        <p class=\"help-block\">Page header border color</p>\n      </div>\n    </div>\n    <h2 id=\"variables-other\">Other</h2>\n    <div class=\"row\">\n      <div class=\"col-lg-6\">\n        <label>@hr-border</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"@gray-lighter\" data-var=\"@hr-border\">\n        <p class=\"help-block\">Horizontal line color</p>\n      </div>\n      <div class=\"col-lg-6\">\n        <label>@component-offset-horizontal</label>\n        <input type=\"text\" class=\"form-control\" placeholder=\"180px\" data-var=\"@component-offset-horizontal\">\n        <p class=\"help-block\">Horizontal offset for forms and lists</p>\n      </div>\n    </div>\n  </div>\n\n  <div class=\"bs-docs-section\">\n    <div class=\"page-header\">\n      <h1 id=\"download\">Download</h1>\n    </div>\n    <p class=\"lead\">Hooray! Your custom version of Bootstrap is now ready to be compiled. Just click the button below to finish the process.</p>\n    <div class=\"bs-customize-download\">\n      <button id=\"btn-compile\" class=\"btn btn-block btn-lg btn-outline\" onclick=\"_gaq.push(['_trackEvent', 'Customize', 'Download', 'Customize and Download']);\">Compile and Download</button>\n    </div>\n  </div><!-- /download -->\n</form>"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/sass-bootstrap/dist/css/bootstrap-theme.css",
    "content": ".btn-default,\n.btn-primary,\n.btn-success,\n.btn-info,\n.btn-warning,\n.btn-danger {\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.2);\n  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 1px rgba(0, 0, 0, 0.075);\n  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n.btn-default:active, .btn-default.active,\n.btn-primary:active,\n.btn-primary.active,\n.btn-success:active,\n.btn-success.active,\n.btn-info:active,\n.btn-info.active,\n.btn-warning:active,\n.btn-warning.active,\n.btn-danger:active,\n.btn-danger.active {\n  -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);\n  box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);\n}\n\n.btn:active, .btn.active {\n  background-image: none;\n}\n\n.btn-default {\n  background-image: -webkit-gradient(linear, left 0%, left 100%, from(white), to(#e6e6e6));\n  background-image: -webkit-linear-gradient(top, white, 0%, #e6e6e6, 100%);\n  background-image: -moz-linear-gradient(top, white 0%, #e6e6e6 100%);\n  background-image: linear-gradient(to bottom, white 0%, #e6e6e6 100%);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFFFFFFF', endColorstr='#FFE6E6E6', GradientType=0);\n  border-color: #e0e0e0;\n  text-shadow: 0 1px 0 #fff;\n  border-color: #ccc;\n}\n.btn-default:active, .btn-default.active {\n  background-color: #e6e6e6;\n  border-color: #e0e0e0;\n}\n\n.btn-primary {\n  background-image: -webkit-gradient(linear, left 0%, left 100%, from(#428bca), to(#3071a9));\n  background-image: -webkit-linear-gradient(top, #428bca, 0%, #3071a9, 100%);\n  background-image: -moz-linear-gradient(top, #428bca 0%, #3071a9 100%);\n  background-image: linear-gradient(to bottom, #428bca 0%, #3071a9 100%);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#FF428BCA', endColorstr='#FF3071A9', GradientType=0);\n  border-color: #2d6ca2;\n}\n.btn-primary:active, .btn-primary.active {\n  background-color: #3071a9;\n  border-color: #2d6ca2;\n}\n\n.btn-success {\n  background-image: -webkit-gradient(linear, left 0%, left 100%, from(#5cb85c), to(#449d44));\n  background-image: -webkit-linear-gradient(top, #5cb85c, 0%, #449d44, 100%);\n  background-image: -moz-linear-gradient(top, #5cb85c 0%, #449d44 100%);\n  background-image: linear-gradient(to bottom, #5cb85c 0%, #449d44 100%);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#FF5CB85C', endColorstr='#FF449D44', GradientType=0);\n  border-color: #419641;\n}\n.btn-success:active, .btn-success.active {\n  background-color: #449d44;\n  border-color: #419641;\n}\n\n.btn-warning {\n  background-image: -webkit-gradient(linear, left 0%, left 100%, from(#f0ad4e), to(#ec971f));\n  background-image: -webkit-linear-gradient(top, #f0ad4e, 0%, #ec971f, 100%);\n  background-image: -moz-linear-gradient(top, #f0ad4e 0%, #ec971f 100%);\n  background-image: linear-gradient(to bottom, #f0ad4e 0%, #ec971f 100%);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFF0AD4E', endColorstr='#FFEC971F', GradientType=0);\n  border-color: #eb9316;\n}\n.btn-warning:active, .btn-warning.active {\n  background-color: #ec971f;\n  border-color: #eb9316;\n}\n\n.btn-danger {\n  background-image: -webkit-gradient(linear, left 0%, left 100%, from(#d9534f), to(#c9302c));\n  background-image: -webkit-linear-gradient(top, #d9534f, 0%, #c9302c, 100%);\n  background-image: -moz-linear-gradient(top, #d9534f 0%, #c9302c 100%);\n  background-image: linear-gradient(to bottom, #d9534f 0%, #c9302c 100%);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFD9534F', endColorstr='#FFC9302C', GradientType=0);\n  border-color: #c12e2a;\n}\n.btn-danger:active, .btn-danger.active {\n  background-color: #c9302c;\n  border-color: #c12e2a;\n}\n\n.btn-info {\n  background-image: -webkit-gradient(linear, left 0%, left 100%, from(#5bc0de), to(#31b0d5));\n  background-image: -webkit-linear-gradient(top, #5bc0de, 0%, #31b0d5, 100%);\n  background-image: -moz-linear-gradient(top, #5bc0de 0%, #31b0d5 100%);\n  background-image: linear-gradient(to bottom, #5bc0de 0%, #31b0d5 100%);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#FF5BC0DE', endColorstr='#FF31B0D5', GradientType=0);\n  border-color: #2aabd2;\n}\n.btn-info:active, .btn-info.active {\n  background-color: #31b0d5;\n  border-color: #2aabd2;\n}\n\n.thumbnail,\n.img-thumbnail {\n  -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075);\n  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075);\n}\n\n.dropdown-menu > li > a:hover,\n.dropdown-menu > li > a:focus,\n.dropdown-menu > .active > a,\n.dropdown-menu > .active > a:hover,\n.dropdown-menu > .active > a:focus {\n  background-image: -webkit-gradient(linear, left 0%, left 100%, from(#428bca), to(#357ebd));\n  background-image: -webkit-linear-gradient(top, #428bca, 0%, #357ebd, 100%);\n  background-image: -moz-linear-gradient(top, #428bca 0%, #357ebd 100%);\n  background-image: linear-gradient(to bottom, #428bca 0%, #357ebd 100%);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#FF428BCA', endColorstr='#FF357EBD', GradientType=0);\n  background-color: #357ebd;\n}\n\n.navbar {\n  background-image: -webkit-gradient(linear, left 0%, left 100%, from(white), to(#f8f8f8));\n  background-image: -webkit-linear-gradient(top, white, 0%, #f8f8f8, 100%);\n  background-image: -moz-linear-gradient(top, white 0%, #f8f8f8 100%);\n  background-image: linear-gradient(to bottom, white 0%, #f8f8f8 100%);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFFFFFFF', endColorstr='#FFF8F8F8', GradientType=0);\n  border-radius: 4px;\n  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 5px rgba(0, 0, 0, 0.075);\n  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 5px rgba(0, 0, 0, 0.075);\n}\n.navbar .navbar-nav > .active > a {\n  background-color: #f8f8f8;\n}\n\n.navbar-brand,\n.navbar-nav > li > a {\n  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.25);\n}\n\n.navbar-inverse {\n  background-image: -webkit-gradient(linear, left 0%, left 100%, from(#3c3c3c), to(#222222));\n  background-image: -webkit-linear-gradient(top, #3c3c3c, 0%, #222222, 100%);\n  background-image: -moz-linear-gradient(top, #3c3c3c 0%, #222222 100%);\n  background-image: linear-gradient(to bottom, #3c3c3c 0%, #222222 100%);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#FF3C3C3C', endColorstr='#FF222222', GradientType=0);\n}\n.navbar-inverse .navbar-nav > .active > a {\n  background-color: #222222;\n}\n.navbar-inverse .navbar-brand,\n.navbar-inverse .navbar-nav > li > a {\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n}\n\n.navbar-static-top,\n.navbar-fixed-top,\n.navbar-fixed-bottom {\n  border-radius: 0;\n}\n\n.alert {\n  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.2);\n  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25), 0 1px 2px rgba(0, 0, 0, 0.05);\n  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.alert-success {\n  background-image: -webkit-gradient(linear, left 0%, left 100%, from(#dff0d8), to(#c8e5bc));\n  background-image: -webkit-linear-gradient(top, #dff0d8, 0%, #c8e5bc, 100%);\n  background-image: -moz-linear-gradient(top, #dff0d8 0%, #c8e5bc 100%);\n  background-image: linear-gradient(to bottom, #dff0d8 0%, #c8e5bc 100%);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFDFF0D8', endColorstr='#FFC8E5BC', GradientType=0);\n  border-color: #b2dba1;\n}\n\n.alert-info {\n  background-image: -webkit-gradient(linear, left 0%, left 100%, from(#d9edf7), to(#b9def0));\n  background-image: -webkit-linear-gradient(top, #d9edf7, 0%, #b9def0, 100%);\n  background-image: -moz-linear-gradient(top, #d9edf7 0%, #b9def0 100%);\n  background-image: linear-gradient(to bottom, #d9edf7 0%, #b9def0 100%);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFD9EDF7', endColorstr='#FFB9DEF0', GradientType=0);\n  border-color: #9acfea;\n}\n\n.alert-warning {\n  background-image: -webkit-gradient(linear, left 0%, left 100%, from(#fcf8e3), to(#f8efc0));\n  background-image: -webkit-linear-gradient(top, #fcf8e3, 0%, #f8efc0, 100%);\n  background-image: -moz-linear-gradient(top, #fcf8e3 0%, #f8efc0 100%);\n  background-image: linear-gradient(to bottom, #fcf8e3 0%, #f8efc0 100%);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFFCF8E3', endColorstr='#FFF8EFC0', GradientType=0);\n  border-color: #f5e79e;\n}\n\n.alert-danger {\n  background-image: -webkit-gradient(linear, left 0%, left 100%, from(#f2dede), to(#e7c3c3));\n  background-image: -webkit-linear-gradient(top, #f2dede, 0%, #e7c3c3, 100%);\n  background-image: -moz-linear-gradient(top, #f2dede 0%, #e7c3c3 100%);\n  background-image: linear-gradient(to bottom, #f2dede 0%, #e7c3c3 100%);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFF2DEDE', endColorstr='#FFE7C3C3', GradientType=0);\n  border-color: #dca7a7;\n}\n\n.progress {\n  background-image: -webkit-gradient(linear, left 0%, left 100%, from(#ebebeb), to(whitesmoke));\n  background-image: -webkit-linear-gradient(top, #ebebeb, 0%, whitesmoke, 100%);\n  background-image: -moz-linear-gradient(top, #ebebeb 0%, whitesmoke 100%);\n  background-image: linear-gradient(to bottom, #ebebeb 0%, whitesmoke 100%);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFEBEBEB', endColorstr='#FFF5F5F5', GradientType=0);\n}\n\n.progress-bar {\n  background-image: -webkit-gradient(linear, left 0%, left 100%, from(#428bca), to(#3071a9));\n  background-image: -webkit-linear-gradient(top, #428bca, 0%, #3071a9, 100%);\n  background-image: -moz-linear-gradient(top, #428bca 0%, #3071a9 100%);\n  background-image: linear-gradient(to bottom, #428bca 0%, #3071a9 100%);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#FF428BCA', endColorstr='#FF3071A9', GradientType=0);\n}\n\n.progress-bar-success {\n  background-image: -webkit-gradient(linear, left 0%, left 100%, from(#5cb85c), to(#449d44));\n  background-image: -webkit-linear-gradient(top, #5cb85c, 0%, #449d44, 100%);\n  background-image: -moz-linear-gradient(top, #5cb85c 0%, #449d44 100%);\n  background-image: linear-gradient(to bottom, #5cb85c 0%, #449d44 100%);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#FF5CB85C', endColorstr='#FF449D44', GradientType=0);\n}\n\n.progress-bar-info {\n  background-image: -webkit-gradient(linear, left 0%, left 100%, from(#5bc0de), to(#31b0d5));\n  background-image: -webkit-linear-gradient(top, #5bc0de, 0%, #31b0d5, 100%);\n  background-image: -moz-linear-gradient(top, #5bc0de 0%, #31b0d5 100%);\n  background-image: linear-gradient(to bottom, #5bc0de 0%, #31b0d5 100%);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#FF5BC0DE', endColorstr='#FF31B0D5', GradientType=0);\n}\n\n.progress-bar-warning {\n  background-image: -webkit-gradient(linear, left 0%, left 100%, from(#f0ad4e), to(#ec971f));\n  background-image: -webkit-linear-gradient(top, #f0ad4e, 0%, #ec971f, 100%);\n  background-image: -moz-linear-gradient(top, #f0ad4e 0%, #ec971f 100%);\n  background-image: linear-gradient(to bottom, #f0ad4e 0%, #ec971f 100%);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFF0AD4E', endColorstr='#FFEC971F', GradientType=0);\n}\n\n.progress-bar-danger {\n  background-image: -webkit-gradient(linear, left 0%, left 100%, from(#d9534f), to(#c9302c));\n  background-image: -webkit-linear-gradient(top, #d9534f, 0%, #c9302c, 100%);\n  background-image: -moz-linear-gradient(top, #d9534f 0%, #c9302c 100%);\n  background-image: linear-gradient(to bottom, #d9534f 0%, #c9302c 100%);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFD9534F', endColorstr='#FFC9302C', GradientType=0);\n}\n\n.list-group {\n  border-radius: 4px;\n  -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075);\n  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075);\n}\n\n.list-group-item.active,\n.list-group-item.active:hover,\n.list-group-item.active:focus {\n  text-shadow: 0 -1px 0 #3071a9;\n  background-image: -webkit-gradient(linear, left 0%, left 100%, from(#428bca), to(#3278b3));\n  background-image: -webkit-linear-gradient(top, #428bca, 0%, #3278b3, 100%);\n  background-image: -moz-linear-gradient(top, #428bca 0%, #3278b3 100%);\n  background-image: linear-gradient(to bottom, #428bca 0%, #3278b3 100%);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#FF428BCA', endColorstr='#FF3278B3', GradientType=0);\n  border-color: #3278b3;\n}\n\n.panel {\n  -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.panel-default > .panel-heading {\n  background-image: -webkit-gradient(linear, left 0%, left 100%, from(whitesmoke), to(#e8e8e8));\n  background-image: -webkit-linear-gradient(top, whitesmoke, 0%, #e8e8e8, 100%);\n  background-image: -moz-linear-gradient(top, whitesmoke 0%, #e8e8e8 100%);\n  background-image: linear-gradient(to bottom, whitesmoke 0%, #e8e8e8 100%);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFF5F5F5', endColorstr='#FFE8E8E8', GradientType=0);\n}\n\n.panel-primary > .panel-heading {\n  background-image: -webkit-gradient(linear, left 0%, left 100%, from(#428bca), to(#357ebd));\n  background-image: -webkit-linear-gradient(top, #428bca, 0%, #357ebd, 100%);\n  background-image: -moz-linear-gradient(top, #428bca 0%, #357ebd 100%);\n  background-image: linear-gradient(to bottom, #428bca 0%, #357ebd 100%);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#FF428BCA', endColorstr='#FF357EBD', GradientType=0);\n}\n\n.panel-success > .panel-heading {\n  background-image: -webkit-gradient(linear, left 0%, left 100%, from(#dff0d8), to(#d0e9c6));\n  background-image: -webkit-linear-gradient(top, #dff0d8, 0%, #d0e9c6, 100%);\n  background-image: -moz-linear-gradient(top, #dff0d8 0%, #d0e9c6 100%);\n  background-image: linear-gradient(to bottom, #dff0d8 0%, #d0e9c6 100%);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFDFF0D8', endColorstr='#FFD0E9C6', GradientType=0);\n}\n\n.panel-info > .panel-heading {\n  background-image: -webkit-gradient(linear, left 0%, left 100%, from(#d9edf7), to(#c4e3f3));\n  background-image: -webkit-linear-gradient(top, #d9edf7, 0%, #c4e3f3, 100%);\n  background-image: -moz-linear-gradient(top, #d9edf7 0%, #c4e3f3 100%);\n  background-image: linear-gradient(to bottom, #d9edf7 0%, #c4e3f3 100%);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFD9EDF7', endColorstr='#FFC4E3F3', GradientType=0);\n}\n\n.panel-warning > .panel-heading {\n  background-image: -webkit-gradient(linear, left 0%, left 100%, from(#fcf8e3), to(#faf2cc));\n  background-image: -webkit-linear-gradient(top, #fcf8e3, 0%, #faf2cc, 100%);\n  background-image: -moz-linear-gradient(top, #fcf8e3 0%, #faf2cc 100%);\n  background-image: linear-gradient(to bottom, #fcf8e3 0%, #faf2cc 100%);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFFCF8E3', endColorstr='#FFFAF2CC', GradientType=0);\n}\n\n.panel-danger > .panel-heading {\n  background-image: -webkit-gradient(linear, left 0%, left 100%, from(#f2dede), to(#ebcccc));\n  background-image: -webkit-linear-gradient(top, #f2dede, 0%, #ebcccc, 100%);\n  background-image: -moz-linear-gradient(top, #f2dede 0%, #ebcccc 100%);\n  background-image: linear-gradient(to bottom, #f2dede 0%, #ebcccc 100%);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFF2DEDE', endColorstr='#FFEBCCCC', GradientType=0);\n}\n\n.well {\n  background-image: -webkit-gradient(linear, left 0%, left 100%, from(#e8e8e8), to(whitesmoke));\n  background-image: -webkit-linear-gradient(top, #e8e8e8, 0%, whitesmoke, 100%);\n  background-image: -moz-linear-gradient(top, #e8e8e8 0%, whitesmoke 100%);\n  background-image: linear-gradient(to bottom, #e8e8e8 0%, whitesmoke 100%);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFE8E8E8', endColorstr='#FFF5F5F5', GradientType=0);\n  border-color: gainsboro;\n  -webkit-box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.05), 0 1px 0 rgba(255, 255, 255, 0.1);\n  box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.05), 0 1px 0 rgba(255, 255, 255, 0.1);\n}\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/sass-bootstrap/dist/css/bootstrap.css",
    "content": "/*!\n * Bootstrap v3.0.0\n *\n * Copyright 2013 Twitter, Inc\n * Licensed under the Apache License v2.0\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Designed and built with all the love in the world by @mdo and @fat.\n */\n/*! normalize.css v2.1.0 | MIT License | git.io/normalize */\narticle,\naside,\ndetails,\nfigcaption,\nfigure,\nfooter,\nheader,\nhgroup,\nmain,\nnav,\nsection,\nsummary {\n  display: block;\n}\n\naudio,\ncanvas,\nvideo {\n  display: inline-block;\n}\n\naudio:not([controls]) {\n  display: none;\n  height: 0;\n}\n\n[hidden] {\n  display: none;\n}\n\nhtml {\n  font-family: sans-serif;\n  -webkit-text-size-adjust: 100%;\n  -ms-text-size-adjust: 100%;\n}\n\nbody {\n  margin: 0;\n}\n\na:focus {\n  outline: thin dotted;\n}\n\na:active,\na:hover {\n  outline: 0;\n}\n\nh1 {\n  font-size: 2em;\n  margin: 0.67em 0;\n}\n\nabbr[title] {\n  border-bottom: 1px dotted;\n}\n\nb,\nstrong {\n  font-weight: bold;\n}\n\ndfn {\n  font-style: italic;\n}\n\nhr {\n  -moz-box-sizing: content-box;\n  box-sizing: content-box;\n  height: 0;\n}\n\nmark {\n  background: #ff0;\n  color: #000;\n}\n\ncode,\nkbd,\npre,\nsamp {\n  font-family: monospace, serif;\n  font-size: 1em;\n}\n\npre {\n  white-space: pre-wrap;\n}\n\nq {\n  quotes: \"\\201C\" \"\\201D\" \"\\2018\" \"\\2019\";\n}\n\nsmall {\n  font-size: 80%;\n}\n\nsub,\nsup {\n  font-size: 75%;\n  line-height: 0;\n  position: relative;\n  vertical-align: baseline;\n}\n\nsup {\n  top: -0.5em;\n}\n\nsub {\n  bottom: -0.25em;\n}\n\nimg {\n  border: 0;\n}\n\nsvg:not(:root) {\n  overflow: hidden;\n}\n\nfigure {\n  margin: 0;\n}\n\nfieldset {\n  border: 1px solid #c0c0c0;\n  margin: 0 2px;\n  padding: 0.35em 0.625em 0.75em;\n}\n\nlegend {\n  border: 0;\n  padding: 0;\n}\n\nbutton,\ninput,\nselect,\ntextarea {\n  font-family: inherit;\n  font-size: 100%;\n  margin: 0;\n}\n\nbutton,\ninput {\n  line-height: normal;\n}\n\nbutton,\nselect {\n  text-transform: none;\n}\n\nbutton,\nhtml input[type=\"button\"],\ninput[type=\"reset\"],\ninput[type=\"submit\"] {\n  -webkit-appearance: button;\n  cursor: pointer;\n}\n\nbutton[disabled],\nhtml input[disabled] {\n  cursor: default;\n}\n\ninput[type=\"checkbox\"],\ninput[type=\"radio\"] {\n  box-sizing: border-box;\n  padding: 0;\n}\n\ninput[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\ninput[type=\"search\"]::-webkit-search-cancel-button,\ninput[type=\"search\"]::-webkit-search-decoration {\n  -webkit-appearance: none;\n}\n\nbutton::-moz-focus-inner,\ninput::-moz-focus-inner {\n  border: 0;\n  padding: 0;\n}\n\ntextarea {\n  overflow: auto;\n  vertical-align: top;\n}\n\ntable {\n  border-collapse: collapse;\n  border-spacing: 0;\n}\n\n@media print {\n  * {\n    text-shadow: none !important;\n    color: #000 !important;\n    background: transparent !important;\n    box-shadow: none !important;\n  }\n\n  a,\n  a:visited {\n    text-decoration: underline;\n  }\n\n  a[href]:after {\n    content: \" (\" attr(href) \")\";\n  }\n\n  abbr[title]:after {\n    content: \" (\" attr(title) \")\";\n  }\n\n  .ir a:after,\n  a[href^=\"javascript:\"]:after,\n  a[href^=\"#\"]:after {\n    content: \"\";\n  }\n\n  pre,\n  blockquote {\n    border: 1px solid #999;\n    page-break-inside: avoid;\n  }\n\n  thead {\n    display: table-header-group;\n  }\n\n  tr,\n  img {\n    page-break-inside: avoid;\n  }\n\n  img {\n    max-width: 100% !important;\n  }\n\n  @page {\n    margin: 2cm .5cm;\n}\n\n  p,\n  h2,\n  h3 {\n    orphans: 3;\n    widows: 3;\n  }\n\n  h2,\n  h3 {\n    page-break-after: avoid;\n  }\n\n  .navbar {\n    display: none;\n  }\n\n  .table td,\n  .table th {\n    background-color: #fff !important;\n  }\n\n  .btn > .caret,\n  .dropup > .btn > .caret {\n    border-top-color: #000 !important;\n  }\n\n  .label {\n    border: 1px solid #000;\n  }\n\n  .table {\n    border-collapse: collapse !important;\n  }\n\n  .table-bordered th,\n  .table-bordered td {\n    border: 1px solid #ddd !important;\n  }\n}\n*,\n*:before,\n*:after {\n  -webkit-box-sizing: border-box;\n  -moz-box-sizing: border-box;\n  box-sizing: border-box;\n}\n\nhtml {\n  font-size: 62.5%;\n  -webkit-tap-highlight-color: rgba(0, 0, 0, 0);\n}\n\nbody {\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n  font-size: 14px;\n  line-height: 1.428571429;\n  color: #333333;\n  background-color: white;\n}\n\ninput,\nbutton,\nselect,\ntextarea {\n  font-family: inherit;\n  font-size: inherit;\n  line-height: inherit;\n}\n\nbutton,\ninput,\nselect[multiple],\ntextarea {\n  background-image: none;\n}\n\na {\n  color: #428bca;\n  text-decoration: none;\n}\na:hover, a:focus {\n  color: #2a6496;\n  text-decoration: underline;\n}\na:focus {\n  outline: thin dotted #333;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n\nimg {\n  vertical-align: middle;\n}\n\n.img-responsive {\n  display: block;\n  max-width: 100%;\n  height: auto;\n}\n\n.img-rounded {\n  border-radius: 6px;\n}\n\n.img-thumbnail, .thumbnail {\n  padding: 4px;\n  line-height: 1.428571429;\n  background-color: white;\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\n.img-circle {\n  border-radius: 50%;\n}\n\nhr {\n  margin-top: 20px;\n  margin-bottom: 20px;\n  border: 0;\n  border-top: 1px solid #eeeeee;\n}\n\n.sr-only {\n  position: absolute;\n  width: 1px;\n  height: 1px;\n  margin: -1px;\n  padding: 0;\n  overflow: hidden;\n  clip: rect(0 0 0 0);\n  border: 0;\n}\n\np {\n  margin: 0 0 10px;\n}\n\n.lead {\n  margin-bottom: 20px;\n  font-size: 16.099999999999998px;\n  font-weight: 200;\n  line-height: 1.4;\n}\n@media (min-width: 768px) {\n  .lead {\n    font-size: 21px;\n  }\n}\n\nsmall {\n  font-size: 85%;\n}\n\ncite {\n  font-style: normal;\n}\n\n.text-muted {\n  color: #999999;\n}\n\n.text-primary {\n  color: #428bca;\n}\n\n.text-warning {\n  color: #c09853;\n}\n\n.text-danger {\n  color: #b94a48;\n}\n\n.text-success {\n  color: #468847;\n}\n\n.text-info {\n  color: #3a87ad;\n}\n\n.text-left {\n  text-align: left;\n}\n\n.text-right {\n  text-align: right;\n}\n\n.text-center {\n  text-align: center;\n}\n\nh1, h2, h3, h4, h5, h6,\n.h1, .h2, .h3, .h4, .h5, .h6 {\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n  font-weight: 500;\n  line-height: 1.1;\n}\nh1 small, h2 small, h3 small, h4 small, h5 small, h6 small,\n.h1 small, .h2 small, .h3 small, .h4 small, .h5 small, .h6 small {\n  font-weight: normal;\n  line-height: 1;\n  color: #999999;\n}\n\nh1,\nh2,\nh3 {\n  margin-top: 20px;\n  margin-bottom: 10px;\n}\n\nh4,\nh5,\nh6 {\n  margin-top: 10px;\n  margin-bottom: 10px;\n}\n\nh1, .h1 {\n  font-size: 36px;\n}\n\nh2, .h2 {\n  font-size: 30px;\n}\n\nh3, .h3 {\n  font-size: 24px;\n}\n\nh4, .h4 {\n  font-size: 18px;\n}\n\nh5, .h5 {\n  font-size: 14px;\n}\n\nh6, .h6 {\n  font-size: 12px;\n}\n\nh1 small, .h1 small {\n  font-size: 24px;\n}\n\nh2 small, .h2 small {\n  font-size: 18px;\n}\n\nh3 small, .h3 small,\nh4 small, .h4 small {\n  font-size: 14px;\n}\n\n.page-header {\n  padding-bottom: 9px;\n  margin: 40px 0 20px;\n  border-bottom: 1px solid #eeeeee;\n}\n\nul,\nol {\n  margin-top: 0;\n  margin-bottom: 10px;\n}\nul ul,\nul ol,\nol ul,\nol ol {\n  margin-bottom: 0;\n}\n\n.list-unstyled, .list-inline {\n  padding-left: 0;\n  list-style: none;\n}\n\n.list-inline > li {\n  display: inline-block;\n  padding-left: 5px;\n  padding-right: 5px;\n}\n\ndl {\n  margin-bottom: 20px;\n}\n\ndt,\ndd {\n  line-height: 1.428571429;\n}\n\ndt {\n  font-weight: bold;\n}\n\ndd {\n  margin-left: 0;\n}\n\n@media (min-width: 768px) {\n  .dl-horizontal dt {\n    float: left;\n    width: 160px;\n    clear: left;\n    text-align: right;\n    overflow: hidden;\n    text-overflow: ellipsis;\n    white-space: nowrap;\n  }\n  .dl-horizontal dd {\n    margin-left: 180px;\n  }\n  .dl-horizontal dd:before, .dl-horizontal dd:after {\n    content: \" \";\n    /* 1 */\n    display: table;\n    /* 2 */\n  }\n  .dl-horizontal dd:after {\n    clear: both;\n  }\n}\nabbr[title],\nabbr[data-original-title] {\n  cursor: help;\n  border-bottom: 1px dotted #999999;\n}\n\nabbr.initialism {\n  font-size: 90%;\n  text-transform: uppercase;\n}\n\nblockquote {\n  padding: 10px 20px;\n  margin: 0 0 20px;\n  border-left: 5px solid #eeeeee;\n}\nblockquote p {\n  font-size: 17.5px;\n  font-weight: 300;\n  line-height: 1.25;\n}\nblockquote p:last-child {\n  margin-bottom: 0;\n}\nblockquote small {\n  display: block;\n  line-height: 1.428571429;\n  color: #999999;\n}\nblockquote small:before {\n  content: '\\2014 \\00A0';\n}\nblockquote.pull-right {\n  padding-right: 15px;\n  padding-left: 0;\n  border-right: 5px solid #eeeeee;\n  border-left: 0;\n}\nblockquote.pull-right p,\nblockquote.pull-right small {\n  text-align: right;\n}\nblockquote.pull-right small:before {\n  content: '';\n}\nblockquote.pull-right small:after {\n  content: '\\00A0 \\2014';\n}\n\nq:before,\nq:after,\nblockquote:before,\nblockquote:after {\n  content: \"\";\n}\n\naddress {\n  display: block;\n  margin-bottom: 20px;\n  font-style: normal;\n  line-height: 1.428571429;\n}\n\ncode,\npre {\n  font-family: Monaco, Menlo, Consolas, \"Courier New\", monospace;\n}\n\ncode {\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\npre {\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: whitesmoke;\n  border: 1px solid #cccccc;\n  border-radius: 4px;\n}\npre.prettyprint {\n  margin-bottom: 20px;\n}\npre code {\n  padding: 0;\n  font-size: inherit;\n  color: inherit;\n  white-space: pre-wrap;\n  background-color: transparent;\n  border: 0;\n}\n\n.pre-scrollable {\n  max-height: 340px;\n  overflow-y: scroll;\n}\n\n.container {\n  margin-right: auto;\n  margin-left: auto;\n  padding-left: 15px;\n  padding-right: 15px;\n}\n.container:before, .container:after {\n  content: \" \";\n  /* 1 */\n  display: table;\n  /* 2 */\n}\n.container:after {\n  clear: both;\n}\n\n.row {\n  margin-left: -15px;\n  margin-right: -15px;\n}\n.row:before, .row:after {\n  content: \" \";\n  /* 1 */\n  display: table;\n  /* 2 */\n}\n.row:after {\n  clear: both;\n}\n\n.col-xs-1,\n.col-xs-2,\n.col-xs-3,\n.col-xs-4,\n.col-xs-5,\n.col-xs-6,\n.col-xs-7,\n.col-xs-8,\n.col-xs-9,\n.col-xs-10,\n.col-xs-11,\n.col-xs-12,\n.col-sm-1,\n.col-sm-2,\n.col-sm-3,\n.col-sm-4,\n.col-sm-5,\n.col-sm-6,\n.col-sm-7,\n.col-sm-8,\n.col-sm-9,\n.col-sm-10,\n.col-sm-11,\n.col-sm-12,\n.col-md-1,\n.col-md-2,\n.col-md-3,\n.col-md-4,\n.col-md-5,\n.col-md-6,\n.col-md-7,\n.col-md-8,\n.col-md-9,\n.col-md-10,\n.col-md-11,\n.col-md-12,\n.col-lg-1,\n.col-lg-2,\n.col-lg-3,\n.col-lg-4,\n.col-lg-5,\n.col-lg-6,\n.col-lg-7,\n.col-lg-8,\n.col-lg-9,\n.col-lg-10,\n.col-lg-11,\n.col-lg-12 {\n  position: relative;\n  min-height: 1px;\n  padding-left: 15px;\n  padding-right: 15px;\n}\n\n.col-xs-1,\n.col-xs-2,\n.col-xs-3,\n.col-xs-4,\n.col-xs-5,\n.col-xs-6,\n.col-xs-7,\n.col-xs-8,\n.col-xs-9,\n.col-xs-10,\n.col-xs-11 {\n  float: left;\n}\n\n.col-xs-1 {\n  width: 8.333333333333332%;\n}\n\n.col-xs-2 {\n  width: 16.666666666666664%;\n}\n\n.col-xs-3 {\n  width: 25%;\n}\n\n.col-xs-4 {\n  width: 33.33333333333333%;\n}\n\n.col-xs-5 {\n  width: 41.66666666666667%;\n}\n\n.col-xs-6 {\n  width: 50%;\n}\n\n.col-xs-7 {\n  width: 58.333333333333336%;\n}\n\n.col-xs-8 {\n  width: 66.66666666666666%;\n}\n\n.col-xs-9 {\n  width: 75%;\n}\n\n.col-xs-10 {\n  width: 83.33333333333334%;\n}\n\n.col-xs-11 {\n  width: 91.66666666666666%;\n}\n\n.col-xs-12 {\n  width: 100%;\n}\n\n@media (min-width: 768px) {\n  .container {\n    max-width: 750px;\n  }\n\n  .col-sm-1,\n  .col-sm-2,\n  .col-sm-3,\n  .col-sm-4,\n  .col-sm-5,\n  .col-sm-6,\n  .col-sm-7,\n  .col-sm-8,\n  .col-sm-9,\n  .col-sm-10,\n  .col-sm-11 {\n    float: left;\n  }\n\n  .col-sm-1 {\n    width: 8.333333333333332%;\n  }\n\n  .col-sm-2 {\n    width: 16.666666666666664%;\n  }\n\n  .col-sm-3 {\n    width: 25%;\n  }\n\n  .col-sm-4 {\n    width: 33.33333333333333%;\n  }\n\n  .col-sm-5 {\n    width: 41.66666666666667%;\n  }\n\n  .col-sm-6 {\n    width: 50%;\n  }\n\n  .col-sm-7 {\n    width: 58.333333333333336%;\n  }\n\n  .col-sm-8 {\n    width: 66.66666666666666%;\n  }\n\n  .col-sm-9 {\n    width: 75%;\n  }\n\n  .col-sm-10 {\n    width: 83.33333333333334%;\n  }\n\n  .col-sm-11 {\n    width: 91.66666666666666%;\n  }\n\n  .col-sm-12 {\n    width: 100%;\n  }\n\n  .col-sm-push-1 {\n    left: 8.333333333333332%;\n  }\n\n  .col-sm-push-2 {\n    left: 16.666666666666664%;\n  }\n\n  .col-sm-push-3 {\n    left: 25%;\n  }\n\n  .col-sm-push-4 {\n    left: 33.33333333333333%;\n  }\n\n  .col-sm-push-5 {\n    left: 41.66666666666667%;\n  }\n\n  .col-sm-push-6 {\n    left: 50%;\n  }\n\n  .col-sm-push-7 {\n    left: 58.333333333333336%;\n  }\n\n  .col-sm-push-8 {\n    left: 66.66666666666666%;\n  }\n\n  .col-sm-push-9 {\n    left: 75%;\n  }\n\n  .col-sm-push-10 {\n    left: 83.33333333333334%;\n  }\n\n  .col-sm-push-11 {\n    left: 91.66666666666666%;\n  }\n\n  .col-sm-pull-1 {\n    right: 8.333333333333332%;\n  }\n\n  .col-sm-pull-2 {\n    right: 16.666666666666664%;\n  }\n\n  .col-sm-pull-3 {\n    right: 25%;\n  }\n\n  .col-sm-pull-4 {\n    right: 33.33333333333333%;\n  }\n\n  .col-sm-pull-5 {\n    right: 41.66666666666667%;\n  }\n\n  .col-sm-pull-6 {\n    right: 50%;\n  }\n\n  .col-sm-pull-7 {\n    right: 58.333333333333336%;\n  }\n\n  .col-sm-pull-8 {\n    right: 66.66666666666666%;\n  }\n\n  .col-sm-pull-9 {\n    right: 75%;\n  }\n\n  .col-sm-pull-10 {\n    right: 83.33333333333334%;\n  }\n\n  .col-sm-pull-11 {\n    right: 91.66666666666666%;\n  }\n\n  .col-sm-offset-1 {\n    margin-left: 8.333333333333332%;\n  }\n\n  .col-sm-offset-2 {\n    margin-left: 16.666666666666664%;\n  }\n\n  .col-sm-offset-3 {\n    margin-left: 25%;\n  }\n\n  .col-sm-offset-4 {\n    margin-left: 33.33333333333333%;\n  }\n\n  .col-sm-offset-5 {\n    margin-left: 41.66666666666667%;\n  }\n\n  .col-sm-offset-6 {\n    margin-left: 50%;\n  }\n\n  .col-sm-offset-7 {\n    margin-left: 58.333333333333336%;\n  }\n\n  .col-sm-offset-8 {\n    margin-left: 66.66666666666666%;\n  }\n\n  .col-sm-offset-9 {\n    margin-left: 75%;\n  }\n\n  .col-sm-offset-10 {\n    margin-left: 83.33333333333334%;\n  }\n\n  .col-sm-offset-11 {\n    margin-left: 91.66666666666666%;\n  }\n}\n@media (min-width: 992px) {\n  .container {\n    max-width: 970px;\n  }\n\n  .col-md-1,\n  .col-md-2,\n  .col-md-3,\n  .col-md-4,\n  .col-md-5,\n  .col-md-6,\n  .col-md-7,\n  .col-md-8,\n  .col-md-9,\n  .col-md-10,\n  .col-md-11 {\n    float: left;\n  }\n\n  .col-md-1 {\n    width: 8.333333333333332%;\n  }\n\n  .col-md-2 {\n    width: 16.666666666666664%;\n  }\n\n  .col-md-3 {\n    width: 25%;\n  }\n\n  .col-md-4 {\n    width: 33.33333333333333%;\n  }\n\n  .col-md-5 {\n    width: 41.66666666666667%;\n  }\n\n  .col-md-6 {\n    width: 50%;\n  }\n\n  .col-md-7 {\n    width: 58.333333333333336%;\n  }\n\n  .col-md-8 {\n    width: 66.66666666666666%;\n  }\n\n  .col-md-9 {\n    width: 75%;\n  }\n\n  .col-md-10 {\n    width: 83.33333333333334%;\n  }\n\n  .col-md-11 {\n    width: 91.66666666666666%;\n  }\n\n  .col-md-12 {\n    width: 100%;\n  }\n\n  .col-md-push-0 {\n    left: auto;\n  }\n\n  .col-md-push-1 {\n    left: 8.333333333333332%;\n  }\n\n  .col-md-push-2 {\n    left: 16.666666666666664%;\n  }\n\n  .col-md-push-3 {\n    left: 25%;\n  }\n\n  .col-md-push-4 {\n    left: 33.33333333333333%;\n  }\n\n  .col-md-push-5 {\n    left: 41.66666666666667%;\n  }\n\n  .col-md-push-6 {\n    left: 50%;\n  }\n\n  .col-md-push-7 {\n    left: 58.333333333333336%;\n  }\n\n  .col-md-push-8 {\n    left: 66.66666666666666%;\n  }\n\n  .col-md-push-9 {\n    left: 75%;\n  }\n\n  .col-md-push-10 {\n    left: 83.33333333333334%;\n  }\n\n  .col-md-push-11 {\n    left: 91.66666666666666%;\n  }\n\n  .col-md-pull-0 {\n    right: auto;\n  }\n\n  .col-md-pull-1 {\n    right: 8.333333333333332%;\n  }\n\n  .col-md-pull-2 {\n    right: 16.666666666666664%;\n  }\n\n  .col-md-pull-3 {\n    right: 25%;\n  }\n\n  .col-md-pull-4 {\n    right: 33.33333333333333%;\n  }\n\n  .col-md-pull-5 {\n    right: 41.66666666666667%;\n  }\n\n  .col-md-pull-6 {\n    right: 50%;\n  }\n\n  .col-md-pull-7 {\n    right: 58.333333333333336%;\n  }\n\n  .col-md-pull-8 {\n    right: 66.66666666666666%;\n  }\n\n  .col-md-pull-9 {\n    right: 75%;\n  }\n\n  .col-md-pull-10 {\n    right: 83.33333333333334%;\n  }\n\n  .col-md-pull-11 {\n    right: 91.66666666666666%;\n  }\n\n  .col-md-offset-0 {\n    margin-left: 0;\n  }\n\n  .col-md-offset-1 {\n    margin-left: 8.333333333333332%;\n  }\n\n  .col-md-offset-2 {\n    margin-left: 16.666666666666664%;\n  }\n\n  .col-md-offset-3 {\n    margin-left: 25%;\n  }\n\n  .col-md-offset-4 {\n    margin-left: 33.33333333333333%;\n  }\n\n  .col-md-offset-5 {\n    margin-left: 41.66666666666667%;\n  }\n\n  .col-md-offset-6 {\n    margin-left: 50%;\n  }\n\n  .col-md-offset-7 {\n    margin-left: 58.333333333333336%;\n  }\n\n  .col-md-offset-8 {\n    margin-left: 66.66666666666666%;\n  }\n\n  .col-md-offset-9 {\n    margin-left: 75%;\n  }\n\n  .col-md-offset-10 {\n    margin-left: 83.33333333333334%;\n  }\n\n  .col-md-offset-11 {\n    margin-left: 91.66666666666666%;\n  }\n}\n@media (min-width: 1200px) {\n  .container {\n    max-width: 1170px;\n  }\n\n  .col-lg-1,\n  .col-lg-2,\n  .col-lg-3,\n  .col-lg-4,\n  .col-lg-5,\n  .col-lg-6,\n  .col-lg-7,\n  .col-lg-8,\n  .col-lg-9,\n  .col-lg-10,\n  .col-lg-11 {\n    float: left;\n  }\n\n  .col-lg-1 {\n    width: 8.333333333333332%;\n  }\n\n  .col-lg-2 {\n    width: 16.666666666666664%;\n  }\n\n  .col-lg-3 {\n    width: 25%;\n  }\n\n  .col-lg-4 {\n    width: 33.33333333333333%;\n  }\n\n  .col-lg-5 {\n    width: 41.66666666666667%;\n  }\n\n  .col-lg-6 {\n    width: 50%;\n  }\n\n  .col-lg-7 {\n    width: 58.333333333333336%;\n  }\n\n  .col-lg-8 {\n    width: 66.66666666666666%;\n  }\n\n  .col-lg-9 {\n    width: 75%;\n  }\n\n  .col-lg-10 {\n    width: 83.33333333333334%;\n  }\n\n  .col-lg-11 {\n    width: 91.66666666666666%;\n  }\n\n  .col-lg-12 {\n    width: 100%;\n  }\n\n  .col-lg-push-0 {\n    left: auto;\n  }\n\n  .col-lg-push-1 {\n    left: 8.333333333333332%;\n  }\n\n  .col-lg-push-2 {\n    left: 16.666666666666664%;\n  }\n\n  .col-lg-push-3 {\n    left: 25%;\n  }\n\n  .col-lg-push-4 {\n    left: 33.33333333333333%;\n  }\n\n  .col-lg-push-5 {\n    left: 41.66666666666667%;\n  }\n\n  .col-lg-push-6 {\n    left: 50%;\n  }\n\n  .col-lg-push-7 {\n    left: 58.333333333333336%;\n  }\n\n  .col-lg-push-8 {\n    left: 66.66666666666666%;\n  }\n\n  .col-lg-push-9 {\n    left: 75%;\n  }\n\n  .col-lg-push-10 {\n    left: 83.33333333333334%;\n  }\n\n  .col-lg-push-11 {\n    left: 91.66666666666666%;\n  }\n\n  .col-lg-pull-0 {\n    right: auto;\n  }\n\n  .col-lg-pull-1 {\n    right: 8.333333333333332%;\n  }\n\n  .col-lg-pull-2 {\n    right: 16.666666666666664%;\n  }\n\n  .col-lg-pull-3 {\n    right: 25%;\n  }\n\n  .col-lg-pull-4 {\n    right: 33.33333333333333%;\n  }\n\n  .col-lg-pull-5 {\n    right: 41.66666666666667%;\n  }\n\n  .col-lg-pull-6 {\n    right: 50%;\n  }\n\n  .col-lg-pull-7 {\n    right: 58.333333333333336%;\n  }\n\n  .col-lg-pull-8 {\n    right: 66.66666666666666%;\n  }\n\n  .col-lg-pull-9 {\n    right: 75%;\n  }\n\n  .col-lg-pull-10 {\n    right: 83.33333333333334%;\n  }\n\n  .col-lg-pull-11 {\n    right: 91.66666666666666%;\n  }\n\n  .col-lg-offset-0 {\n    margin-left: 0;\n  }\n\n  .col-lg-offset-1 {\n    margin-left: 8.333333333333332%;\n  }\n\n  .col-lg-offset-2 {\n    margin-left: 16.666666666666664%;\n  }\n\n  .col-lg-offset-3 {\n    margin-left: 25%;\n  }\n\n  .col-lg-offset-4 {\n    margin-left: 33.33333333333333%;\n  }\n\n  .col-lg-offset-5 {\n    margin-left: 41.66666666666667%;\n  }\n\n  .col-lg-offset-6 {\n    margin-left: 50%;\n  }\n\n  .col-lg-offset-7 {\n    margin-left: 58.333333333333336%;\n  }\n\n  .col-lg-offset-8 {\n    margin-left: 66.66666666666666%;\n  }\n\n  .col-lg-offset-9 {\n    margin-left: 75%;\n  }\n\n  .col-lg-offset-10 {\n    margin-left: 83.33333333333334%;\n  }\n\n  .col-lg-offset-11 {\n    margin-left: 91.66666666666666%;\n  }\n}\ntable {\n  max-width: 100%;\n  background-color: transparent;\n}\n\nth {\n  text-align: left;\n}\n\n.table {\n  width: 100%;\n  margin-bottom: 20px;\n}\n.table thead > tr > th,\n.table thead > tr > td,\n.table tbody > tr > th,\n.table tbody > tr > td,\n.table tfoot > tr > th,\n.table tfoot > tr > td {\n  padding: 8px;\n  line-height: 1.428571429;\n  vertical-align: top;\n  border-top: 1px solid #dddddd;\n}\n.table thead > tr > th {\n  vertical-align: bottom;\n  border-bottom: 2px solid #dddddd;\n}\n.table caption + thead tr:first-child th, .table caption + thead tr:first-child td,\n.table colgroup + thead tr:first-child th,\n.table colgroup + thead tr:first-child td,\n.table thead:first-child tr:first-child th,\n.table thead:first-child tr:first-child td {\n  border-top: 0;\n}\n.table tbody + tbody {\n  border-top: 2px solid #dddddd;\n}\n.table .table {\n  background-color: white;\n}\n\n.table-condensed thead > tr > th,\n.table-condensed thead > tr > td,\n.table-condensed tbody > tr > th,\n.table-condensed tbody > tr > td,\n.table-condensed tfoot > tr > th,\n.table-condensed tfoot > tr > td {\n  padding: 5px;\n}\n\n.table-bordered {\n  border: 1px solid #dddddd;\n}\n.table-bordered > thead > tr > th,\n.table-bordered > thead > tr > td,\n.table-bordered > tbody > tr > th,\n.table-bordered > tbody > tr > td,\n.table-bordered > tfoot > tr > th,\n.table-bordered > tfoot > tr > td {\n  border: 1px solid #dddddd;\n}\n.table-bordered > thead > tr > th,\n.table-bordered > thead > tr > td {\n  border-bottom-width: 2px;\n}\n\n.table-striped > tbody > tr:nth-child(odd) > td,\n.table-striped > tbody > tr:nth-child(odd) > th {\n  background-color: #f9f9f9;\n}\n\n.table-hover > tbody > tr:hover > td,\n.table-hover > tbody > tr:hover > th {\n  background-color: whitesmoke;\n}\n\ntable col[class*=\"col-\"] {\n  float: none;\n  display: table-column;\n}\n\ntable td[class*=\"col-\"],\ntable th[class*=\"col-\"] {\n  float: none;\n  display: table-cell;\n}\n\n.table > thead > tr > td.active,\n.table > thead > tr > th.active, .table > thead > tr.active > td, .table > thead > tr.active > th,\n.table > tbody > tr > td.active,\n.table > tbody > tr > th.active,\n.table > tbody > tr.active > td,\n.table > tbody > tr.active > th,\n.table > tfoot > tr > td.active,\n.table > tfoot > tr > th.active,\n.table > tfoot > tr.active > td,\n.table > tfoot > tr.active > th {\n  background-color: whitesmoke;\n}\n\n.table > thead > tr > td.success,\n.table > thead > tr > th.success, .table > thead > tr.success > td, .table > thead > tr.success > th,\n.table > tbody > tr > td.success,\n.table > tbody > tr > th.success,\n.table > tbody > tr.success > td,\n.table > tbody > tr.success > th,\n.table > tfoot > tr > td.success,\n.table > tfoot > tr > th.success,\n.table > tfoot > tr.success > td,\n.table > tfoot > tr.success > th {\n  background-color: #dff0d8;\n  border-color: #d6e9c6;\n}\n\n.table-hover > tbody > tr > td.success:hover,\n.table-hover > tbody > tr > th.success:hover, .table-hover > tbody > tr.success:hover > td {\n  background-color: #d0e9c6;\n  border-color: #c9e2b3;\n}\n\n.table > thead > tr > td.danger,\n.table > thead > tr > th.danger, .table > thead > tr.danger > td, .table > thead > tr.danger > th,\n.table > tbody > tr > td.danger,\n.table > tbody > tr > th.danger,\n.table > tbody > tr.danger > td,\n.table > tbody > tr.danger > th,\n.table > tfoot > tr > td.danger,\n.table > tfoot > tr > th.danger,\n.table > tfoot > tr.danger > td,\n.table > tfoot > tr.danger > th {\n  background-color: #f2dede;\n  border-color: #eed3d7;\n}\n\n.table-hover > tbody > tr > td.danger:hover,\n.table-hover > tbody > tr > th.danger:hover, .table-hover > tbody > tr.danger:hover > td {\n  background-color: #ebcccc;\n  border-color: #e6c1c7;\n}\n\n.table > thead > tr > td.warning,\n.table > thead > tr > th.warning, .table > thead > tr.warning > td, .table > thead > tr.warning > th,\n.table > tbody > tr > td.warning,\n.table > tbody > tr > th.warning,\n.table > tbody > tr.warning > td,\n.table > tbody > tr.warning > th,\n.table > tfoot > tr > td.warning,\n.table > tfoot > tr > th.warning,\n.table > tfoot > tr.warning > td,\n.table > tfoot > tr.warning > th {\n  background-color: #fcf8e3;\n  border-color: #fbeed5;\n}\n\n.table-hover > tbody > tr > td.warning:hover,\n.table-hover > tbody > tr > th.warning:hover, .table-hover > tbody > tr.warning:hover > td {\n  background-color: #faf2cc;\n  border-color: #f8e5be;\n}\n\n@media (max-width: 768px) {\n  .table-responsive {\n    width: 100%;\n    margin-bottom: 15px;\n    overflow-y: hidden;\n    overflow-x: scroll;\n    border: 1px solid #dddddd;\n  }\n  .table-responsive > .table {\n    margin-bottom: 0;\n    background-color: #fff;\n  }\n  .table-responsive > .table > thead > tr > th,\n  .table-responsive > .table > thead > tr > td,\n  .table-responsive > .table > tbody > tr > th,\n  .table-responsive > .table > tbody > tr > td,\n  .table-responsive > .table > tfoot > tr > th,\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 > thead > tr > td:first-child,\n  .table-responsive > .table-bordered > tbody > tr > th:first-child,\n  .table-responsive > .table-bordered > tbody > tr > td:first-child,\n  .table-responsive > .table-bordered > tfoot > tr > th: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 > thead > tr > td:last-child,\n  .table-responsive > .table-bordered > tbody > tr > th:last-child,\n  .table-responsive > .table-bordered > tbody > tr > td:last-child,\n  .table-responsive > .table-bordered > tfoot > tr > th:last-child,\n  .table-responsive > .table-bordered > tfoot > tr > td:last-child {\n    border-right: 0;\n  }\n  .table-responsive > .table-bordered > thead > tr:last-child > th,\n  .table-responsive > .table-bordered > thead > tr:last-child > td,\n  .table-responsive > .table-bordered > tbody > tr:last-child > th,\n  .table-responsive > .table-bordered > tbody > tr:last-child > td,\n  .table-responsive > .table-bordered > tfoot > tr:last-child > th,\n  .table-responsive > .table-bordered > tfoot > tr:last-child > td {\n    border-bottom: 0;\n  }\n}\nfieldset {\n  padding: 0;\n  margin: 0;\n  border: 0;\n}\n\nlegend {\n  display: block;\n  width: 100%;\n  padding: 0;\n  margin-bottom: 20px;\n  font-size: 21px;\n  line-height: inherit;\n  color: #333333;\n  border: 0;\n  border-bottom: 1px solid #e5e5e5;\n}\n\nlabel {\n  display: inline-block;\n  margin-bottom: 5px;\n  font-weight: bold;\n}\n\ninput[type=\"search\"] {\n  -webkit-box-sizing: border-box;\n  -moz-box-sizing: border-box;\n  box-sizing: border-box;\n}\n\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  margin: 4px 0 0;\n  margin-top: 1px \\9;\n  /* IE8-9 */\n  line-height: normal;\n}\n\ninput[type=\"file\"] {\n  display: block;\n}\n\nselect[multiple],\nselect[size] {\n  height: auto;\n}\n\nselect optgroup {\n  font-size: inherit;\n  font-style: inherit;\n  font-family: inherit;\n}\n\ninput[type=\"file\"]:focus,\ninput[type=\"radio\"]:focus,\ninput[type=\"checkbox\"]:focus {\n  outline: thin dotted #333;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n\ninput[type=\"number\"]::-webkit-outer-spin-button, input[type=\"number\"]::-webkit-inner-spin-button {\n  height: auto;\n}\n\n.form-control:-moz-placeholder {\n  color: #999999;\n}\n.form-control::-moz-placeholder {\n  color: #999999;\n}\n.form-control:-ms-input-placeholder {\n  color: #999999;\n}\n.form-control::-webkit-input-placeholder {\n  color: #999999;\n}\n\n.form-control {\n  display: block;\n  width: 100%;\n  height: 34px;\n  padding: 6px 12px;\n  font-size: 14px;\n  line-height: 1.428571429;\n  color: #555555;\n  vertical-align: middle;\n  background-color: white;\n  border: 1px solid #cccccc;\n  border-radius: 4px;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n  box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n  -webkit-transition: border-color ease-in-out 0.15s, box-shadow ease-in-out 0.15s;\n  transition: border-color ease-in-out 0.15s, box-shadow ease-in-out 0.15s;\n}\n.form-control:focus {\n  border-color: #66afe9;\n  outline: 0;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(102, 175, 233, 0.6);\n  box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(102, 175, 233, 0.6);\n}\n.form-control[disabled], .form-control[readonly], fieldset[disabled] .form-control {\n  cursor: not-allowed;\n  background-color: #eeeeee;\n}\n\ntextarea.form-control {\n  height: auto;\n}\n\n.form-group {\n  margin-bottom: 15px;\n}\n\n.radio,\n.checkbox {\n  display: block;\n  min-height: 20px;\n  margin-top: 10px;\n  margin-bottom: 10px;\n  padding-left: 20px;\n  vertical-align: middle;\n}\n.radio label,\n.checkbox label {\n  display: inline;\n  margin-bottom: 0;\n  font-weight: normal;\n  cursor: pointer;\n}\n\n.radio input[type=\"radio\"],\n.radio-inline input[type=\"radio\"],\n.checkbox input[type=\"checkbox\"],\n.checkbox-inline input[type=\"checkbox\"] {\n  float: left;\n  margin-left: -20px;\n}\n\n.radio + .radio,\n.checkbox + .checkbox {\n  margin-top: -5px;\n}\n\n.radio-inline,\n.checkbox-inline {\n  display: inline-block;\n  padding-left: 20px;\n  margin-bottom: 0;\n  vertical-align: middle;\n  font-weight: normal;\n  cursor: pointer;\n}\n\n.radio-inline + .radio-inline,\n.checkbox-inline + .checkbox-inline {\n  margin-top: 0;\n  margin-left: 10px;\n}\n\ninput[type=\"radio\"][disabled], fieldset[disabled] input[type=\"radio\"],\ninput[type=\"checkbox\"][disabled], fieldset[disabled]\ninput[type=\"checkbox\"],\n.radio[disabled], fieldset[disabled]\n.radio,\n.radio-inline[disabled], fieldset[disabled]\n.radio-inline,\n.checkbox[disabled], fieldset[disabled]\n.checkbox,\n.checkbox-inline[disabled], fieldset[disabled]\n.checkbox-inline {\n  cursor: not-allowed;\n}\n\n.input-sm, .input-group-sm > .form-control,\n.input-group-sm > .input-group-addon,\n.input-group-sm > .input-group-btn > .btn {\n  height: 30px;\n  padding: 5px 10px;\n  font-size: 12px;\n  line-height: 1.5;\n  border-radius: 3px;\n}\n\nselect.input-sm, .input-group-sm > select.form-control,\n.input-group-sm > select.input-group-addon,\n.input-group-sm > .input-group-btn > select.btn {\n  height: 30px;\n  line-height: 30px;\n}\n\ntextarea.input-sm, .input-group-sm > textarea.form-control,\n.input-group-sm > textarea.input-group-addon,\n.input-group-sm > .input-group-btn > textarea.btn {\n  height: auto;\n}\n\n.input-lg, .input-group-lg > .form-control,\n.input-group-lg > .input-group-addon,\n.input-group-lg > .input-group-btn > .btn {\n  height: 45px;\n  padding: 10px 16px;\n  font-size: 18px;\n  line-height: 1.33;\n  border-radius: 6px;\n}\n\nselect.input-lg, .input-group-lg > select.form-control,\n.input-group-lg > select.input-group-addon,\n.input-group-lg > .input-group-btn > select.btn {\n  height: 45px;\n  line-height: 45px;\n}\n\ntextarea.input-lg, .input-group-lg > textarea.form-control,\n.input-group-lg > textarea.input-group-addon,\n.input-group-lg > .input-group-btn > textarea.btn {\n  height: auto;\n}\n\n.has-warning .help-block,\n.has-warning .control-label {\n  color: #c09853;\n}\n.has-warning .form-control {\n  border-color: #c09853;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n  box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n.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.has-warning .input-group-addon {\n  color: #c09853;\n  border-color: #c09853;\n  background-color: #fcf8e3;\n}\n\n.has-error .help-block,\n.has-error .control-label {\n  color: #b94a48;\n}\n.has-error .form-control {\n  border-color: #b94a48;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n  box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n.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.has-error .input-group-addon {\n  color: #b94a48;\n  border-color: #b94a48;\n  background-color: #f2dede;\n}\n\n.has-success .help-block,\n.has-success .control-label {\n  color: #468847;\n}\n.has-success .form-control {\n  border-color: #468847;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n  box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n.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.has-success .input-group-addon {\n  color: #468847;\n  border-color: #468847;\n  background-color: #dff0d8;\n}\n\n.form-control-static {\n  margin-bottom: 0;\n  padding-top: 7px;\n}\n\n.help-block {\n  display: block;\n  margin-top: 5px;\n  margin-bottom: 10px;\n  color: #737373;\n}\n\n@media (min-width: 768px) {\n  .form-inline .form-group, .navbar-form .form-group {\n    display: inline-block;\n    margin-bottom: 0;\n    vertical-align: middle;\n  }\n  .form-inline .form-control, .navbar-form .form-control {\n    display: inline-block;\n  }\n  .form-inline .radio, .navbar-form .radio,\n  .form-inline .checkbox,\n  .navbar-form .checkbox {\n    display: inline-block;\n    margin-top: 0;\n    margin-bottom: 0;\n    padding-left: 0;\n  }\n  .form-inline .radio input[type=\"radio\"], .navbar-form .radio input[type=\"radio\"],\n  .form-inline .checkbox input[type=\"checkbox\"],\n  .navbar-form .checkbox input[type=\"checkbox\"] {\n    float: none;\n    margin-left: 0;\n  }\n}\n\n.form-horizontal .control-label,\n.form-horizontal .radio,\n.form-horizontal .checkbox,\n.form-horizontal .radio-inline,\n.form-horizontal .checkbox-inline {\n  margin-top: 0;\n  margin-bottom: 0;\n  padding-top: 7px;\n}\n.form-horizontal .form-group {\n  margin-left: -15px;\n  margin-right: -15px;\n}\n.form-horizontal .form-group:before, .form-horizontal .form-group:after {\n  content: \" \";\n  /* 1 */\n  display: table;\n  /* 2 */\n}\n.form-horizontal .form-group:after {\n  clear: both;\n}\n@media (min-width: 768px) {\n  .form-horizontal .control-label {\n    text-align: right;\n  }\n}\n\n.btn {\n  display: inline-block;\n  padding: 6px 12px;\n  margin-bottom: 0;\n  font-size: 14px;\n  font-weight: normal;\n  line-height: 1.428571429;\n  text-align: center;\n  vertical-align: middle;\n  cursor: pointer;\n  border: 1px solid transparent;\n  border-radius: 4px;\n  white-space: nowrap;\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.btn:focus {\n  outline: thin dotted #333;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n.btn:hover, .btn:focus {\n  color: #333333;\n  text-decoration: none;\n}\n.btn:active, .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.btn.disabled, .btn[disabled], fieldset[disabled] .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\n.btn-default {\n  color: #333333;\n  background-color: white;\n  border-color: #cccccc;\n}\n.btn-default:hover, .btn-default:focus, .btn-default:active, .btn-default.active {\n  color: #333333;\n  background-color: #ebebeb;\n  border-color: #adadad;\n}\n.open .btn-default.dropdown-toggle {\n  color: #333333;\n  background-color: #ebebeb;\n  border-color: #adadad;\n}\n.btn-default:active, .btn-default.active {\n  background-image: none;\n}\n.open .btn-default.dropdown-toggle {\n  background-image: none;\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[disabled].active, 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: white;\n  border-color: #cccccc;\n}\n\n.btn-primary {\n  color: white;\n  background-color: #428bca;\n  border-color: #357ebd;\n}\n.btn-primary:hover, .btn-primary:focus, .btn-primary:active, .btn-primary.active {\n  color: white;\n  background-color: #3276b1;\n  border-color: #285e8e;\n}\n.open .btn-primary.dropdown-toggle {\n  color: white;\n  background-color: #3276b1;\n  border-color: #285e8e;\n}\n.btn-primary:active, .btn-primary.active {\n  background-image: none;\n}\n.open .btn-primary.dropdown-toggle {\n  background-image: none;\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[disabled].active, 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: #428bca;\n  border-color: #357ebd;\n}\n\n.btn-warning {\n  color: white;\n  background-color: #f0ad4e;\n  border-color: #eea236;\n}\n.btn-warning:hover, .btn-warning:focus, .btn-warning:active, .btn-warning.active {\n  color: white;\n  background-color: #ed9c28;\n  border-color: #d58512;\n}\n.open .btn-warning.dropdown-toggle {\n  color: white;\n  background-color: #ed9c28;\n  border-color: #d58512;\n}\n.btn-warning:active, .btn-warning.active {\n  background-image: none;\n}\n.open .btn-warning.dropdown-toggle {\n  background-image: none;\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[disabled].active, 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: #f0ad4e;\n  border-color: #eea236;\n}\n\n.btn-danger {\n  color: white;\n  background-color: #d9534f;\n  border-color: #d43f3a;\n}\n.btn-danger:hover, .btn-danger:focus, .btn-danger:active, .btn-danger.active {\n  color: white;\n  background-color: #d2322d;\n  border-color: #ac2925;\n}\n.open .btn-danger.dropdown-toggle {\n  color: white;\n  background-color: #d2322d;\n  border-color: #ac2925;\n}\n.btn-danger:active, .btn-danger.active {\n  background-image: none;\n}\n.open .btn-danger.dropdown-toggle {\n  background-image: none;\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[disabled].active, 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: #d9534f;\n  border-color: #d43f3a;\n}\n\n.btn-success {\n  color: white;\n  background-color: #5cb85c;\n  border-color: #4cae4c;\n}\n.btn-success:hover, .btn-success:focus, .btn-success:active, .btn-success.active {\n  color: white;\n  background-color: #47a447;\n  border-color: #398439;\n}\n.open .btn-success.dropdown-toggle {\n  color: white;\n  background-color: #47a447;\n  border-color: #398439;\n}\n.btn-success:active, .btn-success.active {\n  background-image: none;\n}\n.open .btn-success.dropdown-toggle {\n  background-image: none;\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[disabled].active, 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: #5cb85c;\n  border-color: #4cae4c;\n}\n\n.btn-info {\n  color: white;\n  background-color: #5bc0de;\n  border-color: #46b8da;\n}\n.btn-info:hover, .btn-info:focus, .btn-info:active, .btn-info.active {\n  color: white;\n  background-color: #39b3d7;\n  border-color: #269abc;\n}\n.open .btn-info.dropdown-toggle {\n  color: white;\n  background-color: #39b3d7;\n  border-color: #269abc;\n}\n.btn-info:active, .btn-info.active {\n  background-image: none;\n}\n.open .btn-info.dropdown-toggle {\n  background-image: none;\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[disabled].active, 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: #5bc0de;\n  border-color: #46b8da;\n}\n\n.btn-link {\n  color: #428bca;\n  font-weight: normal;\n  cursor: pointer;\n  border-radius: 0;\n}\n.btn-link, .btn-link:active, .btn-link[disabled], fieldset[disabled] .btn-link {\n  background-color: transparent;\n  -webkit-box-shadow: none;\n  box-shadow: none;\n}\n.btn-link, .btn-link:hover, .btn-link:focus, .btn-link:active {\n  border-color: transparent;\n}\n.btn-link:hover, .btn-link:focus {\n  color: #2a6496;\n  text-decoration: underline;\n  background-color: transparent;\n}\n.btn-link[disabled]:hover, .btn-link[disabled]:focus, fieldset[disabled] .btn-link:hover, fieldset[disabled] .btn-link:focus {\n  color: #999999;\n  text-decoration: none;\n}\n\n.btn-lg, .btn-group-lg > .btn {\n  padding: 10px 16px;\n  font-size: 18px;\n  line-height: 1.33;\n  border-radius: 6px;\n}\n\n.btn-sm, .btn-group-sm > .btn,\n.btn-xs,\n.btn-group-xs > .btn {\n  padding: 5px 10px;\n  font-size: 12px;\n  line-height: 1.5;\n  border-radius: 3px;\n}\n\n.btn-xs, .btn-group-xs > .btn {\n  padding: 1px 5px;\n}\n\n.btn-block {\n  display: block;\n  width: 100%;\n  padding-left: 0;\n  padding-right: 0;\n}\n\n.btn-block + .btn-block {\n  margin-top: 5px;\n}\n\ninput[type=\"submit\"].btn-block,\ninput[type=\"reset\"].btn-block,\ninput[type=\"button\"].btn-block {\n  width: 100%;\n}\n\n.fade {\n  opacity: 0;\n  -webkit-transition: opacity 0.15s linear;\n  transition: opacity 0.15s linear;\n}\n.fade.in {\n  opacity: 1;\n}\n\n.collapse {\n  display: none;\n}\n.collapse.in {\n  display: block;\n}\n\n.collapsing {\n  position: relative;\n  height: 0;\n  overflow: hidden;\n  -webkit-transition: height 0.35s ease;\n  transition: height 0.35s ease;\n}\n\n@font-face {\n  font-family: 'Glyphicons Halflings';\n  src: url(\"../fonts/glyphicons-halflings-regular.eot\");\n  src: url(\"../fonts/glyphicons-halflings-regular.eot?#iefix\") format(\"embedded-opentype\"), url(\"../fonts/glyphicons-halflings-regular.woff\") format(\"woff\"), url(\"../fonts/glyphicons-halflings-regular.ttf\") format(\"truetype\"), url(\"../fonts/glyphicons-halflings-regular.svg#glyphicons-halflingsregular\") format(\"svg\");\n}\n\n.glyphicon {\n  position: relative;\n  top: 1px;\n  display: inline-block;\n  font-family: 'Glyphicons Halflings';\n  font-style: normal;\n  font-weight: normal;\n  line-height: 1;\n  -webkit-font-smoothing: antialiased;\n}\n\n.glyphicon-asterisk:before {\n  content: \"\\2a\";\n}\n\n.glyphicon-plus:before {\n  content: \"\\2b\";\n}\n\n.glyphicon-euro:before {\n  content: \"\\20ac\";\n}\n\n.glyphicon-minus:before {\n  content: \"\\2212\";\n}\n\n.glyphicon-cloud:before {\n  content: \"\\2601\";\n}\n\n.glyphicon-envelope:before {\n  content: \"\\2709\";\n}\n\n.glyphicon-pencil:before {\n  content: \"\\270f\";\n}\n\n.glyphicon-glass:before {\n  content: \"\\e001\";\n}\n\n.glyphicon-music:before {\n  content: \"\\e002\";\n}\n\n.glyphicon-search:before {\n  content: \"\\e003\";\n}\n\n.glyphicon-heart:before {\n  content: \"\\e005\";\n}\n\n.glyphicon-star:before {\n  content: \"\\e006\";\n}\n\n.glyphicon-star-empty:before {\n  content: \"\\e007\";\n}\n\n.glyphicon-user:before {\n  content: \"\\e008\";\n}\n\n.glyphicon-film:before {\n  content: \"\\e009\";\n}\n\n.glyphicon-th-large:before {\n  content: \"\\e010\";\n}\n\n.glyphicon-th:before {\n  content: \"\\e011\";\n}\n\n.glyphicon-th-list:before {\n  content: \"\\e012\";\n}\n\n.glyphicon-ok:before {\n  content: \"\\e013\";\n}\n\n.glyphicon-remove:before {\n  content: \"\\e014\";\n}\n\n.glyphicon-zoom-in:before {\n  content: \"\\e015\";\n}\n\n.glyphicon-zoom-out:before {\n  content: \"\\e016\";\n}\n\n.glyphicon-off:before {\n  content: \"\\e017\";\n}\n\n.glyphicon-signal:before {\n  content: \"\\e018\";\n}\n\n.glyphicon-cog:before {\n  content: \"\\e019\";\n}\n\n.glyphicon-trash:before {\n  content: \"\\e020\";\n}\n\n.glyphicon-home:before {\n  content: \"\\e021\";\n}\n\n.glyphicon-file:before {\n  content: \"\\e022\";\n}\n\n.glyphicon-time:before {\n  content: \"\\e023\";\n}\n\n.glyphicon-road:before {\n  content: \"\\e024\";\n}\n\n.glyphicon-download-alt:before {\n  content: \"\\e025\";\n}\n\n.glyphicon-download:before {\n  content: \"\\e026\";\n}\n\n.glyphicon-upload:before {\n  content: \"\\e027\";\n}\n\n.glyphicon-inbox:before {\n  content: \"\\e028\";\n}\n\n.glyphicon-play-circle:before {\n  content: \"\\e029\";\n}\n\n.glyphicon-repeat:before {\n  content: \"\\e030\";\n}\n\n.glyphicon-refresh:before {\n  content: \"\\e031\";\n}\n\n.glyphicon-list-alt:before {\n  content: \"\\e032\";\n}\n\n.glyphicon-flag:before {\n  content: \"\\e034\";\n}\n\n.glyphicon-headphones:before {\n  content: \"\\e035\";\n}\n\n.glyphicon-volume-off:before {\n  content: \"\\e036\";\n}\n\n.glyphicon-volume-down:before {\n  content: \"\\e037\";\n}\n\n.glyphicon-volume-up:before {\n  content: \"\\e038\";\n}\n\n.glyphicon-qrcode:before {\n  content: \"\\e039\";\n}\n\n.glyphicon-barcode:before {\n  content: \"\\e040\";\n}\n\n.glyphicon-tag:before {\n  content: \"\\e041\";\n}\n\n.glyphicon-tags:before {\n  content: \"\\e042\";\n}\n\n.glyphicon-book:before {\n  content: \"\\e043\";\n}\n\n.glyphicon-print:before {\n  content: \"\\e045\";\n}\n\n.glyphicon-font:before {\n  content: \"\\e047\";\n}\n\n.glyphicon-bold:before {\n  content: \"\\e048\";\n}\n\n.glyphicon-italic:before {\n  content: \"\\e049\";\n}\n\n.glyphicon-text-height:before {\n  content: \"\\e050\";\n}\n\n.glyphicon-text-width:before {\n  content: \"\\e051\";\n}\n\n.glyphicon-align-left:before {\n  content: \"\\e052\";\n}\n\n.glyphicon-align-center:before {\n  content: \"\\e053\";\n}\n\n.glyphicon-align-right:before {\n  content: \"\\e054\";\n}\n\n.glyphicon-align-justify:before {\n  content: \"\\e055\";\n}\n\n.glyphicon-list:before {\n  content: \"\\e056\";\n}\n\n.glyphicon-indent-left:before {\n  content: \"\\e057\";\n}\n\n.glyphicon-indent-right:before {\n  content: \"\\e058\";\n}\n\n.glyphicon-facetime-video:before {\n  content: \"\\e059\";\n}\n\n.glyphicon-picture:before {\n  content: \"\\e060\";\n}\n\n.glyphicon-map-marker:before {\n  content: \"\\e062\";\n}\n\n.glyphicon-adjust:before {\n  content: \"\\e063\";\n}\n\n.glyphicon-tint:before {\n  content: \"\\e064\";\n}\n\n.glyphicon-edit:before {\n  content: \"\\e065\";\n}\n\n.glyphicon-share:before {\n  content: \"\\e066\";\n}\n\n.glyphicon-check:before {\n  content: \"\\e067\";\n}\n\n.glyphicon-move:before {\n  content: \"\\e068\";\n}\n\n.glyphicon-step-backward:before {\n  content: \"\\e069\";\n}\n\n.glyphicon-fast-backward:before {\n  content: \"\\e070\";\n}\n\n.glyphicon-backward:before {\n  content: \"\\e071\";\n}\n\n.glyphicon-play:before {\n  content: \"\\e072\";\n}\n\n.glyphicon-pause:before {\n  content: \"\\e073\";\n}\n\n.glyphicon-stop:before {\n  content: \"\\e074\";\n}\n\n.glyphicon-forward:before {\n  content: \"\\e075\";\n}\n\n.glyphicon-fast-forward:before {\n  content: \"\\e076\";\n}\n\n.glyphicon-step-forward:before {\n  content: \"\\e077\";\n}\n\n.glyphicon-eject:before {\n  content: \"\\e078\";\n}\n\n.glyphicon-chevron-left:before {\n  content: \"\\e079\";\n}\n\n.glyphicon-chevron-right:before {\n  content: \"\\e080\";\n}\n\n.glyphicon-plus-sign:before {\n  content: \"\\e081\";\n}\n\n.glyphicon-minus-sign:before {\n  content: \"\\e082\";\n}\n\n.glyphicon-remove-sign:before {\n  content: \"\\e083\";\n}\n\n.glyphicon-ok-sign:before {\n  content: \"\\e084\";\n}\n\n.glyphicon-question-sign:before {\n  content: \"\\e085\";\n}\n\n.glyphicon-info-sign:before {\n  content: \"\\e086\";\n}\n\n.glyphicon-screenshot:before {\n  content: \"\\e087\";\n}\n\n.glyphicon-remove-circle:before {\n  content: \"\\e088\";\n}\n\n.glyphicon-ok-circle:before {\n  content: \"\\e089\";\n}\n\n.glyphicon-ban-circle:before {\n  content: \"\\e090\";\n}\n\n.glyphicon-arrow-left:before {\n  content: \"\\e091\";\n}\n\n.glyphicon-arrow-right:before {\n  content: \"\\e092\";\n}\n\n.glyphicon-arrow-up:before {\n  content: \"\\e093\";\n}\n\n.glyphicon-arrow-down:before {\n  content: \"\\e094\";\n}\n\n.glyphicon-share-alt:before {\n  content: \"\\e095\";\n}\n\n.glyphicon-resize-full:before {\n  content: \"\\e096\";\n}\n\n.glyphicon-resize-small:before {\n  content: \"\\e097\";\n}\n\n.glyphicon-exclamation-sign:before {\n  content: \"\\e101\";\n}\n\n.glyphicon-gift:before {\n  content: \"\\e102\";\n}\n\n.glyphicon-leaf:before {\n  content: \"\\e103\";\n}\n\n.glyphicon-eye-open:before {\n  content: \"\\e105\";\n}\n\n.glyphicon-eye-close:before {\n  content: \"\\e106\";\n}\n\n.glyphicon-warning-sign:before {\n  content: \"\\e107\";\n}\n\n.glyphicon-plane:before {\n  content: \"\\e108\";\n}\n\n.glyphicon-random:before {\n  content: \"\\e110\";\n}\n\n.glyphicon-comment:before {\n  content: \"\\e111\";\n}\n\n.glyphicon-magnet:before {\n  content: \"\\e112\";\n}\n\n.glyphicon-chevron-up:before {\n  content: \"\\e113\";\n}\n\n.glyphicon-chevron-down:before {\n  content: \"\\e114\";\n}\n\n.glyphicon-retweet:before {\n  content: \"\\e115\";\n}\n\n.glyphicon-shopping-cart:before {\n  content: \"\\e116\";\n}\n\n.glyphicon-folder-close:before {\n  content: \"\\e117\";\n}\n\n.glyphicon-folder-open:before {\n  content: \"\\e118\";\n}\n\n.glyphicon-resize-vertical:before {\n  content: \"\\e119\";\n}\n\n.glyphicon-resize-horizontal:before {\n  content: \"\\e120\";\n}\n\n.glyphicon-hdd:before {\n  content: \"\\e121\";\n}\n\n.glyphicon-bullhorn:before {\n  content: \"\\e122\";\n}\n\n.glyphicon-certificate:before {\n  content: \"\\e124\";\n}\n\n.glyphicon-thumbs-up:before {\n  content: \"\\e125\";\n}\n\n.glyphicon-thumbs-down:before {\n  content: \"\\e126\";\n}\n\n.glyphicon-hand-right:before {\n  content: \"\\e127\";\n}\n\n.glyphicon-hand-left:before {\n  content: \"\\e128\";\n}\n\n.glyphicon-hand-up:before {\n  content: \"\\e129\";\n}\n\n.glyphicon-hand-down:before {\n  content: \"\\e130\";\n}\n\n.glyphicon-circle-arrow-right:before {\n  content: \"\\e131\";\n}\n\n.glyphicon-circle-arrow-left:before {\n  content: \"\\e132\";\n}\n\n.glyphicon-circle-arrow-up:before {\n  content: \"\\e133\";\n}\n\n.glyphicon-circle-arrow-down:before {\n  content: \"\\e134\";\n}\n\n.glyphicon-globe:before {\n  content: \"\\e135\";\n}\n\n.glyphicon-tasks:before {\n  content: \"\\e137\";\n}\n\n.glyphicon-filter:before {\n  content: \"\\e138\";\n}\n\n.glyphicon-fullscreen:before {\n  content: \"\\e140\";\n}\n\n.glyphicon-dashboard:before {\n  content: \"\\e141\";\n}\n\n.glyphicon-heart-empty:before {\n  content: \"\\e143\";\n}\n\n.glyphicon-link:before {\n  content: \"\\e144\";\n}\n\n.glyphicon-phone:before {\n  content: \"\\e145\";\n}\n\n.glyphicon-usd:before {\n  content: \"\\e148\";\n}\n\n.glyphicon-gbp:before {\n  content: \"\\e149\";\n}\n\n.glyphicon-sort:before {\n  content: \"\\e150\";\n}\n\n.glyphicon-sort-by-alphabet:before {\n  content: \"\\e151\";\n}\n\n.glyphicon-sort-by-alphabet-alt:before {\n  content: \"\\e152\";\n}\n\n.glyphicon-sort-by-order:before {\n  content: \"\\e153\";\n}\n\n.glyphicon-sort-by-order-alt:before {\n  content: \"\\e154\";\n}\n\n.glyphicon-sort-by-attributes:before {\n  content: \"\\e155\";\n}\n\n.glyphicon-sort-by-attributes-alt:before {\n  content: \"\\e156\";\n}\n\n.glyphicon-unchecked:before {\n  content: \"\\e157\";\n}\n\n.glyphicon-expand:before {\n  content: \"\\e158\";\n}\n\n.glyphicon-collapse-down:before {\n  content: \"\\e159\";\n}\n\n.glyphicon-collapse-up:before {\n  content: \"\\e160\";\n}\n\n.glyphicon-log-in:before {\n  content: \"\\e161\";\n}\n\n.glyphicon-flash:before {\n  content: \"\\e162\";\n}\n\n.glyphicon-log-out:before {\n  content: \"\\e163\";\n}\n\n.glyphicon-new-window:before {\n  content: \"\\e164\";\n}\n\n.glyphicon-record:before {\n  content: \"\\e165\";\n}\n\n.glyphicon-save:before {\n  content: \"\\e166\";\n}\n\n.glyphicon-open:before {\n  content: \"\\e167\";\n}\n\n.glyphicon-saved:before {\n  content: \"\\e168\";\n}\n\n.glyphicon-import:before {\n  content: \"\\e169\";\n}\n\n.glyphicon-export:before {\n  content: \"\\e170\";\n}\n\n.glyphicon-send:before {\n  content: \"\\e171\";\n}\n\n.glyphicon-floppy-disk:before {\n  content: \"\\e172\";\n}\n\n.glyphicon-floppy-saved:before {\n  content: \"\\e173\";\n}\n\n.glyphicon-floppy-remove:before {\n  content: \"\\e174\";\n}\n\n.glyphicon-floppy-save:before {\n  content: \"\\e175\";\n}\n\n.glyphicon-floppy-open:before {\n  content: \"\\e176\";\n}\n\n.glyphicon-credit-card:before {\n  content: \"\\e177\";\n}\n\n.glyphicon-transfer:before {\n  content: \"\\e178\";\n}\n\n.glyphicon-cutlery:before {\n  content: \"\\e179\";\n}\n\n.glyphicon-header:before {\n  content: \"\\e180\";\n}\n\n.glyphicon-compressed:before {\n  content: \"\\e181\";\n}\n\n.glyphicon-earphone:before {\n  content: \"\\e182\";\n}\n\n.glyphicon-phone-alt:before {\n  content: \"\\e183\";\n}\n\n.glyphicon-tower:before {\n  content: \"\\e184\";\n}\n\n.glyphicon-stats:before {\n  content: \"\\e185\";\n}\n\n.glyphicon-sd-video:before {\n  content: \"\\e186\";\n}\n\n.glyphicon-hd-video:before {\n  content: \"\\e187\";\n}\n\n.glyphicon-subtitles:before {\n  content: \"\\e188\";\n}\n\n.glyphicon-sound-stereo:before {\n  content: \"\\e189\";\n}\n\n.glyphicon-sound-dolby:before {\n  content: \"\\e190\";\n}\n\n.glyphicon-sound-5-1:before {\n  content: \"\\e191\";\n}\n\n.glyphicon-sound-6-1:before {\n  content: \"\\e192\";\n}\n\n.glyphicon-sound-7-1:before {\n  content: \"\\e193\";\n}\n\n.glyphicon-copyright-mark:before {\n  content: \"\\e194\";\n}\n\n.glyphicon-registration-mark:before {\n  content: \"\\e195\";\n}\n\n.glyphicon-cloud-download:before {\n  content: \"\\e197\";\n}\n\n.glyphicon-cloud-upload:before {\n  content: \"\\e198\";\n}\n\n.glyphicon-tree-conifer:before {\n  content: \"\\e199\";\n}\n\n.glyphicon-tree-deciduous:before {\n  content: \"\\e200\";\n}\n\n.glyphicon-briefcase:before {\n  content: \"\\1f4bc\";\n}\n\n.glyphicon-calendar:before {\n  content: \"\\1f4c5\";\n}\n\n.glyphicon-pushpin:before {\n  content: \"\\1f4cc\";\n}\n\n.glyphicon-paperclip:before {\n  content: \"\\1f4ce\";\n}\n\n.glyphicon-camera:before {\n  content: \"\\1f4f7\";\n}\n\n.glyphicon-lock:before {\n  content: \"\\1f512\";\n}\n\n.glyphicon-bell:before {\n  content: \"\\1f514\";\n}\n\n.glyphicon-bookmark:before {\n  content: \"\\1f516\";\n}\n\n.glyphicon-fire:before {\n  content: \"\\1f525\";\n}\n\n.glyphicon-wrench:before {\n  content: \"\\1f527\";\n}\n\n.caret {\n  display: inline-block;\n  width: 0;\n  height: 0;\n  margin-left: 2px;\n  vertical-align: middle;\n  border-top: 4px solid black;\n  border-right: 4px solid transparent;\n  border-left: 4px solid transparent;\n  border-bottom: 0 dotted;\n  content: \"\";\n}\n\n.dropdown {\n  position: relative;\n}\n\n.dropdown-toggle:focus {\n  outline: 0;\n}\n\n.dropdown-menu {\n  position: absolute;\n  top: 100%;\n  left: 0;\n  z-index: 1000;\n  display: none;\n  float: left;\n  min-width: 160px;\n  padding: 5px 0;\n  margin: 2px 0 0;\n  list-style: none;\n  font-size: 14px;\n  background-color: white;\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.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.428571429;\n  color: #333333;\n  white-space: nowrap;\n}\n\n.dropdown-menu > li > a:hover, .dropdown-menu > li > a:focus {\n  text-decoration: none;\n  color: white;\n  background-color: #428bca;\n}\n\n.dropdown-menu > .active > a, .dropdown-menu > .active > a:hover, .dropdown-menu > .active > a:focus {\n  color: white;\n  text-decoration: none;\n  outline: 0;\n  background-color: #428bca;\n}\n\n.dropdown-menu > .disabled > a, .dropdown-menu > .disabled > a:hover, .dropdown-menu > .disabled > a:focus {\n  color: #999999;\n}\n\n.dropdown-menu > .disabled > a:hover, .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\n.open > .dropdown-menu {\n  display: block;\n}\n.open > a {\n  outline: 0;\n}\n\n.dropdown-header {\n  display: block;\n  padding: 3px 20px;\n  font-size: 12px;\n  line-height: 1.428571429;\n  color: #999999;\n}\n\n.dropdown-backdrop {\n  position: fixed;\n  left: 0;\n  right: 0;\n  bottom: 0;\n  top: 0;\n  z-index: 990;\n}\n\n.pull-right > .dropdown-menu {\n  right: 0;\n  left: auto;\n}\n\n.dropup .caret,\n.navbar-fixed-bottom .dropdown .caret {\n  border-top: 0 dotted;\n  border-bottom: 4px solid black;\n  content: \"\";\n}\n.dropup .dropdown-menu,\n.navbar-fixed-bottom .dropdown .dropdown-menu {\n  top: auto;\n  bottom: 100%;\n  margin-bottom: 1px;\n}\n\n@media (min-width: 768px) {\n  .navbar-right .dropdown-menu {\n    right: 0;\n    left: auto;\n  }\n}\n.btn-default .caret {\n  border-top-color: #333333;\n}\n.btn-primary .caret, .btn-success .caret, .btn-warning .caret, .btn-danger .caret, .btn-info .caret {\n  border-top-color: #fff;\n}\n\n.dropup .btn-default .caret {\n  border-bottom-color: #333333;\n}\n.dropup .btn-primary .caret,\n.dropup .btn-success .caret,\n.dropup .btn-warning .caret,\n.dropup .btn-danger .caret,\n.dropup .btn-info .caret {\n  border-bottom-color: #fff;\n}\n\n.btn-group,\n.btn-group-vertical {\n  position: relative;\n  display: inline-block;\n  vertical-align: middle;\n}\n.btn-group > .btn,\n.btn-group-vertical > .btn {\n  position: relative;\n  float: left;\n}\n.btn-group > .btn:hover, .btn-group > .btn:focus, .btn-group > .btn:active, .btn-group > .btn.active,\n.btn-group-vertical > .btn:hover,\n.btn-group-vertical > .btn:focus,\n.btn-group-vertical > .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\n.btn-group .btn + .btn,\n.btn-group .btn + .btn-group,\n.btn-group .btn-group + .btn,\n.btn-group .btn-group + .btn-group {\n  margin-left: -1px;\n}\n\n.btn-toolbar:before, .btn-toolbar:after {\n  content: \" \";\n  /* 1 */\n  display: table;\n  /* 2 */\n}\n.btn-toolbar:after {\n  clear: both;\n}\n.btn-toolbar .btn-group {\n  float: left;\n}\n.btn-toolbar > .btn + .btn,\n.btn-toolbar > .btn + .btn-group,\n.btn-toolbar > .btn-group + .btn,\n.btn-toolbar > .btn-group + .btn-group {\n  margin-left: 5px;\n}\n\n.btn-group > .btn:not(:first-child):not(:last-child):not(.dropdown-toggle) {\n  border-radius: 0;\n}\n\n.btn-group > .btn:first-child {\n  margin-left: 0;\n}\n.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\n.btn-group > .btn:last-child:not(:first-child),\n.btn-group > .dropdown-toggle:not(:first-child) {\n  border-bottom-left-radius: 0;\n  border-top-left-radius: 0;\n}\n\n.btn-group > .btn-group {\n  float: left;\n}\n\n.btn-group > .btn-group:not(:first-child):not(:last-child) > .btn {\n  border-radius: 0;\n}\n\n.btn-group > .btn-group:first-child > .btn:last-child,\n.btn-group > .btn-group:first-child > .dropdown-toggle {\n  border-bottom-right-radius: 0;\n  border-top-right-radius: 0;\n}\n\n.btn-group > .btn-group:last-child > .btn:first-child {\n  border-bottom-left-radius: 0;\n  border-top-left-radius: 0;\n}\n\n.btn-group .dropdown-toggle:active,\n.btn-group.open .dropdown-toggle {\n  outline: 0;\n}\n\n.btn-group > .btn + .dropdown-toggle {\n  padding-left: 8px;\n  padding-right: 8px;\n}\n\n.btn-group > .btn-lg + .dropdown-toggle, .btn-group-lg.btn-group > .btn + .dropdown-toggle {\n  padding-left: 12px;\n  padding-right: 12px;\n}\n\n.btn-group.open .dropdown-toggle {\n  -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);\n  box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);\n}\n\n.btn .caret {\n  margin-left: 0;\n}\n\n.btn-lg .caret, .btn-group-lg > .btn .caret {\n  border-width: 5px 5px 0;\n  border-bottom-width: 0;\n}\n\n.dropup .btn-lg .caret, .dropup .btn-group-lg > .btn .caret {\n  border-width: 0 5px 5px;\n}\n\n.btn-group-vertical > .btn,\n.btn-group-vertical > .btn-group {\n  display: block;\n  float: none;\n  width: 100%;\n  max-width: 100%;\n}\n.btn-group-vertical > .btn-group:before, .btn-group-vertical > .btn-group:after {\n  content: \" \";\n  /* 1 */\n  display: table;\n  /* 2 */\n}\n.btn-group-vertical > .btn-group:after {\n  clear: both;\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\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-bottom-left-radius: 4px;\n  border-top-right-radius: 0;\n  border-top-left-radius: 0;\n}\n\n.btn-group-vertical > .btn-group:not(:first-child):not(:last-child) > .btn {\n  border-radius: 0;\n}\n\n.btn-group-vertical > .btn-group:first-child > .btn:last-child,\n.btn-group-vertical > .btn-group:first-child > .dropdown-toggle {\n  border-bottom-right-radius: 0;\n  border-bottom-left-radius: 0;\n}\n\n.btn-group-vertical > .btn-group:last-child > .btn:first-child {\n  border-top-right-radius: 0;\n  border-top-left-radius: 0;\n}\n\n.btn-group-justified {\n  display: table;\n  width: 100%;\n  table-layout: fixed;\n  border-collapse: separate;\n}\n.btn-group-justified .btn {\n  float: none;\n  display: table-cell;\n  width: 1%;\n}\n\n[data-toggle=\"buttons\"] > .btn > input[type=\"radio\"],\n[data-toggle=\"buttons\"] > .btn > input[type=\"checkbox\"] {\n  display: none;\n}\n\n.input-group {\n  position: relative;\n  display: table;\n  border-collapse: separate;\n}\n.input-group.col {\n  float: none;\n  padding-left: 0;\n  padding-right: 0;\n}\n.input-group .form-control {\n  width: 100%;\n  margin-bottom: 0;\n}\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\n.input-group-addon,\n.input-group-btn {\n  width: 1%;\n  white-space: nowrap;\n  vertical-align: middle;\n}\n\n.input-group-addon {\n  padding: 6px 12px;\n  font-size: 14px;\n  font-weight: normal;\n  line-height: 1;\n  text-align: center;\n  background-color: #eeeeee;\n  border: 1px solid #cccccc;\n  border-radius: 4px;\n}\n.input-group-addon.input-sm,\n.input-group-sm > .input-group-addon,\n.input-group-sm > .input-group-btn > .input-group-addon.btn {\n  padding: 5px 10px;\n  font-size: 12px;\n  border-radius: 3px;\n}\n.input-group-addon.input-lg,\n.input-group-lg > .input-group-addon,\n.input-group-lg > .input-group-btn > .input-group-addon.btn {\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\n.input-group .form-control:first-child,\n.input-group-addon:first-child,\n.input-group-btn:first-child > .btn,\n.input-group-btn:first-child > .dropdown-toggle,\n.input-group-btn:last-child > .btn:not(:last-child):not(.dropdown-toggle) {\n  border-bottom-right-radius: 0;\n  border-top-right-radius: 0;\n}\n\n.input-group-addon:first-child {\n  border-right: 0;\n}\n\n.input-group .form-control:last-child,\n.input-group-addon:last-child,\n.input-group-btn:last-child > .btn,\n.input-group-btn:last-child > .dropdown-toggle,\n.input-group-btn:first-child > .btn:not(:first-child) {\n  border-bottom-left-radius: 0;\n  border-top-left-radius: 0;\n}\n\n.input-group-addon:last-child {\n  border-left: 0;\n}\n\n.input-group-btn {\n  position: relative;\n  white-space: nowrap;\n}\n\n.input-group-btn > .btn {\n  position: relative;\n}\n.input-group-btn > .btn + .btn {\n  margin-left: -4px;\n}\n.input-group-btn > .btn:hover, .input-group-btn > .btn:active {\n  z-index: 2;\n}\n\n.nav {\n  margin-bottom: 0;\n  padding-left: 0;\n  list-style: none;\n}\n.nav:before, .nav:after {\n  content: \" \";\n  /* 1 */\n  display: table;\n  /* 2 */\n}\n.nav:after {\n  clear: both;\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, .nav > li > a:focus {\n  text-decoration: none;\n  background-color: #eeeeee;\n}\n.nav > li.disabled > a {\n  color: #999999;\n}\n.nav > li.disabled > a:hover, .nav > li.disabled > a:focus {\n  color: #999999;\n  text-decoration: none;\n  background-color: transparent;\n  cursor: not-allowed;\n}\n.nav .open > a, .nav .open > a:hover, .nav .open > a:focus {\n  background-color: #eeeeee;\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\n.nav-tabs {\n  border-bottom: 1px solid #dddddd;\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.428571429;\n  border: 1px solid transparent;\n  border-radius: 4px 4px 0 0;\n}\n.nav-tabs > li > a:hover {\n  border-color: #eeeeee #eeeeee #dddddd;\n}\n.nav-tabs > li.active > a, .nav-tabs > li.active > a:hover, .nav-tabs > li.active > a:focus {\n  color: #555555;\n  background-color: white;\n  border: 1px solid #dddddd;\n  border-bottom-color: transparent;\n  cursor: default;\n}\n\n.nav-pills > li {\n  float: left;\n}\n.nav-pills > li > a {\n  border-radius: 5px;\n}\n.nav-pills > li + li {\n  margin-left: 2px;\n}\n.nav-pills > li.active > a, .nav-pills > li.active > a:hover, .nav-pills > li.active > a:focus {\n  color: white;\n  background-color: #428bca;\n}\n\n.nav-stacked > li {\n  float: none;\n}\n.nav-stacked > li + li {\n  margin-top: 2px;\n  margin-left: 0;\n}\n\n.nav-justified, .nav-tabs.nav-justified {\n  width: 100%;\n}\n.nav-justified > li, .nav-tabs.nav-justified > li {\n  float: none;\n}\n.nav-justified > li > a, .nav-tabs.nav-justified > li > a {\n  text-align: center;\n}\n@media (min-width: 768px) {\n  .nav-justified > li, .nav-tabs.nav-justified > li {\n    display: table-cell;\n    width: 1%;\n  }\n}\n\n.nav-tabs-justified, .nav-tabs.nav-justified {\n  border-bottom: 0;\n}\n.nav-tabs-justified > li > a, .nav-tabs.nav-justified > li > a {\n  border-bottom: 1px solid #dddddd;\n  margin-right: 0;\n}\n.nav-tabs-justified > .active > a, .nav-tabs.nav-justified > .active > a {\n  border-bottom-color: white;\n}\n\n.tabbable:before, .tabbable:after {\n  content: \" \";\n  /* 1 */\n  display: table;\n  /* 2 */\n}\n.tabbable:after {\n  clear: both;\n}\n\n.tab-content > .tab-pane,\n.pill-content > .pill-pane {\n  display: none;\n}\n\n.tab-content > .active,\n.pill-content > .active {\n  display: block;\n}\n\n.nav .caret {\n  border-top-color: #428bca;\n  border-bottom-color: #428bca;\n}\n\n.nav a:hover .caret {\n  border-top-color: #2a6496;\n  border-bottom-color: #2a6496;\n}\n\n.nav-tabs .dropdown-menu {\n  margin-top: -1px;\n  border-top-right-radius: 0;\n  border-top-left-radius: 0;\n}\n\n.navbar {\n  position: relative;\n  z-index: 1000;\n  min-height: 50px;\n  margin-bottom: 20px;\n  border: 1px solid transparent;\n}\n.navbar:before, .navbar:after {\n  content: \" \";\n  /* 1 */\n  display: table;\n  /* 2 */\n}\n.navbar:after {\n  clear: both;\n}\n@media (min-width: 768px) {\n  .navbar {\n    border-radius: 4px;\n  }\n}\n\n.navbar-header:before, .navbar-header:after {\n  content: \" \";\n  /* 1 */\n  display: table;\n  /* 2 */\n}\n.navbar-header:after {\n  clear: both;\n}\n@media (min-width: 768px) {\n  .navbar-header {\n    float: left;\n  }\n}\n\n.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.navbar-collapse:before, .navbar-collapse:after {\n  content: \" \";\n  /* 1 */\n  display: table;\n  /* 2 */\n}\n.navbar-collapse:after {\n  clear: both;\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-collapse .navbar-nav.navbar-left:first-child {\n    margin-left: -15px;\n  }\n  .navbar-collapse .navbar-nav.navbar-right:last-child {\n    margin-right: -15px;\n  }\n  .navbar-collapse .navbar-text:last-child {\n    margin-right: 0;\n  }\n}\n\n.container > .navbar-header,\n.container > .navbar-collapse {\n  margin-right: -15px;\n  margin-left: -15px;\n}\n@media (min-width: 768px) {\n  .container > .navbar-header,\n  .container > .navbar-collapse {\n    margin-right: 0;\n    margin-left: 0;\n  }\n}\n\n.navbar-static-top {\n  border-width: 0 0 1px;\n}\n@media (min-width: 768px) {\n  .navbar-static-top {\n    border-radius: 0;\n  }\n}\n\n.navbar-fixed-top,\n.navbar-fixed-bottom {\n  position: fixed;\n  right: 0;\n  left: 0;\n  border-width: 0 0 1px;\n}\n@media (min-width: 768px) {\n  .navbar-fixed-top,\n  .navbar-fixed-bottom {\n    border-radius: 0;\n  }\n}\n\n.navbar-fixed-top {\n  z-index: 1030;\n  top: 0;\n}\n\n.navbar-fixed-bottom {\n  bottom: 0;\n  margin-bottom: 0;\n}\n\n.navbar-brand {\n  float: left;\n  padding: 15px 15px;\n  font-size: 18px;\n  line-height: 20px;\n}\n.navbar-brand:hover, .navbar-brand:focus {\n  text-decoration: none;\n}\n@media (min-width: 768px) {\n  .navbar > .container .navbar-brand {\n    margin-left: -15px;\n  }\n}\n\n.navbar-toggle {\n  position: relative;\n  float: right;\n  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.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\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, .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}\n\n@media (min-width: 768px) {\n  .navbar-left {\n    float: left !important;\n  }\n\n  .navbar-right {\n    float: right !important;\n  }\n}\n.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 (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    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\n.navbar-nav > li > .dropdown-menu {\n  margin-top: 0;\n  border-top-right-radius: 0;\n  border-top-left-radius: 0;\n}\n\n.navbar-fixed-bottom .navbar-nav > li > .dropdown-menu {\n  border-bottom-right-radius: 0;\n  border-bottom-left-radius: 0;\n}\n\n.navbar-nav.pull-right > li > .dropdown-menu,\n.navbar-nav > li > .dropdown-menu.pull-right {\n  left: auto;\n  right: 0;\n}\n\n.navbar-btn {\n  margin-top: 8px;\n  margin-bottom: 8px;\n}\n\n.navbar-text {\n  float: left;\n  margin-top: 15px;\n  margin-bottom: 15px;\n}\n@media (min-width: 768px) {\n  .navbar-text {\n    margin-left: 15px;\n    margin-right: 15px;\n  }\n}\n\n.navbar-default {\n  background-color: #f8f8f8;\n  border-color: #e7e7e7;\n}\n.navbar-default .navbar-brand {\n  color: #777777;\n}\n.navbar-default .navbar-brand:hover, .navbar-default .navbar-brand:focus {\n  color: #5e5e5e;\n  background-color: transparent;\n}\n.navbar-default .navbar-text {\n  color: #777777;\n}\n.navbar-default .navbar-nav > li > a {\n  color: #777777;\n}\n.navbar-default .navbar-nav > li > a:hover, .navbar-default .navbar-nav > li > a:focus {\n  color: #333333;\n  background-color: transparent;\n}\n.navbar-default .navbar-nav > .active > a, .navbar-default .navbar-nav > .active > a:hover, .navbar-default .navbar-nav > .active > a:focus {\n  color: #555555;\n  background-color: #e7e7e7;\n}\n.navbar-default .navbar-nav > .disabled > a, .navbar-default .navbar-nav > .disabled > a:hover, .navbar-default .navbar-nav > .disabled > a:focus {\n  color: #cccccc;\n  background-color: transparent;\n}\n.navbar-default .navbar-toggle {\n  border-color: #dddddd;\n}\n.navbar-default .navbar-toggle:hover, .navbar-default .navbar-toggle:focus {\n  background-color: #dddddd;\n}\n.navbar-default .navbar-toggle .icon-bar {\n  background-color: #cccccc;\n}\n.navbar-default .navbar-collapse,\n.navbar-default .navbar-form {\n  border-color: #e6e6e6;\n}\n.navbar-default .navbar-nav > .dropdown > a:hover .caret,\n.navbar-default .navbar-nav > .dropdown > a:focus .caret {\n  border-top-color: #333333;\n  border-bottom-color: #333333;\n}\n.navbar-default .navbar-nav > .open > a, .navbar-default .navbar-nav > .open > a:hover, .navbar-default .navbar-nav > .open > a:focus {\n  background-color: #e7e7e7;\n  color: #555555;\n}\n.navbar-default .navbar-nav > .open > a .caret, .navbar-default .navbar-nav > .open > a:hover .caret, .navbar-default .navbar-nav > .open > a:focus .caret {\n  border-top-color: #555555;\n  border-bottom-color: #555555;\n}\n.navbar-default .navbar-nav > .dropdown > a .caret {\n  border-top-color: #777777;\n  border-bottom-color: #777777;\n}\n@media (max-width: 767px) {\n  .navbar-default .navbar-nav .open .dropdown-menu > li > a {\n    color: #777777;\n  }\n  .navbar-default .navbar-nav .open .dropdown-menu > li > a:hover, .navbar-default .navbar-nav .open .dropdown-menu > li > a:focus {\n    color: #333333;\n    background-color: transparent;\n  }\n  .navbar-default .navbar-nav .open .dropdown-menu > .active > a, .navbar-default .navbar-nav .open .dropdown-menu > .active > a:hover, .navbar-default .navbar-nav .open .dropdown-menu > .active > a:focus {\n    color: #555555;\n    background-color: #e7e7e7;\n  }\n  .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a, .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:hover, .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:focus {\n    color: #cccccc;\n    background-color: transparent;\n  }\n}\n.navbar-default .navbar-link {\n  color: #777777;\n}\n.navbar-default .navbar-link:hover {\n  color: #333333;\n}\n\n.navbar-inverse {\n  background-color: #222222;\n  border-color: #090909;\n}\n.navbar-inverse .navbar-brand {\n  color: #999999;\n}\n.navbar-inverse .navbar-brand:hover, .navbar-inverse .navbar-brand:focus {\n  color: white;\n  background-color: transparent;\n}\n.navbar-inverse .navbar-text {\n  color: #999999;\n}\n.navbar-inverse .navbar-nav > li > a {\n  color: #999999;\n}\n.navbar-inverse .navbar-nav > li > a:hover, .navbar-inverse .navbar-nav > li > a:focus {\n  color: white;\n  background-color: transparent;\n}\n.navbar-inverse .navbar-nav > .active > a, .navbar-inverse .navbar-nav > .active > a:hover, .navbar-inverse .navbar-nav > .active > a:focus {\n  color: white;\n  background-color: #090909;\n}\n.navbar-inverse .navbar-nav > .disabled > a, .navbar-inverse .navbar-nav > .disabled > a:hover, .navbar-inverse .navbar-nav > .disabled > a:focus {\n  color: #444444;\n  background-color: transparent;\n}\n.navbar-inverse .navbar-toggle {\n  border-color: #333333;\n}\n.navbar-inverse .navbar-toggle:hover, .navbar-inverse .navbar-toggle:focus {\n  background-color: #333333;\n}\n.navbar-inverse .navbar-toggle .icon-bar {\n  background-color: white;\n}\n.navbar-inverse .navbar-collapse,\n.navbar-inverse .navbar-form {\n  border-color: #101010;\n}\n.navbar-inverse .navbar-nav > .open > a, .navbar-inverse .navbar-nav > .open > a:hover, .navbar-inverse .navbar-nav > .open > a:focus {\n  background-color: #090909;\n  color: white;\n}\n.navbar-inverse .navbar-nav > .dropdown > a:hover .caret {\n  border-top-color: white;\n  border-bottom-color: white;\n}\n.navbar-inverse .navbar-nav > .dropdown > a .caret {\n  border-top-color: #999999;\n  border-bottom-color: #999999;\n}\n.navbar-inverse .navbar-nav > .open > a .caret, .navbar-inverse .navbar-nav > .open > a:hover .caret, .navbar-inverse .navbar-nav > .open > a:focus .caret {\n  border-top-color: white;\n  border-bottom-color: white;\n}\n@media (max-width: 767px) {\n  .navbar-inverse .navbar-nav .open .dropdown-menu > .dropdown-header {\n    border-color: #090909;\n  }\n  .navbar-inverse .navbar-nav .open .dropdown-menu > li > a {\n    color: #999999;\n  }\n  .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:hover, .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:focus {\n    color: white;\n    background-color: transparent;\n  }\n  .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a, .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:hover, .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:focus {\n    color: white;\n    background-color: #090909;\n  }\n  .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a, .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:hover, .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:focus {\n    color: #444444;\n    background-color: transparent;\n  }\n}\n.navbar-inverse .navbar-link {\n  color: #999999;\n}\n.navbar-inverse .navbar-link:hover {\n  color: white;\n}\n\n.breadcrumb {\n  padding: 8px 15px;\n  margin-bottom: 20px;\n  list-style: none;\n  background-color: whitesmoke;\n  border-radius: 4px;\n}\n.breadcrumb > li {\n  display: inline-block;\n}\n.breadcrumb > li + li:before {\n  content: \"/\\00a0\";\n  padding: 0 5px;\n  color: #cccccc;\n}\n.breadcrumb > .active {\n  color: #999999;\n}\n\n.pagination {\n  display: inline-block;\n  padding-left: 0;\n  margin: 20px 0;\n  border-radius: 4px;\n}\n.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  line-height: 1.428571429;\n  text-decoration: none;\n  background-color: white;\n  border: 1px solid #dddddd;\n  margin-left: -1px;\n}\n.pagination > li:first-child > a,\n.pagination > li:first-child > span {\n  margin-left: 0;\n  border-bottom-left-radius: 4px;\n  border-top-left-radius: 4px;\n}\n.pagination > li:last-child > a,\n.pagination > li:last-child > span {\n  border-bottom-right-radius: 4px;\n  border-top-right-radius: 4px;\n}\n.pagination > li > a:hover, .pagination > li > a:focus,\n.pagination > li > span:hover,\n.pagination > li > span:focus {\n  background-color: #eeeeee;\n}\n.pagination > .active > a, .pagination > .active > a:hover, .pagination > .active > a:focus,\n.pagination > .active > span,\n.pagination > .active > span:hover,\n.pagination > .active > span:focus {\n  z-index: 2;\n  color: white;\n  background-color: #428bca;\n  border-color: #428bca;\n  cursor: default;\n}\n.pagination > .disabled > span,\n.pagination > .disabled > a,\n.pagination > .disabled > a:hover,\n.pagination > .disabled > a:focus {\n  color: #999999;\n  background-color: white;\n  border-color: #dddddd;\n  cursor: not-allowed;\n}\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-bottom-left-radius: 6px;\n  border-top-left-radius: 6px;\n}\n.pagination-lg > li:last-child > a,\n.pagination-lg > li:last-child > span {\n  border-bottom-right-radius: 6px;\n  border-top-right-radius: 6px;\n}\n\n.pagination-sm > li > a,\n.pagination-sm > li > span {\n  padding: 5px 10px;\n  font-size: 12px;\n}\n.pagination-sm > li:first-child > a,\n.pagination-sm > li:first-child > span {\n  border-bottom-left-radius: 3px;\n  border-top-left-radius: 3px;\n}\n.pagination-sm > li:last-child > a,\n.pagination-sm > li:last-child > span {\n  border-bottom-right-radius: 3px;\n  border-top-right-radius: 3px;\n}\n\n.pager {\n  padding-left: 0;\n  margin: 20px 0;\n  list-style: none;\n  text-align: center;\n}\n.pager:before, .pager:after {\n  content: \" \";\n  /* 1 */\n  display: table;\n  /* 2 */\n}\n.pager:after {\n  clear: both;\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: white;\n  border: 1px solid #dddddd;\n  border-radius: 15px;\n}\n.pager li > a:hover,\n.pager li > a:focus {\n  text-decoration: none;\n  background-color: #eeeeee;\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: #999999;\n  background-color: white;\n  cursor: not-allowed;\n}\n\n.label {\n  display: inline;\n  padding: .2em .6em .3em;\n  font-size: 75%;\n  font-weight: bold;\n  line-height: 1;\n  color: white;\n  text-align: center;\n  white-space: nowrap;\n  vertical-align: baseline;\n  border-radius: .25em;\n}\n.label[href]:hover, .label[href]:focus {\n  color: white;\n  text-decoration: none;\n  cursor: pointer;\n}\n.label:empty {\n  display: none;\n}\n\n.label-default {\n  background-color: #999999;\n}\n.label-default[href]:hover, .label-default[href]:focus {\n  background-color: gray;\n}\n\n.label-primary {\n  background-color: #428bca;\n}\n.label-primary[href]:hover, .label-primary[href]:focus {\n  background-color: #3071a9;\n}\n\n.label-success {\n  background-color: #5cb85c;\n}\n.label-success[href]:hover, .label-success[href]:focus {\n  background-color: #449d44;\n}\n\n.label-info {\n  background-color: #5bc0de;\n}\n.label-info[href]:hover, .label-info[href]:focus {\n  background-color: #31b0d5;\n}\n\n.label-warning {\n  background-color: #f0ad4e;\n}\n.label-warning[href]:hover, .label-warning[href]:focus {\n  background-color: #ec971f;\n}\n\n.label-danger {\n  background-color: #d9534f;\n}\n.label-danger[href]:hover, .label-danger[href]:focus {\n  background-color: #c9302c;\n}\n\n.badge {\n  display: inline-block;\n  min-width: 10px;\n  padding: 3px 7px;\n  font-size: 12px;\n  font-weight: bold;\n  color: white;\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.badge:empty {\n  display: none;\n}\n\na.badge:hover, a.badge:focus {\n  color: white;\n  text-decoration: none;\n  cursor: pointer;\n}\n\n.btn .badge {\n  position: relative;\n  top: -1px;\n}\n\na.list-group-item.active > .badge,\n.nav-pills > .active > a > .badge {\n  color: #428bca;\n  background-color: white;\n}\n\n.nav-pills > li > a > .badge {\n  margin-left: 3px;\n}\n\n.jumbotron {\n  padding: 30px;\n  margin-bottom: 30px;\n  font-size: 21px;\n  font-weight: 200;\n  line-height: 2.1428571435;\n  color: inherit;\n  background-color: #eeeeee;\n}\n.jumbotron h1 {\n  line-height: 1;\n  color: inherit;\n}\n.jumbotron p {\n  line-height: 1.4;\n}\n.container .jumbotron {\n  border-radius: 6px;\n}\n@media screen and (min-width: 768px) {\n  .jumbotron {\n    padding-top: 48px;\n    padding-bottom: 48px;\n  }\n  .container .jumbotron {\n    padding-left: 60px;\n    padding-right: 60px;\n  }\n  .jumbotron h1 {\n    font-size: 63px;\n  }\n}\n\n.thumbnail {\n  display: block;\n}\n.thumbnail > img {\n  display: block;\n  max-width: 100%;\n  height: auto;\n}\n\na.thumbnail:hover,\na.thumbnail:focus {\n  border-color: #428bca;\n}\n\n.thumbnail > img {\n  margin-left: auto;\n  margin-right: auto;\n}\n\n.thumbnail .caption {\n  padding: 9px;\n  color: #333333;\n}\n\n.alert {\n  padding: 15px;\n  margin-bottom: 20px;\n  border: 1px solid transparent;\n  border-radius: 4px;\n}\n.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\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\n.alert-success {\n  background-color: #dff0d8;\n  border-color: #d6e9c6;\n  color: #468847;\n}\n.alert-success hr {\n  border-top-color: #c9e2b3;\n}\n.alert-success .alert-link {\n  color: #356635;\n}\n\n.alert-info {\n  background-color: #d9edf7;\n  border-color: #bce8f1;\n  color: #3a87ad;\n}\n.alert-info hr {\n  border-top-color: #a6e1ec;\n}\n.alert-info .alert-link {\n  color: #2d6987;\n}\n\n.alert-warning {\n  background-color: #fcf8e3;\n  border-color: #fbeed5;\n  color: #c09853;\n}\n.alert-warning hr {\n  border-top-color: #f8e5be;\n}\n.alert-warning .alert-link {\n  color: #a47e3c;\n}\n\n.alert-danger {\n  background-color: #f2dede;\n  border-color: #eed3d7;\n  color: #b94a48;\n}\n.alert-danger hr {\n  border-top-color: #e6c1c7;\n}\n.alert-danger .alert-link {\n  color: #953b39;\n}\n\n@-webkit-keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n\n  to {\n    background-position: 0 0;\n  }\n}\n\n@-moz-keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n\n  to {\n    background-position: 0 0;\n  }\n}\n\n@-o-keyframes progress-bar-stripes {\n  from {\n    background-position: 0 0;\n  }\n\n  to {\n    background-position: 40px 0;\n  }\n}\n\n@keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n\n  to {\n    background-position: 0 0;\n  }\n}\n\n.progress {\n  overflow: hidden;\n  height: 20px;\n  margin-bottom: 20px;\n  background-color: whitesmoke;\n  border-radius: 4px;\n  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n  box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n}\n\n.progress-bar {\n  float: left;\n  width: 0%;\n  height: 100%;\n  font-size: 12px;\n  color: white;\n  text-align: center;\n  background-color: #428bca;\n  -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n  box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n  -webkit-transition: width 0.6s ease;\n  transition: width 0.6s ease;\n}\n\n.progress-striped .progress-bar {\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-size: 40px 40px;\n}\n\n.progress.active .progress-bar {\n  -webkit-animation: progress-bar-stripes 2s linear infinite;\n  -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\n.progress-bar-success {\n  background-color: #5cb85c;\n}\n.progress-striped .progress-bar-success {\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.progress-bar-info {\n  background-color: #5bc0de;\n}\n.progress-striped .progress-bar-info {\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.progress-bar-warning {\n  background-color: #f0ad4e;\n}\n.progress-striped .progress-bar-warning {\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.progress-bar-danger {\n  background-color: #d9534f;\n}\n.progress-striped .progress-bar-danger {\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.media,\n.media-body {\n  overflow: hidden;\n  zoom: 1;\n}\n\n.media,\n.media .media {\n  margin-top: 15px;\n}\n\n.media:first-child {\n  margin-top: 0;\n}\n\n.media-object {\n  display: block;\n}\n\n.media-heading {\n  margin: 0 0 5px;\n}\n\n.media > .pull-left {\n  margin-right: 10px;\n}\n.media > .pull-right {\n  margin-left: 10px;\n}\n\n.media-list {\n  padding-left: 0;\n  list-style: none;\n}\n\n.list-group {\n  margin-bottom: 20px;\n  padding-left: 0;\n}\n\n.list-group-item {\n  position: relative;\n  display: block;\n  padding: 10px 15px;\n  margin-bottom: -1px;\n  background-color: white;\n  border: 1px solid #dddddd;\n}\n.list-group-item:first-child {\n  border-top-right-radius: 4px;\n  border-top-left-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}\n.list-group-item.active, .list-group-item.active:hover, .list-group-item.active:focus {\n  z-index: 2;\n  color: white;\n  background-color: #428bca;\n  border-color: #428bca;\n}\n.list-group-item.active .list-group-item-heading, .list-group-item.active:hover .list-group-item-heading, .list-group-item.active:focus .list-group-item-heading {\n  color: inherit;\n}\n.list-group-item.active .list-group-item-text, .list-group-item.active:hover .list-group-item-text, .list-group-item.active:focus .list-group-item-text {\n  color: #e1edf7;\n}\n\na.list-group-item {\n  color: #555555;\n}\na.list-group-item .list-group-item-heading {\n  color: #333333;\n}\na.list-group-item:hover, a.list-group-item:focus {\n  text-decoration: none;\n  background-color: whitesmoke;\n}\n\n.list-group-item-heading {\n  margin-top: 0;\n  margin-bottom: 5px;\n}\n\n.list-group-item-text {\n  margin-bottom: 0;\n  line-height: 1.3;\n}\n\n.panel {\n  margin-bottom: 20px;\n  background-color: white;\n  border: 1px solid transparent;\n  border-radius: 4px;\n  -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05);\n  box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05);\n}\n\n.panel-body {\n  padding: 15px;\n}\n.panel-body:before, .panel-body:after {\n  content: \" \";\n  /* 1 */\n  display: table;\n  /* 2 */\n}\n.panel-body:after {\n  clear: both;\n}\n\n.panel > .list-group {\n  margin-bottom: 0;\n}\n.panel > .list-group .list-group-item {\n  border-width: 1px 0;\n}\n.panel > .list-group .list-group-item:first-child {\n  border-top-right-radius: 0;\n  border-top-left-radius: 0;\n}\n.panel > .list-group .list-group-item:last-child {\n  border-bottom: 0;\n}\n\n.panel-heading + .list-group .list-group-item:first-child {\n  border-top-width: 0;\n}\n\n.panel > .table {\n  margin-bottom: 0;\n}\n.panel > .panel-body + .table {\n  border-top: 1px solid #dddddd;\n}\n\n.panel-heading {\n  padding: 10px 15px;\n  border-bottom: 1px solid transparent;\n  border-top-right-radius: 3px;\n  border-top-left-radius: 3px;\n}\n\n.panel-title {\n  margin-top: 0;\n  margin-bottom: 0;\n  font-size: 16px;\n}\n.panel-title > a {\n  color: inherit;\n}\n\n.panel-footer {\n  padding: 10px 15px;\n  background-color: whitesmoke;\n  border-top: 1px solid #dddddd;\n  border-bottom-right-radius: 3px;\n  border-bottom-left-radius: 3px;\n}\n\n.panel-group .panel {\n  margin-bottom: 0;\n  border-radius: 4px;\n  overflow: hidden;\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 #dddddd;\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 #dddddd;\n}\n\n.panel-default {\n  border-color: #dddddd;\n}\n.panel-default > .panel-heading {\n  color: #333333;\n  background-color: whitesmoke;\n  border-color: #dddddd;\n}\n.panel-default > .panel-heading + .panel-collapse .panel-body {\n  border-top-color: #dddddd;\n}\n.panel-default > .panel-footer + .panel-collapse .panel-body {\n  border-bottom-color: #dddddd;\n}\n\n.panel-primary {\n  border-color: #428bca;\n}\n.panel-primary > .panel-heading {\n  color: white;\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\n.panel-success {\n  border-color: #d6e9c6;\n}\n.panel-success > .panel-heading {\n  color: #468847;\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\n.panel-warning {\n  border-color: #fbeed5;\n}\n.panel-warning > .panel-heading {\n  color: #c09853;\n  background-color: #fcf8e3;\n  border-color: #fbeed5;\n}\n.panel-warning > .panel-heading + .panel-collapse .panel-body {\n  border-top-color: #fbeed5;\n}\n.panel-warning > .panel-footer + .panel-collapse .panel-body {\n  border-bottom-color: #fbeed5;\n}\n\n.panel-danger {\n  border-color: #eed3d7;\n}\n.panel-danger > .panel-heading {\n  color: #b94a48;\n  background-color: #f2dede;\n  border-color: #eed3d7;\n}\n.panel-danger > .panel-heading + .panel-collapse .panel-body {\n  border-top-color: #eed3d7;\n}\n.panel-danger > .panel-footer + .panel-collapse .panel-body {\n  border-bottom-color: #eed3d7;\n}\n\n.panel-info {\n  border-color: #bce8f1;\n}\n.panel-info > .panel-heading {\n  color: #3a87ad;\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\n.well {\n  min-height: 20px;\n  padding: 19px;\n  margin-bottom: 20px;\n  background-color: whitesmoke;\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.well blockquote {\n  border-color: #ddd;\n  border-color: rgba(0, 0, 0, 0.15);\n}\n\n.well-lg {\n  padding: 24px;\n  border-radius: 6px;\n}\n\n.well-sm {\n  padding: 9px;\n  border-radius: 3px;\n}\n\n.close {\n  float: right;\n  font-size: 21px;\n  font-weight: bold;\n  line-height: 1;\n  color: black;\n  text-shadow: 0 1px 0 white;\n  opacity: 0.2;\n  filter: alpha(opacity=20);\n}\n.close:hover, .close:focus {\n  color: black;\n  text-decoration: none;\n  cursor: pointer;\n  opacity: 0.5;\n  filter: alpha(opacity=50);\n}\n\nbutton.close {\n  padding: 0;\n  cursor: pointer;\n  background: transparent;\n  border: 0;\n  -webkit-appearance: none;\n}\n\n.modal-open {\n  overflow: hidden;\n}\n.modal-open .navbar-fixed-top,\n.modal-open .navbar-fixed-bottom {\n  margin-right: 15px;\n}\n\nbody.modal-open {\n  margin-right: 15px;\n}\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\n.modal-dialog {\n  margin-left: auto;\n  margin-right: auto;\n  width: auto;\n  padding: 10px;\n  z-index: 1050;\n}\n\n.modal-content {\n  position: relative;\n  background-color: white;\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\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: black;\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\n.modal-header {\n  padding: 15px;\n  border-bottom: 1px solid #e5e5e5;\n  min-height: 16.428571429px;\n}\n\n.modal-header .close {\n  margin-top: -2px;\n}\n\n.modal-title {\n  margin: 0;\n  line-height: 1.428571429;\n}\n\n.modal-body {\n  position: relative;\n  padding: 20px;\n}\n\n.modal-footer {\n  margin-top: 15px;\n  padding: 19px 20px 20px;\n  text-align: right;\n  border-top: 1px solid #e5e5e5;\n}\n.modal-footer:before, .modal-footer:after {\n  content: \" \";\n  /* 1 */\n  display: table;\n  /* 2 */\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\n@media screen and (min-width: 768px) {\n  .modal-dialog {\n    left: 50%;\n    right: auto;\n    width: 600px;\n    padding-top: 30px;\n    padding-bottom: 30px;\n  }\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\n.tooltip-inner {\n  max-width: 200px;\n  padding: 3px 8px;\n  color: white;\n  text-align: center;\n  text-decoration: none;\n  background-color: black;\n  border-radius: 4px;\n}\n\n.tooltip-arrow {\n  position: absolute;\n  width: 0;\n  height: 0;\n  border-color: transparent;\n  border-style: solid;\n}\n\n.tooltip.top .tooltip-arrow {\n  bottom: 0;\n  left: 50%;\n  margin-left: -5px;\n  border-width: 5px 5px 0;\n  border-top-color: black;\n}\n.tooltip.top-left .tooltip-arrow {\n  bottom: 0;\n  left: 5px;\n  border-width: 5px 5px 0;\n  border-top-color: black;\n}\n.tooltip.top-right .tooltip-arrow {\n  bottom: 0;\n  right: 5px;\n  border-width: 5px 5px 0;\n  border-top-color: black;\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: black;\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: black;\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: black;\n}\n.tooltip.bottom-left .tooltip-arrow {\n  top: 0;\n  left: 5px;\n  border-width: 0 5px 5px;\n  border-bottom-color: black;\n}\n.tooltip.bottom-right .tooltip-arrow {\n  top: 0;\n  right: 5px;\n  border-width: 0 5px 5px;\n  border-bottom-color: black;\n}\n\n.popover {\n  position: absolute;\n  top: 0;\n  left: 0;\n  z-index: 1010;\n  display: none;\n  max-width: 276px;\n  padding: 1px;\n  text-align: left;\n  background-color: white;\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\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\n.popover-content {\n  padding: 9px 14px;\n}\n\n.popover .arrow, .popover .arrow:after {\n  position: absolute;\n  display: block;\n  width: 0;\n  height: 0;\n  border-color: transparent;\n  border-style: solid;\n}\n\n.popover .arrow {\n  border-width: 11px;\n}\n\n.popover .arrow:after {\n  border-width: 10px;\n  content: \"\";\n}\n\n.popover.top .arrow {\n  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: white;\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: white;\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: white;\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: white;\n  bottom: -10px;\n}\n\n.carousel {\n  position: relative;\n}\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\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: white;\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, .carousel-control:focus {\n  color: white;\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  left: 50%;\n  z-index: 5;\n  display: inline-block;\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\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 white;\n  border-radius: 10px;\n  cursor: pointer;\n}\n.carousel-indicators .active {\n  margin: 0;\n  width: 12px;\n  height: 12px;\n  background-color: white;\n}\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: white;\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\n@media screen and (min-width: 768px) {\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\n  .carousel-caption {\n    left: 20%;\n    right: 20%;\n    padding-bottom: 30px;\n  }\n\n  .carousel-indicators {\n    bottom: 20px;\n  }\n}\n.clearfix:before, .clearfix:after {\n  content: \" \";\n  /* 1 */\n  display: table;\n  /* 2 */\n}\n.clearfix:after {\n  clear: both;\n}\n\n.pull-right {\n  float: right !important;\n}\n\n.pull-left {\n  float: left !important;\n}\n\n.hide {\n  display: none !important;\n}\n\n.show {\n  display: block !important;\n}\n\n.invisible {\n  visibility: hidden;\n}\n\n.text-hide {\n  font: 0/0 a;\n  color: transparent;\n  text-shadow: none;\n  background-color: transparent;\n  border: 0;\n}\n\n.affix {\n  position: fixed;\n}\n\n@-ms-viewport {\n  width: device-width;\n}\n\n@media screen and (max-width: 400px) {\n  @-ms-viewport {\n    width: 320px;\n}\n}\n.hidden {\n  display: none !important;\n  visibility: hidden !important;\n}\n\n.visible-xs {\n  display: none !important;\n}\n\ntr.visible-xs {\n  display: none !important;\n}\n\nth.visible-xs,\ntd.visible-xs {\n  display: none !important;\n}\n\n@media (max-width: 767px) {\n  .visible-xs {\n    display: block !important;\n  }\n\n  tr.visible-xs {\n    display: table-row !important;\n  }\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\n  tr.visible-xs.visible-sm {\n    display: table-row !important;\n  }\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\n  tr.visible-xs.visible-md {\n    display: table-row !important;\n  }\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\n  tr.visible-xs.visible-lg {\n    display: table-row !important;\n  }\n\n  th.visible-xs.visible-lg,\n  td.visible-xs.visible-lg {\n    display: table-cell !important;\n  }\n}\n.visible-sm {\n  display: none !important;\n}\n\ntr.visible-sm {\n  display: none !important;\n}\n\nth.visible-sm,\ntd.visible-sm {\n  display: none !important;\n}\n\n@media (max-width: 767px) {\n  .visible-sm.visible-xs {\n    display: block !important;\n  }\n\n  tr.visible-sm.visible-xs {\n    display: table-row !important;\n  }\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\n  tr.visible-sm {\n    display: table-row !important;\n  }\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\n  tr.visible-sm.visible-md {\n    display: table-row !important;\n  }\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\n  tr.visible-sm.visible-lg {\n    display: table-row !important;\n  }\n\n  th.visible-sm.visible-lg,\n  td.visible-sm.visible-lg {\n    display: table-cell !important;\n  }\n}\n.visible-md {\n  display: none !important;\n}\n\ntr.visible-md {\n  display: none !important;\n}\n\nth.visible-md,\ntd.visible-md {\n  display: none !important;\n}\n\n@media (max-width: 767px) {\n  .visible-md.visible-xs {\n    display: block !important;\n  }\n\n  tr.visible-md.visible-xs {\n    display: table-row !important;\n  }\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\n  tr.visible-md.visible-sm {\n    display: table-row !important;\n  }\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\n  tr.visible-md {\n    display: table-row !important;\n  }\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\n  tr.visible-md.visible-lg {\n    display: table-row !important;\n  }\n\n  th.visible-md.visible-lg,\n  td.visible-md.visible-lg {\n    display: table-cell !important;\n  }\n}\n.visible-lg {\n  display: none !important;\n}\n\ntr.visible-lg {\n  display: none !important;\n}\n\nth.visible-lg,\ntd.visible-lg {\n  display: none !important;\n}\n\n@media (max-width: 767px) {\n  .visible-lg.visible-xs {\n    display: block !important;\n  }\n\n  tr.visible-lg.visible-xs {\n    display: table-row !important;\n  }\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\n  tr.visible-lg.visible-sm {\n    display: table-row !important;\n  }\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\n  tr.visible-lg.visible-md {\n    display: table-row !important;\n  }\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\n  tr.visible-lg {\n    display: table-row !important;\n  }\n\n  th.visible-lg,\n  td.visible-lg {\n    display: table-cell !important;\n  }\n}\n.hidden-xs {\n  display: block !important;\n}\n\ntr.hidden-xs {\n  display: table-row !important;\n}\n\nth.hidden-xs,\ntd.hidden-xs {\n  display: table-cell !important;\n}\n\n@media (max-width: 767px) {\n  .hidden-xs {\n    display: none !important;\n  }\n\n  tr.hidden-xs {\n    display: none !important;\n  }\n\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    display: none !important;\n  }\n\n  tr.hidden-xs.hidden-sm {\n    display: none !important;\n  }\n\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    display: none !important;\n  }\n\n  tr.hidden-xs.hidden-md {\n    display: none !important;\n  }\n\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    display: none !important;\n  }\n\n  tr.hidden-xs.hidden-lg {\n    display: none !important;\n  }\n\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}\n\ntr.hidden-sm {\n  display: table-row !important;\n}\n\nth.hidden-sm,\ntd.hidden-sm {\n  display: table-cell !important;\n}\n\n@media (max-width: 767px) {\n  .hidden-sm.hidden-xs {\n    display: none !important;\n  }\n\n  tr.hidden-sm.hidden-xs {\n    display: none !important;\n  }\n\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    display: none !important;\n  }\n\n  tr.hidden-sm {\n    display: none !important;\n  }\n\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    display: none !important;\n  }\n\n  tr.hidden-sm.hidden-md {\n    display: none !important;\n  }\n\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    display: none !important;\n  }\n\n  tr.hidden-sm.hidden-lg {\n    display: none !important;\n  }\n\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}\n\ntr.hidden-md {\n  display: table-row !important;\n}\n\nth.hidden-md,\ntd.hidden-md {\n  display: table-cell !important;\n}\n\n@media (max-width: 767px) {\n  .hidden-md.hidden-xs {\n    display: none !important;\n  }\n\n  tr.hidden-md.hidden-xs {\n    display: none !important;\n  }\n\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    display: none !important;\n  }\n\n  tr.hidden-md.hidden-sm {\n    display: none !important;\n  }\n\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    display: none !important;\n  }\n\n  tr.hidden-md {\n    display: none !important;\n  }\n\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    display: none !important;\n  }\n\n  tr.hidden-md.hidden-lg {\n    display: none !important;\n  }\n\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}\n\ntr.hidden-lg {\n  display: table-row !important;\n}\n\nth.hidden-lg,\ntd.hidden-lg {\n  display: table-cell !important;\n}\n\n@media (max-width: 767px) {\n  .hidden-lg.hidden-xs {\n    display: none !important;\n  }\n\n  tr.hidden-lg.hidden-xs {\n    display: none !important;\n  }\n\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    display: none !important;\n  }\n\n  tr.hidden-lg.hidden-sm {\n    display: none !important;\n  }\n\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    display: none !important;\n  }\n\n  tr.hidden-lg.hidden-md {\n    display: none !important;\n  }\n\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    display: none !important;\n  }\n\n  tr.hidden-lg {\n    display: none !important;\n  }\n\n  th.hidden-lg,\n  td.hidden-lg {\n    display: none !important;\n  }\n}\n.visible-print {\n  display: none !important;\n}\n\ntr.visible-print {\n  display: none !important;\n}\n\nth.visible-print,\ntd.visible-print {\n  display: none !important;\n}\n\n@media print {\n  .visible-print {\n    display: block !important;\n  }\n\n  tr.visible-print {\n    display: table-row !important;\n  }\n\n  th.visible-print,\n  td.visible-print {\n    display: table-cell !important;\n  }\n\n  .hidden-print {\n    display: none !important;\n  }\n\n  tr.hidden-print {\n    display: none !important;\n  }\n\n  th.hidden-print,\n  td.hidden-print {\n    display: none !important;\n  }\n}\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/sass-bootstrap/dist/js/bootstrap.js",
    "content": "/**\n* bootstrap.js v3.0.0 by @fat and @mdo\n* Copyright 2013 Twitter Inc.\n* http://www.apache.org/licenses/LICENSE-2.0\n*/\nif (!jQuery) { throw new Error(\"Bootstrap requires jQuery\") }\n\n/* ========================================================================\n * Bootstrap: transition.js v3.0.0\n * http://twbs.github.com/bootstrap/javascript.html#transitions\n * ========================================================================\n * Copyright 2013 Twitter, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n * ======================================================================== */\n\n\n+function ($) { \"use strict\";\n\n  // CSS TRANSITION SUPPORT (Shoutout: http://www.modernizr.com/)\n  // ============================================================\n\n  function transitionEnd() {\n    var el = document.createElement('bootstrap')\n\n    var transEndEventNames = {\n      'WebkitTransition' : 'webkitTransitionEnd'\n    , 'MozTransition'    : 'transitionend'\n    , 'OTransition'      : 'oTransitionEnd otransitionend'\n    , 'transition'       : 'transitionend'\n    }\n\n    for (var name in transEndEventNames) {\n      if (el.style[name] !== undefined) {\n        return { end: transEndEventNames[name] }\n      }\n    }\n  }\n\n  // http://blog.alexmaccaw.com/css-transitions\n  $.fn.emulateTransitionEnd = function (duration) {\n    var called = false, $el = this\n    $(this).one($.support.transition.end, function () { called = true })\n    var callback = function () { if (!called) $($el).trigger($.support.transition.end) }\n    setTimeout(callback, duration)\n    return this\n  }\n\n  $(function () {\n    $.support.transition = transitionEnd()\n  })\n\n}(window.jQuery);\n\n/* ========================================================================\n * Bootstrap: alert.js v3.0.0\n * http://twbs.github.com/bootstrap/javascript.html#alerts\n * ========================================================================\n * Copyright 2013 Twitter, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n * ======================================================================== */\n\n\n+function ($) { \"use strict\";\n\n  // ALERT CLASS DEFINITION\n  // ======================\n\n  var dismiss = '[data-dismiss=\"alert\"]'\n  var Alert   = function (el) {\n    $(el).on('click', dismiss, this.close)\n  }\n\n  Alert.prototype.close = function (e) {\n    var $this    = $(this)\n    var selector = $this.attr('data-target')\n\n    if (!selector) {\n      selector = $this.attr('href')\n      selector = selector && selector.replace(/.*(?=#[^\\s]*$)/, '') // strip for ie7\n    }\n\n    var $parent = $(selector)\n\n    if (e) e.preventDefault()\n\n    if (!$parent.length) {\n      $parent = $this.hasClass('alert') ? $this : $this.parent()\n    }\n\n    $parent.trigger(e = $.Event('close.bs.alert'))\n\n    if (e.isDefaultPrevented()) return\n\n    $parent.removeClass('in')\n\n    function removeElement() {\n      $parent.trigger('closed.bs.alert').remove()\n    }\n\n    $.support.transition && $parent.hasClass('fade') ?\n      $parent\n        .one($.support.transition.end, removeElement)\n        .emulateTransitionEnd(150) :\n      removeElement()\n  }\n\n\n  // ALERT PLUGIN DEFINITION\n  // =======================\n\n  var old = $.fn.alert\n\n  $.fn.alert = function (option) {\n    return this.each(function () {\n      var $this = $(this)\n      var data  = $this.data('bs.alert')\n\n      if (!data) $this.data('bs.alert', (data = new Alert(this)))\n      if (typeof option == 'string') data[option].call($this)\n    })\n  }\n\n  $.fn.alert.Constructor = Alert\n\n\n  // ALERT NO CONFLICT\n  // =================\n\n  $.fn.alert.noConflict = function () {\n    $.fn.alert = old\n    return this\n  }\n\n\n  // ALERT DATA-API\n  // ==============\n\n  $(document).on('click.bs.alert.data-api', dismiss, Alert.prototype.close)\n\n}(window.jQuery);\n\n/* ========================================================================\n * Bootstrap: button.js v3.0.0\n * http://twbs.github.com/bootstrap/javascript.html#buttons\n * ========================================================================\n * Copyright 2013 Twitter, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n * ======================================================================== */\n\n\n+function ($) { \"use strict\";\n\n  // BUTTON PUBLIC CLASS DEFINITION\n  // ==============================\n\n  var Button = function (element, options) {\n    this.$element = $(element)\n    this.options  = $.extend({}, Button.DEFAULTS, options)\n  }\n\n  Button.DEFAULTS = {\n    loadingText: 'loading...'\n  }\n\n  Button.prototype.setState = function (state) {\n    var d    = 'disabled'\n    var $el  = this.$element\n    var val  = $el.is('input') ? 'val' : 'html'\n    var data = $el.data()\n\n    state = state + 'Text'\n\n    if (!data.resetText) $el.data('resetText', $el[val]())\n\n    $el[val](data[state] || this.options[state])\n\n    // push to event loop to allow forms to submit\n    setTimeout(function () {\n      state == 'loadingText' ?\n        $el.addClass(d).attr(d, d) :\n        $el.removeClass(d).removeAttr(d);\n    }, 0)\n  }\n\n  Button.prototype.toggle = function () {\n    var $parent = this.$element.closest('[data-toggle=\"buttons\"]')\n\n    if ($parent.length) {\n      var $input = this.$element.find('input')\n        .prop('checked', !this.$element.hasClass('active'))\n        .trigger('change')\n      if ($input.prop('type') === 'radio') $parent.find('.active').removeClass('active')\n    }\n\n    this.$element.toggleClass('active')\n  }\n\n\n  // BUTTON PLUGIN DEFINITION\n  // ========================\n\n  var old = $.fn.button\n\n  $.fn.button = function (option) {\n    return this.each(function () {\n      var $this   = $(this)\n      var data    = $this.data('bs.button')\n      var options = typeof option == 'object' && option\n\n      if (!data) $this.data('bs.button', (data = new Button(this, options)))\n\n      if (option == 'toggle') data.toggle()\n      else if (option) data.setState(option)\n    })\n  }\n\n  $.fn.button.Constructor = Button\n\n\n  // BUTTON NO CONFLICT\n  // ==================\n\n  $.fn.button.noConflict = function () {\n    $.fn.button = old\n    return this\n  }\n\n\n  // BUTTON DATA-API\n  // ===============\n\n  $(document).on('click.bs.button.data-api', '[data-toggle^=button]', function (e) {\n    var $btn = $(e.target)\n    if (!$btn.hasClass('btn')) $btn = $btn.closest('.btn')\n    $btn.button('toggle')\n    e.preventDefault()\n  })\n\n}(window.jQuery);\n\n/* ========================================================================\n * Bootstrap: carousel.js v3.0.0\n * http://twbs.github.com/bootstrap/javascript.html#carousel\n * ========================================================================\n * Copyright 2012 Twitter, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n * ======================================================================== */\n\n\n+function ($) { \"use strict\";\n\n  // CAROUSEL CLASS DEFINITION\n  // =========================\n\n  var Carousel = function (element, options) {\n    this.$element    = $(element)\n    this.$indicators = this.$element.find('.carousel-indicators')\n    this.options     = options\n    this.paused      =\n    this.sliding     =\n    this.interval    =\n    this.$active     =\n    this.$items      = null\n\n    this.options.pause == 'hover' && this.$element\n      .on('mouseenter', $.proxy(this.pause, this))\n      .on('mouseleave', $.proxy(this.cycle, this))\n  }\n\n  Carousel.DEFAULTS = {\n    interval: 5000\n  , pause: 'hover'\n  , wrap: true\n  }\n\n  Carousel.prototype.cycle =  function (e) {\n    e || (this.paused = false)\n\n    this.interval && clearInterval(this.interval)\n\n    this.options.interval\n      && !this.paused\n      && (this.interval = setInterval($.proxy(this.next, this), this.options.interval))\n\n    return this\n  }\n\n  Carousel.prototype.getActiveIndex = function () {\n    this.$active = this.$element.find('.item.active')\n    this.$items  = this.$active.parent().children()\n\n    return this.$items.index(this.$active)\n  }\n\n  Carousel.prototype.to = function (pos) {\n    var that        = this\n    var activeIndex = this.getActiveIndex()\n\n    if (pos > (this.$items.length - 1) || pos < 0) return\n\n    if (this.sliding)       return this.$element.one('slid', function () { that.to(pos) })\n    if (activeIndex == pos) return this.pause().cycle()\n\n    return this.slide(pos > activeIndex ? 'next' : 'prev', $(this.$items[pos]))\n  }\n\n  Carousel.prototype.pause = function (e) {\n    e || (this.paused = true)\n\n    if (this.$element.find('.next, .prev').length && $.support.transition.end) {\n      this.$element.trigger($.support.transition.end)\n      this.cycle(true)\n    }\n\n    this.interval = clearInterval(this.interval)\n\n    return this\n  }\n\n  Carousel.prototype.next = function () {\n    if (this.sliding) return\n    return this.slide('next')\n  }\n\n  Carousel.prototype.prev = function () {\n    if (this.sliding) return\n    return this.slide('prev')\n  }\n\n  Carousel.prototype.slide = function (type, next) {\n    var $active   = this.$element.find('.item.active')\n    var $next     = next || $active[type]()\n    var isCycling = this.interval\n    var direction = type == 'next' ? 'left' : 'right'\n    var fallback  = type == 'next' ? 'first' : 'last'\n    var that      = this\n\n    if (!$next.length) {\n      if (!this.options.wrap) return\n      $next = this.$element.find('.item')[fallback]()\n    }\n\n    this.sliding = true\n\n    isCycling && this.pause()\n\n    var e = $.Event('slide.bs.carousel', { relatedTarget: $next[0], direction: direction })\n\n    if ($next.hasClass('active')) return\n\n    if (this.$indicators.length) {\n      this.$indicators.find('.active').removeClass('active')\n      this.$element.one('slid', function () {\n        var $nextIndicator = $(that.$indicators.children()[that.getActiveIndex()])\n        $nextIndicator && $nextIndicator.addClass('active')\n      })\n    }\n\n    if ($.support.transition && this.$element.hasClass('slide')) {\n      this.$element.trigger(e)\n      if (e.isDefaultPrevented()) return\n      $next.addClass(type)\n      $next[0].offsetWidth // force reflow\n      $active.addClass(direction)\n      $next.addClass(direction)\n      $active\n        .one($.support.transition.end, function () {\n          $next.removeClass([type, direction].join(' ')).addClass('active')\n          $active.removeClass(['active', direction].join(' '))\n          that.sliding = false\n          setTimeout(function () { that.$element.trigger('slid') }, 0)\n        })\n        .emulateTransitionEnd(600)\n    } else {\n      this.$element.trigger(e)\n      if (e.isDefaultPrevented()) return\n      $active.removeClass('active')\n      $next.addClass('active')\n      this.sliding = false\n      this.$element.trigger('slid')\n    }\n\n    isCycling && this.cycle()\n\n    return this\n  }\n\n\n  // CAROUSEL PLUGIN DEFINITION\n  // ==========================\n\n  var old = $.fn.carousel\n\n  $.fn.carousel = function (option) {\n    return this.each(function () {\n      var $this   = $(this)\n      var data    = $this.data('bs.carousel')\n      var options = $.extend({}, Carousel.DEFAULTS, $this.data(), typeof option == 'object' && option)\n      var action  = typeof option == 'string' ? option : options.slide\n\n      if (!data) $this.data('bs.carousel', (data = new Carousel(this, options)))\n      if (typeof option == 'number') data.to(option)\n      else if (action) data[action]()\n      else if (options.interval) data.pause().cycle()\n    })\n  }\n\n  $.fn.carousel.Constructor = Carousel\n\n\n  // CAROUSEL NO CONFLICT\n  // ====================\n\n  $.fn.carousel.noConflict = function () {\n    $.fn.carousel = old\n    return this\n  }\n\n\n  // CAROUSEL DATA-API\n  // =================\n\n  $(document).on('click.bs.carousel.data-api', '[data-slide], [data-slide-to]', function (e) {\n    var $this   = $(this), href\n    var $target = $($this.attr('data-target') || (href = $this.attr('href')) && href.replace(/.*(?=#[^\\s]+$)/, '')) //strip for ie7\n    var options = $.extend({}, $target.data(), $this.data())\n    var slideIndex = $this.attr('data-slide-to')\n    if (slideIndex) options.interval = false\n\n    $target.carousel(options)\n\n    if (slideIndex = $this.attr('data-slide-to')) {\n      $target.data('bs.carousel').to(slideIndex)\n    }\n\n    e.preventDefault()\n  })\n\n  $(window).on('load', function () {\n    $('[data-ride=\"carousel\"]').each(function () {\n      var $carousel = $(this)\n      $carousel.carousel($carousel.data())\n    })\n  })\n\n}(window.jQuery);\n\n/* ========================================================================\n * Bootstrap: collapse.js v3.0.0\n * http://twbs.github.com/bootstrap/javascript.html#collapse\n * ========================================================================\n * Copyright 2012 Twitter, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n * ======================================================================== */\n\n\n+function ($) { \"use strict\";\n\n  // COLLAPSE PUBLIC CLASS DEFINITION\n  // ================================\n\n  var Collapse = function (element, options) {\n    this.$element      = $(element)\n    this.options       = $.extend({}, Collapse.DEFAULTS, options)\n    this.transitioning = null\n\n    if (this.options.parent) this.$parent = $(this.options.parent)\n    if (this.options.toggle) this.toggle()\n  }\n\n  Collapse.DEFAULTS = {\n    toggle: true\n  }\n\n  Collapse.prototype.dimension = function () {\n    var hasWidth = this.$element.hasClass('width')\n    return hasWidth ? 'width' : 'height'\n  }\n\n  Collapse.prototype.show = function () {\n    if (this.transitioning || this.$element.hasClass('in')) return\n\n    var startEvent = $.Event('show.bs.collapse')\n    this.$element.trigger(startEvent)\n    if (startEvent.isDefaultPrevented()) return\n\n    var actives = this.$parent && this.$parent.find('> .panel > .in')\n\n    if (actives && actives.length) {\n      var hasData = actives.data('bs.collapse')\n      if (hasData && hasData.transitioning) return\n      actives.collapse('hide')\n      hasData || actives.data('bs.collapse', null)\n    }\n\n    var dimension = this.dimension()\n\n    this.$element\n      .removeClass('collapse')\n      .addClass('collapsing')\n      [dimension](0)\n\n    this.transitioning = 1\n\n    var complete = function () {\n      this.$element\n        .removeClass('collapsing')\n        .addClass('in')\n        [dimension]('auto')\n      this.transitioning = 0\n      this.$element.trigger('shown.bs.collapse')\n    }\n\n    if (!$.support.transition) return complete.call(this)\n\n    var scrollSize = $.camelCase(['scroll', dimension].join('-'))\n\n    this.$element\n      .one($.support.transition.end, $.proxy(complete, this))\n      .emulateTransitionEnd(350)\n      [dimension](this.$element[0][scrollSize])\n  }\n\n  Collapse.prototype.hide = function () {\n    if (this.transitioning || !this.$element.hasClass('in')) return\n\n    var startEvent = $.Event('hide.bs.collapse')\n    this.$element.trigger(startEvent)\n    if (startEvent.isDefaultPrevented()) return\n\n    var dimension = this.dimension()\n\n    this.$element\n      [dimension](this.$element[dimension]())\n      [0].offsetHeight\n\n    this.$element\n      .addClass('collapsing')\n      .removeClass('collapse')\n      .removeClass('in')\n\n    this.transitioning = 1\n\n    var complete = function () {\n      this.transitioning = 0\n      this.$element\n        .trigger('hidden.bs.collapse')\n        .removeClass('collapsing')\n        .addClass('collapse')\n    }\n\n    if (!$.support.transition) return complete.call(this)\n\n    this.$element\n      [dimension](0)\n      .one($.support.transition.end, $.proxy(complete, this))\n      .emulateTransitionEnd(350)\n  }\n\n  Collapse.prototype.toggle = function () {\n    this[this.$element.hasClass('in') ? 'hide' : 'show']()\n  }\n\n\n  // COLLAPSE PLUGIN DEFINITION\n  // ==========================\n\n  var old = $.fn.collapse\n\n  $.fn.collapse = function (option) {\n    return this.each(function () {\n      var $this   = $(this)\n      var data    = $this.data('bs.collapse')\n      var options = $.extend({}, Collapse.DEFAULTS, $this.data(), typeof option == 'object' && option)\n\n      if (!data) $this.data('bs.collapse', (data = new Collapse(this, options)))\n      if (typeof option == 'string') data[option]()\n    })\n  }\n\n  $.fn.collapse.Constructor = Collapse\n\n\n  // COLLAPSE NO CONFLICT\n  // ====================\n\n  $.fn.collapse.noConflict = function () {\n    $.fn.collapse = old\n    return this\n  }\n\n\n  // COLLAPSE DATA-API\n  // =================\n\n  $(document).on('click.bs.collapse.data-api', '[data-toggle=collapse]', function (e) {\n    var $this   = $(this), href\n    var target  = $this.attr('data-target')\n        || e.preventDefault()\n        || (href = $this.attr('href')) && href.replace(/.*(?=#[^\\s]+$)/, '') //strip for ie7\n    var $target = $(target)\n    var data    = $target.data('bs.collapse')\n    var option  = data ? 'toggle' : $this.data()\n    var parent  = $this.attr('data-parent')\n    var $parent = parent && $(parent)\n\n    if (!data || !data.transitioning) {\n      if ($parent) $parent.find('[data-toggle=collapse][data-parent=\"' + parent + '\"]').not($this).addClass('collapsed')\n      $this[$target.hasClass('in') ? 'addClass' : 'removeClass']('collapsed')\n    }\n\n    $target.collapse(option)\n  })\n\n}(window.jQuery);\n\n/* ========================================================================\n * Bootstrap: dropdown.js v3.0.0\n * http://twbs.github.com/bootstrap/javascript.html#dropdowns\n * ========================================================================\n * Copyright 2012 Twitter, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n * ======================================================================== */\n\n\n+function ($) { \"use strict\";\n\n  // DROPDOWN CLASS DEFINITION\n  // =========================\n\n  var backdrop = '.dropdown-backdrop'\n  var toggle   = '[data-toggle=dropdown]'\n  var Dropdown = function (element) {\n    var $el = $(element).on('click.bs.dropdown', this.toggle)\n  }\n\n  Dropdown.prototype.toggle = function (e) {\n    var $this = $(this)\n\n    if ($this.is('.disabled, :disabled')) return\n\n    var $parent  = getParent($this)\n    var isActive = $parent.hasClass('open')\n\n    clearMenus()\n\n    if (!isActive) {\n      if ('ontouchstart' in document.documentElement && !$parent.closest('.navbar-nav').length) {\n        // if mobile we we use a backdrop because click events don't delegate\n        $('<div class=\"dropdown-backdrop\"/>').insertAfter($(this)).on('click', clearMenus)\n      }\n\n      $parent.trigger(e = $.Event('show.bs.dropdown'))\n\n      if (e.isDefaultPrevented()) return\n\n      $parent\n        .toggleClass('open')\n        .trigger('shown.bs.dropdown')\n\n      $this.focus()\n    }\n\n    return false\n  }\n\n  Dropdown.prototype.keydown = function (e) {\n    if (!/(38|40|27)/.test(e.keyCode)) return\n\n    var $this = $(this)\n\n    e.preventDefault()\n    e.stopPropagation()\n\n    if ($this.is('.disabled, :disabled')) return\n\n    var $parent  = getParent($this)\n    var isActive = $parent.hasClass('open')\n\n    if (!isActive || (isActive && e.keyCode == 27)) {\n      if (e.which == 27) $parent.find(toggle).focus()\n      return $this.click()\n    }\n\n    var $items = $('[role=menu] li:not(.divider):visible a', $parent)\n\n    if (!$items.length) return\n\n    var index = $items.index($items.filter(':focus'))\n\n    if (e.keyCode == 38 && index > 0)                 index--                        // up\n    if (e.keyCode == 40 && index < $items.length - 1) index++                        // down\n    if (!~index)                                      index=0\n\n    $items.eq(index).focus()\n  }\n\n  function clearMenus() {\n    $(backdrop).remove()\n    $(toggle).each(function (e) {\n      var $parent = getParent($(this))\n      if (!$parent.hasClass('open')) return\n      $parent.trigger(e = $.Event('hide.bs.dropdown'))\n      if (e.isDefaultPrevented()) return\n      $parent.removeClass('open').trigger('hidden.bs.dropdown')\n    })\n  }\n\n  function getParent($this) {\n    var selector = $this.attr('data-target')\n\n    if (!selector) {\n      selector = $this.attr('href')\n      selector = selector && /#/.test(selector) && selector.replace(/.*(?=#[^\\s]*$)/, '') //strip for ie7\n    }\n\n    var $parent = selector && $(selector)\n\n    return $parent && $parent.length ? $parent : $this.parent()\n  }\n\n\n  // DROPDOWN PLUGIN DEFINITION\n  // ==========================\n\n  var old = $.fn.dropdown\n\n  $.fn.dropdown = function (option) {\n    return this.each(function () {\n      var $this = $(this)\n      var data  = $this.data('dropdown')\n\n      if (!data) $this.data('dropdown', (data = new Dropdown(this)))\n      if (typeof option == 'string') data[option].call($this)\n    })\n  }\n\n  $.fn.dropdown.Constructor = Dropdown\n\n\n  // DROPDOWN NO CONFLICT\n  // ====================\n\n  $.fn.dropdown.noConflict = function () {\n    $.fn.dropdown = old\n    return this\n  }\n\n\n  // APPLY TO STANDARD DROPDOWN ELEMENTS\n  // ===================================\n\n  $(document)\n    .on('click.bs.dropdown.data-api', clearMenus)\n    .on('click.bs.dropdown.data-api', '.dropdown form', function (e) { e.stopPropagation() })\n    .on('click.bs.dropdown.data-api'  , toggle, Dropdown.prototype.toggle)\n    .on('keydown.bs.dropdown.data-api', toggle + ', [role=menu]' , Dropdown.prototype.keydown)\n\n}(window.jQuery);\n\n/* ========================================================================\n * Bootstrap: modal.js v3.0.0\n * http://twbs.github.com/bootstrap/javascript.html#modals\n * ========================================================================\n * Copyright 2012 Twitter, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n * ======================================================================== */\n\n\n+function ($) { \"use strict\";\n\n  // MODAL CLASS DEFINITION\n  // ======================\n\n  var Modal = function (element, options) {\n    this.options   = options\n    this.$element  = $(element)\n    this.$backdrop =\n    this.isShown   = null\n\n    if (this.options.remote) this.$element.load(this.options.remote)\n  }\n\n  Modal.DEFAULTS = {\n      backdrop: true\n    , keyboard: true\n    , show: true\n  }\n\n  Modal.prototype.toggle = function (_relatedTarget) {\n    return this[!this.isShown ? 'show' : 'hide'](_relatedTarget)\n  }\n\n  Modal.prototype.show = function (_relatedTarget) {\n    var that = this\n    var e    = $.Event('show.bs.modal', { relatedTarget: _relatedTarget })\n\n    this.$element.trigger(e)\n\n    if (this.isShown || e.isDefaultPrevented()) return\n\n    this.isShown = true\n\n    this.escape()\n\n    this.$element.on('click.dismiss.modal', '[data-dismiss=\"modal\"]', $.proxy(this.hide, this))\n\n    this.backdrop(function () {\n      var transition = $.support.transition && that.$element.hasClass('fade')\n\n      if (!that.$element.parent().length) {\n        that.$element.appendTo(document.body) // don't move modals dom position\n      }\n\n      that.$element.show()\n\n      if (transition) {\n        that.$element[0].offsetWidth // force reflow\n      }\n\n      that.$element\n        .addClass('in')\n        .attr('aria-hidden', false)\n\n      that.enforceFocus()\n\n      var e = $.Event('shown.bs.modal', { relatedTarget: _relatedTarget })\n\n      transition ?\n        that.$element.find('.modal-dialog') // wait for modal to slide in\n          .one($.support.transition.end, function () {\n            that.$element.focus().trigger(e)\n          })\n          .emulateTransitionEnd(300) :\n        that.$element.focus().trigger(e)\n    })\n  }\n\n  Modal.prototype.hide = function (e) {\n    if (e) e.preventDefault()\n\n    e = $.Event('hide.bs.modal')\n\n    this.$element.trigger(e)\n\n    if (!this.isShown || e.isDefaultPrevented()) return\n\n    this.isShown = false\n\n    this.escape()\n\n    $(document).off('focusin.bs.modal')\n\n    this.$element\n      .removeClass('in')\n      .attr('aria-hidden', true)\n      .off('click.dismiss.modal')\n\n    $.support.transition && this.$element.hasClass('fade') ?\n      this.$element\n        .one($.support.transition.end, $.proxy(this.hideModal, this))\n        .emulateTransitionEnd(300) :\n      this.hideModal()\n  }\n\n  Modal.prototype.enforceFocus = function () {\n    $(document)\n      .off('focusin.bs.modal') // guard against infinite focus loop\n      .on('focusin.bs.modal', $.proxy(function (e) {\n        if (this.$element[0] !== e.target && !this.$element.has(e.target).length) {\n          this.$element.focus()\n        }\n      }, this))\n  }\n\n  Modal.prototype.escape = function () {\n    if (this.isShown && this.options.keyboard) {\n      this.$element.on('keyup.dismiss.bs.modal', $.proxy(function (e) {\n        e.which == 27 && this.hide()\n      }, this))\n    } else if (!this.isShown) {\n      this.$element.off('keyup.dismiss.bs.modal')\n    }\n  }\n\n  Modal.prototype.hideModal = function () {\n    var that = this\n    this.$element.hide()\n    this.backdrop(function () {\n      that.removeBackdrop()\n      that.$element.trigger('hidden.bs.modal')\n    })\n  }\n\n  Modal.prototype.removeBackdrop = function () {\n    this.$backdrop && this.$backdrop.remove()\n    this.$backdrop = null\n  }\n\n  Modal.prototype.backdrop = function (callback) {\n    var that    = this\n    var animate = this.$element.hasClass('fade') ? 'fade' : ''\n\n    if (this.isShown && this.options.backdrop) {\n      var doAnimate = $.support.transition && animate\n\n      this.$backdrop = $('<div class=\"modal-backdrop ' + animate + '\" />')\n        .appendTo(document.body)\n\n      this.$element.on('click.dismiss.modal', $.proxy(function (e) {\n        if (e.target !== e.currentTarget) return\n        this.options.backdrop == 'static'\n          ? this.$element[0].focus.call(this.$element[0])\n          : this.hide.call(this)\n      }, this))\n\n      if (doAnimate) this.$backdrop[0].offsetWidth // force reflow\n\n      this.$backdrop.addClass('in')\n\n      if (!callback) return\n\n      doAnimate ?\n        this.$backdrop\n          .one($.support.transition.end, callback)\n          .emulateTransitionEnd(150) :\n        callback()\n\n    } else if (!this.isShown && this.$backdrop) {\n      this.$backdrop.removeClass('in')\n\n      $.support.transition && this.$element.hasClass('fade')?\n        this.$backdrop\n          .one($.support.transition.end, callback)\n          .emulateTransitionEnd(150) :\n        callback()\n\n    } else if (callback) {\n      callback()\n    }\n  }\n\n\n  // MODAL PLUGIN DEFINITION\n  // =======================\n\n  var old = $.fn.modal\n\n  $.fn.modal = function (option, _relatedTarget) {\n    return this.each(function () {\n      var $this   = $(this)\n      var data    = $this.data('bs.modal')\n      var options = $.extend({}, Modal.DEFAULTS, $this.data(), typeof option == 'object' && option)\n\n      if (!data) $this.data('bs.modal', (data = new Modal(this, options)))\n      if (typeof option == 'string') data[option](_relatedTarget)\n      else if (options.show) data.show(_relatedTarget)\n    })\n  }\n\n  $.fn.modal.Constructor = Modal\n\n\n  // MODAL NO CONFLICT\n  // =================\n\n  $.fn.modal.noConflict = function () {\n    $.fn.modal = old\n    return this\n  }\n\n\n  // MODAL DATA-API\n  // ==============\n\n  $(document).on('click.bs.modal.data-api', '[data-toggle=\"modal\"]', function (e) {\n    var $this   = $(this)\n    var href    = $this.attr('href')\n    var $target = $($this.attr('data-target') || (href && href.replace(/.*(?=#[^\\s]+$)/, ''))) //strip for ie7\n    var option  = $target.data('modal') ? 'toggle' : $.extend({ remote: !/#/.test(href) && href }, $target.data(), $this.data())\n\n    e.preventDefault()\n\n    $target\n      .modal(option, this)\n      .one('hide', function () {\n        $this.is(':visible') && $this.focus()\n      })\n  })\n\n  $(document)\n    .on('show.bs.modal',  '.modal', function () { $(document.body).addClass('modal-open') })\n    .on('hidden.bs.modal', '.modal', function () { $(document.body).removeClass('modal-open') })\n\n}(window.jQuery);\n\n/* ========================================================================\n * Bootstrap: tooltip.js v3.0.0\n * http://twbs.github.com/bootstrap/javascript.html#tooltip\n * Inspired by the original jQuery.tipsy by Jason Frame\n * ========================================================================\n * Copyright 2012 Twitter, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n * ======================================================================== */\n\n\n+function ($) { \"use strict\";\n\n  // TOOLTIP PUBLIC CLASS DEFINITION\n  // ===============================\n\n  var Tooltip = function (element, options) {\n    this.type       =\n    this.options    =\n    this.enabled    =\n    this.timeout    =\n    this.hoverState =\n    this.$element   = null\n\n    this.init('tooltip', element, options)\n  }\n\n  Tooltip.DEFAULTS = {\n    animation: true\n  , placement: 'top'\n  , selector: false\n  , template: '<div class=\"tooltip\"><div class=\"tooltip-arrow\"></div><div class=\"tooltip-inner\"></div></div>'\n  , trigger: 'hover focus'\n  , title: ''\n  , delay: 0\n  , html: false\n  , container: false\n  }\n\n  Tooltip.prototype.init = function (type, element, options) {\n    this.enabled  = true\n    this.type     = type\n    this.$element = $(element)\n    this.options  = this.getOptions(options)\n\n    var triggers = this.options.trigger.split(' ')\n\n    for (var i = triggers.length; i--;) {\n      var trigger = triggers[i]\n\n      if (trigger == 'click') {\n        this.$element.on('click.' + this.type, this.options.selector, $.proxy(this.toggle, this))\n      } else if (trigger != 'manual') {\n        var eventIn  = trigger == 'hover' ? 'mouseenter' : 'focus'\n        var eventOut = trigger == 'hover' ? 'mouseleave' : 'blur'\n\n        this.$element.on(eventIn  + '.' + this.type, this.options.selector, $.proxy(this.enter, this))\n        this.$element.on(eventOut + '.' + this.type, this.options.selector, $.proxy(this.leave, this))\n      }\n    }\n\n    this.options.selector ?\n      (this._options = $.extend({}, this.options, { trigger: 'manual', selector: '' })) :\n      this.fixTitle()\n  }\n\n  Tooltip.prototype.getDefaults = function () {\n    return Tooltip.DEFAULTS\n  }\n\n  Tooltip.prototype.getOptions = function (options) {\n    options = $.extend({}, this.getDefaults(), this.$element.data(), options)\n\n    if (options.delay && typeof options.delay == 'number') {\n      options.delay = {\n        show: options.delay\n      , hide: options.delay\n      }\n    }\n\n    return options\n  }\n\n  Tooltip.prototype.getDelegateOptions = function () {\n    var options  = {}\n    var defaults = this.getDefaults()\n\n    this._options && $.each(this._options, function (key, value) {\n      if (defaults[key] != value) options[key] = value\n    })\n\n    return options\n  }\n\n  Tooltip.prototype.enter = function (obj) {\n    var self = obj instanceof this.constructor ?\n      obj : $(obj.currentTarget)[this.type](this.getDelegateOptions()).data('bs.' + this.type)\n\n    clearTimeout(self.timeout)\n\n    self.hoverState = 'in'\n\n    if (!self.options.delay || !self.options.delay.show) return self.show()\n\n    self.timeout = setTimeout(function () {\n      if (self.hoverState == 'in') self.show()\n    }, self.options.delay.show)\n  }\n\n  Tooltip.prototype.leave = function (obj) {\n    var self = obj instanceof this.constructor ?\n      obj : $(obj.currentTarget)[this.type](this.getDelegateOptions()).data('bs.' + this.type)\n\n    clearTimeout(self.timeout)\n\n    self.hoverState = 'out'\n\n    if (!self.options.delay || !self.options.delay.hide) return self.hide()\n\n    self.timeout = setTimeout(function () {\n      if (self.hoverState == 'out') self.hide()\n    }, self.options.delay.hide)\n  }\n\n  Tooltip.prototype.show = function () {\n    var e = $.Event('show.bs.'+ this.type)\n\n    if (this.hasContent() && this.enabled) {\n      this.$element.trigger(e)\n\n      if (e.isDefaultPrevented()) return\n\n      var $tip = this.tip()\n\n      this.setContent()\n\n      if (this.options.animation) $tip.addClass('fade')\n\n      var placement = typeof this.options.placement == 'function' ?\n        this.options.placement.call(this, $tip[0], this.$element[0]) :\n        this.options.placement\n\n      var autoToken = /\\s?auto?\\s?/i\n      var autoPlace = autoToken.test(placement)\n      if (autoPlace) placement = placement.replace(autoToken, '') || 'top'\n\n      $tip\n        .detach()\n        .css({ top: 0, left: 0, display: 'block' })\n        .addClass(placement)\n\n      this.options.container ? $tip.appendTo(this.options.container) : $tip.insertAfter(this.$element)\n\n      var pos          = this.getPosition()\n      var actualWidth  = $tip[0].offsetWidth\n      var actualHeight = $tip[0].offsetHeight\n\n      if (autoPlace) {\n        var $parent = this.$element.parent()\n\n        var orgPlacement = placement\n        var docScroll    = document.documentElement.scrollTop || document.body.scrollTop\n        var parentWidth  = this.options.container == 'body' ? window.innerWidth  : $parent.outerWidth()\n        var parentHeight = this.options.container == 'body' ? window.innerHeight : $parent.outerHeight()\n        var parentLeft   = this.options.container == 'body' ? 0 : $parent.offset().left\n\n        placement = placement == 'bottom' && pos.top   + pos.height  + actualHeight - docScroll > parentHeight  ? 'top'    :\n                    placement == 'top'    && pos.top   - docScroll   - actualHeight < 0                         ? 'bottom' :\n                    placement == 'right'  && pos.right + actualWidth > parentWidth                              ? 'left'   :\n                    placement == 'left'   && pos.left  - actualWidth < parentLeft                               ? 'right'  :\n                    placement\n\n        $tip\n          .removeClass(orgPlacement)\n          .addClass(placement)\n      }\n\n      var calculatedOffset = this.getCalculatedOffset(placement, pos, actualWidth, actualHeight)\n\n      this.applyPlacement(calculatedOffset, placement)\n      this.$element.trigger('shown.bs.' + this.type)\n    }\n  }\n\n  Tooltip.prototype.applyPlacement = function(offset, placement) {\n    var replace\n    var $tip   = this.tip()\n    var width  = $tip[0].offsetWidth\n    var height = $tip[0].offsetHeight\n\n    // manually read margins because getBoundingClientRect includes difference\n    var marginTop = parseInt($tip.css('margin-top'), 10)\n    var marginLeft = parseInt($tip.css('margin-left'), 10)\n\n    // we must check for NaN for ie 8/9\n    if (isNaN(marginTop))  marginTop  = 0\n    if (isNaN(marginLeft)) marginLeft = 0\n\n    offset.top  = offset.top  + marginTop\n    offset.left = offset.left + marginLeft\n\n    $tip\n      .offset(offset)\n      .addClass('in')\n\n    // check to see if placing tip in new offset caused the tip to resize itself\n    var actualWidth  = $tip[0].offsetWidth\n    var actualHeight = $tip[0].offsetHeight\n\n    if (placement == 'top' && actualHeight != height) {\n      replace = true\n      offset.top = offset.top + height - actualHeight\n    }\n\n    if (/bottom|top/.test(placement)) {\n      var delta = 0\n\n      if (offset.left < 0) {\n        delta       = offset.left * -2\n        offset.left = 0\n\n        $tip.offset(offset)\n\n        actualWidth  = $tip[0].offsetWidth\n        actualHeight = $tip[0].offsetHeight\n      }\n\n      this.replaceArrow(delta - width + actualWidth, actualWidth, 'left')\n    } else {\n      this.replaceArrow(actualHeight - height, actualHeight, 'top')\n    }\n\n    if (replace) $tip.offset(offset)\n  }\n\n  Tooltip.prototype.replaceArrow = function(delta, dimension, position) {\n    this.arrow().css(position, delta ? (50 * (1 - delta / dimension) + \"%\") : '')\n  }\n\n  Tooltip.prototype.setContent = function () {\n    var $tip  = this.tip()\n    var title = this.getTitle()\n\n    $tip.find('.tooltip-inner')[this.options.html ? 'html' : 'text'](title)\n    $tip.removeClass('fade in top bottom left right')\n  }\n\n  Tooltip.prototype.hide = function () {\n    var that = this\n    var $tip = this.tip()\n    var e    = $.Event('hide.bs.' + this.type)\n\n    function complete() {\n      if (that.hoverState != 'in') $tip.detach()\n    }\n\n    this.$element.trigger(e)\n\n    if (e.isDefaultPrevented()) return\n\n    $tip.removeClass('in')\n\n    $.support.transition && this.$tip.hasClass('fade') ?\n      $tip\n        .one($.support.transition.end, complete)\n        .emulateTransitionEnd(150) :\n      complete()\n\n    this.$element.trigger('hidden.bs.' + this.type)\n\n    return this\n  }\n\n  Tooltip.prototype.fixTitle = function () {\n    var $e = this.$element\n    if ($e.attr('title') || typeof($e.attr('data-original-title')) != 'string') {\n      $e.attr('data-original-title', $e.attr('title') || '').attr('title', '')\n    }\n  }\n\n  Tooltip.prototype.hasContent = function () {\n    return this.getTitle()\n  }\n\n  Tooltip.prototype.getPosition = function () {\n    var el = this.$element[0]\n    return $.extend({}, (typeof el.getBoundingClientRect == 'function') ? el.getBoundingClientRect() : {\n      width: el.offsetWidth\n    , height: el.offsetHeight\n    }, this.$element.offset())\n  }\n\n  Tooltip.prototype.getCalculatedOffset = function (placement, pos, actualWidth, actualHeight) {\n    return placement == 'bottom' ? { top: pos.top + pos.height,   left: pos.left + pos.width / 2 - actualWidth / 2  } :\n           placement == 'top'    ? { top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2  } :\n           placement == 'left'   ? { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth } :\n        /* placement == 'right' */ { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width   }\n  }\n\n  Tooltip.prototype.getTitle = function () {\n    var title\n    var $e = this.$element\n    var o  = this.options\n\n    title = $e.attr('data-original-title')\n      || (typeof o.title == 'function' ? o.title.call($e[0]) :  o.title)\n\n    return title\n  }\n\n  Tooltip.prototype.tip = function () {\n    return this.$tip = this.$tip || $(this.options.template)\n  }\n\n  Tooltip.prototype.arrow = function () {\n    return this.$arrow = this.$arrow || this.tip().find('.tooltip-arrow')\n  }\n\n  Tooltip.prototype.validate = function () {\n    if (!this.$element[0].parentNode) {\n      this.hide()\n      this.$element = null\n      this.options  = null\n    }\n  }\n\n  Tooltip.prototype.enable = function () {\n    this.enabled = true\n  }\n\n  Tooltip.prototype.disable = function () {\n    this.enabled = false\n  }\n\n  Tooltip.prototype.toggleEnabled = function () {\n    this.enabled = !this.enabled\n  }\n\n  Tooltip.prototype.toggle = function (e) {\n    var self = e ? $(e.currentTarget)[this.type](this.getDelegateOptions()).data('bs.' + this.type) : this\n    self.tip().hasClass('in') ? self.leave(self) : self.enter(self)\n  }\n\n  Tooltip.prototype.destroy = function () {\n    this.hide().$element.off('.' + this.type).removeData('bs.' + this.type)\n  }\n\n\n  // TOOLTIP PLUGIN DEFINITION\n  // =========================\n\n  var old = $.fn.tooltip\n\n  $.fn.tooltip = function (option) {\n    return this.each(function () {\n      var $this   = $(this)\n      var data    = $this.data('bs.tooltip')\n      var options = typeof option == 'object' && option\n\n      if (!data) $this.data('bs.tooltip', (data = new Tooltip(this, options)))\n      if (typeof option == 'string') data[option]()\n    })\n  }\n\n  $.fn.tooltip.Constructor = Tooltip\n\n\n  // TOOLTIP NO CONFLICT\n  // ===================\n\n  $.fn.tooltip.noConflict = function () {\n    $.fn.tooltip = old\n    return this\n  }\n\n}(window.jQuery);\n\n/* ========================================================================\n * Bootstrap: popover.js v3.0.0\n * http://twbs.github.com/bootstrap/javascript.html#popovers\n * ========================================================================\n * Copyright 2012 Twitter, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n * ======================================================================== */\n\n\n+function ($) { \"use strict\";\n\n  // POPOVER PUBLIC CLASS DEFINITION\n  // ===============================\n\n  var Popover = function (element, options) {\n    this.init('popover', element, options)\n  }\n\n  if (!$.fn.tooltip) throw new Error('Popover requires tooltip.js')\n\n  Popover.DEFAULTS = $.extend({} , $.fn.tooltip.Constructor.DEFAULTS, {\n    placement: 'right'\n  , trigger: 'click'\n  , content: ''\n  , template: '<div class=\"popover\"><div class=\"arrow\"></div><h3 class=\"popover-title\"></h3><div class=\"popover-content\"></div></div>'\n  })\n\n\n  // NOTE: POPOVER EXTENDS tooltip.js\n  // ================================\n\n  Popover.prototype = $.extend({}, $.fn.tooltip.Constructor.prototype)\n\n  Popover.prototype.constructor = Popover\n\n  Popover.prototype.getDefaults = function () {\n    return Popover.DEFAULTS\n  }\n\n  Popover.prototype.setContent = function () {\n    var $tip    = this.tip()\n    var title   = this.getTitle()\n    var content = this.getContent()\n\n    $tip.find('.popover-title')[this.options.html ? 'html' : 'text'](title)\n    $tip.find('.popover-content')[this.options.html ? 'html' : 'text'](content)\n\n    $tip.removeClass('fade top bottom left right in')\n\n    // IE8 doesn't accept hiding via the `:empty` pseudo selector, we have to do\n    // this manually by checking the contents.\n    if (!$tip.find('.popover-title').html()) $tip.find('.popover-title').hide()\n  }\n\n  Popover.prototype.hasContent = function () {\n    return this.getTitle() || this.getContent()\n  }\n\n  Popover.prototype.getContent = function () {\n    var $e = this.$element\n    var o  = this.options\n\n    return $e.attr('data-content')\n      || (typeof o.content == 'function' ?\n            o.content.call($e[0]) :\n            o.content)\n  }\n\n  Popover.prototype.arrow = function () {\n    return this.$arrow = this.$arrow || this.tip().find('.arrow')\n  }\n\n  Popover.prototype.tip = function () {\n    if (!this.$tip) this.$tip = $(this.options.template)\n    return this.$tip\n  }\n\n\n  // POPOVER PLUGIN DEFINITION\n  // =========================\n\n  var old = $.fn.popover\n\n  $.fn.popover = function (option) {\n    return this.each(function () {\n      var $this   = $(this)\n      var data    = $this.data('bs.popover')\n      var options = typeof option == 'object' && option\n\n      if (!data) $this.data('bs.popover', (data = new Popover(this, options)))\n      if (typeof option == 'string') data[option]()\n    })\n  }\n\n  $.fn.popover.Constructor = Popover\n\n\n  // POPOVER NO CONFLICT\n  // ===================\n\n  $.fn.popover.noConflict = function () {\n    $.fn.popover = old\n    return this\n  }\n\n}(window.jQuery);\n\n/* ========================================================================\n * Bootstrap: scrollspy.js v3.0.0\n * http://twbs.github.com/bootstrap/javascript.html#scrollspy\n * ========================================================================\n * Copyright 2012 Twitter, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n * ======================================================================== */\n\n\n+function ($) { \"use strict\";\n\n  // SCROLLSPY CLASS DEFINITION\n  // ==========================\n\n  function ScrollSpy(element, options) {\n    var href\n    var process  = $.proxy(this.process, this)\n\n    this.$element       = $(element).is('body') ? $(window) : $(element)\n    this.$body          = $('body')\n    this.$scrollElement = this.$element.on('scroll.bs.scroll-spy.data-api', process)\n    this.options        = $.extend({}, ScrollSpy.DEFAULTS, options)\n    this.selector       = (this.options.target\n      || ((href = $(element).attr('href')) && href.replace(/.*(?=#[^\\s]+$)/, '')) //strip for ie7\n      || '') + ' .nav li > a'\n    this.offsets        = $([])\n    this.targets        = $([])\n    this.activeTarget   = null\n\n    this.refresh()\n    this.process()\n  }\n\n  ScrollSpy.DEFAULTS = {\n    offset: 10\n  }\n\n  ScrollSpy.prototype.refresh = function () {\n    var offsetMethod = this.$element[0] == window ? 'offset' : 'position'\n\n    this.offsets = $([])\n    this.targets = $([])\n\n    var self     = this\n    var $targets = this.$body\n      .find(this.selector)\n      .map(function () {\n        var $el   = $(this)\n        var href  = $el.data('target') || $el.attr('href')\n        var $href = /^#\\w/.test(href) && $(href)\n\n        return ($href\n          && $href.length\n          && [[ $href[offsetMethod]().top + (!$.isWindow(self.$scrollElement.get(0)) && self.$scrollElement.scrollTop()), href ]]) || null\n      })\n      .sort(function (a, b) { return a[0] - b[0] })\n      .each(function () {\n        self.offsets.push(this[0])\n        self.targets.push(this[1])\n      })\n  }\n\n  ScrollSpy.prototype.process = function () {\n    var scrollTop    = this.$scrollElement.scrollTop() + this.options.offset\n    var scrollHeight = this.$scrollElement[0].scrollHeight || this.$body[0].scrollHeight\n    var maxScroll    = scrollHeight - this.$scrollElement.height()\n    var offsets      = this.offsets\n    var targets      = this.targets\n    var activeTarget = this.activeTarget\n    var i\n\n    if (scrollTop >= maxScroll) {\n      return activeTarget != (i = targets.last()[0]) && this.activate(i)\n    }\n\n    for (i = offsets.length; i--;) {\n      activeTarget != targets[i]\n        && scrollTop >= offsets[i]\n        && (!offsets[i + 1] || scrollTop <= offsets[i + 1])\n        && this.activate( targets[i] )\n    }\n  }\n\n  ScrollSpy.prototype.activate = function (target) {\n    this.activeTarget = target\n\n    $(this.selector)\n      .parents('.active')\n      .removeClass('active')\n\n    var selector = this.selector\n      + '[data-target=\"' + target + '\"],'\n      + this.selector + '[href=\"' + target + '\"]'\n\n    var active = $(selector)\n      .parents('li')\n      .addClass('active')\n\n    if (active.parent('.dropdown-menu').length)  {\n      active = active\n        .closest('li.dropdown')\n        .addClass('active')\n    }\n\n    active.trigger('activate')\n  }\n\n\n  // SCROLLSPY PLUGIN DEFINITION\n  // ===========================\n\n  var old = $.fn.scrollspy\n\n  $.fn.scrollspy = function (option) {\n    return this.each(function () {\n      var $this   = $(this)\n      var data    = $this.data('bs.scrollspy')\n      var options = typeof option == 'object' && option\n\n      if (!data) $this.data('bs.scrollspy', (data = new ScrollSpy(this, options)))\n      if (typeof option == 'string') data[option]()\n    })\n  }\n\n  $.fn.scrollspy.Constructor = ScrollSpy\n\n\n  // SCROLLSPY NO CONFLICT\n  // =====================\n\n  $.fn.scrollspy.noConflict = function () {\n    $.fn.scrollspy = old\n    return this\n  }\n\n\n  // SCROLLSPY DATA-API\n  // ==================\n\n  $(window).on('load', function () {\n    $('[data-spy=\"scroll\"]').each(function () {\n      var $spy = $(this)\n      $spy.scrollspy($spy.data())\n    })\n  })\n\n}(window.jQuery);\n\n/* ========================================================================\n * Bootstrap: tab.js v3.0.0\n * http://twbs.github.com/bootstrap/javascript.html#tabs\n * ========================================================================\n * Copyright 2012 Twitter, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n * ======================================================================== */\n\n\n+function ($) { \"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.attr('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}(window.jQuery);\n\n/* ========================================================================\n * Bootstrap: affix.js v3.0.0\n * http://twbs.github.com/bootstrap/javascript.html#affix\n * ========================================================================\n * Copyright 2012 Twitter, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n * ======================================================================== */\n\n\n+function ($) { \"use strict\";\n\n  // AFFIX CLASS DEFINITION\n  // ======================\n\n  var Affix = function (element, options) {\n    this.options = $.extend({}, Affix.DEFAULTS, options)\n    this.$window = $(window)\n      .on('scroll.bs.affix.data-api', $.proxy(this.checkPosition, this))\n      .on('click.bs.affix.data-api',  $.proxy(this.checkPositionWithEventLoop, this))\n\n    this.$element = $(element)\n    this.affixed  =\n    this.unpin    = null\n\n    this.checkPosition()\n  }\n\n  Affix.RESET = 'affix affix-top affix-bottom'\n\n  Affix.DEFAULTS = {\n    offset: 0\n  }\n\n  Affix.prototype.checkPositionWithEventLoop = function () {\n    setTimeout($.proxy(this.checkPosition, this), 1)\n  }\n\n  Affix.prototype.checkPosition = function () {\n    if (!this.$element.is(':visible')) return\n\n    var scrollHeight = $(document).height()\n    var scrollTop    = this.$window.scrollTop()\n    var position     = this.$element.offset()\n    var offset       = this.options.offset\n    var offsetTop    = offset.top\n    var offsetBottom = offset.bottom\n\n    if (typeof offset != 'object')         offsetBottom = offsetTop = offset\n    if (typeof offsetTop == 'function')    offsetTop    = offset.top()\n    if (typeof offsetBottom == 'function') offsetBottom = offset.bottom()\n\n    var affix = this.unpin   != null && (scrollTop + this.unpin <= position.top) ? false :\n                offsetBottom != null && (position.top + this.$element.height() >= scrollHeight - offsetBottom) ? 'bottom' :\n                offsetTop    != null && (scrollTop <= offsetTop) ? 'top' : false\n\n    if (this.affixed === affix) return\n    if (this.unpin) this.$element.css('top', '')\n\n    this.affixed = affix\n    this.unpin   = affix == 'bottom' ? position.top - scrollTop : null\n\n    this.$element.removeClass(Affix.RESET).addClass('affix' + (affix ? '-' + affix : ''))\n\n    if (affix == 'bottom') {\n      this.$element.offset({ top: document.body.offsetHeight - offsetBottom - this.$element.height() })\n    }\n  }\n\n\n  // AFFIX PLUGIN DEFINITION\n  // =======================\n\n  var old = $.fn.affix\n\n  $.fn.affix = function (option) {\n    return this.each(function () {\n      var $this   = $(this)\n      var data    = $this.data('bs.affix')\n      var options = typeof option == 'object' && option\n\n      if (!data) $this.data('bs.affix', (data = new Affix(this, options)))\n      if (typeof option == 'string') data[option]()\n    })\n  }\n\n  $.fn.affix.Constructor = Affix\n\n\n  // AFFIX NO CONFLICT\n  // =================\n\n  $.fn.affix.noConflict = function () {\n    $.fn.affix = old\n    return this\n  }\n\n\n  // AFFIX DATA-API\n  // ==============\n\n  $(window).on('load', function () {\n    $('[data-spy=\"affix\"]').each(function () {\n      var $spy = $(this)\n      var data = $spy.data()\n\n      data.offset = data.offset || {}\n\n      if (data.offsetBottom) data.offset.bottom = data.offsetBottom\n      if (data.offsetTop)    data.offset.top    = data.offsetTop\n\n      $spy.affix(data)\n    })\n  })\n\n}(window.jQuery);\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/sass-bootstrap/examples/carousel/carousel.css",
    "content": "/* GLOBAL STYLES\n-------------------------------------------------- */\n/* Padding below the footer and lighter body text */\n\nbody {\n  padding-bottom: 40px;\n  color: #5a5a5a;\n}\n\n\n\n/* CUSTOMIZE THE NAVBAR\n-------------------------------------------------- */\n\n/* Special class on .container surrounding .navbar, used for positioning it into place. */\n.navbar-wrapper {\n  position: relative;\n  z-index: 15;\n}\n\n\n/* CUSTOMIZE THE CAROUSEL\n-------------------------------------------------- */\n\n/* Carousel base class */\n.carousel {\n  margin-bottom: 60px;\n\n  /* Negative margin to pull up carousel. 90px is roughly margins and height of navbar. */\n  margin-top: -90px;\n}\n/* Since positioning the image, we need to help out the caption */\n.carousel-caption {\n  z-index: 10;\n}\n\n/* Declare heights because of positioning of img element */\n.carousel .item {\n  height: 500px;\n  background-color: #777;\n}\n.carousel-inner > .item > img {\n  position: absolute;\n  top: 0;\n  left: 0;\n  min-width: 100%;\n  height: 500px;\n}\n\n\n\n/* MARKETING CONTENT\n-------------------------------------------------- */\n\n/* Pad the edges of the mobile views a bit */\n.marketing {\n  padding-left: 15px;\n  padding-right: 15px;\n}\n\n/* Center align the text within the three columns below the carousel */\n.marketing .col-lg-4 {\n  text-align: center;\n  margin-bottom: 20px;\n}\n.marketing h2 {\n  font-weight: normal;\n}\n.marketing .col-lg-4 p {\n  margin-left: 10px;\n  margin-right: 10px;\n}\n\n\n/* Featurettes\n------------------------- */\n\n.featurette-divider {\n  margin: 80px 0; /* Space out the Bootstrap <hr> more */\n}\n\n/* Thin out the marketing headings */\n.featurette-heading {\n  font-weight: 300;\n  line-height: 1;\n  letter-spacing: -1px;\n}\n\n\n\n/* RESPONSIVE CSS\n-------------------------------------------------- */\n\n@media (min-width: 768px) {\n\n  /* Remove the edge padding needed for mobile */\n  .marketing {\n    padding-left: 0;\n    padding-right: 0;\n  }\n\n  /* Navbar positioning foo */\n  .navbar-wrapper {\n    margin-top: 20px;\n  }\n  /* The navbar becomes detached from the top, so we round the corners */\n  .navbar-wrapper .navbar {\n    border-radius: 4px;\n  }\n\n  /* Bump up size of carousel content */\n  .carousel-caption p {\n    margin-bottom: 20px;\n    font-size: 21px;\n    line-height: 1.4;\n  }\n\n  .featurette-heading {\n    font-size: 50px;\n  }\n\n}\n\n@media (min-width: 992px) {\n  .featurette-heading {\n    margin-top: 120px;\n  }\n}\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/sass-bootstrap/examples/carousel/index.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"utf-8\">\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n    <meta name=\"description\" content=\"\">\n    <meta name=\"author\" content=\"\">\n    <link rel=\"shortcut icon\" href=\"../../assets/ico/favicon.png\">\n\n    <title>Carousel Template for Bootstrap</title>\n\n    <!-- Bootstrap core CSS -->\n    <link href=\"../../dist/css/bootstrap.css\" rel=\"stylesheet\">\n\n    <!-- HTML5 shim and Respond.js IE8 support of HTML5 elements and media queries -->\n    <!--[if lt IE 9]>\n      <script src=\"../../assets/js/html5shiv.js\"></script>\n      <script src=\"../../assets/js/respond.min.js\"></script>\n    <![endif]-->\n\n    <!-- Custom styles for this template -->\n    <link href=\"carousel.css\" rel=\"stylesheet\">\n  </head>\n<!-- NAVBAR\n================================================== -->\n  <body>\n    <div class=\"navbar-wrapper\">\n      <div class=\"container\">\n\n        <div class=\"navbar navbar-inverse navbar-static-top\">\n          <div class=\"container\">\n            <div class=\"navbar-header\">\n              <button type=\"button\" class=\"navbar-toggle\" data-toggle=\"collapse\" data-target=\".navbar-collapse\">\n                <span class=\"icon-bar\"></span>\n                <span class=\"icon-bar\"></span>\n                <span class=\"icon-bar\"></span>\n              </button>\n              <a class=\"navbar-brand\" href=\"#\">Project name</a>\n            </div>\n            <div class=\"navbar-collapse collapse\">\n              <ul class=\"nav navbar-nav\">\n                <li class=\"active\"><a href=\"#\">Home</a></li>\n                <li><a href=\"#about\">About</a></li>\n                <li><a href=\"#contact\">Contact</a></li>\n                <li class=\"dropdown\">\n                  <a href=\"#\" class=\"dropdown-toggle\" data-toggle=\"dropdown\">Dropdown <b class=\"caret\"></b></a>\n                  <ul class=\"dropdown-menu\">\n                    <li><a href=\"#\">Action</a></li>\n                    <li><a href=\"#\">Another action</a></li>\n                    <li><a href=\"#\">Something else here</a></li>\n                    <li class=\"divider\"></li>\n                    <li class=\"dropdown-header\">Nav header</li>\n                    <li><a href=\"#\">Separated link</a></li>\n                    <li><a href=\"#\">One more separated link</a></li>\n                  </ul>\n                </li>\n              </ul>\n            </div>\n          </div>\n        </div>\n\n      </div>\n    </div>\n\n\n    <!-- Carousel\n    ================================================== -->\n    <div id=\"myCarousel\" class=\"carousel slide\">\n      <!-- Indicators -->\n      <ol class=\"carousel-indicators\">\n        <li data-target=\"#myCarousel\" data-slide-to=\"0\" class=\"active\"></li>\n        <li data-target=\"#myCarousel\" data-slide-to=\"1\"></li>\n        <li data-target=\"#myCarousel\" data-slide-to=\"2\"></li>\n      </ol>\n      <div class=\"carousel-inner\">\n        <div class=\"item active\">\n          <img src=\"data:image/png;base64,\" data-src=\"holder.js/100%x500/auto/#777:#7a7a7a/text:First slide\" alt=\"First slide\">\n          <div class=\"container\">\n            <div class=\"carousel-caption\">\n              <h1>Example headline.</h1>\n              <p>Cras justo odio, dapibus ac facilisis in, egestas eget quam. Donec id elit non mi porta gravida at eget metus. Nullam id dolor id nibh ultricies vehicula ut id elit.</p>\n              <p><a class=\"btn btn-large btn-primary\" href=\"#\">Sign up today</a></p>\n            </div>\n          </div>\n        </div>\n        <div class=\"item\">\n          <img src=\"data:image/png;base64,\" data-src=\"holder.js/100%x500/auto/#777:#7a7a7a/text:Second slide\" alt=\"Second slide\">\n          <div class=\"container\">\n            <div class=\"carousel-caption\">\n              <h1>Another example headline.</h1>\n              <p>Cras justo odio, dapibus ac facilisis in, egestas eget quam. Donec id elit non mi porta gravida at eget metus. Nullam id dolor id nibh ultricies vehicula ut id elit.</p>\n              <p><a class=\"btn btn-large btn-primary\" href=\"#\">Learn more</a></p>\n            </div>\n          </div>\n        </div>\n        <div class=\"item\">\n          <img src=\"data:image/png;base64,\" data-src=\"holder.js/100%x500/auto/#777:#7a7a7a/text:Third slide\" alt=\"Third slide\">\n          <div class=\"container\">\n            <div class=\"carousel-caption\">\n              <h1>One more for good measure.</h1>\n              <p>Cras justo odio, dapibus ac facilisis in, egestas eget quam. Donec id elit non mi porta gravida at eget metus. Nullam id dolor id nibh ultricies vehicula ut id elit.</p>\n              <p><a class=\"btn btn-large btn-primary\" href=\"#\">Browse gallery</a></p>\n            </div>\n          </div>\n        </div>\n      </div>\n      <a class=\"left carousel-control\" href=\"#myCarousel\" data-slide=\"prev\"><span class=\"glyphicon glyphicon-chevron-left\"></span></a>\n      <a class=\"right carousel-control\" href=\"#myCarousel\" data-slide=\"next\"><span class=\"glyphicon glyphicon-chevron-right\"></span></a>\n    </div><!-- /.carousel -->\n\n\n\n    <!-- Marketing messaging and featurettes\n    ================================================== -->\n    <!-- Wrap the rest of the page in another container to center all the content. -->\n\n    <div class=\"container marketing\">\n\n      <!-- Three columns of text below the carousel -->\n      <div class=\"row\">\n        <div class=\"col-lg-4\">\n          <img class=\"img-circle\" src=\"data:image/png;base64,\" data-src=\"holder.js/140x140\" alt=\"Generic placeholder image\">\n          <h2>Heading</h2>\n          <p>Donec sed odio dui. Etiam porta sem malesuada magna mollis euismod. Nullam id dolor id nibh ultricies vehicula ut id elit. Morbi leo risus, porta ac consectetur ac, vestibulum at eros. Praesent commodo cursus magna.</p>\n          <p><a class=\"btn btn-default\" href=\"#\">View details &raquo;</a></p>\n        </div><!-- /.col-lg-4 -->\n        <div class=\"col-lg-4\">\n          <img class=\"img-circle\" src=\"data:image/png;base64,\" data-src=\"holder.js/140x140\" alt=\"Generic placeholder image\">\n          <h2>Heading</h2>\n          <p>Duis mollis, est non commodo luctus, nisi erat porttitor ligula, eget lacinia odio sem nec elit. Cras mattis consectetur purus sit amet fermentum. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh.</p>\n          <p><a class=\"btn btn-default\" href=\"#\">View details &raquo;</a></p>\n        </div><!-- /.col-lg-4 -->\n        <div class=\"col-lg-4\">\n          <img class=\"img-circle\" src=\"data:image/png;base64,\" data-src=\"holder.js/140x140\" alt=\"Generic placeholder image\">\n          <h2>Heading</h2>\n          <p>Donec sed odio dui. Cras justo odio, dapibus ac facilisis in, egestas eget quam. Vestibulum id ligula porta felis euismod semper. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus.</p>\n          <p><a class=\"btn btn-default\" href=\"#\">View details &raquo;</a></p>\n        </div><!-- /.col-lg-4 -->\n      </div><!-- /.row -->\n\n\n      <!-- START THE FEATURETTES -->\n\n      <hr class=\"featurette-divider\">\n\n      <div class=\"row featurette\">\n        <div class=\"col-md-7\">\n          <h2 class=\"featurette-heading\">First featurette heading. <span class=\"text-muted\">It'll blow your mind.</span></h2>\n          <p class=\"lead\">Donec ullamcorper nulla non metus auctor fringilla. Vestibulum id ligula porta felis euismod semper. Praesent commodo cursus magna, vel scelerisque nisl consectetur. Fusce dapibus, tellus ac cursus commodo.</p>\n        </div>\n        <div class=\"col-md-5\">\n          <img class=\"featurette-image img-responsive\" src=\"data:image/png;base64,\" data-src=\"holder.js/500x500/auto\" alt=\"Generic placeholder image\">\n        </div>\n      </div>\n\n      <hr class=\"featurette-divider\">\n\n      <div class=\"row featurette\">\n        <div class=\"col-md-5\">\n          <img class=\"featurette-image img-responsive\" src=\"data:image/png;base64,\" data-src=\"holder.js/500x500/auto\" alt=\"Generic placeholder image\">\n        </div>\n        <div class=\"col-md-7\">\n          <h2 class=\"featurette-heading\">Oh yeah, it's that good. <span class=\"text-muted\">See for yourself.</span></h2>\n          <p class=\"lead\">Donec ullamcorper nulla non metus auctor fringilla. Vestibulum id ligula porta felis euismod semper. Praesent commodo cursus magna, vel scelerisque nisl consectetur. Fusce dapibus, tellus ac cursus commodo.</p>\n        </div>\n      </div>\n\n      <hr class=\"featurette-divider\">\n\n      <div class=\"row featurette\">\n        <div class=\"col-md-7\">\n          <h2 class=\"featurette-heading\">And lastly, this one. <span class=\"text-muted\">Checkmate.</span></h2>\n          <p class=\"lead\">Donec ullamcorper nulla non metus auctor fringilla. Vestibulum id ligula porta felis euismod semper. Praesent commodo cursus magna, vel scelerisque nisl consectetur. Fusce dapibus, tellus ac cursus commodo.</p>\n        </div>\n        <div class=\"col-md-5\">\n          <img class=\"featurette-image img-responsive\" src=\"data:image/png;base64,\" data-src=\"holder.js/500x500/auto\" alt=\"Generic placeholder image\">\n        </div>\n      </div>\n\n      <hr class=\"featurette-divider\">\n\n      <!-- /END THE FEATURETTES -->\n\n\n      <!-- FOOTER -->\n      <footer>\n        <p class=\"pull-right\"><a href=\"#\">Back to top</a></p>\n        <p>&copy; 2013 Company, Inc. &middot; <a href=\"#\">Privacy</a> &middot; <a href=\"#\">Terms</a></p>\n      </footer>\n\n    </div><!-- /.container -->\n\n\n    <!-- Bootstrap core JavaScript\n    ================================================== -->\n    <!-- Placed at the end of the document so the pages load faster -->\n    <script src=\"../../assets/js/jquery.js\"></script>\n    <script src=\"../../dist/js/bootstrap.min.js\"></script>\n    <script src=\"../../assets/js/holder.js\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/sass-bootstrap/examples/grid/grid.css",
    "content": ".container {\n  padding-left: 15px;\n  padding-right: 15px;\n}\n\nh4 {\n  margin-top: 25px;\n}\n.row {\n  margin-bottom: 20px;\n}\n.row .row {\n  margin-top: 10px;\n  margin-bottom: 0;\n}\n[class*=\"col-\"] {\n  padding-top: 15px;\n  padding-bottom: 15px;\n  background-color: #eee;\n  border: 1px solid #ddd;\n  background-color: rgba(86,61,124,.15);\n  border: 1px solid rgba(86,61,124,.2);\n}\n\nhr {\n  margin-top: 40px;\n  margin-bottom: 40px;\n}"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/sass-bootstrap/examples/grid/index.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"utf-8\">\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n    <meta name=\"description\" content=\"\">\n    <meta name=\"author\" content=\"\">\n    <link rel=\"shortcut icon\" href=\"../../assets/ico/favicon.png\">\n\n    <title>Grid Template for Bootstrap</title>\n\n    <!-- Bootstrap core CSS -->\n    <link href=\"../../dist/css/bootstrap.css\" rel=\"stylesheet\">\n\n    <!-- Custom styles for this template -->\n    <link href=\"grid.css\" rel=\"stylesheet\">\n\n    <!-- HTML5 shim and Respond.js IE8 support of HTML5 elements and media queries -->\n    <!--[if lt IE 9]>\n      <script src=\"../../assets/js/html5shiv.js\"></script>\n      <script src=\"../../assets/js/respond.min.js\"></script>\n    <![endif]-->\n  </head>\n\n  <body>\n    <div class=\"container\">\n\n      <div class=\"page-header\">\n        <h1>Bootstrap grid examples</h1>\n        <p class=\"lead\">Basic grid layouts to get you familiar with building within the Bootstrap grid system.</p>\n      </div>\n\n      <h3>Three equal columns</h3>\n      <p>Get three equal-width columns <strong>starting at desktops and scaling to large desktops</strong>. On mobile devices, tablets and below, the columns will automatically stack.</p>\n      <div class=\"row\">\n        <div class=\"col-md-4\">.col-md-4</div>\n        <div class=\"col-md-4\">.col-md-4</div>\n        <div class=\"col-md-4\">.col-md-4</div>\n      </div>\n\n      <h3>Three unequal columns</h3>\n      <p>Get three columns <strong>starting at desktops and scaling to large desktops</strong> of various widths. Remember, grid columns should add up to twelve for a single horizontal block. More than that, and columns start stacking no matter the viewport.</p>\n      <div class=\"row\">\n        <div class=\"col-md-3\">.col-md-3</div>\n        <div class=\"col-md-6\">.col-md-6</div>\n        <div class=\"col-md-3\">.col-md-3</div>\n      </div>\n\n      <h3>Two columns</h3>\n      <p>Get two columns <strong>starting at desktops and scaling to large desktops</strong>.</p>\n      <div class=\"row\">\n        <div class=\"col-md-8\">.col-md-8</div>\n        <div class=\"col-md-4\">.col-md-4</div>\n      </div>\n\n      <h3>Full width, single column</h3>\n      <p class=\"text-warning\">No grid classes are necessary for full-width elements.</p>\n\n      <hr>\n\n      <h3>Two columns with two nested columns</h3>\n      <p>Per the documentation, nesting is easy—just put a row of columns within an existing row. This gives you two columns <strong>starting at desktops and scaling to large desktops</strong>, with another two (equal widths) within the larger column.</p>\n      <p>At mobile device sizes, tablets and down, these columns and their nested columns will stack.</p>\n      <div class=\"row\">\n        <div class=\"col-md-8\">\n          .col-md-8\n          <div class=\"row\">\n            <div class=\"col-md-6\">.col-md-6</div>\n            <div class=\"col-md-6\">.col-md-6</div>\n          </div>\n        </div>\n        <div class=\"col-md-4\">.col-md-4</div>\n      </div>\n\n      <hr>\n\n      <h3>Mixed: mobile and desktop</h3>\n      <p>The Bootstrap 3 grid system has four tiers of classes: xs (phones), sm (tablets), md (desktops), and lg (larger desktops). You can use nearly any combination of these classes to create more dynamic and flexible layouts.</p>\n      <p>Each tier of classes scales up, meaning if you plan on setting the same widths for xs and sm, you only need to specify xs.</p>\n      <div class=\"row\">\n        <div class=\"col-xs-12 col-md-8\">.col-xs-12 .col-md-8</div>\n        <div class=\"col-xs-6 col-md-4\">.col-xs-6 .col-md-4</div>\n      </div>\n      <div class=\"row\">\n        <div class=\"col-xs-6 col-md-4\">.col-xs-6 .col-md-4</div>\n        <div class=\"col-xs-6 col-md-4\">.col-xs-6 .col-md-4</div>\n        <div class=\"col-xs-6 col-md-4\">.col-xs-6 .col-md-4</div>\n      </div>\n      <div class=\"row\">\n        <div class=\"col-xs-6 col-md-6\">.col-xs-6 .col-md-6</div>\n        <div class=\"col-xs-6 col-md-6\">.col-xs-6 .col-md-6</div>\n      </div>\n\n      <hr>\n\n      <h3>Mixed: mobile, tablet, and desktop</h3>\n      <p></p>\n      <div class=\"row\">\n        <div class=\"col-xs-12 col-sm-8 col-lg-8\">.col-xs-12 .col-lg-8</div>\n        <div class=\"col-xs-6 col-sm-4 col-lg-4\">.col-xs-6 .col-lg-4</div>\n      </div>\n      <div class=\"row\">\n        <div class=\"col-xs-6 col-sm-4 col-lg-4\">.col-xs-6 .col-sm-4 .col-lg-4</div>\n        <div class=\"col-xs-6 col-sm-4 col-lg-4\">.col-xs-6 .col-sm-4 .col-lg-4</div>\n        <div class=\"col-xs-6 col-sm-4 col-lg-4\">.col-xs-6 .col-sm-4 .col-lg-4</div>\n      </div>\n      <div class=\"row\">\n        <div class=\"col-xs-6 col-sm-6 col-lg-6\">.col-xs-6 .col-sm-6 .col-lg-6</div>\n        <div class=\"col-xs-6 col-sm-6 col-lg-6\">.col-xs-6 .col-sm-6 .col-lg-6</div>\n      </div>\n\n    </div> <!-- /container -->\n\n\n    <!-- Bootstrap core JavaScript\n    ================================================== -->\n    <!-- Placed at the end of the document so the pages load faster -->\n  </body>\n</html>\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/sass-bootstrap/examples/jumbotron/index.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"utf-8\">\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n    <meta name=\"description\" content=\"\">\n    <meta name=\"author\" content=\"\">\n    <link rel=\"shortcut icon\" href=\"../../assets/ico/favicon.png\">\n\n    <title>Jumbotron Template for Bootstrap</title>\n\n    <!-- Bootstrap core CSS -->\n    <link href=\"../../dist/css/bootstrap.css\" rel=\"stylesheet\">\n\n    <!-- Custom styles for this template -->\n    <link href=\"jumbotron.css\" rel=\"stylesheet\">\n\n    <!-- HTML5 shim and Respond.js IE8 support of HTML5 elements and media queries -->\n    <!--[if lt IE 9]>\n      <script src=\"../../assets/js/html5shiv.js\"></script>\n      <script src=\"../../assets/js/respond.min.js\"></script>\n    <![endif]-->\n  </head>\n\n  <body>\n\n    <div class=\"navbar navbar-inverse navbar-fixed-top\">\n      <div class=\"container\">\n        <div class=\"navbar-header\">\n          <button type=\"button\" class=\"navbar-toggle\" data-toggle=\"collapse\" data-target=\".navbar-collapse\">\n            <span class=\"icon-bar\"></span>\n            <span class=\"icon-bar\"></span>\n            <span class=\"icon-bar\"></span>\n          </button>\n          <a class=\"navbar-brand\" href=\"#\">Project name</a>\n        </div>\n        <div class=\"navbar-collapse collapse\">\n          <ul class=\"nav navbar-nav\">\n            <li class=\"active\"><a href=\"#\">Home</a></li>\n            <li><a href=\"#about\">About</a></li>\n            <li><a href=\"#contact\">Contact</a></li>\n            <li class=\"dropdown\">\n              <a href=\"#\" class=\"dropdown-toggle\" data-toggle=\"dropdown\">Dropdown <b class=\"caret\"></b></a>\n              <ul class=\"dropdown-menu\">\n                <li><a href=\"#\">Action</a></li>\n                <li><a href=\"#\">Another action</a></li>\n                <li><a href=\"#\">Something else here</a></li>\n                <li class=\"divider\"></li>\n                <li class=\"dropdown-header\">Nav header</li>\n                <li><a href=\"#\">Separated link</a></li>\n                <li><a href=\"#\">One more separated link</a></li>\n              </ul>\n            </li>\n          </ul>\n          <form class=\"navbar-form navbar-right\">\n            <div class=\"form-group\">\n              <input type=\"text\" placeholder=\"Email\" class=\"form-control\">\n            </div>\n            <div class=\"form-group\">\n              <input type=\"password\" placeholder=\"Password\" class=\"form-control\">\n            </div>\n            <button type=\"submit\" class=\"btn btn-success\">Sign in</button>\n          </form>\n        </div><!--/.navbar-collapse -->\n      </div>\n    </div>\n\n    <!-- Main jumbotron for a primary marketing message or call to action -->\n    <div class=\"jumbotron\">\n      <div class=\"container\">\n        <h1>Hello, world!</h1>\n        <p>This is a template for a simple marketing or informational website. It includes a large callout called the hero unit and three supporting pieces of content. Use it as a starting point to create something more unique.</p>\n        <p><a class=\"btn btn-primary btn-lg\">Learn more &raquo;</a></p>\n      </div>\n    </div>\n\n    <div class=\"container\">\n      <!-- Example row of columns -->\n      <div class=\"row\">\n        <div class=\"col-lg-4\">\n          <h2>Heading</h2>\n          <p>Donec id elit non mi porta gravida at eget metus. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus. Etiam porta sem malesuada magna mollis euismod. Donec sed odio dui. </p>\n          <p><a class=\"btn btn-default\" href=\"#\">View details &raquo;</a></p>\n        </div>\n        <div class=\"col-lg-4\">\n          <h2>Heading</h2>\n          <p>Donec id elit non mi porta gravida at eget metus. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus. Etiam porta sem malesuada magna mollis euismod. Donec sed odio dui. </p>\n          <p><a class=\"btn btn-default\" href=\"#\">View details &raquo;</a></p>\n       </div>\n        <div class=\"col-lg-4\">\n          <h2>Heading</h2>\n          <p>Donec sed odio dui. Cras justo odio, dapibus ac facilisis in, egestas eget quam. Vestibulum id ligula porta felis euismod semper. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus.</p>\n          <p><a class=\"btn btn-default\" href=\"#\">View details &raquo;</a></p>\n        </div>\n      </div>\n\n      <hr>\n\n      <footer>\n        <p>&copy; Company 2013</p>\n      </footer>\n    </div> <!-- /container -->\n\n\n    <!-- Bootstrap core JavaScript\n    ================================================== -->\n    <!-- Placed at the end of the document so the pages load faster -->\n    <script src=\"../../assets/js/jquery.js\"></script>\n    <script src=\"../../dist/js/bootstrap.min.js\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/sass-bootstrap/examples/jumbotron/jumbotron.css",
    "content": "/* Move down content because we have a fixed navbar that is 50px tall */\nbody {\n  padding-top: 50px;\n  padding-bottom: 20px;\n}\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/sass-bootstrap/examples/jumbotron-narrow/index.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"utf-8\">\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n    <meta name=\"description\" content=\"\">\n    <meta name=\"author\" content=\"\">\n    <link rel=\"shortcut icon\" href=\"../../assets/ico/favicon.png\">\n\n    <title>Narrow Jumbotron Template for Bootstrap</title>\n\n    <!-- Bootstrap core CSS -->\n    <link href=\"../../dist/css/bootstrap.css\" rel=\"stylesheet\">\n\n    <!-- Custom styles for this template -->\n    <link href=\"jumbotron-narrow.css\" rel=\"stylesheet\">\n\n    <!-- HTML5 shim and Respond.js IE8 support of HTML5 elements and media queries -->\n    <!--[if lt IE 9]>\n      <script src=\"../../assets/js/html5shiv.js\"></script>\n      <script src=\"../../assets/js/respond.min.js\"></script>\n    <![endif]-->\n  </head>\n\n  <body>\n\n    <div class=\"container\">\n      <div class=\"header\">\n        <ul class=\"nav nav-pills pull-right\">\n          <li class=\"active\"><a href=\"#\">Home</a></li>\n          <li><a href=\"#\">About</a></li>\n          <li><a href=\"#\">Contact</a></li>\n        </ul>\n        <h3 class=\"text-muted\">Project name</h3>\n      </div>\n\n      <div class=\"jumbotron\">\n        <h1>Jumbotron heading</h1>\n        <p class=\"lead\">Cras justo odio, dapibus ac facilisis in, egestas eget quam. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus.</p>\n        <p><a class=\"btn btn-lg btn-success\" href=\"#\">Sign up today</a></p>\n      </div>\n\n      <div class=\"row marketing\">\n        <div class=\"col-lg-6\">\n          <h4>Subheading</h4>\n          <p>Donec id elit non mi porta gravida at eget metus. Maecenas faucibus mollis interdum.</p>\n\n          <h4>Subheading</h4>\n          <p>Morbi leo risus, porta ac consectetur ac, vestibulum at eros. Cras mattis consectetur purus sit amet fermentum.</p>\n\n          <h4>Subheading</h4>\n          <p>Maecenas sed diam eget risus varius blandit sit amet non magna.</p>\n        </div>\n\n        <div class=\"col-lg-6\">\n          <h4>Subheading</h4>\n          <p>Donec id elit non mi porta gravida at eget metus. Maecenas faucibus mollis interdum.</p>\n\n          <h4>Subheading</h4>\n          <p>Morbi leo risus, porta ac consectetur ac, vestibulum at eros. Cras mattis consectetur purus sit amet fermentum.</p>\n\n          <h4>Subheading</h4>\n          <p>Maecenas sed diam eget risus varius blandit sit amet non magna.</p>\n        </div>\n      </div>\n\n      <div class=\"footer\">\n        <p>&copy; Company 2013</p>\n      </div>\n\n    </div> <!-- /container -->\n\n\n    <!-- Bootstrap core JavaScript\n    ================================================== -->\n    <!-- Placed at the end of the document so the pages load faster -->\n  </body>\n</html>\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/sass-bootstrap/examples/jumbotron-narrow/jumbotron-narrow.css",
    "content": "/* Space out content a bit */\nbody {\n  padding-top: 20px;\n  padding-bottom: 20px;\n}\n\n/* Everything but the jumbotron gets side spacing for mobile first views */\n.header,\n.marketing,\n.footer {\n  padding-left: 15px;\n  padding-right: 15px;\n}\n\n/* Custom page header */\n.header {\n  border-bottom: 1px solid #e5e5e5;\n}\n/* Make the masthead heading the same height as the navigation */\n.header h3 {\n  margin-top: 0;\n  margin-bottom: 0;\n  line-height: 40px;\n  padding-bottom: 19px;\n}\n\n/* Custom page footer */\n.footer {\n  padding-top: 19px;\n  color: #777;\n  border-top: 1px solid #e5e5e5;\n}\n\n/* Customize container */\n@media (min-width: 768px) {\n  .container {\n    max-width: 730px;\n  }\n}\n.container-narrow > hr {\n  margin: 30px 0;\n}\n\n/* Main marketing message and sign up button */\n.jumbotron {\n  text-align: center;\n  border-bottom: 1px solid #e5e5e5;\n}\n.jumbotron .btn {\n  font-size: 21px;\n  padding: 14px 24px;\n}\n\n/* Supporting marketing content */\n.marketing {\n  margin: 40px 0;\n}\n.marketing p + h4 {\n  margin-top: 28px;\n}\n\n/* Responsive: Portrait tablets and up */\n@media screen and (min-width: 768px) {\n  /* Remove the padding we set earlier */\n  .header,\n  .marketing,\n  .footer {\n    padding-left: 0;\n    padding-right: 0;\n  }\n  /* Space out the masthead */\n  .header {\n    margin-bottom: 30px;\n  }\n  /* Remove the bottom border on the jumbotron for visual effect */\n  .jumbotron {\n    border-bottom: 0;\n  }\n}\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/sass-bootstrap/examples/justified-nav/index.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"utf-8\">\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n    <meta name=\"description\" content=\"\">\n    <meta name=\"author\" content=\"\">\n    <link rel=\"shortcut icon\" href=\"../../assets/ico/favicon.png\">\n\n    <title>Justified Nav Template for Bootstrap</title>\n\n    <!-- Bootstrap core CSS -->\n    <link href=\"../../dist/css/bootstrap.css\" rel=\"stylesheet\">\n\n    <!-- Custom styles for this template -->\n    <link href=\"justified-nav.css\" rel=\"stylesheet\">\n\n    <!-- HTML5 shim and Respond.js IE8 support of HTML5 elements and media queries -->\n    <!--[if lt IE 9]>\n      <script src=\"../../assets/js/html5shiv.js\"></script>\n      <script src=\"../../assets/js/respond.min.js\"></script>\n    <![endif]-->\n  </head>\n\n  <body>\n\n    <div class=\"container\">\n\n      <div class=\"masthead\">\n        <h3 class=\"text-muted\">Project name</h3>\n        <ul class=\"nav nav-justified\">\n          <li class=\"active\"><a href=\"#\">Home</a></li>\n          <li><a href=\"#\">Projects</a></li>\n          <li><a href=\"#\">Services</a></li>\n          <li><a href=\"#\">Downloads</a></li>\n          <li><a href=\"#\">About</a></li>\n          <li><a href=\"#\">Contact</a></li>\n        </ul>\n      </div>\n\n      <!-- Jumbotron -->\n      <div class=\"jumbotron\">\n        <h1>Marketing stuff!</h1>\n        <p class=\"lead\">Cras justo odio, dapibus ac facilisis in, egestas eget quam. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet.</p>\n        <p><a class=\"btn btn-lg btn-success\" href=\"#\">Get started today</a></p>\n      </div>\n\n      <!-- Example row of columns -->\n      <div class=\"row\">\n        <div class=\"col-lg-4\">\n          <h2>Heading</h2>\n          <p>Donec id elit non mi porta gravida at eget metus. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus. Etiam porta sem malesuada magna mollis euismod. Donec sed odio dui. </p>\n          <p><a class=\"btn btn-primary\" href=\"#\">View details &raquo;</a></p>\n        </div>\n        <div class=\"col-lg-4\">\n          <h2>Heading</h2>\n          <p>Donec id elit non mi porta gravida at eget metus. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus. Etiam porta sem malesuada magna mollis euismod. Donec sed odio dui. </p>\n          <p><a class=\"btn btn-primary\" href=\"#\">View details &raquo;</a></p>\n       </div>\n        <div class=\"col-lg-4\">\n          <h2>Heading</h2>\n          <p>Donec sed odio dui. Cras justo odio, dapibus ac facilisis in, egestas eget quam. Vestibulum id ligula porta felis euismod semper. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa.</p>\n          <p><a class=\"btn btn-primary\" href=\"#\">View details &raquo;</a></p>\n        </div>\n      </div>\n\n      <!-- Site footer -->\n      <div class=\"footer\">\n        <p>&copy; Company 2013</p>\n      </div>\n\n    </div> <!-- /container -->\n\n\n    <!-- Bootstrap core JavaScript\n    ================================================== -->\n    <!-- Placed at the end of the document so the pages load faster -->\n  </body>\n</html>\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/sass-bootstrap/examples/justified-nav/justified-nav.css",
    "content": "body {\n  padding-top: 20px;\n}\n\n.footer {\n  border-top: 1px solid #eee;\n  margin-top: 40px;\n  padding-top: 40px;\n  padding-bottom: 40px;\n}\n\n/* Main marketing message and sign up button */\n.jumbotron {\n  text-align: center;\n  background-color: transparent;\n}\n.jumbotron .btn {\n  font-size: 21px;\n  padding: 14px 24px;\n}\n\n/* Customize the nav-justified links to be fill the entire space of the .navbar */\n\n.nav-justified {\n  background-color: #eee;\n  border-radius: 5px;\n  border: 1px solid #ccc;\n}\n.nav-justified > li > a {\n  padding-top: 15px;\n  padding-bottom: 15px;\n  color: #777;\n  font-weight: bold;\n  text-align: center;\n  border-bottom: 1px solid #d5d5d5;\n  background-color: #e5e5e5; /* Old browsers */\n  background-repeat: repeat-x; /* Repeat the gradient */\n  background-image: -moz-linear-gradient(top, #f5f5f5 0%, #e5e5e5 100%); /* FF3.6+ */\n  background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#f5f5f5), color-stop(100%,#e5e5e5)); /* Chrome,Safari4+ */\n  background-image: -webkit-linear-gradient(top, #f5f5f5 0%,#e5e5e5 100%); /* Chrome 10+,Safari 5.1+ */\n  background-image: -ms-linear-gradient(top, #f5f5f5 0%,#e5e5e5 100%); /* IE10+ */\n  background-image: -o-linear-gradient(top, #f5f5f5 0%,#e5e5e5 100%); /* Opera 11.10+ */\n  filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#f5f5f5', endColorstr='#e5e5e5',GradientType=0 ); /* IE6-9 */\n  background-image: linear-gradient(top, #f5f5f5 0%,#e5e5e5 100%); /* W3C */\n}\n.nav-justified > .active > a,\n.nav-justified > .active > a:hover,\n.nav-justified > .active > a:focus {\n  background-color: #ddd;\n  background-image: none;\n  box-shadow: inset 0 3px 7px rgba(0,0,0,.15);\n}\n.nav-justified > li:first-child > a {\n  border-radius: 5px 5px 0 0;\n}\n.nav-justified > li:last-child > a {\n  border-bottom: 0;\n  border-radius: 0 0 5px 5px;\n}\n\n@media (min-width: 768px) {\n  .nav-justified {\n    max-height: 52px;\n  }\n  .nav-justified > li > a {\n    border-left: 1px solid #fff;\n    border-right: 1px solid #d5d5d5;\n  }\n  .nav-justified > li:first-child > a {\n    border-left: 0;\n    border-radius: 5px 0 0 5px;\n  }\n  .nav-justified > li:last-child > a {\n    border-radius: 0 5px 5px 0;\n    border-right: 0;\n  }\n}\n\n/* Responsive: Portrait tablets and up */\n@media screen and (min-width: 768px) {\n  /* Remove the padding we set earlier */\n  .masthead,\n  .marketing,\n  .footer {\n    padding-left: 0;\n    padding-right: 0;\n  }\n}\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/sass-bootstrap/examples/navbar/index.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"utf-8\">\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n    <meta name=\"description\" content=\"\">\n    <meta name=\"author\" content=\"\">\n    <link rel=\"shortcut icon\" href=\"../../assets/ico/favicon.png\">\n\n    <title>Navbar Template for Bootstrap</title>\n\n    <!-- Bootstrap core CSS -->\n    <link href=\"../../dist/css/bootstrap.css\" rel=\"stylesheet\">\n\n    <!-- Custom styles for this template -->\n    <link href=\"navbar.css\" rel=\"stylesheet\">\n\n    <!-- HTML5 shim and Respond.js IE8 support of HTML5 elements and media queries -->\n    <!--[if lt IE 9]>\n      <script src=\"../../assets/js/html5shiv.js\"></script>\n      <script src=\"../../assets/js/respond.min.js\"></script>\n    <![endif]-->\n  </head>\n\n  <body>\n\n    <div class=\"container\">\n\n      <!-- Static navbar -->\n      <div class=\"navbar navbar-default\">\n        <div class=\"navbar-header\">\n          <button type=\"button\" class=\"navbar-toggle\" data-toggle=\"collapse\" data-target=\".navbar-collapse\">\n            <span class=\"icon-bar\"></span>\n            <span class=\"icon-bar\"></span>\n            <span class=\"icon-bar\"></span>\n          </button>\n          <a class=\"navbar-brand\" href=\"#\">Project name</a>\n        </div>\n        <div class=\"navbar-collapse collapse\">\n          <ul class=\"nav navbar-nav\">\n            <li class=\"active\"><a href=\"#\">Link</a></li>\n            <li><a href=\"#\">Link</a></li>\n            <li><a href=\"#\">Link</a></li>\n            <li class=\"dropdown\">\n              <a href=\"#\" class=\"dropdown-toggle\" data-toggle=\"dropdown\">Dropdown <b class=\"caret\"></b></a>\n              <ul class=\"dropdown-menu\">\n                <li><a href=\"#\">Action</a></li>\n                <li><a href=\"#\">Another action</a></li>\n                <li><a href=\"#\">Something else here</a></li>\n                <li class=\"divider\"></li>\n                <li class=\"dropdown-header\">Nav header</li>\n                <li><a href=\"#\">Separated link</a></li>\n                <li><a href=\"#\">One more separated link</a></li>\n              </ul>\n            </li>\n          </ul>\n          <ul class=\"nav navbar-nav navbar-right\">\n            <li class=\"active\"><a href=\"./\">Default</a></li>\n            <li><a href=\"../navbar-static-top/\">Static top</a></li>\n            <li><a href=\"../navbar-fixed-top/\">Fixed top</a></li>\n          </ul>\n        </div><!--/.nav-collapse -->\n      </div>\n\n      <!-- Main component for a primary marketing message or call to action -->\n      <div class=\"jumbotron\">\n        <h1>Navbar example</h1>\n        <p>This example is a quick exercise to illustrate how the default, static navbar and fixed to top navbar work. It includes the responsive CSS and HTML, so it also adapts to your viewport and device.</p>\n        <p>\n          <a class=\"btn btn-lg btn-primary\" href=\"../../components/#navbar\">View navbar docs &raquo;</a>\n        </p>\n      </div>\n\n    </div> <!-- /container -->\n\n\n    <!-- Bootstrap core JavaScript\n    ================================================== -->\n    <!-- Placed at the end of the document so the pages load faster -->\n    <script src=\"../../assets/js/jquery.js\"></script>\n    <script src=\"../../dist/js/bootstrap.min.js\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/sass-bootstrap/examples/navbar/navbar.css",
    "content": "body {\npadding: 30px;\n}\n\n.navbar {\nmargin-bottom: 30px;\n}"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/sass-bootstrap/examples/navbar-fixed-top/index.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"utf-8\">\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n    <meta name=\"description\" content=\"\">\n    <meta name=\"author\" content=\"\">\n    <link rel=\"shortcut icon\" href=\"../../assets/ico/favicon.png\">\n\n    <title>Fixed Top Navbar Example for Bootstrap</title>\n\n    <!-- Bootstrap core CSS -->\n    <link href=\"../../dist/css/bootstrap.css\" rel=\"stylesheet\">\n\n    <!-- Custom styles for this template -->\n    <link href=\"navbar-fixed-top.css\" rel=\"stylesheet\">\n\n    <!-- HTML5 shim and Respond.js IE8 support of HTML5 elements and media queries -->\n    <!--[if lt IE 9]>\n      <script src=\"../../assets/js/html5shiv.js\"></script>\n      <script src=\"../../assets/js/respond.min.js\"></script>\n    <![endif]-->\n  </head>\n\n  <body>\n\n    <!-- Fixed navbar -->\n    <div class=\"navbar navbar-default navbar-fixed-top\">\n      <div class=\"container\">\n        <div class=\"navbar-header\">\n          <button type=\"button\" class=\"navbar-toggle\" data-toggle=\"collapse\" data-target=\".navbar-collapse\">\n            <span class=\"icon-bar\"></span>\n            <span class=\"icon-bar\"></span>\n            <span class=\"icon-bar\"></span>\n          </button>\n          <a class=\"navbar-brand\" href=\"#\">Project name</a>\n        </div>\n        <div class=\"navbar-collapse collapse\">\n          <ul class=\"nav navbar-nav\">\n            <li class=\"active\"><a href=\"#\">Home</a></li>\n            <li><a href=\"#about\">About</a></li>\n            <li><a href=\"#contact\">Contact</a></li>\n            <li class=\"dropdown\">\n              <a href=\"#\" class=\"dropdown-toggle\" data-toggle=\"dropdown\">Dropdown <b class=\"caret\"></b></a>\n              <ul class=\"dropdown-menu\">\n                <li><a href=\"#\">Action</a></li>\n                <li><a href=\"#\">Another action</a></li>\n                <li><a href=\"#\">Something else here</a></li>\n                <li class=\"divider\"></li>\n                <li class=\"dropdown-header\">Nav header</li>\n                <li><a href=\"#\">Separated link</a></li>\n                <li><a href=\"#\">One more separated link</a></li>\n              </ul>\n            </li>\n          </ul>\n          <ul class=\"nav navbar-nav navbar-right\">\n            <li><a href=\"../navbar/\">Default</a></li>\n            <li><a href=\"../navbar-static-top/\">Static top</a></li>\n            <li class=\"active\"><a href=\"./\">Fixed top</a></li>\n          </ul>\n        </div><!--/.nav-collapse -->\n      </div>\n    </div>\n\n    <div class=\"container\">\n\n      <!-- Main component for a primary marketing message or call to action -->\n      <div class=\"jumbotron\">\n        <h1>Navbar example</h1>\n        <p>This example is a quick exercise to illustrate how the default, static and fixed to top navbar work. It includes the responsive CSS and HTML, so it also adapts to your viewport and device.</p>\n        <p>To see the difference between static and fixed top navbars, just scroll.</p>\n        <p>\n          <a class=\"btn btn-lg btn-primary\" href=\"../../components/#navbar\">View navbar docs &raquo;</a>\n        </p>\n      </div>\n\n    </div> <!-- /container -->\n\n\n    <!-- Bootstrap core JavaScript\n    ================================================== -->\n    <!-- Placed at the end of the document so the pages load faster -->\n    <script src=\"../../assets/js/jquery.js\"></script>\n    <script src=\"../../dist/js/bootstrap.min.js\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/sass-bootstrap/examples/navbar-fixed-top/navbar-fixed-top.css",
    "content": "body {\n  min-height: 2000px;\n  padding-top: 70px;\n}\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/sass-bootstrap/examples/navbar-static-top/index.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"utf-8\">\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n    <meta name=\"description\" content=\"\">\n    <meta name=\"author\" content=\"\">\n    <link rel=\"shortcut icon\" href=\"../../assets/ico/favicon.png\">\n\n    <title>Static Top Navbar Example for Bootstrap</title>\n\n    <!-- Bootstrap core CSS -->\n    <link href=\"../../dist/css/bootstrap.css\" rel=\"stylesheet\">\n\n    <!-- Custom styles for this template -->\n    <link href=\"navbar-static-top.css\" rel=\"stylesheet\">\n\n    <!-- HTML5 shim and Respond.js IE8 support of HTML5 elements and media queries -->\n    <!--[if lt IE 9]>\n      <script src=\"../../assets/js/html5shiv.js\"></script>\n      <script src=\"../../assets/js/respond.min.js\"></script>\n    <![endif]-->\n  </head>\n\n  <body>\n\n    <!-- Static navbar -->\n    <div class=\"navbar navbar-default navbar-static-top\">\n      <div class=\"container\">\n        <div class=\"navbar-header\">\n          <button type=\"button\" class=\"navbar-toggle\" data-toggle=\"collapse\" data-target=\".navbar-collapse\">\n            <span class=\"icon-bar\"></span>\n            <span class=\"icon-bar\"></span>\n            <span class=\"icon-bar\"></span>\n          </button>\n          <a class=\"navbar-brand\" href=\"#\">Project name</a>\n        </div>\n        <div class=\"navbar-collapse collapse\">\n          <ul class=\"nav navbar-nav\">\n            <li class=\"active\"><a href=\"#\">Home</a></li>\n            <li><a href=\"#about\">About</a></li>\n            <li><a href=\"#contact\">Contact</a></li>\n            <li class=\"dropdown\">\n              <a href=\"#\" class=\"dropdown-toggle\" data-toggle=\"dropdown\">Dropdown <b class=\"caret\"></b></a>\n              <ul class=\"dropdown-menu\">\n                <li><a href=\"#\">Action</a></li>\n                <li><a href=\"#\">Another action</a></li>\n                <li><a href=\"#\">Something else here</a></li>\n                <li class=\"divider\"></li>\n                <li class=\"dropdown-header\">Nav header</li>\n                <li><a href=\"#\">Separated link</a></li>\n                <li><a href=\"#\">One more separated link</a></li>\n              </ul>\n            </li>\n          </ul>\n          <ul class=\"nav navbar-nav navbar-right\">\n            <li><a href=\"../navbar/\">Default</a></li>\n            <li class=\"active\"><a href=\"./\">Static top</a></li>\n            <li><a href=\"../navbar-fixed-top/\">Fixed top</a></li>\n          </ul>\n        </div><!--/.nav-collapse -->\n      </div>\n    </div>\n\n\n    <div class=\"container\">\n\n      <!-- Main component for a primary marketing message or call to action -->\n      <div class=\"jumbotron\">\n        <h1>Navbar example</h1>\n        <p>This example is a quick exercise to illustrate how the default, static and fixed to top navbar work. It includes the responsive CSS and HTML, so it also adapts to your viewport and device.</p>\n        <p>To see the difference between static and fixed top navbars, just scroll.</p>\n        <p>\n          <a class=\"btn btn-lg btn-primary\" href=\"../../components/#navbar\">View navbar docs &raquo;</a>\n        </p>\n      </div>\n\n    </div> <!-- /container -->\n\n\n    <!-- Bootstrap core JavaScript\n    ================================================== -->\n    <!-- Placed at the end of the document so the pages load faster -->\n    <script src=\"../../assets/js/jquery.js\"></script>\n    <script src=\"../../dist/js/bootstrap.min.js\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/sass-bootstrap/examples/navbar-static-top/navbar-static-top.css",
    "content": "body {\n  min-height: 2000px;\n}\n\n.navbar-static-top {\n  margin-bottom: 19px;\n}"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/sass-bootstrap/examples/non-responsive/index.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"utf-8\">\n    <meta name=\"description\" content=\"\">\n    <meta name=\"author\" content=\"\">\n\n    <!-- Note there is no responsive meta tag here -->\n\n    <link rel=\"shortcut icon\" href=\"../../assets/ico/favicon.png\">\n\n    <title>Non-responsive Template for Bootstrap</title>\n\n    <!-- Bootstrap core CSS -->\n    <link href=\"../../dist/css/bootstrap.css\" rel=\"stylesheet\">\n\n    <!-- Custom styles for this template -->\n    <link href=\"non-responsive.css\" rel=\"stylesheet\">\n\n    <!-- HTML5 shim and Respond.js IE8 support of HTML5 elements and media queries -->\n    <!--[if lt IE 9]>\n      <script src=\"../../assets/js/html5shiv.js\"></script>\n      <script src=\"../../assets/js/respond.min.js\"></script>\n    <![endif]-->\n  </head>\n\n  <body>\n\n    <!-- Fixed navbar -->\n    <div class=\"navbar navbar-default navbar-fixed-top\">\n      <div class=\"container\">\n        <div class=\"navbar-header\">\n          <button type=\"button\" class=\"navbar-toggle\" data-toggle=\"collapse\" data-target=\".navbar-collapse\">\n            <span class=\"icon-bar\"></span>\n            <span class=\"icon-bar\"></span>\n            <span class=\"icon-bar\"></span>\n          </button>\n          <a class=\"navbar-brand\" href=\"#\">Project name</a>\n        </div>\n        <div class=\"navbar-collapse collapse\">\n          <ul class=\"nav navbar-nav\">\n            <li class=\"active\"><a href=\"#\">Home</a></li>\n            <li><a href=\"#about\">About</a></li>\n            <li><a href=\"#contact\">Contact</a></li>\n            <li class=\"dropdown\">\n              <a href=\"#\" class=\"dropdown-toggle\" data-toggle=\"dropdown\">Dropdown <b class=\"caret\"></b></a>\n              <ul class=\"dropdown-menu\">\n                <li><a href=\"#\">Action</a></li>\n                <li><a href=\"#\">Another action</a></li>\n                <li><a href=\"#\">Something else here</a></li>\n                <li class=\"divider\"></li>\n                <li class=\"dropdown-header\">Nav header</li>\n                <li><a href=\"#\">Separated link</a></li>\n                <li><a href=\"#\">One more separated link</a></li>\n              </ul>\n            </li>\n          </ul>\n          <ul class=\"nav navbar-nav navbar-right\">\n            <li><a href=\"#\">Link</a></li>\n            <li><a href=\"#\">Link</a></li>\n            <li><a href=\"#\">Link</a></li>\n          </ul>\n        </div><!--/.nav-collapse -->\n      </div>\n    </div>\n\n    <div class=\"container\">\n\n      <div class=\"page-header\">\n        <h1>Non-responsive Bootstrap</h1>\n        <p class=\"lead\">Disable the responsiveness of Bootstrap by fixing the width of the container and using the first grid system tier.</p>\n      </div>\n\n      <h3>What changes</h3>\n      <p>Note the lack of the <code>&lt;meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"&gt;</code>, which disables the zooming aspect of sites in mobile devices. In addition, we reset our container's width and are basically good to go.</p>\n\n      <h3>Regarding navbars</h3>\n      <p>As a heads up, the navbar component is rather tricky here in that the styles for displaying it are rather specific and detailed. Overrides to ensure desktop styles display are not as performant or sleek as one would like. Just be aware there may be potential gotchas as you build on top of this example when using the navbar.</p>\n\n      <h3>Non-responsive grid system</h3>\n      <div class=\"row\">\n        <div class=\"col-xs-4\">One third</div>\n        <div class=\"col-xs-4\">One third</div>\n        <div class=\"col-xs-4\">One third</div>\n      </div>\n\n    </div> <!-- /container -->\n\n\n    <!-- Bootstrap core JavaScript\n    ================================================== -->\n    <!-- Placed at the end of the document so the pages load faster -->\n    <script src=\"../../assets/js/jquery.js\"></script>\n    <script src=\"../../dist/js/bootstrap.min.js\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/sass-bootstrap/examples/non-responsive/non-responsive.css",
    "content": "/* Template-specific stuff\n *\n * Customizations just for the template; these are not necessary for anything\n * with disabling the responsiveness.\n */\n\n/* Account for fixed navbar */\nbody {\n  padding-top: 70px;\n  padding-bottom: 30px;\n}\n\n/* Finesse the page header spacing */\n.page-header {\n  margin-bottom: 30px;\n}\n.page-header .lead {\n  margin-bottom: 10px;\n}\n\n\n/* Non-responsive overrides\n *\n * Utilitze the following CSS to disable the responsive-ness of the container,\n * grid system, and navbar.\n */\n\n/* Reset the container */\n.container {\n  max-width: none !important;\n  width: 970px;\n}\n\n/* Demonstrate the grids */\n.col-xs-4 {\n  padding-top: 15px;\n  padding-bottom: 15px;\n  background-color: #eee;\n  border: 1px solid #ddd;\n  background-color: rgba(86,61,124,.15);\n  border: 1px solid rgba(86,61,124,.2);\n}\n\n.container .navbar-header,\n.container .navbar-collapse {\n  margin-right: 0;\n  margin-left: 0;\n}\n\n/* Always float the navbar header */\n.navbar-header {\n  float: left;\n}\n\n/* Undo the collapsing navbar */\n.navbar-collapse {\n  display: block !important;\n  height: auto !important;\n  padding-bottom: 0;\n  overflow: visible !important;\n}\n\n.navbar-toggle {\n  display: none;\n}\n\n.navbar-brand {\n  margin-left: -15px;\n}\n\n/* Always apply the floated nav */\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: 15px;\n}\n\n/* Redeclare since we override the float above */\n.navbar-nav.navbar-right {\n  float: right;\n}\n\n/* Undo custom dropdowns */\n.navbar .open .dropdown-menu {\n  position: absolute;\n  float: left;\n  background-color: #fff;\n  border: 1px solid #cccccc;\n  border: 1px solid rgba(0, 0, 0, 0.15);\n  border-width: 0 1px 1px;\n  border-radius: 0 0 4px 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}\n.navbar .open .dropdown-menu > li > a {\n  color: #333;\n}\n.navbar .open .dropdown-menu > li > a:hover,\n.navbar .open .dropdown-menu > li > a:focus,\n.navbar .open .dropdown-menu > .active > a,\n.navbar .open .dropdown-menu > .active > a:hover,\n.navbar .open .dropdown-menu > .active > a:focus {\n  color: #fff !important;\n  background-color: #428bca !important;\n}\n.navbar .open .dropdown-menu > .disabled > a,\n.navbar .open .dropdown-menu > .disabled > a:hover,\n.navbar .open .dropdown-menu > .disabled > a:focus {\n  color: #999 !important;\n  background-color: transparent !important;\n}\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/sass-bootstrap/examples/offcanvas/index.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"utf-8\">\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n    <meta name=\"description\" content=\"\">\n    <meta name=\"author\" content=\"\">\n    <link rel=\"shortcut icon\" href=\"../../assets/ico/favicon.png\">\n\n    <title>Off Canvas Template for Bootstrap</title>\n\n    <!-- Bootstrap core CSS -->\n    <link href=\"../../dist/css/bootstrap.min.css\" rel=\"stylesheet\">\n\n    <!-- Custom styles for this template -->\n    <link href=\"offcanvas.css\" rel=\"stylesheet\">\n\n    <!-- HTML5 shim and Respond.js IE8 support of HTML5 elements and media queries -->\n    <!--[if lt IE 9]>\n      <script src=\"../../assets/js/html5shiv.js\"></script>\n      <script src=\"../../assets/js/respond.min.js\"></script>\n    <![endif]-->\n  </head>\n\n  <body>\n    <div class=\"navbar navbar-fixed-top navbar-inverse\" role=\"navigation\">\n      <div class=\"container\">\n        <div class=\"navbar-header\">\n          <button type=\"button\" class=\"navbar-toggle\" data-toggle=\"collapse\" data-target=\".navbar-collapse\">\n            <span class=\"icon-bar\"></span>\n            <span class=\"icon-bar\"></span>\n            <span class=\"icon-bar\"></span>\n          </button>\n          <a class=\"navbar-brand\" href=\"#\">Project name</a>\n        </div>\n        <div class=\"collapse navbar-collapse\">\n          <ul class=\"nav navbar-nav\">\n            <li class=\"active\"><a href=\"#\">Home</a></li>\n            <li><a href=\"#about\">About</a></li>\n            <li><a href=\"#contact\">Contact</a></li>\n          </ul>\n        </div><!-- /.nav-collapse -->\n      </div><!-- /.container -->\n    </div><!-- /.navbar -->\n\n    <div class=\"container\">\n\n      <div class=\"row row-offcanvas row-offcanvas-right\">\n        <div class=\"col-xs-12 col-sm-9\">\n          <p class=\"pull-right visible-xs\">\n            <button type=\"button\" class=\"btn btn-primary btn-xs\" data-toggle=\"offcanvas\">Toggle nav</button>\n          </p>\n          <div class=\"jumbotron\">\n            <h1>Hello, world!</h1>\n            <p>This is an example to show the potential of an offcanvas layout pattern in Bootstrap. Try some responsive-range viewport sizes to see it in action.</p>\n          </div>\n          <div class=\"row\">\n            <div class=\"col-6 col-sm-6 col-lg-4\">\n              <h2>Heading</h2>\n              <p>Donec id elit non mi porta gravida at eget metus. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus. Etiam porta sem malesuada magna mollis euismod. Donec sed odio dui. </p>\n              <p><a class=\"btn btn-default\" href=\"#\">View details &raquo;</a></p>\n            </div><!--/span-->\n            <div class=\"col-6 col-sm-6 col-lg-4\">\n              <h2>Heading</h2>\n              <p>Donec id elit non mi porta gravida at eget metus. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus. Etiam porta sem malesuada magna mollis euismod. Donec sed odio dui. </p>\n              <p><a class=\"btn btn-default\" href=\"#\">View details &raquo;</a></p>\n            </div><!--/span-->\n            <div class=\"col-6 col-sm-6 col-lg-4\">\n              <h2>Heading</h2>\n              <p>Donec id elit non mi porta gravida at eget metus. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus. Etiam porta sem malesuada magna mollis euismod. Donec sed odio dui. </p>\n              <p><a class=\"btn btn-default\" href=\"#\">View details &raquo;</a></p>\n            </div><!--/span-->\n            <div class=\"col-6 col-sm-6 col-lg-4\">\n              <h2>Heading</h2>\n              <p>Donec id elit non mi porta gravida at eget metus. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus. Etiam porta sem malesuada magna mollis euismod. Donec sed odio dui. </p>\n              <p><a class=\"btn btn-default\" href=\"#\">View details &raquo;</a></p>\n            </div><!--/span-->\n            <div class=\"col-6 col-sm-6 col-lg-4\">\n              <h2>Heading</h2>\n              <p>Donec id elit non mi porta gravida at eget metus. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus. Etiam porta sem malesuada magna mollis euismod. Donec sed odio dui. </p>\n              <p><a class=\"btn btn-default\" href=\"#\">View details &raquo;</a></p>\n            </div><!--/span-->\n            <div class=\"col-6 col-sm-6 col-lg-4\">\n              <h2>Heading</h2>\n              <p>Donec id elit non mi porta gravida at eget metus. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus. Etiam porta sem malesuada magna mollis euismod. Donec sed odio dui. </p>\n              <p><a class=\"btn btn-default\" href=\"#\">View details &raquo;</a></p>\n            </div><!--/span-->\n          </div><!--/row-->\n        </div><!--/span-->\n\n        <div class=\"col-xs-6 col-sm-3 sidebar-offcanvas\" id=\"sidebar\" role=\"navigation\">\n          <div class=\"well sidebar-nav\">\n            <ul class=\"nav\">\n              <li>Sidebar</li>\n              <li class=\"active\"><a href=\"#\">Link</a></li>\n              <li><a href=\"#\">Link</a></li>\n              <li><a href=\"#\">Link</a></li>\n              <li>Sidebar</li>\n              <li><a href=\"#\">Link</a></li>\n              <li><a href=\"#\">Link</a></li>\n              <li><a href=\"#\">Link</a></li>\n              <li>Sidebar</li>\n              <li><a href=\"#\">Link</a></li>\n              <li><a href=\"#\">Link</a></li>\n            </ul>\n          </div><!--/.well -->\n        </div><!--/span-->\n      </div><!--/row-->\n\n      <hr>\n\n      <footer>\n        <p>&copy; Company 2013</p>\n      </footer>\n\n    </div><!--/.container-->\n\n\n\n    <!-- Bootstrap core JavaScript\n    ================================================== -->\n    <!-- Placed at the end of the document so the pages load faster -->\n    <script src=\"../../assets/js/jquery.js\"></script>\n    <script src=\"../../dist/js/bootstrap.min.js\"></script>\n    <script src=\"offcanvas.js\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/sass-bootstrap/examples/offcanvas/offcanvas.css",
    "content": "/*\n * Style twaks\n * --------------------------------------------------\n */\nbody {\n  padding-top: 70px;\n}\nfooter {\n  padding-left: 15px;\n  padding-right: 15px;\n}\n\n/*\n * Off Canvas\n * --------------------------------------------------\n */\n@media screen and (max-width: 768px) {\n  .row-offcanvas {\n    position: relative;\n    -webkit-transition: all 0.25s ease-out;\n    -moz-transition: all 0.25s ease-out;\n    transition: all 0.25s ease-out;\n  }\n\n  .row-offcanvas-right\n  .sidebar-offcanvas {\n    right: -50%; /* 6 columns */\n  }\n\n  .row-offcanvas-left\n  .sidebar-offcanvas {\n    left: -50%; /* 6 columns */\n  }\n\n  .row-offcanvas-right.active {\n    right: 50%; /* 6 columns */\n  }\n\n  .row-offcanvas-left.active {\n    left: 50%; /* 6 columns */\n  }\n\n  .sidebar-offcanvas {\n    position: absolute;\n    top: 0;\n    width: 50%; /* 6 columns */\n  }\n}"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/sass-bootstrap/examples/offcanvas/offcanvas.js",
    "content": "$(document).ready(function() {\n  $('[data-toggle=offcanvas]').click(function() {\n    $('.row-offcanvas').toggleClass('active');\n  });\n});"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/sass-bootstrap/examples/signin/index.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"utf-8\">\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n    <meta name=\"description\" content=\"\">\n    <meta name=\"author\" content=\"\">\n    <link rel=\"shortcut icon\" href=\"../../assets/ico/favicon.png\">\n\n    <title>Signin Template for Bootstrap</title>\n\n    <!-- Bootstrap core CSS -->\n    <link href=\"../../dist/css/bootstrap.css\" rel=\"stylesheet\">\n\n    <!-- Custom styles for this template -->\n    <link href=\"signin.css\" rel=\"stylesheet\">\n\n    <!-- HTML5 shim and Respond.js IE8 support of HTML5 elements and media queries -->\n    <!--[if lt IE 9]>\n      <script src=\"../../assets/js/html5shiv.js\"></script>\n      <script src=\"../../assets/js/respond.min.js\"></script>\n    <![endif]-->\n  </head>\n\n  <body>\n\n    <div class=\"container\">\n\n      <form class=\"form-signin\">\n        <h2 class=\"form-signin-heading\">Please sign in</h2>\n        <input type=\"text\" class=\"form-control\" placeholder=\"Email address\" autofocus>\n        <input type=\"password\" class=\"form-control\" placeholder=\"Password\">\n        <label class=\"checkbox\">\n          <input type=\"checkbox\" value=\"remember-me\"> Remember me\n        </label>\n        <button class=\"btn btn-lg btn-primary btn-block\" type=\"submit\">Sign in</button>\n      </form>\n\n    </div> <!-- /container -->\n\n\n    <!-- Bootstrap core JavaScript\n    ================================================== -->\n    <!-- Placed at the end of the document so the pages load faster -->\n  </body>\n</html>\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/sass-bootstrap/examples/signin/signin.css",
    "content": "body {\n  padding-top: 40px;\n  padding-bottom: 40px;\n  background-color: #eee;\n}\n\n.form-signin {\n  max-width: 330px;\n  padding: 15px;\n  margin: 0 auto;\n}\n.form-signin .form-signin-heading,\n.form-signin .checkbox {\n  margin-bottom: 10px;\n}\n.form-signin .checkbox {\n  font-weight: normal;\n}\n.form-signin .form-control {\n  position: relative;\n  font-size: 16px;\n  height: auto;\n  padding: 10px;\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n}\n.form-signin .form-control:focus {\n  z-index: 2;\n}\n.form-signin input[type=\"text\"] {\n  margin-bottom: -1px;\n  border-bottom-left-radius: 0;\n  border-bottom-right-radius: 0;\n}\n.form-signin input[type=\"password\"] {\n  margin-bottom: 10px;\n  border-top-left-radius: 0;\n  border-top-right-radius: 0;\n}"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/sass-bootstrap/examples/starter-template/index.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"utf-8\">\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n    <meta name=\"description\" content=\"\">\n    <meta name=\"author\" content=\"\">\n    <link rel=\"shortcut icon\" href=\"../../assets/ico/favicon.png\">\n\n    <title>Starter Template for Bootstrap</title>\n\n    <!-- Bootstrap core CSS -->\n    <link href=\"../../dist/css/bootstrap.css\" rel=\"stylesheet\">\n\n    <!-- Custom styles for this template -->\n    <link href=\"starter-template.css\" rel=\"stylesheet\">\n\n    <!-- HTML5 shim and Respond.js IE8 support of HTML5 elements and media queries -->\n    <!--[if lt IE 9]>\n      <script src=\"../../assets/js/html5shiv.js\"></script>\n      <script src=\"../../assets/js/respond.min.js\"></script>\n    <![endif]-->\n  </head>\n\n  <body>\n\n    <div class=\"navbar navbar-inverse navbar-fixed-top\">\n      <div class=\"container\">\n        <div class=\"navbar-header\">\n          <button type=\"button\" class=\"navbar-toggle\" data-toggle=\"collapse\" data-target=\".navbar-collapse\">\n            <span class=\"icon-bar\"></span>\n            <span class=\"icon-bar\"></span>\n            <span class=\"icon-bar\"></span>\n          </button>\n          <a class=\"navbar-brand\" href=\"#\">Project name</a>\n        </div>\n        <div class=\"collapse navbar-collapse\">\n          <ul class=\"nav navbar-nav\">\n            <li class=\"active\"><a href=\"#\">Home</a></li>\n            <li><a href=\"#about\">About</a></li>\n            <li><a href=\"#contact\">Contact</a></li>\n          </ul>\n        </div><!--/.nav-collapse -->\n      </div>\n    </div>\n\n    <div class=\"container\">\n\n      <div class=\"starter-template\">\n        <h1>Bootstrap starter template</h1>\n        <p class=\"lead\">Use this document as a way to quickly start any new project.<br> All you get is this text and a mostly barebones HTML document.</p>\n      </div>\n\n    </div><!-- /.container -->\n\n\n    <!-- Bootstrap core JavaScript\n    ================================================== -->\n    <!-- Placed at the end of the document so the pages load faster -->\n    <script src=\"../../assets/js/jquery.js\"></script>\n    <script src=\"../../dist/js/bootstrap.min.js\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/sass-bootstrap/examples/starter-template/starter-template.css",
    "content": "body {\n  padding-top: 50px;\n}\n.starter-template {\n  padding: 40px 15px;\n  text-align: center;\n}\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/sass-bootstrap/examples/sticky-footer/index.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"utf-8\">\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n    <meta name=\"description\" content=\"\">\n    <meta name=\"author\" content=\"\">\n    <link rel=\"shortcut icon\" href=\"../../assets/ico/favicon.png\">\n\n    <title>Sticky Footer Template for Bootstrap</title>\n\n    <!-- Bootstrap core CSS -->\n    <link href=\"../../dist/css/bootstrap.css\" rel=\"stylesheet\">\n\n    <!-- Custom styles for this template -->\n    <link href=\"sticky-footer.css\" rel=\"stylesheet\">\n\n    <!-- HTML5 shim and Respond.js IE8 support of HTML5 elements and media queries -->\n    <!--[if lt IE 9]>\n      <script src=\"../../assets/js/html5shiv.js\"></script>\n      <script src=\"../../assets/js/respond.min.js\"></script>\n    <![endif]-->\n  </head>\n\n  <body>\n\n    <!-- Wrap all page content here -->\n    <div id=\"wrap\">\n\n      <!-- Begin page content -->\n      <div class=\"container\">\n        <div class=\"page-header\">\n          <h1>Sticky footer</h1>\n        </div>\n        <p class=\"lead\">Pin a fixed-height footer to the bottom of the viewport in desktop browsers with this custom HTML and CSS.</p>\n        <p>Use <a href=\"../sticky-footer-navbar\">the sticky footer with a fixed navbar</a> if need be, too.</p>\n      </div>\n    </div>\n\n    <div id=\"footer\">\n      <div class=\"container\">\n        <p class=\"text-muted credit\">Example courtesy <a href=\"http://martinbean.co.uk\">Martin Bean</a> and <a href=\"http://ryanfait.com/sticky-footer/\">Ryan Fait</a>.</p>\n      </div>\n    </div>\n\n\n    <!-- Bootstrap core JavaScript\n    ================================================== -->\n    <!-- Placed at the end of the document so the pages load faster -->\n  </body>\n</html>\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/sass-bootstrap/examples/sticky-footer/sticky-footer.css",
    "content": "/* Sticky footer styles\n-------------------------------------------------- */\n\nhtml,\nbody {\n  height: 100%;\n  /* The html and body elements cannot have any padding or margin. */\n}\n\n/* Wrapper for page content to push down footer */\n#wrap {\n  min-height: 100%;\n  height: auto !important;\n  height: 100%;\n  /* Negative indent footer by its height */\n  margin: 0 auto -60px;\n  /* Pad bottom by footer height */\n  padding: 0 0 60px;\n}\n\n/* Set the fixed height of the footer here */\n#footer {\n  height: 60px;\n  background-color: #f5f5f5;\n}\n\n\n/* Custom page CSS\n-------------------------------------------------- */\n/* Not required for template or sticky footer method. */\n\n.container {\n  width: auto;\n  max-width: 680px;\n  padding: 0 15px;\n}\n.container .credit {\n  margin: 20px 0;\n}"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/sass-bootstrap/examples/sticky-footer-navbar/index.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"utf-8\">\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n    <meta name=\"description\" content=\"\">\n    <meta name=\"author\" content=\"\">\n    <link rel=\"shortcut icon\" href=\"../../assets/ico/favicon.png\">\n\n    <title>Sticky Footer Navbar Template for Bootstrap</title>\n\n    <!-- Bootstrap core CSS -->\n    <link href=\"../../dist/css/bootstrap.css\" rel=\"stylesheet\">\n\n    <!-- Custom styles for this template -->\n    <link href=\"sticky-footer-navbar.css\" rel=\"stylesheet\">\n\n    <!-- HTML5 shim and Respond.js IE8 support of HTML5 elements and media queries -->\n    <!--[if lt IE 9]>\n      <script src=\"../../assets/js/html5shiv.js\"></script>\n      <script src=\"../../assets/js/respond.min.js\"></script>\n    <![endif]-->\n  </head>\n\n  <body>\n\n    <!-- Wrap all page content here -->\n    <div id=\"wrap\">\n\n      <!-- Fixed navbar -->\n      <div class=\"navbar navbar-default navbar-fixed-top\">\n        <div class=\"container\">\n          <div class=\"navbar-header\">\n            <button type=\"button\" class=\"navbar-toggle\" data-toggle=\"collapse\" data-target=\".navbar-collapse\">\n              <span class=\"icon-bar\"></span>\n              <span class=\"icon-bar\"></span>\n              <span class=\"icon-bar\"></span>\n            </button>\n            <a class=\"navbar-brand\" href=\"#\">Project name</a>\n          </div>\n          <div class=\"collapse navbar-collapse\">\n            <ul class=\"nav navbar-nav\">\n              <li class=\"active\"><a href=\"#\">Home</a></li>\n              <li><a href=\"#about\">About</a></li>\n              <li><a href=\"#contact\">Contact</a></li>\n              <li class=\"dropdown\">\n                <a href=\"#\" class=\"dropdown-toggle\" data-toggle=\"dropdown\">Dropdown <b class=\"caret\"></b></a>\n                <ul class=\"dropdown-menu\">\n                  <li><a href=\"#\">Action</a></li>\n                  <li><a href=\"#\">Another action</a></li>\n                  <li><a href=\"#\">Something else here</a></li>\n                  <li class=\"divider\"></li>\n                  <li class=\"dropdown-header\">Nav header</li>\n                  <li><a href=\"#\">Separated link</a></li>\n                  <li><a href=\"#\">One more separated link</a></li>\n                </ul>\n              </li>\n            </ul>\n          </div><!--/.nav-collapse -->\n        </div>\n      </div>\n\n      <!-- Begin page content -->\n      <div class=\"container\">\n        <div class=\"page-header\">\n          <h1>Sticky footer with fixed navbar</h1>\n        </div>\n        <p class=\"lead\">Pin a fixed-height footer to the bottom of the viewport in desktop browsers with this custom HTML and CSS. A fixed navbar has been added within <code>#wrap</code> with <code>padding-top: 60px;</code> on the <code>.container</code>.</p>\n        <p>Back to <a href=\"../sticky-footer\">the default sticky footer</a> minus the navbar.</p>\n      </div>\n    </div>\n\n    <div id=\"footer\">\n      <div class=\"container\">\n        <p class=\"text-muted credit\">Example courtesy <a href=\"http://martinbean.co.uk\">Martin Bean</a> and <a href=\"http://ryanfait.com/sticky-footer/\">Ryan Fait</a>.</p>\n      </div>\n    </div>\n\n\n    <!-- Bootstrap core JavaScript\n    ================================================== -->\n    <!-- Placed at the end of the document so the pages load faster -->\n    <script src=\"../../assets/js/jquery.js\"></script>\n    <script src=\"../../dist/js/bootstrap.min.js\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/sass-bootstrap/examples/sticky-footer-navbar/sticky-footer-navbar.css",
    "content": "/* Sticky footer styles\n-------------------------------------------------- */\n\nhtml,\nbody {\n  height: 100%;\n  /* The html and body elements cannot have any padding or margin. */\n}\n\n/* Wrapper for page content to push down footer */\n#wrap {\n  min-height: 100%;\n  height: auto !important;\n  height: 100%;\n  /* Negative indent footer by its height */\n  margin: 0 auto -60px;\n  /* Pad bottom by footer height */\n  padding: 0 0 60px;\n}\n\n/* Set the fixed height of the footer here */\n#footer {\n  height: 60px;\n  background-color: #f5f5f5;\n}\n\n\n/* Custom page CSS\n-------------------------------------------------- */\n/* Not required for template or sticky footer method. */\n\n#wrap > .container {\n  padding: 60px 15px 0;\n}\n.container .credit {\n  margin: 20px 0;\n}\n\n#footer > .container {\n  padding-left: 15px;\n  padding-right: 15px;\n}\n\ncode {\n  font-size: 80%;\n}"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/sass-bootstrap/examples/theme/index.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"utf-8\">\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n    <meta name=\"description\" content=\"\">\n    <meta name=\"author\" content=\"\">\n    <link rel=\"shortcut icon\" href=\"../../assets/ico/favicon.png\">\n\n    <title>Theme Template for Bootstrap</title>\n\n    <!-- Bootstrap core CSS -->\n    <link href=\"../../dist/css/bootstrap.css\" rel=\"stylesheet\">\n    <!-- Bootstrap theme -->\n    <link href=\"../../dist/css/bootstrap-theme.min.css\" rel=\"stylesheet\">\n\n    <!-- Custom styles for this template -->\n    <link href=\"theme.css\" rel=\"stylesheet\">\n\n    <!-- HTML5 shim and Respond.js IE8 support of HTML5 elements and media queries -->\n    <!--[if lt IE 9]>\n      <script src=\"../../assets/js/html5shiv.js\"></script>\n      <script src=\"../../assets/js/respond.min.js\"></script>\n    <![endif]-->\n  </head>\n\n  <body>\n\n    <!-- Fixed navbar -->\n    <div class=\"navbar navbar-inverse navbar-fixed-top\">\n      <div class=\"container\">\n        <div class=\"navbar-header\">\n          <button type=\"button\" class=\"navbar-toggle\" data-toggle=\"collapse\" data-target=\".navbar-collapse\">\n            <span class=\"icon-bar\"></span>\n            <span class=\"icon-bar\"></span>\n            <span class=\"icon-bar\"></span>\n          </button>\n          <a class=\"navbar-brand\" href=\"#\">Bootstrap theme</a>\n        </div>\n        <div class=\"navbar-collapse collapse\">\n          <ul class=\"nav navbar-nav\">\n            <li class=\"active\"><a href=\"#\">Home</a></li>\n            <li><a href=\"#about\">About</a></li>\n            <li><a href=\"#contact\">Contact</a></li>\n            <li class=\"dropdown\">\n              <a href=\"#\" class=\"dropdown-toggle\" data-toggle=\"dropdown\">Dropdown <b class=\"caret\"></b></a>\n              <ul class=\"dropdown-menu\">\n                <li><a href=\"#\">Action</a></li>\n                <li><a href=\"#\">Another action</a></li>\n                <li><a href=\"#\">Something else here</a></li>\n                <li class=\"divider\"></li>\n                <li class=\"dropdown-header\">Nav header</li>\n                <li><a href=\"#\">Separated link</a></li>\n                <li><a href=\"#\">One more separated link</a></li>\n              </ul>\n            </li>\n          </ul>\n        </div><!--/.nav-collapse -->\n      </div>\n    </div>\n\n    <div class=\"container theme-showcase\">\n\n      <!-- Main jumbotron for a primary marketing message or call to action -->\n      <div class=\"jumbotron\">\n        <h1>Hello, world!</h1>\n        <p>This is a template for a simple marketing or informational website. It includes a large callout called the hero unit and three supporting pieces of content. Use it as a starting point to create something more unique.</p>\n        <p><a class=\"btn btn-primary btn-lg\">Learn more &raquo;</a></p>\n      </div>\n\n\n\n      <div class=\"page-header\">\n        <h1>Buttons</h1>\n      </div>\n      <p>\n        <button type=\"button\" class=\"btn btn-lg btn-default\">Default</button>\n        <button type=\"button\" class=\"btn btn-lg btn-primary\">Primary</button>\n        <button type=\"button\" class=\"btn btn-lg btn-success\">Success</button>\n        <button type=\"button\" class=\"btn btn-lg btn-info\">Info</button>\n        <button type=\"button\" class=\"btn btn-lg btn-warning\">Warning</button>\n        <button type=\"button\" class=\"btn btn-lg btn-danger\">Danger</button>\n        <button type=\"button\" class=\"btn btn-lg btn-link\">Link</button>\n      </p>\n      <p>\n        <button type=\"button\" class=\"btn btn-default\">Default</button>\n        <button type=\"button\" class=\"btn btn-primary\">Primary</button>\n        <button type=\"button\" class=\"btn btn-success\">Success</button>\n        <button type=\"button\" class=\"btn btn-info\">Info</button>\n        <button type=\"button\" class=\"btn btn-warning\">Warning</button>\n        <button type=\"button\" class=\"btn btn-danger\">Danger</button>\n        <button type=\"button\" class=\"btn btn-link\">Link</button>\n      </p>\n      <p>\n        <button type=\"button\" class=\"btn btn-sm btn-default\">Default</button>\n        <button type=\"button\" class=\"btn btn-sm btn-primary\">Primary</button>\n        <button type=\"button\" class=\"btn btn-sm btn-success\">Success</button>\n        <button type=\"button\" class=\"btn btn-sm btn-info\">Info</button>\n        <button type=\"button\" class=\"btn btn-sm btn-warning\">Warning</button>\n        <button type=\"button\" class=\"btn btn-sm btn-danger\">Danger</button>\n        <button type=\"button\" class=\"btn btn-sm btn-link\">Link</button>\n      </p>\n      <p>\n        <button type=\"button\" class=\"btn btn-xs btn-default\">Default</button>\n        <button type=\"button\" class=\"btn btn-xs btn-primary\">Primary</button>\n        <button type=\"button\" class=\"btn btn-xs btn-success\">Success</button>\n        <button type=\"button\" class=\"btn btn-xs btn-info\">Info</button>\n        <button type=\"button\" class=\"btn btn-xs btn-warning\">Warning</button>\n        <button type=\"button\" class=\"btn btn-xs btn-danger\">Danger</button>\n        <button type=\"button\" class=\"btn btn-xs btn-link\">Link</button>\n      </p>\n\n\n\n      <div class=\"page-header\">\n        <h1>Thumbnails</h1>\n      </div>\n      <img data-src=\"holder.js/200x200\" src=\"data:image/png;base64,\" class=\"img-thumbnail\" alt=\"A generic square placeholder image with a white border around it, making it resemble a photograph taken with an old instant camera\">\n\n\n\n      <div class=\"page-header\">\n        <h1>Dropdown menus</h1>\n      </div>\n      <div class=\"dropdown theme-dropdown clearfix\">\n        <a id=\"dropdownMenu1\" href=\"#\" role=\"button\" class=\"sr-only dropdown-toggle\" data-toggle=\"dropdown\">Dropdown <b class=\"caret\"></b></a>\n        <ul class=\"dropdown-menu\" role=\"menu\" aria-labelledby=\"dropdownMenu1\">\n          <li role=\"presentation\"><a role=\"menuitem\" tabindex=\"-1\" href=\"#\">Action</a></li>\n          <li role=\"presentation\"><a role=\"menuitem\" tabindex=\"-1\" href=\"#\">Another action</a></li>\n          <li role=\"presentation\"><a role=\"menuitem\" tabindex=\"-1\" href=\"#\">Something else here</a></li>\n          <li role=\"presentation\" class=\"divider\"></li>\n          <li role=\"presentation\"><a role=\"menuitem\" tabindex=\"-1\" href=\"#\">Separated link</a></li>\n        </ul>\n      </div>\n\n\n\n\n      <div class=\"page-header\">\n        <h1>Navbars</h1>\n      </div>\n\n      <div class=\"navbar navbar-default\">\n        <div class=\"container\">\n          <div class=\"navbar-header\">\n            <button type=\"button\" class=\"navbar-toggle\" data-toggle=\"collapse\" data-target=\".navbar-collapse\">\n              <span class=\"icon-bar\"></span>\n              <span class=\"icon-bar\"></span>\n              <span class=\"icon-bar\"></span>\n            </button>\n            <a class=\"navbar-brand\" href=\"#\">Project name</a>\n          </div>\n          <div class=\"navbar-collapse collapse\">\n            <ul class=\"nav navbar-nav\">\n              <li class=\"active\"><a href=\"#\">Home</a></li>\n              <li><a href=\"#about\">About</a></li>\n              <li><a href=\"#contact\">Contact</a></li>\n              <li class=\"dropdown\">\n                <a href=\"#\" class=\"dropdown-toggle\" data-toggle=\"dropdown\">Dropdown <b class=\"caret\"></b></a>\n                <ul class=\"dropdown-menu\">\n                  <li><a href=\"#\">Action</a></li>\n                  <li><a href=\"#\">Another action</a></li>\n                  <li><a href=\"#\">Something else here</a></li>\n                  <li class=\"divider\"></li>\n                  <li class=\"dropdown-header\">Nav header</li>\n                  <li><a href=\"#\">Separated link</a></li>\n                  <li><a href=\"#\">One more separated link</a></li>\n                </ul>\n              </li>\n            </ul>\n            <ul class=\"nav navbar-nav navbar-right\">\n              <li><a href=\"../navbar/\">Default</a></li>\n              <li><a href=\"../navbar-static-top/\">Static top</a></li>\n              <li class=\"active\"><a href=\"./\">Fixed top</a></li>\n            </ul>\n          </div><!--/.nav-collapse -->\n        </div>\n      </div>\n\n      <div class=\"navbar navbar-inverse\">\n        <div class=\"container\">\n          <div class=\"navbar-header\">\n            <button type=\"button\" class=\"navbar-toggle\" data-toggle=\"collapse\" data-target=\".navbar-collapse\">\n              <span class=\"icon-bar\"></span>\n              <span class=\"icon-bar\"></span>\n              <span class=\"icon-bar\"></span>\n            </button>\n            <a class=\"navbar-brand\" href=\"#\">Project name</a>\n          </div>\n          <div class=\"navbar-collapse collapse\">\n            <ul class=\"nav navbar-nav\">\n              <li class=\"active\"><a href=\"#\">Home</a></li>\n              <li><a href=\"#about\">About</a></li>\n              <li><a href=\"#contact\">Contact</a></li>\n              <li class=\"dropdown\">\n                <a href=\"#\" class=\"dropdown-toggle\" data-toggle=\"dropdown\">Dropdown <b class=\"caret\"></b></a>\n                <ul class=\"dropdown-menu\">\n                  <li><a href=\"#\">Action</a></li>\n                  <li><a href=\"#\">Another action</a></li>\n                  <li><a href=\"#\">Something else here</a></li>\n                  <li class=\"divider\"></li>\n                  <li class=\"dropdown-header\">Nav header</li>\n                  <li><a href=\"#\">Separated link</a></li>\n                  <li><a href=\"#\">One more separated link</a></li>\n                </ul>\n              </li>\n            </ul>\n            <ul class=\"nav navbar-nav navbar-right\">\n              <li><a href=\"../navbar/\">Default</a></li>\n              <li><a href=\"../navbar-static-top/\">Static top</a></li>\n              <li class=\"active\"><a href=\"./\">Fixed top</a></li>\n            </ul>\n          </div><!--/.nav-collapse -->\n        </div>\n      </div>\n\n\n\n      <div class=\"page-header\">\n        <h1>Alerts</h1>\n      </div>\n      <div class=\"alert alert-success\">\n        <strong>Well done!</strong> You successfully read this important alert message.\n      </div>\n      <div class=\"alert alert-info\">\n        <strong>Heads up!</strong> This alert needs your attention, but it's not super important.\n      </div>\n      <div class=\"alert alert-warning\">\n        <strong>Warning!</strong> Best check yo self, you're not looking too good.\n      </div>\n      <div class=\"alert alert-danger\">\n        <strong>Oh snap!</strong> Change a few things up and try submitting again.\n      </div>\n\n\n\n      <div class=\"page-header\">\n        <h1>Progress bars</h1>\n      </div>\n      <div class=\"progress\">\n        <div class=\"progress-bar\" role=\"progressbar\" aria-valuenow=\"60\" aria-valuemin=\"0\" aria-valuemax=\"100\" style=\"width: 60%;\"><span class=\"sr-only\">60% Complete</span></div>\n      </div>\n      <div class=\"progress\">\n        <div class=\"progress-bar progress-bar-success\" role=\"progressbar\" aria-valuenow=\"40\" aria-valuemin=\"0\" aria-valuemax=\"100\" style=\"width: 40%\"><span class=\"sr-only\">40% Complete (success)</span></div>\n      </div>\n      <div class=\"progress\">\n        <div class=\"progress-bar progress-bar-info\" role=\"progressbar\" aria-valuenow=\"20\" aria-valuemin=\"0\" aria-valuemax=\"100\" style=\"width: 20%\"><span class=\"sr-only\">20% Complete</span></div>\n      </div>\n      <div class=\"progress\">\n        <div class=\"progress-bar progress-bar-warning\" role=\"progressbar\" aria-valuenow=\"60\" aria-valuemin=\"0\" aria-valuemax=\"100\" style=\"width: 60%\"><span class=\"sr-only\">60% Complete (warning)</span></div>\n      </div>\n      <div class=\"progress\">\n        <div class=\"progress-bar progress-bar-danger\" role=\"progressbar\" aria-valuenow=\"80\" aria-valuemin=\"0\" aria-valuemax=\"100\" style=\"width: 80%\"><span class=\"sr-only\">80% Complete (danger)</span></div>\n      </div>\n      <div class=\"progress\">\n        <div class=\"progress-bar progress-bar-success\" style=\"width: 35%\"><span class=\"sr-only\">35% Complete (success)</span></div>\n        <div class=\"progress-bar progress-bar-warning\" style=\"width: 20%\"><span class=\"sr-only\">20% Complete (warning)</span></div>\n        <div class=\"progress-bar progress-bar-danger\" style=\"width: 10%\"><span class='sr-only'>10% Complete (danger)</span></div>\n      </div>\n\n\n\n      <div class=\"page-header\">\n        <h1>List groups</h1>\n      </div>\n      <div class=\"row\">\n        <div class=\"col-sm-4\">\n          <ul class=\"list-group\">\n            <li class=\"list-group-item\">Cras justo odio</li>\n            <li class=\"list-group-item\">Dapibus ac facilisis in</li>\n            <li class=\"list-group-item\">Morbi leo risus</li>\n            <li class=\"list-group-item\">Porta ac consectetur ac</li>\n            <li class=\"list-group-item\">Vestibulum at eros</li>\n          </ul>\n        </div><!-- /.col-sm-4 -->\n        <div class=\"col-sm-4\">\n          <div class=\"list-group\">\n            <a href=\"#\" class=\"list-group-item active\">\n              Cras justo odio\n            </a>\n            <a href=\"#\" class=\"list-group-item\">Dapibus ac facilisis in</a>\n            <a href=\"#\" class=\"list-group-item\">Morbi leo risus</a>\n            <a href=\"#\" class=\"list-group-item\">Porta ac consectetur ac</a>\n            <a href=\"#\" class=\"list-group-item\">Vestibulum at eros</a>\n          </div>\n        </div><!-- /.col-sm-4 -->\n        <div class=\"col-sm-4\">\n          <div class=\"list-group\">\n            <a href=\"#\" class=\"list-group-item active\">\n              <h4 class=\"list-group-item-heading\">List group item heading</h4>\n              <p class=\"list-group-item-text\">Donec id elit non mi porta gravida at eget metus. Maecenas sed diam eget risus varius blandit.</p>\n            </a>\n            <a href=\"#\" class=\"list-group-item\">\n              <h4 class=\"list-group-item-heading\">List group item heading</h4>\n              <p class=\"list-group-item-text\">Donec id elit non mi porta gravida at eget metus. Maecenas sed diam eget risus varius blandit.</p>\n            </a>\n            <a href=\"#\" class=\"list-group-item\">\n              <h4 class=\"list-group-item-heading\">List group item heading</h4>\n              <p class=\"list-group-item-text\">Donec id elit non mi porta gravida at eget metus. Maecenas sed diam eget risus varius blandit.</p>\n            </a>\n          </div>\n        </div><!-- /.col-sm-4 -->\n      </div>\n\n\n\n      <div class=\"page-header\">\n        <h1>Panels</h1>\n      </div>\n      <div class=\"row\">\n        <div class=\"col-sm-4\">\n          <div class=\"panel panel-default\">\n            <div class=\"panel-heading\">\n              <h3 class=\"panel-title\">Panel title</h3>\n            </div>\n            <div class=\"panel-body\">\n              Panel content\n            </div>\n          </div>\n          <div class=\"panel panel-primary\">\n            <div class=\"panel-heading\">\n              <h3 class=\"panel-title\">Panel title</h3>\n            </div>\n            <div class=\"panel-body\">\n              Panel content\n            </div>\n          </div>\n        </div><!-- /.col-sm-4 -->\n        <div class=\"col-sm-4\">\n          <div class=\"panel panel-success\">\n            <div class=\"panel-heading\">\n              <h3 class=\"panel-title\">Panel title</h3>\n            </div>\n            <div class=\"panel-body\">\n              Panel content\n            </div>\n          </div>\n          <div class=\"panel panel-info\">\n            <div class=\"panel-heading\">\n              <h3 class=\"panel-title\">Panel title</h3>\n            </div>\n            <div class=\"panel-body\">\n              Panel content\n            </div>\n          </div>\n        </div><!-- /.col-sm-4 -->\n        <div class=\"col-sm-4\">\n          <div class=\"panel panel-warning\">\n            <div class=\"panel-heading\">\n              <h3 class=\"panel-title\">Panel title</h3>\n            </div>\n            <div class=\"panel-body\">\n              Panel content\n            </div>\n          </div>\n          <div class=\"panel panel-danger\">\n            <div class=\"panel-heading\">\n              <h3 class=\"panel-title\">Panel title</h3>\n            </div>\n            <div class=\"panel-body\">\n              Panel content\n            </div>\n          </div>\n        </div><!-- /.col-sm-4 -->\n      </div>\n\n\n\n      <div class=\"page-header\">\n        <h1>Wells</h1>\n      </div>\n      <div class=\"well\">\n        <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas sed diam eget risus varius blandit sit amet non magna. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Praesent commodo cursus magna, vel scelerisque nisl consectetur et. Cras mattis consectetur purus sit amet fermentum. Duis mollis, est non commodo luctus, nisi erat porttitor ligula, eget lacinia odio sem nec elit. Aenean lacinia bibendum nulla sed consectetur.</p>\n      </div>\n\n\n    </div> <!-- /container -->\n\n\n    <!-- Bootstrap core JavaScript\n    ================================================== -->\n    <!-- Placed at the end of the document so the pages load faster -->\n    <script src=\"../../assets/js/jquery.js\"></script>\n    <script src=\"../../dist/js/bootstrap.min.js\"></script>\n    <script src=\"../../assets/js/holder.js\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/sass-bootstrap/examples/theme/theme.css",
    "content": "body {\n  padding-top: 70px;\n  padding-bottom: 30px;\n}\n\n.theme-dropdown .dropdown-menu {\n  display: block;\n  position: static;\n  margin-bottom: 20px;\n}\n\n.theme-showcase > p > .btn {\n  margin: 5px 0;\n}"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/sass-bootstrap/getting-started.html",
    "content": "---\nlayout: default\ntitle: Getting started\nslug: getting-started\nlead: \"An overview of Bootstrap, how to download and use, basic templates and examples, and more.\"\nbase_url: \"../\"\n---\n\n\n  <!-- Getting started\n  ================================================== -->\n  <div class=\"bs-docs-section\">\n    <div class=\"page-header\">\n      <h1 id=\"download\">Download Bootstrap</h1>\n    </div>\n    <p class=\"lead\">There are a few easy ways to quickly get started with Bootstrap, each one appealing to a different skill level and use case. Read through to see what suits your particular needs.</p>\n\n    <h3 id=\"download-compiled\">Compiled CSS, JS, and fonts</h3>\n    <p>The fastest way to get Bootstrap is to download the compiled and minified versions of our CSS and JavaScript, along with the included fonts. No documentation or original source files are included.</p>\n    <p><a class=\"btn btn-lg btn-primary\" href=\"{{ site.download_dist }}\" onclick=\"_gaq.push(['_trackEvent', 'Getting started', 'Download', 'Download compiled']);\">Download Bootstrap</a></p>\n\n    <h3 id=\"download-additional\">Additional downloads</h3>\n    <div class=\"bs-docs-dl-options\">\n      <h4>\n        <a href=\"{{ site.download }}\" onclick=\"_gaq.push(['_trackEvent', 'Getting started', 'Download', 'Download source']);\">Download latest source code</a>\n      </h4>\n      <p>Get the original files for all CSS and JavaScript by downloading the latest version directly from GitHub.</p>\n      <h4>\n        <a href=\"{{ site.repo }}\" onclick=\"_gaq.push(['_trackEvent', 'Getting started', 'Download', 'GitHub project']);\">Clone or fork via GitHub</a>\n      </h4>\n      <p>Clone the entire project or fork your own version of Bootstrap to make it your own by visiting us on GitHub.</p>\n      <h4>\n        Install with <a href=\"http://bower.io\">Bower</a>\n      </h4>\n      <p>Install and manage the original files for all CSS and JavaScript, along with a local copy of the docs, using <a href=\"http://bower.io\">Bower</a>.</p>\n      {% highlight bash %}$ bower install bootstrap{% endhighlight %}\n    </div>\n\n    <h3 id=\"download-cdn\">Bootstrap CDN</h3>\n    <p>The folks over at <a href=\"https://www.netdna.com/\">NetDNA</a> have graciously provided CDN support for Bootstrap's CSS and JavaScript. To use, swap your local instances for the <a href=\"http://www.bootstrapcdn.com/\">Bootstrap CDN</a> links listed below.</p>\n{% highlight html %}\n<!-- Latest compiled and minified CSS -->\n<link rel=\"stylesheet\" href=\"{{ site.cdn_css }}\">\n\n<!-- Optional theme -->\n<link rel=\"stylesheet\" href=\"{{ site.cdn_theme_css }}\">\n\n<!-- Latest compiled and minified JavaScript -->\n<script src=\"{{ site.cdn_js }}\"></script>\n{% endhighlight %}\n\n    <div class=\"bs-callout bs-callout-warning\" id=\"callout-less-compilation\">\n      <h4>LESS compilation</h4>\n      <p>If you download the original files, you need to compile Bootstrap's LESS files into usable CSS. To do that, Bootstrap only officially supports <a href=\"http://twitter.github.io/recess/\">Recess</a>, Twitter's CSS hinter built on top of <a href=\"http://lesscss.org\">less.js</a>.</p>\n    </div>\n  </div>\n\n\n\n  <!-- File structure\n  ================================================== -->\n  <div class=\"bs-docs-section\">\n    <div class=\"page-header\">\n      <h1 id=\"whats-included\">What's included</h1>\n    </div>\n    <p class=\"lead\">Within the download you'll find the following directories and files, logically grouping common assets and providing both compiled and minified variations.</p>\n    <p>Once downloaded, unzip the compressed folder to see the structure of (the compiled) Bootstrap. You'll see something like this:</p>\n\n{% highlight bash %}\nbootstrap/\n├── css/\n│   ├── bootstrap.css\n│   ├── bootstrap.min.css\n│   ├── bootstrap-theme.css\n│   ├── bootstrap-theme.min.css\n├── js/\n│   ├── bootstrap.js\n│   ├── bootstrap.min.js\n└── fonts/\n    ├── glyphicons-halflings-regular.eot\n    ├── glyphicons-halflings-regular.svg\n    ├── glyphicons-halflings-regular.ttf\n    └── glyphicons-halflings-regular.woff\n{% endhighlight %}\n\n    <p>This is the most basic form of Bootstrap: compiled files for quick drop-in usage in nearly any web project. We provide compiled CSS and JS (<code>bootstrap.*</code>), as well as compiled and minified CSS and JS (<code>bootstrap.min.*</code>). Fonts from Glyphicons are included, as is the optional Bootstrap theme.</p>\n    <div class=\"bs-callout bs-callout-danger\">\n      <h4>jQuery required</h4>\n      <p>Please note that <strong>all JavaScript plugins require jQuery</strong> to be included, as shown in the <a href=\"#template\">starter template</a>.</p>\n    </div>\n  </div>\n\n\n\n  <!-- Template\n  ================================================== -->\n  <div class=\"bs-docs-section\">\n    <div class=\"page-header\">\n      <h1 id=\"template\">Basic template</h1>\n    </div>\n    <p class=\"lead\">Make use of a super basic HTML template, or dive into a <a href=\"../getting-started#examples\">few examples</a> we've started for you. We encourage folks to iterate on these examples and not simply use them as an end result.</p>\n\n    <p>Copy and paste the HTML from below to get started with a bare bones Bootstrap document.</p>\n{% highlight html %}\n<!DOCTYPE html>\n<html>\n  <head>\n    <title>Bootstrap 101 Template</title>\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n    <!-- Bootstrap -->\n    <link href=\"css/bootstrap.min.css\" rel=\"stylesheet\" media=\"screen\">\n\n    <!-- HTML5 shim and Respond.js IE8 support of HTML5 elements and media queries -->\n    <!--[if lt IE 9]>\n      <script src=\"../../assets/js/html5shiv.js\"></script>\n      <script src=\"../../assets/js/respond.min.js\"></script>\n    <![endif]-->\n  </head>\n  <body>\n    <h1>Hello, world!</h1>\n\n    <!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->\n    <script src=\"//code.jquery.com/jquery.js\"></script>\n    <!-- Include all compiled plugins (below), or include individual files as needed -->\n    <script src=\"js/bootstrap.min.js\"></script>\n  </body>\n</html>\n{% endhighlight %}\n  </div>\n\n\n\n  <!-- Template\n  ================================================== -->\n  <div class=\"bs-docs-section\">\n    <div class=\"page-header\">\n      <h1 id=\"examples\">Examples</h1>\n    </div>\n    <p class=\"lead\">Build on the basic template above with Bootstrap's many components. Check out some of the more advanced tips for how to customize and build on top of them.</p>\n\n    <div class=\"row bs-examples\">\n      <div class=\"col-xs-6 col-md-4\">\n        <a class=\"thumbnail\" href=\"../examples/starter-template/\">\n          <img src=\"../examples/screenshots/starter-template.jpg\" alt=\"\">\n        </a>\n        <h4>Starter template</h4>\n        <p>Nothing but the basics: compiled CSS and JavaScript along with a container.</p>\n      </div>\n      <div class=\"col-xs-6 col-md-4\">\n        <a class=\"thumbnail\" href=\"../examples/grid/\">\n          <img src=\"../examples/screenshots/grid.jpg\" alt=\"\">\n        </a>\n        <h4>Grids</h4>\n        <p>Multiple examples of grid layouts with all four tiers, nesting, and more.</p>\n      </div>\n      <div class=\"clearfix visible-xs\"></div>\n\n      <div class=\"col-xs-6 col-md-4\">\n        <a class=\"thumbnail\" href=\"../examples/jumbotron/\">\n          <img src=\"../examples/screenshots/jumbotron.jpg\" alt=\"\">\n        </a>\n        <h4>Jumbotron</h4>\n        <p>Build around the jumbotron with a navbar and some basic grid columns.</p>\n      </div>\n      <div class=\"col-xs-6 col-md-4\">\n        <a class=\"thumbnail\" href=\"../examples/jumbotron-narrow/\">\n          <img src=\"../examples/screenshots/jumbotron-narrow.jpg\" alt=\"\">\n        </a>\n        <h4>Narrow jumbotron</h4>\n        <p>Build a more custom page by narrowing the default container and jumbotron.</p>\n      </div>\n      <div class=\"clearfix visible-xs\"></div>\n\n      <div class=\"col-xs-6 col-md-4\">\n        <a class=\"thumbnail\" href=\"../examples/navbar/\">\n          <img src=\"../examples/screenshots/navbar.jpg\" alt=\"\">\n        </a>\n        <h4>Navbar</h4>\n        <p>Super basic template that includes the navbar along with some additional content.</p>\n      </div>\n      <div class=\"col-xs-6 col-md-4\">\n        <a class=\"thumbnail\" href=\"../examples/navbar-static-top/\">\n          <img src=\"../examples/screenshots/navbar-static.jpg\" alt=\"\">\n        </a>\n        <h4>Static top navbar</h4>\n        <p>Super basic template with a static top navbar along with some additional content.</p>\n      </div>\n      <div class=\"clearfix visible-xs\"></div>\n\n      <div class=\"col-xs-6 col-md-4\">\n        <a class=\"thumbnail\" href=\"../examples/navbar-fixed-top/\">\n          <img src=\"../examples/screenshots/navbar-fixed.jpg\" alt=\"\">\n        </a>\n        <h4>Fixed navbar</h4>\n        <p>Super basic template with a fixed top navbar along with some additional content.</p>\n      </div>\n      <div class=\"col-xs-6 col-md-4\">\n        <a class=\"thumbnail\" href=\"../examples/signin/\">\n          <img src=\"../examples/screenshots/sign-in.jpg\" alt=\"\">\n        </a>\n        <h4>Sign-in page</h4>\n        <p>Custom form layout and design for a simple sign in form.</p>\n      </div>\n      <div class=\"clearfix visible-xs\"></div>\n\n      <div class=\"col-xs-6 col-md-4\">\n        <a class=\"thumbnail\" href=\"../examples/sticky-footer/\">\n          <img src=\"../examples/screenshots/sticky-footer.jpg\" alt=\"\">\n        </a>\n        <h4>Sticky footer</h4>\n        <p>Attach a footer to the bottom of the viewport when the content is shorter than it.</p>\n      </div>\n      <div class=\"col-xs-6 col-md-4\">\n        <a class=\"thumbnail\" href=\"../examples/sticky-footer-navbar/\">\n          <img src=\"../examples/screenshots/sticky-footer-navbar.jpg\" alt=\"\">\n        </a>\n        <h4>Sticky footer with navbar</h4>\n        <p>Attach a footer to the bottom of the viewport with a fixed navbar at the top.</p>\n      </div>\n      <div class=\"clearfix visible-xs\"></div>\n\n      <div class=\"col-xs-6 col-md-4\">\n        <a class=\"thumbnail\" href=\"../examples/justified-nav/\">\n          <img src=\"../examples/screenshots/justified-nav.jpg\" alt=\"\">\n        </a>\n        <h4>Justified nav</h4>\n        <p>Expand on the default navbar and more to create justified navigation links.</p>\n      </div>\n      <div class=\"col-xs-6 col-md-4\">\n        <a class=\"thumbnail\" href=\"../examples/offcanvas/\">\n          <img src=\"../examples/screenshots/offcanvas.jpg\" alt=\"\">\n        </a>\n        <h4>Offcanvas</h4>\n        <p>Build a toggleable off-canvas navigation menu for use with Bootstrap.</p>\n      </div>\n      <div class=\"clearfix visible-xs\"></div>\n\n      <div class=\"col-xs-6 col-md-4\">\n        <a class=\"thumbnail\" href=\"../examples/carousel/\">\n          <img src=\"../examples/screenshots/carousel.jpg\" alt=\"\">\n        </a>\n        <h4>Carousel</h4>\n        <p>Customize the navbar and carousel, then add some new components.</p>\n      </div>\n      <div class=\"col-xs-6 col-md-4\">\n        <a class=\"thumbnail\" href=\"../examples/non-responsive/\">\n          <img src=\"../examples/screenshots/non-responsive.jpg\" alt=\"\">\n        </a>\n        <h4>Non-responsive Bootstrap</h4>\n        <p>Easily disable the responsiveness of Bootstrap <a href=\"../getting-started/#disable-responsive\">per our docs</a>.</p>\n      </div>\n      <div class=\"clearfix visible-xs\"></div>\n\n      <div class=\"col-xs-6 col-md-4\">\n        <a class=\"thumbnail\" href=\"../examples/theme/\">\n          <img src=\"../examples/screenshots/theme.jpg\" alt=\"\">\n        </a>\n        <h4>Bootstrap theme</h4>\n        <p>Load the optional Bootstrap theme for a visually enhanced experience.</p>\n      </div>\n    </div>\n\n  </div>\n\n\n\n  <!-- Template\n  ================================================== -->\n  <div class=\"bs-docs-section\">\n    <div class=\"page-header\">\n      <h1 id=\"disable-responsive\">Disabling responsiveness</h1>\n    </div>\n    <p class=\"lead\">Don't want your site or application to be scaled on different devices? With a little bit of work, you can disable the responsive features of Bootstrap so that mobile users see your full desktop-version site. Read below or check out <a href=\"../examples/non-responsive/\">the non-responsive example</a>.</p>\n\n    <h3>Steps to disable responsive views</h3>\n    <p>To disable responsive features, follow these steps. See it in action in the modified template below.</p>\n    <ol>\n      <li>Remove (or just don't add) the viewport <code>&lt;meta&gt;</code> mentioned in <a href=\"../css/#overview-mobile\">the CSS docs</a></li>\n      <li>Remove the <code>max-width</code> on the <code>.container</code> for all grid tiers with <code>max-width: none !important;</code> and set a regular width like <code>width: 970px;</code>. Be sure that this comes after the default Bootstrap CSS. You can optionally avoid the <code>!important</code> with media queries or some selector-fu.</li>\n      <li>If using navbars, undo all the navbar collapsing and expanding behavior (this is too much to show here, so peep the example).</li>\n      <li>For grid layouts, make use of <code>.col-xs-*</code> classes in addition to or in place of the medium/large ones. Don't worry, the extra-small device grid scales up to all resolutions, so you're set there.</li>\n    </ol>\n    <p>You'll still need Respond.js for IE8 (since our media queries are still there and need to be picked up). This just disables the \"mobile site\" of Bootstrap.</p>\n\n    <h3>Bootstrap template with disabled responsive</h3>\n    <p>We've taken the above steps and applied them to an example. Read it's source code to see the specific changes called out.</p>\n    <p>\n      <a href=\"../examples/non-responsive/\" class=\"btn btn-primary\">View non-responsive example</a>\n    </p>\n  </div>\n\n\n\n  <!-- Migration\n  ================================================== -->\n  <div class=\"bs-docs-section\">\n    <div class=\"page-header\">\n      <h1 id=\"migration\">Migrating from 2.x to 3.0</h1>\n    </div>\n    <p class=\"lead\">Folks looking to upgrade to v3 should use this section as a general upgrade guide. We've outlined some of the major changes and provided tables that highlight key changes. For an overview, <a href=\"http://blog.getbootstrap.com/2013/08/19/bootstrap-3-released/\">read the announcement blog post</a>.</p>\n\n\n    <h2 id=\"migration-classes\">Major class changes</h2>\n    <p>Reference table for classes that have changed between v2.x and v3.0.</p>\n    <div class=\"table-responsive\">\n      <table class=\"table table-bordered table-striped\">\n        <thead>\n          <tr>\n            <th>Bootstrap 2.x</th>\n            <th>Bootstrap 3.0</th>\n          </tr>\n        </thead>\n        <tbody>\n          <tr>\n            <td><code>.container-fluid</code></td>\n            <td><code>.container</code></td>\n          </tr>\n          <tr>\n            <td><code>.row-fluid</code></td>\n            <td><code>.row</code></td>\n          </tr>\n          <tr>\n            <td><code>.span*</code></td>\n            <td><code>.col-md-*</code></td>\n          </tr>\n          <tr>\n            <td><code>.offset*</code></td>\n            <td><code>.col-md-offset-*</code></td>\n          </tr>\n          <tr>\n            <td><code>.brand</code></td>\n            <td><code>.navbar-brand</code></td>\n          </tr>\n          <tr>\n            <td><code>.nav-collapse</code></td>\n            <td><code>.navbar-collapse</code></td>\n          </tr>\n          <tr>\n            <td><code>.nav-toggle</code></td>\n            <td><code>.navbar-toggle</code></td>\n          </tr>\n          <tr>\n            <td><code>.btn-navbar</code></td>\n            <td><code>.navbar-btn</code></td>\n          </tr>\n          <tr>\n            <td><code>.hero-unit</code></td>\n            <td><code>.jumbotron</code></td>\n          </tr>\n          <tr>\n            <td><code>.icon-*</code></td>\n            <td><code>.glyphicon .glyphicon-*</code></td>\n          </tr>\n          <tr>\n            <td><code>.btn</code></td>\n            <td><code>.btn .btn-default</code></td>\n          </tr>\n          <tr>\n            <td><code>.btn-mini</code></td>\n            <td><code>.btn-xs</code></td>\n          </tr>\n          <tr>\n            <td><code>.btn-small</code></td>\n            <td><code>.btn-sm</code></td>\n          </tr>\n          <tr>\n            <td><code>.btn-large</code></td>\n            <td><code>.btn-lg</code></td>\n          </tr>\n          <tr>\n            <td><code>.visible-phone</code></td>\n            <td><code>.visible-sm</code></td>\n          </tr>\n          <tr>\n            <td><code>.visible-tablet</code></td>\n            <td><code>.visible-md</code></td>\n          </tr>\n          <tr>\n            <td><code>.visible-desktop</code></td>\n            <td><code>.visible-lg</code></td>\n          </tr>\n          <tr>\n            <td><code>.hidden-phone</code></td>\n            <td><code>.hidden-sm</code></td>\n          </tr>\n          <tr>\n            <td><code>.hidden-tablet</code></td>\n            <td><code>.hidden-md</code></td>\n          </tr>\n          <tr>\n            <td><code>.hidden-desktop</code></td>\n            <td><code>.hidden-lg</code></td>\n          </tr>\n          <tr>\n            <td><code>.input-small</code></td>\n            <td><code>.input-sm</code></td>\n          </tr>\n          <tr>\n            <td><code>.input-large</code></td>\n            <td><code>.input-lg</code></td>\n          </tr>\n          <tr>\n            <td><code>.checkbox.inline</code> <code>.radio.inline</code></td>\n            <td><code>.checkbox-inline</code> <code>.radio-inline</code></td>\n          </tr>\n          <tr>\n            <td><code>.input-prepend</code> <code>.input-append</code></td>\n            <td><code>.input-group</code></td>\n          </tr>\n          <tr>\n            <td><code>.add-on</code></td>\n            <td><code>.input-group-addon</code></td>\n          </tr>\n          <tr>\n            <td><code>.thumbnail</code></td>\n            <td><code>.img-thumbnail</code></td>\n          </tr>\n          <tr>\n            <td><code>ul.unstyled</code></td>\n            <td><code>.list-unstyled</code></td>\n          </tr>\n          <tr>\n            <td><code>ul.inline</code></td>\n            <td><code>.list-inline</code></td>\n          </tr>\n        </tbody>\n      </table>\n    </div><!-- /.table-responsive -->\n\n\n    <h2 id=\"migration-new\">What's new</h2>\n    <p>We've added a few new elements and changed some existing ones. Here's their new or updated classes.</p>\n    <div class=\"table-responsive\">\n      <table class=\"table table-bordered table-striped\">\n        <thead>\n          <tr>\n            <th>Element</th>\n            <th>Description</th>\n          </tr>\n        </thead>\n        <tbody>\n          <tr>\n            <td>Panels</td>\n            <td><code>.panel .panel-default</code> <code>.panel-body</code> <code>.panel-title</code> <code>.panel-heading</code> <code>.panel-footer</code> <code>.panel-collapse</code></td>\n          </tr>\n          <tr>\n            <td>List groups</td>\n            <td><code>.list-group</code> <code>.list-group-item</code> <code>.list-group-item-text</code> <code>.list-group-item-heading</code></td>\n          </tr>\n          <tr>\n            <td>Glyphicons</td>\n            <td><code>.glyphicon</code></td>\n          </tr>\n          <tr>\n            <td>Jumbotron</td>\n            <td><code>.jumbotron</code></td>\n          </tr>\n          <tr>\n            <td>Tiny grid (&lt;768 px)</td>\n            <td><code>.col-xs-*</code></td>\n          </tr>\n          <tr>\n            <td>Small grid (&gt;768 px)</td>\n            <td><code>.col-sm-*</code></td>\n          </tr>\n          <tr>\n            <td>Medium grid (&gt;992 px)</td>\n            <td><code>.col-md-*</code></td>\n          </tr>\n          <tr>\n            <td>Large grid (&gt;1200 px)</td>\n            <td><code>.col-lg-*</code></td>\n          </tr>\n          <tr>\n            <td>Offsets</td>\n            <td><code>.col-sm-offset-*</code> <code>.col-md-offset-*</code> <code>.col-lg-offset-*</code></td>\n          </tr>\n          <tr>\n            <td>Push</td>\n            <td><code>.col-sm-push-*</code> <code>.col-md-push-*</code> <code>.col-lg-push-*</code></td>\n          </tr>\n          <tr>\n            <td>Pull</td>\n            <td><code>.col-sm-pull-*</code> <code>.col-md-pull-*</code> <code>.col-lg-pull-*</code></td>\n          </tr>\n          <tr>\n            <td>Input groups</td>\n            <td><code>.input-group</code> <code>.input-group-addon</code> <code>.input-group-btn</code></td>\n          </tr>\n          <tr>\n            <td>Form controls</td>\n            <td><code>.form-control</code> <code>.form-group</code></td>\n          </tr>\n          <tr>\n            <td>Button group sizes</td>\n            <td><code>.btn-group-xs</code> <code>.btn-group-sm</code> <code>.btn-group-lg</code></td>\n          </tr>\n          <tr>\n            <td>Navbar text</td>\n            <td><code>.navbar-text</code></td>\n          </tr>\n          <tr>\n            <td>Navbar header</td>\n            <td><code>.navbar-header</code></td>\n          </tr>\n          <tr>\n            <td>Justified tabs / pills</td>\n            <td><code>.nav-justified</code></td>\n          </tr>\n          <tr>\n            <td>Responsive images</td>\n            <td><code>.img-responsive</code></td>\n          </tr>\n          <tr>\n            <td>Contextual table rows</td>\n            <td><code>.success</code> <code>.danger</code> <code>.warning</code> <code>.active</code></td>\n          </tr>\n          <tr>\n            <td>Contextual panels</td>\n            <td><code>.panel-success</code> <code>.panel-danger</code> <code>.panel-warning</code> <code>.panel-info</code></td>\n          </tr>\n          <tr>\n            <td>Modal</td>\n            <td><code>.modal-dialog</code> <code>.modal-content</code></td>\n          </tr>\n          <tr>\n            <td>Thumbnail image</td>\n            <td><code>.img-thumbnail</code></td>\n          </tr>\n          <tr>\n            <td>Well sizes</td>\n            <td><code>.well-sm</code> <code>.well-lg</code></td>\n          </tr>\n          <tr>\n            <td>Alert links</td>\n            <td><code>.alert-link</code></td>\n          </tr>\n        </tbody>\n      </table>\n    </div><!-- /.table-responsive -->\n\n\n    <h2 id=\"migration-dropped\">What's removed</h2>\n    <p>The following elements have been dropped or changed in v3.</p>\n    <div class=\"table-responsive\">\n      <table class=\"table table-bordered table-striped\">\n        <thead>\n          <tr>\n            <th>Element</th>\n            <th>Removed from 2.x</th>\n            <th>3.0 Equivalent</th>\n          </tr>\n        </thead>\n        <tbody>\n          <tr>\n            <td>Form actions</td>\n            <td><code>.form-actions</code></td>\n            <td class=\"text-muted\">N/A</td>\n          </tr>\n          <tr>\n            <td>Search form</td>\n            <td><code>.form-search</code></td>\n            <td class=\"text-muted\">N/A</td>\n          </tr>\n          <tr>\n            <td>Fluid container</td>\n            <td><code>.container-fluid</code></td>\n            <td><code>.container</code> (no more fixed grid)</td>\n          </tr>\n          <tr>\n            <td>Fluid row</td>\n            <td><code>.row-fluid</code></td>\n            <td><code>.row</code> (no more fixed grid)</td>\n          </tr>\n          <tr>\n            <td>Navbar inner</td>\n            <td><code>.navbar-inner</code></td>\n            <td class=\"text-muted\">N/A</td>\n          </tr>\n          <tr>\n            <td>Dropdown submenu</td>\n            <td><code>.dropdown-submenu</code></td>\n            <td class=\"text-muted\">N/A</td>\n          </tr>\n          <tr>\n            <td>Tab alignments</td>\n            <td><code>.tabs-left</code> <code>.tabs-right</code> <code>.tabs-below</code></td>\n            <td class=\"text-muted\">N/A</td>\n          </tr>\n        </tbody>\n      </table>\n    </div><!-- /.table-responsive -->\n\n\n    <h2 id=\"migration-notes\">Additional notes</h2>\n    <p>We've made many underlying changes in v3 that are not immediately apparent. Base classes, key styles, and behaviors have been adjusted for flexibility and our mobile first approach.</p>\n    <ul>\n      <li>Text-based form controls are now 100% wide. Wrap inputs inside <code>&lt;div class=\"col-*\"&gt;&lt;/div&gt;</code> to control input widths.</li>\n      <li><code>.badge</code> no longer has contextual (-success,-primary,etc..) classes.</li>\n      <li><code>.btn</code> must also use <code>.btn-default</code> to get the \"default\" button.</li>\n      <li><code>.container</code> and <code>.row</code> are now fluid (percentage-based).</li>\n      <li>Images are no longer responsive by default. Use <code>.img-responsive</code> for fluid <code>&lt;img&gt;</code> size.</li>\n      <li>The icons, now <code>.glyphicon</code>, are now font based. They also require a base and icon class (e.g. <code>.glyphicon .glyphicon-asterisk</code>).</li>\n      <li>Typeahead has been dropped, in favor of using <a href=\"http://twitter.github.io/typeahead.js/\">Twitter Typeahead</a>.</li>\n      <li>Modal markup has changed significantly. The <code>.modal-header</code>, <code>.modal-body</code>, and <code>.modal-footer</code> sections now get wrapped in <code>.modal-content</code> and <code>.modal-dialog</code> for improved mobile styling and behavior.</li>\n      <li>JavaScript events are namespaced. For example, to handle the modal \"show\" event, use <code>'show.bs.modal'</code>. For tabs \"shown\" use <code>'shown.bs.tab'</code>, etc..</li>\n    </ul>\n    <p>For more information on upgrades and code snippets from the community check out <a href=\"http://bootply.com/\">Bootply</a>.</p>\n  </div>\n\n\n\n  <!-- Browser support\n  ================================================== -->\n  <div class=\"bs-docs-section\">\n    <div class=\"page-header\">\n      <h1 id=\"browsers\">Browser support</h1>\n    </div>\n    <p class=\"lead\">Bootstrap is built to work best in the latest desktop and mobile browsers, meaning older and less advanced browsers might receive a less stylized, though fully functional, version of certain components.</p>\n\n    <h3>Supported browsers</h3>\n    <p>Specifically, we support the latest versions of the following:</p>\n    <ul>\n      <li>Chrome (Mac, Windows, iOS, and Android)</li>\n      <li>Safari (Mac and iOS only, as Windows has more or less been discontinued)</li>\n      <li>Firefox (Mac, Windows)</li>\n      <li>Internet Explorer</li>\n      <li>Opera (Mac, Windows)</li>\n    </ul>\n    <p>Unofficially, Bootstrap should look and behave well enough in Chromium for Linux and Internet Explorer 7, though they are not officially supported.</p>\n\n    <h3>Internet Explorer 8 and 9</h3>\n    <p>Internet Explorer 8 and 9 are also supported, however, please be aware that many CSS3 properties—e.g., rounded corners and shadows—are not supported by IE8. The <code>placeholder</code> attribute is also not supported in either of these versions.</p>\n    <p>In addition, <strong>Internet Explorer 8 requires the use of <a href=\"https://github.com/scottjehl/Respond\">respond.js</a> to enable media query support.</strong></p>\n\n    <h3>IE Compatibility modes</h3>\n    <p>Bootstrap is not supported in the old Internet Explorer compatibility modes. To be sure you're using the latest rendering mode for IE, consider including the appropriate <code>&lt;meta&gt;</code> tag in your pages:</p>\n{% highlight html %}\n<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n{% endhighlight %}\n    <p>See <a href=\"http://stackoverflow.com/questions/6771258/whats-the-difference-if-meta-http-equiv-x-ua-compatible-content-ie-edge\">this StackOverflow question</a> for more information.</p>\n\n    <h3>Windows Phone 8 and Internet Explorer 10</h3>\n    <p>Internet Explorer 10 doesn't differentiate device width from viewport width, and thus doesn't properly apply the media queries in Bootstrap's CSS. To address this, you can optionally include the following CSS and JavaScript to work around this problem until Microsoft issues a fix.</p>\n{% highlight css %}\n@-webkit-viewport   { width: device-width; }\n@-moz-viewport      { width: device-width; }\n@-ms-viewport       { width: device-width; }\n@-o-viewport        { width: device-width; }\n@viewport           { width: device-width; }\n{% endhighlight %}\n\n{% highlight js %}\nif (navigator.userAgent.match(/IEMobile\\/10\\.0/)) {\n  var msViewportStyle = document.createElement(\"style\")\n  msViewportStyle.appendChild(\n    document.createTextNode(\n      \"@-ms-viewport{width:auto!important}\"\n    )\n  )\n  document.getElementsByTagName(\"head\")[0].appendChild(msViewportStyle)\n}\n{% endhighlight %}\n    <p>For more information and usage guidelines, read <a href=\"http://timkadlec.com/2013/01/windows-phone-8-and-device-width/\">Windows Phone 8 and Device-Width</a>.</p>\n\n    <h3>Safari percent rounding</h3>\n    <p>In the latest Safari for Mac, its rendering engine has a little trouble with the long decimal places of our <code>.col-*-1</code> grid classes, meaning if you have 12 individual columns you'll notice they come up short compared to other rows of columns. There's not much we can do here (<a href=\"https://github.com/twbs/bootstrap/issues/9282\">see #9282</a>) but you do have some options:</p>\n    <ul>\n      <li>Add <code>.pull-right</code> to your last grid column to get the hard-right alignment</li>\n      <li>Tweak your percentages manually to get the perfect rounding for Safari (more difficult than the first option)</li>\n    </ul>\n    <p>We'll keep an eye on this though and update our code if we have an easy solution.</p>\n\n    <h3>Modals and mobile devices</h3>\n    <h4>Overflow and scrolling</h4>\n    <p>Support for <code>overflow: hidden</code> on the <code>&lt;body&gt;</code> element is quite limited in iOS and Android. To that end, when you scroll past the top or bottom of a modal in either of those devices' browsers, the <code>&lt;body&gt;</code> content will begin to scroll.</p>\n    <h4>Virtual keyboards</h4>\n    <p>Also, note that if you're using inputs in your modal – iOS has a rendering bug which doesn't update the position of fixed elements when the virtual keyboard is triggered. There are a few work arounds for this, including transforming your elements to <code>position: absolute</code> or invoking a timer on focus to try to correct the positioning manually. This is not handled by Bootstrap, so it is up to you to decide which solution is best for your application.</p>\n\n    <h3>Browser zooming</h3>\n    <p>Page zooming inevitably presents rendering artifacts in some components, both in Bootstrap and the rest of the web. Depending on the issue, we may be able to fix it (search first and then open an issue if need be). However, we tend to ignore these as they often have no direct solution other than hacky workarounds.</p>\n  </div>\n\n\n\n  <!-- Third party support\n  ================================================== -->\n  <div class=\"bs-docs-section\">\n    <div class=\"page-header\">\n      <h1 id=\"third-parties\">Third party support</h1>\n    </div>\n    <p class=\"lead\">While we don't officially support any third party plugins or add-ons, we do offer some useful advice to help avoid potential issues in your projects.</p>\n\n    <h3>Google Maps</h3>\n    <p>If you're using Google Maps on a Bootstrapped project, you might run into some display problems due to our use of <code>* { box-sizing: border-box; }</code>. Previously, you may have also ran into issues with the use of <code>max-width</code> on images. The following snippet should avoid all those problems.</p>\n{% highlight css %}\n/* Fix Google Maps canvas\n *\n * Wrap your Google Maps embed in a `.google-map-canvas` to reset Bootstrap's\n * global `box-sizing` changes. You may optionally need to reset the `max-width`\n * on images in case you've applied that anywhere else. (That shouldn't be as\n * necessary with Bootstrap 3 though as that behavior is relegated to the\n * `.img-responsive` class.)\n */\n\n.google-map-canvas,\n.google-map-canvas * { .box-sizing(content-box); }\n\n/* Optional responsive image override */\nimg { max-width: none; }\n{% endhighlight %}\n  </div>\n\n\n\n  <!-- Accessibility\n  ================================================== -->\n  <div class=\"bs-docs-section\">\n    <div class=\"page-header\">\n      <h1 id=\"accessibility\">Accessibility</h1>\n    </div>\n    <p class=\"lead\">Bootstrap follows common web standards, and with minimal extra effort, can be used to create sites that are accessibile to those using <abbr title=\"Assistive Technology\" class=\"initialism\">AT</abbr>.</p>\n\n    <h3>Skip navigation</h3>\n    <p>If your navigation contains many links and comes before the main content in the DOM, add a <code>Skip to content</code> link immediately after your opening <code>&lt;body&gt;</code> tag. <a href=\"http://a11yproject.com/posts/skip-nav-links/\">(read why)</a></p>\n{% highlight html %}\n<body>\n  <a href=\"#content\" class=\"sr-only\">Skip to content</a>\n  <div class=\"container\" id=\"content\">\n    The main page content.\n  </div>\n</body>\n{% endhighlight %}\n\n    <h3>Nested headers</h3>\n    <p>Another \"gotcha\" has to do with how you nest your <code>&lt;header&gt;</code> elements. <a href=\"http://squizlabs.github.io/HTML_CodeSniffer/Standards/Section508/\">Section 508</a> states that your largest header must be an <code>h1</code>, and the next header must be an <code>&lt;h2&gt;</code>, etc. This is hard to achieve in practice, but if the largest header on your site is smaller than Bootstrap's default 38px, you should consider modifying your stylesheets before using a smaller header element.</p>\n\n    <h3>Additional resources</h3>\n    <ul>\n      <li><a href=\"https://github.com/squizlabs/HTML_CodeSniffer\">\"HTML Codesniffer\" bookmarklet for identifying accessibility issues</a></li>\n      <li><a href=\"http://a11yproject.com/\">The A11Y Project</a></li>\n      <li><a href=\"https://developer.mozilla.org/en-US/docs/Accessibility\">MDN accessibility documentation</a></li>\n    </ul>\n  </div>\n\n\n\n  <!-- License FAQs\n  ================================================== -->\n  <div class=\"bs-docs-section\">\n    <div class=\"page-header\">\n      <h1 id=\"license-faqs\">License FAQs</h1>\n    </div>\n    <p class=\"lead\">Bootstrap is released under the Apache 2 license and is copyright {{ site.time | date: \"%Y\" }} Twitter. Boiled down to smaller chunks, it can be described with the following conditions.</p>\n\n    <div class=\"row\">\n      <div class=\"col-12 col-lg-6\">\n        <h4>It allows you to:</h4>\n        <ul>\n          <li>Freely download and use Bootstrap, in whole or in part, for personal, company internal or commercial purposes</li>\n          <li>Use Bootstrap in packages or distributions that you create</li>\n        </ul>\n      </div>\n      <div class=\"col-12 col-lg-6\">\n        <h4>It forbids you to:</h4>\n        <ul>\n          <li>Redistribute any piece of Bootstrap without proper attribution</li>\n          <li>Use any marks owned by Twitter in any way that might state or imply that Twitter endorses your distribution</li>\n          <li>Use any marks owned by Twitter in any way that might state or imply that you created the Twitter software in question</li>\n        </ul>\n      </div>\n    </div>\n    <div class=\"row\">\n      <div class=\"col-12 col-lg-6\">\n        <h4>It requires you to:</h4>\n        <ul>\n          <li>Include a copy of the license in any redistribution you may make that includes Bootstrap</li>\n          <li>Provide clear attribution to Twitter for any distributions that include Bootstrap</li>\n        </ul>\n      </div>\n      <div class=\"col-12 col-lg-6\">\n        <h4>It does not require you to:</h4>\n        <ul>\n          <li>Include the source of Bootstrap itself, or of any modifications you may have made to it, in any redistribution you may assemble that includes it</li>\n          <li>Submit changes that you make to Bootstrap back to the Bootstrap project (though such feedback is encouraged)</li>\n        </ul>\n      </div>\n    </div>\n    <p>The full Bootstrap license is located <a href=\"{{ site.repo }}/blob/master/README.md\">in the project repository</a> for more information.</p>\n  </div><!-- /.bs-docs-section -->\n\n\n\n\n  <div class=\"bs-docs-section\">\n    <div class=\"page-header\">\n      <h1 id=\"customizing\">Customizing Bootstrap</h1>\n    </div>\n    <p class=\"lead\">Customizing Bootstrap is best accomplished when you treat it as another dependency in your development stack. Doing so ensures future upgrades are as easy as possible while also familiarizing yourself to the intricacies of the framework.</p>\n\n    <p>Once you've downloaded and included Bootstrap's CSS into your templates, you can move on to customizing the included components. To do so, create a new stylesheet (LESS, if you like, or just plain CSS) to house your customizations.</p>\n\n    <div class=\"bs-callout bs-callout-info\">\n      <h4>Compiled or minified?</h4>\n      <p>Unless you plan on reading a good chunk of the compiled CSS, go with the minified. It's the same code, just compacted. Less bandwidth is good, especially in production environments.</p>\n    </div>\n\n    <p>From there, include whatever Bootstrap components and HTML content you need to get your template setup. It's best to have a rough idea in mind of modifications to make and content to include, so be sure to spend a brief amount of time on that before moving on.</p>\n\n    <h3>Customizing components</h3>\n    <p>There are varying degrees to customizing components, but most fall into two camps: light customizations and complete visual overhauls. Luckily, there are plenty of examples of both.</p>\n    <p>We define light customizations as mostly surface layer changes, things like a color and font changes to existing Bootstrap components. A great example of this is the <a href=\"http://translate.twitter.com\">Twitter Translation Center</a> (coded by @mdo). Let's look at how to implement the custom button we wrote for this site, <code>.btn-ttc</code>.</p>\n    <p>Instead of using the provided Bootstrap buttons, which only require just one class to start, <code>.btn</code>, we'll add our own modifier class, <code>.btn-ttc</code>. This will give us a slightly custom look with minimal effort.</p>\n{% highlight html %}\n<button type=\"button\" class=\"btn btn-ttc\">Save changes</button>\n{% endhighlight %}\n\n  <p>In the custom stylesheet, add the following CSS:</p>\n\n{% highlight css %}\n/* Custom button\n-------------------------------------------------- */\n\n/* Override base .btn styles */\n/* Apply text and background changes to three key states: default, hover, and active (click). */\n.btn-ttc,\n.btn-ttc:hover,\n.btn-ttc:active {\n  color: white;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #007da7;\n}\n\n/* Apply the custom-colored gradients */\n/* Note: you'll need to include all the appropriate gradients for various browsers and standards. */\n.btn-ttc {\n  background-repeat: repeat-x;\n  background-image: linear-gradient(top, #009ED2 0%, #007DA7 100%);\n  ...\n}\n\n/* Set the hover state */\n/* An easy hover state is just to move the gradient up a small amount. Add other embellishments as you see fit. */\n.btn-ttc:hover {\n  background-position: 0 -15px;\n}\n{% endhighlight %}\n\n    <p>Customizing Bootstrap components takes time, but should be straightforward. <strong>Look to the source code often and duplicate the selectors you need for your modifications.</strong> Placing them after the Bootstrap source makes for easy overriding without complication. <strong>To recap, here's the basic workflow:</strong></p>\n    <ul>\n      <li>For each element you want to customize, find its code in the compiled Bootstrap CSS. Copy and paste the selector for a component as-is. For instance, to customize the navbar background, just snag <code>.navbar</code>.</li>\n      <li>Add all your custom CSS in a separate stylesheet using the selectors you just copied from the Bootstrap source. No need for prefacing with additional classes or using <code>!important</code> here.</li>\n      <li>Rinse and repeat until you're happy with your customizations.</li>\n    </ul>\n    <p>Going beyond light customizations and into visual overhauls is just as straightforward as the above custom button. For a site like <a href=\"http://yourkarma.com\">Karma</a>, which uses Bootstrap as a CSS reset with heavy modifications, more extensive work is involved, but well worth it in the end.</p>\n\n    <div class=\"bs-callout bs-callout-info\">\n      <h4>Alternate customization methods</h4>\n      <p>While not recommended for folks new to Bootstrap, you may use one of two alternate methods for customization. The first is modifying the source .less files (making upgrades super difficult), and the second is mapping source LESS code to <a href=\"http://ruby.bvision.com/blog/please-stop-embedding-bootstrap-classes-in-your-html\">your own classes via mixins</a>. For the time being, neither of those options are documented here.</p>\n    </div>\n\n    <h3>Removing potential bloat</h3>\n    <p>Not all sites and applications need to make use of everything Bootstrap has to offer, especially in production environments where bandwidth literally becomes a financial issue. We encourage folks to remove whatever is unused with our <a href=\"../customize/\">Customizer</a>.</p>\n    <p>Using the Customizer, simply uncheck any component, feature, or asset you don't need. Hit download and swap out the default Bootstrap files with these newly customized ones. You'll get vanilla Bootstrap, but without the features *you* deem unnecessary. All custom builds include compiled and minified versions, so use whichever works for you.</p>\n\n  </div>\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/sass-bootstrap/index.html",
    "content": "---\nlayout: home\ntitle: Bootstrap\nbase_url: \"./\"\n---\n\n<main class=\"bs-masthead\" id=\"content\" role=\"main\">\n  <div class=\"container\">\n    <h1>Bootstrap</h1>\n    <p class=\"lead\">Sleek, intuitive, and powerful mobile first front-end framework for faster and easier web development.</p>\n    <p>\n      <a href=\"{{ site.download }}\" class=\"btn btn-outline-inverse btn-lg\" onclick=\"_gaq.push(['_trackEvent', 'Jumbotron actions', 'Download', 'Download 3.0.0']);\">Download Bootstrap</a>\n    </p>\n  </div>\n</main>\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/sass-bootstrap/javascript.html",
    "content": "---\nlayout: default\ntitle: JavaScript\nslug: js\nlead: \"Bring Bootstrap's components to life with over a dozen custom jQuery plugins. Easily include them all, or one by one.\"\nbase_url: \"../\"\n---\n\n\n  <!-- Overview\n  ================================================== -->\n  <div class=\"bs-docs-section\">\n    <div class=\"page-header\">\n      <h1 id=\"js-overview\">Overview</h1>\n    </div>\n\n    <h3 id=\"js-individual-compiled\">Individual or compiled</h3>\n    <p>Plugins can be included individually (using Bootstrap's individual <code>*.js</code> files), or all at once (using <code>bootstrap.js</code> or the minified <code>bootstrap.min.js</code>).</p>\n\n    <div class=\"bs-callout bs-callout-danger\">\n      <h4>Do not attempt to include both.</h4>\n      <p>Both <code>bootstrap.js</code> and <code>bootstrap.min.js</code> contain all plugins in a single file.</p>\n    </div>\n\n    <div class=\"bs-callout bs-callout-danger\">\n      <h4>Plugin dependencies</h4>\n      <p>Some plugins and CSS components depend on other plugins. If you include plugins individually, make sure to check for these dependencies in the docs. Also note that all plugins depend on jQuery (this means jQuery must be included <strong>before</strong> the plugin files).</p>\n    </div>\n\n    <h3 id=\"js-data-attrs\">Data attributes</h3>\n    <p>You can use all Bootstrap plugins purely through the markup API without writing a single line of JavaScript. This is Bootstrap's first-class API and should be your first consideration when using a plugin.</p>\n\n    <p>That said, in some situations it may be desirable to turn this functionality off. Therefore, we also provide the ability to disable the data attribute API by unbinding all events on the document namespaced with <code>data-api</code>. This looks like this:\n{% highlight js %}\n$(document).off('.data-api')\n{% endhighlight %}\n\n    <p>Alternatively, to target a specific plugin, just include the plugin's name as a namespace along with the data-api namespace like this:</p>\n{% highlight js %}\n$(document).off('.alert.data-api')\n{% endhighlight %}\n\n    <h3 id=\"js-programmatic-api\">Programmatic API</h3>\n    <p>We also believe you should be able to use all Bootstrap plugins purely through the JavaScript API. All public APIs are single, chainable methods, and return the collection acted upon.</p>\n{% highlight js %}\n$(\".btn.danger\").button(\"toggle\").addClass(\"fat\")\n{% endhighlight %}\n\n    <p>All methods should accept an optional options object, a string which targets a particular method, or nothing (which initiates a plugin with default behavior):</p>\n{% highlight js %}\n$(\"#myModal\").modal()                      // initialized with defaults\n$(\"#myModal\").modal({ keyboard: false })   // initialized with no keyboard\n$(\"#myModal\").modal('show')                // initializes and invokes show immediately</p>\n{% endhighlight %}\n\n    <p>Each plugin also exposes its raw constructor on a <code>Constructor</code> property: <code>$.fn.popover.Constructor</code>. If you'd like to get a particular plugin instance, retrieve it directly from an element: <code>$('[rel=popover]').data('popover')</code>.</p>\n\n    <h3 id=\"js-noconflict\">No conflict</h3>\n    <p>Sometimes it is necessary to use Bootstrap plugins with other UI frameworks. In these circumstances, namespace collisions can occasionally occur. If this happens, you may call <code>.noConflict</code> on the plugin you wish to revert the value of.</p>\n{% highlight js %}\nvar bootstrapButton = $.fn.button.noConflict() // return $.fn.button to previously assigned value\n$.fn.bootstrapBtn = bootstrapButton            // give $().bootstrapBtn the Bootstrap functionality\n{% endhighlight %}\n\n    <h3 id=\"js-events\">Events</h3>\n    <p>Bootstrap provides custom events for most plugin's unique actions. Generally, these come in an infinitive and past participle form - where the infinitive (ex. <code>show</code>) is triggered at the start of an event, and its past participle form (ex. <code>shown</code>) is trigger on the completion of an action.</p>\n    <p>As of 3.0.0, all Bootstrap events are namespaced.</p>\n    <p>All infinitive events provide <code>preventDefault</code> functionality. This provides the ability to stop the execution of an action before it starts.</p>\n{% highlight js %}\n$('#myModal').on('show.bs.modal', function (e) {\n  if (!data) return e.preventDefault() // stops modal from being shown\n})\n{% endhighlight %}\n\n    <div class=\"bs-callout bs-callout-warning\" id=\"callout-third-party-libs\">\n      <h4>Third-party libraries</h4>\n      <p><strong>Bootstrap does not officially support third-party JavaScript libraries</strong> like Prototype or jQuery UI. Despite <code>.noConflict</code> and namespaced events, there may be compatibility problems that you need to fix on your own. Ask on the <a href=\"http://groups.google.com/group/twitter-bootstrap\">mailing list</a> if you need help.</p>\n    </div>\n  </div>\n\n\n\n  <!-- Transitions\n  ================================================== -->\n  <div class=\"bs-docs-section\">\n    <div class=\"page-header\">\n      <h1 id=\"transitions\">Transitions <small>transition.js</small></h1>\n    </div>\n    <h3>About transitions</h3>\n    <p>For simple transition effects, include <code>transition.js</code> once alongside the other JS files. If you're using the compiled (or minified) <code>bootstrap.js</code>, there is no need to include this&mdash;it's already there.</p>\n    <h3>What's inside</h3>\n    <p>Transition.js is a basic helper for <code>transitionEnd</code> events as well as a CSS transition emulator. It's used by the other plugins to check for CSS transition support and to catch hanging transitions.</p>\n  </div>\n\n\n\n  <!-- Modal\n  ================================================== -->\n  <div class=\"bs-docs-section\">\n    <div class=\"page-header\">\n      <h1 id=\"modals\">Modals <small>modal.js</small></h1>\n    </div>\n\n    <h2 id=\"modals-examples\">Examples</h2>\n    <p>Modals are streamlined, but flexible, dialog prompts with the minimum required functionality and smart defaults.</p>\n\n    <h3>Static example</h3>\n    <p>A rendered modal with header, body, and set of actions in the footer.</p>\n    <div class=\"bs-example bs-example-modal\">\n      <div class=\"modal\">\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\">&times;</button>\n              <h4 class=\"modal-title\">Modal title</h4>\n            </div>\n            <div class=\"modal-body\">\n              <p>One fine body&hellip;</p>\n            </div>\n            <div class=\"modal-footer\">\n              <button type=\"button\" class=\"btn btn-default\" data-dismiss=\"modal\">Close</button>\n              <button type=\"button\" class=\"btn btn-primary\">Save changes</button>\n            </div>\n          </div><!-- /.modal-content -->\n        </div><!-- /.modal-dialog -->\n      </div><!-- /.modal -->\n    </div><!-- /example -->\n{% highlight html %}\n<div class=\"modal fade\">\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\">&times;</button>\n        <h4 class=\"modal-title\">Modal title</h4>\n      </div>\n      <div class=\"modal-body\">\n        <p>One fine body&hellip;</p>\n      </div>\n      <div class=\"modal-footer\">\n        <button type=\"button\" class=\"btn btn-default\" data-dismiss=\"modal\">Close</button>\n        <button type=\"button\" class=\"btn btn-primary\">Save changes</button>\n      </div>\n    </div><!-- /.modal-content -->\n  </div><!-- /.modal-dialog -->\n</div><!-- /.modal -->\n{% endhighlight %}\n\n    <h3>Live demo</h3>\n    <p>Toggle a modal via JavaScript by clicking the button below. It will slide down and fade in from the top of the page.</p>\n    <!-- sample modal content -->\n    <div id=\"myModal\" class=\"modal fade\" tabindex=\"-1\" role=\"dialog\" aria-labelledby=\"myModalLabel\" aria-hidden=\"true\">\n      <div class=\"modal-dialog\">\n        <div class=\"modal-content\">\n\n          <div class=\"modal-header\">\n            <button type=\"button\" class=\"close\" data-dismiss=\"modal\" aria-hidden=\"true\">&times;</button>\n            <h4 class=\"modal-title\" id=\"myModalLabel\">Modal Heading</h4>\n          </div>\n          <div class=\"modal-body\">\n            <h4>Text in a modal</h4>\n            <p>Duis mollis, est non commodo luctus, nisi erat porttitor ligula.</p>\n\n            <h4>Popover in a modal</h4>\n            <p>This <a href=\"#\" role=\"button\" class=\"btn btn-default popover-test\" title=\"A Title\" data-content=\"And here's some amazing content. It's very engaging. right?\">button</a> should trigger a popover on click.</p>\n\n            <h4>Tooltips in a modal</h4>\n            <p><a href=\"#\" class=\"tooltip-test\" title=\"Tooltip\">This link</a> and <a href=\"#\" class=\"tooltip-test\" title=\"Tooltip\">that link</a> should have tooltips on hover.</p>\n\n            <hr>\n\n            <h4>Overflowing text to show scroll behavior</h4>\n            <p>Cras mattis consectetur purus sit amet fermentum. Cras justo odio, dapibus ac facilisis in, egestas eget quam. Morbi leo risus, porta ac consectetur ac, vestibulum at eros.</p>\n            <p>Praesent commodo cursus magna, vel scelerisque nisl consectetur et. Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor.</p>\n            <p>Aenean lacinia bibendum nulla sed consectetur. Praesent commodo cursus magna, vel scelerisque nisl consectetur et. Donec sed odio dui. Donec ullamcorper nulla non metus auctor fringilla.</p>\n            <p>Cras mattis consectetur purus sit amet fermentum. Cras justo odio, dapibus ac facilisis in, egestas eget quam. Morbi leo risus, porta ac consectetur ac, vestibulum at eros.</p>\n            <p>Praesent commodo cursus magna, vel scelerisque nisl consectetur et. Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor.</p>\n            <p>Aenean lacinia bibendum nulla sed consectetur. Praesent commodo cursus magna, vel scelerisque nisl consectetur et. Donec sed odio dui. Donec ullamcorper nulla non metus auctor fringilla.</p>\n            <p>Cras mattis consectetur purus sit amet fermentum. Cras justo odio, dapibus ac facilisis in, egestas eget quam. Morbi leo risus, porta ac consectetur ac, vestibulum at eros.</p>\n            <p>Praesent commodo cursus magna, vel scelerisque nisl consectetur et. Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor.</p>\n            <p>Aenean lacinia bibendum nulla sed consectetur. Praesent commodo cursus magna, vel scelerisque nisl consectetur et. Donec sed odio dui. Donec ullamcorper nulla non metus auctor fringilla.</p>\n          </div>\n          <div class=\"modal-footer\">\n            <button type=\"button\" class=\"btn btn-default\" data-dismiss=\"modal\">Close</button>\n            <button type=\"button\" class=\"btn btn-primary\">Save changes</button>\n          </div>\n\n        </div><!-- /.modal-content -->\n      </div><!-- /.modal-dialog -->\n    </div><!-- /.modal -->\n\n    <div class=\"bs-example\" style=\"padding-bottom: 24px;\">\n      <a data-toggle=\"modal\" href=\"#myModal\" class=\"btn btn-primary btn-lg\">Launch demo modal</a>\n    </div><!-- /example -->\n{% highlight html %}\n  <!-- Button trigger modal -->\n  <a data-toggle=\"modal\" href=\"#myModal\" class=\"btn btn-primary btn-lg\">Launch demo modal</a>\n\n  <!-- Modal -->\n  <div class=\"modal fade\" id=\"myModal\" tabindex=\"-1\" role=\"dialog\" aria-labelledby=\"myModalLabel\" aria-hidden=\"true\">\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\">&times;</button>\n          <h4 class=\"modal-title\">Modal title</h4>\n        </div>\n        <div class=\"modal-body\">\n          ...\n        </div>\n        <div class=\"modal-footer\">\n          <button type=\"button\" class=\"btn btn-default\" data-dismiss=\"modal\">Close</button>\n          <button type=\"button\" class=\"btn btn-primary\">Save changes</button>\n        </div>\n      </div><!-- /.modal-content -->\n    </div><!-- /.modal-dialog -->\n  </div><!-- /.modal -->\n{% endhighlight %}\n\n\n    <div class=\"bs-callout bs-callout-warning\">\n      <h4>Make modals accessible</h4>\n      <p>\n        Be sure to add <code>role=\"dialog\"</code> to your primary modal div. In the example above, <code>div#myModal</code>.<br>\n        Also, the <code>aria-labelledby</code> attribute references your modal title. In this example, <code>h4#myModalLabel</code>.<br>\n        Finally, <code>aria-hidden=\"true\"</code> tells assistive technologies to skip DOM elements.<br>\n        Additionally, you may give a description of your modal dialog. Use the <code>aria-describedby</code> attribute in the modal's primary <code>&lt;div&gt;</code> to point to this description (this is not shown in the above example).\n      </p>\n    </div>\n\n    <h2 id=\"modals-usage\">Usage</h2>\n\n    <h3>Via data attributes</h3>\n    <p>Activate a modal without writing JavaScript. Set <code>data-toggle=\"modal\"</code> on a controller element, like a button, along with a <code>data-target=\"#foo\"</code> or <code>href=\"#foo\"</code> to target a specific modal to toggle.</p>\n{% highlight html %}\n<button type=\"button\" data-toggle=\"modal\" data-target=\"#myModal\">Launch modal</button>\n{% endhighlight %}\n\n    <h3>Via JavaScript</h3>\n    <p>Call a modal with id <code>myModal</code> with a single line of JavaScript:</p>\n    {% highlight js %}$('#myModal').modal(options){% endhighlight %}\n\n    <h3>Options</h3>\n    <p>Options can be passed via data attributes or JavaScript. For data attributes, append the option name to <code>data-</code>, as in <code>data-backdrop=\"\"</code>.</p>\n    <div class=\"table-responsive\">\n      <table class=\"table table-bordered table-striped\">\n        <thead>\n         <tr>\n           <th style=\"width: 100px;\">Name</th>\n           <th style=\"width: 50px;\">type</th>\n           <th style=\"width: 50px;\">default</th>\n           <th>description</th>\n         </tr>\n        </thead>\n        <tbody>\n         <tr>\n           <td>backdrop</td>\n           <td>boolean</td>\n           <td>true</td>\n           <td>Includes a modal-backdrop element. Alternatively, specify <code>static</code> for a backdrop which doesn't close the modal on click.</td>\n         </tr>\n         <tr>\n           <td>keyboard</td>\n           <td>boolean</td>\n           <td>true</td>\n           <td>Closes the modal when escape key is pressed</td>\n         </tr>\n         <tr>\n           <td>show</td>\n           <td>boolean</td>\n           <td>true</td>\n           <td>Shows the modal when initialized.</td>\n         </tr>\n         <tr>\n           <td>remote</td>\n           <td>path</td>\n           <td>false</td>\n           <td><p>If a remote URL is provided, content will be loaded via jQuery's <code>load</code> method and injected into the root of the modal element. If you're using the data api, you may alternatively use the <code>href</code> attribute to specify the remote source. An example of this is shown below:</p>\n{% highlight html %}\n<a data-toggle=\"modal\" href=\"remote.html\" data-target=\"#modal\">Click me</a>\n{% endhighlight %}\n         </tr>\n        </tbody>\n      </table>\n    </div><!-- /.table-responsive -->\n\n    <h3>Methods</h3>\n\n    <h4>.modal(options)</h4>\n    <p>Activates your content as a modal. Accepts an optional options <code>object</code>.</p>\n{% highlight js %}\n$('#myModal').modal({\n  keyboard: false\n})\n{% endhighlight %}\n\n    <h4>.modal('toggle')</h4>\n    <p>Manually toggles a modal.</p>\n    {% highlight js %}$('#myModal').modal('toggle'){% endhighlight %}\n\n    <h4>.modal('show')</h4>\n    <p>Manually opens a modal.</p>\n    {% highlight js %}$('#myModal').modal('show'){% endhighlight %}\n\n    <h4>.modal('hide')</h4>\n    <p>Manually hides a modal.</p>\n    {% highlight js %}$('#myModal').modal('hide'){% endhighlight %}\n\n    <h3>Events</h3>\n    <p>Bootstrap's modal class exposes a few events for hooking into modal functionality.</p>\n    <div class=\"table-responsive\">\n      <table class=\"table table-bordered table-striped\">\n        <thead>\n         <tr>\n           <th style=\"width: 150px;\">Event Type</th>\n           <th>Description</th>\n         </tr>\n        </thead>\n        <tbody>\n         <tr>\n           <td>show.bs.modal</td>\n           <td>This event fires immediately when the <code>show</code> instance method is called.</td>\n         </tr>\n         <tr>\n           <td>shown.bs.modal</td>\n           <td>This event is fired when the modal has been made visible to the user (will wait for CSS transitions to complete).</td>\n         </tr>\n         <tr>\n           <td>hide.bs.modal</td>\n           <td>This event is fired immediately when the <code>hide</code> instance method has been called.</td>\n         </tr>\n         <tr>\n           <td>hidden.bs.modal</td>\n           <td>This event is fired when the modal has finished being hidden from the user (will wait for CSS transitions to complete).</td>\n         </tr>\n        </tbody>\n      </table>\n    </div><!-- /.table-responsive -->\n{% highlight js %}\n$('#myModal').on('hidden.bs.modal', function () {\n  // do something…\n})\n{% endhighlight %}\n  </div>\n\n\n\n  <!-- Dropdowns\n  ================================================== -->\n  <div class=\"bs-docs-section\">\n    <div class=\"page-header\">\n      <h1 id=\"dropdowns\">Dropdowns <small>dropdown.js</small></h1>\n    </div>\n\n    <h2 id=\"dropdowns-examples\">Examples</h2>\n    <p>Add dropdown menus to nearly anything with this simple plugin, including the navbar, tabs, and pills.</p>\n\n    <h3>Within a navbar</h3>\n    <div class=\"bs-example\">\n      <nav id=\"navbar-example\" class=\"navbar navbar-default navbar-static\" role=\"navigation\">\n        <div class=\"navbar-header\">\n          <button class=\"navbar-toggle\" type=\"button\" data-toggle=\"collapse\" data-target=\".bs-js-navbar-collapse\">\n            <span class=\"sr-only\">Toggle navigation</span>\n            <span class=\"icon-bar\"></span>\n            <span class=\"icon-bar\"></span>\n            <span class=\"icon-bar\"></span>\n          </button>\n          <a class=\"navbar-brand\" href=\"#\">Project Name</a>\n        </div>\n        <div class=\"collapse navbar-collapse bs-js-navbar-collapse\">\n          <ul class=\"nav navbar-nav\">\n            <li class=\"dropdown\">\n              <a id=\"drop1\" href=\"#\" role=\"button\" class=\"dropdown-toggle\" data-toggle=\"dropdown\">Dropdown <b class=\"caret\"></b></a>\n              <ul class=\"dropdown-menu\" role=\"menu\" aria-labelledby=\"drop1\">\n                <li role=\"presentation\"><a role=\"menuitem\" tabindex=\"-1\" href=\"http://twitter.com/fat\">Action</a></li>\n                <li role=\"presentation\"><a role=\"menuitem\" tabindex=\"-1\" href=\"http://twitter.com/fat\">Another action</a></li>\n                <li role=\"presentation\"><a role=\"menuitem\" tabindex=\"-1\" href=\"http://twitter.com/fat\">Something else here</a></li>\n                <li role=\"presentation\" class=\"divider\"></li>\n                <li role=\"presentation\"><a role=\"menuitem\" tabindex=\"-1\" href=\"http://twitter.com/fat\">Separated link</a></li>\n              </ul>\n            </li>\n            <li class=\"dropdown\">\n              <a href=\"#\" id=\"drop2\" role=\"button\" class=\"dropdown-toggle\" data-toggle=\"dropdown\">Dropdown 2 <b class=\"caret\"></b></a>\n              <ul class=\"dropdown-menu\" role=\"menu\" aria-labelledby=\"drop2\">\n                <li role=\"presentation\"><a role=\"menuitem\" tabindex=\"-1\" href=\"http://twitter.com/fat\">Action</a></li>\n                <li role=\"presentation\"><a role=\"menuitem\" tabindex=\"-1\" href=\"http://twitter.com/fat\">Another action</a></li>\n                <li role=\"presentation\"><a role=\"menuitem\" tabindex=\"-1\" href=\"http://twitter.com/fat\">Something else here</a></li>\n                <li role=\"presentation\" class=\"divider\"></li>\n                <li role=\"presentation\"><a role=\"menuitem\" tabindex=\"-1\" href=\"http://twitter.com/fat\">Separated link</a></li>\n              </ul>\n            </li>\n          </ul>\n          <ul class=\"nav navbar-nav navbar-right\">\n            <li id=\"fat-menu\" class=\"dropdown\">\n              <a href=\"#\" id=\"drop3\" role=\"button\" class=\"dropdown-toggle\" data-toggle=\"dropdown\">Dropdown 3 <b class=\"caret\"></b></a>\n              <ul class=\"dropdown-menu\" role=\"menu\" aria-labelledby=\"drop3\">\n                <li role=\"presentation\"><a role=\"menuitem\" tabindex=\"-1\" href=\"http://twitter.com/fat\">Action</a></li>\n                <li role=\"presentation\"><a role=\"menuitem\" tabindex=\"-1\" href=\"http://twitter.com/fat\">Another action</a></li>\n                <li role=\"presentation\"><a role=\"menuitem\" tabindex=\"-1\" href=\"http://twitter.com/fat\">Something else here</a></li>\n                <li role=\"presentation\" class=\"divider\"></li>\n                <li role=\"presentation\"><a role=\"menuitem\" tabindex=\"-1\" href=\"http://twitter.com/fat\">Separated link</a></li>\n              </ul>\n            </li>\n          </ul>\n        </div><!-- /.nav-collapse -->\n      </nav> <!-- /navbar-example -->\n    </div> <!-- /example -->\n\n    <h3>Within tabs</h3>\n    <div class=\"bs-example\">\n      <ul class=\"nav nav-pills\">\n        <li class=\"active\"><a href=\"#\">Regular link</a></li>\n        <li class=\"dropdown\">\n          <a id=\"drop4\" role=\"button\" data-toggle=\"dropdown\" href=\"#\">Dropdown <b class=\"caret\"></b></a>\n          <ul id=\"menu1\" class=\"dropdown-menu\" role=\"menu\" aria-labelledby=\"drop4\">\n            <li role=\"presentation\"><a role=\"menuitem\" tabindex=\"-1\" href=\"http://twitter.com/fat\">Action</a></li>\n            <li role=\"presentation\"><a role=\"menuitem\" tabindex=\"-1\" href=\"http://twitter.com/fat\">Another action</a></li>\n            <li role=\"presentation\"><a role=\"menuitem\" tabindex=\"-1\" href=\"http://twitter.com/fat\">Something else here</a></li>\n            <li role=\"presentation\" class=\"divider\"></li>\n            <li role=\"presentation\"><a role=\"menuitem\" tabindex=\"-1\" href=\"http://twitter.com/fat\">Separated link</a></li>\n          </ul>\n        </li>\n        <li class=\"dropdown\">\n          <a id=\"drop5\" role=\"button\" data-toggle=\"dropdown\" href=\"#\">Dropdown 2 <b class=\"caret\"></b></a>\n          <ul id=\"menu2\" class=\"dropdown-menu\" role=\"menu\" aria-labelledby=\"drop5\">\n            <li role=\"presentation\"><a role=\"menuitem\" tabindex=\"-1\" href=\"http://twitter.com/fat\">Action</a></li>\n            <li role=\"presentation\"><a role=\"menuitem\" tabindex=\"-1\" href=\"http://twitter.com/fat\">Another action</a></li>\n            <li role=\"presentation\"><a role=\"menuitem\" tabindex=\"-1\" href=\"http://twitter.com/fat\">Something else here</a></li>\n            <li role=\"presentation\" class=\"divider\"></li>\n            <li role=\"presentation\"><a role=\"menuitem\" tabindex=\"-1\" href=\"http://twitter.com/fat\">Separated link</a></li>\n          </ul>\n        </li>\n        <li class=\"dropdown\">\n          <a id=\"drop6\" role=\"button\" data-toggle=\"dropdown\" href=\"#\">Dropdown 3 <b class=\"caret\"></b></a>\n          <ul id=\"menu3\" class=\"dropdown-menu\" role=\"menu\" aria-labelledby=\"drop6\">\n            <li role=\"presentation\"><a role=\"menuitem\" tabindex=\"-1\" href=\"http://twitter.com/fat\">Action</a></li>\n            <li role=\"presentation\"><a role=\"menuitem\" tabindex=\"-1\" href=\"http://twitter.com/fat\">Another action</a></li>\n            <li role=\"presentation\"><a role=\"menuitem\" tabindex=\"-1\" href=\"http://twitter.com/fat\">Something else here</a></li>\n            <li role=\"presentation\" class=\"divider\"></li>\n            <li role=\"presentation\"><a role=\"menuitem\" tabindex=\"-1\" href=\"http://twitter.com/fat\">Separated link</a></li>\n          </ul>\n        </li>\n      </ul> <!-- /tabs -->\n    </div> <!-- /example -->\n\n\n    <h2 id=\"dropdowns-usage\">Usage</h2>\n\n    <h3>Via data attributes</h3>\n    <p>Add <code>data-toggle=\"dropdown\"</code> to a link or button to toggle a dropdown.</p>\n{% highlight html %}\n<div class=\"dropdown\">\n  <a data-toggle=\"dropdown\" href=\"#\">Dropdown trigger</a>\n  <ul class=\"dropdown-menu\" role=\"menu\" aria-labelledby=\"dLabel\">\n    ...\n  </ul>\n</div>\n{% endhighlight %}\n          <p>To keep URLs intact, use the <code>data-target</code> attribute instead of <code>href=\"#\"</code>.</p>\n{% highlight html %}\n<div class=\"dropdown\">\n  <a id=\"dLabel\" role=\"button\" data-toggle=\"dropdown\" data-target=\"#\" href=\"/page.html\">\n    Dropdown <span class=\"caret\"></span>\n  </a>\n  <ul class=\"dropdown-menu\" role=\"menu\" aria-labelledby=\"dLabel\">\n    ...\n  </ul>\n</div>\n{% endhighlight %}\n\n    <h3>Via JavaScript</h3>\n    <p>Call the dropdowns via JavaScript:</p>\n{% highlight js %}\n$('.dropdown-toggle').dropdown()\n{% endhighlight %}\n\n    <h3>Options</h3>\n    <p><em>None</em></p>\n\n    <h3>Methods</h3>\n    <h4>$().dropdown('toggle')</h4>\n    <p>Toggles the dropdown menu of a given navbar or tabbed navigation.</p>\n\n    <h3>Events</h3>\n    <div class=\"table-responsive\">\n      <table class=\"table table-bordered table-striped\">\n        <thead>\n          <tr>\n            <th style=\"width: 150px;\">Event Type</th>\n            <th>Description</th>\n          </tr>\n        </thead>\n        <tbody>\n          <tr>\n            <td>show.bs.dropdown</td>\n            <td>This event fires immediately when the show instance method is called.</td>\n          </tr>\n          <tr>\n            <td>shown.bs.dropdown</td>\n            <td>This event is fired when the dropdown has been made visible to the user (will wait for CSS transitions, to complete).</td>\n          </tr>\n          <tr>\n            <td>hide.bs.dropdown</td>\n            <td>This event is fired immediately when the hide instance method has been called.</td>\n          </tr>\n          <tr>\n            <td>hidden.bs.dropdown</td>\n            <td>This event is fired when the dropdown has finished being hidden from the user (will wait for CSS transitions, to complete).</td>\n          </tr>\n        </tbody>\n      </table>\n    </div><!-- ./bs-table-responsive -->\n{% highlight js %}\n$('#myDropdown').on('show.bs.dropdown', function () {\n  // do something…\n})\n{% endhighlight %}\n  </div>\n\n  <!-- ScrollSpy\n  ================================================== -->\n  <div class=\"bs-docs-section\">\n    <div class=\"page-header\">\n      <h1 id=\"scrollspy\">ScrollSpy <small>scrollspy.js</small></h1>\n    </div>\n\n\n    <h2 id=\"scrollspy-examples\">Example in navbar</h2>\n    <p>The ScrollSpy plugin is for automatically updating nav targets based on scroll position. Scroll the area below the navbar and watch the active class change. The dropdown sub items will be highlighted as well.</p>\n    <div class=\"bs-example\">\n      <nav id=\"navbar-example2\" class=\"navbar navbar-default navbar-static\" role=\"navigation\">\n        <div class=\"navbar-header\">\n          <button class=\"navbar-toggle\" type=\"button\" data-toggle=\"collapse\" data-target=\".bs-js-navbar-scrollspy\">\n            <span class=\"sr-only\">Toggle navigation</span>\n            <span class=\"icon-bar\"></span>\n            <span class=\"icon-bar\"></span>\n            <span class=\"icon-bar\"></span>\n          </button>\n          <a class=\"navbar-brand\" href=\"#\">Project Name</a>\n        </div>\n        <div class=\"collapse navbar-collapse bs-js-navbar-scrollspy\">\n          <ul class=\"nav navbar-nav\">\n            <li><a href=\"#fat\">@fat</a></li>\n            <li><a href=\"#mdo\">@mdo</a></li>\n            <li class=\"dropdown\">\n              <a href=\"#\" id=\"navbarDrop1\" class=\"dropdown-toggle\" data-toggle=\"dropdown\">Dropdown <b class=\"caret\"></b></a>\n              <ul class=\"dropdown-menu\" role=\"menu\" aria-labelledby=\"navbarDrop1\">\n                <li><a href=\"#one\" tabindex=\"-1\">one</a></li>\n                <li><a href=\"#two\" tabindex=\"-1\">two</a></li>\n                <li class=\"divider\"></li>\n                <li><a href=\"#three\" tabindex=\"-1\">three</a></li>\n              </ul>\n            </li>\n          </ul>\n        </div>\n      </nav>\n      <div data-spy=\"scroll\" data-target=\"#navbar-example2\" data-offset=\"0\" class=\"scrollspy-example\">\n        <h4 id=\"fat\">@fat</h4>\n        <p>Ad leggings keytar, brunch id art party dolor labore. Pitchfork yr enim lo-fi before they sold out qui. Tumblr farm-to-table bicycle rights whatever. Anim keffiyeh carles cardigan. Velit seitan mcsweeney's photo booth 3 wolf moon irure. Cosby sweater lomo jean shorts, williamsburg hoodie minim qui you probably haven't heard of them et cardigan trust fund culpa biodiesel wes anderson aesthetic. Nihil tattooed accusamus, cred irony biodiesel keffiyeh artisan ullamco consequat.</p>\n        <h4 id=\"mdo\">@mdo</h4>\n        <p>Veniam marfa mustache skateboard, adipisicing fugiat velit pitchfork beard. Freegan beard aliqua cupidatat mcsweeney's vero. Cupidatat four loko nisi, ea helvetica nulla carles. Tattooed cosby sweater food truck, mcsweeney's quis non freegan vinyl. Lo-fi wes anderson +1 sartorial. Carles non aesthetic exercitation quis gentrify. Brooklyn adipisicing craft beer vice keytar deserunt.</p>\n        <h4 id=\"one\">one</h4>\n        <p>Occaecat commodo aliqua delectus. Fap craft beer deserunt skateboard ea. Lomo bicycle rights adipisicing banh mi, velit ea sunt next level locavore single-origin coffee in magna veniam. High life id vinyl, echo park consequat quis aliquip banh mi pitchfork. Vero VHS est adipisicing. Consectetur nisi DIY minim messenger bag. Cred ex in, sustainable delectus consectetur fanny pack iphone.</p>\n        <h4 id=\"two\">two</h4>\n        <p>In incididunt echo park, officia deserunt mcsweeney's proident master cleanse thundercats sapiente veniam. Excepteur VHS elit, proident shoreditch +1 biodiesel laborum craft beer. Single-origin coffee wayfarers irure four loko, cupidatat terry richardson master cleanse. Assumenda you probably haven't heard of them art party fanny pack, tattooed nulla cardigan tempor ad. Proident wolf nesciunt sartorial keffiyeh eu banh mi sustainable. Elit wolf voluptate, lo-fi ea portland before they sold out four loko. Locavore enim nostrud mlkshk brooklyn nesciunt.</p>\n        <h4 id=\"three\">three</h4>\n        <p>Ad leggings keytar, brunch id art party dolor labore. Pitchfork yr enim lo-fi before they sold out qui. Tumblr farm-to-table bicycle rights whatever. Anim keffiyeh carles cardigan. Velit seitan mcsweeney's photo booth 3 wolf moon irure. Cosby sweater lomo jean shorts, williamsburg hoodie minim qui you probably haven't heard of them et cardigan trust fund culpa biodiesel wes anderson aesthetic. Nihil tattooed accusamus, cred irony biodiesel keffiyeh artisan ullamco consequat.</p>\n        <p>Keytar twee blog, culpa messenger bag marfa whatever delectus food truck. Sapiente synth id assumenda. Locavore sed helvetica cliche irony, thundercats you probably haven't heard of them consequat hoodie gluten-free lo-fi fap aliquip. Labore elit placeat before they sold out, terry richardson proident brunch nesciunt quis cosby sweater pariatur keffiyeh ut helvetica artisan. Cardigan craft beer seitan readymade velit. VHS chambray laboris tempor veniam. Anim mollit minim commodo ullamco thundercats.\n        </p>\n      </div>\n    </div><!-- /example -->\n\n\n    <h2 id=\"scrollspy-usage\">Usage</h2>\n\n    <h3>Via data attributes</h3>\n    <p>To easily add scrollspy behavior to your topbar navigation, add <code>data-spy=\"scroll\"</code> to the element you want to spy on (most typically this would be the <code>&lt;body&gt;</code>. Then add the <code>data-target</code> attribute with the ID or class of the parent element of any Bootstrap <code>.nav</code> component.</p>\n{% highlight html %}\n<body data-spy=\"scroll\" data-target=\"#navbar-example\">\n  ...\n</body>\n{% endhighlight %}\n\n    <h3>Via JavaScript</h3>\n    <p>Call the scrollspy via JavaScript:</p>\n{% highlight js %}\n$('body').scrollspy({ target: '#navbar-example' })\n{% endhighlight %}\n\n    <div class=\"bs-callout bs-callout-danger\">\n      <h4>Resolvable ID targets required</h4>\n      <p>Navbar links must have resolvable id targets. For example, a <code>&lt;a href=\"#home\"&gt;home&lt;/a&gt;</code> must correspond to something in the DOM like <code>&lt;div id=\"home\"&gt;&lt;/div&gt;</code>.</p>\n    </div>\n\n    <h3>Methods</h3>\n    <h4>.scrollspy('refresh')</h4>\n    <p>When using scrollspy in conjunction with adding or removing of elements from the DOM, you'll need to call the refresh method like so:</p>\n{% highlight js %}\n$('[data-spy=\"scroll\"]').each(function () {\n  var $spy = $(this).scrollspy('refresh')\n})\n{% endhighlight %}\n\n\n    <h3>Options</h3>\n    <p>Options can be passed via data attributes or JavaScript. For data attributes, append the option name to <code>data-</code>, as in <code>data-offset=\"\"</code>.</p>\n    <div class=\"table-responsive\">\n      <table class=\"table table-bordered table-striped\">\n        <thead>\n         <tr>\n           <th style=\"width: 100px;\">Name</th>\n           <th style=\"width: 100px;\">type</th>\n           <th style=\"width: 50px;\">default</th>\n           <th>description</th>\n         </tr>\n        </thead>\n        <tbody>\n         <tr>\n           <td>offset</td>\n           <td>number</td>\n           <td>10</td>\n           <td>Pixels to offset from top when calculating position of scroll.</td>\n         </tr>\n        </tbody>\n      </table>\n    </div><!-- ./bs-table-responsive -->\n\n    <h3>Events</h3>\n    <div class=\"table-responsive\">\n      <table class=\"table table-bordered table-striped\">\n        <thead>\n         <tr>\n           <th style=\"width: 150px;\">Event Type</th>\n           <th>Description</th>\n         </tr>\n        </thead>\n        <tbody>\n         <tr>\n           <td>activate.bs.scrollspy</td>\n           <td>This event fires whenever a new item becomes activated by the scrollspy.</td>\n        </tr>\n        </tbody>\n      </table>\n    </div><!-- ./bs-table-responsive -->\n{% highlight js %}\n$('#myScrollspy').on('activate.bs.scrollspy', function () {\n  // do something…\n})\n{% endhighlight %}\n  </div>\n\n\n\n  <!-- Tabs\n  ================================================== -->\n  <div class=\"bs-docs-section\">\n    <div class=\"page-header\">\n      <h1 id=\"tabs\">Togglable tabs <small>tab.js</small></h1>\n    </div>\n\n    <h2 id=\"tabs-examples\">Example tabs</h2>\n    <p>Add quick, dynamic tab functionality to transition through panes of local content, even via dropdown menus.</p>\n    <div class=\"bs-example bs-example-tabs\">\n      <ul id=\"myTab\" class=\"nav nav-tabs\">\n        <li class=\"active\"><a href=\"#home\" data-toggle=\"tab\">Home</a></li>\n        <li><a href=\"#profile\" data-toggle=\"tab\">Profile</a></li>\n        <li class=\"dropdown\">\n          <a href=\"#\" id=\"myTabDrop1\" class=\"dropdown-toggle\" data-toggle=\"dropdown\">Dropdown <b class=\"caret\"></b></a>\n          <ul class=\"dropdown-menu\" role=\"menu\" aria-labelledby=\"myTabDrop1\">\n            <li><a href=\"#dropdown1\" tabindex=\"-1\" data-toggle=\"tab\">@fat</a></li>\n            <li><a href=\"#dropdown2\" tabindex=\"-1\" data-toggle=\"tab\">@mdo</a></li>\n          </ul>\n        </li>\n      </ul>\n      <div id=\"myTabContent\" class=\"tab-content\">\n        <div class=\"tab-pane fade in active\" id=\"home\">\n          <p>Raw denim you probably haven't heard of them jean shorts Austin. Nesciunt tofu stumptown aliqua, retro synth master cleanse. Mustache cliche tempor, williamsburg carles vegan helvetica. Reprehenderit butcher retro keffiyeh dreamcatcher synth. Cosby sweater eu banh mi, qui irure terry richardson ex squid. Aliquip placeat salvia cillum iphone. Seitan aliquip quis cardigan american apparel, butcher voluptate nisi qui.</p>\n        </div>\n        <div class=\"tab-pane fade\" id=\"profile\">\n          <p>Food truck fixie locavore, accusamus mcsweeney's marfa nulla single-origin coffee squid. Exercitation +1 labore velit, blog sartorial PBR leggings next level wes anderson artisan four loko farm-to-table craft beer twee. Qui photo booth letterpress, commodo enim craft beer mlkshk aliquip jean shorts ullamco ad vinyl cillum PBR. Homo nostrud organic, assumenda labore aesthetic magna delectus mollit. Keytar helvetica VHS salvia yr, vero magna velit sapiente labore stumptown. Vegan fanny pack odio cillum wes anderson 8-bit, sustainable jean shorts beard ut DIY ethical culpa terry richardson biodiesel. Art party scenester stumptown, tumblr butcher vero sint qui sapiente accusamus tattooed echo park.</p>\n        </div>\n        <div class=\"tab-pane fade\" id=\"dropdown1\">\n          <p>Etsy mixtape wayfarers, ethical wes anderson tofu before they sold out mcsweeney's organic lomo retro fanny pack lo-fi farm-to-table readymade. Messenger bag gentrify pitchfork tattooed craft beer, iphone skateboard locavore carles etsy salvia banksy hoodie helvetica. DIY synth PBR banksy irony. Leggings gentrify squid 8-bit cred pitchfork. Williamsburg banh mi whatever gluten-free, carles pitchfork biodiesel fixie etsy retro mlkshk vice blog. Scenester cred you probably haven't heard of them, vinyl craft beer blog stumptown. Pitchfork sustainable tofu synth chambray yr.</p>\n        </div>\n        <div class=\"tab-pane fade\" id=\"dropdown2\">\n          <p>Trust fund seitan letterpress, keytar raw denim keffiyeh etsy art party before they sold out master cleanse gluten-free squid scenester freegan cosby sweater. Fanny pack portland seitan DIY, art party locavore wolf cliche high life echo park Austin. Cred vinyl keffiyeh DIY salvia PBR, banh mi before they sold out farm-to-table VHS viral locavore cosby sweater. Lomo wolf viral, mustache readymade thundercats keffiyeh craft beer marfa ethical. Wolf salvia freegan, sartorial keffiyeh echo park vegan.</p>\n        </div>\n      </div>\n    </div><!-- /example -->\n\n\n    <h2 id=\"tabs-usage\">Usage</h2>\n    <p>Enable tabbable tabs via JavaScript (each tab needs to be activated individually):</p>\n{% highlight js %}\n$('#myTab a').click(function (e) {\n  e.preventDefault()\n  $(this).tab('show')\n})\n{% endhighlight %}\n\n          <p>You can activate individual tabs in several ways:</p>\n{% highlight js %}\n$('#myTab a[href=\"#profile\"]').tab('show') // Select tab by name\n$('#myTab a:first').tab('show') // Select first tab\n$('#myTab a:last').tab('show') // Select last tab\n$('#myTab li:eq(2) a').tab('show') // Select third tab (0-indexed)\n{% endhighlight %}\n\n    <h3>Markup</h3>\n    <p>You can activate a tab or pill navigation without writing any JavaScript by simply specifying <code>data-toggle=\"tab\"</code> or <code>data-toggle=\"pill\"</code> on an element. Adding the <code>nav</code> and <code>nav-tabs</code> classes to the tab <code>ul</code> will apply the Bootstrap tab styling.</p>\n{% highlight html %}\n<ul class=\"nav nav-tabs\">\n  <li><a href=\"#home\" data-toggle=\"tab\">Home</a></li>\n  <li><a href=\"#profile\" data-toggle=\"tab\">Profile</a></li>\n  <li><a href=\"#messages\" data-toggle=\"tab\">Messages</a></li>\n  <li><a href=\"#settings\" data-toggle=\"tab\">Settings</a></li>\n</ul>\n{% endhighlight %}\n\n    <p>To make tabs fade in, add <code>.fade</code> to each <code>.tab-pane</code>.</p>\n\n    <h3>Methods</h3>\n    <h4>$().tab</h4>\n    <p>\n      Activates a tab element and content container. Tab should have either a <code>data-target</code> or an <code>href</code> targeting a container node in the DOM.\n    </p>\n{% highlight html %}\n<ul class=\"nav nav-tabs\" id=\"myTab\">\n  <li class=\"active\"><a href=\"#home\">Home</a></li>\n  <li><a href=\"#profile\">Profile</a></li>\n  <li><a href=\"#messages\">Messages</a></li>\n  <li><a href=\"#settings\">Settings</a></li>\n</ul>\n\n<div class=\"tab-content\">\n  <div class=\"tab-pane active\" id=\"home\">...</div>\n  <div class=\"tab-pane\" id=\"profile\">...</div>\n  <div class=\"tab-pane\" id=\"messages\">...</div>\n  <div class=\"tab-pane\" id=\"settings\">...</div>\n</div>\n\n<script>\n  $(function () {\n    $('#myTab a:last').tab('show')\n  })\n</script>\n{% endhighlight %}\n\n    <h3>Events</h3>\n    <div class=\"table-responsive\">\n      <table class=\"table table-bordered table-striped\">\n        <thead>\n         <tr>\n           <th style=\"width: 150px;\">Event Type</th>\n           <th>Description</th>\n         </tr>\n        </thead>\n        <tbody>\n         <tr>\n           <td>show.bs.tab</td>\n           <td>This event fires on tab show, but before the new tab has been shown. Use <code>event.target</code> and <code>event.relatedTarget</code> to target the active tab and the previous active tab (if available) respectively.</td>\n        </tr>\n        <tr>\n           <td>shown.bs.tab</td>\n           <td>This event fires on tab show after a tab has been shown. Use <code>event.target</code> and <code>event.relatedTarget</code> to target the active tab and the previous active tab (if available) respectively.</td>\n         </tr>\n        </tbody>\n      </table>\n    </div><!-- /.table-responsive -->\n{% highlight js %}\n$('a[data-toggle=\"tab\"]').on('shown.bs.tab', function (e) {\n  e.target // activated tab\n  e.relatedTarget // previous tab\n})\n{% endhighlight %}\n  </div>\n\n\n\n  <!-- Tooltips\n  ================================================== -->\n  <div class=\"bs-docs-section\">\n    <div class=\"page-header\">\n      <h1 id=\"tooltips\">Tooltips <small>tooltip.js</small></h1>\n    </div>\n\n    <h2 id=\"tooltips-examples\">Examples</h2>\n    <p>Inspired by the excellent jQuery.tipsy plugin written by Jason Frame; Tooltips are an updated version, which don't rely on images, use CSS3 for animations, and data-attributes for local title storage.</p>\n    <p>Hover over the links below to see tooltips:</p>\n    <div class=\"bs-example tooltip-demo\">\n      <p class=\"muted\" style=\"margin-bottom: 0;\">Tight pants next level keffiyeh <a href=\"#\" data-toggle=\"tooltip\" title=\"Default tooltip\">you probably</a> haven't heard of them. Photo booth beard raw denim letterpress vegan messenger bag stumptown. Farm-to-table seitan, mcsweeney's fixie sustainable quinoa 8-bit american apparel <a href=\"#\" data-toggle=\"tooltip\" title=\"Another tooltip\">have a</a> terry richardson vinyl chambray. Beard stumptown, cardigans banh mi lomo thundercats. Tofu biodiesel williamsburg marfa, four loko mcsweeney's cleanse vegan chambray. A really ironic artisan <a href=\"#\" data-toggle=\"tooltip\" title=\"Another one here too\">whatever keytar</a>, scenester farm-to-table banksy Austin <a href=\"#\" data-toggle=\"tooltip\" title=\"The last tip!\">twitter handle</a> freegan cred raw denim single-origin coffee viral.\n      </p>\n    </div><!-- /example -->\n\n    <h3>Four directions</h3>\n    <div class=\"bs-example tooltip-demo\">\n      <div class=\"bs-example-tooltips\">\n        <button type=\"button\" class=\"btn btn-default\" data-toggle=\"tooltip\" data-placement=\"left\" title=\"Tooltip on left\">Tooltip on left</button>\n        <button type=\"button\" class=\"btn btn-default\" data-toggle=\"tooltip\" data-placement=\"top\" title=\"Tooltip on top\">Tooltip on top</button>\n        <button type=\"button\" class=\"btn btn-default\" data-toggle=\"tooltip\" data-placement=\"bottom\" title=\"Tooltip on bottom\">Tooltip on bottom</button>\n        <button type=\"button\" class=\"btn btn-default\" data-toggle=\"tooltip\" data-placement=\"right\" title=\"Tooltip on right\">Tooltip on right</button>\n      </div>\n    </div><!-- /example -->\n\n    <div class=\"bs-callout bs-callout-info\">\n      <h4>Tooltips in button groups and input groups require special setting</h4>\n      <p>When using tooltips on elements within a <code>.btn-group</code> or an <code>.input-group</code>, you'll have to specify the option <code>container: 'body'</code> (documented below) to avoid unwanted side effects (such as the element growing wider and/or losing its rounded corners when the tooltip is triggered).</p>\n    </div>\n\n\n    <h2 id=\"tooltips-usage\">Usage</h2>\n    <p>Trigger the tooltip via JavaScript:</p>\n{% highlight js %}\n$('#example').tooltip(options)\n{% endhighlight %}\n\n    <h3>Options</h3>\n    <p>Options can be passed via data attributes or JavaScript. For data attributes, append the option name to <code>data-</code>, as in <code>data-animation=\"\"</code>.</p>\n    <div class=\"table-responsive\">\n      <table class=\"table table-bordered table-striped\">\n        <thead>\n         <tr>\n           <th style=\"width: 100px;\">Name</th>\n           <th style=\"width: 100px;\">type</th>\n           <th style=\"width: 50px;\">default</th>\n           <th>description</th>\n         </tr>\n        </thead>\n        <tbody>\n         <tr>\n           <td>animation</td>\n           <td>boolean</td>\n           <td>true</td>\n           <td>apply a CSS fade transition to the tooltip</td>\n         </tr>\n         <tr>\n           <td>html</td>\n           <td>boolean</td>\n           <td>false</td>\n           <td>Insert HTML into the tooltip. If false, jQuery's <code>text</code> method will be used to insert content into the DOM. Use text if you're worried about XSS attacks.</td>\n         </tr>\n         <tr>\n           <td>placement</td>\n           <td>string | function</td>\n           <td>'top'</td>\n           <td>how to position the tooltip - top | bottom | left | right | auto. <br> When \"auto\" is specified, it will dynamically reorient the tooltip. For example, if placement is \"auto left\", the tooltip will display to the left when possible, otherwise it will display right.</td>\n         </tr>\n         <tr>\n           <td>selector</td>\n           <td>string</td>\n           <td>false</td>\n           <td>If a selector is provided, tooltip objects will be delegated to the specified targets.</td>\n         </tr>\n         <tr>\n           <td>title</td>\n           <td>string | function</td>\n           <td>''</td>\n           <td>default title value if <code>title</code> attribute isn't present</td>\n         </tr>\n         <tr>\n           <td>trigger</td>\n           <td>string</td>\n           <td>'hover focus'</td>\n           <td>how tooltip is triggered - click | hover | focus | manual. You may pass multiple triggers; separate them with a space.</td>\n         </tr>\n         <tr>\n           <td>delay</td>\n           <td>number | object</td>\n           <td>0</td>\n           <td>\n            <p>delay showing and hiding the tooltip (ms) - does not apply to manual trigger type</p>\n            <p>If a number is supplied, delay is applied to both hide/show</p>\n            <p>Object structure is: <code>delay: { show: 500, hide: 100 }</code></p>\n           </td>\n         </tr>\n         <tr>\n           <td>container</td>\n           <td>string | false</td>\n           <td>false</td>\n           <td>\n            <p>Appends the tooltip to a specific element. Example: <code>container: 'body'</code></p>\n           </td>\n         </tr>\n        </tbody>\n      </table>\n    </div><!-- /.table-responsive -->\n    <div class=\"bs-callout bs-callout-info\">\n      <h4>Data attributes for individual tooltips</h4>\n      <p>Options for individual tooltips can alternatively be specified through the use of data attributes, as explained above.</p>\n    </div>\n\n    <h3>Markup</h3>\n{% highlight html %}\n<a href=\"#\" data-toggle=\"tooltip\" title=\"first tooltip\">Hover over me</a>\n{% endhighlight %}\n\n    <h3>Methods</h3>\n\n    <h4>$().tooltip(options)</h4>\n    <p>Attaches a tooltip handler to an element collection.</p>\n\n    <h4>.tooltip('show')</h4>\n    <p>Reveals an element's tooltip.</p>\n    {% highlight js %}$('#element').tooltip('show'){% endhighlight %}\n\n    <h4>.tooltip('hide')</h4>\n    <p>Hides an element's tooltip.</p>\n    {% highlight js %}$('#element').tooltip('hide'){% endhighlight %}\n\n    <h4>.tooltip('toggle')</h4>\n    <p>Toggles an element's tooltip.</p>\n    {% highlight js %}$('#element').tooltip('toggle'){% endhighlight %}\n\n    <h4>.tooltip('destroy')</h4>\n    <p>Hides and destroys an element's tooltip.</p>\n    {% highlight js %}$('#element').tooltip('destroy'){% endhighlight %}\n\n    <h3>Events</h3>\n    <div class=\"table-responsive\">\n      <table class=\"table table-bordered table-striped\">\n        <thead>\n         <tr>\n           <th style=\"width: 150px;\">Event Type</th>\n           <th>Description</th>\n         </tr>\n        </thead>\n        <tbody>\n         <tr>\n           <td>show.bs.tooltip</td>\n           <td>This event fires immediately when the <code>show</code> instance method is called.</td>\n         </tr>\n         <tr>\n           <td>shown.bs.tooltip</td>\n           <td>This event is fired when the tooltip has been made visible to the user (will wait for CSS transitions to complete).</td>\n         </tr>\n         <tr>\n           <td>hide.bs.tooltip</td>\n           <td>This event is fired immediately when the <code>hide</code> instance method has been called.</td>\n         </tr>\n         <tr>\n           <td>hidden.bs.tooltip</td>\n           <td>This event is fired when the tooltip has finished being hidden from the user (will wait for CSS transitions to complete).</td>\n         </tr>\n        </tbody>\n      </table>\n    </div><!-- /.table-responsive -->\n{% highlight js %}\n$('#myTooltip').on('hidden.bs.tooltip', function () {\n  // do something…\n})\n{% endhighlight %}\n  </div>\n\n  <!-- Popovers\n  ================================================== -->\n  <div class=\"bs-docs-section\">\n    <div class=\"page-header\">\n      <h1 id=\"popovers\">Popovers <small>popover.js</small></h1>\n    </div>\n\n    <h2 id=\"popovers-examples\">Examples</h2>\n    <p>Add small overlays of content, like those on the iPad, to any element for housing secondary information.</p>\n\n    <div class=\"bs-callout bs-callout-danger\">\n      <h4>Plugin dependency</h4>\n      <p>Popovers require the <a href=\"#tooltips\">tooltip plugin</a> to be included in your version of Bootstrap.</p>\n    </div>\n    <div class=\"bs-callout bs-callout-info\">\n      <h4>Popovers in button groups and input groups require special setting</h4>\n      <p>When using popovers on elements within a <code>.btn-group</code> or an <code>.input-group</code>, you'll have to specify the option <code>container: 'body'</code> (documented below) to avoid unwanted side effects (such as the element growing wider and/or losing its rounded corners when the popover is triggered).</p>\n    </div>\n\n    <h3>Static popover</h3>\n    <p>Four options are available: top, right, bottom, and left aligned.</p>\n    <div class=\"bs-example bs-example-popover\">\n      <div class=\"popover top\">\n        <div class=\"arrow\"></div>\n        <h3 class=\"popover-title\">Popover top</h3>\n        <div class=\"popover-content\">\n          <p>Sed posuere consectetur est at lobortis. Aenean eu leo quam. Pellentesque ornare sem lacinia quam venenatis vestibulum.</p>\n        </div>\n      </div>\n\n      <div class=\"popover right\">\n        <div class=\"arrow\"></div>\n        <h3 class=\"popover-title\">Popover right</h3>\n        <div class=\"popover-content\">\n          <p>Sed posuere consectetur est at lobortis. Aenean eu leo quam. Pellentesque ornare sem lacinia quam venenatis vestibulum.</p>\n        </div>\n      </div>\n\n      <div class=\"popover bottom\">\n        <div class=\"arrow\"></div>\n        <h3 class=\"popover-title\">Popover bottom</h3>\n        <div class=\"popover-content\">\n          <p>Sed posuere consectetur est at lobortis. Aenean eu leo quam. Pellentesque ornare sem lacinia quam venenatis vestibulum.</p>\n        </div>\n      </div>\n\n      <div class=\"popover left\">\n        <div class=\"arrow\"></div>\n        <h3 class=\"popover-title\">Popover left</h3>\n        <div class=\"popover-content\">\n          <p>Sed posuere consectetur est at lobortis. Aenean eu leo quam. Pellentesque ornare sem lacinia quam venenatis vestibulum.</p>\n        </div>\n      </div>\n\n      <div class=\"clearfix\"></div>\n    </div>\n\n    <h3>Live demo</h3>\n    <div class=\"bs-example\" style=\"padding-bottom: 24px;\">\n      <a href=\"#\" class=\"btn btn-lg btn-danger\" data-toggle=\"popover\" title=\"A Title\" data-content=\"And here's some amazing content. It's very engaging. right?\">Click to toggle popover</a>\n    </div>\n\n    <h4>Four directions</h4>\n    <div class=\"bs-example tooltip-demo\">\n      <div class=\"bs-example-tooltips\">\n        <button type=\"button\" class=\"btn btn-default\" data-container=\"body\" data-toggle=\"popover\" data-placement=\"left\" data-content=\"Vivamus sagittis lacus vel augue laoreet rutrum faucibus.\">\n          Popover on left\n        </button>\n        <button type=\"button\" class=\"btn btn-default\" data-container=\"body\" data-toggle=\"popover\" data-placement=\"top\" data-content=\"Vivamus sagittis lacus vel augue laoreet rutrum faucibus.\">\n          Popover on top\n        </button>\n        <button type=\"button\" class=\"btn btn-default\" data-container=\"body\" data-toggle=\"popover\" data-placement=\"bottom\" data-content=\"Vivamus sagittis lacus vel augue laoreet rutrum faucibus.\">\n          Popover on bottom\n        </button>\n        <button type=\"button\" class=\"btn btn-default\" data-container=\"body\" data-toggle=\"popover\" data-placement=\"right\" data-content=\"Vivamus sagittis lacus vel augue laoreet rutrum faucibus.\">\n          Popover on right\n        </button>\n      </div>\n    </div><!-- /example -->\n\n\n    <h2 id=\"popovers-usage\">Usage</h2>\n    <p>Enable popovers via JavaScript:</p>\n    {% highlight js %}$('#example').popover(options){% endhighlight %}\n\n    <h3>Options</h3>\n    <p>Options can be passed via data attributes or JavaScript. For data attributes, append the option name to <code>data-</code>, as in <code>data-animation=\"\"</code>.</p>\n    <div class=\"table-responsive\">\n      <table class=\"table table-bordered table-striped\">\n        <thead>\n          <tr>\n            <th style=\"width: 100px;\">Name</th>\n            <th style=\"width: 100px;\">type</th>\n            <th style=\"width: 50px;\">default</th>\n            <th>description</th>\n          </tr>\n        </thead>\n        <tbody>\n          <tr>\n            <td>animation</td>\n            <td>boolean</td>\n            <td>true</td>\n            <td>apply a CSS fade transition to the tooltip</td>\n          </tr>\n          <tr>\n            <td>html</td>\n            <td>boolean</td>\n            <td>false</td>\n            <td>Insert HTML into the popover. If false, jQuery's <code>text</code> method will be used to insert content into the DOM. Use text if you're worried about XSS attacks.</td>\n          </tr>\n          <tr>\n            <td>placement</td>\n            <td>string | function</td>\n            <td>'right'</td>\n            <td>how to position the popover - top | bottom | left | right | auto.<br> When \"auto\" is specified, it will dynamically reorient the popover. For example, if placement is \"auto left\", the tooltip will display to the left when possible, otherwise it will display right.</td>\n          </tr>\n          <tr>\n            <td>selector</td>\n            <td>string</td>\n            <td>false</td>\n            <td>if a selector is provided, tooltip objects will be delegated to the specified targets if a selector is provided, tooltip objects will be delegated to the specified targets. in practice, this is used to enable dynamic HTML content to have popovers added. See <a href=\"https://github.com/twbs/bootstrap/issues/4215\">this</a> and <a href=\"http://jsfiddle.net/KPeKS/4/\">an informative example</a>.</td>\n          </tr>\n          <tr>\n            <td>trigger</td>\n            <td>string</td>\n            <td>'click'</td>\n            <td>how popover is triggered - click | hover | focus | manual</td>\n          </tr>\n          <tr>\n            <td>title</td>\n            <td>string | function</td>\n            <td>''</td>\n            <td>default title value if <code>title</code> attribute isn't present</td>\n          </tr>\n          <tr>\n            <td>content</td>\n            <td>string | function</td>\n            <td>''</td>\n            <td>default content value if <code>data-content</code> attribute isn't present</td>\n          </tr>\n          <tr>\n            <td>delay</td>\n            <td>number | object</td>\n            <td>0</td>\n            <td>\n             <p>delay showing and hiding the popover (ms) - does not apply to manual trigger type</p>\n             <p>If a number is supplied, delay is applied to both hide/show</p>\n             <p>Object structure is: <code>delay: { show: 500, hide: 100 }</code></p>\n            </td>\n          </tr>\n          <tr>\n            <td>container</td>\n            <td>string | false</td>\n            <td>false</td>\n            <td>\n             <p>Appends the popover to a specific element. Example: <code>container: 'body'</code>. This option is particularly useful in that it allows you to position the popover in the flow of the document near the triggering element - which will prevent the popover from floating away from the triggering element during a window resize.</p>\n            </td>\n          </tr>\n        </tbody>\n      </table>\n    </div><!-- /.table-responsive -->\n    <div class=\"bs-callout bs-callout-info\">\n      <h4>Data attributes for individual popovers</h4>\n      <p>Options for individual popovers can alternatively be specified through the use of data attributes, as explained above.</p>\n    </div>\n\n    <h3>Markup</h3>\n    <p>For performance reasons, the Tooltip and Popover data-apis are opt in. If you would like to use them just specify a selector option.</p>\n\n    <h3>Methods</h3>\n    <h4>$().popover(options)</h4>\n    <p>Initializes popovers for an element collection.</p>\n\n    <h4>.popover('show')</h4>\n    <p>Reveals an elements popover.</p>\n    {% highlight js %}$('#element').popover('show'){% endhighlight %}\n\n    <h4>.popover('hide')</h4>\n    <p>Hides an elements popover.</p>\n    {% highlight js %}$('#element').popover('hide'){% endhighlight %}\n\n    <h4>.popover('toggle')</h4>\n    <p>Toggles an elements popover.</p>\n    {% highlight js %}$('#element').popover('toggle'){% endhighlight %}\n\n    <h4>.popover('destroy')</h4>\n    <p>Hides and destroys an element's popover.</p>\n    {% highlight js %}$('#element').popover('destroy'){% endhighlight %}\n    <h3>Events</h3>\n    <div class=\"table-responsive\">\n      <table class=\"table table-bordered table-striped\">\n        <thead>\n         <tr>\n           <th style=\"width: 150px;\">Event Type</th>\n           <th>Description</th>\n         </tr>\n        </thead>\n        <tbody>\n         <tr>\n           <td>show.bs.popover</td>\n           <td>This event fires immediately when the <code>show</code> instance method is called.</td>\n         </tr>\n         <tr>\n           <td>shown.bs.popover</td>\n           <td>This event is fired when the popover has been made visible to the user (will wait for CSS transitions to complete).</td>\n         </tr>\n         <tr>\n           <td>hide.bs.popover</td>\n           <td>This event is fired immediately when the <code>hide</code> instance method has been called.</td>\n         </tr>\n         <tr>\n           <td>hidden.bs.popover</td>\n           <td>This event is fired when the popover has finished being hidden from the user (will wait for CSS transitions to complete).</td>\n         </tr>\n        </tbody>\n      </table>\n    </div><!-- /.table-responsive -->\n{% highlight js %}\n$('#myPopover').on('hidden.bs.popover', function () {\n  // do something…\n})\n{% endhighlight %}\n  </div>\n\n  <!-- Alert\n  ================================================== -->\n  <div class=\"bs-docs-section\">\n    <div class=\"page-header\">\n      <h1 id=\"alerts\">Alert messages <small>alert.js</small></h1>\n    </div>\n\n\n    <h2 id=\"alerts-examples\">Example alerts</h2>\n    <p>Add dismiss functionality to all alert messages with this plugin.</p>\n    <div class=\"bs-example\">\n      <div class=\"alert alert-warning fade in\">\n        <button type=\"button\" class=\"close\" data-dismiss=\"alert\" aria-hidden=\"true\">&times;</button>\n        <strong>Holy guacamole!</strong> Best check yo self, you're not looking too good.\n      </div>\n    </div><!-- /example -->\n\n    <div class=\"bs-example\">\n      <div class=\"alert alert-block alert-danger fade in\">\n        <button type=\"button\" class=\"close\" data-dismiss=\"alert\" aria-hidden=\"true\">&times;</button>\n        <h4>Oh snap! You got an error!</h4>\n        <p>Change this and that and try again. Duis mollis, est non commodo luctus, nisi erat porttitor ligula, eget lacinia odio sem nec elit. Cras mattis consectetur purus sit amet fermentum.</p>\n        <p>\n          <a class=\"btn btn-danger\" href=\"#\">Take this action</a> <a class=\"btn btn-default\" href=\"#\">Or do this</a>\n        </p>\n      </div>\n    </div><!-- /example -->\n\n\n    <h2 id=\"alerts-usage\">Usage</h2>\n    <p>Enable dismissal of an alert via JavaScript:</p>\n    {% highlight js %}$(\".alert\").alert(){% endhighlight %}\n\n    <h3>Markup</h3>\n    <p>Just add <code>data-dismiss=\"alert\"</code> to your close button to automatically give an alert close functionality.</p>\n    {% highlight html %}<a class=\"close\" data-dismiss=\"alert\" href=\"#\" aria-hidden=\"true\">&times;</a>{% endhighlight %}\n\n    <h3>Methods</h3>\n\n    <h4>$().alert()</h4>\n    <p>Wraps all alerts with close functionality. To have your alerts animate out when closed, make sure they have the <code>.fade</code> and <code>.in</code> class already applied to them.</p>\n\n    <h4>.alert('close')</h4>\n    <p>Closes an alert.</p>\n    {% highlight js %}$(\".alert\").alert('close'){% endhighlight %}\n\n\n    <h3>Events</h3>\n    <p>Bootstrap's alert class exposes a few events for hooking into alert functionality.</p>\n    <div class=\"table-responsive\">\n      <table class=\"table table-bordered table-striped\">\n        <thead>\n          <tr>\n            <th style=\"width: 150px;\">Event Type</th>\n            <th>Description</th>\n          </tr>\n        </thead>\n        <tbody>\n          <tr>\n            <td>close.bs.alert</td>\n            <td>This event fires immediately when the <code>close</code> instance method is called.</td>\n          </tr>\n          <tr>\n            <td>closed.bs.alert</td>\n            <td>This event is fired when the alert has been closed (will wait for CSS transitions to complete).</td>\n          </tr>\n        </tbody>\n      </table>\n    </div><!-- /.table-responsive -->\n{% highlight js %}\n$('#my-alert').bind('closed.bs.alert', function () {\n  // do something…\n})\n{% endhighlight %}\n  </div>\n\n\n\n  <!-- Buttons\n  ================================================== -->\n  <div class=\"bs-docs-section\">\n    <div class=\"page-header\">\n      <h1 id=\"buttons\">Buttons <small>button.js</small></h1>\n    </div>\n\n    <h2 id=\"buttons-examples\">Example uses</h2>\n    <p>Do more with buttons. Control button states or create groups of buttons for more components like toolbars.</p>\n\n    <h4>Stateful</h4>\n    <p>Add <code>data-loading-text=\"Loading...\"</code> to use a loading state on a button.</p>\n    <div class=\"bs-example\" style=\"padding-bottom: 24px;\">\n      <button type=\"button\" id=\"fat-btn\" data-loading-text=\"Loading...\" class=\"btn btn-primary\">\n        Loading state\n      </button>\n    </div><!-- /example -->\n{% highlight html %}\n<button type=\"button\" data-loading-text=\"Loading...\" class=\"btn btn-primary\">\n  Loading state\n</button>\n{% endhighlight %}\n\n    <h4>Single toggle</h4>\n    <p>Add <code>data-toggle=\"button\"</code> to activate toggling on a single button.</p>\n    <div class=\"bs-example\" style=\"padding-bottom: 24px;\">\n      <button type=\"button\" class=\"btn btn-primary\" data-toggle=\"button\">Single toggle</button>\n    </div><!-- /example -->\n{% highlight html %}\n<button type=\"button\" class=\"btn btn-primary\" data-toggle=\"button\">Single toggle</button>\n{% endhighlight %}\n\n    <h4>Checkbox</h4>\n    <p>Add <code>data-toggle=\"buttons\"</code> to a group of checkboxes for checkbox style toggling on btn-group.</p>\n    <div class=\"bs-example\" style=\"padding-bottom: 24px;\">\n      <div class=\"btn-group\" data-toggle=\"buttons\">\n        <label class=\"btn btn-primary\">\n          <input type=\"checkbox\"> Option 1\n        </label>\n        <label class=\"btn btn-primary\">\n          <input type=\"checkbox\"> Option 2\n        </label>\n        <label class=\"btn btn-primary\">\n          <input type=\"checkbox\"> Option 3\n        </label>\n      </div>\n    </div><!-- /example -->\n{% highlight html %}\n<div class=\"btn-group\" data-toggle=\"buttons\">\n  <label class=\"btn btn-primary\">\n    <input type=\"checkbox\"> Option 1\n  </label>\n  <label class=\"btn btn-primary\">\n    <input type=\"checkbox\"> Option 2\n  </label>\n  <label class=\"btn btn-primary\">\n    <input type=\"checkbox\"> Option 3\n  </label>\n</div>\n{% endhighlight %}\n\n    <h4>Radio</h4>\n    <p>Add <code>data-toggle=\"buttons\"</code> to a group of radio inputs for radio style toggling on btn-group.</p>\n    <div class=\"bs-example\" style=\"padding-bottom: 24px;\">\n      <div class=\"btn-group\" data-toggle=\"buttons\">\n        <label class=\"btn btn-primary\">\n          <input type=\"radio\" name=\"options\" id=\"option1\"> Option 1\n        </label>\n        <label class=\"btn btn-primary\">\n          <input type=\"radio\" name=\"options\" id=\"option2\"> Option 2\n        </label>\n        <label class=\"btn btn-primary\">\n          <input type=\"radio\" name=\"options\" id=\"option3\"> Option 3\n        </label>\n      </div>\n    </div><!-- /example -->\n{% highlight html %}\n<div class=\"btn-group\" data-toggle=\"buttons\">\n  <label class=\"btn btn-primary\">\n    <input type=\"radio\" name=\"options\" id=\"option1\"> Option 1\n  </label>\n  <label class=\"btn btn-primary\">\n    <input type=\"radio\" name=\"options\" id=\"option2\"> Option 2\n  </label>\n  <label class=\"btn btn-primary\">\n    <input type=\"radio\" name=\"options\" id=\"option3\"> Option 3\n  </label>\n</div>\n{% endhighlight %}\n\n\n    <h2 id=\"buttons-usage\">Usage</h2>\n    <p>Enable buttons via JavaScript:</p>\n{% highlight js %}\n$('.nav-tabs').button()\n{% endhighlight %}\n\n    <h3>Markup</h3>\n    <p>Data attributes are integral to the button plugin. Check out the example code below for the various markup types.</p>\n\n    <h3>Options</h3>\n    <p><em>None</em></p>\n\n    <h3>Methods</h3>\n\n    <h4>$().button('toggle')</h4>\n    <p>Toggles push state. Gives the button the appearance that it has been activated.</p>\n    <div class=\"bs-callout bs-callout-info\">\n      <h4>Auto toggling</h4>\n      <p>You can enable auto toggling of a button by using the <code>data-toggle</code> attribute.</p>\n    </div>\n{% highlight html %}\n<button type=\"button\" class=\"btn\" data-toggle=\"button\">...</button>\n{% endhighlight %}\n\n    <h4>$().button('loading')</h4>\n    <p>Sets button state to loading - disables button and swaps text to loading text. Loading text should be defined on the button element using the data attribute <code>data-loading-text</code>.\n    </p>\n{% highlight html %}\n<button type=\"button\" class=\"btn\" data-loading-text=\"loading stuff...\">...</button>\n{% endhighlight %}\n\n    <div class=\"bs-callout bs-callout-danger\">\n      <h4>Cross-browser compatibility</h4>\n      <p><a href=\"https://github.com/twbs/bootstrap/issues/793\">Firefox persists the disabled state across page loads</a>. A workaround for this is to use <code>autocomplete=\"off\"</code>.</p>\n    </div>\n\n    <h4>$().button('reset')</h4>\n    <p>Resets button state - swaps text to original text.</p>\n\n    <h4>$().button(string)</h4>\n    <p>Resets button state - swaps text to any data defined text state.</p>\n{% highlight html %}\n<button type=\"button\" class=\"btn\" data-complete-text=\"finished!\" >...</button>\n<script>\n  $('.btn').button('complete')\n</script>\n{% endhighlight %}\n  </div>\n\n\n\n  <!-- Collapse\n  ================================================== -->\n  <div class=\"bs-docs-section\">\n    <div class=\"page-header\">\n      <h1 id=\"collapse\">Collapse <small>collapse.js</small></h1>\n    </div>\n\n    <h3>About</h3>\n    <p>Get base styles and flexible support for collapsible components like accordions and navigation.</p>\n\n    <div class=\"bs-callout bs-callout-danger\">\n      <h4>Plugin dependency</h4>\n      <p>Collapse requires the <a href=\"#transitions\">transitions plugin</a> to be included in your version of Bootstrap.</p>\n    </div>\n\n    <h2 id=\"collapse-examples\">Example accordion</h2>\n    <p>Using the collapse plugin, we built a simple accordion by extending the panel component.</p>\n\n    <div class=\"bs-example\">\n      <div class=\"panel-group\" id=\"accordion\">\n        <div class=\"panel panel-default\">\n          <div class=\"panel-heading\">\n            <h4 class=\"panel-title\">\n              <a class=\"accordion-toggle\" data-toggle=\"collapse\" data-parent=\"#accordion\" href=\"#collapseOne\">\n                Collapsible Group Item #1\n              </a>\n            </h4>\n          </div>\n          <div id=\"collapseOne\" class=\"panel-collapse collapse in\">\n            <div class=\"panel-body\">\n              Anim pariatur cliche reprehenderit, enim eiusmod high life accusamus terry richardson ad squid. 3 wolf moon officia aute, non cupidatat skateboard dolor brunch. Food truck quinoa nesciunt laborum eiusmod. Brunch 3 wolf moon tempor, sunt aliqua put a bird on it squid single-origin coffee nulla assumenda shoreditch et. Nihil anim keffiyeh helvetica, craft beer labore wes anderson cred nesciunt sapiente ea proident. Ad vegan excepteur butcher vice lomo. Leggings occaecat craft beer farm-to-table, raw denim aesthetic synth nesciunt you probably haven't heard of them accusamus labore sustainable VHS.\n            </div>\n          </div>\n        </div>\n        <div class=\"panel panel-default\">\n          <div class=\"panel-heading\">\n            <h4 class=\"panel-title\">\n              <a class=\"accordion-toggle\" data-toggle=\"collapse\" data-parent=\"#accordion\" href=\"#collapseTwo\">\n                Collapsible Group Item #2\n              </a>\n            </h4>\n          </div>\n          <div id=\"collapseTwo\" class=\"panel-collapse collapse\">\n            <div class=\"panel-body\">\n              Anim pariatur cliche reprehenderit, enim eiusmod high life accusamus terry richardson ad squid. 3 wolf moon officia aute, non cupidatat skateboard dolor brunch. Food truck quinoa nesciunt laborum eiusmod. Brunch 3 wolf moon tempor, sunt aliqua put a bird on it squid single-origin coffee nulla assumenda shoreditch et. Nihil anim keffiyeh helvetica, craft beer labore wes anderson cred nesciunt sapiente ea proident. Ad vegan excepteur butcher vice lomo. Leggings occaecat craft beer farm-to-table, raw denim aesthetic synth nesciunt you probably haven't heard of them accusamus labore sustainable VHS.\n            </div>\n          </div>\n        </div>\n        <div class=\"panel panel-default\">\n          <div class=\"panel-heading\">\n            <h4 class=\"panel-title\">\n              <a class=\"accordion-toggle\" data-toggle=\"collapse\" data-parent=\"#accordion\" href=\"#collapseThree\">\n                Collapsible Group Item #3\n              </a>\n            </h4>\n          </div>\n          <div id=\"collapseThree\" class=\"panel-collapse collapse\">\n            <div class=\"panel-body\">\n              Anim pariatur cliche reprehenderit, enim eiusmod high life accusamus terry richardson ad squid. 3 wolf moon officia aute, non cupidatat skateboard dolor brunch. Food truck quinoa nesciunt laborum eiusmod. Brunch 3 wolf moon tempor, sunt aliqua put a bird on it squid single-origin coffee nulla assumenda shoreditch et. Nihil anim keffiyeh helvetica, craft beer labore wes anderson cred nesciunt sapiente ea proident. Ad vegan excepteur butcher vice lomo. Leggings occaecat craft beer farm-to-table, raw denim aesthetic synth nesciunt you probably haven't heard of them accusamus labore sustainable VHS.\n            </div>\n          </div>\n        </div>\n      </div>\n    </div><!-- /example -->\n{% highlight html %}\n<div class=\"panel-group\" id=\"accordion\">\n  <div class=\"panel panel-default\">\n    <div class=\"panel-heading\">\n      <h4 class=\"panel-title\">\n        <a class=\"accordion-toggle\" data-toggle=\"collapse\" data-parent=\"#accordion\" href=\"#collapseOne\">\n          Collapsible Group Item #1\n        </a>\n      </h4>\n    </div>\n    <div id=\"collapseOne\" class=\"panel-collapse collapse in\">\n      <div class=\"panel-body\">\n        Anim pariatur cliche reprehenderit, enim eiusmod high life accusamus terry richardson ad squid. 3 wolf moon officia aute, non cupidatat skateboard dolor brunch. Food truck quinoa nesciunt laborum eiusmod. Brunch 3 wolf moon tempor, sunt aliqua put a bird on it squid single-origin coffee nulla assumenda shoreditch et. Nihil anim keffiyeh helvetica, craft beer labore wes anderson cred nesciunt sapiente ea proident. Ad vegan excepteur butcher vice lomo. Leggings occaecat craft beer farm-to-table, raw denim aesthetic synth nesciunt you probably haven't heard of them accusamus labore sustainable VHS.\n      </div>\n    </div>\n  </div>\n  <div class=\"panel panel-default\">\n    <div class=\"panel-heading\">\n      <h4 class=\"panel-title\">\n        <a class=\"accordion-toggle\" data-toggle=\"collapse\" data-parent=\"#accordion\" href=\"#collapseTwo\">\n          Collapsible Group Item #2\n        </a>\n      </h4>\n    </div>\n    <div id=\"collapseTwo\" class=\"panel-collapse collapse\">\n      <div class=\"panel-body\">\n        Anim pariatur cliche reprehenderit, enim eiusmod high life accusamus terry richardson ad squid. 3 wolf moon officia aute, non cupidatat skateboard dolor brunch. Food truck quinoa nesciunt laborum eiusmod. Brunch 3 wolf moon tempor, sunt aliqua put a bird on it squid single-origin coffee nulla assumenda shoreditch et. Nihil anim keffiyeh helvetica, craft beer labore wes anderson cred nesciunt sapiente ea proident. Ad vegan excepteur butcher vice lomo. Leggings occaecat craft beer farm-to-table, raw denim aesthetic synth nesciunt you probably haven't heard of them accusamus labore sustainable VHS.\n      </div>\n    </div>\n  </div>\n  <div class=\"panel panel-default\">\n    <div class=\"panel-heading\">\n      <h4 class=\"panel-title\">\n        <a class=\"accordion-toggle\" data-toggle=\"collapse\" data-parent=\"#accordion\" href=\"#collapseThree\">\n          Collapsible Group Item #3\n        </a>\n      </h4>\n    </div>\n    <div id=\"collapseThree\" class=\"panel-collapse collapse\">\n      <div class=\"panel-body\">\n        Anim pariatur cliche reprehenderit, enim eiusmod high life accusamus terry richardson ad squid. 3 wolf moon officia aute, non cupidatat skateboard dolor brunch. Food truck quinoa nesciunt laborum eiusmod. Brunch 3 wolf moon tempor, sunt aliqua put a bird on it squid single-origin coffee nulla assumenda shoreditch et. Nihil anim keffiyeh helvetica, craft beer labore wes anderson cred nesciunt sapiente ea proident. Ad vegan excepteur butcher vice lomo. Leggings occaecat craft beer farm-to-table, raw denim aesthetic synth nesciunt you probably haven't heard of them accusamus labore sustainable VHS.\n      </div>\n    </div>\n  </div>\n</div>\n{% endhighlight %}\n\n    <p>You can also use the plugin without the accordion markup. Make a button toggle the expanding and collapsing of another element.</p>\n{% highlight html %}\n<button type=\"button\" class=\"btn btn-danger\" data-toggle=\"collapse\" data-target=\"#demo\">\n  simple collapsible\n</button>\n\n<div id=\"demo\" class=\"collapse in\">...</div>\n{% endhighlight %}\n\n\n    <h2 id=\"collapse-usage\">Usage</h2>\n\n    <h3>Via data attributes</h3>\n    <p>Just add <code>data-toggle=\"collapse\"</code> and a <code>data-target</code> to element to automatically assign control of a collapsible element. The <code>data-target</code> attribute accepts a CSS selector to apply the collapse to. Be sure to add the class <code>collapse</code> to the collapsible element. If you'd like it to default open, add the additional class <code>in</code>.</p>\n    <p>To add accordion-like group management to a collapsible control, add the data attribute <code>data-parent=\"#selector\"</code>. Refer to the demo to see this in action.</p>\n\n    <h3>Via JavaScript</h3>\n    <p>Enable manually with:</p>\n{% highlight js %}\n$(\".collapse\").collapse()\n{% endhighlight %}\n\n    <h3>Options</h3>\n    <p>Options can be passed via data attributes or JavaScript. For data attributes, append the option name to <code>data-</code>, as in <code>data-parent=\"\"</code>.</p>\n    <div class=\"table-responsive\">\n      <table class=\"table table-bordered table-striped\">\n        <thead>\n         <tr>\n           <th style=\"width: 100px;\">Name</th>\n           <th style=\"width: 50px;\">type</th>\n           <th style=\"width: 50px;\">default</th>\n           <th>description</th>\n         </tr>\n        </thead>\n        <tbody>\n         <tr>\n           <td>parent</td>\n           <td>selector</td>\n           <td>false</td>\n           <td>If selector then all collapsible elements under the specified parent will be closed when this collapsible item is shown. (similar to traditional accordion behavior - this dependent on the <code>accordion-group</code> class)</td>\n         </tr>\n         <tr>\n           <td>toggle</td>\n           <td>boolean</td>\n           <td>true</td>\n           <td>Toggles the collapsible element on invocation</td>\n         </tr>\n        </tbody>\n      </table>\n    </div><!-- /.table-responsive -->\n\n    <h3>Methods</h3>\n\n    <h4>.collapse(options)</h4>\n    <p>Activates your content as a collapsible element. Accepts an optional options <code>object</code>.\n{% highlight js %}\n$('#myCollapsible').collapse({\n  toggle: false\n})\n{% endhighlight %}\n\n    <h4>.collapse('toggle')</h4>\n    <p>Toggles a collapsible element to shown or hidden.</p>\n\n    <h4>.collapse('show')</h4>\n    <p>Shows a collapsible element.</p>\n\n    <h4>.collapse('hide')</h4>\n    <p>Hides a collapsible element.</p>\n\n    <h3>Events</h3>\n    <p>Bootstrap's collapse class exposes a few events for hooking into collapse functionality.</p>\n    <div class=\"table-responsive\">\n      <table class=\"table table-bordered table-striped\">\n        <thead>\n         <tr>\n           <th style=\"width: 150px;\">Event Type</th>\n           <th>Description</th>\n         </tr>\n        </thead>\n        <tbody>\n         <tr>\n           <td>show.bs.collapse</td>\n           <td>This event fires immediately when the <code>show</code> instance method is called.</td>\n         </tr>\n         <tr>\n           <td>shown.bs.collapse</td>\n           <td>This event is fired when a collapse element has been made visible to the user (will wait for CSS transitions to complete).</td>\n         </tr>\n         <tr>\n           <td>hide.bs.collapse</td>\n           <td>\n            This event is fired immediately when the <code>hide</code> method has been called.\n           </td>\n         </tr>\n         <tr>\n           <td>hidden.bs.collapse</td>\n           <td>This event is fired when a collapse element has been hidden from the user (will wait for CSS transitions to complete).</td>\n         </tr>\n        </tbody>\n      </table>\n    </div><!-- /.table-responsive -->\n{% highlight js %}\n$('#myCollapsible').on('hidden.bs.collapse', function () {\n  // do something…\n})\n{% endhighlight %}\n  </div>\n\n\n\n  <!-- Carousel\n  ================================================== -->\n  <div class=\"bs-docs-section\">\n    <div class=\"page-header\">\n      <h1 id=\"carousel\">Carousel <small>carousel.js</small></h1>\n    </div>\n\n    <h2 id=\"carousel-examples\">Examples</h2>\n    <p>The slideshow below shows a generic plugin and component for cycling through elements like a carousel.</p>\n    <div class=\"bs-example\">\n      <div id=\"carousel-example-generic\" class=\"carousel slide bs-docs-carousel-example\">\n        <ol class=\"carousel-indicators\">\n          <li data-target=\"#carousel-example-generic\" data-slide-to=\"0\" class=\"active\"></li>\n          <li data-target=\"#carousel-example-generic\" data-slide-to=\"1\"></li>\n          <li data-target=\"#carousel-example-generic\" data-slide-to=\"2\"></li>\n        </ol>\n        <div class=\"carousel-inner\">\n          <div class=\"item active\">\n            <img src=\"data:image/png;base64,\" data-src=\"holder.js/900x500/auto/#777:#555/text:First slide\" alt=\"First slide\">\n          </div>\n          <div class=\"item\">\n            <img src=\"data:image/png;base64,\" data-src=\"holder.js/900x500/auto/#666:#444/text:Second slide\" alt=\"Second slide\">\n          </div>\n          <div class=\"item\">\n            <img src=\"data:image/png;base64,\" data-src=\"holder.js/900x500/auto/#555:#333/text:Third slide\" alt=\"Third slide\">\n          </div>\n        </div>\n        <a class=\"left carousel-control\" href=\"#carousel-example-generic\" data-slide=\"prev\">\n          <span class=\"icon-prev\"></span>\n        </a>\n        <a class=\"right carousel-control\" href=\"#carousel-example-generic\" data-slide=\"next\">\n          <span class=\"icon-next\"></span>\n        </a>\n      </div>\n    </div><!-- /example -->\n{% highlight html %}\n<div id=\"carousel-example-generic\" class=\"carousel slide\">\n  <!-- Indicators -->\n  <ol class=\"carousel-indicators\">\n    <li data-target=\"#carousel-example-generic\" data-slide-to=\"0\" class=\"active\"></li>\n    <li data-target=\"#carousel-example-generic\" data-slide-to=\"1\"></li>\n    <li data-target=\"#carousel-example-generic\" data-slide-to=\"2\"></li>\n  </ol>\n\n  <!-- Wrapper for slides -->\n  <div class=\"carousel-inner\">\n    <div class=\"item active\">\n      <img src=\"...\" alt=\"...\">\n      <div class=\"carousel-caption\">\n        ...\n      </div>\n    </div>\n    ...\n  </div>\n\n  <!-- Controls -->\n  <a class=\"left carousel-control\" href=\"#carousel-example-generic\" data-slide=\"prev\">\n    <span class=\"icon-prev\"></span>\n  </a>\n  <a class=\"right carousel-control\" href=\"#carousel-example-generic\" data-slide=\"next\">\n    <span class=\"icon-next\"></span>\n  </a>\n</div>\n{% endhighlight %}\n<div class=\"bs-callout bs-callout-info\">\n  <h4>Glyphicon Alternative</h4>\n  <p>With <a href=\"{{ page.base_url }}components/#glyphicons\">Glyphicons</a> available, you may choose to style the left and right toggle buttons with <code>.glyphicon .glyphicon-chevron-left</code> and <code>.glyphicon .glyphicon-chevron-right</code>.</p>\n</div>\n\n    <h3>Optional captions</h3>\n    <p>Add captions to your slides easily with the <code>.carousel-caption</code> element within any <code>.item</code>. Place just about any optional HTML within there and it will be automatically aligned and formatted.</p>\n    <div class=\"bs-example\">\n      <div id=\"carousel-example-captions\" class=\"carousel slide bs-docs-carousel-example\">\n        <ol class=\"carousel-indicators\">\n          <li data-target=\"#carousel-example-captions\" data-slide-to=\"0\" class=\"active\"></li>\n          <li data-target=\"#carousel-example-captions\" data-slide-to=\"1\"></li>\n          <li data-target=\"#carousel-example-captions\" data-slide-to=\"2\"></li>\n        </ol>\n        <div class=\"carousel-inner\">\n          <div class=\"item active\">\n            <img data-src=\"holder.js/900x500/auto/#777:#777\" src=\"data:image/png;base64,\" alt=\"First slide image\">\n            <div class=\"carousel-caption\">\n              <h3>First slide label</h3>\n              <p>Nulla vitae elit libero, a pharetra augue mollis interdum.</p>\n            </div>\n          </div>\n          <div class=\"item\">\n            <img data-src=\"holder.js/900x500/auto/#666:#666\" src=\"data:image/png;base64,\" alt=\"Second slide image\">\n            <div class=\"carousel-caption\">\n              <h3>Second slide label</h3>\n              <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>\n            </div>\n          </div>\n          <div class=\"item\">\n            <img data-src=\"holder.js/900x500/auto/#555:#5555\" src=\"data:image/png;base64,\" alt=\"Third slide image\">\n            <div class=\"carousel-caption\">\n              <h3>Third slide label</h3>\n              <p>Praesent commodo cursus magna, vel scelerisque nisl consectetur.</p>\n            </div>\n          </div>\n        </div>\n        <a class=\"left carousel-control\" href=\"#carousel-example-captions\" data-slide=\"prev\">\n          <span class=\"icon-prev\"></span>\n        </a>\n        <a class=\"right carousel-control\" href=\"#carousel-example-captions\" data-slide=\"next\">\n          <span class=\"icon-next\"></span>\n        </a>\n      </div>\n    </div><!-- /example -->\n{% highlight html %}\n<div class=\"item active\">\n  <img src=\"...\" alt=\"...\">\n  <div class=\"carousel-caption\">\n    <h3>...</h3>\n    <p>...</p>\n  </div>\n</div>\n{% endhighlight %}\n\n<div class=\"bs-callout bs-callout-danger\">\n  <h4>Accessibility issue</h4>\n  <p>The carousel component is generally not compliant with accessibility standards. If you need to be compliant, please consider other options for presenting your content.</p>\n</div>\n\n    <h2 id=\"carousel-usage\">Usage</h2>\n\n    <h3>Via data attributes</h3>\n    <p>Use data attributes to easily control the position of the carousel. <code>data-slide</code> accepts the keywords <code>prev</code> or <code>next</code>, which alters the slide position relative to its current position. Alternatively, use <code>data-slide-to</code> to pass a raw slide index to the carousel <code>data-slide-to=\"2\"</code>, which shifts the slide position to a particular index beginning with <code>0</code>.</p>\n\n    <h3>Via JavaScript</h3>\n    <p>Call carousel manually with:</p>\n{% highlight js %}\n$('.carousel').carousel()\n{% endhighlight %}\n\n    <h3>Options</h3>\n    <p>Options can be passed via data attributes or JavaScript. For data attributes, append the option name to <code>data-</code>, as in <code>data-interval=\"\"</code>.</p>\n    <div class=\"table-responsive\">\n      <table class=\"table table-bordered table-striped\">\n        <thead>\n         <tr>\n           <th style=\"width: 100px;\">Name</th>\n           <th style=\"width: 50px;\">type</th>\n           <th style=\"width: 50px;\">default</th>\n           <th>description</th>\n         </tr>\n        </thead>\n        <tbody>\n         <tr>\n           <td>interval</td>\n           <td>number</td>\n           <td>5000</td>\n           <td>The amount of time to delay between automatically cycling an item. If false, carousel will not automatically cycle.</td>\n         </tr>\n         <tr>\n           <td>pause</td>\n           <td>string</td>\n           <td>\"hover\"</td>\n           <td>Pauses the cycling of the carousel on mouseenter and resumes the cycling of the carousel on mouseleave.</td>\n         </tr>\n         <tr>\n           <td>wrap</td>\n           <td>boolean</td>\n           <td>true</td>\n           <td>Whether the carousel should cycle continuously or have hard stops.</td>\n         </tr>\n        </tbody>\n      </table>\n    </div><!-- /.table-responsive -->\n\n    <h3>Methods</h3>\n\n    <h4>.carousel(options)</h4>\n    <p>Initializes the carousel with an optional options <code>object</code> and starts cycling through items.</p>\n{% highlight js %}\n$('.carousel').carousel({\n  interval: 2000\n})\n{% endhighlight %}\n\n    <h4>.carousel('cycle')</h4>\n    <p>Cycles through the carousel items from left to right.</p>\n\n    <h4>.carousel('pause')</h4>\n    <p>Stops the carousel from cycling through items.</p>\n\n\n    <h4>.carousel(number)</h4>\n    <p>Cycles the carousel to a particular frame (0 based, similar to an array).</p>\n\n    <h4>.carousel('prev')</h4>\n    <p>Cycles to the previous item.</p>\n\n    <h4>.carousel('next')</h4>\n    <p>Cycles to the next item.</p>\n\n    <h3>Events</h3>\n    <p>Bootstrap's carousel class exposes two events for hooking into carousel functionality.</p>\n    <div class=\"table-responsive\">\n      <table class=\"table table-bordered table-striped\">\n        <thead>\n         <tr>\n           <th style=\"width: 150px;\">Event Type</th>\n           <th>Description</th>\n         </tr>\n        </thead>\n        <tbody>\n         <tr>\n           <td>slide.bs.carousel</td>\n           <td>This event fires immediately when the <code>slide</code> instance method is invoked.</td>\n         </tr>\n         <tr>\n           <td>slid.bs.carousel</td>\n           <td>This event is fired when the carousel has completed its slide transition.</td>\n         </tr>\n        </tbody>\n      </table>\n    </div><!-- /.table-responsive -->\n{% highlight js %}\n$('#myCarousel').on('slide.bs.carousel', function () {\n  // do something…\n})\n{% endhighlight %}\n  </div>\n\n\n\n  <!-- Affix\n  ================================================== -->\n  <div class=\"bs-docs-section\">\n    <div class=\"page-header\">\n      <h1 id=\"affix\">Affix <small>affix.js</small></h1>\n    </div>\n\n    <h2 id=\"affix-examples\">Example</h2>\n    <p>The subnavigation on the left is a live demo of the affix plugin.</p>\n\n    <hr class=\"bs-docs-separator\">\n\n    <h2 id=\"affix-usage\">Usage</h2>\n\n    <h3>Via data attributes</h3>\n    <p>To easily add affix behavior to any element, just add <code>data-spy=\"affix\"</code> to the element you want to spy on. Then use offsets to define when to toggle the pinning of an element on and off.</p>\n\n{% highlight html %}\n<div data-spy=\"affix\" data-offset-top=\"200\">...</div>\n{% endhighlight %}\n\n    <div class=\"bs-callout bs-callout-warning\">\n      <h4>Requires independent styling ;)</h4>\n      <p>\n        Affix toggles between three states/classes: <code>affix</code>, <code>affix-top</code>, and <code>affix-bottom</code>. You must provide the styles for these classes yourself (independent of this plugin).\n        The <code>affix-top</code> class should be in the regular flow of the document. The <code>affix</code> class should be fixed to the page. And <code>affix-bottom</code> should be positioned absolute. Note, <code>affix-bottom</code> is special in that the plugin will place the element with JS relative to the <code>offset: { bottom: number }</code> option you've provided.\n      </p>\n    </div>\n\n    <h3>Via JavaScript</h3>\n    <p>Call the affix plugin via JavaScript:</p>\n{% highlight js %}\n  $('#myAffix').affix({\n    offset: {\n      top: 100\n    , bottom: function () {\n        return (this.bottom = $('.bs-footer').outerHeight(true))\n      }\n    }\n  })\n{% endhighlight %}\n\n\n    <h3>Options</h3>\n    <p>Options can be passed via data attributes or JavaScript. For data attributes, append the option name to <code>data-</code>, as in <code>data-offset-top=\"200\"</code>.</p>\n\n    <div class=\"table-responsive\">\n      <table class=\"table table-bordered table-striped\">\n        <thead>\n         <tr>\n           <th style=\"width: 100px;\">Name</th>\n           <th style=\"width: 100px;\">type</th>\n           <th style=\"width: 50px;\">default</th>\n           <th>description</th>\n         </tr>\n        </thead>\n        <tbody>\n         <tr>\n           <td>offset</td>\n           <td>number | function | object</td>\n           <td>10</td>\n           <td>Pixels to offset from screen when calculating position of scroll. If a single number is provided, the offset will be applied in both top and bottom directions. To provide a unique, bottom and top offset just provide an object <code>offset: { top: 10 }</code> or <code>offset: { top: 10, bottom: 5 }</code>. Use a function when you need to dynamically calculate an offset.</td>\n         </tr>\n        </tbody>\n      </table>\n    </div><!-- /.table-responsive -->\n\n  </div>\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/sass-bootstrap/js/affix.js",
    "content": "/* ========================================================================\n * Bootstrap: affix.js v3.0.0\n * http://twbs.github.com/bootstrap/javascript.html#affix\n * ========================================================================\n * Copyright 2012 Twitter, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n * ======================================================================== */\n\n\n+function ($) { \"use strict\";\n\n  // AFFIX CLASS DEFINITION\n  // ======================\n\n  var Affix = function (element, options) {\n    this.options = $.extend({}, Affix.DEFAULTS, options)\n    this.$window = $(window)\n      .on('scroll.bs.affix.data-api', $.proxy(this.checkPosition, this))\n      .on('click.bs.affix.data-api',  $.proxy(this.checkPositionWithEventLoop, this))\n\n    this.$element = $(element)\n    this.affixed  =\n    this.unpin    = null\n\n    this.checkPosition()\n  }\n\n  Affix.RESET = 'affix affix-top affix-bottom'\n\n  Affix.DEFAULTS = {\n    offset: 0\n  }\n\n  Affix.prototype.checkPositionWithEventLoop = function () {\n    setTimeout($.proxy(this.checkPosition, this), 1)\n  }\n\n  Affix.prototype.checkPosition = function () {\n    if (!this.$element.is(':visible')) return\n\n    var scrollHeight = $(document).height()\n    var scrollTop    = this.$window.scrollTop()\n    var position     = this.$element.offset()\n    var offset       = this.options.offset\n    var offsetTop    = offset.top\n    var offsetBottom = offset.bottom\n\n    if (typeof offset != 'object')         offsetBottom = offsetTop = offset\n    if (typeof offsetTop == 'function')    offsetTop    = offset.top()\n    if (typeof offsetBottom == 'function') offsetBottom = offset.bottom()\n\n    var affix = this.unpin   != null && (scrollTop + this.unpin <= position.top) ? false :\n                offsetBottom != null && (position.top + this.$element.height() >= scrollHeight - offsetBottom) ? 'bottom' :\n                offsetTop    != null && (scrollTop <= offsetTop) ? 'top' : false\n\n    if (this.affixed === affix) return\n    if (this.unpin) this.$element.css('top', '')\n\n    this.affixed = affix\n    this.unpin   = affix == 'bottom' ? position.top - scrollTop : null\n\n    this.$element.removeClass(Affix.RESET).addClass('affix' + (affix ? '-' + affix : ''))\n\n    if (affix == 'bottom') {\n      this.$element.offset({ top: document.body.offsetHeight - offsetBottom - this.$element.height() })\n    }\n  }\n\n\n  // AFFIX PLUGIN DEFINITION\n  // =======================\n\n  var old = $.fn.affix\n\n  $.fn.affix = function (option) {\n    return this.each(function () {\n      var $this   = $(this)\n      var data    = $this.data('bs.affix')\n      var options = typeof option == 'object' && option\n\n      if (!data) $this.data('bs.affix', (data = new Affix(this, options)))\n      if (typeof option == 'string') data[option]()\n    })\n  }\n\n  $.fn.affix.Constructor = Affix\n\n\n  // AFFIX NO CONFLICT\n  // =================\n\n  $.fn.affix.noConflict = function () {\n    $.fn.affix = old\n    return this\n  }\n\n\n  // AFFIX DATA-API\n  // ==============\n\n  $(window).on('load', function () {\n    $('[data-spy=\"affix\"]').each(function () {\n      var $spy = $(this)\n      var data = $spy.data()\n\n      data.offset = data.offset || {}\n\n      if (data.offsetBottom) data.offset.bottom = data.offsetBottom\n      if (data.offsetTop)    data.offset.top    = data.offsetTop\n\n      $spy.affix(data)\n    })\n  })\n\n}(window.jQuery);\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/sass-bootstrap/js/alert.js",
    "content": "/* ========================================================================\n * Bootstrap: alert.js v3.0.0\n * http://twbs.github.com/bootstrap/javascript.html#alerts\n * ========================================================================\n * Copyright 2013 Twitter, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n * ======================================================================== */\n\n\n+function ($) { \"use strict\";\n\n  // ALERT CLASS DEFINITION\n  // ======================\n\n  var dismiss = '[data-dismiss=\"alert\"]'\n  var Alert   = function (el) {\n    $(el).on('click', dismiss, this.close)\n  }\n\n  Alert.prototype.close = function (e) {\n    var $this    = $(this)\n    var selector = $this.attr('data-target')\n\n    if (!selector) {\n      selector = $this.attr('href')\n      selector = selector && selector.replace(/.*(?=#[^\\s]*$)/, '') // strip for ie7\n    }\n\n    var $parent = $(selector)\n\n    if (e) e.preventDefault()\n\n    if (!$parent.length) {\n      $parent = $this.hasClass('alert') ? $this : $this.parent()\n    }\n\n    $parent.trigger(e = $.Event('close.bs.alert'))\n\n    if (e.isDefaultPrevented()) return\n\n    $parent.removeClass('in')\n\n    function removeElement() {\n      $parent.trigger('closed.bs.alert').remove()\n    }\n\n    $.support.transition && $parent.hasClass('fade') ?\n      $parent\n        .one($.support.transition.end, removeElement)\n        .emulateTransitionEnd(150) :\n      removeElement()\n  }\n\n\n  // ALERT PLUGIN DEFINITION\n  // =======================\n\n  var old = $.fn.alert\n\n  $.fn.alert = function (option) {\n    return this.each(function () {\n      var $this = $(this)\n      var data  = $this.data('bs.alert')\n\n      if (!data) $this.data('bs.alert', (data = new Alert(this)))\n      if (typeof option == 'string') data[option].call($this)\n    })\n  }\n\n  $.fn.alert.Constructor = Alert\n\n\n  // ALERT NO CONFLICT\n  // =================\n\n  $.fn.alert.noConflict = function () {\n    $.fn.alert = old\n    return this\n  }\n\n\n  // ALERT DATA-API\n  // ==============\n\n  $(document).on('click.bs.alert.data-api', dismiss, Alert.prototype.close)\n\n}(window.jQuery);\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/sass-bootstrap/js/button.js",
    "content": "/* ========================================================================\n * Bootstrap: button.js v3.0.0\n * http://twbs.github.com/bootstrap/javascript.html#buttons\n * ========================================================================\n * Copyright 2013 Twitter, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n * ======================================================================== */\n\n\n+function ($) { \"use strict\";\n\n  // BUTTON PUBLIC CLASS DEFINITION\n  // ==============================\n\n  var Button = function (element, options) {\n    this.$element = $(element)\n    this.options  = $.extend({}, Button.DEFAULTS, options)\n  }\n\n  Button.DEFAULTS = {\n    loadingText: 'loading...'\n  }\n\n  Button.prototype.setState = function (state) {\n    var d    = 'disabled'\n    var $el  = this.$element\n    var val  = $el.is('input') ? 'val' : 'html'\n    var data = $el.data()\n\n    state = state + 'Text'\n\n    if (!data.resetText) $el.data('resetText', $el[val]())\n\n    $el[val](data[state] || this.options[state])\n\n    // push to event loop to allow forms to submit\n    setTimeout(function () {\n      state == 'loadingText' ?\n        $el.addClass(d).attr(d, d) :\n        $el.removeClass(d).removeAttr(d);\n    }, 0)\n  }\n\n  Button.prototype.toggle = function () {\n    var $parent = this.$element.closest('[data-toggle=\"buttons\"]')\n\n    if ($parent.length) {\n      var $input = this.$element.find('input')\n        .prop('checked', !this.$element.hasClass('active'))\n        .trigger('change')\n      if ($input.prop('type') === 'radio') $parent.find('.active').removeClass('active')\n    }\n\n    this.$element.toggleClass('active')\n  }\n\n\n  // BUTTON PLUGIN DEFINITION\n  // ========================\n\n  var old = $.fn.button\n\n  $.fn.button = function (option) {\n    return this.each(function () {\n      var $this   = $(this)\n      var data    = $this.data('bs.button')\n      var options = typeof option == 'object' && option\n\n      if (!data) $this.data('bs.button', (data = new Button(this, options)))\n\n      if (option == 'toggle') data.toggle()\n      else if (option) data.setState(option)\n    })\n  }\n\n  $.fn.button.Constructor = Button\n\n\n  // BUTTON NO CONFLICT\n  // ==================\n\n  $.fn.button.noConflict = function () {\n    $.fn.button = old\n    return this\n  }\n\n\n  // BUTTON DATA-API\n  // ===============\n\n  $(document).on('click.bs.button.data-api', '[data-toggle^=button]', function (e) {\n    var $btn = $(e.target)\n    if (!$btn.hasClass('btn')) $btn = $btn.closest('.btn')\n    $btn.button('toggle')\n    e.preventDefault()\n  })\n\n}(window.jQuery);\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/sass-bootstrap/js/carousel.js",
    "content": "/* ========================================================================\n * Bootstrap: carousel.js v3.0.0\n * http://twbs.github.com/bootstrap/javascript.html#carousel\n * ========================================================================\n * Copyright 2012 Twitter, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n * ======================================================================== */\n\n\n+function ($) { \"use strict\";\n\n  // CAROUSEL CLASS DEFINITION\n  // =========================\n\n  var Carousel = function (element, options) {\n    this.$element    = $(element)\n    this.$indicators = this.$element.find('.carousel-indicators')\n    this.options     = options\n    this.paused      =\n    this.sliding     =\n    this.interval    =\n    this.$active     =\n    this.$items      = null\n\n    this.options.pause == 'hover' && this.$element\n      .on('mouseenter', $.proxy(this.pause, this))\n      .on('mouseleave', $.proxy(this.cycle, this))\n  }\n\n  Carousel.DEFAULTS = {\n    interval: 5000\n  , pause: 'hover'\n  , wrap: true\n  }\n\n  Carousel.prototype.cycle =  function (e) {\n    e || (this.paused = false)\n\n    this.interval && clearInterval(this.interval)\n\n    this.options.interval\n      && !this.paused\n      && (this.interval = setInterval($.proxy(this.next, this), this.options.interval))\n\n    return this\n  }\n\n  Carousel.prototype.getActiveIndex = function () {\n    this.$active = this.$element.find('.item.active')\n    this.$items  = this.$active.parent().children()\n\n    return this.$items.index(this.$active)\n  }\n\n  Carousel.prototype.to = function (pos) {\n    var that        = this\n    var activeIndex = this.getActiveIndex()\n\n    if (pos > (this.$items.length - 1) || pos < 0) return\n\n    if (this.sliding)       return this.$element.one('slid', function () { that.to(pos) })\n    if (activeIndex == pos) return this.pause().cycle()\n\n    return this.slide(pos > activeIndex ? 'next' : 'prev', $(this.$items[pos]))\n  }\n\n  Carousel.prototype.pause = function (e) {\n    e || (this.paused = true)\n\n    if (this.$element.find('.next, .prev').length && $.support.transition.end) {\n      this.$element.trigger($.support.transition.end)\n      this.cycle(true)\n    }\n\n    this.interval = clearInterval(this.interval)\n\n    return this\n  }\n\n  Carousel.prototype.next = function () {\n    if (this.sliding) return\n    return this.slide('next')\n  }\n\n  Carousel.prototype.prev = function () {\n    if (this.sliding) return\n    return this.slide('prev')\n  }\n\n  Carousel.prototype.slide = function (type, next) {\n    var $active   = this.$element.find('.item.active')\n    var $next     = next || $active[type]()\n    var isCycling = this.interval\n    var direction = type == 'next' ? 'left' : 'right'\n    var fallback  = type == 'next' ? 'first' : 'last'\n    var that      = this\n\n    if (!$next.length) {\n      if (!this.options.wrap) return\n      $next = this.$element.find('.item')[fallback]()\n    }\n\n    this.sliding = true\n\n    isCycling && this.pause()\n\n    var e = $.Event('slide.bs.carousel', { relatedTarget: $next[0], direction: direction })\n\n    if ($next.hasClass('active')) return\n\n    if (this.$indicators.length) {\n      this.$indicators.find('.active').removeClass('active')\n      this.$element.one('slid', function () {\n        var $nextIndicator = $(that.$indicators.children()[that.getActiveIndex()])\n        $nextIndicator && $nextIndicator.addClass('active')\n      })\n    }\n\n    if ($.support.transition && this.$element.hasClass('slide')) {\n      this.$element.trigger(e)\n      if (e.isDefaultPrevented()) return\n      $next.addClass(type)\n      $next[0].offsetWidth // force reflow\n      $active.addClass(direction)\n      $next.addClass(direction)\n      $active\n        .one($.support.transition.end, function () {\n          $next.removeClass([type, direction].join(' ')).addClass('active')\n          $active.removeClass(['active', direction].join(' '))\n          that.sliding = false\n          setTimeout(function () { that.$element.trigger('slid') }, 0)\n        })\n        .emulateTransitionEnd(600)\n    } else {\n      this.$element.trigger(e)\n      if (e.isDefaultPrevented()) return\n      $active.removeClass('active')\n      $next.addClass('active')\n      this.sliding = false\n      this.$element.trigger('slid')\n    }\n\n    isCycling && this.cycle()\n\n    return this\n  }\n\n\n  // CAROUSEL PLUGIN DEFINITION\n  // ==========================\n\n  var old = $.fn.carousel\n\n  $.fn.carousel = function (option) {\n    return this.each(function () {\n      var $this   = $(this)\n      var data    = $this.data('bs.carousel')\n      var options = $.extend({}, Carousel.DEFAULTS, $this.data(), typeof option == 'object' && option)\n      var action  = typeof option == 'string' ? option : options.slide\n\n      if (!data) $this.data('bs.carousel', (data = new Carousel(this, options)))\n      if (typeof option == 'number') data.to(option)\n      else if (action) data[action]()\n      else if (options.interval) data.pause().cycle()\n    })\n  }\n\n  $.fn.carousel.Constructor = Carousel\n\n\n  // CAROUSEL NO CONFLICT\n  // ====================\n\n  $.fn.carousel.noConflict = function () {\n    $.fn.carousel = old\n    return this\n  }\n\n\n  // CAROUSEL DATA-API\n  // =================\n\n  $(document).on('click.bs.carousel.data-api', '[data-slide], [data-slide-to]', function (e) {\n    var $this   = $(this), href\n    var $target = $($this.attr('data-target') || (href = $this.attr('href')) && href.replace(/.*(?=#[^\\s]+$)/, '')) //strip for ie7\n    var options = $.extend({}, $target.data(), $this.data())\n    var slideIndex = $this.attr('data-slide-to')\n    if (slideIndex) options.interval = false\n\n    $target.carousel(options)\n\n    if (slideIndex = $this.attr('data-slide-to')) {\n      $target.data('bs.carousel').to(slideIndex)\n    }\n\n    e.preventDefault()\n  })\n\n  $(window).on('load', function () {\n    $('[data-ride=\"carousel\"]').each(function () {\n      var $carousel = $(this)\n      $carousel.carousel($carousel.data())\n    })\n  })\n\n}(window.jQuery);\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/sass-bootstrap/js/collapse.js",
    "content": "/* ========================================================================\n * Bootstrap: collapse.js v3.0.0\n * http://twbs.github.com/bootstrap/javascript.html#collapse\n * ========================================================================\n * Copyright 2012 Twitter, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n * ======================================================================== */\n\n\n+function ($) { \"use strict\";\n\n  // COLLAPSE PUBLIC CLASS DEFINITION\n  // ================================\n\n  var Collapse = function (element, options) {\n    this.$element      = $(element)\n    this.options       = $.extend({}, Collapse.DEFAULTS, options)\n    this.transitioning = null\n\n    if (this.options.parent) this.$parent = $(this.options.parent)\n    if (this.options.toggle) this.toggle()\n  }\n\n  Collapse.DEFAULTS = {\n    toggle: true\n  }\n\n  Collapse.prototype.dimension = function () {\n    var hasWidth = this.$element.hasClass('width')\n    return hasWidth ? 'width' : 'height'\n  }\n\n  Collapse.prototype.show = function () {\n    if (this.transitioning || this.$element.hasClass('in')) return\n\n    var startEvent = $.Event('show.bs.collapse')\n    this.$element.trigger(startEvent)\n    if (startEvent.isDefaultPrevented()) return\n\n    var actives = this.$parent && this.$parent.find('> .panel > .in')\n\n    if (actives && actives.length) {\n      var hasData = actives.data('bs.collapse')\n      if (hasData && hasData.transitioning) return\n      actives.collapse('hide')\n      hasData || actives.data('bs.collapse', null)\n    }\n\n    var dimension = this.dimension()\n\n    this.$element\n      .removeClass('collapse')\n      .addClass('collapsing')\n      [dimension](0)\n\n    this.transitioning = 1\n\n    var complete = function () {\n      this.$element\n        .removeClass('collapsing')\n        .addClass('in')\n        [dimension]('auto')\n      this.transitioning = 0\n      this.$element.trigger('shown.bs.collapse')\n    }\n\n    if (!$.support.transition) return complete.call(this)\n\n    var scrollSize = $.camelCase(['scroll', dimension].join('-'))\n\n    this.$element\n      .one($.support.transition.end, $.proxy(complete, this))\n      .emulateTransitionEnd(350)\n      [dimension](this.$element[0][scrollSize])\n  }\n\n  Collapse.prototype.hide = function () {\n    if (this.transitioning || !this.$element.hasClass('in')) return\n\n    var startEvent = $.Event('hide.bs.collapse')\n    this.$element.trigger(startEvent)\n    if (startEvent.isDefaultPrevented()) return\n\n    var dimension = this.dimension()\n\n    this.$element\n      [dimension](this.$element[dimension]())\n      [0].offsetHeight\n\n    this.$element\n      .addClass('collapsing')\n      .removeClass('collapse')\n      .removeClass('in')\n\n    this.transitioning = 1\n\n    var complete = function () {\n      this.transitioning = 0\n      this.$element\n        .trigger('hidden.bs.collapse')\n        .removeClass('collapsing')\n        .addClass('collapse')\n    }\n\n    if (!$.support.transition) return complete.call(this)\n\n    this.$element\n      [dimension](0)\n      .one($.support.transition.end, $.proxy(complete, this))\n      .emulateTransitionEnd(350)\n  }\n\n  Collapse.prototype.toggle = function () {\n    this[this.$element.hasClass('in') ? 'hide' : 'show']()\n  }\n\n\n  // COLLAPSE PLUGIN DEFINITION\n  // ==========================\n\n  var old = $.fn.collapse\n\n  $.fn.collapse = function (option) {\n    return this.each(function () {\n      var $this   = $(this)\n      var data    = $this.data('bs.collapse')\n      var options = $.extend({}, Collapse.DEFAULTS, $this.data(), typeof option == 'object' && option)\n\n      if (!data) $this.data('bs.collapse', (data = new Collapse(this, options)))\n      if (typeof option == 'string') data[option]()\n    })\n  }\n\n  $.fn.collapse.Constructor = Collapse\n\n\n  // COLLAPSE NO CONFLICT\n  // ====================\n\n  $.fn.collapse.noConflict = function () {\n    $.fn.collapse = old\n    return this\n  }\n\n\n  // COLLAPSE DATA-API\n  // =================\n\n  $(document).on('click.bs.collapse.data-api', '[data-toggle=collapse]', function (e) {\n    var $this   = $(this), href\n    var target  = $this.attr('data-target')\n        || e.preventDefault()\n        || (href = $this.attr('href')) && href.replace(/.*(?=#[^\\s]+$)/, '') //strip for ie7\n    var $target = $(target)\n    var data    = $target.data('bs.collapse')\n    var option  = data ? 'toggle' : $this.data()\n    var parent  = $this.attr('data-parent')\n    var $parent = parent && $(parent)\n\n    if (!data || !data.transitioning) {\n      if ($parent) $parent.find('[data-toggle=collapse][data-parent=\"' + parent + '\"]').not($this).addClass('collapsed')\n      $this[$target.hasClass('in') ? 'addClass' : 'removeClass']('collapsed')\n    }\n\n    $target.collapse(option)\n  })\n\n}(window.jQuery);\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/sass-bootstrap/js/dropdown.js",
    "content": "/* ========================================================================\n * Bootstrap: dropdown.js v3.0.0\n * http://twbs.github.com/bootstrap/javascript.html#dropdowns\n * ========================================================================\n * Copyright 2012 Twitter, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n * ======================================================================== */\n\n\n+function ($) { \"use strict\";\n\n  // DROPDOWN CLASS DEFINITION\n  // =========================\n\n  var backdrop = '.dropdown-backdrop'\n  var toggle   = '[data-toggle=dropdown]'\n  var Dropdown = function (element) {\n    var $el = $(element).on('click.bs.dropdown', this.toggle)\n  }\n\n  Dropdown.prototype.toggle = function (e) {\n    var $this = $(this)\n\n    if ($this.is('.disabled, :disabled')) return\n\n    var $parent  = getParent($this)\n    var isActive = $parent.hasClass('open')\n\n    clearMenus()\n\n    if (!isActive) {\n      if ('ontouchstart' in document.documentElement && !$parent.closest('.navbar-nav').length) {\n        // if mobile we we use a backdrop because click events don't delegate\n        $('<div class=\"dropdown-backdrop\"/>').insertAfter($(this)).on('click', clearMenus)\n      }\n\n      $parent.trigger(e = $.Event('show.bs.dropdown'))\n\n      if (e.isDefaultPrevented()) return\n\n      $parent\n        .toggleClass('open')\n        .trigger('shown.bs.dropdown')\n\n      $this.focus()\n    }\n\n    return false\n  }\n\n  Dropdown.prototype.keydown = function (e) {\n    if (!/(38|40|27)/.test(e.keyCode)) return\n\n    var $this = $(this)\n\n    e.preventDefault()\n    e.stopPropagation()\n\n    if ($this.is('.disabled, :disabled')) return\n\n    var $parent  = getParent($this)\n    var isActive = $parent.hasClass('open')\n\n    if (!isActive || (isActive && e.keyCode == 27)) {\n      if (e.which == 27) $parent.find(toggle).focus()\n      return $this.click()\n    }\n\n    var $items = $('[role=menu] li:not(.divider):visible a', $parent)\n\n    if (!$items.length) return\n\n    var index = $items.index($items.filter(':focus'))\n\n    if (e.keyCode == 38 && index > 0)                 index--                        // up\n    if (e.keyCode == 40 && index < $items.length - 1) index++                        // down\n    if (!~index)                                      index=0\n\n    $items.eq(index).focus()\n  }\n\n  function clearMenus() {\n    $(backdrop).remove()\n    $(toggle).each(function (e) {\n      var $parent = getParent($(this))\n      if (!$parent.hasClass('open')) return\n      $parent.trigger(e = $.Event('hide.bs.dropdown'))\n      if (e.isDefaultPrevented()) return\n      $parent.removeClass('open').trigger('hidden.bs.dropdown')\n    })\n  }\n\n  function getParent($this) {\n    var selector = $this.attr('data-target')\n\n    if (!selector) {\n      selector = $this.attr('href')\n      selector = selector && /#/.test(selector) && selector.replace(/.*(?=#[^\\s]*$)/, '') //strip for ie7\n    }\n\n    var $parent = selector && $(selector)\n\n    return $parent && $parent.length ? $parent : $this.parent()\n  }\n\n\n  // DROPDOWN PLUGIN DEFINITION\n  // ==========================\n\n  var old = $.fn.dropdown\n\n  $.fn.dropdown = function (option) {\n    return this.each(function () {\n      var $this = $(this)\n      var data  = $this.data('dropdown')\n\n      if (!data) $this.data('dropdown', (data = new Dropdown(this)))\n      if (typeof option == 'string') data[option].call($this)\n    })\n  }\n\n  $.fn.dropdown.Constructor = Dropdown\n\n\n  // DROPDOWN NO CONFLICT\n  // ====================\n\n  $.fn.dropdown.noConflict = function () {\n    $.fn.dropdown = old\n    return this\n  }\n\n\n  // APPLY TO STANDARD DROPDOWN ELEMENTS\n  // ===================================\n\n  $(document)\n    .on('click.bs.dropdown.data-api', clearMenus)\n    .on('click.bs.dropdown.data-api', '.dropdown form', function (e) { e.stopPropagation() })\n    .on('click.bs.dropdown.data-api'  , toggle, Dropdown.prototype.toggle)\n    .on('keydown.bs.dropdown.data-api', toggle + ', [role=menu]' , Dropdown.prototype.keydown)\n\n}(window.jQuery);\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/sass-bootstrap/js/modal.js",
    "content": "/* ========================================================================\n * Bootstrap: modal.js v3.0.0\n * http://twbs.github.com/bootstrap/javascript.html#modals\n * ========================================================================\n * Copyright 2012 Twitter, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n * ======================================================================== */\n\n\n+function ($) { \"use strict\";\n\n  // MODAL CLASS DEFINITION\n  // ======================\n\n  var Modal = function (element, options) {\n    this.options   = options\n    this.$element  = $(element)\n    this.$backdrop =\n    this.isShown   = null\n\n    if (this.options.remote) this.$element.load(this.options.remote)\n  }\n\n  Modal.DEFAULTS = {\n      backdrop: true\n    , keyboard: true\n    , show: true\n  }\n\n  Modal.prototype.toggle = function (_relatedTarget) {\n    return this[!this.isShown ? 'show' : 'hide'](_relatedTarget)\n  }\n\n  Modal.prototype.show = function (_relatedTarget) {\n    var that = this\n    var e    = $.Event('show.bs.modal', { relatedTarget: _relatedTarget })\n\n    this.$element.trigger(e)\n\n    if (this.isShown || e.isDefaultPrevented()) return\n\n    this.isShown = true\n\n    this.escape()\n\n    this.$element.on('click.dismiss.modal', '[data-dismiss=\"modal\"]', $.proxy(this.hide, this))\n\n    this.backdrop(function () {\n      var transition = $.support.transition && that.$element.hasClass('fade')\n\n      if (!that.$element.parent().length) {\n        that.$element.appendTo(document.body) // don't move modals dom position\n      }\n\n      that.$element.show()\n\n      if (transition) {\n        that.$element[0].offsetWidth // force reflow\n      }\n\n      that.$element\n        .addClass('in')\n        .attr('aria-hidden', false)\n\n      that.enforceFocus()\n\n      var e = $.Event('shown.bs.modal', { relatedTarget: _relatedTarget })\n\n      transition ?\n        that.$element.find('.modal-dialog') // wait for modal to slide in\n          .one($.support.transition.end, function () {\n            that.$element.focus().trigger(e)\n          })\n          .emulateTransitionEnd(300) :\n        that.$element.focus().trigger(e)\n    })\n  }\n\n  Modal.prototype.hide = function (e) {\n    if (e) e.preventDefault()\n\n    e = $.Event('hide.bs.modal')\n\n    this.$element.trigger(e)\n\n    if (!this.isShown || e.isDefaultPrevented()) return\n\n    this.isShown = false\n\n    this.escape()\n\n    $(document).off('focusin.bs.modal')\n\n    this.$element\n      .removeClass('in')\n      .attr('aria-hidden', true)\n      .off('click.dismiss.modal')\n\n    $.support.transition && this.$element.hasClass('fade') ?\n      this.$element\n        .one($.support.transition.end, $.proxy(this.hideModal, this))\n        .emulateTransitionEnd(300) :\n      this.hideModal()\n  }\n\n  Modal.prototype.enforceFocus = function () {\n    $(document)\n      .off('focusin.bs.modal') // guard against infinite focus loop\n      .on('focusin.bs.modal', $.proxy(function (e) {\n        if (this.$element[0] !== e.target && !this.$element.has(e.target).length) {\n          this.$element.focus()\n        }\n      }, this))\n  }\n\n  Modal.prototype.escape = function () {\n    if (this.isShown && this.options.keyboard) {\n      this.$element.on('keyup.dismiss.bs.modal', $.proxy(function (e) {\n        e.which == 27 && this.hide()\n      }, this))\n    } else if (!this.isShown) {\n      this.$element.off('keyup.dismiss.bs.modal')\n    }\n  }\n\n  Modal.prototype.hideModal = function () {\n    var that = this\n    this.$element.hide()\n    this.backdrop(function () {\n      that.removeBackdrop()\n      that.$element.trigger('hidden.bs.modal')\n    })\n  }\n\n  Modal.prototype.removeBackdrop = function () {\n    this.$backdrop && this.$backdrop.remove()\n    this.$backdrop = null\n  }\n\n  Modal.prototype.backdrop = function (callback) {\n    var that    = this\n    var animate = this.$element.hasClass('fade') ? 'fade' : ''\n\n    if (this.isShown && this.options.backdrop) {\n      var doAnimate = $.support.transition && animate\n\n      this.$backdrop = $('<div class=\"modal-backdrop ' + animate + '\" />')\n        .appendTo(document.body)\n\n      this.$element.on('click.dismiss.modal', $.proxy(function (e) {\n        if (e.target !== e.currentTarget) return\n        this.options.backdrop == 'static'\n          ? this.$element[0].focus.call(this.$element[0])\n          : this.hide.call(this)\n      }, this))\n\n      if (doAnimate) this.$backdrop[0].offsetWidth // force reflow\n\n      this.$backdrop.addClass('in')\n\n      if (!callback) return\n\n      doAnimate ?\n        this.$backdrop\n          .one($.support.transition.end, callback)\n          .emulateTransitionEnd(150) :\n        callback()\n\n    } else if (!this.isShown && this.$backdrop) {\n      this.$backdrop.removeClass('in')\n\n      $.support.transition && this.$element.hasClass('fade')?\n        this.$backdrop\n          .one($.support.transition.end, callback)\n          .emulateTransitionEnd(150) :\n        callback()\n\n    } else if (callback) {\n      callback()\n    }\n  }\n\n\n  // MODAL PLUGIN DEFINITION\n  // =======================\n\n  var old = $.fn.modal\n\n  $.fn.modal = function (option, _relatedTarget) {\n    return this.each(function () {\n      var $this   = $(this)\n      var data    = $this.data('bs.modal')\n      var options = $.extend({}, Modal.DEFAULTS, $this.data(), typeof option == 'object' && option)\n\n      if (!data) $this.data('bs.modal', (data = new Modal(this, options)))\n      if (typeof option == 'string') data[option](_relatedTarget)\n      else if (options.show) data.show(_relatedTarget)\n    })\n  }\n\n  $.fn.modal.Constructor = Modal\n\n\n  // MODAL NO CONFLICT\n  // =================\n\n  $.fn.modal.noConflict = function () {\n    $.fn.modal = old\n    return this\n  }\n\n\n  // MODAL DATA-API\n  // ==============\n\n  $(document).on('click.bs.modal.data-api', '[data-toggle=\"modal\"]', function (e) {\n    var $this   = $(this)\n    var href    = $this.attr('href')\n    var $target = $($this.attr('data-target') || (href && href.replace(/.*(?=#[^\\s]+$)/, ''))) //strip for ie7\n    var option  = $target.data('modal') ? 'toggle' : $.extend({ remote: !/#/.test(href) && href }, $target.data(), $this.data())\n\n    e.preventDefault()\n\n    $target\n      .modal(option, this)\n      .one('hide', function () {\n        $this.is(':visible') && $this.focus()\n      })\n  })\n\n  $(document)\n    .on('show.bs.modal',  '.modal', function () { $(document.body).addClass('modal-open') })\n    .on('hidden.bs.modal', '.modal', function () { $(document.body).removeClass('modal-open') })\n\n}(window.jQuery);\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/sass-bootstrap/js/popover.js",
    "content": "/* ========================================================================\n * Bootstrap: popover.js v3.0.0\n * http://twbs.github.com/bootstrap/javascript.html#popovers\n * ========================================================================\n * Copyright 2012 Twitter, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n * ======================================================================== */\n\n\n+function ($) { \"use strict\";\n\n  // POPOVER PUBLIC CLASS DEFINITION\n  // ===============================\n\n  var Popover = function (element, options) {\n    this.init('popover', element, options)\n  }\n\n  if (!$.fn.tooltip) throw new Error('Popover requires tooltip.js')\n\n  Popover.DEFAULTS = $.extend({} , $.fn.tooltip.Constructor.DEFAULTS, {\n    placement: 'right'\n  , trigger: 'click'\n  , content: ''\n  , template: '<div class=\"popover\"><div class=\"arrow\"></div><h3 class=\"popover-title\"></h3><div class=\"popover-content\"></div></div>'\n  })\n\n\n  // NOTE: POPOVER EXTENDS tooltip.js\n  // ================================\n\n  Popover.prototype = $.extend({}, $.fn.tooltip.Constructor.prototype)\n\n  Popover.prototype.constructor = Popover\n\n  Popover.prototype.getDefaults = function () {\n    return Popover.DEFAULTS\n  }\n\n  Popover.prototype.setContent = function () {\n    var $tip    = this.tip()\n    var title   = this.getTitle()\n    var content = this.getContent()\n\n    $tip.find('.popover-title')[this.options.html ? 'html' : 'text'](title)\n    $tip.find('.popover-content')[this.options.html ? 'html' : 'text'](content)\n\n    $tip.removeClass('fade top bottom left right in')\n\n    // IE8 doesn't accept hiding via the `:empty` pseudo selector, we have to do\n    // this manually by checking the contents.\n    if (!$tip.find('.popover-title').html()) $tip.find('.popover-title').hide()\n  }\n\n  Popover.prototype.hasContent = function () {\n    return this.getTitle() || this.getContent()\n  }\n\n  Popover.prototype.getContent = function () {\n    var $e = this.$element\n    var o  = this.options\n\n    return $e.attr('data-content')\n      || (typeof o.content == 'function' ?\n            o.content.call($e[0]) :\n            o.content)\n  }\n\n  Popover.prototype.arrow = function () {\n    return this.$arrow = this.$arrow || this.tip().find('.arrow')\n  }\n\n  Popover.prototype.tip = function () {\n    if (!this.$tip) this.$tip = $(this.options.template)\n    return this.$tip\n  }\n\n\n  // POPOVER PLUGIN DEFINITION\n  // =========================\n\n  var old = $.fn.popover\n\n  $.fn.popover = function (option) {\n    return this.each(function () {\n      var $this   = $(this)\n      var data    = $this.data('bs.popover')\n      var options = typeof option == 'object' && option\n\n      if (!data) $this.data('bs.popover', (data = new Popover(this, options)))\n      if (typeof option == 'string') data[option]()\n    })\n  }\n\n  $.fn.popover.Constructor = Popover\n\n\n  // POPOVER NO CONFLICT\n  // ===================\n\n  $.fn.popover.noConflict = function () {\n    $.fn.popover = old\n    return this\n  }\n\n}(window.jQuery);\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/sass-bootstrap/js/scrollspy.js",
    "content": "/* ========================================================================\n * Bootstrap: scrollspy.js v3.0.0\n * http://twbs.github.com/bootstrap/javascript.html#scrollspy\n * ========================================================================\n * Copyright 2012 Twitter, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n * ======================================================================== */\n\n\n+function ($) { \"use strict\";\n\n  // SCROLLSPY CLASS DEFINITION\n  // ==========================\n\n  function ScrollSpy(element, options) {\n    var href\n    var process  = $.proxy(this.process, this)\n\n    this.$element       = $(element).is('body') ? $(window) : $(element)\n    this.$body          = $('body')\n    this.$scrollElement = this.$element.on('scroll.bs.scroll-spy.data-api', process)\n    this.options        = $.extend({}, ScrollSpy.DEFAULTS, options)\n    this.selector       = (this.options.target\n      || ((href = $(element).attr('href')) && href.replace(/.*(?=#[^\\s]+$)/, '')) //strip for ie7\n      || '') + ' .nav li > a'\n    this.offsets        = $([])\n    this.targets        = $([])\n    this.activeTarget   = null\n\n    this.refresh()\n    this.process()\n  }\n\n  ScrollSpy.DEFAULTS = {\n    offset: 10\n  }\n\n  ScrollSpy.prototype.refresh = function () {\n    var offsetMethod = this.$element[0] == window ? 'offset' : 'position'\n\n    this.offsets = $([])\n    this.targets = $([])\n\n    var self     = this\n    var $targets = this.$body\n      .find(this.selector)\n      .map(function () {\n        var $el   = $(this)\n        var href  = $el.data('target') || $el.attr('href')\n        var $href = /^#\\w/.test(href) && $(href)\n\n        return ($href\n          && $href.length\n          && [[ $href[offsetMethod]().top + (!$.isWindow(self.$scrollElement.get(0)) && self.$scrollElement.scrollTop()), href ]]) || null\n      })\n      .sort(function (a, b) { return a[0] - b[0] })\n      .each(function () {\n        self.offsets.push(this[0])\n        self.targets.push(this[1])\n      })\n  }\n\n  ScrollSpy.prototype.process = function () {\n    var scrollTop    = this.$scrollElement.scrollTop() + this.options.offset\n    var scrollHeight = this.$scrollElement[0].scrollHeight || this.$body[0].scrollHeight\n    var maxScroll    = scrollHeight - this.$scrollElement.height()\n    var offsets      = this.offsets\n    var targets      = this.targets\n    var activeTarget = this.activeTarget\n    var i\n\n    if (scrollTop >= maxScroll) {\n      return activeTarget != (i = targets.last()[0]) && this.activate(i)\n    }\n\n    for (i = offsets.length; i--;) {\n      activeTarget != targets[i]\n        && scrollTop >= offsets[i]\n        && (!offsets[i + 1] || scrollTop <= offsets[i + 1])\n        && this.activate( targets[i] )\n    }\n  }\n\n  ScrollSpy.prototype.activate = function (target) {\n    this.activeTarget = target\n\n    $(this.selector)\n      .parents('.active')\n      .removeClass('active')\n\n    var selector = this.selector\n      + '[data-target=\"' + target + '\"],'\n      + this.selector + '[href=\"' + target + '\"]'\n\n    var active = $(selector)\n      .parents('li')\n      .addClass('active')\n\n    if (active.parent('.dropdown-menu').length)  {\n      active = active\n        .closest('li.dropdown')\n        .addClass('active')\n    }\n\n    active.trigger('activate')\n  }\n\n\n  // SCROLLSPY PLUGIN DEFINITION\n  // ===========================\n\n  var old = $.fn.scrollspy\n\n  $.fn.scrollspy = function (option) {\n    return this.each(function () {\n      var $this   = $(this)\n      var data    = $this.data('bs.scrollspy')\n      var options = typeof option == 'object' && option\n\n      if (!data) $this.data('bs.scrollspy', (data = new ScrollSpy(this, options)))\n      if (typeof option == 'string') data[option]()\n    })\n  }\n\n  $.fn.scrollspy.Constructor = ScrollSpy\n\n\n  // SCROLLSPY NO CONFLICT\n  // =====================\n\n  $.fn.scrollspy.noConflict = function () {\n    $.fn.scrollspy = old\n    return this\n  }\n\n\n  // SCROLLSPY DATA-API\n  // ==================\n\n  $(window).on('load', function () {\n    $('[data-spy=\"scroll\"]').each(function () {\n      var $spy = $(this)\n      $spy.scrollspy($spy.data())\n    })\n  })\n\n}(window.jQuery);\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/sass-bootstrap/js/tab.js",
    "content": "/* ========================================================================\n * Bootstrap: tab.js v3.0.0\n * http://twbs.github.com/bootstrap/javascript.html#tabs\n * ========================================================================\n * Copyright 2012 Twitter, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n * ======================================================================== */\n\n\n+function ($) { \"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.attr('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}(window.jQuery);\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/sass-bootstrap/js/tests/index.html",
    "content": "<!DOCTYPE HTML>\n<html>\n<head>\n  <title>Bootstrap Plugin Test Suite</title>\n\n  <!-- jquery -->\n  <!--<script src=\"http://code.jquery.com/jquery-1.7.min.js\"></script>-->\n  <script src=\"vendor/jquery.js\"></script>\n\n  <!-- qunit -->\n  <link rel=\"stylesheet\" href=\"vendor/qunit.css\" type=\"text/css\" media=\"screen\" />\n  <script src=\"vendor/qunit.js\"></script>\n\n  <!--  plugin sources -->\n  <script src=\"../../js/transition.js\"></script>\n  <script src=\"../../js/alert.js\"></script>\n  <script src=\"../../js/button.js\"></script>\n  <script src=\"../../js/carousel.js\"></script>\n  <script src=\"../../js/collapse.js\"></script>\n  <script src=\"../../js/dropdown.js\"></script>\n  <script src=\"../../js/modal.js\"></script>\n  <script src=\"../../js/scrollspy.js\"></script>\n  <script src=\"../../js/tab.js\"></script>\n  <script src=\"../../js/tooltip.js\"></script>\n  <script src=\"../../js/popover.js\"></script>\n  <script src=\"../../js/affix.js\"></script>\n\n  <!-- unit tests -->\n  <script src=\"unit/transition.js\"></script>\n  <script src=\"unit/alert.js\"></script>\n  <script src=\"unit/button.js\"></script>\n  <script src=\"unit/carousel.js\"></script>\n  <script src=\"unit/collapse.js\"></script>\n  <script src=\"unit/dropdown.js\"></script>\n  <script src=\"unit/modal.js\"></script>\n  <script src=\"unit/scrollspy.js\"></script>\n  <script src=\"unit/tab.js\"></script>\n  <script src=\"unit/tooltip.js\"></script>\n  <script src=\"unit/popover.js\"></script>\n  <script src=\"unit/affix.js\"></script>\n\n</head>\n<body>\n  <div>\n    <h1 id=\"qunit-header\">Bootstrap Plugin Test Suite</h1>\n    <h2 id=\"qunit-banner\"></h2>\n    <h2 id=\"qunit-userAgent\"></h2>\n    <ol id=\"qunit-tests\"></ol>\n    <div id=\"qunit-fixture\"></div>\n  </div>\n</body>\n</html>\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/sass-bootstrap/js/tests/phantom.js",
    "content": "// Simple phantom.js integration script\n// Adapted from Modernizr\n\nfunction waitFor(testFx, onReady, timeOutMillis) {\n  var maxtimeOutMillis = timeOutMillis ? timeOutMillis :  5001 //< Default Max Timout is 5s\n    , start = new Date().getTime()\n    , condition = false\n    , interval = setInterval(function () {\n        if ((new Date().getTime() - start < maxtimeOutMillis) && !condition) {\n          // If not time-out yet and condition not yet fulfilled\n          condition = (typeof(testFx) === \"string\" ? eval(testFx) : testFx()) //< defensive code\n        } else {\n          if (!condition) {\n            // If condition still not fulfilled (timeout but condition is 'false')\n            console.log(\"'waitFor()' timeout\")\n            phantom.exit(1)\n          } else {\n            // Condition fulfilled (timeout and/or condition is 'true')\n            typeof(onReady) === \"string\" ? eval(onReady) : onReady() //< Do what it's supposed to do once the condition is fulfilled\n            clearInterval(interval) //< Stop this interval\n          }\n        }\n    }, 100) //< repeat check every 100ms\n}\n\n\nif (phantom.args.length === 0 || phantom.args.length > 2) {\n  console.log('Usage: phantom.js URL')\n  phantom.exit()\n}\n\nvar page = new WebPage()\n\n// Route \"console.log()\" calls from within the Page context to the main Phantom context (i.e. current \"this\")\npage.onConsoleMessage = function(msg) {\n  console.log(msg)\n};\n\npage.open(phantom.args[0], function(status){\n  if (status !== \"success\") {\n    console.log(\"Unable to access network\")\n    phantom.exit()\n  } else {\n    waitFor(function(){\n      return page.evaluate(function(){\n        var el = document.getElementById('qunit-testresult')\n        if (el && el.innerText.match('completed')) {\n          return true\n        }\n        return false\n      })\n    }, function(){\n      var failedNum = page.evaluate(function(){\n        var el = document.getElementById('qunit-testresult')\n        try {\n          return el.getElementsByClassName('failed')[0].innerHTML\n        } catch (e) { }\n        return 10000\n      });\n      phantom.exit((parseInt(failedNum, 10) > 0) ? 1 : 0)\n    })\n  }\n})\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/sass-bootstrap/js/tests/server.js",
    "content": "/*\n * Simple connect server for phantom.js\n * Adapted from Modernizr\n */\n\nvar connect = require('connect')\n  , http = require('http')\n  , fs   = require('fs')\n  , app = connect()\n      .use(connect.static(__dirname + '/../../'));\n\nhttp.createServer(app).listen(3000);\n\nfs.writeFileSync(__dirname + '/pid.txt', process.pid, 'utf-8')\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/sass-bootstrap/js/tests/unit/affix.js",
    "content": "$(function () {\n\n    module(\"affix\")\n\n      test(\"should provide no conflict\", function () {\n        var affix = $.fn.affix.noConflict()\n        ok(!$.fn.affix, 'affix was set back to undefined (org value)')\n        $.fn.affix = affix\n      })\n\n      test(\"should be defined on jquery object\", function () {\n        ok($(document.body).affix, 'affix method is defined')\n      })\n\n      test(\"should return element\", function () {\n        ok($(document.body).affix()[0] == document.body, 'document.body returned')\n      })\n\n      test(\"should exit early if element is not visible\", function () {\n        var $affix = $('<div style=\"display: none\"></div>').affix()\n        $affix.data('bs.affix').checkPosition()\n        ok(!$affix.hasClass('affix'), 'affix class was not added')\n      })\n\n})\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/sass-bootstrap/js/tests/unit/alert.js",
    "content": "$(function () {\n\n    module(\"alert\")\n\n      test(\"should provide no conflict\", function () {\n        var alert = $.fn.alert.noConflict()\n        ok(!$.fn.alert, 'alert was set back to undefined (org value)')\n        $.fn.alert = alert\n      })\n\n      test(\"should be defined on jquery object\", function () {\n        ok($(document.body).alert, 'alert method is defined')\n      })\n\n      test(\"should return element\", function () {\n        ok($(document.body).alert()[0] == document.body, 'document.body returned')\n      })\n\n      test(\"should fade element out on clicking .close\", function () {\n        var alertHTML = '<div class=\"alert-message warning fade in\">'\n          + '<a class=\"close\" href=\"#\" data-dismiss=\"alert\">×</a>'\n          + '<p><strong>Holy guacamole!</strong> Best check yo self, you\\'re not looking too good.</p>'\n          + '</div>'\n          , alert = $(alertHTML).alert()\n\n        alert.find('.close').click()\n\n        ok(!alert.hasClass('in'), 'remove .in class on .close click')\n      })\n\n      test(\"should remove element when clicking .close\", function () {\n        $.support.transition = false\n\n        var alertHTML = '<div class=\"alert-message warning fade in\">'\n          + '<a class=\"close\" href=\"#\" data-dismiss=\"alert\">×</a>'\n          + '<p><strong>Holy guacamole!</strong> Best check yo self, you\\'re not looking too good.</p>'\n          + '</div>'\n          , alert = $(alertHTML).appendTo('#qunit-fixture').alert()\n\n        ok($('#qunit-fixture').find('.alert-message').length, 'element added to dom')\n\n        alert.find('.close').click()\n\n        ok(!$('#qunit-fixture').find('.alert-message').length, 'element removed from dom')\n      })\n\n      test(\"should not fire closed when close is prevented\", function () {\n        $.support.transition = false\n        stop();\n        $('<div class=\"alert\"/>')\n          .on('close.bs.alert', function (e) {\n            e.preventDefault();\n            ok(true);\n            start();\n          })\n          .on('closed.bs.alert', function () {\n            ok(false);\n          })\n          .alert('close')\n      })\n\n})\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/sass-bootstrap/js/tests/unit/button.js",
    "content": "$(function () {\n\n    module(\"button\")\n\n      test(\"should provide no conflict\", function () {\n        var button = $.fn.button.noConflict()\n        ok(!$.fn.button, 'button was set back to undefined (org value)')\n        $.fn.button = button\n      })\n\n      test(\"should be defined on jquery object\", function () {\n        ok($(document.body).button, 'button method is defined')\n      })\n\n      test(\"should return element\", function () {\n        ok($(document.body).button()[0] == document.body, 'document.body returned')\n      })\n\n      test(\"should return set state to loading\", function () {\n        var btn = $('<button class=\"btn\" data-loading-text=\"fat\">mdo</button>')\n        equals(btn.html(), 'mdo', 'btn text equals mdo')\n        btn.button('loading')\n        equals(btn.html(), 'fat', 'btn text equals fat')\n        stop()\n        setTimeout(function () {\n          ok(btn.attr('disabled'), 'btn is disabled')\n          ok(btn.hasClass('disabled'), 'btn has disabled class')\n          start()\n        }, 0)\n      })\n\n      test(\"should return reset state\", function () {\n        var btn = $('<button class=\"btn\" data-loading-text=\"fat\">mdo</button>')\n        equals(btn.html(), 'mdo', 'btn text equals mdo')\n        btn.button('loading')\n        equals(btn.html(), 'fat', 'btn text equals fat')\n        stop()\n        setTimeout(function () {\n          ok(btn.attr('disabled'), 'btn is disabled')\n          ok(btn.hasClass('disabled'), 'btn has disabled class')\n          start()\n          stop()\n          btn.button('reset')\n          equals(btn.html(), 'mdo', 'btn text equals mdo')\n          setTimeout(function () {\n            ok(!btn.attr('disabled'), 'btn is not disabled')\n            ok(!btn.hasClass('disabled'), 'btn does not have disabled class')\n            start()\n          }, 0)\n        }, 0)\n\n      })\n\n      test(\"should toggle active\", function () {\n        var btn = $('<button class=\"btn\">mdo</button>')\n        ok(!btn.hasClass('active'), 'btn does not have active class')\n        btn.button('toggle')\n        ok(btn.hasClass('active'), 'btn has class active')\n      })\n\n      test(\"should toggle active when btn children are clicked\", function () {\n        var btn = $('<button class=\"btn\" data-toggle=\"button\">mdo</button>')\n          , inner = $('<i></i>')\n        btn\n          .append(inner)\n          .appendTo($('#qunit-fixture'))\n        ok(!btn.hasClass('active'), 'btn does not have active class')\n        inner.click()\n        ok(btn.hasClass('active'), 'btn has class active')\n      })\n\n      test(\"should toggle active when btn children are clicked within btn-group\", function () {\n        var btngroup = $('<div class=\"btn-group\" data-toggle=\"buttons\"></div>')\n          , btn = $('<button class=\"btn\">fat</button>')\n          , inner = $('<i></i>')\n        btngroup\n          .append(btn.append(inner))\n          .appendTo($('#qunit-fixture'))\n        ok(!btn.hasClass('active'), 'btn does not have active class')\n        inner.click()\n        ok(btn.hasClass('active'), 'btn has class active')\n      })\n\n      test(\"should check for closest matching toggle\", function () {\n        var group = '<div class=\"btn-group\" data-toggle=\"buttons\">' +\n          '<label class=\"btn btn-primary active\">' +\n            '<input type=\"radio\" name=\"options\" id=\"option1\" checked=\"true\"> Option 1' +\n          '</label>' +\n          '<label class=\"btn btn-primary\">' +\n            '<input type=\"radio\" name=\"options\" id=\"option2\"> Option 2' +\n          '</label>' +\n          '<label class=\"btn btn-primary\">' +\n            '<input type=\"radio\" name=\"options\" id=\"option3\"> Option 3' +\n          '</label>' +\n        '</div>'\n\n        group = $(group)\n\n        var btn1 = $(group.children()[0])\n        var btn2 = $(group.children()[1])\n        var btn3 = $(group.children()[2])\n\n        group.appendTo($('#qunit-fixture'))\n\n        ok(btn1.hasClass('active'), 'btn1 has active class')\n        ok(btn1.find('input').prop('checked'), 'btn1 is checked')\n        ok(!btn2.hasClass('active'), 'btn2 does not have active class')\n        ok(!btn2.find('input').prop('checked'), 'btn2 is not checked')\n        btn2.find('input').click()\n        ok(!btn1.hasClass('active'), 'btn1 does not have active class')\n        ok(!btn1.find('input').prop('checked'), 'btn1 is checked')\n        ok(btn2.hasClass('active'), 'btn2 has active class')\n        ok(btn2.find('input').prop('checked'), 'btn2 is checked')\n      })\n\n})\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/sass-bootstrap/js/tests/unit/carousel.js",
    "content": "$(function () {\n\n    module(\"carousel\")\n\n      test(\"should provide no conflict\", function () {\n        var carousel = $.fn.carousel.noConflict()\n        ok(!$.fn.carousel, 'carousel was set back to undefined (org value)')\n        $.fn.carousel = carousel\n      })\n\n      test(\"should be defined on jquery object\", function () {\n        ok($(document.body).carousel, 'carousel method is defined')\n      })\n\n      test(\"should return element\", function () {\n        ok($(document.body).carousel()[0] == document.body, 'document.body returned')\n      })\n\n      test(\"should not fire sliden when slide is prevented\", function () {\n        $.support.transition = false\n        stop()\n        $('<div class=\"carousel\"/>')\n          .on('slide.bs.carousel', function (e) {\n            e.preventDefault();\n            ok(true);\n            start();\n          })\n          .on('slid.bs.carousel', function () {\n            ok(false);\n          })\n          .carousel('next')\n      })\n\n      test(\"should fire slide event with direction\", function () {\n        var template = '<div id=\"myCarousel\" class=\"carousel slide\"><div class=\"carousel-inner\"><div class=\"item active\"><img alt=\"\"><div class=\"carousel-caption\"><h4>{{_i}}First Thumbnail label{{/i}}</h4><p>Cras justo odio, dapibus ac facilisis in, egestas eget quam. Donec id elit non mi porta gravida at eget metus. Nullam id dolor id nibh ultricies vehicula ut id elit.</p></div></div><div class=\"item\"><img alt=\"\"><div class=\"carousel-caption\"><h4>{{_i}}Second Thumbnail label{{/i}}</h4><p>Cras justo odio, dapibus ac facilisis in, egestas eget quam. Donec id elit non mi porta gravida at eget metus. Nullam id dolor id nibh ultricies vehicula ut id elit.</p></div></div><div class=\"item\"><img alt=\"\"><div class=\"carousel-caption\"><h4>{{_i}}Third Thumbnail label{{/i}}</h4><p>Cras justo odio, dapibus ac facilisis in, egestas eget quam. Donec id elit non mi porta gravida at eget metus. Nullam id dolor id nibh ultricies vehicula ut id elit.</p></div></div></div><a class=\"left carousel-control\" href=\"#myCarousel\" data-slide=\"prev\">&lsaquo;</a><a class=\"right carousel-control\" href=\"#myCarousel\" data-slide=\"next\">&rsaquo;</a></div>'\n        $.support.transition = false\n        stop()\n        $(template).on('slide.bs.carousel', function (e) {\n          e.preventDefault()\n          ok(e.direction)\n          ok(e.direction === 'right' || e.direction === 'left')\n          start()\n        }).carousel('next')\n      })\n\n      test(\"should fire slide event with relatedTarget\", function () {\n        var template = '<div id=\"myCarousel\" class=\"carousel slide\"><div class=\"carousel-inner\"><div class=\"item active\"><img alt=\"\"><div class=\"carousel-caption\"><h4>{{_i}}First Thumbnail label{{/i}}</h4><p>Cras justo odio, dapibus ac facilisis in, egestas eget quam. Donec id elit non mi porta gravida at eget metus. Nullam id dolor id nibh ultricies vehicula ut id elit.</p></div></div><div class=\"item\"><img alt=\"\"><div class=\"carousel-caption\"><h4>{{_i}}Second Thumbnail label{{/i}}</h4><p>Cras justo odio, dapibus ac facilisis in, egestas eget quam. Donec id elit non mi porta gravida at eget metus. Nullam id dolor id nibh ultricies vehicula ut id elit.</p></div></div><div class=\"item\"><img alt=\"\"><div class=\"carousel-caption\"><h4>{{_i}}Third Thumbnail label{{/i}}</h4><p>Cras justo odio, dapibus ac facilisis in, egestas eget quam. Donec id elit non mi porta gravida at eget metus. Nullam id dolor id nibh ultricies vehicula ut id elit.</p></div></div></div><a class=\"left carousel-control\" href=\"#myCarousel\" data-slide=\"prev\">&lsaquo;</a><a class=\"right carousel-control\" href=\"#myCarousel\" data-slide=\"next\">&rsaquo;</a></div>'\n        $.support.transition = false\n        stop()\n        $(template)\n          .on('slide.bs.carousel', function (e) {\n            e.preventDefault();\n            ok(e.relatedTarget);\n            ok($(e.relatedTarget).hasClass('item'));\n            start();\n          })\n          .carousel('next')\n      })\n\n      test(\"should set interval from data attribute\", 4, function () {\n        var template = $('<div id=\"myCarousel\" class=\"carousel slide\"> <div class=\"carousel-inner\"> <div class=\"item active\"> <img alt=\"\"> <div class=\"carousel-caption\"> <h4>{{_i}}First Thumbnail label{{/i}}</h4> <p>Cras justo odio, dapibus ac facilisis in, egestas eget quam. Donec id elit non mi porta gravida at eget metus. Nullam id dolor id nibh ultricies vehicula ut id elit.</p> </div> </div> <div class=\"item\"> <img alt=\"\"> <div class=\"carousel-caption\"> <h4>{{_i}}Second Thumbnail label{{/i}}</h4> <p>Cras justo odio, dapibus ac facilisis in, egestas eget quam. Donec id elit non mi porta gravida at eget metus. Nullam id dolor id nibh ultricies vehicula ut id elit.</p> </div> </div> <div class=\"item\"> <img alt=\"\"> <div class=\"carousel-caption\"> <h4>{{_i}}Third Thumbnail label{{/i}}</h4> <p>Cras justo odio, dapibus ac facilisis in, egestas eget quam. Donec id elit non mi porta gravida at eget metus. Nullam id dolor id nibh ultricies vehicula ut id elit.</p> </div> </div> </div> <a class=\"left carousel-control\" href=\"#myCarousel\" data-slide=\"prev\">&lsaquo;</a> <a class=\"right carousel-control\" href=\"#myCarousel\" data-slide=\"next\">&rsaquo;</a> </div>');\n        template.attr(\"data-interval\", 1814);\n\n        template.appendTo(\"body\");\n        $('[data-slide]').first().click();\n        ok($('#myCarousel').data('bs.carousel').options.interval == 1814);\n        $('#myCarousel').remove();\n\n        template.appendTo(\"body\").attr(\"data-modal\", \"foobar\");\n        $('[data-slide]').first().click();\n        ok($('#myCarousel').data('bs.carousel').options.interval == 1814, \"even if there is an data-modal attribute set\");\n        $('#myCarousel').remove();\n\n        template.appendTo(\"body\");\n        $('[data-slide]').first().click();\n        $('#myCarousel').attr('data-interval', 1860);\n        $('[data-slide]').first().click();\n        ok($('#myCarousel').data('bs.carousel').options.interval == 1814, \"attributes should be read only on intitialization\");\n        $('#myCarousel').remove();\n\n        template.attr(\"data-interval\", false);\n        template.appendTo(\"body\");\n        $('#myCarousel').carousel(1);\n        ok($('#myCarousel').data('bs.carousel').options.interval === false, \"data attribute has higher priority than default options\");\n        $('#myCarousel').remove();\n      })\n})\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/sass-bootstrap/js/tests/unit/collapse.js",
    "content": "$(function () {\n\n    module(\"collapse\")\n\n      test(\"should provide no conflict\", function () {\n        var collapse = $.fn.collapse.noConflict()\n        ok(!$.fn.collapse, 'collapse was set back to undefined (org value)')\n        $.fn.collapse = collapse\n      })\n\n      test(\"should be defined on jquery object\", function () {\n        ok($(document.body).collapse, 'collapse method is defined')\n      })\n\n      test(\"should return element\", function () {\n        ok($(document.body).collapse()[0] == document.body, 'document.body returned')\n      })\n\n      test(\"should show a collapsed element\", function () {\n        var el = $('<div class=\"collapse\"></div>').collapse('show')\n        ok(el.hasClass('in'), 'has class in')\n        ok(/height/.test(el.attr('style')), 'has height set')\n      })\n\n      test(\"should hide a collapsed element\", function () {\n        var el = $('<div class=\"collapse\"></div>').collapse('hide')\n        ok(!el.hasClass('in'), 'does not have class in')\n        ok(/height/.test(el.attr('style')), 'has height set')\n      })\n\n      test(\"should not fire shown when show is prevented\", function () {\n        $.support.transition = false\n        stop()\n        $('<div class=\"collapse\"/>')\n          .on('show.bs.collapse', function (e) {\n            e.preventDefault();\n            ok(true);\n            start();\n          })\n          .on('shown.bs.collapse', function () {\n            ok(false);\n          })\n          .collapse('show')\n      })\n\n      test(\"should reset style to auto after finishing opening collapse\", function () {\n        $.support.transition = false\n        stop()\n        $('<div class=\"collapse\" style=\"height: 0px\"/>')\n          .on('show.bs.collapse', function () {\n            ok(this.style.height == '0px')\n          })\n          .on('shown.bs.collapse', function () {\n            ok(this.style.height == 'auto')\n            start()\n          })\n          .collapse('show')\n      })\n\n      test(\"should add active class to target when collapse shown\", function () {\n        $.support.transition = false\n        stop()\n\n        var target = $('<a data-toggle=\"collapse\" href=\"#test1\"></a>')\n          .appendTo($('#qunit-fixture'))\n\n        var collapsible = $('<div id=\"test1\"></div>')\n          .appendTo($('#qunit-fixture'))\n          .on('show.bs.collapse', function () {\n            ok(!target.hasClass('collapsed'))\n            start()\n          })\n\n        target.click()\n      })\n\n      test(\"should remove active class to target when collapse hidden\", function () {\n        $.support.transition = false\n        stop()\n\n        var target = $('<a data-toggle=\"collapse\" href=\"#test1\"></a>')\n          .appendTo($('#qunit-fixture'))\n\n        var collapsible = $('<div id=\"test1\" class=\"in\"></div>')\n          .appendTo($('#qunit-fixture'))\n          .on('hide.bs.collapse', function () {\n            ok(target.hasClass('collapsed'))\n            start()\n          })\n\n        target.click()\n      })\n\n      test(\"should remove active class from inactive accordion targets\", function () {\n        $.support.transition = false\n        stop()\n\n        var accordion = $('<div id=\"accordion\"><div class=\"accordion-group\"></div><div class=\"accordion-group\"></div><div class=\"accordion-group\"></div></div>')\n          .appendTo($('#qunit-fixture'))\n\n        var target1 = $('<a data-toggle=\"collapse\" href=\"#body1\" data-parent=\"#accordion\"></a>')\n          .appendTo(accordion.find('.accordion-group').eq(0))\n\n        var collapsible1 = $('<div id=\"body1\" class=\"in\"></div>')\n          .appendTo(accordion.find('.accordion-group').eq(0))\n\n        var target2 = $('<a class=\"collapsed\" data-toggle=\"collapse\" href=\"#body2\" data-parent=\"#accordion\"></a>')\n          .appendTo(accordion.find('.accordion-group').eq(1))\n\n        var collapsible2 = $('<div id=\"body2\"></div>')\n          .appendTo(accordion.find('.accordion-group').eq(1))\n\n        var target3 = $('<a class=\"collapsed\" data-toggle=\"collapse\" href=\"#body3\" data-parent=\"#accordion\"></a>')\n          .appendTo(accordion.find('.accordion-group').eq(2))\n\n        var collapsible3 = $('<div id=\"body3\"></div>')\n          .appendTo(accordion.find('.accordion-group').eq(2))\n          .on('show.bs.collapse', function () {\n            ok(target1.hasClass('collapsed'))\n            ok(target2.hasClass('collapsed'))\n            ok(!target3.hasClass('collapsed'))\n\n            start()\n          })\n\n        target3.click()\n      })\n\n      test(\"should allow dots in data-parent\", function () {\n        $.support.transition = false\n        stop()\n\n        var accordion = $('<div class=\"accordion\"><div class=\"accordion-group\"></div><div class=\"accordion-group\"></div><div class=\"accordion-group\"></div></div>')\n          .appendTo($('#qunit-fixture'))\n\n        var target1 = $('<a data-toggle=\"collapse\" href=\"#body1\" data-parent=\".accordion\"></a>')\n          .appendTo(accordion.find('.accordion-group').eq(0))\n\n        var collapsible1 = $('<div id=\"body1\" class=\"in\"></div>')\n          .appendTo(accordion.find('.accordion-group').eq(0))\n\n        var target2 = $('<a class=\"collapsed\" data-toggle=\"collapse\" href=\"#body2\" data-parent=\".accordion\"></a>')\n          .appendTo(accordion.find('.accordion-group').eq(1))\n\n        var collapsible2 = $('<div id=\"body2\"></div>')\n          .appendTo(accordion.find('.accordion-group').eq(1))\n\n        var target3 = $('<a class=\"collapsed\" data-toggle=\"collapse\" href=\"#body3\" data-parent=\".accordion\"></a>')\n          .appendTo(accordion.find('.accordion-group').eq(2))\n\n        var collapsible3 = $('<div id=\"body3\"></div>')\n          .appendTo(accordion.find('.accordion-group').eq(2))\n          .on('show.bs.collapse', function () {\n            ok(target1.hasClass('collapsed'))\n            ok(target2.hasClass('collapsed'))\n            ok(!target3.hasClass('collapsed'))\n\n            start()\n          })\n\n        target3.click()\n      })\n\n})\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/sass-bootstrap/js/tests/unit/dropdown.js",
    "content": "$(function () {\n\n    module(\"dropdowns\")\n\n      test(\"should provide no conflict\", function () {\n        var dropdown = $.fn.dropdown.noConflict()\n        ok(!$.fn.dropdown, 'dropdown was set back to undefined (org value)')\n        $.fn.dropdown = dropdown\n      })\n\n      test(\"should be defined on jquery object\", function () {\n        ok($(document.body).dropdown, 'dropdown method is defined')\n      })\n\n      test(\"should return element\", function () {\n        var el = $(\"<div />\")\n        ok(el.dropdown()[0] === el[0], 'same element returned')\n      })\n\n      test(\"should not open dropdown if target is disabled\", function () {\n        var dropdownHTML = '<ul class=\"tabs\">'\n          + '<li class=\"dropdown\">'\n          + '<button disabled href=\"#\" class=\"btn dropdown-toggle\" data-toggle=\"dropdown\">Dropdown</button>'\n          + '<ul class=\"dropdown-menu\">'\n          + '<li><a href=\"#\">Secondary link</a></li>'\n          + '<li><a href=\"#\">Something else here</a></li>'\n          + '<li class=\"divider\"></li>'\n          + '<li><a href=\"#\">Another link</a></li>'\n          + '</ul>'\n          + '</li>'\n          + '</ul>'\n          , dropdown = $(dropdownHTML).find('[data-toggle=\"dropdown\"]').dropdown().click()\n\n        ok(!dropdown.parent('.dropdown').hasClass('open'), 'open class added on click')\n      })\n\n      test(\"should not open dropdown if target is disabled\", function () {\n        var dropdownHTML = '<ul class=\"tabs\">'\n          + '<li class=\"dropdown\">'\n          + '<button href=\"#\" class=\"btn dropdown-toggle disabled\" data-toggle=\"dropdown\">Dropdown</button>'\n          + '<ul class=\"dropdown-menu\">'\n          + '<li><a href=\"#\">Secondary link</a></li>'\n          + '<li><a href=\"#\">Something else here</a></li>'\n          + '<li class=\"divider\"></li>'\n          + '<li><a href=\"#\">Another link</a></li>'\n          + '</ul>'\n          + '</li>'\n          + '</ul>'\n          , dropdown = $(dropdownHTML).find('[data-toggle=\"dropdown\"]').dropdown().click()\n\n        ok(!dropdown.parent('.dropdown').hasClass('open'), 'open class added on click')\n      })\n\n      test(\"should add class open to menu if clicked\", function () {\n        var dropdownHTML = '<ul class=\"tabs\">'\n          + '<li class=\"dropdown\">'\n          + '<a href=\"#\" class=\"dropdown-toggle\" data-toggle=\"dropdown\">Dropdown</a>'\n          + '<ul class=\"dropdown-menu\">'\n          + '<li><a href=\"#\">Secondary link</a></li>'\n          + '<li><a href=\"#\">Something else here</a></li>'\n          + '<li class=\"divider\"></li>'\n          + '<li><a href=\"#\">Another link</a></li>'\n          + '</ul>'\n          + '</li>'\n          + '</ul>'\n          , dropdown = $(dropdownHTML).find('[data-toggle=\"dropdown\"]').dropdown().click()\n\n        ok(dropdown.parent('.dropdown').hasClass('open'), 'open class added on click')\n      })\n\n      test(\"should test if element has a # before assuming it's a selector\", function () {\n        var dropdownHTML = '<ul class=\"tabs\">'\n          + '<li class=\"dropdown\">'\n          + '<a href=\"/foo/\" class=\"dropdown-toggle\" data-toggle=\"dropdown\">Dropdown</a>'\n          + '<ul class=\"dropdown-menu\">'\n          + '<li><a href=\"#\">Secondary link</a></li>'\n          + '<li><a href=\"#\">Something else here</a></li>'\n          + '<li class=\"divider\"></li>'\n          + '<li><a href=\"#\">Another link</a></li>'\n          + '</ul>'\n          + '</li>'\n          + '</ul>'\n          , dropdown = $(dropdownHTML).find('[data-toggle=\"dropdown\"]').dropdown().click()\n\n        ok(dropdown.parent('.dropdown').hasClass('open'), 'open class added on click')\n      })\n\n\n      test(\"should remove open class if body clicked\", function () {\n        var dropdownHTML = '<ul class=\"tabs\">'\n          + '<li class=\"dropdown\">'\n          + '<a href=\"#\" class=\"dropdown-toggle\" data-toggle=\"dropdown\">Dropdown</a>'\n          + '<ul class=\"dropdown-menu\">'\n          + '<li><a href=\"#\">Secondary link</a></li>'\n          + '<li><a href=\"#\">Something else here</a></li>'\n          + '<li class=\"divider\"></li>'\n          + '<li><a href=\"#\">Another link</a></li>'\n          + '</ul>'\n          + '</li>'\n          + '</ul>'\n          , dropdown = $(dropdownHTML)\n            .appendTo('#qunit-fixture')\n            .find('[data-toggle=\"dropdown\"]')\n            .dropdown()\n            .click()\n\n        ok(dropdown.parent('.dropdown').hasClass('open'), 'open class added on click')\n        $('body').click()\n        ok(!dropdown.parent('.dropdown').hasClass('open'), 'open class removed')\n        dropdown.remove()\n      })\n\n      test(\"should remove open class if body clicked, with multiple drop downs\", function () {\n          var dropdownHTML =\n            '<ul class=\"nav\">'\n            + '    <li><a href=\"#menu1\">Menu 1</a></li>'\n            + '    <li class=\"dropdown\" id=\"testmenu\">'\n            + '      <a class=\"dropdown-toggle\" data-toggle=\"dropdown\" href=\"#testmenu\">Test menu <b class=\"caret\"></b></a>'\n            + '      <ul class=\"dropdown-menu\" role=\"menu\">'\n            + '        <li><a href=\"#sub1\">Submenu 1</a></li>'\n            + '      </ul>'\n            + '    </li>'\n            + '</ul>'\n            + '<div class=\"btn-group\">'\n            + '    <button class=\"btn\">Actions</button>'\n            + '    <button class=\"btn dropdown-toggle\" data-toggle=\"dropdown\"><span class=\"caret\"></span></button>'\n            + '    <ul class=\"dropdown-menu\">'\n            + '        <li><a href=\"#\">Action 1</a></li>'\n            + '    </ul>'\n            + '</div>'\n          , dropdowns = $(dropdownHTML).appendTo('#qunit-fixture').find('[data-toggle=\"dropdown\"]')\n          , first = dropdowns.first()\n          , last = dropdowns.last()\n\n        ok(dropdowns.length == 2, \"Should be two dropdowns\")\n\n        first.click()\n        ok(first.parents('.open').length == 1, 'open class added on click')\n        ok($('#qunit-fixture .open').length == 1, 'only one object is open')\n        $('body').click()\n        ok($(\"#qunit-fixture .open\").length === 0, 'open class removed')\n\n        last.click()\n        ok(last.parent('.open').length == 1, 'open class added on click')\n        ok($('#qunit-fixture .open').length == 1, 'only one object is open')\n        $('body').click()\n        ok($(\"#qunit-fixture .open\").length === 0, 'open class removed')\n\n        $(\"#qunit-fixture\").html(\"\")\n      })\n\n      test(\"should fire show and hide event\", function () {\n        var dropdownHTML = '<ul class=\"tabs\">'\n          + '<li class=\"dropdown\">'\n          + '<a href=\"#\" class=\"dropdown-toggle\" data-toggle=\"dropdown\">Dropdown</a>'\n          + '<ul class=\"dropdown-menu\">'\n          + '<li><a href=\"#\">Secondary link</a></li>'\n          + '<li><a href=\"#\">Something else here</a></li>'\n          + '<li class=\"divider\"></li>'\n          + '<li><a href=\"#\">Another link</a></li>'\n          + '</ul>'\n          + '</li>'\n          + '</ul>'\n          , dropdown = $(dropdownHTML)\n            .appendTo('#qunit-fixture')\n            .find('[data-toggle=\"dropdown\"]')\n            .dropdown()\n\n        stop()\n\n        dropdown\n          .parent('.dropdown')\n          .bind('show.bs.dropdown', function () {\n            ok(true, 'show was called')\n          })\n          .bind('hide.bs.dropdown', function () {\n            ok(true, 'hide was called')\n            start()\n          })\n\n        dropdown.click()\n        $(document.body).click()\n      })\n\n\n      test(\"should fire shown and hiden event\", function () {\n        var dropdownHTML = '<ul class=\"tabs\">'\n          + '<li class=\"dropdown\">'\n          + '<a href=\"#\" class=\"dropdown-toggle\" data-toggle=\"dropdown\">Dropdown</a>'\n          + '<ul class=\"dropdown-menu\">'\n          + '<li><a href=\"#\">Secondary link</a></li>'\n          + '<li><a href=\"#\">Something else here</a></li>'\n          + '<li class=\"divider\"></li>'\n          + '<li><a href=\"#\">Another link</a></li>'\n          + '</ul>'\n          + '</li>'\n          + '</ul>'\n          , dropdown = $(dropdownHTML)\n            .appendTo('#qunit-fixture')\n            .find('[data-toggle=\"dropdown\"]')\n            .dropdown()\n\n        stop()\n\n        dropdown\n          .parent('.dropdown')\n          .bind('shown.bs.dropdown', function () {\n            ok(true, 'show was called')\n          })\n          .bind('hidden.bs.dropdown', function () {\n            ok(true, 'hide was called')\n            start()\n          })\n\n        dropdown.click()\n        $(document.body).click()\n      })\n\n})\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/sass-bootstrap/js/tests/unit/modal.js",
    "content": "$(function () {\n\n  module(\"modal\")\n\n    test(\"should provide no conflict\", function () {\n      var modal = $.fn.modal.noConflict()\n      ok(!$.fn.modal, 'modal was set back to undefined (org value)')\n      $.fn.modal = modal\n    })\n\n    test(\"should be defined on jquery object\", function () {\n      var div = $(\"<div id='modal-test'></div>\")\n      ok(div.modal, 'modal method is defined')\n    })\n\n    test(\"should return element\", function () {\n      var div = $(\"<div id='modal-test'></div>\")\n      ok(div.modal() == div, 'document.body returned')\n      $('#modal-test').remove()\n    })\n\n    test(\"should expose defaults var for settings\", function () {\n      ok($.fn.modal.Constructor.DEFAULTS, 'default object exposed')\n    })\n\n    test(\"should insert into dom when show method is called\", function () {\n      stop()\n      $.support.transition = false\n      $(\"<div id='modal-test'></div>\")\n        .on(\"shown.bs.modal\", function () {\n          ok($('#modal-test').length, 'modal inserted into dom')\n          $(this).remove()\n          start()\n        })\n        .modal(\"show\")\n    })\n\n    test(\"should fire show event\", function () {\n      stop()\n      $.support.transition = false\n      $(\"<div id='modal-test'></div>\")\n        .on(\"show.bs.modal\", function () {\n          ok(true, \"show was called\")\n        })\n        .on(\"shown.bs.modal\", function () {\n          $(this).remove()\n          start()\n        })\n        .modal(\"show\")\n    })\n\n    test(\"should not fire shown when default prevented\", function () {\n      stop()\n      $.support.transition = false\n      $(\"<div id='modal-test'></div>\")\n        .on(\"show.bs.modal\", function (e) {\n          e.preventDefault()\n          ok(true, \"show was called\")\n          start()\n        })\n        .on(\"shown.bs.modal\", function () {\n          ok(false, \"shown was called\")\n        })\n        .modal(\"show\")\n    })\n\n    test(\"should hide modal when hide is called\", function () {\n      stop()\n      $.support.transition = false\n\n      $(\"<div id='modal-test'></div>\")\n        .on(\"shown.bs.modal\", function () {\n          ok($('#modal-test').is(\":visible\"), 'modal visible')\n          ok($('#modal-test').length, 'modal inserted into dom')\n          $(this).modal(\"hide\")\n        })\n        .on(\"hidden.bs.modal\", function() {\n          ok(!$('#modal-test').is(\":visible\"), 'modal hidden')\n          $('#modal-test').remove()\n          start()\n        })\n        .modal(\"show\")\n    })\n\n    test(\"should toggle when toggle is called\", function () {\n      stop()\n      $.support.transition = false\n      var div = $(\"<div id='modal-test'></div>\")\n      div\n        .on(\"shown.bs.modal\", function () {\n          ok($('#modal-test').is(\":visible\"), 'modal visible')\n          ok($('#modal-test').length, 'modal inserted into dom')\n          div.modal(\"toggle\")\n        })\n        .on(\"hidden.bs.modal\", function() {\n          ok(!$('#modal-test').is(\":visible\"), 'modal hidden')\n          div.remove()\n          start()\n        })\n        .modal(\"toggle\")\n    })\n\n    test(\"should remove from dom when click [data-dismiss=modal]\", function () {\n      stop()\n      $.support.transition = false\n      var div = $(\"<div id='modal-test'><span class='close' data-dismiss='modal'></span></div>\")\n      div\n        .on(\"shown.bs.modal\", function () {\n          ok($('#modal-test').is(\":visible\"), 'modal visible')\n          ok($('#modal-test').length, 'modal inserted into dom')\n          div.find('.close').click()\n        })\n        .on(\"hidden.bs.modal\", function() {\n          ok(!$('#modal-test').is(\":visible\"), 'modal hidden')\n          div.remove()\n          start()\n        })\n        .modal(\"toggle\")\n    })\n\n    test(\"should allow modal close with 'backdrop:false'\", function () {\n      stop()\n      $.support.transition = false\n      var div = $(\"<div>\", { id: 'modal-test', \"data-backdrop\": false })\n      div\n        .on(\"shown.bs.modal\", function () {\n          ok($('#modal-test').is(\":visible\"), 'modal visible')\n          div.modal(\"hide\")\n        })\n        .on(\"hidden.bs.modal\", function() {\n          ok(!$('#modal-test').is(\":visible\"), 'modal hidden')\n          div.remove()\n          start()\n        })\n        .modal(\"show\")\n    })\n\n    test(\"should close modal when clicking outside of modal-content\", function () {\n      stop()\n      $.support.transition = false\n      var div = $(\"<div id='modal-test'><div class='contents'></div></div>\")\n      div\n        .bind(\"shown.bs.modal\", function () {\n          ok($('#modal-test').length, 'modal insterted into dom')\n          $('.contents').click()\n          ok($('#modal-test').is(\":visible\"), 'modal visible')\n          $('#modal-test').click()\n        })\n        .bind(\"hidden.bs.modal\", function() {\n          ok(!$('#modal-test').is(\":visible\"), 'modal hidden')\n          div.remove()\n          start()\n        })\n        .modal(\"show\")\n    })\n\n    test(\"should trigger hide event once when clicking outside of modal-content\", function () {\n      stop()\n      $.support.transition = false\n      var div = $(\"<div id='modal-test'><div class='contents'></div></div>\")\n      var triggered\n      div\n        .bind(\"shown.bs.modal\", function () {\n          triggered = 0\n          $('#modal-test').click()\n        })\n        .one(\"hidden.bs.modal\", function() {\n          div.modal(\"show\")\n        })\n        .bind(\"hide.bs.modal\", function () {\n          triggered += 1\n          ok(triggered === 1, 'modal hide triggered once')\n          start()\n        })\n        .modal(\"show\")\n    })\n\n    test(\"should close reopened modal with [data-dismiss=modal] click\", function () {\n      stop()\n      $.support.transition = false\n      var div = $(\"<div id='modal-test'><div class='contents'><div id='close' data-dismiss='modal'></div></div></div>\")\n      div\n        .bind(\"shown.bs.modal\", function () {\n          $('#close').click()\n          ok(!$('#modal-test').is(\":visible\"), 'modal hidden')\n        })\n        .one(\"hidden.bs.modal\", function() {\n          div.one('hidden.bs.modal', function () {\n            start()\n          }).modal(\"show\")\n        })\n        .modal(\"show\")\n\n      div.remove()\n    })\n})\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/sass-bootstrap/js/tests/unit/phantom.js",
    "content": "/*\n * grunt-contrib-qunit\n * http://gruntjs.com/\n *\n * Copyright (c) 2013 \"Cowboy\" Ben Alman, contributors\n * Licensed under the MIT license.\n */\n\n/*global QUnit:true, alert:true*/\n(function () {\n  'use strict';\n\n  // Don't re-order tests.\n  QUnit.config.reorder = false\n  // Run tests serially, not in parallel.\n  QUnit.config.autorun = false\n\n  // Send messages to the parent PhantomJS process via alert! Good times!!\n  function sendMessage() {\n    var args = [].slice.call(arguments)\n    alert(JSON.stringify(args))\n  }\n\n  // These methods connect QUnit to PhantomJS.\n  QUnit.log = function(obj) {\n    // What is this I don’t even\n    if (obj.message === '[object Object], undefined:undefined') { return }\n    // Parse some stuff before sending it.\n    var actual = QUnit.jsDump.parse(obj.actual)\n    var expected = QUnit.jsDump.parse(obj.expected)\n    // Send it.\n    sendMessage('qunit.log', obj.result, actual, expected, obj.message, obj.source)\n  }\n\n  QUnit.testStart = function(obj) {\n    sendMessage('qunit.testStart', obj.name)\n  }\n\n  QUnit.testDone = function(obj) {\n    sendMessage('qunit.testDone', obj.name, obj.failed, obj.passed, obj.total)\n  }\n\n  QUnit.moduleStart = function(obj) {\n    sendMessage('qunit.moduleStart', obj.name)\n  }\n\n  QUnit.begin = function () {\n    sendMessage('qunit.begin')\n    console.log(\"Starting test suite\")\n    console.log(\"================================================\\n\")\n  }\n\n  QUnit.moduleDone = function (opts) {\n    if (opts.failed === 0) {\n      console.log(\"\\r\\u2714 All tests passed in '\" + opts.name + \"' module\")\n    } else {\n      console.log(\"\\u2716 \" + opts.failed + \" tests failed in '\" + opts.name + \"' module\")\n    }\n    sendMessage('qunit.moduleDone', opts.name, opts.failed, opts.passed, opts.total)\n  }\n\n  QUnit.done = function (opts) {\n    console.log(\"\\n================================================\")\n    console.log(\"Tests completed in \" + opts.runtime + \" milliseconds\")\n    console.log(opts.passed + \" tests of \" + opts.total + \" passed, \" + opts.failed + \" failed.\")\n    sendMessage('qunit.done', opts.failed, opts.passed, opts.total, opts.runtime)\n  }\n\n}())\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/sass-bootstrap/js/tests/unit/popover.js",
    "content": "$(function () {\n\n    module(\"popover\")\n\n      test(\"should provide no conflict\", function () {\n        var popover = $.fn.popover.noConflict()\n        ok(!$.fn.popover, 'popover was set back to undefined (org value)')\n        $.fn.popover = popover\n      })\n\n      test(\"should be defined on jquery object\", function () {\n        var div = $('<div></div>')\n        ok(div.popover, 'popover method is defined')\n      })\n\n      test(\"should return element\", function () {\n        var div = $('<div></div>')\n        ok(div.popover() == div, 'document.body returned')\n      })\n\n      test(\"should render popover element\", function () {\n        $.support.transition = false\n        var popover = $('<a href=\"#\" title=\"mdo\" data-content=\"http://twitter.com/mdo\">@mdo</a>')\n          .appendTo('#qunit-fixture')\n          .popover('show')\n\n        ok($('.popover').length, 'popover was inserted')\n        popover.popover('hide')\n        ok(!$(\".popover\").length, 'popover removed')\n      })\n\n      test(\"should store popover instance in popover data object\", function () {\n        $.support.transition = false\n        var popover = $('<a href=\"#\" title=\"mdo\" data-content=\"http://twitter.com/mdo\">@mdo</a>')\n          .popover()\n\n        ok(!!popover.data('bs.popover'), 'popover instance exists')\n      })\n\n      test(\"should get title and content from options\", function () {\n        $.support.transition = false\n        var popover = $('<a href=\"#\">@fat</a>')\n          .appendTo('#qunit-fixture')\n          .popover({\n            title: function () {\n              return '@fat'\n            }\n          , content: function () {\n              return 'loves writing tests （╯°□°）╯︵ ┻━┻'\n            }\n          })\n\n        popover.popover('show')\n\n        ok($('.popover').length, 'popover was inserted')\n        equals($('.popover .popover-title').text(), '@fat', 'title correctly inserted')\n        equals($('.popover .popover-content').text(), 'loves writing tests （╯°□°）╯︵ ┻━┻', 'content correctly inserted')\n\n        popover.popover('hide')\n        ok(!$('.popover').length, 'popover was removed')\n        $('#qunit-fixture').empty()\n      })\n\n      test(\"should get title and content from attributes\", function () {\n        $.support.transition = false\n        var popover = $('<a href=\"#\" title=\"@mdo\" data-content=\"loves data attributes (づ｡◕‿‿◕｡)づ ︵ ┻━┻\" >@mdo</a>')\n          .appendTo('#qunit-fixture')\n          .popover()\n          .popover('show')\n\n        ok($('.popover').length, 'popover was inserted')\n        equals($('.popover .popover-title').text(), '@mdo', 'title correctly inserted')\n        equals($('.popover .popover-content').text(), \"loves data attributes (づ｡◕‿‿◕｡)づ ︵ ┻━┻\", 'content correctly inserted')\n\n        popover.popover('hide')\n        ok(!$('.popover').length, 'popover was removed')\n        $('#qunit-fixture').empty()\n      })\n\n\n      test(\"should get title and content from attributes #2\", function () {\n        $.support.transition = false\n        var popover = $('<a href=\"#\" title=\"@mdo\" data-content=\"loves data attributes (づ｡◕‿‿◕｡)づ ︵ ┻━┻\" >@mdo</a>')\n          .appendTo('#qunit-fixture')\n          .popover({\n              title: 'ignored title option',\n              content: 'ignored content option'\n          })\n          .popover('show')\n\n        ok($('.popover').length, 'popover was inserted')\n        equals($('.popover .popover-title').text(), '@mdo', 'title correctly inserted')\n        equals($('.popover .popover-content').text(), \"loves data attributes (づ｡◕‿‿◕｡)づ ︵ ┻━┻\", 'content correctly inserted')\n\n        popover.popover('hide')\n        ok(!$('.popover').length, 'popover was removed')\n        $('#qunit-fixture').empty()\n      })\n\n      test(\"should respect custom classes\", function() {\n        $.support.transition = false\n        var popover = $('<a href=\"#\">@fat</a>')\n          .appendTo('#qunit-fixture')\n          .popover({\n            title: 'Test'\n          , content: 'Test'\n          , template: '<div class=\"popover foobar\"><div class=\"arrow\"></div><div class=\"inner\"><h3 class=\"title\"></h3><div class=\"content\"><p></p></div></div></div>'\n          })\n\n        popover.popover('show')\n\n        ok($('.popover').length, 'popover was inserted')\n        ok($('.popover').hasClass('foobar'), 'custom class is present')\n\n        popover.popover('hide')\n        ok(!$('.popover').length, 'popover was removed')\n        $('#qunit-fixture').empty()\n      })\n\n      test(\"should destroy popover\", function () {\n        var popover = $('<div/>').popover({trigger: 'hover'}).on('click.foo', function(){})\n        ok(popover.data('bs.popover'), 'popover has data')\n        ok($._data(popover[0], 'events').mouseover && $._data(popover[0], 'events').mouseout, 'popover has hover event')\n        ok($._data(popover[0], 'events').click[0].namespace == 'foo', 'popover has extra click.foo event')\n        popover.popover('show')\n        popover.popover('destroy')\n        ok(!popover.hasClass('in'), 'popover is hidden')\n        ok(!popover.data('popover'), 'popover does not have data')\n        ok($._data(popover[0],'events').click[0].namespace == 'foo', 'popover still has click.foo')\n        ok(!$._data(popover[0], 'events').mouseover && !$._data(popover[0], 'events').mouseout, 'popover does not have any events')\n      })\n\n})\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/sass-bootstrap/js/tests/unit/scrollspy.js",
    "content": "$(function () {\n\n    module(\"scrollspy\")\n\n      test(\"should provide no conflict\", function () {\n        var scrollspy = $.fn.scrollspy.noConflict()\n        ok(!$.fn.scrollspy, 'scrollspy was set back to undefined (org value)')\n        $.fn.scrollspy = scrollspy\n      })\n\n      test(\"should be defined on jquery object\", function () {\n        ok($(document.body).scrollspy, 'scrollspy method is defined')\n      })\n\n      test(\"should return element\", function () {\n        ok($(document.body).scrollspy()[0] == document.body, 'document.body returned')\n      })\n\n      test(\"should switch active class on scroll\", function () {\n        var sectionHTML = '<div id=\"masthead\"></div>'\n          , $section = $(sectionHTML).append('#qunit-fixture')\n          , topbarHTML ='<div class=\"topbar\">'\n          + '<div class=\"topbar-inner\">'\n          + '<div class=\"container\">'\n          + '<h3><a href=\"#\">Bootstrap</a></h3>'\n          + '<ul class=\"nav\">'\n          + '<li><a href=\"#masthead\">Overview</a></li>'\n          + '</ul>'\n          + '</div>'\n          + '</div>'\n          + '</div>'\n          , $topbar = $(topbarHTML).scrollspy()\n\n        ok($topbar.find('.active', true))\n      })\n\n})\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/sass-bootstrap/js/tests/unit/tab.js",
    "content": "$(function () {\n\n    module(\"tabs\")\n\n      test(\"should provide no conflict\", function () {\n        var tab = $.fn.tab.noConflict()\n        ok(!$.fn.tab, 'tab was set back to undefined (org value)')\n        $.fn.tab = tab\n      })\n\n      test(\"should be defined on jquery object\", function () {\n        ok($(document.body).tab, 'tabs method is defined')\n      })\n\n      test(\"should return element\", function () {\n        ok($(document.body).tab()[0] == document.body, 'document.body returned')\n      })\n\n      test(\"should activate element by tab id\", function () {\n        var tabsHTML =\n            '<ul class=\"tabs\">'\n          + '<li><a href=\"#home\">Home</a></li>'\n          + '<li><a href=\"#profile\">Profile</a></li>'\n          + '</ul>'\n\n        $('<ul><li id=\"home\"></li><li id=\"profile\"></li></ul>').appendTo(\"#qunit-fixture\")\n\n        $(tabsHTML).find('li:last a').tab('show')\n        equals($(\"#qunit-fixture\").find('.active').attr('id'), \"profile\")\n\n        $(tabsHTML).find('li:first a').tab('show')\n        equals($(\"#qunit-fixture\").find('.active').attr('id'), \"home\")\n      })\n\n      test(\"should activate element by tab id\", function () {\n        var pillsHTML =\n            '<ul class=\"pills\">'\n          + '<li><a href=\"#home\">Home</a></li>'\n          + '<li><a href=\"#profile\">Profile</a></li>'\n          + '</ul>'\n\n        $('<ul><li id=\"home\"></li><li id=\"profile\"></li></ul>').appendTo(\"#qunit-fixture\")\n\n        $(pillsHTML).find('li:last a').tab('show')\n        equals($(\"#qunit-fixture\").find('.active').attr('id'), \"profile\")\n\n        $(pillsHTML).find('li:first a').tab('show')\n        equals($(\"#qunit-fixture\").find('.active').attr('id'), \"home\")\n      })\n\n\n      test(\"should not fire closed when close is prevented\", function () {\n        $.support.transition = false\n        stop();\n        $('<div class=\"tab\"/>')\n          .on('show.bs.tab', function (e) {\n            e.preventDefault();\n            ok(true);\n            start();\n          })\n          .on('shown.bs.tab', function () {\n            ok(false);\n          })\n          .tab('show')\n      })\n\n      test(\"show and shown events should reference correct relatedTarget\", function () {\n        var dropHTML =\n            '<ul class=\"drop\">'\n          + '<li class=\"dropdown\"><a data-toggle=\"dropdown\" href=\"#\">1</a>'\n          + '<ul class=\"dropdown-menu\">'\n          + '<li><a href=\"#1-1\" data-toggle=\"tab\">1-1</a></li>'\n          + '<li><a href=\"#1-2\" data-toggle=\"tab\">1-2</a></li>'\n          + '</ul>'\n          + '</li>'\n          + '</ul>'\n\n        $(dropHTML).find('ul>li:first a').tab('show').end()\n          .find('ul>li:last a').on('show', function(event){\n            equals(event.relatedTarget.hash, \"#1-1\")\n          }).on('shown', function(event){\n            equals(event.relatedTarget.hash, \"#1-1\")\n          }).tab('show')\n      })\n\n})\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/sass-bootstrap/js/tests/unit/tooltip.js",
    "content": "$(function () {\n\n    module(\"tooltip\")\n\n      test(\"should provide no conflict\", function () {\n        var tooltip = $.fn.tooltip.noConflict()\n        ok(!$.fn.tooltip, 'tooltip was set back to undefined (org value)')\n        $.fn.tooltip = tooltip\n      })\n\n      test(\"should be defined on jquery object\", function () {\n        var div = $(\"<div></div>\")\n        ok(div.tooltip, 'popover method is defined')\n      })\n\n      test(\"should return element\", function () {\n        var div = $(\"<div></div>\")\n        ok(div.tooltip() == div, 'document.body returned')\n      })\n\n      test(\"should expose default settings\", function () {\n        ok(!!$.fn.tooltip.Constructor.DEFAULTS, 'defaults is defined')\n      })\n\n      test(\"should empty title attribute\", function () {\n        var tooltip = $('<a href=\"#\" rel=\"tooltip\" title=\"Another tooltip\"></a>').tooltip()\n        ok(tooltip.attr('title') === '', 'title attribute was emptied')\n      })\n\n      test(\"should add data attribute for referencing original title\", function () {\n        var tooltip = $('<a href=\"#\" rel=\"tooltip\" title=\"Another tooltip\"></a>').tooltip()\n        equals(tooltip.attr('data-original-title'), 'Another tooltip', 'original title preserved in data attribute')\n      })\n\n      test(\"should place tooltips relative to placement option\", function () {\n        $.support.transition = false\n        var tooltip = $('<a href=\"#\" rel=\"tooltip\" title=\"Another tooltip\"></a>')\n          .appendTo('#qunit-fixture')\n          .tooltip({placement: 'bottom'})\n          .tooltip('show')\n\n        ok($(\".tooltip\").is('.fade.bottom.in'), 'has correct classes applied')\n        tooltip.tooltip('hide')\n      })\n\n      test(\"should allow html entities\", function () {\n        $.support.transition = false\n        var tooltip = $('<a href=\"#\" rel=\"tooltip\" title=\"<b>@fat</b>\"></a>')\n          .appendTo('#qunit-fixture')\n          .tooltip({html: true})\n          .tooltip('show')\n\n        ok($('.tooltip b').length, 'b tag was inserted')\n        tooltip.tooltip('hide')\n        ok(!$(\".tooltip\").length, 'tooltip removed')\n      })\n\n      test(\"should respect custom classes\", function () {\n        var tooltip = $('<a href=\"#\" rel=\"tooltip\" title=\"Another tooltip\"></a>')\n          .appendTo('#qunit-fixture')\n          .tooltip({ template: '<div class=\"tooltip some-class\"><div class=\"tooltip-arrow\"/><div class=\"tooltip-inner\"/></div>'})\n          .tooltip('show')\n\n        ok($('.tooltip').hasClass('some-class'), 'custom class is present')\n        tooltip.tooltip('hide')\n        ok(!$(\".tooltip\").length, 'tooltip removed')\n      })\n\n      test(\"should fire show event\", function () {\n        stop()\n        var tooltip = $('<div title=\"tooltip title\"></div>')\n          .on(\"show.bs.tooltip\", function() {\n            ok(true, \"show was called\")\n            start()\n          })\n          .tooltip('show')\n      })\n\n      test(\"should fire shown event\", function () {\n        stop()\n        var tooltip = $('<div title=\"tooltip title\"></div>')\n          .on(\"shown.bs.tooltip\", function() {\n            ok(true, \"shown was called\")\n            start()\n          })\n          .tooltip('show')\n      })\n\n      test(\"should not fire shown event when default prevented\", function () {\n        stop()\n        var tooltip = $('<div title=\"tooltip title\"></div>')\n          .on(\"show.bs.tooltip\", function(e) {\n            e.preventDefault()\n            ok(true, \"show was called\")\n            start()\n          })\n          .on(\"shown.bs.tooltip\", function() {\n            ok(false, \"shown was called\")\n          })\n          .tooltip('show')\n      })\n\n      test(\"should fire hide event\", function () {\n        stop()\n        var tooltip = $('<div title=\"tooltip title\"></div>')\n          .on(\"shown.bs.tooltip\", function() {\n            $(this).tooltip('hide')\n          })\n          .on(\"hide.bs.tooltip\", function() {\n            ok(true, \"hide was called\")\n            start()\n          })\n          .tooltip('show')\n      })\n\n      test(\"should fire hidden event\", function () {\n        stop()\n        var tooltip = $('<div title=\"tooltip title\"></div>')\n          .on(\"shown.bs.tooltip\", function() {\n            $(this).tooltip('hide')\n          })\n          .on(\"hidden.bs.tooltip\", function() {\n            ok(true, \"hidden was called\")\n            start()\n          })\n          .tooltip('show')\n      })\n\n      test(\"should not fire hidden event when default prevented\", function () {\n        stop()\n        var tooltip = $('<div title=\"tooltip title\"></div>')\n          .on(\"shown.bs.tooltip\", function() {\n            $(this).tooltip('hide')\n          })\n          .on(\"hide.bs.tooltip\", function(e) {\n            e.preventDefault()\n            ok(true, \"hide was called\")\n            start()\n          })\n          .on(\"hidden.bs.tooltip\", function() {\n            ok(false, \"hidden was called\")\n          })\n          .tooltip('show')\n      })\n\n      test(\"should not show tooltip if leave event occurs before delay expires\", function () {\n        var tooltip = $('<a href=\"#\" rel=\"tooltip\" title=\"Another tooltip\"></a>')\n          .appendTo('#qunit-fixture')\n          .tooltip({ delay: 200 })\n\n        stop()\n\n        tooltip.trigger('mouseenter')\n\n        setTimeout(function () {\n          ok(!$(\".tooltip\").is('.fade.in'), 'tooltip is not faded in')\n          tooltip.trigger('mouseout')\n          setTimeout(function () {\n            ok(!$(\".tooltip\").is('.fade.in'), 'tooltip is not faded in')\n            start()\n          }, 200)\n        }, 100)\n      })\n\n      test(\"should not show tooltip if leave event occurs before delay expires, even if hide delay is 0\", function () {\n        var tooltip = $('<a href=\"#\" rel=\"tooltip\" title=\"Another tooltip\"></a>')\n          .appendTo('#qunit-fixture')\n          .tooltip({ delay: { show: 200, hide: 0} })\n\n        stop()\n\n        tooltip.trigger('mouseenter')\n\n        setTimeout(function () {\n          ok(!$(\".tooltip\").is('.fade.in'), 'tooltip is not faded in')\n          tooltip.trigger('mouseout')\n          setTimeout(function () {\n            ok(!$(\".tooltip\").is('.fade.in'), 'tooltip is not faded in')\n            start()\n          }, 200)\n        }, 100)\n      })\n\n      test(\"should wait 200 ms before hiding the tooltip\", 3, function () {\n        var tooltip = $('<a href=\"#\" rel=\"tooltip\" title=\"Another tooltip\"></a>')\n          .appendTo('#qunit-fixture')\n          .tooltip({ delay: { show: 0, hide: 200} })\n\n        stop()\n\n        tooltip.trigger('mouseenter')\n\n        setTimeout(function () {\n          ok($(\".tooltip\").is('.fade.in'), 'tooltip is faded in')\n          tooltip.trigger('mouseout')\n          setTimeout(function () {\n            ok($(\".tooltip\").is('.fade.in'), '100ms:tooltip is still faded in')\n            setTimeout(function () {\n              ok(!$(\".tooltip\").is('.in'), 'tooltip removed')\n              start()\n            }, 150)\n          }, 100)\n        }, 1)\n      })\n\n      test(\"should not hide tooltip if leave event occurs, then tooltip is show immediately again\", function () {\n        var tooltip = $('<a href=\"#\" rel=\"tooltip\" title=\"Another tooltip\"></a>')\n          .appendTo('#qunit-fixture')\n          .tooltip({ delay: { show: 0, hide: 200} })\n\n        stop()\n\n        tooltip.trigger('mouseenter')\n\n        setTimeout(function () {\n          ok($(\".tooltip\").is('.fade.in'), 'tooltip is faded in')\n          tooltip.trigger('mouseout')\n          setTimeout(function () {\n            ok($(\".tooltip\").is('.fade.in'), '100ms:tooltip is still faded in')\n            tooltip.trigger('mouseenter')\n            setTimeout(function () {\n              ok($(\".tooltip\").is('.in'), 'tooltip removed')\n              start()\n            }, 150)\n          }, 100)\n        }, 1)\n      })\n\n      test(\"should not show tooltip if leave event occurs before delay expires\", function () {\n        var tooltip = $('<a href=\"#\" rel=\"tooltip\" title=\"Another tooltip\"></a>')\n          .appendTo('#qunit-fixture')\n          .tooltip({ delay: 100 })\n        stop()\n        tooltip.trigger('mouseenter')\n        setTimeout(function () {\n          ok(!$(\".tooltip\").is('.fade.in'), 'tooltip is not faded in')\n          tooltip.trigger('mouseout')\n          setTimeout(function () {\n            ok(!$(\".tooltip\").is('.fade.in'), 'tooltip is not faded in')\n            start()\n          }, 100)\n        }, 50)\n      })\n\n      test(\"should show tooltip if leave event hasn't occured before delay expires\", function () {\n        var tooltip = $('<a href=\"#\" rel=\"tooltip\" title=\"Another tooltip\"></a>')\n          .appendTo('#qunit-fixture')\n          .tooltip({ delay: 150 })\n        stop()\n        tooltip.trigger('mouseenter')\n        setTimeout(function () {\n          ok(!$(\".tooltip\").is('.fade.in'), 'tooltip is not faded in')\n        }, 100)\n        setTimeout(function () {\n          ok($(\".tooltip\").is('.fade.in'), 'tooltip has faded in')\n          start()\n        }, 200)\n      })\n\n      test(\"should destroy tooltip\", function () {\n        var tooltip = $('<div/>').tooltip().on('click.foo', function(){})\n        ok(tooltip.data('bs.tooltip'), 'tooltip has data')\n        ok($._data(tooltip[0], 'events').mouseover && $._data(tooltip[0], 'events').mouseout, 'tooltip has hover event')\n        ok($._data(tooltip[0], 'events').click[0].namespace == 'foo', 'tooltip has extra click.foo event')\n        tooltip.tooltip('show')\n        tooltip.tooltip('destroy')\n        ok(!tooltip.hasClass('in'), 'tooltip is hidden')\n        ok(!$._data(tooltip[0], 'bs.tooltip'), 'tooltip does not have data')\n        ok($._data(tooltip[0], 'events').click[0].namespace == 'foo', 'tooltip still has click.foo')\n        ok(!$._data(tooltip[0], 'events').mouseover && !$._data(tooltip[0], 'events').mouseout, 'tooltip does not have any events')\n      })\n\n      test(\"should show tooltip with delegate selector on click\", function () {\n        var div = $('<div><a href=\"#\" rel=\"tooltip\" title=\"Another tooltip\"></a></div>')\n        var tooltip = div.appendTo('#qunit-fixture')\n                         .tooltip({ selector: 'a[rel=tooltip]',\n                                    trigger: 'click' })\n        div.find('a').trigger('click')\n        ok($(\".tooltip\").is('.fade.in'), 'tooltip is faded in')\n      })\n\n      test(\"should show tooltip when toggle is called\", function () {\n        var tooltip = $('<a href=\"#\" rel=\"tooltip\" title=\"tooltip on toggle\"></a>')\n          .appendTo('#qunit-fixture')\n          .tooltip({trigger: 'manual'})\n          .tooltip('toggle')\n        ok($(\".tooltip\").is('.fade.in'), 'tooltip should be toggled in')\n      })\n\n      test(\"should place tooltips inside the body\", function () {\n        var tooltip = $('<a href=\"#\" rel=\"tooltip\" title=\"Another tooltip\"></a>')\n          .appendTo('#qunit-fixture')\n          .tooltip({container:'body'})\n          .tooltip('show')\n        ok($(\"body > .tooltip\").length, 'inside the body')\n        ok(!$(\"#qunit-fixture > .tooltip\").length, 'not found in parent')\n        tooltip.tooltip('hide')\n      })\n\n      test(\"should place tooltip inside window\", function(){\n        var container = $(\"<div />\").appendTo(\"body\")\n            .css({position: \"absolute\", width: 200, height: 200, bottom: 0, left: 0})\n          , tooltip = $(\"<a href='#' title='Very very very very very very very very long tooltip'>Hover me</a>\")\n          .css({position: \"absolute\", top:0, left: 0})\n          .appendTo(container)\n          .tooltip({placement: \"top\", animate: false})\n          .tooltip(\"show\")\n\n        stop()\n\n        setTimeout(function(){\n          ok($(\".tooltip\").offset().left >= 0)\n\n          start()\n          container.remove()\n        }, 100)\n      })\n\n      test(\"should place tooltip on top of element\", function(){\n        var container = $(\"<div />\").appendTo(\"body\")\n              .css({position: \"absolute\", bottom: 0, left: 0, textAlign: \"right\", width: 300, height: 300})\n            , p = $(\"<p style='margin-top:200px' />\").appendTo(container)\n            , tooltiped = $(\"<a href='#' title='very very very very very very very long tooltip'>Hover me</a>\")\n              .css({marginTop: 200})\n              .appendTo(p)\n              .tooltip({placement: \"top\", animate: false})\n              .tooltip(\"show\")\n\n        stop()\n\n        setTimeout(function(){\n          var tooltip = container.find(\".tooltip\")\n\n          start()\n          ok(tooltip.offset().top + tooltip.outerHeight() <= tooltiped.offset().top)\n          container.remove()\n        }, 100)\n      })\n\n      test(\"should add position class before positioning so that position-specific styles are taken into account\", function(){\n        $(\"head\").append('<style> .tooltip.right { white-space: nowrap; } .tooltip.right .tooltip-inner { max-width: none; } </style>')\n\n        var container = $(\"<div />\").appendTo(\"body\")\n          , target = $('<a href=\"#\" rel=\"tooltip\" title=\"very very very very very very very very long tooltip in one line\"></a>')\n              .appendTo(container)\n              .tooltip({placement: 'right'})\n              .tooltip('show')\n          , tooltip = container.find(\".tooltip\")\n\n        ok( Math.round(target.offset().top + target[0].offsetHeight/2 - tooltip[0].offsetHeight/2) === Math.round(tooltip.offset().top) )\n        target.tooltip('hide')\n      })\n\n      test(\"tooltip title test #1\", function () {\n        var tooltip = $('<a href=\"#\" rel=\"tooltip\" title=\"Simple tooltip\" style=\"display: inline-block; position: absolute; top: 0; left: 0;\"></a>')\n          .appendTo('#qunit-fixture')\n          .tooltip({\n          })\n          .tooltip('show')\n        equal($('.tooltip').children('.tooltip-inner').text(), 'Simple tooltip', 'title from title attribute is set')\n        tooltip.tooltip('hide')\n        ok(!$(\".tooltip\").length, 'tooltip removed')\n      })\n\n      test(\"tooltip title test #2\", function () {\n        var tooltip = $('<a href=\"#\" rel=\"tooltip\" title=\"Simple tooltip\" style=\"display: inline-block; position: absolute; top: 0; left: 0;\"></a>')\n          .appendTo('#qunit-fixture')\n          .tooltip({\n            title: 'This is a tooltip with some content'\n          })\n          .tooltip('show')\n        equal($('.tooltip').children('.tooltip-inner').text(), 'Simple tooltip', 'title is set from title attribute while prefered over title option')\n        tooltip.tooltip('hide')\n        ok(!$(\".tooltip\").length, 'tooltip removed')\n      })\n\n      test(\"tooltip title test #3\", function () {\n        var tooltip = $('<a href=\"#\" rel=\"tooltip\" style=\"display: inline-block; position: absolute; top: 0; left: 0;\"></a>')\n          .appendTo('#qunit-fixture')\n          .tooltip({\n            title: 'This is a tooltip with some content'\n          })\n          .tooltip('show')\n        equal($('.tooltip').children('.tooltip-inner').text(), 'This is a tooltip with some content', 'title from title option is set')\n        tooltip.tooltip('hide')\n        ok(!$(\".tooltip\").length, 'tooltip removed')\n      })\n\n      test(\"tooltips should be placed dynamically, with the dynamic placement option\", function () {\n        $.support.transition = false\n        var ttContainer = $('<div id=\"dynamic-tt-test\"/>').css({\n          'height' : 400\n          , 'overflow' : 'hidden'\n          , 'position' : 'absolute'\n          , 'top' : 0\n          , 'left' : 0\n          , 'width' : 600})\n          .appendTo('body')\n\n        var topTooltip = $('<div style=\"display: inline-block; position: absolute; left: 0; top: 0;\" rel=\"tooltip\" title=\"Top tooltip\">Top Dynamic Tooltip</div>')\n          .appendTo('#dynamic-tt-test')\n          .tooltip({placement: 'auto'})\n          .tooltip('show')\n\n\n        ok($(\".tooltip\").is('.bottom'),  'top positioned tooltip is dynamically positioned bottom')\n\n        topTooltip.tooltip('hide')\n\n        var rightTooltip = $('<div style=\"display: inline-block; position: absolute; right: 0;\" rel=\"tooltip\" title=\"Right tooltip\">Right Dynamic Tooltip</div>')\n          .appendTo('#dynamic-tt-test')\n          .tooltip({placement: 'right auto'})\n          .tooltip('show')\n\n        ok($(\".tooltip\").is('.left'),  'right positioned tooltip is dynamically positioned left')\n        rightTooltip.tooltip('hide')\n\n        var bottomTooltip = $('<div style=\"display: inline-block; position: absolute; bottom: 0;\" rel=\"tooltip\" title=\"Bottom tooltip\">Bottom Dynamic Tooltip</div>')\n          .appendTo('#dynamic-tt-test')\n          .tooltip({placement: 'auto bottom'})\n          .tooltip('show')\n\n        ok($(\".tooltip\").is('.top'),  'bottom positioned tooltip is dynamically positioned top')\n        bottomTooltip.tooltip('hide')\n\n        var leftTooltip = $('<div style=\"display: inline-block; position: absolute; left: 0;\" rel=\"tooltip\" title=\"Left tooltip\">Left Dynamic Tooltip</div>')\n          .appendTo('#dynamic-tt-test')\n          .tooltip({placement: 'auto left'})\n          .tooltip('show')\n\n        ok($(\".tooltip\").is('.right'),  'left positioned tooltip is dynamically positioned right')\n        leftTooltip.tooltip('hide')\n\n        ttContainer.remove()\n      })\n\n})\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/sass-bootstrap/js/tests/unit/transition.js",
    "content": "$(function () {\n\n    module(\"transition\")\n\n      test(\"should be defined on jquery support object\", function () {\n        ok($.support.transition !== undefined, 'transition object is defined')\n      })\n\n      test(\"should provide an end object\", function () {\n        ok($.support.transition ? $.support.transition.end : true, 'end string is defined')\n      })\n\n})\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/sass-bootstrap/js/tests/vendor/jquery.js",
    "content": "/*! jQuery v1.10.2 | (c) 2005, 2013 jQuery Foundation, Inc. | jquery.org/license\n//@ sourceMappingURL=jquery-1.10.2.min.map\n*/\n(function(e,t){var n,r,i=typeof t,o=e.location,a=e.document,s=a.documentElement,l=e.jQuery,u=e.$,c={},p=[],f=\"1.10.2\",d=p.concat,h=p.push,g=p.slice,m=p.indexOf,y=c.toString,v=c.hasOwnProperty,b=f.trim,x=function(e,t){return new x.fn.init(e,t,r)},w=/[+-]?(?:\\d*\\.|)\\d+(?:[eE][+-]?\\d+|)/.source,T=/\\S+/g,C=/^[\\s\\uFEFF\\xA0]+|[\\s\\uFEFF\\xA0]+$/g,N=/^(?:\\s*(<[\\w\\W]+>)[^>]*|#([\\w-]*))$/,k=/^<(\\w+)\\s*\\/?>(?:<\\/\\1>|)$/,E=/^[\\],:{}\\s]*$/,S=/(?:^|:|,)(?:\\s*\\[)+/g,A=/\\\\(?:[\"\\\\\\/bfnrt]|u[\\da-fA-F]{4})/g,j=/\"[^\"\\\\\\r\\n]*\"|true|false|null|-?(?:\\d+\\.|)\\d+(?:[eE][+-]?\\d+|)/g,D=/^-ms-/,L=/-([\\da-z])/gi,H=function(e,t){return t.toUpperCase()},q=function(e){(a.addEventListener||\"load\"===e.type||\"complete\"===a.readyState)&&(_(),x.ready())},_=function(){a.addEventListener?(a.removeEventListener(\"DOMContentLoaded\",q,!1),e.removeEventListener(\"load\",q,!1)):(a.detachEvent(\"onreadystatechange\",q),e.detachEvent(\"onload\",q))};x.fn=x.prototype={jquery:f,constructor:x,init:function(e,n,r){var i,o;if(!e)return this;if(\"string\"==typeof e){if(i=\"<\"===e.charAt(0)&&\">\"===e.charAt(e.length-1)&&e.length>=3?[null,e,null]:N.exec(e),!i||!i[1]&&n)return!n||n.jquery?(n||r).find(e):this.constructor(n).find(e);if(i[1]){if(n=n instanceof x?n[0]:n,x.merge(this,x.parseHTML(i[1],n&&n.nodeType?n.ownerDocument||n:a,!0)),k.test(i[1])&&x.isPlainObject(n))for(i in n)x.isFunction(this[i])?this[i](n[i]):this.attr(i,n[i]);return this}if(o=a.getElementById(i[2]),o&&o.parentNode){if(o.id!==i[2])return r.find(e);this.length=1,this[0]=o}return this.context=a,this.selector=e,this}return e.nodeType?(this.context=this[0]=e,this.length=1,this):x.isFunction(e)?r.ready(e):(e.selector!==t&&(this.selector=e.selector,this.context=e.context),x.makeArray(e,this))},selector:\"\",length:0,toArray:function(){return g.call(this)},get:function(e){return null==e?this.toArray():0>e?this[this.length+e]:this[e]},pushStack:function(e){var t=x.merge(this.constructor(),e);return t.prevObject=this,t.context=this.context,t},each:function(e,t){return x.each(this,e,t)},ready:function(e){return x.ready.promise().done(e),this},slice:function(){return this.pushStack(g.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(e){var t=this.length,n=+e+(0>e?t:0);return this.pushStack(n>=0&&t>n?[this[n]]:[])},map:function(e){return this.pushStack(x.map(this,function(t,n){return e.call(t,n,t)}))},end:function(){return this.prevObject||this.constructor(null)},push:h,sort:[].sort,splice:[].splice},x.fn.init.prototype=x.fn,x.extend=x.fn.extend=function(){var e,n,r,i,o,a,s=arguments[0]||{},l=1,u=arguments.length,c=!1;for(\"boolean\"==typeof s&&(c=s,s=arguments[1]||{},l=2),\"object\"==typeof s||x.isFunction(s)||(s={}),u===l&&(s=this,--l);u>l;l++)if(null!=(o=arguments[l]))for(i in o)e=s[i],r=o[i],s!==r&&(c&&r&&(x.isPlainObject(r)||(n=x.isArray(r)))?(n?(n=!1,a=e&&x.isArray(e)?e:[]):a=e&&x.isPlainObject(e)?e:{},s[i]=x.extend(c,a,r)):r!==t&&(s[i]=r));return s},x.extend({expando:\"jQuery\"+(f+Math.random()).replace(/\\D/g,\"\"),noConflict:function(t){return e.$===x&&(e.$=u),t&&e.jQuery===x&&(e.jQuery=l),x},isReady:!1,readyWait:1,holdReady:function(e){e?x.readyWait++:x.ready(!0)},ready:function(e){if(e===!0?!--x.readyWait:!x.isReady){if(!a.body)return setTimeout(x.ready);x.isReady=!0,e!==!0&&--x.readyWait>0||(n.resolveWith(a,[x]),x.fn.trigger&&x(a).trigger(\"ready\").off(\"ready\"))}},isFunction:function(e){return\"function\"===x.type(e)},isArray:Array.isArray||function(e){return\"array\"===x.type(e)},isWindow:function(e){return null!=e&&e==e.window},isNumeric:function(e){return!isNaN(parseFloat(e))&&isFinite(e)},type:function(e){return null==e?e+\"\":\"object\"==typeof e||\"function\"==typeof e?c[y.call(e)]||\"object\":typeof e},isPlainObject:function(e){var n;if(!e||\"object\"!==x.type(e)||e.nodeType||x.isWindow(e))return!1;try{if(e.constructor&&!v.call(e,\"constructor\")&&!v.call(e.constructor.prototype,\"isPrototypeOf\"))return!1}catch(r){return!1}if(x.support.ownLast)for(n in e)return v.call(e,n);for(n in e);return n===t||v.call(e,n)},isEmptyObject:function(e){var t;for(t in e)return!1;return!0},error:function(e){throw Error(e)},parseHTML:function(e,t,n){if(!e||\"string\"!=typeof e)return null;\"boolean\"==typeof t&&(n=t,t=!1),t=t||a;var r=k.exec(e),i=!n&&[];return r?[t.createElement(r[1])]:(r=x.buildFragment([e],t,i),i&&x(i).remove(),x.merge([],r.childNodes))},parseJSON:function(n){return e.JSON&&e.JSON.parse?e.JSON.parse(n):null===n?n:\"string\"==typeof n&&(n=x.trim(n),n&&E.test(n.replace(A,\"@\").replace(j,\"]\").replace(S,\"\")))?Function(\"return \"+n)():(x.error(\"Invalid JSON: \"+n),t)},parseXML:function(n){var r,i;if(!n||\"string\"!=typeof n)return null;try{e.DOMParser?(i=new DOMParser,r=i.parseFromString(n,\"text/xml\")):(r=new ActiveXObject(\"Microsoft.XMLDOM\"),r.async=\"false\",r.loadXML(n))}catch(o){r=t}return r&&r.documentElement&&!r.getElementsByTagName(\"parsererror\").length||x.error(\"Invalid XML: \"+n),r},noop:function(){},globalEval:function(t){t&&x.trim(t)&&(e.execScript||function(t){e.eval.call(e,t)})(t)},camelCase:function(e){return e.replace(D,\"ms-\").replace(L,H)},nodeName:function(e,t){return e.nodeName&&e.nodeName.toLowerCase()===t.toLowerCase()},each:function(e,t,n){var r,i=0,o=e.length,a=M(e);if(n){if(a){for(;o>i;i++)if(r=t.apply(e[i],n),r===!1)break}else for(i in e)if(r=t.apply(e[i],n),r===!1)break}else if(a){for(;o>i;i++)if(r=t.call(e[i],i,e[i]),r===!1)break}else for(i in e)if(r=t.call(e[i],i,e[i]),r===!1)break;return e},trim:b&&!b.call(\"\\ufeff\\u00a0\")?function(e){return null==e?\"\":b.call(e)}:function(e){return null==e?\"\":(e+\"\").replace(C,\"\")},makeArray:function(e,t){var n=t||[];return null!=e&&(M(Object(e))?x.merge(n,\"string\"==typeof e?[e]:e):h.call(n,e)),n},inArray:function(e,t,n){var r;if(t){if(m)return m.call(t,e,n);for(r=t.length,n=n?0>n?Math.max(0,r+n):n:0;r>n;n++)if(n in t&&t[n]===e)return n}return-1},merge:function(e,n){var r=n.length,i=e.length,o=0;if(\"number\"==typeof r)for(;r>o;o++)e[i++]=n[o];else while(n[o]!==t)e[i++]=n[o++];return e.length=i,e},grep:function(e,t,n){var r,i=[],o=0,a=e.length;for(n=!!n;a>o;o++)r=!!t(e[o],o),n!==r&&i.push(e[o]);return i},map:function(e,t,n){var r,i=0,o=e.length,a=M(e),s=[];if(a)for(;o>i;i++)r=t(e[i],i,n),null!=r&&(s[s.length]=r);else for(i in e)r=t(e[i],i,n),null!=r&&(s[s.length]=r);return d.apply([],s)},guid:1,proxy:function(e,n){var r,i,o;return\"string\"==typeof n&&(o=e[n],n=e,e=o),x.isFunction(e)?(r=g.call(arguments,2),i=function(){return e.apply(n||this,r.concat(g.call(arguments)))},i.guid=e.guid=e.guid||x.guid++,i):t},access:function(e,n,r,i,o,a,s){var l=0,u=e.length,c=null==r;if(\"object\"===x.type(r)){o=!0;for(l in r)x.access(e,n,l,r[l],!0,a,s)}else if(i!==t&&(o=!0,x.isFunction(i)||(s=!0),c&&(s?(n.call(e,i),n=null):(c=n,n=function(e,t,n){return c.call(x(e),n)})),n))for(;u>l;l++)n(e[l],r,s?i:i.call(e[l],l,n(e[l],r)));return o?e:c?n.call(e):u?n(e[0],r):a},now:function(){return(new Date).getTime()},swap:function(e,t,n,r){var i,o,a={};for(o in t)a[o]=e.style[o],e.style[o]=t[o];i=n.apply(e,r||[]);for(o in t)e.style[o]=a[o];return i}}),x.ready.promise=function(t){if(!n)if(n=x.Deferred(),\"complete\"===a.readyState)setTimeout(x.ready);else if(a.addEventListener)a.addEventListener(\"DOMContentLoaded\",q,!1),e.addEventListener(\"load\",q,!1);else{a.attachEvent(\"onreadystatechange\",q),e.attachEvent(\"onload\",q);var r=!1;try{r=null==e.frameElement&&a.documentElement}catch(i){}r&&r.doScroll&&function o(){if(!x.isReady){try{r.doScroll(\"left\")}catch(e){return setTimeout(o,50)}_(),x.ready()}}()}return n.promise(t)},x.each(\"Boolean Number String Function Array Date RegExp Object Error\".split(\" \"),function(e,t){c[\"[object \"+t+\"]\"]=t.toLowerCase()});function M(e){var t=e.length,n=x.type(e);return x.isWindow(e)?!1:1===e.nodeType&&t?!0:\"array\"===n||\"function\"!==n&&(0===t||\"number\"==typeof t&&t>0&&t-1 in e)}r=x(a),function(e,t){var n,r,i,o,a,s,l,u,c,p,f,d,h,g,m,y,v,b=\"sizzle\"+-new Date,w=e.document,T=0,C=0,N=st(),k=st(),E=st(),S=!1,A=function(e,t){return e===t?(S=!0,0):0},j=typeof t,D=1<<31,L={}.hasOwnProperty,H=[],q=H.pop,_=H.push,M=H.push,O=H.slice,F=H.indexOf||function(e){var t=0,n=this.length;for(;n>t;t++)if(this[t]===e)return t;return-1},B=\"checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped\",P=\"[\\\\x20\\\\t\\\\r\\\\n\\\\f]\",R=\"(?:\\\\\\\\.|[\\\\w-]|[^\\\\x00-\\\\xa0])+\",W=R.replace(\"w\",\"w#\"),$=\"\\\\[\"+P+\"*(\"+R+\")\"+P+\"*(?:([*^$|!~]?=)\"+P+\"*(?:(['\\\"])((?:\\\\\\\\.|[^\\\\\\\\])*?)\\\\3|(\"+W+\")|)|)\"+P+\"*\\\\]\",I=\":(\"+R+\")(?:\\\\(((['\\\"])((?:\\\\\\\\.|[^\\\\\\\\])*?)\\\\3|((?:\\\\\\\\.|[^\\\\\\\\()[\\\\]]|\"+$.replace(3,8)+\")*)|.*)\\\\)|)\",z=RegExp(\"^\"+P+\"+|((?:^|[^\\\\\\\\])(?:\\\\\\\\.)*)\"+P+\"+$\",\"g\"),X=RegExp(\"^\"+P+\"*,\"+P+\"*\"),U=RegExp(\"^\"+P+\"*([>+~]|\"+P+\")\"+P+\"*\"),V=RegExp(P+\"*[+~]\"),Y=RegExp(\"=\"+P+\"*([^\\\\]'\\\"]*)\"+P+\"*\\\\]\",\"g\"),J=RegExp(I),G=RegExp(\"^\"+W+\"$\"),Q={ID:RegExp(\"^#(\"+R+\")\"),CLASS:RegExp(\"^\\\\.(\"+R+\")\"),TAG:RegExp(\"^(\"+R.replace(\"w\",\"w*\")+\")\"),ATTR:RegExp(\"^\"+$),PSEUDO:RegExp(\"^\"+I),CHILD:RegExp(\"^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\\\(\"+P+\"*(even|odd|(([+-]|)(\\\\d*)n|)\"+P+\"*(?:([+-]|)\"+P+\"*(\\\\d+)|))\"+P+\"*\\\\)|)\",\"i\"),bool:RegExp(\"^(?:\"+B+\")$\",\"i\"),needsContext:RegExp(\"^\"+P+\"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\\\(\"+P+\"*((?:-\\\\d)?\\\\d*)\"+P+\"*\\\\)|)(?=[^-]|$)\",\"i\")},K=/^[^{]+\\{\\s*\\[native \\w/,Z=/^(?:#([\\w-]+)|(\\w+)|\\.([\\w-]+))$/,et=/^(?:input|select|textarea|button)$/i,tt=/^h\\d$/i,nt=/'|\\\\/g,rt=RegExp(\"\\\\\\\\([\\\\da-f]{1,6}\"+P+\"?|(\"+P+\")|.)\",\"ig\"),it=function(e,t,n){var r=\"0x\"+t-65536;return r!==r||n?t:0>r?String.fromCharCode(r+65536):String.fromCharCode(55296|r>>10,56320|1023&r)};try{M.apply(H=O.call(w.childNodes),w.childNodes),H[w.childNodes.length].nodeType}catch(ot){M={apply:H.length?function(e,t){_.apply(e,O.call(t))}:function(e,t){var n=e.length,r=0;while(e[n++]=t[r++]);e.length=n-1}}}function at(e,t,n,i){var o,a,s,l,u,c,d,m,y,x;if((t?t.ownerDocument||t:w)!==f&&p(t),t=t||f,n=n||[],!e||\"string\"!=typeof e)return n;if(1!==(l=t.nodeType)&&9!==l)return[];if(h&&!i){if(o=Z.exec(e))if(s=o[1]){if(9===l){if(a=t.getElementById(s),!a||!a.parentNode)return n;if(a.id===s)return n.push(a),n}else if(t.ownerDocument&&(a=t.ownerDocument.getElementById(s))&&v(t,a)&&a.id===s)return n.push(a),n}else{if(o[2])return M.apply(n,t.getElementsByTagName(e)),n;if((s=o[3])&&r.getElementsByClassName&&t.getElementsByClassName)return M.apply(n,t.getElementsByClassName(s)),n}if(r.qsa&&(!g||!g.test(e))){if(m=d=b,y=t,x=9===l&&e,1===l&&\"object\"!==t.nodeName.toLowerCase()){c=mt(e),(d=t.getAttribute(\"id\"))?m=d.replace(nt,\"\\\\$&\"):t.setAttribute(\"id\",m),m=\"[id='\"+m+\"'] \",u=c.length;while(u--)c[u]=m+yt(c[u]);y=V.test(e)&&t.parentNode||t,x=c.join(\",\")}if(x)try{return M.apply(n,y.querySelectorAll(x)),n}catch(T){}finally{d||t.removeAttribute(\"id\")}}}return kt(e.replace(z,\"$1\"),t,n,i)}function st(){var e=[];function t(n,r){return e.push(n+=\" \")>o.cacheLength&&delete t[e.shift()],t[n]=r}return t}function lt(e){return e[b]=!0,e}function ut(e){var t=f.createElement(\"div\");try{return!!e(t)}catch(n){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function ct(e,t){var n=e.split(\"|\"),r=e.length;while(r--)o.attrHandle[n[r]]=t}function pt(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&(~t.sourceIndex||D)-(~e.sourceIndex||D);if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function ft(e){return function(t){var n=t.nodeName.toLowerCase();return\"input\"===n&&t.type===e}}function dt(e){return function(t){var n=t.nodeName.toLowerCase();return(\"input\"===n||\"button\"===n)&&t.type===e}}function ht(e){return lt(function(t){return t=+t,lt(function(n,r){var i,o=e([],n.length,t),a=o.length;while(a--)n[i=o[a]]&&(n[i]=!(r[i]=n[i]))})})}s=at.isXML=function(e){var t=e&&(e.ownerDocument||e).documentElement;return t?\"HTML\"!==t.nodeName:!1},r=at.support={},p=at.setDocument=function(e){var n=e?e.ownerDocument||e:w,i=n.defaultView;return n!==f&&9===n.nodeType&&n.documentElement?(f=n,d=n.documentElement,h=!s(n),i&&i.attachEvent&&i!==i.top&&i.attachEvent(\"onbeforeunload\",function(){p()}),r.attributes=ut(function(e){return e.className=\"i\",!e.getAttribute(\"className\")}),r.getElementsByTagName=ut(function(e){return e.appendChild(n.createComment(\"\")),!e.getElementsByTagName(\"*\").length}),r.getElementsByClassName=ut(function(e){return e.innerHTML=\"<div class='a'></div><div class='a i'></div>\",e.firstChild.className=\"i\",2===e.getElementsByClassName(\"i\").length}),r.getById=ut(function(e){return d.appendChild(e).id=b,!n.getElementsByName||!n.getElementsByName(b).length}),r.getById?(o.find.ID=function(e,t){if(typeof t.getElementById!==j&&h){var n=t.getElementById(e);return n&&n.parentNode?[n]:[]}},o.filter.ID=function(e){var t=e.replace(rt,it);return function(e){return e.getAttribute(\"id\")===t}}):(delete o.find.ID,o.filter.ID=function(e){var t=e.replace(rt,it);return function(e){var n=typeof e.getAttributeNode!==j&&e.getAttributeNode(\"id\");return n&&n.value===t}}),o.find.TAG=r.getElementsByTagName?function(e,n){return typeof n.getElementsByTagName!==j?n.getElementsByTagName(e):t}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if(\"*\"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},o.find.CLASS=r.getElementsByClassName&&function(e,n){return typeof n.getElementsByClassName!==j&&h?n.getElementsByClassName(e):t},m=[],g=[],(r.qsa=K.test(n.querySelectorAll))&&(ut(function(e){e.innerHTML=\"<select><option selected=''></option></select>\",e.querySelectorAll(\"[selected]\").length||g.push(\"\\\\[\"+P+\"*(?:value|\"+B+\")\"),e.querySelectorAll(\":checked\").length||g.push(\":checked\")}),ut(function(e){var t=n.createElement(\"input\");t.setAttribute(\"type\",\"hidden\"),e.appendChild(t).setAttribute(\"t\",\"\"),e.querySelectorAll(\"[t^='']\").length&&g.push(\"[*^$]=\"+P+\"*(?:''|\\\"\\\")\"),e.querySelectorAll(\":enabled\").length||g.push(\":enabled\",\":disabled\"),e.querySelectorAll(\"*,:x\"),g.push(\",.*:\")})),(r.matchesSelector=K.test(y=d.webkitMatchesSelector||d.mozMatchesSelector||d.oMatchesSelector||d.msMatchesSelector))&&ut(function(e){r.disconnectedMatch=y.call(e,\"div\"),y.call(e,\"[s!='']:x\"),m.push(\"!=\",I)}),g=g.length&&RegExp(g.join(\"|\")),m=m.length&&RegExp(m.join(\"|\")),v=K.test(d.contains)||d.compareDocumentPosition?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},A=d.compareDocumentPosition?function(e,t){if(e===t)return S=!0,0;var i=t.compareDocumentPosition&&e.compareDocumentPosition&&e.compareDocumentPosition(t);return i?1&i||!r.sortDetached&&t.compareDocumentPosition(e)===i?e===n||v(w,e)?-1:t===n||v(w,t)?1:c?F.call(c,e)-F.call(c,t):0:4&i?-1:1:e.compareDocumentPosition?-1:1}:function(e,t){var r,i=0,o=e.parentNode,a=t.parentNode,s=[e],l=[t];if(e===t)return S=!0,0;if(!o||!a)return e===n?-1:t===n?1:o?-1:a?1:c?F.call(c,e)-F.call(c,t):0;if(o===a)return pt(e,t);r=e;while(r=r.parentNode)s.unshift(r);r=t;while(r=r.parentNode)l.unshift(r);while(s[i]===l[i])i++;return i?pt(s[i],l[i]):s[i]===w?-1:l[i]===w?1:0},n):f},at.matches=function(e,t){return at(e,null,null,t)},at.matchesSelector=function(e,t){if((e.ownerDocument||e)!==f&&p(e),t=t.replace(Y,\"='$1']\"),!(!r.matchesSelector||!h||m&&m.test(t)||g&&g.test(t)))try{var n=y.call(e,t);if(n||r.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(i){}return at(t,f,null,[e]).length>0},at.contains=function(e,t){return(e.ownerDocument||e)!==f&&p(e),v(e,t)},at.attr=function(e,n){(e.ownerDocument||e)!==f&&p(e);var i=o.attrHandle[n.toLowerCase()],a=i&&L.call(o.attrHandle,n.toLowerCase())?i(e,n,!h):t;return a===t?r.attributes||!h?e.getAttribute(n):(a=e.getAttributeNode(n))&&a.specified?a.value:null:a},at.error=function(e){throw Error(\"Syntax error, unrecognized expression: \"+e)},at.uniqueSort=function(e){var t,n=[],i=0,o=0;if(S=!r.detectDuplicates,c=!r.sortStable&&e.slice(0),e.sort(A),S){while(t=e[o++])t===e[o]&&(i=n.push(o));while(i--)e.splice(n[i],1)}return e},a=at.getText=function(e){var t,n=\"\",r=0,i=e.nodeType;if(i){if(1===i||9===i||11===i){if(\"string\"==typeof e.textContent)return e.textContent;for(e=e.firstChild;e;e=e.nextSibling)n+=a(e)}else if(3===i||4===i)return e.nodeValue}else for(;t=e[r];r++)n+=a(t);return n},o=at.selectors={cacheLength:50,createPseudo:lt,match:Q,attrHandle:{},find:{},relative:{\">\":{dir:\"parentNode\",first:!0},\" \":{dir:\"parentNode\"},\"+\":{dir:\"previousSibling\",first:!0},\"~\":{dir:\"previousSibling\"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(rt,it),e[3]=(e[4]||e[5]||\"\").replace(rt,it),\"~=\"===e[2]&&(e[3]=\" \"+e[3]+\" \"),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),\"nth\"===e[1].slice(0,3)?(e[3]||at.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*(\"even\"===e[3]||\"odd\"===e[3])),e[5]=+(e[7]+e[8]||\"odd\"===e[3])):e[3]&&at.error(e[0]),e},PSEUDO:function(e){var n,r=!e[5]&&e[2];return Q.CHILD.test(e[0])?null:(e[3]&&e[4]!==t?e[2]=e[4]:r&&J.test(r)&&(n=mt(r,!0))&&(n=r.indexOf(\")\",r.length-n)-r.length)&&(e[0]=e[0].slice(0,n),e[2]=r.slice(0,n)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(rt,it).toLowerCase();return\"*\"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=N[e+\" \"];return t||(t=RegExp(\"(^|\"+P+\")\"+e+\"(\"+P+\"|$)\"))&&N(e,function(e){return t.test(\"string\"==typeof e.className&&e.className||typeof e.getAttribute!==j&&e.getAttribute(\"class\")||\"\")})},ATTR:function(e,t,n){return function(r){var i=at.attr(r,e);return null==i?\"!=\"===t:t?(i+=\"\",\"=\"===t?i===n:\"!=\"===t?i!==n:\"^=\"===t?n&&0===i.indexOf(n):\"*=\"===t?n&&i.indexOf(n)>-1:\"$=\"===t?n&&i.slice(-n.length)===n:\"~=\"===t?(\" \"+i+\" \").indexOf(n)>-1:\"|=\"===t?i===n||i.slice(0,n.length+1)===n+\"-\":!1):!0}},CHILD:function(e,t,n,r,i){var o=\"nth\"!==e.slice(0,3),a=\"last\"!==e.slice(-4),s=\"of-type\"===t;return 1===r&&0===i?function(e){return!!e.parentNode}:function(t,n,l){var u,c,p,f,d,h,g=o!==a?\"nextSibling\":\"previousSibling\",m=t.parentNode,y=s&&t.nodeName.toLowerCase(),v=!l&&!s;if(m){if(o){while(g){p=t;while(p=p[g])if(s?p.nodeName.toLowerCase()===y:1===p.nodeType)return!1;h=g=\"only\"===e&&!h&&\"nextSibling\"}return!0}if(h=[a?m.firstChild:m.lastChild],a&&v){c=m[b]||(m[b]={}),u=c[e]||[],d=u[0]===T&&u[1],f=u[0]===T&&u[2],p=d&&m.childNodes[d];while(p=++d&&p&&p[g]||(f=d=0)||h.pop())if(1===p.nodeType&&++f&&p===t){c[e]=[T,d,f];break}}else if(v&&(u=(t[b]||(t[b]={}))[e])&&u[0]===T)f=u[1];else while(p=++d&&p&&p[g]||(f=d=0)||h.pop())if((s?p.nodeName.toLowerCase()===y:1===p.nodeType)&&++f&&(v&&((p[b]||(p[b]={}))[e]=[T,f]),p===t))break;return f-=i,f===r||0===f%r&&f/r>=0}}},PSEUDO:function(e,t){var n,r=o.pseudos[e]||o.setFilters[e.toLowerCase()]||at.error(\"unsupported pseudo: \"+e);return r[b]?r(t):r.length>1?(n=[e,e,\"\",t],o.setFilters.hasOwnProperty(e.toLowerCase())?lt(function(e,n){var i,o=r(e,t),a=o.length;while(a--)i=F.call(e,o[a]),e[i]=!(n[i]=o[a])}):function(e){return r(e,0,n)}):r}},pseudos:{not:lt(function(e){var t=[],n=[],r=l(e.replace(z,\"$1\"));return r[b]?lt(function(e,t,n,i){var o,a=r(e,null,i,[]),s=e.length;while(s--)(o=a[s])&&(e[s]=!(t[s]=o))}):function(e,i,o){return t[0]=e,r(t,null,o,n),!n.pop()}}),has:lt(function(e){return function(t){return at(e,t).length>0}}),contains:lt(function(e){return function(t){return(t.textContent||t.innerText||a(t)).indexOf(e)>-1}}),lang:lt(function(e){return G.test(e||\"\")||at.error(\"unsupported lang: \"+e),e=e.replace(rt,it).toLowerCase(),function(t){var n;do if(n=h?t.lang:t.getAttribute(\"xml:lang\")||t.getAttribute(\"lang\"))return n=n.toLowerCase(),n===e||0===n.indexOf(e+\"-\");while((t=t.parentNode)&&1===t.nodeType);return!1}}),target:function(t){var n=e.location&&e.location.hash;return n&&n.slice(1)===t.id},root:function(e){return e===d},focus:function(e){return e===f.activeElement&&(!f.hasFocus||f.hasFocus())&&!!(e.type||e.href||~e.tabIndex)},enabled:function(e){return e.disabled===!1},disabled:function(e){return e.disabled===!0},checked:function(e){var t=e.nodeName.toLowerCase();return\"input\"===t&&!!e.checked||\"option\"===t&&!!e.selected},selected:function(e){return e.parentNode&&e.parentNode.selectedIndex,e.selected===!0},empty:function(e){for(e=e.firstChild;e;e=e.nextSibling)if(e.nodeName>\"@\"||3===e.nodeType||4===e.nodeType)return!1;return!0},parent:function(e){return!o.pseudos.empty(e)},header:function(e){return tt.test(e.nodeName)},input:function(e){return et.test(e.nodeName)},button:function(e){var t=e.nodeName.toLowerCase();return\"input\"===t&&\"button\"===e.type||\"button\"===t},text:function(e){var t;return\"input\"===e.nodeName.toLowerCase()&&\"text\"===e.type&&(null==(t=e.getAttribute(\"type\"))||t.toLowerCase()===e.type)},first:ht(function(){return[0]}),last:ht(function(e,t){return[t-1]}),eq:ht(function(e,t,n){return[0>n?n+t:n]}),even:ht(function(e,t){var n=0;for(;t>n;n+=2)e.push(n);return e}),odd:ht(function(e,t){var n=1;for(;t>n;n+=2)e.push(n);return e}),lt:ht(function(e,t,n){var r=0>n?n+t:n;for(;--r>=0;)e.push(r);return e}),gt:ht(function(e,t,n){var r=0>n?n+t:n;for(;t>++r;)e.push(r);return e})}},o.pseudos.nth=o.pseudos.eq;for(n in{radio:!0,checkbox:!0,file:!0,password:!0,image:!0})o.pseudos[n]=ft(n);for(n in{submit:!0,reset:!0})o.pseudos[n]=dt(n);function gt(){}gt.prototype=o.filters=o.pseudos,o.setFilters=new gt;function mt(e,t){var n,r,i,a,s,l,u,c=k[e+\" \"];if(c)return t?0:c.slice(0);s=e,l=[],u=o.preFilter;while(s){(!n||(r=X.exec(s)))&&(r&&(s=s.slice(r[0].length)||s),l.push(i=[])),n=!1,(r=U.exec(s))&&(n=r.shift(),i.push({value:n,type:r[0].replace(z,\" \")}),s=s.slice(n.length));for(a in o.filter)!(r=Q[a].exec(s))||u[a]&&!(r=u[a](r))||(n=r.shift(),i.push({value:n,type:a,matches:r}),s=s.slice(n.length));if(!n)break}return t?s.length:s?at.error(e):k(e,l).slice(0)}function yt(e){var t=0,n=e.length,r=\"\";for(;n>t;t++)r+=e[t].value;return r}function vt(e,t,n){var r=t.dir,o=n&&\"parentNode\"===r,a=C++;return t.first?function(t,n,i){while(t=t[r])if(1===t.nodeType||o)return e(t,n,i)}:function(t,n,s){var l,u,c,p=T+\" \"+a;if(s){while(t=t[r])if((1===t.nodeType||o)&&e(t,n,s))return!0}else while(t=t[r])if(1===t.nodeType||o)if(c=t[b]||(t[b]={}),(u=c[r])&&u[0]===p){if((l=u[1])===!0||l===i)return l===!0}else if(u=c[r]=[p],u[1]=e(t,n,s)||i,u[1]===!0)return!0}}function bt(e){return e.length>1?function(t,n,r){var i=e.length;while(i--)if(!e[i](t,n,r))return!1;return!0}:e[0]}function xt(e,t,n,r,i){var o,a=[],s=0,l=e.length,u=null!=t;for(;l>s;s++)(o=e[s])&&(!n||n(o,r,i))&&(a.push(o),u&&t.push(s));return a}function wt(e,t,n,r,i,o){return r&&!r[b]&&(r=wt(r)),i&&!i[b]&&(i=wt(i,o)),lt(function(o,a,s,l){var u,c,p,f=[],d=[],h=a.length,g=o||Nt(t||\"*\",s.nodeType?[s]:s,[]),m=!e||!o&&t?g:xt(g,f,e,s,l),y=n?i||(o?e:h||r)?[]:a:m;if(n&&n(m,y,s,l),r){u=xt(y,d),r(u,[],s,l),c=u.length;while(c--)(p=u[c])&&(y[d[c]]=!(m[d[c]]=p))}if(o){if(i||e){if(i){u=[],c=y.length;while(c--)(p=y[c])&&u.push(m[c]=p);i(null,y=[],u,l)}c=y.length;while(c--)(p=y[c])&&(u=i?F.call(o,p):f[c])>-1&&(o[u]=!(a[u]=p))}}else y=xt(y===a?y.splice(h,y.length):y),i?i(null,a,y,l):M.apply(a,y)})}function Tt(e){var t,n,r,i=e.length,a=o.relative[e[0].type],s=a||o.relative[\" \"],l=a?1:0,c=vt(function(e){return e===t},s,!0),p=vt(function(e){return F.call(t,e)>-1},s,!0),f=[function(e,n,r){return!a&&(r||n!==u)||((t=n).nodeType?c(e,n,r):p(e,n,r))}];for(;i>l;l++)if(n=o.relative[e[l].type])f=[vt(bt(f),n)];else{if(n=o.filter[e[l].type].apply(null,e[l].matches),n[b]){for(r=++l;i>r;r++)if(o.relative[e[r].type])break;return wt(l>1&&bt(f),l>1&&yt(e.slice(0,l-1).concat({value:\" \"===e[l-2].type?\"*\":\"\"})).replace(z,\"$1\"),n,r>l&&Tt(e.slice(l,r)),i>r&&Tt(e=e.slice(r)),i>r&&yt(e))}f.push(n)}return bt(f)}function Ct(e,t){var n=0,r=t.length>0,a=e.length>0,s=function(s,l,c,p,d){var h,g,m,y=[],v=0,b=\"0\",x=s&&[],w=null!=d,C=u,N=s||a&&o.find.TAG(\"*\",d&&l.parentNode||l),k=T+=null==C?1:Math.random()||.1;for(w&&(u=l!==f&&l,i=n);null!=(h=N[b]);b++){if(a&&h){g=0;while(m=e[g++])if(m(h,l,c)){p.push(h);break}w&&(T=k,i=++n)}r&&((h=!m&&h)&&v--,s&&x.push(h))}if(v+=b,r&&b!==v){g=0;while(m=t[g++])m(x,y,l,c);if(s){if(v>0)while(b--)x[b]||y[b]||(y[b]=q.call(p));y=xt(y)}M.apply(p,y),w&&!s&&y.length>0&&v+t.length>1&&at.uniqueSort(p)}return w&&(T=k,u=C),x};return r?lt(s):s}l=at.compile=function(e,t){var n,r=[],i=[],o=E[e+\" \"];if(!o){t||(t=mt(e)),n=t.length;while(n--)o=Tt(t[n]),o[b]?r.push(o):i.push(o);o=E(e,Ct(i,r))}return o};function Nt(e,t,n){var r=0,i=t.length;for(;i>r;r++)at(e,t[r],n);return n}function kt(e,t,n,i){var a,s,u,c,p,f=mt(e);if(!i&&1===f.length){if(s=f[0]=f[0].slice(0),s.length>2&&\"ID\"===(u=s[0]).type&&r.getById&&9===t.nodeType&&h&&o.relative[s[1].type]){if(t=(o.find.ID(u.matches[0].replace(rt,it),t)||[])[0],!t)return n;e=e.slice(s.shift().value.length)}a=Q.needsContext.test(e)?0:s.length;while(a--){if(u=s[a],o.relative[c=u.type])break;if((p=o.find[c])&&(i=p(u.matches[0].replace(rt,it),V.test(s[0].type)&&t.parentNode||t))){if(s.splice(a,1),e=i.length&&yt(s),!e)return M.apply(n,i),n;break}}}return l(e,f)(i,t,!h,n,V.test(e)),n}r.sortStable=b.split(\"\").sort(A).join(\"\")===b,r.detectDuplicates=S,p(),r.sortDetached=ut(function(e){return 1&e.compareDocumentPosition(f.createElement(\"div\"))}),ut(function(e){return e.innerHTML=\"<a href='#'></a>\",\"#\"===e.firstChild.getAttribute(\"href\")})||ct(\"type|href|height|width\",function(e,n,r){return r?t:e.getAttribute(n,\"type\"===n.toLowerCase()?1:2)}),r.attributes&&ut(function(e){return e.innerHTML=\"<input/>\",e.firstChild.setAttribute(\"value\",\"\"),\"\"===e.firstChild.getAttribute(\"value\")})||ct(\"value\",function(e,n,r){return r||\"input\"!==e.nodeName.toLowerCase()?t:e.defaultValue}),ut(function(e){return null==e.getAttribute(\"disabled\")})||ct(B,function(e,n,r){var i;return r?t:(i=e.getAttributeNode(n))&&i.specified?i.value:e[n]===!0?n.toLowerCase():null}),x.find=at,x.expr=at.selectors,x.expr[\":\"]=x.expr.pseudos,x.unique=at.uniqueSort,x.text=at.getText,x.isXMLDoc=at.isXML,x.contains=at.contains}(e);var O={};function F(e){var t=O[e]={};return x.each(e.match(T)||[],function(e,n){t[n]=!0}),t}x.Callbacks=function(e){e=\"string\"==typeof e?O[e]||F(e):x.extend({},e);var n,r,i,o,a,s,l=[],u=!e.once&&[],c=function(t){for(r=e.memory&&t,i=!0,a=s||0,s=0,o=l.length,n=!0;l&&o>a;a++)if(l[a].apply(t[0],t[1])===!1&&e.stopOnFalse){r=!1;break}n=!1,l&&(u?u.length&&c(u.shift()):r?l=[]:p.disable())},p={add:function(){if(l){var t=l.length;(function i(t){x.each(t,function(t,n){var r=x.type(n);\"function\"===r?e.unique&&p.has(n)||l.push(n):n&&n.length&&\"string\"!==r&&i(n)})})(arguments),n?o=l.length:r&&(s=t,c(r))}return this},remove:function(){return l&&x.each(arguments,function(e,t){var r;while((r=x.inArray(t,l,r))>-1)l.splice(r,1),n&&(o>=r&&o--,a>=r&&a--)}),this},has:function(e){return e?x.inArray(e,l)>-1:!(!l||!l.length)},empty:function(){return l=[],o=0,this},disable:function(){return l=u=r=t,this},disabled:function(){return!l},lock:function(){return u=t,r||p.disable(),this},locked:function(){return!u},fireWith:function(e,t){return!l||i&&!u||(t=t||[],t=[e,t.slice?t.slice():t],n?u.push(t):c(t)),this},fire:function(){return p.fireWith(this,arguments),this},fired:function(){return!!i}};return p},x.extend({Deferred:function(e){var t=[[\"resolve\",\"done\",x.Callbacks(\"once memory\"),\"resolved\"],[\"reject\",\"fail\",x.Callbacks(\"once memory\"),\"rejected\"],[\"notify\",\"progress\",x.Callbacks(\"memory\")]],n=\"pending\",r={state:function(){return n},always:function(){return i.done(arguments).fail(arguments),this},then:function(){var e=arguments;return x.Deferred(function(n){x.each(t,function(t,o){var a=o[0],s=x.isFunction(e[t])&&e[t];i[o[1]](function(){var e=s&&s.apply(this,arguments);e&&x.isFunction(e.promise)?e.promise().done(n.resolve).fail(n.reject).progress(n.notify):n[a+\"With\"](this===r?n.promise():this,s?[e]:arguments)})}),e=null}).promise()},promise:function(e){return null!=e?x.extend(e,r):r}},i={};return r.pipe=r.then,x.each(t,function(e,o){var a=o[2],s=o[3];r[o[1]]=a.add,s&&a.add(function(){n=s},t[1^e][2].disable,t[2][2].lock),i[o[0]]=function(){return i[o[0]+\"With\"](this===i?r:this,arguments),this},i[o[0]+\"With\"]=a.fireWith}),r.promise(i),e&&e.call(i,i),i},when:function(e){var t=0,n=g.call(arguments),r=n.length,i=1!==r||e&&x.isFunction(e.promise)?r:0,o=1===i?e:x.Deferred(),a=function(e,t,n){return function(r){t[e]=this,n[e]=arguments.length>1?g.call(arguments):r,n===s?o.notifyWith(t,n):--i||o.resolveWith(t,n)}},s,l,u;if(r>1)for(s=Array(r),l=Array(r),u=Array(r);r>t;t++)n[t]&&x.isFunction(n[t].promise)?n[t].promise().done(a(t,u,n)).fail(o.reject).progress(a(t,l,s)):--i;return i||o.resolveWith(u,n),o.promise()}}),x.support=function(t){var n,r,o,s,l,u,c,p,f,d=a.createElement(\"div\");if(d.setAttribute(\"className\",\"t\"),d.innerHTML=\"  <link/><table></table><a href='/a'>a</a><input type='checkbox'/>\",n=d.getElementsByTagName(\"*\")||[],r=d.getElementsByTagName(\"a\")[0],!r||!r.style||!n.length)return t;s=a.createElement(\"select\"),u=s.appendChild(a.createElement(\"option\")),o=d.getElementsByTagName(\"input\")[0],r.style.cssText=\"top:1px;float:left;opacity:.5\",t.getSetAttribute=\"t\"!==d.className,t.leadingWhitespace=3===d.firstChild.nodeType,t.tbody=!d.getElementsByTagName(\"tbody\").length,t.htmlSerialize=!!d.getElementsByTagName(\"link\").length,t.style=/top/.test(r.getAttribute(\"style\")),t.hrefNormalized=\"/a\"===r.getAttribute(\"href\"),t.opacity=/^0.5/.test(r.style.opacity),t.cssFloat=!!r.style.cssFloat,t.checkOn=!!o.value,t.optSelected=u.selected,t.enctype=!!a.createElement(\"form\").enctype,t.html5Clone=\"<:nav></:nav>\"!==a.createElement(\"nav\").cloneNode(!0).outerHTML,t.inlineBlockNeedsLayout=!1,t.shrinkWrapBlocks=!1,t.pixelPosition=!1,t.deleteExpando=!0,t.noCloneEvent=!0,t.reliableMarginRight=!0,t.boxSizingReliable=!0,o.checked=!0,t.noCloneChecked=o.cloneNode(!0).checked,s.disabled=!0,t.optDisabled=!u.disabled;try{delete d.test}catch(h){t.deleteExpando=!1}o=a.createElement(\"input\"),o.setAttribute(\"value\",\"\"),t.input=\"\"===o.getAttribute(\"value\"),o.value=\"t\",o.setAttribute(\"type\",\"radio\"),t.radioValue=\"t\"===o.value,o.setAttribute(\"checked\",\"t\"),o.setAttribute(\"name\",\"t\"),l=a.createDocumentFragment(),l.appendChild(o),t.appendChecked=o.checked,t.checkClone=l.cloneNode(!0).cloneNode(!0).lastChild.checked,d.attachEvent&&(d.attachEvent(\"onclick\",function(){t.noCloneEvent=!1}),d.cloneNode(!0).click());for(f in{submit:!0,change:!0,focusin:!0})d.setAttribute(c=\"on\"+f,\"t\"),t[f+\"Bubbles\"]=c in e||d.attributes[c].expando===!1;d.style.backgroundClip=\"content-box\",d.cloneNode(!0).style.backgroundClip=\"\",t.clearCloneStyle=\"content-box\"===d.style.backgroundClip;for(f in x(t))break;return t.ownLast=\"0\"!==f,x(function(){var n,r,o,s=\"padding:0;margin:0;border:0;display:block;box-sizing:content-box;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;\",l=a.getElementsByTagName(\"body\")[0];l&&(n=a.createElement(\"div\"),n.style.cssText=\"border:0;width:0;height:0;position:absolute;top:0;left:-9999px;margin-top:1px\",l.appendChild(n).appendChild(d),d.innerHTML=\"<table><tr><td></td><td>t</td></tr></table>\",o=d.getElementsByTagName(\"td\"),o[0].style.cssText=\"padding:0;margin:0;border:0;display:none\",p=0===o[0].offsetHeight,o[0].style.display=\"\",o[1].style.display=\"none\",t.reliableHiddenOffsets=p&&0===o[0].offsetHeight,d.innerHTML=\"\",d.style.cssText=\"box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%;\",x.swap(l,null!=l.style.zoom?{zoom:1}:{},function(){t.boxSizing=4===d.offsetWidth}),e.getComputedStyle&&(t.pixelPosition=\"1%\"!==(e.getComputedStyle(d,null)||{}).top,t.boxSizingReliable=\"4px\"===(e.getComputedStyle(d,null)||{width:\"4px\"}).width,r=d.appendChild(a.createElement(\"div\")),r.style.cssText=d.style.cssText=s,r.style.marginRight=r.style.width=\"0\",d.style.width=\"1px\",t.reliableMarginRight=!parseFloat((e.getComputedStyle(r,null)||{}).marginRight)),typeof d.style.zoom!==i&&(d.innerHTML=\"\",d.style.cssText=s+\"width:1px;padding:1px;display:inline;zoom:1\",t.inlineBlockNeedsLayout=3===d.offsetWidth,d.style.display=\"block\",d.innerHTML=\"<div></div>\",d.firstChild.style.width=\"5px\",t.shrinkWrapBlocks=3!==d.offsetWidth,t.inlineBlockNeedsLayout&&(l.style.zoom=1)),l.removeChild(n),n=d=o=r=null)}),n=s=l=u=r=o=null,t\n}({});var B=/(?:\\{[\\s\\S]*\\}|\\[[\\s\\S]*\\])$/,P=/([A-Z])/g;function R(e,n,r,i){if(x.acceptData(e)){var o,a,s=x.expando,l=e.nodeType,u=l?x.cache:e,c=l?e[s]:e[s]&&s;if(c&&u[c]&&(i||u[c].data)||r!==t||\"string\"!=typeof n)return c||(c=l?e[s]=p.pop()||x.guid++:s),u[c]||(u[c]=l?{}:{toJSON:x.noop}),(\"object\"==typeof n||\"function\"==typeof n)&&(i?u[c]=x.extend(u[c],n):u[c].data=x.extend(u[c].data,n)),a=u[c],i||(a.data||(a.data={}),a=a.data),r!==t&&(a[x.camelCase(n)]=r),\"string\"==typeof n?(o=a[n],null==o&&(o=a[x.camelCase(n)])):o=a,o}}function W(e,t,n){if(x.acceptData(e)){var r,i,o=e.nodeType,a=o?x.cache:e,s=o?e[x.expando]:x.expando;if(a[s]){if(t&&(r=n?a[s]:a[s].data)){x.isArray(t)?t=t.concat(x.map(t,x.camelCase)):t in r?t=[t]:(t=x.camelCase(t),t=t in r?[t]:t.split(\" \")),i=t.length;while(i--)delete r[t[i]];if(n?!I(r):!x.isEmptyObject(r))return}(n||(delete a[s].data,I(a[s])))&&(o?x.cleanData([e],!0):x.support.deleteExpando||a!=a.window?delete a[s]:a[s]=null)}}}x.extend({cache:{},noData:{applet:!0,embed:!0,object:\"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000\"},hasData:function(e){return e=e.nodeType?x.cache[e[x.expando]]:e[x.expando],!!e&&!I(e)},data:function(e,t,n){return R(e,t,n)},removeData:function(e,t){return W(e,t)},_data:function(e,t,n){return R(e,t,n,!0)},_removeData:function(e,t){return W(e,t,!0)},acceptData:function(e){if(e.nodeType&&1!==e.nodeType&&9!==e.nodeType)return!1;var t=e.nodeName&&x.noData[e.nodeName.toLowerCase()];return!t||t!==!0&&e.getAttribute(\"classid\")===t}}),x.fn.extend({data:function(e,n){var r,i,o=null,a=0,s=this[0];if(e===t){if(this.length&&(o=x.data(s),1===s.nodeType&&!x._data(s,\"parsedAttrs\"))){for(r=s.attributes;r.length>a;a++)i=r[a].name,0===i.indexOf(\"data-\")&&(i=x.camelCase(i.slice(5)),$(s,i,o[i]));x._data(s,\"parsedAttrs\",!0)}return o}return\"object\"==typeof e?this.each(function(){x.data(this,e)}):arguments.length>1?this.each(function(){x.data(this,e,n)}):s?$(s,e,x.data(s,e)):null},removeData:function(e){return this.each(function(){x.removeData(this,e)})}});function $(e,n,r){if(r===t&&1===e.nodeType){var i=\"data-\"+n.replace(P,\"-$1\").toLowerCase();if(r=e.getAttribute(i),\"string\"==typeof r){try{r=\"true\"===r?!0:\"false\"===r?!1:\"null\"===r?null:+r+\"\"===r?+r:B.test(r)?x.parseJSON(r):r}catch(o){}x.data(e,n,r)}else r=t}return r}function I(e){var t;for(t in e)if((\"data\"!==t||!x.isEmptyObject(e[t]))&&\"toJSON\"!==t)return!1;return!0}x.extend({queue:function(e,n,r){var i;return e?(n=(n||\"fx\")+\"queue\",i=x._data(e,n),r&&(!i||x.isArray(r)?i=x._data(e,n,x.makeArray(r)):i.push(r)),i||[]):t},dequeue:function(e,t){t=t||\"fx\";var n=x.queue(e,t),r=n.length,i=n.shift(),o=x._queueHooks(e,t),a=function(){x.dequeue(e,t)};\"inprogress\"===i&&(i=n.shift(),r--),i&&(\"fx\"===t&&n.unshift(\"inprogress\"),delete o.stop,i.call(e,a,o)),!r&&o&&o.empty.fire()},_queueHooks:function(e,t){var n=t+\"queueHooks\";return x._data(e,n)||x._data(e,n,{empty:x.Callbacks(\"once memory\").add(function(){x._removeData(e,t+\"queue\"),x._removeData(e,n)})})}}),x.fn.extend({queue:function(e,n){var r=2;return\"string\"!=typeof e&&(n=e,e=\"fx\",r--),r>arguments.length?x.queue(this[0],e):n===t?this:this.each(function(){var t=x.queue(this,e,n);x._queueHooks(this,e),\"fx\"===e&&\"inprogress\"!==t[0]&&x.dequeue(this,e)})},dequeue:function(e){return this.each(function(){x.dequeue(this,e)})},delay:function(e,t){return e=x.fx?x.fx.speeds[e]||e:e,t=t||\"fx\",this.queue(t,function(t,n){var r=setTimeout(t,e);n.stop=function(){clearTimeout(r)}})},clearQueue:function(e){return this.queue(e||\"fx\",[])},promise:function(e,n){var r,i=1,o=x.Deferred(),a=this,s=this.length,l=function(){--i||o.resolveWith(a,[a])};\"string\"!=typeof e&&(n=e,e=t),e=e||\"fx\";while(s--)r=x._data(a[s],e+\"queueHooks\"),r&&r.empty&&(i++,r.empty.add(l));return l(),o.promise(n)}});var z,X,U=/[\\t\\r\\n\\f]/g,V=/\\r/g,Y=/^(?:input|select|textarea|button|object)$/i,J=/^(?:a|area)$/i,G=/^(?:checked|selected)$/i,Q=x.support.getSetAttribute,K=x.support.input;x.fn.extend({attr:function(e,t){return x.access(this,x.attr,e,t,arguments.length>1)},removeAttr:function(e){return this.each(function(){x.removeAttr(this,e)})},prop:function(e,t){return x.access(this,x.prop,e,t,arguments.length>1)},removeProp:function(e){return e=x.propFix[e]||e,this.each(function(){try{this[e]=t,delete this[e]}catch(n){}})},addClass:function(e){var t,n,r,i,o,a=0,s=this.length,l=\"string\"==typeof e&&e;if(x.isFunction(e))return this.each(function(t){x(this).addClass(e.call(this,t,this.className))});if(l)for(t=(e||\"\").match(T)||[];s>a;a++)if(n=this[a],r=1===n.nodeType&&(n.className?(\" \"+n.className+\" \").replace(U,\" \"):\" \")){o=0;while(i=t[o++])0>r.indexOf(\" \"+i+\" \")&&(r+=i+\" \");n.className=x.trim(r)}return this},removeClass:function(e){var t,n,r,i,o,a=0,s=this.length,l=0===arguments.length||\"string\"==typeof e&&e;if(x.isFunction(e))return this.each(function(t){x(this).removeClass(e.call(this,t,this.className))});if(l)for(t=(e||\"\").match(T)||[];s>a;a++)if(n=this[a],r=1===n.nodeType&&(n.className?(\" \"+n.className+\" \").replace(U,\" \"):\"\")){o=0;while(i=t[o++])while(r.indexOf(\" \"+i+\" \")>=0)r=r.replace(\" \"+i+\" \",\" \");n.className=e?x.trim(r):\"\"}return this},toggleClass:function(e,t){var n=typeof e;return\"boolean\"==typeof t&&\"string\"===n?t?this.addClass(e):this.removeClass(e):x.isFunction(e)?this.each(function(n){x(this).toggleClass(e.call(this,n,this.className,t),t)}):this.each(function(){if(\"string\"===n){var t,r=0,o=x(this),a=e.match(T)||[];while(t=a[r++])o.hasClass(t)?o.removeClass(t):o.addClass(t)}else(n===i||\"boolean\"===n)&&(this.className&&x._data(this,\"__className__\",this.className),this.className=this.className||e===!1?\"\":x._data(this,\"__className__\")||\"\")})},hasClass:function(e){var t=\" \"+e+\" \",n=0,r=this.length;for(;r>n;n++)if(1===this[n].nodeType&&(\" \"+this[n].className+\" \").replace(U,\" \").indexOf(t)>=0)return!0;return!1},val:function(e){var n,r,i,o=this[0];{if(arguments.length)return i=x.isFunction(e),this.each(function(n){var o;1===this.nodeType&&(o=i?e.call(this,n,x(this).val()):e,null==o?o=\"\":\"number\"==typeof o?o+=\"\":x.isArray(o)&&(o=x.map(o,function(e){return null==e?\"\":e+\"\"})),r=x.valHooks[this.type]||x.valHooks[this.nodeName.toLowerCase()],r&&\"set\"in r&&r.set(this,o,\"value\")!==t||(this.value=o))});if(o)return r=x.valHooks[o.type]||x.valHooks[o.nodeName.toLowerCase()],r&&\"get\"in r&&(n=r.get(o,\"value\"))!==t?n:(n=o.value,\"string\"==typeof n?n.replace(V,\"\"):null==n?\"\":n)}}}),x.extend({valHooks:{option:{get:function(e){var t=x.find.attr(e,\"value\");return null!=t?t:e.text}},select:{get:function(e){var t,n,r=e.options,i=e.selectedIndex,o=\"select-one\"===e.type||0>i,a=o?null:[],s=o?i+1:r.length,l=0>i?s:o?i:0;for(;s>l;l++)if(n=r[l],!(!n.selected&&l!==i||(x.support.optDisabled?n.disabled:null!==n.getAttribute(\"disabled\"))||n.parentNode.disabled&&x.nodeName(n.parentNode,\"optgroup\"))){if(t=x(n).val(),o)return t;a.push(t)}return a},set:function(e,t){var n,r,i=e.options,o=x.makeArray(t),a=i.length;while(a--)r=i[a],(r.selected=x.inArray(x(r).val(),o)>=0)&&(n=!0);return n||(e.selectedIndex=-1),o}}},attr:function(e,n,r){var o,a,s=e.nodeType;if(e&&3!==s&&8!==s&&2!==s)return typeof e.getAttribute===i?x.prop(e,n,r):(1===s&&x.isXMLDoc(e)||(n=n.toLowerCase(),o=x.attrHooks[n]||(x.expr.match.bool.test(n)?X:z)),r===t?o&&\"get\"in o&&null!==(a=o.get(e,n))?a:(a=x.find.attr(e,n),null==a?t:a):null!==r?o&&\"set\"in o&&(a=o.set(e,r,n))!==t?a:(e.setAttribute(n,r+\"\"),r):(x.removeAttr(e,n),t))},removeAttr:function(e,t){var n,r,i=0,o=t&&t.match(T);if(o&&1===e.nodeType)while(n=o[i++])r=x.propFix[n]||n,x.expr.match.bool.test(n)?K&&Q||!G.test(n)?e[r]=!1:e[x.camelCase(\"default-\"+n)]=e[r]=!1:x.attr(e,n,\"\"),e.removeAttribute(Q?n:r)},attrHooks:{type:{set:function(e,t){if(!x.support.radioValue&&\"radio\"===t&&x.nodeName(e,\"input\")){var n=e.value;return e.setAttribute(\"type\",t),n&&(e.value=n),t}}}},propFix:{\"for\":\"htmlFor\",\"class\":\"className\"},prop:function(e,n,r){var i,o,a,s=e.nodeType;if(e&&3!==s&&8!==s&&2!==s)return a=1!==s||!x.isXMLDoc(e),a&&(n=x.propFix[n]||n,o=x.propHooks[n]),r!==t?o&&\"set\"in o&&(i=o.set(e,r,n))!==t?i:e[n]=r:o&&\"get\"in o&&null!==(i=o.get(e,n))?i:e[n]},propHooks:{tabIndex:{get:function(e){var t=x.find.attr(e,\"tabindex\");return t?parseInt(t,10):Y.test(e.nodeName)||J.test(e.nodeName)&&e.href?0:-1}}}}),X={set:function(e,t,n){return t===!1?x.removeAttr(e,n):K&&Q||!G.test(n)?e.setAttribute(!Q&&x.propFix[n]||n,n):e[x.camelCase(\"default-\"+n)]=e[n]=!0,n}},x.each(x.expr.match.bool.source.match(/\\w+/g),function(e,n){var r=x.expr.attrHandle[n]||x.find.attr;x.expr.attrHandle[n]=K&&Q||!G.test(n)?function(e,n,i){var o=x.expr.attrHandle[n],a=i?t:(x.expr.attrHandle[n]=t)!=r(e,n,i)?n.toLowerCase():null;return x.expr.attrHandle[n]=o,a}:function(e,n,r){return r?t:e[x.camelCase(\"default-\"+n)]?n.toLowerCase():null}}),K&&Q||(x.attrHooks.value={set:function(e,n,r){return x.nodeName(e,\"input\")?(e.defaultValue=n,t):z&&z.set(e,n,r)}}),Q||(z={set:function(e,n,r){var i=e.getAttributeNode(r);return i||e.setAttributeNode(i=e.ownerDocument.createAttribute(r)),i.value=n+=\"\",\"value\"===r||n===e.getAttribute(r)?n:t}},x.expr.attrHandle.id=x.expr.attrHandle.name=x.expr.attrHandle.coords=function(e,n,r){var i;return r?t:(i=e.getAttributeNode(n))&&\"\"!==i.value?i.value:null},x.valHooks.button={get:function(e,n){var r=e.getAttributeNode(n);return r&&r.specified?r.value:t},set:z.set},x.attrHooks.contenteditable={set:function(e,t,n){z.set(e,\"\"===t?!1:t,n)}},x.each([\"width\",\"height\"],function(e,n){x.attrHooks[n]={set:function(e,r){return\"\"===r?(e.setAttribute(n,\"auto\"),r):t}}})),x.support.hrefNormalized||x.each([\"href\",\"src\"],function(e,t){x.propHooks[t]={get:function(e){return e.getAttribute(t,4)}}}),x.support.style||(x.attrHooks.style={get:function(e){return e.style.cssText||t},set:function(e,t){return e.style.cssText=t+\"\"}}),x.support.optSelected||(x.propHooks.selected={get:function(e){var t=e.parentNode;return t&&(t.selectedIndex,t.parentNode&&t.parentNode.selectedIndex),null}}),x.each([\"tabIndex\",\"readOnly\",\"maxLength\",\"cellSpacing\",\"cellPadding\",\"rowSpan\",\"colSpan\",\"useMap\",\"frameBorder\",\"contentEditable\"],function(){x.propFix[this.toLowerCase()]=this}),x.support.enctype||(x.propFix.enctype=\"encoding\"),x.each([\"radio\",\"checkbox\"],function(){x.valHooks[this]={set:function(e,n){return x.isArray(n)?e.checked=x.inArray(x(e).val(),n)>=0:t}},x.support.checkOn||(x.valHooks[this].get=function(e){return null===e.getAttribute(\"value\")?\"on\":e.value})});var Z=/^(?:input|select|textarea)$/i,et=/^key/,tt=/^(?:mouse|contextmenu)|click/,nt=/^(?:focusinfocus|focusoutblur)$/,rt=/^([^.]*)(?:\\.(.+)|)$/;function it(){return!0}function ot(){return!1}function at(){try{return a.activeElement}catch(e){}}x.event={global:{},add:function(e,n,r,o,a){var s,l,u,c,p,f,d,h,g,m,y,v=x._data(e);if(v){r.handler&&(c=r,r=c.handler,a=c.selector),r.guid||(r.guid=x.guid++),(l=v.events)||(l=v.events={}),(f=v.handle)||(f=v.handle=function(e){return typeof x===i||e&&x.event.triggered===e.type?t:x.event.dispatch.apply(f.elem,arguments)},f.elem=e),n=(n||\"\").match(T)||[\"\"],u=n.length;while(u--)s=rt.exec(n[u])||[],g=y=s[1],m=(s[2]||\"\").split(\".\").sort(),g&&(p=x.event.special[g]||{},g=(a?p.delegateType:p.bindType)||g,p=x.event.special[g]||{},d=x.extend({type:g,origType:y,data:o,handler:r,guid:r.guid,selector:a,needsContext:a&&x.expr.match.needsContext.test(a),namespace:m.join(\".\")},c),(h=l[g])||(h=l[g]=[],h.delegateCount=0,p.setup&&p.setup.call(e,o,m,f)!==!1||(e.addEventListener?e.addEventListener(g,f,!1):e.attachEvent&&e.attachEvent(\"on\"+g,f))),p.add&&(p.add.call(e,d),d.handler.guid||(d.handler.guid=r.guid)),a?h.splice(h.delegateCount++,0,d):h.push(d),x.event.global[g]=!0);e=null}},remove:function(e,t,n,r,i){var o,a,s,l,u,c,p,f,d,h,g,m=x.hasData(e)&&x._data(e);if(m&&(c=m.events)){t=(t||\"\").match(T)||[\"\"],u=t.length;while(u--)if(s=rt.exec(t[u])||[],d=g=s[1],h=(s[2]||\"\").split(\".\").sort(),d){p=x.event.special[d]||{},d=(r?p.delegateType:p.bindType)||d,f=c[d]||[],s=s[2]&&RegExp(\"(^|\\\\.)\"+h.join(\"\\\\.(?:.*\\\\.|)\")+\"(\\\\.|$)\"),l=o=f.length;while(o--)a=f[o],!i&&g!==a.origType||n&&n.guid!==a.guid||s&&!s.test(a.namespace)||r&&r!==a.selector&&(\"**\"!==r||!a.selector)||(f.splice(o,1),a.selector&&f.delegateCount--,p.remove&&p.remove.call(e,a));l&&!f.length&&(p.teardown&&p.teardown.call(e,h,m.handle)!==!1||x.removeEvent(e,d,m.handle),delete c[d])}else for(d in c)x.event.remove(e,d+t[u],n,r,!0);x.isEmptyObject(c)&&(delete m.handle,x._removeData(e,\"events\"))}},trigger:function(n,r,i,o){var s,l,u,c,p,f,d,h=[i||a],g=v.call(n,\"type\")?n.type:n,m=v.call(n,\"namespace\")?n.namespace.split(\".\"):[];if(u=f=i=i||a,3!==i.nodeType&&8!==i.nodeType&&!nt.test(g+x.event.triggered)&&(g.indexOf(\".\")>=0&&(m=g.split(\".\"),g=m.shift(),m.sort()),l=0>g.indexOf(\":\")&&\"on\"+g,n=n[x.expando]?n:new x.Event(g,\"object\"==typeof n&&n),n.isTrigger=o?2:3,n.namespace=m.join(\".\"),n.namespace_re=n.namespace?RegExp(\"(^|\\\\.)\"+m.join(\"\\\\.(?:.*\\\\.|)\")+\"(\\\\.|$)\"):null,n.result=t,n.target||(n.target=i),r=null==r?[n]:x.makeArray(r,[n]),p=x.event.special[g]||{},o||!p.trigger||p.trigger.apply(i,r)!==!1)){if(!o&&!p.noBubble&&!x.isWindow(i)){for(c=p.delegateType||g,nt.test(c+g)||(u=u.parentNode);u;u=u.parentNode)h.push(u),f=u;f===(i.ownerDocument||a)&&h.push(f.defaultView||f.parentWindow||e)}d=0;while((u=h[d++])&&!n.isPropagationStopped())n.type=d>1?c:p.bindType||g,s=(x._data(u,\"events\")||{})[n.type]&&x._data(u,\"handle\"),s&&s.apply(u,r),s=l&&u[l],s&&x.acceptData(u)&&s.apply&&s.apply(u,r)===!1&&n.preventDefault();if(n.type=g,!o&&!n.isDefaultPrevented()&&(!p._default||p._default.apply(h.pop(),r)===!1)&&x.acceptData(i)&&l&&i[g]&&!x.isWindow(i)){f=i[l],f&&(i[l]=null),x.event.triggered=g;try{i[g]()}catch(y){}x.event.triggered=t,f&&(i[l]=f)}return n.result}},dispatch:function(e){e=x.event.fix(e);var n,r,i,o,a,s=[],l=g.call(arguments),u=(x._data(this,\"events\")||{})[e.type]||[],c=x.event.special[e.type]||{};if(l[0]=e,e.delegateTarget=this,!c.preDispatch||c.preDispatch.call(this,e)!==!1){s=x.event.handlers.call(this,e,u),n=0;while((o=s[n++])&&!e.isPropagationStopped()){e.currentTarget=o.elem,a=0;while((i=o.handlers[a++])&&!e.isImmediatePropagationStopped())(!e.namespace_re||e.namespace_re.test(i.namespace))&&(e.handleObj=i,e.data=i.data,r=((x.event.special[i.origType]||{}).handle||i.handler).apply(o.elem,l),r!==t&&(e.result=r)===!1&&(e.preventDefault(),e.stopPropagation()))}return c.postDispatch&&c.postDispatch.call(this,e),e.result}},handlers:function(e,n){var r,i,o,a,s=[],l=n.delegateCount,u=e.target;if(l&&u.nodeType&&(!e.button||\"click\"!==e.type))for(;u!=this;u=u.parentNode||this)if(1===u.nodeType&&(u.disabled!==!0||\"click\"!==e.type)){for(o=[],a=0;l>a;a++)i=n[a],r=i.selector+\" \",o[r]===t&&(o[r]=i.needsContext?x(r,this).index(u)>=0:x.find(r,this,null,[u]).length),o[r]&&o.push(i);o.length&&s.push({elem:u,handlers:o})}return n.length>l&&s.push({elem:this,handlers:n.slice(l)}),s},fix:function(e){if(e[x.expando])return e;var t,n,r,i=e.type,o=e,s=this.fixHooks[i];s||(this.fixHooks[i]=s=tt.test(i)?this.mouseHooks:et.test(i)?this.keyHooks:{}),r=s.props?this.props.concat(s.props):this.props,e=new x.Event(o),t=r.length;while(t--)n=r[t],e[n]=o[n];return e.target||(e.target=o.srcElement||a),3===e.target.nodeType&&(e.target=e.target.parentNode),e.metaKey=!!e.metaKey,s.filter?s.filter(e,o):e},props:\"altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which\".split(\" \"),fixHooks:{},keyHooks:{props:\"char charCode key keyCode\".split(\" \"),filter:function(e,t){return null==e.which&&(e.which=null!=t.charCode?t.charCode:t.keyCode),e}},mouseHooks:{props:\"button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement\".split(\" \"),filter:function(e,n){var r,i,o,s=n.button,l=n.fromElement;return null==e.pageX&&null!=n.clientX&&(i=e.target.ownerDocument||a,o=i.documentElement,r=i.body,e.pageX=n.clientX+(o&&o.scrollLeft||r&&r.scrollLeft||0)-(o&&o.clientLeft||r&&r.clientLeft||0),e.pageY=n.clientY+(o&&o.scrollTop||r&&r.scrollTop||0)-(o&&o.clientTop||r&&r.clientTop||0)),!e.relatedTarget&&l&&(e.relatedTarget=l===e.target?n.toElement:l),e.which||s===t||(e.which=1&s?1:2&s?3:4&s?2:0),e}},special:{load:{noBubble:!0},focus:{trigger:function(){if(this!==at()&&this.focus)try{return this.focus(),!1}catch(e){}},delegateType:\"focusin\"},blur:{trigger:function(){return this===at()&&this.blur?(this.blur(),!1):t},delegateType:\"focusout\"},click:{trigger:function(){return x.nodeName(this,\"input\")&&\"checkbox\"===this.type&&this.click?(this.click(),!1):t},_default:function(e){return x.nodeName(e.target,\"a\")}},beforeunload:{postDispatch:function(e){e.result!==t&&(e.originalEvent.returnValue=e.result)}}},simulate:function(e,t,n,r){var i=x.extend(new x.Event,n,{type:e,isSimulated:!0,originalEvent:{}});r?x.event.trigger(i,null,t):x.event.dispatch.call(t,i),i.isDefaultPrevented()&&n.preventDefault()}},x.removeEvent=a.removeEventListener?function(e,t,n){e.removeEventListener&&e.removeEventListener(t,n,!1)}:function(e,t,n){var r=\"on\"+t;e.detachEvent&&(typeof e[r]===i&&(e[r]=null),e.detachEvent(r,n))},x.Event=function(e,n){return this instanceof x.Event?(e&&e.type?(this.originalEvent=e,this.type=e.type,this.isDefaultPrevented=e.defaultPrevented||e.returnValue===!1||e.getPreventDefault&&e.getPreventDefault()?it:ot):this.type=e,n&&x.extend(this,n),this.timeStamp=e&&e.timeStamp||x.now(),this[x.expando]=!0,t):new x.Event(e,n)},x.Event.prototype={isDefaultPrevented:ot,isPropagationStopped:ot,isImmediatePropagationStopped:ot,preventDefault:function(){var e=this.originalEvent;this.isDefaultPrevented=it,e&&(e.preventDefault?e.preventDefault():e.returnValue=!1)},stopPropagation:function(){var e=this.originalEvent;this.isPropagationStopped=it,e&&(e.stopPropagation&&e.stopPropagation(),e.cancelBubble=!0)},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=it,this.stopPropagation()}},x.each({mouseenter:\"mouseover\",mouseleave:\"mouseout\"},function(e,t){x.event.special[e]={delegateType:t,bindType:t,handle:function(e){var n,r=this,i=e.relatedTarget,o=e.handleObj;return(!i||i!==r&&!x.contains(r,i))&&(e.type=o.origType,n=o.handler.apply(this,arguments),e.type=t),n}}}),x.support.submitBubbles||(x.event.special.submit={setup:function(){return x.nodeName(this,\"form\")?!1:(x.event.add(this,\"click._submit keypress._submit\",function(e){var n=e.target,r=x.nodeName(n,\"input\")||x.nodeName(n,\"button\")?n.form:t;r&&!x._data(r,\"submitBubbles\")&&(x.event.add(r,\"submit._submit\",function(e){e._submit_bubble=!0}),x._data(r,\"submitBubbles\",!0))}),t)},postDispatch:function(e){e._submit_bubble&&(delete e._submit_bubble,this.parentNode&&!e.isTrigger&&x.event.simulate(\"submit\",this.parentNode,e,!0))},teardown:function(){return x.nodeName(this,\"form\")?!1:(x.event.remove(this,\"._submit\"),t)}}),x.support.changeBubbles||(x.event.special.change={setup:function(){return Z.test(this.nodeName)?((\"checkbox\"===this.type||\"radio\"===this.type)&&(x.event.add(this,\"propertychange._change\",function(e){\"checked\"===e.originalEvent.propertyName&&(this._just_changed=!0)}),x.event.add(this,\"click._change\",function(e){this._just_changed&&!e.isTrigger&&(this._just_changed=!1),x.event.simulate(\"change\",this,e,!0)})),!1):(x.event.add(this,\"beforeactivate._change\",function(e){var t=e.target;Z.test(t.nodeName)&&!x._data(t,\"changeBubbles\")&&(x.event.add(t,\"change._change\",function(e){!this.parentNode||e.isSimulated||e.isTrigger||x.event.simulate(\"change\",this.parentNode,e,!0)}),x._data(t,\"changeBubbles\",!0))}),t)},handle:function(e){var n=e.target;return this!==n||e.isSimulated||e.isTrigger||\"radio\"!==n.type&&\"checkbox\"!==n.type?e.handleObj.handler.apply(this,arguments):t},teardown:function(){return x.event.remove(this,\"._change\"),!Z.test(this.nodeName)}}),x.support.focusinBubbles||x.each({focus:\"focusin\",blur:\"focusout\"},function(e,t){var n=0,r=function(e){x.event.simulate(t,e.target,x.event.fix(e),!0)};x.event.special[t]={setup:function(){0===n++&&a.addEventListener(e,r,!0)},teardown:function(){0===--n&&a.removeEventListener(e,r,!0)}}}),x.fn.extend({on:function(e,n,r,i,o){var a,s;if(\"object\"==typeof e){\"string\"!=typeof n&&(r=r||n,n=t);for(a in e)this.on(a,n,r,e[a],o);return this}if(null==r&&null==i?(i=n,r=n=t):null==i&&(\"string\"==typeof n?(i=r,r=t):(i=r,r=n,n=t)),i===!1)i=ot;else if(!i)return this;return 1===o&&(s=i,i=function(e){return x().off(e),s.apply(this,arguments)},i.guid=s.guid||(s.guid=x.guid++)),this.each(function(){x.event.add(this,e,i,r,n)})},one:function(e,t,n,r){return this.on(e,t,n,r,1)},off:function(e,n,r){var i,o;if(e&&e.preventDefault&&e.handleObj)return i=e.handleObj,x(e.delegateTarget).off(i.namespace?i.origType+\".\"+i.namespace:i.origType,i.selector,i.handler),this;if(\"object\"==typeof e){for(o in e)this.off(o,n,e[o]);return this}return(n===!1||\"function\"==typeof n)&&(r=n,n=t),r===!1&&(r=ot),this.each(function(){x.event.remove(this,e,r,n)})},trigger:function(e,t){return this.each(function(){x.event.trigger(e,t,this)})},triggerHandler:function(e,n){var r=this[0];return r?x.event.trigger(e,n,r,!0):t}});var st=/^.[^:#\\[\\.,]*$/,lt=/^(?:parents|prev(?:Until|All))/,ut=x.expr.match.needsContext,ct={children:!0,contents:!0,next:!0,prev:!0};x.fn.extend({find:function(e){var t,n=[],r=this,i=r.length;if(\"string\"!=typeof e)return this.pushStack(x(e).filter(function(){for(t=0;i>t;t++)if(x.contains(r[t],this))return!0}));for(t=0;i>t;t++)x.find(e,r[t],n);return n=this.pushStack(i>1?x.unique(n):n),n.selector=this.selector?this.selector+\" \"+e:e,n},has:function(e){var t,n=x(e,this),r=n.length;return this.filter(function(){for(t=0;r>t;t++)if(x.contains(this,n[t]))return!0})},not:function(e){return this.pushStack(ft(this,e||[],!0))},filter:function(e){return this.pushStack(ft(this,e||[],!1))},is:function(e){return!!ft(this,\"string\"==typeof e&&ut.test(e)?x(e):e||[],!1).length},closest:function(e,t){var n,r=0,i=this.length,o=[],a=ut.test(e)||\"string\"!=typeof e?x(e,t||this.context):0;for(;i>r;r++)for(n=this[r];n&&n!==t;n=n.parentNode)if(11>n.nodeType&&(a?a.index(n)>-1:1===n.nodeType&&x.find.matchesSelector(n,e))){n=o.push(n);break}return this.pushStack(o.length>1?x.unique(o):o)},index:function(e){return e?\"string\"==typeof e?x.inArray(this[0],x(e)):x.inArray(e.jquery?e[0]:e,this):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(e,t){var n=\"string\"==typeof e?x(e,t):x.makeArray(e&&e.nodeType?[e]:e),r=x.merge(this.get(),n);return this.pushStack(x.unique(r))},addBack:function(e){return this.add(null==e?this.prevObject:this.prevObject.filter(e))}});function pt(e,t){do e=e[t];while(e&&1!==e.nodeType);return e}x.each({parent:function(e){var t=e.parentNode;return t&&11!==t.nodeType?t:null},parents:function(e){return x.dir(e,\"parentNode\")},parentsUntil:function(e,t,n){return x.dir(e,\"parentNode\",n)},next:function(e){return pt(e,\"nextSibling\")},prev:function(e){return pt(e,\"previousSibling\")},nextAll:function(e){return x.dir(e,\"nextSibling\")},prevAll:function(e){return x.dir(e,\"previousSibling\")},nextUntil:function(e,t,n){return x.dir(e,\"nextSibling\",n)},prevUntil:function(e,t,n){return x.dir(e,\"previousSibling\",n)},siblings:function(e){return x.sibling((e.parentNode||{}).firstChild,e)},children:function(e){return x.sibling(e.firstChild)},contents:function(e){return x.nodeName(e,\"iframe\")?e.contentDocument||e.contentWindow.document:x.merge([],e.childNodes)}},function(e,t){x.fn[e]=function(n,r){var i=x.map(this,t,n);return\"Until\"!==e.slice(-5)&&(r=n),r&&\"string\"==typeof r&&(i=x.filter(r,i)),this.length>1&&(ct[e]||(i=x.unique(i)),lt.test(e)&&(i=i.reverse())),this.pushStack(i)}}),x.extend({filter:function(e,t,n){var r=t[0];return n&&(e=\":not(\"+e+\")\"),1===t.length&&1===r.nodeType?x.find.matchesSelector(r,e)?[r]:[]:x.find.matches(e,x.grep(t,function(e){return 1===e.nodeType}))},dir:function(e,n,r){var i=[],o=e[n];while(o&&9!==o.nodeType&&(r===t||1!==o.nodeType||!x(o).is(r)))1===o.nodeType&&i.push(o),o=o[n];return i},sibling:function(e,t){var n=[];for(;e;e=e.nextSibling)1===e.nodeType&&e!==t&&n.push(e);return n}});function ft(e,t,n){if(x.isFunction(t))return x.grep(e,function(e,r){return!!t.call(e,r,e)!==n});if(t.nodeType)return x.grep(e,function(e){return e===t!==n});if(\"string\"==typeof t){if(st.test(t))return x.filter(t,e,n);t=x.filter(t,e)}return x.grep(e,function(e){return x.inArray(e,t)>=0!==n})}function dt(e){var t=ht.split(\"|\"),n=e.createDocumentFragment();if(n.createElement)while(t.length)n.createElement(t.pop());return n}var ht=\"abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video\",gt=/ jQuery\\d+=\"(?:null|\\d+)\"/g,mt=RegExp(\"<(?:\"+ht+\")[\\\\s/>]\",\"i\"),yt=/^\\s+/,vt=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\\w:]+)[^>]*)\\/>/gi,bt=/<([\\w:]+)/,xt=/<tbody/i,wt=/<|&#?\\w+;/,Tt=/<(?:script|style|link)/i,Ct=/^(?:checkbox|radio)$/i,Nt=/checked\\s*(?:[^=]|=\\s*.checked.)/i,kt=/^$|\\/(?:java|ecma)script/i,Et=/^true\\/(.*)/,St=/^\\s*<!(?:\\[CDATA\\[|--)|(?:\\]\\]|--)>\\s*$/g,At={option:[1,\"<select multiple='multiple'>\",\"</select>\"],legend:[1,\"<fieldset>\",\"</fieldset>\"],area:[1,\"<map>\",\"</map>\"],param:[1,\"<object>\",\"</object>\"],thead:[1,\"<table>\",\"</table>\"],tr:[2,\"<table><tbody>\",\"</tbody></table>\"],col:[2,\"<table><tbody></tbody><colgroup>\",\"</colgroup></table>\"],td:[3,\"<table><tbody><tr>\",\"</tr></tbody></table>\"],_default:x.support.htmlSerialize?[0,\"\",\"\"]:[1,\"X<div>\",\"</div>\"]},jt=dt(a),Dt=jt.appendChild(a.createElement(\"div\"));At.optgroup=At.option,At.tbody=At.tfoot=At.colgroup=At.caption=At.thead,At.th=At.td,x.fn.extend({text:function(e){return x.access(this,function(e){return e===t?x.text(this):this.empty().append((this[0]&&this[0].ownerDocument||a).createTextNode(e))},null,e,arguments.length)},append:function(){return this.domManip(arguments,function(e){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var t=Lt(this,e);t.appendChild(e)}})},prepend:function(){return this.domManip(arguments,function(e){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var t=Lt(this,e);t.insertBefore(e,t.firstChild)}})},before:function(){return this.domManip(arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this)})},after:function(){return this.domManip(arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this.nextSibling)})},remove:function(e,t){var n,r=e?x.filter(e,this):this,i=0;for(;null!=(n=r[i]);i++)t||1!==n.nodeType||x.cleanData(Ft(n)),n.parentNode&&(t&&x.contains(n.ownerDocument,n)&&_t(Ft(n,\"script\")),n.parentNode.removeChild(n));return this},empty:function(){var e,t=0;for(;null!=(e=this[t]);t++){1===e.nodeType&&x.cleanData(Ft(e,!1));while(e.firstChild)e.removeChild(e.firstChild);e.options&&x.nodeName(e,\"select\")&&(e.options.length=0)}return this},clone:function(e,t){return e=null==e?!1:e,t=null==t?e:t,this.map(function(){return x.clone(this,e,t)})},html:function(e){return x.access(this,function(e){var n=this[0]||{},r=0,i=this.length;if(e===t)return 1===n.nodeType?n.innerHTML.replace(gt,\"\"):t;if(!(\"string\"!=typeof e||Tt.test(e)||!x.support.htmlSerialize&&mt.test(e)||!x.support.leadingWhitespace&&yt.test(e)||At[(bt.exec(e)||[\"\",\"\"])[1].toLowerCase()])){e=e.replace(vt,\"<$1></$2>\");try{for(;i>r;r++)n=this[r]||{},1===n.nodeType&&(x.cleanData(Ft(n,!1)),n.innerHTML=e);n=0}catch(o){}}n&&this.empty().append(e)},null,e,arguments.length)},replaceWith:function(){var e=x.map(this,function(e){return[e.nextSibling,e.parentNode]}),t=0;return this.domManip(arguments,function(n){var r=e[t++],i=e[t++];i&&(r&&r.parentNode!==i&&(r=this.nextSibling),x(this).remove(),i.insertBefore(n,r))},!0),t?this:this.remove()},detach:function(e){return this.remove(e,!0)},domManip:function(e,t,n){e=d.apply([],e);var r,i,o,a,s,l,u=0,c=this.length,p=this,f=c-1,h=e[0],g=x.isFunction(h);if(g||!(1>=c||\"string\"!=typeof h||x.support.checkClone)&&Nt.test(h))return this.each(function(r){var i=p.eq(r);g&&(e[0]=h.call(this,r,i.html())),i.domManip(e,t,n)});if(c&&(l=x.buildFragment(e,this[0].ownerDocument,!1,!n&&this),r=l.firstChild,1===l.childNodes.length&&(l=r),r)){for(a=x.map(Ft(l,\"script\"),Ht),o=a.length;c>u;u++)i=l,u!==f&&(i=x.clone(i,!0,!0),o&&x.merge(a,Ft(i,\"script\"))),t.call(this[u],i,u);if(o)for(s=a[a.length-1].ownerDocument,x.map(a,qt),u=0;o>u;u++)i=a[u],kt.test(i.type||\"\")&&!x._data(i,\"globalEval\")&&x.contains(s,i)&&(i.src?x._evalUrl(i.src):x.globalEval((i.text||i.textContent||i.innerHTML||\"\").replace(St,\"\")));l=r=null}return this}});function Lt(e,t){return x.nodeName(e,\"table\")&&x.nodeName(1===t.nodeType?t:t.firstChild,\"tr\")?e.getElementsByTagName(\"tbody\")[0]||e.appendChild(e.ownerDocument.createElement(\"tbody\")):e}function Ht(e){return e.type=(null!==x.find.attr(e,\"type\"))+\"/\"+e.type,e}function qt(e){var t=Et.exec(e.type);return t?e.type=t[1]:e.removeAttribute(\"type\"),e}function _t(e,t){var n,r=0;for(;null!=(n=e[r]);r++)x._data(n,\"globalEval\",!t||x._data(t[r],\"globalEval\"))}function Mt(e,t){if(1===t.nodeType&&x.hasData(e)){var n,r,i,o=x._data(e),a=x._data(t,o),s=o.events;if(s){delete a.handle,a.events={};for(n in s)for(r=0,i=s[n].length;i>r;r++)x.event.add(t,n,s[n][r])}a.data&&(a.data=x.extend({},a.data))}}function Ot(e,t){var n,r,i;if(1===t.nodeType){if(n=t.nodeName.toLowerCase(),!x.support.noCloneEvent&&t[x.expando]){i=x._data(t);for(r in i.events)x.removeEvent(t,r,i.handle);t.removeAttribute(x.expando)}\"script\"===n&&t.text!==e.text?(Ht(t).text=e.text,qt(t)):\"object\"===n?(t.parentNode&&(t.outerHTML=e.outerHTML),x.support.html5Clone&&e.innerHTML&&!x.trim(t.innerHTML)&&(t.innerHTML=e.innerHTML)):\"input\"===n&&Ct.test(e.type)?(t.defaultChecked=t.checked=e.checked,t.value!==e.value&&(t.value=e.value)):\"option\"===n?t.defaultSelected=t.selected=e.defaultSelected:(\"input\"===n||\"textarea\"===n)&&(t.defaultValue=e.defaultValue)}}x.each({appendTo:\"append\",prependTo:\"prepend\",insertBefore:\"before\",insertAfter:\"after\",replaceAll:\"replaceWith\"},function(e,t){x.fn[e]=function(e){var n,r=0,i=[],o=x(e),a=o.length-1;for(;a>=r;r++)n=r===a?this:this.clone(!0),x(o[r])[t](n),h.apply(i,n.get());return this.pushStack(i)}});function Ft(e,n){var r,o,a=0,s=typeof e.getElementsByTagName!==i?e.getElementsByTagName(n||\"*\"):typeof e.querySelectorAll!==i?e.querySelectorAll(n||\"*\"):t;if(!s)for(s=[],r=e.childNodes||e;null!=(o=r[a]);a++)!n||x.nodeName(o,n)?s.push(o):x.merge(s,Ft(o,n));return n===t||n&&x.nodeName(e,n)?x.merge([e],s):s}function Bt(e){Ct.test(e.type)&&(e.defaultChecked=e.checked)}x.extend({clone:function(e,t,n){var r,i,o,a,s,l=x.contains(e.ownerDocument,e);if(x.support.html5Clone||x.isXMLDoc(e)||!mt.test(\"<\"+e.nodeName+\">\")?o=e.cloneNode(!0):(Dt.innerHTML=e.outerHTML,Dt.removeChild(o=Dt.firstChild)),!(x.support.noCloneEvent&&x.support.noCloneChecked||1!==e.nodeType&&11!==e.nodeType||x.isXMLDoc(e)))for(r=Ft(o),s=Ft(e),a=0;null!=(i=s[a]);++a)r[a]&&Ot(i,r[a]);if(t)if(n)for(s=s||Ft(e),r=r||Ft(o),a=0;null!=(i=s[a]);a++)Mt(i,r[a]);else Mt(e,o);return r=Ft(o,\"script\"),r.length>0&&_t(r,!l&&Ft(e,\"script\")),r=s=i=null,o},buildFragment:function(e,t,n,r){var i,o,a,s,l,u,c,p=e.length,f=dt(t),d=[],h=0;for(;p>h;h++)if(o=e[h],o||0===o)if(\"object\"===x.type(o))x.merge(d,o.nodeType?[o]:o);else if(wt.test(o)){s=s||f.appendChild(t.createElement(\"div\")),l=(bt.exec(o)||[\"\",\"\"])[1].toLowerCase(),c=At[l]||At._default,s.innerHTML=c[1]+o.replace(vt,\"<$1></$2>\")+c[2],i=c[0];while(i--)s=s.lastChild;if(!x.support.leadingWhitespace&&yt.test(o)&&d.push(t.createTextNode(yt.exec(o)[0])),!x.support.tbody){o=\"table\"!==l||xt.test(o)?\"<table>\"!==c[1]||xt.test(o)?0:s:s.firstChild,i=o&&o.childNodes.length;while(i--)x.nodeName(u=o.childNodes[i],\"tbody\")&&!u.childNodes.length&&o.removeChild(u)}x.merge(d,s.childNodes),s.textContent=\"\";while(s.firstChild)s.removeChild(s.firstChild);s=f.lastChild}else d.push(t.createTextNode(o));s&&f.removeChild(s),x.support.appendChecked||x.grep(Ft(d,\"input\"),Bt),h=0;while(o=d[h++])if((!r||-1===x.inArray(o,r))&&(a=x.contains(o.ownerDocument,o),s=Ft(f.appendChild(o),\"script\"),a&&_t(s),n)){i=0;while(o=s[i++])kt.test(o.type||\"\")&&n.push(o)}return s=null,f},cleanData:function(e,t){var n,r,o,a,s=0,l=x.expando,u=x.cache,c=x.support.deleteExpando,f=x.event.special;for(;null!=(n=e[s]);s++)if((t||x.acceptData(n))&&(o=n[l],a=o&&u[o])){if(a.events)for(r in a.events)f[r]?x.event.remove(n,r):x.removeEvent(n,r,a.handle);\nu[o]&&(delete u[o],c?delete n[l]:typeof n.removeAttribute!==i?n.removeAttribute(l):n[l]=null,p.push(o))}},_evalUrl:function(e){return x.ajax({url:e,type:\"GET\",dataType:\"script\",async:!1,global:!1,\"throws\":!0})}}),x.fn.extend({wrapAll:function(e){if(x.isFunction(e))return this.each(function(t){x(this).wrapAll(e.call(this,t))});if(this[0]){var t=x(e,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&t.insertBefore(this[0]),t.map(function(){var e=this;while(e.firstChild&&1===e.firstChild.nodeType)e=e.firstChild;return e}).append(this)}return this},wrapInner:function(e){return x.isFunction(e)?this.each(function(t){x(this).wrapInner(e.call(this,t))}):this.each(function(){var t=x(this),n=t.contents();n.length?n.wrapAll(e):t.append(e)})},wrap:function(e){var t=x.isFunction(e);return this.each(function(n){x(this).wrapAll(t?e.call(this,n):e)})},unwrap:function(){return this.parent().each(function(){x.nodeName(this,\"body\")||x(this).replaceWith(this.childNodes)}).end()}});var Pt,Rt,Wt,$t=/alpha\\([^)]*\\)/i,It=/opacity\\s*=\\s*([^)]*)/,zt=/^(top|right|bottom|left)$/,Xt=/^(none|table(?!-c[ea]).+)/,Ut=/^margin/,Vt=RegExp(\"^(\"+w+\")(.*)$\",\"i\"),Yt=RegExp(\"^(\"+w+\")(?!px)[a-z%]+$\",\"i\"),Jt=RegExp(\"^([+-])=(\"+w+\")\",\"i\"),Gt={BODY:\"block\"},Qt={position:\"absolute\",visibility:\"hidden\",display:\"block\"},Kt={letterSpacing:0,fontWeight:400},Zt=[\"Top\",\"Right\",\"Bottom\",\"Left\"],en=[\"Webkit\",\"O\",\"Moz\",\"ms\"];function tn(e,t){if(t in e)return t;var n=t.charAt(0).toUpperCase()+t.slice(1),r=t,i=en.length;while(i--)if(t=en[i]+n,t in e)return t;return r}function nn(e,t){return e=t||e,\"none\"===x.css(e,\"display\")||!x.contains(e.ownerDocument,e)}function rn(e,t){var n,r,i,o=[],a=0,s=e.length;for(;s>a;a++)r=e[a],r.style&&(o[a]=x._data(r,\"olddisplay\"),n=r.style.display,t?(o[a]||\"none\"!==n||(r.style.display=\"\"),\"\"===r.style.display&&nn(r)&&(o[a]=x._data(r,\"olddisplay\",ln(r.nodeName)))):o[a]||(i=nn(r),(n&&\"none\"!==n||!i)&&x._data(r,\"olddisplay\",i?n:x.css(r,\"display\"))));for(a=0;s>a;a++)r=e[a],r.style&&(t&&\"none\"!==r.style.display&&\"\"!==r.style.display||(r.style.display=t?o[a]||\"\":\"none\"));return e}x.fn.extend({css:function(e,n){return x.access(this,function(e,n,r){var i,o,a={},s=0;if(x.isArray(n)){for(o=Rt(e),i=n.length;i>s;s++)a[n[s]]=x.css(e,n[s],!1,o);return a}return r!==t?x.style(e,n,r):x.css(e,n)},e,n,arguments.length>1)},show:function(){return rn(this,!0)},hide:function(){return rn(this)},toggle:function(e){return\"boolean\"==typeof e?e?this.show():this.hide():this.each(function(){nn(this)?x(this).show():x(this).hide()})}}),x.extend({cssHooks:{opacity:{get:function(e,t){if(t){var n=Wt(e,\"opacity\");return\"\"===n?\"1\":n}}}},cssNumber:{columnCount:!0,fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{\"float\":x.support.cssFloat?\"cssFloat\":\"styleFloat\"},style:function(e,n,r,i){if(e&&3!==e.nodeType&&8!==e.nodeType&&e.style){var o,a,s,l=x.camelCase(n),u=e.style;if(n=x.cssProps[l]||(x.cssProps[l]=tn(u,l)),s=x.cssHooks[n]||x.cssHooks[l],r===t)return s&&\"get\"in s&&(o=s.get(e,!1,i))!==t?o:u[n];if(a=typeof r,\"string\"===a&&(o=Jt.exec(r))&&(r=(o[1]+1)*o[2]+parseFloat(x.css(e,n)),a=\"number\"),!(null==r||\"number\"===a&&isNaN(r)||(\"number\"!==a||x.cssNumber[l]||(r+=\"px\"),x.support.clearCloneStyle||\"\"!==r||0!==n.indexOf(\"background\")||(u[n]=\"inherit\"),s&&\"set\"in s&&(r=s.set(e,r,i))===t)))try{u[n]=r}catch(c){}}},css:function(e,n,r,i){var o,a,s,l=x.camelCase(n);return n=x.cssProps[l]||(x.cssProps[l]=tn(e.style,l)),s=x.cssHooks[n]||x.cssHooks[l],s&&\"get\"in s&&(a=s.get(e,!0,r)),a===t&&(a=Wt(e,n,i)),\"normal\"===a&&n in Kt&&(a=Kt[n]),\"\"===r||r?(o=parseFloat(a),r===!0||x.isNumeric(o)?o||0:a):a}}),e.getComputedStyle?(Rt=function(t){return e.getComputedStyle(t,null)},Wt=function(e,n,r){var i,o,a,s=r||Rt(e),l=s?s.getPropertyValue(n)||s[n]:t,u=e.style;return s&&(\"\"!==l||x.contains(e.ownerDocument,e)||(l=x.style(e,n)),Yt.test(l)&&Ut.test(n)&&(i=u.width,o=u.minWidth,a=u.maxWidth,u.minWidth=u.maxWidth=u.width=l,l=s.width,u.width=i,u.minWidth=o,u.maxWidth=a)),l}):a.documentElement.currentStyle&&(Rt=function(e){return e.currentStyle},Wt=function(e,n,r){var i,o,a,s=r||Rt(e),l=s?s[n]:t,u=e.style;return null==l&&u&&u[n]&&(l=u[n]),Yt.test(l)&&!zt.test(n)&&(i=u.left,o=e.runtimeStyle,a=o&&o.left,a&&(o.left=e.currentStyle.left),u.left=\"fontSize\"===n?\"1em\":l,l=u.pixelLeft+\"px\",u.left=i,a&&(o.left=a)),\"\"===l?\"auto\":l});function on(e,t,n){var r=Vt.exec(t);return r?Math.max(0,r[1]-(n||0))+(r[2]||\"px\"):t}function an(e,t,n,r,i){var o=n===(r?\"border\":\"content\")?4:\"width\"===t?1:0,a=0;for(;4>o;o+=2)\"margin\"===n&&(a+=x.css(e,n+Zt[o],!0,i)),r?(\"content\"===n&&(a-=x.css(e,\"padding\"+Zt[o],!0,i)),\"margin\"!==n&&(a-=x.css(e,\"border\"+Zt[o]+\"Width\",!0,i))):(a+=x.css(e,\"padding\"+Zt[o],!0,i),\"padding\"!==n&&(a+=x.css(e,\"border\"+Zt[o]+\"Width\",!0,i)));return a}function sn(e,t,n){var r=!0,i=\"width\"===t?e.offsetWidth:e.offsetHeight,o=Rt(e),a=x.support.boxSizing&&\"border-box\"===x.css(e,\"boxSizing\",!1,o);if(0>=i||null==i){if(i=Wt(e,t,o),(0>i||null==i)&&(i=e.style[t]),Yt.test(i))return i;r=a&&(x.support.boxSizingReliable||i===e.style[t]),i=parseFloat(i)||0}return i+an(e,t,n||(a?\"border\":\"content\"),r,o)+\"px\"}function ln(e){var t=a,n=Gt[e];return n||(n=un(e,t),\"none\"!==n&&n||(Pt=(Pt||x(\"<iframe frameborder='0' width='0' height='0'/>\").css(\"cssText\",\"display:block !important\")).appendTo(t.documentElement),t=(Pt[0].contentWindow||Pt[0].contentDocument).document,t.write(\"<!doctype html><html><body>\"),t.close(),n=un(e,t),Pt.detach()),Gt[e]=n),n}function un(e,t){var n=x(t.createElement(e)).appendTo(t.body),r=x.css(n[0],\"display\");return n.remove(),r}x.each([\"height\",\"width\"],function(e,n){x.cssHooks[n]={get:function(e,r,i){return r?0===e.offsetWidth&&Xt.test(x.css(e,\"display\"))?x.swap(e,Qt,function(){return sn(e,n,i)}):sn(e,n,i):t},set:function(e,t,r){var i=r&&Rt(e);return on(e,t,r?an(e,n,r,x.support.boxSizing&&\"border-box\"===x.css(e,\"boxSizing\",!1,i),i):0)}}}),x.support.opacity||(x.cssHooks.opacity={get:function(e,t){return It.test((t&&e.currentStyle?e.currentStyle.filter:e.style.filter)||\"\")?.01*parseFloat(RegExp.$1)+\"\":t?\"1\":\"\"},set:function(e,t){var n=e.style,r=e.currentStyle,i=x.isNumeric(t)?\"alpha(opacity=\"+100*t+\")\":\"\",o=r&&r.filter||n.filter||\"\";n.zoom=1,(t>=1||\"\"===t)&&\"\"===x.trim(o.replace($t,\"\"))&&n.removeAttribute&&(n.removeAttribute(\"filter\"),\"\"===t||r&&!r.filter)||(n.filter=$t.test(o)?o.replace($t,i):o+\" \"+i)}}),x(function(){x.support.reliableMarginRight||(x.cssHooks.marginRight={get:function(e,n){return n?x.swap(e,{display:\"inline-block\"},Wt,[e,\"marginRight\"]):t}}),!x.support.pixelPosition&&x.fn.position&&x.each([\"top\",\"left\"],function(e,n){x.cssHooks[n]={get:function(e,r){return r?(r=Wt(e,n),Yt.test(r)?x(e).position()[n]+\"px\":r):t}}})}),x.expr&&x.expr.filters&&(x.expr.filters.hidden=function(e){return 0>=e.offsetWidth&&0>=e.offsetHeight||!x.support.reliableHiddenOffsets&&\"none\"===(e.style&&e.style.display||x.css(e,\"display\"))},x.expr.filters.visible=function(e){return!x.expr.filters.hidden(e)}),x.each({margin:\"\",padding:\"\",border:\"Width\"},function(e,t){x.cssHooks[e+t]={expand:function(n){var r=0,i={},o=\"string\"==typeof n?n.split(\" \"):[n];for(;4>r;r++)i[e+Zt[r]+t]=o[r]||o[r-2]||o[0];return i}},Ut.test(e)||(x.cssHooks[e+t].set=on)});var cn=/%20/g,pn=/\\[\\]$/,fn=/\\r?\\n/g,dn=/^(?:submit|button|image|reset|file)$/i,hn=/^(?:input|select|textarea|keygen)/i;x.fn.extend({serialize:function(){return x.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var e=x.prop(this,\"elements\");return e?x.makeArray(e):this}).filter(function(){var e=this.type;return this.name&&!x(this).is(\":disabled\")&&hn.test(this.nodeName)&&!dn.test(e)&&(this.checked||!Ct.test(e))}).map(function(e,t){var n=x(this).val();return null==n?null:x.isArray(n)?x.map(n,function(e){return{name:t.name,value:e.replace(fn,\"\\r\\n\")}}):{name:t.name,value:n.replace(fn,\"\\r\\n\")}}).get()}}),x.param=function(e,n){var r,i=[],o=function(e,t){t=x.isFunction(t)?t():null==t?\"\":t,i[i.length]=encodeURIComponent(e)+\"=\"+encodeURIComponent(t)};if(n===t&&(n=x.ajaxSettings&&x.ajaxSettings.traditional),x.isArray(e)||e.jquery&&!x.isPlainObject(e))x.each(e,function(){o(this.name,this.value)});else for(r in e)gn(r,e[r],n,o);return i.join(\"&\").replace(cn,\"+\")};function gn(e,t,n,r){var i;if(x.isArray(t))x.each(t,function(t,i){n||pn.test(e)?r(e,i):gn(e+\"[\"+(\"object\"==typeof i?t:\"\")+\"]\",i,n,r)});else if(n||\"object\"!==x.type(t))r(e,t);else for(i in t)gn(e+\"[\"+i+\"]\",t[i],n,r)}x.each(\"blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error contextmenu\".split(\" \"),function(e,t){x.fn[t]=function(e,n){return arguments.length>0?this.on(t,null,e,n):this.trigger(t)}}),x.fn.extend({hover:function(e,t){return this.mouseenter(e).mouseleave(t||e)},bind:function(e,t,n){return this.on(e,null,t,n)},unbind:function(e,t){return this.off(e,null,t)},delegate:function(e,t,n,r){return this.on(t,e,n,r)},undelegate:function(e,t,n){return 1===arguments.length?this.off(e,\"**\"):this.off(t,e||\"**\",n)}});var mn,yn,vn=x.now(),bn=/\\?/,xn=/#.*$/,wn=/([?&])_=[^&]*/,Tn=/^(.*?):[ \\t]*([^\\r\\n]*)\\r?$/gm,Cn=/^(?:about|app|app-storage|.+-extension|file|res|widget):$/,Nn=/^(?:GET|HEAD)$/,kn=/^\\/\\//,En=/^([\\w.+-]+:)(?:\\/\\/([^\\/?#:]*)(?::(\\d+)|)|)/,Sn=x.fn.load,An={},jn={},Dn=\"*/\".concat(\"*\");try{yn=o.href}catch(Ln){yn=a.createElement(\"a\"),yn.href=\"\",yn=yn.href}mn=En.exec(yn.toLowerCase())||[];function Hn(e){return function(t,n){\"string\"!=typeof t&&(n=t,t=\"*\");var r,i=0,o=t.toLowerCase().match(T)||[];if(x.isFunction(n))while(r=o[i++])\"+\"===r[0]?(r=r.slice(1)||\"*\",(e[r]=e[r]||[]).unshift(n)):(e[r]=e[r]||[]).push(n)}}function qn(e,n,r,i){var o={},a=e===jn;function s(l){var u;return o[l]=!0,x.each(e[l]||[],function(e,l){var c=l(n,r,i);return\"string\"!=typeof c||a||o[c]?a?!(u=c):t:(n.dataTypes.unshift(c),s(c),!1)}),u}return s(n.dataTypes[0])||!o[\"*\"]&&s(\"*\")}function _n(e,n){var r,i,o=x.ajaxSettings.flatOptions||{};for(i in n)n[i]!==t&&((o[i]?e:r||(r={}))[i]=n[i]);return r&&x.extend(!0,e,r),e}x.fn.load=function(e,n,r){if(\"string\"!=typeof e&&Sn)return Sn.apply(this,arguments);var i,o,a,s=this,l=e.indexOf(\" \");return l>=0&&(i=e.slice(l,e.length),e=e.slice(0,l)),x.isFunction(n)?(r=n,n=t):n&&\"object\"==typeof n&&(a=\"POST\"),s.length>0&&x.ajax({url:e,type:a,dataType:\"html\",data:n}).done(function(e){o=arguments,s.html(i?x(\"<div>\").append(x.parseHTML(e)).find(i):e)}).complete(r&&function(e,t){s.each(r,o||[e.responseText,t,e])}),this},x.each([\"ajaxStart\",\"ajaxStop\",\"ajaxComplete\",\"ajaxError\",\"ajaxSuccess\",\"ajaxSend\"],function(e,t){x.fn[t]=function(e){return this.on(t,e)}}),x.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:yn,type:\"GET\",isLocal:Cn.test(mn[1]),global:!0,processData:!0,async:!0,contentType:\"application/x-www-form-urlencoded; charset=UTF-8\",accepts:{\"*\":Dn,text:\"text/plain\",html:\"text/html\",xml:\"application/xml, text/xml\",json:\"application/json, text/javascript\"},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:\"responseXML\",text:\"responseText\",json:\"responseJSON\"},converters:{\"* text\":String,\"text html\":!0,\"text json\":x.parseJSON,\"text xml\":x.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(e,t){return t?_n(_n(e,x.ajaxSettings),t):_n(x.ajaxSettings,e)},ajaxPrefilter:Hn(An),ajaxTransport:Hn(jn),ajax:function(e,n){\"object\"==typeof e&&(n=e,e=t),n=n||{};var r,i,o,a,s,l,u,c,p=x.ajaxSetup({},n),f=p.context||p,d=p.context&&(f.nodeType||f.jquery)?x(f):x.event,h=x.Deferred(),g=x.Callbacks(\"once memory\"),m=p.statusCode||{},y={},v={},b=0,w=\"canceled\",C={readyState:0,getResponseHeader:function(e){var t;if(2===b){if(!c){c={};while(t=Tn.exec(a))c[t[1].toLowerCase()]=t[2]}t=c[e.toLowerCase()]}return null==t?null:t},getAllResponseHeaders:function(){return 2===b?a:null},setRequestHeader:function(e,t){var n=e.toLowerCase();return b||(e=v[n]=v[n]||e,y[e]=t),this},overrideMimeType:function(e){return b||(p.mimeType=e),this},statusCode:function(e){var t;if(e)if(2>b)for(t in e)m[t]=[m[t],e[t]];else C.always(e[C.status]);return this},abort:function(e){var t=e||w;return u&&u.abort(t),k(0,t),this}};if(h.promise(C).complete=g.add,C.success=C.done,C.error=C.fail,p.url=((e||p.url||yn)+\"\").replace(xn,\"\").replace(kn,mn[1]+\"//\"),p.type=n.method||n.type||p.method||p.type,p.dataTypes=x.trim(p.dataType||\"*\").toLowerCase().match(T)||[\"\"],null==p.crossDomain&&(r=En.exec(p.url.toLowerCase()),p.crossDomain=!(!r||r[1]===mn[1]&&r[2]===mn[2]&&(r[3]||(\"http:\"===r[1]?\"80\":\"443\"))===(mn[3]||(\"http:\"===mn[1]?\"80\":\"443\")))),p.data&&p.processData&&\"string\"!=typeof p.data&&(p.data=x.param(p.data,p.traditional)),qn(An,p,n,C),2===b)return C;l=p.global,l&&0===x.active++&&x.event.trigger(\"ajaxStart\"),p.type=p.type.toUpperCase(),p.hasContent=!Nn.test(p.type),o=p.url,p.hasContent||(p.data&&(o=p.url+=(bn.test(o)?\"&\":\"?\")+p.data,delete p.data),p.cache===!1&&(p.url=wn.test(o)?o.replace(wn,\"$1_=\"+vn++):o+(bn.test(o)?\"&\":\"?\")+\"_=\"+vn++)),p.ifModified&&(x.lastModified[o]&&C.setRequestHeader(\"If-Modified-Since\",x.lastModified[o]),x.etag[o]&&C.setRequestHeader(\"If-None-Match\",x.etag[o])),(p.data&&p.hasContent&&p.contentType!==!1||n.contentType)&&C.setRequestHeader(\"Content-Type\",p.contentType),C.setRequestHeader(\"Accept\",p.dataTypes[0]&&p.accepts[p.dataTypes[0]]?p.accepts[p.dataTypes[0]]+(\"*\"!==p.dataTypes[0]?\", \"+Dn+\"; q=0.01\":\"\"):p.accepts[\"*\"]);for(i in p.headers)C.setRequestHeader(i,p.headers[i]);if(p.beforeSend&&(p.beforeSend.call(f,C,p)===!1||2===b))return C.abort();w=\"abort\";for(i in{success:1,error:1,complete:1})C[i](p[i]);if(u=qn(jn,p,n,C)){C.readyState=1,l&&d.trigger(\"ajaxSend\",[C,p]),p.async&&p.timeout>0&&(s=setTimeout(function(){C.abort(\"timeout\")},p.timeout));try{b=1,u.send(y,k)}catch(N){if(!(2>b))throw N;k(-1,N)}}else k(-1,\"No Transport\");function k(e,n,r,i){var c,y,v,w,T,N=n;2!==b&&(b=2,s&&clearTimeout(s),u=t,a=i||\"\",C.readyState=e>0?4:0,c=e>=200&&300>e||304===e,r&&(w=Mn(p,C,r)),w=On(p,w,C,c),c?(p.ifModified&&(T=C.getResponseHeader(\"Last-Modified\"),T&&(x.lastModified[o]=T),T=C.getResponseHeader(\"etag\"),T&&(x.etag[o]=T)),204===e||\"HEAD\"===p.type?N=\"nocontent\":304===e?N=\"notmodified\":(N=w.state,y=w.data,v=w.error,c=!v)):(v=N,(e||!N)&&(N=\"error\",0>e&&(e=0))),C.status=e,C.statusText=(n||N)+\"\",c?h.resolveWith(f,[y,N,C]):h.rejectWith(f,[C,N,v]),C.statusCode(m),m=t,l&&d.trigger(c?\"ajaxSuccess\":\"ajaxError\",[C,p,c?y:v]),g.fireWith(f,[C,N]),l&&(d.trigger(\"ajaxComplete\",[C,p]),--x.active||x.event.trigger(\"ajaxStop\")))}return C},getJSON:function(e,t,n){return x.get(e,t,n,\"json\")},getScript:function(e,n){return x.get(e,t,n,\"script\")}}),x.each([\"get\",\"post\"],function(e,n){x[n]=function(e,r,i,o){return x.isFunction(r)&&(o=o||i,i=r,r=t),x.ajax({url:e,type:n,dataType:o,data:r,success:i})}});function Mn(e,n,r){var i,o,a,s,l=e.contents,u=e.dataTypes;while(\"*\"===u[0])u.shift(),o===t&&(o=e.mimeType||n.getResponseHeader(\"Content-Type\"));if(o)for(s in l)if(l[s]&&l[s].test(o)){u.unshift(s);break}if(u[0]in r)a=u[0];else{for(s in r){if(!u[0]||e.converters[s+\" \"+u[0]]){a=s;break}i||(i=s)}a=a||i}return a?(a!==u[0]&&u.unshift(a),r[a]):t}function On(e,t,n,r){var i,o,a,s,l,u={},c=e.dataTypes.slice();if(c[1])for(a in e.converters)u[a.toLowerCase()]=e.converters[a];o=c.shift();while(o)if(e.responseFields[o]&&(n[e.responseFields[o]]=t),!l&&r&&e.dataFilter&&(t=e.dataFilter(t,e.dataType)),l=o,o=c.shift())if(\"*\"===o)o=l;else if(\"*\"!==l&&l!==o){if(a=u[l+\" \"+o]||u[\"* \"+o],!a)for(i in u)if(s=i.split(\" \"),s[1]===o&&(a=u[l+\" \"+s[0]]||u[\"* \"+s[0]])){a===!0?a=u[i]:u[i]!==!0&&(o=s[0],c.unshift(s[1]));break}if(a!==!0)if(a&&e[\"throws\"])t=a(t);else try{t=a(t)}catch(p){return{state:\"parsererror\",error:a?p:\"No conversion from \"+l+\" to \"+o}}}return{state:\"success\",data:t}}x.ajaxSetup({accepts:{script:\"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript\"},contents:{script:/(?:java|ecma)script/},converters:{\"text script\":function(e){return x.globalEval(e),e}}}),x.ajaxPrefilter(\"script\",function(e){e.cache===t&&(e.cache=!1),e.crossDomain&&(e.type=\"GET\",e.global=!1)}),x.ajaxTransport(\"script\",function(e){if(e.crossDomain){var n,r=a.head||x(\"head\")[0]||a.documentElement;return{send:function(t,i){n=a.createElement(\"script\"),n.async=!0,e.scriptCharset&&(n.charset=e.scriptCharset),n.src=e.url,n.onload=n.onreadystatechange=function(e,t){(t||!n.readyState||/loaded|complete/.test(n.readyState))&&(n.onload=n.onreadystatechange=null,n.parentNode&&n.parentNode.removeChild(n),n=null,t||i(200,\"success\"))},r.insertBefore(n,r.firstChild)},abort:function(){n&&n.onload(t,!0)}}}});var Fn=[],Bn=/(=)\\?(?=&|$)|\\?\\?/;x.ajaxSetup({jsonp:\"callback\",jsonpCallback:function(){var e=Fn.pop()||x.expando+\"_\"+vn++;return this[e]=!0,e}}),x.ajaxPrefilter(\"json jsonp\",function(n,r,i){var o,a,s,l=n.jsonp!==!1&&(Bn.test(n.url)?\"url\":\"string\"==typeof n.data&&!(n.contentType||\"\").indexOf(\"application/x-www-form-urlencoded\")&&Bn.test(n.data)&&\"data\");return l||\"jsonp\"===n.dataTypes[0]?(o=n.jsonpCallback=x.isFunction(n.jsonpCallback)?n.jsonpCallback():n.jsonpCallback,l?n[l]=n[l].replace(Bn,\"$1\"+o):n.jsonp!==!1&&(n.url+=(bn.test(n.url)?\"&\":\"?\")+n.jsonp+\"=\"+o),n.converters[\"script json\"]=function(){return s||x.error(o+\" was not called\"),s[0]},n.dataTypes[0]=\"json\",a=e[o],e[o]=function(){s=arguments},i.always(function(){e[o]=a,n[o]&&(n.jsonpCallback=r.jsonpCallback,Fn.push(o)),s&&x.isFunction(a)&&a(s[0]),s=a=t}),\"script\"):t});var Pn,Rn,Wn=0,$n=e.ActiveXObject&&function(){var e;for(e in Pn)Pn[e](t,!0)};function In(){try{return new e.XMLHttpRequest}catch(t){}}function zn(){try{return new e.ActiveXObject(\"Microsoft.XMLHTTP\")}catch(t){}}x.ajaxSettings.xhr=e.ActiveXObject?function(){return!this.isLocal&&In()||zn()}:In,Rn=x.ajaxSettings.xhr(),x.support.cors=!!Rn&&\"withCredentials\"in Rn,Rn=x.support.ajax=!!Rn,Rn&&x.ajaxTransport(function(n){if(!n.crossDomain||x.support.cors){var r;return{send:function(i,o){var a,s,l=n.xhr();if(n.username?l.open(n.type,n.url,n.async,n.username,n.password):l.open(n.type,n.url,n.async),n.xhrFields)for(s in n.xhrFields)l[s]=n.xhrFields[s];n.mimeType&&l.overrideMimeType&&l.overrideMimeType(n.mimeType),n.crossDomain||i[\"X-Requested-With\"]||(i[\"X-Requested-With\"]=\"XMLHttpRequest\");try{for(s in i)l.setRequestHeader(s,i[s])}catch(u){}l.send(n.hasContent&&n.data||null),r=function(e,i){var s,u,c,p;try{if(r&&(i||4===l.readyState))if(r=t,a&&(l.onreadystatechange=x.noop,$n&&delete Pn[a]),i)4!==l.readyState&&l.abort();else{p={},s=l.status,u=l.getAllResponseHeaders(),\"string\"==typeof l.responseText&&(p.text=l.responseText);try{c=l.statusText}catch(f){c=\"\"}s||!n.isLocal||n.crossDomain?1223===s&&(s=204):s=p.text?200:404}}catch(d){i||o(-1,d)}p&&o(s,c,p,u)},n.async?4===l.readyState?setTimeout(r):(a=++Wn,$n&&(Pn||(Pn={},x(e).unload($n)),Pn[a]=r),l.onreadystatechange=r):r()},abort:function(){r&&r(t,!0)}}}});var Xn,Un,Vn=/^(?:toggle|show|hide)$/,Yn=RegExp(\"^(?:([+-])=|)(\"+w+\")([a-z%]*)$\",\"i\"),Jn=/queueHooks$/,Gn=[nr],Qn={\"*\":[function(e,t){var n=this.createTween(e,t),r=n.cur(),i=Yn.exec(t),o=i&&i[3]||(x.cssNumber[e]?\"\":\"px\"),a=(x.cssNumber[e]||\"px\"!==o&&+r)&&Yn.exec(x.css(n.elem,e)),s=1,l=20;if(a&&a[3]!==o){o=o||a[3],i=i||[],a=+r||1;do s=s||\".5\",a/=s,x.style(n.elem,e,a+o);while(s!==(s=n.cur()/r)&&1!==s&&--l)}return i&&(a=n.start=+a||+r||0,n.unit=o,n.end=i[1]?a+(i[1]+1)*i[2]:+i[2]),n}]};function Kn(){return setTimeout(function(){Xn=t}),Xn=x.now()}function Zn(e,t,n){var r,i=(Qn[t]||[]).concat(Qn[\"*\"]),o=0,a=i.length;for(;a>o;o++)if(r=i[o].call(n,t,e))return r}function er(e,t,n){var r,i,o=0,a=Gn.length,s=x.Deferred().always(function(){delete l.elem}),l=function(){if(i)return!1;var t=Xn||Kn(),n=Math.max(0,u.startTime+u.duration-t),r=n/u.duration||0,o=1-r,a=0,l=u.tweens.length;for(;l>a;a++)u.tweens[a].run(o);return s.notifyWith(e,[u,o,n]),1>o&&l?n:(s.resolveWith(e,[u]),!1)},u=s.promise({elem:e,props:x.extend({},t),opts:x.extend(!0,{specialEasing:{}},n),originalProperties:t,originalOptions:n,startTime:Xn||Kn(),duration:n.duration,tweens:[],createTween:function(t,n){var r=x.Tween(e,u.opts,t,n,u.opts.specialEasing[t]||u.opts.easing);return u.tweens.push(r),r},stop:function(t){var n=0,r=t?u.tweens.length:0;if(i)return this;for(i=!0;r>n;n++)u.tweens[n].run(1);return t?s.resolveWith(e,[u,t]):s.rejectWith(e,[u,t]),this}}),c=u.props;for(tr(c,u.opts.specialEasing);a>o;o++)if(r=Gn[o].call(u,e,c,u.opts))return r;return x.map(c,Zn,u),x.isFunction(u.opts.start)&&u.opts.start.call(e,u),x.fx.timer(x.extend(l,{elem:e,anim:u,queue:u.opts.queue})),u.progress(u.opts.progress).done(u.opts.done,u.opts.complete).fail(u.opts.fail).always(u.opts.always)}function tr(e,t){var n,r,i,o,a;for(n in e)if(r=x.camelCase(n),i=t[r],o=e[n],x.isArray(o)&&(i=o[1],o=e[n]=o[0]),n!==r&&(e[r]=o,delete e[n]),a=x.cssHooks[r],a&&\"expand\"in a){o=a.expand(o),delete e[r];for(n in o)n in e||(e[n]=o[n],t[n]=i)}else t[r]=i}x.Animation=x.extend(er,{tweener:function(e,t){x.isFunction(e)?(t=e,e=[\"*\"]):e=e.split(\" \");var n,r=0,i=e.length;for(;i>r;r++)n=e[r],Qn[n]=Qn[n]||[],Qn[n].unshift(t)},prefilter:function(e,t){t?Gn.unshift(e):Gn.push(e)}});function nr(e,t,n){var r,i,o,a,s,l,u=this,c={},p=e.style,f=e.nodeType&&nn(e),d=x._data(e,\"fxshow\");n.queue||(s=x._queueHooks(e,\"fx\"),null==s.unqueued&&(s.unqueued=0,l=s.empty.fire,s.empty.fire=function(){s.unqueued||l()}),s.unqueued++,u.always(function(){u.always(function(){s.unqueued--,x.queue(e,\"fx\").length||s.empty.fire()})})),1===e.nodeType&&(\"height\"in t||\"width\"in t)&&(n.overflow=[p.overflow,p.overflowX,p.overflowY],\"inline\"===x.css(e,\"display\")&&\"none\"===x.css(e,\"float\")&&(x.support.inlineBlockNeedsLayout&&\"inline\"!==ln(e.nodeName)?p.zoom=1:p.display=\"inline-block\")),n.overflow&&(p.overflow=\"hidden\",x.support.shrinkWrapBlocks||u.always(function(){p.overflow=n.overflow[0],p.overflowX=n.overflow[1],p.overflowY=n.overflow[2]}));for(r in t)if(i=t[r],Vn.exec(i)){if(delete t[r],o=o||\"toggle\"===i,i===(f?\"hide\":\"show\"))continue;c[r]=d&&d[r]||x.style(e,r)}if(!x.isEmptyObject(c)){d?\"hidden\"in d&&(f=d.hidden):d=x._data(e,\"fxshow\",{}),o&&(d.hidden=!f),f?x(e).show():u.done(function(){x(e).hide()}),u.done(function(){var t;x._removeData(e,\"fxshow\");for(t in c)x.style(e,t,c[t])});for(r in c)a=Zn(f?d[r]:0,r,u),r in d||(d[r]=a.start,f&&(a.end=a.start,a.start=\"width\"===r||\"height\"===r?1:0))}}function rr(e,t,n,r,i){return new rr.prototype.init(e,t,n,r,i)}x.Tween=rr,rr.prototype={constructor:rr,init:function(e,t,n,r,i,o){this.elem=e,this.prop=n,this.easing=i||\"swing\",this.options=t,this.start=this.now=this.cur(),this.end=r,this.unit=o||(x.cssNumber[n]?\"\":\"px\")},cur:function(){var e=rr.propHooks[this.prop];return e&&e.get?e.get(this):rr.propHooks._default.get(this)},run:function(e){var t,n=rr.propHooks[this.prop];return this.pos=t=this.options.duration?x.easing[this.easing](e,this.options.duration*e,0,1,this.options.duration):e,this.now=(this.end-this.start)*t+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),n&&n.set?n.set(this):rr.propHooks._default.set(this),this}},rr.prototype.init.prototype=rr.prototype,rr.propHooks={_default:{get:function(e){var t;return null==e.elem[e.prop]||e.elem.style&&null!=e.elem.style[e.prop]?(t=x.css(e.elem,e.prop,\"\"),t&&\"auto\"!==t?t:0):e.elem[e.prop]},set:function(e){x.fx.step[e.prop]?x.fx.step[e.prop](e):e.elem.style&&(null!=e.elem.style[x.cssProps[e.prop]]||x.cssHooks[e.prop])?x.style(e.elem,e.prop,e.now+e.unit):e.elem[e.prop]=e.now}}},rr.propHooks.scrollTop=rr.propHooks.scrollLeft={set:function(e){e.elem.nodeType&&e.elem.parentNode&&(e.elem[e.prop]=e.now)}},x.each([\"toggle\",\"show\",\"hide\"],function(e,t){var n=x.fn[t];x.fn[t]=function(e,r,i){return null==e||\"boolean\"==typeof e?n.apply(this,arguments):this.animate(ir(t,!0),e,r,i)}}),x.fn.extend({fadeTo:function(e,t,n,r){return this.filter(nn).css(\"opacity\",0).show().end().animate({opacity:t},e,n,r)},animate:function(e,t,n,r){var i=x.isEmptyObject(e),o=x.speed(t,n,r),a=function(){var t=er(this,x.extend({},e),o);(i||x._data(this,\"finish\"))&&t.stop(!0)};return a.finish=a,i||o.queue===!1?this.each(a):this.queue(o.queue,a)},stop:function(e,n,r){var i=function(e){var t=e.stop;delete e.stop,t(r)};return\"string\"!=typeof e&&(r=n,n=e,e=t),n&&e!==!1&&this.queue(e||\"fx\",[]),this.each(function(){var t=!0,n=null!=e&&e+\"queueHooks\",o=x.timers,a=x._data(this);if(n)a[n]&&a[n].stop&&i(a[n]);else for(n in a)a[n]&&a[n].stop&&Jn.test(n)&&i(a[n]);for(n=o.length;n--;)o[n].elem!==this||null!=e&&o[n].queue!==e||(o[n].anim.stop(r),t=!1,o.splice(n,1));(t||!r)&&x.dequeue(this,e)})},finish:function(e){return e!==!1&&(e=e||\"fx\"),this.each(function(){var t,n=x._data(this),r=n[e+\"queue\"],i=n[e+\"queueHooks\"],o=x.timers,a=r?r.length:0;for(n.finish=!0,x.queue(this,e,[]),i&&i.stop&&i.stop.call(this,!0),t=o.length;t--;)o[t].elem===this&&o[t].queue===e&&(o[t].anim.stop(!0),o.splice(t,1));for(t=0;a>t;t++)r[t]&&r[t].finish&&r[t].finish.call(this);delete n.finish})}});function ir(e,t){var n,r={height:e},i=0;for(t=t?1:0;4>i;i+=2-t)n=Zt[i],r[\"margin\"+n]=r[\"padding\"+n]=e;return t&&(r.opacity=r.width=e),r}x.each({slideDown:ir(\"show\"),slideUp:ir(\"hide\"),slideToggle:ir(\"toggle\"),fadeIn:{opacity:\"show\"},fadeOut:{opacity:\"hide\"},fadeToggle:{opacity:\"toggle\"}},function(e,t){x.fn[e]=function(e,n,r){return this.animate(t,e,n,r)}}),x.speed=function(e,t,n){var r=e&&\"object\"==typeof e?x.extend({},e):{complete:n||!n&&t||x.isFunction(e)&&e,duration:e,easing:n&&t||t&&!x.isFunction(t)&&t};return r.duration=x.fx.off?0:\"number\"==typeof r.duration?r.duration:r.duration in x.fx.speeds?x.fx.speeds[r.duration]:x.fx.speeds._default,(null==r.queue||r.queue===!0)&&(r.queue=\"fx\"),r.old=r.complete,r.complete=function(){x.isFunction(r.old)&&r.old.call(this),r.queue&&x.dequeue(this,r.queue)},r},x.easing={linear:function(e){return e},swing:function(e){return.5-Math.cos(e*Math.PI)/2}},x.timers=[],x.fx=rr.prototype.init,x.fx.tick=function(){var e,n=x.timers,r=0;for(Xn=x.now();n.length>r;r++)e=n[r],e()||n[r]!==e||n.splice(r--,1);n.length||x.fx.stop(),Xn=t},x.fx.timer=function(e){e()&&x.timers.push(e)&&x.fx.start()},x.fx.interval=13,x.fx.start=function(){Un||(Un=setInterval(x.fx.tick,x.fx.interval))},x.fx.stop=function(){clearInterval(Un),Un=null},x.fx.speeds={slow:600,fast:200,_default:400},x.fx.step={},x.expr&&x.expr.filters&&(x.expr.filters.animated=function(e){return x.grep(x.timers,function(t){return e===t.elem}).length}),x.fn.offset=function(e){if(arguments.length)return e===t?this:this.each(function(t){x.offset.setOffset(this,e,t)});var n,r,o={top:0,left:0},a=this[0],s=a&&a.ownerDocument;if(s)return n=s.documentElement,x.contains(n,a)?(typeof a.getBoundingClientRect!==i&&(o=a.getBoundingClientRect()),r=or(s),{top:o.top+(r.pageYOffset||n.scrollTop)-(n.clientTop||0),left:o.left+(r.pageXOffset||n.scrollLeft)-(n.clientLeft||0)}):o},x.offset={setOffset:function(e,t,n){var r=x.css(e,\"position\");\"static\"===r&&(e.style.position=\"relative\");var i=x(e),o=i.offset(),a=x.css(e,\"top\"),s=x.css(e,\"left\"),l=(\"absolute\"===r||\"fixed\"===r)&&x.inArray(\"auto\",[a,s])>-1,u={},c={},p,f;l?(c=i.position(),p=c.top,f=c.left):(p=parseFloat(a)||0,f=parseFloat(s)||0),x.isFunction(t)&&(t=t.call(e,n,o)),null!=t.top&&(u.top=t.top-o.top+p),null!=t.left&&(u.left=t.left-o.left+f),\"using\"in t?t.using.call(e,u):i.css(u)}},x.fn.extend({position:function(){if(this[0]){var e,t,n={top:0,left:0},r=this[0];return\"fixed\"===x.css(r,\"position\")?t=r.getBoundingClientRect():(e=this.offsetParent(),t=this.offset(),x.nodeName(e[0],\"html\")||(n=e.offset()),n.top+=x.css(e[0],\"borderTopWidth\",!0),n.left+=x.css(e[0],\"borderLeftWidth\",!0)),{top:t.top-n.top-x.css(r,\"marginTop\",!0),left:t.left-n.left-x.css(r,\"marginLeft\",!0)}}},offsetParent:function(){return this.map(function(){var e=this.offsetParent||s;while(e&&!x.nodeName(e,\"html\")&&\"static\"===x.css(e,\"position\"))e=e.offsetParent;return e||s})}}),x.each({scrollLeft:\"pageXOffset\",scrollTop:\"pageYOffset\"},function(e,n){var r=/Y/.test(n);x.fn[e]=function(i){return x.access(this,function(e,i,o){var a=or(e);return o===t?a?n in a?a[n]:a.document.documentElement[i]:e[i]:(a?a.scrollTo(r?x(a).scrollLeft():o,r?o:x(a).scrollTop()):e[i]=o,t)},e,i,arguments.length,null)}});function or(e){return x.isWindow(e)?e:9===e.nodeType?e.defaultView||e.parentWindow:!1}x.each({Height:\"height\",Width:\"width\"},function(e,n){x.each({padding:\"inner\"+e,content:n,\"\":\"outer\"+e},function(r,i){x.fn[i]=function(i,o){var a=arguments.length&&(r||\"boolean\"!=typeof i),s=r||(i===!0||o===!0?\"margin\":\"border\");return x.access(this,function(n,r,i){var o;return x.isWindow(n)?n.document.documentElement[\"client\"+e]:9===n.nodeType?(o=n.documentElement,Math.max(n.body[\"scroll\"+e],o[\"scroll\"+e],n.body[\"offset\"+e],o[\"offset\"+e],o[\"client\"+e])):i===t?x.css(n,r,s):x.style(n,r,i,s)},n,a?i:t,a,null)}})}),x.fn.size=function(){return this.length},x.fn.andSelf=x.fn.addBack,\"object\"==typeof module&&module&&\"object\"==typeof module.exports?module.exports=x:(e.jQuery=e.$=x,\"function\"==typeof define&&define.amd&&define(\"jquery\",[],function(){return x}))})(window);"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/sass-bootstrap/js/tests/vendor/qunit.css",
    "content": "/**\n * QUnit - A JavaScript Unit Testing Framework\n *\n * http://docs.jquery.com/QUnit\n *\n * Copyright (c) 2012 John Resig, Jörn Zaefferer\n * Dual licensed under the MIT (MIT-LICENSE.txt)\n * or GPL (GPL-LICENSE.txt) licenses.\n */\n\n/** Font Family and Sizes */\n\n#qunit-tests, #qunit-header, #qunit-banner, #qunit-testrunner-toolbar, #qunit-userAgent, #qunit-testresult {\n\tfont-family: \"Helvetica Neue Light\", \"HelveticaNeue-Light\", \"Helvetica Neue\", Calibri, Helvetica, Arial, sans-serif;\n}\n\n#qunit-testrunner-toolbar, #qunit-userAgent, #qunit-testresult, #qunit-tests li { font-size: small; }\n#qunit-tests { font-size: smaller; }\n\n\n/** Resets */\n\n#qunit-tests, #qunit-tests ol, #qunit-header, #qunit-banner, #qunit-userAgent, #qunit-testresult {\n\tmargin: 0;\n\tpadding: 0;\n}\n\n\n/** Header */\n\n#qunit-header {\n\tpadding: 0.5em 0 0.5em 1em;\n\n\tcolor: #8699a4;\n\tbackground-color: #0d3349;\n\n\tfont-size: 1.5em;\n\tline-height: 1em;\n\tfont-weight: normal;\n\n\tborder-radius: 15px 15px 0 0;\n\t-moz-border-radius: 15px 15px 0 0;\n\t-webkit-border-top-right-radius: 15px;\n\t-webkit-border-top-left-radius: 15px;\n}\n\n#qunit-header a {\n\ttext-decoration: none;\n\tcolor: #c2ccd1;\n}\n\n#qunit-header a:hover,\n#qunit-header a:focus {\n\tcolor: #fff;\n}\n\n#qunit-banner {\n\theight: 5px;\n}\n\n#qunit-testrunner-toolbar {\n\tpadding: 0.5em 0 0.5em 2em;\n\tcolor: #5E740B;\n\tbackground-color: #eee;\n}\n\n#qunit-userAgent {\n\tpadding: 0.5em 0 0.5em 2.5em;\n\tbackground-color: #2b81af;\n\tcolor: #fff;\n\ttext-shadow: rgba(0, 0, 0, 0.5) 2px 2px 1px;\n}\n\n\n/** Tests: Pass/Fail */\n\n#qunit-tests {\n\tlist-style-position: inside;\n}\n\n#qunit-tests li {\n\tpadding: 0.4em 0.5em 0.4em 2.5em;\n\tborder-bottom: 1px solid #fff;\n\tlist-style-position: inside;\n}\n\n#qunit-tests.hidepass li.pass, #qunit-tests.hidepass li.running  {\n\tdisplay: none;\n}\n\n#qunit-tests li strong {\n\tcursor: pointer;\n}\n\n#qunit-tests li a {\n\tpadding: 0.5em;\n\tcolor: #c2ccd1;\n\ttext-decoration: none;\n}\n#qunit-tests li a:hover,\n#qunit-tests li a:focus {\n\tcolor: #000;\n}\n\n#qunit-tests ol {\n\tmargin-top: 0.5em;\n\tpadding: 0.5em;\n\n\tbackground-color: #fff;\n\n\tborder-radius: 15px;\n\t-moz-border-radius: 15px;\n\t-webkit-border-radius: 15px;\n\n\tbox-shadow: inset 0px 2px 13px #999;\n\t-moz-box-shadow: inset 0px 2px 13px #999;\n\t-webkit-box-shadow: inset 0px 2px 13px #999;\n}\n\n#qunit-tests table {\n\tborder-collapse: collapse;\n\tmargin-top: .2em;\n}\n\n#qunit-tests th {\n\ttext-align: right;\n\tvertical-align: top;\n\tpadding: 0 .5em 0 0;\n}\n\n#qunit-tests td {\n\tvertical-align: top;\n}\n\n#qunit-tests pre {\n\tmargin: 0;\n\twhite-space: pre-wrap;\n\tword-wrap: break-word;\n}\n\n#qunit-tests del {\n\tbackground-color: #e0f2be;\n\tcolor: #374e0c;\n\ttext-decoration: none;\n}\n\n#qunit-tests ins {\n\tbackground-color: #ffcaca;\n\tcolor: #500;\n\ttext-decoration: none;\n}\n\n/*** Test Counts */\n\n#qunit-tests b.counts                       { color: black; }\n#qunit-tests b.passed                       { color: #5E740B; }\n#qunit-tests b.failed                       { color: #710909; }\n\n#qunit-tests li li {\n\tmargin: 0.5em;\n\tpadding: 0.4em 0.5em 0.4em 0.5em;\n\tbackground-color: #fff;\n\tborder-bottom: none;\n\tlist-style-position: inside;\n}\n\n/*** Passing Styles */\n\n#qunit-tests li li.pass {\n\tcolor: #5E740B;\n\tbackground-color: #fff;\n\tborder-left: 26px solid #C6E746;\n}\n\n#qunit-tests .pass                          { color: #528CE0; background-color: #D2E0E6; }\n#qunit-tests .pass .test-name               { color: #366097; }\n\n#qunit-tests .pass .test-actual,\n#qunit-tests .pass .test-expected           { color: #999999; }\n\n#qunit-banner.qunit-pass                    { background-color: #C6E746; }\n\n/*** Failing Styles */\n\n#qunit-tests li li.fail {\n\tcolor: #710909;\n\tbackground-color: #fff;\n\tborder-left: 26px solid #EE5757;\n\twhite-space: pre;\n}\n\n#qunit-tests > li:last-child {\n\tborder-radius: 0 0 15px 15px;\n\t-moz-border-radius: 0 0 15px 15px;\n\t-webkit-border-bottom-right-radius: 15px;\n\t-webkit-border-bottom-left-radius: 15px;\n}\n\n#qunit-tests .fail                          { color: #000000; background-color: #EE5757; }\n#qunit-tests .fail .test-name,\n#qunit-tests .fail .module-name             { color: #000000; }\n\n#qunit-tests .fail .test-actual             { color: #EE5757; }\n#qunit-tests .fail .test-expected           { color: green;   }\n\n#qunit-banner.qunit-fail                    { background-color: #EE5757; }\n\n\n/** Result */\n\n#qunit-testresult {\n\tpadding: 0.5em 0.5em 0.5em 2.5em;\n\n\tcolor: #2b81af;\n\tbackground-color: #D2E0E6;\n\n\tborder-bottom: 1px solid white;\n}\n\n/** Fixture */\n\n#qunit-fixture {\n\tposition: absolute;\n\ttop: -10000px;\n\tleft: -10000px;\n}\n\n/** Runoff */\n\n#qunit-fixture {\n  display:none;\n}\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/sass-bootstrap/js/tests/vendor/qunit.js",
    "content": "/**\n * QUnit - A JavaScript Unit Testing Framework\n *\n * http://docs.jquery.com/QUnit\n *\n * Copyright (c) 2012 John Resig, Jörn Zaefferer\n * Dual licensed under the MIT (MIT-LICENSE.txt)\n * or GPL (GPL-LICENSE.txt) licenses.\n */\n\n(function(window) {\n\nvar defined = {\n\tsetTimeout: typeof window.setTimeout !== \"undefined\",\n\tsessionStorage: (function() {\n\t\ttry {\n\t\t\treturn !!sessionStorage.getItem;\n\t\t} catch(e) {\n\t\t\treturn false;\n\t\t}\n\t})()\n};\n\nvar testId = 0;\n\nvar Test = function(name, testName, expected, testEnvironmentArg, async, callback) {\n\tthis.name = name;\n\tthis.testName = testName;\n\tthis.expected = expected;\n\tthis.testEnvironmentArg = testEnvironmentArg;\n\tthis.async = async;\n\tthis.callback = callback;\n\tthis.assertions = [];\n};\nTest.prototype = {\n\tinit: function() {\n\t\tvar tests = id(\"qunit-tests\");\n\t\tif (tests) {\n\t\t\tvar b = document.createElement(\"strong\");\n\t\t\t\tb.innerHTML = \"Running \" + this.name;\n\t\t\tvar li = document.createElement(\"li\");\n\t\t\t\tli.appendChild( b );\n\t\t\t\tli.className = \"running\";\n\t\t\t\tli.id = this.id = \"test-output\" + testId++;\n\t\t\ttests.appendChild( li );\n\t\t}\n\t},\n\tsetup: function() {\n\t\tif (this.module != config.previousModule) {\n\t\t\tif ( config.previousModule ) {\n\t\t\t\tQUnit.moduleDone( {\n\t\t\t\t\tname: config.previousModule,\n\t\t\t\t\tfailed: config.moduleStats.bad,\n\t\t\t\t\tpassed: config.moduleStats.all - config.moduleStats.bad,\n\t\t\t\t\ttotal: config.moduleStats.all\n\t\t\t\t} );\n\t\t\t}\n\t\t\tconfig.previousModule = this.module;\n\t\t\tconfig.moduleStats = { all: 0, bad: 0 };\n\t\t\tQUnit.moduleStart( {\n\t\t\t\tname: this.module\n\t\t\t} );\n\t\t}\n\n\t\tconfig.current = this;\n\t\tthis.testEnvironment = extend({\n\t\t\tsetup: function() {},\n\t\t\tteardown: function() {}\n\t\t}, this.moduleTestEnvironment);\n\t\tif (this.testEnvironmentArg) {\n\t\t\textend(this.testEnvironment, this.testEnvironmentArg);\n\t\t}\n\n\t\tQUnit.testStart( {\n\t\t\tname: this.testName\n\t\t} );\n\n\t\t// allow utility functions to access the current test environment\n\t\t// TODO why??\n\t\tQUnit.current_testEnvironment = this.testEnvironment;\n\n\t\ttry {\n\t\t\tif ( !config.pollution ) {\n\t\t\t\tsaveGlobal();\n\t\t\t}\n\n\t\t\tthis.testEnvironment.setup.call(this.testEnvironment);\n\t\t} catch(e) {\n\t\t\tQUnit.ok( false, \"Setup failed on \" + this.testName + \": \" + e.message );\n\t\t}\n\t},\n\trun: function() {\n\t\tif ( this.async ) {\n\t\t\tQUnit.stop();\n\t\t}\n\n\t\tif ( config.notrycatch ) {\n\t\t\tthis.callback.call(this.testEnvironment);\n\t\t\treturn;\n\t\t}\n\t\ttry {\n\t\t\tthis.callback.call(this.testEnvironment);\n\t\t} catch(e) {\n\t\t\tfail(\"Test \" + this.testName + \" died, exception and test follows\", e, this.callback);\n\t\t\tQUnit.ok( false, \"Died on test #\" + (this.assertions.length + 1) + \": \" + e.message + \" - \" + QUnit.jsDump.parse(e) );\n\t\t\t// else next test will carry the responsibility\n\t\t\tsaveGlobal();\n\n\t\t\t// Restart the tests if they're blocking\n\t\t\tif ( config.blocking ) {\n\t\t\t\tstart();\n\t\t\t}\n\t\t}\n\t},\n\tteardown: function() {\n\t\ttry {\n\t\t\tthis.testEnvironment.teardown.call(this.testEnvironment);\n\t\t\tcheckPollution();\n\t\t} catch(e) {\n\t\t\tQUnit.ok( false, \"Teardown failed on \" + this.testName + \": \" + e.message );\n\t\t}\n\t},\n\tfinish: function() {\n\t\tif ( this.expected && this.expected != this.assertions.length ) {\n\t\t\tQUnit.ok( false, \"Expected \" + this.expected + \" assertions, but \" + this.assertions.length + \" were run\" );\n\t\t}\n\n\t\tvar good = 0, bad = 0,\n\t\t\ttests = id(\"qunit-tests\");\n\n\t\tconfig.stats.all += this.assertions.length;\n\t\tconfig.moduleStats.all += this.assertions.length;\n\n\t\tif ( tests ) {\n\t\t\tvar ol = document.createElement(\"ol\");\n\n\t\t\tfor ( var i = 0; i < this.assertions.length; i++ ) {\n\t\t\t\tvar assertion = this.assertions[i];\n\n\t\t\t\tvar li = document.createElement(\"li\");\n\t\t\t\tli.className = assertion.result ? \"pass\" : \"fail\";\n\t\t\t\tli.innerHTML = assertion.message || (assertion.result ? \"okay\" : \"failed\");\n\t\t\t\tol.appendChild( li );\n\n\t\t\t\tif ( assertion.result ) {\n\t\t\t\t\tgood++;\n\t\t\t\t} else {\n\t\t\t\t\tbad++;\n\t\t\t\t\tconfig.stats.bad++;\n\t\t\t\t\tconfig.moduleStats.bad++;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// store result when possible\n\t\t\tif ( QUnit.config.reorder && defined.sessionStorage ) {\n\t\t\t\tif (bad) {\n\t\t\t\t\tsessionStorage.setItem(\"qunit-\" + this.module + \"-\" + this.testName, bad);\n\t\t\t\t} else {\n\t\t\t\t\tsessionStorage.removeItem(\"qunit-\" + this.module + \"-\" + this.testName);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (bad == 0) {\n\t\t\t\tol.style.display = \"none\";\n\t\t\t}\n\n\t\t\tvar b = document.createElement(\"strong\");\n\t\t\tb.innerHTML = this.name + \" <b class='counts'>(<b class='failed'>\" + bad + \"</b>, <b class='passed'>\" + good + \"</b>, \" + this.assertions.length + \")</b>\";\n\n\t\t\tvar a = document.createElement(\"a\");\n\t\t\ta.innerHTML = \"Rerun\";\n\t\t\ta.href = QUnit.url({ filter: getText([b]).replace(/\\([^)]+\\)$/, \"\").replace(/(^\\s*|\\s*$)/g, \"\") });\n\n\t\t\taddEvent(b, \"click\", function() {\n\t\t\t\tvar next = b.nextSibling.nextSibling,\n\t\t\t\t\tdisplay = next.style.display;\n\t\t\t\tnext.style.display = display === \"none\" ? \"block\" : \"none\";\n\t\t\t});\n\n\t\t\taddEvent(b, \"dblclick\", function(e) {\n\t\t\t\tvar target = e && e.target ? e.target : window.event.srcElement;\n\t\t\t\tif ( target.nodeName.toLowerCase() == \"span\" || target.nodeName.toLowerCase() == \"b\" ) {\n\t\t\t\t\ttarget = target.parentNode;\n\t\t\t\t}\n\t\t\t\tif ( window.location && target.nodeName.toLowerCase() === \"strong\" ) {\n\t\t\t\t\twindow.location = QUnit.url({ filter: getText([target]).replace(/\\([^)]+\\)$/, \"\").replace(/(^\\s*|\\s*$)/g, \"\") });\n\t\t\t\t}\n\t\t\t});\n\n\t\t\tvar li = id(this.id);\n\t\t\tli.className = bad ? \"fail\" : \"pass\";\n\t\t\tli.removeChild( li.firstChild );\n\t\t\tli.appendChild( b );\n\t\t\tli.appendChild( a );\n\t\t\tli.appendChild( ol );\n\n\t\t} else {\n\t\t\tfor ( var i = 0; i < this.assertions.length; i++ ) {\n\t\t\t\tif ( !this.assertions[i].result ) {\n\t\t\t\t\tbad++;\n\t\t\t\t\tconfig.stats.bad++;\n\t\t\t\t\tconfig.moduleStats.bad++;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\ttry {\n\t\t\tQUnit.reset();\n\t\t} catch(e) {\n\t\t\tfail(\"reset() failed, following Test \" + this.testName + \", exception and reset fn follows\", e, QUnit.reset);\n\t\t}\n\n\t\tQUnit.testDone( {\n\t\t\tname: this.testName,\n\t\t\tfailed: bad,\n\t\t\tpassed: this.assertions.length - bad,\n\t\t\ttotal: this.assertions.length\n\t\t} );\n\t},\n\n\tqueue: function() {\n\t\tvar test = this;\n\t\tsynchronize(function() {\n\t\t\ttest.init();\n\t\t});\n\t\tfunction run() {\n\t\t\t// each of these can by async\n\t\t\tsynchronize(function() {\n\t\t\t\ttest.setup();\n\t\t\t});\n\t\t\tsynchronize(function() {\n\t\t\t\ttest.run();\n\t\t\t});\n\t\t\tsynchronize(function() {\n\t\t\t\ttest.teardown();\n\t\t\t});\n\t\t\tsynchronize(function() {\n\t\t\t\ttest.finish();\n\t\t\t});\n\t\t}\n\t\t// defer when previous test run passed, if storage is available\n\t\tvar bad = QUnit.config.reorder && defined.sessionStorage && +sessionStorage.getItem(\"qunit-\" + this.module + \"-\" + this.testName);\n\t\tif (bad) {\n\t\t\trun();\n\t\t} else {\n\t\t\tsynchronize(run);\n\t\t};\n\t}\n\n};\n\nvar QUnit = {\n\n\t// call on start of module test to prepend name to all tests\n\tmodule: function(name, testEnvironment) {\n\t\tconfig.currentModule = name;\n\t\tconfig.currentModuleTestEnviroment = testEnvironment;\n\t},\n\n\tasyncTest: function(testName, expected, callback) {\n\t\tif ( arguments.length === 2 ) {\n\t\t\tcallback = expected;\n\t\t\texpected = 0;\n\t\t}\n\n\t\tQUnit.test(testName, expected, callback, true);\n\t},\n\n\ttest: function(testName, expected, callback, async) {\n\t\tvar name = '<span class=\"test-name\">' + testName + '</span>', testEnvironmentArg;\n\n\t\tif ( arguments.length === 2 ) {\n\t\t\tcallback = expected;\n\t\t\texpected = null;\n\t\t}\n\t\t// is 2nd argument a testEnvironment?\n\t\tif ( expected && typeof expected === 'object') {\n\t\t\ttestEnvironmentArg = expected;\n\t\t\texpected = null;\n\t\t}\n\n\t\tif ( config.currentModule ) {\n\t\t\tname = '<span class=\"module-name\">' + config.currentModule + \"</span>: \" + name;\n\t\t}\n\n\t\tif ( !validTest(config.currentModule + \": \" + testName) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar test = new Test(name, testName, expected, testEnvironmentArg, async, callback);\n\t\ttest.module = config.currentModule;\n\t\ttest.moduleTestEnvironment = config.currentModuleTestEnviroment;\n\t\ttest.queue();\n\t},\n\n\t/**\n\t * Specify the number of expected assertions to gurantee that failed test (no assertions are run at all) don't slip through.\n\t */\n\texpect: function(asserts) {\n\t\tconfig.current.expected = asserts;\n\t},\n\n\t/**\n\t * Asserts true.\n\t * @example ok( \"asdfasdf\".length > 5, \"There must be at least 5 chars\" );\n\t */\n\tok: function(a, msg) {\n\t\ta = !!a;\n\t\tvar details = {\n\t\t\tresult: a,\n\t\t\tmessage: msg\n\t\t};\n\t\tmsg = escapeHtml(msg);\n\t\tQUnit.log(details);\n\t\tconfig.current.assertions.push({\n\t\t\tresult: a,\n\t\t\tmessage: msg\n\t\t});\n\t},\n\n\t/**\n\t * Checks that the first two arguments are equal, with an optional message.\n\t * Prints out both actual and expected values.\n\t *\n\t * Prefered to ok( actual == expected, message )\n\t *\n\t * @example equal( format(\"Received {0} bytes.\", 2), \"Received 2 bytes.\" );\n\t *\n\t * @param Object actual\n\t * @param Object expected\n\t * @param String message (optional)\n\t */\n\tequal: function(actual, expected, message) {\n\t\tQUnit.push(expected == actual, actual, expected, message);\n\t},\n\n\tnotEqual: function(actual, expected, message) {\n\t\tQUnit.push(expected != actual, actual, expected, message);\n\t},\n\n\tdeepEqual: function(actual, expected, message) {\n\t\tQUnit.push(QUnit.equiv(actual, expected), actual, expected, message);\n\t},\n\n\tnotDeepEqual: function(actual, expected, message) {\n\t\tQUnit.push(!QUnit.equiv(actual, expected), actual, expected, message);\n\t},\n\n\tstrictEqual: function(actual, expected, message) {\n\t\tQUnit.push(expected === actual, actual, expected, message);\n\t},\n\n\tnotStrictEqual: function(actual, expected, message) {\n\t\tQUnit.push(expected !== actual, actual, expected, message);\n\t},\n\n\traises: function(block, expected, message) {\n\t\tvar actual, ok = false;\n\n\t\tif (typeof expected === 'string') {\n\t\t\tmessage = expected;\n\t\t\texpected = null;\n\t\t}\n\n\t\ttry {\n\t\t\tblock();\n\t\t} catch (e) {\n\t\t\tactual = e;\n\t\t}\n\n\t\tif (actual) {\n\t\t\t// we don't want to validate thrown error\n\t\t\tif (!expected) {\n\t\t\t\tok = true;\n\t\t\t// expected is a regexp\n\t\t\t} else if (QUnit.objectType(expected) === \"regexp\") {\n\t\t\t\tok = expected.test(actual);\n\t\t\t// expected is a constructor\n\t\t\t} else if (actual instanceof expected) {\n\t\t\t\tok = true;\n\t\t\t// expected is a validation function which returns true is validation passed\n\t\t\t} else if (expected.call({}, actual) === true) {\n\t\t\t\tok = true;\n\t\t\t}\n\t\t}\n\n\t\tQUnit.ok(ok, message);\n\t},\n\n\tstart: function() {\n\t\tconfig.semaphore--;\n\t\tif (config.semaphore > 0) {\n\t\t\t// don't start until equal number of stop-calls\n\t\t\treturn;\n\t\t}\n\t\tif (config.semaphore < 0) {\n\t\t\t// ignore if start is called more often then stop\n\t\t\tconfig.semaphore = 0;\n\t\t}\n\t\t// A slight delay, to avoid any current callbacks\n\t\tif ( defined.setTimeout ) {\n\t\t\twindow.setTimeout(function() {\n\t\t\t\tif (config.semaphore > 0) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tif ( config.timeout ) {\n\t\t\t\t\tclearTimeout(config.timeout);\n\t\t\t\t}\n\n\t\t\t\tconfig.blocking = false;\n\t\t\t\tprocess();\n\t\t\t}, 13);\n\t\t} else {\n\t\t\tconfig.blocking = false;\n\t\t\tprocess();\n\t\t}\n\t},\n\n\tstop: function(timeout) {\n\t\tconfig.semaphore++;\n\t\tconfig.blocking = true;\n\n\t\tif ( timeout && defined.setTimeout ) {\n\t\t\tclearTimeout(config.timeout);\n\t\t\tconfig.timeout = window.setTimeout(function() {\n\t\t\t\tQUnit.ok( false, \"Test timed out\" );\n\t\t\t\tQUnit.start();\n\t\t\t}, timeout);\n\t\t}\n\t}\n};\n\n// Backwards compatibility, deprecated\nQUnit.equals = QUnit.equal;\nQUnit.same = QUnit.deepEqual;\n\n// Maintain internal state\nvar config = {\n\t// The queue of tests to run\n\tqueue: [],\n\n\t// block until document ready\n\tblocking: true,\n\n\t// when enabled, show only failing tests\n\t// gets persisted through sessionStorage and can be changed in UI via checkbox\n\thidepassed: false,\n\n\t// by default, run previously failed tests first\n\t// very useful in combination with \"Hide passed tests\" checked\n\treorder: true,\n\n\t// by default, modify document.title when suite is done\n\taltertitle: true,\n\n\turlConfig: ['noglobals', 'notrycatch']\n};\n\n// Load paramaters\n(function() {\n\tvar location = window.location || { search: \"\", protocol: \"file:\" },\n\t\tparams = location.search.slice( 1 ).split( \"&\" ),\n\t\tlength = params.length,\n\t\turlParams = {},\n\t\tcurrent;\n\n\tif ( params[ 0 ] ) {\n\t\tfor ( var i = 0; i < length; i++ ) {\n\t\t\tcurrent = params[ i ].split( \"=\" );\n\t\t\tcurrent[ 0 ] = decodeURIComponent( current[ 0 ] );\n\t\t\t// allow just a key to turn on a flag, e.g., test.html?noglobals\n\t\t\tcurrent[ 1 ] = current[ 1 ] ? decodeURIComponent( current[ 1 ] ) : true;\n\t\t\turlParams[ current[ 0 ] ] = current[ 1 ];\n\t\t}\n\t}\n\n\tQUnit.urlParams = urlParams;\n\tconfig.filter = urlParams.filter;\n\n\t// Figure out if we're running the tests from a server or not\n\tQUnit.isLocal = !!(location.protocol === 'file:');\n})();\n\n// Expose the API as global variables, unless an 'exports'\n// object exists, in that case we assume we're in CommonJS\nif ( typeof exports === \"undefined\" || typeof require === \"undefined\" ) {\n\textend(window, QUnit);\n\twindow.QUnit = QUnit;\n} else {\n\textend(exports, QUnit);\n\texports.QUnit = QUnit;\n}\n\n// define these after exposing globals to keep them in these QUnit namespace only\nextend(QUnit, {\n\tconfig: config,\n\n\t// Initialize the configuration options\n\tinit: function() {\n\t\textend(config, {\n\t\t\tstats: { all: 0, bad: 0 },\n\t\t\tmoduleStats: { all: 0, bad: 0 },\n\t\t\tstarted: +new Date,\n\t\t\tupdateRate: 1000,\n\t\t\tblocking: false,\n\t\t\tautostart: true,\n\t\t\tautorun: false,\n\t\t\tfilter: \"\",\n\t\t\tqueue: [],\n\t\t\tsemaphore: 0\n\t\t});\n\n\t\tvar tests = id( \"qunit-tests\" ),\n\t\t\tbanner = id( \"qunit-banner\" ),\n\t\t\tresult = id( \"qunit-testresult\" );\n\n\t\tif ( tests ) {\n\t\t\ttests.innerHTML = \"\";\n\t\t}\n\n\t\tif ( banner ) {\n\t\t\tbanner.className = \"\";\n\t\t}\n\n\t\tif ( result ) {\n\t\t\tresult.parentNode.removeChild( result );\n\t\t}\n\n\t\tif ( tests ) {\n\t\t\tresult = document.createElement( \"p\" );\n\t\t\tresult.id = \"qunit-testresult\";\n\t\t\tresult.className = \"result\";\n\t\t\ttests.parentNode.insertBefore( result, tests );\n\t\t\tresult.innerHTML = 'Running...<br/>&nbsp;';\n\t\t}\n\t},\n\n\t/**\n\t * Resets the test setup. Useful for tests that modify the DOM.\n\t *\n\t * If jQuery is available, uses jQuery's html(), otherwise just innerHTML.\n\t */\n\treset: function() {\n\t\tif ( window.jQuery ) {\n\t\t\tjQuery( \"#qunit-fixture\" ).html( config.fixture );\n\t\t} else {\n\t\t\tvar main = id( 'qunit-fixture' );\n\t\t\tif ( main ) {\n\t\t\t\tmain.innerHTML = config.fixture;\n\t\t\t}\n\t\t}\n\t},\n\n\t/**\n\t * Trigger an event on an element.\n\t *\n\t * @example triggerEvent( document.body, \"click\" );\n\t *\n\t * @param DOMElement elem\n\t * @param String type\n\t */\n\ttriggerEvent: function( elem, type, event ) {\n\t\tif ( document.createEvent ) {\n\t\t\tevent = document.createEvent(\"MouseEvents\");\n\t\t\tevent.initMouseEvent(type, true, true, elem.ownerDocument.defaultView,\n\t\t\t\t0, 0, 0, 0, 0, false, false, false, false, 0, null);\n\t\t\telem.dispatchEvent( event );\n\n\t\t} else if ( elem.fireEvent ) {\n\t\t\telem.fireEvent(\"on\"+type);\n\t\t}\n\t},\n\n\t// Safe object type checking\n\tis: function( type, obj ) {\n\t\treturn QUnit.objectType( obj ) == type;\n\t},\n\n\tobjectType: function( obj ) {\n\t\tif (typeof obj === \"undefined\") {\n\t\t\t\treturn \"undefined\";\n\n\t\t// consider: typeof null === object\n\t\t}\n\t\tif (obj === null) {\n\t\t\t\treturn \"null\";\n\t\t}\n\n\t\tvar type = Object.prototype.toString.call( obj )\n\t\t\t.match(/^\\[object\\s(.*)\\]$/)[1] || '';\n\n\t\tswitch (type) {\n\t\t\t\tcase 'Number':\n\t\t\t\t\t\tif (isNaN(obj)) {\n\t\t\t\t\t\t\t\treturn \"nan\";\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\treturn \"number\";\n\t\t\t\t\t\t}\n\t\t\t\tcase 'String':\n\t\t\t\tcase 'Boolean':\n\t\t\t\tcase 'Array':\n\t\t\t\tcase 'Date':\n\t\t\t\tcase 'RegExp':\n\t\t\t\tcase 'Function':\n\t\t\t\t\t\treturn type.toLowerCase();\n\t\t}\n\t\tif (typeof obj === \"object\") {\n\t\t\t\treturn \"object\";\n\t\t}\n\t\treturn undefined;\n\t},\n\n\tpush: function(result, actual, expected, message) {\n\t\tvar details = {\n\t\t\tresult: result,\n\t\t\tmessage: message,\n\t\t\tactual: actual,\n\t\t\texpected: expected\n\t\t};\n\n\t\tmessage = escapeHtml(message) || (result ? \"okay\" : \"failed\");\n\t\tmessage = '<span class=\"test-message\">' + message + \"</span>\";\n\t\texpected = escapeHtml(QUnit.jsDump.parse(expected));\n\t\tactual = escapeHtml(QUnit.jsDump.parse(actual));\n\t\tvar output = message + '<table><tr class=\"test-expected\"><th>Expected: </th><td><pre>' + expected + '</pre></td></tr>';\n\t\tif (actual != expected) {\n\t\t\toutput += '<tr class=\"test-actual\"><th>Result: </th><td><pre>' + actual + '</pre></td></tr>';\n\t\t\toutput += '<tr class=\"test-diff\"><th>Diff: </th><td><pre>' + QUnit.diff(expected, actual) +'</pre></td></tr>';\n\t\t}\n\t\tif (!result) {\n\t\t\tvar source = sourceFromStacktrace();\n\t\t\tif (source) {\n\t\t\t\tdetails.source = source;\n\t\t\t\toutput += '<tr class=\"test-source\"><th>Source: </th><td><pre>' + escapeHtml(source) + '</pre></td></tr>';\n\t\t\t}\n\t\t}\n\t\toutput += \"</table>\";\n\n\t\tQUnit.log(details);\n\n\t\tconfig.current.assertions.push({\n\t\t\tresult: !!result,\n\t\t\tmessage: output\n\t\t});\n\t},\n\n\turl: function( params ) {\n\t\tparams = extend( extend( {}, QUnit.urlParams ), params );\n\t\tvar querystring = \"?\",\n\t\t\tkey;\n\t\tfor ( key in params ) {\n\t\t\tquerystring += encodeURIComponent( key ) + \"=\" +\n\t\t\t\tencodeURIComponent( params[ key ] ) + \"&\";\n\t\t}\n\t\treturn window.location.pathname + querystring.slice( 0, -1 );\n\t},\n\n\textend: extend,\n\tid: id,\n\taddEvent: addEvent,\n\n\t// Logging callbacks; all receive a single argument with the listed properties\n\t// run test/logs.html for any related changes\n\tbegin: function() {},\n\t// done: { failed, passed, total, runtime }\n\tdone: function() {},\n\t// log: { result, actual, expected, message }\n\tlog: function() {},\n\t// testStart: { name }\n\ttestStart: function() {},\n\t// testDone: { name, failed, passed, total }\n\ttestDone: function() {},\n\t// moduleStart: { name }\n\tmoduleStart: function() {},\n\t// moduleDone: { name, failed, passed, total }\n\tmoduleDone: function() {}\n});\n\nif ( typeof document === \"undefined\" || document.readyState === \"complete\" ) {\n\tconfig.autorun = true;\n}\n\nQUnit.load = function() {\n\tQUnit.begin({});\n\n\t// Initialize the config, saving the execution queue\n\tvar oldconfig = extend({}, config);\n\tQUnit.init();\n\textend(config, oldconfig);\n\n\tconfig.blocking = false;\n\n\tvar urlConfigHtml = '', len = config.urlConfig.length;\n\tfor ( var i = 0, val; i < len, val = config.urlConfig[i]; i++ ) {\n\t\tconfig[val] = QUnit.urlParams[val];\n\t\turlConfigHtml += '<label><input name=\"' + val + '\" type=\"checkbox\"' + ( config[val] ? ' checked=\"checked\"' : '' ) + '>' + val + '</label>';\n\t}\n\n\tvar userAgent = id(\"qunit-userAgent\");\n\tif ( userAgent ) {\n\t\tuserAgent.innerHTML = navigator.userAgent;\n\t}\n\tvar banner = id(\"qunit-header\");\n\tif ( banner ) {\n\t\tbanner.innerHTML = '<a href=\"' + QUnit.url({ filter: undefined }) + '\"> ' + banner.innerHTML + '</a> ' + urlConfigHtml;\n\t\taddEvent( banner, \"change\", function( event ) {\n\t\t\tvar params = {};\n\t\t\tparams[ event.target.name ] = event.target.checked ? true : undefined;\n\t\t\twindow.location = QUnit.url( params );\n\t\t});\n\t}\n\n\tvar toolbar = id(\"qunit-testrunner-toolbar\");\n\tif ( toolbar ) {\n\t\tvar filter = document.createElement(\"input\");\n\t\tfilter.type = \"checkbox\";\n\t\tfilter.id = \"qunit-filter-pass\";\n\t\taddEvent( filter, \"click\", function() {\n\t\t\tvar ol = document.getElementById(\"qunit-tests\");\n\t\t\tif ( filter.checked ) {\n\t\t\t\tol.className = ol.className + \" hidepass\";\n\t\t\t} else {\n\t\t\t\tvar tmp = \" \" + ol.className.replace( /[\\n\\t\\r]/g, \" \" ) + \" \";\n\t\t\t\tol.className = tmp.replace(/ hidepass /, \" \");\n\t\t\t}\n\t\t\tif ( defined.sessionStorage ) {\n\t\t\t\tif (filter.checked) {\n\t\t\t\t\tsessionStorage.setItem(\"qunit-filter-passed-tests\", \"true\");\n\t\t\t\t} else {\n\t\t\t\t\tsessionStorage.removeItem(\"qunit-filter-passed-tests\");\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t\tif ( config.hidepassed || defined.sessionStorage && sessionStorage.getItem(\"qunit-filter-passed-tests\") ) {\n\t\t\tfilter.checked = true;\n\t\t\tvar ol = document.getElementById(\"qunit-tests\");\n\t\t\tol.className = ol.className + \" hidepass\";\n\t\t}\n\t\ttoolbar.appendChild( filter );\n\n\t\tvar label = document.createElement(\"label\");\n\t\tlabel.setAttribute(\"for\", \"qunit-filter-pass\");\n\t\tlabel.innerHTML = \"Hide passed tests\";\n\t\ttoolbar.appendChild( label );\n\t}\n\n\tvar main = id('qunit-fixture');\n\tif ( main ) {\n\t\tconfig.fixture = main.innerHTML;\n\t}\n\n\tif (config.autostart) {\n\t\tQUnit.start();\n\t}\n};\n\naddEvent(window, \"load\", QUnit.load);\n\nfunction done() {\n\tconfig.autorun = true;\n\n\t// Log the last module results\n\tif ( config.currentModule ) {\n\t\tQUnit.moduleDone( {\n\t\t\tname: config.currentModule,\n\t\t\tfailed: config.moduleStats.bad,\n\t\t\tpassed: config.moduleStats.all - config.moduleStats.bad,\n\t\t\ttotal: config.moduleStats.all\n\t\t} );\n\t}\n\n\tvar banner = id(\"qunit-banner\"),\n\t\ttests = id(\"qunit-tests\"),\n\t\truntime = +new Date - config.started,\n\t\tpassed = config.stats.all - config.stats.bad,\n\t\thtml = [\n\t\t\t'Tests completed in ',\n\t\t\truntime,\n\t\t\t' milliseconds.<br/>',\n\t\t\t'<span class=\"passed\">',\n\t\t\tpassed,\n\t\t\t'</span> tests of <span class=\"total\">',\n\t\t\tconfig.stats.all,\n\t\t\t'</span> passed, <span class=\"failed\">',\n\t\t\tconfig.stats.bad,\n\t\t\t'</span> failed.'\n\t\t].join('');\n\n\tif ( banner ) {\n\t\tbanner.className = (config.stats.bad ? \"qunit-fail\" : \"qunit-pass\");\n\t}\n\n\tif ( tests ) {\n\t\tid( \"qunit-testresult\" ).innerHTML = html;\n\t}\n\n\tif ( config.altertitle && typeof document !== \"undefined\" && document.title ) {\n\t\t// show ✖ for good, ✔ for bad suite result in title\n\t\t// use escape sequences in case file gets loaded with non-utf-8-charset\n\t\tdocument.title = [\n\t\t\t(config.stats.bad ? \"\\u2716\" : \"\\u2714\"),\n\t\t\tdocument.title.replace(/^[\\u2714\\u2716] /i, \"\")\n\t\t].join(\" \");\n\t}\n\n\tQUnit.done( {\n\t\tfailed: config.stats.bad,\n\t\tpassed: passed,\n\t\ttotal: config.stats.all,\n\t\truntime: runtime\n\t} );\n}\n\nfunction validTest( name ) {\n\tvar filter = config.filter,\n\t\trun = false;\n\n\tif ( !filter ) {\n\t\treturn true;\n\t}\n\n\tvar not = filter.charAt( 0 ) === \"!\";\n\tif ( not ) {\n\t\tfilter = filter.slice( 1 );\n\t}\n\n\tif ( name.indexOf( filter ) !== -1 ) {\n\t\treturn !not;\n\t}\n\n\tif ( not ) {\n\t\trun = true;\n\t}\n\n\treturn run;\n}\n\n// so far supports only Firefox, Chrome and Opera (buggy)\n// could be extended in the future to use something like https://github.com/csnover/TraceKit\nfunction sourceFromStacktrace() {\n\ttry {\n\t\tthrow new Error();\n\t} catch ( e ) {\n\t\tif (e.stacktrace) {\n\t\t\t// Opera\n\t\t\treturn e.stacktrace.split(\"\\n\")[6];\n\t\t} else if (e.stack) {\n\t\t\t// Firefox, Chrome\n\t\t\treturn e.stack.split(\"\\n\")[4];\n\t\t} else if (e.sourceURL) {\n\t\t\t// Safari, PhantomJS\n\t\t\t// TODO sourceURL points at the 'throw new Error' line above, useless\n\t\t\t//return e.sourceURL + \":\" + e.line;\n\t\t}\n\t}\n}\n\nfunction escapeHtml(s) {\n\tif (!s) {\n\t\treturn \"\";\n\t}\n\ts = s + \"\";\n\treturn s.replace(/[\\&\"<>\\\\]/g, function(s) {\n\t\tswitch(s) {\n\t\t\tcase \"&\": return \"&amp;\";\n\t\t\tcase \"\\\\\": return \"\\\\\\\\\";\n\t\t\tcase '\"': return '\\\"';\n\t\t\tcase \"<\": return \"&lt;\";\n\t\t\tcase \">\": return \"&gt;\";\n\t\t\tdefault: return s;\n\t\t}\n\t});\n}\n\nfunction synchronize( callback ) {\n\tconfig.queue.push( callback );\n\n\tif ( config.autorun && !config.blocking ) {\n\t\tprocess();\n\t}\n}\n\nfunction process() {\n\tvar start = (new Date()).getTime();\n\n\twhile ( config.queue.length && !config.blocking ) {\n\t\tif ( config.updateRate <= 0 || (((new Date()).getTime() - start) < config.updateRate) ) {\n\t\t\tconfig.queue.shift()();\n\t\t} else {\n\t\t\twindow.setTimeout( process, 13 );\n\t\t\tbreak;\n\t\t}\n\t}\n\tif (!config.blocking && !config.queue.length) {\n\t\tdone();\n\t}\n}\n\nfunction saveGlobal() {\n\tconfig.pollution = [];\n\n\tif ( config.noglobals ) {\n\t\tfor ( var key in window ) {\n\t\t\tconfig.pollution.push( key );\n\t\t}\n\t}\n}\n\nfunction checkPollution( name ) {\n\tvar old = config.pollution;\n\tsaveGlobal();\n\n\tvar newGlobals = diff( config.pollution, old );\n\tif ( newGlobals.length > 0 ) {\n\t\tok( false, \"Introduced global variable(s): \" + newGlobals.join(\", \") );\n\t}\n\n\tvar deletedGlobals = diff( old, config.pollution );\n\tif ( deletedGlobals.length > 0 ) {\n\t\tok( false, \"Deleted global variable(s): \" + deletedGlobals.join(\", \") );\n\t}\n}\n\n// returns a new Array with the elements that are in a but not in b\nfunction diff( a, b ) {\n\tvar result = a.slice();\n\tfor ( var i = 0; i < result.length; i++ ) {\n\t\tfor ( var j = 0; j < b.length; j++ ) {\n\t\t\tif ( result[i] === b[j] ) {\n\t\t\t\tresult.splice(i, 1);\n\t\t\t\ti--;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\treturn result;\n}\n\nfunction fail(message, exception, callback) {\n\tif ( typeof console !== \"undefined\" && console.error && console.warn ) {\n\t\tconsole.error(message);\n\t\tconsole.error(exception);\n\t\tconsole.warn(callback.toString());\n\n\t} else if ( window.opera && opera.postError ) {\n\t\topera.postError(message, exception, callback.toString);\n\t}\n}\n\nfunction extend(a, b) {\n\tfor ( var prop in b ) {\n\t\tif ( b[prop] === undefined ) {\n\t\t\tdelete a[prop];\n\t\t} else {\n\t\t\ta[prop] = b[prop];\n\t\t}\n\t}\n\n\treturn a;\n}\n\nfunction addEvent(elem, type, fn) {\n\tif ( elem.addEventListener ) {\n\t\telem.addEventListener( type, fn, false );\n\t} else if ( elem.attachEvent ) {\n\t\telem.attachEvent( \"on\" + type, fn );\n\t} else {\n\t\tfn();\n\t}\n}\n\nfunction id(name) {\n\treturn !!(typeof document !== \"undefined\" && document && document.getElementById) &&\n\t\tdocument.getElementById( name );\n}\n\n// Test for equality any JavaScript type.\n// Discussions and reference: http://philrathe.com/articles/equiv\n// Test suites: http://philrathe.com/tests/equiv\n// Author: Philippe Rathé <prathe@gmail.com>\nQUnit.equiv = function () {\n\n\tvar innerEquiv; // the real equiv function\n\tvar callers = []; // stack to decide between skip/abort functions\n\tvar parents = []; // stack to avoiding loops from circular referencing\n\n\t// Call the o related callback with the given arguments.\n\tfunction bindCallbacks(o, callbacks, args) {\n\t\tvar prop = QUnit.objectType(o);\n\t\tif (prop) {\n\t\t\tif (QUnit.objectType(callbacks[prop]) === \"function\") {\n\t\t\t\treturn callbacks[prop].apply(callbacks, args);\n\t\t\t} else {\n\t\t\t\treturn callbacks[prop]; // or undefined\n\t\t\t}\n\t\t}\n\t}\n\n\tvar callbacks = function () {\n\n\t\t// for string, boolean, number and null\n\t\tfunction useStrictEquality(b, a) {\n\t\t\tif (b instanceof a.constructor || a instanceof b.constructor) {\n\t\t\t\t// to catch short annotaion VS 'new' annotation of a\n\t\t\t\t// declaration\n\t\t\t\t// e.g. var i = 1;\n\t\t\t\t// var j = new Number(1);\n\t\t\t\treturn a == b;\n\t\t\t} else {\n\t\t\t\treturn a === b;\n\t\t\t}\n\t\t}\n\n\t\treturn {\n\t\t\t\"string\" : useStrictEquality,\n\t\t\t\"boolean\" : useStrictEquality,\n\t\t\t\"number\" : useStrictEquality,\n\t\t\t\"null\" : useStrictEquality,\n\t\t\t\"undefined\" : useStrictEquality,\n\n\t\t\t\"nan\" : function(b) {\n\t\t\t\treturn isNaN(b);\n\t\t\t},\n\n\t\t\t\"date\" : function(b, a) {\n\t\t\t\treturn QUnit.objectType(b) === \"date\"\n\t\t\t\t\t\t&& a.valueOf() === b.valueOf();\n\t\t\t},\n\n\t\t\t\"regexp\" : function(b, a) {\n\t\t\t\treturn QUnit.objectType(b) === \"regexp\"\n\t\t\t\t\t\t&& a.source === b.source && // the regex itself\n\t\t\t\t\t\ta.global === b.global && // and its modifers\n\t\t\t\t\t\t\t\t\t\t\t\t\t// (gmi) ...\n\t\t\t\t\t\ta.ignoreCase === b.ignoreCase\n\t\t\t\t\t\t&& a.multiline === b.multiline;\n\t\t\t},\n\n\t\t\t// - skip when the property is a method of an instance (OOP)\n\t\t\t// - abort otherwise,\n\t\t\t// initial === would have catch identical references anyway\n\t\t\t\"function\" : function() {\n\t\t\t\tvar caller = callers[callers.length - 1];\n\t\t\t\treturn caller !== Object && typeof caller !== \"undefined\";\n\t\t\t},\n\n\t\t\t\"array\" : function(b, a) {\n\t\t\t\tvar i, j, loop;\n\t\t\t\tvar len;\n\n\t\t\t\t// b could be an object literal here\n\t\t\t\tif (!(QUnit.objectType(b) === \"array\")) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t\tlen = a.length;\n\t\t\t\tif (len !== b.length) { // safe and faster\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t\t// track reference to avoid circular references\n\t\t\t\tparents.push(a);\n\t\t\t\tfor (i = 0; i < len; i++) {\n\t\t\t\t\tloop = false;\n\t\t\t\t\tfor (j = 0; j < parents.length; j++) {\n\t\t\t\t\t\tif (parents[j] === a[i]) {\n\t\t\t\t\t\t\tloop = true;// dont rewalk array\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif (!loop && !innerEquiv(a[i], b[i])) {\n\t\t\t\t\t\tparents.pop();\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tparents.pop();\n\t\t\t\treturn true;\n\t\t\t},\n\n\t\t\t\"object\" : function(b, a) {\n\t\t\t\tvar i, j, loop;\n\t\t\t\tvar eq = true; // unless we can proove it\n\t\t\t\tvar aProperties = [], bProperties = []; // collection of\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t// strings\n\n\t\t\t\t// comparing constructors is more strict than using\n\t\t\t\t// instanceof\n\t\t\t\tif (a.constructor !== b.constructor) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t\t// stack constructor before traversing properties\n\t\t\t\tcallers.push(a.constructor);\n\t\t\t\t// track reference to avoid circular references\n\t\t\t\tparents.push(a);\n\n\t\t\t\tfor (i in a) { // be strict: don't ensures hasOwnProperty\n\t\t\t\t\t\t\t\t// and go deep\n\t\t\t\t\tloop = false;\n\t\t\t\t\tfor (j = 0; j < parents.length; j++) {\n\t\t\t\t\t\tif (parents[j] === a[i])\n\t\t\t\t\t\t\tloop = true; // don't go down the same path\n\t\t\t\t\t\t\t\t\t\t\t// twice\n\t\t\t\t\t}\n\t\t\t\t\taProperties.push(i); // collect a's properties\n\n\t\t\t\t\tif (!loop && !innerEquiv(a[i], b[i])) {\n\t\t\t\t\t\teq = false;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tcallers.pop(); // unstack, we are done\n\t\t\t\tparents.pop();\n\n\t\t\t\tfor (i in b) {\n\t\t\t\t\tbProperties.push(i); // collect b's properties\n\t\t\t\t}\n\n\t\t\t\t// Ensures identical properties name\n\t\t\t\treturn eq\n\t\t\t\t\t\t&& innerEquiv(aProperties.sort(), bProperties\n\t\t\t\t\t\t\t\t.sort());\n\t\t\t}\n\t\t};\n\t}();\n\n\tinnerEquiv = function() { // can take multiple arguments\n\t\tvar args = Array.prototype.slice.apply(arguments);\n\t\tif (args.length < 2) {\n\t\t\treturn true; // end transition\n\t\t}\n\n\t\treturn (function(a, b) {\n\t\t\tif (a === b) {\n\t\t\t\treturn true; // catch the most you can\n\t\t\t} else if (a === null || b === null || typeof a === \"undefined\"\n\t\t\t\t\t|| typeof b === \"undefined\"\n\t\t\t\t\t|| QUnit.objectType(a) !== QUnit.objectType(b)) {\n\t\t\t\treturn false; // don't lose time with error prone cases\n\t\t\t} else {\n\t\t\t\treturn bindCallbacks(a, callbacks, [ b, a ]);\n\t\t\t}\n\n\t\t\t// apply transition with (1..n) arguments\n\t\t})(args[0], args[1])\n\t\t\t\t&& arguments.callee.apply(this, args.splice(1,\n\t\t\t\t\t\targs.length - 1));\n\t};\n\n\treturn innerEquiv;\n\n}();\n\n/**\n * jsDump Copyright (c) 2008 Ariel Flesler - aflesler(at)gmail(dot)com |\n * http://flesler.blogspot.com Licensed under BSD\n * (http://www.opensource.org/licenses/bsd-license.php) Date: 5/15/2008\n *\n * @projectDescription Advanced and extensible data dumping for Javascript.\n * @version 1.0.0\n * @author Ariel Flesler\n * @link {http://flesler.blogspot.com/2008/05/jsdump-pretty-dump-of-any-javascript.html}\n */\nQUnit.jsDump = (function() {\n\tfunction quote( str ) {\n\t\treturn '\"' + str.toString().replace(/\"/g, '\\\\\"') + '\"';\n\t};\n\tfunction literal( o ) {\n\t\treturn o + '';\n\t};\n\tfunction join( pre, arr, post ) {\n\t\tvar s = jsDump.separator(),\n\t\t\tbase = jsDump.indent(),\n\t\t\tinner = jsDump.indent(1);\n\t\tif ( arr.join )\n\t\t\tarr = arr.join( ',' + s + inner );\n\t\tif ( !arr )\n\t\t\treturn pre + post;\n\t\treturn [ pre, inner + arr, base + post ].join(s);\n\t};\n\tfunction array( arr, stack ) {\n\t\tvar i = arr.length, ret = Array(i);\n\t\tthis.up();\n\t\twhile ( i-- )\n\t\t\tret[i] = this.parse( arr[i] , undefined , stack);\n\t\tthis.down();\n\t\treturn join( '[', ret, ']' );\n\t};\n\n\tvar reName = /^function (\\w+)/;\n\n\tvar jsDump = {\n\t\tparse:function( obj, type, stack ) { //type is used mostly internally, you can fix a (custom)type in advance\n\t\t\tstack = stack || [ ];\n\t\t\tvar parser = this.parsers[ type || this.typeOf(obj) ];\n\t\t\ttype = typeof parser;\n\t\t\tvar inStack = inArray(obj, stack);\n\t\t\tif (inStack != -1) {\n\t\t\t\treturn 'recursion('+(inStack - stack.length)+')';\n\t\t\t}\n\t\t\t//else\n\t\t\tif (type == 'function')  {\n\t\t\t\t\tstack.push(obj);\n\t\t\t\t\tvar res = parser.call( this, obj, stack );\n\t\t\t\t\tstack.pop();\n\t\t\t\t\treturn res;\n\t\t\t}\n\t\t\t// else\n\t\t\treturn (type == 'string') ? parser : this.parsers.error;\n\t\t},\n\t\ttypeOf:function( obj ) {\n\t\t\tvar type;\n\t\t\tif ( obj === null ) {\n\t\t\t\ttype = \"null\";\n\t\t\t} else if (typeof obj === \"undefined\") {\n\t\t\t\ttype = \"undefined\";\n\t\t\t} else if (QUnit.is(\"RegExp\", obj)) {\n\t\t\t\ttype = \"regexp\";\n\t\t\t} else if (QUnit.is(\"Date\", obj)) {\n\t\t\t\ttype = \"date\";\n\t\t\t} else if (QUnit.is(\"Function\", obj)) {\n\t\t\t\ttype = \"function\";\n\t\t\t} else if (typeof obj.setInterval !== undefined && typeof obj.document !== \"undefined\" && typeof obj.nodeType === \"undefined\") {\n\t\t\t\ttype = \"window\";\n\t\t\t} else if (obj.nodeType === 9) {\n\t\t\t\ttype = \"document\";\n\t\t\t} else if (obj.nodeType) {\n\t\t\t\ttype = \"node\";\n\t\t\t} else if (typeof obj === \"object\" && typeof obj.length === \"number\" && obj.length >= 0) {\n\t\t\t\ttype = \"array\";\n\t\t\t} else {\n\t\t\t\ttype = typeof obj;\n\t\t\t}\n\t\t\treturn type;\n\t\t},\n\t\tseparator:function() {\n\t\t\treturn this.multiline ?\tthis.HTML ? '<br />' : '\\n' : this.HTML ? '&nbsp;' : ' ';\n\t\t},\n\t\tindent:function( extra ) {// extra can be a number, shortcut for increasing-calling-decreasing\n\t\t\tif ( !this.multiline )\n\t\t\t\treturn '';\n\t\t\tvar chr = this.indentChar;\n\t\t\tif ( this.HTML )\n\t\t\t\tchr = chr.replace(/\\t/g,'   ').replace(/ /g,'&nbsp;');\n\t\t\treturn Array( this._depth_ + (extra||0) ).join(chr);\n\t\t},\n\t\tup:function( a ) {\n\t\t\tthis._depth_ += a || 1;\n\t\t},\n\t\tdown:function( a ) {\n\t\t\tthis._depth_ -= a || 1;\n\t\t},\n\t\tsetParser:function( name, parser ) {\n\t\t\tthis.parsers[name] = parser;\n\t\t},\n\t\t// The next 3 are exposed so you can use them\n\t\tquote:quote,\n\t\tliteral:literal,\n\t\tjoin:join,\n\t\t//\n\t\t_depth_: 1,\n\t\t// This is the list of parsers, to modify them, use jsDump.setParser\n\t\tparsers:{\n\t\t\twindow: '[Window]',\n\t\t\tdocument: '[Document]',\n\t\t\terror:'[ERROR]', //when no parser is found, shouldn't happen\n\t\t\tunknown: '[Unknown]',\n\t\t\t'null':'null',\n\t\t\t'undefined':'undefined',\n\t\t\t'function':function( fn ) {\n\t\t\t\tvar ret = 'function',\n\t\t\t\t\tname = 'name' in fn ? fn.name : (reName.exec(fn)||[])[1];//functions never have name in IE\n\t\t\t\tif ( name )\n\t\t\t\t\tret += ' ' + name;\n\t\t\t\tret += '(';\n\n\t\t\t\tret = [ ret, QUnit.jsDump.parse( fn, 'functionArgs' ), '){'].join('');\n\t\t\t\treturn join( ret, QUnit.jsDump.parse(fn,'functionCode'), '}' );\n\t\t\t},\n\t\t\tarray: array,\n\t\t\tnodelist: array,\n\t\t\targuments: array,\n\t\t\tobject:function( map, stack ) {\n\t\t\t\tvar ret = [ ];\n\t\t\t\tQUnit.jsDump.up();\n\t\t\t\tfor ( var key in map ) {\n\t\t\t\t    var val = map[key];\n\t\t\t\t\tret.push( QUnit.jsDump.parse(key,'key') + ': ' + QUnit.jsDump.parse(val, undefined, stack));\n                }\n\t\t\t\tQUnit.jsDump.down();\n\t\t\t\treturn join( '{', ret, '}' );\n\t\t\t},\n\t\t\tnode:function( node ) {\n\t\t\t\tvar open = QUnit.jsDump.HTML ? '&lt;' : '<',\n\t\t\t\t\tclose = QUnit.jsDump.HTML ? '&gt;' : '>';\n\n\t\t\t\tvar tag = node.nodeName.toLowerCase(),\n\t\t\t\t\tret = open + tag;\n\n\t\t\t\tfor ( var a in QUnit.jsDump.DOMAttrs ) {\n\t\t\t\t\tvar val = node[QUnit.jsDump.DOMAttrs[a]];\n\t\t\t\t\tif ( val )\n\t\t\t\t\t\tret += ' ' + a + '=' + QUnit.jsDump.parse( val, 'attribute' );\n\t\t\t\t}\n\t\t\t\treturn ret + close + open + '/' + tag + close;\n\t\t\t},\n\t\t\tfunctionArgs:function( fn ) {//function calls it internally, it's the arguments part of the function\n\t\t\t\tvar l = fn.length;\n\t\t\t\tif ( !l ) return '';\n\n\t\t\t\tvar args = Array(l);\n\t\t\t\twhile ( l-- )\n\t\t\t\t\targs[l] = String.fromCharCode(97+l);//97 is 'a'\n\t\t\t\treturn ' ' + args.join(', ') + ' ';\n\t\t\t},\n\t\t\tkey:quote, //object calls it internally, the key part of an item in a map\n\t\t\tfunctionCode:'[code]', //function calls it internally, it's the content of the function\n\t\t\tattribute:quote, //node calls it internally, it's an html attribute value\n\t\t\tstring:quote,\n\t\t\tdate:quote,\n\t\t\tregexp:literal, //regex\n\t\t\tnumber:literal,\n\t\t\t'boolean':literal\n\t\t},\n\t\tDOMAttrs:{//attributes to dump from nodes, name=>realName\n\t\t\tid:'id',\n\t\t\tname:'name',\n\t\t\t'class':'className'\n\t\t},\n\t\tHTML:false,//if true, entities are escaped ( <, >, \\t, space and \\n )\n\t\tindentChar:'  ',//indentation unit\n\t\tmultiline:true //if true, items in a collection, are separated by a \\n, else just a space.\n\t};\n\n\treturn jsDump;\n})();\n\n// from Sizzle.js\nfunction getText( 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 += getText( elem.childNodes );\n\t\t}\n\t}\n\n\treturn ret;\n};\n\n//from jquery.js\nfunction inArray( elem, array ) {\n\tif ( array.indexOf ) {\n\t\treturn array.indexOf( elem );\n\t}\n\n\tfor ( var i = 0, length = array.length; i < length; i++ ) {\n\t\tif ( array[ i ] === elem ) {\n\t\t\treturn i;\n\t\t}\n\t}\n\n\treturn -1;\n}\n\n/*\n * Javascript Diff Algorithm\n *  By John Resig (http://ejohn.org/)\n *  Modified by Chu Alan \"sprite\"\n *\n * Released under the MIT license.\n *\n * More Info:\n *  http://ejohn.org/projects/javascript-diff-algorithm/\n *\n * Usage: QUnit.diff(expected, actual)\n *\n * QUnit.diff(\"the quick brown fox jumped over\", \"the quick fox jumps over\") == \"the  quick <del>brown </del> fox <del>jumped </del><ins>jumps </ins> over\"\n */\nQUnit.diff = (function() {\n\tfunction diff(o, n) {\n\t\tvar ns = {};\n\t\tvar os = {};\n\n\t\tfor (var i = 0; i < n.length; i++) {\n\t\t\tif (ns[n[i]] == null)\n\t\t\t\tns[n[i]] = {\n\t\t\t\t\trows: [],\n\t\t\t\t\to: null\n\t\t\t\t};\n\t\t\tns[n[i]].rows.push(i);\n\t\t}\n\n\t\tfor (var i = 0; i < o.length; i++) {\n\t\t\tif (os[o[i]] == null)\n\t\t\t\tos[o[i]] = {\n\t\t\t\t\trows: [],\n\t\t\t\t\tn: null\n\t\t\t\t};\n\t\t\tos[o[i]].rows.push(i);\n\t\t}\n\n\t\tfor (var i in ns) {\n\t\t\tif (ns[i].rows.length == 1 && typeof(os[i]) != \"undefined\" && os[i].rows.length == 1) {\n\t\t\t\tn[ns[i].rows[0]] = {\n\t\t\t\t\ttext: n[ns[i].rows[0]],\n\t\t\t\t\trow: os[i].rows[0]\n\t\t\t\t};\n\t\t\t\to[os[i].rows[0]] = {\n\t\t\t\t\ttext: o[os[i].rows[0]],\n\t\t\t\t\trow: ns[i].rows[0]\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\n\t\tfor (var i = 0; i < n.length - 1; i++) {\n\t\t\tif (n[i].text != null && n[i + 1].text == null && n[i].row + 1 < o.length && o[n[i].row + 1].text == null &&\n\t\t\tn[i + 1] == o[n[i].row + 1]) {\n\t\t\t\tn[i + 1] = {\n\t\t\t\t\ttext: n[i + 1],\n\t\t\t\t\trow: n[i].row + 1\n\t\t\t\t};\n\t\t\t\to[n[i].row + 1] = {\n\t\t\t\t\ttext: o[n[i].row + 1],\n\t\t\t\t\trow: i + 1\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\n\t\tfor (var i = n.length - 1; i > 0; i--) {\n\t\t\tif (n[i].text != null && n[i - 1].text == null && n[i].row > 0 && o[n[i].row - 1].text == null &&\n\t\t\tn[i - 1] == o[n[i].row - 1]) {\n\t\t\t\tn[i - 1] = {\n\t\t\t\t\ttext: n[i - 1],\n\t\t\t\t\trow: n[i].row - 1\n\t\t\t\t};\n\t\t\t\to[n[i].row - 1] = {\n\t\t\t\t\ttext: o[n[i].row - 1],\n\t\t\t\t\trow: i - 1\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\n\t\treturn {\n\t\t\to: o,\n\t\t\tn: n\n\t\t};\n\t}\n\n\treturn function(o, n) {\n\t\to = o.replace(/\\s+$/, '');\n\t\tn = n.replace(/\\s+$/, '');\n\t\tvar out = diff(o == \"\" ? [] : o.split(/\\s+/), n == \"\" ? [] : n.split(/\\s+/));\n\n\t\tvar str = \"\";\n\n\t\tvar oSpace = o.match(/\\s+/g);\n\t\tif (oSpace == null) {\n\t\t\toSpace = [\" \"];\n\t\t}\n\t\telse {\n\t\t\toSpace.push(\" \");\n\t\t}\n\t\tvar nSpace = n.match(/\\s+/g);\n\t\tif (nSpace == null) {\n\t\t\tnSpace = [\" \"];\n\t\t}\n\t\telse {\n\t\t\tnSpace.push(\" \");\n\t\t}\n\n\t\tif (out.n.length == 0) {\n\t\t\tfor (var i = 0; i < out.o.length; i++) {\n\t\t\t\tstr += '<del>' + out.o[i] + oSpace[i] + \"</del>\";\n\t\t\t}\n\t\t}\n\t\telse {\n\t\t\tif (out.n[0].text == null) {\n\t\t\t\tfor (n = 0; n < out.o.length && out.o[n].text == null; n++) {\n\t\t\t\t\tstr += '<del>' + out.o[n] + oSpace[n] + \"</del>\";\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfor (var i = 0; i < out.n.length; i++) {\n\t\t\t\tif (out.n[i].text == null) {\n\t\t\t\t\tstr += '<ins>' + out.n[i] + nSpace[i] + \"</ins>\";\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tvar pre = \"\";\n\n\t\t\t\t\tfor (n = out.n[i].row + 1; n < out.o.length && out.o[n].text == null; n++) {\n\t\t\t\t\t\tpre += '<del>' + out.o[n] + oSpace[n] + \"</del>\";\n\t\t\t\t\t}\n\t\t\t\t\tstr += \" \" + out.n[i].text + nSpace[i] + pre;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn str;\n\t};\n})();\n\n})(this);\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/sass-bootstrap/js/tooltip.js",
    "content": "/* ========================================================================\n * Bootstrap: tooltip.js v3.0.0\n * http://twbs.github.com/bootstrap/javascript.html#tooltip\n * Inspired by the original jQuery.tipsy by Jason Frame\n * ========================================================================\n * Copyright 2012 Twitter, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n * ======================================================================== */\n\n\n+function ($) { \"use strict\";\n\n  // TOOLTIP PUBLIC CLASS DEFINITION\n  // ===============================\n\n  var Tooltip = function (element, options) {\n    this.type       =\n    this.options    =\n    this.enabled    =\n    this.timeout    =\n    this.hoverState =\n    this.$element   = null\n\n    this.init('tooltip', element, options)\n  }\n\n  Tooltip.DEFAULTS = {\n    animation: true\n  , placement: 'top'\n  , selector: false\n  , template: '<div class=\"tooltip\"><div class=\"tooltip-arrow\"></div><div class=\"tooltip-inner\"></div></div>'\n  , trigger: 'hover focus'\n  , title: ''\n  , delay: 0\n  , html: false\n  , container: false\n  }\n\n  Tooltip.prototype.init = function (type, element, options) {\n    this.enabled  = true\n    this.type     = type\n    this.$element = $(element)\n    this.options  = this.getOptions(options)\n\n    var triggers = this.options.trigger.split(' ')\n\n    for (var i = triggers.length; i--;) {\n      var trigger = triggers[i]\n\n      if (trigger == 'click') {\n        this.$element.on('click.' + this.type, this.options.selector, $.proxy(this.toggle, this))\n      } else if (trigger != 'manual') {\n        var eventIn  = trigger == 'hover' ? 'mouseenter' : 'focus'\n        var eventOut = trigger == 'hover' ? 'mouseleave' : 'blur'\n\n        this.$element.on(eventIn  + '.' + this.type, this.options.selector, $.proxy(this.enter, this))\n        this.$element.on(eventOut + '.' + this.type, this.options.selector, $.proxy(this.leave, this))\n      }\n    }\n\n    this.options.selector ?\n      (this._options = $.extend({}, this.options, { trigger: 'manual', selector: '' })) :\n      this.fixTitle()\n  }\n\n  Tooltip.prototype.getDefaults = function () {\n    return Tooltip.DEFAULTS\n  }\n\n  Tooltip.prototype.getOptions = function (options) {\n    options = $.extend({}, this.getDefaults(), this.$element.data(), options)\n\n    if (options.delay && typeof options.delay == 'number') {\n      options.delay = {\n        show: options.delay\n      , hide: options.delay\n      }\n    }\n\n    return options\n  }\n\n  Tooltip.prototype.getDelegateOptions = function () {\n    var options  = {}\n    var defaults = this.getDefaults()\n\n    this._options && $.each(this._options, function (key, value) {\n      if (defaults[key] != value) options[key] = value\n    })\n\n    return options\n  }\n\n  Tooltip.prototype.enter = function (obj) {\n    var self = obj instanceof this.constructor ?\n      obj : $(obj.currentTarget)[this.type](this.getDelegateOptions()).data('bs.' + this.type)\n\n    clearTimeout(self.timeout)\n\n    self.hoverState = 'in'\n\n    if (!self.options.delay || !self.options.delay.show) return self.show()\n\n    self.timeout = setTimeout(function () {\n      if (self.hoverState == 'in') self.show()\n    }, self.options.delay.show)\n  }\n\n  Tooltip.prototype.leave = function (obj) {\n    var self = obj instanceof this.constructor ?\n      obj : $(obj.currentTarget)[this.type](this.getDelegateOptions()).data('bs.' + this.type)\n\n    clearTimeout(self.timeout)\n\n    self.hoverState = 'out'\n\n    if (!self.options.delay || !self.options.delay.hide) return self.hide()\n\n    self.timeout = setTimeout(function () {\n      if (self.hoverState == 'out') self.hide()\n    }, self.options.delay.hide)\n  }\n\n  Tooltip.prototype.show = function () {\n    var e = $.Event('show.bs.'+ this.type)\n\n    if (this.hasContent() && this.enabled) {\n      this.$element.trigger(e)\n\n      if (e.isDefaultPrevented()) return\n\n      var $tip = this.tip()\n\n      this.setContent()\n\n      if (this.options.animation) $tip.addClass('fade')\n\n      var placement = typeof this.options.placement == 'function' ?\n        this.options.placement.call(this, $tip[0], this.$element[0]) :\n        this.options.placement\n\n      var autoToken = /\\s?auto?\\s?/i\n      var autoPlace = autoToken.test(placement)\n      if (autoPlace) placement = placement.replace(autoToken, '') || 'top'\n\n      $tip\n        .detach()\n        .css({ top: 0, left: 0, display: 'block' })\n        .addClass(placement)\n\n      this.options.container ? $tip.appendTo(this.options.container) : $tip.insertAfter(this.$element)\n\n      var pos          = this.getPosition()\n      var actualWidth  = $tip[0].offsetWidth\n      var actualHeight = $tip[0].offsetHeight\n\n      if (autoPlace) {\n        var $parent = this.$element.parent()\n\n        var orgPlacement = placement\n        var docScroll    = document.documentElement.scrollTop || document.body.scrollTop\n        var parentWidth  = this.options.container == 'body' ? window.innerWidth  : $parent.outerWidth()\n        var parentHeight = this.options.container == 'body' ? window.innerHeight : $parent.outerHeight()\n        var parentLeft   = this.options.container == 'body' ? 0 : $parent.offset().left\n\n        placement = placement == 'bottom' && pos.top   + pos.height  + actualHeight - docScroll > parentHeight  ? 'top'    :\n                    placement == 'top'    && pos.top   - docScroll   - actualHeight < 0                         ? 'bottom' :\n                    placement == 'right'  && pos.right + actualWidth > parentWidth                              ? 'left'   :\n                    placement == 'left'   && pos.left  - actualWidth < parentLeft                               ? 'right'  :\n                    placement\n\n        $tip\n          .removeClass(orgPlacement)\n          .addClass(placement)\n      }\n\n      var calculatedOffset = this.getCalculatedOffset(placement, pos, actualWidth, actualHeight)\n\n      this.applyPlacement(calculatedOffset, placement)\n      this.$element.trigger('shown.bs.' + this.type)\n    }\n  }\n\n  Tooltip.prototype.applyPlacement = function(offset, placement) {\n    var replace\n    var $tip   = this.tip()\n    var width  = $tip[0].offsetWidth\n    var height = $tip[0].offsetHeight\n\n    // manually read margins because getBoundingClientRect includes difference\n    var marginTop = parseInt($tip.css('margin-top'), 10)\n    var marginLeft = parseInt($tip.css('margin-left'), 10)\n\n    // we must check for NaN for ie 8/9\n    if (isNaN(marginTop))  marginTop  = 0\n    if (isNaN(marginLeft)) marginLeft = 0\n\n    offset.top  = offset.top  + marginTop\n    offset.left = offset.left + marginLeft\n\n    $tip\n      .offset(offset)\n      .addClass('in')\n\n    // check to see if placing tip in new offset caused the tip to resize itself\n    var actualWidth  = $tip[0].offsetWidth\n    var actualHeight = $tip[0].offsetHeight\n\n    if (placement == 'top' && actualHeight != height) {\n      replace = true\n      offset.top = offset.top + height - actualHeight\n    }\n\n    if (/bottom|top/.test(placement)) {\n      var delta = 0\n\n      if (offset.left < 0) {\n        delta       = offset.left * -2\n        offset.left = 0\n\n        $tip.offset(offset)\n\n        actualWidth  = $tip[0].offsetWidth\n        actualHeight = $tip[0].offsetHeight\n      }\n\n      this.replaceArrow(delta - width + actualWidth, actualWidth, 'left')\n    } else {\n      this.replaceArrow(actualHeight - height, actualHeight, 'top')\n    }\n\n    if (replace) $tip.offset(offset)\n  }\n\n  Tooltip.prototype.replaceArrow = function(delta, dimension, position) {\n    this.arrow().css(position, delta ? (50 * (1 - delta / dimension) + \"%\") : '')\n  }\n\n  Tooltip.prototype.setContent = function () {\n    var $tip  = this.tip()\n    var title = this.getTitle()\n\n    $tip.find('.tooltip-inner')[this.options.html ? 'html' : 'text'](title)\n    $tip.removeClass('fade in top bottom left right')\n  }\n\n  Tooltip.prototype.hide = function () {\n    var that = this\n    var $tip = this.tip()\n    var e    = $.Event('hide.bs.' + this.type)\n\n    function complete() {\n      if (that.hoverState != 'in') $tip.detach()\n    }\n\n    this.$element.trigger(e)\n\n    if (e.isDefaultPrevented()) return\n\n    $tip.removeClass('in')\n\n    $.support.transition && this.$tip.hasClass('fade') ?\n      $tip\n        .one($.support.transition.end, complete)\n        .emulateTransitionEnd(150) :\n      complete()\n\n    this.$element.trigger('hidden.bs.' + this.type)\n\n    return this\n  }\n\n  Tooltip.prototype.fixTitle = function () {\n    var $e = this.$element\n    if ($e.attr('title') || typeof($e.attr('data-original-title')) != 'string') {\n      $e.attr('data-original-title', $e.attr('title') || '').attr('title', '')\n    }\n  }\n\n  Tooltip.prototype.hasContent = function () {\n    return this.getTitle()\n  }\n\n  Tooltip.prototype.getPosition = function () {\n    var el = this.$element[0]\n    return $.extend({}, (typeof el.getBoundingClientRect == 'function') ? el.getBoundingClientRect() : {\n      width: el.offsetWidth\n    , height: el.offsetHeight\n    }, this.$element.offset())\n  }\n\n  Tooltip.prototype.getCalculatedOffset = function (placement, pos, actualWidth, actualHeight) {\n    return placement == 'bottom' ? { top: pos.top + pos.height,   left: pos.left + pos.width / 2 - actualWidth / 2  } :\n           placement == 'top'    ? { top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2  } :\n           placement == 'left'   ? { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth } :\n        /* placement == 'right' */ { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width   }\n  }\n\n  Tooltip.prototype.getTitle = function () {\n    var title\n    var $e = this.$element\n    var o  = this.options\n\n    title = $e.attr('data-original-title')\n      || (typeof o.title == 'function' ? o.title.call($e[0]) :  o.title)\n\n    return title\n  }\n\n  Tooltip.prototype.tip = function () {\n    return this.$tip = this.$tip || $(this.options.template)\n  }\n\n  Tooltip.prototype.arrow = function () {\n    return this.$arrow = this.$arrow || this.tip().find('.tooltip-arrow')\n  }\n\n  Tooltip.prototype.validate = function () {\n    if (!this.$element[0].parentNode) {\n      this.hide()\n      this.$element = null\n      this.options  = null\n    }\n  }\n\n  Tooltip.prototype.enable = function () {\n    this.enabled = true\n  }\n\n  Tooltip.prototype.disable = function () {\n    this.enabled = false\n  }\n\n  Tooltip.prototype.toggleEnabled = function () {\n    this.enabled = !this.enabled\n  }\n\n  Tooltip.prototype.toggle = function (e) {\n    var self = e ? $(e.currentTarget)[this.type](this.getDelegateOptions()).data('bs.' + this.type) : this\n    self.tip().hasClass('in') ? self.leave(self) : self.enter(self)\n  }\n\n  Tooltip.prototype.destroy = function () {\n    this.hide().$element.off('.' + this.type).removeData('bs.' + this.type)\n  }\n\n\n  // TOOLTIP PLUGIN DEFINITION\n  // =========================\n\n  var old = $.fn.tooltip\n\n  $.fn.tooltip = function (option) {\n    return this.each(function () {\n      var $this   = $(this)\n      var data    = $this.data('bs.tooltip')\n      var options = typeof option == 'object' && option\n\n      if (!data) $this.data('bs.tooltip', (data = new Tooltip(this, options)))\n      if (typeof option == 'string') data[option]()\n    })\n  }\n\n  $.fn.tooltip.Constructor = Tooltip\n\n\n  // TOOLTIP NO CONFLICT\n  // ===================\n\n  $.fn.tooltip.noConflict = function () {\n    $.fn.tooltip = old\n    return this\n  }\n\n}(window.jQuery);\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/sass-bootstrap/js/transition.js",
    "content": "/* ========================================================================\n * Bootstrap: transition.js v3.0.0\n * http://twbs.github.com/bootstrap/javascript.html#transitions\n * ========================================================================\n * Copyright 2013 Twitter, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n * ======================================================================== */\n\n\n+function ($) { \"use strict\";\n\n  // CSS TRANSITION SUPPORT (Shoutout: http://www.modernizr.com/)\n  // ============================================================\n\n  function transitionEnd() {\n    var el = document.createElement('bootstrap')\n\n    var transEndEventNames = {\n      'WebkitTransition' : 'webkitTransitionEnd'\n    , 'MozTransition'    : 'transitionend'\n    , 'OTransition'      : 'oTransitionEnd otransitionend'\n    , 'transition'       : 'transitionend'\n    }\n\n    for (var name in transEndEventNames) {\n      if (el.style[name] !== undefined) {\n        return { end: transEndEventNames[name] }\n      }\n    }\n  }\n\n  // http://blog.alexmaccaw.com/css-transitions\n  $.fn.emulateTransitionEnd = function (duration) {\n    var called = false, $el = this\n    $(this).one($.support.transition.end, function () { called = true })\n    var callback = function () { if (!called) $($el).trigger($.support.transition.end) }\n    setTimeout(callback, duration)\n    return this\n  }\n\n  $(function () {\n    $.support.transition = transitionEnd()\n  })\n\n}(window.jQuery);\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/sass-bootstrap/lib/_alerts.scss",
    "content": "//\n// Alerts\n// --------------------------------------------------\n\n\n// Base styles\n// -------------------------\n\n.alert {\n  padding: $alert-padding;\n  margin-bottom: $line-height-computed;\n  border: 1px solid transparent;\n  border-radius: $alert-border-radius;\n\n  // Headings for larger alerts\n  h4 {\n    margin-top: 0;\n    // Specified for the h4 to prevent conflicts of changing $headingsColor\n    color: inherit;\n  }\n  // Provide class for links that match alerts\n  .alert-link {\n    font-weight: $alert-link-font-weight;\n  }\n\n  // Improve alignment and spacing of inner content\n  > p,\n  > ul {\n    margin-bottom: 0;\n  }\n  > p + p {\n    margin-top: 5px;\n  }\n}\n\n// Dismissable alerts\n//\n// Expand the right padding and account for the close button's positioning.\n\n.alert-dismissable {\n padding-right: ($alert-padding + 20);\n\n  // Adjust close link position\n  .close {\n    position: relative;\n    top: -2px;\n    right: -21px;\n    color: inherit;\n  }\n}\n\n// Alternate styles\n//\n// Generate contextual modifier classes for colorizing the alert.\n\n.alert-success {\n  @include alert-variant($alert-success-bg, $alert-success-border, $alert-success-text);\n}\n.alert-info {\n  @include alert-variant($alert-info-bg, $alert-info-border, $alert-info-text);\n}\n.alert-warning {\n  @include alert-variant($alert-warning-bg, $alert-warning-border, $alert-warning-text);\n}\n.alert-danger {\n  @include alert-variant($alert-danger-bg, $alert-danger-border, $alert-danger-text);\n}\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/sass-bootstrap/lib/_badges.scss",
    "content": "//\n// Badges\n// --------------------------------------------------\n\n\n// Base classes\n.badge {\n  display: inline-block;\n  min-width: 10px;\n  padding: 3px 7px;\n  font-size: $font-size-small;\n  font-weight: $badge-font-weight;\n  color: $badge-color;\n  line-height: $badge-line-height;\n  vertical-align: baseline;\n  white-space: nowrap;\n  text-align: center;\n  background-color: $badge-bg;\n  border-radius: $badge-border-radius;\n\n  // Empty badges collapse automatically (not available in IE8)\n  &:empty {\n    display: none;\n  }\n}\n\n// Hover state, but only for links\na.badge {\n  &:hover,\n  &:focus {\n    color: $badge-link-hover-color;\n    text-decoration: none;\n    cursor: pointer;\n  }\n}\n\n// Quick fix for labels/badges in buttons\n.btn .badge {\n  position: relative;\n  top: -1px;\n}\n\n// Account for counters in navs\na.list-group-item.active > .badge,\n.nav-pills > .active > a > .badge {\n  color: $badge-active-color;\n  background-color: $badge-active-bg;\n}\n.nav-pills > li > a > .badge {\n  margin-left: 3px;\n}\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/sass-bootstrap/lib/_breadcrumbs.scss",
    "content": "//\n// Breadcrumbs\n// --------------------------------------------------\n\n\n.breadcrumb {\n  padding: 8px 15px;\n  margin-bottom: $line-height-computed;\n  list-style: none;\n  background-color: $breadcrumb-bg;\n  border-radius: $border-radius-base;\n  > li {\n    display: inline-block;\n    &+li:before {\n      content: \"/\\00a0\"; // Unicode space added since inline-block means non-collapsing white-space\n      padding: 0 5px;\n      color: $breadcrumb-color;\n    }\n  }\n  > .active {\n    color: $breadcrumb-active-color;\n  }\n}\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/sass-bootstrap/lib/_button-groups.scss",
    "content": "//\n// Button groups\n// --------------------------------------------------\n\n// Button carets\n//\n// Match the button text color to the arrow/caret for indicating dropdown-ness.\n\n.caret {\n  .btn-default & {\n    border-top-color: $btn-default-color;\n  }\n  .btn-primary &,\n  .btn-success &,\n  .btn-warning &,\n  .btn-danger &,\n  .btn-info & {\n    border-top-color: #fff;\n  }\n}\n.dropup {\n  & .btn-default .caret {\n    border-bottom-color: $btn-default-color;\n  }\n  .btn-primary,\n  .btn-success,\n  .btn-warning,\n  .btn-danger,\n  .btn-info {\n   .caret {\n      border-bottom-color: #fff;\n    }\n  }\n}\n\n// Make the div behave like a button\n.btn-group,\n.btn-group-vertical {\n  position: relative;\n  display: inline-block;\n  vertical-align: middle; // match .btn alignment given font-size hack above\n  > .btn {\n    position: relative;\n    float: left;\n    // Bring the \"active\" button to the front\n    &:hover,\n    &:focus,\n    &:active,\n    &.active {\n      z-index: 2;\n    }\n    &:focus {\n      // Remove focus outline when dropdown JS adds it after closing the menu\n      outline: none;\n    }\n  }\n}\n\n// Prevent double borders when buttons are next to each other\n.btn-group {\n  .btn + .btn,\n  .btn + .btn-group,\n  .btn-group + .btn,\n  .btn-group + .btn-group {\n    margin-left: -1px;\n  }\n}\n\n// Optional: Group multiple button groups together for a toolbar\n.btn-toolbar {\n  @include clearfix();\n\n  .btn-group {\n    float: left;\n  }\n  // Space out series of button groups\n  > .btn,\n  > .btn-group {\n    + .btn,\n    + .btn-group {\n      margin-left: 5px;\n    }\n  }\n}\n\n.btn-group > .btn:not(:first-child):not(:last-child):not(.dropdown-toggle) {\n  border-radius: 0;\n}\n\n// Set corners individual because sometimes a single button can be in a .btn-group and we need :first-child and :last-child to both match\n.btn-group > .btn:first-child {\n  margin-left: 0;\n  &:not(:last-child):not(.dropdown-toggle) {\n    @include border-right-radius(0);\n  }\n}\n// Need .dropdown-toggle since :last-child doesn't apply given a .dropdown-menu immediately after it\n.btn-group > .btn:last-child:not(:first-child),\n.btn-group > .dropdown-toggle:not(:first-child) {\n  @include border-left-radius(0);\n}\n\n// Custom edits for including btn-groups within btn-groups (useful for including dropdown buttons within a btn-group)\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 {\n  > .btn:last-child,\n  > .dropdown-toggle {\n    @include border-right-radius(0);\n  }\n}\n.btn-group > .btn-group:last-child > .btn:first-child {\n  @include border-left-radius(0);\n}\n\n// On active and open, don't show outline\n.btn-group .dropdown-toggle:active,\n.btn-group.open .dropdown-toggle {\n  outline: 0;\n}\n\n\n// Sizing\n//\n// Remix the default button sizing classes into new ones for easier manipulation.\n\n.btn-group-xs > .btn { @extend .btn-xs; }\n.btn-group-sm > .btn { @extend .btn-sm; }\n.btn-group-lg > .btn { @extend .btn-lg; }\n\n\n// Split button dropdowns\n// ----------------------\n\n// Give the line between buttons some depth\n.btn-group > .btn + .dropdown-toggle {\n  padding-left: 8px;\n  padding-right: 8px;\n}\n.btn-group > .btn-lg + .dropdown-toggle {\n  padding-left: 12px;\n  padding-right: 12px;\n}\n\n// The clickable button for toggling the menu\n// Remove the gradient and set the same inset shadow as the :active state\n.btn-group.open .dropdown-toggle {\n  @include box-shadow(inset 0 3px 5px rgba(0,0,0,.125));\n}\n\n\n// Reposition the caret\n.btn .caret {\n  margin-left: 0;\n}\n// Carets in other button sizes\n.btn-lg .caret {\n  border-width: $caret-width-large $caret-width-large 0;\n  border-bottom-width: 0;\n}\n// Upside down carets for .dropup\n.dropup .btn-lg .caret {\n  border-width: 0 $caret-width-large $caret-width-large;\n}\n\n\n// Vertical button groups\n// ----------------------\n\n.btn-group-vertical {\n  > .btn,\n  > .btn-group {\n    display: block;\n    float: none;\n    width: 100%;\n    max-width: 100%;\n  }\n\n  // Clear floats so dropdown menus can be properly placed\n  > .btn-group {\n    @include clearfix();\n    > .btn {\n      float: none;\n    }\n  }\n\n  > .btn + .btn,\n  > .btn + .btn-group,\n  > .btn-group + .btn,\n  > .btn-group + .btn-group {\n    margin-top: -1px;\n    margin-left: 0;\n  }\n}\n\n.btn-group-vertical > .btn {\n  &:not(:first-child):not(:last-child) {\n    border-radius: 0;\n  }\n  &:first-child:not(:last-child) {\n    border-top-right-radius: $border-radius-base;\n    @include border-bottom-radius(0);\n  }\n  &:last-child:not(:first-child) {\n    border-bottom-left-radius: $border-radius-base;\n    @include border-top-radius(0);\n  }\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 {\n  > .btn:last-child,\n  > .dropdown-toggle {\n    @include border-bottom-radius(0);\n  }\n}\n.btn-group-vertical > .btn-group:last-child > .btn:first-child {\n  @include border-top-radius(0);\n}\n\n\n\n// Justified button groups\n// ----------------------\n\n.btn-group-justified {\n  display: table;\n  width: 100%;\n  table-layout: fixed;\n  border-collapse: separate;\n  .btn {\n    float: none;\n    display: table-cell;\n    width: 1%;\n  }\n}\n\n\n// Checkbox and radio options\n[data-toggle=\"buttons\"] > .btn > input[type=\"radio\"],\n[data-toggle=\"buttons\"] > .btn > input[type=\"checkbox\"] {\n  display: none;\n}\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/sass-bootstrap/lib/_buttons.scss",
    "content": "//\n// Buttons\n// --------------------------------------------------\n\n\n// Base styles\n// --------------------------------------------------\n\n// Core styles\n.btn {\n  display: inline-block;\n  padding: $padding-base-vertical $padding-base-horizontal;\n  margin-bottom: 0; // For input.btn\n  font-size: $font-size-base;\n  font-weight: $btn-font-weight;\n  line-height: $line-height-base;\n  text-align: center;\n  vertical-align: middle;\n  cursor: pointer;\n  border: 1px solid transparent;\n  border-radius: $border-radius-base;\n  white-space: nowrap;\n  @include user-select(none);\n\n  &:focus {\n    @include tab-focus();\n  }\n\n  &:hover,\n  &:focus {\n    color: $btn-default-color;\n    text-decoration: none;\n  }\n\n  &:active,\n  &.active {\n    outline: 0;\n    background-image: none;\n    @include box-shadow(inset 0 3px 5px rgba(0,0,0,.125));\n  }\n\n  &.disabled,\n  &[disabled],\n  fieldset[disabled] & {\n    cursor: not-allowed;\n    pointer-events: none; // Future-proof disabling of clicks\n    @include opacity(.65);\n    @include box-shadow(none);\n  }\n\n}\n\n\n// Alternate buttons\n// --------------------------------------------------\n\n.btn-default {\n  @include button-variant($btn-default-color, $btn-default-bg, $btn-default-border);\n}\n.btn-primary {\n  @include button-variant($btn-primary-color, $btn-primary-bg, $btn-primary-border);\n}\n// Warning appears as orange\n.btn-warning {\n  @include button-variant($btn-warning-color, $btn-warning-bg, $btn-warning-border);\n}\n// Danger and error appear as red\n.btn-danger {\n  @include button-variant($btn-danger-color, $btn-danger-bg, $btn-danger-border);\n}\n// Success appears as green\n.btn-success {\n  @include button-variant($btn-success-color, $btn-success-bg, $btn-success-border);\n}\n// Info appears as blue-green\n.btn-info {\n  @include button-variant($btn-info-color, $btn-info-bg, $btn-info-border);\n}\n\n\n// Link buttons\n// -------------------------\n\n// Make a button look and behave like a link\n.btn-link {\n  color: $link-color;\n  font-weight: normal;\n  cursor: pointer;\n  border-radius: 0;\n\n  &,\n  &:active,\n  &[disabled],\n  fieldset[disabled] & {\n    background-color: transparent;\n    @include box-shadow(none);\n  }\n  &,\n  &:hover,\n  &:focus,\n  &:active {\n    border-color: transparent;\n  }\n  &:hover,\n  &:focus {\n    color: $link-hover-color;\n    text-decoration: underline;\n    background-color: transparent;\n  }\n  &[disabled],\n  fieldset[disabled] & {\n    &:hover,\n    &:focus {\n      color: $btn-link-disabled-color;\n      text-decoration: none;\n    }\n  }\n}\n\n\n// Button Sizes\n// --------------------------------------------------\n\n.btn-lg {\n  // line-height: ensure even-numbered height of button next to large input\n  @include button-size($padding-large-vertical, $padding-large-horizontal, $font-size-large, $line-height-large, $border-radius-large);\n}\n.btn-sm,\n.btn-xs {\n  // line-height: ensure proper height of button next to small input\n  @include button-size($padding-small-vertical, $padding-small-horizontal, $font-size-small, $line-height-small, $border-radius-small);\n}\n.btn-xs {\n  padding: 1px 5px;\n}\n\n\n// Block button\n// --------------------------------------------------\n\n.btn-block {\n  display: block;\n  width: 100%;\n  padding-left: 0;\n  padding-right: 0;\n}\n\n// Vertically space out multiple block buttons\n.btn-block + .btn-block {\n  margin-top: 5px;\n}\n\n// Specificity overrides\ninput[type=\"submit\"],\ninput[type=\"reset\"],\ninput[type=\"button\"] {\n  &.btn-block {\n    width: 100%;\n  }\n}\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/sass-bootstrap/lib/_carousel.scss",
    "content": "//\n// Carousel\n// --------------------------------------------------\n\n\n// Wrapper for the slide container and indicators\n.carousel {\n  position: relative;\n}\n\n.carousel-inner {\n  position: relative;\n  overflow: hidden;\n  width: 100%;\n\n  > .item {\n    display: none;\n    position: relative;\n    @include transition(.6s ease-in-out left);\n\n    // Account for jankitude on images\n    > img,\n    > a > img {\n      @include img-responsive();\n      line-height: 1;\n    }\n  }\n\n  > .active,\n  > .next,\n  > .prev { display: block; }\n\n  > .active {\n    left: 0;\n  }\n\n  > .next,\n  > .prev {\n    position: absolute;\n    top: 0;\n    width: 100%;\n  }\n\n  > .next {\n    left: 100%;\n  }\n  > .prev {\n    left: -100%;\n  }\n  > .next.left,\n  > .prev.right {\n    left: 0;\n  }\n\n  > .active.left {\n    left: -100%;\n  }\n  > .active.right {\n    left: 100%;\n  }\n\n}\n\n// Left/right controls for nav\n// ---------------------------\n\n.carousel-control {\n  position: absolute;\n  top: 0;\n  left: 0;\n  bottom: 0;\n  width: $carousel-control-width;\n  @include opacity($carousel-control-opacity);\n  font-size: $carousel-control-font-size;\n  color: $carousel-control-color;\n  text-align: center;\n  text-shadow: $carousel-text-shadow;\n  // We can't have this transition here because webkit cancels the carousel\n  // animation if you trip this while in the middle of another animation.\n\n  // Set gradients for backgrounds\n  &.left {\n    @include gradient-horizontal($start-color: rgba(0,0,0,.5), $end-color: rgba(0,0,0,.0001));\n  }\n  &.right {\n    left: auto;\n    right: 0;\n    @include gradient-horizontal($start-color: rgba(0,0,0,.0001), $end-color: rgba(0,0,0,.5));\n  }\n\n  // Hover/focus state\n  &:hover,\n  &:focus {\n    color: $carousel-control-color;\n    text-decoration: none;\n    @include opacity(.9);\n  }\n\n  // Toggles\n  .icon-prev,\n  .icon-next,\n  .glyphicon-chevron-left,\n  .glyphicon-chevron-right {\n    position: absolute;\n    top: 50%;\n    left: 50%;\n    z-index: 5;\n    display: inline-block;\n  }\n  .icon-prev,\n  .icon-next {\n    width:  20px;\n    height: 20px;\n    margin-top: -10px;\n    margin-left: -10px;\n    font-family: serif;\n  }\n\n  .icon-prev {\n    &:before {\n      content: '\\2039';// SINGLE LEFT-POINTING ANGLE QUOTATION MARK (U+2039)\n    }\n  }\n  .icon-next {\n    &:before {\n      content: '\\203a';// SINGLE RIGHT-POINTING ANGLE QUOTATION MARK (U+203A)\n    }\n  }\n}\n\n// Optional indicator pips\n//\n// Add an unordered list with the following class and add a list item for each\n// slide your carousel holds.\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  li {\n    display: inline-block;\n    width:  10px;\n    height: 10px;\n    margin: 1px;\n    text-indent: -999px;\n    border: 1px solid $carousel-indicator-border-color;\n    border-radius: 10px;\n    cursor: pointer;\n  }\n  .active {\n    margin: 0;\n    width:  12px;\n    height: 12px;\n    background-color: $carousel-indicator-active-bg;\n  }\n}\n\n// Optional captions\n// -----------------------------\n// Hidden by default for smaller viewports\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: $carousel-caption-color;\n  text-align: center;\n  text-shadow: $carousel-text-shadow;\n  & .btn {\n    text-shadow: none; // No shadow for button elements in carousel-caption\n  }\n}\n\n\n// Scale up controls for tablets and up\n@media screen and (min-width: $screen-tablet) {\n\n  // Scale up the controls a smidge\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\n  // Show and left align the captions\n  .carousel-caption {\n    left: 20%;\n    right: 20%;\n    padding-bottom: 30px;\n  }\n\n  // Move up the indicators\n  .carousel-indicators {\n    bottom: 20px;\n  }\n}\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/sass-bootstrap/lib/_close.scss",
    "content": "//\n// Close icons\n// --------------------------------------------------\n\n\n.close {\n  float: right;\n  font-size: ($font-size-base * 1.5);\n  font-weight: $close-font-weight;\n  line-height: 1;\n  color: $close-color;\n  text-shadow: $close-text-shadow;\n  @include opacity(.2);\n\n  &:hover,\n  &:focus {\n    color: $close-color;\n    text-decoration: none;\n    cursor: pointer;\n    @include opacity(.5);\n  }\n}\n\n// Additional properties for button version\n// iOS requires the button element instead of an anchor tag.\n// If you want the anchor version, it requires `href=\"#\"`.\nbutton.close {\n  padding: 0;\n  cursor: pointer;\n  background: transparent;\n  border: 0;\n  -webkit-appearance: none;\n}\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/sass-bootstrap/lib/_code.scss",
    "content": "//\n// Code (inline and blocK)\n// --------------------------------------------------\n\n\n// Inline and block code styles\ncode,\npre {\n  font-family: $font-family-monospace;\n}\n\n// Inline code\ncode {\n  padding: 2px 4px;\n  font-size: 90%;\n  color: $code-color;\n  background-color: $code-bg;\n  white-space: nowrap;\n  border-radius: $border-radius-base;\n}\n\n// Blocks of code\npre {\n  display: block;\n  padding: (($line-height-computed - 1) / 2);\n  margin: 0 0 ($line-height-computed / 2);\n  font-size: ($font-size-base - 1); // 14px to 13px\n  line-height: $line-height-base;\n  word-break: break-all;\n  word-wrap: break-word;\n  color: $pre-color;\n  background-color: $pre-bg;\n  border: 1px solid $pre-border-color;\n  border-radius: $border-radius-base;\n\n  // Make prettyprint styles more spaced out for readability\n  &.prettyprint {\n    margin-bottom: $line-height-computed;\n  }\n\n  // Account for some code outputs that place code tags in pre tags\n  code {\n    padding: 0;\n    font-size: inherit;\n    color: inherit;\n    white-space: pre-wrap;\n    background-color: transparent;\n    border: 0;\n  }\n}\n\n// Enable scrollable blocks of code\n.pre-scrollable {\n  max-height: $pre-scrollable-max-height;\n  overflow-y: scroll;\n}\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/sass-bootstrap/lib/_component-animations.scss",
    "content": "//\n// Component animations\n// --------------------------------------------------\n\n// Heads up!\n//\n// We don't use the `.opacity()` mixin here since it causes a bug with text\n// fields in IE7-8. Source: https://github.com/twitter/bootstrap/pull/3552.\n\n.fade {\n  opacity: 0;\n  @include transition(opacity .15s linear);\n  &.in {\n    opacity: 1;\n  }\n}\n\n.collapse {\n  display: none;\n  &.in {\n    display: block;\n  }\n}\n.collapsing {\n  position: relative;\n  height: 0;\n  overflow: hidden;\n  @include transition(height .35s ease);\n}\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/sass-bootstrap/lib/_dropdowns.scss",
    "content": "//\n// Dropdown menus\n// --------------------------------------------------\n\n\n// Dropdown arrow/caret\n.caret {\n  display: inline-block;\n  width: 0;\n  height: 0;\n  margin-left: 2px;\n  vertical-align: middle;\n  border-top:   $caret-width-base solid $dropdown-caret-color;\n  border-right: $caret-width-base solid transparent;\n  border-left:  $caret-width-base solid transparent;\n  // Firefox fix for https://github.com/twbs/bootstrap/issues/9538. Once fixed,\n  // we can just straight up remove this.\n  border-bottom: 0 dotted;\n  content: \"\";\n}\n\n// The dropdown wrapper (div)\n.dropdown {\n  position: relative;\n}\n\n// Prevent the focus on the dropdown toggle when closing dropdowns\n.dropdown-toggle:focus {\n  outline: 0;\n}\n\n// The dropdown menu (ul)\n.dropdown-menu {\n  position: absolute;\n  top: 100%;\n  left: 0;\n  z-index: $zindex-dropdown;\n  display: none; // none by default, but block on \"open\" of the menu\n  float: left;\n  min-width: 160px;\n  padding: 5px 0;\n  margin: 2px 0 0; // override default ul\n  list-style: none;\n  font-size: $font-size-base;\n  background-color: $dropdown-bg;\n  border: 1px solid $dropdown-fallback-border; // IE8 fallback\n  border: 1px solid $dropdown-border;\n  border-radius: $border-radius-base;\n  @include box-shadow(0 6px 12px rgba(0,0,0,.175));\n  background-clip: padding-box;\n\n  // Aligns the dropdown menu to right\n  &.pull-right {\n    right: 0;\n    left: auto;\n  }\n\n  // Dividers (basically an hr) within the dropdown\n  .divider {\n    @include nav-divider($dropdown-divider-bg);\n  }\n\n  // Links within the dropdown menu\n  > li > a {\n    display: block;\n    padding: 3px 20px;\n    clear: both;\n    font-weight: normal;\n    line-height: $line-height-base;\n    color: $dropdown-link-color;\n    white-space: nowrap; // prevent links from randomly breaking onto new lines\n  }\n}\n\n// Hover/Focus state\n.dropdown-menu > li > a {\n  &:hover,\n  &:focus {\n    text-decoration: none;\n    color: $dropdown-link-hover-color;\n    background-color: $dropdown-link-hover-bg;\n  }\n}\n\n// Active state\n.dropdown-menu > .active > a {\n  &,\n  &:hover,\n  &:focus {\n    color: $dropdown-link-active-color;\n    text-decoration: none;\n    outline: 0;\n    background-color: $dropdown-link-active-bg;\n  }\n}\n\n// Disabled state\n//\n// Gray out text and ensure the hover/focus state remains gray\n\n.dropdown-menu > .disabled > a {\n  &,\n  &:hover,\n  &:focus {\n    color: $dropdown-link-disabled-color;\n  }\n}\n// Nuke hover/focus effects\n.dropdown-menu > .disabled > a {\n  &:hover,\n  &:focus {\n    text-decoration: none;\n    background-color: transparent;\n    background-image: none; // Remove CSS gradient\n    @include reset-filter();\n    cursor: not-allowed;\n  }\n}\n\n// Open state for the dropdown\n.open {\n  // Show the menu\n  > .dropdown-menu {\n    display: block;\n  }\n\n  // Remove the outline when :focus is triggered\n  > a {\n    outline: 0;\n  }\n}\n\n// Dropdown section headers\n.dropdown-header {\n  display: block;\n  padding: 3px 20px;\n  font-size: $font-size-small;\n  line-height: $line-height-base;\n  color: $dropdown-header-color;\n}\n\n// Backdrop to catch body clicks on mobile, etc.\n.dropdown-backdrop {\n  position: fixed;\n  left: 0;\n  right: 0;\n  bottom: 0;\n  top: 0;\n  z-index: $zindex-dropdown - 10;\n}\n\n// Right aligned dropdowns\n.pull-right > .dropdown-menu {\n  right: 0;\n  left: auto;\n}\n\n// Allow for dropdowns to go bottom up (aka, dropup-menu)\n//\n// Just add .dropup after the standard .dropdown class and you're set, bro.\n// TODO: abstract this so that the navbar fixed styles are not placed here?\n\n.dropup,\n.navbar-fixed-bottom .dropdown {\n  // Reverse the caret\n  .caret {\n    // Firefox fix for https://github.com/twbs/bootstrap/issues/9538. Once this\n    // gets fixed, restore `border-top: 0;`.\n    border-top: 0 dotted;\n    border-bottom: 4px solid $dropdown-caret-color;\n    content: \"\";\n  }\n  // Different positioning for bottom up menu\n  .dropdown-menu {\n    top: auto;\n    bottom: 100%;\n    margin-bottom: 1px;\n  }\n}\n\n\n// Component alignment\n//\n// Reiterate per navbar.less and the modified component alignment there.\n\n@media (min-width: $grid-float-breakpoint) {\n  .navbar-right {\n    .dropdown-menu {\n      right: 0;\n      left: auto;\n    }\n  }\n}\n\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/sass-bootstrap/lib/_forms.scss",
    "content": "//\n// Forms\n// --------------------------------------------------\n\n\n// Normalize non-controls\n//\n// Restyle and baseline non-control form elements.\n\nfieldset {\n  padding: 0;\n  margin: 0;\n  border: 0;\n}\n\nlegend {\n  display: block;\n  width: 100%;\n  padding: 0;\n  margin-bottom: $line-height-computed;\n  font-size: ($font-size-base * 1.5);\n  line-height: inherit;\n  color: $legend-color;\n  border: 0;\n  border-bottom: 1px solid $legend-border-color;\n}\n\nlabel {\n  display: inline-block;\n  margin-bottom: 5px;\n  font-weight: bold;\n}\n\n\n// Normalize form controls\n\n// Override content-box in Normalize (* isn't specific enough)\ninput[type=\"search\"] {\n  @include box-sizing(border-box);\n}\n\n// Position radios and checkboxes better\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  margin: 4px 0 0;\n  margin-top: 1px \\9; /* IE8-9 */\n  line-height: normal;\n}\n\n// Set the height of select and file controls to match text inputs\ninput[type=\"file\"] {\n  display: block;\n}\n\n// Make multiple select elements height not fixed\nselect[multiple],\nselect[size] {\n  height: auto;\n}\n\n// Fix optgroup Firefox bug per https://github.com/twbs/bootstrap/issues/7611\nselect optgroup {\n  font-size: inherit;\n  font-style: inherit;\n  font-family: inherit;\n}\n\n// Focus for select, file, radio, and checkbox\ninput[type=\"file\"]:focus,\ninput[type=\"radio\"]:focus,\ninput[type=\"checkbox\"]:focus {\n  @include tab-focus();\n}\n\n// Fix for Chrome number input\n// Setting certain font-sizes causes the `I` bar to appear on hover of the bottom increment button.\n// See https://github.com/twbs/bootstrap/issues/8350 for more.\ninput[type=\"number\"] {\n  &::-webkit-outer-spin-button,\n  &::-webkit-inner-spin-button {\n    height: auto;\n  }\n}\n\n\n// Placeholder\n//\n// Placeholder text gets special styles because when browsers invalidate entire\n// lines if it doesn't understand a selector/\n.form-control {\n  @include placeholder();\n}\n\n\n// Common form controls\n//\n// Shared size and type resets for form controls. Apply `.form-control` to any\n// of the following form controls:\n//\n// select\n// textarea\n// input[type=\"text\"]\n// input[type=\"password\"]\n// input[type=\"datetime\"]\n// input[type=\"datetime-local\"]\n// input[type=\"date\"]\n// input[type=\"month\"]\n// input[type=\"time\"]\n// input[type=\"week\"]\n// input[type=\"number\"]\n// input[type=\"email\"]\n// input[type=\"url\"]\n// input[type=\"search\"]\n// input[type=\"tel\"]\n// input[type=\"color\"]\n\n.form-control {\n  display: block;\n  width: 100%;\n  height: $input-height-base; // Make inputs at least the height of their button counterpart (base line-height + padding + border)\n  padding: $padding-base-vertical $padding-base-horizontal;\n  font-size: $font-size-base;\n  line-height: $line-height-base;\n  color: $input-color;\n  vertical-align: middle;\n  background-color: $input-bg;\n  border: 1px solid $input-border;\n  border-radius: $input-border-radius;\n  @include box-shadow(inset 0 1px 1px rgba(0,0,0,.075));\n  @include transition(border-color ease-in-out .15s, box-shadow ease-in-out .15s);\n\n  // Customize the `:focus` state to imitate native WebKit styles.\n  @include form-control-focus();\n\n  // Disabled and read-only inputs\n  // Note: HTML5 says that controls under a fieldset > legend:first-child won't\n  // be disabled if the fieldset is disabled. Due to implementation difficulty,\n  // we don't honor that edge case; we style them as disabled anyway.\n  &[disabled],\n  &[readonly],\n  fieldset[disabled] & {\n    cursor: not-allowed;\n    background-color: $input-bg-disabled;\n  }\n}\n\n// Reset height for `textarea`s\ntextarea.form-control {\n  height: auto;\n}\n\n\n// Form groups\n//\n// Designed to help with the organization and spacing of vertical forms. For\n// horizontal forms, use the predefined grid classes.\n\n.form-group {\n  margin-bottom: 15px;\n}\n\n\n// Checkboxes and radios\n//\n// Indent the labels to position radios/checkboxes as hanging controls.\n\n.radio,\n.checkbox {\n  display: block;\n  min-height: $line-height-computed; // clear the floating input if there is no label text\n  margin-top: 10px;\n  margin-bottom: 10px;\n  padding-left: 20px;\n  vertical-align: middle;\n  label {\n    display: inline;\n    margin-bottom: 0;\n    font-weight: normal;\n    cursor: pointer;\n  }\n}\n.radio input[type=\"radio\"],\n.radio-inline input[type=\"radio\"],\n.checkbox input[type=\"checkbox\"],\n.checkbox-inline input[type=\"checkbox\"] {\n  float: left;\n  margin-left: -20px;\n}\n.radio + .radio,\n.checkbox + .checkbox {\n  margin-top: -5px; // Move up sibling radios or checkboxes for tighter spacing\n}\n\n// Radios and checkboxes on same line\n.radio-inline,\n.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.radio-inline + .radio-inline,\n.checkbox-inline + .checkbox-inline {\n  margin-top: 0;\n  margin-left: 10px; // space out consecutive inline controls\n}\n\n// Apply same disabled cursor tweak as for inputs\n//\n// Note: Neither radios nor checkboxes can be readonly.\ninput[type=\"radio\"],\ninput[type=\"checkbox\"],\n.radio,\n.radio-inline,\n.checkbox,\n.checkbox-inline {\n  &[disabled],\n  fieldset[disabled] & {\n    cursor: not-allowed;\n  }\n}\n\n// Form control sizing\n\n@include input-size('.input-sm', $input-height-small, $padding-small-vertical, $padding-small-horizontal, $font-size-small, $line-height-small, $border-radius-small);\n\n@include input-size('.input-lg', $input-height-large, $padding-large-vertical, $padding-large-horizontal, $font-size-large, $line-height-large, $border-radius-large);\n\n\n// Form control feedback states\n//\n// Apply contextual and semantic states to individual form controls.\n\n// Warning\n.has-warning {\n  @include form-control-validation($state-warning-text, $state-warning-text, $state-warning-bg);\n}\n// Error\n.has-error {\n  @include form-control-validation($state-danger-text, $state-danger-text, $state-danger-bg);\n}\n// Success\n.has-success {\n  @include form-control-validation($state-success-text, $state-success-text, $state-success-bg);\n}\n\n\n// Static form control text\n//\n// Apply class to a `p` element to make any string of text align with labels in\n// a horizontal form layout.\n\n.form-control-static {\n  margin-bottom: 0; // Remove default margin from `p`\n  padding-top: ($padding-base-vertical + 1);\n}\n\n\n// Help text\n//\n// Apply to any element you wish to create light text for placement immediately\n// below a form control. Use for general help, formatting, or instructional text.\n\n.help-block {\n  display: block; // account for any element using help-block\n  margin-top: 5px;\n  margin-bottom: 10px;\n  color: lighten($text-color, 25%); // lighten the text some for contrast\n}\n\n\n\n// Inline forms\n//\n// Make forms appear inline(-block) by adding the `.form-inline` class. Inline\n// forms begin stacked on extra small (mobile) devices and then go inline when\n// viewports reach <768px.\n//\n// Requires wrapping inputs and labels with `.form-group` for proper display of\n// default HTML form controls and our custom form controls (e.g., input groups).\n//\n// Heads up! This is mixin-ed into `.navbar-form` in navbars.less.\n\n.form-inline {\n\n  // Kick in the inline\n  @media (min-width: $screen-tablet) {\n    // Inline-block all the things for \"inline\"\n    .form-group  {\n      display: inline-block;\n      margin-bottom: 0;\n      vertical-align: middle;\n    }\n\n    // In navbar-form, allow folks to *not* use `.form-group`\n    .form-control {\n      display: inline-block;\n    }\n\n    // Remove default margin on radios/checkboxes that were used for stacking, and\n    // then undo the floating of radios and checkboxes to match (which also avoids\n    // a bug in WebKit: https://github.com/twbs/bootstrap/issues/1969).\n    .radio,\n    .checkbox {\n      display: inline-block;\n      margin-top: 0;\n      margin-bottom: 0;\n      padding-left: 0;\n    }\n    .radio input[type=\"radio\"],\n    .checkbox input[type=\"checkbox\"] {\n      float: none;\n      margin-left: 0;\n    }\n  }\n}\n\n\n// Horizontal forms\n//\n// Horizontal forms are built on grid classes and allow you to create forms with\n// labels on the left and inputs on the right.\n\n.form-horizontal {\n\n  // Consistent vertical alignment of labels, radios, and checkboxes\n  .control-label,\n  .radio,\n  .checkbox,\n  .radio-inline,\n  .checkbox-inline {\n    margin-top: 0;\n    margin-bottom: 0;\n    padding-top: ($padding-base-vertical + 1); // Default padding plus a border\n  }\n\n  // Make form groups behave like rows\n  .form-group {\n    @include make-row();\n  }\n\n  // Only right align form labels here when the columns stop stacking\n  @media (min-width: $screen-tablet) {\n    .control-label {\n      text-align: right;\n    }\n  }\n}\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/sass-bootstrap/lib/_glyphicons.scss",
    "content": "//\n// Glyphicons for Bootstrap\n//\n// Since icons are fonts, they can be placed anywhere text is placed and are\n// thus automatically sized to match the surrounding child. To use, create an\n// inline element with the appropriate classes, like so:\n//\n// <a href=\"#\"><span class=\"glyphicon glyphicon-star\"></span> Star</a>\n\n// Import the fonts\n@font-face {\n  font-family: 'Glyphicons Halflings';\n  src: url('#{$icon-font-path}#{$icon-font-name}.eot');\n  src: url('#{$icon-font-path}#{$icon-font-name}.eot?#iefix') format('embedded-opentype'),\n       url('#{$icon-font-path}#{$icon-font-name}.woff') format('woff'),\n       url('#{$icon-font-path}#{$icon-font-name}.ttf') format('truetype'),\n       url('#{$icon-font-path}#{$icon-font-name}.svg#glyphicons-halflingsregular') format('svg');\n}\n\n// Catchall baseclass\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  -webkit-font-smoothing: antialiased;\n}\n\n// Individual icons\n.glyphicon-asterisk               { &:before { content: \"\\2a\"; } }\n.glyphicon-plus                   { &:before { content: \"\\2b\"; } }\n.glyphicon-euro                   { &:before { content: \"\\20ac\"; } }\n.glyphicon-minus                  { &:before { content: \"\\2212\"; } }\n.glyphicon-cloud                  { &:before { content: \"\\2601\"; } }\n.glyphicon-envelope               { &:before { content: \"\\2709\"; } }\n.glyphicon-pencil                 { &:before { content: \"\\270f\"; } }\n.glyphicon-glass                  { &:before { content: \"\\e001\"; } }\n.glyphicon-music                  { &:before { content: \"\\e002\"; } }\n.glyphicon-search                 { &:before { content: \"\\e003\"; } }\n.glyphicon-heart                  { &:before { content: \"\\e005\"; } }\n.glyphicon-star                   { &:before { content: \"\\e006\"; } }\n.glyphicon-star-empty             { &:before { content: \"\\e007\"; } }\n.glyphicon-user                   { &:before { content: \"\\e008\"; } }\n.glyphicon-film                   { &:before { content: \"\\e009\"; } }\n.glyphicon-th-large               { &:before { content: \"\\e010\"; } }\n.glyphicon-th                     { &:before { content: \"\\e011\"; } }\n.glyphicon-th-list                { &:before { content: \"\\e012\"; } }\n.glyphicon-ok                     { &:before { content: \"\\e013\"; } }\n.glyphicon-remove                 { &:before { content: \"\\e014\"; } }\n.glyphicon-zoom-in                { &:before { content: \"\\e015\"; } }\n.glyphicon-zoom-out               { &:before { content: \"\\e016\"; } }\n.glyphicon-off                    { &:before { content: \"\\e017\"; } }\n.glyphicon-signal                 { &:before { content: \"\\e018\"; } }\n.glyphicon-cog                    { &:before { content: \"\\e019\"; } }\n.glyphicon-trash                  { &:before { content: \"\\e020\"; } }\n.glyphicon-home                   { &:before { content: \"\\e021\"; } }\n.glyphicon-file                   { &:before { content: \"\\e022\"; } }\n.glyphicon-time                   { &:before { content: \"\\e023\"; } }\n.glyphicon-road                   { &:before { content: \"\\e024\"; } }\n.glyphicon-download-alt           { &:before { content: \"\\e025\"; } }\n.glyphicon-download               { &:before { content: \"\\e026\"; } }\n.glyphicon-upload                 { &:before { content: \"\\e027\"; } }\n.glyphicon-inbox                  { &:before { content: \"\\e028\"; } }\n.glyphicon-play-circle            { &:before { content: \"\\e029\"; } }\n.glyphicon-repeat                 { &:before { content: \"\\e030\"; } }\n.glyphicon-refresh                { &:before { content: \"\\e031\"; } }\n.glyphicon-list-alt               { &:before { content: \"\\e032\"; } }\n.glyphicon-flag                   { &:before { content: \"\\e034\"; } }\n.glyphicon-headphones             { &:before { content: \"\\e035\"; } }\n.glyphicon-volume-off             { &:before { content: \"\\e036\"; } }\n.glyphicon-volume-down            { &:before { content: \"\\e037\"; } }\n.glyphicon-volume-up              { &:before { content: \"\\e038\"; } }\n.glyphicon-qrcode                 { &:before { content: \"\\e039\"; } }\n.glyphicon-barcode                { &:before { content: \"\\e040\"; } }\n.glyphicon-tag                    { &:before { content: \"\\e041\"; } }\n.glyphicon-tags                   { &:before { content: \"\\e042\"; } }\n.glyphicon-book                   { &:before { content: \"\\e043\"; } }\n.glyphicon-print                  { &:before { content: \"\\e045\"; } }\n.glyphicon-font                   { &:before { content: \"\\e047\"; } }\n.glyphicon-bold                   { &:before { content: \"\\e048\"; } }\n.glyphicon-italic                 { &:before { content: \"\\e049\"; } }\n.glyphicon-text-height            { &:before { content: \"\\e050\"; } }\n.glyphicon-text-width             { &:before { content: \"\\e051\"; } }\n.glyphicon-align-left             { &:before { content: \"\\e052\"; } }\n.glyphicon-align-center           { &:before { content: \"\\e053\"; } }\n.glyphicon-align-right            { &:before { content: \"\\e054\"; } }\n.glyphicon-align-justify          { &:before { content: \"\\e055\"; } }\n.glyphicon-list                   { &:before { content: \"\\e056\"; } }\n.glyphicon-indent-left            { &:before { content: \"\\e057\"; } }\n.glyphicon-indent-right           { &:before { content: \"\\e058\"; } }\n.glyphicon-facetime-video         { &:before { content: \"\\e059\"; } }\n.glyphicon-picture                { &:before { content: \"\\e060\"; } }\n.glyphicon-map-marker             { &:before { content: \"\\e062\"; } }\n.glyphicon-adjust                 { &:before { content: \"\\e063\"; } }\n.glyphicon-tint                   { &:before { content: \"\\e064\"; } }\n.glyphicon-edit                   { &:before { content: \"\\e065\"; } }\n.glyphicon-share                  { &:before { content: \"\\e066\"; } }\n.glyphicon-check                  { &:before { content: \"\\e067\"; } }\n.glyphicon-move                   { &:before { content: \"\\e068\"; } }\n.glyphicon-step-backward          { &:before { content: \"\\e069\"; } }\n.glyphicon-fast-backward          { &:before { content: \"\\e070\"; } }\n.glyphicon-backward               { &:before { content: \"\\e071\"; } }\n.glyphicon-play                   { &:before { content: \"\\e072\"; } }\n.glyphicon-pause                  { &:before { content: \"\\e073\"; } }\n.glyphicon-stop                   { &:before { content: \"\\e074\"; } }\n.glyphicon-forward                { &:before { content: \"\\e075\"; } }\n.glyphicon-fast-forward           { &:before { content: \"\\e076\"; } }\n.glyphicon-step-forward           { &:before { content: \"\\e077\"; } }\n.glyphicon-eject                  { &:before { content: \"\\e078\"; } }\n.glyphicon-chevron-left           { &:before { content: \"\\e079\"; } }\n.glyphicon-chevron-right          { &:before { content: \"\\e080\"; } }\n.glyphicon-plus-sign              { &:before { content: \"\\e081\"; } }\n.glyphicon-minus-sign             { &:before { content: \"\\e082\"; } }\n.glyphicon-remove-sign            { &:before { content: \"\\e083\"; } }\n.glyphicon-ok-sign                { &:before { content: \"\\e084\"; } }\n.glyphicon-question-sign          { &:before { content: \"\\e085\"; } }\n.glyphicon-info-sign              { &:before { content: \"\\e086\"; } }\n.glyphicon-screenshot             { &:before { content: \"\\e087\"; } }\n.glyphicon-remove-circle          { &:before { content: \"\\e088\"; } }\n.glyphicon-ok-circle              { &:before { content: \"\\e089\"; } }\n.glyphicon-ban-circle             { &:before { content: \"\\e090\"; } }\n.glyphicon-arrow-left             { &:before { content: \"\\e091\"; } }\n.glyphicon-arrow-right            { &:before { content: \"\\e092\"; } }\n.glyphicon-arrow-up               { &:before { content: \"\\e093\"; } }\n.glyphicon-arrow-down             { &:before { content: \"\\e094\"; } }\n.glyphicon-share-alt              { &:before { content: \"\\e095\"; } }\n.glyphicon-resize-full            { &:before { content: \"\\e096\"; } }\n.glyphicon-resize-small           { &:before { content: \"\\e097\"; } }\n.glyphicon-exclamation-sign       { &:before { content: \"\\e101\"; } }\n.glyphicon-gift                   { &:before { content: \"\\e102\"; } }\n.glyphicon-leaf                   { &:before { content: \"\\e103\"; } }\n.glyphicon-eye-open               { &:before { content: \"\\e105\"; } }\n.glyphicon-eye-close              { &:before { content: \"\\e106\"; } }\n.glyphicon-warning-sign           { &:before { content: \"\\e107\"; } }\n.glyphicon-plane                  { &:before { content: \"\\e108\"; } }\n.glyphicon-random                 { &:before { content: \"\\e110\"; } }\n.glyphicon-comment                { &:before { content: \"\\e111\"; } }\n.glyphicon-magnet                 { &:before { content: \"\\e112\"; } }\n.glyphicon-chevron-up             { &:before { content: \"\\e113\"; } }\n.glyphicon-chevron-down           { &:before { content: \"\\e114\"; } }\n.glyphicon-retweet                { &:before { content: \"\\e115\"; } }\n.glyphicon-shopping-cart          { &:before { content: \"\\e116\"; } }\n.glyphicon-folder-close           { &:before { content: \"\\e117\"; } }\n.glyphicon-folder-open            { &:before { content: \"\\e118\"; } }\n.glyphicon-resize-vertical        { &:before { content: \"\\e119\"; } }\n.glyphicon-resize-horizontal      { &:before { content: \"\\e120\"; } }\n.glyphicon-hdd                    { &:before { content: \"\\e121\"; } }\n.glyphicon-bullhorn               { &:before { content: \"\\e122\"; } }\n.glyphicon-certificate            { &:before { content: \"\\e124\"; } }\n.glyphicon-thumbs-up              { &:before { content: \"\\e125\"; } }\n.glyphicon-thumbs-down            { &:before { content: \"\\e126\"; } }\n.glyphicon-hand-right             { &:before { content: \"\\e127\"; } }\n.glyphicon-hand-left              { &:before { content: \"\\e128\"; } }\n.glyphicon-hand-up                { &:before { content: \"\\e129\"; } }\n.glyphicon-hand-down              { &:before { content: \"\\e130\"; } }\n.glyphicon-circle-arrow-right     { &:before { content: \"\\e131\"; } }\n.glyphicon-circle-arrow-left      { &:before { content: \"\\e132\"; } }\n.glyphicon-circle-arrow-up        { &:before { content: \"\\e133\"; } }\n.glyphicon-circle-arrow-down      { &:before { content: \"\\e134\"; } }\n.glyphicon-globe                  { &:before { content: \"\\e135\"; } }\n.glyphicon-tasks                  { &:before { content: \"\\e137\"; } }\n.glyphicon-filter                 { &:before { content: \"\\e138\"; } }\n.glyphicon-fullscreen             { &:before { content: \"\\e140\"; } }\n.glyphicon-dashboard              { &:before { content: \"\\e141\"; } }\n.glyphicon-heart-empty            { &:before { content: \"\\e143\"; } }\n.glyphicon-link                   { &:before { content: \"\\e144\"; } }\n.glyphicon-phone                  { &:before { content: \"\\e145\"; } }\n.glyphicon-usd                    { &:before { content: \"\\e148\"; } }\n.glyphicon-gbp                    { &:before { content: \"\\e149\"; } }\n.glyphicon-sort                   { &:before { content: \"\\e150\"; } }\n.glyphicon-sort-by-alphabet       { &:before { content: \"\\e151\"; } }\n.glyphicon-sort-by-alphabet-alt   { &:before { content: \"\\e152\"; } }\n.glyphicon-sort-by-order          { &:before { content: \"\\e153\"; } }\n.glyphicon-sort-by-order-alt      { &:before { content: \"\\e154\"; } }\n.glyphicon-sort-by-attributes     { &:before { content: \"\\e155\"; } }\n.glyphicon-sort-by-attributes-alt { &:before { content: \"\\e156\"; } }\n.glyphicon-unchecked              { &:before { content: \"\\e157\"; } }\n.glyphicon-expand                 { &:before { content: \"\\e158\"; } }\n.glyphicon-collapse-down          { &:before { content: \"\\e159\"; } }\n.glyphicon-collapse-up            { &:before { content: \"\\e160\"; } }\n.glyphicon-log-in                 { &:before { content: \"\\e161\"; } }\n.glyphicon-flash                  { &:before { content: \"\\e162\"; } }\n.glyphicon-log-out                { &:before { content: \"\\e163\"; } }\n.glyphicon-new-window             { &:before { content: \"\\e164\"; } }\n.glyphicon-record                 { &:before { content: \"\\e165\"; } }\n.glyphicon-save                   { &:before { content: \"\\e166\"; } }\n.glyphicon-open                   { &:before { content: \"\\e167\"; } }\n.glyphicon-saved                  { &:before { content: \"\\e168\"; } }\n.glyphicon-import                 { &:before { content: \"\\e169\"; } }\n.glyphicon-export                 { &:before { content: \"\\e170\"; } }\n.glyphicon-send                   { &:before { content: \"\\e171\"; } }\n.glyphicon-floppy-disk            { &:before { content: \"\\e172\"; } }\n.glyphicon-floppy-saved           { &:before { content: \"\\e173\"; } }\n.glyphicon-floppy-remove          { &:before { content: \"\\e174\"; } }\n.glyphicon-floppy-save            { &:before { content: \"\\e175\"; } }\n.glyphicon-floppy-open            { &:before { content: \"\\e176\"; } }\n.glyphicon-credit-card            { &:before { content: \"\\e177\"; } }\n.glyphicon-transfer               { &:before { content: \"\\e178\"; } }\n.glyphicon-cutlery                { &:before { content: \"\\e179\"; } }\n.glyphicon-header                 { &:before { content: \"\\e180\"; } }\n.glyphicon-compressed             { &:before { content: \"\\e181\"; } }\n.glyphicon-earphone               { &:before { content: \"\\e182\"; } }\n.glyphicon-phone-alt              { &:before { content: \"\\e183\"; } }\n.glyphicon-tower                  { &:before { content: \"\\e184\"; } }\n.glyphicon-stats                  { &:before { content: \"\\e185\"; } }\n.glyphicon-sd-video               { &:before { content: \"\\e186\"; } }\n.glyphicon-hd-video               { &:before { content: \"\\e187\"; } }\n.glyphicon-subtitles              { &:before { content: \"\\e188\"; } }\n.glyphicon-sound-stereo           { &:before { content: \"\\e189\"; } }\n.glyphicon-sound-dolby            { &:before { content: \"\\e190\"; } }\n.glyphicon-sound-5-1              { &:before { content: \"\\e191\"; } }\n.glyphicon-sound-6-1              { &:before { content: \"\\e192\"; } }\n.glyphicon-sound-7-1              { &:before { content: \"\\e193\"; } }\n.glyphicon-copyright-mark         { &:before { content: \"\\e194\"; } }\n.glyphicon-registration-mark      { &:before { content: \"\\e195\"; } }\n.glyphicon-cloud-download         { &:before { content: \"\\e197\"; } }\n.glyphicon-cloud-upload           { &:before { content: \"\\e198\"; } }\n.glyphicon-tree-conifer           { &:before { content: \"\\e199\"; } }\n.glyphicon-tree-deciduous         { &:before { content: \"\\e200\"; } }\n.glyphicon-briefcase              { &:before { content: \"\\1f4bc\"; } }\n.glyphicon-calendar               { &:before { content: \"\\1f4c5\"; } }\n.glyphicon-pushpin                { &:before { content: \"\\1f4cc\"; } }\n.glyphicon-paperclip              { &:before { content: \"\\1f4ce\"; } }\n.glyphicon-camera                 { &:before { content: \"\\1f4f7\"; } }\n.glyphicon-lock                   { &:before { content: \"\\1f512\"; } }\n.glyphicon-bell                   { &:before { content: \"\\1f514\"; } }\n.glyphicon-bookmark               { &:before { content: \"\\1f516\"; } }\n.glyphicon-fire                   { &:before { content: \"\\1f525\"; } }\n.glyphicon-wrench                 { &:before { content: \"\\1f527\"; } }\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/sass-bootstrap/lib/_grid.scss",
    "content": "//\n// Grid system\n// --------------------------------------------------\n\n\n// Set the container width, and override it for fixed navbars in media queries\n.container {\n  @include container-fixed();\n}\n\n// mobile first defaults\n.row {\n  @include make-row();\n}\n\n// Common styles for small and large grid columns\n.col-xs-1,\n.col-xs-2,\n.col-xs-3,\n.col-xs-4,\n.col-xs-5,\n.col-xs-6,\n.col-xs-7,\n.col-xs-8,\n.col-xs-9,\n.col-xs-10,\n.col-xs-11,\n.col-xs-12,\n.col-sm-1,\n.col-sm-2,\n.col-sm-3,\n.col-sm-4,\n.col-sm-5,\n.col-sm-6,\n.col-sm-7,\n.col-sm-8,\n.col-sm-9,\n.col-sm-10,\n.col-sm-11,\n.col-sm-12,\n.col-md-1,\n.col-md-2,\n.col-md-3,\n.col-md-4,\n.col-md-5,\n.col-md-6,\n.col-md-7,\n.col-md-8,\n.col-md-9,\n.col-md-10,\n.col-md-11,\n.col-md-12,\n.col-lg-1,\n.col-lg-2,\n.col-lg-3,\n.col-lg-4,\n.col-lg-5,\n.col-lg-6,\n.col-lg-7,\n.col-lg-8,\n.col-lg-9,\n.col-lg-10,\n.col-lg-11,\n.col-lg-12 {\n  position: relative;\n  // Prevent columns from collapsing when empty\n  min-height: 1px;\n  // Inner gutter via padding\n  padding-left:  ($grid-gutter-width / 2);\n  padding-right: ($grid-gutter-width / 2);\n}\n\n\n// Extra small grid\n//\n// Grid classes for extra small devices like smartphones. No offset, push, or\n// pull classes are present here due to the size of the target.\n//\n// Note that `.col-xs-12` doesn't get floated on purpose—there's no need since\n// it's full-width.\n\n.col-xs-1,\n.col-xs-2,\n.col-xs-3,\n.col-xs-4,\n.col-xs-5,\n.col-xs-6,\n.col-xs-7,\n.col-xs-8,\n.col-xs-9,\n.col-xs-10,\n.col-xs-11 {\n  float: left;\n}\n.col-xs-1  { width: percentage((1 / $grid-columns)); }\n.col-xs-2  { width: percentage((2 / $grid-columns)); }\n.col-xs-3  { width: percentage((3 / $grid-columns)); }\n.col-xs-4  { width: percentage((4 / $grid-columns)); }\n.col-xs-5  { width: percentage((5 / $grid-columns)); }\n.col-xs-6  { width: percentage((6 / $grid-columns)); }\n.col-xs-7  { width: percentage((7 / $grid-columns)); }\n.col-xs-8  { width: percentage((8 / $grid-columns)); }\n.col-xs-9  { width: percentage((9 / $grid-columns)); }\n.col-xs-10 { width: percentage((10/ $grid-columns)); }\n.col-xs-11 { width: percentage((11/ $grid-columns)); }\n.col-xs-12 { width: 100%; }\n\n\n// Small grid\n//\n// Columns, offsets, pushes, and pulls for the small device range, from phones\n// to tablets.\n//\n// Note that `.col-sm-12` doesn't get floated on purpose—there's no need since\n// it's full-width.\n\n@media (min-width: $screen-tablet) {\n  .container {\n    max-width: $container-tablet;\n  }\n\n  .col-sm-1,\n  .col-sm-2,\n  .col-sm-3,\n  .col-sm-4,\n  .col-sm-5,\n  .col-sm-6,\n  .col-sm-7,\n  .col-sm-8,\n  .col-sm-9,\n  .col-sm-10,\n  .col-sm-11 {\n    float: left;\n  }\n  .col-sm-1  { width: percentage((1 / $grid-columns)); }\n  .col-sm-2  { width: percentage((2 / $grid-columns)); }\n  .col-sm-3  { width: percentage((3 / $grid-columns)); }\n  .col-sm-4  { width: percentage((4 / $grid-columns)); }\n  .col-sm-5  { width: percentage((5 / $grid-columns)); }\n  .col-sm-6  { width: percentage((6 / $grid-columns)); }\n  .col-sm-7  { width: percentage((7 / $grid-columns)); }\n  .col-sm-8  { width: percentage((8 / $grid-columns)); }\n  .col-sm-9  { width: percentage((9 / $grid-columns)); }\n  .col-sm-10 { width: percentage((10/ $grid-columns)); }\n  .col-sm-11 { width: percentage((11/ $grid-columns)); }\n  .col-sm-12 { width: 100%; }\n\n  // Push and pull columns for source order changes\n  .col-sm-push-1  { left: percentage((1 / $grid-columns)); }\n  .col-sm-push-2  { left: percentage((2 / $grid-columns)); }\n  .col-sm-push-3  { left: percentage((3 / $grid-columns)); }\n  .col-sm-push-4  { left: percentage((4 / $grid-columns)); }\n  .col-sm-push-5  { left: percentage((5 / $grid-columns)); }\n  .col-sm-push-6  { left: percentage((6 / $grid-columns)); }\n  .col-sm-push-7  { left: percentage((7 / $grid-columns)); }\n  .col-sm-push-8  { left: percentage((8 / $grid-columns)); }\n  .col-sm-push-9  { left: percentage((9 / $grid-columns)); }\n  .col-sm-push-10 { left: percentage((10/ $grid-columns)); }\n  .col-sm-push-11 { left: percentage((11/ $grid-columns)); }\n\n  .col-sm-pull-1  { right: percentage((1 / $grid-columns)); }\n  .col-sm-pull-2  { right: percentage((2 / $grid-columns)); }\n  .col-sm-pull-3  { right: percentage((3 / $grid-columns)); }\n  .col-sm-pull-4  { right: percentage((4 / $grid-columns)); }\n  .col-sm-pull-5  { right: percentage((5 / $grid-columns)); }\n  .col-sm-pull-6  { right: percentage((6 / $grid-columns)); }\n  .col-sm-pull-7  { right: percentage((7 / $grid-columns)); }\n  .col-sm-pull-8  { right: percentage((8 / $grid-columns)); }\n  .col-sm-pull-9  { right: percentage((9 / $grid-columns)); }\n  .col-sm-pull-10 { right: percentage((10/ $grid-columns)); }\n  .col-sm-pull-11 { right: percentage((11/ $grid-columns)); }\n\n  // Offsets\n  .col-sm-offset-1  { margin-left: percentage((1 / $grid-columns)); }\n  .col-sm-offset-2  { margin-left: percentage((2 / $grid-columns)); }\n  .col-sm-offset-3  { margin-left: percentage((3 / $grid-columns)); }\n  .col-sm-offset-4  { margin-left: percentage((4 / $grid-columns)); }\n  .col-sm-offset-5  { margin-left: percentage((5 / $grid-columns)); }\n  .col-sm-offset-6  { margin-left: percentage((6 / $grid-columns)); }\n  .col-sm-offset-7  { margin-left: percentage((7 / $grid-columns)); }\n  .col-sm-offset-8  { margin-left: percentage((8 / $grid-columns)); }\n  .col-sm-offset-9  { margin-left: percentage((9 / $grid-columns)); }\n  .col-sm-offset-10 { margin-left: percentage((10/ $grid-columns)); }\n  .col-sm-offset-11 { margin-left: percentage((11/ $grid-columns)); }\n}\n\n\n// Medium grid\n//\n// Columns, offsets, pushes, and pulls for the desktop device range.\n//\n// Note that `.col-md-12` doesn't get floated on purpose—there's no need since\n// it's full-width.\n\n@media (min-width: $screen-desktop) {\n  .container {\n    max-width: $container-desktop;\n  }\n  .col-md-1,\n  .col-md-2,\n  .col-md-3,\n  .col-md-4,\n  .col-md-5,\n  .col-md-6,\n  .col-md-7,\n  .col-md-8,\n  .col-md-9,\n  .col-md-10,\n  .col-md-11 {\n    float: left;\n  }\n  .col-md-1  { width: percentage((1 / $grid-columns)); }\n  .col-md-2  { width: percentage((2 / $grid-columns)); }\n  .col-md-3  { width: percentage((3 / $grid-columns)); }\n  .col-md-4  { width: percentage((4 / $grid-columns)); }\n  .col-md-5  { width: percentage((5 / $grid-columns)); }\n  .col-md-6  { width: percentage((6 / $grid-columns)); }\n  .col-md-7  { width: percentage((7 / $grid-columns)); }\n  .col-md-8  { width: percentage((8 / $grid-columns)); }\n  .col-md-9  { width: percentage((9 / $grid-columns)); }\n  .col-md-10 { width: percentage((10/ $grid-columns)); }\n  .col-md-11 { width: percentage((11/ $grid-columns)); }\n  .col-md-12 { width: 100%; }\n\n  // Push and pull columns for source order changes\n  .col-md-push-0  { left: auto; }\n  .col-md-push-1  { left: percentage((1 / $grid-columns)); }\n  .col-md-push-2  { left: percentage((2 / $grid-columns)); }\n  .col-md-push-3  { left: percentage((3 / $grid-columns)); }\n  .col-md-push-4  { left: percentage((4 / $grid-columns)); }\n  .col-md-push-5  { left: percentage((5 / $grid-columns)); }\n  .col-md-push-6  { left: percentage((6 / $grid-columns)); }\n  .col-md-push-7  { left: percentage((7 / $grid-columns)); }\n  .col-md-push-8  { left: percentage((8 / $grid-columns)); }\n  .col-md-push-9  { left: percentage((9 / $grid-columns)); }\n  .col-md-push-10 { left: percentage((10/ $grid-columns)); }\n  .col-md-push-11 { left: percentage((11/ $grid-columns)); }\n\n  .col-md-pull-0  { right: auto; }\n  .col-md-pull-1  { right: percentage((1 / $grid-columns)); }\n  .col-md-pull-2  { right: percentage((2 / $grid-columns)); }\n  .col-md-pull-3  { right: percentage((3 / $grid-columns)); }\n  .col-md-pull-4  { right: percentage((4 / $grid-columns)); }\n  .col-md-pull-5  { right: percentage((5 / $grid-columns)); }\n  .col-md-pull-6  { right: percentage((6 / $grid-columns)); }\n  .col-md-pull-7  { right: percentage((7 / $grid-columns)); }\n  .col-md-pull-8  { right: percentage((8 / $grid-columns)); }\n  .col-md-pull-9  { right: percentage((9 / $grid-columns)); }\n  .col-md-pull-10 { right: percentage((10/ $grid-columns)); }\n  .col-md-pull-11 { right: percentage((11/ $grid-columns)); }\n\n  // Offsets\n  .col-md-offset-0  { margin-left: 0; }\n  .col-md-offset-1  { margin-left: percentage((1 / $grid-columns)); }\n  .col-md-offset-2  { margin-left: percentage((2 / $grid-columns)); }\n  .col-md-offset-3  { margin-left: percentage((3 / $grid-columns)); }\n  .col-md-offset-4  { margin-left: percentage((4 / $grid-columns)); }\n  .col-md-offset-5  { margin-left: percentage((5 / $grid-columns)); }\n  .col-md-offset-6  { margin-left: percentage((6 / $grid-columns)); }\n  .col-md-offset-7  { margin-left: percentage((7 / $grid-columns)); }\n  .col-md-offset-8  { margin-left: percentage((8 / $grid-columns)); }\n  .col-md-offset-9  { margin-left: percentage((9 / $grid-columns)); }\n  .col-md-offset-10 { margin-left: percentage((10/ $grid-columns)); }\n  .col-md-offset-11 { margin-left: percentage((11/ $grid-columns)); }\n}\n\n\n// Large grid\n//\n// Columns, offsets, pushes, and pulls for the large desktop device range.\n//\n// Note that `.col-lg-12` doesn't get floated on purpose—there's no need since\n// it's full-width.\n\n@media (min-width: $screen-lg-desktop) {\n  .container {\n    max-width: $container-lg-desktop;\n  }\n\n  .col-lg-1,\n  .col-lg-2,\n  .col-lg-3,\n  .col-lg-4,\n  .col-lg-5,\n  .col-lg-6,\n  .col-lg-7,\n  .col-lg-8,\n  .col-lg-9,\n  .col-lg-10,\n  .col-lg-11 {\n    float: left;\n  }\n  .col-lg-1  { width: percentage((1 / $grid-columns)); }\n  .col-lg-2  { width: percentage((2 / $grid-columns)); }\n  .col-lg-3  { width: percentage((3 / $grid-columns)); }\n  .col-lg-4  { width: percentage((4 / $grid-columns)); }\n  .col-lg-5  { width: percentage((5 / $grid-columns)); }\n  .col-lg-6  { width: percentage((6 / $grid-columns)); }\n  .col-lg-7  { width: percentage((7 / $grid-columns)); }\n  .col-lg-8  { width: percentage((8 / $grid-columns)); }\n  .col-lg-9  { width: percentage((9 / $grid-columns)); }\n  .col-lg-10 { width: percentage((10/ $grid-columns)); }\n  .col-lg-11 { width: percentage((11/ $grid-columns)); }\n  .col-lg-12 { width: 100%; }\n\n  // Push and pull columns for source order changes\n  .col-lg-push-0  { left: auto; }\n  .col-lg-push-1  { left: percentage((1 / $grid-columns)); }\n  .col-lg-push-2  { left: percentage((2 / $grid-columns)); }\n  .col-lg-push-3  { left: percentage((3 / $grid-columns)); }\n  .col-lg-push-4  { left: percentage((4 / $grid-columns)); }\n  .col-lg-push-5  { left: percentage((5 / $grid-columns)); }\n  .col-lg-push-6  { left: percentage((6 / $grid-columns)); }\n  .col-lg-push-7  { left: percentage((7 / $grid-columns)); }\n  .col-lg-push-8  { left: percentage((8 / $grid-columns)); }\n  .col-lg-push-9  { left: percentage((9 / $grid-columns)); }\n  .col-lg-push-10 { left: percentage((10/ $grid-columns)); }\n  .col-lg-push-11 { left: percentage((11/ $grid-columns)); }\n\n  .col-lg-pull-0  { right: auto; }\n  .col-lg-pull-1  { right: percentage((1 / $grid-columns)); }\n  .col-lg-pull-2  { right: percentage((2 / $grid-columns)); }\n  .col-lg-pull-3  { right: percentage((3 / $grid-columns)); }\n  .col-lg-pull-4  { right: percentage((4 / $grid-columns)); }\n  .col-lg-pull-5  { right: percentage((5 / $grid-columns)); }\n  .col-lg-pull-6  { right: percentage((6 / $grid-columns)); }\n  .col-lg-pull-7  { right: percentage((7 / $grid-columns)); }\n  .col-lg-pull-8  { right: percentage((8 / $grid-columns)); }\n  .col-lg-pull-9  { right: percentage((9 / $grid-columns)); }\n  .col-lg-pull-10 { right: percentage((10/ $grid-columns)); }\n  .col-lg-pull-11 { right: percentage((11/ $grid-columns)); }\n\n  // Offsets\n  .col-lg-offset-0  { margin-left: 0; }\n  .col-lg-offset-1  { margin-left: percentage((1 / $grid-columns)); }\n  .col-lg-offset-2  { margin-left: percentage((2 / $grid-columns)); }\n  .col-lg-offset-3  { margin-left: percentage((3 / $grid-columns)); }\n  .col-lg-offset-4  { margin-left: percentage((4 / $grid-columns)); }\n  .col-lg-offset-5  { margin-left: percentage((5 / $grid-columns)); }\n  .col-lg-offset-6  { margin-left: percentage((6 / $grid-columns)); }\n  .col-lg-offset-7  { margin-left: percentage((7 / $grid-columns)); }\n  .col-lg-offset-8  { margin-left: percentage((8 / $grid-columns)); }\n  .col-lg-offset-9  { margin-left: percentage((9 / $grid-columns)); }\n  .col-lg-offset-10 { margin-left: percentage((10/ $grid-columns)); }\n  .col-lg-offset-11 { margin-left: percentage((11/ $grid-columns)); }\n}\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/sass-bootstrap/lib/_input-groups.scss",
    "content": "//\n// Input groups\n// --------------------------------------------------\n\n// Base styles\n// -------------------------\n.input-group {\n  position: relative; // For dropdowns\n  display: table;\n  border-collapse: separate; // prevent input groups from inheriting border styles from table cells when placed within a table\n\n  // Undo padding and float of grid classes\n  &.col {\n    float: none;\n    padding-left: 0;\n    padding-right: 0;\n  }\n\n  .form-control {\n    width: 100%;\n    margin-bottom: 0;\n  }\n}\n\n// Sizing options\n//\n// Remix the default form control sizing classes into new ones for easier\n// manipulation.\n\n.input-group-lg > .form-control,\n.input-group-lg > .input-group-addon,\n.input-group-lg > .input-group-btn > .btn { @extend .input-lg; }\n.input-group-sm > .form-control,\n.input-group-sm > .input-group-addon,\n.input-group-sm > .input-group-btn > .btn { @extend .input-sm; }\n\n\n// Display as table-cell\n// -------------------------\n.input-group-addon,\n.input-group-btn,\n.input-group .form-control {\n  display: table-cell;\n\n  &:not(:first-child):not(:last-child) {\n    border-radius: 0;\n  }\n}\n// Addon and addon wrapper for buttons\n.input-group-addon,\n.input-group-btn {\n  width: 1%;\n  white-space: nowrap;\n  vertical-align: middle; // Match the inputs\n}\n\n// Text input groups\n// -------------------------\n.input-group-addon {\n  padding: $padding-base-vertical $padding-base-horizontal;\n  font-size: $font-size-base;\n  font-weight: normal;\n  line-height: 1;\n  text-align: center;\n  background-color: $input-group-addon-bg;\n  border: 1px solid $input-group-addon-border-color;\n  border-radius: $border-radius-base;\n\n  // Sizing\n  &.input-sm {\n    padding: $padding-small-vertical $padding-small-horizontal;\n    font-size: $font-size-small;\n    border-radius: $border-radius-small;\n  }\n  &.input-lg {\n    padding: $padding-large-vertical $padding-large-horizontal;\n    font-size: $font-size-large;\n    border-radius: $border-radius-large;\n  }\n\n  // Nuke default margins from checkboxes and radios to vertically center within.\n  input[type=\"radio\"],\n  input[type=\"checkbox\"] {\n    margin-top: 0;\n  }\n}\n\n// Reset rounded corners\n.input-group .form-control:first-child,\n.input-group-addon:first-child,\n.input-group-btn:first-child > .btn,\n.input-group-btn:first-child > .dropdown-toggle,\n.input-group-btn:last-child > .btn:not(:last-child):not(.dropdown-toggle) {\n  @include border-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 > .dropdown-toggle,\n.input-group-btn:first-child > .btn:not(:first-child) {\n  @include border-left-radius(0);\n}\n.input-group-addon:last-child {\n  border-left: 0;\n}\n\n// Button input groups\n// -------------------------\n.input-group-btn {\n  position: relative;\n  white-space: nowrap;\n}\n.input-group-btn > .btn {\n  position: relative;\n  // Jankily prevent input button groups from wrapping\n  + .btn {\n    margin-left: -4px;\n  }\n  // Bring the \"active\" button to the front\n  &:hover,\n  &:active {\n    z-index: 2;\n  }\n}\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/sass-bootstrap/lib/_jumbotron.scss",
    "content": "//\n// Jumbotron\n// --------------------------------------------------\n\n\n.jumbotron {\n  padding: $jumbotron-padding;\n  margin-bottom: $jumbotron-padding;\n  font-size: ($font-size-base * 1.5);\n  font-weight: 200;\n  line-height: ($line-height-base * 1.5);\n  color: $jumbotron-color;\n  background-color: $jumbotron-bg;\n\n  h1 {\n    line-height: 1;\n    color: $jumbotron-heading-color;\n  }\n  p {\n    line-height: 1.4;\n  }\n\n  .container & {\n    border-radius: $border-radius-large; // Only round corners at higher resolutions if contained in a container\n  }\n\n  @media screen and (min-width: $screen-tablet) {\n    padding-top:    ($jumbotron-padding * 1.6);\n    padding-bottom: ($jumbotron-padding * 1.6);\n\n    .container & {\n      padding-left:  ($jumbotron-padding * 2);\n      padding-right: ($jumbotron-padding * 2);\n    }\n\n    h1 {\n      font-size: ($font-size-base * 4.5);\n    }\n  }\n}\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/sass-bootstrap/lib/_labels.scss",
    "content": "//\n// Labels\n// --------------------------------------------------\n\n.label {\n  display: inline;\n  padding: .2em .6em .3em;\n  font-size: 75%;\n  font-weight: bold;\n  line-height: 1;\n  color: $label-color;\n  text-align: center;\n  white-space: nowrap;\n  vertical-align: baseline;\n  border-radius: .25em;\n\n  // Add hover effects, but only for links\n  &[href] {\n    &:hover,\n    &:focus {\n      color: $label-link-hover-color;\n      text-decoration: none;\n      cursor: pointer;\n    }\n  }\n\n  // Empty labels collapse automatically (not available in IE8)\n  &:empty {\n    display: none;\n  }\n}\n\n// Colors\n// Contextual variations (linked labels get darker on :hover)\n\n.label-default {\n  @include label-variant($label-default-bg);\n}\n\n.label-primary {\n  @include label-variant($label-primary-bg);\n}\n\n.label-success {\n  @include label-variant($label-success-bg);\n}\n\n.label-info {\n  @include label-variant($label-info-bg);\n}\n\n.label-warning {\n  @include label-variant($label-warning-bg);\n}\n\n.label-danger {\n  @include label-variant($label-danger-bg);\n}\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/sass-bootstrap/lib/_list-group.scss",
    "content": "//\n// List groups\n// --------------------------------------------------\n\n// Base class\n//\n// Easily usable on <ul>, <ol>, or <div>.\n.list-group {\n  // No need to set list-style: none; since .list-group-item is block level\n  margin-bottom: 20px;\n  padding-left: 0; // reset padding because ul and ol\n}\n\n// Individual list items\n// -------------------------\n\n.list-group-item {\n  position: relative;\n  display: block;\n  padding: 10px 15px;\n  // Place the border on the list items and negative margin up for better styling\n  margin-bottom: -1px;\n  background-color: $list-group-bg;\n  border: 1px solid $list-group-border;\n\n  // Round the first and last items\n  &:first-child {\n    @include border-top-radius($list-group-border-radius);\n  }\n  &:last-child {\n    margin-bottom: 0;\n    @include border-bottom-radius($list-group-border-radius);\n  }\n\n  // Align badges within list items\n  > .badge {\n    float: right;\n  }\n  > .badge + .badge {\n    margin-right: 5px;\n  }\n\n  // Active class on item itself, not parent\n  &.active,\n  &.active:hover,\n  &.active:focus {\n    z-index: 2; // Place active items above their siblings for proper border styling\n    color: $list-group-active-color;\n    background-color: $list-group-active-bg;\n    border-color: $list-group-active-border;\n\n    // Force color to inherit for custom content\n    .list-group-item-heading {\n      color: inherit;\n    }\n    .list-group-item-text {\n      color: lighten($list-group-active-bg, 40%);\n    }\n  }\n}\n\n// Linked list items\na.list-group-item {\n  color: $list-group-link-color;\n\n  .list-group-item-heading {\n    color: $list-group-link-heading-color;\n  }\n\n  // Hover state\n  &:hover,\n  &:focus {\n    text-decoration: none;\n    background-color: $list-group-hover-bg;\n  }\n}\n\n// Custom content options\n// -------------------------\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"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/sass-bootstrap/lib/_media.scss",
    "content": "// Media objects\n// Source: http://stubbornella.org/content/?p=497\n// --------------------------------------------------\n\n\n// Common styles\n// -------------------------\n\n// Clear the floats\n.media,\n.media-body {\n  overflow: hidden;\n  zoom: 1;\n}\n\n// Proper spacing between instances of .media\n.media,\n.media .media {\n  margin-top: 15px;\n}\n.media:first-child {\n  margin-top: 0;\n}\n\n// For images and videos, set to block\n.media-object {\n  display: block;\n}\n\n// Reset margins on headings for tighter default spacing\n.media-heading {\n  margin: 0 0 5px;\n}\n\n\n// Media image alignment\n// -------------------------\n\n.media {\n  > .pull-left {\n    margin-right: 10px;\n  }\n  > .pull-right {\n    margin-left: 10px;\n  }\n}\n\n\n// Media list variation\n// -------------------------\n\n// Undo default ul/ol styles\n.media-list {\n  padding-left: 0;\n  list-style: none;\n}\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/sass-bootstrap/lib/_mixins.scss",
    "content": "//\n// Mixins\n// --------------------------------------------------\n\n\n// Utilities\n// -------------------------\n\n// Clearfix\n// Source: http://nicolasgallagher.com/micro-clearfix-hack/\n//\n// For modern browsers\n// 1. The space content is one way to avoid an Opera bug when the\n//    contenteditable attribute is included anywhere else in the document.\n//    Otherwise it causes space to appear at the top and bottom of elements\n//    that are clearfixed.\n// 2. The use of `table` rather than `block` is only necessary if using\n//    `:before` to contain the top-margins of child elements.\n@mixin clearfix() {\n  &:before,\n  &:after {\n    content: \" \"; /* 1 */\n    display: table; /* 2 */\n  }\n  &:after {\n    clear: both;\n  }\n}\n\n// Webkit-style focus\n@mixin tab-focus() {\n  // Default\n  outline: thin dotted #333;\n  // Webkit\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n\n// Center-align a block level element\n@mixin center-block() {\n  display: block;\n  margin-left: auto;\n  margin-right: auto;\n}\n\n// Sizing shortcuts\n@mixin size($width, $height) {\n  width: $width;\n  height: $height;\n}\n@mixin square($size) {\n  @include size($size, $size);\n}\n\n// Placeholder text\n@mixin placeholder($color: $input-color-placeholder) {\n  &:-moz-placeholder            { color: $color; } // Firefox 4-18\n  &::-moz-placeholder           { color: $color; } // Firefox 19+\n  &:-ms-input-placeholder       { color: $color; } // Internet Explorer 10+\n  &::-webkit-input-placeholder  { color: $color; } // Safari and Chrome\n}\n\n// Text overflow\n// Requires inline-block or block for proper styling\n@mixin text-overflow() {\n  overflow: hidden;\n  text-overflow: ellipsis;\n  white-space: nowrap;\n}\n\n// CSS image replacement\n// Source: https://github.com/h5bp/html5-boilerplate/commit/aa0396eae757\n@mixin hide-text() {\n  font: 0/0 a;\n  color: transparent;\n  text-shadow: none;\n  background-color: transparent;\n  border: 0;\n}\n\n\n\n// CSS3 PROPERTIES\n// --------------------------------------------------\n\n// Single side border-radius\n@mixin border-top-radius($radius) {\n  border-top-right-radius: $radius;\n   border-top-left-radius: $radius;\n}\n@mixin border-right-radius($radius) {\n  border-bottom-right-radius: $radius;\n     border-top-right-radius: $radius;\n}\n@mixin border-bottom-radius($radius) {\n  border-bottom-right-radius: $radius;\n   border-bottom-left-radius: $radius;\n}\n@mixin border-left-radius($radius) {\n  border-bottom-left-radius: $radius;\n     border-top-left-radius: $radius;\n}\n\n// Drop shadows\n@mixin box-shadow($shadow...) {\n  -webkit-box-shadow: $shadow; // iOS <4.3 & Android <4.1\n          box-shadow: $shadow;\n}\n\n// Transitions\n@mixin transition($transition...) {\n  -webkit-transition: $transition;\n          transition: $transition;\n}\n@mixin transition-delay($transition-delay) {\n  -webkit-transition-delay: $transition-delay;\n          transition-delay: $transition-delay;\n}\n@mixin transition-duration($transition-duration) {\n  -webkit-transition-duration: $transition-duration;\n          transition-duration: $transition-duration;\n}\n@mixin transition-transform($transition...) {\n  -webkit-transition: -webkit-transform $transition;\n     -moz-transition: -moz-transform $transition;\n       -o-transition: -o-transform $transition;\n          transition: transform $transition;\n}\n\n// Transformations\n@mixin rotate($degrees) {\n  -webkit-transform: rotate($degrees);\n      -ms-transform: rotate($degrees); // IE9+\n          transform: rotate($degrees);\n}\n@mixin scale($ratio) {\n  -webkit-transform: scale($ratio);\n      -ms-transform: scale($ratio); // IE9+\n          transform: scale($ratio);\n}\n@mixin translate($x, $y) {\n  -webkit-transform: translate($x, $y);\n      -ms-transform: translate($x, $y); // IE9+\n          transform: translate($x, $y);\n}\n@mixin skew($x, $y) {\n  -webkit-transform: skew($x, $y);\n      -ms-transform: skewX($x) skewY($y); // See https://github.com/twbs/bootstrap/issues/4885; IE9+\n          transform: skew($x, $y);\n}\n@mixin translate3d($x, $y, $z) {\n  -webkit-transform: translate3d($x, $y, $z);\n          transform: translate3d($x, $y, $z);\n}\n\n// Backface visibility\n// Prevent browsers from flickering when using CSS 3D transforms.\n// Default value is `visible`, but can be changed to `hidden`\n// See git pull https://github.com/dannykeane/bootstrap.git backface-visibility for examples\n@mixin backface-visibility($visibility){\n  -webkit-backface-visibility: $visibility;\n     -moz-backface-visibility: $visibility;\n          backface-visibility: $visibility;\n}\n\n// Box sizing\n@mixin box-sizing($boxmodel) {\n  -webkit-box-sizing: $boxmodel;\n     -moz-box-sizing: $boxmodel;\n          box-sizing: $boxmodel;\n}\n\n// User select\n// For selecting text on the page\n@mixin user-select($select) {\n  -webkit-user-select: $select;\n     -moz-user-select: $select;\n      -ms-user-select: $select; // IE10+\n       -o-user-select: $select;\n          user-select: $select;\n}\n\n// Resize anything\n@mixin resizable($direction) {\n  resize: $direction; // Options: horizontal, vertical, both\n  overflow: auto; // Safari fix\n}\n\n// CSS3 Content Columns\n@mixin content-columns($column-count, $column-gap: $grid-gutter-width) {\n  -webkit-column-count: $column-count;\n     -moz-column-count: $column-count;\n          column-count: $column-count;\n  -webkit-column-gap: $column-gap;\n     -moz-column-gap: $column-gap;\n          column-gap: $column-gap;\n}\n\n// Optional hyphenation\n@mixin hyphens($mode: auto) {\n  word-wrap: break-word;\n  -webkit-hyphens: $mode;\n     -moz-hyphens: $mode;\n      -ms-hyphens: $mode; // IE10+\n       -o-hyphens: $mode;\n          hyphens: $mode;\n}\n\n// Opacity\n@mixin opacity($opacity) {\n  opacity: $opacity;\n  // IE8 filter\n  $opacity-ie: ($opacity * 100);\n  filter: alpha(opacity=$opacity-ie);\n}\n\n\n\n// GRADIENTS\n// --------------------------------------------------\n\n\n\n// Horizontal gradient, from left to right\n//\n// Creates two color stops, start and end, by specifying a color and position for each color stop.\n// Color stops are not available in IE9 and below.\n@mixin gradient-horizontal($start-color: #555, $end-color: #333, $start-percent: 0%, $end-percent: 100%) {\n  background-image: -webkit-gradient(linear, $start-percent top, $end-percent top, from($start-color), to($end-color)); // Safari 4+, Chrome 2+\n  background-image: -webkit-linear-gradient(left, color-stop($start-color $start-percent), color-stop($end-color $end-percent)); // Safari 5.1+, Chrome 10+\n  background-image: -moz-linear-gradient(left, $start-color $start-percent, $end-color $end-percent); // FF 3.6+\n  background-image:  linear-gradient(to right, $start-color $start-percent, $end-color $end-percent); // Standard, IE10\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#{ie-hex-str($start-color)}', endColorstr='#{ie-hex-str($end-color)}', GradientType=1); // IE9 and down\n}\n\n// Vertical gradient, from top to bottom\n//\n// Creates two color stops, start and end, by specifying a color and position for each color stop.\n// Color stops are not available in IE9 and below.\n@mixin gradient-vertical($start-color: #555, $end-color: #333, $start-percent: 0%, $end-percent: 100%) {\n  background-image: -webkit-gradient(linear, left $start-percent, left $end-percent, from($start-color), to($end-color)); // Safari 4+, Chrome 2+\n  background-image: -webkit-linear-gradient(top, $start-color, $start-percent, $end-color, $end-percent); // Safari 5.1+, Chrome 10+\n  background-image:  -moz-linear-gradient(top, $start-color $start-percent, $end-color $end-percent); // FF 3.6+\n  background-image: linear-gradient(to bottom, $start-color $start-percent, $end-color $end-percent); // Standard, IE10\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#{ie-hex-str($start-color)}', endColorstr='#{ie-hex-str($end-color)}', GradientType=0); // IE9 and down\n}\n\n@mixin gradient-directional($start-color: #555, $end-color: #333, $deg: 45deg) {\n  background-repeat: repeat-x;\n  background-image: -webkit-linear-gradient($deg, $start-color, $end-color); // Safari 5.1+, Chrome 10+\n  background-image: -moz-linear-gradient($deg, $start-color, $end-color); // FF 3.6+\n  background-image: linear-gradient($deg, $start-color, $end-color); // Standard, IE10\n}\n@mixin gradient-horizontal-three-colors($start-color: #00b3ee, $mid-color: #7a43b6, $color-stop: 50%, $end-color: #c3325f) {\n  background-image: -webkit-gradient(left, linear, 0 0, 0 100%, from($start-color), color-stop($color-stop, $mid-color), to($end-color));\n  background-image: -webkit-linear-gradient(left, $start-color, $mid-color $color-stop, $end-color);\n  background-image: -moz-linear-gradient(left, $start-color, $mid-color $color-stop, $end-color);\n  background-image: linear-gradient(to right, $start-color, $mid-color $color-stop, $end-color);\n  background-repeat: no-repeat;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#{ie-hex-str($start-color)}', endColorstr='#{ie-hex-str($end-color)}', GradientType=1); // IE9 and down, gets no color-stop at all for proper fallback\n}\n@mixin gradient-vertical-three-colors($start-color: #00b3ee, $mid-color: #7a43b6, $color-stop: 50%, $end-color: #c3325f) {\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from($start-color), color-stop($color-stop, $mid-color), to($end-color));\n  background-image: -webkit-linear-gradient($start-color, $mid-color $color-stop, $end-color);\n  background-image: -moz-linear-gradient(top, $start-color, $mid-color $color-stop, $end-color);\n  background-image: linear-gradient($start-color, $mid-color $color-stop, $end-color);\n  background-repeat: no-repeat;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#{ie-hex-str($start-color)}', endColorstr='#{ie-hex-str($end-color)}', GradientType=0); // IE9 and down, gets no color-stop at all for proper fallback\n}\n@mixin gradient-radial($inner-color: #555, $outer-color: #333) {\n  background-image: -webkit-gradient(radial, center center, 0, center center, 460, from($inner-color), to($outer-color));\n  background-image: -webkit-radial-gradient(circle, $inner-color, $outer-color);\n  background-image: -moz-radial-gradient(circle, $inner-color, $outer-color);\n  background-image: radial-gradient(circle, $inner-color, $outer-color);\n  background-repeat: no-repeat;\n}\n@mixin gradient-striped($color: #555, $angle: 45deg) {\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(.25, rgba(255,255,255,.15)), color-stop(.25, transparent), color-stop(.5, transparent), color-stop(.5, rgba(255,255,255,.15)), color-stop(.75, rgba(255,255,255,.15)), color-stop(.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient($angle, 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: -moz-linear-gradient($angle, 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($angle, 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\n// Reset filters for IE\n//\n// When you need to remove a gradient background, do not forget to use this to reset\n// the IE filter for IE9 and below.\n@mixin reset-filter() {\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n}\n\n\n\n// Retina images\n//\n// Short retina mixin for setting background-image and -size\n\n@mixin img-retina($file-1x, $file-2x, $width-1x, $height-1x) {\n  background-image: url(\"#{$file-1x}\");\n\n  @media\n  only screen and (-webkit-min-device-pixel-ratio: 2),\n  only screen and (   min--moz-device-pixel-ratio: 2),\n  only screen and (     -o-min-device-pixel-ratio: 2/1),\n  only screen and (        min-device-pixel-ratio: 2),\n  only screen and (                min-resolution: 192dpi),\n  only screen and (                min-resolution: 2dppx) {\n    background-image: url(\"#{$file-2x}\");\n    background-size: $width-1x $height-1x;\n  }\n}\n\n\n// Responsive image\n//\n// Keep images from scaling beyond the width of their parents.\n\n@mixin img-responsive($display: block) {\n  display: $display;\n  max-width: 100%; // Part 1: Set a maximum relative to the parent\n  height: auto; // Part 2: Scale the height according to the width, otherwise you get stretching\n}\n\n\n// COMPONENT MIXINS\n// --------------------------------------------------\n\n// Horizontal dividers\n// -------------------------\n// Dividers (basically an hr) within dropdowns and nav lists\n@mixin nav-divider($color: #e5e5e5) {\n  height: 1px;\n  margin: (($line-height-computed / 2) - 1) 0;\n  overflow: hidden;\n  background-color: $color;\n}\n\n// Panels\n// -------------------------\n@mixin panel-variant($border, $heading-text-color, $heading-bg-color, $heading-border) {\n  border-color: $border;\n  & > .panel-heading {\n    color: $heading-text-color;\n    background-color: $heading-bg-color;\n    border-color: $heading-border;\n    + .panel-collapse .panel-body {\n      border-top-color: $border;\n    }\n  }\n  & > .panel-footer {\n    + .panel-collapse .panel-body {\n      border-bottom-color: $border;\n    }\n  }\n}\n\n// Alerts\n// -------------------------\n@mixin alert-variant($background, $border, $text-color) {\n  background-color: $background;\n  border-color: $border;\n  color: $text-color;\n  hr {\n    border-top-color: darken($border, 5%);\n  }\n  .alert-link {\n    color: darken($text-color, 10%);\n  }\n}\n\n// Tables\n// -------------------------\n@mixin table-row-variant($state, $background, $border) {\n  // Exact selectors below required to override `.table-striped` and prevent\n  // inheritance to nested tables.\n  .table > thead > tr,\n  .table > tbody > tr,\n  .table > tfoot > tr {\n    > td.#{$state},\n    > th.#{$state},\n    &.#{$state} > td,\n    &.#{$state} > th {\n      background-color: $background;\n      border-color: $border;\n    }\n  }\n\n  // Hover states for `.table-hover`\n  // Note: this is not available for cells or rows within `thead` or `tfoot`.\n  .table-hover > tbody > tr {\n    > td.#{$state}:hover,\n    > th.#{$state}:hover,\n    &.#{$state}:hover > td {\n      background-color: darken($background, 5%);\n      border-color: darken($border, 5%);\n    }\n  }\n}\n\n// Button variants\n// -------------------------\n// Easily pump out default styles, as well as :hover, :focus, :active,\n// and disabled options for all buttons\n@mixin button-variant($color, $background, $border) {\n  color: $color;\n  background-color: $background;\n  border-color: $border;\n\n  &:hover,\n  &:focus,\n  &:active,\n  &.active {\n    color: $color;\n    background-color: darken($background, 8%);\n        border-color: darken($border, 12%);\n  }\n  .open & { &.dropdown-toggle {\n    color: $color;\n    background-color: darken($background, 8%);\n        border-color: darken($border, 12%);\n  } }\n  &:active,\n  &.active {\n    background-image: none;\n  }\n  .open & { &.dropdown-toggle {\n    background-image: none;\n  } }\n  &.disabled,\n  &[disabled],\n  fieldset[disabled] & {\n    &,\n    &:hover,\n    &:focus,\n    &:active,\n    &.active {\n      background-color: $background;\n          border-color: $border\n    }\n  }\n}\n\n// Button sizes\n// -------------------------\n@mixin button-size($padding-vertical, $padding-horizontal, $font-size, $line-height, $border-radius) {\n  padding: $padding-vertical $padding-horizontal;\n  font-size: $font-size;\n  line-height: $line-height;\n  border-radius: $border-radius;\n}\n\n// Pagination\n// -------------------------\n@mixin pagination-size($padding-vertical, $padding-horizontal, $font-size, $border-radius) {\n  > li {\n    > a,\n    > span {\n      padding: $padding-vertical $padding-horizontal;\n      font-size: $font-size;\n    }\n    &:first-child {\n      > a,\n      > span {\n        @include border-left-radius($border-radius);\n      }\n    }\n    &:last-child {\n      > a,\n      > span {\n        @include border-right-radius($border-radius);\n      }\n    }\n  }\n}\n\n// Labels\n// -------------------------\n@mixin label-variant($color) {\n  background-color: $color;\n  &[href] {\n    &:hover,\n    &:focus {\n      background-color: darken($color, 10%);\n    }\n  }\n}\n\n// Navbar vertical align\n// -------------------------\n// Vertically center elements in the navbar.\n// Example: an element has a height of 30px, so write out `.navbar-vertical-align(30px);` to calculate the appropriate top margin.\n@mixin navbar-vertical-align($element-height) {\n  margin-top: (($navbar-height - $element-height) / 2);\n  margin-bottom: (($navbar-height - $element-height) / 2);\n}\n\n// Progress bars\n// -------------------------\n@mixin progress-bar-variant($color) {\n  background-color: $color;\n  .progress-striped & {\n    @include gradient-striped($color);\n  }\n}\n\n// Responsive utilities\n// -------------------------\n// More easily include all the states for responsive-utilities.less.\n// $parent hack because sass doesn't support tr& (without space)\n@mixin responsive-visibility($parent) {\n  #{$parent} { display: block !important; }\n  tr#{$parent} { display: table-row !important; }\n  th#{$parent},\n  td#{$parent} { display: table-cell !important; }\n}\n\n@mixin responsive-invisibility($parent) {\n  #{$parent} { display: none !important; }\n  tr#{$parent} { display: none !important; }\n  th#{$parent},\n  td#{$parent} { display: none !important; }\n}\n\n// Grid System\n// -----------\n\n// Centered container element\n@mixin container-fixed() {\n  margin-right: auto;\n  margin-left: auto;\n  padding-left:  ($grid-gutter-width / 2);\n  padding-right: ($grid-gutter-width / 2);\n  @include clearfix();\n}\n\n// Creates a wrapper for a series of columns\n@mixin make-row($gutter: $grid-gutter-width) {\n  margin-left:  ($gutter / -2);\n  margin-right: ($gutter / -2);\n  @include clearfix();\n}\n\n// Generate the extra small columns\n@mixin make-xs-column($columns, $gutter: $grid-gutter-width) {\n  position: relative;\n  float: left;\n  width: percentage(($columns / $grid-columns));\n  // Prevent columns from collapsing when empty\n  min-height: 1px;\n  // Inner gutter via padding\n  padding-left:  ($gutter / 2);\n  padding-right: ($gutter / 2);\n}\n\n// Generate the small columns\n@mixin make-sm-column($columns, $gutter: $grid-gutter-width) {\n  position: relative;\n  // Prevent columns from collapsing when empty\n  min-height: 1px;\n  // Inner gutter via padding\n  padding-left:  ($gutter / 2);\n  padding-right: ($gutter / 2);\n\n  // Calculate width based on number of columns available\n  @media (min-width: $screen-sm) {\n    float: left;\n    width: percentage(($columns / $grid-columns));\n  }\n}\n\n// Generate the small column offsets\n@mixin make-sm-column-offset($columns) {\n  @media (min-width: $screen-sm) {\n    margin-left: percentage(($columns / $grid-columns));\n  }\n}\n@mixin make-sm-column-push($columns) {\n  @media (min-width: $screen-sm) {\n    left: percentage(($columns / $grid-columns));\n  }\n}\n@mixin make-sm-column-pull($columns) {\n  @media (min-width: $screen-sm) {\n    right: percentage(($columns / $grid-columns));\n  }\n}\n\n// Generate the medium columns\n@mixin make-md-column($columns, $gutter: $grid-gutter-width) {\n  position: relative;\n  // Prevent columns from collapsing when empty\n  min-height: 1px;\n  // Inner gutter via padding\n  padding-left:  ($gutter / 2);\n  padding-right: ($gutter / 2);\n\n  // Calculate width based on number of columns available\n  @media (min-width: $screen-md) {\n    float: left;\n    width: percentage(($columns / $grid-columns));\n  }\n}\n\n// Generate the large column offsets\n@mixin make-md-column-offset($columns) {\n  @media (min-width: $screen-md) {\n    margin-left: percentage(($columns / $grid-columns));\n  }\n}\n@mixin make-md-column-push($columns) {\n  @media (min-width: $screen-md) {\n    left: percentage(($columns / $grid-columns));\n  }\n}\n@mixin make-md-column-pull($columns) {\n  @media (min-width: $screen-md) {\n    right: percentage(($columns / $grid-columns));\n  }\n}\n\n// Generate the large columns\n@mixin make-lg-column($columns, $gutter: $grid-gutter-width) {\n  position: relative;\n  // Prevent columns from collapsing when empty\n  min-height: 1px;\n  // Inner gutter via padding\n  padding-left:  ($gutter / 2);\n  padding-right: ($gutter / 2);\n\n  // Calculate width based on number of columns available\n  @media (min-width: $screen-lg) {\n    float: left;\n    width: percentage(($columns / $grid-columns));\n  }\n}\n\n// Generate the large column offsets\n@mixin make-lg-column-offset($columns) {\n  @media (min-width: $screen-lg) {\n    margin-left: percentage(($columns / $grid-columns));\n  }\n}\n@mixin make-lg-column-push($columns) {\n  @media (min-width: $screen-lg) {\n    left: percentage(($columns / $grid-columns));\n  }\n}\n@mixin make-lg-column-pull($columns) {\n  @media (min-width: $screen-lg) {\n    right: percentage(($columns / $grid-columns));\n  }\n}\n\n\n// Form validation states\n//\n// Used in forms.less to generate the form validation CSS for warnings, errors,\n// and successes.\n\n@mixin form-control-validation($text-color: #555, $border-color: #ccc, $background-color: #f5f5f5) {\n  // Color the label and help text\n  .help-block,\n  .control-label {\n    color: $text-color;\n  }\n  // Set the border and box shadow on specific inputs to match\n  .form-control {\n    border-color: $border-color;\n    @include box-shadow(inset 0 1px 1px rgba(0,0,0,.075)); // Redeclare so transitions work\n    &:focus {\n      border-color: darken($border-color, 10%);\n      $shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 6px lighten($border-color, 20%);\n      @include box-shadow($shadow);\n    }\n  }\n  // Set validation states also for addons\n  .input-group-addon {\n    color: $text-color;\n    border-color: $border-color;\n    background-color: $background-color;\n  }\n}\n\n// Form control focus state\n//\n// Generate a customized focus state and for any input with the specified color,\n// which defaults to the `$input-focus-border` variable.\n//\n// We highly encourage you to not customize the default value, but instead use\n// this to tweak colors on an as-needed basis. This aesthetic change is based on\n// WebKit's default styles, but applicable to a wider range of browsers. Its\n// usability and accessibility should be taken into account with any change.\n//\n// Example usage: change the default blue border and shadow to white for better\n// contrast against a dark gray background.\n\n@mixin form-control-focus($color: $input-border-focus) {\n  $color-rgba: rgba(red($color), green($color), blue($color), .6);\n  &:focus {\n    border-color: $color;\n    outline: 0;\n    @include box-shadow(inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px $color-rgba);\n  }\n}\n\n// Form control sizing\n//\n// Relative text size, padding, and border-radii changes for form controls. For\n// horizontal sizing, wrap controls in the predefined grid classes. `<select>`\n// element gets special love because it's special, and that's a fact!\n\n@mixin input-size($parent, $input-height, $padding-vertical, $padding-horizontal, $font-size, $line-height, $border-radius) {\n  #{$parent} { height: $input-height;\n  padding: $padding-vertical $padding-horizontal;\n  font-size: $font-size;\n  line-height: $line-height;\n  border-radius: $border-radius; }\n  select#{$parent} {\n    height: $input-height;\n    line-height: $input-height;\n  }\n\n  textarea#{$parent} {\n    height: auto;\n  }\n}\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/sass-bootstrap/lib/_modals.scss",
    "content": "//\n// Modals\n// --------------------------------------------------\n\n// .modal-open      - body class for killing the scroll\n// .modal           - container to scroll within\n// .modal-dialog    - positioning shell for the actual modal\n// .modal-content   - actual modal w/ bg and corners and shit\n\n// Kill the scroll on the body\n.modal-open {\n  overflow: hidden;\n\n\n  // Account for hiding of scrollbar\n  \n  .navbar-fixed-top,\n  .navbar-fixed-bottom {\n    margin-right: 15px\n  }\n}\n\nbody.modal-open {\n  margin-right: 15px\n}\n\n// Container that the modal scrolls within\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: $zindex-modal-background;\n\n  // When fading in the modal, animate it to slide down\n  &.fade .modal-dialog {\n    @include translate(0, -25%);\n    @include transition-transform(0.3s ease-out);\n  }\n  &.in .modal-dialog { @include translate(0, 0)}\n}\n\n// Shell div to position the modal with bottom padding\n.modal-dialog {\n  margin-left: auto;\n  margin-right: auto;\n  width: auto;\n  padding: 10px;\n  z-index: ($zindex-modal-background + 10);\n}\n\n// Actual modal\n.modal-content {\n  position: relative;\n  background-color: $modal-content-bg;\n  border: 1px solid $modal-content-fallback-border-color; //old browsers fallback (ie8 etc)\n  border: 1px solid $modal-content-border-color;\n  border-radius: $border-radius-large;\n  @include box-shadow(0 3px 9px rgba(0,0,0,.5));\n  background-clip: padding-box;\n  // Remove focus outline from opened modal\n  outline: none;\n}\n\n// Modal background\n.modal-backdrop {\n  position: fixed;\n  top: 0;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  z-index: ($zindex-modal-background - 10);\n  background-color: $modal-backdrop-bg;\n  // Fade for backdrop\n  &.fade { @include opacity(0); }\n  &.in { @include opacity(.5); }\n}\n\n// Modal header\n// Top section of the modal w/ title and dismiss\n.modal-header {\n  padding: $modal-title-padding;\n  border-bottom: 1px solid $modal-header-border-color;\n  min-height: ($modal-title-padding + $modal-title-line-height);\n}\n// Close icon\n.modal-header .close {\n  margin-top: -2px;\n}\n\n// Title text within header\n.modal-title {\n  margin: 0;\n  line-height: $modal-title-line-height;\n}\n\n// Modal body\n// Where all modal content resides (sibling of .modal-header and .modal-footer)\n.modal-body {\n  position: relative;\n  padding: $modal-inner-padding;\n}\n\n// Footer (for actions)\n.modal-footer {\n  margin-top: 15px;\n  padding: ($modal-inner-padding - 1) $modal-inner-padding $modal-inner-padding;\n  text-align: right; // right align buttons\n  border-top: 1px solid $modal-footer-border-color;\n  @include clearfix(); // clear it in case folks use .pull-* classes on buttons\n\n  // Properly space out buttons\n  .btn + .btn {\n    margin-left: 5px;\n    margin-bottom: 0; // account for input[type=\"submit\"] which gets the bottom margin like all other inputs\n  }\n  // but override that for button groups\n  .btn-group .btn + .btn {\n    margin-left: -1px;\n  }\n  // and override it for block buttons as well\n  .btn-block + .btn-block {\n    margin-left: 0;\n  }\n}\n\n// Scale up the modal\n@media screen and (min-width: $screen-tablet) {\n\n  .modal-dialog {\n    left: 50%;\n    right: auto;\n    width: 600px;\n    padding-top: 30px;\n    padding-bottom: 30px;\n  }\n  .modal-content {\n    @include box-shadow(0 5px 15px rgba(0,0,0,.5));\n  }\n\n}\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/sass-bootstrap/lib/_navbar.scss",
    "content": "//\n// Navbars\n// --------------------------------------------------\n\n\n// Wrapper and base class\n//\n// Provide a static navbar from which we expand to create full-width, fixed, and\n// other navbar variations.\n\n.navbar {\n  position: relative;\n  z-index: $zindex-navbar;\n  min-height: $navbar-height; // Ensure a navbar always shows (e.g., without a .navbar-brand in collapsed mode)\n  margin-bottom: $navbar-margin-bottom;\n  border: 1px solid transparent;\n\n  // Prevent floats from breaking the navbar\n  @include clearfix();\n\n  @media (min-width: $grid-float-breakpoint) {\n    border-radius: $navbar-border-radius;\n  }\n}\n\n\n// Navbar heading\n//\n// Groups `.navbar-brand` and `.navbar-toggle` into a single component for easy\n// styling of responsive aspects.\n\n.navbar-header {\n  @include clearfix();\n\n  @media (min-width: $grid-float-breakpoint) {\n    float: left;\n  }\n}\n\n\n// Navbar collapse (body)\n//\n// Group your navbar content into this for easy collapsing and expanding across\n// various device sizes. By default, this content is collapsed when <768px, but\n// will expand past that for a horizontal display.\n//\n// To start (on mobile devices) the navbar links, forms, and buttons are stacked\n// vertically and include a `max-height` to overflow in case you have too much\n// content for the user's viewport.\n\n.navbar-collapse {\n  max-height: 340px;\n  overflow-x: visible;\n  padding-right: $navbar-padding-horizontal;\n  padding-left:  $navbar-padding-horizontal;\n  border-top: 1px solid transparent;\n  box-shadow: inset 0 1px 0 rgba(255,255,255,.1);\n  @include clearfix();\n  -webkit-overflow-scrolling: touch;\n\n  &.in {\n    overflow-y: auto;\n  }\n\n  @media (min-width: $grid-float-breakpoint) {\n    width: auto;\n    border-top: 0;\n    box-shadow: none;\n\n    &.collapse {\n      display: block !important;\n      height: auto !important;\n      padding-bottom: 0; // Override default setting\n      overflow: visible !important;\n    }\n\n    &.in {\n      overflow-y: visible;\n    }\n\n    // Account for first and last children spacing\n    .navbar-nav.navbar-left:first-child {\n      margin-left: -$navbar-padding-horizontal;\n    }\n    .navbar-nav.navbar-right:last-child {\n      margin-right: -$navbar-padding-horizontal;\n    }\n    .navbar-text:last-child {\n      margin-right: 0;\n    }\n  }\n}\n\n\n// Both navbar header and collapse\n//\n// When a container is present, change the behavior of the header and collapse.\n\n.container > .navbar-header,\n.container > .navbar-collapse {\n  margin-right: -$navbar-padding-horizontal;\n  margin-left:  -$navbar-padding-horizontal;\n\n  @media (min-width: $grid-float-breakpoint) {\n    margin-right: 0;\n    margin-left:  0;\n  }\n}\n\n\n//\n// Navbar alignment options\n//\n// Display the navbar across the entirity of the page or fixed it to the top or\n// bottom of the page.\n\n// Static top (unfixed, but 100% wide) navbar\n.navbar-static-top {\n  border-width: 0 0 1px;\n  @media (min-width: $grid-float-breakpoint) {\n    border-radius: 0;\n  }\n}\n\n// Fix the top/bottom navbars when screen real estate supports it\n.navbar-fixed-top,\n.navbar-fixed-bottom {\n  position: fixed;\n  right: 0;\n  left: 0;\n  border-width: 0 0 1px;\n\n  // Undo the rounded corners\n  @media (min-width: $grid-float-breakpoint) {\n    border-radius: 0;\n  }\n}\n.navbar-fixed-top {\n  z-index: $zindex-navbar-fixed;\n  top: 0;\n}\n.navbar-fixed-bottom {\n  bottom: 0;\n  margin-bottom: 0; // override .navbar defaults\n}\n\n\n// Brand/project name\n\n.navbar-brand {\n  float: left;\n  padding: $navbar-padding-vertical $navbar-padding-horizontal;\n  font-size: $font-size-large;\n  line-height: $line-height-computed;\n  &:hover,\n  &:focus {\n    text-decoration: none;\n  }\n\n  @media (min-width: $grid-float-breakpoint) {\n    .navbar > .container & {\n      margin-left: -$navbar-padding-horizontal;\n    }\n  }\n}\n\n\n// Navbar toggle\n//\n// Custom button for toggling the `.navbar-collapse`, powered by the collapse\n// JavaScript plugin.\n\n.navbar-toggle {\n  position: relative;\n  float: right;\n  margin-right: $navbar-padding-horizontal;\n  padding: 9px 10px;\n  @include navbar-vertical-align(34px);\n  background-color: transparent;\n  border: 1px solid transparent;\n  border-radius: $border-radius-base;\n\n  // Bars\n  .icon-bar {\n    display: block;\n    width: 22px;\n    height: 2px;\n    border-radius: 1px;\n  }\n  .icon-bar + .icon-bar {\n    margin-top: 4px;\n  }\n\n  @media (min-width: $grid-float-breakpoint) {\n    display: none;\n  }\n}\n\n\n// Navbar nav links\n//\n// Builds on top of the `.nav` components with it's own modifier class to make\n// the nav the full height of the horizontal nav (above 768px).\n\n.navbar-nav {\n  margin: ($navbar-padding-vertical / 2) (-$navbar-padding-horizontal);\n\n  > li > a {\n    padding-top:    10px;\n    padding-bottom: 10px;\n    line-height: $line-height-computed;\n  }\n\n  @media (max-width: $screen-xs-max) {\n    // Dropdowns get custom display when collapsed\n    .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      > li > a,\n      .dropdown-header {\n        padding: 5px 15px 5px 25px;\n      }\n      > li > a {\n        line-height: $line-height-computed;\n        &:hover,\n        &:focus {\n          background-image: none;\n        }\n      }\n    }\n  }\n\n  // Uncollapse the nav\n  @media (min-width: $grid-float-breakpoint) {\n    float: left;\n    margin: 0;\n\n    > li {\n      float: left;\n      > a {\n        padding-top: (($navbar-height - $line-height-computed) / 2);\n        padding-bottom: (($navbar-height - $line-height-computed) / 2);\n      }\n    }\n  }\n\n}\n\n\n// Component alignment\n//\n// Repurpose the pull utilities as their own navbar utilities to avoid specifity\n// issues with parents and chaining. Only do this when the navbar is uncollapsed\n// though so that navbar contents properly stack and align in mobile.\n\n@media (min-width: $grid-float-breakpoint) {\n  .navbar-left {\n    float: left !important;\n  }\n  .navbar-right {\n    float: right !important;\n  }\n}\n\n\n// Navbar form\n//\n// Extension of the `.form-inline` with some extra flavor for optimum display in\n// our navbars.\n\n.navbar-form {\n  margin-left: -$navbar-padding-horizontal;\n  margin-right: -$navbar-padding-horizontal;\n  padding: 10px $navbar-padding-horizontal;\n  border-top: 1px solid transparent;\n  border-bottom: 1px solid transparent;\n  $shadow: inset 0 1px 0 rgba(255,255,255,.1), 0 1px 0 rgba(255,255,255,.1);\n  @include box-shadow($shadow);\n\n  // Mixin behavior for optimum display\n  @extend .form-inline;\n\n  .form-group {\n    @media (max-width: $screen-xs-max) {\n      margin-bottom: 5px;\n    }\n  }\n\n  // Vertically center in expanded, horizontal navbar\n  @include navbar-vertical-align($input-height-base);\n\n  // Undo 100% width for pull classes\n  @media (min-width: $grid-float-breakpoint) {\n    width: auto;\n    border: 0;\n    margin-left: 0;\n    margin-right: 0;\n    padding-top: 0;\n    padding-bottom: 0;\n    @include box-shadow(none);\n  }\n}\n\n\n// Dropdown menus\n\n// Menu position and menu carets\n.navbar-nav > li > .dropdown-menu {\n  margin-top: 0;\n  @include border-top-radius(0);\n}\n// Menu position and menu caret support for dropups via extra dropup class\n.navbar-fixed-bottom .navbar-nav > li > .dropdown-menu {\n  @include border-bottom-radius(0);\n}\n\n// Right aligned menus need alt position\n.navbar-nav.pull-right > li > .dropdown-menu,\n.navbar-nav > li > .dropdown-menu.pull-right {\n  left: auto;\n  right: 0;\n}\n\n\n// Buttons in navbars\n//\n// Vertically center a button within a navbar (when *not* in a form).\n\n.navbar-btn {\n  @include navbar-vertical-align($input-height-base);\n}\n\n\n// Text in navbars\n//\n// Add a class to make any element properly align itself vertically within the navbars.\n\n.navbar-text {\n  float: left;\n  @include navbar-vertical-align($line-height-computed);\n\n  @media (min-width: $grid-float-breakpoint) {\n    margin-left: $navbar-padding-horizontal;\n    margin-right: $navbar-padding-horizontal;\n  }\n}\n\n// Alternate navbars\n// --------------------------------------------------\n\n// Default navbar\n.navbar-default {\n  background-color: $navbar-default-bg;\n  border-color: $navbar-default-border;\n\n  .navbar-brand {\n    color: $navbar-default-brand-color;\n    &:hover,\n    &:focus {\n      color: $navbar-default-brand-hover-color;\n      background-color: $navbar-default-brand-hover-bg;\n    }\n  }\n\n  .navbar-text {\n    color: $navbar-default-color;\n  }\n\n  .navbar-nav {\n    > li > a {\n      color: $navbar-default-link-color;\n\n      &:hover,\n      &:focus {\n        color: $navbar-default-link-hover-color;\n        background-color: $navbar-default-link-hover-bg;\n      }\n    }\n    > .active > a {\n      &,\n      &:hover,\n      &:focus {\n        color: $navbar-default-link-active-color;\n        background-color: $navbar-default-link-active-bg;\n      }\n    }\n    > .disabled > a {\n      &,\n      &:hover,\n      &:focus {\n        color: $navbar-default-link-disabled-color;\n        background-color: $navbar-default-link-disabled-bg;\n      }\n    }\n  }\n\n  .navbar-toggle {\n    border-color: $navbar-default-toggle-border-color;\n    &:hover,\n    &:focus {\n      background-color: $navbar-default-toggle-hover-bg;\n    }\n    .icon-bar {\n      background-color: $navbar-default-toggle-icon-bar-bg;\n    }\n  }\n\n  .navbar-collapse,\n  .navbar-form {\n    border-color: darken($navbar-default-bg, 7%);\n  }\n\n  // Dropdown menu items and carets\n  .navbar-nav {\n    // Caret should match text color on hover\n    > .dropdown > a:hover .caret,\n    > .dropdown > a:focus .caret {\n      border-top-color: $navbar-default-link-hover-color;\n      border-bottom-color: $navbar-default-link-hover-color;\n    }\n\n    // Remove background color from open dropdown\n    > .open > a {\n      &,\n      &:hover,\n      &:focus {\n        background-color: $navbar-default-link-active-bg;\n        color: $navbar-default-link-active-color;\n        .caret {\n          border-top-color: $navbar-default-link-active-color;\n          border-bottom-color: $navbar-default-link-active-color;\n        }\n      }\n    }\n    > .dropdown > a .caret {\n      border-top-color: $navbar-default-link-color;\n      border-bottom-color: $navbar-default-link-color;\n    }\n\n\n    @media (max-width: $screen-xs-max) {\n      // Dropdowns get custom display when collapsed\n      .open .dropdown-menu {\n        > li > a {\n          color: $navbar-default-link-color;\n          &:hover,\n          &:focus {\n            color: $navbar-default-link-hover-color;\n            background-color: $navbar-default-link-hover-bg;\n          }\n        }\n        > .active > a {\n          &,\n          &:hover,\n          &:focus {\n            color: $navbar-default-link-active-color;\n            background-color: $navbar-default-link-active-bg;\n          }\n        }\n        > .disabled > a {\n          &,\n          &:hover,\n          &:focus {\n            color: $navbar-default-link-disabled-color;\n            background-color: $navbar-default-link-disabled-bg;\n          }\n        }\n      }\n    }\n  }\n\n\n  // Links in navbars\n  //\n  // Add a class to ensure links outside the navbar nav are colored correctly.\n\n  .navbar-link {\n    color: $navbar-default-link-color;\n    &:hover {\n      color: $navbar-default-link-hover-color;\n    }\n  }\n\n}\n\n// Inverse navbar\n\n.navbar-inverse {\n  background-color: $navbar-inverse-bg;\n  border-color: $navbar-inverse-border;\n\n  .navbar-brand {\n    color: $navbar-inverse-brand-color;\n    &:hover,\n    &:focus {\n      color: $navbar-inverse-brand-hover-color;\n      background-color: $navbar-inverse-brand-hover-bg;\n    }\n  }\n\n  .navbar-text {\n    color: $navbar-inverse-color;\n  }\n\n  .navbar-nav {\n    > li > a {\n      color: $navbar-inverse-link-color;\n\n      &:hover,\n      &:focus {\n        color: $navbar-inverse-link-hover-color;\n        background-color: $navbar-inverse-link-hover-bg;\n      }\n    }\n    > .active > a {\n      &,\n      &:hover,\n      &:focus {\n        color: $navbar-inverse-link-active-color;\n        background-color: $navbar-inverse-link-active-bg;\n      }\n    }\n    > .disabled > a {\n      &,\n      &:hover,\n      &:focus {\n        color: $navbar-inverse-link-disabled-color;\n        background-color: $navbar-inverse-link-disabled-bg;\n      }\n    }\n  }\n\n  // Darken the responsive nav toggle\n  .navbar-toggle {\n    border-color: $navbar-inverse-toggle-border-color;\n    &:hover,\n    &:focus {\n      background-color: $navbar-inverse-toggle-hover-bg;\n    }\n    .icon-bar {\n      background-color: $navbar-inverse-toggle-icon-bar-bg;\n    }\n  }\n\n  .navbar-collapse,\n  .navbar-form {\n    border-color: darken($navbar-inverse-bg, 7%);\n  }\n\n  // Dropdowns\n  .navbar-nav {\n    > .open > a {\n      &,\n      &:hover,\n      &:focus {\n        background-color: $navbar-inverse-link-active-bg;\n        color: $navbar-inverse-link-active-color;\n      }\n    }\n    > .dropdown > a:hover .caret {\n      border-top-color: $navbar-inverse-link-hover-color;\n      border-bottom-color: $navbar-inverse-link-hover-color;\n    }\n    > .dropdown > a .caret {\n      border-top-color: $navbar-inverse-link-color;\n      border-bottom-color: $navbar-inverse-link-color;\n    }\n    > .open > a {\n      &,\n      &:hover,\n      &:focus {\n        .caret {\n          border-top-color: $navbar-inverse-link-active-color;\n          border-bottom-color: $navbar-inverse-link-active-color;\n        }\n      }\n    }\n\n    @media (max-width: $screen-xs-max) {\n      // Dropdowns get custom display\n      .open .dropdown-menu {\n        > .dropdown-header {\n          border-color: $navbar-inverse-border;\n        }\n        > li > a {\n          color: $navbar-inverse-link-color;\n          &:hover,\n          &:focus {\n            color: $navbar-inverse-link-hover-color;\n            background-color: $navbar-inverse-link-hover-bg;\n          }\n        }\n        > .active > a {\n          &,\n          &:hover,\n          &:focus {\n            color: $navbar-inverse-link-active-color;\n            background-color: $navbar-inverse-link-active-bg;\n          }\n        }\n        > .disabled > a {\n          &,\n          &:hover,\n          &:focus {\n            color: $navbar-inverse-link-disabled-color;\n            background-color: $navbar-inverse-link-disabled-bg;\n          }\n        }\n      }\n    }\n  }\n\n  .navbar-link {\n    color: $navbar-inverse-link-color;\n    &:hover {\n      color: $navbar-inverse-link-hover-color;\n    }\n  }\n\n}\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/sass-bootstrap/lib/_navs.scss",
    "content": "//\n// Navs\n// --------------------------------------------------\n\n\n// Base class\n// --------------------------------------------------\n\n.nav {\n  margin-bottom: 0;\n  padding-left: 0; // Override default ul/ol\n  list-style: none;\n  @include clearfix();\n\n  > li {\n    position: relative;\n    display: block;\n\n    > a {\n      position: relative;\n      display: block;\n      padding: $nav-link-padding;\n      &:hover,\n      &:focus {\n        text-decoration: none;\n        background-color: $nav-link-hover-bg;\n      }\n    }\n\n    // Disabled state sets text to gray and nukes hover/tab effects\n    &.disabled > a {\n      color: $nav-disabled-link-color;\n\n      &:hover,\n      &:focus {\n        color: $nav-disabled-link-hover-color;\n        text-decoration: none;\n        background-color: transparent;\n        cursor: not-allowed;\n      }\n    }\n  }\n\n  // Open dropdowns\n  .open > a {\n    &,\n    &:hover,\n    &:focus {\n      background-color: $nav-link-hover-bg;\n      border-color: $link-color;\n    }\n  }\n\n  // Dividers (basically an hr) within the dropdown\n  .nav-divider {\n    @include nav-divider();\n  }\n\n  // Prevent IE8 from misplacing imgs\n  // See https://github.com/h5bp/html5-boilerplate/issues/984#issuecomment-3985989\n  > li > a > img {\n    max-width: none;\n  }\n}\n\n\n// Tabs\n// -------------------------\n\n// Give the tabs something to sit on\n.nav-tabs {\n  border-bottom: 1px solid $nav-tabs-border-color;\n  > li {\n    float: left;\n    // Make the list-items overlay the bottom border\n    margin-bottom: -1px;\n\n    // Actual tabs (as links)\n    > a {\n      margin-right: 2px;\n      line-height: $line-height-base;\n      border: 1px solid transparent;\n      border-radius: $border-radius-base $border-radius-base 0 0;\n      &:hover {\n        border-color: $nav-tabs-link-hover-border-color $nav-tabs-link-hover-border-color $nav-tabs-border-color;\n      }\n    }\n\n    // Active state, and it's :hover to override normal :hover\n    &.active > a {\n      &,\n      &:hover,\n      &:focus {\n        color: $nav-tabs-active-link-hover-color;\n        background-color: $nav-tabs-active-link-hover-bg;\n        border: 1px solid $nav-tabs-active-link-hover-border-color;\n        border-bottom-color: transparent;\n        cursor: default;\n      }\n    }\n  }\n  // pulling this in mainly for less shorthand\n  &.nav-justified {\n    @extend .nav-justified;\n    @extend .nav-tabs-justified;\n  }\n}\n\n\n// Pills\n// -------------------------\n.nav-pills {\n  > li {\n    float: left;\n\n    // Links rendered as pills\n    > a {\n      border-radius: 5px;\n    }\n    + li {\n      margin-left: 2px;\n    }\n\n    // Active state\n    &.active > a {\n      &,\n      &:hover,\n      &:focus {\n        color: $nav-pills-active-link-hover-color;\n        background-color: $nav-pills-active-link-hover-bg;\n      }\n    }\n  }\n}\n\n\n// Stacked pills\n.nav-stacked {\n  > li {\n    float: none;\n    + li {\n      margin-top: 2px;\n      margin-left: 0; // no need for this gap between nav items\n    }\n  }\n}\n\n\n// Nav variations\n// --------------------------------------------------\n\n// Justified nav links\n// -------------------------\n\n.nav-justified {\n  width: 100%;\n\n  > li {\n    float: none;\n     > a {\n      text-align: center;\n    }\n  }\n\n  @media (min-width: $screen-sm) {\n    > li {\n      display: table-cell;\n      width: 1%;\n    }\n  }\n}\n\n// Move borders to anchors instead of bottom of list\n.nav-tabs-justified {\n  border-bottom: 0;\n  > li > a {\n    border-bottom: 1px solid $nav-tabs-justified-link-border-color;\n\n    // Override margin from .nav-tabs\n    margin-right: 0;\n  }\n  > .active > a {\n    border-bottom-color: $nav-tabs-justified-active-link-border-color;\n  }\n}\n\n\n// Tabbable tabs\n// -------------------------\n\n// Clear any floats\n.tabbable {\n  @include clearfix();\n}\n\n// Show/hide tabbable areas\n.tab-content > .tab-pane,\n.pill-content > .pill-pane {\n  display: none;\n}\n.tab-content,\n.pill-content {\n  > .active {\n    display: block;\n  }\n}\n\n\n\n// Dropdowns\n// -------------------------\n\n// Make dropdown carets use link color in navs\n.nav .caret {\n  border-top-color: $link-color;\n  border-bottom-color: $link-color;\n}\n.nav a:hover .caret {\n  border-top-color: $link-hover-color;\n  border-bottom-color: $link-hover-color;\n}\n\n// Specific dropdowns\n.nav-tabs .dropdown-menu {\n  // make dropdown border overlap tab border\n  margin-top: -1px;\n  // Remove the top rounded corners here since there is a hard edge above the menu\n  @include border-top-radius(0);\n}\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/sass-bootstrap/lib/_normalize.scss",
    "content": "/*! normalize.css v2.1.0 | MIT License | git.io/normalize */\n\n// ==========================================================================\n// HTML5 display definitions\n// ==========================================================================\n\n//\n// Correct `block` display not defined in IE 8/9.\n//\n\narticle,\naside,\ndetails,\nfigcaption,\nfigure,\nfooter,\nheader,\nhgroup,\nmain,\nnav,\nsection,\nsummary {\n  display: block;\n}\n\n//\n// Correct `inline-block` display not defined in IE 8/9.\n//\n\naudio,\ncanvas,\nvideo {\n  display: inline-block;\n}\n\n//\n// Prevent modern browsers from displaying `audio` without controls.\n// Remove excess height in iOS 5 devices.\n//\n\naudio:not([controls]) {\n  display: none;\n  height: 0;\n}\n\n//\n// Address styling not present in IE 8/9.\n//\n\n[hidden] {\n  display: none;\n}\n\n// ==========================================================================\n// Base\n// ==========================================================================\n\n//\n// 1. Set default font family to sans-serif.\n// 2. Prevent iOS text size adjust after orientation change, without disabling\n//    user zoom.\n//\n\nhtml {\n  font-family: sans-serif; // 1\n  -webkit-text-size-adjust: 100%; // 2\n  -ms-text-size-adjust: 100%; // 2\n}\n\n//\n// Remove default margin.\n//\n\nbody {\n  margin: 0;\n}\n\n// ==========================================================================\n// Links\n// ==========================================================================\n\n//\n// Address `outline` inconsistency between Chrome and other browsers.\n//\n\na:focus {\n  outline: thin dotted;\n}\n\n//\n// Improve readability when focused and also mouse hovered in all browsers.\n//\n\na:active,\na:hover {\n  outline: 0;\n}\n\n// ==========================================================================\n// Typography\n// ==========================================================================\n\n//\n// Address variable `h1` font-size and margin within `section` and `article`\n// contexts in Firefox 4+, Safari 5, and Chrome.\n//\n\nh1 {\n  font-size: 2em;\n  margin: 0.67em 0;\n}\n\n//\n// Address styling not present in IE 8/9, Safari 5, and Chrome.\n//\n\nabbr[title] {\n  border-bottom: 1px dotted;\n}\n\n//\n// Address style set to `bolder` in Firefox 4+, Safari 5, and Chrome.\n//\n\nb,\nstrong {\n  font-weight: bold;\n}\n\n//\n// Address styling not present in Safari 5 and Chrome.\n//\n\ndfn {\n  font-style: italic;\n}\n\n//\n// Address differences between Firefox and other browsers.\n//\n\nhr {\n  -moz-box-sizing: content-box;\n  box-sizing: content-box;\n  height: 0;\n}\n\n//\n// Address styling not present in IE 8/9.\n//\n\nmark {\n  background: #ff0;\n  color: #000;\n}\n\n//\n// Correct font family set oddly in Safari 5 and Chrome.\n//\n\ncode,\nkbd,\npre,\nsamp {\n  font-family: monospace, serif;\n  font-size: 1em;\n}\n\n//\n// Improve readability of pre-formatted text in all browsers.\n//\n\npre {\n  white-space: pre-wrap;\n}\n\n//\n// Set consistent quote types.\n//\n\nq {\n  quotes: \"\\201C\" \"\\201D\" \"\\2018\" \"\\2019\";\n}\n\n//\n// Address inconsistent and variable font size in all browsers.\n//\n\nsmall {\n  font-size: 80%;\n}\n\n//\n// Prevent `sub` and `sup` affecting `line-height` in all browsers.\n//\n\nsub,\nsup {\n  font-size: 75%;\n  line-height: 0;\n  position: relative;\n  vertical-align: baseline;\n}\n\nsup {\n  top: -0.5em;\n}\n\nsub {\n  bottom: -0.25em;\n}\n\n// ==========================================================================\n// Embedded content\n// ==========================================================================\n\n//\n// Remove border when inside `a` element in IE 8/9.\n//\n\nimg {\n  border: 0;\n}\n\n//\n// Correct overflow displayed oddly in IE 9.\n//\n\nsvg:not(:root) {\n  overflow: hidden;\n}\n\n// ==========================================================================\n// Figures\n// ==========================================================================\n\n//\n// Address margin not present in IE 8/9 and Safari 5.\n//\n\nfigure {\n  margin: 0;\n}\n\n// ==========================================================================\n// Forms\n// ==========================================================================\n\n//\n// Define consistent border, margin, and padding.\n//\n\nfieldset {\n  border: 1px solid #c0c0c0;\n  margin: 0 2px;\n  padding: 0.35em 0.625em 0.75em;\n}\n\n//\n// 1. Correct `color` not being inherited in IE 8/9.\n// 2. Remove padding so people aren't caught out if they zero out fieldsets.\n//\n\nlegend {\n  border: 0; // 1\n  padding: 0; // 2\n}\n\n//\n// 1. Correct font family not being inherited in all browsers.\n// 2. Correct font size not being inherited in all browsers.\n// 3. Address margins set differently in Firefox 4+, Safari 5, and Chrome.\n//\n\nbutton,\ninput,\nselect,\ntextarea {\n  font-family: inherit; // 1\n  font-size: 100%; // 2\n  margin: 0; // 3\n}\n\n//\n// Address Firefox 4+ setting `line-height` on `input` using `!important` in\n// the UA stylesheet.\n//\n\nbutton,\ninput {\n  line-height: normal;\n}\n\n//\n// Address inconsistent `text-transform` inheritance for `button` and `select`.\n// All other form control elements do not inherit `text-transform` values.\n// Correct `button` style inheritance in Chrome, Safari 5+, and IE 8+.\n// Correct `select` style inheritance in Firefox 4+ and Opera.\n//\n\nbutton,\nselect {\n  text-transform: none;\n}\n\n//\n// 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio`\n//    and `video` controls.\n// 2. Correct inability to style clickable `input` types in iOS.\n// 3. Improve usability and consistency of cursor style between image-type\n//    `input` and others.\n//\n\nbutton,\nhtml input[type=\"button\"], // 1\ninput[type=\"reset\"],\ninput[type=\"submit\"] {\n  -webkit-appearance: button; // 2\n  cursor: pointer; // 3\n}\n\n//\n// Re-set default cursor for disabled elements.\n//\n\nbutton[disabled],\nhtml input[disabled] {\n  cursor: default;\n}\n\n//\n// 1. Address box sizing set to `content-box` in IE 8/9.\n// 2. Remove excess padding in IE 8/9.\n//\n\ninput[type=\"checkbox\"],\ninput[type=\"radio\"] {\n  box-sizing: border-box; // 1\n  padding: 0; // 2\n}\n\n//\n// 1. Address `appearance` set to `searchfield` in Safari 5 and Chrome.\n// 2. Address `box-sizing` set to `border-box` in Safari 5 and Chrome\n//    (include `-moz` to future-proof).\n//\n\ninput[type=\"search\"] {\n  -webkit-appearance: textfield; // 1\n  -moz-box-sizing: content-box;\n  -webkit-box-sizing: content-box; // 2\n  box-sizing: content-box;\n}\n\n//\n// Remove inner padding and search cancel button in Safari 5 and Chrome\n// on OS X.\n//\n\ninput[type=\"search\"]::-webkit-search-cancel-button,\ninput[type=\"search\"]::-webkit-search-decoration {\n  -webkit-appearance: none;\n}\n\n//\n// Remove inner padding and border in Firefox 4+.\n//\n\nbutton::-moz-focus-inner,\ninput::-moz-focus-inner {\n  border: 0;\n  padding: 0;\n}\n\n//\n// 1. Remove default vertical scrollbar in IE 8/9.\n// 2. Improve readability and alignment in all browsers.\n//\n\ntextarea {\n  overflow: auto; // 1\n  vertical-align: top; // 2\n}\n\n// ==========================================================================\n// Tables\n// ==========================================================================\n\n//\n// Remove most spacing between table cells.\n//\n\ntable {\n  border-collapse: collapse;\n  border-spacing: 0;\n}\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/sass-bootstrap/lib/_pager.scss",
    "content": "//\n// Pager pagination\n// --------------------------------------------------\n\n\n.pager {\n  padding-left: 0;\n  margin: $line-height-computed 0;\n  list-style: none;\n  text-align: center;\n  @include clearfix();\n  li {\n    display: inline;\n    > a,\n    > span {\n      display: inline-block;\n      padding: 5px 14px;\n      background-color: $pagination-bg;\n      border: 1px solid $pagination-border;\n      border-radius: $pager-border-radius;\n    }\n\n    > a:hover,\n    > a:focus {\n      text-decoration: none;\n      background-color: $pagination-hover-bg;\n    }\n  }\n\n  .next {\n    > a,\n    > span {\n      float: right;\n    }\n  }\n\n  .previous {\n    > a,\n    > span {\n      float: left;\n    }\n  }\n\n  .disabled {\n    > a,\n    > a:hover,\n    > a:focus,\n    > span {\n      color: $pager-disabled-color;\n      background-color: $pagination-bg;\n      cursor: not-allowed;\n    }\n  }\n\n}\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/sass-bootstrap/lib/_pagination.scss",
    "content": "//\n// Pagination (multiple pages)\n// --------------------------------------------------\n.pagination {\n  display: inline-block;\n  padding-left: 0;\n  margin: $line-height-computed 0;\n  border-radius: $border-radius-base;\n\n  > li {\n    display: inline; // Remove list-style and block-level defaults\n    > a,\n    > span {\n      position: relative;\n      float: left; // Collapse white-space\n      padding: $padding-base-vertical $padding-base-horizontal;\n      line-height: $line-height-base;\n      text-decoration: none;\n      background-color: $pagination-bg;\n      border: 1px solid $pagination-border;\n      margin-left: -1px;\n    }\n    &:first-child {\n      > a,\n      > span {\n        margin-left: 0;\n        @include border-left-radius($border-radius-base);\n      }\n    }\n    &:last-child {\n      > a,\n      > span {\n        @include border-right-radius($border-radius-base);\n      }\n    }\n  }\n\n  > li > a,\n  > li > span {\n    &:hover,\n    &:focus {\n      background-color: $pagination-hover-bg;\n    }\n  }\n\n  > .active > a,\n  > .active > span {\n    &,\n    &:hover,\n    &:focus {\n      z-index: 2;\n      color: $pagination-active-color;\n      background-color: $pagination-active-bg;\n      border-color: $pagination-active-bg;\n      cursor: default;\n    }\n  }\n\n  > .disabled {\n    > span,\n    > a,\n    > a:hover,\n    > a:focus {\n      color: $pagination-disabled-color;\n      background-color: $pagination-bg;\n      border-color: $pagination-border;\n      cursor: not-allowed;\n    }\n  }\n}\n\n// Sizing\n// --------------------------------------------------\n\n// Large\n.pagination-lg {\n  @include pagination-size($padding-large-vertical, $padding-large-horizontal, $font-size-large, $border-radius-large);\n}\n\n// Small\n.pagination-sm {\n  @include pagination-size($padding-small-vertical, $padding-small-horizontal, $font-size-small, $border-radius-small);\n}\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/sass-bootstrap/lib/_panels.scss",
    "content": "//\n// Panels\n// --------------------------------------------------\n\n\n// Base class\n.panel {\n  margin-bottom: $line-height-computed;\n  background-color: $panel-bg;\n  border: 1px solid transparent;\n  border-radius: $panel-border-radius;\n  @include box-shadow(0 1px 1px rgba(0,0,0,.05));\n}\n\n// Panel contents\n.panel-body {\n  padding: 15px;\n  @include clearfix();\n}\n\n\n// List groups in panels\n//\n// By default, space out list group content from panel headings to account for\n// any kind of custom content between the two.\n\n.panel {\n  > .list-group {\n    margin-bottom: 0;\n\n    .list-group-item {\n      border-width: 1px 0;\n\n      // Remove border radius for top one\n      &:first-child {\n        @include border-top-radius(0);\n      }\n      // But keep it for the last one\n      &:last-child {\n        border-bottom: 0;\n      }\n    }\n  }\n}\n// Collapse space between when there's no additional content.\n.panel-heading + .list-group {\n  .list-group-item:first-child {\n    border-top-width: 0;\n  }\n}\n\n\n// Tables in panels\n//\n// Place a non-bordered `.table` within a panel (not within a `.panel-body`) and\n// watch it go full width.\n\n.panel {\n  > .table {\n    margin-bottom: 0;\n  }\n  > .panel-body + .table {\n    border-top: 1px solid $table-border-color;\n  }\n}\n\n\n// Optional heading\n.panel-heading {\n  padding: 10px 15px;\n  border-bottom: 1px solid transparent;\n  @include border-top-radius($panel-border-radius - 1);\n}\n\n// Within heading, strip any `h*` tag of it's default margins for spacing.\n.panel-title {\n  margin-top: 0;\n  margin-bottom: 0;\n  font-size: ceil(($font-size-base * 1.125));\n  > a {\n    color: inherit;\n  }\n}\n\n// Optional footer (stays gray in every modifier class)\n.panel-footer {\n  padding: 10px 15px;\n  background-color: $panel-footer-bg;\n  border-top: 1px solid $panel-inner-border;\n  @include border-bottom-radius($panel-border-radius - 1);\n}\n\n\n// Collapsable panels (aka, accordion)\n//\n// Wrap a series of panels in `.panel-group` to turn them into an accordion with\n// the help of our collapse JavaScript plugin.\n\n.panel-group {\n  // Tighten up margin so it's only between panels\n  .panel {\n    margin-bottom: 0;\n    border-radius: $panel-border-radius;\n    overflow: hidden; // crop contents when collapsed\n    + .panel {\n      margin-top: 5px;\n    }\n  }\n\n  .panel-heading {\n    border-bottom: 0;\n    + .panel-collapse .panel-body {\n      border-top: 1px solid $panel-inner-border;\n    }\n  }\n  .panel-footer {\n    border-top: 0;\n    + .panel-collapse .panel-body {\n      border-bottom: 1px solid $panel-inner-border;\n    }\n  }\n\n  // New subcomponent for wrapping collapsable content for proper animations\n  .panel-collapse {\n\n  }\n}\n\n\n// Contextual variations\n.panel-default {\n  @include panel-variant($panel-default-border, $panel-default-text, $panel-default-heading-bg, $panel-default-border);\n}\n.panel-primary {\n  @include panel-variant($panel-primary-border, $panel-primary-text, $panel-primary-heading-bg, $panel-primary-border);\n}\n.panel-success {\n  @include panel-variant($panel-success-border, $panel-success-text, $panel-success-heading-bg, $panel-success-border);\n}\n.panel-warning {\n  @include panel-variant($panel-warning-border, $panel-warning-text, $panel-warning-heading-bg, $panel-warning-border);\n}\n.panel-danger {\n  @include panel-variant($panel-danger-border, $panel-danger-text, $panel-danger-heading-bg, $panel-danger-border);\n}\n.panel-info {\n  @include panel-variant($panel-info-border, $panel-info-text, $panel-info-heading-bg, $panel-info-border);\n}\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/sass-bootstrap/lib/_popovers.scss",
    "content": "//\n// Popovers\n// --------------------------------------------------\n\n\n.popover {\n  position: absolute;\n  top: 0;\n  left: 0;\n  z-index: $zindex-popover;\n  display: none;\n  max-width: $popover-max-width;\n  padding: 1px;\n  text-align: left; // Reset given new insertion method\n  background-color: $popover-bg;\n  background-clip: padding-box;\n  border: 1px solid $popover-fallback-border-color;\n  border: 1px solid $popover-border-color;\n  border-radius: $border-radius-large;\n  @include box-shadow(0 5px 10px rgba(0,0,0,.2));\n\n  // Overrides for proper insertion\n  white-space: normal;\n\n  // Offset the popover to account for the popover arrow\n  &.top     { margin-top: -10px; }\n  &.right   { margin-left: 10px; }\n  &.bottom  { margin-top: 10px; }\n  &.left    { margin-left: -10px; }\n}\n\n.popover-title {\n  margin: 0; // reset heading margin\n  padding: 8px 14px;\n  font-size: $font-size-base;\n  font-weight: normal;\n  line-height: 18px;\n  background-color: $popover-title-bg;\n  border-bottom: 1px solid darken($popover-title-bg, 5%);\n  border-radius: 5px 5px 0 0;\n}\n\n.popover-content {\n  padding: 9px 14px;\n}\n\n// Arrows\n//\n// .arrow is outer, .arrow:after is inner\n\n.popover .arrow {\n  &,\n  &:after {\n    position: absolute;\n    display: block;\n    width: 0;\n    height: 0;\n    border-color: transparent;\n    border-style: solid;\n  }\n}\n.popover .arrow {\n  border-width: $popover-arrow-outer-width;\n}\n.popover .arrow:after {\n  border-width: $popover-arrow-width;\n  content: \"\";\n}\n\n.popover {\n  &.top .arrow {\n    left: 50%;\n    margin-left: -$popover-arrow-outer-width;\n    border-bottom-width: 0;\n    border-top-color: $popover-arrow-outer-fallback-color; // IE8 fallback\n    border-top-color: $popover-arrow-outer-color;\n    bottom: -$popover-arrow-outer-width;\n    &:after {\n      content: \" \";\n      bottom: 1px;\n      margin-left: -$popover-arrow-width;\n      border-bottom-width: 0;\n      border-top-color: $popover-arrow-color;\n    }\n  }\n  &.right .arrow {\n    top: 50%;\n    left: -$popover-arrow-outer-width;\n    margin-top: -$popover-arrow-outer-width;\n    border-left-width: 0;\n    border-right-color: $popover-arrow-outer-fallback-color; // IE8 fallback\n    border-right-color: $popover-arrow-outer-color;\n    &:after {\n      content: \" \";\n      left: 1px;\n      bottom: -$popover-arrow-width;\n      border-left-width: 0;\n      border-right-color: $popover-arrow-color;\n    }\n  }\n  &.bottom .arrow {\n    left: 50%;\n    margin-left: -$popover-arrow-outer-width;\n    border-top-width: 0;\n    border-bottom-color: $popover-arrow-outer-fallback-color; // IE8 fallback\n    border-bottom-color: $popover-arrow-outer-color;\n    top: -$popover-arrow-outer-width;\n    &:after {\n      content: \" \";\n      top: 1px;\n      margin-left: -$popover-arrow-width;\n      border-top-width: 0;\n      border-bottom-color: $popover-arrow-color;\n    }\n  }\n\n  &.left .arrow {\n    top: 50%;\n    right: -$popover-arrow-outer-width;\n    margin-top: -$popover-arrow-outer-width;\n    border-right-width: 0;\n    border-left-color: $popover-arrow-outer-fallback-color; // IE8 fallback\n    border-left-color: $popover-arrow-outer-color;\n    &:after {\n      content: \" \";\n      right: 1px;\n      border-right-width: 0;\n      border-left-color: $popover-arrow-color;\n      bottom: -$popover-arrow-width;\n    }\n  }\n\n}\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/sass-bootstrap/lib/_print.scss",
    "content": "//\n// Basic print styles\n// --------------------------------------------------\n// Source: https://github.com/h5bp/html5-boilerplate/blob/master/css/main.css\n\n@media print {\n\n  * {\n    text-shadow: none !important;\n    color: #000 !important; // Black prints faster: h5bp.com/s\n    background: transparent !important;\n    box-shadow: none !important;\n  }\n\n  a,\n  a:visited {\n    text-decoration: underline;\n  }\n\n  a[href]:after {\n    content: \" (\" attr(href) \")\";\n  }\n\n  abbr[title]:after {\n    content: \" (\" attr(title) \")\";\n  }\n\n  // Don't show links for images, or javascript/internal links\n  .ir a:after,\n  a[href^=\"javascript:\"]:after,\n  a[href^=\"#\"]:after {\n    content: \"\";\n  }\n\n  pre,\n  blockquote {\n    border: 1px solid #999;\n    page-break-inside: avoid;\n  }\n\n  thead {\n    display: table-header-group; // h5bp.com/t\n  }\n\n  tr,\n  img {\n    page-break-inside: avoid;\n  }\n\n  img {\n    max-width: 100% !important;\n  }\n\n  @page {\n    margin: 2cm .5cm;\n  }\n\n  p,\n  h2,\n  h3 {\n    orphans: 3;\n    widows: 3;\n  }\n\n  h2,\n  h3 {\n    page-break-after: avoid;\n  }\n\n  // Bootstrap components\n  .navbar {\n    display: none;\n  }\n  .table {\n    td,\n    th {\n      background-color: #fff !important;\n    }\n  }\n  .btn,\n  .dropup > .btn {\n    > .caret {\n      border-top-color: #000 !important;\n    }\n  }\n  .label {\n    border: 1px solid #000;\n  }\n\n  .table {\n    border-collapse: collapse !important;\n  }\n  .table-bordered {\n    th,\n    td {\n      border: 1px solid #ddd !important;\n    }\n  }\n\n}\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/sass-bootstrap/lib/_progress-bars.scss",
    "content": "//\n// Progress bars\n// --------------------------------------------------\n\n\n// Bar animations\n// -------------------------\n\n// Webkit\n@-webkit-keyframes progress-bar-stripes {\n  from  { background-position: 40px 0; }\n  to    { background-position: 0 0; }\n}\n\n// Firefox\n@-moz-keyframes progress-bar-stripes {\n  from  { background-position: 40px 0; }\n  to    { background-position: 0 0; }\n}\n\n// Opera\n@-o-keyframes progress-bar-stripes {\n  from  { background-position: 0 0; }\n  to    { background-position: 40px 0; }\n}\n\n// Spec and IE10+\n@keyframes progress-bar-stripes {\n  from  { background-position: 40px 0; }\n  to    { background-position: 0 0; }\n}\n\n\n\n// Bar itself\n// -------------------------\n\n// Outer container\n.progress {\n  overflow: hidden;\n  height: $line-height-computed;\n  margin-bottom: $line-height-computed;\n  background-color: $progress-bg;\n  border-radius: $border-radius-base;\n  @include box-shadow(inset 0 1px 2px rgba(0,0,0,.1));\n}\n\n// Bar of progress\n.progress-bar {\n  float: left;\n  width: 0%;\n  height: 100%;\n  font-size: $font-size-small;\n  color: $progress-bar-color;\n  text-align: center;\n  background-color: $progress-bar-bg;\n  @include box-shadow(inset 0 -1px 0 rgba(0,0,0,.15));\n  @include transition(width .6s ease);\n}\n\n// Striped bars\n.progress-striped .progress-bar {\n  @include gradient-striped($progress-bar-bg);\n  background-size: 40px 40px;\n}\n\n// Call animation for the active one\n.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\n\n\n// Variations\n// -------------------------\n\n.progress-bar-success {\n  @include progress-bar-variant($progress-bar-success-bg);\n}\n\n.progress-bar-info {\n  @include progress-bar-variant($progress-bar-info-bg);\n}\n\n.progress-bar-warning {\n  @include progress-bar-variant($progress-bar-warning-bg);\n}\n\n.progress-bar-danger {\n  @include progress-bar-variant($progress-bar-danger-bg);\n}\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/sass-bootstrap/lib/_responsive-utilities.scss",
    "content": "//\n// Responsive: Utility classes\n// --------------------------------------------------\n\n\n// IE10 Metro responsive\n// Required for Windows 8 Metro split-screen snapping with IE10\n//\n// Source: http://timkadlec.com/2012/10/ie10-snap-mode-and-responsive-design/\n@-ms-viewport{\n  width: device-width;\n}\n\n// IE10 on Windows Phone 8\n// IE10 on WP8 doesn't report CSS pixels, but actual device pixels. In\n// other words, say on a Lumia, you'll get 768px as the device width,\n// meaning users will see the tablet styles and not phone styles.\n//\n// Alternatively you can override this with JS (see source below), but\n// we won't be doing that here given our limited scope.\n//\n// Source: http://timkadlec.com/2013/01/windows-phone-8-and-device-width/\n@media screen and (max-width: 400px) {\n  @-ms-viewport{\n    width: 320px;\n  }\n}\n\n// Hide from screenreaders and browsers\n// Credit: HTML5 Boilerplate\n.hidden {\n  display: none !important;\n  visibility: hidden !important;\n}\n\n// Visibility utilities\n\n@include responsive-invisibility('.visible-xs');\n@media (max-width: $screen-xs-max) {\n  @include responsive-visibility('.visible-xs');\n}\n\n@media (min-width: $screen-sm) and (max-width: $screen-sm-max) {\n  @include responsive-visibility('.visible-xs.visible-sm');\n}\n\n\n@media (min-width: $screen-md) and (max-width: $screen-md-max) {\n  @include responsive-visibility('.visible-xs.visible-md');\n}\n\n\n@media (min-width: $screen-lg) {\n  @include responsive-visibility('.visible-xs.visible-lg');\n}\n\n\n@include responsive-invisibility('.visible-sm');\n\n@media (max-width: $screen-xs-max) {\n  @include responsive-visibility('.visible-sm.visible-xs');\n}\n\n@media (min-width: $screen-sm) and (max-width: $screen-sm-max) {\n  @include responsive-visibility('.visible-sm');\n}\n\n@media (min-width: $screen-md) and (max-width: $screen-md-max) {\n  @include responsive-visibility('.visible-sm.visible-md');\n}\n\n\n@media (min-width: $screen-lg) {\n  @include responsive-visibility('.visible-sm.visible-lg');\n}\n\n\n@include responsive-invisibility('.visible-md');\n\n@media (max-width: $screen-xs-max) {\n  @include responsive-visibility('.visible-md.visible-xs');\n}\n\n\n@media (min-width: $screen-sm) and (max-width: $screen-sm-max) {\n  @include responsive-visibility('.visible-md.visible-sm');\n}\n\n@media (min-width: $screen-md) and (max-width: $screen-md-max) {\n  @include responsive-visibility('.visible-md');\n}\n\n@media (min-width: $screen-lg) {\n  @include responsive-visibility('.visible-md.visible-lg');\n}\n\n\n@include responsive-invisibility('.visible-lg');\n\n@media (max-width: $screen-xs-max) {\n  @include responsive-visibility('.visible-lg.visible-xs');\n}\n\n\n@media (min-width: $screen-sm) and (max-width: $screen-sm-max) {\n  @include responsive-visibility('.visible-lg.visible-sm');\n}\n\n\n@media (min-width: $screen-md) and (max-width: $screen-md-max) {\n  @include responsive-visibility('.visible-lg.visible-md');\n}\n\n@media (min-width: $screen-lg) {\n  @include responsive-visibility('.visible-lg');\n}\n\n@include responsive-visibility('.hidden-xs');\n@media (max-width: $screen-xs-max) {\n  @include responsive-invisibility('.hidden-xs');\n}\n\n@media (min-width: $screen-sm) and (max-width: $screen-sm-max) {\n  @include responsive-invisibility('.hidden-xs.hidden-sm');\n}\n\n\n@media (min-width: $screen-md) and (max-width: $screen-md-max) {\n  @include responsive-invisibility('.hidden-xs.hidden-md');\n}\n\n\n@media (min-width: $screen-lg) {\n  @include responsive-invisibility('.hidden-xs.hidden-lg');\n}\n\n\n@include responsive-visibility('.hidden-sm');\n\n@media (max-width: $screen-xs-max) {\n  @include responsive-invisibility('.hidden-sm.hidden-xs');\n}\n\n@media (min-width: $screen-sm) and (max-width: $screen-sm-max) {\n  @include responsive-invisibility('.hidden-sm');\n}\n\n@media (min-width: $screen-md) and (max-width: $screen-md-max) {\n  @include responsive-invisibility('.hidden-sm.hidden-md');\n}\n\n\n@media (min-width: $screen-lg) {\n  @include responsive-invisibility('.hidden-sm.hidden-lg');\n}\n\n\n@include responsive-visibility('.hidden-md');\n\n@media (max-width: $screen-xs-max) {\n  @include responsive-invisibility('.hidden-md.hidden-xs');\n}\n\n\n@media (min-width: $screen-sm) and (max-width: $screen-sm-max) {\n  @include responsive-invisibility('.hidden-md.hidden-sm');\n}\n\n@media (min-width: $screen-md) and (max-width: $screen-md-max) {\n  @include responsive-invisibility('.hidden-md');\n}\n\n@media (min-width: $screen-lg) {\n  @include responsive-invisibility('.hidden-md.hidden-lg');\n}\n\n\n@include responsive-visibility('.hidden-lg');\n\n@media (max-width: $screen-xs-max) {\n  @include responsive-invisibility('.hidden-lg.hidden-xs');\n}\n\n\n@media (min-width: $screen-sm) and (max-width: $screen-sm-max) {\n  @include responsive-invisibility('.hidden-lg.hidden-sm');\n}\n\n\n@media (min-width: $screen-md) and (max-width: $screen-md-max) {\n  @include responsive-invisibility('.hidden-lg.hidden-md');\n}\n\n@media (min-width: $screen-lg) {\n  @include responsive-invisibility('.hidden-lg');\n}\n\n// Print utilities\n\n@include responsive-invisibility('.visible-print');\n\n@media print {\n\n  @include responsive-visibility('.visible-print');\n\n\n  @include responsive-invisibility('.hidden-print');\n\n}\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/sass-bootstrap/lib/_scaffolding.scss",
    "content": "//\n// Scaffolding\n// --------------------------------------------------\n\n\n// Reset the box-sizing\n\n*,\n*:before,\n*:after {\n  @include box-sizing(border-box);\n}\n\n\n// Body reset\n\nhtml {\n  font-size: 62.5%;\n  -webkit-tap-highlight-color: rgba(0,0,0,0);\n}\n\nbody {\n  font-family: $font-family-base;\n  font-size: $font-size-base;\n  line-height: $line-height-base;\n  color: $text-color;\n  background-color: $body-bg;\n}\n\n// Reset fonts for relevant elements\ninput,\nbutton,\nselect,\ntextarea {\n  font-family: inherit;\n  font-size: inherit;\n  line-height: inherit;\n}\n\n// Reset unusual Firefox-on-Android default style.\n//\n// See https://github.com/necolas/normalize.css/issues/214\n\nbutton,\ninput,\nselect[multiple],\ntextarea {\n  background-image: none;\n}\n\n\n// Links\n\na {\n  color: $link-color;\n  text-decoration: none;\n\n  &:hover,\n  &:focus {\n    color: $link-hover-color;\n    text-decoration: underline;\n  }\n\n  &:focus {\n    @include tab-focus();\n  }\n}\n\n\n// Images\n\nimg {\n  vertical-align: middle;\n}\n\n// Responsive images (ensure images don't scale beyond their parents)\n.img-responsive {\n  @include img-responsive();\n}\n\n// Rounded corners\n.img-rounded {\n  border-radius: $border-radius-large;\n}\n\n// Image thumbnails\n//\n// Heads up! This is mixin-ed into thumbnails.less for `.thumbnail`.\n.img-thumbnail {\n  padding: $thumbnail-padding;\n  line-height: $line-height-base;\n  background-color: $thumbnail-bg;\n  border: 1px solid $thumbnail-border;\n  border-radius: $thumbnail-border-radius;\n  @include transition(all .2s ease-in-out);\n\n  // Keep them at most 100% wide\n  @include img-responsive(inline-block);\n}\n\n// Perfect circle\n.img-circle {\n  border-radius: 50%; // set radius in percents\n}\n\n\n// Horizontal rules\n\nhr {\n  margin-top:    $line-height-computed;\n  margin-bottom: $line-height-computed;\n  border: 0;\n  border-top: 1px solid $hr-border;\n}\n\n\n// Only display content to screen readers\n//\n// See: http://a11yproject.com/posts/how-to-hide-content/\n\n.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"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/sass-bootstrap/lib/_tables.scss",
    "content": "//\n// Tables\n// --------------------------------------------------\n\n\ntable {\n  max-width: 100%;\n  background-color: $table-bg;\n}\nth {\n  text-align: left;\n}\n\n\n// Baseline styles\n\n.table {\n  width: 100%;\n  margin-bottom: $line-height-computed;\n  // Cells\n  thead,\n  tbody,\n  tfoot {\n    > tr {\n      > th,\n      > td {\n        padding: $table-cell-padding;\n        line-height: $line-height-base;\n        vertical-align: top;\n        border-top: 1px solid $table-border-color;\n      }\n    }\n  }\n  // Bottom align for column headings\n  thead > tr > th {\n    vertical-align: bottom;\n    border-bottom: 2px solid $table-border-color;\n  }\n  // Remove top border from thead by default\n  caption + thead,\n  colgroup + thead,\n  thead:first-child {\n    tr:first-child {\n      th, td {\n        border-top: 0;\n      }\n    }\n  }\n  // Account for multiple tbody instances\n  tbody + tbody {\n    border-top: 2px solid $table-border-color;\n  }\n\n  // Nesting\n  .table {\n    background-color: $body-bg;\n  }\n}\n\n\n// Condensed table w/ half padding\n\n.table-condensed {\n  thead,\n  tbody,\n  tfoot {\n    > tr {\n      > th,\n      > td {\n        padding: $table-condensed-cell-padding;\n      }\n    }\n  }\n}\n\n\n// Bordered version\n//\n// Add borders all around the table and between all the columns.\n\n.table-bordered {\n  border: 1px solid $table-border-color;\n  > thead,\n  > tbody,\n  > tfoot {\n    > tr {\n      > th,\n      > td {\n        border: 1px solid $table-border-color;\n      }\n    }\n  }\n  > thead {\n    > tr {\n      > th,\n      > td {\n        border-bottom-width: 2px;\n      }\n    }\n  }\n}\n\n\n// Zebra-striping\n//\n// Default zebra-stripe styles (alternating gray and transparent backgrounds)\n\n.table-striped {\n  > tbody {\n    > tr:nth-child(odd) {\n      > td,\n      > th {\n        background-color: $table-bg-accent;\n      }\n    }\n  }\n}\n\n\n// Hover effect\n//\n// Placed here since it has to come after the potential zebra striping\n\n.table-hover {\n  > tbody {\n    > tr:hover {\n      > td,\n      > th {\n        background-color: $table-bg-hover;\n      }\n    }\n  }\n}\n\n\n// Table cell sizing\n//\n// Reset default table behavior\n\ntable col[class*=\"col-\"] {\n  float: none;\n  display: table-column;\n}\ntable {\n  td,\n  th {\n    &[class*=\"col-\"] {\n      float: none;\n      display: table-cell;\n    }\n  }\n}\n\n\n// Table backgrounds\n//\n// Exact selectors below required to override `.table-striped` and prevent\n// inheritance to nested tables.\n\n.table > thead > tr,\n.table > tbody > tr,\n.table > tfoot > tr {\n  > td.active,\n  > th.active,\n  &.active > td,\n  &.active > th  {\n    background-color: $table-bg-active;\n  }\n}\n\n// Generate the contextual variants\n@include table-row-variant('success', $state-success-bg, $state-success-border);\n@include table-row-variant('danger', $state-danger-bg, $state-danger-border);\n@include table-row-variant('warning', $state-warning-bg, $state-warning-border);\n\n\n// Responsive tables\n//\n// Wrap your tables in `.table-scrollable` and we'll make them mobile friendly\n// by enabling horizontal scrolling. Only applies <768px. Everything above that\n// will display normally.\n\n@media (max-width: $screen-sm) {\n  .table-responsive {\n    width: 100%;\n    margin-bottom: 15px;\n    overflow-y: hidden;\n    overflow-x: scroll;\n    border: 1px solid $table-border-color;\n\n    // Tighten up spacing and give a background color\n    > .table {\n      margin-bottom: 0;\n      background-color: #fff;\n\n      // Ensure the content doesn't wrap\n      > thead,\n      > tbody,\n      > tfoot {\n        > tr {\n          > th,\n          > td {\n            white-space: nowrap;\n          }\n        }\n      }\n    }\n\n    // Special overrides for the bordered tables\n    > .table-bordered {\n      border: 0;\n\n      // Nuke the appropriate borders so that the parent can handle them\n      > thead,\n      > tbody,\n      > tfoot {\n        > tr {\n          > th:first-child,\n          > td:first-child {\n            border-left: 0;\n          }\n          > th:last-child,\n          > td:last-child {\n            border-right: 0;\n          }\n        }\n        > tr:last-child {\n          > th,\n          > td {\n            border-bottom: 0;\n          }\n        }\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/sass-bootstrap/lib/_theme.scss",
    "content": "\n//\n// Load core variables and mixins\n// --------------------------------------------------\n\n@import \"variables\";\n@import \"mixins\";\n\n\n\n//\n// Buttons\n// --------------------------------------------------\n\n// Common styles\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  $shadow: inset 0 1px 0 rgba(255,255,255,.15), 0 1px 1px rgba(0,0,0,.075);\n  @include box-shadow($shadow);\n\n  // Reset the shadow\n  &:active,\n  &.active {\n    @include box-shadow(inset 0 3px 5px rgba(0,0,0,.125));\n  }\n}\n\n// Mixin for generating new styles\n@mixin btn-styles($btn-color: #555) {\n  @include gradient-vertical($start-color: $btn-color, $end-color: darken($btn-color, 10%));\n  border-color: darken($btn-color, 12%);\n\n  &:active,\n  &.active {\n    background-color: darken($btn-color, 10%);\n    border-color: darken($btn-color, 12%);\n  }\n}\n\n// Common styles\n.btn {\n  // Remove the gradient for the pressed/active state\n  &:active,\n  &.active {\n    background-image: none;\n  }\n}\n\n// Apply the mixin to the buttons\n.btn-default { @include btn-styles($btn-default-bg); text-shadow: 0 1px 0 #fff; border-color: #ccc; }\n.btn-primary { @include btn-styles($btn-primary-bg); }\n.btn-success { @include btn-styles($btn-success-bg); }\n.btn-warning { @include btn-styles($btn-warning-bg); }\n.btn-danger  { @include btn-styles($btn-danger-bg); }\n.btn-info    { @include btn-styles($btn-info-bg); }\n\n\n\n//\n// Images\n// --------------------------------------------------\n\n.thumbnail,\n.img-thumbnail {\n  @include box-shadow(0 1px 2px rgba(0,0,0,.075));\n}\n\n\n\n//\n// Dropdowns\n// --------------------------------------------------\n\n.dropdown-menu > li > a:hover,\n.dropdown-menu > li > a:focus,\n.dropdown-menu > .active > a,\n.dropdown-menu > .active > a:hover,\n.dropdown-menu > .active > a:focus {\n  @include gradient-vertical($start-color: $dropdown-link-hover-bg, $end-color: darken($dropdown-link-hover-bg, 5%));\n  background-color: darken($dropdown-link-hover-bg, 5%);\n}\n\n\n\n//\n// Navbar\n// --------------------------------------------------\n\n// Basic navbar\n.navbar {\n  @include gradient-vertical($start-color: lighten($navbar-default-bg, 10%), $end-color: $navbar-default-bg);\n  border-radius: $navbar-border-radius;\n  $shadow: inset 0 1px 0 rgba(255,255,255,.15), 0 1px 5px rgba(0,0,0,.075);\n  @include box-shadow($shadow);\n\n  .navbar-nav > .active > a {\n    background-color: $navbar-default-bg;\n  }\n}\n.navbar-brand,\n.navbar-nav > li > a {\n  text-shadow: 0 1px 0 rgba(255,255,255,.25);\n}\n\n// Inverted navbar\n.navbar-inverse {\n  @include gradient-vertical($start-color: lighten($navbar-inverse-bg, 10%), $end-color: $navbar-inverse-bg);\n\n  .navbar-nav > .active > a {\n    background-color: $navbar-inverse-bg;\n  }\n\n  .navbar-brand,\n  .navbar-nav > li > a {\n    text-shadow: 0 -1px 0 rgba(0,0,0,.25);\n  }\n}\n\n// Undo rounded corners in static and fixed navbars\n.navbar-static-top,\n.navbar-fixed-top,\n.navbar-fixed-bottom {\n  border-radius: 0;\n}\n\n\n\n//\n// Alerts\n// --------------------------------------------------\n\n// Common styles\n.alert {\n  text-shadow: 0 1px 0 rgba(255,255,255,.2);\n  $shadow: inset 0 1px 0 rgba(255,255,255,.25), 0 1px 2px rgba(0,0,0,.05);\n  @include box-shadow($shadow);\n}\n\n// Mixin for generating new styles\n@mixin alert-styles($color) {\n  @include gradient-vertical($start-color: $color, $end-color: darken($color, 7.5%));\n  border-color: darken($color, 15%);\n}\n\n// Apply the mixin to the alerts\n.alert-success    { @include alert-styles($alert-success-bg); }\n.alert-info       { @include alert-styles($alert-info-bg); }\n.alert-warning    { @include alert-styles($alert-warning-bg); }\n.alert-danger     { @include alert-styles($alert-danger-bg); }\n\n\n\n//\n// Progress bars\n// --------------------------------------------------\n\n// Give the progress background some depth\n.progress {\n  @include gradient-vertical($start-color: darken($progress-bg, 4%), $end-color: $progress-bg)\n}\n\n// Mixin for generating new styles\n@mixin progress-bar-styles($color) {\n  @include gradient-vertical($start-color: $color, $end-color: darken($color, 10%));\n}\n\n// Apply the mixin to the progress bars\n.progress-bar            { @include progress-bar-styles($progress-bar-bg); }\n.progress-bar-success    { @include progress-bar-styles($progress-bar-success-bg); }\n.progress-bar-info       { @include progress-bar-styles($progress-bar-info-bg); }\n.progress-bar-warning    { @include progress-bar-styles($progress-bar-warning-bg); }\n.progress-bar-danger     { @include progress-bar-styles($progress-bar-danger-bg); }\n\n\n\n//\n// List groups\n// --------------------------------------------------\n\n.list-group {\n  border-radius: $border-radius-base;\n  @include 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 darken($list-group-active-bg, 10%);\n  @include gradient-vertical($start-color: $list-group-active-bg, $end-color: darken($list-group-active-bg, 7.5%));\n  border-color: darken($list-group-active-border, 7.5%);\n}\n\n\n\n//\n// Panels\n// --------------------------------------------------\n\n// Common styles\n.panel {\n  @include box-shadow(0 1px 2px rgba(0,0,0,.05));\n}\n\n// Mixin for generating new styles\n@mixin panel-heading-styles($color) {\n  @include gradient-vertical($start-color: $color, $end-color: darken($color, 5%));\n}\n\n// Apply the mixin to the panel headings only\n.panel-default > .panel-heading   { @include panel-heading-styles($panel-default-heading-bg); }\n.panel-primary > .panel-heading   { @include panel-heading-styles($panel-primary-heading-bg); }\n.panel-success > .panel-heading   { @include panel-heading-styles($panel-success-heading-bg); }\n.panel-info > .panel-heading      { @include panel-heading-styles($panel-info-heading-bg); }\n.panel-warning > .panel-heading   { @include panel-heading-styles($panel-warning-heading-bg); }\n.panel-danger > .panel-heading    { @include panel-heading-styles($panel-danger-heading-bg); }\n\n\n\n//\n// Wells\n// --------------------------------------------------\n\n.well {\n  @include gradient-vertical($start-color: darken($well-bg, 5%), $end-color: $well-bg);\n  border-color: darken($well-bg, 10%);\n  $shadow: inset 0 1px 3px rgba(0,0,0,.05), 0 1px 0 rgba(255,255,255,.1);\n  @include box-shadow($shadow);\n}\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/sass-bootstrap/lib/_thumbnails.scss",
    "content": "//\n// Thumbnails\n// --------------------------------------------------\n\n\n// Mixin and adjust the regular image class\n.thumbnail {\n  @extend .img-thumbnail;\n  display: block; // Override the inline-block from `.img-thumbnail`\n\n  > img {\n    @include img-responsive();\n  }\n}\n\n\n// Add a hover state for linked versions only\na.thumbnail:hover,\na.thumbnail:focus {\n  border-color: $link-color;\n}\n\n// Images and captions\n.thumbnail > img {\n  margin-left: auto;\n  margin-right: auto;\n}\n.thumbnail .caption {\n  padding: $thumbnail-caption-padding;\n  color: $thumbnail-caption-color;\n}\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/sass-bootstrap/lib/_tooltip.scss",
    "content": "//\n// Tooltips\n// --------------------------------------------------\n\n\n// Base class\n.tooltip {\n  position: absolute;\n  z-index: $zindex-tooltip;\n  display: block;\n  visibility: visible;\n  font-size: $font-size-small;\n  line-height: 1.4;\n  @include opacity(0);\n\n  &.in     { @include opacity(.9); }\n  &.top    { margin-top:  -3px; padding: 5px 0; }\n  &.right  { margin-left:  3px; padding: 0 5px; }\n  &.bottom { margin-top:   3px; padding: 5px 0; }\n  &.left   { margin-left: -3px; padding: 0 5px; }\n}\n\n// Wrapper for the tooltip content\n.tooltip-inner {\n  max-width: $tooltip-max-width;\n  padding: 3px 8px;\n  color: $tooltip-color;\n  text-align: center;\n  text-decoration: none;\n  background-color: $tooltip-bg;\n  border-radius: $border-radius-base;\n}\n\n// Arrows\n.tooltip-arrow {\n  position: absolute;\n  width: 0;\n  height: 0;\n  border-color: transparent;\n  border-style: solid;\n}\n.tooltip {\n  &.top .tooltip-arrow {\n    bottom: 0;\n    left: 50%;\n    margin-left: -$tooltip-arrow-width;\n    border-width: $tooltip-arrow-width $tooltip-arrow-width 0;\n    border-top-color: $tooltip-arrow-color;\n  }\n  &.top-left .tooltip-arrow {\n    bottom: 0;\n    left: 5px;\n    border-width: $tooltip-arrow-width $tooltip-arrow-width 0;\n    border-top-color: $tooltip-arrow-color;\n  }\n  &.top-right .tooltip-arrow {\n    bottom: 0;\n    right: 5px;\n    border-width: $tooltip-arrow-width $tooltip-arrow-width 0;\n    border-top-color: $tooltip-arrow-color;\n  }\n  &.right .tooltip-arrow {\n    top: 50%;\n    left: 0;\n    margin-top: -$tooltip-arrow-width;\n    border-width: $tooltip-arrow-width $tooltip-arrow-width $tooltip-arrow-width 0;\n    border-right-color: $tooltip-arrow-color;\n  }\n  &.left .tooltip-arrow {\n    top: 50%;\n    right: 0;\n    margin-top: -$tooltip-arrow-width;\n    border-width: $tooltip-arrow-width 0 $tooltip-arrow-width $tooltip-arrow-width;\n    border-left-color: $tooltip-arrow-color;\n  }\n  &.bottom .tooltip-arrow {\n    top: 0;\n    left: 50%;\n    margin-left: -$tooltip-arrow-width;\n    border-width: 0 $tooltip-arrow-width $tooltip-arrow-width;\n    border-bottom-color: $tooltip-arrow-color;\n  }\n  &.bottom-left .tooltip-arrow {\n    top: 0;\n    left: 5px;\n    border-width: 0 $tooltip-arrow-width $tooltip-arrow-width;\n    border-bottom-color: $tooltip-arrow-color;\n  }\n  &.bottom-right .tooltip-arrow {\n    top: 0;\n    right: 5px;\n    border-width: 0 $tooltip-arrow-width $tooltip-arrow-width;\n    border-bottom-color: $tooltip-arrow-color;\n  }\n}\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/sass-bootstrap/lib/_type.scss",
    "content": "//\n// Typography\n// --------------------------------------------------\n\n\n// Body text\n// -------------------------\n\np {\n  margin: 0 0 ($line-height-computed / 2);\n}\n.lead {\n  margin-bottom: $line-height-computed;\n  font-size: ($font-size-base * 1.15);\n  font-weight: 200;\n  line-height: 1.4;\n\n  @media (min-width: 768px) {\n    font-size: ($font-size-base * 1.5);\n  }\n}\n\n\n// Emphasis & misc\n// -------------------------\n\n// Ex: 14px base font * 85% = about 12px\nsmall   { font-size: 85%; }\n\n// Undo browser default styling\ncite    { font-style: normal; }\n\n// Contextual emphasis\n.text-muted          { color: $text-muted; }\n.text-primary        { color: $brand-primary; }\n.text-warning        { color: $state-warning-text; }\n.text-danger         { color: $state-danger-text; }\n.text-success        { color: $state-success-text; }\n.text-info           { color: $state-info-text; }\n\n// Alignment\n.text-left           { text-align: left; }\n.text-right          { text-align: right; }\n.text-center         { text-align: center; }\n\n\n// Headings\n// -------------------------\n\nh1, h2, h3, h4, h5, h6,\n.h1, .h2, .h3, .h4, .h5, .h6 {\n  font-family: $headings-font-family;\n  font-weight: $headings-font-weight;\n  line-height: $headings-line-height;\n  small {\n    font-weight: normal;\n    line-height: 1;\n    color: $headings-small-color;\n  }\n}\n\nh1,\nh2,\nh3 {\n  margin-top: $line-height-computed;\n  margin-bottom: ($line-height-computed / 2);\n}\nh4,\nh5,\nh6 {\n  margin-top: ($line-height-computed / 2);\n  margin-bottom: ($line-height-computed / 2);\n}\n\nh1, .h1 { font-size: floor($font-size-base * 2.60); } // ~36px\nh2, .h2 { font-size: floor($font-size-base * 2.15); } // ~30px\nh3, .h3 { font-size: ceil($font-size-base * 1.70); } // ~24px\nh4, .h4 { font-size: ceil($font-size-base * 1.25); } // ~18px\nh5, .h5 { font-size:  $font-size-base; }\nh6, .h6 { font-size: ceil($font-size-base * 0.85); } // ~12px\n\nh1 small, .h1 small { font-size: ceil($font-size-base * 1.70); } // ~24px\nh2 small, .h2 small { font-size: ceil($font-size-base * 1.25); } // ~18px\nh3 small, .h3 small,\nh4 small, .h4 small { font-size: $font-size-base; }\n\n\n// Page header\n// -------------------------\n\n.page-header {\n  padding-bottom: (($line-height-computed / 2) - 1);\n  margin: ($line-height-computed * 2) 0 $line-height-computed;\n  border-bottom: 1px solid $page-header-border-color;\n}\n\n\n\n// Lists\n// --------------------------------------------------\n\n// Unordered and Ordered lists\nul,\nol {\n  margin-top: 0;\n  margin-bottom: ($line-height-computed / 2);\n  ul,\n  ol{\n    margin-bottom: 0;\n  }\n}\n\n// List options\n\n// Unstyled keeps list items block level, just removes default browser padding and list-style\n.list-unstyled {\n  padding-left: 0;\n  list-style: none;\n}\n// Inline turns list items into inline-block\n.list-inline {\n  @extend .list-unstyled;\n  > li {\n    display: inline-block;\n    padding-left: 5px;\n    padding-right: 5px;\n  }\n}\n\n// Description Lists\ndl {\n  margin-bottom: $line-height-computed;\n}\ndt,\ndd {\n  line-height: $line-height-base;\n}\ndt {\n  font-weight: bold;\n}\ndd {\n  margin-left: 0; // Undo browser default\n}\n\n// Horizontal description lists\n//\n// Defaults to being stacked without any of the below styles applied, until the\n// grid breakpoint is reached (default of ~768px).\n\n@media (min-width: $grid-float-breakpoint) {\n  .dl-horizontal {\n    dt {\n      float: left;\n      width: ($component-offset-horizontal - 20);\n      clear: left;\n      text-align: right;\n      @include text-overflow();\n    }\n    dd {\n      margin-left: $component-offset-horizontal;\n      @include clearfix(); // Clear the floated `dt` if an empty `dd` is present\n    }\n  }\n}\n\n// MISC\n// ----\n\n// Abbreviations and acronyms\nabbr[title],\n// Added data-* attribute to help out our tooltip plugin, per https://github.com/twbs/bootstrap/issues/5257\nabbr[data-original-title] {\n  cursor: help;\n  border-bottom: 1px dotted $abbr-border-color;\n}\nabbr.initialism {\n  font-size: 90%;\n  text-transform: uppercase;\n}\n\n// Blockquotes\nblockquote {\n  padding: ($line-height-computed / 2) $line-height-computed;\n  margin: 0 0 $line-height-computed;\n  border-left: 5px solid $blockquote-border-color;\n  p {\n    font-size: ($font-size-base * 1.25);\n    font-weight: 300;\n    line-height: 1.25;\n  }\n  p:last-child {\n    margin-bottom: 0;\n  }\n  small {\n    display: block;\n    line-height: $line-height-base;\n    color: $blockquote-small-color;\n    &:before {\n      content: '\\2014 \\00A0';// EM DASH, NBSP\n    }\n  }\n\n  // Float right with text-align: right\n  &.pull-right {\n    padding-right: 15px;\n    padding-left: 0;\n    border-right: 5px solid $blockquote-border-color;\n    border-left: 0;\n    p,\n    small {\n      text-align: right;\n    }\n    small {\n      &:before {\n        content: '';\n      }\n      &:after {\n        content: '\\00A0 \\2014';// NBSP, EM DASH\n      }\n    }\n  }\n}\n\n// Quotes\nq:before,\nq:after,\nblockquote:before,\nblockquote:after {\n  content: \"\";\n}\n\n// Addresses\naddress {\n  display: block;\n  margin-bottom: $line-height-computed;\n  font-style: normal;\n  line-height: $line-height-base;\n}\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/sass-bootstrap/lib/_utilities.scss",
    "content": "//\n// Utility classes\n// --------------------------------------------------\n\n\n// Floats\n// -------------------------\n\n.clearfix {\n  @include clearfix();\n}\n.pull-right {\n  float: right !important;\n}\n.pull-left {\n  float: left !important;\n}\n\n\n// Toggling content\n// -------------------------\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  @include hide-text();\n}\n\n\n// For Affix plugin\n// -------------------------\n\n.affix {\n  position: fixed;\n}\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/sass-bootstrap/lib/_variables.scss",
    "content": "//\n// Variables\n// --------------------------------------------------\n\n\n// Global values\n// --------------------------------------------------\n\n// Grays\n// -------------------------\n\n$gray-darker:            lighten(#000, 13.5%) !default; // #222\n$gray-dark:              lighten(#000, 20%) !default;   // #333\n$gray:                   lighten(#000, 33.5%) !default; // #555\n$gray-light:             lighten(#000, 60%) !default;   // #999\n$gray-lighter:           lighten(#000, 93.5%) !default; // #eee\n\n// Brand colors\n// -------------------------\n\n$brand-primary:         #428bca !default;\n$brand-success:         #5cb85c !default;\n$brand-warning:         #f0ad4e !default;\n$brand-danger:          #d9534f !default;\n$brand-info:            #5bc0de !default;\n\n// Scaffolding\n// -------------------------\n\n$body-bg:               #fff !default;\n$text-color:            $gray-dark !default;\n\n// Links\n// -------------------------\n\n$link-color:            $brand-primary !default;\n$link-hover-color:      darken($link-color, 15%) !default;\n\n// Typography\n// -------------------------\n\n$font-family-sans-serif:  \"Helvetica Neue\", Helvetica, Arial, sans-serif !default;\n$font-family-serif:       Georgia, \"Times New Roman\", Times, serif !default;\n$font-family-monospace:   Monaco, Menlo, Consolas, \"Courier New\", monospace !default;\n$font-family-base:        $font-family-sans-serif !default;\n\n$font-size-base:          14px !default;\n$font-size-large:         ceil($font-size-base * 1.25) !default; // ~18px\n$font-size-small:         ceil($font-size-base * 0.85) !default; // ~12px\n\n$line-height-base:        1.428571429 !default; // 20/14\n$line-height-computed:    floor($font-size-base * $line-height-base) !default; // ~20px\n\n$headings-font-family:    $font-family-base !default;\n$headings-font-weight:    500 !default;\n$headings-line-height:    1.1 !default;\n\n// Iconography\n// -------------------------\n\n$icon-font-path:          \"../fonts/\" !default;\n$icon-font-name:          \"glyphicons-halflings-regular\" !default;\n\n\n// Components\n// -------------------------\n// Based on 14px font-size and 1.428 line-height (~20px to start)\n\n$padding-base-vertical:          6px !default;\n$padding-base-horizontal:        12px !default;\n\n$padding-large-vertical:         10px !default;\n$padding-large-horizontal:       16px !default;\n\n$padding-small-vertical:         5px !default;\n$padding-small-horizontal:       10px !default;\n\n$line-height-large:              1.33 !default;\n$line-height-small:              1.5 !default;\n\n$border-radius-base:             4px !default;\n$border-radius-large:            6px !default;\n$border-radius-small:            3px !default;\n\n$component-active-bg:            $brand-primary !default;\n\n$caret-width-base:               4px !default;\n$caret-width-large:              5px !default;\n\n// Tables\n// -------------------------\n\n$table-cell-padding:                 8px !default;\n$table-condensed-cell-padding:       5px !default;\n\n$table-bg:                           transparent !default; // overall background-color\n$table-bg-accent:                    #f9f9f9 !default; // for striping\n$table-bg-hover:                     #f5f5f5 !default;\n$table-bg-active:                    $table-bg-hover !default;\n\n$table-border-color:                 #ddd !default; // table and cell border\n\n\n// Buttons\n// -------------------------\n\n$btn-font-weight:                normal !default;\n\n$btn-default-color:              #333 !default;\n$btn-default-bg:                 #fff !default;\n$btn-default-border:             #ccc !default;\n\n$btn-primary-color:              #fff !default;\n$btn-primary-bg:                 $brand-primary !default;\n$btn-primary-border:             darken($btn-primary-bg, 5%) !default;\n\n$btn-success-color:              #fff !default;\n$btn-success-bg:                 $brand-success !default;\n$btn-success-border:             darken($btn-success-bg, 5%) !default;\n\n$btn-warning-color:              #fff !default;\n$btn-warning-bg:                 $brand-warning !default;\n$btn-warning-border:             darken($btn-warning-bg, 5%) !default;\n\n$btn-danger-color:               #fff !default;\n$btn-danger-bg:                  $brand-danger !default;\n$btn-danger-border:              darken($btn-danger-bg, 5%) !default;\n\n$btn-info-color:                 #fff !default;\n$btn-info-bg:                    $brand-info !default;\n$btn-info-border:                darken($btn-info-bg, 5%) !default;\n\n$btn-link-disabled-color:        $gray-light !default;\n\n\n// Forms\n// -------------------------\n\n$input-bg:                       #fff !default;\n$input-bg-disabled:              $gray-lighter !default;\n\n$input-color:                    $gray !default;\n$input-border:                   #ccc !default;\n$input-border-radius:            $border-radius-base !default;\n$input-border-focus:             #66afe9 !default;\n\n$input-color-placeholder:        $gray-light !default;\n\n$input-height-base:              ($line-height-computed + ($padding-base-vertical * 2) + 2) !default;\n$input-height-large:             (floor($font-size-large * $line-height-large) + ($padding-large-vertical * 2) + 2) !default;\n$input-height-small:             (floor($font-size-small * $line-height-small) + ($padding-small-vertical * 2) + 2) !default;\n\n$legend-color:                   $gray-dark !default;\n$legend-border-color:            #e5e5e5 !default;\n\n$input-group-addon-bg:           $gray-lighter !default;\n$input-group-addon-border-color: $input-border !default;\n\n\n// Dropdowns\n// -------------------------\n\n$dropdown-bg:                    #fff !default;\n$dropdown-border:                rgba(0,0,0,.15) !default;\n$dropdown-fallback-border:       #ccc !default;\n$dropdown-divider-bg:            #e5e5e5 !default;\n\n$dropdown-link-active-color:     #fff !default;\n$dropdown-link-active-bg:        $component-active-bg !default;\n\n$dropdown-link-color:            $gray-dark !default;\n$dropdown-link-hover-color:      #fff !default;\n$dropdown-link-hover-bg:         $dropdown-link-active-bg !default;\n\n$dropdown-link-disabled-color:   $gray-light !default;\n\n$dropdown-header-color:          $gray-light !default;\n\n$dropdown-caret-color:           #000 !default;\n\n\n// COMPONENT VARIABLES\n// --------------------------------------------------\n\n\n// Z-index master list\n// -------------------------\n// Used for a bird's eye view of components dependent on the z-axis\n// Try to avoid customizing these :)\n\n$zindex-navbar:            1000 !default;\n$zindex-dropdown:          1000 !default;\n$zindex-popover:           1010 !default;\n$zindex-tooltip:           1030 !default;\n$zindex-navbar-fixed:      1030 !default;\n$zindex-modal-background:  1040 !default;\n$zindex-modal:             1050 !default;\n\n// Media queries breakpoints\n// --------------------------------------------------\n\n// Extra small screen / phone\n$screen-xs:                  480px !default;\n$screen-phone:               $screen-xs !default;\n\n// Small screen / tablet\n$screen-sm:                  768px !default;\n$screen-tablet:              $screen-sm !default;\n\n// Medium screen / desktop\n$screen-md:                  992px !default;\n$screen-desktop:             $screen-md !default;\n\n// Large screen / wide desktop\n$screen-lg:                  1200px !default;\n$screen-lg-desktop:          $screen-lg !default;\n\n// So media queries don't overlap when required, provide a maximum\n$screen-xs-max:              ($screen-sm - 1) !default;\n$screen-sm-max:              ($screen-md - 1) !default;\n$screen-md-max:              ($screen-lg - 1) !default;\n\n\n// Grid system\n// --------------------------------------------------\n\n// Number of columns in the grid system\n$grid-columns:              12 !default;\n// Padding, to be divided by two and applied to the left and right of all columns\n$grid-gutter-width:         30px !default;\n// Point at which the navbar stops collapsing\n$grid-float-breakpoint:     $screen-tablet !default;\n\n\n// Navbar\n// -------------------------\n\n// Basics of a navbar\n$navbar-height:                    50px !default;\n$navbar-margin-bottom:             $line-height-computed !default;\n$navbar-default-color:             #777 !default;\n$navbar-default-bg:                #f8f8f8 !default;\n$navbar-default-border:            darken($navbar-default-bg, 6.5%) !default;\n$navbar-border-radius:             $border-radius-base !default;\n$navbar-padding-horizontal:        floor($grid-gutter-width / 2) !default;\n$navbar-padding-vertical:          (($navbar-height - $line-height-computed) / 2) !default;\n\n// Navbar links\n$navbar-default-link-color:                #777 !default;\n$navbar-default-link-hover-color:          #333 !default;\n$navbar-default-link-hover-bg:             transparent !default;\n$navbar-default-link-active-color:         #555 !default;\n$navbar-default-link-active-bg:            darken($navbar-default-bg, 6.5%) !default;\n$navbar-default-link-disabled-color:       #ccc !default;\n$navbar-default-link-disabled-bg:          transparent !default;\n\n// Navbar brand label\n$navbar-default-brand-color:               $navbar-default-link-color !default;\n$navbar-default-brand-hover-color:         darken($navbar-default-link-color, 10%) !default;\n$navbar-default-brand-hover-bg:            transparent !default;\n\n// Navbar toggle\n$navbar-default-toggle-hover-bg:           #ddd !default;\n$navbar-default-toggle-icon-bar-bg:        #ccc !default;\n$navbar-default-toggle-border-color:       #ddd !default;\n\n\n// Inverted navbar\n//\n// Reset inverted navbar basics\n$navbar-inverse-color:                      $gray-light !default;\n$navbar-inverse-bg:                         #222 !default;\n$navbar-inverse-border:                     darken($navbar-inverse-bg, 10%) !default;\n\n// Inverted navbar links\n$navbar-inverse-link-color:                 $gray-light !default;\n$navbar-inverse-link-hover-color:           #fff !default;\n$navbar-inverse-link-hover-bg:              transparent !default;\n$navbar-inverse-link-active-color:          $navbar-inverse-link-hover-color !default;\n$navbar-inverse-link-active-bg:             darken($navbar-inverse-bg, 10%) !default;\n$navbar-inverse-link-disabled-color:        #444 !default;\n$navbar-inverse-link-disabled-bg:           transparent !default;\n\n// Inverted navbar brand label\n$navbar-inverse-brand-color:                $navbar-inverse-link-color !default;\n$navbar-inverse-brand-hover-color:          #fff !default;\n$navbar-inverse-brand-hover-bg:             transparent !default;\n\n// Inverted navbar search\n// Normal navbar needs no special styles or vars\n$navbar-inverse-search-bg:                  lighten($navbar-inverse-bg, 25%) !default;\n$navbar-inverse-search-bg-focus:            #fff !default;\n$navbar-inverse-search-border:              $navbar-inverse-bg !default;\n$navbar-inverse-search-placeholder-color:   #ccc !default;\n\n// Inverted navbar toggle\n$navbar-inverse-toggle-hover-bg:            #333 !default;\n$navbar-inverse-toggle-icon-bar-bg:         #fff !default;\n$navbar-inverse-toggle-border-color:        #333 !default;\n\n\n// Navs\n// -------------------------\n\n$nav-link-padding:                          10px 15px !default;\n$nav-link-hover-bg:                         $gray-lighter !default;\n\n$nav-disabled-link-color:                   $gray-light !default;\n$nav-disabled-link-hover-color:             $gray-light !default;\n\n$nav-open-link-hover-color:                 #fff !default;\n$nav-open-caret-border-color:               #fff !default;\n\n// Tabs\n$nav-tabs-border-color:                     #ddd !default;\n\n$nav-tabs-link-hover-border-color:          $gray-lighter !default;\n\n$nav-tabs-active-link-hover-bg:             $body-bg !default;\n$nav-tabs-active-link-hover-color:          $gray !default;\n$nav-tabs-active-link-hover-border-color:   #ddd !default;\n\n$nav-tabs-justified-link-border-color:            #ddd !default;\n$nav-tabs-justified-active-link-border-color:     $body-bg !default;\n\n// Pills\n$nav-pills-active-link-hover-bg:            $component-active-bg !default;\n$nav-pills-active-link-hover-color:         #fff !default;\n\n\n// Pagination\n// -------------------------\n\n$pagination-bg:                        #fff !default;\n$pagination-border:                    #ddd !default;\n\n$pagination-hover-bg:                  $gray-lighter !default;\n\n$pagination-active-bg:                 $brand-primary !default;\n$pagination-active-color:              #fff !default;\n\n$pagination-disabled-color:            $gray-light !default;\n\n\n// Pager\n// -------------------------\n\n$pager-border-radius:                  15px !default;\n$pager-disabled-color:                 $gray-light !default;\n\n\n// Jumbotron\n// -------------------------\n\n$jumbotron-padding:              30px !default;\n$jumbotron-color:                inherit !default;\n$jumbotron-bg:                   $gray-lighter !default;\n\n$jumbotron-heading-color:        inherit !default;\n\n\n// Form states and alerts\n// -------------------------\n\n$state-warning-text:             #c09853 !default;\n$state-warning-bg:               #fcf8e3 !default;\n$state-warning-border:           darken(adjust-hue($state-warning-bg, -10), 3%) !default;\n\n$state-danger-text:              #b94a48 !default;\n$state-danger-bg:                #f2dede !default;\n$state-danger-border:            darken(adjust-hue($state-danger-bg, -10), 3%) !default;\n\n$state-success-text:             #468847 !default;\n$state-success-bg:               #dff0d8 !default;\n$state-success-border:           darken(adjust-hue($state-success-bg, -10), 5%) !default;\n\n$state-info-text:                #3a87ad !default;\n$state-info-bg:                  #d9edf7 !default;\n$state-info-border:              darken(adjust-hue($state-info-bg, -10), 7%) !default;\n\n\n// Tooltips\n// -------------------------\n$tooltip-max-width:           200px !default;\n$tooltip-color:               #fff !default;\n$tooltip-bg:                  #000 !default;\n\n$tooltip-arrow-width:         5px !default;\n$tooltip-arrow-color:         $tooltip-bg !default;\n\n\n// Popovers\n// -------------------------\n$popover-bg:                          #fff !default;\n$popover-max-width:                   276px !default;\n$popover-border-color:                rgba(0,0,0,.2) !default;\n$popover-fallback-border-color:       #ccc !default;\n\n$popover-title-bg:                    darken($popover-bg, 3%) !default;\n\n$popover-arrow-width:                 10px !default;\n$popover-arrow-color:                 #fff !default;\n\n$popover-arrow-outer-width:           ($popover-arrow-width + 1) !default;\n$popover-arrow-outer-color:           rgba(0,0,0,.25) !default;\n$popover-arrow-outer-fallback-color:  #999 !default;\n\n\n// Labels\n// -------------------------\n\n$label-default-bg:            $gray-light !default;\n$label-primary-bg:            $brand-primary !default;\n$label-success-bg:            $brand-success !default;\n$label-info-bg:               $brand-info !default;\n$label-warning-bg:            $brand-warning !default;\n$label-danger-bg:             $brand-danger !default;\n\n$label-color:                 #fff !default;\n$label-link-hover-color:      #fff !default;\n\n\n// Modals\n// -------------------------\n$modal-inner-padding:         20px !default;\n\n$modal-title-padding:         15px !default;\n$modal-title-line-height:     $line-height-base !default;\n\n$modal-content-bg:                             #fff !default;\n$modal-content-border-color:                   rgba(0,0,0,.2) !default;\n$modal-content-fallback-border-color:          #999 !default;\n\n$modal-backdrop-bg:           #000 !default;\n$modal-header-border-color:   #e5e5e5 !default;\n$modal-footer-border-color:   $modal-header-border-color !default;\n\n\n// Alerts\n// -------------------------\n$alert-padding:               15px !default;\n$alert-border-radius:         $border-radius-base !default;\n$alert-link-font-weight:      bold !default;\n\n$alert-success-bg:            $state-success-bg !default;\n$alert-success-text:          $state-success-text !default;\n$alert-success-border:        $state-success-border !default;\n\n$alert-info-bg:               $state-info-bg !default;\n$alert-info-text:             $state-info-text !default;\n$alert-info-border:           $state-info-border !default;\n\n$alert-warning-bg:            $state-warning-bg !default;\n$alert-warning-text:          $state-warning-text !default;\n$alert-warning-border:        $state-warning-border !default;\n\n$alert-danger-bg:             $state-danger-bg !default;\n$alert-danger-text:           $state-danger-text !default;\n$alert-danger-border:         $state-danger-border !default;\n\n\n// Progress bars\n// -------------------------\n$progress-bg:                 #f5f5f5 !default;\n$progress-bar-color:          #fff !default;\n\n$progress-bar-bg:             $brand-primary !default;\n$progress-bar-success-bg:     $brand-success !default;\n$progress-bar-warning-bg:     $brand-warning !default;\n$progress-bar-danger-bg:      $brand-danger !default;\n$progress-bar-info-bg:        $brand-info !default;\n\n\n// List group\n// -------------------------\n$list-group-bg:               #fff !default;\n$list-group-border:           #ddd !default;\n$list-group-border-radius:    $border-radius-base !default;\n\n$list-group-hover-bg:         #f5f5f5 !default;\n$list-group-active-color:     #fff !default;\n$list-group-active-bg:        $component-active-bg !default;\n$list-group-active-border:    $list-group-active-bg !default;\n\n$list-group-link-color:          #555 !default;\n$list-group-link-heading-color:  #333 !default;\n\n\n// Panels\n// -------------------------\n$panel-bg:                    #fff !default;\n$panel-inner-border:          #ddd !default;\n$panel-border-radius:         $border-radius-base !default;\n$panel-footer-bg:             #f5f5f5 !default;\n\n$panel-default-text:          $gray-dark !default;\n$panel-default-border:        #ddd !default;\n$panel-default-heading-bg:    #f5f5f5 !default;\n\n$panel-primary-text:          #fff !default;\n$panel-primary-border:        $brand-primary !default;\n$panel-primary-heading-bg:    $brand-primary !default;\n\n$panel-success-text:          $state-success-text !default;\n$panel-success-border:        $state-success-border !default;\n$panel-success-heading-bg:    $state-success-bg !default;\n\n$panel-warning-text:          $state-warning-text !default;\n$panel-warning-border:        $state-warning-border !default;\n$panel-warning-heading-bg:    $state-warning-bg !default;\n\n$panel-danger-text:           $state-danger-text !default;\n$panel-danger-border:         $state-danger-border !default;\n$panel-danger-heading-bg:     $state-danger-bg !default;\n\n$panel-info-text:             $state-info-text !default;\n$panel-info-border:           $state-info-border !default;\n$panel-info-heading-bg:       $state-info-bg !default;\n\n\n// Thumbnails\n// -------------------------\n$thumbnail-padding:           4px !default;\n$thumbnail-bg:                $body-bg !default;\n$thumbnail-border:            #ddd !default;\n$thumbnail-border-radius:     $border-radius-base !default;\n\n$thumbnail-caption-color:     $text-color !default;\n$thumbnail-caption-padding:   9px !default;\n\n\n// Wells\n// -------------------------\n$well-bg:                     #f5f5f5 !default;\n\n\n// Badges\n// -------------------------\n$badge-color:                 #fff !default;\n$badge-link-hover-color:      #fff !default;\n$badge-bg:                    $gray-light !default;\n\n$badge-active-color:          $link-color !default;\n$badge-active-bg:             #fff !default;\n\n$badge-font-weight:           bold !default;\n$badge-line-height:           1 !default;\n$badge-border-radius:         10px !default;\n\n\n// Breadcrumbs\n// -------------------------\n$breadcrumb-bg:               #f5f5f5 !default;\n$breadcrumb-color:            #ccc !default;\n$breadcrumb-active-color:     $gray-light !default;\n\n\n// Carousel\n// ------------------------\n\n$carousel-text-shadow:                        0 1px 2px rgba(0,0,0,.6) !default;\n\n$carousel-control-color:                      #fff !default;\n$carousel-control-width:                      15% !default;\n$carousel-control-opacity:                    .5 !default;\n$carousel-control-font-size:                  20px !default;\n\n$carousel-indicator-active-bg:                #fff !default;\n$carousel-indicator-border-color:             #fff !default;\n\n$carousel-caption-color:                      #fff !default;\n\n\n// Close\n// ------------------------\n$close-color:                 #000 !default;\n$close-font-weight:           bold !default;\n$close-text-shadow:           0 1px 0 #fff !default;\n\n\n// Code\n// ------------------------\n$code-color:                  #c7254e !default;\n$code-bg:                     #f9f2f4 !default;\n\n$pre-bg:                      #f5f5f5 !default;\n$pre-color:                   $gray-dark !default;\n$pre-border-color:            #ccc !default;\n$pre-scrollable-max-height:   340px !default;\n\n// Type\n// ------------------------\n$text-muted:                  $gray-light !default;\n$abbr-border-color:           $gray-light !default;\n$headings-small-color:        $gray-light !default;\n$blockquote-small-color:      $gray-light !default;\n$blockquote-border-color:     $gray-lighter !default;\n$page-header-border-color:    $gray-lighter !default;\n\n// Miscellaneous\n// -------------------------\n\n// Hr border color\n$hr-border:                   $gray-lighter !default;\n\n// Horizontal forms & lists\n$component-offset-horizontal: 180px !default;\n\n\n// Container sizes\n// --------------------------------------------------\n\n// Small screen / tablet\n$container-tablet:            ((720px + $grid-gutter-width)) !default;\n\n// Medium screen / desktop\n$container-desktop:           ((940px + $grid-gutter-width)) !default;\n\n// Large screen / wide desktop\n$container-lg-desktop:        ((1140px + $grid-gutter-width)) !default;\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/sass-bootstrap/lib/_wells.scss",
    "content": "//\n// Wells\n// --------------------------------------------------\n\n\n// Base class\n.well {\n  min-height: 20px;\n  padding: 19px;\n  margin-bottom: 20px;\n  background-color: $well-bg;\n  border: 1px solid darken($well-bg, 7%);\n  border-radius: $border-radius-base;\n  @include box-shadow(inset 0 1px 1px rgba(0,0,0,.05));\n  blockquote {\n    border-color: #ddd;\n    border-color: rgba(0,0,0,.15);\n  }\n}\n\n// Sizes\n.well-lg {\n  padding: 24px;\n  border-radius: $border-radius-large;\n}\n.well-sm {\n  padding: 9px;\n  border-radius: $border-radius-small;\n}\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/sass-bootstrap/lib/bootstrap.scss",
    "content": "/*!\n * Bootstrap v3.0.0\n *\n * Copyright 2013 Twitter, Inc\n * Licensed under the Apache License v2.0\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Designed and built with all the love in the world by @mdo and @fat.\n */\n\n// Core variables and mixins\n@import \"variables\";\n@import \"mixins\";\n\n// Reset\n@import \"normalize\";\n@import \"print\";\n\n// Core CSS\n@import \"scaffolding\";\n@import \"type\";\n@import \"code\";\n@import \"grid\";\n@import \"tables\";\n@import \"forms\";\n@import \"buttons\";\n\n// Components\n@import \"component-animations\";\n@import \"glyphicons\";\n@import \"dropdowns\";\n@import \"button-groups\";\n@import \"input-groups\";\n@import \"navs\";\n@import \"navbar\";\n@import \"breadcrumbs\";\n@import \"pagination\";\n@import \"pager\";\n@import \"labels\";\n@import \"badges\";\n@import \"jumbotron\";\n@import \"thumbnails\";\n@import \"alerts\";\n@import \"progress-bars\";\n@import \"media\";\n@import \"list-group\";\n@import \"panels\";\n@import \"wells\";\n@import \"close\";\n\n// Components w/ JavaScript\n@import \"modals\";\n@import \"tooltip\";\n@import \"popovers\";\n@import \"carousel\";\n\n// Utility classes\n@import \"utilities\";\n@import \"responsive-utilities\";\n"
  },
  {
    "path": "flowable-ui-web/admin/bower_components/sass-bootstrap/package.json",
    "content": "{\n    \"name\": \"bootstrap\"\n  , \"description\": \"Sleek, intuitive, and powerful front-end framework for faster and easier web development.\"\n  , \"version\": \"3.0.0\"\n  , \"keywords\": [\"bootstrap\", \"css\"]\n  , \"homepage\": \"http://twbs.github.com/bootstrap/\"\n  , \"author\": \"Twitter Inc.\"\n  , \"scripts\": { \"test\": \"grunt test\" }\n  , \"repository\": {\n      \"type\": \"git\"\n    , \"url\": \"https://github.com/twbs/bootstrap.git\"\n  }\n  , \"licenses\": [\n    {\n        \"type\": \"Apache-2.0\"\n      , \"url\": \"http://www.apache.org/licenses/LICENSE-2.0\"\n    }\n  ]\n  , \"devDependencies\": {\n      \"grunt\": \"~0.4.1\"\n    , \"grunt-contrib-clean\": \"~0.5.0\"\n    , \"grunt-contrib-connect\": \"~0.3.0\"\n    , \"grunt-contrib-concat\": \"~0.3.0\"\n    , \"grunt-contrib-copy\": \"~0.4.0\"\n    , \"grunt-contrib-jshint\": \"~0.6.0\"\n    , \"grunt-contrib-uglify\": \"~0.2.2\"\n    , \"grunt-contrib-qunit\": \"~0.2.2\"\n    , \"grunt-contrib-watch\": \"~0.5.1\"\n    , \"grunt-html-validation\": \"git://github.com/praveenvijayan/grunt-html-validation.git\"\n    , \"grunt-jekyll\": \"~0.3.8\"\n    , \"grunt-recess\": \"~0.3.3\"\n    , \"browserstack-runner\": \"~0.0.11\"\n  }\n}\n"
  },
  {
    "path": "flowable-ui-web/admin/browserconfig.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<browserconfig>\n  <msapplication>\n    <tile>\n      <square150x150logo src=\"images/mstile-150x150.png?v=Om5N75Y123\"/>\n      <TileColor>#da532c</TileColor>\n    </tile>\n  </msapplication>\n</browserconfig>\n"
  },
  {
    "path": "flowable-ui-web/admin/display/Polyline.js",
    "content": "/* Copyright 2005-2015 Alfresco Software, Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \n/**\n * Class to generate polyline\n *\n * @author Dmitry Farafonov\n */\n\nvar ANCHOR_TYPE= {\n\tmain: \"main\",\n\tmiddle: \"middle\",\n\tfirst: \"first\",\n\tlast: \"last\"\n};\n\nfunction Anchor(uuid, type, x, y) {\n\tthis.uuid = uuid;\n\tthis.x = x;\n\tthis.y = y;\n\tthis.type = (type == ANCHOR_TYPE.middle) ? ANCHOR_TYPE.middle : ANCHOR_TYPE.main;\n};\nAnchor.prototype = {\n\tuuid: null,\n\tx: 0,\n\ty: 0,\n\ttype: ANCHOR_TYPE.main,\n\tisFirst: false,\n\tisLast: false,\n\tndex: 0,\n\ttypeIndex: 0\n};\n\nfunction Polyline(uuid, points, strokeWidth, paper) {\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\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\n\tthis.anchors = [];\n\n\tif (strokeWidth) this.strokeWidth = strokeWidth;\n\n\tthis.paper = paper;\n\n\tthis.closePath = false;\n\n\tthis.init();\n};\n\nPolyline.prototype = {\n\tid: null,\n\tpoints: [],\n\tpath: [],\n\tanchors: [],\n\tstrokeWidth: 1,\n\tradius: 1,\n\tshowDetails: false,\n\tpaper: null,\n\telement: null,\n\tisDefaultConditionAvailable: false,\n\tclosePath: false,\n\n\tinit: function(points){\n\t\tvar linesCount = this.getLinesCount();\n\t\tif (linesCount < 1)\n\t\t\treturn;\n\n\t\tthis.normalizeCoordinates();\n\n\t\t// create anchors\n\n\t\tthis.pushAnchor(ANCHOR_TYPE.first, this.getLine(0).x1, this.getLine(0).y1);\n\n\t\tfor (var i = 1; i < linesCount; i++)\n\t\t{\n\t\t\tvar line1 = this.getLine(i-1);\n\t\t\tthis.pushAnchor(ANCHOR_TYPE.main,  line1.x2, line1.y2);\n\t\t}\n\n\t\tthis.pushAnchor(ANCHOR_TYPE.last, this.getLine(linesCount-1).x2, this.getLine(linesCount-1).y2);\n\n\t\tthis.rebuildPath();\n\t},\n\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\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\treturn Math.sqrt(Math.pow(this.getLineLengthX(i), 2) + Math.pow(this.getLineLengthY(i), 2));\n\t},\n\n\tgetAnchors: function(){\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\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\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\n\t\tvar anchor = new Anchor(this.id, ANCHOR_TYPE.main, x, y, index, typeIndex);\n\n\t\tthis.anchors.push(anchor);\n\t},\n\n\tgetAnchor: function(position){\n\t\treturn this.anchors[position];\n\t},\n\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\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\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\n\t\tthis.rebuildPath();\n\t},\n\n\trebuildPath: function(){\n\t\tvar path = [];\n\n\t\tfor(var i = 0; i < this.getAnchorsCount(); i++){\n\t\t\tvar anchor = this.getAnchor(i);\n\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\n\t\t\t// TODO: save previous points and calculate new path just if points are updated, and then save currents values as previous\n\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\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\n\t\t\t\tthis.isDefaultConditionAvailable = (this.isDefaultConditionAvailable || (i == 1 && AO > 10));\n\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\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\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\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\n\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\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\n\t\t\t\t\tzx=nextSrcX, zy=nextSrcY;\n\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}\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\n\t\t\tpath.push([pathType, targetX, targetY]);\n\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\n\t\tif (this.closePath)\n\t\t{\n\t\t\tpath.push([\"Z\"]);\n\t\t}\n\n\t\tthis.path = path;\n\t},\n\n\ttransform: function(transformation)\n\t{\n\t\tthis.element.transform(transformation);\n\t},\n\tattr: function(attrs)\n\t{\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\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\n\tthis.anchors = [];\n\n\tif (strokeWidth) this.strokeWidth = strokeWidth;\n\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\tfor(var i = 0; i < this.getAnchorsCount(); i++){\n\t\tvar anchor = this.getAnchor(i);\n\n\t\tvar pathType = \"\";\n\t\tif (i == 0)\n\t\t\tpathType = \"M\";\n\t\telse\n\t\t\tpathType = \"L\";\n\n\t\tvar targetX = anchor.x, targetY = anchor.y;\n\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\n\t\tpath.push([pathType, targetX, targetY]);\n\t}\n\tif (this.closePath)\n\t\tpath.push([\"Z\"]);\n\n\tthis.path = path;\n};\n"
  },
  {
    "path": "flowable-ui-web/admin/display/bpmn-draw.js",
    "content": "/* Copyright 2005-2015 Alfresco Software, Ltd.\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\nfunction _bpmnGetColor(element, defaultColor) {\n  var strokeColor;\n  if(element.current) {\n    strokeColor = CURRENT_COLOR;\n  } else if(element.completed) {\n    strokeColor = COMPLETED_COLOR;\n  } else {\n    strokeColor = defaultColor;\n  }\n  return strokeColor;\n}\n\nfunction _drawPool(pool, isMigrationModelElement, currentPaper)\n{\n\tvar rect = currentPaper.rect(pool.x, pool.y, pool.width, pool.height);\n\n\trect.attr({\"stroke-width\": 1,\n\t\t\"stroke\": MAIN_STROKE_COLOR,\n\t\t\"fill\": \"white\"\n \t});\n\n\tif (pool.name) {\n\t\tvar poolName = currentPaper.text(pool.x + 14, pool.y + (pool.height / 2), pool.name).attr({\n\t        \"text-anchor\" : \"middle\",\n\t        \"font-family\" : \"Arial\",\n\t        \"font-size\" : \"12\",\n\t        \"fill\" : MAIN_STROKE_COLOR\n\t  \t});\n\n\t\tpoolName.transform(\"r270\");\n\t}\n\n\tif (pool.lanes) {\n\t\tfor (var i = 0; i < pool.lanes.length; i++)\n\t\t{\n\t\t\tvar lane = pool.lanes[i];\n\t\t\t_drawLane(lane, isMigrationModelElement, currentPaper);\n\t\t}\n\t}\n}\n\nfunction _drawLane(lane, isMigrationModelElement, currentPaper)\n{\n\tvar rect = currentPaper.rect(lane.x, lane.y, lane.width, lane.height);\n\n\trect.attr({\"stroke-width\": 1,\n\t\t\"stroke\": MAIN_STROKE_COLOR,\n\t\t\"fill\": \"white\"\n \t});\n\n\tif (lane.name) {\n\t\tvar laneName = currentPaper.text(lane.x + 10, lane.y + (lane.height / 2), lane.name).attr({\n\t        \"text-anchor\" : \"middle\",\n\t        \"font-family\" : \"Arial\",\n\t        \"font-size\" : \"12\",\n\t        \"fill\" : MAIN_STROKE_COLOR\n\t  \t});\n\n\t\tlaneName.transform(\"r270\");\n\t}\n}\n\nfunction _drawSubProcess(element, isMigrationModelElement, currentPaper)\n{\n\tvar rect = currentPaper.rect(element.x, element.y, element.width, element.height, 4);\n\n\tvar strokeColor = _bpmnGetColor(element, MAIN_STROKE_COLOR);\n\n\trect.attr({\"stroke-width\": 1,\n\t\t\"stroke\": strokeColor,\n\t\t\"fill\": \"white\"\n \t});\n \t\n \tif (element.collapsed) {\n        if (element.name) {\n            this._drawMultilineText(element.name, element.x, element.y, element.width, element.height, \"middle\", \"middle\", 11,\n            _bpmnGetColor(element, TEXT_COLOR), currentPaper);\n        }\n\n        rect.click(function() {\n            _expandCollapsedElement(element);\n        });\n    }\n}\n\nfunction _drawEventSubProcess(element, isMigrationModelElement, currentPaper)\n{\n\tvar rect = currentPaper.rect(element.x, element.y, element.width, element.height, 4);\n\tvar strokeColor = _bpmnGetColor(element, MAIN_STROKE_COLOR);\n\n\trect.attr({\"stroke-width\": 2,\n\t\t\"stroke\": strokeColor,\n\t\t\"stroke-dasharray\": \".\",\n\t\t\"fill\": \"white\"\n \t});\n}\n\nfunction _drawStartEvent(element, isMigrationModelElement, currentPaper)\n{\n\tvar startEvent = _drawEvent(element, NORMAL_STROKE, 15, currentPaper);\n\tstartEvent.click(function() {\n\t\t_zoom(true);\n\t});\n\t_addHoverLogic(element, \"circle\", MAIN_STROKE_COLOR, isMigrationModelElement, currentPaper);\n}\n\nfunction _drawEndEvent(element, isMigrationModelElement, currentPaper)\n{\n\tvar endEvent = _drawEvent(element, ENDEVENT_STROKE, 14, currentPaper);\n\tendEvent.click(function() {\n\t\t_zoom(false);\n\t});\n\t_addHoverLogic(element, \"circle\", MAIN_STROKE_COLOR, isMigrationModelElement, currentPaper);\n}\n\nfunction _drawEvent(element, strokeWidth, radius, currentPaper)\n{\n\tvar x = element.x + (element.width / 2);\n\tvar y = element.y + (element.height / 2);\n\n\tvar circle = currentPaper.circle(x, y, radius);\n\n\tvar strokeColor = _bpmnGetColor(element, MAIN_STROKE_COLOR);\n\tcircle.attr({\"stroke-width\": strokeWidth,\n\t\t\"stroke\": strokeColor,\n\t\t\"fill\": \"#ffffff\"\n \t});\n\n\tcircle.id = element.id;\n\n\t_drawEventIcon(currentPaper, element);\n\n\treturn circle;\n}\n\nfunction _drawServiceTask(element, isMigrationModelElement, currentPaper)\n{\n\t_drawTask(element, currentPaper);\n\tif (element.taskType === \"mail\") {\n\t\t_drawSendTaskIcon(currentPaper, element.x - 4, element.y - 4, element);\n\t\t\n\t} else if (element.taskType === \"camel\") {\n        _drawCamelTaskIcon(currentPaper, element.x + 4, element.y + 4);\n        \n    } else if (element.taskType === \"mule\") {\n        _drawMuleTaskIcon(currentPaper, element.x + 4, element.y + 4);\n        \n    } else if (element.taskType === \"http\") {\n        _drawHttpTaskIcon(currentPaper, element.x + 4, element.y + 4);\n        \n    } else if (element.taskType === \"dmn\") {\n        _drawDecisionTaskIcon(currentPaper, element.x + 4, element.y + 4);\n        \n    } else if (element.taskType === \"shell\") {\n        _drawShellTaskIcon(currentPaper, element.x + 4, element.y + 4);\n        \n    } else if (element.stencilIconId) {\n\t\tcurrentPaper.image(\"../service/stencilitem/\" + element.stencilIconId + \"/icon\", element.x + 4, element.y + 4, 16, 16);\n\t\t\n\t} else {\n\t\t_drawServiceTaskIcon(currentPaper, element.x + 4, element.y + 4, element);\n\t}\n\t_addHoverLogic(element, \"rect\", ACTIVITY_STROKE_COLOR, isMigrationModelElement, currentPaper);\n}\n\nfunction _drawHttpServiceTask(element, isMigrationModelElement, currentPaper)\n{\n    _drawTask(element, currentPaper);\n    _drawHttpTaskIcon(currentPaper, element.x + 4, element.y + 4);\n    _addHoverLogic(element, \"rect\", ACTIVITY_STROKE_COLOR, isMigrationModelElement, currentPaper);\n}\n\nfunction _drawCallActivity(element, isMigrationModelElement, currentPaper)\n{\n  var width = element.width - (CALL_ACTIVITY_STROKE / 2);\n  var height = element.height - (CALL_ACTIVITY_STROKE / 2);\n\n  var rect = currentPaper.rect(element.x, element.y, width, height, 4);\n\n\n  var strokeColor = _bpmnGetColor(element, ACTIVITY_STROKE_COLOR);\n\n  rect.attr({\"stroke-width\": CALL_ACTIVITY_STROKE,\n    \"stroke\": strokeColor,\n    \"fill\": ACTIVITY_FILL_COLOR\n  });\n\n  rect.id = element.id;\n\n  if (element.name) {\n    this._drawMultilineText(element.name, element.x, element.y, element.width, element.height, \"middle\", \"middle\", 11, null, currentPaper);\n  }\n  _addHoverLogic(element, \"rect\", ACTIVITY_STROKE_COLOR, isMigrationModelElement, currentPaper);\n}\n\nfunction _drawScriptTask(element, isMigrationModelElement, currentPaper)\n{\n\t_drawTask(element, currentPaper);\n\t_drawScriptTaskIcon(currentPaper, element.x + 4, element.y + 4, element);\n\t_addHoverLogic(element, \"rect\", ACTIVITY_STROKE_COLOR, isMigrationModelElement, currentPaper);\n}\n\nfunction _drawUserTask(element, isMigrationModelElement, currentPaper)\n{\n\t_drawTask(element, currentPaper);\n\t_drawUserTaskIcon(currentPaper, element.x + 4, element.y + 4, element);\n\t_addHoverLogic(element, \"rect\", ACTIVITY_STROKE_COLOR, isMigrationModelElement, currentPaper);\n}\n\nfunction _drawBusinessRuleTask(element, isMigrationModelElement, currentPaper)\n{\n\t_drawTask(element, currentPaper);\n\t_drawBusinessRuleTaskIcon(currentPaper, element.x + 4, element.y + 4, element);\n\t_addHoverLogic(element, \"rect\", ACTIVITY_STROKE_COLOR, isMigrationModelElement, currentPaper);\n}\n\nfunction _drawManualTask(element, isMigrationModelElement, currentPaper)\n{\n\t_drawTask(element, currentPaper);\n\t_drawManualTaskIcon(currentPaper, element.x + 4, element.y + 4, element);\n\t_addHoverLogic(element, \"rect\", ACTIVITY_STROKE_COLOR, isMigrationModelElement, currentPaper);\n}\n\nfunction _drawReceiveTask(element, isMigrationModelElement, currentPaper)\n{\n\t_drawTask(element, currentPaper);\n\t_drawReceiveTaskIcon(currentPaper, element.x, element.y, element);\n\t_addHoverLogic(element, \"rect\", ACTIVITY_STROKE_COLOR, isMigrationModelElement, currentPaper);\n}\n\nfunction _drawTask(element, currentPaper)\n{\n\tvar width = element.width - (TASK_STROKE / 2);\n\tvar height = element.height - (TASK_STROKE / 2);\n\n\tvar rect = currentPaper.rect(element.x, element.y, width, height, 4);\n\n\n\tvar strokeColor = _bpmnGetColor(element, ACTIVITY_STROKE_COLOR);\n    var strokeWidth = element.current ? CURRENT_ACTIVITY_STROKE : TASK_STROKE;\n\trect.attr({\"stroke-width\": strokeWidth,\n\t\t\"stroke\": strokeColor,\n\t\t\"fill\": ACTIVITY_FILL_COLOR\n \t});\n\n\trect.id = element.id;\n\n\tif (element.name) {\n\t\tthis._drawMultilineText(element.name, element.x, element.y, element.width, element.height, \"middle\", \"middle\", 11,\n\t\t    _bpmnGetColor(element, TEXT_COLOR), currentPaper);\n\t}\n}\n\nfunction _drawExclusiveGateway(element, isMigrationModelElement, currentPaper)\n{\n\t_drawGateway(element, currentPaper);\n\tvar quarterWidth = element.width / 4;\n\tvar quarterHeight = element.height / 4;\n\n\tvar strokeColor = _bpmnGetColor(element, MAIN_STROKE_COLOR);\n\n\tvar iks = currentPaper.path(\n\t\t\"M\" + (element.x + quarterWidth + 3) + \" \" + (element.y + quarterHeight + 3) +\n\t\t\"L\" + (element.x + 3 * quarterWidth - 3) + \" \" + (element.y + 3 * quarterHeight - 3) +\n\t\t\"M\" + (element.x + quarterWidth + 3) + \" \" + (element.y + 3 * quarterHeight - 3) +\n\t\t\"L\" + (element.x + 3 * quarterWidth - 3) + \" \" + (element.y + quarterHeight + 3)\n\t);\n\tiks.attr({\"stroke-width\": 3, \"stroke\": strokeColor});\n\n\t_addHoverLogic(element, \"rhombus\", MAIN_STROKE_COLOR, isMigrationModelElement, currentPaper);\n}\n\nfunction _drawParallelGateway(element, isMigrationModelElement, currentPaper)\n{\n\t_drawGateway(element, currentPaper);\n\n\tvar strokeColor = _bpmnGetColor(element, MAIN_STROKE_COLOR);\n\n\tvar path1 = currentPaper.path(\"M 6.75,16 L 25.75,16 M 16,6.75 L 16,25.75\");\n\tpath1.attr({\n\t\t\"stroke-width\": 3,\n\t\t\"stroke\": strokeColor,\n\t\t\"fill\": \"none\"\n\t});\n\n\tpath1.transform(\"T\" + (element.x + 4) + \",\" + (element.y + 4));\n\n\t_addHoverLogic(element, \"rhombus\", MAIN_STROKE_COLOR, isMigrationModelElement, currentPaper);\n}\n\nfunction _drawInclusiveGateway(element, isMigrationModelElement, currentPaper)\n{\n\t_drawGateway(element, currentPaper);\n\n\tvar strokeColor = _bpmnGetColor(element, MAIN_STROKE_COLOR);\n\n\tvar circle1 = currentPaper.circle(element.x + (element.width / 2), element.y + (element.height / 2), 9.75);\n\tcircle1.attr({\n\t\t\"stroke-width\": 2.5,\n\t\t\"stroke\": strokeColor,\n\t\t\"fill\": \"none\"\n\t});\n\n\t_addHoverLogic(element, \"rhombus\", MAIN_STROKE_COLOR, isMigrationModelElement, currentPaper);\n}\n\nfunction _drawEventGateway(element, isMigrationModelElement, currentPaper)\n{\n\t_drawGateway(element, currentPaper);\n\n\tvar strokeColor = _bpmnGetColor(element, MAIN_STROKE_COLOR);\n\n\tvar circle1 = currentPaper.circle(element.x + (element.width / 2), element.y + (element.height / 2), 10.4);\n\tcircle1.attr({\n\t\t\"stroke-width\": 0.5,\n\t\t\"stroke\": strokeColor,\n\t\t\"fill\": \"none\"\n\t});\n\n\tvar circle2 = currentPaper.circle(element.x + (element.width / 2), element.y + (element.height / 2), 11.7);\n\tcircle2.attr({\n\t\t\"stroke-width\": 0.5,\n\t\t\"stroke\": strokeColor,\n\t\t\"fill\": \"none\"\n\t});\n\n\tvar path1 = currentPaper.path(\"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\tpath1.attr({\n\t\t\"stroke-width\": 1.39999998,\n\t\t\"stroke\": strokeColor,\n\t\t\"fill\": \"none\",\n\t\t\"stroke-linejoin\": \"bevel\"\n\t});\n\n\tpath1.transform(\"T\" + (element.x + 4) + \",\" + (element.y + 4));\n\n\t_addHoverLogic(element, \"rhombus\", MAIN_STROKE_COLOR, isMigrationModelElement, currentPaper);\n}\n\nfunction _drawGateway(element, currentPaper)\n{\n  var strokeColor = _bpmnGetColor(element, MAIN_STROKE_COLOR);\n\n\tvar rhombus = currentPaper.path(\"M\" + element.x + \" \" + (element.y + (element.height / 2)) +\n\t\t\"L\" + (element.x + (element.width / 2)) + \" \" + (element.y + element.height) +\n\t\t\"L\" + (element.x + element.width) + \" \" + (element.y + (element.height / 2)) +\n\t\t\"L\" + (element.x + (element.width / 2)) + \" \" + element.y + \"z\"\n\t);\n\n\trhombus.attr(\"stroke-width\", 2);\n\trhombus.attr(\"stroke\", strokeColor);\n\trhombus.attr({fill: \"#ffffff\"});\n\n\trhombus.id = element.id;\n\n\treturn rhombus;\n}\n\nfunction _drawBoundaryEvent(element, isMigrationModelElement, currentPaper)\n{\n\tvar x = element.x + (element.width / 2);\n\tvar y = element.y + (element.height / 2);\n\n\tvar circle = currentPaper.circle(x, y, 15);\n\n\tvar strokeColor = _bpmnGetColor(element, MAIN_STROKE_COLOR);\n\n\tcircle.attr({\"stroke-width\": 1,\n\t\t\"stroke\": strokeColor,\n\t\t\"fill\": \"white\"\n \t});\n\n\tvar innerCircle = currentPaper.circle(x, y, 12);\n\n\tinnerCircle.attr({\"stroke-width\": 1,\n\t\t\"stroke\": strokeColor,\n\t\t\"fill\": \"none\"\n \t});\n\n\t_drawEventIcon(currentPaper, element);\n\t_addHoverLogic(element, \"circle\", MAIN_STROKE_COLOR, isMigrationModelElement, currentPaper);\n\n\tcircle.id = element.id;\n\tinnerCircle.id = element.id + \"_inner\";\n}\n\nfunction _drawIntermediateCatchEvent(element, isMigrationModelElement, currentPaper)\n{\n\tvar x = element.x + (element.width / 2);\n\tvar y = element.y + (element.height / 2);\n\n\tvar circle = currentPaper.circle(x, y, 15);\n\n\tvar strokeColor = _bpmnGetColor(element, MAIN_STROKE_COLOR);\n\n\tcircle.attr({\"stroke-width\": 1,\n\t\t\"stroke\": strokeColor,\n\t\t\"fill\": \"white\"\n \t});\n\n\tvar innerCircle = currentPaper.circle(x, y, 12);\n\n\tinnerCircle.attr({\"stroke-width\": 1,\n\t\t\"stroke\": strokeColor,\n\t\t\"fill\": \"none\"\n \t});\n\n\t_drawEventIcon(currentPaper, element);\n\t_addHoverLogic(element, \"circle\", MAIN_STROKE_COLOR, isMigrationModelElement, currentPaper);\n\n\tcircle.id = element.id;\n\tinnerCircle.id = element.id + \"_inner\";\n}\n\nfunction _drawThrowEvent(element, isMigrationModelElement, currentPaper)\n{\n\tvar x = element.x + (element.width / 2);\n\tvar y = element.y + (element.height / 2);\n\n\tvar circle = currentPaper.circle(x, y, 15);\n\n\tvar strokeColor = _bpmnGetColor(element, MAIN_STROKE_COLOR);\n\n\tcircle.attr({\"stroke-width\": 1,\n\t\t\"stroke\": strokeColor,\n\t\t\"fill\": \"white\"\n \t});\n\n\tvar innerCircle = currentPaper.circle(x, y, 12);\n\n\tinnerCircle.attr({\"stroke-width\": 1,\n\t\t\"stroke\": strokeColor,\n\t\t\"fill\": \"none\"\n \t});\n\n\t_drawEventIcon(currentPaper, element);\n\t_addHoverLogic(element, \"circle\", MAIN_STROKE_COLOR, isMigrationModelElement, currentPaper);\n\n\tcircle.id = element.id;\n\tinnerCircle.id = element.id + \"_inner\";\n}\n\nfunction _drawMultilineText(text, x, y, boxWidth, boxHeight, horizontalAnchor, verticalAnchor, fontSize, color, currentPaper)\n{\n\tif (!text || text == \"\")\n\t{\n\t\treturn;\n\t}\n\n\tvar textBoxX=0, textBoxY;\n    var width = boxWidth - (2 * TEXT_PADDING);\n\n    if (horizontalAnchor === \"middle\")\n    {\n    \ttextBoxX = x + (boxWidth / 2);\n    }\n    else if (horizontalAnchor === \"start\")\n    {\n    \ttextBoxX = x;\n    }\n\n    textBoxY = y + (boxHeight / 2);\n\n    if(!color) {\n     color = TEXT_COLOR;\n    }\n \tvar t = currentPaper.text(textBoxX + TEXT_PADDING, textBoxY + TEXT_PADDING).attr({\n        \"text-anchor\" : horizontalAnchor,\n        \"font-family\" : \"Arial\",\n        \"font-size\" : fontSize,\n        \"fill\" : color\n  \t});\n\n    var abc = \"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ\";\n    t.attr({\n        \"text\" : abc\n    });\n    var letterWidth = t.getBBox().width / abc.length;\n\n    t.attr({\n        \"text\" : text\n    });\n    var removedLineBreaks = text.split(\"\\n\");\n    var x = 0, s = [];\n    for (var r = 0; r < removedLineBreaks.length; r++)\n    {\n  \t    var words = removedLineBreaks[r].split(\" \");\n  \t    for ( var i = 0; i < words.length; i++) {\n\n  \t        var l = words[i].length;\n  \t        if (x + (l * letterWidth) > width) {\n  \t            s.push(\"\\n\");\n  \t            x = 0;\n  \t        }\n  \t        x += l * letterWidth;\n  \t        s.push(words[i] + \" \");\n  \t    }\n\t  \ts.push(\"\\n\");\n        x = 0;\n    }\n    t.attr({\n    \t\"text\" : s.join(\"\")\n    });\n\n    if (verticalAnchor && verticalAnchor === \"top\")\n    {\n    \tt.attr({\"y\": y + (t.getBBox().height / 2)});\n    }\n}\n\nfunction _drawFlow(flow, currentPaper){\n\n\tvar polyline = new Polyline(flow.id, flow.waypoints, SEQUENCEFLOW_STROKE, currentPaper);\n\n\tvar strokeColor = _bpmnGetColor(flow, MAIN_STROKE_COLOR);\n\n\tpolyline.element = currentPaper.path(polyline.path);\n\tpolyline.element.attr({\"stroke-width\":SEQUENCEFLOW_STROKE});\n\tpolyline.element.attr({\"stroke\":strokeColor});\n\n\tpolyline.element.id = flow.id;\n\n\tvar lastLineIndex = polyline.getLinesCount() - 1;\n\tvar line = polyline.getLine(lastLineIndex);\n\n\tif (flow.type == \"connection\" && flow.conditions) {\n\t\tvar middleX = (line.x1 + line.x2) / 2;\n\t\tvar middleY = (line.y1 + line.y2) / 2;\n\t\tvar image = currentPaper.image(\"../editor/images/condition-flow.png\", middleX - 8, middleY - 8, 16, 16);\n\t}\n\n\tvar polylineInvisible = new Polyline(flow.id, flow.waypoints, SEQUENCEFLOW_STROKE, currentPaper);\n\n\tpolylineInvisible.element = currentPaper.path(polyline.path);\n\tpolylineInvisible.element.attr({\n\t\t\t\"opacity\": 0,\n\t\t\t\"stroke-width\": 8,\n            \"stroke\" : \"#000000\"\n\t});\n\n    if (flow.name) {\n        var firstLine = polyline.getLine(0);\n\n        var angle;\n        if (firstLine.x1 !== firstLine.x2) {\n            angle = Math.atan((firstLine.y2 - firstLine.y1) / (firstLine.x2 - firstLine.x1));\n        } else if (firstLine.y1 < firstLine.y2) {\n            angle = Math.PI / 2;\n        } else {\n            angle = -Math.PI / 2;\n        }\n        var flowName = currentPaper.text(firstLine.x1, firstLine.y1, flow.name).attr({\n            \"text-anchor\": \"middle\",\n            \"font-family\" : \"Arial\",\n            \"font-size\" : \"12\",\n            \"fill\" : \"#000000\"\n        });\n\n        var offsetX = (flowName.getBBox().width / 2 + 5);\n        var offsetY = -(flowName.getBBox().height / 2 + 5);\n\n        if (firstLine.x1 > firstLine.x2) {\n            offsetX = -offsetX;\n        }\n        var rotatedOffsetX = offsetX * Math.cos(angle) - offsetY * Math.sin(angle);\n        var rotatedOffsetY = offsetX * Math.sin(angle) + offsetY * Math.cos(angle);\n\n        flowName.attr({\n            x: firstLine.x1 + rotatedOffsetX,\n            y: firstLine.y1 + rotatedOffsetY\n        });\n\n        flowName.transform(\"r\" + ((angle) * 180) / Math.PI);\n    }\n\n    _showTip($(polylineInvisible.element.node), flow);\n\n\tpolylineInvisible.element.mouseover(function() {\n\t\tcurrentPaper.getById(polyline.element.id).attr({\"stroke\": HOVER_COLOR});\n\t});\n\n\tpolylineInvisible.element.mouseout(function() {\n\t\tcurrentPaper.getById(polyline.element.id).attr({\"stroke\":strokeColor});\n\t});\n\n\t_drawArrowHead(line, strokeColor, currentPaper);\n}\n\nfunction _drawArrowHead(line, color, currentPaper)\n{\n\tvar doubleArrowWidth = 2 * ARROW_WIDTH;\n\n\tvar arrowHead = currentPaper.path(\"M0 0L-\" + (ARROW_WIDTH / 2 + .5) + \" -\" + doubleArrowWidth + \"L\" + (ARROW_WIDTH/2 + .5) + \" -\" + doubleArrowWidth + \"z\");\n\n\t// anti smoothing\n\tif (this.strokeWidth%2 == 1)\n\t\tline.x2 += .5, line.y2 += .5;\n\n\tarrowHead.transform(\"t\" + line.x2 + \",\" + line.y2 + \"\");\n\tarrowHead.transform(\"...r\" + Raphael.deg(line.angle - Math.PI / 2) + \" \" + 0 + \" \" + 0);\n\n\tarrowHead.attr(\"fill\", color);\n\n\tarrowHead.attr(\"stroke-width\", SEQUENCEFLOW_STROKE);\n\tarrowHead.attr(\"stroke\", color);\n\n\treturn arrowHead;\n}\n"
  },
  {
    "path": "flowable-ui-web/admin/display/bpmn-icons.js",
    "content": "/* 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\nfunction _drawUserTaskIcon(paper, startX, startY, element)\n{\n\n  var color = _bpmnGetColor(element, \"#000000\");\n\tvar path1 = paper.path(\"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\tpath1.attr({\n\t\t\"opacity\": 1,\n\t\t\"stroke\": \"none\",\n\t\t\"fill\": color\n \t});\n\n\tvar userTaskIcon = paper.set();\n\tuserTaskIcon.push(path1);\n\n\tuserTaskIcon.transform(\"T\" + startX + \",\" + startY);\n}\n\nfunction _drawServiceTaskIcon(paper, startX, startY, element)\n{\n  var color = _bpmnGetColor(element, \"#000000\");\n\tvar path1 = paper.path(\"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\tpath1.attr({\n\t\t\"opacity\": 1,\n\t\t\"stroke\": \"none\",\n\t\t\"fill\": color\n \t});\n\n\tvar serviceTaskIcon = paper.set();\n\tserviceTaskIcon.push(path1);\n\n\tserviceTaskIcon.transform(\"T\" + startX + \",\" + startY);\n}\n\nfunction _drawScriptTaskIcon(paper, startX, startY, element)\n{\n  var color = _bpmnGetColor(element, \"#000000\");\n\tvar path1 = paper.path(\"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\tpath1.attr({\n\t\t\"opacity\": 1,\n\t\t\"stroke\": \"none\",\n\t\t\"fill\": color\n \t});\n\n\tvar scriptTaskIcon = paper.set();\n\tscriptTaskIcon.push(path1);\n\n\tscriptTaskIcon.transform(\"T\" + startX + \",\" + startY);\n}\n\nfunction _drawBusinessRuleTaskIcon(paper, startX, startY, element)\n{\n  var color = _bpmnGetColor(element, \"#000000\");\n\tvar rect1 = paper.rect(0, 0, 22, 4);\n\trect1.attr({\n\t\t\"stroke\": \"#000000\",\n\t\t\"fill\": color\n \t});\n\n\tvar rect2 = paper.rect(0, 4, 22, 12);\n\trect2.attr({\n\t\t\"stroke\": \"#000000\",\n\t\t\"fill\": \"none\"\n \t});\n\n\tvar path1 = paper.path(\"M 0 10 L 22 10\");\n\tpath1.attr({\n\t\t\"stroke\": \"#000000\",\n\t\t\"fill\": \"none\"\n \t});\n\n\tvar path2 = paper.path(\"M 7 4 L 7 16\");\n\tpath2.attr({\n\t\t\"stroke\": \"#000000\",\n\t\t\"fill\": \"none\"\n \t});\n\n\tvar businessRuleTaskIcon = paper.set();\n\tbusinessRuleTaskIcon.push(rect1, rect2, path1, path2);\n\n\tbusinessRuleTaskIcon.transform(\"S0.7,0.7,0,0 T\" + startX + \",\" + startY);\n}\n\nfunction _drawSendTaskIcon(paper, startX, startY, element)\n{\n  var color = _bpmnGetColor(element, \"#000000\");\n\tvar path1 = paper.path(\"M8,11 L8,21 L24,21 L24,11 L16,17z\");\n\tpath1.attr({\n\t\t\"stroke\": \"white\",\n\t\t\"fill\": color\n \t});\n\n\tvar path2 = paper.path(\"M7,10 L16,17 L25 10z6\");\n\tpath2.attr({\n\t\t\"stroke\": \"white\",\n\t\t\"fill\": color\n \t});\n\n\tvar sendTaskIcon = paper.set();\n\tsendTaskIcon.push(path1, path2);\n\n\tsendTaskIcon.transform(\"T\" + startX + \",\" + startY);\n}\n\nfunction _drawManualTaskIcon(paper, startX, startY, element)\n{\n  var color = _bpmnGetColor(element, \"#000000\");\n\tvar path1 = paper.path(\"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\tpath1.attr({\n\t\t\"opacity\": 1,\n\t\t\"stroke\": \"none\",\n\t\t\"fill\": color\n \t});\n\n\tvar manualTaskIcon = paper.set();\n\tmanualTaskIcon.push(path1);\n\n\tmanualTaskIcon.transform(\"T\" + startX + \",\" + startY);\n}\n\nfunction _drawReceiveTaskIcon(paper, startX, startY, element)\n{\n  var color = _bpmnGetColor(element, \"#000000\");\n\tvar path = paper.path(\"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\tpath.attr({\n\t\t\"opacity\": 1,\n\t\t\"stroke\": \"none\",\n\t\t\"fill\": color\n \t});\n\n\tstartX += 4;\n\tstartY += 2;\n\n\tpath.transform(\"T\" + startX + \",\" + startY);\n\n}\n\nfunction _drawCamelTaskIcon(paper, startX, startY)\n{\n    var path = paper.path(\"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    path.attr({\n        \"opacity\": 1,\n        \"stroke\": \"none\",\n        \"fill\": \"#000000\"\n    });\n\n    startX += 4;\n    startY += 2;\n\n    path.transform(\"T\" + startX + \",\" + startY);\n\n}\n\nfunction _drawHttpTaskIcon(paper, startX, startY)\n{\n    var path = paper.path(\"m 16.704699,5.9229055 q 0.358098,0 0.608767,0.2506681 0.250669,0.250668 0.250669,0.6087677 0,0.3580997 -0.250669,0.6087677 -0.250669,0.2506679 -0.608767,0.2506679 -0.358098,0 -0.608767,-0.2506679 -0.250669,-0.250668 -0.250669,-0.6087677 0,-0.3580997 0.250669,-0.6087677 0.250669,-0.2506681 0.608767,-0.2506681 z m 2.578308,-2.0053502 q -2.229162,0 -3.854034,0.6759125 -1.624871,0.6759067 -3.227361,2.2694472 -0.716197,0.725146 -1.575633,1.7457293 L 7.2329969,8.7876913 Q 7.0897576,8.8055849 7.000233,8.9309334 L 4.9948821,12.368677 q -0.035811,0.06267 -0.035811,0.143242 0,0.107426 0.080572,0.205905 l 0.5729577,0.572957 q 0.125334,0.116384 0.2864786,0.07162 l 2.4708789,-0.760963 2.5156417,2.515645 -0.76096,2.470876 q -0.009,0.02687 -0.009,0.08057 0,0.125338 0.08058,0.205905 l 0.572957,0.572958 q 0.170096,0.152194 0.349146,0.04476 l 3.437744,-2.005351 q 0.125335,-0.08953 0.143239,-0.232763 l 0.17905,-3.392986 q 1.02058,-0.859435 1.745729,-1.575629 1.67411,-1.6830612 2.309735,-3.2049805 0.635625,-1.5219191 0.635625,-3.8585111 0,-0.1253369 -0.08505,-0.2148575 -0.08505,-0.089526 -0.201431,-0.089526 z\");\n    path.attr({\n        \"opacity\": 1,\n        \"stroke\": \"none\",\n        \"fill\": \"#000000\"\n    });\n\n    startX += -2;\n    startY += -2;\n\n    path.transform(\"T\" + startX + \",\" + startY);\n\n}\n\nfunction _drawShellTaskIcon(paper, startX, startY)\n{\n    var path = paper.path(\"m 1,2 0,14 16,0 0,-14 z m 1.4,3 12.7,0 0,10 -12.7,0 z\");\n    path.attr({\n        \"opacity\": 1,\n        \"stroke\": \"none\",\n        \"fill\": \"#000000\"\n    });\n    var text = paper.text(3, 9, \">_\").attr({\n        \"font-size\": \"5px\",\n        \"fill\": \"#000000\"\n    });\n\n    startY += -2;\n    text.transform(\"T\" + startX + \",\" + startY);\n    startX += -2;\n    path.transform(\"T\" + startX + \",\" + startY);\n}\n\nfunction _drawDecisionTaskIcon(paper, startX, startY)\n{\n    var path = paper.path(\"m 1,2 0,14 16,0 0,-14 z m 1.9,2.4000386 3.7,0 0,2.7999224 -3.7,0 z m 4.36364,0 3.7,0 0,2.7999224 -3.7,0 z m 4.36364,0 3.7,0 0,2.7999224 -3.7,0 z m -8.67364,3.9 3.7,0 0,2.7999224 -3.7,0 z m 4.36364,0 3.7,0 0,2.7999224 -3.7,0 z m 4.36364,0 3.7,0 0,2.7999224 -3.7,0 z m -8.67364,3.9 3.7,0 0,2.7999224 -3.7,0 z m 4.36364,0 3.7,0 0,2.7999224 -3.7,0 z m 4.36364,0 3.7,0 0,2.7999224 -3.7,0 z\");\n    path.attr({\n        \"opacity\": 1,\n        \"stroke\": \"none\",\n        \"fill\": \"#000000\"\n    });\n\n    startX += -2;\n    startY += -2;\n\n    path.transform(\"T\" + startX + \",\" + startY);\n\n}\n\nfunction _drawMuleTaskIcon(paper, startX, startY)\n{\n    var path = paper.path(\"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    path.attr({\n        \"opacity\": 1,\n        \"stroke\": \"none\",\n        \"fill\": \"#000000\"\n    });\n\n    startX += 4;\n    startY += 2;\n\n    path.transform(\"T\" + startX + \",\" + startY);\n\n}\n\nfunction _drawEventIcon(paper, element)\n{\n\tif (element.eventDefinition && element.eventDefinition.type)\n\t{\n\t\tif (\"timer\" === element.eventDefinition.type)\n\t\t{\n\t\t\t_drawTimerIcon(paper, element);\n\t\t}\n\t\telse if (\"error\" === element.eventDefinition.type)\n\t\t{\n\t\t\t_drawErrorIcon(paper, element);\n\t\t}\n\t\telse if (\"signal\" === element.eventDefinition.type)\n\t\t{\n\t\t\t_drawSignalIcon(paper, element);\n\t\t}\n\t\telse if (\"message\" === element.eventDefinition.type)\n\t\t{\n\t\t\t_drawMessageIcon(paper, element);\n\t\t}\n\t}\n}\n\nfunction _drawTimerIcon(paper, element)\n{\n\tvar x = element.x + (element.width / 2);\n\tvar y = element.y + (element.height / 2);\n\n\tvar strokeColor = _bpmnGetColor(element, MAIN_STROKE_COLOR);\n\n\tvar circle = paper.circle(x, y, 10);\n\n\tcircle.attr({\"stroke-width\": 1,\n\t\t\"stroke\": strokeColor,\n\t\t\"fill\": \"none\"\n \t});\n\n\tvar path = paper.path(\"M 16 6 L 16 9 M 21 7 L 19.5 10 M 25 11 L 22 12.5 M 26 16 L 23 16 \" +\n\t\t\"M 25 21 L 22 19.5 M 21 25 L 19.5 22 M 16 26 L 16 23 M 11 25 L 12.5 22 M 7 21 L 10 19.5 \" +\n\t\t\"M 6 16 L 9 16 M 7 11 L 10 12.5 M 11 7 L 12.5 10 M 18 9 L 16 16 L 20 16\");\n\tpath.attr({\n\t\t\"stroke\": strokeColor,\n\t\t\"stroke-width\": 1,\n\t\t\"fill\": \"none\"\n \t});\n\tpath.transform(\"T\" + (element.x - 1) + \",\" + (element.y - 1));\n\treturn path;\n}\n\nfunction _drawErrorIcon(paper, element)\n{\n\tvar path = paper.path(\"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\n\tvar strokeColor = _bpmnGetColor(element, MAIN_STROKE_COLOR);\n\n\tvar fill = \"none\";\n\tvar x = element.x - 1;\n\tvar y = element.y - 1;\n\tif (element.type === \"EndEvent\")\n\t{\n\t\tfill = strokeColor;\n\t\tx -= 1;\n\t\ty -= 1;\n\t}\n\n\n\tpath.attr({\n\t\t\"stroke\": strokeColor,\n\t\t\"stroke-width\": 1,\n\t\t\"fill\": fill\n \t});\n\n\tpath.transform(\"T\" + x + \",\" + y);\n\treturn path;\n}\n\nfunction _drawSignalIcon(paper, element)\n{\n  var strokeColor = _bpmnGetColor(element, MAIN_STROKE_COLOR);\n\n\tvar fill = \"none\";\n\tif (element.type === \"ThrowEvent\")\n\t{\n\t\tfill = strokeColor;\n\t}\n\n\tvar path = paper.path(\"M 8.7124971,21.247342 L 23.333334,21.247342 L 16.022915,8.5759512 L 8.7124971,21.247342 z\");\n\tpath.attr({\n\t\t\"stroke\": strokeColor,\n\t\t\"stroke-width\": 1,\n\t\t\"fill\": fill\n \t});\n\tpath.transform(\"T\" + (element.x - 1) + \",\" + (element.y - 1));\n\treturn path;\n}\n\nfunction _drawMessageIcon(paper, element)\n{\n  var strokeColor = _bpmnGetColor(element, MAIN_STROKE_COLOR);\n\n\tvar path = paper.path(\"M8,11 L8,21 L24,21 L24,11z M8,11 L16,17 L24,11\");\n\tpath.attr({\n\t\t\"stroke\": strokeColor,\n\t\t\"stroke-width\": 1,\n\t\t\"fill\": \"none\"\n \t});\n\tpath.transform(\"T\" + (element.x - 1) + \",\" + (element.y - 1));\n\treturn path;\n}\n"
  },
  {
    "path": "flowable-ui-web/admin/display/displaymodel.css",
    "content": "div[class*='ui-tooltip-kisbpm-'] {\n    background-color: #ffffff;\n    border-color: #2674aa;\n    color: #4a4a4a;\n    font-family: 'Open Sans', sans-serif;\n    font-size: 12px;\n}\n\ndiv[class*='ui-tooltip-kisbpm-'] .qtip-content {\n  color: #4a4a4a;\n  background-color: #ffffff;\n  font-family: 'Open Sans', sans-serif;\n  font-size: 12px;\n  padding-top: 10px;\n}\n\n.ui-tooltip-kisbpm-bpmn .qtip-titlebar {\n  color: #ffffff;\n  font-size: 12px;\n  background: #2674aa;\n  font-weight: bolder;\n}\n\n.ui-tooltip-kisbpm-bpmn .qtip-tip {\n  background-color: #2674aa;\n}\n"
  },
  {
    "path": "flowable-ui-web/admin/display/displaymodel.html",
    "content": "<html>  \n    <head>  \n        <title>BPMN 2.0 display</title>\n        <link type=\"text/css\" rel=\"stylesheet\" href=\"display/jquery.qtip.min.css\" />\n        <link type=\"text/css\" rel=\"stylesheet\" href=\"display/jquery.growl.css\" />\n        <link type=\"text/css\" rel=\"stylesheet\" href=\"display/jquery-confirm.min.css\" />\n        <link type=\"text/css\" rel=\"stylesheet\" href=\"display/displaymodel.css\" />\n        <script type=\"text/javascript\" src=\"display/jquery-1.12.4.min.js\"></script>\n        <script type=\"text/javascript\" src=\"display/jquery.qtip.min.js\"></script>\n        <script type=\"text/javascript\" src=\"display/jquery.growl.js\"></script>\n        <script type=\"text/javascript\" src=\"display/jquery-confirm.min.js\"></script>\n        <script type=\"text/javascript\" src=\"display/raphael.min.js\"></script>\n        <script type=\"text/javascript\" src=\"display/bpmn-draw.js\"></script>\n        <script type=\"text/javascript\" src=\"display/bpmn-icons.js\"></script>\n        <script type=\"text/javascript\" src=\"display/Polyline.js\"></script>\n        <script type=\"text/javascript\">\n        \tvar NORMAL_STROKE = 2;\n        \tvar SEQUENCEFLOW_STROKE = 2;\n        \tvar TASK_STROKE = 2;\n        \tvar CALL_ACTIVITY_STROKE = 4;\n        \tvar ENDEVENT_STROKE = 4;\n        \tvar CURRENT_ACTIVITY_STROKE = 4;\n        \t\n        \tvar COMPLETED_COLOR= \"#2674aa\";\n        \tvar TEXT_COLOR= \"#373e48\";\n        \tvar CURRENT_COLOR= \"#66AA66\";\n        \tvar HOVER_COLOR= \"#d5bc01\";\n        \tvar ACTIVITY_STROKE_COLOR = \"#000000\";\n        \tvar ACTIVITY_FILL_COLOR = \"#ffffff\";\n        \tvar MAIN_STROKE_COLOR = \"#585858\";\n        \t\n        \tvar TEXT_PADDING = 3;\n        \tvar ARROW_WIDTH = 6;\n        \tvar MARKER_WIDTH = 12;\n        \t\n        \tvar TASK_FONT = {font: \"11px Arial\", opacity: 1, fill: Raphael.rgb(0, 0, 0)};\n        \t\n        \t// icons\n        \tvar ICON_SIZE = 16;\n        \tvar ICON_PADDING = 4;\n        \t\n        \tvar INITIAL_CANVAS_WIDTH;\n        \tvar INITIAL_CANVAS_HEIGHT;\n        \t\n        \tvar paper;\n        \tvar migrationPaper;\n        \tvar viewBox;\n        \tvar viewBoxWidth;\n        \tvar viewBoxHeight;\n        \t\n        \tvar canvasWidth;\n        \tvar canvasHeight;\n        \t\n        \tvar definitionId = $('#bpmnModel').attr('data-definition-id');\n            var instanceId = $('#bpmnModel').attr('data-instance-id');\n            var historyInstanceId = $('#bpmnModel').attr('data-history-id');\n            var serverId = $('#bpmnModel').attr('data-server-id');\n        \t\n        \tvar migrationDefinitionId = $('#targetModel').attr('data-migration-definition-id');\n         \n            var elementsAdded = new Array();\n            var elementsRemoved = new Array();\n            var changeStateStartElementIds = new Array();\n            var changeStateStartElements = new Array();\n            var changeStateStartGlowElements = new Array();\n            var changeStateEndElementIds = new Array();\n            var changeStateEndElements = new Array();\n            var changeStateEndGlowElements = new Array();\n            \n            var migrationMappedElements = new Array();\n            var migrationMappedElementsText = new Array();\n            \n            var collapsedItemNavigation = new Array();\n            var bpmnData;\n            var migrationData;\n        \t\n        \tfunction _showTip(htmlNode, element) {\n        \t    if (migrationDefinitionId && migrationDefinitionId.length > 0) return;\n        \t\tvar documentation = \"\";\n        \t\tif (element.name && element.name.length > 0) {\n        \t\t\tdocumentation += \"<b>Name</b>: <i>\" + element.name + \"</i><br/><br/>\";\n        \t\t}\n        \t\t\n        \t\tvar text;\n        \t\tif (element.name && element.name.length > 0) {\n        \t\t\ttext = element.name;\n        \t\t} else {\n        \t\t\ttext = element.id;\n        \t\t}\n        \t\t\n        \t\thtmlNode.qtip({ \n                \tcontent: {\n                  \t\ttext: documentation,\n                  \t\ttitle: {\n                \t  \t\ttext: text\n                  \t\t}\n                \t},\n\t                position: {\n\t                  my: 'top left',\n\t                  at: 'bottom center',\n\t                  viewport: $(window)\n\t                },\n\t                hide: {\n\t                  fixed: true, delay: 100,\n\t                  event: 'click mouseleave'\n\t                },\n\t                style: {\n\t                \tclasses: 'ui-tooltip-kisbpm-bpmn'\n\t                }\n              });\n          \t}\n          \t\n          \tfunction _expandCollapsedElement(element) {\n                if (bpmnData.collapsed) {\n                    for (var i = 0; i < bpmnData.collapsed.length; i++) {\n                        var collapsedItem = bpmnData.collapsed[i];\n                        if (element.id == collapsedItem.id) {\n                            paper.clear();\n                            \n                            var modelElements = collapsedItem.elements;\n                            for (var i = 0; i < modelElements.length; i++) {\n                                var subElement = modelElements[i];\n                                var drawFunction = eval(\"_draw\" + subElement.type);\n                                drawFunction(subElement);\n                            }\n                            \n                            if (collapsedItem.flows) {\n                                for (var i = 0; i < collapsedItem.flows.length; i++) {\n                                    var subFlow = collapsedItem.flows[i];\n                                    _drawFlow(subFlow);\n                                }\n                            }\n                            \n                            var collapsedName;\n                            if (element.name) {\n                                collapsedName = element.name;\n                            } else {\n                                collapsedName = 'sub process ' + element.id;\n                            }\n                            \n                            collapsedItemNavigation.push({\n                                \"id\": element.id,\n                                \"name\": collapsedName\n                            });\n                            \n                            _buildNavigationTree();\n                            \n                            break;\n                        }\n                    }\n                }\n            }\n            \n            function _navigateTo(elementId) {\n                var modelElements = undefined;\n                var modelFlows = undefined;\n                newCollapsedItemNavigation = new Array();\n                \n                if (elementId == 'FLOWABLE_ROOT_PROCESS') {\n                    modelElements = bpmnData.elements;\n                    modelFlows = bpmnData.flows;\n                    \n                } else {\n                \n                    for (var i = 0; i < bpmnData.collapsed.length; i++) {\n                        var collapsedItem = bpmnData.collapsed[i];\n                        \n                        var collapsedName = undefined;\n                        for (var j = 0; j < collapsedItemNavigation.length; j++) {\n                            if (elementId == collapsedItemNavigation[j].id) {\n                                collapsedName = collapsedItemNavigation[j].name;\n                                break;\n                            }\n                        }\n                    \n                        if (!collapsedName) {\n                            continue;\n                        }\n                        \n                        newCollapsedItemNavigation.push({\n                            \"id\": collapsedItem.id,\n                            \"name\": collapsedName\n                        });\n                        \n                        if (elementId == collapsedItem.id) {\n                            modelElements = collapsedItem.elements;\n                            modelFlows = collapsedItem.flows;\n                            break;\n                        }\n                    }\n                }\n                \n                if (modelElements) {\n                    paper.clear();\n                                \n                    for (var i = 0; i < modelElements.length; i++) {\n                        var subElement = modelElements[i];\n                        var drawFunction = eval(\"_draw\" + subElement.type);\n                        drawFunction(subElement);\n                    }\n                    \n                    if (modelFlows) {\n                        for (var i = 0; i < modelFlows.length; i++) {\n                            var subFlow = modelFlows[i];\n                            _drawFlow(subFlow);\n                        }\n                    }\n                    \n                    collapsedItemNavigation = newCollapsedItemNavigation;\n                    \n                    _buildNavigationTree();\n                }\n            }\n            \n            function _buildNavigationTree() {\n                var navigationUrl = '| <a href=\"javascript:_navigateTo(\\'FLOWABLE_ROOT_PROCESS\\')\">Root</a>';\n                            \n                for (var i = 0; i < collapsedItemNavigation.length; i++) {\n                    navigationUrl += ' > <a href=\"javascript:_navigateTo(\\'' + collapsedItemNavigation[i].id + '\\')\">' + \n                        collapsedItemNavigation[i].name + '</a>';\n                }\n                \n                $('#navigationTree').html(navigationUrl);\n            }\n        \t\n        \tfunction _addHoverLogic(element, type, defaultColor, isMigrationModelElement, currentPaper) {\n        \t    var strokeColor = _bpmnGetColor(element, defaultColor);\n                var topBodyRect;\n                if (type === \"rect\") {\n                    topBodyRect = currentPaper.rect(element.x, element.y, element.width, element.height);\n                    \n                } else if (type === \"circle\") {\n                    var x = element.x + (element.width / 2);\n                    var y = element.y + (element.height / 2);\n                    topBodyRect = currentPaper.circle(x, y, 15);\n                    \n                } else if (type === \"rhombus\") {\n                    topBodyRect = currentPaper.path(\"M\" + element.x + \" \" + (element.y + (element.height / 2)) + \n                        \"L\" + (element.x + (element.width / 2)) + \" \" + (element.y + element.height) + \n                        \"L\" + (element.x + element.width) + \" \" + (element.y + (element.height / 2)) +\n                        \"L\" + (element.x + (element.width / 2)) + \" \" + element.y + \"z\"\n                    );\n                }\n                \n        \t    if (isMigrationModelElement) {\n        \t    \n        \t        topBodyRect.attr({\n                        \"opacity\": 0,\n                        \"stroke\" : \"none\",\n                        \"fill\" : \"#ffffff\"\n                    });\n        \t    \n        \t        topBodyRect.click(function() {\n                        var endElementIndex = $.inArray(element.id, changeStateEndElementIds);\n                        if (endElementIndex >= 0) {\n                        \n                            var glowElement = changeStateEndGlowElements[endElementIndex];\n                            glowElement.remove();\n                            \n                            changeStateEndGlowElements.splice(endElementIndex, 1);\n                            changeStateEndElementIds.splice(endElementIndex, 1);\n                            changeStateEndElements.splice(endElementIndex, 1);\n                            \n                        } else {\n                            var endGlowElement = topBodyRect.glow({'color': 'red'});\n                            changeStateEndGlowElements.push(endGlowElement);\n                            changeStateEndElementIds.push(element.id);\n                            changeStateEndElements.push(element);\n                        }\n                        \n                        if (changeStateStartElements.length > 0 && changeStateEndElements.length > 0) {\n                           $('#addMappingButton').show();\n    \n                        } else {\n                           $('#addMappingButton').hide();\n                        }\n                    });\n        \t    \n        \t    } else {\n            \t\tvar opacity = 0;\n            \t\tvar fillColor = \"#ffffff\";\n            \t\tif ($.inArray(element.id, elementsAdded) >= 0) {\n            \t\t\topacity = 0.2;\n                \t\tfillColor = \"green\";\n            \t\t}\n            \t\t\n            \t\tif ($.inArray(element.id, elementsRemoved) >= 0) {\n            \t\t\topacity = 0.2;\n                \t\tfillColor = \"red\";\n            \t\t}\n            \t\t\n              \t\ttopBodyRect.attr({\n              \t\t\t\"opacity\": opacity,\n    \t                \"stroke\" : \"none\",\n    \t                \"fill\" : fillColor\n    \t          \t});\n              \t\t_showTip($(topBodyRect.node), element);\n              \t\t\n              \t\ttopBodyRect.click(function() {\n              \t\t    if (migrationDefinitionId && migrationDefinitionId.length > 0) {\n              \t\t        var startElementIndex = $.inArray(element.id, changeStateStartElementIds);\n                            if (startElementIndex >= 0) {\n                            \n                                var glowElement = changeStateStartGlowElements[startElementIndex];\n                                glowElement.remove();\n                                \n                                changeStateStartGlowElements.splice(startElementIndex, 1);\n                                changeStateStartElementIds.splice(startElementIndex, 1);\n                                changeStateStartElements.splice(startElementIndex, 1);\n                                \n                            } else {\n                                var startGlowElement = topBodyRect.glow({'color': 'blue'});\n                                changeStateStartGlowElements.push(startGlowElement);\n                                changeStateStartElementIds.push(element.id);\n                                changeStateStartElements.push(element);\n                            }\n                            \n                            if (changeStateStartElements.length > 0 && changeStateEndElements.length > 0) {\n                               $('#addMappingButton').show();\n        \n                            } else {\n                               $('#addMappingButton').hide();\n                            }\n                            \n              \t\t    } else {\n                            var startElementIndex = $.inArray(element.id, changeStateStartElementIds);\n                            var endElementIndex = $.inArray(element.id, changeStateEndElementIds);\n                            if (startElementIndex >= 0) {\n                                \n                                var glowElement = changeStateStartGlowElements[startElementIndex];\n                                glowElement.remove();\n                                \n                                changeStateStartGlowElements.splice(startElementIndex, 1);\n                                changeStateStartElementIds.splice(startElementIndex, 1);\n                                changeStateStartElements.splice(startElementIndex, 1);\n                                \n                            } else if (endElementIndex >= 0) {\n                            \n                                var glowElement = changeStateEndGlowElements[endElementIndex];\n                                glowElement.remove();\n                                \n                                changeStateEndGlowElements.splice(endElementIndex, 1);\n                                changeStateEndElementIds.splice(endElementIndex, 1);\n                                changeStateEndElements.splice(endElementIndex, 1);\n                                \n                            } else {\n                                if (element.current) {\n                                   var startGlowElement = topBodyRect.glow({'color': 'blue'});\n                                   changeStateStartGlowElements.push(startGlowElement);\n                                   changeStateStartElementIds.push(element.id);\n                                   changeStateStartElements.push(element);\n                                   \n                                } else {\n                                   var endGlowElement = topBodyRect.glow({'color': 'red'});\n                                   changeStateEndGlowElements.push(endGlowElement);\n                                   changeStateEndElementIds.push(element.id);\n                                   changeStateEndElements.push(element);\n                                }\n                            }\n                            \n                            if (changeStateStartElements.length > 0 && changeStateEndElements.length > 0) {\n                               $('#changeStateButton').show();\n                            } else {\n                               $('#changeStateButton').hide();\n                            }\n                        }\n                    });\n          \t\t}\n          \t\t\n          \t\ttopBodyRect.mouseover(function() {\n          \t\t\tcurrentPaper.getById(element.id).attr({\"stroke\": HOVER_COLOR});\n          \t\t});\n          \t\t\n          \t\ttopBodyRect.mouseout(function() {\n          \t\t\tcurrentPaper.getById(element.id).attr({\"stroke\": strokeColor});\n          \t\t});\n        \t}\n        \t\n        \tfunction _zoom(zoomIn)\n        \t{\n        \t\tvar tmpCanvasWidth, tmpCanvasHeight;\n                if (zoomIn) {\n                \ttmpCanvasWidth = canvasWidth * (1.0/0.90);\n                \ttmpCanvasHeight = canvasHeight * (1.0/0.90);\n                } else {\n                \ttmpCanvasWidth = canvasWidth * (1.0/1.10);\n                \ttmpCanvasHeight = canvasHeight * (1.0/1.10);\n                }\n                \n                if (tmpCanvasWidth != canvasWidth || tmpCanvasHeight != canvasHeight) {\n                \tcanvasWidth = tmpCanvasWidth;\n                \tcanvasHeight = tmpCanvasHeight;\n                \tpaper.setSize(canvasWidth, canvasHeight);\n                }\n        \t}\n        \t\n        \tfunction _showProcessDiagram() {\n        \t    var request;\n\t        \tif (historyInstanceId != null) {\n\t        \t   request = $.ajax({\n                        type: 'get',\n                        url: './app/rest/admin/process-instances/' + historyInstanceId + '/history-model-json?processDefinitionId=' + definitionId + '&nocaching=' + new Date().getTime()\n                    });\n                    \n\t        \t} else if (instanceId != null) {\n\t\t\t\t\trequest = $.ajax({\n\t\t\t\t\t    type: 'get',\n\t\t\t\t\t    url: './app/rest/admin/process-instances/' + instanceId + '/model-json?processDefinitionId=' + definitionId + '&nocaching=' + new Date().getTime()\n\t\t\t\t\t});\n\t\t\t\t\t\n\t        \t} else {\n\t\t\t\t\trequest = $.ajax({\n\t\t\t\t\t    type: 'get',\n\t\t\t\t\t    url: './app/rest/admin/process-definitions/' + definitionId + '/model-json?nocaching=' + new Date().getTime()\n\t\t\t\t\t});\n\t        \t}\n\t\n\t\t\t\trequest.success(function(data, textStatus, jqXHR) {\n\t\t\t\t\t\n\t\t\t\t\tif (!data.elements || data.elements.length == 0) return;\n\t\t\t\t\t\n\t\t\t\t\tINITIAL_CANVAS_WIDTH = data.diagramWidth + 20;\n\t\t\t\t\tINITIAL_CANVAS_HEIGHT = data.diagramHeight + 50;\n\t\t\t\t\tcanvasWidth = INITIAL_CANVAS_WIDTH;\n\t\t\t\t\tcanvasHeight = INITIAL_CANVAS_HEIGHT;\n\t\t\t\t\tviewBoxWidth = INITIAL_CANVAS_WIDTH;\n\t\t\t\t\tviewBoxHeight = INITIAL_CANVAS_HEIGHT;\n\t\t\t\t\t\n\t\t\t\t\tvar x = 0;\n\t\t\t\t\tif ($(window).width() > canvasWidth) {\n\t\t\t\t\t\tx = ($(window).width() - canvasWidth) / 2 - (data.diagramBeginX / 2);\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\tvar canvasValue = 'bpmnModel';\n\t\t\t\t\t\n\t\t\t\t\t$('#' + canvasValue).width(INITIAL_CANVAS_WIDTH);\n\t\t\t\t\t$('#' + canvasValue).height(INITIAL_CANVAS_HEIGHT);\n\t\t\t\t\tpaper = Raphael(document.getElementById(canvasValue), canvasWidth, canvasHeight);\n\t\t\t\t\tpaper.setViewBox(0, 0, viewBoxWidth, viewBoxHeight, false);\n\t          \t\tpaper.renderfix();\n\t          \t\t\n\t          \t\tif (data.pools) {\n\t          \t\t\tfor (var i = 0; i < data.pools.length; i++) {\n\t\t\t\t\t    \tvar pool = data.pools[i];\n\t\t\t\t\t    \t_drawPool(pool, false, paper);\n\t\t\t\t\t    }\n\t          \t\t}\n\t          \t\t\n\t\t\t\t    var modelElements = data.elements;\n\t\t\t\t    for (var i = 0; i < modelElements.length; i++) {\n\t\t\t\t    \tvar element = modelElements[i];\n\t\t\t\t    \ttry {\n\t\t\t\t    \t\t//console.log(element.type);\n\t\t\t\t    \t\tvar drawFunction = eval(\"_draw\" + element.type);\n\t\t\t\t    \t\tdrawFunction(element, false, paper);\n\t\t\t\t    \t} catch (err) {\n\t\t\t\t\t\t\tconsole.warn(err);\n\t\t\t\t\t\t}\n\t\t\t\t    }\n\t\t\t\t    \n\t\t\t\t    if (data.flows) {\n\t\t\t\t\t    for (var i = 0; i < data.flows.length; i++) {\n\t\t\t\t\t    \tvar flow = data.flows[i];\n\t\t\t\t\t    \t_drawFlow(flow, paper);\n\t\t\t\t\t    }\n\t\t\t\t    }\n\t\t\t\t    \n\t\t\t\t    bpmnData = data;\n\t\t\t\t});\n\t\n\t\t\t\trequest.error(function(jqXHR, textStatus, errorThrown) {\n\t\t\t\t    alert(\"error\");\n\t\t\t\t});\n\t\t\t\t\n\t\t\t\tif (migrationDefinitionId && migrationDefinitionId.length > 0) {\n                  migrationRequest = $.ajax({\n                        type: 'get',\n                        url: './app/rest/admin/process-definitions/' + migrationDefinitionId + '/model-json?nocaching=' + new Date().getTime()\n                  });\n                  \n                  migrationRequest.success(function(data, textStatus, jqXHR) {\n                    \n                    if (!data.elements || data.elements.length == 0) return;\n                    \n                    INITIAL_CANVAS_WIDTH = data.diagramWidth + 20;\n                    INITIAL_CANVAS_HEIGHT = data.diagramHeight + 50;\n                    canvasWidth = INITIAL_CANVAS_WIDTH;\n                    canvasHeight = INITIAL_CANVAS_HEIGHT;\n                    viewBoxWidth = INITIAL_CANVAS_WIDTH;\n                    viewBoxHeight = INITIAL_CANVAS_HEIGHT;\n                    \n                    var x = 0;\n                    if ($(window).width() > canvasWidth) {\n                        x = ($(window).width() - canvasWidth) / 2 - (data.diagramBeginX / 2);\n                    }\n                    \n                    var canvasValue = 'targetModel';\n                    \n                    $('#' + canvasValue).width(INITIAL_CANVAS_WIDTH);\n                    $('#' + canvasValue).height(INITIAL_CANVAS_HEIGHT);\n                    migrationPaper = Raphael(document.getElementById(canvasValue), canvasWidth, canvasHeight);\n                    migrationPaper.setViewBox(0, 0, viewBoxWidth, viewBoxHeight, false);\n                    migrationPaper.renderfix();\n                    \n                    if (data.pools) {\n                        for (var i = 0; i < data.pools.length; i++) {\n                            var pool = data.pools[i];\n                            _drawPool(pool, true, migrationPaper);\n                        }\n                    }\n                    \n                    var modelElements = data.elements;\n                    for (var i = 0; i < modelElements.length; i++) {\n                        var element = modelElements[i];\n                        try {\n                            var drawFunction = eval(\"_draw\" + element.type);\n                            drawFunction(element, true, migrationPaper);\n                        } catch (err) {\n                            console.warn(err);\n                        }\n                    }\n                    \n                    if (data.flows) {\n                        for (var i = 0; i < data.flows.length; i++) {\n                            var flow = data.flows[i];\n                            _drawFlow(flow, migrationPaper);\n                        }\n                    }\n                    \n                    migrationData = data;\n                  });\n                }\n\t\t\t}\n\t\t\t\n\t\t\t$(document).ready(function () {\n\t\t\t     $('#changeStateButton').on('click', function(e) {\n                    e.preventDefault();\n                    \n                    var startElementText = '';\n                    for (var i = 0; i < changeStateStartElements.length; i++) {\n                        if (startElementText.length > 0) {\n                            startElementText += ', ';\n                        }\n                        startElementText += changeStateStartElements[i].name\n                    }\n                    \n                    var endElementText = '';\n                    for (var i = 0; i < changeStateEndElements.length; i++) {\n                        if (endElementText.length > 0) {\n                            endElementText += ', ';\n                        }\n                        endElementText += changeStateEndElements[i].name\n                    }\n                    \n                    $.confirm({\n                        title: 'Change current activity?',\n                        content: 'Are you sure you want to move the current state from (' + \n                            startElementText + ') to (' + endElementText + ')',\n                        buttons: {\n                            confirm: function () {\n                                $.ajax({\n                                    type: 'post',\n                                    url: './app/rest/admin/process-instances/' + instanceId + '/change-state',\n                                    contentType: 'application/json; charset=utf-8',\n                                    data: JSON.stringify({\n                                        cancelActivityIds: changeStateStartElementIds,\n                                        startActivityIds: changeStateEndElementIds\n                                    }),\n                                    success: function() {\n                                        paper.clear();\n                                        $('#changeStateButton').hide();\n                                        _showProcessDiagram();\n                                    }\n                                });\n                            },\n                            cancel: function () {\n                                \n                            }\n                        }\n                    });\n                 });\n                 \n                 $('#addMappingButton').on('click', function(e) {\n                    e.preventDefault();\n                    \n                    var fromActivityIds = new Array();\n                    var startElementText = '';\n                    for (var i = 0; i < changeStateStartElements.length; i++) {\n                        if (startElementText.length > 0) {\n                            startElementText += ', ';\n                        }\n                        \n                        startElementText += changeStateStartElements[i].name;\n                        fromActivityIds.push(changeStateStartElements[i].id);\n                    }\n                    \n                    var toActivityIds = new Array();\n                    var endElementText = '';\n                    for (var i = 0; i < changeStateEndElements.length; i++) {\n                        if (endElementText.length > 0) {\n                            endElementText += ', ';\n                        }\n                        endElementText += changeStateEndElements[i].name\n                        toActivityIds.push(changeStateEndElements[i].id);\n                    }\n                    \n                    migrationMappedElements.push({\n                        fromActivityIds: fromActivityIds,\n                        toActivityIds: toActivityIds\n                    });\n                    \n                    migrationMappedElementsText.push({\n                        startElementText: startElementText,\n                        endElementText: endElementText\n                    });\n                    \n                    var mappingValuesText = '';\n                    var counter = 1;\n                    for (var i = 0; i < migrationMappedElementsText.length; i++) {\n                        if (mappingValuesText.length > 0) {\n                            mappingValuesText += '  -  ';\n                        }\n                        mappingValuesText += 'Mapping ' + counter + ' from (' + migrationMappedElementsText[i].startElementText + ') to (' + \n                            migrationMappedElementsText[i].endElementText + ')';\n                        \n                        counter++;\n                    }\n                    $('#currentMappingValues').text(mappingValuesText);\n                    \n                    $('#executeMigrationDocument').show();\n                    $('#addMappingButton').hide();\n                 });\n                 \n                 $('#executeMigrationDocument').on('click', function(e) {\n                    e.preventDefault();\n                    \n                    var migrationDocumentPayload = {\n                        toProcessDefinitionId: migrationDefinitionId\n                    };\n                    \n                    var mappingPayload = new Array();\n                    for (var i = 0; i < migrationMappedElements.length; i++) {\n                        var mappedElement = migrationMappedElements[i];\n                        var mappingValue = {};\n                        if (mappedElement.fromActivityIds.length == 1) {\n                            mappingValue.fromActivityId = mappedElement.fromActivityIds[0];\n                        } else {\n                            mappingValue.fromActivityIds = mappedElement.fromActivityIds;\n                        }\n                        \n                        if (mappedElement.toActivityIds.length == 1) {\n                            mappingValue.toActivityId = mappedElement.toActivityIds[0];\n                        } else {\n                            mappingValue.toActivityIds = mappedElement.toActivityIds;\n                        }\n                        \n                        mappingPayload.push(mappingValue);\n                    }\n                    \n                    migrationDocumentPayload.activityMappings = mappingPayload;\n                    \n                    $.confirm({\n                        title: 'Migrate process instance',\n                        content: 'Are you sure you want to migrate the process instance with the defined mappings',\n                        buttons: {\n                            confirm: function () {\n                                $.ajax({\n                                    type: 'post',\n                                    url: './app/rest/admin/process-instances/' + instanceId + '/migrate',\n                                    contentType: 'application/json; charset=utf-8',\n                                    data: JSON.stringify(migrationDocumentPayload),\n                                    success: function() {\n                                        paper.clear();\n                                        migrationPaper.clear();\n                                        $('#targetModel').removeAttr('data-migration-definition-id');\n                                        definitionId = migrationDefinitionId;\n                                        migrationDefinitionId = undefined;\n                                        migrationMappedElementsText = new Array();\n                                        migrationMappedElements = new Array();\n                                        $('#targetModel').hide();\n                                        $('#migrationDivider').hide();\n                                        $('#executeMigrationDocument').hide();\n                                        $('#currentMappingValues').hide();\n                                        _showProcessDiagram();\n                                    }\n                                });\n                            },\n                            cancel: function () {\n                                \n                            }\n                        }\n                    });\n                 });\n\t\t\t     \n\t\t\t});\n\t\t\t\n\t\t\telementsAdded = new Array();\n            elementsRemoved = new Array();\n            changeStateStartElementIds = new Array();\n            changeStateStartElements = new Array();\n            changeStateStartGlowElements = new Array();\n            changeStateEndElementIds = new Array();\n            changeStateEndElements = new Array();\n            changeStateEndGlowElements = new Array();\n            \n            migrationMappedElements = new Array();\n            migrationMappedElementsText = new Array();\n            \n            _showProcessDiagram();\n\t\t\t\n\t\t</script>\n    </head>\n</html>"
  },
  {
    "path": "flowable-ui-web/admin/display/jquery.growl.css",
    "content": "/* jQuery Growl\n * Copyright 2015 Kevin Sylvestre\n * 1.3.2\n */\n#growls {\n  z-index: 50000;\n  position: fixed; }\n  #growls.default {\n    top: 10px;\n    right: 10px; }\n  #growls.tl {\n    top: 10px;\n    left: 10px; }\n  #growls.tr {\n    top: 10px;\n    right: 10px; }\n  #growls.bl {\n    bottom: 10px;\n    left: 10px; }\n  #growls.br {\n    bottom: 10px;\n    right: 10px; }\n  #growls.tc {\n    top: 10px;\n    right: 10px;\n    left: 10px; }\n  #growls.bc {\n    bottom: 10px;\n    right: 10px;\n    left: 10px; }\n  #growls.tc .growl, #growls.bc .growl {\n    margin-left: auto;\n    margin-right: auto; }\n\n.growl {\n  opacity: 0.8;\n  filter: alpha(opacity=80);\n  position: relative;\n  border-radius: 4px;\n  -webkit-transition: all 0.4s ease-in-out;\n  -moz-transition: all 0.4s ease-in-out;\n  transition: all 0.4s ease-in-out; }\n  .growl.growl-incoming {\n    opacity: 0;\n    filter: alpha(opacity=0); }\n  .growl.growl-outgoing {\n    opacity: 0;\n    filter: alpha(opacity=0); }\n  .growl.growl-small {\n    width: 200px;\n    padding: 5px;\n    margin: 5px; }\n  .growl.growl-medium {\n    width: 250px;\n    padding: 10px;\n    margin: 10px; }\n  .growl.growl-large {\n    width: 300px;\n    padding: 15px;\n    margin: 15px; }\n  .growl.growl-default {\n    color: #FFF;\n    background: #7f8c8d; }\n  .growl.growl-error {\n    color: #FFF;\n    background: #C0392B; }\n  .growl.growl-notice {\n    color: #FFF;\n    background: #2ECC71; }\n  .growl.growl-warning {\n    color: #FFF;\n    background: #F39C12; }\n  .growl .growl-close {\n    cursor: pointer;\n    float: right;\n    font-size: 14px;\n    line-height: 18px;\n    font-weight: normal;\n    font-family: helvetica, verdana, sans-serif; }\n  .growl .growl-title {\n    font-size: 18px;\n    line-height: 24px; }\n  .growl .growl-message {\n    font-size: 14px;\n    line-height: 18px; }\n"
  },
  {
    "path": "flowable-ui-web/admin/display/jquery.growl.js",
    "content": "// Generated by CoffeeScript 1.10.0\n\n/*\njQuery Growl\nCopyright 2015 Kevin Sylvestre\n1.3.2\n */\n\n(function() {\n  \"use strict\";\n  var $, Animation, Growl,\n    bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };\n\n  $ = jQuery;\n\n  Animation = (function() {\n    function Animation() {}\n\n    Animation.transitions = {\n      \"webkitTransition\": \"webkitTransitionEnd\",\n      \"mozTransition\": \"mozTransitionEnd\",\n      \"oTransition\": \"oTransitionEnd\",\n      \"transition\": \"transitionend\"\n    };\n\n    Animation.transition = function($el) {\n      var el, ref, result, type;\n      el = $el[0];\n      ref = this.transitions;\n      for (type in ref) {\n        result = ref[type];\n        if (el.style[type] != null) {\n          return result;\n        }\n      }\n    };\n\n    return Animation;\n\n  })();\n\n  Growl = (function() {\n    Growl.settings = {\n      namespace: 'growl',\n      duration: 3200,\n      close: \"&#215;\",\n      location: \"default\",\n      style: \"default\",\n      size: \"medium\",\n      delayOnHover: true\n    };\n\n    Growl.growl = function(settings) {\n      if (settings == null) {\n        settings = {};\n      }\n      this.initialize();\n      return new Growl(settings);\n    };\n\n    Growl.initialize = function() {\n      return $(\"body:not(:has(#growls))\").append('<div id=\"growls\" />');\n    };\n\n    function Growl(settings) {\n      if (settings == null) {\n        settings = {};\n      }\n      this.container = bind(this.container, this);\n      this.content = bind(this.content, this);\n      this.html = bind(this.html, this);\n      this.$growl = bind(this.$growl, this);\n      this.$growls = bind(this.$growls, this);\n      this.animate = bind(this.animate, this);\n      this.remove = bind(this.remove, this);\n      this.dismiss = bind(this.dismiss, this);\n      this.present = bind(this.present, this);\n      this.waitAndDismiss = bind(this.waitAndDismiss, this);\n      this.cycle = bind(this.cycle, this);\n      this.close = bind(this.close, this);\n      this.click = bind(this.click, this);\n      this.mouseLeave = bind(this.mouseLeave, this);\n      this.mouseEnter = bind(this.mouseEnter, this);\n      this.unbind = bind(this.unbind, this);\n      this.bind = bind(this.bind, this);\n      this.render = bind(this.render, this);\n      this.settings = $.extend({}, Growl.settings, settings);\n      this.$growls().attr('class', this.settings.location);\n      this.render();\n    }\n\n    Growl.prototype.render = function() {\n      var $growl;\n      $growl = this.$growl();\n      this.$growls().append($growl);\n      if (this.settings.fixed) {\n        this.present();\n      } else {\n        this.cycle();\n      }\n    };\n\n    Growl.prototype.bind = function($growl) {\n      if ($growl == null) {\n        $growl = this.$growl();\n      }\n      $growl.on(\"click\", this.click);\n      if (this.settings.delayOnHover) {\n        $growl.on(\"mouseenter\", this.mouseEnter);\n        $growl.on(\"mouseleave\", this.mouseLeave);\n      }\n      return $growl.on(\"contextmenu\", this.close).find(\".\" + this.settings.namespace + \"-close\").on(\"click\", this.close);\n    };\n\n    Growl.prototype.unbind = function($growl) {\n      if ($growl == null) {\n        $growl = this.$growl();\n      }\n      $growl.off(\"click\", this.click);\n      if (this.settings.delayOnHover) {\n        $growl.off(\"mouseenter\", this.mouseEnter);\n        $growl.off(\"mouseleave\", this.mouseLeave);\n      }\n      return $growl.off(\"contextmenu\", this.close).find(\".\" + this.settings.namespace + \"-close\").off(\"click\", this.close);\n    };\n\n    Growl.prototype.mouseEnter = function(event) {\n      var $growl;\n      $growl = this.$growl();\n      return $growl.stop(true, true);\n    };\n\n    Growl.prototype.mouseLeave = function(event) {\n      return this.waitAndDismiss();\n    };\n\n    Growl.prototype.click = function(event) {\n      if (this.settings.url != null) {\n        event.preventDefault();\n        event.stopPropagation();\n        return window.open(this.settings.url);\n      }\n    };\n\n    Growl.prototype.close = function(event) {\n      var $growl;\n      event.preventDefault();\n      event.stopPropagation();\n      $growl = this.$growl();\n      return $growl.stop().queue(this.dismiss).queue(this.remove);\n    };\n\n    Growl.prototype.cycle = function() {\n      var $growl;\n      $growl = this.$growl();\n      return $growl.queue(this.present).queue(this.waitAndDismiss());\n    };\n\n    Growl.prototype.waitAndDismiss = function() {\n      var $growl;\n      $growl = this.$growl();\n      return $growl.delay(this.settings.duration).queue(this.dismiss).queue(this.remove);\n    };\n\n    Growl.prototype.present = function(callback) {\n      var $growl;\n      $growl = this.$growl();\n      this.bind($growl);\n      return this.animate($growl, this.settings.namespace + \"-incoming\", 'out', callback);\n    };\n\n    Growl.prototype.dismiss = function(callback) {\n      var $growl;\n      $growl = this.$growl();\n      this.unbind($growl);\n      return this.animate($growl, this.settings.namespace + \"-outgoing\", 'in', callback);\n    };\n\n    Growl.prototype.remove = function(callback) {\n      this.$growl().remove();\n      return typeof callback === \"function\" ? callback() : void 0;\n    };\n\n    Growl.prototype.animate = function($element, name, direction, callback) {\n      var transition;\n      if (direction == null) {\n        direction = 'in';\n      }\n      transition = Animation.transition($element);\n      $element[direction === 'in' ? 'removeClass' : 'addClass'](name);\n      $element.offset().position;\n      $element[direction === 'in' ? 'addClass' : 'removeClass'](name);\n      if (callback == null) {\n        return;\n      }\n      if (transition != null) {\n        $element.one(transition, callback);\n      } else {\n        callback();\n      }\n    };\n\n    Growl.prototype.$growls = function() {\n      return this.$_growls != null ? this.$_growls : this.$_growls = $('#growls');\n    };\n\n    Growl.prototype.$growl = function() {\n      return this.$_growl != null ? this.$_growl : this.$_growl = $(this.html());\n    };\n\n    Growl.prototype.html = function() {\n      return this.container(this.content());\n    };\n\n    Growl.prototype.content = function() {\n      return \"<div class='\" + this.settings.namespace + \"-close'>\" + this.settings.close + \"</div>\\n<div class='\" + this.settings.namespace + \"-title'>\" + this.settings.title + \"</div>\\n<div class='\" + this.settings.namespace + \"-message'>\" + this.settings.message + \"</div>\";\n    };\n\n    Growl.prototype.container = function(content) {\n      return \"<div class='\" + this.settings.namespace + \" \" + this.settings.namespace + \"-\" + this.settings.style + \" \" + this.settings.namespace + \"-\" + this.settings.size + \"'>\\n  \" + content + \"\\n</div>\";\n    };\n\n    return Growl;\n\n  })();\n\n  this.Growl = Growl;\n\n  $.growl = function(options) {\n    if (options == null) {\n      options = {};\n    }\n    return Growl.growl(options);\n  };\n\n  $.growl.error = function(options) {\n    var settings;\n    if (options == null) {\n      options = {};\n    }\n    settings = {\n      title: \"Error!\",\n      style: \"error\"\n    };\n    return $.growl($.extend(settings, options));\n  };\n\n  $.growl.notice = function(options) {\n    var settings;\n    if (options == null) {\n      options = {};\n    }\n    settings = {\n      title: \"Notice!\",\n      style: \"notice\"\n    };\n    return $.growl($.extend(settings, options));\n  };\n\n  $.growl.warning = function(options) {\n    var settings;\n    if (options == null) {\n      options = {};\n    }\n    settings = {\n      title: \"Warning!\",\n      style: \"warning\"\n    };\n    return $.growl($.extend(settings, options));\n  };\n\n}).call(this);\n"
  },
  {
    "path": "flowable-ui-web/admin/display-cmmn/cmmn-draw.js",
    "content": "/* 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\nfunction _cmmnGetColor(element, defaultColor)\n{\n    var strokeColor;\n    if(element.current) {\n        strokeColor = CURRENT_COLOR;\n    } else if(element.completed) {\n        strokeColor = COMPLETED_COLOR;\n    } else {\n        strokeColor = defaultColor;\n    }\n    return strokeColor;\n}\n\nfunction _drawPlanModel(planModel)\n{\n\tvar rect = paper.rect(planModel.x, planModel.y, planModel.width, planModel.height);\n\n\trect.attr({\"stroke-width\": 1,\n\t\t\"stroke\": \"#000000\",\n\t\t\"fill\": \"white\"\n \t});\n\n\tif (planModel.name)\n\t{\n\t\tvar planModelName = paper.text(planModel.x + 14, planModel.y + (planModel.height / 2), planModel.name).attr({\n\t        \"text-anchor\" : \"middle\",\n\t        \"font-family\" : \"Arial\",\n\t        \"font-size\" : \"12\",\n\t        \"fill\" : \"#000000\"\n\t  \t});\n\n\t\tplanModelName.transform(\"r270\");\n\t}\n}\n\nfunction _drawSubProcess(element)\n{\n\tvar rect = paper.rect(element.x, element.y, element.width, element.height, 4);\n\n\tvar strokeColor = _cmmnGetColor(element, MAIN_STROKE_COLOR);\n\n\trect.attr({\"stroke-width\": 1,\n\t\t\"stroke\": strokeColor,\n\t\t\"fill\": \"white\"\n \t});\n}\n\nfunction _drawVariableServiceTaskIcon(element)\n{\n\t_drawTask(element);\n\tif (element.taskType === \"mail\")\n\t{\n\t\t_drawSendTaskIcon(paper, element.x + 4, element.y + 4);\n\t}\n\telse if (element.taskType === \"camel\")\n\t{\n\t\t_drawCamelTaskIcon(paper, element.x + 4, element.y + 4);\n\t}\n\telse if (element.taskType === \"mule\")\n\t{\n\t\t_drawMuleTaskIcon(paper, element.x + 4, element.y + 4);\n\t}\n    else if (element.taskType === \"http\")\n    {\n        _drawHttpTaskIcon(paper, element.x + 4, element.y + 4);\n    }\n\telse if (element.stencilIconId)\n\t{\n\t\tpaper.image(\"../service/stencilitem/\" + element.stencilIconId + \"/icon\", element.x + 4, element.y + 4, 16, 16);\n\t}\n\telse\n\t{\n\t\t_drawServiceTaskIcon(paper, element.x + 4, element.y + 4);\n\t}\n\t_addHoverLogic(element, \"rect\", ACTIVITY_STROKE_COLOR);\n}\n\nfunction _drawHttpServiceTask(element)\n{\n    _drawTask(element);\n    _drawHttpTaskIcon(paper, element.x + 4, element.y + 4);\n    _addHoverLogic(element, \"rect\", ACTIVITY_STROKE_COLOR);\n}\n\nfunction _drawHumanTask(element)\n{\n\t_drawTask(element);\n\t_drawHumanTaskIcon(paper, element.x + 4, element.y + 4);\n\t_addHoverLogic(element, \"rect\", ACTIVITY_STROKE_COLOR);\n}\n\nfunction _drawCaseTask(element)\n{\n    _drawTask(element);\n    _drawCaseTaskIcon(paper, element.x + 1, element.y + 1);\n    _addHoverLogic(element, \"rect\", ACTIVITY_STROKE_COLOR);\n}\n\nfunction _drawProcessTask(element)\n{\n    _drawTask(element);\n    _drawProcessTaskIcon(paper, element.x + 1, element.y + 1);\n    _addHoverLogic(element, \"rect\", ACTIVITY_STROKE_COLOR);\n}\n\nfunction _drawScriptTaskIcon(paper, startX, startY)\n{\n\tvar path1 = paper.path(\"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\tpath1.attr({\n\t\t\"opacity\": 1,\n\t\t\"stroke\": \"none\",\n\t\t\"fill\": \"#72a7d0\"\n \t});\n\n\tvar scriptTaskIcon = paper.set();\n\tscriptTaskIcon.push(path1);\n\n\tscriptTaskIcon.transform(\"T\" + startX + \",\" + startY);\n}\n\nfunction _drawScriptServiceTask(element)\n{\n\t_drawTask(element);\n\t_drawScriptTaskIcon(paper, element.x + 4, element.y + 4);\n\t_addHoverLogic(element, \"rect\", ACTIVITY_STROKE_COLOR);\n}\n\nfunction _drawDecisionTask(element)\n{\n    _drawTask(element);\n    _drawDecisionTaskIcon(paper, element.x + 1, element.y + 1);\n    _addHoverLogic(element, \"rect\", ACTIVITY_STROKE_COLOR);\n}\n\nfunction _drawServiceTask(element)\n{\n    _drawTask(element);\n    _drawVariableServiceTaskIcon(element);\n    _addHoverLogic(element, \"rect\", ACTIVITY_STROKE_COLOR);\n}\n\nfunction _drawTask(element)\n{\n    var rectAttrs = {};\n\n    // Stroke\n    var strokeColor = _cmmnGetColor(element, ACTIVITY_STROKE_COLOR);\n    rectAttrs['stroke'] = strokeColor;\n\n    var strokeWidth;\n    if (strokeColor === ACTIVITY_STROKE_COLOR) {\n        strokeWidth = TASK_STROKE;\n    } else {\n        strokeWidth = TASK_HIGHLIGHT_STROKE;\n    }\n\n\tvar width = element.width - (strokeWidth / 2);\n\tvar height = element.height - (strokeWidth / 2);\n\n\tvar rect = paper.rect(element.x, element.y, width, height, 4);\n    rectAttrs['stroke-width'] = strokeWidth;\n\n    // Fill\n\trectAttrs['fill'] = ACTIVITY_FILL_COLOR;\n\n    rect.attr(rectAttrs);\n\trect.id = element.id;\n\n\tif (element.name) {\n\t\tthis._drawMultilineText(element.name, element.x, element.y, element.width, element.height, \"middle\", \"middle\", 11);\n\t}\n}\n\nfunction _drawTimerEventListener(element)\n{\n    _drawEventListener(element);\n    _drawTimerEventListenerIcon(paper, element);\n    _addHoverLogic(element, \"rect\", ACTIVITY_STROKE_COLOR);\n}\n\nfunction _drawEventListener(element)\n{\n    var x = element.x + (element.width / 2);\n\tvar y = element.y + (element.height / 2);\n\n\tvar circle = paper.circle(x, y, 15);\n\n    circle.attr({\"stroke-width\": 1,\n        \"stroke\": \"black\",\n        \"fill\": \"white\"\n    });\n\n\tcircle.id = element.id;\n}\n\nfunction _drawMilestone(element)\n{\n    var rectAttrs = {};\n\n    // Stroke\n    var strokeColor = _cmmnGetColor(element, ACTIVITY_STROKE_COLOR);\n    rectAttrs['stroke'] = strokeColor;\n\n    var strokeWidth;\n    if (strokeColor === ACTIVITY_STROKE_COLOR) {\n        strokeWidth = TASK_STROKE;\n    } else {\n        strokeWidth = TASK_HIGHLIGHT_STROKE;\n    }\n\n    var width = element.width - (strokeWidth / 2);\n    var height = element.height - (strokeWidth / 2);\n\n    var rect = paper.rect(element.x, element.y, width, height, 24);\n    rectAttrs['stroke-width'] = strokeWidth;\n\n    // Fill\n    rectAttrs['fill'] = WHITE_FILL_COLOR;\n\n    rect.attr(rectAttrs);\n    rect.id = element.id;\n\n    if (element.name) {\n        this._drawMultilineText(element.name, element.x, element.y, element.width, element.height, \"middle\", \"middle\", 11);\n    }\n}\n\nfunction _drawStage(element)\n{\n    var rectAttrs = {};\n\n    // Stroke\n    var strokeColor = _cmmnGetColor(element, ACTIVITY_STROKE_COLOR);\n    rectAttrs['stroke'] = strokeColor;\n\n    var strokeWidth;\n    if (strokeColor === ACTIVITY_STROKE_COLOR) {\n        strokeWidth = TASK_STROKE;\n    } else {\n        strokeWidth = TASK_HIGHLIGHT_STROKE;\n    }\n\n    var width = element.width - (strokeWidth / 2);\n    var height = element.height - (strokeWidth / 2);\n\n    var rect = paper.rect(element.x, element.y, width, height, 16);\n    rectAttrs['stroke-width'] = strokeWidth;\n\n    // Fill\n    rectAttrs['fill'] = WHITE_FILL_COLOR;\n\n    rect.attr(rectAttrs);\n    rect.id = element.id;\n\n    if (element.name) {\n        this._drawMultilineText(element.name, element.x + 10, element.y + 5, element.width, element.height, \"start\", \"top\", 11);\n    }\n}\n\nfunction _drawPlanModel(element)\n{\n    var rectAttrs = {};\n\n    // Stroke\n    var strokeColor = _cmmnGetColor(element, ACTIVITY_STROKE_COLOR);\n    rectAttrs['stroke'] = strokeColor;\n\n    var strokeWidth;\n    if (strokeColor === ACTIVITY_STROKE_COLOR) {\n        strokeWidth = TASK_STROKE;\n    } else {\n        strokeWidth = TASK_HIGHLIGHT_STROKE;\n    }\n\n    var width = element.width - (strokeWidth / 2);\n    var height = element.height - (strokeWidth / 2);\n\n    var rect = paper.rect(element.x, element.y, width, height, 4);\n    rectAttrs['stroke-width'] = strokeWidth;\n\n    // Fill\n    rectAttrs['fill'] = WHITE_FILL_COLOR;\n\n    rect.attr(rectAttrs);\n    rect.id = element.id;\n\n    var path1 = paper.path(\"M20 55 L37 34 L275 34 L291 55\");\n    path1.attr({\n        \"opacity\": 1,\n        \"stroke\": strokeColor,\n        \"fill\": \"#ffffff\"\n    });\n\n    var planModelHeader = paper.set();\n    planModelHeader.push(path1);\n\n    planModelHeader.translate(element.x, element.y - 55);\n    if (element.name) {\n        this._drawMultilineText(element.name, element.x + 10, element.y - 16, 275, element.height, \"middle\", \"top\", 11);\n    }\n}\n\nfunction _drawEntryCriterion(element)\n{\n    var strokeColor = _cmmnGetColor(element, MAIN_STROKE_COLOR);\n\n    var rhombus = paper.path(\"M\" + element.x + \" \" + (element.y + (element.height / 2)) +\n        \"L\" + (element.x + (element.width / 2)) + \" \" + (element.y + element.height) +\n        \"L\" + (element.x + element.width) + \" \" + (element.y + (element.height / 2)) +\n        \"L\" + (element.x + (element.width / 2)) + \" \" + element.y + \"z\"\n    );\n\n    // Fill\n    var gatewayFillColor = WHITE_FILL_COLOR;\n\n    // Opacity\n    var gatewayOpacity = 1.0;\n\n    rhombus.attr(\"stroke-width\", 1);\n    rhombus.attr(\"stroke\", strokeColor);\n    rhombus.attr(\"fill\", gatewayFillColor);\n    rhombus.attr(\"fill-opacity\", gatewayOpacity);\n\n    rhombus.id = element.id;\n}\n\nfunction _drawExitCriterion(element)\n{\n    var strokeColor = _cmmnGetColor(element, MAIN_STROKE_COLOR);\n\n    var rhombus = paper.path(\"M\" + element.x + \" \" + (element.y + (element.height / 2)) +\n        \"L\" + (element.x + (element.width / 2)) + \" \" + (element.y + element.height) +\n        \"L\" + (element.x + element.width) + \" \" + (element.y + (element.height / 2)) +\n        \"L\" + (element.x + (element.width / 2)) + \" \" + element.y + \"z\"\n    );\n\n    // Fill\n    var gatewayFillColor = '#000000';\n\n    // Opacity\n    var gatewayOpacity = 1.0;\n\n    rhombus.attr(\"stroke-width\", 1);\n    rhombus.attr(\"stroke\", strokeColor);\n    rhombus.attr(\"fill\", gatewayFillColor);\n    rhombus.attr(\"fill-opacity\", gatewayOpacity);\n\n    rhombus.id = element.id;\n}\n\nfunction _drawMultilineText(text, x, y, boxWidth, boxHeight, horizontalAnchor, verticalAnchor, fontSize)\n{\n\tif (!text || text == \"\")\n\t{\n\t\treturn;\n\t}\n\n\tvar textBoxX, textBoxY;\n    var width = boxWidth - (2 * TEXT_PADDING);\n\n    if (horizontalAnchor === \"middle\")\n    {\n    \ttextBoxX = x + (boxWidth / 2);\n    }\n    else if (horizontalAnchor === \"start\")\n    {\n    \ttextBoxX = x;\n    }\n\n    textBoxY = y + (boxHeight / 2);\n\n \tvar t = paper.text(textBoxX + TEXT_PADDING, textBoxY + TEXT_PADDING).attr({\n        \"text-anchor\" : horizontalAnchor,\n        \"font-family\" : \"Arial\",\n        \"font-size\" : fontSize,\n        \"fill\" : \"#373e48\"\n  \t});\n\n    var abc = \"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ\";\n    t.attr({\n        \"text\" : abc\n    });\n    var letterWidth = t.getBBox().width / abc.length;\n\n    t.attr({\n        \"text\" : text\n    });\n    var removedLineBreaks = text.split(\"\\n\");\n    var x = 0, s = [];\n    for (var r = 0; r < removedLineBreaks.length; r++)\n    {\n  \t    var words = removedLineBreaks[r].split(\" \");\n  \t    for ( var i = 0; i < words.length; i++) {\n\n  \t        var l = words[i].length;\n  \t        if (x + (l * letterWidth) > width) {\n  \t            s.push(\"\\n\");\n  \t            x = 0;\n  \t        }\n  \t        x += l * letterWidth;\n  \t        s.push(words[i] + \" \");\n  \t    }\n\t  \ts.push(\"\\n\");\n        x = 0;\n    }\n    t.attr({\n    \t\"text\" : s.join(\"\")\n    });\n\n    if (verticalAnchor && verticalAnchor === \"top\")\n    {\n    \tt.attr({\"y\": y + (t.getBBox().height / 2)});\n    }\n}\n\nfunction _drawAssociation(flow){\n\n\tvar polyline = new Polyline(flow.id, flow.waypoints, ASSOCIATION_STROKE, paper);\n\tpolyline.element = paper.path(polyline.path);\n\tpolyline.element.attr({\"stroke-width\": ASSOCIATION_STROKE});\n\tpolyline.element.attr({\"stroke-dasharray\": \". \"});\n\tpolyline.element.attr({\"stroke\":\"#585858\"});\n\n\tpolyline.element.id = flow.id;\n\n\tvar polylineInvisible = new Polyline(flow.id, flow.waypoints, ASSOCIATION_STROKE, paper);\n\n\tpolylineInvisible.element = paper.path(polyline.path);\n\tpolylineInvisible.element.attr({\n\t\t\t\"opacity\": 0,\n\t\t\t\"stroke-width\": 8,\n            \"stroke\" : \"#000000\"\n\t});\n\n\t_showTip(jQuery(polylineInvisible.element.node), flow);\n\n\tpolylineInvisible.element.mouseover(function() {\n\t\tpaper.getById(polyline.element.id).attr({\"stroke\":\"blue\"});\n\t});\n\n\tpolylineInvisible.element.mouseout(function() {\n\t\tpaper.getById(polyline.element.id).attr({\"stroke\":\"#585858\"});\n\t});\n}\n\nfunction _drawArrowHead(line, connectionType)\n{\n\tvar doubleArrowWidth = 2 * ARROW_WIDTH;\n\n\tvar arrowHead = paper.path(\"M0 0L-\" + (ARROW_WIDTH / 2 + .5) + \" -\" + doubleArrowWidth + \"L\" + (ARROW_WIDTH/2 + .5) + \" -\" + doubleArrowWidth + \"z\");\n\n\t// anti smoothing\n\tif (this.strokeWidth%2 == 1)\n\t\tline.x2 += .5, line.y2 += .5;\n\n\tarrowHead.transform(\"t\" + line.x2 + \",\" + line.y2 + \"\");\n\tarrowHead.transform(\"...r\" + Raphael.deg(line.angle - Math.PI / 2) + \" \" + 0 + \" \" + 0);\n\n\tarrowHead.attr(\"fill\", \"#585858\");\n\n\tarrowHead.attr(\"stroke-width\", SEQUENCEFLOW_STROKE);\n\tarrowHead.attr(\"stroke\", \"#585858\");\n\n\treturn arrowHead;\n}\n"
  },
  {
    "path": "flowable-ui-web/admin/display-cmmn/cmmn-icons.js",
    "content": "/* 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\nfunction _drawHumanTaskIcon(paper, startX, startY)\n{\n\tvar path1 = paper.path(\"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\tpath1.attr({\n\t\t\"opacity\": 1,\n\t\t\"stroke\": \"none\",\n\t\t\"fill\": \"#d1b575\"\n \t});\n\n\tvar userTaskIcon = paper.set();\n\tuserTaskIcon.push(path1);\n\n\tuserTaskIcon.transform(\"T\" + startX + \",\" + startY);\n}\n\nfunction _drawServiceTaskIcon(paper, startX, startY)\n{\n\tvar path1 = paper.path(\"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\tpath1.attr({\n\t\t\"opacity\": 1,\n\t\t\"stroke\": \"none\",\n\t\t\"fill\": \"#72a7d0\"\n \t});\n\n\tvar serviceTaskIcon = paper.set();\n\tserviceTaskIcon.push(path1);\n\n\tserviceTaskIcon.transform(\"T\" + startX + \",\" + startY);\n}\n\nfunction _drawCaseTaskIcon(paper, startX, startY)\n{\n    var path1 = paper.path(\"M5 8 L9 4 L18 4 L 21 7\");\n    path1.attr({\n        \"opacity\": 1,\n        \"stroke\": \"#000000\",\n        \"fill\": \"#000000\"\n    });\n\n    var path2 = paper.path(\"M1 23 L1 4 L30 4 L30 23z\");\n    path2.attr({\n        \"opacity\": 1,\n        \"stroke\": \"#000000\",\n        \"fill\": \"#F4F6F7\"\n    });\n\n    var caseTaskIcon = paper.set();\n    caseTaskIcon.push(path1);\n    caseTaskIcon.push(path2);\n\n    caseTaskIcon.translate(startX, startY);\n    caseTaskIcon.scale(0.7, 0.7);\n}\n\nfunction _drawProcessTaskIcon(paper, startX, startY)\n{\n    var path1 = paper.path(\"M1 23 L7 11 L1 0 L30 0 L 35 11 L 30 23z\");\n    path1.attr({\n        \"opacity\": 1,\n        \"stroke\": \"#000000\",\n        \"fill\": \"#F4F6F7\"\n    });\n\n    var processTaskIcon = paper.set();\n    processTaskIcon.push(path1);\n\n    processTaskIcon.translate(startX, startY);\n    processTaskIcon.scale(0.7, 0.7);\n}\n\nfunction _drawDecisionTaskIcon(paper, startX, startY)\n{\n    var path1 = paper.path(\"m 1,2 0,14 16,0 0,-14 z m 1.9,2.4000386 3.7,0 0,2.7999224 -3.7,0 z m 4.36364,0 3.7,0 0,2.7999224 -3.7,0 z m 4.36364,0 3.7,0 0,2.7999224 -3.7,0 z m -8.67364,3.9 3.7,0 0,2.7999224 -3.7,0 z m 4.36364,0 3.7,0 0,2.7999224 -3.7,0 z m 4.36364,0 3.7,0 0,2.7999224 -3.7,0 z m -8.67364,3.9 3.7,0 0,2.7999224 -3.7,0 z m 4.36364,0 3.7,0 0,2.7999224 -3.7,0 z m 4.36364,0 3.7,0 0,2.7999224 -3.7,0 z\");\n    path1.attr({\n        \"opacity\": 1,\n        \"stroke\": \"#000000\",\n        \"fill\": \"#F4F6F7\"\n    });\n\n    var decisionTaskIcon = paper.set();\n    decisionTaskIcon.push(path1);\n\n    decisionTaskIcon.translate(startX, startY);\n    decisionTaskIcon.scale(0.7, 0.7);\n}\n\nfunction _drawHttpTaskIcon(paper, startX, startY)\n{\n    var path = paper.path(\"m 16.704699,5.9229055 q 0.358098,0 0.608767,0.2506681 0.250669,0.250668 0.250669,0.6087677 0,0.3580997 -0.250669,0.6087677 -0.250669,0.2506679 -0.608767,0.2506679 -0.358098,0 -0.608767,-0.2506679 -0.250669,-0.250668 -0.250669,-0.6087677 0,-0.3580997 0.250669,-0.6087677 0.250669,-0.2506681 0.608767,-0.2506681 z m 2.578308,-2.0053502 q -2.229162,0 -3.854034,0.6759125 -1.624871,0.6759067 -3.227361,2.2694472 -0.716197,0.725146 -1.575633,1.7457293 L 7.2329969,8.7876913 Q 7.0897576,8.8055849 7.000233,8.9309334 L 4.9948821,12.368677 q -0.035811,0.06267 -0.035811,0.143242 0,0.107426 0.080572,0.205905 l 0.5729577,0.572957 q 0.125334,0.116384 0.2864786,0.07162 l 2.4708789,-0.760963 2.5156417,2.515645 -0.76096,2.470876 q -0.009,0.02687 -0.009,0.08057 0,0.125338 0.08058,0.205905 l 0.572957,0.572958 q 0.170096,0.152194 0.349146,0.04476 l 3.437744,-2.005351 q 0.125335,-0.08953 0.143239,-0.232763 l 0.17905,-3.392986 q 1.02058,-0.859435 1.745729,-1.575629 1.67411,-1.6830612 2.309735,-3.2049805 0.635625,-1.5219191 0.635625,-3.8585111 0,-0.1253369 -0.08505,-0.2148575 -0.08505,-0.089526 -0.201431,-0.089526 z\");\n    path.attr({\n        \"opacity\": 1,\n        \"stroke\": \"none\",\n        \"fill\": \"#16964d\"\n    });\n\n    startX += -2;\n    startY += -2;\n\n    path.transform(\"T\" + startX + \",\" + startY);\n\n}\n\nfunction _drawBusinessRuleTaskIcon(paper, startX, startY) {\n    var path1 = paper.path(\"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    path1.attr({\n        \"stroke\": \"none\",\n        \"fill\": \"#72a7d0\"\n    });\n\n    var businessRuleTaskIcon = paper.set();\n    businessRuleTaskIcon.push(path1);\n\n    businessRuleTaskIcon.transform(\"T\" + startX + \",\" + startY);\n}\n\nfunction _drawTimerEventListenerIcon(paper, element)\n{\n\tvar x = element.x + (element.width / 2);\n    var y = element.y + (element.height / 2);\n\n\tvar circle = paper.circle(x, y, 10);\n\n\tcircle.attr({\"stroke-width\": 1,\n\t\t\"stroke\": \"black\",\n\t\t\"fill\": \"none\"\n \t});\n\n\tvar path = paper.path(\"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\tpath.attr({\n\t\t\"stroke\": \"none\",\n\t\t\"fill\": \"#585858\"\n \t});\n\tpath.transform(\"T\" + (element.x + 5) + \",\" + (element.y + 5));\n\treturn path;\n}\n"
  },
  {
    "path": "flowable-ui-web/admin/display-cmmn/displaymodel.css",
    "content": "div[class*='ui-tooltip-flowable-'] {\n    background-color: #ffffff;\n    border-color: #c5c5c5;\n    color: #4a4a4a;\n    font-family: Verdana;\n    font-size: 12px;\n}\n\ndiv[class*='ui-tooltip-flowable-'] .qtip-content {\n  color: #4a4a4a;\n  background-color: #ffffff;\n  font-family: Verdana;\n  font-size: 12px;\n}\n\n.ui-tooltip-flowable-cmmn .qtip-titlebar {\n  color: #FFFFFF;\n  font-size: 12px;\n  background: #2B414F;\n}\n\n.ui-tooltip-flowable-cmmn .qtip-tip {\n  background-color: #2B414F;\n}\n"
  },
  {
    "path": "flowable-ui-web/admin/display-cmmn/displaymodel.html",
    "content": "<html>  \n    <head>\n\n        <link type=\"text/css\" rel=\"stylesheet\" href=\"display/jquery.qtip.min.css\" />\n        <link type=\"text/css\" rel=\"stylesheet\" href=\"display-cmmn/displaymodel.css\" />\n\n        <script type=\"text/javascript\" src=\"display/jquery.qtip.min.js\"></script>\n        <script type=\"text/javascript\" src=\"display/raphael.min.js\"></script>\n        <script type=\"text/javascript\" src=\"display-cmmn/cmmn-draw.js\"></script>\n        <script type=\"text/javascript\" src=\"display-cmmn/cmmn-icons.js\"></script>\n        <script type=\"text/javascript\" src=\"display/Polyline.js\"></script>\n        <script type=\"text/javascript\" src=\"display-cmmn/displaymodel.js\"></script>\n\n    </head>\n</html>"
  },
  {
    "path": "flowable-ui-web/admin/display-cmmn/displaymodel.js",
    "content": "/* 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 */\nvar NORMAL_STROKE = 1;\nvar ASSOCIATION_STROKE = 2;\nvar TASK_STROKE = 1;\nvar TASK_HIGHLIGHT_STROKE = 2;\n\nvar TEXT_COLOR= \"#373e48\";\nvar CURRENT_COLOR= \"#017501\";\nvar HOVER_COLOR= \"#666666\";\nvar ACTIVITY_STROKE_COLOR = \"#bbbbbb\";\nvar ACTIVITY_FILL_COLOR = \"#f9f9f9\";\nvar WHITE_FILL_COLOR = \"#ffffff\";\nvar MAIN_STROKE_COLOR = \"#585858\";\n\nvar TEXT_PADDING = 3;\nvar ARROW_WIDTH = 4;\nvar MARKER_WIDTH = 12;\n\nvar TASK_FONT = {font: \"11px Arial\", opacity: 1, fill: Raphael.rgb(0, 0, 0)};\n\n// icons\nvar ICON_SIZE = 16;\nvar ICON_PADDING = 4;\n\nvar INITIAL_CANVAS_WIDTH;\nvar INITIAL_CANVAS_HEIGHT;\n\nvar paper;\nvar viewBox;\nvar viewBoxWidth;\nvar viewBoxHeight;\n\nvar canvasWidth;\nvar canvasHeight;\n\nvar modelDiv = jQuery('#cmmnModel');\nvar modelId = modelDiv.attr('data-model-id');\nvar historyModelId = modelDiv.attr('data-history-id');\nvar caseDefinitionId = modelDiv.attr('data-definition-id');\nvar modelType = modelDiv.attr('data-model-type');\n\nvar elementsAdded = new Array();\nvar elementsRemoved = new Array();\n\nfunction _showTip(htmlNode, element)\n{\n    // Default tooltip, no custom tool tip set\n    if (documentation === undefined) {\n        var documentation = \"\";\n        if (element.name && element.name.length > 0) {\n            documentation += \"<b>Name</b>: <i>\" + element.name + \"</i><br/><br/>\";\n        }\n\n        if (element.properties) {\n            for (var i = 0; i < element.properties.length; i++) {\n                var propName = element.properties[i].name;\n                if (element.properties[i].type && element.properties[i].type === 'list') {\n                    documentation += '<b>' + propName + '</b>:<br/>';\n                    for (var j = 0; j < element.properties[i].value.length; j++) {\n                        documentation += '<i>' + element.properties[i].value[j] + '</i><br/>';\n                    }\n                }\n                else {\n                    documentation += '<b>' + propName + '</b>: <i>' + element.properties[i].value + '</i><br/>';\n                }\n            }\n        }\n    }\n\n    var text = element.type + \" \";\n    if (element.name && element.name.length > 0)\n    {\n        text += element.name;\n    }\n    else\n    {\n        text += element.id;\n    }\n\n    htmlNode.qtip({\n        content: {\n            text: documentation,\n            title: {\n                text: text\n            }\n        },\n        position: {\n            my: 'top left',\n            at: 'bottom center',\n            viewport: jQuery('#cmmnModel')\n        },\n        hide: {\n            fixed: true, delay: 500,\n            event: 'click mouseleave'\n        },\n        style: {\n            classes: 'ui-tooltip-flowable-cmmn'\n        }\n    });\n}\n\nfunction _addHoverLogic(element, type, defaultColor)\n{\n    var strokeColor = _cmmnGetColor(element, defaultColor);\n    var topBodyRect = null;\n    if (type === \"rect\")\n    {\n        topBodyRect = paper.rect(element.x, element.y, element.width, element.height);\n    }\n    else if (type === \"circle\")\n    {\n        var x = element.x + (element.width / 2);\n        var y = element.y + (element.height / 2);\n        topBodyRect = paper.circle(x, y, 15);\n    }\n    else if (type === \"rhombus\")\n    {\n        topBodyRect = paper.path(\"M\" + element.x + \" \" + (element.y + (element.height / 2)) +\n            \"L\" + (element.x + (element.width / 2)) + \" \" + (element.y + element.height) +\n            \"L\" + (element.x + element.width) + \" \" + (element.y + (element.height / 2)) +\n            \"L\" + (element.x + (element.width / 2)) + \" \" + element.y + \"z\"\n        );\n    }\n\n    var opacity = 0;\n    var fillColor = \"#ffffff\";\n    if (jQuery.inArray(element.id, elementsAdded) >= 0)\n    {\n        opacity = 0.2;\n        fillColor = \"green\";\n    }\n\n    if (jQuery.inArray(element.id, elementsRemoved) >= 0)\n    {\n        opacity = 0.2;\n        fillColor = \"red\";\n    }\n\n    topBodyRect.attr({\n        \"opacity\": opacity,\n        \"stroke\" : \"none\",\n        \"fill\" : fillColor\n    });\n    _showTip(jQuery(topBodyRect.node), element);\n\n    topBodyRect.mouseover(function() {\n        paper.getById(element.id).attr({\"stroke\":HOVER_COLOR});\n    });\n\n    topBodyRect.mouseout(function() {\n        paper.getById(element.id).attr({\"stroke\":strokeColor});\n    });\n}\n\nfunction _zoom(zoomIn)\n{\n    var tmpCanvasWidth, tmpCanvasHeight;\n    if (zoomIn)\n    {\n        tmpCanvasWidth = canvasWidth * (1.0/0.90);\n        tmpCanvasHeight = canvasHeight * (1.0/0.90);\n    }\n    else\n    {\n        tmpCanvasWidth = canvasWidth * (1.0/1.10);\n        tmpCanvasHeight = canvasHeight * (1.0/1.10);\n    }\n\n    if (tmpCanvasWidth != canvasWidth || tmpCanvasHeight != canvasHeight)\n    {\n        canvasWidth = tmpCanvasWidth;\n        canvasHeight = tmpCanvasHeight;\n        paper.setSize(canvasWidth, canvasHeight);\n    }\n}\n\nvar modelUrl = './app/rest/admin/case-definitions/' + caseDefinitionId + '/model-json';\n\nvar request = jQuery.ajax({\n    type: 'get',\n    url: modelUrl + '?nocaching=' + new Date().getTime()\n});\n\nrequest.success(function(data, textStatus, jqXHR) {\n\n    if ((!data.elements || data.elements.length == 0) && (!data.pools || data.pools.length == 0)) return;\n\n    INITIAL_CANVAS_WIDTH = data.diagramWidth;\n    \n    if (modelType == 'design') {\n    \tINITIAL_CANVAS_WIDTH += 20;\n    } else {\n        INITIAL_CANVAS_WIDTH += 30;\n    }\n    \n    INITIAL_CANVAS_HEIGHT = data.diagramHeight + 50;\n    canvasWidth = INITIAL_CANVAS_WIDTH;\n    canvasHeight = INITIAL_CANVAS_HEIGHT;\n    viewBoxWidth = INITIAL_CANVAS_WIDTH;\n    viewBoxHeight = INITIAL_CANVAS_HEIGHT;\n    \n    if (modelType == 'design') {\n    \tvar headerBarHeight = 170;\n    \tvar offsetY = 0;\n    \tif (jQuery(window).height() > (canvasHeight + headerBarHeight))\n    \t{\n        \toffsetY = (jQuery(window).height() - headerBarHeight - canvasHeight) / 2;\n    \t}\n\n    \tif (offsetY > 50) {\n        \toffsetY = 50;\n    \t}\n\n    \tjQuery('#cmmnModel').css('marginTop', offsetY);\n    }\n\n    jQuery('#cmmnModel').width(INITIAL_CANVAS_WIDTH);\n    jQuery('#cmmnModel').height(INITIAL_CANVAS_HEIGHT);\n    paper = Raphael(document.getElementById('cmmnModel'), canvasWidth, canvasHeight);\n    paper.setViewBox(0, 0, viewBoxWidth, viewBoxHeight, false);\n    paper.renderfix();\n\n    var modelElements = data.elements;\n    for (var i = 0; i < modelElements.length; i++)\n    {\n        var element = modelElements[i];\n        //try {\n        var drawFunction = eval(\"_draw\" + element.type);\n        drawFunction(element);\n        //} catch(err) {console.log(err);}\n    }\n\n    if (data.flows)\n    {\n        for (var i = 0; i < data.flows.length; i++)\n        {\n            var flow = data.flows[i];\n            _drawAssociation(flow);\n        }\n    }\n});\n\nrequest.error(function(jqXHR, textStatus, errorThrown) {\n    alert(\"error\");\n});\n"
  },
  {
    "path": "flowable-ui-web/admin/error/404.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n    <head>\n        <meta charset=\"utf-8\">\n        <title>Page Not Found :(</title>\n        <style>\n            ::-moz-selection {\n                background: #b3d4fc;\n                text-shadow: none;\n            }\n\n            ::selection {\n                background: #b3d4fc;\n                text-shadow: none;\n            }\n\n            html {\n                padding: 30px 10px;\n                font-size: 20px;\n                line-height: 1.4;\n                color: #737373;\n                background: #f0f0f0;\n                -webkit-text-size-adjust: 100%;\n                -ms-text-size-adjust: 100%;\n            }\n\n            html,\n            input {\n                font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n            }\n\n            body {\n                max-width: 500px;\n                _width: 500px;\n                padding: 30px 20px 50px;\n                border: 1px solid #b3b3b3;\n                border-radius: 4px;\n                margin: 0 auto;\n                box-shadow: 0 1px 10px #a7a7a7, inset 0 1px 0 #fff;\n                background: #fcfcfc;\n            }\n\n            h1 {\n                margin: 0 10px;\n                font-size: 50px;\n                text-align: center;\n            }\n\n            h1 span {\n                color: #bbb;\n            }\n\n            h3 {\n                margin: 1.5em 0 0.5em;\n            }\n\n            p {\n                margin: 1em 0;\n            }\n\n            ul {\n                padding: 0 0 0 40px;\n                margin: 1em 0;\n            }\n\n            .container {\n                max-width: 380px;\n                _width: 380px;\n                margin: 0 auto;\n            }\n\n            /* google search */\n\n            #goog-fixurl ul {\n                list-style: none;\n                padding: 0;\n                margin: 0;\n            }\n\n            #goog-fixurl form {\n                margin: 0;\n            }\n\n            #goog-wm-qt,\n            #goog-wm-sb {\n                border: 1px solid #bbb;\n                font-size: 16px;\n                line-height: normal;\n                vertical-align: top;\n                color: #444;\n                border-radius: 2px;\n            }\n\n            #goog-wm-qt {\n                width: 220px;\n                height: 20px;\n                padding: 5px;\n                margin: 5px 10px 0 0;\n                box-shadow: inset 0 1px 1px #ccc;\n            }\n\n            #goog-wm-sb {\n                display: inline-block;\n                height: 32px;\n                padding: 0 10px;\n                margin: 5px 0 0;\n                white-space: nowrap;\n                cursor: pointer;\n                background-color: #f5f5f5;\n                background-image: -webkit-linear-gradient(rgba(255,255,255,0), #f1f1f1);\n                background-image: -moz-linear-gradient(rgba(255,255,255,0), #f1f1f1);\n                background-image: -ms-linear-gradient(rgba(255,255,255,0), #f1f1f1);\n                background-image: -o-linear-gradient(rgba(255,255,255,0), #f1f1f1);\n                -webkit-appearance: none;\n                -moz-appearance: none;\n                appearance: none;\n                *overflow: visible;\n                *display: inline;\n                *zoom: 1;\n            }\n\n            #goog-wm-sb:hover,\n            #goog-wm-sb:focus {\n                border-color: #aaa;\n                box-shadow: 0 1px 1px rgba(0, 0, 0, 0.1);\n                background-color: #f8f8f8;\n            }\n\n            #goog-wm-qt:hover,\n            #goog-wm-qt:focus {\n                border-color: #105cb6;\n                outline: 0;\n                color: #222;\n            }\n\n            input::-moz-focus-inner {\n                padding: 0;\n                border: 0;\n            }\n        </style>\n    </head>\n    <body>\n        <div class=\"container\">\n            <h1>Not found <span>:(</span></h1>\n            <p>Sorry, but the page you were trying to view does not exist.</p>\n            <p>It looks like this was the result of either:</p>\n            <ul>\n                <li>a mistyped address</li>\n                <li>an out-of-date link</li>\n            </ul>\n            <script>\n                var GOOG_FIXURL_LANG = (navigator.language || '').slice(0,2),GOOG_FIXURL_SITE = location.host;\n            </script>\n            <script src=\"//linkhelp.clients.google.com/tbproxy/lh/wm/fixurl.js\"></script>\n        </div>\n    </body>\n</html>\n"
  },
  {
    "path": "flowable-ui-web/admin/error/500.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n    <head>\n        <meta charset=\"utf-8\">\n        <title>Page Not Found :(</title>\n        <style>\n            ::-moz-selection {\n                background: #b3d4fc;\n                text-shadow: none;\n            }\n\n            ::selection {\n                background: #b3d4fc;\n                text-shadow: none;\n            }\n\n            html {\n                padding: 30px 10px;\n                font-size: 20px;\n                line-height: 1.4;\n                color: #737373;\n                background: #f0f0f0;\n                -webkit-text-size-adjust: 100%;\n                -ms-text-size-adjust: 100%;\n            }\n\n            html,\n            input {\n                font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n            }\n\n            body {\n                max-width: 500px;\n                _width: 500px;\n                padding: 30px 20px 50px;\n                border: 1px solid #b3b3b3;\n                border-radius: 4px;\n                margin: 0 auto;\n                box-shadow: 0 1px 10px #a7a7a7, inset 0 1px 0 #fff;\n                background: #fcfcfc;\n            }\n\n            h1 {\n                margin: 0 10px;\n                font-size: 50px;\n                text-align: center;\n            }\n\n            h1 span {\n                color: #bbb;\n            }\n\n            h3 {\n                margin: 1.5em 0 0.5em;\n            }\n\n            p {\n                margin: 1em 0;\n            }\n\n            ul {\n                padding: 0 0 0 40px;\n                margin: 1em 0;\n            }\n\n            .container {\n                max-width: 380px;\n                _width: 380px;\n                margin: 0 auto;\n            }\n\n            /* google search */\n\n            #goog-fixurl ul {\n                list-style: none;\n                padding: 0;\n                margin: 0;\n            }\n\n            #goog-fixurl form {\n                margin: 0;\n            }\n\n            #goog-wm-qt,\n            #goog-wm-sb {\n                border: 1px solid #bbb;\n                font-size: 16px;\n                line-height: normal;\n                vertical-align: top;\n                color: #444;\n                border-radius: 2px;\n            }\n\n            #goog-wm-qt {\n                width: 220px;\n                height: 20px;\n                padding: 5px;\n                margin: 5px 10px 0 0;\n                box-shadow: inset 0 1px 1px #ccc;\n            }\n\n            #goog-wm-sb {\n                display: inline-block;\n                height: 32px;\n                padding: 0 10px;\n                margin: 5px 0 0;\n                white-space: nowrap;\n                cursor: pointer;\n                background-color: #f5f5f5;\n                background-image: -webkit-linear-gradient(rgba(255,255,255,0), #f1f1f1);\n                background-image: -moz-linear-gradient(rgba(255,255,255,0), #f1f1f1);\n                background-image: -ms-linear-gradient(rgba(255,255,255,0), #f1f1f1);\n                background-image: -o-linear-gradient(rgba(255,255,255,0), #f1f1f1);\n                -webkit-appearance: none;\n                -moz-appearance: none;\n                appearance: none;\n                *overflow: visible;\n                *display: inline;\n                *zoom: 1;\n            }\n\n            #goog-wm-sb:hover,\n            #goog-wm-sb:focus {\n                border-color: #aaa;\n                box-shadow: 0 1px 1px rgba(0, 0, 0, 0.1);\n                background-color: #f8f8f8;\n            }\n\n            #goog-wm-qt:hover,\n            #goog-wm-qt:focus {\n                border-color: #105cb6;\n                outline: 0;\n                color: #222;\n            }\n\n            input::-moz-focus-inner {\n                padding: 0;\n                border: 0;\n            }\n        </style>\n    </head>\n    <body>\n        <div class=\"container\">\n            <h1>Internal server error <span>:(</span></h1>\n            <p>Sorry, an internal error has occured.</p>\n            <p>You can try again this request later.</p>\n        </div>\n    </body>\n</html>\n"
  },
  {
    "path": "flowable-ui-web/admin/i18n/en.json",
    "content": "{\n    \"GENERAL\": {\n        \"YES\": \"Yes\",\n        \"NO\": \"No\",\n        \"ACTION\": {\n            \"LOGOUT\": \"Sign out\",\n            \"DISMISS-ALERT\": \"Click to dismiss this message\",\n            \"RETURN-TO-LIST\": \"Return to list\",\n            \"SHOW-RESULTS\": \"Show {{size}} results\",\n            \"REFRESH-LIST\": \"Refresh list\",\n            \"SORT-BY\": \"Sort by {{sort}}\",\n            \"CLEAR-FILTERS\": \"Clear filters\",\n            \"CANCEL-AND-CLOSE\": \"Cancel and Close\",\n            \"CANCEL\": \"Cancel\",\n            \"OK\": \"Ok\",\n            \"NEXT\": \"Next\",\n            \"PREVIOUS\": \"Previous\",\n            \"CLOSE\": \"Close\",\n            \"SHOWLICENSE\": \"License info\"\n        },\n        \"TITLE\": {\n            \"MAIN\": \"Activiti Administrator\",\n            \"ACTIONS\": \"Actions\",\n            \"FILTERS\": \"Filters\"\n        },\n        \"MENU\": {\n            \"PROCESS-ENGINE\": \"Process Engine\",\n            \"CMMN-ENGINE\": \"CMMN Engine\",\n            \"APP-ENGINE\": \"App Engine\",\n            \"FORM-ENGINE\": \"Form Engine\",\n            \"CONTENT-ENGINE\": \"Content Engine\",\n            \"DMN-ENGINE\": \"DMN Engine\",\n            \"DEPLOYMENTS\": \"Deployments\",\n            \"DEFINITIONS\": \"Definitions\",\n            \"INSTANCES\": \"Instances\",\n            \"TASKS\": \"Tasks\",\n            \"JOBS\": \"Jobs\",\n            \"EVENT-SUBSCRIPTIONS\": \"Event subscriptions\",\n            \"CONFIGURATION\": \"Configuration\",\n            \"CONFIGURATION-ENGINE\": \"Engine\",\n            \"DECISION-TABLES\": \"Decision tables\",\n            \"DECISION-TABLE-EXECUTIONS\": \"Executions\",\n            \"CONTENT-ITEMS\": \"Content items\"\n        },\n        \"RESULT-SIZES\": {\n            \"10\": \"10\",\n            \"25\": \"25\",\n            \"50\": \"50\",\n            \"100\": \"100\",\n            \"100000000\": \"all\"\n        }\n    },\n    \"PROCESS-DEFINITION\": {\n        \"ID\": \"ID:\",\n        \"NAME\": \"Name:\",\n        \"VERSION\": \"Version:\",\n        \"DESCRIPTION\": \"Description:\",\n        \"KEY\": \"Key:\",\n        \"CATEGORY\": \"Category:\",\n        \"SUSPENDED\": \"Suspended:\",\n        \"DEPLOYMENT\": \"Deployment:\",\n        \"TENANT\": \"Tenant:\",\n        \"START-FORM-DEFINED\": \"Start form defined:\",\n        \"GRAPHICAL-NOTATION-DEFINED\": \"Graphical notation defined:\",\n        \"PROCESS-INSTANCES-SIZE\": \"Definition has {{total}} process instances running\",\n        \"PROCESS-INSTANCES-SHOWING\": \", showing {{size}} most recently started\",\n        \"PROCESS-INSTANCES-EMPTY\": \"Definition has no process instances running\",\n        \"JOBS-SIZE\": \"Definition has {{total}} jobs running\",\n        \"JOBS-EMPTY\": \"Definition has no jobs running\",\n        \"DECISION-TABLES-SIZE\": \"Definition has {{total}} decision tables.\",\n        \"DECISION-TABLES-EMPTY\": \"Definition has no decision tables.\",\n        \"FORM-DEFINITIONS-SIZE\": \"Definition has {{total}} form definitions.\",\n        \"FORM-DEFINITIONS-EMPTY\": \"Definition has no form definitions.\",\n        \"TITLE\": {\n            \"PROCESS-INSTANCES\": \"Process instances\",\n            \"JOBS\": \"Jobs\",\n            \"DECISION-TABLES\": \"Decision tables\",\n            \"FORMS\": \"Form definitions\"\n        },\n        \"ACTION\": {\n            \"EDIT-CATEGORY\": \"Edit category\",\n            \"SHOW-ALL-JOBS\": \"Show all jobs\",\n            \"SHOW-ALL-PROCESSES\": \"Show all processes\",\n            \"SHOW-DIAGRAM\": \"Show process diagram\"\n        },\n        \"POPUP\": {\n            \"EDIT-CATEGORY\": {\n                \"TITLE\": \"Edit category for definition\",\n                \"MESSAGE\": \"The initial category for the definition is populated from the targetNameSpace attribute in the BPMN 2.0 XML, but can be altered after deployment.\",\n                \"CATEGORY\": \"Category\",\n                \"CATEGORY-PLACEHOLDER\": \"Enter a category\",\n                \"CONFIRM\": \"Update category\"\n            },\n            \"SHOW-PROCESS-MODEL\": {\n                \"TITLE\": \"Process diagram\"\n            },\n            \"MIGRATE\": {\n                \"TITLE\": \"Migrate process instance\",\n                \"MESSAGE\": \"Migrate the process instance to another version of the process definition and define activity mappings.\",\n                \"CURRENT-DEFINITION\": \"Current process definition\",\n                \"TARGET-DEFINITION\": \"Target process definition\"\n            }\n        }\n    },\n    \"PROCESS-DEFINITIONS\": {\n        \"LIST-MESSAGE\": \"Showing {{size}} results, from a total of {{total}} matching definitions.\",\n        \"LIST-MESSAGE-EMPTY\": \"No matching process definitions.\",\n        \"FILTER\": {\n            \"NAME\": \"Name (case sensitive)\",\n            \"KEY\": \"Key (case sensitive)\",\n            \"DEPLOYMENT-ID\": \"Deployment ID\",\n            \"TENANT-ID\": \"Tenant ID\",\n            \"LATEST\": \"Latest version\",\n            \"LATEST-HELP\": \"Only show latest versions\"\n        },\n        \"TITLE\": {\n            \"MAIN\": \"Process Definitions\"\n        },\n        \"SORT\": {\n            \"ID\": \"ID\",\n            \"NAME\": \"Name\",\n            \"VERSION\": \"Version\"\n        },\n        \"HEADER\": {\n            \"ID\": \"ID\",\n            \"NAME\": \"Name\",\n            \"VERSION\": \"Version\",\n            \"KEY\": \"Key\",\n            \"TENANT\": \"Tenant\"\n        },\n        \"ACTIONS\": {\n            \"UPLOAD-FROM-MODELER\": \"Upload from Flowable Editor\"\n        },\n        \"POPUP\": {\n            \"UPLOAD-FROM-MODELER\": {\n                \"NAME\": \"User name\",\n                \"PASSWORD\": \"Password\",\n                \"ERROR\": \"We couldn't contact the Editor\",\n                \"UNAUTHORIZED\": \"Invalid credentials\",\n                \"UPLOAD-DESCRIPTION\": \"The process model will now be fetched and deployed to the currently active Flowable cluster. Select an appropriate name for deployment package.\"\n            }\n        }\n    },\n    \"PROCESS-INSTANCE\": {\n        \"ID\": \"ID:\",\n        \"NAME\": \"Name:\",\n        \"DESCRIPTION\": \"Description:\",\n        \"BUSINESS-KEY\": \"Business key:\",\n        \"TENANT-ID\": \"Tenant:\",\n        \"STATUS\": \"Status:\",\n        \"STATUS-ACTIVE\": \"Active\",\n        \"STATUS-COMPLETED\": \"Completed\",\n        \"ACTIVITY-ID-STARTED\": \"Activity ID started:\",\n        \"ACTIVITY-ID-ENDED\": \"Ended in activity:\",\n        \"DELETE-REASON\": \"Delete reason:\",\n        \"STARTED-BY\": \"Started by:\",\n        \"END-TIME\": \"End time:\",\n        \"DURATION\": \"Duration:\",\n        \"SUPER-PROCESS-INSTANCE-ID\": \"Super process instance ID:\",\n        \"TASKS-SIZE\": \"This process instance has {{total}} tasks.\",\n        \"TASKS-EMPTY\": \"This process instance has no tasks.\",\n        \"VARIABLES-SIZE\": \"This process instance has {{total}} variables.\",\n        \"VARIABLES-EMPTY\": \"This process instance has no variables.\",\n        \"JOBS-SIZE\": \"This process instance has {{total}} jobs.\",\n        \"JOBS-EMPTY\": \"This process instance has no jobs.\",\n        \"SUBPROCESSES-SIZE\": \"This process instance has {{total}} subprocesses.\",\n        \"SUBPROCESSES-EMPTY\": \"This process instance has no subprocesses.\",\n        \"DECISION-TABLES-SIZE\": \"This process instance has {{total}} decision tables.\",\n        \"DECISION-TABLES-EMPTY\": \"This process instance has no decision tables.\",\n        \"FORM-INSTANCES-SIZE\": \"This process instance has {{total}} form instances.\",\n        \"FORM-INSTANCES-EMPTY\": \"This process instance has no form instances.\",\n        \"TITLE\": {\n            \"TASKS\": \"Tasks\",\n            \"VARIABLES\": \"Variables\",\n            \"JOBS\": \"Jobs\",\n            \"SUBPROCESSES\": \"Subprocesses\",\n            \"DECISION-TABLES\": \"Decision Tables\",\n            \"FORM-INSTANCES\": \"Form instances\"\n        },\n        \"ACTION\": {\n            \"DELETE\": \"Delete process instance\",\n            \"TERMINATE\": \"Terminate process instance\",\n            \"SHOW-ALL-TASKS\": \"Show all tasks\",\n            \"SHOW-ALL-JOBS\": \"Show all jobs\",\n            \"SHOW-ALL-SUBPROCESSES\": \"Show all subprocesses\",\n            \"SHOW-DIAGRAM\": \"Show process diagram\",\n            \"MIGRATE-PROCESSINSTANCE\": \"Migrate process instance\",\n            \"TITLE-VARIABLES\": \"Actions on selected variable\",\n            \"DELETE-VARIABLE\": \"Delete the variable\",\n            \"UPDATE-VALUE\": \"Update variable\",\n            \"ADD-VARIABLE\": \"Add variable\"\n        },\n        \"POPUP\": {\n            \"DELETE\": {\n                \"TITLE\": \"Delete process instance\",\n                \"MESSAGE-DELETE\": \"Are you sure you want to delete the process instance\",\n                \"MESSAGE-TERMINATE\": \"Are you sure you want to terminate the process instance\",\n                \"DELETE-REASON\": \"Delete reason\",\n                \"DELETE-REASON-HELP\": \"Enter an optional delete reason\",\n                \"CONFIRM-DELETE\": \"Delete process instance\",\n                \"CONFIRM-TERMINATE\": \"Terminate process instance\"\n            },\n            \"SHOW-PROCESS-MODEL\": {\n                \"TITLE\": \"Process diagram\"\n            },\n            \"CREATE-VARIABLE\": {\n                \"TITLE\": \"Create Variable\",\n                \"NAME\": \"Variable name\",\n                \"TYPE\": \"Activiti variable type\",\n                \"VALUE\": \"Variable value\",\n                \"CREATE\": \"Create\"\n            },\n            \"UPDATE-VARIABLE\": {\n                \"TITLE\": \"Update variable '{{name}}'\",\n                \"NAME\": \"Variable name\",\n                \"VALUE\": \"Value\",\n                \"CHECKED\": \"true\",\n                \"UNCHECKED\": \"false\",\n                \"DATE-HELP\": \"ISO-8601 format (example : 2016-01-28T23:00:00Z)\",\n                \"ACTION-UPDATE\": \"Update\"\n            },\n            \"DELETE-VARIABLE\": {\n                \"TITLE\": \"Delete variable '{{name}}\",\n                \"MESSAGE\": \"Are you sure you want to remove this variable?\",\n                \"DELETE\": \"Delete\"\n            }\n        }\n    },\n    \"PROCESS-INSTANCES\": {\n        \"TITLE\": \"Process instances\",\n        \"LIST-MESSAGE\": \"Showing {{size}} results, from a total of {{total}} matching process instances.\",\n        \"LIST-MESSAGE-EMPTY\": \"No matching process instances.\",\n        \"FILTER\": {\n            \"NAME\": \"Name\",\n            \"PROCESS-DEFINITION\": \"Process definition\",\n            \"ALL-PROCESS-DEFINITIONS\": \"All process definitions\",\n            \"STATUS\": \"Status\",\n            \"STATUS-ANY\": \"Any status\",\n            \"STATUS-ACTIVE\": \"Active instances\",\n            \"STATUS-COMPLETE\": \"Completed instances\",\n            \"BUSINESS-KEY\": \"Business key\",\n            \"SUPER-PROCESS-INSTANCE-ID\": \"Super process instance ID\",\n            \"STARTED-BEFORE\": \"Started before\",\n            \"STARTED-AFTER\": \"Started after\",\n            \"ENDED-BEFORE\": \"Ended before\",\n            \"ENDED-AFTER\": \"Ended after\",\n            \"VARIABLE\": \"Variable\",\n            \"VARIABLE-NAME\": \"Variable name\",\n            \"VARIABLE-VALUE\": \"Variable value\",\n            \"VARIABLE-BOOLEAN-VALUE\": \"Boolean value: {{value}}\",\n            \"TENANT-ID\": \"Tenant identifier\"\n        },\n        \"SORT\": {\n            \"ID\": \"ID\",\n            \"START-TIME\": \"Time started\"\n        },\n        \"HEADER\": {\n            \"ID\": \"ID\",\n            \"NAME\": \"Name\",\n            \"BUSINESS-KEY\": \"Business key\",\n            \"PROCESS-DEFINITION\": \"Process definition\",\n            \"CREATE-TIME\": \"Created\",\n            \"END-TIME\": \"Ended\",\n            \"STATUS\": \"Status\"\n        }\n    },\n    \"TASK\": {\n        \"ID\": \"ID:\",\n        \"NAME\": \"Name:\",\n        \"STATUS\": \"Status:\",\n        \"STATUS-COMPLETED\": \"Completed\",\n        \"STATUS-ACTIVE\": \"Active\",\n        \"DESCRIPTION\": \"Description:\",\n        \"TASK-DEFINITION-KEY\": \"Definition key:\",\n        \"FORM-KEY\": \"Form key:\",\n        \"PRIORITY\": \"Priority:\",\n        \"DELEGATION-STATE\": \"Delegation state:\",\n        \"CATEGORY\": \"Category:\",\n        \"TENANT-ID\": \"Tenant:\",\n        \"PARENT\": \"Parent task:\",\n        \"ASSIGNEE\": \"Assignee:\",\n        \"OWNER\": \"Owner:\",\n        \"START-DATE\": \"Start date:\",\n        \"DUE-DATE\": \"Due date:\",\n        \"END-DATE\": \"End date:\",\n        \"DELETE-REASON\": \"Delete reason:\",\n        \"PROCESS-INSTANCE\": \"Process Instance\",\n        \"PROCESS-DEFINITION\": \"Process definition\",\n        \"CASE-INSTANCE\": \"Case Instance\",\n        \"CASE-DEFINITION\": \"Case definition\",\n        \"EXECUTION-ID\": \"Execution ID:\",\n        \"SUBTASKS-MESSAGE\": \"This task has {{total}} subtasks, showing {{size}}.\",\n        \"SUBTASKS-MESSAGE-EMPTY\": \"This task has no subtasks.\",\n        \"VARIABLES-MESSAGE\": \"This task has {{size}} variables.\",\n        \"VARIABLES-MESSAGE-EMPTY\": \"This task has no variables.\",\n        \"IDENTITY-LINKS-MESSAGE\": \"This task has {{size}} identity links.\",\n        \"IDENTITY-LINKS-MESSAGE-EMPTY\": \"This task has no identity links.\",\n        \"ACTION\": {\n            \"EDIT\": \"Edit task\",\n            \"ASSIGN-CLAIM\": \"Assign/Claim task\",\n            \"DELEGATE\": \"Delegate task\",\n            \"RESOLVE\": \"Resolve task\",\n            \"COMPLETE\": \"Complete task\",\n            \"DELETE\": \"Delete task\",\n            \"SHOW-ALL-SUBTASKS\": \"Show all subtasks\",\n            \"SHOW-SUBMITTED-FORM\": \"Show form instance\"\n        },\n        \"TITLE\": {\n            \"SUBTASKS\": \"Sub tasks\",\n            \"IDENTITY-LINKS\": \"Identity links\",\n            \"VARIABLES\": \"Variables\"\n        },\n        \"POPUP\": {\n            \"ASSIGN\": {\n                \"TITLE\": \"Assign task\",\n                \"MESSAGE\": \"Are you sure you want to assign task\",\n                \"NEW-ASSIGNEE\": \"New assignee\",\n                \"NEW-ASSIGNEE-HELP\": \"Leave the assignee field empty if you want to assign the task to nobody. Mind: when providing a user id make sure it exists.\",\n                \"CONFIRM\": \"Assign task\"\n            },\n            \"COMPLETE\": {\n                \"TITLE\": \"Complete task\",\n                \"MESSAGE\": \"Are you sure you want to complete task\",\n                \"CONFIRM\": \"Complete task\"\n            },\n            \"DELEGATE\": {\n                \"TITLE\": \"Delegate task\",\n                \"MESSAGE\": \"Are you sure you want to delegate task\",\n                \"CONFIRM\": \"Delegate task\",\n                \"DELEGATE-TO\": \"User to delegate to\"\n            },\n            \"RESOLVE\": {\n                \"TITLE\": \"Resolve task\",\n                \"MESSAGE\": \"Are you sure you want to resolve task\",\n                \"CONFIRM\": \"Resolve task\"\n            },\n            \"DELETE\": {\n                \"TITLE\": \"Delete task\",\n                \"MESSAGE\": \"Are you sure you want to delete task\",\n                \"CONFIRM\": \"Delete task\"\n            },\n            \"EDIT\": {\n                \"TITLE\": \"Edit task\",\n                \"CONFIRM\": \"Update task\",\n                \"NAME\": \"Name\",\n                \"DESCRIPTION\": \"Description\",\n                \"PRIORITY\": \"Priority\",\n                \"CATEGORY\": \"Category\",\n                \"ASSIGNEE\": \"Assignee\",\n                \"OWNER\": \"Owner\",\n                \"DUE-DATE\": \"Due date\"\n            }\n        }\n    },\n    \"TASKS\": {\n        \"TITLE\": \"Tasks\",\n        \"LIST-MESSAGE\": \"Showing {{size}} results, from a total of {{total}} matching tasks.\",\n        \"LIST-MESSAGE-EMPTY\": \"No matching tasks.\",\n        \"FILTER\": {\n            \"NAME\": \"Name (case sensitive)\",\n            \"ASSIGNEE\": \"Assignee (case sensitive)\",\n            \"STATUS\": \"Status\",\n            \"STATUS-ANY\": \"Any status\",\n            \"STATUS-ACTIVE\": \"Active tasks\",\n            \"STATUS-COMPLETE\": \"Completed tasks\",\n            \"PROCESS-INSTANCE-ID\": \"Process instance ID\",\n            \"CASE-INSTANCE-ID\": \"Case instance ID\",\n            \"TENANT-ID\": \"Tenant identifier\",\n            \"OWNER\": \"Owner (case sensitive)\",\n            \"PARENT-TASK-ID\": \"Parent task ID\",\n            \"CREATED-BEFORE\": \"Created before\",\n            \"CREATED-AFTER\": \"Created after\",\n            \"ENDED-BEFORE\": \"Ended before\",\n            \"ENDED-AFTER\": \"Ended after\",\n            \"DUE-BEFORE\": \"Due before\",\n            \"DUE-AFTER\": \"Due after\",\n            \"TASK-VARIABLE\": \"Task local variable\",\n            \"PROCESS-VARIABLE\": \"Process variable\",\n            \"VARIABLE-NAME\": \"Variable name\",\n            \"VARIABLE-VALUE\": \"Variable value\",\n            \"VARIABLE-BOOLEAN-VALUE\": \"Boolean value: {{value}}\"\n        },\n        \"SORT\": {\n            \"NAME\": \"Name\",\n            \"DUE-DATE\": \"Due date\",\n            \"START-TIME\": \"Time started\",\n            \"END-TIME\": \"Time ended\",\n            \"PRIORITY\": \"Priority\"\n        },\n        \"HEADER\": {\n            \"ID\": \"ID\",\n            \"NAME\": \"Name\",\n            \"ASSIGNEE\": \"Assignee\",\n            \"OWNER\": \"Owner\",\n            \"CREATE-TIME\": \"Created\",\n            \"END-TIME\": \"Ended\",\n            \"PRIORITY\": \"Priority\"\n        }\n    },\n    \"DEPLOYMENTS\": {\n        \"TITLE\": \"Deployments\",\n        \"LIST-MESSAGE\": \"Showing {{size}} results, from a total of {{total}} matching deployments.\",\n        \"LIST-MESSAGE-EMPTY\": \"No matching deployments.\",\n        \"FILTER\": {\n            \"NAME\": \"Name (case sensitive)\",\n            \"TENANTID\": \"Tenant identifier (case sensitive)\"\n        },\n        \"SORT\": {\n            \"ID\": \"ID\",\n            \"NAME\": \"Name\"\n        },\n        \"HEADER\": {\n            \"ID\": \"ID\",\n            \"NAME\": \"Name\",\n            \"DEPLOY-TIME\": \"Deploy time\",\n            \"CATEGORY\": \"Category\",\n            \"TENANT\": \"Tenant\"\n        },\n        \"ACTION\": {\n            \"UPLOAD\": \"Upload process or package\",\n            \"DELETE\": \"Delete deployment\"\n        },\n        \"POPUP\": {\n            \"UPLOAD\": {\n                \"DESCRIPTION\": \"Select a .bpmn, .bpmn20.xml process file to deploy or upload a package of processes (with assets) contained in .zip or .bar file.\",\n                \"DROPZONE\": \"Or drop a file here\",\n                \"NO-DROP\": \"File drop is not supported by your browser\",\n                \"CANCEL-UPLOAD\": \"Cancel upload\",\n                \"ERROR\": \"Could not upload this file\"\n            },\n            \"DELETE\": {\n            \t\"CONFIRM-MESSAGE\": \"Delete deployment '{{name}}'?\"\n            \t}\n        }\n    },\n    \"DEPLOYMENT\": {\n        \"ID\": \"ID:\",\n        \"NAME\": \"Name:\",\n        \"TIME\": \"Deployment time:\",\n        \"CATEGORY\": \"Category:\",\n        \"PARENT-DEPLOYMENT-ID\": \"Parent deployment id:\",\n        \"TENANTID\": \"Tenant identifier:\",\n        \"DEFINITIONS-MESSAGE\": \"This deployment has {{total}} process definitions, showing {{size}}.\",\n        \"DEFINITIONS-MESSAGE-EMPTY\": \"This deployment has no process definitions.\",\n        \"TITLE\": {\n            \"DEFINITIONS\": \"Process Definitions\",\n            \"RESOURCES\": \"Resources\"\n        },\n        \"ACTION\": {\n            \"SHOW-ALL-DEFINITIONS\": \"Show all definitions\"\n        }\n    },\n    \"JOB\": {\n        \"TITLE\": {\n            \"MAIN\": \"Job {{id}}\",\n            \"EXCEPTION\": \"Exception\"\n        },\n        \"ACTIONS\": {\n            \"EXECUTE\": \"Execute job\",\n            \"MOVE\": \"Move job\",\n            \"DELETE\": \"Delete job\"\n        },\n        \"POPUP\": {\n            \"DELETE-JOB\": {\n                \"TITLE\": \"Delete job '{{id}}'\",\n                \"MESSAGE\": \"Are you sure you want to delete job {{id}}?\",\n                \"CONFIRM\": \"Delete job\"\n            }\n        },\n        \"ID\": \"ID:\",\n        \"EXECUTION-ID\": \"Execution ID:\",\n        \"PROCESS-INSTANCE\": \"Process instance:\",\n        \"PROCESS-DEFINITION\": \"Process definition:\",\n        \"CASE-INSTANCE\": \"Case instance:\",\n        \"CASE-DEFINITION\": \"Case definition:\",\n        \"DUEDATE\": \"Due date:\",\n        \"RETRIES-LEFT\": \"Retries left:\",\n        \"TENANT-ID\": \"Tenant:\"\n    },\n    \"JOBS\": {\n        \"TITLE\": \"Jobs\",\n        \"LIST-MESSAGE\": \"Showing {{size}} results, from a total of {{total}} matching jobs.\",\n        \"LIST-MESSAGE-EMPTY\": \"No matching jobs.\",\n        \"FILTER\": {\n        \t\"JOBTYPE\": {\n        \t\t\"LABEL\": \"Job type\",\n        \t\t\"EXECUTABLE-JOB\": \"Executable jobs\",\n        \t\t\"TIMER-JOB\": \"Timer jobs\",\n        \t\t\"SUSPENDED-JOB\": \"Suspended jobs\",\n        \t\t\"DEADLETTER-JOB\": \"Deadletter jobs\"\n        \t},\n            \"PROCESS-DEFINITION\": \"Process definition\",\n            \"ALL-PROCESS-DEFINITIONS\": \"All process definitions\",\n            \"PROCESS-INSTANCE-ID\": \"Process instance ID\",\n            \"CASE-DEFINITION\": \"Case definition\",\n            \"ALL-CASE-DEFINITIONS\": \"All case definitions\",\n            \"CASE-INSTANCE-ID\": \"Case instance ID\",\n            \"TENANT-ID\": \"Tenant identifier\",\n            \"DUE-BEFORE\": \"Due before\",\n            \"DUE-AFTER\": \"Due after\",\n            \"EXCEPTION\": \"Exception\",\n            \"EXCEPTION-HELP\": \"Only show jobs with an exception\"\n        },\n        \"SORT\": {\n            \"ID\": \"Job ID\",\n            \"DUE-DATE\": \"Due date\",\n            \"PROCESS-INSTANCE-ID\": \"Process instance ID\",\n            \"CASE-INSTANCE-ID\": \"Case instance ID\"\n        },\n        \"HEADER\": {\n            \"ID\": \"ID\",\n            \"DUE-DATE\": \"Due date\",\n            \"PROCESS-DEFINITION\": \"Process definition\",\n            \"CASE-DEFINITION\": \"Case definition\",\n            \"RETRIES\": \"Retries\",\n            \"EXCEPTION\": \"Exception\"\n        }\n    },\n    \"EVENT-SUBSCRIPTION\": {\n        \"TITLE\": {\n            \"MAIN\": \"Event subscription {{id}}\"\n        },\n        \"ACTIONS\": {\n            \"TRIGGER\": \"Trigger event\"\n        },\n        \"ID\": \"ID:\",\n        \"ACTIVITY-ID\": \"Activity ID:\",\n        \"EXECUTION-ID\": \"Execution ID:\",\n        \"PROCESS-INSTANCE\": \"Process instance:\",\n        \"PROCESS-DEFINITION\": \"Process definition:\",\n        \"CREATE-DATE\": \"Created:\",\n        \"EVENT-TYPE\": \"Event type:\",\n        \"EVENT-NAME\": \"Event name:\",\n        \"TENANT-ID\": \"Tenant:\"\n    },\n    \"EVENT-SUBSCRIPTIONS\": {\n    \t\"TITLE\": \"Event subscriptions\",\n        \"LIST-MESSAGE\": \"Showing {{size}} results, from a total of {{total}} matching event subscriptions.\",\n        \"LIST-MESSAGE-EMPTY\": \"No matching event subscriptions.\",\n    \t\"FILTER\": {\n            \"PROCESS-DEFINITION\": \"Process definition\",\n            \"ALL-PROCESS-DEFINITIONS\": \"All process definitions\",\n            \"PROCESS-INSTANCE-ID\": \"Process instance ID\",\n            \"TENANT-ID\": \"Tenant identifier\",\n            \"CREATED-BEFORE\": \"Created before\",\n            \"CREATED-AFTER\": \"Created after\"\n        },\n        \"SORT\": {\n            \"ID\": \"Event subscription ID\",\n            \"CREATE-DATE\": \"Created\",\n            \"PROCESS-INSTANCE-ID\": \"Process instance ID\"\n        },\n    \t\"HEADER\": {\n            \"ID\": \"ID\",\n            \"CREATE-DATE\": \"Created\",\n            \"PROCESS-DEFINITION\": \"Process definition\",\n            \"EVENT-TYPE\": \"Event type\",\n            \"EVENT-NAME\": \"Event name\"\n        }\n    },\n    \"LOGIN\": {\n        \"TITLE\": \"Sign in\",\n        \"USERNAME\": \"Username\",\n        \"USERNAME-PLACEHOLDER\": \"Enter your username\",\n        \"PASSWORD\": \"Password\",\n        \"PASSWORD-PLACEHOLDER\": \"Enter your password\",\n        \"ACTION\": {\n            \"CONFIRM\": \"Sign in\"\n        }\n    },\n    \"USER\": {\n        \"POPUP\": {\n            \"CHANGE-PASSWORD\": {\n                \"TITLE\": \"Change password for '{{login}}'\",\n                \"OLD-PASSWORD\": \"Old password\",\n                \"NEW-PASSWORD\": \"New password\",\n                \"CONFIRM\": \"Change password\"\n            },\n            \"DELETE\": {\n                \"TITLE\": \"Delete user {{login}}\",\n                \"MESSAGE\": \"Are you sure you want to delete user '{{login}}'?\",\n                \"CONFIRM\": \"Delete user\"\n            },\n            \"EDIT\": {\n                \"TITLE\": \"Edit user {{login}}\",\n                \"LOGIN\": \"Login\",\n                \"EMAIL\": \"Email\",\n                \"FIRSTNAME\": \"Firstname\",\n                \"LASTNAME\": \"Lastname\",\n                \"CONFIRM\": \"Update user\"\n            },\n            \"NEW\": {\n                \"TITLE\": \"Create new user\",\n                \"LOGIN\": \"Login\",\n                \"EMAIL\": \"Email\",\n                \"FIRSTNAME\": \"Firstname\",\n                \"LASTNAME\": \"Lastname\",\n                \"PASSWORD\": \"Password\",\n                \"ADMIN\": \"Has admin rights\",\n                \"CONFIRM\": \"Create user\"\n            }\n        }\n    },\n    \"USERS\": {\n        \"TITLE\": \"Users\",\n        \"ACTION\": {\n            \"EDIT\": \"Edit user\",\n            \"NEW\": \"Create new user\",\n            \"DELETE\": \"Delete user\",\n            \"CHANGE-PASSWORD\": \"Change password\"\n        },\n        \"HEADER\": {\n            \"LOGIN\": \"Login\",\n            \"FIRSTNAME\": \"Firstname\",\n            \"LASTNAME\": \"Lastname\",\n            \"EMAIL\": \"Email\",\n            \"CLUSTER_USER\": \"Cluster user\"\n        }\n    },\n    \"LICENSE\": {\n        \"POPUP\": {\n            \"TITLE\": \"License information\",\n            \"HOLDER\": \"Holder\",\n            \"SUBJECT\": \"Subject\",\n            \"PRODUCTKEY\": \"Product type\",\n            \"GOODAFTERDATE\": \"License valid after\",\n            \"GOODBEFOREDATE\": \"License valid until\",\n            \"NUMBER_OF_PROCESSES\": \"Number of active processes\",\n            \"NUMBER_OF_ADMINS\": \"Number of administrator users\",\n            \"MULTI_TENANT\": \"Multi tenant\",\n            \"DEFAULT_TENANT\": \"Default tenant\"\n        }\n    },\n    \"CLUSTER\": {\n        \"NAME\": \"Name:\",\n        \"USER\": \"User:\",\n        \"MASTER-MANDATORY\": \"Master configuration mandatory:\",\n        \"METRICS-SEND-INTERVAL\": \"Metric send interval:\",\n        \"ENDPOINT-HELP\": \"The endpoint configuration (each cluster has only one) needs to point to a Flowable REST installation. This endpoint will then be used to retrieve and manage the data used in the other sections (for example deployments, process definitions, and so on) of this application.\",\n        \"ENDPOINT-NAME\": \"Name:\",\n        \"ENDPOINT-DESCRIPTION\": \"Description:\",\n        \"ENDPOINT-ADDRESS\": \"Server address:\",\n        \"ENDPOINT-PORT\": \"Server port:\",\n        \"ENDPOINT-CONTEXT-ROOT\": \"Context root:\",\n        \"ENDPOINT-REST-ROOT\": \"REST root:\",\n        \"ENDPOINT-USERNAME\": \"Username:\",\n        \"PROCESS-ENGINE-HELP\": \"This section allows you to define a 'master configuration' for the cluster. All instances in the cluster will use this configuration when they boot up (if the cluster config jar is on the classpath or if the corresponding properties are set). If not set, the instances will use their local configuration files.\",\n        \"NO-MASTER-DEFINED\": \"No master configuration defined\",\n        \"ACTION\": {\n            \"SHOW-PASSWORD\": \"Show password\",\n            \"EDIT-CLUSTER-CONFIG\": \"Edit cluster configuration\",\n            \"CREATE-CLUSTER-CONFIG\": \"Create new cluster\",\n            \"DELETE-CLUSTER-CONFIG\": \"Delete cluster configuration\",\n            \"GENERATE-JAR\": \"Generate cluster config jar\",\n            \"EDIT-ENDPOINT\": \"Edit REST endpoint\",\n            \"CHECK-ENDPOINT\": \"Check REST endpoint\",\n            \"SELECT-MASTER\": \"Select master configuration\",\n            \"ADD-CONFIGURATION\": \"Add master configuration\",\n            \"EDIT-CONFIGURATION\": \"Edit master configuration\",\n            \"DELETE-CONFIGURATION\": \"Delete master configuration\"\n        },\n        \"TITLE\": {\n            \"PROCESS-ENDPOINT\": \"Process API Endpoint configuration\",\n            \"CMMN-ENDPOINT\": \"CMMN API Endpoint configuration\",\n            \"DMN-ENDPOINT\": \"DMN API Endpoint configuration\",\n            \"FORM-ENDPOINT\": \"Form API Endpoint configuration\",\n            \"CONTENT-ENDPOINT\": \"Content API Endpoint configuration\",\n            \"APP-ENDPOINT\": \"App API Endpoint configuration\"\n        },\n        \"POPUP\": {\n            \"EDIT-ENDPOINT\": {\n                \"ENDPOINT-NAME\": \"Name\",\n                \"ENDPOINT-DESCRIPTION\": \"Description\",\n                \"ENDPOINT-ADDRESS\": \"Server address\",\n                \"ENDPOINT-PORT\": \"Server port\",\n                \"ENDPOINT-CONTEXT-ROOT\": \"Context root\",\n                \"ENDPOINT-REST-ROOT\": \"REST root\",\n                \"ENDPOINT-USERNAME\": \"Username\",\n                \"ENDPOINT-PASSWORD\": \"Password\",\n                \"ENDPOINT-PASSWORD-HELP\": \"Leave blank to keep current password\",\n                \"ENDPOINT-URL-PREVIEW\": \"URL preview\",\n                \"ACTION-CONFIRM\": \"Save endpoint configuration\",\n                \"ERROR-401\": \"Error: invalid credentials\",\n                \"ERROR-403\": \"Error: invalid credentials or URL\",\n                \"ERROR-404\": \"Error: URL not found\",\n                \"ERROR-500\": \"Error: server error. Check server logs.\"\n            }\n        }\n    },\n    \"APP-DEPLOYMENTS\": {\n        \"TITLE\": \"App Deployments\",\n        \"LIST-MESSAGE\": \"Showing {{size}} results, from a total of {{total}} matching app deployments.\",\n        \"LIST-MESSAGE-EMPTY\": \"No matching app deployments.\",\n        \"FILTER\": {\n            \"NAME\": \"Name\",\n            \"TENANTID\": \"Tenant identifier\",\n            \"LATEST\": \"Latest version\",\n            \"LATEST-HELP\": \"Only show latest versions\"\n        },\n        \"SORT\": {\n            \"ID\": \"ID\",\n            \"NAME\": \"Name\"\n        },\n        \"HEADER\": {\n            \"ID\": \"ID\",\n            \"APP-DEFINITION-ID\": \"App ID\",\n            \"DEPLOYMENT-ID\": \"Process Deployment ID\",\n            \"DMN-DEPLOYMENT-ID\": \"DMN Deployment ID\",\n            \"NAME\": \"Name\",\n            \"DEPLOY-TIME\": \"Deploy time\",\n            \"DEPLOYED-BY\": \"Deployed by\",\n            \"TENANT\": \"Tenant ID\"\n        },\n        \"ACTION\": {\n            \"UPLOAD\": \"Upload and publish an app\"\n        },\n        \"POPUP\": {\n            \"UPLOAD\": {\n                \"DESCRIPTION\": \"Select a .zip app definition to deploy.\",\n                \"WARNING\": \"Uploading a process is only possible to an Flowable UI instance.\",\n                \"DROPZONE\": \"Or drop a file here\",\n                \"NO-DROP\": \"File drop is not supported by your browser\",\n                \"CANCEL-UPLOAD\": \"Cancel upload\",\n                \"ERROR\": \"Could not upload this file\"\n            }\n        }\n    },\n    \"VARIABLES\": {\n        \"HEADER\": {\n            \"NAME\": \"Name\",\n            \"TYPE\": \"Type\",\n            \"VALUE\": \"Value\"\n        }\n    },\n    \"IDENTITY-LINKS\": {\n        \"HEADER\": {\n            \"GROUP-ID\": \"Group ID\",\n            \"TYPE\": \"Type\",\n            \"USER-ID\": \"User ID\"\n        }\n    },\n    \"ALERT\": {\n        \"GENERAL\": {\n            \"HTTP-ERROR\": \"We couldn't get data from the server\",\n            \"AUTHENTICATION-ERROR\": \"You entered invalid login credentials\"\n        },\n        \"ENGINE\": {\n            \"ENDPOINT-UPDATED\": \"Endpoint '{{name}}' updated.\",\n            \"ENDPOINT-INVALID\": \"Endpoint configuration for '{{name}}' is invalid.\",\n            \"ENDPOINT-VALID\": \"Endpoint valid, Engine at endpoint: {{name}} - {{version}}\"\n        },\n        \"JOB\": {\n            \"DELETED\": \"Job '{{id}}' deleted successfully.\",\n            \"MOVED\": \"Job '{{id}}' moved successfully.\",\n            \"EXECUTED\": \"Job '{{id}}' was executed successfully.\"\n        },\n        \"EVENT-SUBSCRIPTION\": {\n        \t\"TRIGGERED\": \"Event subscription '{{id}}' triggered successfully.\"\n        },\n        \"PROCESS-INSTANCE\": {\n            \"DELETED\": \"Process instance '{{id}}' deleted successfully.\",\n            \"TERMINATED\": \"Process instance '{{id}}' terminated successfully.\"\n        },\n        \"TASK\": {\n            \"DELETED\": \"Task '{{id}}' deleted successfully.\",\n            \"COMPLETED\": \"Task '{{id}}' completed successfully.\",\n            \"DELEGATED\": \"Task '{{id}}' delegated to user {{user}}.\",\n            \"RESOLVED\": \"Task '{{id}}' successfully resolved.\",\n            \"ASSIGNED\": \"Task '{{id}}' is now assigned to {{user}}.\",\n            \"UNASSIGNED\": \"Task '{{id}}' is now unassigned.\",\n            \"UPDATED\": \"Task '{{id}}' updated successfully.\"\n        },\n        \"USER\": {\n            \"DELETED\": \"User '{{login}}' deleted successfully.\",\n            \"UPDATED\": \"User '{{login}}' updated successfully.\",\n            \"CREATED\": \"User '{{login}}' created.\",\n            \"PASSWORD-CHANGED\": \"Password for '{{login}}' is changed successfully.\"\n        },\n        \"PROCESS-DEFINITION\": {\n            \"CATEGORY-UPDATED\": \"Process definition category updated\"\n        },\n        \"DEPLOYMENT\": {\n        \t\"DELETED-DEPLOYMENT\": \"Deleted deployment '{{name}}'\",\n        \t\"DELETE-ERROR\": \"Could not delete deployment. {{exception || ''}}\",\n        \t\"DEPLOYMENT-SUCCESS\": \"Deployment succeeded\"\n        },\n        \"APP-DEPLOYMENT\": {\n        \t\"DELETED-APP\": \"Deleted app '{{appDefinition.name}}'\",\n        \t\"DELETE-ERROR\": \"Could not delete app. {{message || ''}}\"\n        }\n    },\n    \"CMMN-DEPLOYMENTS\": {\n        \"TITLE\": \"Deployments\",\n        \"LIST-MESSAGE\": \"Showing {{size}} results, from a total of {{total}} matching deployments.\",\n        \"LIST-MESSAGE-EMPTY\": \"No matching deployments.\",\n        \"FILTER\": {\n            \"NAME\": \"Name (case sensitive)\",\n            \"TENANTID\": \"Tenant identifier (case sensitive)\"\n        },\n        \"SORT\": {\n            \"ID\": \"ID\",\n            \"NAME\": \"Name\"\n        },\n        \"HEADER\": {\n            \"ID\": \"ID\",\n            \"NAME\": \"Name\",\n            \"DEPLOY-TIME\": \"Deploy time\",\n            \"CATEGORY\": \"Category\",\n            \"TENANT\": \"Tenant\"\n        },\n        \"ACTION\": {\n            \"UPLOAD\": \"Upload case or package\",\n            \"DELETE\": \"Delete deployment\"\n        },\n        \"POPUP\": {\n            \"UPLOAD\": {\n                \"DESCRIPTION\": \"Select a .cmmn, .cmmn.xml case file to deploy or upload a package of cases (with assets) contained in .zip or .bar file.\",\n                \"DROPZONE\": \"Or drop a file here\",\n                \"NO-DROP\": \"File drop is not supported by your browser\",\n                \"CANCEL-UPLOAD\": \"Cancel upload\",\n                \"ERROR\": \"Could not upload this file\"\n            },\n            \"DELETE\": {\n                \"CONFIRM-MESSAGE\": \"Delete deployment '{{name}}'?\"\n                }\n        }\n    },\n    \"CMMN-DEPLOYMENT\": {\n        \"ID\": \"ID:\",\n        \"NAME\": \"Name:\",\n        \"TIME\": \"Deployment time:\",\n        \"CATEGORY\": \"Category:\",\n        \"TENANTID\": \"Tenant identifier:\",\n        \"PARENT-DEPLOYMENT-ID\": \"Parent deployment id:\",\n        \"DEFINITIONS-MESSAGE\": \"This deployment has {{total}} case definitions, showing {{size}}.\",\n        \"DEFINITIONS-MESSAGE-EMPTY\": \"This deployment has no case definitions.\",\n        \"TITLE\": {\n            \"CASE-DEFINITIONS\": \"Case Definitions\",\n            \"RESOURCES\": \"Resources\"\n        },\n        \"ACTION\": {\n            \"SHOW-ALL-DEFINITIONS\": \"Show all definitions\"\n        }\n    },\n    \"CASE-DEFINITIONS\": {\n        \"LIST-MESSAGE\": \"Showing {{size}} results, from a total of {{total}} matching definitions.\",\n        \"LIST-MESSAGE-EMPTY\": \"No matching case definitions.\",\n        \"FILTER\": {\n            \"NAME\": \"Name (case sensitive)\",\n            \"KEY\": \"Key (case sensitive)\",\n            \"DEPLOYMENT-ID\": \"Deployment ID\",\n            \"TENANT-ID\": \"Tenant ID\",\n            \"LATEST\": \"Latest version\",\n            \"LATEST-HELP\": \"Only show latest versions\"\n        },\n        \"TITLE\": {\n            \"MAIN\": \"Case Definitions\"\n        },\n        \"SORT\": {\n            \"ID\": \"ID\",\n            \"NAME\": \"Name\",\n            \"VERSION\": \"Version\"\n        },\n        \"HEADER\": {\n            \"ID\": \"ID\",\n            \"NAME\": \"Name\",\n            \"VERSION\": \"Version\",\n            \"KEY\": \"Key\",\n            \"TENANT\": \"Tenant\"\n        },\n        \"ACTIONS\": {\n            \"UPLOAD-FROM-MODELER\": \"Upload from Flowable Editor\"\n        },\n        \"POPUP\": {\n            \"UPLOAD-FROM-MODELER\": {\n                \"NAME\": \"User name\",\n                \"PASSWORD\": \"Password\",\n                \"ERROR\": \"We couldn't contact the Editor\",\n                \"UNAUTHORIZED\": \"Invalid credentials\",\n                \"UPLOAD-DESCRIPTION\": \"The process model will now be fetched and deployed to the currently active Flowable cluster. Select an appropriate name for deployment package.\"\n            }\n        }\n    },\n    \"CASE-DEFINITION\": {\n        \"ID\": \"ID:\",\n        \"NAME\": \"Name:\",\n        \"VERSION\": \"Version:\",\n        \"DESCRIPTION\": \"Description:\",\n        \"KEY\": \"Key:\",\n        \"CATEGORY\": \"Category:\",\n        \"DEPLOYMENT\": \"Deployment:\",\n        \"TENANT\": \"Tenant:\",\n        \"START-FORM-DEFINED\": \"Start form defined:\",\n        \"GRAPHICAL-NOTATION-DEFINED\": \"Graphical notation defined:\",\n        \"CASE-INSTANCES-SIZE\": \"Definition has {{total}} case instances running\",\n        \"CASE-INSTANCES-SHOWING\": \", showing {{size}} most recently started\",\n        \"CASE-INSTANCES-EMPTY\": \"Definition has no case instances running\",\n        \"JOBS-SIZE\": \"Definition has {{total}} jobs running\",\n        \"JOBS-EMPTY\": \"Definition has no jobs running\",\n        \"DECISION-TABLES-SIZE\": \"Definition has {{total}} decision tables.\",\n        \"DECISION-TABLES-EMPTY\": \"Definition has no decision tables.\",\n        \"FORM-DEFINITIONS-SIZE\": \"Definition has {{total}} form definitions.\",\n        \"FORM-DEFINITIONS-EMPTY\": \"Definition has no form definitions.\",\n        \"TITLE\": {\n            \"CASE-INSTANCES\": \"Case instances\",\n            \"JOBS\": \"Jobs\",\n            \"DECISION-TABLES\": \"Decision tables\",\n            \"FORMS\": \"Form definitions\"\n        },\n        \"ACTION\": {\n            \"EDIT-CATEGORY\": \"Edit category\",\n            \"SHOW-ALL-JOBS\": \"Show all jobs\",\n            \"SHOW-ALL-CASES\": \"Show all cases\",\n            \"SHOW-DIAGRAM\": \"Show case diagram\"\n        },\n        \"POPUP\": {\n            \"EDIT-CATEGORY\": {\n                \"TITLE\": \"Edit category for definition\",\n                \"MESSAGE\": \"The initial category for the definition is populated from the targetNameSpace attribute in the CMMN 1.1 XML, but can be altered after deployment.\",\n                \"CATEGORY\": \"Category\",\n                \"CATEGORY-PLACEHOLDER\": \"Enter a category\",\n                \"CONFIRM\": \"Update category\"\n            },\n            \"SHOW-CASE-MODEL\": {\n                \"TITLE\": \"Case diagram\"\n            }\n        }\n    },\n    \"CASE-INSTANCES\": {\n        \"TITLE\": \"Case instances\",\n        \"LIST-MESSAGE\": \"Showing {{size}} results, from a total of {{total}} matching case instances.\",\n        \"LIST-MESSAGE-EMPTY\": \"No matching case instances.\",\n        \"FILTER\": {\n            \"NAME\": \"Name\",\n            \"CASE-DEFINITION\": \"Case definition\",\n            \"ALL-CASE-DEFINITIONS\": \"All case definitions\",\n            \"STATUS\": \"Status\",\n            \"STATUS-ANY\": \"Any status\",\n            \"STATUS-ACTIVE\": \"Active instances\",\n            \"STATUS-COMPLETE\": \"Completed instances\",\n            \"BUSINESS-KEY\": \"Business key\",\n            \"STARTED-BEFORE\": \"Started before\",\n            \"STARTED-AFTER\": \"Started after\",\n            \"ENDED-BEFORE\": \"Ended before\",\n            \"ENDED-AFTER\": \"Ended after\",\n            \"VARIABLE\": \"Variable\",\n            \"VARIABLE-NAME\": \"Variable name\",\n            \"VARIABLE-VALUE\": \"Variable value\",\n            \"VARIABLE-BOOLEAN-VALUE\": \"Boolean value: {{value}}\",\n            \"TENANT-ID\": \"Tenant identifier\"\n        },\n        \"SORT\": {\n            \"ID\": \"ID\",\n            \"START-TIME\": \"Time started\"\n        },\n        \"HEADER\": {\n            \"ID\": \"ID\",\n            \"NAME\": \"Name\",\n            \"BUSINESS-KEY\": \"Business key\",\n            \"CASE-DEFINITION\": \"Case definition\",\n            \"CREATE-TIME\": \"Created\",\n            \"END-TIME\": \"Ended\",\n            \"STATUS\": \"Status\"\n        }\n    },\n    \"CASE-INSTANCE\": {\n        \"ID\": \"ID:\",\n        \"NAME\": \"Name:\",\n        \"DESCRIPTION\": \"Description:\",\n        \"BUSINESS-KEY\": \"Business key:\",\n        \"TENANT-ID\": \"Tenant:\",\n        \"STATUS\": \"Status:\",\n        \"STATUS-ACTIVE\": \"Active\",\n        \"STATUS-COMPLETED\": \"Completed\",\n        \"DELETE-REASON\": \"Delete reason:\",\n        \"STARTED-BY\": \"Started by:\",\n        \"END-TIME\": \"End time:\",\n        \"DURATION\": \"Duration:\",\n        \"TASKS-SIZE\": \"This case instance has {{total}} tasks.\",\n        \"TASKS-EMPTY\": \"This case instance has no tasks.\",\n        \"VARIABLES-SIZE\": \"This case instance has {{total}} variables.\",\n        \"VARIABLES-EMPTY\": \"This case instance has no variables.\",\n        \"JOBS-SIZE\": \"This case instance has {{total}} jobs.\",\n        \"JOBS-EMPTY\": \"This case instance has no jobs.\",\n        \"DECISION-TABLES-SIZE\": \"This case instance has {{total}} decision tables.\",\n        \"DECISION-TABLES-EMPTY\": \"This case instance has no decision tables.\",\n        \"FORM-INSTANCES-SIZE\": \"This case instance has {{total}} form instances.\",\n        \"FORM-INSTANCES-EMPTY\": \"This case instance has no form instances.\",\n        \"TITLE\": {\n            \"TASKS\": \"Tasks\",\n            \"VARIABLES\": \"Variables\",\n            \"JOBS\": \"Jobs\",\n            \"DECISION-TABLES\": \"Decision Tables\",\n            \"FORM-INSTANCES\": \"Form instances\"\n        },\n        \"ACTION\": {\n            \"DELETE\": \"Delete case instance\",\n            \"TERMINATE\": \"Terminate case instance\",\n            \"SHOW-ALL-TASKS\": \"Show all tasks\",\n            \"SHOW-ALL-JOBS\": \"Show all jobs\",\n            \"SHOW-DIAGRAM\": \"Show case diagram\",\n            \"TITLE-VARIABLES\": \"Actions on selected variable\",\n            \"DELETE-VARIABLE\": \"Delete the variable\",\n            \"UPDATE-VALUE\": \"Update variable\",\n            \"ADD-VARIABLE\": \"Add variable\"\n        },\n        \"POPUP\": {\n            \"DELETE\": {\n                \"TITLE\": \"Delete case instance\",\n                \"MESSAGE-DELETE\": \"Are you sure you want to delete the case instance\",\n                \"MESSAGE-TERMINATE\": \"Are you sure you want to terminate the case instance\",\n                \"DELETE-REASON\": \"Delete reason\",\n                \"DELETE-REASON-HELP\": \"Enter an optional delete reason\",\n                \"CONFIRM-DELETE\": \"Delete case instance\",\n                \"CONFIRM-TERMINATE\": \"Terminate case instance\"\n            },\n            \"SHOW-CASE-MODEL\": {\n                \"TITLE\": \"Case diagram\"\n            },\n            \"CREATE-VARIABLE\": {\n                \"TITLE\": \"Create Variable\",\n                \"NAME\": \"Variable name\",\n                \"TYPE\": \"Flowable variable type\",\n                \"VALUE\": \"Variable value\",\n                \"CREATE\": \"Create\"\n            },\n            \"UPDATE-VARIABLE\": {\n                \"TITLE\": \"Update variable '{{name}}'\",\n                \"NAME\": \"Variable name\",\n                \"VALUE\": \"Value\",\n                \"CHECKED\": \"true\",\n                \"UNCHECKED\": \"false\",\n                \"DATE-HELP\": \"ISO-8601 format (example : 2016-01-28T23:00:00Z)\",\n                \"ACTION-UPDATE\": \"Update\"\n            },\n            \"DELETE-VARIABLE\": {\n                \"TITLE\": \"Delete variable '{{name}}\",\n                \"MESSAGE\": \"Are you sure you want to remove this variable?\",\n                \"DELETE\": \"Delete\"\n            }\n        }\n    },\n    \"APP-DEPLOYMENTS\": {\n        \"TITLE\": \"Deployments\",\n        \"LIST-MESSAGE\": \"Showing {{size}} results, from a total of {{total}} matching deployments.\",\n        \"LIST-MESSAGE-EMPTY\": \"No matching deployments.\",\n        \"FILTER\": {\n            \"NAME\": \"Name (case sensitive)\",\n            \"TENANTID\": \"Tenant identifier (case sensitive)\"\n        },\n        \"SORT\": {\n            \"ID\": \"ID\",\n            \"NAME\": \"Name\"\n        },\n        \"HEADER\": {\n            \"ID\": \"ID\",\n            \"NAME\": \"Name\",\n            \"DEPLOY-TIME\": \"Deploy time\",\n            \"CATEGORY\": \"Category\",\n            \"TENANT\": \"Tenant\"\n        },\n        \"ACTION\": {\n            \"UPLOAD\": \"Upload app\",\n            \"DELETE\": \"Delete deployment\"\n        },\n        \"POPUP\": {\n            \"UPLOAD\": {\n                \"DESCRIPTION\": \"Select a .app app definition file to deploy or upload a package of an app with assets contained in a .zip or .bar file.\",\n                \"DROPZONE\": \"Or drop a file here\",\n                \"NO-DROP\": \"File drop is not supported by your browser\",\n                \"CANCEL-UPLOAD\": \"Cancel upload\",\n                \"ERROR\": \"Could not upload this file\"\n            },\n            \"DELETE\": {\n                \"CONFIRM-MESSAGE\": \"Delete deployment '{{name}}'?\"\n                }\n        }\n    },\n    \"APP-DEPLOYMENT\": {\n        \"ID\": \"ID:\",\n        \"NAME\": \"Name:\",\n        \"TIME\": \"Deployment time:\",\n        \"KEY\": \"Key:\",\n        \"CATEGORY\": \"Category:\",\n        \"TENANTID\": \"Tenant identifier:\",\n        \"DEFINITIONS-MESSAGE\": \"This deployment has {{total}} app definitions, showing {{size}}.\",\n        \"DEFINITIONS-MESSAGE-EMPTY\": \"This deployment has no app definitions.\",\n        \"TITLE\": {\n            \"APP-DEFINITIONS\": \"App Definitions\",\n            \"RESOURCES\": \"Resources\"\n        },\n        \"ACTION\": {\n            \"SHOW-ALL-DEFINITIONS\": \"Show all definitions\"\n        }\n    },\n    \"APP-DEFINITIONS\": {\n        \"LIST-MESSAGE\": \"Showing {{size}} results, from a total of {{total}} matching definitions.\",\n        \"LIST-MESSAGE-EMPTY\": \"No matching app definitions.\",\n        \"FILTER\": {\n            \"NAME\": \"Name (case sensitive)\",\n            \"KEY\": \"Key (case sensitive)\",\n            \"DEPLOYMENT-ID\": \"Deployment ID\",\n            \"TENANT-ID\": \"Tenant ID\",\n            \"LATEST\": \"Latest version\",\n            \"LATEST-HELP\": \"Only show latest versions\"\n        },\n        \"TITLE\": {\n            \"MAIN\": \"App Definitions\"\n        },\n        \"SORT\": {\n            \"ID\": \"ID\",\n            \"NAME\": \"Name\",\n            \"VERSION\": \"Version\"\n        },\n        \"HEADER\": {\n            \"ID\": \"ID\",\n            \"NAME\": \"Name\",\n            \"VERSION\": \"Version\",\n            \"KEY\": \"Key\",\n            \"TENANT\": \"Tenant\"\n        }\n    },\n    \"APP-DEFINITION\": {\n        \"ID\": \"ID:\",\n        \"NAME\": \"Name:\",\n        \"VERSION\": \"Version:\",\n        \"DESCRIPTION\": \"Description:\",\n        \"KEY\": \"Key:\",\n        \"CATEGORY\": \"Category:\",\n        \"DEPLOYMENT\": \"Deployment:\",\n        \"TENANT\": \"Tenant:\",\n        \"PROCESS-DEFINITIONS-SIZE\": \"App has {{total}} process definitions\",\n        \"PROCESS-DEFINITIONS-EMPTY\": \"App has no process definitions\",\n        \"CASE-DEFINITIONS-SIZE\": \"App has {{total}} case definitions\",\n        \"CASE-DEFINITIONS-EMPTY\": \"App has no case definitions\",\n        \"DECISION-TABLES-SIZE\": \"App has {{total}} decision tables.\",\n        \"DECISION-TABLES-EMPTY\": \"App has no decision tables.\",\n        \"FORM-DEFINITIONS-SIZE\": \"App has {{total}} form definitions.\",\n        \"FORM-DEFINITIONS-EMPTY\": \"App has no form definitions.\",\n        \"TITLE\": {\n            \"PROCESS-DEFINITIONS\": \"Process definitions\",\n            \"CASE-DEFINITIONS\": \"Case definitions\",\n            \"DECISION-TABLES\": \"Decision tables\",\n            \"FORM-DEFINITIONS\": \"Form definitions\"\n        },\n        \"ACTION\": {\n            \"EDIT-CATEGORY\": \"Edit category\"\n        }\n    },\n    \"DECISION-TABLE-DEPLOYMENTS\": {\n        \"TITLE\": \"Decision Table Deployments\",\n        \"LIST-MESSAGE\": \"Showing {{size}} results, from a total of {{total}} matching deployments.\",\n        \"LIST-MESSAGE-EMPTY\": \"No matching deployments.\",\n        \"FILTER\": {\n            \"NAME\": \"Name (case sensitive)\",\n            \"TENANTID\": \"Tenant identifier (case sensitive)\"\n        },\n        \"SORT\": {\n            \"ID\": \"ID\",\n            \"NAME\": \"Name\"\n        },\n        \"HEADER\": {\n            \"ID\": \"ID\",\n            \"NAME\": \"Name\",\n            \"DEPLOY-TIME\": \"Deploy time\",\n            \"CATEGORY\": \"Category\",\n            \"TENANT\": \"Tenant\"\n        },\n        \"ACTION\": {\n            \"UPLOAD\": \"Upload decision\",\n            \"DELETE\": \"Delete deployment\"\n        },\n        \"POPUP\": {\n            \"UPLOAD\": {\n                \"DESCRIPTION\": \"Select a .dmn, .dmn.xml decision file to deploy to the DMN engine.\",\n                \"DROPZONE\": \"Or drop a file here\",\n                \"NO-DROP\": \"File drop is not supported by your browser\",\n                \"CANCEL-UPLOAD\": \"Cancel upload\",\n                \"ERROR\": \"Could not upload this file\"\n            },\n            \"DELETE\": {\n                \"CONFIRM-MESSAGE\": \"Delete deployment '{{name}}'?\"\n            }\n        }\n    },\n    \"DECISION-TABLE-DEPLOYMENT\": {\n        \"ID\": \"ID:\",\n        \"NAME\": \"Name:\",\n        \"TIME\": \"Deployment time:\",\n        \"CATEGORY\": \"Category:\",\n        \"TENANTID\": \"Tenant identifier:\",\n        \"DECISION-TABLES-MESSAGE\": \"This deployment has {{total}} decision tables, showing {{size}}.\",\n        \"DECISION-TABLES-MESSAGE-EMPTY\": \"This deployment has no decision tables.\",\n        \"PARENT-DEPLOYMENT-ID\": \"Parent deployment ID\",\n        \"TITLE\": {\n            \"DECISION-TABLES\": \"Decision Tables\",\n            \"RESOURCES\": \"Resources\"\n        },\n        \"ACTION\": {\n            \"SHOW-ALL-DEFINITIONS\": \"Show all decision tables\"\n        }\n    },\n    \"DECISION-TABLES\": {\n        \"TITLE\": \"Decision tables\",\n        \"LIST-MESSAGE\": \"Showing {{size}} results, from a total of {{total}} matching decision tables.\",\n        \"LIST-MESSAGE-EMPTY\": \"No matching decision tables.\",\n        \"FILTER\": {\n            \"NAME\": \"Name\",\n            \"KEY\": \"Key\",\n            \"TENANTID\": \"Tenant identifier\"\n        },\n        \"SORT\": {\n            \"ID\": \"ID\",\n            \"NAME\": \"Name\"\n        },\n        \"HEADER\": {\n            \"ID\": \"ID\",\n            \"NAME\": \"Name\",\n            \"VERSION\": \"Version\",\n            \"KEY\": \"Key\",\n            \"DEPLOY-TIME\": \"Deploy time\",\n            \"TENANT-ID\": \"Tenant ID\"\n        }\n    },\n    \"DECISION-TABLE\": {\n        \"ID\": \"ID:\",\n        \"NAME\": \"Name:\",\n        \"VERSION\": \"Version:\",\n        \"KEY\": \"Key:\",\n        \"CATEGORY\": \"Category:\",\n        \"DEPLOYMENT-ID\": \"Deployment ID:\",\n        \"PARENT-DEPLOYMENT-ID\": \"Parent deployment ID\",\n        \"RESOURCE-NAME\": \"Resource name:\",\n        \"DESCRIPTION\": \"Description:\",\n        \"TENANT\": \"Tenant:\",\n        \"TITLE\": {\n            \"DECISION-AUDITS\": \"Decision audits\"\n        },\n        \"DECISION-EXECUTION-MESSAGE\": \"This decision table has {{total}} executions, showing {{size}}.\",\n        \"DECISION-EXECUTION-MESSAGE-EMPTY\": \"This decision table has no executions\",\n        \"ACTION\": {\n            \"EDIT-CATEGORY\": \"Edit category\",\n            \"SHOW-ALL-JOBS\": \"Show all jobs\",\n            \"SHOW-ALL-PROCESSES\": \"Show all processes\",\n            \"SHOW-DIAGRAM\": \"Show process diagram\",\n            \"SHOW-DECISION-TABLE\": \"Show decision table\",\n            \"SHOW-ALL-EXECUTIONS\": \"Show all executions\"\n        },\n        \"POPUP\": {\n            \"TITLE\": \"Decision Table: \",\n            \"KEY\": \"Key: \",\n            \"HIT-POLICY\": \"Hit Policy: \",\n            \"HIT-POLICIES\": {\n                \"FIRST\": \"First (Single pass)\",\n                \"ANY\": \"Any (Single pass)\"\n            }\n        }\n    },\n    \"DECISION-TABLE-EXECUTIONS\": {\n        \"TITLE\": \"Decision table executions\",\n        \"LIST-MESSAGE\": \"Showing {{size}} results, from a total of {{total}} matching decision table executions.\",\n        \"LIST-MESSAGE-EMPTY\": \"No matching decision table executions.\",\n        \"FILTER\": {\n            \"DEFINITION-ID\": \"Definition ID\",\n            \"PROCESS-INSTANCE-ID\": \"Process Instance ID\",\n            \"CASE-INSTANCE-ID\": \"Case Instance ID\",\n            \"TENANTID\": \"Tenant identifier\"\n        },\n        \"SORT\": {\n            \"START-TIME\": \"Start Time\",\n            \"END-TIME\": \"End Time\",\n            \"TENANT-ID\": \"Tenant ID\"\n        },\n        \"HEADER\": {\n            \"ID\": \"ID\",\n            \"DECISION-DEFINITION-KEY\": \"Decision Key\",\n            \"DECISION-DEFINITION-NAME\": \"Decision Name\",\n            \"FAILED\": \"Failed\",\n            \"END-TIME\": \"End Time\",\n            \"TENANT-ID\": \"Tenant ID\"\n        }\n    },\n    \"DECISION-TABLE-EXECUTION\": {\n        \"TITLE\": \"Decision table execution\",\n        \"LIST-MESSAGE\": \"Showing {{size}} results, from a total of {{total}} matching decision tables.\",\n        \"LIST-MESSAGE-EMPTY\": \"No matching decision tables.\",\n        \"DEFINITION-ID\": \"Decision Definition ID\",\n        \"DEPLOYMENT-ID\": \"Deployment ID\",\n        \"DEFINITION-KEY\": \"Decision Key\",\n        \"DEFINITION-NAME\": \"Decision Name\",\n        \"DEFINITION-VERSION\": \"Decision Version\",\n        \"PROCESS-INSTANCE-ID\": \"Process Instance ID\",\n        \"CASE-INSTANCE-ID\": \"Case Instance ID\",\n        \"EXECUTION-START-TIME\": \"Start Time\",\n        \"EXECUTION-END-TIME\": \"End Time\",\n        \"FAILED\": \"Failed\",\n        \"FILTER\": {\n            \"DEFINITION-ID\": \"Definition ID\",\n            \"PROCESS-INSTANCE-ID\": \"Process Instance ID\",\n            \"CASE-INSTANCE-ID\": \"Case Instance ID\",\n            \"TENANTID\": \"Tenant identifier\"\n        },\n        \"SORT\": {\n            \"START-TIME\": \"Start Time\",\n            \"END-TIME\": \"End Time\",\n            \"TENANT-ID\": \"Tenant ID\"\n        },\n        \"HEADER\": {\n            \"ID\": \"ID\",\n            \"DECISION-DEFINITION-ID\": \"Definition ID\",\n            \"DECISION-KEY\": \"Decision Key\",\n            \"PROCESS-INSTANCE-ID\": \"Process Instance ID\",\n            \"CASE-INSTANCE-ID\": \"Case Instance ID\",\n            \"FAILED\": \"Failed\",\n            \"START-TIME\": \"Start Time\",\n            \"END-TIME\": \"End Time\",\n            \"TENANT-ID\": \"Tenant ID\"\n        },\n        \"AUDIT-DATA\": {\n            \"HEADER\": \"Audit Data\",\n            \"HIT-POLICY\": \"Hit Policy\",\n            \"STRICT-MODE\": \"Strict Mode enabled\",\n            \"EXCEPTION-MESSAGE\": \"Exception message\",\n            \"VALIDATION-MESSAGE\": \"Validation message\",\n            \"RESULT\": \"Result\",\n            \"RULE-EXECUTIONS\": \"Rule Executions\",\n            \"INPUT-VARIABLES\": \"Input Variables\",\n            \"VARIABLE-KEY\": \"Key\",\n            \"VARIABLE-VALUE\": \"Value\"\n        }\n    },\n    \"FORM-DEFINITIONS\": {\n    \t\"TITLE\": \"Form definitions\",\n        \"LIST-MESSAGE\": \"Showing {{size}} results, from a total of {{total}} matching forms.\",\n        \"LIST-MESSAGE-EMPTY\": \"No matching form definitions.\",\n        \"HEADER\": {\n            \"ID\": \"ID\",\n            \"NAME\": \"Name\",\n            \"DEPLOYMENTID\": \"Deployment ID\",\n            \"TENANTID\": \"Tenant ID\",\n            \"KEY\": \"Key\",\n            \"VERSION\": \"Version\"\n        },\n        \"FILTER\": {\n            \"NAME\": \"Name\",\n            \"APPID\": \"App deployment ID\",\n            \"TENANTID\": \"Tenant identifier\"\n        },\n        \"SORT\": {\n            \"ID\": \"ID\",\n            \"NAME\": \"Name\"\n        }\n    },\n    \"FORM-DEFINITION\": {\n        \"ID\": \"ID:\",\n        \"NAME\": \"Name:\",\n        \"KEY\": \"Key:\",\n        \"CATEGORY\": \"Category:\",\n        \"PARENT-DEPLOYMENT-ID\": \"Parent Deployment ID:\",\n        \"DEPLOYMENT-ID\": \"Deployment ID:\",\n        \"DESCRIPTION\": \"Description:\",\n        \"TENANT\": \"Tenant:\",\n        \"MESSAGE-EMPTY\": \"(None)\",\n        \"TITLE\": {\n            \"FORM-INSTANCES\": \"Form instances\"\n        },\n        \"FORM-INSTANCES-MESSAGE\": \"This definition has {{total}} form instances, showing {{size}}.\",\n        \"FORM-INSTANCES-MESSAGE-EMPTY\": \"This definition has no form instances\",\n        \"ACTION\": {\n            \"EDIT-CATEGORY\": \"Edit category\",\n            \"SHOW-ALL-JOBS\": \"Show all jobs\",\n            \"SHOW-ALL-PROCESSES\": \"Show all processes\",\n            \"SHOW-DIAGRAM\": \"Show process diagram\",\n            \"SHOW-FORM\": \"Show form\"\n        },\n        \"POPUP\": {\n            \"TITLE\": \"Form: \"\n        },\n        \"FIELD-PREVIEW\" : {\n        \t\"DISPLAY-REF\": \"Display value\",\n        \t\"SELECT-FIELD\": \"(No field selected)\",\n        \t\"FIELD-VALUE\": \"Show value of field \\\"{{name}}\\\"\",\n        \t\"UNKNOWN-TYPE\": \"Unknown field type {{type}}\",\n        \t\"TEXT-VALUE\": \"Text\",\n        \t\"MULTI-TEXT-VALUE\": \"Multi-line text\",\n        \t\"NUMBER-VALUE\": \"123\",\n        \t\"DATE-VALUE\": \"Date\",\n        \t\"DROPDOWN-VALUE\": \"Select ...\",\n        \t\"UPLOAD-VALUE\": \"Upload or import content...\",\n        \t\"RADIOS-OPTION1\": \"Option 1\",\n        \t\"SELECT-PERSON\": \"Select a person\",\n        \t\"SELECT-GROUP\": \"Select a group\"\n        \t}\n    },\n    \"FORM-DEPLOYMENTS\": {\n        \"TITLE\": \"Form Deployments\",\n        \"LIST-MESSAGE\": \"Showing {{size}} results, from a total of {{total}} matching form deployments.\",\n        \"LIST-MESSAGE-EMPTY\": \"No matching form deployments.\",\n        \"FILTER\": {\n            \"NAME\": \"Name (case sensitive)\",\n            \"TENANTID\": \"Tenant identifier (case sensitive)\"\n        },\n        \"SORT\": {\n            \"ID\": \"ID\",\n            \"NAME\": \"Name\"\n        },\n        \"HEADER\": {\n            \"ID\": \"ID\",\n            \"NAME\": \"Name\",\n            \"DEPLOY-TIME\": \"Deploy time\",\n            \"CATEGORY\": \"Category\",\n            \"TENANT\": \"Tenant\"\n        },\n        \"ACTION\": {\n            \"UPLOAD\": \"Upload form\",\n            \"DELETE\": \"Delete deployment\"\n        },\n        \"POPUP\": {\n            \"UPLOAD\": {\n                \"DESCRIPTION\": \"Select a .form, .json form file to deploy to the FORM engine.\",\n                \"DROPZONE\": \"Or drop a file here\",\n                \"NO-DROP\": \"File drop is not supported by your browser\",\n                \"CANCEL-UPLOAD\": \"Cancel upload\",\n                \"ERROR\": \"Could not upload this file\"\n            },\n            \"DELETE\": {\n                \"CONFIRM-MESSAGE\": \"Delete deployment '{{name}}'?\"\n            }\n        }\n    },\n    \"FORM-DEPLOYMENT\": {\n        \"ID\": \"ID:\",\n        \"NAME\": \"Name:\",\n        \"TIME\": \"Deployment time:\",\n        \"CATEGORY\": \"Category:\",\n        \"TENANTID\": \"Tenant identifier:\",\n        \"PARENT-DEPLOYMENT-ID\": \"Parent Deployment ID\",\n        \"DEFINITIONS-MESSAGE\": \"This deployment has {{total}} form definitions, showing {{size}}.\",\n        \"DEFINITIONS-MESSAGE-EMPTY\": \"This deployment has no form definitions.\",\n        \"TITLE\": {\n            \"FORM-DEFINITIONS\": \"Form Definitions\",\n            \"RESOURCES\": \"Resources\"\n        },\n        \"ACTION\": {\n            \"SHOW-ALL-DEFINITIONS\": \"Show all form definitions\"\n        }\n    },\n    \"FORM-INSTANCES\": {\n        \"TITLE\": \"Form instances\",\n        \"LIST-MESSAGE\": \"Showing {{size}} results, from a total of {{total}} matching form instances.\",\n        \"LIST-MESSAGE-EMPTY\": \"No matching form instances.\",\n        \"HEADER\": {\n            \"ID\": \"ID\",\n            \"PROCESS-INSTANCE-ID\": \"Process Instance ID\",\n            \"CASE-INSTANCE-ID\": \"Case Instance ID\",\n            \"TASK-ID\": \"Task ID\",\n            \"SUBMITTED-ON\": \"Submitted Date\",\n            \"SUBMITTED-BY\": \"Submitted By\",\n            \"TENANT-ID\": \"Tenant ID\"\n        },\n        \"FILTER\": {\n            \"NAME\": \"Name\",\n            \"TENANTID\": \"Tenant identifier\"\n        },\n        \"SORT\": {\n            \"SUBMITTED-DATE\": \"Submitted On\"\n        }\n    },\n    \"FORM-INSTANCE\": {\n        \"HEADER\": {\n            \"ID\": \"ID\",\n            \"TASK-ID\": \"Task ID\",\n            \"PROCESS-ID\": \"Process Instance ID\",\n            \"CASE-INSTANCE-ID\": \"Case Instance ID\",\n            \"SUBMITTED\": \"Submitted on\",\n            \"SUBMITTED-BY\": \"Submitted by\",\n            \"FORM-DEFINITION-ID\": \"Form Definition ID\"\n        },\n        \"FORM-FIELD-VALUES-MESSAGE\": \"This instance has {{total}} form field values, showing {{size}}\",\n        \"FORM-FIELD-VALUES-MESSAGE-EMPTY\": \"This instance has no form field values\",\n        \"ACTION\": {\n            \"SHOW-FORM-INSTANCE\": \"Show form instance\"\n        },\n        \"TITLE\": {\n            \"FORM-FIELD-VALUES\": \"Form field values\"\n        },\n        \"FORM-FIELD-VALUES\": {\n            \"ID\": \"Form field ID\",\n            \"NAME\": \"Form field name\",\n            \"TYPE\": \"Form field type\",\n            \"VALUE\": \"Form field value\"\n        }\n    },\n    \"CONTENT-ITEMS\": {\n        \"TITLE\": \"Content items\",\n        \"LIST-MESSAGE\": \"Showing {{size}} results, from a total of {{total}} matching content items.\",\n        \"LIST-MESSAGE-EMPTY\": \"No matching content items.\",\n        \"HEADER\": {\n            \"ID\": \"ID\",\n            \"NAME\": \"Name\",\n            \"PROCESS-INSTANCE-ID\": \"Process Instance ID\",\n            \"TASK-ID\": \"Task ID\",\n            \"LAST-MODIFIED-ON\": \"Last Modified Date\",\n            \"LAST-MODIFIED-BY\": \"Last Modified By\",\n            \"TENANT-ID\": \"Tenant ID\"\n        },\n        \"FILTER\": {\n            \"NAME\": \"Name\",\n            \"TENANTID\": \"Tenant identifier\"\n        },\n        \"SORT\": {\n            \"CREATED\": \"Created On\"\n        }\n    },\n    \"CONTENT-ITEM\": {\n        \"HEADER\": {\n            \"ID\": \"ID\",\n            \"TASK-ID\": \"Task ID\",\n            \"PROCESS-INSTANCE-ID\": \"Process Instance ID\",\n            \"CREATED-ON\": \"Created on\",\n            \"CREATED-BY\": \"Created by\",\n            \"LAST-MODIFIED-ON\": \"Last Modified Date\",\n            \"LAST-MODIFIED-BY\": \"Last Modified By\",\n            \"CONTENT-STORE-ID\": \"Content store ID\"\n        },\n        \"ACTION\": {\n            \"SHOW-CONTENT-ITEM\": \"Show content item\"\n        }\n    }\n}\n"
  },
  {
    "path": "flowable-ui-web/admin/i18n/es.json",
    "content": "{\n    \"GENERAL\": {\n        \"YES\": \"Si\",\n        \"NO\": \"No\",\n        \"ACTION\": {\n            \"LOGOUT\": \"Salir\",\n            \"DISMISS-ALERT\": \"Click para descartar este mensaje\",\n            \"RETURN-TO-LIST\": \"Regresar a la lista\",\n            \"SHOW-RESULTS\": \"Mostrar {{'GENERAL.RESULT-SIZES.' + resultSize.toString() | translate}} resultados\",\n            \"REFRESH-LIST\": \"Actualizar lista\",\n            \"SORT-BY\": \"Ordenar por {{name | translate}}\",\n            \"CLEAR-FILTERS\": \"Limpiar filtros\",\n            \"CANCEL-AND-CLOSE\": \"Cancelar y Cerrar\",\n            \"CANCEL\": \"Cancelar\",\n            \"NEXT\": \"Siguiente\",\n            \"PREVIOUS\": \"Anterior\",\n            \"CLOSE\": \"Cerrar\",\n            \"SHOWLICENSE\": \"Informacion de licencia\"\n        },\n        \"TITLE\": {\n            \"MAIN\": \"Administrador de actividades\",\n            \"ACTIONS\": \"Acciones\",\n            \"FILTERS\": \"Filtros\"\n        },\n        \"MENU\": {\n            \"PROCESS-ENGINE\": \"Motor de procesos\",\n            \"FORM-ENGINE\": \"Motor de formularios\",\n            \"CONTENT-ENGINE\": \"Motor de contenido\",\n            \"DMN-ENGINE\": \"Motor DMN\",\n            \"DEPLOYMENTS\": \"Despliegues\",\n            \"DEFINITIONS\": \"Definiciones\",\n            \"INSTANCES\": \"Instancias\",\n            \"TASKS\": \"Tareas\",\n            \"JOBS\": \"Trabajos\",\n            \"EVENT-SUBSCRIPTIONS\": \"Subscripciones a eventos\",\n            \"CONFIGURATION\": \"Configuracion\",\n            \"CONFIGURATION-ENGINE\": \"Motor\",\n            \"DECISION-TABLES\": \"Tablas de decision\",\n            \"CONTENT-ITEMS\": \"Contenidos\"\n        },\n        \"RESULT-SIZES\": {\n            \"10\": \"10\",\n            \"25\": \"25\",\n            \"50\": \"50\",\n            \"100\": \"100\",\n            \"100000000\": \"todo\"\n        }\n    },\n    \"PROCESS-DEFINITION\": {\n        \"ID\": \"Identificador:\",\n        \"NAME\": \"nombre:\",\n        \"VERSION\": \"Version:\",\n        \"DESCRIPTION\": \"Descripcion:\",\n        \"KEY\": \"Llave:\",\n        \"CATEGORY\": \"Categoria:\",\n        \"SUSPENDED\": \"Suspendido:\",\n        \"DEPLOYMENT\": \"Despliegue:\",\n        \"TENANT\": \"Tenant:\",\n        \"START-FORM-DEFINED\": \"Formulario inicial definido:\",\n        \"GRAPHICAL-NOTATION-DEFINED\": \"Notacion grafica definida:\",\n        \"PROCESS-INSTANCES-SIZE\": \"La definicion tiene {{total}} instancias de proceso corriendo\",\n        \"PROCESS-INSTANCES-SHOWING\": \", mostrando {{size}} iniciados mas recientemente\",\n        \"PROCESS-INSTANCES-EMPTY\": \"La definicion no tiene instancias de proceso corriendo\",\n        \"JOBS-SIZE\": \"La definicion tiene {{total}} trabajos corriendo\",\n        \"JOBS-EMPTY\": \"La definicion no tiene trabajos corriendo\",\n        \"DECISION-TABLES-SIZE\": \"La definicion {{total}} tablas de decision.\",\n        \"DECISION-TABLES-EMPTY\": \"La definicion no tiene tablas de decision.\",\n        \"FORM-DEFINITIONS-SIZE\": \"La definicion tiene {{total}} definiciones de formulario.\",\n        \"FORM-DEFINITIONS-EMPTY\": \"La definicion no tiene definiciones de formulario.\",\n        \"TITLE\": {\n            \"PROCESS-INSTANCES\": \"Instancias de proceso\",\n            \"JOBS\": \"Trabajos\",\n            \"DECISION-TABLES\": \"Tablas de decision\",\n            \"FORMS\": \"Definiciones de formulario\"\n        },\n        \"ACTION\": {\n            \"EDIT-CATEGORY\": \"Editar categoria\",\n            \"SHOW-ALL-JOBS\": \"Mostrar todos los trabajos\",\n            \"SHOW-ALL-PROCESSES\": \"Mostrar todos los procesos\",\n            \"SHOW-DIAGRAM\": \"Mostrar diagrama de proceso\"\n        },\n        \"POPUP\": {\n            \"EDIT-CATEGORY\": {\n                \"TITLE\": \"Editar catgoria para una definicion\",\n                \"MESSAGE\": \"La categoria inicial de la definicion es poblada desde el atributo targetNameSpace en el BPMN 2.0 XML, pero puede ser modificada despues del despliegue.\",\n                \"CATEGORY\": \"Categoria\",\n                \"CATEGORY-PLACEHOLDER\": \"Introduce una categoria\",\n                \"CONFIRM\": \"Actualizar categoria\"\n            },\n            \"SHOW-PROCESS-MODEL\": {\n                \"TITLE\": \"Diagrama de proceso\"\n            }\n        }\n    },\n    \"PROCESS-DEFINITIONS\": {\n        \"LIST-MESSAGE\": \"Mostrando {{size}} resultados, de un total de {{total}} definiciones similares.\",\n        \"LIST-MESSAGE-EMPTY\": \"No hay definiciones de proceso similares.\",\n        \"FILTER\": {\n            \"NAME\": \"Nombre (sensible a mayusculas y minusculas )\",\n            \"KEY\": \"Key (sensible a mayusculas y minusculas)\",\n            \"DEPLOYMENT-ID\": \"Identificador de despliegue\",\n            \"TENANT-ID\": \"Tenant ID\",\n            \"LATEST\": \"Ultima version\",\n            \"LATEST-HELP\": \"Mostrar solo las ultimas versiones\"\n        },\n        \"TITLE\": {\n            \"MAIN\": \"Definiciones de procesos\"\n        },\n        \"SORT\": {\n            \"ID\": \"Identificador\",\n            \"NAME\": \"Nombre\",\n            \"VERSION\": \"Version\"\n        },\n        \"HEADER\": {\n            \"ID\": \"Identificador\",\n            \"NAME\": \"Nombre\",\n            \"VERSION\": \"Version\",\n            \"KEY\": \"Key\",\n            \"TENANT\": \"Tenant\"\n        },\n        \"ACTIONS\": {\n            \"UPLOAD-FROM-MODELER\": \"Subir desde el Editor de Flowable\"\n        },\n        \"POPUP\": {\n            \"UPLOAD-FROM-MODELER\": {\n                \"NAME\": \"Usuario\",\n                \"PASSWORD\": \"Password\",\n                \"ERROR\": \"No se pudo contactar al Editor\",\n                \"UNAUTHORIZED\": \"Datos invalidos\",\n                \"UPLOAD-DESCRIPTION\": \"El modelo de proceso sera buscado y desplegado al cluster actualmente activo de Flowable. Selecciona un nombre apropiado para el paquete de despliegue.\"\n            }\n        }\n    },\n    \"PROCESS-INSTANCE\": {\n        \"ID\": \"Identificador:\",\n        \"NAME\": \"Nombre:\",\n        \"DESCRIPTION\": \"Descripcion:\",\n        \"BUSINESS-KEY\": \"Business key:\",\n        \"TENANT-ID\": \"Tenant:\",\n        \"STATUS\": \"Estatus:\",\n        \"STATUS-ACTIVE\": \"Activo\",\n        \"STATUS-COMPLETED\": \"Completado\",\n        \"ACTIVITY-ID-STARTED\": \"Identificador de inicio de actividad:\",\n        \"ACTIVITY-ID-ENDED\": \"Finalizado en actividad:\",\n        \"DELETE-REASON\": \"Razon de eliminado:\",\n        \"STARTED-BY\": \"Iniciado por:\",\n        \"END-TIME\": \"Hora de finalizacion:\",\n        \"DURATION\": \"Duracion:\",\n        \"SUPER-PROCESS-INSTANCE-ID\": \"Identificador de proceso padre:\",\n        \"TASKS-SIZE\": \"Esta instancia de proceso tiene {{total}} tareas.\",\n        \"TASKS-EMPTY\": \"Esta instancia de proceso no tiene tareas.\",\n        \"VARIABLES-SIZE\": \"Esta instancia de proceso tiene {{total}} variables.\",\n        \"VARIABLES-EMPTY\": \"Esta instancia de proceso no tiene variables.\",\n        \"JOBS-SIZE\": \"Esta instancia de proceso tiene {{total}} trabajos.\",\n        \"JOBS-EMPTY\": \"Esta instancia de proceso no tiene trabajos.\",\n        \"SUBPROCESSES-SIZE\": \"Esta instancia de proceso tiene {{total}} subprocesos.\",\n        \"SUBPROCESSES-EMPTY\": \"Esta instancia de proceso no tiene subprocesos.\",\n        \"DECISION-TABLES-SIZE\": \"Esta instancia de proceso tiene {{total}} tablas de decision.\",\n        \"DECISION-TABLES-EMPTY\": \"Esta instancia de proceso no tiene tablas de decision.\",\n        \"FORM-INSTANCES-SIZE\": \"Esta instancia de proceso tiene {{total}} instancias de formulario.\",\n        \"FORM-INSTANCES-EMPTY\": \"Esta instancia de proceso no tiene instancias de formulario.\",\n        \"TITLE\": {\n            \"TASKS\": \"Tareas\",\n            \"VARIABLES\": \"Variables\",\n            \"JOBS\": \"Trabajos\",\n            \"SUBPROCESSES\": \"Subprocesos\",\n            \"DECISION-TABLES\": \"Tablas de Decision\",\n            \"FORM-INSTANCES\": \"Instacias de Formularios\"\n        },\n        \"ACTION\": {\n            \"DELETE\": \"Eliminar instacia de proceso\",\n            \"TERMINATE\": \"Terminar instancia de proceso\",\n            \"SHOW-ALL-TASKS\": \"Mostrar todas las tareas\",\n            \"SHOW-ALL-JOBS\": \"Mostrar todos los trabajos\",\n            \"SHOW-ALL-SUBPROCESSES\": \"Mostrar todos los subprocesos\",\n            \"SHOW-DIAGRAM\": \"Mostrar diagrama de proceso\",\n            \"TITLE-VARIABLES\": \"Acciones en la variable selecionada\",\n            \"DELETE-VARIABLE\": \"Borra variable\",\n            \"UPDATE-VALUE\": \"Actualizar variable\",\n            \"ADD-VARIABLE\": \"Agregar variable\"\n        },\n        \"POPUP\": {\n            \"DELETE\": {\n                \"TITLE\": \"Eliminar instacia de proceso\",\n                \"MESSAGE-DELETE\": \"Estas seguro que deseas borrar la instancia de proceso\",\n                \"MESSAGE-TERMINATE\": \"Estas seguro que deseas terminar la instancia de proceso\",\n                \"DELETE-REASON\": \"Razon de eliminado\",\n                \"DELETE-REASON-HELP\": \"Introduce una razon de eliminado opcional\",\n                \"CONFIRM-DELETE\": \"Eliminar instancia de proceso\",\n                \"CONFIRM-TERMINATE\": \"Terminar instancia de proceso\"\n            },\n            \"SHOW-PROCESS-MODEL\": {\n                \"TITLE\": \"Diagrama de proceso\"\n            },\n            \"CREATE-VARIABLE\": {\n                \"TITLE\": \"Crear variable\",\n                \"NAME\": \"Nombre de variable\",\n                \"TYPE\": \"Tipo de variable de actividad\",\n                \"VALUE\": \"Valor de variable\",\n                \"CREATE\": \"Crear\"\n            },\n            \"UPDATE-VARIABLE\": {\n                \"TITLE\": \"Actualizar variable '{{name}}'\",\n                \"NAME\": \"Nombre variable\",\n                \"VALUE\": \"Valor\",\n                \"CHECKED\": \"true\",\n                \"UNCHECKED\": \"false\",\n                \"DATE-HELP\": \"ISO-8601 format (example : 2016-01-28T23:00:00Z)\",\n                \"ACTION-UPDATE\": \"Actualizar\"\n            },\n            \"DELETE-VARIABLE\": {\n                \"TITLE\": \"Borrar variable '{{name}}\",\n                \"MESSAGE\": \"Estas seguro que deseas eliminar esta variable?\",\n                \"DELETE\": \"Borrar\"\n            }\n        }\n    },\n    \"PROCESS-INSTANCES\": {\n        \"TITLE\": \"Instancias de proceso\",\n        \"LIST-MESSAGE\": \"Mostrando {{size}} resultados, de un total de {{total}} instancias de proceso similares.\",\n        \"LIST-MESSAGE-EMPTY\": \"No hay instancias de proceso similares.\",\n        \"FILTER\": {\n            \"NAME\": \"Nombre\",\n            \"PROCESS-DEFINITION\": \"Definicion de proceso\",\n            \"ALL-PROCESS-DEFINITIONS\": \"Todas las definiciones de proceo\",\n            \"BUSINESS-KEY\": \"Business key\",\n            \"SUPER-PROCESS-INSTANCE-ID\": \"Identificador de instancia de proceso padre\",\n            \"STARTED-BEFORE\": \"Iniciado antes\",\n            \"STARTED-AFTER\": \"Iniciado despues\",\n            \"ENDED-BEFORE\": \"Terminado antes\",\n            \"ENDED-AFTER\": \"Terminado despues\",\n            \"VARIABLE\": \"Variable\",\n            \"VARIABLE-NAME\": \"Nombre de variable\",\n            \"VARIABLE-VALUE\": \"Valor de variable\",\n            \"VARIABLE-BOOLEAN-VALUE\": \"Boolean value: {{value}}\",\n            \"TENANT-ID\": \"Tenant identifier\"\n        },\n        \"SORT\": {\n            \"ID\": \"ID\",\n            \"START-TIME\": \"Hora de inicio\"\n        },\n        \"HEADER\": {\n            \"ID\": \"ID\",\n            \"NAME\": \"Nombre\",\n            \"BUSINESS-KEY\": \"Business key\",\n            \"PROCESS-DEFINITION\": \"Definicion de proceso\",\n            \"CREATE-TIME\": \"Creado\",\n            \"END-TIME\": \"Finalizado\",\n            \"STATUS\":\"Estatus\"\n        }\n    },\n    \"TASK\": {\n        \"ID\": \"Identificador:\",\n        \"NAME\": \"Nombre:\",\n        \"STATUS\": \"Estatus:\",\n        \"STATUS-COMPLETED\": \"Completado\",\n        \"STATUS-ACTIVE\": \"Activo\",\n        \"DESCRIPTION\": \"Descripcion:\",\n        \"TASK-DEFINITION-KEY\": \"Definicion key:\",\n        \"FORM-KEY\": \"Formulario key:\",\n        \"PRIORITY\": \"Prioridad:\",\n        \"DELEGATION-STATE\": \"Delegation state:\",\n        \"CATEGORY\": \"Categoria:\",\n        \"TENANT-ID\": \"Tenant:\",\n        \"PARENT\": \"Tarea padre:\",\n        \"ASSIGNEE\": \"Assignado:\",\n        \"OWNER\": \"Propietario:\",\n        \"START-DATE\": \"Fecha de inicio:\",\n        \"DUE-DATE\": \"Fecha de vencimiento:\",\n        \"END-DATE\": \"Fecha de finalizacion:\",\n        \"DELETE-REASON\": \"Razon de eliminado:\",\n        \"PROCESS-INSTANCE\": \"Instancia de proceso\",\n        \"PROCESS-DEFINITION\": \"Definicion de proceso\",\n        \"EXECUTION-ID\": \"Identificador de Ejecucion:\",\n        \"SUBTASKS-MESSAGE\": \"Esta tarea tiene {{total}} subtareas, mostrando {{size}}.\",\n        \"SUBTASKS-MESSAGE-EMPTY\": \"Esta tarea no tiene subtareas.\",\n        \"VARIABLES-MESSAGE\": \"Esta tarea tiene {{size}} variables.\",\n        \"VARIABLES-MESSAGE-EMPTY\": \"Esta tarea no tiene variables.\",\n        \"IDENTITY-LINKS-MESSAGE\": \"Esta tarea tiene {{size}} identity links.\",\n        \"IDENTITY-LINKS-MESSAGE-EMPTY\": \"Esta tarea no tiene identity links.\",\n        \"ACTION\": {\n            \"EDIT\": \"Editar tarea\",\n            \"ASSIGN-CLAIM\": \"Asignar/Reclamar tarea\",\n            \"DELEGATE\": \"Delegar tarea\",\n            \"RESOLVE\": \"Resolver tarea\",\n            \"COMPLETE\": \"Completar tarea\",\n            \"DELETE\": \"Eliminar tarea\",\n            \"SHOW-ALL-SUBTASKS\": \"Mostrar todas las subtareas\",\n            \"SHOW-SUBMITTED-FORM\": \"Mostrar instancia de formulario\"\n        },\n        \"TITLE\": {\n            \"SUBTASKS\": \"Sub tareas\",\n            \"IDENTITY-LINKS\": \"Identity links\",\n            \"VARIABLES\": \"Variables\"\n        },\n        \"POPUP\": {\n            \"ASSIGN\": {\n                \"TITLE\": \"Asignar tareas\",\n                \"MESSAGE\": \"Estas seguro que deseas asignar la tarea\",\n                \"NEW-ASSIGNEE\": \"Nueva asignacion\",\n                \"NEW-ASSIGNEE-HELP\": \"Deja el campo asignado en blanco si deseas que la tarea no se asignada a nadie.\",\n                \"CONFIRM\": \"Asignar tarea\"\n            },\n            \"COMPLETE\": {\n                \"TITLE\": \"Completar tarea\",\n                \"MESSAGE\": \"Estas seguro que deseas completar la tarea\",\n                \"CONFIRM\": \"Completar tarea\"\n            },\n            \"DELEGATE\": {\n                \"TITLE\": \"Delegar tarea\",\n                \"MESSAGE\": \"Estas seguro que deseas delegar la tarea\",\n                \"CONFIRM\": \"Delegar tarea\",\n                \"DELEGATE-TO\": \"Usuario a quien delega\"\n            },\n            \"RESOLVE\": {\n                \"TITLE\": \"Resolver tarea\",\n                \"MESSAGE\": \"Estas seguro que deseas resolver la tarea\",\n                \"CONFIRM\": \"Resolver tarea\"\n            },\n            \"DELETE\": {\n                \"TITLE\": \"Eliminar tarea\",\n                \"MESSAGE\": \"Estas seguro que deseas borrar la tarea\",\n                \"CONFIRM\": \"Eliminar tarea\"\n            },\n            \"EDIT\": {\n                \"TITLE\": \"Editar tarea\",\n                \"CONFIRM\": \"Actualizar tarea\",\n                \"NAME\": \"Nombre\",\n                \"DESCRIPTION\": \"Descripcion\",\n                \"PRIORITY\": \"Prioridad\",\n                \"CATEGORY\": \"Categoria\",\n                \"ASSIGNEE\": \"Assignado\",\n                \"OWNER\": \"Propietario\",\n                \"DUE-DATE\": \"Fecha de vencimiento\"\n            }\n        }\n    },\n    \"TASKS\": {\n        \"TITLE\": \"Tareas\",\n        \"LIST-MESSAGE\": \"Mostrando {{size}} resultados, de un total de {{total}} tareas similares.\",\n        \"LIST-MESSAGE-EMPTY\": \"No hay tareas similares.\",\n        \"FILTER\": {\n            \"NAME\": \"Nombre (Sensible a mayusculas y minusculas)\",\n            \"ASSIGNEE\": \"Assignado (Sensible a mayusculas y minusculas)\",\n            \"STATUS\":\"Estatus\",\n            \"STATUS-ANY\": \"Cualquier estatus\",\n            \"STATUS-ACTIVE\": \"Tareas activas\",\n            \"STATUS-COMPLETE\": \"Tareas completadas\",\n            \"PROCESS-INSTANCE-ID\": \"Identificador de instancia de proceso\",\n            \"TENANT-ID\": \"Tenant identifier\",\n            \"OWNER\": \"Propietario (sensible a mayusculas y minusculas)\",\n            \"PARENT-TASK-ID\": \"Parent Identificador de tarea\",\n            \"CREATED-BEFORE\": \"Creado antes\",\n            \"CREATED-AFTER\": \"Creado despues\",\n            \"ENDED-BEFORE\": \"Finalizado antes\",\n            \"ENDED-AFTER\": \"Finalizado despues\",\n            \"DUE-BEFORE\": \"Vencido antes\",\n            \"DUE-AFTER\": \"Vencido despues\",\n            \"TASK-VARIABLE\": \"Variable local de tarea\",\n            \"PROCESS-VARIABLE\": \"Variable de proceso\",\n            \"VARIABLE-NAME\": \"Nombre de variable\",\n            \"VARIABLE-VALUE\": \"Valor de variable\",\n            \"VARIABLE-BOOLEAN-VALUE\": \"Boolean value: {{value}}\"\n        },\n        \"SORT\": {\n            \"NAME\": \"Nombre\",\n            \"DUE-DATE\": \"Fecha de vencimiento\",\n            \"START-TIME\": \"Hora de inicio\",\n            \"END-TIME\": \"Hora de finalizacion\",\n            \"PRIORITY\": \"Prioridad\"\n        },\n        \"HEADER\": {\n            \"ID\": \"ID\",\n            \"NAME\": \"Nombre\",\n            \"ASSIGNEE\": \"Assignado\",\n            \"OWNER\": \"Propietario\",\n            \"CREATE-TIME\": \"Creado\",\n            \"END-TIME\": \"Finalizado\",\n            \"PRIORITY\": \"Prioridad\"\n        }\n    },\n    \"DEPLOYMENTS\": {\n        \"TITLE\": \"Despliegues\",\n        \"LIST-MESSAGE\": \"Mostrando {{size}} resultados, de un total de {{total}} despliegues similares.\",\n        \"LIST-MESSAGE-EMPTY\": \"No hay despliegues similares.\",\n        \"FILTER\": {\n            \"NAME\": \"Nombre (Sensible a mayusculas y minusculas)\",\n            \"TENANTID\": \"Tenant identifier (Sensible a mayusculas y minusculas)\"\n        },\n        \"SORT\": {\n            \"ID\": \"Identificador\",\n            \"NAME\": \"Nombre\"\n        },\n        \"HEADER\": {\n            \"ID\": \"Identificador\",\n            \"NAME\": \"Nombre\",\n            \"DEPLOY-TIME\": \"Hora de despliegue\",\n            \"CATEGORY\": \"Categoria\",\n            \"TENANT\": \"Tenant\"\n        },\n        \"ACTION\": {\n            \"UPLOAD\": \"Subir proceso o paquete\",\n            \"DELETE\": \"Borrar despliegue\"\n        },\n        \"POPUP\": {\n            \"UPLOAD\": {\n                \"DESCRIPTION\": \"Selecciona un archivo de proceso .bpmn, .bpmn20.xml para desplegar o sube un paquete de procesos en un archivo .zip o .bar.\",\n                \"DROPZONE\": \"O arrastra un archivo aqui\",\n                \"NO-DROP\": \"Arrastrar archivos no esta permitido por su navegador\",\n                \"CANCEL-UPLOAD\": \"Cancelar carga\",\n                \"ERROR\": \"No se pudo subir este archivo\"\n            },\n            \"DELETE\": {\n            \t\"CONFIRM-MESSAGE\": \"Borrar despliegue '{{name}}'?\"\n            \t}\n        }\n    },\n    \"DEPLOYMENT\": {\n        \"ID\": \"Identificador:\",\n        \"NAME\": \"Nombre:\",\n        \"TIME\": \"Hora de despliegue:\",\n        \"CATEGORY\": \"Categoria:\",\n        \"TENANTID\": \"Tenant identifier:\",\n        \"DEFINITIONS-MESSAGE\": \"Este despliegue tiene {{total}} definiciones de proceso, mostrando {{size}}.\",\n        \"DEFINITIONS-MESSAGE-EMPTY\": \"Este despliegue no tiene definiciones de proceso.\",\n        \"TITLE\": {\n            \"DEFINITIONS\": \"Definiciones de proceso\",\n            \"RESOURCES\": \"Recursos\"\n        },\n        \"ACTION\": {\n            \"SHOW-ALL-DEFINITIONS\": \"Mostrar todas las definiciones\"\n        }\n    },\n    \"JOB\": {\n        \"TITLE\": {\n            \"MAIN\": \"Trabajo {{id}}\",\n            \"EXCEPTION\": \"Excepcion\"\n        },\n        \"ACTIONS\": {\n            \"EXECUTE\": \"Ejecutar trabajo\",\n            \"DELETE\": \"Eliminar trabajo\"\n        },\n        \"POPUP\": {\n            \"DELETE-JOB\": {\n                \"TITLE\": \"Eliminar trabajo '{{id}}'\",\n                \"MESSAGE\": \"Estas seguro que deseas borrar el trabajo {{id}}?\",\n                \"CONFIRM\": \"Eliminar trabajo\"\n            }\n        },\n        \"ID\": \"Identificador:\",\n        \"EXECUTION-ID\": \"Identificador de ejecucion:\",\n        \"PROCESS-INSTANCE\": \"Instancia de proceso:\",\n        \"PROCESS-DEFINITION\": \"Definicion de proceso:\",\n        \"DUEDATE\": \"Fecha de vencimiento:\",\n        \"RETRIES-LEFT\": \"Intentos restantes:\",\n        \"TENANT-ID\": \"Tenant:\"\n    },\n    \"JOBS\": {\n        \"TITLE\": \"Trabajos\",\n        \"LIST-MESSAGE\": \"Mostrando {{size}} resultados, de un total de {{total}} trabajos similares.\",\n        \"LIST-MESSAGE-EMPTY\": \"No hay trabajos similares.\",\n        \"FILTER\": {\n            \"PROCESS-DEFINITION\": \"Definicion de proceso\",\n            \"ALL-PROCESS-DEFINITIONS\": \"Todas las definiciones de proceo\",\n            \"PROCESS-INSTANCE-ID\": \"Identificador de instancia de proceso\",\n            \"TENANT-ID\": \"Tenant identifier\",\n            \"DUE-BEFORE\": \"Vencido antes\",\n            \"DUE-AFTER\": \"Vencido despues\",\n            \"EXCEPTION\": \"Excepcion\",\n            \"EXCEPTION-HELP\": \"Solo0 mostrar trabajos con excepciones\"\n        },\n        \"SORT\": {\n            \"ID\": \"Identificador de trabajo\",\n            \"DUE-DATE\": \"Fecha de vencimiento\",\n            \"PROCESS-INSTANCE-ID\": \"Identificador de instancia de proceso\"\n        },\n        \"HEADER\": {\n            \"ID\": \"Identificador\",\n            \"DUE-DATE\": \"Fecha de vencimiento\",\n            \"PROCESS-DEFINITION\": \"Definicion de proceso\",\n            \"RETRIES\": \"Intentos\",\n            \"EXCEPTION\": \"Excepcion\"\n        }\n    },\n    \"EVENT-SUBSCRIPTION\": {\n        \"TITLE\": {\n            \"MAIN\": \"Suscripcion a evento {{id}}\"\n        },\n        \"ACTIONS\": {\n            \"TRIGGER\": \"Evento disparador\"\n        },\n        \"ID\": \"Identificador:\",\n        \"ACTIVITY-ID\": \"Identificador de actividad:\",\n        \"EXECUTION-ID\": \"Identificador de ejecucion:\",\n        \"PROCESS-INSTANCE\": \"Instancia de proceso:\",\n        \"PROCESS-DEFINITION\": \"Definicion de proceso:\",\n        \"CREATE-DATE\": \"Creado:\",\n        \"EVENT-TYPE\": \"Tipo de evento:\",\n        \"EVENT-NAME\": \"Nombre de evento:\",\n        \"TENANT-ID\": \"Tenant:\"\n    },\n    \"EVENT-SUBSCRIPTIONS\": {\n    \t\"TITLE\": \"Suscripciones aventos\",\n        \"LIST-MESSAGE\": \"Mostrando {{size}} resultados, de un total de {{total}} suscripciones a eventos similares.\",\n        \"LIST-MESSAGE-EMPTY\": \"No hay suscripciones a eventos similares.\",\n    \t\"FILTER\": {\n            \"PROCESS-DEFINITION\": \"Definicion de proceso\",\n            \"ALL-PROCESS-DEFINITIONS\": \"Todas las definiciones de proceo\",\n            \"PROCESS-INSTANCE-ID\": \"Identificador de instancia de proceso\",\n            \"TENANT-ID\": \"Tenant identifier\",\n            \"CREATED-BEFORE\": \"Creado antes\",\n            \"CREATED-AFTER\": \"Creado despues\"\n        },\n        \"SORT\": {\n            \"ID\": \"Identificador de suscripcion a evento\",\n            \"CREATE-DATE\": \"Creado\",\n            \"PROCESS-INSTANCE-ID\": \"Identificador de instancia de proceso\"\n        },\n    \t\"HEADER\": {\n            \"ID\": \"Identificador\",\n            \"CREATE-DATE\": \"Creado\",\n            \"PROCESS-DEFINITION\": \"Definicion de proceso\",\n            \"EVENT-TYPE\": \"Tipo de evento\",\n            \"EVENT-NAME\": \"Nombre de evento\"\n        }\n    },\n    \"LOGIN\": {\n        \"TITLE\": \"Iniciar sesion\",\n        \"USERNAME\": \"Usuario\",\n        \"USERNAME-PLACEHOLDER\": \"Introduce tu usuario\",\n        \"PASSWORD\": \"Password\",\n        \"PASSWORD-PLACEHOLDER\": \"Introduce tu password\",\n        \"ACTION\": {\n            \"CONFIRM\": \"Iniciar sesion\"\n        }\n    },\n    \"USER\": {\n        \"POPUP\": {\n            \"CHANGE-PASSWORD\": {\n                \"TITLE\": \"Cambiar password para '{{login}}'\",\n                \"OLD-PASSWORD\": \"Viejo password\",\n                \"NEW-PASSWORD\": \"Nuevo password\",\n                \"CONFIRM\": \"Cambiar password\"\n            },\n            \"DELETE\": {\n                \"TITLE\": \"Borrar usuario {{login}}\",\n                \"MESSAGE\": \"Estas seguro que deseas borrar el usuario '{{login}}'?\",\n                \"CONFIRM\": \"Borrar usuario\"\n            },\n            \"EDIT\": {\n                \"TITLE\": \"Editar usuario {{login}}\",\n                \"LOGIN\": \"Inicio de sesion\",\n                \"EMAIL\": \"Email\",\n                \"FIRSTNAME\": \"Nombre\",\n                \"LASTNAME\": \"Apellido\",\n                \"CONFIRM\": \"Actualizar usuario\"\n            },\n            \"NEW\": {\n                \"TITLE\": \"Crear nuevo usuario\",\n                \"LOGIN\": \"Inicio de sesion\",\n                \"EMAIL\": \"Email\",\n                \"FIRSTNAME\": \"Nombre\",\n                \"LASTNAME\": \"Apellido\",\n                \"PASSWORD\": \"Password\",\n                \"ADMIN\": \"Tiene derecho de administrador\",\n                \"CONFIRM\": \"Crear usuario\"\n            }\n        }\n    },\n    \"USERS\": {\n        \"TITLE\": \"Usuarios\",\n        \"ACTION\": {\n            \"EDIT\": \"Editar usuario\",\n            \"NEW\": \"Crear nuevo usuario\",\n            \"DELETE\": \"Borrar usuario\",\n            \"CHANGE-PASSWORD\": \"Cambiar password\"\n        },\n        \"HEADER\": {\n            \"LOGIN\": \"Inicio de sesion\",\n            \"FIRSTNAME\": \"Nombre\",\n            \"LASTNAME\": \"Apellido\",\n            \"EMAIL\": \"Email\",\n            \"CLUSTER_USER\": \"Cluster usuario\"\n        }\n    },\n    \"LICENSE\": {\n        \"POPUP\": {\n            \"TITLE\": \"License information\",\n            \"HOLDER\": \"Holder\",\n            \"SUBJECT\": \"Subject\",\n            \"PRODUCTKEY\": \"Product type\",\n            \"GOODAFTERDATE\": \"License valid after\",\n            \"GOODBEFOREDATE\": \"License valid until\",\n            \"NUMBER_OF_PROCESSES\": \"Number of active processes\",\n            \"NUMBER_OF_ADMINS\": \"Number of administrator users\",\n            \"MULTI_TENANT\": \"Multi tenant\",\n            \"DEFAULT_TENANT\": \"Default tenant\"\n        }\n    },\n    \"CLUSTER\": {\n        \"NAME\": \"Nombre:\",\n        \"USER\": \"User:\",\n        \"MASTER-MANDATORY\": \"Master configuration mandatory:\",\n        \"METRICS-SEND-INTERVAL\": \"Metric send interval:\",\n        \"ENDPOINT-HELP\": \"The endpoint configuration (each cluster has only one) needs to point to a Flowable REST installation. This endpoint will then be used to retrieve and manage the data used in the other sections (for example deployments, process definitions, and so on) of this application.\",\n        \"ENDPOINT-NAME\": \"Nombre:\",\n        \"ENDPOINT-DESCRIPTION\": \"Description:\",\n        \"ENDPOINT-ADDRESS\": \"Server address:\",\n        \"ENDPOINT-PORT\": \"Server port:\",\n        \"ENDPOINT-CONTEXT-ROOT\": \"Context root:\",\n        \"ENDPOINT-REST-ROOT\": \"REST root:\",\n        \"ENDPOINT-USERNAME\": \"Username:\",\n        \"PROCESS-ENGINE-HELP\": \"This section allows you to define a 'master configuration' for the cluster. All instances in the cluster will use this configuration when they boot up (if the cluster config jar is on the classpath or if the corresponding properties are set). If not set, the instances will use their local configuration files.\",\n        \"NO-MASTER-DEFINED\": \"No master configuration defined\",\n        \"ACTION\": {\n            \"SHOW-PASSWORD\": \"Show password\",\n            \"EDIT-CLUSTER-CONFIG\": \"Edit cluster configuration\",\n            \"CREATE-CLUSTER-CONFIG\": \"Create new cluster\",\n            \"DELETE-CLUSTER-CONFIG\": \"Delete cluster configuration\",\n            \"GENERATE-JAR\": \"Generate cluster config jar\",\n            \"EDIT-ENDPOINT\": \"Edit REST endpoint\",\n            \"CHECK-ENDPOINT\": \"Check REST endpoint\",\n            \"SELECT-MASTER\": \"Select master configuration\",\n            \"ADD-CONFIGURATION\": \"Add master configuration\",\n            \"EDIT-CONFIGURATION\": \"Edit master configuration\",\n            \"DELETE-CONFIGURATION\": \"Delete master configuration\"\n        },\n        \"TITLE\": {\n            \"PROCESS-ENDPOINT\": \"Process API Endpoint configuration\",\n            \"DMN-ENDPOINT\": \"DMN API Endpoint configuration\",\n            \"FORM-ENDPOINT\": \"Form API Endpoint configuration\",\n            \"CONTENT-ENDPOINT\": \"Content API Endpoint configuration\"\n        },\n        \"POPUP\": {\n            \"EDIT-ENDPOINT\": {\n                \"ENDPOINT-NAME\": \"Nombre\",\n                \"ENDPOINT-DESCRIPTION\": \"Description\",\n                \"ENDPOINT-ADDRESS\": \"Server address\",\n                \"ENDPOINT-PORT\": \"Server port\",\n                \"ENDPOINT-CONTEXT-ROOT\": \"Context root\",\n                \"ENDPOINT-REST-ROOT\": \"REST root\",\n                \"ENDPOINT-USERNAME\": \"Username\",\n                \"ENDPOINT-PASSWORD\": \"Password\",\n                \"ENDPOINT-PASSWORD-HELP\": \"Leave blank to keep current password\",\n                \"ENDPOINT-URL-PREVIEW\": \"URL preview\",\n                \"ACTION-CONFIRM\": \"Save endpoint configuration\",\n                \"ERROR-401\": \"Error: invalid credentials\",\n                \"ERROR-403\": \"Error: invalid credentials or URL\",\n                \"ERROR-404\": \"Error: URL not found\",\n                \"ERROR-500\": \"Error: server error. Check server logs.\"\n            }\n        }\n    },\n    \"APP-DEPLOYMENTS\": {\n        \"TITLE\": \"App desplegadas\",\n        \"LIST-MESSAGE\": \"Mostrando {{size}} resultados, de un total de{{total}} app deseplegadas similares.\",\n        \"LIST-MESSAGE-EMPTY\": \"No hay app desplegadas similares.\",\n        \"FILTER\": {\n            \"NAME\": \"Nombre\",\n            \"TENANTID\": \"Tenant identifier\",\n            \"LATEST\": \"Ultima version\",\n            \"LATEST-HELP\": \"Mostrar solo ultimas versiones\"\n        },\n        \"SORT\": {\n            \"ID\": \"Identificador\",\n            \"NAME\": \"Nombre\"\n        },\n        \"HEADER\": {\n            \"ID\": \"Identificador\",\n            \"APP-DEFINITION-ID\": \"Identificador de App\",\n            \"DEPLOYMENT-ID\": \"Identificador de Despliegue de Proceso\",\n            \"DMN-DEPLOYMENT-ID\": \"Identificador de despliegue de DMN\",\n            \"NAME\": \"Nombre\",\n            \"DEPLOY-TIME\": \"Hora de despliegue\",\n            \"DEPLOYED-BY\": \"Dsplegado por\",\n            \"TENANT\": \"Tenant ID\"\n        },\n        \"ACTION\": {\n            \"UPLOAD\": \"Subir y publicar una App\"\n        },\n        \"POPUP\": {\n            \"UPLOAD\": {\n                \"DESCRIPTION\": \"Selecciona una dfeinicion de app .zip para desplegar.\",\n                \"WARNING\": \"Solo es posible subir un proceso a una instancia de Flowable UI.\",\n                \"DROPZONE\": \"O arrastra un archivo aqui\",\n                \"NO-DROP\": \"Arrastrar archivos no soportado por el navegador\",\n                \"CANCEL-UPLOAD\": \"Cancelar carga\",\n                \"ERROR\": \"No se puede subir este archivo\"\n            }\n        }\n    },\n    \"VARIABLES\": {\n        \"HEADER\": {\n            \"NAME\": \"Nombre\",\n            \"TYPE\": \"Tipo\",\n            \"VALUE\": \"Valor\"\n        }\n    },\n    \"IDENTITY-LINKS\": {\n        \"HEADER\": {\n            \"GROUP-ID\": \"Identificador de Grupo\",\n            \"TYPE\": \"Tipo\",\n            \"USER-ID\": \"Identificador de usuario\"\n        }\n    },\n    \"ALERT\": {\n        \"GENERAL\": {\n            \"HTTP-ERROR\": \"No pudimos obtener datos del servidor\",\n            \"AUTHENTICATION-ERROR\": \"Introdujiste datos de acceso invalidos\"\n        },\n        \"ENGINE\": {\n            \"ENDPOINT-UPDATED\": \"Endpoint '{{name}}' updated.\",\n            \"ENDPOINT-INVALID\": \"Endpoint configuration for '{{name}}' is invalid.\",\n            \"ENDPOINT-VALID\": \"Endpoint valid, Engine at endpoint: {{name}} - {{version}}\"\n        },\n        \"JOB\": {\n            \"DELETED\": \"Trabajo '{{id}}' borrado correctamente.\",\n            \"EXECUTED\": \"Trabajo '{{id}}' ejecutado correctamente.\"\n        },\n        \"EVENT-SUBSCRIPTION\": {\n        \t\"TRIGGERED\": \"Event subscription '{{id}}' disparado correctamente.\"\n        },\n        \"PROCESS-INSTANCE\": {\n            \"DELETED\": \"Process instance '{{id}}' borrado correctamente.\",\n            \"TERMINATED\": \"Process instance '{{id}}' terminado correctamente.\"\n        },\n        \"TASK\": {\n            \"DELETED\": \"Tarea '{{id}}' borrado correctamente.\",\n            \"COMPLETED\": \"Tarea '{{id}}' completado correctamente.\",\n            \"DELEGATED\": \"Tarea '{{id}}' delegado al usuario {{user}}.\",\n            \"RESOLVED\": \"Tarea '{{id}}' resuelto correctamente.\",\n            \"ASSIGNED\": \"Tarea '{{id}}' ha sido asignado al usuario {{user}}.\",\n            \"UNASSIGNED\": \"Tarea '{{id}}' ha sido desasignado.\",\n            \"UPDATED\": \"Tarea '{{id}}' actualizado correctamente.\"\n        },\n        \"USER\": {\n            \"DELETED\": \"Usuario '{{login}}' borrado correctamente.\",\n            \"UPDATED\": \"Usuario '{{login}}' actualizado correctamente.\",\n            \"CREATED\": \"Usuario '{{login}}' creado.\",\n            \"PASSWORD-CHANGED\": \"Password para '{{login}}' se cambiado correctamente.\"\n        },\n        \"PROCESS-DEFINITION\": {\n            \"CATEGORY-UPDATED\": \"Categoria de la definicion de proceso actualizada\"\n        },\n        \"DEPLOYMENT\": {\n        \t\"DELETED-DEPLOYMENT\": \"Borrar despliegue '{{name}}'\",\n        \t\"DELETE-ERROR\": \"No se puede borrar el despliegue. {{exception || ''}}\",\n        \t\"DEPLOYMENT-SUCCESS\": \"Despliegu exitoso\"\n        },\n        \"APP-DEPLOYMENT\": {\n        \t\"DELETED-APP\": \"App eliminada '{{appDefinition.name}}'\",\n        \t\"DELETE-ERROR\": \"No se pudo eliminar la App. {{message || ''}}\"\n        }\n    },\n    \"DECISION-TABLE-DEPLOYMENTS\": {\n        \"TITLE\": \"Despliegues de Tablas de Decisiones\",\n        \"LIST-MESSAGE\": \"Mostrando {{size}} resultados, de un total de{{total}} matching deployments.\",\n        \"LIST-MESSAGE-EMPTY\": \"No hay despliegues similares\",\n        \"FILTER\": {\n            \"NAME\": \"Nombre (case sensitive)\",\n            \"TENANTID\": \"Tenant identifier (Sensible a mayusculas y minusculas)\"\n        },\n        \"SORT\": {\n            \"ID\": \"Identificador\",\n            \"NAME\": \"Nombre\"\n        },\n        \"HEADER\": {\n            \"ID\": \"Identificador\",\n            \"NAME\": \"Nombre\",\n            \"DEPLOY-TIME\": \"Hora de despliegue\",\n            \"CATEGORY\": \"Categoria\",\n            \"TENANT\": \"Tenant\"\n        },\n        \"ACTION\": {\n            \"DELETE\": \"Eliminar despliegue\"\n        }\n    },\n    \"DECISION-TABLE-DEPLOYMENT\": {\n        \"ID\": \"Identificador:\",\n        \"NAME\": \"Nombre:\",\n        \"TIME\": \"Hora de despliegue:\",\n        \"CATEGORY\": \"Categoria:\",\n        \"TENANTID\": \"Tenant identifier:\",\n        \"DECISION-TABLES-MESSAGE\": \"Este despliegue tiene {{total}} tablas de decision, mostrando {{size}}.\",\n        \"DECISION-TABLES-MESSAGE-EMPTY\": \"Este despliegue no tiene tablas de decision.\",\n        \"PARENT-DEPLOYMENT-ID\": \"Identificador de despliegue padre\",\n        \"TITLE\": {\n            \"DECISION-TABLES\": \"Tablas de Decision\",\n            \"RESOURCES\": \"Recursos\"\n        },\n        \"ACTION\": {\n            \"SHOW-ALL-DEFINITIONS\": \"Mostrar todas las tablas de decision\"\n        }\n    },\n    \"DECISION-TABLES\": {\n        \"TITLE\": \"Tablas de decision\",\n        \"LIST-MESSAGE\": \"Mostrando {{size}} resultados, de un total de {{total}} tablas de decision similares.\",\n        \"LIST-MESSAGE-EMPTY\": \"No hay tablas de decision similares.\",\n        \"FILTER\": {\n            \"NAME\": \"Nombre\",\n            \"KEY\": \"Key\",\n            \"TENANTID\": \"Tenant identifier\"\n        },\n        \"SORT\": {\n            \"ID\": \"Identificador\",\n            \"NAME\": \"Nombre\"\n        },\n        \"HEADER\": {\n            \"ID\": \"Identificador\",\n            \"NAME\": \"Nombre\",\n            \"VERSION\": \"Version\",\n            \"KEY\": \"Key\",\n            \"DEPLOY-TIME\": \"Hora de despliegue\",\n            \"TENANT-ID\": \"Tenant ID\"\n        }\n    },\n    \"DECISION-TABLE\": {\n        \"ID\": \"Identificador:\",\n        \"NAME\": \"Nombre:\",\n        \"VERSION\": \"Version:\",\n        \"KEY\": \"Key:\",\n        \"DEPLOYMENT-ID\": \"Identificador de despliegue:\",\n        \"PARENT-DEPLOYMENT-ID\": \"Identificador de despliegue padre\",\n        \"RESOURCE-NAME\": \"Nombre del recurso:\",\n        \"DESCRIPTION\": \"Descripcion:\",\n        \"TENANT\": \"Tenant:\",\n        \"TITLE\": {\n            \"DECISION-AUDITS\": \"Auditorias de decision\"\n        },\n        \"DECISION-AUDITS-MESSAGE\": \"Esta tabla de decision tiene {{total}} auditorias, mostrando {{size}}.\",\n        \"DECISION-AUDITS-MESSAGE-EMPTY\": \"Esta tabla de decision no tiene auditorias\",\n        \"ACTION\": {\n            \"EDIT-CATEGORY\": \"Editar categoria\",\n            \"SHOW-ALL-JOBS\": \"Mostrar todos los trabajos\",\n            \"SHOW-ALL-PROCESSES\": \"Mostrar todos los procesos\",\n            \"SHOW-DIAGRAM\": \"Mostrar diagramas de procesos\",\n            \"SHOW-DECISION-TABLE\": \"Mostrar tablas de decision\"\n        },\n        \"POPUP\": {\n            \"TITLE\": \"Tablka de decision: \",\n            \"KEY\": \"Key: \",\n            \"HIT-POLICY\": \"Politica de aciertos: \",\n            \"HIT-POLICIES\": {\n                \"FIRST\": \"Primero (Single pass)\",\n                \"ANY\": \"Cualquiera (Single pass)\"\n            }\n        }\n    },\n    \"FORM-DEFINITIONS\": {\n    \t\"TITLE\": \"Definicion de formularios\",\n        \"LIST-MESSAGE\": \"Mostrando {{size}} resultados, de un total de{{total}} formularios similares.\",\n        \"LIST-MESSAGE-EMPTY\": \"No hay formularios similares.\",\n        \"HEADER\": {\n            \"ID\": \"Identificador\",\n            \"NAME\": \"Nombre\",\n            \"DEPLOYMENTID\": \"Identificador de despliegue\",\n            \"TENANTID\": \"Tenant ID\",\n            \"KEY\": \"Key\",\n            \"VERSION\": \"Version\"\n        },\n        \"FILTER\": {\n            \"NAME\": \"Nombre\",\n            \"APPID\": \"Identificador de despliegue de App\",\n            \"TENANTID\": \"Tenant identifier\"\n        },\n        \"SORT\": {\n            \"ID\": \"Identificador\",\n            \"NAME\": \"Nombre\"\n        }\n    },\n    \"FORM-DEFINITION\": {\n        \"ID\": \"Identificador:\",\n        \"NAME\": \"Nombre:\",\n        \"PARENT-DEPLOYMENT-ID\": \"Identificador de despliegue padre\",\n        \"DEPLOYMENT-ID\": \"Identificador de despliegue\",\n        \"DESCRIPTION\": \"Descripcion:\",\n        \"TENANT\": \"Tenant:\",\n        \"MESSAGE-EMPTY\": \"(None)\",\n        \"TITLE\": {\n            \"FORM-INSTANCES\": \"Instancias de formulario\"\n        },\n        \"FORM-INSTANCES-MESSAGE\": \"Esta definicion tiene {{total}} instancias de formulario, mostrando {{size}}.\",\n        \"FORM-INSTANCES-MESSAGE-EMPTY\": \"Esta definicion no tiene instacias de formulario\",\n        \"ACTION\": {\n            \"EDIT-CATEGORY\": \"Editar categoria\",\n            \"SHOW-ALL-JOBS\": \"Mostrar todos los trabajos\",\n            \"SHOW-ALL-PROCESSES\": \"Mostrar todos los procesos\",\n            \"SHOW-DIAGRAM\": \"Mostrar diagrama de proceso\",\n            \"SHOW-FORM\": \"Mostrar formulario\"\n        },\n        \"POPUP\": {\n            \"TITLE\": \"Formulario: \"\n        },\n        \"FIELD-PREVIEW\" : {\n        \t\"DISPLAY-REF\": \"Valor a mostrar\",\n        \t\"SELECT-FIELD\": \"(No hay campo seleccionado)\",\n        \t\"FIELD-VALUE\": \"Mostrar valor del campo \\\"{{name}}\\\"\",\n        \t\"UNKNOWN-TYPE\": \"Tipo de campo desconocido {{type}}\",\n        \t\"TEXT-VALUE\": \"Texto\",\n        \t\"MULTI-TEXT-VALUE\": \"Texto multi-linea\",\n        \t\"NUMBER-VALUE\": \"123\",\n        \t\"DATE-VALUE\": \"Fecha\",\n        \t\"DROPDOWN-VALUE\": \"Selecciona ...\",\n        \t\"UPLOAD-VALUE\": \"Sube o importa contenido...\",\n        \t\"RADIOS-OPTION1\": \"Opcion 1\",\n        \t\"SELECT-PERSON\": \"Selecciona una persona\",\n        \t\"SELECT-GROUP\": \"Selecciona un grupo\"\n        \t}\n    },\n    \"FORM-DEPLOYMENTS\": {\n        \"TITLE\": \"Form Deployments\",\n        \"LIST-MESSAGE\": \"Mostrando {{size}} resultados, de un total de{{total}} despliegues de formulario similares.\",\n        \"LIST-MESSAGE-EMPTY\": \"No hay despliegues de formularios similares.\",\n        \"FILTER\": {\n            \"NAME\": \"Nombre (sensible a mayusculas y minusculas)\",\n            \"TENANTID\": \"Tenant identifier (case sensitive)\"\n        },\n        \"SORT\": {\n            \"ID\": \"Identificador\",\n            \"NAME\": \"Nombre\"\n        },\n        \"HEADER\": {\n            \"ID\": \"Identificador\",\n            \"NAME\": \"Nombre\",\n            \"DEPLOY-TIME\": \"Hora de despliegue\",\n            \"CATEGORY\": \"Categoria\",\n            \"TENANT\": \"Tenant\"\n        },\n        \"ACTION\": {\n            \"DELETE\": \"Delete deployment\"\n        }\n    },\n    \"FORM-DEPLOYMENT\": {\n        \"ID\": \"Identificador:\",\n        \"NAME\": \"Nombre:\",\n        \"TIME\": \"Hora de despliegue:\",\n        \"CATEGORY\": \"Categoria:\",\n        \"TENANTID\": \"Tenant identifier:\",\n        \"PARENT-DEPLOYMENT-ID\": \"Identificador de despliegue padre\",\n        \"DEFINITIONS-MESSAGE\": \"Este despliegue tiene {{total}} definiciones de formulario, mostrando {{size}}.\",\n        \"DEFINITIONS-MESSAGE-EMPTY\": \"Este despliegue no tiene definiciones de formulario.\",\n        \"TITLE\": {\n            \"FORM-DEFINITIONS\": \"Definiciones de formulario\",\n            \"RESOURCES\": \"Recursos\"\n        },\n        \"ACTION\": {\n            \"SHOW-ALL-DEFINITIONS\": \"Mostrar todas las definiciones de formulario\"\n        }\n    },\n    \"FORM-INSTANCES\": {\n        \"TITLE\": \"Instancias de formulario\",\n        \"LIST-MESSAGE\": \"Mostrando {{size}} resultados, de un total de{{total}} instancias de formulario similares.\",\n        \"LIST-MESSAGE-EMPTY\": \"No hay instancias de formulario similares.\",\n        \"HEADER\": {\n            \"ID\": \"ID\",\n            \"PROCESS-INSTANCE-ID\": \"Identificador de instancia de proceso\",\n            \"TASK-ID\": \"Identificador de tarea\",\n            \"SUBMITTED-ON\": \"Fecha de envio\",\n            \"SUBMITTED-BY\": \"Enviado por\",\n            \"TENANT-ID\": \"Tenant ID\"\n        },\n        \"FILTER\": {\n            \"NAME\": \"Nombre\",\n            \"TENANTID\": \"Tenant identifier\"\n        },\n        \"SORT\": {\n            \"SUBMITTED-DATE\": \"Fecha de envio\"\n        }\n    },\n    \"FORM-INSTANCE\": {\n        \"HEADER\": {\n            \"ID\": \"ID\",\n            \"TASK-ID\": \"Identificador de tarea\",\n            \"PROCESS-ID\": \"Identificador de instancia de proceso\",\n            \"SUBMITTED\": \"Fecha de envio\",\n            \"SUBMITTED-BY\": \"Enviado por\",\n            \"FORM-DEFINITION-ID\": \"Identificador de definicion de forma\"\n        },\n        \"FORM-FIELD-VALUES-MESSAGE\": \"Esta instancia tiene {{total}} valores de campo de formulario, mostrando {{size}}\",\n        \"FORM-FIELD-VALUES-MESSAGE-EMPTY\": \"Esta instancia no tiene valores de campo de formulario\",\n        \"ACTION\": {\n            \"SHOW-FORM-INSTANCE\": \"Mostrar instancia de formulario\"\n        },\n        \"TITLE\": {\n            \"FORM-FIELD-VALUES\": \"Valor de campo de formulario\"\n        },\n        \"FORM-FIELD-VALUES\": {\n            \"ID\": \"Identificador de campo de formulario\",\n            \"NAME\": \"Nombre de campo de formulario\",\n            \"TYPE\": \"Tipo de campo de formulario\",\n            \"VALUE\": \"Valor de campo de formulario\"\n        }\n    },\n    \"CONTENT-ITEMS\": {\n        \"TITLE\": \"Articulos de contenido\",\n        \"LIST-MESSAGE\": \"Mostrando {{size}} resultados, de un total de{{total}} articulos de contenido similares.\",\n        \"LIST-MESSAGE-EMPTY\": \"No hay articulos de contenido.\",\n        \"HEADER\": {\n            \"ID\": \"Identificador\",\n            \"NAME\": \"Nombre\",\n            \"PROCESS-INSTANCE-ID\": \"Identificador de instancia de proceso\",\n            \"TASK-ID\": \"Identificador de tarea\",\n            \"LAST-MODIFIED-ON\": \"Fecha de ultima actualizacion\",\n            \"LAST-MODIFIED-BY\": \"Ultima vez modificado por\",\n            \"TENANT-ID\": \"Tenant ID\"\n        },\n        \"FILTER\": {\n            \"NAME\": \"Nombre\",\n            \"TENANTID\": \"Tenant identifier\"\n        },\n        \"SORT\": {\n            \"CREATED\": \"Fecha de creacion\"\n        }\n    },\n    \"CONTENT-ITEM\": {\n        \"HEADER\": {\n            \"ID\": \"Identificador\",\n            \"TASK-ID\": \"Identificador de tarea\",\n            \"PROCESS-INSTANCE-ID\": \"Identificador de instancia de proceso\",\n            \"CREATED-ON\": \"Fecha de creacion\",\n            \"CREATED-BY\": \"Creado por\",\n            \"LAST-MODIFIED-ON\": \"Fecha de ultima actualizacion\",\n            \"LAST-MODIFIED-BY\": \"Ultima vez modificado por\",\n            \"CONTENT-STORE-ID\": \"Identificador de alamacenamiento de contenido\"\n        },\n        \"ACTION\": {\n            \"SHOW-CONTENT-ITEM\": \"Mostrar contenido del articulo\"\n        }\n    }\n}"
  },
  {
    "path": "flowable-ui-web/admin/i18n/fr.json",
    "content": "{\n    \"GENERAL\": {\n        \"YES\": \"Oui\",\n        \"NO\": \"Non\",\n        \"ACTION\": {\n            \"LOGOUT\": \"Déconnexion\",\n            \"DISMISS-ALERT\": \"Cliquez pour retirer ce message\",\n            \"RETURN-TO-LIST\": \"Retourner à la liste\",\n            \"SHOW-RESULTS\": \"Montrer {{size}} résultats\",\n            \"REFRESH-LIST\": \"Rafraîchir la liste\",\n            \"SORT-BY\": \"Trier par {{sort}}\",\n            \"CLEAR-FILTERS\": \"Enelever les filtres\",\n            \"CANCEL-AND-CLOSE\": \"Annuler et fermer\",\n            \"CANCEL\": \"Annuler\",\n            \"NEXT\": \"Suivant\",\n            \"PREVIOUS\": \"Précédent\",\n            \"CLOSE\": \"Fermer\",\n            \"SHOWLICENSE\": \"Informations de licence\"\n        },\n        \"TITLE\": {\n            \"MAIN\": \"Activiti administrateur\",\n            \"ACTIONS\": \"Actions\",\n            \"FILTERS\": \"Filtres\"\n        },\n        \"MENU\": {\n            \"PROCESS-ENGINE\": \"Moteur de Processus\",\n            \"FORM-ENGINE\": \"Moteur de Formulaires\",\n            \"CONTENT-ENGINE\": \"Moteur de Contenu\",\n            \"DMN-ENGINE\": \"Moteur DMN \",\n            \"DEPLOYMENTS\": \"Déploiements\",\n            \"DEFINITIONS\": \"Définitions\",\n            \"INSTANCES\": \"Instances\",\n            \"TASKS\": \"Tâches\",\n            \"JOBS\": \"Jobs\",\n            \"EVENT-SUBSCRIPTIONS\": \"Abonnements aux événements\",\n            \"CONFIGURATION\": \"Configuration\",\n            \"CONFIGURATION-ENGINE\": \"Moteur\",\n            \"DECISION-TABLES\": \"Tables de décision\",\n            \"CONTENT-ITEMS\": \"Contenus\"\n        },\n        \"RESULT-SIZES\": {\n            \"10\": \"10\",\n            \"25\": \"25\",\n            \"50\": \"50\",\n            \"100\": \"100\",\n            \"100000000\": \"tous\"\n        }\n    },\n    \"PROCESS-DEFINITION\": {\n        \"ID\": \"ID:\",\n        \"NAME\": \"Nom:\",\n        \"VERSION\": \"Version:\",\n        \"DESCRIPTION\": \"Description:\",\n        \"KEY\": \"Key:\",\n        \"CATEGORY\": \"Categorie:\",\n        \"SUSPENDED\": \"Suspendu:\",\n        \"DEPLOYMENT\": \"Déploiement:\",\n        \"TENANT\": \"Tenant:\",\n        \"START-FORM-DEFINED\": \"Formulaire initial défini:\",\n        \"GRAPHICAL-NOTATION-DEFINED\": \"Notation graphique définie:\",\n        \"PROCESS-INSTANCES-SIZE\": \"La définition possède {{total}} instances de processus en cours\",\n        \"PROCESS-INSTANCES-SHOWING\": \", montrer {{size}} récemment démarrées\",\n        \"PROCESS-INSTANCES-EMPTY\": \"La définition ne possède pas d'instance en cours\",\n        \"JOBS-SIZE\": \"La définition a {{total}} jobs en cours\",\n        \"JOBS-EMPTY\": \"La définition n'a aucun job en cours\",\n        \"DECISION-TABLES-SIZE\": \"La définition possède {{total}} tables de décision.\",\n        \"DECISION-TABLES-EMPTY\": \"La définition n'a aucune table de décision.\",\n        \"FORM-DEFINITIONS-SIZE\": \"La définition a {{total}} définitions de formulaires.\",\n        \"FORM-DEFINITIONS-EMPTY\": \"La définition ne possède aucune définition de formulaire.\",\n        \"TITLE\": {\n            \"PROCESS-INSTANCES\": \"Instance de processus\",\n            \"JOBS\": \"Jobs\",\n            \"DECISION-TABLES\": \"Tables de décision\",\n            \"FORMS\": \"Définition de formulaire\"\n        },\n        \"ACTION\": {\n            \"EDIT-CATEGORY\": \"Editer les catégories\",\n            \"SHOW-ALL-JOBS\": \"Montrer tous les jobs\",\n            \"SHOW-ALL-PROCESSES\": \"Montrer tous les processus\",\n            \"SHOW-DIAGRAM\": \"Montrer le diagramme du processus\"\n        },\n        \"POPUP\": {\n            \"EDIT-CATEGORY\": {\n                \"TITLE\": \"Editer les catégories d'une définition\",\n                \"MESSAGE\": \"La catégorie initiale pour la définition est remplie à partir de l'attribut targetNameSpace dans le fichier XML BPMN 2.0, néanmoins il peut être modifiée après le déploiement.\",\n                \"CATEGORY\": \"Catégorie\",\n                \"CATEGORY-PLACEHOLDER\": \"Entrer une catégorie\",\n                \"CONFIRM\": \"Mettre à jour une catégorie\"\n            },\n            \"SHOW-PROCESS-MODEL\": {\n                \"TITLE\": \"Diagramme de processus\"\n            }\n        }\n    },\n    \"PROCESS-DEFINITIONS\": {\n        \"LIST-MESSAGE\": \"Montrer {{size}} résultats, sur un total de {{total}} définitions correspondantes.\",\n        \"LIST-MESSAGE-EMPTY\": \"Aucune définition de processus disponible.\",\n        \"FILTER\": {\n            \"NAME\": \"Nom (sensible à la casse)\",\n            \"KEY\": \"Key (sensible à la casse)\",\n            \"DEPLOYMENT-ID\": \"ID du déploiement \",\n            \"TENANT-ID\": \"ID du Tenant\",\n            \"LATEST\": \"Dernière version\",\n            \"LATEST-HELP\": \"Montrer uniquement les dernières versions\"\n        },\n        \"TITLE\": {\n            \"MAIN\": \"Définitions de processus\"\n        },\n        \"SORT\": {\n            \"ID\": \"ID\",\n            \"NAME\": \"Nom\",\n            \"VERSION\": \"Version\"\n        },\n        \"HEADER\": {\n            \"ID\": \"ID\",\n            \"NAME\": \"Nom\",\n            \"VERSION\": \"Version\",\n            \"KEY\": \"Key\",\n            \"TENANT\": \"Tenant\"\n        },\n        \"ACTIONS\": {\n            \"UPLOAD-FROM-MODELER\": \"Importer depuis l'éditeur Flowable\"\n        },\n        \"POPUP\": {\n            \"UPLOAD-FROM-MODELER\": {\n                \"NAME\": \"Nom d'utilisateur\",\n                \"PASSWORD\": \"Mot de Passe\",\n                \"ERROR\": \"Nous n'avons pas été en mesure de contacter l'éditeur\",\n                \"UNAUTHORIZED\": \"Identifiants invalides\",\n                \"UPLOAD-DESCRIPTION\": \"Le modèle de processus va maintenant être récupéré et déployé sur le cluster Flowable actuellement actif. Sélectionnez un nom approprié pour le package de déploiement.\"\n            }\n        }\n    },\n    \"PROCESS-INSTANCE\": {\n        \"ID\": \"ID:\",\n        \"NAME\": \"Nom:\",\n        \"DESCRIPTION\": \"Description:\",\n        \"BUSINESS-KEY\": \"Clé métier:\",\n        \"TENANT-ID\": \"Tenant:\",\n        \"STATUS\": \"Statut:\",\n        \"STATUS-ACTIVE\": \"Actif\",\n        \"STATUS-COMPLETED\": \"Terminé\",\n        \"ACTIVITY-ID-STARTED\": \"Identificateur de début d'activité:\",\n        \"ACTIVITY-ID-ENDED\": \"Terminé lors de l'activité:\",\n        \"DELETE-REASON\": \"Raison de suppression:\",\n        \"STARTED-BY\": \"Démarré par:\",\n        \"END-TIME\": \"Terminé le:\",\n        \"DURATION\": \"Durée:\",\n        \"SUPER-PROCESS-INSTANCE-ID\": \"Identificateur de l'instance du super processus:\",\n        \"TASKS-SIZE\": \"Cette instance de processus comporte {{total}} tâches.\",\n        \"TASKS-EMPTY\": \"Cette instance de processus n'a pas de tâches.\",\n        \"VARIABLES-SIZE\": \"Cette instance de processus possède {{total}} variables.\",\n        \"VARIABLES-EMPTY\": \"Cette instance de processus n'a pas de variables.\",\n        \"JOBS-SIZE\": \"Cette instance de processus a {{total}} jobs.\",\n        \"JOBS-EMPTY\": \"Cette instance de processus n'a pas de jobs.\",\n        \"SUBPROCESSES-SIZE\": \"Cette instance de processus comporte {{total}} sous-processus.\",\n        \"SUBPROCESSES-EMPTY\": \"Cette instance de processus n'a pas de sous-processus.\",\n        \"DECISION-TABLES-SIZE\": \"Cette instance de processus a {{total}} tables de décision.\",\n        \"DECISION-TABLES-EMPTY\": \"Cette instance de processus n'a pas de tables de décision.\",\n        \"FORM-INSTANCES-SIZE\": \"Cette instance de processus comporte {{total}} instances de formulaire\",\n        \"FORM-INSTANCES-EMPTY\": \"Cette instance de processus n'a pas d'instance de formulaire.\",\n        \"TITLE\": {\n            \"TASKS\": \"Tâches\",\n            \"VARIABLES\": \"Variables\",\n            \"JOBS\": \"Jobs\",\n            \"SUBPROCESSES\": \"Sous Processus\",\n            \"DECISION-TABLES\": \"Tables de décision\",\n            \"FORM-INSTANCES\": \"Formulaires\"\n        },\n        \"ACTION\": {\n            \"DELETE\": \"Supprimer une instance de processus\",\n            \"TERMINATE\": \"Terminer une instance de processus\",\n            \"SHOW-ALL-TASKS\": \"Montrer toutes les tâches\",\n            \"SHOW-ALL-JOBS\": \"Montrer tous les jobs\",\n            \"SHOW-ALL-SUBPROCESSES\": \"Montrer tous les sous-processus\",\n            \"SHOW-DIAGRAM\": \"Montrer le diagramme de processus\",\n            \"TITLE-VARIABLES\": \"Actions sur la variable sélectionnée\",\n            \"DELETE-VARIABLE\": \"Supprimer la variable\",\n            \"UPDATE-VALUE\": \"Mettre à jour la variable\",\n            \"ADD-VARIABLE\": \"Ajouter une variable\"\n        },\n        \"POPUP\": {\n            \"DELETE\": {\n                \"TITLE\": \"Supprimer une instance de processus\",\n                \"MESSAGE-DELETE\": \"Veuillez confirmer la suppression de l'instance de processus\",\n                \"MESSAGE-TERMINATE\": \"Êtes-vous sûr de vouloir terminer l'instance du processus\",\n                \"DELETE-REASON\": \"Raison de la suppression\",\n                \"DELETE-REASON-HELP\": \"Ajouter une motif de suppression (optionnel)\",\n                \"CONFIRM-DELETE\": \"Supprimer l'instance de processus\",\n                \"CONFIRM-TERMINATE\": \"Terminer l'instance de processus\"\n            },\n            \"SHOW-PROCESS-MODEL\": {\n                \"TITLE\": \"Diagramme de processus\"\n            },\n            \"CREATE-VARIABLE\": {\n                \"TITLE\": \"Créer une variable\",\n                \"NAME\": \"Nom de la variable\",\n                \"TYPE\": \"Type de variable\",\n                \"VALUE\": \"Valeur de la variable\",\n                \"CREATE\": \"Créer\"\n            },\n            \"UPDATE-VARIABLE\": {\n                \"TITLE\": \"Mettre à jour la variable '{{name}}'\",\n                \"NAME\": \"Nom de la variable\",\n                \"VALUE\": \"Valeur\",\n                \"CHECKED\": \"vrai\",\n                \"UNCHECKED\": \"faux\",\n                \"DATE-HELP\": \"format ISO-8601 (exemple : 2016-01-28T23:00:00Z)\",\n                \"ACTION-UPDATE\": \"Mettre à jour\"\n            },\n            \"DELETE-VARIABLE\": {\n                \"TITLE\": \"Supprimer la variable '{{name}}\",\n                \"MESSAGE\": \"Voulez vous confirmer la suppression de la variable?\",\n                \"DELETE\": \"Supprimer\"\n            }\n        }\n    },\n    \"PROCESS-INSTANCES\": {\n        \"TITLE\": \"Instances de Processus\",\n        \"LIST-MESSAGE\": \"Montrer {{size}} resultats, sur un total de {{total}} instances de processus correspondantes.\",\n        \"LIST-MESSAGE-EMPTY\": \"Aucune instance de processus disponible.\",\n        \"FILTER\": {\n            \"NAME\": \"Nom\",\n            \"PROCESS-DEFINITION\": \"Définition du processus\",\n            \"ALL-PROCESS-DEFINITIONS\": \"Toutes les définitions de processus\",\n            \"BUSINESS-KEY\": \"Clé métier\",\n            \"SUPER-PROCESS-INSTANCE-ID\": \"Super process instance ID\",\n            \"STARTED-BEFORE\": \"Démarré avant le\",\n            \"STARTED-AFTER\": \"Démarré après le\",\n            \"ENDED-BEFORE\": \"Terminé avant le\",\n            \"ENDED-AFTER\": \"Terminé après le\",\n            \"VARIABLE\": \"Variable\",\n            \"VARIABLE-NAME\": \"Nom de la variable\",\n            \"VARIABLE-VALUE\": \"Valeur de la variable\",\n            \"VARIABLE-BOOLEAN-VALUE\": \"Valeur booléenne: {{value}}\",\n            \"TENANT-ID\": \"Identifiant de Tenant\"\n        },\n        \"SORT\": {\n            \"ID\": \"ID\",\n            \"START-TIME\": \"Temps de départ\"\n        },\n        \"HEADER\": {\n            \"ID\": \"ID\",\n            \"NAME\": \"Nom\",\n            \"BUSINESS-KEY\": \"Clé métier\",\n            \"PROCESS-DEFINITION\": \"Définition de processus\",\n            \"CREATE-TIME\": \"Créé le\",\n            \"END-TIME\": \"Terminé le\",\n            \"STATUS\": \"Statut\"\n        }\n    },\n    \"TASK\": {\n        \"ID\": \"ID:\",\n        \"NAME\": \"Nom:\",\n        \"STATUS\": \"Statut:\",\n        \"STATUS-COMPLETED\": \"Terminé\",\n        \"STATUS-ACTIVE\": \"Actif\",\n        \"DESCRIPTION\": \"Description:\",\n        \"TASK-DEFINITION-KEY\": \"Clé de Définition:\",\n        \"FORM-KEY\": \"Clé de formulaire:\",\n        \"PRIORITY\": \"Priorité:\",\n        \"DELEGATION-STATE\": \"Etat de la délégation:\",\n        \"CATEGORY\": \"Catégorie:\",\n        \"TENANT-ID\": \"Tenant:\",\n        \"PARENT\": \"Tâche parente:\",\n        \"ASSIGNEE\": \"Personne assignée:\",\n        \"OWNER\": \"Propriétaire:\",\n        \"START-DATE\": \"Date de début:\",\n        \"DUE-DATE\": \"Date d'échéance:\",\n        \"END-DATE\": \"Date de fin:\",\n        \"DELETE-REASON\": \"Raison de la suppression:\",\n        \"PROCESS-INSTANCE\": \"Instance de processus\",\n        \"PROCESS-DEFINITION\": \"Définition du processus\",\n        \"EXECUTION-ID\": \"Identifiant d'éxecution:\",\n        \"SUBTASKS-MESSAGE\": \"Cette tâche posséde {{total}} sous-tâches, afficher {{size}}.\",\n        \"SUBTASKS-MESSAGE-EMPTY\": \"Cette tâche n'a pas de sous-tâche.\",\n        \"VARIABLES-MESSAGE\": \"Cette tâche posséde possède {{size}} variables.\",\n        \"VARIABLES-MESSAGE-EMPTY\": \"Cette tâche n'a pas de variables.\",\n        \"IDENTITY-LINKS-MESSAGE\": \"Cette tâche posséde {{size}} liens d'identité.\",\n        \"IDENTITY-LINKS-MESSAGE-EMPTY\": \"Cette tâche n'a pas de liens d'identité.\",\n        \"ACTION\": {\n            \"EDIT\": \"Editer la tâche\",\n            \"ASSIGN-CLAIM\": \"Assigner/Revendiquer une tâche\",\n            \"DELEGATE\": \"Déléguer la tâche\",\n            \"RESOLVE\": \"Résourdre la tâche\",\n            \"COMPLETE\": \"Terminer la tâche\",\n            \"DELETE\": \"Supprimer la tâche\",\n            \"SHOW-ALL-SUBTASKS\": \"Montrer toutes les sous-tâches\",\n            \"SHOW-SUBMITTED-FORM\": \"Montrer le formulaire\"\n        },\n        \"TITLE\": {\n            \"SUBTASKS\": \"Sous-tâches\",\n            \"IDENTITY-LINKS\": \"Liens d'identité\",\n            \"VARIABLES\": \"Variables\"\n        },\n        \"POPUP\": {\n            \"ASSIGN\": {\n                \"TITLE\": \"Assigner la tâche\",\n                \"MESSAGE\": \"Êtes-vous sûr de vouloir assigner cette tâche\",\n                \"NEW-ASSIGNEE\": \"Nouvelle personne assignée\",\n                \"NEW-ASSIGNEE-HELP\": \"Laisser le champs personne assignée vide si vous voulez assigner cette tâche à personne.\",\n                \"CONFIRM\": \"Assigner la tâche\"\n            },\n            \"COMPLETE\": {\n                \"TITLE\": \"Terminer la tâche\",\n                \"MESSAGE\": \"Êtes-vous sûr de vouloir terminer cette tâche\",\n                \"CONFIRM\": \"Terminer la tâche\"\n            },\n            \"DELEGATE\": {\n                \"TITLE\": \"Déléguer la tâche\",\n                \"MESSAGE\": \"Êtes-vous sûr de vouloir déléguer cette tâche\",\n                \"CONFIRM\": \"Déléguer la tâche\",\n                \"DELEGATE-TO\": \"Utilisateur délégué\"\n            },\n            \"RESOLVE\": {\n                \"TITLE\": \"Résoudre la tâche\",\n                \"MESSAGE\": \"Êtes-vous sûr de vouloir résoudre la tâche\",\n                \"CONFIRM\": \"Résoudre tâche\"\n            },\n            \"DELETE\": {\n                \"TITLE\": \"Supprimer la tâche\",\n                \"MESSAGE\": \"Êtes-vous sûr de vouloir supprimer la tâche\",\n                \"CONFIRM\": \"Supprimer la tâche\"\n            },\n            \"EDIT\": {\n                \"TITLE\": \"Modifier la tâche\",\n                \"CONFIRM\": \"Mettre à jour la tâche\",\n                \"NAME\": \"Nom\",\n                \"DESCRIPTION\": \"Description\",\n                \"PRIORITY\": \"Priorité\",\n                \"CATEGORY\": \"Catégorie\",\n                \"ASSIGNEE\": \"Personne assignée\",\n                \"OWNER\": \"Propriétaire\",\n                \"DUE-DATE\": \"Date d'échéance\"\n            }\n        }\n    },\n    \"TASKS\": {\n        \"TITLE\": \"Tâches\",\n        \"LIST-MESSAGE\": \"Montrer {{size}} resultats, sur un total de {{total}} tâches correspondantes.\",\n        \"LIST-MESSAGE-EMPTY\": \"Aucune tâches correspondates.\",\n        \"FILTER\": {\n            \"NAME\": \"Nom (sensible à la casse)\",\n            \"ASSIGNEE\": \"Personne assignée (sensible à la casse)\",\n            \"STATUS\": \"Statut\",\n            \"STATUS-ANY\": \"Aucun statut\",\n            \"STATUS-ACTIVE\": \"Tâches actives\",\n            \"STATUS-COMPLETE\": \"Tâches terminées\",\n            \"PROCESS-INSTANCE-ID\": \"Identifiant de l'instance du processus\",\n            \"TENANT-ID\": \"Identifiant du tenant\",\n            \"OWNER\": \"Propriétaire (sensible à la casse)\",\n            \"PARENT-TASK-ID\": \"Identifiant de la Tâche parent\",\n            \"CREATED-BEFORE\": \"Créé avant\",\n            \"CREATED-AFTER\": \"Créé après\",\n            \"ENDED-BEFORE\": \"Terminé avant\",\n            \"ENDED-AFTER\": \"Terminé après\",\n            \"DUE-BEFORE\": \"Echéance avant\",\n            \"DUE-AFTER\": \"Echéance après\",\n            \"TASK-VARIABLE\": \"Variable local de la tâche\",\n            \"PROCESS-VARIABLE\": \"Variable de processus\",\n            \"VARIABLE-NAME\": \"Nom de la variable\",\n            \"VARIABLE-VALUE\": \"Valeur de la variable\",\n            \"VARIABLE-BOOLEAN-VALUE\": \"Valeur booléenne: {{value}}\"\n        },\n        \"SORT\": {\n            \"NAME\": \"Nom\",\n            \"DUE-DATE\": \"Date d'échéance\",\n            \"START-TIME\": \"Temps de départ\",\n            \"END-TIME\": \"Tamps d'arrivée\",\n            \"PRIORITY\": \"Priorité\"\n        },\n        \"HEADER\": {\n            \"ID\": \"ID\",\n            \"NAME\": \"Nom\",\n            \"ASSIGNEE\": \"Personne assignée\",\n            \"OWNER\": \"Propriétaire\",\n            \"CREATE-TIME\": \"Créé le\",\n            \"END-TIME\": \"Terminé le\",\n            \"PRIORITY\": \"Priorité\"\n        }\n    },\n    \"DEPLOYMENTS\": {\n        \"TITLE\": \"Déploiements\",\n        \"LIST-MESSAGE\": \"Montrer {{size}} resultats,sur un total de {{total}} déploiements correspondants.\",\n        \"LIST-MESSAGE-EMPTY\": \"Aucun déploiements correspondants.\",\n        \"FILTER\": {\n            \"NAME\": \"Nom (sensible à la casse)\",\n            \"TENANTID\": \"Identifiant du tenant (sensible à la casse)\"\n        },\n        \"SORT\": {\n            \"ID\": \"ID\",\n            \"NAME\": \"Nom\"\n        },\n        \"HEADER\": {\n            \"ID\": \"ID\",\n            \"NAME\": \"Nom\",\n            \"DEPLOY-TIME\": \"Date de déploiement\",\n            \"CATEGORY\": \"Catégorie\",\n            \"TENANT\": \"Tenant\"\n        },\n        \"ACTION\": {\n            \"UPLOAD\": \"Télécharger un processus ou package\",\n            \"DELETE\": \"Supprimer le déploiement\"\n        },\n        \"POPUP\": {\n            \"UPLOAD\": {\n                \"DESCRIPTION\": \"Selectionner un fichier au format .bpmn, .bpmn20.xml afin de le déployer ou bien télécharger un fichier au format .zip or .bar contenant un ensemble de processesus.\",\n                \"DROPZONE\": \"ou déposer un fichier ici\",\n                \"NO-DROP\": \"Le dépôt de fichier n'est pas supporté par votre navigateur web\",\n                \"CANCEL-UPLOAD\": \"Annuler l'envoi\",\n                \"ERROR\": \"Impossible d'envoyer ce fichier\"\n            },\n            \"DELETE\": {\n            \t\"CONFIRM-MESSAGE\": \"Supprimer le déploiement '{{name}}'?\"\n            \t}\n        }\n    },\n    \"DEPLOYMENT\": {\n        \"ID\": \"ID:\",\n        \"NAME\": \"Nomo:\",\n        \"TIME\": \"Date de déploiement:\",\n        \"CATEGORY\": \"Catégorie:\",\n        \"TENANTID\": \"Identifiant du tenant:\",\n        \"DEFINITIONS-MESSAGE\": \"Ce déploiement a {{total}} définitions de processuss, afficher {{size}}.\",\n        \"DEFINITIONS-MESSAGE-EMPTY\": \"Ce déploiement n'a pas de définition du processuss.\",\n        \"TITLE\": {\n            \"DEFINITIONS\": \"Définition du processuss\",\n            \"RESOURCES\": \"Ressources\"\n        },\n        \"ACTION\": {\n            \"SHOW-ALL-DEFINITIONS\": \"Montrer toutes les définitions\"\n        }\n    },\n    \"JOB\": {\n        \"TITLE\": {\n            \"MAIN\": \"Job {{id}}\",\n            \"EXCEPTION\": \"Exception\"\n        },\n        \"ACTIONS\": {\n            \"EXECUTE\": \"Executer le job\",\n            \"MOVE\": \"Déplacer le job\",\n            \"DELETE\": \"Supprime le job\"\n        },\n        \"POPUP\": {\n            \"DELETE-JOB\": {\n                \"TITLE\": \"Supprimer le job '{{id}}'\",\n                \"MESSAGE\": \"Êtes-vous sûr de vouloir supprimer le job {{id}}?\",\n                \"CONFIRM\": \"Supprimer le job\"\n            }\n        },\n        \"ID\": \"ID:\",\n        \"EXECUTION-ID\": \"Execution ID:\",\n        \"PROCESS-INSTANCE\": \"Instance du processus:\",\n        \"PROCESS-DEFINITION\": \"Définition du processus:\",\n        \"DUEDATE\": \"Date d'échéance:\",\n        \"RETRIES-LEFT\": \"Tentatives restantes:\",\n        \"TENANT-ID\": \"Tenant:\"\n    },\n    \"JOBS\": {\n        \"TITLE\": \"Jobs\",\n        \"LIST-MESSAGE\": \"Montrer {{size}} resultats, sur un totle de {{total}} jobs correspondants.\",\n        \"LIST-MESSAGE-EMPTY\": \"Aucun jobs correspondants.\",\n        \"FILTER\": {\n        \t\"JOBTYPE\": {\n        \t\t\"LABEL\": \"Type de job \",\n        \t\t\"EXECUTABLE-JOB\": \"Jobs exécutables\",\n        \t\t\"TIMER-JOB\": \"Jobs temporisés\",\n        \t\t\"SUSPENDED-JOB\": \"Jobs suspendus\",\n        \t\t\"DEADLETTER-JOB\": \"Jobs perdus\"\n        \t},\n            \"PROCESS-DEFINITION\": \"Définition du processus\",\n            \"ALL-PROCESS-DEFINITIONS\": \"Toutes les définitions du processuss\",\n            \"PROCESS-INSTANCE-ID\": \"Identifiant de l'instance du processus \",\n            \"TENANT-ID\": \"Identifiant du tenant\",\n            \"DUE-BEFORE\": \"Echéance avant\",\n            \"DUE-AFTER\": \"Echéance après\",\n            \"EXCEPTION\": \"Exception\",\n            \"EXCEPTION-HELP\": \"Montrer uniquement les jobs avec exception\"\n        },\n        \"SORT\": {\n            \"ID\": \"Job ID\",\n            \"DUE-DATE\": \"Date d'échéance\",\n            \"PROCESS-INSTANCE-ID\": \"Identifiant de l'instance du processus \"\n        },\n        \"HEADER\": {\n            \"ID\": \"ID\",\n            \"DUE-DATE\": \"Date d'échéance\",\n            \"PROCESS-DEFINITION\": \"Définition du processus\",\n            \"RETRIES\": \"Tentatives\",\n            \"EXCEPTION\": \"Exception\"\n        }\n    },\n    \"EVENT-SUBSCRIPTION\": {\n        \"TITLE\": {\n            \"MAIN\": \"Abonnements à l'évènement {{id}}\"\n        },\n        \"ACTIONS\": {\n            \"TRIGGER\": \"Évènement déclencheur\"\n        },\n        \"ID\": \"ID:\",\n        \"ACTIVITY-ID\": \"Identifiant de l'activité:\",\n        \"EXECUTION-ID\": \"Identifiant de l'exécution:\",\n        \"PROCESS-INSTANCE\": \"Instance du Processus:\",\n        \"PROCESS-DEFINITION\": \"Définition du processus:\",\n        \"CREATE-DATE\": \"Date de création:\",\n        \"EVENT-TYPE\": \"Type d'évènement:\",\n        \"EVENT-NAME\": \"Nom de l'évènement:\",\n        \"TENANT-ID\": \"Tenant:\"\n    },\n    \"EVENT-SUBSCRIPTIONS\": {\n    \t\"TITLE\": \"Abonnements à l'évènement\",\n        \"LIST-MESSAGE\": \"Montrer {{size}} resultats, sur un total de {{total}} abonnements correspondants.\",\n        \"LIST-MESSAGE-EMPTY\": \"Aucun abonnements correspondants.\",\n    \t\"FILTER\": {\n            \"PROCESS-DEFINITION\": \"Définition du processus\",\n            \"ALL-PROCESS-DEFINITIONS\": \"Toutes les définition du processuss\",\n            \"PROCESS-INSTANCE-ID\": \"Identifiant de l'instance du processus \",\n            \"TENANT-ID\": \"Identifiant du tenant\",\n            \"CREATED-BEFORE\": \"Créé avant\",\n            \"CREATED-AFTER\": \"Créé après\"\n        },\n        \"SORT\": {\n            \"ID\": \"Identifiant de l'abonnement à l'évènement\",\n            \"CREATE-DATE\": \"Date de création\",\n            \"PROCESS-INSTANCE-ID\": \"Identifiant de l'instance du processus \"\n        },\n    \t\"HEADER\": {\n            \"ID\": \"ID\",\n            \"CREATE-DATE\": \"Date de création\",\n            \"PROCESS-DEFINITION\": \"Définition du processus\",\n            \"EVENT-TYPE\": \"Type d'évènement\",\n            \"EVENT-NAME\": \"Nom de l'évènement\"\n        }\n    },\n    \"LOGIN\": {\n        \"TITLE\": \"Se connecter\",\n        \"USERNAME\": \"Nom d'utilisateur\",\n        \"USERNAME-PLACEHOLDER\": \"Entrer votre nom d'utilisateur\",\n        \"PASSWORD\": \"Mot de passe\",\n        \"PASSWORD-PLACEHOLDER\": \"Entrer votre mot de passe\",\n        \"ACTION\": {\n            \"CONFIRM\": \"Se connecter\"\n        }\n    },\n    \"USER\": {\n        \"POPUP\": {\n            \"CHANGE-PASSWORD\": {\n                \"TITLE\": \"Changer le mot de passe pour'{{login}}'\",\n                \"OLD-PASSWORD\": \"Ancien mot de passe\",\n                \"NEW-PASSWORD\": \"Nouveau mot de passe\",\n                \"CONFIRM\": \"Changer le mot de passe\"\n            },\n            \"DELETE\": {\n                \"TITLE\": \"Supprimer l'utilisateur {{login}}\",\n                \"MESSAGE\": \"Êtes-vous sûr de vouloir supprimer l'utilisateur '{{login}}'?\",\n                \"CONFIRM\": \"Supprimer l'utilisateur\"\n            },\n            \"EDIT\": {\n                \"TITLE\": \"Modifier l'utilisateur {{login}}\",\n                \"LOGIN\": \"Nom d'utilisateur\",\n                \"EMAIL\": \"E-mail\",\n                \"FIRSTNAME\": \"Prénom\",\n                \"LASTNAME\": \"Nom\",\n                \"CONFIRM\": \"Modifier l'utilisateur\"\n            },\n            \"NEW\": {\n                \"TITLE\": \"Créer un nouvel utilisateur\",\n                \"LOGIN\": \"Nom d'utilisateur\",\n                \"EMAIL\": \"E-mail\",\n                \"FIRSTNAME\": \"Prénom\",\n                \"LASTNAME\": \"Nom\",\n                \"PASSWORD\": \"Mot de passe\",\n                \"ADMIN\": \"Posséde droits administrateur\",\n                \"CONFIRM\": \"Créer l'utilisateur\"\n            }\n        }\n    },\n    \"USERS\": {\n        \"TITLE\": \"Utilisateurs\",\n        \"ACTION\": {\n            \"EDIT\": \"Modifier l'utilisateur\",\n            \"NEW\": \"Créer un nouvel utilisateur\",\n            \"DELETE\": \"Supprimer l'utilisateur\",\n            \"CHANGE-PASSWORD\": \"Modifier le mot de passe\"\n        },\n        \"HEADER\": {\n            \"LOGIN\": \"Nom d'utilisateur\",\n            \"FIRSTNAME\": \"Prénom\",\n            \"LASTNAME\": \"Nom\",\n            \"EMAIL\": \"E-mail\",\n            \"CLUSTER_USER\": \"Cluster d'utilisateur\"\n        }\n    },\n    \"LICENSE\": {\n        \"POPUP\": {\n            \"TITLE\": \"Information de Licence \",\n            \"HOLDER\": \"Titulaire\",\n            \"SUBJECT\": \"Sujet\",\n            \"PRODUCTKEY\": \"Type de produit\",\n            \"GOODAFTERDATE\": \"Licence valide après\",\n            \"GOODBEFOREDATE\": \"Licence valide jusqu'au\",\n            \"NUMBER_OF_PROCESSES\": \"Nombre de processus actifs\",\n            \"NUMBER_OF_ADMINS\": \"Nombre d'administrateurs \",\n            \"MULTI_TENANT\": \"Multi tenant\",\n            \"DEFAULT_TENANT\": \"Tenant par défaut\"\n        }\n    },\n    \"CLUSTER\": {\n        \"NAME\": \"Nom:\",\n        \"USER\": \"Nom d'utilisateur:\",\n        \"MASTER-MANDATORY\": \"La configuration maître obligatoire:\",\n        \"METRICS-SEND-INTERVAL\": \"Metric send interval:\",\n        \"ENDPOINT-HELP\": \"La configuration du endpoint (chaque cluster en a un seul uniquement) a besoin de pointer vers une installation de Flowable REST. Ce endpoint sera utilisé pour retrouver et gérer les informations utilisées dans les autres sections (par exemple Déploiements, Définition du processuss...) de cette application.\",\n        \"ENDPOINT-NAME\": \"Nom:\",\n        \"ENDPOINT-DESCRIPTION\": \"Description:\",\n        \"ENDPOINT-ADDRESS\": \"Adresse du serveur:\",\n        \"ENDPOINT-PORT\": \"Port serveur:\",\n        \"ENDPOINT-CONTEXT-ROOT\": \"Context racine:\",\n        \"ENDPOINT-REST-ROOT\": \"Racine REST:\",\n        \"ENDPOINT-USERNAME\": \"Nom d'utilisateur:\",\n        \"PROCESS-ENGINE-HELP\": \"Cette section permet de définir 'la configuration maître' pour le cluster. Toutes les instances du cluster utiliseront cette configuration lors du démarrage (si le jar de configuration du cluster est dans le classpath ou si les propriétés correspondantes sont définies). Si la configuration n'est pas définie, les instances utiliseront leurs fichiers de configuration locaux.\",\n        \"NO-MASTER-DEFINED\": \"Aucune configuration maître définie\",\n        \"ACTION\": {\n            \"SHOW-PASSWORD\": \"Afficher le mot de passe\",\n            \"EDIT-CLUSTER-CONFIG\": \"Modifier la configuration du cluster\",\n            \"CREATE-CLUSTER-CONFIG\": \"Créer un nouveau cluster\",\n            \"DELETE-CLUSTER-CONFIG\": \"Supprimer la configuration du cluster\",\n            \"GENERATE-JAR\": \"Générer le 'jar' de configuration du cluster\",\n            \"EDIT-ENDPOINT\": \"Modifier REST endpoint\",\n            \"CHECK-ENDPOINT\": \"Vérifier REST endpoint\",\n            \"SELECT-MASTER\": \"Choisir la configuration maître\",\n            \"ADD-CONFIGURATION\": \"Ajouter une configuration maître\",\n            \"EDIT-CONFIGURATION\": \"Modifier la configuration maître\",\n            \"DELETE-CONFIGURATION\": \"Supprimer la configuration maître\"\n        },\n        \"TITLE\": {\n            \"PROCESS-ENDPOINT\": \"Process API Endpoint configuration\",\n            \"DMN-ENDPOINT\": \"DMN API Endpoint configuration\",\n            \"FORM-ENDPOINT\": \"Form API Endpoint configuration\",\n            \"CONTENT-ENDPOINT\": \"Content API Endpoint configuration\"\n        },\n        \"POPUP\": {\n            \"EDIT-ENDPOINT\": {\n                \"ENDPOINT-NAME\": \"Nom\",\n                \"ENDPOINT-DESCRIPTION\": \"Description\",\n                \"ENDPOINT-ADDRESS\": \"Adresse Serveur\",\n                \"ENDPOINT-PORT\": \"Port serveur\",\n                \"ENDPOINT-CONTEXT-ROOT\": \"Context Racine\",\n                \"ENDPOINT-REST-ROOT\": \"Racine REST\",\n                \"ENDPOINT-USERNAME\": \"Nom d'utilisateur\",\n                \"ENDPOINT-PASSWORD\": \"Mot de Passe\",\n                \"ENDPOINT-PASSWORD-HELP\": \"Laisser vide pour garder le mot de passe courant\",\n                \"ENDPOINT-URL-PREVIEW\": \"URL aperçu\",\n                \"ACTION-CONFIRM\": \"Sauvegarder la configuration du endpoint\",\n                \"ERROR-401\": \"Erreur: identifiants invalides\",\n                \"ERROR-403\": \"Erreur: identifiants invalides or mauvaise URL\",\n                \"ERROR-404\": \"Erreur: URL non trouvée\",\n                \"ERROR-500\": \"Erreur: erreur serveur. Vérifier les logs serveur.\"\n            }\n        }\n    },\n    \"APP-DEPLOYMENTS\": {\n        \"TITLE\": \"Déploiements d'Applications\",\n        \"LIST-MESSAGE\": \"Montrer {{size}} resultats, sur un total de {{total}} déploiements d'App.\",\n        \"LIST-MESSAGE-EMPTY\": \"Aucun déploiements correspondants.\",\n        \"FILTER\": {\n            \"NAME\": \"Nom\",\n            \"TENANTID\": \"Identifiant du tenant\",\n            \"LATEST\": \"Dernière version\",\n            \"LATEST-HELP\": \"Afficher uniquement les dernières versions\"\n        },\n        \"SORT\": {\n            \"ID\": \"ID\",\n            \"NAME\": \"Nom\"\n        },\n        \"HEADER\": {\n            \"ID\": \"ID\",\n            \"APP-DEFINITION-ID\": \"Identifiant de l'App\",\n            \"DEPLOYMENT-ID\": \"Identifiant du déploiement de processus\",\n            \"DMN-DEPLOYMENT-ID\": \"Identifiant du déploiement DMN\",\n            \"NAME\": \"Nom\",\n            \"DEPLOY-TIME\": \"Date du déploiement\",\n            \"DEPLOYED-BY\": \"Deployé par\",\n            \"TENANT\": \"Identifiant du Tenant\"\n        },\n        \"ACTION\": {\n            \"UPLOAD\": \"Envoyer et publier une App\"\n        },\n        \"POPUP\": {\n            \"UPLOAD\": {\n                \"DESCRIPTION\": \"Selectionner un fichier au format .zip à deployer.\",\n                \"WARNING\": \"Uploading a process is only possible to an Flowable UI instance.\",\n                \"DROPZONE\": \"ou déposer un fichier ici\",\n                \"NO-DROP\": \"Le dépôt de fichier n'est pas supporté par votre navigateur web\",\n                \"CANCEL-UPLOAD\": \"Annuler l'envoi\",\n                \"ERROR\": \"Impossible d'envoyer ce fichier\"\n            }\n        }\n    },\n    \"VARIABLES\": {\n        \"HEADER\": {\n            \"NAME\": \"Nom\",\n            \"TYPE\": \"Type\",\n            \"VALUE\": \"Valeur\"\n        }\n    },\n    \"IDENTITY-LINKS\": {\n        \"HEADER\": {\n            \"GROUP-ID\": \"Identifiant de groupe\",\n            \"TYPE\": \"Type\",\n            \"USER-ID\": \"Identifiant de l'utilisateur\"\n        }\n    },\n    \"ALERT\": {\n        \"GENERAL\": {\n            \"HTTP-ERROR\": \"Nous sommes dans l'impossibilité de retrouver les informations du serveur\",\n            \"AUTHENTICATION-ERROR\": \"Vous avez entré de mauvaises informations\"\n        },\n        \"ENGINE\": {\n            \"ENDPOINT-UPDATED\": \"Le Endpoint '{{name}}' a été mis à jour.\",\n            \"ENDPOINT-INVALID\": \"La configuration du Endpoint '{{name}}' est invalide.\",\n            \"ENDPOINT-VALID\": \"Endpoint valide, Moteur du endpoint: {{name}} - {{version}}\"\n        },\n        \"JOB\": {\n            \"DELETED\": \"Le Job '{{id}}' a été supprimé.\",\n            \"MOVED\": \"Le Job '{{id}}' a été déplacé.\",\n            \"EXECUTED\": \"Le Job '{{id}}' a été exécuté.\"\n        },\n        \"EVENT-SUBSCRIPTION\": {\n        \t\"TRIGGERED\": \"L'abonnement à l'événement '{{id}}' a été déclenché.\"\n        },\n        \"PROCESS-INSTANCE\": {\n            \"DELETED\": \"L'instance de processus '{{id}}' a été supprimé.\",\n            \"TERMINATED\": \"L'instance de processus  '{{id}}' a été terminé.\"\n        },\n        \"TASK\": {\n            \"DELETED\": \"La tâche '{{id}}' a été supprimée.\",\n            \"COMPLETED\": \"La tâche '{{id}}' a été terminé avec succès.\",\n            \"DELEGATED\": \"La tâche '{{id}}' a été délégué à l'utilisateur {{user}}.\",\n            \"RESOLVED\": \"La tâche '{{id}}' a été résolue\",\n            \"ASSIGNED\": \"La tâche '{{id}}' est maintenant assigné à {{user}}.\",\n            \"UNASSIGNED\": \"La tâche '{{id}}' is maintenant non-assigné.\",\n            \"UPDATED\": \"La tâche '{{id}}' a été mise à jour.\"\n        },\n        \"USER\": {\n            \"DELETED\": \"L'utilisateur '{{login}}' a été supprimé.\",\n            \"UPDATED\": \"L'utilisateur '{{login}}' a été mise à jour.\",\n            \"CREATED\": \"L'utilisateur '{{login}}' a été créé.\",\n            \"PASSWORD-CHANGED\": \"Le mot de passe pour '{{login}}' a été modifié avec succès.\"\n        },\n        \"PROCESS-DEFINITION\": {\n            \"CATEGORY-UPDATED\": \"La catégorie de la définition du processus Catégorie a été mis à jour\"\n        },\n        \"DEPLOYMENT\": {\n        \t\"DELETED-DEPLOYMENT\": \"Déploiement supprimé '{{name}}'\",\n        \t\"DELETE-ERROR\": \"Impossible de supprimer le déploiement. {{exception || ''}}\",\n        \t\"DEPLOYMENT-SUCCESS\": \"Le déploiement a réussi\"\n        },\n        \"APP-DEPLOYMENT\": {\n        \t\"DELETED-APP\": \"App supprimée '{{appDefinition.name}}'\",\n        \t\"DELETE-ERROR\": \"Impossible de supprimer l'App. {{message || ''}}\"\n        }\n    },\n    \"DECISION-TABLE-DEPLOYMENTS\": {\n        \"TITLE\": \"Déploiements des tables de décision\",\n        \"LIST-MESSAGE\": \"Montrer {{size}} resultats, sur un total de {{total}} déploiements correspondants.\",\n        \"LIST-MESSAGE-EMPTY\": \"Aucun déploiements correspondants.\",\n        \"FILTER\": {\n            \"NAME\": \"Nom (sensible à la casse)\",\n            \"TENANTID\": \"Identifiant du tenant (sensible à la casse)\"\n        },\n        \"SORT\": {\n            \"ID\": \"ID\",\n            \"NAME\": \"Nom\"\n        },\n        \"HEADER\": {\n            \"ID\": \"ID\",\n            \"NAME\": \"Nom\",\n            \"DEPLOY-TIME\": \"Temps du déploiement\",\n            \"CATEGORY\": \"Catégorie\",\n            \"TENANT\": \"Tenant\"\n        },\n        \"ACTION\": {\n            \"DELETE\": \"Supprimer le déploiement\"\n        }\n    },\n    \"DECISION-TABLE-DEPLOYMENT\": {\n        \"ID\": \"ID:\",\n        \"NAME\": \"Nom:\",\n        \"TIME\": \"Date de déploiement:\",\n        \"CATEGORY\": \"Catégorie:\",\n        \"TENANTID\": \"Identifiant du tenant:\",\n        \"DECISION-TABLES-MESSAGE\": \"Ce déploiement comporte{{total}} tables de décision, afficher {{size}}.\",\n        \"DECISION-TABLES-MESSAGE-EMPTY\": \"Ce déploiement n'a pas de tables de décision.\",\n        \"PARENT-DEPLOYMENT-ID\": \"Identifiant du déploiement parent\",\n        \"TITLE\": {\n            \"DECISION-TABLES\": \"Tables de décisions\",\n            \"RESOURCES\": \"Ressources\"\n        },\n        \"ACTION\": {\n            \"SHOW-ALL-DEFINITIONS\": \"Afficher toutes les tables de décision \"\n        }\n    },\n    \"DECISION-TABLES\": {\n        \"TITLE\": \"Tables de décision\",\n        \"LIST-MESSAGE\": \"Montrer {{size}} resultats, sur un total de {{total}} tables de décisions correspondantes.\",\n        \"LIST-MESSAGE-EMPTY\": \"Aucune tables de décision correspondantes.\",\n        \"FILTER\": {\n            \"NAME\": \"Nom\",\n            \"KEY\": \"Clé\",\n            \"TENANTID\": \"Identifiant du tenant\"\n        },\n        \"SORT\": {\n            \"ID\": \"ID\",\n            \"NAME\": \"Nom\"\n        },\n        \"HEADER\": {\n            \"ID\": \"ID\",\n            \"NAME\": \"Nom\",\n            \"VERSION\": \"Version\",\n            \"KEY\": \"Clé\",\n            \"DEPLOY-TIME\": \"Temps du déploiement\",\n            \"TENANT-ID\": \"Tenant ID\"\n        }\n    },\n    \"DECISION-TABLE\": {\n        \"ID\": \"ID:\",\n        \"NAME\": \"Nom:\",\n        \"VERSION\": \"Version:\",\n        \"KEY\": \"Clé:\",\n        \"DEPLOYMENT-ID\": \"Identifiant du déploiement:\",\n        \"PARENT-DEPLOYMENT-ID\": \"Identifiant du déploiement parent:\",\n        \"RESOURCE-NAME\": \"Nom de la resource:\",\n        \"DESCRIPTION\": \"Description:\",\n        \"TENANT\": \"Tenant:\",\n        \"TITLE\": {\n            \"DECISION-AUDITS\": \"Audits de décision\"\n        },\n        \"DECISION-AUDITS-MESSAGE\": \"Cette table de décision posséde {{total}} audits, afficher {{size}}.\",\n        \"DECISION-AUDITS-MESSAGE-EMPTY\": \"Cette table de décision table n'a pas d'audits\",\n        \"ACTION\": {\n            \"EDIT-CATEGORY\": \"Modifier Catégorie\",\n            \"SHOW-ALL-JOBS\": \"Montrer tous les jobs\",\n            \"SHOW-ALL-PROCESSES\": \"Montrer tous les  processus\",\n            \"SHOW-DIAGRAM\": \"Afficher le diagramme de processus\",\n            \"SHOW-DECISION-TABLE\": \"Montrer la table de décision\"\n        },\n        \"POPUP\": {\n            \"TITLE\": \"Table de décision: \",\n            \"KEY\": \"Clé: \",\n            \"HIT-POLICY\": \"Hit Policy: \",\n            \"HIT-POLICIES\": {\n                \"FIRST\": \"Premier (Single pass)\",\n                \"ANY\": \"Aucun (Single pass)\"\n            }\n        }\n    },\n    \"FORM-DEFINITIONS\": {\n    \t\"TITLE\": \"Définitions de formulaires\",\n        \"LIST-MESSAGE\": \"Montrer {{size}} resultats, sur un total de {{total}} formulaires correspondants.\",\n        \"LIST-MESSAGE-EMPTY\": \"Aucune définition de formulaire correspondantes.\",\n        \"HEADER\": {\n            \"ID\": \"ID\",\n            \"NAME\": \"Nom\",\n            \"DEPLOYMENTID\": \"Identifiant du déploiement\",\n            \"TENANTID\": \"Identifiant du Tenant\",\n            \"KEY\": \"Clé\",\n            \"VERSION\": \"Version\"\n        },\n        \"FILTER\": {\n            \"NAME\": \"Nom\",\n            \"APPID\": \"Identifiant du déploiement de l'App\",\n            \"TENANTID\": \"Identifiant du tenant\"\n        },\n        \"SORT\": {\n            \"ID\": \"ID\",\n            \"NAME\": \"Nom\"\n        }\n    },\n    \"FORM-DEFINITION\": {\n        \"ID\": \"ID:\",\n        \"NAME\": \"Nom:\",\n        \"PARENT-DEPLOYMENT-ID\": \"Identifiant de déploiement parent:\",\n        \"DEPLOYMENT-ID\": \"Identifiant de déploiement:\",\n        \"DESCRIPTION\": \"Description:\",\n        \"TENANT\": \"Tenant:\",\n        \"MESSAGE-EMPTY\": \"(None)\",\n        \"TITLE\": {\n            \"FORM-INSTANCES\": \"Instances de formulaire\"\n        },\n        \"FORM-INSTANCES-MESSAGE\": \"Cette définition possède {{total}} instances de formulaires, afficher {{size}}.\",\n        \"FORM-INSTANCES-MESSAGE-EMPTY\": \"Cette définition n'a pas d'intance de formulaires\",\n        \"ACTION\": {\n            \"EDIT-CATEGORY\": \"Modifier la Catégorie\",\n            \"SHOW-ALL-JOBS\": \"Montrer tous les jobs\",\n            \"SHOW-ALL-PROCESSES\": \"Montrer tous les processus\",\n            \"SHOW-DIAGRAM\": \"Montrer le diagramme de processus\",\n            \"SHOW-FORM\": \"Afficher le formulaire\"\n        },\n        \"POPUP\": {\n            \"TITLE\": \"Formulaire: \"\n        },\n        \"FIELD-PREVIEW\" : {\n        \t\"DISPLAY-REF\": \"Valeur affichée\",\n        \t\"SELECT-FIELD\": \"(Aucun champ sélectionné)\",\n        \t\"FIELD-VALUE\": \"Montrer la valeur du champ \\\"{{name}}\\\"\",\n        \t\"UNKNOWN-TYPE\": \"Type de champ indéfini {{type}}\",\n        \t\"TEXT-VALUE\": \"Texte\",\n        \t\"MULTI-TEXT-VALUE\": \"Champ muli-lignes\",\n        \t\"NUMBER-VALUE\": \"123\",\n        \t\"DATE-VALUE\": \"Date\",\n        \t\"DROPDOWN-VALUE\": \"Sélectionner ...\",\n        \t\"UPLOAD-VALUE\": \"Télécharger ou import un contenu...\",\n        \t\"RADIOS-OPTION1\": \"Option 1\",\n        \t\"SELECT-PERSON\": \"Choisir une personne\",\n        \t\"SELECT-GROUP\": \"Choisir un groupe\"\n        \t}\n    },\n    \"FORM-DEPLOYMENTS\": {\n        \"TITLE\": \"Déploiements de formulaire \",\n        \"LIST-MESSAGE\": \"Montrer {{size}} resultats, sur un total de {{total}} déploiements de formulaire correspondants.\",\n        \"LIST-MESSAGE-EMPTY\": \"Aucun déploiements de formulaire correspondant.\",\n        \"FILTER\": {\n            \"NAME\": \"Nom (sensible à la casse)\",\n            \"TENANTID\": \"Identifiant du tenant (sensible à la casse)\"\n        },\n        \"SORT\": {\n            \"ID\": \"ID\",\n            \"NAME\": \"Nom\"\n        },\n        \"HEADER\": {\n            \"ID\": \"ID\",\n            \"NAME\": \"Nom\",\n            \"DEPLOY-TIME\": \"Temps du déploiement\",\n            \"CATEGORY\": \"Catégorie\",\n            \"TENANT\": \"Tenant\"\n        },\n        \"ACTION\": {\n            \"DELETE\": \"Supprimer le déploiement\"\n        }\n    },\n    \"FORM-DEPLOYMENT\": {\n        \"ID\": \"ID:\",\n        \"NAME\": \"Nom:\",\n        \"TIME\": \"Date de déploiement:\",\n        \"CATEGORY\": \"Catégorie:\",\n        \"TENANTID\": \"Identifiant du tenant:\",\n        \"PARENT-DEPLOYMENT-ID\": \"Identifiant du déploiement parent\",\n        \"DEFINITIONS-MESSAGE\": \"Ce déploiement a {{total}} définitions de formulaire, afficher {{size}}.\",\n        \"DEFINITIONS-MESSAGE-EMPTY\": \"Ce déploiement n'a pas de définitions de formulaire.\",\n        \"TITLE\": {\n            \"FORM-DEFINITIONS\": \"Définitions de formulaire \",\n            \"RESOURCES\": \"Ressources\"\n        },\n        \"ACTION\": {\n            \"SHOW-ALL-DEFINITIONS\": \"Montrer toutes les définitions de formulaire\"\n        }\n    },\n    \"FORM-INSTANCES\": {\n        \"TITLE\": \"Form instances\",\n        \"LIST-MESSAGE\": \"Montrer {{size}} resultats, sur un total de {{total}} instances de formulaires correspondantes\",\n        \"LIST-MESSAGE-EMPTY\": \"Aucune instances de formulaires correspondantes.\",\n        \"HEADER\": {\n            \"ID\": \"ID\",\n            \"PROCESS-INSTANCE-ID\": \"Identifiant de l'instance du processus \",\n            \"TASK-ID\": \"Identifiant de tâche\",\n            \"SUBMITTED-ON\": \"Date de soumission\",\n            \"SUBMITTED-BY\": \"Soumis par\",\n            \"TENANT-ID\": \"Identifiant du tenant\"\n        },\n        \"FILTER\": {\n            \"NAME\": \"Nom\",\n            \"TENANTID\": \"Identifiant du tenant\"\n        },\n        \"SORT\": {\n            \"SUBMITTED-DATE\": \"Date de soumission\"\n        }\n    },\n    \"FORM-INSTANCE\": {\n        \"HEADER\": {\n            \"ID\": \"ID\",\n            \"TASK-ID\": \"Identifiant de Tâche\",\n            \"PROCESS-ID\": \"Identifiant de l'instance du processus \",\n            \"SUBMITTED\": \"Date de soumission\",\n            \"SUBMITTED-BY\": \"Soumis par\",\n            \"FORM-DEFINITION-ID\": \"Identifiant de la définition de formulaire\"\n        },\n        \"FORM-FIELD-VALUES-MESSAGE\": \"Cette instance a {{total}} valeurs de champs, montrer {{size}}\",\n        \"FORM-FIELD-VALUES-MESSAGE-EMPTY\": \"Cette instance n'a pas de valeurs de champ\",\n        \"ACTION\": {\n            \"SHOW-FORM-INSTANCE\": \"Montrer l'instance de formulaire\"\n        },\n        \"TITLE\": {\n            \"FORM-FIELD-VALUES\": \"Valeurs du champs de formulaire\"\n        },\n        \"FORM-FIELD-VALUES\": {\n            \"ID\": \"Identifiant du champ de formulaire\",\n            \"NAME\": \"Nom du champ de formulaire\",\n            \"TYPE\": \"Type du champ de formulaire\",\n            \"VALUE\": \"Valeur du champs de formulaire\"\n        }\n    },\n    \"CONTENT-ITEMS\": {\n        \"TITLE\": \"Liste des contenus\",\n        \"LIST-MESSAGE\": \"Montrer {{size}} résultats, sur un total de {{total}} contenus correspondants.\",\n        \"LIST-MESSAGE-EMPTY\": \"Aucun contenus correspondants.\",\n        \"HEADER\": {\n            \"ID\": \"ID\",\n            \"NAME\": \"Nom\",\n            \"PROCESS-INSTANCE-ID\": \"Identifiant de l'instance du Processus\",\n            \"TASK-ID\": \"Identifiant de tâche\",\n            \"LAST-MODIFIED-ON\": \"Date de modification\",\n            \"LAST-MODIFIED-BY\": \"Modifié par\",\n            \"TENANT-ID\": \"Identifiant du Tenant\"\n        },\n        \"FILTER\": {\n            \"NAME\": \"Nom\",\n            \"TENANTID\": \"Identifiant du Tenant\"\n        },\n        \"SORT\": {\n            \"CREATED\": \"Date de création\"\n        }\n    },\n    \"CONTENT-ITEM\": {\n        \"HEADER\": {\n            \"ID\": \"ID\",\n            \"TASK-ID\": \"Identifiant de tâche\",\n            \"PROCESS-INSTANCE-ID\": \"Identifiant de l'instance du Processus\",\n            \"CREATED-ON\": \"Date de création\",\n            \"CREATED-BY\": \"Créé par\",\n            \"LAST-MODIFIED-ON\": \"Date de modification\",\n            \"LAST-MODIFIED-BY\": \"Modifié par\",\n            \"CONTENT-STORE-ID\": \"Identifiant du Content store\"\n        },\n        \"ACTION\": {\n            \"SHOW-CONTENT-ITEM\": \"Voir le contenu\"\n        }\n    }\n}\n"
  },
  {
    "path": "flowable-ui-web/admin/i18n/pt-BR.json",
    "content": "{\n  \"GENERAL\":{\n    \"YES\":\"Sim\",\n    \"NO\":\"Não\",\n    \"ACTION\":{\n      \"LOGOUT\":\"Sair\",\n      \"DISMISS-ALERT\":\"Clique para ignorar esta mensagem\",\n      \"RETURN-TO-LIST\":\"Retornar à Lista\",\n      \"SHOW-RESULTS\":\"Mostrar {{'GENERAL.RESULT-SIZES.' + resultSize.toString() | translate}} resultados\",\n      \"REFRESH-LIST\":\"Atualizar lista\",\n      \"SORT-BY\":\"Classificar por {{name | translate}}\",\n      \"CLEAR-FILTERS\":\"Limpar filtros\",\n      \"CANCEL-AND-CLOSE\":\"Cancelar e fechar\",\n      \"CANCEL\":\"Cancelar\",\n      \"NEXT\":\"Próximo\",\n      \"PREVIOUS\":\"Anterior\",\n      \"CLOSE\":\"Fechar\",\n      \"SHOWLICENSE\":\"Informações da licença\"\n    },\n    \"TITLE\":{\n      \"MAIN\":\"Administrador Activiti\",\n      \"ACTIONS\":\"Ações\",\n      \"FILTERS\":\"Filtros\"\n    },\n    \"MENU\":{\n      \"PROCESS-ENGINE\":\"Motor de Processo\",\n      \"FORM-ENGINE\":\"Motor de Formulários\",\n      \"CONTENT-ENGINE\":\"Motor de Conteúdo\",\n      \"DMN-ENGINE\":\"Motor de DMN\",\n      \"DEPLOYMENTS\":\"Implantações\",\n      \"DEFINITIONS\":\"Definições\",\n      \"INSTANCES\":\"Instâncias\",\n      \"TASKS\":\"Tarefas\",\n      \"JOBS\":\"Trabalhos\",\n      \"EVENT-SUBSCRIPTIONS\":\"Inscrições em eventos\",\n      \"CONFIGURATION\":\"Configuração\",\n      \"CONFIGURATION-ENGINE\":\"Mecanismo\",\n      \"DECISION-TABLES\":\"Tabelas de decisão\",\n      \"CONTENT-ITEMS\":\"Itens de conteúdo\"\n    },\n    \"RESULT-SIZES\":{\n      \"10\":\"10\",\n      \"25\":\"25\",\n      \"50\":\"50\",\n      \"100\":\"100\",\n      \"100000000\":\"todos\"\n    }\n  },\n  \"PROCESS-DEFINITION\":{\n    \"ID\":\"ID:\",\n    \"NAME\":\"Nome:\",\n    \"VERSION\":\"Versão:\",\n    \"DESCRIPTION\":\"Descrição:\",\n    \"KEY\":\"Chave:\",\n    \"CATEGORY\":\"Categoria:\",\n    \"SUSPENDED\":\"Suspenso:\",\n    \"DEPLOYMENT\":\"Implantação:\",\n    \"TENANT\":\"Tenant:\",\n    \"START-FORM-DEFINED\":\"Formulário inicial definido:\",\n    \"GRAPHICAL-NOTATION-DEFINED\":\"Notação gráfica definida:\",\n    \"PROCESS-INSTANCES-SIZE\":\"A definição tem {{total}} instâncias de processo em execução\",\n    \"PROCESS-INSTANCES-SHOWING\":\", mostrando {{size}} mais recentemente iniciadas\",\n    \"PROCESS-INSTANCES-EMPTY\":\"A definição não tem instâncias de processo em execução\",\n    \"JOBS-SIZE\":\"A definição tem {{total}} trabalhos em execução\",\n    \"JOBS-EMPTY\":\"A definição não tem trabalhos em execução\",\n    \"DECISION-TABLES-SIZE\":\"A definição tem {{total}} tabelas de decisão.\",\n    \"DECISION-TABLES-EMPTY\":\"A definição não tem tabelas de decisão.\",\n    \"FORM-DEFINITIONS-SIZE\":\"A definição tem {{total}} formulários.\",\n    \"FORM-DEFINITIONS-EMPTY\":\"A definição não tem formulários.\",\n    \"TITLE\":{\n      \"PROCESS-INSTANCES\":\"Instâncias de processo\",\n      \"JOBS\":\"Trabalhos\",\n      \"DECISION-TABLES\":\"Tabelas de decisão\",\n      \"FORMS\":\"Formulários\"\n    },\n    \"ACTION\":{\n      \"EDIT-CATEGORY\":\"Editar categoria\",\n      \"SHOW-ALL-JOBS\":\"Mostrar todos os trabalhos\",\n      \"SHOW-ALL-PROCESSES\":\"Mostrar todos os processos\",\n      \"SHOW-DIAGRAM\":\"Mostrar o diagrama de processo\"\n    },\n    \"POPUP\":{\n      \"EDIT-CATEGORY\":{\n        \"TITLE\":\"Editar categoria para a definição\",\n        \"MESSAGE\":\"A categoria inicial da definição é preenchida com base no atributo targetNameSpace no XML do BPMN 2.0, mas pode ser alterada após a implantação.\",\n        \"CATEGORY\":\"Categoria\",\n        \"CATEGORY-PLACEHOLDER\":\"Insira uma categoria\",\n        \"CONFIRM\":\"Atualizar categoria\"\n      },\n      \"SHOW-PROCESS-MODEL\":{\n        \"TITLE\":\"Diagrama de processo\"\n      }\n    }\n  },\n  \"PROCESS-DEFINITIONS\":{\n    \"LIST-MESSAGE\":\"Mostrando {{size}} resultados, de um total de {{total}} definições correspondentes.\",\n    \"LIST-MESSAGE-EMPTY\":\"Nenhuma definição de processo correspondente.\",\n    \"FILTER\":{\n      \"NAME\":\"Nome (com diferenciação entre maiúsculas e minúsculas)\",\n      \"KEY\":\"Chave (com diferenciação entre maiúsculas e minúsculas)\",\n      \"DEPLOYMENT-ID\":\"ID de implantação\",\n      \"TENANT-ID\":\"ID do Tenant\",\n      \"LATEST\":\"Versão mais recente\",\n      \"LATEST-HELP\":\"Mostrar apenas as versões mais recentes\"\n    },\n    \"TITLE\":{\n      \"MAIN\":\"Definições de Processo\"\n    },\n    \"SORT\":{\n      \"ID\":\"ID\",\n      \"NAME\":\"Nome\",\n      \"VERSION\":\"Versão\"\n    },\n    \"HEADER\":{\n      \"ID\":\"ID\",\n      \"NAME\":\"Nome\",\n      \"VERSION\":\"Versão\",\n      \"KEY\":\"Chave\",\n      \"TENANT\":\"Tenant\"\n    },\n    \"ACTIONS\":{\n      \"UPLOAD-FROM-MODELER\":\"Carregar a partir do Editor Flowable\"\n    },\n    \"POPUP\":{\n      \"UPLOAD-FROM-MODELER\":{\n        \"NAME\":\"Usuário\",\n        \"PASSWORD\":\"Senha\",\n        \"ERROR\":\"Não foi possível encontrar o Editor\",\n        \"UNAUTHORIZED\":\"Credenciais inválidas\",\n        \"UPLOAD-DESCRIPTION\":\"O modelo de processo agora será identificado e implantado no cluster Flowable ativo. Selecione um nome adequado para o pacote de implantação.\"\n      }\n    }\n  },\n  \"PROCESS-INSTANCE\":{\n    \"ID\":\"ID:\",\n    \"NAME\":\"Nome:\",\n    \"DESCRIPTION\":\"Descrição:\",\n    \"BUSINESS-KEY\":\"Chave do negócio:\",\n    \"TENANT-ID\":\"Tenant:\",\n    \"STATUS\":\"Status:\",\n    \"STATUS-ACTIVE\":\"Ativo\",\n    \"STATUS-COMPLETED\":\"Concluído\",\n    \"ACTIVITY-ID-STARTED\":\"ID da atividade iniciada:\",\n    \"ACTIVITY-ID-ENDED\":\"Finalizado na atividade:\",\n    \"DELETE-REASON\":\"Motivo de exclusão:\",\n    \"STARTED-BY\":\"Iniciado por:\",\n    \"END-TIME\":\"Término:\",\n    \"DURATION\":\"Duração:\",\n    \"SUPER-PROCESS-INSTANCE-ID\":\"ID de instância do processo pai:\",\n    \"TASKS-SIZE\":\"Esta instância de processo tem {{total}} tarefas.\",\n    \"TASKS-EMPTY\":\"Esta instância de processo não tem tarefas.\",\n    \"VARIABLES-SIZE\":\"Esta instância de processo tem {{total}} variáveis.\",\n    \"VARIABLES-EMPTY\":\"Esta instância de processo não tem variáveis.\",\n    \"JOBS-SIZE\":\"Esta instância de processo tem {{total}} trabalhos.\",\n    \"JOBS-EMPTY\":\"Esta instância de processo não tem trabalhos.\",\n    \"SUBPROCESSES-SIZE\":\"Esta instância de processo tem {{total}} subprocessos.\",\n    \"SUBPROCESSES-EMPTY\":\"Esta instância de processo não tem subprocessos.\",\n    \"DECISION-TABLES-SIZE\":\"Esta instância de processo tem {{total}} tabelas de decisão.\",\n    \"DECISION-TABLES-EMPTY\":\"Esta instância de processo não tem tabelas de decisão.\",\n    \"FORM-INSTANCES-SIZE\":\"Esta instância de processo tem {{total}} formulários.\",\n    \"FORM-INSTANCES-EMPTY\":\"Esta instância de processo não tem formulários.\",\n    \"TITLE\":{\n      \"TASKS\":\"Tarefas\",\n      \"VARIABLES\":\"Variáveis\",\n      \"JOBS\":\"Trabalhos\",\n      \"SUBPROCESSES\":\"Subprocessos\",\n      \"DECISION-TABLES\":\"Tabelas de decisão\",\n      \"FORM-INSTANCES\":\"Formulários\"\n    },\n    \"ACTION\":{\n      \"DELETE\":\"Excluir instância de processo\",\n      \"TERMINATE\":\"Encerrar instância de processo\",\n      \"SHOW-ALL-TASKS\":\"Mostrar todas as tarefas\",\n      \"SHOW-ALL-JOBS\":\"Mostrar todos os trabalhos\",\n      \"SHOW-ALL-SUBPROCESSES\":\"Mostrar todos os subprocessos\",\n      \"SHOW-DIAGRAM\":\"Mostrar diagrama de processo\",\n      \"TITLE-VARIABLES\":\"Ações na variável selecionada\",\n      \"DELETE-VARIABLE\":\"Excluir a variável\",\n      \"UPDATE-VALUE\":\"Atualizar variável\",\n      \"ADD-VARIABLE\":\"Adicionar variável\"\n    },\n    \"POPUP\":{\n      \"DELETE\":{\n        \"TITLE\":\"Excluir instância de processo\",\n        \"MESSAGE-DELETE\":\"Tem certeza que deseja excluir a instância do processo?\",\n        \"MESSAGE-TERMINATE\":\"Tem certeza que deseja encerrar a instância do processo?\",\n        \"DELETE-REASON\":\"Motivo da exclusão\",\n        \"DELETE-REASON-HELP\":\"Insira um motivo de exclusão (opcional)\",\n        \"CONFIRM-DELETE\":\"Excluir instância de processo\",\n        \"CONFIRM-TERMINATE\":\"Encerrar instância de processo\"\n      },\n      \"SHOW-PROCESS-MODEL\":{\n        \"TITLE\":\"Diagrama de processo\"\n      },\n      \"CREATE-VARIABLE\":{\n        \"TITLE\":\"Criar variável\",\n        \"NAME\":\"Nome da variável\",\n        \"TYPE\":\"Tipo de variável\",\n        \"VALUE\":\"Valor da variável\",\n        \"CREATE\":\"Criar\"\n      },\n      \"UPDATE-VARIABLE\":{\n        \"TITLE\":\"Atualizar a variável '{{name}}'\",\n        \"NAME\":\"Nome da variável\",\n        \"VALUE\":\"Valor\",\n        \"CHECKED\":\"verdadeiro\",\n        \"UNCHECKED\":\"falso\",\n        \"DATE-HELP\":\"Formato ISO-8601 (exemplo: 2016-01-28T23:00:00Z)\",\n        \"ACTION-UPDATE\":\"Atualizar\"\n      },\n      \"DELETE-VARIABLE\":{\n        \"TITLE\":\"Excluir a variável '{{name}}'\",\n        \"MESSAGE\":\"Tem certeza que deseja remover essa variável?\",\n        \"DELETE\":\"Excluir\"\n      }\n    }\n  },\n  \"PROCESS-INSTANCES\":{\n    \"TITLE\":\"Instâncias de processo\",\n    \"LIST-MESSAGE\":\"Mostrando {{size}} resultados, de um total de {{total}} instâncias de processo correspondentes.\",\n    \"LIST-MESSAGE-EMPTY\":\"Não há instâncias de processos correspondente.\",\n    \"FILTER\":{\n      \"NAME\":\"Nome\",\n      \"PROCESS-DEFINITION\":\"Definição de processo\",\n      \"ALL-PROCESS-DEFINITIONS\":\"Todas as definições de processo\",\n      \"BUSINESS-KEY\":\"Chave de negócios\",\n      \"SUPER-PROCESS-INSTANCE-ID\":\"ID de instância do processo pai\",\n      \"STARTED-BEFORE\":\"Iniciado antes\",\n      \"STARTED-AFTER\":\"Iniciado depois\",\n      \"ENDED-BEFORE\":\"Finalizado antes\",\n      \"ENDED-AFTER\":\"Finalizado depois\",\n      \"VARIABLE\":\"Variável\",\n      \"VARIABLE-NAME\":\"Nome da variável\",\n      \"VARIABLE-VALUE\":\"Valor da variável\",\n      \"VARIABLE-BOOLEAN-VALUE\":\"Valor booleano: {{value}}\",\n      \"TENANT-ID\":\"Identificador do tenant\"\n    },\n    \"SORT\":{\n      \"ID\":\"ID\",\n      \"START-TIME\":\"Iniciado em\"\n    },\n    \"HEADER\":{\n      \"ID\":\"ID\",\n      \"NAME\":\"Nome\",\n      \"BUSINESS-KEY\":\"Chave do negócio\",\n      \"PROCESS-DEFINITION\":\"Definição de processo\",\n      \"CREATE-TIME\":\"Criado em\",\n      \"END-TIME\":\"Finalizado em\",\n      \"STATUS\":\"Status\"\n    }\n  },\n  \"TASK\":{\n    \"ID\":\"ID:\",\n    \"NAME\":\"Nome:\",\n    \"STATUS\":\"Status:\",\n    \"STATUS-COMPLETED\":\"Concluído\",\n    \"STATUS-ACTIVE\":\"Ativo\",\n    \"DESCRIPTION\":\"Descrição:\",\n    \"TASK-DEFINITION-KEY\":\"Chave da definição:\",\n    \"FORM-KEY\":\"Chave do formulário:\",\n    \"PRIORITY\":\"Prioridade:\",\n    \"DELEGATION-STATE\":\"Estado da atribuição:\",\n    \"CATEGORY\":\"Categoria:\",\n    \"TENANT-ID\":\"Tenant:\",\n    \"PARENT\":\"Tarefa pai:\",\n    \"ASSIGNEE\":\"Destinatário:\",\n    \"OWNER\":\"Proprietário:\",\n    \"START-DATE\":\"Data de início:\",\n    \"DUE-DATE\":\"Data de vencimento:\",\n    \"END-DATE\":\"Data de término:\",\n    \"DELETE-REASON\":\"Motivo de exclusão:\",\n    \"PROCESS-INSTANCE\":\"Instância de processo\",\n    \"PROCESS-DEFINITION\":\"Definição de processo\",\n    \"EXECUTION-ID\":\"ID de execução:\",\n    \"SUBTASKS-MESSAGE\":\"Esta tarefa tem {{total}} subtarefas, mostrando {{size}}.\",\n    \"SUBTASKS-MESSAGE-EMPTY\":\"Esta tarefa não tem subtarefas.\",\n    \"VARIABLES-MESSAGE\":\"Esta tarefa tem {{size}} variáveis.\",\n    \"VARIABLES-MESSAGE-EMPTY\":\"Esta tarefa não tem variáveis.\",\n    \"IDENTITY-LINKS-MESSAGE\":\"Esta tarefa tem {{size}} links de identidade.\",\n    \"IDENTITY-LINKS-MESSAGE-EMPTY\":\"Esta tarefa não tem links de identidade.\",\n    \"ACTION\":{\n      \"EDIT\":\"Editar Tarefa\",\n      \"ASSIGN-CLAIM\":\"Atribuir/Assumir tarefa\",\n      \"DELEGATE\":\"Delegar Tarefa\",\n      \"RESOLVE\":\"Resolver tarefa\",\n      \"COMPLETE\":\"Completar tarefa\",\n      \"DELETE\":\"Excluir tarefa\",\n      \"SHOW-ALL-SUBTASKS\":\"Mostrar todas as subtarefas\",\n      \"SHOW-SUBMITTED-FORM\":\"Mostrar formulário enviado\"\n    },\n    \"TITLE\":{\n      \"SUBTASKS\":\"Subtarefas\",\n      \"IDENTITY-LINKS\":\"Links de identidade\",\n      \"VARIABLES\":\"Variáveis\"\n    },\n    \"POPUP\":{\n      \"ASSIGN\":{\n        \"TITLE\":\"Atribuir tarefa\",\n        \"MESSAGE\":\"Tem certeza que deseja atribuir a tarefa?\",\n        \"NEW-ASSIGNEE\":\"Novo destinatário\",\n        \"NEW-ASSIGNEE-HELP\":\"Deixe o campo de destinatário vazio se você não quiser atribuir a tarefa a alguém.\",\n        \"CONFIRM\":\"Atribuir tarefa\"\n      },\n      \"COMPLETE\":{\n        \"TITLE\":\"Completar tarefa\",\n        \"MESSAGE\":\"Tem certeza que deseja completar a tarefa?\",\n        \"CONFIRM\":\"Completar tarefa\"\n      },\n      \"DELEGATE\":{\n        \"TITLE\":\"Delegar tarefa\",\n        \"MESSAGE\":\"Tem certeza que deseja delegar a tarefa?\",\n        \"CONFIRM\":\"Delegar tarefa\",\n        \"DELEGATE-TO\":\"Usuário ao qual delegar\"\n      },\n      \"RESOLVE\":{\n        \"TITLE\":\"Resolver a tarefa\",\n        \"MESSAGE\":\"Tem certeza de deseja resolver a tarefa?\",\n        \"CONFIRM\":\"Resolver tarefa\"\n      },\n      \"DELETE\":{\n        \"TITLE\":\"Excluir tarefa\",\n        \"MESSAGE\":\"Tem certeza que deseja excluir a tarefa?\",\n        \"CONFIRM\":\"Excluir tarefa\"\n      },\n      \"EDIT\":{\n        \"TITLE\":\"Editar tarefa\",\n        \"CONFIRM\":\"Atualizar tarefa\",\n        \"NAME\":\"Nome\",\n        \"DESCRIPTION\":\"Descrição\",\n        \"PRIORITY\":\"Prioridade\",\n        \"CATEGORY\":\"Categoria\",\n        \"ASSIGNEE\":\"Destinatário\",\n        \"OWNER\":\"Proprietário\",\n        \"DUE-DATE\":\"Data de vencimento\"\n      }\n    }\n  },\n  \"TASKS\":{\n    \"TITLE\":\"Tarefas\",\n    \"LIST-MESSAGE\":\"Mostrando {{size}} resultados, de um total de {{total}} tarefas correspondentes.\",\n    \"LIST-MESSAGE-EMPTY\":\"Nenhuma tarefa correspondente.\",\n    \"FILTER\":{\n      \"NAME\":\"Nome (com diferenciação entre maiúsculas e minúsculas)\",\n      \"ASSIGNEE\":\"Destinatário (com diferenciação entre maiúsculas e minúsculas)\",\n      \"STATUS\":\"Status\",\n      \"STATUS-ANY\":\"Qualquer status\",\n      \"STATUS-ACTIVE\":\"Tarefas ativas\",\n      \"STATUS-COMPLETE\":\"Tarefas concluídas\",\n      \"PROCESS-INSTANCE-ID\":\"ID da instância do processo\",\n      \"TENANT-ID\":\"Identificador do tenant\",\n      \"OWNER\":\"Proprietário (com diferenciação entre maiúsculas e minúsculas)\",\n      \"PARENT-TASK-ID\":\"ID da tarefa pai\",\n      \"CREATED-BEFORE\":\"Criado antes de\",\n      \"CREATED-AFTER\":\"Criado depois de\",\n      \"ENDED-BEFORE\":\"Finalizado antes de\",\n      \"ENDED-AFTER\":\"Finalizado depois de\",\n      \"DUE-BEFORE\":\"Vencido antes de\",\n      \"DUE-AFTER\":\"Vencido depois de\",\n      \"TASK-VARIABLE\":\"Variável local da tarefa\",\n      \"PROCESS-VARIABLE\":\"Variável do processo\",\n      \"VARIABLE-NAME\":\"Nome da variável\",\n      \"VARIABLE-VALUE\":\"Valor da variável\",\n      \"VARIABLE-BOOLEAN-VALUE\":\"Valor booleano: {{value}}\"\n    },\n    \"SORT\":{\n      \"NAME\":\"Nome\",\n      \"DUE-DATE\":\"Data de vencimento\",\n      \"START-TIME\":\"Iniciado em\",\n      \"END-TIME\":\"Finalizado em\",\n      \"PRIORITY\":\"Prioridade\"\n    },\n    \"HEADER\":{\n      \"ID\":\"ID\",\n      \"NAME\":\"Nome\",\n      \"ASSIGNEE\":\"Destinatário\",\n      \"OWNER\":\"Proprietário\",\n      \"CREATE-TIME\":\"Criado em\",\n      \"END-TIME\":\"Finalizado em\",\n      \"PRIORITY\":\"Prioridade\"\n    }\n  },\n  \"DEPLOYMENTS\":{\n    \"TITLE\":\"Implantações\",\n    \"LIST-MESSAGE\":\"Mostrando {{size}} resultados, de um total de {{total}} implantações correspondentes.\",\n    \"LIST-MESSAGE-EMPTY\":\"Nenhuma implantação correspondente.\",\n    \"FILTER\":{\n      \"NAME\":\"Nome (com diferenciação entre maiúsculas e minúsculas)\",\n      \"TENANTID\":\"Identificador de tenant (com diferenciação entre maiúsculas e minúsculas)\"\n    },\n    \"SORT\":{\n      \"ID\":\"ID\",\n      \"NAME\":\"Nome\"\n    },\n    \"HEADER\":{\n      \"ID\":\"ID\",\n      \"NAME\":\"Nome\",\n      \"DEPLOY-TIME\":\"Hora da implantação\",\n      \"CATEGORY\":\"Categoria\",\n      \"TENANT\":\"Tenant\"\n    },\n    \"ACTION\":{\n      \"UPLOAD\":\"Carregar processo ou pacote\",\n      \"DELETE\":\"Excluir implantação\"\n    },\n    \"POPUP\":{\n      \"UPLOAD\":{\n        \"DESCRIPTION\":\"Selecione um arquivo de processo .bpmn ou .bpmn20.xml para ser implantado ou carregue um pacote de processos (com ativos) contido em um arquivo .zip ou .bar.\",\n        \"DROPZONE\":\"Ou solte um arquivo aqui\",\n        \"NO-DROP\":\"Seu navegador não suporta a ação de Arrastar e soltar\",\n        \"CANCEL-UPLOAD\":\"Cancelar upload\",\n        \"ERROR\":\"Não foi possível carregar este arquivo\"\n      },\n      \"DELETE\":{\n        \"CONFIRM-MESSAGE\":\"Você está prestes a excluir a implantação '{{name}}'. Se houver instâncias de processo associadas a ela, ativas ou concluídas, elas também serão excluídas. Tem certeza de que deseja excluir a implantação '{{name}}'?\"\n      }\n    }\n  },\n  \"DEPLOYMENT\":{\n    \"ID\":\"ID:\",\n    \"NAME\":\"Nome:\",\n    \"TIME\":\"Hora da implantação:\",\n    \"CATEGORY\":\"Categoria:\",\n    \"TENANTID\":\"Identificador do tenant:\",\n    \"DEFINITIONS-MESSAGE\":\"Esta implantação tem {{total}} definições de processo, mostrando {{size}}.\",\n    \"DEFINITIONS-MESSAGE-EMPTY\":\"Essa implantação não tem definições de processo.\",\n    \"TITLE\":{\n      \"DEFINITIONS\":\"Definições de processo\",\n      \"RESOURCES\":\"Recursos\"\n    },\n    \"ACTION\":{\n      \"SHOW-ALL-DEFINITIONS\":\"Mostrar todas as definições\"\n    }\n  },\n  \"JOB\":{\n    \"TITLE\":{\n      \"MAIN\":\"Trabalho {{id}}\",\n      \"EXCEPTION\":\"Exceção\"\n    },\n    \"ACTIONS\":{\n      \"EXECUTE\":\"Executar trabalho\",\n      \"DELETE\":\"Excluir trabalho\"\n    },\n    \"POPUP\":{\n      \"DELETE-JOB\":{\n        \"TITLE\":\"Excluir o trabalho '{{id}}'\",\n        \"MESSAGE\":\"Tem certeza que deseja excluir o trabalho {{id}}?\",\n        \"CONFIRM\":\"Excluir trabalho\"\n      }\n    },\n    \"ID\":\"ID:\",\n    \"EXECUTION-ID\":\"ID de execução:\",\n    \"PROCESS-INSTANCE\":\"Instância do processo:\",\n    \"PROCESS-DEFINITION\":\"Definição do processo:\",\n    \"DUEDATE\":\"Data de vencimento:\",\n    \"RETRIES-LEFT\":\"Tentativas restantes:\",\n    \"TENANT-ID\":\"Tenant:\"\n  },\n  \"JOBS\":{\n    \"TITLE\":\"Trabalhos\",\n    \"LIST-MESSAGE\":\"Mostrando {{size}} resultados, de um total de {{total}} trabalhos correspondentes.\",\n    \"LIST-MESSAGE-EMPTY\":\"Nenhum trabalho correspondente.\",\n    \"FILTER\":{\n      \"PROCESS-DEFINITION\":\"Definição de processo\",\n      \"ALL-PROCESS-DEFINITIONS\":\"Todas as definições de processo\",\n      \"PROCESS-INSTANCE-ID\":\"ID da instância do processo\",\n      \"TENANT-ID\":\"Identificador do tenant\",\n      \"DUE-BEFORE\":\"Vencimento antes de\",\n      \"DUE-AFTER\":\"Vencimento depois de\",\n      \"EXCEPTION\":\"Exceção\",\n      \"EXCEPTION-HELP\":\"Mostrar apenas trabalhos com uma exceção\"\n    },\n    \"SORT\":{\n      \"ID\":\"ID do Trabalho\",\n      \"DUE-DATE\":\"Data de vencimento\",\n      \"PROCESS-INSTANCE-ID\":\"ID da instância do processo\"\n    },\n    \"HEADER\":{\n      \"ID\":\"ID\",\n      \"DUE-DATE\":\"Data de vencimento\",\n      \"PROCESS-DEFINITION\":\"Definição de processo\",\n      \"RETRIES\":\"Novas tentativas\",\n      \"EXCEPTION\":\"Exceção\"\n    }\n  },\n  \"EVENT-SUBSCRIPTION\":{\n    \"TITLE\":{\n      \"MAIN\":\"Assinatura de evento {{id}}\"\n    },\n    \"ACTIONS\":{\n      \"TRIGGER\":\"Evento de gatilho\"\n    },\n    \"ID\":\"ID:\",\n    \"ACTIVITY-ID\":\"ID da atividade:\",\n    \"EXECUTION-ID\":\"ID da execução:\",\n    \"PROCESS-INSTANCE\":\"Instância do processo:\",\n    \"PROCESS-DEFINITION\":\"Definição do processo:\",\n    \"CREATE-DATE\":\"Criado em:\",\n    \"EVENT-TYPE\":\"Tipo do evento:\",\n    \"EVENT-NAME\":\"Nome do evento:\",\n    \"TENANT-ID\":\"Tenant:\"\n  },\n  \"EVENT-SUBSCRIPTIONS\":{\n    \"TITLE\":\"Inscrições de eventos\",\n    \"LIST-MESSAGE\":\"Mostrando {{size}} resultados, de um total de {{total}} inscricões de eventos correspondentes.\",\n    \"LIST-MESSAGE-EMPTY\":\"Não há inscrições de evento correspondente.\",\n    \"FILTER\":{\n      \"PROCESS-DEFINITION\":\"Definição de processo\",\n      \"ALL-PROCESS-DEFINITIONS\":\"Todas as definições de processo\",\n      \"PROCESS-INSTANCE-ID\":\"ID da instância do processo\",\n      \"TENANT-ID\":\"Identificador do tenant\",\n      \"CREATED-BEFORE\":\"Criado antes\",\n      \"CREATED-AFTER\":\"Criado depois\"\n    },\n    \"SORT\":{\n      \"ID\":\"ID da inscrição do evento\",\n      \"CREATE-DATE\":\"Criado em\",\n      \"PROCESS-INSTANCE-ID\":\"ID da instância do processo\"\n    },\n    \"HEADER\":{\n      \"ID\":\"ID\",\n      \"CREATE-DATE\":\"Criado em\",\n      \"PROCESS-DEFINITION\":\"Definição do processo\",\n      \"EVENT-TYPE\":\"Tipo de evento\",\n      \"EVENT-NAME\":\"Nome do evento\"\n    }\n  },\n  \"LOGIN\":{\n    \"TITLE\":\"Entrar\",\n    \"USERNAME\":\"Nome de Usuário\",\n    \"USERNAME-PLACEHOLDER\":\"Digite seu nome de usuário\",\n    \"PASSWORD\":\"Senha\",\n    \"PASSWORD-PLACEHOLDER\":\"Digite sua senha\",\n    \"ACTION\":{\n      \"CONFIRM\":\"Entrar\"\n    }\n  },\n  \"USER\":{\n    \"POPUP\":{\n      \"CHANGE-PASSWORD\":{\n        \"TITLE\":\"Alterar a senha para '{{login}}'\",\n        \"OLD-PASSWORD\":\"Senha Antiga\",\n        \"NEW-PASSWORD\":\"Nova Senha\",\n        \"CONFIRM\":\"Alterar a senha\"\n      },\n      \"DELETE\":{\n        \"TITLE\":\"Excluir o usuário {{login}}\",\n        \"MESSAGE\":\"Tem certeza que deseja excluir usuário '{{login}}'?\",\n        \"CONFIRM\":\"Excluir usuário\"\n      },\n      \"EDIT\":{\n        \"TITLE\":\"Editar usuário {{login}}\",\n        \"LOGIN\":\"Login\",\n        \"EMAIL\":\"Email\",\n        \"FIRSTNAME\":\"Primeiro Nome\",\n        \"LASTNAME\":\"Último Nome\",\n        \"CONFIRM\":\"Atualizar usuário\"\n      },\n      \"NEW\":{\n        \"TITLE\":\"Criar novo usuário\",\n        \"LOGIN\":\"Login\",\n        \"EMAIL\":\"Email\",\n        \"FIRSTNAME\":\"Primeiro Nome\",\n        \"LASTNAME\":\"Último nome\",\n        \"PASSWORD\":\"Senha\",\n        \"ADMIN\":\"Tem direitos de administrador\",\n        \"CONFIRM\":\"Criar usuário\"\n      }\n    }\n  },\n  \"USERS\":{\n    \"TITLE\":\"Usuários\",\n    \"ACTION\":{\n      \"EDIT\":\"Editar usuário\",\n      \"NEW\":\"Criar novo usuário\",\n      \"DELETE\":\"Excluir usuário\",\n      \"CHANGE-PASSWORD\":\"Alterar a senha\"\n    },\n    \"HEADER\":{\n      \"LOGIN\":\"Login\",\n      \"FIRSTNAME\":\"Primeiro Nome\",\n      \"LASTNAME\":\"Último nome\",\n      \"EMAIL\":\"Email\",\n      \"CLUSTER_USER\":\"Usuário do cluster\"\n    }\n  },\n  \"LICENSE\":{\n    \"POPUP\":{\n      \"TITLE\":\"Informações de licença\",\n      \"HOLDER\":\"Titular\",\n      \"SUBJECT\":\"Assunto\",\n      \"PRODUCTKEY\":\"Tipo do produto\",\n      \"GOODAFTERDATE\":\"Licença válida após\",\n      \"GOODBEFOREDATE\":\"Licença válida até\",\n      \"NUMBER_OF_PROCESSES\":\"Número de processos ativos\",\n      \"NUMBER_OF_ADMINS\":\"Número de usuários administradores\",\n      \"MULTI_TENANT\":\"Multi tenant\",\n      \"DEFAULT_TENANT\":\"Tenant principal\"\n    }\n  },\n  \"CLUSTER\":{\n    \"NAME\":\"Nome:\",\n    \"USER\":\"Usuário:\",\n    \"MASTER-MANDATORY\":\"Configuração-mestre obrigatória:\",\n    \"METRICS-SEND-INTERVAL\":\"Intervalo de envio de métrica:\",\n    \"ENDPOINT-HELP\":\"A configuração de endpoint (cada cluster tem apenas um) precisa apontar para uma instalação REST Flowable. Este endpoint será então usado para recuperar e gerenciar os dados usados nas outras seções (por exemplo, implantações, definições de processos e assim por diante) desta aplicação.\",\n    \"ENDPOINT-NAME\":\"Nome:\",\n    \"ENDPOINT-DESCRIPTION\":\"Descrição:\",\n    \"ENDPOINT-ADDRESS\":\"Endereço do servidor:\",\n    \"ENDPOINT-PORT\":\"Porta do servidor:\",\n    \"ENDPOINT-CONTEXT-ROOT\":\"Contexto base:\",\n    \"ENDPOINT-REST-ROOT\":\"Raiz do REST:\",\n    \"ENDPOINT-USERNAME\":\"Nome de Usuário:\",\n    \"PROCESS-ENGINE-HELP\":\"Esta seção permite que você defina uma 'configuração mestre' para o cluster. Todas as instâncias do cluster usarão esta configuração quando inicializar (se o jar de configuração de cluster estiver no classpath ou se as propriedades correspondentes estiverem devidamente preenchidas). Se não definido, as instâncias usará seus arquivos de configuração locais.\",\n    \"NO-MASTER-DEFINED\":\"Nenhuma configuração mestre definida\",\n    \"ACTION\":{\n      \"SHOW-PASSWORD\":\"Mostrar Senha\",\n      \"EDIT-CLUSTER-CONFIG\":\"Editar configuração do cluster\",\n      \"CREATE-CLUSTER-CONFIG\":\"Criar novo cluster\",\n      \"DELETE-CLUSTER-CONFIG\":\"Excluir configuração do cluster\",\n      \"GENERATE-JAR\":\"Gerar o jar de configuração do cluster\",\n      \"EDIT-ENDPOINT\":\"Editar endpoint REST\",\n      \"CHECK-ENDPOINT\":\"Verificar endpoint REST\",\n      \"SELECT-MASTER\":\"Selecione a configuração-mestre\",\n      \"ADD-CONFIGURATION\":\"Adicionar configuração-mestre\",\n      \"EDIT-CONFIGURATION\":\"Editar a configuração-mestre\",\n      \"DELETE-CONFIGURATION\":\"Excluir a configuração-mestre\"\n    },\n    \"TITLE\":{\n      \"PROCESS-ENDPOINT\":\"Configuração da API do endpoint do processo\",\n      \"DMN-ENDPOINT\":\"Configuração do endpoint para a API DMN\",\n      \"FORM-ENDPOINT\":\"Configuração do endpoint para a API de formulários\",\n      \"CONTENT-ENDPOINT\":\"Configuração do endpoint da API de conteúdo\"\n    },\n    \"POPUP\":{\n      \"EDIT-ENDPOINT\":{\n        \"ENDPOINT-NAME\":\"Nome\",\n        \"ENDPOINT-DESCRIPTION\":\"Descrição\",\n        \"ENDPOINT-ADDRESS\":\"Endereço do servidor\",\n        \"ENDPOINT-PORT\":\"Porta do servidor\",\n        \"ENDPOINT-CONTEXT-ROOT\":\"Contexto base\",\n        \"ENDPOINT-REST-ROOT\":\"Contexto raiz do REST\",\n        \"ENDPOINT-USERNAME\":\"Nome de Usuário\",\n        \"ENDPOINT-PASSWORD\":\"Senha\",\n        \"ENDPOINT-PASSWORD-HELP\":\"Deixe em branco para manter a senha atual\",\n        \"ENDPOINT-URL-PREVIEW\":\"URL de Visualização\",\n        \"ACTION-CONFIRM\":\"Salvar configuração do endpoint\",\n        \"ERROR-401\":\"Erro: credenciais inválidas\",\n        \"ERROR-403\":\"Erro: credenciais ou URL inválidas\",\n        \"ERROR-404\":\"Erro: URL não encontrada\",\n        \"ERROR-500\":\"Erro: erro de servidor. Verifique os logs do servidor.\"\n      }\n    }\n  },\n  \"APP-DEPLOYMENTS\":{\n    \"TITLE\":\"Implantações de Aplicativo\",\n    \"LIST-MESSAGE\":\"Mostrando {{size}} resultados, de um total de {{total}} implantações de aplicativos correspondentes.\",\n    \"LIST-MESSAGE-EMPTY\":\"Nenhuma implantação de aplicativo correspondente.\",\n    \"FILTER\":{\n      \"NAME\":\"Nome\",\n      \"TENANTID\":\"Identificador do tenant\",\n      \"LATEST\":\"Última versão\",\n      \"LATEST-HELP\":\"Mostrar apenas as versões mais recentes\"\n    },\n    \"SORT\":{\n      \"ID\":\"ID\",\n      \"NAME\":\"Nome\"\n    },\n    \"HEADER\":{\n      \"ID\":\"ID\",\n      \"APP-DEFINITION-ID\":\"ID do App\",\n      \"DEPLOYMENT-ID\":\"ID do processo de implantação\",\n      \"DMN-DEPLOYMENT-ID\":\"ID da implantação DMN\",\n      \"NAME\":\"Nome\",\n      \"DEPLOY-TIME\":\"Hora da implantação\",\n      \"DEPLOYED-BY\":\"Implantado por\",\n      \"TENANT\":\"ID do Tenant\"\n    },\n    \"ACTION\":{\n      \"UPLOAD\":\"Carregar e publicar um aplicativo\"\n    },\n    \"POPUP\":{\n      \"UPLOAD\":{\n        \"DESCRIPTION\":\"Selecione uma definição de aplicativo .zip para implantar.\",\n        \"WARNING\":\"Carregar um processo só é possível através de uma instância Flowable.\",\n        \"DROPZONE\":\"Ou solte um arquivo aqui\",\n        \"NO-DROP\":\"Arrastar e soltar arquivo não é suportado pelo seu navegador\",\n        \"CANCEL-UPLOAD\":\"Cancelar carregamento\",\n        \"ERROR\":\"Não foi possível carregar este arquivo\"\n      }\n    }\n  },\n  \"VARIABLES\":{\n    \"HEADER\":{\n      \"NAME\":\"Nome\",\n      \"TYPE\":\"Tipo\",\n      \"VALUE\":\"Valor\"\n    }\n  },\n  \"IDENTITY-LINKS\":{\n    \"HEADER\":{\n      \"GROUP-ID\":\"Id do Grupo\",\n      \"TYPE\":\"Tipo\",\n      \"USER-ID\":\"ID do Usuário\"\n    }\n  },\n  \"ALERT\":{\n    \"GENERAL\":{\n      \"HTTP-ERROR\":\"Não conseguimos obter os dados do servidor\",\n      \"AUTHENTICATION-ERROR\":\"Você inseriu as credenciais de login inválidas\"\n    },\n    \"ENGINE\":{\n      \"ENDPOINT-UPDATED\":\"Endpoint '{{name}}' atualizado.\",\n      \"ENDPOINT-INVALID\":\"A configuração do endpoint para '{{name}}' esta inválida.\",\n      \"ENDPOINT-VALID\":\"Endpoint válido, Motor no endpoint: {{name}} - {{version}}\"\n    },\n    \"JOB\":{\n      \"DELETED\":\"Trabalho '{{id}}' excluído com sucesso.\",\n      \"EXECUTED\":\"Trabalho '{{id}}' foi executado com êxito.\"\n    },\n    \"EVENT-SUBSCRIPTION\":{\n      \"TRIGGERED\":\"Inscrição de evento '{{id}}' disparado com êxito.\"\n    },\n    \"PROCESS-INSTANCE\":{\n      \"DELETED\":\"Instância do processo '{{id}}' excluído com sucesso.\",\n      \"TERMINATED\":\"Instância do processo '{{id}}' finalizada com sucesso.\"\n    },\n    \"TASK\":{\n      \"DELETED\":\"Tarefa '{{id}}' excluída com sucesso.\",\n      \"COMPLETED\":\"Tarefa '{{id}}' foi concluída com êxito.\",\n      \"DELEGATED\":\"Tarefa '{{id}}' delegada ao usuário {{user}}.\",\n      \"RESOLVED\":\"Tarefa '{{id}}' resolvida com êxito.\",\n      \"ASSIGNED\":\"Tarefa '{{id}}' agora esta atribuída a {{user}}.\",\n      \"UNASSIGNED\":\"Tarefa '{{id}}' não esta atribuída.\",\n      \"UPDATED\":\"Tarefa '{{id}}' atualizada com êxito.\"\n    },\n    \"USER\":{\n      \"DELETED\":\"Usuário '{{login}}' foi excluído com sucesso.\",\n      \"UPDATED\":\"Usuário '{{login}}' foi atualizado com êxito.\",\n      \"CREATED\":\"Usuário '{{login}}' criado.\",\n      \"PASSWORD-CHANGED\":\"Senha para '{{login}}' foi alterada com êxito.\"\n    },\n    \"PROCESS-DEFINITION\":{\n      \"CATEGORY-UPDATED\":\"Categoria de definição de processo atualizada\"\n    },\n    \"DEPLOYMENT\":{\n      \"DELETED-DEPLOYMENT\":\"Excluir a implantação '{{name}}'\",\n      \"DELETE-ERROR\":\"Não foi possível excluir a implantação. {{exception || ''}}\",\n      \"DEPLOYMENT-SUCCESS\":\"Implantação bem sucedida\"\n    },\n    \"APP-DEPLOYMENT\":{\n      \"DELETED-APP\":\"App excluído '{{appDefinition.name}}'\",\n      \"DELETE-ERROR\":\"Não foi possível excluir o app {{message || ''}}\"\n    }\n  },\n  \"DECISION-TABLE-DEPLOYMENTS\":{\n    \"TITLE\":\"Implantações de Tabela de Decisão\",\n    \"LIST-MESSAGE\":\"Mostrando {{size}} resultados, de um total de {{total}} implantações correspondentes.\",\n    \"LIST-MESSAGE-EMPTY\":\"Nenhuma implantação correspondente.\",\n    \"FILTER\":{\n      \"NAME\":\"Nome (com diferenciação entre maiúsculas e minúsculas)\",\n      \"TENANTID\":\"Identificador de tenant (com diferenciação entre maiúsculas e minúsculas)\"\n    },\n    \"SORT\":{\n      \"ID\":\"ID\",\n      \"NAME\":\"Nome\"\n    },\n    \"HEADER\":{\n      \"ID\":\"ID\",\n      \"NAME\":\"Nome\",\n      \"DEPLOY-TIME\":\"Hora da implantação\",\n      \"CATEGORY\":\"Categoria\",\n      \"TENANT\":\"Tenant\"\n    },\n    \"ACTION\":{\n      \"DELETE\":\"Excluir a implantação\"\n    }\n  },\n  \"DECISION-TABLE-DEPLOYMENT\":{\n    \"ID\":\"ID:\",\n    \"NAME\":\"Nome:\",\n    \"TIME\":\"Data de implantação:\",\n    \"CATEGORY\":\"Categoria:\",\n    \"TENANTID\":\"Identificador do tenant:\",\n    \"DECISION-TABLES-MESSAGE\":\"Esta implantação tem {{total}} tabelas de decisão, mostrando {{size}}.\",\n    \"DECISION-TABLES-MESSAGE-EMPTY\":\"Essa implantação não tem tabelas de decisão.\",\n    \"PARENT-DEPLOYMENT-ID\":\"ID de implantação do pai\",\n    \"TITLE\":{\n      \"DECISION-TABLES\":\"Tabelas de Decisão\",\n      \"RESOURCES\":\"Recursos\"\n    },\n    \"ACTION\":{\n      \"SHOW-ALL-DEFINITIONS\":\"Mostrar todas as tabelas de decisão\"\n    }\n  },\n  \"DECISION-TABLES\":{\n    \"TITLE\":\"Tabelas de decisão\",\n    \"LIST-MESSAGE\":\"Mostrando {{size}} resultados, de um total de {{total}} tabelas de decisão correspondentes.\",\n    \"LIST-MESSAGE-EMPTY\":\"Nenhuma tabela de decisão correspondente.\",\n    \"FILTER\":{\n      \"NAME\":\"Nome\",\n      \"KEY\":\"Chave\",\n      \"TENANTID\":\"Identificador do tenant\"\n    },\n    \"SORT\":{\n      \"ID\":\"ID\",\n      \"NAME\":\"Nome\"\n    },\n    \"HEADER\":{\n      \"ID\":\"ID\",\n      \"NAME\":\"Nome\",\n      \"VERSION\":\"Versão\",\n      \"KEY\":\"Chave\",\n      \"DEPLOY-TIME\":\"Hora da implantação\",\n      \"TENANT-ID\":\"ID do Tenant\"\n    }\n  },\n  \"DECISION-TABLE\":{\n    \"ID\":\"ID:\",\n    \"NAME\":\"Nome:\",\n    \"VERSION\":\"Versão:\",\n    \"KEY\":\"Chave:\",\n    \"DEPLOYMENT-ID\":\"ID de implantação:\",\n    \"PARENT-DEPLOYMENT-ID\":\"ID de implantação do pai\",\n    \"RESOURCE-NAME\":\"Nome do recurso:\",\n    \"DESCRIPTION\":\"Descrição:\",\n    \"TENANT\":\"Tenant:\",\n    \"TITLE\":{\n      \"DECISION-AUDITS\":\"Auditorias de decisão\"\n    },\n    \"DECISION-AUDITS-MESSAGE\":\"Esta tabela de decisão tem {{total}} auditorias, mostrando {{size}}.\",\n    \"DECISION-AUDITS-MESSAGE-EMPTY\":\"Esta tabela de decisão não tem auditorias\",\n    \"ACTION\":{\n      \"EDIT-CATEGORY\":\"Editar Categoria\",\n      \"SHOW-ALL-JOBS\":\"Mostrar todos os trabalhos\",\n      \"SHOW-ALL-PROCESSES\":\"Mostrar todos os processos\",\n      \"SHOW-DIAGRAM\":\"Mostrar diagrama de processo\",\n      \"SHOW-DECISION-TABLE\":\"Mostrar tabela de decisão\"\n    },\n    \"POPUP\":{\n      \"TITLE\":\"Tabelas de Decisão: \",\n      \"KEY\":\"Chave: \",\n      \"HIT-POLICY\":\"Acertar política: \",\n      \"HIT-POLICIES\":{\n        \"FIRST\":\"Primeiro (passagem única)\",\n        \"ANY\":\"Qualquer (passagem única)\"\n      }\n    }\n  },\n  \"FORM-DEFINITIONS\":{\n    \"TITLE\":\"Definições de formulários\",\n    \"LIST-MESSAGE\":\"Mostrando {{size}} resultados, de um total de {{total}} formulários correspondentes.\",\n    \"LIST-MESSAGE-EMPTY\":\"Não há definições de formulários.\",\n    \"HEADER\":{\n      \"ID\":\"ID\",\n      \"NAME\":\"Nome\",\n      \"DEPLOYMENTID\":\"ID de implantação\",\n      \"TENANTID\":\"ID do Tenant\",\n      \"KEY\":\"Chave\",\n      \"VERSION\":\"Versão\"\n    },\n    \"FILTER\":{\n      \"NAME\":\"Nome\",\n      \"APPID\":\"ID da implantação do Aplicativo\",\n      \"TENANTID\":\"Identificador do tenant\"\n    },\n    \"SORT\":{\n      \"ID\":\"ID\",\n      \"NAME\":\"Nome\"\n    }\n  },\n  \"FORM-DEFINITION\":{\n    \"ID\":\"ID:\",\n    \"NAME\":\"Nome:\",\n    \"PARENT-DEPLOYMENT-ID\":\"ID de implantação do pai:\",\n    \"DEPLOYMENT-ID\":\"ID de implantação:\",\n    \"DESCRIPTION\":\"Descrição:\",\n    \"TENANT\":\"Tenant:\",\n    \"MESSAGE-EMPTY\":\"(Nenhum)\",\n    \"TITLE\":{\n      \"FORM-INSTANCES\":\"Instâncias do formulário\"\n    },\n    \"FORM-INSTANCES-MESSAGE\":\"Esta definição tem {{total}} instâncias de formulários, mostrando {{size}}.\",\n    \"FORM-INSTANCES-MESSAGE-EMPTY\":\"Esta definição não tem instâncias de formulários\",\n    \"ACTION\":{\n      \"EDIT-CATEGORY\":\"Editar Categoria\",\n      \"SHOW-ALL-JOBS\":\"Mostrar todos os trabalhos\",\n      \"SHOW-ALL-PROCESSES\":\"Mostrar todos os processos\",\n      \"SHOW-DIAGRAM\":\"Mostrar diagrama de processo\",\n      \"SHOW-FORM\":\"Mostrar formulário\"\n    },\n    \"POPUP\":{\n      \"TITLE\":\"Formulário: \"\n    },\n    \"FIELD-PREVIEW\":{\n      \"DISPLAY-REF\":\"Exibir valor\",\n      \"SELECT-FIELD\":\"(Nenhum campo selecionado)\",\n      \"FIELD-VALUE\":\"Mostrar o valor do campo \\\"{{name}}\\\"\",\n      \"UNKNOWN-TYPE\":\"Tipo de campo desconhecido {{type}}\",\n      \"TEXT-VALUE\":\"Texto\",\n      \"MULTI-TEXT-VALUE\":\"Caixa de Texto Multi-Linha\",\n      \"NUMBER-VALUE\":\"123\",\n      \"DATE-VALUE\":\"Data\",\n      \"DROPDOWN-VALUE\":\"Selecione ...\",\n      \"UPLOAD-VALUE\":\"Carregar ou importar conteúdo...\",\n      \"RADIOS-OPTION1\":\"Opção 1\",\n      \"SELECT-PERSON\":\"Selecione uma pessoa\",\n      \"SELECT-GROUP\":\"Selecione um grupo\"\n    }\n  },\n  \"FORM-DEPLOYMENTS\":{\n    \"TITLE\":\"Implantações de formulário\",\n    \"LIST-MESSAGE\":\"Mostrando {{size}} resultados, de um total de {{total}} implantações de formulários correspondentes.\",\n    \"LIST-MESSAGE-EMPTY\":\"Nenhuma implantação de formulário correspondente.\",\n    \"FILTER\":{\n      \"NAME\":\"Nome (com diferenciação entre maiúsculas e minúsculas)\",\n      \"TENANTID\":\"Identificador de tenant (com diferenciação entre maiúsculas e minúsculas)\"\n    },\n    \"SORT\":{\n      \"ID\":\"ID\",\n      \"NAME\":\"Nome\"\n    },\n    \"HEADER\":{\n      \"ID\":\"ID\",\n      \"NAME\":\"Nome\",\n      \"DEPLOY-TIME\":\"Hora da implantação\",\n      \"CATEGORY\":\"Categoria\",\n      \"TENANT\":\"Tenant\"\n    },\n    \"ACTION\":{\n      \"DELETE\":\"Excluir a implantação\"\n    }\n  },\n  \"FORM-DEPLOYMENT\":{\n    \"ID\":\"ID:\",\n    \"NAME\":\"Nome:\",\n    \"TIME\":\"Data de implantação:\",\n    \"CATEGORY\":\"Categoria:\",\n    \"TENANTID\":\"Identificador do tenant:\",\n    \"PARENT-DEPLOYMENT-ID\":\"ID de implantação do pai\",\n    \"DEFINITIONS-MESSAGE\":\"Esta implantação tem {{total}} definições de formulários. Mostrando {{size}}.\",\n    \"DEFINITIONS-MESSAGE-EMPTY\":\"Essa implantação não tem nenhuma definição de formulário.\",\n    \"TITLE\":{\n      \"FORM-DEFINITIONS\":\"Definições de formulários\",\n      \"RESOURCES\":\"Recursos\"\n    },\n    \"ACTION\":{\n      \"SHOW-ALL-DEFINITIONS\":\"Mostrar todas as definições de formulários\"\n    }\n  },\n  \"FORM-INSTANCES\":{\n    \"TITLE\":\"Instâncias do formulário\",\n    \"LIST-MESSAGE\":\"Mostrando {{size}} resultados, de um total de {{total}} instâncias de formulários correspondentes.\",\n    \"LIST-MESSAGE-EMPTY\":\"Não há instâncias de formulário correspondente.\",\n    \"HEADER\":{\n      \"ID\":\"ID\",\n      \"PROCESS-INSTANCE-ID\":\"ID da instância de processo\",\n      \"TASK-ID\":\"ID da tarefa\",\n      \"SUBMITTED-ON\":\"Data de Submissão\\t\\t\",\n      \"SUBMITTED-BY\":\"Enviado por\",\n      \"TENANT-ID\":\"ID do Tenant\"\n    },\n    \"FILTER\":{\n      \"NAME\":\"Nome\",\n      \"TENANTID\":\"Identificador do tenant\"\n    },\n    \"SORT\":{\n      \"SUBMITTED-DATE\":\"Submetido em\"\n    }\n  },\n  \"FORM-INSTANCE\":{\n    \"HEADER\":{\n      \"ID\":\"ID\",\n      \"TASK-ID\":\"ID da tarefa\",\n      \"PROCESS-ID\":\"ID da instância de processo\",\n      \"SUBMITTED\":\"Submetido em\",\n      \"SUBMITTED-BY\":\"Submetido por\",\n      \"FORM-DEFINITION-ID\":\"ID da definição do formulário\"\n    },\n    \"FORM-FIELD-VALUES-MESSAGE\":\"Esta definição tem {{total}} valores de campos de formulários, mostrando {{size}}\",\n    \"FORM-FIELD-VALUES-MESSAGE-EMPTY\":\"Esta instância não tem valores de campo de formulário\",\n    \"ACTION\":{\n      \"SHOW-FORM-INSTANCE\":\"Visualizar instância de formulário\"\n    },\n    \"TITLE\":{\n      \"FORM-FIELD-VALUES\":\"Valores de campo de formulário\"\n    },\n    \"FORM-FIELD-VALUES\":{\n      \"ID\":\"ID do campo de formulário\",\n      \"NAME\":\"Nome do campo de formulário\",\n      \"TYPE\":\"Tipo de campo de formulário\",\n      \"VALUE\":\"Valores de campo de formulário\"\n    }\n  },\n  \"CONTENT-ITEMS\":{\n    \"TITLE\":\"Itens de conteúdo\",\n    \"LIST-MESSAGE\":\"Mostrando {{size}} resultados, de um total de {{total}} itens de conteúdo correspondente.\",\n    \"LIST-MESSAGE-EMPTY\":\"Não há itens de conteúdo correspondente.\",\n    \"HEADER\":{\n      \"ID\":\"ID\",\n      \"NAME\":\"Nome\",\n      \"PROCESS-INSTANCE-ID\":\"ID da instância de processo\",\n      \"TASK-ID\":\"ID da tarefa\",\n      \"LAST-MODIFIED-ON\":\"Data da última modificação\",\n      \"LAST-MODIFIED-BY\":\"Modificado pela última vez por\",\n      \"TENANT-ID\":\"ID do Tenant\"\n    },\n    \"FILTER\":{\n      \"NAME\":\"Nome\",\n      \"TENANTID\":\"Identificador do tenant\"\n    },\n    \"SORT\":{\n      \"CREATED\":\"Criado em\"\n    }\n  },\n  \"CONTENT-ITEM\":{\n    \"HEADER\":{\n      \"ID\":\"ID\",\n      \"TASK-ID\":\"ID da tarefa\",\n      \"PROCESS-INSTANCE-ID\":\"ID da instância de processo\",\n      \"CREATED-ON\":\"Criado em\",\n      \"CREATED-BY\":\"Criado por\",\n      \"LAST-MODIFIED-ON\":\"Data da última modificação\",\n      \"LAST-MODIFIED-BY\":\"Última Modificação Por\",\n      \"CONTENT-STORE-ID\":\"ID de armazenamento de conteúdo\"\n    },\n    \"ACTION\":{\n      \"SHOW-CONTENT-ITEM\":\"Mostrar ítem de conteúdo\"\n    }\n  }\n}\n"
  },
  {
    "path": "flowable-ui-web/admin/i18n/zh-CN.json",
    "content": "{\n    \"GENERAL\": {\n        \"YES\": \"是\",\n        \"NO\": \"否\",\n        \"ACTION\": {\n            \"LOGOUT\": \"退出\",\n            \"DISMISS-ALERT\": \"单击此处可删除此消息\",\n            \"RETURN-TO-LIST\": \"返回列表\",\n            \"SHOW-RESULTS\": \"显示{{size}}结果集\",\n            \"REFRESH-LIST\": \"刷新列表\",\n            \"SORT-BY\": \"根据{{sort}}排序\",\n            \"CLEAR-FILTERS\": \"清除过滤器\",\n            \"CANCEL-AND-CLOSE\": \"取消并且关闭\",\n            \"CANCEL\": \"取消\",\n            \"NEXT\": \"下一页\",\n            \"PREVIOUS\": \"上一页\",\n            \"CLOSE\": \"关闭\",\n            \"SHOWLICENSE\": \"许可证信息\"\n        },\n        \"TITLE\": {\n            \"MAIN\": \"flowable管理员\",\n            \"ACTIONS\": \"动作\",\n            \"FILTERS\": \"过滤器\"\n        },\n        \"MENU\": {\n            \"PROCESS-ENGINE\": \"流程引擎\",\n            \"CMMN-ENGINE\": \"CMMN引擎\",\n            \"APP-ENGINE\": \"App引擎\",\n            \"FORM-ENGINE\": \"表单引擎\",\n            \"CONTENT-ENGINE\": \"Content引擎\",\n            \"DMN-ENGINE\": \"DMN引擎\",\n            \"DEPLOYMENTS\": \"部署对象\",\n            \"DEFINITIONS\": \"定义\",\n            \"INSTANCES\": \"实例\",\n            \"TASKS\": \"任务\",\n            \"JOBS\": \"Jobs\",\n            \"EVENT-SUBSCRIPTIONS\": \"事件订阅\",\n            \"CONFIGURATION\": \"配置\",\n            \"CONFIGURATION-ENGINE\": \"引擎\",\n            \"DECISION-TABLES\": \"决策表\",\n            \"DECISION-TABLE-EXECUTIONS\": \"执行实例\",\n            \"CONTENT-ITEMS\": \"Content主题\"\n        },\n        \"RESULT-SIZES\": {\n            \"10\": \"10\",\n            \"25\": \"25\",\n            \"50\": \"50\",\n            \"100\": \"100\",\n            \"100000000\": \"all\"\n        }\n    },\n    \"PROCESS-DEFINITION\": {\n        \"ID\": \"ID:\",\n        \"NAME\": \"名称:\",\n        \"VERSION\": \"版本:\",\n        \"DESCRIPTION\": \"描述:\",\n        \"KEY\": \"Key:\",\n        \"CATEGORY\": \"分类:\",\n        \"SUSPENDED\": \"挂起:\",\n        \"DEPLOYMENT\": \"部署:\",\n        \"TENANT\": \"租户:\",\n        \"START-FORM-DEFINED\": \"开始表单定义:\",\n        \"GRAPHICAL-NOTATION-DEFINED\": \"图形符号定义:\",\n        \"PROCESS-INSTANCES-SIZE\": \"定义有 {{total}}个流程实例正在运行\",\n        \"PROCESS-INSTANCES-SHOWING\": \", 显示 {{size}}个最近启动的\",\n        \"PROCESS-INSTANCES-EMPTY\": \"定义中没有运行的流程实例\",\n        \"JOBS-SIZE\": \"定义有{{total}}个jobs正在运行\",\n        \"JOBS-EMPTY\": \"定义中没有运行的jobs\",\n        \"DECISION-TABLES-SIZE\": \"定义有 {{total}}个决策表.\",\n        \"DECISION-TABLES-EMPTY\": \"定义中没有决策表.\",\n        \"FORM-DEFINITIONS-SIZE\": \"定义有 {{total}}个表单定义.\",\n        \"FORM-DEFINITIONS-EMPTY\": \"定义中没有表单定义.\",\n        \"TITLE\": {\n            \"PROCESS-INSTANCES\": \"流程实例\",\n            \"JOBS\": \"Jobs\",\n            \"DECISION-TABLES\": \"决策表\",\n            \"FORMS\": \"表单定义\"\n        },\n        \"ACTION\": {\n            \"EDIT-CATEGORY\": \"编辑分类\",\n            \"SHOW-ALL-JOBS\": \"显示所有的jobs\",\n            \"SHOW-ALL-PROCESSES\": \"显示所有的历程\",\n            \"SHOW-DIAGRAM\": \"显示流程图片\"\n        },\n        \"POPUP\": {\n            \"EDIT-CATEGORY\": {\n                \"TITLE\": \"定义编辑分类\",\n                \"MESSAGE\": \"从BPMN 2 XM中的目标命名空间属性填充定义的初始分类, 但部署后可以更改。\",\n                \"CATEGORY\": \"分类\",\n                \"CATEGORY-PLACEHOLDER\": \"输入一个分类\",\n                \"CONFIRM\": \"更新分类\"\n            },\n            \"SHOW-PROCESS-MODEL\": {\n                \"TITLE\": \"流程图片\"\n            }\n        }\n    },\n    \"PROCESS-DEFINITIONS\": {\n        \"LIST-MESSAGE\": \"显示{{size}}个结果, 匹配到的定义总数{{total}}\",\n        \"LIST-MESSAGE-EMPTY\": \"没有匹配的流程定义.\",\n        \"FILTER\": {\n            \"NAME\": \"名称(case sensitive)\",\n            \"KEY\": \"Key (case sensitive)\",\n            \"DEPLOYMENT-ID\": \"部署ID\",\n            \"TENANT-ID\": \"租户ID\",\n            \"LATEST\": \"最新版本\",\n            \"LATEST-HELP\": \"只显示最新版本\"\n        },\n        \"TITLE\": {\n            \"MAIN\": \"流程定义\"\n        },\n        \"SORT\": {\n            \"ID\": \"ID\",\n            \"NAME\": \"名称\",\n            \"VERSION\": \"版本\"\n        },\n        \"HEADER\": {\n            \"ID\": \"ID\",\n            \"NAME\": \"名称\",\n            \"VERSION\": \"版本\",\n            \"KEY\": \"Key\",\n            \"TENANT\": \"租户\"\n        },\n        \"ACTIONS\": {\n            \"UPLOAD-FROM-MODELER\": \"从Flowable编辑编辑器上传\"\n        },\n        \"POPUP\": {\n            \"UPLOAD-FROM-MODELER\": {\n                \"NAME\": \"用户名\",\n                \"PASSWORD\": \"密码\",\n                \"ERROR\": \"我们不能连接到编辑器\",\n                \"UNAUTHORIZED\": \"域相关参数设置有误\",\n                \"UPLOAD-DESCRIPTION\": \"流程模型现在将被获取并部署到当前活动的Flowable集群中。为部署包选择适当的名称。\"\n            }\n        }\n    },\n    \"PROCESS-INSTANCE\": {\n        \"ID\": \"ID:\",\n        \"NAME\": \"名称:\",\n        \"DESCRIPTION\": \"描述:\",\n        \"BUSINESS-KEY\": \"Business key:\",\n        \"TENANT-ID\": \"租户:\",\n        \"STATUS\": \"状态:\",\n        \"STATUS-ACTIVE\": \"有效\",\n        \"STATUS-COMPLETED\": \"完成的\",\n        \"ACTIVITY-ID-STARTED\": \"启动的活动ID:\",\n        \"ACTIVITY-ID-ENDED\": \"结束的活动:\",\n        \"DELETE-REASON\": \"删除原因:\",\n        \"STARTED-BY\": \"Started by:\",\n        \"END-TIME\": \"结束时间:\",\n        \"DURATION\": \"持续时间:\",\n        \"SUPER-PROCESS-INSTANCE-ID\": \"父流程实例ID:\",\n        \"TASKS-SIZE\": \"这个流程实例有{{total}}个任务.\",\n        \"TASKS-EMPTY\": \"这个流程实例没有任务.\",\n        \"VARIABLES-SIZE\": \"这个流程实例有{{total}}个变量.\",\n        \"VARIABLES-EMPTY\": \"这个流程实例没有变量.\",\n        \"JOBS-SIZE\": \"这个流程实例有{{total}}个jobs.\",\n        \"JOBS-EMPTY\": \"这个流程实例没有jobs.\",\n        \"流程图片-SIZE\": \"这个流程实例有{{total}}个子流程.\",\n        \"SUBPROCESSES-EMPTY\": \"这个流程实例没有子流程.\",\n        \"DECISION-TABLES-SIZE\": \"这个流程实例有{{total}}个决策表.\",\n        \"DECISION-TABLES-EMPTY\": \"这个流程实例没有决策表.\",\n        \"FORM-INSTANCES-SIZE\": \"这个流程实例有{{total}}个表单实例.\",\n        \"FORM-INSTANCES-EMPTY\": \"这个流程实例没有子流程.\",\n        \"TITLE\": {\n            \"TASKS\": \"任务\",\n            \"VARIABLES\": \"变量\",\n            \"JOBS\": \"Jobs\",\n            \"SUBPROCESSES\": \"子流程\",\n            \"DECISION-TABLES\": \"决策表\",\n            \"FORM-INSTANCES\": \"表单实例\"\n        },\n        \"ACTION\": {\n            \"DELETE\": \"删除流程实例\",\n            \"TERMINATE\": \"终止流程实例\",\n            \"SHOW-ALL-TASKS\": \"显示所有任务\",\n            \"SHOW-ALL-JOBS\": \"显示所有jobs\",\n            \"SHOW-ALL-SUBPROCESSES\": \"显示所有子流程\",\n            \"SHOW-DIAGRAM\": \"显示流程图片\",\n            \"TITLE-VARIABLES\": \"对选定变量的操作\",\n            \"DELETE-VARIABLE\": \"删除这个变量\",\n            \"UPDATE-VALUE\": \"更新变量\",\n            \"ADD-VARIABLE\": \"添加变量\"\n        },\n        \"POPUP\": {\n            \"DELETE\": {\n                \"TITLE\": \"删除删除流程实例\",\n                \"MESSAGE-DELETE\": \"确实要删除流程实例吗？\",\n                \"MESSAGE-TERMINATE\": \"确实要终止流程实例吗？\",\n                \"DELETE-REASON\": \"删除原因\",\n                \"DELETE-REASON-HELP\": \"输入一个可选的删除原因\",\n                \"CONFIRM-DELETE\": \"删除流程实例\",\n                \"CONFIRM-TERMINATE\": \"终止流程实例\"\n            },\n            \"SHOW-PROCESS-MODEL\": {\n                \"TITLE\": \"流程图片\"\n            },\n            \"CREATE-VARIABLE\": {\n                \"TITLE\": \"创建变量\",\n                \"NAME\": \"变量名称\",\n                \"TYPE\": \"Flowable变量类型\",\n                \"VALUE\": \"变量值\",\n                \"CREATE\": \"创建\"\n            },\n            \"UPDATE-VARIABLE\": {\n                \"TITLE\": \"更新的变量'{{name}}'\",\n                \"NAME\": \"变量名称\",\n                \"VALUE\": \"值\",\n                \"CHECKED\": \"true\",\n                \"UNCHECKED\": \"false\",\n                \"DATE-HELP\": \"ISO-8601格式 (例子 : 2016-01-28T23:00:00Z)\",\n                \"ACTION-UPDATE\": \"更新\"\n            },\n            \"DELETE-VARIABLE\": {\n                \"TITLE\": \"删除变量'{{name}}\",\n                \"MESSAGE\": \"确实要删除此变量吗?\",\n                \"DELETE\": \"删除\"\n            }\n        }\n    },\n    \"PROCESS-INSTANCES\": {\n        \"TITLE\": \"流程实例\",\n        \"LIST-MESSAGE\": \"显示{{size}}个结果, 总计{{total}}个匹配到的流程实例.\",\n        \"LIST-MESSAGE-EMPTY\": \"没有匹配到流程实例\",\n        \"FILTER\": {\n            \"NAME\": \"名称\",\n            \"PROCESS-DEFINITION\": \"流程定义\",\n            \"ALL-PROCESS-DEFINITIONS\": \"所有的流程定义\",\n            \"STATUS\": \"状态\",\n            \"STATUS-ANY\": \"任何状态\",\n            \"STATUS-ACTIVE\": \"活动的实例\",\n            \"STATUS-COMPLETE\": \"完成的实例\",\n            \"BUSINESS-KEY\": \"Business key\",\n            \"SUPER-PROCESS-INSTANCE-ID\": \"父流程实例ID\",\n            \"STARTED-BEFORE\": \"开始之前\",\n            \"STARTED-AFTER\": \"开始后\",\n            \"ENDED-BEFORE\": \"结束前\",\n            \"ENDED-AFTER\": \"结束后\",\n            \"VARIABLE\": \"变量\",\n            \"VARIABLE-NAME\": \"变量名称\",\n            \"VARIABLE-VALUE\": \"变量值\",\n            \"VARIABLE-BOOLEAN-VALUE\": \"Boolean值: {{value}}\",\n            \"TENANT-ID\": \"租户标识符\"\n        },\n        \"SORT\": {\n            \"ID\": \"ID\",\n            \"START-TIME\": \"启动时间\"\n        },\n        \"HEADER\": {\n            \"ID\": \"ID\",\n            \"NAME\": \"名称\",\n            \"BUSINESS-KEY\": \"Business key\",\n            \"PROCESS-DEFINITION\": \"流程定义\",\n            \"CREATE-TIME\": \"创建\",\n            \"END-TIME\": \"完成\",\n            \"STATUS\": \"状态\"\n        }\n    },\n    \"TASK\": {\n        \"ID\": \"ID:\",\n        \"NAME\": \"名称:\",\n        \"STATUS\": \"状态:\",\n        \"STATUS-COMPLETED\": \"完成的\",\n        \"STATUS-ACTIVE\": \"有效\",\n        \"DESCRIPTION\": \"描述:\",\n        \"TASK-DEFINITION-KEY\": \"定义key:\",\n        \"FORM-KEY\": \"表单key:\",\n        \"优先级\": \"优先级:\",\n        \"DELEGATION-STATE\": \"委派状态:\",\n        \"CATEGORY\": \"分类:\",\n        \"TENANT-ID\": \"租户:\",\n        \"PARENT\": \"父任务:\",\n        \"ASSIGNEE\": \"分配人:\",\n        \"OWNER\": \"Owner:\",\n        \"START-DATE\": \"开始时间:\",\n        \"DUE-DATE\": \"到期时间:\",\n        \"END-DATE\": \"结束时间:\",\n        \"DELETE-REASON\": \"删除原因:\",\n        \"PROCESS-INSTANCE\": \"流程实例\",\n        \"PROCESS-DEFINITION\": \"流程定义\",\n        \"CASE-INSTANCE\": \"Case实例\",\n        \"CASE-DEFINITION\": \"Case定义\",\n        \"EXECUTION-ID\": \"执行实例ID:\",\n        \"SUBTASKS-MESSAGE\": \"这个任务有{{total}}个 子任务, 显示 {{size}}.\",\n        \"SUBTASKS-MESSAGE-EMPTY\": \"这个任务没有子任务.\",\n        \"VARIABLES-MESSAGE\": \"这个任务有{{size}}个变量.\",\n        \"VARIABLES-MESSAGE-EMPTY\": \"这个任务有没有变量.\",\n        \"IDENTITY-LINKS-MESSAGE\": \"这个任务有{{size}}个处理人.\",\n        \"IDENTITY-LINKS-MESSAGE-EMPTY\": \"这个任务没有处理人\",\n        \"ACTION\": {\n            \"EDIT\": \"编辑任务\",\n            \"ASSIGN-CLAIM\": \"分配/签收任务\",\n            \"DELEGATE\": \"委托任务\",\n            \"RESOLVE\": \"Resolve任务\",\n            \"COMPLETE\": \"完成任务\",\n            \"DELETE\": \"删除任务\",\n            \"SHOW-ALL-SUBTASKS\": \"显示所有子任务\",\n            \"SHOW-SUBMITTED-FORM\": \"显示表单实例\"\n        },\n        \"TITLE\": {\n            \"SUBTASKS\": \"子任务\",\n            \"IDENTITY-LINKS\": \"Identity links\",\n            \"VARIABLES\": \"变量\"\n        },\n        \"POPUP\": {\n            \"ASSIGN\": {\n                \"TITLE\": \"分配任务\",\n                \"MESSAGE\": \"你确定要分配任务\",\n                \"NEW-ASSIGNEE\": \"新的分配人\",\n                \"NEW-ASSIGNEE-HELP\": \"如果要将任务分配给任何人，请将assign字段设为空。注意：当提供用户ID时，确保它存在。\",\n                \"CONFIRM\": \"分配任务\"\n            },\n            \"COMPLETE\": {\n                \"TITLE\": \"完成任务\",\n                \"MESSAGE\": \"你确定要完成任务吗？\",\n                \"CONFIRM\": \"完成任务\"\n            },\n            \"DELEGATE\": {\n                \"TITLE\": \"委托任务\",\n                \"MESSAGE\": \"你确定要委托任务吗？\",\n                \"CONFIRM\": \"委托任务\",\n                \"DELEGATE-TO\": \"用户委托给\"\n            },\n            \"RESOLVE\": {\n                \"TITLE\": \"Resolve任务\",\n                \"MESSAGE\": \"你确定要resolve任务吗？\",\n                \"CONFIRM\": \"Resolve任务\"\n            },\n            \"DELETE\": {\n                \"TITLE\": \"删除任务\",\n                \"MESSAGE\": \"你确定要删除任务吗？\",\n                \"CONFIRM\": \"删除任务\"\n            },\n            \"EDIT\": {\n                \"TITLE\": \"编辑任务\",\n                \"CONFIRM\": \"更新任务\",\n                \"NAME\": \"名称\",\n                \"DESCRIPTION\": \"描述\",\n                \"PRIORITY\": \"优先级\",\n                \"CATEGORY\": \"分类\",\n                \"ASSIGNEE\": \"分配人\",\n                \"OWNER\": \"Owner\",\n                \"DUE-DATE\": \"到期时间\"\n            }\n        }\n    },\n    \"TASKS\": {\n        \"TITLE\": \"任务\",\n        \"LIST-MESSAGE\": \"显示{{size}}个结果,总计{{total}}个匹配到的任务。\",\n        \"LIST-MESSAGE-EMPTY\": \"没有匹配到任务\",\n        \"FILTER\": {\n            \"NAME\": \"名称 (case sensitive)\",\n            \"ASSIGNEE\": \"分配人(case sensitive)\",\n            \"STATUS\": \"状态\",\n            \"STATUS-ANY\": \"任何状态\",\n            \"STATUS-ACTIVE\": \"激活任务\",\n            \"STATUS-COMPLETE\": \"完成的任务\",\n            \"PROCESS-INSTANCE-ID\": \"流程实例ID\",\n            \"CASE-INSTANCE-ID\": \"Case实例ID\",\n            \"TENANT-ID\": \"租户标识符\",\n            \"OWNER\": \"Owner (case sensitive)\",\n            \"PARENT-TASK-ID\": \"父任务ID\",\n            \"CREATED-BEFORE\": \"创建前\",\n            \"CREATED-AFTER\": \"创建后\",\n            \"ENDED-BEFORE\": \"结束前\",\n            \"ENDED-AFTER\": \"结束后\",\n            \"DUE-BEFORE\": \"到期前\",\n            \"DUE-AFTER\": \"到期\",\n            \"TASK-VARIABLE\": \"任务局部变量\",\n            \"PROCESS-VARIABLE\": \"流程变量\",\n            \"VARIABLE-NAME\": \"变量名称\",\n            \"VARIABLE-VALUE\": \"变量值\",\n            \"VARIABLE-BOOLEAN-VALUE\": \"Boolean值: {{value}}\"\n        },\n        \"SORT\": {\n            \"NAME\": \"名称\",\n            \"DUE-DATE\": \"到期时间\",\n            \"START-TIME\": \"开始时间\",\n            \"END-TIME\": \"Time ended\",\n            \"PRIORITY\": \"优先级\"\n        },\n        \"HEADER\": {\n            \"ID\": \"ID\",\n            \"NAME\": \"名称\",\n            \"ASSIGNEE\": \"分配人\",\n            \"OWNER\": \"Owner\",\n            \"CREATE-TIME\": \"创建\",\n            \"END-TIME\": \"结束了\",\n            \"PRIORITY\": \"优先级\"\n        }\n    },\n    \"DEPLOYMENTS\": {\n        \"TITLE\": \"部署对象\",\n        \"LIST-MESSAGE\": \"显示{{size}} 条结果,总计{{total}}个匹配到的部署对象.\",\n        \"LIST-MESSAGE-EMPTY\": \"没有匹配到部署对象.\",\n        \"FILTER\": {\n            \"NAME\": \"名称 (case sensitive)\",\n            \"TENANTID\": \"租户标识符 (case sensitive)\"\n        },\n        \"SORT\": {\n            \"ID\": \"ID\",\n            \"NAME\": \"名称\"\n        },\n        \"HEADER\": {\n            \"ID\": \"ID\",\n            \"NAME\": \"名称\",\n            \"DEPLOY-TIME\": \"部署时间\",\n            \"CATEGORY\": \"分类\",\n            \"TENANT\": \"租户\"\n        },\n        \"ACTION\": {\n            \"UPLOAD\": \"上传流程或者包\",\n            \"DELETE\": \"删除部署\"\n        },\n        \"POPUP\": {\n            \"UPLOAD\": {\n                \"DESCRIPTION\": \"选择一个.bpmn, .bpmn20.xml流程文件 去部署或者上传一个包含资产的应用程序的 .zip或者.bar文件。\",\n                \"DROPZONE\": \"或在此处拖拽一个文件\",\n                \"NO-DROP\": \"浏览器不支持文件丢拖拽\",\n                \"CANCEL-UPLOAD\": \"取消上传\",\n                \"ERROR\": \"不能上传这个文件\"\n            },\n            \"DELETE\": {\n            \t\"CONFIRM-MESSAGE\": \"删除部署 '{{name}}'?\"\n            \t}\n        }\n    },\n    \"DEPLOYMENT\": {\n        \"ID\": \"ID:\",\n        \"NAME\": \"名称:\",\n        \"TIME\": \"部署时间:\",\n        \"CATEGORY\": \"分类:\",\n        \"PARENT-DEPLOYMENT-ID\": \"父部署ID:\",\n        \"TENANTID\": \"租户标识符:\",\n        \"DEFINITIONS-MESSAGE\": \"这个部署有 {{total}}个流程定义, 显示 {{size}}.\",\n        \"DEFINITIONS-MESSAGE-EMPTY\": \"这个部署没有流程定义\",\n        \"TITLE\": {\n            \"DEFINITIONS\": \"流程定义\",\n            \"RESOURCES\": \"Resources\"\n        },\n        \"ACTION\": {\n            \"SHOW-ALL-DEFINITIONS\": \"显示所有定义\"\n        }\n    },\n    \"JOB\": {\n        \"TITLE\": {\n            \"MAIN\": \"Job {{id}}\",\n            \"EXCEPTION\": \"异常\"\n        },\n        \"ACTIONS\": {\n            \"EXECUTE\": \"执行job\",\n            \"MOVE\": \"移除job\",\n            \"DELETE\": \"删除job\"\n        },\n        \"POPUP\": {\n            \"DELETE-JOB\": {\n                \"TITLE\": \"删除job'{{id}}'\",\n                \"MESSAGE\": \"你确定要删除job{{id}}?\",\n                \"CONFIRM\": \"删除job\"\n            }\n        },\n        \"ID\": \"ID:\",\n        \"EXECUTION-ID\": \"执行ID:\",\n        \"PROCESS-INSTANCE\": \"流程实例:\",\n        \"PROCESS-DEFINITION\": \"流程定义:\",\n        \"CASE-INSTANCE\": \"Case实例:\",\n        \"CASE-DEFINITION\": \"Case定义:\",\n        \"DUEDATE\": \"到期时间:\",\n        \"RETRIES-LEFT\": \"左边重试:\",\n        \"TENANT-ID\": \"租户:\"\n    },\n    \"JOBS\": {\n        \"TITLE\": \"Jobs\",\n        \"LIST-MESSAGE\": \"显示{{size}} 条结果,总计{{total}}个匹配到的jobs.\",\n        \"LIST-MESSAGE-EMPTY\": \"没有匹配到jobs\",\n        \"FILTER\": {\n        \t\"JOBTYPE\": {\n        \t\t\"LABEL\": \"Job类型\",\n        \t\t\"EXECUTABLE-JOB\": \"可以执行的jobs\",\n        \t\t\"TIMER-JOB\": \"定时的jobs\",\n        \t\t\"SUSPENDED-JOB\": \"挂起的jobs\",\n        \t\t\"DEADLETTER-JOB\": \"死信的jobs\"\n        \t},\n            \"PROCESS-DEFINITION\": \"流程定义\",\n            \"ALL-PROCESS-DEFINITIONS\": \"所有的流程定义\",\n            \"PROCESS-INSTANCE-ID\": \"流程实例ID\",\n            \"CASE-DEFINITION\": \"Case定义\",\n            \"ALL-CASE-DEFINITIONS\": \"所有Case定义\",\n            \"CASE-INSTANCE-ID\": \"Case实例ID\",\n            \"TENANT-ID\": \"租户标识符\",\n            \"DUE-BEFORE\": \"到期前\",\n            \"DUE-AFTER\": \"到期后\",\n            \"EXCEPTION\": \"异常\",\n            \"EXCEPTION-HELP\": \"只显示有异常的jobs\"\n        },\n        \"SORT\": {\n            \"ID\": \"Job ID\",\n            \"DUE-DATE\": \"到期时间\",\n            \"PROCESS-INSTANCE-ID\": \"流程实例ID\",\n            \"CASE-INSTANCE-ID\": \"Case实例ID\"\n        },\n        \"HEADER\": {\n            \"ID\": \"ID\",\n            \"DUE-DATE\": \"到期时间\",\n            \"PROCESS-DEFINITION\": \"流程定义\",\n            \"CASE-DEFINITION\": \"Case定义\",\n            \"RETRIES\": \"重试\",\n            \"EXCEPTION\": \"异常\"\n        }\n    },\n    \"EVENT-SUBSCRIPTION\": {\n        \"TITLE\": {\n            \"MAIN\": \"事件订阅{{id}}\"\n        },\n        \"ACTIONS\": {\n            \"TRIGGER\": \"触发事件\"\n        },\n        \"ID\": \"ID:\",\n        \"ACTIVITY-ID\": \"活动ID:\",\n        \"EXECUTION-ID\": \"执行ID:\",\n        \"PROCESS-INSTANCE\": \"流程实例:\",\n        \"PROCESS-DEFINITION\": \"流程定义:\",\n        \"CREATE-DATE\": \"已经创建:\",\n        \"EVENT-TYPE\": \"事件类型:\",\n        \"EVENT-NAME\": \"事件名称:\",\n        \"TENANT-ID\": \"租户:\"\n    },\n    \"EVENT-SUBSCRIPTIONS\": {\n    \t\"TITLE\": \"事件订阅\",\n        \"LIST-MESSAGE\": \"显示{{size}} 条结果,总计{{total}}个匹配到的事件订阅\",\n        \"LIST-MESSAGE-EMPTY\": \"没有匹配到事件订阅\",\n    \t\"FILTER\": {\n            \"PROCESS-DEFINITION\": \"流程定义\",\n            \"ALL-PROCESS-DEFINITIONS\": \"所有的流程定义\",\n            \"PROCESS-INSTANCE-ID\": \"流程实例ID\",\n            \"TENANT-ID\": \"租户标识符\",\n            \"CREATED-BEFORE\": \"创建前\",\n            \"CREATED-AFTER\": \"创建后\"\n        },\n        \"SORT\": {\n            \"ID\": \"事件订阅ID\",\n            \"CREATE-DATE\": \"已经创建\",\n            \"PROCESS-INSTANCE-ID\": \"流程实例ID\"\n        },\n    \t\"HEADER\": {\n            \"ID\": \"ID\",\n            \"CREATE-DATE\": \"已经创建\",\n            \"PROCESS-DEFINITION\": \"流程定义\",\n            \"EVENT-TYPE\": \"事件类型\",\n            \"EVENT-NAME\": \"事件名称\"\n        }\n    },\n    \"LOGIN\": {\n        \"TITLE\": \"登录\",\n        \"USERNAME\": \"用户名\",\n        \"USERNAME-PLACEHOLDER\": \"输入您的用户名\",\n        \"PASSWORD\": \"密码\",\n        \"PASSWORD-PLACEHOLDER\": \"输入您的密码\",\n        \"ACTION\": {\n            \"CONFIRM\": \"登录\"\n        }\n    },\n    \"USER\": {\n        \"POPUP\": {\n            \"CHANGE-PASSWORD\": {\n                \"TITLE\": \"修改'{{login}}'的密码\",\n                \"OLD-PASSWORD\": \"旧密码\",\n                \"NEW-PASSWORD\": \"新密码\",\n                \"CONFIRM\": \"修改密码\"\n            },\n            \"DELETE\": {\n                \"TITLE\": \"删除{{login}}用户\",\n                \"MESSAGE\": \"你确定要删除'{{login}}'用户?\",\n                \"CONFIRM\": \"删除用户\"\n            },\n            \"EDIT\": {\n                \"TITLE\": \"编辑{{login}}用户\",\n                \"LOGIN\": \"登录\",\n                \"EMAIL\": \"邮箱\",\n                \"FIRSTNAME\": \"名字\",\n                \"LASTNAME\": \"姓氏\",\n                \"CONFIRM\": \"更新用户\"\n            },\n            \"NEW\": {\n                \"TITLE\": \"创建新用户\",\n                \"LOGIN\": \"登录\",\n                \"EMAIL\": \"邮箱\",\n                \"FIRSTNAME\": \"名字\",\n                \"LASTNAME\": \"姓氏\",\n                \"PASSWORD\": \"密码\",\n                \"ADMIN\": \"有管理员权限\",\n                \"CONFIRM\": \"创建用户\"\n            }\n        }\n    },\n    \"USERS\": {\n        \"TITLE\": \"用户\",\n        \"ACTION\": {\n            \"EDIT\": \"编辑用户\",\n            \"NEW\": \"创建新用户\",\n            \"DELETE\": \"删除用户\",\n            \"CHANGE-PASSWORD\": \"修改密码\"\n        },\n        \"HEADER\": {\n            \"LOGIN\": \"登录\",\n            \"FIRSTNAME\": \"名字\",\n            \"LASTNAME\": \"姓氏\",\n            \"EMAIL\": \"邮箱\",\n            \"CLUSTER_USER\": \"集群用户\"\n        }\n    },\n    \"LICENSE\": {\n        \"POPUP\": {\n            \"TITLE\": \"许可证信息\",\n            \"HOLDER\": \"持有人\",\n            \"SUBJECT\": \"主体\",\n            \"PRODUCTKEY\": \"产品类型\",\n            \"GOODAFTERDATE\": \"许可证有效后\",\n            \"GOODBEFOREDATE\": \"许可证有效，直到\",\n            \"NUMBER_OF_PROCESSES\": \"活动流程数量\",\n            \"NUMBER_OF_ADMINS\": \"管理员用户数\",\n            \"MULTI_TENANT\": \"多租户\",\n            \"DEFAULT_TENANT\": \"默认租户\"\n        }\n    },\n    \"CLUSTER\": {\n        \"NAME\": \"名称:\",\n        \"USER\": \"用户:\",\n        \"MASTER-MANDATORY\": \"强制使用主配置:\",\n        \"METRICS-SEND-INTERVAL\": \"Metric send interval:\",\n        \"ENDPOINT-HELP\": \"端点配置（每个集群只有一个）需要指向 Flowable REST的安装。然后，这个端点将被用于检索和管理其他部分中使用的数据此应用程序(例如部署、流程定义等等。) \",\n        \"ENDPOINT-NAME\": \"名称:\",\n        \"ENDPOINT-DESCRIPTION\": \"描述:\",\n        \"ENDPOINT-ADDRESS\": \"服务地址（address）:\",\n        \"ENDPOINT-PORT\": \"服务端口（port）:\",\n        \"ENDPOINT-CONTEXT-ROOT\": \"上下文根:\",\n        \"ENDPOINT-REST-ROOT\": \"REST根:\",\n        \"ENDPOINT-USERNAME\": \"用户名:\",\n        \"PROCESS-ENGINE-HELP\": \"这部分允许您为群集定义一个‘主配置’。集群中的所有实例将在启动时使用此配置。(如果群集配置jar包位于类路径上，或者如果设置了相应的属性). 如果没有设置，实例将使用它们的本地配置文件。\",\n        \"NO-MASTER-DEFINED\": \"没有定义主配置\",\n        \"ACTION\": {\n            \"SHOW-PASSWORD\": \"显示密码\",\n            \"EDIT-CLUSTER-CONFIG\": \"编辑集群配置\",\n            \"CREATE-CLUSTER-CONFIG\": \"创建新集群\",\n            \"DELETE-CLUSTER-CONFIG\": \"删除集群配置\",\n            \"GENERATE-JAR\": \"生成集群配置jar\",\n            \"EDIT-ENDPOINT\": \"编辑REST端点\",\n            \"CHECK-ENDPOINT\": \"检查 REST端点\",\n            \"SELECT-MASTER\": \"选择主配置\",\n            \"ADD-CONFIGURATION\": \"添加主配置\",\n            \"EDIT-CONFIGURATION\": \"编辑主配置\",\n            \"DELETE-CONFIGURATION\": \"删除主配置\"\n        },\n        \"TITLE\": {\n            \"PROCESS-ENDPOINT\": \"流程API端点配置\",\n            \"CMMN-ENDPOINT\": \"CMMN API端点配置\",\n            \"DMN-ENDPOINT\": \"DMN API端点配置\",\n            \"FORM-ENDPOINT\": \"表单API端点配置\",\n            \"CONTENT-ENDPOINT\": \"Content API端点配置\",\n            \"APP-ENDPOINT\": \"应用程序API端点配置\"\n        },\n        \"POPUP\": {\n            \"EDIT-ENDPOINT\": {\n                \"ENDPOINT-NAME\": \"名称\",\n                \"ENDPOINT-DESCRIPTION\": \"描述\",\n                \"ENDPOINT-ADDRESS\": \"服务地址（address）\",\n                \"ENDPOINT-PORT\": \"服务端口（port） \",\n                \"ENDPOINT-CONTEXT-ROOT\": \"上下文根(root)\",\n                \"ENDPOINT-REST-ROOT\": \"REST根(root)\",\n                \"ENDPOINT-密码\": \"用户名\",\n                \"ENDPOINT-PASSWORD\": \"密码\",\n                \"ENDPOINT-PASSWORD-HELP\": \"离开当前的去保存密码\",\n                \"ENDPOINT-URL-PREVIEW\": \"URL预览\",\n                \"ACTION-CONFIRM\": \"保存endpoint配置\",\n                \"ERROR-401\": \"错误:无效凭据\",\n                \"ERROR-403\": \"错误: 无效凭据或URL\",\n                \"ERROR-404\": \"错误: URL没找到\",\n                \"ERROR-500\": \"错误: 服务器错误。检查服务器日志。\"\n            }\n        }\n    },\n    \"APP-DEPLOYMENTS\": {\n        \"TITLE\": \"应用程序部署对象\",\n        \"LIST-MESSAGE\": \"显示{{size}} 条结果,总计{{total}}个匹配到的应用部署对象.\",\n        \"LIST-MESSAGE-EMPTY\": \"没有匹配到应用部署对象.\",\n        \"FILTER\": {\n            \"NAME\": \"名称\",\n            \"TENANTID\": \"租户标识符\",\n            \"LATEST\": \"最新版本\",\n            \"LATEST-HELP\": \"仅显示最近的部署时间\"\n        },\n        \"SORT\": {\n            \"ID\": \"ID\",\n            \"NAME\": \"名称\"\n        },\n        \"HEADER\": {\n            \"ID\": \"ID\",\n            \"APP-DEFINITION-ID\": \"应用程序ID\",\n            \"DEPLOYMENT-ID\": \"流程部署ID\",\n            \"DMN-DEPLOYMENT-ID\": \"DMN部署ID\",\n            \"NAME\": \"名称\",\n            \"DEPLOY-TIME\": \"部署时间\",\n            \"DEPLOYED-BY\": \"Deployed by\",\n            \"TENANT\": \"租户ID\"\n        },\n        \"ACTION\": {\n            \"UPLOAD\": \"上传和发布应用程序\"\n        },\n        \"POPUP\": {\n            \"UPLOAD\": {\n                \"DESCRIPTION\": \"选择一个.zip应用程序定义去部署\",\n                \"WARNING\": \"只能在Flowable UI实例中上传一个流程。\",\n                \"DROPZONE\": \"或在此处拖拽一个文件\",\n                \"NO-DROP\": \"浏览器不支持文件丢拖拽\",\n                \"CANCEL-UPLOAD\": \"取消上传\",\n                \"ERROR\": \"不能上传这个文件\"\n            }\n        }\n    },\n    \"VARIABLES\": {\n        \"HEADER\": {\n            \"NAME\": \"名称\",\n            \"TYPE\": \"类型\",\n            \"VALUE\": \"值\"\n        }\n    },\n    \"IDENTITY-LINKS\": {\n        \"HEADER\": {\n            \"GROUP-ID\": \"组ID\",\n            \"TYPE\": \"类型\",\n            \"USER-ID\": \"用户ID\"\n        }\n    },\n    \"ALERT\": {\n        \"GENERAL\": {\n            \"HTTP-ERROR\": \"我们无法从服务器获得数据\",\n            \"AUTHENTICATION-ERROR\": \"输入无效登录凭据\"\n        },\n        \"ENGINE\": {\n            \"ENDPOINT-UPDATED\": \"Endpoint '{{name}}' 被更新.\",\n            \"ENDPOINT-INVALID\": \"Endpoint配置'{{name}}' 无效.\",\n            \"ENDPOINT-VALID\": \"Endpoint有效的, 引擎在endpoint: {{name}} - {{version}}\"\n        },\n        \"JOB\": {\n            \"DELETED\": \"Job '{{id}}'成功删除。\",\n            \"MOVED\": \"Job '{{id}}'移除成功\",\n            \"EXECUTED\": \"Job '{{id}}' 执行成功\"\n        },\n        \"EVENT-SUBSCRIPTION\": {\n        \t\"TRIGGERED\": \"事件订阅 '{{id}}'成功被触发.\"\n        },\n        \"PROCESS-INSTANCE\": {\n            \"DELETED\": \"流程实例 '{{id}}'成功删除。\",\n            \"TERMINATED\": \"流程实例 '{{id}}'成功终止。\"\n        },\n        \"TASK\": {\n            \"DELETED\": \"任务 '{{id}}' 成功删除。\",\n            \"COMPLETED\": \"任务 '{{id}}'成功完成。\",\n            \"DELEGATED\": \"任务 '{{id}}' 委托给 {{user}}用户.\",\n            \"RESOLVED\": \"任务 '{{id}}'resolved成功.\",\n            \"ASSIGNED\": \"任务 '{{id}}' 现在已经分配给了{{user}}.\",\n            \"UNASSIGNED\": \"任务 '{{id}}' 现在未分配.\",\n            \"UPDATED\": \"任务 '{{id}}'成功更新。\"\n        },\n        \"USER\": {\n            \"DELETED\": \"'{{login}}'用户删除成功。\",\n            \"UPDATED\": \"'{{login}}'用户更新成功。\",\n            \"CREATED\": \"'{{login}}' 用户被创建.\",\n            \"PASSWORD-CHANGED\": \"'{{login}}'密码修改成功。\"\n        },\n        \"PROCESS-DEFINITION\": {\n            \"CATEGORY-UPDATED\": \"流程定义分类被更新\"\n        },\n        \"DEPLOYMENT\": {\n        \t\"DELETED-DEPLOYMENT\": \"删除部署对象'{{name}}'\",\n        \t\"DELETE-ERROR\": \"不能删除部署对象. {{exception || ''}}\",\n        \t\"DEPLOYMENT-SUCCESS\": \"部署成功\"\n        },\n        \"APP-DEPLOYMENT\": {\n        \t\"DELETED-APP\": \"删除应用程序'{{appDefinition.name}}'\",\n        \t\"DELETE-ERROR\": \"不能删除应用程序。{{message || ''}}\"\n        }\n    },\n    \"CMMN-DEPLOYMENTS\": {\n        \"TITLE\": \"部署对象\",\n        \"LIST-MESSAGE\": \"显示{{size}} 条结果,总计{{total}}个匹配到的部署对象.\",\n        \"LIST-MESSAGE-EMPTY\": \"No matching deployments.\",\n        \"FILTER\": {\n            \"NAME\": \"名称 (case sensitive)\",\n            \"TENANTID\": \"租户标识符 (case sensitive)\"\n        },\n        \"SORT\": {\n            \"ID\": \"ID\",\n            \"NAME\": \"名称\"\n        },\n        \"HEADER\": {\n            \"ID\": \"ID\",\n            \"NAME\": \"名称\",\n            \"DEPLOY-TIME\": \"部署时间\",\n            \"CATEGORY\": \"分类\",\n            \"TENANT\": \"租户\"\n        },\n        \"ACTION\": {\n            \"UPLOAD\": \"上传一个流程或者包\",\n            \"DELETE\": \"删除部署\"\n        },\n        \"POPUP\": {\n            \"UPLOAD\": {\n                \"DESCRIPTION\": \"选择一个.bpmn, .bpmn20.xml流程文件 去部署或者上传一个包含资产的应用程序的 .zip或者.bar文件。\",\n                \"DROPZONE\": \"或在此处拖拽一个文件\",\n                \"NO-DROP\": \"浏览器不支持文件丢拖拽\",\n                \"CANCEL-UPLOAD\": \"取消上传\",\n                \"ERROR\": \"不能上传这个文件\"\n            },\n            \"DELETE\": {\n                \"CONFIRM-MESSAGE\": \"删除部署 '{{name}}'?\"\n                }\n        }\n    },\n    \"CMMN-DEPLOYMENT\": {\n        \"ID\": \"ID:\",\n        \"NAME\": \"名称:\",\n        \"TIME\": \"部署时间:\",\n        \"CATEGORY\": \"分类:\",\n        \"TENANTID\": \"租户标识符:\",\n        \"PARENT-DEPLOYMENT-ID\": \"父部署ID:\",\n        \"DEFINITIONS-MESSAGE\": \"这个部署对象有{{total}}个Case定义, 显示 {{size}}.\",\n        \"DEFINITIONS-MESSAGE-EMPTY\": \"这个部署对象没有Case定义.\",\n        \"TITLE\": {\n            \"CASE-DEFINITIONS\": \"Case定义\",\n            \"RESOURCES\": \"资源\"\n        },\n        \"ACTION\": {\n            \"SHOW-ALL-DEFINITIONS\": \"显示所有定义\"\n        }\n    },\n    \"CASE-DEFINITIONS\": {\n        \"LIST-MESSAGE\": \"显示{{size}} 条结果,总计{{total}}个匹配到的定义\",\n        \"LIST-MESSAGE-EMPTY\": \"没有匹配到Case定义.\",\n        \"FILTER\": {\n            \"NAME\": \"名称 (case sensitive)\",\n            \"KEY\": \"Key (case sensitive)\",\n            \"DEPLOYMENT-ID\": \"部署ID\",\n            \"TENANT-ID\": \"租户ID\",\n            \"LATEST\": \"最新版本\",\n            \"LATEST-HELP\": \"只显示最新版本\"\n        },\n        \"TITLE\": {\n            \"MAIN\": \"Case定义\"\n        },\n        \"SORT\": {\n            \"ID\": \"ID\",\n            \"NAME\": \"名称\",\n            \"VERSION\": \"版本\"\n        },\n        \"HEADER\": {\n            \"ID\": \"ID\",\n            \"NAME\": \"名称\",\n            \"VERSION\": \"版本\",\n            \"KEY\": \"Key\",\n            \"TENANT\": \"租户\"\n        },\n        \"ACTIONS\": {\n            \"UPLOAD-FROM-MODELER\": \"从Flowable编辑器上传\"\n        },\n        \"POPUP\": {\n            \"UPLOAD-FROM-MODELER\": {\n                \"NAME\": \"用户名\",\n                \"PASSWORD\": \"密码\",\n                \"ERROR\": \"我们无法使用编辑器\",\n                \"UNAUTHORIZED\": \"域相关参数设置有误\",\n                \"UPLOAD-DESCRIPTION\": \"流程模型现在将被获取并部署到当前活动的Flowable集群中。为部署包选择适当的名称。\"\n            }\n        }\n    },\n    \"CASE-DEFINITION\": {\n        \"ID\": \"ID:\",\n        \"NAME\": \"名称:\",\n        \"VERSION\": \"版本:\",\n        \"DESCRIPTION\": \"描述:\",\n        \"KEY\": \"Key:\",\n        \"CATEGORY\": \"分类:\",\n        \"DEPLOYMENT\": \"部署对象:\",\n        \"TENANT\": \"租户:\",\n        \"START-FORM-DEFINED\": \"启动表单定义:\",\n        \"GRAPHICAL-NOTATION-DEFINED\": \"图形符号定义:\",\n        \"CASE-INSTANCES-SIZE\": \"定义有{{total}}个正在运行的case实例\",\n        \"CASE-INSTANCES-SHOWING\": \", 显示 {{size}}个最近使用的\",\n        \"CASE-INSTANCES-EMPTY\": \"定义没有正在运行的case实例\",\n        \"JOBS-SIZE\": \"定义有 {{total}}个正在运行的jobs\",\n        \"JOBS-EMPTY\": \"定义没有正在运行的jobs\",\n        \"DECISION-TABLES-SIZE\": \"定义有{{total}}个决策表.\",\n        \"DECISION-TABLES-EMPTY\": \"定义没有决策表.\",\n        \"FORM-DEFINITIONS-SIZE\": \"定义有{{total}}个表单定义.\",\n        \"FORM-DEFINITIONS-EMPTY\": \"定义没有表单定义.\",\n        \"TITLE\": {\n            \"CASE-INSTANCES\": \"Case实例\",\n            \"JOBS\": \"Jobs\",\n            \"DECISION-TABLES\": \"决策表\",\n            \"FORMS\": \"表单定义\"\n        },\n        \"ACTION\": {\n            \"EDIT-CATEGORY\": \"编辑分类\",\n            \"SHOW-ALL-JOBS\": \"显示所有的 jobs\",\n            \"SHOW-ALL-CASES\": \"显示所有的cases\",\n            \"SHOW-DIAGRAM\": \"显示case图\"\n        },\n        \"POPUP\": {\n            \"EDIT-CATEGORY\": {\n                \"TITLE\": \"定义编辑分类\",\n                \"MESSAGE\": \" 从CMMN 1.1 xml中的目标命名空间属性填充定义的初始分类, 但部署后可以更改。\",\n                \"CATEGORY\": \"分类\",\n                \"CATEGORY-PLACEHOLDER\": \"输入一个分类\",\n                \"CONFIRM\": \"修改分类\"\n            },\n            \"SHOW-CASE-MODEL\": {\n                \"TITLE\": \"Case图\"\n            }\n        }\n    },\n    \"CASE-INSTANCES\": {\n        \"TITLE\": \"Case实例\",\n        \"LIST-MESSAGE\": \"显示{{size}} 条结果,总计{{total}}个匹配到的case实例.\",\n        \"LIST-MESSAGE-EMPTY\": \"没有匹配到到case实例.\",\n        \"FILTER\": {\n            \"NAME\": \"名称\",\n            \"CASE-DEFINITION\": \"Case定义\",\n            \"ALL-CASE-DEFINITIONS\": \"All Case定义\",\n            \"STATUS\": \"状态\",\n            \"STATUS-ANY\": \"任何状态\",\n            \"STATUS-ACTIVE\": \"激活的实例\",\n            \"STATUS-COMPLETE\": \"完成的实例\",\n            \"BUSINESS-KEY\": \"Business key\",\n            \"STARTED-BEFORE\": \"开始之前\",\n            \"STARTED-AFTER\": \"开始后\",\n            \"ENDED-BEFORE\": \"结束前\",\n            \"ENDED-AFTER\": \"结束后\",\n            \"VARIABLE\": \"变量\",\n            \"VARIABLE-NAME\": \"变量名称\",\n            \"VARIABLE-VALUE\": \"变量值\",\n            \"VARIABLE-BOOLEAN-VALUE\": \"Boolean值: {{value}}\",\n            \"TENANT-ID\": \"租户标识符\"\n        },\n        \"SORT\": {\n            \"ID\": \"ID\",\n            \"START-TIME\": \"开始时间\"\n        },\n        \"HEADER\": {\n            \"ID\": \"ID\",\n            \"NAME\": \"名称\",\n            \"BUSINESS-KEY\": \"Business key\",\n            \"CASE-DEFINITION\": \"Case定义\",\n            \"CREATE-TIME\": \"已经创建\",\n            \"END-TIME\": \"结束的\",\n            \"STATUS\": \"状态\"\n        }\n    },\n    \"CASE-INSTANCE\": {\n        \"ID\": \"ID:\",\n        \"NAME\": \"名称:\",\n        \"DESCRIPTION\": \"描述:\",\n        \"BUSINESS-KEY\": \"Business key:\",\n        \"TENANT-ID\": \"租户:\",\n        \"STATUS\": \"状态:\",\n        \"STATUS-ACTIVE\": \"有效\",\n        \"STATUS-有效\": \"完成的\",\n        \"DELETE-REASON\": \"删除原因:\",\n        \"STARTED-BY\": \"Started by:\",\n        \"END-TIME\": \"结束时间:\",\n        \"DURATION\": \"持续时间:\",\n        \"TASKS-SIZE\": \"这个case实例有{{total}}个任务.\",\n        \"TASKS-EMPTY\": \"这个case实例没有任务.\",\n        \"VARIABLES-SIZE\": \"这个case实例有{{total}}个变量.\",\n        \"VARIABLES-EMPTY\": \"这个case实例没有变量.\",\n        \"JOBS-SIZE\": \"这个case实例有{{total}}个jobs.\",\n        \"JOBS-EMPTY\": \"这个case实例没有jobs.\",\n        \"DECISION-TABLES-SIZE\": \"这个case实例有{{total}}个决策表.\",\n        \"DECISION-TABLES-EMPTY\": \"这个case实例没有决策表.\",\n        \"FORM-INSTANCES-SIZE\": \"这个case实例有{{total}}个表单实例.\",\n        \"FORM-INSTANCES-EMPTY\": \"这个case实例没有表单实例\",\n        \"TITLE\": {\n            \"TASKS\": \"任务\",\n            \"VARIABLES\": \"变量\",\n            \"JOBS\": \"Jobs\",\n            \"DECISION-TABLES\": \"决策表\",\n            \"FORM-INSTANCES\": \"表单实例\"\n        },\n        \"ACTION\": {\n            \"DELETE\": \"删除Case实例e\",\n            \"TERMINATE\": \"终止Case实例\",\n            \"SHOW-ALL-TASKS\": \"显示所有的tasks\",\n            \"SHOW-ALL-JOBS\": \"显示所有的jobs\",\n            \"SHOW-DIAGRAM\": \"显示case图标\",\n            \"TITLE-VARIABLES\": \"对选定变量的操作\",\n            \"DELETE-VARIABLE\": \"删除这个变量\",\n            \"UPDATE-VALUE\": \"更新变量\",\n            \"ADD-VARIABLE\": \"添加变量\"\n        },\n        \"POPUP\": {\n            \"DELETE\": {\n                \"TITLE\": \"删除Case实例\",\n                \"MESSAGE-DELETE\": \"你确定要删除这个case实例吗？\",\n                \"MESSAGE-TERMINATE\": \"你确定要终止这个case实例吗？\",\n                \"DELETE-REASON\": \"删除原因\",\n                \"DELETE-REASON-HELP\": \"输入一个可选的删除原因\",\n                \"CONFIRM-DELETE\": \"删除Case实例\",\n                \"CONFIRM-TERMINATE\": \"终止Case实例\"\n            },\n            \"SHOW-CASE-MODEL\": {\n                \"TITLE\": \"Case图\"\n            },\n            \"CREATE-VARIABLE\": {\n                \"TITLE\": \"创建变量\",\n                \"NAME\": \"变量名称\",\n                \"TYPE\": \"Flowable变量类型\",\n                \"VALUE\": \"变量值\",\n                \"CREATE\": \"创建\"\n            },\n            \"UPDATE-VARIABLE\": {\n                \"TITLE\": \"更新变量'{{name}}'\",\n                \"NAME\": \"变量名称\",\n                \"VALUE\": \"值\",\n                \"CHECKED\": \"true\",\n                \"UNCHECKED\": \"false\",\n                \"DATE-HELP\": \"ISO-8601格式 (例子 : 2016-01-28T23:00:00Z)\",\n                \"ACTION-UPDATE\": \"更新\"\n            },\n            \"DELETE-VARIABLE\": {\n                \"TITLE\": \"删除变量'{{name}}\",\n                \"MESSAGE\": \"确实要删除此变量吗?\",\n                \"DELETE\": \"删除\"\n            }\n        }\n    },\n    \"APP-DEPLOYMENTS\": {\n        \"TITLE\": \"部署\",\n        \"LIST-MESSAGE\": \"显示{{size}}个结果, 总计{{total}}匹配到的部署对象.\",\n        \"LIST-MESSAGE-EMPTY\": \"没有匹配到的部署.\",\n        \"FILTER\": {\n            \"NAME\": \"名称(case sensitive)\",\n            \"TENANTID\": \"租户标识符(case sensitive)\"\n        },\n        \"SORT\": {\n            \"ID\": \"ID\",\n            \"NAME\": \"名称\"\n        },\n        \"HEADER\": {\n            \"ID\": \"ID\",\n            \"NAME\": \"名称\",\n            \"DEPLOY-TIME\": \"部署时间\",\n            \"CATEGORY\": \"分类\",\n            \"TENANT\": \"租户\"\n        },\n        \"ACTION\": {\n            \"UPLOAD\": \"上传应用程序\",\n            \"DELETE\": \"删除部署\"\n        },\n        \"POPUP\": {\n            \"UPLOAD\": {\n                \"DESCRIPTION\": \"选择一个.app应用程序定义文件去部署或者上传一个包含资产的应用程序的.zip或者.bar 文件.\",\n                \"DROPZONE\": \"或在此处拖拽一个文件\",\n                \"NO-DROP\": \"浏览器不支持文件丢拖拽\",\n                \"CANCEL-UPLOAD\": \"取消上传\",\n                \"ERROR\": \"不能上传这个文件\"\n            },\n            \"DELETE\": {\n                \"CONFIRM-MESSAGE\": \"删除部署 '{{name}}'?\"\n                }\n        }\n    },\n    \"APP-DEPLOYMENT\": {\n        \"ID\": \"ID:\",\n        \"NAME\": \"名称:\",\n        \"TIME\": \"部署时间:\",\n        \"KEY\": \"Key:\",\n        \"CATEGORY\": \"分类:\",\n        \"TENANTID\": \"租户标识符:\",\n        \"DEFINITIONS-MESSAGE\": \"这个部署有{{total}}个应用程序定义, 显示 {{size}}.\",\n        \"DEFINITIONS-MESSAGE-EMPTY\": \"这个部署没有个应用程序定义。\",\n        \"TITLE\": {\n            \"APP-DEFINITIONS\": \"应用程序定义\",\n            \"RESOURCES\": \"资源\"\n        },\n        \"ACTION\": {\n            \"SHOW-ALL-DEFINITIONS\": \"显示所有定义\"\n        }\n    },\n    \"APP-DEFINITIONS\": {\n        \"LIST-MESSAGE\": \"显示{{size}} 条结果,总计{{total}}个匹配到的应用程序定义。\",\n        \"LIST-MESSAGE-EMPTY\": \"没有匹配到的应用程序定义。\",\n        \"FILTER\": {\n            \"NAME\": \"名称 (case sensitive)\",\n            \"KEY\": \"Key (case sensitive)\",\n            \"DEPLOYMENT-ID\": \"部署ID\",\n            \"TENANT-ID\": \"租户ID\",\n            \"LATEST\": \"最新版本\",\n            \"LATEST-HELP\": \"只显示最新版本\"\n        },\n        \"TITLE\": {\n            \"MAIN\": \"应用程序定义\"\n        },\n        \"SORT\": {\n            \"ID\": \"ID\",\n            \"NAME\": \"名称\",\n            \"VERSION\": \"版本\"\n        },\n        \"HEADER\": {\n            \"ID\": \"ID\",\n            \"NAME\": \"名称\",\n            \"VERSION\": \"版本\",\n            \"KEY\": \"Key\",\n            \"TENANT\": \"租户\"\n        }\n    },\n    \"APP-DEFINITION\": {\n        \"ID\": \"ID:\",\n        \"NAME\": \"名称:\",\n        \"VERSION\": \"版本:\",\n        \"DESCRIPTION\": \"描述:\",\n        \"KEY\": \"Key:\",\n        \"CATEGORY\": \"分类:\",\n        \"DEPLOYMENT\": \"部署对象:\",\n        \"TENANT\": \"租户:\",\n        \"PROCESS-DEFINITIONS-SIZE\": \"应用程序有{{total}}个流程实例\",\n        \"PROCESS-DEFINITIONS-EMPTY\": \"应用程序没有流程实例\",\n        \"CASE-DEFINITIONS-SIZE\": \"应用程序有{{total}}个Case定义。\",\n        \"CASE-DEFINITIONS-EMPTY\": \"应用程序没有Case定义。\",\n        \"DECISION-TABLES-SIZE\": \"应用程序有{{total}}个决策表。\",\n        \"DECISION-TABLES-EMPTY\": \"应用程序有没有流程定义。\",\n        \"FORM-DEFINITIONS-SIZE\": \"应用程序有{{total}}个表单定义。\",\n        \"FORM-DEFINITIONS-EMPTY\": \"应用程序没有表单定义。\",\n        \"TITLE\": {\n            \"PROCESS-DEFINITIONS\": \"流程定义\",\n            \"CASE-DEFINITIONS\": \"Case定义\",\n            \"DECISION-TABLES\": \"决策表\",\n            \"FORM-DEFINITIONS\": \"表单定义\"\n        },\n        \"ACTION\": {\n            \"EDIT-CATEGORY\": \"编辑分类\"\n        }\n    },\n    \"DECISION-TABLE-DEPLOYMENTS\": {\n        \"TITLE\": \"决策表部署对象\",\n        \"LIST-MESSAGE\": \"显示{{size}} 条结果,总计{{total}} 个匹配到的部署对象。\",\n        \"LIST-MESSAGE-EMPTY\": \"没有匹配到部署对象。\",\n        \"FILTER\": {\n            \"NAME\": \"名称 (case sensitive)\",\n            \"TENANTID\": \"租户标识符 (case sensitive)\"\n        },\n        \"SORT\": {\n            \"ID\": \"ID\",\n            \"NAME\": \"名称\"\n        },\n        \"HEADER\": {\n            \"ID\": \"ID\",\n            \"NAME\": \"名称\",\n            \"DEPLOY-TIME\": \"部署时间\",\n            \"CATEGORY\": \"分类\",\n            \"TENANT\": \"租户\"\n        },\n        \"ACTION\": {\n            \"DELETE\": \"删除部署\"\n        }\n    },\n    \"DECISION-TABLE-DEPLOYMENT\": {\n        \"ID\": \"ID:\",\n        \"NAME\": \"名称:\",\n        \"TIME\": \"部署时间:\",\n        \"CATEGORY\": \"分类:\",\n        \"TENANTID\": \"租户标识符:\",\n        \"DECISION-TABLES-MESSAGE\": \"这个部署对象有{{total}}决策表, 显示 {{size}}.\",\n        \"DECISION-TABLES-MESSAGE-EMPTY\": \"这个部署对象没有匹配到决策表。\",\n        \"PARENT-DEPLOYMENT-ID\": \"父部署ID\",\n        \"TITLE\": {\n            \"DECISION-TABLES\": \"决策表\",\n            \"RESOURCES\": \"资源\"\n        },\n        \"ACTION\": {\n            \"SHOW-ALL-DEFINITIONS\": \"显示所有的决策表\"\n        }\n    },\n    \"DECISION-TABLES\": {\n        \"TITLE\": \"决策表\",\n        \"LIST-MESSAGE\": \"显示{{size}} 条结果,总计{{total}} 个匹配到的决策表。\",\n        \"LIST-MESSAGE-EMPTY\": \"没有匹配到决策表。\",\n        \"FILTER\": {\n            \"NAME\": \"名称\",\n            \"KEY\": \"Key\",\n            \"TENANTID\": \"租户标识符\"\n        },\n        \"SORT\": {\n            \"ID\": \"ID\",\n            \"NAME\": \"名称\"\n        },\n        \"HEADER\": {\n            \"ID\": \"ID\",\n            \"NAME\": \"名称\",\n            \"VERSION\": \"版本\",\n            \"KEY\": \"Key\",\n            \"DEPLOY-TIME\": \"部署时间\",\n            \"TENANT-ID\": \"租户ID\"\n        }\n    },\n    \"DECISION-TABLE\": {\n        \"ID\": \"ID:\",\n        \"NAME\": \"名称:\",\n        \"VERSION\": \"版本:\",\n        \"KEY\": \"Key:\",\n        \"CATEGORY\": \"分类:\",\n        \"DEPLOYMENT-ID\": \"部署ID:\",\n        \"PARENT-DEPLOYMENT-ID\": \"父部署ID\",\n        \"RESOURCE-NAME\": \"资源名称:\",\n        \"DESCRIPTION\": \"描述:\",\n        \"TENANT\": \"租户:\",\n        \"TITLE\": {\n            \"DECISION-AUDITS\": \"决策审计\"\n        },\n        \"DECISION-EXECUTION-MESSAGE\": \"这个决策表{{total}}个执行实例, 显示 {{size}}.\",\n        \"DECISION-EXECUTION-MESSAGE-EMPTY\": \"这个决策表没有执行实例\",\n        \"ACTION\": {\n            \"EDIT-CATEGORY\": \"编辑分类\",\n            \"SHOW-ALL-JOBS\": \"显示所有的jobs\",\n            \"SHOW-ALL-PROCESSES\": \"显示所有的流程\",\n            \"SHOW-DIAGRAM\": \"显示流程图片\",\n            \"SHOW-DECISION-TABLE\": \"显示决策表\",\n            \"SHOW-ALL-EXECUTIONS\": \"显示所有的执行实例对象\"\n        },\n        \"POPUP\": {\n            \"TITLE\": \"决策表: \",\n            \"KEY\": \"Key:\",\n            \"HIT-POLICY\": \"命中策略:\",\n            \"HIT-POLICIES\": {\n                \"FIRST\": \"First (Single pass)\",\n                \"ANY\": \"Any (Single pass)\"\n            }\n        }\n    },\n    \"DECISION-TABLE-EXECUTIONS\": {\n        \"TITLE\": \"决策表执行实例对象\",\n        \"LIST-MESSAGE\": \"显示{{size}} 条结果,总计{{total}}个匹配到的决策表执行实例.\",\n        \"LIST-MESSAGE-EMPTY\": \"没有匹配到决策表执行实例\",\n        \"FILTER\": {\n            \"DEFINITION-ID\": \"定义ID\",\n            \"PROCESS-INSTANCE-ID\": \"流程实例ID\",\n            \"CASE-INSTANCE-ID\": \"Case实例ID\",\n            \"TENANTID\": \"租户标识符\"\n        },\n        \"SORT\": {\n            \"START-TIME\": \"开始时间\",\n            \"END-TIME\": \"结束时间\",\n            \"TENANT-ID\": \"租户ID\"\n        },\n        \"HEADER\": {\n            \"ID\": \"ID\",\n            \"DECISION-DEFINITION-KEY\": \"决策Key\",\n            \"DECISION-DEFINITION-NAME\": \"决策名称\",\n            \"FAILED\": \"失败\",\n            \"END-TIME\": \"结束时间\",\n            \"TENANT-ID\": \"租户ID\"\n        }\n    },\n    \"DECISION-TABLE-EXECUTION\": {\n        \"TITLE\": \"Decision table execution\",\n        \"LIST-MESSAGE\": \"显示{{size}} 条结果,总计{{total}}个匹配到的决策表。\",\n        \"LIST-MESSAGE-EMPTY\": \"没有匹配到决策表。\",\n        \"DEFINITION-ID\": \"决策定义ID\",\n        \"DEPLOYMENT-ID\": \"部署ID\",\n        \"DEFINITION-KEY\": \"决策Key\",\n        \"DEFINITION-NAME\": \"决策名称\",\n        \"DEFINITION-VERSION\": \"决策版本\",\n        \"PROCESS-INSTANCE-ID\": \"流程实例ID\",\n        \"CASE-INSTANCE-ID\": \"Case实例ID\",\n        \"EXECUTION-START-TIME\": \"开始时间\",\n        \"EXECUTION-END-TIME\": \"结束时间\",\n        \"FAILED\": \"失败\",\n        \"FILTER\": {\n            \"DEFINITION-ID\": \"Definition ID\",\n            \"PROCESS-INSTANCE-ID\": \"流程实例 ID\",\n            \"CASE-INSTANCE-ID\": \"Case实例ID\",\n            \"TENANTID\": \"租户标识符\"\n        },\n        \"SORT\": {\n            \"START-TIME\": \"开始时间\",\n            \"END-TIME\": \"结束时间\",\n            \"TENANT-ID\": \"租户ID\"\n        },\n        \"HEADER\": {\n            \"ID\": \"ID\",\n            \"DECISION-DEFINITION-ID\": \"Definition ID\",\n            \"DECISION-KEY\": \"Decision Key\",\n            \"PROCESS-INSTANCE-ID\": \"流程实例 ID\",\n            \"CASE-INSTANCE-ID\": \"Case实例ID\",\n            \"FAILED\": \"失败\",\n            \"START-TIME\": \"开始时间\",\n            \"END-TIME\": \"结束时间\",\n            \"TENANT-ID\": \"租户ID\"\n        },\n        \"AUDIT-DATA\": {\n            \"HEADER\": \"审计数据\",\n            \"HIT-POLICY\": \"命中策略\",\n            \"STRICT-MODE\": \"启用严格模式\",\n            \"EXCEPTION-MESSAGE\": \"异常消息\",\n            \"VALIDATION-MESSAGE\": \"验证消息\",\n            \"RESULT\": \"结果\",\n            \"RULE-EXECUTIONS\": \"规则执行实例对象\",\n            \"INPUT-VARIABLES\": \"输入变量\",\n            \"VARIABLE-KEY\": \"Key\",\n            \"VARIABLE-VALUE\": \"值\"\n        }\n    },\n    \"FORM-DEFINITIONS\": {\n    \t\"TITLE\": \"表单定义\",\n        \"LIST-MESSAGE\": \"显示{{size}} 条结果,总计{{total}}个匹配到的表单定义.\",\n        \"LIST-MESSAGE-EMPTY\": \"没有匹配到表单定义\",\n        \"HEADER\": {\n            \"ID\": \"ID\",\n            \"NAME\": \"名称\",\n            \"DEPLOYMENTID\": \"部署ID\",\n            \"TENANTID\": \"租户ID\",\n            \"KEY\": \"Key\",\n            \"VERSION\": \"版本\"\n        },\n        \"FILTER\": {\n            \"NAME\": \"名称\",\n            \"APPID\": \"应用程序部署ID\",\n            \"TENANTID\": \"租户标识符\"\n        },\n        \"SORT\": {\n            \"ID\": \"ID\",\n            \"NAME\": \"名称\"\n        }\n    },\n    \"FORM-DEFINITION\": {\n        \"ID\": \"ID:\",\n        \"NAME\": \"名称:\",\n        \"KEY\": \"Key:\",\n        \"CATEGORY\": \"分类:\",\n        \"PARENT-DEPLOYMENT-ID\": \"父部署ID:\",\n        \"DEPLOYMENT-ID\": \"部署ID:\",\n        \"DESCRIPTION\": \"描述:\",\n        \"TENANT\": \"租户:\",\n        \"MESSAGE-EMPTY\": \"(None)\",\n        \"TITLE\": {\n            \"FORM-INSTANCES\": \"表单实例\"\n        },\n        \"FORM-INSTANCES-MESSAGE\": \"这个定义有{{total}}个表单实例, 显示 {{size}}.\",\n        \"FORM-INSTANCES-MESSAGE-EMPTY\": \"这个定义没有表单实例\",\n        \"ACTION\": {\n            \"EDIT-CATEGORY\": \"编辑分类\",\n            \"SHOW-ALL-JOBS\": \"显示所有的jobs\",\n            \"SHOW-ALL-PROCESSES\": \"显示所有的流程\",\n            \"SHOW-DIAGRAM\": \"显示流程图片\",\n            \"SHOW-FORM\": \"显示表单\"\n        },\n        \"POPUP\": {\n            \"TITLE\": \"表单: \"\n        },\n        \"FIELD-PREVIEW\" : {\n        \t\"DISPLAY-REF\": \"显示值\",\n        \t\"SELECT-FIELD\": \"(没有选择字段)\",\n        \t\"FIELD-VALUE\": \"显示\\\"{{name}}\\\" 字段值\",\n        \t\"UNKNOWN-TYPE\": \"未知字段类型 {{type}}\",\n        \t\"TEXT-VALUE\": \"文本\",\n        \t\"MULTI-TEXT-VALUE\": \"多行文本\",\n        \t\"NUMBER-VALUE\": \"123\",\n        \t\"DATE-VALUE\": \"日期\",\n        \t\"DROPDOWN-VALUE\": \"选择...\",\n        \t\"UPLOAD-VALUE\": \"上传或者导入content...\",\n        \t\"RADIOS-OPTION1\": \"选择 1\",\n        \t\"SELECT-PERSON\": \"选择一个人\",\n        \t\"SELECT-GROUP\": \"选择一个组\"\n        \t}\n    },\n    \"FORM-DEPLOYMENTS\": {\n        \"TITLE\": \"表单部署对象\",\n        \"LIST-MESSAGE\": \"显示{{size}} 条结果,总计{{total}}个匹配到的表单部署对象\",\n        \"LIST-MESSAGE-EMPTY\": \"没有匹配到表单部署对象。\",\n        \"FILTER\": {\n            \"NAME\": \"名称(case sensitive)\",\n            \"TENANTID\": \"租户标识符(case sensitive)\"\n        },\n        \"SORT\": {\n            \"ID\": \"ID\",\n            \"NAME\": \"名称\"\n        },\n        \"HEADER\": {\n            \"ID\": \"ID\",\n            \"NAME\": \"名称\",\n            \"DEPLOY-TIME\": \"部署时间\",\n            \"CATEGORY\": \"分类\",\n            \"TENANT\": \"租户\"\n        },\n        \"ACTION\": {\n            \"DELETE\": \"删除部署\"\n        }\n    },\n    \"FORM-DEPLOYMENT\": {\n        \"ID\": \"ID:\",\n        \"NAME\": \"名称:\",\n        \"TIME\": \"部署时间:\",\n        \"CATEGORY\": \"分类:\",\n        \"TENANTID\": \"租户标识符:\",\n        \"PARENT-DEPLOYMENT-ID\": \"父部署ID\",\n        \"DEFINITIONS-MESSAGE\": \"这个部署有{{total}}个表单定义, 显示 {{size}}.\",\n        \"DEFINITIONS-MESSAGE-EMPTY\": \"这个部署没有表单定义。\",\n        \"TITLE\": {\n            \"FORM-DEFINITIONS\": \"表单定义\",\n            \"RESOURCES\": \"Resources\"\n        },\n        \"ACTION\": {\n            \"SHOW-ALL-DEFINITIONS\": \"显示所有的表单定义\"\n        }\n    },\n    \"FORM-INSTANCES\": {\n        \"TITLE\": \"表单实例\",\n        \"LIST-MESSAGE\": \"显示{{size}} 条结果,总计{{total}}个匹配到的表单实例\",\n        \"LIST-MESSAGE-EMPTY\": \"没有匹配的表单实例。\",\n        \"HEADER\": {\n            \"ID\": \"ID\",\n            \"PROCESS-INSTANCE-ID\": \"流程实例ID\",\n            \"CASE-INSTANCE-ID\": \"Case实例ID\",\n            \"TASK-ID\": \"任务ID\",\n            \"SUBMITTED-ON\": \"提交日期\",\n            \"SUBMITTED-BY\": \"Submitted By\",\n            \"TENANT-ID\": \"租户ID\"\n        },\n        \"FILTER\": {\n            \"NAME\": \"名称\",\n            \"TENANTID\": \"租户标识符\"\n        },\n        \"SORT\": {\n            \"SUBMITTED-DATE\": \"Submitted On\"\n        }\n    },\n    \"FORM-INSTANCE\": {\n        \"HEADER\": {\n            \"ID\": \"ID\",\n            \"TASK-ID\": \"任务ID\",\n            \"PROCESS-ID\": \"流程实例ID\",\n            \"CASE-INSTANCE-ID\": \"Case实例ID\",\n            \"SUBMITTED\": \"Submitted on\",\n            \"SUBMITTED-BY\": \"Submitted by\",\n            \"FORM-DEFINITION-ID\": \"表单定义ID\"\n        },\n        \"FORM-FIELD-VALUES-MESSAGE\": \"这个实例有{{total}}个表单字段值, 显示 {{size}}\",\n        \"FORM-FIELD-VALUES-MESSAGE-EMPTY\": \"这个实例没有表单字段值\",\n        \"ACTION\": {\n            \"SHOW-FORM-INSTANCE\": \"显示表单实例\"\n        },\n        \"TITLE\": {\n            \"FORM-FIELD-VALUES\": \"表单字段值\"\n        },\n        \"FORM-FIELD-VALUES\": {\n            \"ID\": \"表单字段ID\",\n            \"NAME\": \"表单字段名称\",\n            \"TYPE\": \"表单字段类别\",\n            \"VALUE\": \"表单字段值\"\n        }\n    },\n    \"CONTENT-ITEMS\": {\n        \"TITLE\": \"Content items\",\n        \"LIST-MESSAGE\": \"显示{{size}} 条结果,总计{{total}}个匹配到的content主题。\",\n        \"LIST-MESSAGE-EMPTY\": \"没有匹配到的content主题。\",\n        \"HEADER\": {\n            \"ID\": \"ID\",\n            \"NAME\": \"名称\",\n            \"PROCESS-INSTANCE-ID\": \"流程实例ID\",\n            \"TASK-ID\": \"任务ID\",\n            \"LAST-MODIFIED-ON\": \"最后修改日期\",\n            \"LAST-MODIFIED-BY\": \"最后修改\",\n            \"TENANT-ID\": \"租户ID\"\n        },\n        \"FILTER\": {\n            \"NAME\": \"名称\",\n            \"TENANTID\": \"租户标识符\"\n        },\n        \"SORT\": {\n            \"CREATED\": \"已经创建\"\n        }\n    },\n    \"CONTENT-ITEM\": {\n        \"HEADER\": {\n            \"ID\": \"ID\",\n            \"TASK-ID\": \"任务ID\",\n            \"PROCESS-INSTANCE-ID\": \"流程实例ID\",\n            \"CREATED-ON\": \"已经创建\",\n            \"CREATED-BY\": \"创建\",\n            \"LAST-MODIFIED-ON\": \"最后修改日期\",\n            \"LAST-MODIFIED-BY\": \"最后修改\",\n            \"CONTENT-STORE-ID\": \"Content存储ID\"\n        },\n        \"ACTION\": {\n            \"SHOW-CONTENT-ITEM\": \"显示content主题\"\n        }\n    }\n}\n"
  },
  {
    "path": "flowable-ui-web/admin/index.html",
    "content": "<!doctype html>\n<!--[if lt IE 7]>      <html class=\"no-js lt-ie9 lt-ie8 lt-ie7\"> <![endif]-->\n<!--[if IE 7]>         <html class=\"no-js lt-ie9 lt-ie8\"> <![endif]-->\n<!--[if IE 8]>         <html class=\"no-js lt-ie9\"> <![endif]-->\n<!--[if gt IE 8]><!--> <html class=\"no-js\"> <!--<![endif]-->\n    <head>\n        <meta charset=\"utf-8\"/>\n        <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n        <title>Flowable Admin</title>\n        <meta name=\"description\" content=\"\">\n        <meta name=\"viewport\" content=\"width=device-width\">\n        <meta name=\"theme-color\" content=\"#ffffff\">\n\n        <link rel=\"apple-touch-icon\" sizes=\"180x180\" href=\"images/apple-touch-icon.png?v=Om5N75Y123\">\n        <link rel=\"icon\" type=\"image/png\" href=\"images/favicon-32x32.png?v=Om5N75Y123\" sizes=\"32x32\">\n        <link rel=\"icon\" type=\"image/png\" href=\"images/favicon-16x16.png?v=Om5N75Y123\" sizes=\"16x16\">\n        <link rel=\"manifest\" href=\"manifest.json\">\n        <link rel=\"mask-icon\" href=\"images/safari-pinned-tab.svg?v=Om5N75Y123\" color=\"#506d75\">\n        <link rel=\"shortcut icon\" href=\"favicon.ico?v=Om5N75Y123\">\n\n        <link href=\"styles/bootstrap.min.css\" rel=\"stylesheet\" >\n        <link href=\"additional_components/angular-ui-select2/select2.css\" rel=\"stylesheet\" >\n        <link href=\"additional_components/ng-grid/ng-grid-2.0.14.min.css\" rel=\"stylesheet\" >\n        <link href=\"additional_components/ui-grid/ui-grid.min.css\" rel=\"stylesheet\" >\n        <link href=\"bower_components/json-formatter/json-formatter.min.css\" rel=\"stylesheet\" >\n        <link href=\"styles/style.css\" rel=\"stylesheet\" >\n\n        <!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries -->\n        <!-- WARNING: Respond.js doesn't work if you view the page via file:// -->\n        <!--[if lt IE 9]>\n        <script src=\"https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js\"></script>\n        <script src=\"https://oss.maxcdn.com/libs/respond.js/1.3.0/respond.min.js\"></script>\n        <![endif]-->\n    </head>\n    <body ng-app=\"flowableAdminApp\">\n        <div class=\"navbar navbar-fixed-top navbar-inverse\" role=\"navigation\" ng-show=\"authenticated\" ng-cloak>\n            <div class=\"container\">\n                <!-- Profile/user -->\n                <div ng-show=\"authenticated\" class=\"btn-group btn-group-sm pull-right\">\n                    <button type=\"button\" class=\"btn btn-default dropdown-toggle\" data-toggle=\"dropdown\">\n                        {{account.fullName}}\n                        <span class=\"caret\"></span>\n                    </button>\n                    <ul class=\"dropdown-menu\">\n                        <li><a href=\"#engine\" translate=\"GENERAL.MENU.CONFIGURATION\"></a></li>\n                        <li><a href=\"\" ng-click=\"logout()\" translate=\"GENERAL.ACTION.LOGOUT\"></a></li>\n                    </ul>\n                </div>\n                <div class=\"navbar-header pull-right\">\n                    <a class=\"navbar-brand\" title=\"{{'GENERAL.MAIN-TITLE' | translate}}\"><span class=\"sr-only\">{{'GENERAL.TITLE.MAIN' | translate}}</span></a>\n                </div>\n                <div class=\"collapse navbar-collapse\">\n                    <ul class=\"nav navbar-nav\" ng-show=\"authenticated\">\n                        <li ng-class=\"{'active-process': navigation.main == 'process-engine'}\"><a href=\"#process-engine\" translate=\"GENERAL.MENU.PROCESS-ENGINE\"></a></li>\n                        <li ng-class=\"{'active-cmmn': navigation.main == 'cmmn-engine'}\"><a href=\"#cmmn-engine\" translate=\"GENERAL.MENU.CMMN-ENGINE\"></a></li>\n                        <li ng-class=\"{'active-app': navigation.main == 'app-engine'}\"><a href=\"#app-engine\" translate=\"GENERAL.MENU.APP-ENGINE\"></a></li>\n                        <li ng-class=\"{'active-form': navigation.main == 'form-engine'}\"><a href=\"#form-engine\" translate=\"GENERAL.MENU.FORM-ENGINE\"></a></li>\n                        <li ng-class=\"{'active-dmn': navigation.main == 'dmn-engine'}\"><a href=\"#dmn-engine\" translate=\"GENERAL.MENU.DMN-ENGINE\"></a></li>\n                        <li ng-class=\"{'active-content': navigation.main == 'content-engine'}\"><a href=\"#content-engine\" translate=\"GENERAL.MENU.CONTENT-ENGINE\"></a></li>\n                    </ul>\n                </div>\n                <div class=\"sub-navbar\" ng-class=\"{'active-process': navigation.main == 'process-engine', 'active-cmmn': navigation.main == 'cmmn-engine', 'active-app': navigation.main == 'app-engine', 'active-form': navigation.main == 'form-engine', 'active-dmn': navigation.main == 'dmn-engine', 'active-content': navigation.main == 'content-engine'}\">\n                    <div class=\"collapse navbar-collapse\">\n                        <ul class=\"nav navbar-nav\" ng-if=\"navigation.main == 'process-engine'\">\n                            <li ng-class=\"{'active': navigation.sub == 'deployments'}\"><a href=\"#deployments\" translate=\"GENERAL.MENU.DEPLOYMENTS\"></a></li>\n                            <li ng-class=\"{'active': navigation.sub == 'definitions'}\"><a href=\"#process-definitions\" translate=\"GENERAL.MENU.DEFINITIONS\"></a></li>\n                            <li ng-class=\"{'active': navigation.sub == 'instances'}\"><a href=\"#process-instances\" translate=\"GENERAL.MENU.INSTANCES\"></a></li>\n                            <li ng-class=\"{'active': navigation.sub == 'tasks'}\"><a href=\"#tasks\" translate=\"GENERAL.MENU.TASKS\"></a></li>\n                            <li ng-class=\"{'active': navigation.sub == 'jobs'}\"><a href=\"#jobs\" translate=\"GENERAL.MENU.JOBS\"></a></li>\n                            <li ng-class=\"{'active': navigation.sub == 'event-subscriptions'}\"><a href=\"#event-subscriptions\" translate=\"GENERAL.MENU.EVENT-SUBSCRIPTIONS\"></a></li>\n                        </ul>\n                        <ul class=\"nav navbar-nav\" ng-if=\"navigation.main == 'cmmn-engine'\">\n                            <li ng-class=\"{'active': navigation.sub == 'deployments'}\"><a href=\"#cmmn-deployments\" translate=\"GENERAL.MENU.DEPLOYMENTS\"></a></li>\n                            <li ng-class=\"{'active': navigation.sub == 'definitions'}\"><a href=\"#case-definitions\" translate=\"GENERAL.MENU.DEFINITIONS\"></a></li>\n                            <li ng-class=\"{'active': navigation.sub == 'instances'}\"><a href=\"#case-instances\" translate=\"GENERAL.MENU.INSTANCES\"></a></li>\n                            <li ng-class=\"{'active': navigation.sub == 'tasks'}\"><a href=\"#cmmn-tasks\" translate=\"GENERAL.MENU.TASKS\"></a></li>\n                            <li ng-class=\"{'active': navigation.sub == 'jobs'}\"><a href=\"#cmmn-jobs\" translate=\"GENERAL.MENU.JOBS\"></a></li>\n                        </ul>\n                        <ul class=\"nav navbar-nav\" ng-if=\"navigation.main == 'app-engine'\">\n                            <li ng-class=\"{'active': navigation.sub == 'deployments'}\"><a href=\"#app-deployments\" translate=\"GENERAL.MENU.DEPLOYMENTS\"></a></li>\n                            <li ng-class=\"{'active': navigation.sub == 'definitions'}\"><a href=\"#app-definitions\" translate=\"GENERAL.MENU.DEFINITIONS\"></a></li>\n                        </ul>\n                        <ul class=\"nav navbar-nav\" ng-if=\"navigation.main == 'form-engine'\">\n                            <li ng-class=\"{active: navigation.sub == 'deployments'}\"><a href=\"#form-deployments\" translate=\"GENERAL.MENU.DEPLOYMENTS\"></a></li>\n                            <li ng-class=\"{active: navigation.sub == 'definitions'}\"><a href=\"#form-definitions\" translate=\"GENERAL.MENU.DEFINITIONS\"></a></li>\n                            <li ng-class=\"{active: navigation.sub == 'instances'}\"><a href=\"#form-instances\" translate=\"GENERAL.MENU.INSTANCES\"></a></li>\n                        </ul>\n                        <ul class=\"nav navbar-nav\" ng-if=\"navigation.main == 'dmn-engine'\">\n                            <li ng-class=\"{active: navigation.sub == 'deployments'}\"><a href=\"#decision-table-deployments\" translate=\"GENERAL.MENU.DEPLOYMENTS\"></a></li>\n                            <li ng-class=\"{active: navigation.sub == 'decision-tables'}\"><a href=\"#decision-tables\" translate=\"GENERAL.MENU.DECISION-TABLES\"></a></li>\n                            <li ng-class=\"{active: navigation.sub == 'executions'}\"><a href=\"#decision-table-executions\" translate=\"GENERAL.MENU.DECISION-TABLE-EXECUTIONS\"></a></li>\n                        </ul>\n                        <ul class=\"nav navbar-nav\" ng-if=\"navigation.main == 'content-engine'\">\n                            <li ng-class=\"{active: navigation.sub == 'content-items'}\"><a href=\"#content-items\" translate=\"GENERAL.MENU.CONTENT-ITEMS\"></a></li>\n                        </ul>\n                    </div>\n                </div>\n\n                <!-- /.nav-collapse -->\n\n            </div><!-- /.container -->\n        </div><!-- /.navbar -->\n\n\t\t<div class=\"alert-wrapper\" ng-cloak>\n\t\t\t<div class=\"alert fadein {{alerts.current.type}}\" ng-show=\"alerts.current\" ng-click=\"dismissAlert()\">\n\t\t\t\t<i class=\"glyphicon\" ng-class=\"{'glyphicon-ok': alerts.current.type == 'info', 'glyphicon-remove': alerts.current.type == 'error'}\"></i>\n\t\t\t\t<span>{{alerts.current.message}}</span>\n\t\t\t\t<div class=\"pull-right\" ng-show=\"alerts.queue.length > 0\">\n\t\t\t\t\t<span class=\"badge\">{{alerts.queue.length + 1}}</span>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</div>\n\n        <div ng-view=\"\" ng-show=\"serverLoaded || authenticated\" ng-cloak></div>\n        <script type=\"text/ng-template\" id=\"userItemTemplate.html\"><a typeahead-scroll-item=\"$parent.$index\"><span class=\"glyphicon glyphicon-user\"></span><span class=\"user-label\" bind-html-unsafe=\"match.label | typeaheadHighlight:query\"></span></a></script>\n\n        <!-- build:js scripts/scripts.js -->\n        <script src=\"bower_components/modernizr/modernizr.js\"></script>\n        <script src=\"bower_components/jquery/jquery.js\"></script>\n        <script src=\"additional_components/angular-ui-select2/select2.min.js\"></script>\n        <script src=\"bower_components/angular/angular.min.js\"></script>\n        <script src=\"bower_components/ng-file-upload/ng-file-upload-shim.js\" ></script>\n        <script src=\"bower_components/ng-file-upload/ng-file-upload.min.js\" ></script>\n        <script src=\"bower_components/momentjs/momentjs.min.js\"></script>\n        <script src=\"bower_components/angular-route/angular-route.min.js\"></script>\n        <script src=\"bower_components/angular-resource/angular-resource.min.js\"></script>\n        <script src=\"bower_components/angular-cookies/angular-cookies.min.js\"></script>\n        <script src=\"bower_components/angular-sanitize/angular-sanitize.min.js\"></script>\n        <script src=\"bower_components/angular-translate/angular-translate.min.js\"></script>\n        <script src=\"bower_components/angular-bootstrap/ui-bootstrap.min.js\"></script>\n        <script src=\"bower_components/angular-bootstrap/ui-bootstrap-tpls.min.js\"></script>\n        <script src=\"bower_components/angular-translate-storage-cookie/angular-translate-storage-cookie.min.js\"></script>\n        <script src=\"bower_components/angular-translate-loader-static-files/angular-translate-loader-static-files.min.js\"></script>\n        <script src=\"bower_components/angular-ui-utils/ui-utils.min.js\"></script>\n        <script src=\"additional_components/angular-ui-select2/angular-ui-select2.js\"></script>\n        <script src=\"additional_components/ng-grid/ng-grid-2.0.14.min.js\"></script>\n        <script src=\"additional_components/ui-grid/ui-grid.min.js\"></script>\n        <script src=\"bower_components/sass-bootstrap/js/affix.js\"></script>\n        <script src=\"bower_components/sass-bootstrap/js/alert.js\"></script>\n        <script src=\"bower_components/sass-bootstrap/js/dropdown.js\"></script>\n        <script src=\"bower_components/sass-bootstrap/js/tooltip.js\"></script>\n        <script src=\"bower_components/sass-bootstrap/js/modal.js\"></script>\n        <script src=\"bower_components/sass-bootstrap/js/transition.js\"></script>\n        <script src=\"bower_components/sass-bootstrap/js/button.js\"></script>\n        <script src=\"bower_components/sass-bootstrap/js/popover.js\"></script>\n        <script src=\"bower_components/sass-bootstrap/js/carousel.js\"></script>\n        <script src=\"bower_components/sass-bootstrap/js/scrollspy.js\"></script>\n        <script src=\"bower_components/sass-bootstrap/js/collapse.js\"></script>\n        <script src=\"bower_components/sass-bootstrap/js/tab.js\"></script>\n        <script src=\"bower_components/json-formatter/json-formatter.min.js\"></script>\n\n\n        <script src=\"scripts/config.js\"></script>\n        <script src=\"scripts/utils.js\"></script>\n        <script src=\"scripts/app.js\"></script>\n        <script src=\"scripts/recursion-helper.js\"></script>\n        <script src=\"scripts/controllers.js\"></script>\n        <script src=\"scripts/deployments-controllers.js\"></script>\n        <script src=\"scripts/deployment-controllers.js\"></script>\n        <script src=\"scripts/process-definitions-controllers.js\"></script>\n        <script src=\"scripts/process-definition-controllers.js\"></script>\n        <script src=\"scripts/process-instances-controllers.js\"></script>\n        <script src=\"scripts/process-instance-controllers.js\"></script>\n        <script src=\"scripts/tasks-controllers.js\"></script>\n        <script src=\"scripts/task-controllers.js\"></script>\n        <script src=\"scripts/engine-controller.js\"></script>\n        <script src=\"scripts/jobs-controllers.js\"></script>\n        <script src=\"scripts/job-controllers.js\"></script>\n        <script src=\"scripts/event-subscriptions-controllers.js\"></script>\n        <script src=\"scripts/event-subscription-controllers.js\"></script>\n        <script src=\"scripts/users-controllers.js\"></script>\n        <script src=\"scripts/services.js\"></script>\n        <script src=\"scripts/directives.js\"></script>\n        <script src=\"scripts/constants.js\"></script>\n        <script src=\"scripts/cmmn-deployments-controllers.js\"></script>\n        <script src=\"scripts/cmmn-deployment-controllers.js\"></script>\n        <script src=\"scripts/case-definitions-controllers.js\"></script>\n        <script src=\"scripts/case-definition-controllers.js\"></script>\n        <script src=\"scripts/case-instances-controllers.js\"></script>\n        <script src=\"scripts/case-instance-controllers.js\"></script>\n        <script src=\"scripts/cmmn-tasks-controllers.js\"></script>\n        <script src=\"scripts/cmmn-task-controllers.js\"></script>\n        <script src=\"scripts/cmmn-jobs-controllers.js\"></script>\n        <script src=\"scripts/cmmn-job-controllers.js\"></script>\n        <script src=\"scripts/app-deployments-controllers.js\"></script>\n        <script src=\"scripts/app-deployment-controllers.js\"></script>\n        <script src=\"scripts/app-definitions-controllers.js\"></script>\n        <script src=\"scripts/app-definition-controllers.js\"></script>\n        <script src=\"scripts/decision-table-deployments-controllers.js\"></script>\n        <script src=\"scripts/decision-table-deployment-controllers.js\"></script>\n        <script src=\"scripts/decision-tables-controllers.js\"></script>\n        <script src=\"scripts/decision-table-controllers.js\"></script>\n        <script src=\"scripts/decision-table-executions-controllers.js\"></script>\n        <script src=\"scripts/decision-table-execution-controllers.js\"></script>\n        <script src=\"scripts/form-deployments-controllers.js\"></script>\n        <script src=\"scripts/form-deployment-controllers.js\"></script>\n        <script src=\"scripts/form-definitions-controllers.js\"></script>\n        <script src=\"scripts/form-definition-controllers.js\"></script>\n        <script src=\"scripts/form-instances-controllers.js\"></script>\n        <script src=\"scripts/form-instance-controllers.js\"></script>\n        <script src=\"scripts/content-items-controllers.js\"></script>\n        <script src=\"scripts/content-item-controllers.js\"></script>\n        <!-- endbuild -->\n</body>\n</html>\n"
  },
  {
    "path": "flowable-ui-web/admin/manifest.json",
    "content": "{\n\t\"name\": \"\",\n\t\"icons\": [\n\t\t{\n\t\t\t\"src\": \"images\\/android-chrome-192x192.png?v=Om5N75Y123\",\n\t\t\t\"sizes\": \"192x192\",\n\t\t\t\"type\": \"image\\/png\"\n\t\t},\n\t\t{\n\t\t\t\"src\": \"images\\/android-chrome-384x384.png?v=Om5N75Y123\",\n\t\t\t\"sizes\": \"256x256\",\n\t\t\t\"type\": \"image\\/png\"\n\t\t}\n\t],\n\t\"theme_color\": \"#ffffff\",\n\t\"display\": \"standalone\"\n}\n"
  },
  {
    "path": "flowable-ui-web/admin/scripts/app-definition-controllers.js",
    "content": "/* Copyright 2005-2015 Alfresco Software, Ltd.\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'use strict';\n\nflowableAdminApp.controller('AppDefinitionController', ['$scope', '$rootScope', '$http', '$timeout','$location','$routeParams', '$modal', '$translate', '$q', 'gridConstants',\n    function ($scope, $rootScope, $http, $timeout, $location, $routeParams, $modal, $translate, $q, gridConstants) {\n\n        $rootScope.navigation = {main: 'app-engine', sub: 'definitions'};\n\n        $scope.tabData = {\n\t\t    tabs: [\n\t\t       {id: 'processDefinitions', name: 'APP-DEFINITION.TITLE.PROCESS-DEFINITIONS'},\n\t\t       {id: 'caseDefintions', name: 'APP-DEFINITION.TITLE.CASE-DEFINITIONS'},\n\t\t       {id: 'decisionTables', name: 'APP-DEFINITION.TITLE.DECISION-TABLES'},\n\t\t       {id: 'formDefinitions', name: 'APP-DEFINITION.TITLE.FORM-DEFINITIONS'}\n\t\t    ]\n\t\t};\n\t\t$scope.tabData.activeTab = $scope.tabData.tabs[0].id;\n\n\t\t$scope.returnToList = function() {\n\t\t\t$location.path(\"/app-definitions\");\n\t\t};\n\n\t\t$scope.openDefinition = function(definitionId) {\n\t\t\tif (definitionId) {\n\t\t\t\t$location.path(\"/app-definition/\" + definitionId);\n\t\t\t}\n\t\t};\n\n\n\t\t$scope.openDeployment = function(deploymentId) {\n\t\t    if (deploymentId) {\n\t\t        $location.path(\"/app-deployment/\" + deploymentId);\n\t\t    }\n\t\t};\n\n        $scope.openProcessDefinition = function(processDefinition) {\n          if (processDefinition && processDefinition.getProperty('id')) {\n            $location.path(\"/process-definition/\" + processDefinition.getProperty('id'));\n          }\n        };\n        \n        $scope.openCaseDefinition = function(caseDefinition) {\n          if (caseDefinition && caseDefinition.getProperty('id')) {\n            $location.path(\"/case-definition/\" + caseDefinition.getProperty('id'));\n          }\n        };\n    \n        $scope.openFormDefinition = function (formDefinition) {\n            if (formDefinition && formDefinition.getProperty('id')) {\n                $location.path(\"/form-definition/\" + formDefinition.getProperty('id'));\n            }\n        };\n        \n        $scope.openDecisionTable = function (decisionTable) {\n            if (decisionTable && decisionTable.getProperty('id')) {\n                $location.path(\"/decision-table/\" + decisionTable.getProperty('id'));\n            }\n        };\n        \n        $scope.loadProcessDefinitions = function() {\n            $scope.processDefinitions = undefined;\n            $http({method: 'GET', url: FlowableAdmin.webContextRoot + '/app/rest/admin/app-definitions/' + $scope.definition.id +'/process-definitions?deploymentId=' + $scope.definition.deploymentId}).\n            success(function(data, status, headers, config) {\n                $scope.processDefinitions = data;\n                $scope.tabData.tabs[0].info = data.total;\n            });\n        };\n    \n        $scope.loadCaseDefinitions = function() {\n            $scope.caseDefinitions = undefined;\n            $http({method: 'GET', url: FlowableAdmin.webContextRoot + '/app/rest/admin/app-definitions/' + $scope.definition.id +'/case-definitions?deploymentId=' + $scope.definition.deploymentId}).\n            success(function(data, status, headers, config) {\n                $scope.caseDefinitions = data;\n                $scope.tabData.tabs[1].info = data.total;\n            });\n        };\n        \n        $scope.loadDecisionTables = function() {\n            $scope.decisionTables = undefined;\n            $http({method: 'GET', url: FlowableAdmin.webContextRoot + '/app/rest/admin/app-definitions/'+ $scope.definition.id + '/decision-tables?deploymentId=' + $scope.definition.deploymentId}).\n            success(function(data, status, headers, config) {\n                $scope.decisionTables = data;\n                $scope.tabData.tabs[2].info = data.total;\n            }).\n            error(function(data, status, headers, config) {\n            });\n        };\n        \n        $scope.loadFormDefinitions = function() {\n            $scope.formDefinitions = undefined;\n            $http({method: 'GET', url: FlowableAdmin.webContextRoot + '/app/rest/admin/app-definitions/'+ $scope.definition.id + '/form-definitions?deploymentId=' + $scope.definition.deploymentId}).\n            success(function(data, status, headers, config) {\n                $scope.formDefinitions = data;\n                $scope.tabData.tabs[3].info = data.total;\n            }).\n            error(function(data, status, headers, config) {\n            });\n        };\n\n\t\t$scope.executeWhenReady(function() {\n\t\t    // Load definition\n\t\t    $http({method: 'GET', url: FlowableAdmin.webContextRoot + '/app/rest/admin/app-definitions/' + $routeParams.definitionId}).\n\t\t    success(function(data, status, headers, config) {\n\t\t        $scope.definition = data;\n\t\t        $scope.loadProcessDefinitions();\n\t\t        $scope.loadCaseDefinitions();\n                $scope.loadDecisionTables();\n                $scope.loadFormDefinitions();\n\t\t    }).\n\t\t    error(function(data, status, headers, config) {\n\t\t        if (data && data.message) {\n                    // Extract error-message\n                    $rootScope.addAlert(data.message, 'error');\n                } else {\n                    // Use default error-message\n                    $rootScope.addAlert($translate.instant('ALERT.GENERAL.HTTP-ERROR'), 'error');\n                }\n\t\t    });\n\n            $q.all([$translate('PROCESS-DEFINITION.ID'),\n                  $translate('PROCESS-DEFINITION.NAME'),\n                  $translate('PROCESS-DEFINITION.KEY'),\n                  $translate('PROCESS-DEFINITION.CATEGORY')])\n            .then(function(headers) {\n                \n                $scope.gridProcessDefinitions = {\n                    data: 'processDefinitions.data',\n                    enableRowReordering: false,\n                    multiSelect: false,\n                    keepLastSelected : false,\n                    enableSorting: false,\n                    rowHeight: 36,\n                    afterSelectionChange: $scope.openProcessDefinition,\n                    columnDefs: [\n                        { field: 'id', displayName: headers[0], width: 75},\n                        { field: 'name', displayName: headers[1]},\n                        { field: 'key', displayName: headers[2]},\n                        { field: 'category', displayName: headers[3]}\n                    ]\n                };\n            });\n\n\t\t    $q.all([$translate('CASE-DEFINITION.ID'),\n                  $translate('CASE-DEFINITION.NAME'),\n                  $translate('CASE-DEFINITION.KEY'),\n                  $translate('CASE-DEFINITION.CATEGORY')])\n            .then(function(headers) {\n                \n                $scope.gridCaseDefinitions = {\n                    data: 'caseDefinitions.data',\n                    enableRowReordering: false,\n                    multiSelect: false,\n                    keepLastSelected : false,\n                    enableSorting: false,\n                    rowHeight: 36,\n                    afterSelectionChange: $scope.openCaseDefinition,\n                    columnDefs: [\n                        { field: 'id', displayName: headers[0], width: 75},\n                        { field: 'name', displayName: headers[1]},\n                        { field: 'key', displayName: headers[2]},\n                        { field: 'category', displayName: headers[3]}\n                    ]\n                };\n            });\n            \n            $q.all([$translate('DECISION-TABLE.ID'),\n                  $translate('DECISION-TABLE.NAME'),\n                  $translate('DECISION-TABLE.KEY'),\n                  $translate('DECISION-TABLE.CATEGORY')])\n            .then(function(headers) {\n                \n                $scope.gridDecisionTables = {\n                    data: 'decisionTables.data',\n                    enableRowReordering: false,\n                    multiSelect: false,\n                    keepLastSelected : false,\n                    enableSorting: false,\n                    rowHeight: 36,\n                    afterSelectionChange: $scope.openDecisionTable,\n                    columnDefs: [\n                        { field: 'id', displayName: headers[0], width: 75},\n                        { field: 'name', displayName: headers[1]},\n                        { field: 'key', displayName: headers[2]},\n                        { field: 'category', displayName: headers[3]}\n                    ]\n                };\n            });\n            \n            $q.all([$translate('FORM-DEFINITION.ID'),\n                  $translate('FORM-DEFINITION.NAME'),\n                  $translate('FORM-DEFINITION.KEY'),\n                  $translate('FORM-DEFINITION.CATEGORY')])\n            .then(function(headers) {\n                \n                $scope.gridFormDefinitions = {\n                    data: 'formDefinitions.data',\n                    enableRowReordering: false,\n                    multiSelect: false,\n                    keepLastSelected : false,\n                    enableSorting: false,\n                    rowHeight: 36,\n                    afterSelectionChange: $scope.openFormDefinition,\n                    columnDefs: [\n                        { field: 'id', displayName: headers[0], width: 75},\n                        { field: 'name', displayName: headers[1]},\n                        { field: 'key', displayName: headers[2]},\n                        { field: 'category', displayName: headers[3]}\n                    ]\n                };\n            });\n\t\t      \n\t\t});\n\n}]);\n"
  },
  {
    "path": "flowable-ui-web/admin/scripts/app-definitions-controllers.js",
    "content": "/* Copyright 2005-2015 Alfresco Software, Ltd.\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'use strict';\n\n/* Controllers */\n\nflowableAdminApp.controller('AppDefinitionsController', ['$rootScope', '$scope', '$http', '$timeout', '$location','$translate', '$q', '$modal', 'gridConstants',\n    function ($rootScope, $scope, $http, $timeout, $location, $translate, $q, $modal, gridConstants) {\n\n\t\t$rootScope.navigation = {main: 'app-engine', sub: 'definitions'};\n        \n\t\t$scope.filter = {};\n\t\t$scope.appDefinitionsData = {};\n\n\t\t// Array to contain selected properties (yes - we only can select one, but ng-grid isn't smart enough)\n\t    $scope.selectedDefinitions = [];\n\n\t    var filterConfig = {\n\t    \turl: FlowableAdmin.webContextRoot + '/app/rest/admin/app-definitions',\n\t    \tmethod: 'GET',\n\t    \tsuccess: function(data, status, headers, config) {\n\t    \t\t$scope.appDefinitionsData = data;\n            },\n            error: function(data, status, headers, config) {\n                if (data && data.message) {\n                    // Extract error-message\n                    $rootScope.addAlert(data.message, 'error');\n                } else {\n                    // Use default error-message\n                    $rootScope.addAlert($translate.instant('ALERT.GENERAL.HTTP-ERROR'), 'error');\n                }\n            },\n\n            sortObjects: [\n                {name: 'APP-DEFINITIONS.SORT.ID', id: 'id'},\n                {name: 'APP-DEFINITIONS.SORT.NAME', id: 'name'},\n                {name: 'APP-DEFINITIONS.SORT.VERSION', id: 'version'}\n            ],\n\n            supportedProperties: [\n                {id: 'nameLike', name: 'APP-DEFINITIONS.FILTER.NAME', showByDefault: false},\n                {id: 'keyLike', name: 'APP-DEFINITIONS.FILTER.KEY', showByDefault: true},\n                {id: 'deploymentId', name: 'APP-DEFINITIONS.FILTER.DEPLOYMENT-ID', showByDefault: false},\n                {id: 'tenantIdLike', name: 'APP-DEFINITIONS.FILTER.TENANT-ID', showByDefault: false},\n                {id: 'latest', name: 'APP-DEFINITIONS.FILTER.LATEST', showByDefault: true, defaultValue: true}\n            ]\n\t    };\n\n\t    if ($rootScope.filters.forced.appDefinitionFilter) {\n\t        // Always recreate the filter and add all properties\n\t        $scope.filter = new FlowableAdmin.Utils.Filter(filterConfig, $http, $timeout, $rootScope);\n\t        $rootScope.filters.appDefinitionFilter = $scope.filter;\n\n\t        for (var prop in $rootScope.filters.forced.appDefinitionFilter) {\n\t            $scope.filter.addProperty({id: prop}, $rootScope.filters.forced.appDefinitionFilter[prop]);\n\t            if (prop == 'deploymentId') {\n\t                $scope.filter.removeProperty({id: 'latest'});\n\t            }\n\t        }\n\n\t        $rootScope.filters.forced.appDefinitionFilter = undefined;\n\n\t    } else if ($rootScope.filters && $rootScope.filters.appDefinitionFilter) {\n\t    \t// Reuse the existing filter\n\t    \t$scope.filter = $rootScope.filters.appDefinitionFilter;\n\t    \t$scope.filter.config = filterConfig;\n\t    } else {\n\t\t    $scope.filter = new FlowableAdmin.Utils.Filter(filterConfig, $http, $timeout, $rootScope);\n\t\t    $rootScope.filters.appDefinitionFilter = $scope.filter;\n\t    }\n\n\t    $scope.definitionSelected = function(definition) {\n\t    \tif (definition && definition.getProperty('id')) {\n\t    \t\t$location.path('/app-definition/' + definition.getProperty('id'));\n\t    \t}\n\t    };\n\n\t    $scope.toggleLatestVersion = function() {\n\t      if($scope.filter.properties.latest === true) {\n\t        $scope.filter.properties.nameLike = undefined;\n\t        $scope.filter.properties.deploymentId = undefined;\n\t      }\n\n\t      $scope.filter.refresh();\n\t    };\n\n\t    $q.all([$translate('APP-DEFINITIONS.HEADER.ID'),\n              $translate('APP-DEFINITIONS.HEADER.NAME'),\n              $translate('APP-DEFINITIONS.HEADER.VERSION'),\n              $translate('APP-DEFINITIONS.HEADER.KEY'),\n              $translate('APP-DEFINITIONS.HEADER.TENANT')])\n              .then(function(headers) {\n\n          // Config for grid\n          $scope.gridDefinitions = {\n              data: 'appDefinitionsData.data',\n              enableRowReordering: true,\n              multiSelect: false,\n              keepLastSelected : false,\n              rowHeight: 36,\n              selectedItems: $scope.selectedDefinitions,\n              afterSelectionChange: $scope.definitionSelected,\n              columnDefs: [\n                  { field: 'id', displayName: headers[0], cellTemplate: gridConstants.defaultTemplate},\n                  { field: 'name', displayName: headers[1], cellTemplate: gridConstants.defaultTemplate},\n                  { field: 'version', displayName: headers[2], cellTemplate: gridConstants.defaultTemplate},\n                  { field: 'key', displayName: headers[3], cellTemplate: gridConstants.defaultTemplate},\n                  { field: 'tenantId', displayName: headers[4], cellTemplate: gridConstants.defaultTemplate}]\n          };\n       });\n\n\n\t   // Hook in initial fetching of the definitions\n\t   $scope.executeWhenReady(function() {\n\t       $scope.filter.refresh();\n\t   });\n        \n\n    }]);\n"
  },
  {
    "path": "flowable-ui-web/admin/scripts/app-deployment-controllers.js",
    "content": "/* 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'use strict';\n\nflowableAdminApp.controller('AppDeploymentController', ['$scope', '$rootScope', '$http', '$timeout','$location','$routeParams', '$modal', '$translate', '$q',\n    function ($scope, $rootScope, $http, $timeout, $location, $routeParams, $modal, $translate, $q) {\n\n        $rootScope.navigation = {main: 'app-engine', sub: 'deployments'};\n        \n\t\t$scope.returnToList = function() {\n\t\t\t$location.path(\"/app-deployments\");\n\t\t};\n\t\t\n\t\t$scope.openDefinition = function(definition) {\n\t\t\tif (definition && definition.getProperty('id')) {\n\t\t\t\t$location.path(\"/app-definition/\" + definition.getProperty('id'));\n\t\t\t}\n\t\t};\n\t\t\n\t\t$q.all([$translate('APP-DEFINITIONS.HEADER.ID'),\n            $translate('APP-DEFINITIONS.HEADER.NAME'),\n            $translate('APP-DEFINITIONS.HEADER.VERSION'),\n            $translate('APP-DEFINITIONS.HEADER.KEY')])\n            .then(function(headers) { \n        \n                $scope.gridAppDefinitions = {\n                    data: 'appDefinitions.data',\n                    enableRowReordering: false,\n                    multiSelect: false,\n                    keepLastSelected : false,\n                    enableSorting: false,\n                    rowHeight: 36,\n                    afterSelectionChange: $scope.openDefinition,\n                    columnDefs: [\n                          { field: 'id', displayName: headers[0]},\n                          { field: 'name', displayName: headers[1]},\n                          { field: 'version', displayName: headers[2]},\n                          { field: 'key', displayName: headers[3]}\n                    ]\n                };\n        });\n\t\t\n\t\t$scope.deleteDeployment = function() {\n\t\t    var modalInstance = $modal.open({\n                templateUrl: 'views/confirm-popup.html',\n                controller: 'ConfirmPopupCtrl',\n                resolve: {\n                    model: function () {\n                      return {\n                          confirm: $translate.instant('APP-DEPLOYMENTS.ACTION.DELETE'),\n                          title: $translate.instant('APP-DEPLOYMENTS.ACTION.DELETE'),\n                          message: $translate.instant('APP-DEPLOYMENTS.POPUP.DELETE.CONFIRM-MESSAGE', $scope.cmmnDeployment)\n                          };\n                    }\n                }\n                \n            });\n            \n            modalInstance.result.then(function (result) {\n                if (result === true) {\n                    $http({method: 'DELETE', url: FlowableAdmin.webContextRoot + '/app/rest/admin/app-deployments/' + $routeParams.deploymentId}).\n                    success(function(data, status, headers, config) {\n                        $scope.addAlert($translate.instant('ALERT.APP-DEPLOYMENT.DELETED-DEPLOYMENT', $scope.appDeployment), 'info');\n                        $scope.returnToList();\n                    }).\n                    error(function(data, status, headers, config) {\n                        $scope.addAlert($translate.instant('ALERT.APP-DEPLOYMENT.DELETE-ERROR', data), 'error');\n                    });\n                }\n            });\n            \n        };\n        \n\t\t$scope.executeWhenReady(function() {\n\t\t    // Load deployment\n\t\t    $http({method: 'GET', url: FlowableAdmin.webContextRoot + '/app/rest/admin/app-deployments/' + $routeParams.deploymentId}).\n  \t    \t    success(function(data, status, headers, config) {\n  \t    \t        $scope.appDeployment = data;\n  \t    \t    }).\n  \t    \t    error(function(data, status, headers, config) {\n                    if (data && data.message) {\n                        // Extract error-message\n                        $rootScope.addAlert(data.message, 'error');\n                    } else {\n                        // Use default error-message\n                        $rootScope.addAlert($translate.instant('ALERT.GENERAL.HTTP-ERROR'), 'error');\n                    }\n  \t    \t    });\n  \t\t\n\t\t    // Load case definitions\n\t\t    $http({method: 'GET', url: FlowableAdmin.webContextRoot + '/app/rest/admin/app-definitions?deploymentId=' + $routeParams.deploymentId}).\n  \t    \t    success(function(data, status, headers, config) {\n  \t    \t        $scope.appDefinitions = data;\n  \t    \t    });\n\t\t    \n  \t     });\n}]);"
  },
  {
    "path": "flowable-ui-web/admin/scripts/app-deployments-controllers.js",
    "content": "/* 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'use strict';\n\n/* Controllers */\n\nflowableAdminApp.controller('AppDeploymentsController', ['$rootScope', '$scope', '$http', '$timeout', '$location', '$translate', '$q', '$modal', 'gridConstants',\n    function ($rootScope, $scope, $http, $timeout, $location, $translate, $q, $modal, gridConstants) {\n\n\t\t$rootScope.navigation = {main: 'app-engine', sub: 'deployments'};\n        \n\t\t$scope.filter = {};\n\t\t$scope.appDeploymentsData = {};\n\n\t\t// Array to contain selected properties (yes - we only can select one, but ng-grid isn't smart enough)\n\t    $scope.selectedDeployments = [];\n\n\t    var filterConfig = {\n\t    \turl: FlowableAdmin.webContextRoot + '/app/rest/admin/app-deployments',\n\t    \tmethod: 'GET',\n\t    \tsuccess: function(data, status, headers, config) {\n\t    \t\t$scope.appDeploymentsData = data;\n            },\n            error: function(data, status, headers, config) {\n                if (data && data.message) {\n                    // Extract error-message\n                    $rootScope.addAlert(data.message, 'error');\n                } else {\n                    // Use default error-message\n                    $rootScope.addAlert($translate.instant('ALERT.GENERAL.HTTP-ERROR'), 'error');\n                }\n            },\n\n            sortObjects: [\n                {name: 'APP-DEPLOYMENTS.SORT.ID', id: 'id'},\n                {name: 'APP-DEPLOYMENTS.SORT.NAME', id: 'name'}\n            ],\n\n            supportedProperties: [\n                {id: 'nameLike', name: 'APP-DEPLOYMENTS.FILTER.NAME', showByDefault: true},\n                {id: 'tenantIdLike', name: 'APP-DEPLOYMENTS.FILTER.TENANTID', showByDefault: true}\n            ]\n\t    };\n\n\t    if($rootScope.filters && $rootScope.filters.appDeploymentFilter) {\n\t    \t// Reuse the existing filter\n\t    \t$scope.filter = $rootScope.filters.appDeploymentFilter;\n\t    \t$scope.filter.config = filterConfig;\n\t    } else {\n\t\t    $scope.filter = new FlowableAdmin.Utils.Filter(filterConfig, $http, $timeout, $rootScope);\n\t\t    $rootScope.filters.appDeploymentFilter = $scope.filter;\n\t    }\n\n\t    $scope.deploymentSelected = function(deployment) {\n\t    \tif (deployment && deployment.getProperty('id')) {\n\t    \t\t$location.path('/app-deployment/' + deployment.getProperty('id'));\n\t    \t}\n\t    };\n\n\t    $q.all([$translate('APP-DEPLOYMENTS.HEADER.ID'),\n              $translate('APP-DEPLOYMENTS.HEADER.NAME'),\n              $translate('APP-DEPLOYMENTS.HEADER.DEPLOY-TIME'),\n              $translate('APP-DEPLOYMENTS.HEADER.CATEGORY'),\n              $translate('APP-DEPLOYMENTS.HEADER.TENANT')])\n              .then(function(headers) {\n\n          // Config for grid\n          $scope.gridAppDeployments = {\n              data: 'appDeploymentsData.data',\n              enableRowReordering: true,\n              multiSelect: false,\n              keepLastSelected : false,\n              rowHeight: 36,\n              afterSelectionChange: $scope.deploymentSelected,\n              columnDefs: [\n                  { field: 'id', displayName: headers[0], cellTemplate: gridConstants.defaultTemplate},\n                  { field: 'name', displayName: headers[1], cellTemplate: gridConstants.defaultTemplate},\n                  { field: 'deploymentTime', displayName: headers[2], cellTemplate: gridConstants.dateTemplate},\n                  { field: 'category', displayName: headers[3], cellTemplate: gridConstants.defaultTemplate},\n                  { field: 'tenantId', displayName: headers[4], cellTemplate: gridConstants.defaultTemplate}]\n          };\n      });\n\n      $scope.executeWhenReady(function() {\n          $scope.filter.refresh();\n      });\n\n\n      /*\n       * ACTIONS\n       */\n\n      $scope.uploadDeployment = function () {\n          var modalInstance = $modal.open({\n              templateUrl: 'views/upload-app.html',\n              controller: 'UploadAppDeploymentCtrl'\n          });\n          modalInstance.result.then(function (result) {\n              // Refresh page if closed successfully\n              if (result) {\n                  $scope.deploymentsData = {};\n                  $scope.filter.refresh();\n              }\n          });\n      };\n\n\n    }]);\n\n\n/**\n * Controller for the APP upload\n */\n flowableAdminApp.controller('UploadAppDeploymentCtrl',\n    ['$scope', '$modalInstance', '$http', 'Upload', '$timeout', '$translate', function ($scope, $modalInstance, $http, Upload, $timeout, $translate) {\n\n    $scope.status = {loading: false};\n\n    $scope.model = {};\n\n    $scope.onFileSelect = function($files) {\n\n        for (var i = 0; i < $files.length; i++) {\n            var file = $files[i];\n            file.upload = Upload.upload({\n                url: FlowableAdmin.webContextRoot + '/app/rest/admin/app-deployments',\n                method: 'POST',\n                data: {file: file}\n            });\n\n            file.upload.then(function (response) {\n                $timeout(function () {\n                    $scope.addAlert($translate.instant('ALERT.DEPLOYMENT.DEPLOYMENT-SUCCESS'), 'info');\n                    $scope.status.loading = false;\n                    $modalInstance.close(true);\n                });\n            }, function (response) {\n                if (response.data && response.data.message) {\n                    $scope.model.errorMessage = response.data.message;\n                }\n                $scope.model.error = true;\n                $scope.status.loading = false;\n            }, function (evt) {\n                file.progress = Math.min(100, parseInt(100.0 *\n                    evt.loaded / evt.total));\n            });\n        }\n    };\n\n    $scope.cancel = function () {\n        if (!$scope.status.loading) {\n            $modalInstance.dismiss('cancel');\n        }\n    };\n\n}]);\n"
  },
  {
    "path": "flowable-ui-web/admin/scripts/app.js",
    "content": "/* Copyright 2005-2015 Alfresco Software, Ltd.\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'use strict';\n\n/* App Module */\n\nvar flowableAdminApp = angular.module('flowableAdminApp', ['ngResource', 'ngRoute', 'ngCookies', 'ngSanitize',\n    'pascalprecht.translate', 'ngGrid', 'ui.select2', 'ui.bootstrap', 'ngFileUpload', 'ui.keypress',\n    'ui.grid', 'ui.grid.edit', 'ui.grid.selection', 'ui.grid.autoResize', 'ui.grid.moveColumns', 'ui.grid.cellNav', 'jsonFormatter']);\n\nflowableAdminApp\n    .config(['$routeProvider', '$httpProvider', '$translateProvider', '$provide',\n        function ($routeProvider, $httpProvider, $translateProvider, $provide) {\n            $routeProvider\n            \t.when('/login', {\n            \t\ttemplateUrl: 'views/login.html',\n            \t\tcontroller: 'LoginController'\n            \t})\n                .when('/process-engine', {\n                    templateUrl: 'views/deployments.html',\n                    controller: 'DeploymentsController',\n                    reloadOnSearch: true\n                })\n                .when('/cmmn-engine', {\n                    templateUrl: 'views/cmmn-deployments.html',\n                    controller: 'CmmnDeploymentsController',\n                    reloadOnSearch: true\n                })\n                .when('/app-engine', {\n                    templateUrl: 'views/app-deployments.html',\n                    controller: 'AppDeploymentsController',\n                    reloadOnSearch: true\n                })\n                .when('/form-engine', {\n                    templateUrl: 'views/form-deployments.html',\n                    controller: 'FormDeploymentsController',\n                    reloadOnSearch: true\n                })\n                .when('/dmn-engine', {\n                    templateUrl: 'views/decision-table-deployments.html',\n                    controller: 'DecisionTableDeploymentsController',\n                    reloadOnSearch: true\n                })\n                .when('/content-engine', {\n                    templateUrl: 'views/content-items.html',\n                    controller: 'ContentItemsController',\n                    reloadOnSearch: true\n                })\n                .when('/process-definitions', {\n                    templateUrl: 'views/process-definitions.html',\n                    controller: 'ProcessDefinitionsController',\n                    reloadOnSearch: true\n                })\n                .when('/process-definition/:definitionId', {\n                    templateUrl: 'views/process-definition.html',\n                    controller: 'ProcessDefinitionController',\n                    reloadOnSearch: true\n                })\n                .when('/deployments', {\n                    templateUrl: 'views/deployments.html',\n                    controller: 'DeploymentsController',\n                    reloadOnSearch: true\n                })\n                .when('/deployment/:deploymentId', {\n                    templateUrl: 'views/deployment.html',\n                    controller: 'DeploymentController',\n                    reloadOnSearch: true\n                })\n                .when('/process-instances', {\n                    templateUrl: 'views/process-instances.html',\n                    controller: 'ProcessInstancesController',\n                    reloadOnSearch: true\n                })\n                .when('/process-instance/:processInstanceId', {\n                \ttemplateUrl: 'views/process-instance.html',\n                \tcontroller: 'ProcessInstanceController',\n                  \treloadOnSearch: true\n                })\n                .when('/tasks', {\n                \ttemplateUrl: 'views/tasks.html',\n                \tcontroller: 'TasksController',\n                 \treloadOnSearch: true\n                })\n                .when('/task/:taskId', {\n                \ttemplateUrl: 'views/task.html',\n                \tcontroller: 'TaskController',\n                  \treloadOnSearch: true\n                })\n                .when('/jobs', {\n                \ttemplateUrl: 'views/jobs.html',\n                \tcontroller: 'JobsController',\n                  \treloadOnSearch: true\n                })\n                .when('/job/:jobId', {\n                \ttemplateUrl: 'views/job.html',\n                \tcontroller: 'JobController',\n                  \treloadOnSearch: true\n                })\n                .when('/event-subscriptions', {\n                \ttemplateUrl: 'views/event-subscriptions.html',\n                \tcontroller: 'EventSubscriptionsController',\n                  \treloadOnSearch: true\n                })\n                .when('/event-subscriptions/:eventSubscriptionId', {\n                \ttemplateUrl: 'views/event-subscription.html',\n                \tcontroller: 'EventSubscriptionController',\n                  \treloadOnSearch: true\n                })\n                .when('/users', {\n                \ttemplateUrl: 'views/users.html',\n                \tcontroller: 'UsersController',\n                  \treloadOnSearch: true\n                })\n                .when('/engine', {\n                    templateUrl: 'views/engine.html',\n                    controller: 'EngineController',\n                    reloadOnSearch: true\n                })\n                .when('/monitoring', {\n                    templateUrl: 'views/monitoring.html',\n                    controller: 'MonitoringController',\n                    reloadOnSearch: true\n                })\n                .when('/', {\n              \t  \tredirectTo: '/engine'\n                })\n              \t.when('/process-definitions-refresh', {\n              \t\tredirectTo: '/process-definitions'\n              \t})\n              \t.when('/cmmn-deployments', {\n                    templateUrl: 'views/cmmn-deployments.html',\n                    controller: 'CmmnDeploymentsController',\n                    reloadOnSearch: true\n                })\n              \t.when('/cmmn-deployment/:deploymentId', {\n                    templateUrl: 'views/cmmn-deployment.html',\n                    controller: 'CmmnDeploymentController',\n                    reloadOnSearch: true\n                })\n                .when('/case-definitions', {\n                    templateUrl: 'views/case-definitions.html',\n                    controller: 'CaseDefinitionsController',\n                    reloadOnSearch: true\n                })\n                .when('/case-definition/:definitionId', {\n                    templateUrl: 'views/case-definition.html',\n                    controller: 'CaseDefinitionController',\n                    reloadOnSearch: true\n                })\n                .when('/case-instances', {\n                    templateUrl: 'views/case-instances.html',\n                    controller: 'CaseInstancesController',\n                    reloadOnSearch: true\n                })\n                .when('/case-instance/:caseInstanceId', {\n                    templateUrl: 'views/case-instance.html',\n                    controller: 'CaseInstanceController',\n                    reloadOnSearch: true\n                })\n                .when('/cmmn-tasks', {\n                    templateUrl: 'views/cmmn-tasks.html',\n                    controller: 'CmmnTasksController',\n                    reloadOnSearch: true\n                })\n                .when('/cmmn-task/:taskId', {\n                    templateUrl: 'views/cmmn-task.html',\n                    controller: 'CmmnTaskController',\n                    reloadOnSearch: true\n                })\n                .when('/cmmn-jobs', {\n                    templateUrl: 'views/cmmn-jobs.html',\n                    controller: 'CmmnJobsController',\n                    reloadOnSearch: true\n                })\n                .when('/cmmn-job/:jobId', {\n                    templateUrl: 'views/cmmn-job.html',\n                    controller: 'CmmnJobController',\n                    reloadOnSearch: true\n                })\n                .when('/app-deployments', {\n                    templateUrl: 'views/app-deployments.html',\n                    controller: 'AppDeploymentsController',\n                    reloadOnSearch: true\n                })\n                .when('/app-deployment/:deploymentId', {\n                    templateUrl: 'views/app-deployment.html',\n                    controller: 'AppDeploymentController',\n                    reloadOnSearch: true\n                })\n                .when('/app-definitions', {\n                    templateUrl: 'views/app-definitions.html',\n                    controller: 'AppDefinitionsController',\n                    reloadOnSearch: true\n                })\n                .when('/app-definition/:definitionId', {\n                    templateUrl: 'views/app-definition.html',\n                    controller: 'AppDefinitionController',\n                    reloadOnSearch: true\n                })\n                .when('/decision-table-deployments', {\n                    templateUrl: 'views/decision-table-deployments.html',\n                    controller: 'DecisionTableDeploymentsController',\n                    reloadOnSearch: true\n                })\n                .when('/decision-table-deployment/:deploymentId', {\n                    templateUrl: 'views/decision-table-deployment.html',\n                    controller: 'DecisionTableDeploymentController',\n                    reloadOnSearch: true\n                })\n                .when('/decision-tables', {\n                    templateUrl: 'views/decision-tables.html',\n                    controller: 'DecisionTablesController',\n                    reloadOnSearch: true\n                })\n                .when('/decision-table/:decisionTableId', {\n                    templateUrl: 'views/decision-table.html',\n                    controller: 'DecisionTableController',\n                    reloadOnSearch: true\n                })\n                .when('/decision-table-executions', {\n                    templateUrl: 'views/decision-table-executions.html',\n                    controller: 'DecisionTableExecutionsController',\n                    reloadOnSearch: true\n                })\n                .when('/decision-table-execution/:executionId', {\n                    templateUrl: 'views/decision-table-execution.html',\n                    controller: 'DecisionTableExecutionController',\n                    reloadOnSearch: true\n                })\n                .when('/form-deployments', {\n                    templateUrl: 'views/form-deployments.html',\n                    controller: 'FormDeploymentsController',\n                    reloadOnSearch: true\n                })\n                .when('/form-deployment/:formDeploymentId', {\n                    templateUrl: 'views/form-deployment.html',\n                    controller: 'FormDeploymentController',\n                    reloadOnSearch: true\n                })\n                .when('/form-definitions', {\n                    templateUrl: 'views/form-definitions.html',\n                    controller: 'FormDefinitionsController',\n                    reloadOnSearch: true\n                })\n                .when('/form-instances', {\n                    templateUrl: 'views/form-instances.html',\n                    controller: 'FormInstancesController',\n                    reloadOnSearch: true\n                })\n                .when('/form-definition/:formId', {\n                    templateUrl: 'views/form-definition.html',\n                    controller: 'FormDefinitionController',\n                    reloadOnSearch: true\n                })\n                .when('/form-instance/:formInstanceId', {\n                    templateUrl: 'views/form-instance.html',\n                    controller: 'FormInstanceController',\n                    reloadOnSearch: true\n                })\n                .when('/content-items', {\n                    templateUrl: 'views/content-items.html',\n                    controller: 'ContentItemsController',\n                    reloadOnSearch: true\n                })\n                .when('/content-item/:contentItemId', {\n                    templateUrl: 'views/content-item.html',\n                    controller: 'ContentItemController',\n                    reloadOnSearch: true\n                })\n                .otherwise({\n                \ttemplateUrl: 'views/login.html',\n                    controller: 'LoginController',\n                    reloadOnSearch: true\n                });\n\n            // Initialize angular-translate\n            $translateProvider.useStaticFilesLoader({\n                prefix: './i18n/',\n                suffix: '.json'\n            })\n            /*\n             This can be used to map multiple browser language keys to a\n             angular translate language key.\n             */\n            // .registerAvailableLanguageKeys(['en'], {\n            //     'en-*': 'en'\n            // })\n            .useSanitizeValueStrategy('escapeParameters')\n            .uniformLanguageTag('bcp47')\n            .determinePreferredLanguage();\n\n        }])\n\n    .factory('NotPermittedInterceptor', [ '$q', '$window', '$rootScope', function($q, $window, $rootScope) {\n        return {\n            responseError: function ( response ) {\n\n                if (response.status === 403) {\n                    $rootScope.login = null;\n                    $rootScope.authenticated = false;\n                    $window.location.href = '/';\n                    $window.location.reload();\n                    return $q.reject(response);\n                }\n                else{\n                    return $q.reject(response);\n                }\n            }\n        }\n    }])\n\n    // Custom Http interceptor that adds the correct prefix to each url\n    .config(['$httpProvider', function ($httpProvider) {\n        $httpProvider.interceptors.push(function ($q) {\n            return {\n                'request': function (config) {\n\n                    // Check if it starts with /app, if so add ., such that it works with a context root\n                    if (config.url && config.url.indexOf('/app') === 0) {\n                        config.url = '.' + config.url;\n                    } else  if (config.url && config.url.indexOf('app') === 0) {\n                        config.url = './' + config.url;\n                    }\n\n                    return config || $q.when(config);\n                }\n            };\n        });\n        \n        $httpProvider.interceptors.push('NotPermittedInterceptor');\n    }])\n\n    .config(function (JSONFormatterConfigProvider) {\n\n        JSONFormatterConfigProvider.hoverPreviewEnabled = true;\n    })\n\n    /* Filters */\n\n    .filter('dateformat', function() {\n\t\t    return function(date, format) {\n\t\t    \tif(date) {\n\t\t    \t\tif(format == ('full')) {\n\t\t    \t\t\t// Format the given value\n\t\t    \t\t\treturn moment(date).format(\"LLL\");\n\t\t    \t\t} else {\n\t\t    \t\t\t// By default, return a pretty date, based on the current time\n\t\t    \t\t\treturn moment(date).format(\"lll\");\n\t\t    \t\t}\n\t\t    \t}\n\t\t    \treturn '';\n\t\t    };\n\t\t})\n\t\t.filter('empty', function() {\n\t\t    return function(value) {\n\t\t    \tif(value) {\n\t\t    \t\treturn value;\n\t\t    \t}\n\t\t    \treturn '(None)';\n\t\t    };\n\t\t})\n        .filter('humanTime', function() {\n            return function(milliseconds){\n                var seconds = milliseconds / 1000;\n                var numyears = Math.floor(seconds / 31536000);\n                var numdays = Math.floor((seconds % 31536000) / 86400);\n                var numhours = Math.floor(((seconds % 31536000) % 86400) / 3600);\n                var numminutes = Math.floor((((seconds % 31536000) % 86400) % 3600) / 60);\n                var numseconds = Math.floor((((seconds % 31536000) % 86400) % 3600) % 60);\n                return numyears + \" years \" +  numdays + \" days \" + numhours + \" hours \" + numminutes + \" minutes \" + numseconds + \" seconds\";\n            };\n        })\n        .filter('megabytes', function() {\n            return function(bytes) {\n                 return Math.floor((bytes/1048576)) + 'MB';\n            };\n        })\n        .filter('round', function() {\n        \treturn function(number) {\n        \t\tif(!number) {\n        \t\t\treturn \"0\";\n        \t\t} else {\n        \t\t\treturn +number.toFixed(3);\n        \t\t}\n        \t};\n        })\n        .filter('range', function() {\n          return function(input, min, max) {\n            min = parseInt(min); //Make string input int\n            max = parseInt(max);\n            for (var i=min; i<max; i++)\n              input.push(i);\n            return input;\n          };\n        })\n        .run(['$rootScope', '$http', '$timeout', '$location', '$cookies', '$modal', '$translate', '$window',\n            function($rootScope, $http, $timeout, $location, $cookies, $modal, $translate, $window) {\n\n                // set angular translate fallback language\n                $translate.fallbackLanguage(['en']);\n\n                // setting Moment-JS (global) locale\n                if (FlowableAdmin.Config.localization.dates) {\n                    moment.locale($translate.proposedLanguage());\n                }\n\n                $rootScope.serverStatus = {\n                };\n\n        \t\t$rootScope.serversLoaded = false;\n\n        \t\t$rootScope.loadServerConfig = function(callbackAfterLoad) {\n                    $http({method: 'GET', url: FlowableAdmin.webContextRoot + '/app/rest/server-configs'}).\n                    success(function(data) {\n                        if (data.length > 0) {\n\n                            $rootScope.activeServers = {};\n\n                            for (var i = 0; i < data.length; i++) {\n                                if (data[i].endpointType === 1) {\n                                    $rootScope.activeServers['process'] = data[i];\n                                } else if (data[i].endpointType === 2) {\n                                    $rootScope.activeServers['dmn'] = data[i];\n                                } else if (data[i].endpointType === 3) {\n                                    $rootScope.activeServers['form'] = data[i];\n                                } else if (data[i].endpointType === 4) {\n                                    $rootScope.activeServers['content'] = data[i];\n                                } else if (data[i].endpointType === 5) {\n                                    $rootScope.activeServers['cmmn'] = data[i];\n                                } else if (data[i].endpointType === 6) {\n                                    $rootScope.activeServers['app'] = data[i];\n                                } else {\n                                    console.log('Warning! Invalid endpoint type received: '+data[i].endpointType);\n                                }\n                            }\n\n                            $rootScope.serversLoaded = true;\n                        } else {\n                            console.log('Warning! No server configurations received');\n                        }\n                    }).\n                    error(function(data, status, headers, config) {\n                        console.log('Something went wrong: ' + data);\n                    });\n\n                };\n\n        \t\t$http.get(FlowableAdmin.webContextRoot + '/app/rest/account')\n\t\t        \t.success(function (data, status, headers, config) {\n\t\t              \t$rootScope.account = data;\n\t\t               \t$rootScope.authenticated = true;\n\t\t               \t$rootScope.loadServerConfig(false);\n\t\t          \t});\n\n\t        \t$rootScope.loadProcessDefinitionsCache = function() {\n                    var promise = $http({\n                        method: 'GET',\n                        url: FlowableAdmin.webContextRoot + '/app/rest/admin/process-definitions?size=100000000'\n                    }).success(function (data, status, headers, config) {\n                        return data;\n                    }).error(function (data, status, headers, config) {\n                        return {'status': false};\n                    });\n\n                    return promise;\n\t            };\n\t            \n\t            $rootScope.loadCaseDefinitionsCache = function() {\n                    var promise = $http({\n                        method: 'GET',\n                        url: FlowableAdmin.webContextRoot + '/app/rest/admin/case-definitions?size=100000000'\n                    }).success(function (data, status, headers, config) {\n                        return data;\n                    }).error(function (data, status, headers, config) {\n                        return {'status': false};\n                    });\n\n                    return promise;\n                };\n\n\t            $rootScope.getProcessDefinitionFromCache = function(processDefId) {\n\t            \tfor (var i = 0; i < $rootScope.processDefinitionsCache.data.length; i++) {\n            \t\t\tif ($rootScope.processDefinitionsCache.data[i].id === processDefId) {\n            \t\t\t\treturn $rootScope.processDefinitionsCache.data[i];\n            \t\t\t}\n            \t\t}\n\t            \treturn null;\n\t            };\n\t            \n\t            $rootScope.getCaseDefinitionFromCache = function(caseDefId) {\n                    for (var i = 0; i < $rootScope.caseDefinitionsCache.data.length; i++) {\n                        if ($rootScope.caseDefinitionsCache.data[i].id === caseDefId) {\n                            return $rootScope.caseDefinitionsCache.data[i];\n                        }\n                    }\n                    return null;\n                };\n\n\t            // Reference the fixed configuration values on the root scope\n\t            $rootScope.config = FlowableAdmin.Config;\n\n\t            // Store empty object for filter-references\n\t            $rootScope.filters = { forced: {} };\n\n\t            // Alerts\n\t            $rootScope.alerts = {\n\t                queue: []\n\t            };\n\n\t            $rootScope.showAlert = function(alert) {\n\t                if (alert.queue.length > 0) {\n\t                    alert.current = alert.queue.shift();\n\t                    // Start timout for message-pruning\n\t                    alert.timeout = $timeout(function() {\n\t                        if(alert.queue.length == 0) {\n\t                            alert.current = undefined;\n\t                            alert.timeout = undefined;\n\t                        } else {\n\t                            $rootScope.showAlert(alert);\n\t                        }\n\t                    }, 1500);\n\t                } else {\n\t                    $rootScope.alerts.current = undefined;\n\t                }\n\t            };\n\n\t            $rootScope.addAlert = function(message, type) {\n\t                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\t            };\n\n\t            $rootScope.dismissAlert = function() {\n\t                if (!$rootScope.alerts.timeout) {\n\t                    $rootScope.alerts.current = undefined;\n\t                } else {\n\t                    $timeout.cancel($rootScope.alerts.timeout);\n\t                    $rootScope.alerts.timeout = undefined;\n\t                    $rootScope.showAlert($rootScope.alerts);\n\t                }\n\t            };\n\n\t            $rootScope.addAlertPromise = function(promise, type) {\n\t                promise.then(function(data) {\n\t                    $rootScope.addAlert(data, type);\n\t                });\n\t            };\n\t            \n\t            $rootScope.logout = function () {\n\t\t\t\t\t$rootScope.authenticated = false;\n\t\t\t\t\t$rootScope.authenticationError = false;\n\t\t\t\t\t$http.get('/app/logout')\n\t\t\t\t\t\t.success(function (data, status, headers, config) {\n\t\t\t\t\t\t\t$rootScope.login = null;\n\t\t\t\t\t\t\t$rootScope.authenticated = false;\n\t\t\t\t\t\t});\n\t\t\t\t}; \n\n\t            $rootScope.executeWhenReady = function(callback) {\n\t                if ($rootScope.activeServers) {\n\t                    callback();\n\t                } else {\n\t                    $rootScope.$watch('activeServers', function() {\n\t                        if ($rootScope.activeServers) {\n\t                            callback();\n\t                        }\n\t                    });\n\t                }\n\t            };\n        \t}\n        ]);\n\n"
  },
  {
    "path": "flowable-ui-web/admin/scripts/case-definition-controllers.js",
    "content": "/* Copyright 2005-2015 Alfresco Software, Ltd.\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'use strict';\n\nflowableAdminApp.controller('CaseDefinitionController', ['$scope', '$rootScope', '$http', '$timeout','$location','$routeParams', '$modal', '$translate', '$q', 'gridConstants',\n    function ($scope, $rootScope, $http, $timeout, $location, $routeParams, $modal, $translate, $q, gridConstants) {\n\n        $rootScope.navigation = {main: 'cmmn-engine', sub: 'definitions'};\n\n        $scope.tabData = {\n\t\t    tabs: [\n\t\t       {id: 'caseInstances', name: 'CASE-DEFINITION.TITLE.CASE-INSTANCES'},\n\t\t       {id: 'jobs', name: 'CASE-DEFINITION.TITLE.JOBS'}\n\t\t    ]\n\t\t};\n\t\t$scope.tabData.activeTab = $scope.tabData.tabs[0].id;\n\n\t\t$scope.returnToList = function() {\n\t\t\t$location.path(\"/case-definitions\");\n\t\t};\n\n\t\t$scope.openDefinition = function(definitionId) {\n\t\t\tif (definitionId) {\n\t\t\t\t$location.path(\"/case-definition/\" + definitionId);\n\t\t\t}\n\t\t};\n\n\n\t\t$scope.openDeployment = function(deploymentId) {\n\t\t    if (deploymentId) {\n\t\t        $location.path(\"/cmmn-deployment/\" + deploymentId);\n\t\t    }\n\t\t};\n\n    $scope.editCategory = function() {\n      var modalInstance = $modal.open({\n        templateUrl: 'views/case-definition-edit-category-popup.html',\n        controller: 'EditCaseDefinitionCategoryModalCtrl',\n        resolve: {\n          definition: function() {\n            return $scope.definition;\n          }\n        }\n      });\n\n      modalInstance.result.then(function (data) {\n        if(data) {\n          $scope.addAlert($translate.instant('ALERT.CASE-DEFINITION.CATEGORY-UPDATED', $scope.definition), 'info');\n          $scope.definition = data;\n        }\n      });\n    };\n\n    $scope.showCaseDiagram = function() {\n      $modal.open({\n        templateUrl: 'views/case-definition-diagram-popup.html',\n        windowClass: 'modal modal-full-width',\n        controller: 'ShowCaseDefinitionDiagramPopupCtrl',\n        resolve: {\n          definition: function() {\n            return $scope.definition;\n          }\n        }\n      });\n    };\n\n    $scope.openJob = function(job) {\n      if (job && job.getProperty('id')) {\n        $location.path(\"/job/\" + job.getProperty('id'));\n      }\n    };\n\n    $scope.openCaseInstance = function(instance) {\n      if (instance && instance.getProperty('id')) {\n        $location.path(\"/case-instance/\" + instance.getProperty('id'));\n      }\n    };\n    \n    $scope.openStartForm = function () {\n        if ($scope.startForm) {\n            $location.path(\"/form/\" + $scope.startForm.id);\n        }\n    };\n    \n    $scope.openFormDefinition = function (form) {\n        if (form && form.getProperty('id')) {\n            $location.path(\"/form-definition/\" + form.getProperty('id'));\n          }\n    };\n    \n    $scope.openDecisionTable = function (decisionTable) {\n        if (decisionTable && decisionTable.getProperty('id')) {\n            $location.path(\"/decision-table/\" + decisionTable.getProperty('id'));\n          }\n    };\n\n    $scope.showAllJobs = function() {\n      // Populate the job-filter with case definition id\n      $rootScope.filters.forced.jobFilter = {\n        caseDefinitionId: $scope.definition.id\n      };\n      $location.path(\"/jobs\");\n    };\n\n    $scope.showAllCases = function() {\n      // Populate the case filter with parentId\n      $rootScope.filters.forced.instanceFilter = {\n          caseDefinitionId: $scope.definition.id\n      };\n      $location.path(\"/case-instances\");\n    };\n\n    $scope.loadCaseInstances = function() {\n      $scope.caseInstances = undefined;\n      $http({method: 'GET', url: FlowableAdmin.webContextRoot + '/app/rest/admin/case-definitions/' + $scope.definition.id +'/case-instances'}).\n      success(function(data, status, headers, config) {\n        $scope.caseInstances = data;\n        $scope.tabData.tabs[0].info = data.total;\n      });\n    };\n\n        $scope.loadJobs = function() {\n            $scope.jobs = undefined;\n            $http({method: 'GET', url: FlowableAdmin.webContextRoot + '/app/rest/admin/case-definitions/' + $scope.definition.id +'/jobs'}).\n            success(function(data, status, headers, config) {\n                $scope.jobs = data;\n                $scope.tabData.tabs[1].info = data.total;\n            });\n        };\n        \n        $scope.loadDecisionTables = function() {\n            // Load decision tables\n            $http({method: 'GET', url: FlowableAdmin.webContextRoot + '/app/rest/admin/case-definition-decision-tables/' + $scope.definition.id}).\n            success(function(data, status, headers, config) {\n                $scope.decisionTables = data;\n                $scope.tabData.tabs[2].info = data.length;\n            }).\n            error(function(data, status, headers, config) {\n            });\n        };\n        \n        $scope.loadFormDefinitions = function() {\n            // Load forms\n            $http({method: 'GET', url: FlowableAdmin.webContextRoot + '/app/rest/admin/case-definition-form-definitions/' + $scope.definition.id}).\n            success(function(data, status, headers, config) {\n                $scope.formDefinitions = data;\n                $scope.tabData.tabs[3].info = data.length;\n            }).\n            error(function(data, status, headers, config) {\n            });\n        };\n\n\t\t$scope.executeWhenReady(function() {\n\t\t    // Load definition\n\t\t    $http({method: 'GET', url: FlowableAdmin.webContextRoot + '/app/rest/admin/case-definitions/' + $routeParams.definitionId}).\n\t\t    success(function(data, status, headers, config) {\n\t\t        $scope.definition = data;\n\t\t        $scope.loadCaseInstances();\n\t\t        $scope.loadJobs();\n                $scope.tabData.tabs.push({id: 'decisionTables', name: 'CASE-DEFINITION.TITLE.DECISION-TABLES'});\n                $scope.tabData.tabs.push({id: 'forms', name: 'CASE-DEFINITION.TITLE.FORMS'});\n                \n                $scope.loadDecisionTables();\n                $scope.loadFormDefinitions();\n\t\t    }).\n\t\t    error(function(data, status, headers, config) {\n\t\t        if (data && data.message) {\n                    // Extract error-message\n                    $rootScope.addAlert(data.message, 'error');\n                } else {\n                    // Use default error-message\n                    $rootScope.addAlert($translate.instant('ALERT.GENERAL.HTTP-ERROR'), 'error');\n                }\n\t\t    });\n\n\n\t\t    $q.all([$translate('CASE-INSTANCES.HEADER.ID'),\n                  $translate('CASE-INSTANCES.HEADER.NAME'),\n                  $translate('CASE-INSTANCES.HEADER.STATUS'),\n                  $translate('CASE-INSTANCES.HEADER.CREATE-TIME')])\n            .then(function(headers) {\n                var stateTemplate = '<div><div class=\"ngCellText\">{{row.getProperty(\"endTime\") && \"Completed\" || \"Active\"}}</div></div>';\n                var dateTemplate = '<div><div class=\"ngCellText\" title=\"{{row.getProperty(col.field) | dateformat:\\'full\\'}}\">{{row.getProperty(col.field) | dateformat}}</div></div>';\n    \n                // Config for variable grid\n                $scope.gridCaseInstances = {\n                    data: 'caseInstances.data',\n                    enableRowReordering: false,\n                    multiSelect: false,\n                    keepLastSelected : false,\n                    enableSorting: false,\n                    rowHeight: 36,\n                    afterSelectionChange: $scope.openCaseInstance,\n                    columnDefs: [\n                        { field: 'id', displayName: headers[0], width: 75},\n                        { field: 'name', displayName: headers[1]},\n                        { field: 'endTime', displayName: headers[2], cellTemplate: stateTemplate},\n                        { field: 'startTime', displayName: headers[3], cellTemplate: dateTemplate}\n                    ]\n                };\n            });\n\n\t\t    $q.all([$translate('JOBS.HEADER.ID'),\n                  $translate('JOBS.HEADER.DUE-DATE'),\n                  $translate('JOBS.HEADER.RETRIES'),\n                  $translate('JOBS.HEADER.EXCEPTION')])\n            .then(function(headers) {\n                var dateTemplate = '<div><div class=\"ngCellText\" title=\"{{row.getProperty(col.field) | dateformat:\\'full\\'}}\">{{row.getProperty(col.field) | dateformat}}</div></div>';\n    \n                // Config for variable grid\n                $scope.gridJobs = {\n                    data: 'jobs.data',\n                    enableRowReordering: false,\n                    multiSelect: false,\n                    keepLastSelected : false,\n                    enableSorting: false,\n                    rowHeight: 36,\n                    afterSelectionChange: $scope.openJob,\n                    columnDefs: [\n                        { field: 'id', displayName: headers[0], width: 50},\n                        { field: 'dueDate', displayName: headers[1], cellTemplate: dateTemplate},\n                        { field: 'retries', displayName: headers[2]},\n                        { field: 'exceptionMessage', displayName: headers[3]}\n                    ]\n                };\n            });\n\t\t    \n\t\t    $q.all([$translate('DECISION-TABLES.HEADER.ID'),\n\t                $translate('DECISION-TABLES.HEADER.NAME'),\n\t                $translate('DECISION-TABLES.HEADER.KEY'),\n\t                $translate('DECISION-TABLES.HEADER.VERSION'),\n\t                $translate('DECISION-TABLES.HEADER.TENANT-ID')])\n\t            .then(function (headers) {\n\t                // Config for grid\n\t                $scope.gridDecisionTables = {\n\t                    data: 'decisionTables',\n\t                    enableRowReordering: true,\n\t                    multiSelect: false,\n\t                    keepLastSelected: false,\n\t                    rowHeight: 36,\n\t                    afterSelectionChange: $scope.openDecisionTable,\n\t                    columnDefs: [\n\t                        {field: 'id', displayName: headers[0], cellTemplate: gridConstants.defaultTemplate},\n\t                        {field: 'name', displayName: headers[1], cellTemplate: gridConstants.defaultTemplate},\n\t                        {field: 'key', displayName: headers[2], cellTemplate: gridConstants.defaultTemplate},\n\t                        {field: 'version', displayName: headers[3], cellTemplate: gridConstants.defaultTemplate},\n\t                        {field: 'tenantId', displayName: headers[4], cellTemplate: gridConstants.defaultTemplate}]\n\t                };\n\t            });\n\t\t    \n\t\t    $q.all([$translate('FORM-DEFINITIONS.HEADER.ID'),\n\t                $translate('FORM-DEFINITIONS.HEADER.NAME'),\n\t                $translate('FORM-DEFINITIONS.HEADER.DEPLOYMENTID'),\n\t                $translate('FORM-DEFINITIONS.HEADER.TENANTID')])\n\t            .then(function (headers) {\n\t                // Config for grid\n\t                $scope.gridFormDefinitions = {\n\t                    data: 'formDefinitions',\n\t                    enableRowReordering: true,\n\t                    multiSelect: false,\n\t                    keepLastSelected: false,\n\t                    rowHeight: 36,\n\t                    afterSelectionChange: $scope.openFormDefinition,\n\t                    columnDefs: [\n\t                        {field: 'id', displayName: headers[0], cellTemplate: gridConstants.defaultTemplate},\n\t                        {field: 'name', displayName: headers[1], cellTemplate: gridConstants.defaultTemplate},\n\t                        {field: 'deploymentId', displayName: headers[2], cellTemplate: gridConstants.defaultTemplate},\n\t                        {field: 'tenantId', displayName: headers[3], cellTemplate: gridConstants.defaultTemplate}]\n\t                };\n\t            });\n\t\t      \n\t\t});\n\n}]);\n\nflowableAdminApp.controller('EditCaseDefinitionCategoryModalCtrl',\n    ['$rootScope', '$scope', '$modalInstance', '$http', 'definition', function ($rootScope, $scope, $modalInstance, $http, definition) {\n\n  $scope.model = {\n      id: definition.id,\n      category: definition.category,\n      name: definition.name,\n      key: definition.key,\n  };\n\n  $scope.status = {loading: false};\n\n\n  $scope.ok = function () {\n    $scope.status.loading = true;\n\n    var data = {\n        category: $scope.model.category\n    };\n\n    $http({method: 'PUT', url: FlowableAdmin.webContextRoot + '/app/rest/admin/case-definitions/' + $scope.model.id, data: data}).\n      success(function(data, status, headers, config) {\n        $modalInstance.close(data);\n        $scope.status.loading = false;\n      }).\n      error(function(data, status, headers, config) {\n        $modalInstance.close(false);\n       $scope.status.loading = false;\n      });\n  };\n\n  $scope.cancel = function () {\n  if(!$scope.status.loading) {\n    $modalInstance.dismiss('cancel');\n  }\n  };\n}]);\n\nflowableAdminApp.controller('ShowCaseDefinitionDiagramPopupCtrl',\n    ['$rootScope', '$scope', '$modalInstance', '$http', 'definition', '$timeout', function ($rootScope, $scope, $modalInstance, $http, definition, $timeout) {\n\n  $scope.model = {\n      id: definition.id,\n      name: definition.name\n  };\n\n  $scope.status = {loading: false};\n\n  $scope.cancel = function () {\n    if(!$scope.status.loading) {\n      $modalInstance.dismiss('cancel');\n    }\n  };\n\n  $timeout(function() {\n    $(\"#cmmnModel\").attr(\"data-definition-id\", definition.id);\n    $(\"#cmmnModel\").attr(\"data-server-id\", $rootScope.activeServers['cmmn']);\n    $(\"#cmmnModel\").load(\"./display-cmmn/displaymodel.html?definitionId=\" + definition.id);\n  }, 200);\n\n\n}]);\n"
  },
  {
    "path": "flowable-ui-web/admin/scripts/case-definitions-controllers.js",
    "content": "/* Copyright 2005-2015 Alfresco Software, Ltd.\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'use strict';\n\n/* Controllers */\n\nflowableAdminApp.controller('CaseDefinitionsController', ['$rootScope', '$scope', '$http', '$timeout', '$location','$translate', '$q', '$modal', 'gridConstants',\n    function ($rootScope, $scope, $http, $timeout, $location, $translate, $q, $modal, gridConstants) {\n\n\t\t$rootScope.navigation = {main: 'cmmn-engine', sub: 'definitions'};\n        \n\t\t$scope.filter = {};\n\t\t$scope.caseDefinitionsData = {};\n\n\t\t// Array to contain selected properties (yes - we only can select one, but ng-grid isn't smart enough)\n\t    $scope.selectedDefinitions = [];\n\n\t    var filterConfig = {\n\t    \turl: FlowableAdmin.webContextRoot + '/app/rest/admin/case-definitions',\n\t    \tmethod: 'GET',\n\t    \tsuccess: function(data, status, headers, config) {\n\t    \t\t$scope.caseDefinitionsData = data;\n            },\n            error: function(data, status, headers, config) {\n                if (data && data.message) {\n                    // Extract error-message\n                    $rootScope.addAlert(data.message, 'error');\n                } else {\n                    // Use default error-message\n                    $rootScope.addAlert($translate.instant('ALERT.GENERAL.HTTP-ERROR'), 'error');\n                }\n            },\n\n            sortObjects: [\n                {name: 'CASE-DEFINITIONS.SORT.ID', id: 'id'},\n                {name: 'CASE-DEFINITIONS.SORT.NAME', id: 'name'},\n                {name: 'CASE-DEFINITIONS.SORT.VERSION', id: 'version'}\n            ],\n\n            supportedProperties: [\n                {id: 'nameLike', name: 'CASE-DEFINITIONS.FILTER.NAME', showByDefault: false},\n                {id: 'keyLike', name: 'CASE-DEFINITIONS.FILTER.KEY', showByDefault: true},\n                {id: 'deploymentId', name: 'CASE-DEFINITIONS.FILTER.DEPLOYMENT-ID', showByDefault: false},\n                {id: 'tenantIdLike', name: 'CASE-DEFINITIONS.FILTER.TENANT-ID', showByDefault: false},\n                {id: 'latest', name: 'CASE-DEFINITIONS.FILTER.LATEST', showByDefault: true, defaultValue: true}\n            ]\n\t    };\n\n\t    if ($rootScope.filters.forced.caseDefinitionFilter) {\n\t        // Always recreate the filter and add all properties\n\t        $scope.filter = new FlowableAdmin.Utils.Filter(filterConfig, $http, $timeout, $rootScope);\n\t        $rootScope.filters.caseDefinitionFilter = $scope.filter;\n\n\t        for (var prop in $rootScope.filters.forced.processDefinitionFilter) {\n\t            $scope.filter.addProperty({id: prop}, $rootScope.filters.forced.caseDefinitionFilter[prop]);\n\t            if (prop == 'deploymentId') {\n\t                $scope.filter.removeProperty({id: 'latest'});\n\t            }\n\t        }\n\n\t        $rootScope.filters.forced.caseDefinitionFilter = undefined;\n\n\t    } else if ($rootScope.filters && $rootScope.filters.caseDefinitionFilter) {\n\t    \t// Reuse the existing filter\n\t    \t$scope.filter = $rootScope.filters.caseDefinitionFilter;\n\t    \t$scope.filter.config = filterConfig;\n\t    } else {\n\t\t    $scope.filter = new FlowableAdmin.Utils.Filter(filterConfig, $http, $timeout, $rootScope);\n\t\t    $rootScope.filters.caseDefinitionFilter = $scope.filter;\n\t    }\n\n\t    $scope.definitionSelected = function(definition) {\n\t    \tif (definition && definition.getProperty('id')) {\n\t    \t\t$location.path('/case-definition/' + definition.getProperty('id'));\n\t    \t}\n\t    };\n\n\t    $scope.toggleLatestVersion = function() {\n\t      if($scope.filter.properties.latest === true) {\n\t        $scope.filter.properties.nameLike = undefined;\n\t        $scope.filter.properties.deploymentId = undefined;\n\t      }\n\n\t      $scope.filter.refresh();\n\t    };\n\n\t    $q.all([$translate('CASE-DEFINITIONS.HEADER.ID'),\n              $translate('CASE-DEFINITIONS.HEADER.NAME'),\n              $translate('CASE-DEFINITIONS.HEADER.VERSION'),\n              $translate('CASE-DEFINITIONS.HEADER.KEY'),\n              $translate('CASE-DEFINITIONS.HEADER.TENANT')])\n              .then(function(headers) {\n\n          // Config for grid\n          $scope.gridDefinitions = {\n              data: 'caseDefinitionsData.data',\n              enableRowReordering: true,\n              multiSelect: false,\n              keepLastSelected : false,\n              rowHeight: 36,\n              selectedItems: $scope.selectedDefinitions,\n              afterSelectionChange: $scope.definitionSelected,\n              columnDefs: [\n                  { field: 'id', displayName: headers[0], cellTemplate: gridConstants.defaultTemplate},\n                  { field: 'name', displayName: headers[1], cellTemplate: gridConstants.defaultTemplate},\n                  { field: 'version', displayName: headers[2], cellTemplate: gridConstants.defaultTemplate},\n                  { field: 'key', displayName: headers[3], cellTemplate: gridConstants.defaultTemplate},\n                  { field: 'tenantId', displayName: headers[4], cellTemplate: gridConstants.defaultTemplate}]\n          };\n       });\n\n\n\t   // Hook in initial fetching of the definitions\n\t   $scope.executeWhenReady(function() {\n\t       $scope.filter.refresh();\n\t   });\n        \n\n    }]);\n"
  },
  {
    "path": "flowable-ui-web/admin/scripts/case-instance-controllers.js",
    "content": "/* Copyright 2005-2015 Alfresco Software, Ltd.\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'use strict';\n\nflowableAdminApp.controller('CaseInstanceController', ['$scope', '$rootScope', '$http', '$timeout', '$location', '$routeParams', '$modal', '$translate', '$q', 'gridConstants',\n    function ($scope, $rootScope, $http, $timeout, $location, $routeParams, $modal, $translate, $q, gridConstants) {\n\n        $rootScope.navigation = {main: 'cmmn-engine', sub: 'instances'};\n\n        $scope.tabData = {\n            tabs: [\n                {id: 'tasks', name: 'CASE-INSTANCE.TITLE.TASKS'},\n                {id: 'variables', name: 'CASE-INSTANCE.TITLE.VARIABLES'},\n                {id: 'jobs', name: 'CASE-INSTANCE.TITLE.JOBS'}\n            ]\n        };\n\n        $scope.tabData.activeTab = $scope.tabData.tabs[0].id;\n\n        $scope.returnToList = function () {\n            $location.path(\"/case-instances\");\n        };\n\n        $scope.openTask = function (task) {\n            if (task && task.getProperty('id')) {\n                $location.path(\"/cmmn-task/\" + task.getProperty('id'));\n            }\n        };\n\n        $scope.openJob = function (job) {\n            if (job && job.getProperty('id')) {\n                $location.path(\"/job/\" + job.getProperty('id'));\n            }\n        };\n\n        $scope.openCaseInstance = function (instance) {\n            if (instance) {\n                var id;\n                if (instance.getProperty !== undefined) {\n                    id = instance.getProperty('id');\n                } else {\n                    id = instance;\n                }\n                $location.path(\"/case-instance/\" + id);\n            }\n        };\n\n        $scope.showAllTasks = function () {\n            // Populate the task-filter with parentId\n            $rootScope.filters.forced.cmmnTaskFilter = {\n                caseInstanceId: $scope.caseInstance.id\n            };\n            $location.path(\"/cmmn-tasks\");\n        };\n\n        $scope.openCaseDefinition = function (caseDefinitionId) {\n            if (caseDefinitionId) {\n                $location.path(\"/case-definition/\" + caseDefinitionId);\n            }\n        };\n\n        $scope.openDecisionTable = function (decisionTable) {\n            if (decisionTable && decisionTable.getProperty('id')) {\n                $location.path(\"/decision-table-execution/\" + decisionTable.getProperty('id'));\n            }\n        };\n\n        $scope.openFormInstance = function (submittedForm) {\n            if (submittedForm && submittedForm.getProperty('id')) {\n                $location.path(\"/form-instance/\" + submittedForm.getProperty('id'));\n            }\n        };\n\n        $scope.loadCaseDefinition = function () {\n            // Load definition\n            $http({\n                method: 'GET',\n                url: FlowableAdmin.webContextRoot + '/app/rest/admin/case-definitions/' + $scope.caseInstance.caseDefinitionId\n            }).success(function (data, status, headers, config) {\n                $scope.definition = data;\n            }).error(function (data, status, headers, config) {\n            });\n        };\n\n        $scope.loadCaseInstance = function () {\n            $scope.caseInstance = undefined;\n            // Load process\n            $http({\n                method: 'GET',\n                url: FlowableAdmin.webContextRoot + '/app/rest/admin/case-instances/' + $routeParams.caseInstanceId\n            }).success(function (data, status, headers, config) {\n                $scope.caseInstance = data;\n\n                if (data) {\n                    $scope.caseCompleted = data.endTime != undefined;\n                }\n\n                // Start loading children\n                $scope.loadCaseDefinition();\n                $scope.loadTasks();\n                $scope.loadVariables();\n                $scope.loadJobs();\n                $scope.loadDecisionTables()\n\n                $scope.tabData.tabs.push({id: 'decisionTables', name: 'CASE-INSTANCE.TITLE.DECISION-TABLES'});\n                $scope.tabData.tabs.push({id: 'forms', name: 'CASE-INSTANCE.TITLE.FORM-INSTANCES'});\n                $scope.loadFormInstances();\n                \n            }).error(function (data, status, headers, config) {\n                if (data && data.message) {\n                    // Extract error-message\n                    $rootScope.addAlert(data.message, 'error');\n                } else {\n                    // Use default error-message\n                    $rootScope.addAlert($translate.instant('ALERT.GENERAL.HTTP-ERROR'), 'error');\n                }\n            });\n        };\n\n        var dateTemplate = '<div><div class=\"ngCellText\" title=\"{{row.getProperty(col.field) | dateformat:\\'full\\'}}\">{{row.getProperty(col.field) | dateformat}}</div></div>';\n\n        // Config for subtasks grid\n        $q.all([$translate('TASKS.HEADER.ID'),\n            $translate('TASKS.HEADER.NAME'),\n            $translate('TASKS.HEADER.ASSIGNEE'),\n            $translate('TASKS.HEADER.OWNER'),\n            $translate('TASKS.HEADER.CREATE-TIME'),\n            $translate('TASKS.HEADER.END-TIME')])\n            .then(function (headers) {\n                $scope.gridTasks = {\n                    data: 'tasks.data',\n                    enableRowReordering: false,\n                    multiSelect: false,\n                    keepLastSelected: false,\n                    enableSorting: false,\n                    rowHeight: 36,\n                    afterSelectionChange: $scope.openTask,\n                    columnDefs: [\n                        {field: 'id', displayName: headers[0], width: 50},\n                        {field: 'name', displayName: headers[1]},\n                        {field: 'assignee', displayName: headers[2], cellTemplate: gridConstants.defaultTemplate},\n                        {field: 'owner', displayName: headers[3], cellTemplate: gridConstants.defaultTemplate},\n                        {field: 'startTime', displayName: headers[4], cellTemplate: dateTemplate},\n                        {field: 'endTime', displayName: headers[5], cellTemplate: dateTemplate}\n                    ]\n                };\n            });\n\n        $q.all([$translate('VARIABLES.HEADER.NAME'),\n            $translate('VARIABLES.HEADER.TYPE'),\n            $translate('VARIABLES.HEADER.VALUE')])\n            .then(function (headers) {\n                var variableValueTemplate = '<div><div class=\"ngCellText\">{{row.getProperty(\"variable.valueUrl\") && \"(Binary)\" || row.getProperty(col.field)}}</div></div>';\n                var variableTypeTemplate = '<div><div class=\"ngCellText\">{{row.getProperty(col.field) && row.getProperty(col.field) || \"null\"}}</div></div>';\n\n                $scope.selectedVariables = [];\n\n                // Config for variable grid\n                $scope.gridVariables = {\n                    data: 'variables.data',\n                    enableRowReordering: false,\n                    multiSelect: false,\n                    keepLastSelected: false,\n                    enableSorting: false,\n                    rowHeight: 36,\n                    selectedItems: $scope.selectedVariables,\n                    columnDefs: [\n                        {field: 'variable.name', displayName: headers[0]},\n                        {field: 'variable.type', displayName: headers[1], cellTemplate: variableTypeTemplate},\n                        {field: 'variable.value', displayName: headers[2], cellTemplate: variableValueTemplate}\n                    ]\n                };\n            });\n        \n        $q.all([$translate('JOBS.HEADER.ID'),\n            $translate('JOBS.HEADER.DUE-DATE'),\n            $translate('JOBS.HEADER.RETRIES'),\n            $translate('JOBS.HEADER.EXCEPTION')])\n            .then(function (headers) {\n                var dateTemplate = '<div><div class=\"ngCellText\" title=\"{{row.getProperty(col.field) | dateformat:\\'full\\'}}\">{{row.getProperty(col.field) | dateformat}}</div></div>';\n\n                // Config for variable grid\n                $scope.gridJobs = {\n                    data: 'jobs.data',\n                    enableRowReordering: false,\n                    multiSelect: false,\n                    keepLastSelected: false,\n                    enableSorting: false,\n                    rowHeight: 36,\n                    afterSelectionChange: $scope.openJob,\n                    columnDefs: [\n                        {field: 'id', displayName: headers[0], width: 50},\n                        {field: 'dueDate', displayName: headers[1], cellTemplate: dateTemplate},\n                        {field: 'retries', displayName: headers[2]},\n                        {field: 'exceptionMessage', displayName: headers[3]}\n                    ]\n                };\n            });\n            \n        $q.all([$translate('DECISION-TABLE-EXECUTION.HEADER.ID'),\n            $translate('DECISION-TABLE-EXECUTION.HEADER.DECISION-KEY'),\n            $translate('DECISION-TABLE-EXECUTION.HEADER.DECISION-DEFINITION-ID'),\n            $translate('DECISION-TABLE-EXECUTION.HEADER.END-TIME'),\n            $translate('DECISION-TABLE-EXECUTION.HEADER.FAILED')])\n            .then(function (headers) {\n\n                $scope.gridDecisionTables = {\n                    data: 'decisionTables.data',\n                    enableRowReordering: false,\n                    multiSelect: false,\n                    keepLastSelected: false,\n                    enableSorting: false,\n                    rowHeight: 36,\n                    afterSelectionChange: $scope.openDecisionTable,\n                    columnDefs: [\n                        {field: 'id', displayName: headers[0]},\n                        {field: 'decisionKey', displayName: headers[1]},\n                        {field: 'decisionDefinitionId', displayName: headers[2]},\n                        {\n                            field: 'endTime',\n                            displayName: headers[3],\n                            cellTemplate: gridConstants.dateTemplate\n                        },\n                        {field: 'decisionExecutionFailed', displayName: headers[4]}\n                    ]\n                };\n            });\n\n        $q.all([$translate('FORM-INSTANCE.HEADER.ID'),\n            $translate('FORM-INSTANCE.HEADER.TASK-ID'),\n            $translate('FORM-INSTANCE.HEADER.CASE-ID'),\n            $translate('FORM-INSTANCE.HEADER.SUBMITTED'),\n            $translate('FORM-INSTANCE.HEADER.SUBMITTED-BY')])\n            .then(function (headers) {\n\n                $scope.gridFormInstances = {\n                    data: 'formInstances.data',\n                    enableRowReordering: false,\n                    multiSelect: false,\n                    keepLastSelected: false,\n                    enableSorting: false,\n                    rowHeight: 36,\n                    afterSelectionChange: $scope.openFormInstance,\n                    columnDefs: [\n                        {field: 'id', displayName: headers[0]},\n                        {field: 'taskId', displayName: headers[1]},\n                        {field: 'scopeId', displayName: headers[2]},\n                        {field: 'submittedDate', displayName: headers[3], cellTemplate: gridConstants.dateTemplate},\n                        {field: 'submittedBy', displayName: headers[4], cellTemplate: gridConstants.userObjectTemplate}\n                    ]\n                };\n            });\n\n        $scope.showAllJobs = function () {\n            // Populate the job-filter with case id\n            $rootScope.filters.forced.jobFilter = {\n                caseInstanceId: $scope.caseInstance.id\n            };\n            $location.path(\"/jobs\");\n        };\n\n        $scope.loadTasks = function () {\n            $scope.tasks = undefined;\n            $http({\n                method: 'GET',\n                url: FlowableAdmin.webContextRoot + '/app/rest/admin/case-instances/' + $scope.caseInstance.id + '/tasks'\n            }).success(function (data, status, headers, config) {\n                $scope.tasks = data;\n                $scope.tabData.tabs[0].info = data.total;\n            });\n        };\n\n        $scope.loadVariables = function () {\n            $scope.variables = undefined;\n            $http({\n                method: 'GET',\n                url: FlowableAdmin.webContextRoot + '/app/rest/admin/case-instances/' + $scope.caseInstance.id + '/variables'\n            }).success(function (data, status, headers, config) {\n                $scope.variables = data;\n                $scope.tabData.tabs[1].info = data.total;\n            });\n        };\n\n        $scope.loadJobs = function () {\n            $scope.jobs = undefined;\n            $http({\n                method: 'GET',\n                url: FlowableAdmin.webContextRoot + '/app/rest/admin/case-instances/' + $scope.caseInstance.id + '/jobs'\n            }).success(function (data, status, headers, config) {\n                $scope.jobs = data;\n                $scope.tabData.tabs[3].info = data.total;\n            });\n        };\n\n        $scope.loadCaseDefinition = function () {\n            // Load definition\n            $http({\n                method: 'GET',\n                url: FlowableAdmin.webContextRoot + '/app/rest/admin/case-definitions/' + $scope.caseInstance.caseDefinitionId\n            }).success(function (data, status, headers, config) {\n                $scope.definition = data;\n            }).error(function (data, status, headers, config) {\n            });\n        };\n\n        $scope.loadDecisionTables = function () {\n            // Load decision tables\n            $http({\n                method: 'GET',\n                url: FlowableAdmin.webContextRoot + '/app/rest/admin/case-instances/' + $scope.caseInstance.id + '/decision-executions'\n            }).success(function (data, status, headers, config) {\n                $scope.decisionTables = data;\n                $scope.tabData.tabs[3].info = data.total;\n            }).error(function (data, status, headers, config) {\n            });\n        };\n\n        $scope.loadFormInstances = function () {\n            // Load form instances\n            $http({\n                method: 'GET',\n                url: FlowableAdmin.webContextRoot + '/app/rest/admin/case-form-instances/' + $scope.caseInstance.id\n            }).success(function (response, status, headers, config) {\n                $scope.formInstances = response;\n                $scope.tabData.tabs[4].info = response.total;\n            }).error(function (data, status, headers, config) {\n            });\n        };\n\n\n        $scope.executeWhenReady(function () {\n            $scope.loadCaseInstance();\n        });\n\n\n        // Dialogs\n        $scope.deleteCaseInstance = function (action) {\n            if (!action) {\n                action = \"delete\";\n            }\n            var modalInstance = $modal.open({\n                templateUrl: 'views/case-instance-delete-popup.html',\n                controller: 'DeleteCaseModalInstanceCtrl',\n                resolve: {\n                    process: function () {\n                        return $scope.caseInstance;\n                    },\n                    action: function () {\n                        return action;\n                    }\n                }\n            });\n\n            modalInstance.result.then(function (deleteCaseInstance) {\n                if (deleteProcessInstance) {\n                    if (action == 'delete') {\n                        $scope.addAlert($translate.instant('ALERT.CASE-INSTANCE.DELETED', $scope.caseInstance), 'info');\n                        $scope.returnToList();\n                    } else {\n                        $scope.addAlert($translate.instant('ALERT.CASE-INSTANCE.TERMINATED', $scope.caseInstance), 'info');\n                        $scope.loadCaseInstance();\n                    }\n                }\n            });\n        };\n\n        $scope.updateSelectedVariable = function () {\n            if ($scope.selectedVariables && $scope.selectedVariables.length > 0) {\n                var selectedVariable = $scope.selectedVariables[0];\n                var modalInstance = $modal.open({\n                    templateUrl: 'views/update-variable-popup.html',\n                    controller: 'UpdateCaseInstanceVariableCtrl',\n                    resolve: {\n                        variable: function () {\n                            return selectedVariable.variable;\n                        },\n                        caseInstanceId: function () {\n                            return $scope.caseInstance.id;\n                        }\n                    }\n                });\n\n                modalInstance.result.then(function (updated) {\n                    if (updated == true) {\n                        $scope.selectedVariables.splice(0, $scope.selectedVariables.length);\n                        $scope.loadVariables();\n                    }\n                });\n            }\n        };\n\n        $scope.deleteVariable = function () {\n            if ($scope.selectedVariables && $scope.selectedVariables.length > 0) {\n                var selectedVariable = $scope.selectedVariables[0];\n                var modalInstance = $modal.open({\n                    templateUrl: 'views/variable-delete-popup.html',\n                    controller: 'DeleteCaseInstanceVariableCtrl',\n                    resolve: {\n                        variable: function () {\n                            return selectedVariable.variable;\n                        },\n                        caseInstanceId: function () {\n                            return $scope.caseInstance.id;\n                        }\n                    }\n                });\n\n                modalInstance.result.then(function (updated) {\n                    if (updated == true) {\n                        $scope.selectedVariables.splice(0, $scope.selectedVariables.length);\n                        $scope.loadVariables();\n                    }\n                });\n            }\n        };\n\n        $scope.addVariable = function () {\n            var modalInstance = $modal.open({\n                templateUrl: 'views/variable-add-popup.html',\n                controller: 'AddCaseInstanceVariableCtrl',\n                resolve: {\n                    caseInstanceId: function () {\n                        return $scope.caseInstance.id;\n                    }\n                }\n            });\n\n            modalInstance.result.then(function (updated) {\n                if (updated == true) {\n                    $scope.selectedVariables.splice(0, $scope.selectedVariables.length);\n                    $scope.loadVariables();\n                }\n            });\n        };\n\n        $scope.terminateCaseInstance = function () {\n            $scope.deleteCaseInstance(\"terminate\");\n        };\n    }]);\n\nflowableAdminApp.controller('DeleteCaseModalInstanceCtrl',\n    ['$rootScope', '$scope', '$modalInstance', '$http', 'caseInstance', 'action', function ($rootScope, $scope, $modalInstance, $http, caseInstance, action) {\n\n        $scope.caseInstance = caseInstance;\n        $scope.action = action;\n        $scope.status = {loading: false};\n        $scope.model = {};\n        $scope.ok = function () {\n            $scope.status.loading = true;\n\n            var dataForPost = {action: $scope.action};\n            if ($scope.action == 'terminate' && $scope.model.deleteReason) {\n                dataForPost.deleteReason = $scope.model.deleteReason;\n            }\n\n            $http({\n                method: 'POST', url: FlowableAdmin.webContextRoot + '/app/rest/admin/case-instances/' + $scope.caseInstance.id,\n                data: dataForPost\n            }).success(function (data, status, headers, config) {\n                $modalInstance.close(true);\n                $scope.status.loading = false;\n            }).error(function (data, status, headers, config) {\n                $modalInstance.close(false);\n                $scope.status.loading = false;\n            });\n        };\n\n        $scope.cancel = function () {\n            if (!$scope.status.loading) {\n                $modalInstance.dismiss('cancel');\n            }\n        };\n    }]);\n\nflowableAdminApp.controller('ShowCaseInstanceDiagramPopupCtrl',\n    ['$rootScope', '$scope', '$modalInstance', '$http', 'caseInstance', '$timeout', function ($rootScope, $scope, $modalInstance, $http, caseInstance, $timeout) {\n\n        $scope.model = {\n            id: caseInstance.id,\n            name: caseInstance.name\n        };\n\n        $scope.status = {loading: false};\n\n        $scope.cancel = function () {\n            if (!$scope.status.loading) {\n                $modalInstance.dismiss('cancel');\n            }\n        };\n\n        $timeout(function () {\n            $(\"#bpmnModel\").attr(\"data-instance-id\", caseInstance.id);\n            $(\"#bpmnModel\").attr(\"data-definition-id\", caseInstance.caseDefinitionId);\n            $(\"#bpmnModel\").attr(\"data-server-id\", $rootScope.activeServers['cmmn'].id);\n            if (process.endTime != undefined) {\n                $(\"#bpmnModel\").attr(\"data-history-id\", caseInstance.id);\n            }\n            $(\"#bpmnModel\").load(\"./display/displaymodel.html?instanceId=\" + caseInstance.id);\n        }, 200);\n\n\n    }]);\n\nflowableAdminApp.controller('UpdateCaseInstanceVariableCtrl',\n    ['$rootScope', '$scope', '$modalInstance', '$http', 'variable', 'caseInstanceId', function ($rootScope, $scope, $modalInstance, $http, variable, caseInstanceId) {\n\n        $scope.status = {loading: false};\n        $scope.originalVariable = variable;\n\n        $scope.updateVariable = {\n            name: variable.name,\n            value: variable.value,\n            type: variable.type\n        };\n\n        $scope.executeUpdateVariable = function () {\n\n            $scope.status.loading = true;\n\n            var dataForPut = {\n                name: $scope.updateVariable.name,\n                type: $scope.updateVariable.type\n            };\n\n            if ($scope.updateVariable.value !== null || $scope.updateVariable.value !== undefined || $scope.updateVariable.value !== '') {\n\n                if ($scope.updateVariable.type === 'string') {\n\n                    dataForPut.value = $scope.updateVariable.value;\n\n                } else if ($scope.updateVariable.type === 'boolean') {\n\n                    if ($scope.updateVariable.value) {\n                        dataForPut.value = true;\n                    } else {\n                        dataForPut.value = false;\n                    }\n\n                } else if ($scope.updateVariable.type === 'date') {\n\n                    dataForPut.value = $scope.updateVariable.value;\n\n                } else if ($scope.updateVariable.type === 'double'\n                    || $scope.updateVariable.type === 'long'\n                    || $scope.updateVariable.type === 'integer'\n                    || $scope.updateVariable.type === 'short') {\n\n                    dataForPut.value = Number($scope.updateVariable.value);\n\n                }\n\n            } else {\n\n                dataForPut.value = null;\n\n            }\n\n            $http({\n                method: 'PUT',\n                url: FlowableAdmin.webContextRoot + '/app/rest/admin/case-instances/' + caseInstanceId + '/variables/' + $scope.updateVariable.name,\n                data: dataForPut\n            }).success(function (data, status, headers, config) {\n                $modalInstance.close(true);\n                $scope.status.loading = false;\n            }).error(function (data, status, headers, config) {\n                $modalInstance.close(false);\n                $scope.status.loading = false;\n            });\n\n        };\n\n        $scope.cancel = function () {\n            $modalInstance.dismiss('cancel');\n        };\n\n    }]);\n\nflowableAdminApp.controller('DeleteCaseInstanceVariableCtrl',\n    ['$rootScope', '$scope', '$modalInstance', '$http', 'variable', 'caseInstanceId',\n        function ($rootScope, $scope, $modalInstance, $http, variable, caseInstanceId) {\n\n            $scope.status = {loading: false};\n            $scope.variable = variable;\n\n            $scope.deleteVariable = function () {\n                $http({\n                    method: 'DELETE',\n                    url: FlowableAdmin.webContextRoot + '/app/rest/admin/case-instances/' + caseInstanceId + '/variables/' + $scope.variable.name\n                }).success(function (data, status, headers, config) {\n                    $modalInstance.close(true);\n                    $scope.status.loading = false;\n                }).error(function (data, status, headers, config) {\n                    $modalInstance.close(false);\n                    $scope.status.loading = false;\n                });\n            };\n\n            $scope.cancel = function () {\n                $modalInstance.dismiss('cancel');\n            };\n\n        }]);\n\nflowableAdminApp.controller('AddCaseInstanceVariableCtrl',\n    ['$rootScope', '$scope', '$modalInstance', '$http', 'caseInstanceId',\n        function ($rootScope, $scope, $modalInstance, $http, caseInstanceId) {\n\n            $scope.status = {loading: false};\n\n            $scope.types = [\n                \"string\",\n                \"boolean\",\n                \"date\",\n                \"double\",\n                \"integer\",\n                \"long\",\n                \"short\"\n            ];\n\n            $scope.newVariable = {};\n\n            $scope.createVariable = function () {\n\n                var data = {\n                    name: $scope.newVariable.name,\n                    type: $scope.newVariable.type,\n                };\n\n                if ($scope.newVariable.type === 'string') {\n\n                    data.value = $scope.newVariable.value;\n\n                } else if ($scope.newVariable.type === 'boolean') {\n\n                    if ($scope.newVariable.value) {\n                        data.value = true;\n                    } else {\n                        data.value = false;\n                    }\n\n                } else if ($scope.newVariable.type === 'date') {\n\n                    data.value = $scope.newVariable.value;\n\n                } else if ($scope.newVariable.type === 'double'\n                    || $scope.newVariable.type === 'long'\n                    || $scope.newVariable.type === 'integer'\n                    || $scope.newVariable.type === 'short') {\n\n                    data.value = Number($scope.newVariable.value);\n\n                }\n\n                $http({\n                    method: 'POST',\n                    url: FlowableAdmin.webContextRoot + '/app/rest/admin/case-instances/' + caseInstanceId + '/variables',\n                    data: data\n                }).success(function (data, status, headers, config) {\n                    $modalInstance.close(true);\n                    $scope.status.loading = false;\n                }).error(function (data, status, headers, config) {\n                    $modalInstance.close(false);\n                    $scope.status.loading = false;\n                });\n            };\n\n            $scope.cancel = function () {\n                $modalInstance.dismiss('cancel');\n            };\n\n        }]);\n"
  },
  {
    "path": "flowable-ui-web/admin/scripts/case-instances-controllers.js",
    "content": "/* Copyright 2005-2015 Alfresco Software, Ltd.\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'use strict';\n\n/* Controllers */\n\nflowableAdminApp.controller('CaseInstancesController', ['$rootScope', '$scope', '$http', '$timeout', '$location', '$translate', '$q', 'gridConstants',\n    function ($rootScope, $scope, $http, $timeout, $location, $translate, $q, gridConstants) {\n\n\t\t$rootScope.navigation = {main: 'cmmn-engine', sub: 'instances'};\n\t\t\n\t\t$scope.filter = {};\n\t\t$scope.caseInstances = {};\n\t\t$scope.definitionCacheLoaded = false;\n\n\t\t$scope.variableFilterTypes = FlowableAdmin.Utils.variableFilterTypes;\n\t\t$scope.variableFilterOperators = FlowableAdmin.Utils.variableFilterOperators;\n\n\t    var filterConfig = {\n\t    \turl: FlowableAdmin.webContextRoot + '/app/rest/admin/case-instances',\n\t    \tmethod: 'POST',\n\t    \tsuccess: function(data, status, headers, config) {\n\t    \t\tif ($scope.definitionCacheLoaded) {\n                \t$scope.processQueryResponse(data);\n                }\n                else {\n\t                $rootScope.loadCaseDefinitionsCache().then(function(promise) {\n\t        \t\t\t$rootScope.caseDefinitionsCache = promise.data;\n\n\t        \t\t\t$scope.definitionCacheLoaded = true;\n\t        \t\t\t$scope.processQueryResponse(data);\n\t        \t\t});\n                }\n            },\n            error: function(data, status, headers, config) {\n                if (data && data.message) {\n                    // Extract error-message\n                    $rootScope.addAlert(data.message, 'error');\n                } else {\n                    // Use default error-message\n                    $rootScope.addAlert($translate.instant('ALERT.GENERAL.HTTP-ERROR'), 'error');\n                }\n            },\n\n            sortObjects: [\n                {name: 'CASE-INSTANCES.SORT.ID', id: 'caseInstanceId'},\n                {name: 'CASE-INSTANCES.SORT.START-TIME', id: 'startTime'}\n            ],\n            \n            options: {\n                finished: [\n                    {name: 'CASE-INSTANCES.FILTER.STATUS-ANY', value: ''},\n                    {name: 'CASE-INSTANCES.FILTER.STATUS-ACTIVE', value: 'false'},\n                    {name: 'CASE-INSTANCES.FILTER.STATUS-COMPLETE', value: 'true'}\n                ]\n            },\n\n            supportedProperties: [\n                {id: 'finished', name: 'CASE-INSTANCES.FILTER.STATUS', showByDefault: true},\n                {id: 'caseBusinessKey', name: 'CASE-INSTANCES.FILTER.BUSINESS-KEY'},\n                {id: 'startedBefore', name: 'CASE-INSTANCES.FILTER.STARTED-BEFORE'},\n                {id: 'startedAfter', name: 'CASE-INSTANCES.FILTER.STARTED-AFTER'},\n                {id: 'finishedBefore', name: 'CASE-INSTANCES.FILTER.ENDED-BEFORE'},\n                {id: 'finishedAfter', name: 'CASE-INSTANCES.FILTER.ENDED-AFTER'},\n                {id: 'variable', name: 'CASE-INSTANCES.FILTER.VARIABLE'},\n                {id: 'tenantIdLike', name: 'CASE-INSTANCES.FILTER.TENANT-ID'}\n            ]\n\t    };\n\n\t    if ($rootScope.filters.forced.caseInstanceFilter) {\n\t        // Always recreate the filter and add all properties\n            $scope.filter = new FlowableAdmin.Utils.Filter(filterConfig, $http, $timeout, $rootScope);\n            $rootScope.filters.caseInstanceFilter = $scope.filter;\n\n    \t\tfor (var prop in $rootScope.filters.forced.caseInstanceFilter) {\n    \t\t\t$scope.filter.addProperty({id: prop}, $rootScope.filters.forced.caseInstanceFilter[prop]);\n    \t\t}\n\n    \t\t$rootScope.filters.forced.caseInstanceFilter = undefined;\n\n\t    } else if ($rootScope.filters && $rootScope.filters.caseInstanceFilter) {\n            // Reuse the existing filter\n            $scope.filter = $rootScope.filters.caseInstanceFilter;\n            $scope.filter.config = filterConfig;\n\n\t    } else {\n            $scope.filter = new FlowableAdmin.Utils.Filter(filterConfig, $http, $timeout, $rootScope);\n            $rootScope.filters.caseInstanceFilter = $scope.filter;\n\t    }\n\n\t    $scope.caseInstanceSelected = function(caseInstance) {\n            if (caseInstance && caseInstance.getProperty('id')) {\n                $location.path('/case-instance/' + caseInstance.getProperty('id'));\n            }\n        };\n\n\t    if (!$scope.filter.properties.variables) {\n\t        $scope.filter.properties.variables = [];\n\t    }\n\n\t    // Set value-filter callback to convert variables to nice format\n\t    $scope.filter.config.valueFilter = function(prop, value) {\n\t      if (prop == 'variables') {\n\t        var actualValue = [];\n\t        var variable;\n\t        for (var i=0; i<value.length; i++) {\n\t          variable = value[i];\n\n\t          if (variable.name && variable.type && variable.value !== undefined && variable.value !== '' && variable.operator) {\n\t              var varPayload =  {\n\t                  name: variable.name,\n\t                  value: variable.value,\n\t                  operation: variable.operator.id,\n\t                  type: variable.type.id\n\t              };\n\n\t              if (variable.type.id == 'long' || variable.type.id == 'short' || variable.type.id == 'double' || variable.type.id == 'integer') {\n\t                  varPayload.value = parseFloat(varPayload.value);\n\t                  if (!isNaN(varPayload.value)) {\n\t                      // Return valid value for number\n\t                      actualValue.push(varPayload);\n\t                  }\n\t              } else {\n\t                  // Return valid value\n\t                  actualValue.push(varPayload);\n\t              }\n\t          }\n\t        }\n\t        return actualValue;\n\t      } else {\n\t        return value;\n\t      }\n\t    };\n\n\t    $scope.clearFilters = function() {\n\t      $scope.filter.clear();\n\t      $scope.filter.properties.variables = [];\n\t    };\n\n\t    $scope.setVariableFilterType = function(varFilter, type) {\n\n\t      varFilter.value = undefined;\n\t      if (type.id == 'boolean') {\n\t        varFilter.value = true;\n\n\t        if (varFilter.operator.id != 'equals') {\n\t          varFilter.operator = $scope.variableFilterOperators[0];\n\t        }\n\t      }\n\n\t      varFilter.type = type;\n\t      $scope.highlightVariableValue(varFilter);\n\t      $scope.filter.refresh();\n\t    };\n\n\t    $scope.setVariableFilterOperator = function(varFilter, operator) {\n\t      if(operator.id == 'like') {\n\t        varFilter.value = '';\n\t        varFilter.type = $scope.variableFilterTypes[0];\n\t      }\n\n\t      if(varFilter.type.id == 'boolean' && operator.id != 'equals') {\n\t        varFilter.operator = $scope.variableFilterOperators[0];\n\t      } else {\n\t        varFilter.operator = operator;\n\t      }\n\t      $scope.highlightVariableValue(varFilter);\n\t      $scope.filter.refresh();\n\t    };\n\n\t    $scope.highlightVariableValue = function(varFilter) {\n\t       var index = -1;\n            for (var i=0; i<$scope.filter.properties.variables.length; i++) {\n                if (varFilter == $scope.filter.properties.variables[i]) {\n                    index = i;\n                    break;\n                }\n            }\n\n            $timeout(function() {\n                var formField = $('#filter-variable-value-' + index);\n                formField.focus();\n            }, 100);\n\t    };\n\n\t    $scope.addFilterProperty = function(prop) {\n\t      if(prop.id != 'variable') {\n\t        $scope.filter.addProperty(prop);\n\t      } else {\n\t        // Add additional variable\n\t        $scope.filter.properties.variables.push({\n\t          type: $scope.variableFilterTypes[0],\n\t          operator: $scope.variableFilterOperators[0],\n\t          scope: 'variable'\n\t        });\n\n\t        $timeout(function() {\n\t          var formField = $('#filter-variable-name-' + ($scope.filter.properties.variables.length - 1));\n\t          formField.focus();\n\t        }, 100);\n\t      }\n\t    };\n\n\t    $q.all([$translate('CASE-INSTANCES.HEADER.ID'),\n              $translate('CASE-INSTANCES.HEADER.BUSINESS-KEY'),\n              $translate('CASE-INSTANCES.HEADER.CASE-DEFINITION'),\n              $translate('CASE-INSTANCES.HEADER.CREATE-TIME'),\n              $translate('CASE-INSTANCES.HEADER.END-TIME'),])\n              .then(function(headers) {\n\n          $scope.gridInstances = {\n              data: 'caseInstances.data',\n              enableRowReordering: true,\n              multiSelect: false,\n              keepLastSelected : false,\n              rowHeight: 36,\n              afterSelectionChange: $scope.caseInstanceSelected,\n              columnDefs: [\n                  { field: 'id', displayName: headers[0], cellTemplate: gridConstants.defaultTemplate},\n                  { field: 'businessKey', displayName: headers[1], cellTemplate: gridConstants.defaultTemplate},\n                  { field: 'caseDefinition.name', displayName: headers[2], cellTemplate: gridConstants.defaultTemplate},\n                  { field: 'startTime', displayName: headers[3], cellTemplate: gridConstants.dateTemplate},\n                  { field: 'endTime', displayName: headers[4], cellTemplate: gridConstants.dateTemplate}]\n          };\n        });\n\n        $scope.processQueryResponse = function(caseInstancesResponse) {\n        \tfor (var i = 0; i < caseInstancesResponse.data.length; i++) {\n\t\t\t\tcaseInstancesResponse.data[i].caseDefinition =\n            \t\t$rootScope.getCaseDefinitionFromCache(caseInstancesResponse.data[i].caseDefinitionId);\n\n\t\t\t\t// Fallback to id, of case definition doesn't have a name (getCaseDefinitionFromCache returns null if not found)\n\t\t\t\tif ((caseInstancesResponse.data[i].caseDefinition === null || caseInstancesResponse.data[i].caseDefinition === undefined) && caseInstancesResponse.data[i].caseDefinitionId) {\n\t\t\t\t    caseInstancesResponse.data[i].caseDefinition = { id: caseInstancesResponse.data[i].caseDefinitionId, name: caseInstancesResponse.data[i].caseDefinitionId }\n\t\t\t\t}\n\n            }\n\t\t\t$scope.caseInstances = caseInstancesResponse;\n        };\n\n        $scope.caseDefinitionFilterChanged = function() {\n        \tif ($scope.filter.caseDefinition && $scope.filter.caseDefinition !== '-1') {\n        \t\t$scope.filter.properties.caseDefinitionId = $scope.filter.caseDefinition;\n        \t\t$scope.filter.refresh();\n        \t\t\n        \t} else {\n        \t\tvar tempCaseDefinitionId = $scope.filter.properties.caseDefinitionId;\n        \t\t$scope.filter.properties.caseDefinitionId = null;\n        \t\tif (tempCaseDefinitionId && tempCaseDefinitionId.length > 0) {\n        \t\t\t$scope.filter.refresh();\n        \t\t}\n        \t}\n        };\n\n        $scope.executeWhenReady(function() {\n            $scope.filter.refresh();\n        });\n\n    }]);\n"
  },
  {
    "path": "flowable-ui-web/admin/scripts/cmmn-deployment-controllers.js",
    "content": "/* 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'use strict';\n\nflowableAdminApp.controller('CmmnDeploymentController', ['$scope', '$rootScope', '$http', '$timeout','$location','$routeParams', '$modal', '$translate', '$q',\n    function ($scope, $rootScope, $http, $timeout, $location, $routeParams, $modal, $translate, $q) {\n\n        $rootScope.navigation = {main: 'cmmn-engine', sub: 'deployments'};\n        \n\t\t$scope.returnToList = function() {\n\t\t\t$location.path(\"/cmmn-deployments\");\n\t\t};\n\t\t\n\t\t$scope.openDefinition = function(definition) {\n\t\t\tif (definition && definition.getProperty('id')) {\n\t\t\t\t$location.path(\"/case-definition/\" + definition.getProperty('id'));\n\t\t\t}\n\t\t};\n\t\t\n\t\t$scope.showAllDefinitions = function() {\n\t\t    // Populate the cmmn-filter with parentId\n\t\t    $rootScope.filters.forced.caseDefinitionFilter = {\n\t            deploymentId: $scope.cmmnDeployment.id\n\t\t    };\n\t\t    $location.path(\"/case-definitions\");\n\t\t};\n\t\t\n\t\t$q.all([$translate('CASE-DEFINITIONS.HEADER.ID'),\n            $translate('CASE-DEFINITIONS.HEADER.NAME'),\n            $translate('CASE-DEFINITIONS.HEADER.VERSION'),\n            $translate('CASE-DEFINITIONS.HEADER.KEY')])\n            .then(function(headers) { \n        \n                $scope.gridCaseDefinitions = {\n                    data: 'caseDefinitions.data',\n                    enableRowReordering: false,\n                    multiSelect: false,\n                    keepLastSelected : false,\n                    enableSorting: false,\n                    rowHeight: 36,\n                    afterSelectionChange: $scope.openDefinition,\n                    columnDefs: [\n                          { field: 'id', displayName: headers[0]},\n                          { field: 'name', displayName: headers[1]},\n                          { field: 'version', displayName: headers[2]},\n                          { field: 'key', displayName: headers[3]}\n                    ]\n                };\n        });\n\t\t\n\t\t$scope.deleteDeployment = function() {\n\t\t    var modalInstance = $modal.open({\n                templateUrl: 'views/confirm-popup.html',\n                controller: 'ConfirmPopupCtrl',\n                resolve: {\n                    model: function () {\n                      return {\n                          confirm: $translate.instant('CMMN-DEPLOYMENTS.ACTION.DELETE'),\n                          title: $translate.instant('CMMN-DEPLOYMENTS.ACTION.DELETE'),\n                          message: $translate.instant('CMMN-DEPLOYMENTS.POPUP.DELETE.CONFIRM-MESSAGE', $scope.cmmnDeployment)\n                          };\n                    }\n                }\n                \n            });\n            \n            modalInstance.result.then(function (result) {\n                if (result === true) {\n                    $http({method: 'DELETE', url: FlowableAdmin.webContextRoot + '/app/rest/admin/cmmn-deployments/' + $routeParams.deploymentId}).\n                    success(function(data, status, headers, config) {\n                        $scope.addAlert($translate.instant('ALERT.CMMN-DEPLOYMENT.DELETED-DEPLOYMENT', $scope.cmmnDeployment), 'info');\n                        $scope.returnToList();\n                    }).\n                    error(function(data, status, headers, config) {\n                        $scope.addAlert($translate.instant('ALERT.CMMN-DEPLOYMENT.DELETE-ERROR', data), 'error');\n                    });\n                }\n            });\n            \n        };\n        \n\t\t$scope.executeWhenReady(function() {\n\t\t    // Load deployment\n\t\t    $http({method: 'GET', url: FlowableAdmin.webContextRoot + '/app/rest/admin/cmmn-deployments/' + $routeParams.deploymentId}).\n  \t    \t    success(function(data, status, headers, config) {\n  \t    \t        $scope.cmmnDeployment = data;\n  \t    \t    }).\n  \t    \t    error(function(data, status, headers, config) {\n                    if (data && data.message) {\n                        // Extract error-message\n                        $rootScope.addAlert(data.message, 'error');\n                    } else {\n                        // Use default error-message\n                        $rootScope.addAlert($translate.instant('ALERT.GENERAL.HTTP-ERROR'), 'error');\n                    }\n  \t    \t    });\n  \t\t\n\t\t    // Load case definitions\n\t\t    $http({method: 'GET', url: FlowableAdmin.webContextRoot + '/app/rest/admin/case-definitions?deploymentId=' + $routeParams.deploymentId}).\n  \t    \t    success(function(data, status, headers, config) {\n  \t    \t        $scope.caseDefinitions = data;\n  \t    \t    });\n\t\t    \n  \t     });\n}]);"
  },
  {
    "path": "flowable-ui-web/admin/scripts/cmmn-deployments-controllers.js",
    "content": "/* 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'use strict';\n\n/* Controllers */\n\nflowableAdminApp.controller('CmmnDeploymentsController', ['$rootScope', '$scope', '$http', '$timeout', '$location', '$translate', '$q', '$modal', 'gridConstants',\n    function ($rootScope, $scope, $http, $timeout, $location, $translate, $q, $modal, gridConstants) {\n\n\t\t$rootScope.navigation = {main: 'cmmn-engine', sub: 'deployments'};\n        \n\t\t$scope.filter = {};\n\t\t$scope.cmmnDeploymentsData = {};\n\n\t\t// Array to contain selected properties (yes - we only can select one, but ng-grid isn't smart enough)\n\t    $scope.selectedDeployments = [];\n\n\t    var filterConfig = {\n\t    \turl: FlowableAdmin.webContextRoot + '/app/rest/admin/cmmn-deployments',\n\t    \tmethod: 'GET',\n\t    \tsuccess: function(data, status, headers, config) {\n\t    \t\t$scope.cmmnDeploymentsData = data;\n            },\n            error: function(data, status, headers, config) {\n                if (data && data.message) {\n                    // Extract error-message\n                    $rootScope.addAlert(data.message, 'error');\n                } else {\n                    // Use default error-message\n                    $rootScope.addAlert($translate.instant('ALERT.GENERAL.HTTP-ERROR'), 'error');\n                }\n            },\n\n            sortObjects: [\n                {name: 'CMMN-DEPLOYMENTS.SORT.ID', id: 'id'},\n                {name: 'CMMN-DEPLOYMENTS.SORT.NAME', id: 'name'}\n            ],\n\n            supportedProperties: [\n                {id: 'nameLike', name: 'CMMN-DEPLOYMENTS.FILTER.NAME', showByDefault: true},\n                {id: 'tenantIdLike', name: 'CMMN-DEPLOYMENTS.FILTER.TENANTID', showByDefault: true}\n            ]\n\t    };\n\n\t    if($rootScope.filters && $rootScope.filters.cmmnDeploymentFilter) {\n\t    \t// Reuse the existing filter\n\t    \t$scope.filter = $rootScope.filters.cmmnDeploymentFilter;\n\t    \t$scope.filter.config = filterConfig;\n\t    } else {\n\t\t    $scope.filter = new FlowableAdmin.Utils.Filter(filterConfig, $http, $timeout, $rootScope);\n\t\t    $rootScope.filters.cmmnDeploymentFilter = $scope.filter;\n\t    }\n\n\t    $scope.deploymentSelected = function(deployment) {\n\t    \tif (deployment && deployment.getProperty('id')) {\n\t    \t\t$location.path('/cmmn-deployment/' + deployment.getProperty('id'));\n\t    \t}\n\t    };\n\n\t    $q.all([$translate('CMMN-DEPLOYMENTS.HEADER.ID'),\n              $translate('CMMN-DEPLOYMENTS.HEADER.NAME'),\n              $translate('CMMN-DEPLOYMENTS.HEADER.DEPLOY-TIME'),\n              $translate('CMMN-DEPLOYMENTS.HEADER.CATEGORY'),\n              $translate('CMMN-DEPLOYMENTS.HEADER.TENANT')])\n              .then(function(headers) {\n\n          // Config for grid\n          $scope.gridCmmnDeployments = {\n              data: 'cmmnDeploymentsData.data',\n              enableRowReordering: true,\n              multiSelect: false,\n              keepLastSelected : false,\n              rowHeight: 36,\n              afterSelectionChange: $scope.deploymentSelected,\n              columnDefs: [\n                  { field: 'id', displayName: headers[0], cellTemplate: gridConstants.defaultTemplate},\n                  { field: 'name', displayName: headers[1], cellTemplate: gridConstants.defaultTemplate},\n                  { field: 'deploymentTime', displayName: headers[2], cellTemplate: gridConstants.dateTemplate},\n                  { field: 'category', displayName: headers[3], cellTemplate: gridConstants.defaultTemplate},\n                  { field: 'tenantId', displayName: headers[4], cellTemplate: gridConstants.defaultTemplate}]\n          };\n      });\n\n      $scope.executeWhenReady(function() {\n          $scope.filter.refresh();\n      });\n\n\n      /*\n       * ACTIONS\n       */\n\n      $scope.uploadDeployment = function () {\n          var modalInstance = $modal.open({\n              templateUrl: 'views/upload-cmmn-deployment.html',\n              controller: 'UploadCmmnDeploymentCtrl'\n          });\n          modalInstance.result.then(function (result) {\n              // Refresh page if closed successfully\n              if (result) {\n                  $scope.deploymentsData = {};\n                  $scope.filter.refresh();\n              }\n          });\n      };\n\n\n    }]);\n\n\n/**\n * Controller for the upload a model from the Case Modeler.\n */\n flowableAdminApp.controller('UploadCmmnDeploymentCtrl',\n    ['$scope', '$modalInstance', '$http', 'Upload', '$timeout', '$translate', function ($scope, $modalInstance, $http, Upload, $timeout, $translate) {\n\n    $scope.status = {loading: false};\n\n    $scope.model = {};\n\n    $scope.onFileSelect = function($files) {\n\n        for (var i = 0; i < $files.length; i++) {\n            var file = $files[i];\n            file.upload = Upload.upload({\n                url: FlowableAdmin.webContextRoot + '/app/rest/admin/cmmn-deployments',\n                method: 'POST',\n                data: {file: file}\n            });\n\n            file.upload.then(function (response) {\n                $timeout(function () {\n                    $scope.addAlert($translate.instant('ALERT.DEPLOYMENT.DEPLOYMENT-SUCCESS'), 'info');\n                    $scope.status.loading = false;\n                    $modalInstance.close(true);\n                });\n            }, function (response) {\n                if (response.data && response.data.message) {\n                    $scope.model.errorMessage = response.data.message;\n                }\n                $scope.model.error = true;\n                $scope.status.loading = false;\n            }, function (evt) {\n                file.progress = Math.min(100, parseInt(100.0 *\n                    evt.loaded / evt.total));\n            });\n        }\n    };\n\n    $scope.cancel = function () {\n        if (!$scope.status.loading) {\n            $modalInstance.dismiss('cancel');\n        }\n    };\n\n}]);\n"
  },
  {
    "path": "flowable-ui-web/admin/scripts/cmmn-job-controllers.js",
    "content": "/* Copyright 2005-2015 Alfresco Software, Ltd.\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'use strict';\n\nflowableAdminApp.controller('CmmnJobController', ['$scope', '$rootScope', '$http', '$timeout','$location','$routeParams', '$modal', '$translate',\n    function ($scope, $rootScope, $http, $timeout, $location, $routeParams, $modal, $translate) {\n\t\t$rootScope.navigation = {main: 'cmmn-engine', sub: 'jobs'};\n\t\t$scope.jobType = {\n\t\t\tparam: $routeParams.jobType\n\t\t}\n\t\t\n\t\t$scope.returnToList = function() {\n\t\t\t$location.path(\"/cmmn-jobs\").search({jobType: $scope.jobType.param});\n\t\t};\n\n\t\t$scope.openDefinition = function(definitionId) {\n\t\t\tif (definitionId) {\n\t\t\t\t$location.path(\"/case-definition/\" + definitionId);\n\t\t\t}\n\t\t};\n\n\t\t$scope.executeJob = function() {\n\t\t\t$http({method: 'POST', url: FlowableAdmin.webContextRoot + '/app/rest/admin/cmmn-jobs/' + $scope.job.id}).\n        \tsuccess(function(data, status, headers, config) {\n        \t  \t$scope.addAlert($translate.instant('ALERT.JOB.EXECUTED', $scope.job), 'info');\n        \t\t$scope.returnToList();\n        \t})\n        \t.error(function(data, status, headers, config) {\n        \t\t$scope.loadJob();\n        \t});\n\t\t};\n\t\t\n\t\t$scope.moveJob = function() {\n\t\t\t$http({method: 'POST', url: FlowableAdmin.webContextRoot + '/app/rest/admin/move-cmmn-jobs/' + $scope.job.id + '?jobType=' + $scope.jobType.param}).\n        \tsuccess(function(data, status, headers, config) {\n        \t  \t$scope.addAlert($translate.instant('ALERT.JOB.MOVED', $scope.job), 'info');\n        \t\t$scope.returnToList();\n        \t})\n        \t.error(function(data, status, headers, config) {\n        \t\t$scope.loadJob();\n        \t});\n\t\t};\n\n\t\t$scope.deleteJob = function() {\n\t\t\tvar modalInstance = $modal.open({\n\t\t\t\ttemplateUrl: 'views/job-delete-popup.html',\n\t\t\t\tcontroller: 'DeleteCmmnJobModalInstanceCtrl',\n\t\t\t\tresolve: {\n\t\t\t\t\tjob: function() {\n\t\t\t\t\t\treturn $scope.job;\n\t\t\t\t\t},\n\t\t\t\t\tjobType: function() {\n\t\t\t\t\t\treturn $scope.jobType;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\n\t\t\tmodalInstance.result.then(function (deletejob) {\n\t\t\t\tif(deletejob) {\n\t\t\t\t\t$scope.addAlert($translate.instant('ALERT.JOB.DELETED', $scope.job), 'info');\n\t\t\t\t\t$scope.returnToList();\n\t\t\t\t}\n\t\t\t});\n\t\t};\n\n\t\t$scope.openCaseInstance = function(caseInstanceId) {\n\t\t\tif (processInstanceId) {\n\t\t\t\t$location.path(\"/case-instance/\" + caseInstanceId);\n\t\t\t}\n\t\t};\n\n\t\t$scope.openCaseDefinition = function(caseDefinitionId) {\n\t\t\tif (processDefinitionId) {\n\t\t\t\t$location.path(\"/case-definition/\" + caseDefinitionId);\n\t\t\t}\n\t\t};\n\n\t\t$scope.loadJob = function() {\n\t\t\t$scope.job = {};\n\t\t\t$http({method: 'GET', url: FlowableAdmin.webContextRoot + '/app/rest/admin/cmmn-jobs/' + $routeParams.jobId + '?jobType=' + $scope.jobType.param}).\n\t    \tsuccess(function(data, status, headers, config) {\n\t            $scope.job = data;\n\n\t            if ($scope.job.exceptionMessage) {\n\t            \t// Fetch the full stacktrace, associated with this job\n\t            \t$http({method: 'GET', url: FlowableAdmin.webContextRoot + '/app/rest/admin/cmmn-jobs/' + $scope.job.id + '/stacktrace?jobType=' + $scope.jobType.param}).\n\t            \tsuccess(function(data, status, headers, config) {\n\t    \t            $scope.job.exceptionStack = data;\n\t            \t});\n\t            }\n\t    \t}).\n\t    \terror(function(data, status, headers, config) {\n                if (data && data.message) {\n                    // Extract error-message\n                    $rootScope.addAlert(data.message, 'error');\n                } else {\n                    // Use default error-message\n                    $rootScope.addAlert($translate.instant('ALERT.GENERAL.HTTP-ERROR'), 'error');\n                }\n            });\n\t\t};\n\n\t\t// Load job\n\t\t$scope.executeWhenReady(function() {\n\t\t    $scope.loadJob();\n\t\t});\n\n}]);\n\nflowableAdminApp.controller('DeleteCmmnJobModalInstanceCtrl',\n    ['$rootScope', '$scope', '$modalInstance', '$http', 'job', 'jobType', function ($rootScope, $scope, $modalInstance, $http, job, jobType) {\n\n\t  $scope.job = job;\n\t  $scope.jobType = jobType;\n\t  $scope.status = {loading: false};\n\n\t  $scope.ok = function () {\n\t\t  $scope.status.loading = true;\n\t\t  $http({method: 'DELETE', url: FlowableAdmin.webContextRoot + '/app/rest/admin/cmmn-jobs/' + $scope.job.id + '?jobType=' + jobType.param}).\n\t    \tsuccess(function(data, status, headers, config) {\n\t    \t\t$modalInstance.close(true);\n\t\t  \t\t$scope.status.loading = false;\n\t        }).\n\t        error(function(data, status, headers, config) {\n\t        \t$modalInstance.close(false);\n\t\t    \t$scope.status.loading = false;\n\t        });\n\t  };\n\n\t  $scope.cancel = function () {\n\t\tif(!$scope.status.loading) {\n\t\t\t$modalInstance.dismiss('cancel');\n\t\t}\n\t  };\n\t}]);\n"
  },
  {
    "path": "flowable-ui-web/admin/scripts/cmmn-jobs-controllers.js",
    "content": "/* Copyright 2005-2015 Alfresco Software, Ltd.\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'use strict';\n\n/* Controllers */\n\nflowableAdminApp.controller('CmmnJobsController', ['$scope', '$rootScope', '$http', '$timeout','$location','$translate', '$q', 'gridConstants', '$routeParams',\n    function ($scope, $rootScope, $http, $timeout, $location, $translate, $q, gridConstants, $routeParams) {\n\t\t$rootScope.navigation = {main: 'cmmn-engine', sub: 'jobs'};\n\t\t$scope.jobType = {\n\t\t\tparam: $routeParams.jobType\n\t\t}\n\t\t\n\t\t$scope.jobData = {};\n\t    $scope.selectedJobs = [];\n\n\t    var filterConfig = {\n\t\t    \turl: FlowableAdmin.webContextRoot + '/app/rest/admin/cmmn-jobs',\n\t\t    \tmethod: 'GET',\n\t\t    \tsuccess: function(data, status, headers, config) {\n\t\t    \t\tif ($scope.definitionCacheLoaded) {\n\t                \t$scope.processQueryResponse(data);\n\t                \t\n\t                } else {\n\t\t                $rootScope.loadCaseDefinitionsCache().then(function(promise) {\n  \t\t        \t\t\t$rootScope.caseDefinitionsCache = promise.data;\n  \t\t        \t\t\t$scope.definitionCacheLoaded = true;\n  \t\t        \t\t\t$scope.processQueryResponse(data);\n  \t\t        \t\t});\n\t                }\n\t            },\n\t            error: function(data, status, headers, config) {\n\t                if (data && data.message) {\n\t                    // Extract error-message\n\t                    $rootScope.addAlert(data.message, 'error');\n\t                } else {\n\t                    // Use default error-message\n\t                    $rootScope.addAlert($translate.instant('ALERT.GENERAL.HTTP-ERROR'), 'error');\n\t                }\n\t            },\n\t            \n\t            sortObjects: [\n\t                {name: 'JOBS.SORT.ID', id: 'id'},\n\t                {name: 'JOBS.SORT.DUE-DATE', id: 'dueDate'},\n\t                {name: 'JOBS.SORT.CASE-INSTANCE-ID', id: 'caseInstanceId'}\n\t            ],\n\t            \n\t            supportedProperties: [\n\t                {id: 'caseInstanceId', name: 'JOBS.FILTER.CASE-INSTANCE-ID'},\n\t                {id: 'tenantIdLike', name: 'JOBS.FILTER.TENANT-ID'},\n\t                {id: 'dueBefore', name: 'JOBS.FILTER.DUE-BEFORE', showByDefault: true},\n\t                {id: 'dueAfter', name: 'JOBS.FILTER.DUE-AFTER', showByDefault: true},\n\t                {id: 'withException', name: 'JOBS.FILTER.EXCEPTION'}\n\t            ]\n\t\t    };\n\n    \t\t\n\t    if ($rootScope.filters.forced.cmmnJobFilter) {\n\t    \t// Always recreate the filter and add all properties\n\t    \t$scope.filter = new FlowableAdmin.Utils.Filter(filterConfig, $http, $timeout, $rootScope);\n    \t\t$rootScope.filters.cmmnJobFilter = $scope.filter;\n    \t\t\n    \t\tfor (var prop in $rootScope.filters.forced.cmmnJobFilter) {\n    \t\t\t$scope.filter.addProperty({id: prop}, $rootScope.filters.forced.cmmnJobFilter[prop]);\n    \t\t}\n    \t\t\n    \t\t$rootScope.filters.forced.cmmnJobFilter = undefined;\n    \t\t\n\t    } else {\n\t    \tif ($rootScope.filters && $rootScope.filters.cmmnJobFilter) {\n\t    \t\t// Reuse the existing filter\n\t    \t\t$scope.filter = $rootScope.filters.cmmnJobFilter;\n\t    \t\t$scope.filter.config = filterConfig;\n\t    \t} else {\n\t    \t\t$scope.filter = new FlowableAdmin.Utils.Filter(filterConfig, $http, $timeout, $rootScope);\n\t    \t\t$rootScope.filters.cmmnJobFilter = $scope.filter;\n\t    \t}\n\t    }\n\t    \n\t    if ($scope.jobType.param) {\n\t    \t$scope.filter.jobType = $scope.jobType.param;\n\t    }\n\t    \n\t    if (!$scope.filter.jobType) {\n\t    \t$scope.filter.jobType = 'executableJob';\n\t    }\n\t    \n\t    $scope.filter.properties.jobType = $scope.filter.jobType;\n\t    \n\t    $scope.jobSelected = function(job) {\n\t    \tif (job && job.getProperty('id')) {\n\t    \t\t$location.path('/cmmn-job/' + job.getProperty('id')).search({jobType: $scope.filter.jobType});\n\t    \t}\n\t    };\n\t    \n\t    $q.all([$translate('JOBS.HEADER.ID'), \n\t            $translate('JOBS.HEADER.DUE-DATE'),\n\t            $translate('JOBS.HEADER.CASE-DEFINITION'),\n\t            $translate('JOBS.HEADER.RETRIES'),\n\t            $translate('JOBS.HEADER.EXCEPTION')])\n\t    .then(function(headers) { \n\n          // Config for grid\n          $scope.gridJobs = {\n              data: 'jobData.data',\n              enableRowReordering: true,\n              multiSelect: false,\n              keepLastSelected : false,\n              enableSorting: false,\n              rowHeight: 36,\n              afterSelectionChange: $scope.jobSelected,\n              columnDefs: [\n                  { field: 'id', displayName: headers[0], width: 50, cellTemplate: gridConstants.defaultTemplate},\n                  { field: 'dueDate', displayName: headers[1], cellTemplate: gridConstants.dateTemplate},\n                  { field: 'caseDefinition.name', displayName: headers[2], cellTemplate: gridConstants.defaultTemplate},\n                  { field: 'retries', displayName: headers[3], width: 50, cellTemplate: gridConstants.defaultTemplate},\n                  { field: 'exceptionMessage', displayName: headers[4], width: 150, cellTemplate: gridConstants.defaultTemplate}\n              ]\n          };\n\t    });\n        \n        $scope.processQueryResponse = function(jobsResponse) {\n        \tfor (var i = 0; i < jobsResponse.data.length; i++) {\n        \t\tjobsResponse.data[i].caseDefinition = \n            \t\t$rootScope.getCaseDefinitionFromCache(jobsResponse.data[i].caseDefinitionId);\n            \t\n            }\n        \t$scope.jobData = jobsResponse;\n        };\n        \n        $scope.jobTypeFilterChanged = function()  {\n        \t$scope.filter.properties.jobType = $scope.filter.jobType;\n        \t$scope.filter.refresh();\n        };\n        \n        $scope.caseDefinitionFilterChanged = function()  {\n        \tif ($scope.filter.caseDefinition && $scope.filter.caseDefinition !== '-1') {\n        \t\t$scope.filter.properties.caseDefinitionId = $scope.filter.caseDefinition;\n        \t\t$scope.filter.refresh();\n        \t\t\n        \t} else {\n        \t\tvar tempCaseDefinitionId = $scope.filter.properties.caseDefinitionId;\n        \t\t$scope.filter.properties.caseDefinitionId = null;\n        \t\tif (tempCaseDefinitionId && tempCaseDefinitionId.length > 0) {\n        \t\t\t$scope.filter.refresh();\n        \t\t}\n        \t}\n        };\n        \n        $scope.executeWhenReady(function() {\n          \t$scope.filter.refresh();\n        });\n    }]);\n"
  },
  {
    "path": "flowable-ui-web/admin/scripts/cmmn-task-controllers.js",
    "content": "/* Copyright 2005-2015 Alfresco Software, Ltd.\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'use strict';\n\nflowableAdminApp.controller('CmmnTaskController', ['$scope', '$rootScope', '$http', '$timeout','$location','$routeParams', '$modal', '$translate', '$q', 'gridConstants',\n    function ($scope, $rootScope, $http, $timeout, $location, $routeParams, $modal, $translate, $q, gridConstants) {\n\n        $rootScope.navigation = {main: 'cmmn-engine', sub: 'tasks'};\n\t\t\n\t\t$scope.tabData = {\n            tabs: [\n               {id: 'subTasks', name: 'TASK.TITLE.SUBTASKS'},\n               {id: 'variables', name: 'TASK.TITLE.VARIABLES'},\n               {id: 'identityLinks', name: 'TASK.TITLE.IDENTITY-LINKS'}\n            ],\n        };\n\n\t\t$scope.tabData.activeTab = $scope.tabData.tabs[0].id;\n\n\t\t$scope.returnToList = function() {\n\t\t\t$location.path(\"/tasks\");\n\t\t};\n\n\t\t$scope.openTask = function(taskId) {\n\t\t\tif (taskId) {\n\t\t\t\t$location.path(\"/task/\" + taskId);\n\t\t\t}\n\t\t};\n\n\t\t$scope.openCaseInstance = function(caseInstanceId) {\n\t\t\tif (caseInstanceId) {\n\t\t\t\t$location.path(\"/case-instance/\" + caseInstanceId);\n\t\t\t}\n\t\t};\n\n\t\t$scope.openCaseDefinition = function(caseDefinitionId) {\n\t\t\tif (caseDefinitionId) {\n\t\t\t\t$location.path(\"/case-definition/\" + caseDefinitionId);\n\t\t\t}\n\t\t};\n\n\t\t$scope.loadTask = function() {\n\t\t\t$scope.task = undefined;\n\t\t\t// Load task\n\t\t\t$http({method: 'GET', url: FlowableAdmin.webContextRoot + '/app/rest/admin/cmmn-tasks/' + $routeParams.taskId}).\n\t\t\tsuccess(function(data, status, headers, config) {\n\t\t\t\t$scope.task = data;\n\n\t\t\t\tif(data) {\n\t\t\t\t\t$scope.taskCompleted = data.endTime != undefined;\n\t\t\t\t\t$scope.taskPartOfCase = data.caseInstanceId != undefined;\n\t\t\t\t}\n\n\t\t\t\t// Load runtime-task, if available, for accurate delegation-state\n\t\t\t\t$scope.loadRuntimeTask();\n\n\t\t\t\t// Start loading children\n\t\t\t\t$scope.loadSubTasks();\n\t\t\t\t$scope.loadVariables();\n\t\t\t\t$scope.loadIdentityLinks();\n\t\t\t}).\n\t\t\terror(function(data, status, headers, config) {\n                if (data && data.message) {\n                    // Extract error-message\n                    $rootScope.addAlert(data.message, 'error');\n                } else {\n                    // Use default error-message\n                    $rootScope.addAlert($translate.instant('ALERT.GENERAL.HTTP-ERROR'), 'error');\n                }\n            });\n\t\t};\n\n\t\t$scope.loadRuntimeTask = function() {\n\t\t\tif($scope.task && !$scope.taskCompleted) {\n\t\t\t\t// Load runtime task, if available to fetch delegation state\n\t\t\t\t$http({method: 'GET', url: FlowableAdmin.webContextRoot + '/app/rest/admin/cmmn-tasks/' + $routeParams.taskId,\n\t\t\t\t\tparams: {runtime: 'true'}}).\n\t\t\t\tsuccess(function(data, status, headers, config) {\n\t\t\t\t\t// Workaround for pre 5.15 installs, historic assignee is not updated when set to null\n\t\t\t\t\t$scope.task.assignee = data.assignee;\n\t\t\t\t\tif(data.delegationState) {\n\t\t\t\t\t\t$scope.task.delegationState = data.delegationState;\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// Use empty string to trigger delegate-button to show when delegationState is loaded\n\t\t\t\t\t\t$scope.task.delegationState = '';\n\t\t\t\t\t}\n\t\t\t\t\t$scope.task.delegationStateLoaded = true;\n\t\t\t\t});\n\t\t\t}\n\t\t};\n\n\t\t$scope.subTaskSelected = function(task) {\n\t    \tif(task && task.getProperty('id')) {\n\t    \t\t$scope.openTask(task.getProperty('id'));\n\t    \t}\n\t\t};\n\t  // Config for subtasks grid\n    $q.all([$translate('TASKS.HEADER.ID'),\n             $translate('TASKS.HEADER.NAME'),\n             $translate('TASKS.HEADER.ASSIGNEE'),\n             $translate('TASKS.HEADER.OWNER')])\n    .then(function(headers) {\n        $scope.subTaskGridDefinitions = {\n            data: 'subTasks.data',\n            enableRowReordering: false,\n            multiSelect: false,\n            keepLastSelected : false,\n            enableSorting: false,\n            rowHeight: 36,\n            afterSelectionChange: $scope.subTaskSelected,\n            columnDefs: [\n                { field: 'id', displayName: headers[0], width: 50, cellTemplate: gridConstants.defaultTemplate},\n                { field: 'name', displayName: headers[1], cellTemplate: gridConstants.defaultTemplate},\n                { field: 'assignee', displayName: headers[2], width: 100, cellTemplate: gridConstants.defaultTemplate},\n                { field: 'owner', displayName: headers[3], width: 100, cellTemplate: gridConstants.defaultTemplate}\n            ]\n        };\n    });\n\n    $q.all([$translate('VARIABLES.HEADER.NAME'),\n            $translate('VARIABLES.HEADER.TYPE'),\n            $translate('VARIABLES.HEADER.VALUE')])\n   .then(function(headers) {\n        var variableValueTemplate = '<div><div class=\"ngCellText\">{{row.getProperty(\"variable.valueUrl\") && \"(Binary)\" || row.getProperty(col.field)}}</div></div>';\n        var variableTypeTemplate = '<div><div class=\"ngCellText\">{{row.getProperty(col.field) && row.getProperty(col.field) || \"null\"}}</div></div>';\n        // Config for variable grid\n        $scope.variableGridDefinitions = {\n            data: 'variables.data',\n            enableRowReordering: false,\n            multiSelect: false,\n            keepLastSelected : false,\n            enableSorting: false,\n            rowHeight: 36,\n            columnDefs: [\n                { field: 'variable.name', displayName: headers[0]},\n                { field: 'variable.type', displayName: headers[1], cellTemplate: variableTypeTemplate},\n                { field: 'variable.value', displayName: headers[2], cellTemplate: variableValueTemplate}\n            ]\n        };\n   });\n\n    $q.all([$translate('IDENTITY-LINKS.HEADER.TYPE'),\n            $translate('IDENTITY-LINKS.HEADER.GROUP-ID'),\n            $translate('IDENTITY-LINKS.HEADER.USER-ID')])\n   .then(function(headers) {\n        // Config for variable grid\n        $scope.identityLinkGridDefinitions = {\n            data: 'identityLinks.data',\n            enableRowReordering: false,\n            multiSelect: false,\n            keepLastSelected : false,\n            enableSorting: false,\n            rowHeight: 36,\n            columnDefs: [\n                { field: 'type', displayName: headers[0]},\n                { field: 'groupId', displayName: headers[1], cellTemplate: gridConstants.defaultTemplate},\n                { field: 'userId', displayName: headers[2], cellTemplate: gridConstants.defaultTemplate}\n            ]\n        };\n   });\n\n\n        $scope.showAllSubtasks = function() {\n        \t// Populate the task-filter with parentId\n        \t$rootScope.filters.forced.cmmnTaskFilter = {\n        \t\tparentTaskId: $scope.task.id\n        \t};\n\n        \t$scope.returnToList();\n        };\n\n\t\t$scope.loadSubTasks = function() {\n\t\t\t$scope.subTasks = undefined;\n\t\t\t$http({method: 'GET', url: FlowableAdmin.webContextRoot + '/app/rest/admin/cmmn-tasks/' + $scope.task.id +'/subtasks'}).\n\t\t\tsuccess(function(data, status, headers, config) {\n\t\t\t\t$scope.subTasks = data;\n\t\t\t\t$scope.tabData.tabs[0].info = data.total;\n\t\t\t});\n\t\t};\n\n\t\t$scope.loadVariables = function() {\n\t\t\t$scope.variables = undefined;\n\t\t\t$http({method: 'GET', url: FlowableAdmin.webContextRoot + '/app/rest/admin/cmmn-tasks/' + $scope.task.id +'/variables'}).\n\t\t\tsuccess(function(data, status, headers, config) {\n\t\t\t\t$scope.variables = data;\n\t\t\t\t$scope.tabData.tabs[1].info = data.total;\n\t\t\t});\n\t\t};\n\n\t\t$scope.loadIdentityLinks = function() {\n\t\t\t$scope.identityLinks = undefined;\n\t\t\t$http({method: 'GET', url: FlowableAdmin.webContextRoot + '/app/rest/admin/cmmn-tasks/' + $scope.task.id +'/identitylinks'}).\n\t\t\tsuccess(function(data, status, headers, config) {\n\t\t\t\t$scope.identityLinks = {data: data, size: data.length};\n\t\t\t\t$scope.tabData.tabs[2].info = data.length;\n\t\t\t});\n\t\t};\n\t\t\n\t\t$scope.showTaskForm = function() {\n\t\t    if($scope.task.endTime) {\n\t\t        $http({method: 'GET', url: FlowableAdmin.webContextRoot + '/app/rest/admin/task-form-instance/' + $scope.task.id}).\n\t            success(function(data, status, headers, config) {\n\t                $rootScope.submittedForm = data.data[0]; // saving fetched submitted form in root scope to avoid another fetch in submitted form controller\n\t                $location.path(\"/form-instance/\" + data.data[0].id);\n\t            });\n\t\t    }\n\t\t};\n\n\t\t// Initial load of task\n\n\t\t$scope.executeWhenReady(function() {\n        $scope.loadTask();\n    });\n\n\n\t\t// Dialogs\n\t\tvar resolve = {\n\t\t\t// Reference the current task\n\t\t\ttask: function () {\n\t          return $scope.task;\n\t        }\n\t\t};\n\n\t\t$scope.deleteTask = function() {\n\t\t\tvar modalInstance = $modal.open({\n\t\t\t\ttemplateUrl: 'views/task-delete-popup.html',\n\t\t\t\tcontroller: 'CmmnDeleteTaskModalInstanceCtrl',\n\t\t\t\tresolve: resolve\n\t\t\t});\n\n\t\t\tmodalInstance.result.then(function (deleteTask) {\n\t\t\t\tif(deleteTask) {\n\t\t\t\t  $scope.addAlert($translate.instant('ALERT.TASK.DELETED', $scope.task), 'info');\n\t\t\t\t\t$scope.returnToList();\n\t\t\t\t}\n\t\t\t});\n\t\t};\n\n\t\t$scope.completeTask = function() {\n\t\t\tvar modalInstance = $modal.open({\n\t\t\t\ttemplateUrl: 'views/task-complete-popup.html',\n\t\t\t\tcontroller: 'CmmnCompleteModalInstanceCtrl',\n\t\t\t\tresolve: resolve\n\t\t\t});\n\n\t\t\tmodalInstance.result.then(function (completeTask) {\n\t\t\t\tif(completeTask) {\n\t\t\t\t  $scope.addAlert($translate.instant('ALERT.TASK.COMPLETED', $scope.task), 'info');\n\t\t\t\t\t$scope.loadTask();\n\t\t\t\t}\n\t\t\t});\n\t\t};\n\n\t\t$scope.delegateTask = function() {\n\t\t\tvar modalInstance = $modal.open({\n\t\t\t\ttemplateUrl: 'views/task-delegate-popup.html',\n\t\t\t\tcontroller: 'CmmnDelegateModalInstanceCtrl',\n\t\t\t\tresolve: resolve\n\t\t\t});\n\n\t\t\tmodalInstance.result.then(function (user) {\n\t\t\t\tif(user) {\n\t\t\t\t\t$scope.addAlert($translate.instant('ALERT.TASK.DELEGATED', {id: $scope.task.id, user: user}), 'info');\n\t\t\t\t\t$scope.loadTask();\n\t\t\t\t}\n\t\t\t});\n\t\t};\n\n\t\t$scope.resolveTask = function() {\n\t\t\tvar modalInstance = $modal.open({\n\t\t\t\ttemplateUrl: 'views/task-resolve-popup.html',\n\t\t\t\tcontroller: 'CmmnResolveTaskModalInstanceCtrl',\n\t\t\t\tresolve: resolve\n\t\t\t});\n\n\t\t\tmodalInstance.result.then(function (user) {\n\t\t\t\tif(user) {\n\t\t\t\t  $scope.addAlert($translate.instant('ALERT.TASK.RESOLVED', $scope.task), 'info');\n\t\t\t\t\t$scope.loadTask();\n\t\t\t\t}\n\t\t\t});\n\t\t};\n\n\t\t$scope.assignTask = function() {\n\t\t\tvar modalInstance = $modal.open({\n\t\t\t\ttemplateUrl: 'views/task-assign-popup.html',\n\t\t\t\tcontroller: 'CmmnAssignModalInstanceCtrl',\n\t\t\t\tresolve: resolve\n\t\t\t});\n\n\t\t\tmodalInstance.result.then(function (user) {\n\t\t\t\tif(user !== undefined) {\n\t\t\t\t\tif(user == '') {\n\t\t\t\t\t\t$scope.addAlert($translate.instant('ALERT.TASK.UNASSIGNED', $scope.task), 'info');\n\t\t\t\t\t} else {\n\t\t\t\t\t  $scope.addAlert($translate.instant('ALERT.TASK.ASSIGNED', {id: $scope.task.id, user: user}), 'info');\n\t\t\t\t\t}\n\t\t\t\t\t$scope.loadTask();\n\t\t\t\t}\n\t\t\t});\n\t\t};\n\n\t\t$scope.editTask = function() {\n\t\t\tvar modalInstance = $modal.open({\n\t\t\t\ttemplateUrl: 'views/task-edit-popup.html',\n\t\t\t\tcontroller: 'CmmnEditTaskModalInstanceCtrl',\n\t\t\t\tresolve: resolve\n\t\t\t});\n\n\t\t\tmodalInstance.result.then(function (taskUpdated) {\n\t\t\t\tif(taskUpdated) {\n\t\t\t\t  $scope.addAlert($translate.instant('ALERT.TASK.UPDATED', $scope.task), 'info');\n\t\t\t\t\t$scope.loadTask();\n\t\t\t\t}\n\t\t\t});\n\t\t};\n}]);\n\n\n// Popup controllers\nflowableAdminApp.controller('CmmnCompleteModalInstanceCtrl',\n    ['$rootScope', '$scope', '$modalInstance', '$http', 'task', function ($rootScope, $scope, $modalInstance, $http, task) {\n\n  $scope.task = task;\n  $scope.status = {loading: false};\n\n  $scope.ok = function () {\n\t  $scope.status.loading = true;\n\t  $http({method: 'POST', url: FlowableAdmin.webContextRoot + '/app/rest/admin/cmmn-tasks/' + $scope.task.id, data: {action: 'complete'}}).\n  \t  success(function(data, status, headers, config) {\n  \t\t$modalInstance.close(true);\n  \t\t$scope.status.loading = false;\n      }).error(function(data, status, headers, config) {\n    \t $modalInstance.close(false);\n    \t $scope.status.loading = false;\n      });\n  };\n\n  $scope.cancel = function () {\n\t  if(!$scope.status.loading) {\n\t\t$modalInstance.dismiss('cancel');\n\t}\n  };\n}]);\n\nflowableAdminApp.controller('CmmnResolveTaskModalInstanceCtrl',\n    ['$rootScope', '$scope', '$modalInstance', '$http', 'task', function ($rootScope, $scope, $modalInstance, $http, task) {\n\n  $scope.task = task;\n  $scope.status = {loading: false};\n\n  $scope.ok = function () {\n\t  $scope.status.loading = true;\n\t  $http({method: 'POST', url: FlowableAdmin.webContextRoot + '/app/rest/admin/cmmn-tasks/' + $scope.task.id, data: {action: 'resolve'}}).\n  \t  success(function(data, status, headers, config) {\n  \t\t$modalInstance.close(true);\n  \t\t$scope.status.loading = false;\n      }).error(function(data, status, headers, config) {\n    \t $modalInstance.close(false);\n    \t $scope.status.loading = false;\n      });\n  };\n\n  $scope.cancel = function () {\n\t  if(!$scope.status.loading) {\n\t\t$modalInstance.dismiss('cancel');\n\t}\n  };\n}]);\n\nflowableAdminApp.controller('CmmnDeleteTaskModalInstanceCtrl',\n    ['$rootScope', '$scope', '$modalInstance', '$http', 'task', function ($rootScope, $scope, $modalInstance, $http, task) {\n\n  $scope.task = task;\n  $scope.status = {loading: false};\n\n\n  $scope.ok = function () {\n\t  $scope.status.loading = true;\n\t  $http({method: 'DELETE', url: FlowableAdmin.webContextRoot + '/app/rest/admin/cmmn-tasks/' + $scope.task.id}).\n    \tsuccess(function(data, status, headers, config) {\n    \t\t$modalInstance.close(true);\n\t  \t\t$scope.status.loading = false;\n        }).\n        error(function(data, status, headers, config) {\n        \t$modalInstance.close(false);\n\t    \t $scope.status.loading = false;\n        });\n  };\n\n  $scope.cancel = function () {\n\tif(!$scope.status.loading) {\n\t\t$modalInstance.dismiss('cancel');\n\t}\n  };\n}]);\n\n\nflowableAdminApp.controller('CmmnDelegateModalInstanceCtrl',\n    ['$rootScope', '$scope', '$modalInstance', '$http', 'task', function ($rootScope, $scope, $modalInstance, $http, task) {\n\n  $scope.task = task;\n  $scope.status = {loading: false};\n\n  $scope.ok = function () {\n\t  $scope.status.loading = true;\n\t  $http({method: 'POST', url: FlowableAdmin.webContextRoot + '/app/rest/admin/cmmn-tasks/' + $scope.task.id, data: {action: 'delegate', assignee: $scope.status.user}}).\n  \t  success(function(data, status, headers, config) {\n  \t    if ($scope.newAssignee && $scope.newAssignee.name) {\n  \t      $modalInstance.close($scope.newAssignee.name);\n  \t    } else {\n  \t      $modalInstance.close($scope.status.user);\n  \t    }\n  \t\t$scope.status.loading = false;\n      }).error(function(data, status, headers, config) {\n    \t $modalInstance.close(false);\n    \t $scope.status.loading = false;\n      });\n  };\n\n  $scope.cancel = function () {\n\tif(!$scope.status.loading) {\n\t\t$modalInstance.dismiss('cancel');\n\t}\n  };\n}]);\n\nflowableAdminApp.controller('CmmnAssignModalInstanceCtrl',\n    ['$rootScope', '$scope', '$modalInstance', '$http', 'task', function ($rootScope, $scope, $modalInstance, $http, task) {\n\n\t  $scope.task = task;\n\t  $scope.status = {loading: false};\n\n\t  $scope.ok = function () {\n\t\t  $scope.status.loading = true;\n\t\t  var rawUserValue = $scope.status.user;\n\t\t  var resultUserValue = $scope.status.user;\n\t\t  if(!$scope.status.user) {\n\t\t\t  rawUserValue = null;\n\t\t\t  resultUserValue = '';\n\t\t  } else if ($scope.newAssignee && $scope.newAssignee.name) {\n\t\t      resultUserValue = $scope.newAssignee.name;\n\t\t  }\n\t\t  $http({method: 'PUT', url: FlowableAdmin.webContextRoot + '/app/rest/admin/cmmn-tasks/' + $scope.task.id, data: {assignee: rawUserValue}}).\n\t  \t  success(function(data, status, headers, config) {\n\t  \t\t$modalInstance.close(resultUserValue);\n\t  \t\t$scope.status.loading = false;\n\t      }).error(function(data, status, headers, config) {\n\t    \t $modalInstance.close(false);\n\t    \t $scope.status.loading = false;\n\t      });\n\t  };\n\n\t  $scope.cancel = function () {\n\t\tif(!$scope.status.loading) {\n\t\t\t$modalInstance.dismiss('cancel');\n\t\t}\n\t  };\n\t}]);\n\nflowableAdminApp.controller('CmmnEditTaskModalInstanceCtrl',\n    ['$rootScope', '$scope', '$modalInstance', '$http', 'task', function ($rootScope, $scope, $modalInstance, $http, task) {\n\n      $scope.task = task;\n\t  $scope.model = {\n\t\t  name: task.name,\n\t\t  description: task.description,\n\t\t  owner: task.owner,\n\t\t  assignee: task.assignee,\n\t\t  dueDate: task.dueDate,\n\t\t  priority: task.priority,\n\t\t  category: task.category,\n\t  };\n\n\t  $scope.status = {loading: false};\n\n\t  $scope.ok = function () {\n\t\t  $scope.status.loading = true;\n\t\t  $http({method: 'PUT', url: FlowableAdmin.webContextRoot + '/app/rest/admin/cmmn-tasks/' + $scope.task.id, data: $scope.model}).\n\t  \t  success(function(data, status, headers, config) {\n\t  \t\t$modalInstance.close(true);\n\t  \t\t$scope.status.loading = false;\n\t      }).error(function(data, status, headers, config) {\n\t    \t $modalInstance.close(false);\n\t    \t $scope.status.loading = false;\n\t      });\n\t  };\n\n\t  $scope.cancel = function () {\n\t\tif(!$scope.status.loading) {\n\t\t\t$modalInstance.dismiss('cancel');\n\t\t}\n\t  };\n\t}]);\n"
  },
  {
    "path": "flowable-ui-web/admin/scripts/cmmn-tasks-controllers.js",
    "content": "/* Copyright 2005-2015 Alfresco Software, Ltd.\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'use strict';\n\n/* Controllers */\n\nflowableAdminApp.controller('CmmnTasksController', ['$scope', '$rootScope', '$http', '$timeout','$location','$translate', '$q', 'gridConstants',\n    function ($scope, $rootScope, $http, $timeout, $location, $translate, $q, gridConstants) {\n\t\t$rootScope.navigation = {main: 'cmmn-engine', sub: 'tasks'};\n        \n\t\t$scope.taskData = {};\n\t\t$scope.selectedTasks = [];\n\t  \n\t\t$scope.variableFilterTypes = FlowableAdmin.Utils.variableFilterTypes;\n\t\t$scope.variableFilterOperators = FlowableAdmin.Utils.variableFilterOperators;\n\n\t    var filterConfig = {\n\t\t    \turl: FlowableAdmin.webContextRoot + '/app/rest/admin/cmmn-tasks',\n\t\t    \tmethod: 'POST',\n\t\t    \tsuccess: function(data, status, headers, config) {\n\t                $scope.taskData = data;\n\t            },\n\t            error: function(data, status, headers, config) {\n\t                if (data && data.message) {\n\t                    // Extract error-message\n\t                    $rootScope.addAlert(data.message, 'error');\n\t                } else {\n\t                    // Use default error-message\n\t                    $rootScope.addAlert($translate.instant('ALERT.GENERAL.HTTP-ERROR'), 'error');\n\t                }\n\t            },\n\t            \n\t            sortObjects: [\n\t                {name: 'TASKS.SORT.NAME', id: 'name'},\n\t                {name: 'TASKS.SORT.DUE-DATE', id: 'dueDate'},\n\t                {name: 'TASKS.SORT.START-TIME', id: 'start'},\n\t                {name: 'TASKS.SORT.END-TIME', id: 'endTime'},\n\t                {name: 'TASKS.SORT.PRIORITY', id: 'priority'}\n\t            ],\n\t            \n\t            options: {\n\t            \tfinished: [\n\t                 \t{name: 'TASKS.FILTER.STATUS-ANY', value: ''},\n\t                 \t{name: 'TASKS.FILTER.STATUS-ACTIVE', value: 'false'},\n\t                 \t{name: 'TASKS.FILTER.STATUS-COMPLETE', value: 'true'}\n\t                ]\n\t            },\n\t            \n\t            supportedProperties: [\n\t                {id: 'finished', name: 'TASKS.FILTER.FINISHED', showByDefault: true},\n\t                {id: 'taskNameLike', name: 'TASKS.FILTER.NAME', showByDefault: true},\n\t                {id: 'taskAssignee', name: 'TASKS.FILTER.ASSIGNEE', showByDefault: true},\n\t                {id: 'taskOwner', name: 'TASKS.FILTER.OWNER'},\n\t                {id: 'parentTaskId', name: 'TASKS.FILTER.PARENT-TASK-ID'},\n\t                {id: 'caseInstanceId', name: 'TASKS.FILTER.CASE-INSTANCE-ID'},\n\t                {id: 'tenantIdLike', name: 'TASKS.FILTER.TENANT-ID'},\n\t                {id: 'dueBefore', name: 'TASKS.FILTER.DUE-BEFORE'},\n\t                {id: 'dueAfter', name: 'TASKS.FILTER.DUE-AFTER'},\n\t                {id: 'taskCreatedBefore', name: 'TASKS.FILTER.CREATED-BEFORE'},\n\t                {id: 'taskCreatedAfter', name: 'TASKS.FILTER.CREATED-AFTER'},\n\t                {id: 'taskCompletedBefore', name: 'TASKS.FILTER.ENDED-BEFORE'},\n\t                {id: 'taskCompletedAfter', name: 'TASKS.FILTER.ENDED-AFTER'},\n\t                {id: 'taskVariables', name: 'TASKS.FILTER.TASK-VARIABLE'}\n\t            ]\n\t\t    };\n\n\t    if ($rootScope.filters.forced.cmmnTaskFilter) {\n\t    \t// Always recreate the filter and add all properties\n\t    \t$scope.filter = new FlowableAdmin.Utils.Filter(filterConfig, $http, $timeout, $rootScope);\n    \t\t$rootScope.filters.cmmnTaskFilter = $scope.filter;\n    \t\t\n    \t\tfor (var prop in $rootScope.filters.forced.cmmnTaskFilter) {\n    \t\t\t$scope.filter.addProperty({id: prop}, $rootScope.filters.forced.cmmnTaskFilter[prop]);\n    \t\t}\n    \t\t\n    \t\t$rootScope.filters.forced.cmmnTaskFilter = undefined;\n    \t\t\n\t    } else {\n\t    \tif ($rootScope.filters && $rootScope.filters.cmmnTaskFilter) {\n\t    \t\t// Reuse the existing filter\n\t    \t\t$scope.filter = $rootScope.filters.cmmnTaskFilter;\n\t    \t\t$scope.filter.config = filterConfig;\n\t    \t} else {\n\t    \t\t$scope.filter = new FlowableAdmin.Utils.Filter(filterConfig, $http, $timeout, $rootScope);\n\t    \t\t$rootScope.filters.cmmnTaskFilter = $scope.filter;\n\t    \t}\n\t    }\n\t    \n\t    \n        $scope.filter.properties.taskVariables = [];\n      \n      // Set value-filter callback to convert variables to nice format\n      $scope.filter.config.valueFilter = function(prop, value) {\n        if(prop == 'taskVariables') {\n          var actualValue = [];\n          var variable;\n          for(var i=0; i<value.length; i++) {\n            variable = value[i];\n            \n            if(variable.name && variable.type && variable.value !== undefined && variable.value !== '' && variable.operator) {\n              var varPayload =  {\n                  name: variable.name,\n                  value: variable.value,\n                  operation: variable.operator.id,\n                  type: variable.type.id\n              };\n              \n              if(variable.type.id == 'long' || variable.type.id == 'short' || variable.type.id == 'double' || variable.type.id == 'integer') {\n                varPayload.value = parseFloat(varPayload.value);\n                if(!isNaN(varPayload.value)) {\n                  // Return valid value for number\n                  actualValue.push(varPayload);\n                }\n              } else {\n                // Return valid value\n                actualValue.push(varPayload);\n              }\n            }\n          }\n          return actualValue;\n        } else {\n          return value;\n        }\n      };\n      \n      $scope.clearFilters = function() {\n        $scope.filter.clear();\n        $scope.filter.properties.taskVariables = [];\n      };\n      \n      $scope.setVariableFilterType = function(varFilter, type) {\n        \n        varFilter.value = undefined;\n        if(type.id == 'boolean') {\n          varFilter.value = true;\n          \n          if(varFilter.operator.id != 'equals') {\n            varFilter.operator = $scope.variableFilterOperators[0];\n          }\n        }\n        \n        varFilter.type = type;\n        $scope.highlightVariableValue(varFilter);\n        $scope.filter.refresh();\n      };\n      \n      $scope.setVariableFilterOperator = function(varFilter, operator) {\n        if(operator.id == 'like') {\n          varFilter.value = '';\n          varFilter.type = $scope.variableFilterTypes[0];\n        }\n        \n        if(varFilter.type.id == 'boolean' && operator.id != 'equals') {\n          varFilter.operator = $scope.variableFilterOperators[0];\n        } else {\n          varFilter.operator = operator;\n        }\n        $scope.highlightVariableValue(varFilter);\n        $scope.filter.refresh();\n      };\n      \n      $scope.highlightVariableValue = function(varFilter) {\n        var index = -1;\n        for(var i=0; i<$scope.filter.properties[varFilter.scope].length; i++) {\n          if(varFilter == $scope.filter.properties[varFilter.scope][i]) {\n            index = i;\n            break;\n          }\n        }\n        \n        $timeout(function() {\n          var formField = $('#filter-' + varFilter.scope + '-value-' + index);\n          formField.focus();\n        }, 100);\n      };\n      \n      $scope.addFilterProperty = function(prop) {\n        if (prop.id != 'taskVariables') {\n          $scope.filter.addProperty(prop);\n        } else {\n            $scope.filter.properties[prop.id].push({\n                type: $scope.variableFilterTypes[0],\n                operator: $scope.variableFilterOperators[0],\n                scope: prop.id\n            });\n              \n            $timeout(function() {\n                var formField = $('#filter-' + prop.id + '-name-' + ($scope.filter.properties[prop.id].length - 1));\n                formField.focus();\n            }, 100);\n        }\n      };\n\t    \n\t    $scope.taskSelected = function(task) {\n\t    \tif(task && task.getProperty('id')) {\n\t    \t\t$location.path('/cmmn-task/' + task.getProperty('id'));\n\t    \t}\n\t    };\n\t    \n\t    $q.all([$translate('TASKS.HEADER.ID'), \n\t            $translate('TASKS.HEADER.NAME'),\n\t            $translate('TASKS.HEADER.ASSIGNEE'),\n\t            $translate('TASKS.HEADER.OWNER'),\n\t            $translate('TASKS.HEADER.CREATE-TIME'),\n\t            $translate('TASKS.HEADER.END-TIME'),\n\t            $translate('TASKS.HEADER.PRIORITY')])\n\t    .then(function(headers) { \n\n          $scope.gridDefinitions = {\n              data: 'taskData.data',\n              enableRowReordering: true,\n              multiSelect: false,\n              keepLastSelected : false,\n              enableSorting: false,\n              rowHeight: 36,\n              afterSelectionChange: $scope.taskSelected,\n              columnDefs: [{ field: 'id', displayName: headers[0], width: 50, cellTemplate: gridConstants.defaultTemplate},\n                  { field: 'name', displayName: headers[1], cellTemplate: gridConstants.defaultTemplate},\n                  { field: 'assignee', displayName: headers[2], width: 150, cellTemplate: gridConstants.defaultTemplate},\n                  { field: 'owner', displayName: headers[3], width: 150, cellTemplate: gridConstants.defaultTemplate},\n                  { field: 'startTime', displayName: headers[4], cellTemplate: gridConstants.dateTemplate},\n                  { field: 'endTime', displayName: headers[5], cellTemplate: gridConstants.dateTemplate},\n                  { field: 'priority', displayName: headers[6], cellTemplate: gridConstants.defaultTemplate}\n              ]\n          };\n\t    });\n        \n        // Task state filtering\n        $scope.getTaskStateLabel = function(value) {\n        \tfor(var i=0; i<$scope.filter.config.taskStates.length; i++) {\n        \t\tvar state = $scope.filter.config.taskStates[i];\n        \t\tif(value == state.value) {\n        \t\t\treturn state.name;\n        \t\t}\n        \t}\n        \treturn $scope.filter.config.taskStates[0].name;\n        };\n        \n        $scope.setStateFilter = function(state) {\n        \tif(state.value !== $scope.filter.properties.finished) {\n        \t\t$scope.filter.properties.finished = state.value;\n        \t\t$scope.filter.refresh();\n        \t}\n        };\n        \n        $scope.executeWhenReady(function() {\n          $scope.filter.refresh();\n        });\n    }]);\n"
  },
  {
    "path": "flowable-ui-web/admin/scripts/config.js",
    "content": "/* Copyright 2005-2015 Alfresco Software, Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n *\n * Global fixed configuration values for Flowable Admin app.\n *\n */\nvar FlowableAdmin = {};\n\nFlowableAdmin.webContextRoot = '/flowable_admin';\nFlowableAdmin.Config = {};\n\n// General settings\nFlowableAdmin.Config.alert = {};\nFlowableAdmin.Config.alert.infoDisplayTime = 3000;\nFlowableAdmin.Config.alert.errorDisplayTime = 5000;\n\n// Filter settings\nFlowableAdmin.Config.filter = {};\nFlowableAdmin.Config.filter.resultSizes = [10, 25, 50, 100, 100000000];    // fairly large number for 'all'\nFlowableAdmin.Config.filter.defaultResultSize = 25;\nFlowableAdmin.Config.filter.defaultOrder = \"asc\";\nFlowableAdmin.Config.filter.delay = 400;\n\n// Localization\nFlowableAdmin.Config.localization = {};\nFlowableAdmin.Config.localization.dates = false;\n"
  },
  {
    "path": "flowable-ui-web/admin/scripts/constants.js",
    "content": "/* Copyright 2005-2015 Alfresco Software, Ltd.\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'use strict';\n\nangular.module('flowableAdminApp')\n    .constant('gridConstants', {\n        defaultTemplate : '<div><div class=\"ngCellText\" title=\"{{row.getProperty(col.field)}}\">{{row.getProperty(col.field)}}</div></div>',\n        dateTemplate : '<div><div class=\"ngCellText\" title=\"{{row.getProperty(col.field) | dateformat:\\'full\\'}}\">{{row.getProperty(col.field) | dateformat}}</div></div>',\n        userTemplate : '<div><div class=\"ngCellText\" title=\"{{row.getProperty(col.field)}}\" username=\"row.getProperty(col.field)\"></div></div>',\n        groupTemplate : '<div><div class=\"ngCellText\" title=\"{{row.getProperty(col.field)}}\" groupname=\"row.getProperty(col.field)\"></div></div>',\n        userObjectTemplate : '<div><div class=\"ngCellText\" title=\"{{row.getProperty(col.field)}}\" user=\"row.getProperty(col.field)\"></div></div>'\n    });\n\n\n    "
  },
  {
    "path": "flowable-ui-web/admin/scripts/content-item-controllers.js",
    "content": "/* 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'use strict';\n\n/* Controllers */\n\nflowableAdminApp.controller('ContentItemController', ['$rootScope', '$scope', '$http', '$timeout', '$location', '$translate', '$q', '$modal', '$routeParams',\n    function ($rootScope, $scope, $http, $timeout, $location, $translate, $q, $modal, $routeParams) {\n\n        $rootScope.navigation = {main: 'content-engine', sub: 'content-items'};\n\n        $scope.returnToList = function () {\n            $location.path(\"/content-items\");\n        };\n\n        $scope.showContentItem = function () {\n            $modal.open({\n                templateUrl: 'views/form-render-popup.html',\n                windowClass: 'modal modal-full-width',\n                controller: 'ShowFormRenderPopupCtrl',\n                resolve: {\n                    form: function () {\n                        return $scope.contentItem;\n                    }\n                }\n            });\n        };\n\n        $scope.executeWhenReady(function () {\n            if ($rootScope.contentItem) {\n                $scope.contentItem = $rootScope.contentItem;\n                $rootScope.contentItem = undefined;\n                return;\n            }\n\n            // Load submitted form\n            $http({method: 'GET', url: FlowableAdmin.webContextRoot + '/app/rest/admin/content-items/' + $routeParams.contentItemId}).\n            success(function (data, status, headers, config) {\n                $scope.contentItem = data;\n            }).\n            error(function (data, status, headers, config) {\n                if (data && data.message) {\n                    // Extract error-message\n                    $rootScope.addAlert(data.message, 'error');\n                } else {\n                    // Use default error-message\n                    $rootScope.addAlert($translate.instant('ALERT.GENERAL.HTTP-ERROR'), 'error');\n                }\n            });\n        });\n    }]);\n"
  },
  {
    "path": "flowable-ui-web/admin/scripts/content-items-controllers.js",
    "content": "/* 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'use strict';\n\n/* Controllers */\n\nflowableAdminApp.controller('ContentItemsController', ['$rootScope', '$scope', '$http', '$timeout', '$location', '$translate', '$q', '$modal', 'gridConstants',\n    function ($rootScope, $scope, $http, $timeout, $location, $translate, $q, $modal, gridConstants) {\n\n        $rootScope.navigation = {main: 'content-engine', sub: 'content-items'};\n\n        $scope.filter = {};\n        $scope.contentItemsData = {};\n\n        // Array to contain selected properties (yes - we only can select one, but ng-grid isn't smart enough)\n        $scope.selectedItem = [];\n\n        var filterConfig = {\n            url: FlowableAdmin.webContextRoot + '/app/rest/admin/content-items',\n            method: 'GET',\n            success: function (data, status, headers, config) {\n                $scope.contentItemsData = data;\n            },\n            error: function (data, status, headers, config) {\n                if (data && data.message) {\n                    // Extract error-message\n                    $rootScope.addAlert(data.message, 'error');\n                } else {\n                    // Use default error-message\n                    $rootScope.addAlert($translate.instant('ALERT.GENERAL.HTTP-ERROR'), 'error');\n                }\n            },\n\n            sortObjects: [\n                {name: 'CONTENT-ITEMS.SORT.CREATED', id: 'created'}\n            ],\n\n            supportedProperties: [\n                {id: 'nameLike', name: 'CONTENT-ITEMS.FILTER.NAME', showByDefault: true},\n                {id: 'tenantId', name: 'CONTENT-ITEMS.FILTER.TENANTID', showByDefault: true}\n            ]\n        };\n\n        if ($rootScope.filters && $rootScope.filters.contentItemFilter) {\n            // Reuse the existing filter\n            $scope.filter = $rootScope.filters.contentItemFilter;\n            $scope.filter.config = filterConfig;\n        } else {\n            $scope.filter = new FlowableAdmin.Utils.Filter(filterConfig, $http, $timeout, $rootScope);\n            $rootScope.filters.contentItemFilter = $scope.filter;\n        }\n\n        $scope.itemSelected = function (contentItem) {\n            if (contentItem && contentItem.getProperty('id')) {\n                $location.path('/content-item/' + contentItem.getProperty('id'));\n            }\n        };\n\n        $q.all([$translate('CONTENT-ITEMS.HEADER.ID'),\n                $translate('CONTENT-ITEMS.HEADER.NAME'),\n                $translate('CONTENT-ITEMS.HEADER.TASK-ID'),\n                $translate('CONTENT-ITEMS.HEADER.PROCESS-INSTANCE-ID'),\n                $translate('CONTENT-ITEMS.HEADER.LAST-MODIFIED-ON'),\n                $translate('CONTENT-ITEMS.HEADER.LAST-MODIFIED-BY'),\n                $translate('CONTENT-ITEMS.HEADER.TENANT-ID')])\n            .then(function (headers) {\n                // Config for grid\n                $scope.gridContentItems = {\n                    data: 'contentItemsData.data',\n                    enableRowReordering: true,\n                    multiSelect: false,\n                    keepLastSelected: false,\n                    rowHeight: 36,\n                    afterSelectionChange: $scope.itemSelected,\n                    columnDefs: [\n                        {field: 'id', displayName: headers[0], cellTemplate: gridConstants.defaultTemplate},\n                        {field: 'name', displayName: headers[1], cellTemplate: gridConstants.defaultTemplate},\n                        {field: 'taskId', displayName: headers[2], cellTemplate: gridConstants.defaultTemplate},\n                        {field: 'processInstanceId', displayName: headers[3], cellTemplate: gridConstants.defaultTemplate},\n                        {field: 'lastModified', displayName: headers[4], cellTemplate: gridConstants.dateTemplate},\n                        {field: 'lastModifiedBy', displayName: headers[5], cellTemplate: gridConstants.defaultTemplate},\n                        {field: 'tenantId', displayName: headers[6], cellTemplate: gridConstants.defaultTemplate}]\n                };\n            });\n\n        $scope.executeWhenReady(function () {\n            $scope.filter.refresh();\n        });\n\n    }]);\n"
  },
  {
    "path": "flowable-ui-web/admin/scripts/controllers.js",
    "content": "/* Copyright 2005-2015 Alfresco Software, Ltd.\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'use strict';\n\n/* Controllers */\n\nflowableAdminApp.controller('ConfirmPopupCtrl', ['$scope', '$modalInstance', 'model', \n    function ($scope, $modalInstance, model) {\n        $scope.model = model;\n        $scope.ok = function () {\n            $modalInstance.close(true);\n        };\n    }]);"
  },
  {
    "path": "flowable-ui-web/admin/scripts/decision-table-controllers.js",
    "content": "/* 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'use strict';\n\nflowableAdminApp.controller('DecisionTableController', ['$scope', '$rootScope', '$http', '$timeout', '$location', '$routeParams', '$modal', '$translate', '$q', 'gridConstants',\n    function ($scope, $rootScope, $http, $timeout, $location, $routeParams, $modal, $translate, $q, gridConstants) {\n        $rootScope.navigation = {main: 'dmn-engine', sub: 'decision-tables'};\n        \n        $scope.returnToList = function () {\n            $location.path(\"/decision-tables\");\n        };\n\n        $scope.showAllDecisionTables = function () {\n            // Populate the process-filter with parentId\n            $rootScope.filters.forced.processDefinitionFilter = {\n                deploymentId: $scope.deployment.id\n            };\n            $location.path(\"/process-definitions\");\n        };\n\n        $scope.showAllExecutions = function () {\n            $location.path(\"/decision-table-executions\");\n        };\n\n        $scope.showDecisionTable = function () {\n            $modal.open({\n                templateUrl: 'views/decision-table-popup.html',\n                windowClass: 'modal modal-full-width',\n                controller: 'ShowDecisionTablePopupCtrl',\n                resolve: {\n                    decisionTable: function () {\n                        return $scope.decisionTable;\n                    }\n                }\n            });\n        };\n\n        $scope.showDecisionExecution = function (decisionExecution) {\n            if (decisionExecution && decisionExecution.getProperty('id')) {\n                $location.path(\"/decision-table-execution/\"+decisionExecution.getProperty('id'));\n            }\n        };\n\n        $q.all([$translate('DECISION-TABLE-EXECUTION.HEADER.ID'),\n                $translate('DECISION-TABLE-EXECUTION.HEADER.PROCESS-INSTANCE-ID'),\n                $translate('DECISION-TABLE-EXECUTION.HEADER.START-TIME'),\n                $translate('DECISION-TABLE-EXECUTION.HEADER.END-TIME'),\n                $translate('DECISION-TABLE-EXECUTION.HEADER.FAILED')])\n            .then(function (headers) {\n\n                $scope.gridDecisionExecutions = {\n                    data: 'decisionExecutions.data',\n                    enableRowReordering: false,\n                    multiSelect: false,\n                    keepLastSelected: false,\n                    enableSorting: true,\n                    rowHeight: 36,\n                    afterSelectionChange: $scope.showDecisionExecution,\n                    columnDefs: [\n                        {field: 'id', displayName: headers[0]},\n                        {field: 'instanceId', displayName: headers[1]},\n                        {field: 'startTime', displayName: headers[2], cellTemplate: gridConstants.dateTemplate},\n                        {field: 'endTime', displayName: headers[3], cellTemplate: gridConstants.dateTemplate},\n                        {field: 'failed', displayName: headers[4]}\n                    ]\n                };\n            });\n\n        $scope.executeWhenReady(function () {\n            // Load deployment\n            $http({method: 'GET', url: FlowableAdmin.webContextRoot + '/app/rest/admin/decision-tables/' + $routeParams.decisionTableId}).\n            success(function (data, status, headers, config) {\n                $scope.decisionTable = data;\n\n                // Load decision executions\n                $http({\n                    method: 'GET',\n                    url: FlowableAdmin.webContextRoot + '/app/rest/admin/decision-tables/history?decisionKey=' + data.key + '&deploymentId=' + data.deploymentId\n                }).\n                success(function (executionsData, status, headers, config) {\n                    $scope.decisionExecutions = executionsData;\n                });\n            }).\n            error(function (data, status, headers, config) {\n                if (data && data.message) {\n                    // Extract error-message\n                    $rootScope.addAlert(data.message, 'error');\n                } else {\n                    // Use default error-message\n                    $rootScope.addAlert($translate.instant('ALERT.GENERAL.HTTP-ERROR'), 'error');\n                }\n            });\n        });\n\n    }]);\n\nflowableAdminApp.controller('ShowDecisionTablePopupCtrl',\n    ['$rootScope', '$scope', '$modalInstance', '$http', 'decisionTable', '$timeout', '$translate', 'uiGridConstants',\n        function ($rootScope, $scope, $modalInstance, $http, decisionTable, $timeout, $translate, uiGridConstants) {\n\n            var MIN_COLUMN_WIDTH = 200;\n\n            $scope.status = {loading: false};\n\n            $scope.cancel = function () {\n                if (!$scope.status.loading) {\n                    $modalInstance.dismiss('cancel');\n                }\n            };\n\n            $scope.popup = {\n                currentDecisionTableRules: [],\n                columnDefs: [],\n                columnVariableIdMap: {}\n            };\n\n            $scope.executeWhenReady(function () {\n                // Load deployment\n                $http({\n                    method: 'GET',\n                    url: FlowableAdmin.webContextRoot + '/app/rest/admin/decision-tables/' + decisionTable.id + '/editorJson'\n                }).\n                success(function (data, status, headers, config) {\n                    $scope.popup.currentDecisionTable = data;\n                }).\n                error(function (data, status, headers, config) {\n                    if (data && data.message) {\n                        // Extract error-message\n                        $rootScope.addAlert(data.message, 'error');\n                    } else {\n                        // Use default error-message\n                        $rootScope.addAlert($translate.instant('ALERT.GENERAL.HTTP-ERROR'), 'error');\n                    }\n                });\n            });\n\n            var variableUndefined = $translate.instant('DECISION-TABLE-EDITOR.EMPTY-MESSAGES.NO-VARIABLE-SELECTED');\n            // helper for looking up variable id by col id\n            $scope.getVariableNameByColumnId = function (colId) {\n\n                if (!colId) {\n                    return;\n                }\n\n                if ($scope.popup.columnVariableIdMap[colId]) {\n                    return $scope.popup.columnVariableIdMap[colId];\n                } else {\n                    return variableUndefined;\n                }\n            };\n\n            var _loadDecisionTableDefinition = function () {\n\n                if ($scope.popup.currentDecisionTable.inputExpressions) {\n                    $scope.popup.currentDecisionTable.inputExpressions.forEach(function (inputExpression) {\n                        $scope.popup.columnVariableIdMap[inputExpression.id] = inputExpression.variableId;\n                    });\n                }\n\n                if ($scope.popup.currentDecisionTable.outputExpressions) {\n                    $scope.popup.currentDecisionTable.outputExpressions.forEach(function (outputExpression) {\n                        $scope.popup.columnVariableIdMap[outputExpression.id] = outputExpression.variableId;\n                    });\n                }\n\n                // initialize ui grid model\n                if ($scope.popup.currentDecisionTable.rules && $scope.popup.currentDecisionTable.rules.length > 0) {\n                    Array.prototype.push.apply($scope.popup.currentDecisionTableRules, $scope.popup.currentDecisionTable.rules);\n                }\n\n                // get column definitions\n                $scope.getColumnDefinitions($scope.popup.currentDecisionTable);\n\n            };\n\n            // Custom UI grid template\n            var _getHeaderInputExpressionCellTemplate = function () {\n                return \"\" +\n                    \"<div role=\\\"columnheader\\\" ui-grid-one-bind-aria-labelledby-grid=\\\"col.uid + '-header-text ' + col.uid + '-sortdir-text'\\\">\" +\n                    \"   <div class=\\\"ui-grid-cell-contents ui-grid-header-cell-primary-focus\\\" col-index=\\\"renderIndex\\\" title=\\\"TOOLTIP\\\">\" +\n                    \"       <div class=\\\"text-center\\\"><span>{{ col.displayName CUSTOM_FILTERS }}</span></div>\" +\n                    \"       <div class=\\\"text-center\\\"><span ui-grid-one-bind-id-grid=\\\"col.uid + '-header-text'\\\" style=\\\"text-decoration: underline;\\\">[ {{ grid.appScope.getVariableNameByColumnId(col.name) }} ]</span></div>\" +\n                    \"   </div>\" +\n                    \"</div>\";\n            };\n\n            var _getHeaderOutputExpressionCellTemplate = function () {\n                return \"\" +\n                    \"<div role=\\\"columnheader\\\" ui-grid-one-bind-aria-labelledby-grid=\\\"col.uid + '-header-text ' + col.uid + '-sortdir-text'\\\">\" +\n                    \"   <div class=\\\"ui-grid-cell-contents ui-grid-header-cell-primary-focus\\\" col-index=\\\"renderIndex\\\" title=\\\"TOOLTIP\\\">\" +\n                    \"       <div class=\\\"text-center\\\"><span>{{ col.displayName CUSTOM_FILTERS }}</span></div>\" +\n                    \"       <div class=\\\"text-center\\\"><span ui-grid-one-bind-id-grid=\\\"col.uid + '-header-text'\\\" style=\\\"text-decoration: underline;\\\">[ {{ grid.appScope.getVariableNameByColumnId(col.name) }} ]</span></div>\" +\n                    \"   </div>\" +\n                    \"</div>\";\n            };\n\n            var _rowHeaderTemplate = function () {\n                return \"<div class=\\\"ui-grid-disable-selection\\\"><div class=\\\"ui-grid-cell-contents text-center customRowHeader\\\">{{rowRenderIndex + 1}}</div></div>\"\n            };\n\n            var _getCellTemplate = function (columnType) {\n                var cellTemplate = \"\" +\n                    \"<div class=\\\"ui-grid-cell-contents\\\" ng-class=\\\"{ 'ui-grid-cell-contents-empty': !COL_FIELD }\\\" title=\\\"TOOLTIP\\\">\" +\n                    \"   <span class=\\\"contents-value\\\">{{COL_FIELD}}</span>\" +\n                    \"</div>\";\n                return cellTemplate;\n            };\n\n            // create UI grid column definitions based on input / output expression\n            $scope.getColumnDefinitions = function (decisionTable) {\n\n                if (!decisionTable) {\n                    return;\n                }\n\n                var expressionCounter = 0;\n                var newColumnDefs = [];\n\n                // input expression column defs\n                if (decisionTable.inputExpressions && decisionTable.inputExpressions.length > 0) {\n\n                    decisionTable.inputExpressions.forEach(function (inputExpression) {\n\n                        newColumnDefs.push({\n                            name: inputExpression.id,\n                            displayName: inputExpression.label ? inputExpression.label : \"\",\n                            field: inputExpression.id,\n                            type: 'string',\n                            headerCellClass: 'header-expression header-input-expression',\n                            headerCellTemplate: _getHeaderInputExpressionCellTemplate(),\n                            cellClass: 'cell-expression cell-input-expression',\n                            cellTemplate: _getCellTemplate(),\n                            enableHiding: false,\n                            enableCellEditOnFocus: false,\n                            minWidth: MIN_COLUMN_WIDTH\n                        });\n\n                        expressionCounter++;\n                    });\n                }\n\n                // output expression column defs\n                if (decisionTable.outputExpressions && decisionTable.outputExpressions.length > 0) {\n\n                    decisionTable.outputExpressions.forEach(function (outputExpression) {\n\n                        newColumnDefs.push({\n                            name: outputExpression.id,\n                            displayName: outputExpression.label ? outputExpression.label : \"\",\n                            field: outputExpression.id,\n                            type: 'string',\n                            headerCellTemplate: _getHeaderOutputExpressionCellTemplate(),\n                            headerCellClass: 'header-expression header-output-expression',\n                            cellClass: 'cell-expression cell-output-expression',\n                            cellTemplate: _getCellTemplate(),\n                            enableHiding: false,\n                            enableCellEditOnFocus: false,\n                            minWidth: MIN_COLUMN_WIDTH\n                        });\n\n                        expressionCounter++;\n                    });\n                }\n\n                // merge models\n                if ($scope.popup.columnDefs) {\n                    $scope.popup.columnDefs.length = 0;\n                }\n\n                else {\n                    $scope.popup.columnDefs = [];\n                }\n                Array.prototype.push.apply($scope.popup.columnDefs, newColumnDefs);\n\n                $scope.popup.gridApi.core.notifyDataChange(uiGridConstants.dataChange.ALL);\n            };\n\n            // config for grid\n            $scope.popup.gridOptions = {\n                data: $scope.popup.currentDecisionTableRules,\n                enableRowHeaderSelection: false,\n                multiSelect: false,\n                modifierKeysToMultiSelect: false,\n                enableHorizontalScrollbar: 2,\n                enableColumnMenus: false,\n                enableSorting: false,\n                enableCellEditOnFocus: false,\n                columnDefs: $scope.popup.columnDefs\n                //headerTemplate: 'views/templates/decision-table-header-template.html'\n            };\n\n            $scope.popup.gridOptions.onRegisterApi = function (gridApi) {\n                //set gridApi on scope\n                $scope.popup.gridApi = gridApi;\n\n                var cellTemplate = _rowHeaderTemplate();   // you could use your own template here\n                $scope.popup.gridApi.core.addRowHeaderColumn({name: 'rowHeaderCol', displayName: '', width: 35, cellTemplate: cellTemplate});\n\n                // Load definition that will be rendered\n                _loadDecisionTableDefinition();\n            };\n            \n\n        }]);\n\n"
  },
  {
    "path": "flowable-ui-web/admin/scripts/decision-table-deployment-controllers.js",
    "content": "/* 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'use strict';\n\nflowableAdminApp.controller('DecisionTableDeploymentController', ['$scope', '$rootScope', '$http', '$timeout','$location','$routeParams', '$modal', '$translate', '$q',\n    function ($scope, $rootScope, $http, $timeout, $location, $routeParams, $modal, $translate, $q) {\n\n        $rootScope.navigation = {main: 'dmn-engine', sub: 'deployments'};\n        \n\t\t$scope.returnToList = function() {\n\t\t\t$location.path(\"/decision-table-deployments\");\n\t\t};\n\t\t\n\t\t$scope.openDecisionTable = function(definition) {\n\t\t\tif (definition && definition.getProperty('id')) {\n\t\t\t\t$location.path(\"/decision-table/\" + definition.getProperty('id'));\n\t\t\t}\n\t\t};\n\t\t\n\t\t$scope.showAllDecisionTables = function() {\n\t\t    // Populate the process-filter with parentId\n\t\t    $rootScope.filters.forced.decisionTablesFilter = {\n\t\t            deploymentId: $scope.deployment.id\n\t\t    };\n\t\t    $location.path(\"/decision-tables\");\n\t\t};\n\t\t\n\t\t$q.all([$translate('DECISION-TABLES.HEADER.ID'),\n            $translate('DECISION-TABLES.HEADER.NAME'),\n            $translate('DECISION-TABLES.HEADER.VERSION'),\n            $translate('DECISION-TABLES.HEADER.KEY')])\n            .then(function(headers) { \n        \n                $scope.gridDecisionTables = {\n                    data: 'decisionTables.data',\n                    enableRowReordering: false,\n                    multiSelect: false,\n                    keepLastSelected : false,\n                    enableSorting: false,\n                    rowHeight: 36,\n                    afterSelectionChange: $scope.openDecisionTable,\n                    columnDefs: [\n                          { field: 'id', displayName: headers[0]},\n                          { field: 'name', displayName: headers[1]},\n                          { field: 'version', displayName: headers[2]},\n                          { field: 'key', displayName: headers[3]}\n                    ]\n                };\n        });\n\t\t\n\t\t$scope.deleteDeployment = function() {\n\t\t    var modalInstance = $modal.open({\n                templateUrl: 'views/confirm-popup.html',\n                controller: 'ConfirmPopupCtrl',\n                resolve: {\n                    model: function () {\n                      return {\n                          confirm: $translate.instant('DECISION-TABLE-DEPLOYMENTS.ACTION.DELETE'),\n                          title: $translate.instant('DECISION-TABLE-DEPLOYMENTS.ACTION.DELETE'),\n                          message: $translate.instant('DECISION-TABLE-DEPLOYMENTS.POPUP.DELETE.CONFIRM-MESSAGE', $scope.deployment)\n                          };\n                    }\n                }\n                \n            });\n            \n            modalInstance.result.then(function (result) {\n                if (result === true) {\n                    $http({method: 'DELETE', url: FlowableAdmin.webContextRoot + '/app/rest/admin/decision-table-deployments/' + $routeParams.deploymentId}).\n                    success(function(data, status, headers, config) {\n                        $scope.addAlert($translate.instant('ALERT.DECISION-TABLE-DEPLOYMENT.DELETED-DEPLOYMENT', $scope.deployment), 'info');\n                        $scope.returnToList();\n                    }).\n                    error(function(data, status, headers, config) {\n                        $scope.addAlert($translate.instant('ALERT.DECISION-TABLE-DEPLOYMENT.DELETE-ERROR', data), 'error');\n                    });\n                }\n            });\n            \n        };\n        \n\t\t$scope.executeWhenReady(function() {\n\t\t    // Load deployment\n\t\t    $http({method: 'GET', url: FlowableAdmin.webContextRoot + '/app/rest/admin/decision-table-deployments/' + $routeParams.deploymentId}).\n  \t    \t    success(function(data, status, headers, config) {\n  \t    \t        $scope.deployment = data;\n  \t    \t    }).\n  \t    \t    error(function(data, status, headers, config) {\n                    if (data && data.message) {\n                        // Extract error-message\n                        $rootScope.addAlert(data.message, 'error');\n                    } else {\n                        // Use default error-message\n                        $rootScope.addAlert($translate.instant('ALERT.GENERAL.HTTP-ERROR'), 'error');\n                    }\n  \t    \t    });\n  \t\t\n\t\t    // Load process definitions\n\t\t    $http({method: 'GET', url: FlowableAdmin.webContextRoot + '/app/rest/admin/decision-tables?deploymentId=' + $routeParams.deploymentId}).\n  \t    \t    success(function(data, status, headers, config) {\n  \t    \t        $scope.decisionTables = data;\n  \t    \t    });\n\t\t    \n  \t     });\n}]);"
  },
  {
    "path": "flowable-ui-web/admin/scripts/decision-table-deployments-controllers.js",
    "content": "/* 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'use strict';\n\n/* Controllers */\n\nflowableAdminApp.controller('DecisionTableDeploymentsController', ['$rootScope', '$scope', '$http', '$timeout', '$location', '$translate', '$q', '$modal', 'gridConstants',\n    function ($rootScope, $scope, $http, $timeout, $location, $translate, $q, $modal, gridConstants) {\n\n        $rootScope.navigation = {main: 'dmn-engine', sub: 'deployments'};\n\n        $scope.filter = {};\n        $scope.deploymentsData = {};\n\n        // Array to contain selected properties (yes - we only can select one, but ng-grid isn't smart enough)\n        $scope.selectedDefinitions = [];\n\n        var filterConfig = {\n            url: FlowableAdmin.webContextRoot + '/app/rest/admin/decision-table-deployments',\n            method: 'GET',\n            success: function (data, status, headers, config) {\n                $scope.deploymentsData = data;\n            },\n            error: function (data, status, headers, config) {\n                if (data && data.message) {\n                    // Extract error-message\n                    $rootScope.addAlert(data.message, 'error');\n                } else {\n                    // Use default error-message\n                    $rootScope.addAlert($translate.instant('ALERT.GENERAL.HTTP-ERROR'), 'error');\n                }\n            },\n\n            sortObjects: [\n                {name: 'DECISION-TABLE-DEPLOYMENTS.SORT.ID', id: 'id'},\n                {name: 'DECISION-TABLE-DEPLOYMENTS.SORT.NAME', id: 'name'}\n            ],\n\n            supportedProperties: [\n                {id: 'nameLike', name: 'DECISION-TABLE-DEPLOYMENTS.FILTER.NAME', showByDefault: true},\n                {id: 'tenantIdLike', name: 'DECISION-TABLE-DEPLOYMENTS.FILTER.TENANTID', showByDefault: true}\n            ]\n        };\n\n        if ($rootScope.filters && $rootScope.filters.decisionTableDeploymentFilter) {\n            // Reuse the existing filter\n            $scope.filter = $rootScope.filters.decisionTableDeploymentFilter;\n            $scope.filter.config = filterConfig;\n        } else {\n            $scope.filter = new FlowableAdmin.Utils.Filter(filterConfig, $http, $timeout, $rootScope);\n            $rootScope.filters.decisionTableDeploymentFilter = $scope.filter;\n        }\n\n        $scope.deploymentSelected = function (deployment) {\n            if (deployment && deployment.getProperty('id')) {\n                $location.path('/decision-table-deployment/' + deployment.getProperty('id'));\n            }\n        };\n\n        $q.all([$translate('DECISION-TABLE-DEPLOYMENTS.HEADER.ID'),\n            $translate('DECISION-TABLE-DEPLOYMENTS.HEADER.NAME'),\n            $translate('DECISION-TABLE-DEPLOYMENTS.HEADER.DEPLOY-TIME'),\n            $translate('DECISION-TABLE-DEPLOYMENTS.HEADER.CATEGORY'),\n            $translate('DECISION-TABLE-DEPLOYMENTS.HEADER.TENANT')])\n            .then(function (headers) {\n\n                // Config for grid\n                $scope.gridDeployments = {\n                    data: 'deploymentsData.data',\n                    enableRowReordering: true,\n                    multiSelect: false,\n                    keepLastSelected: false,\n                    rowHeight: 36,\n                    afterSelectionChange: $scope.deploymentSelected,\n                    columnDefs: [\n                        {field: 'id', displayName: headers[0], cellTemplate: gridConstants.defaultTemplate},\n                        {field: 'name', displayName: headers[1], cellTemplate: gridConstants.defaultTemplate},\n                        {field: 'deploymentTime', displayName: headers[2], cellTemplate: gridConstants.dateTemplate},\n                        {field: 'category', displayName: headers[3], cellTemplate: gridConstants.defaultTemplate},\n                        {field: 'tenantId', displayName: headers[4], cellTemplate: gridConstants.defaultTemplate}]\n                };\n            });\n\n        $scope.executeWhenReady(function () {\n            $scope.filter.refresh();\n        });\n\n        /*\n        * ACTIONS\n        */\n\n        $scope.uploadDeployment = function () {\n            var modalInstance = $modal.open({\n                templateUrl: 'views/upload-dmn-deployment.html',\n                controller: 'UploadDecisionDeploymentCtrl'\n            });\n            modalInstance.result.then(function (result) {\n                // Refresh page if closed successfully\n                if (result) {\n                    $scope.deploymentsData = {};\n                    $scope.filter.refresh();\n                }\n            });\n        };\n\n    }]);\n\n\n/**\\\n * Controller for the upload a model from the process Modeler.\n */\nflowableAdminApp.controller('UploadDecisionDeploymentCtrl',\n    ['$scope', '$modalInstance', '$http', 'Upload', '$timeout', '$translate', function ($scope, $modalInstance, $http, Upload, $timeout, $translate) {\n\n        $scope.status = {loading: false};\n\n        $scope.model = {};\n\n        $scope.onFileSelect = function ($files) {\n\n            for (var i = 0; i < $files.length; i++) {\n                var file = $files[i];\n                file.upload = Upload.upload({\n                    url: FlowableAdmin.webContextRoot + '/app/rest/admin/decision-table-deployments',\n                    method: 'POST',\n                    data: {file: file}\n                });\n\n                file.upload.then(function (response) {\n                    $timeout(function () {\n                        $scope.addAlert($translate.instant('ALERT.DEPLOYMENT.DEPLOYMENT-SUCCESS'), 'info');\n                        $scope.status.loading = false;\n                        $modalInstance.close(true);\n                    });\n                }, function (response) {\n                    if (response.data && response.data.message) {\n                        $scope.model.errorMessage = response.data.message;\n                    }\n                    $scope.model.error = true;\n                    $scope.status.loading = false;\n                }, function (evt) {\n                    file.progress = Math.min(100, parseInt(100.0 *\n                        evt.loaded / evt.total));\n                });\n            }\n        };\n\n        $scope.cancel = function () {\n            if (!$scope.status.loading) {\n                $modalInstance.dismiss('cancel');\n            }\n        };\n\n    }]);\n"
  },
  {
    "path": "flowable-ui-web/admin/scripts/decision-table-execution-controllers.js",
    "content": "/* 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'use strict';\n\nflowableAdminApp.controller('DecisionTableExecutionController', ['$scope', '$rootScope', '$http', '$timeout', '$location', '$routeParams', '$modal', '$translate', '$q',\n    function ($scope, $rootScope, $http, $timeout, $location, $routeParams, $modal, $translate, $q) {\n\n        $rootScope.navigation = {main: 'dmn-engine', sub: 'executions'};\n\n        $scope.returnToList = function () {\n            $location.path(\"/decision-table-executions\");\n        };\n\n        $scope.openDecisionTable = function (definition) {\n            if (definition && definition.getProperty('id')) {\n                $location.path(\"/decision-table/\" + definition.getProperty('id'));\n            }\n        };\n\n        $q.all([$translate('DECISION-TABLE-EXECUTION.HEADER.ID'),\n            $translate('DECISION-TABLE-EXECUTION.HEADER.NAME'),\n            $translate('DECISION-TABLE-EXECUTION.HEADER.VERSION'),\n            $translate('DECISION-TABLE-EXECUTION.HEADER.KEY')])\n            .then(function (headers) {\n\n                $scope.gridDecisionTables = {\n                    data: 'decisionTables.data',\n                    enableRowReordering: false,\n                    multiSelect: false,\n                    keepLastSelected: false,\n                    enableSorting: false,\n                    rowHeight: 36,\n                    afterSelectionChange: $scope.openDecisionTable,\n                    columnDefs: [\n                        {field: 'id', displayName: headers[0]},\n                        {field: 'name', displayName: headers[1]},\n                        {field: 'version', displayName: headers[2]},\n                        {field: 'key', displayName: headers[3]}\n                    ]\n                };\n            });\n\n        var formatInputVariablesInRows = function (inputVariables, inputVariableTypes) {\n            if (inputVariables === null || inputVariableTypes === null) {\n                return;\n            }\n\n            var result = [];\n            var columnCounter = 1;\n            var noColumns = 2;\n            var tmpRow = [];\n\n            for (var key in inputVariables) {\n                if (inputVariables.hasOwnProperty(key)) {\n\n                    tmpRow.push({\n                        key: key,\n                        value: inputVariables[key],\n                        type: inputVariableTypes[key]\n                    });\n\n                    if (columnCounter === noColumns) {\n                        result.push(tmpRow);\n                    }\n\n                    columnCounter++;\n                    if (columnCounter > noColumns) {\n                        tmpRow = [];\n                        columnCounter = 0;\n                    }\n                }\n            }\n            return result;\n        };\n\n        $scope.executeWhenReady(function () {\n            // Load historic execution\n            $http({\n                method: 'GET',\n                url: FlowableAdmin.webContextRoot + '/app/rest/admin/decision-tables/history/' + $routeParams.executionId\n            }).success(function (data, status, headers, config) {\n                $scope.execution = data;\n            }).error(function (data, status, headers, config) {\n                if (data && data.message) {\n                    // Extract error-message\n                    $rootScope.addAlert(data.message, 'error');\n                } else {\n                    // Use default error-message\n                    $rootScope.addAlert($translate.instant('ALERT.GENERAL.HTTP-ERROR'), 'error');\n                }\n            });\n\n            // Load historic execution audit data\n            $http({\n                method: 'GET',\n                url: FlowableAdmin.webContextRoot + '/app/rest/admin/decision-tables/history/' + $routeParams.executionId + '/auditdata'\n            }).success(function (data, status, headers, config) {\n                $scope.auditData = data;\n                $scope.formattedInputVariables = formatInputVariablesInRows(\n                    data.inputVariables,\n                    data.inputVariableTypes);\n            });\n        });\n    }]);"
  },
  {
    "path": "flowable-ui-web/admin/scripts/decision-table-executions-controllers.js",
    "content": "/* Copyright 2005-2015 Alfresco Software, Ltd.\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'use strict';\n\n/* Controllers */\n\nflowableAdminApp.controller('DecisionTableExecutionsController', ['$rootScope', '$scope', '$http', '$timeout', '$location', '$translate', '$q', '$modal', 'gridConstants',\n    function ($rootScope, $scope, $http, $timeout, $location, $translate, $q, $modal, gridConstants) {\n\n        $rootScope.navigation = {main: 'dmn-engine', sub: 'executions'};\n        \n        $scope.filter = {};\n        $scope.decisionTableExecutionsData = {};\n\n        // Array to contain selected properties (yes - we only can select one, but ng-grid isn't smart enough)\n        $scope.selectedDecisionTables = [];\n\n        var filterConfig = {\n            url: FlowableAdmin.webContextRoot + '/app/rest/admin/decision-tables/history',\n            method: 'GET',\n            success: function (data, status, headers, config) {\n                $scope.decisionTableExecutionsData = data;\n            },\n            error: function (data, status, headers, config) {\n                if (data && data.message) {\n                    // Extract error-message\n                    $rootScope.addAlert(data.message, 'error');\n                } else {\n                    // Use default error-message\n                    $rootScope.addAlert($translate.instant('ALERT.GENERAL.HTTP-ERROR'), 'error');\n                }\n            },\n\n            sortObjects: [\n                {name: 'DECISION-TABLE-EXECUTIONS.SORT.START-TIME', id: 'startTime'},\n                {name: 'DECISION-TABLE-EXECUTIONS.SORT.END-TIME', id: 'endTime'},\n                {name: 'DECISION-TABLE-EXECUTIONS.SORT.TENANT-ID', id: 'tenantId'}\n            ],\n\n            supportedProperties: [\n                {id: 'tenantIdLike', name: 'DECISION-TABLE-EXECUTIONS.FILTER.TENANTID', showByDefault: true}\n            ]\n        };\n\n        if ($rootScope.filters && $rootScope.filters.decisionTableExecutionsFilter) {\n            // Reuse the existing filter\n            $scope.filter = $rootScope.filters.decisionTableExecutionsFilter;\n            $scope.filter.config = filterConfig;\n        } else {\n            $scope.filter = new FlowableAdmin.Utils.Filter(filterConfig, $http, $timeout, $rootScope);\n            $rootScope.filters.decisionTableExecutionsFilter = $scope.filter;\n        }\n\n        $scope.decisionTableExecutionSelected = function (decisionTableExecution) {\n            if (decisionTableExecution && decisionTableExecution.getProperty('id')) {\n                $location.path('/decision-table-execution/' + decisionTableExecution.getProperty('id'));\n            }\n        };\n\n        $q.all([$translate('DECISION-TABLE-EXECUTIONS.HEADER.ID'),\n                $translate('DECISION-TABLE-EXECUTIONS.HEADER.DECISION-DEFINITION-KEY'),\n                $translate('DECISION-TABLE-EXECUTIONS.HEADER.DECISION-DEFINITION-NAME'),\n                $translate('DECISION-TABLE-EXECUTIONS.HEADER.END-TIME'),\n                $translate('DECISION-TABLE-EXECUTIONS.HEADER.FAILED'),\n                $translate('DECISION-TABLE-EXECUTIONS.HEADER.TENANT-ID')])\n            .then(function (headers) {\n                // Config for grid\n                $scope.gridDecisionTableExecutions = {\n                    data: 'decisionTableExecutionsData.data',\n                    enableRowReordering: true,\n                    multiSelect: false,\n                    keepLastSelected: false,\n                    rowHeight: 36,\n                    afterSelectionChange: $scope.decisionTableExecutionSelected,\n                    columnDefs: [\n                        {field: 'id', displayName: headers[0], cellTemplate: gridConstants.defaultTemplate},\n                        {field: 'decisionKey', displayName: headers[1], cellTemplate: gridConstants.defaultTemplate},\n                        {field: 'decisionName', displayName: headers[2], cellTemplate: gridConstants.defaultTemplate},\n                        {field: 'endTime', displayName: headers[3], cellTemplate: gridConstants.dateTemplate},\n                        {field: 'failed', displayName: headers[4], cellTemplate: gridConstants.defaultTemplate},\n                        {field: 'tenantId', displayName: headers[5], cellTemplate: gridConstants.defaultTemplate}]\n                };\n            });\n\n        $scope.executeWhenReady(function () {\n            $scope.filter.refresh();\n        });\n\n    }]);\n"
  },
  {
    "path": "flowable-ui-web/admin/scripts/decision-tables-controllers.js",
    "content": "/* Copyright 2005-2015 Alfresco Software, Ltd.\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'use strict';\n\n/* Controllers */\n\nflowableAdminApp.controller('DecisionTablesController', ['$rootScope', '$scope', '$http', '$timeout', '$location', '$translate', '$q', '$modal', 'gridConstants',\n    function ($rootScope, $scope, $http, $timeout, $location, $translate, $q, $modal, gridConstants) {\n\n        $rootScope.navigation = {main: 'dmn-engine', sub: 'decision-tables'};\n        \n        $scope.filter = {};\n        $scope.decisionTablesData = {};\n\n        // Array to contain selected properties (yes - we only can select one, but ng-grid isn't smart enough)\n        $scope.selectedDecisionTables = [];\n\n        var filterConfig = {\n            url: FlowableAdmin.webContextRoot + '/app/rest/admin/decision-tables',\n            method: 'GET',\n            success: function (data, status, headers, config) {\n                $scope.decisionTablesData = data;\n            },\n            error: function (data, status, headers, config) {\n                if (data && data.message) {\n                    // Extract error-message\n                    $rootScope.addAlert(data.message, 'error');\n                } else {\n                    // Use default error-message\n                    $rootScope.addAlert($translate.instant('ALERT.GENERAL.HTTP-ERROR'), 'error');\n                }\n            },\n\n            sortObjects: [\n                {name: 'DECISION-TABLES.SORT.ID', id: 'id'},\n                {name: 'DECISION-TABLES.SORT.NAME', id: 'name'}\n            ],\n\n            supportedProperties: [\n                {id: 'nameLike', name: 'DECISION-TABLES.FILTER.NAME', showByDefault: true},\n                {id: 'keyLike', name: 'DECISION-TABLES.FILTER.KEY', showByDefault: true},\n                {id: 'tenantIdLike', name: 'DECISION-TABLES.FILTER.TENANTID', showByDefault: true}\n            ]\n        };\n\n        if ($rootScope.filters && $rootScope.filters.decisionTableFilter) {\n            // Reuse the existing filter\n            $scope.filter = $rootScope.filters.decisionTableFilter;\n            $scope.filter.config = filterConfig;\n        } else {\n            $scope.filter = new FlowableAdmin.Utils.Filter(filterConfig, $http, $timeout, $rootScope);\n            $rootScope.filters.decisionTableFilter = $scope.filter;\n        }\n\n        $scope.decisionTableSelected = function (decisionTable) {\n            if (decisionTable && decisionTable.getProperty('id')) {\n                $location.path('/decision-table/' + decisionTable.getProperty('id'));\n            }\n        };\n\n        $q.all([$translate('DECISION-TABLES.HEADER.ID'),\n                $translate('DECISION-TABLES.HEADER.NAME'),\n                $translate('DECISION-TABLES.HEADER.KEY'),\n                $translate('DECISION-TABLES.HEADER.VERSION'),\n                $translate('DECISION-TABLES.HEADER.TENANT-ID')])\n            .then(function (headers) {\n                // Config for grid\n                $scope.gridDecisionTables = {\n                    data: 'decisionTablesData.data',\n                    enableRowReordering: true,\n                    multiSelect: false,\n                    keepLastSelected: false,\n                    rowHeight: 36,\n                    afterSelectionChange: $scope.decisionTableSelected,\n                    columnDefs: [\n                        {field: 'id', displayName: headers[0], cellTemplate: gridConstants.defaultTemplate},\n                        {field: 'name', displayName: headers[1], cellTemplate: gridConstants.defaultTemplate},\n                        {field: 'key', displayName: headers[2], cellTemplate: gridConstants.defaultTemplate},\n                        {field: 'version', displayName: headers[3], cellTemplate: gridConstants.defaultTemplate},\n                        {field: 'tenantId', displayName: headers[4], cellTemplate: gridConstants.defaultTemplate}]\n                };\n            });\n\n        $scope.executeWhenReady(function () {\n            $scope.filter.refresh();\n        });\n\n    }]);\n"
  },
  {
    "path": "flowable-ui-web/admin/scripts/deployment-controllers.js",
    "content": "/* Copyright 2005-2015 Alfresco Software, Ltd.\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'use strict';\n\nflowableAdminApp.controller('DeploymentController', ['$scope', '$rootScope', '$http', '$timeout','$location','$routeParams', '$modal', '$translate', '$q',\n    function ($scope, $rootScope, $http, $timeout, $location, $routeParams, $modal, $translate, $q) {\n\n        $rootScope.navigation = {main: 'process-engine', sub: 'deployments'};\n        \n\t\t$scope.returnToList = function() {\n\t\t\t$location.path(\"/deployments\");\n\t\t};\n\t\t\n\t\t$scope.openDefinition = function(definition) {\n\t\t\tif (definition && definition.getProperty('id')) {\n\t\t\t\t$location.path(\"/process-definition/\" + definition.getProperty('id'));\n\t\t\t}\n\t\t};\n\t\t\n\t\t$scope.showAllDefinitions = function() {\n\t\t    // Populate the process-filter with parentId\n\t\t    $rootScope.filters.forced.processDefinitionFilter = {\n\t\t            deploymentId: $scope.deployment.id\n\t\t    };\n\t\t    $location.path(\"/process-definitions\");\n\t\t};\n\t\t\n\t\t$q.all([$translate('PROCESS-DEFINITIONS.HEADER.ID'), \n            $translate('PROCESS-DEFINITIONS.HEADER.NAME'),\n            $translate('PROCESS-DEFINITIONS.HEADER.VERSION'),\n            $translate('PROCESS-DEFINITIONS.HEADER.KEY')])\n            .then(function(headers) { \n        \n                $scope.gridDefinitions = {\n                    data: 'definitions.data',\n                    enableRowReordering: false,\n                    multiSelect: false,\n                    keepLastSelected : false,\n                    enableSorting: false,\n                    rowHeight: 36,\n                    afterSelectionChange: $scope.openDefinition,\n                    columnDefs: [\n                          { field: 'id', displayName: headers[0]},\n                          { field: 'name', displayName: headers[1]},\n                          { field: 'version', displayName: headers[2]},\n                          { field: 'key', displayName: headers[3]}\n                    ]\n                };\n        });\n\t\t\n\t\t$scope.deleteDeployment = function() {\n\t\t    var modalInstance = $modal.open({\n                templateUrl: 'views/confirm-popup.html',\n                controller: 'ConfirmPopupCtrl',\n                resolve: {\n                    model: function () {\n                      return {\n                          confirm: $translate.instant('DEPLOYMENTS.ACTION.DELETE'), \n                          title: $translate.instant('DEPLOYMENTS.ACTION.DELETE'), \n                          message: $translate.instant('DEPLOYMENTS.POPUP.DELETE.CONFIRM-MESSAGE', $scope.deployment)\n                          };\n                    }\n                }\n                \n            });\n            \n            modalInstance.result.then(function (result) {\n                if (result === true) {\n                    $http({method: 'DELETE', url: FlowableAdmin.webContextRoot + '/app/rest/admin/deployments/' + $routeParams.deploymentId}).\n                    success(function(data, status, headers, config) {\n                        $scope.addAlert($translate.instant('ALERT.DEPLOYMENT.DELETED-DEPLOYMENT', $scope.deployment), 'info');\n                        $scope.returnToList();\n                    }).\n                    error(function(data, status, headers, config) {\n                        $scope.addAlert($translate.instant('ALERT.DEPLOYMENT.DELETE-ERROR', data), 'error');\n                    });\n                }\n            });\n            \n        };\n        \n\t\t$scope.executeWhenReady(function() {\n\t\t    // Load deployment\n\t\t    $http({method: 'GET', url: FlowableAdmin.webContextRoot + '/app/rest/admin/deployments/' + $routeParams.deploymentId}).\n  \t    \t    success(function(data, status, headers, config) {\n  \t    \t        $scope.deployment = data;\n  \t    \t    }).\n  \t    \t    error(function(data, status, headers, config) {\n                    if (data && data.message) {\n                        // Extract error-message\n                        $rootScope.addAlert(data.message, 'error');\n                    } else {\n                        // Use default error-message\n                        $rootScope.addAlert($translate.instant('ALERT.GENERAL.HTTP-ERROR'), 'error');\n                    }\n  \t    \t    });\n  \t\t\n\t\t    // Load process definitions\n\t\t    $http({method: 'GET', url: FlowableAdmin.webContextRoot + '/app/rest/admin/process-definitions?deploymentId=' + $routeParams.deploymentId}).\n  \t    \t    success(function(data, status, headers, config) {\n  \t    \t        $scope.definitions = data;\n  \t    \t    });\n\t\t    \n  \t     });\n}]);"
  },
  {
    "path": "flowable-ui-web/admin/scripts/deployments-controllers.js",
    "content": "/* Copyright 2005-2015 Alfresco Software, Ltd.\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'use strict';\n\n/* Controllers */\n\nflowableAdminApp.controller('DeploymentsController', ['$rootScope', '$scope', '$http', '$timeout', '$location', '$translate', '$q', '$modal', 'gridConstants',\n    function ($rootScope, $scope, $http, $timeout, $location, $translate, $q, $modal, gridConstants) {\n\n\t\t$rootScope.navigation = {main: 'process-engine', sub: 'deployments'};\n        \n\t\t$scope.filter = {};\n\t\t$scope.deploymentsData = {};\n\n\t\t// Array to contain selected properties (yes - we only can select one, but ng-grid isn't smart enough)\n\t    $scope.selectedDefinitions = [];\n\n\t    var filterConfig = {\n\t    \turl: FlowableAdmin.webContextRoot + '/app/rest/admin/deployments',\n\t    \tmethod: 'GET',\n\t    \tsuccess: function(data, status, headers, config) {\n\t    \t\t$scope.deploymentsData = data;\n            },\n            error: function(data, status, headers, config) {\n                if (data && data.message) {\n                    // Extract error-message\n                    $rootScope.addAlert(data.message, 'error');\n                } else {\n                    // Use default error-message\n                    $rootScope.addAlert($translate.instant('ALERT.GENERAL.HTTP-ERROR'), 'error');\n                }\n            },\n\n            sortObjects: [\n                {name: 'DEPLOYMENTS.SORT.ID', id: 'id'},\n                {name: 'DEPLOYMENTS.SORT.NAME', id: 'name'}\n            ],\n\n            supportedProperties: [\n                {id: 'nameLike', name: 'DEPLOYMENTS.FILTER.NAME', showByDefault: true},\n                {id: 'tenantIdLike', name: 'DEPLOYMENTS.FILTER.TENANTID', showByDefault: true}\n            ]\n\t    };\n\n\t    if($rootScope.filters && $rootScope.filters.deploymentFilter) {\n\t    \t// Reuse the existing filter\n\t    \t$scope.filter = $rootScope.filters.deploymentFilter;\n\t    \t$scope.filter.config = filterConfig;\n\t    } else {\n\t\t    $scope.filter = new FlowableAdmin.Utils.Filter(filterConfig, $http, $timeout, $rootScope);\n\t\t    $rootScope.filters.deploymentFilter = $scope.filter;\n\t    }\n\n\t    $scope.deploymentSelected = function(deployment) {\n\t    \tif (deployment && deployment.getProperty('id')) {\n\t    \t\t$location.path('/deployment/' + deployment.getProperty('id'));\n\t    \t}\n\t    };\n\n\t    $q.all([$translate('DEPLOYMENTS.HEADER.ID'),\n              $translate('DEPLOYMENTS.HEADER.NAME'),\n              $translate('DEPLOYMENTS.HEADER.DEPLOY-TIME'),\n              $translate('DEPLOYMENTS.HEADER.CATEGORY'),\n              $translate('DEPLOYMENTS.HEADER.TENANT')])\n              .then(function(headers) {\n\n          // Config for grid\n          $scope.gridDeployments = {\n              data: 'deploymentsData.data',\n              enableRowReordering: true,\n              multiSelect: false,\n              keepLastSelected : false,\n              rowHeight: 36,\n              afterSelectionChange: $scope.deploymentSelected,\n              columnDefs: [\n                  { field: 'id', displayName: headers[0], cellTemplate: gridConstants.defaultTemplate},\n                  { field: 'name', displayName: headers[1], cellTemplate: gridConstants.defaultTemplate},\n                  { field: 'deploymentTime', displayName: headers[2], cellTemplate: gridConstants.dateTemplate},\n                  { field: 'category', displayName: headers[3], cellTemplate: gridConstants.defaultTemplate},\n                  { field: 'tenantId', displayName: headers[4], cellTemplate: gridConstants.defaultTemplate}]\n          };\n      });\n\n      $scope.executeWhenReady(function() {\n          $scope.filter.refresh();\n      });\n\n\n      /*\n       * ACTIONS\n       */\n\n\n      $scope.uploadDeployment = function () {\n          var modalInstance = $modal.open({\n              templateUrl: 'views/upload-deployment.html',\n              controller: 'UploadDeploymentCtrl'\n          });\n          modalInstance.result.then(function (result) {\n              // Refresh page if closed successfully\n              if (result) {\n                  $scope.deploymentsData = {};\n                  $scope.filter.refresh();\n              }\n          });\n      };\n\n\n    }]);\n\n\n/**\\\n * Controller for the upload a model from the process Modeler.\n */\n flowableAdminApp.controller('UploadDeploymentCtrl',\n    ['$scope', '$modalInstance', '$http', 'Upload', '$timeout', '$translate', function ($scope, $modalInstance, $http, Upload, $timeout, $translate) {\n\n    $scope.status = {loading: false};\n\n    $scope.model = {};\n\n    $scope.onFileSelect = function($files) {\n\n        for (var i = 0; i < $files.length; i++) {\n            var file = $files[i];\n\n            file.upload = Upload.upload({\n                url: FlowableAdmin.webContextRoot + '/app/rest/admin/deployments',\n                method: 'POST',\n                data: {file: file}\n            });\n\n            file.upload.then(function (response) {\n                $timeout(function () {\n                    $scope.addAlert($translate.instant('ALERT.DEPLOYMENT.DEPLOYMENT-SUCCESS'), 'info');\n                    $scope.status.loading = false;\n                    $modalInstance.close(true);\n                });\n            }, function (response) {\n                if (response.data && response.data.message) {\n                    $scope.model.errorMessage = response.data.message;\n                }\n                $scope.model.error = true;\n                $scope.status.loading = false;\n            }, function (evt) {\n                file.progress = Math.min(100, parseInt(100.0 *\n                    evt.loaded / evt.total));\n            });\n\n        }\n\n    };\n\n    $scope.cancel = function () {\n        if (!$scope.status.loading) {\n            $modalInstance.dismiss('cancel');\n        }\n    };\n\n}]);\n"
  },
  {
    "path": "flowable-ui-web/admin/scripts/directives.js",
    "content": "/* Copyright 2005-2015 Alfresco Software, Ltd.\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'use strict';\n\nangular.module('flowableAdminApp')\n    .directive('autoFocus', ['$timeout', function($timeout) {\n        return {\n            restrict: 'AC',\n            link: function(_scope, _element) {\n                $timeout(function(){\n                    _element[0].focus();\n                }, 100);\n            }\n        };\n    }])\n    .directive('loadingIndicator', ['$translate', function($translate) {\n        return {\n            restrict: 'E',\n            template: '<div class=\\'loading pull-right\\' ng-show=\\'status.loading\\'><div class=\\'l1\\'></div><div class=\\'l2\\'></div><div class=\\'l2\\'></div></div>'\n        };\n    }])\n    .directive('activeMenu', ['$translate', function($translate) {\n        return {\n            restrict: 'A',\n            link: function(scope, element, attrs, controller) {\n                var language = attrs.activeMenu;\n\n                scope.$watch(function() {\n                    return $translate.uses();\n                }, function(selectedLanguage) {\n                    if (language === selectedLanguage) {\n                        element.addClass('active');\n                    } else {\n                        element.removeClass('active');\n                    }\n                });\n            }\n        };\n    }])\n    .directive('activeLink', ['$location', function(location) {\n        return {\n            restrict: 'A',\n            link: function(scope, element, attrs, controller) {\n                var clazz = attrs.activeLink;\n                var path = attrs.href;\n                path = path.substring(1); //hack because path does bot return including hashbang\n                scope.location = location;\n                scope.$watch('location.path()', function(newPath) {\n                    if (path === newPath) {\n                        element.addClass(clazz);\n                    } else {\n                        element.removeClass(clazz);\n                    }\n                });\n            }\n        };\n    }])\n    .directive('hourChart', [function () {\n        return {\n            restrict: 'E',\n            templateUrl: 'views/monitoring-hour-chart.html',\n            scope: {\n                model : '=model',\n            },\n            link: function ($scope, element, attributes) {\n            }\n        };\n    }])\n    .directive('weekdayChart', [function () {\n        return {\n            restrict: 'E',\n            templateUrl: 'views/monitoring-weekday-chart.html',\n            scope: {\n                model : '=model',\n            },\n            link: function ($scope, element, attributes) {\n            }\n        };\n    }])\n    /** Typeahead scroll hack\n     *  directive used in typeahead custom template that enables scrolling \n     *  Must be used in the outer most element of the template and\n     *  passed it's index typeahedScrollItem=\"$parent.$index\" */\n    .directive('typeaheadScrollItem', function($timeout) {\n        return {link: function(scope, element, attrs) {\n        \n            scope.$watch(attrs.typeaheadScrollItem, function (index) {\n                scope.myIndex = index; // this element's index\n            \n                if (index === 0) { // if first item scroll to top\n                    $timeout(function(){\n                        element.parent().parent().scrollTop(0);\n                    }, 100);\n                }\n            });\n        \n            // listen when parent's active index changes\n            scope.$parent.$watch('active', function (active) {\n                if (scope.myIndex === active) { // if this is the active item\n                    var liElement = element.parent();\n                    var ulElement = liElement.parent();\n                    var elementTop = liElement.offset().top;\n                    var minTop = ulElement.offset().top;\n                    var maxTop = minTop + ulElement.height();\n                    if(!(elementTop > minTop && elementTop < maxTop)) {\n                        liElement[0].scrollIntoView();\n                    }\n                }\n            });\n        }};\n    })\n    // Form field preview\n    .directive('fieldPreview', ['RecursionHelper', function (RecursionHelper) {\n    return {\n        restrict: 'E',\n        templateUrl: 'views/field-preview-template.html',\n        transclude: false,\n        scope: {\n            field: '=',\n            customFieldTemplates: '='\n        },\n        compile: function (element) {\n            return RecursionHelper.compile(element, this.link);\n        },\n        link: function ($scope, $element, attributes) {\n            \n            $scope.getHtmlTemplate = function(field) {\n                return $scope.customFieldTemplates[field.type];\n            };\n            \n            // initialize dynamic table if field's type is dynamic-table\n            // or references a dynamic table\n            \n            if ($scope.field.type === 'dynamic-table') {\n                if ($scope.field.columnDefinitions && $scope.field.columnDefinitions.length > 0) {\n                    initializeDynamicTable($scope.field.columnDefinitions);\n                }\n            } else if ($scope.field.type === 'readonly') {\n                if ($scope.field.params && $scope.field.params.field.columnDefinitions && $scope.field.params.field.columnDefinitions.length > 0) {\n                    initializeDynamicTable($scope.field.params.field.columnDefinitions);\n                }\n            }\n            \n            function initializeDynamicTable (columnDefinitions) {\n                \n                var columnDefs = [];\n                \n                for (var i = 0; i < columnDefinitions.length; i++) {\n                    if (columnDefinitions[i].visible) {\n                        columnDefs.push({\n                            'field': columnDefinitions[i].name,\n                            'displayName': columnDefinitions[i].name,\n                            'enableColumnMenu': false\n                        });\n                    }\n                }\n                \n                $scope.gridOptions = {\n                        columnDefs: columnDefs,\n                        enableRowSelection: false,\n                        enableSorting: false,\n                        enableRowHeaderSelection: false,\n                        multiSelect: false,\n                        enableHorizontalScrollbar: 0,\n                        modifierKeysToMultiSelect: false\n                    };\n            }\n        }\n    }\n}])\n\n    // Form element\n    .directive('formElement', ['RecursionHelper', function (RecursionHelper) {\n    return {\n        restrict: 'E',\n        templateUrl: 'views/form-element-template.html',\n        transclude: false,\n        scope: {\n            field: '=',\n            customFieldTemplates: '='\n        },\n        compile: function (element) {\n            return RecursionHelper.compile(element, this.link);\n        },\n        link: function ($scope, $element, attributes) {\n            \n            $scope.getHtmlTemplate = function(field) {\n                return $scope.customFieldTemplates[field.type];\n            };\n            \n            // initialize dynamic table if field's type is dynamic-table\n            // or references a dynamic table\n            \n            if ($scope.field.type === 'dynamic-table') {\n                if ($scope.field.columnDefinitions && $scope.field.columnDefinitions.length > 0) {\n                    initializeDynamicTable($scope.field.columnDefinitions);\n                }\n            } else if ($scope.field.type === 'readonly') {\n                if ($scope.field.params && $scope.field.params && $scope.field.params.field && $scope.field.params.field.type === 'dynamic-table') {\n                    if ($scope.field.columnDefinitions && $scope.field.columnDefinitions.length > 0) {\n                        initializeDynamicTable($scope.field.columnDefinitions, $scope.field.value);\n                    } else if ($scope.field.params.field.columnDefinitions && $scope.field.params.field.columnDefinitions.length > 0) {\n                        initializeDynamicTable($scope.field.params.field.columnDefinitions, $scope.field.value);\n                    }\n                }\n            }\n            \n            function initializeDynamicTable (columnDefinitions, data) {\n                var columnDefs = [];\n                \n                for (var i = 0; i < columnDefinitions.length; i++) {\n                    if (columnDefinitions[i].visible) {\n                        columnDefs.push({\n                            'field': columnDefinitions[i].id,\n                            'displayName': columnDefinitions[i].name,\n                            'enableColumnMenu': false\n                        });\n                    }\n                }\n                \n                $scope.gridOptions = {\n                        columnDefs: columnDefs,\n                        data: data,\n                        enableRowSelection: false,\n                        enableSorting: false,\n                        enableRowHeaderSelection: false,\n                        multiSelect: false,\n                        enableHorizontalScrollbar: 0,\n                        modifierKeysToMultiSelect: false\n                    };\n            }\n        }\n    }\n}])\n\n    .directive('numberInputCheck', function() {\n\n        return {\n            require: 'ngModel',\n            link: function(scope, element, attrs, modelCtrl) {\n\n                var opts = {\n                        positiveOnly: attrs.numberPositiveOnly ? true : false,\n                        moneyFraction: attrs.numberMoneyFraction ? true : false\n                    };\n\n                modelCtrl.$parsers.push(function (inputValue) {\n\n                    var transformedInput;\n                    if (inputValue && inputValue.indexOf('-') === 0 && !opts.positiveOnly) {\n                        transformedInput = inputValue.substr(1).replace(/([^0-9])/g, '');\n                        transformedInput = '-' + transformedInput;\n                    } else {\n                        transformedInput = inputValue.replace(/([^0-9])/g, '');\n                    }\n\n                    var parsed = parseInt(transformedInput);\n                    if (!isNaN(parsed) && !opts.moneyFraction) {\n                        transformedInput = parsed.toString();\n                    }\n\n                    if (transformedInput != inputValue) {\n                        modelCtrl.$setViewValue(transformedInput);\n                        modelCtrl.$render();\n                    }\n\n                    return transformedInput;\n                });\n            }\n        };\n    });\n    \n"
  },
  {
    "path": "flowable-ui-web/admin/scripts/engine-controller.js",
    "content": "/* Copyright 2005-2015 Alfresco Software, Ltd.\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'use strict';\n\n/* Controllers */\n\nflowableAdminApp.controller('EngineController', ['$rootScope', '$scope', '$http', '$timeout', '$modal', '$translate',\n    function ($rootScope, $scope, $http, $timeout, $modal, $translate) {\n\n        // Set root navigation\n        $rootScope.navigation = {selection: 'engine'};\n\n        // Static data\n        $scope.options = {\n            schemaUpdate: ['true', 'false'],\n            history: ['none', 'activity', 'audit', 'full']\n        };\n\n        // Empty model\n        $scope.model = {};\n\n\n        // Show popup to edit the Flowable endpoint\n        $scope.editProcessEndpointConfig = function () {\n            editEndpointConfig(1);\n        };\n\n        $scope.editDmnEndpointConfig = function () {\n            editEndpointConfig(2);\n        };\n\n        $scope.editFormEndpointConfig = function () {\n            editEndpointConfig(3);\n        };\n\n        $scope.editContentEndpointConfig = function () {\n            editEndpointConfig(4);\n        };\n        \n        $scope.editCmmnEndpointConfig = function () {\n            editEndpointConfig(5);\n        };\n        \n        $scope.editAppEndpointConfig = function () {\n            editEndpointConfig(6);\n        };\n\n        var editEndpointConfig = function (endpointType) {\n\n            var selectedServer;\n\n            if (endpointType === 1) {\n                selectedServer = $rootScope.activeServers['process'];\n            } else if (endpointType === 2) {\n                selectedServer = $rootScope.activeServers['dmn'];\n            } else if (endpointType === 3) {\n                selectedServer = $rootScope.activeServers['form'];\n            } else if (endpointType === 4) {\n                selectedServer = $rootScope.activeServers['content'];\n            } else if (endpointType === 5) {\n                selectedServer = $rootScope.activeServers['cmmn'];\n            } else if (endpointType === 6) {\n                selectedServer = $rootScope.activeServers['app'];\n            }\n\n            if (selectedServer) {\n                showEditpointConfigModel(selectedServer);\n            } else {\n                // load default endpoint configs properties\n                $http({method: 'GET', url: FlowableAdmin.webContextRoot + '/app/rest/server-configs/default/'+endpointType}).\n                success(function(defaultServerconfig, status, headers, config) {\n                    showEditpointConfigModel(defaultServerconfig);\n                });\n            }\n\n            function showEditpointConfigModel(server) {\n                var cloneOfModel = {};\n                for (var prop in server) {\n                    cloneOfModel[prop] = server[prop];\n                }\n\n                var modalInstance = $modal.open({\n                    templateUrl: 'views/engine-edit-endpoint-popup.html',\n                    controller: 'EditEndpointConfigModalInstanceCtrl',\n                    resolve: {\n                        server: function () {\n                            return cloneOfModel;\n                        }\n                    }\n                });\n\n                modalInstance.result.then(function (result) {\n                    if (result) {\n                        $scope.addAlert($translate.instant('ALERT.ENGINE.ENDPOINT-UPDATED', result), 'info');\n                        if (endpointType === 1) {\n                            $rootScope.activeServers['process'] = result;\n                        } else if (endpointType === 2) {\n                            $rootScope.activeServers['dmn'] = result;\n                        } else if (endpointType === 3) {\n                            $rootScope.activeServers['form'] = result;\n                        } else if (endpointType === 4) {\n                            $rootScope.activeServers['content'] = result;\n                        } else if (endpointType === 5) {\n                            $rootScope.activeServers['cmmn'] = result;\n                        } else if (endpointType === 6) {\n                            $rootScope.activeServers['app'] = result;\n                        }\n                    }\n                });\n            }\n        };\n\n        $scope.checkProcessEndpointConfig = function () {\n            checkEndpointConfig(1);\n        };\n\n        $scope.checkDmnEndpointConfig = function () {\n            checkEndpointConfig(2);\n        };\n\n        $scope.checkFormEndpointConfig = function () {\n            checkEndpointConfig(3);\n        };\n\n        $scope.checkContentEndpointConfig = function () {\n            checkEndpointConfig(4);\n        };\n        \n        $scope.checkCmmnEndpointConfig = function () {\n            checkEndpointConfig(5);\n        };\n        \n        $scope.checkAppEndpointConfig = function () {\n            checkEndpointConfig(6);\n        };\n\n        var checkEndpointConfig = function (endpointType) {\n            $http({\n                method: 'GET',\n                url: FlowableAdmin.webContextRoot + '/app/rest/admin/engine-info/'+endpointType,\n                ignoreErrors: true\n            }).success(function (data) {\n                $scope.addAlert($translate.instant('ALERT.ENGINE.ENDPOINT-VALID', data), 'info');\n            }).error(function () {\n                $scope.addAlert($translate.instant('ALERT.ENGINE.ENDPOINT-INVALID', $rootScope.activeServer), 'error');\n            });\n        };\n    }]);\n\n\nflowableAdminApp.controller('EditEndpointConfigModalInstanceCtrl',\n    ['$scope', '$modalInstance', '$http', 'server', function ($scope, $modalInstance, $http, server) {\n\n        $scope.model = {server: server};\n\n        $scope.status = {loading: false};\n\n        $scope.ok = function () {\n            $scope.status.loading = true;\n\n            delete $scope.model.error;\n\n            var serverConfigUrl = FlowableAdmin.webContextRoot + '/app/rest/server-configs';\n            var method = 'PUT';\n            if ($scope.model.server && $scope.model.server.id) {\n                serverConfigUrl += '/' + $scope.model.server.id;\n            } else {\n                method = 'POST';\n            }\n\n            $http({\n                method: method,\n                url: serverConfigUrl,\n                data: $scope.model.server\n            }).success(function (data, status, headers, config) {\n                $scope.status.loading = false;\n                $modalInstance.close($scope.model.server);\n            }).error(function (data, status, headers, config) {\n                $scope.status.loading = false;\n                $scope.model.error = {\n                    statusCode: status,\n                    message: data\n                };\n            });\n        };\n\n        $scope.cancel = function () {\n            if (!$scope.status.loading) {\n                $modalInstance.dismiss('cancel');\n            }\n        };\n    }]);\n"
  },
  {
    "path": "flowable-ui-web/admin/scripts/event-subscription-controllers.js",
    "content": "/* \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'use strict';\n\nflowableAdminApp.controller('EventSubscriptionController', ['$scope', '$rootScope', '$http', '$timeout','$location','$routeParams', '$modal', '$translate',\n    function ($scope, $rootScope, $http, $timeout, $location, $routeParams, $modal, $translate) {\n\t\t$rootScope.navigation = {main: 'process-engine', sub: 'event-subscriptions'};\n\t\t\n\t\t$scope.returnToList = function() {\n\t\t\t$location.path(\"/event-subscriptions\");\n\t\t};\n\n\t\t$scope.triggerEvent = function() {\n\t\t\tvar dataForPost = {\n\t\t\t\teventType: $scope.eventSubscription.eventType,\n\t\t\t\teventName: $scope.eventSubscription.eventName,\n\t\t\t};\n\t\t\t\n            if ($scope.eventSubscription.executionId !== undefined && $scope.eventSubscription.executionId.length > 0) {\n                dataForPost.executionId = $scope.eventSubscription.executionId;\n            }\n            \n            if ($scope.eventSubscription.tenantId !== undefined && $scope.eventSubscription.tenantId.length > 0) {\n                dataForPost.tenantId = $scope.eventSubscription.tenantId;\n            }\n\t\t\n\t\t\t$http({method: 'POST', \n\t\t\t\turl: FlowableAdmin.webContextRoot + '/app/rest/admin/event-subscriptions/' + $scope.eventSubscription.id,\n\t\t\t\tdata: dataForPost}).\n        \tsuccess(function(data, status, headers, config) {\n        \t  $scope.addAlert($translate.instant('ALERT.EVENT-SUBSCRIPTION.TRIGGERED', $scope.eventSubscription), 'info');\n        \t\t$scope.returnToList();\n        \t})\n        \t.error(function(data, status, headers, config) {\n        \t\t$scope.loadEventSubscription();\n        \t});\n\t\t};\n\n\t\t$scope.openProcessInstance = function(processInstanceId) {\n\t\t\tif (processInstanceId) {\n\t\t\t\t$location.path(\"/process-instance/\" + processInstanceId);\n\t\t\t}\n\t\t};\n\n\t\t$scope.openProcessDefinition = function(processDefinitionId) {\n\t\t\tif (processDefinitionId) {\n\t\t\t\t$location.path(\"/process-definition/\" + processDefinitionId);\n\t\t\t}\n\t\t};\n\n\t\t$scope.loadEventSubscription = function() {\n\t\t\t$scope.eventSubscription = {};\n\t\t\t$http({method: 'GET', url: FlowableAdmin.webContextRoot + '/app/rest/admin/event-subscriptions/' + $routeParams.eventSubscriptionId}).\n\t    \tsuccess(function(data, status, headers, config) {\n\t            $scope.eventSubscription = data;\n\t    \t}).\n\t    \terror(function(data, status, headers, config) {\n                if (data && data.message) {\n                    // Extract error-message\n                    $rootScope.addAlert(data.message, 'error');\n                } else {\n                    // Use default error-message\n                    $rootScope.addAlert($translate.instant('ALERT.GENERAL.HTTP-ERROR'), 'error');\n                }\n            });\n\t\t};\n\n\t\t// Load job\n\t\t$scope.executeWhenReady(function() {\n\t\t    $scope.loadEventSubscription();\n\t\t});\n\n}]);\n"
  },
  {
    "path": "flowable-ui-web/admin/scripts/event-subscriptions-controllers.js",
    "content": "/* \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'use strict';\n\n/* Controllers */\n\nflowableAdminApp.controller('EventSubscriptionsController', ['$scope', '$rootScope', '$http', '$timeout','$location','$translate', '$q', 'gridConstants',\n    function ($scope, $rootScope, $http, $timeout, $location, $translate, $q, gridConstants) {\n\t\t$rootScope.navigation = {main: 'process-engine', sub: 'event-subscriptions'};\n\t\t\n\t\t$scope.eventSubscriptionData = {};\n\t    $scope.selectedEvents = [];\n\n\t    var filterConfig = {\n\t\t    \turl: FlowableAdmin.webContextRoot + '/app/rest/admin/event-subscriptions',\n\t\t    \tmethod: 'GET',\n\t\t    \tsuccess: function(data, status, headers, config) {\n\t\t    \t\tif ($scope.definitionCacheLoaded) {\n\t                \t$scope.processQueryResponse(data);\n\t                \t\n\t                } else {\n\t\t                $rootScope.loadProcessDefinitionsCache().then(function(promise) {\n  \t\t        \t\t\t$rootScope.processDefinitionsCache = promise.data;\n  \t\t        \t\t\t$scope.definitionCacheLoaded = true;\n  \t\t        \t\t\t$scope.processQueryResponse(data);\n  \t\t        \t\t});\n\t                }\n\t            },\n\t            error: function(data, status, headers, config) {\n\t                if (data && data.message) {\n\t                    // Extract error-message\n\t                    $rootScope.addAlert(data.message, 'error');\n\t                } else {\n\t                    // Use default error-message\n\t                    $rootScope.addAlert($translate.instant('ALERT.GENERAL.HTTP-ERROR'), 'error');\n\t                }\n\t            },\n\t            \n\t            sortObjects: [\n\t                {name: 'EVENT-SUBSCRIPTIONS.SORT.ID', id: 'id'},\n\t                {name: 'EVENT-SUBSCRIPTIONS.SORT.CREATE-DATE', id: 'dueDate'},\n\t                {name: 'EVENT-SUBSCRIPTIONS.SORT.PROCESS-INSTANCE-ID', id: 'processInstanceId'}\n\t            ],\n\t            \n\t            supportedProperties: [\n\t                {id: 'processInstanceId', name: 'EVENT-SUBSCRIPTIONS.FILTER.PROCESS-INSTANCE-ID'},\n\t                {id: 'tenantIdLike', name: 'EVENT-SUBSCRIPTIONS.FILTER.TENANT-ID'},\n\t                {id: 'createdBefore', name: 'EVENT-SUBSCRIPTIONS.FILTER.CREATED-BEFORE', showByDefault: true},\n\t                {id: 'createdAfter', name: 'EVENT-SUBSCRIPTIONS.FILTER.CREATED-AFTER', showByDefault: true}\n\t            ]\n\t\t    };\n\n    \t\t\n\t    if ($rootScope.filters.forced.eventSubscriptionsFilter) {\n\t    \t// Always recreate the filter and add all properties\n\t    \t$scope.filter = new FlowableAdmin.Utils.Filter(filterConfig, $http, $timeout, $rootScope);\n    \t\t$rootScope.filters.eventSubscriptionsFilter = $scope.filter;\n    \t\t\n    \t\tfor (var prop in $rootScope.filters.forced.eventSubscriptionsFilter) {\n    \t\t\t$scope.filter.addProperty({id: prop}, $rootScope.filters.forced.eventSubscriptionsFilter[prop]);\n    \t\t}\n    \t\t\n    \t\t$rootScope.filters.forced.eventSubscriptionsFilter = undefined;\n    \t\t\n\t    } else {\n\t    \tif ($rootScope.filters && $rootScope.filters.eventSubscriptionsFilter) {\n\t    \t\t// Reuse the existing filter\n\t    \t\t$scope.filter = $rootScope.filters.eventSubscriptionsFilter;\n\t    \t\t$scope.filter.config = filterConfig;\n\t    \t} else {\n\t    \t\t$scope.filter = new FlowableAdmin.Utils.Filter(filterConfig, $http, $timeout, $rootScope);\n\t    \t\t$rootScope.filters.eventSubscriptionsFilter = $scope.filter;\n\t    \t}\n\t    }\n\t    \n\t    $scope.eventSubscriptionSelected = function(event) {\n\t    \tif (event && event.getProperty('id')) {\n\t    \t\t$location.path('/event-subscriptions/' + event.getProperty('id'));\n\t    \t}\n\t    };\n\t    \n\t    $q.all([$translate('EVENT-SUBSCRIPTIONS.HEADER.ID'),\n\t            $translate('EVENT-SUBSCRIPTIONS.HEADER.EVENT-TYPE'),\n\t            $translate('EVENT-SUBSCRIPTIONS.HEADER.EVENT-NAME'), \n\t            $translate('EVENT-SUBSCRIPTIONS.HEADER.CREATE-DATE'),\n\t            $translate('EVENT-SUBSCRIPTIONS.HEADER.PROCESS-DEFINITION')])\n\t    .then(function(headers) { \n\n          // Config for grid\n          $scope.gridEventSubscriptions = {\n              data: 'eventSubscriptionData.data',\n              enableRowReordering: true,\n              multiSelect: false,\n              keepLastSelected : false,\n              enableSorting: false,\n              rowHeight: 36,\n              afterSelectionChange: $scope.eventSubscriptionSelected,\n              columnDefs: [\n                  { field: 'id', displayName: headers[0], width: 50, cellTemplate: gridConstants.defaultTemplate},\n                  { field: 'eventType', displayName: headers[1], cellTemplate: gridConstants.defaultTemplate},\n                  { field: 'eventName', displayName: headers[2], cellTemplate: gridConstants.defaultTemplate},\n                  { field: 'created', displayName: headers[3], cellTemplate: gridConstants.dateTemplate},\n                  { field: 'processDefinition.name', displayName: headers[4], cellTemplate: gridConstants.defaultTemplate}\n              ]\n          };\n\t     });\n        \n        $scope.processQueryResponse = function(eventsResponse) {\n        \tfor (var i = 0; i < eventsResponse.data.length; i++) {\n        \t\teventsResponse.data[i].processDefinition = \n            \t\t$rootScope.getProcessDefinitionFromCache(eventsResponse.data[i].processDefinitionId);\n            }\n        \t$scope.eventSubscriptionData = eventsResponse;\n        };\n        \n        $scope.processDefinitionFilterChanged = function() \n        {\n        \tif ($scope.filter.processDefinition && $scope.filter.processDefinition !== '-1') {\n        \t\t$scope.filter.properties.processDefinitionId = $scope.filter.processDefinition;\n        \t\t$scope.filter.refresh();\n        \t\t\n        \t} else {\n        \t\tvar tempProcessDefinitionId = $scope.filter.properties.processDefinitionId;\n        \t\t$scope.filter.properties.processDefinitionId = null;\n        \t\tif (tempProcessDefinitionId && tempProcessDefinitionId.length > 0) {\n        \t\t\t$scope.filter.refresh();\n        \t\t}\n        \t}\n        };\n        \n        $scope.executeWhenReady(function() {\n          \t$scope.filter.refresh();\n        });\n    }]);\n"
  },
  {
    "path": "flowable-ui-web/admin/scripts/filter-controllers.js",
    "content": "/* Copyright 2005-2015 Alfresco Software, Ltd.\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'use strict';\n\n/* Controllers */\n\nflowableAdminApp.controller('ProcessDefinitionFilterController', ['$scope', '$rootScope', '$http', '$timeout',\n    function ($scope, $rootScope, $http, $timeout) {\n\t\n\t$scope.setFilterPropertyName = function(filterPropertyName) {\n\t\t$scope.filterPropertyName = filterPropertyName;\n\t\t\n\t\t$scope.filter[filterPropertyName] = \"TEST\";\n\t};\n\t\n}]);\n"
  },
  {
    "path": "flowable-ui-web/admin/scripts/form-definition-controllers.js",
    "content": "/* Copyright 2005-2015 Alfresco Software, Ltd.\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'use strict';\n\nflowableAdminApp.controller('FormDefinitionController', ['$scope', '$rootScope', '$http', '$timeout', '$location', '$routeParams', '$modal', '$translate', '$q', 'gridConstants',\n    function ($scope, $rootScope, $http, $timeout, $location, $routeParams, $modal, $translate, $q, gridConstants) {\n        $rootScope.navigation = {main: 'form-engine', sub: 'definitions'};\n\n        $scope.returnToList = function () {\n            $location.path(\"/form-definitions\");\n        };\n\n        $scope.showForm = function () {\n            $modal.open({\n                templateUrl: 'views/form-popup.html',\n                windowClass: 'modal modal-full-width',\n                controller: 'ShowFormPopupCtrl',\n                resolve: {\n                    form: function () {\n                        return $scope.form;\n                    }\n                }\n            });\n        };\n\n        $scope.showFormInstance = function (formInstance) {\n            if (formInstance && formInstance.getProperty('id')) {\n                $location.path(\"/form-instance/\"+formInstance.getProperty('id'));\n            }\n        };\n\n       $scope.openDeployment = function(deploymentId) {\n            if (deploymentId) {\n                $location.path(\"/deployment/\" + deploymentId);\n            }\n        };\n\n        $q.all([$translate('FORM-INSTANCE.HEADER.ID'),\n                $translate('FORM-INSTANCE.HEADER.TASK-ID'),\n                $translate('FORM-INSTANCE.HEADER.PROCESS-ID'),\n                $translate('FORM-INSTANCE.HEADER.SUBMITTED'),\n                $translate('FORM-INSTANCE.HEADER.SUBMITTED-BY')])\n            .then(function (headers) {\n\n                $scope.gridFormInstances = {\n                    data: 'formInstances.data',\n                    enableRowReordering: false,\n                    multiSelect: false,\n                    keepLastSelected: false,\n                    enableSorting: false,\n                    rowHeight: 36,\n                    afterSelectionChange: $scope.showFormInstance,\n                    columnDefs: [\n                        {field: 'id', displayName: headers[0]},\n                        {field: 'taskId', displayName: headers[1]},\n                        {field: 'processInstanceId', displayName: headers[2]},\n                        {field: 'submittedDate', displayName: headers[3], cellTemplate: gridConstants.dateTemplate},\n                        {field: 'submittedBy', displayName: headers[4], cellTemplate: gridConstants.userObjectTemplate}\n                    ]\n                };\n            });\n\n        $scope.executeWhenReady(function () {\n            // Load form\n            $http({method: 'GET', url: FlowableAdmin.webContextRoot + '/app/rest/admin/form-definitions/' + $routeParams.formId}).\n            success(function (data, status, headers, config) {\n                $scope.form = data;\n\n                // Load form submitted forms\n                $http({\n                    method: 'GET',\n                    url: FlowableAdmin.webContextRoot + '/app/rest/admin/form-definition-form-instances/' + $routeParams.formId\n                }).\n                success(function (formInstancesData, status, headers, config) {\n                    $scope.formInstances = formInstancesData;\n                });\n            }).\n            error(function (data, status, headers, config) {\n                if (data && data.message) {\n                    // Extract error-message\n                    $rootScope.addAlert(data.message, 'error');\n                } else {\n                    // Use default error-message\n                    $rootScope.addAlert($translate.instant('ALERT.GENERAL.HTTP-ERROR'), 'error');\n                }\n            });\n        });\n\n    }]);\n\nflowableAdminApp.controller('ShowFormPopupCtrl',\n    ['$rootScope', '$scope', '$modalInstance', '$http', 'form', '$timeout', '$translate', 'uiGridConstants',\n        function ($rootScope, $scope, $modalInstance, $http, form, $timeout, $translate, uiGridConstants) {\n\n            $scope.status = {loading: false};\n\n            $scope.cancel = function () {\n                if (!$scope.status.loading) {\n                    $modalInstance.dismiss('cancel');\n                }\n            };\n\n            $scope.popup = {};\n            \n            $scope.formTabClicked = function(tab) {\n                $scope.activeFormTab = tab;\n            };\n\n            $scope.executeWhenReady(function () {\n                // Load form definition\n                $http({\n                    method: 'GET',\n                    url: FlowableAdmin.webContextRoot + '/app/rest/admin/form-definitions/' + form.id + '/editorJson'\n                }).\n                success(function (data, status, headers, config) {\n                    $scope.popup.currentForm = data;\n                    $scope.popup.formName = form.name || '';\n                    resetActiveFormTab(data);\n                }).\n                error(function (data, status, headers, config) {\n                    if (data && data.message) {\n                        // Extract error-message\n                        $rootScope.addAlert(data.message, 'error');\n                    } else {\n                        // Use default error-message\n                        $rootScope.addAlert($translate.instant('ALERT.GENERAL.HTTP-ERROR'), 'error');\n                    }\n                });\n            });\n\n            function resetActiveFormTab(form) {\n                if (form.tabs && form.tabs.length > 0) {\n                    $scope.activeFormTab = form.tabs[0];\n                } else {\n                    $scope.activeFormTab = undefined;\n                }\n            };\n            \n        }]);\n"
  },
  {
    "path": "flowable-ui-web/admin/scripts/form-definitions-controllers.js",
    "content": "/* Copyright 2005-2015 Alfresco Software, Ltd.\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'use strict';\n\n/* Controllers */\n\nflowableAdminApp.controller('FormDefinitionsController', ['$rootScope', '$scope', '$http', '$timeout', '$location', '$translate', '$q', '$modal', 'gridConstants',\n    function ($rootScope, $scope, $http, $timeout, $location, $translate, $q, $modal, gridConstants) {\n\n        $rootScope.navigation = {main: 'form-engine', sub: 'definitions'};\n        \n        $scope.filter = {};\n        $scope.formsData = {};\n\n        // Array to contain selected properties (yes - we only can select one, but ng-grid isn't smart enough)\n        $scope.selectedForms = [];\n\n        var filterConfig = {\n            url: FlowableAdmin.webContextRoot + '/app/rest/admin/form-definitions',\n            method: 'GET',\n            success: function (data, status, headers, config) {\n                $scope.formsData = data;\n            },\n            error: function (data, status, headers, config) {\n                if (data && data.message) {\n                    // Extract error-message\n                    $rootScope.addAlert(data.message, 'error');\n                } else {\n                    // Use default error-message\n                    $rootScope.addAlert($translate.instant('ALERT.GENERAL.HTTP-ERROR'), 'error');\n                }\n            },\n\n            sortObjects: [\n                {name: 'FORM-DEFINITIONS.SORT.ID', id: 'id'},\n                {name: 'FORM-DEFINITIONS.SORT.NAME', id: 'name'}\n            ],\n\n            supportedProperties: [\n                {id: 'nameLike', name: 'FORM-DEFINITIONS.FILTER.NAME', showByDefault: true},\n                {id: 'appId', name: 'FORM-DEFINITIONS.FILTER.APPID', showByDefault: true},\n                {id: 'tenantId', name: 'FORM-DEFINITIONS.FILTER.TENANTID', showByDefault: true}\n            ]\n        };\n\n        if ($rootScope.filters && $rootScope.filters.formFilter) {\n            // Reuse the existing filter\n            $scope.filter = $rootScope.filters.formFilter;\n            $scope.filter.config = filterConfig;\n        } else {\n            $scope.filter = new FlowableAdmin.Utils.Filter(filterConfig, $http, $timeout, $rootScope);\n            $rootScope.filters.formFilter = $scope.filter;\n        }\n\n        $scope.formSelected = function (form) {\n            if (form && form.getProperty('id')) {\n                $location.path('/form-definition/' + form.getProperty('id'));\n            }\n        };\n\n        $q.all([$translate('FORM-DEFINITIONS.HEADER.ID'),\n                $translate('FORM-DEFINITIONS.HEADER.NAME'),\n                $translate('FORM-DEFINITIONS.HEADER.DEPLOYMENTID'),\n                $translate('FORM-DEFINITIONS.HEADER.TENANTID')])\n            .then(function (headers) {\n                // Config for grid\n                $scope.gridForms = {\n                    data: 'formsData.data',\n                    enableRowReordering: true,\n                    multiSelect: false,\n                    keepLastSelected: false,\n                    rowHeight: 36,\n                    afterSelectionChange: $scope.formSelected,\n                    columnDefs: [\n                        {field: 'id', displayName: headers[0], cellTemplate: gridConstants.defaultTemplate},\n                        {field: 'name', displayName: headers[1], cellTemplate: gridConstants.defaultTemplate},\n                        {field: 'deploymentId', displayName: headers[2], cellTemplate: gridConstants.defaultTemplate},\n                        {field: 'tenantId', displayName: headers[3], cellTemplate: gridConstants.defaultTemplate}]\n                };\n            });\n\n        $scope.executeWhenReady(function () {\n            $scope.filter.refresh();\n        });\n\n    }]);\n"
  },
  {
    "path": "flowable-ui-web/admin/scripts/form-deployment-controllers.js",
    "content": "/* 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'use strict';\n\nflowableAdminApp.controller('FormDeploymentController', ['$scope', '$rootScope', '$http', '$timeout','$location','$routeParams', '$modal', '$translate', '$q',\n    function ($scope, $rootScope, $http, $timeout, $location, $routeParams, $modal, $translate, $q) {\n\n        $rootScope.navigation = {main: 'form-engine', sub: 'deployments'};\n        \n\t\t$scope.returnToList = function() {\n\t\t\t$location.path(\"/form-deployments\");\n\t\t};\n\t\t\n\t\t$scope.openDefinition = function(definition) {\n\t\t\tif (definition && definition.getProperty('id')) {\n\t\t\t\t$location.path(\"/form-definition/\" + definition.getProperty('id'));\n\t\t\t}\n\t\t};\n\t\t\n\t\t$scope.showAllDefinitions = function() {\n\t\t    // Populate the form-filter with parentId\n\t\t    $rootScope.filters.forced.formDefinitionFilter = {\n\t\t            deploymentId: $scope.formDeployment.id\n\t\t    };\n\t\t    $location.path(\"/form-definitions\");\n\t\t};\n\t\t\n\t\t$q.all([$translate('FORM-DEFINITIONS.HEADER.ID'),\n            $translate('FORM-DEFINITIONS.HEADER.NAME'),\n            $translate('FORM-DEFINITIONS.HEADER.VERSION'),\n            $translate('FORM-DEFINITIONS.HEADER.KEY')])\n            .then(function(headers) { \n        \n                $scope.gridFormDefinitions = {\n                    data: 'formDefinitions.data',\n                    enableRowReordering: false,\n                    multiSelect: false,\n                    keepLastSelected : false,\n                    enableSorting: false,\n                    rowHeight: 36,\n                    afterSelectionChange: $scope.openDefinition,\n                    columnDefs: [\n                          { field: 'id', displayName: headers[0]},\n                          { field: 'name', displayName: headers[1]},\n                          { field: 'version', displayName: headers[2]},\n                          { field: 'key', displayName: headers[3]}\n                    ]\n                };\n        });\n\t\t\n\t\t$scope.deleteDeployment = function() {\n\t\t    var modalInstance = $modal.open({\n                templateUrl: 'views/confirm-popup.html',\n                controller: 'ConfirmPopupCtrl',\n                resolve: {\n                    model: function () {\n                      return {\n                          confirm: $translate.instant('FORM-DEPLOYMENTS.ACTION.DELETE'),\n                          title: $translate.instant('FORM-DEPLOYMENTS.ACTION.DELETE'),\n                          message: $translate.instant('FORM-DEPLOYMENTS.POPUP.DELETE.CONFIRM-MESSAGE', $scope.formDeployment)\n                          };\n                    }\n                }\n                \n            });\n            \n            modalInstance.result.then(function (result) {\n                if (result === true) {\n                    $http({method: 'DELETE', url: FlowableAdmin.webContextRoot + '/app/rest/admin/form-deployments/' + $routeParams.formDeploymentId}).\n                    success(function(data, status, headers, config) {\n                        $scope.addAlert($translate.instant('ALERT.FORM-DEPLOYMENT.DELETED-DEPLOYMENT', $scope.formDeployment), 'info');\n                        $scope.returnToList();\n                    }).\n                    error(function(data, status, headers, config) {\n                        $scope.addAlert($translate.instant('ALERT.FORM-DEPLOYMENT.DELETE-ERROR', data), 'error');\n                    });\n                }\n            });\n            \n        };\n        \n\t\t$scope.executeWhenReady(function() {\n\t\t    // Load deployment\n\t\t    $http({method: 'GET', url: FlowableAdmin.webContextRoot + '/app/rest/admin/form-deployments/' + $routeParams.formDeploymentId}).\n  \t    \t    success(function(data, status, headers, config) {\n  \t    \t        $scope.formDeployment = data;\n  \t    \t    }).\n  \t    \t    error(function(data, status, headers, config) {\n                    if (data && data.message) {\n                        // Extract error-message\n                        $rootScope.addAlert(data.message, 'error');\n                    } else {\n                        // Use default error-message\n                        $rootScope.addAlert($translate.instant('ALERT.GENERAL.HTTP-ERROR'), 'error');\n                    }\n  \t    \t    });\n  \t\t\n\t\t    // Load process definitions\n\t\t    $http({method: 'GET', url: FlowableAdmin.webContextRoot + '/app/rest/admin/form-definitions?deploymentId=' + $routeParams.formDeploymentId}).\n  \t    \t    success(function(data, status, headers, config) {\n  \t    \t        $scope.formDefinitions = data;\n  \t    \t    });\n\t\t    \n  \t     });\n}]);"
  },
  {
    "path": "flowable-ui-web/admin/scripts/form-deployments-controllers.js",
    "content": "/* 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'use strict';\n\n/* Controllers */\n\nflowableAdminApp.controller('FormDeploymentsController', ['$rootScope', '$scope', '$http', '$timeout', '$location', '$translate', '$q', '$modal', 'gridConstants',\n    function ($rootScope, $scope, $http, $timeout, $location, $translate, $q, $modal, gridConstants) {\n\n\t\t$rootScope.navigation = {main: 'form-engine', sub: 'deployments'};\n        \n\t\t$scope.filter = {};\n\t\t$scope.formDeploymentsData = {};\n\n\t\t// Array to contain selected properties (yes - we only can select one, but ng-grid isn't smart enough)\n\t    $scope.selectedDeployments = [];\n\n\t    var filterConfig = {\n\t    \turl: FlowableAdmin.webContextRoot + '/app/rest/admin/form-deployments',\n\t    \tmethod: 'GET',\n\t    \tsuccess: function(data, status, headers, config) {\n\t    \t\t$scope.formDeploymentsData = data;\n            },\n            error: function(data, status, headers, config) {\n                if (data && data.message) {\n                    // Extract error-message\n                    $rootScope.addAlert(data.message, 'error');\n                } else {\n                    // Use default error-message\n                    $rootScope.addAlert($translate.instant('ALERT.GENERAL.HTTP-ERROR'), 'error');\n                }\n            },\n\n            sortObjects: [\n                {name: 'FORM-DEPLOYMENTS.SORT.ID', id: 'id'},\n                {name: 'FORM-DEPLOYMENTS.SORT.NAME', id: 'name'}\n            ],\n\n            supportedProperties: [\n                {id: 'nameLike', name: 'FORM-DEPLOYMENTS.FILTER.NAME', showByDefault: true},\n                {id: 'tenantIdLike', name: 'FORM-DEPLOYMENTS.FILTER.TENANTID', showByDefault: true}\n            ]\n\t    };\n\n\t    if($rootScope.filters && $rootScope.filters.formDeploymentFilter) {\n\t    \t// Reuse the existing filter\n\t    \t$scope.filter = $rootScope.filters.formDeploymentFilter;\n\t    \t$scope.filter.config = filterConfig;\n\t    } else {\n\t\t    $scope.filter = new FlowableAdmin.Utils.Filter(filterConfig, $http, $timeout, $rootScope);\n\t\t    $rootScope.filters.formDeploymentFilter = $scope.filter;\n\t    }\n\n\t    $scope.deploymentSelected = function(deployment) {\n\t    \tif (deployment && deployment.getProperty('id')) {\n\t    \t\t$location.path('/form-deployment/' + deployment.getProperty('id'));\n\t    \t}\n\t    };\n\n\t    $q.all([$translate('FORM-DEPLOYMENTS.HEADER.ID'),\n              $translate('FORM-DEPLOYMENTS.HEADER.NAME'),\n              $translate('FORM-DEPLOYMENTS.HEADER.DEPLOY-TIME'),\n              $translate('FORM-DEPLOYMENTS.HEADER.CATEGORY'),\n              $translate('FORM-DEPLOYMENTS.HEADER.TENANT')])\n              .then(function(headers) {\n\n          // Config for grid\n          $scope.gridFormDeployments = {\n              data: 'formDeploymentsData.data',\n              enableRowReordering: true,\n              multiSelect: false,\n              keepLastSelected : false,\n              rowHeight: 36,\n              afterSelectionChange: $scope.deploymentSelected,\n              columnDefs: [\n                  { field: 'id', displayName: headers[0], cellTemplate: gridConstants.defaultTemplate},\n                  { field: 'name', displayName: headers[1], cellTemplate: gridConstants.defaultTemplate},\n                  { field: 'deploymentTime', displayName: headers[2], cellTemplate: gridConstants.dateTemplate},\n                  { field: 'category', displayName: headers[3], cellTemplate: gridConstants.defaultTemplate},\n                  { field: 'tenantId', displayName: headers[4], cellTemplate: gridConstants.defaultTemplate}]\n          };\n      });\n\n      $scope.executeWhenReady(function() {\n          $scope.filter.refresh();\n      });\n\n\n      /*\n       * ACTIONS\n       */\n\n      $scope.uploadDeployment = function () {\n          var modalInstance = $modal.open({\n              templateUrl: 'views/upload-form-deployment.html',\n              controller: 'UploadFormDeploymentCtrl'\n          });\n          modalInstance.result.then(function (result) {\n              // Refresh page if closed successfully\n              if (result) {\n                  $scope.deploymentsData = {};\n                  $scope.filter.refresh();\n              }\n          });\n      };\n\n\n    }]);\n\n\n/**\\\n * Controller for the upload a model from the process Modeler.\n */\n flowableAdminApp.controller('UploadFormDeploymentCtrl',\n    ['$scope', '$modalInstance', '$http', 'Upload', '$timeout', '$translate', function ($scope, $modalInstance, $http, Upload, $timeout, $translate) {\n\n    $scope.status = {loading: false};\n\n    $scope.model = {};\n\n    $scope.onFileSelect = function($files) {\n\n        for (var i = 0; i < $files.length; i++) {\n            var file = $files[i];\n            file.upload = Upload.upload({\n                url: FlowableAdmin.webContextRoot + '/app/rest/admin/form-deployments',\n                method: 'POST',\n                data: {file: file}\n            });\n\n            file.upload.then(function (response) {\n                $timeout(function () {\n                    $scope.addAlert($translate.instant('ALERT.DEPLOYMENT.DEPLOYMENT-SUCCESS'), 'info');\n                    $scope.status.loading = false;\n                    $modalInstance.close(true);\n                });\n            }, function (response) {\n                if (response.data && response.data.message) {\n                    $scope.model.errorMessage = response.data.message;\n                }\n                $scope.model.error = true;\n                $scope.status.loading = false;\n            }, function (evt) {\n                file.progress = Math.min(100, parseInt(100.0 *\n                    evt.loaded / evt.total));\n            });\n        }\n    };\n\n    $scope.cancel = function () {\n        if (!$scope.status.loading) {\n            $modalInstance.dismiss('cancel');\n        }\n    };\n\n}]);\n"
  },
  {
    "path": "flowable-ui-web/admin/scripts/form-instance-controllers.js",
    "content": "/* Copyright 2005-2015 Alfresco Software, Ltd.\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'use strict';\n\n/* Controllers */\n\nflowableAdminApp.controller('FormInstanceController', ['$rootScope', '$scope', '$http', '$timeout', '$location', '$translate', '$q', '$modal', '$routeParams',\n    function ($rootScope, $scope, $http, $timeout, $location, $translate, $q, $modal, $routeParams) {\n\n        $rootScope.navigation = {main: 'form-engine', sub: 'instances'};\n\n        $scope.returnToList = function () {\n            $location.path(\"/form-instances\");\n        };\n\n        $q.all([$translate('FORM-INSTANCE.FORM-FIELD-VALUES.ID'),\n            $translate('FORM-INSTANCE.FORM-FIELD-VALUES.NAME'),\n            $translate('FORM-INSTANCE.FORM-FIELD-VALUES.TYPE'),\n            $translate('FORM-INSTANCE.FORM-FIELD-VALUES.VALUE')])\n            .then(function (headers) {\n\n                $scope.gridFormFieldValues = {\n                    data: 'formFieldValues.data',\n                    enableRowReordering: false,\n                    multiSelect: false,\n                    keepLastSelected: false,\n                    enableSorting: false,\n                    rowHeight: 36,\n                    afterSelectionChange: $scope.showFormInstance,\n                    columnDefs: [\n                        {field: 'id', displayName: headers[0]},\n                        {field: 'name', displayName: headers[1]},\n                        {field: 'type', displayName: headers[2]},\n                        {field: 'value', displayName: headers[3], cellFilter: 'empty'}\n                    ]\n                };\n            });\n        \n        $scope.executeWhenReady(function () {\n            if ($rootScope.formInstance) {\n                $scope.formInstance = $rootScope.formInstance;\n                $rootScope.formInstance = undefined;\n                return;\n            }\n            \n            // Load submitted form\n            $http({method: 'GET', url: FlowableAdmin.webContextRoot + '/app/rest/admin/form-instances/' + $routeParams.formInstanceId}).\n            success(function (data, status, headers, config) {\n                $scope.formInstance = data;\n\n                // Load form submitted forms\n                $http({\n                    method: 'GET',\n                    url: FlowableAdmin.webContextRoot + '/app/rest/admin/form-instances/' + $routeParams.formInstanceId + '/form-field-values/'\n                }).\n                success(function (formFieldValuesData, status, headers, config) {\n                    $scope.formFieldValues = formFieldValuesData;\n                });\n            }).\n            error(function (data, status, headers, config) {\n                if (data && data.message) {\n                    // Extract error-message\n                    $rootScope.addAlert(data.message, 'error');\n                } else {\n                    // Use default error-message\n                    $rootScope.addAlert($translate.instant('ALERT.GENERAL.HTTP-ERROR'), 'error');\n                }\n            });\n        });\n    }]);\n\nflowableAdminApp.controller('ShowFormRenderPopupCtrl',\n        ['$rootScope', '$scope', '$modalInstance', '$http', 'form', '$timeout', '$translate', 'uiGridConstants',\n            function ($rootScope, $scope, $modalInstance, $http, form, $timeout, $translate, uiGridConstants) {\n\n                $scope.status = {loading: false};\n\n                $scope.cancel = function () {\n                    if (!$scope.status.loading) {\n                        $modalInstance.dismiss('cancel');\n                    }\n                };\n\n                $scope.popup = {};\n                \n                $scope.formTabClicked = function(tab) {\n                    $scope.activeFormTab = tab;\n                };\n\n                $scope.executeWhenReady(function () {\n                    if (!form.form) {\n                        // Load form\n                        $http({\n                            method: 'GET',\n                            url: FlowableAdmin.webContextRoot + '/app/rest/admin/form-instances/' + form.id\n                        }).\n                        success(function (data, status, headers, config) {\n                            $scope.popup.currentForm = data.form;\n                            $scope.popup.formName = form.name || '';\n                            resetActiveFormTab(data.form);\n                        }).\n                        error(function (data, status, headers, config) {\n                            if (data && data.message) {\n                                // Extract error-message\n                                $rootScope.addAlert(data.message, 'error');\n                            } else {\n                                // Use default error-message\n                                $rootScope.addAlert($translate.instant('ALERT.GENERAL.HTTP-ERROR'), 'error');\n                            }\n                        });\n                    } else {\n                        $scope.popup.currentForm = form.form;\n                        $scope.popup.formName = form.name || '';\n                        resetActiveFormTab(form.form);\n                    }\n                });\n\n                function resetActiveFormTab(form) {\n                    if (form.tabs && form.tabs.length > 0) {\n                        $scope.activeFormTab = form.tabs[0];\n                    } else {\n                        $scope.activeFormTab = undefined;\n                    }\n                };\n                \n            }]);"
  },
  {
    "path": "flowable-ui-web/admin/scripts/form-instances-controllers.js",
    "content": "/* 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'use strict';\n\n/* Controllers */\n\nflowableAdminApp.controller('FormInstancesController', ['$rootScope', '$scope', '$http', '$timeout', '$location', '$translate', '$q', '$modal', 'gridConstants',\n    function ($rootScope, $scope, $http, $timeout, $location, $translate, $q, $modal, gridConstants) {\n\n        $rootScope.navigation = {main: 'form-engine', sub: 'instances'};\n        \n        $scope.filter = {};\n        $scope.formInstancesData = {};\n\n        // Array to contain selected properties (yes - we only can select one, but ng-grid isn't smart enough)\n        $scope.selectedForms = [];\n\n        var filterConfig = {\n            url: FlowableAdmin.webContextRoot + '/app/rest/admin/form-instances',\n            method: 'GET',\n            success: function (data, status, headers, config) {\n                $scope.formInstancesData = data;\n            },\n            error: function (data, status, headers, config) {\n                if (data && data.message) {\n                    // Extract error-message\n                    $rootScope.addAlert(data.message, 'error');\n                } else {\n                    // Use default error-message\n                    $rootScope.addAlert($translate.instant('ALERT.GENERAL.HTTP-ERROR'), 'error');\n                }\n            },\n\n            sortObjects: [\n                {name: 'FORM-INSTANCES.SORT.SUBMITTED-DATE', id: 'submittedDate'}\n            ],\n\n            supportedProperties: [\n                {id: 'nameLike', name: 'FORM-INSTANCES.FILTER.NAME', showByDefault: true},\n                {id: 'tenantId', name: 'FORM-INSTANCES.FILTER.TENANTID', showByDefault: true}\n            ]\n        };\n\n        if ($rootScope.filters && $rootScope.filters.formInstanceFilter) {\n            // Reuse the existing filter\n            $scope.filter = $rootScope.filters.formInstanceFilter;\n            $scope.filter.config = filterConfig;\n        } else {\n            $scope.filter = new FlowableAdmin.Utils.Filter(filterConfig, $http, $timeout, $rootScope);\n            $rootScope.filters.formInstanceFilter = $scope.filter;\n        }\n\n        $scope.formSelected = function (form) {\n            if (form && form.getProperty('id')) {\n                $location.path('/form-instance/' + form.getProperty('id'));\n            }\n        };\n\n        $q.all([$translate('FORM-INSTANCES.HEADER.ID'),\n                $translate('FORM-INSTANCES.HEADER.TASK-ID'),\n                $translate('FORM-INSTANCES.HEADER.PROCESS-INSTANCE-ID'),\n                $translate('FORM-INSTANCES.HEADER.SUBMITTED-ON'),\n                $translate('FORM-INSTANCES.HEADER.SUBMITTED-BY'),\n                $translate('FORM-INSTANCES.HEADER.TENANT-ID')])\n            .then(function (headers) {\n                // Config for grid\n                $scope.gridFormInstances = {\n                    data: 'formInstancesData.data',\n                    enableRowReordering: true,\n                    multiSelect: false,\n                    keepLastSelected: false,\n                    rowHeight: 36,\n                    afterSelectionChange: $scope.formSelected,\n                    columnDefs: [\n                        {field: 'id', displayName: headers[0], cellTemplate: gridConstants.defaultTemplate},\n                        {field: 'taskId', displayName: headers[1], cellTemplate: gridConstants.defaultTemplate},\n                        {field: 'processInstanceId', displayName: headers[2], cellTemplate: gridConstants.defaultTemplate},\n                        {field: 'submittedDate', displayName: headers[3], cellTemplate: gridConstants.dateTemplate},\n                        {field: 'submittedBy', displayName: headers[4], cellTemplate: gridConstants.defaultTemplate},\n                        {field: 'tenantId', displayName: headers[5], cellTemplate: gridConstants.defaultTemplate}]\n                };\n            });\n\n        $scope.executeWhenReady(function () {\n            $scope.filter.refresh();\n        });\n\n    }]);\n"
  },
  {
    "path": "flowable-ui-web/admin/scripts/job-controllers.js",
    "content": "/* Copyright 2005-2015 Alfresco Software, Ltd.\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'use strict';\n\nflowableAdminApp.controller('JobController', ['$scope', '$rootScope', '$http', '$timeout','$location','$routeParams', '$modal', '$translate',\n    function ($scope, $rootScope, $http, $timeout, $location, $routeParams, $modal, $translate) {\n\t\t$rootScope.navigation = {main: 'process-engine', sub: 'jobs'};\n\t\t$scope.jobType = {\n\t\t\tparam: $routeParams.jobType\n\t\t}\n\t\t\n\t\t$scope.returnToList = function() {\n\t\t\t$location.path(\"/jobs\").search({jobType: $scope.jobType.param});\n\t\t};\n\n\t\t$scope.openDefinition = function(definitionId) {\n\t\t\tif (definitionId) {\n\t\t\t\t$location.path(\"/process-definition/\" + definitionId);\n\t\t\t}\n\t\t};\n\n\t\t$scope.executeJob = function() {\n\t\t\t$http({method: 'POST', url: FlowableAdmin.webContextRoot + '/app/rest/admin/jobs/' + $scope.job.id}).\n        \tsuccess(function(data, status, headers, config) {\n        \t  \t$scope.addAlert($translate.instant('ALERT.JOB.EXECUTED', $scope.job), 'info');\n        \t\t$scope.returnToList();\n        \t})\n        \t.error(function(data, status, headers, config) {\n        \t\t$scope.loadJob();\n        \t});\n\t\t};\n\t\t\n\t\t$scope.moveJob = function() {\n\t\t\t$http({method: 'POST', url: FlowableAdmin.webContextRoot + '/app/rest/admin/move-jobs/' + $scope.job.id + '?jobType=' + $scope.jobType.param}).\n        \tsuccess(function(data, status, headers, config) {\n        \t  \t$scope.addAlert($translate.instant('ALERT.JOB.MOVED', $scope.job), 'info');\n        \t\t$scope.returnToList();\n        \t})\n        \t.error(function(data, status, headers, config) {\n        \t\t$scope.loadJob();\n        \t});\n\t\t};\n\n\t\t$scope.deleteJob = function() {\n\t\t\tvar modalInstance = $modal.open({\n\t\t\t\ttemplateUrl: 'views/job-delete-popup.html',\n\t\t\t\tcontroller: 'DeleteJobModalInstanceCtrl',\n\t\t\t\tresolve: {\n\t\t\t\t\tjob: function() {\n\t\t\t\t\t\treturn $scope.job;\n\t\t\t\t\t},\n\t\t\t\t\tjobType: function() {\n\t\t\t\t\t\treturn $scope.jobType;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\n\t\t\tmodalInstance.result.then(function (deletejob) {\n\t\t\t\tif(deletejob) {\n\t\t\t\t\t$scope.addAlert($translate.instant('ALERT.JOB.DELETED', $scope.job), 'info');\n\t\t\t\t\t$scope.returnToList();\n\t\t\t\t}\n\t\t\t});\n\t\t};\n\n\t\t$scope.openProcessInstance = function(processInstanceId) {\n\t\t\tif (processInstanceId) {\n\t\t\t\t$location.path(\"/process-instance/\" + processInstanceId);\n\t\t\t}\n\t\t};\n\n\t\t$scope.openProcessDefinition = function(processDefinitionId) {\n\t\t\tif (processDefinitionId) {\n\t\t\t\t$location.path(\"/process-definition/\" + processDefinitionId);\n\t\t\t}\n\t\t};\n\n\t\t$scope.loadJob = function() {\n\t\t\t$scope.job = {};\n\t\t\t$http({method: 'GET', url: FlowableAdmin.webContextRoot + '/app/rest/admin/jobs/' + $routeParams.jobId + '?jobType=' + $scope.jobType.param}).\n\t    \tsuccess(function(data, status, headers, config) {\n\t            $scope.job = data;\n\n\t            if ($scope.job.exceptionMessage) {\n\t            \t// Fetch the full stacktrace, associated with this job\n\t            \t$http({method: 'GET', url: FlowableAdmin.webContextRoot + '/app/rest/admin/jobs/' + $scope.job.id + '/stacktrace?jobType=' + $scope.jobType.param}).\n\t            \tsuccess(function(data, status, headers, config) {\n\t    \t            $scope.job.exceptionStack = data;\n\t            \t});\n\t            }\n\t    \t}).\n\t    \terror(function(data, status, headers, config) {\n                if (data && data.message) {\n                    // Extract error-message\n                    $rootScope.addAlert(data.message, 'error');\n                } else {\n                    // Use default error-message\n                    $rootScope.addAlert($translate.instant('ALERT.GENERAL.HTTP-ERROR'), 'error');\n                }\n            });\n\t\t};\n\n\t\t// Load job\n\t\t$scope.executeWhenReady(function() {\n\t\t    $scope.loadJob();\n\t\t});\n\n}]);\n\nflowableAdminApp.controller('DeleteJobModalInstanceCtrl',\n    ['$rootScope', '$scope', '$modalInstance', '$http', 'job', 'jobType', function ($rootScope, $scope, $modalInstance, $http, job, jobType) {\n\n\t  $scope.job = job;\n\t  $scope.jobType = jobType;\n\t  $scope.status = {loading: false};\n\n\t  $scope.ok = function () {\n\t\t  $scope.status.loading = true;\n\t\t  $http({method: 'DELETE', url: FlowableAdmin.webContextRoot + '/app/rest/admin/jobs/' + $scope.job.id + '?jobType=' + jobType.param}).\n\t    \tsuccess(function(data, status, headers, config) {\n\t    \t\t$modalInstance.close(true);\n\t\t  \t\t$scope.status.loading = false;\n\t        }).\n\t        error(function(data, status, headers, config) {\n\t        \t$modalInstance.close(false);\n\t\t    \t$scope.status.loading = false;\n\t        });\n\t  };\n\n\t  $scope.cancel = function () {\n\t\tif(!$scope.status.loading) {\n\t\t\t$modalInstance.dismiss('cancel');\n\t\t}\n\t  };\n\t}]);\n"
  },
  {
    "path": "flowable-ui-web/admin/scripts/jobs-controllers.js",
    "content": "/* Copyright 2005-2015 Alfresco Software, Ltd.\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'use strict';\n\n/* Controllers */\n\nflowableAdminApp.controller('JobsController', ['$scope', '$rootScope', '$http', '$timeout','$location','$translate', '$q', 'gridConstants', '$routeParams',\n    function ($scope, $rootScope, $http, $timeout, $location, $translate, $q, gridConstants, $routeParams) {\n\t\t$rootScope.navigation = {main: 'process-engine', sub: 'jobs'};\n\t\t$scope.jobType = {\n\t\t\tparam: $routeParams.jobType\n\t\t}\n\t\t\n\t\t$scope.jobData = {};\n\t    $scope.selectedJobs = [];\n\n\t    var filterConfig = {\n\t\t    \turl: FlowableAdmin.webContextRoot + '/app/rest/admin/jobs',\n\t\t    \tmethod: 'GET',\n\t\t    \tsuccess: function(data, status, headers, config) {\n\t\t    \t\tif ($scope.definitionCacheLoaded) {\n\t                \t$scope.processQueryResponse(data);\n\t                \t\n\t                } else {\n\t\t                $rootScope.loadProcessDefinitionsCache().then(function(promise) {\n  \t\t        \t\t\t$rootScope.processDefinitionsCache = promise.data;\n  \t\t        \t\t\t$scope.definitionCacheLoaded = true;\n  \t\t        \t\t\t$scope.processQueryResponse(data);\n  \t\t        \t\t});\n\t                }\n\t            },\n\t            error: function(data, status, headers, config) {\n\t                if (data && data.message) {\n\t                    // Extract error-message\n\t                    $rootScope.addAlert(data.message, 'error');\n\t                } else {\n\t                    // Use default error-message\n\t                    $rootScope.addAlert($translate.instant('ALERT.GENERAL.HTTP-ERROR'), 'error');\n\t                }\n\t            },\n\t            \n\t            sortObjects: [\n\t                {name: 'JOBS.SORT.ID', id: 'id'},\n\t                {name: 'JOBS.SORT.DUE-DATE', id: 'dueDate'},\n\t                {name: 'JOBS.SORT.PROCESS-INSTANCE-ID', id: 'processInstanceId'}\n\t            ],\n\t            \n\t            supportedProperties: [\n\t                {id: 'processInstanceId', name: 'JOBS.FILTER.PROCESS-INSTANCE-ID'},\n\t                {id: 'tenantIdLike', name: 'JOBS.FILTER.TENANT-ID'},\n\t                {id: 'dueBefore', name: 'JOBS.FILTER.DUE-BEFORE', showByDefault: true},\n\t                {id: 'dueAfter', name: 'JOBS.FILTER.DUE-AFTER', showByDefault: true},\n\t                {id: 'withException', name: 'JOBS.FILTER.EXCEPTION'}\n\t            ]\n\t\t    };\n\n    \t\t\n\t    if ($rootScope.filters.forced.jobFilter) {\n\t    \t// Always recreate the filter and add all properties\n\t    \t$scope.filter = new FlowableAdmin.Utils.Filter(filterConfig, $http, $timeout, $rootScope);\n    \t\t$rootScope.filters.jobFilter = $scope.filter;\n    \t\t\n    \t\tfor (var prop in $rootScope.filters.forced.jobFilter) {\n    \t\t\t$scope.filter.addProperty({id: prop}, $rootScope.filters.forced.jobFilter[prop]);\n    \t\t}\n    \t\t\n    \t\t$rootScope.filters.forced.jobFilter = undefined;\n    \t\t\n\t    } else {\n\t    \tif ($rootScope.filters && $rootScope.filters.jobFilter) {\n\t    \t\t// Reuse the existing filter\n\t    \t\t$scope.filter = $rootScope.filters.jobFilter;\n\t    \t\t$scope.filter.config = filterConfig;\n\t    \t} else {\n\t    \t\t$scope.filter = new FlowableAdmin.Utils.Filter(filterConfig, $http, $timeout, $rootScope);\n\t    \t\t$rootScope.filters.jobFilter = $scope.filter;\n\t    \t}\n\t    }\n\t    \n\t    if ($scope.jobType.param) {\n\t    \t$scope.filter.jobType = $scope.jobType.param;\n\t    }\n\t    \n\t    if (!$scope.filter.jobType) {\n\t    \t$scope.filter.jobType = 'executableJob';\n\t    }\n\t    \n\t    $scope.filter.properties.jobType = $scope.filter.jobType;\n\t    \n\t    $scope.jobSelected = function(job) {\n\t    \tif (job && job.getProperty('id')) {\n\t    \t\t$location.path('/job/' + job.getProperty('id')).search({jobType: $scope.filter.jobType});\n\t    \t}\n\t    };\n\t    \n\t    $q.all([$translate('JOBS.HEADER.ID'), \n\t            $translate('JOBS.HEADER.DUE-DATE'),\n\t            $translate('JOBS.HEADER.PROCESS-DEFINITION'),\n\t            $translate('JOBS.HEADER.RETRIES'),\n\t            $translate('JOBS.HEADER.EXCEPTION')])\n\t    .then(function(headers) { \n\n          // Config for grid\n          $scope.gridJobs = {\n              data: 'jobData.data',\n              enableRowReordering: true,\n              multiSelect: false,\n              keepLastSelected : false,\n              enableSorting: false,\n              rowHeight: 36,\n              afterSelectionChange: $scope.jobSelected,\n              columnDefs: [\n                  { field: 'id', displayName: headers[0], width: 50, cellTemplate: gridConstants.defaultTemplate},\n                  { field: 'dueDate', displayName: headers[1], cellTemplate: gridConstants.dateTemplate},\n                  { field: 'processDefinition.name', displayName: headers[2], cellTemplate: gridConstants.defaultTemplate},\n                  { field: 'retries', displayName: headers[3], width: 50, cellTemplate: gridConstants.defaultTemplate},\n                  { field: 'exceptionMessage', displayName: headers[4], width: 150, cellTemplate: gridConstants.defaultTemplate}\n              ]\n          };\n\t    });\n        \n        $scope.processQueryResponse = function(jobsResponse) {\n        \tfor (var i = 0; i < jobsResponse.data.length; i++) {\n        \t\tjobsResponse.data[i].processDefinition = \n            \t\t$rootScope.getProcessDefinitionFromCache(jobsResponse.data[i].processDefinitionId);\n            \t\n            }\n        \t$scope.jobData = jobsResponse;\n        };\n        \n        $scope.jobTypeFilterChanged = function()  {\n        \t$scope.filter.properties.jobType = $scope.filter.jobType;\n        \t$scope.filter.refresh();\n        };\n        \n        $scope.processDefinitionFilterChanged = function()  {\n        \tif ($scope.filter.processDefinition && $scope.filter.processDefinition !== '-1') {\n        \t\t$scope.filter.properties.processDefinitionId = $scope.filter.processDefinition;\n        \t\t$scope.filter.refresh();\n        \t\t\n        \t} else {\n        \t\tvar tempProcessDefinitionId = $scope.filter.properties.processDefinitionId;\n        \t\t$scope.filter.properties.processDefinitionId = null;\n        \t\tif (tempProcessDefinitionId && tempProcessDefinitionId.length > 0) {\n        \t\t\t$scope.filter.refresh();\n        \t\t}\n        \t}\n        };\n        \n        $scope.executeWhenReady(function() {\n          \t$scope.filter.refresh();\n        });\n    }]);\n"
  },
  {
    "path": "flowable-ui-web/admin/scripts/process-definition-controllers.js",
    "content": "/* Copyright 2005-2015 Alfresco Software, Ltd.\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'use strict';\n\nflowableAdminApp.controller('ProcessDefinitionController', ['$scope', '$rootScope', '$http', '$timeout','$location','$routeParams', '$modal', '$translate', '$q', 'gridConstants',\n    function ($scope, $rootScope, $http, $timeout, $location, $routeParams, $modal, $translate, $q, gridConstants) {\n\n        $rootScope.navigation = {main: 'process-engine', sub: 'definitions'};\n\n        $scope.tabData = {\n\t\t    tabs: [\n\t\t       {id: 'processInstances', name: 'PROCESS-DEFINITION.TITLE.PROCESS-INSTANCES'},\n\t\t       {id: 'jobs', name: 'PROCESS-DEFINITION.TITLE.JOBS'}\n\t\t    ]\n\t\t};\n\t\t$scope.tabData.activeTab = $scope.tabData.tabs[0].id;\n\n\t\t$scope.returnToList = function() {\n\t\t\t$location.path(\"/process-definitions\");\n\t\t};\n\n\t\t$scope.openDefinition = function(definitionId) {\n\t\t\tif (definitionId) {\n\t\t\t\t$location.path(\"/process-definition/\" + definitionId);\n\t\t\t}\n\t\t};\n\n\n\t\t$scope.openDeployment = function(deploymentId) {\n\t\t    if (deploymentId) {\n\t\t        $location.path(\"/deployment/\" + deploymentId);\n\t\t    }\n\t\t};\n\n    $scope.editCategory = function() {\n      var modalInstance = $modal.open({\n        templateUrl: 'views/process-definition-edit-category-popup.html',\n        controller: 'EditProcessDefinitionCategoryModalCtrl',\n        resolve: {\n          definition: function() {\n            return $scope.definition;\n          }\n        }\n      });\n\n      modalInstance.result.then(function (data) {\n        if(data) {\n          $scope.addAlert($translate.instant('ALERT.PROCESS-DEFINITION.CATEGORY-UPDATED', $scope.definition), 'info');\n          $scope.definition = data;\n        }\n      });\n    };\n\n    $scope.showProcessDiagram = function() {\n      $modal.open({\n        templateUrl: 'views/process-definition-diagram-popup.html',\n        windowClass: 'modal modal-full-width',\n        controller: 'ShowProcessDefinitionDiagramPopupCtrl',\n        resolve: {\n          definition: function() {\n            return $scope.definition;\n          }\n        }\n      });\n    };\n\n    $scope.openJob = function(job) {\n      if (job && job.getProperty('id')) {\n        $location.path(\"/job/\" + job.getProperty('id'));\n      }\n    };\n\n    $scope.openProcessInstance = function(instance) {\n      if (instance && instance.getProperty('id')) {\n        $location.path(\"/process-instance/\" + instance.getProperty('id'));\n      }\n    };\n    \n    $scope.openStartForm = function () {\n        if ($scope.startForm) {\n            $location.path(\"/form/\" + $scope.startForm.id);\n        }\n    };\n    \n    $scope.openFormDefinition = function (form) {\n        if (form && form.getProperty('id')) {\n            $location.path(\"/form-definition/\" + form.getProperty('id'));\n          }\n    };\n    \n    $scope.openDecisionTable = function (decisionTable) {\n        if (decisionTable && decisionTable.getProperty('id')) {\n            $location.path(\"/decision-table/\" + decisionTable.getProperty('id'));\n          }\n    };\n\n    $scope.showAllJobs = function() {\n      // Populate the job-filter with process definition id\n      $rootScope.filters.forced.jobFilter = {\n        processDefinitionId: $scope.definition.id\n      };\n      $location.path(\"/jobs\");\n    };\n\n    $scope.showAllProcesses = function() {\n      // Populate the process-filter with parentId\n      $rootScope.filters.forced.instanceFilter = {\n          processDefinitionId: $scope.definition.id\n      };\n      $location.path(\"/process-instances\");\n    };\n\n    $scope.loadProcessInstances = function() {\n      $scope.processInstances = undefined;\n      $http({method: 'GET', url: FlowableAdmin.webContextRoot + '/app/rest/admin/process-definitions/' + $scope.definition.id +'/process-instances'}).\n      success(function(data, status, headers, config) {\n        $scope.processInstances = data;\n        $scope.tabData.tabs[0].info = data.total;\n      });\n    };\n\n        $scope.loadJobs = function() {\n            $scope.jobs = undefined;\n            $http({method: 'GET', url: FlowableAdmin.webContextRoot + '/app/rest/admin/process-definitions/' + $scope.definition.id +'/jobs'}).\n            success(function(data, status, headers, config) {\n                $scope.jobs = data;\n                $scope.tabData.tabs[1].info = data.total;\n            });\n        };\n        \n        $scope.loadDecisionTables = function() {\n            // Load decision tables\n            $http({method: 'GET', url: FlowableAdmin.webContextRoot + '/app/rest/admin/process-definition-decision-tables/' + $scope.definition.id}).\n            success(function(data, status, headers, config) {\n                $scope.decisionTables = data;\n                $scope.tabData.tabs[2].info = data.length;\n            }).\n            error(function(data, status, headers, config) {\n            });\n        };\n        \n        $scope.loadFormDefinitions = function() {\n            // Load forms\n            $http({method: 'GET', url: FlowableAdmin.webContextRoot + '/app/rest/admin/process-definition-form-definitions/' + $scope.definition.id}).\n            success(function(data, status, headers, config) {\n                $scope.formDefinitions = data;\n                $scope.tabData.tabs[3].info = data.length;\n            }).\n            error(function(data, status, headers, config) {\n            });\n        };\n\n\t\t$scope.executeWhenReady(function() {\n\t\t    // Load definition\n\t\t    $http({method: 'GET', url: FlowableAdmin.webContextRoot + '/app/rest/admin/process-definitions/' + $routeParams.definitionId}).\n\t\t    success(function(data, status, headers, config) {\n\t\t        $scope.definition = data;\n\t\t        $scope.loadProcessInstances();\n\t\t        $scope.loadJobs();\n                $scope.tabData.tabs.push({id: 'decisionTables', name: 'PROCESS-DEFINITION.TITLE.DECISION-TABLES'});\n                $scope.tabData.tabs.push({id: 'forms', name: 'PROCESS-DEFINITION.TITLE.FORMS'});\n                \n                $scope.loadDecisionTables();\n                $scope.loadFormDefinitions();\n\t\t    }).\n\t\t    error(function(data, status, headers, config) {\n\t\t        if (data && data.message) {\n                    // Extract error-message\n                    $rootScope.addAlert(data.message, 'error');\n                } else {\n                    // Use default error-message\n                    $rootScope.addAlert($translate.instant('ALERT.GENERAL.HTTP-ERROR'), 'error');\n                }\n\t\t    });\n\n\n\t\t    $q.all([$translate('PROCESS-INSTANCES.HEADER.ID'),\n                  $translate('PROCESS-INSTANCES.HEADER.NAME'),\n                  $translate('PROCESS-INSTANCES.HEADER.STATUS'),\n                  $translate('PROCESS-INSTANCES.HEADER.CREATE-TIME')])\n            .then(function(headers) {\n                var stateTemplate = '<div><div class=\"ngCellText\">{{row.getProperty(\"endTime\") && \"Completed\" || \"Active\"}}</div></div>';\n                var dateTemplate = '<div><div class=\"ngCellText\" title=\"{{row.getProperty(col.field) | dateformat:\\'full\\'}}\">{{row.getProperty(col.field) | dateformat}}</div></div>';\n    \n                // Config for variable grid\n                $scope.gridProcessInstances = {\n                    data: 'processInstances.data',\n                    enableRowReordering: false,\n                    multiSelect: false,\n                    keepLastSelected : false,\n                    enableSorting: false,\n                    rowHeight: 36,\n                    afterSelectionChange: $scope.openProcessInstance,\n                    columnDefs: [\n                        { field: 'id', displayName: headers[0], width: 75},\n                        { field: 'name', displayName: headers[1]},\n                        { field: 'endTime', displayName: headers[2], cellTemplate: stateTemplate},\n                        { field: 'startTime', displayName: headers[3], cellTemplate: dateTemplate}\n                    ]\n                };\n            });\n\n\t\t    $q.all([$translate('JOBS.HEADER.ID'),\n                  $translate('JOBS.HEADER.DUE-DATE'),\n                  $translate('JOBS.HEADER.RETRIES'),\n                  $translate('JOBS.HEADER.EXCEPTION')])\n            .then(function(headers) {\n                var dateTemplate = '<div><div class=\"ngCellText\" title=\"{{row.getProperty(col.field) | dateformat:\\'full\\'}}\">{{row.getProperty(col.field) | dateformat}}</div></div>';\n    \n                // Config for variable grid\n                $scope.gridJobs = {\n                    data: 'jobs.data',\n                    enableRowReordering: false,\n                    multiSelect: false,\n                    keepLastSelected : false,\n                    enableSorting: false,\n                    rowHeight: 36,\n                    afterSelectionChange: $scope.openJob,\n                    columnDefs: [\n                        { field: 'id', displayName: headers[0], width: 50},\n                        { field: 'dueDate', displayName: headers[1], cellTemplate: dateTemplate},\n                        { field: 'retries', displayName: headers[2]},\n                        { field: 'exceptionMessage', displayName: headers[3]}\n                    ]\n                };\n            });\n\t\t    \n\t\t    $q.all([$translate('DECISION-TABLES.HEADER.ID'),\n\t                $translate('DECISION-TABLES.HEADER.NAME'),\n\t                $translate('DECISION-TABLES.HEADER.KEY'),\n\t                $translate('DECISION-TABLES.HEADER.VERSION'),\n\t                $translate('DECISION-TABLES.HEADER.TENANT-ID')])\n\t            .then(function (headers) {\n\t                // Config for grid\n\t                $scope.gridDecisionTables = {\n\t                    data: 'decisionTables',\n\t                    enableRowReordering: true,\n\t                    multiSelect: false,\n\t                    keepLastSelected: false,\n\t                    rowHeight: 36,\n\t                    afterSelectionChange: $scope.openDecisionTable,\n\t                    columnDefs: [\n\t                        {field: 'id', displayName: headers[0], cellTemplate: gridConstants.defaultTemplate},\n\t                        {field: 'name', displayName: headers[1], cellTemplate: gridConstants.defaultTemplate},\n\t                        {field: 'key', displayName: headers[2], cellTemplate: gridConstants.defaultTemplate},\n\t                        {field: 'version', displayName: headers[3], cellTemplate: gridConstants.defaultTemplate},\n\t                        {field: 'tenantId', displayName: headers[4], cellTemplate: gridConstants.defaultTemplate}]\n\t                };\n\t            });\n\t\t    \n\t\t    $q.all([$translate('FORM-DEFINITIONS.HEADER.ID'),\n\t                $translate('FORM-DEFINITIONS.HEADER.NAME'),\n\t                $translate('FORM-DEFINITIONS.HEADER.DEPLOYMENTID'),\n\t                $translate('FORM-DEFINITIONS.HEADER.TENANTID')])\n\t            .then(function (headers) {\n\t                // Config for grid\n\t                $scope.gridFormDefinitions = {\n\t                    data: 'formDefinitions',\n\t                    enableRowReordering: true,\n\t                    multiSelect: false,\n\t                    keepLastSelected: false,\n\t                    rowHeight: 36,\n\t                    afterSelectionChange: $scope.openFormDefinition,\n\t                    columnDefs: [\n\t                        {field: 'id', displayName: headers[0], cellTemplate: gridConstants.defaultTemplate},\n\t                        {field: 'name', displayName: headers[1], cellTemplate: gridConstants.defaultTemplate},\n\t                        {field: 'deploymentId', displayName: headers[2], cellTemplate: gridConstants.defaultTemplate},\n\t                        {field: 'tenantId', displayName: headers[3], cellTemplate: gridConstants.defaultTemplate}]\n\t                };\n\t            });\n\t\t      \n\t\t});\n\n}]);\n\nflowableAdminApp.controller('EditProcessDefinitionCategoryModalCtrl',\n    ['$rootScope', '$scope', '$modalInstance', '$http', 'definition', function ($rootScope, $scope, $modalInstance, $http, definition) {\n\n  $scope.model = {\n      id: definition.id,\n      category: definition.category,\n      name: definition.name,\n      key: definition.key,\n  };\n\n  $scope.status = {loading: false};\n\n\n  $scope.ok = function () {\n    $scope.status.loading = true;\n\n    var data = {\n        category: $scope.model.category\n    };\n\n    $http({method: 'PUT', url: FlowableAdmin.webContextRoot + '/app/rest/admin/process-definitions/' + $scope.model.id, data: data}).\n      success(function(data, status, headers, config) {\n        $modalInstance.close(data);\n        $scope.status.loading = false;\n      }).\n      error(function(data, status, headers, config) {\n        $modalInstance.close(false);\n       $scope.status.loading = false;\n      });\n  };\n\n  $scope.cancel = function () {\n  if(!$scope.status.loading) {\n    $modalInstance.dismiss('cancel');\n  }\n  };\n}]);\n\nflowableAdminApp.controller('ShowProcessDefinitionDiagramPopupCtrl',\n    ['$rootScope', '$scope', '$modalInstance', '$http', 'definition', '$timeout', function ($rootScope, $scope, $modalInstance, $http, definition, $timeout) {\n\n  $scope.model = {\n      id: definition.id,\n      name: definition.name\n  };\n\n  $scope.status = {loading: false};\n\n  $scope.cancel = function () {\n    if(!$scope.status.loading) {\n      $modalInstance.dismiss('cancel');\n    }\n  };\n\n  $timeout(function() {\n    $(\"#bpmnModel\").attr(\"data-definition-id\", definition.id);\n    $(\"#bpmnModel\").attr(\"data-server-id\", $rootScope.activeServers['process']);\n    $(\"#bpmnModel\").load(\"./display/displaymodel.html?definitionId=\" + definition.id);\n  }, 200);\n\n\n}]);\n"
  },
  {
    "path": "flowable-ui-web/admin/scripts/process-definitions-controllers.js",
    "content": "/* Copyright 2005-2015 Alfresco Software, Ltd.\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'use strict';\n\n/* Controllers */\n\nflowableAdminApp.controller('ProcessDefinitionsController', ['$rootScope', '$scope', '$http', '$timeout', '$location','$translate', '$q', '$modal', 'gridConstants',\n    function ($rootScope, $scope, $http, $timeout, $location, $translate, $q, $modal, gridConstants) {\n\n\t\t$rootScope.navigation = {main: 'process-engine', sub: 'definitions'};\n        \n\t\t$scope.filter = {};\n\t\t$scope.processDefinitionsData = {};\n\n\t\t// Array to contain selected properties (yes - we only can select one, but ng-grid isn't smart enough)\n\t    $scope.selectedDefinitions = [];\n\n\t    var filterConfig = {\n\t    \turl: FlowableAdmin.webContextRoot + '/app/rest/admin/process-definitions',\n\t    \tmethod: 'GET',\n\t    \tsuccess: function(data, status, headers, config) {\n\t    \t\t$scope.processDefinitionsData = data;\n            },\n            error: function(data, status, headers, config) {\n                if (data && data.message) {\n                    // Extract error-message\n                    $rootScope.addAlert(data.message, 'error');\n                } else {\n                    // Use default error-message\n                    $rootScope.addAlert($translate.instant('ALERT.GENERAL.HTTP-ERROR'), 'error');\n                }\n            },\n\n            sortObjects: [\n                {name: 'PROCESS-DEFINITIONS.SORT.ID', id: 'id'},\n                {name: 'PROCESS-DEFINITIONS.SORT.NAME', id: 'name'},\n                {name: 'PROCESS-DEFINITIONS.SORT.VERSION', id: 'version'}\n            ],\n\n            supportedProperties: [\n                {id: 'nameLike', name: 'PROCESS-DEFINITIONS.FILTER.NAME', showByDefault: false},\n                {id: 'keyLike', name: 'PROCESS-DEFINITIONS.FILTER.KEY', showByDefault: true},\n                {id: 'deploymentId', name: 'PROCESS-DEFINITIONS.FILTER.DEPLOYMENT-ID', showByDefault: false},\n                {id: 'tenantIdLike', name: 'PROCESS-DEFINITIONS.FILTER.TENANT-ID', showByDefault: false},\n                {id: 'latest', name: 'PROCESS-DEFINITIONS.FILTER.LATEST', showByDefault: true, defaultValue: true}\n            ]\n\t    };\n\n\t    if ($rootScope.filters.forced.processDefinitionFilter) {\n\t        // Always recreate the filter and add all properties\n\t        $scope.filter = new FlowableAdmin.Utils.Filter(filterConfig, $http, $timeout, $rootScope);\n\t        $rootScope.filters.processDefinitionFilter = $scope.filter;\n\n\t        for (var prop in $rootScope.filters.forced.processDefinitionFilter) {\n\t            $scope.filter.addProperty({id: prop}, $rootScope.filters.forced.processDefinitionFilter[prop]);\n\t            if (prop == 'deploymentId') {\n\t                $scope.filter.removeProperty({id: 'latest'});\n\t            }\n\t        }\n\n\t        $rootScope.filters.forced.processDefinitionFilter = undefined;\n\n\t    } else if ($rootScope.filters && $rootScope.filters.processDefinitionFilter) {\n\t    \t// Reuse the existing filter\n\t    \t$scope.filter = $rootScope.filters.processDefinitionFilter;\n\t    \t$scope.filter.config = filterConfig;\n\t    } else {\n\t\t    $scope.filter = new FlowableAdmin.Utils.Filter(filterConfig, $http, $timeout, $rootScope);\n\t\t    $rootScope.filters.processDefinitionFilter = $scope.filter;\n\t    }\n\n\t    $scope.definitionSelected = function(definition) {\n\t    \tif (definition && definition.getProperty('id')) {\n\t    \t\t$location.path('/process-definition/' + definition.getProperty('id'));\n\t    \t}\n\t    };\n\n\t    $scope.toggleLatestVersion = function() {\n\t      if($scope.filter.properties.latest === true) {\n\t        $scope.filter.properties.nameLike = undefined;\n\t        $scope.filter.properties.deploymentId = undefined;\n\t      }\n\n\t      $scope.filter.refresh();\n\t    };\n\n\t    $q.all([$translate('PROCESS-DEFINITIONS.HEADER.ID'),\n              $translate('PROCESS-DEFINITIONS.HEADER.NAME'),\n              $translate('PROCESS-DEFINITIONS.HEADER.VERSION'),\n              $translate('PROCESS-DEFINITIONS.HEADER.KEY'),\n              $translate('PROCESS-DEFINITIONS.HEADER.TENANT')])\n              .then(function(headers) {\n\n          // Config for grid\n          $scope.gridDefinitions = {\n              data: 'processDefinitionsData.data',\n              enableRowReordering: true,\n              multiSelect: false,\n              keepLastSelected : false,\n              rowHeight: 36,\n              selectedItems: $scope.selectedDefinitions,\n              afterSelectionChange: $scope.definitionSelected,\n              columnDefs: [\n                  { field: 'id', displayName: headers[0], cellTemplate: gridConstants.defaultTemplate},\n                  { field: 'name', displayName: headers[1], cellTemplate: gridConstants.defaultTemplate},\n                  { field: 'version', displayName: headers[2], cellTemplate: gridConstants.defaultTemplate},\n                  { field: 'key', displayName: headers[3], cellTemplate: gridConstants.defaultTemplate},\n                  { field: 'tenantId', displayName: headers[4], cellTemplate: gridConstants.defaultTemplate}]\n          };\n       });\n\n\n\t   // Hook in initial fetching of the definitions\n\t   $scope.executeWhenReady(function() {\n\t       $scope.filter.refresh();\n\t   });\n        \n\n    }]);\n"
  },
  {
    "path": "flowable-ui-web/admin/scripts/process-instance-controllers.js",
    "content": "/* Copyright 2005-2015 Alfresco Software, Ltd.\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'use strict';\n\nflowableAdminApp.controller('ProcessInstanceController', ['$scope', '$rootScope', '$http', '$timeout', '$location', '$routeParams', '$modal', '$translate', '$q', 'gridConstants',\n    function ($scope, $rootScope, $http, $timeout, $location, $routeParams, $modal, $translate, $q, gridConstants) {\n\n        $rootScope.navigation = {main: 'process-engine', sub: 'instances'};\n\n        $scope.tabData = {\n            tabs: [\n                {id: 'tasks', name: 'PROCESS-INSTANCE.TITLE.TASKS'},\n                {id: 'variables', name: 'PROCESS-INSTANCE.TITLE.VARIABLES'},\n                {id: 'subProcesses', name: 'PROCESS-INSTANCE.TITLE.SUBPROCESSES'},\n                {id: 'jobs', name: 'PROCESS-INSTANCE.TITLE.JOBS'}\n            ]\n        };\n\n        $scope.tabData.activeTab = $scope.tabData.tabs[0].id;\n\n        $scope.returnToList = function () {\n            $location.path(\"/process-instances\");\n        };\n\n        $scope.openTask = function (task) {\n            if (task && task.getProperty('id')) {\n                $location.path(\"/task/\" + task.getProperty('id'));\n            }\n        };\n\n        $scope.openJob = function (job) {\n            if (job && job.getProperty('id')) {\n                $location.path(\"/job/\" + job.getProperty('id'));\n            }\n        };\n\n        $scope.openProcessInstance = function (instance) {\n            if (instance) {\n                var id;\n                if (instance.getProperty !== undefined) {\n                    id = instance.getProperty('id');\n                } else {\n                    id = instance;\n                }\n                $location.path(\"/process-instance/\" + id);\n            }\n        };\n\n        $scope.showAllTasks = function () {\n            // Populate the task-filter with parentId\n            $rootScope.filters.forced.taskFilter = {\n                processInstanceId: $scope.process.id\n            };\n            $location.path(\"/tasks\");\n        };\n\n        $scope.showAllSubprocesses = function () {\n            // Populate the process-filter with parentId\n            $rootScope.filters.forced.instanceFilter = {\n                superProcessInstanceId: $scope.process.id\n            };\n            $scope.returnToList();\n        };\n\n        $scope.openProcessDefinition = function (processDefinitionId) {\n            if (processDefinitionId) {\n                $location.path(\"/process-definition/\" + processDefinitionId);\n            }\n        };\n\n        $scope.showProcessDiagram = function () {\n            $modal.open({\n                templateUrl: 'views/process-instance-diagram-popup.html',\n                windowClass: 'modal modal-full-width',\n                controller: 'ShowProcessInstanceDiagramPopupCtrl',\n                resolve: {\n                    process: function () {\n                        return $scope.process;\n                    }\n                }\n            });\n        };\n        \n        $scope.showMigrateProcessDialog = function () {\n            $scope.migrationScope = {\n                targetProcessDefinition: undefined\n            };\n            var modalInstance = $modal.open({\n                templateUrl: 'views/process-instance-migration-popup.html', \n                controller: 'ShowProcessInstanceMigrationPopupCtrl',\n                resolve: {\n                    process: function () {\n                        return $scope.process;\n                    },\n                    processDefinition: function() {\n                        return $scope.definition;\n                    },\n                    migrationScope: function() {\n                        return $scope.migrationScope;\n                    }\n                }\n            });\n            \n            modalInstance.result.then(function (migrateProcessInstance) {\n                if (migrateProcessInstance) {\n                    var migrationModalInstance = $modal.open({\n                        templateUrl: 'views/process-instance-migration-diagram-popup.html',\n                        windowClass: 'modal modal-full-width',\n                        controller: 'ShowProcessInstanceMigrationDiagramPopupCtrl',\n                        resolve: {\n                            process: function () {\n                                return $scope.process;\n                            },\n                            migrationScope: function () {\n                                return $scope.migrationScope;\n                            }\n                        }\n                    });\n                    \n                    migrationModalInstance.result.then(function (result) {\n                        $scope.loadProcessInstance();\n                    });\n                }\n            });\n        };\n\n        $scope.openDecisionTable = function (decisionTable) {\n            if (decisionTable && decisionTable.getProperty('id')) {\n                $location.path(\"/decision-table-execution/\" + decisionTable.getProperty('id'));\n            }\n        };\n\n        $scope.openFormInstance = function (submittedForm) {\n            if (submittedForm && submittedForm.getProperty('id')) {\n                $location.path(\"/form-instance/\" + submittedForm.getProperty('id'));\n            }\n        };\n\n        $scope.loadProcessDefinition = function () {\n            // Load definition\n            $http({\n                method: 'GET',\n                url: FlowableAdmin.webContextRoot + '/app/rest/admin/process-definitions/' + $scope.process.processDefinitionId\n            }).success(function (data, status, headers, config) {\n                $scope.definition = data;\n            }).error(function (data, status, headers, config) {\n            });\n        };\n\n        $scope.loadProcessInstance = function () {\n            $scope.process = undefined;\n            // Load process\n            $http({\n                method: 'GET',\n                url: FlowableAdmin.webContextRoot + '/app/rest/admin/process-instances/' + $routeParams.processInstanceId\n            }).success(function (data, status, headers, config) {\n                $scope.process = data;\n\n                if (data) {\n                    $scope.processCompleted = data.endTime != undefined;\n                }\n\n                // Start loading children\n                $scope.loadProcessDefinition();\n                $scope.loadTasks();\n                $scope.loadVariables();\n                $scope.loadSubProcesses();\n                $scope.loadJobs();\n                $scope.loadDecisionTables()\n\n                var extraTabsAlreadyPresent = false;\n                for (var i = 0; i < $scope.tabData.tabs.length; i++) {\n                    if ($scope.tabData.tabs[i].id == 'decisionTables') {\n                        extraTabsAlreadyPresent = true;\n                        break;\n                    }\n                }\n                \n                if (!extraTabsAlreadyPresent) {\n                    $scope.tabData.tabs.push({id: 'decisionTables', name: 'PROCESS-INSTANCE.TITLE.DECISION-TABLES'});\n                    $scope.tabData.tabs.push({id: 'forms', name: 'PROCESS-INSTANCE.TITLE.FORM-INSTANCES'});\n                }\n                \n                //TODO: implement when decision task runtime data is stored\n                // $scope.loadDecisionTables();\n                $scope.loadFormInstances();\n            }).error(function (data, status, headers, config) {\n                if (data && data.message) {\n                    // Extract error-message\n                    $rootScope.addAlert(data.message, 'error');\n                } else {\n                    // Use default error-message\n                    $rootScope.addAlert($translate.instant('ALERT.GENERAL.HTTP-ERROR'), 'error');\n                }\n            });\n        };\n\n        var dateTemplate = '<div><div class=\"ngCellText\" title=\"{{row.getProperty(col.field) | dateformat:\\'full\\'}}\">{{row.getProperty(col.field) | dateformat}}</div></div>';\n\n        // Config for subtasks grid\n        $q.all([$translate('TASKS.HEADER.ID'),\n            $translate('TASKS.HEADER.NAME'),\n            $translate('TASKS.HEADER.ASSIGNEE'),\n            $translate('TASKS.HEADER.OWNER'),\n            $translate('TASKS.HEADER.CREATE-TIME'),\n            $translate('TASKS.HEADER.END-TIME')])\n            .then(function (headers) {\n                $scope.gridTasks = {\n                    data: 'tasks.data',\n                    enableRowReordering: false,\n                    multiSelect: false,\n                    keepLastSelected: false,\n                    enableSorting: false,\n                    rowHeight: 36,\n                    afterSelectionChange: $scope.openTask,\n                    columnDefs: [\n                        {field: 'id', displayName: headers[0], width: 50},\n                        {field: 'name', displayName: headers[1]},\n                        {field: 'assignee', displayName: headers[2], cellTemplate: gridConstants.defaultTemplate},\n                        {field: 'owner', displayName: headers[3], cellTemplate: gridConstants.defaultTemplate},\n                        {field: 'startTime', displayName: headers[4], cellTemplate: dateTemplate},\n                        {field: 'endTime', displayName: headers[5], cellTemplate: dateTemplate}\n                    ]\n                };\n            });\n\n        $q.all([$translate('VARIABLES.HEADER.NAME'),\n            $translate('VARIABLES.HEADER.TYPE'),\n            $translate('VARIABLES.HEADER.VALUE')])\n            .then(function (headers) {\n                var variableValueTemplate = '<div><div class=\"ngCellText\">{{row.getProperty(\"variable.valueUrl\") && \"(Binary)\" || row.getProperty(col.field)}}</div></div>';\n                var variableTypeTemplate = '<div><div class=\"ngCellText\">{{row.getProperty(col.field) && row.getProperty(col.field) || \"null\"}}</div></div>';\n\n                $scope.selectedVariables = [];\n\n                // Config for variable grid\n                $scope.gridVariables = {\n                    data: 'variables.data',\n                    enableRowReordering: false,\n                    multiSelect: false,\n                    keepLastSelected: false,\n                    enableSorting: false,\n                    rowHeight: 36,\n                    selectedItems: $scope.selectedVariables,\n                    columnDefs: [\n                        {field: 'variable.name', displayName: headers[0]},\n                        {field: 'variable.type', displayName: headers[1], cellTemplate: variableTypeTemplate},\n                        {field: 'variable.value', displayName: headers[2], cellTemplate: variableValueTemplate}\n                    ]\n                };\n            });\n        $q.all([$translate('PROCESS-INSTANCES.HEADER.ID'),\n            $translate('PROCESS-INSTANCES.HEADER.NAME'),\n            $translate('PROCESS-INSTANCES.HEADER.PROCESS-DEFINITION'),\n            $translate('PROCESS-INSTANCES.HEADER.STATUS')])\n            .then(function (headers) {\n                var subprocessStateTemplate = '<div><div class=\"ngCellText\">{{row.getProperty(\"endTime\") && \"Completed\" || \"Active\"}}</div></div>';\n                // Config for variable grid\n                $scope.gridSubprocesses = {\n                    data: 'subprocesses.data',\n                    enableRowReordering: false,\n                    multiSelect: false,\n                    keepLastSelected: false,\n                    enableSorting: false,\n                    rowHeight: 36,\n                    afterSelectionChange: $scope.openProcessInstance,\n                    columnDefs: [\n                        {field: 'id', displayName: headers[0]},\n                        {field: 'name', displayName: headers[1]},\n                        {field: 'processDefinitionId', displayName: headers[2]},\n                        {field: 'endTime', displayName: headers[3], cellTemplate: subprocessStateTemplate}\n                    ]\n                };\n            });\n\n        $q.all([$translate('JOBS.HEADER.ID'),\n            $translate('JOBS.HEADER.DUE-DATE'),\n            $translate('JOBS.HEADER.RETRIES'),\n            $translate('JOBS.HEADER.EXCEPTION')])\n            .then(function (headers) {\n                var dateTemplate = '<div><div class=\"ngCellText\" title=\"{{row.getProperty(col.field) | dateformat:\\'full\\'}}\">{{row.getProperty(col.field) | dateformat}}</div></div>';\n\n                // Config for variable grid\n                $scope.gridJobs = {\n                    data: 'jobs.data',\n                    enableRowReordering: false,\n                    multiSelect: false,\n                    keepLastSelected: false,\n                    enableSorting: false,\n                    rowHeight: 36,\n                    afterSelectionChange: $scope.openJob,\n                    columnDefs: [\n                        {field: 'id', displayName: headers[0], width: 50},\n                        {field: 'dueDate', displayName: headers[1], cellTemplate: dateTemplate},\n                        {field: 'retries', displayName: headers[2]},\n                        {field: 'exceptionMessage', displayName: headers[3]}\n                    ]\n                };\n            });\n\n        $q.all([$translate('DECISION-TABLE-EXECUTION.HEADER.ID'),\n            $translate('DECISION-TABLE-EXECUTION.HEADER.DECISION-KEY'),\n            $translate('DECISION-TABLE-EXECUTION.HEADER.DECISION-DEFINITION-ID'),\n            $translate('DECISION-TABLE-EXECUTION.HEADER.END-TIME'),\n            $translate('DECISION-TABLE-EXECUTION.HEADER.FAILED')])\n            .then(function (headers) {\n\n                $scope.gridDecisionTables = {\n                    data: 'decisionTables.data',\n                    enableRowReordering: false,\n                    multiSelect: false,\n                    keepLastSelected: false,\n                    enableSorting: false,\n                    rowHeight: 36,\n                    afterSelectionChange: $scope.openDecisionTable,\n                    columnDefs: [\n                        {field: 'id', displayName: headers[0]},\n                        {field: 'decisionKey', displayName: headers[1]},\n                        {field: 'decisionDefinitionId', displayName: headers[2]},\n                        {\n                            field: 'endTime',\n                            displayName: headers[3],\n                            cellTemplate: gridConstants.dateTemplate\n                        },\n                        {field: 'decisionExecutionFailed', displayName: headers[4]}\n                    ]\n                };\n            });\n\n        $q.all([$translate('FORM-INSTANCE.HEADER.ID'),\n            $translate('FORM-INSTANCE.HEADER.TASK-ID'),\n            $translate('FORM-INSTANCE.HEADER.PROCESS-ID'),\n            $translate('FORM-INSTANCE.HEADER.SUBMITTED'),\n            $translate('FORM-INSTANCE.HEADER.SUBMITTED-BY')])\n            .then(function (headers) {\n\n                $scope.gridFormInstances = {\n                    data: 'formInstances.data',\n                    enableRowReordering: false,\n                    multiSelect: false,\n                    keepLastSelected: false,\n                    enableSorting: false,\n                    rowHeight: 36,\n                    afterSelectionChange: $scope.openFormInstance,\n                    columnDefs: [\n                        {field: 'id', displayName: headers[0]},\n                        {field: 'taskId', displayName: headers[1]},\n                        {field: 'processInstanceId', displayName: headers[2]},\n                        {field: 'submittedDate', displayName: headers[3], cellTemplate: gridConstants.dateTemplate},\n                        {field: 'submittedBy', displayName: headers[4], cellTemplate: gridConstants.userObjectTemplate}\n                    ]\n                };\n            });\n\n        $scope.showAllJobs = function () {\n            // Populate the job-filter with process id\n            $rootScope.filters.forced.jobFilter = {\n                processInstanceId: $scope.process.id\n            };\n            $location.path(\"/jobs\");\n        };\n\n        $scope.loadTasks = function () {\n            $scope.tasks = undefined;\n            $http({\n                method: 'GET',\n                url: FlowableAdmin.webContextRoot + '/app/rest/admin/process-instances/' + $scope.process.id + '/tasks'\n            }).success(function (data, status, headers, config) {\n                $scope.tasks = data;\n                $scope.tabData.tabs[0].info = data.total;\n            });\n        };\n\n        $scope.loadVariables = function () {\n            $scope.variables = undefined;\n            $http({\n                method: 'GET',\n                url: FlowableAdmin.webContextRoot + '/app/rest/admin/process-instances/' + $scope.process.id + '/variables'\n            }).success(function (data, status, headers, config) {\n                $scope.variables = data;\n                $scope.tabData.tabs[1].info = data.total;\n            });\n        };\n\n        $scope.loadSubProcesses = function () {\n            $scope.subprocesses = undefined;\n            $http({\n                method: 'GET',\n                url: FlowableAdmin.webContextRoot + '/app/rest/admin/process-instances/' + $scope.process.id + '/subprocesses'\n            }).success(function (data, status, headers, config) {\n                $scope.subprocesses = data;\n                $scope.tabData.tabs[2].info = data.total;\n            });\n        };\n\n        $scope.loadJobs = function () {\n            $scope.jobs = undefined;\n            $http({\n                method: 'GET',\n                url: FlowableAdmin.webContextRoot + '/app/rest/admin/process-instances/' + $scope.process.id + '/jobs'\n            }).success(function (data, status, headers, config) {\n                $scope.jobs = data;\n                $scope.tabData.tabs[3].info = data.total;\n            });\n        };\n\n        $scope.loadProcessDefinition = function () {\n            // Load definition\n            $http({\n                method: 'GET',\n                url: FlowableAdmin.webContextRoot + '/app/rest/admin/process-definitions/' + $scope.process.processDefinitionId\n            }).success(function (data, status, headers, config) {\n                $scope.definition = data;\n            }).error(function (data, status, headers, config) {\n            });\n        };\n\n        $scope.loadDecisionTables = function () {\n            // Load decision tables\n            $http({\n                method: 'GET',\n                url: FlowableAdmin.webContextRoot + '/app/rest/admin/process-instances/' + $scope.process.id + '/decision-executions'\n            }).success(function (data, status, headers, config) {\n                $scope.decisionTables = data;\n                $scope.tabData.tabs[4].info = data.total;\n            }).error(function (data, status, headers, config) {\n            });\n        };\n\n        $scope.loadFormInstances = function () {\n            // Load form instances\n            $http({\n                method: 'GET',\n                url: FlowableAdmin.webContextRoot + '/app/rest/admin/process-form-instances/' + $scope.process.id\n            }).success(function (data, status, headers, config) {\n                $scope.formInstances = data;\n                $scope.tabData.tabs[5].info = data.total;\n            }).error(function (data, status, headers, config) {\n            });\n        };\n\n\n        $scope.executeWhenReady(function () {\n            $scope.loadProcessInstance();\n        });\n\n\n        // Dialogs\n        $scope.deleteProcessInstance = function (action) {\n            if (!action) {\n                action = \"delete\";\n            }\n            var modalInstance = $modal.open({\n                templateUrl: 'views/process-instance-delete-popup.html',\n                controller: 'DeleteProcessModalInstanceCtrl',\n                resolve: {\n                    process: function () {\n                        return $scope.process;\n                    },\n                    action: function () {\n                        return action;\n                    }\n                }\n            });\n\n            modalInstance.result.then(function (deleteProcessInstance) {\n                if (deleteProcessInstance) {\n                    if (action == 'delete') {\n                        $scope.addAlert($translate.instant('ALERT.PROCESS-INSTANCE.DELETED', $scope.process), 'info');\n                        $scope.returnToList();\n                    } else {\n                        $scope.addAlert($translate.instant('ALERT.PROCESS-INSTANCE.TERMINATED', $scope.process), 'info');\n                        $scope.loadProcessInstance();\n                    }\n                }\n            });\n        };\n\n        $scope.updateSelectedVariable = function () {\n            if ($scope.selectedVariables && $scope.selectedVariables.length > 0) {\n                var selectedVariable = $scope.selectedVariables[0];\n                var modalInstance = $modal.open({\n                    templateUrl: 'views/update-variable-popup.html',\n                    controller: 'UpdateVariableCtrl',\n                    resolve: {\n                        variable: function () {\n                            return selectedVariable.variable;\n                        },\n                        processInstanceId: function () {\n                            return $scope.process.id;\n                        }\n                    }\n                });\n\n                modalInstance.result.then(function (updated) {\n                    if (updated == true) {\n                        $scope.selectedVariables.splice(0, $scope.selectedVariables.length);\n                        $scope.loadVariables();\n                    }\n                });\n            }\n        };\n\n        $scope.deleteVariable = function () {\n            if ($scope.selectedVariables && $scope.selectedVariables.length > 0) {\n                var selectedVariable = $scope.selectedVariables[0];\n                var modalInstance = $modal.open({\n                    templateUrl: 'views/variable-delete-popup.html',\n                    controller: 'DeleteVariableCtrl',\n                    resolve: {\n                        variable: function () {\n                            return selectedVariable.variable;\n                        },\n                        processInstanceId: function () {\n                            return $scope.process.id;\n                        }\n                    }\n                });\n\n                modalInstance.result.then(function (updated) {\n                    if (updated == true) {\n                        $scope.selectedVariables.splice(0, $scope.selectedVariables.length);\n                        $scope.loadVariables();\n                    }\n                });\n            }\n        };\n\n        $scope.addVariable = function () {\n            var modalInstance = $modal.open({\n                templateUrl: 'views/variable-add-popup.html',\n                controller: 'AddVariableCtrl',\n                resolve: {\n                    processInstanceId: function () {\n                        return $scope.process.id;\n                    }\n                }\n            });\n\n            modalInstance.result.then(function (updated) {\n                if (updated == true) {\n                    $scope.selectedVariables.splice(0, $scope.selectedVariables.length);\n                    $scope.loadVariables();\n                }\n            });\n        };\n\n        $scope.terminateProcessInstance = function () {\n            $scope.deleteProcessInstance(\"terminate\");\n        };\n    }]);\n\nflowableAdminApp.controller('DeleteProcessModalInstanceCtrl',\n    ['$rootScope', '$scope', '$modalInstance', '$http', 'process', function ($rootScope, $scope, $modalInstance, $http, process, action) {\n\n        $scope.process = process;\n        $scope.action = action;\n        $scope.status = {loading: false};\n        $scope.model = {};\n        $scope.ok = function () {\n            $scope.status.loading = true;\n\n            var dataForPost = {action: $scope.action};\n            if ($scope.action == 'terminate' && $scope.model.deleteReason) {\n                dataForPost.deleteReason = $scope.model.deleteReason;\n            }\n\n            $http({\n                method: 'POST', url: FlowableAdmin.webContextRoot + '/app/rest/admin/process-instances/' + $scope.process.id,\n                data: dataForPost\n            }).success(function (data, status, headers, config) {\n                $modalInstance.close(true);\n                $scope.status.loading = false;\n            }).error(function (data, status, headers, config) {\n                $modalInstance.close(false);\n                $scope.status.loading = false;\n            });\n        };\n\n        $scope.cancel = function () {\n            if (!$scope.status.loading) {\n                $modalInstance.dismiss('cancel');\n            }\n        };\n    }]);\n\nflowableAdminApp.controller('ShowProcessInstanceDiagramPopupCtrl',\n    ['$rootScope', '$scope', '$modalInstance', '$http', 'process', '$timeout', function ($rootScope, $scope, $modalInstance, $http, process, $timeout) {\n\n        $scope.model = {\n            id: process.id,\n            name: process.name\n        };\n\n        $scope.status = {loading: false};\n\n        $scope.cancel = function () {\n            if (!$scope.status.loading) {\n                $modalInstance.dismiss('cancel');\n            }\n        };\n\n        $timeout(function () {\n            $(\"#bpmnModel\").attr(\"data-instance-id\", process.id);\n            $(\"#bpmnModel\").attr(\"data-definition-id\", process.processDefinitionId);\n            $(\"#bpmnModel\").attr(\"data-server-id\", $rootScope.activeServers['process'].id);\n            if (process.endTime != undefined) {\n                $(\"#bpmnModel\").attr(\"data-history-id\", process.id);\n            }\n            $(\"#bpmnModel\").load(\"./display/displaymodel.html?instanceId=\" + process.id);\n        }, 200);\n\n\n    }]);\n    \nflowableAdminApp.controller('ShowProcessInstanceMigrationPopupCtrl',\n    ['$rootScope', '$scope', '$modalInstance', '$http', 'process', 'processDefinition', 'migrationScope', \n    function ($rootScope, $scope, $modalInstance, $http, process, processDefinition, migrationScope) {\n\n        $scope.process = process;\n        $scope.processDefinition = processDefinition;\n        $scope.status = {loading: false};\n        $scope.model = {\n            targetNotSelected: true,\n            currentDefinitionId: processDefinition.id\n        };\n        \n        $http({\n            method: 'GET',\n            url: FlowableAdmin.webContextRoot + '/app/rest/admin/process-definitions?key=' + $scope.processDefinition.key\n        }).success(function (response, status, headers, config) {\n            var definitionList = response.data;\n            var finalResult = [];\n            for (var i = 0; i < definitionList.length; i++) {\n                if (definitionList[i].id !== processDefinition.id) {\n                    finalResult.push(definitionList[i]);\n                }\n            }\n            $scope.filteredProcessDefinitions = finalResult;\n            \n        }).error(function (data, status, headers, config) {\n        });\n        \n        $scope.targetProcessDefinitionChanged = function () {\n            if ($scope.model.newProcessDefinition && $scope.model.newProcessDefinition.length > 0) {\n                migrationScope.targetProcessDefinition = $scope.model.newProcessDefinition;\n                $scope.model.targetNotSelected = false;\n            }\n        };\n        \n        $scope.ok = function () {\n            $modalInstance.close(true);\n        };\n\n        $scope.cancel = function () {\n            if (!$scope.status.loading) {\n                $modalInstance.dismiss('cancel');\n            }\n        };\n    }]);\n    \nflowableAdminApp.controller('ShowProcessInstanceMigrationDiagramPopupCtrl',\n    ['$rootScope', '$scope', '$modalInstance', '$http', 'process', 'migrationScope', '$timeout',\n    function ($rootScope, $scope, $modalInstance, $http, process, migrationScope, $timeout) {\n\n        $scope.model = {\n            id: process.id,\n            name: process.name\n        };\n\n        $scope.status = {loading: false};\n\n        $scope.cancel = function () {\n            if (!$scope.status.loading) {\n                $modalInstance.close(true);\n            }\n        };\n\n        $timeout(function () {\n            $(\"#bpmnModel\").attr(\"data-instance-id\", process.id);\n            $(\"#bpmnModel\").attr(\"data-definition-id\", process.processDefinitionId);\n            $(\"#bpmnModel\").attr(\"data-server-id\", $rootScope.activeServers['process'].id);\n            $(\"#targetModel\").attr(\"data-migration-definition-id\", migrationScope.targetProcessDefinition);\n            \n            $(\"#bpmnModel\").load(\"./display/displaymodel.html?instanceId=\" + process.id);\n        }, 200);\n\n\n    }]);\n\nflowableAdminApp.controller('UpdateVariableCtrl',\n    ['$rootScope', '$scope', '$modalInstance', '$http', 'variable', 'processInstanceId', function ($rootScope, $scope, $modalInstance, $http, variable, processInstanceId) {\n\n        $scope.status = {loading: false};\n        $scope.originalVariable = variable;\n\n        $scope.updateVariable = {\n            name: variable.name,\n            value: variable.value,\n            type: variable.type\n        };\n\n        $scope.executeUpdateVariable = function () {\n\n            $scope.status.loading = true;\n\n            var dataForPut = {\n                name: $scope.updateVariable.name,\n                type: $scope.updateVariable.type\n            };\n\n            if ($scope.updateVariable.value !== null || $scope.updateVariable.value !== undefined || $scope.updateVariable.value !== '') {\n\n                if ($scope.updateVariable.type === 'string') {\n\n                    dataForPut.value = $scope.updateVariable.value;\n\n                } else if ($scope.updateVariable.type === 'boolean') {\n\n                    if ($scope.updateVariable.value) {\n                        dataForPut.value = true;\n                    } else {\n                        dataForPut.value = false;\n                    }\n\n                } else if ($scope.updateVariable.type === 'date') {\n\n                    dataForPut.value = $scope.updateVariable.value;\n\n                } else if ($scope.updateVariable.type === 'double'\n                    || $scope.updateVariable.type === 'long'\n                    || $scope.updateVariable.type === 'integer'\n                    || $scope.updateVariable.type === 'short') {\n\n                    dataForPut.value = Number($scope.updateVariable.value);\n\n                }\n\n            } else {\n\n                dataForPut.value = null;\n\n            }\n\n            $http({\n                method: 'PUT',\n                url: FlowableAdmin.webContextRoot + '/app/rest/admin/process-instances/' + processInstanceId + '/variables/' + $scope.updateVariable.name,\n                data: dataForPut\n            }).success(function (data, status, headers, config) {\n                $modalInstance.close(true);\n                $scope.status.loading = false;\n            }).error(function (data, status, headers, config) {\n                $modalInstance.close(false);\n                $scope.status.loading = false;\n            });\n\n        };\n\n        $scope.cancel = function () {\n            $modalInstance.dismiss('cancel');\n        };\n\n    }]);\n\nflowableAdminApp.controller('DeleteVariableCtrl',\n    ['$rootScope', '$scope', '$modalInstance', '$http', 'variable', 'processInstanceId',\n        function ($rootScope, $scope, $modalInstance, $http, variable, processInstanceId) {\n\n            $scope.status = {loading: false};\n            $scope.variable = variable;\n\n            $scope.deleteVariable = function () {\n                $http({\n                    method: 'DELETE',\n                    url: FlowableAdmin.webContextRoot + '/app/rest/admin/process-instances/' + processInstanceId + '/variables/' + $scope.variable.name\n                }).success(function (data, status, headers, config) {\n                    $modalInstance.close(true);\n                    $scope.status.loading = false;\n                }).error(function (data, status, headers, config) {\n                    $modalInstance.close(false);\n                    $scope.status.loading = false;\n                });\n            };\n\n            $scope.cancel = function () {\n                $modalInstance.dismiss('cancel');\n            };\n\n        }]);\n\nflowableAdminApp.controller('AddVariableCtrl',\n    ['$rootScope', '$scope', '$modalInstance', '$http', 'processInstanceId',\n        function ($rootScope, $scope, $modalInstance, $http, processInstanceId) {\n\n            $scope.status = {loading: false};\n\n            $scope.types = [\n                \"string\",\n                \"boolean\",\n                \"date\",\n                \"double\",\n                \"integer\",\n                \"long\",\n                \"short\"\n            ];\n\n            $scope.newVariable = {};\n\n            $scope.createVariable = function () {\n\n                var data = {\n                    name: $scope.newVariable.name,\n                    type: $scope.newVariable.type,\n                };\n\n                if ($scope.newVariable.type === 'string') {\n\n                    data.value = $scope.newVariable.value;\n\n                } else if ($scope.newVariable.type === 'boolean') {\n\n                    if ($scope.newVariable.value) {\n                        data.value = true;\n                    } else {\n                        data.value = false;\n                    }\n\n                } else if ($scope.newVariable.type === 'date') {\n\n                    data.value = $scope.newVariable.value;\n\n                } else if ($scope.newVariable.type === 'double'\n                    || $scope.newVariable.type === 'long'\n                    || $scope.newVariable.type === 'integer'\n                    || $scope.newVariable.type === 'short') {\n\n                    data.value = Number($scope.newVariable.value);\n\n                }\n\n                $http({\n                    method: 'POST',\n                    url: FlowableAdmin.webContextRoot + '/app/rest/admin/process-instances/' + processInstanceId + '/variables',\n                    data: data\n                }).success(function (data, status, headers, config) {\n                    $modalInstance.close(true);\n                    $scope.status.loading = false;\n                }).error(function (data, status, headers, config) {\n                    $modalInstance.close(false);\n                    $scope.status.loading = false;\n                });\n            };\n\n            $scope.cancel = function () {\n                $modalInstance.dismiss('cancel');\n            };\n\n        }]);\n"
  },
  {
    "path": "flowable-ui-web/admin/scripts/process-instances-controllers.js",
    "content": "/* Copyright 2005-2015 Alfresco Software, Ltd.\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'use strict';\n\n/* Controllers */\n\nflowableAdminApp.controller('ProcessInstancesController', ['$rootScope', '$scope', '$http', '$timeout', '$location', '$translate', '$q', 'gridConstants',\n    function ($rootScope, $scope, $http, $timeout, $location, $translate, $q, gridConstants) {\n\n\t\t$rootScope.navigation = {main: 'process-engine', sub: 'instances'};\n\t\t\n\t\t$scope.filter = {};\n\t\t$scope.processInstances = {};\n\t\t$scope.definitionCacheLoaded = false;\n\n\t\t$scope.variableFilterTypes = FlowableAdmin.Utils.variableFilterTypes;\n\t\t$scope.variableFilterOperators = FlowableAdmin.Utils.variableFilterOperators;\n\n\t    var filterConfig = {\n\t    \turl: FlowableAdmin.webContextRoot + '/app/rest/admin/process-instances',\n\t    \tmethod: 'POST',\n\t    \tsuccess: function(data, status, headers, config) {\n\t    \t\tif ($scope.definitionCacheLoaded) {\n                \t$scope.processQueryResponse(data);\n                }\n                else {\n\t                $rootScope.loadProcessDefinitionsCache().then(function(promise) {\n\t        \t\t\t$rootScope.processDefinitionsCache = promise.data;\n\n\t        \t\t\t$scope.definitionCacheLoaded = true;\n\t        \t\t\t$scope.processQueryResponse(data);\n\t        \t\t});\n                }\n            },\n            error: function(data, status, headers, config) {\n                if (data && data.message) {\n                    // Extract error-message\n                    $rootScope.addAlert(data.message, 'error');\n                } else {\n                    // Use default error-message\n                    $rootScope.addAlert($translate.instant('ALERT.GENERAL.HTTP-ERROR'), 'error');\n                }\n            },\n\n            sortObjects: [\n                {name: 'PROCESS-INSTANCES.SORT.ID', id: 'processInstanceId'},\n                {name: 'PROCESS-INSTANCES.SORT.START-TIME', id: 'startTime'}\n            ],\n            \n            options: {\n                finished: [\n                    {name: 'PROCESS-INSTANCES.FILTER.STATUS-ANY', value: ''},\n                    {name: 'PROCESS-INSTANCES.FILTER.STATUS-ACTIVE', value: 'false'},\n                    {name: 'PROCESS-INSTANCES.FILTER.STATUS-COMPLETE', value: 'true'}\n                ]\n            },\n\n            supportedProperties: [\n                {id: 'finished', name: 'PROCESS-INSTANCES.FILTER.STATUS', showByDefault: true},\n                {id: 'processBusinessKey', name: 'PROCESS-INSTANCES.FILTER.BUSINESS-KEY'},\n                {id: 'superProcessInstanceId', name: 'PROCESS-INSTANCES.FILTER.SUPER-PROCESS-INSTANCE-ID'},\n                {id: 'startedBefore', name: 'PROCESS-INSTANCES.FILTER.STARTED-BEFORE'},\n                {id: 'startedAfter', name: 'PROCESS-INSTANCES.FILTER.STARTED-AFTER'},\n                {id: 'finishedBefore', name: 'PROCESS-INSTANCES.FILTER.ENDED-BEFORE'},\n                {id: 'finishedAfter', name: 'PROCESS-INSTANCES.FILTER.ENDED-AFTER'},\n                {id: 'variable', name: 'PROCESS-INSTANCES.FILTER.VARIABLE'},\n                {id: 'tenantIdLike', name: 'PROCESS-INSTANCES.FILTER.TENANT-ID'}\n            ]\n\t    };\n\n\t    if ($rootScope.filters.forced.instanceFilter) {\n\t        // Always recreate the filter and add all properties\n            $scope.filter = new FlowableAdmin.Utils.Filter(filterConfig, $http, $timeout, $rootScope);\n            $rootScope.filters.instanceFilter = $scope.filter;\n\n    \t\tfor (var prop in $rootScope.filters.forced.instanceFilter) {\n    \t\t\t$scope.filter.addProperty({id: prop}, $rootScope.filters.forced.instanceFilter[prop]);\n    \t\t}\n\n    \t\t$rootScope.filters.forced.instanceFilter = undefined;\n\n\t    } else if ($rootScope.filters && $rootScope.filters.instanceFilter) {\n            // Reuse the existing filter\n            $scope.filter = $rootScope.filters.instanceFilter;\n            $scope.filter.config = filterConfig;\n\n\t    } else {\n            $scope.filter = new FlowableAdmin.Utils.Filter(filterConfig, $http, $timeout, $rootScope);\n            $rootScope.filters.instanceFilter = $scope.filter;\n\t    }\n\n\t    $scope.processInstanceSelected = function(processInstance) {\n        if (processInstance && processInstance.getProperty('id')) {\n            $location.path('/process-instance/' + processInstance.getProperty('id'));\n        }\n      };\n\n\t    if(!$scope.filter.properties.variables) {\n\t      $scope.filter.properties.variables = [];\n\t    }\n\n\t    // Set value-filter callback to convert variables to nice format\n\t    $scope.filter.config.valueFilter = function(prop, value) {\n\t      if (prop == 'variables') {\n\t        var actualValue = [];\n\t        var variable;\n\t        for (var i=0; i<value.length; i++) {\n\t          variable = value[i];\n\n\t          if (variable.name && variable.type && variable.value !== undefined && variable.value !== '' && variable.operator) {\n\t              var varPayload =  {\n\t                  name: variable.name,\n\t                  value: variable.value,\n\t                  operation: variable.operator.id,\n\t                  type: variable.type.id\n\t              };\n\n\t              if (variable.type.id == 'long' || variable.type.id == 'short' || variable.type.id == 'double' || variable.type.id == 'integer') {\n\t                  varPayload.value = parseFloat(varPayload.value);\n\t                  if (!isNaN(varPayload.value)) {\n\t                      // Return valid value for number\n\t                      actualValue.push(varPayload);\n\t                  }\n\t              } else {\n\t                  // Return valid value\n\t                  actualValue.push(varPayload);\n\t              }\n\t          }\n\t        }\n\t        return actualValue;\n\t      } else {\n\t        return value;\n\t      }\n\t    };\n\n\t    $scope.clearFilters = function() {\n\t      $scope.filter.clear();\n\t      $scope.filter.properties.variables = [];\n\t    };\n\n\t    $scope.setVariableFilterType = function(varFilter, type) {\n\n\t      varFilter.value = undefined;\n\t      if (type.id == 'boolean') {\n\t        varFilter.value = true;\n\n\t        if (varFilter.operator.id != 'equals') {\n\t          varFilter.operator = $scope.variableFilterOperators[0];\n\t        }\n\t      }\n\n\t      varFilter.type = type;\n\t      $scope.highlightVariableValue(varFilter);\n\t      $scope.filter.refresh();\n\t    };\n\n\t    $scope.setVariableFilterOperator = function(varFilter, operator) {\n\t      if(operator.id == 'like') {\n\t        varFilter.value = '';\n\t        varFilter.type = $scope.variableFilterTypes[0];\n\t      }\n\n\t      if(varFilter.type.id == 'boolean' && operator.id != 'equals') {\n\t        varFilter.operator = $scope.variableFilterOperators[0];\n\t      } else {\n\t        varFilter.operator = operator;\n\t      }\n\t      $scope.highlightVariableValue(varFilter);\n\t      $scope.filter.refresh();\n\t    };\n\n\t    $scope.highlightVariableValue = function(varFilter) {\n\t       var index = -1;\n            for (var i=0; i<$scope.filter.properties.variables.length; i++) {\n                if (varFilter == $scope.filter.properties.variables[i]) {\n                    index = i;\n                    break;\n                }\n            }\n\n            $timeout(function() {\n                var formField = $('#filter-variable-value-' + index);\n                formField.focus();\n            }, 100);\n\t    };\n\n\t    $scope.addFilterProperty = function(prop) {\n\t      if(prop.id != 'variable') {\n\t        $scope.filter.addProperty(prop);\n\t      } else {\n\t        // Add additional variable\n\t        $scope.filter.properties.variables.push({\n\t          type: $scope.variableFilterTypes[0],\n\t          operator: $scope.variableFilterOperators[0],\n\t          scope: 'variable'\n\t        });\n\n\t        $timeout(function() {\n\t          var formField = $('#filter-variable-name-' + ($scope.filter.properties.variables.length - 1));\n\t          formField.focus();\n\t        }, 100);\n\t      }\n\t    };\n\n\t    $q.all([$translate('PROCESS-INSTANCES.HEADER.ID'),\n              $translate('PROCESS-INSTANCES.HEADER.BUSINESS-KEY'),\n              $translate('PROCESS-INSTANCES.HEADER.PROCESS-DEFINITION'),\n              $translate('PROCESS-INSTANCES.HEADER.CREATE-TIME'),\n              $translate('PROCESS-INSTANCES.HEADER.END-TIME'),])\n              .then(function(headers) {\n\n          $scope.gridInstances = {\n              data: 'processInstances.data',\n              enableRowReordering: true,\n              multiSelect: false,\n              keepLastSelected : false,\n              rowHeight: 36,\n              afterSelectionChange: $scope.processInstanceSelected,\n              columnDefs: [\n                  { field: 'id', displayName: headers[0], cellTemplate: gridConstants.defaultTemplate},\n                  { field: 'businessKey', displayName: headers[1], cellTemplate: gridConstants.defaultTemplate},\n                  { field: 'processDefinition.name', displayName: headers[2], cellTemplate: gridConstants.defaultTemplate},\n                  { field: 'startTime', displayName: headers[3], cellTemplate: gridConstants.dateTemplate},\n                  { field: 'endTime', displayName: headers[4], cellTemplate: gridConstants.dateTemplate}]\n          };\n        });\n\n        $scope.processQueryResponse = function(processInstancesResponse) {\n        \tfor (var i = 0; i < processInstancesResponse.data.length; i++) {\n\t\t\t\tprocessInstancesResponse.data[i].processDefinition =\n            \t\t$rootScope.getProcessDefinitionFromCache(processInstancesResponse.data[i].processDefinitionId);\n\n\t\t\t\t// Fallback to id, of process definition doesn't have a name (getProcessDefinitionFromCache returns null if not found)\n\t\t\t\tif ((processInstancesResponse.data[i].processDefinition === null || processInstancesResponse.data[i].processDefinition === undefined) && processInstancesResponse.data[i].processDefinitionId) {\n\t\t\t\t    processInstancesResponse.data[i].processDefinition = { id: processInstancesResponse.data[i].processDefinitionId, name: processInstancesResponse.data[i].processDefinitionId }\n\t\t\t\t}\n\n            }\n\t\t\t$scope.processInstances = processInstancesResponse;\n        };\n\n        $scope.processDefinitionFilterChanged = function() {\n        \tif ($scope.filter.processDefinition && $scope.filter.processDefinition !== '-1') {\n        \t\t$scope.filter.properties.processDefinitionId = $scope.filter.processDefinition;\n        \t\t$scope.filter.refresh();\n        \t\t\n        \t} else {\n        \t\tvar tempProcessDefinitionId = $scope.filter.properties.processDefinitionId;\n        \t\t$scope.filter.properties.processDefinitionId = null;\n        \t\tif (tempProcessDefinitionId && tempProcessDefinitionId.length > 0) {\n        \t\t\t$scope.filter.refresh();\n        \t\t}\n        \t}\n        };\n\n        $scope.executeWhenReady(function() {\n            $scope.filter.refresh();\n        });\n\n    }]);\n"
  },
  {
    "path": "flowable-ui-web/admin/scripts/recursion-helper.js",
    "content": "/* Copyright 2005-2015 Alfresco Software, Ltd.\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'use strict';\n\n// Recursion Helper service, makes it possible to use nested directives of the same type\nflowableAdminApp.factory('RecursionHelper', ['$compile', function($compile){\n    return {\n        /**\n         * Manually compiles the element, fixing the recursion loop.\n         * @param element\n         * @param [link] A post-link function, or an object with function(s) registered via pre and post properties.\n         * @returns An object containing the linking functions.\n         */\n        compile: function(element, link){\n            // Normalize the link parameter\n            if(angular.isFunction(link)){\n                link = { post: link };\n            }\n\n            // Break the recursion loop by removing the contents\n            var contents = element.contents().remove();\n            var compiledContents;\n            return {\n                pre: (link && link.pre) ? link.pre : null,\n                /**\n                 * Compiles and re-adds the contents\n                 */\n                post: function(scope, element){\n                    // Compile the contents\n                    if(!compiledContents){\n                        compiledContents = $compile(contents);\n                    }\n                    // Re-add the compiled contents to the element\n                    compiledContents(scope, function(clone){\n                        element.append(clone);\n                    });\n\n                    // Call the post-linking function, if any\n                    if(link && link.post){\n                        link.post.apply(null, arguments);\n                    }\n                }\n            };\n        }\n    };\n}]);"
  },
  {
    "path": "flowable-ui-web/admin/scripts/services.js",
    "content": "/* Copyright 2005-2015 Alfresco Software, Ltd.\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'use strict';\n\n/* Services */\n\nflowableAdminApp.factory('Account', ['$resource',\n    function ($resource) {\n        return $resource('/app/rest/account', {}, {\n        });\n    }]);\n\nflowableAdminApp.factory('Sessions', ['$resource',\n    function ($resource) {\n        return $resource('/app/rest/account/sessions/:series', {}, {\n            'get': { method: 'GET', isArray: true}\n        });\n    }]);\n\nflowableAdminApp.factory('Metrics', ['$resource',\n    function ($resource) {\n        return $resource('/metrics/metrics', {}, {\n            'get': { method: 'GET'}\n        });\n    }]);\n\nflowableAdminApp.factory('LogsService', ['$resource',\n    function ($resource) {\n        return $resource('/app/rest/logs', {}, {\n            'findAll': { method: 'GET', isArray: true},\n            'changeLevel':  { method: 'PUT'}\n        });\n    }]);\n"
  },
  {
    "path": "flowable-ui-web/admin/scripts/task-controllers.js",
    "content": "/* Copyright 2005-2015 Alfresco Software, Ltd.\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'use strict';\n\nflowableAdminApp.controller('TaskController', ['$scope', '$rootScope', '$http', '$timeout','$location','$routeParams', '$modal', '$translate', '$q', 'gridConstants',\n    function ($scope, $rootScope, $http, $timeout, $location, $routeParams, $modal, $translate, $q, gridConstants) {\n\n        $rootScope.navigation = {main: 'process-engine', sub: 'tasks'};\n\t\t\n\t\t$scope.tabData = {\n            tabs: [\n               {id: 'subTasks', name: 'TASK.TITLE.SUBTASKS'},\n               {id: 'variables', name: 'TASK.TITLE.VARIABLES'},\n               {id: 'identityLinks', name: 'TASK.TITLE.IDENTITY-LINKS'}\n            ],\n        };\n\n\t\t$scope.tabData.activeTab = $scope.tabData.tabs[0].id;\n\n\t\t$scope.returnToList = function() {\n\t\t\t$location.path(\"/tasks\");\n\t\t};\n\n\t\t$scope.openTask = function(taskId) {\n\t\t\tif (taskId) {\n\t\t\t\t$location.path(\"/task/\" + taskId);\n\t\t\t}\n\t\t};\n\n\t\t$scope.openProcessInstance = function(processInstanceId) {\n\t\t\tif (processInstanceId) {\n\t\t\t\t$location.path(\"/process-instance/\" + processInstanceId);\n\t\t\t}\n\t\t};\n\n\t\t$scope.openProcessDefinition = function(processDefinitionId) {\n\t\t\tif (processDefinitionId) {\n\t\t\t\t$location.path(\"/process-definition/\" + processDefinitionId);\n\t\t\t}\n\t\t};\n\n\t\t$scope.loadTask = function() {\n\t\t\t$scope.task = undefined;\n\t\t\t// Load task\n\t\t\t$http({method: 'GET', url: FlowableAdmin.webContextRoot + '/app/rest/admin/tasks/' + $routeParams.taskId}).\n\t\t\tsuccess(function(data, status, headers, config) {\n\t\t\t\t$scope.task = data;\n\n\t\t\t\tif(data) {\n\t\t\t\t\t$scope.taskCompleted = data.endTime != undefined;\n\t\t\t\t\t$scope.taskPartOfProcess = data.executionId != undefined;\n\t\t\t\t}\n\n\t\t\t\t// Load runtime-task, if available, for accurate delegation-state\n\t\t\t\t$scope.loadRuntimeTask();\n\n\t\t\t\t// Start loading children\n\t\t\t\t$scope.loadSubTasks();\n\t\t\t\t$scope.loadVariables();\n\t\t\t\t$scope.loadIdentityLinks();\n\t\t\t}).\n\t\t\terror(function(data, status, headers, config) {\n                if (data && data.message) {\n                    // Extract error-message\n                    $rootScope.addAlert(data.message, 'error');\n                } else {\n                    // Use default error-message\n                    $rootScope.addAlert($translate.instant('ALERT.GENERAL.HTTP-ERROR'), 'error');\n                }\n            });\n\t\t};\n\n\t\t$scope.loadRuntimeTask = function() {\n\t\t\tif($scope.task && !$scope.taskCompleted) {\n\t\t\t\t// Load runtime task, if available to fetch delegation state\n\t\t\t\t$http({method: 'GET', url: FlowableAdmin.webContextRoot + '/app/rest/admin/tasks/' + $routeParams.taskId,\n\t\t\t\t\tparams: {runtime: 'true'}}).\n\t\t\t\tsuccess(function(data, status, headers, config) {\n\t\t\t\t\t// Workaround for pre 5.15 installs, historic assignee is not updated when set to null\n\t\t\t\t\t$scope.task.assignee = data.assignee;\n\t\t\t\t\tif(data.delegationState) {\n\t\t\t\t\t\t$scope.task.delegationState = data.delegationState;\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// Use empty string to trigger delegate-button to show when delegationState is loaded\n\t\t\t\t\t\t$scope.task.delegationState = '';\n\t\t\t\t\t}\n\t\t\t\t\t$scope.task.delegationStateLoaded = true;\n\t\t\t\t});\n\t\t\t}\n\t\t};\n\n\t\t$scope.subTaskSelected = function(task) {\n\t    \tif(task && task.getProperty('id')) {\n\t    \t\t$scope.openTask(task.getProperty('id'));\n\t    \t}\n\t\t};\n\t  // Config for subtasks grid\n    $q.all([$translate('TASKS.HEADER.ID'),\n             $translate('TASKS.HEADER.NAME'),\n             $translate('TASKS.HEADER.ASSIGNEE'),\n             $translate('TASKS.HEADER.OWNER')])\n    .then(function(headers) {\n        $scope.subTaskGridDefinitions = {\n            data: 'subTasks.data',\n            enableRowReordering: false,\n            multiSelect: false,\n            keepLastSelected : false,\n            enableSorting: false,\n            rowHeight: 36,\n            afterSelectionChange: $scope.subTaskSelected,\n            columnDefs: [\n                { field: 'id', displayName: headers[0], width: 50, cellTemplate: gridConstants.defaultTemplate},\n                { field: 'name', displayName: headers[1], cellTemplate: gridConstants.defaultTemplate},\n                { field: 'assignee', displayName: headers[2], width: 100, cellTemplate: gridConstants.defaultTemplate},\n                { field: 'owner', displayName: headers[3], width: 100, cellTemplate: gridConstants.defaultTemplate}\n            ]\n        };\n    });\n\n    $q.all([$translate('VARIABLES.HEADER.NAME'),\n            $translate('VARIABLES.HEADER.TYPE'),\n            $translate('VARIABLES.HEADER.VALUE')])\n   .then(function(headers) {\n        var variableValueTemplate = '<div><div class=\"ngCellText\">{{row.getProperty(\"variable.valueUrl\") && \"(Binary)\" || row.getProperty(col.field)}}</div></div>';\n        var variableTypeTemplate = '<div><div class=\"ngCellText\">{{row.getProperty(col.field) && row.getProperty(col.field) || \"null\"}}</div></div>';\n        // Config for variable grid\n        $scope.variableGridDefinitions = {\n            data: 'variables.data',\n            enableRowReordering: false,\n            multiSelect: false,\n            keepLastSelected : false,\n            enableSorting: false,\n            rowHeight: 36,\n            columnDefs: [\n                { field: 'variable.name', displayName: headers[0]},\n                { field: 'variable.type', displayName: headers[1], cellTemplate: variableTypeTemplate},\n                { field: 'variable.value', displayName: headers[2], cellTemplate: variableValueTemplate}\n            ]\n        };\n   });\n\n    $q.all([$translate('IDENTITY-LINKS.HEADER.TYPE'),\n            $translate('IDENTITY-LINKS.HEADER.GROUP-ID'),\n            $translate('IDENTITY-LINKS.HEADER.USER-ID')])\n   .then(function(headers) {\n        // Config for variable grid\n        $scope.identityLinkGridDefinitions = {\n            data: 'identityLinks.data',\n            enableRowReordering: false,\n            multiSelect: false,\n            keepLastSelected : false,\n            enableSorting: false,\n            rowHeight: 36,\n            columnDefs: [\n                { field: 'type', displayName: headers[0]},\n                { field: 'groupId', displayName: headers[1], cellTemplate: gridConstants.defaultTemplate},\n                { field: 'userId', displayName: headers[2], cellTemplate: gridConstants.defaultTemplate}\n            ]\n        };\n   });\n\n\n        $scope.showAllSubtasks = function() {\n        \t// Populate the task-filter with parentId\n        \t$rootScope.filters.forced.taskFilter = {\n        \t\tparentTaskId: $scope.task.id\n        \t};\n\n        \t$scope.returnToList();\n        };\n\n\t\t$scope.loadSubTasks = function() {\n\t\t\t$scope.subTasks = undefined;\n\t\t\t$http({method: 'GET', url: FlowableAdmin.webContextRoot + '/app/rest/admin/tasks/' + $scope.task.id +'/subtasks'}).\n\t\t\tsuccess(function(data, status, headers, config) {\n\t\t\t\t$scope.subTasks = data;\n\t\t\t\t$scope.tabData.tabs[0].info = data.total;\n\t\t\t});\n\t\t};\n\n\t\t$scope.loadVariables = function() {\n\t\t\t$scope.variables = undefined;\n\t\t\t$http({method: 'GET', url: FlowableAdmin.webContextRoot + '/app/rest/admin/tasks/' + $scope.task.id +'/variables'}).\n\t\t\tsuccess(function(data, status, headers, config) {\n\t\t\t\t$scope.variables = data;\n\t\t\t\t$scope.tabData.tabs[1].info = data.total;\n\t\t\t});\n\t\t};\n\n\t\t$scope.loadIdentityLinks = function() {\n\t\t\t$scope.identityLinks = undefined;\n\t\t\t$http({method: 'GET', url: FlowableAdmin.webContextRoot + '/app/rest/admin/tasks/' + $scope.task.id +'/identitylinks'}).\n\t\t\tsuccess(function(data, status, headers, config) {\n\t\t\t\t$scope.identityLinks = {data: data, size: data.length};\n\t\t\t\t$scope.tabData.tabs[2].info = data.length;\n\t\t\t});\n\t\t};\n\t\t\n\t\t$scope.showTaskForm = function() {\n\t\t    if($scope.task.endTime) {\n\t\t        $http({method: 'GET', url: FlowableAdmin.webContextRoot + '/app/rest/admin/task-form-instance/' + $scope.task.id}).\n\t            success(function(data, status, headers, config) {\n\t                $rootScope.submittedForm = data.data[0]; // saving fetched submitted form in root scope to avoid another fetch in submitted form controller\n\t                $location.path(\"/form-instance/\" + data.data[0].id);\n\t            });\n\t\t    }\n\t\t};\n\n\t\t// Initial load of task\n\n\t\t$scope.executeWhenReady(function() {\n      $scope.loadTask();\n    });\n\n\n\t\t// Dialogs\n\t\tvar resolve = {\n\t\t\t// Reference the current task\n\t\t\ttask: function () {\n\t          return $scope.task;\n\t        }\n\t\t};\n\n\t\t$scope.deleteTask = function() {\n\t\t\tvar modalInstance = $modal.open({\n\t\t\t\ttemplateUrl: 'views/task-delete-popup.html',\n\t\t\t\tcontroller: 'DeleteTaskModalInstanceCtrl',\n\t\t\t\tresolve: resolve\n\t\t\t});\n\n\t\t\tmodalInstance.result.then(function (deleteTask) {\n\t\t\t\tif(deleteTask) {\n\t\t\t\t  $scope.addAlert($translate.instant('ALERT.TASK.DELETED', $scope.task), 'info');\n\t\t\t\t\t$scope.returnToList();\n\t\t\t\t}\n\t\t\t});\n\t\t};\n\n\t\t$scope.completeTask = function() {\n\t\t\tvar modalInstance = $modal.open({\n\t\t\t\ttemplateUrl: 'views/task-complete-popup.html',\n\t\t\t\tcontroller: 'CompleteModalInstanceCtrl',\n\t\t\t\tresolve: resolve\n\t\t\t});\n\n\t\t\tmodalInstance.result.then(function (completeTask) {\n\t\t\t\tif(completeTask) {\n\t\t\t\t  $scope.addAlert($translate.instant('ALERT.TASK.COMPLETED', $scope.task), 'info');\n\t\t\t\t\t$scope.loadTask();\n\t\t\t\t}\n\t\t\t});\n\t\t};\n\n\t\t$scope.delegateTask = function() {\n\t\t\tvar modalInstance = $modal.open({\n\t\t\t\ttemplateUrl: 'views/task-delegate-popup.html',\n\t\t\t\tcontroller: 'DelegateModalInstanceCtrl',\n\t\t\t\tresolve: resolve\n\t\t\t});\n\n\t\t\tmodalInstance.result.then(function (user) {\n\t\t\t\tif(user) {\n\t\t\t\t\t$scope.addAlert($translate.instant('ALERT.TASK.DELEGATED', {id: $scope.task.id, user: user}), 'info');\n\t\t\t\t\t$scope.loadTask();\n\t\t\t\t}\n\t\t\t});\n\t\t};\n\n\t\t$scope.resolveTask = function() {\n\t\t\tvar modalInstance = $modal.open({\n\t\t\t\ttemplateUrl: 'views/task-resolve-popup.html',\n\t\t\t\tcontroller: 'ResolveTaskModalInstanceCtrl',\n\t\t\t\tresolve: resolve\n\t\t\t});\n\n\t\t\tmodalInstance.result.then(function (user) {\n\t\t\t\tif(user) {\n\t\t\t\t  $scope.addAlert($translate.instant('ALERT.TASK.RESOLVED', $scope.task), 'info');\n\t\t\t\t\t$scope.loadTask();\n\t\t\t\t}\n\t\t\t});\n\t\t};\n\n\t\t$scope.assignTask = function() {\n\t\t\tvar modalInstance = $modal.open({\n\t\t\t\ttemplateUrl: 'views/task-assign-popup.html',\n\t\t\t\tcontroller: 'AssignModalInstanceCtrl',\n\t\t\t\tresolve: resolve\n\t\t\t});\n\n\t\t\tmodalInstance.result.then(function (user) {\n\t\t\t\tif(user !== undefined) {\n\t\t\t\t\tif(user == '') {\n\t\t\t\t\t\t$scope.addAlert($translate.instant('ALERT.TASK.UNASSIGNED', $scope.task), 'info');\n\t\t\t\t\t} else {\n\t\t\t\t\t  $scope.addAlert($translate.instant('ALERT.TASK.ASSIGNED', {id: $scope.task.id, user: user}), 'info');\n\t\t\t\t\t}\n\t\t\t\t\t$scope.loadTask();\n\t\t\t\t}\n\t\t\t});\n\t\t};\n\n\t\t$scope.editTask = function() {\n\t\t\tvar modalInstance = $modal.open({\n\t\t\t\ttemplateUrl: 'views/task-edit-popup.html',\n\t\t\t\tcontroller: 'EditTaskModalInstanceCtrl',\n\t\t\t\tresolve: resolve\n\t\t\t});\n\n\t\t\tmodalInstance.result.then(function (taskUpdated) {\n\t\t\t\tif(taskUpdated) {\n\t\t\t\t  $scope.addAlert($translate.instant('ALERT.TASK.UPDATED', $scope.task), 'info');\n\t\t\t\t\t$scope.loadTask();\n\t\t\t\t}\n\t\t\t});\n\t\t};\n}]);\n\n\n// Popup controllers\nflowableAdminApp.controller('CompleteModalInstanceCtrl',\n    ['$rootScope', '$scope', '$modalInstance', '$http', 'task', function ($rootScope, $scope, $modalInstance, $http, task) {\n\n  $scope.task = task;\n  $scope.status = {loading: false};\n\n  $scope.ok = function () {\n\t  $scope.status.loading = true;\n\t  $http({method: 'POST', url: FlowableAdmin.webContextRoot + '/app/rest/admin/tasks/' + $scope.task.id, data: {action: 'complete'}}).\n  \t  success(function(data, status, headers, config) {\n  \t\t$modalInstance.close(true);\n  \t\t$scope.status.loading = false;\n      }).error(function(data, status, headers, config) {\n    \t $modalInstance.close(false);\n    \t $scope.status.loading = false;\n      });\n  };\n\n  $scope.cancel = function () {\n\t  if(!$scope.status.loading) {\n\t\t$modalInstance.dismiss('cancel');\n\t}\n  };\n}]);\n\nflowableAdminApp.controller('ResolveTaskModalInstanceCtrl',\n    ['$rootScope', '$scope', '$modalInstance', '$http', 'task', function ($rootScope, $scope, $modalInstance, $http, task) {\n\n  $scope.task = task;\n  $scope.status = {loading: false};\n\n  $scope.ok = function () {\n\t  $scope.status.loading = true;\n\t  $http({method: 'POST', url: FlowableAdmin.webContextRoot + '/app/rest/admin/tasks/' + $scope.task.id, data: {action: 'resolve'}}).\n  \t  success(function(data, status, headers, config) {\n  \t\t$modalInstance.close(true);\n  \t\t$scope.status.loading = false;\n      }).error(function(data, status, headers, config) {\n    \t $modalInstance.close(false);\n    \t $scope.status.loading = false;\n      });\n  };\n\n  $scope.cancel = function () {\n\t  if(!$scope.status.loading) {\n\t\t$modalInstance.dismiss('cancel');\n\t}\n  };\n}]);\n\nflowableAdminApp.controller('DeleteTaskModalInstanceCtrl',\n    ['$rootScope', '$scope', '$modalInstance', '$http', 'task', function ($rootScope, $scope, $modalInstance, $http, task) {\n\n  $scope.task = task;\n  $scope.status = {loading: false};\n\n\n  $scope.ok = function () {\n\t  $scope.status.loading = true;\n\t  $http({method: 'DELETE', url: FlowableAdmin.webContextRoot + '/app/rest/admin/tasks/' + $scope.task.id}).\n    \tsuccess(function(data, status, headers, config) {\n    \t\t$modalInstance.close(true);\n\t  \t\t$scope.status.loading = false;\n        }).\n        error(function(data, status, headers, config) {\n        \t$modalInstance.close(false);\n\t    \t $scope.status.loading = false;\n        });\n  };\n\n  $scope.cancel = function () {\n\tif(!$scope.status.loading) {\n\t\t$modalInstance.dismiss('cancel');\n\t}\n  };\n}]);\n\n\nflowableAdminApp.controller('DelegateModalInstanceCtrl',\n    ['$rootScope', '$scope', '$modalInstance', '$http', 'task', function ($rootScope, $scope, $modalInstance, $http, task) {\n\n  $scope.task = task;\n  $scope.status = {loading: false};\n\n  $scope.ok = function () {\n\t  $scope.status.loading = true;\n\t  $http({method: 'POST', url: FlowableAdmin.webContextRoot + '/app/rest/admin/tasks/' + $scope.task.id, data: {action: 'delegate', assignee: $scope.status.user}}).\n  \t  success(function(data, status, headers, config) {\n  \t    if ($scope.newAssignee && $scope.newAssignee.name) {\n  \t      $modalInstance.close($scope.newAssignee.name);\n  \t    } else {\n  \t      $modalInstance.close($scope.status.user);\n  \t    }\n  \t\t$scope.status.loading = false;\n      }).error(function(data, status, headers, config) {\n    \t $modalInstance.close(false);\n    \t $scope.status.loading = false;\n      });\n  };\n\n  $scope.cancel = function () {\n\tif(!$scope.status.loading) {\n\t\t$modalInstance.dismiss('cancel');\n\t}\n  };\n}]);\n\nflowableAdminApp.controller('AssignModalInstanceCtrl',\n    ['$rootScope', '$scope', '$modalInstance', '$http', 'task', function ($rootScope, $scope, $modalInstance, $http, task) {\n\n\t  $scope.task = task;\n\t  $scope.status = {loading: false};\n\n\t  $scope.ok = function () {\n\t\t  $scope.status.loading = true;\n\t\t  var rawUserValue = $scope.status.user;\n\t\t  var resultUserValue = $scope.status.user;\n\t\t  if(!$scope.status.user) {\n\t\t\t  rawUserValue = null;\n\t\t\t  resultUserValue = '';\n\t\t  } else if ($scope.newAssignee && $scope.newAssignee.name) {\n\t\t      resultUserValue = $scope.newAssignee.name;\n\t\t  }\n\t\t  $http({method: 'PUT', url: FlowableAdmin.webContextRoot + '/app/rest/admin/tasks/' + $scope.task.id, data: {assignee: rawUserValue}}).\n\t  \t  success(function(data, status, headers, config) {\n\t  \t\t$modalInstance.close(resultUserValue);\n\t  \t\t$scope.status.loading = false;\n\t      }).error(function(data, status, headers, config) {\n\t    \t $modalInstance.close(false);\n\t    \t $scope.status.loading = false;\n\t      });\n\t  };\n\n\t  $scope.cancel = function () {\n\t\tif(!$scope.status.loading) {\n\t\t\t$modalInstance.dismiss('cancel');\n\t\t}\n\t  };\n\t}]);\n\nflowableAdminApp.controller('EditTaskModalInstanceCtrl',\n    ['$rootScope', '$scope', '$modalInstance', '$http', 'task', function ($rootScope, $scope, $modalInstance, $http, task) {\n\n      $scope.task = task;\n\t  $scope.model = {\n\t\t\t  name: task.name,\n\t\t\t  description: task.description,\n\t\t\t  owner: task.owner,\n\t\t\t  assignee: task.assignee,\n\t\t\t  dueDate: task.dueDate,\n\t\t\t  priority: task.priority,\n\t\t\t  category: task.category\n\t  };\n\n\t  $scope.status = {loading: false};\n\n\t  $scope.ok = function () {\n\t\t  $scope.status.loading = true;\n\t\t  $http({method: 'PUT', url: FlowableAdmin.webContextRoot + '/app/rest/admin/tasks/' + $scope.task.id, data: $scope.model}).\n\t  \t  success(function(data, status, headers, config) {\n\t  \t\t$modalInstance.close(true);\n\t  \t\t$scope.status.loading = false;\n\t      }).error(function(data, status, headers, config) {\n\t    \t $modalInstance.close(false);\n\t    \t $scope.status.loading = false;\n\t      });\n\t  };\n\n\t  $scope.cancel = function () {\n\t\tif(!$scope.status.loading) {\n\t\t\t$modalInstance.dismiss('cancel');\n\t\t}\n\t  };\n\t}]);\n"
  },
  {
    "path": "flowable-ui-web/admin/scripts/tasks-controllers.js",
    "content": "/* Copyright 2005-2015 Alfresco Software, Ltd.\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'use strict';\n\n/* Controllers */\n\nflowableAdminApp.controller('TasksController', ['$scope', '$rootScope', '$http', '$timeout','$location','$translate', '$q', 'gridConstants',\n    function ($scope, $rootScope, $http, $timeout, $location, $translate, $q, gridConstants) {\n\t\t$rootScope.navigation = {main: 'process-engine', sub: 'tasks'};\n        \n\t\t$scope.taskData = {};\n\t\t$scope.selectedTasks = [];\n\t  \n\t\t$scope.variableFilterTypes = FlowableAdmin.Utils.variableFilterTypes;\n\t\t$scope.variableFilterOperators = FlowableAdmin.Utils.variableFilterOperators;\n\n\t    var filterConfig = {\n\t\t    \turl: FlowableAdmin.webContextRoot + '/app/rest/admin/tasks',\n\t\t    \tmethod: 'POST',\n\t\t    \tsuccess: function(data, status, headers, config) {\n\t                $scope.taskData = data;\n\t            },\n\t            error: function(data, status, headers, config) {\n\t                if (data && data.message) {\n\t                    // Extract error-message\n\t                    $rootScope.addAlert(data.message, 'error');\n\t                } else {\n\t                    // Use default error-message\n\t                    $rootScope.addAlert($translate.instant('ALERT.GENERAL.HTTP-ERROR'), 'error');\n\t                }\n\t            },\n\t            \n\t            sortObjects: [\n\t                {name: 'TASKS.SORT.NAME', id: 'name'},\n\t                {name: 'TASKS.SORT.DUE-DATE', id: 'dueDate'},\n\t                {name: 'TASKS.SORT.START-TIME', id: 'start'},\n\t                {name: 'TASKS.SORT.END-TIME', id: 'endTime'},\n\t                {name: 'TASKS.SORT.PRIORITY', id: 'priority'}\n\t            ],\n\t            \n\t            options: {\n\t            \tfinished: [\n\t                 \t{name: 'TASKS.FILTER.STATUS-ANY', value: ''},\n\t                 \t{name: 'TASKS.FILTER.STATUS-ACTIVE', value: 'false'},\n\t                 \t{name: 'TASKS.FILTER.STATUS-COMPLETE', value: 'true'}\n\t                ]\n\t            },\n\t            \n\t            supportedProperties: [\n\t                {id: 'finished', name: 'TASKS.FILTER.FINISHED', showByDefault: true},\n\t                {id: 'taskNameLike', name: 'TASKS.FILTER.NAME', showByDefault: true},\n\t                {id: 'taskAssignee', name: 'TASKS.FILTER.ASSIGNEE', showByDefault: true},\n\t                {id: 'taskOwner', name: 'TASKS.FILTER.OWNER'},\n\t                {id: 'parentTaskId', name: 'TASKS.FILTER.PARENT-TASK-ID'},\n\t                {id: 'processInstanceId', name: 'TASKS.FILTER.PROCESS-INSTANCE-ID'},\n\t                {id: 'tenantIdLike', name: 'TASKS.FILTER.TENANT-ID'},\n\t                {id: 'dueBefore', name: 'TASKS.FILTER.DUE-BEFORE'},\n\t                {id: 'dueAfter', name: 'TASKS.FILTER.DUE-AFTER'},\n\t                {id: 'taskCreatedBefore', name: 'TASKS.FILTER.CREATED-BEFORE'},\n\t                {id: 'taskCreatedAfter', name: 'TASKS.FILTER.CREATED-AFTER'},\n\t                {id: 'taskCompletedBefore', name: 'TASKS.FILTER.ENDED-BEFORE'},\n\t                {id: 'taskCompletedAfter', name: 'TASKS.FILTER.ENDED-AFTER'},\n\t                {id: 'processVariables', name: 'TASKS.FILTER.PROCESS-VARIABLE'},\n\t                {id: 'taskVariables', name: 'TASKS.FILTER.TASK-VARIABLE'}\n\t            ]\n\t\t    };\n\n\t    if($rootScope.filters.forced.taskFilter) {\n\t    \t// Always recreate the filter and add all properties\n\t    \t$scope.filter = new FlowableAdmin.Utils.Filter(filterConfig, $http, $timeout, $rootScope);\n    \t\t$rootScope.filters.taskFilter = $scope.filter;\n    \t\t\n    \t\tfor(var prop in $rootScope.filters.forced.taskFilter) {\n    \t\t\t$scope.filter.addProperty({id: prop}, $rootScope.filters.forced.taskFilter[prop]);\n    \t\t}\n    \t\t\n    \t\t$rootScope.filters.forced.taskFilter = undefined;\n    \t\t\n\t    } else {\n\t    \tif($rootScope.filters && $rootScope.filters.taskFilter) {\n\t    \t\t// Reuse the existing filter\n\t    \t\t$scope.filter = $rootScope.filters.taskFilter;\n\t    \t\t$scope.filter.config = filterConfig;\n\t    \t} else {\n\t    \t\t$scope.filter = new FlowableAdmin.Utils.Filter(filterConfig, $http, $timeout, $rootScope);\n\t    \t\t$rootScope.filters.taskFilter = $scope.filter;\n\t    \t}\n\t    }\n\t    \n\t    if(!$scope.filter.properties.processvariables) {\n        $scope.filter.properties.processVariables = [];\n        $scope.filter.properties.taskVariables = [];\n      }\n      \n      // Set value-filter callback to convert variables to nice format\n      $scope.filter.config.valueFilter = function(prop, value) {\n        if(prop == 'processVariables' || prop == 'taskVariables') {\n          var actualValue = [];\n          var variable;\n          for(var i=0; i<value.length; i++) {\n            variable = value[i];\n            \n            if(variable.name && variable.type && variable.value !== undefined && variable.value !== '' && variable.operator) {\n              var varPayload =  {\n                  name: variable.name,\n                  value: variable.value,\n                  operation: variable.operator.id,\n                  type: variable.type.id\n              };\n              \n              if(variable.type.id == 'long' || variable.type.id == 'short' || variable.type.id == 'double' || variable.type.id == 'integer') {\n                varPayload.value = parseFloat(varPayload.value);\n                if(!isNaN(varPayload.value)) {\n                  // Return valid value for number\n                  actualValue.push(varPayload);\n                }\n              } else {\n                // Return valid value\n                actualValue.push(varPayload);\n              }\n            }\n          }\n          return actualValue;\n        } else {\n          return value;\n        }\n      };\n      \n      $scope.clearFilters = function() {\n        $scope.filter.clear();\n        $scope.filter.properties.processVariables = [];\n        $scope.filter.properties.taskVariables = [];\n      };\n      \n      $scope.setVariableFilterType = function(varFilter, type) {\n        \n        varFilter.value = undefined;\n        if(type.id == 'boolean') {\n          varFilter.value = true;\n          \n          if(varFilter.operator.id != 'equals') {\n            varFilter.operator = $scope.variableFilterOperators[0];\n          }\n        }\n        \n        varFilter.type = type;\n        $scope.highlightVariableValue(varFilter);\n        $scope.filter.refresh();\n      };\n      \n      $scope.setVariableFilterOperator = function(varFilter, operator) {\n        if(operator.id == 'like') {\n          varFilter.value = '';\n          varFilter.type = $scope.variableFilterTypes[0];\n        }\n        \n        if(varFilter.type.id == 'boolean' && operator.id != 'equals') {\n          varFilter.operator = $scope.variableFilterOperators[0];\n        } else {\n          varFilter.operator = operator;\n        }\n        $scope.highlightVariableValue(varFilter);\n        $scope.filter.refresh();\n      };\n      \n      $scope.highlightVariableValue = function(varFilter) {\n        var index = -1;\n        for(var i=0; i<$scope.filter.properties[varFilter.scope].length; i++) {\n          if(varFilter == $scope.filter.properties[varFilter.scope][i]) {\n            index = i;\n            break;\n          }\n        }\n        \n        $timeout(function() {\n          var formField = $('#filter-' + varFilter.scope + '-value-' + index);\n          formField.focus();\n        }, 100);\n      };\n      \n      $scope.addFilterProperty = function(prop) {\n        \n        if(prop.id != 'taskVariables' && prop.id != 'processVariables') {\n          $scope.filter.addProperty(prop);\n        } else {\n          // Add additional variable\n          $scope.filter.properties[prop.id].push({\n            type: $scope.variableFilterTypes[0],\n            operator: $scope.variableFilterOperators[0],\n            scope: prop.id\n          });\n          \n          $timeout(function() {\n            var formField = $('#filter-' + prop.id + '-name-' + ($scope.filter.properties[prop.id].length - 1));\n            formField.focus();\n          }, 100);\n        }\n      };\n\t    \n\t    $scope.taskSelected = function(task) {\n\t    \tif(task && task.getProperty('id')) {\n\t    \t\t$location.path('/task/' + task.getProperty('id'));\n\t    \t}\n\t    };\n\t    \n\t    $q.all([$translate('TASKS.HEADER.ID'), \n\t            $translate('TASKS.HEADER.NAME'),\n\t            $translate('TASKS.HEADER.ASSIGNEE'),\n\t            $translate('TASKS.HEADER.OWNER'),\n\t            $translate('TASKS.HEADER.CREATE-TIME'),\n\t            $translate('TASKS.HEADER.END-TIME'),\n\t            $translate('TASKS.HEADER.PRIORITY')])\n\t    .then(function(headers) { \n\n          $scope.gridDefinitions = {\n              data: 'taskData.data',\n              enableRowReordering: true,\n              multiSelect: false,\n              keepLastSelected : false,\n              enableSorting: false,\n              rowHeight: 36,\n              afterSelectionChange: $scope.taskSelected,\n              columnDefs: [{ field: 'id', displayName: headers[0], width: 50, cellTemplate: gridConstants.defaultTemplate},\n                  { field: 'name', displayName: headers[1], cellTemplate: gridConstants.defaultTemplate},\n                  { field: 'assignee', displayName: headers[2], width: 150, cellTemplate: gridConstants.defaultTemplate},\n                  { field: 'owner', displayName: headers[3], width: 150, cellTemplate: gridConstants.defaultTemplate},\n                  { field: 'startTime', displayName: headers[4], cellTemplate: gridConstants.dateTemplate},\n                  { field: 'endTime', displayName: headers[5], cellTemplate: gridConstants.dateTemplate},\n                  { field: 'priority', displayName: headers[6], cellTemplate: gridConstants.defaultTemplate}\n              ]\n          };\n\t    });\n        \n        // Task state filtering\n        $scope.getTaskStateLabel = function(value) {\n        \tfor(var i=0; i<$scope.filter.config.taskStates.length; i++) {\n        \t\tvar state = $scope.filter.config.taskStates[i];\n        \t\tif(value == state.value) {\n        \t\t\treturn state.name;\n        \t\t}\n        \t}\n        \treturn $scope.filter.config.taskStates[0].name;\n        };\n        \n        $scope.setStateFilter = function(state) {\n        \tif(state.value !== $scope.filter.properties.finished) {\n        \t\t$scope.filter.properties.finished = state.value;\n        \t\t$scope.filter.refresh();\n        \t}\n        };\n        \n        $scope.executeWhenReady(function() {\n          $scope.filter.refresh();\n        });\n    }]);\n"
  },
  {
    "path": "flowable-ui-web/admin/scripts/users-controllers.js",
    "content": "/* Copyright 2005-2015 Alfresco Software, Ltd.\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'use strict';\n\n/* Controllers */\n\nflowableAdminApp.controller('UsersController', ['$scope', '$rootScope', '$http', '$timeout','$location', '$modal', '$translate', '$q',\n    function ($scope, $rootScope, $http, $timeout, $location, $modal, $translate, $q) {\n\t\t$rootScope.navigation = {selection: 'users'};\n\t\t\n\t\t$scope.selectedUsers = [];\n\n\t    $q.all([$translate('USERS.HEADER.LOGIN'),\n              $translate('USERS.HEADER.FIRSTNAME'),\n              $translate('USERS.HEADER.LASTNAME'),\n              $translate('USERS.HEADER.EMAIL'),\n              $translate('USERS.HEADER.CLUSTER_USER')])\n              .then(function(headers) {\n\n                  // Config for grid\n                  $scope.gridUsers = {\n                      data: 'usersData',\n                      enableRowReordering: true,\n                      multiSelect: false,\n                      keepLastSelected : false,\n                      enableSorting: false,\n                      rowHeight: 36,\n                      selectedItems: $scope.selectedUsers,\n                      columnDefs: [{ field: 'login', displayName: headers[0]},\n                          { field: 'firstName', displayName: headers[1]},\n                          { field: 'lastName', displayName: headers[2]},\n                          { field: 'email', displayName: headers[3]},\n                          { field: 'isClusterUser', displayName: headers[4]}\n                      ]\n                  };\n        });\n\n        $scope.loadUsers = function() {\n        \t$http({method: 'GET', url: FlowableAdmin.webContextRoot + '/app/rest/users'}).\n\t\t        success(function(data, status, headers, config) {\n\t\t        \t$scope.usersData = data;\n\n\t\t        \t// Indicate if the user is used for sending events\n\t\t        \tif($scope.usersData !== null && $scope.usersData !== undefined) {\n\t\t        \t    for (var userIndex = 0; userIndex < $scope.usersData.length; userIndex++) {\n\t\t        \t        var userData = $scope.usersData[userIndex];\n\t\t        \t        userData.isClusterUser = userData.clusterUser ? $translate.instant('GENERAL.YES') : $translate.instant('GENERAL.NO');\n\t\t        \t    }\n\t\t        \t}\n\n\t\t        }).\n\t\t        error(function(data, status, headers, config) {\n\t\t            console.log('Something went wrong when fetching users');\n\t\t        });\n        };\n\n        $scope.executeWhenReady(function() {\n            $scope.loadUsers();\n        });\n\n        // Dialogs\n\t\tvar resolve = {\n\t\t\t// Reference the current task\n\t\t\tuser: function () {\n\t\t\t    return $scope.selectedUsers[0];\n\t        }\n\t\t};\n\n\t\t$scope.deleteUser = function() {\n\t\t\tvar modalInstance = $modal.open({\n\t\t\t\ttemplateUrl: 'views/user-delete-popup.html',\n\t\t\t\tcontroller: 'DeleteUserModalInstanceCtrl',\n\t\t\t\tresolve: resolve\n\t\t\t});\n\n\t\t\tmodalInstance.result.then(function (deleteUser) {\n\t\t\t\tif (deleteUser) {\n\t\t\t\t    $scope.addAlert($translate.instant('ALERT.USER.DELETED', $scope.selectedUsers[0]), 'info');\n\n\t\t\t\t    // Clear selection after delete, or actions will still point to deleted user\n\t\t\t\t    $scope.selectedUsers.splice(0,1);\n\t\t\t\t    $scope.loadUsers();\n\t\t\t\t}\n\t\t\t});\n\t\t};\n\n\t\t$scope.editUser = function() {\n\t\t\tvar modalInstance = $modal.open({\n\t\t\t\ttemplateUrl: 'views/user-edit-popup.html',\n\t\t\t\tcontroller: 'EditUserModalInstanceCtrl',\n\t\t\t\tresolve: resolve\n\t\t\t});\n\n\t\t\tmodalInstance.result.then(function (userUpdated) {\n\t\t\t\tif (userUpdated) {\n\t\t\t\t  $scope.addAlert($translate.instant('ALERT.USER.UPDATED', $scope.selectedUsers[0]), 'info');\n\t\t\t\t\t$scope.loadUsers();\n\t\t\t\t}\n\t\t\t});\n\t\t};\n\n\t\t$scope.changePassword = function() {\n\t\t\tvar modalInstance = $modal.open({\n\t\t\t\ttemplateUrl: 'views/user-change-password-popup.html',\n\t\t\t\tcontroller: 'ChangePasswordModalInstanceCtrl',\n\t\t\t\tresolve: resolve\n\t\t\t});\n\n\t\t\tmodalInstance.result.then(function (userUpdated) {\n\t\t\t\tif (userUpdated) {\n\t\t\t\t  $scope.addAlert($translate.instant('ALERT.USER.PASSWORD-CHANGED', $scope.selectedUsers[0]), 'info');\n\t\t\t\t}\n\t\t\t});\n\t\t};\n\n\t\t$scope.newUser = function() {\n\t\t\tvar modalInstance = $modal.open({\n\t\t\t\ttemplateUrl: 'views/user-new-popup.html',\n\t\t\t\tcontroller: 'NewUserModalInstanceCtrl',\n\t\t\t\tresolve: resolve\n\t\t\t});\n\n\t\t\tmodalInstance.result.then(function (userCreated) {\n\t\t\t\tif (userCreated) {\n\t\t\t\t  $scope.addAlert($translate.instant('ALERT.USER.CREATED', userCreated), 'info');\n\t\t\t\t\t$scope.loadUsers();\n\t\t\t\t}\n\t\t\t});\n\t\t};\n    }]);\n\nflowableAdminApp.controller('DeleteUserModalInstanceCtrl',\n    ['$scope', '$modalInstance', '$http', 'user', function ($scope, $modalInstance, $http, user) {\n\n  $scope.user = user;\n  $scope.status = {loading: false};\n\n  $scope.ok = function () {\n\t  $scope.status.loading = true;\n\t  $http({method: 'DELETE', url: FlowableAdmin.webContextRoot + '/app/rest/users/' + $scope.user.login}).\n    \tsuccess(function(data, status, headers, config) {\n    \t\t$modalInstance.close(true);\n\t  \t\t$scope.status.loading = false;\n        }).\n        error(function(data, status, headers, config) {\n        \t$modalInstance.close(false);\n        \t$scope.status.loading = false;\n        });\n  };\n\n  $scope.cancel = function () {\n\tif(!$scope.status.loading) {\n\t\t$modalInstance.dismiss('cancel');\n\t}\n  };\n}]);\n\nflowableAdminApp.controller('EditUserModalInstanceCtrl',\n    ['$scope', '$modalInstance', '$http', 'user', function ($scope, $modalInstance, $http, user) {\n\n  $scope.user = user;\n  $scope.model = {\n\t\t  login: user.login,\n\t\t  firstName: user.firstName,\n\t\t  lastName: user.lastName,\n\t\t  email: user.email\n  };\n\n  $scope.status = {loading: false};\n\n  $scope.ok = function () {\n\t  $scope.status.loading = true;\n\t  $http({method: 'PUT', url: FlowableAdmin.webContextRoot + '/app/rest/users/' + $scope.user.login, data: $scope.model}).\n  \t  success(function(data, status, headers, config) {\n  \t\t  $modalInstance.close(true);\n  \t\t  $scope.status.loading = false;\n      }).error(function(data, status, headers, config) {\n          $scope.status.loading = false;\n\n          if(data.message) {\n            $scope.model.errorMessage = data.message;\n          }\n      });\n  };\n\n  $scope.cancel = function () {\n\tif(!$scope.status.loading) {\n\t\t$modalInstance.dismiss('cancel');\n\t}\n  };\n}]);\n\nflowableAdminApp.controller('ChangePasswordModalInstanceCtrl',\n    ['$scope', '$modalInstance', '$http', 'user', function ($scope, $modalInstance, $http, user) {\n\n\t  $scope.user = user;\n\t  $scope.model = {\n\t\t\t  oldPassword: '',\n\t\t\t  newPassword: ''\n\t  };\n\n\t  $scope.status = {loading: false};\n\n\t  $scope.ok = function () {\n\t\t  $scope.status.loading = true;\n\t\t  $http({method: 'PUT', url: FlowableAdmin.webContextRoot + '/app/rest/users/' + $scope.user.login + '/change-password', data: $scope.model}).\n\t  \t  success(function(data, status, headers, config) {\n\t  \t\t  $modalInstance.close(true);\n\t  \t\t  $scope.status.loading = false;\n\t      }).error(function(data, status, headers, config) {\n\t        $scope.status.loading = false;\n\n\t        if(data.message) {\n\t          $scope.model.errorMessage = data.message;\n\t        }\n\t      });\n\t  };\n\n\t  $scope.cancel = function () {\n\t\tif(!$scope.status.loading) {\n\t\t\t$modalInstance.dismiss('cancel');\n\t\t}\n\t  };\n\t}]);\n\nflowableAdminApp.controller('NewUserModalInstanceCtrl',\n    ['$scope', '$modalInstance', '$http', function ($scope, $modalInstance, $http) {\n\n  $scope.model = {\n\t\t  login: '',\n\t\t  password: '',\n\t\t  firstName: '',\n\t\t  lastName: '',\n\t\t  email: ''\n  };\n\n  $scope.status = {loading: false};\n\n  $scope.ok = function () {\n\t  $scope.status.loading = true;\n\t  $http({method: 'POST', url: FlowableAdmin.webContextRoot + '/app/rest/users', data: $scope.model, ignoreErrors: true}).\n  \t  success(function(data, status, headers, config) {\n  \t\t  $modalInstance.close($scope.model);\n  \t\t  $scope.status.loading = false;\n      }).error(function(data, status, headers, config) {\n    \t  $scope.status.loading = false;\n\n    \t  if(data.message) {\n    \t    $scope.model.errorMessage = data.message;\n    \t  }\n      });\n  };\n\n  $scope.cancel = function () {\n\tif(!$scope.status.loading) {\n\t\t$modalInstance.dismiss('cancel');\n\t}\n  };\n}]);\n"
  },
  {
    "path": "flowable-ui-web/admin/scripts/utils.js",
    "content": "/* Copyright 2005-2015 Alfresco Software, Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n *\n * Utility objects and methods for the Flowable Admin app\n *\n */\nFlowableAdmin.Utils = {};\n\nFlowableAdmin.Utils.resetTimeToMorning = function(date) {\n\tdate.setUTCHours(0);\n\tdate.setUTCMinutes(0);\n\tdate.setUTCSeconds(0);\n\treturn date;\n};\n\nFlowableAdmin.Utils.resetTimeToEvening = function(date) {\n\tdate.setUTCHours(23);\n\tdate.setUTCMinutes(59);\n\tdate.setUTCSeconds(59);\n\treturn date;\n};\n\nFlowableAdmin.Utils.variableFilterTypes = [\n   {name: \"String\", id: \"string\"},\n   {name: \"Integer\", id: \"integer\"},\n   {name: \"Double\", id: \"double\"},\n   {name: \"Long\", id: \"long\"},\n   {name: \"Short\", id: \"short\"},\n   {name: \"Boolean\", id: \"boolean\"},\n   {name: \"Date\", id: \"date\"}\n];\n\nFlowableAdmin.Utils.variableFilterOperators = [\n    {sign: \"=\", id: \"equals\", name: \"Equals\"},\n    {sign: \"<>\", id: \"notEquals\", name: \"Not equals\"},\n    {sign: \"<\", id: \"lessThan\", name: \"Less than\" },\n    {sign: \"<=\", id: \"lessThanOrEquals\", name: \"Less than or equals\"},\n    {sign: \">\", id: \"greaterThan\", name: \"Greater than\" },\n    {sign: \">=\", id: \"greaterThanOrEquals\", name: \"Greater than or equals\" },\n    {sign: \"like\", id: \"like\", name: \"Like\"}\n];\n\n\n/**\n * FlowableAdmin.Utils.Filter\n *\n * Generic list filter implementation.\n */\nFlowableAdmin.Utils.Filter = function(config, $http, $timeout, $rootScope) {\n\tthis.init(config, $http, $timeout, $rootScope);\n};\n\nFlowableAdmin.Utils.Filter.prototype = {\n\n\tinit: function(config, $http, $timeout, $rootScope) {\n\t\tthis.order = FlowableAdmin.Config.filter.defaultOrder;\n\t\tthis.resultSize = FlowableAdmin.Config.filter.defaultResultSize;\n\t\tthis.$http = $http;\n\t\tthis.$timeout = $timeout;\n\t\tthis.$rootScope = $rootScope;\n\n\t\tthis.waiting = false;\n\t\tthis.delayed = false;\n\n\t\tthis.setConfig(config);\n\t\t// Initialize supported properties and defaults\n\t\tthis.properties = {};\n\t\tthis._initializeSupportedPropertiesFromConfig();\n\n\t\tthis.loading = false;\n\t\tthis.pendingReload = false;\n\t},\n\n\tsetConfig: function(config) {\n\t\tthis.config = config;\n\t\tthis.options = config.options;\n\n\t\tif(config.sortObjects !== undefined && config.sortObjects.length > 0) {\n\t\t\tthis.sortObjects = config.sortObjects;\n\t\t\tif(this.sort == undefined) {\n\t\t\t\tthis.sort = config.sortObjects[0];\n\t\t\t}\n\t\t}\n\t},\n\n\trefresh: function() {\n\t\t// Clear the pending reload flag, if needed\n\t\tthis.pendingReload = false;\n\n\t\tif(this.loading) {\n\t\t\tthis.pendingReload = true;\n\t\t} else {\n\t\t\tthis.loading = true;\n\t\t\tthis.$http(this._getHttpParameters()).\n\t    \t\tsuccess(this._success.bind(this)).\n\t    \t\terror(this._error.bind(this));\n\t\t}\n\t},\n\n\trefreshDelayed: function() {\n\t\t// If already waiting, another wait-cycle will be done\n\t\t// after the current wait is over\n\t\tif(this.waiting) {\n\t\t\tthis.delayed = true;\n\t\t} else {\n\t\t\tthis._scheduleDelayedRefresh();\n\t\t}\n\t},\n\n\tclear: function() {\n\t\t// Reset with initial values passed in commit\n\t\tthis.properties = {};\n\t\tthis._initializeSupportedPropertiesFromConfig();\n\n        if (this.processDefinition) {\n            delete this.processDefinition;\n        }\n\n\t\tthis.refresh();\n\t},\n\n\t_initializeSupportedPropertiesFromConfig: function() {\n\t\tthis.supportedProperties = [];\n\t\tif(this.config.supportedProperties) {\n\t\t\tfor(var i=0; i< this.config.supportedProperties.length; i++) {\n\t\t\t\tvar prop = this.config.supportedProperties[i];\n\t\t\t\tif(prop.showByDefault === true) {\n\t\t\t\t\tvar def = '';\n\t\t\t\t\tif(prop.defaultValue) {\n\t\t\t\t\t\tdef = prop.defaultValue;\n\t\t\t\t\t}\n\t\t\t\t\tthis.properties[prop.id] = def;\n\t\t\t\t} else {\n\t\t\t\t\t// Not shown by default, keep in supported properties array\n\t\t\t\t\tthis.supportedProperties.push(prop);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\n\n\t_scheduleDelayedRefresh: function() {\n\t\tthis.waiting = true;\n\n\t\tthis.$timeout((function() {\n\t\t\tthis.waiting = false;\n\t\t\tif(this.delayed) {\n\t\t\t\tthis.delayed = false;\n\t\t\t\t// Delay agian\n\t\t\t\tthis._scheduleDelayedRefresh();\n\t\t\t} else {\n\t\t\t\t// Actually do the refresh-call\n\t\t\t\tthis.refresh();\n\t\t\t}\n\t\t}).bind(this), FlowableAdmin.Config.filter.delay);\n\t},\n\n\t_success: function(data, status, headers, config) {\n\t\tthis.loading = false;\n\t\tif(this.config.success !== undefined) {\n\t\t\tthis.config.success(data, status, headers, config);\n\t\t}\n\n\t\t// In case a refresh-request came in when the current request was still going on, refresh after finished\n\t\tif(this.pendingReload) {\n\t\t\tthis.refresh();\n\t\t}\n\t},\n\n\t_error: function(data, status, headers, config) {\n\t\tthis.loading = false;\n\n\t\tif (this.config.error !== undefined) {\n\t\t\tthis.config.error(data, status, headers, config);\n\t\t}\n\n\t\t// In case a refresh-request came in when the current request was still going on, refresh after finished\n\t\tif (this.pendingReload) {\n\t\t\tthis.refresh();\n\t\t}\n\t},\n\n\tsetResultSize: function(resultSize) {\n    \tif(this.resultSize != resultSize) {\n    \t\tthis.resultSize = resultSize;\n    \t\tthis.refresh();\n    \t}\n\t},\n\n\tsetSort: function(sortObject) {\n\t\tthis.sort = sortObject;\n\t\tthis.refresh();\n\t},\n\n\ttoggleOrder: function() {\n\t\tif(this.order == 'asc') {\n\t\t\tthis.order = 'desc';\n\t\t} else {\n\t\t\tthis.order = 'asc';\n\t\t}\n\t\tthis.refresh();\n\t},\n\n\taddProperty: function(prop, value) {\n\t\tif(prop !== undefined) {\n\t\t\tif(!value) {\n\t\t\t\tvalue = '';\n\t\t\t}\n\t\t\tthis.properties[prop.id] = value;\n\n\t\t\tvar indexToRemove = -1;\n\t\t\t// Remove the property from the supported-properties list\n\t\t\tfor(var i=0; i<this.supportedProperties.length; i++) {\n\t\t\t\tvar supported = this.supportedProperties[i];\n\t\t\t\tif(supported.id == prop.id) {\n\t\t\t\t\tindexToRemove = i;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif(indexToRemove >= 0) {\n\t\t\t\tthis.supportedProperties.splice(indexToRemove, 1);\n\t\t\t}\n\n\t\t\t// Focus the newly added field\n\t\t\tthis.$timeout(function() {\n\t\t\t\tvar formField = $('#filter-' + prop.id);\n\t\t\t\tformField.focus();\n\t\t\t}, 100);\n\t\t}\n\t},\n\n\tremoveProperty: function(prop) {\n\t    if (prop !== undefined) {\n\t        delete this.properties[prop.id];\n\t    }\n\t},\n\n\t/**\n\t * Return the label that corresponds to a value selected in a set of filter-options.\n\t */\n\tgetLabelForOption: function(optionType) {\n\t\tvar options = this.options[optionType];\n\t\tif(options != undefined && options.length > 0) {\n\t\t\tfor(var i=0; i<options.length; i++) {\n\t\t\t\tvar option = options[i];\n\t\t\t\tif(this.properties[optionType] == option.value) {\n\t\t\t\t\treturn option.name;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn options[0].name;\n\t\t}\n\t\treturn \"???\";\n\t},\n\n\tselectOption: function(optionType, option) {\n\t\tvar currentValue = this.properties[optionType];\n\t\tif(currentValue != option.value) {\n\t\t\tthis.properties[optionType] = option.value;\n\t\t\tthis.refresh();\n\t\t}\n\t},\n\n\t/**\n\t * Return an object that can be used in a $http request. It contains all parameters\n\t * set in this filter including size, sort and order.\n\t */\n\t_getHttpParameters: function() {\n\t\tvar httpConfig = {};\n\t\thttpConfig.method = this.config.method,\n\t\thttpConfig.url = this.config.url;\n\n\t\t// Add size and sorting\n\t\tvar params = {\n\t\t\t\"size\": this.resultSize,\n\t\t\t\"order\": this.order\n\t\t};\n\t\tif(this.sort !== undefined) {\n\t\t\tparams.sort = this.sort.id;\n\t\t}\n\n\t\t// Add filter properties\n\t\tfor (var filter in this.properties) {\n\t\t\tif (this.properties[filter] !== undefined && this.properties[filter] !== '' && this.properties[filter] !== null) {\n\t\t\t\t// Special case for \"like\" filters, add wildcard\n\t\t\t\tif (filter.indexOf(\"Like\") > 0) {\n\t\t\t\t\tparams[filter] = \"%\" + this.properties[filter] + \"%\";\n\t\t\t\t} else {\n\t\t\t\t\tif (this.properties[filter].getMonth) {\n\t\t\t\t\t\t// Special handling for dates. Use correct format and reset time-component\n\t\t\t\t\t\tif (filter.indexOf(\"Before\") > 0) {\n\t\t\t\t\t\t\tFlowableAdmin.Utils.resetTimeToEvening(this.properties[filter]);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tFlowableAdmin.Utils.resetTimeToMorning(this.properties[filter]);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tparams[filter] = moment(this.properties[filter]).format(\"YYYY-MM-DDTHH:mm:ssZ\");\n\t\t\t\t\t} else {\n\t\t\t\t\t  // Normal value, pass it through the callback first, if any\n\t\t\t\t\t  var value = this.properties[filter];\n\t\t\t\t\t  if(this.config.valueFilter) {\n\t\t\t\t\t    value = this.config.valueFilter(filter, this.properties[filter]);\n\t\t\t\t\t  }\n\t\t\t\t\t\tparams[filter] = value;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif(httpConfig.method == 'POST' ) {\n\t\t\t// Populate JSON-body\n\t\t\thttpConfig.data = params;\n\t\t} else {\n\t\t\t// Populate query string\n\t\t\thttpConfig.params = params;\n\t\t}\n\t\treturn httpConfig;\n\t}\n\n};\n\n\n\n\n"
  },
  {
    "path": "flowable-ui-web/admin/styles/bootstrap-theme.css",
    "content": "/*!\n * Bootstrap v3.1.0 (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": "flowable-ui-web/admin/styles/bootstrap.css",
    "content": "/*!\n * Bootstrap v3.1.0 (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.428571429;\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  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.428571429;\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  list-style: none;\n}\n.list-inline > li {\n  display: inline-block;\n  padding-right: 5px;\n  padding-left: 5px;\n}\n.list-inline > li:first-child {\n  padding-left: 0;\n}\ndl {\n  margin-top: 0;\n  margin-bottom: 20px;\n}\ndt,\ndd {\n  line-height: 1.428571429;\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.428571429;\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.428571429;\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.428571429;\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.66666666666666%;\n}\n.col-xs-10 {\n  width: 83.33333333333334%;\n}\n.col-xs-9 {\n  width: 75%;\n}\n.col-xs-8 {\n  width: 66.66666666666666%;\n}\n.col-xs-7 {\n  width: 58.333333333333336%;\n}\n.col-xs-6 {\n  width: 50%;\n}\n.col-xs-5 {\n  width: 41.66666666666667%;\n}\n.col-xs-4 {\n  width: 33.33333333333333%;\n}\n.col-xs-3 {\n  width: 25%;\n}\n.col-xs-2 {\n  width: 16.666666666666664%;\n}\n.col-xs-1 {\n  width: 8.333333333333332%;\n}\n.col-xs-pull-12 {\n  right: 100%;\n}\n.col-xs-pull-11 {\n  right: 91.66666666666666%;\n}\n.col-xs-pull-10 {\n  right: 83.33333333333334%;\n}\n.col-xs-pull-9 {\n  right: 75%;\n}\n.col-xs-pull-8 {\n  right: 66.66666666666666%;\n}\n.col-xs-pull-7 {\n  right: 58.333333333333336%;\n}\n.col-xs-pull-6 {\n  right: 50%;\n}\n.col-xs-pull-5 {\n  right: 41.66666666666667%;\n}\n.col-xs-pull-4 {\n  right: 33.33333333333333%;\n}\n.col-xs-pull-3 {\n  right: 25%;\n}\n.col-xs-pull-2 {\n  right: 16.666666666666664%;\n}\n.col-xs-pull-1 {\n  right: 8.333333333333332%;\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.66666666666666%;\n}\n.col-xs-push-10 {\n  left: 83.33333333333334%;\n}\n.col-xs-push-9 {\n  left: 75%;\n}\n.col-xs-push-8 {\n  left: 66.66666666666666%;\n}\n.col-xs-push-7 {\n  left: 58.333333333333336%;\n}\n.col-xs-push-6 {\n  left: 50%;\n}\n.col-xs-push-5 {\n  left: 41.66666666666667%;\n}\n.col-xs-push-4 {\n  left: 33.33333333333333%;\n}\n.col-xs-push-3 {\n  left: 25%;\n}\n.col-xs-push-2 {\n  left: 16.666666666666664%;\n}\n.col-xs-push-1 {\n  left: 8.333333333333332%;\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.66666666666666%;\n}\n.col-xs-offset-10 {\n  margin-left: 83.33333333333334%;\n}\n.col-xs-offset-9 {\n  margin-left: 75%;\n}\n.col-xs-offset-8 {\n  margin-left: 66.66666666666666%;\n}\n.col-xs-offset-7 {\n  margin-left: 58.333333333333336%;\n}\n.col-xs-offset-6 {\n  margin-left: 50%;\n}\n.col-xs-offset-5 {\n  margin-left: 41.66666666666667%;\n}\n.col-xs-offset-4 {\n  margin-left: 33.33333333333333%;\n}\n.col-xs-offset-3 {\n  margin-left: 25%;\n}\n.col-xs-offset-2 {\n  margin-left: 16.666666666666664%;\n}\n.col-xs-offset-1 {\n  margin-left: 8.333333333333332%;\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.66666666666666%;\n  }\n  .col-sm-10 {\n    width: 83.33333333333334%;\n  }\n  .col-sm-9 {\n    width: 75%;\n  }\n  .col-sm-8 {\n    width: 66.66666666666666%;\n  }\n  .col-sm-7 {\n    width: 58.333333333333336%;\n  }\n  .col-sm-6 {\n    width: 50%;\n  }\n  .col-sm-5 {\n    width: 41.66666666666667%;\n  }\n  .col-sm-4 {\n    width: 33.33333333333333%;\n  }\n  .col-sm-3 {\n    width: 25%;\n  }\n  .col-sm-2 {\n    width: 16.666666666666664%;\n  }\n  .col-sm-1 {\n    width: 8.333333333333332%;\n  }\n  .col-sm-pull-12 {\n    right: 100%;\n  }\n  .col-sm-pull-11 {\n    right: 91.66666666666666%;\n  }\n  .col-sm-pull-10 {\n    right: 83.33333333333334%;\n  }\n  .col-sm-pull-9 {\n    right: 75%;\n  }\n  .col-sm-pull-8 {\n    right: 66.66666666666666%;\n  }\n  .col-sm-pull-7 {\n    right: 58.333333333333336%;\n  }\n  .col-sm-pull-6 {\n    right: 50%;\n  }\n  .col-sm-pull-5 {\n    right: 41.66666666666667%;\n  }\n  .col-sm-pull-4 {\n    right: 33.33333333333333%;\n  }\n  .col-sm-pull-3 {\n    right: 25%;\n  }\n  .col-sm-pull-2 {\n    right: 16.666666666666664%;\n  }\n  .col-sm-pull-1 {\n    right: 8.333333333333332%;\n  }\n  .col-sm-pull-0 {\n    right: 0;\n  }\n  .col-sm-push-12 {\n    left: 100%;\n  }\n  .col-sm-push-11 {\n    left: 91.66666666666666%;\n  }\n  .col-sm-push-10 {\n    left: 83.33333333333334%;\n  }\n  .col-sm-push-9 {\n    left: 75%;\n  }\n  .col-sm-push-8 {\n    left: 66.66666666666666%;\n  }\n  .col-sm-push-7 {\n    left: 58.333333333333336%;\n  }\n  .col-sm-push-6 {\n    left: 50%;\n  }\n  .col-sm-push-5 {\n    left: 41.66666666666667%;\n  }\n  .col-sm-push-4 {\n    left: 33.33333333333333%;\n  }\n  .col-sm-push-3 {\n    left: 25%;\n  }\n  .col-sm-push-2 {\n    left: 16.666666666666664%;\n  }\n  .col-sm-push-1 {\n    left: 8.333333333333332%;\n  }\n  .col-sm-push-0 {\n    left: 0;\n  }\n  .col-sm-offset-12 {\n    margin-left: 100%;\n  }\n  .col-sm-offset-11 {\n    margin-left: 91.66666666666666%;\n  }\n  .col-sm-offset-10 {\n    margin-left: 83.33333333333334%;\n  }\n  .col-sm-offset-9 {\n    margin-left: 75%;\n  }\n  .col-sm-offset-8 {\n    margin-left: 66.66666666666666%;\n  }\n  .col-sm-offset-7 {\n    margin-left: 58.333333333333336%;\n  }\n  .col-sm-offset-6 {\n    margin-left: 50%;\n  }\n  .col-sm-offset-5 {\n    margin-left: 41.66666666666667%;\n  }\n  .col-sm-offset-4 {\n    margin-left: 33.33333333333333%;\n  }\n  .col-sm-offset-3 {\n    margin-left: 25%;\n  }\n  .col-sm-offset-2 {\n    margin-left: 16.666666666666664%;\n  }\n  .col-sm-offset-1 {\n    margin-left: 8.333333333333332%;\n  }\n  .col-sm-offset-0 {\n    margin-left: 0;\n  }\n}\n@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.66666666666666%;\n  }\n  .col-md-10 {\n    width: 83.33333333333334%;\n  }\n  .col-md-9 {\n    width: 75%;\n  }\n  .col-md-8 {\n    width: 66.66666666666666%;\n  }\n  .col-md-7 {\n    width: 58.333333333333336%;\n  }\n  .col-md-6 {\n    width: 50%;\n  }\n  .col-md-5 {\n    width: 41.66666666666667%;\n  }\n  .col-md-4 {\n    width: 33.33333333333333%;\n  }\n  .col-md-3 {\n    width: 25%;\n  }\n  .col-md-2 {\n    width: 16.666666666666664%;\n  }\n  .col-md-1 {\n    width: 8.333333333333332%;\n  }\n  .col-md-pull-12 {\n    right: 100%;\n  }\n  .col-md-pull-11 {\n    right: 91.66666666666666%;\n  }\n  .col-md-pull-10 {\n    right: 83.33333333333334%;\n  }\n  .col-md-pull-9 {\n    right: 75%;\n  }\n  .col-md-pull-8 {\n    right: 66.66666666666666%;\n  }\n  .col-md-pull-7 {\n    right: 58.333333333333336%;\n  }\n  .col-md-pull-6 {\n    right: 50%;\n  }\n  .col-md-pull-5 {\n    right: 41.66666666666667%;\n  }\n  .col-md-pull-4 {\n    right: 33.33333333333333%;\n  }\n  .col-md-pull-3 {\n    right: 25%;\n  }\n  .col-md-pull-2 {\n    right: 16.666666666666664%;\n  }\n  .col-md-pull-1 {\n    right: 8.333333333333332%;\n  }\n  .col-md-pull-0 {\n    right: 0;\n  }\n  .col-md-push-12 {\n    left: 100%;\n  }\n  .col-md-push-11 {\n    left: 91.66666666666666%;\n  }\n  .col-md-push-10 {\n    left: 83.33333333333334%;\n  }\n  .col-md-push-9 {\n    left: 75%;\n  }\n  .col-md-push-8 {\n    left: 66.66666666666666%;\n  }\n  .col-md-push-7 {\n    left: 58.333333333333336%;\n  }\n  .col-md-push-6 {\n    left: 50%;\n  }\n  .col-md-push-5 {\n    left: 41.66666666666667%;\n  }\n  .col-md-push-4 {\n    left: 33.33333333333333%;\n  }\n  .col-md-push-3 {\n    left: 25%;\n  }\n  .col-md-push-2 {\n    left: 16.666666666666664%;\n  }\n  .col-md-push-1 {\n    left: 8.333333333333332%;\n  }\n  .col-md-push-0 {\n    left: 0;\n  }\n  .col-md-offset-12 {\n    margin-left: 100%;\n  }\n  .col-md-offset-11 {\n    margin-left: 91.66666666666666%;\n  }\n  .col-md-offset-10 {\n    margin-left: 83.33333333333334%;\n  }\n  .col-md-offset-9 {\n    margin-left: 75%;\n  }\n  .col-md-offset-8 {\n    margin-left: 66.66666666666666%;\n  }\n  .col-md-offset-7 {\n    margin-left: 58.333333333333336%;\n  }\n  .col-md-offset-6 {\n    margin-left: 50%;\n  }\n  .col-md-offset-5 {\n    margin-left: 41.66666666666667%;\n  }\n  .col-md-offset-4 {\n    margin-left: 33.33333333333333%;\n  }\n  .col-md-offset-3 {\n    margin-left: 25%;\n  }\n  .col-md-offset-2 {\n    margin-left: 16.666666666666664%;\n  }\n  .col-md-offset-1 {\n    margin-left: 8.333333333333332%;\n  }\n  .col-md-offset-0 {\n    margin-left: 0;\n  }\n}\n@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.66666666666666%;\n  }\n  .col-lg-10 {\n    width: 83.33333333333334%;\n  }\n  .col-lg-9 {\n    width: 75%;\n  }\n  .col-lg-8 {\n    width: 66.66666666666666%;\n  }\n  .col-lg-7 {\n    width: 58.333333333333336%;\n  }\n  .col-lg-6 {\n    width: 50%;\n  }\n  .col-lg-5 {\n    width: 41.66666666666667%;\n  }\n  .col-lg-4 {\n    width: 33.33333333333333%;\n  }\n  .col-lg-3 {\n    width: 25%;\n  }\n  .col-lg-2 {\n    width: 16.666666666666664%;\n  }\n  .col-lg-1 {\n    width: 8.333333333333332%;\n  }\n  .col-lg-pull-12 {\n    right: 100%;\n  }\n  .col-lg-pull-11 {\n    right: 91.66666666666666%;\n  }\n  .col-lg-pull-10 {\n    right: 83.33333333333334%;\n  }\n  .col-lg-pull-9 {\n    right: 75%;\n  }\n  .col-lg-pull-8 {\n    right: 66.66666666666666%;\n  }\n  .col-lg-pull-7 {\n    right: 58.333333333333336%;\n  }\n  .col-lg-pull-6 {\n    right: 50%;\n  }\n  .col-lg-pull-5 {\n    right: 41.66666666666667%;\n  }\n  .col-lg-pull-4 {\n    right: 33.33333333333333%;\n  }\n  .col-lg-pull-3 {\n    right: 25%;\n  }\n  .col-lg-pull-2 {\n    right: 16.666666666666664%;\n  }\n  .col-lg-pull-1 {\n    right: 8.333333333333332%;\n  }\n  .col-lg-pull-0 {\n    right: 0;\n  }\n  .col-lg-push-12 {\n    left: 100%;\n  }\n  .col-lg-push-11 {\n    left: 91.66666666666666%;\n  }\n  .col-lg-push-10 {\n    left: 83.33333333333334%;\n  }\n  .col-lg-push-9 {\n    left: 75%;\n  }\n  .col-lg-push-8 {\n    left: 66.66666666666666%;\n  }\n  .col-lg-push-7 {\n    left: 58.333333333333336%;\n  }\n  .col-lg-push-6 {\n    left: 50%;\n  }\n  .col-lg-push-5 {\n    left: 41.66666666666667%;\n  }\n  .col-lg-push-4 {\n    left: 33.33333333333333%;\n  }\n  .col-lg-push-3 {\n    left: 25%;\n  }\n  .col-lg-push-2 {\n    left: 16.666666666666664%;\n  }\n  .col-lg-push-1 {\n    left: 8.333333333333332%;\n  }\n  .col-lg-push-0 {\n    left: 0;\n  }\n  .col-lg-offset-12 {\n    margin-left: 100%;\n  }\n  .col-lg-offset-11 {\n    margin-left: 91.66666666666666%;\n  }\n  .col-lg-offset-10 {\n    margin-left: 83.33333333333334%;\n  }\n  .col-lg-offset-9 {\n    margin-left: 75%;\n  }\n  .col-lg-offset-8 {\n    margin-left: 66.66666666666666%;\n  }\n  .col-lg-offset-7 {\n    margin-left: 58.333333333333336%;\n  }\n  .col-lg-offset-6 {\n    margin-left: 50%;\n  }\n  .col-lg-offset-5 {\n    margin-left: 41.66666666666667%;\n  }\n  .col-lg-offset-4 {\n    margin-left: 33.33333333333333%;\n  }\n  .col-lg-offset-3 {\n    margin-left: 25%;\n  }\n  .col-lg-offset-2 {\n    margin-left: 16.666666666666664%;\n  }\n  .col-lg-offset-1 {\n    margin-left: 8.333333333333332%;\n  }\n  .col-lg-offset-0 {\n    margin-left: 0;\n  }\n}\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.428571429;\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.428571429;\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.428571429;\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}\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=\"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 .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.428571429;\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       -o-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  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  padding: 10px 16px;\n  font-size: 18px;\n  line-height: 1.33;\n  border-radius: 6px;\n}\n.btn-sm {\n  padding: 5px 10px;\n  font-size: 12px;\n  line-height: 1.5;\n  border-radius: 3px;\n}\n.btn-xs {\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.428571429;\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.428571429;\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-xs > .btn {\n  padding: 1px 5px;\n  font-size: 12px;\n  line-height: 1.5;\n  border-radius: 3px;\n}\n.btn-group-sm > .btn {\n  padding: 5px 10px;\n  font-size: 12px;\n  line-height: 1.5;\n  border-radius: 3px;\n}\n.btn-group-lg > .btn {\n  padding: 10px 16px;\n  font-size: 18px;\n  line-height: 1.33;\n  border-radius: 6px;\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  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.428571429;\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: 20px;\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 .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.428571429;\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.428571429;\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  display: block;\n  max-width: 100%;\n  height: auto;\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 > .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 .list-group-item:first-child {\n  border-top: 0;\n}\n.panel > .list-group .list-group-item:last-child {\n  border-bottom: 0;\n}\n.panel > .list-group:first-child .list-group-item:first-child {\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-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 > 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 > 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 > 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.panel > .table-bordered > tfoot > tr:first-child > th,\n.panel > .table-responsive > .table-bordered > tfoot > tr:first-child > th,\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 > tfoot > tr:first-child > td,\n.panel > .table-responsive > .table-bordered > tfoot > tr:first-child > td {\n  border-top: 0;\n}\n.panel > .table-bordered > thead > tr:last-child > th,\n.panel > .table-responsive > .table-bordered > thead > tr:last-child > th,\n.panel > .table-bordered > tbody > tr:last-child > th,\n.panel > .table-responsive > .table-bordered > tbody > tr:last-child > th,\n.panel > .table-bordered > tfoot > tr:last-child > th,\n.panel > .table-responsive > .table-bordered > tfoot > tr:last-child > th,\n.panel > .table-bordered > thead > tr:last-child > td,\n.panel > .table-responsive > .table-bordered > thead > tr:last-child > td,\n.panel > .table-bordered > tbody > tr:last-child > td,\n.panel > .table-responsive > .table-bordered > tbody > tr:last-child > td,\n.panel > .table-bordered > tfoot > tr:last-child > td,\n.panel > .table-responsive > .table-bordered > tfoot > tr:last-child > td {\n  border-bottom: 0;\n}\n.panel > .table-responsive {\n  margin-bottom: 0;\n  border: 0;\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-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.428571429px;\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.428571429;\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  .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  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  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 .glyphicons-chevron-left,\n  .carousel-control .glyphicons-chevron-right,\n  .carousel-control .icon-prev,\n  .carousel-control .icon-next {\n    width: 30px;\n    height: 30px;\n    margin-top: -15px;\n    margin-left: -15px;\n    font-size: 30px;\n  }\n  .carousel-caption {\n    right: 20%;\n    left: 20%;\n    padding-bottom: 30px;\n  }\n  .carousel-indicators {\n    bottom: 20px;\n  }\n}\n.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,\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  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.visible-sm,\ntr.visible-sm,\nth.visible-sm,\ntd.visible-sm {\n  display: none !important;\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.visible-md,\ntr.visible-md,\nth.visible-md,\ntd.visible-md {\n  display: none !important;\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.visible-lg,\ntr.visible-lg,\nth.visible-lg,\ntd.visible-lg {\n  display: none !important;\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  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-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-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-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  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  tr.hidden-print,\n  th.hidden-print,\n  td.hidden-print {\n    display: none !important;\n  }\n}\n/*# sourceMappingURL=bootstrap.css.map */\n"
  },
  {
    "path": "flowable-ui-web/admin/styles/style.css",
    "content": "/*\n\tColors:\n\t   - Header dark: #384042\n\t   - Activiti blue: #2674aa\n\t   - Activiti green: #55ae4d\n\t   - Body/border grey: #eef1f1\n\t   - Component border: #c9d2d2\n\t   - Non-focus header-text: #6b7a7a\n\t   - Selection blue: #aad1ec\n*/\n\n@font-face {\n\tfont-family: 'Titillium Web';\n\tfont-style: normal;\n\tfont-weight: normal;\n\turl('../fonts/TitilliumWeb-Regular.ttf') format('truetype');\n}\n\n@font-face {\n\tfont-family: 'Titillium Web';\n\tfont-style: normal;\n\tfont-weight: bold;\n\turl('../fonts/TitilliumWeb-Bold.ttf') format('truetype');\n}\n\nbody {\n\tfont-family: 'Titillium Web', sans-serif;\n\tbackground-color: #eef1f1;\n\tpadding-top: 90px;\n\tpadding-bottom: 20px;\n}\n\n.container {\n  margin: 0 auto;\n  min-width: 1024px;\n}\n\n.no-top-gutter {\n\tmargin-top: -40px; !important;\n}\n\n.error-text {\n    color: red;\n}\n\n\n[ng\\:cloak], [ng-cloak], .ng-cloak { display: none; }\n\n.inline-button input.form-control {\n\twidth: 80%;\n}\n\n.inline-button > .btn-group {\n\twidth: 20%;\n\tpadding-right: 5px;\n}\n\n.inline-button > .btn-group button {\n\twidth: 100%;\n\tmargin: 0 5px;\n}\n\n.inline-button  .checkbox  label {\n\tfont-size: 12px;\n}\n\n.inline-button {\n\tmargin-bottom: 5px;\n}\n\n.inline-button:last-child {\n\tmargin-bottom: 0;\n}\n\n.inline-button > .btn-group > .btn:first-child {\n\tmargin-left: 5px;\n}\n\n.inline-button.wide input.form-control {\n\twidth: 65%;\n}\n\n.inline-button.wide > .btn-group {\n\twidth: 35%;\n}\n\n/* Navigation */\n\n.nav>li>a {\n\tpadding: 10px 25px;\n}\n\n.navbar {\n\tbackground-color: #1f3245;\n\tborder: none;\n\tmin-height: 40px;\n\tmargin-bottom: 5px;\n}\n\n.nav.navbar-nav {\n\tbackground-color: #1f3245;\n\tcolor: #eef1f1;\n\tborder: none;\n}\n\n.navbar-header .navbar-brand {\n    position: relative;\n\tpadding-top: 0px;\n\ttop: 2px;\n\tline-height: 35px;\n    height: 35px;\n    background: url(../images/flowable-logo.png) no-repeat 15px center;\n    width: 180px;\n}\n\n.nav.navbar-nav li a {\n    line-height: 40px;\n    height: 40px;\n    padding-top: 0;\n    color: #eef1f1;\n\tfont-size: 16px;\n}\n\n.navbar-inverse .navbar-nav > .active-process > a, .navbar-inverse .navbar-nav > .active-process > a:hover, .navbar-inverse .navbar-nav > .active-process > a:focus {\n\tbackground: rgb(162,204,70);\n\tcolor: #ffffff;\n}\n\n.navbar-inverse .navbar-nav > .active-cmmn > a, .navbar-inverse .navbar-nav > .active-cmmn > a:hover, .navbar-inverse .navbar-nav > .active-cmmn > a:focus {\n    background: rgb(253,229,65);\n    color: #ffffff;\n}\n\n.navbar-inverse .navbar-nav > .active-app > a, .navbar-inverse .navbar-nav > .active-app > a:hover, .navbar-inverse .navbar-nav > .active-app > a:focus {\n    background: rgb(227,58,58);\n    color: #ffffff;\n}\n\n.navbar-inverse .navbar-nav > .active-form > a, .navbar-inverse .navbar-nav > .active-form > a:hover, .navbar-inverse .navbar-nav > .active-form > a:focus {\n    background: rgb(0,102,153);\n\tcolor: #ffffff;\n}\n\n.navbar-inverse .navbar-nav > .active-dmn > a, .navbar-inverse .navbar-nav > .active-dmn > a:hover, .navbar-inverse .navbar-nav > .active-dmn > a:focus {\n    background: rgb(227,154,33);\n\tcolor: #ffffff;\n}\n\n.navbar-inverse .navbar-nav > .active-content > a, .navbar-inverse .navbar-nav > .active-content > a:hover, .navbar-inverse .navbar-nav > .active-content > a:focus {\n    background: rgb(102,153,255);\n\tcolor: #ffffff;\n}\n\n.navbar .btn-group > .btn-default {\n\tbackground-color: #000000;\n\tborder-color: #000000;\n\tcolor: #eef1f1;\n\tfont-size: 12px;\n\t-webkit-border-radius: 3px;\n\t-moz-border-radius: 3px;\n\tborder-radius: 3px;\n\tmargin-top: 8px;\n\tpadding-top: 2px;\n\tpadding-bottom: 2px;\n}\n\n.navbar .dropdown-menu {\n\tbackground-color: #384042;\n}\n\n.navbar .dropdown-menu>li>a:hover, .navbar .dropdown-menu>li>a:focus {\n\tbackground-color: #384042;\n}\n\n.navbar .dropdown-menu>.active-process>a, .navbar .dropdown-menu>.active-process>a:hover, .navbar .dropdown-menu>.active-process>a:focus {\n\tbackground: rgb(162,204,70);\n\tcolor: #ffffff;\n}\n\n.navbar .dropdown-menu>li>a {\n\tcolor: #ffffff;\n}\n\n.sub-navbar.active-process {\n\tbackground: rgb(162,204,70);\n    background: linear-gradient(to right, rgba(162,204,70,1.0), rgba(162,204,70,1.0), rgba(162,204,70,1.0), rgba(162,204,70,0), rgba(162,204,70,0));\n}\n\n.sub-navbar.active-cmmn {\n    background: rgb(253,229,65);\n    background: linear-gradient(to right, rgba(253,229,65,1.0), rgba(253,229,65,1.0), rgba(253,229,65,1.0), rgba(253,229,65,0), rgba(253,229,65,0));\n}\n\n.sub-navbar.active-app {\n    background: rgb(227,58,58);\n    background: linear-gradient(to right, rgba(227,58,58,1.0), rgba(227,58,58,1.0), rgba(227,58,58,1.0), rgba(227,58,58,0), rgba(227,58,58,0));\n}\n\n.sub-navbar.active-form {\n    background: rgb(0,102,153);\n    background: linear-gradient(to right, rgba(0,102,153,1.0), rgba(0,102,153,1.0), rgba(0,102,153,1.0), rgba(0,102,153,0), rgba(0,102,153,0));\n}\n\n.sub-navbar.active-dmn {\n    background: rgb(227,154,33);\n    background: linear-gradient(to right, rgba(227,154,33,1.0), rgba(227,154,33,1.0), rgba(227,154,33,1.0), rgba(227,154,33,0), rgba(227,154,33,0));\n}\n\n.sub-navbar.active-content {\n    background: rgb(102,153,255);\n    background: linear-gradient(to right, rgba(102,153,255,1.0), rgba(102,153,255,1.0), rgba(102,153,255,1.0), rgba(102,153,255,0), rgba(102,153,255,0));\n}\n\n.sub-navbar .drop-menu {\n    background: none;\n}\n\n.sub-navbar .navbar-nav, .sub-navbar .navbar-nav, .sub-navbar .navbar-nav {\n    background: none;\n    color: #384042;\n}\n\n.sub-navbar .navbar-nav > .active > a, .sub-navbar .navbar-nav > .active > a:hover, .sub-navbar .navbar-nav > .active > a:focus {\n    background: none;\n    color: #ffffff; !important;\n}\n\n.sub-navbar .nav.navbar-nav li.active a{\n    color: #ffffff; !important;\n}\n\n.sub-navbar .nav.navbar-nav li a {\n\tfont-size: 14px;\n    color: #384042;\n    background-color: unset;\n}\n\n.tabs-wrapper {\n\tmargin-bottom: 20px;\n}\n\n.tabs-wrapper .badge {\n\tbackground-color: #bfbfbf;\n\tfont-size: 10px;\n}\n\n.component .tabs-wrapper .title {\n\tbackground: rgb(238,241,241);\n}\n\n.tabs {\n\tpadding: 0px;\n\tmargin-bottom: -1px;\n\tmargin-left: -1px;\n\tmargin-top: -1px;\n\tz-index: 2000;\n}\n.tabs-sm {\n\tmargin-left: 5px;\n\tpadding-top: 10px;\n}\n\n.tabs .tab {\n\tfloat: left;\n\tborder-right: 1px solid #eef1f1;\n\tborder-bottom: 1px solid #eef1f1;\n\tbackground-color: #f5f7f7;\n\tmargin-top: 0;\n}\n\n.tabs .tab a {\n\tfont-size: 15px;\n\tfont-weight: bold;\n\ttext-decoration: none;\n\tmargin: 0;\n\tpadding: 8px 15px;\n\tline-height: 39px;\n\tcolor: #7b8a8a;\n\tbackground-color: #f5f7f7;\n\tcursor: pointer;\n}\n\n.tabs-sm .tab {\n\tborder-top: 1px solid #eef1f1;\n}\n.tabs-sm .tab a {\n\tfont-size: 13px;\n\tpadding: 7px 15px;\n\tline-height: 32px;\n}\n\n.tabs-sm .tab:first-child {\n\tborder-left: 1px solid #eef1f1;\n}\n.tabs .tab:first-child a {\n\t-webkit-border-radius: 3px;\n\t-moz-border-radius: 3px;\n\tborder-radius: 3px;\n}\n\n.tabs .tab.active{\n\tborder-bottom-color: #ffffff;\n\tbackground-color: #ffffff;\n}\n\n.tabs .label {\n\tmargin-left: 5px;\n}\n\n\n.tabs .tab a:hover {\n\tcolor: #384042;\n}\n\n\n.tabs .tab.active a, .tabs .tab.active a:hover{\n\tbackground-color: #ffffff;\n\tcolor: #000000;\n\tcursor: pointer;\n}\n\n\n\n/* Components boxes */\n\n.component {\n\tbackground-color: #ffffff;\n\tmargin-top: 10px;\n\tmin-height: 300px;\n\t-webkit-border-radius: 3px;\n\t-moz-border-radius: 3px;\n\tborder-radius: 3px;\n\n\t-webkit-box-shadow: 0 0 2px 1px rgba(201,210,210,200);\n\tbox-shadow: 0 0 2px 1px rgba(201,210,210,200);\n\tpadding: 1px;\n}\n\n.component pre {\n\tmargin: 10px;\n\tfont-size: 12px;\n}\n.component.component-pack {\n\tmin-height: 50px;\n}\n\n.component h2 {\n\tfont-size: 15px;\n\tfont-weight: bold;\n\ttext-decoration: none;\n\tmargin: 0;\n\tpadding: 10px 10px 10px 10px;\n\tbackground-color: #ffffff;\n\tmin-height: 36px;\n}\n\n.component h1 {\n\tfont-size: 25px;\n\tfont-weight: bold;\n\ttext-decoration: none;\n\tmargin: 0;\n\tpadding: 10px 10px 10px 10px;\n\tbackground-color: #ffffff;\n\tmin-height: 36px;\n}\n\n.component h3 {\n\tfont-size: 14px;\n\tfont-weight: bold;\n\ttext-decoration: none;\n\tmargin: 0;\n\tpadding: 5px 10px 5px 10px;\n\tbackground-color: #ffffff;\n}\n\n.component .no-results {\n\tmargin: 20px 10px;\n\tcolor: #6b7a7a;\n}\n\n.component .no-results .glyphicon-info-sign {\n\tcolor: inherit;\n}\n\n.component .list-group {\n\tlist-style: none;\n\tlist-style-position: inside;\n\tmargin-bottom: 5px;\n\tpadding: 5px 0px 0px 0px;\n}\n\n.component .list-group li {\n\tpadding: 5px 10px 5px 10px;\n\tfont-size: 13px;\n}\n.component .list-group .btn, .component .list-group .btn-group {\n\twidth: 100%;\n\ttext-align: left;\n}\n.component .list-group .btn-danger {\n\tbackground-color: #ffffff;\n\tcolor: #d9534f;\n\tborder-color: #d9534f;\n}\n\n.component .list-group .btn i.glyphicon {\n\tmargin-right: 10px;\n}\n\n.component .title a.action, .component .tabs-wrapper a.action {\n\tfont-size: 11px;\n\tline-height: 35px;\n\tmargin: 0 10px;\n\tcursor: pointer;\n}\n\n.label-wrapper {\n\tmargin: 5px 5px 0px 0px;\n}\n\n.component .title, .component .seperator, .modal-header-wrapper, .modal-footer-wrapper {\n\tpadding-bottom: 1px;\n\tbackground: #c9d2d2; /* Old browsers without gradient */\n\tbackground: -moz-linear-gradient(left,  rgba(255,255,255,1) 0%, rgba(238,241,241,1) 5%, rgba(238,241,241,1) 95%, rgba(255,255,255,1) 100%); /* FF3.6+ */\n\tbackground: -webkit-gradient(linear, left top, right top, color-stop(0%,rgba(255,255,255,1)), color-stop(5%,rgba(238,241,241,1)), color-stop(95%,rgba(238,241,241,1)), color-stop(100%,rgba(255,255,255,1))); /* Chrome,Safari4+ */\n\tbackground: -webkit-linear-gradient(left,  rgba(255,255,255,1) 0%,rgba(238,241,241,1) 5%,rgba(238,241,241,1) 95%,rgba(255,255,255,1) 100%); /* Chrome10+,Safari5.1+ */\n\tbackground: -o-linear-gradient(left,  rgba(255,255,255,1) 0%,rgba(238,241,241,1) 5%,rgba(238,241,241,1) 95%,rgba(255,255,255,1) 100%); /* Opera 11.10+ */\n\tbackground: -ms-linear-gradient(left,  rgba(255,255,255,1) 0%,rgba(238,241,241,1) 5%,rgba(238,241,241,1) 95%,rgba(255,255,255,1) 100%); /* IE10+ */\n\tbackground: linear-gradient(to right,  rgba(255,255,255,1) 0%,rgba(238,241,241,1) 5%,rgba(238,241,241,1) 95%,rgba(255,255,255,1) 100%); /* W3C */\n\tfilter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#c9d2d2', endColorstr='#c9d2d2',GradientType=1 ); /* IE6-9 */\n}\n\n.modal-footer-wrapper {\n\tpadding-top: 1px;\n\tpadding-bottom: 0;\n}\n\n.component .title > .btn-group {\n\tmargin-top: 2px;\n\tmargin-right: 2px;\n}\n\n.component .title.process {\n\tcolor: rgb(162,204,70)\n}\n\n.component .title.cmmn {\n    color: rgb(253,229,65)\n}\n\n.component .title.dmn {\n\tcolor: rgb(227,154,33)\n}\n\n.component .title.form {\n\tcolor: rgb(0,102,153)\n}\n\n.component .title.content {\n\tcolor: rgb(102,153,255)\n}\n\n\n.component .input-group {\n\twidth: 100%;\n}\n.component .input-group .btn-group {\n\twidth: 100%;\n}\n.component .input-group .btn-group .dropdown-menu {\n\twidth: 100%;\n}\n.component .input-group .btn-group .btn {\n\ttext-align: left;\n}\n\n.component .input-group span {\n\tfont-size: 12px;\n}\n\n.dropdown-menu {\n\tfont-size: 12px;\n}\n\n.component .section {\n\tmargin: 5px 10px 10px 10px;\n}\n\n.component .section .subtitle {\n\tcolor: #6b7a7a;\n\tfont-size: 12px;\n\tmargin-bottom: 2px;\n}\n.component .section .subtitle a {\n\ttext-decoration: none;\n\tcursor: pointer;\n\tcolor: #6b7a7a;\n}\n\n.component .section .subtitle .glyphicon-remove {\n\tdisplay: none;\n}\n\n.component .section .subtitle a:hover .glyphicon-remove {\n\tdisplay: inherit;\n}\n\n.component .section .subtitle label {\n\tfont-weight: normal;\n\tmargin: 0;\n\tcursor: pointer;\n}\n\n.component  p {\n\tfont-size: 12px;\n\tmargin: 10px;\n}\n\n.component .glyphicon-info-sign {\n\tcolor: #2674aa;\n\tmargin-right: 5px;\n}\n\n.no-min-height {\n    min-height: 0px;\n}\n\n/* Grids */\n\n.gridStyle {\n    width: 100%;\n    height: 400px;\n\tborder: none;\n\tmargin-bottom: 5px;\n}\n\n.grid-wrapper-compact .gridStyle {\n\theight: 200px;\n}\n\n.grid-wrapper {\n\twidth: 100%;\n\tpadding: 10px;\n}\n\n.grid-wrapper .gridStyle {\n\tmargin-bottom: 5px;\n\tborder: 1px solid transparent;\n}\n\n.grid-wrapper .ngTopPanel {\n\tbackground-color: transparent;\n\tborder: none;\n}\n.grid-wrapper .ngHeaderText {\n\tpadding: 8px 0px 0px 0px;\n}\n.gridStyle .ngHeaderCell {\n\tpadding-left: 5px;\n\tfont-weight: bold;\n\tfont-size: 12px;\n\tbackground-color: transparent;\n}\n\n.grid-wrapper .ngVerticalBar.ngVerticalBarVisible {\n\tbackground-color: #eef1f1;\n}\n\n.grid-wrapper .ngCellText {\n\tfont-size: 12px;\n\tpadding: 10px 5px 10px 5px;\n}\n\n.grid-wrapper .ngCellTextCenter {\n\ttext-align: center;\n\tfont-size: 15px;\n\tcolor: #55ae4d;\n}\n\n.grid-wrapper .ngCellTextCenter .glyphicon {\n\tcolor: #55ae4d;\n}\n\n.grid-wrapper .ngRow.even {\n\tbackground-color: #f6f7f7;\n}\n\n.grid-wrapper .ngRow.odd {\n\tbackground-color: #ffffff;\n}\n\n.grid-wrapper .ngRow.even.selected {\n\tbackground-color: #aad1ec;\n}\n\n.grid-wrapper .ngRow.odd.selected {\n\tbackground-color: #aad1ec;\n}\n\n.grid-wrapper .ngRow:hover {\n\tbackground-color: #aad1ec;\n}\n\n.grid-wrapper .ngRow:hover .ngVerticalBar.ngVerticalBarVisible {\n\tbackground-color: #aad1ec;\n}\n\n.grid-wrapper .ngRow.selected .ngVerticalBar.ngVerticalBarVisible {\n\tbackground-color: #aad1ec;\n}\n\n.grid-wrapper i {\n\tcolor: #6b7a7a;\n}\n\n.grid-wrapper .grid-message {\n\tmargin: 0px 0px 10px 0px;\n\tcolor:  #6b7a7a;\n\tfont-size: 12px;\n}\n\n.grid-wrapper .grid-message .highlight, .grid-wrapper .grid-message .highlight i {\n\tcolor: #2674aa;\n\tfont-weight: bold;\n}\n\n.grid-wrapper .gridStyle-highlight {\n\tborder: 1px solid #aad1ec;\n}\n\n/* Properties */\n\n.property-wrapper {\n\tmargin: 10px;\n}\n\n.property-wrapper table {\n\twidth: 100%;\n}\n\n.property {\n\tfont-size: 12px;\n}\n\n.property td {\n\tpadding: 5px 5px;\n\twidth: 30%;\n\tvertical-align: top;\n}\n\n.property .property-name {\n\tfont-weight: bold;\n\twidth: 15%;\n}\n\n.property.property-float-2 {\n\twidth: 50%;\n\tfloat: left;\n\tpadding: 0 15px 10px 0;\n}\n\n.property.property-float-3 {\n\twidth: 33%;\n\tfloat: left;\n\tpadding: 0 15px 10px 0;\n}\n\n.property.property-float-2 .property-name, .property.property-float-3 .property-name {\n\tmargin-right: 15px;\n\twidth: inherit;\n}\n\n.property a {\n\tcursor: pointer;\n}\n\n.property ul {\n\tpadding: 5px;\n\tlist-style: square inside;\n}\n\n/* Flowable Icon font */\n\n@font-face {\n     font-family: 'svgfont_1regular';\n    src: url('../fonts/font3933-webfont.eot');\n    src: url('../fonts/font3933-webfont.eot?#iefix') format('embedded-opentype'),\n         url('../fonts/font3933-webfont.woff') format('woff'),\n         url('../fonts/font3933-webfont.ttf') format('truetype'),\n         url('../fonts/font3933-webfont.svg#svgfont_1regular') format('svg');\n    font-weight: normal;\n\n}\n\n/* Loading animation */\n\n.loading {\n    margin: 0px 15px;\n    text-align: center;\n    line-height: 34px;\n}\n\n.message .loading {\n    line-height: 40px;\n    margin-left: 0px;\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@-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/* Modal window */\n.modal-header {\n\tmargin-top: 6px;\n\tborder-bottom: none;\n\tbackground-color: white;\n\tpadding: 4px 10px 10px 10px;\n}\n\n.modal-header h2 {\n\tfont-size: 15px;\n\tfont-weight: bold;\n\ttext-decoration: none;\n\tmargin: 0;\n\tbackground-color: #ffffff;\n}\n\n.modal-header a.action {\n\tfont-size: 11px;\n\tline-height: 18px;\n\tmargin: 0 10px;\n    cursor: pointer;\n}\n\n.modal-body {\n\tpadding: 5px 10px;\n\tmax-height: 850px;\n\tmin-height: 100px;\n\toverflow: auto;\n}\n\n.modal-body.modal-body-high {\n\tmin-height: 850px;\n}\n\n.modal-body.modal-body-medium {\n\tmin-height: 300px;\n}\n\n.modal.modal-full-width .modal-dialog {\n\twidth: 95%;\n}\n\n.modal-body p {\n\tfont-size: 13px;\n\tmargin: 20px 0px;\n}\n\n.modal-footer {\n\tmargin-top: 0;\n\tpadding: 11px 10px 5px 10px;\n\tborder: none;\n\tbackground-color: #ffffff;\n\tmargin-bottom: 6px;\n}\n\n.with-right-marging {\n\tmargin-right: 20px;\n}\n\n.edit-table {\n\twidth: 100%;\n\tpadding: 10px;\n\tfont-size: 12px;\n}\n\n.edit-table .message {\n\tfont-size: 12px;\n\tcolor: #6b7a7a;\n\tpadding: 0;\n\tmargin: 2px 5px;\n}\n\n.edit-label {\n\twidth: 30%;\n\tvertical-align: middle;\n\ttext-align: left;\n}\n\n.edit-label-top {\n    width: 30%;\n    vertical-align: top;\n    text-align: left;\n}\n\n.edit-table input, .edit-table .input-group {\n     width: 95%;\n}\n\n.edit-table input[type=checkbox] {\n    width: inherit;\n}\n\n.edit-table td {\n\tpadding: 5px;\n}\n\n.master-config-modal > .modal-dialog {\n    width: 1100px;\n}\n\n/* Graph bars */\n.graph-wrapper {\n\theight: 15px;\n\twidth: 100%;\n\tmargin: 2px 0;\n\tbackground-color: #384042;\n\tborder: 1px solid #384042;\n\toverflow: hidden;\n}\n\n.graph-bar {\n\tbackground-color: #55ae4d;\n\theight: 13px;\n\tcontent: ' ';\n}\n\n/* CSS Arrow */\n.tip-left {\tposition: relative; min-height: 100px;}\n.tip-left:after, .tip-left:before { right: 100%; top: 20px; border: solid transparent; content: ' '; height: 0; width: 0; position: absolute; pointer-events: none; }\n.tip-left:after { border-color: rgba(255, 255, 255, 0); border-right-color: #ffffff; border-width: 6px; margin-top: -6px; }\n.tip-left:before { border-color: rgba(255, 255, 255, 0); border-right-color: #c9d2d2; border-width: 7px; margin-top: -7px; }\n\n/* Retina tweaks */\n\n@media \tonly screen and (-webkit-min-device-pixel-ratio: 1.5),\n\t\tonly screen and (   min--moz-device-pixel-ratio: 1.5),\n\t\tonly screen and (     -o-min-device-pixel-ratio: 3/2),\n\t\tonly screen and (        min-device-pixel-ratio: 1.5),\n\t\tonly screen and (min-resolution: 192dpi) {\n\n    .navbar-header .navbar-brand {\n        background: url(../images/flowable-logo@2x.png) no-repeat 20px center;\n        background-size: 140px 35px;\n        background-repeat: no-repeat;\n    }\n}\n\n\n.engine-section {\n    margin: 20px 0 10px 0;\n}\n\n/* Login */\n\n.login-wrapper {\n\twidth: 100%;\n\tpadding: 15px 10px;\n}\n\n.login {\n\tmargin-top: 45px;\n}\n\n/* Cluster config */\n\n.cluster-config-wizard-step-cluster {\n    background: url(../images/cluster.png) no-repeat left center;\n    background-repeat: no-repeat;\n    padding-left: 44px;\n}\n\n.cluster-config-wizard-step-network {\n    background: url(../images/network.png) no-repeat left center;\n    background-repeat: no-repeat;\n    padding-left: 44px;\n}\n\n.cluster-config-wizard-step-security {\n    background: url(../images/settings.png) no-repeat left center;\n    background-repeat: no-repeat;\n    padding-left: 44px;\n}\n\n.cluster-config-wizard-step-activiti {\n    background: url(../images/activiti.png) no-repeat left center;\n    background-repeat: no-repeat;\n    padding-left: 44px;\n}\n\n@media \tonly screen and (-webkit-min-device-pixel-ratio: 1.5),\nonly screen and (   min--moz-device-pixel-ratio: 1.5),\nonly screen and (     -o-min-device-pixel-ratio: 3/2),\nonly screen and (        min-device-pixel-ratio: 1.5),\nonly screen and (min-resolution: 192dpi) {\n\n    .cluster-config-wizard-step-cluster {\n        background: url(../images/cluster-x2.png) no-repeat left center;\n        background-size: 40px 40px;\n    }\n\n    .cluster-config-wizard-step-network {\n        background: url(../images/network-x2.png) no-repeat left center;\n        background-size: 40px 40px;\n    }\n\n    .cluster-config-wizard-step-security {\n        background: url(../images/settings-x2.png) no-repeat left center;\n        background-size: 40px 40px;\n    }\n\n    .cluster-config-wizard-step-activiti {\n        background: url(../images/activiti-x2.png) no-repeat left center;\n        background-size: 40px 40px;\n    }\n\n}\n\n.bpm-suite-config {\n    height: 500px;\n    max-height: 500px;\n}\n\n\n/* Upload from Modeler */\n\n.upload-from-modeler-dialog > .modal-dialog {\n    width: 800px;\n    min-height: 0px;\n}\n\n.upload-from-modeler-form {\n    text-align: center;\n    margin: 20px 0 20px 0;\n}\n\n.upload-from-modeler-form span {\n    margin-bottom: 20px;\n}\n\n.upload-from-modeler-form form {\n    margin-left: 20%;\n    margin-right: 20%;\n    text-align: left;\n}\n\n.modeler-processes-error {\n    color: red;\n    font-size: smaller;\n    padding: 7px 5px 0 0;\n}\n.process-model-wrapper {\n    padding-left: 0;\n    margin-top: 5px;\n}\n\n.process-model-wrapper .message {\n    text-align: left;\n    margin-left: 5px;\n    line-height: 40px;\n    color: #606b7d;\n}\n.process-model-wrapper .message span {\n    font-size: 14px;\n}\n\n.process-model-wrapper .process-model {\n    width: 33%;\n    padding: 0;\n    margin: 0;\n    float: left;\n}\n\n.process-model-wrapper .process-model .process-model-box {\n    margin: 5px;\n    border: 1px solid #e8edf1;\n    height: 250px;\n    overflow: hidden;\n    cursor: pointer;\n    background-repeat: no-repeat;\n    background-position: center 20px;\n    background-size: 100% auto;\n}\n\n.process-model-box .details {\n    background-color: #e8edf1;\n    height: 160px;\n    margin-top: 120px;\n    padding: 5px;\n    color: #373e48;\n    font-size: 13px;\n\n    transition: margin-top .5s ease;\n    -moz-transition: margin-top .5s ease;\n    -webkit-transition: margin-top .5s ease;\n    -o-transition: margin-top .5s ease;\n}\n\n.process-model-box .selected-process{\n    background-color: #55ae4d;\n}\n\n.process-model-box:hover .details, .process-model-box.active .details {\n    margin-top: 50px;\n}\n\n.process-model-box .actions {\n    padding: 5px;\n    height: 45px;\n}\n\n.process-model-box .actions .btn-group {\n    visibility: hidden;\n}\n\n.process-model-box:hover .actions .btn-group, .process-model-box.active .actions .btn-group {\n    visibility: inherit;\n}\n\n\n.process-model-box .details h3 {\n    font-size: 14px;\n    margin: 0;\n    padding: 2px;\n    color: #373e48;\n}\n\n.process-model-box .details span {\n    display: block;\n    margin-top: 5px;\n}\n\n.process-model-box .details span i {\n    padding-right: 10px;\n    padding-left: 5px;\n}\n\n.process-model-box .details .basic-details {\n    min-height: 60px;\n}\n\n.process-model-box .details p {\n    width: 100%;\n    height: 70px;\n    font-size: 12px;\n    overflow: hidden;\n}\n\n/* Alerts */\n.alert-wrapper {\n\tposition: fixed;\n\ttop: 40px;\n\tleft: 30%;\n\tright: 30%;\n\tz-index: 1030;\n}\n\n.alert {\n\twidth: 100%;\n\tmargin: 5px auto;\n\tmin-height: 20px;\n\tbackground-color: #eef4d7;\n\tborder-color: #bcd35f;\n\tpadding: 4px 10px;\n}\n\n.alert .pull-right {\n\tmargin-left: 10px;\n}\n\n.alert .badge {\n\tbackground-color: #bcd35f;\n\tcolor: #ffffff;\n\tfont-size: 12px;\n\tmargin-top: 2px;\n}\n\n\n.alert .glyphicon {\n\tpadding-right: 8px;\n\tcolor:  #bcd35f;\n}\n\n.alert span {\n\tcolor: #445016;\n\tfont-size: 15px;\n}\n\n.alert.error {\n\tbackground-color: #e9af9f;\n\tborder-color: #e4593d;\n}\n.alert.error .glyphicon {\n\tcolor: #e4593d;\n}\n\n.alert.error span {\n\tcolor: #471313;\n}\n\n.alert.error .badge {\n\tbackground-color: #e4593d;\n\tcolor: #ffffff;\n}\n\n/* Upload deployment */\n\n.upload-deployment-form {\n    margin: 0 20% 0 20%;\n    text-align: center;\n}\n\n.dropbox {\n    background: #F8F8F8;\n    border: 5px dashed #DDD;\n    color: #8e8e8e;\n    text-align: center;\n    padding: 35px 0 35px 0;\n    margin: 20px 0 20px 0;\n}\n\n.dropbox.dragover {\n    border: 5px dashed #55ae4d;\n    color: #55ae4d;\n}\n\n\n#bpmnModel {\n\tmargin-top: 15px;\n\tmargin-bottom: 15px;\n}\n\n\n/* Monitoring */\n\n.metrics {\n    font-size: 12px;\n    float:left;\n}\n\n.metrics-numbers {\n    width: 300px;\n    float: left;\n    margin-top: 26px;\n}\n\n.metrics-count-chart {\n    float: left;\n}\n\n.metrics-title {\n    font-weight: bold;\n}\n\n.metrics-titles td {\n    font-weight: bold;\n    padding-top: 30px;\n}\n\n\n/* Inpired by http://icant.co.uk/csscharts/ */\n\n/* Hour count chart */\n\n.hour-count-chart {\n  position: relative;\n  margin:0;\n  padding:0;\n  background: #fc6;\n  border:1px solid #999;\n  height:100px;\n  width:500px;\n  list-style:none;\n  overflow:hidden;\n}\n\n.hour-count-chart-entry {\n  height:100px;\n  list-style:none;\n  margin:0;\n  padding:0;\n  float:left;\n  width:20px;\n  border: 1px solid #eee;\n  background-color: #fc6;\n  border-right-width: 2px;\n}\n\n.hour-count-chart-entry span{\n  display:none;\n  position:absolute;\n  top:1em;\n  font-size: 14px;\n  font-weight: bold;\n}\n\n.hour-count-chart-entry:hover{\n  background: #693;\n  border-color: #ddd;\n}\n\n.hour-count-chart-entry:hover span{\n  left:1em;\n  display:inline;\n}\n\n/* Weekday css */\n\n.weekday-count-chart {\n  position: relative;\n  margin:0;\n  padding:0;\n  background: #fc6;\n  border:1px solid #999;\n  height:100px;\n  width:182px;\n  list-style:none;\n  overflow:hidden;\n}\n\n.weekday-count-chart-entry {\n  height:100px;\n  list-style:none;\n  margin:0;\n  padding:0;\n  float:left;\n  width:24px;\n  border: 1px solid #eee;\n  background-color: #55ae4d;\n  border-right-width: 2px;\n}\n\n.weekday-count-chart-entry span{\n  display:none;\n  position:absolute;\n  top:1em;\n  font-size: 14px;\n  font-weight: bold;\n}\n\n.weekday-count-chart-entry:hover{\n  background: #693;\n  border-color: #ddd;\n}\n\n.weekday-count-chart-entry:hover span{\n  left:1em;\n  display:inline;\n}\n\n.no-overflow{\n\toverflow: visible;\n}\n\n.type-ahead-scrollable .dropdown-menu {\n\tmax-height: 300px;\n\toverflow: auto;\n\twidth: 100%;\n}\n\n.type-ahead-scrollable .dropdown-menu a .user-label {\n\tpadding-left: 8px;\n}\n\n.decision-table-grid {\n\tborder: 1px solid rgb(212,212,212);\n\twidth: 100%;\n\theight: 372px;\n\tmargin-bottom: 10px;\n}\n\n.decision-table .btn-success {\n\tcolor: #fff;\n\tbackground-color: #5cb85c;\n}\n\n.decision-table .btn-success:hover,\n.decision-table .btn-success:focus {\n\tbackground-color: #419641;\n\tbackground-position: 0 -15px;\n}\n\n.decision-table-grid .ui-grid-header-viewport, .decision-table-grid .ui-grid-header-canvas {\n\theight: 70px;\n}\n\n.decision-table-grid .header-expression {\n\theight: 70px;\n\tborder-bottom: 5px solid rgb(43, 37, 37);\n\tborder-bottom: 5px solid rgba(43, 37, 37, 0.22);\n}\n\n.decision-table-grid .header-input-expression {\n\t/* Fallback for web browsers that doesn't support RGBa */\n\tbackground: rgb(54, 167, 196);\n\t/* RGBa with 0.6 opacity */\n\tbackground: rgba(54, 167, 196, 0.6);\n\t/*background-color: #668b94;*/\n\tcolor: #ffffff;\n\tfont-size: 14px;\n}\n\n.decision-table-grid .header-output-expression {\n\tborder-left: 5px solid rgb(212,212,212);\n\t/* Fallback for web browsers that doesn't support RGBa */\n\tbackground: rgb(92, 184, 92);\n\t/* RGBa with 0.6 opacity */\n\tbackground: rgba(92, 184, 92, 0.6);\n\tcolor: #ffffff;\n\tfont-size: 14px;\n}\n\n.decision-table-grid .header-output-expression ~ .header-output-expression {\n\tborder-left: none;\n}\n\n.decision-table-grid .cell-input-expression {\n\t/* Fallback for web browsers that doesn't support RGBa */\n\tbackground: rgb(54, 167, 196);\n\t/* RGBa with 0.6 opacity */\n\tbackground: rgba(54, 167, 196, 0.1);\n}\n\n.decision-table-grid .cell-output-expression {\n\tborder-left: 5px solid rgb(212,212,212);\n\t/* Fallback for web browsers that doesn't support RGBa */\n\tbackground: rgb(92, 184, 92);\n\t/* RGBa with 0.6 opacity */\n\tbackground: rgba(92, 184, 92, 0.1);\n\tborder-left: 3px solid rgb(212,212,212);\n}\n\n.decision-table-grid .cell-output-expression ~ .cell-output-expression {\n\tborder-left: none;\n}\n\n.decision-table-grid {\n\tfont-size: 13px;\n\tline-height: 20px\n}\n\n.decision-table-output-expression-input, .decision-table-output-expression-input:active, .decision-table-output-expression-input:focus, .decision-table-output-expression-input:visited {\n\tbackground-color: inherit;\n}\n\n.decision-table-output-expression-input:hover {\n\tbackground-color: #287d92;\n}\n\n.decision-table-input-expression-input .caret {\n\tdisplay:none;\n}\n\n.decision-table-grid .ui-grid-row.ui-grid-row-selected  .cell-input-expression > [ui-grid-row] > .ui-grid-cell {\n\tbackground: rgba(92, 184, 92, 0.4);\n}\n\n.decision-table-grid .ui-grid-row:nth-child(odd) .ui-grid-cell.cell-output-expression,\n.decision-table-grid .ui-grid-row:nth-child(even) .ui-grid-cell.cell-output-expression  {\n\tbackground: rgb(92, 184, 92);\n\t/* RGBa with 0.6 opacity */\n\tbackground: rgba(92, 184, 92, 0.1);\n\tborder-bottom: 1px solid rgba(43, 37, 37, 0.22);\n}\n\n.decision-table-grid .ui-grid-row.ui-grid-row-selected:nth-child(odd) .ui-grid-cell.cell-output-expression,\n.decision-table-grid .ui-grid-row.ui-grid-row-selected:nth-child(even) .ui-grid-cell.cell-output-expression  {\n\tbackground: rgba(92, 184, 92, 0.2);\n}\n\n.decision-table-grid .ui-grid-row:nth-child(odd) .ui-grid-cell.cell-input-expression,\n.decision-table-grid .ui-grid-row:nth-child(even) .ui-grid-cell.cell-input-expression {\n\tbackground: rgb(54, 167, 196);\n\t/* RGBa with 0.6 opacity */\n\tbackground: rgba(54, 167, 196, 0.1);\n\tborder-bottom: 1px solid rgba(43, 37, 37, 0.22);\n}\n\n.decision-table-grid .ui-grid-row.ui-grid-row-selected:nth-child(odd) .ui-grid-cell.cell-input-expression,\n.decision-table-grid .ui-grid-row.ui-grid-row-selected:nth-child(even) .ui-grid-cell.cell-input-expression {\n\tbackground: rgba(54, 167, 196, 0.2);\n}\n\n.decision-table-grid .ui-grid-render-container-left .ui-grid-header-cell {\n\t/* Fallback for web browsers that doesn't support RGBa */\n\tbackground: rgb(54, 167, 196);\n\t/* RGBa with 0.6 opacity */\n\tbackground: rgba(54, 167, 196, 0.6);\n\t/*background-color: #668b94;*/\n\tcolor: #ffffff;\n\tfont-size: 14px;\n\n\tborder-bottom: 5px solid rgb(43, 37, 37);\n\tborder-bottom: 5px solid rgba(43, 37, 37, 0.22);\n\n}\n\n.decision-table-grid .ui-grid-pinned-container.ui-grid-pinned-container-left .ui-grid-header-cell:last-child {\n\tborder-top-width: 0px;\n\tborder-right-width: 0px;\n\tborder-left-width: 0px;\n\tborder-bottom: 5px solid rgb(43, 37, 37);\n\tborder-bottom: 5px solid rgba(43, 37, 37, 0.22);\n}\n\n.decision-table-grid .ui-grid-cell-focus {\n\toutline: 0;\n\tbackground-color: transparent;\n}\n\n.decision-table .ui-grid-row-selected .customRowHeader {\n\tbackground-color: #c9dde1;\n\tcolor: #ffffff;\n\tborder-bottom: 1px solid rgba(43, 37, 37, 0.22);\n}\n\n.decision-table .ui-grid-cell-contents {\n\tposition: relative;\n}\n\n.decision-table .ui-grid-cell-contents-empty::before {\n\tcontent: \"-\";\n\ttext-align: center;\n\twidth: 100%;\n\tposition: absolute;\n\theight: 100%;\n\tcolor: gray;\n}\n\n.decision-table .ui-grid-cell-contents .show-error-icon {\n\tdisplay: none;\n}\n\n.decision-table .ui-grid-cell-contents .edit-icon {\n\tposition: absolute;\n\tright: 0;\n}\n\n.decision-table .ui-grid-cell-contents.ui-grid-cell-contents-has-error {\n\tpadding-left: 20px;\n}\n\n.decision-table .decision-table-grid-wrapper {\n\tposition: relative;\n\tmargin-top: 10px;\n}\n.decision-table .decision-table-grid-wrapper > span {\n\tdisplay: none;\n}\n\n.decision-table .decision-table-grid-wrapper .ui-grid-header-cell .ui-grid-cell-contents .text-center {\n\tmin-height: 20px;\n}\n\n.decision-table .decision-table-grid-wrapper.ui-grid-cell-contents-has-error > .decision-table-grid {\n\tborder: 1px solid #a94442;\n}\n\n.decision-table .ui-grid-cell-contents.ui-grid-cell-contents-has-error .contents-value,\n.decision-table .ui-grid-cell-contents.ui-grid-cell-contents-has-error .text-center {\n\tcolor: #a94442;\n}\n\n.decision-table .ui-grid-cell-contents.ui-grid-cell-contents-has-error .show-error-icon,\n.decision-table .decision-table-grid-wrapper.ui-grid-cell-contents-has-error .show-error-icon {\n\tdisplay: block;\n\tposition: absolute;\n\ttop: 0;\n\tleft: 0;\n\tpadding: 3px;\n\tcursor: pointer;\n\tz-index: 1;\n}\n\n.activiti-table .ui-grid-pinned-container .ui-grid-header-cell-row::before {\n\tcontent: \"#\";\n\tposition: absolute;\n\twidth: 100%;\n\ttext-align: center;\n\ttop: 50%;\n\t-webkit-transform: translateY(-50%);\n\t-ms-transform: translateY(-50%);\n\ttransform: translateY(-50%);\n}\n\n.activiti-table .ui-grid-top-panel {\n\tbackground: #FAFAFB none repeat scroll 0% 0%;\n\tfont-weight: normal;\n}\n\n.activiti-table .ui-grid-top-panel .header-output-expression {\n\tbackground: #f2f2f3 none repeat scroll 0% 0%;\n}\n\n.activiti-table .ui-grid-top-panel .text-center {\n\tmin-height: 20px;\n}\n\n.activiti-table .ui-grid-top-panel .text-center.subtle {\n\ttext-transform: uppercase;\n\tmin-height: 15px;\n\tfont-size: 10px;\n\tmargin-top: 3px;\n}\n\n.activiti-table .ui-grid-top-panel .text-value,\n.activiti-table .ui-grid-top-panel .text-label {\n\ttext-overflow: ellipsis;\n\toverflow: hidden;\n}\n\n.activiti-table .ui-grid-top-panel .text-label {\n\tcolor: #646464;\n}\n\n.activiti-table .ui-grid-top-panel .text-value {\n\tfont-family: 'Courier', 'Lato', sans-serif;\n\tfont-size: 12px;\n}\n\n.activiti-table .ui-grid,\n.activiti-table .ui-grid-pinned-container.ui-grid-pinned-container-left .ui-grid-header-cell:last-child\n{\n\tborder: none;\n}\n\n.activiti-table .ui-grid-pinned-container.ui-grid-pinned-container-left .ui-grid-cell:last-child,\n.activiti-table .ui-grid-header-cell,\n.activiti-table .ui-grid-cell {\n\tborder-right: none;\n}\n\n.activiti-table .ui-grid-top-panel .header-output-expression--first {\n\tborder-left: 1px solid #d4d4d4;\n}\n\n.activiti-table .ui-grid-canvas {\n\tpadding-top: 0;\n}\n\n.activiti-table .ui-grid-row .ui-grid-cell.ui-grid-row-header-cell {\n\tbackground-color: white;\n\tborder-bottom: none;\n}\n.activiti-table .ui-grid-row:nth-child(odd) .ui-grid-cell {\n\tbackground-color: white;\n}\n.activiti-table .ui-grid-row:nth-child(even) .ui-grid-cell {\n\tbackground-color: #fcfcfc;\n}\n\n\n.activiti-table .ui-grid-row {\n\tmargin-top: 2px;\n\tmargin-bottom: 1px;\n}\n\n.activiti-table .ui-grid-cell-contents {\n\tmargin-left: 1px;\n\tmargin-right: 1px;\n}\n.activiti-table .decision-table-display-cell-notexecuted {\n\n}\n.activiti-table .cell-expression {\n\tposition: relative;\n\toverflow: visible;\n}\n.activiti-table .decision-table-display-cell-match {\n\tborder: 1px solid #2980b9;\n}\n\n.activiti-table .decision-table-display-cell-nomatch,\n.activiti-table .decision-table-display-cell-exception {\n\tborder: 1px solid #9C4337;\n}\n\n.activiti-table .decision-table-display-cell-exception::before {\n\tcontent: \"!\";\n\tbackground-color: #9C4337;\n\tcolor: white;\n\tborder-radius: 10px;\n\tposition: absolute;\n\tright: 0;\n\tdisplay: block;\n\twidth: 20px;\n\ttext-align: center;\n\theight: 20px;\n\tmargin-right: 5px;\n\tfont-weight: bold;\n}\n\n.activiti-table .header-output-expression-first,\n.activiti-table .cell-output-expression-first {\n\tborder-left: 1px solid #d4d4d4;\n}\n\n.activiti-table .cell-output-expression-first::before {\n\tcontent: \"\";\n\tposition: absolute;\n\ttop: -2px;\n\tleft: -1px;\n\tbackground-color: #d4d4d4;\n\twidth: 1px;\n\theight: 3px;\n}\n\n.activiti-table .section h3 {\n\tmargin: 0;\n\tmargin-bottom: 1rem;\n\tfont-size: 14px;\n\tcolor: rgb(100,100,100);\n\tletter-spacing: 1px;\n\ttext-transform: uppercase;\n}\n\n.activiti-table .ui-grid.activiti-ui-grid-noscroll {\n\theight: auto !important;\n\tmargin-bottom: 2rem;\n}\n\n.activiti-table .ui-grid.activiti-ui-grid-noscroll .ui-grid-render-container-body .ui-grid-viewport {\n\toverflow-x: auto !important;\n\toverflow-y: auto !important;\n\theight: auto !important;\n}\n\n.activiti-table h3.header-expandable {\n\tcursor: pointer;\n}\n\n.activiti-table h3.header-expandable span.glyphicon {\n\tvertical-align: middle;\n\tdisplay: inline-block;\n\tmargin-top: -6px;\n}\n\n.activiti-table h3.header-expandable.header-expanded span.glyphicon {\n\t-ms-transform: rotate(90deg); /* IE 9 */\n\t-webkit-transform: rotate(90deg); /* Chrome, Safari, Opera */\n\ttransform: rotate(90deg);\n}\n\n.activiti-table .section.pack {\n\tmin-height: inherit;\n}\n.activiti-table .section {\n\tmargin: 10px 0;\n\tpadding: 10px 0 0px 0;\n\tmin-height: 120px;\n}\n.activiti-table label {\n\tcolor: #636363;\n\tfont-size: 14px;\n\tdisplay: inline-block;\n\tmargin-bottom: 5px;\n\tfont-weight: 700;\n}\n.form-preview input:disabled, .form-preview select:disabled, .form-preview textarea:disabled {\n    background: #fff;\n    cursor: default;\n}\n.form-popup input:disabled, .form-popup select:disabled, .form-popup textarea:disabled {\n    cursor: default;\n}\n\n.publish-pop-body .ngViewport {\n\toverflow-x: hidden;\n}\n"
  },
  {
    "path": "flowable-ui-web/admin/views/app-definition.html",
    "content": "<div class=\"container\" id=\"detail-container\">\n\t<div class=\"row\">\n\t\t<div class=\"col-md-9\">\n\t\t\t<div class=\"component\" ng-show=\"definition\">\n\t\t\t\t<div class=\"title\">\n\t\t\t\t\t<div class=\"pull-right\">\n\t\t\t\t\t\t<a ng-click=\"returnToList()\" class=\"action\">&larr; {{'GENERAL.ACTION.RETURN-TO-LIST' | translate}}</a>\n\t\t\t\t\t</div>\n\t\t\t\t\t<h2>{{definition.name &amp;&amp; definition.name +\" - \" || \"\"}}{{definition.id}}</h2>\n\t\t\t\t</div>\n\n\t\t\t\t<div class=\"property-wrapper\">\n\t\t\t\t\t<table>\n\t\t\t\t\t\t<tr class=\"property\">\n\t\t\t\t\t\t\t<td class=\"property-name\" translate=\"APP-DEFINITION.ID\"></td>\n\t\t\t\t\t\t\t<td>{{definition.id}}</td>\n\t\t\t\t\t\t\t<td class=\"property-name\" translate=\"APP-DEFINITION.VERSION\"></td>\n\t\t\t\t\t\t\t<td>{{definition.version}}</td>\n\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t<tr class=\"property\">\n\t\t\t\t\t\t\t<td class=\"property-name\" translate=\"APP-DEFINITION.NAME\"></td>\n\t\t\t\t\t\t\t<td>{{definition.name | empty}}</td>\n\t\t\t\t\t\t\t<td class=\"property-name\" translate=\"APP-DEFINITION.KEY\"></td>\n\t\t\t\t\t\t\t<td>{{definition.key}}</td>\n\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t<tr class=\"property\">\n\t\t\t\t\t\t\t<td class=\"property-name\" translate=\"APP-DEFINITION.CATEGORY\"></td>\n\t\t\t\t\t\t\t<td>{{definition.category | empty}}</td>\n\t\t\t\t\t\t\t<td class=\"property-name\" translate=\"APP-DEFINITION.DESCRIPTION\"></td>\n\t\t\t\t\t\t\t<td>{{definition.description | empty}}</td>\n\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t<tr class=\"property\">\n\t\t\t\t\t\t\t<td class=\"property-name\" translate=\"APP-DEFINITION.DEPLOYMENT\"></td>\n\t\t\t\t\t\t\t<td><a ng-click=\"openDeployment(definition.deploymentId)\"><i class=\"glyphicon glyphicon-zoom-in\"></i> {{definition.deploymentId}}</a></td>\n\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t<tr class=\"property\">\n                            <td class=\"property-name\" translate=\"APP-DEFINITION.TENANT\"></td>\n                            <td>{{definition.tenantId | empty}}</td>\n                        </tr>\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<div class=\"col-md-3\">\n\t\t\t<div class=\"component tip-left\">\n\t\t\t\t<div class=\"title\">\n\t\t\t\t\t<h2 translate=\"GENERAL.TITLE.ACTIONS\"></h2>\n\t\t\t\t</div>\n\t\t\t\t<ul class=\"list-group\">\n\t\t\t\t\t  \n\t\t\t\t</ul>\n\t\t\t</div>\n\t\t</div>\n\t</div>\n\t<div class=\"row\">\n\t\t<div class=\"col-md-9\">\n\t\t\t<div class=\"component\">\n\t\t\t\t<div class=\"tabs-wrapper\">\n\t\t\t\t\t<div class=\"tabs clearfix\">\n\t\t       \t\t\t<div class=\"tab\" ng-repeat=\"tab in tabData.tabs\" ng-class=\"{'active': tabData.activeTab == tab.id}\">\n\t\t       \t\t\t\t<a ng-click=\"tabData.activeTab = tab.id\">\n\t\t       \t\t\t\t\t{{tab.name | translate:node}}&nbsp;\n\t\t    \t\t\t\t\t<span class=\"badge\" ng-if=\"tab.info != undefined\">{{tab.info}}</span>\n\t\t    \t\t\t\t</a>\n\t\t       \t\t\t</div>\n\t\t       \t\t</div>\n\t\t        \t<div class=\"title\"></div>\n\n\t\t        \t<div class=\"grid-wrapper\" ng-if=\"processDefinitions && tabData.activeTab == tabData.tabs[0].id\" >\n\t\t\t\t\t\t<div class=\"grid-message\" ng-if=\"processDefinitions.size > 0\">\n\t                        <span>{{'APP-DEFINITION.PROCESS-DEFINITIONS-SIZE' | translate:processDefinitions}}</span>\n\t                    </div>\n\t                     <div class=\"grid-message\" ng-if=\"processDefinitions.size == 0\">\n\t                        <span>{{'APP-DEFINITION.PROCESS-DEFINITIONS-EMPTY' | translate}}</span>\n\t                    </div>\n\t\t\t\t\t\t<div ng-grid=\"gridProcessDefinitions\" class=\"gridStyle\" ng-if=\"processDefinitions\" ng-show=\"processDefinitions.size > 0\"></div>\n\t\t\t\t\t</div>\n\n\t\t\t\t\t<div class=\"grid-wrapper\" ng-if=\"caseDefinitions && tabData.activeTab == tabData.tabs[1].id\" >\n                        <div class=\"grid-message\" ng-if=\"caseDefinitions.size > 0\">\n                            <span>{{'APP-DEFINITION.CASE-DEFINITIONS-SIZE' | translate:caseDefinitions}}</span>\n                        </div>\n                         <div class=\"grid-message\" ng-if=\"caseDefinitions.size == 0\">\n                            <span>{{'APP-DEFINITION.CASE-DEFINITIONS-EMPTY' | translate}}</span>\n                        </div>\n                        <div ng-grid=\"gridCaseDefinitions\" class=\"gridStyle\" ng-if=\"caseDefinitions\" ng-show=\"caseDefinitions.size > 0\"></div>\n                    </div>\n\t\t\t\t\t\n\t\t\t\t\t<div class=\"grid-wrapper\" ng-if=\"decisionTables && tabData.activeTab == tabData.tabs[2].id\">\n\t\t\t\t\t\t<div class=\"grid-message\" ng-if=\"decisionTables.size > 0\">\n\t                        <span>{{'APP-DEFINITION.DECISION-TABLES-SIZE' | translate:decisionTables}}</span>\n\t                    </div>\n\t                     <div class=\"grid-message\" ng-if=\"decisionTables.size == 0\">\n\t                        <span>{{'APP-DEFINITION.DECISION-TABLES-EMPTY' | translate}}</span>\n\t                    </div>\n\t\t\t\t\t\t<div ng-grid=\"gridDecisionTables\" class=\"gridStyle\" ng-if=\"decisionTables\" ng-show=\"decisionTables.size > 0\"></div>\n\t\t\t\t\t</div>\n\t\t\t\t\t\n\t\t\t\t\t<div class=\"grid-wrapper\" ng-if=\"formDefinitions && tabData.activeTab == tabData.tabs[3].id\">\n\t\t\t\t\t\t<div class=\"grid-message\" ng-if=\"formDefinitions.size > 0\">\n\t                        <span>{{'APP-DEFINITION.FORM-DEFINITIONS-SIZE' | translate:formDefinitions}}</span>\n\t                    </div>\n\t                     <div class=\"grid-message\" ng-if=\"formDefinitions.size == 0\">\n\t                        <span>{{'APP-DEFINITION.FORM-DEFINITIONS-EMPTY' | translate}}</span>\n\t                    </div>\n\t\t\t\t\t\t<div ng-grid=\"gridFormDefinitions\" class=\"gridStyle\" ng-if=\"formDefinitions\" ng-show=\"formDefinitions.size > 0\"></div>\n\t\t\t\t\t</div>\n\n\t        \t</div>\n\t\t\t</div>\n\t\t</div>\n\t</div>\n</div>\n<div>\n</div>\n"
  },
  {
    "path": "flowable-ui-web/admin/views/app-definitions.html",
    "content": "<!-- LIST PAGE -->\n<div class=\"container\" id=\"list-container\">\n    <div class=\"row\">\n        <div class=\"col-md-8\">\n            <div class=\"component\">\n                <div class=\"title\">\n                    <div class=\"btn-group btn-group-sm pull-right\">\n                        <div class=\"btn-group btn-group-sm\">\n                            <button type=\"button\" class=\"btn btn-default dropdown-toggle\" data-toggle=\"dropdown\"\n                                    translate=\"GENERAL.ACTION.SHOW-RESULTS\" translate-value-size=\"{{'GENERAL.RESULT-SIZES.' + filter.resultSize | translate}}\">\n                                &nbsp;\n                                <span class=\"caret\"></span>\n                            </button>\n                            <ul class=\"dropdown-menu\">\n                            \t<li ng-repeat=\"resultSize in config.filter.resultSizes\"><a href=\"\" ng-click=\"filter.setResultSize(resultSize)\">{{'GENERAL.RESULT-SIZES.' + resultSize.toString() | translate}}</a></li>\n                            </ul>\n                        </div>\n                        <button type=\"button\" class=\"btn btn-default\" ng-click=\"filter.toggleOrder()\">\n                        \t<i class=\"glyphicon\" ng-class=\"{'glyphicon-sort-by-attributes': filter.order == 'asc', 'glyphicon-sort-by-attributes-alt': filter.order == 'desc'}\"></i>\n                        </button>\n                    </div>\n                    <div class=\"btn-group btn-group-sm pull-right\">\n                    \t<button type=\"button\" class=\"btn btn-default dropdown-toggle\" data-toggle=\"dropdown\"\n                                translate=\"GENERAL.ACTION.SHOW-RESULTS\" translate-value-size=\"{{'GENERAL.RESULT-SIZES.' + filter.resultSize | translate}}\">\n                            &nbsp;\n                            <span class=\"caret\"></span>\n                        </button>\n                    \t<ul class=\"dropdown-menu\">\n                           <li ng-repeat=\"sort in filter.sortObjects\"><a href=\"\" ng-click=\"filter.setSort(sort)\">{{sort.name | translate}}</a></li>\n                        </ul>\n                    </div>\n                    <div class=\"btn-group btn-group-sm pull-right\">\n                        <a class=\"btn btn-default\" role=\"button\"\n                           title=\"{{'GENERAL.ACTION.REFRESH-LIST' | translate}}\"\n                           ng-click=\"filter.refresh();\">\n                            <i class=\"glyphicon glyphicon-refresh\"></i>\n                        </a>\n                    </div>\n                    <div class=\"pull-right loading\" ng-show=\"filter.loading\">\n                    \t<i class=\"glyphicon glyphicon-refresh\"></i>\n                    </div>\n                    <h2>{{'APP-DEFINITIONS.TITLE.MAIN' | translate:job}}</h2>\n                </div>\n\n                <div class=\"grid-wrapper\" id=\"app-definitions\">\n                    <div class=\"grid-message\" ng-if=\"appDefinitionsData.size > 0\">\n                         <span>{{'APP-DEFINITIONS.LIST-MESSAGE' | translate:appDefinitionsData}}</span>\n                    </div>\n                     <div class=\"grid-message\" ng-if=\"appDefinitionsData.size == 0\">\n                        <span>{{'APP-DEFINITIONS.LIST-MESSAGE-EMPTY' | translate}}</span>\n                    </div>\n                    <div ng-grid=\"gridDefinitions\" class=\"gridStyle\" ng-if=\"gridDefinitions && appDefinitionsData.data\" />\n                </div>\n            </div>\n        </div>\n        <div class=\"col-md-4\">\n\n            <!-- FILTERS -->\n            <div class=\"component tip-left\">\n                <div class=\"title\">\n                    <div class=\"btn-group btn-group-sm pull-right\">\n                        <button type=\"button\" class=\"btn btn-default\" data-toggle=\"dropdown\" ng-show=\"filter.supportedProperties.length > 0\">\n                            <i class=\"glyphicon glyphicon-plus\"></i>\n                        </button>\n                        <ul class=\"dropdown-menu\">\n                            <li ng-repeat=\"prop in filter.supportedProperties\"><a href=\"\" ng-click=\"filter.addProperty(prop)\">{{prop.name | translate}}</a></li>\n                        </ul>\n                    </div>\n                    <div class=\"pull-right\">\n                        <a class=\"action\" ng-click=\"filter.clear()\" translate=\"GENERAL.ACTION.CLEAR-FILTERS\"></a>\n                    </div>\n                    <h2>Filter</h2>\n                </div>\n                <div class=\"section\" ng-if=\"filter.properties.latest !== undefined\">\n\t              <div class=\"subtitle\"><label for=\"filter-latest\" translate=\"APP-DEFINITIONS.FILTER.LATEST\"></label> </div>\n               \t  <div class=\"input-group input-group-sm\">\n               \t  \t<input type=\"checkbox\" id=\"filter-latest\" ng-model=\"filter.properties.latest\" ng-change=\"toggleLatestVersion()\" />&nbsp;<span class=\"check\" translate=\"CASE-DEFINITIONS.FILTER.LATEST-HELP\"></span>\n\t              </div>\n\t            </div>\n                <div class=\"section\" ng-if=\"filter.properties.nameLike !== undefined\">\n                    <div class=\"subtitle\"><label for=\"filter-nameLike\" translate=\"APP-DEFINITIONS.FILTER.NAME\"></label> </div>\n                    <div class=\"input-group input-group-sm\">\n                        <input ng-disabled=\"filter.properties.latest == true\" id=\"filter-nameLike\" type=\"text\" class=\"form-control\" value=\"\" ng-model=\"filter.properties.nameLike\" ng-change=\"filter.refreshDelayed()\">\n                    </div>\n                </div>\n                <div class=\"section\" ng-if=\"filter.properties.keyLike !== undefined\">\n                    <div class=\"subtitle\"><label for=\"filter-keyLike\" translate=\"APP-DEFINITIONS.FILTER.KEY\"></label> </div>\n                    <div class=\"input-group input-group-sm\">\n                        <input id=\"filter-keyLike\" type=\"text\" class=\"form-control\" value=\"\" ng-model=\"filter.properties.keyLike\" ng-change=\"filter.refreshDelayed()\">\n                    </div>\n                </div>\n                <div class=\"section\" ng-if=\"filter.properties.deploymentId !== undefined\">\n                    <div class=\"subtitle\"><label for=\"filter-deploymentId\" translate=\"APP-DEFINITIONS.FILTER.DEPLOYMENT-ID\"></label> </div>\n                    <div class=\"input-group input-group-sm\">\n                        <input ng-disabled=\"filter.properties.latest == true\" id=\"filter-deploymentId\" type=\"text\" class=\"form-control\" value=\"\" ng-model=\"filter.properties.deploymentId\" ng-change=\"filter.refreshDelayed()\">\n                    </div>\n                </div>\n                <div class=\"section\" ng-if=\"filter.properties.tenantIdLike !== undefined\">\n                    <div class=\"subtitle\"><label for=\"filter-tenantId\" translate=\"APP-DEFINITIONS.FILTER.TENANT-ID\"></label> </div>\n                    <div class=\"input-group input-group-sm\">\n                        <input id=\"filter-tenantId\" type=\"text\" class=\"form-control\" value=\"\" ng-model=\"filter.properties.tenantIdLike\" ng-change=\"filter.refreshDelayed()\">\n                    </div>\n                </div>\n            </div>\n        </div>\n    </div>\n</div>"
  },
  {
    "path": "flowable-ui-web/admin/views/app-deployment.html",
    "content": "<div class=\"container\" id=\"detail-container\">\n\t<div class=\"row\">\n\t\t<div class=\"col-md-9\">\n\t\t\t<div class=\"component\" ng-show=\"appDeployment\">\n\t\t\t\t<div class=\"title\">\n\t\t\t\t\t<div class=\"pull-right\">\n\t\t\t\t\t\t<a ng-click=\"returnToList()\" class=\"action\">&larr; {{'GENERAL.ACTION.RETURN-TO-LIST' | translate}}</a>\n\t\t\t\t\t</div>\n\t\t\t\t\t<h2>{{appDeployment.name || appDeployment.id}}</h2>\n\t\t\t\t</div>\n\n\t\t\t\t<div class=\"property-wrapper\">\n\t\t\t\t\t<table>\n\t\t\t\t\t\t<tr class=\"property\">\n\t\t\t\t\t\t\t<td class=\"property-name\" translate=\"APP-DEPLOYMENT.ID\"></td>\n\t\t\t\t\t\t\t<td>{{appDeployment.id}}</td>\n\t\t\t\t\t\t\t<td class=\"property-name\" translate=\"APP-DEPLOYMENT.NAME\"></td>\n\t\t\t\t\t\t\t<td>{{appDeployment.name | empty}}</td>\n\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t<tr class=\"property\">\n\t\t\t\t\t\t\t<td class=\"property-name\" translate=\"APP-DEPLOYMENT.TIME\"></td>\n\t\t\t\t\t\t\t<td>{{appDeployment.deploymentTime | dateformat}}</td>\n\t\t\t\t\t\t\t<td class=\"property-name\" translate=\"APP-DEPLOYMENT.CATEGORY\"></td>\n\t\t\t\t\t\t\t<td>{{appDeployment.category | empty}}</td>\n\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t<tr class=\"property\">\n                            <td class=\"property-name\" translate=\"APP-DEPLOYMENT.TENANTID\"></td>\n                            <td>{{appDeployment.tenantId | empty}}</td>\n                        </tr>\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 class=\"col-md-3\">\n\t\t\t<div class=\"component tip-left\">\n\t\t\t\t<div class=\"title\">\n\t\t\t\t\t<h2 translate=\"GENERAL.TITLE.ACTIONS\"></h2>\n\t\t\t\t</div>\n\t\t\t\t<ul class=\"list-group\">\n\t\t\t\t\t  <li>\n\t\t\t\t\t    <button type=\"button\" class=\"btn btn-sm btn-default btn-danger\" ng-click=\"deleteDeployment()\">\n\t\t\t\t\t\t\t<i class=\"glyphicon glyphicon-remove\"></i><span translate=\"APP-DEPLOYMENTS.ACTION.DELETE\"></span>\n\t\t\t\t\t    </button>\n\t\t\t\t\t  </li>\n\t\t\t\t</ul>\n\t\t\t</div>\n\t\t</div>\n\t</div>\n\t<div class=\"row\">\n\t\t<div class=\"col-md-9\">\n\t\t\t<div class=\"component\">\n\t\t\t\t<div class=\"title\">\n\t\t\t\t\t<h2 translate=\"APP-DEPLOYMENT.TITLE.APP-DEFINITIONS\"></h2>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"grid-wrapper grid-wrapper-compact\" ng-if=\"appDefinitions\">\n\t\t\t\t\t<div class=\"grid-message\" ng-if=\"appDefinitions.size > 0\">\n\t                       <span>{{'APP-DEPLOYMENT.DEFINITIONS-MESSAGE' | translate:appDefinitions}}</span>\n\t                   </div>\n\t                    <div class=\"grid-message\" ng-if=\"appDefinitions.size == 0\">\n\t                       <span>{{'APP-DEPLOYMENT.DEFINITIONS-MESSAGE-EMPTY' | translate}}</span>\n\t                   </div>\n\t\t\t\t\t<div ng-grid=\"gridAppDefinitions\" class=\"gridStyle\" ng-if=\"gridAppDefinitions && appDefinitions.data\" ng-show=\"appDefinitions.size > 0\"></div>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</div>\n\t</div>\n</div>\n"
  },
  {
    "path": "flowable-ui-web/admin/views/app-deployments.html",
    "content": "<!-- LIST PAGE -->\n<div class=\"container\" id=\"list-container\">\n    <div class=\"row\">\n        <div class=\"col-md-8\">\n            <div class=\"component\">\n                <div class=\"title\">\n                    <div class=\"btn-group btn-group-sm pull-right\">\n                        <div class=\"btn-group btn-group-sm\">\n                            <button type=\"button\" class=\"btn btn-default dropdown-toggle\" data-toggle=\"dropdown\"\n                                    translate=\"GENERAL.ACTION.SHOW-RESULTS\" translate-value-size=\"{{'GENERAL.RESULT-SIZES.' + filter.resultSize | translate}}\">\n                                &nbsp;\n                                <span class=\"caret\"></span>\n                            </button>\n                            <ul class=\"dropdown-menu\">\n                            \t<li ng-repeat=\"resultSize in config.filter.resultSizes\"><a href=\"\" ng-click=\"filter.setResultSize(resultSize)\">{{'GENERAL.RESULT-SIZES.' + resultSize.toString() | translate}}</a></li>\n                            </ul>\n                        </div>\n                        <button type=\"button\" class=\"btn btn-default\" ng-click=\"filter.toggleOrder()\">\n                        \t<i class=\"glyphicon\" ng-class=\"{'glyphicon-sort-by-attributes': filter.order == 'asc', 'glyphicon-sort-by-attributes-alt': filter.order == 'desc'}\"></i>\n                        </button>\n                    </div>\n                    <div class=\"btn-group btn-group-sm pull-right\">\n                    \t<button type=\"button\" class=\"btn btn-default dropdown-toggle\" data-toggle=\"dropdown\"\n                                translate=\"GENERAL.ACTION.SHOW-RESULTS\" translate-value-size=\"{{'GENERAL.RESULT-SIZES.' + filter.resultSize | translate}}\">\n\t\t\t\t\t\t    &nbsp;\n                            <span class=\"caret\"></span>\n                        </button>\n                    \t<ul class=\"dropdown-menu\">\n                           <li ng-repeat=\"sort in filter.sortObjects\"><a href=\"\" ng-click=\"filter.setSort(sort)\">{{sort.name | translate}}</a></li>\n                        </ul>\n                    </div>\n                    <div class=\"btn-group btn-group-sm pull-right\">\n                        <a class=\"btn btn-default\" role=\"button\"\n                           title=\"{{'GENERAL.ACTION.REFRESH-LIST' | translate}}\"\n                           ng-click=\"filter.refresh();\">\n                            <i class=\"glyphicon glyphicon-refresh\"></i>\n                        </a>\n                    </div>\n                    <div class=\"pull-right loading\" ng-show=\"filter.loading\">\n                    \t<i class=\"glyphicon glyphicon-refresh\"></i>\n                    </div>\n                    <h2 translate=\"APP-DEPLOYMENTS.TITLE\"></h2>\n                </div>\n\n                <div class=\"grid-wrapper\" id=\"deployments\">\n                    <div class=\"grid-message\" ng-if=\"appDeploymentsData.size > 0\">\n                        <span>{{'APP-DEPLOYMENTS.LIST-MESSAGE' | translate:appDeploymentsData}}</span>\n                    </div>\n                     <div class=\"grid-message\" ng-if=\"deploymentsData.size == 0\">\n                        <span>{{'APP-DEPLOYMENTS.LIST-MESSAGE-EMPTY' | translate}}</span>\n                    </div>\n                    <div ng-grid=\"gridAppDeployments\" class=\"gridStyle\" ng-if=\"gridAppDeployments && appDeploymentsData.data\"/>\n                </div>\n            </div>\n        </div>\n        <div class=\"col-md-4\">\n\n            <!-- Deployment filters -->\n            <div class=\"component tip-left\">\n                <div class=\"title\">\n                    <div class=\"pull-right\">\n                        <a class=\"action\" ng-click=\"filter.clear()\" translate=\"GENERAL.ACTION.CLEAR-FILTERS\"></a>\n                    </div>\n                    <h2 translate=\"GENERAL.TITLE.FILTERS\"></h2>\n                </div>\n                <div class=\"section\" ng-if=\"filter.properties.nameLike !== undefined\">\n                    <div class=\"subtitle\"><label for=\"filter-nameLike\" translate=\"APP-DEPLOYMENTS.FILTER.NAME\"></label> </div>\n                    <div class=\"input-group input-group-sm\">\n                        <input id=\"filter-nameLike\" type=\"text\" class=\"form-control\" value=\"\" ng-model=\"filter.properties.nameLike\" ng-change=\"filter.refreshDelayed()\">\n                    </div>\n                </div>\n                <div class=\"section\" ng-if=\"filter.properties.tenantIdLike !== undefined\">\n                    <div class=\"subtitle\"><label for=\"filter-tenantIdLike\" translate=\"APP-DEPLOYMENTS.FILTER.TENANTID\"></label> </div>\n                    <div class=\"input-group input-group-sm\">\n                        <input id=\"filter-tenantIdLike\" type=\"text\" class=\"form-control\" value=\"\" ng-model=\"filter.properties.tenantIdLike\" ng-change=\"filter.refreshDelayed()\">\n                    </div>\n                </div>\n            </div>\n\n            <!-- Actions -->\n            <div class=\"component no-min-height\">\n                <div class=\"title\">\n                    <h2 translate=\"GENERAL.TITLE.ACTIONS\"></h2>\n                </div>\n                <ul class=\"list-group\">\n                    <li>\n                        <button type=\"button\" class=\"btn btn-sm btn-default\" ng-click=\"uploadDeployment()\">\n                            <i class=\"glyphicon glyphicon-open\"></i>{{'APP-DEPLOYMENTS.ACTION.UPLOAD' | translate}}\n                        </button>\n                    </li>\n                </ul>\n            </div>\n\n        </div>\n\n        </div>\n    </div>\n</div>"
  },
  {
    "path": "flowable-ui-web/admin/views/case-definition-diagram-popup.html",
    "content": "<div class=\"modal-header-wrapper\">\n\t<div class=\"modal-header\">\n\t\t<div class=\"pull-right\">\n            <a class=\"action\" ng-click=\"cancel()\">&times; {{'GENERAL.ACTION.CANCEL-AND-CLOSE' | translate}}</a>\n        </div>\n\t\t<h2>{{'CASE-DEFINITION.POPUP.SHOW-CASE-MODEL.TITLE' | translate}} '{{model.name &amp;&amp; model.name || model.key}}'</h2>\t\n\t</div>\n</div>\n<div class=\"modal-body modal-body-medium\">\n\t<div id=\"cmmnModel\" style=\"margin-left:auto;margin-right:auto\"></div>\n</div>\n\n<div class=\"modal-footer-wrapper\">\n\t<div class=\"modal-footer\">\n\t\t<div class=\"pull-right\">\n\t       <button type=\"button\" class=\"btn btn-sm btn-default\" ng-click=\"cancel()\" ng-disabled=\"status.loading\"\n\t\t       \ttranslate=\"GENERAL.ACTION.CLOSE\">\n\t       \t</button>\n\t\t</div>\n\t</div>\n</div>\t"
  },
  {
    "path": "flowable-ui-web/admin/views/case-definition.html",
    "content": "<div class=\"container\" id=\"detail-container\">\n\t<div class=\"row\">\n\t\t<div class=\"col-md-9\">\n\t\t\t<div class=\"component\" ng-show=\"definition\">\n\t\t\t\t<div class=\"title\">\n\t\t\t\t\t<div class=\"pull-right\">\n\t\t\t\t\t\t<a ng-click=\"returnToList()\" class=\"action\">&larr; {{'GENERAL.ACTION.RETURN-TO-LIST' | translate}}</a>\n\t\t\t\t\t</div>\n\t\t\t\t\t<h2>{{definition.name &amp;&amp; definition.name +\" - \" || \"\"}}{{definition.id}}</h2>\n\t\t\t\t</div>\n\n\t\t\t\t<div class=\"property-wrapper\">\n\t\t\t\t\t<table>\n\t\t\t\t\t\t<tr class=\"property\">\n\t\t\t\t\t\t\t<td class=\"property-name\" translate=\"CASE-DEFINITION.ID\"></td>\n\t\t\t\t\t\t\t<td>{{definition.id}}</td>\n\t\t\t\t\t\t\t<td class=\"property-name\" translate=\"CASE-DEFINITION.VERSION\"></td>\n\t\t\t\t\t\t\t<td>{{definition.version}}</td>\n\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t<tr class=\"property\">\n\t\t\t\t\t\t\t<td class=\"property-name\" translate=\"CASE-DEFINITION.NAME\"></td>\n\t\t\t\t\t\t\t<td>{{definition.name | empty}}</td>\n\t\t\t\t\t\t\t<td class=\"property-name\" translate=\"CASE-DEFINITION.KEY\"></td>\n\t\t\t\t\t\t\t<td>{{definition.key}}</td>\n\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t<tr class=\"property\">\n\t\t\t\t\t\t\t<td class=\"property-name\" translate=\"CASE-DEFINITION.CATEGORY\"></td>\n\t\t\t\t\t\t\t<td>{{definition.category | empty}}</td>\n\t\t\t\t\t\t\t<td class=\"property-name\" translate=\"CASE-DEFINITION.DESCRIPTION\"></td>\n\t\t\t\t\t\t\t<td>{{definition.description | empty}}</td>\n\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t<tr class=\"property\">\n\t\t\t\t\t\t\t<td class=\"property-name\" translate=\"CASE-DEFINITION.DEPLOYMENT\"></td>\n\t\t\t\t\t\t\t<td><a ng-click=\"openDeployment(definition.deploymentId)\"><i class=\"glyphicon glyphicon-zoom-in\"></i> {{definition.deploymentId}}</a></td>\n\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t<tr class=\"property\">\n\t\t\t\t\t\t\t<td class=\"property-name\" translate=\"CASE-DEFINITION.START-FORM-DEFINED\"></td>\n\t\t\t\t\t\t\t<td>{{definition.startFormDefined &amp;&amp; ('GENERAL.YES' | translate) || ('GENERAL.NO' | translate)}}<span ng-if=\"definition.startFormDefined\"> - <a ng-click=\"openStartForm()\"><i class=\"glyphicon glyphicon-zoom-in\"></i> {{startForm.id}}</a></span></td>\n\t\t\t\t\t\t\t<td class=\"property-name\" translate=\"CASE-DEFINITION.GRAPHICAL-NOTATION-DEFINED\"></td>\n\t\t\t\t\t\t\t<td>\n\t\t\t\t\t\t\t\t{{definition.graphicalNotationDefined &amp;&amp; ('GENERAL.YES' | translate) || ('GENERAL.NO' | translate)}}\n\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t<tr class=\"property\">\n                            <td class=\"property-name\" translate=\"CASE-DEFINITION.TENANT\"></td>\n                            <td>{{definition.tenantId | empty}}</td>\n                        </tr>\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<div class=\"col-md-3\">\n\t\t\t<div class=\"component tip-left\">\n\t\t\t\t<div class=\"title\">\n\t\t\t\t\t<h2 translate=\"GENERAL.TITLE.ACTIONS\"></h2>\n\t\t\t\t</div>\n\t\t\t\t<ul class=\"list-group\">\n\t\t\t\t\t  <li ng-show=\"definition.graphicalNotationDefined\">\n\t\t\t\t\t    <button type=\"button\" class=\"btn btn-sm btn-default\" ng-click=\"showCaseDiagram()\">\n\t\t\t\t\t\t\t<i class=\"glyphicon glyphicon-zoom-in\"></i>{{'CASE-DEFINITION.ACTION.SHOW-DIAGRAM' | translate}}\n\t\t\t\t\t    </button>\n\t\t\t\t\t  </li>\n\t\t\t\t\t  <li>\n\t\t\t\t\t    <button type=\"button\" class=\"btn btn-sm btn-default\" ng-click=\"editCategory()\">\n\t\t\t\t\t\t\t<i class=\"glyphicon glyphicon-pencil\"></i>{{'CASE-DEFINITION.ACTION.EDIT-CATEGORY' | translate}}\n\t\t\t\t\t    </button>\n\t\t\t\t\t  </li>\n\t\t\t\t</ul>\n\t\t\t</div>\n\t\t</div>\n\t</div>\n\t<div class=\"row\">\n\t\t<div class=\"col-md-9\">\n\t\t\t<div class=\"component\">\n\t\t\t\t<div class=\"tabs-wrapper\">\n\t\t\t\t\t<div class=\"pull-right\">\n\t\t\t\t\t\t<a ng-click=\"showAllCases()\" class=\"action\" ng-show=\"tabData.activeTab == tabData.tabs[0].id\"><i class=\"glyphicon glyphicon-zoom-in\"></i> {{'CASE-DEFINITION.ACTION.SHOW-ALL-CASES' | translate}}</a>\n\t\t\t\t\t\t<a ng-click=\"showAllJobs()\" class=\"action\" ng-show=\"tabData.activeTab == tabData.tabs[1].id\"><i class=\"glyphicon glyphicon-zoom-in\"></i> {{'CASE-DEFINITION.ACTION.SHOW-ALL-JOBS' | translate}}</a>\n\t\t\t\t\t</div>\n\t\t       \t\t<div class=\"tabs clearfix\">\n\t\t       \t\t\t<div class=\"tab\" ng-repeat=\"tab in tabData.tabs\" ng-class=\"{'active': tabData.activeTab == tab.id}\">\n\t\t       \t\t\t\t<a ng-click=\"tabData.activeTab = tab.id\">\n\t\t       \t\t\t\t\t{{tab.name | translate:node}}&nbsp;\n\t\t    \t\t\t\t\t<span class=\"badge\" ng-if=\"tab.info != undefined\">{{tab.info}}</span>\n\t\t    \t\t\t\t</a>\n\t\t       \t\t\t</div>\n\t\t       \t\t</div>\n\t\t        \t<div class=\"title\"></div>\n\n\t\t        \t<div class=\"grid-wrapper\" ng-if=\"caseInstances && tabData.activeTab == tabData.tabs[0].id\" >\n\t\t\t\t\t\t<div class=\"grid-message\" ng-if=\"processInstances.size > 0\">\n\t                        <span>{{'CASE-DEFINITION.CASE-INSTANCES-SIZE' | translate:caseInstances}}</span>\n                            <span ng-if=\"caseInstances.size < caseInstances.total\">{{'CASE-DEFINITION.CASE-INSTANCES-SHOWING' | translate:caseInstances}}</span>\n\t                    </div>\n\t                     <div class=\"grid-message\" ng-if=\"caseInstances.size == 0\">\n\t                        <span>{{'CASE-DEFINITION.CASE-INSTANCES-EMPTY' | translate}}</span>\n\t                    </div>\n\t\t\t\t\t\t<div ng-grid=\"gridCaseInstances\" class=\"gridStyle\" ng-if=\"caseInstances\" ng-show=\"caseInstances.size > 0\"></div>\n\t\t\t\t\t</div>\n\n\t\t\t\t\t<div class=\"grid-wrapper grid-wrapper-compact\" ng-if=\"jobs && tabData.activeTab == tabData.tabs[1].id\">\n\t\t\t\t\t\t<div class=\"grid-message\" ng-if=\"jobs.size > 0\">\n\t                        <span>{{'CASE-DEFINITION.JOBS-SIZE' | translate:jobs}}</span>\n\t                    </div>\n\t                     <div class=\"grid-message\" ng-if=\"jobs.size == 0\">\n\t                        <span>{{'CASE-DEFINITION.JOBS-EMPTY' | translate}}</span>\n\t                    </div>\n\t\t\t\t\t\t<div ng-grid=\"gridJobs\" class=\"gridStyle\" ng-if=\"jobs\" ng-show=\"jobs.size > 0\"></div>\n\t\t\t\t\t</div>\n\t\t\t\t\t\n\t\t\t\t\t<div class=\"grid-wrapper grid-wrapper-compact\" ng-if=\"decisionTables && tabData.activeTab == tabData.tabs[2].id\">\n\t\t\t\t\t\t<div class=\"grid-message\" ng-if=\"decisionTables.length > 0\">\n\t                        <span>{{'CASE-DEFINITION.DECISION-TABLES-SIZE' | translate:decisionTables}}</span>\n\t                    </div>\n\t                     <div class=\"grid-message\" ng-if=\"decisionTables.length == 0\">\n\t                        <span>{{'CASE-DEFINITION.DECISION-TABLES-EMPTY' | translate}}</span>\n\t                    </div>\n\t\t\t\t\t\t<div ng-grid=\"gridDecisionTables\" class=\"gridStyle\" ng-if=\"decisionTables\" ng-show=\"decisionTables.length > 0\"></div>\n\t\t\t\t\t</div>\n\t\t\t\t\t\n\t\t\t\t\t<div class=\"grid-wrapper grid-wrapper-compact\" ng-if=\"formDefinitions && tabData.activeTab == tabData.tabs[3].id\">\n\t\t\t\t\t\t<div class=\"grid-message\" ng-if=\"formDefinitions.length > 0\">\n\t                        <span>{{'CASE-DEFINITION.FORM-DEFINITIONS-SIZE' | translate:formDefinitions}}</span>\n\t                    </div>\n\t                     <div class=\"grid-message\" ng-if=\"formDefinitions.length == 0\">\n\t                        <span>{{'CASE-DEFINITION.FORM-DEFINITIONS-EMPTY' | translate}}</span>\n\t                    </div>\n\t\t\t\t\t\t<div ng-grid=\"gridFormDefinitions\" class=\"gridStyle\" ng-if=\"formDefinitions\" ng-show=\"formDefinitions.length > 0\"></div>\n\t\t\t\t\t</div>\n\n\t        \t</div>\n\t\t\t</div>\n\t\t</div>\n\t</div>\n</div>\n<div>\n</div>\n"
  },
  {
    "path": "flowable-ui-web/admin/views/case-definitions.html",
    "content": "<!-- LIST PAGE -->\n<div class=\"container\" id=\"list-container\">\n    <div class=\"row\">\n        <div class=\"col-md-8\">\n            <div class=\"component\">\n                <div class=\"title\">\n                    <div class=\"btn-group btn-group-sm pull-right\">\n                        <div class=\"btn-group btn-group-sm\">\n                            <button type=\"button\" class=\"btn btn-default dropdown-toggle\" data-toggle=\"dropdown\"\n                                    translate=\"GENERAL.ACTION.SHOW-RESULTS\" translate-value-size=\"{{'GENERAL.RESULT-SIZES.' + filter.resultSize | translate}}\">\n                                &nbsp;\n                                <span class=\"caret\"></span>\n                            </button>\n                            <ul class=\"dropdown-menu\">\n                            \t<li ng-repeat=\"resultSize in config.filter.resultSizes\"><a href=\"\" ng-click=\"filter.setResultSize(resultSize)\">{{'GENERAL.RESULT-SIZES.' + resultSize.toString() | translate}}</a></li>\n                            </ul>\n                        </div>\n                        <button type=\"button\" class=\"btn btn-default\" ng-click=\"filter.toggleOrder()\">\n                        \t<i class=\"glyphicon\" ng-class=\"{'glyphicon-sort-by-attributes': filter.order == 'asc', 'glyphicon-sort-by-attributes-alt': filter.order == 'desc'}\"></i>\n                        </button>\n                    </div>\n                    <div class=\"btn-group btn-group-sm pull-right\">\n                    \t<button type=\"button\" class=\"btn btn-default dropdown-toggle\" data-toggle=\"dropdown\"\n                                translate=\"GENERAL.ACTION.SHOW-RESULTS\" translate-value-size=\"{{'GENERAL.RESULT-SIZES.' + filter.resultSize | translate}}\">\n                            &nbsp;\n                            <span class=\"caret\"></span>\n                        </button>\n                    \t<ul class=\"dropdown-menu\">\n                           <li ng-repeat=\"sort in filter.sortObjects\"><a href=\"\" ng-click=\"filter.setSort(sort)\">{{sort.name | translate}}</a></li>\n                        </ul>\n                    </div>\n                    <div class=\"btn-group btn-group-sm pull-right\">\n                        <a class=\"btn btn-default\" role=\"button\"\n                           title=\"{{'GENERAL.ACTION.REFRESH-LIST' | translate}}\"\n                           ng-click=\"filter.refresh();\">\n                            <i class=\"glyphicon glyphicon-refresh\"></i>\n                        </a>\n                    </div>\n                    <div class=\"pull-right loading\" ng-show=\"filter.loading\">\n                    \t<i class=\"glyphicon glyphicon-refresh\"></i>\n                    </div>\n                    <h2>{{'CASE-DEFINITIONS.TITLE.MAIN' | translate:job}}</h2>\n                </div>\n\n                <div class=\"grid-wrapper\" id=\"case-definitions\">\n                    <div class=\"grid-message\" ng-if=\"caseDefinitionsData.size > 0\">\n                         <span>{{'CASE-DEFINITIONS.LIST-MESSAGE' | translate:caseDefinitionsData}}</span>\n                    </div>\n                     <div class=\"grid-message\" ng-if=\"caseDefinitionsData.size == 0\">\n                        <span>{{'CASE-DEFINITIONS.LIST-MESSAGE-EMPTY' | translate}}</span>\n                    </div>\n                    <div ng-grid=\"gridDefinitions\" class=\"gridStyle\" ng-if=\"gridDefinitions && caseDefinitionsData.data\" />\n                </div>\n            </div>\n        </div>\n        <div class=\"col-md-4\">\n\n            <!-- FILTERS -->\n            <div class=\"component tip-left\">\n                <div class=\"title\">\n                    <div class=\"btn-group btn-group-sm pull-right\">\n                        <button type=\"button\" class=\"btn btn-default\" data-toggle=\"dropdown\" ng-show=\"filter.supportedProperties.length > 0\">\n                            <i class=\"glyphicon glyphicon-plus\"></i>\n                        </button>\n                        <ul class=\"dropdown-menu\">\n                            <li ng-repeat=\"prop in filter.supportedProperties\"><a href=\"\" ng-click=\"filter.addProperty(prop)\">{{prop.name | translate}}</a></li>\n                        </ul>\n                    </div>\n                    <div class=\"pull-right\">\n                        <a class=\"action\" ng-click=\"filter.clear()\" translate=\"GENERAL.ACTION.CLEAR-FILTERS\"></a>\n                    </div>\n                    <h2>Filter</h2>\n                </div>\n                <div class=\"section\" ng-if=\"filter.properties.latest !== undefined\">\n\t              <div class=\"subtitle\"><label for=\"filter-latest\" translate=\"CASE-DEFINITIONS.FILTER.LATEST\"></label> </div>\n               \t  <div class=\"input-group input-group-sm\">\n               \t  \t<input type=\"checkbox\" id=\"filter-latest\" ng-model=\"filter.properties.latest\" ng-change=\"toggleLatestVersion()\" />&nbsp;<span class=\"check\" translate=\"CASE-DEFINITIONS.FILTER.LATEST-HELP\"></span>\n\t              </div>\n\t            </div>\n                <div class=\"section\" ng-if=\"filter.properties.nameLike !== undefined\">\n                    <div class=\"subtitle\"><label for=\"filter-nameLike\" translate=\"CASE-DEFINITIONS.FILTER.NAME\"></label> </div>\n                    <div class=\"input-group input-group-sm\">\n                        <input ng-disabled=\"filter.properties.latest == true\" id=\"filter-nameLike\" type=\"text\" class=\"form-control\" value=\"\" ng-model=\"filter.properties.nameLike\" ng-change=\"filter.refreshDelayed()\">\n                    </div>\n                </div>\n                <div class=\"section\" ng-if=\"filter.properties.keyLike !== undefined\">\n                    <div class=\"subtitle\"><label for=\"filter-keyLike\" translate=\"CASE-DEFINITIONS.FILTER.KEY\"></label> </div>\n                    <div class=\"input-group input-group-sm\">\n                        <input id=\"filter-keyLike\" type=\"text\" class=\"form-control\" value=\"\" ng-model=\"filter.properties.keyLike\" ng-change=\"filter.refreshDelayed()\">\n                    </div>\n                </div>\n                <div class=\"section\" ng-if=\"filter.properties.deploymentId !== undefined\">\n                    <div class=\"subtitle\"><label for=\"filter-deploymentId\" translate=\"CASE-DEFINITIONS.FILTER.DEPLOYMENT-ID\"></label> </div>\n                    <div class=\"input-group input-group-sm\">\n                        <input ng-disabled=\"filter.properties.latest == true\" id=\"filter-deploymentId\" type=\"text\" class=\"form-control\" value=\"\" ng-model=\"filter.properties.deploymentId\" ng-change=\"filter.refreshDelayed()\">\n                    </div>\n                </div>\n                <div class=\"section\" ng-if=\"filter.properties.tenantIdLike !== undefined\">\n                    <div class=\"subtitle\"><label for=\"filter-tenantId\" translate=\"CASE-DEFINITIONS.FILTER.TENANT-ID\"></label> </div>\n                    <div class=\"input-group input-group-sm\">\n                        <input id=\"filter-tenantId\" type=\"text\" class=\"form-control\" value=\"\" ng-model=\"filter.properties.tenantIdLike\" ng-change=\"filter.refreshDelayed()\">\n                    </div>\n                </div>\n            </div>\n        </div>\n    </div>\n</div>"
  },
  {
    "path": "flowable-ui-web/admin/views/case-instance-delete-popup.html",
    "content": "<div class=\"modal-header-wrapper\">\n\t<div class=\"modal-header\">\n\t\t<div class=\"pull-right\">\n            <a class=\"action\" ng-click=\"cancel()\">&times; {{'GENERAL.ACTION.CANCEL-AND-CLOSE' | translate}}</a>\n        </div>\n\t\t<h2>{{'CASE-INSTANCE.POPUP.DELETE.TITLE' | translate}} '{{caseInstance.name &amp;&amp; caseInstance.name + \" - \" || \"\"}}{{caseInstance.id}}'</h2>\t\n\t</div>\n</div>\n<div class=\"modal-body\">\n\t<p ng-if=\"action == 'delete'\">{{'CASE-INSTANCE.POPUP.DELETE.MESSAGE-DELETE' | translate}} '{{caseInstance.name &amp;&amp; task.name + \" - \" || \"\"}}{{caseInstance.id}}'?</p>\n\t<p ng-if=\"action == 'terminate'\">{{'CASE-INSTANCE.POPUP.DELETE.MESSAGE-TERMINATE' | translate}} '{{caseInstance.name &amp;&amp; task.name + \" - \" || \"\"}}{{caseInstance.id}}'?</p>\n\t\n\t<div class=\"input-group input-group-sm\" ng-if=\"action == 'terminate'\">\n\t \t <label for=\"user\" translate=\"CASE-INSTANCE.POPUP.DELETE.DELETE-REASON\"></label>\n         <input id=\"user\" type=\"text\" class=\"form-control\" value=\"\" ng-model=\"model.deleteReason\" focus-me placeholder=\"{{'CASE-INSTANCE.POPUP.DELETE.DELETE-REASON-HELP' | translate}}\"/>\n    </div>\n</div>\n\n<div class=\"modal-footer-wrapper\">\n\t<div class=\"modal-footer\">\n\t\t<div class=\"pull-right\">\n\t       <button type=\"button\" class=\"btn btn-sm btn-default\" ng-click=\"cancel()\" ng-disabled=\"status.loading\"\n\t       \ttranslate=\"GENERAL.ACTION.CANCEL\">\n\t       \t</button>\n\t       <button type=\"button\" class=\"btn btn-sm btn-danger\" ng-click=\"ok()\" ng-disabled=\"status.loading\">\n\t       \t\t{{(action == 'delete') &amp;&amp; ('CASE-INSTANCE.POPUP.DELETE.CONFIRM-DELETE' | translate) || ('CASE-INSTANCE.POPUP.DELETE.CONFIRM-TERMINATE' | translate)}}\n\t       </button>\n\t\t</div>\n        <loading-indicator></loading-indicator>\n</div>\n</div>"
  },
  {
    "path": "flowable-ui-web/admin/views/case-instance-diagram-popup.html",
    "content": "<div class=\"modal-header-wrapper\">\n\t<div class=\"modal-header\">\n\t\t<div class=\"pull-right\">\n            <a class=\"action\" ng-click=\"cancel()\">&times; {{'GENERAL.ACTION.CANCEL-AND-CLOSE' | translate}}</a>\n        </div>\n\t\t<h2>{{'CASE-INSTANCE.POPUP.SHOW-CASE-MODEL.TITLE' | translate}} '{{model.name &amp;&amp; model.name || model.id}}'</h2>\t\n\t</div>\n</div>\n<div class=\"modal-body modal-body-medium\">\n    <div id=\"cmmnModel\" style=\"margin-left:auto;margin-right:auto\"></div>\n</div>\n\n<div class=\"modal-footer-wrapper\">\n\t<div class=\"modal-footer\">\n\t\t<div class=\"pull-right\">\n\t       <button type=\"button\" class=\"btn btn-sm btn-default\" ng-click=\"cancel()\" ng-disabled=\"status.loading\"\n\t\t       \ttranslate=\"GENERAL.ACTION.CLOSE\">\n\t       \t</button>\n\t\t</div>\n\t</div>\n</div>\t"
  },
  {
    "path": "flowable-ui-web/admin/views/case-instance.html",
    "content": "<div class=\"container\" id=\"detail-container\" ng-cloak ng-show=\"caseInstance\">\n\t<div class=\"row\" ng-if=\"caseInstance\">\n\t\t<div class=\"col-md-9\">\n\t\t\t<div class=\"component component-pack\" >\n\t\t\t\t<div class=\"title\">\n\t\t\t\t\t<div class=\"pull-right\">\n\t\t\t\t\t\t<a ng-click=\"returnToList()\" class=\"action\">&larr; {{'GENERAL.ACTION.RETURN-TO-LIST' | translate}}</a>\n\t\t\t\t\t</div>\n\t\t\t\t\t<h2>{{caseInstance.name &amp;&amp; caseInstance.name + \"-\" || \"\"}}{{caseInstance.id}}</h2>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"property-wrapper\">\n\t\t\t\t\t<table>\n\t\t\t\t\t\t<tr class=\"property\">\n\t\t\t\t\t\t\t<td class=\"property-name\" translate=\"CASE-INSTANCE.ID\"></td>\n\t\t\t\t\t\t\t<td>{{caseInstance.id}}</td>\n\t\t\t\t\t\t\t<td class=\"property-name\" translate=\"CASE-INSTANCE.BUSINESS-KEY\"></td>\n\t\t\t\t\t\t\t<td>{{caseInstance.businessKey | empty}}</td>\n\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t<tr class=\"property\">\n\t\t\t\t\t\t\t<td class=\"property-name\" translate=\"CASE-INSTANCE.NAME\"></td>\n\t\t\t\t\t\t\t<td>{{caseInstance.name | empty}}</td>\n\t\t\t\t\t\t\t<td class=\"property-name\" translate=\"CASE-INSTANCE.DESCRIPTION\"></td>\n\t\t\t\t\t\t\t<td>{{caseInstance.description | empty}}</td>\n\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t<tr class=\"property\">\n\t\t\t\t\t\t\t<td class=\"property-name\" translate=\"CASE-INSTANCE.STATUS\"></td>\n\t\t\t\t\t\t\t<td>{{caseInstance.endTime &amp;&amp; ('CASE-INSTANCE.STATUS-COMPLETED' | translate) || ('CASE-INSTANCE.STATUS-ACTIVE' | translate)}}</td>\n\t\t\t\t\t\t\t<td class=\"property-name\">Case definition:</td>\n\t\t\t\t\t\t\t<td><a ng-click=\"openCaseDefinition(caseInstance.caseDefinitionId)\"><i class=\"glyphicon glyphicon-zoom-in\"></i>\n\t\t\t\t\t\t\t \t{{definition.name &amp;&amp; definition.name || caseInstance.caseDefinitionId}}\n\t\t\t\t\t\t\t </a></td>\n\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t<tr class=\"property\">\n\t\t\t\t\t\t\t<td class=\"property-name\"><span class=\"glyphicon glyphicon-user\"></span> {{'CASE-INSTANCE.STARTED-BY' | translate}}</td>\n\t\t\t\t\t\t\t<td>{{caseInstance.startUserId | empty}}</td>\n\t\t\t\t\t\t\t<td class=\"property-name\" translate=\"CASE-INSTANCE.TENANT-ID\"></td>\n                            <td>{{caseInstance.tenantId | empty}}</td>\n\t\t\t\t\t\t</tr>\n\t\t\t\t\t</table>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"seperator\" ng-if=\"caseInstance.endTime\"></div>\n\t\t\t\t<div class=\"property-wrapper\" ng-if=\"caseInstance.endTime\">\n\t\t\t\t\t<table>\n\t\t\t\t\t\t<tr class=\"property\" >\n\t\t\t\t\t\t\t<td class=\"property-name\"><span class=\"glyphicon glyphicon-time\"></span> {{'CASE-INSTANCE.END-TIME' | translate}}</td>\n\t\t\t\t\t\t\t<td>{{caseInstance.endTime | dateformat | empty}}</td>\n\t\t\t\t\t\t</tr>\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<div class=\"col-md-3\">\n\t\t\t<div class=\"component tip-left\">\n\t\t\t\t<div class=\"title\">\n\t\t\t\t\t<h2 translate=\"GENERAL.TITLE.ACTIONS\"></h2>\n\t\t\t\t</div>\n\t\t\t\t<ul class=\"list-group\">\n                    <li ng-if=\"definition.graphicalNotationDefined\">\n                        <button type=\"button\" class=\"btn btn-sm btn-default\" ng-click=\"showCaseDiagram()\">\n                            <i class=\"glyphicon glyphicon-zoom-in\"></i>{{'CASE-INSTANCE.ACTION.SHOW-DIAGRAM' | translate}}\n                        </button>\n                    </li>\n                    <li ng-if=\"caseCompleted\">\n\t\t\t\t\t    <button type=\"button\" class=\"btn btn-sm btn-default btn-danger\" ng-click=\"deleteCaseInstance()\">\n\t\t\t\t\t\t\t<i class=\"glyphicon glyphicon-remove\"></i>{{'CASE-INSTANCE.ACTION.DELETE' | translate}}\n\t\t\t\t\t    </button>\n\t\t\t\t\t  </li>\n\t\t\t\t\t  <li ng-if=\"!caseCompleted\">\n\t\t\t\t\t    <button type=\"button\" class=\"btn btn-sm btn-default btn-danger\" ng-click=\"terminateCaseInstance()\">\n\t\t\t\t\t\t\t<i class=\"glyphicon glyphicon-remove\"></i>{{'CASE-INSTANCE.ACTION.TERMINATE' | translate}}\n\t\t\t\t\t    </button>\n\t\t\t\t\t  </li>\n\t\t\t\t</ul>\n\t\t\t</div>\n\t\t</div>\n\t</div>\n\t<div class=\"row\">\n\t\t<div class=\"col-md-9\">\n\t\t\t<div class=\"component\">\n\t\t\t\t<div class=\"tabs-wrapper\">\n\t\t       \t\t<div class=\"tabs clearfix\">\n\t\t       \t\t\t<div class=\"tab\" ng-repeat=\"tab in tabData.tabs\" ng-class=\"{'active': tabData.activeTab == tab.id}\">\n\t\t       \t\t\t\t<a ng-click=\"tabData.activeTab = tab.id\">\n\t\t       \t\t\t\t\t{{tab.name | translate:node}}&nbsp;\n\t\t    \t\t\t\t\t<span class=\"badge\" ng-if=\"tab.info != undefined\">{{tab.info}}</span>\n\t\t    \t\t\t\t</a>\n\t\t       \t\t\t</div>\n\t\t       \t\t</div>\n\t\t        \t<div class=\"title\"></div>\n\n\t\t        \t<div class=\"grid-wrapper grid-wrapper-compact\" ng-if=\"tasks && tabData.activeTab == tabData.tabs[0].id\">\n\t\t\t\t\t\t<div class=\"grid-message\" ng-if=\"tasks.size > 0\">\n\t                        <span>{{'CASE-INSTANCE.TASKS-SIZE' | translate:tasks}}</span> \n\t                        <span>\n\t                        \t<a ng-click=\"showAllTasks()\" class=\"action\"><i class=\"glyphicon glyphicon-zoom-in\"></i> {{'CASE-INSTANCE.ACTION.SHOW-ALL-TASKS' | translate}}</a>\n\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t</div>\n\t                     <div class=\"grid-message\" ng-if=\"tasks.size == 0\">\n\t                        <span>{{'PROCESS-INSTANCE.TASKS-EMPTY' | translate}}</span>\n\t                    </div>\n\t\t\t\t\t\t<div ng-grid=\"gridTasks\" class=\"gridStyle\" ng-if=\"tasks\" ng-show=\"tasks.size > 0\"></div>\n\t\t\t\t\t</div>\n\n\t\t\t\t\t<div class=\"grid-wrapper grid-wrapper-compact\" ng-if=\"variables && tabData.activeTab == tabData.tabs[1].id\">\n\t\t\t\t\t\t<div class=\"grid-message\" ng-if=\"variables.size > 0\">\n\t                        <span>{{'CASE-INSTANCE.VARIABLES-SIZE' | translate:variables}}</span>\n\t                    </div>\n\t                     <div class=\"grid-message\" ng-if=\"variables.size == 0\">\n\t                         <span>{{'CASE-INSTANCE.VARIABLES-EMPTY' | translate}}</span>\n\t                    </div>\n\t\t\t\t\t\t<div ng-grid=\"gridVariables\" class=\"gridStyle\" ng-if=\"variables\" ng-show=\"variables.size > 0\"></div>\n\t\t\t\t\t</div>\n\n\t\t\t\t\t<div class=\"grid-wrapper grid-wrapper-compact\" ng-if=\"jobs && tabData.activeTab == tabData.tabs[2].id\">\n\t\t\t\t\t\t<div class=\"grid-message\" ng-if=\"jobs.size > 0\">\n\t                        <span>{{'CASE-INSTANCE.JOBS-SIZE' | translate:jobs}}</span>\n\t                        <span>\n\t                        \t<a ng-click=\"showAllJobs()\" class=\"action\"><i class=\"glyphicon glyphicon-zoom-in\"></i> {{'CASE-INSTANCE.ACTION.SHOW-ALL-JOBS' | translate}}</a>\n\t                        </span>\n\t                    </div>\n\t                     <div class=\"grid-message\" ng-if=\"jobs.size == 0\">\n\t                        <span>{{'CASE-INSTANCE.JOBS-EMPTY' | translate}}</span>\n\t                    </div>\n\t\t\t\t\t\t<div ng-grid=\"gridJobs\" class=\"gridStyle\" ng-if=\"jobs\" ng-show=\"jobs.size > 0\"></div>\n\t\t\t\t\t</div>\n\t\t\t\t\t\n\t\t\t\t\t<div class=\"grid-wrapper grid-wrapper-compact\" ng-if=\"decisionTables && tabData.activeTab == tabData.tabs[3].id\">\n\t\t\t\t\t\t<div class=\"grid-message\" ng-if=\"decisionTables.size > 0\">\n\t                        <span>{{'CASE-INSTANCE.DECISION-TABLES-SIZE' | translate:decisionTables}}</span>\n\t                    </div>\n\t                     <div class=\"grid-message\" ng-if=\"decisionTables.size == 0\">\n\t                        <span>{{'CASE-INSTANCE.DECISION-TABLES-EMPTY' | translate}}</span>\n\t                    </div>\n\t\t\t\t\t\t<div ng-grid=\"gridDecisionTables\" class=\"gridStyle\" ng-if=\"decisionTables\" ng-show=\"decisionTables.size > 0\"></div>\n\t\t\t\t\t</div>\n\t\t\t\t\t\n\t\t\t\t\t<div class=\"grid-wrapper grid-wrapper-compact\" ng-if=\"formInstances && tabData.activeTab == tabData.tabs[4].id\">\n\t\t\t\t\t\t<div class=\"grid-message\" ng-if=\"formInstances.size > 0\">\n\t                        <span>{{'CASE-INSTANCE.FORM-INSTANCES-SIZE' | translate:formInstances}}</span>\n\t                    </div>\n\t                     <div class=\"grid-message\" ng-if=\"formInstances.size == 0\">\n\t                        <span>{{'CASE-INSTANCE.FORM-INSTANCES-EMPTY' | translate}}</span>\n\t                    </div>\n\t\t\t\t\t\t<div ng-grid=\"gridFormInstances\" class=\"gridStyle\" ng-if=\"formInstances\" ng-show=\"formInstances.size > 0\"></div>\n\t\t\t\t\t</div>\n\n\t\t        </div>\n\t\t     </div>\n\t\t</div>\n\n        <div class=\"col-md-3\" ng-if=\"tabData.activeTab == tabData.tabs[1].id && caseInstance.endTime == null && caseInstance.endTime == undefined\">\n            <div class=\"component tip-left\">\n                <div class=\"title\">\n                    <h2 translate=\"CASE-INSTANCE.ACTION.TITLE-VARIABLES\"></h2>\n                </div>\n                <ul class=\"list-group\">\n                    <li ng-if=\"selectedVariables && selectedVariables.length > 0\">\n                        <button type=\"button\" class=\"btn btn-sm btn-default\" ng-click=\"updateSelectedVariable()\">\n                            <i class=\"glyphicon glyphicon-pencil\"></i>{{'PROCESS-INSTANCE.ACTION.UPDATE-VALUE' | translate}}\n                        </button>\n                    </li>\n                    <li>\n                        <button type=\"button\" class=\"btn btn-sm btn-default\" ng-click=\"addVariable()\">\n                            <i class=\"glyphicon glyphicon-plus\"></i>{{'PROCESS-INSTANCE.ACTION.ADD-VARIABLE' | translate}}\n                        </button>\n                    </li>\n                    <li ng-if=\"selectedVariables && selectedVariables.length > 0\">\n                        <button type=\"button\" class=\"btn btn-sm btn-danger\" ng-click=\"deleteVariable()\">\n                            <i class=\"glyphicon glyphicon-remove\"></i>{{'PROCESS-INSTANCE.ACTION.DELETE-VARIABLE' | translate}}\n                        </button>\n                    </li>\n                </ul>\n            </div>\n        </div>\n\t</div>\n</div>\n"
  },
  {
    "path": "flowable-ui-web/admin/views/case-instances.html",
    "content": "<!-- LIST PAGE -->\n<div class=\"container\" id=\"list-container\">\n    <div class=\"row\">\n        <div class=\"col-md-8\">\n            <div class=\"component\">\n                <div class=\"title\">\n                    <div class=\"btn-group btn-group-sm pull-right\">\n                        <div class=\"btn-group btn-group-sm\">\n                            <button type=\"button\" class=\"btn btn-default dropdown-toggle\" data-toggle=\"dropdown\"\n                                    translate=\"GENERAL.ACTION.SHOW-RESULTS\" translate-value-size=\"{{'GENERAL.RESULT-SIZES.' + filter.resultSize | translate}}\">\n                                &nbsp;\n                                <span class=\"caret\"></span>\n                            </button>\n                            <ul class=\"dropdown-menu\">\n                            \t<li ng-repeat=\"resultSize in config.filter.resultSizes\"><a href=\"\" ng-click=\"filter.setResultSize(resultSize)\">{{'GENERAL.RESULT-SIZES.' + resultSize.toString() | translate}}</a></li>\n                            </ul>\n                        </div>\n                        <button type=\"button\" class=\"btn btn-default\" ng-click=\"filter.toggleOrder()\">\n                        \t<i class=\"glyphicon\" ng-class=\"{'glyphicon-sort-by-attributes': filter.order == 'asc', 'glyphicon-sort-by-attributes-alt': filter.order == 'desc'}\"></i>\n                        </button>\n                    </div>\n                    <div class=\"btn-group btn-group-sm pull-right\">\n                    \t<button type=\"button\" class=\"btn btn-default dropdown-toggle\" data-toggle=\"dropdown\"\n                                translate=\"GENERAL.ACTION.SHOW-RESULTS\" translate-value-size=\"{{'GENERAL.RESULT-SIZES.' + filter.resultSize | translate}}\">\n                            &nbsp;\n                            <span class=\"caret\"></span>\n                        </button>\n                    \t<ul class=\"dropdown-menu\">\n                           <li ng-repeat=\"sort in filter.sortObjects\"><a href=\"\" ng-click=\"filter.setSort(sort)\">{{sort.name | translate}}</a></li>\n                        </ul>\n                    </div>\n                    <div class=\"btn-group btn-group-sm pull-right\">\n                        <a class=\"btn btn-default\" role=\"button\"\n                           title=\"{{'GENERAL.ACTION.REFRESH-LIST' | translate}}\"\n                           ng-click=\"filter.refresh();\">\n                            <i class=\"glyphicon glyphicon-refresh\"></i>\n                        </a>\n                    </div>\n                    <div class=\"pull-right loading\" ng-show=\"filter.loading\">\n                    \t<i class=\"glyphicon glyphicon-refresh\"></i>\n                    </div>\n\n                    <h2 translate=\"CASE-INSTANCES.TITLE\"></h2>\n                </div>\n\n                <div class=\"grid-wrapper\" id=\"case-instances\">\n                    <div class=\"grid-message\" ng-if=\"caseInstances.size > 0\">\n                         <span>{{'CASE-INSTANCES.LIST-MESSAGE' | translate:caseInstances}}</span>\n                    </div>\n                    <div class=\"grid-message\" ng-if=\"caseInstances.size == 0\">\n                         <span>{{'CASE-INSTANCES.LIST-MESSAGE-EMPTY' | translate}}</span>\n                    </div>\n                    <div ng-grid=\"gridInstances\" class=\"gridStyle\" ng-if=\"gridInstances && caseInstances.data\"/>\n                </div>\n            </div>\n        </div>\n        <div class=\"col-md-4\">\n            <div class=\"component tip-left\">\n                <div class=\"title\">\n                    <div class=\"btn-group btn-group-sm pull-right\" ng-show=\"filter.supportedProperties.length > 0\">\n                        <button type=\"button\" class=\"btn btn-default\" data-toggle=\"dropdown\">\n                            <i class=\"glyphicon glyphicon-plus\"></i>\n                        </button>\n                        <ul class=\"dropdown-menu\">\n                            <li ng-repeat=\"prop in filter.supportedProperties\"><a href=\"\" ng-click=\"addFilterProperty(prop)\">{{prop.name | translate}}</a></li>\n                        </ul>\n                    </div>\n                    <div class=\"pull-right\">\n                        <a class=\"action\" ng-click=\"clearFilters()\" translate=\"GENERAL.ACTION.CLEAR-FILTERS\"></a>\n                    </div>\n                    <h2 translate=\"GENERAL.TITLE.FILTERS\"></h2>\n                </div>\n                <div class=\"section\">\n                    <div class=\"subtitle\"><label translate=\"CASE-INSTANCES.FILTER.CASE-DEFINITION\"></label> </div>\n                    <div>\n                        <select ui-select2\n                                data-placeholder=\"{{'CASE-INSTANCES.FILTER.ALL-CASE-DEFINITIONS' | translate}}\"\n                         \t\tng-model=\"filter.caseDefinition\"\n                         \t\tng-change=\"caseDefinitionFilterChanged()\"\n                         \t\tstyle=\"min-width:250px\">\n                            <option value=\"\"></option>\n                         \t<option value=\"-1\">{{'CASE-INSTANCES.FILTER.ALL-CASE-DEFINITIONS' | translate}}</option>\n                         \t<option ng-title=\"123\" ng-repeat=\"caseDefinition in caseDefinitionsCache.data\" value=\"{{caseDefinition.id}}\">{{caseDefinition.name ? caseDefinition.name : caseDefinition.key}} (v{{caseDefinition.version}})</option>\n                         </select>\n                    </div>\n                </div>\n                <div class=\"section\" ng-if=\"filter.properties.finished !== undefined\">\n                    <div class=\"subtitle\"><label for=\"filter-finished\" translate=\"CASE-INSTANCES.FILTER.STATUS\"></label> </div>\n                    <div class=\"input-group input-group-sm\" id=\"filter-state\">\n                       <div class=\"btn-group btn-group-sm\">\n                        <button type=\"button\" id=\"filter-finished\" class=\"btn btn-default dropdown-toggle form-control\" data-toggle=\"dropdown\">\n                            <span class=\"pull-right\">\n                                <span class=\"caret\"></span>\n                            </span>\n                            {{filter.getLabelForOption('finished') | translate}}\n                        </button>\n                        <ul class=\"dropdown-menu\">\n                            <li ng-repeat=\"state in filter.options.finished\"><a href=\"\" ng-click=\"filter.selectOption('finished', state)\">{{state.name | translate}}</a></li>\n                        </ul>\n                    </div>\n                    </div>\n                </div>\n                <div class=\"section\" ng-if=\"filter.properties.caseBusinessKey!== undefined\">\n                    <div class=\"subtitle\"><label for=\"filter-caseBusinessKey\" translate=\"CASE-INSTANCES.FILTER.BUSINESS-KEY\"></label> </div>\n                    <div class=\"input-group input-group-sm\">\n                        <input id=\"filter-caseBusinessKey\" type=\"text\" class=\"form-control\" value=\"\" ng-model=\"filter.properties.caseBusinessKey\" ng-change=\"filter.refreshDelayed()\">\n                    </div>\n                </div>\n                <div class=\"section\" ng-if=\"filter.properties.startedBefore !== undefined\">\n                  <div class=\"subtitle\"><label for=\"filter-startedBefore\" translate=\"CASE-INSTANCES.FILTER.STARTED-BEFORE\"></label> </div>\n               \t  <div class=\"input-group input-group-sm\">\n               \t  \t<span class=\"input-group-addon\"><span class=\"glyphicon glyphicon-time\"></span></span>\n\t              \t<input id=\"filter-startedBefore\" type=\"text\" class=\"form-control\" ng-model=\"filter.properties.startedBefore\"\n                           ng-change=\"filter.refreshDelayed()\"\n                           datepicker-popup=\"dd/MM/yyyy\"\n                           is-open=\"startedBeforePicker.isOpen\" ng-click=\"startedBeforePicker.isOpen=true\"/>\n\t              </div>\n\t            </div>\n                <div class=\"section\" ng-if=\"filter.properties.startedAfter !== undefined\">\n\t              <div class=\"subtitle\"><label for=\"filter-startedAfter\" translate=\"CASE-INSTANCES.FILTER.STARTED-AFTER\"></label> </div>\n               \t  <div class=\"input-group input-group-sm\">\n               \t  \t<span class=\"input-group-addon\"><span class=\"glyphicon glyphicon-time\"></span></span>\n\t              \t<input id=\"filter-startedAfter\" type=\"text\" class=\"form-control\" ng-model=\"filter.properties.startedAfter\"\n                           ng-change=\"filter.refreshDelayed()\"\n                           datepicker-popup=\"dd/MM/yyyy\"\n                           is-open=\"startedAfterPicker.isOpen\" ng-click=\"startedAfterPicker.isOpen=true\"/>\n\t              </div>\n\t            </div>\n\t            <div class=\"section\" ng-if=\"filter.properties.finishedBefore !== undefined\">\n                  <div class=\"subtitle\"><label for=\"filter-finishedBefore\" translate=\"CASE-INSTANCES.FILTER.ENDED-BEFORE\"></label> </div>\n               \t  <div class=\"input-group input-group-sm\">\n               \t  \t<span class=\"input-group-addon\"><span class=\"glyphicon glyphicon-time\"></span></span>\n\t              \t<input id=\"filter-finishedBefore\" type=\"text\" class=\"form-control\" ng-model=\"filter.properties.finishedBefore\"\n                           ng-change=\"filter.refreshDelayed()\"\n                           datepicker-popup=\"dd/MM/yyyy\"\n                           is-open=\"finishedBeforePicker.isOpen\" ng-click=\"finishedBeforePicker.isOpen=true\"/>\n\t              </div>\n\t            </div>\n                <div class=\"section\" ng-if=\"filter.properties.finishedAfter !== undefined\">\n\t              <div class=\"subtitle\"><label for=\"filter-finishedAfter\" translate=\"CASE-INSTANCES.FILTER.ENDED-AFTER\"></label> </div>\n               \t  <div class=\"input-group input-group-sm\">\n               \t  \t<span class=\"input-group-addon\"><span class=\"glyphicon glyphicon-time\"></span></span>\n\t              \t<input id=\"filter-finishedAfter\" type=\"text\" class=\"form-control\" ng-model=\"filter.properties.finishedAfter\"\n                           ng-change=\"filter.refreshDelayed()\"\n                           datepicker-popup=\"dd/MM/yyyy\"\n                           is-open=\"finishedAfterPicker.isOpen\" ng-click=\"finishedAfterPicker.isOpen=true\"/>\n\t              </div>\n\t            </div>\n\n\t            <div class=\"section clearfix\" ng-repeat=\"varFilter in filter.properties.variables\">\n\t              <div class=\"seperator\" ng-if=\"$index > 0\"></div>\n\t              <div class=\"subtitle\"><label translate=\"CASE-INSTANCES.FILTER.VARIABLE\"></label> </div>\n               \t  <div class=\"inline-button input-group-sm\">\n\t              \t\t<div class=\"pull-right btn-group\">\n\t                        <button ng-disabled=\"varFilter.type.id == 'boolean'\" tabindex=\"-1\" type=\"button\" class=\"btn btn-sm btn-default dropdown-toggle\" data-toggle=\"dropdown\">\n\t                             {{varFilter.operator.sign}} <i class=\"caret\"></i>\n\t                        </button>\n\t                        <ul class=\"dropdown-menu\">\n\t                            <li><a href=\"\" ng-click=\"setVariableFilterOperator(varFilter, operator)\" ng-repeat=\"operator in variableFilterOperators\">{{operator.name}}</a></li>\n\t                        </ul>\n\t                    </div>\n\t              \t\t<input id=\"filter-variable-name-{{$index}}\" type=\"text\" class=\"form-control\" ng-model=\"varFilter.name\" ng-change=\"filter.refreshDelayed()\" placeholder=\"{{'CASE-INSTANCES.FILTER.VARIABLE-NAME' | translate}}\" />\n\t              </div>\n               \t  <div class=\"inline-button wide input-group-sm\" >\n\t              \t\t<div class=\"pull-right btn-group\">\n\t                        <button tabindex=\"-1\" ng-disabled=\"varFilter.operator.id == 'like'\" type=\"button\" class=\"btn btn-sm btn-default dropdown-toggle\" data-toggle=\"dropdown\">\n\t                           {{varFilter.type.name}} <i class=\"caret\"></i>\n\t                        </button>\n\t                        <ul class=\"dropdown-menu\">\n\t                            <li><a href=\"\" ng-click=\"setVariableFilterType(varFilter, type)\" ng-repeat=\"type in variableFilterTypes\" >{{type.name}}</a></li>\n\t                        </ul>\n\t                    </div>\n\t              \t\t<input ng-if=\"varFilter.type.id != 'date' && varFilter.type.id != 'boolean'\" id=\"filter-variable-value-{{$index}}\" type=\"text\" class=\"form-control\" ng-model=\"varFilter.value\" ng-change=\"filter.refreshDelayed()\" placeholder=\"{{'CASE-INSTANCES.FILTER.VARIABLE-VALUE' | translate}}\" />\n\t              \t\t<input ng-if=\"varFilter.type.id == 'date'\" id=\"filter-variable-value-{{$index}}\" type=\"text\" class=\"form-control\" ng-model=\"varFilter.value\"\n                               ng-change=\"filter.refresh()\"\n                               datepicker-popup=\"dd/MM/yyyy\"\n                               is-open=\"varValuePicker.isOpen\" ng-click=\"varValuePicker.isOpen=true\"/>\n\t              \t\t<div class=\"checkbox\" ng-if=\"varFilter.type.id == 'boolean'\">\n\t\t\t\t\t\t    <label>\n\t\t\t\t\t\t      <input type=\"checkbox\" ng-change=\"filter.refresh()\" ng-model=\"varFilter.value\">{{'CASE-INSTANCES.FILTER.VARIABLE-BOOLEAN-VALUE' | translate:varFilter}}\n\t\t\t\t\t\t    </label>\n  \t\t\t\t\t\t</div>\n\t              </div>\n\t            </div>\n\t            <div class=\"section\" ng-if=\"filter.properties.tenantIdLike !== undefined\">\n                    <div class=\"subtitle\"><label for=\"filter-tenantId\" translate=\"CASE-INSTANCES.FILTER.TENANT-ID\"></label> </div>\n                    <div class=\"input-group input-group-sm\">\n                        <input id=\"filter-tenantId\" type=\"text\" class=\"form-control\" value=\"\" ng-model=\"filter.properties.tenantIdLike\" ng-change=\"filter.refreshDelayed()\">\n                    </div>\n                </div>\n            </div>\n        </div>\n    </div>\n</div>\n"
  },
  {
    "path": "flowable-ui-web/admin/views/cmmn-deployment.html",
    "content": "<div class=\"container\" id=\"detail-container\">\n\t<div class=\"row\">\n\t\t<div class=\"col-md-9\">\n\t\t\t<div class=\"component\" ng-show=\"cmmnDeployment\">\n\t\t\t\t<div class=\"title\">\n\t\t\t\t\t<div class=\"pull-right\">\n\t\t\t\t\t\t<a ng-click=\"returnToList()\" class=\"action\">&larr; {{'GENERAL.ACTION.RETURN-TO-LIST' | translate}}</a>\n\t\t\t\t\t</div>\n\t\t\t\t\t<h2>{{cmmnDeployment.name || cmmnDeployment.id}}</h2>\n\t\t\t\t</div>\n\n\t\t\t\t<div class=\"property-wrapper\">\n\t\t\t\t\t<table>\n\t\t\t\t\t\t<tr class=\"property\">\n\t\t\t\t\t\t\t<td class=\"property-name\" translate=\"CMMN-DEPLOYMENT.ID\"></td>\n\t\t\t\t\t\t\t<td>{{cmmnDeployment.id}}</td>\n\t\t\t\t\t\t\t<td class=\"property-name\" translate=\"CMMN-DEPLOYMENT.NAME\"></td>\n\t\t\t\t\t\t\t<td>{{cmmnDeployment.name | empty}}</td>\n\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t<tr class=\"property\">\n\t\t\t\t\t\t\t<td class=\"property-name\" translate=\"CMMN-DEPLOYMENT.TIME\"></td>\n\t\t\t\t\t\t\t<td>{{cmmnDeployment.deploymentTime | dateformat}}</td>\n\t\t\t\t\t\t\t<td class=\"property-name\" translate=\"CMMN-DEPLOYMENT.CATEGORY\"></td>\n\t\t\t\t\t\t\t<td>{{cmmnDeployment.category | empty}}</td>\n\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t<tr class=\"property\">\n                            <td class=\"property-name\" translate=\"CMMN-DEPLOYMENT.TENANTID\"></td>\n                            <td>{{cmmnDeployment.tenantId | empty}}</td>\n                            <td ng-if=\"cmmnDeployment.parentDeploymentId\" class=\"property-name\" translate=\"CMMN-DEPLOYMENT.PARENT-DEPLOYMENT-ID\"></td>\n                            <td ng-if=\"cmmnDeployment.parentDeploymentId\"><a ng-href=\"#/app-deployment/{{cmmnDeployment.parentDeploymentId}}\"><i class=\"glyphicon glyphicon-zoom-in\"></i> {{cmmnDeployment.parentDeploymentId}}</a></td>\n                        </tr>\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 class=\"col-md-3\">\n\t\t\t<div class=\"component tip-left\">\n\t\t\t\t<div class=\"title\">\n\t\t\t\t\t<h2 translate=\"GENERAL.TITLE.ACTIONS\"></h2>\n\t\t\t\t</div>\n\t\t\t\t<ul class=\"list-group\">\n\t\t\t\t\t  <li>\n\t\t\t\t\t    <button type=\"button\" class=\"btn btn-sm btn-default btn-danger\" ng-click=\"deleteDeployment()\">\n\t\t\t\t\t\t\t<i class=\"glyphicon glyphicon-remove\"></i><span translate=\"CMMN-DEPLOYMENTS.ACTION.DELETE\"></span>\n\t\t\t\t\t    </button>\n\t\t\t\t\t  </li>\n\t\t\t\t</ul>\n\t\t\t</div>\n\t\t</div>\n\t</div>\n\t<div class=\"row\">\n\t\t<div class=\"col-md-9\">\n\t\t\t<div class=\"component\">\n\t\t\t\t<div class=\"title\">\n\t\t\t\t\t<div class=\"pull-right\">\n\t\t\t\t\t\t<a ng-click=\"showAllCaseDefinitions()\" class=\"action\"><i class=\"glyphicon glyphicon-zoom-in\"></i> {{'DEPLOYMENT.ACTION.SHOW-ALL-DEFINITIONS' | translate}}</a>\n\t\t\t\t\t</div>\n\t\t\t\t\t<h2 translate=\"CMMN-DEPLOYMENT.TITLE.CASE-DEFINITIONS\"></h2>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"grid-wrapper grid-wrapper-compact\" ng-if=\"caseDefinitions\">\n\t\t\t\t\t<div class=\"grid-message\" ng-if=\"caseDefinitions.size > 0\">\n\t                       <span>{{'CMMN-DEPLOYMENT.DEFINITIONS-MESSAGE' | translate:caseDefinitions}}</span>\n\t                   </div>\n\t                    <div class=\"grid-message\" ng-if=\"caseDefinitions.size == 0\">\n\t                       <span>{{'CMMN-DEPLOYMENT.DEFINITIONS-MESSAGE-EMPTY' | translate}}</span>\n\t                   </div>\n\t\t\t\t\t<div ng-grid=\"gridCaseDefinitions\" class=\"gridStyle\" ng-if=\"gridCaseDefinitions && caseDefinitions.data\" ng-show=\"caseDefinitions.size > 0\"></div>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</div>\n\t</div>\n</div>\n"
  },
  {
    "path": "flowable-ui-web/admin/views/cmmn-deployments.html",
    "content": "<!-- LIST PAGE -->\n<div class=\"container\" id=\"list-container\">\n    <div class=\"row\">\n        <div class=\"col-md-8\">\n            <div class=\"component\">\n                <div class=\"title\">\n                    <div class=\"btn-group btn-group-sm pull-right\">\n                        <div class=\"btn-group btn-group-sm\">\n                            <button type=\"button\" class=\"btn btn-default dropdown-toggle\" data-toggle=\"dropdown\"\n                                    translate=\"GENERAL.ACTION.SHOW-RESULTS\"\n                                    translate-value-size=\"{{'GENERAL.RESULT-SIZES.' + filter.resultSize | translate}}\">\n                                &nbsp;\n                                <span class=\"caret\"></span>\n                            </button>\n                            <ul class=\"dropdown-menu\">\n                                <li ng-repeat=\"resultSize in config.filter.resultSizes\"><a href=\"\"\n                                                                                           ng-click=\"filter.setResultSize(resultSize)\">{{'GENERAL.RESULT-SIZES.'\n                                    + resultSize.toString() | translate}}</a></li>\n                            </ul>\n                        </div>\n                        <button type=\"button\" class=\"btn btn-default\" ng-click=\"filter.toggleOrder()\">\n                            <i class=\"glyphicon\"\n                               ng-class=\"{'glyphicon-sort-by-attributes': filter.order == 'asc', 'glyphicon-sort-by-attributes-alt': filter.order == 'desc'}\"></i>\n                        </button>\n                    </div>\n                    <div class=\"btn-group btn-group-sm pull-right\">\n                        <button type=\"button\" class=\"btn btn-default dropdown-toggle\" data-toggle=\"dropdown\"\n                                translate=\"GENERAL.ACTION.SHOW-RESULTS\"\n                                translate-value-size=\"{{'GENERAL.RESULT-SIZES.' + filter.resultSize | translate}}\">\n                            &nbsp;\n                            <span class=\"caret\"></span>\n                        </button>\n                        <ul class=\"dropdown-menu\">\n                            <li ng-repeat=\"sort in filter.sortObjects\"><a href=\"\" ng-click=\"filter.setSort(sort)\">{{sort.name\n                                | translate}}</a></li>\n                        </ul>\n                    </div>\n                    <div class=\"btn-group btn-group-sm pull-right\">\n                        <a class=\"btn btn-default\" role=\"button\"\n                           title=\"{{'GENERAL.ACTION.REFRESH-LIST' | translate}}\"\n                           ng-click=\"filter.refresh();\">\n                            <i class=\"glyphicon glyphicon-refresh\"></i>\n                        </a>\n                    </div>\n                    <div class=\"pull-right loading\" ng-show=\"filter.loading\">\n                        <i class=\"glyphicon glyphicon-refresh\"></i>\n                    </div>\n                    <h2 translate=\"CMMN-DEPLOYMENTS.TITLE\"></h2>\n                </div>\n\n                <div class=\"grid-wrapper\" id=\"deployments\">\n                    <div class=\"grid-message\" ng-if=\"cmmnDeploymentsData.size > 0\">\n                        <span>{{'CMMN-DEPLOYMENTS.LIST-MESSAGE' | translate:cmmnDeploymentsData}}</span>\n                    </div>\n                    <div class=\"grid-message\" ng-if=\"deploymentsData.size == 0\">\n                        <span>{{'CMMN-DEPLOYMENTS.LIST-MESSAGE-EMPTY' | translate}}</span>\n                    </div>\n                    <div ng-grid=\"gridCmmnDeployments\" class=\"gridStyle\"\n                         ng-if=\"gridCmmnDeployments && cmmnDeploymentsData.data\"/>\n                </div>\n            </div>\n        </div>\n        <div class=\"col-md-4\">\n\n            <!-- Deployment filters -->\n            <div class=\"component tip-left\">\n                <div class=\"title\">\n                    <div class=\"pull-right\">\n                        <a class=\"action\" ng-click=\"filter.clear()\" translate=\"GENERAL.ACTION.CLEAR-FILTERS\"></a>\n                    </div>\n                    <h2 translate=\"GENERAL.TITLE.FILTERS\"></h2>\n                </div>\n                <div class=\"section\" ng-if=\"filter.properties.nameLike !== undefined\">\n                    <div class=\"subtitle\"><label for=\"filter-nameLike\" translate=\"CMMN-DEPLOYMENTS.FILTER.NAME\"></label>\n                    </div>\n                    <div class=\"input-group input-group-sm\">\n                        <input id=\"filter-nameLike\" type=\"text\" class=\"form-control\" value=\"\"\n                               ng-model=\"filter.properties.nameLike\" ng-change=\"filter.refreshDelayed()\">\n                    </div>\n                </div>\n                <div class=\"section\" ng-if=\"filter.properties.tenantIdLike !== undefined\">\n                    <div class=\"subtitle\"><label for=\"filter-tenantIdLike\"\n                                                 translate=\"CMMN-DEPLOYMENTS.FILTER.TENANTID\"></label></div>\n                    <div class=\"input-group input-group-sm\">\n                        <input id=\"filter-tenantIdLike\" type=\"text\" class=\"form-control\" value=\"\"\n                               ng-model=\"filter.properties.tenantIdLike\" ng-change=\"filter.refreshDelayed()\">\n                    </div>\n                </div>\n            </div>\n\n            <!-- Actions -->\n            <div class=\"component no-min-height\">\n                <div class=\"title\">\n                    <h2 translate=\"GENERAL.TITLE.ACTIONS\"></h2>\n                </div>\n                <ul class=\"list-group\">\n                    <li>\n                        <button type=\"button\" class=\"btn btn-sm btn-default\" ng-click=\"uploadDeployment()\">\n                            <i class=\"glyphicon glyphicon-open\"></i>{{'CMMN-DEPLOYMENTS.ACTION.UPLOAD' | translate}}\n                        </button>\n                    </li>\n                </ul>\n            </div>\n        </div>\n    </div>\n</div>"
  },
  {
    "path": "flowable-ui-web/admin/views/cmmn-job.html",
    "content": "\n<div class=\"container\" id=\"detail-container\">\n\t<div class=\"row\">\n\t\t<div class=\"col-md-9\">\n\t\t\t<div class=\"component\" ng-show=\"job\">\n\t\t\t\t<div class=\"title\">\n\t\t\t\t\t<div class=\"pull-right\">\n\t\t\t\t\t\t<a ng-click=\"returnToList()\" class=\"action\">&larr; {{'GENERAL.ACTION.RETURN-TO-LIST' | translate}}</a>\n\t\t\t\t\t</div>\n\t\t\t\t\t<h2>{{'JOB.TITLE.MAIN' | translate:job}}</h2>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"property-wrapper\">\n\t\t\t\t\t<table>\n\t\t\t\t\t\t<tr class=\"property\">\n\t\t\t\t\t\t\t<td class=\"property-name\" translate=\"JOB.ID\"></td>\n\t\t\t\t\t\t\t<td>{{job.id}}</td>\n\t\t\t\t\t\t\t<td class=\"property-name\"><span class=\"glyphicon glyphicon-time\"></span> {{'JOB.DUEDATE' | translate}}</td>\n\t\t\t\t\t\t\t<td>{{job.dueDate | dateformat}}</td>\n\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t<tr class=\"property\">\n\t\t\t\t\t\t\t<td class=\"property-name\" ng-if=\"job.caseInstanceId\"></span> {{'JOB.CASE-INSTANCE' | translate}}</td>\n\t\t\t\t\t\t\t<td ng-if=\"job.caseInstanceId\"><a ng-click=\"openCaseInstance(job.caseInstanceId)\"><i class=\"glyphicon glyphicon-zoom-in\"></i> {{job.caseInstanceId | empty}}</a></td>\n\t\t\t\t\t\t\t<td class=\"property-name\" translate=\"JOB.EXECUTION-ID\"></td>\n\t\t\t\t\t\t\t<td>{{job.executionId}}</td>\n\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t<tr class=\"property\">\n\t\t\t\t\t\t\t<td class=\"property-name\" translate=\"JOB.RETRIES-LEFT\"></td>\n\t\t\t\t\t\t\t<td>{{job.retries}}</td>\n\t\t\t\t\t\t\t<td class=\"property-name\" ng-if=\"job.caseDefinitionId\"></span> {{'JOB.CASE-DEFINITION' | translate}}</td>\n\t\t\t\t\t\t\t<td ng-if=\"job.caseDefinitionId\"><a ng-click=\"openCaseDefinition(job.caseDefinitionId)\"><i class=\"glyphicon glyphicon-zoom-in\"></i> {{job.caseDefinitionId | empty}}</a></td>\n\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t<tr class=\"property\">\n                            <td class=\"property-name\" translate=\"JOB.TENANT-ID\"></td>\n                            <td>{{job.tenantId}}</td>\n                        </tr>\n\t\t\t\t\t</table>\n\t\t\t\t</div>\n\t\t\t\t\n\t\t\t\t\n\t\t\t\t<div ng-if=\"job.exceptionMessage\">\n\t\t\t\t\t<div class=\"title\">\n\t\t\t\t\t\t<h3 translate=\"JOB.TITLE.EXCEPTION\"></h3>\n\t\t\t\t\t</div>\n\t\t\t\t\t<div class=\"property-wrapper\">\n\t\t\t\t\t\t<table>\n\t\t\t\t\t\t\t<tr class=\"property\">\n\t\t\t\t\t\t\t\t<td class=\"property-name\">Exception during last execution:</td>\n\t\t\t\t\t\t\t\t<td>{{job.exceptionMessage}}</td>\n\t\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t</table>\n\t\t\t\t\t</div>\t\n\t\t\t\t\t<pre>{{job.exceptionStack}}</pre>\t\t\t\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</div>\n\t\t<div class=\"col-md-3\">\n\t\t\t<div class=\"component tip-left\">\n\t\t\t\t<div class=\"title\">\n\t\t\t\t\t<h2 translate=\"GENERAL.TITLE.ACTIONS\"></h2>\n\t\t\t\t</div>\n\t\t\t\t<ul class=\"list-group\" ng-if=\"jobType.param == 'executableJob'\">\n\t\t\t\t\t  <li>\n\t\t\t\t\t    <button type=\"button\" class=\"btn btn-sm btn-default\" ng-click=\"executeJob()\">\n\t\t\t\t\t\t\t<i class=\"glyphicon glyphicon-play\"></i> {{'JOB.ACTIONS.EXECUTE' | translate}}\n\t\t\t\t\t    </button>\n\t\t\t\t\t  </li>\n\t\t\t\t</ul>\n\t\t\t\t<ul class=\"list-group\" ng-if=\"jobType.param == 'timerJob' || jobType.param == 'deadletterJob'\">\n\t\t\t\t\t  <li>\n\t\t\t\t\t    <button type=\"button\" class=\"btn btn-sm btn-default\" ng-click=\"moveJob()\">\n\t\t\t\t\t\t\t<i class=\"glyphicon glyphicon-play\"></i> {{'JOB.ACTIONS.MOVE' | translate}}\n\t\t\t\t\t    </button>\n\t\t\t\t\t  </li>\n\t\t\t\t</ul>\n\t\t\t\t<div class=\"seperator\"></div>\n\t\t\t\t<ul class=\"list-group\">\n\t\t\t\t\t  \n\t\t\t\t\t  <li>\n\t\t\t\t\t    <button type=\"button\" class=\"btn btn-sm btn-default btn-danger\" ng-click=\"deleteJob()\">\n\t\t\t\t\t\t\t<i class=\"glyphicon glyphicon-remove\"></i> {{'JOB.ACTIONS.DELETE' | translate}}\n\t\t\t\t\t    </button>\n\t\t\t\t\t  </li>\n\t\t\t\t</ul>\n\t\t\t</div>\n\t\t</div>\n\t</div>\n</div>\n"
  },
  {
    "path": "flowable-ui-web/admin/views/cmmn-jobs.html",
    "content": "<!-- LIST PAGE -->\n<div class=\"container\">\n    <div class=\"row\">\n        <div class=\"col-md-8\">\n            <div class=\"component\">\n                <div class=\"title\">\n                    <div class=\"btn-group btn-group-sm pull-right\">\n                        <div class=\"btn-group btn-group-sm\">\n                            <button type=\"button\" class=\"btn btn-default dropdown-toggle\" data-toggle=\"dropdown\"\n                                    translate=\"GENERAL.ACTION.SHOW-RESULTS\" translate-value-size=\"{{'GENERAL.RESULT-SIZES.' + filter.resultSize | translate}}\">\n                                &nbsp;\n                                <span class=\"caret\"></span>\n                            </button>\n                            <ul class=\"dropdown-menu\">\n                            \t<li ng-repeat=\"resultSize in config.filter.resultSizes\"><a href=\"\" ng-click=\"filter.setResultSize(resultSize)\">{{'GENERAL.RESULT-SIZES.' + resultSize.toString() | translate}}</a></li>\n                            </ul>\n                        </div>\n                        <button type=\"button\" class=\"btn btn-default\" ng-click=\"filter.toggleOrder()\">\n                        \t<i class=\"glyphicon\" ng-class=\"{'glyphicon-sort-by-attributes': filter.order == 'asc', 'glyphicon-sort-by-attributes-alt': filter.order == 'desc'}\"></i>\n                        </button>\n                    </div>\n                    <div class=\"btn-group btn-group-sm pull-right\">\n                    \t<button type=\"button\" class=\"btn btn-default dropdown-toggle\" data-toggle=\"dropdown\"\n                                translate=\"GENERAL.ACTION.SHOW-RESULTS\" translate-value-size=\"{{'GENERAL.RESULT-SIZES.' + filter.resultSize | translate}}\">\n                            &nbsp;\n                            <span class=\"caret\"></span>\n                        </button>\n                    \t<ul class=\"dropdown-menu\">\n                           <li ng-repeat=\"sort in filter.sortObjects\"><a href=\"\" ng-click=\"filter.setSort(sort)\">{{sort.name | translate}}</a></li>\n                        </ul>\n                    </div>\n                    <div class=\"btn-group btn-group-sm pull-right\">\n                        <a class=\"btn btn-default\" role=\"button\"\n                           title=\"{{'GENERAL.ACTION.REFRESH-LIST' | translate}}\"\n                           ng-click=\"filter.refresh();\">\n                            <i class=\"glyphicon glyphicon-refresh\"></i>\n                        </a>\n                    </div>\n                    <div class=\"pull-right loading\" ng-show=\"filter.loading\">\n                    \t<i class=\"glyphicon glyphicon-refresh\"></i>\n                    </div>\n\n                    <h2 translate=\"JOBS.TITLE\"></h2>\n                </div>\n\n                <div class=\"grid-wrapper\" id=\"jobs\">\n                    <div class=\"grid-message\" ng-if=\"jobData.size > 0\">\n                         <span>{{'JOBS.LIST-MESSAGE' | translate:jobs}}</span>\n                    </div>\n                     <div class=\"grid-message\" ng-if=\"jobData.size == 0\">\n                        <span>{{'JOBS.LIST-MESSAGE-EMPTY' | translate}}</span>\n                    </div>\n                    <div ng-grid=\"gridJobs\" class=\"gridStyle\" ng-if=\"gridJobs && jobData.data\"/>\n                </div>\n            </div>\n        </div>\n\n\t\t<!-- Task filters -->\n\t\t<div class=\"col-md-4\">\n            <div class=\"component tip-left\">\n                <div class=\"title\">\n                    <div class=\"btn-group btn-group-sm pull-right\" ng-show=\"filter.supportedProperties.length > 0\">\n                        <button type=\"button\" class=\"btn btn-default\" data-toggle=\"dropdown\">\n                            <i class=\"glyphicon glyphicon-plus\"></i>\n                        </button>\n                        <ul class=\"dropdown-menu\">\n                            <li ng-repeat=\"prop in filter.supportedProperties\"><a href=\"\" ng-click=\"filter.addProperty(prop)\">{{prop.name | translate}}</a></li>\n                        </ul>\n                    </div>\n                    <div class=\"pull-right\">\n                        <a class=\"action\" ng-click=\"filter.clear()\" translate=\"GENERAL.ACTION.CLEAR-FILTERS\"></a>\n                    </div>\n                    <h2 translate=\"GENERAL.TITLE.FILTERS\"></h2>\n                </div>\n                <div class=\"section\">\n                    <div class=\"subtitle\"><label for=\"filter-jobtype\" translate=\"JOBS.FILTER.JOBTYPE.LABEL\"></label> </div>\n                    <div>\n                        <select ui-select2\n                                ng-model=\"filter.jobType\"\n                         \t\tng-change=\"jobTypeFilterChanged()\"\n                         \t\tstyle=\"min-width:250px\">\n                            <option value=\"executableJob\">{{'JOBS.FILTER.JOBTYPE.EXECUTABLE-JOB' | translate}}</option>\n                            <option value=\"timerJob\">{{'JOBS.FILTER.JOBTYPE.TIMER-JOB' | translate}}</option>\n                            <option value=\"suspendedJob\">{{'JOBS.FILTER.JOBTYPE.SUSPENDED-JOB' | translate}}</option>\n                            <option value=\"deadletterJob\">{{'JOBS.FILTER.JOBTYPE.DEADLETTER-JOB' | translate}}</option>\n                         </select>\n                    </div>\n                </div>\n\t            <div class=\"section\">\n                    <div class=\"subtitle\"><label for=\"filter-casedefinition\" translate=\"JOBS.FILTER.CASE-DEFINITION\"></label> </div>\n                    <div>\n                        <select ui-select2\n                                data-placeholder=\"{{'JOBS.FILTER.ALL-CASE-DEFINITIONS' | translate}}\"\n                         \t\tng-model=\"filter.caseDefinition\"\n                         \t\tng-change=\"caseDefinitionFilterChanged()\"\n                         \t\tstyle=\"min-width:250px\">\n                            <option value=\"\"></option>\n                            <option value=\"-1\">{{'JOBS.FILTER.ALL-CASE-DEFINITIONS' | translate}}</option>\n                         \t<option ng-title=\"123\" ng-repeat=\"caseDefinition in caseDefinitionsCache.data\" value=\"{{caseDefinition.id}}\">{{caseDefinition.name ? caseDefinition.name : caseDefinition.key}} (v{{processDefinition.version}})</option>\n                         </select>\n                    </div>\n                </div>\n                <div class=\"section\" ng-if=\"filter.properties.caseInstanceId !== undefined\">\n                    <div class=\"subtitle\"><label for=\"filter-caseInstanceId\" translate=\"JOBS.FILTER.CASE-INSTANCE-ID\"></label> </div>\n                    <div class=\"input-group input-group-sm\">\n                        <input id=\"filter-caseInstanceId\" type=\"text\" class=\"form-control\" value=\"\" ng-model=\"filter.properties.caseInstanceId\" ng-change=\"filter.refreshDelayed()\">\n                    </div>\n                </div>\n                <div class=\"section\" ng-if=\"filter.properties.tenantIdLike !== undefined\">\n                    <div class=\"subtitle\"><label for=\"filter-tenantId\" translate=\"JOBS.FILTER.TENANT-ID\"></label> </div>\n                    <div class=\"input-group input-group-sm\">\n                        <input id=\"filter-tenantId\" type=\"text\" class=\"form-control\" value=\"\" ng-model=\"filter.properties.tenantIdLike\" ng-change=\"filter.refreshDelayed()\">\n                    </div>\n                </div>\n                <div class=\"section\" ng-if=\"filter.properties.dueBefore !== undefined\">\n                  <div class=\"subtitle\"><label for=\"filter-dueBefore\" translate=\"JOBS.FILTER.DUE-BEFORE\"></label> </div>\n               \t  <div class=\"input-group input-group-sm\">\n               \t  \t<span class=\"input-group-addon\"><span class=\"glyphicon glyphicon-time\"></span></span>\n                      <input id=\"filter-dueBefore\" type=\"text\" class=\"form-control\"\n                             ng-model=\"filter.properties.dueBefore\"\n                             ng-change=\"filter.refreshDelayed()\"\n                             datepicker-popup=\"yyyy/MM/dd\"\n                             is-open=\"dueBeforePicker.isOpen\"\n                             ng-click=\"dueBeforePicker.isOpen=true\"/>\n\t              </div>\n\t            </div>\n                <div class=\"section\" ng-if=\"filter.properties.dueAfter !== undefined\">\n\t              <div class=\"subtitle\"><label for=\"filter-dueAfter\" translate=\"JOBS.FILTER.DUE-AFTER\"></label> </div>\n               \t  <div class=\"input-group input-group-sm\">\n               \t  \t<span class=\"input-group-addon\"><span class=\"glyphicon glyphicon-time\"></span></span>\n\t              \t<input id=\"filter-dueAfter\" type=\"text\" class=\"form-control\"\n                           ng-model=\"filter.properties.dueAfter\"\n                           ng-change=\"filter.refreshDelayed()\"\n                           datepicker-popup=\"dd/MM/yyyy\"\n                           is-open=\"dueAfterPicker.isOpen\"\n                           ng-click=\"dueAfterPicker.isOpen=true\"/>\n\t              </div>\n\t            </div>\n                <div class=\"section\" ng-if=\"filter.properties.withException !== undefined\">\n\t              <div class=\"subtitle\"><label for=\"filter-withException\" translate=\"JOBS.FILTER.EXCEPTION\"></label> </div>\n               \t  <div class=\"input-group input-group-sm\">\n               \t  \t<input type=\"checkbox\" id=\"filter-withException\" ng-model=\"filter.properties.withException\" ng-change=\"filter.refresh()\" />&nbsp;<span class=\"check\" translate=\"JOBS.FILTER.EXCEPTION-HELP\"></span>\n\t              </div>\n\t            </div>\n            </div>\n        </div>\n    </div>\n</div>\n"
  },
  {
    "path": "flowable-ui-web/admin/views/cmmn-task.html",
    "content": "<div class=\"container\" id=\"detail-container\" ng-cloak ng-show=\"task\">\n\t<div class=\"row\">\n\t\t<div class=\"col-md-9\">\n\t\t\t<div class=\"component\" >\n\t\t\t\t<div class=\"title\">\n\t\t\t\t\t<div class=\"pull-right\">\n\t\t\t\t\t\t<a ng-click=\"returnToList()\" class=\"action\">&larr; {{'GENERAL.ACTION.RETURN-TO-LIST' | translate}}</a>\n\t\t\t\t\t</div>\n\t\t\t\t\t<h2>{{task.name &amp;&amp; task.name + \" - \" || \"\"}}{{task.id}}</h2>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"property-wrapper\">\n\t\t\t\t\t<table>\n\t\t\t\t\t\t<tr class=\"property\">\n\t\t\t\t\t\t\t<td class=\"property-name\" translate=\"TASK.ID\"></td>\n\t\t\t\t\t\t\t<td>{{task.id}}</td>\n\t\t\t\t\t\t\t<td class=\"property-name\" translate=\"TASK.STATUS\"></td>\n\t\t\t\t\t\t\t<td>{{task.endTime &amp;&amp; ('TASK.STATUS-COMPLETED' | translate) || ('TASK.STATUS-ACTIVE' | translate)}}</td>\n\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t<tr class=\"property\">\n\t\t\t\t\t\t\t<td class=\"property-name\" translate=\"TASK.NAME\"></td>\n\t\t\t\t\t\t\t<td>{{task.name | empty}}</td>\n\t\t\t\t\t\t\t<td class=\"property-name\" translate=\"TASK.DESCRIPTION\"></td>\n\t\t\t\t\t\t\t<td>{{task.description | empty}}</td>\n\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t<tr class=\"property\">\n\t\t\t\t\t\t\t<td class=\"property-name\" translate=\"TASK.TASK-DEFINITION-KEY\"></td>\n\t\t\t\t\t\t\t<td>{{task.taskDefinitionKey | empty}}</td>\n\t\t\t\t\t\t\t<td class=\"property-name\" translate=\"TASK.FORM-KEY\"></td>\n\t\t\t\t\t\t\t<td ng-if=\"task.formKey && task.endTime\"> {{task.formKey | empty}} <a ng-click=\"showTaskForm()\"><i class=\"glyphicon glyphicon-zoom-in\"></i> {{'TASK.ACTION.SHOW-SUBMITTED-FORM' | translate}}</a></td>\n\t\t\t\t\t\t\t<td ng-if=\"!task.endTime && task.formKey\">\n\t\t\t\t\t\t\t\t<a ng-href=\"#/form/{{task.formKey}}\"><i class=\"glyphicon glyphicon-zoom-in\"></i> {{task.formKey}}</a>\n\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t<tr class=\"property\">\n\t\t\t\t\t\t\t<td class=\"property-name\" translate=\"TASK.PRIORITY\"></td>\n\t\t\t\t\t\t\t<td>{{task.priority | empty}}</td>\n\t\t\t\t\t\t\t<td class=\"property-name\" translate=\"TASK.DELEGATION-STATE\"></td>\n\t\t\t\t\t\t\t<td>{{task.delegationState | empty}}</td>\n\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t<tr class=\"property\">\n\t\t\t\t\t\t\t<td class=\"property-name\" translate=\"TASK.CATEGORY\"></td>\n\t\t\t\t\t\t\t<td>{{task.category | empty}}</td>\n\t\t\t\t\t\t\t<td class=\"property-name\" translate=\"TASK.PARENT\"></td>\n\t\t\t\t\t\t\t<td ng-if=\"task.parentTaskId\"><a ng-click=\"openTask(task.parentTaskId)\"><i class=\"glyphicon glyphicon-zoom-in\"></i> {{task.parentTaskId}}</a></td>\n\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t<tr class=\"property\">\n                            <td class=\"property-name\" translate=\"TASK.TENANT-ID\"></td>\n                            <td>{{task.tenantId | empty}}</td>\n                        </tr>\n\t\t\t\t\t</table>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"seperator\"></div>\n\t\t\t\t<div class=\"property-wrapper\">\n\t\t\t\t\t<table>\n\t\t\t\t\t\t<tr class=\"property\">\n\t\t\t\t\t\t\t<td class=\"property-name\"><span class=\"glyphicon glyphicon-user\"></span> {{'TASK.ASSIGNEE' | translate}}</td>\n\t\t\t\t\t\t\t<td>{{task.assignee | empty}}</td>\n\t\t\t\t\t\t\t<td class=\"property-name\"><span class=\"glyphicon glyphicon-user\"></span> {{'TASK.OWNER' | translate}}</td>\n\t\t\t\t\t\t\t<td>{{task.owner | empty}}</td>\n\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t<tr class=\"property\">\n\t\t\t\t\t\t\t<td class=\"property-name\"><span class=\"glyphicon glyphicon-time\"></span> {{'TASK.START-DATE' | translate}}</td>\n\t\t\t\t\t\t\t<td>{{task.startTime | dateformat | empty}}</td>\n\t\t\t\t\t\t\t<td class=\"property-name\"><span class=\"glyphicon glyphicon-time\"></span> {{'TASK.DUE-DATE' | translate}}</td>\n\t\t\t\t\t\t\t<td>{{task.dueDate | dateformat | empty}}</td>\n\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t<tr class=\"property\" ng-if=\"task.endTime\">\n\t\t\t\t\t\t\t<td class=\"property-name\"><span class=\"glyphicon glyphicon-time\"></span> {{'TASK.END-DATE' | translate}}</td>\n\t\t\t\t\t\t\t<td>{{task.endTime | dateformat | empty}}</td>\n\t\t\t\t\t\t\t<td class=\"property-name\" translate=\"TASK.DELETE-REASON\"></td>\n\t\t\t\t\t\t\t<td>{{task.deleteReason | empty}}</td>\n\t\t\t\t\t\t</tr>\n\t\t\t\t\t</table>\n\t\t\t\t</div>\n\t\t\t\t\n\t\t\t\t<!-- Only visible for tasks associated to a case instance -->\n\t\t\t\t<div class=\"seperator\" ng-if=\"taskPartOfCase\"></div>\n\t\t\t\t<div class=\"property-wrapper\">\n\t\t\t\t\t<table ng-if=\"taskPartOfCase\">\n\t\t\t\t\t\t<tr class=\"property\">\n\t\t\t\t\t\t\t<td class=\"property-name\"></span> {{'TASK.CASE-INSTANCE' | translate}}</td>\n\t\t\t\t\t\t\t<td><a ng-click=\"openCaseInstance(task.caseInstanceId)\"><i class=\"glyphicon glyphicon-zoom-in\"></i> {{task.caseInstanceId | empty}}</a></td>\n\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t<tr class=\"property\">\n\t\t\t\t\t\t\t<td class=\"property-name\"></span> {{'TASK.CASE-DEFINITION' | translate}}</td>\n\t\t\t\t\t\t\t<td><a ng-click=\"openCaseDefinition(task.caseDefinitionId)\"><i class=\"glyphicon glyphicon-zoom-in\"></i> {{task.caseDefinitionId | empty}}</a></td>\n\t\t\t\t\t\t</tr>\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<div class=\"col-md-3\">\n\t\t\t<div class=\"component tip-left\">\n\t\t\t\t<div class=\"title\">\n\t\t\t\t\t<h2 translate=\"GENERAL.TITLE.ACTIONS\"></h2>\n\t\t\t\t</div>\n\t\t\t\t<ul class=\"list-group\">\n\t\t\t\t\t  <li ng-if=\"!taskCompleted\">\n\t\t\t\t\t    <button type=\"button\" class=\"btn btn-sm btn-default\"  ng-click=\"editTask()\">\n\t\t\t\t\t\t\t<i class=\"glyphicon glyphicon-pencil\"></i>{{'TASK.ACTION.EDIT' | translate}}\n\t\t\t\t\t    </button>\n\t\t\t\t\t  </li>\n\t\t\t\t\t  <li ng-if=\"!taskCompleted\">\n\t\t\t\t\t    <button type=\"button\" class=\"btn btn-sm btn-default\" ng-click=\"assignTask()\">\n\t\t\t\t\t\t\t<i class=\"glyphicon glyphicon-user\"></i>{{'TASK.ACTION.ASSIGN-CLAIM' | translate}}\n\t\t\t\t\t    </button>\n\t\t\t\t\t  </li>\n\t\t\t\t\t  <li ng-if=\"!taskCompleted && task.delegationState != 'pending' && task.delegationStateLoaded\">\n\t\t\t\t\t    <button type=\"button\" class=\"btn btn-sm btn-default\" ng-click=\"delegateTask()\">\n\t\t\t\t\t\t\t<i class=\"glyphicon glyphicon-transfer\"></i>{{'TASK.ACTION.DELEGATE' | translate}}\n\t\t\t\t\t    </button>\n\t\t\t\t\t  </li>\n\t\t\t\t\t   <li ng-if=\"!taskCompleted && task.delegationState == 'pending' && task.delegationStateLoaded\">\n\t\t\t\t\t    <button type=\"button\" class=\"btn btn-sm btn-default\" ng-click=\"resolveTask()\">\n\t\t\t\t\t\t\t<i class=\"glyphicon glyphicon-transfer\"></i>{{'TASK.ACTION.RESOLVE' | translate}}\n\t\t\t\t\t    </button>\n\t\t\t\t\t  </li>\n\t\t\t\t\t  <li ng-if=\"!taskCompleted\">\n\t\t\t\t\t    <button type=\"button\" class=\"btn btn-sm btn-default\" ng-click=\"completeTask()\">\n\t\t\t\t\t\t\t<i class=\"glyphicon glyphicon-check\"></i>{{'TASK.ACTION.COMPLETE' | translate}}\n\t\t\t\t\t    </button>\n\t\t\t\t\t  </li>\n\t\t\t\t\t  <li ng-if=\"taskCompleted || (!taskCompleted && !taskPartOfProcess)\">\n\t\t\t\t\t    <button type=\"button\" class=\"btn btn-sm btn-default btn-danger\" ng-click=\"deleteTask()\">\n\t\t\t\t\t\t\t<i class=\"glyphicon glyphicon-remove\"></i>{{'TASK.ACTION.DELETE' | translate}}\n\t\t\t\t\t    </button>\n\t\t\t\t\t  </li>\n\t\t\t    </ul>\n\t\t\t</div>\n\t\t</div>\n\t</div>\n\t<div class=\"row\">\n\t\t<div class=\"col-md-9\">\n\t\t\t<div class=\"component\">\n\t\t\t\t<div class=\"tabs-wrapper\">\n\t\t\t\t\t<div class=\"pull-right\">\n\t\t\t\t\t\t<a ng-click=\"showAllSubtasks()\" class=\"action\" ng-show=\"tabData.activeTab == tabData.tabs[0].id\"><i class=\"glyphicon glyphicon-zoom-in\"></i> {{'TASK.ACTION.SHOW-ALL-SUBTASKS' | translate}}</a>\n\t\t\t\t\t</div>\n\t\t       \t\t<div class=\"tabs clearfix\">\n\t\t       \t\t\t<div class=\"tab\" ng-repeat=\"tab in tabData.tabs\" ng-class=\"{'active': tabData.activeTab == tab.id}\">\n\t\t       \t\t\t\t<a ng-click=\"tabData.activeTab = tab.id\">\n\t\t       \t\t\t\t\t{{tab.name | translate:node}}&nbsp;\n\t\t    \t\t\t\t\t<span class=\"badge\" ng-if=\"tab.info != undefined\">{{tab.info}}</span>\n\t\t    \t\t\t\t</a>\n\t\t       \t\t\t</div>\n\t\t       \t\t</div>\n\t\t        \t<div class=\"title\"></div>\n\t\t        \t\n\t\t        \t<div class=\"grid-wrapper grid-wrapper-compact\" ng-if=\"subTasks && tabData.activeTab == tabData.tabs[0].id\">\n\t\t\t\t\t\t<div class=\"grid-message\" ng-if=\"subTasks.size > 0\">\n\t                        <span>{{'TASK.SUBTASKS-MESSAGE' | translate:subTasks}}</span>\n\t                    </div>\n\t                     <div class=\"grid-message\" ng-if=\"subTasks.size == 0\">\n\t                        <span>{{'TASK.SUBTASKS-MESSAGE-EMPTY' | translate}}</span>\n\t                    </div>\n\t\t\t\t\t\t<div ng-grid=\"subTaskGridDefinitions\" class=\"gridStyle\" ng-if=\"subTasks\" ng-show=\"subTasks.size > 0\"></div>\n\t\t\t\t\t</div>\n\t\t\t\t\t\n\t\t\t\t\t<div class=\"grid-wrapper grid-wrapper-compact\" ng-if=\"variables && tabData.activeTab == tabData.tabs[1].id\">\n\t\t\t\t\t\t<div class=\"grid-message\" ng-if=\"variables.size > 0\">\n\t                        <span>{{'TASK.VARIABLES-MESSAGE' | translate:variables}}</span>\n\t                    </div>\n\t                     <div class=\"grid-message\" ng-if=\"variables.size == 0\">\n\t                        <span>{{'TASK.VARIABLES-MESSAGE-EMPTY' | translate}}</span>\n\t                    </div>\n\t\t\t\t\t\t<div ng-grid=\"variableGridDefinitions\" class=\"gridStyle\" ng-if=\"variables\" ng-show=\"variables.size > 0\"></div>\n\t\t\t\t\t</div>\n\t\t\t\t\t\n\t\t\t\t\t<div class=\"grid-wrapper grid-wrapper-compact\" ng-if=\"identityLinks && tabData.activeTab == tabData.tabs[2].id\">\n\t\t\t\t\t\t<div class=\"grid-message\" ng-if=\"identityLinks.size > 0\">\n\t\t\t\t\t\t<span>{{'TASK.IDENTITY-LINKS-MESSAGE' | translate:identityLinks}}</span>\n\t                    </div>\n\t                     <div class=\"grid-message\" ng-if=\"identityLinks.size == 0\">\n\t                        <span>{{'TASK.IDENTITY-LINKS-MESSAGE-EMPTY' | translate}}</span>\n\t                    </div>\n\t\t\t\t\t\t<div ng-grid=\"identityLinkGridDefinitions\" class=\"gridStyle\" ng-if=\"identityLinks\" ng-show=\"identityLinks.size > 0\"></div>\n\t\t\t\t\t</div>\n\t\t        </div>\n\t\t    </div>\n\t\t</div>\n\t</div>\n</div>\n"
  },
  {
    "path": "flowable-ui-web/admin/views/cmmn-tasks.html",
    "content": "<div class=\"container\" >\n    <div class=\"row\">\n        <div class=\"col-md-9\">\n            <div class=\"component\">\n                <div class=\"title\">\n                    <div class=\"btn-group btn-group-sm pull-right\">\n                        <div class=\"btn-group btn-group-sm\">\n                            <button type=\"button\" class=\"btn btn-default dropdown-toggle\" data-toggle=\"dropdown\"\n                                    translate=\"GENERAL.ACTION.SHOW-RESULTS\" translate-value-size=\"{{'GENERAL.RESULT-SIZES.' + filter.resultSize | translate}}\">\n                                &nbsp;\n                                <span class=\"caret\"></span>\n                            </button>\n                            <ul class=\"dropdown-menu\">\n                            \t<li ng-repeat=\"resultSize in config.filter.resultSizes\"><a href=\"\" ng-click=\"filter.setResultSize(resultSize)\">{{'GENERAL.RESULT-SIZES.' + resultSize.toString() | translate}}</a></li>\n                            </ul>\n                        </div>\n                        <button type=\"button\" class=\"btn btn-default\" ng-click=\"filter.toggleOrder()\">\n                        \t<i class=\"glyphicon\" ng-class=\"{'glyphicon-sort-by-attributes': filter.order == 'asc', 'glyphicon-sort-by-attributes-alt': filter.order == 'desc'}\"></i>\n                        </button>\n                    </div>\n                    <div class=\"btn-group btn-group-sm pull-right\">\n                    \t<button type=\"button\" class=\"btn btn-default dropdown-toggle\" data-toggle=\"dropdown\"\n                                translate=\"GENERAL.ACTION.SHOW-RESULTS\" translate-value-size=\"{{'GENERAL.RESULT-SIZES.' + filter.resultSize | translate}}\">\n                            &nbsp;\n                            <span class=\"caret\"></span>\n                        </button>\n                    \t<ul class=\"dropdown-menu\">\n                           <li ng-repeat=\"sort in filter.sortObjects\"><a href=\"\" ng-click=\"filter.setSort(sort)\">{{sort.name | translate}}</a></li>\n                        </ul>\n                    </div>\n                    <div class=\"btn-group btn-group-sm pull-right\">\n                        <a class=\"btn btn-default\" role=\"button\"\n                           title=\"{{'GENERAL.ACTION.REFRESH-LIST' | translate}}\"\n                           ng-click=\"filter.refresh();\">\n                            <i class=\"glyphicon glyphicon-refresh\"></i>\n                        </a>\n                    </div>\n                    <div class=\"pull-right loading\" ng-show=\"filter.loading\">\n                    \t<i class=\"glyphicon glyphicon-refresh\"></i>\n                    </div>\n\n                    <h2 translate=\"TASKS.TITLE\"></h2>\n                </div>\n\n                <div class=\"grid-wrapper\" id=\"process-instances\">\n                    <div class=\"grid-message\" ng-if=\"taskData.size > 0\">\n                        <span>{{'TASKS.LIST-MESSAGE' | translate:taskData}}</span>\n                    </div>\n                     <div class=\"grid-message\" ng-if=\"taskData.size == 0\">\n                        <span>{{'TASKS.LIST-MESSAGE-EMPTY' | translate}}</span>\n                    </div>\n                    <div ng-grid=\"gridDefinitions\" class=\"gridStyle\" ng-if=\"gridDefinitions && taskData.data\" />\n                </div>\n            </div>\n        </div>\n\n\t\t<!-- Task filters -->\n\t\t<div class=\"col-md-3\">\n            <div class=\"component tip-left\">\n                <div class=\"title\">\n                    <div class=\"btn-group btn-group-sm pull-right\" ng-show=\"filter.supportedProperties.length > 0\">\n                        <button type=\"button\" class=\"btn btn-default\" data-toggle=\"dropdown\">\n                            <i class=\"glyphicon glyphicon-plus\"></i>\n                        </button>\n                        <ul class=\"dropdown-menu\">\n                            <li ng-repeat=\"prop in filter.supportedProperties\"><a href=\"\" ng-click=\"addFilterProperty(prop)\">{{prop.name | translate}}</a></li>\n                        </ul>\n                    </div>\n                   <div class=\"pull-right\">\n                        <a class=\"action\" ng-click=\"clearFilters()\" translate=\"GENERAL.ACTION.CLEAR-FILTERS\"></a>\n                    </div>\n                    <h2 translate=\"GENERAL.TITLE.FILTERS\"></h2>\n                </div>\n                <div class=\"section\" ng-if=\"filter.properties.finished !== undefined\">\n                    <div class=\"subtitle\"><label for=\"filter-finished\" translate=\"TASKS.FILTER.STATUS\"></label> </div>\n                    <div class=\"input-group input-group-sm\" id=\"filter-state\">\n                       <div class=\"btn-group btn-group-sm\">\n                    \t<button type=\"button\" id=\"filter-finished\" class=\"btn btn-default dropdown-toggle form-control\" data-toggle=\"dropdown\">\n                            <span class=\"pull-right\">\n                            \t<span class=\"caret\"></span>\n                            </span>\n                    \t\t{{filter.getLabelForOption('finished') | translate}}\n                        </button>\n                    \t<ul class=\"dropdown-menu\">\n                            <li ng-repeat=\"state in filter.options.finished\"><a href=\"\" ng-click=\"filter.selectOption('finished', state)\">{{state.name | translate}}</a></li>\n                        </ul>\n                    </div>\n                    </div>\n                </div>\n                <div class=\"section\" ng-if=\"filter.properties.taskNameLike !== undefined\">\n                    <div class=\"subtitle\"><label for=\"filter-taskNameLike\" translate=\"TASKS.FILTER.NAME\"></label> </div>\n                    <div class=\"input-group input-group-sm\">\n                        <input id=\"filter-taskNameLike\" type=\"text\" class=\"form-control\" value=\"\" ng-model=\"filter.properties.taskNameLike\" ng-change=\"filter.refreshDelayed()\">\n                    </div>\n                </div>\n\n                <div class=\"seperator\"></div>\n                <!-- People filtering -->\n                <div class=\"section\" ng-if=\"filter.properties.taskAssignee !== undefined\">\n                    <div class=\"subtitle\"><label for=\"filter-taskAssignee\"><span class=\"glyphicon glyphicon-user\"></span> {{'TASKS.FILTER.ASSIGNEE' | translate}}</label> </div>\n                    <div class=\"input-group input-group-sm type-ahead-scrollable\">\n                    \t<input id=\"filter-taskAssignee\" type=\"text\" users-typeahead user-model=\"filter.properties.taskAssignee\" user-display-model=\"assigneeFilter\" user-on-change=\"filter.refreshDelayed()\" class=\"form-control\">\n                    </div>\n                </div>\n                <div class=\"section\" ng-if=\"filter.properties.taskOwner !== undefined\">\n                    <div class=\"subtitle\"><label for=\"filter-taskOwner\"><span class=\"glyphicon glyphicon-user\"></span> {{'TASKS.FILTER.OWNER' | translate}}</label> </div>\n                    <div class=\"input-group input-group-sm type-ahead-scrollable\">\n                    \t<input id=\"filter-taskOwner\" type=\"text\" users-typeahead user-model=\"filter.properties.taskOwner\" user-display-model=\"ownerFilter\" user-on-change=\"filter.refreshDelayed()\" class=\"form-control\">\n                    </div>\n                </div>\n                <div class=\"section\" ng-if=\"filter.properties.parentTaskId !== undefined\">\n                    <div class=\"subtitle\"><label for=\"filter-parentTaskId\" translate=\"TASKS.FILTER.PARENT-TASK-ID\"></label> </div>\n                    <div class=\"input-group input-group-sm\">\n                        <input id=\"filter-parentTaskId\" type=\"text\" class=\"form-control\" value=\"\" ng-model=\"filter.properties.parentTaskId\" ng-change=\"filter.refreshDelayed()\">\n                    </div>\n                </div>\n                <div class=\"section\" ng-if=\"filter.properties.caseInstanceId !== undefined\">\n                    <div class=\"subtitle\"><label for=\"filter-caseInstanceId\" translate=\"TASKS.FILTER.CASE-INSTANCE-ID\"></label> </div>\n                    <div class=\"input-group input-group-sm\">\n                        <input id=\"filter-caseInstanceId\" type=\"text\" class=\"form-control\" value=\"\" ng-model=\"filter.properties.caseInstanceId\" ng-change=\"filter.refreshDelayed()\">\n                    </div>\n                </div>\n                <div class=\"section\" ng-if=\"filter.properties.tenantIdLike !== undefined\">\n                    <div class=\"subtitle\"><label for=\"filter-tenantid\">{{'TASKS.FILTER.TENANT-ID' | translate}}</label> </div>\n                    <div class=\"input-group input-group-sm\">\n                        <input id=\"filter-tenantid\" type=\"text\" class=\"form-control\" value=\"\" ng-model=\"filter.properties.tenantIdLike\" ng-change=\"filter.refreshDelayed()\">\n                    </div>\n                </div>\n                <!-- Date filtering -->\n                <div class=\"section\" ng-if=\"filter.properties.dueBefore !== undefined\">\n                  <div class=\"subtitle\"><label for=\"filter-dueBefore\" translate=\"TASKS.FILTER.DUE-BEFORE\"></label> </div>\n               \t  <div class=\"input-group input-group-sm\">\n               \t  \t<span class=\"input-group-addon\"><span class=\"glyphicon glyphicon-time\"></span></span>\n\t              \t<input id=\"filter-dueBefore\" type=\"text\" class=\"form-control\" ng-model=\"filter.properties.dueDateBefore\"\n                           ng-change=\"filter.refreshDelayed()\"\n                           datepicker-popup=\"dd/MM/yyyy\"\n                           is-open=\"dueBeforePicker.isOpen\" ng-click=\"dueBeforePicker.isOpen=true\"/>\n\t              </div>\n\t            </div>\n                <div class=\"section\" ng-if=\"filter.properties.dueAfter !== undefined\">\n\t              <div class=\"subtitle\"><label for=\"filter-dueAfter\" translate=\"TASKS.FILTER.DUE-AFTER\"></label> </div>\n               \t  <div class=\"input-group input-group-sm\">\n               \t  \t<span class=\"input-group-addon\"><span class=\"glyphicon glyphicon-time\"></span></span>\n\t              \t<input id=\"filter-dueAfter\" type=\"text\" class=\"form-control\" ng-model=\"filter.properties.dueDateAfter\"\n                           ng-change=\"filter.refreshDelayed()\"\n                           datepicker-popup=\"dd/MM/yyyy\"\n                           is-open=\"dueAfterPicker.isOpen\" ng-click=\"dueAfterPicker.isOpen=true\"/>\n\t              </div>\n\t            </div>\n\n\t            <div class=\"section\" ng-if=\"filter.properties.taskCreatedBefore !== undefined\">\n                  <div class=\"subtitle\"><label for=\"filter-taskCreatedBefore\" translate=\"TASKS.FILTER.CREATED-BEFORE\"></label> </div>\n               \t  <div class=\"input-group input-group-sm\">\n               \t  \t<span class=\"input-group-addon\"><span class=\"glyphicon glyphicon-time\"></span></span>\n\t              \t<input id=\"filter-taskCreatedBefore\" type=\"text\" class=\"form-control\" ng-model=\"filter.properties.taskCreatedBefore\"\n                           ng-change=\"filter.refreshDelayed()\"\n                           datepicker-popup=\"dd/MM/yyyy\"\n                           is-open=\"createdBeforePicker.isOpen\" ng-click=\"createdBeforePicker.isOpen=true\"/>\n\t              </div>\n\t            </div>\n                <div class=\"section\" ng-if=\"filter.properties.taskCreatedAfter !== undefined\">\n\t              <div class=\"subtitle\"><label for=\"filter-taskCreatedAfter\" translate=\"TASKS.FILTER.CREATED-AFTER\"></label> </div>\n               \t  <div class=\"input-group input-group-sm\">\n               \t  \t<span class=\"input-group-addon\"><span class=\"glyphicon glyphicon-time\"></span></span>\n\t              \t<input id=\"filter-taskCreatedAfter\" type=\"text\" class=\"form-control\" ng-model=\"filter.properties.taskCreatedAfter\"\n                           ng-change=\"filter.refreshDelayed()\"\n                           datepicker-popup=\"dd/MM/yyyy\"\n                           is-open=\"createdAfterPicker.isOpen\" ng-click=\"createdAfterPicker.isOpen=true\"/>\n\t              </div>\n\t            </div>\n\n\t            <div class=\"section\" ng-if=\"filter.properties.taskCompletedBefore !== undefined\">\n                  <div class=\"subtitle\"><label for=\"filter-taskCompletedBefore\" translate=\"TASKS.FILTER.ENDED-BEFORE\"></label> </div>\n               \t  <div class=\"input-group input-group-sm\">\n               \t  \t<span class=\"input-group-addon\"><span class=\"glyphicon glyphicon-time\"></span></span>\n\t              \t<input id=\"filter-taskCompletedBefore\" type=\"text\" class=\"form-control\" ng-model=\"filter.properties.taskCompletedBefore\"\n                           ng-change=\"filter.refreshDelayed()\"\n                           datepicker-popup=\"dd/MM/yyyy\"\n                           is-open=\"completedBeforePicker.isOpen\" ng-click=\"completedBeforePicker.isOpen=true\"/>\n\t              </div>\n\t            </div>\n                <div class=\"section\" ng-if=\"filter.properties.taskCompletedAfter !== undefined\">\n\t              <div class=\"subtitle\"><label for=\"filter-taskCompletedAfter\" translate=\"TASKS.FILTER.ENDED-AFTER\"></label> </div>\n               \t  <div class=\"input-group input-group-sm\">\n               \t  \t<span class=\"input-group-addon\"><span class=\"glyphicon glyphicon-time\"></span></span>\n\t              \t<input id=\"filter-taskCompletedAfter\" type=\"text\" class=\"form-control\" ng-model=\"filter.properties.taskCompletedAfter\"\n                           ng-change=\"filter.refreshDelayed()\"\n                           datepicker-popup=\"dd/MM/yyyy\"\n                           is-open=\"completedAfterPicker.isOpen\" ng-click=\"completedAfterPicker.isOpen=true\"/>\n\t              </div>\n\t            </div>\n\n\t            <div class=\"section clearfix\" ng-repeat=\"varFilter in filter.properties.taskVariables\">\n\t              <div class=\"seperator\" ng-if=\"$index > 0\"></div>\n\t              <div class=\"subtitle\"><label translate=\"TASKS.FILTER.TASK-VARIABLE\"></label> </div>\n               \t  <div class=\"inline-button input-group-sm\">\n\t              \t\t<div class=\"pull-right btn-group\">\n\t                        <button ng-disabled=\"varFilter.type.id == 'boolean'\" tabindex=\"-1\" type=\"button\" class=\"btn btn-sm btn-default dropdown-toggle\" data-toggle=\"dropdown\">\n\t                             {{varFilter.operator.sign}} <i class=\"caret\"></i>\n\t                        </button>\n\t                        <ul class=\"dropdown-menu\">\n\t                            <li><a href=\"\" ng-click=\"setVariableFilterOperator(varFilter, operator)\" ng-repeat=\"operator in variableFilterOperators\">{{operator.name}}</a></li>\n\t                        </ul>\n\t                    </div>\n\t              \t\t<input id=\"filter-taskVariables-name-{{$index}}\" type=\"text\" class=\"form-control\" ng-model=\"varFilter.name\" ng-change=\"filter.refreshDelayed()\" placeholder=\"{{'TASKS.FILTER.VARIABLE-NAME' | translate}}\" />\n\t              </div>\n               \t  <div class=\"inline-button wide input-group-sm\" >\n\t              \t\t<div class=\"pull-right btn-group\">\n\t                        <button tabindex=\"-1\" ng-disabled=\"varFilter.operator.id == 'like'\" type=\"button\" class=\"btn btn-sm btn-default dropdown-toggle\" data-toggle=\"dropdown\">\n\t                           {{varFilter.type.name}} <i class=\"caret\"></i>\n\t                        </button>\n\t                        <ul class=\"dropdown-menu\">\n\t                            <li><a href=\"\" ng-click=\"setVariableFilterType(varFilter, type)\" ng-repeat=\"type in variableFilterTypes\" >{{type.name}}</a></li>\n\t                        </ul>\n\t                    </div>\n\t              \t\t<input ng-if=\"varFilter.type.id != 'date' && varFilter.type.id != 'boolean'\" id=\"filter-taskVariables-value-{{$index}}\" type=\"text\" class=\"form-control\" ng-model=\"varFilter.value\" ng-change=\"filter.refreshDelayed()\" placeholder=\"{{'TASKS.FILTER.VARIABLE-VALUE' | translate}}\" />\n\t              \t\t<input ng-if=\"varFilter.type.id == 'date'\" id=\"filter-taskVariables-value-{{$index}}\" type=\"text\" class=\"form-control\" ng-model=\"varFilter.value\"\n                               ng-change=\"filter.refresh()\"\n                               datepicker-popup=\"dd/MM/yyyy\"\n                               is-open=\"varValuePicker.isOpen\" ng-click=\"varValuePicker.isOpen=true\"/>\n\t              \t\t<div class=\"checkbox\" ng-if=\"varFilter.type.id == 'boolean'\">\n\t\t\t\t\t\t    <label>\n\t\t\t\t\t\t      <input type=\"checkbox\" ng-change=\"filter.refresh()\" ng-model=\"varFilter.value\">{{'TASKS.FILTER.VARIABLE-BOOLEAN-VALUE' | translate:varFilter}}\n\t\t\t\t\t\t    </label>\n  \t\t\t\t\t\t</div>\n\t              </div>\n\t            </div>\n            </div>\n        </div>\n    </div>\n</div>\n"
  },
  {
    "path": "flowable-ui-web/admin/views/confirm-popup.html",
    "content": "<div class=\"modal-header-wrapper\">\n\t<div class=\"modal-header\">\n\t\t<div class=\"pull-right\">\n            <a class=\"action\" ng-click=\"$close()\">&times; {{'GENERAL.ACTION.CANCEL-AND-CLOSE' | translate}}</a>\n        </div>\n\t\t<h2>{{model.title}}</h2>\n\t</div>\n</div>\n<div class=\"modal-body\">\n\t<p>{{model.message}}</p>\n</div>\n\n<div class=\"modal-footer-wrapper\">\n\t<div class=\"modal-footer\">\n\t\t<div class=\"pull-right\">\n\t       <button type=\"button\" class=\"btn btn-sm btn-default\" ng-click=\"$close()\" ng-disabled=\"status.loading\"\n\t       \t\ttranslate=\"GENERAL.ACTION.CANCEL\">\n\t       \t</button>\n\t       <button type=\"button\" class=\"btn btn-sm btn-danger\" ng-click=\"ok()\" ng-disabled=\"status.loading\"\n\t           translate=\"{{model.confirm}}\">\n\t       </button>\n\t\t</div>\n</div>\n</div>\n"
  },
  {
    "path": "flowable-ui-web/admin/views/content-item.html",
    "content": "<!-- LIST PAGE -->\n<div class=\"container\" id=\"list-container\">\n    <div class=\"row\">\n        <div class=\"col-md-9\">\n            <div class=\"component\" ng-show=\"contentItem\">\n                <div class=\"title\">\n                    <div class=\"pull-right\">\n                        <a ng-click=\"returnToList()\" class=\"action\">&larr; {{'GENERAL.ACTION.RETURN-TO-LIST' | translate}}</a>\n                    </div>\n                    <h2>{{contentItem.name &amp;&amp; contentItem.name +\" - \" || \"\"}}{{contentItem.id}}</h2>\n                </div>\n\n                <div class=\"property-wrapper\">\n                    <table>\n                        <tr class=\"property\">\n                            <td class=\"property-name\" translate=\"CONTENT-ITEM.HEADER.ID\"></td>\n                            <td>{{contentItem.id}}</td>\n                            <td class=\"property-name\" translate=\"CONTENT-ITEM.HEADER.TASK-ID\"></td>\n                            <td ng-if=\"contentItem.taskId\"><a ng-href=\"#/task/{{contentItem.taskId}}\"><i class=\"glyphicon glyphicon-zoom-in\"></i> {{contentItem.taskId}}</a></td>\n                            <td ng-if=\"!contentItem.taskId\">{{contentItem.taskId | empty}}</td>\n                        </tr>\n                        <tr class=\"property\">\n                        \t<td class=\"property-name\" translate=\"CONTENT-ITEM.HEADER.PROCESS-INSTANCE-ID\"></td>\n                            <td ng-if=\"contentItem.processInstanceId\"><a ng-href=\"#/process-instance/{{contentItem.processInstanceId}}\"><i class=\"glyphicon glyphicon-zoom-in\"></i> {{contentItem.processInstanceId}}</a></td>\n                            <td ng-if=\"!contentItem.processInstanceId\">{{contentItem.processInstanceId | empty}}</td>\n                            <td class=\"property-name\" translate=\"CONTENT-ITEM.HEADER.CREATED-ON\"></td>\n                            <td>{{contentItem.created | dateformat}}</td>\n                        </tr>\n                        <tr class=\"property\">\n                            <td class=\"property-name\" translate=\"CONTENT-ITEM.HEADER.CREATED-BY\"></td>\n                            <td user=\"contentItem.createdBy\"></td>\n                            <td class=\"property-name\" translate=\"CONTENT-ITEM.HEADER.LAST-MODIFIED-ON\"></td>\n                            <td>{{contentItem.lastModified | dateformat}}</td>\n                        </tr>\n                        <tr class=\"property\">\n                            <td class=\"property-name\" translate=\"CONTENT-ITEM.HEADER.LAST-MODIFIED-BY\"></td>\n                            <td user=\"contentItem.lastModifiedBy\"></td>\n                            <td class=\"property-name\" translate=\"CONTENT-ITEM.HEADER.CONTENT-STORE-ID\"></td>\n                            <td>{{contentItem.contentStoreId}}</td>\n                        </tr>\n                    </table>\n                </div>\n            </div>\n        </div>\n        <div class=\"col-md-3\">\n            <div class=\"component tip-left\">\n                <div class=\"title\">\n                    <h2 translate=\"GENERAL.TITLE.ACTIONS\"></h2>\n                </div>\n                <ul class=\"list-group\">\n                    <li>\n                        <button type=\"button\" class=\"btn btn-sm btn-default\" ng-click=\"showContentItem()\">\n                            <i class=\"glyphicon glyphicon-zoom-in\"></i>{{'CONTENT-ITEM.ACTION.SHOW-CONTENT-ITEM' | translate}}\n                        </button>\n                    </li>\n                </ul>\n            </div>\n        </div>\n    </div>\n</div>"
  },
  {
    "path": "flowable-ui-web/admin/views/content-items.html",
    "content": "<!-- LIST PAGE -->\n<div class=\"container\" id=\"list-container\">\n    <div class=\"row\">\n        <div class=\"col-md-8\">\n            <div class=\"component\">\n                <div class=\"title\">\n                    <div class=\"btn-group btn-group-sm pull-right\">\n                        <div class=\"btn-group btn-group-sm\">\n                            <button type=\"button\" class=\"btn btn-default dropdown-toggle\" data-toggle=\"dropdown\"\n                                    translate=\"GENERAL.ACTION.SHOW-RESULTS\" translate-value-size=\"{{'GENERAL.RESULT-SIZES.' + filter.resultSize | translate}}\">\n\t\t\t\t\t\t\t\t&nbsp;\n                                <span class=\"caret\"></span>\n                            </button>\n                            <ul class=\"dropdown-menu\">\n                            \t<li ng-repeat=\"resultSize in config.filter.resultSizes\"><a href=\"\" ng-click=\"filter.setResultSize(resultSize)\">{{'GENERAL.RESULT-SIZES.' + resultSize.toString() | translate}}</a></li>\n                            </ul>\n                        </div>\n                        <button type=\"button\" class=\"btn btn-default\" ng-click=\"filter.toggleOrder()\">\n                        \t<i class=\"glyphicon\" ng-class=\"{'glyphicon-sort-by-attributes': filter.order == 'asc', 'glyphicon-sort-by-attributes-alt': filter.order == 'desc'}\"></i>\n                        </button>\n                    </div>\n                    <div class=\"btn-group btn-group-sm pull-right\">\n                    \t<button type=\"button\" class=\"btn btn-default dropdown-toggle\" data-toggle=\"dropdown\"\n                                translate=\"GENERAL.ACTION.SORT-BY\" translate-value-sort=\"{{filter.sort.name | translate}}\">\n                            &nbsp;\n                            <span class=\"caret\"></span>\n                        </button>\n                    \t<ul class=\"dropdown-menu\">\n                           <li ng-repeat=\"sort in filter.sortObjects\"><a href=\"\" ng-click=\"filter.setSort(sort)\">{{sort.name | translate}}</a></li>\n                        </ul>\n                    </div>\n                    <div class=\"btn-group btn-group-sm pull-right\">\n                        <a class=\"btn btn-default\" role=\"button\"\n                           title=\"{{'GENERAL.ACTION.REFRESH-LIST' | translate}}\"\n                           ng-click=\"filter.refresh();\">\n                            <i class=\"glyphicon glyphicon-refresh\"></i>\n                        </a>\n                    </div>\n                    <div class=\"pull-right loading\" ng-show=\"filter.loading\">\n                    \t<i class=\"glyphicon glyphicon-refresh\"></i>\n                    </div>\n                    <h2 translate=\"CONTENT-ITEMS.TITLE\"></h2>\n                </div>\n\n                <div class=\"grid-wrapper\" id=\"forms\">\n                    <div class=\"grid-message\" ng-if=\"contentItemsData.size > 0\">\n                        <span>{{'CONTENT-ITEMS.LIST-MESSAGE' | translate:contentItemsData}}</span>\n                    </div>\n                     <div class=\"grid-message\" ng-if=\"contentItemsData.size == 0\">\n                        <span>{{'CONTENT-ITEMS.LIST-MESSAGE-EMPTY' | translate}}</span>\n                    </div>\n                    <div ng-grid=\"gridContentItems\" class=\"gridStyle\" ng-if=\"gridContentItems && contentItemsData.data\"/>\n                </div>\n            </div>\n        </div>\n        <div class=\"col-md-4\">\n\n            <!-- forms filters -->\n            <div class=\"component tip-left\">\n                <div class=\"title\">\n                    <div class=\"pull-right\">\n                        <a class=\"action\" ng-click=\"filter.clear()\" translate=\"GENERAL.ACTION.CLEAR-FILTERS\"></a>\n                    </div>\n                    <h2 translate=\"GENERAL.TITLE.FILTERS\"></h2>\n                </div>\n                <div class=\"section\" ng-if=\"filter.properties.nameLike !== undefined\">\n                    <div class=\"subtitle\"><label for=\"filter-nameLike\" translate=\"FORM-INSTANCES.FILTER.NAME\"></label> </div>\n                    <div class=\"input-group input-group-sm\">\n                        <input id=\"filter-nameLike\" type=\"text\" class=\"form-control\" value=\"\" ng-model=\"filter.properties.nameLike\" ng-change=\"filter.refreshDelayed()\">\n                    </div>\n                </div>\n                <div class=\"section\" ng-if=\"filter.properties.tenantId !== undefined\">\n                    <div class=\"subtitle\"><label for=\"filter-tenantId\" translate=\"APP-DEPLOYMENTS.FILTER.TENANTID\"></label> </div>\n                    <div class=\"input-group input-group-sm\">\n                        <input id=\"filter-tenantId\" type=\"text\" class=\"form-control\" value=\"\" number-input-check ng-model=\"filter.properties.tenantId\" ng-change=\"filter.refreshDelayed()\">\n                    </div>\n                </div>\n            </div>\n\n        </div>\n\n        </div>\n    </div>\n</div>"
  },
  {
    "path": "flowable-ui-web/admin/views/decision-table-deployment.html",
    "content": "<div class=\"container\" id=\"detail-container\">\n\t<div class=\"row\">\n\t\t<div class=\"col-md-9\">\n\t\t\t<div class=\"component\" ng-show=\"deployment\">\n\t\t\t\t<div class=\"title\">\n\t\t\t\t\t<div class=\"pull-right\">\n\t\t\t\t\t\t<a ng-click=\"returnToList()\" class=\"action\">&larr; {{'GENERAL.ACTION.RETURN-TO-LIST' | translate}}</a>\n\t\t\t\t\t</div>\n\t\t\t\t\t<h2>{{deployment.name || deployment.id}}</h2>\n\t\t\t\t</div>\n\n\t\t\t\t<div class=\"property-wrapper\">\n\t\t\t\t\t<table>\n\t\t\t\t\t\t<tr class=\"property\">\n\t\t\t\t\t\t\t<td class=\"property-name\" translate=\"DECISION-TABLE-DEPLOYMENT.ID\"></td>\n\t\t\t\t\t\t\t<td>{{deployment.id}}</td>\n\t\t\t\t\t\t\t<td class=\"property-name\" translate=\"DECISION-TABLE-DEPLOYMENT.NAME\"></td>\n\t\t\t\t\t\t\t<td>{{deployment.name | empty}}</td>\n\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t<tr class=\"property\">\n\t\t\t\t\t\t\t<td class=\"property-name\" translate=\"DECISION-TABLE-DEPLOYMENT.TIME\"></td>\n\t\t\t\t\t\t\t<td>{{deployment.deploymentTime | dateformat:'full'}}</td>\n\t\t\t\t\t\t\t<td class=\"property-name\" translate=\"DECISION-TABLE-DEPLOYMENT.CATEGORY\"></td>\n\t\t\t\t\t\t\t<td>{{deployment.category | empty}}</td>\n\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t<tr class=\"property\">\n                            <td class=\"property-name\" translate=\"DECISION-TABLE-DEPLOYMENT.TENANTID\"></td>\n                            <td>{{deployment.tenantId | empty}}</td>\n\t\t\t\t\t\t\t<td ng-if=\"deployment.parentDeploymentId\" class=\"property-name\" translate=\"DECISION-TABLE-DEPLOYMENT.PARENT-DEPLOYMENT-ID\"></td>\n\t\t\t\t\t\t\t<td ng-if=\"deployment.parentDeploymentId\"><a ng-href=\"#/app-deployment/{{deployment.parentDeploymentId}}\"><i class=\"glyphicon glyphicon-zoom-in\"></i> {{deployment.parentDeploymentId}}</a></td>\n\t\t\t\t\t\t</tr>\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 class=\"col-md-3\">\n\t\t\t<div class=\"component tip-left\">\n\t\t\t\t<div class=\"title\">\n\t\t\t\t\t<h2 translate=\"GENERAL.TITLE.ACTIONS\"></h2>\n\t\t\t\t</div>\n\t\t\t\t<ul class=\"list-group\">\n\t\t\t\t\t  <li>\n\t\t\t\t\t    <button type=\"button\" class=\"btn btn-sm btn-default btn-danger\" ng-click=\"deleteDeployment()\">\n\t\t\t\t\t\t\t<i class=\"glyphicon glyphicon-remove\"></i><span translate=\"DECISION-TABLE-DEPLOYMENTS.ACTION.DELETE\"></span>\n\t\t\t\t\t    </button>\n\t\t\t\t\t  </li>\n\t\t\t\t</ul>\n\t\t\t</div>\n\t\t</div>\n\t</div>\n\t<div class=\"row\">\n\t\t<div class=\"col-md-9\">\n\t\t\t<div class=\"component\">\n\t\t\t\t<div class=\"title\">\n\t\t\t\t\t<div class=\"pull-right\">\n\t\t\t\t\t\t<a ng-click=\"showAllDecisionTables()\" class=\"action\"><i class=\"glyphicon glyphicon-zoom-in\"></i> {{'DECISION-TABLE-DEPLOYMENT.ACTION.SHOW-ALL-DEFINITIONS' | translate}}</a>\n\t\t\t\t\t</div>\n\t\t\t\t\t<h2 translate=\"DECISION-TABLE-DEPLOYMENT.TITLE.DECISION-TABLES\"></h2>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"grid-wrapper grid-wrapper-compact\" ng-if=\"decisionTables\">\n\t\t\t\t\t<div class=\"grid-message\" ng-if=\"decisionTables.size > 0\">\n\t                       <span>{{'DECISION-TABLE-DEPLOYMENT.DECISION-TABLES-MESSAGE' | translate:decisionTables}}</span>\n\t                   </div>\n\t                    <div class=\"grid-message\" ng-if=\"decisionTables.size == 0\">\n\t                       <span>{{'DECISION-TABLE-DEPLOYMENT.DECISION-TABLES-MESSAGE-EMPTY' | translate}}</span>\n\t                   </div>\n\t\t\t\t\t<div ng-grid=\"gridDecisionTables\" class=\"gridStyle\" ng-if=\"gridDecisionTables && decisionTables.data\" ng-show=\"decisionTables.size > 0\"></div>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</div>\n\t</div>\n</div>\n"
  },
  {
    "path": "flowable-ui-web/admin/views/decision-table-deployments.html",
    "content": "<!-- LIST PAGE -->\n<div class=\"container\" id=\"list-container\">\n    <div class=\"row\">\n        <div class=\"col-md-8\">\n            <div class=\"component\">\n                <div class=\"title\">\n                    <div class=\"btn-group btn-group-sm pull-right\">\n                        <div class=\"btn-group btn-group-sm\">\n                            <button type=\"button\" class=\"btn btn-default dropdown-toggle\" data-toggle=\"dropdown\"\n                                    translate=\"GENERAL.ACTION.SHOW-RESULTS\" translate-value-size=\"{{'GENERAL.RESULT-SIZES.' + filter.resultSize | translate}}\">\n\t\t\t\t\t\t\t\t&nbsp;\n                                <span class=\"caret\"></span>\n                            </button>\n                            <ul class=\"dropdown-menu\">\n                            \t<li ng-repeat=\"resultSize in config.filter.resultSizes\"><a href=\"\" ng-click=\"filter.setResultSize(resultSize)\">{{'GENERAL.RESULT-SIZES.' + resultSize.toString() | translate}}</a></li>\n                            </ul>\n                        </div>\n                        <button type=\"button\" class=\"btn btn-default\" ng-click=\"filter.toggleOrder()\">\n                        \t<i class=\"glyphicon\" ng-class=\"{'glyphicon-sort-by-attributes': filter.order == 'asc', 'glyphicon-sort-by-attributes-alt': filter.order == 'desc'}\"></i>\n                        </button>\n                    </div>\n                    <div class=\"btn-group btn-group-sm pull-right\">\n                    \t<button type=\"button\" class=\"btn btn-default dropdown-toggle\" data-toggle=\"dropdown\"\n                                translate=\"GENERAL.ACTION.SORT-BY\" translate-value-sort=\"{{filter.sort.name | translate}}\">\n\t\t\t\t\t\t    &nbsp;\n                            <span class=\"caret\"></span>\n                        </button>\n                    \t<ul class=\"dropdown-menu\">\n                           <li ng-repeat=\"sort in filter.sortObjects\"><a href=\"\" ng-click=\"filter.setSort(sort)\">{{sort.name | translate}}</a></li>\n                        </ul>\n                    </div>\n                    <div class=\"btn-group btn-group-sm pull-right\">\n                        <a class=\"btn btn-default\" role=\"button\"\n                           title=\"{{'GENERAL.ACTION.REFRESH-LIST' | translate}}\"\n                           ng-click=\"filter.refresh();\">\n                            <i class=\"glyphicon glyphicon-refresh\"></i>\n                        </a>\n                    </div>\n                    <div class=\"pull-right loading\" ng-show=\"filter.loading\">\n                    \t<i class=\"glyphicon glyphicon-refresh\"></i>\n                    </div>\n                    <h2 translate=\"DECISION-TABLE-DEPLOYMENTS.TITLE\"></h2>\n                </div>\n\n                <div class=\"grid-wrapper\" id=\"deployments\">\n                    <div class=\"grid-message\" ng-if=\"deploymentsData.size > 0\">\n                        <span>{{'DEPLOYMENTS.LIST-MESSAGE' | translate:deploymentsData}}</span>\n                    </div>\n                     <div class=\"grid-message\" ng-if=\"deploymentsData.size == 0\">\n                        <span>{{'DEPLOYMENTS.LIST-MESSAGE-EMPTY' | translate}}</span>\n                    </div>\n                    <div ng-grid=\"gridDeployments\" class=\"gridStyle\" ng-if=\"gridDeployments && deploymentsData.data\"/>\n                </div>\n            </div>\n        </div>\n        <div class=\"col-md-4\">\n\n            <!-- Deployment filters -->\n            <div class=\"component tip-left\">\n                <div class=\"title\">\n                    <div class=\"pull-right\">\n                        <a class=\"action\" ng-click=\"filter.clear()\" translate=\"GENERAL.ACTION.CLEAR-FILTERS\"></a>\n                    </div>\n                    <h2 translate=\"GENERAL.TITLE.FILTERS\"></h2>\n                </div>\n                <div class=\"section\" ng-if=\"filter.properties.nameLike !== undefined\">\n                    <div class=\"subtitle\"><label for=\"filter-nameLike\" translate=\"DECISION-TABLE-DEPLOYMENTS.FILTER.NAME\"></label> </div>\n                    <div class=\"input-group input-group-sm\">\n                        <input id=\"filter-nameLike\" type=\"text\" class=\"form-control\" value=\"\" ng-model=\"filter.properties.nameLike\" ng-change=\"filter.refreshDelayed()\">\n                    </div>\n                </div>\n                <div class=\"section\" ng-if=\"filter.properties.tenantIdLike !== undefined\">\n                    <div class=\"subtitle\"><label for=\"filter-tenantIdLike\" translate=\"DECISION-TABLE-DEPLOYMENTS.FILTER.TENANTID\"></label> </div>\n                    <div class=\"input-group input-group-sm\">\n                        <input id=\"filter-tenantIdLike\" type=\"text\" class=\"form-control\" value=\"\" ng-model=\"filter.properties.tenantIdLike\" ng-change=\"filter.refreshDelayed()\">\n                    </div>\n                </div>\n            </div>\n\n            <div class=\"component no-min-height\">\n                <div class=\"title\">\n                    <h2 translate=\"GENERAL.TITLE.ACTIONS\"></h2>\n                </div>\n                <ul class=\"list-group\">\n                    <li>\n                        <button type=\"button\" class=\"btn btn-sm btn-default\" ng-click=\"uploadDeployment()\">\n                            <i class=\"glyphicon glyphicon-open\"></i>{{'DECISION-TABLE-DEPLOYMENTS.ACTION.UPLOAD' | translate}}\n                        </button>\n                    </li>\n                </ul>\n            </div>\n\n        </div>\n    </div>\n</div>"
  },
  {
    "path": "flowable-ui-web/admin/views/decision-table-execution.html",
    "content": "<div class=\"container\" id=\"detail-container\">\n\t<div class=\"row\">\n\t\t<div class=\"col-md-9\">\n\t\t\t<div class=\"component\" ng-show=\"execution\" style=\"min-height: 210px;\">\n\t\t\t\t<div class=\"title\">\n\t\t\t\t\t<div class=\"pull-right\">\n\t\t\t\t\t\t<a ng-click=\"returnToList()\" class=\"action\">&larr; {{'GENERAL.ACTION.RETURN-TO-LIST' | translate}}</a>\n\t\t\t\t\t</div>\n\t\t\t\t\t<h2>{{execution.id}}</h2>\n\t\t\t\t</div>\n\n\t\t\t\t<div class=\"property-wrapper\">\n\t\t\t\t\t<table>\n\t\t\t\t\t\t<tr class=\"property\">\n\t\t\t\t\t\t\t<td class=\"property-name\" translate=\"DECISION-TABLE-EXECUTION.DEFINITION-ID\"></td>\n\t\t\t\t\t\t\t<td><a ng-href=\"#/decision-table/{{execution.decisionDefinitionId}}\"><i class=\"glyphicon glyphicon-zoom-in\"></i> {{execution.decisionDefinitionId}}</a></td>\n\t\t\t\t\t\t\t<td class=\"property-name\" translate=\"DECISION-TABLE-EXECUTION.DEPLOYMENT-ID\"></td>\n\t\t\t\t\t\t\t<td><a ng-href=\"#/decision-table-deployment/{{execution.deploymentId}}\"><i class=\"glyphicon glyphicon-zoom-in\"></i> {{execution.deploymentId}}</a></td>\n\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t<tr class=\"property\">\n\t\t\t\t\t\t\t<td class=\"property-name\" translate=\"DECISION-TABLE-EXECUTION.DEFINITION-KEY\"></td>\n\t\t\t\t\t\t\t<td>{{execution.decisionKey}}</td>\n\t\t\t\t\t\t\t<td class=\"property-name\" translate=\"DECISION-TABLE-EXECUTION.DEFINITION-VERSION\"></td>\n\t\t\t\t\t\t\t<td>{{execution.decisionVersion}}</td>\n\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t<tr class=\"property\">\n\t\t\t\t\t\t\t<td class=\"property-name\" translate=\"DECISION-TABLE-EXECUTION.DEFINITION-NAME\"></td>\n\t\t\t\t\t\t\t<td>{{execution.decisionName}}</td>\n\t\t\t\t\t\t\t<td class=\"property-name\" ng-if=\"!execution.scopeType || execution.scopeType != 'cmmn'\" translate=\"DECISION-TABLE-EXECUTION.PROCESS-INSTANCE-ID\"></td>\n\t\t\t\t\t\t\t<td ng-if=\"!execution.scopeType || execution.scopeType != 'cmmn'\"><a ng-href=\"#/process-instance/{{execution.instanceId}}\"><i class=\"glyphicon glyphicon-zoom-in\"></i> {{execution.instanceId}}</a></td>\n\t\t\t\t\t\t\t<td class=\"property-name\" ng-if=\"execution.scopeType && execution.scopeType == 'cmmn'\" translate=\"DECISION-TABLE-EXECUTION.CASE-INSTANCE-ID\"></td>\n                            <td ng-if=\"execution.scopeType && execution.scopeType == 'cmmn'\"><a ng-href=\"#/case-instance/{{execution.instanceId}}\"><i class=\"glyphicon glyphicon-zoom-in\"></i> {{execution.instanceId}}</a></td>\n\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t<tr class=\"property\">\n\t\t\t\t\t\t\t<td class=\"property-name\" translate=\"DECISION-TABLE-EXECUTION.FAILED\"></td>\n\t\t\t\t\t\t\t<td>{{execution.failed}}</td>\n\t\t\t\t\t\t</tr>\n\t\t\t\t\t</table>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"seperator\"></div>\n\t\t\t\t<div class=\"property-wrapper\">\n\t\t\t\t\t<table>\n\t\t\t\t\t\t<tr class=\"property\" >\n\t\t\t\t\t\t\t<td class=\"property-name\"><span class=\"glyphicon glyphicon-time\"></span> {{'DECISION-TABLE-EXECUTION.EXECUTION-START-TIME' | translate}}</td>\n\t\t\t\t\t\t\t<td>{{execution.startTime | dateformat | empty}}</td>\n\t\t\t\t\t\t\t<td class=\"property-name\"><span class=\"glyphicon glyphicon-time\"></span> {{'DECISION-TABLE-EXECUTION.EXECUTION-END-TIME' | translate}}</td>\n\t\t\t\t\t\t\t<td>{{execution.endTime| dateformat}}</td>\n\t\t\t\t\t\t</tr>\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 class=\"col-md-3\">\n\t\t\t<div class=\"component tip-left\">\n\t\t\t\t<div class=\"title\">\n\t\t\t\t\t<h2 translate=\"GENERAL.TITLE.ACTIONS\"></h2>\n\t\t\t\t</div>\n\t\t\t\t<ul class=\"list-group\">\n\n\t\t\t\t</ul>\n\t\t\t</div>\n\t\t</div>\n\t</div>\n\t<div class=\"row\">\n\t\t<div class=\"col-md-9\">\n\t\t\t<div class=\"component\">\n\t\t\t\t<div class=\"title\">\n\t\t\t\t\t<h2 translate=\"DECISION-TABLE-EXECUTION.AUDIT-DATA.HEADER\"></h2>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"property-wrapper\">\n\t\t\t\t\t<table>\n\t\t\t\t\t\t<tr class=\"property\">\n\t\t\t\t\t\t\t<td class=\"property-name\" translate=\"DECISION-TABLE-EXECUTION.AUDIT-DATA.HIT-POLICY\"></td>\n\t\t\t\t\t\t\t<td>{{auditData.hitPolicy}}</td>\n\t\t\t\t\t\t\t<td class=\"property-name\" translate=\"DECISION-TABLE-EXECUTION.AUDIT-DATA.STRICT-MODE\"></td>\n\t\t\t\t\t\t\t<td>{{auditData.strictMode == null ? 'true' : auditData.strictMode}}</td>\n\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t<tr class=\"property\">\n\t\t\t\t\t\t\t<td class=\"property-name\" translate=\"DECISION-TABLE-EXECUTION.AUDIT-DATA.RESULT\"></td>\n\t\t\t\t\t\t\t<td ng-if=\"auditData.decisionResult.length > 0\"><json-formatter json=\"auditData.decisionResult\" open=\"2\"></json-formatter></td>\n\t\t\t\t\t\t\t<td ng-if=\"auditData.decisionResult.length === 0\">no result</td>\n\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t<tr class=\"property\">\n\t\t\t\t\t\t\t<td class=\"property-name\" translate=\"DECISION-TABLE-EXECUTION.AUDIT-DATA.RULE-EXECUTIONS\"></td>\n\t\t\t\t\t\t\t<td colspan=\"3\"><json-formatter json=\"auditData.ruleExecutions\"></json-formatter></td>\n\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t<tr class=\"property\" ng-if=\"auditData.failed\">\n\t\t\t\t\t\t\t<td class=\"property-name\" translate=\"DECISION-TABLE-EXECUTION.AUDIT-DATA.EXCEPTION-MESSAGE\"></td>\n\t\t\t\t\t\t\t<td colspan=\"3\">{{auditData.exception}}</td>\n\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t<tr class=\"property\" ng-if=\"!auditData.failed\">\n\t\t\t\t\t\t\t<td class=\"property-name\" translate=\"DECISION-TABLE-EXECUTION.AUDIT-DATA.VALIDATION-MESSAGE\"></td>\n\t\t\t\t\t\t\t<td colspan=\"3\">{{auditData.validationMessage}}</td>\n\t\t\t\t\t\t</tr>\n\t\t\t\t\t</table>\n\t\t\t\t</div>\n\t\t\t\t<div ng-if=\"auditData.inputVariables\">\n\t\t\t\t\t<div class=\"seperator\"></div>\n\t\t\t\t\t<div class=\"property-wrapper\">\n\t\t\t\t\t\t<table>\n\t\t\t\t\t\t\t<tr class=\"property\">\n\t\t\t\t\t\t\t\t<td class=\"property-name\" translate=\"DECISION-TABLE-EXECUTION.AUDIT-DATA.INPUT-VARIABLES\" colspan=\"4\"></td>\n\t\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t\t<tr class=\"property\" ng-if=\"formattedInputVariables.length > 0\" data-ng-repeat=\"row in formattedInputVariables\">\n\t\t\t\t\t\t\t\t<td class=\"property-name\">{{row[0].key}} <i>({{row[0].type}})</i></td>\n\t\t\t\t\t\t\t\t<td>{{row[0].value}}</td>\n\t\t\t\t\t\t\t\t<td class=\"property-name\">{{row[1].key}} <i>({{row[0].type}})</i></td>\n\t\t\t\t\t\t\t\t<td>{{row[1].value}}</td>\n\t\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t\t<tr class=\"property\" ng-if=\"formattedInputVariables.length === 0\">\n\t\t\t\t\t\t\t\t<td colspan=\"4\" class=\"property-name\">no input variables</td>\n\t\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t</table>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</div>\n\t</div>\n</div>\n"
  },
  {
    "path": "flowable-ui-web/admin/views/decision-table-executions.html",
    "content": "<!-- LIST PAGE -->\n<div class=\"container\" id=\"list-container\">\n    <div class=\"row\">\n        <div class=\"col-md-8\">\n            <div class=\"component\">\n                <div class=\"title\">\n                    <div class=\"btn-group btn-group-sm pull-right\">\n                        <div class=\"btn-group btn-group-sm\">\n                            <button type=\"button\" class=\"btn btn-default dropdown-toggle\" data-toggle=\"dropdown\"\n                                    translate=\"GENERAL.ACTION.SHOW-RESULTS\" translate-value-size=\"{{'GENERAL.RESULT-SIZES.' + filter.resultSize | translate}}\">\n                                &nbsp;\n                                <span class=\"caret\"></span>\n                            </button>\n                            <ul class=\"dropdown-menu\">\n                            \t<li ng-repeat=\"resultSize in config.filter.resultSizes\"><a href=\"\" ng-click=\"filter.setResultSize(resultSize)\">{{'GENERAL.RESULT-SIZES.' + resultSize.toString() | translate}}</a></li>\n                            </ul>\n                        </div>\n                        <button type=\"button\" class=\"btn btn-default\" ng-click=\"filter.toggleOrder()\">\n                        \t<i class=\"glyphicon\" ng-class=\"{'glyphicon-sort-by-attributes': filter.order == 'asc', 'glyphicon-sort-by-attributes-alt': filter.order == 'desc'}\"></i>\n                        </button>\n                    </div>\n                    <div class=\"btn-group btn-group-sm pull-right\">\n                    \t<button type=\"button\" class=\"btn btn-default dropdown-toggle\" data-toggle=\"dropdown\"\n                                translate=\"GENERAL.ACTION.SORT-BY\" translate-value-sort=\"{{filter.sort.name | translate}}\">\n                            &nbsp;\n                            <span class=\"caret\"></span>\n                        </button>\n                    \t<ul class=\"dropdown-menu\">\n                           <li ng-repeat=\"sort in filter.sortObjects\"><a href=\"\" ng-click=\"filter.setSort(sort)\">{{sort.name | translate}}</a></li>\n                        </ul>\n                    </div>\n                    <div class=\"btn-group btn-group-sm pull-right\">\n                        <a class=\"btn btn-default\" role=\"button\"\n                           title=\"{{'GENERAL.ACTION.REFRESH-LIST' | translate}}\"\n                           ng-click=\"filter.refresh();\">\n                            <i class=\"glyphicon glyphicon-refresh\"></i>\n                        </a>\n                    </div>\n                    <div class=\"pull-right loading\" ng-show=\"filter.loading\">\n                    \t<i class=\"glyphicon glyphicon-refresh\"></i>\n                    </div>\n                    <h2 translate=\"DECISION-TABLE-EXECUTIONS.TITLE\"></h2>\n                </div>\n\n                <div class=\"grid-wrapper\" id=\"decision-tables\">\n                    <div class=\"grid-message\" ng-if=\"decisionTableExecutionsData.size > 0\">\n                        <span>{{'DECISION-TABLE-EXECUTIONS.LIST-MESSAGE' | translate:decisionTableExecutionsData}}</span>\n                    </div>\n                     <div class=\"grid-message\" ng-if=\"decisionTableExecutionsData.size == 0\">\n                        <span>{{'DECISION-TABLE-EXECUTIONS.LIST-MESSAGE-EMPTY' | translate}}</span>\n                    </div>\n                    <div ng-grid=\"gridDecisionTableExecutions\" class=\"gridStyle\" ng-if=\"gridDecisionTableExecutions && decisionTableExecutionsData.data\"/>\n                </div>\n            </div>\n        </div>\n        <div class=\"col-md-4\">\n\n            <!-- Decision tables filters -->\n            <div class=\"component tip-left\">\n                <div class=\"title\">\n                    <div class=\"pull-right\">\n                        <a class=\"action\" ng-click=\"filter.clear()\" translate=\"GENERAL.ACTION.CLEAR-FILTERS\"></a>\n                    </div>\n                    <h2 translate=\"GENERAL.TITLE.FILTERS\"></h2>\n                </div>\n                <div class=\"section\" ng-if=\"filter.properties.tenantIdLike !== undefined\">\n                    <div class=\"subtitle\"><label for=\"filter-tenantIdLike\" translate=\"DECISION-TABLE-EXECUTIONS.FILTER.TENANTID\"></label> </div>\n                    <div class=\"input-group input-group-sm\">\n                        <input id=\"filter-tenantIdLike\" type=\"text\" class=\"form-control\" value=\"\" ng-model=\"filter.properties.tenantIdLike\" ng-change=\"filter.refreshDelayed()\">\n                    </div>\n                </div>\n            </div>\n\n        </div>\n\n        </div>\n    </div>\n</div>"
  },
  {
    "path": "flowable-ui-web/admin/views/decision-table-popup.html",
    "content": "<div class=\"modal-header-wrapper\">\n\t<div class=\"modal-header\">\n\t\t<div class=\"pull-right\">\n            <a class=\"action\" ng-click=\"cancel()\">&times; {{'GENERAL.ACTION.CANCEL-AND-CLOSE' | translate}}</a>\n        </div>\n\t\t<h2>{{'DECISION-TABLE.POPUP.TITLE' | translate}} '{{popup.currentDecisionTable.name &amp;&amp; popup.currentDecisionTable.name || popup.currentDecisionTable.key}}'</h2>\n\t</div>\n</div>\n<div class=\"modal-body modal-body-medium\">\n\t<div class=\"container-fluid content decision-table\" ng-if=\"popup.currentDecisionTable\" auto-height offset=\"40\">\n\n\t\t<br/>\n\t\t<div class=\"row\" ng-if=\"popup.currentDecisionTable.hitIndicator\">\n\t\t\t<div class=\"col-xs-6\">\n\t\t\t\t<span>\n\t\t\t\t\t<label>{{'DECISION-TABLE.POPUP.HIT-POLICY' | translate}} {{'DECISION-TABLE.POPUP.HIT-POLICIES.' + popup.currentDecisionTable.hitIndicator | translate}}</label>\n\t\t\t\t</span>\n\t\t\t</div>\n\t\t</div>\n\n\t\t<div class=\"decision-table-grid-wrapper\">\n\t\t\t<div id=\"decisionTableGrid\" class=\"decision-table-grid\" ui-grid=\"popup.gridOptions\" ui-grid-selection  ui-grid-cellnav ui-grid-auto-resize></div>\n\t\t</div>\n\n\t</div></div>\n\n<div class=\"modal-footer-wrapper\">\n\t<div class=\"modal-footer\">\n\t\t<div class=\"pull-right\">\n\t       <button type=\"button\" class=\"btn btn-sm btn-default\" ng-click=\"cancel()\" ng-disabled=\"status.loading\"\n\t\t       \ttranslate=\"GENERAL.ACTION.CLOSE\">\n\t       \t</button>\n\t\t</div>\n\t</div>\n</div>\t"
  },
  {
    "path": "flowable-ui-web/admin/views/decision-table.html",
    "content": "<div class=\"container\" id=\"detail-container\">\n\t<div class=\"row\">\n\t\t<div class=\"col-md-9\">\n\t\t\t<div class=\"component\" ng-show=\"decisionTable\">\n\t\t\t\t<div class=\"title\">\n\t\t\t\t\t<div class=\"pull-right\">\n\t\t\t\t\t\t<a ng-click=\"returnToList()\" class=\"action\">&larr; {{'GENERAL.ACTION.RETURN-TO-LIST' | translate}}</a>\n\t\t\t\t\t</div>\n\t\t\t\t\t<h2>{{decisionTable.name &amp;&amp; decisionTable.name +\" - \" || \"\"}}{{decisionTable.id}}</h2>\n\t\t\t\t</div>\n\n\t\t\t\t<div class=\"property-wrapper\">\n\t\t\t\t\t<table>\n\t\t\t\t\t\t<tr class=\"property\">\n\t\t\t\t\t\t\t<td class=\"property-name\" translate=\"DECISION-TABLE.ID\"></td>\n\t\t\t\t\t\t\t<td>{{decisionTable.id}}</td>\n\t\t\t\t\t\t\t<td class=\"property-name\" translate=\"DECISION-TABLE.VERSION\"></td>\n\t\t\t\t\t\t\t<td>{{decisionTable.version}}</td>\n\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t<tr class=\"property\">\n\t\t\t\t\t\t\t<td class=\"property-name\" translate=\"DECISION-TABLE.NAME\"></td>\n\t\t\t\t\t\t\t<td>{{decisionTable.name | empty}}</td>\n\t\t\t\t\t\t\t<td class=\"property-name\" translate=\"DECISION-TABLE.KEY\"></td>\n\t\t\t\t\t\t\t<td>{{decisionTable.key}}</td>\n\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t<tr class=\"property\">\n\t\t\t\t\t\t\t<td class=\"property-name\" translate=\"DECISION-TABLE.RESOURCE-NAME\"></td>\n\t\t\t\t\t\t\t<td>{{decisionTable.resourceName | empty}}</td>\n\t\t\t\t\t\t\t<td class=\"property-name\" translate=\"DECISION-TABLE.DESCRIPTION\"></td>\n\t\t\t\t\t\t\t<td>{{decisionTable.description | empty}}</td>\n\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t<tr class=\"property\">\n\t\t\t\t\t\t\t<td class=\"property-name\" translate=\"DECISION-TABLE.DEPLOYMENT-ID\"></td>\n\t\t\t\t\t\t\t<td><a ng-href=\"#/decision-table-deployment/{{decisionTable.deploymentId}}\"><i class=\"glyphicon glyphicon-zoom-in\"></i> {{decisionTable.deploymentId}}</a></td>\n\t\t\t\t\t\t\t<td ng-if=\"decisionTable.parentDeploymentId\" class=\"property-name\" translate=\"DECISION-TABLE.PARENT-DEPLOYMENT-ID\"></td>\n\t\t\t\t\t\t\t<td ng-if=\"decisionTable.parentDeploymentId\"><a ng-href=\"#/deployment/{{decisionTable.parentDeploymentId}}\"><i class=\"glyphicon glyphicon-zoom-in\"></i> {{decisionTable.parentDeploymentId}}</a></td>\n\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t<tr class=\"property\">\n                            <td class=\"property-name\" translate=\"DECISION-TABLE.TENANT\"></td>\n                            <td>{{decisionTable.tenantId | empty}}</td>\n                        </tr>\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<div class=\"col-md-3\">\n\t\t\t<div class=\"component tip-left\">\n\t\t\t\t<div class=\"title\">\n\t\t\t\t\t<h2 translate=\"GENERAL.TITLE.ACTIONS\"></h2>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</div>\n\t</div>\n\t<div class=\"row\">\n\t\t<div class=\"col-md-9\">\n\t\t\t<div class=\"component\">\n\t\t\t\t<div class=\"title\">\n\t\t\t\t\t<div class=\"pull-right\">\n\t\t\t\t\t\t<a ng-click=\"showAllExecutions()\" class=\"action\"><i class=\"glyphicon glyphicon-zoom-in\"></i> {{'DECISION-TABLE.ACTION.SHOW-ALL-EXECUTIONS' | translate}}</a>\n\t\t\t\t\t</div>\n\t\t\t\t\t<h2 translate=\"DECISION-TABLE-EXECUTIONS.TITLE\"></h2>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"grid-wrapper grid-wrapper-compact\" ng-if=\"decisionExecutions\">\n\t\t\t\t\t<div class=\"grid-message\" ng-if=\"decisionExecutions.size > 0\">\n\t\t\t\t\t\t<span>{{'DECISION-TABLE.DECISION-EXECUTION-MESSAGE' | translate:decisionExecutions}}</span>\n\t\t\t\t\t</div>\n\t\t\t\t\t<div class=\"grid-message\" ng-if=\"decisionExecutions.size == 0\">\n\t\t\t\t\t\t<span>{{'DECISION-TABLE.DECISION-EXECUTION-MESSAGE-EMPTY' | translate}}</span>\n\t\t\t\t\t</div>\n\t\t\t\t\t<div ng-grid=\"gridDecisionExecutions\" class=\"gridStyle\" ng-if=\"gridDecisionExecutions && decisionExecutions.data\" ng-show=\"decisionExecutions.size > 0\"></div>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</div>\n\t</div>\n</div>\n"
  },
  {
    "path": "flowable-ui-web/admin/views/decision-tables.html",
    "content": "<!-- LIST PAGE -->\n<div class=\"container\" id=\"list-container\">\n    <div class=\"row\">\n        <div class=\"col-md-8\">\n            <div class=\"component\">\n                <div class=\"title\">\n                    <div class=\"btn-group btn-group-sm pull-right\">\n                        <div class=\"btn-group btn-group-sm\">\n                            <button type=\"button\" class=\"btn btn-default dropdown-toggle\" data-toggle=\"dropdown\"\n                                    translate=\"GENERAL.ACTION.SHOW-RESULTS\" translate-value-size=\"{{'GENERAL.RESULT-SIZES.' + filter.resultSize | translate}}\">\n                                &nbsp;\n                                <span class=\"caret\"></span>\n                            </button>\n                            <ul class=\"dropdown-menu\">\n                            \t<li ng-repeat=\"resultSize in config.filter.resultSizes\"><a href=\"\" ng-click=\"filter.setResultSize(resultSize)\">{{'GENERAL.RESULT-SIZES.' + resultSize.toString() | translate}}</a></li>\n                            </ul>\n                        </div>\n                        <button type=\"button\" class=\"btn btn-default\" ng-click=\"filter.toggleOrder()\">\n                        \t<i class=\"glyphicon\" ng-class=\"{'glyphicon-sort-by-attributes': filter.order == 'asc', 'glyphicon-sort-by-attributes-alt': filter.order == 'desc'}\"></i>\n                        </button>\n                    </div>\n                    <div class=\"btn-group btn-group-sm pull-right\">\n                    \t<button type=\"button\" class=\"btn btn-default dropdown-toggle\" data-toggle=\"dropdown\"\n                                translate=\"GENERAL.ACTION.SORT-BY\" translate-value-sort=\"{{filter.sort.name | translate}}\">\n                            &nbsp;\n                            <span class=\"caret\"></span>\n                        </button>\n                    \t<ul class=\"dropdown-menu\">\n                           <li ng-repeat=\"sort in filter.sortObjects\"><a href=\"\" ng-click=\"filter.setSort(sort)\">{{sort.name | translate}}</a></li>\n                        </ul>\n                    </div>\n                    <div class=\"btn-group btn-group-sm pull-right\">\n                        <a class=\"btn btn-default\" role=\"button\"\n                           title=\"{{'GENERAL.ACTION.REFRESH-LIST' | translate}}\"\n                           ng-click=\"filter.refresh();\">\n                            <i class=\"glyphicon glyphicon-refresh\"></i>\n                        </a>\n                    </div>\n                    <div class=\"pull-right loading\" ng-show=\"filter.loading\">\n                    \t<i class=\"glyphicon glyphicon-refresh\"></i>\n                    </div>\n                    <h2 translate=\"DECISION-TABLES.TITLE\"></h2>\n                </div>\n\n                <div class=\"grid-wrapper\" id=\"decision-tables\">\n                    <div class=\"grid-message\" ng-if=\"decisionTablesData.size > 0\">\n                        <span>{{'DECISION-TABLES.LIST-MESSAGE' | translate:decisionTablesData}}</span>\n                    </div>\n                     <div class=\"grid-message\" ng-if=\"decisionTablesData.size == 0\">\n                        <span>{{'DECISION-TABLES.LIST-MESSAGE-EMPTY' | translate}}</span>\n                    </div>\n                    <div ng-grid=\"gridDecisionTables\" class=\"gridStyle\" ng-if=\"gridDecisionTables && decisionTablesData.data\"/>\n                </div>\n            </div>\n        </div>\n        <div class=\"col-md-4\">\n\n            <!-- Decision tables filters -->\n            <div class=\"component tip-left\">\n                <div class=\"title\">\n                    <div class=\"pull-right\">\n                        <a class=\"action\" ng-click=\"filter.clear()\" translate=\"GENERAL.ACTION.CLEAR-FILTERS\"></a>\n                    </div>\n                    <h2 translate=\"GENERAL.TITLE.FILTERS\"></h2>\n                </div>\n                <div class=\"section\" ng-if=\"filter.properties.nameLike !== undefined\">\n                    <div class=\"subtitle\"><label for=\"filter-nameLike\" translate=\"DECISION-TABLES.FILTER.NAME\"></label> </div>\n                    <div class=\"input-group input-group-sm\">\n                        <input id=\"filter-nameLike\" type=\"text\" class=\"form-control\" value=\"\" ng-model=\"filter.properties.nameLike\" ng-change=\"filter.refreshDelayed()\">\n                    </div>\n                </div>\n                <div class=\"section\" ng-if=\"filter.properties.keyLike !== undefined\">\n                    <div class=\"subtitle\"><label for=\"filter-keyLike\" translate=\"DECISION-TABLES.FILTER.KEY\"></label> </div>\n                    <div class=\"input-group input-group-sm\">\n                        <input id=\"filter-keyLike\" type=\"text\" class=\"form-control\" value=\"\" ng-model=\"filter.properties.keyLike\" ng-change=\"filter.refreshDelayed()\">\n                    </div>\n                </div>\n                <div class=\"section\" ng-if=\"filter.properties.tenantIdLike !== undefined\">\n                    <div class=\"subtitle\"><label for=\"filter-tenantIdLike\" translate=\"DECISION-TABLES.FILTER.TENANTID\"></label> </div>\n                    <div class=\"input-group input-group-sm\">\n                        <input id=\"filter-tenantIdLike\" type=\"text\" class=\"form-control\" value=\"\" ng-model=\"filter.properties.tenantIdLike\" ng-change=\"filter.refreshDelayed()\">\n                    </div>\n                </div>\n            </div>\n\n        </div>\n\n        </div>\n    </div>\n</div>"
  },
  {
    "path": "flowable-ui-web/admin/views/deployment.html",
    "content": "<div class=\"container\" id=\"detail-container\">\n\t<div class=\"row\">\n\t\t<div class=\"col-md-9\">\n\t\t\t<div class=\"component\" ng-show=\"deployment\">\n\t\t\t\t<div class=\"title\">\n\t\t\t\t\t<div class=\"pull-right\">\n\t\t\t\t\t\t<a ng-click=\"returnToList()\" class=\"action\">&larr; {{'GENERAL.ACTION.RETURN-TO-LIST' | translate}}</a>\n\t\t\t\t\t</div>\n\t\t\t\t\t<h2>{{deployment.name + \" - \" + deployment.id}}</h2>\n\t\t\t\t</div>\n\n\t\t\t\t<div class=\"property-wrapper\">\n\t\t\t\t\t<table>\n\t\t\t\t\t\t<tr class=\"property\">\n\t\t\t\t\t\t\t<td class=\"property-name\" translate=\"DEPLOYMENT.ID\"></td>\n\t\t\t\t\t\t\t<td>{{deployment.id}}</td>\n\t\t\t\t\t\t\t<td class=\"property-name\" translate=\"DEPLOYMENT.NAME\"></td>\n\t\t\t\t\t\t\t<td>{{deployment.name}}</td>\n\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t<tr class=\"property\">\n\t\t\t\t\t\t\t<td class=\"property-name\" translate=\"DEPLOYMENT.TIME\"></td>\n\t\t\t\t\t\t\t<td>{{deployment.deploymentTime | dateformat:'full'}}</td>\n\t\t\t\t\t\t\t<td class=\"property-name\" translate=\"DEPLOYMENT.CATEGORY\"></td>\n\t\t\t\t\t\t\t<td>{{deployment.category | empty}}</td>\n\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t<tr class=\"property\">\n                            <td class=\"property-name\" translate=\"DEPLOYMENT.TENANTID\"></td>\n                            <td>{{deployment.tenantId | empty}}</td>\n                            <td ng-if=\"deployment.parentDeploymentId\" class=\"property-name\" translate=\"DEPLOYMENT.PARENT-DEPLOYMENT-ID\"></td>\n                            <td ng-if=\"deployment.parentDeploymentId\"><a ng-href=\"#/app-deployment/{{deployment.parentDeploymentId}}\"><i class=\"glyphicon glyphicon-zoom-in\"></i> {{deployment.parentDeploymentId}}</a></td>\n                        </tr>\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 class=\"col-md-3\">\n\t\t\t<div class=\"component tip-left\">\n\t\t\t\t<div class=\"title\">\n\t\t\t\t\t<h2 translate=\"GENERAL.TITLE.ACTIONS\"></h2>\n\t\t\t\t</div>\n\t\t\t\t<ul class=\"list-group\">\n\t\t\t\t\t  <li>\n\t\t\t\t\t    <button type=\"button\" class=\"btn btn-sm btn-default btn-danger\" ng-click=\"deleteDeployment()\">\n\t\t\t\t\t\t\t<i class=\"glyphicon glyphicon-remove\"></i><span translate=\"DEPLOYMENTS.ACTION.DELETE\"></span>\n\t\t\t\t\t    </button>\n\t\t\t\t\t  </li>\n\t\t\t\t</ul>\n\t\t\t</div>\n\t\t</div>\n\t</div>\n\t<div class=\"row\">\n\t\t<div class=\"col-md-9\">\n\t\t\t<div class=\"component\">\n\t\t\t\t<div class=\"title\">\n\t\t\t\t\t<div class=\"pull-right\">\n\t\t\t\t\t\t<a ng-click=\"showAllDefinitions()\" class=\"action\"><i class=\"glyphicon glyphicon-zoom-in\"></i> {{'DEPLOYMENT.ACTION.SHOW-ALL-DEFINITIONS' | translate}}</a>\n\t\t\t\t\t</div>\n\t\t\t\t\t<h2 translate=\"DEPLOYMENT.TITLE.DEFINITIONS\"></h2>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"grid-wrapper grid-wrapper-compact\" ng-if=\"definitions\">\n\t\t\t\t\t<div class=\"grid-message\" ng-if=\"definitions.size > 0\">\n\t                       <span>{{'DEPLOYMENT.DEFINITIONS-MESSAGE' | translate:definitions}}</span>\n\t                   </div>\n\t                    <div class=\"grid-message\" ng-if=\"definitions.size == 0\">\n\t                       <span>{{'DEPLOYMENT.DEFINITIONS-MESSAGE-EMPTY' | translate}}</span>\n\t                   </div>\n\t\t\t\t\t<div ng-grid=\"gridDefinitions\" class=\"gridStyle\" ng-if=\"gridDefinitions && definitions.data\" ng-show=\"definitions.size > 0\"></div>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</div>\n\t</div>\n</div>\n"
  },
  {
    "path": "flowable-ui-web/admin/views/deployments.html",
    "content": "<!-- LIST PAGE -->\n<div class=\"container\" id=\"list-container\">\n    <div class=\"row\">\n        <div class=\"col-md-8\">\n            <div class=\"component\">\n                <div class=\"title\">\n                    <div class=\"btn-group btn-group-sm pull-right\">\n                        <div class=\"btn-group btn-group-sm\">\n                            <button type=\"button\" class=\"btn btn-default dropdown-toggle\" data-toggle=\"dropdown\"\n                                    translate=\"GENERAL.ACTION.SHOW-RESULTS\" translate-value-size=\"{{'GENERAL.RESULT-SIZES.' + filter.resultSize | translate}}\">\n                                &nbsp;\n                                <span class=\"caret\"></span>\n                            </button>\n                            <ul class=\"dropdown-menu\">\n                            \t<li ng-repeat=\"resultSize in config.filter.resultSizes\"><a href=\"\" ng-click=\"filter.setResultSize(resultSize)\">{{'GENERAL.RESULT-SIZES.' + resultSize.toString() | translate}}</a></li>\n                            </ul>\n                        </div>\n                        <button type=\"button\" class=\"btn btn-default\" ng-click=\"filter.toggleOrder()\">\n                        \t<i class=\"glyphicon\" ng-class=\"{'glyphicon-sort-by-attributes': filter.order == 'asc', 'glyphicon-sort-by-attributes-alt': filter.order == 'desc'}\"></i>\n                        </button>\n                    </div>\n                    <div class=\"btn-group btn-group-sm pull-right\">\n                    \t<button type=\"button\" class=\"btn btn-default dropdown-toggle\" data-toggle=\"dropdown\"\n                                translate=\"GENERAL.ACTION.SORT-BY\" translate-value-sort=\"{{filter.sort.name | translate}}\">\n                            &nbsp;\n                            <span class=\"caret\"></span>\n                        </button>\n                    \t<ul class=\"dropdown-menu\">\n                           <li ng-repeat=\"sort in filter.sortObjects\"><a href=\"\" ng-click=\"filter.setSort(sort)\">{{sort.name | translate}}</a></li>\n                        </ul>\n                    </div>\n                    <div class=\"btn-group btn-group-sm pull-right\">\n                        <a class=\"btn btn-default\" role=\"button\"\n                           title=\"{{'GENERAL.ACTION.REFRESH-LIST' | translate}}\"\n                           ng-click=\"filter.refresh();\">\n                            <i class=\"glyphicon glyphicon-refresh\"></i>\n                        </a>\n                    </div>\n                    <div class=\"pull-right loading\" ng-show=\"filter.loading\">\n                    \t<i class=\"glyphicon glyphicon-refresh\"></i>\n                    </div>\n                    <h2 translate=\"DEPLOYMENTS.TITLE\"></h2>\n                </div>\n\n                <div class=\"grid-wrapper\" id=\"deployments\">\n                    <div class=\"grid-message\" ng-if=\"deploymentsData.size > 0\">\n                        <span>{{'DEPLOYMENTS.LIST-MESSAGE' | translate:deploymentsData}}</span>\n                    </div>\n                     <div class=\"grid-message\" ng-if=\"deploymentsData.size == 0\">\n                        <span>{{'DEPLOYMENTS.LIST-MESSAGE-EMPTY' | translate}}</span>\n                    </div>\n                    <div ng-grid=\"gridDeployments\" class=\"gridStyle\" ng-if=\"gridDeployments && deploymentsData.data\"/>\n                </div>\n            </div>\n        </div>\n        <div class=\"col-md-4\">\n\n            <!-- Deployment filters -->\n            <div class=\"component tip-left\">\n                <div class=\"title\">\n                    <div class=\"pull-right\">\n                        <a class=\"action\" ng-click=\"filter.clear()\" translate=\"GENERAL.ACTION.CLEAR-FILTERS\"></a>\n                    </div>\n                    <h2 translate=\"GENERAL.TITLE.FILTERS\"></h2>\n                </div>\n                <div class=\"section\" ng-if=\"filter.properties.nameLike !== undefined\">\n                    <div class=\"subtitle\"><label for=\"filter-nameLike\" translate=\"DEPLOYMENTS.FILTER.NAME\"></label> </div>\n                    <div class=\"input-group input-group-sm\">\n                        <input id=\"filter-nameLike\" type=\"text\" class=\"form-control\" value=\"\" ng-model=\"filter.properties.nameLike\" ng-change=\"filter.refreshDelayed()\">\n                    </div>\n                </div>\n                <div class=\"section\" ng-if=\"filter.properties.tenantIdLike !== undefined\">\n                    <div class=\"subtitle\"><label for=\"filter-tenantIdLike\" translate=\"DEPLOYMENTS.FILTER.TENANTID\"></label> </div>\n                    <div class=\"input-group input-group-sm\">\n                        <input id=\"filter-tenantIdLike\" type=\"text\" class=\"form-control\" value=\"\" ng-model=\"filter.properties.tenantIdLike\" ng-change=\"filter.refreshDelayed()\">\n                    </div>\n                </div>\n            </div>\n\n            <!-- Actions -->\n            <div class=\"component no-min-height\">\n                <div class=\"title\">\n                    <h2 translate=\"GENERAL.TITLE.ACTIONS\"></h2>\n                </div>\n                <ul class=\"list-group\">\n                    <li>\n                        <button type=\"button\" class=\"btn btn-sm btn-default\" ng-click=\"uploadDeployment()\">\n                            <i class=\"glyphicon glyphicon-open\"></i>{{'DEPLOYMENTS.ACTION.UPLOAD' | translate}}\n                        </button>\n                    </li>\n                </ul>\n            </div>\n\n        </div>\n\n        </div>\n    </div>\n</div>"
  },
  {
    "path": "flowable-ui-web/admin/views/engine-edit-config-popup.html",
    "content": "<div class=\"modal-header-wrapper\">\n    <div class=\"modal-header\">\n        <div class=\"pull-right\">\n            <a class=\"action\" ng-click=\"cancel()\" ng-show=\"!status.loading\">&times; {{'GENERAL.ACTION.CANCEL-AND-CLOSE' | translate}}</a>\n        </div>\n        <h2 ng-if=\"model.newConfig\" translate=\"CLUSTER.POPUP.EDIT-CONFIG.TITLE-NEW\"></h2>\n\n        <h2 ng-if=\"!model.newConfig\" translate=\"CLUSTER.POPUP.EDIT-CONFIG.TITLE-EDIT\"></h2>\n    </div>\n</div>\n<div class=\"modal-body\">\n\n    <div>\n        <table class=\"edit-table\">\n            <tr>\n                <td class=\"edit-label\">\n                    <span>{{'CLUSTER.POPUP.EDIT-CONFIG.CONFIG-OPTIONS' | translate}}</span>\n                </td>\n                <td>\n                    <select class=\"form-control\" ng-model=\"model.configType\" ng-change=\"configTypeChanged()\">\n                        <option value=\"engine\">{{'CLUSTER.POPUP.EDIT-CONFIG.OPTION-ENGINE' | translate}}</option>\n                        <option value=\"bpmSuite\">{{'CLUSTER.POPUP.EDIT-CONFIG.OPTION-SUITE' | translate}}</option>\n                    </select>\n                </td>\n            </tr>\n        </table>\n    </div>\n\n    <!-- BPM Suite -->\n    <div ng-if=\"model.configType == 'bpmSuite' && model.fetchingTemplate == false\" class=\"bpm-suite-config\">\n        <textarea class=\"form-control\" style=\"height:100%;margin-top:15px;\"  ng-model=\"model.bpmSuiteConfig\"></textarea>\n    </div>\n    <div ng-if=\"model.fetchingTemplate == true\">\n        <span>{{'CLUSTER.POPUP.EDIT-CONFIG.FETCHING-TEMPLATE' | translate}}</span>\n    </div>\n\n    <!-- Process Engine -->\n    <table class=\"edit-table\" ng-if=\"model.configType == 'engine'\">\n        <tr>\n            <td>\n                <h4 translate=\"CLUSTER.POPUP.EDIT-CONFIG.TITLE-DATABASE\"></h4>\n            </td>\n            <td>\n            </td>\n        </tr>\n        <tr>\n            <td class=\"edit-label\" translate=\"CLUSTER.POPUP.EDIT-CONFIG.JDBC-URL\"></td>\n            <td>\n                <input type=\"text\" class=\"form-control\" id=\"jdbcUrl\" ng-model=\"model.engineConfig.jdbcUrl\">\n            </td>\n\n        </tr>\n        <tr>\n            <td class=\"edit-label\" translate=\"CLUSTER.POPUP.EDIT-CONFIG.JDBC-DRIVER\"></td>\n            <td>\n                <input type=\"text\" class=\"form-control\" id=\"jdbcDriver\" ng-model=\"model.engineConfig.jdbcDriver\">\n            </td>\n        </tr>\n        <tr>\n            <td class=\"edit-label\" translate=\"CLUSTER.POPUP.EDIT-CONFIG.JDBC-USERNAME\"></td>\n            <td>\n                <input type=\"text\" class=\"form-control\" id=\"jdbcUsername\" ng-model=\"model.engineConfig.jdbcUsername\">\n            </td>\n        </tr>\n        <tr>\n            <td class=\"edit-label\" translate=\"CLUSTER.POPUP.EDIT-CONFIG.JDBC-PASSWORD\"></td>\n            <td>\n                <input type=\"password\" class=\"form-control\" id=\"jdbcPassword\"  ng-model=\"model.engineConfig.jdbcPassword\">\n            </td>\n        </tr>\n        <tr>\n            <td class=\"edit-label\" translate=\"CLUSTER.POPUP.EDIT-CONFIG.JDBC-JNDI-NAME\"></td>\n            <td>\n                <input type=\"text\" class=\"form-control\"  ng-model=\"model.engineConfig.dataSourceJndiName\">\n            </td>\n        </tr>\n        <tr>\n            <td></td>\n            <td>\n                <p class=\"message\"><i class=\"glyphicon glyphicon-info-sign\"></i>&nbsp;\n                    {{'CLUSTER.POPUP.EDIT-CONFIG.JDBC-JNDI-HELP' | translate}}\n                </p>\n            </td>\n        </tr>\n\n\n        <tr>\n            <td>\n                <h4 translate=\"CLUSTER.POPUP.EDIT-CONFIG.TITLE-SCHEMA\"></h4>\n            </td>\n            <td>\n            </td>\n        </tr>\n        <tr>\n            <td class=\"edit-label\" translate=\"CLUSTER.POPUP.EDIT-CONFIG.SCHEMA-UPDATE\"></td>\n            <td>\n                <select class=\"form-control\" id=\"databaseSchemaUpdate\"\n                        ng-model=\"model.engineConfig.databaseSchemaUpdate\">\n                    <option ng-repeat=\"option in options.schemaUpdate\">{{option}}</option>\n                </select>\n            </td>\n        </tr>\n        <tr>\n            <td></td>\n            <td>\n                <p class=\"message\"><i class=\"glyphicon glyphicon-info-sign\"></i>&nbsp;\n                   {{'CLUSTER.POPUP.EDIT-CONFIG.SCHEMA-UPDATE-HELP' | translate}}\n                </p>\n            </td>\n        </tr>\n\n\n        <tr>\n            <td>\n                <h4 translate=\"CLUSTER.POPUP.EDIT-CONFIG.TITLE-HISTORY\"></h4>\n            </td>\n            <td>\n            </td>\n        </tr>\n        <tr>\n            <td class=\"edit-label\" translate=\"CLUSTER.POPUP.EDIT-CONFIG.HISTORY-LEVEL\"></td>\n            <td>\n                <select class=\"form-control\" ng-model=\"model.engineConfig.history\">\n                    <option ng-repeat=\"option in options.history\">{{option}}</option>\n                </select>\n            </td>\n        </tr>\n\n        <tr>\n            <td>\n                 <h4 translate=\"CLUSTER.POPUP.EDIT-CONFIG.TITLE-JOB-EXECUTOR\"></h4>\n            </td>\n            <td>\n            </td>\n        </tr>\n        <tr>\n            <td class=\"edit-label\" translate=\"CLUSTER.POPUP.EDIT-CONFIG.JOB-EXECUTOR-ENABLE\"></td>\n            <td>\n                <input type=\"checkbox\" ng-model=\"model.engineConfig.enableJobExecutor\">\n            </td>\n        </tr>\n\n\n        <tr>\n            <td>\n                 <h4 translate=\"CLUSTER.POPUP.EDIT-CONFIG.TITLE-ADVANCED\"></h4>\n            </td>\n            <td>\n            </td>\n        </tr>\n\n        <tr>\n            <td class=\"edit-label\" translate=\"CLUSTER.POPUP.EDIT-CONFIG.PROCESS-DEF-CACHE-LIMIT\"></td>\n            <td>\n                <input type=\"number\" class=\"form-control\" ng-model=\"model.engineConfig.processDefinitionCacheLimit\">\n            </td>\n        </tr>\n        <tr>\n            <td></td>\n            <td>\n                <p class=\"message\"><i class=\"glyphicon glyphicon-info-sign\"></i>&nbsp;\n                   {{'CLUSTER.POPUP.EDIT-CONFIG.PROCESS-DEF-CACHE-LIMIT-HELP' | translate}}\n                </p>\n            </td>\n        </tr>\n\n        <tr>\n            <td class=\"edit-label\" translate=\"CLUSTER.POPUP.EDIT-CONFIG.ID-BLOCK-SIZE\"></td>\n            <td>\n                <input type=\"number\" class=\"form-control\" ng-model=\"model.engineConfig.idBlockSize\">\n            </td>\n        </tr>\n        <tr>\n            <td></td>\n            <td>\n                <p class=\"message\"><i class=\"glyphicon glyphicon-info-sign\"></i>&nbsp;\n                    {{'CLUSTER.POPUP.EDIT-CONFIG.ID-BLOCK-SIZE-HELP' | translate}}\n                </p>\n            </td>\n        </tr>\n\n        <tr>\n            <td class=\"edit-label-top\">\n                <span ng-if=\"!model.enableJobExecutorCfg\" translate=\"CLUSTER.POPUP.EDIT-CONFIG.TITLE-JOB-TWEAKING\"></span>\n                <h4 ng-if=\"model.enableJobExecutorCfg\" translate=\"CLUSTER.POPUP.EDIT-CONFIG.TITLE-JOB-TWEAKING\"></h4>\n            </td>\n            <td>\n                <div ng-if=\"model.newConfig\">\n                    <input type=\"checkbox\" ng-model=\"model.enableJobExecutorCfg\">\n                    <span translate=\"CLUSTER.POPUP.EDIT-CONFIG.ENABLE-JOB-TWEAKING\"></span>\n                    <p  ng-if=\"!model.enableJobExecutorCfg\" class=\"message\"><i class=\"glyphicon glyphicon-info-sign\"></i>&nbsp;\n                        {{'CLUSTER.POPUP.EDIT-CONFIG.ENABLE-JOB-TWEAKING-HELP' | translate}}\n                    </p>\n                </div>\n            </td>\n        </tr>\n        <tr ng-if=\"model.enableJobExecutorCfg\">\n            <td class=\"edit-label\" translate=\"CLUSTER.POPUP.EDIT-CONFIG.MAX-JOBS-PER-ACQUISITION\"></td>\n            <td>\n                <input type=\"number\" class=\"form-control\" ng-model=\"model.engineConfig.maxJobsPerAcquisition\">\n            </td>\n        </tr>\n        <tr ng-if=\"model.enableJobExecutorCfg\">\n            <td></td>\n            <td>\n                <p class=\"message\"><i class=\"glyphicon glyphicon-info-sign\"></i>&nbsp;\n                    {{'CLUSTER.POPUP.EDIT-CONFIG.MAX-JOBS-PER-ACQUISITION-HELP' | translate}}\n                </p>\n            </td>\n        </tr>\n        <tr ng-if=\"model.enableJobExecutorCfg\">\n            <td class=\"edit-label\" translate=\"CLUSTER.POPUP.EDIT-CONFIG.JOB-WAIT-TIME\"></td>\n            <td>\n                <input type=\"number\" class=\"form-control\" ng-model=\"model.engineConfig.jobWaitTime\">\n            </td>\n        </tr>\n        <tr ng-if=\"model.enableJobExecutorCfg\">\n            <td></td>\n            <td>\n                <p class=\"message\"><i class=\"glyphicon glyphicon-info-sign\"></i>&nbsp;\n                    {{'CLUSTER.POPUP.EDIT-CONFIG.JOB-WAIT-TIME-HELP' | translate}}\n                </p>\n            </td>\n        </tr>\n        <tr ng-if=\"model.enableJobExecutorCfg\">\n            <td class=\"edit-label\" translate=\"CLUSTER.POPUP.EDIT-CONFIG.JOB-LOCK-TIME\"></td>\n            <td>\n                <input type=\"number\" class=\"form-control\" ng-model=\"model.engineConfig.jobLockTime\">\n            </td>\n        </tr>\n        <tr ng-if=\"model.enableJobExecutorCfg\">\n            <td></td>\n            <td>\n                <p class=\"message\"><i class=\"glyphicon glyphicon-info-sign\"></i>\n                   {{'CLUSTER.POPUP.EDIT-CONFIG.JOB-LOCK-TIME-HELP' | translate}}\n                </p>\n            </td>\n        </tr>\n        <tr ng-if=\"model.enableJobExecutorCfg\">\n            <td class=\"edit-label\" translate=\"CLUSTER.POPUP.EDIT-CONFIG.JOB-QUEUE-SIZE\"></td>\n            <td>\n                <input type=\"number\" class=\"form-control\" ng-model=\"model.engineConfig.jobQueueSize\">\n            </td>\n        </tr>\n        <tr ng-if=\"model.enableJobExecutorCfg\">\n            <td></td>\n            <td>\n                <p class=\"message\"><i class=\"glyphicon glyphicon-info-sign\"></i>&nbsp;\n                    {{'CLUSTER.POPUP.EDIT-CONFIG.JOB-QUEUE-SIZE-HELP' | translate}}\n                </p>\n            </td>\n        </tr>\n        <tr ng-if=\"model.enableJobExecutorCfg\">\n            <td class=\"edit-label\" translate=\"CLUSTER.POPUP.EDIT-CONFIG.JOB-CORE-POOL-SIZE\"></td>\n            <td>\n                <input type=\"number\" class=\"form-control\" ng-model=\"model.engineConfig.jobCorePoolSize\">\n            </td>\n        </tr>\n        <tr ng-if=\"model.enableJobExecutorCfg\">\n            <td></td>\n            <td>\n                <p class=\"message\"><i class=\"glyphicon glyphicon-info-sign\"></i>&nbsp;\n                    {{'CLUSTER.POPUP.EDIT-CONFIG.JOB-CORE-POOL-SIZE-HELP' | translate}}\n                </p>\n            </td>\n        </tr>\n        <tr ng-if=\"model.enableJobExecutorCfg\">\n            <td class=\"edit-label\" translate=\"CLUSTER.POPUP.EDIT-CONFIG.JOB-MAX-POOL-SIZE\"></td>\n            <td>\n                <input type=\"number\" class=\"form-control\" ng-model=\"model.engineConfig.jobMaxPoolSize\">\n            </td>\n        </tr>\n        <tr ng-if=\"model.enableJobExecutorCfg\">\n            <td></td>\n            <td>\n                <p class=\"message\"><i class=\"glyphicon glyphicon-info-sign\"></i>\n                    {{'CLUSTER.POPUP.EDIT-CONFIG.JOB-MAX-POOL-SIZE-HELP' | translate}}\n                </p>\n            </td>\n        </tr>\n\n\n        <tr>\n            <td class=\"edit-label-top\">\n                 <span ng-if=\"!model.enableJobExecutorCfg\" translate=\"CLUSTER.POPUP.EDIT-CONFIG.TITLE-DB-POOL\"></span>\n                <h4 ng-if=\"model.enableJobExecutorCfg\" translate=\"CLUSTER.POPUP.EDIT-CONFIG.TITLE-DB-POOL\"></h4>\n            </td>\n            <td>\n                <div ng-if=\"model.newConfig\">\n                    <input type=\"checkbox\" ng-model=\"model.enableConnectionPoolCfg\">\n                    <span translate=\"CLUSTER.POPUP.EDIT-CONFIG.ENABLE-DB-POOL\"></span>\n                    <p  ng-if=\"!model.enableConnectionPoolCfg\" class=\"message\"><i class=\"glyphicon glyphicon-info-sign\"></i>&nbsp;\n                       {{'CLUSTER.POPUP.EDIT-CONFIG.ENABLE-DB-POOL-HELP' | translate}}\n                    </p>\n                </div>\n            </td>\n        </tr>\n        <tr ng-if=\"model.enableConnectionPoolCfg\">\n            <td class=\"edit-label\" translate=\"CLUSTER.POPUP.EDIT-CONFIG.JOB-MAX-ACTIVE-CONNECTIONS\"></td>\n            <td>\n                <input type=\"number\" class=\"form-control\" ng-model=\"model.engineConfig.jdbcMaxActiveConnections\">\n            </td>\n        </tr>\n        <tr ng-if=\"model.enableConnectionPoolCfg\">\n            <td class=\"edit-label\" translate=\"CLUSTER.POPUP.EDIT-CONFIG.JOB-MAX-IDLE-CONNECTIONS\"></td>\n            <td>\n                <input type=\"number\" class=\"form-control\"  ng-model=\"model.engineConfig.jdbcMaxIdleConnections\">\n            </td>\n        </tr>\n        <tr ng-if=\"model.enableConnectionPoolCfg\">\n            <td class=\"edit-label\" translate=\"CLUSTER.POPUP.EDIT-CONFIG.JOB-MAX-CHECKOUT-TIME\"></td>\n            <td>\n                <input type=\"number\" class=\"form-control\"  ng-model=\"model.engineConfig.jdbcMaxCheckoutTime\">\n            </td>\n        </tr>\n        <tr ng-if=\"model.enableConnectionPoolCfg\">\n            <td></td>\n            <td>\n                <p class=\"message\"><i class=\"glyphicon glyphicon-info-sign\"></i>&nbsp;\n            \t\t{{'CLUSTER.POPUP.EDIT-CONFIG.JOB-MAX-CHECKOUT-TIME-HELP' | translate}}\n                </p>\n            </td>\n        </tr>\n        <tr ng-if=\"model.enableConnectionPoolCfg\">\n            <td class=\"edit-label\" translate=\"CLUSTER.POPUP.EDIT-CONFIG.JOB-MAX-WAIT-TIME\"></td>\n            <td>\n                <input type=\"number\" class=\"form-control\"  ng-model=\"model.engineConfig.jdbcMaxWaitTime\">\n            </td>\n        </tr>\n        <tr ng-if=\"model.enableConnectionPoolCfg\">\n            <td></td>\n            <td>\n                <p class=\"message\"><i class=\"glyphicon glyphicon-info-sign\"></i>&nbsp;\n                \t{{'CLUSTER.POPUP.EDIT-CONFIG.JOB-MAX-WAIT-TIME-HELP' | translate}}\n                </p>\n            </td>\n        </tr>\n\n\n        <tr>\n            <td class=\"edit-label-top\">\n                <span ng-if=\"!model.enableJobExecutorCfg\" translate=\"CLUSTER.POPUP.EDIT-CONFIG.TITLE-MAIL-SERVER\"></span>\n                <h4 ng-if=\"model.enableJobExecutorCfg\" translate=\"CLUSTER.POPUP.EDIT-CONFIG.TITLE-MAIL-SERVER\"></h4>\n            </td>\n            <td>\n                <div ng-if=\"model.newConfig\">\n                    <input type=\"checkbox\" ng-model=\"model.enableMailServerCfg\">\n                    <span translate=\"CLUSTER.POPUP.EDIT-CONFIG.ENABLE-MAIL-SERVER\"></span>\n                    <p  ng-if=\"!model.enableMailServerCfg\" class=\"message\"><i class=\"glyphicon glyphicon-info-sign\"></i>&nbsp;\n                        {{'CLUSTER.POPUP.EDIT-CONFIG.ENABLE-MAIL-SERVER-INFO' | translate}}\n                    </p>\n                </div>\n            </td>\n        </tr>\n        <tr ng-if=\"model.enableMailServerCfg\">\n            <td class=\"edit-label\" translate=\"CLUSTER.POPUP.EDIT-CONFIG.MAIL-DEFAULT-FROM\"></td>\n            <td>\n                <input type=\"text\" class=\"form-control\" ng-model=\"model.coengineConfignfig.mailServerDefaultFrom\">\n            </td>\n        </tr>\n        <tr ng-if=\"model.enableMailServerCfg\">\n            <td class=\"edit-label\" translate=\"CLUSTER.POPUP.EDIT-CONFIG.MAIL-HOST\"></td>\n            <td>\n                <input type=\"text\" class=\"form-control\" ng-model=\"model.engineConfig.mailServerHost\">\n            </td>\n        </tr>\n        <tr ng-if=\"model.enableMailServerCfg\">\n            <td class=\"edit-label\" translate=\"CLUSTER.POPUP.EDIT-CONFIG.MAIL-PORT\"></td>\n            <td>\n                <input type=\"number\" class=\"form-control\" ng-model=\"model.engineConfig.mailServerPort\">\n            </td>\n        </tr>\n        <tr ng-if=\"model.enableMailServerCfg\">\n            <td class=\"edit-label\" translate=\"CLUSTER.POPUP.EDIT-CONFIG.MAIL-USERNAME\"></td>\n            <td>\n                <input type=\"text\" class=\"form-control\" ng-model=\"model.engineConfig.mailServerUsername\">\n            </td>\n        </tr>\n        <tr ng-if=\"model.enableMailServerCfg\">\n            <td class=\"edit-label\" translate=\"CLUSTER.POPUP.EDIT-CONFIG.MAIL-PASSWORD\"></td>\n            <td>\n                <input type=\"password\" class=\"form-control\"  ng-model=\"model.engineConfig.mailServerPassword\">\n            </td>\n        </tr>\n        <tr ng-if=\"model.enableMailServerCfg\">\n            <td class=\"edit-label\" translate=\"CLUSTER.POPUP.EDIT-CONFIG.MAIL-USE-SSL\"></td>\n            <td>\n                <input type=\"checkbox\" class=\"form-control\" ng-model=\"model.engineConfig.mailServerUseSsl\">\n            </td>\n        </tr>\n        <tr ng-if=\"model.enableMailServerCfg\">\n            <td class=\"edit-label\" translate=\"CLUSTER.POPUP.EDIT-CONFIG.MAIL-USE-TLS\"></td>\n            <td>\n                <input type=\"checkbox\" class=\"form-control\" ng-model=\"model.engineConfig.mailServerUseTls\">\n            </td>\n        </tr>\n        <tr ng-if=\"model.enableMailServerCfg\">\n            <td class=\"edit-label\" translate=\"CLUSTER.POPUP.EDIT-CONFIG.MAIL-JNDI-NAME\"></td>\n            <td>\n                <input type=\"text\" class=\"form-control\" ng-model=\"model.engineConfig.mailServerJndi\">\n            </td>\n        </tr>\n        <tr ng-if=\"model.enableMailServerCfg\">\n            <td></td>\n            <td>\n                <p class=\"message\"><i class=\"glyphicon glyphicon-info-sign\"></i>\n                    {{'CLUSTER.POPUP.EDIT-CONFIG.MAIL-JNDI-NAME-INFO' | translate}}\n                </p>\n            </td>\n        </tr>\n\n    </table>\n\n\n</div>\n\n<div class=\"modal-footer-wrapper\">\n    <div class=\"modal-footer\">\n        <div class=\"pull-right\">\n            <button type=\"button\" class=\"btn btn-sm btn-default\" ng-click=\"cancel()\" ng-disabled=\"status.loading\"\n            \ttranslate=\"GENERAL.ACTION.CANCEL\">\n            </button>\n            <button type=\"button\" class=\"btn btn-sm btn-default\" ng-click=\"ok()\"\n                    ng-disabled=\"status.loading\">\n                {{model.newConfig &amp;&amp; ('CLUSTER.POPUP.EDIT-CONFIG.ACTION-CREATE-CONFIGURATION' | translate) || ('CLUSTER.POPUP.EDIT-CONFIG.ACTION-UPDATE-CONFIGURATION' | translate)}}\n            </button>\n        </div>\n        <loading-indicator></loading-indicator>\n    </div>\n</div>\n"
  },
  {
    "path": "flowable-ui-web/admin/views/engine-edit-endpoint-popup.html",
    "content": "<div class=\"modal-header-wrapper\">\n\t<div class=\"modal-header\">\n\t\t<div class=\"pull-right\">\n            <a class=\"action\" ng-click=\"cancel()\" ng-show=\"!status.loading\">&times; Cancel and close</a>\n        </div>\n\t\t<h2>Edit endpoint configuration</h2>\n\t</div>\n</div>\n<div class=\"modal-body\">\n\t<table class=\"edit-table\">\n\t\t<tr>\n\t\t\t<td class=\"edit-label\" translate=\"CLUSTER.POPUP.EDIT-ENDPOINT.ENDPOINT-NAME\"></td>\n\t\t\t<td>\n\t\t\t\t<input type=\"text\" class=\"form-control\" id=\"name\" ng-model=\"model.server.name\">\n\t\t\t</td>\n\t\t</tr>\n\t\t<tr>\n\t\t\t<td class=\"edit-label\" translate=\"CLUSTER.POPUP.EDIT-ENDPOINT.ENDPOINT-DESCRIPTION\"></td>\n\t\t\t<td>\n                 <input type=\"text\" class=\"form-control\" id=\"description\"\n                 \tng-model=\"model.server.description\">\n\t\t\t</td>\n\t\t</tr>\n\t\t<tr>\n\t\t\t<td class=\"edit-label\" translate=\"CLUSTER.POPUP.EDIT-ENDPOINT.ENDPOINT-ADDRESS\"></td>\n\t\t\t<td>\n                  <input type=\"text\" class=\"form-control\" id=\"serverAddress\"\n                                       ng-model=\"model.server.serverAddress\">\n\t\t\t</td>\n\n\t\t</tr>\n\t\t<tr>\n\t\t\t<td class=\"edit-label\" translate=\"CLUSTER.POPUP.EDIT-ENDPOINT.ENDPOINT-PORT\"></td>\n\t\t\t<td>\n                <input type=\"text\" class=\"form-control\" id=\"serverPort\"\n                   ng-model=\"model.server.serverPort\">\n\t\t\t</td>\n\t\t</tr>\n\t\t<tr>\n\t\t\t<td class=\"edit-label\" translate=\"CLUSTER.POPUP.EDIT-ENDPOINT.ENDPOINT-CONTEXT-ROOT\"></td>\n\t\t\t<td>\n               <input type=\"text\" class=\"form-control\" id=\"contextRoot\"\n                                       ng-model=\"model.server.contextRoot\">\n\t\t\t</td>\n\t\t</tr>\n\t\t<tr>\n\t\t\t<td class=\"edit-label\" translate=\"CLUSTER.POPUP.EDIT-ENDPOINT.ENDPOINT-REST-ROOT\"></td>\n\t\t\t<td>\n              <input type=\"text\" class=\"form-control\" id=\"restRoot\"\n                                        ng-model=\"model.server.restRoot\">\n\t\t\t</td>\n\t\t</tr>\n\t\t<tr>\n\t\t\t<td class=\"edit-label\" translate=\"CLUSTER.POPUP.EDIT-ENDPOINT.ENDPOINT-USERNAME\"></td>\n\t\t\t<td>\n              <input type=\"text\" class=\"form-control\" id=\"userName\"\n                                        ng-model=\"model.server.userName\">\n\t\t\t</td>\n\t\t</tr>\n\t\t<tr>\n\t\t\t<td class=\"edit-label\" translate=\"CLUSTER.POPUP.EDIT-ENDPOINT.ENDPOINT-PASSWORD\"></td>\n\t\t\t<td>\n              <input ng-if=\"model.server.id\" type=\"password\" class=\"form-control\" id=\"password\"\n                                        ng-model=\"model.server.password\" placeholder=\"{{'CLUSTER.POPUP.EDIT-ENDPOINT.ENDPOINT-PASSWORD-HELP' | translate}}\">\n              <input ng-if=\"!model.server.id\" type=\"password\" class=\"form-control\" id=\"password\" ng-model=\"model.server.password\">\n\t\t\t</td>\n\t\t</tr>\n        <tr>\n            <td class=\"edit-label\" translate=\"CLUSTER.POPUP.EDIT-ENDPOINT.ENDPOINT-URL-PREVIEW\"></td>\n            <td ng-if=\"model.server.contextRoot && model.server.contextRoot.length > 0\">\n                {{model.server.serverAddress}}:{{model.server.serverPort}}/{{model.server.contextRoot}}/{{model.server.restRoot}}\n            </td>\n            <td ng-if=\"!model.server.contextRoot || model.server.contextRoot.length == 0\">\n                {{model.server.serverAddress}}:{{model.server.serverPort}}/{{model.server.restRoot}}\n            </td>\n        </tr>\n\t</table>\n</div>\n\n<div class=\"modal-footer-wrapper\">\n\t<div class=\"modal-footer\">\n        <div ng-if=\"model.error\" class=\"pull-left error-text\">\n            <div ng-switch=\"model.error.statusCode\">\n                 <span ng-switch-when=\"401\">\n                    {{'CLUSTER.POPUP.EDIT-ENDPOINT.ERROR-401' | translate}}\n                </span>\n                <span ng-switch-when=\"403\">\n                    {{'CLUSTER.POPUP.EDIT-ENDPOINT.ERROR-403' | translate}}\n                </span>\n                <span ng-switch-when=\"500\">\n                    {{'CLUSTER.POPUP.EDIT-ENDPOINT.ERROR-500' | translate}}\n                </span>\n                <span ng-switch-default>\n                    {{model.error.statusCode}} : {{model.error.message}}\n                </span>\n            </div>\n        </div>\n\t\t<div class=\"pull-right\">\n\t       <button type=\"button\" class=\"btn btn-sm btn-default\" ng-click=\"cancel()\" ng-disabled=\"status.loading\"\n\t       \ttranslate=\"GENERAL.ACTION.CANCEL\">\n\t       </button>\n\t       <button type=\"button\" class=\"btn btn-sm btn-default\" ng-click=\"ok()\" ng-disabled=\"status.loading || !model.server.name\"\n\t       \ttranslate=\"CLUSTER.POPUP.EDIT-ENDPOINT.ACTION-CONFIRM\">\n\t       </button>\n\t\t</div>\n        <loading-indicator></loading-indicator>\n</div>\n</div>\n"
  },
  {
    "path": "flowable-ui-web/admin/views/engine.html",
    "content": "<div class=\"container no-top-gutter\">\n    <div class=\"row\">\n        <div class=\"col-md-9 component\">\n\n            <div class=\"title process\">\n                <h2 translate=\"CLUSTER.TITLE.PROCESS-ENDPOINT\"></h2>\n            </div>\n            <p class=\"message\"><i class=\"glyphicon glyphicon-info-sign\"></i>\n                {{'CLUSTER.ENDPOINT-HELP' | translate}}\n            </p>\n\n            <div class=\"property-wrapper\">\n                <table>\n                    <tr class=\"property\">\n                        <td class=\"property-name\" translate=\"CLUSTER.ENDPOINT-NAME\"></td>\n                        <td>{{activeServers['process'].name | empty}}</td>\n                        <td class=\"property-name\" translate=\"CLUSTER.ENDPOINT-DESCRIPTION\"></td>\n                        <td>{{activeServers['process'].description | empty}}</td>\n                    </tr>\n                    <tr class=\"property\">\n                        <td class=\"property-name\" translate=\"CLUSTER.ENDPOINT-ADDRESS\"></td>\n                        <td>{{activeServers['process'].serverAddress | empty}}</td>\n                        <td class=\"property-name\" translate=\"CLUSTER.ENDPOINT-PORT\"></td>\n                        <td>{{activeServers['process'].serverPort | empty}}</td>\n                    </tr>\n                    <tr class=\"property\">\n                        <td class=\"property-name\" translate=\"CLUSTER.ENDPOINT-CONTEXT-ROOT\"></td>\n                        <td>{{activeServers['process'].contextRoot | empty}}</td>\n                        <td class=\"property-name\" translate=\"CLUSTER.ENDPOINT-REST-ROOT\"></td>\n                        <td>{{activeServers['process'].restRoot | empty}}</td>\n                    </tr>\n                    <tr class=\"property\">\n                        <td class=\"property-name\" translate=\"CLUSTER.ENDPOINT-USERNAME\"></td>\n                        <td>{{activeServers['process'].userName | empty}}</td>\n                    </tr>\n                </table>\n            </div>\n\n        </div>\n\n        <div class=\"col-md-3\">\n            <div class=\"component tip-left\">\n                <div class=\"title process\">\n                    <h2 translate=\"GENERAL.TITLE.ACTIONS\"></h2>\n                </div>\n                <div class=\"seperator\"></div>\n                <ul class=\"list-group\">\n                    <li>\n                        <button type=\"button\" class=\"btn btn-sm btn-default\" ng-click=\"editProcessEndpointConfig()\">\n                            <i class=\"glyphicon glyphicon-pencil\"></i>{{'CLUSTER.ACTION.EDIT-ENDPOINT' | translate}}\n                        </button>\n                    </li>\n                    <li>\n                        <button type=\"button\" class=\"btn btn-sm btn-default\" ng-click=\"checkProcessEndpointConfig()\">\n                            <i class=\"glyphicon glyphicon-ok\"></i>{{'CLUSTER.ACTION.CHECK-ENDPOINT' | translate}}\n                        </button>\n                    </li>\n                </ul>\n            </div>\n        </div>\n        \n        <div class=\"col-md-9 component\">\n            <div class=\"title cmmn\">\n                <h2 translate=\"CLUSTER.TITLE.CMMN-ENDPOINT\"></h2>\n            </div>\n            <p class=\"message\"><i class=\"glyphicon glyphicon-info-sign\"></i>\n                {{'CLUSTER.ENDPOINT-HELP' | translate}}\n            </p>\n\n            <div class=\"property-wrapper\">\n                <table>\n                    <tr class=\"property\">\n                        <td class=\"property-name\" translate=\"CLUSTER.ENDPOINT-NAME\"></td>\n                        <td>{{activeServers['cmmn'].name | empty}}</td>\n                        <td class=\"property-name\" translate=\"CLUSTER.ENDPOINT-DESCRIPTION\"></td>\n                        <td>{{activeServers['cmmn'].description | empty}}</td>\n                    </tr>\n                    <tr class=\"property\">\n                        <td class=\"property-name\" translate=\"CLUSTER.ENDPOINT-ADDRESS\"></td>\n                        <td>{{activeServers['cmmn'].serverAddress | empty}}</td>\n                        <td class=\"property-name\" translate=\"CLUSTER.ENDPOINT-PORT\"></td>\n                        <td>{{activeServers['cmmn'].serverPort | empty}}</td>\n                    </tr>\n                    <tr class=\"property\">\n                        <td class=\"property-name\" translate=\"CLUSTER.ENDPOINT-CONTEXT-ROOT\"></td>\n                        <td>{{activeServers['cmmn'].contextRoot | empty}}</td>\n                        <td class=\"property-name\" translate=\"CLUSTER.ENDPOINT-REST-ROOT\"></td>\n                        <td>{{activeServers['cmmn'].restRoot | empty}}</td>\n                    </tr>\n                    <tr class=\"property\">\n                        <td class=\"property-name\" translate=\"CLUSTER.ENDPOINT-USERNAME\"></td>\n                        <td>{{activeServers['cmmn'].userName | empty}}</td>\n                    </tr>\n                </table>\n            </div>\n        </div>\n        \n        <div class=\"col-md-3\">\n            <div class=\"component tip-left\">\n                <div class=\"title cmmn\">\n                    <h2 translate=\"GENERAL.TITLE.ACTIONS\"></h2>\n                </div>\n                <div class=\"seperator\"></div>\n                <ul class=\"list-group\">\n                    <li>\n                        <button type=\"button\" class=\"btn btn-sm btn-default\" ng-click=\"editCmmnEndpointConfig()\">\n                            <i class=\"glyphicon glyphicon-pencil\"></i>{{'CLUSTER.ACTION.EDIT-ENDPOINT' | translate}}\n                        </button>\n                    </li>\n                    <li>\n                        <button type=\"button\" class=\"btn btn-sm btn-default\" ng-click=\"checkCmmnEndpointConfig()\">\n                            <i class=\"glyphicon glyphicon-ok\"></i>{{'CLUSTER.ACTION.CHECK-ENDPOINT' | translate}}\n                        </button>\n                    </li>\n                </ul>\n            </div>\n        </div>\n        \n        <div class=\"col-md-9 component\">\n            <div class=\"title app\">\n                <h2 translate=\"CLUSTER.TITLE.APP-ENDPOINT\"></h2>\n            </div>\n            <p class=\"message\"><i class=\"glyphicon glyphicon-info-sign\"></i>\n                {{'CLUSTER.ENDPOINT-HELP' | translate}}\n            </p>\n\n            <div class=\"property-wrapper\">\n                <table>\n                    <tr class=\"property\">\n                        <td class=\"property-name\" translate=\"CLUSTER.ENDPOINT-NAME\"></td>\n                        <td>{{activeServers['app'].name | empty}}</td>\n                        <td class=\"property-name\" translate=\"CLUSTER.ENDPOINT-DESCRIPTION\"></td>\n                        <td>{{activeServers['app'].description | empty}}</td>\n                    </tr>\n                    <tr class=\"property\">\n                        <td class=\"property-name\" translate=\"CLUSTER.ENDPOINT-ADDRESS\"></td>\n                        <td>{{activeServers['app'].serverAddress | empty}}</td>\n                        <td class=\"property-name\" translate=\"CLUSTER.ENDPOINT-PORT\"></td>\n                        <td>{{activeServers['app'].serverPort | empty}}</td>\n                    </tr>\n                    <tr class=\"property\">\n                        <td class=\"property-name\" translate=\"CLUSTER.ENDPOINT-CONTEXT-ROOT\"></td>\n                        <td>{{activeServers['app'].contextRoot | empty}}</td>\n                        <td class=\"property-name\" translate=\"CLUSTER.ENDPOINT-REST-ROOT\"></td>\n                        <td>{{activeServers['app'].restRoot | empty}}</td>\n                    </tr>\n                    <tr class=\"property\">\n                        <td class=\"property-name\" translate=\"CLUSTER.ENDPOINT-USERNAME\"></td>\n                        <td>{{activeServers['app'].userName | empty}}</td>\n                    </tr>\n                </table>\n            </div>\n        </div>\n        \n        <div class=\"col-md-3\">\n            <div class=\"component tip-left\">\n                <div class=\"title app\">\n                    <h2 translate=\"GENERAL.TITLE.ACTIONS\"></h2>\n                </div>\n                <div class=\"seperator\"></div>\n                <ul class=\"list-group\">\n                    <li>\n                        <button type=\"button\" class=\"btn btn-sm btn-default\" ng-click=\"editAppEndpointConfig()\">\n                            <i class=\"glyphicon glyphicon-pencil\"></i>{{'CLUSTER.ACTION.EDIT-ENDPOINT' | translate}}\n                        </button>\n                    </li>\n                    <li>\n                        <button type=\"button\" class=\"btn btn-sm btn-default\" ng-click=\"checkAppEndpointConfig()\">\n                            <i class=\"glyphicon glyphicon-ok\"></i>{{'CLUSTER.ACTION.CHECK-ENDPOINT' | translate}}\n                        </button>\n                    </li>\n                </ul>\n            </div>\n        </div>\n\n        <div class=\"col-md-9 component\">\n            <div class=\"title form\">\n                <h2 translate=\"CLUSTER.TITLE.FORM-ENDPOINT\"></h2>\n            </div>\n            <p class=\"message\"><i class=\"glyphicon glyphicon-info-sign\"></i>\n                {{'CLUSTER.ENDPOINT-HELP' | translate}}\n            </p>\n\n            <div class=\"property-wrapper\">\n                <table>\n                    <tr class=\"property\">\n                        <td class=\"property-name\" translate=\"CLUSTER.ENDPOINT-NAME\"></td>\n                        <td>{{activeServers['form'].name | empty}}</td>\n                        <td class=\"property-name\" translate=\"CLUSTER.ENDPOINT-DESCRIPTION\"></td>\n                        <td>{{activeServers['form'].description | empty}}</td>\n                    </tr>\n                    <tr class=\"property\">\n                        <td class=\"property-name\" translate=\"CLUSTER.ENDPOINT-ADDRESS\"></td>\n                        <td>{{activeServers['form'].serverAddress | empty}}</td>\n                        <td class=\"property-name\" translate=\"CLUSTER.ENDPOINT-PORT\"></td>\n                        <td>{{activeServers['form'].serverPort | empty}}</td>\n                    </tr>\n                    <tr class=\"property\">\n                        <td class=\"property-name\" translate=\"CLUSTER.ENDPOINT-CONTEXT-ROOT\"></td>\n                        <td>{{activeServers['form'].contextRoot | empty}}</td>\n                        <td class=\"property-name\" translate=\"CLUSTER.ENDPOINT-REST-ROOT\"></td>\n                        <td>{{activeServers['form'].restRoot | empty}}</td>\n                    </tr>\n                    <tr class=\"property\">\n                        <td class=\"property-name\" translate=\"CLUSTER.ENDPOINT-USERNAME\"></td>\n                        <td>{{activeServers['form'].userName | empty}}</td>\n                    </tr>\n                </table>\n            </div>\n        </div>\n\n        <div class=\"col-md-3\">\n            <div class=\"component tip-left\">\n                <div class=\"title form\">\n                    <h2 translate=\"GENERAL.TITLE.ACTIONS\"></h2>\n                </div>\n                <div class=\"seperator\"></div>\n                <ul class=\"list-group\">\n                    <li>\n                        <button type=\"button\" class=\"btn btn-sm btn-default\" ng-click=\"editFormEndpointConfig()\">\n                            <i class=\"glyphicon glyphicon-pencil\"></i>{{'CLUSTER.ACTION.EDIT-ENDPOINT' | translate}}\n                        </button>\n                    </li>\n                    <li>\n                        <button type=\"button\" class=\"btn btn-sm btn-default\" ng-click=\"checkFormEndpointConfig()\">\n                            <i class=\"glyphicon glyphicon-ok\"></i>{{'CLUSTER.ACTION.CHECK-ENDPOINT' | translate}}\n                        </button>\n                    </li>\n                </ul>\n            </div>\n        </div>\n\n\n        <div class=\"col-md-9 component\">\n\n            <div class=\"title dmn\">\n                <h2 translate=\"CLUSTER.TITLE.DMN-ENDPOINT\"></h2>\n            </div>\n            <p class=\"message\"><i class=\"glyphicon glyphicon-info-sign\"></i>\n                {{'CLUSTER.ENDPOINT-HELP' | translate}}\n            </p>\n\n            <div class=\"property-wrapper\">\n                <table>\n                    <tr class=\"property\">\n                        <td class=\"property-name\" translate=\"CLUSTER.ENDPOINT-NAME\"></td>\n                        <td>{{activeServers['dmn'].name | empty}}</td>\n                        <td class=\"property-name\" translate=\"CLUSTER.ENDPOINT-DESCRIPTION\"></td>\n                        <td>{{activeServers['dmn'].description | empty}}</td>\n                    </tr>\n                    <tr class=\"property\">\n                        <td class=\"property-name\" translate=\"CLUSTER.ENDPOINT-ADDRESS\"></td>\n                        <td>{{activeServers['dmn'].serverAddress | empty}}</td>\n                        <td class=\"property-name\" translate=\"CLUSTER.ENDPOINT-PORT\"></td>\n                        <td>{{activeServers['dmn'].serverPort | empty}}</td>\n                    </tr>\n                    <tr class=\"property\">\n                        <td class=\"property-name\" translate=\"CLUSTER.ENDPOINT-CONTEXT-ROOT\"></td>\n                        <td>{{activeServers['dmn'].contextRoot | empty}}</td>\n                        <td class=\"property-name\" translate=\"CLUSTER.ENDPOINT-REST-ROOT\"></td>\n                        <td>{{activeServers['dmn'].restRoot | empty}}</td>\n                    </tr>\n                    <tr class=\"property\">\n                        <td class=\"property-name\" translate=\"CLUSTER.ENDPOINT-USERNAME\"></td>\n                        <td>{{activeServers['dmn'].userName | empty}}</td>\n                    </tr>\n                </table>\n            </div>\n\n        </div>\n\n        <div class=\"col-md-3\">\n            <div class=\"component tip-left\">\n                <div class=\"title dmn\">\n                    <h2 translate=\"GENERAL.TITLE.ACTIONS\"></h2>\n                </div>\n                <div class=\"seperator\"></div>\n                <ul class=\"list-group\">\n                    <li>\n                        <button type=\"button\" class=\"btn btn-sm btn-default\" ng-click=\"editDmnEndpointConfig()\">\n                            <i class=\"glyphicon glyphicon-pencil\"></i>{{'CLUSTER.ACTION.EDIT-ENDPOINT' | translate}}\n                        </button>\n                    </li>\n                    <li>\n                        <button type=\"button\" class=\"btn btn-sm btn-default\" ng-click=\"checkDmnEndpointConfig()\">\n                            <i class=\"glyphicon glyphicon-ok\"></i>{{'CLUSTER.ACTION.CHECK-ENDPOINT' | translate}}\n                        </button>\n                    </li>\n                </ul>\n            </div>\n        </div>\n\n        <div class=\"col-md-9 component\">\n            <div class=\"title content\">\n                <h2 translate=\"CLUSTER.TITLE.CONTENT-ENDPOINT\"></h2>\n            </div>\n            <p class=\"message\"><i class=\"glyphicon glyphicon-info-sign\"></i>\n                {{'CLUSTER.ENDPOINT-HELP' | translate}}\n            </p>\n\n            <div class=\"property-wrapper\">\n                <table>\n                    <tr class=\"property\">\n                        <td class=\"property-name\" translate=\"CLUSTER.ENDPOINT-NAME\"></td>\n                        <td>{{activeServers['content'].name | empty}}</td>\n                        <td class=\"property-name\" translate=\"CLUSTER.ENDPOINT-DESCRIPTION\"></td>\n                        <td>{{activeServers['content'].description | empty}}</td>\n                    </tr>\n                    <tr class=\"property\">\n                        <td class=\"property-name\" translate=\"CLUSTER.ENDPOINT-ADDRESS\"></td>\n                        <td>{{activeServers['content'].serverAddress | empty}}</td>\n                        <td class=\"property-name\" translate=\"CLUSTER.ENDPOINT-PORT\"></td>\n                        <td>{{activeServers['content'].serverPort | empty}}</td>\n                    </tr>\n                    <tr class=\"property\">\n                        <td class=\"property-name\" translate=\"CLUSTER.ENDPOINT-CONTEXT-ROOT\"></td>\n                        <td>{{activeServers['content'].contextRoot | empty}}</td>\n                        <td class=\"property-name\" translate=\"CLUSTER.ENDPOINT-REST-ROOT\"></td>\n                        <td>{{activeServers['content'].restRoot | empty}}</td>\n                    </tr>\n                    <tr class=\"property\">\n                        <td class=\"property-name\" translate=\"CLUSTER.ENDPOINT-USERNAME\"></td>\n                        <td>{{activeServers['content'].userName | empty}}</td>\n                    </tr>\n                </table>\n            </div>\n        </div>\n\n        <div class=\"col-md-3\">\n            <div class=\"component tip-left\">\n                <div class=\"title content\">\n                    <h2 translate=\"GENERAL.TITLE.ACTIONS\"></h2>\n                </div>\n                <div class=\"seperator\"></div>\n                <ul class=\"list-group\">\n                    <li>\n                        <button type=\"button\" class=\"btn btn-sm btn-default\" ng-click=\"editContentEndpointConfig()\">\n                            <i class=\"glyphicon glyphicon-pencil\"></i>{{'CLUSTER.ACTION.EDIT-ENDPOINT' | translate}}\n                        </button>\n                    </li>\n                    <li>\n                        <button type=\"button\" class=\"btn btn-sm btn-default\" ng-click=\"checkContentEndpointConfig()\">\n                            <i class=\"glyphicon glyphicon-ok\"></i>{{'CLUSTER.ACTION.CHECK-ENDPOINT' | translate}}\n                        </button>\n                    </li>\n                </ul>\n            </div>\n        </div>\n\n\n    </div>\n</div>\n"
  },
  {
    "path": "flowable-ui-web/admin/views/event-subscription.html",
    "content": "\n<div class=\"container\" id=\"detail-container\">\n\t<div class=\"row\">\n\t\t<div class=\"col-md-9\">\n\t\t\t<div class=\"component\" ng-show=\"eventSubscription\">\n\t\t\t\t<div class=\"title\">\n\t\t\t\t\t<div class=\"pull-right\">\n\t\t\t\t\t\t<a ng-click=\"returnToList()\" class=\"action\">&larr; {{'GENERAL.ACTION.RETURN-TO-LIST' | translate}}</a>\n\t\t\t\t\t</div>\n\t\t\t\t\t<h2>{{'EVENT-SUBSCRIPTION.TITLE.MAIN' | translate:eventSubscription}}</h2>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"property-wrapper\">\n\t\t\t\t\t<table>\n\t\t\t\t\t\t<tr class=\"property\">\n\t\t\t\t\t\t\t<td class=\"property-name\" translate=\"EVENT-SUBSCRIPTION.ID\"></td>\n\t\t\t\t\t\t\t<td>{{eventSubscription.id}}</td>\n\t\t\t\t\t\t\t<td class=\"property-name\"><span class=\"glyphicon glyphicon-time\"></span> {{'EVENT-SUBSCRIPTION.CREATE-DATE' | translate}}</td>\n\t\t\t\t\t\t\t<td>{{eventSubscription.created | dateformat}}</td>\n\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t<tr class=\"property\">\n\t\t\t\t\t\t\t<td class=\"property-name\" translate=\"EVENT-SUBSCRIPTION.EVENT-TYPE\"></td>\n\t\t\t\t\t\t\t<td>{{eventSubscription.eventType}}</td>\n\t\t\t\t\t\t\t<td class=\"property-name\" translate=\"EVENT-SUBSCRIPTION.EVENT-NAME\"></td>\n\t\t\t\t\t\t\t<td>{{eventSubscription.eventName}}</td>\n\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t<tr class=\"property\" ng-if=\"eventSubscription.processInstanceId\">\n\t\t\t\t\t\t\t<td class=\"property-name\"></span> {{'EVENT-SUBSCRIPTION.PROCESS-INSTANCE' | translate}}</td>\n\t\t\t\t\t\t\t<td><a ng-click=\"openProcessInstance(eventSubscription.processInstanceId)\"><i class=\"glyphicon glyphicon-zoom-in\"></i> {{eventSubscription.processInstanceId | empty}}</a></td>\n\t\t\t\t\t\t\t<td class=\"property-name\" translate=\"EVENT-SUBSCRIPTION.EXECUTION-ID\"></td>\n\t\t\t\t\t\t\t<td>{{eventSubscription.executionId}}</td>\n\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t<tr class=\"property\">\n\t\t\t\t\t\t\t<td class=\"property-name\" translate=\"EVENT-SUBSCRIPTION.ACTIVITY-ID\"></td>\n\t\t\t\t\t\t\t<td>{{eventSubscription.activityId}}</td>\n\t\t\t\t\t\t\t<td class=\"property-name\" ng-if=\"eventSubscription.processDefinitionId\"></span> {{'EVENT-SUBSCRIPTION.PROCESS-DEFINITION' | translate}}</td>\n\t\t\t\t\t\t\t<td ng-if=\"eventSubscription.processDefinitionId\"><a ng-click=\"openProcessDefinition(eventSubscription.processDefinitionId)\"><i class=\"glyphicon glyphicon-zoom-in\"></i> {{eventSubscription.processDefinitionId | empty}}</a></td>\n\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t<tr class=\"property\">\n                            <td class=\"property-name\" translate=\"EVENT-SUBSCRIPTION.TENANT-ID\"></td>\n                            <td>{{eventSubscription.tenantId}}</td>\n                        </tr>\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<div class=\"col-md-3\">\n\t\t\t<div class=\"component tip-left\">\n\t\t\t\t<div class=\"title\">\n\t\t\t\t\t<h2 translate=\"GENERAL.TITLE.ACTIONS\"></h2>\n\t\t\t\t</div>\n\t\t\t\t<ul class=\"list-group\">\n\t\t\t\t\t  <li>\n\t\t\t\t\t    <button type=\"button\" class=\"btn btn-sm btn-default\" ng-click=\"triggerEvent()\">\n\t\t\t\t\t\t\t<i class=\"glyphicon glyphicon-play\"></i> {{'EVENT-SUBSCRIPTION.ACTIONS.TRIGGER' | translate}}\n\t\t\t\t\t    </button>\n\t\t\t\t\t  </li>\n\t\t\t\t</ul>\n\t\t\t</div>\n\t\t</div>\n\t</div>\n</div>\n"
  },
  {
    "path": "flowable-ui-web/admin/views/event-subscriptions.html",
    "content": "<!-- LIST PAGE -->\n<div class=\"container\">\n    <div class=\"row\">\n        <div class=\"col-md-8\">\n            <div class=\"component\">\n                <div class=\"title\">\n                    <div class=\"btn-group btn-group-sm pull-right\">\n                        <div class=\"btn-group btn-group-sm\">\n                            <button type=\"button\" class=\"btn btn-default dropdown-toggle\" data-toggle=\"dropdown\"\n                                    translate=\"GENERAL.ACTION.SHOW-RESULTS\" translate-value-size=\"{{'GENERAL.RESULT-SIZES.' + filter.resultSize | translate}}\">\n                                &nbsp;\n                                <span class=\"caret\"></span>\n                            </button>\n                            <ul class=\"dropdown-menu\">\n                            \t<li ng-repeat=\"resultSize in config.filter.resultSizes\"><a href=\"\" ng-click=\"filter.setResultSize(resultSize)\">{{'GENERAL.RESULT-SIZES.' + resultSize.toString() | translate}}</a></li>\n                            </ul>\n                        </div>\n                        <button type=\"button\" class=\"btn btn-default\" ng-click=\"filter.toggleOrder()\">\n                        \t<i class=\"glyphicon\" ng-class=\"{'glyphicon-sort-by-attributes': filter.order == 'asc', 'glyphicon-sort-by-attributes-alt': filter.order == 'desc'}\"></i>\n                        </button>\n                    </div>\n                    <div class=\"btn-group btn-group-sm pull-right\">\n                    \t<button type=\"button\" class=\"btn btn-default dropdown-toggle\" data-toggle=\"dropdown\"\n                                translate=\"GENERAL.ACTION.SORT-BY\" translate-value-sort=\"{{filter.sort.name | translate}}\">\n                            &nbsp;\n                            <span class=\"caret\"></span>\n                        </button>\n                    \t<ul class=\"dropdown-menu\">\n                           <li ng-repeat=\"sort in filter.sortObjects\"><a href=\"\" ng-click=\"filter.setSort(sort)\">{{sort.name | translate}}</a></li>\n                        </ul>\n                    </div>\n                    <div class=\"btn-group btn-group-sm pull-right\">\n                        <a class=\"btn btn-default\" role=\"button\"\n                           title=\"{{'GENERAL.ACTION.REFRESH-LIST' | translate}}\"\n                           ng-click=\"filter.refresh();\">\n                            <i class=\"glyphicon glyphicon-refresh\"></i>\n                        </a>\n                    </div>\n                    <div class=\"pull-right loading\" ng-show=\"filter.loading\">\n                    \t<i class=\"glyphicon glyphicon-refresh\"></i>\n                    </div>\n\n                    <h2 translate=\"EVENT-SUBSCRIPTIONS.TITLE\"></h2>\n                </div>\n\n                <div class=\"grid-wrapper\" id=\"eventSubscriptions\">\n                    <div class=\"grid-message\" ng-if=\"eventSubscriptionData.size > 0\">\n                         <span>{{'EVENT-SUBSCRIPTIONS.LIST-MESSAGE' | translate:eventSubscriptions}}</span>\n                    </div>\n                     <div class=\"grid-message\" ng-if=\"eventSubscriptionData.size == 0\">\n                        <span>{{'EVENT-SUBSCRIPTIONS.LIST-MESSAGE-EMPTY' | translate}}</span>\n                    </div>\n                    <div ng-grid=\"gridEventSubscriptions\" class=\"gridStyle\" ng-if=\"gridEventSubscriptions && eventSubscriptionData.data\"/>\n                </div>\n            </div>\n        </div>\n\n\t\t<!-- Event subscription filters -->\n\t\t<div class=\"col-md-4\">\n            <div class=\"component tip-left\">\n                <div class=\"title\">\n                    <div class=\"btn-group btn-group-sm pull-right\" ng-show=\"filter.supportedProperties.length > 0\">\n                        <button type=\"button\" class=\"btn btn-default\" data-toggle=\"dropdown\">\n                            <i class=\"glyphicon glyphicon-plus\"></i>\n                        </button>\n                        <ul class=\"dropdown-menu\">\n                            <li ng-repeat=\"prop in filter.supportedProperties\"><a href=\"\" ng-click=\"filter.addProperty(prop)\">{{prop.name | translate}}</a></li>\n                        </ul>\n                    </div>\n                    <div class=\"pull-right\">\n                        <a class=\"action\" ng-click=\"filter.clear()\" translate=\"GENERAL.ACTION.CLEAR-FILTERS\"></a>\n                    </div>\n                    <h2 translate=\"GENERAL.TITLE.FILTERS\"></h2>\n                </div>\n\t            <div class=\"section\">\n                    <div class=\"subtitle\"><label for=\"filter-processdefinition\" translate=\"EVENT-SUBSCRIPTIONS.FILTER.PROCESS-DEFINITION\"></label> </div>\n                    <div>\n                        <select ui-select2\n                                data-placeholder=\"{{'EVENT-SUBSCRIPTIONS.FILTER.ALL-PROCESS-DEFINITIONS' | translate}}\"\n                         \t\tng-model=\"filter.processDefinition\"\n                         \t\tng-change=\"processDefinitionFilterChanged()\"\n                         \t\tstyle=\"min-width:250px\">\n                            <option value=\"\"></option>\n                            <option value=\"-1\">{{'EVENT-SUBSCRIPTIONS.FILTER.ALL-PROCESS-DEFINITIONS' | translate}}</option>\n                         \t<option ng-title=\"123\" ng-repeat=\"processDefinition in processDefinitionsCache.data\" value=\"{{processDefinition.id}}\">{{processDefinition.name ? processDefinition.name : processDefinition.key}} (v{{processDefinition.version}})</option>\n                         </select>\n                    </div>\n                </div>\n                <div class=\"section\" ng-if=\"filter.properties.processInstanceId !== undefined\">\n                    <div class=\"subtitle\"><label for=\"filter-processInstanceId\" translate=\"EVENT-SUBSCRIPTIONS.FILTER.PROCESS-INSTANCE-ID\"></label> </div>\n                    <div class=\"input-group input-group-sm\">\n                        <input id=\"filter-processInstanceId\" type=\"text\" class=\"form-control\" value=\"\" ng-model=\"filter.properties.processInstanceId\" ng-change=\"filter.refreshDelayed()\">\n                    </div>\n                </div>\n                <div class=\"section\" ng-if=\"filter.properties.tenantIdLike !== undefined\">\n                    <div class=\"subtitle\"><label for=\"filter-tenantId\" translate=\"EVENT-SUBSCRIPTIONS.FILTER.TENANT-ID\"></label> </div>\n                    <div class=\"input-group input-group-sm\">\n                        <input id=\"filter-tenantId\" type=\"text\" class=\"form-control\" value=\"\" ng-model=\"filter.properties.tenantIdLike\" ng-change=\"filter.refreshDelayed()\">\n                    </div>\n                </div>\n                <div class=\"section\" ng-if=\"filter.properties.createdBefore !== undefined\">\n                  <div class=\"subtitle\"><label for=\"filter-createdBefore\" translate=\"EVENT-SUBSCRIPTIONS.FILTER.CREATED-BEFORE\"></label> </div>\n               \t  <div class=\"input-group input-group-sm\">\n               \t  \t<span class=\"input-group-addon\"><span class=\"glyphicon glyphicon-time\"></span></span>\n                      <input id=\"filter-createdBefore\" type=\"text\" class=\"form-control\"\n                             ng-model=\"filter.properties.createdBefore\"\n                             ng-change=\"filter.refreshDelayed()\"\n                             datepicker-popup=\"yyyy/MM/dd\"\n                             is-open=\"createdBeforePicker.isOpen\"\n                             ng-click=\"createdBeforePicker.isOpen=true\"/>\n\t              </div>\n\t            </div>\n                <div class=\"section\" ng-if=\"filter.properties.createdAfter !== undefined\">\n\t              <div class=\"subtitle\"><label for=\"filter-createdAfter\" translate=\"EVENT-SUBSCRIPTIONS.FILTER.CREATED-AFTER\"></label> </div>\n               \t  <div class=\"input-group input-group-sm\">\n               \t  \t<span class=\"input-group-addon\"><span class=\"glyphicon glyphicon-time\"></span></span>\n\t              \t<input id=\"filter-createdAfter\" type=\"text\" class=\"form-control\"\n                           ng-model=\"filter.properties.createdAfter\"\n                           ng-change=\"filter.refreshDelayed()\"\n                           datepicker-popup=\"dd/MM/yyyy\"\n                           is-open=\"createdAfterPicker.isOpen\"\n                           ng-click=\"createdAfterPicker.isOpen=true\"/>\n\t              </div>\n\t            </div>\n            </div>\n        </div>\n    </div>\n</div>\n"
  },
  {
    "path": "flowable-ui-web/admin/views/field-preview-template.html",
    "content": "<div ng-if=\"field != null && field != undefined && !customFieldTemplates[field.type]\" ng-switch=\"field.type\">\n\n    <div ng-switch-when=\"text\" class=\"form-group\">\n        <label class=\"control-label\">{{field.name}}</label>\n        <span class=\"marker\" ng-if=\"field.required\">*</span>\n        <input type=\"text\" class=\"form-control\" value=\"{{'FORM.FIELD-PREVIEW.TEXT-VALUE' | translate}}\" disabled>\n    </div>\n\n    <div ng-switch-when=\"container\" class=\"form-group\">\n        <div class=\"container-control row\">\n            <div class=\"col-sm-6\" ng-repeat=\"(colName, colItems) in field.fields\">\n                <div ng-repeat=\"item in colItems\">\n                    <field-preview field=\"item\" custom-field-templates=\"customFieldTemplates\"></field-preview>\n                </div>\n                <div class=\"clearfix\"></div>\n            </div>\n        </div>\n    </div>\n\n    <div ng-switch-when=\"multi-line-text\" class=\"form-group\">\n        <label class=\"control-label\">{{field.name}}</label>\n        <span class=\"marker\" ng-if=\"field.required\">*</span>\n        <textarea rows=\"4\" class=\"form-control\" disabled>{{'FORM.FIELD-PREVIEW.MULTI-TEXT-VALUE' | translate}}</textarea>\n    </div>\n\n    <div ng-switch-when=\"integer\" class=\"form-group\">\n        <label class=\"control-label\">{{field.name}}</label>\n        <span class=\"marker\" ng-if=\"field.required\">*</span>\n        <input type=\"text\" class=\"form-control\" value=\"{{'FORM.FIELD-PREVIEW.NUMBER-VALUE' | translate}}\" disabled>\n    </div>\n\n    <div ng-switch-when=\"date\" class=\"form-group\">\n        <label class=\"control-label\"><i class=\"glyphicon glyphicon-calendar\"></i> {{field.name}}</label>\n        <span class=\"marker\" ng-if=\"field.required\">*</span>\n        <span class=\"control-label\" ng-if=\"field.acceptedFormat\">({{field.acceptedFormat}})</span>\n        <input type=\"text\" class=\"form-control\" value=\"{{'FORM.FIELD-PREVIEW.DATE-VALUE' | translate}}\" disabled>\n    </div>\n\n    <div ng-switch-when=\"boolean\" class=\"form-group\">\n        <label class=\"control-label\" style=\"cursor: pointer;\">\n            <input type=\"checkbox\"  disabled> <span>{{field.name}}</span>\n            <span class=\"marker\" ng-if=\"field.required\">*</span>\n        </label>\n    </div>\n\n\t<div ng-switch-when=\"amount\" class=\"form-group\">\n\t\t<label class=\"control-label\">{{field.name}}</label>\n\t\t<div class=\"input-group amount-field\">\n\t\t\t<span class=\"input-group-addon\">{{field.currency || '$'}}</span>\n\t\t\t<input type=\"text\" class=\"form-control\" value=\"123\" disabled>\n\t\t\t<span ng-if=\"field.enableFractions\" class=\"input-group-addon\">.00</span>\n\t\t</div>\n\t</div>\n\n\t<div ng-switch-when=\"dropdown\" class=\"form-group\">\n        <label class=\"control-label\">{{field.name}}</label>\n        <span class=\"marker\" ng-if=\"field.required\">*</span>\n        <select class=\"form-control\" disabled>\n          <option>{{'FORM.FIELD-PREVIEW.DROPDOWN-VALUE' | translate}}</option>\n    </select>\n    </div>\n\n    <div ng-switch-when=\"typeahead\" class=\"form-group\">\n        <label class=\"control-label\">{{field.name}}</label>\n        <span class=\"marker\" ng-if=\"field.required\">*</span>\n        <select class=\"form-control\" disabled>\n      <option>{{formElement.placeholder}}</option>\n    </select>\n    </div>\n\n    <div ng-switch-when=\"radio-buttons\" class=\"form-group\">\n        <div>\n            <label class=\"control-label\">{{field.name}}</label>\n            <span class=\"marker\" ng-if=\"field.required\">*</span>\n        </div>\n        \n      <div ng-show=\"field.optionType != 'rest' && field.options && field.options.length> 0\" class=\"radio\" ng-repeat=\"option in field.options\">\n          <label>\n              <input type=\"radio\" name=\"optionsRadios\" id=\"optionsRadios{{$index}}\" value=\"option{{$index}}\" ng-checked=\"field.value == option.name\" disabled>{{option.name}}</input>\n          </label>\n      </div>\n      <div ng-show=\"field.optionType != 'rest' && !field.options && field.options.length === 0\" class=\"radio\">\n          <label>\n              <input type=\"radio\" name=\"optionsRadios\" id=\"optionsRadios1\" value=\"option1\" disabled>\n              {{'FORM.FIELD-PREVIEW.RADIOS-OPTION1' | translate}}\n          </label>\n      </div>\n      <div ng-show=\"field.optionType == 'rest'\" class=\"radio\">\n          <label>\n              <input type=\"radio\" name=\"optionsRadios\" id=\"optionsRadios1\" disabled>\n              {{formElement.restUrl}}\n          </label>\n      </div>\n    </div>\n\n    <div ng-switch-when=\"people\" class=\"form-group\">\n        <label class=\"control-label\">{{field.name}}</label>\n        <span class=\"marker\" ng-if=\"field.required\">*</span>\n        <div class=\"input-group\">\n      <span class=\"input-group-addon\"><i class=\"icon icon-user-add\"></i></span>\n      <input type=\"text\" class=\"form-control\" placeholder=\"{{'FORM.FIELD-PREVIEW.SELECT-PERSON' | translate}}\" value=\"{{field.placeholder}}\" disabled>\n    </div>\n    \n    </div>\n\n    <div ng-switch-when=\"functional-group\" class=\"form-group\">\n        <label class=\"control-label\">{{field.name}}</label>\n        <span class=\"marker\" ng-if=\"field.required\">*</span>\n        <div class=\"input-group\">\n      <span class=\"input-group-addon\"><i class=\"icon icon-user-add\"></i></span>\n      <input type=\"text\" class=\"form-control\" placeholder=\"{{'FORM.FIELD-PREVIEW.SELECT-GROUP' | translate}}\" value=\"{{field.placeholder}}\" disabled>\n    </div>\n    </div>\n\n    <div ng-switch-when=\"group\" class=\"form-group\">\n        <h3>{{field.name}}</h3>\n        <hr style=\"width:100%; height: 1px; background-color: black\" />\n        <div class=\"container-control row\">\n            <div class=\"col-sm-6\" ng-repeat=\"(colName, colItems) in field.fields\">\n                <div ng-repeat=\"item in colItems\">\n                    <field-preview field=\"item\" custom-field-templates=\"customFieldTemplates\"></field-preview>\n                </div>\n                <div class=\"clearfix\"></div>\n            </div>\n        </div>\n        <div class=\"clearfix\"></div>\n    </div>\n\n    <div ng-switch-when=\"dynamic-table\" class=\"form-group dynamicTableContainer\">\n        <label class=\"control-label\">{{field.name}}</label>\n        <span class=\"marker\" ng-if=\"field.required\">*</span>\n\t\t<div class=\"dynamicTable\" ui-grid=\"gridOptions\" ui-grid-auto-resize></div>\n        <div class=\"clearfix\"></div>\n    </div>\n\n    <div ng-switch-when=\"upload\" class=\"form-group\">\n        <label class=\"control-label\">{{field.name}}</label>\n        <span class=\"marker\" ng-if=\"field.required\">*</span>\n        <div class=\"input-group clearfix\">\n      <span class=\"input-group-addon\"><i class=\"icon icon-folder\"></i></span>\n      <input type=\"text\" class=\"form-control\" value=\"{{'FORM.FIELD-PREVIEW.UPLOAD-VALUE' | translate}}\" disabled>\n    </div>\n    </div>\n\n\n    <div ng-switch-when=\"hyperlink\" class=\"form-group\">\n        <label class=\"control-label\">{{field.name}}</label>\n        <div class=\"message\">\n      {{field.hyperlinkUrl}}\n    </div>\n\n    </div>\n\n    <div ng-switch-when=\"readonly\">\n      <div ng-if=\"field.params.field.type == 'dynamic-table'\">\n      <label class=\"control-label form-field-label\">{{field.name}} - <i>{{'FORM.FIELD-PREVIEW.DISPLAY-REF' | translate}}</i></label>\n      <div class=\"dynamicTable\" ui-grid=\"gridOptions\" ui-grid-auto-resize></div>\n    </div>\n    <div ng-if=\"field.params.field.type != 'dynamic-table'\">\n      <div class=\"message\">\n        {{field.params.field.name && ('FORM.FIELD-PREVIEW.FIELD-VALUE' | translate:field.params.field) || ('FORM.FIELD-PREVIEW.SELECT-FIELD' | translate)}}\n      </div>\n    </div>\n    <div class=\"clearfix\"></div>\n    </div>\n\n    <div ng-switch-when=\"readonly-text\" class=\"form-group\">\n        <p>{{field.value}}</p>\n    </div>\n\n    <div ng-switch-default translate=\"FORM.FIELD-PREVIEW.UNKNOWN-TYPE\" translate-values=\"{type: field.type}\">\n    </div>\n</div>\n\n<div ng-if=\"field != null && field != undefined && customFieldTemplates[field.type]\">\n    <div class=\"form-group\" ng-class=\"{'has-error': field.required && isEmpty(field)}\">\n        <label class=\"control-label\">{{field.name}}</label>\n        <span class=\"marker\" ng-if=\"field.required\">*</span>\n        <div compile-html=\"getHtmlTemplate(field)\"></div>\n    </div>\n</div>"
  },
  {
    "path": "flowable-ui-web/admin/views/form-definition.html",
    "content": "<div class=\"container\" id=\"detail-container\">\n\t<div class=\"row\">\n\t\t<div class=\"col-md-9\">\n\t\t\t<div class=\"component\" ng-show=\"form\">\n\t\t\t\t<div class=\"title\">\n\t\t\t\t\t<div class=\"pull-right\">\n\t\t\t\t\t\t<a ng-click=\"returnToList()\" class=\"action\">&larr; {{'GENERAL.ACTION.RETURN-TO-LIST' | translate}}</a>\n\t\t\t\t\t</div>\n\t\t\t\t\t<h2>{{form.name &amp;&amp; form.name +\" - \" || \"\"}}{{form.id}}</h2>\n\t\t\t\t</div>\n\n\t\t\t\t<div class=\"property-wrapper\">\n\t\t\t\t\t<table>\n\t\t\t\t\t\t<tr class=\"property\">\n\t\t\t\t\t\t\t<td class=\"property-name\" translate=\"FORM-DEFINITION.ID\"></td>\n\t\t\t\t\t\t\t<td>{{form.id}}</td>\n\t\t\t\t\t\t\t<td class=\"property-name\" translate=\"FORM-DEFINITION.NAME\"></td>\n\t\t\t\t\t\t\t<td>{{form.name | empty}}</td>\n\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t<tr class=\"property\">\n\t\t\t\t\t\t\t<td class=\"property-name\" translate=\"FORM-DEFINITION.DEPLOYMENT-ID\"></td>\n\t\t\t\t\t\t\t<td><a ng-href=\"#/form-deployment/{{form.deploymentId}}\"><i class=\"glyphicon glyphicon-zoom-in\"></i> {{form.deploymentId}}</a></td>\n\t\t\t\t\t\t\t<td ng-if=\"form.parentDeploymentId\" class=\"property-name\" translate=\"FORM-DEFINITION.PARENT-DEPLOYMENT-ID\"></td>\n\t\t\t\t\t\t\t<td ng-if=\"form.parentDeploymentId\"><a ng-href=\"#/app-deployment/{{form.parentDeploymentId}}\"><i class=\"glyphicon glyphicon-zoom-in\"></i> {{form.parentDeploymentId}}</a></td>\n\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t<tr class=\"property\">\n\t\t\t\t\t\t\t<td class=\"property-name\" translate=\"FORM-DEFINITION.DESCRIPTION\"></td>\n\t\t\t\t\t\t\t<td>{{form.description | empty}}</td>\n\t\t\t\t\t\t</tr>\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<div class=\"col-md-3\">\n\t\t\t<div class=\"component tip-left\">\n\t\t\t\t<div class=\"title\">\n\t\t\t\t\t<h2 translate=\"GENERAL.TITLE.ACTIONS\"></h2>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</div>\n\t</div>\n\t<div class=\"row\">\n\t\t<div class=\"col-md-9\">\n            <div class=\"component\">\n                <div class=\"title\">\n                    <h2 translate=\"FORM-DEFINITION.TITLE.FORM-INSTANCES\"></h2>\n                </div>\n                <div class=\"grid-wrapper grid-wrapper-compact\" ng-if=\"formInstances\">\n                    <div class=\"grid-message\" ng-if=\"formInstances.size > 0\">\n                        <span>{{'FORM-DEFINITION.FORM-INSTANCES-MESSAGE' | translate:formInstances}}</span>\n                    </div>\n                    <div class=\"grid-message\" ng-if=\"formInstances.size == 0\">\n                        <span>{{'FORM-DEFINITION.FORM-INSTANCES-MESSAGE-EMPTY' | translate}}</span>\n                    </div>\n                    <div ng-grid=\"gridFormInstances\" class=\"gridStyle\" ng-if=\"gridFormInstances && formInstances.data\" ng-show=\"formInstances.size > 0\"></div>\n                </div>\n            </div>\n\t\t</div>\n\t</div>\n</div>\n"
  },
  {
    "path": "flowable-ui-web/admin/views/form-definitions.html",
    "content": "<!-- LIST PAGE -->\n<div class=\"container\" id=\"list-container\">\n    <div class=\"row\">\n        <div class=\"col-md-8\">\n            <div class=\"component\">\n                <div class=\"title\">\n                    <div class=\"btn-group btn-group-sm pull-right\">\n                        <div class=\"btn-group btn-group-sm\">\n                            <button type=\"button\" class=\"btn btn-default dropdown-toggle\" data-toggle=\"dropdown\"\n                                    translate=\"GENERAL.ACTION.SHOW-RESULTS\" translate-value-size=\"{{'GENERAL.RESULT-SIZES.' + filter.resultSize | translate}}\">\n                                &nbsp;\n                                <span class=\"caret\"></span>\n                            </button>\n                            <ul class=\"dropdown-menu\">\n                            \t<li ng-repeat=\"resultSize in config.filter.resultSizes\"><a href=\"\" ng-click=\"filter.setResultSize(resultSize)\">{{'GENERAL.RESULT-SIZES.' + resultSize.toString() | translate}}</a></li>\n                            </ul>\n                        </div>\n                        <button type=\"button\" class=\"btn btn-default\" ng-click=\"filter.toggleOrder()\">\n                        \t<i class=\"glyphicon\" ng-class=\"{'glyphicon-sort-by-attributes': filter.order == 'asc', 'glyphicon-sort-by-attributes-alt': filter.order == 'desc'}\"></i>\n                        </button>\n                    </div>\n                    <div class=\"btn-group btn-group-sm pull-right\">\n                    \t<button type=\"button\" class=\"btn btn-default dropdown-toggle\" data-toggle=\"dropdown\"\n                                translate=\"GENERAL.ACTION.SHOW-RESULTS\" translate-value-size=\"{{'GENERAL.RESULT-SIZES.' + filter.resultSize | translate}}\">\n                            &nbsp;\n                            <span class=\"caret\"></span>\n                        </button>\n                    \t<ul class=\"dropdown-menu\">\n                           <li ng-repeat=\"sort in filter.sortObjects\"><a href=\"\" ng-click=\"filter.setSort(sort)\">{{sort.name | translate}}</a></li>\n                        </ul>\n                    </div>\n                    <div class=\"btn-group btn-group-sm pull-right\">\n                        <a class=\"btn btn-default\" role=\"button\"\n                           title=\"{{'GENERAL.ACTION.REFRESH-LIST' | translate}}\"\n                           ng-click=\"filter.refresh();\">\n                            <i class=\"glyphicon glyphicon-refresh\"></i>\n                        </a>\n                    </div>\n                    <div class=\"pull-right loading\" ng-show=\"filter.loading\">\n                    \t<i class=\"glyphicon glyphicon-refresh\"></i>\n                    </div>\n                    <h2 translate=\"FORM-DEFINITIONS.TITLE\"></h2>\n                </div>\n\n                <div class=\"grid-wrapper\" id=\"forms\">\n                    <div class=\"grid-message\" ng-if=\"formsData.size > 0\">\n                        <span>{{'FORM-DEFINITIONS.LIST-MESSAGE' | translate:formsData}}</span>\n                    </div>\n                     <div class=\"grid-message\" ng-if=\"formsData.size == 0\">\n                        <span>{{'FORM-DEFINITIONS.LIST-MESSAGE-EMPTY' | translate}}</span>\n                    </div>\n                    <div ng-grid=\"gridForms\" class=\"gridStyle\" ng-if=\"gridForms && formsData.data\"/>\n                </div>\n            </div>\n        </div>\n        <div class=\"col-md-4\">\n\n            <!-- forms filters -->\n            <div class=\"component tip-left\">\n                <div class=\"title\">\n                    <div class=\"pull-right\">\n                        <a class=\"action\" ng-click=\"filter.clear()\" translate=\"GENERAL.ACTION.CLEAR-FILTERS\"></a>\n                    </div>\n                    <h2 translate=\"GENERAL.TITLE.FILTERS\"></h2>\n                </div>\n                <div class=\"section\" ng-if=\"filter.properties.nameLike !== undefined\">\n                    <div class=\"subtitle\"><label for=\"filter-nameLike\" translate=\"FORM-DEFINITIONS.FILTER.NAME\"></label> </div>\n                    <div class=\"input-group input-group-sm\">\n                        <input id=\"filter-nameLike\" type=\"text\" class=\"form-control\" value=\"\" ng-model=\"filter.properties.nameLike\" ng-change=\"filter.refreshDelayed()\">\n                    </div>\n                </div>\n                <div class=\"section\" ng-if=\"filter.properties.appId !== undefined\">\n                    <div class=\"subtitle\"><label for=\"filter-appId\" translate=\"FORM-DEFINITIONS.FILTER.APPID\"></label> </div>\n                    <div class=\"input-group input-group-sm\">\n                        <input id=\"filter-appId\" type=\"text\" number-input-check class=\"form-control\" value=\"\" ng-model=\"filter.properties.appId\" ng-change=\"filter.refreshDelayed()\">\n                    </div>\n                </div>\n                <div class=\"section\" ng-if=\"filter.properties.tenantId !== undefined\">\n                    <div class=\"subtitle\"><label for=\"filter-tenantId\" translate=\"APP-DEPLOYMENTS.FILTER.TENANTID\"></label> </div>\n                    <div class=\"input-group input-group-sm\">\n                        <input id=\"filter-tenantId\" type=\"text\" class=\"form-control\" value=\"\" number-input-check ng-model=\"filter.properties.tenantId\" ng-change=\"filter.refreshDelayed()\">\n                    </div>\n                </div>\n            </div>\n\n        </div>\n\n        </div>\n    </div>\n</div>"
  },
  {
    "path": "flowable-ui-web/admin/views/form-deployment.html",
    "content": "<div class=\"container\" id=\"detail-container\">\n\t<div class=\"row\">\n\t\t<div class=\"col-md-9\">\n\t\t\t<div class=\"component\" ng-show=\"formDeployment\">\n\t\t\t\t<div class=\"title\">\n\t\t\t\t\t<div class=\"pull-right\">\n\t\t\t\t\t\t<a ng-click=\"returnToList()\" class=\"action\">&larr; {{'GENERAL.ACTION.RETURN-TO-LIST' | translate}}</a>\n\t\t\t\t\t</div>\n\t\t\t\t\t<h2>{{formDeployment.name || formDeployment.id}}</h2>\n\t\t\t\t</div>\n\n\t\t\t\t<div class=\"property-wrapper\">\n\t\t\t\t\t<table>\n\t\t\t\t\t\t<tr class=\"property\">\n\t\t\t\t\t\t\t<td class=\"property-name\" translate=\"FORM-DEPLOYMENT.ID\"></td>\n\t\t\t\t\t\t\t<td>{{formDeployment.id}}</td>\n\t\t\t\t\t\t\t<td class=\"property-name\" translate=\"FORM-DEPLOYMENT.NAME\"></td>\n\t\t\t\t\t\t\t<td>{{formDeployment.name | empty}}</td>\n\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t<tr class=\"property\">\n\t\t\t\t\t\t\t<td class=\"property-name\" translate=\"FORM-DEPLOYMENT.TIME\"></td>\n\t\t\t\t\t\t\t<td>{{formDeployment.deploymentTime | dateformat}}</td>\n\t\t\t\t\t\t\t<td class=\"property-name\" translate=\"FORM-DEPLOYMENT.CATEGORY\"></td>\n\t\t\t\t\t\t\t<td>{{formDeployment.category | empty}}</td>\n\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t<tr class=\"property\">\n                            <td class=\"property-name\" translate=\"FORM-DEPLOYMENT.TENANTID\"></td>\n                            <td>{{formDeployment.tenantId | empty}}</td>\n                            <td ng-if=\"formDeployment.parentDeploymentId\" class=\"property-name\" translate=\"FORM-DEPLOYMENT.PARENT-DEPLOYMENT-ID\"></td>\n                            <td ng-if=\"formDeployment.parentDeploymentId\"><a ng-href=\"#/app-deployment/{{formDeployment.parentDeploymentId}}\"><i class=\"glyphicon glyphicon-zoom-in\"></i> {{formDeployment.parentDeploymentId}}</a></td>\n                        </tr>\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 class=\"col-md-3\">\n\t\t\t<div class=\"component tip-left\">\n\t\t\t\t<div class=\"title\">\n\t\t\t\t\t<h2 translate=\"GENERAL.TITLE.ACTIONS\"></h2>\n\t\t\t\t</div>\n\t\t\t\t<ul class=\"list-group\">\n\t\t\t\t\t  <li>\n\t\t\t\t\t    <button type=\"button\" class=\"btn btn-sm btn-default btn-danger\" ng-click=\"deleteDeployment()\">\n\t\t\t\t\t\t\t<i class=\"glyphicon glyphicon-remove\"></i><span translate=\"FORM-DEPLOYMENTS.ACTION.DELETE\"></span>\n\t\t\t\t\t    </button>\n\t\t\t\t\t  </li>\n\t\t\t\t</ul>\n\t\t\t</div>\n\t\t</div>\n\t</div>\n\t<div class=\"row\">\n\t\t<div class=\"col-md-9\">\n\t\t\t<div class=\"component\">\n\t\t\t\t<div class=\"title\">\n\t\t\t\t\t<div class=\"pull-right\">\n\t\t\t\t\t\t<a ng-click=\"showAllFormDefinitions()\" class=\"action\"><i class=\"glyphicon glyphicon-zoom-in\"></i> {{'DEPLOYMENT.ACTION.SHOW-ALL-DEFINITIONS' | translate}}</a>\n\t\t\t\t\t</div>\n\t\t\t\t\t<h2 translate=\"FORM-DEPLOYMENT.TITLE.FORM-DEFINITIONS\"></h2>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"grid-wrapper grid-wrapper-compact\" ng-if=\"formDefinitions\">\n\t\t\t\t\t<div class=\"grid-message\" ng-if=\"formDefinitions.size > 0\">\n\t                       <span>{{'FORM-DEPLOYMENT.DEFINITIONS-MESSAGE' | translate:formDefinitions}}</span>\n\t                   </div>\n\t                    <div class=\"grid-message\" ng-if=\"formDefinitions.size == 0\">\n\t                       <span>{{'FORM-DEPLOYMENT.DEFINITIONS-MESSAGE-EMPTY' | translate}}</span>\n\t                   </div>\n\t\t\t\t\t<div ng-grid=\"gridFormDefinitions\" class=\"gridStyle\" ng-if=\"gridFormDefinitions && formDefinitions.data\" ng-show=\"formDefinitions.size > 0\"></div>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</div>\n\t</div>\n</div>\n"
  },
  {
    "path": "flowable-ui-web/admin/views/form-deployments.html",
    "content": "<!-- LIST PAGE -->\n<div class=\"container\" id=\"list-container\">\n    <div class=\"row\">\n        <div class=\"col-md-8\">\n            <div class=\"component\">\n                <div class=\"title\">\n                    <div class=\"btn-group btn-group-sm pull-right\">\n                        <div class=\"btn-group btn-group-sm\">\n                            <button type=\"button\" class=\"btn btn-default dropdown-toggle\" data-toggle=\"dropdown\"\n                                    translate=\"GENERAL.ACTION.SHOW-RESULTS\" translate-value-size=\"{{'GENERAL.RESULT-SIZES.' + filter.resultSize | translate}}\">\n                                &nbsp;\n                                <span class=\"caret\"></span>\n                            </button>\n                            <ul class=\"dropdown-menu\">\n                            \t<li ng-repeat=\"resultSize in config.filter.resultSizes\"><a href=\"\" ng-click=\"filter.setResultSize(resultSize)\">{{'GENERAL.RESULT-SIZES.' + resultSize.toString() | translate}}</a></li>\n                            </ul>\n                        </div>\n                        <button type=\"button\" class=\"btn btn-default\" ng-click=\"filter.toggleOrder()\">\n                        \t<i class=\"glyphicon\" ng-class=\"{'glyphicon-sort-by-attributes': filter.order == 'asc', 'glyphicon-sort-by-attributes-alt': filter.order == 'desc'}\"></i>\n                        </button>\n                    </div>\n                    <div class=\"btn-group btn-group-sm pull-right\">\n                    \t<button type=\"button\" class=\"btn btn-default dropdown-toggle\" data-toggle=\"dropdown\"\n                                translate=\"GENERAL.ACTION.SHOW-RESULTS\" translate-value-size=\"{{'GENERAL.RESULT-SIZES.' + filter.resultSize | translate}}\">\n\t\t\t\t\t\t    &nbsp;\n                            <span class=\"caret\"></span>\n                        </button>\n                    \t<ul class=\"dropdown-menu\">\n                           <li ng-repeat=\"sort in filter.sortObjects\"><a href=\"\" ng-click=\"filter.setSort(sort)\">{{sort.name | translate}}</a></li>\n                        </ul>\n                    </div>\n                    <div class=\"btn-group btn-group-sm pull-right\">\n                        <a class=\"btn btn-default\" role=\"button\"\n                           title=\"{{'GENERAL.ACTION.REFRESH-LIST' | translate}}\"\n                           ng-click=\"filter.refresh();\">\n                            <i class=\"glyphicon glyphicon-refresh\"></i>\n                        </a>\n                    </div>\n                    <div class=\"pull-right loading\" ng-show=\"filter.loading\">\n                    \t<i class=\"glyphicon glyphicon-refresh\"></i>\n                    </div>\n                    <h2 translate=\"FORM-DEPLOYMENTS.TITLE\"></h2>\n                </div>\n\n                <div class=\"grid-wrapper\" id=\"deployments\">\n                    <div class=\"grid-message\" ng-if=\"formDeploymentsData.size > 0\">\n                        <span>{{'FORM-DEPLOYMENTS.LIST-MESSAGE' | translate:formDeploymentsData}}</span>\n                    </div>\n                     <div class=\"grid-message\" ng-if=\"deploymentsData.size == 0\">\n                        <span>{{'FORM-DEPLOYMENTS.LIST-MESSAGE-EMPTY' | translate}}</span>\n                    </div>\n                    <div ng-grid=\"gridFormDeployments\" class=\"gridStyle\" ng-if=\"gridFormDeployments && formDeploymentsData.data\"/>\n                </div>\n            </div>\n        </div>\n        <div class=\"col-md-4\">\n\n            <!-- Deployment filters -->\n            <div class=\"component tip-left\">\n                <div class=\"title\">\n                    <div class=\"pull-right\">\n                        <a class=\"action\" ng-click=\"filter.clear()\" translate=\"GENERAL.ACTION.CLEAR-FILTERS\"></a>\n                    </div>\n                    <h2 translate=\"GENERAL.TITLE.FILTERS\"></h2>\n                </div>\n                <div class=\"section\" ng-if=\"filter.properties.nameLike !== undefined\">\n                    <div class=\"subtitle\"><label for=\"filter-nameLike\" translate=\"FORM-DEPLOYMENTS.FILTER.NAME\"></label> </div>\n                    <div class=\"input-group input-group-sm\">\n                        <input id=\"filter-nameLike\" type=\"text\" class=\"form-control\" value=\"\" ng-model=\"filter.properties.nameLike\" ng-change=\"filter.refreshDelayed()\">\n                    </div>\n                </div>\n                <div class=\"section\" ng-if=\"filter.properties.tenantIdLike !== undefined\">\n                    <div class=\"subtitle\"><label for=\"filter-tenantIdLike\" translate=\"FORM-DEPLOYMENTS.FILTER.TENANTID\"></label> </div>\n                    <div class=\"input-group input-group-sm\">\n                        <input id=\"filter-tenantIdLike\" type=\"text\" class=\"form-control\" value=\"\" ng-model=\"filter.properties.tenantIdLike\" ng-change=\"filter.refreshDelayed()\">\n                    </div>\n                </div>\n            </div>\n\n            <!-- Actions -->\n            <div class=\"component no-min-height\">\n                <div class=\"title\">\n                    <h2 translate=\"GENERAL.TITLE.ACTIONS\"></h2>\n                </div>\n                <ul class=\"list-group\">\n                    <li>\n                        <button type=\"button\" class=\"btn btn-sm btn-default\" ng-click=\"uploadDeployment()\">\n                            <i class=\"glyphicon glyphicon-open\"></i>{{'FORM-DEPLOYMENTS.ACTION.UPLOAD' | translate}}\n                        </button>\n                    </li>\n                </ul>\n            </div>\n        </div>\n\n        </div>\n    </div>\n</div>"
  },
  {
    "path": "flowable-ui-web/admin/views/form-element-template.html",
    "content": "<div\n\tng-if=\"field != null && field != undefined && !customFieldTemplates[field.type]\"\n\tng-switch=\"field.type\">\n\n\t<div ng-switch-when=\"container\" class=\"form-group\">\n\t\t<div class=\"container-control row\">\n\t\t\t<div class=\"col-sm-6\" ng-repeat=\"(colName, colItems) in field.fields\">\n\t\t\t\t<div ng-repeat=\"item in colItems\">\n\t\t\t\t\t<form-element field=\"item\"\n\t\t\t\t\t\tcustom-field-templates=\"customFieldTemplates\"></form-element>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"clearfix\"></div>\n\t\t\t</div>\n\t\t</div>\n\t</div>\n\t\n\t<div ng-switch-when=\"group\" class=\"form-group\">\n\t\t\t<h3>{{field.name}}</h3>\n\t\t\t<hr style=\"width: 100%; height: 1px; background-color: black\" />\n\t\t\t<div class=\"container-control row\">\n\t\t\t\t<div class=\"col-sm-6\"\n\t\t\t\t\tng-repeat=\"(colName, colItems) in field.fields\">\n\t\t\t\t\t<div ng-repeat=\"item in colItems\">\n\t\t\t\t\t\t<form-element field=\"item\"\n\t\t\t\t\t\t\tcustom-field-templates=\"customFieldTemplates\"></form-element>\n\t\t\t\t\t</div>\n\t\t\t\t\t<div class=\"clearfix\"></div>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t<div class=\"clearfix\"></div>\n\t\t</div>\n\n\t<div ng-switch-when=\"readonly\"\n\t\tng-if=\"!customFieldTemplates[field.params.field.type]\"\n\t\tng-switch=\"field.params.field.type\">\n\n\t\t<div ng-switch-when=\"readonly-text\" class=\"form-group\">\n\t\t\t<p>{{field.value}}</p>\n\t\t</div>\n\n\t\t<div ng-switch-when=\"text\" class=\"form-group\">\n\t\t\t<label class=\"control-label\">{{field.name}}</label> <span\n\t\t\t\tclass=\"marker\" ng-if=\"field.required\">*</span> <input type=\"text\"\n\t\t\t\tclass=\"form-control\" value=\"{{field.value}}\" disabled>\n\t\t</div>\n\n\t\t<div ng-switch-when=\"multi-line-text\" class=\"form-group\">\n\t\t\t<label class=\"control-label\">{{field.name}}</label> <span\n\t\t\t\tclass=\"marker\" ng-if=\"field.required\">*</span>\n\t\t\t<textarea rows=\"4\" class=\"form-control\" disabled>{{field.value}}</textarea>\n\t\t</div>\n\n\t\t<div ng-switch-when=\"integer\" class=\"form-group\">\n\t\t\t<label class=\"control-label\">{{field.name}}</label> <span\n\t\t\t\tclass=\"marker\" ng-if=\"field.required\">*</span> <input type=\"text\"\n\t\t\t\tclass=\"form-control\"\n\t\t\t\tvalue=\"{{field.value}}\" disabled>\n\t\t</div>\n\n\t\t<div ng-switch-when=\"date\" class=\"form-group\">\n\t\t\t<label class=\"control-label\"><i\n\t\t\t\tclass=\"glyphicon glyphicon-calendar\"></i> {{field.name}}</label> <span\n\t\t\t\tclass=\"marker\" ng-if=\"field.required\">*</span> <span\n\t\t\t\tclass=\"control-label\" ng-if=\"field.acceptedFormat\">({{field.acceptedFormat}})</span>\n\t\t\t<input type=\"text\" class=\"form-control\"\n\t\t\t\tvalue=\"{{field.value | date}}\" disabled>\n\t\t</div>\n\n\t\t<div ng-switch-when=\"boolean\" class=\"form-group\">\n\t\t\t<label class=\"control-label\" style=\"cursor: pointer;\"> <input\n\t\t\t\ttype=\"checkbox\" ng-checked=\"{{field.value}}\" disabled> <span>{{field.name}}</span> <span\n\t\t\t\tclass=\"marker\" ng-if=\"field.required\">*</span>\n\t\t\t</label>\n\t\t</div>\n\n\t\t<div ng-switch-when=\"amount\" class=\"form-group\">\n\t\t\t<label class=\"control-label\">{{field.name}}</label>\n\t\t\t<div class=\"input-group amount-field\">\n\t\t\t\t<span class=\"input-group-addon\">{{field.currency || '$'}}</span> <input\n\t\t\t\t\ttype=\"text\" class=\"form-control\" value=\"{{field.value}}\" disabled>\n\t\t\t</div>\n\t\t</div>\n\n\t\t<div ng-switch-when=\"dropdown\" class=\"form-group\">\n\t\t\t<label class=\"control-label\">{{field.name}}</label> <span\n\t\t\t\tclass=\"marker\" ng-if=\"field.required\">*</span> \n\t\t\t<div class=\"well well-sm\">\n                    {{field.value}}\n                </div>\n\t\t</div>\n\n\t\t<div ng-switch-when=\"radio-buttons\" class=\"form-group\">\n\t\t\t<label class=\"control-label\">{{field.name}}</label> <span\n\t\t\t\tclass=\"marker\" ng-if=\"field.required\">*</span> \n\t\t\t<div class=\"well well-sm\">\n                    {{field.value}}\n                </div>\n\t\t</div>\n\n\t\t<div ng-switch-when=\"people\" class=\"readonly\">\n\t\t\t<label class=\"control-label\">{{field.name}}</label>\n\t\t\t<span class=\"marker\" ng-if=\"field.required\">*</span>\n\t\t\t<div class=\"well well-sm\">\n\t\t\t\t<span ng-if=\"field.value.id\">{{field.value.firstName}} {{field.value.lastName}}</span>\n\t\t\t\t<span ng-if=\"!field.value.id\">{{'' | empty}}</span>\n\t\t\t</div>\n\t\t</div>\n\n\t\t<div ng-switch-when=\"functional-group\" class=\"readonly\">\n\t\t\t<label class=\"control-label\">{{field.name}}</label> \n\t\t\t<span class=\"marker\" ng-if=\"field.required\">*</span>\n\t\t\t<div class=\"well well-sm\">\n\t\t\t\t<span ng-if=\"field.value.id\">{{field.value.name}}</span> \n\t\t\t\t<span ng-if=\"!field.value.id\">{{'' | empty}}</span>\n\t\t\t</div>\n\t\t</div>\n\t\t\n\t\t<div ng-switch-when=\"group\" class=\"readonly\">\n\t\t\t<label class=\"control-label\">{{field.name}}</label> \n\t\t\t<span class=\"marker\" ng-if=\"field.required\">*</span>\n\t\t\t<div class=\"well well-sm\">\n\t\t\t\t<span ng-if=\"field.value.id\">{{field.value.name}}</span> \n\t\t\t\t<span ng-if=\"!field.value.id\">{{'' | empty}}</span>\n\t\t\t</div>\n\t\t</div>\n\t\t\n\t\t<div ng-switch-when=\"dynamic-table\"\n\t\t\tclass=\"form-group dynamicTableContainer\">\n\t\t\t<label class=\"control-label\">{{field.name}}</label> <span\n\t\t\t\tclass=\"marker\" ng-if=\"field.required\">*</span>\n\t\t\t<div class=\"dynamicTable\" ui-grid=\"gridOptions\" ui-grid-auto-resize></div>\n\t\t\t<div class=\"clearfix\"></div>\n\t\t</div>\n\n\t\t<div ng-switch-when=\"upload\" class=\"form-group\">\n\t\t\t<label class=\"control-label\">{{field.name}}</label> <span\n\t\t\t\tclass=\"marker\" ng-if=\"field.required\">*</span>\n\t\t\t<div class=\"well well-sm\">\n\t\t\t\t<span ng-if=\"field.value.length > 0\" ng-repeat=\"attachement in field.value\">{{attachement.name}}</span> \n\t\t\t\t<span ng-if=\"!field.value || field.value.length === 0\">{{'' | empty}}</span>\n\t\t\t</div>\n\t\t</div>\n\n\t\t<div ng-switch-when=\"hyperlink\" class=\"form-group\">\n\t\t\t<label class=\"control-label\">{{field.name}}</label>\n\t\t\t<div class=\"message\">{{field.hyperlinkUrl}}</div>\n\t\t</div>\n\n\t\t<div ng-switch-default class=\"{{field.className}} readonly\">\n\t\t\t<label class=\"control-label\">{{field.name}}</label>\n\t\t\t<div class=\"well well-sm\">\n\t\t\t\t<span ng-if=\"field.value !== undefined && field.value !== null && field.value !== ''\">{{field.value}}</span>\n\t\t\t\t<span ng-if=\"field.value === undefined || field.value === null || field.value === ''\">{{'FORM.MESSAGE-EMPTY' | translate}}</span>\n\t\t\t</div>\n\t\t</div>\n\t</div>\n\n\t<div\n\t\tng-if=\"field != null && field != undefined && customFieldTemplates[field.type]\">\n\t\t<div class=\"form-group\"\n\t\t\tng-class=\"{'has-error': field.required && isEmpty(field)}\">\n\t\t\t<label class=\"control-label\">{{field.name}}</label> <span\n\t\t\t\tclass=\"marker\" ng-if=\"field.required\">*</span>\n\t\t\t<div compile-html=\"getHtmlTemplate(field)\"></div>\n\t\t</div>\n\t</div>\n</div>\n"
  },
  {
    "path": "flowable-ui-web/admin/views/form-instance.html",
    "content": "<!-- LIST PAGE -->\n<div class=\"container\" id=\"list-container\">\n    <div class=\"row\">\n        <div class=\"col-md-9\">\n            <div class=\"component\" ng-show=\"formInstance\">\n                <div class=\"title\">\n                    <div class=\"pull-right\">\n                        <a ng-click=\"returnToList()\" class=\"action\">&larr; {{'GENERAL.ACTION.RETURN-TO-LIST' | translate}}</a>\n                    </div>\n                    <h2>{{formInstance.name &amp;&amp; formInstance.name +\" - \" || \"\"}}{{formInstance.id}}</h2>\n                </div>\n\n                <div class=\"property-wrapper\">\n                    <table>\n                        <tr class=\"property\">\n                            <td class=\"property-name\" translate=\"FORM-INSTANCE.HEADER.ID\"></td>\n                            <td>{{formInstance.id}}</td>\n                            <td class=\"property-name\" translate=\"FORM-INSTANCE.HEADER.TASK-ID\"></td>\n                            <td ng-if=\"formInstance.taskId\"><a ng-href=\"#/task/{{formInstance.taskId}}\"><i class=\"glyphicon glyphicon-zoom-in\"></i> {{formInstance.taskId}}</a></td>\n                            <td ng-if=\"!formInstance.taskId\">{{formInstance.taskId | empty}}</td>\n                        </tr>\n                        <tr class=\"property\">\n                        \t<td class=\"property-name\" ng-if=\"!formInstance.scopeType || formInstance.scopeType != 'cmmn'\" translate=\"FORM-INSTANCE.HEADER.PROCESS-ID\"></td>\n                            <td ng-if=\"(!formInstance.scopeType || formInstance.scopeType != 'cmmn') && formInstance.processInstanceId\"><a ng-href=\"#/process-instance/{{formInstance.processInstanceId}}\"><i class=\"glyphicon glyphicon-zoom-in\"></i> {{formInstance.processInstanceId}}</a></td>\n                            <td ng-if=\"(!formInstance.scopeType || formInstance.scopeType != 'cmmn') && !formInstance.processInstanceId\">{{formInstance.processInstanceId | empty}}</td>\n                            <td class=\"property-name\" ng-if=\"formInstance.scopeType && formInstance.scopeType == 'cmmn'\" translate=\"FORM-INSTANCE.HEADER.CASE-INSTANCE-ID\"></td>\n                            <td ng-if=\"formInstance.scopeType && formInstance.scopeType == 'cmmn' && formInstance.scopeId\"><a ng-href=\"#/case-instance/{{formInstance.scopeId}}\"><i class=\"glyphicon glyphicon-zoom-in\"></i> {{formInstance.scopeId}}</a></td>\n                            <td ng-if=\"formInstance.scopeType && formInstance.scopeType == 'cmmn' && !formInstance.scopeId\">{{formInstance.scopeId | empty}}</td>\n                            <td class=\"property-name\" translate=\"FORM-INSTANCE.HEADER.SUBMITTED\"></td>\n                            <td>{{formInstance.submittedDate | date}}</td>\n                        </tr>\n                        <tr class=\"property\">\n                            <td class=\"property-name\" translate=\"FORM-INSTANCE.HEADER.SUBMITTED-BY\"></td>\n                            <td user=\"formInstance.submittedBy\"></td>\n                            <td class=\"property-name\" translate=\"FORM-INSTANCE.HEADER.FORM-DEFINITION-ID\"></td>\n                            <td><a ng-href=\"#/form-definition/{{formInstance.formDefinitionId}}\"><i class=\"glyphicon glyphicon-zoom-in\"></i> {{formInstance.formDefinitionId}}</a></td>\n                        </tr>\n                    </table>\n                </div>\n            </div>\n        </div>\n        <div class=\"col-md-3\">\n            <div class=\"component tip-left\">\n                <div class=\"title\">\n                    <h2 translate=\"GENERAL.TITLE.ACTIONS\"></h2>\n                </div>\n                <ul class=\"list-group\">\n                    <li>\n                        <!--TODO: <button type=\"button\" class=\"btn btn-sm btn-default\" ng-click=\"showFormInstance()\">-->\n                            <!--<i class=\"glyphicon glyphicon-zoom-in\"></i>{{'FORM-INSTANCE.ACTION.SHOW-FORM-INSTANCE' | translate}}-->\n                        <!--</button>-->\n                    </li>\n                </ul>\n            </div>\n        </div>\n    </div>\n    <div class=\"row\">\n        <div class=\"col-md-9\">\n            <div class=\"component\">\n                <div class=\"title\">\n                    <h2 translate=\"FORM-INSTANCE.TITLE.FORM-FIELD-VALUES\"></h2>\n                </div>\n                <div class=\"grid-wrapper grid-wrapper-compact\" ng-if=\"formFieldValues\">\n                    <div class=\"grid-message\" ng-if=\"formFieldValues.size > 0\">\n                        <span>{{'FORM-INSTANCE.FORM-FIELD-VALUES-MESSAGE' | translate:formFieldValues}}</span>\n                    </div>\n                    <div class=\"grid-message\" ng-if=\"formFieldValues.size == 0\">\n                        <span>{{'FORM-INSTANCE.FORM-FIELD-VALUES-MESSAGE' | translate}}</span>\n                    </div>\n                    <div ng-grid=\"gridFormFieldValues\" class=\"gridStyle\" ng-if=\"gridFormFieldValues && formFieldValues.data\" ng-show=\"formFieldValues.size > 0\"></div>\n                </div>\n            </div>\n        </div>\n    </div>\n</div>"
  },
  {
    "path": "flowable-ui-web/admin/views/form-instances.html",
    "content": "<!-- LIST PAGE -->\n<div class=\"container\" id=\"list-container\">\n    <div class=\"row\">\n        <div class=\"col-md-8\">\n            <div class=\"component\">\n                <div class=\"title\">\n                    <div class=\"btn-group btn-group-sm pull-right\">\n                        <div class=\"btn-group btn-group-sm\">\n                            <button type=\"button\" class=\"btn btn-default dropdown-toggle\" data-toggle=\"dropdown\"\n                                    translate=\"GENERAL.ACTION.SHOW-RESULTS\" translate-value-size=\"{{'GENERAL.RESULT-SIZES.' + filter.resultSize | translate}}\">\n                                &nbsp;\n                                <span class=\"caret\"></span>\n                            </button>\n                            <ul class=\"dropdown-menu\">\n                            \t<li ng-repeat=\"resultSize in config.filter.resultSizes\"><a href=\"\" ng-click=\"filter.setResultSize(resultSize)\">{{'GENERAL.RESULT-SIZES.' + resultSize.toString() | translate}}</a></li>\n                            </ul>\n                        </div>\n                        <button type=\"button\" class=\"btn btn-default\" ng-click=\"filter.toggleOrder()\">\n                        \t<i class=\"glyphicon\" ng-class=\"{'glyphicon-sort-by-attributes': filter.order == 'asc', 'glyphicon-sort-by-attributes-alt': filter.order == 'desc'}\"></i>\n                        </button>\n                    </div>\n                    <div class=\"btn-group btn-group-sm pull-right\">\n                    \t<button type=\"button\" class=\"btn btn-default dropdown-toggle\" data-toggle=\"dropdown\"\n                                translate=\"GENERAL.ACTION.SHOW-RESULTS\" translate-value-size=\"{{'GENERAL.RESULT-SIZES.' + filter.resultSize | translate}}\">\n                            &nbsp;\n                            <span class=\"caret\"></span>\n                        </button>\n                    \t<ul class=\"dropdown-menu\">\n                           <li ng-repeat=\"sort in filter.sortObjects\"><a href=\"\" ng-click=\"filter.setSort(sort)\">{{sort.name | translate}}</a></li>\n                        </ul>\n                    </div>\n                    <div class=\"btn-group btn-group-sm pull-right\">\n                        <a class=\"btn btn-default\" role=\"button\"\n                           title=\"{{'GENERAL.ACTION.REFRESH-LIST' | translate}}\"\n                           ng-click=\"filter.refresh();\">\n                            <i class=\"glyphicon glyphicon-refresh\"></i>\n                        </a>\n                    </div>\n                    <div class=\"pull-right loading\" ng-show=\"filter.loading\">\n                    \t<i class=\"glyphicon glyphicon-refresh\"></i>\n                    </div>\n                    <h2 translate=\"FORM-INSTANCES.TITLE\"></h2>\n                </div>\n\n                <div class=\"grid-wrapper\" id=\"forms\">\n                    <div class=\"grid-message\" ng-if=\"formInstancesData.size > 0\">\n                        <span>{{'FORM-INSTANCES.LIST-MESSAGE' | translate:formInstancesData}}</span>\n                    </div>\n                     <div class=\"grid-message\" ng-if=\"formInstancesData.size == 0\">\n                        <span>{{'FORM-INSTANCES.LIST-MESSAGE-EMPTY' | translate}}</span>\n                    </div>\n                    <div ng-grid=\"gridFormInstances\" class=\"gridStyle\" ng-if=\"gridFormInstances && formInstancesData.data\"/>\n                </div>\n            </div>\n        </div>\n        <div class=\"col-md-4\">\n\n            <!-- forms filters -->\n            <div class=\"component tip-left\">\n                <div class=\"title\">\n                    <div class=\"pull-right\">\n                        <a class=\"action\" ng-click=\"filter.clear()\" translate=\"GENERAL.ACTION.CLEAR-FILTERS\"></a>\n                    </div>\n                    <h2 translate=\"GENERAL.TITLE.FILTERS\"></h2>\n                </div>\n                <div class=\"section\" ng-if=\"filter.properties.nameLike !== undefined\">\n                    <div class=\"subtitle\"><label for=\"filter-nameLike\" translate=\"FORM-INSTANCES.FILTER.NAME\"></label> </div>\n                    <div class=\"input-group input-group-sm\">\n                        <input id=\"filter-nameLike\" type=\"text\" class=\"form-control\" value=\"\" ng-model=\"filter.properties.nameLike\" ng-change=\"filter.refreshDelayed()\">\n                    </div>\n                </div>\n                <div class=\"section\" ng-if=\"filter.properties.tenantId !== undefined\">\n                    <div class=\"subtitle\"><label for=\"filter-tenantId\" translate=\"APP-DEPLOYMENTS.FILTER.TENANTID\"></label> </div>\n                    <div class=\"input-group input-group-sm\">\n                        <input id=\"filter-tenantId\" type=\"text\" class=\"form-control\" value=\"\" number-input-check ng-model=\"filter.properties.tenantId\" ng-change=\"filter.refreshDelayed()\">\n                    </div>\n                </div>\n            </div>\n\n        </div>\n\n        </div>\n    </div>\n</div>"
  },
  {
    "path": "flowable-ui-web/admin/views/form-popup.html",
    "content": "<div class=\"modal-header-wrapper\">\n\t<div class=\"modal-header\">\n\t\t<div class=\"pull-right\">\n\t\t\t<a class=\"action\" ng-click=\"cancel()\">&times;\n\t\t\t\t{{'GENERAL.ACTION.CANCEL-AND-CLOSE' | translate}}</a>\n\t\t</div>\n\t\t<h2>{{'FORM.POPUP.TITLE' | translate}} '{{popup.formName}}'</h2>\n\t</div>\n</div>\n<div class=\"modal-body modal-body-medium\">\n\t<div class=\"container-fluid content decision-table\" ng-if=\"popup.currentForm\" auto-height offset=\"40\">\n\n\t\t<div style=\"padding-top: 10px;\" class=\"form-wrapper container-fluid form-preview\">\n\t\t\t<div class=\"form-center-pane\"\n\t\t\t\tng-if=\"popup.currentForm.tabs && popup.currentForm.tabs.length > 0\">\n\t\t\t\t<div class=\"content\">\n\t\t\t\t\t<div class=\"tabs clearfix\">\n\t\t\t\t\t\t<div style=\"min-width: 100px; text-align: center;\" class=\"tab\" ng-repeat=\"tab in popup.currentForm.tabs\"\n\t\t\t\t\t\t\tng-class=\"{'active': tab.id == activeFormTab.id}\">\n\t\t\t\t\t\t\t<a ng-click=\"formTabClicked(tab)\"> {{tab.title | translate}}&nbsp; </a>\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\n\n\t\t\t<div style=\"padding-top: 10px;\" ng-if=\"!activeFormTab || !activeFormTab.id || (activeFormTab && activeFormTab.id && activeFormTab.id === field.tab)\"\n\t\t\t\tng-repeat=\"field in popup.currentForm.fields\">\n\t\t\t\t<field-preview field=\"field\" custom-field-templates=\"popup.currentForm.customFieldTemplates\"></field-preview>\n\t\t\t</div>\n\n\t\t\t<div class=\"center out-come-buttons\"\n\t\t\t\tng-if=\"popup.currentForm.outcomes && popup.currentForm.outcomes.length > 0\">\n\t\t\t\t<button class=\"activiti-btn\" disabled=\"disabled\"\n\t\t\t\t\tng-repeat=\"outcome in popup.currentForm.outcomes\">{{outcome.name}}</button>\n\t\t\t</div>\n\t\t</div>\n\n\t</div>\n</div>\n\n<div class=\"modal-footer-wrapper\">\n\t<div class=\"modal-footer\">\n\t\t<div class=\"pull-right\">\n\t\t\t<button type=\"button\" class=\"btn btn-sm btn-default\" ng-click=\"cancel()\" ng-disabled=\"status.loading\" translate=\"GENERAL.ACTION.CLOSE\"></button>\n\t\t</div>\n\t</div>\n</div>\n"
  },
  {
    "path": "flowable-ui-web/admin/views/form-render-popup.html",
    "content": "<div class=\"modal-header-wrapper\">\n\t<div class=\"modal-header\">\n\t\t<div class=\"pull-right\">\n\t\t\t<a class=\"action\" ng-click=\"cancel()\">&times;\n\t\t\t\t{{'GENERAL.ACTION.CANCEL-AND-CLOSE' | translate}}</a>\n\t\t</div>\n\t\t<h2>{{'FORM.POPUP.TITLE' | translate}} '{{popup.formName}}'</h2>\n\t</div>\n</div>\n<div class=\"modal-body modal-body-medium\">\n\t<div class=\"container-fluid content decision-table\" ng-if=\"popup.currentForm\" auto-height offset=\"40\">\n\n\t\t<div style=\"padding-top: 10px;\" class=\"form-wrapper container-fluid form-popup\">\n\t\t\t<div class=\"form-center-pane\"\n\t\t\t\tng-if=\"popup.currentForm.tabs && popup.currentForm.tabs.length > 0\">\n\t\t\t\t<div class=\"content\">\n\t\t\t\t\t<div class=\"tabs clearfix\">\n\t\t\t\t\t\t<div style=\"min-width: 100px; text-align: center;\" class=\"tab\" ng-repeat=\"tab in popup.currentForm.tabs\"\n\t\t\t\t\t\t\tng-class=\"{'active': tab.id == activeFormTab.id}\">\n\t\t\t\t\t\t\t<a ng-click=\"formTabClicked(tab)\"> {{tab.title | translate}}&nbsp; </a>\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\n\n\t\t\t<div style=\"padding-top: 10px;\" ng-if=\"!activeFormTab || !activeFormTab.id || (activeFormTab && activeFormTab.id && activeFormTab.id === field.tab)\"\n\t\t\t\tng-repeat=\"field in popup.currentForm.fields\">\n\t\t\t\t<form-element field=\"field\" custom-field-templates=\"popup.currentForm.customFieldTemplates\"></form-element>\n\t\t\t</div>\n\n\t\t\t<div class=\"center out-come-buttons\" ng-if=\"popup.currentForm.selectedOutcome\">\n\t\t\t\t<button class=\"activiti-btn\" disabled=\"disabled\">{{popup.currentForm.selectedOutcome}}</button>\n\t\t\t</div>\n\t\t</div>\n\n\t</div>\n</div>\n\n<div class=\"modal-footer-wrapper\">\n\t<div class=\"modal-footer\">\n\t\t<div class=\"pull-right\">\n\t\t\t<button type=\"button\" class=\"btn btn-sm btn-default\" ng-click=\"cancel()\" ng-disabled=\"status.loading\" translate=\"GENERAL.ACTION.CLOSE\"></button>\n\t\t</div>\n\t</div>\n</div>\n"
  },
  {
    "path": "flowable-ui-web/admin/views/job-delete-popup.html",
    "content": "<div class=\"modal-header-wrapper\">\n\t<div class=\"modal-header\">\n\t\t<div class=\"pull-right\">\n            <a class=\"action\" ng-click=\"cancel()\">&times; {{'GENERAL.ACTION.CANCEL-AND-CLOSE' | translate}}</a>\n        </div>\n\t\t<h2>{{'JOB.POPUP.DELETE-JOB.TITLE' | translate:job}}</h2>\t\n\t</div>\n</div>\n<div class=\"modal-body\">\n\t<p>{{'JOB.POPUP.DELETE-JOB.MESSAGE' | translate:job}}</p>\t\n</div>\n\n<div class=\"modal-footer-wrapper\">\n\t<div class=\"modal-footer\">\n\t\t<div class=\"pull-right\">\n\t       <button type=\"button\" class=\"btn btn-sm btn-default\" ng-click=\"cancel()\" ng-disabled=\"status.loading\"\n\t           translate=\"GENERAL.ACTION.CANCEL\">\n\t       </button>\n\t       <button type=\"button\" class=\"btn btn-sm btn-default\" ng-click=\"ok()\" ng-disabled=\"status.loading\"\n\t       \t   translate=\"JOB.POPUP.DELETE-JOB.CONFIRM\">\n\t       </button>\n\t\t</div>\n        <loading-indicator></loading-indicator>\n</div>\n</div>"
  },
  {
    "path": "flowable-ui-web/admin/views/job.html",
    "content": "\n<div class=\"container\" id=\"detail-container\">\n\t<div class=\"row\">\n\t\t<div class=\"col-md-9\">\n\t\t\t<div class=\"component\" ng-show=\"job\">\n\t\t\t\t<div class=\"title\">\n\t\t\t\t\t<div class=\"pull-right\">\n\t\t\t\t\t\t<a ng-click=\"returnToList()\" class=\"action\">&larr; {{'GENERAL.ACTION.RETURN-TO-LIST' | translate}}</a>\n\t\t\t\t\t</div>\n\t\t\t\t\t<h2>{{'JOB.TITLE.MAIN' | translate:job}}</h2>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"property-wrapper\">\n\t\t\t\t\t<table>\n\t\t\t\t\t\t<tr class=\"property\">\n\t\t\t\t\t\t\t<td class=\"property-name\" translate=\"JOB.ID\"></td>\n\t\t\t\t\t\t\t<td>{{job.id}}</td>\n\t\t\t\t\t\t\t<td class=\"property-name\"><span class=\"glyphicon glyphicon-time\"></span> {{'JOB.DUEDATE' | translate}}</td>\n\t\t\t\t\t\t\t<td>{{job.dueDate | dateformat}}</td>\n\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t<tr class=\"property\">\n\t\t\t\t\t\t\t<td class=\"property-name\" ng-if=\"job.processInstanceId\"></span> {{'JOB.PROCESS-INSTANCE' | translate}}</td>\n\t\t\t\t\t\t\t<td ng-if=\"job.processInstanceId\"><a ng-click=\"openProcessInstance(job.processInstanceId)\"><i class=\"glyphicon glyphicon-zoom-in\"></i> {{job.processInstanceId | empty}}</a></td>\n\t\t\t\t\t\t\t<td class=\"property-name\" translate=\"JOB.EXECUTION-ID\"></td>\n\t\t\t\t\t\t\t<td>{{job.executionId}}</td>\n\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t<tr class=\"property\">\n\t\t\t\t\t\t\t<td class=\"property-name\" translate=\"JOB.RETRIES-LEFT\"></td>\n\t\t\t\t\t\t\t<td>{{job.retries}}</td>\n\t\t\t\t\t\t\t<td class=\"property-name\" ng-if=\"job.processDefinitionId\"></span> {{'JOB.PROCESS-DEFINITION' | translate}}</td>\n\t\t\t\t\t\t\t<td ng-if=\"job.processDefinitionId\"><a ng-click=\"openProcessDefinition(job.processDefinitionId)\"><i class=\"glyphicon glyphicon-zoom-in\"></i> {{job.processDefinitionId | empty}}</a></td>\n\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t<tr class=\"property\">\n                            <td class=\"property-name\" translate=\"JOB.TENANT-ID\"></td>\n                            <td>{{job.tenantId}}</td>\n                        </tr>\n\t\t\t\t\t</table>\n\t\t\t\t</div>\n\t\t\t\t\n\t\t\t\t\n\t\t\t\t<div ng-if=\"job.exceptionMessage\">\n\t\t\t\t\t<div class=\"title\">\n\t\t\t\t\t\t<h3 translate=\"JOB.TITLE.EXCEPTION\"></h3>\n\t\t\t\t\t</div>\n\t\t\t\t\t<div class=\"property-wrapper\">\n\t\t\t\t\t\t<table>\n\t\t\t\t\t\t\t<tr class=\"property\">\n\t\t\t\t\t\t\t\t<td class=\"property-name\">Exception during last execution:</td>\n\t\t\t\t\t\t\t\t<td>{{job.exceptionMessage}}</td>\n\t\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t</table>\n\t\t\t\t\t</div>\t\n\t\t\t\t\t<pre>{{job.exceptionStack}}</pre>\t\t\t\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</div>\n\t\t<div class=\"col-md-3\">\n\t\t\t<div class=\"component tip-left\">\n\t\t\t\t<div class=\"title\">\n\t\t\t\t\t<h2 translate=\"GENERAL.TITLE.ACTIONS\"></h2>\n\t\t\t\t</div>\n\t\t\t\t<ul class=\"list-group\" ng-if=\"jobType.param == 'executableJob'\">\n\t\t\t\t\t  <li>\n\t\t\t\t\t    <button type=\"button\" class=\"btn btn-sm btn-default\" ng-click=\"executeJob()\">\n\t\t\t\t\t\t\t<i class=\"glyphicon glyphicon-play\"></i> {{'JOB.ACTIONS.EXECUTE' | translate}}\n\t\t\t\t\t    </button>\n\t\t\t\t\t  </li>\n\t\t\t\t</ul>\n\t\t\t\t<ul class=\"list-group\" ng-if=\"jobType.param == 'timerJob' || jobType.param == 'deadletterJob'\">\n\t\t\t\t\t  <li>\n\t\t\t\t\t    <button type=\"button\" class=\"btn btn-sm btn-default\" ng-click=\"moveJob()\">\n\t\t\t\t\t\t\t<i class=\"glyphicon glyphicon-play\"></i> {{'JOB.ACTIONS.MOVE' | translate}}\n\t\t\t\t\t    </button>\n\t\t\t\t\t  </li>\n\t\t\t\t</ul>\n\t\t\t\t<div class=\"seperator\"></div>\n\t\t\t\t<ul class=\"list-group\">\n\t\t\t\t\t  \n\t\t\t\t\t  <li>\n\t\t\t\t\t    <button type=\"button\" class=\"btn btn-sm btn-default btn-danger\" ng-click=\"deleteJob()\">\n\t\t\t\t\t\t\t<i class=\"glyphicon glyphicon-remove\"></i> {{'JOB.ACTIONS.DELETE' | translate}}\n\t\t\t\t\t    </button>\n\t\t\t\t\t  </li>\n\t\t\t\t</ul>\n\t\t\t</div>\n\t\t</div>\n\t</div>\n</div>\n"
  },
  {
    "path": "flowable-ui-web/admin/views/jobs.html",
    "content": "<!-- LIST PAGE -->\n<div class=\"container\">\n    <div class=\"row\">\n        <div class=\"col-md-8\">\n            <div class=\"component\">\n                <div class=\"title\">\n                    <div class=\"btn-group btn-group-sm pull-right\">\n                        <div class=\"btn-group btn-group-sm\">\n                            <button type=\"button\" class=\"btn btn-default dropdown-toggle\" data-toggle=\"dropdown\"\n                                    translate=\"GENERAL.ACTION.SHOW-RESULTS\" translate-value-size=\"{{'GENERAL.RESULT-SIZES.' + filter.resultSize | translate}}\">\n                                &nbsp;\n                                <span class=\"caret\"></span>\n                            </button>\n                            <ul class=\"dropdown-menu\">\n                            \t<li ng-repeat=\"resultSize in config.filter.resultSizes\"><a href=\"\" ng-click=\"filter.setResultSize(resultSize)\">{{'GENERAL.RESULT-SIZES.' + resultSize.toString() | translate}}</a></li>\n                            </ul>\n                        </div>\n                        <button type=\"button\" class=\"btn btn-default\" ng-click=\"filter.toggleOrder()\">\n                        \t<i class=\"glyphicon\" ng-class=\"{'glyphicon-sort-by-attributes': filter.order == 'asc', 'glyphicon-sort-by-attributes-alt': filter.order == 'desc'}\"></i>\n                        </button>\n                    </div>\n                    <div class=\"btn-group btn-group-sm pull-right\">\n                    \t<button type=\"button\" class=\"btn btn-default dropdown-toggle\" data-toggle=\"dropdown\"\n                                translate=\"GENERAL.ACTION.SHOW-RESULTS\" translate-value-size=\"{{'GENERAL.RESULT-SIZES.' + filter.resultSize | translate}}\">\n                            &nbsp;\n                            <span class=\"caret\"></span>\n                        </button>\n                    \t<ul class=\"dropdown-menu\">\n                           <li ng-repeat=\"sort in filter.sortObjects\"><a href=\"\" ng-click=\"filter.setSort(sort)\">{{sort.name | translate}}</a></li>\n                        </ul>\n                    </div>\n                    <div class=\"btn-group btn-group-sm pull-right\">\n                        <a class=\"btn btn-default\" role=\"button\"\n                           title=\"{{'GENERAL.ACTION.REFRESH-LIST' | translate}}\"\n                           ng-click=\"filter.refresh();\">\n                            <i class=\"glyphicon glyphicon-refresh\"></i>\n                        </a>\n                    </div>\n                    <div class=\"pull-right loading\" ng-show=\"filter.loading\">\n                    \t<i class=\"glyphicon glyphicon-refresh\"></i>\n                    </div>\n\n                    <h2 translate=\"JOBS.TITLE\"></h2>\n                </div>\n\n                <div class=\"grid-wrapper\" id=\"jobs\">\n                    <div class=\"grid-message\" ng-if=\"jobData.size > 0\">\n                         <span>{{'JOBS.LIST-MESSAGE' | translate:jobs}}</span>\n                    </div>\n                     <div class=\"grid-message\" ng-if=\"jobData.size == 0\">\n                        <span>{{'JOBS.LIST-MESSAGE-EMPTY' | translate}}</span>\n                    </div>\n                    <div ng-grid=\"gridJobs\" class=\"gridStyle\" ng-if=\"gridJobs && jobData.data\"/>\n                </div>\n            </div>\n        </div>\n\n\t\t<!-- Task filters -->\n\t\t<div class=\"col-md-4\">\n            <div class=\"component tip-left\">\n                <div class=\"title\">\n                    <div class=\"btn-group btn-group-sm pull-right\" ng-show=\"filter.supportedProperties.length > 0\">\n                        <button type=\"button\" class=\"btn btn-default\" data-toggle=\"dropdown\">\n                            <i class=\"glyphicon glyphicon-plus\"></i>\n                        </button>\n                        <ul class=\"dropdown-menu\">\n                            <li ng-repeat=\"prop in filter.supportedProperties\"><a href=\"\" ng-click=\"filter.addProperty(prop)\">{{prop.name | translate}}</a></li>\n                        </ul>\n                    </div>\n                    <div class=\"pull-right\">\n                        <a class=\"action\" ng-click=\"filter.clear()\" translate=\"GENERAL.ACTION.CLEAR-FILTERS\"></a>\n                    </div>\n                    <h2 translate=\"GENERAL.TITLE.FILTERS\"></h2>\n                </div>\n                <div class=\"section\">\n                    <div class=\"subtitle\"><label for=\"filter-jobtype\" translate=\"JOBS.FILTER.JOBTYPE.LABEL\"></label> </div>\n                    <div>\n                        <select ui-select2\n                                ng-model=\"filter.jobType\"\n                         \t\tng-change=\"jobTypeFilterChanged()\"\n                         \t\tstyle=\"min-width:250px\">\n                            <option value=\"executableJob\">{{'JOBS.FILTER.JOBTYPE.EXECUTABLE-JOB' | translate}}</option>\n                            <option value=\"timerJob\">{{'JOBS.FILTER.JOBTYPE.TIMER-JOB' | translate}}</option>\n                            <option value=\"suspendedJob\">{{'JOBS.FILTER.JOBTYPE.SUSPENDED-JOB' | translate}}</option>\n                            <option value=\"deadletterJob\">{{'JOBS.FILTER.JOBTYPE.DEADLETTER-JOB' | translate}}</option>\n                         </select>\n                    </div>\n                </div>\n\t            <div class=\"section\">\n                    <div class=\"subtitle\"><label for=\"filter-processdefinition\" translate=\"JOBS.FILTER.PROCESS-DEFINITION\"></label> </div>\n                    <div>\n                        <select ui-select2\n                                data-placeholder=\"{{'JOBS.FILTER.ALL-PROCESS-DEFINITIONS' | translate}}\"\n                         \t\tng-model=\"filter.processDefinition\"\n                         \t\tng-change=\"processDefinitionFilterChanged()\"\n                         \t\tstyle=\"min-width:250px\">\n                            <option value=\"\"></option>\n                            <option value=\"-1\">{{'JOBS.FILTER.ALL-PROCESS-DEFINITIONS' | translate}}</option>\n                         \t<option ng-title=\"123\" ng-repeat=\"processDefinition in processDefinitionsCache.data\" value=\"{{processDefinition.id}}\">{{processDefinition.name ? processDefinition.name : processDefinition.key}} (v{{processDefinition.version}})</option>\n                         </select>\n                    </div>\n                </div>\n                <div class=\"section\" ng-if=\"filter.properties.processInstanceId !== undefined\">\n                    <div class=\"subtitle\"><label for=\"filter-processInstanceId\" translate=\"JOBS.FILTER.PROCESS-INSTANCE-ID\"></label> </div>\n                    <div class=\"input-group input-group-sm\">\n                        <input id=\"filter-processInstanceId\" type=\"text\" class=\"form-control\" value=\"\" ng-model=\"filter.properties.processInstanceId\" ng-change=\"filter.refreshDelayed()\">\n                    </div>\n                </div>\n                <div class=\"section\" ng-if=\"filter.properties.tenantIdLike !== undefined\">\n                    <div class=\"subtitle\"><label for=\"filter-tenantId\" translate=\"JOBS.FILTER.TENANT-ID\"></label> </div>\n                    <div class=\"input-group input-group-sm\">\n                        <input id=\"filter-tenantId\" type=\"text\" class=\"form-control\" value=\"\" ng-model=\"filter.properties.tenantIdLike\" ng-change=\"filter.refreshDelayed()\">\n                    </div>\n                </div>\n                <div class=\"section\" ng-if=\"filter.properties.dueBefore !== undefined\">\n                  <div class=\"subtitle\"><label for=\"filter-dueBefore\" translate=\"JOBS.FILTER.DUE-BEFORE\"></label> </div>\n               \t  <div class=\"input-group input-group-sm\">\n               \t  \t<span class=\"input-group-addon\"><span class=\"glyphicon glyphicon-time\"></span></span>\n                      <input id=\"filter-dueBefore\" type=\"text\" class=\"form-control\"\n                             ng-model=\"filter.properties.dueBefore\"\n                             ng-change=\"filter.refreshDelayed()\"\n                             datepicker-popup=\"yyyy/MM/dd\"\n                             is-open=\"dueBeforePicker.isOpen\"\n                             ng-click=\"dueBeforePicker.isOpen=true\"/>\n\t              </div>\n\t            </div>\n                <div class=\"section\" ng-if=\"filter.properties.dueAfter !== undefined\">\n\t              <div class=\"subtitle\"><label for=\"filter-dueAfter\" translate=\"JOBS.FILTER.DUE-AFTER\"></label> </div>\n               \t  <div class=\"input-group input-group-sm\">\n               \t  \t<span class=\"input-group-addon\"><span class=\"glyphicon glyphicon-time\"></span></span>\n\t              \t<input id=\"filter-dueAfter\" type=\"text\" class=\"form-control\"\n                           ng-model=\"filter.properties.dueAfter\"\n                           ng-change=\"filter.refreshDelayed()\"\n                           datepicker-popup=\"dd/MM/yyyy\"\n                           is-open=\"dueAfterPicker.isOpen\"\n                           ng-click=\"dueAfterPicker.isOpen=true\"/>\n\t              </div>\n\t            </div>\n                <div class=\"section\" ng-if=\"filter.properties.withException !== undefined\">\n\t              <div class=\"subtitle\"><label for=\"filter-withException\" translate=\"JOBS.FILTER.EXCEPTION\"></label> </div>\n               \t  <div class=\"input-group input-group-sm\">\n               \t  \t<input type=\"checkbox\" id=\"filter-withException\" ng-model=\"filter.properties.withException\" ng-change=\"filter.refresh()\" />&nbsp;<span class=\"check\" translate=\"JOBS.FILTER.EXCEPTION-HELP\"></span>\n\t              </div>\n\t            </div>\n            </div>\n        </div>\n    </div>\n</div>\n"
  },
  {
    "path": "flowable-ui-web/admin/views/process-definition-diagram-popup.html",
    "content": "<div class=\"modal-header-wrapper\">\n\t<div class=\"modal-header\">\n\t\t<div class=\"pull-right\">\n            <a class=\"action\" ng-click=\"cancel()\">&times; {{'GENERAL.ACTION.CANCEL-AND-CLOSE' | translate}}</a>\n        </div>\n        <h2>{{'PROCESS-DEFINITION.POPUP.SHOW-PROCESS-MODEL.TITLE' | translate}} '{{model.name &amp;&amp; model.name || model.key}}'\n            <span id=\"navigationTree\">| <a href=\"javascript:_navigateTo('FLOWABLE_ROOT_PROCESS')\">Root</a></span>\n        </h2>\t\n\t</div>\n</div>\n<div class=\"modal-body modal-body-medium\">\n\t<div id=\"bpmnModel\" style=\"margin-left:auto;margin-right:auto\"></div>\n</div>\n\n<div class=\"modal-footer-wrapper\">\n\t<div class=\"modal-footer\">\n\t\t<div class=\"pull-right\">\n\t       <button type=\"button\" class=\"btn btn-sm btn-default\" ng-click=\"cancel()\" ng-disabled=\"status.loading\"\n\t\t       \ttranslate=\"GENERAL.ACTION.CLOSE\">\n\t       \t</button>\n\t\t</div>\n\t</div>\n</div>\t"
  },
  {
    "path": "flowable-ui-web/admin/views/process-definition-edit-category-popup.html",
    "content": "<div class=\"modal-header-wrapper\">\n\t<div class=\"modal-header\">\n\t\t<div class=\"pull-right\">\n            <a class=\"action\" ng-click=\"cancel()\">&times; {{'GENERAL.ACTION.CLOSE' | translate}}</a>\n        </div>\n\t\t<h2>{{'PROCESS-DEFINITION.POPUP.EDIT-CATEGORY.TITLE' | translate}} '{{model.name &amp;&amp; model.name || model.key}}'</h2>\t\n\t</div>\n</div>\n<div class=\"modal-body\">\n\t<p translate=\"PROCESS-DEFINITION.POPUP.EDIT-CATEGORY.MESSAGE\"></p>\n\t<div class=\"input-group input-group-sm\">\n\t \t <label for=\"user\" translate=\"PROCESS-DEFINITION.POPUP.EDIT-CATEGORY.CATEGORY\"></label>\n         <input id=\"user\" type=\"text\" class=\"form-control\" value=\"\" ng-model=\"model.category\" placeholder=\"{{'PROCESS-DEFINITION.POPUP.EDIT-CATEGORY.CATEGORY-PLACEHOLDER' | translate}}\"/>\n    </div>\n</div>\n\n<div class=\"modal-footer-wrapper\">\n\t<div class=\"modal-footer\">\n\t\t<div class=\"pull-right\">\n\t       <button type=\"button\" class=\"btn btn-sm btn-default\" ng-click=\"cancel()\" ng-disabled=\"status.loading\"\n\t       \ttranslate=\"GENERAL.ACTION.CANCEL\">\n\t       \t</button>\n\t       <button type=\"button\" class=\"btn btn-sm btn-default\" ng-click=\"ok()\" ng-disabled=\"status.loading\"\n\t        translate=\"PROCESS-DEFINITION.POPUP.EDIT-CATEGORY.CONFIRM\">\n\t       </button>\n\t\t</div>\n        <loading-indicator></loading-indicator>\n</div>\n</div>"
  },
  {
    "path": "flowable-ui-web/admin/views/process-definition.html",
    "content": "<div class=\"container\" id=\"detail-container\">\n\t<div class=\"row\">\n\t\t<div class=\"col-md-9\">\n\t\t\t<div class=\"component\" ng-show=\"definition\">\n\t\t\t\t<div class=\"title\">\n\t\t\t\t\t<div class=\"pull-right\">\n\t\t\t\t\t\t<a ng-click=\"returnToList()\" class=\"action\">&larr; {{'GENERAL.ACTION.RETURN-TO-LIST' | translate}}</a>\n\t\t\t\t\t</div>\n\t\t\t\t\t<h2>{{definition.name &amp;&amp; definition.name +\" - \" || \"\"}}{{definition.id}}</h2>\n\t\t\t\t</div>\n\n\t\t\t\t<div class=\"property-wrapper\">\n\t\t\t\t\t<table>\n\t\t\t\t\t\t<tr class=\"property\">\n\t\t\t\t\t\t\t<td class=\"property-name\" translate=\"PROCESS-DEFINITION.ID\"></td>\n\t\t\t\t\t\t\t<td>{{definition.id}}</td>\n\t\t\t\t\t\t\t<td class=\"property-name\" translate=\"PROCESS-DEFINITION.VERSION\"></td>\n\t\t\t\t\t\t\t<td>{{definition.version}}</td>\n\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t<tr class=\"property\">\n\t\t\t\t\t\t\t<td class=\"property-name\" translate=\"PROCESS-DEFINITION.NAME\"></td>\n\t\t\t\t\t\t\t<td>{{definition.name | empty}}</td>\n\t\t\t\t\t\t\t<td class=\"property-name\" translate=\"PROCESS-DEFINITION.KEY\"></td>\n\t\t\t\t\t\t\t<td>{{definition.key}}</td>\n\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t<tr class=\"property\">\n\t\t\t\t\t\t\t<td class=\"property-name\" translate=\"PROCESS-DEFINITION.CATEGORY\"></td>\n\t\t\t\t\t\t\t<td>{{definition.category | empty}}</td>\n\t\t\t\t\t\t\t<td class=\"property-name\" translate=\"PROCESS-DEFINITION.DESCRIPTION\"></td>\n\t\t\t\t\t\t\t<td>{{definition.description | empty}}</td>\n\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t<tr class=\"property\">\n\t\t\t\t\t\t\t<td class=\"property-name\" translate=\"PROCESS-DEFINITION.DEPLOYMENT\"></td>\n\t\t\t\t\t\t\t<td><a ng-click=\"openDeployment(definition.deploymentId)\"><i class=\"glyphicon glyphicon-zoom-in\"></i> {{definition.deploymentId}}</a></td>\n\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t<tr class=\"property\">\n\t\t\t\t\t\t\t<td class=\"property-name\" translate=\"PROCESS-DEFINITION.START-FORM-DEFINED\"></td>\n\t\t\t\t\t\t\t<td>{{definition.startFormDefined &amp;&amp; ('GENERAL.YES' | translate) || ('GENERAL.NO' | translate)}}<span ng-if=\"definition.startFormDefined\"> - <a ng-click=\"openStartForm()\"><i class=\"glyphicon glyphicon-zoom-in\"></i> {{startForm.id}}</a></span></td>\n\t\t\t\t\t\t\t<td class=\"property-name\" translate=\"PROCESS-DEFINITION.GRAPHICAL-NOTATION-DEFINED\"></td>\n\t\t\t\t\t\t\t<td>\n\t\t\t\t\t\t\t\t{{definition.graphicalNotationDefined &amp;&amp; ('GENERAL.YES' | translate) || ('GENERAL.NO' | translate)}}\n\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t<tr class=\"property\">\n                            <td class=\"property-name\" translate=\"PROCESS-DEFINITION.TENANT\"></td>\n                            <td>{{definition.tenantId | empty}}</td>\n                            <td class=\"property-name\" translate=\"PROCESS-DEFINITION.SUSPENDED\"></td>\n                            <td>{{definition.suspended &amp;&amp; ('GENERAL.YES' | translate) || ('GENERAL.NO' | translate)}}</td>\n                        </tr>\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<div class=\"col-md-3\">\n\t\t\t<div class=\"component tip-left\">\n\t\t\t\t<div class=\"title\">\n\t\t\t\t\t<h2 translate=\"GENERAL.TITLE.ACTIONS\"></h2>\n\t\t\t\t</div>\n\t\t\t\t<ul class=\"list-group\">\n\t\t\t\t\t  <li ng-show=\"definition.graphicalNotationDefined\">\n\t\t\t\t\t    <button type=\"button\" class=\"btn btn-sm btn-default\" ng-click=\"showProcessDiagram()\">\n\t\t\t\t\t\t\t<i class=\"glyphicon glyphicon-zoom-in\"></i>{{'PROCESS-DEFINITION.ACTION.SHOW-DIAGRAM' | translate}}\n\t\t\t\t\t    </button>\n\t\t\t\t\t  </li>\n\t\t\t\t\t  <li>\n\t\t\t\t\t    <button type=\"button\" class=\"btn btn-sm btn-default\" ng-click=\"editCategory()\">\n\t\t\t\t\t\t\t<i class=\"glyphicon glyphicon-pencil\"></i>{{'PROCESS-DEFINITION.ACTION.EDIT-CATEGORY' | translate}}\n\t\t\t\t\t    </button>\n\t\t\t\t\t  </li>\n\t\t\t\t</ul>\n\t\t\t</div>\n\t\t</div>\n\t</div>\n\t<div class=\"row\">\n\t\t<div class=\"col-md-9\">\n\t\t\t<div class=\"component\">\n\t\t\t\t<div class=\"tabs-wrapper\">\n\t\t\t\t\t<div class=\"pull-right\">\n\t\t\t\t\t\t<a ng-click=\"showAllProcesses()\" class=\"action\" ng-show=\"tabData.activeTab == tabData.tabs[0].id\"><i class=\"glyphicon glyphicon-zoom-in\"></i> {{'PROCESS-DEFINITION.ACTION.SHOW-ALL-PROCESSES' | translate}}</a>\n\t\t\t\t\t\t<a ng-click=\"showAllJobs()\" class=\"action\" ng-show=\"tabData.activeTab == tabData.tabs[1].id\"><i class=\"glyphicon glyphicon-zoom-in\"></i> {{'PROCESS-DEFINITION.ACTION.SHOW-ALL-JOBS' | translate}}</a>\n\t\t\t\t\t</div>\n\t\t       \t\t<div class=\"tabs clearfix\">\n\t\t       \t\t\t<div class=\"tab\" ng-repeat=\"tab in tabData.tabs\" ng-class=\"{'active': tabData.activeTab == tab.id}\">\n\t\t       \t\t\t\t<a ng-click=\"tabData.activeTab = tab.id\">\n\t\t       \t\t\t\t\t{{tab.name | translate:node}}&nbsp;\n\t\t    \t\t\t\t\t<span class=\"badge\" ng-if=\"tab.info != undefined\">{{tab.info}}</span>\n\t\t    \t\t\t\t</a>\n\t\t       \t\t\t</div>\n\t\t       \t\t</div>\n\t\t        \t<div class=\"title\"></div>\n\n\t\t        \t<div class=\"grid-wrapper\" ng-if=\"processInstances && tabData.activeTab == tabData.tabs[0].id\" >\n\t\t\t\t\t\t<div class=\"grid-message\" ng-if=\"processInstances.size > 0\">\n\t                        <span>{{'PROCESS-DEFINITION.PROCESS-INSTANCES-SIZE' | translate:processInstances}}</span>\n                            <span ng-if=\"processInstances.size < processInstances.total\">{{'PROCESS-DEFINITION.PROCESS-INSTANCES-SHOWING' | translate:processInstances}}</span>\n\t                    </div>\n\t                     <div class=\"grid-message\" ng-if=\"processInstances.size == 0\">\n\t                        <span>{{'PROCESS-DEFINITION.PROCESS-INSTANCES-EMPTY' | translate}}</span>\n\t                    </div>\n\t\t\t\t\t\t<div ng-grid=\"gridProcessInstances\" class=\"gridStyle\" ng-if=\"processInstances\" ng-show=\"processInstances.size > 0\"></div>\n\t\t\t\t\t</div>\n\n\t\t\t\t\t<div class=\"grid-wrapper grid-wrapper-compact\" ng-if=\"jobs && tabData.activeTab == tabData.tabs[1].id\">\n\t\t\t\t\t\t<div class=\"grid-message\" ng-if=\"jobs.size > 0\">\n\t                        <span>{{'PROCESS-DEFINITION.JOBS-SIZE' | translate:jobs}}</span>\n\t                    </div>\n\t                     <div class=\"grid-message\" ng-if=\"jobs.size == 0\">\n\t                        <span>{{'PROCESS-DEFINITION.JOBS-EMPTY' | translate}}</span>\n\t                    </div>\n\t\t\t\t\t\t<div ng-grid=\"gridJobs\" class=\"gridStyle\" ng-if=\"jobs\" ng-show=\"jobs.size > 0\"></div>\n\t\t\t\t\t</div>\n\t\t\t\t\t\n\t\t\t\t\t<div class=\"grid-wrapper grid-wrapper-compact\" ng-if=\"decisionTables && tabData.activeTab == tabData.tabs[2].id\">\n\t\t\t\t\t\t<div class=\"grid-message\" ng-if=\"decisionTables.length > 0\">\n\t                        <span>{{'PROCESS-DEFINITION.DECISION-TABLES-SIZE' | translate:decisionTables}}</span>\n\t                    </div>\n\t                     <div class=\"grid-message\" ng-if=\"decisionTables.length == 0\">\n\t                        <span>{{'PROCESS-DEFINITION.DECISION-TABLES-EMPTY' | translate}}</span>\n\t                    </div>\n\t\t\t\t\t\t<div ng-grid=\"gridDecisionTables\" class=\"gridStyle\" ng-if=\"decisionTables\" ng-show=\"decisionTables.length > 0\"></div>\n\t\t\t\t\t</div>\n\t\t\t\t\t\n\t\t\t\t\t<div class=\"grid-wrapper grid-wrapper-compact\" ng-if=\"formDefinitions && tabData.activeTab == tabData.tabs[3].id\">\n\t\t\t\t\t\t<div class=\"grid-message\" ng-if=\"formDefinitions.length > 0\">\n\t                        <span>{{'PROCESS-DEFINITION.FORM-DEFINITIONS-SIZE' | translate:formDefinitions}}</span>\n\t                    </div>\n\t                     <div class=\"grid-message\" ng-if=\"formDefinitions.length == 0\">\n\t                        <span>{{'PROCESS-DEFINITION.FORM-DEFINITIONS-EMPTY' | translate}}</span>\n\t                    </div>\n\t\t\t\t\t\t<div ng-grid=\"gridFormDefinitions\" class=\"gridStyle\" ng-if=\"formDefinitions\" ng-show=\"formDefinitions.length > 0\"></div>\n\t\t\t\t\t</div>\n\n\t        \t</div>\n\t\t\t</div>\n\t\t</div>\n\t</div>\n</div>\n<div>\n</div>\n"
  },
  {
    "path": "flowable-ui-web/admin/views/process-definitions.html",
    "content": "<!-- LIST PAGE -->\n<div class=\"container\" id=\"list-container\">\n    <div class=\"row\">\n        <div class=\"col-md-8\">\n            <div class=\"component\">\n                <div class=\"title\">\n                    <div class=\"btn-group btn-group-sm pull-right\">\n                        <div class=\"btn-group btn-group-sm\">\n                            <button type=\"button\" class=\"btn btn-default dropdown-toggle\" data-toggle=\"dropdown\"\n                                    translate=\"GENERAL.ACTION.SHOW-RESULTS\" translate-value-size=\"{{'GENERAL.RESULT-SIZES.' + filter.resultSize | translate}}\">\n                                &nbsp;\n                                <span class=\"caret\"></span>\n                            </button>\n                            <ul class=\"dropdown-menu\">\n                            \t<li ng-repeat=\"resultSize in config.filter.resultSizes\"><a href=\"\" ng-click=\"filter.setResultSize(resultSize)\">{{'GENERAL.RESULT-SIZES.' + resultSize.toString() | translate}}</a></li>\n                            </ul>\n                        </div>\n                        <button type=\"button\" class=\"btn btn-default\" ng-click=\"filter.toggleOrder()\">\n                        \t<i class=\"glyphicon\" ng-class=\"{'glyphicon-sort-by-attributes': filter.order == 'asc', 'glyphicon-sort-by-attributes-alt': filter.order == 'desc'}\"></i>\n                        </button>\n                    </div>\n                    <div class=\"btn-group btn-group-sm pull-right\">\n                    \t<button type=\"button\" class=\"btn btn-default dropdown-toggle\" data-toggle=\"dropdown\"\n                                translate=\"GENERAL.ACTION.SHOW-RESULTS\" translate-value-size=\"{{'GENERAL.RESULT-SIZES.' + filter.resultSize | translate}}\">\n                            &nbsp;\n                            <span class=\"caret\"></span>\n                        </button>\n                    \t<ul class=\"dropdown-menu\">\n                           <li ng-repeat=\"sort in filter.sortObjects\"><a href=\"\" ng-click=\"filter.setSort(sort)\">{{sort.name | translate}}</a></li>\n                        </ul>\n                    </div>\n                    <div class=\"btn-group btn-group-sm pull-right\">\n                        <a class=\"btn btn-default\" role=\"button\"\n                           title=\"{{'GENERAL.ACTION.REFRESH-LIST' | translate}}\"\n                           ng-click=\"filter.refresh();\">\n                            <i class=\"glyphicon glyphicon-refresh\"></i>\n                        </a>\n                    </div>\n                    <div class=\"pull-right loading\" ng-show=\"filter.loading\">\n                    \t<i class=\"glyphicon glyphicon-refresh\"></i>\n                    </div>\n                    <h2>{{'PROCESS-DEFINITIONS.TITLE.MAIN' | translate:job}}</h2>\n                </div>\n\n                <div class=\"grid-wrapper\" id=\"process-instances\">\n                    <div class=\"grid-message\" ng-if=\"processDefinitionsData.size > 0\">\n                         <span>{{'PROCESS-DEFINITIONS.LIST-MESSAGE' | translate:processDefinitionsData}}</span>\n                    </div>\n                     <div class=\"grid-message\" ng-if=\"processDefinitionsData.size == 0\">\n                        <span>{{'PROCESS-DEFINITIONS.LIST-MESSAGE-EMPTY' | translate}}</span>\n                    </div>\n                    <div ng-grid=\"gridDefinitions\" class=\"gridStyle\" ng-if=\"gridDefinitions && processDefinitionsData.data\" />\n                </div>\n            </div>\n        </div>\n        <div class=\"col-md-4\">\n\n            <!-- FILTERS -->\n            <div class=\"component tip-left\">\n                <div class=\"title\">\n                    <div class=\"btn-group btn-group-sm pull-right\">\n                        <button type=\"button\" class=\"btn btn-default\" data-toggle=\"dropdown\" ng-show=\"filter.supportedProperties.length > 0\">\n                            <i class=\"glyphicon glyphicon-plus\"></i>\n                        </button>\n                        <ul class=\"dropdown-menu\">\n                            <li ng-repeat=\"prop in filter.supportedProperties\"><a href=\"\" ng-click=\"filter.addProperty(prop)\">{{prop.name | translate}}</a></li>\n                        </ul>\n                    </div>\n                    <div class=\"pull-right\">\n                        <a class=\"action\" ng-click=\"filter.clear()\" translate=\"GENERAL.ACTION.CLEAR-FILTERS\"></a>\n                    </div>\n                    <h2>Filter</h2>\n                </div>\n                <div class=\"section\" ng-if=\"filter.properties.latest !== undefined\">\n\t              <div class=\"subtitle\"><label for=\"filter-latest\" translate=\"PROCESS-DEFINITIONS.FILTER.LATEST\"></label> </div>\n               \t  <div class=\"input-group input-group-sm\">\n               \t  \t<input type=\"checkbox\" id=\"filter-latest\" ng-model=\"filter.properties.latest\" ng-change=\"toggleLatestVersion()\" />&nbsp;<span class=\"check\" translate=\"PROCESS-DEFINITIONS.FILTER.LATEST-HELP\"></span>\n\t              </div>\n\t            </div>\n                <div class=\"section\" ng-if=\"filter.properties.nameLike !== undefined\">\n                    <div class=\"subtitle\"><label for=\"filter-nameLike\" translate=\"PROCESS-DEFINITIONS.FILTER.NAME\"></label> </div>\n                    <div class=\"input-group input-group-sm\">\n                        <input ng-disabled=\"filter.properties.latest == true\" id=\"filter-nameLike\" type=\"text\" class=\"form-control\" value=\"\" ng-model=\"filter.properties.nameLike\" ng-change=\"filter.refreshDelayed()\">\n                    </div>\n                </div>\n                <div class=\"section\" ng-if=\"filter.properties.keyLike !== undefined\">\n                    <div class=\"subtitle\"><label for=\"filter-keyLike\" translate=\"PROCESS-DEFINITIONS.FILTER.KEY\"></label> </div>\n                    <div class=\"input-group input-group-sm\">\n                        <input id=\"filter-keyLike\" type=\"text\" class=\"form-control\" value=\"\" ng-model=\"filter.properties.keyLike\" ng-change=\"filter.refreshDelayed()\">\n                    </div>\n                </div>\n                <div class=\"section\" ng-if=\"filter.properties.deploymentId !== undefined\">\n                    <div class=\"subtitle\"><label for=\"filter-deploymentId\" translate=\"PROCESS-DEFINITIONS.FILTER.DEPLOYMENT-ID\"></label> </div>\n                    <div class=\"input-group input-group-sm\">\n                        <input ng-disabled=\"filter.properties.latest == true\" id=\"filter-deploymentId\" type=\"text\" class=\"form-control\" value=\"\" ng-model=\"filter.properties.deploymentId\" ng-change=\"filter.refreshDelayed()\">\n                    </div>\n                </div>\n                <div class=\"section\" ng-if=\"filter.properties.tenantIdLike !== undefined\">\n                    <div class=\"subtitle\"><label for=\"filter-tenantId\" translate=\"PROCESS-DEFINITIONS.FILTER.TENANT-ID\"></label> </div>\n                    <div class=\"input-group input-group-sm\">\n                        <input id=\"filter-tenantId\" type=\"text\" class=\"form-control\" value=\"\" ng-model=\"filter.properties.tenantIdLike\" ng-change=\"filter.refreshDelayed()\">\n                    </div>\n                </div>\n            </div>\n        </div>\n    </div>\n</div>"
  },
  {
    "path": "flowable-ui-web/admin/views/process-instance-delete-popup.html",
    "content": "<div class=\"modal-header-wrapper\">\n\t<div class=\"modal-header\">\n\t\t<div class=\"pull-right\">\n            <a class=\"action\" ng-click=\"cancel()\">&times; {{'GENERAL.ACTION.CANCEL-AND-CLOSE' | translate}}</a>\n        </div>\n\t\t<h2>{{'PROCESS-INSTANCE.POPUP.DELETE.TITLE' | translate}} '{{process.name &amp;&amp; process.name + \" - \" || \"\"}}{{process.id}}'</h2>\t\n\t</div>\n</div>\n<div class=\"modal-body\">\n\t<p ng-if=\"action == 'delete'\">{{'PROCESS-INSTANCE.POPUP.DELETE.MESSAGE-DELETE' | translate}} '{{process.name &amp;&amp; task.name + \" - \" || \"\"}}{{process.id}}'?</p>\n\t<p ng-if=\"action == 'terminate'\">{{'PROCESS-INSTANCE.POPUP.DELETE.MESSAGE-TERMINATE' | translate}} '{{process.name &amp;&amp; task.name + \" - \" || \"\"}}{{process.id}}'?</p>\n\t\n\t<div class=\"input-group input-group-sm\" ng-if=\"action == 'terminate'\">\n\t \t <label for=\"user\" translate=\"PROCESS-INSTANCE.POPUP.DELETE.DELETE-REASON\"></label>\n         <input id=\"user\" type=\"text\" class=\"form-control\" value=\"\" ng-model=\"model.deleteReason\" focus-me placeholder=\"{{'PROCESS-INSTANCE.POPUP.DELETE.DELETE-REASON-HELP' | translate}}\"/>\n    </div>\n</div>\n\n<div class=\"modal-footer-wrapper\">\n\t<div class=\"modal-footer\">\n\t\t<div class=\"pull-right\">\n\t       <button type=\"button\" class=\"btn btn-sm btn-default\" ng-click=\"cancel()\" ng-disabled=\"status.loading\"\n\t       \ttranslate=\"GENERAL.ACTION.CANCEL\">\n\t       \t</button>\n\t       <button type=\"button\" class=\"btn btn-sm btn-danger\" ng-click=\"ok()\" ng-disabled=\"status.loading\">\n\t       \t\t{{(action == 'delete') &amp;&amp; ('PROCESS-INSTANCE.POPUP.DELETE.CONFIRM-DELETE' | translate) || ('PROCESS-INSTANCE.POPUP.DELETE.CONFIRM-TERMINATE' | translate)}}\n\t       </button>\n\t\t</div>\n        <loading-indicator></loading-indicator>\n</div>\n</div>"
  },
  {
    "path": "flowable-ui-web/admin/views/process-instance-diagram-popup.html",
    "content": "<div class=\"modal-header-wrapper\">\n\t<div class=\"modal-header\">\n\t\t<div class=\"pull-right\">\n            <a class=\"action\" ng-click=\"cancel()\">&times; {{'GENERAL.ACTION.CANCEL-AND-CLOSE' | translate}}</a>\n        </div>\n        <h2>{{'PROCESS-INSTANCE.POPUP.SHOW-PROCESS-MODEL.TITLE' | translate}} '{{model.name &amp;&amp; model.name || model.id}}' \n            <span id=\"navigationTree\">| <a href=\"javascript:_navigateTo('FLOWABLE_ROOT_PROCESS')\">Root</a></span>\n        </h2>\n\t</div>\n</div>\n<div class=\"modal-body modal-body-medium\">\n    <div class=\"text-center\">\n        <button type=\"button\" id=\"changeStateButton\" class=\"btn btn-sm btn-default\" style=\"display:none\">Change state</button>\n    </div>\n\t<div id=\"bpmnModel\" style=\"margin-left:auto;margin-right:auto\"></div>\n</div>\n\n<div class=\"modal-footer-wrapper\">\n\t<div class=\"modal-footer\">\n\t\t<div class=\"pull-right\">\n\t       <button type=\"button\" class=\"btn btn-sm btn-default\" ng-click=\"cancel()\" ng-disabled=\"status.loading\"\n\t\t       \ttranslate=\"GENERAL.ACTION.CLOSE\">\n\t       \t</button>\n\t\t</div>\n\t</div>\n</div>\t"
  },
  {
    "path": "flowable-ui-web/admin/views/process-instance-migration-diagram-popup.html",
    "content": "<div class=\"modal-header-wrapper\">\n\t<div class=\"modal-header\">\n\t\t<div class=\"pull-right\">\n            <a class=\"action\" ng-click=\"cancel()\">&times; {{'GENERAL.ACTION.CANCEL-AND-CLOSE' | translate}}</a>\n        </div>\n        <h2>{{'PROCESS-INSTANCE.POPUP.SHOW-PROCESS-MODEL.TITLE' | translate}} '{{definition.name &amp;&amp; model.name || model.id}}' \n            <span id=\"navigationTree\">| <a href=\"javascript:_navigateTo('FLOWABLE_ROOT_PROCESS')\">Root</a></span>\n        </h2>\n\t</div>\n</div>\n<div class=\"modal-body modal-body-medium\">\n    <div class=\"text-center\">\n        <button type=\"button\" id=\"executeMigrationDocument\" class=\"btn btn-sm btn-default\" style=\"display:none\">Execute migration</button>\n        <button type=\"button\" id=\"addMappingButton\" class=\"btn btn-sm btn-default\" style=\"display:none\">Add mapping</button>\n    </div>\n    <div class=\"text-center\">\n        <span id=\"currentMappingValues\"></span>\n    </div>\n\t<div id=\"bpmnModel\" style=\"margin-left:auto;margin-right:auto\"></div>\n\t<hr id=\"migrationDivider\" />\n\t<div id=\"targetModel\" style=\"margin-left:auto;margin-right:auto\"></div>\n</div>\n\n<div class=\"modal-footer-wrapper\">\n\t<div class=\"modal-footer\">\n\t\t<div class=\"pull-right\">\n\t       <button type=\"button\" class=\"btn btn-sm btn-default\" ng-click=\"cancel()\" ng-disabled=\"status.loading\"\n\t\t       \ttranslate=\"GENERAL.ACTION.CLOSE\">\n\t       \t</button>\n\t\t</div>\n\t</div>\n</div>\t"
  },
  {
    "path": "flowable-ui-web/admin/views/process-instance-migration-popup.html",
    "content": "<div class=\"modal-header-wrapper\">\n\t<div class=\"modal-header\">\n\t\t<div class=\"pull-right\">\n            <a class=\"action\" ng-click=\"cancel()\">&times; {{'GENERAL.ACTION.CLOSE' | translate}}</a>\n        </div>\n\t\t<h2>{{'PROCESS-DEFINITION.POPUP.MIGRATE.TITLE' | translate}} '{{definition.name && definition.name || definition.key}}'</h2>\t\n\t</div>\n</div>\n<div class=\"modal-body\">\n\t<p translate=\"PROCESS-DEFINITION.POPUP.MIGRATE.MESSAGE\"></p>\n\t<table class=\"edit-table\">\n        <tr>\n            <td class=\"edit-label\" translate=\"PROCESS-DEFINITION.POPUP.MIGRATE.CURRENT-DEFINITION\"></td>\n            <td>\n                <input type=\"text\" class=\"form-control\" value=\"{{processDefinition.name ? processDefinition.name : processDefinition.key}} (v{{processDefinition.version}})\" disabled>\n            </td>\n\n        </tr>\n        <tr>\n            <td class=\"edit-label\" translate=\"PROCESS-DEFINITION.POPUP.MIGRATE.TARGET-DEFINITION\"></td>\n            <td>\n                <select ui-select2\n                    data-placeholder=\"{{'PROCESS-INSTANCES.FILTER.ALL-PROCESS-DEFINITIONS' | translate}}\"\n                    ng-model=\"model.newProcessDefinition\"\n                    ng-change=\"targetProcessDefinitionChanged()\"\n                    style=\"min-width:250px\">\n                <option ng-title=\"123\" ng-repeat=\"processDefinition in filteredProcessDefinitions\" value=\"{{processDefinition.id}}\">{{processDefinition.name ? processDefinition.name : processDefinition.key}} (v{{processDefinition.version}})</option>\n             </select>\n            </td>\n        </tr>\n    </table>\n</div>\n\n<div class=\"modal-footer-wrapper\">\n\t<div class=\"modal-footer\">\n\t\t<div class=\"pull-right\">\n\t       <button type=\"button\" class=\"btn btn-sm btn-default\" ng-click=\"cancel()\" ng-disabled=\"status.loading\"\n\t       \ttranslate=\"GENERAL.ACTION.CANCEL\">\n\t       \t</button>\n\t       <button type=\"button\" class=\"btn btn-sm btn-default\" ng-click=\"ok()\" ng-disabled=\"status.loading || model.targetNotSelected\"\n\t        translate=\"GENERAL.ACTION.OK\">\n\t       </button>\n\t\t</div>\n        <loading-indicator></loading-indicator>\n</div>\n</div>"
  },
  {
    "path": "flowable-ui-web/admin/views/process-instance.html",
    "content": "<div class=\"container\" id=\"detail-container\" ng-cloak ng-show=\"process\">\n\t<div class=\"row\" ng-if=\"process\">\n\t\t<div class=\"col-md-9\">\n\t\t\t<div class=\"component component-pack\" >\n\t\t\t\t<div class=\"title\">\n\t\t\t\t\t<div class=\"pull-right\">\n\t\t\t\t\t\t<a ng-click=\"returnToList()\" class=\"action\">&larr; {{'GENERAL.ACTION.RETURN-TO-LIST' | translate}}</a>\n\t\t\t\t\t</div>\n\t\t\t\t\t<h2>{{process.name &amp;&amp; process.name + \"-\" || \"\"}}{{process.id}}</h2>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"property-wrapper\">\n\t\t\t\t\t<table>\n\t\t\t\t\t\t<tr class=\"property\">\n\t\t\t\t\t\t\t<td class=\"property-name\" translate=\"PROCESS-INSTANCE.ID\"></td>\n\t\t\t\t\t\t\t<td>{{process.id}}</td>\n\t\t\t\t\t\t\t<td class=\"property-name\" translate=\"PROCESS-INSTANCE.BUSINESS-KEY\"></td>\n\t\t\t\t\t\t\t<td>{{process.businessKey | empty}}</td>\n\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t<tr class=\"property\">\n\t\t\t\t\t\t\t<td class=\"property-name\" translate=\"PROCESS-INSTANCE.NAME\"></td>\n\t\t\t\t\t\t\t<td>{{process.name | empty}}</td>\n\t\t\t\t\t\t\t<td class=\"property-name\" translate=\"PROCESS-INSTANCE.DESCRIPTION\"></td>\n\t\t\t\t\t\t\t<td>{{process.description | empty}}</td>\n\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t<tr class=\"property\">\n\t\t\t\t\t\t\t<td class=\"property-name\" translate=\"PROCESS-INSTANCE.STATUS\"></td>\n\t\t\t\t\t\t\t<td>{{process.endTime &amp;&amp; ('PROCESS-INSTANCE.STATUS-COMPLETED' | translate) || ('PROCESS-INSTANCE.STATUS-ACTIVE' | translate)}}</td>\n\t\t\t\t\t\t\t<td class=\"property-name\">Process definition:</td>\n\t\t\t\t\t\t\t<td><a ng-click=\"openProcessDefinition(process.processDefinitionId)\"><i class=\"glyphicon glyphicon-zoom-in\"></i>\n\t\t\t\t\t\t\t \t{{definition.name &amp;&amp; definition.name || process.processDefinitionId}}\n\t\t\t\t\t\t\t </a></td>\n\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t<tr class=\"property\">\n\t\t\t\t\t\t\t<td class=\"property-name\" translate=\"PROCESS-INSTANCE.ACTIVITY-ID-STARTED\"></td>\n\t\t\t\t\t\t\t<td>{{process.startActivityId | empty}}</td>\n\t\t\t\t\t\t\t<td class=\"property-name\"><span class=\"glyphicon glyphicon-user\"></span> {{'PROCESS-INSTANCE.STARTED-BY' | translate}}</td>\n\t\t\t\t\t\t\t<td>{{process.startUserId | empty}}</td>\n\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t<tr class=\"property\">\n\t\t\t\t\t\t    <td class=\"property-tenantId\" translate=\"PROCESS-INSTANCE.TENANT-ID\"></td>\n                            <td>{{process.tenantId | empty}}</td>\n\t\t\t\t\t\t\t<td class=\"property-name\" translate=\"PROCESS-INSTANCE.SUPER-PROCESS-INSTANCE-ID\"></td>\n\t\t\t\t\t\t\t<td ng-if=\"process.superProcessInstanceId\"><a ng-click=\"openProcessInstance(process.superProcessInstanceId)\"><i class=\"glyphicon glyphicon-zoom-in\"></i> {{process.superProcessInstanceId | empty}}</a></td>\n\t\t\t\t\t\t</tr>\n\t\t\t\t\t</table>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"seperator\" ng-if=\"process.endTime\"></div>\n\t\t\t\t<div class=\"property-wrapper\" ng-if=\"process.endTime\">\n\t\t\t\t\t<table>\n\t\t\t\t\t\t<tr class=\"property\" >\n\t\t\t\t\t\t\t<td class=\"property-name\"><span class=\"glyphicon glyphicon-time\"></span> {{'PROCESS-INSTANCE.END-TIME' | translate}}</td>\n\t\t\t\t\t\t\t<td>{{process.endTime | dateformat | empty}}</td>\n\t\t\t\t\t\t\t<td class=\"property-name\"><span class=\"glyphicon glyphicon-time\"></span> {{'PROCESS-INSTANCE.DURATION' | translate}}</td>\n\t\t\t\t\t\t\t<td>{{process.durationInMillis | humanTime}}</td>\n\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t<tr class=\"property\" ng-if=\"process.endTime\">\n\t\t\t\t\t\t\t<td class=\"property-name\" translate=\"PROCESS-INSTANCE.DELETE-REASON\"></td>\n\t\t\t\t\t\t\t<td>{{process.deleteReason | empty}}</td>\n\t\t\t\t\t\t\t<td class=\"property-name\" translate=\"PROCESS-INSTANCE.ACTIVITY-ID-ENDED\"></td>\n\t\t\t\t\t\t\t<td>{{process.endActivityId | empty}}</td>\n\t\t\t\t\t\t</tr>\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<div class=\"col-md-3\">\n\t\t\t<div class=\"component tip-left\">\n\t\t\t\t<div class=\"title\">\n\t\t\t\t\t<h2 translate=\"GENERAL.TITLE.ACTIONS\"></h2>\n\t\t\t\t</div>\n\t\t\t\t<ul class=\"list-group\">\n                    <li ng-if=\"definition.graphicalNotationDefined\">\n                        <button type=\"button\" class=\"btn btn-sm btn-default\" ng-click=\"showProcessDiagram()\">\n                            <i class=\"glyphicon glyphicon-zoom-in\"></i>{{'PROCESS-INSTANCE.ACTION.SHOW-DIAGRAM' | translate}}\n                        </button>\n                    </li>\n                    <li>\n                        <button type=\"button\" class=\"btn btn-sm btn-default\" ng-click=\"showMigrateProcessDialog()\">\n                            <i class=\"glyphicon glyphicon-zoom-in\"></i>{{'PROCESS-INSTANCE.ACTION.MIGRATE-PROCESSINSTANCE' | translate}}\n                        </button>\n                    </li>\n                    <li ng-if=\"processCompleted\">\n\t\t\t\t\t    <button type=\"button\" class=\"btn btn-sm btn-default btn-danger\" ng-click=\"deleteProcessInstance()\">\n\t\t\t\t\t\t\t<i class=\"glyphicon glyphicon-remove\"></i>{{'PROCESS-INSTANCE.ACTION.DELETE' | translate}}\n\t\t\t\t\t    </button>\n\t\t\t\t\t  </li>\n\t\t\t\t\t  <li ng-if=\"!processCompleted\">\n\t\t\t\t\t    <button type=\"button\" class=\"btn btn-sm btn-default btn-danger\" ng-click=\"terminateProcessInstance()\">\n\t\t\t\t\t\t\t<i class=\"glyphicon glyphicon-remove\"></i>{{'PROCESS-INSTANCE.ACTION.TERMINATE' | translate}}\n\t\t\t\t\t    </button>\n\t\t\t\t\t  </li>\n\t\t\t\t</ul>\n\t\t\t</div>\n\t\t</div>\n\t</div>\n\t<div class=\"row\">\n\t\t<div class=\"col-md-9\">\n\t\t\t<div class=\"component\">\n\t\t\t\t<div class=\"tabs-wrapper\">\n\t\t       \t\t<div class=\"tabs clearfix\">\n\t\t       \t\t\t<div class=\"tab\" ng-repeat=\"tab in tabData.tabs\" ng-class=\"{'active': tabData.activeTab == tab.id}\">\n\t\t       \t\t\t\t<a ng-click=\"tabData.activeTab = tab.id\">\n\t\t       \t\t\t\t\t{{tab.name | translate:node}}&nbsp;\n\t\t    \t\t\t\t\t<span class=\"badge\" ng-if=\"tab.info != undefined\">{{tab.info}}</span>\n\t\t    \t\t\t\t</a>\n\t\t       \t\t\t</div>\n\t\t       \t\t</div>\n\t\t        \t<div class=\"title\"></div>\n\n\t\t        \t<div class=\"grid-wrapper grid-wrapper-compact\" ng-if=\"tasks && tabData.activeTab == tabData.tabs[0].id\">\n\t\t\t\t\t\t<div class=\"grid-message\" ng-if=\"tasks.size > 0\">\n\t                        <span>{{'PROCESS-INSTANCE.TASKS-SIZE' | translate:tasks}}</span> \n\t                        <span>\n\t                        \t<a ng-click=\"showAllTasks()\" class=\"action\"><i class=\"glyphicon glyphicon-zoom-in\"></i> {{'PROCESS-INSTANCE.ACTION.SHOW-ALL-TASKS' | translate}}</a>\n\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t</div>\n\t                     <div class=\"grid-message\" ng-if=\"tasks.size == 0\">\n\t                        <span>{{'PROCESS-INSTANCE.TASKS-EMPTY' | translate}}</span>\n\t                    </div>\n\t\t\t\t\t\t<div ng-grid=\"gridTasks\" class=\"gridStyle\" ng-if=\"tasks\" ng-show=\"tasks.size > 0\"></div>\n\t\t\t\t\t</div>\n\n\t\t\t\t\t<div class=\"grid-wrapper grid-wrapper-compact\" ng-if=\"variables && tabData.activeTab == tabData.tabs[1].id\">\n\t\t\t\t\t\t<div class=\"grid-message\" ng-if=\"variables.size > 0\">\n\t                        <span>{{'PROCESS-INSTANCE.VARIABLES-SIZE' | translate:variables}}</span>\n\t                    </div>\n\t                     <div class=\"grid-message\" ng-if=\"variables.size == 0\">\n\t                         <span>{{'PROCESS-INSTANCE.VARIABLES-EMPTY' | translate}}</span>\n\t                    </div>\n\t\t\t\t\t\t<div ng-grid=\"gridVariables\" class=\"gridStyle\" ng-if=\"variables\" ng-show=\"variables.size > 0\"></div>\n\t\t\t\t\t</div>\n\n\t\t\t\t\t<div class=\"grid-wrapper grid-wrapper-compact\" ng-if=\"subprocesses && tabData.activeTab == tabData.tabs[2].id\">\n\t\t\t\t\t\t<div class=\"grid-message\" ng-if=\"subprocesses.size > 0\">\n\t                        <span>{{'PROCESS-INSTANCE.SUBPROCESSES-SIZE' | translate:subprocesses}}</span>\n\t                        <span>\n\t                        \t<a ng-click=\"showAllSubprocesses()\" class=\"action\"><i class=\"glyphicon glyphicon-zoom-in\"></i> {{'PROCESS-INSTANCE.ACTION.SHOW-ALL-SUBPROCESSES' | translate}}</a>\n\t                        </span>\n\t                    </div>\n\t                     <div class=\"grid-message\" ng-if=\"subprocesses.size == 0\">\n\t                        <span>{{'PROCESS-INSTANCE.SUBPROCESSES-EMPTY' | translate}}</span>\n\t                    </div>\n\t\t\t\t\t\t<div ng-grid=\"gridSubprocesses\" class=\"gridStyle\" ng-if=\"subprocesses\" ng-show=\"subprocesses.size > 0\"></div>\n\t\t\t\t\t</div>\n\n\t\t\t\t\t<div class=\"grid-wrapper grid-wrapper-compact\" ng-if=\"jobs && tabData.activeTab == tabData.tabs[3].id\">\n\t\t\t\t\t\t<div class=\"grid-message\" ng-if=\"jobs.size > 0\">\n\t                        <span>{{'PROCESS-INSTANCE.JOBS-SIZE' | translate:jobs}}</span>\n\t                        <span>\n\t                        \t<a ng-click=\"showAllJobs()\" class=\"action\"><i class=\"glyphicon glyphicon-zoom-in\"></i> {{'PROCESS-INSTANCE.ACTION.SHOW-ALL-JOBS' | translate}}</a>\n\t                        </span>\n\t                    </div>\n\t                     <div class=\"grid-message\" ng-if=\"jobs.size == 0\">\n\t                        <span>{{'PROCESS-INSTANCE.JOBS-EMPTY' | translate}}</span>\n\t                    </div>\n\t\t\t\t\t\t<div ng-grid=\"gridJobs\" class=\"gridStyle\" ng-if=\"jobs\" ng-show=\"jobs.size > 0\"></div>\n\t\t\t\t\t</div>\n\t\t\t\t\t\n\t\t\t\t\t<div class=\"grid-wrapper grid-wrapper-compact\" ng-if=\"decisionTables && tabData.activeTab == tabData.tabs[4].id\">\n\t\t\t\t\t\t<div class=\"grid-message\" ng-if=\"decisionTables.size > 0\">\n\t                        <span>{{'PROCESS-INSTANCE.DECISION-TABLES-SIZE' | translate:decisionTables}}</span>\n\t                    </div>\n\t                     <div class=\"grid-message\" ng-if=\"decisionTables.size == 0\">\n\t                        <span>{{'PROCESS-INSTANCE.DECISION-TABLES-EMPTY' | translate}}</span>\n\t                    </div>\n\t\t\t\t\t\t<div ng-grid=\"gridDecisionTables\" class=\"gridStyle\" ng-if=\"decisionTables\" ng-show=\"decisionTables.size > 0\"></div>\n\t\t\t\t\t</div>\n\t\t\t\t\t\n\t\t\t\t\t<div class=\"grid-wrapper grid-wrapper-compact\" ng-if=\"formInstances && tabData.activeTab == tabData.tabs[5].id\">\n\t\t\t\t\t\t<div class=\"grid-message\" ng-if=\"formInstances.size > 0\">\n\t                        <span>{{'PROCESS-INSTANCE.FORM-INSTANCES-SIZE' | translate:formInstances}}</span>\n\t                    </div>\n\t                     <div class=\"grid-message\" ng-if=\"formInstances.size == 0\">\n\t                        <span>{{'PROCESS-INSTANCE.FORM-INSTANCES-EMPTY' | translate}}</span>\n\t                    </div>\n\t\t\t\t\t\t<div ng-grid=\"gridFormInstances\" class=\"gridStyle\" ng-if=\"formInstances\" ng-show=\"formInstances.size > 0\"></div>\n\t\t\t\t\t</div>\n\n\t\t        </div>\n\t\t     </div>\n\t\t</div>\n\n        <div class=\"col-md-3\" ng-if=\"tabData.activeTab == tabData.tabs[1].id && process.endTime == null && process.endTime == undefined\">\n            <div class=\"component tip-left\">\n                <div class=\"title\">\n                    <h2 translate=\"PROCESS-INSTANCE.ACTION.TITLE-VARIABLES\"></h2>\n                </div>\n                <ul class=\"list-group\">\n                    <li ng-if=\"selectedVariables && selectedVariables.length > 0\">\n                        <button type=\"button\" class=\"btn btn-sm btn-default\" ng-click=\"updateSelectedVariable()\">\n                            <i class=\"glyphicon glyphicon-pencil\"></i>{{'PROCESS-INSTANCE.ACTION.UPDATE-VALUE' | translate}}\n                        </button>\n                    </li>\n                    <li>\n                        <button type=\"button\" class=\"btn btn-sm btn-default\" ng-click=\"addVariable()\">\n                            <i class=\"glyphicon glyphicon-plus\"></i>{{'PROCESS-INSTANCE.ACTION.ADD-VARIABLE' | translate}}\n                        </button>\n                    </li>\n                    <li ng-if=\"selectedVariables && selectedVariables.length > 0\">\n                        <button type=\"button\" class=\"btn btn-sm btn-danger\" ng-click=\"deleteVariable()\">\n                            <i class=\"glyphicon glyphicon-remove\"></i>{{'PROCESS-INSTANCE.ACTION.DELETE-VARIABLE' | translate}}\n                        </button>\n                    </li>\n                </ul>\n            </div>\n        </div>\n\t</div>\n</div>\n"
  },
  {
    "path": "flowable-ui-web/admin/views/process-instances.html",
    "content": "<!-- LIST PAGE -->\n<div class=\"container\" id=\"list-container\">\n    <div class=\"row\">\n        <div class=\"col-md-8\">\n            <div class=\"component\">\n                <div class=\"title\">\n                    <div class=\"btn-group btn-group-sm pull-right\">\n                        <div class=\"btn-group btn-group-sm\">\n                            <button type=\"button\" class=\"btn btn-default dropdown-toggle\" data-toggle=\"dropdown\"\n                                    translate=\"GENERAL.ACTION.SHOW-RESULTS\" translate-value-size=\"{{'GENERAL.RESULT-SIZES.' + filter.resultSize | translate}}\">\n                                &nbsp;\n                                <span class=\"caret\"></span>\n                            </button>\n                            <ul class=\"dropdown-menu\">\n                            \t<li ng-repeat=\"resultSize in config.filter.resultSizes\"><a href=\"\" ng-click=\"filter.setResultSize(resultSize)\">{{'GENERAL.RESULT-SIZES.' + resultSize.toString() | translate}}</a></li>\n                            </ul>\n                        </div>\n                        <button type=\"button\" class=\"btn btn-default\" ng-click=\"filter.toggleOrder()\">\n                        \t<i class=\"glyphicon\" ng-class=\"{'glyphicon-sort-by-attributes': filter.order == 'asc', 'glyphicon-sort-by-attributes-alt': filter.order == 'desc'}\"></i>\n                        </button>\n                    </div>\n                    <div class=\"btn-group btn-group-sm pull-right\">\n                    \t<button type=\"button\" class=\"btn btn-default dropdown-toggle\" data-toggle=\"dropdown\"\n                                translate=\"GENERAL.ACTION.SHOW-RESULTS\" translate-value-size=\"{{'GENERAL.RESULT-SIZES.' + filter.resultSize | translate}}\">\n                            &nbsp;\n                            <span class=\"caret\"></span>\n                        </button>\n                    \t<ul class=\"dropdown-menu\">\n                           <li ng-repeat=\"sort in filter.sortObjects\"><a href=\"\" ng-click=\"filter.setSort(sort)\">{{sort.name | translate}}</a></li>\n                        </ul>\n                    </div>\n                    <div class=\"btn-group btn-group-sm pull-right\">\n                        <a class=\"btn btn-default\" role=\"button\"\n                           title=\"{{'GENERAL.ACTION.REFRESH-LIST' | translate}}\"\n                           ng-click=\"filter.refresh();\">\n                            <i class=\"glyphicon glyphicon-refresh\"></i>\n                        </a>\n                    </div>\n                    <div class=\"pull-right loading\" ng-show=\"filter.loading\">\n                    \t<i class=\"glyphicon glyphicon-refresh\"></i>\n                    </div>\n\n                    <h2 translate=\"PROCESS-INSTANCES.TITLE\"></h2>\n                </div>\n\n                <div class=\"grid-wrapper\" id=\"process-instances\">\n                    <div class=\"grid-message\" ng-if=\"processInstances.size > 0\">\n                         <span>{{'PROCESS-INSTANCES.LIST-MESSAGE' | translate:processInstances}}</span>\n                    </div>\n                     <div class=\"grid-message\" ng-if=\"processInstances.size == 0\">\n                        <span>{{'PROCESS-INSTANCES.LIST-MESSAGE-EMPTY' | translate}}</span>\n                    </div>\n                    <div ng-grid=\"gridInstances\" class=\"gridStyle\" ng-if=\"gridInstances && processInstances.data\"/>\n                </div>\n            </div>\n        </div>\n        <div class=\"col-md-4\">\n            <div class=\"component tip-left\">\n                <div class=\"title\">\n                    <div class=\"btn-group btn-group-sm pull-right\" ng-show=\"filter.supportedProperties.length > 0\">\n                        <button type=\"button\" class=\"btn btn-default\" data-toggle=\"dropdown\">\n                            <i class=\"glyphicon glyphicon-plus\"></i>\n                        </button>\n                        <ul class=\"dropdown-menu\">\n                            <li ng-repeat=\"prop in filter.supportedProperties\"><a href=\"\" ng-click=\"addFilterProperty(prop)\">{{prop.name | translate}}</a></li>\n                        </ul>\n                    </div>\n                    <div class=\"pull-right\">\n                        <a class=\"action\" ng-click=\"clearFilters()\" translate=\"GENERAL.ACTION.CLEAR-FILTERS\"></a>\n                    </div>\n                    <h2 translate=\"GENERAL.TITLE.FILTERS\"></h2>\n                </div>\n                <div class=\"section\">\n                    <div class=\"subtitle\"><label translate=\"PROCESS-INSTANCES.FILTER.PROCESS-DEFINITION\"></label> </div>\n                    <div>\n                        <select ui-select2\n                                data-placeholder=\"{{'PROCESS-INSTANCES.FILTER.ALL-PROCESS-DEFINITIONS' | translate}}\"\n                         \t\tng-model=\"filter.processDefinition\"\n                         \t\tng-change=\"processDefinitionFilterChanged()\"\n                         \t\tstyle=\"min-width:250px\">\n                            <option value=\"\"></option>\n                         \t<option value=\"-1\">{{'PROCESS-INSTANCES.FILTER.ALL-PROCESS-DEFINITIONS' | translate}}</option>\n                         \t<option ng-title=\"123\" ng-repeat=\"processDefinition in processDefinitionsCache.data\" value=\"{{processDefinition.id}}\">{{processDefinition.name ? processDefinition.name : processDefinition.key}} (v{{processDefinition.version}})</option>\n                         </select>\n                    </div>\n                </div>\n                <div class=\"section\" ng-if=\"filter.properties.finished !== undefined\">\n                    <div class=\"subtitle\"><label for=\"filter-finished\" translate=\"PROCESS-INSTANCES.FILTER.STATUS\"></label> </div>\n                    <div class=\"input-group input-group-sm\" id=\"filter-state\">\n                       <div class=\"btn-group btn-group-sm\">\n                        <button type=\"button\" id=\"filter-finished\" class=\"btn btn-default dropdown-toggle form-control\" data-toggle=\"dropdown\">\n                            <span class=\"pull-right\">\n                                <span class=\"caret\"></span>\n                            </span>\n                            {{filter.getLabelForOption('finished') | translate}}\n                        </button>\n                        <ul class=\"dropdown-menu\">\n                            <li ng-repeat=\"state in filter.options.finished\"><a href=\"\" ng-click=\"filter.selectOption('finished', state)\">{{state.name | translate}}</a></li>\n                        </ul>\n                    </div>\n                    </div>\n                </div>\n                <div class=\"section\" ng-if=\"filter.properties.processBusinessKey!== undefined\">\n                    <div class=\"subtitle\"><label for=\"filter-processBusinessKey\" translate=\"PROCESS-INSTANCES.FILTER.BUSINESS-KEY\"></label> </div>\n                    <div class=\"input-group input-group-sm\">\n                        <input id=\"filter-processBusinessKey\" type=\"text\" class=\"form-control\" value=\"\" ng-model=\"filter.properties.processBusinessKey\" ng-change=\"filter.refreshDelayed()\">\n                    </div>\n                </div>\n                <div class=\"section\" ng-if=\"filter.properties.superProcessInstanceId!== undefined\">\n                    <div class=\"subtitle\"><label for=\"filter-superProcessInstanceId\" translate=\"PROCESS-INSTANCES.FILTER.SUPER-PROCESS-INSTANCE-ID\"></label> </div>\n                    <div class=\"input-group input-group-sm\">\n                        <input id=\"filter-superProcessInstanceId\" type=\"text\" class=\"form-control\" value=\"\" ng-model=\"filter.properties.superProcessInstanceId\" ng-change=\"filter.refreshDelayed()\">\n                    </div>\n                </div>\n                <div class=\"section\" ng-if=\"filter.properties.startedBefore !== undefined\">\n                  <div class=\"subtitle\"><label for=\"filter-startedBefore\" translate=\"PROCESS-INSTANCES.FILTER.STARTED-BEFORE\"></label> </div>\n               \t  <div class=\"input-group input-group-sm\">\n               \t  \t<span class=\"input-group-addon\"><span class=\"glyphicon glyphicon-time\"></span></span>\n\t              \t<input id=\"filter-startedBefore\" type=\"text\" class=\"form-control\" ng-model=\"filter.properties.startedBefore\"\n                           ng-change=\"filter.refreshDelayed()\"\n                           datepicker-popup=\"dd/MM/yyyy\"\n                           is-open=\"startedBeforePicker.isOpen\" ng-click=\"startedBeforePicker.isOpen=true\"/>\n\t              </div>\n\t            </div>\n                <div class=\"section\" ng-if=\"filter.properties.startedAfter !== undefined\">\n\t              <div class=\"subtitle\"><label for=\"filter-startedAfter\" translate=\"PROCESS-INSTANCES.FILTER.STARTED-AFTER\"></label> </div>\n               \t  <div class=\"input-group input-group-sm\">\n               \t  \t<span class=\"input-group-addon\"><span class=\"glyphicon glyphicon-time\"></span></span>\n\t              \t<input id=\"filter-startedAfter\" type=\"text\" class=\"form-control\" ng-model=\"filter.properties.startedAfter\"\n                           ng-change=\"filter.refreshDelayed()\"\n                           datepicker-popup=\"dd/MM/yyyy\"\n                           is-open=\"startedAfterPicker.isOpen\" ng-click=\"startedAfterPicker.isOpen=true\"/>\n\t              </div>\n\t            </div>\n\t            <div class=\"section\" ng-if=\"filter.properties.finishedBefore !== undefined\">\n                  <div class=\"subtitle\"><label for=\"filter-finishedBefore\" translate=\"PROCESS-INSTANCES.FILTER.ENDED-BEFORE\"></label> </div>\n               \t  <div class=\"input-group input-group-sm\">\n               \t  \t<span class=\"input-group-addon\"><span class=\"glyphicon glyphicon-time\"></span></span>\n\t              \t<input id=\"filter-finishedBefore\" type=\"text\" class=\"form-control\" ng-model=\"filter.properties.finishedBefore\"\n                           ng-change=\"filter.refreshDelayed()\"\n                           datepicker-popup=\"dd/MM/yyyy\"\n                           is-open=\"finishedBeforePicker.isOpen\" ng-click=\"finishedBeforePicker.isOpen=true\"/>\n\t              </div>\n\t            </div>\n                <div class=\"section\" ng-if=\"filter.properties.finishedAfter !== undefined\">\n\t              <div class=\"subtitle\"><label for=\"filter-finishedAfter\" translate=\"PROCESS-INSTANCES.FILTER.ENDED-AFTER\"></label> </div>\n               \t  <div class=\"input-group input-group-sm\">\n               \t  \t<span class=\"input-group-addon\"><span class=\"glyphicon glyphicon-time\"></span></span>\n\t              \t<input id=\"filter-finishedAfter\" type=\"text\" class=\"form-control\" ng-model=\"filter.properties.finishedAfter\"\n                           ng-change=\"filter.refreshDelayed()\"\n                           datepicker-popup=\"dd/MM/yyyy\"\n                           is-open=\"finishedAfterPicker.isOpen\" ng-click=\"finishedAfterPicker.isOpen=true\"/>\n\t              </div>\n\t            </div>\n\n\t            <div class=\"section clearfix\" ng-repeat=\"varFilter in filter.properties.variables\">\n\t              <div class=\"seperator\" ng-if=\"$index > 0\"></div>\n\t              <div class=\"subtitle\"><label translate=\"PROCESS-INSTANCES.FILTER.VARIABLE\"></label> </div>\n               \t  <div class=\"inline-button input-group-sm\">\n\t              \t\t<div class=\"pull-right btn-group\">\n\t                        <button ng-disabled=\"varFilter.type.id == 'boolean'\" tabindex=\"-1\" type=\"button\" class=\"btn btn-sm btn-default dropdown-toggle\" data-toggle=\"dropdown\">\n\t                             {{varFilter.operator.sign}} <i class=\"caret\"></i>\n\t                        </button>\n\t                        <ul class=\"dropdown-menu\">\n\t                            <li><a href=\"\" ng-click=\"setVariableFilterOperator(varFilter, operator)\" ng-repeat=\"operator in variableFilterOperators\">{{operator.name}}</a></li>\n\t                        </ul>\n\t                    </div>\n\t              \t\t<input id=\"filter-variable-name-{{$index}}\" type=\"text\" class=\"form-control\" ng-model=\"varFilter.name\" ng-change=\"filter.refreshDelayed()\" placeholder=\"{{'PROCESS-INSTANCES.FILTER.VARIABLE-NAME' | translate}}\" />\n\t              </div>\n               \t  <div class=\"inline-button wide input-group-sm\" >\n\t              \t\t<div class=\"pull-right btn-group\">\n\t                        <button tabindex=\"-1\" ng-disabled=\"varFilter.operator.id == 'like'\" type=\"button\" class=\"btn btn-sm btn-default dropdown-toggle\" data-toggle=\"dropdown\">\n\t                           {{varFilter.type.name}} <i class=\"caret\"></i>\n\t                        </button>\n\t                        <ul class=\"dropdown-menu\">\n\t                            <li><a href=\"\" ng-click=\"setVariableFilterType(varFilter, type)\" ng-repeat=\"type in variableFilterTypes\" >{{type.name}}</a></li>\n\t                        </ul>\n\t                    </div>\n\t              \t\t<input ng-if=\"varFilter.type.id != 'date' && varFilter.type.id != 'boolean'\" id=\"filter-variable-value-{{$index}}\" type=\"text\" class=\"form-control\" ng-model=\"varFilter.value\" ng-change=\"filter.refreshDelayed()\" placeholder=\"{{'PROCESS-INSTANCES.FILTER.VARIABLE-VALUE' | translate}}\" />\n\t              \t\t<input ng-if=\"varFilter.type.id == 'date'\" id=\"filter-variable-value-{{$index}}\" type=\"text\" class=\"form-control\" ng-model=\"varFilter.value\"\n                               ng-change=\"filter.refresh()\"\n                               datepicker-popup=\"dd/MM/yyyy\"\n                               is-open=\"varValuePicker.isOpen\" ng-click=\"varValuePicker.isOpen=true\"/>\n\t              \t\t<div class=\"checkbox\" ng-if=\"varFilter.type.id == 'boolean'\">\n\t\t\t\t\t\t    <label>\n\t\t\t\t\t\t      <input type=\"checkbox\" ng-change=\"filter.refresh()\" ng-model=\"varFilter.value\">{{'PROCESS-INSTANCES.FILTER.VARIABLE-BOOLEAN-VALUE' | translate:varFilter}}\n\t\t\t\t\t\t    </label>\n  \t\t\t\t\t\t</div>\n\t              </div>\n\t            </div>\n\t            <div class=\"section\" ng-if=\"filter.properties.tenantIdLike !== undefined\">\n                    <div class=\"subtitle\"><label for=\"filter-tenantId\" translate=\"PROCESS-INSTANCES.FILTER.TENANT-ID\"></label> </div>\n                    <div class=\"input-group input-group-sm\">\n                        <input id=\"filter-tenantId\" type=\"text\" class=\"form-control\" value=\"\" ng-model=\"filter.properties.tenantIdLike\" ng-change=\"filter.refreshDelayed()\">\n                    </div>\n                </div>\n            </div>\n        </div>\n    </div>\n</div>\n"
  },
  {
    "path": "flowable-ui-web/admin/views/redeploy-app-popup.html",
    "content": "<div class=\"modal-header-wrapper\">\n\t<div class=\"modal-header\">\n\t\t<div class=\"pull-right\">\n            <a class=\"action\" ng-click=\"cancel()\">&times; {{'GENERAL.ACTION.CANCEL-AND-CLOSE' | translate}}</a>\n        </div>\n\t\t<h2 translate=\"APPS.POPUP.REDEPLOY.TITLE\"></h2>\n\t</div>\n</div>\n<div class=\"modal-body no-overflow\">\n\n\t<p>\n\t\t<i class=\"glyphicon glyphicon-info-sign\"></i>\n\t\t{{'APPS.POPUP.REDEPLOY.DESCRIPTION' | translate:app.appDefinition }}\n\t</p>\n\n\n\t<div style=\"padding-left: 30%;\">\n\t\t<button type=\"button\" class=\"btn btn-sm dropdown-toggle\"\n\t\t\tstyle=\"border-color: #ccc; background-color: #fff\" data-toggle=\"dropdown\">\n\t\t\t<span ng-if=\"!targetServer\" translate=\"APPS.POPUP.REDEPLOY.SELECT-CLUSTER\"></span> \n\t\t\t<span ng-if=\"targetServer\" translate=\"APPS.POPUP.REDEPLOY.DEPLOY-TO-CLUSTER\" translate-values=\"{name: targetServer.clusterName}\"></span> \n\t\t\t<span class=\"caret\"></span>\n\t\t</button>\n\n\t\t<ul class=\"dropdown-menu\"\n\t\t\tstyle=\"top: auto; left: auto; z-index: 1000000;\">\n\t\t\t<li ng-repeat=\"cluster in availableClusters\"\n\t\t\t\tng-if=\"cluster.id != activeCluster.id\"><a\n\t\t\t\tng-click=\"selectTargetServer(cluster)\">{{cluster.clusterName}}</a></li>\n\t\t</ul>\n\t\t\n\t</div>\n\t\n\t<p ng-if=\"model.isConflict && !model.error\" class=\"text-warning\">\n        <i class=\"glyphicon glyphicon-warning-sign\"></i>&nbsp;\n        <span translate=\"APPS.POPUP.REDEPLOY.APP-CONFLICT-ERROR\" translate-values=\"{ name: model.conflictingAppName, createdBy: model.conflictingAppCreatedBy }\"></span>\n        <span style=\"display: block; padding-left: 18px;\">{{model.conflictMessage}}</span>\n    </p>\n    \n    <p ng-if=\"model.error\" class=\"modeler-processes-error\">\n        <i class=\"glyphicon glyphicon-remove-circle\"></i>\n        <span translate=\"APPS.POPUP.REDEPLOY.ERROR\"></span>\n        {{model.errorMessage}}\n    </p>\n    \n</div>\n\n<div class=\"modal-footer-wrapper\">\n    <div class=\"modal-footer\">\n        <div class=\"pull-right\">\n\t\t\t<button ng-if=\"!model.isConflict\" type=\"button\" class=\"btn btn-sm btn-default\" ng-click=\"deployApp(targetServer.id)\" ng-disabled=\"status.loading || !targetServer.id\" translate=\"APPS.POPUP.REDEPLOY.DEPLOY\"></button>\n\t\t\t<button ng-if=\"model.isConflict\" type=\"button\" class=\"btn btn-sm btn-default\" ng-click=\"deployAppAsNewVersion(targetServer.id, model.conflictAppId)\" ng-disabled=\"status.loading || !targetServer.id || model.error\" translate=\"APPS.POPUP.REDEPLOY.DEPLOY-AS-NEW-VERSION\"></button>\n\t\t</div>\n    </div>\n</div>\n"
  },
  {
    "path": "flowable-ui-web/admin/views/task-assign-popup.html",
    "content": "<div class=\"modal-header-wrapper\">\n\t<div class=\"modal-header\">\n\t\t<div class=\"pull-right\">\n            <a class=\"action\" ng-click=\"cancel()\">&times; {{'GENERAL.ACTION.CANCEL-AND-CLOSE' | translate}}</a>\n        </div>\n\t\t<h2>{{'TASK.POPUP.ASSIGN.TITLE' | translate}} '{{task.name &amp;&amp; task.name || task.id}}'</h2>\t\n\t</div>\n</div>\n<div class=\"modal-body no-overflow\">\n\t<p>\n\t\t{{'TASK.POPUP.ASSIGN.MESSAGE' | translate}} '{{task.name &amp;&amp; task.name + ' (' + task.id + ')' || task.id}}'?\n\t\t{{'TASK.POPUP.ASSIGN.NEW-ASSIGNEE-HELP' | translate}}\n\t</p>\n\t <div class=\"input-group input-group-sm type-ahead-scrollable\">\n\t \t <label for=\"user\" translate=\"TASK.POPUP.ASSIGN.NEW-ASSIGNEE\"></label>\n\t \t <input id=\"user\" type=\"text\" ng-model=\"status.user\" class=\"form-control\" auto-focus>\n     </div>\n</div>\n\n<div class=\"modal-footer-wrapper\">\n\t<div class=\"modal-footer\">\n\t\t<div class=\"pull-right\">\n\t        <button type=\"button\" class=\"btn btn-sm btn-default\" ng-click=\"cancel()\" ng-disabled=\"status.loading\"\n\t       \t\ttranslate=\"GENERAL.ACTION.CANCEL\">\n\t       \t</button>\n\t       <button type=\"button\" class=\"btn btn-sm btn-default\" ng-click=\"ok()\" ng-disabled=\"status.loading\"\n\t       \t   translate=\"TASK.POPUP.ASSIGN.CONFIRM\">\n\t       </button>\n\t\t</div>\n        <loading-indicator></loading-indicator>\n</div>\n</div>"
  },
  {
    "path": "flowable-ui-web/admin/views/task-complete-popup.html",
    "content": "<div class=\"modal-header-wrapper\">\n\t<div class=\"modal-header\">\n\t\t<div class=\"pull-right\">\n            <a class=\"action\" ng-click=\"cancel()\">&times; {{'GENERAL.ACTION.CANCEL-AND-CLOSE' | translate}}</a>\n        </div>\n\t\t<h2>{{'TASK.POPUP.COMPLETE.TITLE' | translate}} '{{task.name &amp;&amp; task.name || task.id}}'</h2>\t\n\t</div>\n</div>\n<div class=\"modal-body\">\n\t<p>{{'TASK.POPUP.COMPLETE.MESSAGE' | translate}} '{{task.name &amp;&amp; task.name + ' (' + task.id + ')' || task.id}}'?</p>\n</div>\n\n<div class=\"modal-footer-wrapper\">\n\t<div class=\"modal-footer\">\n\t\t<div class=\"pull-right\">\n\t        <button type=\"button\" class=\"btn btn-sm btn-default\" ng-click=\"cancel()\" ng-disabled=\"status.loading\"\n\t       \t\ttranslate=\"GENERAL.ACTION.CANCEL\">\n\t       \t</button>\n\t       <button type=\"button\" class=\"btn btn-sm btn-default\" ng-click=\"ok()\" ng-disabled=\"status.loading\"\n\t       \t    translate=\"TASK.POPUP.COMPLETE.CONFIRM\">\n\t       </button>\n\t\t</div>\n        <loading-indicator></loading-indicator>\n</div>\n</div>"
  },
  {
    "path": "flowable-ui-web/admin/views/task-delegate-popup.html",
    "content": "<div class=\"modal-header-wrapper\">\n\t<div class=\"modal-header\">\n\t\t<div class=\"pull-right\">\n            <a class=\"action\" ng-click=\"cancel()\">&times; {{'GENERAL.ACTION.CANCEL-AND-CLOSE' | translate}}</a>\n        </div>\n\t\t<h2>{{'TASK.POPUP.DELEGATE.TITLE' | translate}} '{{task.name &amp;&amp; task.name || task.id}}'</h2>\n\t</div>\n</div>\n<div class=\"modal-body no-overflow\">\n\t<p>{{'TASK.POPUP.DELEGATE.MESSAGE' | translate}} '{{task.name &amp;&amp; task.name + ' (' + task.id + ')' || task.id}}'?</p>\n\t <div class=\"input-group input-group-sm type-ahead-scrollable\">\n\t \t <label for=\"user\" translate=\"TASK.POPUP.DELEGATE.DELEGATE-TO\"></label>\n\t \t <input id=\"user\" type=\"text\" ng-model=\"status.user\" class=\"form-control\" auto-focus>\n     </div>\n</div>\n\n<div class=\"modal-footer-wrapper\">\n\t<div class=\"modal-footer\">\n\t\t<div class=\"pull-right\">\n\t        <button type=\"button\" class=\"btn btn-sm btn-default\" ng-click=\"cancel()\" ng-disabled=\"status.loading\"\n\t       \t\ttranslate=\"GENERAL.ACTION.CANCEL\">\n\t       \t</button>\n\t       <button type=\"button\" class=\"btn btn-sm btn-default\" ng-click=\"ok()\" ng-disabled=\"status.loading || !status.user\"\n\t           translate=\"TASK.POPUP.DELEGATE.CONFIRM\">\n\t       </button>\n\t\t</div>\n        <loading-indicator></loading-indicator>\n</div>\n</div>"
  },
  {
    "path": "flowable-ui-web/admin/views/task-delete-popup.html",
    "content": "<div class=\"modal-header-wrapper\">\n\t<div class=\"modal-header\">\n\t\t<div class=\"pull-right\">\n            <a class=\"action\" ng-click=\"cancel()\">&times; {{'GENERAL.ACTION.CANCEL-AND-CLOSE' | translate}}</a>\n        </div>\n\t\t<h2>{{'TASK.POPUP.DELETE.TITLE' | translate}} '{{task.name &amp;&amp; task.name || task.id}}'</h2>\t\n\t</div>\n</div>\n<div class=\"modal-body\">\n\t<p>{{'TASK.POPUP.DELETE.MESSAGE' | translate}} '{{task.name &amp;&amp; task.name + ' (' + task.id + ')' || task.id}}'?</p>\n</div>\n\n<div class=\"modal-footer-wrapper\">\n\t<div class=\"modal-footer\">\n\t\t<div class=\"pull-right\">\n\t        <button type=\"button\" class=\"btn btn-sm btn-default\" ng-click=\"cancel()\" ng-disabled=\"status.loading\"\n\t       \t\ttranslate=\"GENERAL.ACTION.CANCEL\">\n\t       \t</button>\n\t       <button type=\"button\" class=\"btn btn-sm btn-danger\" ng-click=\"ok()\" ng-disabled=\"status.loading\"\n\t       \t    translate=\"TASK.POPUP.DELETE.CONFIRM\">\n\t       </button>\n\t\t</div>\n        <loading-indicator></loading-indicator>\n</div>\n</div>"
  },
  {
    "path": "flowable-ui-web/admin/views/task-edit-popup.html",
    "content": "<div class=\"modal-header-wrapper\">\n\t<div class=\"modal-header\">\n\t\t<div class=\"pull-right\">\n            <a class=\"action\" ng-click=\"cancel()\">&times; {{'GENERAL.ACTION.CANCEL-AND-CLOSE' | translate}}</a>\n        </div>\n\t\t<h2>{{'TASK.POPUP.EDIT.TITLE' | translate}} '{{task.name &amp;&amp; task.name || task.id}}'</h2>\n\t</div>\n</div>\n<div class=\"modal-body no-overflow\">\n\t<table class=\"edit-table\">\n\t\t<tr>\n\t\t\t<td class=\"edit-label\" translate=\"TASK.POPUP.EDIT.NAME\"></td>\n\t\t\t<td>\n\t\t\t\t<div class=\"input-group input-group-sm\">\n\t\t\t\t\t<input type=\"text\" class=\"form-control\" value=\"\" ng-model=\"model.name\" auto-focus>\n\t\t\t\t</div>\n\t\t\t</td>\n\t\t</tr>\n\t\t<tr>\n\t\t\t<td class=\"edit-label\" translate=\"TASK.POPUP.EDIT.DESCRIPTION\"></td>\n\t\t\t<td>\n\t\t\t\t<div class=\"input-group input-group-sm\">\n\t\t\t\t\t<textarea class=\"form-control\" rows=\"2\" ng-model=\"model.description\"></textarea>\n\t\t\t\t</div>\n\t\t\t</td>\n\t\t</tr>\n\t\t<tr>\n\t\t\t<td class=\"edit-label\" translate=\"TASK.POPUP.EDIT.ASSIGNEE\"></td>\n\t\t\t<td>\n\t\t\t\t<div class=\"input-group input-group-sm type-ahead-scrollable\">\n\t\t\t\t\t<input type=\"text\" ng-model=\"model.assignee\" class=\"form-control\">\n\t\t\t\t</div>\n\t\t\t</td>\n\t\t</tr>\n\t\t<tr>\n\t\t\t<td class=\"edit-label\" translate=\"TASK.POPUP.EDIT.OWNER\"></td>\n\t\t\t<td>\n\t\t\t\t<div class=\"input-group input-group-sm type-ahead-scrollable\">\n\t\t\t\t\t<input type=\"text\" ng-model=\"model.owner\" class=\"form-control\">\n\t\t\t\t</div>\n\t\t\t</td>\n\t\t</tr>\n\n\t\t<tr>\n\t\t\t<td class=\"edit-label\" translate=\"TASK.POPUP.EDIT.DUE-DATE\"></td>\n\t\t\t<td>\n\t\t\t\t<div class=\"input-group input-group-sm\">\n\t\t\t\t\t<span class=\"input-group-addon\"><span class=\"glyphicon glyphicon-time\"></span></span>\n\t\t\t\t\t<input id=\"filter-dueBefore\" type=\"text\" class=\"form-control\"\n                           ng-model=\"model.dueDate\"\n                           datepicker-popup=\"dd/MM/yyyy\"\n                           is-open=\"dueDatePicker.isOpen\" ng-click=\"dueDatePicker.isOpen=true\"/>\n\t\t\t\t</div>\n\t\t\t</td>\n\t\t</tr>\n\t\t<tr>\n\t\t\t<td class=\"edit-label\" translate=\"TASK.POPUP.EDIT.PRIORITY\"></td>\n\t\t\t<td>\n\t\t\t\t<div class=\"input-group input-group-sm\">\n\t\t\t\t\t<input type=\"text\" class=\"form-control\" value=\"\" ng-model=\"model.priority\">\n\t\t\t\t</div>\n\t\t\t</td>\n\t\t</tr>\n\t\t<tr>\n\t\t\t<td class=\"edit-label\" translate=\"TASK.POPUP.EDIT.CATEGORY\"></td>\n\t\t\t<td>\n\t\t\t\t<div class=\"input-group input-group-sm\">\n\t\t\t\t\t<input type=\"text\" class=\"form-control\" value=\"\" ng-model=\"model.category\">\n\t\t\t\t</div>\n\t\t\t</td>\n\t\t</tr>\n\t</table>\n</div>\n\n<div class=\"modal-footer-wrapper\">\n\t<div class=\"modal-footer\">\n\t\t<div class=\"pull-right\">\n\t        <button type=\"button\" class=\"btn btn-sm btn-default\" ng-click=\"cancel()\" ng-disabled=\"status.loading\"\n\t       \t\ttranslate=\"GENERAL.ACTION.CANCEL\">\n\t       \t</button>\n\t       <button type=\"button\" class=\"btn btn-sm btn-default\" ng-click=\"ok()\" ng-disabled=\"status.loading\"\n\t       \t\ttranslate=\"TASK.POPUP.EDIT.CONFIRM\">\n\t       </button>\n\t\t</div>\n        <loading-indicator></loading-indicator>\n</div>\n</div>\n"
  },
  {
    "path": "flowable-ui-web/admin/views/task-resolve-popup.html",
    "content": "<div class=\"modal-header-wrapper\">\n\t<div class=\"modal-header\">\n\t\t<div class=\"pull-right\">\n            <a class=\"action\" ng-click=\"cancel()\">&times; {{'GENERAL.ACTION.CANCEL-AND-CLOSE' | translate}}</a>\n        </div>\n\t\t<h2>{{'TASK.POPUP.RESOLVE.TITLE' | translate}} '{{task.name &amp;&amp; task.name || task.id}}'</h2>\t\n\t</div>\n</div>\n<div class=\"modal-body\">\n\t<p>{{'TASK.POPUP.RESOLVE.MESSAGE' | translate}} '{{task.name &amp;&amp; task.name + ' (' + task.id + ')' || task.id}}'?</p>\n</div>\n\n<div class=\"modal-footer-wrapper\">\n\t<div class=\"modal-footer\">\n\t\t<div class=\"pull-right\">\n\t        <button type=\"button\" class=\"btn btn-sm btn-default\" ng-click=\"cancel()\" ng-disabled=\"status.loading\"\n\t       \t\ttranslate=\"GENERAL.ACTION.CANCEL\">\n\t       \t</button>\n\t       <button type=\"button\" class=\"btn btn-sm btn-default\" ng-click=\"ok()\" ng-disabled=\"status.loading\"\n\t       \t    translate=\"TASK.POPUP.RESOLVE.CONFIRM\">\n\t       </button>\n\t\t</div>\n        <loading-indicator></loading-indicator>\n</div>\n</div>"
  },
  {
    "path": "flowable-ui-web/admin/views/task.html",
    "content": "<div class=\"container\" id=\"detail-container\" ng-cloak ng-show=\"task\">\n\t<div class=\"row\">\n\t\t<div class=\"col-md-9\">\n\t\t\t<div class=\"component\" >\n\t\t\t\t<div class=\"title\">\n\t\t\t\t\t<div class=\"pull-right\">\n\t\t\t\t\t\t<a ng-click=\"returnToList()\" class=\"action\">&larr; {{'GENERAL.ACTION.RETURN-TO-LIST' | translate}}</a>\n\t\t\t\t\t</div>\n\t\t\t\t\t<h2>{{task.name &amp;&amp; task.name + \" - \" || \"\"}}{{task.id}}</h2>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"property-wrapper\">\n\t\t\t\t\t<table>\n\t\t\t\t\t\t<tr class=\"property\">\n\t\t\t\t\t\t\t<td class=\"property-name\" translate=\"TASK.ID\"></td>\n\t\t\t\t\t\t\t<td>{{task.id}}</td>\n\t\t\t\t\t\t\t<td class=\"property-name\" translate=\"TASK.STATUS\"></td>\n\t\t\t\t\t\t\t<td>{{task.endTime &amp;&amp; ('TASK.STATUS-COMPLETED' | translate) || ('TASK.STATUS-ACTIVE' | translate)}}</td>\n\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t<tr class=\"property\">\n\t\t\t\t\t\t\t<td class=\"property-name\" translate=\"TASK.NAME\"></td>\n\t\t\t\t\t\t\t<td>{{task.name | empty}}</td>\n\t\t\t\t\t\t\t<td class=\"property-name\" translate=\"TASK.DESCRIPTION\"></td>\n\t\t\t\t\t\t\t<td>{{task.description | empty}}</td>\n\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t<tr class=\"property\">\n\t\t\t\t\t\t\t<td class=\"property-name\" translate=\"TASK.TASK-DEFINITION-KEY\"></td>\n\t\t\t\t\t\t\t<td>{{task.taskDefinitionKey | empty}}</td>\n\t\t\t\t\t\t\t<td class=\"property-name\" translate=\"TASK.FORM-KEY\"></td>\n\t\t\t\t\t\t\t<td ng-if=\"task.formKey && task.endTime\"> {{task.formKey | empty}} <a ng-click=\"showTaskForm()\"><i class=\"glyphicon glyphicon-zoom-in\"></i> {{'TASK.ACTION.SHOW-SUBMITTED-FORM' | translate}}</a></td>\n\t\t\t\t\t\t\t<td ng-if=\"!task.endTime && task.formKey\">\n\t\t\t\t\t\t\t\t<a ng-href=\"#/form/{{task.formKey}}\"><i class=\"glyphicon glyphicon-zoom-in\"></i> {{task.formKey}}</a>\n\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t<tr class=\"property\">\n\t\t\t\t\t\t\t<td class=\"property-name\" translate=\"TASK.PRIORITY\"></td>\n\t\t\t\t\t\t\t<td>{{task.priority | empty}}</td>\n\t\t\t\t\t\t\t<td class=\"property-name\" translate=\"TASK.DELEGATION-STATE\"></td>\n\t\t\t\t\t\t\t<td>{{task.delegationState | empty}}</td>\n\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t<tr class=\"property\">\n\t\t\t\t\t\t\t<td class=\"property-name\" translate=\"TASK.CATEGORY\"></td>\n\t\t\t\t\t\t\t<td>{{task.category | empty}}</td>\n\t\t\t\t\t\t\t<td class=\"property-name\" translate=\"TASK.PARENT\"></td>\n\t\t\t\t\t\t\t<td ng-if=\"task.parentTaskId\"><a ng-click=\"openTask(task.parentTaskId)\"><i class=\"glyphicon glyphicon-zoom-in\"></i> {{task.parentTaskId}}</a></td>\n\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t<tr class=\"property\">\n                            <td class=\"property-tenant\" translate=\"TASK.TENANT-ID\"></td>\n                            <td>{{task.tenantId | empty}}</td>\n                        </tr>\n\t\t\t\t\t</table>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"seperator\"></div>\n\t\t\t\t<div class=\"property-wrapper\">\n\t\t\t\t\t<table>\n\t\t\t\t\t\t<tr class=\"property\">\n\t\t\t\t\t\t\t<td class=\"property-name\"><span class=\"glyphicon glyphicon-user\"></span> {{'TASK.ASSIGNEE' | translate}}</td>\n\t\t\t\t\t\t\t<td>{{task.assignee | empty}}</td>\n\t\t\t\t\t\t\t<td class=\"property-name\"><span class=\"glyphicon glyphicon-user\"></span> {{'TASK.OWNER' | translate}}</td>\n\t\t\t\t\t\t\t<td>{{task.owner | empty}}</td>\n\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t<tr class=\"property\">\n\t\t\t\t\t\t\t<td class=\"property-name\"><span class=\"glyphicon glyphicon-time\"></span> {{'TASK.START-DATE' | translate}}</td>\n\t\t\t\t\t\t\t<td>{{task.startTime | dateformat | empty}}</td>\n\t\t\t\t\t\t\t<td class=\"property-name\"><span class=\"glyphicon glyphicon-time\"></span> {{'TASK.DUE-DATE' | translate}}</td>\n\t\t\t\t\t\t\t<td>{{task.dueDate | dateformat | empty}}</td>\n\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t<tr class=\"property\" ng-if=\"task.endTime\">\n\t\t\t\t\t\t\t<td class=\"property-name\"><span class=\"glyphicon glyphicon-time\"></span> {{'TASK.END-DATE' | translate}}</td>\n\t\t\t\t\t\t\t<td>{{task.endTime | dateformat | empty}}</td>\n\t\t\t\t\t\t\t<td class=\"property-name\" translate=\"TASK.DELETE-REASON\"></td>\n\t\t\t\t\t\t\t<td>{{task.deleteReason | empty}}</td>\n\t\t\t\t\t\t</tr>\n\t\t\t\t\t</table>\n\t\t\t\t</div>\n\t\t\t\t\n\t\t\t\t<!-- Only visible for tasks associated to an execution -->\n\t\t\t\t<div class=\"seperator\" ng-if=\"taskPartOfProcess\"></div>\n\t\t\t\t<div class=\"property-wrapper\">\n\t\t\t\t\t<table ng-if=\"taskPartOfProcess\">\n\t\t\t\t\t\t<tr class=\"property\">\n\t\t\t\t\t\t\t<td class=\"property-name\"></span> {{'TASK.PROCESS-INSTANCE' | translate}}</td>\n\t\t\t\t\t\t\t<td><a ng-click=\"openProcessInstance(task.processInstanceId)\"><i class=\"glyphicon glyphicon-zoom-in\"></i> {{task.processInstanceId | empty}}</a></td>\n\t\t\t\t\t\t\t<td class=\"property-name\" translate=\"TASK.EXECUTION-ID\"></td>\n\t\t\t\t\t\t\t<td><a><i class=\"glyphicon glyphicon-zoom-in\"></i> {{task.executionId | empty}}</a></td>\n\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t<tr class=\"property\">\n\t\t\t\t\t\t\t<td class=\"property-name\"></span> {{'TASK.PROCESS-DEFINITION' | translate}}</td>\n\t\t\t\t\t\t\t<td><a ng-click=\"openProcessDefinition(task.processDefinitionId)\"><i class=\"glyphicon glyphicon-zoom-in\"></i> {{task.processDefinitionId | empty}}</a></td>\n\t\t\t\t\t\t</tr>\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<div class=\"col-md-3\">\n\t\t\t<div class=\"component tip-left\">\n\t\t\t\t<div class=\"title\">\n\t\t\t\t\t<h2 translate=\"GENERAL.TITLE.ACTIONS\"></h2>\n\t\t\t\t</div>\n\t\t\t\t<ul class=\"list-group\">\n\t\t\t\t\t  <li ng-if=\"!taskCompleted\">\n\t\t\t\t\t    <button type=\"button\" class=\"btn btn-sm btn-default\"  ng-click=\"editTask()\">\n\t\t\t\t\t\t\t<i class=\"glyphicon glyphicon-pencil\"></i>{{'TASK.ACTION.EDIT' | translate}}\n\t\t\t\t\t    </button>\n\t\t\t\t\t  </li>\n\t\t\t\t\t  <li ng-if=\"!taskCompleted\">\n\t\t\t\t\t    <button type=\"button\" class=\"btn btn-sm btn-default\" ng-click=\"assignTask()\">\n\t\t\t\t\t\t\t<i class=\"glyphicon glyphicon-user\"></i>{{'TASK.ACTION.ASSIGN-CLAIM' | translate}}\n\t\t\t\t\t    </button>\n\t\t\t\t\t  </li>\n\t\t\t\t\t  <li ng-if=\"!taskCompleted && task.delegationState != 'pending' && task.delegationStateLoaded\">\n\t\t\t\t\t    <button type=\"button\" class=\"btn btn-sm btn-default\" ng-click=\"delegateTask()\">\n\t\t\t\t\t\t\t<i class=\"glyphicon glyphicon-transfer\"></i>{{'TASK.ACTION.DELEGATE' | translate}}\n\t\t\t\t\t    </button>\n\t\t\t\t\t  </li>\n\t\t\t\t\t   <li ng-if=\"!taskCompleted && task.delegationState == 'pending' && task.delegationStateLoaded\">\n\t\t\t\t\t    <button type=\"button\" class=\"btn btn-sm btn-default\" ng-click=\"resolveTask()\">\n\t\t\t\t\t\t\t<i class=\"glyphicon glyphicon-transfer\"></i>{{'TASK.ACTION.RESOLVE' | translate}}\n\t\t\t\t\t    </button>\n\t\t\t\t\t  </li>\n\t\t\t\t\t  <li ng-if=\"!taskCompleted\">\n\t\t\t\t\t    <button type=\"button\" class=\"btn btn-sm btn-default\" ng-click=\"completeTask()\">\n\t\t\t\t\t\t\t<i class=\"glyphicon glyphicon-check\"></i>{{'TASK.ACTION.COMPLETE' | translate}}\n\t\t\t\t\t    </button>\n\t\t\t\t\t  </li>\n\t\t\t\t\t  <li ng-if=\"taskCompleted || (!taskCompleted && !taskPartOfProcess)\">\n\t\t\t\t\t    <button type=\"button\" class=\"btn btn-sm btn-default btn-danger\" ng-click=\"deleteTask()\">\n\t\t\t\t\t\t\t<i class=\"glyphicon glyphicon-remove\"></i>{{'TASK.ACTION.DELETE' | translate}}\n\t\t\t\t\t    </button>\n\t\t\t\t\t  </li>\n\t\t\t    </ul>\n\t\t\t</div>\n\t\t</div>\n\t</div>\n\t<div class=\"row\">\n\t\t<div class=\"col-md-9\">\n\t\t\t<div class=\"component\">\n\t\t\t\t<div class=\"tabs-wrapper\">\n\t\t\t\t\t<div class=\"pull-right\">\n\t\t\t\t\t\t<a ng-click=\"showAllSubtasks()\" class=\"action\" ng-show=\"tabData.activeTab == tabData.tabs[0].id\"><i class=\"glyphicon glyphicon-zoom-in\"></i> {{'TASK.ACTION.SHOW-ALL-SUBTASKS' | translate}}</a>\n\t\t\t\t\t</div>\n\t\t       \t\t<div class=\"tabs clearfix\">\n\t\t       \t\t\t<div class=\"tab\" ng-repeat=\"tab in tabData.tabs\" ng-class=\"{'active': tabData.activeTab == tab.id}\">\n\t\t       \t\t\t\t<a ng-click=\"tabData.activeTab = tab.id\">\n\t\t       \t\t\t\t\t{{tab.name | translate:node}}&nbsp;\n\t\t    \t\t\t\t\t<span class=\"badge\" ng-if=\"tab.info != undefined\">{{tab.info}}</span>\n\t\t    \t\t\t\t</a>\n\t\t       \t\t\t</div>\n\t\t       \t\t</div>\n\t\t        \t<div class=\"title\"></div>\n\t\t        \t\n\t\t        \t<div class=\"grid-wrapper grid-wrapper-compact\" ng-if=\"subTasks && tabData.activeTab == tabData.tabs[0].id\">\n\t\t\t\t\t\t<div class=\"grid-message\" ng-if=\"subTasks.size > 0\">\n\t                        <span>{{'TASK.SUBTASKS-MESSAGE' | translate:subTasks}}</span>\n\t                    </div>\n\t                     <div class=\"grid-message\" ng-if=\"subTasks.size == 0\">\n\t                        <span>{{'TASK.SUBTASKS-MESSAGE-EMPTY' | translate}}</span>\n\t                    </div>\n\t\t\t\t\t\t<div ng-grid=\"subTaskGridDefinitions\" class=\"gridStyle\" ng-if=\"subTasks\" ng-show=\"subTasks.size > 0\"></div>\n\t\t\t\t\t</div>\n\t\t\t\t\t\n\t\t\t\t\t<div class=\"grid-wrapper grid-wrapper-compact\" ng-if=\"variables && tabData.activeTab == tabData.tabs[1].id\">\n\t\t\t\t\t\t<div class=\"grid-message\" ng-if=\"variables.size > 0\">\n\t                        <span>{{'TASK.VARIABLES-MESSAGE' | translate:variables}}</span>\n\t                    </div>\n\t                     <div class=\"grid-message\" ng-if=\"variables.size == 0\">\n\t                        <span>{{'TASK.VARIABLES-MESSAGE-EMPTY' | translate}}</span>\n\t                    </div>\n\t\t\t\t\t\t<div ng-grid=\"variableGridDefinitions\" class=\"gridStyle\" ng-if=\"variables\" ng-show=\"variables.size > 0\"></div>\n\t\t\t\t\t</div>\n\t\t\t\t\t\n\t\t\t\t\t<div class=\"grid-wrapper grid-wrapper-compact\" ng-if=\"identityLinks && tabData.activeTab == tabData.tabs[2].id\">\n\t\t\t\t\t\t<div class=\"grid-message\" ng-if=\"identityLinks.size > 0\">\n\t\t\t\t\t\t<span>{{'TASK.IDENTITY-LINKS-MESSAGE' | translate:identityLinks}}</span>\n\t                    </div>\n\t                     <div class=\"grid-message\" ng-if=\"identityLinks.size == 0\">\n\t                        <span>{{'TASK.IDENTITY-LINKS-MESSAGE-EMPTY' | translate}}</span>\n\t                    </div>\n\t\t\t\t\t\t<div ng-grid=\"identityLinkGridDefinitions\" class=\"gridStyle\" ng-if=\"identityLinks\" ng-show=\"identityLinks.size > 0\"></div>\n\t\t\t\t\t</div>\n\t\t        </div>\n\t\t    </div>\n\t\t</div>\n\t</div>\n</div>\n"
  },
  {
    "path": "flowable-ui-web/admin/views/tasks.html",
    "content": "<div class=\"container\" >\n    <div class=\"row\">\n        <div class=\"col-md-9\">\n            <div class=\"component\">\n                <div class=\"title\">\n                    <div class=\"btn-group btn-group-sm pull-right\">\n                        <div class=\"btn-group btn-group-sm\">\n                            <button type=\"button\" class=\"btn btn-default dropdown-toggle\" data-toggle=\"dropdown\"\n                                    translate=\"GENERAL.ACTION.SHOW-RESULTS\" translate-value-size=\"{{'GENERAL.RESULT-SIZES.' + filter.resultSize | translate}}\">\n                                &nbsp;\n                                <span class=\"caret\"></span>\n                            </button>\n                            <ul class=\"dropdown-menu\">\n                            \t<li ng-repeat=\"resultSize in config.filter.resultSizes\"><a href=\"\" ng-click=\"filter.setResultSize(resultSize)\">{{'GENERAL.RESULT-SIZES.' + resultSize.toString() | translate}}</a></li>\n                            </ul>\n                        </div>\n                        <button type=\"button\" class=\"btn btn-default\" ng-click=\"filter.toggleOrder()\">\n                        \t<i class=\"glyphicon\" ng-class=\"{'glyphicon-sort-by-attributes': filter.order == 'asc', 'glyphicon-sort-by-attributes-alt': filter.order == 'desc'}\"></i>\n                        </button>\n                    </div>\n                    <div class=\"btn-group btn-group-sm pull-right\">\n                    \t<button type=\"button\" class=\"btn btn-default dropdown-toggle\" data-toggle=\"dropdown\"\n                                translate=\"GENERAL.ACTION.SHOW-RESULTS\" translate-value-size=\"{{'GENERAL.RESULT-SIZES.' + filter.resultSize | translate}}\">\n                            &nbsp;\n                            <span class=\"caret\"></span>\n                        </button>\n                    \t<ul class=\"dropdown-menu\">\n                           <li ng-repeat=\"sort in filter.sortObjects\"><a href=\"\" ng-click=\"filter.setSort(sort)\">{{sort.name | translate}}</a></li>\n                        </ul>\n                    </div>\n                    <div class=\"btn-group btn-group-sm pull-right\">\n                        <a class=\"btn btn-default\" role=\"button\"\n                           title=\"{{'GENERAL.ACTION.REFRESH-LIST' | translate}}\"\n                           ng-click=\"filter.refresh();\">\n                            <i class=\"glyphicon glyphicon-refresh\"></i>\n                        </a>\n                    </div>\n                    <div class=\"pull-right loading\" ng-show=\"filter.loading\">\n                    \t<i class=\"glyphicon glyphicon-refresh\"></i>\n                    </div>\n\n                    <h2 translate=\"TASKS.TITLE\"></h2>\n                </div>\n\n                <div class=\"grid-wrapper\" id=\"process-instances\">\n                    <div class=\"grid-message\" ng-if=\"taskData.size > 0\">\n                        <span>{{'TASKS.LIST-MESSAGE' | translate:taskData}}</span>\n                    </div>\n                     <div class=\"grid-message\" ng-if=\"taskData.size == 0\">\n                        <span>{{'TASKS.LIST-MESSAGE-EMPTY' | translate}}</span>\n                    </div>\n                    <div ng-grid=\"gridDefinitions\" class=\"gridStyle\" ng-if=\"gridDefinitions && taskData.data\" />\n                </div>\n            </div>\n        </div>\n\n\t\t<!-- Task filters -->\n\t\t<div class=\"col-md-3\">\n            <div class=\"component tip-left\">\n                <div class=\"title\">\n                    <div class=\"btn-group btn-group-sm pull-right\" ng-show=\"filter.supportedProperties.length > 0\">\n                        <button type=\"button\" class=\"btn btn-default\" data-toggle=\"dropdown\">\n                            <i class=\"glyphicon glyphicon-plus\"></i>\n                        </button>\n                        <ul class=\"dropdown-menu\">\n                            <li ng-repeat=\"prop in filter.supportedProperties\"><a href=\"\" ng-click=\"addFilterProperty(prop)\">{{prop.name | translate}}</a></li>\n                        </ul>\n                    </div>\n                   <div class=\"pull-right\">\n                        <a class=\"action\" ng-click=\"clearFilters()\" translate=\"GENERAL.ACTION.CLEAR-FILTERS\"></a>\n                    </div>\n                    <h2 translate=\"GENERAL.TITLE.FILTERS\"></h2>\n                </div>\n                <div class=\"section\" ng-if=\"filter.properties.finished !== undefined\">\n                    <div class=\"subtitle\"><label for=\"filter-finished\" translate=\"TASKS.FILTER.STATUS\"></label> </div>\n                    <div class=\"input-group input-group-sm\" id=\"filter-state\">\n                       <div class=\"btn-group btn-group-sm\">\n                    \t<button type=\"button\" id=\"filter-finished\" class=\"btn btn-default dropdown-toggle form-control\" data-toggle=\"dropdown\">\n                            <span class=\"pull-right\">\n                            \t<span class=\"caret\"></span>\n                            </span>\n                    \t\t{{filter.getLabelForOption('finished') | translate}}\n                        </button>\n                    \t<ul class=\"dropdown-menu\">\n                            <li ng-repeat=\"state in filter.options.finished\"><a href=\"\" ng-click=\"filter.selectOption('finished', state)\">{{state.name | translate}}</a></li>\n                        </ul>\n                    </div>\n                    </div>\n                </div>\n                <div class=\"section\" ng-if=\"filter.properties.taskNameLike !== undefined\">\n                    <div class=\"subtitle\"><label for=\"filter-taskNameLike\" translate=\"TASKS.FILTER.NAME\"></label> </div>\n                    <div class=\"input-group input-group-sm\">\n                        <input id=\"filter-taskNameLike\" type=\"text\" class=\"form-control\" value=\"\" ng-model=\"filter.properties.taskNameLike\" ng-change=\"filter.refreshDelayed()\">\n                    </div>\n                </div>\n\n                <div class=\"seperator\"></div>\n                <!-- People filtering -->\n                <div class=\"section\" ng-if=\"filter.properties.taskAssignee !== undefined\">\n                    <div class=\"subtitle\"><label for=\"filter-taskAssignee\"><span class=\"glyphicon glyphicon-user\"></span> {{'TASKS.FILTER.ASSIGNEE' | translate}}</label> </div>\n                    <div class=\"input-group input-group-sm type-ahead-scrollable\">\n                    \t<input id=\"filter-taskAssignee\" type=\"text\" users-typeahead user-model=\"filter.properties.taskAssignee\" user-display-model=\"assigneeFilter\" user-on-change=\"filter.refreshDelayed()\" class=\"form-control\">\n                    </div>\n                </div>\n                <div class=\"section\" ng-if=\"filter.properties.taskOwner !== undefined\">\n                    <div class=\"subtitle\"><label for=\"filter-taskOwner\"><span class=\"glyphicon glyphicon-user\"></span> {{'TASKS.FILTER.OWNER' | translate}}</label> </div>\n                    <div class=\"input-group input-group-sm type-ahead-scrollable\">\n                    \t<input id=\"filter-taskOwner\" type=\"text\" users-typeahead user-model=\"filter.properties.taskOwner\" user-display-model=\"ownerFilter\" user-on-change=\"filter.refreshDelayed()\" class=\"form-control\">\n                    </div>\n                </div>\n                <div class=\"section\" ng-if=\"filter.properties.parentTaskId !== undefined\">\n                    <div class=\"subtitle\"><label for=\"filter-parentTaskId\" translate=\"TASKS.FILTER.PARENT-TASK-ID\"></label> </div>\n                    <div class=\"input-group input-group-sm\">\n                        <input id=\"filter-parentTaskId\" type=\"text\" class=\"form-control\" value=\"\" ng-model=\"filter.properties.parentTaskId\" ng-change=\"filter.refreshDelayed()\">\n                    </div>\n                </div>\n                <div class=\"section\" ng-if=\"filter.properties.processInstanceId !== undefined\">\n                    <div class=\"subtitle\"><label for=\"filter-processInstanceId\" translate=\"TASKS.FILTER.PROCESS-INSTANCE-ID\"></label> </div>\n                    <div class=\"input-group input-group-sm\">\n                        <input id=\"filter-processInstanceId\" type=\"text\" class=\"form-control\" value=\"\" ng-model=\"filter.properties.processInstanceId\" ng-change=\"filter.refreshDelayed()\">\n                    </div>\n                </div>\n                <div class=\"section\" ng-if=\"filter.properties.tenantIdLike !== undefined\">\n                    <div class=\"subtitle\"><label for=\"filter-tenantid\">{{'TASKS.FILTER.TENANT-ID' | translate}}</label> </div>\n                    <div class=\"input-group input-group-sm\">\n                        <input id=\"filter-tenantid\" type=\"text\" class=\"form-control\" value=\"\" ng-model=\"filter.properties.tenantIdLike\" ng-change=\"filter.refreshDelayed()\">\n                    </div>\n                </div>\n                <!-- Date filtering -->\n                <div class=\"section\" ng-if=\"filter.properties.dueBefore !== undefined\">\n                  <div class=\"subtitle\"><label for=\"filter-dueBefore\" translate=\"TASKS.FILTER.DUE-BEFORE\"></label> </div>\n               \t  <div class=\"input-group input-group-sm\">\n               \t  \t<span class=\"input-group-addon\"><span class=\"glyphicon glyphicon-time\"></span></span>\n\t              \t<input id=\"filter-dueBefore\" type=\"text\" class=\"form-control\" ng-model=\"filter.properties.dueDateBefore\"\n                           ng-change=\"filter.refreshDelayed()\"\n                           datepicker-popup=\"dd/MM/yyyy\"\n                           is-open=\"dueBeforePicker.isOpen\" ng-click=\"dueBeforePicker.isOpen=true\"/>\n\t              </div>\n\t            </div>\n                <div class=\"section\" ng-if=\"filter.properties.dueAfter !== undefined\">\n\t              <div class=\"subtitle\"><label for=\"filter-dueAfter\" translate=\"TASKS.FILTER.DUE-AFTER\"></label> </div>\n               \t  <div class=\"input-group input-group-sm\">\n               \t  \t<span class=\"input-group-addon\"><span class=\"glyphicon glyphicon-time\"></span></span>\n\t              \t<input id=\"filter-dueAfter\" type=\"text\" class=\"form-control\" ng-model=\"filter.properties.dueDateAfter\"\n                           ng-change=\"filter.refreshDelayed()\"\n                           datepicker-popup=\"dd/MM/yyyy\"\n                           is-open=\"dueAfterPicker.isOpen\" ng-click=\"dueAfterPicker.isOpen=true\"/>\n\t              </div>\n\t            </div>\n\n\t            <div class=\"section\" ng-if=\"filter.properties.taskCreatedBefore !== undefined\">\n                  <div class=\"subtitle\"><label for=\"filter-taskCreatedBefore\" translate=\"TASKS.FILTER.CREATED-BEFORE\"></label> </div>\n               \t  <div class=\"input-group input-group-sm\">\n               \t  \t<span class=\"input-group-addon\"><span class=\"glyphicon glyphicon-time\"></span></span>\n\t              \t<input id=\"filter-taskCreatedBefore\" type=\"text\" class=\"form-control\" ng-model=\"filter.properties.taskCreatedBefore\"\n                           ng-change=\"filter.refreshDelayed()\"\n                           datepicker-popup=\"dd/MM/yyyy\"\n                           is-open=\"createdBeforePicker.isOpen\" ng-click=\"createdBeforePicker.isOpen=true\"/>\n\t              </div>\n\t            </div>\n                <div class=\"section\" ng-if=\"filter.properties.taskCreatedAfter !== undefined\">\n\t              <div class=\"subtitle\"><label for=\"filter-taskCreatedAfter\" translate=\"TASKS.FILTER.CREATED-AFTER\"></label> </div>\n               \t  <div class=\"input-group input-group-sm\">\n               \t  \t<span class=\"input-group-addon\"><span class=\"glyphicon glyphicon-time\"></span></span>\n\t              \t<input id=\"filter-taskCreatedAfter\" type=\"text\" class=\"form-control\" ng-model=\"filter.properties.taskCreatedAfter\"\n                           ng-change=\"filter.refreshDelayed()\"\n                           datepicker-popup=\"dd/MM/yyyy\"\n                           is-open=\"createdAfterPicker.isOpen\" ng-click=\"createdAfterPicker.isOpen=true\"/>\n\t              </div>\n\t            </div>\n\n\t            <div class=\"section\" ng-if=\"filter.properties.taskCompletedBefore !== undefined\">\n                  <div class=\"subtitle\"><label for=\"filter-taskCompletedBefore\" translate=\"TASKS.FILTER.ENDED-BEFORE\"></label> </div>\n               \t  <div class=\"input-group input-group-sm\">\n               \t  \t<span class=\"input-group-addon\"><span class=\"glyphicon glyphicon-time\"></span></span>\n\t              \t<input id=\"filter-taskCompletedBefore\" type=\"text\" class=\"form-control\" ng-model=\"filter.properties.taskCompletedBefore\"\n                           ng-change=\"filter.refreshDelayed()\"\n                           datepicker-popup=\"dd/MM/yyyy\"\n                           is-open=\"completedBeforePicker.isOpen\" ng-click=\"completedBeforePicker.isOpen=true\"/>\n\t              </div>\n\t            </div>\n                <div class=\"section\" ng-if=\"filter.properties.taskCompletedAfter !== undefined\">\n\t              <div class=\"subtitle\"><label for=\"filter-taskCompletedAfter\" translate=\"TASKS.FILTER.ENDED-AFTER\"></label> </div>\n               \t  <div class=\"input-group input-group-sm\">\n               \t  \t<span class=\"input-group-addon\"><span class=\"glyphicon glyphicon-time\"></span></span>\n\t              \t<input id=\"filter-taskCompletedAfter\" type=\"text\" class=\"form-control\" ng-model=\"filter.properties.taskCompletedAfter\"\n                           ng-change=\"filter.refreshDelayed()\"\n                           datepicker-popup=\"dd/MM/yyyy\"\n                           is-open=\"completedAfterPicker.isOpen\" ng-click=\"completedAfterPicker.isOpen=true\"/>\n\t              </div>\n\t            </div>\n\n\t            <div class=\"section clearfix\" ng-repeat=\"varFilter in filter.properties.taskVariables\">\n\t              <div class=\"seperator\" ng-if=\"$index > 0\"></div>\n\t              <div class=\"subtitle\"><label translate=\"TASKS.FILTER.TASK-VARIABLE\"></label> </div>\n               \t  <div class=\"inline-button input-group-sm\">\n\t              \t\t<div class=\"pull-right btn-group\">\n\t                        <button ng-disabled=\"varFilter.type.id == 'boolean'\" tabindex=\"-1\" type=\"button\" class=\"btn btn-sm btn-default dropdown-toggle\" data-toggle=\"dropdown\">\n\t                             {{varFilter.operator.sign}} <i class=\"caret\"></i>\n\t                        </button>\n\t                        <ul class=\"dropdown-menu\">\n\t                            <li><a href=\"\" ng-click=\"setVariableFilterOperator(varFilter, operator)\" ng-repeat=\"operator in variableFilterOperators\">{{operator.name}}</a></li>\n\t                        </ul>\n\t                    </div>\n\t              \t\t<input id=\"filter-taskVariables-name-{{$index}}\" type=\"text\" class=\"form-control\" ng-model=\"varFilter.name\" ng-change=\"filter.refreshDelayed()\" placeholder=\"{{'TASKS.FILTER.VARIABLE-NAME' | translate}}\" />\n\t              </div>\n               \t  <div class=\"inline-button wide input-group-sm\" >\n\t              \t\t<div class=\"pull-right btn-group\">\n\t                        <button tabindex=\"-1\" ng-disabled=\"varFilter.operator.id == 'like'\" type=\"button\" class=\"btn btn-sm btn-default dropdown-toggle\" data-toggle=\"dropdown\">\n\t                           {{varFilter.type.name}} <i class=\"caret\"></i>\n\t                        </button>\n\t                        <ul class=\"dropdown-menu\">\n\t                            <li><a href=\"\" ng-click=\"setVariableFilterType(varFilter, type)\" ng-repeat=\"type in variableFilterTypes\" >{{type.name}}</a></li>\n\t                        </ul>\n\t                    </div>\n\t              \t\t<input ng-if=\"varFilter.type.id != 'date' && varFilter.type.id != 'boolean'\" id=\"filter-taskVariables-value-{{$index}}\" type=\"text\" class=\"form-control\" ng-model=\"varFilter.value\" ng-change=\"filter.refreshDelayed()\" placeholder=\"{{'TASKS.FILTER.VARIABLE-VALUE' | translate}}\" />\n\t              \t\t<input ng-if=\"varFilter.type.id == 'date'\" id=\"filter-taskVariables-value-{{$index}}\" type=\"text\" class=\"form-control\" ng-model=\"varFilter.value\"\n                               ng-change=\"filter.refresh()\"\n                               datepicker-popup=\"dd/MM/yyyy\"\n                               is-open=\"varValuePicker.isOpen\" ng-click=\"varValuePicker.isOpen=true\"/>\n\t              \t\t<div class=\"checkbox\" ng-if=\"varFilter.type.id == 'boolean'\">\n\t\t\t\t\t\t    <label>\n\t\t\t\t\t\t      <input type=\"checkbox\" ng-change=\"filter.refresh()\" ng-model=\"varFilter.value\">{{'TASKS.FILTER.VARIABLE-BOOLEAN-VALUE' | translate:varFilter}}\n\t\t\t\t\t\t    </label>\n  \t\t\t\t\t\t</div>\n\t              </div>\n\t            </div>\n\n\t            <div class=\"section clearfix\" ng-repeat=\"varFilter in filter.properties.processVariables\">\n\t              <div class=\"seperator\" ng-if=\"$index > 0 || filter.properties.taskVariables.length > 0\"></div>\n\t              <div class=\"subtitle\"><label translate=\"TASKS.FILTER.PROCESS-VARIABLE\"></label> </div>\n               \t  <div class=\"inline-button input-group-sm\">\n\t              \t\t<div class=\"pull-right btn-group\">\n\t                        <button ng-disabled=\"varFilter.type.id == 'boolean'\" tabindex=\"-1\" type=\"button\" class=\"btn btn-sm btn-default dropdown-toggle\" data-toggle=\"dropdown\">\n\t                             {{varFilter.operator.sign}} <i class=\"caret\"></i>\n\t                        </button>\n\t                        <ul class=\"dropdown-menu\">\n\t                            <li><a href=\"\" ng-click=\"setVariableFilterOperator(varFilter, operator)\" ng-repeat=\"operator in variableFilterOperators\">{{operator.name}}</a></li>\n\t                        </ul>\n\t                    </div>\n\t              \t\t<input id=\"filter-processVariables-name-{{$index}}\" type=\"text\" class=\"form-control\" ng-model=\"varFilter.name\" ng-change=\"filter.refreshDelayed()\" placeholder=\"{{'TASKS.FILTER.VARIABLE-NAME' | translate}}\" />\n\t              </div>\n               \t  <div class=\"inline-button wide input-group-sm\" >\n\t              \t\t<div class=\"pull-right btn-group\">\n\t                        <button tabindex=\"-1\" ng-disabled=\"varFilter.operator.id == 'like'\" type=\"button\" class=\"btn btn-sm btn-default dropdown-toggle\" data-toggle=\"dropdown\">\n\t                           {{varFilter.type.name}} <i class=\"caret\"></i>\n\t                        </button>\n\t                        <ul class=\"dropdown-menu\">\n\t                            <li><a href=\"\" ng-click=\"setVariableFilterType(varFilter, type)\" ng-repeat=\"type in variableFilterTypes\" >{{type.name}}</a></li>\n\t                        </ul>\n\t                    </div>\n\t              \t\t<input ng-if=\"varFilter.type.id != 'date' && varFilter.type.id != 'boolean'\" id=\"filter-processVariables-value-{{$index}}\" type=\"text\" class=\"form-control\" ng-model=\"varFilter.value\" ng-change=\"filter.refreshDelayed()\" placeholder=\"{{'TASKS.FILTER.VARIABLE-VALUE' | translate}}\" />\n\t              \t\t<input ng-if=\"varFilter.type.id == 'date'\" id=\"filter-processVariables-value-{{$index}}\" type=\"text\" class=\"form-control\" ng-model=\"varFilter.value\"\n                               ng-change=\"filter.refresh()\"\n                               datepicker-popup=\"dd/MM/yyyy\"\n                               is-open=\"processVarValuePicker.isOpen\" ng-click=\"processVarValuePicker.isOpen=true\"/>\n\t              \t\t<div class=\"checkbox\" ng-if=\"varFilter.type.id == 'boolean'\">\n\t\t\t\t\t\t    <label>\n\t\t\t\t\t\t      <input type=\"checkbox\" ng-change=\"filter.refresh()\" ng-model=\"varFilter.value\">{{'TASKS.FILTER.VARIABLE-BOOLEAN-VALUE' | translate:varFilter}}\n\t\t\t\t\t\t    </label>\n  \t\t\t\t\t\t</div>\n\t              </div>\n\t            </div>\n            </div>\n        </div>\n    </div>\n</div>\n"
  },
  {
    "path": "flowable-ui-web/admin/views/update-variable-popup.html",
    "content": "<div class=\"modal-header-wrapper\">\n\t<div class=\"modal-header\">\n\t\t<div class=\"pull-right\">\n            <a class=\"action\" ng-click=\"cancel()\">&times; {{'GENERAL.ACTION.CANCEL-AND-CLOSE' | translate}}</a>\n        </div>\n\t\t<h2>{{'PROCESS-INSTANCE.POPUP.UPDATE-VARIABLE.TITLE' | translate:originalVariable.variable}}</h2>\n\t</div>\n</div>\n<div class=\"modal-body\">\n\n    <div ng-switch on=\"originalVariable.type\" style=\"margin-top:10px\">\n\n        <div style=\"margin-bottom: 10px\">{{'PROCESS-INSTANCE.POPUP.UPDATE-VARIABLE.VALUE' | translate}}</div>\n        <div ng-switch-when=\"string\">\n            <input class=\"form-control\" type=\"text\" ng-model=\"updateVariable.value\">\n        </div>\n        <div ng-switch-when=\"boolean\">\n            <input type=\"checkbox\" ng-model=\"updateVariable.value\">\n            <span ng-show=\"updateVariable.value\">{{'PROCESS-INSTANCE.POPUP.UPDATE-VARIABLE.CHECKED' | translate}}</span>\n            <span ng-show=\"!updateVariable.value\">{{'PROCESS-INSTANCE.POPUP.UPDATE-VARIABLE.UNCHECKED' | translate}}</span>\n        </div>\n        <div ng-switch-when=\"date\">\n            <input class=\"form-control\" type=\"text\" ng-model=\"updateVariable.value\">\n            <div style=\"margin: 5px 0 0 5px; font-size:12px\">{{'PROCESS-INSTANCE.POPUP.UPDATE-VARIABLE.DATE-HELP' | translate}}</div>\n        </div>\n        <div ng-switch-when=\"double\">\n            <input class=\"form-control\" type=\"number\" ng-model=\"updateVariable.value\">\n        </div>\n        <div ng-switch-when=\"integer\">\n            <input class=\"form-control\" type=\"number\" ng-model=\"updateVariable.value\">\n        </div>\n        <div ng-switch-when=\"long\">\n            <input class=\"form-control\" type=\"number\" ng-model=\"updateVariable.value\">\n        </div>\n        <div ng-switch-when=\"short\">\n            <input class=\"form-control\" type=\"number\" ng-model=\"updateVariable.value\">\n        </div>\n        <div ng-switch-default>\n            <input class=\"form-control\" type=\"text\" ng-model=\"updateVariable.value\">\n        </div>\n    </div>\n</div>\n\n<div class=\"modal-footer-wrapper\">\n\t<div class=\"modal-footer\">\n\t\t<div class=\"pull-right\">\n\t       <button type=\"button\" class=\"btn btn-sm btn-default\" ng-click=\"cancel()\" ng-disabled=\"status.loading\"\n\t       \ttranslate=\"GENERAL.ACTION.CANCEL\">\n\t       \t</button>\n\t       <button type=\"button\" class=\"btn btn-sm btn-info\" ng-click=\"executeUpdateVariable()\" ng-disabled=\"status.loading\">\n               {{'PROCESS-INSTANCE.POPUP.UPDATE-VARIABLE.ACTION-UPDATE' | translate}}\n\t       </button>\n\t\t</div>\n        <loading-indicator></loading-indicator>\n</div>\n</div>\n"
  },
  {
    "path": "flowable-ui-web/admin/views/upload-app.html",
    "content": "<div class=\"modal-header-wrapper\">\n\t<div class=\"modal-header\">\n\t\t<div class=\"pull-right\">\n            <a class=\"action\" ng-click=\"cancel()\">&times; {{'GENERAL.ACTION.CANCEL-AND-CLOSE' | translate}}</a>\n        </div>\n\t\t<h2 translate=\"APP-DEPLOYMENTS.ACTION.UPLOAD\"></h2>\n\t</div>\n</div>\n<div class=\"modal-body\">\n\n    <p>\n        <i class=\"glyphicon glyphicon-info-sign\"></i>\n        {{'APP-DEPLOYMENTS.POPUP.UPLOAD.DESCRIPTION' | translate}}\n    </p>\n\n    <!--<p class=\"text-warning\">-->\n        <!--<i class=\"glyphicon glyphicon-info-sign\"></i>-->\n        <!--{{'APP-DEPLOYMENTS.POPUP.UPLOAD.WARNING' | translate}}-->\n    <!--</p>-->\n\n    <div class=\"upload-deployment-form\">\n\n        <input type=\"file\" ngf-select=\"onFileSelect($files)\" style=\"font-size: smaller; padding-top:6px;\" >\n        <div class=\"dropbox\"\n             ngf-drop=\"onFileSelect($files)\"\n             ngf-drag-over-class=\"dragover\"\n             ng-show=\"dropSupported\">\n            {{'APP-DEPLOYMENTS.POPUP.UPLOAD.DROPZONE' | translate}}\n        </div>\n        <div ngf-drop-available=\"dropSupported=true\"\n             ng-show=\"!dropSupported\">{{'DEPLOYMENTS.POPUP.UPLOAD.NO-DROP' | translate}}</div>\n        <div class=\"graph-wrapper\" ng-show=\"status.loading\" style=\"margin: 10px 0 10px 0\">\n            <div class=\"graph-bar\" style=\"width:{{model.uploadProgress}}%\"></div>\n        </div>\n        <button class=\"btn btn-danger btn-sm\"\n                ng-click=\"upload.abort()\"\n                ng-disabled=\"!status.loading\"\n                style=\"margin-bottom: 20px\">\n            APP-DEPLOYMENTS        </button>\n\n    </div>\n\n</div>\n\n<div class=\"modal-footer-wrapper\">\n    <div class=\"modal-footer\">\n        <loading-indicator></loading-indicator>\n        <div class=\"pull-right modeler-processes-error\" ng-if=\"model.error\">\n            <span>{{'APP-DEPLOYMENTS.POPUP.UPLOAD.ERROR' | translate}} <span ng-if=\"model.errorMessage\"> : </span>{{model.errorMessage}}</span>\n        </div>\n    </div>\n</div>\n"
  },
  {
    "path": "flowable-ui-web/admin/views/upload-cmmn-deployment.html",
    "content": "<div class=\"modal-header-wrapper\">\n\t<div class=\"modal-header\">\n\t\t<div class=\"pull-right\">\n            <a class=\"action\" ng-click=\"cancel()\">&times; {{'GENERAL.ACTION.CANCEL-AND-CLOSE' | translate}}</a>\n        </div>\n\t\t<h2 translate=\"CMMN-DEPLOYMENTS.ACTION.UPLOAD\"></h2>\n\t</div>\n</div>\n<div class=\"modal-body\">\n\n    <p>\n        <i class=\"glyphicon glyphicon-info-sign\"></i>\n        {{'CMMN-DEPLOYMENTS.POPUP.UPLOAD.DESCRIPTION' | translate}}\n    </p>\n\n    <div class=\"upload-deployment-form\">\n\n        <input type=\"file\" ngf-select=\"onFileSelect($files)\" style=\"font-size: smaller; padding-top:6px;\" >\n        <div class=\"dropbox\"\n             ngf-drop=\"onFileSelect($files)\"\n             ngf-drag-over-class=\"dragover\"\n             ng-show=\"dropSupported\">\n            {{'CMMN-DEPLOYMENTS.POPUP.UPLOAD.DROPZONE' | translate}}\n        </div>\n        <div ngf-drop-available=\"dropSupported=true\"\n             ng-show=\"!dropSupported\">{{'CMMN-DEPLOYMENTS.POPUP.UPLOAD.NO-DROP' | translate}}</div>\n        <div class=\"graph-wrapper\" ng-show=\"status.loading\" style=\"margin: 10px 0 10px 0\">\n            <div class=\"graph-bar\" style=\"width:{{model.uploadProgress}}%\"></div>\n        </div>\n        <button class=\"btn btn-danger btn-sm\"\n                ng-click=\"upload.abort()\"\n                ng-disabled=\"!status.loading\"\n                style=\"margin-bottom: 20px\">\n            {{'CMMN-DEPLOYMENTS.POPUP.UPLOAD.CANCEL-UPLOAD' | translate}}\n        </button>\n\n    </div>\n\n</div>\n\n<div class=\"modal-footer-wrapper\">\n    <div class=\"modal-footer\">\n        <loading-indicator></loading-indicator>\n        <div class=\"pull-right modeler-processes-error\" ng-if=\"model.error\">\n            <span>{{'CMMN-DEPLOYMENTS.POPUP.UPLOAD.ERROR' | translate}} <span ng-if=\"model.errorMessage\"> : </span>{{model.errorMessage}}</span>\n        </div>\n    </div>\n</div>\n"
  },
  {
    "path": "flowable-ui-web/admin/views/upload-deployment.html",
    "content": "<div class=\"modal-header-wrapper\">\n\t<div class=\"modal-header\">\n\t\t<div class=\"pull-right\">\n            <a class=\"action\" ng-click=\"cancel()\">&times; {{'GENERAL.ACTION.CANCEL-AND-CLOSE' | translate}}</a>\n        </div>\n\t\t<h2 translate=\"DEPLOYMENTS.ACTION.UPLOAD\"></h2>\n\t</div>\n</div>\n<div class=\"modal-body\">\n\n    <p>\n        <i class=\"glyphicon glyphicon-info-sign\"></i>\n        {{'DEPLOYMENTS.POPUP.UPLOAD.DESCRIPTION' | translate}}\n    </p>\n\n    <div class=\"upload-deployment-form\">\n\n        <input type=\"file\" ngf-select=\"onFileSelect($files)\" style=\"font-size: smaller; padding-top:6px;\" >\n        <div class=\"dropbox\"\n             ngf-drop=\"onFileSelect($files)\"\n             ngf-drag-over-class=\"dragover\"\n             ng-show=\"dropSupported\">\n            {{'DEPLOYMENTS.POPUP.UPLOAD.DROPZONE' | translate}}\n        </div>\n        <div ngf-drop-available=\"dropSupported=true\"\n             ng-show=\"!dropSupported\">{{'DEPLOYMENTS.POPUP.UPLOAD.NO-DROP' | translate}}</div>\n        <div class=\"graph-wrapper\" ng-show=\"status.loading\" style=\"margin: 10px 0 10px 0\">\n            <div class=\"graph-bar\" style=\"width:{{model.uploadProgress}}%\"></div>\n        </div>\n        <button class=\"btn btn-danger btn-sm\"\n                ng-click=\"upload.abort()\"\n                ng-disabled=\"!status.loading\"\n                style=\"margin-bottom: 20px\">\n            {{'DEPLOYMENTS.POPUP.UPLOAD.CANCEL-UPLOAD' | translate}}\n        </button>\n\n    </div>\n\n</div>\n\n<div class=\"modal-footer-wrapper\">\n    <div class=\"modal-footer\">\n        <loading-indicator></loading-indicator>\n        <div class=\"pull-right modeler-processes-error\" ng-if=\"model.error\">\n            <span>{{'DEPLOYMENTS.POPUP.UPLOAD.ERROR' | translate}} <span ng-if=\"model.errorMessage\"> : </span>{{model.errorMessage}}</span>\n        </div>\n    </div>\n</div>\n"
  },
  {
    "path": "flowable-ui-web/admin/views/upload-dmn-deployment.html",
    "content": "<div class=\"modal-header-wrapper\">\n\t<div class=\"modal-header\">\n\t\t<div class=\"pull-right\">\n            <a class=\"action\" ng-click=\"cancel()\">&times; {{'GENERAL.ACTION.CANCEL-AND-CLOSE' | translate}}</a>\n        </div>\n\t\t<h2 translate=\"DECISION-TABLE-DEPLOYMENTS.ACTION.UPLOAD\"></h2>\n\t</div>\n</div>\n<div class=\"modal-body\">\n\n    <p>\n        <i class=\"glyphicon glyphicon-info-sign\"></i>\n        {{'DECISION-TABLE-DEPLOYMENTS.POPUP.UPLOAD.DESCRIPTION' | translate}}\n    </p>\n\n    <div class=\"upload-deployment-form\">\n\n        <input type=\"file\" ngf-select=\"onFileSelect($files)\" style=\"font-size: smaller; padding-top:6px;\" >\n        <div class=\"dropbox\"\n             ngf-drop=\"onFileSelect($files)\"\n             ngf-drag-over-class=\"dragover\"\n             ng-show=\"dropSupported\">\n            {{'DECISION-TABLE-DEPLOYMENTS.POPUP.UPLOAD.DROPZONE' | translate}}\n        </div>\n        <div ngf-drop-available=\"dropSupported=true\"\n             ng-show=\"!dropSupported\">{{'DECISION-TABLE-DEPLOYMENTS.POPUP.UPLOAD.NO-DROP' | translate}}</div>\n        <div class=\"graph-wrapper\" ng-show=\"status.loading\" style=\"margin: 10px 0 10px 0\">\n            <div class=\"graph-bar\" style=\"width:{{model.uploadProgress}}%\"></div>\n        </div>\n        <button class=\"btn btn-danger btn-sm\"\n                ng-click=\"upload.abort()\"\n                ng-disabled=\"!status.loading\"\n                style=\"margin-bottom: 20px\">\n            {{'DECISION-TABLE-DEPLOYMENTS.POPUP.UPLOAD.CANCEL-UPLOAD' | translate}}\n        </button>\n\n    </div>\n\n</div>\n\n<div class=\"modal-footer-wrapper\">\n    <div class=\"modal-footer\">\n        <loading-indicator></loading-indicator>\n        <div class=\"pull-right modeler-processes-error\" ng-if=\"model.error\">\n            <span>{{'DECISION-TABLE-DEPLOYMENTS.POPUP.UPLOAD.ERROR' | translate}} <span ng-if=\"model.errorMessage\"> : </span>{{model.errorMessage}}</span>\n        </div>\n    </div>\n</div>\n"
  },
  {
    "path": "flowable-ui-web/admin/views/upload-form-deployment.html",
    "content": "<div class=\"modal-header-wrapper\">\n\t<div class=\"modal-header\">\n\t\t<div class=\"pull-right\">\n            <a class=\"action\" ng-click=\"cancel()\">&times; {{'GENERAL.ACTION.CANCEL-AND-CLOSE' | translate}}</a>\n        </div>\n\t\t<h2 translate=\"FORM-DEPLOYMENTS.ACTION.UPLOAD\"></h2>\n\t</div>\n</div>\n<div class=\"modal-body\">\n\n    <p>\n        <i class=\"glyphicon glyphicon-info-sign\"></i>\n        {{'FORM-DEPLOYMENTS.POPUP.UPLOAD.DESCRIPTION' | translate}}\n    </p>\n\n    <div class=\"upload-deployment-form\">\n\n        <input type=\"file\" ngf-select=\"onFileSelect($files)\" style=\"font-size: smaller; padding-top:6px;\" >\n        <div class=\"dropbox\"\n             ngf-drop=\"onFileSelect($files)\"\n             ngf-drag-over-class=\"dragover\"\n             ng-show=\"dropSupported\">\n            {{'FORM-DEPLOYMENTS.POPUP.UPLOAD.DROPZONE' | translate}}\n        </div>\n        <div ngf-drop-available=\"dropSupported=true\"\n             ng-show=\"!dropSupported\">{{'FORM-DEPLOYMENTS.POPUP.UPLOAD.NO-DROP' | translate}}</div>\n        <div class=\"graph-wrapper\" ng-show=\"status.loading\" style=\"margin: 10px 0 10px 0\">\n            <div class=\"graph-bar\" style=\"width:{{model.uploadProgress}}%\"></div>\n        </div>\n        <button class=\"btn btn-danger btn-sm\"\n                ng-click=\"upload.abort()\"\n                ng-disabled=\"!status.loading\"\n                style=\"margin-bottom: 20px\">\n            {{'FORM-DEPLOYMENTS.POPUP.UPLOAD.CANCEL-UPLOAD' | translate}}\n        </button>\n\n    </div>\n\n</div>\n\n<div class=\"modal-footer-wrapper\">\n    <div class=\"modal-footer\">\n        <loading-indicator></loading-indicator>\n        <div class=\"pull-right modeler-processes-error\" ng-if=\"model.error\">\n            <span>{{'FORM-DEPLOYMENTS.POPUP.UPLOAD.ERROR' | translate}} <span ng-if=\"model.errorMessage\"> : </span>{{model.errorMessage}}</span>\n        </div>\n    </div>\n</div>\n"
  },
  {
    "path": "flowable-ui-web/admin/views/upload-from-modeler-popup.html",
    "content": "<div class=\"modal-header-wrapper\">\n\t<div class=\"modal-header\">\n\t\t<div class=\"pull-right\">\n            <a class=\"action\" ng-click=\"cancel()\">&times; {{'GENERAL.ACTION.CANCEL-AND-CLOSE' | translate}}</a>\n        </div>\n\t\t<h2 translate=\"PROCESS-DEFINITIONS.ACTIONS.UPLOAD-FROM-MODELER\"></h2>\n\t</div>\n</div>\n<div class=\"modal-body\">\n\n    <div class=\"upload-from-modeler-form\" ng-show=\"model.showingCredentials\">\n        <span class=\"glyphicon glyphicon-cloud-download\" style=\"font-size: 70px\"></span>\n\n        <form role=\"form\">\n            <div class=\"form-group\">\n                <label for=\"name\">{{'PROCESS-DEFINITIONS.POPUP.UPLOAD-FROM-MODELER.NAME' | translate}}</label>\n                <input type=\"text\" class=\"form-control\" id=\"name\" ng-model=\"model.username\" ui-keypress=\"{13:'next()'}\" auto-focus>\n            </div>\n            <div class=\"form-group\">\n                <label for=\"password\">{{'PROCESS-DEFINITIONS.POPUP.UPLOAD-FROM-MODELER.PASSWORD' | translate}}</label>\n                <input type=\"password\" class=\"form-control\" id=\"password\" ng-model=\"model.password\" ui-keypress=\"{13:'next()'}\">\n            </div>\n        </form>\n\n    </div>\n\n    <div class=\"process-model-wrapper\" ng-show=\"model.showingProcesses\">\n        <div class=\"process-model\"\n             ng-repeat=\"process in model.processes.data track by $index\"\n             ng-click=\"model.selectedProcess = process\">\n            <div class=\"process-model-box\" style=\"background-image: url('{{getProcessDiagramUrl(process.id)}}')\">\n                <div class=\"actions\">\n                    <span class=\"badge\">{{process.version}}</span>\n                </div>\n                <div class=\"details\" ng-class=\"{'selected-process': process.id == model.selectedProcess.id}\">\n                    <h3 class=\"truncate\" title=\"{{process.name}}\">\n                        {{process.name}}\n                    </h3>\n                    <div class=\"basic-details truncate\">\n                        <span><i class=\"glyphicon glyphicon-user\"></i> {{process.createdBy}}</span> <span title=\"{{process.lastUpdated | dateformat:'LLLL'}}\"><i class=\"glyphicon glyphicon-pencil\"></i> {{process.lastUpdated | dateformat}}</span>\n                    </div>\n                    <p>{{process.description}}</p>\n                </div>\n            </div>\n        </div>\n    </div>\n\n    <div class=\"upload-from-modeler-form\" ng-show=\"model.showingProcessName\">\n        <p style=\"margin-left:15%; margin-right: 15%\">\n            <i class=\"glyphicon glyphicon-info-sign\"></i>\n            {{'PROCESS-DEFINITIONS.POPUP.UPLOAD-FROM-MODELER.UPLOAD-DESCRIPTION' | translate}}\n        </p>\n        <form role=\"form\">\n            <div class=\"form-group\">\n                <input type=\"text\" class=\"form-control\" id=\"processName\" ng-model=\"model.processName\" ui-keypress=\"{13:'next()'}\" auto-focus>\n            </div>\n        </form>\n    </div>\n\n</div>\n\n<div class=\"modal-footer-wrapper\">\n    <div class=\"modal-footer\">\n        <div class=\"pull-right\">\n            <button type=\"button\" class=\"btn btn-sm btn-default\" ng-click=\"cancel()\" ng-disabled=\"status.loading\"\n                    translate=\"GENERAL.ACTION.CANCEL\">\n            </button>\n            <button type=\"button\" class=\"btn btn-sm btn-default\"\n                    ng-click=\"next()\"\n                    ng-disabled=\"status.loading || !showNextButton()\"\n                    translate=\"GENERAL.ACTION.NEXT\">\n            </button>\n        </div>\n        <loading-indicator></loading-indicator>\n        <div class=\"pull-right modeler-processes-error\" ng-if=\"model.unauthorizedError\">\n            <span>{{'PROCESS-DEFINITIONS.POPUP.UPLOAD-FROM-MODELER.UNAUTHORIZED' | translate}}</span>\n        </div>\n        <div class=\"pull-right modeler-processes-error\" ng-if=\"model.error\">\n            <span>{{'PROCESS-DEFINITIONS.POPUP.UPLOAD-FROM-MODELER.ERROR' | translate}}</span>\n        </div>\n    </div>\n</div>"
  },
  {
    "path": "flowable-ui-web/admin/views/user-change-password-popup.html",
    "content": "<div class=\"modal-header-wrapper\">\n\t<div class=\"modal-header\">\n\t\t<div class=\"pull-right\">\n            <a class=\"action\" ng-click=\"cancel()\">&times; {{'GENERAL.ACTION.CANCEL-AND-CLOSE' | translate}}</a>\n        </div>\n\t\t<h2>{{'USER.POPUP.CHANGE-PASSWORD.TITLE' | translate:user}}</h2>\t\n\t</div>\n</div>\n<div class=\"modal-body\">\n    <div class=\"alert error\" ng-show=\"model.errorMessage\">\n\t\t<i class=\"glyphicon glyphicon-remove\"></i>\n\t\t{{model.errorMessage}}\n\t</div>\n\t<table class=\"edit-table\">\n\t\t<tr>\n\t\t\t<td class=\"edit-label\" translate=\"USER.POPUP.CHANGE-PASSWORD.OLD-PASSWORD\"></td>\n\t\t\t<td>\n\t\t\t\t<div class=\"input-group input-group-sm\">\n\t\t\t\t\t<input type=\"password\" class=\"form-control\" value=\"\" ng-model=\"model.oldPassword\">\n\t\t\t\t</div>\n\t\t\t</td>\n\t\t</tr>\n\t\t<tr>\n\t\t\t<td class=\"edit-label\"translate=\"USER.POPUP.CHANGE-PASSWORD.NEW-PASSWORD\"></td>\n\t\t\t<td>\n\t\t\t\t<div class=\"input-group input-group-sm\">\n\t\t\t\t\t<input type=\"password\" class=\"form-control\" value=\"\" ng-model=\"model.newPassword\">\n\t\t\t\t</div>\n\t\t\t</td>\n\t\t</tr>\n\t</table>\n</div>\n\n<div class=\"modal-footer-wrapper\">\n\t<div class=\"modal-footer\">\n\t\t<div class=\"pull-right\">\n\t       <button type=\"button\" class=\"btn btn-sm btn-default\" ng-click=\"cancel()\" ng-disabled=\"status.loading\"\n\t       \t\ttranslate=\"GENERAL.ACTION.CANCEL\">\n\t       \t</button>\n\t       <button type=\"button\" class=\"btn btn-sm btn-default\" ng-click=\"ok()\" ng-disabled=\"status.loading || !model.newPassword || !model.oldPassword\"\n\t           translate=\"USER.POPUP.CHANGE-PASSWORD.CONFIRM\">\n\t       </button>\n\t\t</div>\n        <loading-indicator></loading-indicator>\n</div>\n</div>"
  },
  {
    "path": "flowable-ui-web/admin/views/user-delete-popup.html",
    "content": "<div class=\"modal-header-wrapper\">\n\t<div class=\"modal-header\">\n\t\t<div class=\"pull-right\">\n            <a class=\"action\" ng-click=\"cancel()\">&times; {{'GENERAL.ACTION.CANCEL-AND-CLOSE' | translate}}</a>\n        </div>\n\t\t<h2>{{'USER.POPUP.DELETE.TITLE' | translate:user}}</h2>\n\t</div>\n</div>\n<div class=\"modal-body\">\n\t<p>{{'USER.POPUP.DELETE.MESSAGE' | translate:user}}</p>\n</div>\n\n<div class=\"modal-footer-wrapper\">\n\t<div class=\"modal-footer\">\n\t\t<div class=\"pull-right\">\n\t       <button type=\"button\" class=\"btn btn-sm btn-default\" ng-click=\"cancel()\" ng-disabled=\"status.loading\"\n\t       \t\ttranslate=\"GENERAL.ACTION.CANCEL\">\n\t       \t</button>\n\t       <button type=\"button\" class=\"btn btn-sm btn-danger\" ng-click=\"ok()\" ng-disabled=\"status.loading\"\n\t           translate=\"USER.POPUP.DELETE.CONFIRM\">\n\t       </button>\n\t\t</div>\n        <loading-indicator></loading-indicator>\n</div>\n</div>\n"
  },
  {
    "path": "flowable-ui-web/admin/views/user-edit-popup.html",
    "content": "<div class=\"modal-header-wrapper\">\n\t<div class=\"modal-header\">\n\t\t<div class=\"pull-right\">\n            <a class=\"action\" ng-click=\"cancel()\">&times; {{'GENERAL.ACTION.CANCEL-AND-CLOSE' | translate}}</a>\n        </div>\n\t\t<h2>{{'USER.POPUP.EDIT.TITLE' | translate:user}}</h2>\t\n\t</div>\n</div>\n<div class=\"modal-body\">\n\t<div class=\"alert error\" ng-show=\"model.errorMessage\">\n\t\t<i class=\"glyphicon glyphicon-remove\"></i>\n\t\t{{model.errorMessage}}\n\t</div>\n\t<table class=\"edit-table\">\n\t\t<tr>\n\t\t\t<td class=\"edit-label\" translate=\"USER.POPUP.EDIT.FIRSTNAME\"></td>\n\t\t\t<td>\n\t\t\t\t<div class=\"input-group input-group-sm\">\n\t\t\t\t\t<input type=\"text\" class=\"form-control\" value=\"\" ng-model=\"model.firstName\"></textarea>\n\t\t\t\t</div>\n\t\t\t</td>\n\t\t</tr>\n\t\t<tr>\n\t\t\t<td class=\"edit-label\" translate=\"USER.POPUP.EDIT.LASTNAME\"></td>\n\t\t\t<td>\n\t\t\t\t<div class=\"input-group input-group-sm\">\n\t\t\t\t\t<input type=\"text\" class=\"form-control\" value=\"\" ng-model=\"model.lastName\"></textarea>\n\t\t\t\t</div>\n\t\t\t</td>\n\t\t</tr>\n\t\t<tr>\n\t\t\t<td class=\"edit-label\" translate=\"USER.POPUP.EDIT.EMAIL\"></td>\n\t\t\t<td>\n\t\t\t\t<div class=\"input-group input-group-sm\">\n\t\t\t\t\t<input type=\"text\" class=\"form-control\" value=\"\" ng-model=\"model.email\"></textarea>\n\t\t\t\t</div>\n\t\t\t</td>\n\t\t</tr>\n\t</table>\n</div>\n\n<div class=\"modal-footer-wrapper\">\n\t<div class=\"modal-footer\">\n\t\t<div class=\"pull-right\">\n\t       <button type=\"button\" class=\"btn btn-sm btn-default\" ng-click=\"cancel()\" ng-disabled=\"status.loading\"\n\t       \t\ttranslate=\"GENERAL.ACTION.CANCEL\">\n\t       \t</button>\n\t       <button type=\"button\" class=\"btn btn-sm btn-default\" ng-click=\"ok()\" ng-disabled=\"status.loading\" \n\t           translate=\"USER.POPUP.EDIT.CONFIRM\">\n\t       </button>\n\t\t</div>\n        <loading-indicator></loading-indicator>\n</div>\n</div>"
  },
  {
    "path": "flowable-ui-web/admin/views/user-new-popup.html",
    "content": "<div class=\"modal-header-wrapper\">\n\t<div class=\"modal-header\">\n\t\t<div class=\"pull-right\">\n            <a class=\"action\" ng-click=\"cancel()\">&times; {{'GENERAL.ACTION.CANCEL-AND-CLOSE' | translate}}</a>\n        </div>\n\t\t<h2 translate=\"USER.POPUP.NEW.TITLE\"></h2>\t\n\t</div>\n</div>\n<div class=\"modal-body\">\n\t<div class=\"alert error\" ng-show=\"model.errorMessage\">\n\t\t<i class=\"glyphicon glyphicon-remove\"></i>\n\t\t{{model.errorMessage}}\n\t</div>\n\t<table class=\"edit-table\">\n\t\t<tr>\n\t\t\t<td class=\"edit-label\" translate=\"USER.POPUP.NEW.LOGIN\"></td>\n\t\t\t<td>\n\t\t\t\t<div class=\"input-group input-group-sm\">\n\t\t\t\t\t<input type=\"text\" class=\"form-control\" value=\"\" ng-model=\"model.login\">\n\t\t\t\t</div>\n\t\t\t</td>\n\t\t</tr>\n\t\t<tr>\n\t\t\t<td class=\"edit-label\" translate=\"USER.POPUP.NEW.PASSWORD\"></td>\n\t\t\t<td>\n\t\t\t\t<div class=\"input-group input-group-sm\">\n\t\t\t\t\t<input type=\"password\" class=\"form-control\" value=\"\" ng-model=\"model.password\">\n\t\t\t\t</div>\n\t\t\t</td>\n\t\t</tr>\n\t\t<tr>\n\t\t\t<td class=\"edit-label\" translate=\"USER.POPUP.NEW.FIRSTNAME\"></td>\n\t\t\t<td>\n\t\t\t\t<div class=\"input-group input-group-sm\">\n\t\t\t\t\t<input type=\"text\" class=\"form-control\" value=\"\" ng-model=\"model.firstName\"></textarea>\n\t\t\t\t</div>\n\t\t\t</td>\n\t\t</tr>\n\t\t<tr>\n\t\t\t<td class=\"edit-label\" translate=\"USER.POPUP.NEW.LASTNAME\"></td>\n\t\t\t<td>\n\t\t\t\t<div class=\"input-group input-group-sm\">\n\t\t\t\t\t<input type=\"text\" class=\"form-control\" value=\"\" ng-model=\"model.lastName\"></textarea>\n\t\t\t\t</div>\n\t\t\t</td>\n\t\t</tr>\n\t\t<tr>\n\t\t\t<td class=\"edit-label\" translate=\"USER.POPUP.NEW.EMAIL\"></td>\n\t\t\t<td>\n\t\t\t\t<div class=\"input-group input-group-sm\">\n\t\t\t\t\t<input type=\"text\" class=\"form-control\" value=\"\" ng-model=\"model.email\"></textarea>\n\t\t\t\t</div>\n\t\t\t</td>\n\t\t</tr>\n\t\t<tr ng-if=\"account.multiTenant\">\n\t\t\t<td class=\"edit-label\" translate=\"USER.POPUP.NEW.ADMIN\"></td>\n\t\t\t<td>\n\t\t\t\t<div class=\"input-group input-group-sm\">\n\t\t\t\t\t<input type=\"checkbox\" style=\"box-shadow:none;\" class=\"form-control\" value=\"\" ng-model=\"model.adminUser\"></textarea>\n\t\t\t\t</div>\n\t\t\t</td>\n\t\t</tr>\n\t</table>\n</div>\n\n<div class=\"modal-footer-wrapper\">\n\t<div class=\"modal-footer\">\n\t\t<div class=\"pull-right\">\n\t       <button type=\"button\" class=\"btn btn-sm btn-default\" ng-click=\"cancel()\" ng-disabled=\"status.loading\"\n\t       \t\ttranslate=\"GENERAL.ACTION.CANCEL\">\n\t       \t</button>\n\t       <button type=\"button\" class=\"btn btn-sm btn-default\" ng-click=\"ok()\" ng-disabled=\"status.loading || !model.login || !model.password\"\n\t       \t\t translate=\"USER.POPUP.NEW.CONFIRM\">>\n\t       </button>\n\t\t</div>\n        <loading-indicator></loading-indicator>\n</div>\n</div>"
  },
  {
    "path": "flowable-ui-web/admin/views/users.html",
    "content": "<div class=\"container\" id=\"list-container\">\n    <div class=\"row\">\n        <div class=\"col-md-9\">\n            <div class=\"component\">\n                <div class=\"title\">\n                   <h2 translate=\"USERS.TITLE\"></h2>\n                </div>\n                <div class=\"grid-wrapper\" id=\"users\">\n                    <div ng-grid=\"gridUsers\" class=\"gridStyle\" ng-if=\"gridUsers && usersData\"/>\n                </div>\n            </div>\n        </div>\n        <div class=\"col-md-3\">\n\t\t\t<div class=\"component tip-left\">\n\t\t\t\t<div class=\"title\">\n\t\t\t\t\t<h2 translate=\"GENERAL.TITLE.ACTIONS\"></h2>\n\t\t\t\t</div>\n\t\t\t\t<ul class=\"list-group\">\n\t\t\t\t\t  <li ng-if=\"selectedUsers[0]\">\n\t\t\t\t\t    <button type=\"button\" class=\"btn btn-sm btn-default\" ng-click=\"editUser()\">\n\t\t\t\t\t\t\t<i class=\"glyphicon glyphicon-pencil\"></i>{{'USERS.ACTION.EDIT' | translate}}\n\t\t\t\t\t    </button>\n\t\t\t\t\t  </li>\n\t\t\t\t\t  <li ng-if=\"account.adminUser\">\n\t\t\t\t\t    <button type=\"button\" class=\"btn btn-sm btn-default\" ng-click=\"newUser()\">\n\t\t\t\t\t\t\t<i class=\"glyphicon glyphicon-user\"></i>{{'USERS.ACTION.NEW' | translate}}\n\t\t\t\t\t    </button>\n\t\t\t\t\t  </li>\n\t\t\t\t\t  <li ng-if=\"selectedUsers[0]\">\n\t\t\t\t\t    <button type=\"button\" class=\"btn btn-sm btn-default\" ng-click=\"changePassword()\">\n\t\t\t\t\t\t\t<i class=\"glyphicon glyphicon-pencil\"></i>{{'USERS.ACTION.CHANGE-PASSWORD' | translate}}\n\t\t\t\t\t    </button>\n\t\t\t\t\t  </li>\n\t\t\t\t\t  <li ng-if=\"account.adminUser && selectedUsers[0] && !selectedUsers[0].clusterUser && selectedUsers[0].login !== account.login\">\n\t\t\t\t\t    <button type=\"button\" class=\"btn btn-sm btn-default btn-danger\"  ng-click=\"deleteUser()\">\n\t\t\t\t\t\t\t<i class=\"glyphicon glyphicon-remove\"></i>{{'USERS.ACTION.DELETE' | translate}}\n\t\t\t\t\t    </button>\n\t\t\t\t\t  </li>\n\t\t\t    </ul>\n\t\t\t</div>\n\t\t</div>\n    </div>\n</div>\n"
  },
  {
    "path": "flowable-ui-web/admin/views/variable-add-popup.html",
    "content": "<div class=\"modal-header-wrapper\">\n\t<div class=\"modal-header\">\n\t\t<div class=\"pull-right\">\n            <a class=\"action\" ng-click=\"cancel()\">&times; {{'GENERAL.ACTION.CANCEL-AND-CLOSE' | translate}}</a>\n        </div>\n\t\t<h2>{{'PROCESS-INSTANCE.POPUP.CREATE-VARIABLE.TITLE' | translate}}</h2>\n\t</div>\n</div>\n<div class=\"modal-body\">\n\n    <div style=\"margin-top:20px\">\n        <div>{{'PROCESS-INSTANCE.POPUP.CREATE-VARIABLE.NAME' | translate}}</div>\n        <input type=\"text\" class=\"form-control\" ng-model=\"newVariable.name\">\n    </div>\n\n    <div style=\"margin-top:20px\">\n        <div>{{'PROCESS-INSTANCE.POPUP.CREATE-VARIABLE.TYPE' | translate}}</div>\n        <div>\n            <select ng-model=\"newVariable.type\" ng-options=\"type as type for type in types\">\n            </select>\n        </div>\n    </div>\n\n    <div ng-show=\"newVariable.type != null && newVariable.type != undefined\" style=\"margin-top:20px\">\n        <div>{{'PROCESS-INSTANCE.POPUP.CREATE-VARIABLE.VALUE' | translate}}</div>\n        <div ng-switch on=\"newVariable.type\" style=\"margin-top:10px\">\n            <div ng-switch-when=\"string\">\n                <input class=\"form-control\" type=\"text\" ng-model=\"newVariable.value\">\n            </div>\n            <div ng-switch-when=\"boolean\">\n                <input type=\"checkbox\" ng-model=\"newVariable.value\">\n                <span ng-show=\"newVariable.value\">{{'PROCESS-INSTANCE.POPUP.UPDATE-VARIABLE.CHECKED' | translate}}</span>\n                <span ng-show=\"!newVariable.value\">{{'PROCESS-INSTANCE.POPUP.UPDATE-VARIABLE.UNCHECKED' | translate}}</span>\n            </div>\n            <div ng-switch-when=\"date\">\n                <input class=\"form-control\" type=\"text\" ng-model=\"newVariable.value\">\n                <div style=\"margin: 5px 0 0 5px; font-size:12px\">{{'PROCESS-INSTANCE.POPUP.UPDATE-VARIABLE.DATE-HELP' | translate}}</div>\n            </div>\n            <div ng-switch-when=\"double\">\n                <input class=\"form-control\" type=\"number\" ng-model=\"newVariable.value\">\n            </div>\n            <div ng-switch-when=\"integer\">\n                <input class=\"form-control\" type=\"number\" ng-model=\"newVariable.value\">\n            </div>\n            <div ng-switch-when=\"long\">\n                <input class=\"form-control\" type=\"number\" ng-model=\"newVariable.value\">\n            </div>\n            <div ng-switch-when=\"short\">\n                <input class=\"form-control\" type=\"number\" ng-model=\"newVariable.value\">\n            </div>\n            <div ng-switch-default>\n                <input class=\"form-control\" type=\"text\" ng-model=\"newVariable.value\">\n            </div>\n        </div>\n    </div>\n</div>\n\n<div class=\"modal-footer-wrapper\">\n\t<div class=\"modal-footer\">\n\t\t<div class=\"pull-right\">\n\t       <button type=\"button\" class=\"btn btn-sm btn-default\" ng-click=\"cancel()\" ng-disabled=\"status.loading\"\n\t       \ttranslate=\"GENERAL.ACTION.CANCEL\">\n\t       \t</button>\n\t       <button type=\"button\" class=\"btn btn-sm btn-info\" ng-click=\"createVariable()\"\n                   ng-disabled=\"status.loading || newVariable.name == null || newVariable.name == undefined || newVariable.type == null || newVariable.type == undefined \">\n               {{'PROCESS-INSTANCE.POPUP.CREATE-VARIABLE.CREATE' | translate}}\n\t       </button>\n\t\t</div>\n        <loading-indicator></loading-indicator>\n</div>\n</div>\n"
  },
  {
    "path": "flowable-ui-web/admin/views/variable-delete-popup.html",
    "content": "<div class=\"modal-header-wrapper\">\n\t<div class=\"modal-header\">\n\t\t<div class=\"pull-right\">\n            <a class=\"action\" ng-click=\"cancel()\">&times; {{'GENERAL.ACTION.CANCEL-AND-CLOSE' | translate}}</a>\n        </div>\n\t\t<h2>{{'PROCESS-INSTANCE.POPUP.DELETE-VARIABLE.TITLE' | translate:variable}}</h2>\n\t</div>\n</div>\n<div class=\"modal-body\">\n    <div style=\"margin-top:40px\">\n        {{'PROCESS-INSTANCE.POPUP.DELETE-VARIABLE.MESSAGE' | translate}}\n    </div>\n</div>\n\n<div class=\"modal-footer-wrapper\">\n\t<div class=\"modal-footer\">\n\t\t<div class=\"pull-right\">\n\t       <button type=\"button\" class=\"btn btn-sm btn-default\" ng-click=\"cancel()\" ng-disabled=\"status.loading\"\n\t       \ttranslate=\"GENERAL.ACTION.CANCEL\">\n\t       \t</button>\n\t       <button type=\"button\" class=\"btn btn-sm btn-danger\" ng-click=\"deleteVariable()\" ng-disabled=\"status.loading\">\n               {{'PROCESS-INSTANCE.POPUP.DELETE-VARIABLE.DELETE' | translate}}\n\t       </button>\n\t\t</div>\n        <loading-indicator></loading-indicator>\n</div>\n</div>\n"
  },
  {
    "path": "flowable-ui-web/idm/browserconfig.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<browserconfig>\n  <msapplication>\n    <tile>\n      <square150x150logo src=\"images/mstile-150x150.png?v=Om5N75Y123\"/>\n      <TileColor>#da532c</TileColor>\n    </tile>\n  </msapplication>\n</browserconfig>\n"
  },
  {
    "path": "flowable-ui-web/idm/error/404.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"utf-8\">\n    <title>Page Not Found :(</title>\n    <style>\n      ::-moz-selection {\n        background: #b3d4fc;\n        text-shadow: none;\n      }\n\n      ::selection {\n        background: #b3d4fc;\n        text-shadow: none;\n      }\n\n      html {\n        padding: 30px 10px;\n        font-size: 20px;\n        line-height: 1.4;\n        color: #737373;\n        background: #f0f0f0;\n        -webkit-text-size-adjust: 100%;\n        -ms-text-size-adjust: 100%;\n      }\n\n      html,\n      input {\n        font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n      }\n\n      body {\n        max-width: 500px;\n        _width: 500px;\n        padding: 30px 20px 50px;\n        border: 1px solid #b3b3b3;\n        border-radius: 4px;\n        margin: 0 auto;\n        box-shadow: 0 1px 10px #a7a7a7, inset 0 1px 0 #fff;\n        background: #fcfcfc;\n      }\n\n      h1 {\n        margin: 0 10px;\n        font-size: 50px;\n        text-align: center;\n      }\n\n      h1 span {\n        color: #bbb;\n      }\n\n      h3 {\n        margin: 1.5em 0 0.5em;\n      }\n\n      p {\n        margin: 1em 0;\n      }\n\n      ul {\n        padding: 0 0 0 40px;\n        margin: 1em 0;\n      }\n\n      .container {\n        max-width: 380px;\n        _width: 380px;\n        margin: 0 auto;\n      }\n\n      /* google search */\n\n      #goog-fixurl ul {\n        list-style: none;\n        padding: 0;\n        margin: 0;\n      }\n\n      #goog-fixurl form {\n        margin: 0;\n      }\n\n      #goog-wm-qt,\n      #goog-wm-sb {\n        border: 1px solid #bbb;\n        font-size: 16px;\n        line-height: normal;\n        vertical-align: top;\n        color: #444;\n        border-radius: 2px;\n      }\n\n      #goog-wm-qt {\n        width: 220px;\n        height: 20px;\n        padding: 5px;\n        margin: 5px 10px 0 0;\n        box-shadow: inset 0 1px 1px #ccc;\n      }\n\n      #goog-wm-sb {\n        display: inline-block;\n        height: 32px;\n        padding: 0 10px;\n        margin: 5px 0 0;\n        white-space: nowrap;\n        cursor: pointer;\n        background-color: #f5f5f5;\n        background-image: -webkit-linear-gradient(rgba(255,255,255,0), #f1f1f1);\n        background-image: -moz-linear-gradient(rgba(255,255,255,0), #f1f1f1);\n        background-image: -ms-linear-gradient(rgba(255,255,255,0), #f1f1f1);\n        background-image: -o-linear-gradient(rgba(255,255,255,0), #f1f1f1);\n        -webkit-appearance: none;\n        -moz-appearance: none;\n        appearance: none;\n        *overflow: visible;\n        *display: inline;\n        *zoom: 1;\n      }\n\n      #goog-wm-sb:hover,\n      #goog-wm-sb:focus {\n        border-color: #aaa;\n        box-shadow: 0 1px 1px rgba(0, 0, 0, 0.1);\n        background-color: #f8f8f8;\n      }\n\n      #goog-wm-qt:hover,\n      #goog-wm-qt:focus {\n        border-color: #105cb6;\n        outline: 0;\n        color: #222;\n      }\n\n      input::-moz-focus-inner {\n        padding: 0;\n        border: 0;\n      }\n    </style>\n  </head>\n  <body>\n    <div class=\"container\">\n      <h1>Not found <span>:(</span></h1>\n      <p>Sorry, but the page you were trying to view does not exist.</p>\n      <p>It looks like this was the result of either:</p>\n      <ul>\n        <li>a mistyped address</li>\n        <li>an out-of-date link</li>\n      </ul>\n      <script>\n        var GOOG_FIXURL_LANG = (navigator.language || '').slice(0,2),GOOG_FIXURL_SITE = location.host;\n      </script>\n      <script src=\"//linkhelp.clients.google.com/tbproxy/lh/wm/fixurl.js\"></script>\n    </div>\n  </body>\n</html>\n"
  },
  {
    "path": "flowable-ui-web/idm/i18n/en.json",
    "content": "{\n   \"GENERAL\": {\n        \"MAIN-TITLE\": \"Flowable\",\n        \"ERROR\": {\n            \"GENERIC\": \"Sorry, an error occured...\",\n            \"UNKNOWN\": \"Sorry, an error occured while performing the requested operation.\",\n            \"BAD_REQUEST\": \"An error occured while performing the requested operation\",\n            \"NOT_FOUND\": \"The resource you are trying to access does not exist\",\n            \"UNAUTHORIZED\": \"You should sign in in order to perform the requested operation.\",\n            \"FORBIDDEN\": \"You are not allowed to perform the requested operation\",\n            \"INTERNAL_SERVER_ERROR\": \"Sorry, an unexpected error occured while performing the requested operation.\"\n        },\n        \"ACTION\": {\n            \"LOGOUT\": \"Sign out\",\n            \"HELP\": \"Getting started\",\n            \"EDIT-PROFILE\": \"Edit profile\",\n            \"SAVE\": \"Save\",\n            \"CANCEL\": \"Cancel\",\n            \"CLOSE\": \"Close\",\n            \"DEPLOY\": \"Deploy\",\n            \"ABOUT\": \"About Flowable\"\n        },\n        \"MESSAGE\": {\n            \"SELECT-PEOPLE-HELP\": \"Use &uparrow; and &downarrow; to select and press enter to confirm\",\n            \"SELECT-GROUP-HELP\": \"Use &uparrow; and &downarrow; to select and press Enter to confirm\",\n            \"SELECT-GROUP-SEARCH-PLACEHOLDER\": \"Search group\",\n            \"SELECT-GROUP-NO-MATCHING-RESULTS\": \"Use the search box above to find groups.\"\n        },\n        \"TITLE\": {\n            \"MATCHING-PEOPLE\": \"Matching people\",\n            \"SELECT-GROUP\": \"Select group\",\n            \"MATCHING-GROUPS\": \"Matching groups\"\n        }\n    },\n    \"LOGIN\": {\n        \"TITLE\": \"Sign in\",\n        \"USERNAME\": \"Username\",\n        \"USERNAME-PLACEHOLDER\": \"Enter your username\",\n        \"PASSWORD\": \"Password\",\n        \"PASSWORD-PLACEHOLDER\": \"Enter your password\",\n        \"INVALID-CREDENTIALS\": \"Invalid credentials\",\n        \"ACTION\": {\n            \"CONFIRM\": \"Sign in\"\n        }\n    },\n    \"ACCOUNT\": {\n        \"ACTIVATE\": {\n          \"TITLE\": \"Activate account\",\n          \"ACTIVATING-MESSAGE\": \"Hold on tight {{userFullName}} we're activating your account...\",\n          \"SUCCESS-MESSAGE\": \"Your account has been activated. Please sign in below to start designing and running processes\",\n          \"FAILURE-MESSAGE\": \"Your account cannot be activated. Either it has already been activated or the activation link has expired.\"\n        },\n\n        \"RESET-PASSWORD-REQUEST\": {\n          \"MESSAGE\": \"Forgot your password? Enter your email address below to receive an email to reset your password.\",\n          \"TITLE\": \"Reset password\",\n          \"EMAIL\": \"Email address\",\n          \"EMAIL-PLACEHOLDER\": \"Enter your email\",\n          \"SECURITY-SECTION\": \"Security check\",\n          \"CONFIRM\": \"Request password reset\",\n          \"SUCCESS-MESSAGE\": \"You will receive a mail shortly with a link to reset your password.\",\n          \"ERROR\": {\n              \"UNEXISTING-USER\": \"User with the given email address does not exist.\"\n          }\n        },\n\n        \"RESET-PASSWORD\": {\n          \"TITLE\": \"Reset password\",\n          \"PASSWORD\": \"Password\",\n          \"PASSWORD-CONFIRM\": \"Confirm password\",\n          \"PASSWORD-PLACEHOLDER\": \"Enter a new password\",\n          \"PASSWORD-CONFIRM-PLACEHOLDER\": \"Confirm the new password\",\n          \"CONFIRM\": \"Change password\",\n          \"LOADING\": \"Resetting password...\",\n          \"SUCCESS-MESSAGE\": \"Your password has been changed.\",\n          \"LOGIN\": \"Sign in now\",\n          \"FAILURE-MESSAGE\": \"Your password cannot be reset. The reset link is invalid or expired.\"\n        }\n    },\n    \"IDM\": {\n      \"GENERAL\" : {\n        \"MAIN-TITLE\": \"Flowable - Identity Management\",\n        \"NAVIGATION\": {\n            \"PROFILE\": \"Personal\",\n            \"USER-MGMT\": \"Users\",\n            \"GROUP-MGMT\": \"Groups\",\n            \"PRIVILEGE-MGMT\": \"Privileges\"\n        },\n        \"ACTION\": {\n          \"CANCEL\": \"Cancel\",\n          \"CREATE\": \"Create\",\n          \"SAVE\": \"Save\",\n          \"CLOSE\": \"Close\",\n          \"LOGOUT\": \"Sign out\",\n          \"ABOUT\": \"About Flowable\"\n        },\n        \"ERROR\": {\n            \"GENERIC\": \"Sorry, an error occured...\",\n            \"UNKNOWN\": \"Sorry, an error occured while performing the requested operation.\",\n            \"BAD_REQUEST\": \"An error occured while performing the requested operation\",\n            \"NOT_FOUND\": \"The resource you are trying to access does not exist\",\n            \"UNAUTHORIZED\": \"You should sign in in order to perform the requested operation.\",\n            \"FORBIDDEN\": \"You are not allowed to perform the requested operation\",\n            \"INTERNAL_SERVER_ERROR\": \"Sorry, an unexpected error occured while performing the requested operation.\"\n        }\n      },\n      \"USER-MGMT\": {\n        \"TITLE\": \"Matching users\",\n         \"CREATE-USER\": \"Create user\",\n         \"NAME-SEARCH\": \"Search by name\",\n         \"COMPANY\": \"Company\",\n         \"STATUS\": \"Status\",\n         \"ACCOUNT\": \"Account type\",\n         \"ACTIONS\": \"Select an action\",\n         \"CHANGE-STATUS\": \"Change status\",\n         \"CHANGE-ACCOUNT-TYPE\": \"Change account type\",\n         \"CHANGE-PASSWORD\": \"Change password\",\n         \"EDIT-USER\": \"Change details\",\n         \"DELETE-USERS\": \"Delete\",\n         \"TOTAL-USERS\": \"total\",\n         \"INACTIVE-USERS\": \"inactive\",\n         \"ENTERPRISE-USERS\": \"enterprise\",\n         \"ACTIVE-USERS\": \"active\",\n         \"DELETED-USERS\": \"deleted\",\n         \"ORDER-BY\": \"Order by\",\n         \"SHOW-NEXT\": \"Show next\",\n         \"SHOW-PREVIOUS\": \"Show previous\",\n         \"NO-MATCHING-USERS\": \"Found no matching users\",\n         \"MATCHING-USERS\": \"Found {{total | number}} matching user(s), showing {{start + 1}} to {{start + size}}\",\n         \"ID\": \"ID\",\n         \"EMAIL\": \"Email\",\n         \"NAME\": \"Name\",\n         \"CREATED\": \"Created\",\n         \"TYPE\": \"Type\",\n         \"EXTERNAL-ID\": \"External id\",\n         \"LAST-SYNC-TIME\": \"Last update\",\n         \"FILTERS\": {\n             \"STATUS-ANY\": \"Any status\",\n             \"STATUS-ACTIVE\": \"Active\",\n             \"STATUS-INACTIVE\": \"Inactive\",\n             \"STATUS-PENDING\": \"Pending\",\n             \"STATUS-DELETED\": \"Deleted\",\n             \"TYPE-ANY\": \"Any type\",\n             \"SORT-DATE-NEWEST\": \"Date created, newest\",\n             \"SORT-DATE-OLDEST\": \"Date created, oldest\",\n             \"SORT-EMAIL-A\": \"Email, A-Z\",\n             \"SORT-EMAIL-Z\": \"Email, Z-A\",\n             \"SORT-ID-A\": \"User id, A-Z\",\n             \"SORT-ID-Z\": \"User id, Z-A\"\n         },\n         \"POPUP\": {\n             \"CREATE-TITLE\": \"Create user\",\n             \"EDIT-TITLE\": \"Edit user details\",\n             \"CREATE-ID\": \"User id\",\n             \"CREATE-EMAIL\": \"Email\",\n             \"CREATE-INVALID-EMAIL\": \"Invalid\",\n             \"CREATE-PASSWORD\": \"Password\",\n             \"CREATE-FIRSTNAME\": \"First name\",\n             \"CREATE-LASTNAME\": \"Last name\",\n             \"CREATE-TENANT\": \"Tenant\",\n             \"CREATE-COMPANY\": \"Company\",\n             \"CREATE-STATUS\": \"Status\",\n             \"CREATE-TYPE\": \"Type\",\n             \"BULK-UPDATE-TITLE\": \"Bulk update users\",\n             \"BULK-UPDATE-NEW-STATUS\": \"New status:\",\n             \"BULK-UPDATE-NEW-TYPE\": \"New account type:\",\n             \"BULK-UPDATE-EMAIL-NOTIFICATIONS\": \"Send email notifications for status change\",\n             \"BULK-UPDATE-STATUS-USERS\": \"You are about to update the status for these {{length}} user(s):\",\n             \"BULK-UPDATE-TYPE-USERS\": \"You are about to update the account type for these {{length}} user(s):\",\n             \"BULK-UPDATE-CANCEL\": \"Cancel and close\",\n             \"BULK-UPDATE-CONFIRM\": \"Update users\",\n             \"BULK-UPDATE-PASSWORD-TITLE\": \"Change password\",\n             \"BULK-UPDATE-PASSWORD\": \"Password\",\n             \"BULK-UPDATE-PASSWORD-REPEAT\": \"Repeat password\",\n             \"BULK-UPDATE-PASSWORD-CONFIRM\": \"Change\"\n         }\n      },\n      \"FUNCTIONAL-GROUP-MGMT\": {\n        \"CREATE\": \"Create group\",\n        \"NO-GROUPS\": \"No groups found\",\n        \"NO-SELECTION\": \"Select a group from the list on the left\",\n        \"SYNC-DETAILS\": \"Synchronization details\",\n        \"EXTERNAL-ID\": \"External id:\",\n        \"LAST-SYNC-TIME\": \"Last update:\",\n        \"MEMBERS\": \"Group members\",\n        \"SUBGROUPS\": \"Subgroups\",\n        \"NO-MEMBERS\": \"No users found\",\n        \"ADD-USER\": \"+ add user\",\n        \"ADD-SUBGROUP\": \"+ add subgroup\",\n        \"NO-SUBGROUPS\": \"No subgroups found\",\n        \"USER-ADDED\": \"Users have been added to group\",\n        \"INACTIVE\": \"deactivated\",\n        \"INACTIVE-DESCRIPTION\": \"This group has been deactivated. Users will still be able complete currently assigned tasks to this group, but new process definitions cannot use this group anymore.\",\n        \"ADD-POPOVER-TITLE\": \"Select user\",\n            \"POPUP\": {\n                \"CREATE-TITLE\": \"Create group\",\n                \"CREATE-ID\": \"Group id\",\n                \"CREATE-NAME\": \"Name\",\n                \"DELETE-TITLE\": \"Delete group\",\n                \"DELETE-DESCRIPTION\": \"Are you sure you want to delete this group?\",\n                \"DELETE-CONFIRM\": \"Confirm\",\n                \"DEACTIVATE-TITLE\": \"Deactivate group\",\n                \"DEACTIVATE-DESCRIPTION\": \"Are you sure you want to delete this group? This will delete all sub groups too. Note that a group will first be deactivated, such that tasks of processes can be properly finished. Clicking the removal button a second time will delete the group completely.\",\n                \"DELETE-MEMBER-TITLE\": \"Delete group member\",\n                \"DELETE-MEMBER-DESCRIPTION\": \"Are you sure you want to delete this user from the group?\",\n                \"ADD-MEMBER-TITLE\": \"Add user\",\n                \"ADD-MEMBER-NO-USERS\": \"No users found\",\n                \"ADD-MEMBER-CONFIRM\": \"Add ({{selectedUsers.length}})\",\n                \"ACTIVATE-TITLE\": \"Activate group\",\n                \"ACTIVATE-DESCRIPTION\": \"Activate this group again? This means that this group would again be eligble for task assignment. Note that subgroups of a group are not activated by default.\",\n                \"ACTIVATE-CONFIRM\": \"Activate\",\n                \"EDIT-TITLE\": \"Edit group\"\n            }\n        },\n      \"PRIVILEGE-MGMT\": {\n          \"access-idm\": \"Access identity management application\",\n          \"access-admin\": \"Access admin application\",\n          \"access-modeler\": \"Access modeler application\",\n\t\t  \"access-task\": \"Access the workflow application\",\n\t\t  \"access-rest-api\": \"Access the REST API\",\n          \"NO-SELECTION\": \"No privilege selected\",\n          \"USERS\": \"Users\",\n          \"GROUPS\": \"Groups\",\n          \"NO-USERS\": \"No users added yet. Click here to add a user.\",\n          \"NO-GROUPS\": \"No groups added yet.  Click here to add a group\",\n          \"ADD-USER\": \"Add a user\",\n          \"ADD-GROUP\": \"Add a group\",\n          \"POPOVER-SELECT-USER-TITLE\": \"Select user\",\n          \"POPOVER-SELECT-GROUP-TITLE\": \"Select group\",\n          \"GROUP-ID\": \"Group id\",\n          \"GROUP-NAME\": \"Group name\"\n      },\n      \"PROFILE-MGMT\": {\n         \"CREATED\": \"Registered since\",\n         \"CHANGE-PASSWORD\": \"Change password\",\n         \"DETAILS\": \"Details\",\n         \"DETAILS-DESCRIPTION\": \"Click on any of the fields below to change them\",\n         \"FIRST-NAME\": \"First name\",\n         \"NOTHING-SET\": \"Nothing set\",\n         \"LAST-NAME\": \"Last name\",\n         \"EMAIL\": \"Email\",\n         \"COMPANY\": \"Company\",\n         \"GROUPS\": \"Your groups\",\n         \"POPUP\": {\n            \"UPLOAD-PICTURE-TITLE\": \"Change picture\",\n            \"UPLOAD-PICTURE-DESCRIPTION\": \"Please select an image from your computer or drop it in the zone below.\",\n            \"UPLOAD-PICTURE-CANCEL-UPLOAD\": \"Cancel upload\",\n            \"UPLOAD-PICTURE-DROPZONE\": \"Drop logo image file here\",\n            \"UPLOAD-PICTURE-NO-DROP\": \"Drop is not supported by your browser\",\n            \"UPLOAD-PICTURE-ERROR\": \"Error\",\n            \"CHANGE-PASSWORD-TITLE\": \"Change password\",\n            \"CHANGE-PASSWORD-ORIGINAL\": \"Original password\",\n            \"CHANGE-PASSWORD-NEW-PASSWORD\": \"New password\",\n            \"CHANGE-PASSWORD-NEW-PASSWORD2\": \"Repeat new password\",\n            \"CHANGE-PASSWORD-CONFIRM\": \"Confirm\",\n            \"CHANGE-PASSWORD-NOT-MATCHING\": \"Passwords don't match\",\n            \"CHANGE-PASSWORD-INVALID\": \"Invalid password\"\n         }\n      },\n      \"USERS\": {\n        \"TITLE\": \"User administration\",\n        \"ACTION\": {\n          \"CREATE\": \"Create user\"\n        }\n      }\n    },\n    \"INVOLVE-PEOPLE\": {\n        \"ACTION-SELECT\": \"Select\",\n        \"SEARCH-PLACEHOLDER\": \"Search by name\",\n        \"NO-MATCHING-RESULTS\": \"Use the search box above to find users\"\n    }\n}\n"
  },
  {
    "path": "flowable-ui-web/idm/i18n/es.json",
    "content": "{\n   \"GENERAL\": {\n        \"MAIN-TITLE\": \"Flowable\",\n        \"ERROR\": {\n            \"GENERIC\": \"Lo sentimos un error ha ocurrido...\",\n            \"UNKNOWN\": \"Lo sentimos un error ha ocurrido mientras se realizaba la operacion solicitada.\",\n            \"BAD_REQUEST\": \"Un error ha ocurrido mientras se realizaba la operacion solicitada\",\n            \"NOT_FOUND\": \"El recurso al que intentas acceder no existe\",\n            \"UNAUTHORIZED\": \"Debes iniciar sesion para poder realizar la operacion seleccionada.\",\n            \"FORBIDDEN\": \"La operacion que deseas realizar no esta permitida\",\n            \"INTERNAL_SERVER_ERROR\": \"Lo sentimos, ocurrio un error inesperado mientras se realizaba la accion seleccionada.\"\n        },\n        \"ACTION\": {\n            \"LOGOUT\": \"Salir\",\n            \"HELP\": \"Empezando\",\n            \"EDIT-PROFILE\": \"Editar perfil\",\n            \"SAVE\": \"Guardar\",\n            \"CANCEL\": \"Cancelar\",\n            \"CLOSE\": \"Cerrar\",\n            \"DEPLOY\": \"Desplegar\",\n            \"ABOUT\": \"Acerca de Flowable\"\n        },\n        \"MESSAGE\": {\n            \"SELECT-PEOPLE-HELP\": \"Usa &flecha arriba ; and &flecha abajo; para seleccionar y presiona Enter para confirmar\",\n            \"SELECT-GROUP-HELP\": \"Usa &flecha arriba ; and &flecha abajo; para seleccionar y presiona Enter para confirmar\",\n            \"SELECT-GROUP-SEARCH-PLACEHOLDER\": \"Buscar Grupo\",\n            \"SELECT-GROUP-NO-MATCHING-RESULTS\": \"Usa el campo buscar de arriba para encontrar Grupos\"\n        },\n        \"TITLE\": {\n            \"MATCHING-PEOPLE\": \"Personas parecidas\",\n            \"SELECT-GROUP\": \"Seleccionar Grupo\",\n            \"MATCHING-GROUPS\": \"Grupos parecidos\"\n        }\n    },\n    \"LOGIN\": {\n        \"TITLE\": \"Iniciar sesion\",\n        \"USERNAME\": \"Usuario\",\n        \"USERNAME-PLACEHOLDER\": \"Introduce tu usuario\",\n        \"PASSWORD\": \"Password\",\n        \"PASSWORD-PLACEHOLDER\": \"Introduce tu password\",\n        \"INVALID-CREDENTIALS\": \"Datos invalidos\",\n        \"ACTION\": {\n            \"CONFIRM\": \"Iniciar sesion\"\n        }\n    },\n    \"ACCOUNT\": {\n        \"ACTIVATE\": {\n          \"TITLE\": \"Activar cuenta\",\n          \"ACTIVATING-MESSAGE\": \"Por favor espera {{userFullName}} estamos activando tu cuenta...\",\n          \"SUCCESS-MESSAGE\": \"Tu cuenta ha sido activada. Por favor inicia sesion para comenzar a diseñar y correr procesos\",\n          \"FAILURE-MESSAGE\": \"Tu cuenta no puede ser activada, esto puede ser por que ya se ha activado o el link de activacion ha expirado\"\n        },\n\n        \"RESET-PASSWORD-REQUEST\": {\n          \"MESSAGE\": \"Olvidaste tu password? Proporciona tu Email para resetear tu password.\",\n          \"TITLE\": \"Resetear password\",\n          \"EMAIL\": \"Direccion de email\",\n          \"EMAIL-PLACEHOLDER\": \"Introduce tu email\",\n          \"SECURITY-SECTION\": \"Validacion de seguridad\",\n          \"CONFIRM\": \"Pedir reset de password\",\n          \"SUCCESS-MESSAGE\": \"Recibiras un email para resetear tu password.\",\n          \"ERROR\": {\n              \"UNEXISTING-USER\": \"No existe un usuario con el email proporcionado.\"\n          }\n        },\n\n        \"RESET-PASSWORD\": {\n          \"TITLE\": \"Reset password\",\n          \"PASSWORD\": \"Password\",\n          \"PASSWORD-CONFIRM\": \"Confirmar password\",\n          \"PASSWORD-PLACEHOLDER\": \"Introduce un nuevo password\",\n          \"PASSWORD-CONFIRM-PLACEHOLDER\": \"Confirmar nuevo password\",\n          \"CONFIRM\": \"Cambiar password\",\n          \"LOADING\": \"Reseteando password...\",\n          \"SUCCESS-MESSAGE\": \"Tu password ha cambiado.\",\n          \"LOGIN\": \"Iniciar sesion ahora\",\n          \"FAILURE-MESSAGE\": \"Tu password no puede ser reseteado. El link para resetearlo es invalido o ha expirado\"\n        }\n    },\n    \"IDM\": {\n      \"GENERAL\" : {\n        \"MAIN-TITLE\": \"Flowable - Identity Management\",\n        \"NAVIGATION\": {\n            \"PROFILE\": \"Personal\",\n            \"USER-MGMT\": \"Usuarios\",\n            \"GROUP-MGMT\": \"Grupos\",\n            \"PRIVILEGE-MGMT\": \"Privilegios\"\n        },\n        \"ACTION\": {\n          \"CANCEL\": \"Cancelar\",\n          \"CREATE\": \"Crear\",\n          \"SAVE\": \"Guardar\",\n          \"CLOSE\": \"Cerrar\",\n          \"LOGOUT\": \"Salir\",\n          \"ABOUT\": \"Acerca de Flowable\"\n        },\n        \"ERROR\": {\n            \"GENERIC\": \"Lo sentimos ocurrio un error...\",\n            \"UNKNOWN\": \"Lo sentimos ocurrio un error mientras solucionabamos la operacion selecionada.\",\n            \"BAD_REQUEST\": \"Ocurrio un error mientras solucionabamos la operacion selecionada\",\n            \"NOT_FOUND\": \"El recurso al que intentas accesar no existe\",\n            \"UNAUTHORIZED\": \"Debes iniciar sesion para poder realizar la accion seleccionada\",\n            \"FORBIDDEN\": \"No puedes realizar la accion seleccionada\",\n            \"INTERNAL_SERVER_ERROR\": \"Lo sentimos ocurrio un error mientras solucionabamos la operacion selecionada.\"\n        }\n      },\n      \"USER-MGMT\": {\n        \"TITLE\": \"Usuarios parecidos\",\n         \"CREATE-USER\": \"Crear usuario\",\n         \"NAME-SEARCH\": \"Buscar por nombre\",\n         \"COMPANY\": \"Compania\",\n         \"STATUS\": \"Estatus\",\n         \"ACCOUNT\": \"Tipo de cuenta\",\n         \"ACTIONS\": \"Seleciona una accion\",\n         \"CHANGE-STATUS\": \"Cambiar estatus\",\n         \"CHANGE-ACCOUNT-TYPE\": \"Cambiar tipo de cuenta\",\n         \"CHANGE-PASSWORD\": \"Cambiar password\",\n         \"EDIT-USER\": \"Cambiar detalles\",\n         \"DELETE-USERS\": \"Borrar\",\n         \"TOTAL-USERS\": \"total\",\n         \"INACTIVE-USERS\": \"inactivo\",\n         \"ENTERPRISE-USERS\": \"empresa\",\n         \"ACTIVE-USERS\": \"activo\",\n         \"DELETED-USERS\": \"eliminado\",\n         \"ORDER-BY\": \"Ordenar por\",\n         \"SHOW-NEXT\": \"Mostrar siguiente\",\n         \"SHOW-PREVIOUS\": \"Mostrar anterior\",\n         \"NO-MATCHING-USERS\": \"No se encontraron usuarios parecidos\",\n         \"MATCHING-USERS\": \"Se encontraron {{total | number}} usuarios parecidos, mostrando de {{start + 1}} a {{start + size}}\",\n         \"ID\": \"Identificador\",\n         \"EMAIL\": \"Email\",\n         \"NAME\": \"Nombre\",\n         \"CREATED\": \"Creado\",\n         \"TYPE\": \"Tipo\",\n         \"EXTERNAL-ID\": \"Identificador externo\",\n         \"LAST-SYNC-TIME\": \"Ultima actualizacion\",\n         \"FILTERS\": {\n             \"STATUS-ANY\": \"Cualquier estatus\",\n             \"STATUS-ACTIVE\": \"Activo\",\n             \"STATUS-INACTIVE\": \"Inactivo\",\n             \"STATUS-PENDING\": \"Pendiente\",\n             \"STATUS-DELETED\": \"Eliminado\",\n             \"TYPE-ANY\": \"Cualquier tipo\",\n             \"SORT-DATE-NEWEST\": \"Fecha de creacion, mas nueva\",\n             \"SORT-DATE-OLDEST\": \"Fecha de creacion, mas vieja\",\n             \"SORT-EMAIL-A\": \"Email, A-Z\",\n             \"SORT-EMAIL-Z\": \"Email, Z-A\",\n             \"SORT-ID-A\": \"Identificador de usuario, A-Z\",\n             \"SORT-ID-Z\": \"Identificador de usuario, Z-A\"\n         },\n         \"POPUP\": {\n             \"CREATE-TITLE\": \"Crear usuario\",\n             \"EDIT-TITLE\": \"Editar detalles de usuario\",\n             \"CREATE-ID\": \"Identificador de usuario\",\n             \"CREATE-EMAIL\": \"Email\",\n             \"CREATE-INVALID-EMAIL\": \"Invalido\",\n             \"CREATE-PASSWORD\": \"Password\",\n             \"CREATE-FIRSTNAME\": \"Nombre\",\n             \"CREATE-LASTNAME\": \"Apellidos\",\n             \"CREATE-TENANT\": \"Tenant\",\n             \"CREATE-COMPANY\": \"Compañia\",\n             \"CREATE-STATUS\": \"Estatus\",\n             \"CREATE-TYPE\": \"Tipo\",\n             \"BULK-UPDATE-TITLE\": \"Actualizacion masiva de usuarios\",\n             \"BULK-UPDATE-NEW-STATUS\": \"Nuevo estatus:\",\n             \"BULK-UPDATE-NEW-TYPE\": \"Nuevo tipo de cuenta:\",\n             \"BULK-UPDATE-EMAIL-NOTIFICATIONS\": \"Enviar notificaciones por email de cambio de estatus\",\n             \"BULK-UPDATE-STATUS-USERS\": \"Estas apunto de actualizar el estatus de los siguientes {{length}} usuarios:\",\n             \"BULK-UPDATE-TYPE-USERS\": \"Estas apunto de actualizar el tipo de cuenta de los siguientes {{length}} usuarios:\",\n             \"BULK-UPDATE-CANCEL\": \"Cancelar y cerrar\",\n             \"BULK-UPDATE-CONFIRM\": \"Actualizar usuarios\",\n             \"BULK-UPDATE-PASSWORD-TITLE\": \"Cambiar password\",\n             \"BULK-UPDATE-PASSWORD\": \"Password\",\n             \"BULK-UPDATE-PASSWORD-REPEAT\": \"Repetir password\",\n             \"BULK-UPDATE-PASSWORD-CONFIRM\": \"Cambiar\"\n         }\n      },\n      \"FUNCTIONAL-GROUP-MGMT\": {\n        \"CREATE\": \"Crear grupo\",\n        \"NO-GROUPS\": \"No se encontraron grupos\",\n        \"NO-SELECTION\": \"Selecciona un grupo de la lista de la izquierda\",\n        \"SYNC-DETAILS\": \"Detalles de sincronizacion\",\n        \"EXTERNAL-ID\": \"Identificador externo:\",\n        \"LAST-SYNC-TIME\": \"Ultima actualizacion:\",\n        \"MEMBERS\": \"Miembros del grupo\",\n        \"SUBGROUPS\": \"Subgrupos\",\n        \"NO-MEMBERS\": \"No se encontraron usuarios\",\n        \"ADD-USER\": \"+ agregar usuario\",\n        \"ADD-SUBGROUP\": \"+ agregar subgrupo\",\n        \"NO-SUBGROUPS\": \"No se encontraron subgrupos\",\n        \"USER-ADDED\": \"Los usuarios se agregaron al grupo\",\n        \"INACTIVE\": \"desactivado\",\n        \"INACTIVE-DESCRIPTION\": \"Este grupo ha sido desactivado. Los usuarios aun podran completar las tareas asignadas a este grupo, pero las nuevas definiciones de proceso no podran utilizar mas este grupo.\",\n        \"ADD-POPOVER-TITLE\": \"Seleccionar usuario\",\n            \"POPUP\": {\n                \"CREATE-TITLE\": \"Crear grupo\",\n                \"CREATE-ID\": \"Grupo identificador\",\n                \"CREATE-NAME\": \"Nombre\",\n                \"DELETE-TITLE\": \"Borrar grupo\",\n                \"DELETE-DESCRIPTION\": \"Estas seguro que deseas borrar este grupo?\",\n                \"DELETE-CONFIRM\": \"Confirmar\",\n                \"DEACTIVATE-TITLE\": \"Desactivar grupo\",\n                \"DEACTIVATE-DESCRIPTION\": \"Estas seguro que deseas borrar este grupo? Esto borrara tambien todos los subgrupos. El grupo primero sera desactivado, para que las tareas del proceso puedan ser completadas correctamente. Dando click en el boton remover por segunda vez, eliminara el grupo permanentemente.\",\n                \"DELETE-MEMBER-TITLE\": \"Borrar miembro del grupo\",\n                \"DELETE-MEMBER-DESCRIPTION\": \"Estas seguro que deseas borrar este usuario del grupo?\",\n                \"ADD-MEMBER-TITLE\": \"Agregar usuario\",\n                \"ADD-MEMBER-NO-USERS\": \"No se encontraron usuarios\",\n                \"ADD-MEMBER-CONFIRM\": \"Agregar ({{selectedUsers.length}})\",\n                \"ACTIVATE-TITLE\": \"Activar grupo\",\n                \"ACTIVATE-DESCRIPTION\": \"Activar este grupo nuevamente? EDIT-PROFILEsto significa que este grupo estara disponible para la asignacion de tareas. Por default los subgrupos de un grupo no estan activos.\",\n                \"ACTIVATE-CONFIRM\": \"Activar\",\n                \"EDIT-TITLE\": \"Editar grupo\"\n            }\n        },\n      \"PRIVILEGE-MGMT\": {\n          \"access-idm\": \"Acceso a la App de gestion de identidad\",\n          \"access-admin\": \"Acceso a la App de administrador\",\n          \"access-modeler\": \"Acceso a la App de modelador\",\n          \"access-task\": \"Acceso a la App de workflow\",\n          \"access-rest-api\": \"Acceso a la REST API\",\n          \"NO-SELECTION\": \"No se seleccionaron privilegios\",\n          \"USERS\": \"Usuarios\",\n          \"GROUPS\": \"Grupos\",\n          \"NO-USERS\": \"Aun no se agregaron usuarios. Click aqui para agregar un usuario.\",\n          \"NO-GROUPS\": \"Aun no se han agregado grupos. Click aqui para agregar un grupo.\",\n          \"ADD-USER\": \"Agregar un usuario\",\n          \"ADD-GROUP\": \"Agregar un grupo\",\n          \"POPOVER-SELECT-USER-TITLE\": \"Usuario seleccionado\",\n          \"POPOVER-SELECT-GROUP-TITLE\": \"Grupo seleccionado\",\n          \"GROUP-ID\": \"Identificador de grupo\",\n          \"GROUP-NAME\": \"Nombre de grupo\"\n      },\n      \"PROFILE-MGMT\": {\n         \"CREATED\": \"Registrado desde\",\n         \"CHANGE-PASSWORD\": \"Cambiar password\",\n         \"DETAILS\": \"Detalles\",\n         \"DETAILS-DESCRIPTION\": \"Click en cualquiera de los campos debajo para cambiar sus valores\",\n         \"FIRST-NAME\": \"Nombre\",\n         \"NOTHING-SET\": \"Nada fijado\",\n         \"LAST-NAME\": \"Apellido\",\n         \"EMAIL\": \"Email\",\n         \"COMPANY\": \"Compania\",\n         \"GROUPS\": \"Tus grupos\",\n         \"POPUP\": {\n            \"UPLOAD-PICTURE-TITLE\": \"Cambiar imagen\",\n            \"UPLOAD-PICTURE-DESCRIPTION\": \"Por favor selecciona una imagen de tu PC o arrastrala en la zona debajo.\",\n            \"UPLOAD-PICTURE-CANCEL-UPLOAD\": \"Cancelar carga\",\n            \"UPLOAD-PICTURE-DROPZONE\": \"Arrastra un archivo de imagen de tu logo aqui\",\n            \"UPLOAD-PICTURE-NO-DROP\": \"Arastre no soportado por tu navegador\",\n            \"UPLOAD-PICTURE-ERROR\": \"Error\",\n            \"CHANGE-PASSWORD-TITLE\": \"Cambiar password\",\n            \"CHANGE-PASSWORD-ORIGINAL\": \"Original password\",\n            \"CHANGE-PASSWORD-NEW-PASSWORD\": \"Nuevo password\",\n            \"CHANGE-PASSWORD-NEW-PASSWORD2\": \"Repetir nuevo password\",\n            \"CHANGE-PASSWORD-CONFIRM\": \"Confirmar\",\n            \"CHANGE-PASSWORD-NOT-MATCHING\": \"Los passwords no coinciden\",\n            \"CHANGE-PASSWORD-INVALID\": \"Password invalido\"\n         }\n      },\n      \"USERS\": {\n        \"TITLE\": \"Administracion de usuarios\",\n        \"ACTION\": {\n          \"CREATE\": \"Crear usuario\"\n        }\n      }\n    },\n    \"INVOLVE-PEOPLE\": {\n        \"ACTION-SELECT\": \"Seleccionar\",\n        \"SEARCH-PLACEHOLDER\": \"Buscar por nombre\",\n        \"NO-MATCHING-RESULTS\": \"Usa el campo de busqueda de arriba para encontrar usuarios\"\n    }\n}\n"
  },
  {
    "path": "flowable-ui-web/idm/i18n/fr.json",
    "content": "{\n   \"GENERAL\": {\n        \"MAIN-TITLE\": \"Flowable\",\n        \"ERROR\": {\n            \"GENERIC\": \"Désolé, une erreur s'est produite...\",\n            \"UNKNOWN\": \"Désolé, une erreur s'est produite lors de l'exécution de l'opération.\",\n            \"BAD_REQUEST\": \"Une erreur s'est produite lors de l'exécution de l'opération demandée.\",\n            \"NOT_FOUND\": \"La resource demandée n'existe pas\",\n            \"UNAUTHORIZED\": \"Veuillez d'abord vous connecter pour effectuer cette opération.\",\n            \"FORBIDDEN\": \"Vous n'êtes pas autorisé à effectuer cette opération.\",\n            \"INTERNAL_SERVER_ERROR\": \"Désolé, une erreur inattendue s'est produite lors de l'exécution de l'opération.\"\n        },\n        \"ACTION\": {\n            \"LOGOUT\": \"Déconnexion\",\n            \"HELP\": \"Prise en main\",\n            \"EDIT-PROFILE\": \"Editer profil\",\n            \"SAVE\": \"Sauver\",\n            \"CANCEL\": \"Annuler\",\n            \"CLOSE\": \"Fermer\",\n            \"DEPLOY\": \"Déployer\",\n            \"ABOUT\": \"A propos Flowable\"\n        },\n        \"MESSAGE\": {\n            \"SELECT-PEOPLE-HELP\": \"Utiliser &uparrow; et &downarrow; pour sélectionner et appuyer sur entrée pour confirmer\",\n            \"SELECT-GROUP-HELP\": \"Utiliser &uparrow; et &downarrow; pour sélectionner et appuyer sur entrée pour confirmer\",\n            \"SELECT-GROUP-SEARCH-PLACEHOLDER\": \"Rechercher un groupe\",\n            \"SELECT-GROUP-NO-MATCHING-RESULTS\": \"Utiliser le champ de recherche au-dessus pour trouver les groupes.\"\n        },\n        \"TITLE\": {\n            \"MATCHING-PEOPLE\": \"Personnes correspondantes\",\n            \"SELECT-GROUP\": \"Choisir un groupe\",\n            \"MATCHING-GROUPS\": \"Groupes correspondants\"\n        }\n    },\n    \"LOGIN\": {\n        \"TITLE\": \"Se connecter\",\n        \"USERNAME\": \"Nom d'utilisateur\",\n        \"USERNAME-PLACEHOLDER\": \"Veuillez saisir votre nom d'utilisateur\",\n        \"PASSWORD\": \"Mot de passe\",\n        \"PASSWORD-PLACEHOLDER\": \"Veuillez saisir votre mot de passe\",\n        \"INVALID-CREDENTIALS\": \"Identifiants invalides\",\n        \"ACTION\": {\n            \"CONFIRM\": \"Connexion\"\n        }\n    },\n    \"ACCOUNT\": {\n        \"ACTIVATE\": {\n          \"TITLE\": \"Activer votre compte\",\n          \"ACTIVATING-MESSAGE\": \"Tenez bon {{userFullName}} nous activons votre compte...\",\n          \"SUCCESS-MESSAGE\": \"Votre compte a été activé. Veuillez vous connecter ci dessous pour concevoir et executer des processus.\",\n          \"FAILURE-MESSAGE\": \"Votre compte ne peut être activé. Il est soit déjà actif soit le lien d'activation a expiré.\"\n        },\n\n        \"RESET-PASSWORD-REQUEST\": {\n          \"MESSAGE\": \"Mot de pass oublié ? Veuillez saisir votre adresse e-mail ci dessous afin de recevoir un email de réinitialisation\",\n          \"TITLE\": \"Réinitialiser mot de passe\",\n          \"EMAIL\": \"Adresse e-mail\",\n          \"EMAIL-PLACEHOLDER\": \"Veuillez saisir votre e-mail\",\n          \"SECURITY-SECTION\": \"Vérifications de sécurité\",\n          \"CONFIRM\": \"Demande de réinitialisation du mot de passe\",\n          \"SUCCESS-MESSAGE\": \"Vous recevrez sous peu un e-mail vous expliquant comment réinitialiser votre mot de passe.\",\n          \"ERROR\": {\n              \"UNEXISTING-USER\": \"Aucun utilisateur n'existe avec cet adresse e-mail.\"\n          }\n        },\n\n        \"RESET-PASSWORD\": {\n          \"TITLE\": \"Réinitialiser mot de passe\",\n          \"PASSWORD\": \"Mot de passe\",\n          \"PASSWORD-CONFIRM\": \"Confirmez le mot de passe\",\n          \"PASSWORD-PLACEHOLDER\": \"Entrez un nouveau mot de passe\",\n          \"PASSWORD-CONFIRM-PLACEHOLDER\": \"Confirmez le nouveau mot de passe \",\n          \"CONFIRM\": \"Changer le mot de passe\",\n          \"LOADING\": \"Réinitialisation du mot de passe...\",\n          \"SUCCESS-MESSAGE\": \"Votre mot de passe a été modifié.\",\n          \"LOGIN\": \"Se connecter\",\n          \"FAILURE-MESSAGE\": \"Votre mot de passe ne peut être réinitialisé. Le lien a expiré ou est invalide.\"\n        }\n    },\n    \"IDM\": {\n      \"GENERAL\" : {\n        \"MAIN-TITLE\": \"Flowable - Gestion des identités\",\n        \"NAVIGATION\": {\n            \"PROFILE\": \"Personnel\",\n            \"USER-MGMT\": \"Utilisateurs\",\n            \"GROUP-MGMT\": \"Groupes\",\n            \"PRIVILEGE-MGMT\": \"Privilèges\"\n        },\n        \"ACTION\": {\n          \"CANCEL\": \"Annuler\",\n          \"CREATE\": \"Créer\",\n          \"SAVE\": \"Sauver\",\n          \"CLOSE\": \"Fermer\",\n          \"LOGOUT\": \"Déconnexion\",\n          \"ABOUT\": \"A Propos Flowable\"\n        },\n        \"ERROR\": {\n          \"GENERIC\": \"Désolé, une erreur s'est produite...\",\n          \"UNKNOWN\": \"Désolé, une erreur s'est produite lors de l'exécution de l'opération.\",\n          \"BAD_REQUEST\": \"Une erreur s'est produite lors de l'exécution de l'opération demandée.\",\n          \"NOT_FOUND\": \"La resource demandée n'existe pas\",\n          \"UNAUTHORIZED\": \"Veuillez d'abord vous connecter pour effectuer cette opération.\",\n          \"FORBIDDEN\": \"Vous n'êtes pas autorisé à effectuer cette opération.\",\n          \"INTERNAL_SERVER_ERROR\": \"Désolé, une erreur inattendue s'est produite lors de l'exécution de l'opération.\"\n        }\n      },\n      \"USER-MGMT\": {\n        \"TITLE\": \"Utilisateurs correspondants\",\n         \"CREATE-USER\": \"Créer un utilisateur\",\n         \"NAME-SEARCH\": \"Recherche par nom\",\n         \"COMPANY\": \"Société\",\n         \"STATUS\": \"Statut\",\n         \"ACCOUNT\": \"Type de compte\",\n         \"ACTIONS\": \"Choisir une action\",\n         \"CHANGE-STATUS\": \"Changer de statut\",\n         \"CHANGE-ACCOUNT-TYPE\": \"Changer de type de compte\",\n         \"CHANGE-PASSWORD\": \"Changer le mot de passe\",\n         \"EDIT-USER\": \"Changer les détails\",\n         \"DELETE-USERS\": \"Supprimer\",\n         \"TOTAL-USERS\": \"total\",\n         \"INACTIVE-USERS\": \"inactif\",\n         \"ENTERPRISE-USERS\": \"enterprise\",\n         \"ACTIVE-USERS\": \"actif\",\n         \"DELETED-USERS\": \"supprimé\",\n         \"ORDER-BY\": \"Trier par\",\n         \"SHOW-NEXT\": \"Afficher la suite\",\n         \"SHOW-PREVIOUS\": \"Afficher précedemment\",\n         \"NO-MATCHING-USERS\": \"Aucun utilisateur correspondant n'a été trouvé\",\n         \"MATCHING-USERS\": \"{{total | number}} utilisateur(s) trouvés, afficher du {{start + 1}} au {{start + size}}\",\n         \"ID\": \"ID\",\n         \"EMAIL\": \"E-mail\",\n         \"NAME\": \"Nom\",\n         \"CREATED\": \"Créé\",\n         \"TYPE\": \"Type\",\n         \"EXTERNAL-ID\": \"Identifiant externe\",\n         \"LAST-SYNC-TIME\": \"Dernière modification\",\n         \"FILTERS\": {\n             \"STATUS-ANY\": \"N'importe quel statut\",\n             \"STATUS-ACTIVE\": \"Actif\",\n             \"STATUS-INACTIVE\": \"Inactif\",\n             \"STATUS-PENDING\": \"En attente\",\n             \"STATUS-DELETED\": \"Supprimé\",\n             \"TYPE-ANY\": \"N'importe quel type\",\n             \"SORT-DATE-NEWEST\": \"Date de création, du plus récent\",\n             \"SORT-DATE-OLDEST\": \"Date de création, du plus ancien\",\n             \"SORT-EMAIL-A\": \"E-mail, A-Z\",\n             \"SORT-EMAIL-Z\": \"E-mail, Z-A\",\n             \"SORT-ID-A\": \"Identifiant utilisateur, A-Z\",\n             \"SORT-ID-Z\": \"Identifiant utilisateur, Z-A\"\n         },\n         \"POPUP\": {\n             \"CREATE-TITLE\": \"Créer utilisateur\",\n             \"EDIT-TITLE\": \"Modifier les détails de l'utilisateur\",\n             \"CREATE-ID\": \"Identifiant utilisateur\",\n             \"CREATE-EMAIL\": \"E-mail\",\n             \"CREATE-INVALID-EMAIL\": \"Invalide\",\n             \"CREATE-PASSWORD\": \"Mot de passe\",\n             \"CREATE-FIRSTNAME\": \"Prénom\",\n             \"CREATE-LASTNAME\": \"Nom\",\n             \"CREATE-TENANT\": \"Tenant\",\n             \"CREATE-COMPANY\": \"Société\",\n             \"CREATE-STATUS\": \"Statut\",\n             \"CREATE-TYPE\": \"Type\",\n             \"BULK-UPDATE-TITLE\": \"Editer en masse les utilisateurs\",\n             \"BULK-UPDATE-NEW-STATUS\": \"Nouveau statut:\",\n             \"BULK-UPDATE-NEW-TYPE\": \"Nouveau type de compte:\",\n             \"BULK-UPDATE-EMAIL-NOTIFICATIONS\": \"Envoyer un e-mail de notification pour un changement de statut \",\n             \"BULK-UPDATE-STATUS-USERS\": \"Vous êtes sur le point de changer votre statut pour {{length}} utilisateur(s):\",\n             \"BULK-UPDATE-TYPE-USERS\": \"Vous êtes sur le point de changer de type de compte pour  {{length}} utilisateur(s):\",\n             \"BULK-UPDATE-CANCEL\": \"Annuler et fermer\",\n             \"BULK-UPDATE-CONFIRM\": \"Mise à jour des utilisateurs\",\n             \"BULK-UPDATE-PASSWORD-TITLE\": \"Modifier le mot de passe\",\n             \"BULK-UPDATE-PASSWORD\": \"Mot de passe\",\n             \"BULK-UPDATE-PASSWORD-REPEAT\": \"Répéter le mot de passe\",\n             \"BULK-UPDATE-PASSWORD-CONFIRM\": \"Modifier\"\n         }\n      },\n      \"FUNCTIONAL-GROUP-MGMT\": {\n        \"CREATE\": \"Créer un groupe\",\n        \"NO-GROUPS\": \"Aucun groupes trouvé\",\n        \"NO-SELECTION\": \"Sélectionner un groupe depuis la liste de gauche.\",\n        \"SYNC-DETAILS\": \"Détails de synchronisation\",\n        \"EXTERNAL-ID\": \"Identifiant externe:\",\n        \"LAST-SYNC-TIME\": \"Dernière modification:\",\n        \"MEMBERS\": \"Membres du groupe\",\n        \"SUBGROUPS\": \"Sous-groupe\",\n        \"NO-MEMBERS\": \"Aucun utilisateurs trouvé\",\n        \"ADD-USER\": \"+ ajouter un utilisateur\",\n        \"ADD-SUBGROUP\": \"+ ajouter un sous-groupe\",\n        \"NO-SUBGROUPS\": \"Aucun sous-groupe trouvé\",\n        \"USER-ADDED\": \"Les utilisateurs ont été ajouté au groupe\",\n        \"INACTIVE\": \"desactivé\",\n        \"INACTIVE-DESCRIPTION\": \"Ce groupe a été désactive. Les utilisateurs peuvent toujours terminer les tâches assignées à ce groupe mais les nouvelles définitions de processus ne peuvent plus utiliser ce groupe.\",\n        \"ADD-POPOVER-TITLE\": \"Séléctionner un utilisateur\",\n            \"POPUP\": {\n                \"CREATE-TITLE\": \"Créer un groupe\",\n                \"CREATE-ID\": \"Identifiant de groupe\",\n                \"CREATE-NAME\": \"Nom\",\n                \"DELETE-TITLE\": \"Supprimer groupe\",\n                \"DELETE-DESCRIPTION\": \"Êtes-vous sûr de vouloir supprimer ce groupe?\",\n                \"DELETE-CONFIRM\": \"Confirmer\",\n                \"DEACTIVATE-TITLE\": \"Desactiver le groupe\",\n                \"DEACTIVATE-DESCRIPTION\": \"Êtes-vous sûr de vouloir supprimer ce groupe? Tous les sous-groupes seront supprimés. A noter que ce groupe sera en premier désactiver afin que les tâches soient proprement terminées. Cliquer sur le boutton de supprimer une deuxième fois supprimera définitivement le groupe.\",\n                \"DELETE-MEMBER-TITLE\": \"Supprimer le membre du groupe\",\n                \"DELETE-MEMBER-DESCRIPTION\": \"Êtes-vous sûr de vouloir retirer l'utilisateur de ce groupe?\",\n                \"ADD-MEMBER-TITLE\": \"Ajouter un utilisateur\",\n                \"ADD-MEMBER-NO-USERS\": \"Aucun utilisateur trouvé\",\n                \"ADD-MEMBER-CONFIRM\": \"Ajouter ({{selectedUsers.length}})\",\n                \"ACTIVATE-TITLE\": \"Activer le groupe\",\n                \"ACTIVATE-DESCRIPTION\": \"Activer ce groupe de nouveau? Ce groupe sera alors de nouveau éligible à l'assignation de tâches. A noter que les sous-groupes du groupe ne sont pas activés par défaut.\",\n                \"ACTIVATE-CONFIRM\": \"Activer\",\n                \"EDIT-TITLE\": \"Modifier le groupe\"\n            }\n        },\n      \"PRIVILEGE-MGMT\": {\n          \"access-idm\": \"Accéder à l'application de gestion des identités\",\n          \"access-admin\": \"Accéder à l'application d'administration\",\n          \"access-modeler\": \"Accéder à l'application de modélisation\",\n\t\t  \"access-task\": \"Accéder à l'application de workflow \",\n\t\t  \"access-rest-api\": \"Accéder à le REST API\",\n          \"NO-SELECTION\": \"Aucun privilège sélectionné\",\n          \"USERS\": \"Utilisateurs\",\n          \"GROUPS\": \"Groupes\",\n          \"NO-USERS\": \"Aucun utilisateur n'a encore été ajouté. Cliquer ici pour en ajouter un\",\n          \"NO-GROUPS\": \"Aucun groupe n'a encore été ajouté.  Cliquer ici pour en ajouter un\",\n          \"ADD-USER\": \"Ajouter un utilisateur\",\n          \"ADD-GROUP\": \"Ajouter un groupe\",\n          \"POPOVER-SELECT-USER-TITLE\": \"Sélectionner un utilisateur\",\n          \"POPOVER-SELECT-GROUP-TITLE\": \"Sélectionner un groupe\",\n          \"GROUP-ID\": \"Identifiant de groupe\",\n          \"GROUP-NAME\": \"Nom du groupe\"\n      },\n      \"PROFILE-MGMT\": {\n         \"CREATED\": \"Enregistré depuis\",\n         \"CHANGE-PASSWORD\": \"Changer de mot de passe\",\n         \"DETAILS\": \"Détails\",\n         \"DETAILS-DESCRIPTION\": \"Cliquer sur n'importe quel champs pour les modifier\",\n         \"FIRST-NAME\": \"Prénom\",\n         \"NOTHING-SET\": \"Vide\",\n         \"LAST-NAME\": \"Nom\",\n         \"EMAIL\": \"E-mail\",\n         \"COMPANY\": \"Société\",\n         \"GROUPS\": \"Vos groupes\",\n         \"POPUP\": {\n            \"UPLOAD-PICTURE-TITLE\": \"Changer la photo\",\n            \"UPLOAD-PICTURE-DESCRIPTION\": \"Veuillez sélectionner une image depuis votre ordinateur ou bien la déposer sur la zone ci-dessous.\",\n            \"UPLOAD-PICTURE-CANCEL-UPLOAD\": \"Annuler l'envoi\",\n            \"UPLOAD-PICTURE-DROPZONE\": \"Déposer le fichier image ici\",\n            \"UPLOAD-PICTURE-NO-DROP\": \"L'action de déposer n'est pas supporté par votre navigateur\",\n            \"UPLOAD-PICTURE-ERROR\": \"Erreur\",\n            \"CHANGE-PASSWORD-TITLE\": \"Modifier le mot de passe\",\n            \"CHANGE-PASSWORD-ORIGINAL\": \"Mot de passe d'origine\",\n            \"CHANGE-PASSWORD-NEW-PASSWORD\": \"Nouveau mot de passe\",\n            \"CHANGE-PASSWORD-NEW-PASSWORD2\": \"Répéter le mot de passe\",\n            \"CHANGE-PASSWORD-CONFIRM\": \"Confirmer\",\n            \"CHANGE-PASSWORD-NOT-MATCHING\": \"Les mots de passe ne sont pas identiques\",\n            \"CHANGE-PASSWORD-INVALID\": \"Mot de passe incorrect\"\n         }\n      },\n      \"USERS\": {\n        \"TITLE\": \"Administration des utilisateurs\",\n        \"ACTION\": {\n          \"CREATE\": \"Créer un utilisateur\"\n        }\n      }\n    },\n    \"INVOLVE-PEOPLE\": {\n        \"ACTION-SELECT\": \"Sélectionner\",\n        \"SEARCH-PLACEHOLDER\": \"Recherche par nom \",\n        \"NO-MATCHING-RESULTS\": \"Utiliser le champ de recherche ci-dessus pour trouver des utilisateurs\"\n    }\n}\n"
  },
  {
    "path": "flowable-ui-web/idm/i18n/pt-BR.json",
    "content": "{\n  \"GENERAL\":{\n    \"MAIN-TITLE\":\"Flowable\",\n    \"ERROR\":{\n      \"GENERIC\":\"Desculpe, ocorreu um erro...\",\n      \"UNKNOWN\":\"Desculpe, um erro ocorreu durante a execução da operação solicitada.\",\n      \"BAD_REQUEST\":\"Um erro ocorreu durante a execução da operação solicitada\",\n      \"NOT_FOUND\":\"O recurso que você está tentando acessar não existe\",\n      \"UNAUTHORIZED\":\"Você deve fazer login para executar a operação solicitada.\",\n      \"FORBIDDEN\":\"Você não tem permissão para executar a operação solicitada\",\n      \"INTERNAL_SERVER_ERROR\":\"Desculpe, um erro inesperado ocorreu durante a execução da operação solicitada.\"\n    },\n    \"ACTION\":{\n      \"LOGOUT\":\"Sair\",\n      \"HELP\":\"Guia de introdução\",\n      \"EDIT-PROFILE\":\"Editar perfil\",\n      \"SAVE\":\"Salvar\",\n      \"CANCEL\":\"Cancelar\",\n      \"CLOSE\":\"Fechar\",\n      \"DEPLOY\":\"Implantar\",\n      \"ABOUT\":\"Sobre Flowable\"\n    },\n    \"MESSAGE\":{\n      \"SELECT-PEOPLE-HELP\":\"Use &uparrow; e &downarrow; para selecionar e pressione Enter para confirmar\",\n      \"SELECT-GROUP-HELP\":\"Use &uparrow; e &downarrow; para selecionar e pressione Enter para confirmar\",\n      \"SELECT-GROUP-SEARCH-PLACEHOLDER\":\"Procurar grupos\",\n      \"SELECT-GROUP-NO-MATCHING-RESULTS\":\"Use a caixa de pesquisa acima para encontrar grupos.\"\n    },\n    \"TITLE\":{\n      \"MATCHING-PEOPLE\":\"Pessoas correspondentes\",\n      \"SELECT-GROUP\":\"Selecionar grupo\",\n      \"MATCHING-GROUPS\":\"Grupos correspondentes\"\n    }\n  },\n  \"LOGIN\":{\n    \"TITLE\":\"Entrar\",\n    \"USERNAME\":\"Nome de Usuário\",\n    \"USERNAME-PLACEHOLDER\":\"Entre com o usuário\",\n    \"PASSWORD\":\"Senha\",\n    \"PASSWORD-PLACEHOLDER\":\"Entre com a senha\",\n    \"INVALID-CREDENTIALS\":\"Credenciais inválidas\",\n    \"ACTION\":{\n      \"CONFIRM\":\"Entrar\"\n    }\n  },\n  \"ACCOUNT\":{\n    \"ACTIVATE\":{\n      \"TITLE\":\"Ativar Conta\",\n      \"ACTIVATING-MESSAGE\":\"Aguarde um momento {{userFullName}} que estamos ativando sua conta...\",\n      \"SUCCESS-MESSAGE\":\"Sua conta foi ativada. Por favor, Cadastre-se abaixo para começar a desenhar e executar processos\",\n      \"FAILURE-MESSAGE\":\"Sua conta não pode ser ativada. Ou já foi ativada ou o link de ativação expirou.\"\n    },\n    \"RESET-PASSWORD-REQUEST\":{\n      \"MESSAGE\":\"Esqueceu sua senha? Digite seu endereço de e-mail abaixo para receber um e-mail e redefinir sua senha.\",\n      \"TITLE\":\"Redefinir senha\",\n      \"EMAIL\":\"E-mail\",\n      \"EMAIL-PLACEHOLDER\":\"Digite seu e-mail\",\n      \"SECURITY-SECTION\":\"Verificação de segurança\",\n      \"CONFIRM\":\"Pedido de redefinição de senha\",\n      \"SUCCESS-MESSAGE\":\"Em breve você receberá um e-mail com um link para redefinir sua senha.\",\n      \"ERROR\":{\n        \"UNEXISTING-USER\":\"O usuário com o endereço de e-mail fornecido não existe.\"\n      }\n    },\n    \"RESET-PASSWORD\":{\n      \"TITLE\":\"Redefinir senha\",\n      \"PASSWORD\":\"Senha\",\n      \"PASSWORD-CONFIRM\":\"Confirme a senha\",\n      \"PASSWORD-PLACEHOLDER\":\"Digite a nova senha\",\n      \"PASSWORD-CONFIRM-PLACEHOLDER\":\"Confirme a nova senha\",\n      \"CONFIRM\":\"Alterar a senha\",\n      \"LOADING\":\"Redefinindo senha...\",\n      \"SUCCESS-MESSAGE\":\"Sua senha foi alterada.\",\n      \"LOGIN\":\"Entrar agora\",\n      \"FAILURE-MESSAGE\":\"Sua senha não pode ser redefinida. O link de redefinição é inválido ou está expirado.\"\n    }\n  },\n  \"IDM\":{\n    \"GENERAL\":{\n      \"MAIN-TITLE\":\"Flowable - Gerenciamento de Identidade\",\n      \"NAVIGATION\":{\n        \"PROFILE\":\"Pessoal\",\n        \"USER-MGMT\":\"Usuários\",\n        \"GROUP-MGMT\":\"Grupos\",\n        \"PRIVILEGE-MGMT\":\"Privilégios\"\n      },\n      \"ACTION\":{\n        \"CANCEL\":\"Cancelar\",\n        \"CREATE\":\"Criar\",\n        \"SAVE\":\"Salvar\",\n        \"CLOSE\":\"Fechar\",\n        \"LOGOUT\":\"Sair\",\n        \"ABOUT\":\"Sobre Flowable\"\n      },\n      \"ERROR\":{\n        \"GENERIC\":\"Desculpe, ocorreu um erro...\",\n        \"UNKNOWN\":\"Desculpe, um erro ocorreu durante a execução da operação solicitada.\",\n        \"BAD_REQUEST\":\"Um erro ocorreu durante a execução da operação solicitada\",\n        \"NOT_FOUND\":\"O recurso que você está tentando acessar não existe\",\n        \"UNAUTHORIZED\":\"Você deveria assinar para executar a operação solicitada.\",\n        \"FORBIDDEN\":\"Você não está autorizado a executar a operação solicitada\",\n        \"INTERNAL_SERVER_ERROR\":\"Desculpe, um erro inesperado ocorreu durante a execução da operação solicitada.\"\n      }\n    },\n    \"USER-MGMT\":{\n      \"TITLE\":\"Usuários correspondentes\",\n      \"CREATE-USER\":\"Criar usuário\",\n      \"NAME-SEARCH\":\"Buscar por nome\",\n      \"COMPANY\":\"Empresa\",\n      \"STATUS\":\"Estado\",\n      \"ACCOUNT\":\"Tipo de Conta\",\n      \"ACTIONS\":\"Selecione uma ação\",\n      \"CHANGE-STATUS\":\"Alterar status\",\n      \"CHANGE-ACCOUNT-TYPE\":\"Alterar tipo de conta\",\n      \"CHANGE-PASSWORD\":\"Alterar a senha\",\n      \"EDIT-USER\":\"Alterar Informações\",\n      \"DELETE-USERS\":\"Excluir\",\n      \"TOTAL-USERS\":\"total\",\n      \"INACTIVE-USERS\":\"inativo\",\n      \"ENTERPRISE-USERS\":\"enterprise\",\n      \"ACTIVE-USERS\":\"ativo\",\n      \"DELETED-USERS\":\"excuído\",\n      \"ORDER-BY\":\"Ordenar por\",\n      \"SHOW-NEXT\":\"Mostrar próxima\",\n      \"SHOW-PREVIOUS\":\"Mostrar anterior\",\n      \"NO-MATCHING-USERS\":\"Não foi encontrado usuário correspondente\",\n      \"MATCHING-USERS\":\"Encontrado {{total | number}} usuários correspondente(s), mostrando {{start + 1}} de {{start + size}}\",\n      \"ID\":\"ID\",\n      \"EMAIL\":\"Email\",\n      \"NAME\":\"Nome\",\n      \"CREATED\":\"Criado em\",\n      \"TYPE\":\"Tipo\",\n      \"EXTERNAL-ID\":\"Id Externo\",\n      \"LAST-SYNC-TIME\":\"Última atualização\",\n      \"FILTERS\":{\n        \"STATUS-ANY\":\"Qualquer estado\",\n        \"STATUS-ACTIVE\":\"Ativo\",\n        \"STATUS-INACTIVE\":\"Inativo\",\n        \"STATUS-PENDING\":\"Pendente\",\n        \"STATUS-DELETED\":\"Excluído\",\n        \"TYPE-ANY\":\"Qualquer tipo\",\n        \"SORT-DATE-NEWEST\":\"Data de criação - mais novo\",\n        \"SORT-DATE-OLDEST\":\"Data de criação - mais antigo\",\n        \"SORT-EMAIL-A\":\"E-mail, A-Z\",\n        \"SORT-EMAIL-Z\":\"E-mail, Z-A\",\n        \"SORT-ID-A\":\"Id de usuário, A-Z\",\n        \"SORT-ID-Z\":\"Id de usuário, Z-A\"\n      },\n      \"POPUP\":{\n        \"CREATE-TITLE\":\"Criar usuário\",\n        \"EDIT-TITLE\":\"Editar informações do usuário\",\n        \"CREATE-ID\":\"ID do usuário\",\n        \"CREATE-EMAIL\":\"Email\",\n        \"CREATE-INVALID-EMAIL\":\"Inválido\",\n        \"CREATE-PASSWORD\":\"Senha\",\n        \"CREATE-FIRSTNAME\":\"Primeiro nome\",\n        \"CREATE-LASTNAME\":\"Último nome\",\n        \"CREATE-TENANT\":\"Tenant\",\n        \"CREATE-COMPANY\":\"Empresa\",\n        \"CREATE-STATUS\":\"Status\",\n        \"CREATE-TYPE\":\"Tipo\",\n        \"BULK-UPDATE-TITLE\":\"Atualização de usuários em massa\",\n        \"BULK-UPDATE-NEW-STATUS\":\"Novo status:\",\n        \"BULK-UPDATE-NEW-TYPE\":\"Novo tipo de conta:\",\n        \"BULK-UPDATE-EMAIL-NOTIFICATIONS\":\"Enviar notificações por e-mail para alteração de status\",\n        \"BULK-UPDATE-STATUS-USERS\":\"Você está prestes a atualizar o status para este(s) {{length}} usuário(s):\",\n        \"BULK-UPDATE-TYPE-USERS\":\"Você está prestes a atualizar o tipo de conta para este(s) {{length}} usuário(s):\",\n        \"BULK-UPDATE-CANCEL\":\"Cancelar e fechar\",\n        \"BULK-UPDATE-CONFIRM\":\"Atualizar usuários\",\n        \"BULK-UPDATE-PASSWORD-TITLE\":\"Alterar a senha\",\n        \"BULK-UPDATE-PASSWORD\":\"Senha\",\n        \"BULK-UPDATE-PASSWORD-REPEAT\":\"Repita a senha\",\n        \"BULK-UPDATE-PASSWORD-CONFIRM\":\"Salvar\"\n      }\n    },\n    \"FUNCTIONAL-GROUP-MGMT\":{\n      \"CREATE\":\"Criar grupo\",\n      \"NO-GROUPS\":\"Nenhum grupo encontrado\",\n      \"NO-SELECTION\":\"Selecione um grupo na lista da esquerda\",\n      \"SYNC-DETAILS\":\"Sincronização de informações\",\n      \"EXTERNAL-ID\":\"ID Externo:\",\n      \"LAST-SYNC-TIME\":\"Última atualização:\",\n      \"MEMBERS\":\"Membros do Grupo\",\n      \"SUBGROUPS\":\"Subgrupos\",\n      \"NO-MEMBERS\":\"Não foram encontrados usuários\",\n      \"ADD-USER\":\"+ Adicionar usuário\",\n      \"ADD-SUBGROUP\":\"+ Adicionar subgrupo\",\n      \"NO-SUBGROUPS\":\"Nenhum subgrupo encontrado\",\n      \"USER-ADDED\":\"Os usuários foram adicionados ao grupo\",\n      \"INACTIVE\":\"desativado\",\n      \"INACTIVE-DESCRIPTION\":\"Este grupo foi desativado. Os usuários ainda serão capazes de completar tarefas atualmente atribuídas a este grupo, mas novas definições do processo não podem mais usar esse grupo.\",\n      \"ADD-POPOVER-TITLE\":\"Selecionar usuário\",\n      \"POPUP\":{\n        \"CREATE-TITLE\":\"Criar Grupo\",\n        \"CREATE-ID\":\"Id do Grupo\",\n        \"CREATE-NAME\":\"Nome\",\n        \"DELETE-TITLE\":\"Excluir grupo\",\n        \"DELETE-DESCRIPTION\":\"Tem certeza que deseja excluir este grupo?\",\n        \"DELETE-CONFIRM\":\"Confirmar\",\n        \"DEACTIVATE-TITLE\":\"Desativar o grupo\",\n        \"DEACTIVATE-DESCRIPTION\":\"Tem certeza que deseja excluir este grupo? Isto irá apagar todos os subgrupos também. Note-se que um grupo será desativado primeiro, tal que as tarefas dos processos podem ser terminadas corretamente. Clicando no botão de remoção uma segunda vez irá apagar o grupo completamente.\",\n        \"DELETE-MEMBER-TITLE\":\"Excluir o membro do grupo\",\n        \"DELETE-MEMBER-DESCRIPTION\":\"Você tem certeza que deseja remover este usuário do grupo de usuários?\",\n        \"ADD-MEMBER-TITLE\":\"Adicionar Usuário\",\n        \"ADD-MEMBER-NO-USERS\":\"Não foram encontrados usuários\",\n        \"ADD-MEMBER-CONFIRM\":\"Adicionar ({{selectedUsers.length}})\",\n        \"ACTIVATE-TITLE\":\"Ativar grupo\",\n        \"ACTIVATE-DESCRIPTION\":\"Ativar este grupo novamente? Isto significa que este grupo seria novamente elegível para atribuição de tarefa. Note que os subgrupos de um grupo não são ativados por padrão.\",\n        \"ACTIVATE-CONFIRM\":\"Ativar\",\n        \"EDIT-TITLE\":\"Editar grupo\"\n      }\n    },\n    \"PRIVILEGE-MGMT\":{\n      \"access-idm\":\"Acesso ao aplicativo de gestão de identidade\",\n      \"access-admin\":\"Acesso ao aplicativo de administração\",\n      \"access-modeler\":\"Acesso ao aplicativo de modelagem\",\n      \"access-task\":\"Acesso ao aplicativo de workflow\",\n      \"access-rest-api\": \"Acesso ao REST API\",\n      \"NO-SELECTION\":\"Nenhum privilégio selecionado\",\n      \"USERS\":\"Usuários\",\n      \"GROUPS\":\"Grupos\",\n      \"NO-USERS\":\"Nenhum usuário adicionado ainda. Clique aqui para adicionar um usuário.\",\n      \"NO-GROUPS\":\"Nenhum grupo adicionado ainda.  Clique aqui para adicionar um grupo\",\n      \"ADD-USER\":\"Adicionar um usuário\",\n      \"ADD-GROUP\":\"Adicionar um grupo\",\n      \"POPOVER-SELECT-USER-TITLE\":\"Selecionar usuário\",\n      \"POPOVER-SELECT-GROUP-TITLE\":\"Selecionar grupo\",\n      \"GROUP-ID\":\"ID do Grupo\",\n      \"GROUP-NAME\":\"Nome do grupo\"\n    },\n    \"PROFILE-MGMT\":{\n      \"CREATED\":\"Registrado desde\",\n      \"CHANGE-PASSWORD\":\"Alterar a senha\",\n      \"DETAILS\":\"Informações\",\n      \"DETAILS-DESCRIPTION\":\"Clique em qualquer um dos campos abaixo para alterá-los\",\n      \"FIRST-NAME\":\"Primeiro nome\",\n      \"NOTHING-SET\":\"Nenhuma informação definida\",\n      \"LAST-NAME\":\"Último nome\",\n      \"EMAIL\":\"Email\",\n      \"COMPANY\":\"Empresa\",\n      \"GROUPS\":\"Seus grupos\",\n      \"POPUP\":{\n        \"UPLOAD-PICTURE-TITLE\":\"Alterar imagem\",\n        \"UPLOAD-PICTURE-DESCRIPTION\":\"Por favor, selecione uma imagem do seu computador ou arraste e solte na região abaixo.\",\n        \"UPLOAD-PICTURE-CANCEL-UPLOAD\":\"Cancelar upload\",\n        \"UPLOAD-PICTURE-DROPZONE\":\"Arraste e solte um arquivo de logo aqui\",\n        \"UPLOAD-PICTURE-NO-DROP\":\"Arrastar e soltar arquivo não é suportado pelo seu navegador\",\n        \"UPLOAD-PICTURE-ERROR\":\"Erro\",\n        \"CHANGE-PASSWORD-TITLE\":\"Alterar a senha\",\n        \"CHANGE-PASSWORD-ORIGINAL\":\"Senha atual\",\n        \"CHANGE-PASSWORD-NEW-PASSWORD\":\"Nova Senha\",\n        \"CHANGE-PASSWORD-NEW-PASSWORD2\":\"Repita a nova senha\",\n        \"CHANGE-PASSWORD-CONFIRM\":\"Confirmar\",\n        \"CHANGE-PASSWORD-NOT-MATCHING\":\"As senhas não conferem\",\n        \"CHANGE-PASSWORD-INVALID\":\"Senha inválida\"\n      }\n    },\n    \"USERS\":{\n      \"TITLE\":\"Administração de usuários\",\n      \"ACTION\":{\n        \"CREATE\":\"Criar usuário\"\n      }\n    }\n  },\n  \"INVOLVE-PEOPLE\":{\n    \"ACTION-SELECT\":\"Selecione\",\n    \"SEARCH-PLACEHOLDER\":\"Buscar por nome\",\n    \"NO-MATCHING-RESULTS\":\"Use a caixa de pesquisa acima para encontrar usuários\"\n  }\n}\n"
  },
  {
    "path": "flowable-ui-web/idm/i18n/zh-CN.json",
    "content": "{\n   \"GENERAL\": {\n        \"MAIN-TITLE\": \"Flowable\",\n        \"ERROR\": {\n            \"GENERIC\": \"对不起, 发生了错误...\",\n            \"UNKNOWN\": \"对不起, 执行请求的操作时出错。\",\n            \"BAD_REQUEST\": \"执行请求的操作时发生错误\",\n            \"NOT_FOUND\": \"您试图访问的资源不存在\",\n            \"UNAUTHORIZED\": \"您应该登录才能执行请求的操作。\",\n            \"FORBIDDEN\": \"您不允许执行请求的操作\",\n            \"INTERNAL_SERVER_ERROR\": \"对不起, 执行请求的操作时出现意外错误。\"\n        },\n     \"ACTION\": {\n            \"LOGOUT\": \"退出\",\n            \"HELP\": \"入门\",\n            \"EDIT-PROFILE\": \"编辑配置文件\",\n            \"SAVE\": \"保存\",\n            \"CANCEL\": \"取消\",\n            \"CLOSE\": \"关闭\",\n            \"DEPLOY\": \"部署\",\n            \"ABOUT\": \"关于Flowable\"\n        },\n        \"MESSAGE\": {\n            \"SELECT-PEOPLE-HELP\": \"使用 &uparrow; 和 &downarrow; 选择并按回车确认\",\n            \"SELECT-GROUP-HELP\": \"使用 &uparrow; 和 &downarrow; 选择并按回车确认\",\n            \"SELECT-GROUP-SEARCH-PLACEHOLDER\": \"选择组\",\n            \"SELECT-GROUP-NO-MATCHING-RESULTS\": \"使用上面的搜索框查找组.\"\n        },\n        \"TITLE\": {\n            \"MATCHING-PEOPLE\": \"匹配人\",\n            \"SELECT-GROUP\": \"选择组\",\n            \"MATCHING-GROUPS\": \"匹配组\"\n        }\n    },\n    \"LOGIN\": {\n        \"TITLE\": \"登录\",\n        \"USERNAME\": \"用户名\",\n        \"USERNAME-PLACEHOLDER\": \"输入您的用户名\",\n        \"PASSWORD\": \"密码\",\n        \"PASSWORD-PLACEHOLDER\": \"输入您的密码\",\n        \"INVALID-CREDENTIALS\": \"无效凭据\",\n        \"ACTION\": {\n            \"CONFIRM\": \"登录\"\n        }\n    },\n    \"ACCOUNT\": {\n        \"ACTIVATE\": {\n          \"TITLE\":\"激活帐户\",\n          \"ACTIVATING-MESSAGE\":\"{{userFullName}}, 请稍候, 我们正在激活您的帐户...\",\n          \"SUCCESS-MESSAGE\":\"您的帐户已被激活。请在下面登录, 开始设计和运行流程 \",\n          \"FAILURE-MESSAGE\":\"您的帐户无法激活。它已被激活或激活链接已过期。\"\n        },\n\n       \"RESET-PASSWORD-REQUEST\": {\n          \"MESSAGE\":\"忘记了您的密码？在下面输入您的电子邮件地址, 以接收电子邮件来重置您的密码。\",\n          \"TITLE\":\"重置密码\",\n          \"EMAIL\":\"电子邮件地址\",\n          \"EMAIL-PLACEHOLDER\":\"输入您的电子邮件\",\n          \"SECURITY-SECTION\":\"安全检查\",\n          \"CONFIRM\":\"请求密码重置\",\n          \"SUCCESS-MESSAGE\":\"你会收到一封邮件的链接, 重置您的密码。\",\n          \"ERROR\": {\n              \"UNEXISTING-USER\":\"具有给定电子邮件地址的用户不存在。\"\n          }\n        },\n\n        \"RESET-PASSWORD\": {\n          \"TITLE\":\"重置密码\",\n          \"PASSWORD\":\"密码\",\n          \"PASSWORD-CONFIRM\":\"确认密码\",\n          \"PASSWORD-PLACEHOLDER\":\"输入新密码\",\n          \"PASSWORD-CONFIRM-PLACEHOLDER\":\"确认新密码\",\n          \"CONFIRM\":\"更改密码\",\n          \"LOADING\":\"重置密码...\",\n          \"SUCCESS-MESSAGE\":\"您的密码已更改。\",\n          \"LOGIN\":\"现在登录\",\n          \"FAILURE-MESSAGE\":\"您的密码无法重置。重置链接无效或已过期。\"\n        }\n    },\n    \"IDM\": {\n      \"GENERAL\" : {\n        \"MAIN-TITLE\": \"Flowable - 身份管理\",\n        \"NAVIGATION\": {\n            \"PROFILE\": \"个人\",\n            \"USER-MGMT\": \"用户\",\n            \"GROUP-MGMT\": \"组\",\n            \"PRIVILEGE-MGMT\": \"权限\"\n        },\n        \"ACTION\": {\n          \"CANCEL\": \"取消\",\n          \"CREATE\": \"创建\",\n          \"SAVE\": \"保存\",\n          \"CLOSE\": \"关闭\",\n          \"LOGOUT\": \"退出\",\n          \"ABOUT\": \"关于Flowable\"\n        },\n        \"ERROR\": {\n           \"GENERIC\": \"对不起, 发生了错误...\",\n            \"UNKNOWN\": \"对不起, 执行请求的操作时出错。\",\n            \"BAD_REQUEST\": \"执行请求的操作时发生错误\",\n            \"NOT_FOUND\": \"您试图访问的资源不存在\",\n            \"UNAUTHORIZED\": \"您应该登录才能执行请求的操作。\",\n            \"FORBIDDEN\": \"您不允许执行请求的操作\",\n            \"INTERNAL_SERVER_ERROR\": \"对不起, 执行请求的操作时出现意外错误。\"\n        }\n      },\n      \"USER-MGMT\": {\n        \"TITLE\": \"匹配用户\",\n         \"CREATE-USER\": \"创建用户\",\n         \"NAME-SEARCH\": \"根据名称搜索\",\n         \"COMPANY\": \"公司\",\n         \"STATUS\": \"状态\",\n         \"ACCOUNT\": \"账户类型\",\n         \"ACTIONS\": \"选择一个动作\",\n         \"CHANGE-STATUS\": \"修改状态\",\n         \"CHANGE-ACCOUNT-TYPE\": \"修改账户类型\",\n         \"CHANGE-PASSWORD\": \"修改密码\",\n         \"EDIT-USER\": \"修改详细信息\",\n         \"DELETE-USERS\": \"删除\",\n         \"TOTAL-USERS\": \"总计\",\n         \"INACTIVE-USERS\": \"不活动的\",\n         \"ENTERPRISE-USERS\": \"企业\",\n         \"ACTIVE-USERS\": \"激活的\",\n         \"DELETED-USERS\": \"删除\",\n         \"ORDER-BY\": \"排序\",\n         \"SHOW-NEXT\": \"显示下一个\",\n         \"SHOW-PREVIOUS\": \"显示以前\",\n         \"NO-MATCHING-USERS\": \"没有找到匹配的用户\",\n         \"MATCHING-USERS\": \"发现 {{total | number}} 匹配到的用户, 显示 {{start + 1}} 到 {{start + size}}\",\n         \"ID\": \"ID\",\n         \"EMAIL\": \"邮箱\",\n         \"NAME\": \"名称\",\n         \"CREATED\": \"创建\",\n         \"TYPE\": \"类型\",\n         \"EXTERNAL-ID\": \"外部标识\",\n         \"LAST-SYNC-TIME\": \"最新更新\",\n         \"FILTERS\": {\n             \"STATUS-ANY\": \"任何状态\",\n             \"STATUS-ACTIVE\": \"激活\",\n             \"STATUS-INACTIVE\": \"不活动\",\n             \"STATUS-PENDING\": \"Pending\",\n             \"STATUS-DELETED\": \"删除\",\n             \"TYPE-ANY\": \"任何类型\",\n             \"SORT-DATE-NEWEST\": \"最新创建日期\",\n             \"SORT-DATE-OLDEST\": \"最早创建日期\",\n             \"SORT-EMAIL-A\": \"邮箱, A-Z升序\",\n             \"SORT-EMAIL-Z\": \"邮箱, Z-A降序\",\n             \"SORT-ID-A\": \"用户id, A-Z升序\",\n             \"SORT-ID-Z\": \"用户id, Z-A降序\"\n         },\n         \"POPUP\": {\n             \"CREATE-TITLE\": \"创建用户\",\n             \"EDIT-TITLE\": \"编辑用户详细信息\",\n             \"CREATE-ID\": \"用户id\",\n             \"CREATE-EMAIL\": \"邮箱\",\n             \"CREATE-INVALID-EMAIL\": \"无效\",\n             \"CREATE-PASSWORD\": \"密码\",\n             \"CREATE-FIRSTNAME\": \"名字\",\n             \"CREATE-LASTNAME\": \"姓氏\",\n             \"CREATE-TENANT\": \"租户\",\n             \"CREATE-COMPANY\": \"公司\",\n             \"CREATE-STATUS\": \"状态\",\n             \"CREATE-TYPE\": \"类别\",\n             \"BULK-UPDATE-TITLE\": \"批量更新用户\",\n             \"BULK-UPDATE-NEW-STATUS\": \"新状态:\",\n             \"BULK-UPDATE-NEW-TYPE\": \"新账户类型:\",\n             \"BULK-UPDATE-EMAIL-NOTIFICATIONS\": \"状态更改时发送电子邮件通知\",\n             \"BULK-UPDATE-STATUS-USERS\": \"您将要更新这些状态 {{length}} user(s):\",\n             \"BULK-UPDATE-TYPE-USERS\": \"您将要更新这些帐户类型  {{length}} user(s):\",\n             \"BULK-UPDATE-CANCEL\": \"取消并且关闭\",\n             \"BULK-UPDATE-CONFIRM\": \"更新用户\",\n             \"BULK-UPDATE-PASSWORD-TITLE\": \"修改密码\",\n             \"BULK-UPDATE-PASSWORD\": \"密码\",\n             \"BULK-UPDATE-PASSWORD-REPEAT\": \"重复密码\",\n             \"BULK-UPDATE-PASSWORD-CONFIRM\": \"修改\"\n         }\n      },\n      \"FUNCTIONAL-GROUP-MGMT\": {\n        \"CREATE\": \"创建组\",\n        \"NO-GROUPS\": \"没有发现任何组\",\n        \"NO-SELECTION\": \"从左边的列表中选择一个组\",\n        \"SYNC-DETAILS\": \"同步详情\",\n        \"EXTERNAL-ID\": \"外部标识:\",\n        \"LAST-SYNC-TIME\": \"最后更新:\",\n        \"MEMBERS\": \"组成员\",\n        \"SUBGROUPS\": \"子组\",\n        \"NO-MEMBERS\": \"没有发现用户\",\n        \"ADD-USER\": \"+ 添加用户\",\n        \"ADD-SUBGROUP\": \"+ 添加子组\",\n        \"NO-SUBGROUPS\": \"没有发现子组\",\n        \"USER-ADDED\": \"用户已被添加到组中\",\n        \"INACTIVE\": \"已停止\",\n        \"INACTIVE-DESCRIPTION\": \"此组已被停用.用户仍然可以完成当前分配给该组的任务, 但发起新进程不能再使用这个组了\",\n        \"ADD-POPOVER-TITLE\": \"选择用户\",\n            \"POPUP\": {\n                \"CREATE-TITLE\": \"创建组\",\n                \"CREATE-ID\": \"组id\",\n                \"CREATE-NAME\": \"名称\",\n                \"DELETE-TITLE\": \"删除组\",\n                \"DELETE-DESCRIPTION\": \"确实要删除这个组吗?\",\n                \"DELETE-CONFIRM\": \"确认\",\n                \"DEACTIVATE-TITLE\": \"停用组\",\n                \"DEACTIVATE-DESCRIPTION\": \"是否确实要删除此组？这将删除所有子组.请注意, 组将首先被停用, 这样可以正确完成进程任务.再次单击 \\\"删除\\\" 按钮将完全将该组.\",\n                \"DELETE-MEMBER-TITLE\": \"删除组中的成员\",\n                \"DELETE-MEMBER-DESCRIPTION\": \"确实要从组中删除此用户吗?\",\n                \"ADD-MEMBER-TITLE\": \"添加用户\",\n                \"ADD-MEMBER-NO-USERS\": \"没有找到用户\",\n                \"ADD-MEMBER-CONFIRM\": \"添加 ({{selectedUsers.length}})\",\n                \"ACTIVATE-TITLE\": \"激活组\",\n                \"ACTIVATE-DESCRIPTION\": \"是否再次激活此组？这意味着该组将再次获得任务分配的资格.请注意, 默认情况下不激活组的子分组.\",\n                \"ACTIVATE-CONFIRM\": \"激活\",\n                \"EDIT-TITLE\": \"编辑组\"\n            }\n        },\n      \"PRIVILEGE-MGMT\": {\n          \"access-idm\": \"访问idm应用\",\n          \"access-admin\": \"访问admin应用\",\n          \"access-modeler\": \"访问modeler应用\",\n\t\t  \"access-task\": \"访问workflow应用\",\n\t\t  \"access-rest-api\": \"访问REST API\",\n          \"NO-SELECTION\": \"没有选择授权应用\",\n          \"USERS\": \"用户\",\n          \"GROUPS\": \"组\",\n          \"NO-USERS\": \"还没有添加任何用户。单击此处添加用户\",\n          \"NO-GROUPS\": \"还没有添加任何组。单击此处添加组\",\n          \"ADD-USER\": \"添加一个用户\",\n          \"ADD-GROUP\": \"添加一个组\",\n          \"POPOVER-SELECT-USER-TITLE\": \"选择用户\",\n          \"POPOVER-SELECT-GROUP-TITLE\": \"选择组\",\n          \"GROUP-ID\": \"组id\",\n          \"GROUP-NAME\": \"组名称\"\n      },\n      \"PROFILE-MGMT\": {\n         \"CREATED\": \"自注册以来\",\n         \"CHANGE-PASSWORD\": \"修改密码\",\n         \"DETAILS\": \"详细信息\",\n         \"DETAILS-DESCRIPTION\": \"点击下面的任何一个字段来更改它们\",\n         \"FIRST-NAME\": \"名称\",\n         \"NOTHING-SET\": \"没有设置任何东西\",\n         \"LAST-NAME\": \"姓氏\",\n         \"EMAIL\": \"邮箱\",\n         \"COMPANY\": \"公司\",\n         \"GROUPS\": \"您的组\",\n         \"POPUP\": {\n            \"UPLOAD-PICTURE-TITLE\": \"修改图片\",\n            \"UPLOAD-PICTURE-DESCRIPTION\": \"请从您的计算机中选择一个图像，或将其放在下面的区域中\",\n            \"UPLOAD-PICTURE-CANCEL-UPLOAD\": \"取消上传\",\n            \"UPLOAD-PICTURE-DROPZONE\": \"在这里删除图像文件\",\n            \"UPLOAD-PICTURE-NO-DROP\": \"您的浏览器不支持删除\",\n            \"UPLOAD-PICTURE-ERROR\": \"错误\",\n            \"CHANGE-PASSWORD-TITLE\": \"修改密码\",\n            \"CHANGE-PASSWORD-ORIGINAL\": \"原有密码\",\n            \"CHANGE-PASSWORD-NEW-PASSWORD\": \"新密码\",\n            \"CHANGE-PASSWORD-NEW-PASSWORD2\": \"重复新密码\",\n            \"CHANGE-PASSWORD-CONFIRM\": \"确认\",\n            \"CHANGE-PASSWORD-NOT-MATCHING\": \"密码不匹配\",\n            \"CHANGE-PASSWORD-INVALID\": \"无效的密码\"\n         }\n      },\n      \"USERS\": {\n        \"TITLE\": \"用户管理员\",\n        \"ACTION\": {\n          \"CREATE\": \"创建用户\"\n        }\n      }\n    },\n    \"INVOLVE-PEOPLE\": {\n        \"ACTION-SELECT\": \"选择\",\n        \"SEARCH-PLACEHOLDER\": \"根据名称搜索\",\n        \"NO-MATCHING-RESULTS\": \"使用上面的搜索框查找用户\"\n    }\n}\n"
  },
  {
    "path": "flowable-ui-web/idm/index.html",
    "content": "<!doctype html>\n<!--[if lt IE 7]>      <html class=\"no-js lt-ie9 lt-ie8 lt-ie7\"> <![endif]-->\n<!--[if IE 7]>         <html class=\"no-js lt-ie9 lt-ie8\"> <![endif]-->\n<!--[if IE 8]>         <html class=\"no-js lt-ie9\"> <![endif]-->\n<!--[if gt IE 8]><!--> <html class=\"no-js\"> <!--<![endif]-->\n<head>\n    <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=\"theme-color\" content=\"#ffffff\">\n\n    <title>Flowable IDM</title>\n\n    <link rel=\"apple-touch-icon\" sizes=\"180x180\" href=\"images/apple-touch-icon.png?v=Om5N75Y123\">\n    <link rel=\"icon\" type=\"image/png\" href=\"images/favicon-32x32.png?v=Om5N75Y123\" sizes=\"32x32\">\n    <link rel=\"icon\" type=\"image/png\" href=\"images/favicon-16x16.png?v=Om5N75Y123\" sizes=\"16x16\">\n    <link rel=\"manifest\" href=\"manifest.json\">\n    <link rel=\"mask-icon\" href=\"images/safari-pinned-tab.svg?v=Om5N75Y123\" color=\"#506d75\">\n    <link rel=\"shortcut icon\" href=\"favicon.ico?v=Om5N75Y123\">\n\n    <!-- build:css styles/common/3thparty.css -->\n    <link href=\"styles/common/bootstrap.min.css\" rel=\"stylesheet\">\n    <link href=\"libs/nvd3_1.1.15-beta/nvd3.min.css\" rel=\"stylesheet\">\n    <link href=\"libs/bootstrap-daterangepicker_1.3.7/daterangepicker-bs3.css\" rel=\"stylesheet\">\n    <!-- endbuild -->\n\n    <!-- build:css styles/style.css -->\n    <link href=\"styles/style-idm.css\" rel=\"stylesheet\">\n    <!-- endbuild -->\n\n    <!-- build:css styles/common/style.css -->\n    <link href=\"styles/common/style.css\" rel=\"stylesheet\">\n    <!-- endbuild -->\n\n</head>\n<body ng-app=\"flowableApp\" ng-cloak>\n\n    <div ng-if=\"!onLogin\">\n\n        <div class=\"navbar navbar-fixed-top navbar-inverse\" role=\"navigation\" id=\"main-nav\" ng-show=\"authenticated\">\n\t        <div class=\"fixed-container\">\n\t            <div class=\"navbar-header\">\n\t                <a ng-click=\"backToLanding()\" class=\"landing-logo\" ng-if=\"account != null && account != undefined\" title=\"{{'IDM.GENERAL.MAIN-TITLE' | translate}}\">\n\t                    <img ng-src=\"{{appResourceRoot}}images/flowable-logo.png\" ng-srcset=\"{{appResourceRoot}}images/flowable-logo.png 1x, {{appResourceRoot}}images/flowable-logo@2x.png 2x\">\n\t                </a>\n\t                <ul class=\"nav navbar-nav\">\n\t                    <li ng-repeat=\"item in mainNavigation\"\n\t                        id=\"{{item.id}}\"\n\t                        ng-show=\"(authenticated && !item.unauthenticated) || (item.unauthenticated && !authenticated)\"\n\t                        ng-class=\"{'active': item.id == mainPage.id}\">\n\t                        <a ng-click=\"setMainPage(item)\">{{item.title | translate}}</a>\n\t                    </li>\n\t                </ul>\n\t            </div>\n\t            <div class=\"pull-right\">\n\t                <div class=\"dropdown btn-group btn-group-sm\">\n\t                    <button type=\"button\" class=\"btn btn-default dropdown-toggle\" data-toggle=\"dropdown\">{{account.firstName}} {{account.lastName}}\n\t                        <span class=\"glyphicon glyphicon-chevron-down\" style=\"font-size: 10px\" aria-hidden=\"true\"></span>\n\t                    </button>\n\t                    <ul class=\"dropdown-menu pull-right\">\n\t                        <li><a ng-click=\"logout()\" translate=\"IDM.GENERAL.ACTION.LOGOUT\"></a></li>\n\t                    </ul>\n\t                </div>\n\t            </div>\n\t        </div>\n\t    </div>\n\t\n\t\n\t    <div class=\"wrapper clearfix\" ng-view=\"\" ng-cloak ng-style=\"{height: window.height + 'px'}\">\n\t    </div>\n\n    </div>\n\n    <div ng-if=\"onLogin\">\n        <div class=\"alert-wrapper\" ng-cloak>\n            <div class=\"alert {{alerts.current.type}}\" ng-show=\"alerts.current\" ng-click=\"dismissAlert()\">\n                <span>{{alerts.current.message}}</span>\n                <span class=\"badge\" ng-show=\"alerts.queue.length\">{{alerts.queue.length + 1}}</span>\n            </div>\n        </div>\n        <div ng-view=\"\" ng-cloak ng-style=\"{height: window.height + 'px'}\"></div>\n    </div>\n\n    <!--[if lt IE 9]>\n    <div class=\"unsupported-browser\">\n        <p class=\"alert error\">You are using an unsupported browser. Please upgrade your browser in order to use the editor.</p>\n    </div>\n    <![endif]-->\n\n    <!--[if lt IE 9]>\n    <script src=\"libs/es5-shim-15.3.4.5/es5-shim.js\"></script>\n    <script src=\"libs/json3_3.2.6/lib/json3.min.js\"></script>\n    <![endif]-->\n\n    <!-- 3rd party libs -->\n    <script src=\"libs/jquery_1.11.0/jquery.min.js\"></script>\n    <script src=\"libs/jquery-ui-1.10.3.custom.min.js\"></script>\n\n    <script src=\"libs/angular_1.3.13/angular.js\"></script>\n    <script src=\"libs/angular-animate_1.3.13/angular-animate.min.js\"></script>\n    <script src=\"libs/bootstrap_3.1.1/js/bootstrap.min.js\"></script>\n    <script src=\"libs/angular-resource_1.3.13/angular-resource.min.js\"></script>\n    <script src=\"libs/angular-cookies_1.3.13/angular-cookies.min.js\"></script>\n    <script src=\"libs/angular-sanitize_1.3.13/angular-sanitize.min.js\"></script>\n    <script src=\"libs/angular-route_1.3.13/angular-route.min.js\"></script>\n    <script src=\"libs/angular-translate_2.15.1/angular-translate.min.js\"></script>\n    <script src=\"libs/angular-translate-storage-cookie/angular-translate-storage-cookie.js\"></script>\n    <script src=\"libs/angular-translate-loader-static-files/angular-translate-loader-static-files.js\"></script>\n    <script src=\"libs/angular-strap_2.1.6/angular-strap.min.js\"></script>\n    <script src=\"libs/angular-strap_2.1.6/angular-strap.tpl.min.js\"></script>\n    <script src=\"libs/ng-file-upload/ng-file-upload-shim.min.js\"></script>\n    <script src=\"libs/ng-file-upload/ng-file-upload.min.js\"></script>\n    <script src=\"libs/ui-grid_3.0.0/ui-grid.min.js\" type=\"text/javascript\"></script>\n    <script src=\"libs/autofill-events_1.0.0/autofill-event.js\"></script>\n    <script src=\"libs/momentjs_2.18.1/momentjs.min.js\"></script>\n\n    <!-- Configuration -->\n    <script src=\"scripts/app-cfg.js?v=2\"></script>\n\n    <!-- build:js scripts/scripts.js -->\n    <script src=\"scripts/idm-app.js\"></script>\n    <script src=\"scripts/idm-service.js\"></script>\n    <script src=\"scripts/idm-user-mgmt-controller.js\"></script>\n    <script src=\"scripts/idm-group-mgmt-controller.js\"></script>\n    <script src=\"scripts/idm-profile-mgmt-controller.js\"></script>\n    <script src=\"scripts/idm-privilege-mgmt-controller.js\"></script>\n    <script src=\"scripts/common/services/authentication-service.js\"></script>\n    <script src=\"scripts/common/directives.js\"></script>\n    <script src=\"scripts/common/providers-config.js\"></script>\n    <script src=\"scripts/common/services/user-service.js\"></script>\n    <script src=\"scripts/common/services/group-service.js\"></script>\n    <script src=\"scripts/controllers.js\"></script>\n\n    <!-- endbuild -->\n\n    <!-- Integration extensions -->\n    <script src=\"scripts/resource-loader.js?v=2\" app=\"landing\"></script>\n\n</body>\n</html>\n"
  },
  {
    "path": "flowable-ui-web/idm/libs/angular-animate_1.3.13/angular-animate.js",
    "content": "/**\n * @license AngularJS v1.3.13\n * (c) 2010-2014 Google, Inc. http://angularjs.org\n * License: MIT\n */\n(function(window, angular, undefined) {'use strict';\n\n/* jshint maxlen: false */\n\n/**\n * @ngdoc module\n * @name ngAnimate\n * @description\n *\n * The `ngAnimate` module provides support for JavaScript, CSS3 transition and CSS3 keyframe animation hooks within existing core and custom directives.\n *\n * <div doc-module-components=\"ngAnimate\"></div>\n *\n * # Usage\n *\n * To see animations in action, all that is required is to define the appropriate CSS classes\n * or to register a JavaScript animation via the `myModule.animation()` function. The directives that support animation automatically are:\n * `ngRepeat`, `ngInclude`, `ngIf`, `ngSwitch`, `ngShow`, `ngHide`, `ngView` and `ngClass`. Custom directives can take advantage of animation\n * by using the `$animate` service.\n *\n * Below is a more detailed breakdown of the supported animation events provided by pre-existing ng directives:\n *\n * | Directive                                                                                                | Supported Animations                                                     |\n * |----------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------|\n * | {@link ng.directive:ngRepeat#animations ngRepeat}                                                        | enter, leave and move                                                    |\n * | {@link ngRoute.directive:ngView#animations ngView}                                                       | enter and leave                                                          |\n * | {@link ng.directive:ngInclude#animations ngInclude}                                                      | enter and leave                                                          |\n * | {@link ng.directive:ngSwitch#animations ngSwitch}                                                        | enter and leave                                                          |\n * | {@link ng.directive:ngIf#animations ngIf}                                                                | enter and leave                                                          |\n * | {@link ng.directive:ngClass#animations ngClass}                                                          | add and remove (the CSS class(es) present)                               |\n * | {@link ng.directive:ngShow#animations ngShow} & {@link ng.directive:ngHide#animations ngHide}            | add and remove (the ng-hide class value)                                 |\n * | {@link ng.directive:form#animation-hooks form} & {@link ng.directive:ngModel#animation-hooks ngModel}    | add and remove (dirty, pristine, valid, invalid & all other validations) |\n * | {@link module:ngMessages#animations ngMessages}                                                          | add and remove (ng-active & ng-inactive)                                 |\n * | {@link module:ngMessages#animations ngMessage}                                                           | enter and leave                                                          |\n *\n * You can find out more information about animations upon visiting each directive page.\n *\n * Below is an example of how to apply animations to a directive that supports animation hooks:\n *\n * ```html\n * <style type=\"text/css\">\n * .slide.ng-enter, .slide.ng-leave {\n *   -webkit-transition:0.5s linear all;\n *   transition:0.5s linear all;\n * }\n *\n * .slide.ng-enter { }        /&#42; starting animations for enter &#42;/\n * .slide.ng-enter.ng-enter-active { } /&#42; terminal animations for enter &#42;/\n * .slide.ng-leave { }        /&#42; starting animations for leave &#42;/\n * .slide.ng-leave.ng-leave-active { } /&#42; terminal animations for leave &#42;/\n * </style>\n *\n * <!--\n * the animate service will automatically add .ng-enter and .ng-leave to the element\n * to trigger the CSS transition/animations\n * -->\n * <ANY class=\"slide\" ng-include=\"...\"></ANY>\n * ```\n *\n * Keep in mind that, by default, if an animation is running, any child elements cannot be animated\n * until the parent element's animation has completed. This blocking feature can be overridden by\n * placing the `ng-animate-children` attribute on a parent container tag.\n *\n * ```html\n * <div class=\"slide-animation\" ng-if=\"on\" ng-animate-children>\n *   <div class=\"fade-animation\" ng-if=\"on\">\n *     <div class=\"explode-animation\" ng-if=\"on\">\n *        ...\n *     </div>\n *   </div>\n * </div>\n * ```\n *\n * When the `on` expression value changes and an animation is triggered then each of the elements within\n * will all animate without the block being applied to child elements.\n *\n * ## Are animations run when the application starts?\n * No they are not. When an application is bootstrapped Angular will disable animations from running to avoid\n * a frenzy of animations from being triggered as soon as the browser has rendered the screen. For this to work,\n * Angular will wait for two digest cycles until enabling animations. From there on, any animation-triggering\n * layout changes in the application will trigger animations as normal.\n *\n * In addition, upon bootstrap, if the routing system or any directives or load remote data (via $http) then Angular\n * will automatically extend the wait time to enable animations once **all** of the outbound HTTP requests\n * are complete.\n *\n * ## CSS-defined Animations\n * The animate service will automatically apply two CSS classes to the animated element and these two CSS classes\n * are designed to contain the start and end CSS styling. Both CSS transitions and keyframe animations are supported\n * and can be used to play along with this naming structure.\n *\n * The following code below demonstrates how to perform animations using **CSS transitions** with Angular:\n *\n * ```html\n * <style type=\"text/css\">\n * /&#42;\n *  The animate class is apart of the element and the ng-enter class\n *  is attached to the element once the enter animation event is triggered\n * &#42;/\n * .reveal-animation.ng-enter {\n *  -webkit-transition: 1s linear all; /&#42; Safari/Chrome &#42;/\n *  transition: 1s linear all; /&#42; All other modern browsers and IE10+ &#42;/\n *\n *  /&#42; The animation preparation code &#42;/\n *  opacity: 0;\n * }\n *\n * /&#42;\n *  Keep in mind that you want to combine both CSS\n *  classes together to avoid any CSS-specificity\n *  conflicts\n * &#42;/\n * .reveal-animation.ng-enter.ng-enter-active {\n *  /&#42; The animation code itself &#42;/\n *  opacity: 1;\n * }\n * </style>\n *\n * <div class=\"view-container\">\n *   <div ng-view class=\"reveal-animation\"></div>\n * </div>\n * ```\n *\n * The following code below demonstrates how to perform animations using **CSS animations** with Angular:\n *\n * ```html\n * <style type=\"text/css\">\n * .reveal-animation.ng-enter {\n *   -webkit-animation: enter_sequence 1s linear; /&#42; Safari/Chrome &#42;/\n *   animation: enter_sequence 1s linear; /&#42; IE10+ and Future Browsers &#42;/\n * }\n * @-webkit-keyframes enter_sequence {\n *   from { opacity:0; }\n *   to { opacity:1; }\n * }\n * @keyframes enter_sequence {\n *   from { opacity:0; }\n *   to { opacity:1; }\n * }\n * </style>\n *\n * <div class=\"view-container\">\n *   <div ng-view class=\"reveal-animation\"></div>\n * </div>\n * ```\n *\n * Both CSS3 animations and transitions can be used together and the animate service will figure out the correct duration and delay timing.\n *\n * Upon DOM mutation, the event class is added first (something like `ng-enter`), then the browser prepares itself to add\n * the active class (in this case `ng-enter-active`) which then triggers the animation. The animation module will automatically\n * detect the CSS code to determine when the animation ends. Once the animation is over then both CSS classes will be\n * removed from the DOM. If a browser does not support CSS transitions or CSS animations then the animation will start and end\n * immediately resulting in a DOM element that is at its final state. This final state is when the DOM element\n * has no CSS transition/animation classes applied to it.\n *\n * ### Structural transition animations\n *\n * Structural transitions (such as enter, leave and move) will always apply a `0s none` transition\n * value to force the browser into rendering the styles defined in the setup (`.ng-enter`, `.ng-leave`\n * or `.ng-move`) class. This means that any active transition animations operating on the element\n * will be cut off to make way for the enter, leave or move animation.\n *\n * ### Class-based transition animations\n *\n * Class-based transitions refer to transition animations that are triggered when a CSS class is\n * added to or removed from the element (via `$animate.addClass`, `$animate.removeClass`,\n * `$animate.setClass`, or by directives such as `ngClass`, `ngModel` and `form`).\n * They are different when compared to structural animations since they **do not cancel existing\n * animations** nor do they **block successive transitions** from rendering on the same element.\n * This distinction allows for **multiple class-based transitions** to be performed on the same element.\n *\n * In addition to ngAnimate supporting the default (natural) functionality of class-based transition\n * animations, ngAnimate also decorates the element with starting and ending CSS classes to aid the\n * developer in further styling the element throughout the transition animation. Earlier versions\n * of ngAnimate may have caused natural CSS transitions to break and not render properly due to\n * $animate temporarily blocking transitions using `0s none` in order to allow the setup CSS class\n * (the `-add` or `-remove` class) to be applied without triggering an animation. However, as of\n * **version 1.3**, this workaround has been removed with ngAnimate and all non-ngAnimate CSS\n * class transitions are compatible with ngAnimate.\n *\n * There is, however, one special case when dealing with class-based transitions in ngAnimate.\n * When rendering class-based transitions that make use of the setup and active CSS classes\n * (e.g. `.fade-add` and `.fade-add-active` for when `.fade` is added) be sure to define\n * the transition value **on the active CSS class** and not the setup class.\n *\n * ```css\n * .fade-add {\n *   /&#42; remember to place a 0s transition here\n *      to ensure that the styles are applied instantly\n *      even if the element already has a transition style &#42;/\n *   transition:0s linear all;\n *\n *   /&#42; starting CSS styles &#42;/\n *   opacity:1;\n * }\n * .fade-add.fade-add-active {\n *   /&#42; this will be the length of the animation &#42;/\n *   transition:1s linear all;\n *   opacity:0;\n * }\n * ```\n *\n * The setup CSS class (in this case `.fade-add`) also has a transition style property, however, it\n * has a duration of zero. This may not be required, however, incase the browser is unable to render\n * the styling present in this CSS class instantly then it could be that the browser is attempting\n * to perform an unnecessary transition.\n *\n * This workaround, however, does not apply to  standard class-based transitions that are rendered\n * when a CSS class containing a transition is applied to an element:\n *\n * ```css\n * /&#42; this works as expected &#42;/\n * .fade {\n *   transition:1s linear all;\n *   opacity:0;\n * }\n * ```\n *\n * Please keep this in mind when coding the CSS markup that will be used within class-based transitions.\n * Also, try not to mix the two class-based animation flavors together since the CSS code may become\n * overly complex.\n *\n *\n * ### Preventing Collisions With Third Party Libraries\n *\n * Some third-party frameworks place animation duration defaults across many element or className\n * selectors in order to make their code small and reuseable. This can lead to issues with ngAnimate, which\n * is expecting actual animations on these elements and has to wait for their completion.\n *\n * You can prevent this unwanted behavior by using a prefix on all your animation classes:\n *\n * ```css\n * /&#42; prefixed with animate- &#42;/\n * .animate-fade-add.animate-fade-add-active {\n *   transition:1s linear all;\n *   opacity:0;\n * }\n * ```\n *\n * You then configure `$animate` to enforce this prefix:\n *\n * ```js\n * $animateProvider.classNameFilter(/animate-/);\n * ```\n * </div>\n *\n * ### CSS Staggering Animations\n * A Staggering animation is a collection of animations that are issued with a slight delay in between each successive operation resulting in a\n * curtain-like effect. The ngAnimate module (versions >=1.2) supports staggering animations and the stagger effect can be\n * performed by creating a **ng-EVENT-stagger** CSS class and attaching that class to the base CSS class used for\n * the animation. The style property expected within the stagger class can either be a **transition-delay** or an\n * **animation-delay** property (or both if your animation contains both transitions and keyframe animations).\n *\n * ```css\n * .my-animation.ng-enter {\n *   /&#42; standard transition code &#42;/\n *   -webkit-transition: 1s linear all;\n *   transition: 1s linear all;\n *   opacity:0;\n * }\n * .my-animation.ng-enter-stagger {\n *   /&#42; this will have a 100ms delay between each successive leave animation &#42;/\n *   -webkit-transition-delay: 0.1s;\n *   transition-delay: 0.1s;\n *\n *   /&#42; in case the stagger doesn't work then these two values\n *    must be set to 0 to avoid an accidental CSS inheritance &#42;/\n *   -webkit-transition-duration: 0s;\n *   transition-duration: 0s;\n * }\n * .my-animation.ng-enter.ng-enter-active {\n *   /&#42; standard transition styles &#42;/\n *   opacity:1;\n * }\n * ```\n *\n * Staggering animations work by default in ngRepeat (so long as the CSS class is defined). Outside of ngRepeat, to use staggering animations\n * on your own, they can be triggered by firing multiple calls to the same event on $animate. However, the restrictions surrounding this\n * are that each of the elements must have the same CSS className value as well as the same parent element. A stagger operation\n * will also be reset if more than 10ms has passed after the last animation has been fired.\n *\n * The following code will issue the **ng-leave-stagger** event on the element provided:\n *\n * ```js\n * var kids = parent.children();\n *\n * $animate.leave(kids[0]); //stagger index=0\n * $animate.leave(kids[1]); //stagger index=1\n * $animate.leave(kids[2]); //stagger index=2\n * $animate.leave(kids[3]); //stagger index=3\n * $animate.leave(kids[4]); //stagger index=4\n *\n * $timeout(function() {\n *   //stagger has reset itself\n *   $animate.leave(kids[5]); //stagger index=0\n *   $animate.leave(kids[6]); //stagger index=1\n * }, 100, false);\n * ```\n *\n * Stagger animations are currently only supported within CSS-defined animations.\n *\n * ## JavaScript-defined Animations\n * In the event that you do not want to use CSS3 transitions or CSS3 animations or if you wish to offer animations on browsers that do not\n * yet support CSS transitions/animations, then you can make use of JavaScript animations defined inside of your AngularJS module.\n *\n * ```js\n * //!annotate=\"YourApp\" Your AngularJS Module|Replace this or ngModule with the module that you used to define your application.\n * var ngModule = angular.module('YourApp', ['ngAnimate']);\n * ngModule.animation('.my-crazy-animation', function() {\n *   return {\n *     enter: function(element, done) {\n *       //run the animation here and call done when the animation is complete\n *       return function(cancelled) {\n *         //this (optional) function will be called when the animation\n *         //completes or when the animation is cancelled (the cancelled\n *         //flag will be set to true if cancelled).\n *       };\n *     },\n *     leave: function(element, done) { },\n *     move: function(element, done) { },\n *\n *     //animation that can be triggered before the class is added\n *     beforeAddClass: function(element, className, done) { },\n *\n *     //animation that can be triggered after the class is added\n *     addClass: function(element, className, done) { },\n *\n *     //animation that can be triggered before the class is removed\n *     beforeRemoveClass: function(element, className, done) { },\n *\n *     //animation that can be triggered after the class is removed\n *     removeClass: function(element, className, done) { }\n *   };\n * });\n * ```\n *\n * JavaScript-defined animations are created with a CSS-like class selector and a collection of events which are set to run\n * a javascript callback function. When an animation is triggered, $animate will look for a matching animation which fits\n * the element's CSS class attribute value and then run the matching animation event function (if found).\n * In other words, if the CSS classes present on the animated element match any of the JavaScript animations then the callback function will\n * be executed. It should be also noted that only simple, single class selectors are allowed (compound class selectors are not supported).\n *\n * Within a JavaScript animation, an object containing various event callback animation functions is expected to be returned.\n * As explained above, these callbacks are triggered based on the animation event. Therefore if an enter animation is run,\n * and the JavaScript animation is found, then the enter callback will handle that animation (in addition to the CSS keyframe animation\n * or transition code that is defined via a stylesheet).\n *\n *\n * ### Applying Directive-specific Styles to an Animation\n * In some cases a directive or service may want to provide `$animate` with extra details that the animation will\n * include into its animation. Let's say for example we wanted to render an animation that animates an element\n * towards the mouse coordinates as to where the user clicked last. By collecting the X/Y coordinates of the click\n * (via the event parameter) we can set the `top` and `left` styles into an object and pass that into our function\n * call to `$animate.addClass`.\n *\n * ```js\n * canvas.on('click', function(e) {\n *   $animate.addClass(element, 'on', {\n *     to: {\n *       left : e.client.x + 'px',\n *       top : e.client.y + 'px'\n *     }\n *   }):\n * });\n * ```\n *\n * Now when the animation runs, and a transition or keyframe animation is picked up, then the animation itself will\n * also include and transition the styling of the `left` and `top` properties into its running animation. If we want\n * to provide some starting animation values then we can do so by placing the starting animations styles into an object\n * called `from` in the same object as the `to` animations.\n *\n * ```js\n * canvas.on('click', function(e) {\n *   $animate.addClass(element, 'on', {\n *     from: {\n *        position: 'absolute',\n *        left: '0px',\n *        top: '0px'\n *     },\n *     to: {\n *       left : e.client.x + 'px',\n *       top : e.client.y + 'px'\n *     }\n *   }):\n * });\n * ```\n *\n * Once the animation is complete or cancelled then the union of both the before and after styles are applied to the\n * element. If `ngAnimate` is not present then the styles will be applied immediately.\n *\n */\n\nangular.module('ngAnimate', ['ng'])\n\n  /**\n   * @ngdoc provider\n   * @name $animateProvider\n   * @description\n   *\n   * The `$animateProvider` allows developers to register JavaScript animation event handlers directly inside of a module.\n   * When an animation is triggered, the $animate service will query the $animate service to find any animations that match\n   * the provided name value.\n   *\n   * Requires the {@link ngAnimate `ngAnimate`} module to be installed.\n   *\n   * Please visit the {@link ngAnimate `ngAnimate`} module overview page learn more about how to use animations in your application.\n   *\n   */\n  .directive('ngAnimateChildren', function() {\n    var NG_ANIMATE_CHILDREN = '$$ngAnimateChildren';\n    return function(scope, element, attrs) {\n      var val = attrs.ngAnimateChildren;\n      if (angular.isString(val) && val.length === 0) { //empty attribute\n        element.data(NG_ANIMATE_CHILDREN, true);\n      } else {\n        scope.$watch(val, function(value) {\n          element.data(NG_ANIMATE_CHILDREN, !!value);\n        });\n      }\n    };\n  })\n\n  //this private service is only used within CSS-enabled animations\n  //IE8 + IE9 do not support rAF natively, but that is fine since they\n  //also don't support transitions and keyframes which means that the code\n  //below will never be used by the two browsers.\n  .factory('$$animateReflow', ['$$rAF', '$document', function($$rAF, $document) {\n    var bod = $document[0].body;\n    return function(fn) {\n      //the returned function acts as the cancellation function\n      return $$rAF(function() {\n        //the line below will force the browser to perform a repaint\n        //so that all the animated elements within the animation frame\n        //will be properly updated and drawn on screen. This is\n        //required to perform multi-class CSS based animations with\n        //Firefox. DO NOT REMOVE THIS LINE.\n        var a = bod.offsetWidth + 1;\n        fn();\n      });\n    };\n  }])\n\n  .config(['$provide', '$animateProvider', function($provide, $animateProvider) {\n    var noop = angular.noop;\n    var forEach = angular.forEach;\n    var selectors = $animateProvider.$$selectors;\n    var isArray = angular.isArray;\n    var isString = angular.isString;\n    var isObject = angular.isObject;\n\n    var ELEMENT_NODE = 1;\n    var NG_ANIMATE_STATE = '$$ngAnimateState';\n    var NG_ANIMATE_CHILDREN = '$$ngAnimateChildren';\n    var NG_ANIMATE_CLASS_NAME = 'ng-animate';\n    var rootAnimateState = {running: true};\n\n    function extractElementNode(element) {\n      for (var i = 0; i < element.length; i++) {\n        var elm = element[i];\n        if (elm.nodeType == ELEMENT_NODE) {\n          return elm;\n        }\n      }\n    }\n\n    function prepareElement(element) {\n      return element && angular.element(element);\n    }\n\n    function stripCommentsFromElement(element) {\n      return angular.element(extractElementNode(element));\n    }\n\n    function isMatchingElement(elm1, elm2) {\n      return extractElementNode(elm1) == extractElementNode(elm2);\n    }\n    var $$jqLite;\n    $provide.decorator('$animate',\n        ['$delegate', '$$q', '$injector', '$sniffer', '$rootElement', '$$asyncCallback', '$rootScope', '$document', '$templateRequest', '$$jqLite',\n function($delegate,   $$q,   $injector,   $sniffer,   $rootElement,   $$asyncCallback,   $rootScope,   $document,   $templateRequest,   $$$jqLite) {\n\n      $$jqLite = $$$jqLite;\n      $rootElement.data(NG_ANIMATE_STATE, rootAnimateState);\n\n      // Wait until all directive and route-related templates are downloaded and\n      // compiled. The $templateRequest.totalPendingRequests variable keeps track of\n      // all of the remote templates being currently downloaded. If there are no\n      // templates currently downloading then the watcher will still fire anyway.\n      var deregisterWatch = $rootScope.$watch(\n        function() { return $templateRequest.totalPendingRequests; },\n        function(val, oldVal) {\n          if (val !== 0) return;\n          deregisterWatch();\n\n          // Now that all templates have been downloaded, $animate will wait until\n          // the post digest queue is empty before enabling animations. By having two\n          // calls to $postDigest calls we can ensure that the flag is enabled at the\n          // very end of the post digest queue. Since all of the animations in $animate\n          // use $postDigest, it's important that the code below executes at the end.\n          // This basically means that the page is fully downloaded and compiled before\n          // any animations are triggered.\n          $rootScope.$$postDigest(function() {\n            $rootScope.$$postDigest(function() {\n              rootAnimateState.running = false;\n            });\n          });\n        }\n      );\n\n      var globalAnimationCounter = 0;\n      var classNameFilter = $animateProvider.classNameFilter();\n      var isAnimatableClassName = !classNameFilter\n              ? function() { return true; }\n              : function(className) {\n                return classNameFilter.test(className);\n              };\n\n      function classBasedAnimationsBlocked(element, setter) {\n        var data = element.data(NG_ANIMATE_STATE) || {};\n        if (setter) {\n          data.running = true;\n          data.structural = true;\n          element.data(NG_ANIMATE_STATE, data);\n        }\n        return data.disabled || (data.running && data.structural);\n      }\n\n      function runAnimationPostDigest(fn) {\n        var cancelFn, defer = $$q.defer();\n        defer.promise.$$cancelFn = function() {\n          cancelFn && cancelFn();\n        };\n        $rootScope.$$postDigest(function() {\n          cancelFn = fn(function() {\n            defer.resolve();\n          });\n        });\n        return defer.promise;\n      }\n\n      function parseAnimateOptions(options) {\n        // some plugin code may still be passing in the callback\n        // function as the last param for the $animate methods so\n        // it's best to only allow string or array values for now\n        if (isObject(options)) {\n          if (options.tempClasses && isString(options.tempClasses)) {\n            options.tempClasses = options.tempClasses.split(/\\s+/);\n          }\n          return options;\n        }\n      }\n\n      function resolveElementClasses(element, cache, runningAnimations) {\n        runningAnimations = runningAnimations || {};\n\n        var lookup = {};\n        forEach(runningAnimations, function(data, selector) {\n          forEach(selector.split(' '), function(s) {\n            lookup[s]=data;\n          });\n        });\n\n        var hasClasses = Object.create(null);\n        forEach((element.attr('class') || '').split(/\\s+/), function(className) {\n          hasClasses[className] = true;\n        });\n\n        var toAdd = [], toRemove = [];\n        forEach((cache && cache.classes) || [], function(status, className) {\n          var hasClass = hasClasses[className];\n          var matchingAnimation = lookup[className] || {};\n\n          // When addClass and removeClass is called then $animate will check to\n          // see if addClass and removeClass cancel each other out. When there are\n          // more calls to removeClass than addClass then the count falls below 0\n          // and then the removeClass animation will be allowed. Otherwise if the\n          // count is above 0 then that means an addClass animation will commence.\n          // Once an animation is allowed then the code will also check to see if\n          // there exists any on-going animation that is already adding or remvoing\n          // the matching CSS class.\n          if (status === false) {\n            //does it have the class or will it have the class\n            if (hasClass || matchingAnimation.event == 'addClass') {\n              toRemove.push(className);\n            }\n          } else if (status === true) {\n            //is the class missing or will it be removed?\n            if (!hasClass || matchingAnimation.event == 'removeClass') {\n              toAdd.push(className);\n            }\n          }\n        });\n\n        return (toAdd.length + toRemove.length) > 0 && [toAdd.join(' '), toRemove.join(' ')];\n      }\n\n      function lookup(name) {\n        if (name) {\n          var matches = [],\n              flagMap = {},\n              classes = name.substr(1).split('.');\n\n          //the empty string value is the default animation\n          //operation which performs CSS transition and keyframe\n          //animations sniffing. This is always included for each\n          //element animation procedure if the browser supports\n          //transitions and/or keyframe animations. The default\n          //animation is added to the top of the list to prevent\n          //any previous animations from affecting the element styling\n          //prior to the element being animated.\n          if ($sniffer.transitions || $sniffer.animations) {\n            matches.push($injector.get(selectors['']));\n          }\n\n          for (var i=0; i < classes.length; i++) {\n            var klass = classes[i],\n                selectorFactoryName = selectors[klass];\n            if (selectorFactoryName && !flagMap[klass]) {\n              matches.push($injector.get(selectorFactoryName));\n              flagMap[klass] = true;\n            }\n          }\n          return matches;\n        }\n      }\n\n      function animationRunner(element, animationEvent, className, options) {\n        //transcluded directives may sometimes fire an animation using only comment nodes\n        //best to catch this early on to prevent any animation operations from occurring\n        var node = element[0];\n        if (!node) {\n          return;\n        }\n\n        if (options) {\n          options.to = options.to || {};\n          options.from = options.from || {};\n        }\n\n        var classNameAdd;\n        var classNameRemove;\n        if (isArray(className)) {\n          classNameAdd = className[0];\n          classNameRemove = className[1];\n          if (!classNameAdd) {\n            className = classNameRemove;\n            animationEvent = 'removeClass';\n          } else if (!classNameRemove) {\n            className = classNameAdd;\n            animationEvent = 'addClass';\n          } else {\n            className = classNameAdd + ' ' + classNameRemove;\n          }\n        }\n\n        var isSetClassOperation = animationEvent == 'setClass';\n        var isClassBased = isSetClassOperation\n                           || animationEvent == 'addClass'\n                           || animationEvent == 'removeClass'\n                           || animationEvent == 'animate';\n\n        var currentClassName = element.attr('class');\n        var classes = currentClassName + ' ' + className;\n        if (!isAnimatableClassName(classes)) {\n          return;\n        }\n\n        var beforeComplete = noop,\n            beforeCancel = [],\n            before = [],\n            afterComplete = noop,\n            afterCancel = [],\n            after = [];\n\n        var animationLookup = (' ' + classes).replace(/\\s+/g,'.');\n        forEach(lookup(animationLookup), function(animationFactory) {\n          var created = registerAnimation(animationFactory, animationEvent);\n          if (!created && isSetClassOperation) {\n            registerAnimation(animationFactory, 'addClass');\n            registerAnimation(animationFactory, 'removeClass');\n          }\n        });\n\n        function registerAnimation(animationFactory, event) {\n          var afterFn = animationFactory[event];\n          var beforeFn = animationFactory['before' + event.charAt(0).toUpperCase() + event.substr(1)];\n          if (afterFn || beforeFn) {\n            if (event == 'leave') {\n              beforeFn = afterFn;\n              //when set as null then animation knows to skip this phase\n              afterFn = null;\n            }\n            after.push({\n              event: event, fn: afterFn\n            });\n            before.push({\n              event: event, fn: beforeFn\n            });\n            return true;\n          }\n        }\n\n        function run(fns, cancellations, allCompleteFn) {\n          var animations = [];\n          forEach(fns, function(animation) {\n            animation.fn && animations.push(animation);\n          });\n\n          var count = 0;\n          function afterAnimationComplete(index) {\n            if (cancellations) {\n              (cancellations[index] || noop)();\n              if (++count < animations.length) return;\n              cancellations = null;\n            }\n            allCompleteFn();\n          }\n\n          //The code below adds directly to the array in order to work with\n          //both sync and async animations. Sync animations are when the done()\n          //operation is called right away. DO NOT REFACTOR!\n          forEach(animations, function(animation, index) {\n            var progress = function() {\n              afterAnimationComplete(index);\n            };\n            switch (animation.event) {\n              case 'setClass':\n                cancellations.push(animation.fn(element, classNameAdd, classNameRemove, progress, options));\n                break;\n              case 'animate':\n                cancellations.push(animation.fn(element, className, options.from, options.to, progress));\n                break;\n              case 'addClass':\n                cancellations.push(animation.fn(element, classNameAdd || className,     progress, options));\n                break;\n              case 'removeClass':\n                cancellations.push(animation.fn(element, classNameRemove || className,  progress, options));\n                break;\n              default:\n                cancellations.push(animation.fn(element, progress, options));\n                break;\n            }\n          });\n\n          if (cancellations && cancellations.length === 0) {\n            allCompleteFn();\n          }\n        }\n\n        return {\n          node: node,\n          event: animationEvent,\n          className: className,\n          isClassBased: isClassBased,\n          isSetClassOperation: isSetClassOperation,\n          applyStyles: function() {\n            if (options) {\n              element.css(angular.extend(options.from || {}, options.to || {}));\n            }\n          },\n          before: function(allCompleteFn) {\n            beforeComplete = allCompleteFn;\n            run(before, beforeCancel, function() {\n              beforeComplete = noop;\n              allCompleteFn();\n            });\n          },\n          after: function(allCompleteFn) {\n            afterComplete = allCompleteFn;\n            run(after, afterCancel, function() {\n              afterComplete = noop;\n              allCompleteFn();\n            });\n          },\n          cancel: function() {\n            if (beforeCancel) {\n              forEach(beforeCancel, function(cancelFn) {\n                (cancelFn || noop)(true);\n              });\n              beforeComplete(true);\n            }\n            if (afterCancel) {\n              forEach(afterCancel, function(cancelFn) {\n                (cancelFn || noop)(true);\n              });\n              afterComplete(true);\n            }\n          }\n        };\n      }\n\n      /**\n       * @ngdoc service\n       * @name $animate\n       * @kind object\n       *\n       * @description\n       * The `$animate` service provides animation detection support while performing DOM operations (enter, leave and move) as well as during addClass and removeClass operations.\n       * When any of these operations are run, the $animate service\n       * will examine any JavaScript-defined animations (which are defined by using the $animateProvider provider object)\n       * as well as any CSS-defined animations against the CSS classes present on the element once the DOM operation is run.\n       *\n       * The `$animate` service is used behind the scenes with pre-existing directives and animation with these directives\n       * will work out of the box without any extra configuration.\n       *\n       * Requires the {@link ngAnimate `ngAnimate`} module to be installed.\n       *\n       * Please visit the {@link ngAnimate `ngAnimate`} module overview page learn more about how to use animations in your application.\n       * ## Callback Promises\n       * With AngularJS 1.3, each of the animation methods, on the `$animate` service, return a promise when called. The\n       * promise itself is then resolved once the animation has completed itself, has been cancelled or has been\n       * skipped due to animations being disabled. (Note that even if the animation is cancelled it will still\n       * call the resolve function of the animation.)\n       *\n       * ```js\n       * $animate.enter(element, container).then(function() {\n       *   //...this is called once the animation is complete...\n       * });\n       * ```\n       *\n       * Also note that, due to the nature of the callback promise, if any Angular-specific code (like changing the scope,\n       * location of the page, etc...) is executed within the callback promise then be sure to wrap the code using\n       * `$scope.$apply(...)`;\n       *\n       * ```js\n       * $animate.leave(element).then(function() {\n       *   $scope.$apply(function() {\n       *     $location.path('/new-page');\n       *   });\n       * });\n       * ```\n       *\n       * An animation can also be cancelled by calling the `$animate.cancel(promise)` method with the provided\n       * promise that was returned when the animation was started.\n       *\n       * ```js\n       * var promise = $animate.addClass(element, 'super-long-animation');\n       * promise.then(function() {\n       *   //this will still be called even if cancelled\n       * });\n       *\n       * element.on('click', function() {\n       *   //tooo lazy to wait for the animation to end\n       *   $animate.cancel(promise);\n       * });\n       * ```\n       *\n       * (Keep in mind that the promise cancellation is unique to `$animate` since promises in\n       * general cannot be cancelled.)\n       *\n       */\n      return {\n        /**\n         * @ngdoc method\n         * @name $animate#animate\n         * @kind function\n         *\n         * @description\n         * Performs an inline animation on the element which applies the provided `to` and `from` CSS styles to the element.\n         * If any detected CSS transition, keyframe or JavaScript matches the provided `className` value then the animation\n         * will take on the provided styles. For example, if a transition animation is set for the given className then the\n         * provided `from` and `to` styles will be applied alongside the given transition. If a JavaScript animation is\n         * detected then the provided styles will be given in as function paramters.\n         *\n         * ```js\n         * ngModule.animation('.my-inline-animation', function() {\n         *   return {\n         *     animate : function(element, className, from, to, done) {\n         *       //styles\n         *     }\n         *   }\n         * });\n         * ```\n         *\n         * Below is a breakdown of each step that occurs during the `animate` animation:\n         *\n         * | Animation Step                                                                                                        | What the element class attribute looks like                  |\n         * |-----------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------|\n         * | 1. `$animate.animate(...)` is called                                                                                  | `class=\"my-animation\"`                                       |\n         * | 2. `$animate` waits for the next digest to start the animation                                                        | `class=\"my-animation ng-animate\"`                            |\n         * | 3. `$animate` runs the JavaScript-defined animations detected on the element                                          | `class=\"my-animation ng-animate\"`                            |\n         * | 4. the `className` class value is added to the element                                                                | `class=\"my-animation ng-animate className\"`                  |\n         * | 5. `$animate` scans the element styles to get the CSS transition/animation duration and delay                         | `class=\"my-animation ng-animate className\"`                  |\n         * | 6. `$animate` blocks all CSS transitions on the element to ensure the `.className` class styling is applied right away| `class=\"my-animation ng-animate className\"`                  |\n         * | 7. `$animate` applies the provided collection of `from` CSS styles to the element                                     | `class=\"my-animation ng-animate className\"`                  |\n         * | 8. `$animate` waits for a single animation frame (this performs a reflow)                                             | `class=\"my-animation ng-animate className\"`                  |\n         * | 9. `$animate` removes the CSS transition block placed on the element                                                  | `class=\"my-animation ng-animate className\"`                  |\n         * | 10. the `className-active` class is added (this triggers the CSS transition/animation)                                | `class=\"my-animation ng-animate className className-active\"` |\n         * | 11. `$animate` applies the collection of `to` CSS styles to the element which are then handled by the transition      | `class=\"my-animation ng-animate className className-active\"` |\n         * | 12. `$animate` waits for the animation to complete (via events and timeout)                                           | `class=\"my-animation ng-animate className className-active\"` |\n         * | 13. The animation ends and all generated CSS classes are removed from the element                                     | `class=\"my-animation\"`                                       |\n         * | 14. The returned promise is resolved.                                                                                 | `class=\"my-animation\"`                                       |\n         *\n         * @param {DOMElement} element the element that will be the focus of the enter animation\n         * @param {object} from a collection of CSS styles that will be applied to the element at the start of the animation\n         * @param {object} to a collection of CSS styles that the element will animate towards\n         * @param {string=} className an optional CSS class that will be added to the element for the duration of the animation (the default class is `ng-inline-animate`)\n         * @param {object=} options an optional collection of options that will be picked up by the CSS transition/animation\n         * @return {Promise} the animation callback promise\n        */\n        animate: function(element, from, to, className, options) {\n          className = className || 'ng-inline-animate';\n          options = parseAnimateOptions(options) || {};\n          options.from = to ? from : null;\n          options.to   = to ? to : from;\n\n          return runAnimationPostDigest(function(done) {\n            return performAnimation('animate', className, stripCommentsFromElement(element), null, null, noop, options, done);\n          });\n        },\n\n        /**\n         * @ngdoc method\n         * @name $animate#enter\n         * @kind function\n         *\n         * @description\n         * Appends the element to the parentElement element that resides in the document and then runs the enter animation. Once\n         * the animation is started, the following CSS classes will be present on the element for the duration of the animation:\n         *\n         * Below is a breakdown of each step that occurs during enter animation:\n         *\n         * | Animation Step                                                                                                        | What the element class attribute looks like                |\n         * |-----------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------|\n         * | 1. `$animate.enter(...)` is called                                                                                    | `class=\"my-animation\"`                                     |\n         * | 2. element is inserted into the `parentElement` element or beside the `afterElement` element                          | `class=\"my-animation\"`                                     |\n         * | 3. `$animate` waits for the next digest to start the animation                                                        | `class=\"my-animation ng-animate\"`                          |\n         * | 4. `$animate` runs the JavaScript-defined animations detected on the element                                          | `class=\"my-animation ng-animate\"`                          |\n         * | 5. the `.ng-enter` class is added to the element                                                                      | `class=\"my-animation ng-animate ng-enter\"`                 |\n         * | 6. `$animate` scans the element styles to get the CSS transition/animation duration and delay                         | `class=\"my-animation ng-animate ng-enter\"`                 |\n         * | 7. `$animate` blocks all CSS transitions on the element to ensure the `.ng-enter` class styling is applied right away | `class=\"my-animation ng-animate ng-enter\"`                 |\n         * | 8. `$animate` waits for a single animation frame (this performs a reflow)                                             | `class=\"my-animation ng-animate ng-enter\"`                 |\n         * | 9. `$animate` removes the CSS transition block placed on the element                                                  | `class=\"my-animation ng-animate ng-enter\"`                 |\n         * | 10. the `.ng-enter-active` class is added (this triggers the CSS transition/animation)                                | `class=\"my-animation ng-animate ng-enter ng-enter-active\"` |\n         * | 11. `$animate` waits for the animation to complete (via events and timeout)                                           | `class=\"my-animation ng-animate ng-enter ng-enter-active\"` |\n         * | 12. The animation ends and all generated CSS classes are removed from the element                                     | `class=\"my-animation\"`                                     |\n         * | 13. The returned promise is resolved.                                                                                 | `class=\"my-animation\"`                                     |\n         *\n         * @param {DOMElement} element the element that will be the focus of the enter animation\n         * @param {DOMElement} parentElement the parent element of the element that will be the focus of the enter animation\n         * @param {DOMElement} afterElement the sibling element (which is the previous element) of the element that will be the focus of the enter animation\n         * @param {object=} options an optional collection of options that will be picked up by the CSS transition/animation\n         * @return {Promise} the animation callback promise\n        */\n        enter: function(element, parentElement, afterElement, options) {\n          options = parseAnimateOptions(options);\n          element = angular.element(element);\n          parentElement = prepareElement(parentElement);\n          afterElement = prepareElement(afterElement);\n\n          classBasedAnimationsBlocked(element, true);\n          $delegate.enter(element, parentElement, afterElement);\n          return runAnimationPostDigest(function(done) {\n            return performAnimation('enter', 'ng-enter', stripCommentsFromElement(element), parentElement, afterElement, noop, options, done);\n          });\n        },\n\n        /**\n         * @ngdoc method\n         * @name $animate#leave\n         * @kind function\n         *\n         * @description\n         * Runs the leave animation operation and, upon completion, removes the element from the DOM. Once\n         * the animation is started, the following CSS classes will be added for the duration of the animation:\n         *\n         * Below is a breakdown of each step that occurs during leave animation:\n         *\n         * | Animation Step                                                                                                        | What the element class attribute looks like                |\n         * |-----------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------|\n         * | 1. `$animate.leave(...)` is called                                                                                    | `class=\"my-animation\"`                                     |\n         * | 2. `$animate` runs the JavaScript-defined animations detected on the element                                          | `class=\"my-animation ng-animate\"`                          |\n         * | 3. `$animate` waits for the next digest to start the animation                                                        | `class=\"my-animation ng-animate\"`                          |\n         * | 4. the `.ng-leave` class is added to the element                                                                      | `class=\"my-animation ng-animate ng-leave\"`                 |\n         * | 5. `$animate` scans the element styles to get the CSS transition/animation duration and delay                         | `class=\"my-animation ng-animate ng-leave\"`                 |\n         * | 6. `$animate` blocks all CSS transitions on the element to ensure the `.ng-leave` class styling is applied right away | `class=\"my-animation ng-animate ng-leave\"`                 |\n         * | 7. `$animate` waits for a single animation frame (this performs a reflow)                                             | `class=\"my-animation ng-animate ng-leave\"`                 |\n         * | 8. `$animate` removes the CSS transition block placed on the element                                                  | `class=\"my-animation ng-animate ng-leave\"`                 |\n         * | 9. the `.ng-leave-active` class is added (this triggers the CSS transition/animation)                                 | `class=\"my-animation ng-animate ng-leave ng-leave-active\"` |\n         * | 10. `$animate` waits for the animation to complete (via events and timeout)                                           | `class=\"my-animation ng-animate ng-leave ng-leave-active\"` |\n         * | 11. The animation ends and all generated CSS classes are removed from the element                                     | `class=\"my-animation\"`                                     |\n         * | 12. The element is removed from the DOM                                                                               | ...                                                        |\n         * | 13. The returned promise is resolved.                                                                                 | ...                                                        |\n         *\n         * @param {DOMElement} element the element that will be the focus of the leave animation\n         * @param {object=} options an optional collection of styles that will be picked up by the CSS transition/animation\n         * @return {Promise} the animation callback promise\n        */\n        leave: function(element, options) {\n          options = parseAnimateOptions(options);\n          element = angular.element(element);\n\n          cancelChildAnimations(element);\n          classBasedAnimationsBlocked(element, true);\n          return runAnimationPostDigest(function(done) {\n            return performAnimation('leave', 'ng-leave', stripCommentsFromElement(element), null, null, function() {\n              $delegate.leave(element);\n            }, options, done);\n          });\n        },\n\n        /**\n         * @ngdoc method\n         * @name $animate#move\n         * @kind function\n         *\n         * @description\n         * Fires the move DOM operation. Just before the animation starts, the animate service will either append it into the parentElement container or\n         * add the element directly after the afterElement element if present. Then the move animation will be run. Once\n         * the animation is started, the following CSS classes will be added for the duration of the animation:\n         *\n         * Below is a breakdown of each step that occurs during move animation:\n         *\n         * | Animation Step                                                                                                       | What the element class attribute looks like              |\n         * |----------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------|\n         * | 1. `$animate.move(...)` is called                                                                                    | `class=\"my-animation\"`                                   |\n         * | 2. element is moved into the parentElement element or beside the afterElement element                                | `class=\"my-animation\"`                                   |\n         * | 3. `$animate` waits for the next digest to start the animation                                                       | `class=\"my-animation ng-animate\"`                        |\n         * | 4. `$animate` runs the JavaScript-defined animations detected on the element                                         | `class=\"my-animation ng-animate\"`                        |\n         * | 5. the `.ng-move` class is added to the element                                                                      | `class=\"my-animation ng-animate ng-move\"`                |\n         * | 6. `$animate` scans the element styles to get the CSS transition/animation duration and delay                        | `class=\"my-animation ng-animate ng-move\"`                |\n         * | 7. `$animate` blocks all CSS transitions on the element to ensure the `.ng-move` class styling is applied right away | `class=\"my-animation ng-animate ng-move\"`                |\n         * | 8. `$animate` waits for a single animation frame (this performs a reflow)                                            | `class=\"my-animation ng-animate ng-move\"`                |\n         * | 9. `$animate` removes the CSS transition block placed on the element                                                 | `class=\"my-animation ng-animate ng-move\"`                |\n         * | 10. the `.ng-move-active` class is added (this triggers the CSS transition/animation)                                | `class=\"my-animation ng-animate ng-move ng-move-active\"` |\n         * | 11. `$animate` waits for the animation to complete (via events and timeout)                                          | `class=\"my-animation ng-animate ng-move ng-move-active\"` |\n         * | 12. The animation ends and all generated CSS classes are removed from the element                                    | `class=\"my-animation\"`                                   |\n         * | 13. The returned promise is resolved.                                                                                | `class=\"my-animation\"`                                   |\n         *\n         * @param {DOMElement} element the element that will be the focus of the move animation\n         * @param {DOMElement} parentElement the parentElement element of the element that will be the focus of the move animation\n         * @param {DOMElement} afterElement the sibling element (which is the previous element) of the element that will be the focus of the move animation\n         * @param {object=} options an optional collection of styles that will be picked up by the CSS transition/animation\n         * @return {Promise} the animation callback promise\n        */\n        move: function(element, parentElement, afterElement, options) {\n          options = parseAnimateOptions(options);\n          element = angular.element(element);\n          parentElement = prepareElement(parentElement);\n          afterElement = prepareElement(afterElement);\n\n          cancelChildAnimations(element);\n          classBasedAnimationsBlocked(element, true);\n          $delegate.move(element, parentElement, afterElement);\n          return runAnimationPostDigest(function(done) {\n            return performAnimation('move', 'ng-move', stripCommentsFromElement(element), parentElement, afterElement, noop, options, done);\n          });\n        },\n\n        /**\n         * @ngdoc method\n         * @name $animate#addClass\n         *\n         * @description\n         * Triggers a custom animation event based off the className variable and then attaches the className value to the element as a CSS class.\n         * Unlike the other animation methods, the animate service will suffix the className value with {@type -add} in order to provide\n         * the animate service the setup and active CSS classes in order to trigger the animation (this will be skipped if no CSS transitions\n         * or keyframes are defined on the -add-active or base CSS class).\n         *\n         * Below is a breakdown of each step that occurs during addClass animation:\n         *\n         * | Animation Step                                                                                         | What the element class attribute looks like                        |\n         * |--------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------|\n         * | 1. `$animate.addClass(element, 'super')` is called                                                     | `class=\"my-animation\"`                                             |\n         * | 2. `$animate` runs the JavaScript-defined animations detected on the element                           | `class=\"my-animation ng-animate\"`                                  |\n         * | 3. the `.super-add` class is added to the element                                                      | `class=\"my-animation ng-animate super-add\"`                        |\n         * | 4. `$animate` waits for a single animation frame (this performs a reflow)                              | `class=\"my-animation ng-animate super-add\"`                        |\n         * | 5. the `.super` and `.super-add-active` classes are added (this triggers the CSS transition/animation) | `class=\"my-animation ng-animate super super-add super-add-active\"` |\n         * | 6. `$animate` scans the element styles to get the CSS transition/animation duration and delay          | `class=\"my-animation ng-animate super super-add super-add-active\"` |\n         * | 7. `$animate` waits for the animation to complete (via events and timeout)                             | `class=\"my-animation ng-animate super super-add super-add-active\"` |\n         * | 8. The animation ends and all generated CSS classes are removed from the element                       | `class=\"my-animation super\"`                                       |\n         * | 9. The super class is kept on the element                                                              | `class=\"my-animation super\"`                                       |\n         * | 10. The returned promise is resolved.                                                                  | `class=\"my-animation super\"`                                       |\n         *\n         * @param {DOMElement} element the element that will be animated\n         * @param {string} className the CSS class that will be added to the element and then animated\n         * @param {object=} options an optional collection of styles that will be picked up by the CSS transition/animation\n         * @return {Promise} the animation callback promise\n        */\n        addClass: function(element, className, options) {\n          return this.setClass(element, className, [], options);\n        },\n\n        /**\n         * @ngdoc method\n         * @name $animate#removeClass\n         *\n         * @description\n         * Triggers a custom animation event based off the className variable and then removes the CSS class provided by the className value\n         * from the element. Unlike the other animation methods, the animate service will suffix the className value with {@type -remove} in\n         * order to provide the animate service the setup and active CSS classes in order to trigger the animation (this will be skipped if\n         * no CSS transitions or keyframes are defined on the -remove or base CSS classes).\n         *\n         * Below is a breakdown of each step that occurs during removeClass animation:\n         *\n         * | Animation Step                                                                                                       | What the element class attribute looks like                        |\n         * |----------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------|\n         * | 1. `$animate.removeClass(element, 'super')` is called                                                                | `class=\"my-animation super\"`                                       |\n         * | 2. `$animate` runs the JavaScript-defined animations detected on the element                                         | `class=\"my-animation super ng-animate\"`                            |\n         * | 3. the `.super-remove` class is added to the element                                                                 | `class=\"my-animation super ng-animate super-remove\"`               |\n         * | 4. `$animate` waits for a single animation frame (this performs a reflow)                                            | `class=\"my-animation super ng-animate super-remove\"`               |\n         * | 5. the `.super-remove-active` classes are added and `.super` is removed (this triggers the CSS transition/animation) | `class=\"my-animation ng-animate super-remove super-remove-active\"` |\n         * | 6. `$animate` scans the element styles to get the CSS transition/animation duration and delay                        | `class=\"my-animation ng-animate super-remove super-remove-active\"` |\n         * | 7. `$animate` waits for the animation to complete (via events and timeout)                                           | `class=\"my-animation ng-animate super-remove super-remove-active\"` |\n         * | 8. The animation ends and all generated CSS classes are removed from the element                                     | `class=\"my-animation\"`                                             |\n         * | 9. The returned promise is resolved.                                                                                 | `class=\"my-animation\"`                                             |\n         *\n         *\n         * @param {DOMElement} element the element that will be animated\n         * @param {string} className the CSS class that will be animated and then removed from the element\n         * @param {object=} options an optional collection of styles that will be picked up by the CSS transition/animation\n         * @return {Promise} the animation callback promise\n        */\n        removeClass: function(element, className, options) {\n          return this.setClass(element, [], className, options);\n        },\n\n        /**\n         *\n         * @ngdoc method\n         * @name $animate#setClass\n         *\n         * @description Adds and/or removes the given CSS classes to and from the element.\n         * Once complete, the `done()` callback will be fired (if provided).\n         *\n         * | Animation Step                                                                                                                               | What the element class attribute looks like                                            |\n         * |----------------------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------|\n         * | 1. `$animate.setClass(element, 'on', 'off')` is called                                                                                       | `class=\"my-animation off\"`                                                             |\n         * | 2. `$animate` runs the JavaScript-defined animations detected on the element                                                                 | `class=\"my-animation ng-animate off\"`                                                  |\n         * | 3. the `.on-add` and `.off-remove` classes are added to the element                                                                          | `class=\"my-animation ng-animate on-add off-remove off\"`                                |\n         * | 4. `$animate` waits for a single animation frame (this performs a reflow)                                                                    | `class=\"my-animation ng-animate on-add off-remove off\"`                                |\n         * | 5. the `.on`, `.on-add-active` and `.off-remove-active` classes are added and `.off` is removed (this triggers the CSS transition/animation) | `class=\"my-animation ng-animate on on-add on-add-active off-remove off-remove-active\"` |\n         * | 6. `$animate` scans the element styles to get the CSS transition/animation duration and delay                                                | `class=\"my-animation ng-animate on on-add on-add-active off-remove off-remove-active\"` |\n         * | 7. `$animate` waits for the animation to complete (via events and timeout)                                                                   | `class=\"my-animation ng-animate on on-add on-add-active off-remove off-remove-active\"` |\n         * | 8. The animation ends and all generated CSS classes are removed from the element                                                             | `class=\"my-animation on\"`                                                              |\n         * | 9. The returned promise is resolved.                                                                                                         | `class=\"my-animation on\"`                                                              |\n         *\n         * @param {DOMElement} element the element which will have its CSS classes changed\n         *   removed from it\n         * @param {string} add the CSS classes which will be added to the element\n         * @param {string} remove the CSS class which will be removed from the element\n         *   CSS classes have been set on the element\n         * @param {object=} options an optional collection of styles that will be picked up by the CSS transition/animation\n         * @return {Promise} the animation callback promise\n         */\n        setClass: function(element, add, remove, options) {\n          options = parseAnimateOptions(options);\n\n          var STORAGE_KEY = '$$animateClasses';\n          element = angular.element(element);\n          element = stripCommentsFromElement(element);\n\n          if (classBasedAnimationsBlocked(element)) {\n            return $delegate.$$setClassImmediately(element, add, remove, options);\n          }\n\n          // we're using a combined array for both the add and remove\n          // operations since the ORDER OF addClass and removeClass matters\n          var classes, cache = element.data(STORAGE_KEY);\n          var hasCache = !!cache;\n          if (!cache) {\n            cache = {};\n            cache.classes = {};\n          }\n          classes = cache.classes;\n\n          add = isArray(add) ? add : add.split(' ');\n          forEach(add, function(c) {\n            if (c && c.length) {\n              classes[c] = true;\n            }\n          });\n\n          remove = isArray(remove) ? remove : remove.split(' ');\n          forEach(remove, function(c) {\n            if (c && c.length) {\n              classes[c] = false;\n            }\n          });\n\n          if (hasCache) {\n            if (options && cache.options) {\n              cache.options = angular.extend(cache.options || {}, options);\n            }\n\n            //the digest cycle will combine all the animations into one function\n            return cache.promise;\n          } else {\n            element.data(STORAGE_KEY, cache = {\n              classes: classes,\n              options: options\n            });\n          }\n\n          return cache.promise = runAnimationPostDigest(function(done) {\n            var parentElement = element.parent();\n            var elementNode = extractElementNode(element);\n            var parentNode = elementNode.parentNode;\n            // TODO(matsko): move this code into the animationsDisabled() function once #8092 is fixed\n            if (!parentNode || parentNode['$$NG_REMOVED'] || elementNode['$$NG_REMOVED']) {\n              done();\n              return;\n            }\n\n            var cache = element.data(STORAGE_KEY);\n            element.removeData(STORAGE_KEY);\n\n            var state = element.data(NG_ANIMATE_STATE) || {};\n            var classes = resolveElementClasses(element, cache, state.active);\n            return !classes\n              ? done()\n              : performAnimation('setClass', classes, element, parentElement, null, function() {\n                  if (classes[0]) $delegate.$$addClassImmediately(element, classes[0]);\n                  if (classes[1]) $delegate.$$removeClassImmediately(element, classes[1]);\n                }, cache.options, done);\n          });\n        },\n\n        /**\n         * @ngdoc method\n         * @name $animate#cancel\n         * @kind function\n         *\n         * @param {Promise} animationPromise The animation promise that is returned when an animation is started.\n         *\n         * @description\n         * Cancels the provided animation.\n        */\n        cancel: function(promise) {\n          promise.$$cancelFn();\n        },\n\n        /**\n         * @ngdoc method\n         * @name $animate#enabled\n         * @kind function\n         *\n         * @param {boolean=} value If provided then set the animation on or off.\n         * @param {DOMElement=} element If provided then the element will be used to represent the enable/disable operation\n         * @return {boolean} Current animation state.\n         *\n         * @description\n         * Globally enables/disables animations.\n         *\n        */\n        enabled: function(value, element) {\n          switch (arguments.length) {\n            case 2:\n              if (value) {\n                cleanup(element);\n              } else {\n                var data = element.data(NG_ANIMATE_STATE) || {};\n                data.disabled = true;\n                element.data(NG_ANIMATE_STATE, data);\n              }\n            break;\n\n            case 1:\n              rootAnimateState.disabled = !value;\n            break;\n\n            default:\n              value = !rootAnimateState.disabled;\n            break;\n          }\n          return !!value;\n         }\n      };\n\n      /*\n        all animations call this shared animation triggering function internally.\n        The animationEvent variable refers to the JavaScript animation event that will be triggered\n        and the className value is the name of the animation that will be applied within the\n        CSS code. Element, `parentElement` and `afterElement` are provided DOM elements for the animation\n        and the onComplete callback will be fired once the animation is fully complete.\n      */\n      function performAnimation(animationEvent, className, element, parentElement, afterElement, domOperation, options, doneCallback) {\n        var noopCancel = noop;\n        var runner = animationRunner(element, animationEvent, className, options);\n        if (!runner) {\n          fireDOMOperation();\n          fireBeforeCallbackAsync();\n          fireAfterCallbackAsync();\n          closeAnimation();\n          return noopCancel;\n        }\n\n        animationEvent = runner.event;\n        className = runner.className;\n        var elementEvents = angular.element._data(runner.node);\n        elementEvents = elementEvents && elementEvents.events;\n\n        if (!parentElement) {\n          parentElement = afterElement ? afterElement.parent() : element.parent();\n        }\n\n        //skip the animation if animations are disabled, a parent is already being animated,\n        //the element is not currently attached to the document body or then completely close\n        //the animation if any matching animations are not found at all.\n        //NOTE: IE8 + IE9 should close properly (run closeAnimation()) in case an animation was found.\n        if (animationsDisabled(element, parentElement)) {\n          fireDOMOperation();\n          fireBeforeCallbackAsync();\n          fireAfterCallbackAsync();\n          closeAnimation();\n          return noopCancel;\n        }\n\n        var ngAnimateState  = element.data(NG_ANIMATE_STATE) || {};\n        var runningAnimations     = ngAnimateState.active || {};\n        var totalActiveAnimations = ngAnimateState.totalActive || 0;\n        var lastAnimation         = ngAnimateState.last;\n        var skipAnimation = false;\n\n        if (totalActiveAnimations > 0) {\n          var animationsToCancel = [];\n          if (!runner.isClassBased) {\n            if (animationEvent == 'leave' && runningAnimations['ng-leave']) {\n              skipAnimation = true;\n            } else {\n              //cancel all animations when a structural animation takes place\n              for (var klass in runningAnimations) {\n                animationsToCancel.push(runningAnimations[klass]);\n              }\n              ngAnimateState = {};\n              cleanup(element, true);\n            }\n          } else if (lastAnimation.event == 'setClass') {\n            animationsToCancel.push(lastAnimation);\n            cleanup(element, className);\n          } else if (runningAnimations[className]) {\n            var current = runningAnimations[className];\n            if (current.event == animationEvent) {\n              skipAnimation = true;\n            } else {\n              animationsToCancel.push(current);\n              cleanup(element, className);\n            }\n          }\n\n          if (animationsToCancel.length > 0) {\n            forEach(animationsToCancel, function(operation) {\n              operation.cancel();\n            });\n          }\n        }\n\n        if (runner.isClassBased\n            && !runner.isSetClassOperation\n            && animationEvent != 'animate'\n            && !skipAnimation) {\n          skipAnimation = (animationEvent == 'addClass') == element.hasClass(className); //opposite of XOR\n        }\n\n        if (skipAnimation) {\n          fireDOMOperation();\n          fireBeforeCallbackAsync();\n          fireAfterCallbackAsync();\n          fireDoneCallbackAsync();\n          return noopCancel;\n        }\n\n        runningAnimations     = ngAnimateState.active || {};\n        totalActiveAnimations = ngAnimateState.totalActive || 0;\n\n        if (animationEvent == 'leave') {\n          //there's no need to ever remove the listener since the element\n          //will be removed (destroyed) after the leave animation ends or\n          //is cancelled midway\n          element.one('$destroy', function(e) {\n            var element = angular.element(this);\n            var state = element.data(NG_ANIMATE_STATE);\n            if (state) {\n              var activeLeaveAnimation = state.active['ng-leave'];\n              if (activeLeaveAnimation) {\n                activeLeaveAnimation.cancel();\n                cleanup(element, 'ng-leave');\n              }\n            }\n          });\n        }\n\n        //the ng-animate class does nothing, but it's here to allow for\n        //parent animations to find and cancel child animations when needed\n        $$jqLite.addClass(element, NG_ANIMATE_CLASS_NAME);\n        if (options && options.tempClasses) {\n          forEach(options.tempClasses, function(className) {\n            $$jqLite.addClass(element, className);\n          });\n        }\n\n        var localAnimationCount = globalAnimationCounter++;\n        totalActiveAnimations++;\n        runningAnimations[className] = runner;\n\n        element.data(NG_ANIMATE_STATE, {\n          last: runner,\n          active: runningAnimations,\n          index: localAnimationCount,\n          totalActive: totalActiveAnimations\n        });\n\n        //first we run the before animations and when all of those are complete\n        //then we perform the DOM operation and run the next set of animations\n        fireBeforeCallbackAsync();\n        runner.before(function(cancelled) {\n          var data = element.data(NG_ANIMATE_STATE);\n          cancelled = cancelled ||\n                        !data || !data.active[className] ||\n                        (runner.isClassBased && data.active[className].event != animationEvent);\n\n          fireDOMOperation();\n          if (cancelled === true) {\n            closeAnimation();\n          } else {\n            fireAfterCallbackAsync();\n            runner.after(closeAnimation);\n          }\n        });\n\n        return runner.cancel;\n\n        function fireDOMCallback(animationPhase) {\n          var eventName = '$animate:' + animationPhase;\n          if (elementEvents && elementEvents[eventName] && elementEvents[eventName].length > 0) {\n            $$asyncCallback(function() {\n              element.triggerHandler(eventName, {\n                event: animationEvent,\n                className: className\n              });\n            });\n          }\n        }\n\n        function fireBeforeCallbackAsync() {\n          fireDOMCallback('before');\n        }\n\n        function fireAfterCallbackAsync() {\n          fireDOMCallback('after');\n        }\n\n        function fireDoneCallbackAsync() {\n          fireDOMCallback('close');\n          doneCallback();\n        }\n\n        //it is less complicated to use a flag than managing and canceling\n        //timeouts containing multiple callbacks.\n        function fireDOMOperation() {\n          if (!fireDOMOperation.hasBeenRun) {\n            fireDOMOperation.hasBeenRun = true;\n            domOperation();\n          }\n        }\n\n        function closeAnimation() {\n          if (!closeAnimation.hasBeenRun) {\n            if (runner) { //the runner doesn't exist if it fails to instantiate\n              runner.applyStyles();\n            }\n\n            closeAnimation.hasBeenRun = true;\n            if (options && options.tempClasses) {\n              forEach(options.tempClasses, function(className) {\n                $$jqLite.removeClass(element, className);\n              });\n            }\n\n            var data = element.data(NG_ANIMATE_STATE);\n            if (data) {\n\n              /* only structural animations wait for reflow before removing an\n                 animation, but class-based animations don't. An example of this\n                 failing would be when a parent HTML tag has a ng-class attribute\n                 causing ALL directives below to skip animations during the digest */\n              if (runner && runner.isClassBased) {\n                cleanup(element, className);\n              } else {\n                $$asyncCallback(function() {\n                  var data = element.data(NG_ANIMATE_STATE) || {};\n                  if (localAnimationCount == data.index) {\n                    cleanup(element, className, animationEvent);\n                  }\n                });\n                element.data(NG_ANIMATE_STATE, data);\n              }\n            }\n            fireDoneCallbackAsync();\n          }\n        }\n      }\n\n      function cancelChildAnimations(element) {\n        var node = extractElementNode(element);\n        if (node) {\n          var nodes = angular.isFunction(node.getElementsByClassName) ?\n            node.getElementsByClassName(NG_ANIMATE_CLASS_NAME) :\n            node.querySelectorAll('.' + NG_ANIMATE_CLASS_NAME);\n          forEach(nodes, function(element) {\n            element = angular.element(element);\n            var data = element.data(NG_ANIMATE_STATE);\n            if (data && data.active) {\n              forEach(data.active, function(runner) {\n                runner.cancel();\n              });\n            }\n          });\n        }\n      }\n\n      function cleanup(element, className) {\n        if (isMatchingElement(element, $rootElement)) {\n          if (!rootAnimateState.disabled) {\n            rootAnimateState.running = false;\n            rootAnimateState.structural = false;\n          }\n        } else if (className) {\n          var data = element.data(NG_ANIMATE_STATE) || {};\n\n          var removeAnimations = className === true;\n          if (!removeAnimations && data.active && data.active[className]) {\n            data.totalActive--;\n            delete data.active[className];\n          }\n\n          if (removeAnimations || !data.totalActive) {\n            $$jqLite.removeClass(element, NG_ANIMATE_CLASS_NAME);\n            element.removeData(NG_ANIMATE_STATE);\n          }\n        }\n      }\n\n      function animationsDisabled(element, parentElement) {\n        if (rootAnimateState.disabled) {\n          return true;\n        }\n\n        if (isMatchingElement(element, $rootElement)) {\n          return rootAnimateState.running;\n        }\n\n        var allowChildAnimations, parentRunningAnimation, hasParent;\n        do {\n          //the element did not reach the root element which means that it\n          //is not apart of the DOM. Therefore there is no reason to do\n          //any animations on it\n          if (parentElement.length === 0) break;\n\n          var isRoot = isMatchingElement(parentElement, $rootElement);\n          var state = isRoot ? rootAnimateState : (parentElement.data(NG_ANIMATE_STATE) || {});\n          if (state.disabled) {\n            return true;\n          }\n\n          //no matter what, for an animation to work it must reach the root element\n          //this implies that the element is attached to the DOM when the animation is run\n          if (isRoot) {\n            hasParent = true;\n          }\n\n          //once a flag is found that is strictly false then everything before\n          //it will be discarded and all child animations will be restricted\n          if (allowChildAnimations !== false) {\n            var animateChildrenFlag = parentElement.data(NG_ANIMATE_CHILDREN);\n            if (angular.isDefined(animateChildrenFlag)) {\n              allowChildAnimations = animateChildrenFlag;\n            }\n          }\n\n          parentRunningAnimation = parentRunningAnimation ||\n                                   state.running ||\n                                   (state.last && !state.last.isClassBased);\n        }\n        while (parentElement = parentElement.parent());\n\n        return !hasParent || (!allowChildAnimations && parentRunningAnimation);\n      }\n    }]);\n\n    $animateProvider.register('', ['$window', '$sniffer', '$timeout', '$$animateReflow',\n                           function($window,   $sniffer,   $timeout,   $$animateReflow) {\n      // Detect proper transitionend/animationend event names.\n      var CSS_PREFIX = '', TRANSITION_PROP, TRANSITIONEND_EVENT, ANIMATION_PROP, ANIMATIONEND_EVENT;\n\n      // If unprefixed events are not supported but webkit-prefixed are, use the latter.\n      // Otherwise, just use W3C names, browsers not supporting them at all will just ignore them.\n      // Note: Chrome implements `window.onwebkitanimationend` and doesn't implement `window.onanimationend`\n      // but at the same time dispatches the `animationend` event and not `webkitAnimationEnd`.\n      // Register both events in case `window.onanimationend` is not supported because of that,\n      // do the same for `transitionend` as Safari is likely to exhibit similar behavior.\n      // Also, the only modern browser that uses vendor prefixes for transitions/keyframes is webkit\n      // therefore there is no reason to test anymore for other vendor prefixes: http://caniuse.com/#search=transition\n      if (window.ontransitionend === undefined && window.onwebkittransitionend !== undefined) {\n        CSS_PREFIX = '-webkit-';\n        TRANSITION_PROP = 'WebkitTransition';\n        TRANSITIONEND_EVENT = 'webkitTransitionEnd transitionend';\n      } else {\n        TRANSITION_PROP = 'transition';\n        TRANSITIONEND_EVENT = 'transitionend';\n      }\n\n      if (window.onanimationend === undefined && window.onwebkitanimationend !== undefined) {\n        CSS_PREFIX = '-webkit-';\n        ANIMATION_PROP = 'WebkitAnimation';\n        ANIMATIONEND_EVENT = 'webkitAnimationEnd animationend';\n      } else {\n        ANIMATION_PROP = 'animation';\n        ANIMATIONEND_EVENT = 'animationend';\n      }\n\n      var DURATION_KEY = 'Duration';\n      var PROPERTY_KEY = 'Property';\n      var DELAY_KEY = 'Delay';\n      var ANIMATION_ITERATION_COUNT_KEY = 'IterationCount';\n      var ANIMATION_PLAYSTATE_KEY = 'PlayState';\n      var NG_ANIMATE_PARENT_KEY = '$$ngAnimateKey';\n      var NG_ANIMATE_CSS_DATA_KEY = '$$ngAnimateCSS3Data';\n      var ELAPSED_TIME_MAX_DECIMAL_PLACES = 3;\n      var CLOSING_TIME_BUFFER = 1.5;\n      var ONE_SECOND = 1000;\n\n      var lookupCache = {};\n      var parentCounter = 0;\n      var animationReflowQueue = [];\n      var cancelAnimationReflow;\n      function clearCacheAfterReflow() {\n        if (!cancelAnimationReflow) {\n          cancelAnimationReflow = $$animateReflow(function() {\n            animationReflowQueue = [];\n            cancelAnimationReflow = null;\n            lookupCache = {};\n          });\n        }\n      }\n\n      function afterReflow(element, callback) {\n        if (cancelAnimationReflow) {\n          cancelAnimationReflow();\n        }\n        animationReflowQueue.push(callback);\n        cancelAnimationReflow = $$animateReflow(function() {\n          forEach(animationReflowQueue, function(fn) {\n            fn();\n          });\n\n          animationReflowQueue = [];\n          cancelAnimationReflow = null;\n          lookupCache = {};\n        });\n      }\n\n      var closingTimer = null;\n      var closingTimestamp = 0;\n      var animationElementQueue = [];\n      function animationCloseHandler(element, totalTime) {\n        var node = extractElementNode(element);\n        element = angular.element(node);\n\n        //this item will be garbage collected by the closing\n        //animation timeout\n        animationElementQueue.push(element);\n\n        //but it may not need to cancel out the existing timeout\n        //if the timestamp is less than the previous one\n        var futureTimestamp = Date.now() + totalTime;\n        if (futureTimestamp <= closingTimestamp) {\n          return;\n        }\n\n        $timeout.cancel(closingTimer);\n\n        closingTimestamp = futureTimestamp;\n        closingTimer = $timeout(function() {\n          closeAllAnimations(animationElementQueue);\n          animationElementQueue = [];\n        }, totalTime, false);\n      }\n\n      function closeAllAnimations(elements) {\n        forEach(elements, function(element) {\n          var elementData = element.data(NG_ANIMATE_CSS_DATA_KEY);\n          if (elementData) {\n            forEach(elementData.closeAnimationFns, function(fn) {\n              fn();\n            });\n          }\n        });\n      }\n\n      function getElementAnimationDetails(element, cacheKey) {\n        var data = cacheKey ? lookupCache[cacheKey] : null;\n        if (!data) {\n          var transitionDuration = 0;\n          var transitionDelay = 0;\n          var animationDuration = 0;\n          var animationDelay = 0;\n\n          //we want all the styles defined before and after\n          forEach(element, function(element) {\n            if (element.nodeType == ELEMENT_NODE) {\n              var elementStyles = $window.getComputedStyle(element) || {};\n\n              var transitionDurationStyle = elementStyles[TRANSITION_PROP + DURATION_KEY];\n              transitionDuration = Math.max(parseMaxTime(transitionDurationStyle), transitionDuration);\n\n              var transitionDelayStyle = elementStyles[TRANSITION_PROP + DELAY_KEY];\n              transitionDelay  = Math.max(parseMaxTime(transitionDelayStyle), transitionDelay);\n\n              var animationDelayStyle = elementStyles[ANIMATION_PROP + DELAY_KEY];\n              animationDelay   = Math.max(parseMaxTime(elementStyles[ANIMATION_PROP + DELAY_KEY]), animationDelay);\n\n              var aDuration  = parseMaxTime(elementStyles[ANIMATION_PROP + DURATION_KEY]);\n\n              if (aDuration > 0) {\n                aDuration *= parseInt(elementStyles[ANIMATION_PROP + ANIMATION_ITERATION_COUNT_KEY], 10) || 1;\n              }\n              animationDuration = Math.max(aDuration, animationDuration);\n            }\n          });\n          data = {\n            total: 0,\n            transitionDelay: transitionDelay,\n            transitionDuration: transitionDuration,\n            animationDelay: animationDelay,\n            animationDuration: animationDuration\n          };\n          if (cacheKey) {\n            lookupCache[cacheKey] = data;\n          }\n        }\n        return data;\n      }\n\n      function parseMaxTime(str) {\n        var maxValue = 0;\n        var values = isString(str) ?\n          str.split(/\\s*,\\s*/) :\n          [];\n        forEach(values, function(value) {\n          maxValue = Math.max(parseFloat(value) || 0, maxValue);\n        });\n        return maxValue;\n      }\n\n      function getCacheKey(element) {\n        var parentElement = element.parent();\n        var parentID = parentElement.data(NG_ANIMATE_PARENT_KEY);\n        if (!parentID) {\n          parentElement.data(NG_ANIMATE_PARENT_KEY, ++parentCounter);\n          parentID = parentCounter;\n        }\n        return parentID + '-' + extractElementNode(element).getAttribute('class');\n      }\n\n      function animateSetup(animationEvent, element, className, styles) {\n        var structural = ['ng-enter','ng-leave','ng-move'].indexOf(className) >= 0;\n\n        var cacheKey = getCacheKey(element);\n        var eventCacheKey = cacheKey + ' ' + className;\n        var itemIndex = lookupCache[eventCacheKey] ? ++lookupCache[eventCacheKey].total : 0;\n\n        var stagger = {};\n        if (itemIndex > 0) {\n          var staggerClassName = className + '-stagger';\n          var staggerCacheKey = cacheKey + ' ' + staggerClassName;\n          var applyClasses = !lookupCache[staggerCacheKey];\n\n          applyClasses && $$jqLite.addClass(element, staggerClassName);\n\n          stagger = getElementAnimationDetails(element, staggerCacheKey);\n\n          applyClasses && $$jqLite.removeClass(element, staggerClassName);\n        }\n\n        $$jqLite.addClass(element, className);\n\n        var formerData = element.data(NG_ANIMATE_CSS_DATA_KEY) || {};\n        var timings = getElementAnimationDetails(element, eventCacheKey);\n        var transitionDuration = timings.transitionDuration;\n        var animationDuration = timings.animationDuration;\n\n        if (structural && transitionDuration === 0 && animationDuration === 0) {\n          $$jqLite.removeClass(element, className);\n          return false;\n        }\n\n        var blockTransition = styles || (structural && transitionDuration > 0);\n        var blockAnimation = animationDuration > 0 &&\n                             stagger.animationDelay > 0 &&\n                             stagger.animationDuration === 0;\n\n        var closeAnimationFns = formerData.closeAnimationFns || [];\n        element.data(NG_ANIMATE_CSS_DATA_KEY, {\n          stagger: stagger,\n          cacheKey: eventCacheKey,\n          running: formerData.running || 0,\n          itemIndex: itemIndex,\n          blockTransition: blockTransition,\n          closeAnimationFns: closeAnimationFns\n        });\n\n        var node = extractElementNode(element);\n\n        if (blockTransition) {\n          blockTransitions(node, true);\n          if (styles) {\n            element.css(styles);\n          }\n        }\n\n        if (blockAnimation) {\n          blockAnimations(node, true);\n        }\n\n        return true;\n      }\n\n      function animateRun(animationEvent, element, className, activeAnimationComplete, styles) {\n        var node = extractElementNode(element);\n        var elementData = element.data(NG_ANIMATE_CSS_DATA_KEY);\n        if (node.getAttribute('class').indexOf(className) == -1 || !elementData) {\n          activeAnimationComplete();\n          return;\n        }\n\n        var activeClassName = '';\n        var pendingClassName = '';\n        forEach(className.split(' '), function(klass, i) {\n          var prefix = (i > 0 ? ' ' : '') + klass;\n          activeClassName += prefix + '-active';\n          pendingClassName += prefix + '-pending';\n        });\n\n        var style = '';\n        var appliedStyles = [];\n        var itemIndex = elementData.itemIndex;\n        var stagger = elementData.stagger;\n        var staggerTime = 0;\n        if (itemIndex > 0) {\n          var transitionStaggerDelay = 0;\n          if (stagger.transitionDelay > 0 && stagger.transitionDuration === 0) {\n            transitionStaggerDelay = stagger.transitionDelay * itemIndex;\n          }\n\n          var animationStaggerDelay = 0;\n          if (stagger.animationDelay > 0 && stagger.animationDuration === 0) {\n            animationStaggerDelay = stagger.animationDelay * itemIndex;\n            appliedStyles.push(CSS_PREFIX + 'animation-play-state');\n          }\n\n          staggerTime = Math.round(Math.max(transitionStaggerDelay, animationStaggerDelay) * 100) / 100;\n        }\n\n        if (!staggerTime) {\n          $$jqLite.addClass(element, activeClassName);\n          if (elementData.blockTransition) {\n            blockTransitions(node, false);\n          }\n        }\n\n        var eventCacheKey = elementData.cacheKey + ' ' + activeClassName;\n        var timings = getElementAnimationDetails(element, eventCacheKey);\n        var maxDuration = Math.max(timings.transitionDuration, timings.animationDuration);\n        if (maxDuration === 0) {\n          $$jqLite.removeClass(element, activeClassName);\n          animateClose(element, className);\n          activeAnimationComplete();\n          return;\n        }\n\n        if (!staggerTime && styles && Object.keys(styles).length > 0) {\n          if (!timings.transitionDuration) {\n            element.css('transition', timings.animationDuration + 's linear all');\n            appliedStyles.push('transition');\n          }\n          element.css(styles);\n        }\n\n        var maxDelay = Math.max(timings.transitionDelay, timings.animationDelay);\n        var maxDelayTime = maxDelay * ONE_SECOND;\n\n        if (appliedStyles.length > 0) {\n          //the element being animated may sometimes contain comment nodes in\n          //the jqLite object, so we're safe to use a single variable to house\n          //the styles since there is always only one element being animated\n          var oldStyle = node.getAttribute('style') || '';\n          if (oldStyle.charAt(oldStyle.length - 1) !== ';') {\n            oldStyle += ';';\n          }\n          node.setAttribute('style', oldStyle + ' ' + style);\n        }\n\n        var startTime = Date.now();\n        var css3AnimationEvents = ANIMATIONEND_EVENT + ' ' + TRANSITIONEND_EVENT;\n        var animationTime     = (maxDelay + maxDuration) * CLOSING_TIME_BUFFER;\n        var totalTime         = (staggerTime + animationTime) * ONE_SECOND;\n\n        var staggerTimeout;\n        if (staggerTime > 0) {\n          $$jqLite.addClass(element, pendingClassName);\n          staggerTimeout = $timeout(function() {\n            staggerTimeout = null;\n\n            if (timings.transitionDuration > 0) {\n              blockTransitions(node, false);\n            }\n            if (timings.animationDuration > 0) {\n              blockAnimations(node, false);\n            }\n\n            $$jqLite.addClass(element, activeClassName);\n            $$jqLite.removeClass(element, pendingClassName);\n\n            if (styles) {\n              if (timings.transitionDuration === 0) {\n                element.css('transition', timings.animationDuration + 's linear all');\n              }\n              element.css(styles);\n              appliedStyles.push('transition');\n            }\n          }, staggerTime * ONE_SECOND, false);\n        }\n\n        element.on(css3AnimationEvents, onAnimationProgress);\n        elementData.closeAnimationFns.push(function() {\n          onEnd();\n          activeAnimationComplete();\n        });\n\n        elementData.running++;\n        animationCloseHandler(element, totalTime);\n        return onEnd;\n\n        // This will automatically be called by $animate so\n        // there is no need to attach this internally to the\n        // timeout done method.\n        function onEnd() {\n          element.off(css3AnimationEvents, onAnimationProgress);\n          $$jqLite.removeClass(element, activeClassName);\n          $$jqLite.removeClass(element, pendingClassName);\n          if (staggerTimeout) {\n            $timeout.cancel(staggerTimeout);\n          }\n          animateClose(element, className);\n          var node = extractElementNode(element);\n          for (var i in appliedStyles) {\n            node.style.removeProperty(appliedStyles[i]);\n          }\n        }\n\n        function onAnimationProgress(event) {\n          event.stopPropagation();\n          var ev = event.originalEvent || event;\n          var timeStamp = ev.$manualTimeStamp || ev.timeStamp || Date.now();\n\n          /* Firefox (or possibly just Gecko) likes to not round values up\n           * when a ms measurement is used for the animation */\n          var elapsedTime = parseFloat(ev.elapsedTime.toFixed(ELAPSED_TIME_MAX_DECIMAL_PLACES));\n\n          /* $manualTimeStamp is a mocked timeStamp value which is set\n           * within browserTrigger(). This is only here so that tests can\n           * mock animations properly. Real events fallback to event.timeStamp,\n           * or, if they don't, then a timeStamp is automatically created for them.\n           * We're checking to see if the timeStamp surpasses the expected delay,\n           * but we're using elapsedTime instead of the timeStamp on the 2nd\n           * pre-condition since animations sometimes close off early */\n          if (Math.max(timeStamp - startTime, 0) >= maxDelayTime && elapsedTime >= maxDuration) {\n            activeAnimationComplete();\n          }\n        }\n      }\n\n      function blockTransitions(node, bool) {\n        node.style[TRANSITION_PROP + PROPERTY_KEY] = bool ? 'none' : '';\n      }\n\n      function blockAnimations(node, bool) {\n        node.style[ANIMATION_PROP + ANIMATION_PLAYSTATE_KEY] = bool ? 'paused' : '';\n      }\n\n      function animateBefore(animationEvent, element, className, styles) {\n        if (animateSetup(animationEvent, element, className, styles)) {\n          return function(cancelled) {\n            cancelled && animateClose(element, className);\n          };\n        }\n      }\n\n      function animateAfter(animationEvent, element, className, afterAnimationComplete, styles) {\n        if (element.data(NG_ANIMATE_CSS_DATA_KEY)) {\n          return animateRun(animationEvent, element, className, afterAnimationComplete, styles);\n        } else {\n          animateClose(element, className);\n          afterAnimationComplete();\n        }\n      }\n\n      function animate(animationEvent, element, className, animationComplete, options) {\n        //If the animateSetup function doesn't bother returning a\n        //cancellation function then it means that there is no animation\n        //to perform at all\n        var preReflowCancellation = animateBefore(animationEvent, element, className, options.from);\n        if (!preReflowCancellation) {\n          clearCacheAfterReflow();\n          animationComplete();\n          return;\n        }\n\n        //There are two cancellation functions: one is before the first\n        //reflow animation and the second is during the active state\n        //animation. The first function will take care of removing the\n        //data from the element which will not make the 2nd animation\n        //happen in the first place\n        var cancel = preReflowCancellation;\n        afterReflow(element, function() {\n          //once the reflow is complete then we point cancel to\n          //the new cancellation function which will remove all of the\n          //animation properties from the active animation\n          cancel = animateAfter(animationEvent, element, className, animationComplete, options.to);\n        });\n\n        return function(cancelled) {\n          (cancel || noop)(cancelled);\n        };\n      }\n\n      function animateClose(element, className) {\n        $$jqLite.removeClass(element, className);\n        var data = element.data(NG_ANIMATE_CSS_DATA_KEY);\n        if (data) {\n          if (data.running) {\n            data.running--;\n          }\n          if (!data.running || data.running === 0) {\n            element.removeData(NG_ANIMATE_CSS_DATA_KEY);\n          }\n        }\n      }\n\n      return {\n        animate: function(element, className, from, to, animationCompleted, options) {\n          options = options || {};\n          options.from = from;\n          options.to = to;\n          return animate('animate', element, className, animationCompleted, options);\n        },\n\n        enter: function(element, animationCompleted, options) {\n          options = options || {};\n          return animate('enter', element, 'ng-enter', animationCompleted, options);\n        },\n\n        leave: function(element, animationCompleted, options) {\n          options = options || {};\n          return animate('leave', element, 'ng-leave', animationCompleted, options);\n        },\n\n        move: function(element, animationCompleted, options) {\n          options = options || {};\n          return animate('move', element, 'ng-move', animationCompleted, options);\n        },\n\n        beforeSetClass: function(element, add, remove, animationCompleted, options) {\n          options = options || {};\n          var className = suffixClasses(remove, '-remove') + ' ' +\n                          suffixClasses(add, '-add');\n          var cancellationMethod = animateBefore('setClass', element, className, options.from);\n          if (cancellationMethod) {\n            afterReflow(element, animationCompleted);\n            return cancellationMethod;\n          }\n          clearCacheAfterReflow();\n          animationCompleted();\n        },\n\n        beforeAddClass: function(element, className, animationCompleted, options) {\n          options = options || {};\n          var cancellationMethod = animateBefore('addClass', element, suffixClasses(className, '-add'), options.from);\n          if (cancellationMethod) {\n            afterReflow(element, animationCompleted);\n            return cancellationMethod;\n          }\n          clearCacheAfterReflow();\n          animationCompleted();\n        },\n\n        beforeRemoveClass: function(element, className, animationCompleted, options) {\n          options = options || {};\n          var cancellationMethod = animateBefore('removeClass', element, suffixClasses(className, '-remove'), options.from);\n          if (cancellationMethod) {\n            afterReflow(element, animationCompleted);\n            return cancellationMethod;\n          }\n          clearCacheAfterReflow();\n          animationCompleted();\n        },\n\n        setClass: function(element, add, remove, animationCompleted, options) {\n          options = options || {};\n          remove = suffixClasses(remove, '-remove');\n          add = suffixClasses(add, '-add');\n          var className = remove + ' ' + add;\n          return animateAfter('setClass', element, className, animationCompleted, options.to);\n        },\n\n        addClass: function(element, className, animationCompleted, options) {\n          options = options || {};\n          return animateAfter('addClass', element, suffixClasses(className, '-add'), animationCompleted, options.to);\n        },\n\n        removeClass: function(element, className, animationCompleted, options) {\n          options = options || {};\n          return animateAfter('removeClass', element, suffixClasses(className, '-remove'), animationCompleted, options.to);\n        }\n      };\n\n      function suffixClasses(classes, suffix) {\n        var className = '';\n        classes = isArray(classes) ? classes : classes.split(/\\s+/);\n        forEach(classes, function(klass, i) {\n          if (klass && klass.length > 0) {\n            className += (i > 0 ? ' ' : '') + klass + suffix;\n          }\n        });\n        return className;\n      }\n    }]);\n  }]);\n\n\n})(window, window.angular);\n"
  },
  {
    "path": "flowable-ui-web/idm/libs/angular-cookies_1.3.13/angular-cookies.js",
    "content": "/**\n * @license AngularJS v1.3.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 module\n * @name ngCookies\n * @description\n *\n * # ngCookies\n *\n * The `ngCookies` module provides a convenient wrapper for reading and writing browser cookies.\n *\n *\n * <div doc-module-components=\"ngCookies\"></div>\n *\n * See {@link ngCookies.$cookies `$cookies`} and\n * {@link ngCookies.$cookieStore `$cookieStore`} for usage.\n */\n\n\nangular.module('ngCookies', ['ng']).\n  /**\n   * @ngdoc service\n   * @name $cookies\n   *\n   * @description\n   * Provides read/write access to browser's cookies.\n   *\n   * Only a simple Object is exposed and by adding or removing properties to/from this object, new\n   * cookies are created/deleted at the end of current $eval.\n   * The object's properties can only be strings.\n   *\n   * Requires the {@link ngCookies `ngCookies`} module to be installed.\n   *\n   * @example\n   *\n   * ```js\n   * angular.module('cookiesExample', ['ngCookies'])\n   *   .controller('ExampleController', ['$cookies', function($cookies) {\n   *     // Retrieving a cookie\n   *     var favoriteCookie = $cookies.myFavorite;\n   *     // Setting a cookie\n   *     $cookies.myFavorite = 'oatmeal';\n   *   }]);\n   * ```\n   */\n   factory('$cookies', ['$rootScope', '$browser', function($rootScope, $browser) {\n      var cookies = {},\n          lastCookies = {},\n          lastBrowserCookies,\n          runEval = false,\n          copy = angular.copy,\n          isUndefined = angular.isUndefined;\n\n      //creates a poller fn that copies all cookies from the $browser to service & inits the service\n      $browser.addPollFn(function() {\n        var currentCookies = $browser.cookies();\n        if (lastBrowserCookies != currentCookies) { //relies on browser.cookies() impl\n          lastBrowserCookies = currentCookies;\n          copy(currentCookies, lastCookies);\n          copy(currentCookies, cookies);\n          if (runEval) $rootScope.$apply();\n        }\n      })();\n\n      runEval = true;\n\n      //at the end of each eval, push cookies\n      //TODO: this should happen before the \"delayed\" watches fire, because if some cookies are not\n      //      strings or browser refuses to store some cookies, we update the model in the push fn.\n      $rootScope.$watch(push);\n\n      return cookies;\n\n\n      /**\n       * Pushes all the cookies from the service to the browser and verifies if all cookies were\n       * stored.\n       */\n      function push() {\n        var name,\n            value,\n            browserCookies,\n            updated;\n\n        //delete any cookies deleted in $cookies\n        for (name in lastCookies) {\n          if (isUndefined(cookies[name])) {\n            $browser.cookies(name, undefined);\n          }\n        }\n\n        //update all cookies updated in $cookies\n        for (name in cookies) {\n          value = cookies[name];\n          if (!angular.isString(value)) {\n            value = '' + value;\n            cookies[name] = value;\n          }\n          if (value !== lastCookies[name]) {\n            $browser.cookies(name, value);\n            updated = true;\n          }\n        }\n\n        //verify what was actually stored\n        if (updated) {\n          updated = false;\n          browserCookies = $browser.cookies();\n\n          for (name in cookies) {\n            if (cookies[name] !== browserCookies[name]) {\n              //delete or reset all cookies that the browser dropped from $cookies\n              if (isUndefined(browserCookies[name])) {\n                delete cookies[name];\n              } else {\n                cookies[name] = browserCookies[name];\n              }\n              updated = true;\n            }\n          }\n        }\n      }\n    }]).\n\n\n  /**\n   * @ngdoc service\n   * @name $cookieStore\n   * @requires $cookies\n   *\n   * @description\n   * Provides a key-value (string-object) storage, that is backed by session cookies.\n   * Objects put or retrieved from this storage are automatically serialized or\n   * deserialized by angular's toJson/fromJson.\n   *\n   * Requires the {@link ngCookies `ngCookies`} module to be installed.\n   *\n   * @example\n   *\n   * ```js\n   * angular.module('cookieStoreExample', ['ngCookies'])\n   *   .controller('ExampleController', ['$cookieStore', function($cookieStore) {\n   *     // Put cookie\n   *     $cookieStore.put('myFavorite','oatmeal');\n   *     // Get cookie\n   *     var favoriteCookie = $cookieStore.get('myFavorite');\n   *     // Removing a cookie\n   *     $cookieStore.remove('myFavorite');\n   *   }]);\n   * ```\n   */\n   factory('$cookieStore', ['$cookies', function($cookies) {\n\n      return {\n        /**\n         * @ngdoc method\n         * @name $cookieStore#get\n         *\n         * @description\n         * Returns the value of given cookie key\n         *\n         * @param {string} key Id to use for lookup.\n         * @returns {Object} Deserialized cookie value.\n         */\n        get: function(key) {\n          var value = $cookies[key];\n          return value ? angular.fromJson(value) : value;\n        },\n\n        /**\n         * @ngdoc method\n         * @name $cookieStore#put\n         *\n         * @description\n         * Sets a value for given cookie key\n         *\n         * @param {string} key Id for the `value`.\n         * @param {Object} value Value to be stored.\n         */\n        put: function(key, value) {\n          $cookies[key] = angular.toJson(value);\n        },\n\n        /**\n         * @ngdoc method\n         * @name $cookieStore#remove\n         *\n         * @description\n         * Remove given cookie\n         *\n         * @param {string} key Id of the key-value pair to delete.\n         */\n        remove: function(key) {\n          delete $cookies[key];\n        }\n      };\n\n    }]);\n\n\n})(window, window.angular);\n"
  },
  {
    "path": "flowable-ui-web/idm/libs/angular-drag-and-drop-lists_1.2.0/angular-drag-and-drop-lists.js",
    "content": "/**\n * angular-drag-and-drop-lists v1.2.0\n *\n * Copyright (c) 2014 Marcel Juenemann mail@marcel-junemann.de\n * https://github.com/marceljuenemann/angular-drag-and-drop-lists\n *\n * License: MIT\n */\nangular.module('dndLists', [])\n\n  /**\n   * Use the dnd-draggable attribute to make your element draggable\n   *\n   * Attributes:\n   * - dnd-draggable      Required attribute. The value has to be an object that represents the data\n   *                      of the element. In case of a drag and drop operation the object will be\n   *                      serialized and unserialized on the receiving end.\n   * - dnd-selected       Callback that is invoked when the element was clicked but not dragged.\n   *                      The original click event will be provided in the local event variable.\n   * - dnd-effect-allowed Use this attribute to limit the operations that can be performed. Options:\n   *                      - \"move\": The drag operation will move the element. This is the default.\n   *                      - \"copy\": The drag operation will copy the element. Shows a copy cursor.\n   *                      - \"copyMove\": The user can choose between copy and move by pressing the\n   *                        ctrl or shift key. *Not supported in IE:* In Internet Explorer this\n   *                        option will be the same as \"copy\". *Not fully supported in Chrome on\n   *                        Windows:* In the Windows version of Chrome the cursor will always be the\n   *                        move cursor. However, when the user drops an element and has the ctrl\n   *                        key pressed, we will perform a copy anyways.\n   *                      - HTML5 also specifies the \"link\" option, but this library does not\n   *                        actively support it yet, so use it at your own risk.\n   * - dnd-moved          Callback that is invoked when the element was moved. Usually you will\n   *                      remove your element from the original list in this callback, since the\n   *                      directive is not doing that for you automatically. The original dragend\n   *                      event will be provided in the local event variable.\n   * - dnd-copied         Same as dnd-moved, just that it is called when the element was copied\n   *                      instead of moved. The original dragend event will be provided in the local\n   *                      event variable.\n   * - dnd-dragstart      Callback that is invoked when the element was dragged. The original\n   *                      dragstart event will be provided in the local event variable.\n   * - dnd-type           Use this attribute if you have different kinds of items in your\n   *                      application and you want to limit which items can be dropped into which\n   *                      lists. Combine with dnd-allowed-types on the dnd-list(s). This attribute\n   *                      should evaluate to a string, although this restriction is not enforced.\n   * - dnd-disable-if     You can use this attribute to dynamically disable the draggability of the\n   *                      element. This is useful if you have certain list items that you don't want\n   *                      to be draggable, or if you want to disable drag & drop completely without\n   *                      having two different code branches (e.g. only allow for admins).\n   *                      **Note**: If your element is not draggable, the user is probably able to\n   *                      select text or images inside of it. Since a selection is always draggable,\n   *                      this breaks your UI. You most likely want to disable user selection via\n   *                      CSS (see user-select).\n   *\n   * CSS classes:\n   * - dndDragging        This class will be added to the element while the element is being\n   *                      dragged. It will affect both the element you see while dragging and the\n   *                      source element that stays at it's position. Do not try to hide the source\n   *                      element with this class, because that will abort the drag operation.\n   * - dndDraggingSource  This class will be added to the element after the drag operation was\n   *                      started, meaning it only affects the original element that is still at\n   *                      it's source position, and not the \"element\" that the user is dragging with\n   *                      his mouse pointer.\n   */\n  .directive('dndDraggable', ['$parse', '$timeout', 'dndDropEffectWorkaround', 'dndDragTypeWorkaround',\n                      function($parse,   $timeout,   dndDropEffectWorkaround,   dndDragTypeWorkaround) {\n    return function(scope, element, attr) {\n      // Set the HTML5 draggable attribute on the element\n      element.attr(\"draggable\", \"true\");\n\n      // If the dnd-disable-if attribute is set, we have to watch that\n      if (attr.dndDisableIf) {\n        scope.$watch(attr.dndDisableIf, function(disabled) {\n          element.attr(\"draggable\", !disabled);\n        });\n      }\n\n      /**\n       * When the drag operation is started we have to prepare the dataTransfer object,\n       * which is the primary way we communicate with the target element\n       */\n      element.on('dragstart', function(event) {\n        event = event.originalEvent || event;\n\n        // Serialize the data associated with this element. IE only supports the Text drag type\n        event.dataTransfer.setData(\"Text\", angular.toJson(scope.$eval(attr.dndDraggable)));\n\n        // Only allow actions specified in dnd-effect-allowed attribute\n        event.dataTransfer.effectAllowed = attr.dndEffectAllowed || \"move\";\n\n        // Add CSS classes. See documentation above\n        element.addClass(\"dndDragging\");\n\n        // Workarounds for stupid browsers, see description below\n        dndDropEffectWorkaround.dropEffect = \"none\";\n        dndDragTypeWorkaround.isDragging = true;\n\n        // <FLOWABLE>\n        // This code was originally placed after element.addClass.\n        // This timeout is invoked after the 'dragend' event in IE9 (at least on slooow virtual box)\n        // and since this class is used to hide elements it seems like the element is gone,\n        // therefor make sure the dragging still is happening when adding this class\n        $timeout(function() {\n          // Flowable This code\n          if (dndDragTypeWorkaround.isDragging) {\n            element.addClass(\"dndDraggingSource\");\n          }\n        }, 0);\n        // </FLOWABLE>\n\n        // Save type of item in global state. Usually, this would go into the dataTransfer\n        // typename, but we have to use \"Text\" there to support IE\n        dndDragTypeWorkaround.dragType = attr.dndType ? scope.$eval(attr.dndType) : undefined;\n\n        // Invoke callback\n        $parse(attr.dndDragstart)(scope, {event: event});\n\n        event.stopPropagation();\n      });\n\n      /**\n       * The dragend event is triggered when the element was dropped or when the drag\n       * operation was aborted (e.g. hit escape button). Depending on the executed action\n       * we will invoke the callbacks specified with the dnd-moved or dnd-copied attribute.\n       */\n      element.on('dragend', function(event) {\n        event = event.originalEvent || event;\n\n        // Invoke callbacks. Usually we would use event.dataTransfer.dropEffect to determine\n        // the used effect, but Chrome has not implemented that field correctly. On Windows\n        // it always sets it to 'none', while Chrome on Linux sometimes sets it to something\n        // else when it's supposed to send 'none' (drag operation aborted).\n        var dropEffect = dndDropEffectWorkaround.dropEffect;\n        scope.$apply(function() {\n          switch (dropEffect) {\n            case \"move\":\n              $parse(attr.dndMoved)(scope, {event: event});\n              break;\n\n            case \"copy\":\n              $parse(attr.dndCopied)(scope, {event: event});\n              break;\n          }\n        });\n\n        // Clean up\n        element.removeClass(\"dndDragging\");\n        element.removeClass(\"dndDraggingSource\");\n        dndDragTypeWorkaround.isDragging = false;\n        event.stopPropagation();\n      });\n\n      /**\n       * When the element is clicked we invoke the callback function\n       * specified with the dnd-selected attribute.\n       */\n      element.on('click', function(event) {\n        event = event.originalEvent || event;\n\n        scope.$apply(function() {\n          $parse(attr.dndSelected)(scope, {event: event});\n        });\n\n        event.stopPropagation();\n      });\n\n      /**\n       * Workaround to make element draggable in IE9\n       */\n      element.on('selectstart', function() {\n        if (this.dragDrop) this.dragDrop();\n        return false;\n      });\n    };\n  }])\n\n  /**\n   * Use the dnd-list attribute to make your list element a dropzone. Usually you will add a single\n   * li element as child with the ng-repeat directive. If you don't do that, we will not be able to\n   * position the dropped element correctly. If you want your list to be sortable, also add the\n   * dnd-draggable directive to your li element(s). Both the dnd-list and it's direct children must\n   * have position: relative CSS style, otherwise the positioning algorithm will not be able to\n   * determine the correct placeholder position in all browsers.\n   *\n   * Attributes:\n   * - dnd-list             Required attribute. The value has to be the array in which the data of\n   *                        the dropped element should be inserted.\n   * - dnd-allowed-types    Optional array of allowed item types. When used, only items that had a\n   *                        matching dnd-type attribute will be dropable.\n   * - dnd-disable-if       Optional boolean expresssion. When it evaluates to true, no dropping\n   *                        into the list is possible. Note that this also disables rearranging\n   *                        items inside the list.\n   * - dnd-horizontal-list  Optional boolean expresssion. When it evaluates to true, the positioning\n   *                        algorithm will use the left and right halfs of the list items instead of\n   *                        the upper and lower halfs.\n   * - dnd-dragover         Optional expression that is invoked when an element is dragged over the\n   *                        list. If the expression is set, but does not return true, the element is\n   *                        not allowed to be dropped. The following variables will be available:\n   *                        - event: The original dragover event sent by the browser.\n   *                        - index: The position in the list at which the element would be dropped.\n   *                        - type: The dnd-type set on the dnd-draggable, or undefined if unset.\n   * - dnd-drop             Optional expression that is invoked when an element is dropped over the\n   *                        list. If the expression is set, it must return the object that will be\n   *                        inserted into the list. If it returns false, the drop will be aborted\n   *                        and the event is propagated. The following variables will be available:\n   *                        - event: The original drop event sent by the browser.\n   *                        - index: The position in the list at which the element would be dropped.\n   *                        - item: The transferred object.\n   *                        - type: The dnd-type set on the dnd-draggable, or undefined if unset.\n   * - dnd-external-sources Optional boolean expression. When it evaluates to true, the list accepts\n   *                        drops from sources outside of the current browser tab. This allows to\n   *                        drag and drop accross different browser tabs. Note that this will allow\n   *                        to drop arbitrary text into the list, thus it is highly recommended to\n   *                        implement the dnd-drop callback to check the incoming element for\n   *                        sanity. Furthermore, the dnd-type of external sources can not be\n   *                        determined, therefore do not rely on restrictions of dnd-allowed-type.\n   *\n   * CSS classes:\n   * - dndPlaceholder       When an element is dragged over the list, a new placeholder child\n   *                        element will be added. This element is of type li and has the class\n   *                        dndPlaceholder set.\n   * - dndDragover          Will be added to the list while an element is dragged over the list.\n   */\n  .directive('dndList', ['$parse', '$timeout', 'dndDropEffectWorkaround', 'dndDragTypeWorkaround',\n                 function($parse,   $timeout,   dndDropEffectWorkaround,   dndDragTypeWorkaround) {\n    return function(scope, element, attr) {\n      // While an element is dragged over the list, this placeholder element is inserted\n      // at the location where the element would be inserted after dropping\n      var placeholder = angular.element(\"<li class='dndPlaceholder'></li>\");\n      var placeholderNode = placeholder[0];\n      var listNode = element[0];\n\n      var horizontal = attr.dndHorizontalList && scope.$eval(attr.dndHorizontalList);\n      var externalSources = attr.dndExternalSources && scope.$eval(attr.dndExternalSources);\n\n      /**\n       * The dragover event is triggered \"every few hundred milliseconds\" while an element\n       * is being dragged over our list, or over an child element.\n       */\n      element.on('dragover', function(event) {\n        event = event.originalEvent || event;\n\n        if (!isDropAllowed(event)) {\n            return true;\n        }\n\n        // First of all, make sure that the placeholder is shown\n        // This is especially important if the list is empty\n        if (placeholderNode.parentNode != listNode) {\n          element.append(placeholder);\n        }\n\n        if (event.target !== listNode) {\n          // Try to find the node direct directly below the list node.\n          var listItemNode = event.target;\n          while (listItemNode.parentNode !== listNode && listItemNode.parentNode) {\n            listItemNode = listItemNode.parentNode;\n          }\n\n          if (listItemNode.parentNode === listNode && listItemNode !== placeholderNode) {\n            // If the mouse pointer is in the upper half of the child element,\n            // we place it before the child element, otherwise below it.\n            if (isMouseInFirstHalf(event, listItemNode)) {\n              listNode.insertBefore(placeholderNode, listItemNode);\n            } else {\n              listNode.insertBefore(placeholderNode, listItemNode.nextSibling);\n            }\n          }\n        } else {\n          // This branch is reached when we are dragging directly over the list element.\n          // Usually we wouldn't need to do anything here, but the IE does not fire it's\n          // events for the child element, only for the list directly. Therefore we repeat\n          // the positioning algorithm for IE here.\n          if (isMouseInFirstHalf(event, placeholderNode, true)) {\n            // Check if we should move the placeholder element one spot towards the top.\n            // Note that display none elements will have offsetTop and offsetHeight set to\n            // zero, therefore we need a special check for them.\n            while (placeholderNode.previousElementSibling\n                 && (isMouseInFirstHalf(event, placeholderNode.previousElementSibling, true)\n                 || placeholderNode.previousElementSibling.offsetHeight === 0)) {\n              listNode.insertBefore(placeholderNode, placeholderNode.previousElementSibling);\n            }\n          } else {\n            // Check if we should move the placeholder element one spot towards the bottom\n            while (placeholderNode.nextElementSibling &&\n                 !isMouseInFirstHalf(event, placeholderNode.nextElementSibling, true)) {\n              listNode.insertBefore(placeholderNode,\n                  placeholderNode.nextElementSibling.nextElementSibling);\n            }\n          }\n        }\n\n        // At this point we invoke the callback, which still can disallow the drop.\n        // We can't do this earlier because we want to pass the index of the placeholder.\n        if (attr.dndDragover && !invokeCallback(attr.dndDragover, event)) {\n          return stopDragover();\n        }\n\n        element.addClass(\"dndDragover\");\n        event.preventDefault();\n        event.stopPropagation();\n        return false;\n      });\n\n      /**\n       * When the element is dropped, we use the position of the placeholder element as the\n       * position where we insert the transferred data. This assumes that the list has exactly\n       * one child element per array element.\n       */\n      element.on('drop', function(event) {\n        event = event.originalEvent || event;\n\n        if (!isDropAllowed(event)) return true;\n\n        // The default behavior in Firefox is to interpret the dropped element as URL and\n        // forward to it. We want to prevent that even if our drop is aborted.\n        event.preventDefault();\n\n        // Unserialize the data that was serialized in dragstart. According to the HTML5 specs,\n        // the \"Text\" drag type will be converted to text/plain, but IE does not do that.\n        var data = event.dataTransfer.getData(\"Text\") || event.dataTransfer.getData(\"text/plain\");\n        var transferredObject;\n        try {\n          transferredObject = JSON.parse(data);\n        } catch(e) {\n          return stopDragover();\n        }\n\n        // Invoke the callback, which can transform the transferredObject and even abort the drop.\n        if (attr.dndDrop) {\n          transferredObject = invokeCallback(attr.dndDrop, event, transferredObject);\n          if (!transferredObject) {\n            return stopDragover();\n          }\n        }\n\n        // Retrieve the JSON array and insert the transferred object into it.\n        var targetArray = scope.$eval(attr.dndList);\n        scope.$apply(function() {\n          targetArray.splice(getPlaceholderIndex(), 0, transferredObject);\n        });\n\n        // Invoke the callback, after the transfered objrct is added to the new container.\n        if (attr.dndAfterDrop) {\n           invokeCallback(attr.dndAfterDrop, event, transferredObject);\n        }\n        // In Chrome on Windows the dropEffect will always be none...\n        // We have to determine the actual effect manually from the allowed effects\n        if (event.dataTransfer.dropEffect === \"none\") {\n          if (event.dataTransfer.effectAllowed === \"copy\" ||\n              event.dataTransfer.effectAllowed === \"move\") {\n            dndDropEffectWorkaround.dropEffect = event.dataTransfer.effectAllowed;\n          } else {\n            dndDropEffectWorkaround.dropEffect = event.ctrlKey ? \"copy\" : \"move\";\n          }\n        } else {\n          dndDropEffectWorkaround.dropEffect = event.dataTransfer.dropEffect;\n        }\n\n        // Clean up\n        stopDragover();\n        event.stopPropagation();\n        return false;\n      });\n\n      /**\n       * We have to remove the placeholder when the element is no longer dragged over our list. The\n       * problem is that the dragleave event is not only fired when the element leaves our list,\n       * but also when it leaves a child element -- so practically it's fired all the time. As a\n       * workaround we wait a few milliseconds and then check if the dndDragover class was added\n       * again. If it is there, dragover must have been called in the meantime, i.e. the element\n       * is still dragging over the list. If you know a better way of doing this, please tell me!\n       */\n      element.on('dragleave', function(event) {\n        event = event.originalEvent || event;\n\n        element.removeClass(\"dndDragover\");\n        $timeout(function() {\n          if (!element.hasClass(\"dndDragover\")) {\n            placeholder.remove();\n          }\n        }, 100);\n      });\n\n      /**\n       * Checks whether the mouse pointer is in the first half of the given target element.\n       *\n       * In Chrome we can just use offsetY, but in Firefox we have to use layerY, which only\n       * works if the child element has position relative. In IE the events are only triggered\n       * on the listNode instead of the listNodeItem, therefore the mouse positions are\n       * relative to the parent element of targetNode.\n       */\n      function isMouseInFirstHalf(event, targetNode, relativeToParent) {\n        var mousePointer = horizontal ? (event.offsetX || event.layerX)\n                                      : (event.offsetY || event.layerY);\n        var targetSize = horizontal ? targetNode.offsetWidth : targetNode.offsetHeight;\n        var targetPosition = horizontal ? targetNode.offsetLeft : targetNode.offsetTop;\n        targetPosition = relativeToParent ? targetPosition : 0;\n        return mousePointer < targetPosition + targetSize / 2;\n      }\n\n        /**\n         * Flowable-patched version of isMouseInFirstHalf that uses page and bounding client rect\n         * instead of the offsetX and layerX properties to determine which half of target the mouse pointer is hovering\n         * this is more natural since th method now actually works like above, but it also adds some mild\n         * flickering when sorting inside the list, why its still not in use.\n         */\n        function isMouseInFirstHalf_new(event, targetNode, relativeToParent) {\n            var targetNodeRect = targetNode.getBoundingClientRect();\n            if (horizontal) {\n                return (event.pageX - targetNodeRect.left) < (targetNodeRect.width / 2);\n            }\n            else {\n                return (event.pageY - targetNodeRect.top) < (targetNodeRect.height / 2);\n            }\n        }\n      /**\n       * We use the position of the placeholder node to determine at which position of the array the\n       * object needs to be inserted\n       */\n      function getPlaceholderIndex() {\n        return Array.prototype.indexOf.call(listNode.children, placeholderNode);\n      }\n\n      /**\n       * Checks various conditions that must be fulfilled for a drop to be allowed\n       */\n      function isDropAllowed(event) {\n        // Disallow drop from external source unless it's allowed explicitly.\n        if (!dndDragTypeWorkaround.isDragging && !externalSources) return false;\n\n        // Check mimetype. Usually we would use a custom drag type instead of Text, but IE doesn't\n        // support that.\n        if (!hasTextMimetype(event.dataTransfer.types)) return false;\n\n        // Now check the dnd-allowed-types against the type of the incoming element. For drops from\n        // external sources we don't know the type, so it will need to be checked via dnd-drop.\n        if (attr.dndAllowedTypes && dndDragTypeWorkaround.isDragging) {\n          var allowed = scope.$eval(attr.dndAllowedTypes);\n          if (angular.isArray(allowed) && allowed.indexOf(dndDragTypeWorkaround.dragType) === -1) {\n            return false;\n          }\n        }\n\n        // Check whether droping is disabled completely\n        if (attr.dndDisableIf && scope.$eval(attr.dndDisableIf)) return false;\n\n        return true;\n      }\n\n      /**\n       * Small helper function that cleans up if we aborted a drop.\n       */\n      function stopDragover() {\n        placeholder.remove();\n        element.removeClass(\"dndDragover\");\n        return true;\n      }\n\n      /**\n       * Invokes a callback with some interesting parameters and returns the callbacks return value.\n       */\n      function invokeCallback(expression, event, item) {\n        return $parse(expression)(scope, {\n          event: event,\n          index: getPlaceholderIndex(),\n          item: item || undefined,\n          external: !dndDragTypeWorkaround.isDragging,\n          type: dndDragTypeWorkaround.isDragging ? dndDragTypeWorkaround.dragType : undefined\n        });\n      }\n\n      /**\n       * Check if the dataTransfer object contains a drag type that we can handle. In old versions\n       * of IE the types collection will not even be there, so we just assume a drop is possible.\n       */\n      function hasTextMimetype(types) {\n        if (!types) return true;\n        for (var i = 0; i < types.length; i++) {\n          if (types[i] === \"Text\" || types[i] === \"text/plain\") return true;\n        }\n\n        return false;\n      }\n    };\n  }])\n\n  /**\n   * This workaround handles the fact that Internet Explorer does not support drag types other than\n   * \"Text\" and \"URL\". That means we can not know whether the data comes from one of our elements or\n   * is just some other data like a text selection. As a workaround we save the isDragging flag in\n   * here. When a dropover event occurs, we only allow the drop if we are already dragging, because\n   * that means the element is ours.\n   */\n  .factory('dndDragTypeWorkaround', function(){ return {} })\n\n  /**\n   * Chrome on Windows does not set the dropEffect field, which we need in dragend to determine\n   * whether a drag operation was successful. Therefore we have to maintain it in this global\n   * variable. The bug report for that has been open for years:\n   * https://code.google.com/p/chromium/issues/detail?id=39399\n   */\n  .factory('dndDropEffectWorkaround', function(){ return {} });\n"
  },
  {
    "path": "flowable-ui-web/idm/libs/angular-dragdrop_1.0.11/angular-dragdrop.js",
    "content": "/**\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\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell 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\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\n/**\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.11\n *\n * (c) 2013 Amit Gharat a.k.a codef0rmer <amit.2006.it@gmail.com> - amitgharat.wordpress.com\n */\n\n(function (window, angular, $, undefined) {\n    'use strict';\n\n    var jqyoui = angular.module('ngDragDrop', []).service('ngDragDropService', ['$timeout', '$parse', function($timeout, $parse) {\n        this.draggableScope = null;\n        this.droppableScope = null;\n\n        this.callEventCallback = function (scope, callbackName, event, ui) {\n            if (!callbackName) return;\n\n            var objExtract = extract(callbackName),\n                callback = objExtract.callback,\n                constructor = objExtract.constructor,\n                args = [event, ui].concat(objExtract.args);\n\n            // call either $scoped method i.e. $scope.dropCallback or constructor's method i.e. this.dropCallback.\n            // Removing scope.$apply call that was performance intensive (especially onDrag) and does not require it\n            // always. So call it within the callback if needed.\n            return (scope[callback] || scope[constructor][callback]).apply(scope, args);\n\n            function extract(callbackName) {\n                var atStartBracket = callbackName.indexOf('(') !== -1 ? callbackName.indexOf('(') : callbackName.length,\n                    atEndBracket = callbackName.lastIndexOf(')') !== -1 ? callbackName.lastIndexOf(')') : callbackName.length,\n                    args = callbackName.substring(atStartBracket + 1, atEndBracket), // matching function arguments inside brackets\n                    constructor = callbackName.match(/^[^.]+.\\s*/)[0].slice(0, -1); // matching a string upto a dot to check ctrl as syntax\n                constructor = scope[constructor] && typeof scope[constructor].constructor === 'function' ? constructor : null;\n\n                return {\n                    callback: callbackName.substring(constructor && constructor.length + 1 || 0, atStartBracket),\n                    args: $.map(args && args.split(',') || [], function(item) { return [$parse(item)(scope)]; }),\n                    constructor: constructor\n                }\n            }\n        };\n\n        this.invokeDrop = function ($draggable, $droppable, event, ui) {\n            var dragModel = '',\n                dropModel = '',\n                dragSettings = {},\n                dropSettings = {},\n                jqyoui_pos = null,\n                dragItem = {},\n                dropItem = {},\n                dragModelValue,\n                dropModelValue,\n                $droppableDraggable = null,\n                droppableScope = this.droppableScope,\n                draggableScope = this.draggableScope;\n\n            dragModel = $draggable.ngattr('ng-model');\n            dropModel = $droppable.ngattr('ng-model');\n            dragModelValue = draggableScope.$eval(dragModel);\n            dropModelValue = droppableScope.$eval(dropModel);\n\n            $droppableDraggable = $droppable.find('[jqyoui-draggable]:last,[data-jqyoui-draggable]:last');\n            dropSettings = droppableScope.$eval($droppable.attr('jqyoui-droppable') || $droppable.attr('data-jqyoui-droppable')) || [];\n            dragSettings = draggableScope.$eval($draggable.attr('jqyoui-draggable') || $draggable.attr('data-jqyoui-draggable')) || [];\n\n            // Helps pick up the right item\n            dragSettings.index = this.fixIndex(draggableScope, dragSettings, dragModelValue);\n            dropSettings.index = this.fixIndex(droppableScope, dropSettings, dropModelValue);\n\n            jqyoui_pos = angular.isArray(dragModelValue) ? dragSettings.index : null;\n            dragItem = angular.isArray(dragModelValue) ? dragModelValue[jqyoui_pos] : dragModelValue;\n\n            if (dragSettings.deepCopy) {\n                dragItem = angular.copy(dragItem);\n            }\n\n            if (angular.isArray(dropModelValue) && dropSettings && dropSettings.index !== undefined) {\n                dropItem = dropModelValue[dropSettings.index];\n            } else if (!angular.isArray(dropModelValue)) {\n                dropItem = dropModelValue;\n            } else {\n                dropItem = {};\n            }\n\n            if (dropSettings.deepCopy) {\n                dropItem = angular.copy(dropItem);\n            }\n\n            if (dragSettings.animate === true) {\n                this.move($draggable, $droppableDraggable.length > 0 ? $droppableDraggable : $droppable, null, 'fast', dropSettings, null);\n                this.move($droppableDraggable.length > 0 && !dropSettings.multiple ? $droppableDraggable : [], $draggable.parent('[jqyoui-droppable],[data-jqyoui-droppable]'), jqyoui.startXY, 'fast', dropSettings, angular.bind(this, function() {\n                    $timeout(angular.bind(this, function() {\n                        // Do not move this into move() to avoid flickering issue\n                        $draggable.css({'position': 'relative', 'left': '', 'top': ''});\n                        // Angular v1.2 uses ng-hide to hide an element not display property\n                        // so we've to manually remove display:none set in this.move()\n                        $droppableDraggable.css({'position': 'relative', 'left': '', 'top': '', 'display': $droppableDraggable.css('display') === 'none' ? '' : $droppableDraggable.css('display')});\n\n                        this.mutateDraggable(draggableScope, dropSettings, dragSettings, dragModel, dropModel, dropItem, $draggable);\n                        this.mutateDroppable(droppableScope, dropSettings, dragSettings, dropModel, dragItem, jqyoui_pos);\n                        this.callEventCallback(droppableScope, dropSettings.onDrop, event, ui);\n                    }));\n                }));\n            } else {\n                $timeout(angular.bind(this, function() {\n                    this.mutateDraggable(draggableScope, dropSettings, dragSettings, dragModel, dropModel, dropItem, $draggable);\n                    this.mutateDroppable(droppableScope, dropSettings, dragSettings, dropModel, dragItem, jqyoui_pos);\n                    this.callEventCallback(droppableScope, dropSettings.onDrop, event, ui);\n                }));\n            }\n        };\n\n        this.move = function($fromEl, $toEl, toPos, duration, dropSettings, callback) {\n            if ($fromEl.length === 0) {\n                if (callback) {\n                    window.setTimeout(function() {\n                        callback();\n                    }, 300);\n                }\n                return false;\n            }\n\n            var zIndex = $fromEl.css('z-index'),\n                fromPos = $fromEl[dropSettings.containment || 'offset'](),\n                displayProperty = $toEl.css('display'), // sometimes `display` is other than `block`\n                hadNgHideCls = $toEl.hasClass('ng-hide');\n\n            if (toPos === null && $toEl.length > 0) {\n                if (($toEl.attr('jqyoui-draggable') || $toEl.attr('data-jqyoui-draggable')) !== undefined && $toEl.ngattr('ng-model') !== undefined && $toEl.is(':visible') && dropSettings && dropSettings.multiple) {\n                    toPos = $toEl[dropSettings.containment || 'offset']();\n                    if (dropSettings.stack === false) {\n                        toPos.left+= $toEl.outerWidth(true);\n                    } else {\n                        toPos.top+= $toEl.outerHeight(true);\n                    }\n                } else {\n                    // Angular v1.2 uses ng-hide to hide an element\n                    // so we've to remove it in order to grab its position\n                    if (hadNgHideCls) $toEl.removeClass('ng-hide');\n                    toPos = $toEl.css({'visibility': 'hidden', 'display': 'block'})[dropSettings.containment || 'offset']();\n                    $toEl.css({'visibility': '','display': displayProperty});\n                }\n            }\n\n            $fromEl.css({'position': 'absolute', 'z-index': 9999})\n                .css(fromPos)\n                .animate(toPos, duration, function() {\n                    // Angular v1.2 uses ng-hide to hide an element\n                    // and as we remove it above, we've to put it back to\n                    // hide the element (while swapping) if it was hidden already\n                    // because we remove the display:none in this.invokeDrop()\n                    if (hadNgHideCls) $toEl.addClass('ng-hide');\n                    $fromEl.css('z-index', zIndex);\n                    if (callback) callback();\n                });\n        };\n\n        this.mutateDroppable = function(scope, dropSettings, dragSettings, dropModel, dragItem, jqyoui_pos) {\n            var dropModelValue = scope.$eval(dropModel);\n\n            scope.dndDragItem = dragItem;\n\n            if (angular.isArray(dropModelValue)) {\n                if (dropSettings && dropSettings.index >= 0) {\n                    dropModelValue[dropSettings.index] = dragItem;\n                } else {\n                    dropModelValue.push(dragItem);\n                }\n                if (dragSettings && dragSettings.placeholder === true) {\n                    dropModelValue[dropModelValue.length - 1]['jqyoui_pos'] = jqyoui_pos;\n                }\n            } else {\n                $parse(dropModel + ' = dndDragItem')(scope);\n                if (dragSettings && dragSettings.placeholder === true) {\n                    dropModelValue['jqyoui_pos'] = jqyoui_pos;\n                }\n            }\n        };\n\n        this.mutateDraggable = function(scope, dropSettings, dragSettings, dragModel, dropModel, dropItem, $draggable) {\n            var isEmpty = angular.equals(dropItem, {}) || !dropItem,\n                dragModelValue = scope.$eval(dragModel);\n\n            scope.dndDropItem = dropItem;\n\n            if (dragSettings && dragSettings.placeholder) {\n                if (dragSettings.placeholder != 'keep'){\n                    if (angular.isArray(dragModelValue) && dragSettings.index !== undefined) {\n                        dragModelValue[dragSettings.index] = dropItem;\n                    } else {\n                        $parse(dragModel + ' = dndDropItem')(scope);\n                    }\n                }\n            } else {\n                if (angular.isArray(dragModelValue)) {\n                    if (isEmpty) {\n                        if (dragSettings && ( dragSettings.placeholder !== true && dragSettings.placeholder !== 'keep' )) {\n                            dragModelValue.splice(dragSettings.index, 1);\n                        }\n                    } else {\n                        dragModelValue[dragSettings.index] = dropItem;\n                    }\n                } else {\n                    // Fix: LIST(object) to LIST(array) - model does not get updated using just scope[dragModel] = {...}\n                    // P.S.: Could not figure out why it happened\n                    $parse(dragModel + ' = dndDropItem')(scope);\n                    if (scope.$parent) {\n                        $parse(dragModel + ' = dndDropItem')(scope.$parent);\n                    }\n                }\n            }\n\n            $draggable.css({'z-index': '', 'left': '', 'top': ''});\n        };\n\n        this.fixIndex = function(scope, settings, modelValue) {\n            if (settings.applyFilter && angular.isArray(modelValue) && modelValue.length > 0) {\n                var dragModelValueFiltered = scope[settings.applyFilter](),\n                    lookup = dragModelValueFiltered[settings.index],\n                    actualIndex = undefined;\n\n                modelValue.forEach(function(item, i) {\n                    if (angular.equals(item, lookup)) {\n                        actualIndex = i;\n                    }\n                });\n\n                return actualIndex;\n            }\n\n            return settings.index;\n        };\n    }]).directive('jqyouiDraggable', ['ngDragDropService', function(ngDragDropService) {\n        return {\n            require: '?jqyouiDroppable',\n            restrict: 'A',\n            link: function(scope, element, attrs) {\n                var dragSettings, jqyouiOptions, zIndex;\n                var updateDraggable = function(newValue, oldValue) {\n                    if (newValue) {\n                        dragSettings = scope.$eval(element.attr('jqyoui-draggable') || element.attr('data-jqyoui-draggable')) || {};\n                        jqyouiOptions = scope.$eval(attrs.jqyouiOptions) || {};\n                        element\n                            .draggable({disabled: false})\n                            .draggable(jqyouiOptions)\n                            .draggable({\n                                start: function(event, ui) {\n                                    ngDragDropService.draggableScope = scope;\n                                    zIndex = angular.element(jqyouiOptions.helper ? ui.helper : this).css('z-index');\n                                    angular.element(jqyouiOptions.helper ? ui.helper : this).css('z-index', 9999);\n                                    jqyoui.startXY = angular.element(this)[dragSettings.containment || 'offset']();\n                                    ngDragDropService.callEventCallback(scope, dragSettings.onStart, event, ui);\n                                },\n                                stop: function(event, ui) {\n                                    angular.element(jqyouiOptions.helper ? ui.helper : this).css('z-index', zIndex);\n                                    ngDragDropService.callEventCallback(scope, dragSettings.onStop, event, ui);\n                                },\n                                drag: function(event, ui) {\n                                    ngDragDropService.callEventCallback(scope, dragSettings.onDrag, event, ui);\n                                }\n                            });\n                    } else {\n                        element.draggable({disabled: true});\n                    }\n                };\n                scope.$watch(function() { return scope.$eval(attrs.drag); }, updateDraggable);\n                updateDraggable();\n\n                element.on('$destroy', function() {\n                    element.draggable({disabled: true}).draggable('destroy');\n                });\n            }\n        };\n    }]).directive('jqyouiDroppable', ['ngDragDropService', '$q', function(ngDragDropService, $q) {\n        return {\n            restrict: 'A',\n            priority: 1,\n            link: function(scope, element, attrs) {\n                var dropSettings;\n                var updateDroppable = function(newValue, oldValue) {\n                    if (newValue) {\n                        dropSettings = scope.$eval(angular.element(element).attr('jqyoui-droppable') || angular.element(element).attr('data-jqyoui-droppable')) || {};\n                        element\n                            .droppable({disabled: false})\n                            .droppable(scope.$eval(attrs.jqyouiOptions) || {})\n                            .droppable({\n                                over: function(event, ui) {\n                                    ngDragDropService.callEventCallback(scope, dropSettings.onOver, event, ui);\n                                },\n                                out: function(event, ui) {\n                                    ngDragDropService.callEventCallback(scope, dropSettings.onOut, event, ui);\n                                },\n                                drop: function(event, ui) {\n                                    var beforeDropPromise = null;\n\n                                    if (dropSettings.beforeDrop) {\n                                        beforeDropPromise = ngDragDropService.callEventCallback(scope, dropSettings.beforeDrop, event, ui);\n                                    } else {\n                                        beforeDropPromise = (function() {\n                                            var deferred = $q.defer();\n                                            deferred.resolve();\n                                            return deferred.promise;\n                                        })();\n                                    }\n\n                                    beforeDropPromise.then(angular.bind(this, function() {\n                                        if (angular.element(ui.draggable).ngattr('ng-model') && attrs.ngModel) {\n                                            ngDragDropService.droppableScope = scope;\n                                            ngDragDropService.invokeDrop(angular.element(ui.draggable), angular.element(this), event, ui);\n                                        } else {\n                                            ngDragDropService.callEventCallback(scope, dropSettings.onDrop, event, ui);\n                                        }\n                                    }), function() {\n                                        ui.draggable.css({left: '', top: ''});\n                                    });\n                                }\n                            });\n                    } else {\n                        element.droppable({disabled: true});\n                    }\n                };\n\n                scope.$watch(function() { return scope.$eval(attrs.drop); }, updateDroppable);\n                updateDroppable();\n\n                element.on('$destroy', function() {\n                    element.droppable({disabled: true}).droppable('destroy');\n                });\n            }\n        };\n    }]);\n\n    angular.element.prototype.ngattr = function(name, value) {\n        var element = angular.element(this).get(0);\n\n        return element.getAttribute(name) || element.getAttribute('data-' + name);\n    };\n})(window, window.angular, window.jQuery);"
  },
  {
    "path": "flowable-ui-web/idm/libs/angular-gridster_0.11.7/angular-gridster.js",
    "content": "(function(angular) {\n\n    'use strict';\n\n    angular.module('gridster', [])\n\n        .constant('gridsterConfig', {\n            columns: 6, // number of columns in the grid\n            pushing: true, // whether to push other items out of the way\n            floating: true, // whether to automatically float items up so they stack\n            swapping: false, // whether or not to have items switch places instead of push down if they are the same size\n            width: 'auto', // width of the grid. \"auto\" will expand the grid to its parent container\n            colWidth: 'auto', // width of grid columns. \"auto\" will divide the width of the grid evenly among the columns\n            rowHeight: 'match', // height of grid rows. 'match' will make it the same as the column width, a numeric value will be interpreted as pixels, '/2' is half the column width, '*5' is five times the column width, etc.\n            margins: [10, 10], // margins in between grid items\n            outerMargin: true,\n            isMobile: false, // toggle mobile view\n            mobileBreakPoint: 600, // width threshold to toggle mobile mode\n            mobileModeEnabled: true, // whether or not to toggle mobile mode when screen width is less than mobileBreakPoint\n            minColumns: 1, // minimum amount of columns the grid can scale down to\n            minRows: 1, // minimum amount of rows to show if the grid is empty\n            maxRows: 100, // maximum amount of rows in the grid\n            defaultSizeX: 2, // default width of an item in columns\n            defaultSizeY: 1, // default height of an item in rows\n            minSizeX: 1, // minimum column width of an item\n            maxSizeX: null, // maximum column width of an item\n            minSizeY: 1, // minumum row height of an item\n            maxSizeY: null, // maximum row height of an item\n            saveGridItemCalculatedHeightInMobile: false, // grid item height in mobile display. true- to use the calculated height by sizeY given\n            resizable: { // options to pass to resizable handler\n                enabled: true,\n                handles: ['s', 'e', 'n', 'w', 'se', 'ne', 'sw', 'nw']\n            },\n            draggable: { // options to pass to draggable handler\n                enabled: true,\n                scrollSensitivity: 20, // Distance in pixels from the edge of the viewport after which the viewport should scroll, relative to pointer\n                scrollSpeed: 15 // Speed at which the window should scroll once the mouse pointer gets within scrollSensitivity distance\n            }\n        })\n\n        .controller('GridsterCtrl', ['gridsterConfig', '$timeout',\n            function(gridsterConfig, $timeout) {\n\n                var gridster = this;\n\n                /**\n                 * Create options from gridsterConfig constant\n                 */\n                angular.extend(this, gridsterConfig);\n\n                this.resizable = angular.extend({}, gridsterConfig.resizable || {});\n                this.draggable = angular.extend({}, gridsterConfig.draggable || {});\n\n                var flag = false;\n                this.layoutChanged = function() {\n                    if (flag) {\n                        return;\n                    }\n                    flag = true;\n                    $timeout(function() {\n                        flag = false;\n                        if (gridster.loaded) {\n                            gridster.floatItemsUp();\n                        }\n                        gridster.updateHeight(gridster.movingItem ? gridster.movingItem.sizeY : 0);\n                    });\n                };\n\n                /**\n                 * A positional array of the items in the grid\n                 */\n                this.grid = [];\n\n                /**\n                 * Clean up after yourself\n                 */\n                this.destroy = function() {\n                    if (this.grid) {\n                        this.grid.length = 0;\n                        this.grid = null;\n                    }\n                };\n\n                /**\n                 * Overrides default options\n                 *\n                 * @param {object} options The options to override\n                 */\n                this.setOptions = function(options) {\n                    if (!options) {\n                        return;\n                    }\n\n                    options = angular.extend({}, options);\n\n                    // all this to avoid using jQuery...\n                    if (options.draggable) {\n                        angular.extend(this.draggable, options.draggable);\n                        delete(options.draggable);\n                    }\n                    if (options.resizable) {\n                        angular.extend(this.resizable, options.resizable);\n                        delete(options.resizable);\n                    }\n\n                    angular.extend(this, options);\n\n                    if (!this.margins || this.margins.length !== 2) {\n                        this.margins = [0, 0];\n                    } else {\n                        for (var x = 0, l = this.margins.length; x < l; ++x) {\n                            this.margins[x] = parseInt(this.margins[x], 10);\n                            if (isNaN(this.margins[x])) {\n                                this.margins[x] = 0;\n                            }\n                        }\n                    }\n                };\n\n                /**\n                 * Check if item can occupy a specified position in the grid\n                 *\n                 * @param {object} item The item in question\n                 * @param {number} row The row index\n                 * @param {number} column The column index\n                 * @returns {boolean} True if if item fits\n                 */\n                this.canItemOccupy = function(item, row, column) {\n                    return row > -1 && column > -1 && item.sizeX + column <= this.columns && item.sizeY + row <= this.maxRows;\n                };\n\n                /**\n                 * Set the item in the first suitable position\n                 *\n                 * @param {object} item The item to insert\n                 */\n                this.autoSetItemPosition = function(item) {\n                    // walk through each row and column looking for a place it will fit\n                    for (var rowIndex = 0; rowIndex < this.maxRows; ++rowIndex) {\n                        for (var colIndex = 0; colIndex < this.columns; ++colIndex) {\n                            // only insert if position is not already taken and it can fit\n                            var items = this.getItems(rowIndex, colIndex, item.sizeX, item.sizeY, item);\n                            if (items.length === 0 && this.canItemOccupy(item, rowIndex, colIndex)) {\n                                this.putItem(item, rowIndex, colIndex);\n                                return;\n                            }\n                        }\n                    }\n                    throw new Error('Unable to place item!');\n                };\n\n                /**\n                 * Gets items at a specific coordinate\n                 *\n                 * @param {number} row\n                 * @param {number} column\n                 * @param {number} sizeX\n                 * @param {number} sizeY\n                 * @param {array} excludeItems An array of items to exclude from selection\n                 * @returns {array} Items that match the criteria\n                 */\n                this.getItems = function(row, column, sizeX, sizeY, excludeItems) {\n                    var items = [];\n                    if (!sizeX || !sizeY) {\n                        sizeX = sizeY = 1;\n                    }\n                    if (excludeItems && !(excludeItems instanceof Array)) {\n                        excludeItems = [excludeItems];\n                    }\n                    for (var h = 0; h < sizeY; ++h) {\n                        for (var w = 0; w < sizeX; ++w) {\n                            var item = this.getItem(row + h, column + w, excludeItems);\n                            if (item && (!excludeItems || excludeItems.indexOf(item) === -1) && items.indexOf(item) === -1) {\n                                items.push(item);\n                            }\n                        }\n                    }\n                    return items;\n                };\n\n                this.getBoundingBox = function(items) {\n\n                    if (items.length === 0) {\n                        return null;\n                    }\n                    if (items.length === 1) {\n                        return {\n                            row: items[0].row,\n                            col: items[0].col,\n                            sizeY: items[0].sizeY,\n                            sizeX: items[0].sizeX\n                        };\n                    }\n\n                    var maxRow = 0;\n                    var maxCol = 0;\n                    var minRow = 9999;\n                    var minCol = 9999;\n\n                    for (var i = 0, l = items.length; i < l; ++i) {\n                        var item = items[i];\n                        minRow = Math.min(item.row, minRow);\n                        minCol = Math.min(item.col, minCol);\n                        maxRow = Math.max(item.row + item.sizeY, maxRow);\n                        maxCol = Math.max(item.col + item.sizeX, maxCol);\n                    }\n\n                    return {\n                        row: minRow,\n                        col: minCol,\n                        sizeY: maxRow - minRow,\n                        sizeX: maxCol - minCol\n                    };\n                };\n\n\n                /**\n                 * Removes an item from the grid\n                 *\n                 * @param {object} item\n                 */\n                this.removeItem = function(item) {\n                    for (var rowIndex = 0, l = this.grid.length; rowIndex < l; ++rowIndex) {\n                        var columns = this.grid[rowIndex];\n                        if (!columns) {\n                            continue;\n                        }\n                        var index = columns.indexOf(item);\n                        if (index !== -1) {\n                            columns[index] = null;\n                            break;\n                        }\n                    }\n                    this.layoutChanged();\n                };\n\n                /**\n                 * Returns the item at a specified coordinate\n                 *\n                 * @param {number} row\n                 * @param {number} column\n                 * @param {array} excludeitems Items to exclude from selection\n                 * @returns {object} The matched item or null\n                 */\n                this.getItem = function(row, column, excludeItems) {\n                    if (excludeItems && !(excludeItems instanceof Array)) {\n                        excludeItems = [excludeItems];\n                    }\n                    var sizeY = 1;\n                    while (row > -1) {\n                        var sizeX = 1,\n                            col = column;\n                        while (col > -1) {\n                            var items = this.grid[row];\n                            if (items) {\n                                var item = items[col];\n                                if (item && (!excludeItems || excludeItems.indexOf(item) === -1) && item.sizeX >= sizeX && item.sizeY >= sizeY) {\n                                    return item;\n                                }\n                            }\n                            ++sizeX;\n                            --col;\n                        }\n                        --row;\n                        ++sizeY;\n                    }\n                    return null;\n                };\n\n                /**\n                 * Insert an array of items into the grid\n                 *\n                 * @param {array} items An array of items to insert\n                 */\n                this.putItems = function(items) {\n                    for (var i = 0, l = items.length; i < l; ++i) {\n                        this.putItem(items[i]);\n                    }\n                };\n\n                /**\n                 * Insert a single item into the grid\n                 *\n                 * @param {object} item The item to insert\n                 * @param {number} row (Optional) Specifies the items row index\n                 * @param {number} column (Optional) Specifies the items column index\n                 * @param {array} ignoreItems\n                 */\n                this.putItem = function(item, row, column, ignoreItems) {\n                    if (typeof row === 'undefined' || row === null) {\n                        row = item.row;\n                        column = item.col;\n                        if (typeof row === 'undefined' || row === null) {\n                            this.autoSetItemPosition(item);\n                            return;\n                        }\n                    }\n                    if (!this.canItemOccupy(item, row, column)) {\n                        column = Math.min(this.columns - item.sizeX, Math.max(0, column));\n                        row = Math.min(this.maxRows - item.sizeY, Math.max(0, row));\n                    }\n\n                    if (item.oldRow !== null && typeof item.oldRow !== 'undefined') {\n                        var samePosition = item.oldRow === row && item.oldColumn === column;\n                        var inGrid = this.grid[row] && this.grid[row][column] === item;\n                        if (samePosition && inGrid) {\n                            item.row = row;\n                            item.col = column;\n                            return;\n                        } else {\n                            // remove from old position\n                            var oldRow = this.grid[item.oldRow];\n                            if (oldRow && oldRow[item.oldColumn] === item) {\n                                delete oldRow[item.oldColumn];\n                            }\n                        }\n                    }\n\n                    item.oldRow = item.row = row;\n                    item.oldColumn = item.col = column;\n\n                    this.moveOverlappingItems(item, ignoreItems);\n\n                    if (!this.grid[row]) {\n                        this.grid[row] = [];\n                    }\n                    this.grid[row][column] = item;\n\n                    if (this.movingItem === item) {\n                        this.floatItemUp(item);\n                    }\n                    this.layoutChanged();\n                };\n\n                /**\n                 * Trade row and column if item1 with item2\n                 *\n                 * @param {object} item1\n                 * @param {object} item2\n                 */\n                this.swapItems = function(item1, item2) {\n                    this.grid[item1.row][item1.col] = item2;\n                    this.grid[item2.row][item2.col] = item1;\n\n                    var item1Row = item1.row;\n                    var item1Col = item1.col;\n                    item1.row = item2.row;\n                    item1.col = item2.col;\n                    item2.row = item1Row;\n                    item2.col = item1Col;\n                };\n\n                /**\n                 * Prevents items from being overlapped\n                 *\n                 * @param {object} item The item that should remain\n                 * @param {array} ignoreItems\n                 */\n                this.moveOverlappingItems = function(item, ignoreItems) {\n                    if (ignoreItems) {\n                        if (ignoreItems.indexOf(item) === -1) {\n                            ignoreItems = ignoreItems.slice(0);\n                            ignoreItems.push(item);\n                        }\n                    } else {\n                        ignoreItems = [item];\n                    }\n                    var overlappingItems = this.getItems(\n                        item.row,\n                        item.col,\n                        item.sizeX,\n                        item.sizeY,\n                        ignoreItems\n                    );\n                    this.moveItemsDown(overlappingItems, item.row + item.sizeY, ignoreItems);\n                };\n\n                /**\n                 * Moves an array of items to a specified row\n                 *\n                 * @param {array} items The items to move\n                 * @param {number} newRow The target row\n                 * @param {array} ignoreItems\n                 */\n                this.moveItemsDown = function(items, newRow, ignoreItems) {\n                    if (!items || items.length === 0) {\n                        return;\n                    }\n                    items.sort(function(a, b) {\n                        return a.row - b.row;\n                    });\n                    ignoreItems = ignoreItems ? ignoreItems.slice(0) : [];\n                    var topRows = {},\n                        item, i, l;\n                    // calculate the top rows in each column\n                    for (i = 0, l = items.length; i < l; ++i) {\n                        item = items[i];\n                        var topRow = topRows[item.col];\n                        if (typeof topRow === 'undefined' || item.row < topRow) {\n                            topRows[item.col] = item.row;\n                        }\n                    }\n                    // move each item down from the top row in its column to the row\n                    for (i = 0, l = items.length; i < l; ++i) {\n                        item = items[i];\n                        var rowsToMove = newRow - topRows[item.col];\n                        this.moveItemDown(item, item.row + rowsToMove, ignoreItems);\n                        ignoreItems.push(item);\n                    }\n                };\n\n                this.moveItemDown = function(item, newRow, ignoreItems) {\n                    if (item.row >= newRow) {\n                        return;\n                    }\n                    while (item.row < newRow) {\n                        ++item.row;\n                        this.moveOverlappingItems(item, ignoreItems);\n                    }\n                    this.putItem(item, item.row, item.col, ignoreItems);\n                };\n\n                /**\n                 * Moves all items up as much as possible\n                 */\n                this.floatItemsUp = function() {\n                    if (this.floating === false) {\n                        return;\n                    }\n                    for (var rowIndex = 0, l = this.grid.length; rowIndex < l; ++rowIndex) {\n                        var columns = this.grid[rowIndex];\n                        if (!columns) {\n                            continue;\n                        }\n                        for (var colIndex = 0, len = columns.length; colIndex < len; ++colIndex) {\n                            var item = columns[colIndex];\n                            if (item) {\n                                this.floatItemUp(item);\n                            }\n                        }\n                    }\n                };\n\n                /**\n                 * Float an item up to the most suitable row\n                 *\n                 * @param {object} item The item to move\n                 */\n                this.floatItemUp = function(item) {\n                    if (this.floating === false) {\n                        return;\n                    }\n                    var colIndex = item.col,\n                        sizeY = item.sizeY,\n                        sizeX = item.sizeX,\n                        bestRow = null,\n                        bestColumn = null,\n                        rowIndex = item.row - 1;\n\n                    while (rowIndex > -1) {\n                        var items = this.getItems(rowIndex, colIndex, sizeX, sizeY, item);\n                        if (items.length !== 0) {\n                            break;\n                        }\n                        bestRow = rowIndex;\n                        bestColumn = colIndex;\n                        --rowIndex;\n                    }\n                    if (bestRow !== null) {\n                        this.putItem(item, bestRow, bestColumn);\n                    }\n                };\n\n                /**\n                 * Update gridsters height\n                 *\n                 * @param {number} plus (Optional) Additional height to add\n                 */\n                this.updateHeight = function(plus) {\n                    var maxHeight = this.minRows;\n                    plus = plus || 0;\n                    for (var rowIndex = this.grid.length; rowIndex >= 0; --rowIndex) {\n                        var columns = this.grid[rowIndex];\n                        if (!columns) {\n                            continue;\n                        }\n                        for (var colIndex = 0, len = columns.length; colIndex < len; ++colIndex) {\n                            if (columns[colIndex]) {\n                                maxHeight = Math.max(maxHeight, rowIndex + plus + columns[colIndex].sizeY);\n                            }\n                        }\n                    }\n                    this.gridHeight = this.maxRows - maxHeight > 0 ? Math.min(this.maxRows, maxHeight) : Math.max(this.maxRows, maxHeight);\n                };\n\n                /**\n                 * Returns the number of rows that will fit in given amount of pixels\n                 *\n                 * @param {number} pixels\n                 * @param {boolean} ceilOrFloor (Optional) Determines rounding method\n                 */\n                this.pixelsToRows = function(pixels, ceilOrFloor) {\n                    if (ceilOrFloor === true) {\n                        return Math.ceil(pixels / this.curRowHeight);\n                    } else if (ceilOrFloor === false) {\n                        return Math.floor(pixels / this.curRowHeight);\n                    }\n\n                    return Math.round(pixels / this.curRowHeight);\n                };\n\n                /**\n                 * Returns the number of columns that will fit in a given amount of pixels\n                 *\n                 * @param {number} pixels\n                 * @param {boolean} ceilOrFloor (Optional) Determines rounding method\n                 * @returns {number} The number of columns\n                 */\n                this.pixelsToColumns = function(pixels, ceilOrFloor) {\n                    if (ceilOrFloor === true) {\n                        return Math.ceil(pixels / this.curColWidth);\n                    } else if (ceilOrFloor === false) {\n                        return Math.floor(pixels / this.curColWidth);\n                    }\n\n                    return Math.round(pixels / this.curColWidth);\n                };\n\n                // unified input handling\n                // adopted from a msdn blogs sample\n                this.unifiedInput = function(target, startEvent, moveEvent, endEvent) {\n                    var lastXYById = {};\n\n                    //  Opera doesn't have Object.keys so we use this wrapper\n                    var numberOfKeys = function(theObject) {\n                        if (Object.keys) {\n                            return Object.keys(theObject).length;\n                        }\n\n                        var n = 0,\n                            key;\n                        for (key in theObject) {\n                            ++n;\n                        }\n\n                        return n;\n                    };\n\n                    //  this calculates the delta needed to convert pageX/Y to offsetX/Y because offsetX/Y don't exist in the TouchEvent object or in Firefox's MouseEvent object\n                    var computeDocumentToElementDelta = function(theElement) {\n                        var elementLeft = 0;\n                        var elementTop = 0;\n                        var oldIEUserAgent = navigator.userAgent.match(/\\bMSIE\\b/);\n\n                        for (var offsetElement = theElement; offsetElement != null; offsetElement = offsetElement.offsetParent) {\n                            //  the following is a major hack for versions of IE less than 8 to avoid an apparent problem on the IEBlog with double-counting the offsets\n                            //  this may not be a general solution to IE7's problem with offsetLeft/offsetParent\n                            if (oldIEUserAgent &&\n                                (!document.documentMode || document.documentMode < 8) &&\n                                offsetElement.currentStyle.position === 'relative' && offsetElement.offsetParent && offsetElement.offsetParent.currentStyle.position === 'relative' && offsetElement.offsetLeft === offsetElement.offsetParent.offsetLeft) {\n                                // add only the top\n                                elementTop += offsetElement.offsetTop;\n                            } else {\n                                elementLeft += offsetElement.offsetLeft;\n                                elementTop += offsetElement.offsetTop;\n                            }\n                        }\n\n                        return {\n                            x: elementLeft,\n                            y: elementTop\n                        };\n                    };\n\n                    //  cache the delta from the document to our event target (reinitialized each mousedown/MSPointerDown/touchstart)\n                    var documentToTargetDelta = computeDocumentToElementDelta(target);\n\n                    //  common event handler for the mouse/pointer/touch models and their down/start, move, up/end, and cancel events\n                    var doEvent = function(theEvtObj) {\n\n                        if (theEvtObj.type === 'mousemove' && numberOfKeys(lastXYById) === 0) {\n                            return;\n                        }\n\n                        var prevent = true;\n\n                        var pointerList = theEvtObj.changedTouches ? theEvtObj.changedTouches : [theEvtObj];\n                        for (var i = 0; i < pointerList.length; ++i) {\n                            var pointerObj = pointerList[i];\n                            var pointerId = (typeof pointerObj.identifier !== 'undefined') ? pointerObj.identifier : (typeof pointerObj.pointerId !== 'undefined') ? pointerObj.pointerId : 1;\n\n                            //  use the pageX/Y coordinates to compute target-relative coordinates when we have them (in ie < 9, we need to do a little work to put them there)\n                            if (typeof pointerObj.pageX === 'undefined') {\n                                //  initialize assuming our source element is our target\n                                pointerObj.pageX = pointerObj.offsetX + documentToTargetDelta.x;\n                                pointerObj.pageY = pointerObj.offsetY + documentToTargetDelta.y;\n\n                                if (pointerObj.srcElement.offsetParent === target && document.documentMode && document.documentMode === 8 && pointerObj.type === 'mousedown') {\n                                    //  source element is a child piece of VML, we're in IE8, and we've not called setCapture yet - add the origin of the source element\n                                    pointerObj.pageX += pointerObj.srcElement.offsetLeft;\n                                    pointerObj.pageY += pointerObj.srcElement.offsetTop;\n                                } else if (pointerObj.srcElement !== target && !document.documentMode || document.documentMode < 8) {\n                                    //  source element isn't the target (most likely it's a child piece of VML) and we're in a version of IE before IE8 -\n                                    //  the offsetX/Y values are unpredictable so use the clientX/Y values and adjust by the scroll offsets of its parents\n                                    //  to get the document-relative coordinates (the same as pageX/Y)\n                                    var sx = -2,\n                                        sy = -2; // adjust for old IE's 2-pixel border\n                                    for (var scrollElement = pointerObj.srcElement; scrollElement !== null; scrollElement = scrollElement.parentNode) {\n                                        sx += scrollElement.scrollLeft ? scrollElement.scrollLeft : 0;\n                                        sy += scrollElement.scrollTop ? scrollElement.scrollTop : 0;\n                                    }\n\n                                    pointerObj.pageX = pointerObj.clientX + sx;\n                                    pointerObj.pageY = pointerObj.clientY + sy;\n                                }\n                            }\n\n\n                            var pageX = pointerObj.pageX;\n                            var pageY = pointerObj.pageY;\n\n                            if (theEvtObj.type.match(/(start|down)$/i)) {\n                                //  clause for processing MSPointerDown, touchstart, and mousedown\n\n                                //  refresh the document-to-target delta on start in case the target has moved relative to document\n                                documentToTargetDelta = computeDocumentToElementDelta(target);\n\n                                //  protect against failing to get an up or end on this pointerId\n                                if (lastXYById[pointerId]) {\n                                    if (endEvent) {\n                                        endEvent({\n                                            target: theEvtObj.target,\n                                            which: theEvtObj.which,\n                                            pointerId: pointerId,\n                                            pageX: pageX,\n                                            pageY: pageY\n                                        });\n                                    }\n\n                                    delete lastXYById[pointerId];\n                                }\n\n                                if (startEvent) {\n                                    if (prevent) {\n                                        prevent = startEvent({\n                                            target: theEvtObj.target,\n                                            which: theEvtObj.which,\n                                            pointerId: pointerId,\n                                            pageX: pageX,\n                                            pageY: pageY\n                                        });\n                                    }\n                                }\n\n                                //  init last page positions for this pointer\n                                lastXYById[pointerId] = {\n                                    x: pageX,\n                                    y: pageY\n                                };\n\n                                // IE pointer model\n                                if (target.msSetPointerCapture) {\n                                    target.msSetPointerCapture(pointerId);\n                                } else if (theEvtObj.type === 'mousedown' && numberOfKeys(lastXYById) === 1) {\n                                    if (useSetReleaseCapture) {\n                                        target.setCapture(true);\n                                    } else {\n                                        document.addEventListener('mousemove', doEvent, false);\n                                        document.addEventListener('mouseup', doEvent, false);\n                                    }\n                                }\n                            } else if (theEvtObj.type.match(/move$/i)) {\n                                //  clause handles mousemove, MSPointerMove, and touchmove\n\n                                if (lastXYById[pointerId] && !(lastXYById[pointerId].x === pageX && lastXYById[pointerId].y === pageY)) {\n                                    //  only extend if the pointer is down and it's not the same as the last point\n\n                                    if (moveEvent && prevent) {\n                                        prevent = moveEvent({\n                                            target: theEvtObj.target,\n                                            which: theEvtObj.which,\n                                            pointerId: pointerId,\n                                            pageX: pageX,\n                                            pageY: pageY\n                                        });\n                                    }\n\n                                    //  update last page positions for this pointer\n                                    lastXYById[pointerId].x = pageX;\n                                    lastXYById[pointerId].y = pageY;\n                                }\n                            } else if (lastXYById[pointerId] && theEvtObj.type.match(/(up|end|cancel)$/i)) {\n                                //  clause handles up/end/cancel\n\n                                if (endEvent && prevent) {\n                                    prevent = endEvent({\n                                        target: theEvtObj.target,\n                                        which: theEvtObj.which,\n                                        pointerId: pointerId,\n                                        pageX: pageX,\n                                        pageY: pageY\n                                    });\n                                }\n\n                                //  delete last page positions for this pointer\n                                delete lastXYById[pointerId];\n\n                                //  in the Microsoft pointer model, release the capture for this pointer\n                                //  in the mouse model, release the capture or remove document-level event handlers if there are no down points\n                                //  nothing is required for the iOS touch model because capture is implied on touchstart\n                                if (target.msReleasePointerCapture) {\n                                    target.msReleasePointerCapture(pointerId);\n                                } else if (theEvtObj.type === 'mouseup' && numberOfKeys(lastXYById) === 0) {\n                                    if (useSetReleaseCapture) {\n                                        target.releaseCapture();\n                                    } else {\n                                        document.removeEventListener('mousemove', doEvent, false);\n                                        document.removeEventListener('mouseup', doEvent, false);\n                                    }\n                                }\n                            }\n                        }\n\n                        if (prevent) {\n                            if (theEvtObj.preventDefault) {\n                                theEvtObj.preventDefault();\n                            }\n\n                            if (theEvtObj.preventManipulation) {\n                                theEvtObj.preventManipulation();\n                            }\n\n                            if (theEvtObj.preventMouseEvent) {\n                                theEvtObj.preventMouseEvent();\n                            }\n                        }\n                    };\n\n                    var useSetReleaseCapture = false;\n                    // saving the settings for contentZooming and touchaction before activation\n                    var contentZooming, msTouchAction;\n\n                    this.enable = function() {\n\n                        if (window.navigator.msPointerEnabled) {\n                            //  Microsoft pointer model\n                            target.addEventListener('MSPointerDown', doEvent, false);\n                            target.addEventListener('MSPointerMove', doEvent, false);\n                            target.addEventListener('MSPointerUp', doEvent, false);\n                            target.addEventListener('MSPointerCancel', doEvent, false);\n\n                            //  css way to prevent panning in our target area\n                            if (typeof target.style.msContentZooming !== 'undefined') {\n                                contentZooming = target.style.msContentZooming;\n                                target.style.msContentZooming = 'none';\n                            }\n\n                            //  new in Windows Consumer Preview: css way to prevent all built-in touch actions on our target\n                            //  without this, you cannot touch draw on the element because IE will intercept the touch events\n                            if (typeof target.style.msTouchAction !== 'undefined') {\n                                msTouchAction = target.style.msTouchAction;\n                                target.style.msTouchAction = 'none';\n                            }\n                        } else if (target.addEventListener) {\n                            //  iOS touch model\n                            target.addEventListener('touchstart', doEvent, false);\n                            target.addEventListener('touchmove', doEvent, false);\n                            target.addEventListener('touchend', doEvent, false);\n                            target.addEventListener('touchcancel', doEvent, false);\n\n                            //  mouse model\n                            target.addEventListener('mousedown', doEvent, false);\n\n                            //  mouse model with capture\n                            //  rejecting gecko because, unlike ie, firefox does not send events to target when the mouse is outside target\n                            if (target.setCapture && !window.navigator.userAgent.match(/\\bGecko\\b/)) {\n                                useSetReleaseCapture = true;\n\n                                target.addEventListener('mousemove', doEvent, false);\n                                target.addEventListener('mouseup', doEvent, false);\n                            }\n                        } else if (target.attachEvent && target.setCapture) {\n                            //  legacy IE mode - mouse with capture\n                            useSetReleaseCapture = true;\n                            target.attachEvent('onmousedown', function() {\n                                doEvent(window.event);\n                                window.event.returnValue = false;\n                                return false;\n                            });\n                            target.attachEvent('onmousemove', function() {\n                                doEvent(window.event);\n                                window.event.returnValue = false;\n                                return false;\n                            });\n                            target.attachEvent('onmouseup', function() {\n                                doEvent(window.event);\n                                window.event.returnValue = false;\n                                return false;\n                            });\n                        }\n                    };\n\n                    this.disable = function() {\n                        if (window.navigator.msPointerEnabled) {\n                            //  Microsoft pointer model\n                            target.removeEventListener('MSPointerDown', doEvent, false);\n                            target.removeEventListener('MSPointerMove', doEvent, false);\n                            target.removeEventListener('MSPointerUp', doEvent, false);\n                            target.removeEventListener('MSPointerCancel', doEvent, false);\n\n                            //  reset zooming to saved value\n                            if (contentZooming) {\n                                target.style.msContentZooming = contentZooming;\n                            }\n\n                            // reset touch action setting\n                            if (msTouchAction) {\n                                target.style.msTouchAction = msTouchAction;\n                            }\n                        } else if (target.removeEventListener) {\n                            //  iOS touch model\n                            target.removeEventListener('touchstart', doEvent, false);\n                            target.removeEventListener('touchmove', doEvent, false);\n                            target.removeEventListener('touchend', doEvent, false);\n                            target.removeEventListener('touchcancel', doEvent, false);\n\n                            //  mouse model\n                            target.removeEventListener('mousedown', doEvent, false);\n\n                            //  mouse model with capture\n                            //  rejecting gecko because, unlike ie, firefox does not send events to target when the mouse is outside target\n                            if (target.setCapture && !window.navigator.userAgent.match(/\\bGecko\\b/)) {\n                                useSetReleaseCapture = true;\n\n                                target.removeEventListener('mousemove', doEvent, false);\n                                target.removeEventListener('mouseup', doEvent, false);\n                            }\n                        } else if (target.detachEvent && target.setCapture) {\n                            //  legacy IE mode - mouse with capture\n                            useSetReleaseCapture = true;\n                            target.detachEvent('onmousedown');\n                            target.detachEvent('onmousemove');\n                            target.detachEvent('onmouseup');\n                        }\n                    };\n\n                    return this;\n                };\n\n            }\n        ])\n\n    /**\n     * The gridster directive\n     *\n     * @param {object} $parse\n     * @param {object} $timeout\n     */\n        .directive('gridster', ['$timeout', '$rootScope', '$window',\n            function($timeout, $rootScope, $window) {\n                return {\n                    restrict: 'EAC',\n                    // without transclude, some child items may lose their parent scope\n                    transclude: true,\n                    replace: true,\n                    template: '<div ng-class=\"gridsterClass()\"><div ng-style=\"previewStyle()\" class=\"gridster-item gridster-preview-holder\"></div><div class=\"gridster-content\" ng-transclude></div></div>',\n                    controller: 'GridsterCtrl',\n                    controllerAs: 'gridster',\n                    scope: {\n                        config: '=?gridster'\n                    },\n                    compile: function() {\n\n                        return function(scope, $elem, attrs, gridster) {\n                            gridster.loaded = false;\n\n                            scope.gridsterClass = function() {\n                                return {\n                                    gridster: true,\n                                    'gridster-desktop': !gridster.isMobile,\n                                    'gridster-mobile': gridster.isMobile,\n                                    'gridster-loaded': gridster.loaded\n                                };\n                            };\n\n                            /**\n                             * @returns {Object} style object for preview element\n                             */\n                            scope.previewStyle = function() {\n                                if (!gridster.movingItem) {\n                                    return {\n                                        display: 'none'\n                                    };\n                                }\n\n                                return {\n                                    display: 'block',\n                                    height: (gridster.movingItem.sizeY * gridster.curRowHeight - gridster.margins[0]) + 'px',\n                                    width: (gridster.movingItem.sizeX * gridster.curColWidth - gridster.margins[1]) + 'px',\n                                    top: (gridster.movingItem.row * gridster.curRowHeight + (gridster.outerMargin ? gridster.margins[0] : 0)) + 'px',\n                                    left: (gridster.movingItem.col * gridster.curColWidth + (gridster.outerMargin ? gridster.margins[1] : 0)) + 'px'\n                                };\n                            };\n\n                            var refresh = function() {\n                                gridster.setOptions(scope.config);\n\n                                // resolve \"auto\" & \"match\" values\n                                if (gridster.width === 'auto') {\n                                    gridster.curWidth = $elem[0].offsetWidth || parseInt($elem.css('width'), 10);\n                                } else {\n                                    gridster.curWidth = gridster.width;\n                                }\n\n                                if (gridster.colWidth === 'auto') {\n                                    gridster.curColWidth = (gridster.curWidth + (gridster.outerMargin ? -gridster.margins[1] : gridster.margins[1])) / gridster.columns;\n                                } else {\n                                    gridster.curColWidth = gridster.colWidth;\n                                }\n\n                                gridster.curRowHeight = gridster.rowHeight;\n                                if (typeof gridster.rowHeight === 'string') {\n                                    if (gridster.rowHeight === 'match') {\n                                        gridster.curRowHeight = Math.round(gridster.curColWidth);\n                                    } else if (gridster.rowHeight.indexOf('*') !== -1) {\n                                        gridster.curRowHeight = Math.round(gridster.curColWidth * gridster.rowHeight.replace('*', '').replace(' ', ''));\n                                    } else if (gridster.rowHeight.indexOf('/') !== -1) {\n                                        gridster.curRowHeight = Math.round(gridster.curColWidth / gridster.rowHeight.replace('/', '').replace(' ', ''));\n                                    }\n                                }\n\n                                gridster.isMobile = gridster.mobileModeEnabled && gridster.curWidth <= gridster.mobileBreakPoint;\n\n                                // loop through all items and reset their CSS\n                                for (var rowIndex = 0, l = gridster.grid.length; rowIndex < l; ++rowIndex) {\n                                    var columns = gridster.grid[rowIndex];\n                                    if (!columns) {\n                                        continue;\n                                    }\n\n                                    for (var colIndex = 0, len = columns.length; colIndex < len; ++colIndex) {\n                                        if (columns[colIndex]) {\n                                            var item = columns[colIndex];\n                                            item.setElementPosition();\n                                            item.setElementSizeY();\n                                            item.setElementSizeX();\n                                        }\n                                    }\n                                }\n\n                                updateHeight();\n                            };\n\n                            // update grid items on config changes\n                            scope.$watch('config', refresh, true);\n\n                            scope.$watch('config.draggable', function() {\n                                $rootScope.$broadcast('gridster-draggable-changed');\n                            }, true);\n\n                            scope.$watch('config.resizable', function() {\n                                $rootScope.$broadcast('gridster-resizable-changed');\n                            }, true);\n\n                            var updateHeight = function() {\n                                $elem.css('height', (gridster.gridHeight * gridster.curRowHeight) + (gridster.outerMargin ? gridster.margins[0] : -gridster.margins[0]) + 'px');\n                            };\n\n                            scope.$watch('gridster.gridHeight', updateHeight);\n\n                            scope.$watch('gridster.movingItem', function() {\n                                gridster.updateHeight(gridster.movingItem ? gridster.movingItem.sizeY : 0);\n                            });\n\n                            var prevWidth = $elem[0].offsetWidth || parseInt($elem.css('width'), 10);\n\n                            function resize() {\n                                var width = $elem[0].offsetWidth || parseInt($elem.css('width'), 10);\n\n                                if (!width || width === prevWidth || gridster.movingItem) {\n                                    return;\n                                }\n                                prevWidth = width;\n\n                                if (gridster.loaded) {\n                                    $elem.removeClass('gridster-loaded');\n                                }\n\n                                refresh();\n\n                                if (gridster.loaded) {\n                                    $elem.addClass('gridster-loaded');\n                                }\n\n                                scope.$parent.$broadcast('gridster-resized', [width, $elem.offsetHeight]);\n                            }\n\n                            // track element width changes any way we can\n                            function onResize() {\n                                resize();\n                                $timeout(function() {\n                                    scope.$apply();\n                                });\n                            }\n                            if (typeof $elem.resize === 'function') {\n                                $elem.resize(onResize);\n                            }\n                            var $win = angular.element($window);\n                            $win.on('resize', onResize);\n\n                            scope.$watch(function() {\n                                return $elem[0].offsetWidth || parseInt($elem.css('width'), 10);\n                            }, resize);\n\n                            // be sure to cleanup\n                            scope.$on('$destroy', function() {\n                                gridster.destroy();\n                                $win.off('resize', onResize);\n                            });\n\n                            // allow a little time to place items before floating up\n                            $timeout(function() {\n                                scope.$watch('gridster.floating', function() {\n                                    gridster.floatItemsUp();\n                                });\n                                gridster.loaded = true;\n                            }, 100);\n\n\n\n                            // Custom code\n\n                            /**\n                             * Callback called when starting to drag from palette to canvas.\n                             */\n                            $rootScope.startDragCallback = function (event, ui) {\n                                $timeout(function () {\n                                    var fieldId = event.target.id;\n                                    var fieldType;\n\n                                    var colspan = 1;\n                                    if (fieldId === 'group' || fieldId === 'dynamic-table') {\n                                        colspan = 2;\n                                    }\n\n                                    var numberOfRows = 1;\n                                    if (fieldId === 'multi-line-text') {\n                                        numberOfRows = 2;\n                                    } else if (fieldId === 'dynamic-table') {\n                                        numberOfRows = 2;\n                                    }\n\n                                    scope.startDragItem = {\n                                        type: fieldId,\n                                        fieldType: fieldType,\n                                        name: 'Label',\n                                        required: false,\n                                        readOnly: false,\n                                        sizeX: colspan,\n                                        sizeY: numberOfRows,\n                                        row: -1,\n                                        col: -1\n                                    };\n\n                                    if (fieldId === 'radio-buttons' || fieldId === 'dropdown') {\n                                        scope.startDragItem.options = [\n                                            {name: 'Option 1'}\n                                        ];\n                                    }\n\n                                }, 0);\n                            };\n\n                            /**\n                             * Callback called when stopping to drag from palette to canvas.\n                             */\n                            $rootScope.dropCallback = function (event, ui) {\n                                $timeout(function () {\n                                    gridster.movingItem = null;\n                                    var offset = jQuery($elem[0]).offset();\n                                    var row = gridster.pixelsToRows(event.clientY - offset.top, true) - 1;\n                                    var column = gridster.pixelsToColumns(event.clientX - offset.left, true) - 1;\n                                    if (row >= 0 && column >= 0) {\n\n                                        scope.startDragItem.row = row;\n                                        scope.startDragItem.col = column;\n                                    }\n                                }, 0);\n                            };\n\n                            /**\n                             * Callback called during dragging from palette to canvas.\n                             */\n                            $rootScope.dragCallback = function (event, ui) {\n\n                                    var offset = jQuery($elem[0]).offset();\n                                    var row = gridster.pixelsToRows(event.clientY - offset.top, true) - 1;\n                                    var column = gridster.pixelsToColumns(event.clientX - offset.left, true) - 1;\n\n                                    if (!scope.startDragItem) {\n                                        return;\n                                    }\n\n                                    if (scope.startDragItem.row === row && scope.startDragItem.col === column) {\n                                        return;\n                                    }\n\n                                    if ( ((scope.startDragItem.row === -1 || scope.startDragItem.col === -1) && row >= 0 && column >= 0)\n                                        || (scope.startDragItem.row >= 0 && scope.startDragItem.col >= 0 && (row < 0 || column < 0)) ) {\n                                        $timeout(function () {\n                                            if ((scope.startDragItem.row === -1 || scope.startDragItem.col === -1) && row >= 0 && column >= 0) {\n                                                scope.$parent.formItems.push(scope.startDragItem);\n\n                                                gridster.movingItem = scope.startDragItem;\n                                                gridster.updateHeight(1);\n                                            }\n\n                                            if (scope.startDragItem.row >= 0 && scope.startDragItem.col >= 0 && (row < 0 || column < 0)) {\n                                                scope.$parent.formItems.pop();\n                                                gridster.movingItem = null;\n                                            }\n\n\n                                        }, 0);\n                                    }\n\n                                $timeout(function () {\n                                    scope.startDragItem.row = row;\n                                    scope.startDragItem.col = column;\n                                }, 0);\n\n                            };\n\n                            // END custom code\n\n\n                        };\n                    }\n                };\n            }\n        ])\n\n        .controller('GridsterItemCtrl', function() {\n            this.$element = null;\n            this.gridster = null;\n            this.row = null;\n            this.col = null;\n            this.sizeX = null;\n            this.sizeY = null;\n            this.minSizeX = 0;\n            this.minSizeY = 0;\n            this.maxSizeX = null;\n            this.maxSizeY = null;\n\n            this.init = function($element, gridster) {\n                this.$element = $element;\n                this.gridster = gridster;\n                this.sizeX = gridster.defaultSizeX;\n                this.sizeY = gridster.defaultSizeY;\n            };\n\n            this.destroy = function() {\n                this.gridster = null;\n                this.$element = null;\n            };\n\n            /**\n             * Returns the items most important attributes\n             */\n            this.toJSON = function() {\n                return {\n                    row: this.row,\n                    col: this.col,\n                    sizeY: this.sizeY,\n                    sizeX: this.sizeX\n                };\n            };\n\n            this.isMoving = function() {\n                return this.gridster.movingItem === this;\n            };\n\n            /**\n             * Set the items position\n             *\n             * @param {number} row\n             * @param {number} column\n             */\n            this.setPosition = function(row, column) {\n                this.gridster.putItem(this, row, column);\n\n                if (!this.isMoving()) {\n                    this.setElementPosition();\n                }\n            };\n\n            /**\n             * Sets a specified size property\n             *\n             * @param {string} key Can be either \"x\" or \"y\"\n             * @param {number} value The size amount\n             */\n            this.setSize = function(key, value, preventMove) {\n                key = key.toUpperCase();\n                var camelCase = 'size' + key,\n                    titleCase = 'Size' + key;\n                if (value === '') {\n                    return;\n                }\n                value = parseInt(value, 10);\n                if (isNaN(value) || value === 0) {\n                    value = this.gridster['default' + titleCase];\n                }\n                var max = key === 'X' ? this.gridster.columns : this.gridster.maxRows;\n                if (this['max' + titleCase]) {\n                    max = Math.min(this['max' + titleCase], max);\n                }\n                if (this.gridster['max' + titleCase]) {\n                    max = Math.min(this.gridster['max' + titleCase], max);\n                }\n                if (key === 'X' && this.cols) {\n                    max -= this.cols;\n                } else if (key === 'Y' && this.rows) {\n                    max -= this.rows;\n                }\n\n                var min = 0;\n                if (this['min' + titleCase]) {\n                    min = Math.max(this['min' + titleCase], min);\n                }\n                if (this.gridster['min' + titleCase]) {\n                    min = Math.max(this.gridster['min' + titleCase], min);\n                }\n\n                value = Math.max(Math.min(value, max), min);\n\n                var changed = (this[camelCase] !== value || (this['old' + titleCase] && this['old' + titleCase] !== value));\n                this['old' + titleCase] = this[camelCase] = value;\n\n                if (!this.isMoving()) {\n                    this['setElement' + titleCase]();\n                }\n                if (!preventMove && changed) {\n                    this.gridster.moveOverlappingItems(this);\n                    this.gridster.layoutChanged();\n                }\n\n                return changed;\n            };\n\n            /**\n             * Sets the items sizeY property\n             *\n             * @param {number} rows\n             */\n            this.setSizeY = function(rows, preventMove) {\n                return this.setSize('Y', rows, preventMove);\n            };\n\n            /**\n             * Sets the items sizeX property\n             *\n             * @param {number} rows\n             */\n            this.setSizeX = function(columns, preventMove) {\n                return this.setSize('X', columns, preventMove);\n            };\n\n            /**\n             * Sets an elements position on the page\n             *\n             * @param {number} row\n             * @param {number} column\n             */\n            this.setElementPosition = function() {\n                if (this.gridster.isMobile) {\n                    this.$element.css({\n                        marginLeft: this.gridster.margins[0] + 'px',\n                        marginRight: this.gridster.margins[0] + 'px',\n                        marginTop: this.gridster.margins[1] + 'px',\n                        marginBottom: this.gridster.margins[1] + 'px',\n                        top: '',\n                        left: ''\n                    });\n                } else {\n                    this.$element.css({\n                        margin: 0,\n                        top: (this.row * this.gridster.curRowHeight + (this.gridster.outerMargin ? this.gridster.margins[0] : 0)) + 'px',\n                        left: (this.col * this.gridster.curColWidth + (this.gridster.outerMargin ? this.gridster.margins[1] : 0)) + 'px'\n                    });\n                }\n            };\n\n            /**\n             * Sets an elements height\n             */\n            this.setElementSizeY = function() {\n                if (this.gridster.isMobile && !this.gridster.saveGridItemCalculatedHeightInMobile) {\n                    this.$element.css('height', '');\n                } else {\n                    this.$element.css('height', (this.sizeY * this.gridster.curRowHeight - this.gridster.margins[0]) + 'px');\n                }\n            };\n\n            /**\n             * Sets an elements width\n             */\n            this.setElementSizeX = function() {\n                if (this.gridster.isMobile) {\n                    this.$element.css('width', '');\n                } else {\n                    this.$element.css('width', (this.sizeX * this.gridster.curColWidth - this.gridster.margins[1]) + 'px');\n                }\n            };\n\n            /**\n             * Gets an element's width\n             */\n            this.getElementSizeX = function() {\n                return (this.sizeX * this.gridster.curColWidth - this.gridster.margins[1]);\n            };\n\n            /**\n             * Gets an element's height\n             */\n            this.getElementSizeY = function() {\n                return (this.sizeY * this.gridster.curRowHeight - this.gridster.margins[0]);\n            };\n\n        })\n\n        .factory('GridsterDraggable', ['$document', '$timeout', '$window',\n            function($document, $timeout, $window) {\n                function GridsterDraggable($el, scope, gridster, item, itemOptions) {\n\n                    var elmX, elmY, elmW, elmH,\n\n                        mouseX = 0,\n                        mouseY = 0,\n                        lastMouseX = 0,\n                        lastMouseY = 0,\n                        mOffX = 0,\n                        mOffY = 0,\n\n                        minTop = 0,\n                        maxTop = 9999,\n                        minLeft = 0,\n                        realdocument = $document[0];\n\n                    var originalCol, originalRow;\n                    var inputTags = ['select', 'input', 'textarea', 'button'];\n\n                    function mouseDown(e) {\n                        if (inputTags.indexOf(e.target.nodeName.toLowerCase()) !== -1) {\n                            return false;\n                        }\n\n                        // exit, if a resize handle was hit\n                        if (angular.element(e.target).hasClass('gridster-item-resizable-handler')) {\n                            return false;\n                        }\n\n                        // exit, if the target has it's own click event\n                        if (angular.element(e.target).attr('onclick') || angular.element(e.target).attr('ng-click')) {\n                            return false;\n                        }\n\n                        switch (e.which) {\n                            case 1:\n                                // left mouse button\n                                break;\n                            case 2:\n                            case 3:\n                                // right or middle mouse button\n                                return;\n                        }\n\n                        lastMouseX = e.pageX;\n                        lastMouseY = e.pageY;\n\n                        elmX = parseInt($el.css('left'), 10);\n                        elmY = parseInt($el.css('top'), 10);\n                        elmW = $el[0].offsetWidth;\n                        elmH = $el[0].offsetHeight;\n\n                        originalCol = item.col;\n                        originalRow = item.row;\n\n                        dragStart(e);\n\n                        return true;\n                    }\n\n                    function mouseMove(e) {\n                        if (!$el.hasClass('gridster-item-moving') || $el.hasClass('gridster-item-resizing')) {\n                            return false;\n                        }\n\n                        var maxLeft = gridster.curWidth - 1;\n\n                        // Get the current mouse position.\n                        mouseX = e.pageX;\n                        mouseY = e.pageY;\n\n                        // Get the deltas\n                        var diffX = mouseX - lastMouseX + mOffX;\n                        var diffY = mouseY - lastMouseY + mOffY;\n                        mOffX = mOffY = 0;\n\n                        // Update last processed mouse positions.\n                        lastMouseX = mouseX;\n                        lastMouseY = mouseY;\n\n                        var dX = diffX,\n                            dY = diffY;\n                        if (elmX + dX < minLeft) {\n                            diffX = minLeft - elmX;\n                            mOffX = dX - diffX;\n                        } else if (elmX + elmW + dX > maxLeft) {\n                            diffX = maxLeft - elmX - elmW;\n                            mOffX = dX - diffX;\n                        }\n\n                        if (elmY + dY < minTop) {\n                            diffY = minTop - elmY;\n                            mOffY = dY - diffY;\n                        } else if (elmY + elmH + dY > maxTop) {\n                            diffY = maxTop - elmY - elmH;\n                            mOffY = dY - diffY;\n                        }\n                        elmX += diffX;\n                        elmY += diffY;\n\n                        // set new position\n                        $el.css({\n                            'top': elmY + 'px',\n                            'left': elmX + 'px'\n                        });\n\n                        drag(e);\n\n                        return true;\n                    }\n\n                    function mouseUp(e) {\n                        if (!$el.hasClass('gridster-item-moving') || $el.hasClass('gridster-item-resizing')) {\n                            return false;\n                        }\n\n                        mOffX = mOffY = 0;\n\n                        dragStop(e);\n\n                        return true;\n                    }\n\n                    function dragStart(event) {\n                        $el.addClass('gridster-item-moving');\n                        gridster.movingItem = item;\n\n                        gridster.updateHeight(item.sizeY);\n                        scope.$apply(function() {\n                            if (gridster.draggable && gridster.draggable.start) {\n                                gridster.draggable.start(event, $el, itemOptions);\n                            }\n                        });\n                    }\n\n                    function drag(event) {\n                        var oldRow = item.row,\n                            oldCol = item.col,\n                            hasCallback = gridster.draggable && gridster.draggable.drag,\n                            scrollSensitivity = gridster.draggable.scrollSensitivity,\n                            scrollSpeed = gridster.draggable.scrollSpeed;\n\n                        var row = gridster.pixelsToRows(elmY);\n                        var col = gridster.pixelsToColumns(elmX);\n\n                        var itemsInTheWay = gridster.getItems(row, col, item.sizeX, item.sizeY, item);\n                        var hasItemsInTheWay = itemsInTheWay.length !== 0;\n\n                        if (gridster.swapping === true && hasItemsInTheWay) {\n                            var boundingBoxItem = gridster.getBoundingBox(itemsInTheWay);\n                            var sameSize = boundingBoxItem.sizeX === item.sizeX && boundingBoxItem.sizeY === item.sizeY;\n                            var sameRow = boundingBoxItem.row === row;\n                            var sameCol = boundingBoxItem.col === col;\n                            var samePosition = sameRow && sameCol;\n                            var inline = sameRow || sameCol;\n\n                            if (sameSize && itemsInTheWay.length === 1) {\n                                if (samePosition) {\n                                    gridster.swapItems(item, itemsInTheWay[0]);\n                                } else if (inline) {\n                                    return;\n                                }\n                            } else if (boundingBoxItem.sizeX <= item.sizeX && boundingBoxItem.sizeY <= item.sizeY && inline) {\n                                var emptyRow = item.row <= row ? item.row : row + item.sizeY;\n                                var emptyCol = item.col <= col ? item.col : col + item.sizeX;\n                                var rowOffset = emptyRow - boundingBoxItem.row;\n                                var colOffset = emptyCol - boundingBoxItem.col;\n\n                                for (var i = 0, l = itemsInTheWay.length; i < l; ++i) {\n                                    var itemInTheWay = itemsInTheWay[i];\n\n                                    var itemsInFreeSpace = gridster.getItems(\n                                            itemInTheWay.row + rowOffset,\n                                            itemInTheWay.col + colOffset,\n                                        itemInTheWay.sizeX,\n                                        itemInTheWay.sizeY,\n                                        item\n                                    );\n\n                                    if (itemsInFreeSpace.length === 0) {\n                                        gridster.putItem(itemInTheWay, itemInTheWay.row + rowOffset, itemInTheWay.col + colOffset);\n                                    }\n                                }\n                            }\n                        }\n\n                        if (gridster.pushing !== false || !hasItemsInTheWay) {\n                            item.row = row;\n                            item.col = col;\n                        }\n\n                        if (event.pageY - realdocument.body.scrollTop < scrollSensitivity) {\n                            realdocument.body.scrollTop = realdocument.body.scrollTop - scrollSpeed;\n                        } else if ($window.innerHeight - (event.pageY - realdocument.body.scrollTop) < scrollSensitivity) {\n                            realdocument.body.scrollTop = realdocument.body.scrollTop + scrollSpeed;\n                        }\n\n                        if (event.pageX - realdocument.body.scrollLeft < scrollSensitivity) {\n                            realdocument.body.scrollLeft = realdocument.body.scrollLeft - scrollSpeed;\n                        } else if ($window.innerWidth - (event.pageX - realdocument.body.scrollLeft) < scrollSensitivity) {\n                            realdocument.body.scrollLeft = realdocument.body.scrollLeft + scrollSpeed;\n                        }\n\n                        if (hasCallback || oldRow !== item.row || oldCol !== item.col) {\n                            scope.$apply(function() {\n                                if (hasCallback) {\n                                    gridster.draggable.drag(event, $el, itemOptions);\n                                }\n                            });\n                        }\n                    }\n\n                    function dragStop(event) {\n                        $el.removeClass('gridster-item-moving');\n                        var row = gridster.pixelsToRows(elmY);\n                        var col = gridster.pixelsToColumns(elmX);\n                        if (gridster.pushing !== false || gridster.getItems(row, col, item.sizeX, item.sizeY, item).length === 0) {\n                            item.row = row;\n                            item.col = col;\n                        }\n                        gridster.movingItem = null;\n                        item.setPosition(item.row, item.col);\n\n                        scope.$apply(function() {\n                            if (gridster.draggable && gridster.draggable.stop) {\n                                gridster.draggable.stop(event, $el, itemOptions);\n                            }\n                        });\n                    }\n\n                    var enabled = false;\n                    var $dragHandle = null;\n                    var unifiedInput;\n\n                    this.enable = function() {\n                        var self = this;\n                        // disable and timeout required for some template rendering\n                        $timeout(function() {\n                            self.disable();\n\n                            if (gridster.draggable && gridster.draggable.handle) {\n                                $dragHandle = angular.element($el[0].querySelector(gridster.draggable.handle));\n                                if ($dragHandle.length === 0) {\n                                    // fall back to element if handle not found...\n                                    $dragHandle = $el;\n                                }\n                            } else {\n                                $dragHandle = $el;\n                            }\n\n                            unifiedInput = new gridster.unifiedInput($dragHandle[0], mouseDown, mouseMove, mouseUp);\n                            unifiedInput.enable();\n\n                            enabled = true;\n                        });\n                    };\n\n                    this.disable = function() {\n                        if (!enabled) {\n                            return;\n                        }\n\n                        unifiedInput.disable();\n                        unifiedInput = undefined;\n                        enabled = false;\n                    };\n\n                    this.toggle = function(enabled) {\n                        if (enabled) {\n                            this.enable();\n                        } else {\n                            this.disable();\n                        }\n                    };\n\n                    this.destroy = function() {\n                        this.disable();\n                    };\n                }\n\n                return GridsterDraggable;\n            }\n        ])\n\n        .factory('GridsterResizable', [\n            function() {\n                function GridsterResizable($el, scope, gridster, item, itemOptions) {\n\n                    function ResizeHandle(handleClass) {\n\n                        var hClass = handleClass;\n\n                        var elmX, elmY, elmW, elmH,\n\n                            mouseX = 0,\n                            mouseY = 0,\n                            lastMouseX = 0,\n                            lastMouseY = 0,\n                            mOffX = 0,\n                            mOffY = 0,\n\n                            minTop = 0,\n                            maxTop = 9999,\n                            minLeft = 0;\n\n                        var getMinHeight = function() {\n                            return gridster.curRowHeight - gridster.margins[0];\n                        };\n                        var getMinWidth = function() {\n                            return gridster.curColWidth - gridster.margins[1];\n                        };\n\n                        var originalWidth, originalHeight;\n                        var savedDraggable;\n\n                        function mouseDown(e) {\n                            switch (e.which) {\n                                case 1:\n                                    // left mouse button\n                                    break;\n                                case 2:\n                                case 3:\n                                    // right or middle mouse button\n                                    return;\n                            }\n\n                            // save the draggable setting to restore after resize\n                            savedDraggable = gridster.draggable.enabled;\n                            if (savedDraggable) {\n                                gridster.draggable.enabled = false;\n                                scope.$broadcast('gridster-draggable-changed');\n                            }\n\n                            // Get the current mouse position.\n                            lastMouseX = e.pageX;\n                            lastMouseY = e.pageY;\n\n                            // Record current widget dimensions\n                            elmX = parseInt($el.css('left'), 10);\n                            elmY = parseInt($el.css('top'), 10);\n                            elmW = $el[0].offsetWidth;\n                            elmH = $el[0].offsetHeight;\n\n                            originalWidth = item.sizeX;\n                            originalHeight = item.sizeY;\n\n                            resizeStart(e);\n\n                            return true;\n                        }\n\n                        function resizeStart(e) {\n                            $el.addClass('gridster-item-moving');\n                            $el.addClass('gridster-item-resizing');\n\n                            gridster.movingItem = item;\n\n                            item.setElementSizeX();\n                            item.setElementSizeY();\n                            item.setElementPosition();\n                            gridster.updateHeight(1);\n\n                            scope.$apply(function() {\n                                // callback\n                                if (gridster.resizable && gridster.resizable.start) {\n                                    gridster.resizable.start(e, $el, itemOptions); // options is the item model\n                                }\n                            });\n                        }\n\n                        function mouseMove(e) {\n                            var maxLeft = gridster.curWidth - 1;\n\n                            // Get the current mouse position.\n                            mouseX = e.pageX;\n                            mouseY = e.pageY;\n\n                            // Get the deltas\n                            var diffX = mouseX - lastMouseX + mOffX;\n                            var diffY = mouseY - lastMouseY + mOffY;\n                            mOffX = mOffY = 0;\n\n                            // Update last processed mouse positions.\n                            lastMouseX = mouseX;\n                            lastMouseY = mouseY;\n\n                            var dY = diffY,\n                                dX = diffX;\n\n                            if (hClass.indexOf('n') >= 0) {\n                                if (elmH - dY < getMinHeight()) {\n                                    diffY = elmH - getMinHeight();\n                                    mOffY = dY - diffY;\n                                } else if (elmY + dY < minTop) {\n                                    diffY = minTop - elmY;\n                                    mOffY = dY - diffY;\n                                }\n                                elmY += diffY;\n                                elmH -= diffY;\n                            }\n                            if (hClass.indexOf('s') >= 0) {\n                                if (elmH + dY < getMinHeight()) {\n                                    diffY = getMinHeight() - elmH;\n                                    mOffY = dY - diffY;\n                                } else if (elmY + elmH + dY > maxTop) {\n                                    diffY = maxTop - elmY - elmH;\n                                    mOffY = dY - diffY;\n                                }\n                                elmH += diffY;\n                            }\n                            if (hClass.indexOf('w') >= 0) {\n                                if (elmW - dX < getMinWidth()) {\n                                    diffX = elmW - getMinWidth();\n                                    mOffX = dX - diffX;\n                                } else if (elmX + dX < minLeft) {\n                                    diffX = minLeft - elmX;\n                                    mOffX = dX - diffX;\n                                }\n                                elmX += diffX;\n                                elmW -= diffX;\n                            }\n                            if (hClass.indexOf('e') >= 0) {\n                                if (elmW + dX < getMinWidth()) {\n                                    diffX = getMinWidth() - elmW;\n                                    mOffX = dX - diffX;\n                                } else if (elmX + elmW + dX > maxLeft) {\n                                    diffX = maxLeft - elmX - elmW;\n                                    mOffX = dX - diffX;\n                                }\n                                elmW += diffX;\n                            }\n\n                            // set new position\n                            $el.css({\n                                'top': elmY + 'px',\n                                'left': elmX + 'px',\n                                'width': elmW + 'px',\n                                'height': elmH + 'px'\n                            });\n\n                            resize(e);\n\n                            return true;\n                        }\n\n                        function mouseUp(e) {\n                            // restore draggable setting to its original state\n                            if (gridster.draggable.enabled !== savedDraggable) {\n                                gridster.draggable.enabled = savedDraggable;\n                                scope.$broadcast('gridster-draggable-changed');\n                            }\n\n                            mOffX = mOffY = 0;\n\n                            resizeStop(e);\n\n                            return true;\n                        }\n\n                        function resize(e) {\n                            var oldRow = item.row,\n                                oldCol = item.col,\n                                oldSizeX = item.sizeX,\n                                oldSizeY = item.sizeY,\n                                hasCallback = gridster.resizable && gridster.resizable.resize;\n\n                            var col = item.col;\n                            // only change column if grabbing left edge\n                            if (['w', 'nw', 'sw'].indexOf(handleClass) !== -1) {\n                                col = gridster.pixelsToColumns(elmX, false);\n                            }\n\n                            var row = item.row;\n                            // only change row if grabbing top edge\n                            if (['n', 'ne', 'nw'].indexOf(handleClass) !== -1) {\n                                row = gridster.pixelsToRows(elmY, false);\n                            }\n\n                            var sizeX = item.sizeX;\n                            // only change row if grabbing left or right edge\n                            if (['n', 's'].indexOf(handleClass) === -1) {\n                                sizeX = gridster.pixelsToColumns(elmW, true);\n                            }\n\n                            var sizeY = item.sizeY;\n                            // only change row if grabbing top or bottom edge\n                            if (['e', 'w'].indexOf(handleClass) === -1) {\n                                sizeY = gridster.pixelsToRows(elmH, true);\n                            }\n\n                            if (gridster.pushing !== false || gridster.getItems(row, col, sizeX, sizeY, item).length === 0) {\n                                item.row = row;\n                                item.col = col;\n                                item.sizeX = sizeX;\n                                item.sizeY = sizeY;\n                            }\n                            var isChanged = item.row !== oldRow || item.col !== oldCol || item.sizeX !== oldSizeX || item.sizeY !== oldSizeY;\n\n                            if (hasCallback || isChanged) {\n                                scope.$apply(function() {\n                                    if (hasCallback) {\n                                        gridster.resizable.resize(e, $el, itemOptions); // options is the item model\n                                    }\n                                });\n                            }\n                        }\n\n                        function resizeStop(e) {\n                            $el.removeClass('gridster-item-moving');\n                            $el.removeClass('gridster-item-resizing');\n\n                            gridster.movingItem = null;\n\n                            item.setPosition(item.row, item.col);\n                            item.setSizeY(item.sizeY);\n                            item.setSizeX(item.sizeX);\n\n                            scope.$apply(function() {\n                                if (gridster.resizable && gridster.resizable.stop) {\n                                    gridster.resizable.stop(e, $el, itemOptions); // options is the item model\n                                }\n                            });\n                        }\n\n                        var $dragHandle = null;\n                        var unifiedInput;\n\n                        this.enable = function() {\n                            if (!$dragHandle) {\n                                $dragHandle = angular.element('<div class=\"gridster-item-resizable-handler handle-' + hClass + '\"></div>');\n                                $el.append($dragHandle);\n                            }\n\n                            unifiedInput = new gridster.unifiedInput($dragHandle[0], mouseDown, mouseMove, mouseUp);\n                            unifiedInput.enable();\n                        };\n\n                        this.disable = function() {\n                            if ($dragHandle) {\n                                $dragHandle.remove();\n                                $dragHandle = null;\n                            }\n\n                            unifiedInput.disable();\n                            unifiedInput = undefined;\n                        };\n\n                        this.destroy = function() {\n                            this.disable();\n                        };\n                    }\n\n                    var handles = [];\n                    var handlesOpts = gridster.resizable.handles;\n                    if (typeof handlesOpts === 'string') {\n                        handlesOpts = gridster.resizable.handles.split(',');\n                    }\n                    var enabled = false;\n\n                    for (var c = 0, l = handlesOpts.length; c < l; c++) {\n                        handles.push(new ResizeHandle(handlesOpts[c]));\n                    }\n\n                    this.enable = function() {\n                        if (enabled) {\n                            return;\n                        }\n                        for (var c = 0, l = handles.length; c < l; c++) {\n                            handles[c].enable();\n                        }\n                        enabled = true;\n                    };\n\n                    this.disable = function() {\n                        if (!enabled) {\n                            return;\n                        }\n                        for (var c = 0, l = handles.length; c < l; c++) {\n                            handles[c].disable();\n                        }\n                        enabled = false;\n                    };\n\n                    this.toggle = function(enabled) {\n                        if (enabled) {\n                            this.enable();\n                        } else {\n                            this.disable();\n                        }\n                    };\n\n                    this.destroy = function() {\n                        for (var c = 0, l = handles.length; c < l; c++) {\n                            handles[c].destroy();\n                        }\n                    };\n                }\n                return GridsterResizable;\n            }\n        ])\n\n    /**\n     * GridsterItem directive\n     */\n        .directive('gridsterItem', ['$parse', 'GridsterDraggable', 'GridsterResizable',\n            function($parse, GridsterDraggable, GridsterResizable) {\n                return {\n                    restrict: 'EA',\n                    controller: 'GridsterItemCtrl',\n                    require: ['^gridster', 'gridsterItem'],\n                    link: function(scope, $el, attrs, controllers) {\n                        var optionsKey = attrs.gridsterItem,\n                            options;\n\n                        var gridster = controllers[0],\n                            item = controllers[1];\n\n                        // bind the item's position properties\n                        if (optionsKey) {\n                            var $optionsGetter = $parse(optionsKey);\n                            options = $optionsGetter(scope) || {};\n                            if (!options && $optionsGetter.assign) {\n                                options = {\n                                    row: item.row,\n                                    col: item.col,\n                                    sizeX: item.sizeX,\n                                    sizeY: item.sizeY,\n                                    minSizeX: 0,\n                                    minSizeY: 0,\n                                    maxSizeX: null,\n                                    maxSizeY: null\n                                };\n                                $optionsGetter.assign(scope, options);\n                            }\n                        } else {\n                            options = attrs;\n                        }\n\n                        item.init($el, gridster);\n\n                        $el.addClass('gridster-item');\n\n                        var aspects = ['minSizeX', 'maxSizeX', 'minSizeY', 'maxSizeY', 'sizeX', 'sizeY', 'row', 'col'],\n                            $getters = {};\n\n                        var aspectFn = function(aspect) {\n                            var key;\n                            if (typeof options[aspect] === 'string') {\n                                key = options[aspect];\n                            } else if (typeof options[aspect.toLowerCase()] === 'string') {\n                                key = options[aspect.toLowerCase()];\n                            } else if (optionsKey) {\n                                key = $parse(optionsKey + '.' + aspect);\n                            } else {\n                                return;\n                            }\n                            $getters[aspect] = $parse(key);\n\n                            // when the value changes externally, update the internal item object\n                            scope.$watch(key, function(newVal) {\n                                newVal = parseInt(newVal, 10);\n                                if (!isNaN(newVal)) {\n                                    item[aspect] = newVal;\n                                }\n                            });\n\n                            // initial set\n                            var val = $getters[aspect](scope);\n                            if (typeof val === 'number') {\n                                item[aspect] = val;\n                            }\n                        };\n\n                        for (var i = 0, l = aspects.length; i < l; ++i) {\n                            aspectFn(aspects[i]);\n                        }\n\n                        scope.$broadcast('gridster-item-initialized', [item.sizeY, item.sizeX, item.getElementSizeY(), item.getElementSizeX()]);\n\n                        function positionChanged() {\n                            // call setPosition so the element and gridster controller are updated\n                            item.setPosition(item.row, item.col);\n\n                            // when internal item position changes, update externally bound values\n                            if ($getters.row && $getters.row.assign) {\n                                $getters.row.assign(scope, item.row);\n                            }\n                            if ($getters.col && $getters.col.assign) {\n                                $getters.col.assign(scope, item.col);\n                            }\n                        }\n                        scope.$watch(function() {\n                            return item.row + ',' + item.col;\n                        }, positionChanged);\n\n                        function sizeChanged() {\n                            var changedX = item.setSizeX(item.sizeX, true);\n                            if (changedX && $getters.sizeX && $getters.sizeX.assign) {\n                                $getters.sizeX.assign(scope, item.sizeX);\n                            }\n                            var changedY = item.setSizeY(item.sizeY, true);\n                            if (changedY && $getters.sizeY && $getters.sizeY.assign) {\n                                $getters.sizeY.assign(scope, item.sizeY);\n                            }\n\n                            if (changedX || changedY) {\n                                item.gridster.moveOverlappingItems(item);\n                                gridster.layoutChanged();\n                            }\n                        }\n                        scope.$watch(function() {\n                            return item.sizeY + ',' + item.sizeX + '|' + item.minSizeX + ',' + item.maxSizeX + ',' + item.minSizeY + ',' + item.maxSizeY;\n                        }, sizeChanged);\n\n                        var draggable = new GridsterDraggable($el, scope, gridster, item, options);\n                        var resizable = new GridsterResizable($el, scope, gridster, item, options);\n\n                        scope.$on('gridster-draggable-changed', function() {\n                            draggable.toggle(!gridster.isMobile && gridster.draggable && gridster.draggable.enabled);\n                        });\n                        scope.$on('gridster-resizable-changed', function() {\n                            resizable.toggle(!gridster.isMobile && gridster.resizable && gridster.resizable.enabled);\n                        });\n                        scope.$on('gridster-resized', function() {\n                            resizable.toggle(!gridster.isMobile && gridster.resizable && gridster.resizable.enabled);\n                        });\n                        scope.$watch(function() {\n                            return gridster.isMobile;\n                        }, function() {\n                            resizable.toggle(!gridster.isMobile && gridster.resizable && gridster.resizable.enabled);\n                            draggable.toggle(!gridster.isMobile && gridster.draggable && gridster.draggable.enabled);\n                        });\n\n                        function whichTransitionEvent() {\n                            var el = document.createElement('div');\n                            var transitions = {\n                                'transition': 'transitionend',\n                                'OTransition': 'oTransitionEnd',\n                                'MozTransition': 'transitionend',\n                                'WebkitTransition': 'webkitTransitionEnd'\n                            };\n                            for (var t in transitions) {\n                                if (el.style[t] !== undefined) {\n                                    return transitions[t];\n                                }\n                            }\n                        }\n\n                        $el.on(whichTransitionEvent(), function() {\n                            scope.$apply(function() {\n                                scope.$broadcast('gridster-item-transition-end');\n                            });\n                        });\n\n                        return scope.$on('$destroy', function() {\n                            try {\n                                resizable.destroy();\n                                draggable.destroy();\n                            } catch (e) {}\n\n                            try {\n                                gridster.removeItem(item);\n                            } catch (e) {}\n\n                            try {\n                                item.destroy();\n                            } catch (e) {}\n                        });\n                    }\n                };\n            }\n        ])\n\n    ;\n\n})(angular);"
  },
  {
    "path": "flowable-ui-web/idm/libs/angular-hotkeys_1.4.5/hotkeys--activiti-patch.js",
    "content": "/*! \n * angular-hotkeys v1.4.5\n * https://chieffancypants.github.io/angular-hotkeys\n * Copyright (c) 2014 Wes Cruver\n * License: MIT\n */\n/*\n * angular-hotkeys\n *\n * Automatic keyboard shortcuts for your angular apps\n *\n * (c) 2014 Wes Cruver\n * License: MIT\n */\n\n(function() {\n\n  'use strict';\n\n  angular.module('cfp.hotkeys', []).provider('hotkeys', function() {\n\n    /**\n     * Configurable setting to disable the cheatsheet entirely\n     * @type {Boolean}\n     */\n    this.includeCheatSheet = true;\n\n    /**\n     * Configurable setting for the cheat sheet title\n     * @type {String}\n     */\n\n    this.templateTitle = 'Keyboard Shortcuts:';\n\n    /**\n     * Cheat sheet template in the event you want to totally customize it.\n     * @type {String}\n     */\n    this.template = '<div class=\"cfp-hotkeys-container fade\" ng-class=\"{in: helpVisible}\" style=\"display: none;\"><div class=\"cfp-hotkeys\">' +\n                      '<h4 class=\"cfp-hotkeys-title\">{{ title }}</h4>' +\n                      '<table><tbody>' +\n                        '<tr ng-repeat=\"hotkey in hotkeys | filter:{ description: \\'!$$undefined$$\\' }\">' +\n                          '<td class=\"cfp-hotkeys-keys\">' +\n                            '<span ng-repeat=\"key in hotkey.format() track by $index\" class=\"cfp-hotkeys-key\">{{ key }}</span>' +\n                          '</td>' +\n                          '<td class=\"cfp-hotkeys-text\">{{ hotkey.description }}</td>' +\n                        '</tr>' +\n                      '</tbody></table>' +\n                      '<div class=\"cfp-hotkeys-close\" ng-click=\"toggleCheatSheet()\">×</div>' +\n                    '</div></div>';\n\n    /**\n     * Configurable setting for the cheat sheet hotkey\n     * @type {String}\n     */\n    this.cheatSheetHotkey = '?';\n\n    /**\n     * Configurable setting for the cheat sheet description\n     * @type {String}\n     */\n    this.cheatSheetDescription = 'Show / hide this help menu';\n\n    this.$get = ['$rootElement', '$rootScope', '$compile', '$window', '$document', function ($rootElement, $rootScope, $compile, $window, $document) {\n\n      // monkeypatch Mousetrap's stopCallback() function\n      // this version doesn't return true when the element is an INPUT, SELECT, or TEXTAREA\n      // (instead we will perform this check per-key in the _add() method)\n      Mousetrap.stopCallback = function(event, element) {\n        // if the element has the class \"mousetrap\" then no need to stop\n        if ((' ' + element.className + ' ').indexOf(' mousetrap ') > -1) {\n          return false;\n        }\n\n        return (element.contentEditable && element.contentEditable == 'true');\n      };\n\n      /**\n       * Convert strings like cmd into symbols like ⌘\n       * @param  {String} combo Key combination, e.g. 'mod+f'\n       * @return {String}       The key combination with symbols\n       */\n      function symbolize (combo) {\n        var map = {\n          command   : '⌘',\n          shift     : '⇧',\n          left      : '←',\n          right     : '→',\n          up        : '↑',\n          down      : '↓',\n          'return'  : '↩',\n          backspace : '⌫'\n        };\n        combo = combo.split('+');\n\n        for (var i = 0; i < combo.length; i++) {\n          // try to resolve command / ctrl based on OS:\n          if (combo[i] === 'mod') {\n            if ($window.navigator && $window.navigator.platform.indexOf('Mac') >=0 ) {\n              combo[i] = 'command';\n            } else {\n              combo[i] = 'ctrl';\n            }\n          }\n\n          combo[i] = map[combo[i]] || combo[i];\n        }\n\n        return combo.join(' + ');\n      }\n\n      /**\n       * Hotkey object used internally for consistency\n       *\n       * @param {array}    combo       The keycombo. it's an array to support multiple combos\n       * @param {String}   description Description for the keycombo\n       * @param {Function} callback    function to execute when keycombo pressed\n       * @param {string}   action      the type of event to listen for (for mousetrap)\n       * @param {array}    allowIn     an array of tag names to allow this combo in ('INPUT', 'SELECT', and/or 'TEXTAREA')\n       * @param {Boolean}  persistent  Whether the hotkey persists navigation events\n       */\n      function Hotkey (combo, description, callback, action, allowIn, persistent) {\n        // TODO: Check that the values are sane because we could\n        // be trying to instantiate a new Hotkey with outside dev's\n        // supplied values\n\n        this.combo = combo instanceof Array ? combo : [combo];\n        this.description = description;\n        this.callback = callback;\n        this.action = action;\n        this.allowIn = allowIn;\n        this.persistent = persistent;\n      }\n\n      /**\n       * Helper method to format (symbolize) the key combo for display\n       *\n       * @return {[Array]} An array of the key combination sequence\n       *   for example: \"command+g c i\" becomes [\"⌘ + g\", \"c\", \"i\"]\n       *\n       * TODO: this gets called a lot.  We should cache the result\n       */\n      Hotkey.prototype.format = function() {\n\n        // Don't show all the possible key combos, just the first one.  Not sure\n        // of usecase here, so open a ticket if my assumptions are wrong\n        var combo = this.combo[0];\n\n        var sequence = combo.split(/[\\s]/);\n        for (var i = 0; i < sequence.length; i++) {\n          sequence[i] = symbolize(sequence[i]);\n        }\n\n        return sequence;\n      };\n\n      /**\n       * A new scope used internally for the cheatsheet\n       * @type {$rootScope.Scope}\n       */\n      var scope = $rootScope.$new();\n\n      /**\n       * Holds an array of Hotkey objects currently bound\n       * @type {Array}\n       */\n      scope.hotkeys = [];\n\n      /**\n       * Contains the state of the help's visibility\n       * @type {Boolean}\n       */\n      scope.helpVisible = false;\n\n      /**\n       * Holds the title string for the help menu\n       * @type {String}\n       */\n      scope.title = this.templateTitle;\n\n      /**\n       * Expose toggleCheatSheet to hotkeys scope so we can call it using\n       * ng-click from the template\n       * @type {function}\n       */\n      scope.toggleCheatSheet = toggleCheatSheet;\n\n\n      /**\n       * Holds references to the different scopes that have bound hotkeys\n       * attached.  This is useful to catch when the scopes are `$destroy`d and\n       * then automatically unbind the hotkey.\n       *\n       * @type {Array}\n       */\n      var boundScopes = [];\n\n\n      $rootScope.$on('$routeChangeSuccess', function (event, route) {\n        purgeHotkeys();\n\n        if (route && route.hotkeys) {\n          angular.forEach(route.hotkeys, function (hotkey) {\n            // a string was given, which implies this is a function that is to be\n            // $eval()'d within that controller's scope\n            // TODO: hotkey here is super confusing.  sometimes a function (that gets turned into an array), sometimes a string\n            var callback = hotkey[2];\n            if (typeof(callback) === 'string' || callback instanceof String) {\n              hotkey[2] = [callback, route];\n            }\n\n            // todo: perform check to make sure not already defined:\n            // this came from a route, so it's likely not meant to be persistent\n            hotkey[5] = false;\n            _add.apply(this, hotkey);\n          });\n        }\n      });\n\n\n      // Auto-create a help menu:\n      if (this.includeCheatSheet) {\n        var document = $document[0];\n        var element = $rootElement[0];\n        var helpMenu = angular.element(this.template);\n        _add(this.cheatSheetHotkey, this.cheatSheetDescription, toggleCheatSheet);\n\n        // If $rootElement is document or documentElement, then body must be used\n        if (element === document || element === document.documentElement) {\n          element = document.body;\n        }\n\n        angular.element(element).append($compile(helpMenu)(scope));\n      }\n\n\n      /**\n       * Purges all non-persistent hotkeys (such as those defined in routes)\n       *\n       * Without this, the same hotkey would get recreated everytime\n       * the route is accessed.\n       */\n      function purgeHotkeys() {\n        var i = scope.hotkeys.length;\n        while (i--) {\n          var hotkey = scope.hotkeys[i];\n          if (hotkey && !hotkey.persistent) {\n            _del(hotkey);\n          }\n        }\n      }\n\n      /**\n       * Toggles the help menu element's visiblity\n       */\n      var previousEsc = false;\n\n      function toggleCheatSheet() {\n        scope.helpVisible = !scope.helpVisible;\n\n        // Bind to esc to remove the cheat sheet.  Ideally, this would be done\n        // as a directive in the template, but that would create a nasty\n        // circular dependency issue that I don't feel like sorting out.\n        if (scope.helpVisible) {\n          previousEsc = _get('esc');\n          _del('esc');\n\n          // Here's an odd way to do this: we're going to use the original\n          // description of the hotkey on the cheat sheet so that it shows up.\n          // without it, no entry for esc will ever show up (#22)\n          _add('esc', previousEsc.description, toggleCheatSheet);\n        } else {\n          _del('esc');\n\n          // restore the previously bound ESC key\n          if (previousEsc !== false) {\n            _add(previousEsc);\n          }\n        }\n      }\n\n      /**\n       * Creates a new Hotkey and creates the Mousetrap binding\n       *\n       * @param {string}   combo       mousetrap key binding\n       * @param {string}   description description for the help menu\n       * @param {Function} callback    method to call when key is pressed\n       * @param {string}   action      the type of event to listen for (for mousetrap)\n       * @param {array}    allowIn     an array of tag names to allow this combo in ('INPUT', 'SELECT', and/or 'TEXTAREA')\n       * @param {boolean}  persistent  if true, the binding is preserved upon route changes\n       */\n      function _add (combo, description, callback, action, allowIn, persistent) {\n\n        // used to save original callback for \"allowIn\" wrapping:\n        var _callback;\n\n        // these elements are prevented by the default Mousetrap.stopCallback():\n        var preventIn = ['INPUT', 'SELECT', 'TEXTAREA'];\n\n        // Determine if object format was given:\n        var objType = Object.prototype.toString.call(combo);\n\n        if (objType === '[object Object]') {\n          description = combo.description;\n          callback    = combo.callback;\n          action      = combo.action;\n          persistent  = combo.persistent;\n          allowIn     = combo.allowIn;\n          combo       = combo.combo;\n        }\n\n        // description is optional:\n        if (description instanceof Function) {\n          action = callback;\n          callback = description;\n          description = '$$undefined$$';\n        } else if (angular.isUndefined(description)) {\n          description = '$$undefined$$';\n        }\n\n        // any items added through the public API are for controllers\n        // that persist through navigation, and thus undefined should mean\n        // true in this case.\n        if (persistent === undefined) {\n          persistent = true;\n        }\n\n        // if callback is defined, then wrap it in a function\n        // that checks if the event originated from a form element.\n        // the function blocks the callback from executing unless the element is specified\n        // in allowIn (emulates Mousetrap.stopCallback() on a per-key level)\n        if (typeof callback === 'function') {\n\n          // save the original callback\n          _callback = callback;\n\n          // make sure allowIn is an array\n          if (!(allowIn instanceof Array)) {\n            allowIn = [];\n          }\n\n          // remove anything from preventIn that's present in allowIn\n          var index;\n          for (var i=0; i < allowIn.length; i++) {\n            allowIn[i] = allowIn[i].toUpperCase();\n            index = preventIn.indexOf(allowIn[i]);\n            if (index !== -1) {\n              preventIn.splice(index, 1);\n            }\n          }\n\n          // create the new wrapper callback\n          callback = function(event) {\n            var shouldExecute = true;\n            var target = event.target || event.srcElement; // srcElement is IE only\n            var nodeName = target.nodeName.toUpperCase();\n\n            // check if the input has a mousetrap class, and skip checking preventIn if so\n            if ((' ' + target.className + ' ').indexOf(' mousetrap ') > -1) {\n              shouldExecute = true;\n            } else {\n              // don't execute callback if the event was fired from inside an element listed in preventIn\n              for (var i=0; i<preventIn.length; i++) {\n                if (preventIn[i] === nodeName) {\n                  shouldExecute = false;\n                  break;\n                }\n              }\n            }\n\n            if (shouldExecute) {\n              wrapApply(_callback.apply(this, arguments));\n            }\n          };\n        }\n\n        if (typeof(action) === 'string') {\n          Mousetrap.bind(combo, wrapApply(callback), action);\n        } else {\n          Mousetrap.bind(combo, wrapApply(callback));\n        }\n\n        var hotkey = new Hotkey(combo, description, callback, action, allowIn, persistent);\n        scope.hotkeys.push(hotkey);\n        return hotkey;\n      }\n\n      /**\n       * delete and unbind a Hotkey\n       *\n       * @param  {mixed} hotkey   Either the bound key or an instance of Hotkey\n       * @return {boolean}        true if successful\n       */\n      function _del (hotkey) {\n        var combo = (hotkey instanceof Hotkey) ? hotkey.combo : hotkey;\n\n        Mousetrap.unbind(combo);\n\n        if (angular.isArray(combo)) {\n          var retStatus = true;\n          var i = combo.length;\n          while (i--) {\n            retStatus = _del(combo[i]) && retStatus;\n          }\n          return retStatus;\n        } else {\n          var index = scope.hotkeys.indexOf(_get(combo));\n\n          if (index > -1) {\n            // if the combo has other combos bound, don't unbind the whole thing, just the one combo:\n            if (scope.hotkeys[index].combo.length > 1) {\n              scope.hotkeys[index].combo.splice(scope.hotkeys[index].combo.indexOf(combo), 1);\n            } else {\n              scope.hotkeys.splice(index, 1);\n            }\n            return true;\n          }\n        }\n\n        return false;\n\n      }\n\n      /**\n       * Get a Hotkey object by key binding\n       *\n       * @param  {[string]} combo  the key the Hotkey is bound to\n       * @return {Hotkey}          The Hotkey object\n       */\n      function _get (combo) {\n\n        var hotkey;\n\n        for (var i = 0; i < scope.hotkeys.length; i++) {\n          hotkey = scope.hotkeys[i];\n\n          if (hotkey.combo.indexOf(combo) > -1) {\n            return hotkey;\n          }\n        }\n\n        return false;\n      }\n\n      /**\n       * Binds the hotkey to a particular scope.  Useful if the scope is\n       * destroyed, we can automatically destroy the hotkey binding.\n       *\n       * @param  {Object} scope The scope to bind to\n       */\n      function bindTo (scope) {\n        // Only initialize once to allow multiple calls for same scope.\n        if (!(scope.$id in boundScopes)) {\n\n          // Add the scope to the list of bound scopes\n          boundScopes[scope.$id] = [];\n\n          scope.$on('$destroy', function () {\n            var i = boundScopes[scope.$id].length;\n            while (i--) {\n              _del(boundScopes[scope.$id][i]);\n              delete boundScopes[scope.$id][i];\n            }\n          });\n        }\n        // return an object with an add function so we can keep track of the\n        // hotkeys and their scope that we added via this chaining method\n        return {\n          add: function (args) {\n            var hotkey;\n\n            if (arguments.length > 1) {\n              hotkey = _add.apply(this, arguments);\n            } else {\n              hotkey = _add(args);\n            }\n\n            boundScopes[scope.$id].push(hotkey);\n            return this;\n          }\n        };\n      }\n\n      /**\n       * All callbacks sent to Mousetrap are wrapped using this function\n       * so that we can force a $scope.$apply()\n       *\n       * @param  {Function} callback [description]\n       * @return {[type]}            [description]\n       */\n      function wrapApply (callback) {\n        // return mousetrap a function to call\n        return function (event, combo) {\n\n          // if this is an array, it means we provided a route object\n          // because the scope wasn't available yet, so rewrap the callback\n          // now that the scope is available:\n          if (callback instanceof Array) {\n            var funcString = callback[0];\n            var route = callback[1];\n            callback = function (event) {\n              route.scope.$eval(funcString);\n            };\n          }\n\n          // this takes place outside angular, so we'll have to call\n          // $apply() to make sure angular's digest happens\n          $rootScope.$apply(function() {\n            // call the original hotkey callback with the keyboard event\n            callback(event, _get(combo));\n          });\n        };\n      }\n\n\n      var publicApi = {\n        add                   : _add,\n        del                   : _del,\n        get                   : _get,\n        bindTo                : bindTo,\n        template              : this.template,\n        toggleCheatSheet      : toggleCheatSheet,\n        includeCheatSheet     : this.includeCheatSheet,\n        cheatSheetHotkey      : this.cheatSheetHotkey,\n        cheatSheetDescription : this.cheatSheetDescription,\n        purgeHotkeys          : purgeHotkeys,\n        templateTitle         : this.templateTitle\n      };\n\n      return publicApi;\n\n    }];\n  })\n\n  .directive('hotkey', ['hotkeys', function (hotkeys) {\n    return {\n      restrict: 'A',\n      link: function (scope, el, attrs) {\n        var key, allowIn;\n\n        angular.forEach(scope.$eval(attrs.hotkey), function (func, hotkey) {\n          // split and trim the hotkeys string into array\n          allowIn = typeof attrs.hotkeyAllowIn === \"string\" ? attrs.hotkeyAllowIn.split(/[\\s,]+/) : [];\n\n          key = hotkey;\n\n          hotkeys.add({\n            combo: hotkey,\n            description: attrs.hotkeyDescription,\n            callback: func,\n            action: attrs.hotkeyAction,\n            allowIn: allowIn\n          });\n        });\n\n        // remove the hotkey if the directive is destroyed:\n        el.bind('$destroy', function() {\n          hotkeys.del(key);\n        });\n      }\n    };\n  }])\n\n  .run(['hotkeys', function(hotkeys) {\n    // force hotkeys to run by injecting it. Without this, hotkeys only runs\n    // when a controller or something else asks for it via DI.\n  }]);\n\n})();\n\n/*global define:false */\n/**\n * Copyright 2013 Craig Campbell\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 * Mousetrap is a simple keyboard shortcut library for Javascript with\n * no external dependencies\n *\n * @version 1.4.6\n * @url craig.is/killing/mice\n */\n(function(window, document, undefined) {\n\n    /**\n     * mapping of special keycodes to their corresponding keys\n     *\n     * everything in this dictionary cannot use keypress events\n     * so it has to be here to map to the correct keycodes for\n     * keyup/keydown events\n     *\n     * @type {Object}\n     */\n    var _MAP = {\n            8: 'backspace',\n            9: 'tab',\n            13: 'enter',\n            16: 'shift',\n            17: 'ctrl',\n            18: 'alt',\n            20: 'capslock',\n            27: 'esc',\n            32: 'space',\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: 'ins',\n            46: 'del',\n            91: 'meta',\n            93: 'meta',\n            224: 'meta'\n        },\n\n        /**\n         * mapping for special characters so they can support\n         *\n         * this dictionary is only used incase you want to bind a\n         * keyup or keydown event to one of these keys\n         *\n         * @type {Object}\n         */\n        _KEYCODE_MAP = {\n            106: '*',\n            107: '+',\n            109: '-',\n            110: '.',\n            111 : '/',\n            186: ';',\n            187: '=',\n            188: ',',\n            189: '-',\n            190: '.',\n            191: '/',\n            192: '`',\n            219: '[',\n            220: '\\\\',\n            221: ']',\n            222: '\\''\n        },\n\n        /**\n         * this is a mapping of keys that require shift on a US keypad\n         * back to the non shift equivelents\n         *\n         * this is so you can use keyup events with these keys\n         *\n         * note that this will only work reliably on US keyboards\n         *\n         * @type {Object}\n         */\n        _SHIFT_MAP = {\n            '~': '`',\n            '!': '1',\n            '@': '2',\n            '#': '3',\n            '$': '4',\n            '%': '5',\n            '^': '6',\n            '&': '7',\n            '*': '8',\n            '(': '9',\n            ')': '0',\n            '_': '-',\n            '+': '=',\n            ':': ';',\n            '\\\"': '\\'',\n            '<': ',',\n            '>': '.',\n            '?': '/',\n            '|': '\\\\'\n        },\n\n        /**\n         * this is a list of special strings you can use to map\n         * to modifier keys when you specify your keyboard shortcuts\n         *\n         * @type {Object}\n         */\n        _SPECIAL_ALIASES = {\n            'option': 'alt',\n            'command': 'meta',\n            'return': 'enter',\n            'escape': 'esc',\n            'mod': /Mac|iPod|iPhone|iPad/.test(navigator.platform) ? 'meta' : 'ctrl'\n        },\n\n        /**\n         * variable to store the flipped version of _MAP from above\n         * needed to check if we should use keypress or not when no action\n         * is specified\n         *\n         * @type {Object|undefined}\n         */\n        _REVERSE_MAP,\n\n        /**\n         * a list of all the callbacks setup via Mousetrap.bind()\n         *\n         * @type {Object}\n         */\n        _callbacks = {},\n\n        /**\n         * direct map of string combinations to callbacks used for trigger()\n         *\n         * @type {Object}\n         */\n        _directMap = {},\n\n        /**\n         * keeps track of what level each sequence is at since multiple\n         * sequences can start out with the same sequence\n         *\n         * @type {Object}\n         */\n        _sequenceLevels = {},\n\n        /**\n         * variable to store the setTimeout call\n         *\n         * @type {null|number}\n         */\n        _resetTimer,\n\n        /**\n         * temporary state where we will ignore the next keyup\n         *\n         * @type {boolean|string}\n         */\n        _ignoreNextKeyup = false,\n\n        /**\n         * temporary state where we will ignore the next keypress\n         *\n         * @type {boolean}\n         */\n        _ignoreNextKeypress = false,\n\n        /**\n         * are we currently inside of a sequence?\n         * type of action (\"keyup\" or \"keydown\" or \"keypress\") or false\n         *\n         * @type {boolean|string}\n         */\n        _nextExpectedAction = false;\n\n    /**\n     * loop through the f keys, f1 to f19 and add them to the map\n     * programatically\n     */\n    for (var i = 1; i < 20; ++i) {\n        _MAP[111 + i] = 'f' + i;\n    }\n\n    /**\n     * loop through to map numbers on the numeric keypad\n     */\n    for (i = 0; i <= 9; ++i) {\n        _MAP[i + 96] = i;\n    }\n\n    /**\n     * cross browser add event method\n     *\n     * @param {Element|HTMLDocument} object\n     * @param {string} type\n     * @param {Function} callback\n     * @returns void\n     */\n    function _addEvent(object, type, callback) {\n        if (object.addEventListener) {\n            object.addEventListener(type, callback, false);\n            return;\n        }\n\n        object.attachEvent('on' + type, callback);\n    }\n\n    /**\n     * takes the event and returns the key character\n     *\n     * @param {Event} e\n     * @return {string}\n     */\n    function _characterFromEvent(e) {\n\n        // for keypress events we should return the character as is\n        if (e.type == 'keypress') {\n            var character = String.fromCharCode(e.which);\n\n            // if the shift key is not pressed then it is safe to assume\n            // that we want the character to be lowercase.  this means if\n            // you accidentally have caps lock on then your key bindings\n            // will continue to work\n            //\n            // the only side effect that might not be desired is if you\n            // bind something like 'A' cause you want to trigger an\n            // event when capital A is pressed caps lock will no longer\n            // trigger the event.  shift+a will though.\n            if (!e.shiftKey) {\n                character = character.toLowerCase();\n            }\n\n            return character;\n        }\n\n        // for non keypress events the special maps are needed\n        if (_MAP[e.which]) {\n            return _MAP[e.which];\n        }\n\n        if (_KEYCODE_MAP[e.which]) {\n            return _KEYCODE_MAP[e.which];\n        }\n\n        // if it is not in the special map\n\n        // with keydown and keyup events the character seems to always\n        // come in as an uppercase character whether you are pressing shift\n        // or not.  we should make sure it is always lowercase for comparisons\n        return String.fromCharCode(e.which).toLowerCase();\n    }\n\n    /**\n     * checks if two arrays are equal\n     *\n     * @param {Array} modifiers1\n     * @param {Array} modifiers2\n     * @returns {boolean}\n     */\n    function _modifiersMatch(modifiers1, modifiers2) {\n        return modifiers1.sort().join(',') === modifiers2.sort().join(',');\n    }\n\n    /**\n     * resets all sequence counters except for the ones passed in\n     *\n     * @param {Object} doNotReset\n     * @returns void\n     */\n    function _resetSequences(doNotReset) {\n        doNotReset = doNotReset || {};\n\n        var activeSequences = false,\n            key;\n\n        for (key in _sequenceLevels) {\n            if (doNotReset[key]) {\n                activeSequences = true;\n                continue;\n            }\n            _sequenceLevels[key] = 0;\n        }\n\n        if (!activeSequences) {\n            _nextExpectedAction = false;\n        }\n    }\n\n    /**\n     * finds all callbacks that match based on the keycode, modifiers,\n     * and action\n     *\n     * @param {string} character\n     * @param {Array} modifiers\n     * @param {Event|Object} e\n     * @param {string=} sequenceName - name of the sequence we are looking for\n     * @param {string=} combination\n     * @param {number=} level\n     * @returns {Array}\n     */\n    function _getMatches(character, modifiers, e, sequenceName, combination, level) {\n        var i,\n            callback,\n            matches = [],\n            action = e.type;\n\n        // if there are no events related to this keycode\n        if (!_callbacks[character]) {\n            return [];\n        }\n\n        // if a modifier key is coming up on its own we should allow it\n        if (action == 'keyup' && _isModifier(character)) {\n            modifiers = [character];\n        }\n\n        // loop through all callbacks for the key that was pressed\n        // and see if any of them match\n        for (i = 0; i < _callbacks[character].length; ++i) {\n            callback = _callbacks[character][i];\n\n            // if a sequence name is not specified, but this is a sequence at\n            // the wrong level then move onto the next match\n            if (!sequenceName && callback.seq && _sequenceLevels[callback.seq] != callback.level) {\n                continue;\n            }\n\n            // if the action we are looking for doesn't match the action we got\n            // then we should keep going\n            if (action != callback.action) {\n                continue;\n            }\n\n            // if this is a keypress event and the meta key and control key\n            // are not pressed that means that we need to only look at the\n            // character, otherwise check the modifiers as well\n            //\n            // chrome will not fire a keypress if meta or control is down\n            // safari will fire a keypress if meta or meta+shift is down\n            // firefox will fire a keypress if meta or control is down\n            if ((action == 'keypress' && !e.metaKey && !e.ctrlKey) || _modifiersMatch(modifiers, callback.modifiers)) {\n\n                // when you bind a combination or sequence a second time it\n                // should overwrite the first one.  if a sequenceName or\n                // combination is specified in this call it does just that\n                //\n                // @todo make deleting its own method?\n                var deleteCombo = !sequenceName && callback.combo == combination;\n                var deleteSequence = sequenceName && callback.seq == sequenceName && callback.level == level;\n                if (deleteCombo || deleteSequence) {\n                    _callbacks[character].splice(i, 1);\n                }\n\n                matches.push(callback);\n            }\n        }\n\n        return matches;\n    }\n\n    /**\n     * takes a key event and figures out what the modifiers are\n     *\n     * @param {Event} e\n     * @returns {Array}\n     */\n    function _eventModifiers(e) {\n        var modifiers = [];\n\n        if (e.shiftKey) {\n            modifiers.push('shift');\n        }\n\n        if (e.altKey) {\n            modifiers.push('alt');\n        }\n\n        if (e.ctrlKey) {\n            modifiers.push('ctrl');\n        }\n\n        if (e.metaKey) {\n            modifiers.push('meta');\n        }\n\n        return modifiers;\n    }\n\n    /**\n     * prevents default for this event\n     *\n     * @param {Event} e\n     * @returns void\n     */\n    function _preventDefault(e) {\n        if (e.preventDefault) {\n            e.preventDefault();\n            return;\n        }\n\n        e.returnValue = false;\n    }\n\n    /**\n     * stops propogation for this event\n     *\n     * @param {Event} e\n     * @returns void\n     */\n    function _stopPropagation(e) {\n        if (e.stopPropagation) {\n            e.stopPropagation();\n            return;\n        }\n\n        e.cancelBubble = true;\n    }\n\n    /**\n     * actually calls the callback function\n     *\n     * if your callback function returns false this will use the jquery\n     * convention - prevent default and stop propogation on the event\n     *\n     * @param {Function} callback\n     * @param {Event} e\n     * @returns void\n     */\n    function _fireCallback(callback, e, combo, sequence) {\n\n        // if this event should not happen stop here\n        if (Mousetrap.stopCallback(e, e.target || e.srcElement, combo, sequence)) {\n            return;\n        }\n\n        if (callback(e, combo) === false) {\n            _preventDefault(e);\n            _stopPropagation(e);\n        }\n    }\n\n    /**\n     * handles a character key event\n     *\n     * @param {string} character\n     * @param {Array} modifiers\n     * @param {Event} e\n     * @returns void\n     */\n    function _handleKey(character, modifiers, e) {\n        var callbacks = _getMatches(character, modifiers, e),\n            i,\n            doNotReset = {},\n            maxLevel = 0,\n            processedSequenceCallback = false;\n\n        // Calculate the maxLevel for sequences so we can only execute the longest callback sequence\n        for (i = 0; i < callbacks.length; ++i) {\n            if (callbacks[i].seq) {\n                maxLevel = Math.max(maxLevel, callbacks[i].level);\n            }\n        }\n\n        // loop through matching callbacks for this key event\n        for (i = 0; i < callbacks.length; ++i) {\n\n            // fire for all sequence callbacks\n            // this is because if for example you have multiple sequences\n            // bound such as \"g i\" and \"g t\" they both need to fire the\n            // callback for matching g cause otherwise you can only ever\n            // match the first one\n            if (callbacks[i].seq) {\n\n                // only fire callbacks for the maxLevel to prevent\n                // subsequences from also firing\n                //\n                // for example 'a option b' should not cause 'option b' to fire\n                // even though 'option b' is part of the other sequence\n                //\n                // any sequences that do not match here will be discarded\n                // below by the _resetSequences call\n                if (callbacks[i].level != maxLevel) {\n                    continue;\n                }\n\n                processedSequenceCallback = true;\n\n                // keep a list of which sequences were matches for later\n                doNotReset[callbacks[i].seq] = 1;\n                _fireCallback(callbacks[i].callback, e, callbacks[i].combo, callbacks[i].seq);\n                continue;\n            }\n\n            // if there were no sequence matches but we are still here\n            // that means this is a regular match so we should fire that\n            if (!processedSequenceCallback) {\n                _fireCallback(callbacks[i].callback, e, callbacks[i].combo);\n            }\n        }\n\n        // if the key you pressed matches the type of sequence without\n        // being a modifier (ie \"keyup\" or \"keypress\") then we should\n        // reset all sequences that were not matched by this event\n        //\n        // this is so, for example, if you have the sequence \"h a t\" and you\n        // type \"h e a r t\" it does not match.  in this case the \"e\" will\n        // cause the sequence to reset\n        //\n        // modifier keys are ignored because you can have a sequence\n        // that contains modifiers such as \"enter ctrl+space\" and in most\n        // cases the modifier key will be pressed before the next key\n        //\n        // also if you have a sequence such as \"ctrl+b a\" then pressing the\n        // \"b\" key will trigger a \"keypress\" and a \"keydown\"\n        //\n        // the \"keydown\" is expected when there is a modifier, but the\n        // \"keypress\" ends up matching the _nextExpectedAction since it occurs\n        // after and that causes the sequence to reset\n        //\n        // we ignore keypresses in a sequence that directly follow a keydown\n        // for the same character\n        var ignoreThisKeypress = e.type == 'keypress' && _ignoreNextKeypress;\n        if (e.type == _nextExpectedAction && !_isModifier(character) && !ignoreThisKeypress) {\n            _resetSequences(doNotReset);\n        }\n\n        _ignoreNextKeypress = processedSequenceCallback && e.type == 'keydown';\n    }\n\n    /**\n     * handles a keydown event\n     *\n     * @param {Event} e\n     * @returns void\n     */\n    function _handleKeyEvent(e) {\n\n        // normalize e.which for key events\n        // @see http://stackoverflow.com/questions/4285627/javascript-keycode-vs-charcode-utter-confusion\n        if (typeof e.which !== 'number') {\n            e.which = e.keyCode;\n        }\n\n        var character = _characterFromEvent(e);\n\n        // no character found then stop\n        if (!character) {\n            return;\n        }\n\n        // need to use === for the character check because the character can be 0\n        if (e.type == 'keyup' && _ignoreNextKeyup === character) {\n            _ignoreNextKeyup = false;\n            return;\n        }\n\n        Mousetrap.handleKey(character, _eventModifiers(e), e);\n    }\n\n    /**\n     * determines if the keycode specified is a modifier key or not\n     *\n     * @param {string} key\n     * @returns {boolean}\n     */\n    function _isModifier(key) {\n        return key == 'shift' || key == 'ctrl' || key == 'alt' || key == 'meta';\n    }\n\n    /**\n     * called to set a 1 second timeout on the specified sequence\n     *\n     * this is so after each key press in the sequence you have 1 second\n     * to press the next key before you have to start over\n     *\n     * @returns void\n     */\n    function _resetSequenceTimer() {\n        clearTimeout(_resetTimer);\n        _resetTimer = setTimeout(_resetSequences, 1000);\n    }\n\n    /**\n     * reverses the map lookup so that we can look for specific keys\n     * to see what can and can't use keypress\n     *\n     * @return {Object}\n     */\n    function _getReverseMap() {\n        if (!_REVERSE_MAP) {\n            _REVERSE_MAP = {};\n            for (var key in _MAP) {\n\n                // pull out the numeric keypad from here cause keypress should\n                // be able to detect the keys from the character\n                if (key > 95 && key < 112) {\n                    continue;\n                }\n\n                if (_MAP.hasOwnProperty(key)) {\n                    _REVERSE_MAP[_MAP[key]] = key;\n                }\n            }\n        }\n        return _REVERSE_MAP;\n    }\n\n    /**\n     * picks the best action based on the key combination\n     *\n     * @param {string} key - character for key\n     * @param {Array} modifiers\n     * @param {string=} action passed in\n     */\n    function _pickBestAction(key, modifiers, action) {\n\n        // if no action was picked in we should try to pick the one\n        // that we think would work best for this key\n        if (!action) {\n            action = _getReverseMap()[key] ? 'keydown' : 'keypress';\n        }\n\n        // modifier keys don't work as expected with keypress,\n        // switch to keydown\n        if (action == 'keypress' && modifiers.length) {\n            action = 'keydown';\n        }\n\n        return action;\n    }\n\n    /**\n     * binds a key sequence to an event\n     *\n     * @param {string} combo - combo specified in bind call\n     * @param {Array} keys\n     * @param {Function} callback\n     * @param {string=} action\n     * @returns void\n     */\n    function _bindSequence(combo, keys, callback, action) {\n\n        // start off by adding a sequence level record for this combination\n        // and setting the level to 0\n        _sequenceLevels[combo] = 0;\n\n        /**\n         * callback to increase the sequence level for this sequence and reset\n         * all other sequences that were active\n         *\n         * @param {string} nextAction\n         * @returns {Function}\n         */\n        function _increaseSequence(nextAction) {\n            return function() {\n                _nextExpectedAction = nextAction;\n                ++_sequenceLevels[combo];\n                _resetSequenceTimer();\n            };\n        }\n\n        /**\n         * wraps the specified callback inside of another function in order\n         * to reset all sequence counters as soon as this sequence is done\n         *\n         * @param {Event} e\n         * @returns void\n         */\n        function _callbackAndReset(e) {\n            _fireCallback(callback, e, combo);\n\n            // we should ignore the next key up if the action is key down\n            // or keypress.  this is so if you finish a sequence and\n            // release the key the final key will not trigger a keyup\n            if (action !== 'keyup') {\n                _ignoreNextKeyup = _characterFromEvent(e);\n            }\n\n            // weird race condition if a sequence ends with the key\n            // another sequence begins with\n            setTimeout(_resetSequences, 10);\n        }\n\n        // loop through keys one at a time and bind the appropriate callback\n        // function.  for any key leading up to the final one it should\n        // increase the sequence. after the final, it should reset all sequences\n        //\n        // if an action is specified in the original bind call then that will\n        // be used throughout.  otherwise we will pass the action that the\n        // next key in the sequence should match.  this allows a sequence\n        // to mix and match keypress and keydown events depending on which\n        // ones are better suited to the key provided\n        for (var i = 0; i < keys.length; ++i) {\n            var isFinal = i + 1 === keys.length;\n            var wrappedCallback = isFinal ? _callbackAndReset : _increaseSequence(action || _getKeyInfo(keys[i + 1]).action);\n            _bindSingle(keys[i], wrappedCallback, action, combo, i);\n        }\n    }\n\n    /**\n     * Converts from a string key combination to an array\n     *\n     * @param  {string} combination like \"command+shift+l\"\n     * @return {Array}\n     */\n    function _keysFromString(combination) {\n        if (combination === '+') {\n            return ['+'];\n        }\n\n        return combination.split('+');\n    }\n\n    /**\n     * Gets info for a specific key combination\n     *\n     * @param  {string} combination key combination (\"command+s\" or \"a\" or \"*\")\n     * @param  {string=} action\n     * @returns {Object}\n     */\n    function _getKeyInfo(combination, action) {\n        var keys,\n            key,\n            i,\n            modifiers = [];\n\n        // take the keys from this pattern and figure out what the actual\n        // pattern is all about\n        keys = _keysFromString(combination);\n\n        for (i = 0; i < keys.length; ++i) {\n            key = keys[i];\n\n            // normalize key names\n            if (_SPECIAL_ALIASES[key]) {\n                key = _SPECIAL_ALIASES[key];\n            }\n\n            // if this is not a keypress event then we should\n            // be smart about using shift keys\n            // this will only work for US keyboards however\n            if (action && action != 'keypress' && _SHIFT_MAP[key]) {\n                key = _SHIFT_MAP[key];\n                modifiers.push('shift');\n            }\n\n            // if this key is a modifier then add it to the list of modifiers\n            if (_isModifier(key)) {\n                modifiers.push(key);\n            }\n        }\n\n        // depending on what the key combination is\n        // we will try to pick the best event for it\n        action = _pickBestAction(key, modifiers, action);\n\n        return {\n            key: key,\n            modifiers: modifiers,\n            action: action\n        };\n    }\n\n    /**\n     * binds a single keyboard combination\n     *\n     * @param {string} combination\n     * @param {Function} callback\n     * @param {string=} action\n     * @param {string=} sequenceName - name of sequence if part of sequence\n     * @param {number=} level - what part of the sequence the command is\n     * @returns void\n     */\n    function _bindSingle(combination, callback, action, sequenceName, level) {\n\n        // store a direct mapped reference for use with Mousetrap.trigger\n        _directMap[combination + ':' + action] = callback;\n\n        // make sure multiple spaces in a row become a single space\n        combination = combination.replace(/\\s+/g, ' ');\n\n        var sequence = combination.split(' '),\n            info;\n\n        // if this pattern is a sequence of keys then run through this method\n        // to reprocess each pattern one key at a time\n        if (sequence.length > 1) {\n            _bindSequence(combination, sequence, callback, action);\n            return;\n        }\n\n        info = _getKeyInfo(combination, action);\n\n        // make sure to initialize array if this is the first time\n        // a callback is added for this key\n        _callbacks[info.key] = _callbacks[info.key] || [];\n\n        // remove an existing match if there is one\n        _getMatches(info.key, info.modifiers, {type: info.action}, sequenceName, combination, level);\n\n        // add this call back to the array\n        // if it is a sequence put it at the beginning\n        // if not put it at the end\n        //\n        // this is important because the way these are processed expects\n        // the sequence ones to come first\n        _callbacks[info.key][sequenceName ? 'unshift' : 'push']({\n            callback: callback,\n            modifiers: info.modifiers,\n            action: info.action,\n            seq: sequenceName,\n            level: level,\n            combo: combination\n        });\n    }\n\n    /**\n     * binds multiple combinations to the same callback\n     *\n     * @param {Array} combinations\n     * @param {Function} callback\n     * @param {string|undefined} action\n     * @returns void\n     */\n    function _bindMultiple(combinations, callback, action) {\n        for (var i = 0; i < combinations.length; ++i) {\n            _bindSingle(combinations[i], callback, action);\n        }\n    }\n\n    // start!\n    _addEvent(document, 'keypress', _handleKeyEvent);\n    _addEvent(document, 'keydown', _handleKeyEvent);\n    _addEvent(document, 'keyup', _handleKeyEvent);\n\n    var Mousetrap = {\n\n        /**\n         * binds an event to mousetrap\n         *\n         * can be a single key, a combination of keys separated with +,\n         * an array of keys, or a sequence of keys separated by spaces\n         *\n         * be sure to list the modifier keys first to make sure that the\n         * correct key ends up getting bound (the last key in the pattern)\n         *\n         * @param {string|Array} keys\n         * @param {Function} callback\n         * @param {string=} action - 'keypress', 'keydown', or 'keyup'\n         * @returns void\n         */\n        bind: function(keys, callback, action) {\n            keys = keys instanceof Array ? keys : [keys];\n            _bindMultiple(keys, callback, action);\n            return this;\n        },\n\n        /**\n         * unbinds an event to mousetrap\n         *\n         * the unbinding sets the callback function of the specified key combo\n         * to an empty function and deletes the corresponding key in the\n         * _directMap dict.\n         *\n         * TODO: actually remove this from the _callbacks dictionary instead\n         * of binding an empty function\n         *\n         * the keycombo+action has to be exactly the same as\n         * it was defined in the bind method\n         *\n         * @param {string|Array} keys\n         * @param {string} action\n         * @returns void\n         */\n        unbind: function(keys, action) {\n            return Mousetrap.bind(keys, function() {}, action);\n        },\n\n        /**\n         * triggers an event that has already been bound\n         *\n         * @param {string} keys\n         * @param {string=} action\n         * @returns void\n         */\n        trigger: function(keys, action) {\n            if (_directMap[keys + ':' + action]) {\n                _directMap[keys + ':' + action]({}, keys);\n            }\n            return this;\n        },\n\n        /**\n         * resets the library back to its initial state.  this is useful\n         * if you want to clear out the current keyboard shortcuts and bind\n         * new ones - for example if you switch to another page\n         *\n         * @returns void\n         */\n        reset: function() {\n            _callbacks = {};\n            _directMap = {};\n            return this;\n        },\n\n       /**\n        * should we stop this event before firing off callbacks\n        *\n        * @param {Event} e\n        * @param {Element} element\n        * @return {boolean}\n        */\n        stopCallback: function(e, element) {\n\n            // if the element has the class \"mousetrap\" then no need to stop\n            if ((' ' + element.className + ' ').indexOf(' mousetrap ') > -1) {\n                return false;\n            }\n\n            // stop for input, select, and textarea\n            return element.tagName == 'INPUT' || element.tagName == 'SELECT' || element.tagName == 'TEXTAREA' || element.isContentEditable;\n        },\n\n        /**\n         * exposes _handleKey publicly so it can be overwritten by extensions\n         */\n        handleKey: _handleKey\n    };\n\n    // expose mousetrap to the global object\n    window.Mousetrap = Mousetrap;\n\n    /*\n    <FLOWABLE PATCH START>\n     Can't let hotkeys define itself as a module since it will cause Flowable to not work in Alfresco Share:\n     In Share this file is being loaded from a <script> element (and not using dojos and define/require calls)\n     dojo therefor throws an error named \"multipleDefine\" ( http://dojotoolkit.org/reference-guide/1.10/loader/amd.html )\n     and stops the app.\n\n    // expose mousetrap as an AMD module\n    if (typeof define === 'function' && define.amd) {\n        define(Mousetrap);\n    }\n\n     <FLOWABLE PATCH STOP>\n    */\n}) (window, document);\n"
  },
  {
    "path": "flowable-ui-web/idm/libs/angular-hotkeys_1.4.5/hotkeys.css",
    "content": "/*! \n * angular-hotkeys v1.4.5\n * https://chieffancypants.github.io/angular-hotkeys\n * Copyright (c) 2014 Wes Cruver\n * License: MIT\n */\n.cfp-hotkeys-container {\n  display: table !important;\n  position: fixed;\n  width: 100%;\n  height: 100%;\n  top: 0;\n  left: 0;\n  color: #333;\n  font-size: 1em;\n  background-color: rgba(255,255,255,0.9);\n}\n\n.cfp-hotkeys-container.fade {\n  z-index: -1024;\n  visibility: hidden;\n  opacity: 0;\n  -webkit-transition: opacity 0.15s linear;\n  -moz-transition: opacity 0.15s linear;\n  -o-transition: opacity 0.15s linear;\n  transition: opacity 0.15s linear;\n}\n\n.cfp-hotkeys-container.fade.in {\n  z-index: 10002;\n  visibility: visible;\n  opacity: 1;\n}\n\n.cfp-hotkeys-title {\n  font-weight: bold;\n  text-align: center;\n  font-size: 1.2em;\n}\n\n.cfp-hotkeys {\n  width: 100%;\n  height: 100%;\n  display: table-cell;\n  vertical-align: middle;\n}\n\n.cfp-hotkeys table {\n  margin: auto;\n  color: #333;\n}\n\n.cfp-content {\n  display: table-cell;\n  vertical-align: middle;\n}\n\n.cfp-hotkeys-keys {\n  padding: 5px;\n  text-align: right;\n}\n\n.cfp-hotkeys-key {\n  display: inline-block;\n  color: #fff;\n  background-color: #333;\n  border: 1px solid #333;\n  border-radius: 5px;\n  text-align: center;\n  margin-right: 5px;\n  box-shadow: inset 0 1px 0 #666, 0 1px 0 #bbb;\n  padding: 5px 9px;\n  font-size: 1em;\n}\n\n.cfp-hotkeys-text {\n  padding-left: 10px;\n  font-size: 1em;\n}\n\n.cfp-hotkeys-close {\n  position: fixed;\n  top: 20px;\n  right: 20px;\n  font-size: 2em;\n  font-weight: bold;\n  padding: 5px 10px;\n  border: 1px solid #ddd;\n  border-radius: 5px;\n  min-height: 45px;\n  min-width: 45px;\n  text-align: center;\n}\n\n.cfp-hotkeys-close:hover {\n  background-color: #fff;\n  cursor: pointer;\n}\n\n@media all and (max-width: 500px) {\n  .cfp-hotkeys {\n    font-size: 0.8em;\n  }\n}\n\n@media all and (min-width: 750px) {\n  .cfp-hotkeys {\n    font-size: 1.2em;\n  }\n}\n"
  },
  {
    "path": "flowable-ui-web/idm/libs/angular-hotkeys_1.4.5/hotkeys.js",
    "content": "/*! \n * angular-hotkeys v1.4.5\n * https://chieffancypants.github.io/angular-hotkeys\n * Copyright (c) 2014 Wes Cruver\n * License: MIT\n */\n/*\n * angular-hotkeys\n *\n * Automatic keyboard shortcuts for your angular apps\n *\n * (c) 2014 Wes Cruver\n * License: MIT\n */\n\n(function() {\n\n  'use strict';\n\n  angular.module('cfp.hotkeys', []).provider('hotkeys', function() {\n\n    /**\n     * Configurable setting to disable the cheatsheet entirely\n     * @type {Boolean}\n     */\n    this.includeCheatSheet = true;\n\n    /**\n     * Configurable setting for the cheat sheet title\n     * @type {String}\n     */\n\n    this.templateTitle = 'Keyboard Shortcuts:';\n\n    /**\n     * Cheat sheet template in the event you want to totally customize it.\n     * @type {String}\n     */\n    this.template = '<div class=\"cfp-hotkeys-container fade\" ng-class=\"{in: helpVisible}\" style=\"display: none;\"><div class=\"cfp-hotkeys\">' +\n                      '<h4 class=\"cfp-hotkeys-title\">{{ title }}</h4>' +\n                      '<table><tbody>' +\n                        '<tr ng-repeat=\"hotkey in hotkeys | filter:{ description: \\'!$$undefined$$\\' }\">' +\n                          '<td class=\"cfp-hotkeys-keys\">' +\n                            '<span ng-repeat=\"key in hotkey.format() track by $index\" class=\"cfp-hotkeys-key\">{{ key }}</span>' +\n                          '</td>' +\n                          '<td class=\"cfp-hotkeys-text\">{{ hotkey.description }}</td>' +\n                        '</tr>' +\n                      '</tbody></table>' +\n                      '<div class=\"cfp-hotkeys-close\" ng-click=\"toggleCheatSheet()\">×</div>' +\n                    '</div></div>';\n\n    /**\n     * Configurable setting for the cheat sheet hotkey\n     * @type {String}\n     */\n    this.cheatSheetHotkey = '?';\n\n    /**\n     * Configurable setting for the cheat sheet description\n     * @type {String}\n     */\n    this.cheatSheetDescription = 'Show / hide this help menu';\n\n    this.$get = ['$rootElement', '$rootScope', '$compile', '$window', '$document', function ($rootElement, $rootScope, $compile, $window, $document) {\n\n      // monkeypatch Mousetrap's stopCallback() function\n      // this version doesn't return true when the element is an INPUT, SELECT, or TEXTAREA\n      // (instead we will perform this check per-key in the _add() method)\n      Mousetrap.stopCallback = function(event, element) {\n        // if the element has the class \"mousetrap\" then no need to stop\n        if ((' ' + element.className + ' ').indexOf(' mousetrap ') > -1) {\n          return false;\n        }\n\n        return (element.contentEditable && element.contentEditable == 'true');\n      };\n\n      /**\n       * Convert strings like cmd into symbols like ⌘\n       * @param  {String} combo Key combination, e.g. 'mod+f'\n       * @return {String}       The key combination with symbols\n       */\n      function symbolize (combo) {\n        var map = {\n          command   : '⌘',\n          shift     : '⇧',\n          left      : '←',\n          right     : '→',\n          up        : '↑',\n          down      : '↓',\n          'return'  : '↩',\n          backspace : '⌫'\n        };\n        combo = combo.split('+');\n\n        for (var i = 0; i < combo.length; i++) {\n          // try to resolve command / ctrl based on OS:\n          if (combo[i] === 'mod') {\n            if ($window.navigator && $window.navigator.platform.indexOf('Mac') >=0 ) {\n              combo[i] = 'command';\n            } else {\n              combo[i] = 'ctrl';\n            }\n          }\n\n          combo[i] = map[combo[i]] || combo[i];\n        }\n\n        return combo.join(' + ');\n      }\n\n      /**\n       * Hotkey object used internally for consistency\n       *\n       * @param {array}    combo       The keycombo. it's an array to support multiple combos\n       * @param {String}   description Description for the keycombo\n       * @param {Function} callback    function to execute when keycombo pressed\n       * @param {string}   action      the type of event to listen for (for mousetrap)\n       * @param {array}    allowIn     an array of tag names to allow this combo in ('INPUT', 'SELECT', and/or 'TEXTAREA')\n       * @param {Boolean}  persistent  Whether the hotkey persists navigation events\n       */\n      function Hotkey (combo, description, callback, action, allowIn, persistent) {\n        // TODO: Check that the values are sane because we could\n        // be trying to instantiate a new Hotkey with outside dev's\n        // supplied values\n\n        this.combo = combo instanceof Array ? combo : [combo];\n        this.description = description;\n        this.callback = callback;\n        this.action = action;\n        this.allowIn = allowIn;\n        this.persistent = persistent;\n      }\n\n      /**\n       * Helper method to format (symbolize) the key combo for display\n       *\n       * @return {[Array]} An array of the key combination sequence\n       *   for example: \"command+g c i\" becomes [\"⌘ + g\", \"c\", \"i\"]\n       *\n       * TODO: this gets called a lot.  We should cache the result\n       */\n      Hotkey.prototype.format = function() {\n\n        // Don't show all the possible key combos, just the first one.  Not sure\n        // of usecase here, so open a ticket if my assumptions are wrong\n        var combo = this.combo[0];\n\n        var sequence = combo.split(/[\\s]/);\n        for (var i = 0; i < sequence.length; i++) {\n          sequence[i] = symbolize(sequence[i]);\n        }\n\n        return sequence;\n      };\n\n      /**\n       * A new scope used internally for the cheatsheet\n       * @type {$rootScope.Scope}\n       */\n      var scope = $rootScope.$new();\n\n      /**\n       * Holds an array of Hotkey objects currently bound\n       * @type {Array}\n       */\n      scope.hotkeys = [];\n\n      /**\n       * Contains the state of the help's visibility\n       * @type {Boolean}\n       */\n      scope.helpVisible = false;\n\n      /**\n       * Holds the title string for the help menu\n       * @type {String}\n       */\n      scope.title = this.templateTitle;\n\n      /**\n       * Expose toggleCheatSheet to hotkeys scope so we can call it using\n       * ng-click from the template\n       * @type {function}\n       */\n      scope.toggleCheatSheet = toggleCheatSheet;\n\n\n      /**\n       * Holds references to the different scopes that have bound hotkeys\n       * attached.  This is useful to catch when the scopes are `$destroy`d and\n       * then automatically unbind the hotkey.\n       *\n       * @type {Array}\n       */\n      var boundScopes = [];\n\n\n      $rootScope.$on('$routeChangeSuccess', function (event, route) {\n        purgeHotkeys();\n\n        if (route && route.hotkeys) {\n          angular.forEach(route.hotkeys, function (hotkey) {\n            // a string was given, which implies this is a function that is to be\n            // $eval()'d within that controller's scope\n            // TODO: hotkey here is super confusing.  sometimes a function (that gets turned into an array), sometimes a string\n            var callback = hotkey[2];\n            if (typeof(callback) === 'string' || callback instanceof String) {\n              hotkey[2] = [callback, route];\n            }\n\n            // todo: perform check to make sure not already defined:\n            // this came from a route, so it's likely not meant to be persistent\n            hotkey[5] = false;\n            _add.apply(this, hotkey);\n          });\n        }\n      });\n\n\n      // Auto-create a help menu:\n      if (this.includeCheatSheet) {\n        var document = $document[0];\n        var element = $rootElement[0];\n        var helpMenu = angular.element(this.template);\n        _add(this.cheatSheetHotkey, this.cheatSheetDescription, toggleCheatSheet);\n\n        // If $rootElement is document or documentElement, then body must be used\n        if (element === document || element === document.documentElement) {\n          element = document.body;\n        }\n\n        angular.element(element).append($compile(helpMenu)(scope));\n      }\n\n\n      /**\n       * Purges all non-persistent hotkeys (such as those defined in routes)\n       *\n       * Without this, the same hotkey would get recreated everytime\n       * the route is accessed.\n       */\n      function purgeHotkeys() {\n        var i = scope.hotkeys.length;\n        while (i--) {\n          var hotkey = scope.hotkeys[i];\n          if (hotkey && !hotkey.persistent) {\n            _del(hotkey);\n          }\n        }\n      }\n\n      /**\n       * Toggles the help menu element's visiblity\n       */\n      var previousEsc = false;\n\n      function toggleCheatSheet() {\n        scope.helpVisible = !scope.helpVisible;\n\n        // Bind to esc to remove the cheat sheet.  Ideally, this would be done\n        // as a directive in the template, but that would create a nasty\n        // circular dependency issue that I don't feel like sorting out.\n        if (scope.helpVisible) {\n          previousEsc = _get('esc');\n          _del('esc');\n\n          // Here's an odd way to do this: we're going to use the original\n          // description of the hotkey on the cheat sheet so that it shows up.\n          // without it, no entry for esc will ever show up (#22)\n          _add('esc', previousEsc.description, toggleCheatSheet);\n        } else {\n          _del('esc');\n\n          // restore the previously bound ESC key\n          if (previousEsc !== false) {\n            _add(previousEsc);\n          }\n        }\n      }\n\n      /**\n       * Creates a new Hotkey and creates the Mousetrap binding\n       *\n       * @param {string}   combo       mousetrap key binding\n       * @param {string}   description description for the help menu\n       * @param {Function} callback    method to call when key is pressed\n       * @param {string}   action      the type of event to listen for (for mousetrap)\n       * @param {array}    allowIn     an array of tag names to allow this combo in ('INPUT', 'SELECT', and/or 'TEXTAREA')\n       * @param {boolean}  persistent  if true, the binding is preserved upon route changes\n       */\n      function _add (combo, description, callback, action, allowIn, persistent) {\n\n        // used to save original callback for \"allowIn\" wrapping:\n        var _callback;\n\n        // these elements are prevented by the default Mousetrap.stopCallback():\n        var preventIn = ['INPUT', 'SELECT', 'TEXTAREA'];\n\n        // Determine if object format was given:\n        var objType = Object.prototype.toString.call(combo);\n\n        if (objType === '[object Object]') {\n          description = combo.description;\n          callback    = combo.callback;\n          action      = combo.action;\n          persistent  = combo.persistent;\n          allowIn     = combo.allowIn;\n          combo       = combo.combo;\n        }\n\n        // description is optional:\n        if (description instanceof Function) {\n          action = callback;\n          callback = description;\n          description = '$$undefined$$';\n        } else if (angular.isUndefined(description)) {\n          description = '$$undefined$$';\n        }\n\n        // any items added through the public API are for controllers\n        // that persist through navigation, and thus undefined should mean\n        // true in this case.\n        if (persistent === undefined) {\n          persistent = true;\n        }\n\n        // if callback is defined, then wrap it in a function\n        // that checks if the event originated from a form element.\n        // the function blocks the callback from executing unless the element is specified\n        // in allowIn (emulates Mousetrap.stopCallback() on a per-key level)\n        if (typeof callback === 'function') {\n\n          // save the original callback\n          _callback = callback;\n\n          // make sure allowIn is an array\n          if (!(allowIn instanceof Array)) {\n            allowIn = [];\n          }\n\n          // remove anything from preventIn that's present in allowIn\n          var index;\n          for (var i=0; i < allowIn.length; i++) {\n            allowIn[i] = allowIn[i].toUpperCase();\n            index = preventIn.indexOf(allowIn[i]);\n            if (index !== -1) {\n              preventIn.splice(index, 1);\n            }\n          }\n\n          // create the new wrapper callback\n          callback = function(event) {\n            var shouldExecute = true;\n            var target = event.target || event.srcElement; // srcElement is IE only\n            var nodeName = target.nodeName.toUpperCase();\n\n            // check if the input has a mousetrap class, and skip checking preventIn if so\n            if ((' ' + target.className + ' ').indexOf(' mousetrap ') > -1) {\n              shouldExecute = true;\n            } else {\n              // don't execute callback if the event was fired from inside an element listed in preventIn\n              for (var i=0; i<preventIn.length; i++) {\n                if (preventIn[i] === nodeName) {\n                  shouldExecute = false;\n                  break;\n                }\n              }\n            }\n\n            if (shouldExecute) {\n              wrapApply(_callback.apply(this, arguments));\n            }\n          };\n        }\n\n        if (typeof(action) === 'string') {\n          Mousetrap.bind(combo, wrapApply(callback), action);\n        } else {\n          Mousetrap.bind(combo, wrapApply(callback));\n        }\n\n        var hotkey = new Hotkey(combo, description, callback, action, allowIn, persistent);\n        scope.hotkeys.push(hotkey);\n        return hotkey;\n      }\n\n      /**\n       * delete and unbind a Hotkey\n       *\n       * @param  {mixed} hotkey   Either the bound key or an instance of Hotkey\n       * @return {boolean}        true if successful\n       */\n      function _del (hotkey) {\n        var combo = (hotkey instanceof Hotkey) ? hotkey.combo : hotkey;\n\n        Mousetrap.unbind(combo);\n\n        if (angular.isArray(combo)) {\n          var retStatus = true;\n          var i = combo.length;\n          while (i--) {\n            retStatus = _del(combo[i]) && retStatus;\n          }\n          return retStatus;\n        } else {\n          var index = scope.hotkeys.indexOf(_get(combo));\n\n          if (index > -1) {\n            // if the combo has other combos bound, don't unbind the whole thing, just the one combo:\n            if (scope.hotkeys[index].combo.length > 1) {\n              scope.hotkeys[index].combo.splice(scope.hotkeys[index].combo.indexOf(combo), 1);\n            } else {\n              scope.hotkeys.splice(index, 1);\n            }\n            return true;\n          }\n        }\n\n        return false;\n\n      }\n\n      /**\n       * Get a Hotkey object by key binding\n       *\n       * @param  {[string]} combo  the key the Hotkey is bound to\n       * @return {Hotkey}          The Hotkey object\n       */\n      function _get (combo) {\n\n        var hotkey;\n\n        for (var i = 0; i < scope.hotkeys.length; i++) {\n          hotkey = scope.hotkeys[i];\n\n          if (hotkey.combo.indexOf(combo) > -1) {\n            return hotkey;\n          }\n        }\n\n        return false;\n      }\n\n      /**\n       * Binds the hotkey to a particular scope.  Useful if the scope is\n       * destroyed, we can automatically destroy the hotkey binding.\n       *\n       * @param  {Object} scope The scope to bind to\n       */\n      function bindTo (scope) {\n        // Only initialize once to allow multiple calls for same scope.\n        if (!(scope.$id in boundScopes)) {\n\n          // Add the scope to the list of bound scopes\n          boundScopes[scope.$id] = [];\n\n          scope.$on('$destroy', function () {\n            var i = boundScopes[scope.$id].length;\n            while (i--) {\n              _del(boundScopes[scope.$id][i]);\n              delete boundScopes[scope.$id][i];\n            }\n          });\n        }\n        // return an object with an add function so we can keep track of the\n        // hotkeys and their scope that we added via this chaining method\n        return {\n          add: function (args) {\n            var hotkey;\n\n            if (arguments.length > 1) {\n              hotkey = _add.apply(this, arguments);\n            } else {\n              hotkey = _add(args);\n            }\n\n            boundScopes[scope.$id].push(hotkey);\n            return this;\n          }\n        };\n      }\n\n      /**\n       * All callbacks sent to Mousetrap are wrapped using this function\n       * so that we can force a $scope.$apply()\n       *\n       * @param  {Function} callback [description]\n       * @return {[type]}            [description]\n       */\n      function wrapApply (callback) {\n        // return mousetrap a function to call\n        return function (event, combo) {\n\n          // if this is an array, it means we provided a route object\n          // because the scope wasn't available yet, so rewrap the callback\n          // now that the scope is available:\n          if (callback instanceof Array) {\n            var funcString = callback[0];\n            var route = callback[1];\n            callback = function (event) {\n              route.scope.$eval(funcString);\n            };\n          }\n\n          // this takes place outside angular, so we'll have to call\n          // $apply() to make sure angular's digest happens\n          $rootScope.$apply(function() {\n            // call the original hotkey callback with the keyboard event\n            callback(event, _get(combo));\n          });\n        };\n      }\n\n\n      var publicApi = {\n        add                   : _add,\n        del                   : _del,\n        get                   : _get,\n        bindTo                : bindTo,\n        template              : this.template,\n        toggleCheatSheet      : toggleCheatSheet,\n        includeCheatSheet     : this.includeCheatSheet,\n        cheatSheetHotkey      : this.cheatSheetHotkey,\n        cheatSheetDescription : this.cheatSheetDescription,\n        purgeHotkeys          : purgeHotkeys,\n        templateTitle         : this.templateTitle\n      };\n\n      return publicApi;\n\n    }];\n  })\n\n  .directive('hotkey', ['hotkeys', function (hotkeys) {\n    return {\n      restrict: 'A',\n      link: function (scope, el, attrs) {\n        var key, allowIn;\n\n        angular.forEach(scope.$eval(attrs.hotkey), function (func, hotkey) {\n          // split and trim the hotkeys string into array\n          allowIn = typeof attrs.hotkeyAllowIn === \"string\" ? attrs.hotkeyAllowIn.split(/[\\s,]+/) : [];\n\n          key = hotkey;\n\n          hotkeys.add({\n            combo: hotkey,\n            description: attrs.hotkeyDescription,\n            callback: func,\n            action: attrs.hotkeyAction,\n            allowIn: allowIn\n          });\n        });\n\n        // remove the hotkey if the directive is destroyed:\n        el.bind('$destroy', function() {\n          hotkeys.del(key);\n        });\n      }\n    };\n  }])\n\n  .run(['hotkeys', function(hotkeys) {\n    // force hotkeys to run by injecting it. Without this, hotkeys only runs\n    // when a controller or something else asks for it via DI.\n  }]);\n\n})();\n\n/*global define:false */\n/**\n * Copyright 2013 Craig Campbell\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 * Mousetrap is a simple keyboard shortcut library for Javascript with\n * no external dependencies\n *\n * @version 1.4.6\n * @url craig.is/killing/mice\n */\n(function(window, document, undefined) {\n\n    /**\n     * mapping of special keycodes to their corresponding keys\n     *\n     * everything in this dictionary cannot use keypress events\n     * so it has to be here to map to the correct keycodes for\n     * keyup/keydown events\n     *\n     * @type {Object}\n     */\n    var _MAP = {\n            8: 'backspace',\n            9: 'tab',\n            13: 'enter',\n            16: 'shift',\n            17: 'ctrl',\n            18: 'alt',\n            20: 'capslock',\n            27: 'esc',\n            32: 'space',\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: 'ins',\n            46: 'del',\n            91: 'meta',\n            93: 'meta',\n            224: 'meta'\n        },\n\n        /**\n         * mapping for special characters so they can support\n         *\n         * this dictionary is only used incase you want to bind a\n         * keyup or keydown event to one of these keys\n         *\n         * @type {Object}\n         */\n        _KEYCODE_MAP = {\n            106: '*',\n            107: '+',\n            109: '-',\n            110: '.',\n            111 : '/',\n            186: ';',\n            187: '=',\n            188: ',',\n            189: '-',\n            190: '.',\n            191: '/',\n            192: '`',\n            219: '[',\n            220: '\\\\',\n            221: ']',\n            222: '\\''\n        },\n\n        /**\n         * this is a mapping of keys that require shift on a US keypad\n         * back to the non shift equivelents\n         *\n         * this is so you can use keyup events with these keys\n         *\n         * note that this will only work reliably on US keyboards\n         *\n         * @type {Object}\n         */\n        _SHIFT_MAP = {\n            '~': '`',\n            '!': '1',\n            '@': '2',\n            '#': '3',\n            '$': '4',\n            '%': '5',\n            '^': '6',\n            '&': '7',\n            '*': '8',\n            '(': '9',\n            ')': '0',\n            '_': '-',\n            '+': '=',\n            ':': ';',\n            '\\\"': '\\'',\n            '<': ',',\n            '>': '.',\n            '?': '/',\n            '|': '\\\\'\n        },\n\n        /**\n         * this is a list of special strings you can use to map\n         * to modifier keys when you specify your keyboard shortcuts\n         *\n         * @type {Object}\n         */\n        _SPECIAL_ALIASES = {\n            'option': 'alt',\n            'command': 'meta',\n            'return': 'enter',\n            'escape': 'esc',\n            'mod': /Mac|iPod|iPhone|iPad/.test(navigator.platform) ? 'meta' : 'ctrl'\n        },\n\n        /**\n         * variable to store the flipped version of _MAP from above\n         * needed to check if we should use keypress or not when no action\n         * is specified\n         *\n         * @type {Object|undefined}\n         */\n        _REVERSE_MAP,\n\n        /**\n         * a list of all the callbacks setup via Mousetrap.bind()\n         *\n         * @type {Object}\n         */\n        _callbacks = {},\n\n        /**\n         * direct map of string combinations to callbacks used for trigger()\n         *\n         * @type {Object}\n         */\n        _directMap = {},\n\n        /**\n         * keeps track of what level each sequence is at since multiple\n         * sequences can start out with the same sequence\n         *\n         * @type {Object}\n         */\n        _sequenceLevels = {},\n\n        /**\n         * variable to store the setTimeout call\n         *\n         * @type {null|number}\n         */\n        _resetTimer,\n\n        /**\n         * temporary state where we will ignore the next keyup\n         *\n         * @type {boolean|string}\n         */\n        _ignoreNextKeyup = false,\n\n        /**\n         * temporary state where we will ignore the next keypress\n         *\n         * @type {boolean}\n         */\n        _ignoreNextKeypress = false,\n\n        /**\n         * are we currently inside of a sequence?\n         * type of action (\"keyup\" or \"keydown\" or \"keypress\") or false\n         *\n         * @type {boolean|string}\n         */\n        _nextExpectedAction = false;\n\n    /**\n     * loop through the f keys, f1 to f19 and add them to the map\n     * programatically\n     */\n    for (var i = 1; i < 20; ++i) {\n        _MAP[111 + i] = 'f' + i;\n    }\n\n    /**\n     * loop through to map numbers on the numeric keypad\n     */\n    for (i = 0; i <= 9; ++i) {\n        _MAP[i + 96] = i;\n    }\n\n    /**\n     * cross browser add event method\n     *\n     * @param {Element|HTMLDocument} object\n     * @param {string} type\n     * @param {Function} callback\n     * @returns void\n     */\n    function _addEvent(object, type, callback) {\n        if (object.addEventListener) {\n            object.addEventListener(type, callback, false);\n            return;\n        }\n\n        object.attachEvent('on' + type, callback);\n    }\n\n    /**\n     * takes the event and returns the key character\n     *\n     * @param {Event} e\n     * @return {string}\n     */\n    function _characterFromEvent(e) {\n\n        // for keypress events we should return the character as is\n        if (e.type == 'keypress') {\n            var character = String.fromCharCode(e.which);\n\n            // if the shift key is not pressed then it is safe to assume\n            // that we want the character to be lowercase.  this means if\n            // you accidentally have caps lock on then your key bindings\n            // will continue to work\n            //\n            // the only side effect that might not be desired is if you\n            // bind something like 'A' cause you want to trigger an\n            // event when capital A is pressed caps lock will no longer\n            // trigger the event.  shift+a will though.\n            if (!e.shiftKey) {\n                character = character.toLowerCase();\n            }\n\n            return character;\n        }\n\n        // for non keypress events the special maps are needed\n        if (_MAP[e.which]) {\n            return _MAP[e.which];\n        }\n\n        if (_KEYCODE_MAP[e.which]) {\n            return _KEYCODE_MAP[e.which];\n        }\n\n        // if it is not in the special map\n\n        // with keydown and keyup events the character seems to always\n        // come in as an uppercase character whether you are pressing shift\n        // or not.  we should make sure it is always lowercase for comparisons\n        return String.fromCharCode(e.which).toLowerCase();\n    }\n\n    /**\n     * checks if two arrays are equal\n     *\n     * @param {Array} modifiers1\n     * @param {Array} modifiers2\n     * @returns {boolean}\n     */\n    function _modifiersMatch(modifiers1, modifiers2) {\n        return modifiers1.sort().join(',') === modifiers2.sort().join(',');\n    }\n\n    /**\n     * resets all sequence counters except for the ones passed in\n     *\n     * @param {Object} doNotReset\n     * @returns void\n     */\n    function _resetSequences(doNotReset) {\n        doNotReset = doNotReset || {};\n\n        var activeSequences = false,\n            key;\n\n        for (key in _sequenceLevels) {\n            if (doNotReset[key]) {\n                activeSequences = true;\n                continue;\n            }\n            _sequenceLevels[key] = 0;\n        }\n\n        if (!activeSequences) {\n            _nextExpectedAction = false;\n        }\n    }\n\n    /**\n     * finds all callbacks that match based on the keycode, modifiers,\n     * and action\n     *\n     * @param {string} character\n     * @param {Array} modifiers\n     * @param {Event|Object} e\n     * @param {string=} sequenceName - name of the sequence we are looking for\n     * @param {string=} combination\n     * @param {number=} level\n     * @returns {Array}\n     */\n    function _getMatches(character, modifiers, e, sequenceName, combination, level) {\n        var i,\n            callback,\n            matches = [],\n            action = e.type;\n\n        // if there are no events related to this keycode\n        if (!_callbacks[character]) {\n            return [];\n        }\n\n        // if a modifier key is coming up on its own we should allow it\n        if (action == 'keyup' && _isModifier(character)) {\n            modifiers = [character];\n        }\n\n        // loop through all callbacks for the key that was pressed\n        // and see if any of them match\n        for (i = 0; i < _callbacks[character].length; ++i) {\n            callback = _callbacks[character][i];\n\n            // if a sequence name is not specified, but this is a sequence at\n            // the wrong level then move onto the next match\n            if (!sequenceName && callback.seq && _sequenceLevels[callback.seq] != callback.level) {\n                continue;\n            }\n\n            // if the action we are looking for doesn't match the action we got\n            // then we should keep going\n            if (action != callback.action) {\n                continue;\n            }\n\n            // if this is a keypress event and the meta key and control key\n            // are not pressed that means that we need to only look at the\n            // character, otherwise check the modifiers as well\n            //\n            // chrome will not fire a keypress if meta or control is down\n            // safari will fire a keypress if meta or meta+shift is down\n            // firefox will fire a keypress if meta or control is down\n            if ((action == 'keypress' && !e.metaKey && !e.ctrlKey) || _modifiersMatch(modifiers, callback.modifiers)) {\n\n                // when you bind a combination or sequence a second time it\n                // should overwrite the first one.  if a sequenceName or\n                // combination is specified in this call it does just that\n                //\n                // @todo make deleting its own method?\n                var deleteCombo = !sequenceName && callback.combo == combination;\n                var deleteSequence = sequenceName && callback.seq == sequenceName && callback.level == level;\n                if (deleteCombo || deleteSequence) {\n                    _callbacks[character].splice(i, 1);\n                }\n\n                matches.push(callback);\n            }\n        }\n\n        return matches;\n    }\n\n    /**\n     * takes a key event and figures out what the modifiers are\n     *\n     * @param {Event} e\n     * @returns {Array}\n     */\n    function _eventModifiers(e) {\n        var modifiers = [];\n\n        if (e.shiftKey) {\n            modifiers.push('shift');\n        }\n\n        if (e.altKey) {\n            modifiers.push('alt');\n        }\n\n        if (e.ctrlKey) {\n            modifiers.push('ctrl');\n        }\n\n        if (e.metaKey) {\n            modifiers.push('meta');\n        }\n\n        return modifiers;\n    }\n\n    /**\n     * prevents default for this event\n     *\n     * @param {Event} e\n     * @returns void\n     */\n    function _preventDefault(e) {\n        if (e.preventDefault) {\n            e.preventDefault();\n            return;\n        }\n\n        e.returnValue = false;\n    }\n\n    /**\n     * stops propogation for this event\n     *\n     * @param {Event} e\n     * @returns void\n     */\n    function _stopPropagation(e) {\n        if (e.stopPropagation) {\n            e.stopPropagation();\n            return;\n        }\n\n        e.cancelBubble = true;\n    }\n\n    /**\n     * actually calls the callback function\n     *\n     * if your callback function returns false this will use the jquery\n     * convention - prevent default and stop propogation on the event\n     *\n     * @param {Function} callback\n     * @param {Event} e\n     * @returns void\n     */\n    function _fireCallback(callback, e, combo, sequence) {\n\n        // if this event should not happen stop here\n        if (Mousetrap.stopCallback(e, e.target || e.srcElement, combo, sequence)) {\n            return;\n        }\n\n        if (callback(e, combo) === false) {\n            _preventDefault(e);\n            _stopPropagation(e);\n        }\n    }\n\n    /**\n     * handles a character key event\n     *\n     * @param {string} character\n     * @param {Array} modifiers\n     * @param {Event} e\n     * @returns void\n     */\n    function _handleKey(character, modifiers, e) {\n        var callbacks = _getMatches(character, modifiers, e),\n            i,\n            doNotReset = {},\n            maxLevel = 0,\n            processedSequenceCallback = false;\n\n        // Calculate the maxLevel for sequences so we can only execute the longest callback sequence\n        for (i = 0; i < callbacks.length; ++i) {\n            if (callbacks[i].seq) {\n                maxLevel = Math.max(maxLevel, callbacks[i].level);\n            }\n        }\n\n        // loop through matching callbacks for this key event\n        for (i = 0; i < callbacks.length; ++i) {\n\n            // fire for all sequence callbacks\n            // this is because if for example you have multiple sequences\n            // bound such as \"g i\" and \"g t\" they both need to fire the\n            // callback for matching g cause otherwise you can only ever\n            // match the first one\n            if (callbacks[i].seq) {\n\n                // only fire callbacks for the maxLevel to prevent\n                // subsequences from also firing\n                //\n                // for example 'a option b' should not cause 'option b' to fire\n                // even though 'option b' is part of the other sequence\n                //\n                // any sequences that do not match here will be discarded\n                // below by the _resetSequences call\n                if (callbacks[i].level != maxLevel) {\n                    continue;\n                }\n\n                processedSequenceCallback = true;\n\n                // keep a list of which sequences were matches for later\n                doNotReset[callbacks[i].seq] = 1;\n                _fireCallback(callbacks[i].callback, e, callbacks[i].combo, callbacks[i].seq);\n                continue;\n            }\n\n            // if there were no sequence matches but we are still here\n            // that means this is a regular match so we should fire that\n            if (!processedSequenceCallback) {\n                _fireCallback(callbacks[i].callback, e, callbacks[i].combo);\n            }\n        }\n\n        // if the key you pressed matches the type of sequence without\n        // being a modifier (ie \"keyup\" or \"keypress\") then we should\n        // reset all sequences that were not matched by this event\n        //\n        // this is so, for example, if you have the sequence \"h a t\" and you\n        // type \"h e a r t\" it does not match.  in this case the \"e\" will\n        // cause the sequence to reset\n        //\n        // modifier keys are ignored because you can have a sequence\n        // that contains modifiers such as \"enter ctrl+space\" and in most\n        // cases the modifier key will be pressed before the next key\n        //\n        // also if you have a sequence such as \"ctrl+b a\" then pressing the\n        // \"b\" key will trigger a \"keypress\" and a \"keydown\"\n        //\n        // the \"keydown\" is expected when there is a modifier, but the\n        // \"keypress\" ends up matching the _nextExpectedAction since it occurs\n        // after and that causes the sequence to reset\n        //\n        // we ignore keypresses in a sequence that directly follow a keydown\n        // for the same character\n        var ignoreThisKeypress = e.type == 'keypress' && _ignoreNextKeypress;\n        if (e.type == _nextExpectedAction && !_isModifier(character) && !ignoreThisKeypress) {\n            _resetSequences(doNotReset);\n        }\n\n        _ignoreNextKeypress = processedSequenceCallback && e.type == 'keydown';\n    }\n\n    /**\n     * handles a keydown event\n     *\n     * @param {Event} e\n     * @returns void\n     */\n    function _handleKeyEvent(e) {\n\n        // normalize e.which for key events\n        // @see http://stackoverflow.com/questions/4285627/javascript-keycode-vs-charcode-utter-confusion\n        if (typeof e.which !== 'number') {\n            e.which = e.keyCode;\n        }\n\n        var character = _characterFromEvent(e);\n\n        // no character found then stop\n        if (!character) {\n            return;\n        }\n\n        // need to use === for the character check because the character can be 0\n        if (e.type == 'keyup' && _ignoreNextKeyup === character) {\n            _ignoreNextKeyup = false;\n            return;\n        }\n\n        Mousetrap.handleKey(character, _eventModifiers(e), e);\n    }\n\n    /**\n     * determines if the keycode specified is a modifier key or not\n     *\n     * @param {string} key\n     * @returns {boolean}\n     */\n    function _isModifier(key) {\n        return key == 'shift' || key == 'ctrl' || key == 'alt' || key == 'meta';\n    }\n\n    /**\n     * called to set a 1 second timeout on the specified sequence\n     *\n     * this is so after each key press in the sequence you have 1 second\n     * to press the next key before you have to start over\n     *\n     * @returns void\n     */\n    function _resetSequenceTimer() {\n        clearTimeout(_resetTimer);\n        _resetTimer = setTimeout(_resetSequences, 1000);\n    }\n\n    /**\n     * reverses the map lookup so that we can look for specific keys\n     * to see what can and can't use keypress\n     *\n     * @return {Object}\n     */\n    function _getReverseMap() {\n        if (!_REVERSE_MAP) {\n            _REVERSE_MAP = {};\n            for (var key in _MAP) {\n\n                // pull out the numeric keypad from here cause keypress should\n                // be able to detect the keys from the character\n                if (key > 95 && key < 112) {\n                    continue;\n                }\n\n                if (_MAP.hasOwnProperty(key)) {\n                    _REVERSE_MAP[_MAP[key]] = key;\n                }\n            }\n        }\n        return _REVERSE_MAP;\n    }\n\n    /**\n     * picks the best action based on the key combination\n     *\n     * @param {string} key - character for key\n     * @param {Array} modifiers\n     * @param {string=} action passed in\n     */\n    function _pickBestAction(key, modifiers, action) {\n\n        // if no action was picked in we should try to pick the one\n        // that we think would work best for this key\n        if (!action) {\n            action = _getReverseMap()[key] ? 'keydown' : 'keypress';\n        }\n\n        // modifier keys don't work as expected with keypress,\n        // switch to keydown\n        if (action == 'keypress' && modifiers.length) {\n            action = 'keydown';\n        }\n\n        return action;\n    }\n\n    /**\n     * binds a key sequence to an event\n     *\n     * @param {string} combo - combo specified in bind call\n     * @param {Array} keys\n     * @param {Function} callback\n     * @param {string=} action\n     * @returns void\n     */\n    function _bindSequence(combo, keys, callback, action) {\n\n        // start off by adding a sequence level record for this combination\n        // and setting the level to 0\n        _sequenceLevels[combo] = 0;\n\n        /**\n         * callback to increase the sequence level for this sequence and reset\n         * all other sequences that were active\n         *\n         * @param {string} nextAction\n         * @returns {Function}\n         */\n        function _increaseSequence(nextAction) {\n            return function() {\n                _nextExpectedAction = nextAction;\n                ++_sequenceLevels[combo];\n                _resetSequenceTimer();\n            };\n        }\n\n        /**\n         * wraps the specified callback inside of another function in order\n         * to reset all sequence counters as soon as this sequence is done\n         *\n         * @param {Event} e\n         * @returns void\n         */\n        function _callbackAndReset(e) {\n            _fireCallback(callback, e, combo);\n\n            // we should ignore the next key up if the action is key down\n            // or keypress.  this is so if you finish a sequence and\n            // release the key the final key will not trigger a keyup\n            if (action !== 'keyup') {\n                _ignoreNextKeyup = _characterFromEvent(e);\n            }\n\n            // weird race condition if a sequence ends with the key\n            // another sequence begins with\n            setTimeout(_resetSequences, 10);\n        }\n\n        // loop through keys one at a time and bind the appropriate callback\n        // function.  for any key leading up to the final one it should\n        // increase the sequence. after the final, it should reset all sequences\n        //\n        // if an action is specified in the original bind call then that will\n        // be used throughout.  otherwise we will pass the action that the\n        // next key in the sequence should match.  this allows a sequence\n        // to mix and match keypress and keydown events depending on which\n        // ones are better suited to the key provided\n        for (var i = 0; i < keys.length; ++i) {\n            var isFinal = i + 1 === keys.length;\n            var wrappedCallback = isFinal ? _callbackAndReset : _increaseSequence(action || _getKeyInfo(keys[i + 1]).action);\n            _bindSingle(keys[i], wrappedCallback, action, combo, i);\n        }\n    }\n\n    /**\n     * Converts from a string key combination to an array\n     *\n     * @param  {string} combination like \"command+shift+l\"\n     * @return {Array}\n     */\n    function _keysFromString(combination) {\n        if (combination === '+') {\n            return ['+'];\n        }\n\n        return combination.split('+');\n    }\n\n    /**\n     * Gets info for a specific key combination\n     *\n     * @param  {string} combination key combination (\"command+s\" or \"a\" or \"*\")\n     * @param  {string=} action\n     * @returns {Object}\n     */\n    function _getKeyInfo(combination, action) {\n        var keys,\n            key,\n            i,\n            modifiers = [];\n\n        // take the keys from this pattern and figure out what the actual\n        // pattern is all about\n        keys = _keysFromString(combination);\n\n        for (i = 0; i < keys.length; ++i) {\n            key = keys[i];\n\n            // normalize key names\n            if (_SPECIAL_ALIASES[key]) {\n                key = _SPECIAL_ALIASES[key];\n            }\n\n            // if this is not a keypress event then we should\n            // be smart about using shift keys\n            // this will only work for US keyboards however\n            if (action && action != 'keypress' && _SHIFT_MAP[key]) {\n                key = _SHIFT_MAP[key];\n                modifiers.push('shift');\n            }\n\n            // if this key is a modifier then add it to the list of modifiers\n            if (_isModifier(key)) {\n                modifiers.push(key);\n            }\n        }\n\n        // depending on what the key combination is\n        // we will try to pick the best event for it\n        action = _pickBestAction(key, modifiers, action);\n\n        return {\n            key: key,\n            modifiers: modifiers,\n            action: action\n        };\n    }\n\n    /**\n     * binds a single keyboard combination\n     *\n     * @param {string} combination\n     * @param {Function} callback\n     * @param {string=} action\n     * @param {string=} sequenceName - name of sequence if part of sequence\n     * @param {number=} level - what part of the sequence the command is\n     * @returns void\n     */\n    function _bindSingle(combination, callback, action, sequenceName, level) {\n\n        // store a direct mapped reference for use with Mousetrap.trigger\n        _directMap[combination + ':' + action] = callback;\n\n        // make sure multiple spaces in a row become a single space\n        combination = combination.replace(/\\s+/g, ' ');\n\n        var sequence = combination.split(' '),\n            info;\n\n        // if this pattern is a sequence of keys then run through this method\n        // to reprocess each pattern one key at a time\n        if (sequence.length > 1) {\n            _bindSequence(combination, sequence, callback, action);\n            return;\n        }\n\n        info = _getKeyInfo(combination, action);\n\n        // make sure to initialize array if this is the first time\n        // a callback is added for this key\n        _callbacks[info.key] = _callbacks[info.key] || [];\n\n        // remove an existing match if there is one\n        _getMatches(info.key, info.modifiers, {type: info.action}, sequenceName, combination, level);\n\n        // add this call back to the array\n        // if it is a sequence put it at the beginning\n        // if not put it at the end\n        //\n        // this is important because the way these are processed expects\n        // the sequence ones to come first\n        _callbacks[info.key][sequenceName ? 'unshift' : 'push']({\n            callback: callback,\n            modifiers: info.modifiers,\n            action: info.action,\n            seq: sequenceName,\n            level: level,\n            combo: combination\n        });\n    }\n\n    /**\n     * binds multiple combinations to the same callback\n     *\n     * @param {Array} combinations\n     * @param {Function} callback\n     * @param {string|undefined} action\n     * @returns void\n     */\n    function _bindMultiple(combinations, callback, action) {\n        for (var i = 0; i < combinations.length; ++i) {\n            _bindSingle(combinations[i], callback, action);\n        }\n    }\n\n    // start!\n    _addEvent(document, 'keypress', _handleKeyEvent);\n    _addEvent(document, 'keydown', _handleKeyEvent);\n    _addEvent(document, 'keyup', _handleKeyEvent);\n\n    var Mousetrap = {\n\n        /**\n         * binds an event to mousetrap\n         *\n         * can be a single key, a combination of keys separated with +,\n         * an array of keys, or a sequence of keys separated by spaces\n         *\n         * be sure to list the modifier keys first to make sure that the\n         * correct key ends up getting bound (the last key in the pattern)\n         *\n         * @param {string|Array} keys\n         * @param {Function} callback\n         * @param {string=} action - 'keypress', 'keydown', or 'keyup'\n         * @returns void\n         */\n        bind: function(keys, callback, action) {\n            keys = keys instanceof Array ? keys : [keys];\n            _bindMultiple(keys, callback, action);\n            return this;\n        },\n\n        /**\n         * unbinds an event to mousetrap\n         *\n         * the unbinding sets the callback function of the specified key combo\n         * to an empty function and deletes the corresponding key in the\n         * _directMap dict.\n         *\n         * TODO: actually remove this from the _callbacks dictionary instead\n         * of binding an empty function\n         *\n         * the keycombo+action has to be exactly the same as\n         * it was defined in the bind method\n         *\n         * @param {string|Array} keys\n         * @param {string} action\n         * @returns void\n         */\n        unbind: function(keys, action) {\n            return Mousetrap.bind(keys, function() {}, action);\n        },\n\n        /**\n         * triggers an event that has already been bound\n         *\n         * @param {string} keys\n         * @param {string=} action\n         * @returns void\n         */\n        trigger: function(keys, action) {\n            if (_directMap[keys + ':' + action]) {\n                _directMap[keys + ':' + action]({}, keys);\n            }\n            return this;\n        },\n\n        /**\n         * resets the library back to its initial state.  this is useful\n         * if you want to clear out the current keyboard shortcuts and bind\n         * new ones - for example if you switch to another page\n         *\n         * @returns void\n         */\n        reset: function() {\n            _callbacks = {};\n            _directMap = {};\n            return this;\n        },\n\n       /**\n        * should we stop this event before firing off callbacks\n        *\n        * @param {Event} e\n        * @param {Element} element\n        * @return {boolean}\n        */\n        stopCallback: function(e, element) {\n\n            // if the element has the class \"mousetrap\" then no need to stop\n            if ((' ' + element.className + ' ').indexOf(' mousetrap ') > -1) {\n                return false;\n            }\n\n            // stop for input, select, and textarea\n            return element.tagName == 'INPUT' || element.tagName == 'SELECT' || element.tagName == 'TEXTAREA' || element.isContentEditable;\n        },\n\n        /**\n         * exposes _handleKey publicly so it can be overwritten by extensions\n         */\n        handleKey: _handleKey\n    };\n\n    // expose mousetrap to the global object\n    window.Mousetrap = Mousetrap;\n\n    // expose mousetrap as an AMD module\n    if (typeof define === 'function' && define.amd) {\n        define(Mousetrap);\n    }\n}) (window, document);\n"
  },
  {
    "path": "flowable-ui-web/idm/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": "flowable-ui-web/idm/libs/angular-resource_1.3.13/angular-resource.js",
    "content": "/**\n * @license AngularJS v1.3.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 module\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 *\n * <div doc-module-components=\"ngResource\"></div>\n *\n * See {@link ngResource.$resource `$resource`} for usage.\n */\n\n/**\n * @ngdoc service\n * @name $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 * By default, trailing slashes will be stripped from the calculated URLs,\n * which can pose problems with server backends that do not expect that\n * behavior.  This can be disabled by configuring the `$resourceProvider` like\n * this:\n *\n * ```js\n     app.config(['$resourceProvider', function($resourceProvider) {\n       // Don't strip trailing slashes from calculated URLs\n       $resourceProvider.defaults.stripTrailingSlashes = false;\n     }]);\n * ```\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 for that parameter will be extracted\n *   from the corresponding property on the `data` object (provided when calling an action method).  For\n *   example, if the `defaultParam` object is `{someParam: '@someProp'}` then the value of `someParam`\n *   will be `data.someProp`.\n *\n * @param {Object.<Object>=} actions Hash with declaration of custom actions that should extend\n *   the default set of resource actions. The declaration should be created in the format of {@link\n *   ng.$http#usage $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} – Case insensitive HTTP method (e.g. `GET`, `POST`, `PUT`,\n *     `DELETE`, `JSONP`, etc).\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 *     By default, transformRequest will contain one function that checks if the request data is\n *     an object and serializes to using `angular.toJson`. To prevent this behavior, set\n *     `transformRequest` to an empty array: `transformRequest: []`\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 *     By default, transformResponse will contain one function that checks if the response looks like\n *     a JSON string and deserializes it using `angular.fromJson`. To prevent this behavior, set\n *     `transformResponse` to an empty array: `transformResponse: []`\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\n *     [requests with credentials](https://developer.mozilla.org/en/http_access_control#section_5)\n *     for more information.\n *   - **`responseType`** - `{string}` - see\n *     [requestType](https://developer.mozilla.org/en-US/docs/DOM/XMLHttpRequest#responseType).\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 * @param {Object} options Hash with custom settings that should extend the\n *   default `$resourceProvider` behavior.  The only supported option is\n *\n *   Where:\n *\n *   - **`stripTrailingSlashes`** – {boolean} – If true then the trailing\n *   slashes from any calculated URL will be stripped. (Defaults to true.)\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 *   ```js\n *   { 'get':    {method:'GET'},\n *     'save':   {method:'POST'},\n *     'query':  {method:'GET', isArray:true},\n *     'remove': {method:'DELETE'},\n *     'delete': {method:'DELETE'} };\n *   ```\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 *   ```js\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 *   ```\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 *     If an interceptor object was provided, the promise will instead be resolved with the value\n *     returned by the interceptor.\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 * ```js\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 * ```\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   ```js\n     var User = $resource('/user/:userId', {userId:'@id'});\n     User.get({userId:123}, function(user) {\n       user.abc = true;\n       user.$save();\n     });\n   ```\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   ```js\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   ```\n *\n * You can also access the raw `$http` promise via the `$promise` property on the object returned\n *\n   ```\n     var User = $resource('/user/:userId', {userId:'@id'});\n     User.get({userId:123})\n         .$promise.then(function(user) {\n           $scope.user = user;\n         });\n   ```\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 * ```js\n *    var app = angular.module('app', ['ngResource', 'ngRoute']);\n *\n *    // Some APIs expect a PUT request in the format URL/object/ID\n *    // Here we are creating an 'update' method\n *    app.factory('Notes', ['$resource', function($resource) {\n *    return $resource('/notes/:id', null,\n *        {\n *            'update': { method:'PUT' }\n *        });\n *    }]);\n *\n *    // In our controller we get the ID from the URL using ngRoute and $routeParams\n *    // We pass in $routeParams and our Notes factory along with $scope\n *    app.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 *    }]);\n * ```\n */\nangular.module('ngResource', ['ng']).\n  provider('$resource', function() {\n    var provider = this;\n\n    this.defaults = {\n      // Strip slashes by default\n      stripTrailingSlashes: true,\n\n      // Default actions configuration\n      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    };\n\n    this.$get = ['$http', '$q', function($http, $q) {\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\n       * (pchar) allowed in path 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 = extend({}, provider.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 (unless this behavior is specifically disabled)\n          if (self.defaults.stripTrailingSlashes) {\n            url = url.replace(/\\/+$/, '') || '/';\n          }\n\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, options) {\n        var route = new Route(url, options);\n\n        actions = extend({}, provider.defaults.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        Resource.prototype.toJSON = function() {\n          var data = extend({}, this);\n          delete data.$promise;\n          delete data.$resolved;\n          return data;\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',\n                      'Error in resource configuration for action `{0}`. Expected response to ' +\n                      'contain an {1} but got an {2}', name, action.isArray ? 'array' : 'object',\n                    angular.isArray(data) ? 'array' : 'object');\n                }\n                // jshint +W018\n                if (action.isArray) {\n                  value.length = 0;\n                  forEach(data, function(item) {\n                    if (typeof item === \"object\") {\n                      value.push(new Resource(item));\n                    } else {\n                      // Valid JSON values may be string literals, and these should not be converted\n                      // into objects. These items will not have access to the Resource prototype\n                      // methods, but unfortunately there\n                      value.push(item);\n                    }\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\n})(window, window.angular);\n"
  },
  {
    "path": "flowable-ui-web/idm/libs/angular-route_1.3.13/angular-route.js",
    "content": "/**\n * @license AngularJS v1.3.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 module\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 *\n * <div doc-module-components=\"ngRoute\"></div>\n */\n /* global -ngRouteModule */\nvar ngRouteModule = angular.module('ngRoute', ['ng']).\n                        provider('$route', $RouteProvider),\n    $routeMinErr = angular.$$minErr('ngRoute');\n\n/**\n * @ngdoc provider\n * @name $routeProvider\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(Object.create(parent), extra);\n  }\n\n  var routes = {};\n\n  /**\n   * @ngdoc method\n   * @name $routeProvider#when\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/slashes/edit` and extract:\n   *\n   *    * `color: brown`\n   *    * `largecode: code/with/slashes`.\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 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    //copy original route object to preserve params inherited from proto chain\n    var routeCopy = angular.copy(route);\n    if (angular.isUndefined(routeCopy.reloadOnSearch)) {\n      routeCopy.reloadOnSearch = true;\n    }\n    if (angular.isUndefined(routeCopy.caseInsensitiveMatch)) {\n      routeCopy.caseInsensitiveMatch = this.caseInsensitiveMatch;\n    }\n    routes[path] = angular.extend(\n      routeCopy,\n      path && pathRegExp(path, routeCopy)\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, routeCopy)\n      );\n    }\n\n    return this;\n  };\n\n  /**\n   * @ngdoc property\n   * @name $routeProvider#caseInsensitiveMatch\n   * @description\n   *\n   * A boolean property indicating if routes defined\n   * using this provider should be matched using a case insensitive\n   * algorithm. Defaults to `false`.\n   */\n  this.caseInsensitiveMatch = false;\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 $routeProvider#otherwise\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|string} params Mapping information to be assigned to `$route.current`.\n   * If called with a string, the value maps to `redirectTo`.\n   * @returns {Object} self\n   */\n  this.otherwise = function(params) {\n    if (typeof params === 'string') {\n      params = {redirectTo: params};\n    }\n    this.when(null, params);\n    return this;\n  };\n\n\n  this.$get = ['$rootScope',\n               '$location',\n               '$routeParams',\n               '$q',\n               '$injector',\n               '$templateRequest',\n               '$sce',\n      function($rootScope, $location, $routeParams, $q, $injector, $templateRequest, $sce) {\n\n    /**\n     * @ngdoc service\n     * @name $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 {Object} routes Object with all route configuration Objects as its properties.\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     * <example name=\"$route-service\" module=\"ngRouteExample\"\n     *          deps=\"angular-route.js\" fixBase=\"true\">\n     *   <file name=\"index.html\">\n     *     <div ng-controller=\"MainController\">\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     *\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('ngRouteExample', ['ngRoute'])\n     *\n     *      .controller('MainController', function($scope, $route, $routeParams, $location) {\n     *          $scope.$route = $route;\n     *          $scope.$location = $location;\n     *          $scope.$routeParams = $routeParams;\n     *      })\n     *\n     *      .controller('BookController', function($scope, $routeParams) {\n     *          $scope.name = \"BookController\";\n     *          $scope.params = $routeParams;\n     *      })\n     *\n     *      .controller('ChapterController', function($scope, $routeParams) {\n     *          $scope.name = \"ChapterController\";\n     *          $scope.params = $routeParams;\n     *      })\n     *\n     *     .config(function($routeProvider, $locationProvider) {\n     *       $routeProvider\n     *        .when('/Book/:bookId', {\n     *         templateUrl: 'book.html',\n     *         controller: 'BookController',\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     *       .when('/Book/:bookId/ch/:chapterId', {\n     *         templateUrl: 'chapter.html',\n     *         controller: 'ChapterController'\n     *       });\n     *\n     *       // configure html5 to get links working on jsfiddle\n     *       $locationProvider.html5Mode(true);\n     *     });\n     *\n     *   </file>\n     *\n     *   <file name=\"protractor.js\" type=\"protractor\">\n     *     it('should load and compile correct template', function() {\n     *       element(by.linkText('Moby: Ch1')).click();\n     *       var content = element(by.css('[ng-view]')).getText();\n     *       expect(content).toMatch(/controller\\: ChapterController/);\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('[ng-view]')).getText();\n     *       expect(content).toMatch(/controller\\: BookController/);\n     *       expect(content).toMatch(/Book Id\\: Scarlet/);\n     *     });\n     *   </file>\n     * </example>\n     */\n\n    /**\n     * @ngdoc event\n     * @name $route#$routeChangeStart\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     * The route change (and the `$location` change that triggered it) can be prevented\n     * by calling `preventDefault` method of the event. See {@link ng.$rootScope.Scope#$on}\n     * for more details about event object.\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 $route#$routeChangeSuccess\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 $route#$routeChangeError\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 $route#$routeUpdate\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        preparedRoute,\n        preparedRouteIsUpdateOnly,\n        $route = {\n          routes: routes,\n\n          /**\n           * @ngdoc method\n           * @name $route#reload\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 and reinstantiates the controller.\n           */\n          reload: function() {\n            forceReload = true;\n            $rootScope.$evalAsync(function() {\n              // Don't support cancellation of a reload for now...\n              prepareRoute();\n              commitRoute();\n            });\n          },\n\n          /**\n           * @ngdoc method\n           * @name $route#updateParams\n           *\n           * @description\n           * Causes `$route` service to update the current URL, replacing\n           * current route parameters with those specified in `newParams`.\n           * Provided property names that match the route's path segment\n           * definitions will be interpolated into the location's path, while\n           * remaining properties will be treated as query params.\n           *\n           * @param {!Object<string, string>} newParams mapping of URL parameter names to values\n           */\n          updateParams: function(newParams) {\n            if (this.current && this.current.$$route) {\n              newParams = angular.extend({}, this.current.params, newParams);\n              $location.path(interpolate(this.current.$$route.originalPath, newParams));\n              // interpolate modifies newParams, only query params are left\n              $location.search(newParams);\n            } else {\n              throw $routeMinErr('norout', 'Tried updating route when with no current route');\n            }\n          }\n        };\n\n    $rootScope.$on('$locationChangeStart', prepareRoute);\n    $rootScope.$on('$locationChangeSuccess', commitRoute);\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 = m[i];\n\n        if (key && val) {\n          params[key.name] = val;\n        }\n      }\n      return params;\n    }\n\n    function prepareRoute($locationEvent) {\n      var lastRoute = $route.current;\n\n      preparedRoute = parseRoute();\n      preparedRouteIsUpdateOnly = preparedRoute && lastRoute && preparedRoute.$$route === lastRoute.$$route\n          && angular.equals(preparedRoute.pathParams, lastRoute.pathParams)\n          && !preparedRoute.reloadOnSearch && !forceReload;\n\n      if (!preparedRouteIsUpdateOnly && (lastRoute || preparedRoute)) {\n        if ($rootScope.$broadcast('$routeChangeStart', preparedRoute, lastRoute).defaultPrevented) {\n          if ($locationEvent) {\n            $locationEvent.preventDefault();\n          }\n        }\n      }\n    }\n\n    function commitRoute() {\n      var lastRoute = $route.current;\n      var nextRoute = preparedRoute;\n\n      if (preparedRouteIsUpdateOnly) {\n        lastRoute.params = nextRoute.params;\n        angular.copy(lastRoute.params, $routeParams);\n        $rootScope.$broadcast('$routeUpdate', lastRoute);\n      } else if (nextRoute || lastRoute) {\n        forceReload = false;\n        $route.current = nextRoute;\n        if (nextRoute) {\n          if (nextRoute.redirectTo) {\n            if (angular.isString(nextRoute.redirectTo)) {\n              $location.path(interpolate(nextRoute.redirectTo, nextRoute.params)).search(nextRoute.params)\n                       .replace();\n            } else {\n              $location.url(nextRoute.redirectTo(nextRoute.pathParams, $location.path(), $location.search()))\n                       .replace();\n            }\n          }\n        }\n\n        $q.when(nextRoute).\n          then(function() {\n            if (nextRoute) {\n              var locals = angular.extend({}, nextRoute.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, null, null, key);\n              });\n\n              if (angular.isDefined(template = nextRoute.template)) {\n                if (angular.isFunction(template)) {\n                  template = template(nextRoute.params);\n                }\n              } else if (angular.isDefined(templateUrl = nextRoute.templateUrl)) {\n                if (angular.isFunction(templateUrl)) {\n                  templateUrl = templateUrl(nextRoute.params);\n                }\n                templateUrl = $sce.getTrustedResourceUrl(templateUrl);\n                if (angular.isDefined(templateUrl)) {\n                  nextRoute.loadedTemplateUrl = templateUrl;\n                  template = $templateRequest(templateUrl);\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 (nextRoute == $route.current) {\n              if (nextRoute) {\n                nextRoute.locals = locals;\n                angular.copy(nextRoute.params, $routeParams);\n              }\n              $rootScope.$broadcast('$routeChangeSuccess', nextRoute, lastRoute);\n            }\n          }, function(error) {\n            if (nextRoute == $route.current) {\n              $rootScope.$broadcast('$routeChangeError', nextRoute, lastRoute, error);\n            }\n          });\n      }\n    }\n\n\n    /**\n     * @returns {Object} 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 {string} 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 service\n * @name $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#search `search()`} and {@link ng.$location#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 * ```js\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 * ```\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 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 name=\"ngView-directive\" module=\"ngViewExample\"\n             deps=\"angular-route.js;angular-animate.js\"\n             animations=\"true\" fixBase=\"true\">\n      <file name=\"index.html\">\n        <div ng-controller=\"MainCtrl 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>$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          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          .config(['$routeProvider', '$locationProvider',\n            function($routeProvider, $locationProvider) {\n              $routeProvider\n                .when('/Book/:bookId', {\n                  templateUrl: 'book.html',\n                  controller: 'BookCtrl',\n                  controllerAs: 'book'\n                })\n                .when('/Book/:bookId/ch/:chapterId', {\n                  templateUrl: 'chapter.html',\n                  controller: 'ChapterCtrl',\n                  controllerAs: 'chapter'\n                });\n\n              $locationProvider.html5Mode(true);\n          }])\n          .controller('MainCtrl', ['$route', '$routeParams', '$location',\n            function($route, $routeParams, $location) {\n              this.$route = $route;\n              this.$location = $location;\n              this.$routeParams = $routeParams;\n          }])\n          .controller('BookCtrl', ['$routeParams', function($routeParams) {\n            this.name = \"BookCtrl\";\n            this.params = $routeParams;\n          }])\n          .controller('ChapterCtrl', ['$routeParams', function($routeParams) {\n            this.name = \"ChapterCtrl\";\n            this.params = $routeParams;\n          }]);\n\n      </file>\n\n      <file name=\"protractor.js\" type=\"protractor\">\n        it('should load and compile correct template', function() {\n          element(by.linkText('Moby: Ch1')).click();\n          var content = element(by.css('[ng-view]')).getText();\n          expect(content).toMatch(/controller\\: ChapterCtrl/);\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('[ng-view]')).getText();\n          expect(content).toMatch(/controller\\: BookCtrl/);\n          expect(content).toMatch(/Book Id\\: Scarlet/);\n        });\n      </file>\n    </example>\n */\n\n\n/**\n * @ngdoc event\n * @name ngView#$viewContentLoaded\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            previousLeaveAnimation,\n            autoScrollExp = attr.autoscroll,\n            onloadExp = attr.onload || '';\n\n        scope.$on('$routeChangeSuccess', update);\n        update();\n\n        function cleanupLastView() {\n          if (previousLeaveAnimation) {\n            $animate.cancel(previousLeaveAnimation);\n            previousLeaveAnimation = null;\n          }\n\n          if (currentScope) {\n            currentScope.$destroy();\n            currentScope = null;\n          }\n          if (currentElement) {\n            previousLeaveAnimation = $animate.leave(currentElement);\n            previousLeaveAnimation.then(function() {\n              previousLeaveAnimation = null;\n            });\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).then(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": "flowable-ui-web/idm/libs/angular-sanitize_1.3.13/angular-sanitize.js",
    "content": "/**\n * @license AngularJS v1.3.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 module\n * @name ngSanitize\n * @description\n *\n * # ngSanitize\n *\n * The `ngSanitize` module provides functionality to sanitize HTML.\n *\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 $sanitize\n * @kind 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. The input may also contain SVG markup.\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   <example module=\"sanitizeExample\" deps=\"angular-sanitize.js\">\n   <file name=\"index.html\">\n     <script>\n         angular.module('sanitizeExample', ['ngSanitize'])\n           .controller('ExampleController', ['$scope', '$sce', function($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=\"ExampleController\">\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   </file>\n   <file name=\"protractor.js\" type=\"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   </file>\n   </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       /^<((?:[a-zA-Z])[\\w:-]*)((?:\\s+[\\w:-]+(?:\\s*=\\s*(?:(?:\"[^\"]*\")|(?:'[^']*')|[^>\\s]+))?)*)\\s*(\\/?)\\s*(>?)/,\n  END_TAG_REGEXP = /^<\\/\\s*([\\w:-]+)[^>]*>/,\n  ATTR_REGEXP = /([\\w:-]+)(?:\\s*=\\s*(?:(?:\"((?:[^\"])*)\")|(?:'((?:[^'])*)')|([^>\\s]+)))?/g,\n  BEGIN_TAG_REGEXP = /^</,\n  BEGING_END_TAGE_REGEXP = /^<\\//,\n  COMMENT_REGEXP = /<!--(.*?)-->/g,\n  DOCTYPE_REGEXP = /<!DOCTYPE([^>]*?)>/i,\n  CDATA_REGEXP = /<!\\[CDATA\\[(.*?)]]>/g,\n  SURROGATE_PAIR_REGEXP = /[\\uD800-\\uDBFF][\\uDC00-\\uDFFF]/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// SVG Elements\n// https://wiki.whatwg.org/wiki/Sanitization_rules#svg_Elements\nvar svgElements = makeMap(\"animate,animateColor,animateMotion,animateTransform,circle,defs,\" +\n        \"desc,ellipse,font-face,font-face-name,font-face-src,g,glyph,hkern,image,linearGradient,\" +\n        \"line,marker,metadata,missing-glyph,mpath,path,polygon,polyline,radialGradient,rect,set,\" +\n        \"stop,svg,switch,text,title,tspan,use\");\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                                   svgElements);\n\n//Attributes that have href and hence need to be sanitized\nvar uriAttrs = makeMap(\"background,cite,href,longdesc,src,usemap,xlink:href\");\n\nvar htmlAttrs = makeMap('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\n// SVG attributes (without \"id\" and \"name\" attributes)\n// https://wiki.whatwg.org/wiki/Sanitization_rules#svg_Attributes\nvar svgAttrs = makeMap('accent-height,accumulate,additive,alphabetic,arabic-form,ascent,' +\n    'attributeName,attributeType,baseProfile,bbox,begin,by,calcMode,cap-height,class,color,' +\n    'color-rendering,content,cx,cy,d,dx,dy,descent,display,dur,end,fill,fill-rule,font-family,' +\n    'font-size,font-stretch,font-style,font-variant,font-weight,from,fx,fy,g1,g2,glyph-name,' +\n    'gradientUnits,hanging,height,horiz-adv-x,horiz-origin-x,ideographic,k,keyPoints,' +\n    'keySplines,keyTimes,lang,marker-end,marker-mid,marker-start,markerHeight,markerUnits,' +\n    'markerWidth,mathematical,max,min,offset,opacity,orient,origin,overline-position,' +\n    'overline-thickness,panose-1,path,pathLength,points,preserveAspectRatio,r,refX,refY,' +\n    'repeatCount,repeatDur,requiredExtensions,requiredFeatures,restart,rotate,rx,ry,slope,stemh,' +\n    'stemv,stop-color,stop-opacity,strikethrough-position,strikethrough-thickness,stroke,' +\n    'stroke-dasharray,stroke-dashoffset,stroke-linecap,stroke-linejoin,stroke-miterlimit,' +\n    'stroke-opacity,stroke-width,systemLanguage,target,text-anchor,to,transform,type,u1,u2,' +\n    'underline-position,underline-thickness,unicode,unicode-range,units-per-em,values,version,' +\n    'viewBox,visibility,width,widths,x,x-height,x1,x2,xlink:actuate,xlink:arcrole,xlink:role,' +\n    'xlink:show,xlink:title,xlink:type,xml:base,xml:lang,xml:space,xmlns,xmlns:xlink,y,y1,y2,' +\n    'zoomAndPan');\n\nvar validAttrs = angular.extend({},\n                                uriAttrs,\n                                svgAttrs,\n                                htmlAttrs);\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  if (typeof html !== 'string') {\n    if (html === null || typeof html === 'undefined') {\n      html = '';\n    } else {\n      html = '' + html;\n    }\n  }\n  var index, chars, match, stack = [], last = html, text;\n  stack.last = function() { return stack[stack.length - 1]; };\n\n  while (html) {\n    text = '';\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          // We only have a valid start-tag if there is a '>'.\n          if (match[4]) {\n            html = html.substring(match[0].length);\n            match[0].replace(START_TAG_REGEXP, parseStartTag);\n          }\n          chars = false;\n        } else {\n          // no ending tag found --- this piece should be encoded as an entity.\n          text += '<';\n          html = html.substring(1);\n        }\n      }\n\n      if (chars) {\n        index = html.indexOf(\"<\");\n\n        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      // IE versions 9 and 10 do not understand the regex '[^]', so using a workaround with [\\W\\w].\n      html = html.replace(new RegExp(\"([\\\\W\\\\w]*)<\\\\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 {string} escaped text\n */\nfunction encodeEntities(value) {\n  return value.\n    replace(/&/g, '&amp;').\n    replace(SURROGATE_PAIR_REGEXP, function(value) {\n      var hi = value.charCodeAt(0);\n      var low = value.charCodeAt(1);\n      return '&#' + (((hi - 0xD800) * 0x400) + (low - 0xDC00) + 0x10000) + ';';\n    }).\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 linky\n * @kind 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   <example module=\"linkyExample\" deps=\"angular-sanitize.js\">\n     <file name=\"index.html\">\n       <script>\n         angular.module('linkyExample', ['ngSanitize'])\n           .controller('ExampleController', ['$scope', function($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=\"ExampleController\">\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     </file>\n     <file name=\"protractor.js\" type=\"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     </file>\n   </example>\n */\nangular.module('ngSanitize').filter('linky', ['$sanitize', function($sanitize) {\n  var LINKY_URL_REGEXP =\n        /((ftp|https?):\\/\\/|(www\\.)|(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/www/mailto then assume mailto\n      if (!match[2] && !match[4]) {\n        url = (match[3] ? 'http://' : 'mailto:') + url;\n      }\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                  target,\n                  '\" ');\n      }\n      html.push('href=\"',\n                url.replace(/\"/g, '&quot;'),\n                '\">');\n      addText(text);\n      html.push('</a>');\n    }\n  };\n}]);\n\n\n})(window, window.angular);\n"
  },
  {
    "path": "flowable-ui-web/idm/libs/angular-spectrum-colorpicker_1.0.13/spectrum.css",
    "content": "/***\nSpectrum Colorpicker v1.3.4\nhttps://github.com/bgrins/spectrum\nAuthor: Brian Grinstead\nLicense: MIT\n***/\n\n.sp-container {\n    position:absolute;\n    top:0;\n    left:0;\n    display:inline-block;\n    *display: inline;\n    *zoom: 1;\n    /* https://github.com/bgrins/spectrum/issues/40 */\n    z-index: 9999994;\n    overflow: hidden;\n}\n.sp-container.sp-flat {\n    position: relative;\n}\n\n/* Fix for * { box-sizing: border-box; } */\n.sp-container,\n.sp-container * {\n    -webkit-box-sizing: content-box;\n       -moz-box-sizing: content-box;\n            box-sizing: content-box;\n}\n\n/* http://ansciath.tumblr.com/post/7347495869/css-aspect-ratio */\n.sp-top {\n  position:relative;\n  width: 100%;\n  display:inline-block;\n}\n.sp-top-inner {\n   position:absolute;\n   top:0;\n   left:0;\n   bottom:0;\n   right:0;\n}\n.sp-color {\n    position: absolute;\n    top:0;\n    left:0;\n    bottom:0;\n    right:20%;\n}\n.sp-hue {\n    position: absolute;\n    top:0;\n    right:0;\n    bottom:0;\n    left:84%;\n    height: 100%;\n}\n\n.sp-clear-enabled .sp-hue {\n    top:33px;\n    height: 77.5%;\n}\n\n.sp-fill {\n    padding-top: 80%;\n}\n.sp-sat, .sp-val {\n    position: absolute;\n    top:0;\n    left:0;\n    right:0;\n    bottom:0;\n}\n\n.sp-alpha-enabled .sp-top {\n    margin-bottom: 18px;\n}\n.sp-alpha-enabled .sp-alpha {\n    display: block;\n}\n.sp-alpha-handle {\n    position:absolute;\n    top:-4px;\n    bottom: -4px;\n    width: 6px;\n    left: 50%;\n    cursor: pointer;\n    border: 1px solid black;\n    background: white;\n    opacity: .8;\n}\n.sp-alpha {\n    display: none;\n    position: absolute;\n    bottom: -14px;\n    right: 0;\n    left: 0;\n    height: 8px;\n}\n.sp-alpha-inner {\n    border: solid 1px #333;\n}\n\n.sp-clear {\n    display: none;\n}\n\n.sp-clear.sp-clear-display {\n    background-position: center;\n}\n\n.sp-clear-enabled .sp-clear {\n    display: block;\n    position:absolute;\n    top:0px;\n    right:0;\n    bottom:0;\n    left:84%;\n    height: 28px;\n}\n\n/* Don't allow text selection */\n.sp-container, .sp-replacer, .sp-preview, .sp-dragger, .sp-slider, .sp-alpha, .sp-clear, .sp-alpha-handle, .sp-container.sp-dragging .sp-input, .sp-container button  {\n    -webkit-user-select:none;\n    -moz-user-select: -moz-none;\n    -o-user-select:none;\n    user-select: none;\n}\n\n.sp-container.sp-input-disabled .sp-input-container {\n    display: none;\n}\n.sp-container.sp-buttons-disabled .sp-button-container {\n    display: none;\n}\n.sp-palette-only .sp-picker-container {\n    display: none;\n}\n.sp-palette-disabled .sp-palette-container {\n    display: none;\n}\n\n.sp-initial-disabled .sp-initial {\n    display: none;\n}\n\n\n/* Gradients for hue, saturation and value instead of images.  Not pretty... but it works */\n.sp-sat {\n    background-image: -webkit-gradient(linear,  0 0, 100% 0, from(#FFF), to(rgba(204, 154, 129, 0)));\n    background-image: -webkit-linear-gradient(left, #FFF, rgba(204, 154, 129, 0));\n    background-image: -moz-linear-gradient(left, #fff, rgba(204, 154, 129, 0));\n    background-image: -o-linear-gradient(left, #fff, rgba(204, 154, 129, 0));\n    background-image: -ms-linear-gradient(left, #fff, rgba(204, 154, 129, 0));\n    background-image: linear-gradient(to right, #fff, rgba(204, 154, 129, 0));\n    -ms-filter: \"progid:DXImageTransform.Microsoft.gradient(GradientType = 1, startColorstr=#FFFFFFFF, endColorstr=#00CC9A81)\";\n    filter : progid:DXImageTransform.Microsoft.gradient(GradientType = 1, startColorstr='#FFFFFFFF', endColorstr='#00CC9A81');\n}\n.sp-val {\n    background-image: -webkit-gradient(linear, 0 100%, 0 0, from(#000000), to(rgba(204, 154, 129, 0)));\n    background-image: -webkit-linear-gradient(bottom, #000000, rgba(204, 154, 129, 0));\n    background-image: -moz-linear-gradient(bottom, #000, rgba(204, 154, 129, 0));\n    background-image: -o-linear-gradient(bottom, #000, rgba(204, 154, 129, 0));\n    background-image: -ms-linear-gradient(bottom, #000, rgba(204, 154, 129, 0));\n    background-image: linear-gradient(to top, #000, rgba(204, 154, 129, 0));\n    -ms-filter: \"progid:DXImageTransform.Microsoft.gradient(startColorstr=#00CC9A81, endColorstr=#FF000000)\";\n    filter : progid:DXImageTransform.Microsoft.gradient(startColorstr='#00CC9A81', endColorstr='#FF000000');\n}\n\n.sp-hue {\n    background: -moz-linear-gradient(top, #ff0000 0%, #ffff00 17%, #00ff00 33%, #00ffff 50%, #0000ff 67%, #ff00ff 83%, #ff0000 100%);\n    background: -ms-linear-gradient(top, #ff0000 0%, #ffff00 17%, #00ff00 33%, #00ffff 50%, #0000ff 67%, #ff00ff 83%, #ff0000 100%);\n    background: -o-linear-gradient(top, #ff0000 0%, #ffff00 17%, #00ff00 33%, #00ffff 50%, #0000ff 67%, #ff00ff 83%, #ff0000 100%);\n    background: -webkit-gradient(linear, left top, left bottom, from(#ff0000), color-stop(0.17, #ffff00), color-stop(0.33, #00ff00), color-stop(0.5, #00ffff), color-stop(0.67, #0000ff), color-stop(0.83, #ff00ff), to(#ff0000));\n    background: -webkit-linear-gradient(top, #ff0000 0%, #ffff00 17%, #00ff00 33%, #00ffff 50%, #0000ff 67%, #ff00ff 83%, #ff0000 100%);\n}\n\n/* IE filters do not support multiple color stops.\n   Generate 6 divs, line them up, and do two color gradients for each.\n   Yes, really.\n */\n.sp-1 {\n    height:17%;\n    filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0000', endColorstr='#ffff00');\n}\n.sp-2 {\n    height:16%;\n    filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffff00', endColorstr='#00ff00');\n}\n.sp-3 {\n    height:17%;\n    filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#00ff00', endColorstr='#00ffff');\n}\n.sp-4 {\n    height:17%;\n    filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#00ffff', endColorstr='#0000ff');\n}\n.sp-5 {\n    height:16%;\n    filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#0000ff', endColorstr='#ff00ff');\n}\n.sp-6 {\n    height:17%;\n    filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff00ff', endColorstr='#ff0000');\n}\n\n.sp-hidden {\n    display: none !important;\n}\n\n/* Clearfix hack */\n.sp-cf:before, .sp-cf:after { content: \"\"; display: table; }\n.sp-cf:after { clear: both; }\n.sp-cf { *zoom: 1; }\n\n/* Mobile devices, make hue slider bigger so it is easier to slide */\n@media (max-device-width: 480px) {\n    .sp-color { right: 40%; }\n    .sp-hue { left: 63%; }\n    .sp-fill { padding-top: 60%; }\n}\n.sp-dragger {\n   border-radius: 5px;\n   height: 5px;\n   width: 5px;\n   border: 1px solid #fff;\n   background: #000;\n   cursor: pointer;\n   position:absolute;\n   top:0;\n   left: 0;\n}\n.sp-slider {\n    position: absolute;\n    top:0;\n    cursor:pointer;\n    height: 3px;\n    left: -1px;\n    right: -1px;\n    border: 1px solid #000;\n    background: white;\n    opacity: .8;\n}\n\n/*\nTheme authors:\nHere are the basic themeable display options (colors, fonts, global widths).\nSee http://bgrins.github.io/spectrum/themes/ for instructions.\n*/\n\n.sp-container {\n    border-radius: 0;\n    background-color: #ECECEC;\n    border: solid 1px #f0c49B;\n    padding: 0;\n}\n.sp-container, .sp-container button, .sp-container input, .sp-color, .sp-hue, .sp-clear\n{\n    font: normal 12px \"Lucida Grande\", \"Lucida Sans Unicode\", \"Lucida Sans\", Geneva, Verdana, sans-serif;\n    -webkit-box-sizing: border-box;\n    -moz-box-sizing: border-box;\n    -ms-box-sizing: border-box;\n    box-sizing: border-box;\n}\n.sp-top\n{\n    margin-bottom: 3px;\n}\n.sp-color, .sp-hue, .sp-clear\n{\n    border: solid 1px #666;\n}\n\n/* Input */\n.sp-input-container {\n    float:right;\n    width: 100px;\n    margin-bottom: 4px;\n}\n.sp-initial-disabled  .sp-input-container {\n    width: 100%;\n}\n.sp-input {\n   font-size: 12px !important;\n   border: 1px inset;\n   padding: 4px 5px;\n   margin: 0;\n   width: 100%;\n   background:transparent;\n   border-radius: 3px;\n   color: #222;\n}\n.sp-input:focus  {\n    border: 1px solid orange;\n}\n.sp-input.sp-validation-error\n{\n    border: 1px solid red;\n    background: #fdd;\n}\n.sp-picker-container , .sp-palette-container\n{\n    float:left;\n    position: relative;\n    padding: 10px;\n    padding-bottom: 300px;\n    margin-bottom: -290px;\n}\n.sp-picker-container\n{\n    width: 172px;\n    border-left: solid 1px #fff;\n}\n\n/* Palettes */\n.sp-palette-container\n{\n    border-right: solid 1px #ccc;\n}\n\n.sp-palette .sp-thumb-el {\n    display: block;\n    position:relative;\n    float:left;\n    width: 24px;\n    height: 15px;\n    margin: 3px;\n    cursor: pointer;\n    border:solid 2px transparent;\n}\n.sp-palette .sp-thumb-el:hover, .sp-palette .sp-thumb-el.sp-thumb-active {\n    border-color: orange;\n}\n.sp-thumb-el\n{\n    position:relative;\n}\n\n/* Initial */\n.sp-initial\n{\n    float: left;\n    border: solid 1px #333;\n}\n.sp-initial span {\n    width: 30px;\n    height: 25px;\n    border:none;\n    display:block;\n    float:left;\n    margin:0;\n}\n\n.sp-initial .sp-clear-display {\n    background-position: center;\n}\n\n/* Buttons */\n.sp-button-container {\n    float: right;\n}\n\n/* Replacer (the little preview div that shows up instead of the <input>) */\n.sp-replacer {\n    margin:0;\n    overflow:hidden;\n    cursor:pointer;\n    padding: 4px;\n    display:inline-block;\n    *zoom: 1;\n    *display: inline;\n    border: solid 1px #91765d;\n    background: #eee;\n    color: #333;\n    vertical-align: middle;\n}\n.sp-replacer:hover, .sp-replacer.sp-active {\n    border-color: #F0C49B;\n    color: #111;\n}\n.sp-replacer.sp-disabled {\n    cursor:default;\n    border-color: silver;\n    color: silver;\n}\n.sp-dd {\n    padding: 2px 0;\n    height: 16px;\n    line-height: 16px;\n    float:left;\n    font-size:10px;\n}\n.sp-preview\n{\n    position:relative;\n    width:25px;\n    height: 20px;\n    border: solid 1px #222;\n    margin-right: 5px;\n    float:left;\n    z-index: 0;\n}\n\n.sp-palette\n{\n    *width: 220px;\n    max-width: 220px;\n}\n.sp-palette .sp-thumb-el\n{\n    width:16px;\n    height: 16px;\n    margin:2px 1px;\n    border: solid 1px #d0d0d0;\n}\n\n.sp-container\n{\n    padding-bottom:0;\n}\n\n\n/* Buttons: http://hellohappy.org/css3-buttons/ */\n.sp-container button {\n  background-color: #eeeeee;\n  background-image: -webkit-linear-gradient(top, #eeeeee, #cccccc);\n  background-image: -moz-linear-gradient(top, #eeeeee, #cccccc);\n  background-image: -ms-linear-gradient(top, #eeeeee, #cccccc);\n  background-image: -o-linear-gradient(top, #eeeeee, #cccccc);\n  background-image: linear-gradient(to bottom, #eeeeee, #cccccc);\n  border: 1px solid #ccc;\n  border-bottom: 1px solid #bbb;\n  border-radius: 3px;\n  color: #333;\n  font-size: 14px;\n  line-height: 1;\n  padding: 5px 4px;\n  text-align: center;\n  text-shadow: 0 1px 0 #eee;\n  vertical-align: middle;\n}\n.sp-container button:hover {\n    background-color: #dddddd;\n    background-image: -webkit-linear-gradient(top, #dddddd, #bbbbbb);\n    background-image: -moz-linear-gradient(top, #dddddd, #bbbbbb);\n    background-image: -ms-linear-gradient(top, #dddddd, #bbbbbb);\n    background-image: -o-linear-gradient(top, #dddddd, #bbbbbb);\n    background-image: linear-gradient(to bottom, #dddddd, #bbbbbb);\n    border: 1px solid #bbb;\n    border-bottom: 1px solid #999;\n    cursor: pointer;\n    text-shadow: 0 1px 0 #ddd;\n}\n.sp-container button:active {\n    border: 1px solid #aaa;\n    border-bottom: 1px solid #888;\n    -webkit-box-shadow: inset 0 0 5px 2px #aaaaaa, 0 1px 0 0 #eeeeee;\n    -moz-box-shadow: inset 0 0 5px 2px #aaaaaa, 0 1px 0 0 #eeeeee;\n    -ms-box-shadow: inset 0 0 5px 2px #aaaaaa, 0 1px 0 0 #eeeeee;\n    -o-box-shadow: inset 0 0 5px 2px #aaaaaa, 0 1px 0 0 #eeeeee;\n    box-shadow: inset 0 0 5px 2px #aaaaaa, 0 1px 0 0 #eeeeee;\n}\n.sp-cancel\n{\n    font-size: 11px;\n    color: #d93f3f !important;\n    margin:0;\n    padding:2px;\n    margin-right: 5px;\n    vertical-align: middle;\n    text-decoration:none;\n\n}\n.sp-cancel:hover\n{\n    color: #d93f3f !important;\n    text-decoration: underline;\n}\n\n\n.sp-palette span:hover, .sp-palette span.sp-thumb-active\n{\n    border-color: #000;\n}\n\n.sp-preview, .sp-alpha, .sp-thumb-el\n{\n    position:relative;\n    background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAIAAADZF8uwAAAAGUlEQVQYV2M4gwH+YwCGIasIUwhT25BVBADtzYNYrHvv4gAAAABJRU5ErkJggg==);\n}\n.sp-preview-inner, .sp-alpha-inner, .sp-thumb-inner\n{\n    display:block;\n    position:absolute;\n    top:0;left:0;bottom:0;right:0;\n}\n\n.sp-palette .sp-thumb-inner\n{\n    background-position: 50% 50%;\n    background-repeat: no-repeat;\n}\n\n.sp-palette .sp-thumb-light.sp-thumb-active .sp-thumb-inner\n{\n    background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAYAAABWzo5XAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAIVJREFUeNpiYBhsgJFMffxAXABlN5JruT4Q3wfi/0DsT64h8UD8HmpIPCWG/KemIfOJCUB+Aoacx6EGBZyHBqI+WsDCwuQ9mhxeg2A210Ntfo8klk9sOMijaURm7yc1UP2RNCMbKE9ODK1HM6iegYLkfx8pligC9lCD7KmRof0ZhjQACDAAceovrtpVBRkAAAAASUVORK5CYII=);\n}\n\n.sp-palette .sp-thumb-dark.sp-thumb-active .sp-thumb-inner\n{\n    background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAYAAABWzo5XAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAadEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My41LjEwMPRyoQAAAMdJREFUOE+tkgsNwzAMRMugEAahEAahEAZhEAqlEAZhEAohEAYh81X2dIm8fKpEspLGvudPOsUYpxE2BIJCroJmEW9qJ+MKaBFhEMNabSy9oIcIPwrB+afvAUFoK4H0tMaQ3XtlrggDhOVVMuT4E5MMG0FBbCEYzjYT7OxLEvIHQLY2zWwQ3D+9luyOQTfKDiFD3iUIfPk8VqrKjgAiSfGFPecrg6HN6m/iBcwiDAo7WiBeawa+Kwh7tZoSCGLMqwlSAzVDhoK+6vH4G0P5wdkAAAAASUVORK5CYII=);\n}\n\n.sp-clear-display {\n    background-repeat:no-repeat;\n    background-position: center;\n    background-image: url(data:image/gif;base64,R0lGODlhFAAUAPcAAAAAAJmZmZ2dnZ6enqKioqOjo6SkpKWlpaampqenp6ioqKmpqaqqqqurq/Hx8fLy8vT09PX19ff39/j4+Pn5+fr6+vv7+wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAP8ALAAAAAAUABQAAAihAP9FoPCvoMGDBy08+EdhQAIJCCMybCDAAYUEARBAlFiQQoMABQhKUJBxY0SPICEYHBnggEmDKAuoPMjS5cGYMxHW3IiT478JJA8M/CjTZ0GgLRekNGpwAsYABHIypcAgQMsITDtWJYBR6NSqMico9cqR6tKfY7GeBCuVwlipDNmefAtTrkSzB1RaIAoXodsABiZAEFB06gIBWC1mLVgBa0AAOw==);\n}\n"
  },
  {
    "path": "flowable-ui-web/idm/libs/angular-spectrum-colorpicker_1.0.13/spectrum.js",
    "content": "// Spectrum Colorpicker v1.3.4\n// https://github.com/bgrins/spectrum\n// Author: Brian Grinstead\n// License: MIT\n\n(function (window, $, undefined) {\n    var defaultOpts = {\n\n        // Callbacks\n        beforeShow: noop,\n        move: noop,\n        change: noop,\n        show: noop,\n        hide: noop,\n\n        // Options\n        color: false,\n        flat: false,\n        showInput: false,\n        allowEmpty: false,\n        showButtons: true,\n        clickoutFiresChange: false,\n        showInitial: false,\n        showPalette: false,\n        showPaletteOnly: false,\n        showSelectionPalette: true,\n        localStorageKey: false,\n        appendTo: \"body\",\n        maxSelectionSize: 7,\n        cancelText: \"cancel\",\n        chooseText: \"choose\",\n        clearText: \"Clear Color Selection\",\n        preferredFormat: false,\n        className: \"\", // Deprecated - use containerClassName and replacerClassName instead.\n        containerClassName: \"\",\n        replacerClassName: \"\",\n        showAlpha: false,\n        theme: \"sp-light\",\n        palette: [[\"#ffffff\", \"#000000\", \"#ff0000\", \"#ff8000\", \"#ffff00\", \"#008000\", \"#0000ff\", \"#4b0082\", \"#9400d3\"]],\n        selectionPalette: [],\n        disabled: false\n    },\n    spectrums = [],\n    IE = !!/msie/i.exec( window.navigator.userAgent ),\n    rgbaSupport = (function() {\n        function contains( str, substr ) {\n            return !!~('' + str).indexOf(substr);\n        }\n\n        var elem = document.createElement('div');\n        var style = elem.style;\n        style.cssText = 'background-color:rgba(0,0,0,.5)';\n        return contains(style.backgroundColor, 'rgba') || contains(style.backgroundColor, 'hsla');\n    })(),\n    inputTypeColorSupport = (function() {\n        var colorInput = $(\"<input type='color' value='!' />\")[0];\n        return colorInput.type === \"color\" && colorInput.value !== \"!\";\n    })(),\n    replaceInput = [\n        \"<div class='sp-replacer'>\",\n            \"<div class='sp-preview'><div class='sp-preview-inner'></div></div>\",\n            \"<div class='sp-dd'>&#9660;</div>\",\n        \"</div>\"\n    ].join(''),\n    markup = (function () {\n\n        // IE does not support gradients with multiple stops, so we need to simulate\n        //  that for the rainbow slider with 8 divs that each have a single gradient\n        var gradientFix = \"\";\n        if (IE) {\n            for (var i = 1; i <= 6; i++) {\n                gradientFix += \"<div class='sp-\" + i + \"'></div>\";\n            }\n        }\n\n        return [\n            \"<div class='sp-container sp-hidden'>\",\n                \"<div class='sp-palette-container'>\",\n                    \"<div class='sp-palette sp-thumb sp-cf'></div>\",\n                \"</div>\",\n                \"<div class='sp-picker-container'>\",\n                    \"<div class='sp-top sp-cf'>\",\n                        \"<div class='sp-fill'></div>\",\n                        \"<div class='sp-top-inner'>\",\n                            \"<div class='sp-color'>\",\n                                \"<div class='sp-sat'>\",\n                                    \"<div class='sp-val'>\",\n                                        \"<div class='sp-dragger'></div>\",\n                                    \"</div>\",\n                                \"</div>\",\n                            \"</div>\",\n                            \"<div class='sp-clear sp-clear-display'>\",\n                            \"</div>\",\n                            \"<div class='sp-hue'>\",\n                                \"<div class='sp-slider'></div>\",\n                                gradientFix,\n                            \"</div>\",\n                        \"</div>\",\n                        \"<div class='sp-alpha'><div class='sp-alpha-inner'><div class='sp-alpha-handle'></div></div></div>\",\n                    \"</div>\",\n                    \"<div class='sp-input-container sp-cf'>\",\n                        \"<input class='sp-input' type='text' spellcheck='false'  />\",\n                    \"</div>\",\n                    \"<div class='sp-initial sp-thumb sp-cf'></div>\",\n                    \"<div class='sp-button-container sp-cf'>\",\n                        \"<a class='sp-cancel' href='#'></a>\",\n                        \"<button type='button' class='sp-choose'></button>\",\n                    \"</div>\",\n                \"</div>\",\n            \"</div>\"\n        ].join(\"\");\n    })();\n\n    function paletteTemplate (p, color, className, tooltipFormat) {\n        var html = [];\n        for (var i = 0; i < p.length; i++) {\n            var current = p[i];\n            if(current) {\n                var tiny = tinycolor(current);\n                var c = tiny.toHsl().l < 0.5 ? \"sp-thumb-el sp-thumb-dark\" : \"sp-thumb-el sp-thumb-light\";\n                c += (tinycolor.equals(color, current)) ? \" sp-thumb-active\" : \"\";\n\n                var formattedString = tiny.toString(tooltipFormat || \"rgb\");\n                var swatchStyle = rgbaSupport ? (\"background-color:\" + tiny.toRgbString()) : \"filter:\" + tiny.toFilter();\n                html.push('<span title=\"' + formattedString + '\" data-color=\"' + tiny.toRgbString() + '\" class=\"' + c + '\"><span class=\"sp-thumb-inner\" style=\"' + swatchStyle + ';\" /></span>');\n            } else {\n                var cls = 'sp-clear-display';\n                html.push('<span title=\"No Color Selected\" data-color=\"\" style=\"background-color:transparent;\" class=\"' + cls + '\"></span>');\n            }\n        }\n        return \"<div class='sp-cf \" + className + \"'>\" + html.join('') + \"</div>\";\n    }\n\n    function hideAll() {\n        for (var i = 0; i < spectrums.length; i++) {\n            if (spectrums[i]) {\n                spectrums[i].hide();\n            }\n        }\n    }\n\n    function instanceOptions(o, callbackContext) {\n        var opts = $.extend({}, defaultOpts, o);\n        opts.callbacks = {\n            'move': bind(opts.move, callbackContext),\n            'change': bind(opts.change, callbackContext),\n            'show': bind(opts.show, callbackContext),\n            'hide': bind(opts.hide, callbackContext),\n            'beforeShow': bind(opts.beforeShow, callbackContext)\n        };\n\n        return opts;\n    }\n\n    function spectrum(element, o) {\n\n        var opts = instanceOptions(o, element),\n            flat = opts.flat,\n            showSelectionPalette = opts.showSelectionPalette,\n            localStorageKey = opts.localStorageKey,\n            theme = opts.theme,\n            callbacks = opts.callbacks,\n            resize = throttle(reflow, 10),\n            visible = false,\n            dragWidth = 0,\n            dragHeight = 0,\n            dragHelperHeight = 0,\n            slideHeight = 0,\n            slideWidth = 0,\n            alphaWidth = 0,\n            alphaSlideHelperWidth = 0,\n            slideHelperHeight = 0,\n            currentHue = 0,\n            currentSaturation = 0,\n            currentValue = 0,\n            currentAlpha = 1,\n            palette = [],\n            paletteArray = [],\n            paletteLookup = {},\n            selectionPalette = opts.selectionPalette.slice(0),\n            maxSelectionSize = opts.maxSelectionSize,\n            draggingClass = \"sp-dragging\",\n            shiftMovementDirection = null;\n\n        var doc = element.ownerDocument,\n            body = doc.body,\n            boundElement = $(element),\n            disabled = false,\n            container = $(markup, doc).addClass(theme),\n            dragger = container.find(\".sp-color\"),\n            dragHelper = container.find(\".sp-dragger\"),\n            slider = container.find(\".sp-hue\"),\n            slideHelper = container.find(\".sp-slider\"),\n            alphaSliderInner = container.find(\".sp-alpha-inner\"),\n            alphaSlider = container.find(\".sp-alpha\"),\n            alphaSlideHelper = container.find(\".sp-alpha-handle\"),\n            textInput = container.find(\".sp-input\"),\n            paletteContainer = container.find(\".sp-palette\"),\n            initialColorContainer = container.find(\".sp-initial\"),\n            cancelButton = container.find(\".sp-cancel\"),\n            clearButton = container.find(\".sp-clear\"),\n            chooseButton = container.find(\".sp-choose\"),\n            isInput = boundElement.is(\"input\"),\n            isInputTypeColor = isInput && inputTypeColorSupport && boundElement.attr(\"type\") === \"color\",\n            shouldReplace = isInput && !flat,\n            replacer = (shouldReplace) ? $(replaceInput).addClass(theme).addClass(opts.className).addClass(opts.replacerClassName) : $([]),\n            offsetElement = (shouldReplace) ? replacer : boundElement,\n            previewElement = replacer.find(\".sp-preview-inner\"),\n            initialColor = opts.color || (isInput && boundElement.val()),\n            colorOnShow = false,\n            preferredFormat = opts.preferredFormat,\n            currentPreferredFormat = preferredFormat,\n            clickoutFiresChange = !opts.showButtons || opts.clickoutFiresChange,\n            isEmpty = !initialColor,\n            allowEmpty = opts.allowEmpty && !isInputTypeColor;\n\n        function applyOptions() {\n\n            if (opts.showPaletteOnly) {\n                opts.showPalette = true;\n            }\n\n            if (opts.palette) {\n                palette = opts.palette.slice(0);\n                paletteArray = $.isArray(palette[0]) ? palette : [palette];\n                paletteLookup = {};\n                for (var i = 0; i < paletteArray.length; i++) {\n                    for (var j = 0; j < paletteArray[i].length; j++) {\n                        var rgb = tinycolor(paletteArray[i][j]).toRgbString();\n                        paletteLookup[rgb] = true;\n                    }\n                }\n            }\n\n            container.toggleClass(\"sp-flat\", flat);\n            container.toggleClass(\"sp-input-disabled\", !opts.showInput);\n            container.toggleClass(\"sp-alpha-enabled\", opts.showAlpha);\n            container.toggleClass(\"sp-clear-enabled\", allowEmpty);\n            container.toggleClass(\"sp-buttons-disabled\", !opts.showButtons);\n            container.toggleClass(\"sp-palette-disabled\", !opts.showPalette);\n            container.toggleClass(\"sp-palette-only\", opts.showPaletteOnly);\n            container.toggleClass(\"sp-initial-disabled\", !opts.showInitial);\n            container.addClass(opts.className).addClass(opts.containerClassName);\n\n            reflow();\n        }\n\n        function initialize() {\n\n            if (IE) {\n                container.find(\"*:not(input)\").attr(\"unselectable\", \"on\");\n            }\n\n            applyOptions();\n\n            if (shouldReplace) {\n                boundElement.after(replacer).hide();\n            }\n\n            if (!allowEmpty) {\n                clearButton.hide();\n            }\n\n            if (flat) {\n                boundElement.after(container).hide();\n            }\n            else {\n\n                var appendTo = opts.appendTo === \"parent\" ? boundElement.parent() : $(opts.appendTo);\n                if (appendTo.length !== 1) {\n                    appendTo = $(\"body\");\n                }\n\n                appendTo.append(container);\n            }\n\n            updateSelectionPaletteFromStorage();\n\n            offsetElement.bind(\"click.spectrum touchstart.spectrum\", function (e) {\n                if (!disabled) {\n                    toggle();\n                }\n\n                e.stopPropagation();\n\n                if (!$(e.target).is(\"input\")) {\n                    e.preventDefault();\n                }\n            });\n\n            if(boundElement.is(\":disabled\") || (opts.disabled === true)) {\n                disable();\n            }\n\n            // Prevent clicks from bubbling up to document.  This would cause it to be hidden.\n            container.click(stopPropagation);\n\n            // Handle user typed input\n            textInput.change(setFromTextInput);\n            textInput.bind(\"paste\", function () {\n                setTimeout(setFromTextInput, 1);\n            });\n            textInput.keydown(function (e) { if (e.keyCode == 13) { setFromTextInput(); } });\n\n            cancelButton.text(opts.cancelText);\n            cancelButton.bind(\"click.spectrum\", function (e) {\n                e.stopPropagation();\n                e.preventDefault();\n                hide(\"cancel\");\n            });\n\n            clearButton.attr(\"title\", opts.clearText);\n            clearButton.bind(\"click.spectrum\", function (e) {\n                e.stopPropagation();\n                e.preventDefault();\n                isEmpty = true;\n                move();\n\n                if(flat) {\n                    //for the flat style, this is a change event\n                    updateOriginalInput(true);\n                }\n            });\n\n            chooseButton.text(opts.chooseText);\n            chooseButton.bind(\"click.spectrum\", function (e) {\n                e.stopPropagation();\n                e.preventDefault();\n\n                if (isValid()) {\n                    updateOriginalInput(true);\n                    hide();\n                }\n            });\n\n            draggable(alphaSlider, function (dragX, dragY, e) {\n                currentAlpha = (dragX / alphaWidth);\n                isEmpty = false;\n                if (e.shiftKey) {\n                    currentAlpha = Math.round(currentAlpha * 10) / 10;\n                }\n\n                move();\n            }, dragStart, dragStop);\n\n            draggable(slider, function (dragX, dragY) {\n                currentHue = parseFloat(dragY / slideHeight);\n                isEmpty = false;\n                if (!opts.showAlpha) {\n                    currentAlpha = 1;\n                }\n                move();\n            }, dragStart, dragStop);\n\n            draggable(dragger, function (dragX, dragY, e) {\n\n                // shift+drag should snap the movement to either the x or y axis.\n                if (!e.shiftKey) {\n                    shiftMovementDirection = null;\n                }\n                else if (!shiftMovementDirection) {\n                    var oldDragX = currentSaturation * dragWidth;\n                    var oldDragY = dragHeight - (currentValue * dragHeight);\n                    var furtherFromX = Math.abs(dragX - oldDragX) > Math.abs(dragY - oldDragY);\n\n                    shiftMovementDirection = furtherFromX ? \"x\" : \"y\";\n                }\n\n                var setSaturation = !shiftMovementDirection || shiftMovementDirection === \"x\";\n                var setValue = !shiftMovementDirection || shiftMovementDirection === \"y\";\n\n                if (setSaturation) {\n                    currentSaturation = parseFloat(dragX / dragWidth);\n                }\n                if (setValue) {\n                    currentValue = parseFloat((dragHeight - dragY) / dragHeight);\n                }\n\n                isEmpty = false;\n                if (!opts.showAlpha) {\n                    currentAlpha = 1;\n                }\n\n                move();\n\n            }, dragStart, dragStop);\n\n            if (!!initialColor) {\n                set(initialColor);\n\n                // In case color was black - update the preview UI and set the format\n                // since the set function will not run (default color is black).\n                updateUI();\n                currentPreferredFormat = preferredFormat || tinycolor(initialColor).format;\n\n                addColorToSelectionPalette(initialColor);\n            }\n            else {\n                updateUI();\n            }\n\n            if (flat) {\n                show();\n            }\n\n            function palletElementClick(e) {\n                if (e.data && e.data.ignore) {\n                    set($(this).data(\"color\"));\n                    move();\n                }\n                else {\n                    set($(this).data(\"color\"));\n                    move();\n                    updateOriginalInput(true);\n                    hide();\n                }\n\n                return false;\n            }\n\n            var paletteEvent = IE ? \"mousedown.spectrum\" : \"click.spectrum touchstart.spectrum\";\n            paletteContainer.delegate(\".sp-thumb-el\", paletteEvent, palletElementClick);\n            initialColorContainer.delegate(\".sp-thumb-el:nth-child(1)\", paletteEvent, { ignore: true }, palletElementClick);\n        }\n\n        function updateSelectionPaletteFromStorage() {\n\n            if (localStorageKey && window.localStorage) {\n\n                // Migrate old palettes over to new format.  May want to remove this eventually.\n                try {\n                    var oldPalette = window.localStorage[localStorageKey].split(\",#\");\n                    if (oldPalette.length > 1) {\n                        delete window.localStorage[localStorageKey];\n                        $.each(oldPalette, function(i, c) {\n                             addColorToSelectionPalette(c);\n                        });\n                    }\n                }\n                catch(e) { }\n\n                try {\n                    selectionPalette = window.localStorage[localStorageKey].split(\";\");\n                }\n                catch (e) { }\n            }\n        }\n\n        function addColorToSelectionPalette(color) {\n            if (showSelectionPalette) {\n                var rgb = tinycolor(color).toRgbString();\n                if (!paletteLookup[rgb] && $.inArray(rgb, selectionPalette) === -1) {\n                    selectionPalette.push(rgb);\n                    while(selectionPalette.length > maxSelectionSize) {\n                        selectionPalette.shift();\n                    }\n                }\n\n                if (localStorageKey && window.localStorage) {\n                    try {\n                        window.localStorage[localStorageKey] = selectionPalette.join(\";\");\n                    }\n                    catch(e) { }\n                }\n            }\n        }\n\n        function getUniqueSelectionPalette() {\n            var unique = [];\n            if (opts.showPalette) {\n                for (i = 0; i < selectionPalette.length; i++) {\n                    var rgb = tinycolor(selectionPalette[i]).toRgbString();\n\n                    if (!paletteLookup[rgb]) {\n                        unique.push(selectionPalette[i]);\n                    }\n                }\n            }\n\n            return unique.reverse().slice(0, opts.maxSelectionSize);\n        }\n\n        function drawPalette() {\n\n            var currentColor = get();\n\n            var html = $.map(paletteArray, function (palette, i) {\n                return paletteTemplate(palette, currentColor, \"sp-palette-row sp-palette-row-\" + i, opts.preferredFormat);\n            });\n\n            updateSelectionPaletteFromStorage();\n\n            if (selectionPalette) {\n                html.push(paletteTemplate(getUniqueSelectionPalette(), currentColor, \"sp-palette-row sp-palette-row-selection\", opts.preferredFormat));\n            }\n\n            paletteContainer.html(html.join(\"\"));\n        }\n\n        function drawInitial() {\n            if (opts.showInitial) {\n                var initial = colorOnShow;\n                var current = get();\n                initialColorContainer.html(paletteTemplate([initial, current], current, \"sp-palette-row-initial\", opts.preferredFormat));\n            }\n        }\n\n        function dragStart() {\n            if (dragHeight <= 0 || dragWidth <= 0 || slideHeight <= 0) {\n                reflow();\n            }\n            container.addClass(draggingClass);\n            shiftMovementDirection = null;\n            boundElement.trigger('dragstart.spectrum', [ get() ]);\n        }\n\n        function dragStop() {\n            container.removeClass(draggingClass);\n            boundElement.trigger('dragstop.spectrum', [ get() ]);\n        }\n\n        function setFromTextInput() {\n\n            var value = textInput.val();\n\n            if ((value === null || value === \"\") && allowEmpty) {\n                set(null);\n                updateOriginalInput(true);\n            }\n            else {\n                var tiny = tinycolor(value);\n                if (tiny.ok) {\n                    set(tiny);\n                    updateOriginalInput(true);\n                }\n                else {\n                    textInput.addClass(\"sp-validation-error\");\n                }\n            }\n        }\n\n        function toggle() {\n            if (visible) {\n                hide();\n            }\n            else {\n                show();\n            }\n        }\n\n        function show() {\n            var event = $.Event('beforeShow.spectrum');\n\n            if (visible) {\n                reflow();\n                return;\n            }\n\n            boundElement.trigger(event, [ get() ]);\n\n            if (callbacks.beforeShow(get()) === false || event.isDefaultPrevented()) {\n                return;\n            }\n\n            hideAll();\n            visible = true;\n\n            $(doc).bind(\"click.spectrum\", hide);\n            $(window).bind(\"resize.spectrum\", resize);\n            replacer.addClass(\"sp-active\");\n            container.removeClass(\"sp-hidden\");\n\n            reflow();\n            updateUI();\n\n            colorOnShow = get();\n\n            drawInitial();\n            callbacks.show(colorOnShow);\n            boundElement.trigger('show.spectrum', [ colorOnShow ]);\n        }\n\n        function hide(e) {\n\n            // Return on right click\n            if (e && e.type == \"click\" && e.button == 2) { return; }\n\n            // Return if hiding is unnecessary\n            if (!visible || flat) { return; }\n            visible = false;\n\n            $(doc).unbind(\"click.spectrum\", hide);\n            $(window).unbind(\"resize.spectrum\", resize);\n\n            replacer.removeClass(\"sp-active\");\n            container.addClass(\"sp-hidden\");\n\n            var colorHasChanged = !tinycolor.equals(get(), colorOnShow);\n\n            if (colorHasChanged) {\n                if (clickoutFiresChange && e !== \"cancel\") {\n                    updateOriginalInput(true);\n                }\n                else {\n                    revert();\n                }\n            }\n\n            callbacks.hide(get());\n            boundElement.trigger('hide.spectrum', [ get() ]);\n        }\n\n        function revert() {\n            set(colorOnShow, true);\n        }\n\n        function set(color, ignoreFormatChange) {\n            if (tinycolor.equals(color, get())) {\n                // Update UI just in case a validation error needs\n                // to be cleared.\n                updateUI();\n                return;\n            }\n\n            var newColor, newHsv;\n            if (!color && allowEmpty) {\n                isEmpty = true;\n            } else {\n                isEmpty = false;\n                newColor = tinycolor(color);\n                newHsv = newColor.toHsv();\n\n                currentHue = (newHsv.h % 360) / 360;\n                currentSaturation = newHsv.s;\n                currentValue = newHsv.v;\n                currentAlpha = newHsv.a;\n            }\n            updateUI();\n\n            if (newColor && newColor.ok && !ignoreFormatChange) {\n                currentPreferredFormat = preferredFormat || newColor.format;\n            }\n        }\n\n        function get(opts) {\n            opts = opts || { };\n\n            if (allowEmpty && isEmpty) {\n                return null;\n            }\n\n            return tinycolor.fromRatio({\n                h: currentHue,\n                s: currentSaturation,\n                v: currentValue,\n                a: Math.round(currentAlpha * 100) / 100\n            }, { format: opts.format || currentPreferredFormat });\n        }\n\n        function isValid() {\n            return !textInput.hasClass(\"sp-validation-error\");\n        }\n\n        function move() {\n            updateUI();\n\n            callbacks.move(get());\n            boundElement.trigger('move.spectrum', [ get() ]);\n        }\n\n        function updateUI() {\n\n            textInput.removeClass(\"sp-validation-error\");\n\n            updateHelperLocations();\n\n            // Update dragger background color (gradients take care of saturation and value).\n            var flatColor = tinycolor.fromRatio({ h: currentHue, s: 1, v: 1 });\n            dragger.css(\"background-color\", flatColor.toHexString());\n\n            // Get a format that alpha will be included in (hex and names ignore alpha)\n            var format = currentPreferredFormat;\n            if (currentAlpha < 1 && !(currentAlpha === 0 && format === \"name\")) {\n                if (format === \"hex\" || format === \"hex3\" || format === \"hex6\" || format === \"name\") {\n                    format = \"rgb\";\n                }\n            }\n\n            var realColor = get({ format: format }),\n                displayColor = '';\n\n             //reset background info for preview element\n            previewElement.removeClass(\"sp-clear-display\");\n            previewElement.css('background-color', 'transparent');\n\n            if (!realColor && allowEmpty) {\n                // Update the replaced elements background with icon indicating no color selection\n                previewElement.addClass(\"sp-clear-display\");\n            }\n            else {\n                var realHex = realColor.toHexString(),\n                    realRgb = realColor.toRgbString();\n\n                // Update the replaced elements background color (with actual selected color)\n                if (rgbaSupport || realColor.alpha === 1) {\n                    previewElement.css(\"background-color\", realRgb);\n                }\n                else {\n                    previewElement.css(\"background-color\", \"transparent\");\n                    previewElement.css(\"filter\", realColor.toFilter());\n                }\n\n                if (opts.showAlpha) {\n                    var rgb = realColor.toRgb();\n                    rgb.a = 0;\n                    var realAlpha = tinycolor(rgb).toRgbString();\n                    var gradient = \"linear-gradient(left, \" + realAlpha + \", \" + realHex + \")\";\n\n                    if (IE) {\n                        alphaSliderInner.css(\"filter\", tinycolor(realAlpha).toFilter({ gradientType: 1 }, realHex));\n                    }\n                    else {\n                        alphaSliderInner.css(\"background\", \"-webkit-\" + gradient);\n                        alphaSliderInner.css(\"background\", \"-moz-\" + gradient);\n                        alphaSliderInner.css(\"background\", \"-ms-\" + gradient);\n                        // Use current syntax gradient on unprefixed property.\n                        alphaSliderInner.css(\"background\",\n                            \"linear-gradient(to right, \" + realAlpha + \", \" + realHex + \")\");\n                    }\n                }\n\n                displayColor = realColor.toString(format);\n            }\n\n            // Update the text entry input as it changes happen\n            if (opts.showInput) {\n                textInput.val(displayColor);\n            }\n\n            if (opts.showPalette) {\n                drawPalette();\n            }\n\n            drawInitial();\n        }\n\n        function updateHelperLocations() {\n            var s = currentSaturation;\n            var v = currentValue;\n\n            if(allowEmpty && isEmpty) {\n                //if selected color is empty, hide the helpers\n                alphaSlideHelper.hide();\n                slideHelper.hide();\n                dragHelper.hide();\n            }\n            else {\n                //make sure helpers are visible\n                alphaSlideHelper.show();\n                slideHelper.show();\n                dragHelper.show();\n\n                // Where to show the little circle in that displays your current selected color\n                var dragX = s * dragWidth;\n                var dragY = dragHeight - (v * dragHeight);\n                dragX = Math.max(\n                    -dragHelperHeight,\n                    Math.min(dragWidth - dragHelperHeight, dragX - dragHelperHeight)\n                );\n                dragY = Math.max(\n                    -dragHelperHeight,\n                    Math.min(dragHeight - dragHelperHeight, dragY - dragHelperHeight)\n                );\n                dragHelper.css({\n                    \"top\": dragY + \"px\",\n                    \"left\": dragX + \"px\"\n                });\n\n                var alphaX = currentAlpha * alphaWidth;\n                alphaSlideHelper.css({\n                    \"left\": (alphaX - (alphaSlideHelperWidth / 2)) + \"px\"\n                });\n\n                // Where to show the bar that displays your current selected hue\n                var slideY = (currentHue) * slideHeight;\n                slideHelper.css({\n                    \"top\": (slideY - slideHelperHeight) + \"px\"\n                });\n            }\n        }\n\n        function updateOriginalInput(fireCallback) {\n            var color = get(),\n                displayColor = '',\n                hasChanged = !tinycolor.equals(color, colorOnShow);\n\n            if (color) {\n                displayColor = color.toString(currentPreferredFormat);\n                // Update the selection palette with the current color\n                addColorToSelectionPalette(color);\n            }\n\n            if (isInput) {\n                boundElement.val(displayColor);\n            }\n\n            colorOnShow = color;\n\n            if (fireCallback && hasChanged) {\n                callbacks.change(color);\n                boundElement.trigger('change', [ color ]);\n            }\n        }\n\n        function reflow() {\n            dragWidth = dragger.width();\n            dragHeight = dragger.height();\n            dragHelperHeight = dragHelper.height();\n            slideWidth = slider.width();\n            slideHeight = slider.height();\n            slideHelperHeight = slideHelper.height();\n            alphaWidth = alphaSlider.width();\n            alphaSlideHelperWidth = alphaSlideHelper.width();\n\n            if (!flat) {\n                container.css(\"position\", \"absolute\");\n                container.offset(getOffset(container, offsetElement));\n            }\n\n            updateHelperLocations();\n\n            if (opts.showPalette) {\n                drawPalette();\n            }\n\n            boundElement.trigger('reflow.spectrum');\n        }\n\n        function destroy() {\n            boundElement.show();\n            offsetElement.unbind(\"click.spectrum touchstart.spectrum\");\n            container.remove();\n            replacer.remove();\n            spectrums[spect.id] = null;\n        }\n\n        function option(optionName, optionValue) {\n            if (optionName === undefined) {\n                return $.extend({}, opts);\n            }\n            if (optionValue === undefined) {\n                return opts[optionName];\n            }\n\n            opts[optionName] = optionValue;\n            applyOptions();\n        }\n\n        function enable() {\n            disabled = false;\n            boundElement.attr(\"disabled\", false);\n            offsetElement.removeClass(\"sp-disabled\");\n        }\n\n        function disable() {\n            hide();\n            disabled = true;\n            boundElement.attr(\"disabled\", true);\n            offsetElement.addClass(\"sp-disabled\");\n        }\n\n        initialize();\n\n        var spect = {\n            show: show,\n            hide: hide,\n            toggle: toggle,\n            reflow: reflow,\n            option: option,\n            enable: enable,\n            disable: disable,\n            set: function (c) {\n                set(c);\n                updateOriginalInput();\n            },\n            get: get,\n            destroy: destroy,\n            container: container\n        };\n\n        spect.id = spectrums.push(spect) - 1;\n\n        return spect;\n    }\n\n    /**\n    * checkOffset - get the offset below/above and left/right element depending on screen position\n    * Thanks https://github.com/jquery/jquery-ui/blob/master/ui/jquery.ui.datepicker.js\n    */\n    function getOffset(picker, input) {\n        var extraY = 0;\n        var dpWidth = picker.outerWidth();\n        var dpHeight = picker.outerHeight();\n        var inputHeight = input.outerHeight();\n        var doc = picker[0].ownerDocument;\n        var docElem = doc.documentElement;\n        var viewWidth = docElem.clientWidth + $(doc).scrollLeft();\n        var viewHeight = docElem.clientHeight + $(doc).scrollTop();\n        var offset = input.offset();\n        offset.top += inputHeight;\n\n        offset.left -=\n            Math.min(offset.left, (offset.left + dpWidth > viewWidth && viewWidth > dpWidth) ?\n            Math.abs(offset.left + dpWidth - viewWidth) : 0);\n\n        offset.top -=\n            Math.min(offset.top, ((offset.top + dpHeight > viewHeight && viewHeight > dpHeight) ?\n            Math.abs(dpHeight + inputHeight - extraY) : extraY));\n\n        return offset;\n    }\n\n    /**\n    * noop - do nothing\n    */\n    function noop() {\n\n    }\n\n    /**\n    * stopPropagation - makes the code only doing this a little easier to read in line\n    */\n    function stopPropagation(e) {\n        e.stopPropagation();\n    }\n\n    /**\n    * Create a function bound to a given object\n    * Thanks to underscore.js\n    */\n    function bind(func, obj) {\n        var slice = Array.prototype.slice;\n        var args = slice.call(arguments, 2);\n        return function () {\n            return func.apply(obj, args.concat(slice.call(arguments)));\n        };\n    }\n\n    /**\n    * Lightweight drag helper.  Handles containment within the element, so that\n    * when dragging, the x is within [0,element.width] and y is within [0,element.height]\n    */\n    function draggable(element, onmove, onstart, onstop) {\n        onmove = onmove || function () { };\n        onstart = onstart || function () { };\n        onstop = onstop || function () { };\n        var doc = element.ownerDocument || document;\n        var dragging = false;\n        var offset = {};\n        var maxHeight = 0;\n        var maxWidth = 0;\n        var hasTouch = ('ontouchstart' in window);\n\n        var duringDragEvents = {};\n        duringDragEvents[\"selectstart\"] = prevent;\n        duringDragEvents[\"dragstart\"] = prevent;\n        duringDragEvents[\"touchmove mousemove\"] = move;\n        duringDragEvents[\"touchend mouseup\"] = stop;\n\n        function prevent(e) {\n            if (e.stopPropagation) {\n                e.stopPropagation();\n            }\n            if (e.preventDefault) {\n                e.preventDefault();\n            }\n            e.returnValue = false;\n        }\n\n        function move(e) {\n            if (dragging) {\n                // Mouseup happened outside of window\n                if (IE && document.documentMode < 9 && !e.button) {\n                    return stop();\n                }\n\n                var touches = e.originalEvent.touches;\n                var pageX = touches ? touches[0].pageX : e.pageX;\n                var pageY = touches ? touches[0].pageY : e.pageY;\n\n                var dragX = Math.max(0, Math.min(pageX - offset.left, maxWidth));\n                var dragY = Math.max(0, Math.min(pageY - offset.top, maxHeight));\n\n                if (hasTouch) {\n                    // Stop scrolling in iOS\n                    prevent(e);\n                }\n\n                onmove.apply(element, [dragX, dragY, e]);\n            }\n        }\n\n        function start(e) {\n            var rightclick = (e.which) ? (e.which == 3) : (e.button == 2);\n            var touches = e.originalEvent.touches;\n\n            if (!rightclick && !dragging) {\n                if (onstart.apply(element, arguments) !== false) {\n                    dragging = true;\n                    maxHeight = $(element).height();\n                    maxWidth = $(element).width();\n                    offset = $(element).offset();\n\n                    $(doc).bind(duringDragEvents);\n                    $(doc.body).addClass(\"sp-dragging\");\n\n                    if (!hasTouch) {\n                        move(e);\n                    }\n\n                    prevent(e);\n                }\n            }\n        }\n\n        function stop() {\n            if (dragging) {\n                $(doc).unbind(duringDragEvents);\n                $(doc.body).removeClass(\"sp-dragging\");\n                onstop.apply(element, arguments);\n            }\n            dragging = false;\n        }\n\n        $(element).bind(\"touchstart mousedown\", start);\n    }\n\n    function throttle(func, wait, debounce) {\n        var timeout;\n        return function () {\n            var context = this, args = arguments;\n            var throttler = function () {\n                timeout = null;\n                func.apply(context, args);\n            };\n            if (debounce) clearTimeout(timeout);\n            if (debounce || !timeout) timeout = setTimeout(throttler, wait);\n        };\n    }\n\n    function log(){/* jshint -W021 */if(window.console){if(Function.prototype.bind)log=Function.prototype.bind.call(console.log,console);else log=function(){Function.prototype.apply.call(console.log,console,arguments);};log.apply(this,arguments);}}\n\n    /**\n    * Define a jQuery plugin\n    */\n    var dataID = \"spectrum.id\";\n    $.fn.spectrum = function (opts, extra) {\n\n        if (typeof opts == \"string\") {\n\n            var returnValue = this;\n            var args = Array.prototype.slice.call( arguments, 1 );\n\n            this.each(function () {\n                var spect = spectrums[$(this).data(dataID)];\n                if (spect) {\n                    var method = spect[opts];\n                    if (!method) {\n                        throw new Error( \"Spectrum: no such method: '\" + opts + \"'\" );\n                    }\n\n                    if (opts == \"get\") {\n                        returnValue = spect.get();\n                    }\n                    else if (opts == \"container\") {\n                        returnValue = spect.container;\n                    }\n                    else if (opts == \"option\") {\n                        returnValue = spect.option.apply(spect, args);\n                    }\n                    else if (opts == \"destroy\") {\n                        spect.destroy();\n                        $(this).removeData(dataID);\n                    }\n                    else {\n                        method.apply(spect, args);\n                    }\n                }\n            });\n\n            return returnValue;\n        }\n\n        // Initializing a new instance of spectrum\n        return this.spectrum(\"destroy\").each(function () {\n            var options = $.extend({}, opts, $(this).data());\n            var spect = spectrum(this, options);\n            $(this).data(dataID, spect.id);\n        });\n    };\n\n    $.fn.spectrum.load = true;\n    $.fn.spectrum.loadOpts = {};\n    $.fn.spectrum.draggable = draggable;\n    $.fn.spectrum.defaults = defaultOpts;\n\n    $.spectrum = { };\n    $.spectrum.localization = { };\n    $.spectrum.palettes = { };\n\n    $.fn.spectrum.processNativeColorInputs = function () {\n        if (!inputTypeColorSupport) {\n            $(\"input[type=color]\").spectrum({\n                preferredFormat: \"hex6\"\n            });\n        }\n    };\n\n    // TinyColor v0.9.17\n    // https://github.com/bgrins/TinyColor\n    // 2013-08-10, Brian Grinstead, MIT License\n\n    (function() {\n\n    var trimLeft = /^[\\s,#]+/,\n        trimRight = /\\s+$/,\n        tinyCounter = 0,\n        math = Math,\n        mathRound = math.round,\n        mathMin = math.min,\n        mathMax = math.max,\n        mathRandom = math.random;\n\n    function tinycolor (color, opts) {\n\n        color = (color) ? color : '';\n        opts = opts || { };\n\n        // If input is already a tinycolor, return itself\n        if (typeof color == \"object\" && color.hasOwnProperty(\"_tc_id\")) {\n           return color;\n        }\n\n        var rgb = inputToRGB(color);\n        var r = rgb.r,\n            g = rgb.g,\n            b = rgb.b,\n            a = rgb.a,\n            roundA = mathRound(100*a) / 100,\n            format = opts.format || rgb.format;\n\n        // Don't let the range of [0,255] come back in [0,1].\n        // Potentially lose a little bit of precision here, but will fix issues where\n        // .5 gets interpreted as half of the total, instead of half of 1\n        // If it was supposed to be 128, this was already taken care of by `inputToRgb`\n        if (r < 1) { r = mathRound(r); }\n        if (g < 1) { g = mathRound(g); }\n        if (b < 1) { b = mathRound(b); }\n\n        return {\n            ok: rgb.ok,\n            format: format,\n            _tc_id: tinyCounter++,\n            alpha: a,\n            getAlpha: function() {\n                return a;\n            },\n            setAlpha: function(value) {\n                a = boundAlpha(value);\n                roundA = mathRound(100*a) / 100;\n            },\n            toHsv: function() {\n                var hsv = rgbToHsv(r, g, b);\n                return { h: hsv.h * 360, s: hsv.s, v: hsv.v, a: a };\n            },\n            toHsvString: function() {\n                var hsv = rgbToHsv(r, g, b);\n                var h = mathRound(hsv.h * 360), s = mathRound(hsv.s * 100), v = mathRound(hsv.v * 100);\n                return (a == 1) ?\n                  \"hsv(\"  + h + \", \" + s + \"%, \" + v + \"%)\" :\n                  \"hsva(\" + h + \", \" + s + \"%, \" + v + \"%, \"+ roundA + \")\";\n            },\n            toHsl: function() {\n                var hsl = rgbToHsl(r, g, b);\n                return { h: hsl.h * 360, s: hsl.s, l: hsl.l, a: a };\n            },\n            toHslString: function() {\n                var hsl = rgbToHsl(r, g, b);\n                var h = mathRound(hsl.h * 360), s = mathRound(hsl.s * 100), l = mathRound(hsl.l * 100);\n                return (a == 1) ?\n                  \"hsl(\"  + h + \", \" + s + \"%, \" + l + \"%)\" :\n                  \"hsla(\" + h + \", \" + s + \"%, \" + l + \"%, \"+ roundA + \")\";\n            },\n            toHex: function(allow3Char) {\n                return rgbToHex(r, g, b, allow3Char);\n            },\n            toHexString: function(allow3Char) {\n                return '#' + this.toHex(allow3Char);\n            },\n            toHex8: function() {\n                return rgbaToHex(r, g, b, a);\n            },\n            toHex8String: function() {\n                return '#' + this.toHex8();\n            },\n            toRgb: function() {\n                return { r: mathRound(r), g: mathRound(g), b: mathRound(b), a: a };\n            },\n            toRgbString: function() {\n                return (a == 1) ?\n                  \"rgb(\"  + mathRound(r) + \", \" + mathRound(g) + \", \" + mathRound(b) + \")\" :\n                  \"rgba(\" + mathRound(r) + \", \" + mathRound(g) + \", \" + mathRound(b) + \", \" + roundA + \")\";\n            },\n            toPercentageRgb: function() {\n                return { r: mathRound(bound01(r, 255) * 100) + \"%\", g: mathRound(bound01(g, 255) * 100) + \"%\", b: mathRound(bound01(b, 255) * 100) + \"%\", a: a };\n            },\n            toPercentageRgbString: function() {\n                return (a == 1) ?\n                  \"rgb(\"  + mathRound(bound01(r, 255) * 100) + \"%, \" + mathRound(bound01(g, 255) * 100) + \"%, \" + mathRound(bound01(b, 255) * 100) + \"%)\" :\n                  \"rgba(\" + mathRound(bound01(r, 255) * 100) + \"%, \" + mathRound(bound01(g, 255) * 100) + \"%, \" + mathRound(bound01(b, 255) * 100) + \"%, \" + roundA + \")\";\n            },\n            toName: function() {\n                if (a === 0) {\n                    return \"transparent\";\n                }\n\n                return hexNames[rgbToHex(r, g, b, true)] || false;\n            },\n            toFilter: function(secondColor) {\n                var hex8String = '#' + rgbaToHex(r, g, b, a);\n                var secondHex8String = hex8String;\n                var gradientType = opts && opts.gradientType ? \"GradientType = 1, \" : \"\";\n\n                if (secondColor) {\n                    var s = tinycolor(secondColor);\n                    secondHex8String = s.toHex8String();\n                }\n\n                return \"progid:DXImageTransform.Microsoft.gradient(\"+gradientType+\"startColorstr=\"+hex8String+\",endColorstr=\"+secondHex8String+\")\";\n            },\n            toString: function(format) {\n                var formatSet = !!format;\n                format = format || this.format;\n\n                var formattedString = false;\n                var hasAlphaAndFormatNotSet = !formatSet && a < 1 && a > 0;\n                var formatWithAlpha = hasAlphaAndFormatNotSet && (format === \"hex\" || format === \"hex6\" || format === \"hex3\" || format === \"name\");\n\n                if (format === \"rgb\") {\n                    formattedString = this.toRgbString();\n                }\n                if (format === \"prgb\") {\n                    formattedString = this.toPercentageRgbString();\n                }\n                if (format === \"hex\" || format === \"hex6\") {\n                    formattedString = this.toHexString();\n                }\n                if (format === \"hex3\") {\n                    formattedString = this.toHexString(true);\n                }\n                if (format === \"hex8\") {\n                    formattedString = this.toHex8String();\n                }\n                if (format === \"name\") {\n                    formattedString = this.toName();\n                }\n                if (format === \"hsl\") {\n                    formattedString = this.toHslString();\n                }\n                if (format === \"hsv\") {\n                    formattedString = this.toHsvString();\n                }\n\n                if (formatWithAlpha) {\n                    return this.toRgbString();\n                }\n\n                return formattedString || this.toHexString();\n            }\n        };\n    }\n\n    // If input is an object, force 1 into \"1.0\" to handle ratios properly\n    // String input requires \"1.0\" as input, so 1 will be treated as 1\n    tinycolor.fromRatio = function(color, opts) {\n        if (typeof color == \"object\") {\n            var newColor = {};\n            for (var i in color) {\n                if (color.hasOwnProperty(i)) {\n                    if (i === \"a\") {\n                        newColor[i] = color[i];\n                    }\n                    else {\n                        newColor[i] = convertToPercentage(color[i]);\n                    }\n                }\n            }\n            color = newColor;\n        }\n\n        return tinycolor(color, opts);\n    };\n\n    // Given a string or object, convert that input to RGB\n    // Possible string inputs:\n    //\n    //     \"red\"\n    //     \"#f00\" or \"f00\"\n    //     \"#ff0000\" or \"ff0000\"\n    //     \"#ff000000\" or \"ff000000\"\n    //     \"rgb 255 0 0\" or \"rgb (255, 0, 0)\"\n    //     \"rgb 1.0 0 0\" or \"rgb (1, 0, 0)\"\n    //     \"rgba (255, 0, 0, 1)\" or \"rgba 255, 0, 0, 1\"\n    //     \"rgba (1.0, 0, 0, 1)\" or \"rgba 1.0, 0, 0, 1\"\n    //     \"hsl(0, 100%, 50%)\" or \"hsl 0 100% 50%\"\n    //     \"hsla(0, 100%, 50%, 1)\" or \"hsla 0 100% 50%, 1\"\n    //     \"hsv(0, 100%, 100%)\" or \"hsv 0 100% 100%\"\n    //\n    function inputToRGB(color) {\n\n        var rgb = { r: 0, g: 0, b: 0 };\n        var a = 1;\n        var ok = false;\n        var format = false;\n\n        if (typeof color == \"string\") {\n            color = stringInputToObject(color);\n        }\n\n        if (typeof color == \"object\") {\n            if (color.hasOwnProperty(\"r\") && color.hasOwnProperty(\"g\") && color.hasOwnProperty(\"b\")) {\n                rgb = rgbToRgb(color.r, color.g, color.b);\n                ok = true;\n                format = String(color.r).substr(-1) === \"%\" ? \"prgb\" : \"rgb\";\n            }\n            else if (color.hasOwnProperty(\"h\") && color.hasOwnProperty(\"s\") && color.hasOwnProperty(\"v\")) {\n                color.s = convertToPercentage(color.s);\n                color.v = convertToPercentage(color.v);\n                rgb = hsvToRgb(color.h, color.s, color.v);\n                ok = true;\n                format = \"hsv\";\n            }\n            else if (color.hasOwnProperty(\"h\") && color.hasOwnProperty(\"s\") && color.hasOwnProperty(\"l\")) {\n                color.s = convertToPercentage(color.s);\n                color.l = convertToPercentage(color.l);\n                rgb = hslToRgb(color.h, color.s, color.l);\n                ok = true;\n                format = \"hsl\";\n            }\n\n            if (color.hasOwnProperty(\"a\")) {\n                a = color.a;\n            }\n        }\n\n        a = boundAlpha(a);\n\n        return {\n            ok: ok,\n            format: color.format || format,\n            r: mathMin(255, mathMax(rgb.r, 0)),\n            g: mathMin(255, mathMax(rgb.g, 0)),\n            b: mathMin(255, mathMax(rgb.b, 0)),\n            a: a\n        };\n    }\n\n\n    // Conversion Functions\n    // --------------------\n\n    // `rgbToHsl`, `rgbToHsv`, `hslToRgb`, `hsvToRgb` modified from:\n    // <http://mjijackson.com/2008/02/rgb-to-hsl-and-rgb-to-hsv-color-model-conversion-algorithms-in-javascript>\n\n    // `rgbToRgb`\n    // Handle bounds / percentage checking to conform to CSS color spec\n    // <http://www.w3.org/TR/css3-color/>\n    // *Assumes:* r, g, b in [0, 255] or [0, 1]\n    // *Returns:* { r, g, b } in [0, 255]\n    function rgbToRgb(r, g, b){\n        return {\n            r: bound01(r, 255) * 255,\n            g: bound01(g, 255) * 255,\n            b: bound01(b, 255) * 255\n        };\n    }\n\n    // `rgbToHsl`\n    // Converts an RGB color value to HSL.\n    // *Assumes:* r, g, and b are contained in [0, 255] or [0, 1]\n    // *Returns:* { h, s, l } in [0,1]\n    function rgbToHsl(r, g, b) {\n\n        r = bound01(r, 255);\n        g = bound01(g, 255);\n        b = bound01(b, 255);\n\n        var max = mathMax(r, g, b), min = mathMin(r, g, b);\n        var h, s, l = (max + min) / 2;\n\n        if(max == min) {\n            h = s = 0; // achromatic\n        }\n        else {\n            var d = max - min;\n            s = l > 0.5 ? d / (2 - max - min) : d / (max + min);\n            switch(max) {\n                case r: h = (g - b) / d + (g < b ? 6 : 0); break;\n                case g: h = (b - r) / d + 2; break;\n                case b: h = (r - g) / d + 4; break;\n            }\n\n            h /= 6;\n        }\n\n        return { h: h, s: s, l: l };\n    }\n\n    // `hslToRgb`\n    // Converts an HSL color value to RGB.\n    // *Assumes:* h is contained in [0, 1] or [0, 360] and s and l are contained [0, 1] or [0, 100]\n    // *Returns:* { r, g, b } in the set [0, 255]\n    function hslToRgb(h, s, l) {\n        var r, g, b;\n\n        h = bound01(h, 360);\n        s = bound01(s, 100);\n        l = bound01(l, 100);\n\n        function hue2rgb(p, q, t) {\n            if(t < 0) t += 1;\n            if(t > 1) t -= 1;\n            if(t < 1/6) return p + (q - p) * 6 * t;\n            if(t < 1/2) return q;\n            if(t < 2/3) return p + (q - p) * (2/3 - t) * 6;\n            return p;\n        }\n\n        if(s === 0) {\n            r = g = b = l; // achromatic\n        }\n        else {\n            var q = l < 0.5 ? l * (1 + s) : l + s - l * s;\n            var p = 2 * l - q;\n            r = hue2rgb(p, q, h + 1/3);\n            g = hue2rgb(p, q, h);\n            b = hue2rgb(p, q, h - 1/3);\n        }\n\n        return { r: r * 255, g: g * 255, b: b * 255 };\n    }\n\n    // `rgbToHsv`\n    // Converts an RGB color value to HSV\n    // *Assumes:* r, g, and b are contained in the set [0, 255] or [0, 1]\n    // *Returns:* { h, s, v } in [0,1]\n    function rgbToHsv(r, g, b) {\n\n        r = bound01(r, 255);\n        g = bound01(g, 255);\n        b = bound01(b, 255);\n\n        var max = mathMax(r, g, b), min = mathMin(r, g, b);\n        var h, s, v = max;\n\n        var d = max - min;\n        s = max === 0 ? 0 : d / max;\n\n        if(max == min) {\n            h = 0; // achromatic\n        }\n        else {\n            switch(max) {\n                case r: h = (g - b) / d + (g < b ? 6 : 0); break;\n                case g: h = (b - r) / d + 2; break;\n                case b: h = (r - g) / d + 4; break;\n            }\n            h /= 6;\n        }\n        return { h: h, s: s, v: v };\n    }\n\n    // `hsvToRgb`\n    // Converts an HSV color value to RGB.\n    // *Assumes:* h is contained in [0, 1] or [0, 360] and s and v are contained in [0, 1] or [0, 100]\n    // *Returns:* { r, g, b } in the set [0, 255]\n     function hsvToRgb(h, s, v) {\n\n        h = bound01(h, 360) * 6;\n        s = bound01(s, 100);\n        v = bound01(v, 100);\n\n        var i = math.floor(h),\n            f = h - i,\n            p = v * (1 - s),\n            q = v * (1 - f * s),\n            t = v * (1 - (1 - f) * s),\n            mod = i % 6,\n            r = [v, q, p, p, t, v][mod],\n            g = [t, v, v, q, p, p][mod],\n            b = [p, p, t, v, v, q][mod];\n\n        return { r: r * 255, g: g * 255, b: b * 255 };\n    }\n\n    // `rgbToHex`\n    // Converts an RGB color to hex\n    // Assumes r, g, and b are contained in the set [0, 255]\n    // Returns a 3 or 6 character hex\n    function rgbToHex(r, g, b, allow3Char) {\n\n        var hex = [\n            pad2(mathRound(r).toString(16)),\n            pad2(mathRound(g).toString(16)),\n            pad2(mathRound(b).toString(16))\n        ];\n\n        // Return a 3 character hex if possible\n        if (allow3Char && hex[0].charAt(0) == hex[0].charAt(1) && hex[1].charAt(0) == hex[1].charAt(1) && hex[2].charAt(0) == hex[2].charAt(1)) {\n            return hex[0].charAt(0) + hex[1].charAt(0) + hex[2].charAt(0);\n        }\n\n        return hex.join(\"\");\n    }\n        // `rgbaToHex`\n        // Converts an RGBA color plus alpha transparency to hex\n        // Assumes r, g, b and a are contained in the set [0, 255]\n        // Returns an 8 character hex\n        function rgbaToHex(r, g, b, a) {\n\n            var hex = [\n                pad2(convertDecimalToHex(a)),\n                pad2(mathRound(r).toString(16)),\n                pad2(mathRound(g).toString(16)),\n                pad2(mathRound(b).toString(16))\n            ];\n\n            return hex.join(\"\");\n        }\n\n    // `equals`\n    // Can be called with any tinycolor input\n    tinycolor.equals = function (color1, color2) {\n        if (!color1 || !color2) { return false; }\n        return tinycolor(color1).toRgbString() == tinycolor(color2).toRgbString();\n    };\n    tinycolor.random = function() {\n        return tinycolor.fromRatio({\n            r: mathRandom(),\n            g: mathRandom(),\n            b: mathRandom()\n        });\n    };\n\n\n    // Modification Functions\n    // ----------------------\n    // Thanks to less.js for some of the basics here\n    // <https://github.com/cloudhead/less.js/blob/master/lib/less/functions.js>\n\n    tinycolor.desaturate = function (color, amount) {\n        amount = (amount === 0) ? 0 : (amount || 10);\n        var hsl = tinycolor(color).toHsl();\n        hsl.s -= amount / 100;\n        hsl.s = clamp01(hsl.s);\n        return tinycolor(hsl);\n    };\n    tinycolor.saturate = function (color, amount) {\n        amount = (amount === 0) ? 0 : (amount || 10);\n        var hsl = tinycolor(color).toHsl();\n        hsl.s += amount / 100;\n        hsl.s = clamp01(hsl.s);\n        return tinycolor(hsl);\n    };\n    tinycolor.greyscale = function(color) {\n        return tinycolor.desaturate(color, 100);\n    };\n    tinycolor.lighten = function(color, amount) {\n        amount = (amount === 0) ? 0 : (amount || 10);\n        var hsl = tinycolor(color).toHsl();\n        hsl.l += amount / 100;\n        hsl.l = clamp01(hsl.l);\n        return tinycolor(hsl);\n    };\n    tinycolor.darken = function (color, amount) {\n        amount = (amount === 0) ? 0 : (amount || 10);\n        var hsl = tinycolor(color).toHsl();\n        hsl.l -= amount / 100;\n        hsl.l = clamp01(hsl.l);\n        return tinycolor(hsl);\n    };\n    tinycolor.complement = function(color) {\n        var hsl = tinycolor(color).toHsl();\n        hsl.h = (hsl.h + 180) % 360;\n        return tinycolor(hsl);\n    };\n\n\n    // Combination Functions\n    // ---------------------\n    // Thanks to jQuery xColor for some of the ideas behind these\n    // <https://github.com/infusion/jQuery-xcolor/blob/master/jquery.xcolor.js>\n\n    tinycolor.triad = function(color) {\n        var hsl = tinycolor(color).toHsl();\n        var h = hsl.h;\n        return [\n            tinycolor(color),\n            tinycolor({ h: (h + 120) % 360, s: hsl.s, l: hsl.l }),\n            tinycolor({ h: (h + 240) % 360, s: hsl.s, l: hsl.l })\n        ];\n    };\n    tinycolor.tetrad = function(color) {\n        var hsl = tinycolor(color).toHsl();\n        var h = hsl.h;\n        return [\n            tinycolor(color),\n            tinycolor({ h: (h + 90) % 360, s: hsl.s, l: hsl.l }),\n            tinycolor({ h: (h + 180) % 360, s: hsl.s, l: hsl.l }),\n            tinycolor({ h: (h + 270) % 360, s: hsl.s, l: hsl.l })\n        ];\n    };\n    tinycolor.splitcomplement = function(color) {\n        var hsl = tinycolor(color).toHsl();\n        var h = hsl.h;\n        return [\n            tinycolor(color),\n            tinycolor({ h: (h + 72) % 360, s: hsl.s, l: hsl.l}),\n            tinycolor({ h: (h + 216) % 360, s: hsl.s, l: hsl.l})\n        ];\n    };\n    tinycolor.analogous = function(color, results, slices) {\n        results = results || 6;\n        slices = slices || 30;\n\n        var hsl = tinycolor(color).toHsl();\n        var part = 360 / slices;\n        var ret = [tinycolor(color)];\n\n        for (hsl.h = ((hsl.h - (part * results >> 1)) + 720) % 360; --results; ) {\n            hsl.h = (hsl.h + part) % 360;\n            ret.push(tinycolor(hsl));\n        }\n        return ret;\n    };\n    tinycolor.monochromatic = function(color, results) {\n        results = results || 6;\n        var hsv = tinycolor(color).toHsv();\n        var h = hsv.h, s = hsv.s, v = hsv.v;\n        var ret = [];\n        var modification = 1 / results;\n\n        while (results--) {\n            ret.push(tinycolor({ h: h, s: s, v: v}));\n            v = (v + modification) % 1;\n        }\n\n        return ret;\n    };\n\n\n    // Readability Functions\n    // ---------------------\n    // <http://www.w3.org/TR/AERT#color-contrast>\n\n    // `readability`\n    // Analyze the 2 colors and returns an object with the following properties:\n    //    `brightness`: difference in brightness between the two colors\n    //    `color`: difference in color/hue between the two colors\n    tinycolor.readability = function(color1, color2) {\n        var a = tinycolor(color1).toRgb();\n        var b = tinycolor(color2).toRgb();\n        var brightnessA = (a.r * 299 + a.g * 587 + a.b * 114) / 1000;\n        var brightnessB = (b.r * 299 + b.g * 587 + b.b * 114) / 1000;\n        var colorDiff = (\n            Math.max(a.r, b.r) - Math.min(a.r, b.r) +\n            Math.max(a.g, b.g) - Math.min(a.g, b.g) +\n            Math.max(a.b, b.b) - Math.min(a.b, b.b)\n        );\n\n        return {\n            brightness: Math.abs(brightnessA - brightnessB),\n            color: colorDiff\n        };\n    };\n\n    // `readable`\n    // http://www.w3.org/TR/AERT#color-contrast\n    // Ensure that foreground and background color combinations provide sufficient contrast.\n    // *Example*\n    //    tinycolor.readable(\"#000\", \"#111\") => false\n    tinycolor.readable = function(color1, color2) {\n        var readability = tinycolor.readability(color1, color2);\n        return readability.brightness > 125 && readability.color > 500;\n    };\n\n    // `mostReadable`\n    // Given a base color and a list of possible foreground or background\n    // colors for that base, returns the most readable color.\n    // *Example*\n    //    tinycolor.mostReadable(\"#123\", [\"#fff\", \"#000\"]) => \"#000\"\n    tinycolor.mostReadable = function(baseColor, colorList) {\n        var bestColor = null;\n        var bestScore = 0;\n        var bestIsReadable = false;\n        for (var i=0; i < colorList.length; i++) {\n\n            // We normalize both around the \"acceptable\" breaking point,\n            // but rank brightness constrast higher than hue.\n\n            var readability = tinycolor.readability(baseColor, colorList[i]);\n            var readable = readability.brightness > 125 && readability.color > 500;\n            var score = 3 * (readability.brightness / 125) + (readability.color / 500);\n\n            if ((readable && ! bestIsReadable) ||\n                (readable && bestIsReadable && score > bestScore) ||\n                ((! readable) && (! bestIsReadable) && score > bestScore)) {\n                bestIsReadable = readable;\n                bestScore = score;\n                bestColor = tinycolor(colorList[i]);\n            }\n        }\n        return bestColor;\n    };\n\n\n    // Big List of Colors\n    // ------------------\n    // <http://www.w3.org/TR/css3-color/#svg-color>\n    var names = tinycolor.names = {\n        aliceblue: \"f0f8ff\",\n        antiquewhite: \"faebd7\",\n        aqua: \"0ff\",\n        aquamarine: \"7fffd4\",\n        azure: \"f0ffff\",\n        beige: \"f5f5dc\",\n        bisque: \"ffe4c4\",\n        black: \"000\",\n        blanchedalmond: \"ffebcd\",\n        blue: \"00f\",\n        blueviolet: \"8a2be2\",\n        brown: \"a52a2a\",\n        burlywood: \"deb887\",\n        burntsienna: \"ea7e5d\",\n        cadetblue: \"5f9ea0\",\n        chartreuse: \"7fff00\",\n        chocolate: \"d2691e\",\n        coral: \"ff7f50\",\n        cornflowerblue: \"6495ed\",\n        cornsilk: \"fff8dc\",\n        crimson: \"dc143c\",\n        cyan: \"0ff\",\n        darkblue: \"00008b\",\n        darkcyan: \"008b8b\",\n        darkgoldenrod: \"b8860b\",\n        darkgray: \"a9a9a9\",\n        darkgreen: \"006400\",\n        darkgrey: \"a9a9a9\",\n        darkkhaki: \"bdb76b\",\n        darkmagenta: \"8b008b\",\n        darkolivegreen: \"556b2f\",\n        darkorange: \"ff8c00\",\n        darkorchid: \"9932cc\",\n        darkred: \"8b0000\",\n        darksalmon: \"e9967a\",\n        darkseagreen: \"8fbc8f\",\n        darkslateblue: \"483d8b\",\n        darkslategray: \"2f4f4f\",\n        darkslategrey: \"2f4f4f\",\n        darkturquoise: \"00ced1\",\n        darkviolet: \"9400d3\",\n        deeppink: \"ff1493\",\n        deepskyblue: \"00bfff\",\n        dimgray: \"696969\",\n        dimgrey: \"696969\",\n        dodgerblue: \"1e90ff\",\n        firebrick: \"b22222\",\n        floralwhite: \"fffaf0\",\n        forestgreen: \"228b22\",\n        fuchsia: \"f0f\",\n        gainsboro: \"dcdcdc\",\n        ghostwhite: \"f8f8ff\",\n        gold: \"ffd700\",\n        goldenrod: \"daa520\",\n        gray: \"808080\",\n        green: \"008000\",\n        greenyellow: \"adff2f\",\n        grey: \"808080\",\n        honeydew: \"f0fff0\",\n        hotpink: \"ff69b4\",\n        indianred: \"cd5c5c\",\n        indigo: \"4b0082\",\n        ivory: \"fffff0\",\n        khaki: \"f0e68c\",\n        lavender: \"e6e6fa\",\n        lavenderblush: \"fff0f5\",\n        lawngreen: \"7cfc00\",\n        lemonchiffon: \"fffacd\",\n        lightblue: \"add8e6\",\n        lightcoral: \"f08080\",\n        lightcyan: \"e0ffff\",\n        lightgoldenrodyellow: \"fafad2\",\n        lightgray: \"d3d3d3\",\n        lightgreen: \"90ee90\",\n        lightgrey: \"d3d3d3\",\n        lightpink: \"ffb6c1\",\n        lightsalmon: \"ffa07a\",\n        lightseagreen: \"20b2aa\",\n        lightskyblue: \"87cefa\",\n        lightslategray: \"789\",\n        lightslategrey: \"789\",\n        lightsteelblue: \"b0c4de\",\n        lightyellow: \"ffffe0\",\n        lime: \"0f0\",\n        limegreen: \"32cd32\",\n        linen: \"faf0e6\",\n        magenta: \"f0f\",\n        maroon: \"800000\",\n        mediumaquamarine: \"66cdaa\",\n        mediumblue: \"0000cd\",\n        mediumorchid: \"ba55d3\",\n        mediumpurple: \"9370db\",\n        mediumseagreen: \"3cb371\",\n        mediumslateblue: \"7b68ee\",\n        mediumspringgreen: \"00fa9a\",\n        mediumturquoise: \"48d1cc\",\n        mediumvioletred: \"c71585\",\n        midnightblue: \"191970\",\n        mintcream: \"f5fffa\",\n        mistyrose: \"ffe4e1\",\n        moccasin: \"ffe4b5\",\n        navajowhite: \"ffdead\",\n        navy: \"000080\",\n        oldlace: \"fdf5e6\",\n        olive: \"808000\",\n        olivedrab: \"6b8e23\",\n        orange: \"ffa500\",\n        orangered: \"ff4500\",\n        orchid: \"da70d6\",\n        palegoldenrod: \"eee8aa\",\n        palegreen: \"98fb98\",\n        paleturquoise: \"afeeee\",\n        palevioletred: \"db7093\",\n        papayawhip: \"ffefd5\",\n        peachpuff: \"ffdab9\",\n        peru: \"cd853f\",\n        pink: \"ffc0cb\",\n        plum: \"dda0dd\",\n        powderblue: \"b0e0e6\",\n        purple: \"800080\",\n        red: \"f00\",\n        rosybrown: \"bc8f8f\",\n        royalblue: \"4169e1\",\n        saddlebrown: \"8b4513\",\n        salmon: \"fa8072\",\n        sandybrown: \"f4a460\",\n        seagreen: \"2e8b57\",\n        seashell: \"fff5ee\",\n        sienna: \"a0522d\",\n        silver: \"c0c0c0\",\n        skyblue: \"87ceeb\",\n        slateblue: \"6a5acd\",\n        slategray: \"708090\",\n        slategrey: \"708090\",\n        snow: \"fffafa\",\n        springgreen: \"00ff7f\",\n        steelblue: \"4682b4\",\n        tan: \"d2b48c\",\n        teal: \"008080\",\n        thistle: \"d8bfd8\",\n        tomato: \"ff6347\",\n        turquoise: \"40e0d0\",\n        violet: \"ee82ee\",\n        wheat: \"f5deb3\",\n        white: \"fff\",\n        whitesmoke: \"f5f5f5\",\n        yellow: \"ff0\",\n        yellowgreen: \"9acd32\"\n    };\n\n    // Make it easy to access colors via `hexNames[hex]`\n    var hexNames = tinycolor.hexNames = flip(names);\n\n\n    // Utilities\n    // ---------\n\n    // `{ 'name1': 'val1' }` becomes `{ 'val1': 'name1' }`\n    function flip(o) {\n        var flipped = { };\n        for (var i in o) {\n            if (o.hasOwnProperty(i)) {\n                flipped[o[i]] = i;\n            }\n        }\n        return flipped;\n    }\n\n    // Return a valid alpha value [0,1] with all invalid values being set to 1\n    function boundAlpha(a) {\n        a = parseFloat(a);\n\n        if (isNaN(a) || a < 0 || a > 1) {\n            a = 1;\n        }\n\n        return a;\n    }\n\n    // Take input from [0, n] and return it as [0, 1]\n    function bound01(n, max) {\n        if (isOnePointZero(n)) { n = \"100%\"; }\n\n        var processPercent = isPercentage(n);\n        n = mathMin(max, mathMax(0, parseFloat(n)));\n\n        // Automatically convert percentage into number\n        if (processPercent) {\n            n = parseInt(n * max, 10) / 100;\n        }\n\n        // Handle floating point rounding errors\n        if ((math.abs(n - max) < 0.000001)) {\n            return 1;\n        }\n\n        // Convert into [0, 1] range if it isn't already\n        return (n % max) / parseFloat(max);\n    }\n\n    // Force a number between 0 and 1\n    function clamp01(val) {\n        return mathMin(1, mathMax(0, val));\n    }\n\n    // Parse a base-16 hex value into a base-10 integer\n    function parseIntFromHex(val) {\n        return parseInt(val, 16);\n    }\n\n    // Need to handle 1.0 as 100%, since once it is a number, there is no difference between it and 1\n    // <http://stackoverflow.com/questions/7422072/javascript-how-to-detect-number-as-a-decimal-including-1-0>\n    function isOnePointZero(n) {\n        return typeof n == \"string\" && n.indexOf('.') != -1 && parseFloat(n) === 1;\n    }\n\n    // Check to see if string passed in is a percentage\n    function isPercentage(n) {\n        return typeof n === \"string\" && n.indexOf('%') != -1;\n    }\n\n    // Force a hex value to have 2 characters\n    function pad2(c) {\n        return c.length == 1 ? '0' + c : '' + c;\n    }\n\n    // Replace a decimal with it's percentage value\n    function convertToPercentage(n) {\n        if (n <= 1) {\n            n = (n * 100) + \"%\";\n        }\n\n        return n;\n    }\n\n    // Converts a decimal to a hex value\n    function convertDecimalToHex(d) {\n        return Math.round(parseFloat(d) * 255).toString(16);\n    }\n    // Converts a hex value to a decimal\n    function convertHexToDecimal(h) {\n        return (parseIntFromHex(h) / 255);\n    }\n\n    var matchers = (function() {\n\n        // <http://www.w3.org/TR/css3-values/#integers>\n        var CSS_INTEGER = \"[-\\\\+]?\\\\d+%?\";\n\n        // <http://www.w3.org/TR/css3-values/#number-value>\n        var CSS_NUMBER = \"[-\\\\+]?\\\\d*\\\\.\\\\d+%?\";\n\n        // Allow positive/negative integer/number.  Don't capture the either/or, just the entire outcome.\n        var CSS_UNIT = \"(?:\" + CSS_NUMBER + \")|(?:\" + CSS_INTEGER + \")\";\n\n        // Actual matching.\n        // Parentheses and commas are optional, but not required.\n        // Whitespace can take the place of commas or opening paren\n        var PERMISSIVE_MATCH3 = \"[\\\\s|\\\\(]+(\" + CSS_UNIT + \")[,|\\\\s]+(\" + CSS_UNIT + \")[,|\\\\s]+(\" + CSS_UNIT + \")\\\\s*\\\\)?\";\n        var PERMISSIVE_MATCH4 = \"[\\\\s|\\\\(]+(\" + CSS_UNIT + \")[,|\\\\s]+(\" + CSS_UNIT + \")[,|\\\\s]+(\" + CSS_UNIT + \")[,|\\\\s]+(\" + CSS_UNIT + \")\\\\s*\\\\)?\";\n\n        return {\n            rgb: new RegExp(\"rgb\" + PERMISSIVE_MATCH3),\n            rgba: new RegExp(\"rgba\" + PERMISSIVE_MATCH4),\n            hsl: new RegExp(\"hsl\" + PERMISSIVE_MATCH3),\n            hsla: new RegExp(\"hsla\" + PERMISSIVE_MATCH4),\n            hsv: new RegExp(\"hsv\" + PERMISSIVE_MATCH3),\n            hex3: /^([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/,\n            hex6: /^([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/,\n            hex8: /^([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/\n        };\n    })();\n\n    // `stringInputToObject`\n    // Permissive string parsing.  Take in a number of formats, and output an object\n    // based on detected format.  Returns `{ r, g, b }` or `{ h, s, l }` or `{ h, s, v}`\n    function stringInputToObject(color) {\n\n        color = color.replace(trimLeft,'').replace(trimRight, '').toLowerCase();\n        var named = false;\n        if (names[color]) {\n            color = names[color];\n            named = true;\n        }\n        else if (color == 'transparent') {\n            return { r: 0, g: 0, b: 0, a: 0, format: \"name\" };\n        }\n\n        // Try to match string input using regular expressions.\n        // Keep most of the number bounding out of this function - don't worry about [0,1] or [0,100] or [0,360]\n        // Just return an object and let the conversion functions handle that.\n        // This way the result will be the same whether the tinycolor is initialized with string or object.\n        var match;\n        if ((match = matchers.rgb.exec(color))) {\n            return { r: match[1], g: match[2], b: match[3] };\n        }\n        if ((match = matchers.rgba.exec(color))) {\n            return { r: match[1], g: match[2], b: match[3], a: match[4] };\n        }\n        if ((match = matchers.hsl.exec(color))) {\n            return { h: match[1], s: match[2], l: match[3] };\n        }\n        if ((match = matchers.hsla.exec(color))) {\n            return { h: match[1], s: match[2], l: match[3], a: match[4] };\n        }\n        if ((match = matchers.hsv.exec(color))) {\n            return { h: match[1], s: match[2], v: match[3] };\n        }\n        if ((match = matchers.hex8.exec(color))) {\n            return {\n                a: convertHexToDecimal(match[1]),\n                r: parseIntFromHex(match[2]),\n                g: parseIntFromHex(match[3]),\n                b: parseIntFromHex(match[4]),\n                format: named ? \"name\" : \"hex8\"\n            };\n        }\n        if ((match = matchers.hex6.exec(color))) {\n            return {\n                r: parseIntFromHex(match[1]),\n                g: parseIntFromHex(match[2]),\n                b: parseIntFromHex(match[3]),\n                format: named ? \"name\" : \"hex\"\n            };\n        }\n        if ((match = matchers.hex3.exec(color))) {\n            return {\n                r: parseIntFromHex(match[1] + '' + match[1]),\n                g: parseIntFromHex(match[2] + '' + match[2]),\n                b: parseIntFromHex(match[3] + '' + match[3]),\n                format: named ? \"name\" : \"hex\"\n            };\n        }\n\n        return false;\n    }\n\n    // Expose tinycolor to window, does not need to run in non-browser context.\n    window.tinycolor = tinycolor;\n\n    })();\n\n\n    $(function () {\n        if ($.fn.spectrum.load) {\n            $.fn.spectrum.processNativeColorInputs();\n        }\n    });\n\n})(window, jQuery);\n"
  },
  {
    "path": "flowable-ui-web/idm/libs/angular-strap_2.1.6/angular-strap.js",
    "content": "/**\n * angular-strap\n * @version v2.1.6 - 2015-01-11\n * @link http://mgcrea.github.io/angular-strap\n * @author Olivier Louvignes (olivier@mg-crea.com)\n * @license MIT License, http://www.opensource.org/licenses/MIT\n */\n(function(window, document, undefined) {\n'use strict';\n// Source: module.js\nangular.module('mgcrea.ngStrap', [\n  'mgcrea.ngStrap.modal',\n  'mgcrea.ngStrap.aside',\n  'mgcrea.ngStrap.alert',\n  'mgcrea.ngStrap.button',\n  'mgcrea.ngStrap.select',\n  'mgcrea.ngStrap.datepicker',\n  'mgcrea.ngStrap.timepicker',\n  'mgcrea.ngStrap.navbar',\n  'mgcrea.ngStrap.tooltip',\n  'mgcrea.ngStrap.popover',\n  'mgcrea.ngStrap.dropdown',\n  'mgcrea.ngStrap.typeahead',\n  'mgcrea.ngStrap.scrollspy',\n  'mgcrea.ngStrap.affix',\n  'mgcrea.ngStrap.tab',\n  'mgcrea.ngStrap.collapse'\n]);\n\n// Source: affix.js\nangular.module('mgcrea.ngStrap.affix', ['mgcrea.ngStrap.helpers.dimensions', 'mgcrea.ngStrap.helpers.debounce'])\n\n  .provider('$affix', function() {\n\n    var defaults = this.defaults = {\n      offsetTop: 'auto'\n    };\n\n    this.$get = [\"$window\", \"debounce\", \"dimensions\", function($window, debounce, dimensions) {\n\n      var bodyEl = angular.element($window.document.body);\n      var windowEl = angular.element($window);\n\n      function AffixFactory(element, config) {\n\n        var $affix = {};\n\n        // Common vars\n        var options = angular.extend({}, defaults, config);\n        var targetEl = options.target;\n\n        // Initial private vars\n        var reset = 'affix affix-top affix-bottom',\n            setWidth = false,\n            initialAffixTop = 0,\n            initialOffsetTop = 0,\n            offsetTop = 0,\n            offsetBottom = 0,\n            affixed = null,\n            unpin = null;\n\n        var parent = element.parent();\n        // Options: custom parent\n        if (options.offsetParent) {\n          if (options.offsetParent.match(/^\\d+$/)) {\n            for (var i = 0; i < (options.offsetParent * 1) - 1; i++) {\n              parent = parent.parent();\n            }\n          }\n          else {\n            parent = angular.element(options.offsetParent);\n          }\n        }\n\n        $affix.init = function() {\n\n          this.$parseOffsets();\n          initialOffsetTop = dimensions.offset(element[0]).top + initialAffixTop;\n          setWidth = !element[0].style.width;\n\n          // Bind events\n          targetEl.on('scroll', this.checkPosition);\n          targetEl.on('click', this.checkPositionWithEventLoop);\n          windowEl.on('resize', this.$debouncedOnResize);\n\n          // Both of these checkPosition() calls are necessary for the case where\n          // the user hits refresh after scrolling to the bottom of the page.\n          this.checkPosition();\n          this.checkPositionWithEventLoop();\n\n        };\n\n        $affix.destroy = function() {\n\n          // Unbind events\n          targetEl.off('scroll', this.checkPosition);\n          targetEl.off('click', this.checkPositionWithEventLoop);\n          windowEl.off('resize', this.$debouncedOnResize);\n\n        };\n\n        $affix.checkPositionWithEventLoop = function() {\n\n          // IE 9 throws an error if we use 'this' instead of '$affix'\n          // in this setTimeout call\n          setTimeout($affix.checkPosition, 1);\n\n        };\n\n        $affix.checkPosition = function() {\n          // if (!this.$element.is(':visible')) return\n\n          var scrollTop = getScrollTop();\n          var position = dimensions.offset(element[0]);\n          var elementHeight = dimensions.height(element[0]);\n\n          // Get required affix class according to position\n          var affix = getRequiredAffixClass(unpin, position, elementHeight);\n\n          // Did affix status changed this last check?\n          if(affixed === affix) return;\n          affixed = affix;\n\n          // Add proper affix class\n          element.removeClass(reset).addClass('affix' + ((affix !== 'middle') ? '-' + affix : ''));\n\n          if(affix === 'top') {\n            unpin = null;\n            element.css('position', (options.offsetParent) ? '' : 'relative');\n            if(setWidth) {\n              element.css('width', '');\n            }\n            element.css('top', '');\n          } else if(affix === 'bottom') {\n            if (options.offsetUnpin) {\n              unpin = -(options.offsetUnpin * 1);\n            }\n            else {\n              // Calculate unpin threshold when affixed to bottom.\n              // Hopefully the browser scrolls pixel by pixel.\n              unpin = position.top - scrollTop;\n            }\n            if(setWidth) {\n              element.css('width', '');\n            }\n            element.css('position', (options.offsetParent) ? '' : 'relative');\n            element.css('top', (options.offsetParent) ? '' : ((bodyEl[0].offsetHeight - offsetBottom - elementHeight - initialOffsetTop) + 'px'));\n          } else { // affix === 'middle'\n            unpin = null;\n            if(setWidth) {\n              element.css('width', element[0].offsetWidth + 'px');\n            }\n            element.css('position', 'fixed');\n            element.css('top', initialAffixTop + 'px');\n          }\n\n        };\n\n        $affix.$onResize = function() {\n          $affix.$parseOffsets();\n          $affix.checkPosition();\n        };\n        $affix.$debouncedOnResize = debounce($affix.$onResize, 50);\n\n        $affix.$parseOffsets = function() {\n          var initialPosition = element.css('position');\n          // Reset position to calculate correct offsetTop\n          element.css('position', (options.offsetParent) ? '' : 'relative');\n\n          if(options.offsetTop) {\n            if(options.offsetTop === 'auto') {\n              options.offsetTop = '+0';\n            }\n            if(options.offsetTop.match(/^[-+]\\d+$/)) {\n              initialAffixTop = - options.offsetTop * 1;\n              if(options.offsetParent) {\n                offsetTop = dimensions.offset(parent[0]).top + (options.offsetTop * 1);\n              }\n              else {\n                offsetTop = dimensions.offset(element[0]).top - dimensions.css(element[0], 'marginTop', true) + (options.offsetTop * 1);\n              }\n            }\n            else {\n              offsetTop = options.offsetTop * 1;\n            }\n          }\n\n          if(options.offsetBottom) {\n            if(options.offsetParent && options.offsetBottom.match(/^[-+]\\d+$/)) {\n              // add 1 pixel due to rounding problems...\n              offsetBottom = getScrollHeight() - (dimensions.offset(parent[0]).top + dimensions.height(parent[0])) + (options.offsetBottom * 1) + 1;\n            }\n            else {\n              offsetBottom = options.offsetBottom * 1;\n            }\n          }\n\n          // Bring back the element's position after calculations\n          element.css('position', initialPosition);\n        };\n\n        // Private methods\n\n        function getRequiredAffixClass(unpin, position, elementHeight) {\n\n          var scrollTop = getScrollTop();\n          var scrollHeight = getScrollHeight();\n\n          if(scrollTop <= offsetTop) {\n            return 'top';\n          } else if(unpin !== null && (scrollTop + unpin <= position.top)) {\n            return 'middle';\n          } else if(offsetBottom !== null && (position.top + elementHeight + initialAffixTop >= scrollHeight - offsetBottom)) {\n            return 'bottom';\n          } else {\n            return 'middle';\n          }\n\n        }\n\n        function getScrollTop() {\n          return targetEl[0] === $window ? $window.pageYOffset : targetEl[0].scrollTop;\n        }\n\n        function getScrollHeight() {\n          return targetEl[0] === $window ? $window.document.body.scrollHeight : targetEl[0].scrollHeight;\n        }\n\n        $affix.init();\n        return $affix;\n\n      }\n\n      return AffixFactory;\n\n    }];\n\n  })\n\n  .directive('bsAffix', [\"$affix\", \"$window\", function($affix, $window) {\n\n    return {\n      restrict: 'EAC',\n      require: '^?bsAffixTarget',\n      link: function postLink(scope, element, attr, affixTarget) {\n\n        var options = {scope: scope, offsetTop: 'auto', target: affixTarget ? affixTarget.$element : angular.element($window)};\n        angular.forEach(['offsetTop', 'offsetBottom', 'offsetParent', 'offsetUnpin'], function(key) {\n          if(angular.isDefined(attr[key])) options[key] = attr[key];\n        });\n\n        var affix = $affix(element, options);\n        scope.$on('$destroy', function() {\n          affix && affix.destroy();\n          options = null;\n          affix = null;\n        });\n\n      }\n    };\n\n  }])\n\n  .directive('bsAffixTarget', function() {\n    return {\n      controller: [\"$element\", function($element) {\n        this.$element = $element;\n      }]\n    };\n  });\n\n// Source: alert.js\n// @BUG: following snippet won't compile correctly\n// @TODO: submit issue to core\n// '<span ng-if=\"title\"><strong ng-bind=\"title\"></strong>&nbsp;</span><span ng-bind-html=\"content\"></span>' +\n\nangular.module('mgcrea.ngStrap.alert', ['mgcrea.ngStrap.modal'])\n\n  .provider('$alert', function() {\n\n    var defaults = this.defaults = {\n      animation: 'am-fade',\n      prefixClass: 'alert',\n      prefixEvent: 'alert',\n      placement: null,\n      template: 'alert/alert.tpl.html',\n      container: false,\n      element: null,\n      backdrop: false,\n      keyboard: true,\n      show: true,\n      // Specific options\n      duration: false,\n      type: false,\n      dismissable: true\n    };\n\n    this.$get = [\"$modal\", \"$timeout\", function($modal, $timeout) {\n\n      function AlertFactory(config) {\n\n        var $alert = {};\n\n        // Common vars\n        var options = angular.extend({}, defaults, config);\n\n        $alert = $modal(options);\n\n        // Support scope as string options [/*title, content, */ type, dismissable]\n        $alert.$scope.dismissable = !!options.dismissable;\n        if(options.type) {\n          $alert.$scope.type = options.type;\n        }\n\n        // Support auto-close duration\n        var show = $alert.show;\n        if(options.duration) {\n          $alert.show = function() {\n            show();\n            $timeout(function() {\n              $alert.hide();\n            }, options.duration * 1000);\n          };\n        }\n\n        return $alert;\n\n      }\n\n      return AlertFactory;\n\n    }];\n\n  })\n\n  .directive('bsAlert', [\"$window\", \"$sce\", \"$alert\", function($window, $sce, $alert) {\n\n    var requestAnimationFrame = $window.requestAnimationFrame || $window.setTimeout;\n\n    return {\n      restrict: 'EAC',\n      scope: true,\n      link: function postLink(scope, element, attr, transclusion) {\n\n        // Directive options\n        var options = {scope: scope, element: element, show: false};\n        angular.forEach(['template', 'placement', 'keyboard', 'html', 'container', 'animation', 'duration', 'dismissable'], function(key) {\n          if(angular.isDefined(attr[key])) options[key] = attr[key];\n        });\n\n        // Support scope as data-attrs\n        angular.forEach(['title', 'content', 'type'], function(key) {\n          attr[key] && attr.$observe(key, function(newValue, oldValue) {\n            scope[key] = $sce.trustAsHtml(newValue);\n          });\n        });\n\n        // Support scope as an object\n        attr.bsAlert && scope.$watch(attr.bsAlert, function(newValue, oldValue) {\n          if(angular.isObject(newValue)) {\n            angular.extend(scope, newValue);\n          } else {\n            scope.content = newValue;\n          }\n        }, true);\n\n        // Initialize alert\n        var alert = $alert(options);\n\n        // Trigger\n        element.on(attr.trigger || 'click', alert.toggle);\n\n        // Garbage collection\n        scope.$on('$destroy', function() {\n          if (alert) alert.destroy();\n          options = null;\n          alert = null;\n        });\n\n      }\n    };\n\n  }]);\n\n// Source: aside.js\nangular.module('mgcrea.ngStrap.aside', ['mgcrea.ngStrap.modal'])\n\n  .provider('$aside', function() {\n\n    var defaults = this.defaults = {\n      animation: 'am-fade-and-slide-right',\n      prefixClass: 'aside',\n      prefixEvent: 'aside',\n      placement: 'right',\n      template: 'aside/aside.tpl.html',\n      contentTemplate: false,\n      container: false,\n      element: null,\n      backdrop: true,\n      keyboard: true,\n      html: false,\n      show: true\n    };\n\n    this.$get = [\"$modal\", function($modal) {\n\n      function AsideFactory(config) {\n\n        var $aside = {};\n\n        // Common vars\n        var options = angular.extend({}, defaults, config);\n\n        $aside = $modal(options);\n\n        return $aside;\n\n      }\n\n      return AsideFactory;\n\n    }];\n\n  })\n\n  .directive('bsAside', [\"$window\", \"$sce\", \"$aside\", function($window, $sce, $aside) {\n\n    var requestAnimationFrame = $window.requestAnimationFrame || $window.setTimeout;\n\n    return {\n      restrict: 'EAC',\n      scope: true,\n      link: function postLink(scope, element, attr, transclusion) {\n        // Directive options\n        var options = {scope: scope, element: element, show: false};\n        angular.forEach(['template', 'contentTemplate', 'placement', 'backdrop', 'keyboard', 'html', 'container', 'animation'], function(key) {\n          if(angular.isDefined(attr[key])) options[key] = attr[key];\n        });\n\n        // Support scope as data-attrs\n        angular.forEach(['title', 'content'], function(key) {\n          attr[key] && attr.$observe(key, function(newValue, oldValue) {\n            scope[key] = $sce.trustAsHtml(newValue);\n          });\n        });\n\n        // Support scope as an object\n        attr.bsAside && scope.$watch(attr.bsAside, function(newValue, oldValue) {\n          if(angular.isObject(newValue)) {\n            angular.extend(scope, newValue);\n          } else {\n            scope.content = newValue;\n          }\n        }, true);\n\n        // Initialize aside\n        var aside = $aside(options);\n\n        // Trigger\n        element.on(attr.trigger || 'click', aside.toggle);\n\n        // Garbage collection\n        scope.$on('$destroy', function() {\n          if (aside) aside.destroy();\n          options = null;\n          aside = null;\n        });\n\n      }\n    };\n\n  }]);\n\n// Source: button.js\nangular.module('mgcrea.ngStrap.button', [])\n\n  .provider('$button', function() {\n\n    var defaults = this.defaults = {\n      activeClass:'active',\n      toggleEvent:'click'\n    };\n\n    this.$get = function() {\n      return {defaults: defaults};\n    };\n\n  })\n\n  .directive('bsCheckboxGroup', function() {\n\n    return {\n      restrict: 'A',\n      require: 'ngModel',\n      compile: function postLink(element, attr) {\n        element.attr('data-toggle', 'buttons');\n        element.removeAttr('ng-model');\n        var children = element[0].querySelectorAll('input[type=\"checkbox\"]');\n        angular.forEach(children, function(child) {\n          var childEl = angular.element(child);\n          childEl.attr('bs-checkbox', '');\n          childEl.attr('ng-model', attr.ngModel + '.' + childEl.attr('value'));\n        });\n      }\n\n    };\n\n  })\n\n  .directive('bsCheckbox', [\"$button\", \"$$rAF\", function($button, $$rAF) {\n\n    var defaults = $button.defaults;\n    var constantValueRegExp = /^(true|false|\\d+)$/;\n\n    return {\n      restrict: 'A',\n      require: 'ngModel',\n      link: function postLink(scope, element, attr, controller) {\n\n        var options = defaults;\n\n        // Support label > input[type=\"checkbox\"]\n        var isInput = element[0].nodeName === 'INPUT';\n        var activeElement = isInput ? element.parent() : element;\n\n        var trueValue = angular.isDefined(attr.trueValue) ? attr.trueValue : true;\n        if(constantValueRegExp.test(attr.trueValue)) {\n          trueValue = scope.$eval(attr.trueValue);\n        }\n        var falseValue = angular.isDefined(attr.falseValue) ? attr.falseValue : false;\n        if(constantValueRegExp.test(attr.falseValue)) {\n          falseValue = scope.$eval(attr.falseValue);\n        }\n\n        // Parse exotic values\n        var hasExoticValues = typeof trueValue !== 'boolean' || typeof falseValue !== 'boolean';\n        if(hasExoticValues) {\n          controller.$parsers.push(function(viewValue) {\n            // console.warn('$parser', element.attr('ng-model'), 'viewValue', viewValue);\n            return viewValue ? trueValue : falseValue;\n          });\n          // modelValue -> $formatters -> viewValue\n          controller.$formatters.push(function(modelValue) {\n             // console.warn('$formatter(\"%s\"): modelValue=%o (%o)', element.attr('ng-model'), modelValue, typeof modelValue);\n             return angular.equals(modelValue, trueValue);\n          });\n          // Fix rendering for exotic values\n          scope.$watch(attr.ngModel, function(newValue, oldValue) {\n            controller.$render();\n          });\n        }\n\n        // model -> view\n        controller.$render = function () {\n          // console.warn('$render', element.attr('ng-model'), 'controller.$modelValue', typeof controller.$modelValue, controller.$modelValue, 'controller.$viewValue', typeof controller.$viewValue, controller.$viewValue);\n          var isActive = angular.equals(controller.$modelValue, trueValue);\n          $$rAF(function() {\n            if(isInput) element[0].checked = isActive;\n            activeElement.toggleClass(options.activeClass, isActive);\n          });\n        };\n\n        // view -> model\n        element.bind(options.toggleEvent, function() {\n          scope.$apply(function () {\n            // console.warn('!click', element.attr('ng-model'), 'controller.$viewValue', typeof controller.$viewValue, controller.$viewValue, 'controller.$modelValue', typeof controller.$modelValue, controller.$modelValue);\n            if(!isInput) {\n              controller.$setViewValue(!activeElement.hasClass('active'));\n            }\n            if(!hasExoticValues) {\n              controller.$render();\n            }\n          });\n        });\n\n      }\n\n    };\n\n  }])\n\n  .directive('bsRadioGroup', function() {\n\n    return {\n      restrict: 'A',\n      require: 'ngModel',\n      compile: function postLink(element, attr) {\n        element.attr('data-toggle', 'buttons');\n        element.removeAttr('ng-model');\n        var children = element[0].querySelectorAll('input[type=\"radio\"]');\n        angular.forEach(children, function(child) {\n          angular.element(child).attr('bs-radio', '');\n          angular.element(child).attr('ng-model', attr.ngModel);\n        });\n      }\n\n    };\n\n  })\n\n  .directive('bsRadio', [\"$button\", \"$$rAF\", function($button, $$rAF) {\n\n    var defaults = $button.defaults;\n    var constantValueRegExp = /^(true|false|\\d+)$/;\n\n    return {\n      restrict: 'A',\n      require: 'ngModel',\n      link: function postLink(scope, element, attr, controller) {\n\n        var options = defaults;\n\n        // Support `label > input[type=\"radio\"]` markup\n        var isInput = element[0].nodeName === 'INPUT';\n        var activeElement = isInput ? element.parent() : element;\n\n        var value = constantValueRegExp.test(attr.value) ? scope.$eval(attr.value) : attr.value;\n\n        // model -> view\n        controller.$render = function () {\n          // console.warn('$render', element.attr('value'), 'controller.$modelValue', typeof controller.$modelValue, controller.$modelValue, 'controller.$viewValue', typeof controller.$viewValue, controller.$viewValue);\n          var isActive = angular.equals(controller.$modelValue, value);\n          $$rAF(function() {\n            if(isInput) element[0].checked = isActive;\n            activeElement.toggleClass(options.activeClass, isActive);\n          });\n        };\n\n        // view -> model\n        element.bind(options.toggleEvent, function() {\n          scope.$apply(function () {\n            // console.warn('!click', element.attr('value'), 'controller.$viewValue', typeof controller.$viewValue, controller.$viewValue, 'controller.$modelValue', typeof controller.$modelValue, controller.$modelValue);\n            controller.$setViewValue(value);\n            controller.$render();\n          });\n        });\n\n      }\n\n    };\n\n  }]);\n\n// Source: collapse.js\nangular.module('mgcrea.ngStrap.collapse', [])\n\n  .provider('$collapse', function() {\n\n    var defaults = this.defaults = {\n      animation: 'am-collapse',\n      disallowToggle: false,\n      activeClass: 'in',\n      startCollapsed: false,\n      allowMultiple: false\n    };\n\n    var controller = this.controller = function($scope, $element, $attrs) {\n      var self = this;\n\n      // Attributes options\n      self.$options = angular.copy(defaults);\n      angular.forEach(['animation', 'disallowToggle', 'activeClass', 'startCollapsed', 'allowMultiple'], function (key) {\n        if(angular.isDefined($attrs[key])) self.$options[key] = $attrs[key];\n      });\n\n      self.$toggles = [];\n      self.$targets = [];\n\n      self.$viewChangeListeners = [];\n\n      self.$registerToggle = function(element) {\n        self.$toggles.push(element);\n      };\n      self.$registerTarget = function(element) {\n        self.$targets.push(element);\n      };\n\n      self.$unregisterToggle = function(element) {\n        var index = self.$toggles.indexOf(element);\n        // remove toggle from $toggles array\n        self.$toggles.splice(index, 1);\n      };\n      self.$unregisterTarget = function(element) {\n        var index = self.$targets.indexOf(element);\n\n        // remove element from $targets array\n        self.$targets.splice(index, 1);\n\n        if (self.$options.allowMultiple) {\n          // remove target index from $active array values\n          deactivateItem(element);\n        }\n\n        // fix active item indexes\n        fixActiveItemIndexes(index);\n\n        self.$viewChangeListeners.forEach(function(fn) {\n          fn();\n        });\n      };\n\n      // use array to store all the currently open panels\n      self.$targets.$active = !self.$options.startCollapsed ? [0] : [];\n      self.$setActive = $scope.$setActive = function(value) {\n        if(angular.isArray(value)) {\n          self.$targets.$active = angular.copy(value);\n        }\n        else if(!self.$options.disallowToggle) {\n          // toogle element active status\n          isActive(value) ? deactivateItem(value) : activateItem(value);\n        } else {\n          activateItem(value);\n        }\n\n        self.$viewChangeListeners.forEach(function(fn) {\n          fn();\n        });\n      };\n\n      self.$activeIndexes = function() {\n        return self.$options.allowMultiple ? self.$targets.$active :\n          self.$targets.$active.length === 1 ? self.$targets.$active[0] : -1;\n      };\n\n      function fixActiveItemIndexes(index) {\n        // item with index was removed, so we\n        // need to adjust other items index values\n        var activeIndexes = self.$targets.$active;\n        for(var i = 0; i < activeIndexes.length; i++) {\n          if (index < activeIndexes[i]) {\n            activeIndexes[i] = activeIndexes[i] - 1;\n          }\n\n          // the last item is active, so we need to\n          // adjust its index\n          if (activeIndexes[i] === self.$targets.length) {\n            activeIndexes[i] = self.$targets.length - 1;\n          }\n        }\n      }\n\n      function isActive(value) {\n        var activeItems = self.$targets.$active;\n        return activeItems.indexOf(value) === -1 ? false : true;\n      }\n\n      function deactivateItem(value) {\n        var index = self.$targets.$active.indexOf(value);\n        if (index !== -1) {\n          self.$targets.$active.splice(index, 1);\n        }\n      }\n\n      function activateItem(value) {\n        if (!self.$options.allowMultiple) {\n          // remove current selected item\n          self.$targets.$active.splice(0, 1);\n        }\n\n        if (self.$targets.$active.indexOf(value) === -1) {\n          self.$targets.$active.push(value);\n        }\n      }\n\n    };\n\n    this.$get = function() {\n      var $collapse = {};\n      $collapse.defaults = defaults;\n      $collapse.controller = controller;\n      return $collapse;\n    };\n\n  })\n\n  .directive('bsCollapse', [\"$window\", \"$animate\", \"$collapse\", function($window, $animate, $collapse) {\n\n    var defaults = $collapse.defaults;\n\n    return {\n      require: ['?ngModel', 'bsCollapse'],\n      controller: ['$scope', '$element', '$attrs', $collapse.controller],\n      link: function postLink(scope, element, attrs, controllers) {\n\n        var ngModelCtrl = controllers[0];\n        var bsCollapseCtrl = controllers[1];\n\n        if(ngModelCtrl) {\n\n          // Update the modelValue following\n          bsCollapseCtrl.$viewChangeListeners.push(function() {\n            ngModelCtrl.$setViewValue(bsCollapseCtrl.$activeIndexes());\n          });\n\n          // modelValue -> $formatters -> viewValue\n          ngModelCtrl.$formatters.push(function(modelValue) {\n            // console.warn('$formatter(\"%s\"): modelValue=%o (%o)', element.attr('ng-model'), modelValue, typeof modelValue);\n            if (angular.isArray(modelValue)) {\n              // model value is an array, so just replace\n              // the active items directly\n              bsCollapseCtrl.$setActive(modelValue);\n            }\n            else {\n              var activeIndexes = bsCollapseCtrl.$activeIndexes();\n\n              if (angular.isArray(activeIndexes)) {\n                // we have an array of selected indexes\n                if (activeIndexes.indexOf(modelValue * 1) === -1) {\n                  // item with modelValue index is not active\n                  bsCollapseCtrl.$setActive(modelValue * 1);\n                }\n              }\n              else if (activeIndexes !== modelValue * 1) {\n                bsCollapseCtrl.$setActive(modelValue * 1);\n              }\n            }\n            return modelValue;\n          });\n\n        }\n\n      }\n    };\n\n  }])\n\n  .directive('bsCollapseToggle', function() {\n\n    return {\n      require: ['^?ngModel', '^bsCollapse'],\n      link: function postLink(scope, element, attrs, controllers) {\n\n        var ngModelCtrl = controllers[0];\n        var bsCollapseCtrl = controllers[1];\n\n        // Add base attr\n        element.attr('data-toggle', 'collapse');\n\n        // Push pane to parent bsCollapse controller\n        bsCollapseCtrl.$registerToggle(element);\n\n        // remove toggle from collapse controller when toggle is destroyed\n        scope.$on('$destroy', function() {\n          bsCollapseCtrl.$unregisterToggle(element);\n        });\n\n        element.on('click', function() {\n          var index = attrs.bsCollapseToggle || bsCollapseCtrl.$toggles.indexOf(element);\n          bsCollapseCtrl.$setActive(index * 1);\n          scope.$apply();\n        });\n\n      }\n    };\n\n  })\n\n  .directive('bsCollapseTarget', [\"$animate\", function($animate) {\n\n    return {\n      require: ['^?ngModel', '^bsCollapse'],\n      // scope: true,\n      link: function postLink(scope, element, attrs, controllers) {\n\n        var ngModelCtrl = controllers[0];\n        var bsCollapseCtrl = controllers[1];\n\n        // Add base class\n        element.addClass('collapse');\n\n        // Add animation class\n        if(bsCollapseCtrl.$options.animation) {\n          element.addClass(bsCollapseCtrl.$options.animation);\n        }\n\n        // Push pane to parent bsCollapse controller\n        bsCollapseCtrl.$registerTarget(element);\n\n        // remove pane target from collapse controller when target is destroyed\n        scope.$on('$destroy', function() {\n          bsCollapseCtrl.$unregisterTarget(element);\n        });\n\n        function render() {\n          var index = bsCollapseCtrl.$targets.indexOf(element);\n          var active = bsCollapseCtrl.$activeIndexes();\n          var action = 'removeClass';\n          if (angular.isArray(active)) {\n            if (active.indexOf(index) !== -1) {\n              action = 'addClass';\n            }\n          }\n          else if (index === active) {\n            action = 'addClass';\n          }\n\n          $animate[action](element, bsCollapseCtrl.$options.activeClass);\n        }\n\n        bsCollapseCtrl.$viewChangeListeners.push(function() {\n          render();\n        });\n        render();\n\n      }\n    };\n\n  }]);\n\n// Source: datepicker.js\nangular.module('mgcrea.ngStrap.datepicker', [\n  'mgcrea.ngStrap.helpers.dateParser',\n  'mgcrea.ngStrap.helpers.dateFormatter',\n  'mgcrea.ngStrap.tooltip'])\n\n  .provider('$datepicker', function() {\n\n    var defaults = this.defaults = {\n      animation: 'am-fade',\n      prefixClass: 'datepicker',\n      placement: 'bottom-left',\n      template: 'datepicker/datepicker.tpl.html',\n      trigger: 'focus',\n      container: false,\n      keyboard: true,\n      html: false,\n      delay: 0,\n      // lang: $locale.id,\n      useNative: false,\n      dateType: 'date',\n      dateFormat: 'shortDate',\n      modelDateFormat: null,\n      dayFormat: 'dd',\n      monthFormat: 'MMM',\n      yearFormat: 'yyyy',\n      monthTitleFormat: 'MMMM yyyy',\n      yearTitleFormat: 'yyyy',\n      strictFormat: false,\n      autoclose: false,\n      minDate: -Infinity,\n      maxDate: +Infinity,\n      startView: 0,\n      minView: 0,\n      startWeek: 0,\n      daysOfWeekDisabled: '',\n      iconLeft: 'glyphicon glyphicon-chevron-left',\n      iconRight: 'glyphicon glyphicon-chevron-right'\n    };\n\n    this.$get = [\"$window\", \"$document\", \"$rootScope\", \"$sce\", \"$dateFormatter\", \"datepickerViews\", \"$tooltip\", \"$timeout\", function($window, $document, $rootScope, $sce, $dateFormatter, datepickerViews, $tooltip, $timeout) {\n\n      var bodyEl = angular.element($window.document.body);\n      var isNative = /(ip(a|o)d|iphone|android)/ig.test($window.navigator.userAgent);\n      var isTouch = ('createTouch' in $window.document) && isNative;\n      if(!defaults.lang) defaults.lang = $dateFormatter.getDefaultLocale();\n\n      function DatepickerFactory(element, controller, config) {\n\n        var $datepicker = $tooltip(element, angular.extend({}, defaults, config));\n        var parentScope = config.scope;\n        var options = $datepicker.$options;\n        var scope = $datepicker.$scope;\n        if(options.startView) options.startView -= options.minView;\n\n        // View vars\n\n        var pickerViews = datepickerViews($datepicker);\n        $datepicker.$views = pickerViews.views;\n        var viewDate = pickerViews.viewDate;\n        scope.$mode = options.startView;\n        scope.$iconLeft = options.iconLeft;\n        scope.$iconRight = options.iconRight;\n        var $picker = $datepicker.$views[scope.$mode];\n\n        // Scope methods\n\n        scope.$select = function(date) {\n          $datepicker.select(date);\n        };\n        scope.$selectPane = function(value) {\n          $datepicker.$selectPane(value);\n        };\n        scope.$toggleMode = function() {\n          $datepicker.setMode((scope.$mode + 1) % $datepicker.$views.length);\n        };\n\n        // Public methods\n\n        $datepicker.update = function(date) {\n          // console.warn('$datepicker.update() newValue=%o', date);\n          if(angular.isDate(date) && !isNaN(date.getTime())) {\n            $datepicker.$date = date;\n            $picker.update.call($picker, date);\n          }\n          // Build only if pristine\n          $datepicker.$build(true);\n        };\n\n        $datepicker.updateDisabledDates = function(dateRanges) {\n          options.disabledDateRanges = dateRanges;\n          for(var i = 0, l = scope.rows.length; i < l; i++) {\n            angular.forEach(scope.rows[i], $datepicker.$setDisabledEl);\n          }\n        };\n\n        $datepicker.select = function(date, keep) {\n          // console.warn('$datepicker.select', date, scope.$mode);\n          if(!angular.isDate(controller.$dateValue)) controller.$dateValue = new Date(date);\n          if(!scope.$mode || keep) {\n            controller.$setViewValue(angular.copy(date));\n            controller.$render();\n            if(options.autoclose && !keep) {\n              $timeout(function() { $datepicker.hide(true); });\n            }\n          } else {\n            angular.extend(viewDate, {year: date.getFullYear(), month: date.getMonth(), date: date.getDate()});\n            $datepicker.setMode(scope.$mode - 1);\n            $datepicker.$build();\n          }\n        };\n\n        $datepicker.setMode = function(mode) {\n          // console.warn('$datepicker.setMode', mode);\n          scope.$mode = mode;\n          $picker = $datepicker.$views[scope.$mode];\n          $datepicker.$build();\n        };\n\n        // Protected methods\n\n        $datepicker.$build = function(pristine) {\n          // console.warn('$datepicker.$build() viewDate=%o', viewDate);\n          if(pristine === true && $picker.built) return;\n          if(pristine === false && !$picker.built) return;\n          $picker.build.call($picker);\n        };\n\n        $datepicker.$updateSelected = function() {\n          for(var i = 0, l = scope.rows.length; i < l; i++) {\n            angular.forEach(scope.rows[i], updateSelected);\n          }\n        };\n\n        $datepicker.$isSelected = function(date) {\n          return $picker.isSelected(date);\n        };\n\n        $datepicker.$setDisabledEl = function(el) {\n          el.disabled = $picker.isDisabled(el.date);\n        };\n\n        $datepicker.$selectPane = function(value) {\n          var steps = $picker.steps;\n          // set targetDate to first day of month to avoid problems with\n          // date values rollover. This assumes the viewDate does not\n          // depend on the day of the month\n          var targetDate = new Date(Date.UTC(viewDate.year + ((steps.year || 0) * value), viewDate.month + ((steps.month || 0) * value), 1));\n          angular.extend(viewDate, {year: targetDate.getUTCFullYear(), month: targetDate.getUTCMonth(), date: targetDate.getUTCDate()});\n          $datepicker.$build();\n        };\n\n        $datepicker.$onMouseDown = function(evt) {\n          // Prevent blur on mousedown on .dropdown-menu\n          evt.preventDefault();\n          evt.stopPropagation();\n          // Emulate click for mobile devices\n          if(isTouch) {\n            var targetEl = angular.element(evt.target);\n            if(targetEl[0].nodeName.toLowerCase() !== 'button') {\n              targetEl = targetEl.parent();\n            }\n            targetEl.triggerHandler('click');\n          }\n        };\n\n        $datepicker.$onKeyDown = function(evt) {\n          if (!/(38|37|39|40|13)/.test(evt.keyCode) || evt.shiftKey || evt.altKey) return;\n          evt.preventDefault();\n          evt.stopPropagation();\n\n          if(evt.keyCode === 13) {\n            if(!scope.$mode) {\n              return $datepicker.hide(true);\n            } else {\n              return scope.$apply(function() { $datepicker.setMode(scope.$mode - 1); });\n            }\n          }\n\n          // Navigate with keyboard\n          $picker.onKeyDown(evt);\n          parentScope.$digest();\n        };\n\n        // Private\n\n        function updateSelected(el) {\n          el.selected = $datepicker.$isSelected(el.date);\n        }\n\n        function focusElement() {\n          element[0].focus();\n        }\n\n        // Overrides\n\n        var _init = $datepicker.init;\n        $datepicker.init = function() {\n          if(isNative && options.useNative) {\n            element.prop('type', 'date');\n            element.css('-webkit-appearance', 'textfield');\n            return;\n          } else if(isTouch) {\n            element.prop('type', 'text');\n            element.attr('readonly', 'true');\n            element.on('click', focusElement);\n          }\n          _init();\n        };\n\n        var _destroy = $datepicker.destroy;\n        $datepicker.destroy = function() {\n          if(isNative && options.useNative) {\n            element.off('click', focusElement);\n          }\n          _destroy();\n        };\n\n        var _show = $datepicker.show;\n        $datepicker.show = function() {\n          _show();\n          // use timeout to hookup the events to prevent\n          // event bubbling from being processed imediately.\n          $timeout(function() {\n            // if $datepicker is no longer showing, don't setup events\n            if(!$datepicker.$isShown) return;\n            $datepicker.$element.on(isTouch ? 'touchstart' : 'mousedown', $datepicker.$onMouseDown);\n            if(options.keyboard) {\n              element.on('keydown', $datepicker.$onKeyDown);\n            }\n          }, 0, false);\n        };\n\n        var _hide = $datepicker.hide;\n        $datepicker.hide = function(blur) {\n          if(!$datepicker.$isShown) return;\n          $datepicker.$element.off(isTouch ? 'touchstart' : 'mousedown', $datepicker.$onMouseDown);\n          if(options.keyboard) {\n            element.off('keydown', $datepicker.$onKeyDown);\n          }\n          _hide(blur);\n        };\n\n        return $datepicker;\n\n      }\n\n      DatepickerFactory.defaults = defaults;\n      return DatepickerFactory;\n\n    }];\n\n  })\n\n  .directive('bsDatepicker', [\"$window\", \"$parse\", \"$q\", \"$dateFormatter\", \"$dateParser\", \"$datepicker\", function($window, $parse, $q, $dateFormatter, $dateParser, $datepicker) {\n\n    var defaults = $datepicker.defaults;\n    var isNative = /(ip(a|o)d|iphone|android)/ig.test($window.navigator.userAgent);\n\n    return {\n      restrict: 'EAC',\n      require: 'ngModel',\n      link: function postLink(scope, element, attr, controller) {\n\n        // Directive options\n        var options = {scope: scope, controller: controller};\n        angular.forEach(['placement', 'container', 'delay', 'trigger', 'keyboard', 'html', 'animation', 'template', 'autoclose', 'dateType', 'dateFormat', 'modelDateFormat', 'dayFormat', 'strictFormat', 'startWeek', 'startDate', 'useNative', 'lang', 'startView', 'minView', 'iconLeft', 'iconRight', 'daysOfWeekDisabled', 'id'], function(key) {\n          if(angular.isDefined(attr[key])) options[key] = attr[key];\n        });\n\n        // Visibility binding support\n        attr.bsShow && scope.$watch(attr.bsShow, function(newValue, oldValue) {\n          if(!datepicker || !angular.isDefined(newValue)) return;\n          if(angular.isString(newValue)) newValue = !!newValue.match(/true|,?(datepicker),?/i);\n          newValue === true ? datepicker.show() : datepicker.hide();\n        });\n\n        // Initialize datepicker\n        var datepicker = $datepicker(element, controller, options);\n        options = datepicker.$options;\n        // Set expected iOS format\n        if(isNative && options.useNative) options.dateFormat = 'yyyy-MM-dd';\n\n        var lang = options.lang;\n\n        var formatDate = function(date, format) {\n          return $dateFormatter.formatDate(date, format, lang);\n        };\n\n        var dateParser = $dateParser({format: options.dateFormat, lang: lang, strict: options.strictFormat});\n\n        // Observe attributes for changes\n        angular.forEach(['minDate', 'maxDate'], function(key) {\n          // console.warn('attr.$observe(%s)', key, attr[key]);\n          angular.isDefined(attr[key]) && attr.$observe(key, function(newValue) {\n            // console.warn('attr.$observe(%s)=%o', key, newValue);\n            datepicker.$options[key] = dateParser.getDateForAttribute(key, newValue);\n            // Build only if dirty\n            !isNaN(datepicker.$options[key]) && datepicker.$build(false);\n            validateAgainstMinMaxDate(controller.$dateValue);\n          });\n        });\n\n        // Watch model for changes\n        scope.$watch(attr.ngModel, function(newValue, oldValue) {\n          datepicker.update(controller.$dateValue);\n        }, true);\n\n        // Normalize undefined/null/empty array,\n        // so that we don't treat changing from undefined->null as a change.\n        function normalizeDateRanges(ranges) {\n          if (!ranges || !ranges.length) return null;\n          return ranges;\n        }\n\n        if (angular.isDefined(attr.disabledDates)) {\n          scope.$watch(attr.disabledDates, function(disabledRanges, previousValue) {\n            disabledRanges = normalizeDateRanges(disabledRanges);\n            previousValue = normalizeDateRanges(previousValue);\n\n            if (disabledRanges) {\n              datepicker.updateDisabledDates(disabledRanges);\n            }\n          });\n        }\n\n        function validateAgainstMinMaxDate(parsedDate) {\n          if (!angular.isDate(parsedDate)) return;\n          var isMinValid = isNaN(datepicker.$options.minDate) || parsedDate.getTime() >= datepicker.$options.minDate;\n          var isMaxValid = isNaN(datepicker.$options.maxDate) || parsedDate.getTime() <= datepicker.$options.maxDate;\n          var isValid = isMinValid && isMaxValid;\n          controller.$setValidity('date', isValid);\n          controller.$setValidity('min', isMinValid);\n          controller.$setValidity('max', isMaxValid);\n          // Only update the model when we have a valid date\n          if(isValid) controller.$dateValue = parsedDate;\n        }\n\n        // viewValue -> $parsers -> modelValue\n        controller.$parsers.unshift(function(viewValue) {\n          // console.warn('$parser(\"%s\"): viewValue=%o', element.attr('ng-model'), viewValue);\n          // Null values should correctly reset the model value & validity\n          if(!viewValue) {\n            controller.$setValidity('date', true);\n            // BREAKING CHANGE:\n            // return null (not undefined) when input value is empty, so angularjs 1.3\n            // ngModelController can go ahead and run validators, like ngRequired\n            return null;\n          }\n          var parsedDate = dateParser.parse(viewValue, controller.$dateValue);\n          if(!parsedDate || isNaN(parsedDate.getTime())) {\n            controller.$setValidity('date', false);\n            // return undefined, causes ngModelController to\n            // invalidate model value\n            return;\n          } else {\n            validateAgainstMinMaxDate(parsedDate);\n          }\n          if(options.dateType === 'string') {\n            return formatDate(parsedDate, options.modelDateFormat || options.dateFormat);\n          } else if(options.dateType === 'number') {\n            return controller.$dateValue.getTime();\n          } else if(options.dateType === 'unix') {\n            return controller.$dateValue.getTime() / 1000;\n          } else if(options.dateType === 'iso') {\n            return controller.$dateValue.toISOString();\n          } else {\n            return new Date(controller.$dateValue);\n          }\n        });\n\n        // modelValue -> $formatters -> viewValue\n        controller.$formatters.push(function(modelValue) {\n          // console.warn('$formatter(\"%s\"): modelValue=%o (%o)', element.attr('ng-model'), modelValue, typeof modelValue);\n          var date;\n          if(angular.isUndefined(modelValue) || modelValue === null) {\n            date = NaN;\n          } else if(angular.isDate(modelValue)) {\n            date = modelValue;\n          } else if(options.dateType === 'string') {\n            date = dateParser.parse(modelValue, null, options.modelDateFormat);\n          } else if(options.dateType === 'unix') {\n            date = new Date(modelValue * 1000);\n          } else {\n            date = new Date(modelValue);\n          }\n          // Setup default value?\n          // if(isNaN(date.getTime())) {\n          //   var today = new Date();\n          //   date = new Date(today.getFullYear(), today.getMonth(), today.getDate(), 0, 0, 0, 0);\n          // }\n          controller.$dateValue = date;\n          return getDateFormattedString();\n        });\n\n        // viewValue -> element\n        controller.$render = function() {\n          // console.warn('$render(\"%s\"): viewValue=%o', element.attr('ng-model'), controller.$viewValue);\n          element.val(getDateFormattedString());\n        };\n\n        function getDateFormattedString() {\n          return !controller.$dateValue || isNaN(controller.$dateValue.getTime()) ? '' : formatDate(controller.$dateValue, options.dateFormat);\n        }\n\n        // Garbage collection\n        scope.$on('$destroy', function() {\n          if(datepicker) datepicker.destroy();\n          options = null;\n          datepicker = null;\n        });\n\n      }\n    };\n\n  }])\n\n  .provider('datepickerViews', function() {\n\n    var defaults = this.defaults = {\n      dayFormat: 'dd',\n      daySplit: 7\n    };\n\n    // Split array into smaller arrays\n    function split(arr, size) {\n      var arrays = [];\n      while(arr.length > 0) {\n        arrays.push(arr.splice(0, size));\n      }\n      return arrays;\n    }\n\n    // Modulus operator\n    function mod(n, m) {\n      return ((n % m) + m) % m;\n    }\n\n    this.$get = [\"$dateFormatter\", \"$dateParser\", \"$sce\", function($dateFormatter, $dateParser, $sce) {\n\n      return function(picker) {\n\n        var scope = picker.$scope;\n        var options = picker.$options;\n\n        var lang = options.lang;\n        var formatDate = function(date, format) {\n          return $dateFormatter.formatDate(date, format, lang);\n        };\n        var dateParser = $dateParser({format: options.dateFormat, lang: lang, strict: options.strictFormat});\n\n        var weekDaysMin = $dateFormatter.weekdaysShort(lang);\n        var weekDaysLabels = weekDaysMin.slice(options.startWeek).concat(weekDaysMin.slice(0, options.startWeek));\n        var weekDaysLabelsHtml = $sce.trustAsHtml('<th class=\"dow text-center\">' + weekDaysLabels.join('</th><th class=\"dow text-center\">') + '</th>');\n\n        var startDate = picker.$date || (options.startDate ? dateParser.getDateForAttribute('startDate', options.startDate) : new Date());\n        var viewDate = {year: startDate.getFullYear(), month: startDate.getMonth(), date: startDate.getDate()};\n        var timezoneOffset = startDate.getTimezoneOffset() * 6e4;\n\n        var views = [{\n            format: options.dayFormat,\n            split: 7,\n            steps: { month: 1 },\n            update: function(date, force) {\n              if(!this.built || force || date.getFullYear() !== viewDate.year || date.getMonth() !== viewDate.month) {\n                angular.extend(viewDate, {year: picker.$date.getFullYear(), month: picker.$date.getMonth(), date: picker.$date.getDate()});\n                picker.$build();\n              } else if(date.getDate() !== viewDate.date) {\n                viewDate.date = picker.$date.getDate();\n                picker.$updateSelected();\n              }\n            },\n            build: function() {\n              var firstDayOfMonth = new Date(viewDate.year, viewDate.month, 1), firstDayOfMonthOffset = firstDayOfMonth.getTimezoneOffset();\n              var firstDate = new Date(+firstDayOfMonth - mod(firstDayOfMonth.getDay() - options.startWeek, 7) * 864e5), firstDateOffset = firstDate.getTimezoneOffset();\n              var today = new Date().toDateString();\n              // Handle daylight time switch\n              if(firstDateOffset !== firstDayOfMonthOffset) firstDate = new Date(+firstDate + (firstDateOffset - firstDayOfMonthOffset) * 60e3);\n              var days = [], day;\n              for(var i = 0; i < 42; i++) { // < 7 * 6\n                day = dateParser.daylightSavingAdjust(new Date(firstDate.getFullYear(), firstDate.getMonth(), firstDate.getDate() + i));\n                days.push({date: day, isToday: day.toDateString() === today, label: formatDate(day, this.format), selected: picker.$date && this.isSelected(day), muted: day.getMonth() !== viewDate.month, disabled: this.isDisabled(day)});\n              }\n              scope.title = formatDate(firstDayOfMonth, options.monthTitleFormat);\n              scope.showLabels = true;\n              scope.labels = weekDaysLabelsHtml;\n              scope.rows = split(days, this.split);\n              this.built = true;\n            },\n            isSelected: function(date) {\n              return picker.$date && date.getFullYear() === picker.$date.getFullYear() && date.getMonth() === picker.$date.getMonth() && date.getDate() === picker.$date.getDate();\n            },\n            isDisabled: function(date) {\n              var time = date.getTime();\n\n              // Disabled because of min/max date.\n              if (time < options.minDate || time > options.maxDate) return true;\n\n              // Disabled due to being a disabled day of the week\n              if (options.daysOfWeekDisabled.indexOf(date.getDay()) !== -1) return true;\n\n              // Disabled because of disabled date range.\n              if (options.disabledDateRanges) {\n                for (var i = 0; i < options.disabledDateRanges.length; i++) {\n                  if (time >= options.disabledDateRanges[i].start && time <= options.disabledDateRanges[i].end) {\n                    return true;\n                  }\n                }\n              }\n\n              return false;\n            },\n            onKeyDown: function(evt) {\n              if (!picker.$date) {\n                return;\n              }\n              var actualTime = picker.$date.getTime();\n              var newDate;\n\n              if(evt.keyCode === 37) newDate = new Date(actualTime - 1 * 864e5);\n              else if(evt.keyCode === 38) newDate = new Date(actualTime - 7 * 864e5);\n              else if(evt.keyCode === 39) newDate = new Date(actualTime + 1 * 864e5);\n              else if(evt.keyCode === 40) newDate = new Date(actualTime + 7 * 864e5);\n\n              if (!this.isDisabled(newDate)) picker.select(newDate, true);\n            }\n          }, {\n            name: 'month',\n            format: options.monthFormat,\n            split: 4,\n            steps: { year: 1 },\n            update: function(date, force) {\n              if(!this.built || date.getFullYear() !== viewDate.year) {\n                angular.extend(viewDate, {year: picker.$date.getFullYear(), month: picker.$date.getMonth(), date: picker.$date.getDate()});\n                picker.$build();\n              } else if(date.getMonth() !== viewDate.month) {\n                angular.extend(viewDate, {month: picker.$date.getMonth(), date: picker.$date.getDate()});\n                picker.$updateSelected();\n              }\n            },\n            build: function() {\n              var firstMonth = new Date(viewDate.year, 0, 1);\n              var months = [], month;\n              for (var i = 0; i < 12; i++) {\n                month = new Date(viewDate.year, i, 1);\n                months.push({date: month, label: formatDate(month, this.format), selected: picker.$isSelected(month), disabled: this.isDisabled(month)});\n              }\n              scope.title = formatDate(month, options.yearTitleFormat);\n              scope.showLabels = false;\n              scope.rows = split(months, this.split);\n              this.built = true;\n            },\n            isSelected: function(date) {\n              return picker.$date && date.getFullYear() === picker.$date.getFullYear() && date.getMonth() === picker.$date.getMonth();\n            },\n            isDisabled: function(date) {\n              var lastDate = +new Date(date.getFullYear(), date.getMonth() + 1, 0);\n              return lastDate < options.minDate || date.getTime() > options.maxDate;\n            },\n            onKeyDown: function(evt) {\n              if (!picker.$date) {\n                return;\n              }\n              var actualMonth = picker.$date.getMonth();\n              var newDate = new Date(picker.$date);\n\n              if(evt.keyCode === 37) newDate.setMonth(actualMonth - 1);\n              else if(evt.keyCode === 38) newDate.setMonth(actualMonth - 4);\n              else if(evt.keyCode === 39) newDate.setMonth(actualMonth + 1);\n              else if(evt.keyCode === 40) newDate.setMonth(actualMonth + 4);\n\n              if (!this.isDisabled(newDate)) picker.select(newDate, true);\n            }\n          }, {\n            name: 'year',\n            format: options.yearFormat,\n            split: 4,\n            steps: { year: 12 },\n            update: function(date, force) {\n              if(!this.built || force || parseInt(date.getFullYear()/20, 10) !== parseInt(viewDate.year/20, 10)) {\n                angular.extend(viewDate, {year: picker.$date.getFullYear(), month: picker.$date.getMonth(), date: picker.$date.getDate()});\n                picker.$build();\n              } else if(date.getFullYear() !== viewDate.year) {\n                angular.extend(viewDate, {year: picker.$date.getFullYear(), month: picker.$date.getMonth(), date: picker.$date.getDate()});\n                picker.$updateSelected();\n              }\n            },\n            build: function() {\n              var firstYear = viewDate.year - viewDate.year % (this.split * 3);\n              var years = [], year;\n              for (var i = 0; i < 12; i++) {\n                year = new Date(firstYear + i, 0, 1);\n                years.push({date: year, label: formatDate(year, this.format), selected: picker.$isSelected(year), disabled: this.isDisabled(year)});\n              }\n              scope.title = years[0].label + '-' + years[years.length - 1].label;\n              scope.showLabels = false;\n              scope.rows = split(years, this.split);\n              this.built = true;\n            },\n            isSelected: function(date) {\n              return picker.$date && date.getFullYear() === picker.$date.getFullYear();\n            },\n            isDisabled: function(date) {\n              var lastDate = +new Date(date.getFullYear() + 1, 0, 0);\n              return lastDate < options.minDate || date.getTime() > options.maxDate;\n            },\n            onKeyDown: function(evt) {\n              if (!picker.$date) {\n                return;\n              }\n              var actualYear = picker.$date.getFullYear(),\n                  newDate = new Date(picker.$date);\n\n              if(evt.keyCode === 37) newDate.setYear(actualYear - 1);\n              else if(evt.keyCode === 38) newDate.setYear(actualYear - 4);\n              else if(evt.keyCode === 39) newDate.setYear(actualYear + 1);\n              else if(evt.keyCode === 40) newDate.setYear(actualYear + 4);\n\n              if (!this.isDisabled(newDate)) picker.select(newDate, true);\n            }\n          }];\n\n        return {\n          views: options.minView ? Array.prototype.slice.call(views, options.minView) : views,\n          viewDate: viewDate\n        };\n\n      };\n\n    }];\n\n  });\n\n// Source: dropdown.js\nangular.module('mgcrea.ngStrap.dropdown', ['mgcrea.ngStrap.tooltip'])\n\n  .provider('$dropdown', function() {\n\n    var defaults = this.defaults = {\n      animation: 'am-fade',\n      prefixClass: 'dropdown',\n      placement: 'bottom-left',\n      template: 'dropdown/dropdown.tpl.html',\n      trigger: 'click',\n      container: false,\n      keyboard: true,\n      html: false,\n      delay: 0\n    };\n\n    this.$get = [\"$window\", \"$rootScope\", \"$tooltip\", \"$timeout\", function($window, $rootScope, $tooltip, $timeout) {\n\n      var bodyEl = angular.element($window.document.body);\n      var matchesSelector = Element.prototype.matchesSelector || Element.prototype.webkitMatchesSelector || Element.prototype.mozMatchesSelector || Element.prototype.msMatchesSelector || Element.prototype.oMatchesSelector;\n\n      function DropdownFactory(element, config) {\n\n        var $dropdown = {};\n\n        // Common vars\n        var options = angular.extend({}, defaults, config);\n        var scope = $dropdown.$scope = options.scope && options.scope.$new() || $rootScope.$new();\n\n        $dropdown = $tooltip(element, options);\n        var parentEl = element.parent();\n\n        // Protected methods\n\n        $dropdown.$onKeyDown = function(evt) {\n          if (!/(38|40)/.test(evt.keyCode)) return;\n          evt.preventDefault();\n          evt.stopPropagation();\n\n          // Retrieve focused index\n          var items = angular.element($dropdown.$element[0].querySelectorAll('li:not(.divider) a'));\n          if(!items.length) return;\n          var index;\n          angular.forEach(items, function(el, i) {\n            if(matchesSelector && matchesSelector.call(el, ':focus')) index = i;\n          });\n\n          // Navigate with keyboard\n          if(evt.keyCode === 38 && index > 0) index--;\n          else if(evt.keyCode === 40 && index < items.length - 1) index++;\n          else if(angular.isUndefined(index)) index = 0;\n          items.eq(index)[0].focus();\n\n        };\n\n        // Overrides\n\n        var show = $dropdown.show;\n        $dropdown.show = function() {\n          show();\n          // use timeout to hookup the events to prevent\n          // event bubbling from being processed imediately.\n          $timeout(function() {\n            options.keyboard && $dropdown.$element.on('keydown', $dropdown.$onKeyDown);\n            bodyEl.on('click', onBodyClick);\n          }, 0, false);\n          parentEl.hasClass('dropdown') && parentEl.addClass('open');\n        };\n\n        var hide = $dropdown.hide;\n        $dropdown.hide = function() {\n          if(!$dropdown.$isShown) return;\n          options.keyboard && $dropdown.$element.off('keydown', $dropdown.$onKeyDown);\n          bodyEl.off('click', onBodyClick);\n          parentEl.hasClass('dropdown') && parentEl.removeClass('open');\n          hide();\n        };\n\n        var destroy = $dropdown.destroy;\n        $dropdown.destroy = function() {\n          bodyEl.off('click', onBodyClick);\n          destroy();\n        };\n\n        // Private functions\n\n        function onBodyClick(evt) {\n          if(evt.target === element[0]) return;\n          return evt.target !== element[0] && $dropdown.hide();\n        }\n\n        return $dropdown;\n\n      }\n\n      return DropdownFactory;\n\n    }];\n\n  })\n\n  .directive('bsDropdown', [\"$window\", \"$sce\", \"$dropdown\", function($window, $sce, $dropdown) {\n\n    return {\n      restrict: 'EAC',\n      scope: true,\n      link: function postLink(scope, element, attr, transclusion) {\n\n        // Directive options\n        var options = {scope: scope};\n        angular.forEach(['placement', 'container', 'delay', 'trigger', 'keyboard', 'html', 'animation', 'template', 'id'], function(key) {\n          if(angular.isDefined(attr[key])) options[key] = attr[key];\n        });\n\n        // Support scope as an object\n        attr.bsDropdown && scope.$watch(attr.bsDropdown, function(newValue, oldValue) {\n          scope.content = newValue;\n        }, true);\n\n        // Visibility binding support\n        attr.bsShow && scope.$watch(attr.bsShow, function(newValue, oldValue) {\n          if(!dropdown || !angular.isDefined(newValue)) return;\n          if(angular.isString(newValue)) newValue = !!newValue.match(/true|,?(dropdown),?/i);\n          newValue === true ? dropdown.show() : dropdown.hide();\n        });\n\n        // Initialize dropdown\n        var dropdown = $dropdown(element, options);\n\n        // Garbage collection\n        scope.$on('$destroy', function() {\n          if (dropdown) dropdown.destroy();\n          options = null;\n          dropdown = null;\n        });\n\n      }\n    };\n\n  }]);\n\n// Source: date-formatter.js\nangular.module('mgcrea.ngStrap.helpers.dateFormatter', [])\n\n  .service('$dateFormatter', [\"$locale\", \"dateFilter\", function($locale, dateFilter) {\n\n    // The unused `lang` arguments are on purpose. The default implementation does not\n    // use them and it always uses the locale loaded into the `$locale` service.\n    // Custom implementations might use it, thus allowing different directives to\n    // have different languages.\n\n    this.getDefaultLocale = function() {\n      return $locale.id;\n    };\n\n    // Format is either a data format name, e.g. \"shortTime\" or \"fullDate\", or a date format\n    // Return either the corresponding date format or the given date format.\n    this.getDatetimeFormat = function(format, lang) {\n      return $locale.DATETIME_FORMATS[format] || format;\n    };\n\n    this.weekdaysShort = function(lang) {\n      return $locale.DATETIME_FORMATS.SHORTDAY;\n    };\n\n    function splitTimeFormat(format) {\n      return /(h+)([:\\.])?(m+)[ ]?(a?)/i.exec(format).slice(1);\n    }\n\n    // h:mm a => h\n    this.hoursFormat = function(timeFormat) {\n      return splitTimeFormat(timeFormat)[0];\n    };\n\n    // h:mm a => mm\n    this.minutesFormat = function(timeFormat) {\n      return splitTimeFormat(timeFormat)[2];\n    };\n\n    // h:mm a => :\n    this.timeSeparator = function(timeFormat) {\n      return splitTimeFormat(timeFormat)[1];\n    };\n\n    // h:mm a => true, H.mm => false\n    this.showAM = function(timeFormat) {\n      return !!splitTimeFormat(timeFormat)[3];\n    };\n\n    this.formatDate = function(date, format, lang){\n      return dateFilter(date, format);\n    };\n\n  }]);\n\n// Source: date-parser.js\nangular.module('mgcrea.ngStrap.helpers.dateParser', [])\n\n.provider('$dateParser', [\"$localeProvider\", function($localeProvider) {\n\n  // define a custom ParseDate object to use instead of native Date\n  // to avoid date values wrapping when setting date component values\n  function ParseDate() {\n    this.year = 1970;\n    this.month = 0;\n    this.day = 1;\n    this.hours = 0;\n    this.minutes = 0;\n    this.seconds = 0;\n    this.milliseconds = 0;\n  }\n\n  ParseDate.prototype.setMilliseconds = function(value) { this.milliseconds = value; };\n  ParseDate.prototype.setSeconds = function(value) { this.seconds = value; };\n  ParseDate.prototype.setMinutes = function(value) { this.minutes = value; };\n  ParseDate.prototype.setHours = function(value) { this.hours = value; };\n  ParseDate.prototype.getHours = function() { return this.hours; };\n  ParseDate.prototype.setDate = function(value) { this.day = value; };\n  ParseDate.prototype.setMonth = function(value) { this.month = value; };\n  ParseDate.prototype.setFullYear = function(value) { this.year = value; };\n  ParseDate.prototype.fromDate = function(value) {\n    this.year = value.getFullYear();\n    this.month = value.getMonth();\n    this.day = value.getDate();\n    this.hours = value.getHours();\n    this.minutes = value.getMinutes();\n    this.seconds = value.getSeconds();\n    this.milliseconds = value.getMilliseconds();\n    return this;\n  };\n\n  ParseDate.prototype.toDate = function() {\n    return new Date(this.year, this.month, this.day, this.hours, this.minutes, this.seconds, this.milliseconds);\n  };\n\n  var proto = ParseDate.prototype;\n\n  function noop() {\n  }\n\n  function isNumeric(n) {\n    return !isNaN(parseFloat(n)) && isFinite(n);\n  }\n\n  function indexOfCaseInsensitive(array, value) {\n    var len = array.length, str=value.toString().toLowerCase();\n    for (var i=0; i<len; i++) {\n      if (array[i].toLowerCase() === str) { return i; }\n    }\n    return -1; // Return -1 per the \"Array.indexOf()\" method.\n  }\n\n  var defaults = this.defaults = {\n    format: 'shortDate',\n    strict: false\n  };\n\n  this.$get = [\"$locale\", \"dateFilter\", function($locale, dateFilter) {\n\n    var DateParserFactory = function(config) {\n\n      var options = angular.extend({}, defaults, config);\n\n      var $dateParser = {};\n\n      var regExpMap = {\n        'sss'   : '[0-9]{3}',\n        'ss'    : '[0-5][0-9]',\n        's'     : options.strict ? '[1-5]?[0-9]' : '[0-9]|[0-5][0-9]',\n        'mm'    : '[0-5][0-9]',\n        'm'     : options.strict ? '[1-5]?[0-9]' : '[0-9]|[0-5][0-9]',\n        'HH'    : '[01][0-9]|2[0-3]',\n        'H'     : options.strict ? '1?[0-9]|2[0-3]' : '[01]?[0-9]|2[0-3]',\n        'hh'    : '[0][1-9]|[1][012]',\n        'h'     : options.strict ? '[1-9]|1[012]' : '0?[1-9]|1[012]',\n        'a'     : 'AM|PM',\n        'EEEE'  : $locale.DATETIME_FORMATS.DAY.join('|'),\n        'EEE'   : $locale.DATETIME_FORMATS.SHORTDAY.join('|'),\n        'dd'    : '0[1-9]|[12][0-9]|3[01]',\n        'd'     : options.strict ? '[1-9]|[1-2][0-9]|3[01]' : '0?[1-9]|[1-2][0-9]|3[01]',\n        'MMMM'  : $locale.DATETIME_FORMATS.MONTH.join('|'),\n        'MMM'   : $locale.DATETIME_FORMATS.SHORTMONTH.join('|'),\n        'MM'    : '0[1-9]|1[012]',\n        'M'     : options.strict ? '[1-9]|1[012]' : '0?[1-9]|1[012]',\n        'yyyy'  : '[1]{1}[0-9]{3}|[2]{1}[0-9]{3}',\n        'yy'    : '[0-9]{2}',\n        'y'     : options.strict ? '-?(0|[1-9][0-9]{0,3})' : '-?0*[0-9]{1,4}',\n      };\n\n      var setFnMap = {\n        'sss'   : proto.setMilliseconds,\n        'ss'    : proto.setSeconds,\n        's'     : proto.setSeconds,\n        'mm'    : proto.setMinutes,\n        'm'     : proto.setMinutes,\n        'HH'    : proto.setHours,\n        'H'     : proto.setHours,\n        'hh'    : proto.setHours,\n        'h'     : proto.setHours,\n        'EEEE'  : noop,\n        'EEE'   : noop,\n        'dd'    : proto.setDate,\n        'd'     : proto.setDate,\n        'a'     : function(value) { var hours = this.getHours() % 12; return this.setHours(value.match(/pm/i) ? hours + 12 : hours); },\n        'MMMM'  : function(value) { return this.setMonth(indexOfCaseInsensitive($locale.DATETIME_FORMATS.MONTH, value)); },\n        'MMM'   : function(value) { return this.setMonth(indexOfCaseInsensitive($locale.DATETIME_FORMATS.SHORTMONTH, value)); },\n        'MM'    : function(value) { return this.setMonth(1 * value - 1); },\n        'M'     : function(value) { return this.setMonth(1 * value - 1); },\n        'yyyy'  : proto.setFullYear,\n        'yy'    : function(value) { return this.setFullYear(2000 + 1 * value); },\n        'y'     : proto.setFullYear\n      };\n\n      var regex, setMap;\n\n      $dateParser.init = function() {\n        $dateParser.$format = $locale.DATETIME_FORMATS[options.format] || options.format;\n        regex = regExpForFormat($dateParser.$format);\n        setMap = setMapForFormat($dateParser.$format);\n      };\n\n      $dateParser.isValid = function(date) {\n        if(angular.isDate(date)) return !isNaN(date.getTime());\n        return regex.test(date);\n      };\n\n      $dateParser.parse = function(value, baseDate, format) {\n        // check for date format special names\n        if(format) format = $locale.DATETIME_FORMATS[format] || format;\n        if(angular.isDate(value)) value = dateFilter(value, format || $dateParser.$format);\n        var formatRegex = format ? regExpForFormat(format) : regex;\n        var formatSetMap = format ? setMapForFormat(format) : setMap;\n        var matches = formatRegex.exec(value);\n        if(!matches) return false;\n        // use custom ParseDate object to set parsed values\n        var date = baseDate && !isNaN(baseDate.getTime()) ? new ParseDate().fromDate(baseDate) : new ParseDate().fromDate(new Date(1970, 0, 1, 0));\n        for(var i = 0; i < matches.length - 1; i++) {\n          formatSetMap[i] && formatSetMap[i].call(date, matches[i+1]);\n        }\n        // convert back to native Date object\n        var newDate = date.toDate();\n\n        // check new native Date object for day values overflow\n        if (parseInt(date.day, 10) !== newDate.getDate()) {\n          return false;\n        }\n\n        return newDate;\n      };\n\n      $dateParser.getDateForAttribute = function(key, value) {\n        var date;\n\n        if(value === 'today') {\n          var today = new Date();\n          date = new Date(today.getFullYear(), today.getMonth(), today.getDate() + (key === 'maxDate' ? 1 : 0), 0, 0, 0, (key === 'minDate' ? 0 : -1));\n        } else if(angular.isString(value) && value.match(/^\".+\"$/)) { // Support {{ dateObj }}\n          date = new Date(value.substr(1, value.length - 2));\n        } else if(isNumeric(value)) {\n          date = new Date(parseInt(value, 10));\n        } else if (angular.isString(value) && 0 === value.length) { // Reset date\n          date = key === 'minDate' ? -Infinity : +Infinity;\n        } else {\n          date = new Date(value);\n        }\n\n        return date;\n      };\n\n      $dateParser.getTimeForAttribute = function(key, value) {\n        var time;\n\n        if(value === 'now') {\n          time = new Date().setFullYear(1970, 0, 1);\n        } else if(angular.isString(value) && value.match(/^\".+\"$/)) {\n          time = new Date(value.substr(1, value.length - 2)).setFullYear(1970, 0, 1);\n        } else if(isNumeric(value)) {\n          time = new Date(parseInt(value, 10)).setFullYear(1970, 0, 1);\n        } else if (angular.isString(value) && 0 === value.length) { // Reset time\n          time = key === 'minTime' ? -Infinity : +Infinity;\n        } else {\n          time = $dateParser.parse(value, new Date(1970, 0, 1, 0));\n        }\n\n        return time;\n      };\n\n      /* Handle switch to/from daylight saving.\n      * Hours may be non-zero on daylight saving cut-over:\n      * > 12 when midnight changeover, but then cannot generate\n      * midnight datetime, so jump to 1AM, otherwise reset.\n      * @param  date  (Date) the date to check\n      * @return  (Date) the corrected date\n      *\n      * __ copied from jquery ui datepicker __\n      */\n      $dateParser.daylightSavingAdjust = function(date) {\n        if (!date) {\n          return null;\n        }\n        date.setHours(date.getHours() > 12 ? date.getHours() + 2 : 0);\n        return date;\n      };\n\n      // Private functions\n\n      function setMapForFormat(format) {\n        var keys = Object.keys(setFnMap), i;\n        var map = [], sortedMap = [];\n        // Map to setFn\n        var clonedFormat = format;\n        for(i = 0; i < keys.length; i++) {\n          if(format.split(keys[i]).length > 1) {\n            var index = clonedFormat.search(keys[i]);\n            format = format.split(keys[i]).join('');\n            if(setFnMap[keys[i]]) {\n              map[index] = setFnMap[keys[i]];\n            }\n          }\n        }\n        // Sort result map\n        angular.forEach(map, function(v) {\n          // conditional required since angular.forEach broke around v1.2.21\n          // related pr: https://github.com/angular/angular.js/pull/8525\n          if(v) sortedMap.push(v);\n        });\n        return sortedMap;\n      }\n\n      function escapeReservedSymbols(text) {\n        return text.replace(/\\//g, '[\\\\/]').replace('/-/g', '[-]').replace(/\\./g, '[.]').replace(/\\\\s/g, '[\\\\s]');\n      }\n\n      function regExpForFormat(format) {\n        var keys = Object.keys(regExpMap), i;\n\n        var re = format;\n        // Abstract replaces to avoid collisions\n        for(i = 0; i < keys.length; i++) {\n          re = re.split(keys[i]).join('${' + i + '}');\n        }\n        // Replace abstracted values\n        for(i = 0; i < keys.length; i++) {\n          re = re.split('${' + i + '}').join('(' + regExpMap[keys[i]] + ')');\n        }\n        format = escapeReservedSymbols(format);\n\n        return new RegExp('^' + re + '$', ['i']);\n      }\n\n      $dateParser.init();\n      return $dateParser;\n\n    };\n\n    return DateParserFactory;\n\n  }];\n\n}]);\n\n// Source: debounce.js\nangular.module('mgcrea.ngStrap.helpers.debounce', [])\n\n// @source jashkenas/underscore\n// @url https://github.com/jashkenas/underscore/blob/1.5.2/underscore.js#L693\n.factory('debounce', [\"$timeout\", function($timeout) {\n  return function(func, wait, immediate) {\n    var timeout = null;\n    return function() {\n      var context = this,\n        args = arguments,\n        callNow = immediate && !timeout;\n      if(timeout) {\n        $timeout.cancel(timeout);\n      }\n      timeout = $timeout(function later() {\n        timeout = null;\n        if(!immediate) {\n          func.apply(context, args);\n        }\n      }, wait, false);\n      if(callNow) {\n        func.apply(context, args);\n      }\n      return timeout;\n    };\n  };\n}])\n\n\n// @source jashkenas/underscore\n// @url https://github.com/jashkenas/underscore/blob/1.5.2/underscore.js#L661\n.factory('throttle', [\"$timeout\", function($timeout) {\n  return function(func, wait, options) {\n    var timeout = null;\n    options || (options = {});\n    return function() {\n      var context = this,\n        args = arguments;\n      if(!timeout) {\n        if(options.leading !== false) {\n          func.apply(context, args);\n        }\n        timeout = $timeout(function later() {\n          timeout = null;\n          if(options.trailing !== false) {\n            func.apply(context, args);\n          }\n        }, wait, false);\n      }\n    };\n  };\n}]);\n\n// Source: dimensions.js\nangular.module('mgcrea.ngStrap.helpers.dimensions', [])\n\n  .factory('dimensions', [\"$document\", \"$window\", function($document, $window) {\n\n    var jqLite = angular.element;\n    var fn = {};\n\n    /**\n     * Test the element nodeName\n     * @param element\n     * @param name\n     */\n    var nodeName = fn.nodeName = function(element, name) {\n      return element.nodeName && element.nodeName.toLowerCase() === name.toLowerCase();\n    };\n\n    /**\n     * Returns the element computed style\n     * @param element\n     * @param prop\n     * @param extra\n     */\n    fn.css = function(element, prop, extra) {\n      var value;\n      if (element.currentStyle) { //IE\n        value = element.currentStyle[prop];\n      } else if (window.getComputedStyle) {\n        value = window.getComputedStyle(element)[prop];\n      } else {\n        value = element.style[prop];\n      }\n      return extra === true ? parseFloat(value) || 0 : value;\n    };\n\n    /**\n     * Provides read-only equivalent of jQuery's offset function:\n     * @required-by bootstrap-tooltip, bootstrap-affix\n     * @url http://api.jquery.com/offset/\n     * @param element\n     */\n    fn.offset = function(element) {\n      var boxRect = element.getBoundingClientRect();\n      var docElement = element.ownerDocument;\n      return {\n        width: boxRect.width || element.offsetWidth,\n        height: boxRect.height || element.offsetHeight,\n        top: boxRect.top + (window.pageYOffset || docElement.documentElement.scrollTop) - (docElement.documentElement.clientTop || 0),\n        left: boxRect.left + (window.pageXOffset || docElement.documentElement.scrollLeft) - (docElement.documentElement.clientLeft || 0)\n      };\n    };\n\n    /**\n     * Provides read-only equivalent of jQuery's position function\n     * @required-by bootstrap-tooltip, bootstrap-affix\n     * @url http://api.jquery.com/offset/\n     * @param element\n     */\n    fn.position = function(element) {\n\n      var offsetParentRect = {top: 0, left: 0},\n          offsetParentElement,\n          offset;\n\n      // Fixed elements are offset from window (parentOffset = {top:0, left: 0}, because it is it's only offset parent\n      if (fn.css(element, 'position') === 'fixed') {\n\n        // We assume that getBoundingClientRect is available when computed position is fixed\n        offset = element.getBoundingClientRect();\n\n      } else {\n\n        // Get *real* offsetParentElement\n        offsetParentElement = offsetParent(element);\n\n        // Get correct offsets\n        offset = fn.offset(element);\n        if (!nodeName(offsetParentElement, 'html')) {\n          offsetParentRect = fn.offset(offsetParentElement);\n        }\n\n        // Add offsetParent borders\n        offsetParentRect.top += fn.css(offsetParentElement, 'borderTopWidth', true);\n        offsetParentRect.left += fn.css(offsetParentElement, 'borderLeftWidth', true);\n      }\n\n      // Subtract parent offsets and element margins\n      return {\n        width: element.offsetWidth,\n        height: element.offsetHeight,\n        top: offset.top - offsetParentRect.top - fn.css(element, 'marginTop', true),\n        left: offset.left - offsetParentRect.left - fn.css(element, 'marginLeft', true)\n      };\n\n    };\n\n    /**\n     * Returns the closest, non-statically positioned offsetParent of a given element\n     * @required-by fn.position\n     * @param element\n     */\n    var offsetParent = function offsetParentElement(element) {\n      var docElement = element.ownerDocument;\n      var offsetParent = element.offsetParent || docElement;\n      if(nodeName(offsetParent, '#document')) return docElement.documentElement;\n      while(offsetParent && !nodeName(offsetParent, 'html') && fn.css(offsetParent, 'position') === 'static') {\n        offsetParent = offsetParent.offsetParent;\n      }\n      return offsetParent || docElement.documentElement;\n    };\n\n    /**\n     * Provides equivalent of jQuery's height function\n     * @required-by bootstrap-affix\n     * @url http://api.jquery.com/height/\n     * @param element\n     * @param outer\n     */\n    fn.height = function(element, outer) {\n      var value = element.offsetHeight;\n      if(outer) {\n        value += fn.css(element, 'marginTop', true) + fn.css(element, 'marginBottom', true);\n      } else {\n        value -= fn.css(element, 'paddingTop', true) + fn.css(element, 'paddingBottom', true) + fn.css(element, 'borderTopWidth', true) + fn.css(element, 'borderBottomWidth', true);\n      }\n      return value;\n    };\n\n    /**\n     * Provides equivalent of jQuery's width function\n     * @required-by bootstrap-affix\n     * @url http://api.jquery.com/width/\n     * @param element\n     * @param outer\n     */\n    fn.width = function(element, outer) {\n      var value = element.offsetWidth;\n      if(outer) {\n        value += fn.css(element, 'marginLeft', true) + fn.css(element, 'marginRight', true);\n      } else {\n        value -= fn.css(element, 'paddingLeft', true) + fn.css(element, 'paddingRight', true) + fn.css(element, 'borderLeftWidth', true) + fn.css(element, 'borderRightWidth', true);\n      }\n      return value;\n    };\n\n    return fn;\n\n  }]);\n\n// Source: parse-options.js\nangular.module('mgcrea.ngStrap.helpers.parseOptions', [])\n\n  .provider('$parseOptions', function() {\n\n    var defaults = this.defaults = {\n      regexp: /^\\s*(.*?)(?:\\s+as\\s+(.*?))?(?:\\s+group\\s+by\\s+(.*))?\\s+for\\s+(?:([\\$\\w][\\$\\w]*)|(?:\\(\\s*([\\$\\w][\\$\\w]*)\\s*,\\s*([\\$\\w][\\$\\w]*)\\s*\\)))\\s+in\\s+(.*?)(?:\\s+track\\s+by\\s+(.*?))?$/\n    };\n\n    this.$get = [\"$parse\", \"$q\", function($parse, $q) {\n\n      function ParseOptionsFactory(attr, config) {\n\n        var $parseOptions = {};\n\n        // Common vars\n        var options = angular.extend({}, defaults, config);\n        $parseOptions.$values = [];\n\n        // Private vars\n        var match, displayFn, valueName, keyName, groupByFn, valueFn, valuesFn;\n\n        $parseOptions.init = function() {\n          $parseOptions.$match = match = attr.match(options.regexp);\n          displayFn = $parse(match[2] || match[1]),\n          valueName = match[4] || match[6],\n          keyName = match[5],\n          groupByFn = $parse(match[3] || ''),\n          valueFn = $parse(match[2] ? match[1] : valueName),\n          valuesFn = $parse(match[7]);\n        };\n\n        $parseOptions.valuesFn = function(scope, controller) {\n          return $q.when(valuesFn(scope, controller))\n          .then(function(values) {\n            $parseOptions.$values = values ? parseValues(values, scope) : {};\n            return $parseOptions.$values;\n          });\n        };\n\n        $parseOptions.displayValue = function(modelValue) {\n          var scope = {};\n          scope[valueName] = modelValue;\n          return displayFn(scope);\n        };\n\n        // Private functions\n\n        function parseValues(values, scope) {\n          return values.map(function(match, index) {\n            var locals = {}, label, value;\n            locals[valueName] = match;\n            label = displayFn(scope, locals);\n            value = valueFn(scope, locals);\n            return {label: label, value: value, index: index};\n          });\n        }\n\n        $parseOptions.init();\n        return $parseOptions;\n\n      }\n\n      return ParseOptionsFactory;\n\n    }];\n\n  });\n\n// Source: raf.js\n(angular.version.minor < 3 && angular.version.dot < 14) && angular.module('ng')\n\n.factory('$$rAF', [\"$window\", \"$timeout\", function($window, $timeout) {\n\n  var requestAnimationFrame = $window.requestAnimationFrame ||\n                              $window.webkitRequestAnimationFrame ||\n                              $window.mozRequestAnimationFrame;\n\n  var cancelAnimationFrame = $window.cancelAnimationFrame ||\n                             $window.webkitCancelAnimationFrame ||\n                             $window.mozCancelAnimationFrame ||\n                             $window.webkitCancelRequestAnimationFrame;\n\n  var rafSupported = !!requestAnimationFrame;\n  var raf = rafSupported ?\n    function(fn) {\n      var id = requestAnimationFrame(fn);\n      return function() {\n        cancelAnimationFrame(id);\n      };\n    } :\n    function(fn) {\n      var timer = $timeout(fn, 16.66, false); // 1000 / 60 = 16.666\n      return function() {\n        $timeout.cancel(timer);\n      };\n    };\n\n  raf.supported = rafSupported;\n\n  return raf;\n\n}]);\n\n// .factory('$$animateReflow', function($$rAF, $document) {\n\n//   var bodyEl = $document[0].body;\n\n//   return function(fn) {\n//     //the returned function acts as the cancellation function\n//     return $$rAF(function() {\n//       //the line below will force the browser to perform a repaint\n//       //so that all the animated elements within the animation frame\n//       //will be properly updated and drawn on screen. This is\n//       //required to perform multi-class CSS based animations with\n//       //Firefox. DO NOT REMOVE THIS LINE.\n//       var a = bodyEl.offsetWidth + 1;\n//       fn();\n//     });\n//   };\n\n// });\n\n// Source: modal.js\nangular.module('mgcrea.ngStrap.modal', ['mgcrea.ngStrap.helpers.dimensions'])\n\n  .provider('$modal', function() {\n\n    var defaults = this.defaults = {\n      animation: 'am-fade',\n      backdropAnimation: 'am-fade',\n      prefixClass: 'modal',\n      prefixEvent: 'modal',\n      placement: 'top',\n      template: 'modal/modal.tpl.html',\n      contentTemplate: false,\n      container: false,\n      element: null,\n      backdrop: true,\n      keyboard: true,\n      html: false,\n      show: true\n    };\n\n    this.$get = [\"$window\", \"$rootScope\", \"$compile\", \"$q\", \"$templateCache\", \"$http\", \"$animate\", \"$timeout\", \"$sce\", \"dimensions\", function($window, $rootScope, $compile, $q, $templateCache, $http, $animate, $timeout, $sce, dimensions) {\n\n      var forEach = angular.forEach;\n      var trim = String.prototype.trim;\n      var requestAnimationFrame = $window.requestAnimationFrame || $window.setTimeout;\n      var bodyElement = angular.element($window.document.body);\n      var htmlReplaceRegExp = /ng-bind=\"/ig;\n\n      function ModalFactory(config) {\n\n        var $modal = {};\n\n        // Common vars\n        var options = $modal.$options = angular.extend({}, defaults, config);\n        $modal.$promise = fetchTemplate(options.template);\n        var scope = $modal.$scope = options.scope && options.scope.$new() || $rootScope.$new();\n        if(!options.element && !options.container) {\n          options.container = 'body';\n        }\n\n        // store $id to identify the triggering element in events\n        // give priority to options.id, otherwise, try to use\n        // element id if defined\n        $modal.$id = options.id || options.element && options.element.attr('id') || '';\n\n        // Support scope as string options\n        forEach(['title', 'content'], function(key) {\n          if(options[key]) scope[key] = $sce.trustAsHtml(options[key]);\n        });\n\n        // Provide scope helpers\n        scope.$hide = function() {\n          scope.$$postDigest(function() {\n            $modal.hide();\n          });\n        };\n        scope.$show = function() {\n          scope.$$postDigest(function() {\n            $modal.show();\n          });\n        };\n        scope.$toggle = function() {\n          scope.$$postDigest(function() {\n            $modal.toggle();\n          });\n        };\n        // Publish isShown as a protected var on scope\n        $modal.$isShown = scope.$isShown = false;\n\n        // Support contentTemplate option\n        if(options.contentTemplate) {\n          $modal.$promise = $modal.$promise.then(function(template) {\n            var templateEl = angular.element(template);\n            return fetchTemplate(options.contentTemplate)\n            .then(function(contentTemplate) {\n              var contentEl = findElement('[ng-bind=\"content\"]', templateEl[0]).removeAttr('ng-bind').html(contentTemplate);\n              // Drop the default footer as you probably don't want it if you use a custom contentTemplate\n              if(!config.template) contentEl.next().remove();\n              return templateEl[0].outerHTML;\n            });\n          });\n        }\n\n        // Fetch, compile then initialize modal\n        var modalLinker, modalElement;\n        var backdropElement = angular.element('<div class=\"' + options.prefixClass + '-backdrop\"/>');\n        $modal.$promise.then(function(template) {\n          if(angular.isObject(template)) template = template.data;\n          if(options.html) template = template.replace(htmlReplaceRegExp, 'ng-bind-html=\"');\n          template = trim.apply(template);\n          modalLinker = $compile(template);\n          $modal.init();\n        });\n\n        $modal.init = function() {\n\n          // Options: show\n          if(options.show) {\n            scope.$$postDigest(function() {\n              $modal.show();\n            });\n          }\n\n        };\n\n        $modal.destroy = function() {\n\n          // Remove element\n          if(modalElement) {\n            modalElement.remove();\n            modalElement = null;\n          }\n          if(backdropElement) {\n            backdropElement.remove();\n            backdropElement = null;\n          }\n\n          // Destroy scope\n          scope.$destroy();\n\n        };\n\n        $modal.show = function() {\n          if($modal.$isShown) return;\n\n          if(scope.$emit(options.prefixEvent + '.show.before', $modal).defaultPrevented) {\n            return;\n          }\n          var parent, after;\n          if(angular.isElement(options.container)) {\n            parent = options.container;\n            after = options.container[0].lastChild ? angular.element(options.container[0].lastChild) : null;\n          } else {\n            if (options.container) {\n              parent = findElement(options.container);\n              after = parent[0].lastChild ? angular.element(parent[0].lastChild) : null;\n            } else {\n              parent = null;\n              after = options.element;\n            }\n          }\n\n          // Fetch a cloned element linked from template\n          modalElement = $modal.$element = modalLinker(scope, function(clonedElement, scope) {});\n\n          // Set the initial positioning.\n          modalElement.css({display: 'block'}).addClass(options.placement);\n\n          // Options: animation\n          if(options.animation) {\n            if(options.backdrop) {\n              backdropElement.addClass(options.backdropAnimation);\n            }\n            modalElement.addClass(options.animation);\n          }\n\n          if(options.backdrop) {\n            $animate.enter(backdropElement, bodyElement, null);\n          }\n          // Support v1.3+ $animate\n          // https://github.com/angular/angular.js/commit/bf0f5502b1bbfddc5cdd2f138efd9188b8c652a9\n          var promise = $animate.enter(modalElement, parent, after, enterAnimateCallback);\n          if(promise && promise.then) promise.then(enterAnimateCallback);\n\n          $modal.$isShown = scope.$isShown = true;\n          safeDigest(scope);\n          // Focus once the enter-animation has started\n          // Weird PhantomJS bug hack\n          var el = modalElement[0];\n          requestAnimationFrame(function() {\n            el.focus();\n          });\n\n          bodyElement.addClass(options.prefixClass + '-open');\n          if(options.animation) {\n            bodyElement.addClass(options.prefixClass + '-with-' + options.animation);\n          }\n\n          // Bind events\n          if(options.backdrop) {\n            modalElement.on('click', hideOnBackdropClick);\n            backdropElement.on('click', hideOnBackdropClick);\n            backdropElement.on('wheel', preventEventDefault);\n          }\n          if(options.keyboard) {\n            modalElement.on('keyup', $modal.$onKeyUp);\n          }\n        };\n\n        function enterAnimateCallback() {\n          scope.$emit(options.prefixEvent + '.show', $modal);\n        }\n\n        $modal.hide = function() {\n          if(!$modal.$isShown) return;\n\n          if(scope.$emit(options.prefixEvent + '.hide.before', $modal).defaultPrevented) {\n            return;\n          }\n          var promise = $animate.leave(modalElement, leaveAnimateCallback);\n          // Support v1.3+ $animate\n          // https://github.com/angular/angular.js/commit/bf0f5502b1bbfddc5cdd2f138efd9188b8c652a9\n          if(promise && promise.then) promise.then(leaveAnimateCallback);\n\n          if(options.backdrop) {\n            $animate.leave(backdropElement);\n          }\n          $modal.$isShown = scope.$isShown = false;\n          safeDigest(scope);\n\n          // Unbind events\n          if(options.backdrop) {\n            modalElement.off('click', hideOnBackdropClick);\n            backdropElement.off('click', hideOnBackdropClick);\n            backdropElement.off('wheel', preventEventDefault);\n          }\n          if(options.keyboard) {\n            modalElement.off('keyup', $modal.$onKeyUp);\n          }\n        };\n\n        function leaveAnimateCallback() {\n          scope.$emit(options.prefixEvent + '.hide', $modal);\n          bodyElement.removeClass(options.prefixClass + '-open');\n          if(options.animation) {\n            bodyElement.removeClass(options.prefixClass + '-with-' + options.animation);\n          }\n        }\n\n        $modal.toggle = function() {\n\n          $modal.$isShown ? $modal.hide() : $modal.show();\n\n        };\n\n        $modal.focus = function() {\n          modalElement[0].focus();\n        };\n\n        // Protected methods\n\n        $modal.$onKeyUp = function(evt) {\n\n          if (evt.which === 27 && $modal.$isShown) {\n            $modal.hide();\n            evt.stopPropagation();\n          }\n\n        };\n\n        // Private methods\n\n        function hideOnBackdropClick(evt) {\n          if(evt.target !== evt.currentTarget) return;\n          options.backdrop === 'static' ? $modal.focus() : $modal.hide();\n        }\n\n        function preventEventDefault(evt) {\n          evt.preventDefault();\n        }\n\n        return $modal;\n\n      }\n\n      // Helper functions\n\n      function safeDigest(scope) {\n        scope.$$phase || (scope.$root && scope.$root.$$phase) || scope.$digest();\n      }\n\n      function findElement(query, element) {\n        return angular.element((element || document).querySelectorAll(query));\n      }\n\n      var fetchPromises = {};\n      function fetchTemplate(template) {\n        if(fetchPromises[template]) return fetchPromises[template];\n        return (fetchPromises[template] = $q.when($templateCache.get(template) || $http.get(template))\n        .then(function(res) {\n          if(angular.isObject(res)) {\n            $templateCache.put(template, res.data);\n            return res.data;\n          }\n          return res;\n        }));\n      }\n\n      return ModalFactory;\n\n    }];\n\n  })\n\n  .directive('bsModal', [\"$window\", \"$sce\", \"$modal\", function($window, $sce, $modal) {\n\n    return {\n      restrict: 'EAC',\n      scope: true,\n      link: function postLink(scope, element, attr, transclusion) {\n\n        // Directive options\n        var options = {scope: scope, element: element, show: false};\n        angular.forEach(['template', 'contentTemplate', 'placement', 'backdrop', 'keyboard', 'html', 'container', 'animation', 'id'], function(key) {\n          if(angular.isDefined(attr[key])) options[key] = attr[key];\n        });\n\n        // Support scope as data-attrs\n        angular.forEach(['title', 'content'], function(key) {\n          attr[key] && attr.$observe(key, function(newValue, oldValue) {\n            scope[key] = $sce.trustAsHtml(newValue);\n          });\n        });\n\n        // Support scope as an object\n        attr.bsModal && scope.$watch(attr.bsModal, function(newValue, oldValue) {\n          if(angular.isObject(newValue)) {\n            angular.extend(scope, newValue);\n          } else {\n            scope.content = newValue;\n          }\n        }, true);\n\n        // Initialize modal\n        var modal = $modal(options);\n\n        // Trigger\n        element.on(attr.trigger || 'click', modal.toggle);\n\n        // Garbage collection\n        scope.$on('$destroy', function() {\n          if (modal) modal.destroy();\n          options = null;\n          modal = null;\n        });\n\n      }\n    };\n\n  }]);\n\n// Source: navbar.js\nangular.module('mgcrea.ngStrap.navbar', [])\n\n  .provider('$navbar', function() {\n\n    var defaults = this.defaults = {\n      activeClass: 'active',\n      routeAttr: 'data-match-route',\n      strict: false\n    };\n\n    this.$get = function() {\n      return {defaults: defaults};\n    };\n\n  })\n\n  .directive('bsNavbar', [\"$window\", \"$location\", \"$navbar\", function($window, $location, $navbar) {\n\n    var defaults = $navbar.defaults;\n\n    return {\n      restrict: 'A',\n      link: function postLink(scope, element, attr, controller) {\n\n        // Directive options\n        var options = angular.copy(defaults);\n        angular.forEach(Object.keys(defaults), function(key) {\n          if(angular.isDefined(attr[key])) options[key] = attr[key];\n        });\n\n        // Watch for the $location\n        scope.$watch(function() {\n\n          return $location.path();\n\n        }, function(newValue, oldValue) {\n\n          var liElements = element[0].querySelectorAll('li[' + options.routeAttr + ']');\n\n          angular.forEach(liElements, function(li) {\n\n            var liElement = angular.element(li);\n            var pattern = liElement.attr(options.routeAttr).replace('/', '\\\\/');\n            if(options.strict) {\n              pattern = '^' + pattern + '$';\n            }\n            var regexp = new RegExp(pattern, ['i']);\n\n            if(regexp.test(newValue)) {\n              liElement.addClass(options.activeClass);\n            } else {\n              liElement.removeClass(options.activeClass);\n            }\n\n          });\n\n        });\n\n      }\n\n    };\n\n  }]);\n\n// Source: popover.js\nangular.module('mgcrea.ngStrap.popover', ['mgcrea.ngStrap.tooltip'])\n\n  .provider('$popover', function() {\n\n    var defaults = this.defaults = {\n      animation: 'am-fade',\n      customClass: '',\n      container: false,\n      target: false,\n      placement: 'right',\n      template: 'popover/popover.tpl.html',\n      contentTemplate: false,\n      trigger: 'click',\n      keyboard: true,\n      html: false,\n      title: '',\n      content: '',\n      delay: 0,\n      autoClose: false\n    };\n\n    this.$get = [\"$tooltip\", function($tooltip) {\n\n      function PopoverFactory(element, config) {\n\n        // Common vars\n        var options = angular.extend({}, defaults, config);\n\n        var $popover = $tooltip(element, options);\n\n        // Support scope as string options [/*title, */content]\n        if(options.content) {\n          $popover.$scope.content = options.content;\n        }\n\n        return $popover;\n\n      }\n\n      return PopoverFactory;\n\n    }];\n\n  })\n\n  .directive('bsPopover', [\"$window\", \"$sce\", \"$popover\", function($window, $sce, $popover) {\n\n    var requestAnimationFrame = $window.requestAnimationFrame || $window.setTimeout;\n\n    return {\n      restrict: 'EAC',\n      scope: true,\n      link: function postLink(scope, element, attr) {\n\n        // Directive options\n        var options = {scope: scope};\n        angular.forEach(['template', 'contentTemplate', 'placement', 'container', 'target', 'delay', 'trigger', 'keyboard', 'html', 'animation', 'customClass', 'autoClose', 'id'], function(key) {\n          if(angular.isDefined(attr[key])) options[key] = attr[key];\n        });\n\n        // Support scope as data-attrs\n        angular.forEach(['title', 'content'], function(key) {\n          attr[key] && attr.$observe(key, function(newValue, oldValue) {\n            scope[key] = $sce.trustAsHtml(newValue);\n            angular.isDefined(oldValue) && requestAnimationFrame(function() {\n              popover && popover.$applyPlacement();\n            });\n          });\n        });\n\n        // Support scope as an object\n        attr.bsPopover && scope.$watch(attr.bsPopover, function(newValue, oldValue) {\n          if(angular.isObject(newValue)) {\n            angular.extend(scope, newValue);\n          } else {\n            scope.content = newValue;\n          }\n          angular.isDefined(oldValue) && requestAnimationFrame(function() {\n            popover && popover.$applyPlacement();\n          });\n        }, true);\n\n        // Visibility binding support\n        attr.bsShow && scope.$watch(attr.bsShow, function(newValue, oldValue) {\n          if(!popover || !angular.isDefined(newValue)) return;\n          if(angular.isString(newValue)) newValue = !!newValue.match(/true|,?(popover),?/i);\n          newValue === true ? popover.show() : popover.hide();\n        });\n\n        // Initialize popover\n        var popover = $popover(element, options);\n\n        // Garbage collection\n        scope.$on('$destroy', function() {\n          if (popover) popover.destroy();\n          options = null;\n          popover = null;\n        });\n\n      }\n    };\n\n  }]);\n\n// Source: select.js\nangular.module('mgcrea.ngStrap.select', ['mgcrea.ngStrap.tooltip', 'mgcrea.ngStrap.helpers.parseOptions'])\n\n  .provider('$select', function() {\n\n    var defaults = this.defaults = {\n      animation: 'am-fade',\n      prefixClass: 'select',\n      prefixEvent: '$select',\n      placement: 'bottom-left',\n      template: 'select/select.tpl.html',\n      trigger: 'focus',\n      container: false,\n      keyboard: true,\n      html: false,\n      delay: 0,\n      multiple: false,\n      allNoneButtons: false,\n      sort: true,\n      caretHtml: '&nbsp;<span class=\"caret\"></span>',\n      placeholder: 'Choose among the following...',\n      allText: 'All',\n      noneText: 'None',\n      maxLength: 3,\n      maxLengthHtml: 'selected',\n      iconCheckmark: 'glyphicon glyphicon-ok'\n    };\n\n    this.$get = [\"$window\", \"$document\", \"$rootScope\", \"$tooltip\", \"$timeout\", function($window, $document, $rootScope, $tooltip, $timeout) {\n\n      var bodyEl = angular.element($window.document.body);\n      var isNative = /(ip(a|o)d|iphone|android)/ig.test($window.navigator.userAgent);\n      var isTouch = ('createTouch' in $window.document) && isNative;\n\n      function SelectFactory(element, controller, config) {\n\n        var $select = {};\n\n        // Common vars\n        var options = angular.extend({}, defaults, config);\n\n        $select = $tooltip(element, options);\n        var scope = $select.$scope;\n\n        scope.$matches = [];\n        scope.$activeIndex = 0;\n        scope.$isMultiple = options.multiple;\n        scope.$showAllNoneButtons = options.allNoneButtons && options.multiple;\n        scope.$iconCheckmark = options.iconCheckmark;\n        scope.$allText = options.allText;\n        scope.$noneText = options.noneText;\n\n        scope.$activate = function(index) {\n          scope.$$postDigest(function() {\n            $select.activate(index);\n          });\n        };\n\n        scope.$select = function(index, evt) {\n          scope.$$postDigest(function() {\n            $select.select(index);\n          });\n        };\n\n        scope.$isVisible = function() {\n          return $select.$isVisible();\n        };\n\n        scope.$isActive = function(index) {\n          return $select.$isActive(index);\n        };\n\n        scope.$selectAll = function () {\n          for (var i = 0; i < scope.$matches.length; i++) {\n            if (!scope.$isActive(i)) {\n              scope.$select(i);\n            }\n          }\n        };\n\n        scope.$selectNone = function () {\n          for (var i = 0; i < scope.$matches.length; i++) {\n            if (scope.$isActive(i)) {\n              scope.$select(i);\n            }\n          }\n        };\n\n        // Public methods\n\n        $select.update = function(matches) {\n          scope.$matches = matches;\n          $select.$updateActiveIndex();\n        };\n\n        $select.activate = function(index) {\n          if(options.multiple) {\n            scope.$activeIndex.sort();\n            $select.$isActive(index) ? scope.$activeIndex.splice(scope.$activeIndex.indexOf(index), 1) : scope.$activeIndex.push(index);\n            if(options.sort) scope.$activeIndex.sort();\n          } else {\n            scope.$activeIndex = index;\n          }\n          return scope.$activeIndex;\n        };\n\n        $select.select = function(index) {\n          var value = scope.$matches[index].value;\n          scope.$apply(function() {\n            $select.activate(index);\n            if(options.multiple) {\n              controller.$setViewValue(scope.$activeIndex.map(function(index) {\n                return scope.$matches[index].value;\n              }));\n            } else {\n              controller.$setViewValue(value);\n              // Hide if single select\n              $select.hide();\n            }\n          });\n          // Emit event\n          scope.$emit(options.prefixEvent + '.select', value, index, $select);\n        };\n\n        // Protected methods\n\n        $select.$updateActiveIndex = function() {\n          if(controller.$modelValue && scope.$matches.length) {\n            if(options.multiple && angular.isArray(controller.$modelValue)) {\n              scope.$activeIndex = controller.$modelValue.map(function(value) {\n                return $select.$getIndex(value);\n              });\n            } else {\n              scope.$activeIndex = $select.$getIndex(controller.$modelValue);\n            }\n          } else if(scope.$activeIndex >= scope.$matches.length) {\n            scope.$activeIndex = options.multiple ? [] : 0;\n          }\n        };\n\n        $select.$isVisible = function() {\n          if(!options.minLength || !controller) {\n            return scope.$matches.length;\n          }\n          // minLength support\n          return scope.$matches.length && controller.$viewValue.length >= options.minLength;\n        };\n\n        $select.$isActive = function(index) {\n          if(options.multiple) {\n            return scope.$activeIndex.indexOf(index) !== -1;\n          } else {\n            return scope.$activeIndex === index;\n          }\n        };\n\n        $select.$getIndex = function(value) {\n          var l = scope.$matches.length, i = l;\n          if(!l) return;\n          for(i = l; i--;) {\n            if(scope.$matches[i].value === value) break;\n          }\n          if(i < 0) return;\n          return i;\n        };\n\n        $select.$onMouseDown = function(evt) {\n          // Prevent blur on mousedown on .dropdown-menu\n          evt.preventDefault();\n          evt.stopPropagation();\n          // Emulate click for mobile devices\n          if(isTouch) {\n            var targetEl = angular.element(evt.target);\n            targetEl.triggerHandler('click');\n          }\n        };\n\n        $select.$onKeyDown = function(evt) {\n          if (!/(9|13|38|40)/.test(evt.keyCode)) return;\n          evt.preventDefault();\n          evt.stopPropagation();\n\n          // Select with enter\n          if(!options.multiple && (evt.keyCode === 13 || evt.keyCode === 9)) {\n            return $select.select(scope.$activeIndex);\n          }\n\n          // Navigate with keyboard\n          if(evt.keyCode === 38 && scope.$activeIndex > 0) scope.$activeIndex--;\n          else if(evt.keyCode === 40 && scope.$activeIndex < scope.$matches.length - 1) scope.$activeIndex++;\n          else if(angular.isUndefined(scope.$activeIndex)) scope.$activeIndex = 0;\n          scope.$digest();\n        };\n\n        // Overrides\n\n        var _show = $select.show;\n        $select.show = function() {\n          _show();\n          if(options.multiple) {\n            $select.$element.addClass('select-multiple');\n          }\n          // use timeout to hookup the events to prevent\n          // event bubbling from being processed imediately.\n          $timeout(function() {\n            $select.$element.on(isTouch ? 'touchstart' : 'mousedown', $select.$onMouseDown);\n            if(options.keyboard) {\n              element.on('keydown', $select.$onKeyDown);\n            }\n          }, 0, false);\n        };\n\n        var _hide = $select.hide;\n        $select.hide = function() {\n          $select.$element.off(isTouch ? 'touchstart' : 'mousedown', $select.$onMouseDown);\n          if(options.keyboard) {\n            element.off('keydown', $select.$onKeyDown);\n          }\n          _hide(true);\n        };\n\n        return $select;\n\n      }\n\n      SelectFactory.defaults = defaults;\n      return SelectFactory;\n\n    }];\n\n  })\n\n  .directive('bsSelect', [\"$window\", \"$parse\", \"$q\", \"$select\", \"$parseOptions\", function($window, $parse, $q, $select, $parseOptions) {\n\n    var defaults = $select.defaults;\n\n    return {\n      restrict: 'EAC',\n      require: 'ngModel',\n      link: function postLink(scope, element, attr, controller) {\n\n        // Directive options\n        var options = {scope: scope, placeholder: defaults.placeholder};\n        angular.forEach(['placement', 'container', 'delay', 'trigger', 'keyboard', 'html', 'animation', 'template', 'placeholder', 'multiple', 'allNoneButtons', 'maxLength', 'maxLengthHtml', 'allText', 'noneText', 'iconCheckmark', 'autoClose', 'id'], function(key) {\n          if(angular.isDefined(attr[key])) options[key] = attr[key];\n        });\n\n        // Add support for select markup\n        if(element[0].nodeName.toLowerCase() === 'select') {\n          var inputEl = element;\n          inputEl.css('display', 'none');\n          element = angular.element('<button type=\"button\" class=\"btn btn-default\"></button>');\n          inputEl.after(element);\n        }\n\n        // Build proper ngOptions\n        var parsedOptions = $parseOptions(attr.ngOptions);\n\n        // Initialize select\n        var select = $select(element, controller, options);\n\n        // Watch ngOptions values before filtering for changes\n        var watchedOptions = parsedOptions.$match[7].replace(/\\|.+/, '').trim();\n        scope.$watch(watchedOptions, function(newValue, oldValue) {\n          // console.warn('scope.$watch(%s)', watchedOptions, newValue, oldValue);\n          parsedOptions.valuesFn(scope, controller)\n          .then(function(values) {\n            select.update(values);\n            controller.$render();\n          });\n        }, true);\n\n        // Watch model for changes\n        scope.$watch(attr.ngModel, function(newValue, oldValue) {\n          // console.warn('scope.$watch(%s)', attr.ngModel, newValue, oldValue);\n          select.$updateActiveIndex();\n          controller.$render();\n        }, true);\n\n        // Model rendering in view\n        controller.$render = function () {\n          // console.warn('$render', element.attr('ng-model'), 'controller.$modelValue', typeof controller.$modelValue, controller.$modelValue, 'controller.$viewValue', typeof controller.$viewValue, controller.$viewValue);\n          var selected, index;\n          if(options.multiple && angular.isArray(controller.$modelValue)) {\n            selected = controller.$modelValue.map(function(value) {\n              index = select.$getIndex(value);\n              return angular.isDefined(index) ? select.$scope.$matches[index].label : false;\n            }).filter(angular.isDefined);\n            if(selected.length > (options.maxLength || defaults.maxLength)) {\n              selected = selected.length + ' ' + (options.maxLengthHtml || defaults.maxLengthHtml);\n            } else {\n              selected = selected.join(', ');\n            }\n          } else {\n            index = select.$getIndex(controller.$modelValue);\n            selected = angular.isDefined(index) ? select.$scope.$matches[index].label : false;\n          }\n          element.html((selected ? selected : options.placeholder) + defaults.caretHtml);\n        };\n\n        if(options.multiple){\n          controller.$isEmpty = function(value){\n            return !value || value.length === 0;\n          };\n        }\n\n        // Garbage collection\n        scope.$on('$destroy', function() {\n          if (select) select.destroy();\n          options = null;\n          select = null;\n        });\n\n      }\n    };\n\n  }]);\n\n// Source: tab.js\nangular.module('mgcrea.ngStrap.tab', [])\n\n  .provider('$tab', function() {\n\n    var defaults = this.defaults = {\n      animation: 'am-fade',\n      template: 'tab/tab.tpl.html',\n      navClass: 'nav-tabs',\n      activeClass: 'active'\n    };\n\n    var controller = this.controller = function($scope, $element, $attrs) {\n      var self = this;\n\n      // Attributes options\n      self.$options = angular.copy(defaults);\n      angular.forEach(['animation', 'navClass', 'activeClass'], function(key) {\n        if(angular.isDefined($attrs[key])) self.$options[key] = $attrs[key];\n      });\n\n      // Publish options on scope\n      $scope.$navClass = self.$options.navClass;\n      $scope.$activeClass = self.$options.activeClass;\n\n      self.$panes = $scope.$panes = [];\n\n      // DEPRECATED: $viewChangeListeners, please use $activePaneChangeListeners\n      // Because we deprecated ngModel usage, we rename viewChangeListeners to \n      // activePaneChangeListeners to make more sense.\n      self.$activePaneChangeListeners = self.$viewChangeListeners = [];\n\n      self.$push = function(pane) {\n        self.$panes.push(pane);\n      };\n\n      self.$remove = function(pane) {\n        var index = self.$panes.indexOf(pane);\n        var activeIndex = self.$panes.$active;\n\n        // remove pane from $panes array\n        self.$panes.splice(index, 1);\n\n        if (index < activeIndex) {\n          // we removed a pane before the active pane, so we need to \n          // decrement the active pane index\n          activeIndex--;\n        }\n        else if (index === activeIndex && activeIndex === self.$panes.length) {\n          // we remove the active pane and it was the one at the end,\n          // so select the previous one\n          activeIndex--;\n        }\n        self.$setActive(activeIndex);\n      };\n\n      self.$panes.$active = 0;\n      self.$setActive = $scope.$setActive = function(value) {\n        self.$panes.$active = value;\n        self.$activePaneChangeListeners.forEach(function(fn) {\n          fn();\n        });\n      };\n\n    };\n\n    this.$get = function() {\n      var $tab = {};\n      $tab.defaults = defaults;\n      $tab.controller = controller;\n      return $tab;\n    };\n\n  })\n\n  .directive('bsTabs', [\"$window\", \"$animate\", \"$tab\", \"$parse\", function($window, $animate, $tab, $parse) {\n\n    var defaults = $tab.defaults;\n\n    return {\n      require: ['?ngModel', 'bsTabs'],\n      transclude: true,\n      scope: true,\n      controller: ['$scope', '$element', '$attrs', $tab.controller],\n      templateUrl: function(element, attr) {\n        return attr.template || defaults.template;\n      },\n      link: function postLink(scope, element, attrs, controllers) {\n\n        var ngModelCtrl = controllers[0];\n        var bsTabsCtrl = controllers[1];\n\n        // DEPRECATED: ngModel, please use bsActivePane\n        // 'ngModel' is deprecated bacause if interferes with form validation\n        // and status, so avoid using it here.\n        if(ngModelCtrl) {\n          console.warn('Usage of ngModel is deprecated, please use bsActivePane instead!');\n\n          // Update the modelValue following\n          bsTabsCtrl.$activePaneChangeListeners.push(function() {\n            ngModelCtrl.$setViewValue(bsTabsCtrl.$panes.$active);\n          });\n\n          // modelValue -> $formatters -> viewValue\n          ngModelCtrl.$formatters.push(function(modelValue) {\n            // console.warn('$formatter(\"%s\"): modelValue=%o (%o)', element.attr('ng-model'), modelValue, typeof modelValue);\n            bsTabsCtrl.$setActive(modelValue * 1);\n            return modelValue;\n          });\n\n        }\n\n        if (attrs.bsActivePane) {\n          // adapted from angularjs ngModelController bindings\n          // https://github.com/angular/angular.js/blob/v1.3.1/src%2Fng%2Fdirective%2Finput.js#L1730\n          var parsedBsActivePane = $parse(attrs.bsActivePane);\n\n          // Update bsActivePane value with change\n          bsTabsCtrl.$activePaneChangeListeners.push(function() {\n            parsedBsActivePane.assign(scope, bsTabsCtrl.$panes.$active);\n          });\n\n          // watch bsActivePane for value changes\n          scope.$watch(attrs.bsActivePane, function(newValue, oldValue) {\n            bsTabsCtrl.$setActive(newValue * 1);\n          }, true);\n        }\n      }\n    };\n\n  }])\n\n  .directive('bsPane', [\"$window\", \"$animate\", \"$sce\", function($window, $animate, $sce) {\n\n    return {\n      require: ['^?ngModel', '^bsTabs'],\n      scope: true,\n      link: function postLink(scope, element, attrs, controllers) {\n\n        var ngModelCtrl = controllers[0];\n        var bsTabsCtrl = controllers[1];\n\n        // Add base class\n        element.addClass('tab-pane');\n\n        // Observe title attribute for change\n        attrs.$observe('title', function(newValue, oldValue) {\n          scope.title = $sce.trustAsHtml(newValue);\n        });\n\n        // Add animation class\n        if(bsTabsCtrl.$options.animation) {\n          element.addClass(bsTabsCtrl.$options.animation);\n        }\n\n        // Push pane to parent bsTabs controller\n        bsTabsCtrl.$push(scope);\n\n        // remove pane from tab controller when pane is destroyed\n        scope.$on('$destroy', function() {\n          bsTabsCtrl.$remove(scope);\n        });\n\n        function render() {\n          var index = bsTabsCtrl.$panes.indexOf(scope);\n          var active = bsTabsCtrl.$panes.$active;\n          $animate[index === active ? 'addClass' : 'removeClass'](element, bsTabsCtrl.$options.activeClass);\n        }\n\n        bsTabsCtrl.$activePaneChangeListeners.push(function() {\n          render();\n        });\n        render();\n\n      }\n    };\n\n  }]);\n\n// Source: scrollspy.js\nangular.module('mgcrea.ngStrap.scrollspy', ['mgcrea.ngStrap.helpers.debounce', 'mgcrea.ngStrap.helpers.dimensions'])\n\n  .provider('$scrollspy', function() {\n\n    // Pool of registered spies\n    var spies = this.$$spies = {};\n\n    var defaults = this.defaults = {\n      debounce: 150,\n      throttle: 100,\n      offset: 100\n    };\n\n    this.$get = [\"$window\", \"$document\", \"$rootScope\", \"dimensions\", \"debounce\", \"throttle\", function($window, $document, $rootScope, dimensions, debounce, throttle) {\n\n      var windowEl = angular.element($window);\n      var docEl = angular.element($document.prop('documentElement'));\n      var bodyEl = angular.element($window.document.body);\n\n      // Helper functions\n\n      function nodeName(element, name) {\n        return element[0].nodeName && element[0].nodeName.toLowerCase() === name.toLowerCase();\n      }\n\n      function ScrollSpyFactory(config) {\n\n        // Common vars\n        var options = angular.extend({}, defaults, config);\n        if(!options.element) options.element = bodyEl;\n        var isWindowSpy = nodeName(options.element, 'body');\n        var scrollEl = isWindowSpy ? windowEl : options.element;\n        var scrollId = isWindowSpy ? 'window' : options.id;\n\n        // Use existing spy\n        if(spies[scrollId]) {\n          spies[scrollId].$$count++;\n          return spies[scrollId];\n        }\n\n        var $scrollspy = {};\n\n        // Private vars\n        var unbindViewContentLoaded, unbindIncludeContentLoaded;\n        var trackedElements = $scrollspy.$trackedElements = [];\n        var sortedElements = [];\n        var activeTarget;\n        var debouncedCheckPosition;\n        var throttledCheckPosition;\n        var debouncedCheckOffsets;\n        var viewportHeight;\n        var scrollTop;\n\n        $scrollspy.init = function() {\n\n          // Setup internal ref counter\n          this.$$count = 1;\n\n          // Bind events\n          debouncedCheckPosition = debounce(this.checkPosition, options.debounce);\n          throttledCheckPosition = throttle(this.checkPosition, options.throttle);\n          scrollEl.on('click', this.checkPositionWithEventLoop);\n          windowEl.on('resize', debouncedCheckPosition);\n          scrollEl.on('scroll', throttledCheckPosition);\n\n          debouncedCheckOffsets = debounce(this.checkOffsets, options.debounce);\n          unbindViewContentLoaded = $rootScope.$on('$viewContentLoaded', debouncedCheckOffsets);\n          unbindIncludeContentLoaded = $rootScope.$on('$includeContentLoaded', debouncedCheckOffsets);\n          debouncedCheckOffsets();\n\n          // Register spy for reuse\n          if(scrollId) {\n            spies[scrollId] = $scrollspy;\n          }\n\n        };\n\n        $scrollspy.destroy = function() {\n\n          // Check internal ref counter\n          this.$$count--;\n          if(this.$$count > 0) {\n            return;\n          }\n\n          // Unbind events\n          scrollEl.off('click', this.checkPositionWithEventLoop);\n          windowEl.off('resize', debouncedCheckPosition);\n          scrollEl.off('scroll', throttledCheckPosition);\n          unbindViewContentLoaded();\n          unbindIncludeContentLoaded();\n          if (scrollId) {\n            delete spies[scrollId];\n          }\n        };\n\n        $scrollspy.checkPosition = function() {\n\n          // Not ready yet\n          if(!sortedElements.length) return;\n\n          // Calculate the scroll position\n          scrollTop = (isWindowSpy ? $window.pageYOffset : scrollEl.prop('scrollTop')) || 0;\n\n          // Calculate the viewport height for use by the components\n          viewportHeight = Math.max($window.innerHeight, docEl.prop('clientHeight'));\n\n          // Activate first element if scroll is smaller\n          if(scrollTop < sortedElements[0].offsetTop && activeTarget !== sortedElements[0].target) {\n            return $scrollspy.$activateElement(sortedElements[0]);\n          }\n\n          // Activate proper element\n          for (var i = sortedElements.length; i--;) {\n            if(angular.isUndefined(sortedElements[i].offsetTop) || sortedElements[i].offsetTop === null) continue;\n            if(activeTarget === sortedElements[i].target) continue;\n            if(scrollTop < sortedElements[i].offsetTop) continue;\n            if(sortedElements[i + 1] && scrollTop > sortedElements[i + 1].offsetTop) continue;\n            return $scrollspy.$activateElement(sortedElements[i]);\n          }\n\n        };\n\n        $scrollspy.checkPositionWithEventLoop = function() {\n          // IE 9 throws an error if we use 'this' instead of '$scrollspy'\n          // in this setTimeout call\n          setTimeout($scrollspy.checkPosition, 1);\n        };\n\n        // Protected methods\n\n        $scrollspy.$activateElement = function(element) {\n          if(activeTarget) {\n            var activeElement = $scrollspy.$getTrackedElement(activeTarget);\n            if(activeElement) {\n              activeElement.source.removeClass('active');\n              if(nodeName(activeElement.source, 'li') && nodeName(activeElement.source.parent().parent(), 'li')) {\n                activeElement.source.parent().parent().removeClass('active');\n              }\n            }\n          }\n          activeTarget = element.target;\n          element.source.addClass('active');\n          if(nodeName(element.source, 'li') && nodeName(element.source.parent().parent(), 'li')) {\n            element.source.parent().parent().addClass('active');\n          }\n        };\n\n        $scrollspy.$getTrackedElement = function(target) {\n          return trackedElements.filter(function(obj) {\n            return obj.target === target;\n          })[0];\n        };\n\n        // Track offsets behavior\n\n        $scrollspy.checkOffsets = function() {\n\n          angular.forEach(trackedElements, function(trackedElement) {\n            var targetElement = document.querySelector(trackedElement.target);\n            trackedElement.offsetTop = targetElement ? dimensions.offset(targetElement).top : null;\n            if(options.offset && trackedElement.offsetTop !== null) trackedElement.offsetTop -= options.offset * 1;\n          });\n\n          sortedElements = trackedElements\n          .filter(function(el) {\n            return el.offsetTop !== null;\n          })\n          .sort(function(a, b) {\n            return a.offsetTop - b.offsetTop;\n          });\n\n          debouncedCheckPosition();\n\n        };\n\n        $scrollspy.trackElement = function(target, source) {\n          trackedElements.push({target: target, source: source});\n        };\n\n        $scrollspy.untrackElement = function(target, source) {\n          var toDelete;\n          for (var i = trackedElements.length; i--;) {\n            if(trackedElements[i].target === target && trackedElements[i].source === source) {\n              toDelete = i;\n              break;\n            }\n          }\n          trackedElements = trackedElements.splice(toDelete, 1);\n        };\n\n        $scrollspy.activate = function(i) {\n          trackedElements[i].addClass('active');\n        };\n\n        // Initialize plugin\n\n        $scrollspy.init();\n        return $scrollspy;\n\n      }\n\n      return ScrollSpyFactory;\n\n    }];\n\n  })\n\n  .directive('bsScrollspy', [\"$rootScope\", \"debounce\", \"dimensions\", \"$scrollspy\", function($rootScope, debounce, dimensions, $scrollspy) {\n\n    return {\n      restrict: 'EAC',\n      link: function postLink(scope, element, attr) {\n\n        var options = {scope: scope};\n        angular.forEach(['offset', 'target'], function(key) {\n          if(angular.isDefined(attr[key])) options[key] = attr[key];\n        });\n\n        var scrollspy = $scrollspy(options);\n        scrollspy.trackElement(options.target, element);\n\n        scope.$on('$destroy', function() {\n          if (scrollspy) {\n            scrollspy.untrackElement(options.target, element);\n            scrollspy.destroy();\n          }\n          options = null;\n          scrollspy = null;\n        });\n\n      }\n    };\n\n  }])\n\n\n  .directive('bsScrollspyList', [\"$rootScope\", \"debounce\", \"dimensions\", \"$scrollspy\", function($rootScope, debounce, dimensions, $scrollspy) {\n\n    return {\n      restrict: 'A',\n      compile: function postLink(element, attr) {\n        var children = element[0].querySelectorAll('li > a[href]');\n        angular.forEach(children, function(child) {\n          var childEl = angular.element(child);\n          childEl.parent().attr('bs-scrollspy', '').attr('data-target', childEl.attr('href'));\n        });\n      }\n\n    };\n\n  }]);\n\n// Source: timepicker.js\nangular.module('mgcrea.ngStrap.timepicker', [\n  'mgcrea.ngStrap.helpers.dateParser',\n  'mgcrea.ngStrap.helpers.dateFormatter',\n  'mgcrea.ngStrap.tooltip'])\n\n  .provider('$timepicker', function() {\n\n    var defaults = this.defaults = {\n      animation: 'am-fade',\n      prefixClass: 'timepicker',\n      placement: 'bottom-left',\n      template: 'timepicker/timepicker.tpl.html',\n      trigger: 'focus',\n      container: false,\n      keyboard: true,\n      html: false,\n      delay: 0,\n      // lang: $locale.id,\n      useNative: true,\n      timeType: 'date',\n      timeFormat: 'shortTime',\n      modelTimeFormat: null,\n      autoclose: false,\n      minTime: -Infinity,\n      maxTime: +Infinity,\n      length: 5,\n      hourStep: 1,\n      minuteStep: 5,\n      iconUp: 'glyphicon glyphicon-chevron-up',\n      iconDown: 'glyphicon glyphicon-chevron-down',\n      arrowBehavior: 'pager'\n    };\n\n    this.$get = [\"$window\", \"$document\", \"$rootScope\", \"$sce\", \"$dateFormatter\", \"$tooltip\", \"$timeout\", function($window, $document, $rootScope, $sce, $dateFormatter, $tooltip, $timeout) {\n\n      var bodyEl = angular.element($window.document.body);\n      var isNative = /(ip(a|o)d|iphone|android)/ig.test($window.navigator.userAgent);\n      var isTouch = ('createTouch' in $window.document) && isNative;\n      if(!defaults.lang) defaults.lang = $dateFormatter.getDefaultLocale();\n\n      function timepickerFactory(element, controller, config) {\n\n        var $timepicker = $tooltip(element, angular.extend({}, defaults, config));\n        var parentScope = config.scope;\n        var options = $timepicker.$options;\n        var scope = $timepicker.$scope;\n\n        var lang = options.lang;\n        var formatDate = function(date, format) {\n          return $dateFormatter.formatDate(date, format, lang);\n        };\n\n        // View vars\n\n        var selectedIndex = 0;\n        var startDate = controller.$dateValue || new Date();\n        var viewDate = {hour: startDate.getHours(), meridian: startDate.getHours() < 12, minute: startDate.getMinutes(), second: startDate.getSeconds(), millisecond: startDate.getMilliseconds()};\n\n        var format = $dateFormatter.getDatetimeFormat(options.timeFormat, lang);\n\n        var hoursFormat = $dateFormatter.hoursFormat(format),\n          timeSeparator = $dateFormatter.timeSeparator(format),\n          minutesFormat = $dateFormatter.minutesFormat(format),\n          showAM = $dateFormatter.showAM(format);\n\n        scope.$iconUp = options.iconUp;\n        scope.$iconDown = options.iconDown;\n\n        // Scope methods\n\n        scope.$select = function(date, index) {\n          $timepicker.select(date, index);\n        };\n        scope.$moveIndex = function(value, index) {\n          $timepicker.$moveIndex(value, index);\n        };\n        scope.$switchMeridian = function(date) {\n          $timepicker.switchMeridian(date);\n        };\n\n        // Public methods\n\n        $timepicker.update = function(date) {\n          // console.warn('$timepicker.update() newValue=%o', date);\n          if(angular.isDate(date) && !isNaN(date.getTime())) {\n            $timepicker.$date = date;\n            angular.extend(viewDate, {hour: date.getHours(), minute: date.getMinutes(), second: date.getSeconds(), millisecond: date.getMilliseconds()});\n            $timepicker.$build();\n          } else if(!$timepicker.$isBuilt) {\n            $timepicker.$build();\n          }\n        };\n\n        $timepicker.select = function(date, index, keep) {\n          // console.warn('$timepicker.select', date, scope.$mode);\n          if(!controller.$dateValue || isNaN(controller.$dateValue.getTime())) controller.$dateValue = new Date(1970, 0, 1);\n          if(!angular.isDate(date)) date = new Date(date);\n          if(index === 0) controller.$dateValue.setHours(date.getHours());\n          else if(index === 1) controller.$dateValue.setMinutes(date.getMinutes());\n          controller.$setViewValue(angular.copy(controller.$dateValue));\n          controller.$render();\n          if(options.autoclose && !keep) {\n            $timeout(function() { $timepicker.hide(true); });\n          }\n        };\n\n        $timepicker.switchMeridian = function(date) {\n          if (!controller.$dateValue || isNaN(controller.$dateValue.getTime())) {\n            return;\n          }\n          var hours = (date || controller.$dateValue).getHours();\n          controller.$dateValue.setHours(hours < 12 ? hours + 12 : hours - 12);\n          controller.$setViewValue(angular.copy(controller.$dateValue));\n          controller.$render();\n        };\n\n        // Protected methods\n\n        $timepicker.$build = function() {\n          // console.warn('$timepicker.$build() viewDate=%o', viewDate);\n          var i, midIndex = scope.midIndex = parseInt(options.length / 2, 10);\n          var hours = [], hour;\n          for(i = 0; i < options.length; i++) {\n            hour = new Date(1970, 0, 1, viewDate.hour - (midIndex - i) * options.hourStep);\n            hours.push({date: hour, label: formatDate(hour, hoursFormat), selected: $timepicker.$date && $timepicker.$isSelected(hour, 0), disabled: $timepicker.$isDisabled(hour, 0)});\n          }\n          var minutes = [], minute;\n          for(i = 0; i < options.length; i++) {\n            minute = new Date(1970, 0, 1, 0, viewDate.minute - (midIndex - i) * options.minuteStep);\n            minutes.push({date: minute, label: formatDate(minute, minutesFormat), selected: $timepicker.$date && $timepicker.$isSelected(minute, 1), disabled: $timepicker.$isDisabled(minute, 1)});\n          }\n\n          var rows = [];\n          for(i = 0; i < options.length; i++) {\n            rows.push([hours[i], minutes[i]]);\n          }\n          scope.rows = rows;\n          scope.showAM = showAM;\n          scope.isAM = ($timepicker.$date || hours[midIndex].date).getHours() < 12;\n          scope.timeSeparator = timeSeparator;\n          $timepicker.$isBuilt = true;\n        };\n\n        $timepicker.$isSelected = function(date, index) {\n          if(!$timepicker.$date) return false;\n          else if(index === 0) {\n            return date.getHours() === $timepicker.$date.getHours();\n          } else if(index === 1) {\n            return date.getMinutes() === $timepicker.$date.getMinutes();\n          }\n        };\n\n        $timepicker.$isDisabled = function(date, index) {\n          var selectedTime;\n          if(index === 0) {\n            selectedTime = date.getTime() + viewDate.minute * 6e4;\n          } else if(index === 1) {\n            selectedTime = date.getTime() + viewDate.hour * 36e5;\n          }\n          return selectedTime < options.minTime * 1 || selectedTime > options.maxTime * 1;\n        };\n\n        scope.$arrowAction = function (value, index) {\n          if (options.arrowBehavior === 'picker') {\n            $timepicker.$setTimeByStep(value,index);\n          } else {\n            $timepicker.$moveIndex(value,index);\n          }\n        };\n\n        $timepicker.$setTimeByStep = function(value, index) {\n          var newDate = new Date($timepicker.$date);\n          var hours = newDate.getHours(), hoursLength = formatDate(newDate, hoursFormat).length;\n          var minutes = newDate.getMinutes(), minutesLength = formatDate(newDate, minutesFormat).length;\n          if (index === 0) {\n            newDate.setHours(hours - (parseInt(options.hourStep, 10) * value));\n          }\n          else {\n            newDate.setMinutes(minutes - (parseInt(options.minuteStep, 10) * value));\n          }\n          $timepicker.select(newDate, index, true);\n        };\n\n        $timepicker.$moveIndex = function(value, index) {\n          var targetDate;\n          if(index === 0) {\n            targetDate = new Date(1970, 0, 1, viewDate.hour + (value * options.length), viewDate.minute);\n            angular.extend(viewDate, {hour: targetDate.getHours()});\n          } else if(index === 1) {\n            targetDate = new Date(1970, 0, 1, viewDate.hour, viewDate.minute + (value * options.length * options.minuteStep));\n            angular.extend(viewDate, {minute: targetDate.getMinutes()});\n          }\n          $timepicker.$build();\n        };\n\n        $timepicker.$onMouseDown = function(evt) {\n          // Prevent blur on mousedown on .dropdown-menu\n          if(evt.target.nodeName.toLowerCase() !== 'input') evt.preventDefault();\n          evt.stopPropagation();\n          // Emulate click for mobile devices\n          if(isTouch) {\n            var targetEl = angular.element(evt.target);\n            if(targetEl[0].nodeName.toLowerCase() !== 'button') {\n              targetEl = targetEl.parent();\n            }\n            targetEl.triggerHandler('click');\n          }\n        };\n\n        $timepicker.$onKeyDown = function(evt) {\n          if (!/(38|37|39|40|13)/.test(evt.keyCode) || evt.shiftKey || evt.altKey) return;\n          evt.preventDefault();\n          evt.stopPropagation();\n\n          // Close on enter\n          if(evt.keyCode === 13) return $timepicker.hide(true);\n\n          // Navigate with keyboard\n          var newDate = new Date($timepicker.$date);\n          var hours = newDate.getHours(), hoursLength = formatDate(newDate, hoursFormat).length;\n          var minutes = newDate.getMinutes(), minutesLength = formatDate(newDate, minutesFormat).length;\n          var lateralMove = /(37|39)/.test(evt.keyCode);\n          var count = 2 + showAM * 1;\n\n          // Navigate indexes (left, right)\n          if (lateralMove) {\n            if(evt.keyCode === 37) selectedIndex = selectedIndex < 1 ? count - 1 : selectedIndex - 1;\n            else if(evt.keyCode === 39) selectedIndex = selectedIndex < count - 1 ? selectedIndex + 1 : 0;\n          }\n\n          // Update values (up, down)\n          var selectRange = [0, hoursLength];\n          if(selectedIndex === 0) {\n            if(evt.keyCode === 38) newDate.setHours(hours - parseInt(options.hourStep, 10));\n            else if(evt.keyCode === 40) newDate.setHours(hours + parseInt(options.hourStep, 10));\n            // re-calculate hours length because we have changed hours value\n            hoursLength = formatDate(newDate, hoursFormat).length;\n            selectRange = [0, hoursLength];\n          } else if(selectedIndex === 1) {\n            if(evt.keyCode === 38) newDate.setMinutes(minutes - parseInt(options.minuteStep, 10));\n            else if(evt.keyCode === 40) newDate.setMinutes(minutes + parseInt(options.minuteStep, 10));\n            // re-calculate minutes length because we have changes minutes value\n            minutesLength = formatDate(newDate, minutesFormat).length;\n            selectRange = [hoursLength + 1, hoursLength + 1 + minutesLength];\n          } else if(selectedIndex === 2) {\n            if(!lateralMove) $timepicker.switchMeridian();\n            selectRange = [hoursLength + 1 + minutesLength + 1, hoursLength + 1 + minutesLength + 3];\n          }\n          $timepicker.select(newDate, selectedIndex, true);\n          createSelection(selectRange[0], selectRange[1]);\n          parentScope.$digest();\n        };\n\n        // Private\n\n        function createSelection(start, end) {\n          if(element[0].createTextRange) {\n            var selRange = element[0].createTextRange();\n            selRange.collapse(true);\n            selRange.moveStart('character', start);\n            selRange.moveEnd('character', end);\n            selRange.select();\n          } else if(element[0].setSelectionRange) {\n            element[0].setSelectionRange(start, end);\n          } else if(angular.isUndefined(element[0].selectionStart)) {\n            element[0].selectionStart = start;\n            element[0].selectionEnd = end;\n          }\n        }\n\n        function focusElement() {\n          element[0].focus();\n        }\n\n        // Overrides\n\n        var _init = $timepicker.init;\n        $timepicker.init = function() {\n          if(isNative && options.useNative) {\n            element.prop('type', 'time');\n            element.css('-webkit-appearance', 'textfield');\n            return;\n          } else if(isTouch) {\n            element.prop('type', 'text');\n            element.attr('readonly', 'true');\n            element.on('click', focusElement);\n          }\n          _init();\n        };\n\n        var _destroy = $timepicker.destroy;\n        $timepicker.destroy = function() {\n          if(isNative && options.useNative) {\n            element.off('click', focusElement);\n          }\n          _destroy();\n        };\n\n        var _show = $timepicker.show;\n        $timepicker.show = function() {\n          _show();\n          // use timeout to hookup the events to prevent\n          // event bubbling from being processed imediately.\n          $timeout(function() {\n            $timepicker.$element.on(isTouch ? 'touchstart' : 'mousedown', $timepicker.$onMouseDown);\n            if(options.keyboard) {\n              element.on('keydown', $timepicker.$onKeyDown);\n            }\n          }, 0, false);\n        };\n\n        var _hide = $timepicker.hide;\n        $timepicker.hide = function(blur) {\n          if(!$timepicker.$isShown) return;\n          $timepicker.$element.off(isTouch ? 'touchstart' : 'mousedown', $timepicker.$onMouseDown);\n          if(options.keyboard) {\n            element.off('keydown', $timepicker.$onKeyDown);\n          }\n          _hide(blur);\n        };\n\n        return $timepicker;\n\n      }\n\n      timepickerFactory.defaults = defaults;\n      return timepickerFactory;\n\n    }];\n\n  })\n\n\n  .directive('bsTimepicker', [\"$window\", \"$parse\", \"$q\", \"$dateFormatter\", \"$dateParser\", \"$timepicker\", function($window, $parse, $q, $dateFormatter, $dateParser, $timepicker) {\n\n    var defaults = $timepicker.defaults;\n    var isNative = /(ip(a|o)d|iphone|android)/ig.test($window.navigator.userAgent);\n    var requestAnimationFrame = $window.requestAnimationFrame || $window.setTimeout;\n\n    return {\n      restrict: 'EAC',\n      require: 'ngModel',\n      link: function postLink(scope, element, attr, controller) {\n\n        // Directive options\n        var options = {scope: scope, controller: controller};\n        angular.forEach(['placement', 'container', 'delay', 'trigger', 'keyboard', 'html', 'animation', 'template', 'autoclose', 'timeType', 'timeFormat', 'modelTimeFormat', 'useNative', 'hourStep', 'minuteStep', 'length', 'arrowBehavior', 'iconUp', 'iconDown', 'id'], function(key) {\n          if(angular.isDefined(attr[key])) options[key] = attr[key];\n        });\n\n        // Visibility binding support\n        attr.bsShow && scope.$watch(attr.bsShow, function(newValue, oldValue) {\n          if(!timepicker || !angular.isDefined(newValue)) return;\n          if(angular.isString(newValue)) newValue = !!newValue.match(/true|,?(timepicker),?/i);\n          newValue === true ? timepicker.show() : timepicker.hide();\n        });\n\n        // Initialize timepicker\n        if(isNative && (options.useNative || defaults.useNative)) options.timeFormat = 'HH:mm';\n        var timepicker = $timepicker(element, controller, options);\n        options = timepicker.$options;\n\n        var lang = options.lang;\n        var formatDate = function(date, format) {\n          return $dateFormatter.formatDate(date, format, lang);\n        };\n\n        // Initialize parser\n        var dateParser = $dateParser({format: options.timeFormat, lang: lang});\n\n        // Observe attributes for changes\n        angular.forEach(['minTime', 'maxTime'], function(key) {\n          // console.warn('attr.$observe(%s)', key, attr[key]);\n          angular.isDefined(attr[key]) && attr.$observe(key, function(newValue) {\n            timepicker.$options[key] = dateParser.getTimeForAttribute(key, newValue);\n            !isNaN(timepicker.$options[key]) && timepicker.$build();\n            validateAgainstMinMaxTime(controller.$dateValue);\n          });\n        });\n\n        // Watch model for changes\n        scope.$watch(attr.ngModel, function(newValue, oldValue) {\n          // console.warn('scope.$watch(%s)', attr.ngModel, newValue, oldValue, controller.$dateValue);\n          timepicker.update(controller.$dateValue);\n        }, true);\n\n        function validateAgainstMinMaxTime(parsedTime) {\n          if (!angular.isDate(parsedTime)) return;\n          var isMinValid = isNaN(options.minTime) || new Date(parsedTime.getTime()).setFullYear(1970, 0, 1) >= options.minTime;\n          var isMaxValid = isNaN(options.maxTime) || new Date(parsedTime.getTime()).setFullYear(1970, 0, 1) <= options.maxTime;\n          var isValid = isMinValid && isMaxValid;\n          controller.$setValidity('date', isValid);\n          controller.$setValidity('min', isMinValid);\n          controller.$setValidity('max', isMaxValid);\n          // Only update the model when we have a valid date\n          if(!isValid) {\n              return;\n          }\n          controller.$dateValue = parsedTime;\n        }\n\n        // viewValue -> $parsers -> modelValue\n        controller.$parsers.unshift(function(viewValue) {\n          // console.warn('$parser(\"%s\"): viewValue=%o', element.attr('ng-model'), viewValue);\n          // Null values should correctly reset the model value & validity\n          if(!viewValue) {\n            // BREAKING CHANGE:\n            // return null (not undefined) when input value is empty, so angularjs 1.3\n            // ngModelController can go ahead and run validators, like ngRequired\n            controller.$setValidity('date', true);\n            return null;\n          }\n          var parsedTime = angular.isDate(viewValue) ? viewValue : dateParser.parse(viewValue, controller.$dateValue);\n          if(!parsedTime || isNaN(parsedTime.getTime())) {\n            controller.$setValidity('date', false);\n            // return undefined, causes ngModelController to\n            // invalidate model value\n            return;\n          } else {\n            validateAgainstMinMaxTime(parsedTime);\n          }\n          if(options.timeType === 'string') {\n            return formatDate(parsedTime, options.modelTimeFormat || options.timeFormat);\n          } else if(options.timeType === 'number') {\n            return controller.$dateValue.getTime();\n          } else if(options.timeType === 'unix') {\n            return controller.$dateValue.getTime() / 1000;\n          } else if(options.timeType === 'iso') {\n            return controller.$dateValue.toISOString();\n          } else {\n            return new Date(controller.$dateValue);\n          }\n        });\n\n        // modelValue -> $formatters -> viewValue\n        controller.$formatters.push(function(modelValue) {\n          // console.warn('$formatter(\"%s\"): modelValue=%o (%o)', element.attr('ng-model'), modelValue, typeof modelValue);\n          var date;\n          if(angular.isUndefined(modelValue) || modelValue === null) {\n            date = NaN;\n          } else if(angular.isDate(modelValue)) {\n            date = modelValue;\n          } else if(options.timeType === 'string') {\n            date = dateParser.parse(modelValue, null, options.modelTimeFormat);\n          } else if(options.timeType === 'unix') {\n            date = new Date(modelValue * 1000);\n          } else {\n            date = new Date(modelValue);\n          }\n          // Setup default value?\n          // if(isNaN(date.getTime())) date = new Date(new Date().setMinutes(0) + 36e5);\n          controller.$dateValue = date;\n          return getTimeFormattedString();\n        });\n\n        // viewValue -> element\n        controller.$render = function() {\n          // console.warn('$render(\"%s\"): viewValue=%o', element.attr('ng-model'), controller.$viewValue);\n          element.val(getTimeFormattedString());\n        };\n\n        function getTimeFormattedString() {\n          return !controller.$dateValue || isNaN(controller.$dateValue.getTime()) ? '' : formatDate(controller.$dateValue, options.timeFormat);\n        }\n\n        // Garbage collection\n        scope.$on('$destroy', function() {\n          if (timepicker) timepicker.destroy();\n          options = null;\n          timepicker = null;\n        });\n\n      }\n    };\n\n  }]);\n\n// Source: tooltip.js\nangular.module('mgcrea.ngStrap.tooltip', ['mgcrea.ngStrap.helpers.dimensions'])\n\n  .provider('$tooltip', function() {\n\n    var defaults = this.defaults = {\n      animation: 'am-fade',\n      customClass: '',\n      prefixClass: 'tooltip',\n      prefixEvent: 'tooltip',\n      container: false,\n      target: false,\n      placement: 'top',\n      template: 'tooltip/tooltip.tpl.html',\n      contentTemplate: false,\n      trigger: 'hover focus',\n      keyboard: false,\n      html: false,\n      show: false,\n      title: '',\n      type: '',\n      delay: 0,\n      autoClose: false,\n      bsEnabled: true\n    };\n\n    this.$get = [\"$window\", \"$rootScope\", \"$compile\", \"$q\", \"$templateCache\", \"$http\", \"$animate\", \"$sce\", \"dimensions\", \"$$rAF\", \"$timeout\", function($window, $rootScope, $compile, $q, $templateCache, $http, $animate, $sce, dimensions, $$rAF, $timeout) {\n\n      var trim = String.prototype.trim;\n      var isTouch = 'createTouch' in $window.document;\n      var htmlReplaceRegExp = /ng-bind=\"/ig;\n      var $body = angular.element($window.document);\n\n      function TooltipFactory(element, config) {\n\n        var $tooltip = {};\n\n        // Common vars\n        var nodeName = element[0].nodeName.toLowerCase();\n        var options = $tooltip.$options = angular.extend({}, defaults, config);\n        $tooltip.$promise = fetchTemplate(options.template);\n        var scope = $tooltip.$scope = options.scope && options.scope.$new() || $rootScope.$new();\n        if(options.delay && angular.isString(options.delay)) {\n          var split = options.delay.split(',').map(parseFloat);\n          options.delay = split.length > 1 ? {show: split[0], hide: split[1]} : split[0];\n        }\n\n        // store $id to identify the triggering element in events\n        // give priority to options.id, otherwise, try to use\n        // element id if defined\n        $tooltip.$id = options.id || element.attr('id') || '';\n\n        // Support scope as string options\n        if(options.title) {\n          scope.title = $sce.trustAsHtml(options.title);\n        }\n\n        // Provide scope helpers\n        scope.$setEnabled = function(isEnabled) {\n          scope.$$postDigest(function() {\n            $tooltip.setEnabled(isEnabled);\n          });\n        };\n        scope.$hide = function() {\n          scope.$$postDigest(function() {\n            $tooltip.hide();\n          });\n        };\n        scope.$show = function() {\n          scope.$$postDigest(function() {\n            $tooltip.show();\n          });\n        };\n        scope.$toggle = function() {\n          scope.$$postDigest(function() {\n            $tooltip.toggle();\n          });\n        };\n        // Publish isShown as a protected var on scope\n        $tooltip.$isShown = scope.$isShown = false;\n\n        // Private vars\n        var timeout, hoverState;\n\n        // Support contentTemplate option\n        if(options.contentTemplate) {\n          $tooltip.$promise = $tooltip.$promise.then(function(template) {\n            var templateEl = angular.element(template);\n            return fetchTemplate(options.contentTemplate)\n            .then(function(contentTemplate) {\n              var contentEl = findElement('[ng-bind=\"content\"]', templateEl[0]);\n              if(!contentEl.length) contentEl = findElement('[ng-bind=\"title\"]', templateEl[0]);\n              contentEl.removeAttr('ng-bind').html(contentTemplate);\n              return templateEl[0].outerHTML;\n            });\n          });\n        }\n\n        // Fetch, compile then initialize tooltip\n        var tipLinker, tipElement, tipTemplate, tipContainer, tipScope;\n        $tooltip.$promise.then(function(template) {\n          if(angular.isObject(template)) template = template.data;\n          if(options.html) template = template.replace(htmlReplaceRegExp, 'ng-bind-html=\"');\n          template = trim.apply(template);\n          tipTemplate = template;\n          tipLinker = $compile(template);\n          $tooltip.init();\n        });\n\n        $tooltip.init = function() {\n\n          // Options: delay\n          if (options.delay && angular.isNumber(options.delay)) {\n            options.delay = {\n              show: options.delay,\n              hide: options.delay\n            };\n          }\n\n          // Replace trigger on touch devices ?\n          // if(isTouch && options.trigger === defaults.trigger) {\n          //   options.trigger.replace(/hover/g, 'click');\n          // }\n\n          // Options : container\n          if(options.container === 'self') {\n            tipContainer = element;\n          } else if(angular.isElement(options.container)) {\n            tipContainer = options.container;\n          } else if(options.container) {\n            tipContainer = findElement(options.container);\n          }\n\n          // Options: trigger\n          bindTriggerEvents();\n\n          // Options: target\n          if(options.target) {\n            options.target = angular.isElement(options.target) ? options.target : findElement(options.target);\n          }\n\n          // Options: show\n          if(options.show) {\n            scope.$$postDigest(function() {\n              options.trigger === 'focus' ? element[0].focus() : $tooltip.show();\n            });\n          }\n\n        };\n\n        $tooltip.destroy = function() {\n\n          // Unbind events\n          unbindTriggerEvents();\n\n          // Remove element\n          destroyTipElement();\n\n          // Destroy scope\n          scope.$destroy();\n\n        };\n\n        $tooltip.enter = function() {\n\n          clearTimeout(timeout);\n          hoverState = 'in';\n          if (!options.delay || !options.delay.show) {\n            return $tooltip.show();\n          }\n\n          timeout = setTimeout(function() {\n            if (hoverState ==='in') $tooltip.show();\n          }, options.delay.show);\n\n        };\n\n        $tooltip.show = function() {\n          if (!options.bsEnabled || $tooltip.$isShown) return;\n\n          scope.$emit(options.prefixEvent + '.show.before', $tooltip);\n          var parent, after;\n          if (options.container) {\n            parent = tipContainer;\n            if (tipContainer[0].lastChild) {\n              after = angular.element(tipContainer[0].lastChild);\n            } else {\n              after = null;\n            }\n          } else {\n            parent = null;\n            after = element;\n          }\n\n\n          // Hide any existing tipElement\n          if(tipElement) destroyTipElement();\n          // Fetch a cloned element linked from template\n          tipScope = $tooltip.$scope.$new();\n          tipElement = $tooltip.$element = tipLinker(tipScope, function(clonedElement, scope) {});\n\n          // Set the initial positioning.  Make the tooltip invisible\n          // so IE doesn't try to focus on it off screen.\n          tipElement.css({top: '-9999px', left: '-9999px', display: 'block', visibility: 'hidden'});\n\n          // Options: animation\n          if(options.animation) tipElement.addClass(options.animation);\n          // Options: type\n          if(options.type) tipElement.addClass(options.prefixClass + '-' + options.type);\n          // Options: custom classes\n          if(options.customClass) tipElement.addClass(options.customClass);\n\n          // Support v1.3+ $animate\n          // https://github.com/angular/angular.js/commit/bf0f5502b1bbfddc5cdd2f138efd9188b8c652a9\n          var promise = $animate.enter(tipElement, parent, after, enterAnimateCallback);\n          if(promise && promise.then) promise.then(enterAnimateCallback);\n\n          $tooltip.$isShown = scope.$isShown = true;\n          safeDigest(scope);\n          $$rAF(function () {\n            $tooltip.$applyPlacement();\n\n            // Once placed, make the tooltip visible\n            if(tipElement) tipElement.css({visibility: 'visible'});\n          }); // var a = bodyEl.offsetWidth + 1; ?\n\n          // Bind events\n          if(options.keyboard) {\n            if(options.trigger !== 'focus') {\n              $tooltip.focus();\n            }\n            bindKeyboardEvents();\n          }\n\n          if(options.autoClose) {\n            bindAutoCloseEvents();\n          }\n\n        };\n\n        function enterAnimateCallback() {\n          scope.$emit(options.prefixEvent + '.show', $tooltip);\n        }\n\n        $tooltip.leave = function() {\n\n          clearTimeout(timeout);\n          hoverState = 'out';\n          if (!options.delay || !options.delay.hide) {\n            return $tooltip.hide();\n          }\n          timeout = setTimeout(function () {\n            if (hoverState === 'out') {\n              $tooltip.hide();\n            }\n          }, options.delay.hide);\n\n        };\n\n        var _blur;\n        var _tipToHide;\n        $tooltip.hide = function(blur) {\n\n          if(!$tooltip.$isShown) return;\n          scope.$emit(options.prefixEvent + '.hide.before', $tooltip);\n\n          // store blur value for leaveAnimateCallback to use\n          _blur = blur;\n\n          // store current tipElement reference to use\n          // in leaveAnimateCallback\n          _tipToHide = tipElement;\n\n          // Support v1.3+ $animate\n          // https://github.com/angular/angular.js/commit/bf0f5502b1bbfddc5cdd2f138efd9188b8c652a9\n          var promise = $animate.leave(tipElement, leaveAnimateCallback);\n          if(promise && promise.then) promise.then(leaveAnimateCallback);\n\n          $tooltip.$isShown = scope.$isShown = false;\n          safeDigest(scope);\n\n          // Unbind events\n          if(options.keyboard && tipElement !== null) {\n            unbindKeyboardEvents();\n          }\n\n          if(options.autoClose && tipElement !== null) {\n            unbindAutoCloseEvents();\n          }\n        };\n\n        function leaveAnimateCallback() {\n          scope.$emit(options.prefixEvent + '.hide', $tooltip);\n\n          // check if current tipElement still references\n          // the same element when hide was called\n          if (tipElement === _tipToHide) {\n            // Allow to blur the input when hidden, like when pressing enter key\n            if(_blur && options.trigger === 'focus') {\n              return element[0].blur();\n            }\n\n            // clean up child scopes\n            destroyTipElement();\n          }\n        }\n\n        $tooltip.toggle = function() {\n          $tooltip.$isShown ? $tooltip.leave() : $tooltip.enter();\n        };\n\n        $tooltip.focus = function() {\n          tipElement[0].focus();\n        };\n\n        $tooltip.setEnabled = function(isEnabled) {\n          options.bsEnabled = isEnabled;\n        };\n\n        // Protected methods\n\n        $tooltip.$applyPlacement = function() {\n          if(!tipElement) return;\n\n          // Determine if we're doing an auto or normal placement\n          var placement = options.placement,\n              autoToken = /\\s?auto?\\s?/i,\n              autoPlace  = autoToken.test(placement);\n\n          if (autoPlace) {\n            placement = placement.replace(autoToken, '') || defaults.placement;\n          }\n\n          // Need to add the position class before we get\n          // the offsets\n          tipElement.addClass(options.placement);\n\n          // Get the position of the target element\n          // and the height and width of the tooltip so we can center it.\n          var elementPosition = getPosition(),\n              tipWidth = tipElement.prop('offsetWidth'),\n              tipHeight = tipElement.prop('offsetHeight');\n\n          // If we're auto placing, we need to check the positioning\n          if (autoPlace) {\n            var originalPlacement = placement;\n            var container = options.container ? angular.element(document.querySelector(options.container)) : element.parent();\n            var containerPosition = getPosition(container);\n\n            // Determine if the vertical placement\n            if (originalPlacement.indexOf('bottom') >= 0 && elementPosition.bottom + tipHeight > containerPosition.bottom) {\n              placement = originalPlacement.replace('bottom', 'top');\n            } else if (originalPlacement.indexOf('top') >= 0 && elementPosition.top - tipHeight < containerPosition.top) {\n              placement = originalPlacement.replace('top', 'bottom');\n            }\n\n            // Determine the horizontal placement\n            // The exotic placements of left and right are opposite of the standard placements.  Their arrows are put on the left/right\n            // and flow in the opposite direction of their placement.\n            if ((originalPlacement === 'right' || originalPlacement === 'bottom-left' || originalPlacement === 'top-left') &&\n                elementPosition.right + tipWidth > containerPosition.width) {\n\n              placement = originalPlacement === 'right' ? 'left' : placement.replace('left', 'right');\n            } else if ((originalPlacement === 'left' || originalPlacement === 'bottom-right' || originalPlacement === 'top-right') &&\n                elementPosition.left - tipWidth < containerPosition.left) {\n\n              placement = originalPlacement === 'left' ? 'right' : placement.replace('right', 'left');\n            }\n\n            tipElement.removeClass(originalPlacement).addClass(placement);\n          }\n\n          // Get the tooltip's top and left coordinates to center it with this directive.\n          var tipPosition = getCalculatedOffset(placement, elementPosition, tipWidth, tipHeight);\n          applyPlacementCss(tipPosition.top, tipPosition.left);\n        };\n\n        $tooltip.$onKeyUp = function(evt) {\n          if (evt.which === 27 && $tooltip.$isShown) {\n            $tooltip.hide();\n            evt.stopPropagation();\n          }\n        };\n\n        $tooltip.$onFocusKeyUp = function(evt) {\n          if (evt.which === 27) {\n            element[0].blur();\n            evt.stopPropagation();\n          }\n        };\n\n        $tooltip.$onFocusElementMouseDown = function(evt) {\n          evt.preventDefault();\n          evt.stopPropagation();\n          // Some browsers do not auto-focus buttons (eg. Safari)\n          $tooltip.$isShown ? element[0].blur() : element[0].focus();\n        };\n\n        // bind/unbind events\n        function bindTriggerEvents() {\n          var triggers = options.trigger.split(' ');\n          angular.forEach(triggers, function(trigger) {\n            if(trigger === 'click') {\n              element.on('click', $tooltip.toggle);\n            } else if(trigger !== 'manual') {\n              element.on(trigger === 'hover' ? 'mouseenter' : 'focus', $tooltip.enter);\n              element.on(trigger === 'hover' ? 'mouseleave' : 'blur', $tooltip.leave);\n              nodeName === 'button' && trigger !== 'hover' && element.on(isTouch ? 'touchstart' : 'mousedown', $tooltip.$onFocusElementMouseDown);\n            }\n          });\n        }\n\n        function unbindTriggerEvents() {\n          var triggers = options.trigger.split(' ');\n          for (var i = triggers.length; i--;) {\n            var trigger = triggers[i];\n            if(trigger === 'click') {\n              element.off('click', $tooltip.toggle);\n            } else if(trigger !== 'manual') {\n              element.off(trigger === 'hover' ? 'mouseenter' : 'focus', $tooltip.enter);\n              element.off(trigger === 'hover' ? 'mouseleave' : 'blur', $tooltip.leave);\n              nodeName === 'button' && trigger !== 'hover' && element.off(isTouch ? 'touchstart' : 'mousedown', $tooltip.$onFocusElementMouseDown);\n            }\n          }\n        }\n\n        function bindKeyboardEvents() {\n          if(options.trigger !== 'focus') {\n            tipElement.on('keyup', $tooltip.$onKeyUp);\n          } else {\n            element.on('keyup', $tooltip.$onFocusKeyUp);\n          }\n        }\n\n        function unbindKeyboardEvents() {\n          if(options.trigger !== 'focus') {\n            tipElement.off('keyup', $tooltip.$onKeyUp);\n          } else {\n            element.off('keyup', $tooltip.$onFocusKeyUp);\n          }\n        }\n\n        var _autoCloseEventsBinded = false;\n        function bindAutoCloseEvents() {\n          // use timeout to hookup the events to prevent\n          // event bubbling from being processed imediately.\n          $timeout(function() {\n            // Stop propagation when clicking inside tooltip\n            tipElement.on('click', stopEventPropagation);\n\n            // Hide when clicking outside tooltip\n            $body.on('click', $tooltip.hide);\n\n            _autoCloseEventsBinded = true;\n          }, 0, false);\n        }\n\n        function unbindAutoCloseEvents() {\n          if (_autoCloseEventsBinded) {\n            tipElement.off('click', stopEventPropagation);\n            $body.off('click', $tooltip.hide);\n            _autoCloseEventsBinded = false;\n          }\n        }\n\n        function stopEventPropagation(event) {\n          event.stopPropagation();\n        }\n\n        // Private methods\n\n        function getPosition($element) {\n          $element = $element || (options.target || element);\n\n          var el = $element[0];\n\n          var elRect = el.getBoundingClientRect();\n          if (elRect.width === null) {\n            // width and height are missing in IE8, so compute them manually; see https://github.com/twbs/bootstrap/issues/14093\n            elRect = angular.extend({}, elRect, { width: elRect.right - elRect.left, height: elRect.bottom - elRect.top });\n          }\n\n          var elPos;\n          if (options.container === 'body') {\n            elPos = dimensions.offset(el);\n          } else {\n            elPos = dimensions.position(el);\n          }\n\n          return angular.extend({}, elRect, elPos);\n        }\n\n        function getCalculatedOffset(placement, position, actualWidth, actualHeight) {\n          var offset;\n          var split = placement.split('-');\n\n          switch (split[0]) {\n          case 'right':\n            offset = {\n              top: position.top + position.height / 2 - actualHeight / 2,\n              left: position.left + position.width\n            };\n            break;\n          case 'bottom':\n            offset = {\n              top: position.top + position.height,\n              left: position.left + position.width / 2 - actualWidth / 2\n            };\n            break;\n          case 'left':\n            offset = {\n              top: position.top + position.height / 2 - actualHeight / 2,\n              left: position.left - actualWidth\n            };\n            break;\n          default:\n            offset = {\n              top: position.top - actualHeight,\n              left: position.left + position.width / 2 - actualWidth / 2\n            };\n            break;\n          }\n\n          if(!split[1]) {\n            return offset;\n          }\n\n          // Add support for corners @todo css\n          if(split[0] === 'top' || split[0] === 'bottom') {\n            switch (split[1]) {\n            case 'left':\n              offset.left = position.left;\n              break;\n            case 'right':\n              offset.left =  position.left + position.width - actualWidth;\n            }\n          } else if(split[0] === 'left' || split[0] === 'right') {\n            switch (split[1]) {\n            case 'top':\n              offset.top = position.top - actualHeight;\n              break;\n            case 'bottom':\n              offset.top = position.top + position.height;\n            }\n          }\n\n          return offset;\n        }\n\n        function applyPlacementCss(top, left) {\n          tipElement.css({ top: top + 'px', left: left + 'px' });\n        }\n\n        function destroyTipElement() {\n          // Cancel pending callbacks\n          clearTimeout(timeout);\n\n          if($tooltip.$isShown && tipElement !== null) {\n            if(options.autoClose) {\n              unbindAutoCloseEvents();\n            }\n\n            if(options.keyboard) {\n              unbindKeyboardEvents();\n            }\n          }\n\n          if(tipScope) {\n            tipScope.$destroy();\n            tipScope = null;\n          }\n\n          if(tipElement) {\n            tipElement.remove();\n            tipElement = $tooltip.$element = null;\n          }\n        }\n\n        return $tooltip;\n\n      }\n\n      // Helper functions\n\n      function safeDigest(scope) {\n        scope.$$phase || (scope.$root && scope.$root.$$phase) || scope.$digest();\n      }\n\n      function findElement(query, element) {\n        return angular.element((element || document).querySelectorAll(query));\n      }\n\n      var fetchPromises = {};\n      function fetchTemplate(template) {\n        if(fetchPromises[template]) return fetchPromises[template];\n        return (fetchPromises[template] = $q.when($templateCache.get(template) || $http.get(template))\n        .then(function(res) {\n          if(angular.isObject(res)) {\n            $templateCache.put(template, res.data);\n            return res.data;\n          }\n          return res;\n        }));\n      }\n\n      return TooltipFactory;\n\n    }];\n\n  })\n\n  .directive('bsTooltip', [\"$window\", \"$location\", \"$sce\", \"$tooltip\", \"$$rAF\", function($window, $location, $sce, $tooltip, $$rAF) {\n\n    return {\n      restrict: 'EAC',\n      scope: true,\n      link: function postLink(scope, element, attr, transclusion) {\n\n        // Directive options\n        var options = {scope: scope};\n        angular.forEach(['template', 'contentTemplate', 'placement', 'container', 'target', 'delay', 'trigger', 'keyboard', 'html', 'animation', 'backdropAnimation', 'type', 'customClass', 'id'], function(key) {\n          if(angular.isDefined(attr[key])) options[key] = attr[key];\n        });\n\n        // overwrite inherited title value when no value specified\n        // fix for angular 1.3.1 531a8de72c439d8ddd064874bf364c00cedabb11\n        if (!scope.hasOwnProperty('title')){\n          scope.title = '';\n        }\n\n        // Observe scope attributes for change\n        attr.$observe('title', function(newValue) {\n          if (angular.isDefined(newValue) || !scope.hasOwnProperty('title')) {\n            var oldValue = scope.title;\n            scope.title = $sce.trustAsHtml(newValue);\n            angular.isDefined(oldValue) && $$rAF(function() {\n              tooltip && tooltip.$applyPlacement();\n            });\n          }\n        });\n\n        // Support scope as an object\n        attr.bsTooltip && scope.$watch(attr.bsTooltip, function(newValue, oldValue) {\n          if(angular.isObject(newValue)) {\n            angular.extend(scope, newValue);\n          } else {\n            scope.title = newValue;\n          }\n          angular.isDefined(oldValue) && $$rAF(function() {\n            tooltip && tooltip.$applyPlacement();\n          });\n        }, true);\n\n        // Visibility binding support\n        attr.bsShow && scope.$watch(attr.bsShow, function(newValue, oldValue) {\n          if(!tooltip || !angular.isDefined(newValue)) return;\n          if(angular.isString(newValue)) newValue = !!newValue.match(/true|,?(tooltip),?/i);\n          newValue === true ? tooltip.show() : tooltip.hide();\n        });\n\n        // Enabled binding support\n        attr.bsEnabled && scope.$watch(attr.bsEnabled, function(newValue, oldValue) {\n          // console.warn('scope.$watch(%s)', attr.bsEnabled, newValue, oldValue);\n          if(!tooltip || !angular.isDefined(newValue)) return;\n          if(angular.isString(newValue)) newValue = !!newValue.match(/true|1|,?(tooltip),?/i);\n          newValue === false ? tooltip.setEnabled(false) : tooltip.setEnabled(true);\n        });\n\n        // Initialize popover\n        var tooltip = $tooltip(element, options);\n\n        // Garbage collection\n        scope.$on('$destroy', function() {\n          if(tooltip) tooltip.destroy();\n          options = null;\n          tooltip = null;\n        });\n\n      }\n    };\n\n  }]);\n\n// Source: typeahead.js\nangular.module('mgcrea.ngStrap.typeahead', ['mgcrea.ngStrap.tooltip', 'mgcrea.ngStrap.helpers.parseOptions'])\n\n  .provider('$typeahead', function() {\n\n    var defaults = this.defaults = {\n      animation: 'am-fade',\n      prefixClass: 'typeahead',\n      prefixEvent: '$typeahead',\n      placement: 'bottom-left',\n      template: 'typeahead/typeahead.tpl.html',\n      trigger: 'focus',\n      container: false,\n      keyboard: true,\n      html: false,\n      delay: 0,\n      minLength: 1,\n      filter: 'filter',\n      limit: 6,\n      comparator: ''\n    };\n\n    this.$get = [\"$window\", \"$rootScope\", \"$tooltip\", \"$timeout\", function($window, $rootScope, $tooltip, $timeout) {\n\n      var bodyEl = angular.element($window.document.body);\n\n      function TypeaheadFactory(element, controller, config) {\n\n        var $typeahead = {};\n\n        // Common vars\n        var options = angular.extend({}, defaults, config);\n\n        $typeahead = $tooltip(element, options);\n        var parentScope = config.scope;\n        var scope = $typeahead.$scope;\n\n        scope.$resetMatches = function(){\n          scope.$matches = [];\n          scope.$activeIndex = 0;\n        };\n        scope.$resetMatches();\n\n        scope.$activate = function(index) {\n          scope.$$postDigest(function() {\n            $typeahead.activate(index);\n          });\n        };\n\n        scope.$select = function(index, evt) {\n          scope.$$postDigest(function() {\n            $typeahead.select(index);\n          });\n        };\n\n        scope.$isVisible = function() {\n          return $typeahead.$isVisible();\n        };\n\n        // Public methods\n\n        $typeahead.update = function(matches) {\n          scope.$matches = matches;\n          if(scope.$activeIndex >= matches.length) {\n            scope.$activeIndex = 0;\n          }\n        };\n\n        $typeahead.activate = function(index) {\n          scope.$activeIndex = index;\n        };\n\n        $typeahead.select = function(index) {\n          var value = scope.$matches[index].value;\n          // console.log('$setViewValue', value);\n          controller.$setViewValue(value);\n          controller.$render();\n          scope.$resetMatches();\n          if(parentScope) parentScope.$digest();\n          // Emit event\n          scope.$emit(options.prefixEvent + '.select', value, index, $typeahead);\n        };\n\n        // Protected methods\n\n        $typeahead.$isVisible = function() {\n          if(!options.minLength || !controller) {\n            return !!scope.$matches.length;\n          }\n          // minLength support\n          return scope.$matches.length && angular.isString(controller.$viewValue) && controller.$viewValue.length >= options.minLength;\n        };\n\n        $typeahead.$getIndex = function(value) {\n          var l = scope.$matches.length, i = l;\n          if(!l) return;\n          for(i = l; i--;) {\n            if(scope.$matches[i].value === value) break;\n          }\n          if(i < 0) return;\n          return i;\n        };\n\n        $typeahead.$onMouseDown = function(evt) {\n          // Prevent blur on mousedown\n          evt.preventDefault();\n          evt.stopPropagation();\n        };\n\n        $typeahead.$onKeyDown = function(evt) {\n          if(!/(38|40|13)/.test(evt.keyCode)) return;\n\n          // Let ngSubmit pass if the typeahead tip is hidden\n          if($typeahead.$isVisible()) {\n            evt.preventDefault();\n            evt.stopPropagation();\n          }\n\n          // Select with enter\n          if(evt.keyCode === 13 && scope.$matches.length) {\n            $typeahead.select(scope.$activeIndex);\n          }\n\n          // Navigate with keyboard\n          else if(evt.keyCode === 38 && scope.$activeIndex > 0) scope.$activeIndex--;\n          else if(evt.keyCode === 40 && scope.$activeIndex < scope.$matches.length - 1) scope.$activeIndex++;\n          else if(angular.isUndefined(scope.$activeIndex)) scope.$activeIndex = 0;\n          scope.$digest();\n        };\n\n        // Overrides\n\n        var show = $typeahead.show;\n        $typeahead.show = function() {\n          show();\n          // use timeout to hookup the events to prevent\n          // event bubbling from being processed imediately.\n          $timeout(function() {\n            $typeahead.$element.on('mousedown', $typeahead.$onMouseDown);\n            if(options.keyboard) {\n              element.on('keydown', $typeahead.$onKeyDown);\n            }\n          }, 0, false);\n        };\n\n        var hide = $typeahead.hide;\n        $typeahead.hide = function() {\n          $typeahead.$element.off('mousedown', $typeahead.$onMouseDown);\n          if(options.keyboard) {\n            element.off('keydown', $typeahead.$onKeyDown);\n          }\n          hide();\n        };\n\n        return $typeahead;\n\n      }\n\n      TypeaheadFactory.defaults = defaults;\n      return TypeaheadFactory;\n\n    }];\n\n  })\n\n  .directive('bsTypeahead', [\"$window\", \"$parse\", \"$q\", \"$typeahead\", \"$parseOptions\", function($window, $parse, $q, $typeahead, $parseOptions) {\n\n    var defaults = $typeahead.defaults;\n\n    return {\n      restrict: 'EAC',\n      require: 'ngModel',\n      link: function postLink(scope, element, attr, controller) {\n\n        // Directive options\n        var options = {scope: scope};\n        angular.forEach(['placement', 'container', 'delay', 'trigger', 'keyboard', 'html', 'animation', 'template', 'filter', 'limit', 'minLength', 'watchOptions', 'selectMode', 'comparator', 'id'], function(key) {\n          if(angular.isDefined(attr[key])) options[key] = attr[key];\n        });\n\n        // Build proper ngOptions\n        var filter = options.filter || defaults.filter;\n        var limit = options.limit || defaults.limit;\n        var comparator = options.comparator || defaults.comparator;\n\n        var ngOptions = attr.ngOptions;\n        if(filter) ngOptions += ' | ' + filter + ':$viewValue';\n        if (comparator) ngOptions += ':' + comparator;\n        if(limit) ngOptions += ' | limitTo:' + limit;\n        var parsedOptions = $parseOptions(ngOptions);\n\n        // Initialize typeahead\n        var typeahead = $typeahead(element, controller, options);\n\n        // Watch options on demand\n        if(options.watchOptions) {\n          // Watch ngOptions values before filtering for changes, drop function calls\n          var watchedOptions = parsedOptions.$match[7].replace(/\\|.+/, '').replace(/\\(.*\\)/g, '').trim();\n          scope.$watch(watchedOptions, function (newValue, oldValue) {\n            // console.warn('scope.$watch(%s)', watchedOptions, newValue, oldValue);\n            parsedOptions.valuesFn(scope, controller).then(function (values) {\n              typeahead.update(values);\n              controller.$render();\n            });\n          }, true);\n        }\n\n        // Watch model for changes\n        scope.$watch(attr.ngModel, function(newValue, oldValue) {\n          // console.warn('$watch', element.attr('ng-model'), newValue);\n          scope.$modelValue = newValue; // Publish modelValue on scope for custom templates\n          parsedOptions.valuesFn(scope, controller)\n          .then(function(values) {\n            // Prevent input with no future prospect if selectMode is truthy\n            // @TODO test selectMode\n            if(options.selectMode && !values.length && newValue.length > 0) {\n              controller.$setViewValue(controller.$viewValue.substring(0, controller.$viewValue.length - 1));\n              return;\n            }\n            if(values.length > limit) values = values.slice(0, limit);\n            var isVisible = typeahead.$isVisible();\n            isVisible && typeahead.update(values);\n            // Do not re-queue an update if a correct value has been selected\n            if(values.length === 1 && values[0].value === newValue) return;\n            !isVisible && typeahead.update(values);\n            // Queue a new rendering that will leverage collection loading\n            controller.$render();\n          });\n        });\n\n        // modelValue -> $formatters -> viewValue\n        controller.$formatters.push(function(modelValue) {\n          // console.warn('$formatter(\"%s\"): modelValue=%o (%o)', element.attr('ng-model'), modelValue, typeof modelValue);\n          var displayValue = parsedOptions.displayValue(modelValue);\n          return displayValue === undefined ? '' : displayValue;\n        });\n\n        // Model rendering in view\n        controller.$render = function () {\n          // console.warn('$render', element.attr('ng-model'), 'controller.$modelValue', typeof controller.$modelValue, controller.$modelValue, 'controller.$viewValue', typeof controller.$viewValue, controller.$viewValue);\n          if(controller.$isEmpty(controller.$viewValue)) return element.val('');\n          var index = typeahead.$getIndex(controller.$modelValue);\n          var selected = angular.isDefined(index) ? typeahead.$scope.$matches[index].label : controller.$viewValue;\n          selected = angular.isObject(selected) ? parsedOptions.displayValue(selected) : selected;\n          element.val(selected ? selected.toString().replace(/<(?:.|\\n)*?>/gm, '').trim() : '');\n        };\n\n        // Garbage collection\n        scope.$on('$destroy', function() {\n          if (typeahead) typeahead.destroy();\n          options = null;\n          typeahead = null;\n        });\n\n      }\n    };\n\n  }]);\n\n})(window, document);\n"
  },
  {
    "path": "flowable-ui-web/idm/libs/angular-strap_2.1.6/angular-strap.tpl.js",
    "content": "/**\n * angular-strap\n * @version v2.1.6 - 2015-01-11\n * @link http://mgcrea.github.io/angular-strap\n * @author Olivier Louvignes (olivier@mg-crea.com)\n * @license MIT License, http://www.opensource.org/licenses/MIT\n */\n(function(window, document, undefined) {\n'use strict';\n\n// Source: alert.tpl.js\nangular.module('mgcrea.ngStrap.alert').run(['$templateCache', function($templateCache) {\n\n  $templateCache.put('alert/alert.tpl.html', '<div class=\"alert\" ng-class=\"[type ? \\'alert-\\' + type : null]\"><button type=\"button\" class=\"close\" ng-if=\"dismissable\" ng-click=\"$hide()\">&times;</button> <strong ng-bind=\"title\"></strong>&nbsp;<span ng-bind-html=\"content\"></span></div>');\n\n}]);\n\n// Source: aside.tpl.js\nangular.module('mgcrea.ngStrap.aside').run(['$templateCache', function($templateCache) {\n\n  $templateCache.put('aside/aside.tpl.html', '<div class=\"aside\" tabindex=\"-1\" role=\"dialog\"><div class=\"aside-dialog\"><div class=\"aside-content\"><div class=\"aside-header\" ng-show=\"title\"><button type=\"button\" class=\"close\" ng-click=\"$hide()\">&times;</button><h4 class=\"aside-title\" ng-bind=\"title\"></h4></div><div class=\"aside-body\" ng-bind=\"content\"></div><div class=\"aside-footer\"><button type=\"button\" class=\"btn btn-default\" ng-click=\"$hide()\">Close</button></div></div></div></div>');\n\n}]);\n\n// Source: datepicker.tpl.js\nangular.module('mgcrea.ngStrap.datepicker').run(['$templateCache', function($templateCache) {\n\n  $templateCache.put('datepicker/datepicker.tpl.html', '<div class=\"dropdown-menu datepicker\" ng-class=\"\\'datepicker-mode-\\' + $mode\" style=\"max-width: 320px\"><table style=\"table-layout: fixed; height: 100%; width: 100%\"><thead><tr class=\"text-center\"><th><button tabindex=\"-1\" type=\"button\" class=\"btn btn-default pull-left\" ng-click=\"$selectPane(-1)\"><i class=\"{{$iconLeft}}\"></i></button></th><th colspan=\"{{ rows[0].length - 2 }}\"><button tabindex=\"-1\" type=\"button\" class=\"btn btn-default btn-block text-strong\" ng-click=\"$toggleMode()\"><strong style=\"text-transform: capitalize\" ng-bind=\"title\"></strong></button></th><th><button tabindex=\"-1\" type=\"button\" class=\"btn btn-default pull-right\" ng-click=\"$selectPane(+1)\"><i class=\"{{$iconRight}}\"></i></button></th></tr><tr ng-show=\"showLabels\" ng-bind-html=\"labels\"></tr></thead><tbody><tr ng-repeat=\"(i, row) in rows\" height=\"{{ 100 / rows.length }}%\"><td class=\"text-center\" ng-repeat=\"(j, el) in row\"><button tabindex=\"-1\" type=\"button\" class=\"btn btn-default\" style=\"width: 100%\" ng-class=\"{\\'btn-primary\\': el.selected, \\'btn-info btn-today\\': el.isToday && !el.selected}\" ng-click=\"$select(el.date)\" ng-disabled=\"el.disabled\"><span ng-class=\"{\\'text-muted\\': el.muted}\" ng-bind=\"el.label\"></span></button></td></tr></tbody></table></div>');\n\n}]);\n\n// Source: dropdown.tpl.js\nangular.module('mgcrea.ngStrap.dropdown').run(['$templateCache', function($templateCache) {\n\n  $templateCache.put('dropdown/dropdown.tpl.html', '<ul tabindex=\"-1\" class=\"dropdown-menu\" role=\"menu\"><li role=\"presentation\" ng-class=\"{divider: item.divider}\" ng-repeat=\"item in content\"><a role=\"menuitem\" tabindex=\"-1\" ng-href=\"{{item.href}}\" ng-if=\"!item.divider && item.href\" target=\"{{item.target || \\'\\'}}\" ng-bind=\"item.text\"></a> <a role=\"menuitem\" tabindex=\"-1\" href=\"javascript:void(0)\" ng-if=\"!item.divider && item.click\" ng-click=\"$eval(item.click);$hide()\" ng-bind=\"item.text\"></a></li></ul>');\n\n}]);\n\n// Source: modal.tpl.js\nangular.module('mgcrea.ngStrap.modal').run(['$templateCache', function($templateCache) {\n\n  $templateCache.put('modal/modal.tpl.html', '<div class=\"modal\" tabindex=\"-1\" role=\"dialog\"><div class=\"modal-dialog\"><div class=\"modal-content\"><div class=\"modal-header\" ng-show=\"title\"><button type=\"button\" class=\"close\" ng-click=\"$hide()\">&times;</button><h4 class=\"modal-title\" ng-bind=\"title\"></h4></div><div class=\"modal-body\" ng-bind=\"content\"></div><div class=\"modal-footer\"><button type=\"button\" class=\"btn btn-default\" ng-click=\"$hide()\">Close</button></div></div></div></div>');\n\n}]);\n\n// Source: popover.tpl.js\nangular.module('mgcrea.ngStrap.popover').run(['$templateCache', function($templateCache) {\n\n  $templateCache.put('popover/popover.tpl.html', '<div class=\"popover\"><div class=\"arrow\"></div><h3 class=\"popover-title\" ng-bind=\"title\" ng-show=\"title\"></h3><div class=\"popover-content\" ng-bind=\"content\"></div></div>');\n\n}]);\n\n// Source: select.tpl.js\nangular.module('mgcrea.ngStrap.select').run(['$templateCache', function($templateCache) {\n\n  $templateCache.put('select/select.tpl.html', '<ul tabindex=\"-1\" class=\"select dropdown-menu\" ng-show=\"$isVisible()\" role=\"select\"><li ng-if=\"$showAllNoneButtons\"><div class=\"btn-group\" style=\"margin-bottom: 5px; margin-left: 5px\"><button type=\"button\" class=\"btn btn-default btn-xs\" ng-click=\"$selectAll()\">{{$allText}}</button> <button type=\"button\" class=\"btn btn-default btn-xs\" ng-click=\"$selectNone()\">{{$noneText}}</button></div></li><li role=\"presentation\" ng-repeat=\"match in $matches\" ng-class=\"{active: $isActive($index)}\"><a style=\"cursor: default\" role=\"menuitem\" tabindex=\"-1\" ng-click=\"$select($index, $event)\"><i class=\"{{$iconCheckmark}} pull-right\" ng-if=\"$isMultiple && $isActive($index)\"></i> <span ng-bind=\"match.label\"></span></a></li></ul>');\n\n}]);\n\n// Source: tab.tpl.js\nangular.module('mgcrea.ngStrap.tab').run(['$templateCache', function($templateCache) {\n\n  $templateCache.put('tab/tab.tpl.html', '<ul class=\"nav\" ng-class=\"$navClass\" role=\"tablist\"><li ng-repeat=\"$pane in $panes track by $index\" ng-class=\"$index == $panes.$active ? $activeClass : \\'\\'\"><a role=\"tab\" data-toggle=\"tab\" ng-click=\"$setActive($index)\" data-index=\"{{ $index }}\" ng-bind-html=\"$pane.title\"></a></li></ul><div ng-transclude class=\"tab-content\"></div>');\n\n}]);\n\n// Source: timepicker.tpl.js\nangular.module('mgcrea.ngStrap.timepicker').run(['$templateCache', function($templateCache) {\n\n  $templateCache.put('timepicker/timepicker.tpl.html', '<div class=\"dropdown-menu timepicker\" style=\"min-width: 0px;width: auto\"><table height=\"100%\"><thead><tr class=\"text-center\"><th><button tabindex=\"-1\" type=\"button\" class=\"btn btn-default pull-left\" ng-click=\"$arrowAction(-1, 0)\"><i class=\"{{ $iconUp }}\"></i></button></th><th>&nbsp;</th><th><button tabindex=\"-1\" type=\"button\" class=\"btn btn-default pull-left\" ng-click=\"$arrowAction(-1, 1)\"><i class=\"{{ $iconUp }}\"></i></button></th></tr></thead><tbody><tr ng-repeat=\"(i, row) in rows\"><td class=\"text-center\"><button tabindex=\"-1\" style=\"width: 100%\" type=\"button\" class=\"btn btn-default\" ng-class=\"{\\'btn-primary\\': row[0].selected}\" ng-click=\"$select(row[0].date, 0)\" ng-disabled=\"row[0].disabled\"><span ng-class=\"{\\'text-muted\\': row[0].muted}\" ng-bind=\"row[0].label\"></span></button></td><td><span ng-bind=\"i == midIndex ? timeSeparator : \\' \\'\"></span></td><td class=\"text-center\"><button tabindex=\"-1\" ng-if=\"row[1].date\" style=\"width: 100%\" type=\"button\" class=\"btn btn-default\" ng-class=\"{\\'btn-primary\\': row[1].selected}\" ng-click=\"$select(row[1].date, 1)\" ng-disabled=\"row[1].disabled\"><span ng-class=\"{\\'text-muted\\': row[1].muted}\" ng-bind=\"row[1].label\"></span></button></td><td ng-if=\"showAM\">&nbsp;</td><td ng-if=\"showAM\"><button tabindex=\"-1\" ng-show=\"i == midIndex - !isAM * 1\" style=\"width: 100%\" type=\"button\" ng-class=\"{\\'btn-primary\\': !!isAM}\" class=\"btn btn-default\" ng-click=\"$switchMeridian()\" ng-disabled=\"el.disabled\">AM</button> <button tabindex=\"-1\" ng-show=\"i == midIndex + 1 - !isAM * 1\" style=\"width: 100%\" type=\"button\" ng-class=\"{\\'btn-primary\\': !isAM}\" class=\"btn btn-default\" ng-click=\"$switchMeridian()\" ng-disabled=\"el.disabled\">PM</button></td></tr></tbody><tfoot><tr class=\"text-center\"><th><button tabindex=\"-1\" type=\"button\" class=\"btn btn-default pull-left\" ng-click=\"$arrowAction(1, 0)\"><i class=\"{{ $iconDown }}\"></i></button></th><th>&nbsp;</th><th><button tabindex=\"-1\" type=\"button\" class=\"btn btn-default pull-left\" ng-click=\"$arrowAction(1, 1)\"><i class=\"{{ $iconDown }}\"></i></button></th></tr></tfoot></table></div>');\n\n}]);\n\n// Source: tooltip.tpl.js\nangular.module('mgcrea.ngStrap.tooltip').run(['$templateCache', function($templateCache) {\n\n  $templateCache.put('tooltip/tooltip.tpl.html', '<div class=\"tooltip in\" ng-show=\"title\"><div class=\"tooltip-arrow\"></div><div class=\"tooltip-inner\" ng-bind=\"title\"></div></div>');\n\n}]);\n\n// Source: typeahead.tpl.js\nangular.module('mgcrea.ngStrap.typeahead').run(['$templateCache', function($templateCache) {\n\n  $templateCache.put('typeahead/typeahead.tpl.html', '<ul tabindex=\"-1\" class=\"typeahead dropdown-menu\" ng-show=\"$isVisible()\" role=\"select\"><li role=\"presentation\" ng-repeat=\"match in $matches\" ng-class=\"{active: $index == $activeIndex}\"><a role=\"menuitem\" tabindex=\"-1\" ng-click=\"$select($index, $event)\" ng-bind=\"match.label\"></a></li></ul>');\n\n}]);\n\n\n})(window, document);\n"
  },
  {
    "path": "flowable-ui-web/idm/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": "flowable-ui-web/idm/libs/angular-translate-loader-static-files/angular-translate-loader-static-files.js",
    "content": "/*!\n * angular-translate - v2.15.1 - 2017-03-04\n * \n * Copyright (c) 2017 The angular-translate team, Pascal Precht; Licensed MIT\n */\n(function (root, factory) {\n  if (typeof define === 'function' && define.amd) {\n    // AMD. Register as an anonymous module unless amdModuleId is set\n    define([], function () {\n      return (factory());\n    });\n  } else if (typeof exports === 'object') {\n    // Node. Does not work with strict CommonJS, but\n    // only CommonJS-like environments that support module.exports,\n    // like Node.\n    module.exports = factory();\n  } else {\n    factory();\n  }\n}(this, function () {\n\n$translateStaticFilesLoader.$inject = ['$q', '$http'];\nangular.module('pascalprecht.translate')\n/**\n * @ngdoc object\n * @name pascalprecht.translate.$translateStaticFilesLoader\n * @requires $q\n * @requires $http\n *\n * @description\n * Creates a loading function for a typical static file url pattern:\n * \"lang-en_US.json\", \"lang-de_DE.json\", etc. Using this builder,\n * the response of these urls must be an object of key-value pairs.\n *\n * @param {object} options Options object, which gets prefix, suffix, key, and fileMap\n */\n.factory('$translateStaticFilesLoader', $translateStaticFilesLoader);\n\nfunction $translateStaticFilesLoader($q, $http) {\n\n  'use strict';\n\n  return function (options) {\n\n    if (!options || (!angular.isArray(options.files) && (!angular.isString(options.prefix) || !angular.isString(options.suffix)))) {\n      throw new Error('Couldn\\'t load static files, no files and prefix or suffix specified!');\n    }\n\n    if (!options.files) {\n      options.files = [{\n        prefix: options.prefix,\n        suffix: options.suffix\n      }];\n    }\n\n    var load = function (file) {\n      if (!file || (!angular.isString(file.prefix) || !angular.isString(file.suffix))) {\n        throw new Error('Couldn\\'t load static file, no prefix or suffix specified!');\n      }\n\n      var fileUrl = [\n        file.prefix,\n        options.key,\n        file.suffix\n      ].join('');\n\n      if (angular.isObject(options.fileMap) && options.fileMap[fileUrl]) {\n        fileUrl = options.fileMap[fileUrl];\n      }\n\n      return $http(angular.extend({\n        url: fileUrl,\n        method: 'GET'\n      }, options.$http))\n        .then(function(result) {\n          return result.data;\n        }, function () {\n          return $q.reject(options.key);\n        });\n    };\n\n    var promises = [],\n        length = options.files.length;\n\n    for (var i = 0; i < length; i++) {\n      promises.push(load({\n        prefix: options.files[i].prefix,\n        key: options.key,\n        suffix: options.files[i].suffix\n      }));\n    }\n\n    return $q.all(promises)\n      .then(function (data) {\n        var length = data.length,\n            mergedData = {};\n\n        for (var i = 0; i < length; i++) {\n          for (var key in data[i]) {\n            mergedData[key] = data[i][key];\n          }\n        }\n\n        return mergedData;\n      });\n  };\n}\n\n$translateStaticFilesLoader.displayName = '$translateStaticFilesLoader';\nreturn 'pascalprecht.translate';\n\n}));\n"
  },
  {
    "path": "flowable-ui-web/idm/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": "flowable-ui-web/idm/libs/angular-translate-storage-cookie/angular-translate-storage-cookie.js",
    "content": "/*!\n * angular-translate - v2.15.1 - 2017-03-04\n * \n * Copyright (c) 2017 The angular-translate team, Pascal Precht; Licensed MIT\n */\n(function (root, factory) {\n  if (typeof define === 'function' && define.amd) {\n    // AMD. Register as an anonymous module unless amdModuleId is set\n    define([], function () {\n      return (factory());\n    });\n  } else if (typeof exports === 'object') {\n    // Node. Does not work with strict CommonJS, but\n    // only CommonJS-like environments that support module.exports,\n    // like Node.\n    module.exports = factory();\n  } else {\n    factory();\n  }\n}(this, function () {\n\n$translateCookieStorageFactory.$inject = ['$injector'];\nangular.module('pascalprecht.translate')\n\n/**\n * @ngdoc object\n * @name pascalprecht.translate.$translateCookieStorage\n * @requires $cookieStore\n *\n * @description\n * Abstraction layer for cookieStore. This service is used when telling angular-translate\n * to use cookieStore as storage.\n *\n */\n  .factory('$translateCookieStorage', $translateCookieStorageFactory);\n\nfunction $translateCookieStorageFactory($injector) {\n\n  'use strict';\n\n  // Since AngularJS 1.4, $cookieStore is deprecated\n  var delegate;\n  if (angular.version.major === 1 && angular.version.minor >= 4) {\n    var $cookies = $injector.get('$cookies');\n    delegate = {\n      get : function (key) {\n        return $cookies.get(key);\n      },\n      put : function (key, value) {\n        $cookies.put(key, value);\n      }\n    };\n  } else {\n    var $cookieStore = $injector.get('$cookieStore');\n    delegate = {\n      get : function (key) {\n        return $cookieStore.get(key);\n      },\n      put : function (key, value) {\n        $cookieStore.put(key, value);\n      }\n    };\n  }\n\n  var $translateCookieStorage = {\n\n    /**\n     * @ngdoc function\n     * @name pascalprecht.translate.$translateCookieStorage#get\n     * @methodOf pascalprecht.translate.$translateCookieStorage\n     *\n     * @description\n     * Returns an item from cookieStorage by given name.\n     *\n     * @param {string} name Item name\n     * @return {string} Value of item name\n     */\n    get : function (name) {\n      return delegate.get(name);\n    },\n\n    /**\n     * @ngdoc function\n     * @name pascalprecht.translate.$translateCookieStorage#set\n     * @methodOf pascalprecht.translate.$translateCookieStorage\n     *\n     * @description\n     * Sets an item in cookieStorage by given name.\n     *\n     * @deprecated use #put\n     *\n     * @param {string} name Item name\n     * @param {string} value Item value\n     */\n    set : function (name, value) {\n      delegate.put(name, value);\n    },\n\n    /**\n     * @ngdoc function\n     * @name pascalprecht.translate.$translateCookieStorage#put\n     * @methodOf pascalprecht.translate.$translateCookieStorage\n     *\n     * @description\n     * Sets an item in cookieStorage by given name.\n     *\n     * @param {string} name Item name\n     * @param {string} value Item value\n     */\n    put : function (name, value) {\n      delegate.put(name, value);\n    }\n  };\n\n  return $translateCookieStorage;\n}\n\n$translateCookieStorageFactory.displayName = '$translateCookieStorage';\nreturn 'pascalprecht.translate';\n\n}));\n"
  },
  {
    "path": "flowable-ui-web/idm/libs/angular-translate_2.15.1/angular-translate.js",
    "content": "/*!\n * angular-translate - v2.15.1 - 2017-03-04\n * \n * Copyright (c) 2017 The angular-translate team, Pascal Precht; Licensed MIT\n */\n(function (root, factory) {\n  if (typeof define === 'function' && define.amd) {\n    // AMD. Register as an anonymous module unless amdModuleId is set\n    define([], function () {\n      return (factory());\n    });\n  } else if (typeof exports === 'object') {\n    // Node. Does not work with strict CommonJS, but\n    // only CommonJS-like environments that support module.exports,\n    // like Node.\n    module.exports = factory();\n  } else {\n    factory();\n  }\n}(this, function () {\n\n/**\n * @ngdoc overview\n * @name pascalprecht.translate\n *\n * @description\n * The main module which holds everything together.\n */\nrunTranslate.$inject = ['$translate'];\n$translate.$inject = ['$STORAGE_KEY', '$windowProvider', '$translateSanitizationProvider', 'pascalprechtTranslateOverrider'];\n$translateDefaultInterpolation.$inject = ['$interpolate', '$translateSanitization'];\ntranslateDirective.$inject = ['$translate', '$interpolate', '$compile', '$parse', '$rootScope'];\ntranslateAttrDirective.$inject = ['$translate', '$rootScope'];\ntranslateCloakDirective.$inject = ['$translate', '$rootScope'];\ntranslateFilterFactory.$inject = ['$parse', '$translate'];\n$translationCache.$inject = ['$cacheFactory'];\nangular.module('pascalprecht.translate', ['ng'])\n  .run(runTranslate);\n\nfunction runTranslate($translate) {\n\n  'use strict';\n\n  var key = $translate.storageKey(),\n    storage = $translate.storage();\n\n  var fallbackFromIncorrectStorageValue = function () {\n    var preferred = $translate.preferredLanguage();\n    if (angular.isString(preferred)) {\n      $translate.use(preferred);\n      // $translate.use() will also remember the language.\n      // So, we don't need to call storage.put() here.\n    } else {\n      storage.put(key, $translate.use());\n    }\n  };\n\n  fallbackFromIncorrectStorageValue.displayName = 'fallbackFromIncorrectStorageValue';\n\n  if (storage) {\n    if (!storage.get(key)) {\n      fallbackFromIncorrectStorageValue();\n    } else {\n      $translate.use(storage.get(key))['catch'](fallbackFromIncorrectStorageValue);\n    }\n  } else if (angular.isString($translate.preferredLanguage())) {\n    $translate.use($translate.preferredLanguage());\n  }\n}\n\nrunTranslate.displayName = 'runTranslate';\n\n/**\n * @ngdoc object\n * @name pascalprecht.translate.$translateSanitizationProvider\n *\n * @description\n *\n * Configurations for $translateSanitization\n */\nangular.module('pascalprecht.translate').provider('$translateSanitization', $translateSanitizationProvider);\n\nfunction $translateSanitizationProvider () {\n\n  'use strict';\n\n  var $sanitize,\n      $sce,\n      currentStrategy = null, // TODO change to either 'sanitize', 'escape' or ['sanitize', 'escapeParameters'] in 3.0.\n      hasConfiguredStrategy = false,\n      hasShownNoStrategyConfiguredWarning = false,\n      strategies;\n\n  /**\n   * Definition of a sanitization strategy function\n   * @callback StrategyFunction\n   * @param {string|object} value - value to be sanitized (either a string or an interpolated value map)\n   * @param {string} mode - either 'text' for a string (translation) or 'params' for the interpolated params\n   * @return {string|object}\n   */\n\n  /**\n   * @ngdoc property\n   * @name strategies\n   * @propertyOf pascalprecht.translate.$translateSanitizationProvider\n   *\n   * @description\n   * Following strategies are built-in:\n   * <dl>\n   *   <dt>sanitize</dt>\n   *   <dd>Sanitizes HTML in the translation text using $sanitize</dd>\n   *   <dt>escape</dt>\n   *   <dd>Escapes HTML in the translation</dd>\n   *   <dt>sanitizeParameters</dt>\n   *   <dd>Sanitizes HTML in the values of the interpolation parameters using $sanitize</dd>\n   *   <dt>escapeParameters</dt>\n   *   <dd>Escapes HTML in the values of the interpolation parameters</dd>\n   *   <dt>escaped</dt>\n   *   <dd>Support legacy strategy name 'escaped' for backwards compatibility (will be removed in 3.0)</dd>\n   * </dl>\n   *\n   */\n\n  strategies = {\n    sanitize: function (value, mode/*, context*/) {\n      if (mode === 'text') {\n        value = htmlSanitizeValue(value);\n      }\n      return value;\n    },\n    escape: function (value, mode/*, context*/) {\n      if (mode === 'text') {\n        value = htmlEscapeValue(value);\n      }\n      return value;\n    },\n    sanitizeParameters: function (value, mode/*, context*/) {\n      if (mode === 'params') {\n        value = mapInterpolationParameters(value, htmlSanitizeValue);\n      }\n      return value;\n    },\n    escapeParameters: function (value, mode/*, context*/) {\n      if (mode === 'params') {\n        value = mapInterpolationParameters(value, htmlEscapeValue);\n      }\n      return value;\n    },\n    sce: function (value, mode, context) {\n      if (mode === 'text') {\n        value = htmlTrustValue(value);\n      } else if (mode === 'params') {\n        if (context !== 'filter') {\n          // do html escape in filter context #1101\n          value = mapInterpolationParameters(value, htmlEscapeValue);\n        }\n      }\n      return value;\n    },\n    sceParameters: function (value, mode/*, context*/) {\n      if (mode === 'params') {\n        value = mapInterpolationParameters(value, htmlTrustValue);\n      }\n      return value;\n    }\n  };\n  // Support legacy strategy name 'escaped' for backwards compatibility.\n  // TODO should be removed in 3.0\n  strategies.escaped = strategies.escapeParameters;\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateSanitizationProvider#addStrategy\n   * @methodOf pascalprecht.translate.$translateSanitizationProvider\n   *\n   * @description\n   * Adds a sanitization strategy to the list of known strategies.\n   *\n   * @param {string} strategyName - unique key for a strategy\n   * @param {StrategyFunction} strategyFunction - strategy function\n   * @returns {object} this\n   */\n  this.addStrategy = function (strategyName, strategyFunction) {\n    strategies[strategyName] = strategyFunction;\n    return this;\n  };\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateSanitizationProvider#removeStrategy\n   * @methodOf pascalprecht.translate.$translateSanitizationProvider\n   *\n   * @description\n   * Removes a sanitization strategy from the list of known strategies.\n   *\n   * @param {string} strategyName - unique key for a strategy\n   * @returns {object} this\n   */\n  this.removeStrategy = function (strategyName) {\n    delete strategies[strategyName];\n    return this;\n  };\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateSanitizationProvider#useStrategy\n   * @methodOf pascalprecht.translate.$translateSanitizationProvider\n   *\n   * @description\n   * Selects a sanitization strategy. When an array is provided the strategies will be executed in order.\n   *\n   * @param {string|StrategyFunction|array} strategy The sanitization strategy / strategies which should be used. Either a name of an existing strategy, a custom strategy function, or an array consisting of multiple names and / or custom functions.\n   * @returns {object} this\n   */\n  this.useStrategy = function (strategy) {\n    hasConfiguredStrategy = true;\n    currentStrategy = strategy;\n    return this;\n  };\n\n  /**\n   * @ngdoc object\n   * @name pascalprecht.translate.$translateSanitization\n   * @requires $injector\n   * @requires $log\n   *\n   * @description\n   * Sanitizes interpolation parameters and translated texts.\n   *\n   */\n  this.$get = ['$injector', '$log', function ($injector, $log) {\n\n    var cachedStrategyMap = {};\n\n    var applyStrategies = function (value, mode, context, selectedStrategies) {\n      angular.forEach(selectedStrategies, function (selectedStrategy) {\n        if (angular.isFunction(selectedStrategy)) {\n          value = selectedStrategy(value, mode, context);\n        } else if (angular.isFunction(strategies[selectedStrategy])) {\n          value = strategies[selectedStrategy](value, mode, context);\n        } else if (angular.isString(strategies[selectedStrategy])) {\n          if (!cachedStrategyMap[strategies[selectedStrategy]]) {\n            try {\n              cachedStrategyMap[strategies[selectedStrategy]] = $injector.get(strategies[selectedStrategy]);\n            } catch (e) {\n              cachedStrategyMap[strategies[selectedStrategy]] = function() {};\n              throw new Error('pascalprecht.translate.$translateSanitization: Unknown sanitization strategy: \\'' + selectedStrategy + '\\'');\n            }\n          }\n          value = cachedStrategyMap[strategies[selectedStrategy]](value, mode, context);\n        } else {\n          throw new Error('pascalprecht.translate.$translateSanitization: Unknown sanitization strategy: \\'' + selectedStrategy + '\\'');\n        }\n      });\n      return value;\n    };\n\n    // TODO: should be removed in 3.0\n    var showNoStrategyConfiguredWarning = function () {\n      if (!hasConfiguredStrategy && !hasShownNoStrategyConfiguredWarning) {\n        $log.warn('pascalprecht.translate.$translateSanitization: No sanitization strategy has been configured. This can have serious security implications. See http://angular-translate.github.io/docs/#/guide/19_security for details.');\n        hasShownNoStrategyConfiguredWarning = true;\n      }\n    };\n\n    if ($injector.has('$sanitize')) {\n      $sanitize = $injector.get('$sanitize');\n    }\n    if ($injector.has('$sce')) {\n      $sce = $injector.get('$sce');\n    }\n\n    return {\n      /**\n       * @ngdoc function\n       * @name pascalprecht.translate.$translateSanitization#useStrategy\n       * @methodOf pascalprecht.translate.$translateSanitization\n       *\n       * @description\n       * Selects a sanitization strategy. When an array is provided the strategies will be executed in order.\n       *\n       * @param {string|StrategyFunction|array} strategy The sanitization strategy / strategies which should be used. Either a name of an existing strategy, a custom strategy function, or an array consisting of multiple names and / or custom functions.\n       */\n      useStrategy: (function (self) {\n        return function (strategy) {\n          self.useStrategy(strategy);\n        };\n      })(this),\n\n      /**\n       * @ngdoc function\n       * @name pascalprecht.translate.$translateSanitization#sanitize\n       * @methodOf pascalprecht.translate.$translateSanitization\n       *\n       * @description\n       * Sanitizes a value.\n       *\n       * @param {string|object} value The value which should be sanitized.\n       * @param {string} mode The current sanitization mode, either 'params' or 'text'.\n       * @param {string|StrategyFunction|array} [strategy] Optional custom strategy which should be used instead of the currently selected strategy.\n       * @param {string} [context] The context of this call: filter, service. Default is service\n       * @returns {string|object} sanitized value\n       */\n      sanitize: function (value, mode, strategy, context) {\n        if (!currentStrategy) {\n          showNoStrategyConfiguredWarning();\n        }\n\n        if (!strategy && strategy !== null) {\n          strategy = currentStrategy;\n        }\n\n        if (!strategy) {\n          return value;\n        }\n\n        if (!context) {\n          context = 'service';\n        }\n\n        var selectedStrategies = angular.isArray(strategy) ? strategy : [strategy];\n        return applyStrategies(value, mode, context, selectedStrategies);\n      }\n    };\n  }];\n\n  var htmlEscapeValue = function (value) {\n    var element = angular.element('<div></div>');\n    element.text(value); // not chainable, see #1044\n    return element.html();\n  };\n\n  var htmlSanitizeValue = function (value) {\n    if (!$sanitize) {\n      throw new Error('pascalprecht.translate.$translateSanitization: Error cannot find $sanitize service. Either include the ngSanitize module (https://docs.angularjs.org/api/ngSanitize) or use a sanitization strategy which does not depend on $sanitize, such as \\'escape\\'.');\n    }\n    return $sanitize(value);\n  };\n\n  var htmlTrustValue = function (value) {\n    if (!$sce) {\n      throw new Error('pascalprecht.translate.$translateSanitization: Error cannot find $sce service.');\n    }\n    return $sce.trustAsHtml(value);\n  };\n\n  var mapInterpolationParameters = function (value, iteratee, stack) {\n    if (angular.isDate(value)) {\n      return value;\n    } else if (angular.isObject(value)) {\n      var result = angular.isArray(value) ? [] : {};\n\n      if (!stack) {\n        stack = [];\n      } else {\n        if (stack.indexOf(value) > -1) {\n          throw new Error('pascalprecht.translate.$translateSanitization: Error cannot interpolate parameter due recursive object');\n        }\n      }\n\n      stack.push(value);\n      angular.forEach(value, function (propertyValue, propertyKey) {\n\n        /* Skipping function properties. */\n        if (angular.isFunction(propertyValue)) {\n          return;\n        }\n\n        result[propertyKey] = mapInterpolationParameters(propertyValue, iteratee, stack);\n      });\n      stack.splice(-1, 1); // remove last\n\n      return result;\n    } else if (angular.isNumber(value)) {\n      return value;\n    } else if (!angular.isUndefined(value) && value !== null) {\n      return iteratee(value);\n    } else {\n      return value;\n    }\n  };\n}\n\n/**\n * @ngdoc object\n * @name pascalprecht.translate.$translateProvider\n * @description\n *\n * $translateProvider allows developers to register translation-tables, asynchronous loaders\n * and similar to configure translation behavior directly inside of a module.\n *\n */\nangular.module('pascalprecht.translate')\n  .constant('pascalprechtTranslateOverrider', {})\n  .provider('$translate', $translate);\n\nfunction $translate($STORAGE_KEY, $windowProvider, $translateSanitizationProvider, pascalprechtTranslateOverrider) {\n\n  'use strict';\n\n  var $translationTable = {},\n    $preferredLanguage,\n    $availableLanguageKeys = [],\n    $languageKeyAliases,\n    $fallbackLanguage,\n    $fallbackWasString,\n    $uses,\n    $nextLang,\n    $storageFactory,\n    $storageKey = $STORAGE_KEY,\n    $storagePrefix,\n    $missingTranslationHandlerFactory,\n    $interpolationFactory,\n    $interpolatorFactories = [],\n    $loaderFactory,\n    $cloakClassName = 'translate-cloak',\n    $loaderOptions,\n    $notFoundIndicatorLeft,\n    $notFoundIndicatorRight,\n    $postCompilingEnabled = false,\n    $forceAsyncReloadEnabled = false,\n    $nestedObjectDelimeter = '.',\n    $isReady = false,\n    $keepContent = false,\n    loaderCache,\n    directivePriority = 0,\n    statefulFilter = true,\n    postProcessFn,\n    uniformLanguageTagResolver = 'default',\n    languageTagResolver = {\n      'default' : function (tag) {\n        return (tag || '').split('-').join('_');\n      },\n      java : function (tag) {\n        var temp = (tag || '').split('-').join('_');\n        var parts = temp.split('_');\n        return parts.length > 1 ? (parts[0].toLowerCase() + '_' + parts[1].toUpperCase()) : temp;\n      },\n      bcp47 : function (tag) {\n        var temp = (tag || '').split('_').join('-');\n        var parts = temp.split('-');\n        return parts.length > 1 ? (parts[0].toLowerCase() + '-' + parts[1].toUpperCase()) : temp;\n      },\n      'iso639-1' : function (tag) {\n        var temp = (tag || '').split('_').join('-');\n        var parts = temp.split('-');\n        return parts[0].toLowerCase();\n      }\n    };\n\n  var version = '2.15.1';\n\n  // tries to determine the browsers language\n  var getFirstBrowserLanguage = function () {\n\n    // internal purpose only\n    if (angular.isFunction(pascalprechtTranslateOverrider.getLocale)) {\n      return pascalprechtTranslateOverrider.getLocale();\n    }\n\n    var nav = $windowProvider.$get().navigator,\n      browserLanguagePropertyKeys = ['language', 'browserLanguage', 'systemLanguage', 'userLanguage'],\n      i,\n      language;\n\n    // support for HTML 5.1 \"navigator.languages\"\n    if (angular.isArray(nav.languages)) {\n      for (i = 0; i < nav.languages.length; i++) {\n        language = nav.languages[i];\n        if (language && language.length) {\n          return language;\n        }\n      }\n    }\n\n    // support for other well known properties in browsers\n    for (i = 0; i < browserLanguagePropertyKeys.length; i++) {\n      language = nav[browserLanguagePropertyKeys[i]];\n      if (language && language.length) {\n        return language;\n      }\n    }\n\n    return null;\n  };\n  getFirstBrowserLanguage.displayName = 'angular-translate/service: getFirstBrowserLanguage';\n\n  // tries to determine the browsers locale\n  var getLocale = function () {\n    var locale = getFirstBrowserLanguage() || '';\n    if (languageTagResolver[uniformLanguageTagResolver]) {\n      locale = languageTagResolver[uniformLanguageTagResolver](locale);\n    }\n    return locale;\n  };\n  getLocale.displayName = 'angular-translate/service: getLocale';\n\n  /**\n   * @name indexOf\n   * @private\n   *\n   * @description\n   * indexOf polyfill. Kinda sorta.\n   *\n   * @param {array} array Array to search in.\n   * @param {string} searchElement Element to search for.\n   *\n   * @returns {int} Index of search element.\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\n  /**\n   * @name trim\n   * @private\n   *\n   * @description\n   * trim polyfill\n   *\n   * @returns {string} The string stripped of whitespace from both ends\n   */\n  var trim = function () {\n    return this.toString().replace(/^\\s+|\\s+$/g, '');\n  };\n\n  var negotiateLocale = function (preferred) {\n    if (!preferred) {\n      return;\n    }\n\n    var avail = [],\n      locale = angular.lowercase(preferred),\n      i = 0,\n      n = $availableLanguageKeys.length;\n\n    for (; i < n; i++) {\n      avail.push(angular.lowercase($availableLanguageKeys[i]));\n    }\n\n    // Check for an exact match in our list of available keys\n    if (indexOf(avail, locale) > -1) {\n      return preferred;\n    }\n\n    if ($languageKeyAliases) {\n      var alias;\n      for (var langKeyAlias in $languageKeyAliases) {\n        if ($languageKeyAliases.hasOwnProperty(langKeyAlias)) {\n          var hasWildcardKey = false;\n          var hasExactKey = Object.prototype.hasOwnProperty.call($languageKeyAliases, langKeyAlias) &&\n            angular.lowercase(langKeyAlias) === angular.lowercase(preferred);\n\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    }\n\n    // Check for a language code without region\n    var parts = preferred.split('_');\n\n    if (parts.length > 1 && indexOf(avail, angular.lowercase(parts[0])) > -1) {\n      return parts[0];\n    }\n\n    // If everything fails, return undefined.\n    return;\n  };\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#translations\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * Registers a new translation table for specific language key.\n   *\n   * To register a translation table for specific language, pass a defined language\n   * key as first parameter.\n   *\n   * <pre>\n   *  // register translation table for language: 'de_DE'\n   *  $translateProvider.translations('de_DE', {\n   *    'GREETING': 'Hallo Welt!'\n   *  });\n   *\n   *  // register another one\n   *  $translateProvider.translations('en_US', {\n   *    'GREETING': 'Hello world!'\n   *  });\n   * </pre>\n   *\n   * When registering multiple translation tables for for the same language key,\n   * the actual translation table gets extended. This allows you to define module\n   * specific translation which only get added, once a specific module is loaded in\n   * your app.\n   *\n   * Invoking this method with no arguments returns the translation table which was\n   * registered with no language key. Invoking it with a language key returns the\n   * related translation table.\n   *\n   * @param {string} langKey A language key.\n   * @param {object} translationTable A plain old JavaScript object that represents a translation table.\n   *\n   */\n  var translations = function (langKey, translationTable) {\n\n    if (!langKey && !translationTable) {\n      return $translationTable;\n    }\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\n  this.translations = translations;\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#cloakClassName\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   *\n   * Let's you change the class name for `translate-cloak` directive.\n   * Default class name is `translate-cloak`.\n   *\n   * @param {string} name translate-cloak class name\n   */\n  this.cloakClassName = function (name) {\n    if (!name) {\n      return $cloakClassName;\n    }\n    $cloakClassName = name;\n    return this;\n  };\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#nestedObjectDelimeter\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   *\n   * Let's you change the delimiter for namespaced translations.\n   * Default delimiter is `.`.\n   *\n   * @param {string} delimiter namespace separator\n   */\n  this.nestedObjectDelimeter = function (delimiter) {\n    if (!delimiter) {\n      return $nestedObjectDelimeter;\n    }\n    $nestedObjectDelimeter = delimiter;\n    return this;\n  };\n\n  /**\n   * @name flatObject\n   * @private\n   *\n   * @description\n   * Flats an object. This function is used to flatten given translation data with\n   * namespaces, so they are later accessible via dot notation.\n   */\n  var flatObject = function (data, path, result, prevKey) {\n    var key, keyWithPath, keyWithShortPath, val;\n\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($nestedObjectDelimeter) + $nestedObjectDelimeter + key) : key;\n        if (path.length && key === prevKey) {\n          // Create shortcut path (foo.bar == foo.bar.bar)\n          keyWithShortPath = '' + path.join($nestedObjectDelimeter);\n          // Link it to original path\n          result[keyWithShortPath] = '@:' + keyWithPath;\n        }\n        result[keyWithPath] = val;\n      }\n    }\n    return result;\n  };\n  flatObject.displayName = 'flatObject';\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#addInterpolation\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * Adds interpolation services to angular-translate, so it can manage them.\n   *\n   * @param {object} factory Interpolation service factory\n   */\n  this.addInterpolation = function (factory) {\n    $interpolatorFactories.push(factory);\n    return this;\n  };\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#useMessageFormatInterpolation\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * Tells angular-translate to use interpolation functionality of messageformat.js.\n   * This is useful when having high level pluralization and gender selection.\n   */\n  this.useMessageFormatInterpolation = function () {\n    return this.useInterpolation('$translateMessageFormatInterpolation');\n  };\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#useInterpolation\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * Tells angular-translate which interpolation style to use as default, application-wide.\n   * Simply pass a factory/service name. The interpolation service has to implement\n   * the correct interface.\n   *\n   * @param {string} factory Interpolation service name.\n   */\n  this.useInterpolation = function (factory) {\n    $interpolationFactory = factory;\n    return this;\n  };\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#useSanitizeStrategy\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * Simply sets a sanitation strategy type.\n   *\n   * @param {string} value Strategy type.\n   */\n  this.useSanitizeValueStrategy = function (value) {\n    $translateSanitizationProvider.useStrategy(value);\n    return this;\n  };\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#preferredLanguage\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * Tells the module which of the registered translation tables to use for translation\n   * at initial startup by passing a language key. Similar to `$translateProvider#use`\n   * only that it says which language to **prefer**.\n   *\n   * @param {string} langKey A language key.\n   */\n  this.preferredLanguage = function (langKey) {\n    if (langKey) {\n      setupPreferredLanguage(langKey);\n      return this;\n    }\n    return $preferredLanguage;\n  };\n  var setupPreferredLanguage = function (langKey) {\n    if (langKey) {\n      $preferredLanguage = langKey;\n    }\n    return $preferredLanguage;\n  };\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#translationNotFoundIndicator\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * Sets an indicator which is used when a translation isn't found. E.g. when\n   * setting the indicator as 'X' and one tries to translate a translation id\n   * called `NOT_FOUND`, this will result in `X NOT_FOUND X`.\n   *\n   * Internally this methods sets a left indicator and a right indicator using\n   * `$translateProvider.translationNotFoundIndicatorLeft()` and\n   * `$translateProvider.translationNotFoundIndicatorRight()`.\n   *\n   * **Note**: These methods automatically add a whitespace between the indicators\n   * and the translation id.\n   *\n   * @param {string} indicator An indicator, could be any string.\n   */\n  this.translationNotFoundIndicator = function (indicator) {\n    this.translationNotFoundIndicatorLeft(indicator);\n    this.translationNotFoundIndicatorRight(indicator);\n    return this;\n  };\n\n  /**\n   * ngdoc function\n   * @name pascalprecht.translate.$translateProvider#translationNotFoundIndicatorLeft\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * Sets an indicator which is used when a translation isn't found left to the\n   * translation id.\n   *\n   * @param {string} indicator An indicator.\n   */\n  this.translationNotFoundIndicatorLeft = function (indicator) {\n    if (!indicator) {\n      return $notFoundIndicatorLeft;\n    }\n    $notFoundIndicatorLeft = indicator;\n    return this;\n  };\n\n  /**\n   * ngdoc function\n   * @name pascalprecht.translate.$translateProvider#translationNotFoundIndicatorLeft\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * Sets an indicator which is used when a translation isn't found right to the\n   * translation id.\n   *\n   * @param {string} indicator An indicator.\n   */\n  this.translationNotFoundIndicatorRight = function (indicator) {\n    if (!indicator) {\n      return $notFoundIndicatorRight;\n    }\n    $notFoundIndicatorRight = indicator;\n    return this;\n  };\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#fallbackLanguage\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * Tells the module which of the registered translation tables to use when missing translations\n   * at initial startup by passing a language key. Similar to `$translateProvider#use`\n   * only that it says which language to **fallback**.\n   *\n   * @param {string||array} langKey A language key.\n   *\n   */\n  this.fallbackLanguage = function (langKey) {\n    fallbackStack(langKey);\n    return this;\n  };\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\n      return this;\n    } else {\n      if ($fallbackWasString) {\n        return $fallbackLanguage[0];\n      } else {\n        return $fallbackLanguage;\n      }\n    }\n  };\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#use\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * Set which translation table to use for translation by given language key. When\n   * trying to 'use' a language which isn't provided, it'll throw an error.\n   *\n   * You actually don't have to use this method since `$translateProvider#preferredLanguage`\n   * does the job too.\n   *\n   * @param {string} langKey A language key.\n   */\n  this.use = function (langKey) {\n    if (langKey) {\n      if (!$translationTable[langKey] && (!$loaderFactory)) {\n        // only throw an error, when not loading translation data asynchronously\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\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#resolveClientLocale\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * This returns the current browser/client's language key. The result is processed with the configured uniform tag resolver.\n   *\n   * @returns {string} the current client/browser language key\n   */\n  this.resolveClientLocale = function () {\n    return getLocale();\n  };\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#storageKey\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * Tells the module which key must represent the choosed language by a user in the storage.\n   *\n   * @param {string} key A key for the storage.\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    return this;\n  };\n\n  this.storageKey = storageKey;\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#useUrlLoader\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * Tells angular-translate to use `$translateUrlLoader` extension service as loader.\n   *\n   * @param {string} url Url\n   * @param {Object=} options Optional configuration object\n   */\n  this.useUrlLoader = function (url, options) {\n    return this.useLoader('$translateUrlLoader', angular.extend({url : url}, options));\n  };\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#useStaticFilesLoader\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * Tells angular-translate to use `$translateStaticFilesLoader` extension service as loader.\n   *\n   * @param {Object=} options Optional configuration object\n   */\n  this.useStaticFilesLoader = function (options) {\n    return this.useLoader('$translateStaticFilesLoader', options);\n  };\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#useLoader\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * Tells angular-translate to use any other service as loader.\n   *\n   * @param {string} loaderFactory Factory name to use\n   * @param {Object=} options Optional configuration object\n   */\n  this.useLoader = function (loaderFactory, options) {\n    $loaderFactory = loaderFactory;\n    $loaderOptions = options || {};\n    return this;\n  };\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#useLocalStorage\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * Tells angular-translate to use `$translateLocalStorage` service as storage layer.\n   *\n   */\n  this.useLocalStorage = function () {\n    return this.useStorage('$translateLocalStorage');\n  };\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#useCookieStorage\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * Tells angular-translate to use `$translateCookieStorage` service as storage layer.\n   */\n  this.useCookieStorage = function () {\n    return this.useStorage('$translateCookieStorage');\n  };\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#useStorage\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * Tells angular-translate to use custom service as storage layer.\n   */\n  this.useStorage = function (storageFactory) {\n    $storageFactory = storageFactory;\n    return this;\n  };\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#storagePrefix\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * Sets prefix for storage key.\n   *\n   * @param {string} prefix Storage key prefix\n   */\n  this.storagePrefix = function (prefix) {\n    if (!prefix) {\n      return prefix;\n    }\n    $storagePrefix = prefix;\n    return this;\n  };\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#useMissingTranslationHandlerLog\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * Tells angular-translate to use built-in log handler when trying to translate\n   * a translation Id which doesn't exist.\n   *\n   * This is actually a shortcut method for `useMissingTranslationHandler()`.\n   *\n   */\n  this.useMissingTranslationHandlerLog = function () {\n    return this.useMissingTranslationHandler('$translateMissingTranslationHandlerLog');\n  };\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#useMissingTranslationHandler\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * Expects a factory name which later gets instantiated with `$injector`.\n   * This method can be used to tell angular-translate to use a custom\n   * missingTranslationHandler. Just build a factory which returns a function\n   * and expects a translation id as argument.\n   *\n   * Example:\n   * <pre>\n   *  app.config(function ($translateProvider) {\n   *    $translateProvider.useMissingTranslationHandler('customHandler');\n   *  });\n   *\n   *  app.factory('customHandler', function (dep1, dep2) {\n   *    return function (translationId) {\n   *      // something with translationId and dep1 and dep2\n   *    };\n   *  });\n   * </pre>\n   *\n   * @param {string} factory Factory name\n   */\n  this.useMissingTranslationHandler = function (factory) {\n    $missingTranslationHandlerFactory = factory;\n    return this;\n  };\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#usePostCompiling\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * If post compiling is enabled, all translated values will be processed\n   * again with AngularJS' $compile.\n   *\n   * Example:\n   * <pre>\n   *  app.config(function ($translateProvider) {\n   *    $translateProvider.usePostCompiling(true);\n   *  });\n   * </pre>\n   *\n   * @param {string} factory Factory name\n   */\n  this.usePostCompiling = function (value) {\n    $postCompilingEnabled = !(!value);\n    return this;\n  };\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#forceAsyncReload\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * If force async reload is enabled, async loader will always be called\n   * even if $translationTable already contains the language key, adding\n   * possible new entries to the $translationTable.\n   *\n   * Example:\n   * <pre>\n   *  app.config(function ($translateProvider) {\n   *    $translateProvider.forceAsyncReload(true);\n   *  });\n   * </pre>\n   *\n   * @param {boolean} value - valid values are true or false\n   */\n  this.forceAsyncReload = function (value) {\n    $forceAsyncReloadEnabled = !(!value);\n    return this;\n  };\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#uniformLanguageTag\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * Tells angular-translate which language tag should be used as a result when determining\n   * the current browser language.\n   *\n   * This setting must be set before invoking {@link pascalprecht.translate.$translateProvider#methods_determinePreferredLanguage determinePreferredLanguage()}.\n   *\n   * <pre>\n   * $translateProvider\n   *   .uniformLanguageTag('bcp47')\n   *   .determinePreferredLanguage()\n   * </pre>\n   *\n   * The resolver currently supports:\n   * * default\n   *     (traditionally: hyphens will be converted into underscores, i.e. en-US => en_US)\n   *     en-US => en_US\n   *     en_US => en_US\n   *     en-us => en_us\n   * * java\n   *     like default, but the second part will be always in uppercase\n   *     en-US => en_US\n   *     en_US => en_US\n   *     en-us => en_US\n   * * BCP 47 (RFC 4646 & 4647)\n   *     en-US => en-US\n   *     en_US => en-US\n   *     en-us => en-US\n   *\n   * See also:\n   * * http://en.wikipedia.org/wiki/IETF_language_tag\n   * * http://www.w3.org/International/core/langtags/\n   * * http://tools.ietf.org/html/bcp47\n   *\n   * @param {string|object} options - options (or standard)\n   * @param {string} options.standard - valid values are 'default', 'bcp47', 'java'\n   */\n  this.uniformLanguageTag = function (options) {\n\n    if (!options) {\n      options = {};\n    } else if (angular.isString(options)) {\n      options = {\n        standard : options\n      };\n    }\n\n    uniformLanguageTagResolver = options.standard;\n\n    return this;\n  };\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#determinePreferredLanguage\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * Tells angular-translate to try to determine on its own which language key\n   * to set as preferred language. When `fn` is given, angular-translate uses it\n   * to determine a language key, otherwise it uses the built-in `getLocale()`\n   * method.\n   *\n   * The `getLocale()` returns a language key in the format `[lang]_[country]` or\n   * `[lang]` depending on what the browser provides.\n   *\n   * Use this method at your own risk, since not all browsers return a valid\n   * locale (see {@link pascalprecht.translate.$translateProvider#methods_uniformLanguageTag uniformLanguageTag()}).\n   *\n   * @param {Function=} fn Function to determine a browser's locale\n   */\n  this.determinePreferredLanguage = function (fn) {\n\n    var locale = (fn && angular.isFunction(fn)) ? fn() : getLocale();\n\n    if (!$availableLanguageKeys.length) {\n      $preferredLanguage = locale;\n    } else {\n      $preferredLanguage = negotiateLocale(locale) || locale;\n    }\n\n    return this;\n  };\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#registerAvailableLanguageKeys\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * Registers a set of language keys the app will work with. Use this method in\n   * combination with\n   * {@link pascalprecht.translate.$translateProvider#determinePreferredLanguage determinePreferredLanguage}.\n   * When available languages keys are registered, angular-translate\n   * tries to find the best fitting language key depending on the browsers locale,\n   * considering your language key convention.\n   *\n   * @param {object} languageKeys Array of language keys the your app will use\n   * @param {object=} aliases Alias map.\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\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#useLoaderCache\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * Registers a cache for internal $http based loaders.\n   * {@link pascalprecht.translate.$translationCache $translationCache}.\n   * When false the cache will be disabled (default). When true or undefined\n   * the cache will be a default (see $cacheFactory). When an object it will\n   * be treat as a cache object itself: the usage is $http({cache: cache})\n   *\n   * @param {object} cache boolean, string or cache-object\n   */\n  this.useLoaderCache = function (cache) {\n    if (cache === false) {\n      // disable cache\n      loaderCache = undefined;\n    } else if (cache === true) {\n      // enable cache using AJS defaults\n      loaderCache = true;\n    } else if (typeof(cache) === 'undefined') {\n      // enable cache using default\n      loaderCache = '$translationCache';\n    } else if (cache) {\n      // enable cache using given one (see $cacheFactory)\n      loaderCache = cache;\n    }\n    return this;\n  };\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#directivePriority\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * Sets the default priority of the translate directive. The standard value is `0`.\n   * Calling this function without an argument will return the current value.\n   *\n   * @param {number} priority for the translate-directive\n   */\n  this.directivePriority = function (priority) {\n    if (priority === undefined) {\n      // getter\n      return directivePriority;\n    } else {\n      // setter with chaining\n      directivePriority = priority;\n      return this;\n    }\n  };\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#statefulFilter\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * Since AngularJS 1.3, filters which are not stateless (depending at the scope)\n   * have to explicit define this behavior.\n   * Sets whether the translate filter should be stateful or stateless. The standard value is `true`\n   * meaning being stateful.\n   * Calling this function without an argument will return the current value.\n   *\n   * @param {boolean} state - defines the state of the filter\n   */\n  this.statefulFilter = function (state) {\n    if (state === undefined) {\n      // getter\n      return statefulFilter;\n    } else {\n      // setter with chaining\n      statefulFilter = state;\n      return this;\n    }\n  };\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#postProcess\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * The post processor will be intercept right after the translation result. It can modify the result.\n   *\n   * @param {object} fn Function or service name (string) to be called after the translation value has been set / resolved. The function itself will enrich every value being processed and then continue the normal resolver process\n   */\n  this.postProcess = function (fn) {\n    if (fn) {\n      postProcessFn = fn;\n    } else {\n      postProcessFn = undefined;\n    }\n    return this;\n  };\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#keepContent\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * If keepContent is set to true than translate directive will always use innerHTML\n   * as a default translation\n   *\n   * Example:\n   * <pre>\n   *  app.config(function ($translateProvider) {\n   *    $translateProvider.keepContent(true);\n   *  });\n   * </pre>\n   *\n   * @param {boolean} value - valid values are true or false\n   */\n  this.keepContent = function (value) {\n    $keepContent = !(!value);\n    return this;\n  };\n\n  /**\n   * @ngdoc object\n   * @name pascalprecht.translate.$translate\n   * @requires $interpolate\n   * @requires $log\n   * @requires $rootScope\n   * @requires $q\n   *\n   * @description\n   * The `$translate` service is the actual core of angular-translate. It expects a translation id\n   * and optional interpolate parameters to translate contents.\n   *\n   * <pre>\n   *  $translate('HEADLINE_TEXT').then(function (translation) {\n   *    $scope.translatedText = translation;\n   *  });\n   * </pre>\n   *\n   * @param {string|array} translationId A token which represents a translation id\n   *                                     This can be optionally an array of translation ids which\n   *                                     results that the function returns an object where each key\n   *                                     is the translation id and the value the translation.\n   * @param {object=} interpolateParams An object hash for dynamic values\n   * @param {string} interpolationId The id of the interpolation to use\n   * @param {string} defaultTranslationText the optional default translation text that is written as\n   *                                        as default text in case it is not found in any configured language\n   * @param {string} forceLanguage A language to be used instead of the current language\n   * @returns {object} promise\n   */\n  this.$get = ['$log', '$injector', '$rootScope', '$q', function ($log, $injector, $rootScope, $q) {\n\n    var Storage,\n      defaultInterpolator = $injector.get($interpolationFactory || '$translateDefaultInterpolation'),\n      pendingLoader = false,\n      interpolatorHashMap = {},\n      langPromises = {},\n      fallbackIndex,\n      startFallbackIteration;\n\n    var $translate = function (translationId, interpolateParams, interpolationId, defaultTranslationText, forceLanguage) {\n      if (!$uses && $preferredLanguage) {\n        $uses = $preferredLanguage;\n      }\n      var uses = (forceLanguage && forceLanguage !== $uses) ? // we don't want to re-negotiate $uses\n        (negotiateLocale(forceLanguage) || forceLanguage) : $uses;\n\n      // Check forceLanguage is present\n      if (forceLanguage) {\n        loadTranslationsIfMissing(forceLanguage);\n      }\n\n      // Duck detection: If the first argument is an array, a bunch of translations was requested.\n      // The result is an object.\n      if (angular.isArray(translationId)) {\n        // Inspired by Q.allSettled by Kris Kowal\n        // https://github.com/kriskowal/q/blob/b0fa72980717dc202ffc3cbf03b936e10ebbb9d7/q.js#L1553-1563\n        // This transforms all promises regardless resolved or rejected\n        var translateAll = function (translationIds) {\n          var results = {}; // storing the actual results\n          var promises = []; // promises to wait for\n          // Wraps the promise a) being always resolved and b) storing the link id->value\n          var translate = function (translationId) {\n            var deferred = $q.defer();\n            var regardless = function (value) {\n              results[translationId] = value;\n              deferred.resolve([translationId, value]);\n            };\n            // we don't care whether the promise was resolved or rejected; just store the values\n            $translate(translationId, interpolateParams, interpolationId, defaultTranslationText, forceLanguage).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          // wait for all (including storing to results)\n          return $q.all(promises).then(function () {\n            // return the results\n            return results;\n          });\n        };\n        return translateAll(translationId);\n      }\n\n      var deferred = $q.defer();\n\n      // trim off any whitespace\n      if (translationId) {\n        translationId = trim.apply(translationId);\n      }\n\n      var promiseToWaitFor = (function () {\n        var promise = $preferredLanguage ?\n          langPromises[$preferredLanguage] :\n          langPromises[uses];\n\n        fallbackIndex = 0;\n\n        if ($storageFactory && !promise) {\n          // looks like there's no pending promise for $preferredLanguage or\n          // $uses. Maybe there's one pending for a language that comes from\n          // storage.\n          var langKey = Storage.get($storageKey);\n          promise = langPromises[langKey];\n\n          if ($fallbackLanguage && $fallbackLanguage.length) {\n            var index = indexOf($fallbackLanguage, langKey);\n            // maybe the language from storage is also defined as fallback language\n            // we increase the fallback language index to not search in that language\n            // as fallback, since it's probably the first used language\n            // in that case the index starts after the first element\n            fallbackIndex = (index === 0) ? 1 : 0;\n\n            // but we can make sure to ALWAYS fallback to preferred language at least\n            if (indexOf($fallbackLanguage, $preferredLanguage) < 0) {\n              $fallbackLanguage.push($preferredLanguage);\n            }\n          }\n        }\n        return promise;\n      }());\n\n      if (!promiseToWaitFor) {\n        // no promise to wait for? okay. Then there's no loader registered\n        // nor is a one pending for language that comes from storage.\n        // We can just translate.\n        determineTranslation(translationId, interpolateParams, interpolationId, defaultTranslationText, uses).then(deferred.resolve, deferred.reject);\n      } else {\n        var promiseResolved = function () {\n          // $uses may have changed while waiting\n          if (!forceLanguage) {\n            uses = $uses;\n          }\n          determineTranslation(translationId, interpolateParams, interpolationId, defaultTranslationText, uses).then(deferred.resolve, deferred.reject);\n        };\n        promiseResolved.displayName = 'promiseResolved';\n\n        promiseToWaitFor['finally'](promiseResolved)\n          .catch(angular.noop); // we don't care about errors here, already handled\n      }\n      return deferred.promise;\n    };\n\n    /**\n     * @name applyNotFoundIndicators\n     * @private\n     *\n     * @description\n     * Applies not fount indicators to given translation id, if needed.\n     * This function gets only executed, if a translation id doesn't exist,\n     * which is why a translation id is expected as argument.\n     *\n     * @param {string} translationId Translation id.\n     * @returns {string} Same as given translation id but applied with not found\n     * indicators.\n     */\n    var applyNotFoundIndicators = function (translationId) {\n      // applying notFoundIndicators\n      if ($notFoundIndicatorLeft) {\n        translationId = [$notFoundIndicatorLeft, translationId].join(' ');\n      }\n      if ($notFoundIndicatorRight) {\n        translationId = [translationId, $notFoundIndicatorRight].join(' ');\n      }\n      return translationId;\n    };\n\n    /**\n     * @name useLanguage\n     * @private\n     *\n     * @description\n     * Makes actual use of a language by setting a given language key as used\n     * language and informs registered interpolators to also use the given\n     * key as locale.\n     *\n     * @param {string} key Locale key.\n     */\n    var useLanguage = function (key) {\n      $uses = key;\n\n      // make sure to store new language key before triggering success event\n      if ($storageFactory) {\n        Storage.put($translate.storageKey(), $uses);\n      }\n\n      $rootScope.$emit('$translateChangeSuccess', {language : key});\n\n      // inform default interpolator\n      defaultInterpolator.setLocale($uses);\n\n      var eachInterpolator = function (interpolator, id) {\n        interpolatorHashMap[id].setLocale($uses);\n      };\n      eachInterpolator.displayName = 'eachInterpolatorLocaleSetter';\n\n      // inform all others too!\n      angular.forEach(interpolatorHashMap, eachInterpolator);\n      $rootScope.$emit('$translateChangeEnd', {language : key});\n    };\n\n    /**\n     * @name loadAsync\n     * @private\n     *\n     * @description\n     * Kicks off registered async loader using `$injector` and applies existing\n     * loader options. When resolved, it updates translation tables accordingly\n     * or rejects with given language key.\n     *\n     * @param {string} key Language key.\n     * @return {Promise} A promise.\n     */\n    var loadAsync = function (key) {\n      if (!key) {\n        throw 'No language key specified for loading.';\n      }\n\n      var deferred = $q.defer();\n\n      $rootScope.$emit('$translateLoadingStart', {language : key});\n      pendingLoader = true;\n\n      var cache = loaderCache;\n      if (typeof(cache) === 'string') {\n        // getting on-demand instance of loader\n        cache = $injector.get(cache);\n      }\n\n      var loaderOptions = angular.extend({}, $loaderOptions, {\n        key : key,\n        $http : angular.extend({}, {\n          cache : cache\n        }, $loaderOptions.$http)\n      });\n\n      var onLoaderSuccess = function (data) {\n        var translationTable = {};\n        $rootScope.$emit('$translateLoadingSuccess', {language : key});\n\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      };\n      onLoaderSuccess.displayName = 'onLoaderSuccess';\n\n      var onLoaderError = function (key) {\n        $rootScope.$emit('$translateLoadingError', {language : key});\n        deferred.reject(key);\n        $rootScope.$emit('$translateLoadingEnd', {language : key});\n      };\n      onLoaderError.displayName = 'onLoaderError';\n\n      $injector.get($loaderFactory)(loaderOptions)\n        .then(onLoaderSuccess, onLoaderError);\n\n      return deferred.promise;\n    };\n\n    if ($storageFactory) {\n      Storage = $injector.get($storageFactory);\n\n      if (!Storage.get || !Storage.put) {\n        throw new Error('Couldn\\'t use storage \\'' + $storageFactory + '\\', missing get() or put() method!');\n      }\n    }\n\n    // if we have additional interpolations that were added via\n    // $translateProvider.addInterpolation(), we have to map'em\n    if ($interpolatorFactories.length) {\n      var eachInterpolationFactory = function (interpolatorFactory) {\n        var interpolator = $injector.get(interpolatorFactory);\n        // setting initial locale for each interpolation service\n        interpolator.setLocale($preferredLanguage || $uses);\n        // make'em recognizable through id\n        interpolatorHashMap[interpolator.getInterpolationIdentifier()] = interpolator;\n      };\n      eachInterpolationFactory.displayName = 'interpolationFactoryAdder';\n\n      angular.forEach($interpolatorFactories, eachInterpolationFactory);\n    }\n\n    /**\n     * @name getTranslationTable\n     * @private\n     *\n     * @description\n     * Returns a promise that resolves to the translation table\n     * or is rejected if an error occurred.\n     *\n     * @param langKey\n     * @returns {Q.promise}\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        var onResolve = function (data) {\n          translations(data.key, data.table);\n          deferred.resolve(data.table);\n        };\n        onResolve.displayName = 'translationTableResolver';\n        langPromises[langKey].then(onResolve, deferred.reject);\n      } else {\n        deferred.reject();\n      }\n      return deferred.promise;\n    };\n\n    /**\n     * @name getFallbackTranslation\n     * @private\n     *\n     * @description\n     * Returns a promise that will resolve to the translation\n     * or be rejected if no translation was found for the language.\n     * This function is currently only used for fallback language translation.\n     *\n     * @param langKey The language to translate to.\n     * @param translationId\n     * @param interpolateParams\n     * @param Interpolator\n     * @param sanitizeStrategy\n     * @returns {Q.promise}\n     */\n    var getFallbackTranslation = function (langKey, translationId, interpolateParams, Interpolator, sanitizeStrategy) {\n      var deferred = $q.defer();\n\n      var onResolve = function (translationTable) {\n        if (Object.prototype.hasOwnProperty.call(translationTable, translationId) && translationTable[translationId] !== null) {\n          Interpolator.setLocale(langKey);\n          var translation = translationTable[translationId];\n          if (translation.substr(0, 2) === '@:') {\n            getFallbackTranslation(langKey, translation.substr(2), interpolateParams, Interpolator, sanitizeStrategy)\n              .then(deferred.resolve, deferred.reject);\n          } else {\n            var interpolatedValue = Interpolator.interpolate(translationTable[translationId], interpolateParams, 'service', sanitizeStrategy, translationId);\n            interpolatedValue = applyPostProcessing(translationId, translationTable[translationId], interpolatedValue, interpolateParams, langKey);\n\n            deferred.resolve(interpolatedValue);\n\n          }\n          Interpolator.setLocale($uses);\n        } else {\n          deferred.reject();\n        }\n      };\n      onResolve.displayName = 'fallbackTranslationResolver';\n\n      getTranslationTable(langKey).then(onResolve, deferred.reject);\n\n      return deferred.promise;\n    };\n\n    /**\n     * @name getFallbackTranslationInstant\n     * @private\n     *\n     * @description\n     * Returns a translation\n     * This function is currently only used for fallback language translation.\n     *\n     * @param langKey The language to translate to.\n     * @param translationId\n     * @param interpolateParams\n     * @param Interpolator\n     * @param sanitizeStrategy sanitize strategy override\n     *\n     * @returns {string} translation\n     */\n    var getFallbackTranslationInstant = function (langKey, translationId, interpolateParams, Interpolator, sanitizeStrategy) {\n      var result, translationTable = $translationTable[langKey];\n\n      if (translationTable && Object.prototype.hasOwnProperty.call(translationTable, translationId) && translationTable[translationId] !== null) {\n        Interpolator.setLocale(langKey);\n        result = Interpolator.interpolate(translationTable[translationId], interpolateParams, 'filter', sanitizeStrategy, translationId);\n        result = applyPostProcessing(translationId, translationTable[translationId], result, interpolateParams, langKey, sanitizeStrategy);\n        // workaround for TrustedValueHolderType\n        if (!angular.isString(result) && angular.isFunction(result.$$unwrapTrustedValue)) {\n          var result2 = result.$$unwrapTrustedValue();\n          if (result2.substr(0, 2) === '@:') {\n            return getFallbackTranslationInstant(langKey, result2.substr(2), interpolateParams, Interpolator, sanitizeStrategy);\n          }\n        } else if (result.substr(0, 2) === '@:') {\n          return getFallbackTranslationInstant(langKey, result.substr(2), interpolateParams, Interpolator, sanitizeStrategy);\n        }\n        Interpolator.setLocale($uses);\n      }\n\n      return result;\n    };\n\n\n    /**\n     * @name translateByHandler\n     * @private\n     *\n     * Translate by missing translation handler.\n     *\n     * @param translationId\n     * @param interpolateParams\n     * @param defaultTranslationText\n     * @param sanitizeStrategy sanitize strategy override\n     *\n     * @returns translation created by $missingTranslationHandler or translationId is $missingTranslationHandler is\n     * absent\n     */\n    var translateByHandler = function (translationId, interpolateParams, defaultTranslationText, sanitizeStrategy) {\n      // If we have a handler factory - we might also call it here to determine if it provides\n      // a default text for a translationid that can't be found anywhere in our tables\n      if ($missingTranslationHandlerFactory) {\n        return $injector.get($missingTranslationHandlerFactory)(translationId, $uses, interpolateParams, defaultTranslationText, sanitizeStrategy);\n      } else {\n        return translationId;\n      }\n    };\n\n    /**\n     * @name resolveForFallbackLanguage\n     * @private\n     *\n     * Recursive helper function for fallbackTranslation that will sequentially look\n     * for a translation in the fallbackLanguages starting with fallbackLanguageIndex.\n     *\n     * @param fallbackLanguageIndex\n     * @param translationId\n     * @param interpolateParams\n     * @param Interpolator\n     * @param defaultTranslationText\n     * @param sanitizeStrategy\n     * @returns {Q.promise} Promise that will resolve to the translation.\n     */\n    var resolveForFallbackLanguage = function (fallbackLanguageIndex, translationId, interpolateParams, Interpolator, defaultTranslationText, sanitizeStrategy) {\n      var deferred = $q.defer();\n\n      if (fallbackLanguageIndex < $fallbackLanguage.length) {\n        var langKey = $fallbackLanguage[fallbackLanguageIndex];\n        getFallbackTranslation(langKey, translationId, interpolateParams, Interpolator, sanitizeStrategy).then(\n          function (data) {\n            deferred.resolve(data);\n          },\n          function () {\n            // Look in the next fallback language for a translation.\n            // It delays the resolving by passing another promise to resolve.\n            return resolveForFallbackLanguage(fallbackLanguageIndex + 1, translationId, interpolateParams, Interpolator, defaultTranslationText, sanitizeStrategy).then(deferred.resolve, deferred.reject);\n          }\n        );\n      } else {\n        // No translation found in any fallback language\n        // if a default translation text is set in the directive, then return this as a result\n        if (defaultTranslationText) {\n          deferred.resolve(defaultTranslationText);\n        } else {\n          var missingTranslationHandlerTranslation = translateByHandler(translationId, interpolateParams, defaultTranslationText);\n\n          // if no default translation is set and an error handler is defined, send it to the handler\n          // and then return the result if it isn't undefined\n          if ($missingTranslationHandlerFactory && missingTranslationHandlerTranslation) {\n            deferred.resolve(missingTranslationHandlerTranslation);\n          } else {\n            deferred.reject(applyNotFoundIndicators(translationId));\n          }\n        }\n      }\n      return deferred.promise;\n    };\n\n    /**\n     * @name resolveForFallbackLanguageInstant\n     * @private\n     *\n     * Recursive helper function for fallbackTranslation that will sequentially look\n     * for a translation in the fallbackLanguages starting with fallbackLanguageIndex.\n     *\n     * @param fallbackLanguageIndex\n     * @param translationId\n     * @param interpolateParams\n     * @param Interpolator\n     * @param sanitizeStrategy\n     * @returns {string} translation\n     */\n    var resolveForFallbackLanguageInstant = function (fallbackLanguageIndex, translationId, interpolateParams, Interpolator, sanitizeStrategy) {\n      var result;\n\n      if (fallbackLanguageIndex < $fallbackLanguage.length) {\n        var langKey = $fallbackLanguage[fallbackLanguageIndex];\n        result = getFallbackTranslationInstant(langKey, translationId, interpolateParams, Interpolator, sanitizeStrategy);\n        if (!result && result !== '') {\n          result = resolveForFallbackLanguageInstant(fallbackLanguageIndex + 1, translationId, interpolateParams, Interpolator);\n        }\n      }\n      return result;\n    };\n\n    /**\n     * Translates with the usage of the fallback languages.\n     *\n     * @param translationId\n     * @param interpolateParams\n     * @param Interpolator\n     * @param defaultTranslationText\n     * @param sanitizeStrategy\n     * @returns {Q.promise} Promise, that resolves to the translation.\n     */\n    var fallbackTranslation = function (translationId, interpolateParams, Interpolator, defaultTranslationText, sanitizeStrategy) {\n      // Start with the fallbackLanguage with index 0\n      return resolveForFallbackLanguage((startFallbackIteration > 0 ? startFallbackIteration : fallbackIndex), translationId, interpolateParams, Interpolator, defaultTranslationText, sanitizeStrategy);\n    };\n\n    /**\n     * Translates with the usage of the fallback languages.\n     *\n     * @param translationId\n     * @param interpolateParams\n     * @param Interpolator\n     * @param sanitizeStrategy\n     * @returns {String} translation\n     */\n    var fallbackTranslationInstant = function (translationId, interpolateParams, Interpolator, sanitizeStrategy) {\n      // Start with the fallbackLanguage with index 0\n      return resolveForFallbackLanguageInstant((startFallbackIteration > 0 ? startFallbackIteration : fallbackIndex), translationId, interpolateParams, Interpolator, sanitizeStrategy);\n    };\n\n    var determineTranslation = function (translationId, interpolateParams, interpolationId, defaultTranslationText, uses, sanitizeStrategy) {\n\n      var deferred = $q.defer();\n\n      var table = uses ? $translationTable[uses] : $translationTable,\n        Interpolator = (interpolationId) ? interpolatorHashMap[interpolationId] : defaultInterpolator;\n\n      // if the translation id exists, we can just interpolate it\n      if (table && Object.prototype.hasOwnProperty.call(table, translationId) && table[translationId] !== null) {\n        var translation = table[translationId];\n\n        // If using link, rerun $translate with linked translationId and return it\n        if (translation.substr(0, 2) === '@:') {\n\n          $translate(translation.substr(2), interpolateParams, interpolationId, defaultTranslationText, uses)\n            .then(deferred.resolve, deferred.reject);\n        } else {\n          //\n          var resolvedTranslation = Interpolator.interpolate(translation, interpolateParams, 'service', sanitizeStrategy, translationId);\n          resolvedTranslation = applyPostProcessing(translationId, translation, resolvedTranslation, interpolateParams, uses);\n          deferred.resolve(resolvedTranslation);\n        }\n      } else {\n        var missingTranslationHandlerTranslation;\n        // for logging purposes only (as in $translateMissingTranslationHandlerLog), value is not returned to promise\n        if ($missingTranslationHandlerFactory && !pendingLoader) {\n          missingTranslationHandlerTranslation = translateByHandler(translationId, interpolateParams, defaultTranslationText);\n        }\n\n        // since we couldn't translate the inital requested translation id,\n        // we try it now with one or more fallback languages, if fallback language(s) is\n        // configured.\n        if (uses && $fallbackLanguage && $fallbackLanguage.length) {\n          fallbackTranslation(translationId, interpolateParams, Interpolator, defaultTranslationText, sanitizeStrategy)\n            .then(function (translation) {\n              deferred.resolve(translation);\n            }, function (_translationId) {\n              deferred.reject(applyNotFoundIndicators(_translationId));\n            });\n        } else if ($missingTranslationHandlerFactory && !pendingLoader && missingTranslationHandlerTranslation) {\n          // looks like the requested translation id doesn't exists.\n          // Now, if there is a registered handler for missing translations and no\n          // asyncLoader is pending, we execute the handler\n          if (defaultTranslationText) {\n            deferred.resolve(defaultTranslationText);\n          } else {\n            deferred.resolve(missingTranslationHandlerTranslation);\n          }\n        } else {\n          if (defaultTranslationText) {\n            deferred.resolve(defaultTranslationText);\n          } else {\n            deferred.reject(applyNotFoundIndicators(translationId));\n          }\n        }\n      }\n      return deferred.promise;\n    };\n\n    var determineTranslationInstant = function (translationId, interpolateParams, interpolationId, uses, sanitizeStrategy) {\n\n      var result, table = uses ? $translationTable[uses] : $translationTable,\n        Interpolator = defaultInterpolator;\n\n      // if the interpolation id exists use custom interpolator\n      if (interpolatorHashMap && Object.prototype.hasOwnProperty.call(interpolatorHashMap, interpolationId)) {\n        Interpolator = interpolatorHashMap[interpolationId];\n      }\n\n      // if the translation id exists, we can just interpolate it\n      if (table && Object.prototype.hasOwnProperty.call(table, translationId) && table[translationId] !== null) {\n        var translation = table[translationId];\n\n        // If using link, rerun $translate with linked translationId and return it\n        if (translation.substr(0, 2) === '@:') {\n          result = determineTranslationInstant(translation.substr(2), interpolateParams, interpolationId, uses, sanitizeStrategy);\n        } else {\n          result = Interpolator.interpolate(translation, interpolateParams, 'filter', sanitizeStrategy, translationId);\n          result = applyPostProcessing(translationId, translation, result, interpolateParams, uses, sanitizeStrategy);\n        }\n      } else {\n        var missingTranslationHandlerTranslation;\n        // for logging purposes only (as in $translateMissingTranslationHandlerLog), value is not returned to promise\n        if ($missingTranslationHandlerFactory && !pendingLoader) {\n          missingTranslationHandlerTranslation = translateByHandler(translationId, interpolateParams, sanitizeStrategy);\n        }\n\n        // since we couldn't translate the inital requested translation id,\n        // we try it now with one or more fallback languages, if fallback language(s) is\n        // configured.\n        if (uses && $fallbackLanguage && $fallbackLanguage.length) {\n          fallbackIndex = 0;\n          result = fallbackTranslationInstant(translationId, interpolateParams, Interpolator, sanitizeStrategy);\n        } else if ($missingTranslationHandlerFactory && !pendingLoader && missingTranslationHandlerTranslation) {\n          // looks like the requested translation id doesn't exists.\n          // Now, if there is a registered handler for missing translations and no\n          // asyncLoader is pending, we execute the handler\n          result = missingTranslationHandlerTranslation;\n        } else {\n          result = applyNotFoundIndicators(translationId);\n        }\n      }\n\n      return result;\n    };\n\n    var clearNextLangAndPromise = function (key) {\n      if ($nextLang === key) {\n        $nextLang = undefined;\n      }\n      langPromises[key] = undefined;\n    };\n\n    var applyPostProcessing = function (translationId, translation, resolvedTranslation, interpolateParams, uses, sanitizeStrategy) {\n      var fn = postProcessFn;\n\n      if (fn) {\n\n        if (typeof(fn) === 'string') {\n          // getting on-demand instance\n          fn = $injector.get(fn);\n        }\n        if (fn) {\n          return fn(translationId, translation, resolvedTranslation, interpolateParams, uses, sanitizeStrategy);\n        }\n      }\n\n      return resolvedTranslation;\n    };\n\n    var loadTranslationsIfMissing = function (key) {\n      if (!$translationTable[key] && $loaderFactory && !langPromises[key]) {\n        langPromises[key] = loadAsync(key).then(function (translation) {\n          translations(translation.key, translation.table);\n          return translation;\n        });\n      }\n    };\n\n    /**\n     * @ngdoc function\n     * @name pascalprecht.translate.$translate#preferredLanguage\n     * @methodOf pascalprecht.translate.$translate\n     *\n     * @description\n     * Returns the language key for the preferred language.\n     *\n     * @param {string} langKey language String or Array to be used as preferredLanguage (changing at runtime)\n     *\n     * @return {string} preferred language key\n     */\n    $translate.preferredLanguage = function (langKey) {\n      if (langKey) {\n        setupPreferredLanguage(langKey);\n      }\n      return $preferredLanguage;\n    };\n\n    /**\n     * @ngdoc function\n     * @name pascalprecht.translate.$translate#cloakClassName\n     * @methodOf pascalprecht.translate.$translate\n     *\n     * @description\n     * Returns the configured class name for `translate-cloak` directive.\n     *\n     * @return {string} cloakClassName\n     */\n    $translate.cloakClassName = function () {\n      return $cloakClassName;\n    };\n\n    /**\n     * @ngdoc function\n     * @name pascalprecht.translate.$translate#nestedObjectDelimeter\n     * @methodOf pascalprecht.translate.$translate\n     *\n     * @description\n     * Returns the configured delimiter for nested namespaces.\n     *\n     * @return {string} nestedObjectDelimeter\n     */\n    $translate.nestedObjectDelimeter = function () {\n      return $nestedObjectDelimeter;\n    };\n\n    /**\n     * @ngdoc function\n     * @name pascalprecht.translate.$translate#fallbackLanguage\n     * @methodOf pascalprecht.translate.$translate\n     *\n     * @description\n     * Returns the language key for the fallback languages or sets a new fallback stack.\n     *\n     * @param {string=} langKey language String or Array of fallback languages to be used (to change stack at runtime)\n     *\n     * @return {string||array} fallback language key\n     */\n    $translate.fallbackLanguage = function (langKey) {\n      if (langKey !== undefined && langKey !== null) {\n        fallbackStack(langKey);\n\n        // as we might have an async loader initiated and a new translation language might have been defined\n        // we need to add the promise to the stack also. So - iterate.\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    };\n\n    /**\n     * @ngdoc function\n     * @name pascalprecht.translate.$translate#useFallbackLanguage\n     * @methodOf pascalprecht.translate.$translate\n     *\n     * @description\n     * Sets the first key of the fallback language stack to be used for translation.\n     * Therefore all languages in the fallback array BEFORE this key will be skipped!\n     *\n     * @param {string=} langKey Contains the langKey the iteration shall start with. Set to false if you want to\n     * get back to the whole stack\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\n    };\n\n    /**\n     * @ngdoc function\n     * @name pascalprecht.translate.$translate#proposedLanguage\n     * @methodOf pascalprecht.translate.$translate\n     *\n     * @description\n     * Returns the language key of language that is currently loaded asynchronously.\n     *\n     * @return {string} language key\n     */\n    $translate.proposedLanguage = function () {\n      return $nextLang;\n    };\n\n    /**\n     * @ngdoc function\n     * @name pascalprecht.translate.$translate#storage\n     * @methodOf pascalprecht.translate.$translate\n     *\n     * @description\n     * Returns registered storage.\n     *\n     * @return {object} Storage\n     */\n    $translate.storage = function () {\n      return Storage;\n    };\n\n    /**\n     * @ngdoc function\n     * @name pascalprecht.translate.$translate#negotiateLocale\n     * @methodOf pascalprecht.translate.$translate\n     *\n     * @description\n     * Returns a language key based on available languages and language aliases. If a\n     * language key cannot be resolved, returns undefined.\n     *\n     * If no or a falsy key is given, returns undefined.\n     *\n     * @param {string} [key] Language key\n     * @return {string|undefined} Language key or undefined if no language key is found.\n     */\n    $translate.negotiateLocale = negotiateLocale;\n\n    /**\n     * @ngdoc function\n     * @name pascalprecht.translate.$translate#use\n     * @methodOf pascalprecht.translate.$translate\n     *\n     * @description\n     * Tells angular-translate which language to use by given language key. This method is\n     * used to change language at runtime. It also takes care of storing the language\n     * key in a configured store to let your app remember the choosed language.\n     *\n     * When trying to 'use' a language which isn't available it tries to load it\n     * asynchronously with registered loaders.\n     *\n     * Returns promise object with loaded language file data or string of the currently used language.\n     *\n     * If no or a falsy key is given it returns the currently used language key.\n     * The returned string will be ```undefined``` if setting up $translate hasn't finished.\n     * @example\n     * $translate.use(\"en_US\").then(function(data){\n       *   $scope.text = $translate(\"HELLO\");\n       * });\n     *\n     * @param {string} [key] Language key\n     * @return {object|string} Promise with loaded language data or the language key if a falsy param was given.\n     */\n    $translate.use = function (key) {\n      if (!key) {\n        return $uses;\n      }\n\n      var deferred = $q.defer();\n      deferred.promise.then(null, angular.noop); // AJS \"Possibly unhandled rejection\"\n\n      $rootScope.$emit('$translateChangeStart', {language : key});\n\n      // Try to get the aliased language key\n      var aliasedKey = negotiateLocale(key);\n      // Ensure only registered language keys will be loaded\n      if ($availableLanguageKeys.length > 0 && !aliasedKey) {\n        return $q.reject(key);\n      }\n\n      if (aliasedKey) {\n        key = aliasedKey;\n      }\n\n      // if there isn't a translation table for the language we've requested,\n      // we load it asynchronously\n      $nextLang = key;\n      if (($forceAsyncReloadEnabled || !$translationTable[key]) && $loaderFactory && !langPromises[key]) {\n        langPromises[key] = loadAsync(key).then(function (translation) {\n          translations(translation.key, translation.table);\n          deferred.resolve(translation.key);\n          if ($nextLang === key) {\n            useLanguage(translation.key);\n          }\n          return translation;\n        }, function (key) {\n          $rootScope.$emit('$translateChangeError', {language : key});\n          deferred.reject(key);\n          $rootScope.$emit('$translateChangeEnd', {language : key});\n          return $q.reject(key);\n        });\n        langPromises[key]['finally'](function () {\n          clearNextLangAndPromise(key);\n        }).catch(angular.noop); // we don't care about errors (clearing)\n      } else if (langPromises[key]) {\n        // we are already loading this asynchronously\n        // resolve our new deferred when the old langPromise is resolved\n        langPromises[key].then(function (translation) {\n          if ($nextLang === translation.key) {\n            useLanguage(translation.key);\n          }\n          deferred.resolve(translation.key);\n          return translation;\n        }, function (key) {\n          // find first available fallback language if that request has failed\n          if (!$uses && $fallbackLanguage && $fallbackLanguage.length > 0 && $fallbackLanguage[0] !== key) {\n            return $translate.use($fallbackLanguage[0]).then(deferred.resolve, deferred.reject);\n          } else {\n            return deferred.reject(key);\n          }\n        });\n      } else {\n        deferred.resolve(key);\n        useLanguage(key);\n      }\n\n      return deferred.promise;\n    };\n\n    /**\n     * @ngdoc function\n     * @name pascalprecht.translate.$translate#resolveClientLocale\n     * @methodOf pascalprecht.translate.$translate\n     *\n     * @description\n     * This returns the current browser/client's language key. The result is processed with the configured uniform tag resolver.\n     *\n     * @returns {string} the current client/browser language key\n     */\n    $translate.resolveClientLocale = function () {\n      return getLocale();\n    };\n\n    /**\n     * @ngdoc function\n     * @name pascalprecht.translate.$translate#storageKey\n     * @methodOf pascalprecht.translate.$translate\n     *\n     * @description\n     * Returns the key for the storage.\n     *\n     * @return {string} storage key\n     */\n    $translate.storageKey = function () {\n      return storageKey();\n    };\n\n    /**\n     * @ngdoc function\n     * @name pascalprecht.translate.$translate#isPostCompilingEnabled\n     * @methodOf pascalprecht.translate.$translate\n     *\n     * @description\n     * Returns whether post compiling is enabled or not\n     *\n     * @return {bool} storage key\n     */\n    $translate.isPostCompilingEnabled = function () {\n      return $postCompilingEnabled;\n    };\n\n    /**\n     * @ngdoc function\n     * @name pascalprecht.translate.$translate#isForceAsyncReloadEnabled\n     * @methodOf pascalprecht.translate.$translate\n     *\n     * @description\n     * Returns whether force async reload is enabled or not\n     *\n     * @return {boolean} forceAsyncReload value\n     */\n    $translate.isForceAsyncReloadEnabled = function () {\n      return $forceAsyncReloadEnabled;\n    };\n\n    /**\n     * @ngdoc function\n     * @name pascalprecht.translate.$translate#isKeepContent\n     * @methodOf pascalprecht.translate.$translate\n     *\n     * @description\n     * Returns whether keepContent or not\n     *\n     * @return {boolean} keepContent value\n     */\n    $translate.isKeepContent = function () {\n      return $keepContent;\n    };\n\n    /**\n     * @ngdoc function\n     * @name pascalprecht.translate.$translate#refresh\n     * @methodOf pascalprecht.translate.$translate\n     *\n     * @description\n     * Refreshes a translation table pointed by the given langKey. If langKey is not specified,\n     * the module will drop all existent translation tables and load new version of those which\n     * are currently in use.\n     *\n     * Refresh means that the module will drop target translation table and try to load it again.\n     *\n     * In case there are no loaders registered the refresh() method will throw an Error.\n     *\n     * If the module is able to refresh translation tables refresh() method will broadcast\n     * $translateRefreshStart and $translateRefreshEnd events.\n     *\n     * @example\n     * // this will drop all currently existent translation tables and reload those which are\n     * // currently in use\n     * $translate.refresh();\n     * // this will refresh a translation table for the en_US language\n     * $translate.refresh('en_US');\n     *\n     * @param {string} langKey A language key of the table, which has to be refreshed\n     *\n     * @return {promise} Promise, which will be resolved in case a translation tables refreshing\n     * process is finished successfully, and reject if not.\n     */\n    $translate.refresh = function (langKey) {\n      if (!$loaderFactory) {\n        throw new Error('Couldn\\'t refresh translation table, no loader registered!');\n      }\n\n      $rootScope.$emit('$translateRefreshStart', {language : langKey});\n\n      var deferred = $q.defer(), updatedLanguages = {};\n\n      //private helper\n      function loadNewData(languageKey) {\n        var promise = loadAsync(languageKey);\n        //update the load promise cache for this language\n        langPromises[languageKey] = promise;\n        //register a data handler for the promise\n        promise.then(function (data) {\n            //clear the cache for this language\n            $translationTable[languageKey] = {};\n            //add the new data for this language\n            translations(languageKey, data.table);\n            //track that we updated this language\n            updatedLanguages[languageKey] = true;\n          },\n          //handle rejection to appease the $q validation\n          angular.noop);\n        return promise;\n      }\n\n      //set up post-processing\n      deferred.promise.then(\n        function () {\n          for (var key in $translationTable) {\n            if ($translationTable.hasOwnProperty(key)) {\n              //delete cache entries that were not updated\n              if (!(key in updatedLanguages)) {\n                delete $translationTable[key];\n              }\n            }\n          }\n          if ($uses) {\n            useLanguage($uses);\n          }\n        },\n        //handle rejection to appease the $q validation\n        angular.noop\n      ).finally(\n        function () {\n          $rootScope.$emit('$translateRefreshEnd', {language : langKey});\n        }\n      );\n\n      if (!langKey) {\n        // if there's no language key specified we refresh ALL THE THINGS!\n        var languagesToReload = $fallbackLanguage && $fallbackLanguage.slice() || [];\n        if ($uses && languagesToReload.indexOf($uses) === -1) {\n          languagesToReload.push($uses);\n        }\n        $q.all(languagesToReload.map(loadNewData)).then(deferred.resolve, deferred.reject);\n\n      } else if ($translationTable[langKey]) {\n        //just refresh the specified language cache\n        loadNewData(langKey).then(deferred.resolve, deferred.reject);\n\n      } else {\n        deferred.reject();\n      }\n\n      return deferred.promise;\n    };\n\n    /**\n     * @ngdoc function\n     * @name pascalprecht.translate.$translate#instant\n     * @methodOf pascalprecht.translate.$translate\n     *\n     * @description\n     * Returns a translation instantly from the internal state of loaded translation. All rules\n     * regarding the current language, the preferred language of even fallback languages will be\n     * used except any promise handling. If a language was not found, an asynchronous loading\n     * will be invoked in the background.\n     *\n     * @param {string|array} translationId A token which represents a translation id\n     *                                     This can be optionally an array of translation ids which\n     *                                     results that the function's promise returns an object where\n     *                                     each key is the translation id and the value the translation.\n     * @param {object} interpolateParams Params\n     * @param {string} interpolationId The id of the interpolation to use\n     * @param {string} forceLanguage A language to be used instead of the current language\n     * @param {string} sanitizeStrategy force sanitize strategy for this call instead of using the configured one\n     *\n     * @return {string|object} translation\n     */\n    $translate.instant = function (translationId, interpolateParams, interpolationId, forceLanguage, sanitizeStrategy) {\n\n      // we don't want to re-negotiate $uses\n      var uses = (forceLanguage && forceLanguage !== $uses) ? // we don't want to re-negotiate $uses\n        (negotiateLocale(forceLanguage) || forceLanguage) : $uses;\n\n      // Detect undefined and null values to shorten the execution and prevent exceptions\n      if (translationId === null || angular.isUndefined(translationId)) {\n        return translationId;\n      }\n\n      // Check forceLanguage is present\n      if (forceLanguage) {\n        loadTranslationsIfMissing(forceLanguage);\n      }\n\n      // Duck detection: If the first argument is an array, a bunch of translations was requested.\n      // The result is an object.\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, forceLanguage, sanitizeStrategy);\n        }\n        return results;\n      }\n\n      // We discarded unacceptable values. So we just need to verify if translationId is empty String\n      if (angular.isString(translationId) && translationId.length < 1) {\n        return translationId;\n      }\n\n      // trim off any whitespace\n      if (translationId) {\n        translationId = trim.apply(translationId);\n      }\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, uses, sanitizeStrategy);\n          }\n        }\n        if (typeof result !== 'undefined') {\n          break;\n        }\n      }\n\n      if (!result && result !== '') {\n        if ($notFoundIndicatorLeft || $notFoundIndicatorRight) {\n          result = applyNotFoundIndicators(translationId);\n        } else {\n          // Return translation of default interpolator if not found anything.\n          result = defaultInterpolator.interpolate(translationId, interpolateParams, 'filter', sanitizeStrategy);\n\n          // looks like the requested translation id doesn't exists.\n          // Now, if there is a registered handler for missing translations and no\n          // asyncLoader is pending, we execute the handler\n          var missingTranslationHandlerTranslation;\n          if ($missingTranslationHandlerFactory && !pendingLoader) {\n            missingTranslationHandlerTranslation = translateByHandler(translationId, interpolateParams, sanitizeStrategy);\n          }\n\n          if ($missingTranslationHandlerFactory && !pendingLoader && missingTranslationHandlerTranslation) {\n            result = missingTranslationHandlerTranslation;\n          }\n        }\n      }\n\n      return result;\n    };\n\n    /**\n     * @ngdoc function\n     * @name pascalprecht.translate.$translate#versionInfo\n     * @methodOf pascalprecht.translate.$translate\n     *\n     * @description\n     * Returns the current version information for the angular-translate library\n     *\n     * @return {string} angular-translate version\n     */\n    $translate.versionInfo = function () {\n      return version;\n    };\n\n    /**\n     * @ngdoc function\n     * @name pascalprecht.translate.$translate#loaderCache\n     * @methodOf pascalprecht.translate.$translate\n     *\n     * @description\n     * Returns the defined loaderCache.\n     *\n     * @return {boolean|string|object} current value of loaderCache\n     */\n    $translate.loaderCache = function () {\n      return loaderCache;\n    };\n\n    // internal purpose only\n    $translate.directivePriority = function () {\n      return directivePriority;\n    };\n\n    // internal purpose only\n    $translate.statefulFilter = function () {\n      return statefulFilter;\n    };\n\n    /**\n     * @ngdoc function\n     * @name pascalprecht.translate.$translate#isReady\n     * @methodOf pascalprecht.translate.$translate\n     *\n     * @description\n     * Returns whether the service is \"ready\" to translate (i.e. loading 1st language).\n     *\n     * See also {@link pascalprecht.translate.$translate#methods_onReady onReady()}.\n     *\n     * @return {boolean} current value of ready\n     */\n    $translate.isReady = function () {\n      return $isReady;\n    };\n\n    var $onReadyDeferred = $q.defer();\n    $onReadyDeferred.promise.then(function () {\n      $isReady = true;\n    });\n\n    /**\n     * @ngdoc function\n     * @name pascalprecht.translate.$translate#onReady\n     * @methodOf pascalprecht.translate.$translate\n     *\n     * @description\n     * Calls the function provided or resolved the returned promise after the service is \"ready\" to translate (i.e. loading 1st language).\n     *\n     * See also {@link pascalprecht.translate.$translate#methods_isReady isReady()}.\n     *\n     * @param {Function=} fn Function to invoke when service is ready\n     * @return {object} Promise resolved when service is ready\n     */\n    $translate.onReady = function (fn) {\n      var deferred = $q.defer();\n      if (angular.isFunction(fn)) {\n        deferred.promise.then(fn);\n      }\n      if ($isReady) {\n        deferred.resolve();\n      } else {\n        $onReadyDeferred.promise.then(deferred.resolve);\n      }\n      return deferred.promise;\n    };\n\n    /**\n     * @ngdoc function\n     * @name pascalprecht.translate.$translate#getAvailableLanguageKeys\n     * @methodOf pascalprecht.translate.$translate\n     *\n     * @description\n     * This function simply returns the registered language keys being defined before in the config phase\n     * With this, an application can use the array to provide a language selection dropdown or similar\n     * without any additional effort\n     *\n     * @returns {object} returns the list of possibly registered language keys and mapping or null if not defined\n     */\n    $translate.getAvailableLanguageKeys = function () {\n      if ($availableLanguageKeys.length > 0) {\n        return $availableLanguageKeys;\n      }\n      return null;\n    };\n\n    /**\n     * @ngdoc function\n     * @name pascalprecht.translate.$translate#getTranslationTable\n     * @methodOf pascalprecht.translate.$translate\n     *\n     * @description\n     * Returns translation table by the given language key.\n     *\n     * Unless a language is provided it returns a translation table of the current one.\n     * Note: If translation dictionary is currently downloading or in progress\n     * it will return null.\n     *\n     * @param {string} langKey A token which represents a translation id\n     *\n     * @return {object} a copy of angular-translate $translationTable\n     */\n    $translate.getTranslationTable = function (langKey) {\n      langKey = langKey || $translate.use();\n      if (langKey && $translationTable[langKey]) {\n        return angular.copy($translationTable[langKey]);\n      }\n      return null;\n    };\n\n    // Whenever $translateReady is being fired, this will ensure the state of $isReady\n    var globalOnReadyListener = $rootScope.$on('$translateReady', function () {\n      $onReadyDeferred.resolve();\n      globalOnReadyListener(); // one time only\n      globalOnReadyListener = null;\n    });\n    var globalOnChangeListener = $rootScope.$on('$translateChangeEnd', function () {\n      $onReadyDeferred.resolve();\n      globalOnChangeListener(); // one time only\n      globalOnChangeListener = null;\n    });\n\n    if ($loaderFactory) {\n\n      // If at least one async loader is defined and there are no\n      // (default) translations available we should try to load them.\n      if (angular.equals($translationTable, {})) {\n        if ($translate.use()) {\n          $translate.use($translate.use());\n        }\n      }\n\n      // Also, if there are any fallback language registered, we start\n      // loading them asynchronously as soon as we can.\n      if ($fallbackLanguage && $fallbackLanguage.length) {\n        var processAsyncResult = function (translation) {\n          translations(translation.key, translation.table);\n          $rootScope.$emit('$translateChangeEnd', {language : translation.key});\n          return translation;\n        };\n        for (var i = 0, len = $fallbackLanguage.length; i < len; i++) {\n          var fallbackLanguageId = $fallbackLanguage[i];\n          if ($forceAsyncReloadEnabled || !$translationTable[fallbackLanguageId]) {\n            langPromises[fallbackLanguageId] = loadAsync(fallbackLanguageId).then(processAsyncResult);\n          }\n        }\n      }\n    } else {\n      $rootScope.$emit('$translateReady', {language : $translate.use()});\n    }\n\n    return $translate;\n  }];\n}\n\n$translate.displayName = 'displayName';\n\n/**\n * @ngdoc object\n * @name pascalprecht.translate.$translateDefaultInterpolation\n * @requires $interpolate\n *\n * @description\n * Uses angular's `$interpolate` services to interpolate strings against some values.\n *\n * Be aware to configure a proper sanitization strategy.\n *\n * See also:\n * * {@link pascalprecht.translate.$translateSanitization}\n *\n * @return {object} $translateDefaultInterpolation Interpolator service\n */\nangular.module('pascalprecht.translate').factory('$translateDefaultInterpolation', $translateDefaultInterpolation);\n\nfunction $translateDefaultInterpolation ($interpolate, $translateSanitization) {\n\n  'use strict';\n\n  var $translateInterpolator = {},\n      $locale,\n      $identifier = 'default';\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateDefaultInterpolation#setLocale\n   * @methodOf pascalprecht.translate.$translateDefaultInterpolation\n   *\n   * @description\n   * Sets current locale (this is currently not use in this interpolation).\n   *\n   * @param {string} locale Language key or locale.\n   */\n  $translateInterpolator.setLocale = function (locale) {\n    $locale = locale;\n  };\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateDefaultInterpolation#getInterpolationIdentifier\n   * @methodOf pascalprecht.translate.$translateDefaultInterpolation\n   *\n   * @description\n   * Returns an identifier for this interpolation service.\n   *\n   * @returns {string} $identifier\n   */\n  $translateInterpolator.getInterpolationIdentifier = function () {\n    return $identifier;\n  };\n\n  /**\n   * @deprecated will be removed in 3.0\n   * @see {@link pascalprecht.translate.$translateSanitization}\n   */\n  $translateInterpolator.useSanitizeValueStrategy = function (value) {\n    $translateSanitization.useStrategy(value);\n    return this;\n  };\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateDefaultInterpolation#interpolate\n   * @methodOf pascalprecht.translate.$translateDefaultInterpolation\n   *\n   * @description\n   * Interpolates given value agains given interpolate params using angulars\n   * `$interpolate` service.\n   *\n   * Since AngularJS 1.5, `value` must not be a string but can be anything input.\n   *\n   * @param {string} value translation\n   * @param {object} interpolationParams interpolation params\n   * @param {string} context current context (filter, directive, service)\n   * @param {string} sanitizeStrategy sanitize strategy\n   * @param {string} translationId current translationId\n   *\n   * @returns {string} interpolated string\n   */\n  $translateInterpolator.interpolate = function (value, interpolationParams, context, sanitizeStrategy, translationId) { // jshint ignore:line\n    interpolationParams = interpolationParams || {};\n    interpolationParams = $translateSanitization.sanitize(interpolationParams, 'params', sanitizeStrategy, context);\n\n    var interpolatedText;\n    if (angular.isNumber(value)) {\n      // numbers are safe\n      interpolatedText = '' + value;\n    } else if (angular.isString(value)) {\n      // strings must be interpolated (that's the job here)\n      interpolatedText = $interpolate(value)(interpolationParams);\n      interpolatedText = $translateSanitization.sanitize(interpolatedText, 'text', sanitizeStrategy, context);\n    } else {\n      // neither a number or a string, cant interpolate => empty string\n      interpolatedText = '';\n    }\n\n    return interpolatedText;\n  };\n\n  return $translateInterpolator;\n}\n\n$translateDefaultInterpolation.displayName = '$translateDefaultInterpolation';\n\nangular.module('pascalprecht.translate').constant('$STORAGE_KEY', 'NG_TRANSLATE_LANG_KEY');\n\nangular.module('pascalprecht.translate')\n/**\n * @ngdoc directive\n * @name pascalprecht.translate.directive:translate\n * @requires $interpolate, \n * @requires $compile, \n * @requires $parse, \n * @requires $rootScope\n * @restrict AE\n *\n * @description\n * Translates given translation id either through attribute or DOM content.\n * Internally it uses $translate service to translate the translation id. It possible to\n * pass an optional `translate-values` object literal as string into translation id.\n *\n * @param {string=} translate Translation id which could be either string or interpolated string.\n * @param {string=} translate-values Values to pass into translation id. Can be passed as object literal string or interpolated object.\n * @param {string=} translate-attr-ATTR translate Translation id and put it into ATTR attribute.\n * @param {string=} translate-default will be used unless translation was successful\n * @param {boolean=} translate-compile (default true if present) defines locally activation of {@link pascalprecht.translate.$translateProvider#methods_usePostCompiling}\n * @param {boolean=} translate-keep-content (default true if present) defines that in case a KEY could not be translated, that the existing content is left in the innerHTML}\n *\n * @example\n   <example module=\"ngView\">\n    <file name=\"index.html\">\n      <div ng-controller=\"TranslateCtrl\">\n\n        <pre translate=\"TRANSLATION_ID\"></pre>\n        <pre translate>TRANSLATION_ID</pre>\n        <pre translate translate-attr-title=\"TRANSLATION_ID\"></pre>\n        <pre translate=\"{{translationId}}\"></pre>\n        <pre translate>{{translationId}}</pre>\n        <pre translate=\"WITH_VALUES\" translate-values=\"{value: 5}\"></pre>\n        <pre translate translate-values=\"{value: 5}\">WITH_VALUES</pre>\n        <pre translate=\"WITH_VALUES\" translate-values=\"{{values}}\"></pre>\n        <pre translate translate-values=\"{{values}}\">WITH_VALUES</pre>\n        <pre translate translate-attr-title=\"WITH_VALUES\" translate-values=\"{{values}}\"></pre>\n        <pre translate=\"WITH_CAMEL_CASE_KEY\" translate-value-camel-case-key=\"Hi\"></pre>\n\n      </div>\n    </file>\n    <file name=\"script.js\">\n      angular.module('ngView', ['pascalprecht.translate'])\n\n      .config(function ($translateProvider) {\n\n        $translateProvider.translations('en',{\n          'TRANSLATION_ID': 'Hello there!',\n          'WITH_VALUES': 'The following value is dynamic: {{value}}',\n          'WITH_CAMEL_CASE_KEY': 'The interpolation key is camel cased: {{camelCaseKey}}'\n        }).preferredLanguage('en');\n\n      });\n\n      angular.module('ngView').controller('TranslateCtrl', function ($scope) {\n        $scope.translationId = 'TRANSLATION_ID';\n\n        $scope.values = {\n          value: 78\n        };\n      });\n    </file>\n    <file name=\"scenario.js\">\n      it('should translate', function () {\n        inject(function ($rootScope, $compile) {\n          $rootScope.translationId = 'TRANSLATION_ID';\n\n          element = $compile('<p translate=\"TRANSLATION_ID\"></p>')($rootScope);\n          $rootScope.$digest();\n          expect(element.text()).toBe('Hello there!');\n\n          element = $compile('<p translate=\"{{translationId}}\"></p>')($rootScope);\n          $rootScope.$digest();\n          expect(element.text()).toBe('Hello there!');\n\n          element = $compile('<p translate>TRANSLATION_ID</p>')($rootScope);\n          $rootScope.$digest();\n          expect(element.text()).toBe('Hello there!');\n\n          element = $compile('<p translate>{{translationId}}</p>')($rootScope);\n          $rootScope.$digest();\n          expect(element.text()).toBe('Hello there!');\n\n          element = $compile('<p translate translate-attr-title=\"TRANSLATION_ID\"></p>')($rootScope);\n          $rootScope.$digest();\n          expect(element.attr('title')).toBe('Hello there!');\n\n          element = $compile('<p translate=\"WITH_CAMEL_CASE_KEY\" translate-value-camel-case-key=\"Hello\"></p>')($rootScope);\n          $rootScope.$digest();\n          expect(element.text()).toBe('The interpolation key is camel cased: Hello');\n        });\n      });\n    </file>\n   </example>\n */\n.directive('translate', translateDirective);\nfunction translateDirective($translate, $interpolate, $compile, $parse, $rootScope) {\n\n  'use strict';\n\n  /**\n   * @name trim\n   * @private\n   *\n   * @description\n   * trim polyfill\n   *\n   * @returns {string} The string stripped of whitespace from both ends\n   */\n  var trim = function() {\n    return this.toString().replace(/^\\s+|\\s+$/g, '');\n  };\n\n  return {\n    restrict: 'AE',\n    scope: true,\n    priority: $translate.directivePriority(),\n    compile: function (tElement, tAttr) {\n\n      var translateValuesExist = (tAttr.translateValues) ?\n        tAttr.translateValues : undefined;\n\n      var translateInterpolation = (tAttr.translateInterpolation) ?\n        tAttr.translateInterpolation : undefined;\n\n      var translateValueExist = tElement[0].outerHTML.match(/translate-value-+/i);\n\n      var interpolateRegExp = '^(.*)(' + $interpolate.startSymbol() + '.*' + $interpolate.endSymbol() + ')(.*)',\n          watcherRegExp = '^(.*)' + $interpolate.startSymbol() + '(.*)' + $interpolate.endSymbol() + '(.*)';\n\n      return function linkFn(scope, iElement, iAttr) {\n\n        scope.interpolateParams = {};\n        scope.preText = '';\n        scope.postText = '';\n        scope.translateNamespace = getTranslateNamespace(scope);\n        var translationIds = {};\n\n        var initInterpolationParams = function (interpolateParams, iAttr, tAttr) {\n          // initial setup\n          if (iAttr.translateValues) {\n            angular.extend(interpolateParams, $parse(iAttr.translateValues)(scope.$parent));\n          }\n          // initially fetch all attributes if existing and fill the params\n          if (translateValueExist) {\n            for (var attr in tAttr) {\n              if (Object.prototype.hasOwnProperty.call(iAttr, attr) && attr.substr(0, 14) === 'translateValue' && attr !== 'translateValues') {\n                var attributeName = angular.lowercase(attr.substr(14, 1)) + attr.substr(15);\n                interpolateParams[attributeName] = tAttr[attr];\n              }\n            }\n          }\n        };\n\n        // Ensures any change of the attribute \"translate\" containing the id will\n        // be re-stored to the scope's \"translationId\".\n        // If the attribute has no content, the element's text value (white spaces trimmed off) will be used.\n        var observeElementTranslation = function (translationId) {\n\n          // Remove any old watcher\n          if (angular.isFunction(observeElementTranslation._unwatchOld)) {\n            observeElementTranslation._unwatchOld();\n            observeElementTranslation._unwatchOld = undefined;\n          }\n\n          if (angular.equals(translationId , '') || !angular.isDefined(translationId)) {\n            var iElementText = trim.apply(iElement.text());\n\n            // Resolve translation id by inner html if required\n            var interpolateMatches = iElementText.match(interpolateRegExp);\n            // Interpolate translation id if required\n            if (angular.isArray(interpolateMatches)) {\n              scope.preText = interpolateMatches[1];\n              scope.postText = interpolateMatches[3];\n              translationIds.translate = $interpolate(interpolateMatches[2])(scope.$parent);\n              var watcherMatches = iElementText.match(watcherRegExp);\n              if (angular.isArray(watcherMatches) && watcherMatches[2] && watcherMatches[2].length) {\n                observeElementTranslation._unwatchOld = scope.$watch(watcherMatches[2], function (newValue) {\n                  translationIds.translate = newValue;\n                  updateTranslations();\n                });\n              }\n            } else {\n              // do not assigne the translation id if it is empty.\n              translationIds.translate = !iElementText ? undefined : iElementText;\n            }\n          } else {\n            translationIds.translate = translationId;\n          }\n          updateTranslations();\n        };\n\n        var observeAttributeTranslation = function (translateAttr) {\n          iAttr.$observe(translateAttr, function (translationId) {\n            translationIds[translateAttr] = translationId;\n            updateTranslations();\n          });\n        };\n\n        // initial setup with values\n        initInterpolationParams(scope.interpolateParams, iAttr, tAttr);\n\n        var firstAttributeChangedEvent = true;\n        iAttr.$observe('translate', function (translationId) {\n          if (typeof translationId === 'undefined') {\n            // case of element \"<translate>xyz</translate>\"\n            observeElementTranslation('');\n          } else {\n            // case of regular attribute\n            if (translationId !== '' || !firstAttributeChangedEvent) {\n              translationIds.translate = translationId;\n              updateTranslations();\n            }\n          }\n          firstAttributeChangedEvent = false;\n        });\n\n        for (var translateAttr in iAttr) {\n          if (iAttr.hasOwnProperty(translateAttr) && translateAttr.substr(0, 13) === 'translateAttr' && translateAttr.length > 13) {\n            observeAttributeTranslation(translateAttr);\n          }\n        }\n\n        iAttr.$observe('translateDefault', function (value) {\n          scope.defaultText = value;\n          updateTranslations();\n        });\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\n        if (translateValueExist) {\n          var observeValueAttribute = function (attrName) {\n            iAttr.$observe(attrName, function (value) {\n              var attributeName = angular.lowercase(attrName.substr(14, 1)) + attrName.substr(15);\n              scope.interpolateParams[attributeName] = 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              observeValueAttribute(attr);\n            }\n          }\n        }\n\n        // Master update function\n        var updateTranslations = function () {\n          for (var key in translationIds) {\n            if (translationIds.hasOwnProperty(key) && translationIds[key] !== undefined) {\n              updateTranslation(key, translationIds[key], scope, scope.interpolateParams, scope.defaultText, scope.translateNamespace);\n            }\n          }\n        };\n\n        // Put translation processing function outside loop\n        var updateTranslation = function(translateAttr, translationId, scope, interpolateParams, defaultTranslationText, translateNamespace) {\n          if (translationId) {\n            // if translation id starts with '.' and translateNamespace given, prepend namespace\n            if (translateNamespace && translationId.charAt(0) === '.') {\n              translationId = translateNamespace + translationId;\n            }\n\n            $translate(translationId, interpolateParams, translateInterpolation, defaultTranslationText, scope.translateLanguage)\n              .then(function (translation) {\n                applyTranslation(translation, scope, true, translateAttr);\n              }, function (translationId) {\n                applyTranslation(translationId, scope, false, translateAttr);\n              });\n          } else {\n            // as an empty string cannot be translated, we can solve this using successful=false\n            applyTranslation(translationId, scope, false, translateAttr);\n          }\n        };\n\n        var applyTranslation = function (value, scope, successful, translateAttr) {\n          if (!successful) {\n            if (typeof scope.defaultText !== 'undefined') {\n              value = scope.defaultText;\n            }\n          }\n          if (translateAttr === 'translate') {\n            // default translate into innerHTML\n            if (successful || (!successful && !$translate.isKeepContent() && typeof iAttr.translateKeepContent === 'undefined')) {\n              iElement.empty().append(scope.preText + value + scope.postText);\n            }\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          } else {\n            // translate attribute\n            var attributeName = iAttr.$attr[translateAttr];\n            if (attributeName.substr(0, 5) === 'data-') {\n              // ensure html5 data prefix is stripped\n              attributeName = attributeName.substr(5);\n            }\n            attributeName = attributeName.substr(15);\n            iElement.attr(attributeName, value);\n          }\n        };\n\n        if (translateValuesExist || translateValueExist || iAttr.translateDefault) {\n          scope.$watch('interpolateParams', updateTranslations, true);\n        }\n\n        // Replaced watcher on translateLanguage with event listener\n        scope.$on('translateLanguageChanged', updateTranslations);\n\n        // Ensures the text will be refreshed after the current language was changed\n        // w/ $translate.use(...)\n        var unbind = $rootScope.$on('$translateChangeSuccess', updateTranslations);\n\n        // ensure translation will be looked up at least one\n        if (iElement.text().length) {\n          if (iAttr.translate) {\n            observeElementTranslation(iAttr.translate);\n          } else {\n            observeElementTranslation('');\n          }\n        } else if (iAttr.translate) {\n          // ensure attribute will be not skipped\n          observeElementTranslation(iAttr.translate);\n        }\n        updateTranslations();\n        scope.$on('$destroy', unbind);\n      };\n    }\n  };\n}\n\n/**\n * Returns the scope's namespace.\n * @private\n * @param scope\n * @returns {string}\n */\nfunction getTranslateNamespace(scope) {\n  'use strict';\n  if (scope.translateNamespace) {\n    return scope.translateNamespace;\n  }\n  if (scope.$parent) {\n    return getTranslateNamespace(scope.$parent);\n  }\n}\n\ntranslateDirective.displayName = 'translateDirective';\n\nangular.module('pascalprecht.translate')\n/**\n * @ngdoc directive\n * @name pascalprecht.translate.directive:translate-attr\n * @restrict A\n *\n * @description\n * Translates attributes like translate-attr-ATTR, but with an object like ng-class.\n * Internally it uses `translate` service to translate translation id. It possible to\n * pass an optional `translate-values` object literal as string into translation id.\n *\n * @param {string=} translate-attr Object literal mapping attributes to translation ids.\n * @param {string=} translate-values Values to pass into the translation ids. Can be passed as object literal string.\n *\n * @example\n   <example module=\"ngView\">\n    <file name=\"index.html\">\n      <div ng-controller=\"TranslateCtrl\">\n\n        <input translate-attr=\"{ placeholder: translationId, title: 'WITH_VALUES' }\" translate-values=\"{value: 5}\" />\n\n      </div>\n    </file>\n    <file name=\"script.js\">\n      angular.module('ngView', ['pascalprecht.translate'])\n\n      .config(function ($translateProvider) {\n\n        $translateProvider.translations('en',{\n          'TRANSLATION_ID': 'Hello there!',\n          'WITH_VALUES': 'The following value is dynamic: {{value}}',\n        }).preferredLanguage('en');\n\n      });\n\n      angular.module('ngView').controller('TranslateCtrl', function ($scope) {\n        $scope.translationId = 'TRANSLATION_ID';\n\n        $scope.values = {\n          value: 78\n        };\n      });\n    </file>\n    <file name=\"scenario.js\">\n      it('should translate', function () {\n        inject(function ($rootScope, $compile) {\n          $rootScope.translationId = 'TRANSLATION_ID';\n\n          element = $compile('<input translate-attr=\"{ placeholder: translationId, title: 'WITH_VALUES' }\" translate-values=\"{ value: 5 }\" />')($rootScope);\n          $rootScope.$digest();\n          expect(element.attr('placeholder)).toBe('Hello there!');\n          expect(element.attr('title)).toBe('The following value is dynamic: 5');\n        });\n      });\n    </file>\n   </example>\n */\n.directive('translateAttr', translateAttrDirective);\nfunction translateAttrDirective($translate, $rootScope) {\n\n  'use strict';\n\n  return {\n    restrict: 'A',\n    priority: $translate.directivePriority(),\n    link: function linkFn(scope, element, attr) {\n\n      var translateAttr,\n          translateValues,\n          previousAttributes = {};\n\n      // Main update translations function\n      var updateTranslations = function () {\n        angular.forEach(translateAttr, function (translationId, attributeName) {\n          if (!translationId) {\n            return;\n          }\n          previousAttributes[attributeName] = true;\n\n          // if translation id starts with '.' and translateNamespace given, prepend namespace\n          if (scope.translateNamespace && translationId.charAt(0) === '.') {\n            translationId = scope.translateNamespace + translationId;\n          }\n          $translate(translationId, translateValues, attr.translateInterpolation, undefined, scope.translateLanguage)\n            .then(function (translation) {\n              element.attr(attributeName, translation);\n            }, function (translationId) {\n              element.attr(attributeName, translationId);\n            });\n        });\n\n        // Removing unused attributes that were previously used\n        angular.forEach(previousAttributes, function (flag, attributeName) {\n          if (!translateAttr[attributeName]) {\n            element.removeAttr(attributeName);\n            delete previousAttributes[attributeName];\n          }\n        });\n      };\n\n      // Watch for attribute changes\n      watchAttribute(\n        scope,\n        attr.translateAttr,\n        function (newValue) { translateAttr = newValue; },\n        updateTranslations\n      );\n      // Watch for value changes\n      watchAttribute(\n        scope,\n        attr.translateValues,\n        function (newValue) { translateValues = newValue; },\n        updateTranslations\n      );\n\n      if (attr.translateValues) {\n        scope.$watch(attr.translateValues, updateTranslations, true);\n      }\n\n      // Replaced watcher on translateLanguage with event listener\n      scope.$on('translateLanguageChanged', updateTranslations);\n\n      // Ensures the text will be refreshed after the current language was changed\n      // w/ $translate.use(...)\n      var unbind = $rootScope.$on('$translateChangeSuccess', updateTranslations);\n\n      updateTranslations();\n      scope.$on('$destroy', unbind);\n    }\n  };\n}\n\nfunction watchAttribute(scope, attribute, valueCallback, changeCallback) {\n  'use strict';\n  if (!attribute) {\n    return;\n  }\n  if (attribute.substr(0, 2) === '::') {\n    attribute = attribute.substr(2);\n  } else {\n    scope.$watch(attribute, function(newValue) {\n      valueCallback(newValue);\n      changeCallback();\n    }, true);\n  }\n  valueCallback(scope.$eval(attribute));\n}\n\ntranslateAttrDirective.displayName = 'translateAttrDirective';\n\nangular.module('pascalprecht.translate')\n/**\n * @ngdoc directive\n * @name pascalprecht.translate.directive:translateCloak\n * @requires $translate\n * @restrict A\n *\n * $description\n * Adds a `translate-cloak` class name to the given element where this directive\n * is applied initially and removes it, once a loader has finished loading.\n *\n * This directive can be used to prevent initial flickering when loading translation\n * data asynchronously.\n *\n * The class name is defined in\n * {@link pascalprecht.translate.$translateProvider#cloakClassName $translate.cloakClassName()}.\n *\n * @param {string=} translate-cloak If a translationId is provided, it will be used for showing\n *                                  or hiding the cloak. Basically it relies on the translation\n *                                  resolve.\n */\n.directive('translateCloak', translateCloakDirective);\n\nfunction translateCloakDirective($translate, $rootScope) {\n\n  'use strict';\n\n  return {\n    compile : function (tElement) {\n      var applyCloak = function (element) {\n          element.addClass($translate.cloakClassName());\n        },\n        removeCloak = function (element) {\n          element.removeClass($translate.cloakClassName());\n        };\n      applyCloak(tElement);\n\n      return function linkFn(scope, iElement, iAttr) {\n        //Create bound functions that incorporate the active DOM element.\n        var iRemoveCloak = removeCloak.bind(this, iElement), iApplyCloak = applyCloak.bind(this, iElement);\n        if (iAttr.translateCloak && iAttr.translateCloak.length) {\n          // Register a watcher for the defined translation allowing a fine tuned cloak\n          iAttr.$observe('translateCloak', function (translationId) {\n            $translate(translationId).then(iRemoveCloak, iApplyCloak);\n          });\n          $rootScope.$on('$translateChangeSuccess', function () {\n            $translate(iAttr.translateCloak).then(iRemoveCloak, iApplyCloak);\n          });\n        } else {\n          $translate.onReady(iRemoveCloak);\n        }\n      };\n    }\n  };\n}\n\ntranslateCloakDirective.displayName = 'translateCloakDirective';\n\nangular.module('pascalprecht.translate')\n/**\n * @ngdoc directive\n * @name pascalprecht.translate.directive:translateNamespace\n * @restrict A\n *\n * @description\n * Translates given translation id either through attribute or DOM content.\n * Internally it uses `translate` filter to translate translation id. It possible to\n * pass an optional `translate-values` object literal as string into translation id.\n *\n * @param {string=} translate namespace name which could be either string or interpolated string.\n *\n * @example\n   <example module=\"ngView\">\n    <file name=\"index.html\">\n      <div translate-namespace=\"CONTENT\">\n\n        <div>\n            <h1 translate>.HEADERS.TITLE</h1>\n            <h1 translate>.HEADERS.WELCOME</h1>\n        </div>\n\n        <div translate-namespace=\".HEADERS\">\n            <h1 translate>.TITLE</h1>\n            <h1 translate>.WELCOME</h1>\n        </div>\n\n      </div>\n    </file>\n    <file name=\"script.js\">\n      angular.module('ngView', ['pascalprecht.translate'])\n\n      .config(function ($translateProvider) {\n\n        $translateProvider.translations('en',{\n          'TRANSLATION_ID': 'Hello there!',\n          'CONTENT': {\n            'HEADERS': {\n                TITLE: 'Title'\n            }\n          },\n          'CONTENT.HEADERS.WELCOME': 'Welcome'\n        }).preferredLanguage('en');\n\n      });\n\n    </file>\n   </example>\n */\n.directive('translateNamespace', translateNamespaceDirective);\n\nfunction translateNamespaceDirective() {\n\n  'use strict';\n\n  return {\n    restrict: 'A',\n    scope: true,\n    compile: function () {\n      return {\n        pre: function (scope, iElement, iAttrs) {\n          scope.translateNamespace = getTranslateNamespace(scope);\n\n          if (scope.translateNamespace && iAttrs.translateNamespace.charAt(0) === '.') {\n            scope.translateNamespace += iAttrs.translateNamespace;\n          } else {\n            scope.translateNamespace = iAttrs.translateNamespace;\n          }\n        }\n      };\n    }\n  };\n}\n\n/**\n * Returns the scope's namespace.\n * @private\n * @param scope\n * @returns {string}\n */\nfunction getTranslateNamespace(scope) {\n  'use strict';\n  if (scope.translateNamespace) {\n    return scope.translateNamespace;\n  }\n  if (scope.$parent) {\n    return getTranslateNamespace(scope.$parent);\n  }\n}\n\ntranslateNamespaceDirective.displayName = 'translateNamespaceDirective';\n\nangular.module('pascalprecht.translate')\n/**\n * @ngdoc directive\n * @name pascalprecht.translate.directive:translateLanguage\n * @restrict A\n *\n * @description\n * Forces the language to the directives in the underlying scope.\n *\n * @param {string=} translate language that will be negotiated.\n *\n * @example\n   <example module=\"ngView\">\n    <file name=\"index.html\">\n      <div>\n\n        <div>\n            <h1 translate>HELLO</h1>\n        </div>\n\n        <div translate-language=\"de\">\n            <h1 translate>HELLO</h1>\n        </div>\n\n      </div>\n    </file>\n    <file name=\"script.js\">\n      angular.module('ngView', ['pascalprecht.translate'])\n\n      .config(function ($translateProvider) {\n\n        $translateProvider\n          .translations('en',{\n            'HELLO': 'Hello world!'\n          })\n          .translations('de',{\n            'HELLO': 'Hallo Welt!'\n          })\n          .preferredLanguage('en');\n\n      });\n\n    </file>\n   </example>\n */\n.directive('translateLanguage', translateLanguageDirective);\n\nfunction translateLanguageDirective() {\n\n  'use strict';\n\n  return {\n    restrict: 'A',\n    scope: true,\n    compile: function () {\n      return function linkFn(scope, iElement, iAttrs) {\n\n        iAttrs.$observe('translateLanguage', function (newTranslateLanguage) {\n          scope.translateLanguage = newTranslateLanguage;\n        });\n\n        scope.$watch('translateLanguage', function(){\n          scope.$broadcast('translateLanguageChanged');\n        });\n      };\n    }\n  };\n}\n\ntranslateLanguageDirective.displayName = 'translateLanguageDirective';\n\nangular.module('pascalprecht.translate')\n/**\n * @ngdoc filter\n * @name pascalprecht.translate.filter:translate\n * @requires $parse\n * @requires pascalprecht.translate.$translate\n * @function\n *\n * @description\n * Uses `$translate` service to translate contents. Accepts interpolate parameters\n * to pass dynamized values though translation.\n *\n * @param {string} translationId A translation id to be translated.\n * @param {*=} interpolateParams Optional object literal (as hash or string) to pass values into translation.\n *\n * @returns {string} Translated text.\n *\n * @example\n   <example module=\"ngView\">\n    <file name=\"index.html\">\n      <div ng-controller=\"TranslateCtrl\">\n\n        <pre>{{ 'TRANSLATION_ID' | translate }}</pre>\n        <pre>{{ translationId | translate }}</pre>\n        <pre>{{ 'WITH_VALUES' | translate:'{value: 5}' }}</pre>\n        <pre>{{ 'WITH_VALUES' | translate:values }}</pre>\n\n      </div>\n    </file>\n    <file name=\"script.js\">\n      angular.module('ngView', ['pascalprecht.translate'])\n\n      .config(function ($translateProvider) {\n\n        $translateProvider.translations('en', {\n          'TRANSLATION_ID': 'Hello there!',\n          'WITH_VALUES': 'The following value is dynamic: {{value}}'\n        });\n        $translateProvider.preferredLanguage('en');\n\n      });\n\n      angular.module('ngView').controller('TranslateCtrl', function ($scope) {\n        $scope.translationId = 'TRANSLATION_ID';\n\n        $scope.values = {\n          value: 78\n        };\n      });\n    </file>\n   </example>\n */\n.filter('translate', translateFilterFactory);\n\nfunction translateFilterFactory($parse, $translate) {\n\n  'use strict';\n\n  var translateFilter = function (translationId, interpolateParams, interpolation, forceLanguage) {\n    if (!angular.isObject(interpolateParams)) {\n      var ctx = this || {\n        '__SCOPE_IS_NOT_AVAILABLE': 'More info at https://github.com/angular/angular.js/commit/8863b9d04c722b278fa93c5d66ad1e578ad6eb1f'\n        };\n      interpolateParams = $parse(interpolateParams)(ctx);\n    }\n\n    return $translate.instant(translationId, interpolateParams, interpolation, forceLanguage);\n  };\n\n  if ($translate.statefulFilter()) {\n    translateFilter.$stateful = true;\n  }\n\n  return translateFilter;\n}\n\ntranslateFilterFactory.displayName = 'translateFilterFactory';\n\nangular.module('pascalprecht.translate')\n\n/**\n * @ngdoc object\n * @name pascalprecht.translate.$translationCache\n * @requires $cacheFactory\n *\n * @description\n * The first time a translation table is used, it is loaded in the translation cache for quick retrieval. You\n * can load translation tables directly into the cache by consuming the\n * `$translationCache` service directly.\n *\n * @return {object} $cacheFactory object.\n */\n  .factory('$translationCache', $translationCache);\n\nfunction $translationCache($cacheFactory) {\n\n  'use strict';\n\n  return $cacheFactory('translations');\n}\n\n$translationCache.displayName = '$translationCache';\nreturn 'pascalprecht.translate';\n\n}));\n"
  },
  {
    "path": "flowable-ui-web/idm/libs/angular_1.3.13/angular.js",
    "content": "/**\n * @license AngularJS v1.3.13\n * (c) 2010-2014 Google, Inc. http://angularjs.org\n * License: MIT\n */\n(function(window, document, undefined) {'use strict';\n\n/**\n * @description\n *\n * This object provides a utility for producing rich Error messages within\n * Angular. It can be called as follows:\n *\n * var exampleMinErr = minErr('example');\n * throw exampleMinErr('one', 'This {0} is {1}', foo, bar);\n *\n * The above creates an instance of minErr in the example namespace. The\n * resulting error will have a namespaced error code of example.one.  The\n * resulting error will replace {0} with the value of foo, and {1} with the\n * value of bar. The object is not restricted in the number of arguments it can\n * take.\n *\n * If fewer arguments are specified than necessary for interpolation, the extra\n * interpolation markers will be preserved in the final string.\n *\n * Since data will be parsed statically during a build step, some restrictions\n * are applied with respect to how minErr instances are created and called.\n * Instances should have names of the form namespaceMinErr for a minErr created\n * using minErr('namespace') . Error codes, namespaces and template strings\n * should all be static strings, not variables or general expressions.\n *\n * @param {string} module The namespace to use for the new minErr instance.\n * @param {function} ErrorConstructor Custom error constructor to be instantiated when returning\n *   error from returned function, for cases when a particular type of error is useful.\n * @returns {function(code:string, template:string, ...templateArgs): Error} minErr instance\n */\n\nfunction minErr(module, ErrorConstructor) {\n  ErrorConstructor = ErrorConstructor || Error;\n  return function() {\n    var code = arguments[0],\n      prefix = '[' + (module ? module + ':' : '') + code + '] ',\n      template = arguments[1],\n      templateArgs = arguments,\n\n      message, i;\n\n    message = prefix + template.replace(/\\{\\d+\\}/g, function(match) {\n      var index = +match.slice(1, -1), arg;\n\n      if (index + 2 < templateArgs.length) {\n        return toDebugString(templateArgs[index + 2]);\n      }\n      return match;\n    });\n\n    message = message + '\\nhttp://errors.angularjs.org/1.3.13/' +\n      (module ? module + '/' : '') + code;\n    for (i = 2; i < arguments.length; i++) {\n      message = message + (i == 2 ? '?' : '&') + 'p' + (i - 2) + '=' +\n        encodeURIComponent(toDebugString(arguments[i]));\n    }\n    return new ErrorConstructor(message);\n  };\n}\n\n/* We need to tell jshint what variables are being exported */\n/* global angular: true,\n  msie: true,\n  jqLite: true,\n  jQuery: true,\n  slice: true,\n  splice: true,\n  push: true,\n  toString: true,\n  ngMinErr: true,\n  angularModule: true,\n  uid: true,\n  REGEX_STRING_REGEXP: true,\n  VALIDITY_STATE_PROPERTY: true,\n\n  lowercase: true,\n  uppercase: true,\n  manualLowercase: true,\n  manualUppercase: true,\n  nodeName_: true,\n  isArrayLike: true,\n  forEach: true,\n  sortedKeys: true,\n  forEachSorted: true,\n  reverseParams: true,\n  nextUid: true,\n  setHashKey: true,\n  extend: true,\n  int: true,\n  inherit: true,\n  noop: true,\n  identity: true,\n  valueFn: true,\n  isUndefined: true,\n  isDefined: true,\n  isObject: true,\n  isString: true,\n  isNumber: true,\n  isDate: true,\n  isArray: true,\n  isFunction: true,\n  isRegExp: true,\n  isWindow: true,\n  isScope: true,\n  isFile: true,\n  isFormData: true,\n  isBlob: true,\n  isBoolean: true,\n  isPromiseLike: true,\n  trim: true,\n  escapeForRegexp: true,\n  isElement: true,\n  makeMap: true,\n  includes: true,\n  arrayRemove: true,\n  copy: true,\n  shallowCopy: true,\n  equals: true,\n  csp: true,\n  concat: true,\n  sliceArgs: true,\n  bind: true,\n  toJsonReplacer: true,\n  toJson: true,\n  fromJson: true,\n  startingTag: true,\n  tryDecodeURIComponent: true,\n  parseKeyValue: true,\n  toKeyValue: true,\n  encodeUriSegment: true,\n  encodeUriQuery: true,\n  angularInit: true,\n  bootstrap: true,\n  getTestability: true,\n  snake_case: true,\n  bindJQuery: true,\n  assertArg: true,\n  assertArgFn: true,\n  assertNotHasOwnProperty: true,\n  getter: true,\n  getBlockNodes: true,\n  hasOwnProperty: true,\n  createMap: true,\n\n  NODE_TYPE_ELEMENT: true,\n  NODE_TYPE_TEXT: true,\n  NODE_TYPE_COMMENT: true,\n  NODE_TYPE_DOCUMENT: true,\n  NODE_TYPE_DOCUMENT_FRAGMENT: true,\n*/\n\n////////////////////////////////////\n\n/**\n * @ngdoc module\n * @name ng\n * @module ng\n * @description\n *\n * # ng (core module)\n * The ng module is loaded by default when an AngularJS application is started. The module itself\n * contains the essential components for an AngularJS application to function. The table below\n * lists a high level breakdown of each of the services/factories, filters, directives and testing\n * components available within this core module.\n *\n * <div doc-module-components=\"ng\"></div>\n */\n\nvar REGEX_STRING_REGEXP = /^\\/(.+)\\/([a-z]*)$/;\n\n// The name of a form control's ValidityState property.\n// This is used so that it's possible for internal tests to create mock ValidityStates.\nvar VALIDITY_STATE_PROPERTY = 'validity';\n\n/**\n * @ngdoc function\n * @name angular.lowercase\n * @module ng\n * @kind function\n *\n * @description Converts the specified string to lowercase.\n * @param {string} string String to be converted to lowercase.\n * @returns {string} Lowercased string.\n */\nvar lowercase = function(string) {return isString(string) ? string.toLowerCase() : string;};\nvar hasOwnProperty = Object.prototype.hasOwnProperty;\n\n/**\n * @ngdoc function\n * @name angular.uppercase\n * @module ng\n * @kind function\n *\n * @description Converts the specified string to uppercase.\n * @param {string} string String to be converted to uppercase.\n * @returns {string} Uppercased string.\n */\nvar uppercase = function(string) {return isString(string) ? string.toUpperCase() : string;};\n\n\nvar manualLowercase = function(s) {\n  /* jshint bitwise: false */\n  return isString(s)\n      ? s.replace(/[A-Z]/g, function(ch) {return String.fromCharCode(ch.charCodeAt(0) | 32);})\n      : s;\n};\nvar manualUppercase = function(s) {\n  /* jshint bitwise: false */\n  return isString(s)\n      ? s.replace(/[a-z]/g, function(ch) {return String.fromCharCode(ch.charCodeAt(0) & ~32);})\n      : s;\n};\n\n\n// String#toLowerCase and String#toUpperCase don't produce correct results in browsers with Turkish\n// locale, for this reason we need to detect this case and redefine lowercase/uppercase methods\n// with correct but slower alternatives.\nif ('i' !== 'I'.toLowerCase()) {\n  lowercase = manualLowercase;\n  uppercase = manualUppercase;\n}\n\n\nvar\n    msie,             // holds major version number for IE, or NaN if UA is not IE.\n    jqLite,           // delay binding since jQuery could be loaded after us.\n    jQuery,           // delay binding\n    slice             = [].slice,\n    splice            = [].splice,\n    push              = [].push,\n    toString          = Object.prototype.toString,\n    ngMinErr          = minErr('ng'),\n\n    /** @name angular */\n    angular           = window.angular || (window.angular = {}),\n    angularModule,\n    uid               = 0;\n\n/**\n * documentMode is an IE-only property\n * http://msdn.microsoft.com/en-us/library/ie/cc196988(v=vs.85).aspx\n */\nmsie = document.documentMode;\n\n\n/**\n * @private\n * @param {*} obj\n * @return {boolean} Returns true if `obj` is an array or array-like object (NodeList, Arguments,\n *                   String ...)\n */\nfunction isArrayLike(obj) {\n  if (obj == null || isWindow(obj)) {\n    return false;\n  }\n\n  var length = obj.length;\n\n  if (obj.nodeType === NODE_TYPE_ELEMENT && length) {\n    return true;\n  }\n\n  return isString(obj) || isArray(obj) || length === 0 ||\n         typeof length === 'number' && length > 0 && (length - 1) in obj;\n}\n\n/**\n * @ngdoc function\n * @name angular.forEach\n * @module ng\n * @kind function\n *\n * @description\n * Invokes the `iterator` function once for each item in `obj` collection, which can be either an\n * object or an array. The `iterator` function is invoked with `iterator(value, key, obj)`, where `value`\n * is the value of an object property or an array element, `key` is the object property key or\n * array element index and obj is the `obj` itself. Specifying a `context` for the function is optional.\n *\n * It is worth noting that `.forEach` does not iterate over inherited properties because it filters\n * using the `hasOwnProperty` method.\n *\n * Unlike ES262's\n * [Array.prototype.forEach](http://www.ecma-international.org/ecma-262/5.1/#sec-15.4.4.18),\n * Providing 'undefined' or 'null' values for `obj` will not throw a TypeError, but rather just\n * return the value provided.\n *\n   ```js\n     var values = {name: 'misko', gender: 'male'};\n     var log = [];\n     angular.forEach(values, function(value, key) {\n       this.push(key + ': ' + value);\n     }, log);\n     expect(log).toEqual(['name: misko', 'gender: male']);\n   ```\n *\n * @param {Object|Array} obj Object to iterate over.\n * @param {Function} iterator Iterator function.\n * @param {Object=} context Object to become context (`this`) for the iterator function.\n * @returns {Object|Array} Reference to `obj`.\n */\n\nfunction forEach(obj, iterator, context) {\n  var key, length;\n  if (obj) {\n    if (isFunction(obj)) {\n      for (key in obj) {\n        // Need to check if hasOwnProperty exists,\n        // as on IE8 the result of querySelectorAll is an object without a hasOwnProperty function\n        if (key != 'prototype' && key != 'length' && key != 'name' && (!obj.hasOwnProperty || obj.hasOwnProperty(key))) {\n          iterator.call(context, obj[key], key, obj);\n        }\n      }\n    } else if (isArray(obj) || isArrayLike(obj)) {\n      var isPrimitive = typeof obj !== 'object';\n      for (key = 0, length = obj.length; key < length; key++) {\n        if (isPrimitive || key in obj) {\n          iterator.call(context, obj[key], key, obj);\n        }\n      }\n    } else if (obj.forEach && obj.forEach !== forEach) {\n        obj.forEach(iterator, context, obj);\n    } else {\n      for (key in obj) {\n        if (obj.hasOwnProperty(key)) {\n          iterator.call(context, obj[key], key, obj);\n        }\n      }\n    }\n  }\n  return obj;\n}\n\nfunction sortedKeys(obj) {\n  return Object.keys(obj).sort();\n}\n\nfunction forEachSorted(obj, iterator, context) {\n  var keys = sortedKeys(obj);\n  for (var i = 0; i < keys.length; i++) {\n    iterator.call(context, obj[keys[i]], keys[i]);\n  }\n  return keys;\n}\n\n\n/**\n * when using forEach the params are value, key, but it is often useful to have key, value.\n * @param {function(string, *)} iteratorFn\n * @returns {function(*, string)}\n */\nfunction reverseParams(iteratorFn) {\n  return function(value, key) { iteratorFn(key, value); };\n}\n\n/**\n * A consistent way of creating unique IDs in angular.\n *\n * Using simple numbers allows us to generate 28.6 million unique ids per second for 10 years before\n * we hit number precision issues in JavaScript.\n *\n * Math.pow(2,53) / 60 / 60 / 24 / 365 / 10 = 28.6M\n *\n * @returns {number} an unique alpha-numeric string\n */\nfunction nextUid() {\n  return ++uid;\n}\n\n\n/**\n * Set or clear the hashkey for an object.\n * @param obj object\n * @param h the hashkey (!truthy to delete the hashkey)\n */\nfunction setHashKey(obj, h) {\n  if (h) {\n    obj.$$hashKey = h;\n  } else {\n    delete obj.$$hashKey;\n  }\n}\n\n/**\n * @ngdoc function\n * @name angular.extend\n * @module ng\n * @kind function\n *\n * @description\n * Extends the destination object `dst` by copying own enumerable properties from the `src` object(s)\n * to `dst`. You can specify multiple `src` objects. If you want to preserve original objects, you can do so\n * by passing an empty object as the target: `var object = angular.extend({}, object1, object2)`.\n * Note: Keep in mind that `angular.extend` does not support recursive merge (deep copy).\n *\n * @param {Object} dst Destination object.\n * @param {...Object} src Source object(s).\n * @returns {Object} Reference to `dst`.\n */\nfunction extend(dst) {\n  var h = dst.$$hashKey;\n\n  for (var i = 1, ii = arguments.length; i < ii; i++) {\n    var obj = arguments[i];\n    if (obj) {\n      var keys = Object.keys(obj);\n      for (var j = 0, jj = keys.length; j < jj; j++) {\n        var key = keys[j];\n        dst[key] = obj[key];\n      }\n    }\n  }\n\n  setHashKey(dst, h);\n  return dst;\n}\n\nfunction int(str) {\n  return parseInt(str, 10);\n}\n\n\nfunction inherit(parent, extra) {\n  return extend(Object.create(parent), extra);\n}\n\n/**\n * @ngdoc function\n * @name angular.noop\n * @module ng\n * @kind function\n *\n * @description\n * A function that performs no operations. This function can be useful when writing code in the\n * functional style.\n   ```js\n     function foo(callback) {\n       var result = calculateResult();\n       (callback || angular.noop)(result);\n     }\n   ```\n */\nfunction noop() {}\nnoop.$inject = [];\n\n\n/**\n * @ngdoc function\n * @name angular.identity\n * @module ng\n * @kind function\n *\n * @description\n * A function that returns its first argument. This function is useful when writing code in the\n * functional style.\n *\n   ```js\n     function transformer(transformationFn, value) {\n       return (transformationFn || angular.identity)(value);\n     };\n   ```\n  * @param {*} value to be returned.\n  * @returns {*} the value passed in.\n */\nfunction identity($) {return $;}\nidentity.$inject = [];\n\n\nfunction valueFn(value) {return function() {return value;};}\n\n/**\n * @ngdoc function\n * @name angular.isUndefined\n * @module ng\n * @kind function\n *\n * @description\n * Determines if a reference is undefined.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is undefined.\n */\nfunction isUndefined(value) {return typeof value === 'undefined';}\n\n\n/**\n * @ngdoc function\n * @name angular.isDefined\n * @module ng\n * @kind function\n *\n * @description\n * Determines if a reference is defined.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is defined.\n */\nfunction isDefined(value) {return typeof value !== 'undefined';}\n\n\n/**\n * @ngdoc function\n * @name angular.isObject\n * @module ng\n * @kind function\n *\n * @description\n * Determines if a reference is an `Object`. Unlike `typeof` in JavaScript, `null`s are not\n * considered to be objects. Note that JavaScript arrays are objects.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is an `Object` but not `null`.\n */\nfunction isObject(value) {\n  // http://jsperf.com/isobject4\n  return value !== null && typeof value === 'object';\n}\n\n\n/**\n * @ngdoc function\n * @name angular.isString\n * @module ng\n * @kind function\n *\n * @description\n * Determines if a reference is a `String`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `String`.\n */\nfunction isString(value) {return typeof value === 'string';}\n\n\n/**\n * @ngdoc function\n * @name angular.isNumber\n * @module ng\n * @kind function\n *\n * @description\n * Determines if a reference is a `Number`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Number`.\n */\nfunction isNumber(value) {return typeof value === 'number';}\n\n\n/**\n * @ngdoc function\n * @name angular.isDate\n * @module ng\n * @kind function\n *\n * @description\n * Determines if a value is a date.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Date`.\n */\nfunction isDate(value) {\n  return toString.call(value) === '[object Date]';\n}\n\n\n/**\n * @ngdoc function\n * @name angular.isArray\n * @module ng\n * @kind function\n *\n * @description\n * Determines if a reference is an `Array`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is an `Array`.\n */\nvar isArray = Array.isArray;\n\n/**\n * @ngdoc function\n * @name angular.isFunction\n * @module ng\n * @kind function\n *\n * @description\n * Determines if a reference is a `Function`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Function`.\n */\nfunction isFunction(value) {return typeof value === 'function';}\n\n\n/**\n * Determines if a value is a regular expression object.\n *\n * @private\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `RegExp`.\n */\nfunction isRegExp(value) {\n  return toString.call(value) === '[object RegExp]';\n}\n\n\n/**\n * Checks if `obj` is a window object.\n *\n * @private\n * @param {*} obj Object to check\n * @returns {boolean} True if `obj` is a window obj.\n */\nfunction isWindow(obj) {\n  return obj && obj.window === obj;\n}\n\n\nfunction isScope(obj) {\n  return obj && obj.$evalAsync && obj.$watch;\n}\n\n\nfunction isFile(obj) {\n  return toString.call(obj) === '[object File]';\n}\n\n\nfunction isFormData(obj) {\n  return toString.call(obj) === '[object FormData]';\n}\n\n\nfunction isBlob(obj) {\n  return toString.call(obj) === '[object Blob]';\n}\n\n\nfunction isBoolean(value) {\n  return typeof value === 'boolean';\n}\n\n\nfunction isPromiseLike(obj) {\n  return obj && isFunction(obj.then);\n}\n\n\nvar trim = function(value) {\n  return isString(value) ? value.trim() : value;\n};\n\n// Copied from:\n// http://docs.closure-library.googlecode.com/git/local_closure_goog_string_string.js.source.html#line1021\n// Prereq: s is a string.\nvar escapeForRegexp = function(s) {\n  return s.replace(/([-()\\[\\]{}+?*.$\\^|,:#<!\\\\])/g, '\\\\$1').\n           replace(/\\x08/g, '\\\\x08');\n};\n\n\n/**\n * @ngdoc function\n * @name angular.isElement\n * @module ng\n * @kind function\n *\n * @description\n * Determines if a reference is a DOM element (or wrapped jQuery element).\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a DOM element (or wrapped jQuery element).\n */\nfunction isElement(node) {\n  return !!(node &&\n    (node.nodeName  // we are a direct element\n    || (node.prop && node.attr && node.find)));  // we have an on and find method part of jQuery API\n}\n\n/**\n * @param str 'key1,key2,...'\n * @returns {object} in the form of {key1:true, key2:true, ...}\n */\nfunction makeMap(str) {\n  var obj = {}, items = str.split(\",\"), i;\n  for (i = 0; i < items.length; i++)\n    obj[items[i]] = true;\n  return obj;\n}\n\n\nfunction nodeName_(element) {\n  return lowercase(element.nodeName || (element[0] && element[0].nodeName));\n}\n\nfunction includes(array, obj) {\n  return Array.prototype.indexOf.call(array, obj) != -1;\n}\n\nfunction arrayRemove(array, value) {\n  var index = array.indexOf(value);\n  if (index >= 0)\n    array.splice(index, 1);\n  return value;\n}\n\n/**\n * @ngdoc function\n * @name angular.copy\n * @module ng\n * @kind function\n *\n * @description\n * Creates a deep copy of `source`, which should be an object or an array.\n *\n * * If no destination is supplied, a copy of the object or array is created.\n * * If a destination is provided, all of its elements (for arrays) or properties (for objects)\n *   are deleted and then all elements/properties from the source are copied to it.\n * * If `source` is not an object or array (inc. `null` and `undefined`), `source` is returned.\n * * If `source` is identical to 'destination' an exception will be thrown.\n *\n * @param {*} source The source that will be used to make a copy.\n *                   Can be any type, including primitives, `null`, and `undefined`.\n * @param {(Object|Array)=} destination Destination into which the source is copied. If\n *     provided, must be of the same type as `source`.\n * @returns {*} The copy or updated `destination`, if `destination` was specified.\n *\n * @example\n <example module=\"copyExample\">\n <file name=\"index.html\">\n <div ng-controller=\"ExampleController\">\n <form novalidate class=\"simple-form\">\n Name: <input type=\"text\" ng-model=\"user.name\" /><br />\n E-mail: <input type=\"email\" ng-model=\"user.email\" /><br />\n Gender: <input type=\"radio\" ng-model=\"user.gender\" value=\"male\" />male\n <input type=\"radio\" ng-model=\"user.gender\" value=\"female\" />female<br />\n <button ng-click=\"reset()\">RESET</button>\n <button ng-click=\"update(user)\">SAVE</button>\n </form>\n <pre>form = {{user | json}}</pre>\n <pre>master = {{master | json}}</pre>\n </div>\n\n <script>\n  angular.module('copyExample', [])\n    .controller('ExampleController', ['$scope', function($scope) {\n      $scope.master= {};\n\n      $scope.update = function(user) {\n        // Example with 1 argument\n        $scope.master= angular.copy(user);\n      };\n\n      $scope.reset = function() {\n        // Example with 2 arguments\n        angular.copy($scope.master, $scope.user);\n      };\n\n      $scope.reset();\n    }]);\n </script>\n </file>\n </example>\n */\nfunction copy(source, destination, stackSource, stackDest) {\n  if (isWindow(source) || isScope(source)) {\n    throw ngMinErr('cpws',\n      \"Can't copy! Making copies of Window or Scope instances is not supported.\");\n  }\n\n  if (!destination) {\n    destination = source;\n    if (source) {\n      if (isArray(source)) {\n        destination = copy(source, [], stackSource, stackDest);\n      } else if (isDate(source)) {\n        destination = new Date(source.getTime());\n      } else if (isRegExp(source)) {\n        destination = new RegExp(source.source, source.toString().match(/[^\\/]*$/)[0]);\n        destination.lastIndex = source.lastIndex;\n      } else if (isObject(source)) {\n        var emptyObject = Object.create(Object.getPrototypeOf(source));\n        destination = copy(source, emptyObject, stackSource, stackDest);\n      }\n    }\n  } else {\n    if (source === destination) throw ngMinErr('cpi',\n      \"Can't copy! Source and destination are identical.\");\n\n    stackSource = stackSource || [];\n    stackDest = stackDest || [];\n\n    if (isObject(source)) {\n      var index = stackSource.indexOf(source);\n      if (index !== -1) return stackDest[index];\n\n      stackSource.push(source);\n      stackDest.push(destination);\n    }\n\n    var result;\n    if (isArray(source)) {\n      destination.length = 0;\n      for (var i = 0; i < source.length; i++) {\n        result = copy(source[i], null, stackSource, stackDest);\n        if (isObject(source[i])) {\n          stackSource.push(source[i]);\n          stackDest.push(result);\n        }\n        destination.push(result);\n      }\n    } else {\n      var h = destination.$$hashKey;\n      if (isArray(destination)) {\n        destination.length = 0;\n      } else {\n        forEach(destination, function(value, key) {\n          delete destination[key];\n        });\n      }\n      for (var key in source) {\n        if (source.hasOwnProperty(key)) {\n          result = copy(source[key], null, stackSource, stackDest);\n          if (isObject(source[key])) {\n            stackSource.push(source[key]);\n            stackDest.push(result);\n          }\n          destination[key] = result;\n        }\n      }\n      setHashKey(destination,h);\n    }\n\n  }\n  return destination;\n}\n\n/**\n * Creates a shallow copy of an object, an array or a primitive.\n *\n * Assumes that there are no proto properties for objects.\n */\nfunction shallowCopy(src, dst) {\n  if (isArray(src)) {\n    dst = dst || [];\n\n    for (var i = 0, ii = src.length; i < ii; i++) {\n      dst[i] = src[i];\n    }\n  } else if (isObject(src)) {\n    dst = dst || {};\n\n    for (var key in src) {\n      if (!(key.charAt(0) === '$' && key.charAt(1) === '$')) {\n        dst[key] = src[key];\n      }\n    }\n  }\n\n  return dst || src;\n}\n\n\n/**\n * @ngdoc function\n * @name angular.equals\n * @module ng\n * @kind function\n *\n * @description\n * Determines if two objects or two values are equivalent. Supports value types, regular\n * expressions, arrays and objects.\n *\n * Two objects or values are considered equivalent if at least one of the following is true:\n *\n * * Both objects or values pass `===` comparison.\n * * Both objects or values are of the same type and all of their properties are equal by\n *   comparing them with `angular.equals`.\n * * Both values are NaN. (In JavaScript, NaN == NaN => false. But we consider two NaN as equal)\n * * Both values represent the same regular expression (In JavaScript,\n *   /abc/ == /abc/ => false. But we consider two regular expressions as equal when their textual\n *   representation matches).\n *\n * During a property comparison, properties of `function` type and properties with names\n * that begin with `$` are ignored.\n *\n * Scope and DOMWindow objects are being compared only by identify (`===`).\n *\n * @param {*} o1 Object or value to compare.\n * @param {*} o2 Object or value to compare.\n * @returns {boolean} True if arguments are equal.\n */\nfunction equals(o1, o2) {\n  if (o1 === o2) return true;\n  if (o1 === null || o2 === null) return false;\n  if (o1 !== o1 && o2 !== o2) return true; // NaN === NaN\n  var t1 = typeof o1, t2 = typeof o2, length, key, keySet;\n  if (t1 == t2) {\n    if (t1 == 'object') {\n      if (isArray(o1)) {\n        if (!isArray(o2)) return false;\n        if ((length = o1.length) == o2.length) {\n          for (key = 0; key < length; key++) {\n            if (!equals(o1[key], o2[key])) return false;\n          }\n          return true;\n        }\n      } else if (isDate(o1)) {\n        if (!isDate(o2)) return false;\n        return equals(o1.getTime(), o2.getTime());\n      } else if (isRegExp(o1) && isRegExp(o2)) {\n        return o1.toString() == o2.toString();\n      } else {\n        if (isScope(o1) || isScope(o2) || isWindow(o1) || isWindow(o2) || isArray(o2)) return false;\n        keySet = {};\n        for (key in o1) {\n          if (key.charAt(0) === '$' || isFunction(o1[key])) continue;\n          if (!equals(o1[key], o2[key])) return false;\n          keySet[key] = true;\n        }\n        for (key in o2) {\n          if (!keySet.hasOwnProperty(key) &&\n              key.charAt(0) !== '$' &&\n              o2[key] !== undefined &&\n              !isFunction(o2[key])) return false;\n        }\n        return true;\n      }\n    }\n  }\n  return false;\n}\n\nvar csp = function() {\n  if (isDefined(csp.isActive_)) return csp.isActive_;\n\n  var active = !!(document.querySelector('[ng-csp]') ||\n                  document.querySelector('[data-ng-csp]'));\n\n  if (!active) {\n    try {\n      /* jshint -W031, -W054 */\n      new Function('');\n      /* jshint +W031, +W054 */\n    } catch (e) {\n      active = true;\n    }\n  }\n\n  return (csp.isActive_ = active);\n};\n\n\n\nfunction concat(array1, array2, index) {\n  return array1.concat(slice.call(array2, index));\n}\n\nfunction sliceArgs(args, startIndex) {\n  return slice.call(args, startIndex || 0);\n}\n\n\n/* jshint -W101 */\n/**\n * @ngdoc function\n * @name angular.bind\n * @module ng\n * @kind function\n *\n * @description\n * Returns a function which calls function `fn` bound to `self` (`self` becomes the `this` for\n * `fn`). You can supply optional `args` that are prebound to the function. This feature is also\n * known as [partial application](http://en.wikipedia.org/wiki/Partial_application), as\n * distinguished from [function currying](http://en.wikipedia.org/wiki/Currying#Contrast_with_partial_function_application).\n *\n * @param {Object} self Context which `fn` should be evaluated in.\n * @param {function()} fn Function to be bound.\n * @param {...*} args Optional arguments to be prebound to the `fn` function call.\n * @returns {function()} Function that wraps the `fn` with all the specified bindings.\n */\n/* jshint +W101 */\nfunction bind(self, fn) {\n  var curryArgs = arguments.length > 2 ? sliceArgs(arguments, 2) : [];\n  if (isFunction(fn) && !(fn instanceof RegExp)) {\n    return curryArgs.length\n      ? function() {\n          return arguments.length\n            ? fn.apply(self, concat(curryArgs, arguments, 0))\n            : fn.apply(self, curryArgs);\n        }\n      : function() {\n          return arguments.length\n            ? fn.apply(self, arguments)\n            : fn.call(self);\n        };\n  } else {\n    // in IE, native methods are not functions so they cannot be bound (note: they don't need to be)\n    return fn;\n  }\n}\n\n\nfunction toJsonReplacer(key, value) {\n  var val = value;\n\n  if (typeof key === 'string' && key.charAt(0) === '$' && key.charAt(1) === '$') {\n    val = undefined;\n  } else if (isWindow(value)) {\n    val = '$WINDOW';\n  } else if (value &&  document === value) {\n    val = '$DOCUMENT';\n  } else if (isScope(value)) {\n    val = '$SCOPE';\n  }\n\n  return val;\n}\n\n\n/**\n * @ngdoc function\n * @name angular.toJson\n * @module ng\n * @kind function\n *\n * @description\n * Serializes input into a JSON-formatted string. Properties with leading $$ characters will be\n * stripped since angular uses this notation internally.\n *\n * @param {Object|Array|Date|string|number} obj Input to be serialized into JSON.\n * @param {boolean|number=} pretty If set to true, the JSON output will contain newlines and whitespace.\n *    If set to an integer, the JSON output will contain that many spaces per indentation (the default is 2).\n * @returns {string|undefined} JSON-ified string representing `obj`.\n */\nfunction toJson(obj, pretty) {\n  if (typeof obj === 'undefined') return undefined;\n  if (!isNumber(pretty)) {\n    pretty = pretty ? 2 : null;\n  }\n  return JSON.stringify(obj, toJsonReplacer, pretty);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.fromJson\n * @module ng\n * @kind function\n *\n * @description\n * Deserializes a JSON string.\n *\n * @param {string} json JSON string to deserialize.\n * @returns {Object|Array|string|number} Deserialized JSON string.\n */\nfunction fromJson(json) {\n  return isString(json)\n      ? JSON.parse(json)\n      : json;\n}\n\n\n/**\n * @returns {string} Returns the string representation of the element.\n */\nfunction startingTag(element) {\n  element = jqLite(element).clone();\n  try {\n    // turns out IE does not let you set .html() on elements which\n    // are not allowed to have children. So we just ignore it.\n    element.empty();\n  } catch (e) {}\n  var elemHtml = jqLite('<div>').append(element).html();\n  try {\n    return element[0].nodeType === NODE_TYPE_TEXT ? lowercase(elemHtml) :\n        elemHtml.\n          match(/^(<[^>]+>)/)[1].\n          replace(/^<([\\w\\-]+)/, function(match, nodeName) { return '<' + lowercase(nodeName); });\n  } catch (e) {\n    return lowercase(elemHtml);\n  }\n\n}\n\n\n/////////////////////////////////////////////////\n\n/**\n * Tries to decode the URI component without throwing an exception.\n *\n * @private\n * @param str value potential URI component to check.\n * @returns {boolean} True if `value` can be decoded\n * with the decodeURIComponent function.\n */\nfunction tryDecodeURIComponent(value) {\n  try {\n    return decodeURIComponent(value);\n  } catch (e) {\n    // Ignore any invalid uri component\n  }\n}\n\n\n/**\n * Parses an escaped url query string into key-value pairs.\n * @returns {Object.<string,boolean|Array>}\n */\nfunction parseKeyValue(/**string*/keyValue) {\n  var obj = {}, key_value, key;\n  forEach((keyValue || \"\").split('&'), function(keyValue) {\n    if (keyValue) {\n      key_value = keyValue.replace(/\\+/g,'%20').split('=');\n      key = tryDecodeURIComponent(key_value[0]);\n      if (isDefined(key)) {\n        var val = isDefined(key_value[1]) ? tryDecodeURIComponent(key_value[1]) : true;\n        if (!hasOwnProperty.call(obj, key)) {\n          obj[key] = val;\n        } else if (isArray(obj[key])) {\n          obj[key].push(val);\n        } else {\n          obj[key] = [obj[key],val];\n        }\n      }\n    }\n  });\n  return obj;\n}\n\nfunction toKeyValue(obj) {\n  var parts = [];\n  forEach(obj, function(value, key) {\n    if (isArray(value)) {\n      forEach(value, function(arrayValue) {\n        parts.push(encodeUriQuery(key, true) +\n                   (arrayValue === true ? '' : '=' + encodeUriQuery(arrayValue, true)));\n      });\n    } else {\n    parts.push(encodeUriQuery(key, true) +\n               (value === true ? '' : '=' + encodeUriQuery(value, true)));\n    }\n  });\n  return parts.length ? parts.join('&') : '';\n}\n\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 */\nfunction 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 custom\n * method because encodeURIComponent is too aggressive and encodes stuff that doesn't have to be\n * 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 */\nfunction 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(/%3B/gi, ';').\n             replace(/%20/g, (pctEncodeSpaces ? '%20' : '+'));\n}\n\nvar ngAttrPrefixes = ['ng-', 'data-ng-', 'ng:', 'x-ng-'];\n\nfunction getNgAttribute(element, ngAttr) {\n  var attr, i, ii = ngAttrPrefixes.length;\n  element = jqLite(element);\n  for (i = 0; i < ii; ++i) {\n    attr = ngAttrPrefixes[i] + ngAttr;\n    if (isString(attr = element.attr(attr))) {\n      return attr;\n    }\n  }\n  return null;\n}\n\n/**\n * @ngdoc directive\n * @name ngApp\n * @module ng\n *\n * @element ANY\n * @param {angular.Module} ngApp an optional application\n *   {@link angular.module module} name to load.\n * @param {boolean=} ngStrictDi if this attribute is present on the app element, the injector will be\n *   created in \"strict-di\" mode. This means that the application will fail to invoke functions which\n *   do not use explicit function annotation (and are thus unsuitable for minification), as described\n *   in {@link guide/di the Dependency Injection guide}, and useful debugging info will assist in\n *   tracking down the root of these bugs.\n *\n * @description\n *\n * Use this directive to **auto-bootstrap** an AngularJS application. The `ngApp` directive\n * designates the **root element** of the application and is typically placed near the root element\n * of the page - e.g. on the `<body>` or `<html>` tags.\n *\n * Only one AngularJS application can be auto-bootstrapped per HTML document. The first `ngApp`\n * found in the document will be used to define the root element to auto-bootstrap as an\n * application. To run multiple applications in an HTML document you must manually bootstrap them using\n * {@link angular.bootstrap} instead. AngularJS applications cannot be nested within each other.\n *\n * You can specify an **AngularJS module** to be used as the root module for the application.  This\n * module will be loaded into the {@link auto.$injector} when the application is bootstrapped. It\n * should contain the application code needed or have dependencies on other modules that will\n * contain the code. See {@link angular.module} for more information.\n *\n * In the example below if the `ngApp` directive were not placed on the `html` element then the\n * document would not be compiled, the `AppController` would not be instantiated and the `{{ a+b }}`\n * would not be resolved to `3`.\n *\n * `ngApp` is the easiest, and most common way to bootstrap an application.\n *\n <example module=\"ngAppDemo\">\n   <file name=\"index.html\">\n   <div ng-controller=\"ngAppDemoController\">\n     I can add: {{a}} + {{b}} =  {{ a+b }}\n   </div>\n   </file>\n   <file name=\"script.js\">\n   angular.module('ngAppDemo', []).controller('ngAppDemoController', function($scope) {\n     $scope.a = 1;\n     $scope.b = 2;\n   });\n   </file>\n </example>\n *\n * Using `ngStrictDi`, you would see something like this:\n *\n <example ng-app-included=\"true\">\n   <file name=\"index.html\">\n   <div ng-app=\"ngAppStrictDemo\" ng-strict-di>\n       <div ng-controller=\"GoodController1\">\n           I can add: {{a}} + {{b}} =  {{ a+b }}\n\n           <p>This renders because the controller does not fail to\n              instantiate, by using explicit annotation style (see\n              script.js for details)\n           </p>\n       </div>\n\n       <div ng-controller=\"GoodController2\">\n           Name: <input ng-model=\"name\"><br />\n           Hello, {{name}}!\n\n           <p>This renders because the controller does not fail to\n              instantiate, by using explicit annotation style\n              (see script.js for details)\n           </p>\n       </div>\n\n       <div ng-controller=\"BadController\">\n           I can add: {{a}} + {{b}} =  {{ a+b }}\n\n           <p>The controller could not be instantiated, due to relying\n              on automatic function annotations (which are disabled in\n              strict mode). As such, the content of this section is not\n              interpolated, and there should be an error in your web console.\n           </p>\n       </div>\n   </div>\n   </file>\n   <file name=\"script.js\">\n   angular.module('ngAppStrictDemo', [])\n     // BadController will fail to instantiate, due to relying on automatic function annotation,\n     // rather than an explicit annotation\n     .controller('BadController', function($scope) {\n       $scope.a = 1;\n       $scope.b = 2;\n     })\n     // Unlike BadController, GoodController1 and GoodController2 will not fail to be instantiated,\n     // due to using explicit annotations using the array style and $inject property, respectively.\n     .controller('GoodController1', ['$scope', function($scope) {\n       $scope.a = 1;\n       $scope.b = 2;\n     }])\n     .controller('GoodController2', GoodController2);\n     function GoodController2($scope) {\n       $scope.name = \"World\";\n     }\n     GoodController2.$inject = ['$scope'];\n   </file>\n   <file name=\"style.css\">\n   div[ng-controller] {\n       margin-bottom: 1em;\n       -webkit-border-radius: 4px;\n       border-radius: 4px;\n       border: 1px solid;\n       padding: .5em;\n   }\n   div[ng-controller^=Good] {\n       border-color: #d6e9c6;\n       background-color: #dff0d8;\n       color: #3c763d;\n   }\n   div[ng-controller^=Bad] {\n       border-color: #ebccd1;\n       background-color: #f2dede;\n       color: #a94442;\n       margin-bottom: 0;\n   }\n   </file>\n </example>\n */\nfunction angularInit(element, bootstrap) {\n  var appElement,\n      module,\n      config = {};\n\n  // The element `element` has priority over any other element\n  forEach(ngAttrPrefixes, function(prefix) {\n    var name = prefix + 'app';\n\n    if (!appElement && element.hasAttribute && element.hasAttribute(name)) {\n      appElement = element;\n      module = element.getAttribute(name);\n    }\n  });\n  forEach(ngAttrPrefixes, function(prefix) {\n    var name = prefix + 'app';\n    var candidate;\n\n    if (!appElement && (candidate = element.querySelector('[' + name.replace(':', '\\\\:') + ']'))) {\n      appElement = candidate;\n      module = candidate.getAttribute(name);\n    }\n  });\n  if (appElement) {\n    config.strictDi = getNgAttribute(appElement, \"strict-di\") !== null;\n    bootstrap(appElement, module ? [module] : [], config);\n  }\n}\n\n/**\n * @ngdoc function\n * @name angular.bootstrap\n * @module ng\n * @description\n * Use this function to manually start up angular application.\n *\n * See: {@link guide/bootstrap Bootstrap}\n *\n * Note that Protractor based end-to-end tests cannot use this function to bootstrap manually.\n * They must use {@link ng.directive:ngApp ngApp}.\n *\n * Angular will detect if it has been loaded into the browser more than once and only allow the\n * first loaded script to be bootstrapped and will report a warning to the browser console for\n * each of the subsequent scripts. This prevents strange results in applications, where otherwise\n * multiple instances of Angular try to work on the DOM.\n *\n * ```html\n * <!doctype html>\n * <html>\n * <body>\n * <div ng-controller=\"WelcomeController\">\n *   {{greeting}}\n * </div>\n *\n * <script src=\"angular.js\"></script>\n * <script>\n *   var app = angular.module('demo', [])\n *   .controller('WelcomeController', function($scope) {\n *       $scope.greeting = 'Welcome!';\n *   });\n *   angular.bootstrap(document, ['demo']);\n * </script>\n * </body>\n * </html>\n * ```\n *\n * @param {DOMElement} element DOM element which is the root of angular application.\n * @param {Array<String|Function|Array>=} modules an array of modules to load into the application.\n *     Each item in the array should be the name of a predefined module or a (DI annotated)\n *     function that will be invoked by the injector as a `config` block.\n *     See: {@link angular.module modules}\n * @param {Object=} config an object for defining configuration options for the application. The\n *     following keys are supported:\n *\n * * `strictDi` - disable automatic function annotation for the application. This is meant to\n *   assist in finding bugs which break minified code. Defaults to `false`.\n *\n * @returns {auto.$injector} Returns the newly created injector for this app.\n */\nfunction bootstrap(element, modules, config) {\n  if (!isObject(config)) config = {};\n  var defaultConfig = {\n    strictDi: false\n  };\n  config = extend(defaultConfig, config);\n  var doBootstrap = function() {\n    element = jqLite(element);\n\n    if (element.injector()) {\n      var tag = (element[0] === document) ? 'document' : startingTag(element);\n      //Encode angle brackets to prevent input from being sanitized to empty string #8683\n      throw ngMinErr(\n          'btstrpd',\n          \"App Already Bootstrapped with this Element '{0}'\",\n          tag.replace(/</,'&lt;').replace(/>/,'&gt;'));\n    }\n\n    modules = modules || [];\n    modules.unshift(['$provide', function($provide) {\n      $provide.value('$rootElement', element);\n    }]);\n\n    if (config.debugInfoEnabled) {\n      // Pushing so that this overrides `debugInfoEnabled` setting defined in user's `modules`.\n      modules.push(['$compileProvider', function($compileProvider) {\n        $compileProvider.debugInfoEnabled(true);\n      }]);\n    }\n\n    modules.unshift('ng');\n    var injector = createInjector(modules, config.strictDi);\n    injector.invoke(['$rootScope', '$rootElement', '$compile', '$injector',\n       function bootstrapApply(scope, element, compile, injector) {\n        scope.$apply(function() {\n          element.data('$injector', injector);\n          compile(element)(scope);\n        });\n      }]\n    );\n    return injector;\n  };\n\n  var NG_ENABLE_DEBUG_INFO = /^NG_ENABLE_DEBUG_INFO!/;\n  var NG_DEFER_BOOTSTRAP = /^NG_DEFER_BOOTSTRAP!/;\n\n  if (window && NG_ENABLE_DEBUG_INFO.test(window.name)) {\n    config.debugInfoEnabled = true;\n    window.name = window.name.replace(NG_ENABLE_DEBUG_INFO, '');\n  }\n\n  if (window && !NG_DEFER_BOOTSTRAP.test(window.name)) {\n    return doBootstrap();\n  }\n\n  window.name = window.name.replace(NG_DEFER_BOOTSTRAP, '');\n  angular.resumeBootstrap = function(extraModules) {\n    forEach(extraModules, function(module) {\n      modules.push(module);\n    });\n    return doBootstrap();\n  };\n\n  if (isFunction(angular.resumeDeferredBootstrap)) {\n    angular.resumeDeferredBootstrap();\n  }\n}\n\n/**\n * @ngdoc function\n * @name angular.reloadWithDebugInfo\n * @module ng\n * @description\n * Use this function to reload the current application with debug information turned on.\n * This takes precedence over a call to `$compileProvider.debugInfoEnabled(false)`.\n *\n * See {@link ng.$compileProvider#debugInfoEnabled} for more.\n */\nfunction reloadWithDebugInfo() {\n  window.name = 'NG_ENABLE_DEBUG_INFO!' + window.name;\n  window.location.reload();\n}\n\n/**\n * @name angular.getTestability\n * @module ng\n * @description\n * Get the testability service for the instance of Angular on the given\n * element.\n * @param {DOMElement} element DOM element which is the root of angular application.\n */\nfunction getTestability(rootElement) {\n  var injector = angular.element(rootElement).injector();\n  if (!injector) {\n    throw ngMinErr('test',\n      'no injector found for element argument to getTestability');\n  }\n  return injector.get('$$testability');\n}\n\nvar SNAKE_CASE_REGEXP = /[A-Z]/g;\nfunction snake_case(name, separator) {\n  separator = separator || '_';\n  return name.replace(SNAKE_CASE_REGEXP, function(letter, pos) {\n    return (pos ? separator : '') + letter.toLowerCase();\n  });\n}\n\nvar bindJQueryFired = false;\nvar skipDestroyOnNextJQueryCleanData;\nfunction bindJQuery() {\n  var originalCleanData;\n\n  if (bindJQueryFired) {\n    return;\n  }\n\n  // bind to jQuery if present;\n  jQuery = window.jQuery;\n  // Use jQuery if it exists with proper functionality, otherwise default to us.\n  // Angular 1.2+ requires jQuery 1.7+ for on()/off() support.\n  // Angular 1.3+ technically requires at least jQuery 2.1+ but it may work with older\n  // versions. It will not work for sure with jQuery <1.7, though.\n  if (jQuery && jQuery.fn.on) {\n    jqLite = jQuery;\n    extend(jQuery.fn, {\n      scope: JQLitePrototype.scope,\n      isolateScope: JQLitePrototype.isolateScope,\n      controller: JQLitePrototype.controller,\n      injector: JQLitePrototype.injector,\n      inheritedData: JQLitePrototype.inheritedData\n    });\n\n    // All nodes removed from the DOM via various jQuery APIs like .remove()\n    // are passed through jQuery.cleanData. Monkey-patch this method to fire\n    // the $destroy event on all removed nodes.\n    originalCleanData = jQuery.cleanData;\n    jQuery.cleanData = function(elems) {\n      var events;\n      if (!skipDestroyOnNextJQueryCleanData) {\n        for (var i = 0, elem; (elem = elems[i]) != null; i++) {\n          events = jQuery._data(elem, \"events\");\n          if (events && events.$destroy) {\n            jQuery(elem).triggerHandler('$destroy');\n          }\n        }\n      } else {\n        skipDestroyOnNextJQueryCleanData = false;\n      }\n      originalCleanData(elems);\n    };\n  } else {\n    jqLite = JQLite;\n  }\n\n  angular.element = jqLite;\n\n  // Prevent double-proxying.\n  bindJQueryFired = true;\n}\n\n/**\n * throw error if the argument is falsy.\n */\nfunction assertArg(arg, name, reason) {\n  if (!arg) {\n    throw ngMinErr('areq', \"Argument '{0}' is {1}\", (name || '?'), (reason || \"required\"));\n  }\n  return arg;\n}\n\nfunction assertArgFn(arg, name, acceptArrayAnnotation) {\n  if (acceptArrayAnnotation && isArray(arg)) {\n      arg = arg[arg.length - 1];\n  }\n\n  assertArg(isFunction(arg), name, 'not a function, got ' +\n      (arg && typeof arg === 'object' ? arg.constructor.name || 'Object' : typeof arg));\n  return arg;\n}\n\n/**\n * throw error if the name given is hasOwnProperty\n * @param  {String} name    the name to test\n * @param  {String} context the context in which the name is used, such as module or directive\n */\nfunction assertNotHasOwnProperty(name, context) {\n  if (name === 'hasOwnProperty') {\n    throw ngMinErr('badname', \"hasOwnProperty is not a valid {0} name\", context);\n  }\n}\n\n/**\n * Return the value accessible from the object by path. Any undefined traversals are ignored\n * @param {Object} obj starting object\n * @param {String} path path to traverse\n * @param {boolean} [bindFnToScope=true]\n * @returns {Object} value as accessible by path\n */\n//TODO(misko): this function needs to be removed\nfunction getter(obj, path, bindFnToScope) {\n  if (!path) return obj;\n  var keys = path.split('.');\n  var key;\n  var lastInstance = obj;\n  var len = keys.length;\n\n  for (var i = 0; i < len; i++) {\n    key = keys[i];\n    if (obj) {\n      obj = (lastInstance = obj)[key];\n    }\n  }\n  if (!bindFnToScope && isFunction(obj)) {\n    return bind(lastInstance, obj);\n  }\n  return obj;\n}\n\n/**\n * Return the DOM siblings between the first and last node in the given array.\n * @param {Array} array like object\n * @returns {jqLite} jqLite collection containing the nodes\n */\nfunction getBlockNodes(nodes) {\n  // TODO(perf): just check if all items in `nodes` are siblings and if they are return the original\n  //             collection, otherwise update the original collection.\n  var node = nodes[0];\n  var endNode = nodes[nodes.length - 1];\n  var blockNodes = [node];\n\n  do {\n    node = node.nextSibling;\n    if (!node) break;\n    blockNodes.push(node);\n  } while (node !== endNode);\n\n  return jqLite(blockNodes);\n}\n\n\n/**\n * Creates a new object without a prototype. This object is useful for lookup without having to\n * guard against prototypically inherited properties via hasOwnProperty.\n *\n * Related micro-benchmarks:\n * - http://jsperf.com/object-create2\n * - http://jsperf.com/proto-map-lookup/2\n * - http://jsperf.com/for-in-vs-object-keys2\n *\n * @returns {Object}\n */\nfunction createMap() {\n  return Object.create(null);\n}\n\nvar NODE_TYPE_ELEMENT = 1;\nvar NODE_TYPE_TEXT = 3;\nvar NODE_TYPE_COMMENT = 8;\nvar NODE_TYPE_DOCUMENT = 9;\nvar NODE_TYPE_DOCUMENT_FRAGMENT = 11;\n\n/**\n * @ngdoc type\n * @name angular.Module\n * @module ng\n * @description\n *\n * Interface for configuring angular {@link angular.module modules}.\n */\n\nfunction setupModuleLoader(window) {\n\n  var $injectorMinErr = minErr('$injector');\n  var ngMinErr = minErr('ng');\n\n  function ensure(obj, name, factory) {\n    return obj[name] || (obj[name] = factory());\n  }\n\n  var angular = ensure(window, 'angular', Object);\n\n  // We need to expose `angular.$$minErr` to modules such as `ngResource` that reference it during bootstrap\n  angular.$$minErr = angular.$$minErr || minErr;\n\n  return ensure(angular, 'module', function() {\n    /** @type {Object.<string, angular.Module>} */\n    var modules = {};\n\n    /**\n     * @ngdoc function\n     * @name angular.module\n     * @module ng\n     * @description\n     *\n     * The `angular.module` is a global place for creating, registering and retrieving Angular\n     * modules.\n     * All modules (angular core or 3rd party) that should be available to an application must be\n     * registered using this mechanism.\n     *\n     * When passed two or more arguments, a new module is created.  If passed only one argument, an\n     * existing module (the name passed as the first argument to `module`) is retrieved.\n     *\n     *\n     * # Module\n     *\n     * A module is a collection of services, directives, controllers, filters, and configuration information.\n     * `angular.module` is used to configure the {@link auto.$injector $injector}.\n     *\n     * ```js\n     * // Create a new module\n     * var myModule = angular.module('myModule', []);\n     *\n     * // register a new service\n     * myModule.value('appName', 'MyCoolApp');\n     *\n     * // configure existing services inside initialization blocks.\n     * myModule.config(['$locationProvider', function($locationProvider) {\n     *   // Configure existing providers\n     *   $locationProvider.hashPrefix('!');\n     * }]);\n     * ```\n     *\n     * Then you can create an injector and load your modules like this:\n     *\n     * ```js\n     * var injector = angular.injector(['ng', 'myModule'])\n     * ```\n     *\n     * However it's more likely that you'll just use\n     * {@link ng.directive:ngApp ngApp} or\n     * {@link angular.bootstrap} to simplify this process for you.\n     *\n     * @param {!string} name The name of the module to create or retrieve.\n     * @param {!Array.<string>=} requires If specified then new module is being created. If\n     *        unspecified then the module is being retrieved for further configuration.\n     * @param {Function=} configFn Optional configuration function for the module. Same as\n     *        {@link angular.Module#config Module#config()}.\n     * @returns {module} new module with the {@link angular.Module} api.\n     */\n    return function module(name, requires, configFn) {\n      var assertNotHasOwnProperty = function(name, context) {\n        if (name === 'hasOwnProperty') {\n          throw ngMinErr('badname', 'hasOwnProperty is not a valid {0} name', context);\n        }\n      };\n\n      assertNotHasOwnProperty(name, 'module');\n      if (requires && modules.hasOwnProperty(name)) {\n        modules[name] = null;\n      }\n      return ensure(modules, name, function() {\n        if (!requires) {\n          throw $injectorMinErr('nomod', \"Module '{0}' is not available! You either misspelled \" +\n             \"the module name or forgot to load it. If registering a module ensure that you \" +\n             \"specify the dependencies as the second argument.\", name);\n        }\n\n        /** @type {!Array.<Array.<*>>} */\n        var invokeQueue = [];\n\n        /** @type {!Array.<Function>} */\n        var configBlocks = [];\n\n        /** @type {!Array.<Function>} */\n        var runBlocks = [];\n\n        var config = invokeLater('$injector', 'invoke', 'push', configBlocks);\n\n        /** @type {angular.Module} */\n        var moduleInstance = {\n          // Private state\n          _invokeQueue: invokeQueue,\n          _configBlocks: configBlocks,\n          _runBlocks: runBlocks,\n\n          /**\n           * @ngdoc property\n           * @name angular.Module#requires\n           * @module ng\n           *\n           * @description\n           * Holds the list of modules which the injector will load before the current module is\n           * loaded.\n           */\n          requires: requires,\n\n          /**\n           * @ngdoc property\n           * @name angular.Module#name\n           * @module ng\n           *\n           * @description\n           * Name of the module.\n           */\n          name: name,\n\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#provider\n           * @module ng\n           * @param {string} name service name\n           * @param {Function} providerType Construction function for creating new instance of the\n           *                                service.\n           * @description\n           * See {@link auto.$provide#provider $provide.provider()}.\n           */\n          provider: invokeLater('$provide', 'provider'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#factory\n           * @module ng\n           * @param {string} name service name\n           * @param {Function} providerFunction Function for creating new instance of the service.\n           * @description\n           * See {@link auto.$provide#factory $provide.factory()}.\n           */\n          factory: invokeLater('$provide', 'factory'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#service\n           * @module ng\n           * @param {string} name service name\n           * @param {Function} constructor A constructor function that will be instantiated.\n           * @description\n           * See {@link auto.$provide#service $provide.service()}.\n           */\n          service: invokeLater('$provide', 'service'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#value\n           * @module ng\n           * @param {string} name service name\n           * @param {*} object Service instance object.\n           * @description\n           * See {@link auto.$provide#value $provide.value()}.\n           */\n          value: invokeLater('$provide', 'value'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#constant\n           * @module ng\n           * @param {string} name constant name\n           * @param {*} object Constant value.\n           * @description\n           * Because the constant are fixed, they get applied before other provide methods.\n           * See {@link auto.$provide#constant $provide.constant()}.\n           */\n          constant: invokeLater('$provide', 'constant', 'unshift'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#animation\n           * @module ng\n           * @param {string} name animation name\n           * @param {Function} animationFactory Factory function for creating new instance of an\n           *                                    animation.\n           * @description\n           *\n           * **NOTE**: animations take effect only if the **ngAnimate** module is loaded.\n           *\n           *\n           * Defines an animation hook that can be later used with\n           * {@link ngAnimate.$animate $animate} service and directives that use this service.\n           *\n           * ```js\n           * module.animation('.animation-name', function($inject1, $inject2) {\n           *   return {\n           *     eventName : function(element, done) {\n           *       //code to run the animation\n           *       //once complete, then run done()\n           *       return function cancellationFunction(element) {\n           *         //code to cancel the animation\n           *       }\n           *     }\n           *   }\n           * })\n           * ```\n           *\n           * See {@link ng.$animateProvider#register $animateProvider.register()} and\n           * {@link ngAnimate ngAnimate module} for more information.\n           */\n          animation: invokeLater('$animateProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#filter\n           * @module ng\n           * @param {string} name Filter name.\n           * @param {Function} filterFactory Factory function for creating new instance of filter.\n           * @description\n           * See {@link ng.$filterProvider#register $filterProvider.register()}.\n           */\n          filter: invokeLater('$filterProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#controller\n           * @module ng\n           * @param {string|Object} name Controller name, or an object map of controllers where the\n           *    keys are the names and the values are the constructors.\n           * @param {Function} constructor Controller constructor function.\n           * @description\n           * See {@link ng.$controllerProvider#register $controllerProvider.register()}.\n           */\n          controller: invokeLater('$controllerProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#directive\n           * @module ng\n           * @param {string|Object} name Directive name, or an object map of directives where the\n           *    keys are the names and the values are the factories.\n           * @param {Function} directiveFactory Factory function for creating new instance of\n           * directives.\n           * @description\n           * See {@link ng.$compileProvider#directive $compileProvider.directive()}.\n           */\n          directive: invokeLater('$compileProvider', 'directive'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#config\n           * @module ng\n           * @param {Function} configFn Execute this function on module load. Useful for service\n           *    configuration.\n           * @description\n           * Use this method to register work which needs to be performed on module loading.\n           * For more about how to configure services, see\n           * {@link providers#provider-recipe Provider Recipe}.\n           */\n          config: config,\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#run\n           * @module ng\n           * @param {Function} initializationFn Execute this function after injector creation.\n           *    Useful for application initialization.\n           * @description\n           * Use this method to register work which should be performed when the injector is done\n           * loading all modules.\n           */\n          run: function(block) {\n            runBlocks.push(block);\n            return this;\n          }\n        };\n\n        if (configFn) {\n          config(configFn);\n        }\n\n        return moduleInstance;\n\n        /**\n         * @param {string} provider\n         * @param {string} method\n         * @param {String=} insertMethod\n         * @returns {angular.Module}\n         */\n        function invokeLater(provider, method, insertMethod, queue) {\n          if (!queue) queue = invokeQueue;\n          return function() {\n            queue[insertMethod || 'push']([provider, method, arguments]);\n            return moduleInstance;\n          };\n        }\n      });\n    };\n  });\n\n}\n\n/* global: toDebugString: true */\n\nfunction serializeObject(obj) {\n  var seen = [];\n\n  return JSON.stringify(obj, function(key, val) {\n    val = toJsonReplacer(key, val);\n    if (isObject(val)) {\n\n      if (seen.indexOf(val) >= 0) return '<<already seen>>';\n\n      seen.push(val);\n    }\n    return val;\n  });\n}\n\nfunction toDebugString(obj) {\n  if (typeof obj === 'function') {\n    return obj.toString().replace(/ \\{[\\s\\S]*$/, '');\n  } else if (typeof obj === 'undefined') {\n    return 'undefined';\n  } else if (typeof obj !== 'string') {\n    return serializeObject(obj);\n  }\n  return obj;\n}\n\n/* global angularModule: true,\n  version: true,\n\n  $LocaleProvider,\n  $CompileProvider,\n\n  htmlAnchorDirective,\n  inputDirective,\n  inputDirective,\n  formDirective,\n  scriptDirective,\n  selectDirective,\n  styleDirective,\n  optionDirective,\n  ngBindDirective,\n  ngBindHtmlDirective,\n  ngBindTemplateDirective,\n  ngClassDirective,\n  ngClassEvenDirective,\n  ngClassOddDirective,\n  ngCspDirective,\n  ngCloakDirective,\n  ngControllerDirective,\n  ngFormDirective,\n  ngHideDirective,\n  ngIfDirective,\n  ngIncludeDirective,\n  ngIncludeFillContentDirective,\n  ngInitDirective,\n  ngNonBindableDirective,\n  ngPluralizeDirective,\n  ngRepeatDirective,\n  ngShowDirective,\n  ngStyleDirective,\n  ngSwitchDirective,\n  ngSwitchWhenDirective,\n  ngSwitchDefaultDirective,\n  ngOptionsDirective,\n  ngTranscludeDirective,\n  ngModelDirective,\n  ngListDirective,\n  ngChangeDirective,\n  patternDirective,\n  patternDirective,\n  requiredDirective,\n  requiredDirective,\n  minlengthDirective,\n  minlengthDirective,\n  maxlengthDirective,\n  maxlengthDirective,\n  ngValueDirective,\n  ngModelOptionsDirective,\n  ngAttributeAliasDirectives,\n  ngEventDirectives,\n\n  $AnchorScrollProvider,\n  $AnimateProvider,\n  $BrowserProvider,\n  $CacheFactoryProvider,\n  $ControllerProvider,\n  $DocumentProvider,\n  $ExceptionHandlerProvider,\n  $FilterProvider,\n  $InterpolateProvider,\n  $IntervalProvider,\n  $HttpProvider,\n  $HttpBackendProvider,\n  $LocationProvider,\n  $LogProvider,\n  $ParseProvider,\n  $RootScopeProvider,\n  $QProvider,\n  $$QProvider,\n  $$SanitizeUriProvider,\n  $SceProvider,\n  $SceDelegateProvider,\n  $SnifferProvider,\n  $TemplateCacheProvider,\n  $TemplateRequestProvider,\n  $$TestabilityProvider,\n  $TimeoutProvider,\n  $$RAFProvider,\n  $$AsyncCallbackProvider,\n  $WindowProvider,\n  $$jqLiteProvider\n*/\n\n\n/**\n * @ngdoc object\n * @name angular.version\n * @module ng\n * @description\n * An object that contains information about the current AngularJS version. This object has the\n * following properties:\n *\n * - `full` – `{string}` – Full version string, such as \"0.9.18\".\n * - `major` – `{number}` – Major version number, such as \"0\".\n * - `minor` – `{number}` – Minor version number, such as \"9\".\n * - `dot` – `{number}` – Dot version number, such as \"18\".\n * - `codeName` – `{string}` – Code name of the release, such as \"jiggling-armfat\".\n */\nvar version = {\n  full: '1.3.13',    // all of these placeholder strings will be replaced by grunt's\n  major: 1,    // package task\n  minor: 3,\n  dot: 13,\n  codeName: 'meticulous-riffleshuffle'\n};\n\n\nfunction publishExternalAPI(angular) {\n  extend(angular, {\n    'bootstrap': bootstrap,\n    'copy': copy,\n    'extend': extend,\n    'equals': equals,\n    'element': jqLite,\n    'forEach': forEach,\n    'injector': createInjector,\n    'noop': noop,\n    'bind': bind,\n    'toJson': toJson,\n    'fromJson': fromJson,\n    'identity': identity,\n    'isUndefined': isUndefined,\n    'isDefined': isDefined,\n    'isString': isString,\n    'isFunction': isFunction,\n    'isObject': isObject,\n    'isNumber': isNumber,\n    'isElement': isElement,\n    'isArray': isArray,\n    'version': version,\n    'isDate': isDate,\n    'lowercase': lowercase,\n    'uppercase': uppercase,\n    'callbacks': {counter: 0},\n    'getTestability': getTestability,\n    '$$minErr': minErr,\n    '$$csp': csp,\n    'reloadWithDebugInfo': reloadWithDebugInfo\n  });\n\n  angularModule = setupModuleLoader(window);\n  try {\n    angularModule('ngLocale');\n  } catch (e) {\n    angularModule('ngLocale', []).provider('$locale', $LocaleProvider);\n  }\n\n  angularModule('ng', ['ngLocale'], ['$provide',\n    function ngModule($provide) {\n      // $$sanitizeUriProvider needs to be before $compileProvider as it is used by it.\n      $provide.provider({\n        $$sanitizeUri: $$SanitizeUriProvider\n      });\n      $provide.provider('$compile', $CompileProvider).\n        directive({\n            a: htmlAnchorDirective,\n            input: inputDirective,\n            textarea: inputDirective,\n            form: formDirective,\n            script: scriptDirective,\n            select: selectDirective,\n            style: styleDirective,\n            option: optionDirective,\n            ngBind: ngBindDirective,\n            ngBindHtml: ngBindHtmlDirective,\n            ngBindTemplate: ngBindTemplateDirective,\n            ngClass: ngClassDirective,\n            ngClassEven: ngClassEvenDirective,\n            ngClassOdd: ngClassOddDirective,\n            ngCloak: ngCloakDirective,\n            ngController: ngControllerDirective,\n            ngForm: ngFormDirective,\n            ngHide: ngHideDirective,\n            ngIf: ngIfDirective,\n            ngInclude: ngIncludeDirective,\n            ngInit: ngInitDirective,\n            ngNonBindable: ngNonBindableDirective,\n            ngPluralize: ngPluralizeDirective,\n            ngRepeat: ngRepeatDirective,\n            ngShow: ngShowDirective,\n            ngStyle: ngStyleDirective,\n            ngSwitch: ngSwitchDirective,\n            ngSwitchWhen: ngSwitchWhenDirective,\n            ngSwitchDefault: ngSwitchDefaultDirective,\n            ngOptions: ngOptionsDirective,\n            ngTransclude: ngTranscludeDirective,\n            ngModel: ngModelDirective,\n            ngList: ngListDirective,\n            ngChange: ngChangeDirective,\n            pattern: patternDirective,\n            ngPattern: patternDirective,\n            required: requiredDirective,\n            ngRequired: requiredDirective,\n            minlength: minlengthDirective,\n            ngMinlength: minlengthDirective,\n            maxlength: maxlengthDirective,\n            ngMaxlength: maxlengthDirective,\n            ngValue: ngValueDirective,\n            ngModelOptions: ngModelOptionsDirective\n        }).\n        directive({\n          ngInclude: ngIncludeFillContentDirective\n        }).\n        directive(ngAttributeAliasDirectives).\n        directive(ngEventDirectives);\n      $provide.provider({\n        $anchorScroll: $AnchorScrollProvider,\n        $animate: $AnimateProvider,\n        $browser: $BrowserProvider,\n        $cacheFactory: $CacheFactoryProvider,\n        $controller: $ControllerProvider,\n        $document: $DocumentProvider,\n        $exceptionHandler: $ExceptionHandlerProvider,\n        $filter: $FilterProvider,\n        $interpolate: $InterpolateProvider,\n        $interval: $IntervalProvider,\n        $http: $HttpProvider,\n        $httpBackend: $HttpBackendProvider,\n        $location: $LocationProvider,\n        $log: $LogProvider,\n        $parse: $ParseProvider,\n        $rootScope: $RootScopeProvider,\n        $q: $QProvider,\n        $$q: $$QProvider,\n        $sce: $SceProvider,\n        $sceDelegate: $SceDelegateProvider,\n        $sniffer: $SnifferProvider,\n        $templateCache: $TemplateCacheProvider,\n        $templateRequest: $TemplateRequestProvider,\n        $$testability: $$TestabilityProvider,\n        $timeout: $TimeoutProvider,\n        $window: $WindowProvider,\n        $$rAF: $$RAFProvider,\n        $$asyncCallback: $$AsyncCallbackProvider,\n        $$jqLite: $$jqLiteProvider\n      });\n    }\n  ]);\n}\n\n/* global JQLitePrototype: true,\n  addEventListenerFn: true,\n  removeEventListenerFn: true,\n  BOOLEAN_ATTR: true,\n  ALIASED_ATTR: true,\n*/\n\n//////////////////////////////////\n//JQLite\n//////////////////////////////////\n\n/**\n * @ngdoc function\n * @name angular.element\n * @module ng\n * @kind function\n *\n * @description\n * Wraps a raw DOM element or HTML string as a [jQuery](http://jquery.com) element.\n *\n * If jQuery is available, `angular.element` is an alias for the\n * [jQuery](http://api.jquery.com/jQuery/) function. If jQuery is not available, `angular.element`\n * delegates to Angular's built-in subset of jQuery, called \"jQuery lite\" or \"jqLite.\"\n *\n * <div class=\"alert alert-success\">jqLite is a tiny, API-compatible subset of jQuery that allows\n * Angular to manipulate the DOM in a cross-browser compatible way. **jqLite** implements only the most\n * commonly needed functionality with the goal of having a very small footprint.</div>\n *\n * To use jQuery, simply load it before `DOMContentLoaded` event fired.\n *\n * <div class=\"alert\">**Note:** all element references in Angular are always wrapped with jQuery or\n * jqLite; they are never raw DOM references.</div>\n *\n * ## Angular's jqLite\n * jqLite provides only the following jQuery methods:\n *\n * - [`addClass()`](http://api.jquery.com/addClass/)\n * - [`after()`](http://api.jquery.com/after/)\n * - [`append()`](http://api.jquery.com/append/)\n * - [`attr()`](http://api.jquery.com/attr/) - Does not support functions as parameters\n * - [`bind()`](http://api.jquery.com/bind/) - Does not support namespaces, selectors or eventData\n * - [`children()`](http://api.jquery.com/children/) - Does not support selectors\n * - [`clone()`](http://api.jquery.com/clone/)\n * - [`contents()`](http://api.jquery.com/contents/)\n * - [`css()`](http://api.jquery.com/css/) - Only retrieves inline-styles, does not call `getComputedStyle()`\n * - [`data()`](http://api.jquery.com/data/)\n * - [`detach()`](http://api.jquery.com/detach/)\n * - [`empty()`](http://api.jquery.com/empty/)\n * - [`eq()`](http://api.jquery.com/eq/)\n * - [`find()`](http://api.jquery.com/find/) - Limited to lookups by tag name\n * - [`hasClass()`](http://api.jquery.com/hasClass/)\n * - [`html()`](http://api.jquery.com/html/)\n * - [`next()`](http://api.jquery.com/next/) - Does not support selectors\n * - [`on()`](http://api.jquery.com/on/) - Does not support namespaces, selectors or eventData\n * - [`off()`](http://api.jquery.com/off/) - Does not support namespaces or selectors\n * - [`one()`](http://api.jquery.com/one/) - Does not support namespaces or selectors\n * - [`parent()`](http://api.jquery.com/parent/) - Does not support selectors\n * - [`prepend()`](http://api.jquery.com/prepend/)\n * - [`prop()`](http://api.jquery.com/prop/)\n * - [`ready()`](http://api.jquery.com/ready/)\n * - [`remove()`](http://api.jquery.com/remove/)\n * - [`removeAttr()`](http://api.jquery.com/removeAttr/)\n * - [`removeClass()`](http://api.jquery.com/removeClass/)\n * - [`removeData()`](http://api.jquery.com/removeData/)\n * - [`replaceWith()`](http://api.jquery.com/replaceWith/)\n * - [`text()`](http://api.jquery.com/text/)\n * - [`toggleClass()`](http://api.jquery.com/toggleClass/)\n * - [`triggerHandler()`](http://api.jquery.com/triggerHandler/) - Passes a dummy event object to handlers.\n * - [`unbind()`](http://api.jquery.com/unbind/) - Does not support namespaces\n * - [`val()`](http://api.jquery.com/val/)\n * - [`wrap()`](http://api.jquery.com/wrap/)\n *\n * ## jQuery/jqLite Extras\n * Angular also provides the following additional methods and events to both jQuery and jqLite:\n *\n * ### Events\n * - `$destroy` - AngularJS intercepts all jqLite/jQuery's DOM destruction apis and fires this event\n *    on all DOM nodes being removed.  This can be used to clean up any 3rd party bindings to the DOM\n *    element before it is removed.\n *\n * ### Methods\n * - `controller(name)` - retrieves the controller of the current element or its parent. By default\n *   retrieves controller associated with the `ngController` directive. If `name` is provided as\n *   camelCase directive name, then the controller for this directive will be retrieved (e.g.\n *   `'ngModel'`).\n * - `injector()` - retrieves the injector of the current element or its parent.\n * - `scope()` - retrieves the {@link ng.$rootScope.Scope scope} of the current\n *   element or its parent. Requires {@link guide/production#disabling-debug-data Debug Data} to\n *   be enabled.\n * - `isolateScope()` - retrieves an isolate {@link ng.$rootScope.Scope scope} if one is attached directly to the\n *   current element. This getter should be used only on elements that contain a directive which starts a new isolate\n *   scope. Calling `scope()` on this element always returns the original non-isolate scope.\n *   Requires {@link guide/production#disabling-debug-data Debug Data} to be enabled.\n * - `inheritedData()` - same as `data()`, but walks up the DOM until a value is found or the top\n *   parent element is reached.\n *\n * @param {string|DOMElement} element HTML string or DOMElement to be wrapped into jQuery.\n * @returns {Object} jQuery object.\n */\n\nJQLite.expando = 'ng339';\n\nvar jqCache = JQLite.cache = {},\n    jqId = 1,\n    addEventListenerFn = function(element, type, fn) {\n      element.addEventListener(type, fn, false);\n    },\n    removeEventListenerFn = function(element, type, fn) {\n      element.removeEventListener(type, fn, false);\n    };\n\n/*\n * !!! This is an undocumented \"private\" function !!!\n */\nJQLite._data = function(node) {\n  //jQuery always returns an object on cache miss\n  return this.cache[node[this.expando]] || {};\n};\n\nfunction jqNextId() { return ++jqId; }\n\n\nvar SPECIAL_CHARS_REGEXP = /([\\:\\-\\_]+(.))/g;\nvar MOZ_HACK_REGEXP = /^moz([A-Z])/;\nvar MOUSE_EVENT_MAP= { mouseleave: \"mouseout\", mouseenter: \"mouseover\"};\nvar jqLiteMinErr = minErr('jqLite');\n\n/**\n * Converts snake_case to camelCase.\n * Also there is special case for Moz prefix starting with upper case letter.\n * @param name Name to normalize\n */\nfunction camelCase(name) {\n  return name.\n    replace(SPECIAL_CHARS_REGEXP, function(_, separator, letter, offset) {\n      return offset ? letter.toUpperCase() : letter;\n    }).\n    replace(MOZ_HACK_REGEXP, 'Moz$1');\n}\n\nvar SINGLE_TAG_REGEXP = /^<(\\w+)\\s*\\/?>(?:<\\/\\1>|)$/;\nvar HTML_REGEXP = /<|&#?\\w+;/;\nvar TAG_NAME_REGEXP = /<([\\w:]+)/;\nvar XHTML_TAG_REGEXP = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\\w:]+)[^>]*)\\/>/gi;\n\nvar wrapMap = {\n  'option': [1, '<select multiple=\"multiple\">', '</select>'],\n\n  'thead': [1, '<table>', '</table>'],\n  'col': [2, '<table><colgroup>', '</colgroup></table>'],\n  'tr': [2, '<table><tbody>', '</tbody></table>'],\n  'td': [3, '<table><tbody><tr>', '</tr></tbody></table>'],\n  '_default': [0, \"\", \"\"]\n};\n\nwrapMap.optgroup = wrapMap.option;\nwrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;\nwrapMap.th = wrapMap.td;\n\n\nfunction jqLiteIsTextNode(html) {\n  return !HTML_REGEXP.test(html);\n}\n\nfunction jqLiteAcceptsData(node) {\n  // The window object can accept data but has no nodeType\n  // Otherwise we are only interested in elements (1) and documents (9)\n  var nodeType = node.nodeType;\n  return nodeType === NODE_TYPE_ELEMENT || !nodeType || nodeType === NODE_TYPE_DOCUMENT;\n}\n\nfunction jqLiteBuildFragment(html, context) {\n  var tmp, tag, wrap,\n      fragment = context.createDocumentFragment(),\n      nodes = [], i;\n\n  if (jqLiteIsTextNode(html)) {\n    // Convert non-html into a text node\n    nodes.push(context.createTextNode(html));\n  } else {\n    // Convert html into DOM nodes\n    tmp = tmp || fragment.appendChild(context.createElement(\"div\"));\n    tag = (TAG_NAME_REGEXP.exec(html) || [\"\", \"\"])[1].toLowerCase();\n    wrap = wrapMap[tag] || wrapMap._default;\n    tmp.innerHTML = wrap[1] + html.replace(XHTML_TAG_REGEXP, \"<$1></$2>\") + wrap[2];\n\n    // Descend through wrappers to the right content\n    i = wrap[0];\n    while (i--) {\n      tmp = tmp.lastChild;\n    }\n\n    nodes = concat(nodes, tmp.childNodes);\n\n    tmp = fragment.firstChild;\n    tmp.textContent = \"\";\n  }\n\n  // Remove wrapper from fragment\n  fragment.textContent = \"\";\n  fragment.innerHTML = \"\"; // Clear inner HTML\n  forEach(nodes, function(node) {\n    fragment.appendChild(node);\n  });\n\n  return fragment;\n}\n\nfunction jqLiteParseHTML(html, context) {\n  context = context || document;\n  var parsed;\n\n  if ((parsed = SINGLE_TAG_REGEXP.exec(html))) {\n    return [context.createElement(parsed[1])];\n  }\n\n  if ((parsed = jqLiteBuildFragment(html, context))) {\n    return parsed.childNodes;\n  }\n\n  return [];\n}\n\n/////////////////////////////////////////////\nfunction JQLite(element) {\n  if (element instanceof JQLite) {\n    return element;\n  }\n\n  var argIsString;\n\n  if (isString(element)) {\n    element = trim(element);\n    argIsString = true;\n  }\n  if (!(this instanceof JQLite)) {\n    if (argIsString && element.charAt(0) != '<') {\n      throw jqLiteMinErr('nosel', 'Looking up elements via selectors is not supported by jqLite! See: http://docs.angularjs.org/api/angular.element');\n    }\n    return new JQLite(element);\n  }\n\n  if (argIsString) {\n    jqLiteAddNodes(this, jqLiteParseHTML(element));\n  } else {\n    jqLiteAddNodes(this, element);\n  }\n}\n\nfunction jqLiteClone(element) {\n  return element.cloneNode(true);\n}\n\nfunction jqLiteDealoc(element, onlyDescendants) {\n  if (!onlyDescendants) jqLiteRemoveData(element);\n\n  if (element.querySelectorAll) {\n    var descendants = element.querySelectorAll('*');\n    for (var i = 0, l = descendants.length; i < l; i++) {\n      jqLiteRemoveData(descendants[i]);\n    }\n  }\n}\n\nfunction jqLiteOff(element, type, fn, unsupported) {\n  if (isDefined(unsupported)) throw jqLiteMinErr('offargs', 'jqLite#off() does not support the `selector` argument');\n\n  var expandoStore = jqLiteExpandoStore(element);\n  var events = expandoStore && expandoStore.events;\n  var handle = expandoStore && expandoStore.handle;\n\n  if (!handle) return; //no listeners registered\n\n  if (!type) {\n    for (type in events) {\n      if (type !== '$destroy') {\n        removeEventListenerFn(element, type, handle);\n      }\n      delete events[type];\n    }\n  } else {\n    forEach(type.split(' '), function(type) {\n      if (isDefined(fn)) {\n        var listenerFns = events[type];\n        arrayRemove(listenerFns || [], fn);\n        if (listenerFns && listenerFns.length > 0) {\n          return;\n        }\n      }\n\n      removeEventListenerFn(element, type, handle);\n      delete events[type];\n    });\n  }\n}\n\nfunction jqLiteRemoveData(element, name) {\n  var expandoId = element.ng339;\n  var expandoStore = expandoId && jqCache[expandoId];\n\n  if (expandoStore) {\n    if (name) {\n      delete expandoStore.data[name];\n      return;\n    }\n\n    if (expandoStore.handle) {\n      if (expandoStore.events.$destroy) {\n        expandoStore.handle({}, '$destroy');\n      }\n      jqLiteOff(element);\n    }\n    delete jqCache[expandoId];\n    element.ng339 = undefined; // don't delete DOM expandos. IE and Chrome don't like it\n  }\n}\n\n\nfunction jqLiteExpandoStore(element, createIfNecessary) {\n  var expandoId = element.ng339,\n      expandoStore = expandoId && jqCache[expandoId];\n\n  if (createIfNecessary && !expandoStore) {\n    element.ng339 = expandoId = jqNextId();\n    expandoStore = jqCache[expandoId] = {events: {}, data: {}, handle: undefined};\n  }\n\n  return expandoStore;\n}\n\n\nfunction jqLiteData(element, key, value) {\n  if (jqLiteAcceptsData(element)) {\n\n    var isSimpleSetter = isDefined(value);\n    var isSimpleGetter = !isSimpleSetter && key && !isObject(key);\n    var massGetter = !key;\n    var expandoStore = jqLiteExpandoStore(element, !isSimpleGetter);\n    var data = expandoStore && expandoStore.data;\n\n    if (isSimpleSetter) { // data('key', value)\n      data[key] = value;\n    } else {\n      if (massGetter) {  // data()\n        return data;\n      } else {\n        if (isSimpleGetter) { // data('key')\n          // don't force creation of expandoStore if it doesn't exist yet\n          return data && data[key];\n        } else { // mass-setter: data({key1: val1, key2: val2})\n          extend(data, key);\n        }\n      }\n    }\n  }\n}\n\nfunction jqLiteHasClass(element, selector) {\n  if (!element.getAttribute) return false;\n  return ((\" \" + (element.getAttribute('class') || '') + \" \").replace(/[\\n\\t]/g, \" \").\n      indexOf(\" \" + selector + \" \") > -1);\n}\n\nfunction jqLiteRemoveClass(element, cssClasses) {\n  if (cssClasses && element.setAttribute) {\n    forEach(cssClasses.split(' '), function(cssClass) {\n      element.setAttribute('class', trim(\n          (\" \" + (element.getAttribute('class') || '') + \" \")\n          .replace(/[\\n\\t]/g, \" \")\n          .replace(\" \" + trim(cssClass) + \" \", \" \"))\n      );\n    });\n  }\n}\n\nfunction jqLiteAddClass(element, cssClasses) {\n  if (cssClasses && element.setAttribute) {\n    var existingClasses = (' ' + (element.getAttribute('class') || '') + ' ')\n                            .replace(/[\\n\\t]/g, \" \");\n\n    forEach(cssClasses.split(' '), function(cssClass) {\n      cssClass = trim(cssClass);\n      if (existingClasses.indexOf(' ' + cssClass + ' ') === -1) {\n        existingClasses += cssClass + ' ';\n      }\n    });\n\n    element.setAttribute('class', trim(existingClasses));\n  }\n}\n\n\nfunction jqLiteAddNodes(root, elements) {\n  // THIS CODE IS VERY HOT. Don't make changes without benchmarking.\n\n  if (elements) {\n\n    // if a Node (the most common case)\n    if (elements.nodeType) {\n      root[root.length++] = elements;\n    } else {\n      var length = elements.length;\n\n      // if an Array or NodeList and not a Window\n      if (typeof length === 'number' && elements.window !== elements) {\n        if (length) {\n          for (var i = 0; i < length; i++) {\n            root[root.length++] = elements[i];\n          }\n        }\n      } else {\n        root[root.length++] = elements;\n      }\n    }\n  }\n}\n\n\nfunction jqLiteController(element, name) {\n  return jqLiteInheritedData(element, '$' + (name || 'ngController') + 'Controller');\n}\n\nfunction jqLiteInheritedData(element, name, value) {\n  // if element is the document object work with the html element instead\n  // this makes $(document).scope() possible\n  if (element.nodeType == NODE_TYPE_DOCUMENT) {\n    element = element.documentElement;\n  }\n  var names = isArray(name) ? name : [name];\n\n  while (element) {\n    for (var i = 0, ii = names.length; i < ii; i++) {\n      if ((value = jqLite.data(element, names[i])) !== undefined) return value;\n    }\n\n    // If dealing with a document fragment node with a host element, and no parent, use the host\n    // element as the parent. This enables directives within a Shadow DOM or polyfilled Shadow DOM\n    // to lookup parent controllers.\n    element = element.parentNode || (element.nodeType === NODE_TYPE_DOCUMENT_FRAGMENT && element.host);\n  }\n}\n\nfunction jqLiteEmpty(element) {\n  jqLiteDealoc(element, true);\n  while (element.firstChild) {\n    element.removeChild(element.firstChild);\n  }\n}\n\nfunction jqLiteRemove(element, keepData) {\n  if (!keepData) jqLiteDealoc(element);\n  var parent = element.parentNode;\n  if (parent) parent.removeChild(element);\n}\n\n\nfunction jqLiteDocumentLoaded(action, win) {\n  win = win || window;\n  if (win.document.readyState === 'complete') {\n    // Force the action to be run async for consistent behaviour\n    // from the action's point of view\n    // i.e. it will definitely not be in a $apply\n    win.setTimeout(action);\n  } else {\n    // No need to unbind this handler as load is only ever called once\n    jqLite(win).on('load', action);\n  }\n}\n\n//////////////////////////////////////////\n// Functions which are declared directly.\n//////////////////////////////////////////\nvar JQLitePrototype = JQLite.prototype = {\n  ready: function(fn) {\n    var fired = false;\n\n    function trigger() {\n      if (fired) return;\n      fired = true;\n      fn();\n    }\n\n    // check if document is already loaded\n    if (document.readyState === 'complete') {\n      setTimeout(trigger);\n    } else {\n      this.on('DOMContentLoaded', trigger); // works for modern browsers and IE9\n      // we can not use jqLite since we are not done loading and jQuery could be loaded later.\n      // jshint -W064\n      JQLite(window).on('load', trigger); // fallback to window.onload for others\n      // jshint +W064\n    }\n  },\n  toString: function() {\n    var value = [];\n    forEach(this, function(e) { value.push('' + e);});\n    return '[' + value.join(', ') + ']';\n  },\n\n  eq: function(index) {\n      return (index >= 0) ? jqLite(this[index]) : jqLite(this[this.length + index]);\n  },\n\n  length: 0,\n  push: push,\n  sort: [].sort,\n  splice: [].splice\n};\n\n//////////////////////////////////////////\n// Functions iterating getter/setters.\n// these functions return self on setter and\n// value on get.\n//////////////////////////////////////////\nvar BOOLEAN_ATTR = {};\nforEach('multiple,selected,checked,disabled,readOnly,required,open'.split(','), function(value) {\n  BOOLEAN_ATTR[lowercase(value)] = value;\n});\nvar BOOLEAN_ELEMENTS = {};\nforEach('input,select,option,textarea,button,form,details'.split(','), function(value) {\n  BOOLEAN_ELEMENTS[value] = true;\n});\nvar ALIASED_ATTR = {\n  'ngMinlength': 'minlength',\n  'ngMaxlength': 'maxlength',\n  'ngMin': 'min',\n  'ngMax': 'max',\n  'ngPattern': 'pattern'\n};\n\nfunction getBooleanAttrName(element, name) {\n  // check dom last since we will most likely fail on name\n  var booleanAttr = BOOLEAN_ATTR[name.toLowerCase()];\n\n  // booleanAttr is here twice to minimize DOM access\n  return booleanAttr && BOOLEAN_ELEMENTS[nodeName_(element)] && booleanAttr;\n}\n\nfunction getAliasedAttrName(element, name) {\n  var nodeName = element.nodeName;\n  return (nodeName === 'INPUT' || nodeName === 'TEXTAREA') && ALIASED_ATTR[name];\n}\n\nforEach({\n  data: jqLiteData,\n  removeData: jqLiteRemoveData\n}, function(fn, name) {\n  JQLite[name] = fn;\n});\n\nforEach({\n  data: jqLiteData,\n  inheritedData: jqLiteInheritedData,\n\n  scope: function(element) {\n    // Can't use jqLiteData here directly so we stay compatible with jQuery!\n    return jqLite.data(element, '$scope') || jqLiteInheritedData(element.parentNode || element, ['$isolateScope', '$scope']);\n  },\n\n  isolateScope: function(element) {\n    // Can't use jqLiteData here directly so we stay compatible with jQuery!\n    return jqLite.data(element, '$isolateScope') || jqLite.data(element, '$isolateScopeNoTemplate');\n  },\n\n  controller: jqLiteController,\n\n  injector: function(element) {\n    return jqLiteInheritedData(element, '$injector');\n  },\n\n  removeAttr: function(element, name) {\n    element.removeAttribute(name);\n  },\n\n  hasClass: jqLiteHasClass,\n\n  css: function(element, name, value) {\n    name = camelCase(name);\n\n    if (isDefined(value)) {\n      element.style[name] = value;\n    } else {\n      return element.style[name];\n    }\n  },\n\n  attr: function(element, name, value) {\n    var lowercasedName = lowercase(name);\n    if (BOOLEAN_ATTR[lowercasedName]) {\n      if (isDefined(value)) {\n        if (!!value) {\n          element[name] = true;\n          element.setAttribute(name, lowercasedName);\n        } else {\n          element[name] = false;\n          element.removeAttribute(lowercasedName);\n        }\n      } else {\n        return (element[name] ||\n                 (element.attributes.getNamedItem(name) || noop).specified)\n               ? lowercasedName\n               : undefined;\n      }\n    } else if (isDefined(value)) {\n      element.setAttribute(name, value);\n    } else if (element.getAttribute) {\n      // the extra argument \"2\" is to get the right thing for a.href in IE, see jQuery code\n      // some elements (e.g. Document) don't have get attribute, so return undefined\n      var ret = element.getAttribute(name, 2);\n      // normalize non-existing attributes to undefined (as jQuery)\n      return ret === null ? undefined : ret;\n    }\n  },\n\n  prop: function(element, name, value) {\n    if (isDefined(value)) {\n      element[name] = value;\n    } else {\n      return element[name];\n    }\n  },\n\n  text: (function() {\n    getText.$dv = '';\n    return getText;\n\n    function getText(element, value) {\n      if (isUndefined(value)) {\n        var nodeType = element.nodeType;\n        return (nodeType === NODE_TYPE_ELEMENT || nodeType === NODE_TYPE_TEXT) ? element.textContent : '';\n      }\n      element.textContent = value;\n    }\n  })(),\n\n  val: function(element, value) {\n    if (isUndefined(value)) {\n      if (element.multiple && nodeName_(element) === 'select') {\n        var result = [];\n        forEach(element.options, function(option) {\n          if (option.selected) {\n            result.push(option.value || option.text);\n          }\n        });\n        return result.length === 0 ? null : result;\n      }\n      return element.value;\n    }\n    element.value = value;\n  },\n\n  html: function(element, value) {\n    if (isUndefined(value)) {\n      return element.innerHTML;\n    }\n    jqLiteDealoc(element, true);\n    element.innerHTML = value;\n  },\n\n  empty: jqLiteEmpty\n}, function(fn, name) {\n  /**\n   * Properties: writes return selection, reads return first value\n   */\n  JQLite.prototype[name] = function(arg1, arg2) {\n    var i, key;\n    var nodeCount = this.length;\n\n    // jqLiteHasClass has only two arguments, but is a getter-only fn, so we need to special-case it\n    // in a way that survives minification.\n    // jqLiteEmpty takes no arguments but is a setter.\n    if (fn !== jqLiteEmpty &&\n        (((fn.length == 2 && (fn !== jqLiteHasClass && fn !== jqLiteController)) ? arg1 : arg2) === undefined)) {\n      if (isObject(arg1)) {\n\n        // we are a write, but the object properties are the key/values\n        for (i = 0; i < nodeCount; i++) {\n          if (fn === jqLiteData) {\n            // data() takes the whole object in jQuery\n            fn(this[i], arg1);\n          } else {\n            for (key in arg1) {\n              fn(this[i], key, arg1[key]);\n            }\n          }\n        }\n        // return self for chaining\n        return this;\n      } else {\n        // we are a read, so read the first child.\n        // TODO: do we still need this?\n        var value = fn.$dv;\n        // Only if we have $dv do we iterate over all, otherwise it is just the first element.\n        var jj = (value === undefined) ? Math.min(nodeCount, 1) : nodeCount;\n        for (var j = 0; j < jj; j++) {\n          var nodeValue = fn(this[j], arg1, arg2);\n          value = value ? value + nodeValue : nodeValue;\n        }\n        return value;\n      }\n    } else {\n      // we are a write, so apply to all children\n      for (i = 0; i < nodeCount; i++) {\n        fn(this[i], arg1, arg2);\n      }\n      // return self for chaining\n      return this;\n    }\n  };\n});\n\nfunction createEventHandler(element, events) {\n  var eventHandler = function(event, type) {\n    // jQuery specific api\n    event.isDefaultPrevented = function() {\n      return event.defaultPrevented;\n    };\n\n    var eventFns = events[type || event.type];\n    var eventFnsLength = eventFns ? eventFns.length : 0;\n\n    if (!eventFnsLength) return;\n\n    if (isUndefined(event.immediatePropagationStopped)) {\n      var originalStopImmediatePropagation = event.stopImmediatePropagation;\n      event.stopImmediatePropagation = function() {\n        event.immediatePropagationStopped = true;\n\n        if (event.stopPropagation) {\n          event.stopPropagation();\n        }\n\n        if (originalStopImmediatePropagation) {\n          originalStopImmediatePropagation.call(event);\n        }\n      };\n    }\n\n    event.isImmediatePropagationStopped = function() {\n      return event.immediatePropagationStopped === true;\n    };\n\n    // Copy event handlers in case event handlers array is modified during execution.\n    if ((eventFnsLength > 1)) {\n      eventFns = shallowCopy(eventFns);\n    }\n\n    for (var i = 0; i < eventFnsLength; i++) {\n      if (!event.isImmediatePropagationStopped()) {\n        eventFns[i].call(element, event);\n      }\n    }\n  };\n\n  // TODO: this is a hack for angularMocks/clearDataCache that makes it possible to deregister all\n  //       events on `element`\n  eventHandler.elem = element;\n  return eventHandler;\n}\n\n//////////////////////////////////////////\n// Functions iterating traversal.\n// These functions chain results into a single\n// selector.\n//////////////////////////////////////////\nforEach({\n  removeData: jqLiteRemoveData,\n\n  on: function jqLiteOn(element, type, fn, unsupported) {\n    if (isDefined(unsupported)) throw jqLiteMinErr('onargs', 'jqLite#on() does not support the `selector` or `eventData` parameters');\n\n    // Do not add event handlers to non-elements because they will not be cleaned up.\n    if (!jqLiteAcceptsData(element)) {\n      return;\n    }\n\n    var expandoStore = jqLiteExpandoStore(element, true);\n    var events = expandoStore.events;\n    var handle = expandoStore.handle;\n\n    if (!handle) {\n      handle = expandoStore.handle = createEventHandler(element, events);\n    }\n\n    // http://jsperf.com/string-indexof-vs-split\n    var types = type.indexOf(' ') >= 0 ? type.split(' ') : [type];\n    var i = types.length;\n\n    while (i--) {\n      type = types[i];\n      var eventFns = events[type];\n\n      if (!eventFns) {\n        events[type] = [];\n\n        if (type === 'mouseenter' || type === 'mouseleave') {\n          // Refer to jQuery's implementation of mouseenter & mouseleave\n          // Read about mouseenter and mouseleave:\n          // http://www.quirksmode.org/js/events_mouse.html#link8\n\n          jqLiteOn(element, MOUSE_EVENT_MAP[type], function(event) {\n            var target = this, related = event.relatedTarget;\n            // For mousenter/leave call the handler if related is outside the target.\n            // NB: No relatedTarget if the mouse left/entered the browser window\n            if (!related || (related !== target && !target.contains(related))) {\n              handle(event, type);\n            }\n          });\n\n        } else {\n          if (type !== '$destroy') {\n            addEventListenerFn(element, type, handle);\n          }\n        }\n        eventFns = events[type];\n      }\n      eventFns.push(fn);\n    }\n  },\n\n  off: jqLiteOff,\n\n  one: function(element, type, fn) {\n    element = jqLite(element);\n\n    //add the listener twice so that when it is called\n    //you can remove the original function and still be\n    //able to call element.off(ev, fn) normally\n    element.on(type, function onFn() {\n      element.off(type, fn);\n      element.off(type, onFn);\n    });\n    element.on(type, fn);\n  },\n\n  replaceWith: function(element, replaceNode) {\n    var index, parent = element.parentNode;\n    jqLiteDealoc(element);\n    forEach(new JQLite(replaceNode), function(node) {\n      if (index) {\n        parent.insertBefore(node, index.nextSibling);\n      } else {\n        parent.replaceChild(node, element);\n      }\n      index = node;\n    });\n  },\n\n  children: function(element) {\n    var children = [];\n    forEach(element.childNodes, function(element) {\n      if (element.nodeType === NODE_TYPE_ELEMENT)\n        children.push(element);\n    });\n    return children;\n  },\n\n  contents: function(element) {\n    return element.contentDocument || element.childNodes || [];\n  },\n\n  append: function(element, node) {\n    var nodeType = element.nodeType;\n    if (nodeType !== NODE_TYPE_ELEMENT && nodeType !== NODE_TYPE_DOCUMENT_FRAGMENT) return;\n\n    node = new JQLite(node);\n\n    for (var i = 0, ii = node.length; i < ii; i++) {\n      var child = node[i];\n      element.appendChild(child);\n    }\n  },\n\n  prepend: function(element, node) {\n    if (element.nodeType === NODE_TYPE_ELEMENT) {\n      var index = element.firstChild;\n      forEach(new JQLite(node), function(child) {\n        element.insertBefore(child, index);\n      });\n    }\n  },\n\n  wrap: function(element, wrapNode) {\n    wrapNode = jqLite(wrapNode).eq(0).clone()[0];\n    var parent = element.parentNode;\n    if (parent) {\n      parent.replaceChild(wrapNode, element);\n    }\n    wrapNode.appendChild(element);\n  },\n\n  remove: jqLiteRemove,\n\n  detach: function(element) {\n    jqLiteRemove(element, true);\n  },\n\n  after: function(element, newElement) {\n    var index = element, parent = element.parentNode;\n    newElement = new JQLite(newElement);\n\n    for (var i = 0, ii = newElement.length; i < ii; i++) {\n      var node = newElement[i];\n      parent.insertBefore(node, index.nextSibling);\n      index = node;\n    }\n  },\n\n  addClass: jqLiteAddClass,\n  removeClass: jqLiteRemoveClass,\n\n  toggleClass: function(element, selector, condition) {\n    if (selector) {\n      forEach(selector.split(' '), function(className) {\n        var classCondition = condition;\n        if (isUndefined(classCondition)) {\n          classCondition = !jqLiteHasClass(element, className);\n        }\n        (classCondition ? jqLiteAddClass : jqLiteRemoveClass)(element, className);\n      });\n    }\n  },\n\n  parent: function(element) {\n    var parent = element.parentNode;\n    return parent && parent.nodeType !== NODE_TYPE_DOCUMENT_FRAGMENT ? parent : null;\n  },\n\n  next: function(element) {\n    return element.nextElementSibling;\n  },\n\n  find: function(element, selector) {\n    if (element.getElementsByTagName) {\n      return element.getElementsByTagName(selector);\n    } else {\n      return [];\n    }\n  },\n\n  clone: jqLiteClone,\n\n  triggerHandler: function(element, event, extraParameters) {\n\n    var dummyEvent, eventFnsCopy, handlerArgs;\n    var eventName = event.type || event;\n    var expandoStore = jqLiteExpandoStore(element);\n    var events = expandoStore && expandoStore.events;\n    var eventFns = events && events[eventName];\n\n    if (eventFns) {\n      // Create a dummy event to pass to the handlers\n      dummyEvent = {\n        preventDefault: function() { this.defaultPrevented = true; },\n        isDefaultPrevented: function() { return this.defaultPrevented === true; },\n        stopImmediatePropagation: function() { this.immediatePropagationStopped = true; },\n        isImmediatePropagationStopped: function() { return this.immediatePropagationStopped === true; },\n        stopPropagation: noop,\n        type: eventName,\n        target: element\n      };\n\n      // If a custom event was provided then extend our dummy event with it\n      if (event.type) {\n        dummyEvent = extend(dummyEvent, event);\n      }\n\n      // Copy event handlers in case event handlers array is modified during execution.\n      eventFnsCopy = shallowCopy(eventFns);\n      handlerArgs = extraParameters ? [dummyEvent].concat(extraParameters) : [dummyEvent];\n\n      forEach(eventFnsCopy, function(fn) {\n        if (!dummyEvent.isImmediatePropagationStopped()) {\n          fn.apply(element, handlerArgs);\n        }\n      });\n    }\n  }\n}, function(fn, name) {\n  /**\n   * chaining functions\n   */\n  JQLite.prototype[name] = function(arg1, arg2, arg3) {\n    var value;\n\n    for (var i = 0, ii = this.length; i < ii; i++) {\n      if (isUndefined(value)) {\n        value = fn(this[i], arg1, arg2, arg3);\n        if (isDefined(value)) {\n          // any function which returns a value needs to be wrapped\n          value = jqLite(value);\n        }\n      } else {\n        jqLiteAddNodes(value, fn(this[i], arg1, arg2, arg3));\n      }\n    }\n    return isDefined(value) ? value : this;\n  };\n\n  // bind legacy bind/unbind to on/off\n  JQLite.prototype.bind = JQLite.prototype.on;\n  JQLite.prototype.unbind = JQLite.prototype.off;\n});\n\n\n// Provider for private $$jqLite service\nfunction $$jqLiteProvider() {\n  this.$get = function $$jqLite() {\n    return extend(JQLite, {\n      hasClass: function(node, classes) {\n        if (node.attr) node = node[0];\n        return jqLiteHasClass(node, classes);\n      },\n      addClass: function(node, classes) {\n        if (node.attr) node = node[0];\n        return jqLiteAddClass(node, classes);\n      },\n      removeClass: function(node, classes) {\n        if (node.attr) node = node[0];\n        return jqLiteRemoveClass(node, classes);\n      }\n    });\n  };\n}\n\n/**\n * Computes a hash of an 'obj'.\n * Hash of a:\n *  string is string\n *  number is number as string\n *  object is either result of calling $$hashKey function on the object or uniquely generated id,\n *         that is also assigned to the $$hashKey property of the object.\n *\n * @param obj\n * @returns {string} hash string such that the same input will have the same hash string.\n *         The resulting string key is in 'type:hashKey' format.\n */\nfunction hashKey(obj, nextUidFn) {\n  var key = obj && obj.$$hashKey;\n\n  if (key) {\n    if (typeof key === 'function') {\n      key = obj.$$hashKey();\n    }\n    return key;\n  }\n\n  var objType = typeof obj;\n  if (objType == 'function' || (objType == 'object' && obj !== null)) {\n    key = obj.$$hashKey = objType + ':' + (nextUidFn || nextUid)();\n  } else {\n    key = objType + ':' + obj;\n  }\n\n  return key;\n}\n\n/**\n * HashMap which can use objects as keys\n */\nfunction HashMap(array, isolatedUid) {\n  if (isolatedUid) {\n    var uid = 0;\n    this.nextUid = function() {\n      return ++uid;\n    };\n  }\n  forEach(array, this.put, this);\n}\nHashMap.prototype = {\n  /**\n   * Store key value pair\n   * @param key key to store can be any type\n   * @param value value to store can be any type\n   */\n  put: function(key, value) {\n    this[hashKey(key, this.nextUid)] = value;\n  },\n\n  /**\n   * @param key\n   * @returns {Object} the value for the key\n   */\n  get: function(key) {\n    return this[hashKey(key, this.nextUid)];\n  },\n\n  /**\n   * Remove the key/value pair\n   * @param key\n   */\n  remove: function(key) {\n    var value = this[key = hashKey(key, this.nextUid)];\n    delete this[key];\n    return value;\n  }\n};\n\n/**\n * @ngdoc function\n * @module ng\n * @name angular.injector\n * @kind function\n *\n * @description\n * Creates an injector object that can be used for retrieving services as well as for\n * dependency injection (see {@link guide/di dependency injection}).\n *\n * @param {Array.<string|Function>} modules A list of module functions or their aliases. See\n *     {@link angular.module}. The `ng` module must be explicitly added.\n * @param {boolean=} [strictDi=false] Whether the injector should be in strict mode, which\n *     disallows argument name annotation inference.\n * @returns {injector} Injector object. See {@link auto.$injector $injector}.\n *\n * @example\n * Typical usage\n * ```js\n *   // create an injector\n *   var $injector = angular.injector(['ng']);\n *\n *   // use the injector to kick off your application\n *   // use the type inference to auto inject arguments, or use implicit injection\n *   $injector.invoke(function($rootScope, $compile, $document) {\n *     $compile($document)($rootScope);\n *     $rootScope.$digest();\n *   });\n * ```\n *\n * Sometimes you want to get access to the injector of a currently running Angular app\n * from outside Angular. Perhaps, you want to inject and compile some markup after the\n * application has been bootstrapped. You can do this using the extra `injector()` added\n * to JQuery/jqLite elements. See {@link angular.element}.\n *\n * *This is fairly rare but could be the case if a third party library is injecting the\n * markup.*\n *\n * In the following example a new block of HTML containing a `ng-controller`\n * directive is added to the end of the document body by JQuery. We then compile and link\n * it into the current AngularJS scope.\n *\n * ```js\n * var $div = $('<div ng-controller=\"MyCtrl\">{{content.label}}</div>');\n * $(document.body).append($div);\n *\n * angular.element(document).injector().invoke(function($compile) {\n *   var scope = angular.element($div).scope();\n *   $compile($div)(scope);\n * });\n * ```\n */\n\n\n/**\n * @ngdoc module\n * @name auto\n * @description\n *\n * Implicit module which gets automatically added to each {@link auto.$injector $injector}.\n */\n\nvar FN_ARGS = /^function\\s*[^\\(]*\\(\\s*([^\\)]*)\\)/m;\nvar FN_ARG_SPLIT = /,/;\nvar FN_ARG = /^\\s*(_?)(\\S+?)\\1\\s*$/;\nvar STRIP_COMMENTS = /((\\/\\/.*$)|(\\/\\*[\\s\\S]*?\\*\\/))/mg;\nvar $injectorMinErr = minErr('$injector');\n\nfunction anonFn(fn) {\n  // For anonymous functions, showing at the very least the function signature can help in\n  // debugging.\n  var fnText = fn.toString().replace(STRIP_COMMENTS, ''),\n      args = fnText.match(FN_ARGS);\n  if (args) {\n    return 'function(' + (args[1] || '').replace(/[\\s\\r\\n]+/, ' ') + ')';\n  }\n  return 'fn';\n}\n\nfunction annotate(fn, strictDi, name) {\n  var $inject,\n      fnText,\n      argDecl,\n      last;\n\n  if (typeof fn === 'function') {\n    if (!($inject = fn.$inject)) {\n      $inject = [];\n      if (fn.length) {\n        if (strictDi) {\n          if (!isString(name) || !name) {\n            name = fn.name || anonFn(fn);\n          }\n          throw $injectorMinErr('strictdi',\n            '{0} is not using explicit annotation and cannot be invoked in strict mode', name);\n        }\n        fnText = fn.toString().replace(STRIP_COMMENTS, '');\n        argDecl = fnText.match(FN_ARGS);\n        forEach(argDecl[1].split(FN_ARG_SPLIT), function(arg) {\n          arg.replace(FN_ARG, function(all, underscore, name) {\n            $inject.push(name);\n          });\n        });\n      }\n      fn.$inject = $inject;\n    }\n  } else if (isArray(fn)) {\n    last = fn.length - 1;\n    assertArgFn(fn[last], 'fn');\n    $inject = fn.slice(0, last);\n  } else {\n    assertArgFn(fn, 'fn', true);\n  }\n  return $inject;\n}\n\n///////////////////////////////////////\n\n/**\n * @ngdoc service\n * @name $injector\n *\n * @description\n *\n * `$injector` is used to retrieve object instances as defined by\n * {@link auto.$provide provider}, instantiate types, invoke methods,\n * and load modules.\n *\n * The following always holds true:\n *\n * ```js\n *   var $injector = angular.injector();\n *   expect($injector.get('$injector')).toBe($injector);\n *   expect($injector.invoke(function($injector) {\n *     return $injector;\n *   })).toBe($injector);\n * ```\n *\n * # Injection Function Annotation\n *\n * JavaScript does not have annotations, and annotations are needed for dependency injection. The\n * following are all valid ways of annotating function with injection arguments and are equivalent.\n *\n * ```js\n *   // inferred (only works if code not minified/obfuscated)\n *   $injector.invoke(function(serviceA){});\n *\n *   // annotated\n *   function explicit(serviceA) {};\n *   explicit.$inject = ['serviceA'];\n *   $injector.invoke(explicit);\n *\n *   // inline\n *   $injector.invoke(['serviceA', function(serviceA){}]);\n * ```\n *\n * ## Inference\n *\n * In JavaScript calling `toString()` on a function returns the function definition. The definition\n * can then be parsed and the function arguments can be extracted. This method of discovering\n * annotations is disallowed when the injector is in strict mode.\n * *NOTE:* This does not work with minification, and obfuscation tools since these tools change the\n * argument names.\n *\n * ## `$inject` Annotation\n * By adding an `$inject` property onto a function the injection parameters can be specified.\n *\n * ## Inline\n * As an array of injection names, where the last item in the array is the function to call.\n */\n\n/**\n * @ngdoc method\n * @name $injector#get\n *\n * @description\n * Return an instance of the service.\n *\n * @param {string} name The name of the instance to retrieve.\n * @param {string} caller An optional string to provide the origin of the function call for error messages.\n * @return {*} The instance.\n */\n\n/**\n * @ngdoc method\n * @name $injector#invoke\n *\n * @description\n * Invoke the method and supply the method arguments from the `$injector`.\n *\n * @param {!Function} fn The function to invoke. Function parameters are injected according to the\n *   {@link guide/di $inject Annotation} rules.\n * @param {Object=} self The `this` for the invoked method.\n * @param {Object=} locals Optional object. If preset then any argument names are read from this\n *                         object first, before the `$injector` is consulted.\n * @returns {*} the value returned by the invoked `fn` function.\n */\n\n/**\n * @ngdoc method\n * @name $injector#has\n *\n * @description\n * Allows the user to query if the particular service exists.\n *\n * @param {string} name Name of the service to query.\n * @returns {boolean} `true` if injector has given service.\n */\n\n/**\n * @ngdoc method\n * @name $injector#instantiate\n * @description\n * Create a new instance of JS type. The method takes a constructor function, invokes the new\n * operator, and supplies all of the arguments to the constructor function as specified by the\n * constructor annotation.\n *\n * @param {Function} Type Annotated constructor function.\n * @param {Object=} locals Optional object. If preset then any argument names are read from this\n * object first, before the `$injector` is consulted.\n * @returns {Object} new instance of `Type`.\n */\n\n/**\n * @ngdoc method\n * @name $injector#annotate\n *\n * @description\n * Returns an array of service names which the function is requesting for injection. This API is\n * used by the injector to determine which services need to be injected into the function when the\n * function is invoked. There are three ways in which the function can be annotated with the needed\n * dependencies.\n *\n * # Argument names\n *\n * The simplest form is to extract the dependencies from the arguments of the function. This is done\n * by converting the function into a string using `toString()` method and extracting the argument\n * names.\n * ```js\n *   // Given\n *   function MyController($scope, $route) {\n *     // ...\n *   }\n *\n *   // Then\n *   expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);\n * ```\n *\n * You can disallow this method by using strict injection mode.\n *\n * This method does not work with code minification / obfuscation. For this reason the following\n * annotation strategies are supported.\n *\n * # The `$inject` property\n *\n * If a function has an `$inject` property and its value is an array of strings, then the strings\n * represent names of services to be injected into the function.\n * ```js\n *   // Given\n *   var MyController = function(obfuscatedScope, obfuscatedRoute) {\n *     // ...\n *   }\n *   // Define function dependencies\n *   MyController['$inject'] = ['$scope', '$route'];\n *\n *   // Then\n *   expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);\n * ```\n *\n * # The array notation\n *\n * It is often desirable to inline Injected functions and that's when setting the `$inject` property\n * is very inconvenient. In these situations using the array notation to specify the dependencies in\n * a way that survives minification is a better choice:\n *\n * ```js\n *   // We wish to write this (not minification / obfuscation safe)\n *   injector.invoke(function($compile, $rootScope) {\n *     // ...\n *   });\n *\n *   // We are forced to write break inlining\n *   var tmpFn = function(obfuscatedCompile, obfuscatedRootScope) {\n *     // ...\n *   };\n *   tmpFn.$inject = ['$compile', '$rootScope'];\n *   injector.invoke(tmpFn);\n *\n *   // To better support inline function the inline annotation is supported\n *   injector.invoke(['$compile', '$rootScope', function(obfCompile, obfRootScope) {\n *     // ...\n *   }]);\n *\n *   // Therefore\n *   expect(injector.annotate(\n *      ['$compile', '$rootScope', function(obfus_$compile, obfus_$rootScope) {}])\n *    ).toEqual(['$compile', '$rootScope']);\n * ```\n *\n * @param {Function|Array.<string|Function>} fn Function for which dependent service names need to\n * be retrieved as described above.\n *\n * @param {boolean=} [strictDi=false] Disallow argument name annotation inference.\n *\n * @returns {Array.<string>} The names of the services which the function requires.\n */\n\n\n\n\n/**\n * @ngdoc service\n * @name $provide\n *\n * @description\n *\n * The {@link auto.$provide $provide} service has a number of methods for registering components\n * with the {@link auto.$injector $injector}. Many of these functions are also exposed on\n * {@link angular.Module}.\n *\n * An Angular **service** is a singleton object created by a **service factory**.  These **service\n * factories** are functions which, in turn, are created by a **service provider**.\n * The **service providers** are constructor functions. When instantiated they must contain a\n * property called `$get`, which holds the **service factory** function.\n *\n * When you request a service, the {@link auto.$injector $injector} is responsible for finding the\n * correct **service provider**, instantiating it and then calling its `$get` **service factory**\n * function to get the instance of the **service**.\n *\n * Often services have no configuration options and there is no need to add methods to the service\n * provider.  The provider will be no more than a constructor function with a `$get` property. For\n * these cases the {@link auto.$provide $provide} service has additional helper methods to register\n * services without specifying a provider.\n *\n * * {@link auto.$provide#provider provider(provider)} - registers a **service provider** with the\n *     {@link auto.$injector $injector}\n * * {@link auto.$provide#constant constant(obj)} - registers a value/object that can be accessed by\n *     providers and services.\n * * {@link auto.$provide#value value(obj)} - registers a value/object that can only be accessed by\n *     services, not providers.\n * * {@link auto.$provide#factory factory(fn)} - registers a service **factory function**, `fn`,\n *     that will be wrapped in a **service provider** object, whose `$get` property will contain the\n *     given factory function.\n * * {@link auto.$provide#service service(class)} - registers a **constructor function**, `class`\n *     that will be wrapped in a **service provider** object, whose `$get` property will instantiate\n *      a new object using the given constructor function.\n *\n * See the individual methods for more information and examples.\n */\n\n/**\n * @ngdoc method\n * @name $provide#provider\n * @description\n *\n * Register a **provider function** with the {@link auto.$injector $injector}. Provider functions\n * are constructor functions, whose instances are responsible for \"providing\" a factory for a\n * service.\n *\n * Service provider names start with the name of the service they provide followed by `Provider`.\n * For example, the {@link ng.$log $log} service has a provider called\n * {@link ng.$logProvider $logProvider}.\n *\n * Service provider objects can have additional methods which allow configuration of the provider\n * and its service. Importantly, you can configure what kind of service is created by the `$get`\n * method, or how that service will act. For example, the {@link ng.$logProvider $logProvider} has a\n * method {@link ng.$logProvider#debugEnabled debugEnabled}\n * which lets you specify whether the {@link ng.$log $log} service will log debug messages to the\n * console or not.\n *\n * @param {string} name The name of the instance. NOTE: the provider will be available under `name +\n                        'Provider'` key.\n * @param {(Object|function())} provider If the provider is:\n *\n *   - `Object`: then it should have a `$get` method. The `$get` method will be invoked using\n *     {@link auto.$injector#invoke $injector.invoke()} when an instance needs to be created.\n *   - `Constructor`: a new instance of the provider will be created using\n *     {@link auto.$injector#instantiate $injector.instantiate()}, then treated as `object`.\n *\n * @returns {Object} registered provider instance\n\n * @example\n *\n * The following example shows how to create a simple event tracking service and register it using\n * {@link auto.$provide#provider $provide.provider()}.\n *\n * ```js\n *  // Define the eventTracker provider\n *  function EventTrackerProvider() {\n *    var trackingUrl = '/track';\n *\n *    // A provider method for configuring where the tracked events should been saved\n *    this.setTrackingUrl = function(url) {\n *      trackingUrl = url;\n *    };\n *\n *    // The service factory function\n *    this.$get = ['$http', function($http) {\n *      var trackedEvents = {};\n *      return {\n *        // Call this to track an event\n *        event: function(event) {\n *          var count = trackedEvents[event] || 0;\n *          count += 1;\n *          trackedEvents[event] = count;\n *          return count;\n *        },\n *        // Call this to save the tracked events to the trackingUrl\n *        save: function() {\n *          $http.post(trackingUrl, trackedEvents);\n *        }\n *      };\n *    }];\n *  }\n *\n *  describe('eventTracker', function() {\n *    var postSpy;\n *\n *    beforeEach(module(function($provide) {\n *      // Register the eventTracker provider\n *      $provide.provider('eventTracker', EventTrackerProvider);\n *    }));\n *\n *    beforeEach(module(function(eventTrackerProvider) {\n *      // Configure eventTracker provider\n *      eventTrackerProvider.setTrackingUrl('/custom-track');\n *    }));\n *\n *    it('tracks events', inject(function(eventTracker) {\n *      expect(eventTracker.event('login')).toEqual(1);\n *      expect(eventTracker.event('login')).toEqual(2);\n *    }));\n *\n *    it('saves to the tracking url', inject(function(eventTracker, $http) {\n *      postSpy = spyOn($http, 'post');\n *      eventTracker.event('login');\n *      eventTracker.save();\n *      expect(postSpy).toHaveBeenCalled();\n *      expect(postSpy.mostRecentCall.args[0]).not.toEqual('/track');\n *      expect(postSpy.mostRecentCall.args[0]).toEqual('/custom-track');\n *      expect(postSpy.mostRecentCall.args[1]).toEqual({ 'login': 1 });\n *    }));\n *  });\n * ```\n */\n\n/**\n * @ngdoc method\n * @name $provide#factory\n * @description\n *\n * Register a **service factory**, which will be called to return the service instance.\n * This is short for registering a service where its provider consists of only a `$get` property,\n * which is the given service factory function.\n * You should use {@link auto.$provide#factory $provide.factory(getFn)} if you do not need to\n * configure your service in a provider.\n *\n * @param {string} name The name of the instance.\n * @param {function()} $getFn The $getFn for the instance creation. Internally this is a short hand\n *                            for `$provide.provider(name, {$get: $getFn})`.\n * @returns {Object} registered provider instance\n *\n * @example\n * Here is an example of registering a service\n * ```js\n *   $provide.factory('ping', ['$http', function($http) {\n *     return function ping() {\n *       return $http.send('/ping');\n *     };\n *   }]);\n * ```\n * You would then inject and use this service like this:\n * ```js\n *   someModule.controller('Ctrl', ['ping', function(ping) {\n *     ping();\n *   }]);\n * ```\n */\n\n\n/**\n * @ngdoc method\n * @name $provide#service\n * @description\n *\n * Register a **service constructor**, which will be invoked with `new` to create the service\n * instance.\n * This is short for registering a service where its provider's `$get` property is the service\n * constructor function that will be used to instantiate the service instance.\n *\n * You should use {@link auto.$provide#service $provide.service(class)} if you define your service\n * as a type/class.\n *\n * @param {string} name The name of the instance.\n * @param {Function} constructor A class (constructor function) that will be instantiated.\n * @returns {Object} registered provider instance\n *\n * @example\n * Here is an example of registering a service using\n * {@link auto.$provide#service $provide.service(class)}.\n * ```js\n *   var Ping = function($http) {\n *     this.$http = $http;\n *   };\n *\n *   Ping.$inject = ['$http'];\n *\n *   Ping.prototype.send = function() {\n *     return this.$http.get('/ping');\n *   };\n *   $provide.service('ping', Ping);\n * ```\n * You would then inject and use this service like this:\n * ```js\n *   someModule.controller('Ctrl', ['ping', function(ping) {\n *     ping.send();\n *   }]);\n * ```\n */\n\n\n/**\n * @ngdoc method\n * @name $provide#value\n * @description\n *\n * Register a **value service** with the {@link auto.$injector $injector}, such as a string, a\n * number, an array, an object or a function.  This is short for registering a service where its\n * provider's `$get` property is a factory function that takes no arguments and returns the **value\n * service**.\n *\n * Value services are similar to constant services, except that they cannot be injected into a\n * module configuration function (see {@link angular.Module#config}) but they can be overridden by\n * an Angular\n * {@link auto.$provide#decorator decorator}.\n *\n * @param {string} name The name of the instance.\n * @param {*} value The value.\n * @returns {Object} registered provider instance\n *\n * @example\n * Here are some examples of creating value services.\n * ```js\n *   $provide.value('ADMIN_USER', 'admin');\n *\n *   $provide.value('RoleLookup', { admin: 0, writer: 1, reader: 2 });\n *\n *   $provide.value('halfOf', function(value) {\n *     return value / 2;\n *   });\n * ```\n */\n\n\n/**\n * @ngdoc method\n * @name $provide#constant\n * @description\n *\n * Register a **constant service**, such as a string, a number, an array, an object or a function,\n * with the {@link auto.$injector $injector}. Unlike {@link auto.$provide#value value} it can be\n * injected into a module configuration function (see {@link angular.Module#config}) and it cannot\n * be overridden by an Angular {@link auto.$provide#decorator decorator}.\n *\n * @param {string} name The name of the constant.\n * @param {*} value The constant value.\n * @returns {Object} registered instance\n *\n * @example\n * Here a some examples of creating constants:\n * ```js\n *   $provide.constant('SHARD_HEIGHT', 306);\n *\n *   $provide.constant('MY_COLOURS', ['red', 'blue', 'grey']);\n *\n *   $provide.constant('double', function(value) {\n *     return value * 2;\n *   });\n * ```\n */\n\n\n/**\n * @ngdoc method\n * @name $provide#decorator\n * @description\n *\n * Register a **service decorator** with the {@link auto.$injector $injector}. A service decorator\n * intercepts the creation of a service, allowing it to override or modify the behaviour of the\n * service. The object returned by the decorator may be the original service, or a new service\n * object which replaces or wraps and delegates to the original service.\n *\n * @param {string} name The name of the service to decorate.\n * @param {function()} decorator This function will be invoked when the service needs to be\n *    instantiated and should return the decorated service instance. The function is called using\n *    the {@link auto.$injector#invoke injector.invoke} method and is therefore fully injectable.\n *    Local injection arguments:\n *\n *    * `$delegate` - The original service instance, which can be monkey patched, configured,\n *      decorated or delegated to.\n *\n * @example\n * Here we decorate the {@link ng.$log $log} service to convert warnings to errors by intercepting\n * calls to {@link ng.$log#error $log.warn()}.\n * ```js\n *   $provide.decorator('$log', ['$delegate', function($delegate) {\n *     $delegate.warn = $delegate.error;\n *     return $delegate;\n *   }]);\n * ```\n */\n\n\nfunction createInjector(modulesToLoad, strictDi) {\n  strictDi = (strictDi === true);\n  var INSTANTIATING = {},\n      providerSuffix = 'Provider',\n      path = [],\n      loadedModules = new HashMap([], true),\n      providerCache = {\n        $provide: {\n            provider: supportObject(provider),\n            factory: supportObject(factory),\n            service: supportObject(service),\n            value: supportObject(value),\n            constant: supportObject(constant),\n            decorator: decorator\n          }\n      },\n      providerInjector = (providerCache.$injector =\n          createInternalInjector(providerCache, function(serviceName, caller) {\n            if (angular.isString(caller)) {\n              path.push(caller);\n            }\n            throw $injectorMinErr('unpr', \"Unknown provider: {0}\", path.join(' <- '));\n          })),\n      instanceCache = {},\n      instanceInjector = (instanceCache.$injector =\n          createInternalInjector(instanceCache, function(serviceName, caller) {\n            var provider = providerInjector.get(serviceName + providerSuffix, caller);\n            return instanceInjector.invoke(provider.$get, provider, undefined, serviceName);\n          }));\n\n\n  forEach(loadModules(modulesToLoad), function(fn) { instanceInjector.invoke(fn || noop); });\n\n  return instanceInjector;\n\n  ////////////////////////////////////\n  // $provider\n  ////////////////////////////////////\n\n  function supportObject(delegate) {\n    return function(key, value) {\n      if (isObject(key)) {\n        forEach(key, reverseParams(delegate));\n      } else {\n        return delegate(key, value);\n      }\n    };\n  }\n\n  function provider(name, provider_) {\n    assertNotHasOwnProperty(name, 'service');\n    if (isFunction(provider_) || isArray(provider_)) {\n      provider_ = providerInjector.instantiate(provider_);\n    }\n    if (!provider_.$get) {\n      throw $injectorMinErr('pget', \"Provider '{0}' must define $get factory method.\", name);\n    }\n    return providerCache[name + providerSuffix] = provider_;\n  }\n\n  function enforceReturnValue(name, factory) {\n    return function enforcedReturnValue() {\n      var result = instanceInjector.invoke(factory, this);\n      if (isUndefined(result)) {\n        throw $injectorMinErr('undef', \"Provider '{0}' must return a value from $get factory method.\", name);\n      }\n      return result;\n    };\n  }\n\n  function factory(name, factoryFn, enforce) {\n    return provider(name, {\n      $get: enforce !== false ? enforceReturnValue(name, factoryFn) : factoryFn\n    });\n  }\n\n  function service(name, constructor) {\n    return factory(name, ['$injector', function($injector) {\n      return $injector.instantiate(constructor);\n    }]);\n  }\n\n  function value(name, val) { return factory(name, valueFn(val), false); }\n\n  function constant(name, value) {\n    assertNotHasOwnProperty(name, 'constant');\n    providerCache[name] = value;\n    instanceCache[name] = value;\n  }\n\n  function decorator(serviceName, decorFn) {\n    var origProvider = providerInjector.get(serviceName + providerSuffix),\n        orig$get = origProvider.$get;\n\n    origProvider.$get = function() {\n      var origInstance = instanceInjector.invoke(orig$get, origProvider);\n      return instanceInjector.invoke(decorFn, null, {$delegate: origInstance});\n    };\n  }\n\n  ////////////////////////////////////\n  // Module Loading\n  ////////////////////////////////////\n  function loadModules(modulesToLoad) {\n    var runBlocks = [], moduleFn;\n    forEach(modulesToLoad, function(module) {\n      if (loadedModules.get(module)) return;\n      loadedModules.put(module, true);\n\n      function runInvokeQueue(queue) {\n        var i, ii;\n        for (i = 0, ii = queue.length; i < ii; i++) {\n          var invokeArgs = queue[i],\n              provider = providerInjector.get(invokeArgs[0]);\n\n          provider[invokeArgs[1]].apply(provider, invokeArgs[2]);\n        }\n      }\n\n      try {\n        if (isString(module)) {\n          moduleFn = angularModule(module);\n          runBlocks = runBlocks.concat(loadModules(moduleFn.requires)).concat(moduleFn._runBlocks);\n          runInvokeQueue(moduleFn._invokeQueue);\n          runInvokeQueue(moduleFn._configBlocks);\n        } else if (isFunction(module)) {\n            runBlocks.push(providerInjector.invoke(module));\n        } else if (isArray(module)) {\n            runBlocks.push(providerInjector.invoke(module));\n        } else {\n          assertArgFn(module, 'module');\n        }\n      } catch (e) {\n        if (isArray(module)) {\n          module = module[module.length - 1];\n        }\n        if (e.message && e.stack && e.stack.indexOf(e.message) == -1) {\n          // Safari & FF's stack traces don't contain error.message content\n          // unlike those of Chrome and IE\n          // So if stack doesn't contain message, we create a new string that contains both.\n          // Since error.stack is read-only in Safari, I'm overriding e and not e.stack here.\n          /* jshint -W022 */\n          e = e.message + '\\n' + e.stack;\n        }\n        throw $injectorMinErr('modulerr', \"Failed to instantiate module {0} due to:\\n{1}\",\n                  module, e.stack || e.message || e);\n      }\n    });\n    return runBlocks;\n  }\n\n  ////////////////////////////////////\n  // internal Injector\n  ////////////////////////////////////\n\n  function createInternalInjector(cache, factory) {\n\n    function getService(serviceName, caller) {\n      if (cache.hasOwnProperty(serviceName)) {\n        if (cache[serviceName] === INSTANTIATING) {\n          throw $injectorMinErr('cdep', 'Circular dependency found: {0}',\n                    serviceName + ' <- ' + path.join(' <- '));\n        }\n        return cache[serviceName];\n      } else {\n        try {\n          path.unshift(serviceName);\n          cache[serviceName] = INSTANTIATING;\n          return cache[serviceName] = factory(serviceName, caller);\n        } catch (err) {\n          if (cache[serviceName] === INSTANTIATING) {\n            delete cache[serviceName];\n          }\n          throw err;\n        } finally {\n          path.shift();\n        }\n      }\n    }\n\n    function invoke(fn, self, locals, serviceName) {\n      if (typeof locals === 'string') {\n        serviceName = locals;\n        locals = null;\n      }\n\n      var args = [],\n          $inject = createInjector.$$annotate(fn, strictDi, serviceName),\n          length, i,\n          key;\n\n      for (i = 0, length = $inject.length; i < length; i++) {\n        key = $inject[i];\n        if (typeof key !== 'string') {\n          throw $injectorMinErr('itkn',\n                  'Incorrect injection token! Expected service name as string, got {0}', key);\n        }\n        args.push(\n          locals && locals.hasOwnProperty(key)\n          ? locals[key]\n          : getService(key, serviceName)\n        );\n      }\n      if (isArray(fn)) {\n        fn = fn[length];\n      }\n\n      // http://jsperf.com/angularjs-invoke-apply-vs-switch\n      // #5388\n      return fn.apply(self, args);\n    }\n\n    function instantiate(Type, locals, serviceName) {\n      // Check if Type is annotated and use just the given function at n-1 as parameter\n      // e.g. someModule.factory('greeter', ['$window', function(renamed$window) {}]);\n      // Object creation: http://jsperf.com/create-constructor/2\n      var instance = Object.create((isArray(Type) ? Type[Type.length - 1] : Type).prototype || null);\n      var returnedValue = invoke(Type, instance, locals, serviceName);\n\n      return isObject(returnedValue) || isFunction(returnedValue) ? returnedValue : instance;\n    }\n\n    return {\n      invoke: invoke,\n      instantiate: instantiate,\n      get: getService,\n      annotate: createInjector.$$annotate,\n      has: function(name) {\n        return providerCache.hasOwnProperty(name + providerSuffix) || cache.hasOwnProperty(name);\n      }\n    };\n  }\n}\n\ncreateInjector.$$annotate = annotate;\n\n/**\n * @ngdoc provider\n * @name $anchorScrollProvider\n *\n * @description\n * Use `$anchorScrollProvider` to disable automatic scrolling whenever\n * {@link ng.$location#hash $location.hash()} changes.\n */\nfunction $AnchorScrollProvider() {\n\n  var autoScrollingEnabled = true;\n\n  /**\n   * @ngdoc method\n   * @name $anchorScrollProvider#disableAutoScrolling\n   *\n   * @description\n   * By default, {@link ng.$anchorScroll $anchorScroll()} will automatically detect changes to\n   * {@link ng.$location#hash $location.hash()} and scroll to the element matching the new hash.<br />\n   * Use this method to disable automatic scrolling.\n   *\n   * If automatic scrolling is disabled, one must explicitly call\n   * {@link ng.$anchorScroll $anchorScroll()} in order to scroll to the element related to the\n   * current hash.\n   */\n  this.disableAutoScrolling = function() {\n    autoScrollingEnabled = false;\n  };\n\n  /**\n   * @ngdoc service\n   * @name $anchorScroll\n   * @kind function\n   * @requires $window\n   * @requires $location\n   * @requires $rootScope\n   *\n   * @description\n   * When called, it checks the current value of {@link ng.$location#hash $location.hash()} and\n   * scrolls to the related element, according to the rules specified in the\n   * [Html5 spec](http://dev.w3.org/html5/spec/Overview.html#the-indicated-part-of-the-document).\n   *\n   * It also watches the {@link ng.$location#hash $location.hash()} and automatically scrolls to\n   * match any anchor whenever it changes. This can be disabled by calling\n   * {@link ng.$anchorScrollProvider#disableAutoScrolling $anchorScrollProvider.disableAutoScrolling()}.\n   *\n   * Additionally, you can use its {@link ng.$anchorScroll#yOffset yOffset} property to specify a\n   * vertical scroll-offset (either fixed or dynamic).\n   *\n   * @property {(number|function|jqLite)} yOffset\n   * If set, specifies a vertical scroll-offset. This is often useful when there are fixed\n   * positioned elements at the top of the page, such as navbars, headers etc.\n   *\n   * `yOffset` can be specified in various ways:\n   * - **number**: A fixed number of pixels to be used as offset.<br /><br />\n   * - **function**: A getter function called everytime `$anchorScroll()` is executed. Must return\n   *   a number representing the offset (in pixels).<br /><br />\n   * - **jqLite**: A jqLite/jQuery element to be used for specifying the offset. The distance from\n   *   the top of the page to the element's bottom will be used as offset.<br />\n   *   **Note**: The element will be taken into account only as long as its `position` is set to\n   *   `fixed`. This option is useful, when dealing with responsive navbars/headers that adjust\n   *   their height and/or positioning according to the viewport's size.\n   *\n   * <br />\n   * <div class=\"alert alert-warning\">\n   * In order for `yOffset` to work properly, scrolling should take place on the document's root and\n   * not some child element.\n   * </div>\n   *\n   * @example\n     <example module=\"anchorScrollExample\">\n       <file name=\"index.html\">\n         <div id=\"scrollArea\" ng-controller=\"ScrollController\">\n           <a ng-click=\"gotoBottom()\">Go to bottom</a>\n           <a id=\"bottom\"></a> You're at the bottom!\n         </div>\n       </file>\n       <file name=\"script.js\">\n         angular.module('anchorScrollExample', [])\n           .controller('ScrollController', ['$scope', '$location', '$anchorScroll',\n             function ($scope, $location, $anchorScroll) {\n               $scope.gotoBottom = function() {\n                 // set the location.hash to the id of\n                 // the element you wish to scroll to.\n                 $location.hash('bottom');\n\n                 // call $anchorScroll()\n                 $anchorScroll();\n               };\n             }]);\n       </file>\n       <file name=\"style.css\">\n         #scrollArea {\n           height: 280px;\n           overflow: auto;\n         }\n\n         #bottom {\n           display: block;\n           margin-top: 2000px;\n         }\n       </file>\n     </example>\n   *\n   * <hr />\n   * The example below illustrates the use of a vertical scroll-offset (specified as a fixed value).\n   * See {@link ng.$anchorScroll#yOffset $anchorScroll.yOffset} for more details.\n   *\n   * @example\n     <example module=\"anchorScrollOffsetExample\">\n       <file name=\"index.html\">\n         <div class=\"fixed-header\" ng-controller=\"headerCtrl\">\n           <a href=\"\" ng-click=\"gotoAnchor(x)\" ng-repeat=\"x in [1,2,3,4,5]\">\n             Go to anchor {{x}}\n           </a>\n         </div>\n         <div id=\"anchor{{x}}\" class=\"anchor\" ng-repeat=\"x in [1,2,3,4,5]\">\n           Anchor {{x}} of 5\n         </div>\n       </file>\n       <file name=\"script.js\">\n         angular.module('anchorScrollOffsetExample', [])\n           .run(['$anchorScroll', function($anchorScroll) {\n             $anchorScroll.yOffset = 50;   // always scroll by 50 extra pixels\n           }])\n           .controller('headerCtrl', ['$anchorScroll', '$location', '$scope',\n             function ($anchorScroll, $location, $scope) {\n               $scope.gotoAnchor = function(x) {\n                 var newHash = 'anchor' + x;\n                 if ($location.hash() !== newHash) {\n                   // set the $location.hash to `newHash` and\n                   // $anchorScroll will automatically scroll to it\n                   $location.hash('anchor' + x);\n                 } else {\n                   // call $anchorScroll() explicitly,\n                   // since $location.hash hasn't changed\n                   $anchorScroll();\n                 }\n               };\n             }\n           ]);\n       </file>\n       <file name=\"style.css\">\n         body {\n           padding-top: 50px;\n         }\n\n         .anchor {\n           border: 2px dashed DarkOrchid;\n           padding: 10px 10px 200px 10px;\n         }\n\n         .fixed-header {\n           background-color: rgba(0, 0, 0, 0.2);\n           height: 50px;\n           position: fixed;\n           top: 0; left: 0; right: 0;\n         }\n\n         .fixed-header > a {\n           display: inline-block;\n           margin: 5px 15px;\n         }\n       </file>\n     </example>\n   */\n  this.$get = ['$window', '$location', '$rootScope', function($window, $location, $rootScope) {\n    var document = $window.document;\n\n    // Helper function to get first anchor from a NodeList\n    // (using `Array#some()` instead of `angular#forEach()` since it's more performant\n    //  and working in all supported browsers.)\n    function getFirstAnchor(list) {\n      var result = null;\n      Array.prototype.some.call(list, function(element) {\n        if (nodeName_(element) === 'a') {\n          result = element;\n          return true;\n        }\n      });\n      return result;\n    }\n\n    function getYOffset() {\n\n      var offset = scroll.yOffset;\n\n      if (isFunction(offset)) {\n        offset = offset();\n      } else if (isElement(offset)) {\n        var elem = offset[0];\n        var style = $window.getComputedStyle(elem);\n        if (style.position !== 'fixed') {\n          offset = 0;\n        } else {\n          offset = elem.getBoundingClientRect().bottom;\n        }\n      } else if (!isNumber(offset)) {\n        offset = 0;\n      }\n\n      return offset;\n    }\n\n    function scrollTo(elem) {\n      if (elem) {\n        elem.scrollIntoView();\n\n        var offset = getYOffset();\n\n        if (offset) {\n          // `offset` is the number of pixels we should scroll UP in order to align `elem` properly.\n          // This is true ONLY if the call to `elem.scrollIntoView()` initially aligns `elem` at the\n          // top of the viewport.\n          //\n          // IF the number of pixels from the top of `elem` to the end of the page's content is less\n          // than the height of the viewport, then `elem.scrollIntoView()` will align the `elem` some\n          // way down the page.\n          //\n          // This is often the case for elements near the bottom of the page.\n          //\n          // In such cases we do not need to scroll the whole `offset` up, just the difference between\n          // the top of the element and the offset, which is enough to align the top of `elem` at the\n          // desired position.\n          var elemTop = elem.getBoundingClientRect().top;\n          $window.scrollBy(0, elemTop - offset);\n        }\n      } else {\n        $window.scrollTo(0, 0);\n      }\n    }\n\n    function scroll() {\n      var hash = $location.hash(), elm;\n\n      // empty hash, scroll to the top of the page\n      if (!hash) scrollTo(null);\n\n      // element with given id\n      else if ((elm = document.getElementById(hash))) scrollTo(elm);\n\n      // first anchor with given name :-D\n      else if ((elm = getFirstAnchor(document.getElementsByName(hash)))) scrollTo(elm);\n\n      // no element and hash == 'top', scroll to the top of the page\n      else if (hash === 'top') scrollTo(null);\n    }\n\n    // does not scroll when user clicks on anchor link that is currently on\n    // (no url change, no $location.hash() change), browser native does scroll\n    if (autoScrollingEnabled) {\n      $rootScope.$watch(function autoScrollWatch() {return $location.hash();},\n        function autoScrollWatchAction(newVal, oldVal) {\n          // skip the initial scroll if $location.hash is empty\n          if (newVal === oldVal && newVal === '') return;\n\n          jqLiteDocumentLoaded(function() {\n            $rootScope.$evalAsync(scroll);\n          });\n        });\n    }\n\n    return scroll;\n  }];\n}\n\nvar $animateMinErr = minErr('$animate');\n\n/**\n * @ngdoc provider\n * @name $animateProvider\n *\n * @description\n * Default implementation of $animate that doesn't perform any animations, instead just\n * synchronously performs DOM\n * updates and calls done() callbacks.\n *\n * In order to enable animations the ngAnimate module has to be loaded.\n *\n * To see the functional implementation check out src/ngAnimate/animate.js\n */\nvar $AnimateProvider = ['$provide', function($provide) {\n\n\n  this.$$selectors = {};\n\n\n  /**\n   * @ngdoc method\n   * @name $animateProvider#register\n   *\n   * @description\n   * Registers a new injectable animation factory function. The factory function produces the\n   * animation object which contains callback functions for each event that is expected to be\n   * animated.\n   *\n   *   * `eventFn`: `function(Element, doneFunction)` The element to animate, the `doneFunction`\n   *   must be called once the element animation is complete. If a function is returned then the\n   *   animation service will use this function to cancel the animation whenever a cancel event is\n   *   triggered.\n   *\n   *\n   * ```js\n   *   return {\n     *     eventFn : function(element, done) {\n     *       //code to run the animation\n     *       //once complete, then run done()\n     *       return function cancellationFunction() {\n     *         //code to cancel the animation\n     *       }\n     *     }\n     *   }\n   * ```\n   *\n   * @param {string} name The name of the animation.\n   * @param {Function} factory The factory function that will be executed to return the animation\n   *                           object.\n   */\n  this.register = function(name, factory) {\n    var key = name + '-animation';\n    if (name && name.charAt(0) != '.') throw $animateMinErr('notcsel',\n        \"Expecting class selector starting with '.' got '{0}'.\", name);\n    this.$$selectors[name.substr(1)] = key;\n    $provide.factory(key, factory);\n  };\n\n  /**\n   * @ngdoc method\n   * @name $animateProvider#classNameFilter\n   *\n   * @description\n   * Sets and/or returns the CSS class regular expression that is checked when performing\n   * an animation. Upon bootstrap the classNameFilter value is not set at all and will\n   * therefore enable $animate to attempt to perform an animation on any element.\n   * When setting the classNameFilter value, animations will only be performed on elements\n   * that successfully match the filter expression. This in turn can boost performance\n   * for low-powered devices as well as applications containing a lot of structural operations.\n   * @param {RegExp=} expression The className expression which will be checked against all animations\n   * @return {RegExp} The current CSS className expression value. If null then there is no expression value\n   */\n  this.classNameFilter = function(expression) {\n    if (arguments.length === 1) {\n      this.$$classNameFilter = (expression instanceof RegExp) ? expression : null;\n    }\n    return this.$$classNameFilter;\n  };\n\n  this.$get = ['$$q', '$$asyncCallback', '$rootScope', function($$q, $$asyncCallback, $rootScope) {\n\n    var currentDefer;\n\n    function runAnimationPostDigest(fn) {\n      var cancelFn, defer = $$q.defer();\n      defer.promise.$$cancelFn = function ngAnimateMaybeCancel() {\n        cancelFn && cancelFn();\n      };\n\n      $rootScope.$$postDigest(function ngAnimatePostDigest() {\n        cancelFn = fn(function ngAnimateNotifyComplete() {\n          defer.resolve();\n        });\n      });\n\n      return defer.promise;\n    }\n\n    function resolveElementClasses(element, classes) {\n      var toAdd = [], toRemove = [];\n\n      var hasClasses = createMap();\n      forEach((element.attr('class') || '').split(/\\s+/), function(className) {\n        hasClasses[className] = true;\n      });\n\n      forEach(classes, function(status, className) {\n        var hasClass = hasClasses[className];\n\n        // If the most recent class manipulation (via $animate) was to remove the class, and the\n        // element currently has the class, the class is scheduled for removal. Otherwise, if\n        // the most recent class manipulation (via $animate) was to add the class, and the\n        // element does not currently have the class, the class is scheduled to be added.\n        if (status === false && hasClass) {\n          toRemove.push(className);\n        } else if (status === true && !hasClass) {\n          toAdd.push(className);\n        }\n      });\n\n      return (toAdd.length + toRemove.length) > 0 &&\n        [toAdd.length ? toAdd : null, toRemove.length ? toRemove : null];\n    }\n\n    function cachedClassManipulation(cache, classes, op) {\n      for (var i=0, ii = classes.length; i < ii; ++i) {\n        var className = classes[i];\n        cache[className] = op;\n      }\n    }\n\n    function asyncPromise() {\n      // only serve one instance of a promise in order to save CPU cycles\n      if (!currentDefer) {\n        currentDefer = $$q.defer();\n        $$asyncCallback(function() {\n          currentDefer.resolve();\n          currentDefer = null;\n        });\n      }\n      return currentDefer.promise;\n    }\n\n    function applyStyles(element, options) {\n      if (angular.isObject(options)) {\n        var styles = extend(options.from || {}, options.to || {});\n        element.css(styles);\n      }\n    }\n\n    /**\n     *\n     * @ngdoc service\n     * @name $animate\n     * @description The $animate service provides rudimentary DOM manipulation functions to\n     * insert, remove and move elements within the DOM, as well as adding and removing classes.\n     * This service is the core service used by the ngAnimate $animator service which provides\n     * high-level animation hooks for CSS and JavaScript.\n     *\n     * $animate is available in the AngularJS core, however, the ngAnimate module must be included\n     * to enable full out animation support. Otherwise, $animate will only perform simple DOM\n     * manipulation operations.\n     *\n     * To learn more about enabling animation support, click here to visit the {@link ngAnimate\n     * ngAnimate module page} as well as the {@link ngAnimate.$animate ngAnimate $animate service\n     * page}.\n     */\n    return {\n      animate: function(element, from, to) {\n        applyStyles(element, { from: from, to: to });\n        return asyncPromise();\n      },\n\n      /**\n       *\n       * @ngdoc method\n       * @name $animate#enter\n       * @kind function\n       * @description Inserts the element into the DOM either after the `after` element or\n       * as the first child within the `parent` element. When the function is called a promise\n       * is returned that will be resolved at a later time.\n       * @param {DOMElement} element the element which will be inserted into the DOM\n       * @param {DOMElement} parent the parent element which will append the element as\n       *   a child (if the after element is not present)\n       * @param {DOMElement} after the sibling element which will append the element\n       *   after itself\n       * @param {object=} options an optional collection of styles that will be applied to the element.\n       * @return {Promise} the animation callback promise\n       */\n      enter: function(element, parent, after, options) {\n        applyStyles(element, options);\n        after ? after.after(element)\n              : parent.prepend(element);\n        return asyncPromise();\n      },\n\n      /**\n       *\n       * @ngdoc method\n       * @name $animate#leave\n       * @kind function\n       * @description Removes the element from the DOM. When the function is called a promise\n       * is returned that will be resolved at a later time.\n       * @param {DOMElement} element the element which will be removed from the DOM\n       * @param {object=} options an optional collection of options that will be applied to the element.\n       * @return {Promise} the animation callback promise\n       */\n      leave: function(element, options) {\n        element.remove();\n        return asyncPromise();\n      },\n\n      /**\n       *\n       * @ngdoc method\n       * @name $animate#move\n       * @kind function\n       * @description Moves the position of the provided element within the DOM to be placed\n       * either after the `after` element or inside of the `parent` element. When the function\n       * is called a promise is returned that will be resolved at a later time.\n       *\n       * @param {DOMElement} element the element which will be moved around within the\n       *   DOM\n       * @param {DOMElement} parent the parent element where the element will be\n       *   inserted into (if the after element is not present)\n       * @param {DOMElement} after the sibling element where the element will be\n       *   positioned next to\n       * @param {object=} options an optional collection of options that will be applied to the element.\n       * @return {Promise} the animation callback promise\n       */\n      move: function(element, parent, after, options) {\n        // Do not remove element before insert. Removing will cause data associated with the\n        // element to be dropped. Insert will implicitly do the remove.\n        return this.enter(element, parent, after, options);\n      },\n\n      /**\n       *\n       * @ngdoc method\n       * @name $animate#addClass\n       * @kind function\n       * @description Adds the provided className CSS class value to the provided element.\n       * When the function is called a promise is returned that will be resolved at a later time.\n       * @param {DOMElement} element the element which will have the className value\n       *   added to it\n       * @param {string} className the CSS class which will be added to the element\n       * @param {object=} options an optional collection of options that will be applied to the element.\n       * @return {Promise} the animation callback promise\n       */\n      addClass: function(element, className, options) {\n        return this.setClass(element, className, [], options);\n      },\n\n      $$addClassImmediately: function(element, className, options) {\n        element = jqLite(element);\n        className = !isString(className)\n                        ? (isArray(className) ? className.join(' ') : '')\n                        : className;\n        forEach(element, function(element) {\n          jqLiteAddClass(element, className);\n        });\n        applyStyles(element, options);\n        return asyncPromise();\n      },\n\n      /**\n       *\n       * @ngdoc method\n       * @name $animate#removeClass\n       * @kind function\n       * @description Removes the provided className CSS class value from the provided element.\n       * When the function is called a promise is returned that will be resolved at a later time.\n       * @param {DOMElement} element the element which will have the className value\n       *   removed from it\n       * @param {string} className the CSS class which will be removed from the element\n       * @param {object=} options an optional collection of options that will be applied to the element.\n       * @return {Promise} the animation callback promise\n       */\n      removeClass: function(element, className, options) {\n        return this.setClass(element, [], className, options);\n      },\n\n      $$removeClassImmediately: function(element, className, options) {\n        element = jqLite(element);\n        className = !isString(className)\n                        ? (isArray(className) ? className.join(' ') : '')\n                        : className;\n        forEach(element, function(element) {\n          jqLiteRemoveClass(element, className);\n        });\n        applyStyles(element, options);\n        return asyncPromise();\n      },\n\n      /**\n       *\n       * @ngdoc method\n       * @name $animate#setClass\n       * @kind function\n       * @description Adds and/or removes the given CSS classes to and from the element.\n       * When the function is called a promise is returned that will be resolved at a later time.\n       * @param {DOMElement} element the element which will have its CSS classes changed\n       *   removed from it\n       * @param {string} add the CSS classes which will be added to the element\n       * @param {string} remove the CSS class which will be removed from the element\n       * @param {object=} options an optional collection of options that will be applied to the element.\n       * @return {Promise} the animation callback promise\n       */\n      setClass: function(element, add, remove, options) {\n        var self = this;\n        var STORAGE_KEY = '$$animateClasses';\n        var createdCache = false;\n        element = jqLite(element);\n\n        var cache = element.data(STORAGE_KEY);\n        if (!cache) {\n          cache = {\n            classes: {},\n            options: options\n          };\n          createdCache = true;\n        } else if (options && cache.options) {\n          cache.options = angular.extend(cache.options || {}, options);\n        }\n\n        var classes = cache.classes;\n\n        add = isArray(add) ? add : add.split(' ');\n        remove = isArray(remove) ? remove : remove.split(' ');\n        cachedClassManipulation(classes, add, true);\n        cachedClassManipulation(classes, remove, false);\n\n        if (createdCache) {\n          cache.promise = runAnimationPostDigest(function(done) {\n            var cache = element.data(STORAGE_KEY);\n            element.removeData(STORAGE_KEY);\n\n            // in the event that the element is removed before postDigest\n            // is run then the cache will be undefined and there will be\n            // no need anymore to add or remove and of the element classes\n            if (cache) {\n              var classes = resolveElementClasses(element, cache.classes);\n              if (classes) {\n                self.$$setClassImmediately(element, classes[0], classes[1], cache.options);\n              }\n            }\n\n            done();\n          });\n          element.data(STORAGE_KEY, cache);\n        }\n\n        return cache.promise;\n      },\n\n      $$setClassImmediately: function(element, add, remove, options) {\n        add && this.$$addClassImmediately(element, add);\n        remove && this.$$removeClassImmediately(element, remove);\n        applyStyles(element, options);\n        return asyncPromise();\n      },\n\n      enabled: noop,\n      cancel: noop\n    };\n  }];\n}];\n\nfunction $$AsyncCallbackProvider() {\n  this.$get = ['$$rAF', '$timeout', function($$rAF, $timeout) {\n    return $$rAF.supported\n      ? function(fn) { return $$rAF(fn); }\n      : function(fn) {\n        return $timeout(fn, 0, false);\n      };\n  }];\n}\n\n/* global stripHash: true */\n\n/**\n * ! This is a private undocumented service !\n *\n * @name $browser\n * @requires $log\n * @description\n * This object has two goals:\n *\n * - hide all the global state in the browser caused by the window object\n * - abstract away all the browser specific features and inconsistencies\n *\n * For tests we provide {@link ngMock.$browser mock implementation} of the `$browser`\n * service, which can be used for convenient testing of the application without the interaction with\n * the real browser apis.\n */\n/**\n * @param {object} window The global window object.\n * @param {object} document jQuery wrapped document.\n * @param {object} $log window.console or an object with the same interface.\n * @param {object} $sniffer $sniffer service\n */\nfunction Browser(window, document, $log, $sniffer) {\n  var self = this,\n      rawDocument = document[0],\n      location = window.location,\n      history = window.history,\n      setTimeout = window.setTimeout,\n      clearTimeout = window.clearTimeout,\n      pendingDeferIds = {};\n\n  self.isMock = false;\n\n  var outstandingRequestCount = 0;\n  var outstandingRequestCallbacks = [];\n\n  // TODO(vojta): remove this temporary api\n  self.$$completeOutstandingRequest = completeOutstandingRequest;\n  self.$$incOutstandingRequestCount = function() { outstandingRequestCount++; };\n\n  /**\n   * Executes the `fn` function(supports currying) and decrements the `outstandingRequestCallbacks`\n   * counter. If the counter reaches 0, all the `outstandingRequestCallbacks` are executed.\n   */\n  function completeOutstandingRequest(fn) {\n    try {\n      fn.apply(null, sliceArgs(arguments, 1));\n    } finally {\n      outstandingRequestCount--;\n      if (outstandingRequestCount === 0) {\n        while (outstandingRequestCallbacks.length) {\n          try {\n            outstandingRequestCallbacks.pop()();\n          } catch (e) {\n            $log.error(e);\n          }\n        }\n      }\n    }\n  }\n\n  function getHash(url) {\n    var index = url.indexOf('#');\n    return index === -1 ? '' : url.substr(index + 1);\n  }\n\n  /**\n   * @private\n   * Note: this method is used only by scenario runner\n   * TODO(vojta): prefix this method with $$ ?\n   * @param {function()} callback Function that will be called when no outstanding request\n   */\n  self.notifyWhenNoOutstandingRequests = function(callback) {\n    // force browser to execute all pollFns - this is needed so that cookies and other pollers fire\n    // at some deterministic time in respect to the test runner's actions. Leaving things up to the\n    // regular poller would result in flaky tests.\n    forEach(pollFns, function(pollFn) { pollFn(); });\n\n    if (outstandingRequestCount === 0) {\n      callback();\n    } else {\n      outstandingRequestCallbacks.push(callback);\n    }\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Poll Watcher API\n  //////////////////////////////////////////////////////////////\n  var pollFns = [],\n      pollTimeout;\n\n  /**\n   * @name $browser#addPollFn\n   *\n   * @param {function()} fn Poll function to add\n   *\n   * @description\n   * Adds a function to the list of functions that poller periodically executes,\n   * and starts polling if not started yet.\n   *\n   * @returns {function()} the added function\n   */\n  self.addPollFn = function(fn) {\n    if (isUndefined(pollTimeout)) startPoller(100, setTimeout);\n    pollFns.push(fn);\n    return fn;\n  };\n\n  /**\n   * @param {number} interval How often should browser call poll functions (ms)\n   * @param {function()} setTimeout Reference to a real or fake `setTimeout` function.\n   *\n   * @description\n   * Configures the poller to run in the specified intervals, using the specified\n   * setTimeout fn and kicks it off.\n   */\n  function startPoller(interval, setTimeout) {\n    (function check() {\n      forEach(pollFns, function(pollFn) { pollFn(); });\n      pollTimeout = setTimeout(check, interval);\n    })();\n  }\n\n  //////////////////////////////////////////////////////////////\n  // URL API\n  //////////////////////////////////////////////////////////////\n\n  var cachedState, lastHistoryState,\n      lastBrowserUrl = location.href,\n      baseElement = document.find('base'),\n      reloadLocation = null;\n\n  cacheState();\n  lastHistoryState = cachedState;\n\n  /**\n   * @name $browser#url\n   *\n   * @description\n   * GETTER:\n   * Without any argument, this method just returns current value of location.href.\n   *\n   * SETTER:\n   * With at least one argument, this method sets url to new value.\n   * If html5 history api supported, pushState/replaceState is used, otherwise\n   * location.href/location.replace is used.\n   * Returns its own instance to allow chaining\n   *\n   * NOTE: this api is intended for use only by the $location service. Please use the\n   * {@link ng.$location $location service} to change url.\n   *\n   * @param {string} url New url (when used as setter)\n   * @param {boolean=} replace Should new url replace current history record?\n   * @param {object=} state object to use with pushState/replaceState\n   */\n  self.url = function(url, replace, state) {\n    // In modern browsers `history.state` is `null` by default; treating it separately\n    // from `undefined` would cause `$browser.url('/foo')` to change `history.state`\n    // to undefined via `pushState`. Instead, let's change `undefined` to `null` here.\n    if (isUndefined(state)) {\n      state = null;\n    }\n\n    // Android Browser BFCache causes location, history reference to become stale.\n    if (location !== window.location) location = window.location;\n    if (history !== window.history) history = window.history;\n\n    // setter\n    if (url) {\n      var sameState = lastHistoryState === state;\n\n      // Don't change anything if previous and current URLs and states match. This also prevents\n      // IE<10 from getting into redirect loop when in LocationHashbangInHtml5Url mode.\n      // See https://github.com/angular/angular.js/commit/ffb2701\n      if (lastBrowserUrl === url && (!$sniffer.history || sameState)) {\n        return self;\n      }\n      var sameBase = lastBrowserUrl && stripHash(lastBrowserUrl) === stripHash(url);\n      lastBrowserUrl = url;\n      lastHistoryState = state;\n      // Don't use history API if only the hash changed\n      // due to a bug in IE10/IE11 which leads\n      // to not firing a `hashchange` nor `popstate` event\n      // in some cases (see #9143).\n      if ($sniffer.history && (!sameBase || !sameState)) {\n        history[replace ? 'replaceState' : 'pushState'](state, '', url);\n        cacheState();\n        // Do the assignment again so that those two variables are referentially identical.\n        lastHistoryState = cachedState;\n      } else {\n        if (!sameBase) {\n          reloadLocation = url;\n        }\n        if (replace) {\n          location.replace(url);\n        } else if (!sameBase) {\n          location.href = url;\n        } else {\n          location.hash = getHash(url);\n        }\n      }\n      return self;\n    // getter\n    } else {\n      // - reloadLocation is needed as browsers don't allow to read out\n      //   the new location.href if a reload happened.\n      // - the replacement is a workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=407172\n      return reloadLocation || location.href.replace(/%27/g,\"'\");\n    }\n  };\n\n  /**\n   * @name $browser#state\n   *\n   * @description\n   * This method is a getter.\n   *\n   * Return history.state or null if history.state is undefined.\n   *\n   * @returns {object} state\n   */\n  self.state = function() {\n    return cachedState;\n  };\n\n  var urlChangeListeners = [],\n      urlChangeInit = false;\n\n  function cacheStateAndFireUrlChange() {\n    cacheState();\n    fireUrlChange();\n  }\n\n  // This variable should be used *only* inside the cacheState function.\n  var lastCachedState = null;\n  function cacheState() {\n    // This should be the only place in $browser where `history.state` is read.\n    cachedState = window.history.state;\n    cachedState = isUndefined(cachedState) ? null : cachedState;\n\n    // Prevent callbacks fo fire twice if both hashchange & popstate were fired.\n    if (equals(cachedState, lastCachedState)) {\n      cachedState = lastCachedState;\n    }\n    lastCachedState = cachedState;\n  }\n\n  function fireUrlChange() {\n    if (lastBrowserUrl === self.url() && lastHistoryState === cachedState) {\n      return;\n    }\n\n    lastBrowserUrl = self.url();\n    lastHistoryState = cachedState;\n    forEach(urlChangeListeners, function(listener) {\n      listener(self.url(), cachedState);\n    });\n  }\n\n  /**\n   * @name $browser#onUrlChange\n   *\n   * @description\n   * Register callback function that will be called, when url changes.\n   *\n   * It's only called when the url is changed from outside of angular:\n   * - user types different url into address bar\n   * - user clicks on history (forward/back) button\n   * - user clicks on a link\n   *\n   * It's not called when url is changed by $browser.url() method\n   *\n   * The listener gets called with new url as parameter.\n   *\n   * NOTE: this api is intended for use only by the $location service. Please use the\n   * {@link ng.$location $location service} to monitor url changes in angular apps.\n   *\n   * @param {function(string)} listener Listener function to be called when url changes.\n   * @return {function(string)} Returns the registered listener fn - handy if the fn is anonymous.\n   */\n  self.onUrlChange = function(callback) {\n    // TODO(vojta): refactor to use node's syntax for events\n    if (!urlChangeInit) {\n      // We listen on both (hashchange/popstate) when available, as some browsers (e.g. Opera)\n      // don't fire popstate when user change the address bar and don't fire hashchange when url\n      // changed by push/replaceState\n\n      // html5 history api - popstate event\n      if ($sniffer.history) jqLite(window).on('popstate', cacheStateAndFireUrlChange);\n      // hashchange event\n      jqLite(window).on('hashchange', cacheStateAndFireUrlChange);\n\n      urlChangeInit = true;\n    }\n\n    urlChangeListeners.push(callback);\n    return callback;\n  };\n\n  /**\n   * Checks whether the url has changed outside of Angular.\n   * Needs to be exported to be able to check for changes that have been done in sync,\n   * as hashchange/popstate events fire in async.\n   */\n  self.$$checkUrlChange = fireUrlChange;\n\n  //////////////////////////////////////////////////////////////\n  // Misc API\n  //////////////////////////////////////////////////////////////\n\n  /**\n   * @name $browser#baseHref\n   *\n   * @description\n   * Returns current <base href>\n   * (always relative - without domain)\n   *\n   * @returns {string} The current base href\n   */\n  self.baseHref = function() {\n    var href = baseElement.attr('href');\n    return href ? href.replace(/^(https?\\:)?\\/\\/[^\\/]*/, '') : '';\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Cookies API\n  //////////////////////////////////////////////////////////////\n  var lastCookies = {};\n  var lastCookieString = '';\n  var cookiePath = self.baseHref();\n\n  function safeDecodeURIComponent(str) {\n    try {\n      return decodeURIComponent(str);\n    } catch (e) {\n      return str;\n    }\n  }\n\n  /**\n   * @name $browser#cookies\n   *\n   * @param {string=} name Cookie name\n   * @param {string=} value Cookie value\n   *\n   * @description\n   * The cookies method provides a 'private' low level access to browser cookies.\n   * It is not meant to be used directly, use the $cookie service instead.\n   *\n   * The return values vary depending on the arguments that the method was called with as follows:\n   *\n   * - cookies() -> hash of all cookies, this is NOT a copy of the internal state, so do not modify\n   *   it\n   * - cookies(name, value) -> set name to value, if value is undefined delete the cookie\n   * - cookies(name) -> the same as (name, undefined) == DELETES (no one calls it right now that\n   *   way)\n   *\n   * @returns {Object} Hash of all cookies (if called without any parameter)\n   */\n  self.cookies = function(name, value) {\n    var cookieLength, cookieArray, cookie, i, index;\n\n    if (name) {\n      if (value === undefined) {\n        rawDocument.cookie = encodeURIComponent(name) + \"=;path=\" + cookiePath +\n                                \";expires=Thu, 01 Jan 1970 00:00:00 GMT\";\n      } else {\n        if (isString(value)) {\n          cookieLength = (rawDocument.cookie = encodeURIComponent(name) + '=' + encodeURIComponent(value) +\n                                ';path=' + cookiePath).length + 1;\n\n          // per http://www.ietf.org/rfc/rfc2109.txt browser must allow at minimum:\n          // - 300 cookies\n          // - 20 cookies per unique domain\n          // - 4096 bytes per cookie\n          if (cookieLength > 4096) {\n            $log.warn(\"Cookie '\" + name +\n              \"' possibly not set or overflowed because it was too large (\" +\n              cookieLength + \" > 4096 bytes)!\");\n          }\n        }\n      }\n    } else {\n      if (rawDocument.cookie !== lastCookieString) {\n        lastCookieString = rawDocument.cookie;\n        cookieArray = lastCookieString.split(\"; \");\n        lastCookies = {};\n\n        for (i = 0; i < cookieArray.length; i++) {\n          cookie = cookieArray[i];\n          index = cookie.indexOf('=');\n          if (index > 0) { //ignore nameless cookies\n            name = safeDecodeURIComponent(cookie.substring(0, index));\n            // the first value that is seen for a cookie is the most\n            // specific one.  values for the same cookie name that\n            // follow are for less specific paths.\n            if (lastCookies[name] === undefined) {\n              lastCookies[name] = safeDecodeURIComponent(cookie.substring(index + 1));\n            }\n          }\n        }\n      }\n      return lastCookies;\n    }\n  };\n\n\n  /**\n   * @name $browser#defer\n   * @param {function()} fn A function, who's execution should be deferred.\n   * @param {number=} [delay=0] of milliseconds to defer the function execution.\n   * @returns {*} DeferId that can be used to cancel the task via `$browser.defer.cancel()`.\n   *\n   * @description\n   * Executes a fn asynchronously via `setTimeout(fn, delay)`.\n   *\n   * Unlike when calling `setTimeout` directly, in test this function is mocked and instead of using\n   * `setTimeout` in tests, the fns are queued in an array, which can be programmatically flushed\n   * via `$browser.defer.flush()`.\n   *\n   */\n  self.defer = function(fn, delay) {\n    var timeoutId;\n    outstandingRequestCount++;\n    timeoutId = setTimeout(function() {\n      delete pendingDeferIds[timeoutId];\n      completeOutstandingRequest(fn);\n    }, delay || 0);\n    pendingDeferIds[timeoutId] = true;\n    return timeoutId;\n  };\n\n\n  /**\n   * @name $browser#defer.cancel\n   *\n   * @description\n   * Cancels a deferred task identified with `deferId`.\n   *\n   * @param {*} deferId Token returned by the `$browser.defer` function.\n   * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfully\n   *                    canceled.\n   */\n  self.defer.cancel = function(deferId) {\n    if (pendingDeferIds[deferId]) {\n      delete pendingDeferIds[deferId];\n      clearTimeout(deferId);\n      completeOutstandingRequest(noop);\n      return true;\n    }\n    return false;\n  };\n\n}\n\nfunction $BrowserProvider() {\n  this.$get = ['$window', '$log', '$sniffer', '$document',\n      function($window, $log, $sniffer, $document) {\n        return new Browser($window, $document, $log, $sniffer);\n      }];\n}\n\n/**\n * @ngdoc service\n * @name $cacheFactory\n *\n * @description\n * Factory that constructs {@link $cacheFactory.Cache Cache} objects and gives access to\n * them.\n *\n * ```js\n *\n *  var cache = $cacheFactory('cacheId');\n *  expect($cacheFactory.get('cacheId')).toBe(cache);\n *  expect($cacheFactory.get('noSuchCacheId')).not.toBeDefined();\n *\n *  cache.put(\"key\", \"value\");\n *  cache.put(\"another key\", \"another value\");\n *\n *  // We've specified no options on creation\n *  expect(cache.info()).toEqual({id: 'cacheId', size: 2});\n *\n * ```\n *\n *\n * @param {string} cacheId Name or id of the newly created cache.\n * @param {object=} options Options object that specifies the cache behavior. Properties:\n *\n *   - `{number=}` `capacity` — turns the cache into LRU cache.\n *\n * @returns {object} Newly created cache object with the following set of methods:\n *\n * - `{object}` `info()` — Returns id, size, and options of cache.\n * - `{{*}}` `put({string} key, {*} value)` — Puts a new key-value pair into the cache and returns\n *   it.\n * - `{{*}}` `get({string} key)` — Returns cached value for `key` or undefined for cache miss.\n * - `{void}` `remove({string} key)` — Removes a key-value pair from the cache.\n * - `{void}` `removeAll()` — Removes all cached values.\n * - `{void}` `destroy()` — Removes references to this cache from $cacheFactory.\n *\n * @example\n   <example module=\"cacheExampleApp\">\n     <file name=\"index.html\">\n       <div ng-controller=\"CacheController\">\n         <input ng-model=\"newCacheKey\" placeholder=\"Key\">\n         <input ng-model=\"newCacheValue\" placeholder=\"Value\">\n         <button ng-click=\"put(newCacheKey, newCacheValue)\">Cache</button>\n\n         <p ng-if=\"keys.length\">Cached Values</p>\n         <div ng-repeat=\"key in keys\">\n           <span ng-bind=\"key\"></span>\n           <span>: </span>\n           <b ng-bind=\"cache.get(key)\"></b>\n         </div>\n\n         <p>Cache Info</p>\n         <div ng-repeat=\"(key, value) in cache.info()\">\n           <span ng-bind=\"key\"></span>\n           <span>: </span>\n           <b ng-bind=\"value\"></b>\n         </div>\n       </div>\n     </file>\n     <file name=\"script.js\">\n       angular.module('cacheExampleApp', []).\n         controller('CacheController', ['$scope', '$cacheFactory', function($scope, $cacheFactory) {\n           $scope.keys = [];\n           $scope.cache = $cacheFactory('cacheId');\n           $scope.put = function(key, value) {\n             if ($scope.cache.get(key) === undefined) {\n               $scope.keys.push(key);\n             }\n             $scope.cache.put(key, value === undefined ? null : value);\n           };\n         }]);\n     </file>\n     <file name=\"style.css\">\n       p {\n         margin: 10px 0 3px;\n       }\n     </file>\n   </example>\n */\nfunction $CacheFactoryProvider() {\n\n  this.$get = function() {\n    var caches = {};\n\n    function cacheFactory(cacheId, options) {\n      if (cacheId in caches) {\n        throw minErr('$cacheFactory')('iid', \"CacheId '{0}' is already taken!\", cacheId);\n      }\n\n      var size = 0,\n          stats = extend({}, options, {id: cacheId}),\n          data = {},\n          capacity = (options && options.capacity) || Number.MAX_VALUE,\n          lruHash = {},\n          freshEnd = null,\n          staleEnd = null;\n\n      /**\n       * @ngdoc type\n       * @name $cacheFactory.Cache\n       *\n       * @description\n       * A cache object used to store and retrieve data, primarily used by\n       * {@link $http $http} and the {@link ng.directive:script script} directive to cache\n       * templates and other data.\n       *\n       * ```js\n       *  angular.module('superCache')\n       *    .factory('superCache', ['$cacheFactory', function($cacheFactory) {\n       *      return $cacheFactory('super-cache');\n       *    }]);\n       * ```\n       *\n       * Example test:\n       *\n       * ```js\n       *  it('should behave like a cache', inject(function(superCache) {\n       *    superCache.put('key', 'value');\n       *    superCache.put('another key', 'another value');\n       *\n       *    expect(superCache.info()).toEqual({\n       *      id: 'super-cache',\n       *      size: 2\n       *    });\n       *\n       *    superCache.remove('another key');\n       *    expect(superCache.get('another key')).toBeUndefined();\n       *\n       *    superCache.removeAll();\n       *    expect(superCache.info()).toEqual({\n       *      id: 'super-cache',\n       *      size: 0\n       *    });\n       *  }));\n       * ```\n       */\n      return caches[cacheId] = {\n\n        /**\n         * @ngdoc method\n         * @name $cacheFactory.Cache#put\n         * @kind function\n         *\n         * @description\n         * Inserts a named entry into the {@link $cacheFactory.Cache Cache} object to be\n         * retrieved later, and incrementing the size of the cache if the key was not already\n         * present in the cache. If behaving like an LRU cache, it will also remove stale\n         * entries from the set.\n         *\n         * It will not insert undefined values into the cache.\n         *\n         * @param {string} key the key under which the cached data is stored.\n         * @param {*} value the value to store alongside the key. If it is undefined, the key\n         *    will not be stored.\n         * @returns {*} the value stored.\n         */\n        put: function(key, value) {\n          if (capacity < Number.MAX_VALUE) {\n            var lruEntry = lruHash[key] || (lruHash[key] = {key: key});\n\n            refresh(lruEntry);\n          }\n\n          if (isUndefined(value)) return;\n          if (!(key in data)) size++;\n          data[key] = value;\n\n          if (size > capacity) {\n            this.remove(staleEnd.key);\n          }\n\n          return value;\n        },\n\n        /**\n         * @ngdoc method\n         * @name $cacheFactory.Cache#get\n         * @kind function\n         *\n         * @description\n         * Retrieves named data stored in the {@link $cacheFactory.Cache Cache} object.\n         *\n         * @param {string} key the key of the data to be retrieved\n         * @returns {*} the value stored.\n         */\n        get: function(key) {\n          if (capacity < Number.MAX_VALUE) {\n            var lruEntry = lruHash[key];\n\n            if (!lruEntry) return;\n\n            refresh(lruEntry);\n          }\n\n          return data[key];\n        },\n\n\n        /**\n         * @ngdoc method\n         * @name $cacheFactory.Cache#remove\n         * @kind function\n         *\n         * @description\n         * Removes an entry from the {@link $cacheFactory.Cache Cache} object.\n         *\n         * @param {string} key the key of the entry to be removed\n         */\n        remove: function(key) {\n          if (capacity < Number.MAX_VALUE) {\n            var lruEntry = lruHash[key];\n\n            if (!lruEntry) return;\n\n            if (lruEntry == freshEnd) freshEnd = lruEntry.p;\n            if (lruEntry == staleEnd) staleEnd = lruEntry.n;\n            link(lruEntry.n,lruEntry.p);\n\n            delete lruHash[key];\n          }\n\n          delete data[key];\n          size--;\n        },\n\n\n        /**\n         * @ngdoc method\n         * @name $cacheFactory.Cache#removeAll\n         * @kind function\n         *\n         * @description\n         * Clears the cache object of any entries.\n         */\n        removeAll: function() {\n          data = {};\n          size = 0;\n          lruHash = {};\n          freshEnd = staleEnd = null;\n        },\n\n\n        /**\n         * @ngdoc method\n         * @name $cacheFactory.Cache#destroy\n         * @kind function\n         *\n         * @description\n         * Destroys the {@link $cacheFactory.Cache Cache} object entirely,\n         * removing it from the {@link $cacheFactory $cacheFactory} set.\n         */\n        destroy: function() {\n          data = null;\n          stats = null;\n          lruHash = null;\n          delete caches[cacheId];\n        },\n\n\n        /**\n         * @ngdoc method\n         * @name $cacheFactory.Cache#info\n         * @kind function\n         *\n         * @description\n         * Retrieve information regarding a particular {@link $cacheFactory.Cache Cache}.\n         *\n         * @returns {object} an object with the following properties:\n         *   <ul>\n         *     <li>**id**: the id of the cache instance</li>\n         *     <li>**size**: the number of entries kept in the cache instance</li>\n         *     <li>**...**: any additional properties from the options object when creating the\n         *       cache.</li>\n         *   </ul>\n         */\n        info: function() {\n          return extend({}, stats, {size: size});\n        }\n      };\n\n\n      /**\n       * makes the `entry` the freshEnd of the LRU linked list\n       */\n      function refresh(entry) {\n        if (entry != freshEnd) {\n          if (!staleEnd) {\n            staleEnd = entry;\n          } else if (staleEnd == entry) {\n            staleEnd = entry.n;\n          }\n\n          link(entry.n, entry.p);\n          link(entry, freshEnd);\n          freshEnd = entry;\n          freshEnd.n = null;\n        }\n      }\n\n\n      /**\n       * bidirectionally links two entries of the LRU linked list\n       */\n      function link(nextEntry, prevEntry) {\n        if (nextEntry != prevEntry) {\n          if (nextEntry) nextEntry.p = prevEntry; //p stands for previous, 'prev' didn't minify\n          if (prevEntry) prevEntry.n = nextEntry; //n stands for next, 'next' didn't minify\n        }\n      }\n    }\n\n\n  /**\n   * @ngdoc method\n   * @name $cacheFactory#info\n   *\n   * @description\n   * Get information about all the caches that have been created\n   *\n   * @returns {Object} - key-value map of `cacheId` to the result of calling `cache#info`\n   */\n    cacheFactory.info = function() {\n      var info = {};\n      forEach(caches, function(cache, cacheId) {\n        info[cacheId] = cache.info();\n      });\n      return info;\n    };\n\n\n  /**\n   * @ngdoc method\n   * @name $cacheFactory#get\n   *\n   * @description\n   * Get access to a cache object by the `cacheId` used when it was created.\n   *\n   * @param {string} cacheId Name or id of a cache to access.\n   * @returns {object} Cache object identified by the cacheId or undefined if no such cache.\n   */\n    cacheFactory.get = function(cacheId) {\n      return caches[cacheId];\n    };\n\n\n    return cacheFactory;\n  };\n}\n\n/**\n * @ngdoc service\n * @name $templateCache\n *\n * @description\n * The first time a template is used, it is loaded in the template cache for quick retrieval. You\n * can load templates directly into the cache in a `script` tag, or by consuming the\n * `$templateCache` service directly.\n *\n * Adding via the `script` tag:\n *\n * ```html\n *   <script type=\"text/ng-template\" id=\"templateId.html\">\n *     <p>This is the content of the template</p>\n *   </script>\n * ```\n *\n * **Note:** the `script` tag containing the template does not need to be included in the `head` of\n * the document, but it must be a descendent of the {@link ng.$rootElement $rootElement} (IE,\n * element with ng-app attribute), otherwise the template will be ignored.\n *\n * Adding via the $templateCache service:\n *\n * ```js\n * var myApp = angular.module('myApp', []);\n * myApp.run(function($templateCache) {\n *   $templateCache.put('templateId.html', 'This is the content of the template');\n * });\n * ```\n *\n * To retrieve the template later, simply use it in your HTML:\n * ```html\n * <div ng-include=\" 'templateId.html' \"></div>\n * ```\n *\n * or get it via Javascript:\n * ```js\n * $templateCache.get('templateId.html')\n * ```\n *\n * See {@link ng.$cacheFactory $cacheFactory}.\n *\n */\nfunction $TemplateCacheProvider() {\n  this.$get = ['$cacheFactory', function($cacheFactory) {\n    return $cacheFactory('templates');\n  }];\n}\n\n/* ! VARIABLE/FUNCTION NAMING CONVENTIONS THAT APPLY TO THIS FILE!\n *\n * DOM-related variables:\n *\n * - \"node\" - DOM Node\n * - \"element\" - DOM Element or Node\n * - \"$node\" or \"$element\" - jqLite-wrapped node or element\n *\n *\n * Compiler related stuff:\n *\n * - \"linkFn\" - linking fn of a single directive\n * - \"nodeLinkFn\" - function that aggregates all linking fns for a particular node\n * - \"childLinkFn\" -  function that aggregates all linking fns for child nodes of a particular node\n * - \"compositeLinkFn\" - function that aggregates all linking fns for a compilation root (nodeList)\n */\n\n\n/**\n * @ngdoc service\n * @name $compile\n * @kind function\n *\n * @description\n * Compiles an HTML string or DOM into a template and produces a template function, which\n * can then be used to link {@link ng.$rootScope.Scope `scope`} and the template together.\n *\n * The compilation is a process of walking the DOM tree and matching DOM elements to\n * {@link ng.$compileProvider#directive directives}.\n *\n * <div class=\"alert alert-warning\">\n * **Note:** This document is an in-depth reference of all directive options.\n * For a gentle introduction to directives with examples of common use cases,\n * see the {@link guide/directive directive guide}.\n * </div>\n *\n * ## Comprehensive Directive API\n *\n * There are many different options for a directive.\n *\n * The difference resides in the return value of the factory function.\n * You can either return a \"Directive Definition Object\" (see below) that defines the directive properties,\n * or just the `postLink` function (all other properties will have the default values).\n *\n * <div class=\"alert alert-success\">\n * **Best Practice:** It's recommended to use the \"directive definition object\" form.\n * </div>\n *\n * Here's an example directive declared with a Directive Definition Object:\n *\n * ```js\n *   var myModule = angular.module(...);\n *\n *   myModule.directive('directiveName', function factory(injectables) {\n *     var directiveDefinitionObject = {\n *       priority: 0,\n *       template: '<div></div>', // or // function(tElement, tAttrs) { ... },\n *       // or\n *       // templateUrl: 'directive.html', // or // function(tElement, tAttrs) { ... },\n *       transclude: false,\n *       restrict: 'A',\n *       templateNamespace: 'html',\n *       scope: false,\n *       controller: function($scope, $element, $attrs, $transclude, otherInjectables) { ... },\n *       controllerAs: 'stringAlias',\n *       require: 'siblingDirectiveName', // or // ['^parentDirectiveName', '?optionalDirectiveName', '?^optionalParent'],\n *       compile: function compile(tElement, tAttrs, transclude) {\n *         return {\n *           pre: function preLink(scope, iElement, iAttrs, controller) { ... },\n *           post: function postLink(scope, iElement, iAttrs, controller) { ... }\n *         }\n *         // or\n *         // return function postLink( ... ) { ... }\n *       },\n *       // or\n *       // link: {\n *       //  pre: function preLink(scope, iElement, iAttrs, controller) { ... },\n *       //  post: function postLink(scope, iElement, iAttrs, controller) { ... }\n *       // }\n *       // or\n *       // link: function postLink( ... ) { ... }\n *     };\n *     return directiveDefinitionObject;\n *   });\n * ```\n *\n * <div class=\"alert alert-warning\">\n * **Note:** Any unspecified options will use the default value. You can see the default values below.\n * </div>\n *\n * Therefore the above can be simplified as:\n *\n * ```js\n *   var myModule = angular.module(...);\n *\n *   myModule.directive('directiveName', function factory(injectables) {\n *     var directiveDefinitionObject = {\n *       link: function postLink(scope, iElement, iAttrs) { ... }\n *     };\n *     return directiveDefinitionObject;\n *     // or\n *     // return function postLink(scope, iElement, iAttrs) { ... }\n *   });\n * ```\n *\n *\n *\n * ### Directive Definition Object\n *\n * The directive definition object provides instructions to the {@link ng.$compile\n * compiler}. The attributes are:\n *\n * #### `multiElement`\n * When this property is set to true, the HTML compiler will collect DOM nodes between\n * nodes with the attributes `directive-name-start` and `directive-name-end`, and group them\n * together as the directive elements. It is recommended that this feature be used on directives\n * which are not strictly behavioural (such as {@link ngClick}), and which\n * do not manipulate or replace child nodes (such as {@link ngInclude}).\n *\n * #### `priority`\n * When there are multiple directives defined on a single DOM element, sometimes it\n * is necessary to specify the order in which the directives are applied. The `priority` is used\n * to sort the directives before their `compile` functions get called. Priority is defined as a\n * number. Directives with greater numerical `priority` are compiled first. Pre-link functions\n * are also run in priority order, but post-link functions are run in reverse order. The order\n * of directives with the same priority is undefined. The default priority is `0`.\n *\n * #### `terminal`\n * If set to true then the current `priority` will be the last set of directives\n * which will execute (any directives at the current priority will still execute\n * as the order of execution on same `priority` is undefined). Note that expressions\n * and other directives used in the directive's template will also be excluded from execution.\n *\n * #### `scope`\n * **If set to `true`,** then a new scope will be created for this directive. If multiple directives on the\n * same element request a new scope, only one new scope is created. The new scope rule does not\n * apply for the root of the template since the root of the template always gets a new scope.\n *\n * **If set to `{}` (object hash),** then a new \"isolate\" scope is created. The 'isolate' scope differs from\n * normal scope in that it does not prototypically inherit from the parent scope. This is useful\n * when creating reusable components, which should not accidentally read or modify data in the\n * parent scope.\n *\n * The 'isolate' scope takes an object hash which defines a set of local scope properties\n * derived from the parent scope. These local properties are useful for aliasing values for\n * templates. Locals definition is a hash of local scope property to its source:\n *\n * * `@` or `@attr` - bind a local scope property to the value of DOM attribute. The result is\n *   always a string since DOM attributes are strings. If no `attr` name is specified  then the\n *   attribute name is assumed to be the same as the local name.\n *   Given `<widget my-attr=\"hello {{name}}\">` and widget definition\n *   of `scope: { localName:'@myAttr' }`, then widget scope property `localName` will reflect\n *   the interpolated value of `hello {{name}}`. As the `name` attribute changes so will the\n *   `localName` property on the widget scope. The `name` is read from the parent scope (not\n *   component scope).\n *\n * * `=` or `=attr` - set up bi-directional binding between a local scope property and the\n *   parent scope property of name defined via the value of the `attr` attribute. If no `attr`\n *   name is specified then the attribute name is assumed to be the same as the local name.\n *   Given `<widget my-attr=\"parentModel\">` and widget definition of\n *   `scope: { localModel:'=myAttr' }`, then widget scope property `localModel` will reflect the\n *   value of `parentModel` on the parent scope. Any changes to `parentModel` will be reflected\n *   in `localModel` and any changes in `localModel` will reflect in `parentModel`. If the parent\n *   scope property doesn't exist, it will throw a NON_ASSIGNABLE_MODEL_EXPRESSION exception. You\n *   can avoid this behavior using `=?` or `=?attr` in order to flag the property as optional. If\n *   you want to shallow watch for changes (i.e. $watchCollection instead of $watch) you can use\n *   `=*` or `=*attr` (`=*?` or `=*?attr` if the property is optional).\n *\n * * `&` or `&attr` - provides a way to execute an expression in the context of the parent scope.\n *   If no `attr` name is specified then the attribute name is assumed to be the same as the\n *   local name. Given `<widget my-attr=\"count = count + value\">` and widget definition of\n *   `scope: { localFn:'&myAttr' }`, then isolate scope property `localFn` will point to\n *   a function wrapper for the `count = count + value` expression. Often it's desirable to\n *   pass data from the isolated scope via an expression to the parent scope, this can be\n *   done by passing a map of local variable names and values into the expression wrapper fn.\n *   For example, if the expression is `increment(amount)` then we can specify the amount value\n *   by calling the `localFn` as `localFn({amount: 22})`.\n *\n *\n * #### `bindToController`\n * When an isolate scope is used for a component (see above), and `controllerAs` is used, `bindToController: true` will\n * allow a component to have its properties bound to the controller, rather than to scope. When the controller\n * is instantiated, the initial values of the isolate scope bindings are already available.\n *\n * #### `controller`\n * Controller constructor function. The controller is instantiated before the\n * pre-linking phase and it is shared with other directives (see\n * `require` attribute). This allows the directives to communicate with each other and augment\n * each other's behavior. The controller is injectable (and supports bracket notation) with the following locals:\n *\n * * `$scope` - Current scope associated with the element\n * * `$element` - Current element\n * * `$attrs` - Current attributes object for the element\n * * `$transclude` - A transclude linking function pre-bound to the correct transclusion scope:\n *   `function([scope], cloneLinkingFn, futureParentElement)`.\n *    * `scope`: optional argument to override the scope.\n *    * `cloneLinkingFn`: optional argument to create clones of the original transcluded content.\n *    * `futureParentElement`:\n *        * defines the parent to which the `cloneLinkingFn` will add the cloned elements.\n *        * default: `$element.parent()` resp. `$element` for `transclude:'element'` resp. `transclude:true`.\n *        * only needed for transcludes that are allowed to contain non html elements (e.g. SVG elements)\n *          and when the `cloneLinkinFn` is passed,\n *          as those elements need to created and cloned in a special way when they are defined outside their\n *          usual containers (e.g. like `<svg>`).\n *        * See also the `directive.templateNamespace` property.\n *\n *\n * #### `require`\n * Require another directive and inject its controller as the fourth argument to the linking function. The\n * `require` takes a string name (or array of strings) of the directive(s) to pass in. If an array is used, the\n * injected argument will be an array in corresponding order. If no such directive can be\n * found, or if the directive does not have a controller, then an error is raised. The name can be prefixed with:\n *\n * * (no prefix) - Locate the required controller on the current element. Throw an error if not found.\n * * `?` - Attempt to locate the required controller or pass `null` to the `link` fn if not found.\n * * `^` - Locate the required controller by searching the element and its parents. Throw an error if not found.\n * * `^^` - Locate the required controller by searching the element's parents. Throw an error if not found.\n * * `?^` - Attempt to locate the required controller by searching the element and its parents or pass\n *   `null` to the `link` fn if not found.\n * * `?^^` - Attempt to locate the required controller by searching the element's parents, or pass\n *   `null` to the `link` fn if not found.\n *\n *\n * #### `controllerAs`\n * Controller alias at the directive scope. An alias for the controller so it\n * can be referenced at the directive template. The directive needs to define a scope for this\n * configuration to be used. Useful in the case when directive is used as component.\n *\n *\n * #### `restrict`\n * String of subset of `EACM` which restricts the directive to a specific directive\n * declaration style. If omitted, the defaults (elements and attributes) are used.\n *\n * * `E` - Element name (default): `<my-directive></my-directive>`\n * * `A` - Attribute (default): `<div my-directive=\"exp\"></div>`\n * * `C` - Class: `<div class=\"my-directive: exp;\"></div>`\n * * `M` - Comment: `<!-- directive: my-directive exp -->`\n *\n *\n * #### `templateNamespace`\n * String representing the document type used by the markup in the template.\n * AngularJS needs this information as those elements need to be created and cloned\n * in a special way when they are defined outside their usual containers like `<svg>` and `<math>`.\n *\n * * `html` - All root nodes in the template are HTML. Root nodes may also be\n *   top-level elements such as `<svg>` or `<math>`.\n * * `svg` - The root nodes in the template are SVG elements (excluding `<math>`).\n * * `math` - The root nodes in the template are MathML elements (excluding `<svg>`).\n *\n * If no `templateNamespace` is specified, then the namespace is considered to be `html`.\n *\n * #### `template`\n * HTML markup that may:\n * * Replace the contents of the directive's element (default).\n * * Replace the directive's element itself (if `replace` is true - DEPRECATED).\n * * Wrap the contents of the directive's element (if `transclude` is true).\n *\n * Value may be:\n *\n * * A string. For example `<div red-on-hover>{{delete_str}}</div>`.\n * * A function which takes two arguments `tElement` and `tAttrs` (described in the `compile`\n *   function api below) and returns a string value.\n *\n *\n * #### `templateUrl`\n * This is similar to `template` but the template is loaded from the specified URL, asynchronously.\n *\n * Because template loading is asynchronous the compiler will suspend compilation of directives on that element\n * for later when the template has been resolved.  In the meantime it will continue to compile and link\n * sibling and parent elements as though this element had not contained any directives.\n *\n * The compiler does not suspend the entire compilation to wait for templates to be loaded because this\n * would result in the whole app \"stalling\" until all templates are loaded asynchronously - even in the\n * case when only one deeply nested directive has `templateUrl`.\n *\n * Template loading is asynchronous even if the template has been preloaded into the {@link $templateCache}\n *\n * You can specify `templateUrl` as a string representing the URL or as a function which takes two\n * arguments `tElement` and `tAttrs` (described in the `compile` function api below) and returns\n * a string value representing the url.  In either case, the template URL is passed through {@link\n * $sce#getTrustedResourceUrl $sce.getTrustedResourceUrl}.\n *\n *\n * #### `replace` ([*DEPRECATED*!], will be removed in next major release - i.e. v2.0)\n * specify what the template should replace. Defaults to `false`.\n *\n * * `true` - the template will replace the directive's element.\n * * `false` - the template will replace the contents of the directive's element.\n *\n * The replacement process migrates all of the attributes / classes from the old element to the new\n * one. See the {@link guide/directive#template-expanding-directive\n * Directives Guide} for an example.\n *\n * There are very few scenarios where element replacement is required for the application function,\n * the main one being reusable custom components that are used within SVG contexts\n * (because SVG doesn't work with custom elements in the DOM tree).\n *\n * #### `transclude`\n * Extract the contents of the element where the directive appears and make it available to the directive.\n * The contents are compiled and provided to the directive as a **transclusion function**. See the\n * {@link $compile#transclusion Transclusion} section below.\n *\n * There are two kinds of transclusion depending upon whether you want to transclude just the contents of the\n * directive's element or the entire element:\n *\n * * `true` - transclude the content (i.e. the child nodes) of the directive's element.\n * * `'element'` - transclude the whole of the directive's element including any directives on this\n *   element that defined at a lower priority than this directive. When used, the `template`\n *   property is ignored.\n *\n *\n * #### `compile`\n *\n * ```js\n *   function compile(tElement, tAttrs, transclude) { ... }\n * ```\n *\n * The compile function deals with transforming the template DOM. Since most directives do not do\n * template transformation, it is not used often. The compile function takes the following arguments:\n *\n *   * `tElement` - template element - The element where the directive has been declared. It is\n *     safe to do template transformation on the element and child elements only.\n *\n *   * `tAttrs` - template attributes - Normalized list of attributes declared on this element shared\n *     between all directive compile functions.\n *\n *   * `transclude` -  [*DEPRECATED*!] A transclude linking function: `function(scope, cloneLinkingFn)`\n *\n * <div class=\"alert alert-warning\">\n * **Note:** The template instance and the link instance may be different objects if the template has\n * been cloned. For this reason it is **not** safe to do anything other than DOM transformations that\n * apply to all cloned DOM nodes within the compile function. Specifically, DOM listener registration\n * should be done in a linking function rather than in a compile function.\n * </div>\n\n * <div class=\"alert alert-warning\">\n * **Note:** The compile function cannot handle directives that recursively use themselves in their\n * own templates or compile functions. Compiling these directives results in an infinite loop and a\n * stack overflow errors.\n *\n * This can be avoided by manually using $compile in the postLink function to imperatively compile\n * a directive's template instead of relying on automatic template compilation via `template` or\n * `templateUrl` declaration or manual compilation inside the compile function.\n * </div>\n *\n * <div class=\"alert alert-error\">\n * **Note:** The `transclude` function that is passed to the compile function is deprecated, as it\n *   e.g. does not know about the right outer scope. Please use the transclude function that is passed\n *   to the link function instead.\n * </div>\n\n * A compile function can have a return value which can be either a function or an object.\n *\n * * returning a (post-link) function - is equivalent to registering the linking function via the\n *   `link` property of the config object when the compile function is empty.\n *\n * * returning an object with function(s) registered via `pre` and `post` properties - allows you to\n *   control when a linking function should be called during the linking phase. See info about\n *   pre-linking and post-linking functions below.\n *\n *\n * #### `link`\n * This property is used only if the `compile` property is not defined.\n *\n * ```js\n *   function link(scope, iElement, iAttrs, controller, transcludeFn) { ... }\n * ```\n *\n * The link function is responsible for registering DOM listeners as well as updating the DOM. It is\n * executed after the template has been cloned. This is where most of the directive logic will be\n * put.\n *\n *   * `scope` - {@link ng.$rootScope.Scope Scope} - The scope to be used by the\n *     directive for registering {@link ng.$rootScope.Scope#$watch watches}.\n *\n *   * `iElement` - instance element - The element where the directive is to be used. It is safe to\n *     manipulate the children of the element only in `postLink` function since the children have\n *     already been linked.\n *\n *   * `iAttrs` - instance attributes - Normalized list of attributes declared on this element shared\n *     between all directive linking functions.\n *\n *   * `controller` - a controller instance - A controller instance if at least one directive on the\n *     element defines a controller. The controller is shared among all the directives, which allows\n *     the directives to use the controllers as a communication channel.\n *\n *   * `transcludeFn` - A transclude linking function pre-bound to the correct transclusion scope.\n *     This is the same as the `$transclude`\n *     parameter of directive controllers, see there for details.\n *     `function([scope], cloneLinkingFn, futureParentElement)`.\n *\n * #### Pre-linking function\n *\n * Executed before the child elements are linked. Not safe to do DOM transformation since the\n * compiler linking function will fail to locate the correct elements for linking.\n *\n * #### Post-linking function\n *\n * Executed after the child elements are linked.\n *\n * Note that child elements that contain `templateUrl` directives will not have been compiled\n * and linked since they are waiting for their template to load asynchronously and their own\n * compilation and linking has been suspended until that occurs.\n *\n * It is safe to do DOM transformation in the post-linking function on elements that are not waiting\n * for their async templates to be resolved.\n *\n *\n * ### Transclusion\n *\n * Transclusion is the process of extracting a collection of DOM element from one part of the DOM and\n * copying them to another part of the DOM, while maintaining their connection to the original AngularJS\n * scope from where they were taken.\n *\n * Transclusion is used (often with {@link ngTransclude}) to insert the\n * original contents of a directive's element into a specified place in the template of the directive.\n * The benefit of transclusion, over simply moving the DOM elements manually, is that the transcluded\n * content has access to the properties on the scope from which it was taken, even if the directive\n * has isolated scope.\n * See the {@link guide/directive#creating-a-directive-that-wraps-other-elements Directives Guide}.\n *\n * This makes it possible for the widget to have private state for its template, while the transcluded\n * content has access to its originating scope.\n *\n * <div class=\"alert alert-warning\">\n * **Note:** When testing an element transclude directive you must not place the directive at the root of the\n * DOM fragment that is being compiled. See {@link guide/unit-testing#testing-transclusion-directives\n * Testing Transclusion Directives}.\n * </div>\n *\n * #### Transclusion Functions\n *\n * When a directive requests transclusion, the compiler extracts its contents and provides a **transclusion\n * function** to the directive's `link` function and `controller`. This transclusion function is a special\n * **linking function** that will return the compiled contents linked to a new transclusion scope.\n *\n * <div class=\"alert alert-info\">\n * If you are just using {@link ngTransclude} then you don't need to worry about this function, since\n * ngTransclude will deal with it for us.\n * </div>\n *\n * If you want to manually control the insertion and removal of the transcluded content in your directive\n * then you must use this transclude function. When you call a transclude function it returns a a jqLite/JQuery\n * object that contains the compiled DOM, which is linked to the correct transclusion scope.\n *\n * When you call a transclusion function you can pass in a **clone attach function**. This function accepts\n * two parameters, `function(clone, scope) { ... }`, where the `clone` is a fresh compiled copy of your transcluded\n * content and the `scope` is the newly created transclusion scope, to which the clone is bound.\n *\n * <div class=\"alert alert-info\">\n * **Best Practice**: Always provide a `cloneFn` (clone attach function) when you call a translude function\n * since you then get a fresh clone of the original DOM and also have access to the new transclusion scope.\n * </div>\n *\n * It is normal practice to attach your transcluded content (`clone`) to the DOM inside your **clone\n * attach function**:\n *\n * ```js\n * var transcludedContent, transclusionScope;\n *\n * $transclude(function(clone, scope) {\n *   element.append(clone);\n *   transcludedContent = clone;\n *   transclusionScope = scope;\n * });\n * ```\n *\n * Later, if you want to remove the transcluded content from your DOM then you should also destroy the\n * associated transclusion scope:\n *\n * ```js\n * transcludedContent.remove();\n * transclusionScope.$destroy();\n * ```\n *\n * <div class=\"alert alert-info\">\n * **Best Practice**: if you intend to add and remove transcluded content manually in your directive\n * (by calling the transclude function to get the DOM and and calling `element.remove()` to remove it),\n * then you are also responsible for calling `$destroy` on the transclusion scope.\n * </div>\n *\n * The built-in DOM manipulation directives, such as {@link ngIf}, {@link ngSwitch} and {@link ngRepeat}\n * automatically destroy their transluded clones as necessary so you do not need to worry about this if\n * you are simply using {@link ngTransclude} to inject the transclusion into your directive.\n *\n *\n * #### Transclusion Scopes\n *\n * When you call a transclude function it returns a DOM fragment that is pre-bound to a **transclusion\n * scope**. This scope is special, in that it is a child of the directive's scope (and so gets destroyed\n * when the directive's scope gets destroyed) but it inherits the properties of the scope from which it\n * was taken.\n *\n * For example consider a directive that uses transclusion and isolated scope. The DOM hierarchy might look\n * like this:\n *\n * ```html\n * <div ng-app>\n *   <div isolate>\n *     <div transclusion>\n *     </div>\n *   </div>\n * </div>\n * ```\n *\n * The `$parent` scope hierarchy will look like this:\n *\n * ```\n * - $rootScope\n *   - isolate\n *     - transclusion\n * ```\n *\n * but the scopes will inherit prototypically from different scopes to their `$parent`.\n *\n * ```\n * - $rootScope\n *   - transclusion\n * - isolate\n * ```\n *\n *\n * ### Attributes\n *\n * The {@link ng.$compile.directive.Attributes Attributes} object - passed as a parameter in the\n * `link()` or `compile()` functions. It has a variety of uses.\n *\n * accessing *Normalized attribute names:*\n * Directives like 'ngBind' can be expressed in many ways: 'ng:bind', `data-ng-bind`, or 'x-ng-bind'.\n * the attributes object allows for normalized access to\n *   the attributes.\n *\n * * *Directive inter-communication:* All directives share the same instance of the attributes\n *   object which allows the directives to use the attributes object as inter directive\n *   communication.\n *\n * * *Supports interpolation:* Interpolation attributes are assigned to the attribute object\n *   allowing other directives to read the interpolated value.\n *\n * * *Observing interpolated attributes:* Use `$observe` to observe the value changes of attributes\n *   that contain interpolation (e.g. `src=\"{{bar}}\"`). Not only is this very efficient but it's also\n *   the only way to easily get the actual value because during the linking phase the interpolation\n *   hasn't been evaluated yet and so the value is at this time set to `undefined`.\n *\n * ```js\n * function linkingFn(scope, elm, attrs, ctrl) {\n *   // get the attribute value\n *   console.log(attrs.ngModel);\n *\n *   // change the attribute\n *   attrs.$set('ngModel', 'new value');\n *\n *   // observe changes to interpolated attribute\n *   attrs.$observe('ngModel', function(value) {\n *     console.log('ngModel has changed value to ' + value);\n *   });\n * }\n * ```\n *\n * ## Example\n *\n * <div class=\"alert alert-warning\">\n * **Note**: Typically directives are registered with `module.directive`. The example below is\n * to illustrate how `$compile` works.\n * </div>\n *\n <example module=\"compileExample\">\n   <file name=\"index.html\">\n    <script>\n      angular.module('compileExample', [], function($compileProvider) {\n        // configure new 'compile' directive by passing a directive\n        // factory function. The factory function injects the '$compile'\n        $compileProvider.directive('compile', function($compile) {\n          // directive factory creates a link function\n          return function(scope, element, attrs) {\n            scope.$watch(\n              function(scope) {\n                 // watch the 'compile' expression for changes\n                return scope.$eval(attrs.compile);\n              },\n              function(value) {\n                // when the 'compile' expression changes\n                // assign it into the current DOM\n                element.html(value);\n\n                // compile the new DOM and link it to the current\n                // scope.\n                // NOTE: we only compile .childNodes so that\n                // we don't get into infinite loop compiling ourselves\n                $compile(element.contents())(scope);\n              }\n            );\n          };\n        });\n      })\n      .controller('GreeterController', ['$scope', function($scope) {\n        $scope.name = 'Angular';\n        $scope.html = 'Hello {{name}}';\n      }]);\n    </script>\n    <div ng-controller=\"GreeterController\">\n      <input ng-model=\"name\"> <br>\n      <textarea ng-model=\"html\"></textarea> <br>\n      <div compile=\"html\"></div>\n    </div>\n   </file>\n   <file name=\"protractor.js\" type=\"protractor\">\n     it('should auto compile', function() {\n       var textarea = $('textarea');\n       var output = $('div[compile]');\n       // The initial state reads 'Hello Angular'.\n       expect(output.getText()).toBe('Hello Angular');\n       textarea.clear();\n       textarea.sendKeys('{{name}}!');\n       expect(output.getText()).toBe('Angular!');\n     });\n   </file>\n </example>\n\n *\n *\n * @param {string|DOMElement} element Element or HTML string to compile into a template function.\n * @param {function(angular.Scope, cloneAttachFn=)} transclude function available to directives - DEPRECATED.\n *\n * <div class=\"alert alert-error\">\n * **Note:** Passing a `transclude` function to the $compile function is deprecated, as it\n *   e.g. will not use the right outer scope. Please pass the transclude function as a\n *   `parentBoundTranscludeFn` to the link function instead.\n * </div>\n *\n * @param {number} maxPriority only apply directives lower than given priority (Only effects the\n *                 root element(s), not their children)\n * @returns {function(scope, cloneAttachFn=, options=)} a link function which is used to bind template\n * (a DOM element/tree) to a scope. Where:\n *\n *  * `scope` - A {@link ng.$rootScope.Scope Scope} to bind to.\n *  * `cloneAttachFn` - If `cloneAttachFn` is provided, then the link function will clone the\n *  `template` and call the `cloneAttachFn` function allowing the caller to attach the\n *  cloned elements to the DOM document at the appropriate place. The `cloneAttachFn` is\n *  called as: <br> `cloneAttachFn(clonedElement, scope)` where:\n *\n *      * `clonedElement` - is a clone of the original `element` passed into the compiler.\n *      * `scope` - is the current scope with which the linking function is working with.\n *\n *  * `options` - An optional object hash with linking options. If `options` is provided, then the following\n *  keys may be used to control linking behavior:\n *\n *      * `parentBoundTranscludeFn` - the transclude function made available to\n *        directives; if given, it will be passed through to the link functions of\n *        directives found in `element` during compilation.\n *      * `transcludeControllers` - an object hash with keys that map controller names\n *        to controller instances; if given, it will make the controllers\n *        available to directives.\n *      * `futureParentElement` - defines the parent to which the `cloneAttachFn` will add\n *        the cloned elements; only needed for transcludes that are allowed to contain non html\n *        elements (e.g. SVG elements). See also the directive.controller property.\n *\n * Calling the linking function returns the element of the template. It is either the original\n * element passed in, or the clone of the element if the `cloneAttachFn` is provided.\n *\n * After linking the view is not updated until after a call to $digest which typically is done by\n * Angular automatically.\n *\n * If you need access to the bound view, there are two ways to do it:\n *\n * - If you are not asking the linking function to clone the template, create the DOM element(s)\n *   before you send them to the compiler and keep this reference around.\n *   ```js\n *     var element = $compile('<p>{{total}}</p>')(scope);\n *   ```\n *\n * - if on the other hand, you need the element to be cloned, the view reference from the original\n *   example would not point to the clone, but rather to the original template that was cloned. In\n *   this case, you can access the clone via the cloneAttachFn:\n *   ```js\n *     var templateElement = angular.element('<p>{{total}}</p>'),\n *         scope = ....;\n *\n *     var clonedElement = $compile(templateElement)(scope, function(clonedElement, scope) {\n *       //attach the clone to DOM document at the right place\n *     });\n *\n *     //now we have reference to the cloned DOM via `clonedElement`\n *   ```\n *\n *\n * For information on how the compiler works, see the\n * {@link guide/compiler Angular HTML Compiler} section of the Developer Guide.\n */\n\nvar $compileMinErr = minErr('$compile');\n\n/**\n * @ngdoc provider\n * @name $compileProvider\n *\n * @description\n */\n$CompileProvider.$inject = ['$provide', '$$sanitizeUriProvider'];\nfunction $CompileProvider($provide, $$sanitizeUriProvider) {\n  var hasDirectives = {},\n      Suffix = 'Directive',\n      COMMENT_DIRECTIVE_REGEXP = /^\\s*directive\\:\\s*([\\w\\-]+)\\s+(.*)$/,\n      CLASS_DIRECTIVE_REGEXP = /(([\\w\\-]+)(?:\\:([^;]+))?;?)/,\n      ALL_OR_NOTHING_ATTRS = makeMap('ngSrc,ngSrcset,src,srcset'),\n      REQUIRE_PREFIX_REGEXP = /^(?:(\\^\\^?)?(\\?)?(\\^\\^?)?)?/;\n\n  // Ref: http://developers.whatwg.org/webappapis.html#event-handler-idl-attributes\n  // The assumption is that future DOM event attribute names will begin with\n  // 'on' and be composed of only English letters.\n  var EVENT_HANDLER_ATTR_REGEXP = /^(on[a-z]+|formaction)$/;\n\n  function parseIsolateBindings(scope, directiveName) {\n    var LOCAL_REGEXP = /^\\s*([@&]|=(\\*?))(\\??)\\s*(\\w*)\\s*$/;\n\n    var bindings = {};\n\n    forEach(scope, function(definition, scopeName) {\n      var match = definition.match(LOCAL_REGEXP);\n\n      if (!match) {\n        throw $compileMinErr('iscp',\n            \"Invalid isolate scope definition for directive '{0}'.\" +\n            \" Definition: {... {1}: '{2}' ...}\",\n            directiveName, scopeName, definition);\n      }\n\n      bindings[scopeName] = {\n        mode: match[1][0],\n        collection: match[2] === '*',\n        optional: match[3] === '?',\n        attrName: match[4] || scopeName\n      };\n    });\n\n    return bindings;\n  }\n\n  /**\n   * @ngdoc method\n   * @name $compileProvider#directive\n   * @kind function\n   *\n   * @description\n   * Register a new directive with the compiler.\n   *\n   * @param {string|Object} name Name of the directive in camel-case (i.e. <code>ngBind</code> which\n   *    will match as <code>ng-bind</code>), or an object map of directives where the keys are the\n   *    names and the values are the factories.\n   * @param {Function|Array} directiveFactory An injectable directive factory function. See\n   *    {@link guide/directive} for more info.\n   * @returns {ng.$compileProvider} Self for chaining.\n   */\n   this.directive = function registerDirective(name, directiveFactory) {\n    assertNotHasOwnProperty(name, 'directive');\n    if (isString(name)) {\n      assertArg(directiveFactory, 'directiveFactory');\n      if (!hasDirectives.hasOwnProperty(name)) {\n        hasDirectives[name] = [];\n        $provide.factory(name + Suffix, ['$injector', '$exceptionHandler',\n          function($injector, $exceptionHandler) {\n            var directives = [];\n            forEach(hasDirectives[name], function(directiveFactory, index) {\n              try {\n                var directive = $injector.invoke(directiveFactory);\n                if (isFunction(directive)) {\n                  directive = { compile: valueFn(directive) };\n                } else if (!directive.compile && directive.link) {\n                  directive.compile = valueFn(directive.link);\n                }\n                directive.priority = directive.priority || 0;\n                directive.index = index;\n                directive.name = directive.name || name;\n                directive.require = directive.require || (directive.controller && directive.name);\n                directive.restrict = directive.restrict || 'EA';\n                if (isObject(directive.scope)) {\n                  directive.$$isolateBindings = parseIsolateBindings(directive.scope, directive.name);\n                }\n                directives.push(directive);\n              } catch (e) {\n                $exceptionHandler(e);\n              }\n            });\n            return directives;\n          }]);\n      }\n      hasDirectives[name].push(directiveFactory);\n    } else {\n      forEach(name, reverseParams(registerDirective));\n    }\n    return this;\n  };\n\n\n  /**\n   * @ngdoc method\n   * @name $compileProvider#aHrefSanitizationWhitelist\n   * @kind function\n   *\n   * @description\n   * Retrieves or overrides the default regular expression that is used for whitelisting of safe\n   * urls during a[href] sanitization.\n   *\n   * The sanitization is a security measure aimed at preventing XSS attacks via html links.\n   *\n   * Any url about to be assigned to a[href] via data-binding is first normalized and turned into\n   * an absolute url. Afterwards, the url is matched against the `aHrefSanitizationWhitelist`\n   * regular expression. If a match is found, the original url is written into the dom. Otherwise,\n   * the absolute url is prefixed with `'unsafe:'` string and only then is it written into the DOM.\n   *\n   * @param {RegExp=} regexp New regexp to whitelist urls with.\n   * @returns {RegExp|ng.$compileProvider} Current RegExp if called without value or self for\n   *    chaining otherwise.\n   */\n  this.aHrefSanitizationWhitelist = function(regexp) {\n    if (isDefined(regexp)) {\n      $$sanitizeUriProvider.aHrefSanitizationWhitelist(regexp);\n      return this;\n    } else {\n      return $$sanitizeUriProvider.aHrefSanitizationWhitelist();\n    }\n  };\n\n\n  /**\n   * @ngdoc method\n   * @name $compileProvider#imgSrcSanitizationWhitelist\n   * @kind function\n   *\n   * @description\n   * Retrieves or overrides the default regular expression that is used for whitelisting of safe\n   * urls during img[src] sanitization.\n   *\n   * The sanitization is a security measure aimed at prevent XSS attacks via html links.\n   *\n   * Any url about to be assigned to img[src] via data-binding is first normalized and turned into\n   * an absolute url. Afterwards, the url is matched against the `imgSrcSanitizationWhitelist`\n   * regular expression. If a match is found, the original url is written into the dom. Otherwise,\n   * the absolute url is prefixed with `'unsafe:'` string and only then is it written into the DOM.\n   *\n   * @param {RegExp=} regexp New regexp to whitelist urls with.\n   * @returns {RegExp|ng.$compileProvider} Current RegExp if called without value or self for\n   *    chaining otherwise.\n   */\n  this.imgSrcSanitizationWhitelist = function(regexp) {\n    if (isDefined(regexp)) {\n      $$sanitizeUriProvider.imgSrcSanitizationWhitelist(regexp);\n      return this;\n    } else {\n      return $$sanitizeUriProvider.imgSrcSanitizationWhitelist();\n    }\n  };\n\n  /**\n   * @ngdoc method\n   * @name  $compileProvider#debugInfoEnabled\n   *\n   * @param {boolean=} enabled update the debugInfoEnabled state if provided, otherwise just return the\n   * current debugInfoEnabled state\n   * @returns {*} current value if used as getter or itself (chaining) if used as setter\n   *\n   * @kind function\n   *\n   * @description\n   * Call this method to enable/disable various debug runtime information in the compiler such as adding\n   * binding information and a reference to the current scope on to DOM elements.\n   * If enabled, the compiler will add the following to DOM elements that have been bound to the scope\n   * * `ng-binding` CSS class\n   * * `$binding` data property containing an array of the binding expressions\n   *\n   * You may want to disable this in production for a significant performance boost. See\n   * {@link guide/production#disabling-debug-data Disabling Debug Data} for more.\n   *\n   * The default value is true.\n   */\n  var debugInfoEnabled = true;\n  this.debugInfoEnabled = function(enabled) {\n    if (isDefined(enabled)) {\n      debugInfoEnabled = enabled;\n      return this;\n    }\n    return debugInfoEnabled;\n  };\n\n  this.$get = [\n            '$injector', '$interpolate', '$exceptionHandler', '$templateRequest', '$parse',\n            '$controller', '$rootScope', '$document', '$sce', '$animate', '$$sanitizeUri',\n    function($injector,   $interpolate,   $exceptionHandler,   $templateRequest,   $parse,\n             $controller,   $rootScope,   $document,   $sce,   $animate,   $$sanitizeUri) {\n\n    var Attributes = function(element, attributesToCopy) {\n      if (attributesToCopy) {\n        var keys = Object.keys(attributesToCopy);\n        var i, l, key;\n\n        for (i = 0, l = keys.length; i < l; i++) {\n          key = keys[i];\n          this[key] = attributesToCopy[key];\n        }\n      } else {\n        this.$attr = {};\n      }\n\n      this.$$element = element;\n    };\n\n    Attributes.prototype = {\n      /**\n       * @ngdoc method\n       * @name $compile.directive.Attributes#$normalize\n       * @kind function\n       *\n       * @description\n       * Converts an attribute name (e.g. dash/colon/underscore-delimited string, optionally prefixed with `x-` or\n       * `data-`) to its normalized, camelCase form.\n       *\n       * Also there is special case for Moz prefix starting with upper case letter.\n       *\n       * For further information check out the guide on {@link guide/directive#matching-directives Matching Directives}\n       *\n       * @param {string} name Name to normalize\n       */\n      $normalize: directiveNormalize,\n\n\n      /**\n       * @ngdoc method\n       * @name $compile.directive.Attributes#$addClass\n       * @kind function\n       *\n       * @description\n       * Adds the CSS class value specified by the classVal parameter to the element. If animations\n       * are enabled then an animation will be triggered for the class addition.\n       *\n       * @param {string} classVal The className value that will be added to the element\n       */\n      $addClass: function(classVal) {\n        if (classVal && classVal.length > 0) {\n          $animate.addClass(this.$$element, classVal);\n        }\n      },\n\n      /**\n       * @ngdoc method\n       * @name $compile.directive.Attributes#$removeClass\n       * @kind function\n       *\n       * @description\n       * Removes the CSS class value specified by the classVal parameter from the element. If\n       * animations are enabled then an animation will be triggered for the class removal.\n       *\n       * @param {string} classVal The className value that will be removed from the element\n       */\n      $removeClass: function(classVal) {\n        if (classVal && classVal.length > 0) {\n          $animate.removeClass(this.$$element, classVal);\n        }\n      },\n\n      /**\n       * @ngdoc method\n       * @name $compile.directive.Attributes#$updateClass\n       * @kind function\n       *\n       * @description\n       * Adds and removes the appropriate CSS class values to the element based on the difference\n       * between the new and old CSS class values (specified as newClasses and oldClasses).\n       *\n       * @param {string} newClasses The current CSS className value\n       * @param {string} oldClasses The former CSS className value\n       */\n      $updateClass: function(newClasses, oldClasses) {\n        var toAdd = tokenDifference(newClasses, oldClasses);\n        if (toAdd && toAdd.length) {\n          $animate.addClass(this.$$element, toAdd);\n        }\n\n        var toRemove = tokenDifference(oldClasses, newClasses);\n        if (toRemove && toRemove.length) {\n          $animate.removeClass(this.$$element, toRemove);\n        }\n      },\n\n      /**\n       * Set a normalized attribute on the element in a way such that all directives\n       * can share the attribute. This function properly handles boolean attributes.\n       * @param {string} key Normalized key. (ie ngAttribute)\n       * @param {string|boolean} value The value to set. If `null` attribute will be deleted.\n       * @param {boolean=} writeAttr If false, does not write the value to DOM element attribute.\n       *     Defaults to true.\n       * @param {string=} attrName Optional none normalized name. Defaults to key.\n       */\n      $set: function(key, value, writeAttr, attrName) {\n        // TODO: decide whether or not to throw an error if \"class\"\n        //is set through this function since it may cause $updateClass to\n        //become unstable.\n\n        var node = this.$$element[0],\n            booleanKey = getBooleanAttrName(node, key),\n            aliasedKey = getAliasedAttrName(node, key),\n            observer = key,\n            nodeName;\n\n        if (booleanKey) {\n          this.$$element.prop(key, value);\n          attrName = booleanKey;\n        } else if (aliasedKey) {\n          this[aliasedKey] = value;\n          observer = aliasedKey;\n        }\n\n        this[key] = value;\n\n        // translate normalized key to actual key\n        if (attrName) {\n          this.$attr[key] = attrName;\n        } else {\n          attrName = this.$attr[key];\n          if (!attrName) {\n            this.$attr[key] = attrName = snake_case(key, '-');\n          }\n        }\n\n        nodeName = nodeName_(this.$$element);\n\n        if ((nodeName === 'a' && key === 'href') ||\n            (nodeName === 'img' && key === 'src')) {\n          // sanitize a[href] and img[src] values\n          this[key] = value = $$sanitizeUri(value, key === 'src');\n        } else if (nodeName === 'img' && key === 'srcset') {\n          // sanitize img[srcset] values\n          var result = \"\";\n\n          // first check if there are spaces because it's not the same pattern\n          var trimmedSrcset = trim(value);\n          //                (   999x   ,|   999w   ,|   ,|,   )\n          var srcPattern = /(\\s+\\d+x\\s*,|\\s+\\d+w\\s*,|\\s+,|,\\s+)/;\n          var pattern = /\\s/.test(trimmedSrcset) ? srcPattern : /(,)/;\n\n          // split srcset into tuple of uri and descriptor except for the last item\n          var rawUris = trimmedSrcset.split(pattern);\n\n          // for each tuples\n          var nbrUrisWith2parts = Math.floor(rawUris.length / 2);\n          for (var i = 0; i < nbrUrisWith2parts; i++) {\n            var innerIdx = i * 2;\n            // sanitize the uri\n            result += $$sanitizeUri(trim(rawUris[innerIdx]), true);\n            // add the descriptor\n            result += (\" \" + trim(rawUris[innerIdx + 1]));\n          }\n\n          // split the last item into uri and descriptor\n          var lastTuple = trim(rawUris[i * 2]).split(/\\s/);\n\n          // sanitize the last uri\n          result += $$sanitizeUri(trim(lastTuple[0]), true);\n\n          // and add the last descriptor if any\n          if (lastTuple.length === 2) {\n            result += (\" \" + trim(lastTuple[1]));\n          }\n          this[key] = value = result;\n        }\n\n        if (writeAttr !== false) {\n          if (value === null || value === undefined) {\n            this.$$element.removeAttr(attrName);\n          } else {\n            this.$$element.attr(attrName, value);\n          }\n        }\n\n        // fire observers\n        var $$observers = this.$$observers;\n        $$observers && forEach($$observers[observer], function(fn) {\n          try {\n            fn(value);\n          } catch (e) {\n            $exceptionHandler(e);\n          }\n        });\n      },\n\n\n      /**\n       * @ngdoc method\n       * @name $compile.directive.Attributes#$observe\n       * @kind function\n       *\n       * @description\n       * Observes an interpolated attribute.\n       *\n       * The observer function will be invoked once during the next `$digest` following\n       * compilation. The observer is then invoked whenever the interpolated value\n       * changes.\n       *\n       * @param {string} key Normalized key. (ie ngAttribute) .\n       * @param {function(interpolatedValue)} fn Function that will be called whenever\n                the interpolated value of the attribute changes.\n       *        See the {@link guide/directive#text-and-attribute-bindings Directives} guide for more info.\n       * @returns {function()} Returns a deregistration function for this observer.\n       */\n      $observe: function(key, fn) {\n        var attrs = this,\n            $$observers = (attrs.$$observers || (attrs.$$observers = createMap())),\n            listeners = ($$observers[key] || ($$observers[key] = []));\n\n        listeners.push(fn);\n        $rootScope.$evalAsync(function() {\n          if (!listeners.$$inter && attrs.hasOwnProperty(key)) {\n            // no one registered attribute interpolation function, so lets call it manually\n            fn(attrs[key]);\n          }\n        });\n\n        return function() {\n          arrayRemove(listeners, fn);\n        };\n      }\n    };\n\n\n    function safeAddClass($element, className) {\n      try {\n        $element.addClass(className);\n      } catch (e) {\n        // ignore, since it means that we are trying to set class on\n        // SVG element, where class name is read-only.\n      }\n    }\n\n\n    var startSymbol = $interpolate.startSymbol(),\n        endSymbol = $interpolate.endSymbol(),\n        denormalizeTemplate = (startSymbol == '{{' || endSymbol  == '}}')\n            ? identity\n            : function denormalizeTemplate(template) {\n              return template.replace(/\\{\\{/g, startSymbol).replace(/}}/g, endSymbol);\n        },\n        NG_ATTR_BINDING = /^ngAttr[A-Z]/;\n\n    compile.$$addBindingInfo = debugInfoEnabled ? function $$addBindingInfo($element, binding) {\n      var bindings = $element.data('$binding') || [];\n\n      if (isArray(binding)) {\n        bindings = bindings.concat(binding);\n      } else {\n        bindings.push(binding);\n      }\n\n      $element.data('$binding', bindings);\n    } : noop;\n\n    compile.$$addBindingClass = debugInfoEnabled ? function $$addBindingClass($element) {\n      safeAddClass($element, 'ng-binding');\n    } : noop;\n\n    compile.$$addScopeInfo = debugInfoEnabled ? function $$addScopeInfo($element, scope, isolated, noTemplate) {\n      var dataName = isolated ? (noTemplate ? '$isolateScopeNoTemplate' : '$isolateScope') : '$scope';\n      $element.data(dataName, scope);\n    } : noop;\n\n    compile.$$addScopeClass = debugInfoEnabled ? function $$addScopeClass($element, isolated) {\n      safeAddClass($element, isolated ? 'ng-isolate-scope' : 'ng-scope');\n    } : noop;\n\n    return compile;\n\n    //================================\n\n    function compile($compileNodes, transcludeFn, maxPriority, ignoreDirective,\n                        previousCompileContext) {\n      if (!($compileNodes instanceof jqLite)) {\n        // jquery always rewraps, whereas we need to preserve the original selector so that we can\n        // modify it.\n        $compileNodes = jqLite($compileNodes);\n      }\n      // We can not compile top level text elements since text nodes can be merged and we will\n      // not be able to attach scope data to them, so we will wrap them in <span>\n      forEach($compileNodes, function(node, index) {\n        if (node.nodeType == NODE_TYPE_TEXT && node.nodeValue.match(/\\S+/) /* non-empty */ ) {\n          $compileNodes[index] = jqLite(node).wrap('<span></span>').parent()[0];\n        }\n      });\n      var compositeLinkFn =\n              compileNodes($compileNodes, transcludeFn, $compileNodes,\n                           maxPriority, ignoreDirective, previousCompileContext);\n      compile.$$addScopeClass($compileNodes);\n      var namespace = null;\n      return function publicLinkFn(scope, cloneConnectFn, options) {\n        assertArg(scope, 'scope');\n\n        options = options || {};\n        var parentBoundTranscludeFn = options.parentBoundTranscludeFn,\n          transcludeControllers = options.transcludeControllers,\n          futureParentElement = options.futureParentElement;\n\n        // When `parentBoundTranscludeFn` is passed, it is a\n        // `controllersBoundTransclude` function (it was previously passed\n        // as `transclude` to directive.link) so we must unwrap it to get\n        // its `boundTranscludeFn`\n        if (parentBoundTranscludeFn && parentBoundTranscludeFn.$$boundTransclude) {\n          parentBoundTranscludeFn = parentBoundTranscludeFn.$$boundTransclude;\n        }\n\n        if (!namespace) {\n          namespace = detectNamespaceForChildElements(futureParentElement);\n        }\n        var $linkNode;\n        if (namespace !== 'html') {\n          // When using a directive with replace:true and templateUrl the $compileNodes\n          // (or a child element inside of them)\n          // might change, so we need to recreate the namespace adapted compileNodes\n          // for call to the link function.\n          // Note: This will already clone the nodes...\n          $linkNode = jqLite(\n            wrapTemplate(namespace, jqLite('<div>').append($compileNodes).html())\n          );\n        } else if (cloneConnectFn) {\n          // important!!: we must call our jqLite.clone() since the jQuery one is trying to be smart\n          // and sometimes changes the structure of the DOM.\n          $linkNode = JQLitePrototype.clone.call($compileNodes);\n        } else {\n          $linkNode = $compileNodes;\n        }\n\n        if (transcludeControllers) {\n          for (var controllerName in transcludeControllers) {\n            $linkNode.data('$' + controllerName + 'Controller', transcludeControllers[controllerName].instance);\n          }\n        }\n\n        compile.$$addScopeInfo($linkNode, scope);\n\n        if (cloneConnectFn) cloneConnectFn($linkNode, scope);\n        if (compositeLinkFn) compositeLinkFn(scope, $linkNode, $linkNode, parentBoundTranscludeFn);\n        return $linkNode;\n      };\n    }\n\n    function detectNamespaceForChildElements(parentElement) {\n      // TODO: Make this detect MathML as well...\n      var node = parentElement && parentElement[0];\n      if (!node) {\n        return 'html';\n      } else {\n        return nodeName_(node) !== 'foreignobject' && node.toString().match(/SVG/) ? 'svg' : 'html';\n      }\n    }\n\n    /**\n     * Compile function matches each node in nodeList against the directives. Once all directives\n     * for a particular node are collected their compile functions are executed. The compile\n     * functions return values - the linking functions - are combined into a composite linking\n     * function, which is the a linking function for the node.\n     *\n     * @param {NodeList} nodeList an array of nodes or NodeList to compile\n     * @param {function(angular.Scope, cloneAttachFn=)} transcludeFn A linking function, where the\n     *        scope argument is auto-generated to the new child of the transcluded parent scope.\n     * @param {DOMElement=} $rootElement If the nodeList is the root of the compilation tree then\n     *        the rootElement must be set the jqLite collection of the compile root. This is\n     *        needed so that the jqLite collection items can be replaced with widgets.\n     * @param {number=} maxPriority Max directive priority.\n     * @returns {Function} A composite linking function of all of the matched directives or null.\n     */\n    function compileNodes(nodeList, transcludeFn, $rootElement, maxPriority, ignoreDirective,\n                            previousCompileContext) {\n      var linkFns = [],\n          attrs, directives, nodeLinkFn, childNodes, childLinkFn, linkFnFound, nodeLinkFnFound;\n\n      for (var i = 0; i < nodeList.length; i++) {\n        attrs = new Attributes();\n\n        // we must always refer to nodeList[i] since the nodes can be replaced underneath us.\n        directives = collectDirectives(nodeList[i], [], attrs, i === 0 ? maxPriority : undefined,\n                                        ignoreDirective);\n\n        nodeLinkFn = (directives.length)\n            ? applyDirectivesToNode(directives, nodeList[i], attrs, transcludeFn, $rootElement,\n                                      null, [], [], previousCompileContext)\n            : null;\n\n        if (nodeLinkFn && nodeLinkFn.scope) {\n          compile.$$addScopeClass(attrs.$$element);\n        }\n\n        childLinkFn = (nodeLinkFn && nodeLinkFn.terminal ||\n                      !(childNodes = nodeList[i].childNodes) ||\n                      !childNodes.length)\n            ? null\n            : compileNodes(childNodes,\n                 nodeLinkFn ? (\n                  (nodeLinkFn.transcludeOnThisElement || !nodeLinkFn.templateOnThisElement)\n                     && nodeLinkFn.transclude) : transcludeFn);\n\n        if (nodeLinkFn || childLinkFn) {\n          linkFns.push(i, nodeLinkFn, childLinkFn);\n          linkFnFound = true;\n          nodeLinkFnFound = nodeLinkFnFound || nodeLinkFn;\n        }\n\n        //use the previous context only for the first element in the virtual group\n        previousCompileContext = null;\n      }\n\n      // return a linking function if we have found anything, null otherwise\n      return linkFnFound ? compositeLinkFn : null;\n\n      function compositeLinkFn(scope, nodeList, $rootElement, parentBoundTranscludeFn) {\n        var nodeLinkFn, childLinkFn, node, childScope, i, ii, idx, childBoundTranscludeFn;\n        var stableNodeList;\n\n\n        if (nodeLinkFnFound) {\n          // copy nodeList so that if a nodeLinkFn removes or adds an element at this DOM level our\n          // offsets don't get screwed up\n          var nodeListLength = nodeList.length;\n          stableNodeList = new Array(nodeListLength);\n\n          // create a sparse array by only copying the elements which have a linkFn\n          for (i = 0; i < linkFns.length; i+=3) {\n            idx = linkFns[i];\n            stableNodeList[idx] = nodeList[idx];\n          }\n        } else {\n          stableNodeList = nodeList;\n        }\n\n        for (i = 0, ii = linkFns.length; i < ii;) {\n          node = stableNodeList[linkFns[i++]];\n          nodeLinkFn = linkFns[i++];\n          childLinkFn = linkFns[i++];\n\n          if (nodeLinkFn) {\n            if (nodeLinkFn.scope) {\n              childScope = scope.$new();\n              compile.$$addScopeInfo(jqLite(node), childScope);\n            } else {\n              childScope = scope;\n            }\n\n            if (nodeLinkFn.transcludeOnThisElement) {\n              childBoundTranscludeFn = createBoundTranscludeFn(\n                  scope, nodeLinkFn.transclude, parentBoundTranscludeFn,\n                  nodeLinkFn.elementTranscludeOnThisElement);\n\n            } else if (!nodeLinkFn.templateOnThisElement && parentBoundTranscludeFn) {\n              childBoundTranscludeFn = parentBoundTranscludeFn;\n\n            } else if (!parentBoundTranscludeFn && transcludeFn) {\n              childBoundTranscludeFn = createBoundTranscludeFn(scope, transcludeFn);\n\n            } else {\n              childBoundTranscludeFn = null;\n            }\n\n            nodeLinkFn(childLinkFn, childScope, node, $rootElement, childBoundTranscludeFn);\n\n          } else if (childLinkFn) {\n            childLinkFn(scope, node.childNodes, undefined, parentBoundTranscludeFn);\n          }\n        }\n      }\n    }\n\n    function createBoundTranscludeFn(scope, transcludeFn, previousBoundTranscludeFn, elementTransclusion) {\n\n      var boundTranscludeFn = function(transcludedScope, cloneFn, controllers, futureParentElement, containingScope) {\n\n        if (!transcludedScope) {\n          transcludedScope = scope.$new(false, containingScope);\n          transcludedScope.$$transcluded = true;\n        }\n\n        return transcludeFn(transcludedScope, cloneFn, {\n          parentBoundTranscludeFn: previousBoundTranscludeFn,\n          transcludeControllers: controllers,\n          futureParentElement: futureParentElement\n        });\n      };\n\n      return boundTranscludeFn;\n    }\n\n    /**\n     * Looks for directives on the given node and adds them to the directive collection which is\n     * sorted.\n     *\n     * @param node Node to search.\n     * @param directives An array to which the directives are added to. This array is sorted before\n     *        the function returns.\n     * @param attrs The shared attrs object which is used to populate the normalized attributes.\n     * @param {number=} maxPriority Max directive priority.\n     */\n    function collectDirectives(node, directives, attrs, maxPriority, ignoreDirective) {\n      var nodeType = node.nodeType,\n          attrsMap = attrs.$attr,\n          match,\n          className;\n\n      switch (nodeType) {\n        case NODE_TYPE_ELEMENT: /* Element */\n          // use the node name: <directive>\n          addDirective(directives,\n              directiveNormalize(nodeName_(node)), 'E', maxPriority, ignoreDirective);\n\n          // iterate over the attributes\n          for (var attr, name, nName, ngAttrName, value, isNgAttr, nAttrs = node.attributes,\n                   j = 0, jj = nAttrs && nAttrs.length; j < jj; j++) {\n            var attrStartName = false;\n            var attrEndName = false;\n\n            attr = nAttrs[j];\n            name = attr.name;\n            value = trim(attr.value);\n\n            // support ngAttr attribute binding\n            ngAttrName = directiveNormalize(name);\n            if (isNgAttr = NG_ATTR_BINDING.test(ngAttrName)) {\n              name = name.replace(PREFIX_REGEXP, '')\n                .substr(8).replace(/_(.)/g, function(match, letter) {\n                  return letter.toUpperCase();\n                });\n            }\n\n            var directiveNName = ngAttrName.replace(/(Start|End)$/, '');\n            if (directiveIsMultiElement(directiveNName)) {\n              if (ngAttrName === directiveNName + 'Start') {\n                attrStartName = name;\n                attrEndName = name.substr(0, name.length - 5) + 'end';\n                name = name.substr(0, name.length - 6);\n              }\n            }\n\n            nName = directiveNormalize(name.toLowerCase());\n            attrsMap[nName] = name;\n            if (isNgAttr || !attrs.hasOwnProperty(nName)) {\n                attrs[nName] = value;\n                if (getBooleanAttrName(node, nName)) {\n                  attrs[nName] = true; // presence means true\n                }\n            }\n            addAttrInterpolateDirective(node, directives, value, nName, isNgAttr);\n            addDirective(directives, nName, 'A', maxPriority, ignoreDirective, attrStartName,\n                          attrEndName);\n          }\n\n          // use class as directive\n          className = node.className;\n          if (isObject(className)) {\n              // Maybe SVGAnimatedString\n              className = className.animVal;\n          }\n          if (isString(className) && className !== '') {\n            while (match = CLASS_DIRECTIVE_REGEXP.exec(className)) {\n              nName = directiveNormalize(match[2]);\n              if (addDirective(directives, nName, 'C', maxPriority, ignoreDirective)) {\n                attrs[nName] = trim(match[3]);\n              }\n              className = className.substr(match.index + match[0].length);\n            }\n          }\n          break;\n        case NODE_TYPE_TEXT: /* Text Node */\n          addTextInterpolateDirective(directives, node.nodeValue);\n          break;\n        case NODE_TYPE_COMMENT: /* Comment */\n          try {\n            match = COMMENT_DIRECTIVE_REGEXP.exec(node.nodeValue);\n            if (match) {\n              nName = directiveNormalize(match[1]);\n              if (addDirective(directives, nName, 'M', maxPriority, ignoreDirective)) {\n                attrs[nName] = trim(match[2]);\n              }\n            }\n          } catch (e) {\n            // turns out that under some circumstances IE9 throws errors when one attempts to read\n            // comment's node value.\n            // Just ignore it and continue. (Can't seem to reproduce in test case.)\n          }\n          break;\n      }\n\n      directives.sort(byPriority);\n      return directives;\n    }\n\n    /**\n     * Given a node with an directive-start it collects all of the siblings until it finds\n     * directive-end.\n     * @param node\n     * @param attrStart\n     * @param attrEnd\n     * @returns {*}\n     */\n    function groupScan(node, attrStart, attrEnd) {\n      var nodes = [];\n      var depth = 0;\n      if (attrStart && node.hasAttribute && node.hasAttribute(attrStart)) {\n        do {\n          if (!node) {\n            throw $compileMinErr('uterdir',\n                      \"Unterminated attribute, found '{0}' but no matching '{1}' found.\",\n                      attrStart, attrEnd);\n          }\n          if (node.nodeType == NODE_TYPE_ELEMENT) {\n            if (node.hasAttribute(attrStart)) depth++;\n            if (node.hasAttribute(attrEnd)) depth--;\n          }\n          nodes.push(node);\n          node = node.nextSibling;\n        } while (depth > 0);\n      } else {\n        nodes.push(node);\n      }\n\n      return jqLite(nodes);\n    }\n\n    /**\n     * Wrapper for linking function which converts normal linking function into a grouped\n     * linking function.\n     * @param linkFn\n     * @param attrStart\n     * @param attrEnd\n     * @returns {Function}\n     */\n    function groupElementsLinkFnWrapper(linkFn, attrStart, attrEnd) {\n      return function(scope, element, attrs, controllers, transcludeFn) {\n        element = groupScan(element[0], attrStart, attrEnd);\n        return linkFn(scope, element, attrs, controllers, transcludeFn);\n      };\n    }\n\n    /**\n     * Once the directives have been collected, their compile functions are executed. This method\n     * is responsible for inlining directive templates as well as terminating the application\n     * of the directives if the terminal directive has been reached.\n     *\n     * @param {Array} directives Array of collected directives to execute their compile function.\n     *        this needs to be pre-sorted by priority order.\n     * @param {Node} compileNode The raw DOM node to apply the compile functions to\n     * @param {Object} templateAttrs The shared attribute function\n     * @param {function(angular.Scope, cloneAttachFn=)} transcludeFn A linking function, where the\n     *                                                  scope argument is auto-generated to the new\n     *                                                  child of the transcluded parent scope.\n     * @param {JQLite} jqCollection If we are working on the root of the compile tree then this\n     *                              argument has the root jqLite array so that we can replace nodes\n     *                              on it.\n     * @param {Object=} originalReplaceDirective An optional directive that will be ignored when\n     *                                           compiling the transclusion.\n     * @param {Array.<Function>} preLinkFns\n     * @param {Array.<Function>} postLinkFns\n     * @param {Object} previousCompileContext Context used for previous compilation of the current\n     *                                        node\n     * @returns {Function} linkFn\n     */\n    function applyDirectivesToNode(directives, compileNode, templateAttrs, transcludeFn,\n                                   jqCollection, originalReplaceDirective, preLinkFns, postLinkFns,\n                                   previousCompileContext) {\n      previousCompileContext = previousCompileContext || {};\n\n      var terminalPriority = -Number.MAX_VALUE,\n          newScopeDirective,\n          controllerDirectives = previousCompileContext.controllerDirectives,\n          controllers,\n          newIsolateScopeDirective = previousCompileContext.newIsolateScopeDirective,\n          templateDirective = previousCompileContext.templateDirective,\n          nonTlbTranscludeDirective = previousCompileContext.nonTlbTranscludeDirective,\n          hasTranscludeDirective = false,\n          hasTemplate = false,\n          hasElementTranscludeDirective = previousCompileContext.hasElementTranscludeDirective,\n          $compileNode = templateAttrs.$$element = jqLite(compileNode),\n          directive,\n          directiveName,\n          $template,\n          replaceDirective = originalReplaceDirective,\n          childTranscludeFn = transcludeFn,\n          linkFn,\n          directiveValue;\n\n      // executes all directives on the current element\n      for (var i = 0, ii = directives.length; i < ii; i++) {\n        directive = directives[i];\n        var attrStart = directive.$$start;\n        var attrEnd = directive.$$end;\n\n        // collect multiblock sections\n        if (attrStart) {\n          $compileNode = groupScan(compileNode, attrStart, attrEnd);\n        }\n        $template = undefined;\n\n        if (terminalPriority > directive.priority) {\n          break; // prevent further processing of directives\n        }\n\n        if (directiveValue = directive.scope) {\n\n          // skip the check for directives with async templates, we'll check the derived sync\n          // directive when the template arrives\n          if (!directive.templateUrl) {\n            if (isObject(directiveValue)) {\n              // This directive is trying to add an isolated scope.\n              // Check that there is no scope of any kind already\n              assertNoDuplicate('new/isolated scope', newIsolateScopeDirective || newScopeDirective,\n                                directive, $compileNode);\n              newIsolateScopeDirective = directive;\n            } else {\n              // This directive is trying to add a child scope.\n              // Check that there is no isolated scope already\n              assertNoDuplicate('new/isolated scope', newIsolateScopeDirective, directive,\n                                $compileNode);\n            }\n          }\n\n          newScopeDirective = newScopeDirective || directive;\n        }\n\n        directiveName = directive.name;\n\n        if (!directive.templateUrl && directive.controller) {\n          directiveValue = directive.controller;\n          controllerDirectives = controllerDirectives || {};\n          assertNoDuplicate(\"'\" + directiveName + \"' controller\",\n              controllerDirectives[directiveName], directive, $compileNode);\n          controllerDirectives[directiveName] = directive;\n        }\n\n        if (directiveValue = directive.transclude) {\n          hasTranscludeDirective = true;\n\n          // Special case ngIf and ngRepeat so that we don't complain about duplicate transclusion.\n          // This option should only be used by directives that know how to safely handle element transclusion,\n          // where the transcluded nodes are added or replaced after linking.\n          if (!directive.$$tlb) {\n            assertNoDuplicate('transclusion', nonTlbTranscludeDirective, directive, $compileNode);\n            nonTlbTranscludeDirective = directive;\n          }\n\n          if (directiveValue == 'element') {\n            hasElementTranscludeDirective = true;\n            terminalPriority = directive.priority;\n            $template = $compileNode;\n            $compileNode = templateAttrs.$$element =\n                jqLite(document.createComment(' ' + directiveName + ': ' +\n                                              templateAttrs[directiveName] + ' '));\n            compileNode = $compileNode[0];\n            replaceWith(jqCollection, sliceArgs($template), compileNode);\n\n            childTranscludeFn = compile($template, transcludeFn, terminalPriority,\n                                        replaceDirective && replaceDirective.name, {\n                                          // Don't pass in:\n                                          // - controllerDirectives - otherwise we'll create duplicates controllers\n                                          // - newIsolateScopeDirective or templateDirective - combining templates with\n                                          //   element transclusion doesn't make sense.\n                                          //\n                                          // We need only nonTlbTranscludeDirective so that we prevent putting transclusion\n                                          // on the same element more than once.\n                                          nonTlbTranscludeDirective: nonTlbTranscludeDirective\n                                        });\n          } else {\n            $template = jqLite(jqLiteClone(compileNode)).contents();\n            $compileNode.empty(); // clear contents\n            childTranscludeFn = compile($template, transcludeFn);\n          }\n        }\n\n        if (directive.template) {\n          hasTemplate = true;\n          assertNoDuplicate('template', templateDirective, directive, $compileNode);\n          templateDirective = directive;\n\n          directiveValue = (isFunction(directive.template))\n              ? directive.template($compileNode, templateAttrs)\n              : directive.template;\n\n          directiveValue = denormalizeTemplate(directiveValue);\n\n          if (directive.replace) {\n            replaceDirective = directive;\n            if (jqLiteIsTextNode(directiveValue)) {\n              $template = [];\n            } else {\n              $template = removeComments(wrapTemplate(directive.templateNamespace, trim(directiveValue)));\n            }\n            compileNode = $template[0];\n\n            if ($template.length != 1 || compileNode.nodeType !== NODE_TYPE_ELEMENT) {\n              throw $compileMinErr('tplrt',\n                  \"Template for directive '{0}' must have exactly one root element. {1}\",\n                  directiveName, '');\n            }\n\n            replaceWith(jqCollection, $compileNode, compileNode);\n\n            var newTemplateAttrs = {$attr: {}};\n\n            // combine directives from the original node and from the template:\n            // - take the array of directives for this element\n            // - split it into two parts, those that already applied (processed) and those that weren't (unprocessed)\n            // - collect directives from the template and sort them by priority\n            // - combine directives as: processed + template + unprocessed\n            var templateDirectives = collectDirectives(compileNode, [], newTemplateAttrs);\n            var unprocessedDirectives = directives.splice(i + 1, directives.length - (i + 1));\n\n            if (newIsolateScopeDirective) {\n              markDirectivesAsIsolate(templateDirectives);\n            }\n            directives = directives.concat(templateDirectives).concat(unprocessedDirectives);\n            mergeTemplateAttributes(templateAttrs, newTemplateAttrs);\n\n            ii = directives.length;\n          } else {\n            $compileNode.html(directiveValue);\n          }\n        }\n\n        if (directive.templateUrl) {\n          hasTemplate = true;\n          assertNoDuplicate('template', templateDirective, directive, $compileNode);\n          templateDirective = directive;\n\n          if (directive.replace) {\n            replaceDirective = directive;\n          }\n\n          nodeLinkFn = compileTemplateUrl(directives.splice(i, directives.length - i), $compileNode,\n              templateAttrs, jqCollection, hasTranscludeDirective && childTranscludeFn, preLinkFns, postLinkFns, {\n                controllerDirectives: controllerDirectives,\n                newIsolateScopeDirective: newIsolateScopeDirective,\n                templateDirective: templateDirective,\n                nonTlbTranscludeDirective: nonTlbTranscludeDirective\n              });\n          ii = directives.length;\n        } else if (directive.compile) {\n          try {\n            linkFn = directive.compile($compileNode, templateAttrs, childTranscludeFn);\n            if (isFunction(linkFn)) {\n              addLinkFns(null, linkFn, attrStart, attrEnd);\n            } else if (linkFn) {\n              addLinkFns(linkFn.pre, linkFn.post, attrStart, attrEnd);\n            }\n          } catch (e) {\n            $exceptionHandler(e, startingTag($compileNode));\n          }\n        }\n\n        if (directive.terminal) {\n          nodeLinkFn.terminal = true;\n          terminalPriority = Math.max(terminalPriority, directive.priority);\n        }\n\n      }\n\n      nodeLinkFn.scope = newScopeDirective && newScopeDirective.scope === true;\n      nodeLinkFn.transcludeOnThisElement = hasTranscludeDirective;\n      nodeLinkFn.elementTranscludeOnThisElement = hasElementTranscludeDirective;\n      nodeLinkFn.templateOnThisElement = hasTemplate;\n      nodeLinkFn.transclude = childTranscludeFn;\n\n      previousCompileContext.hasElementTranscludeDirective = hasElementTranscludeDirective;\n\n      // might be normal or delayed nodeLinkFn depending on if templateUrl is present\n      return nodeLinkFn;\n\n      ////////////////////\n\n      function addLinkFns(pre, post, attrStart, attrEnd) {\n        if (pre) {\n          if (attrStart) pre = groupElementsLinkFnWrapper(pre, attrStart, attrEnd);\n          pre.require = directive.require;\n          pre.directiveName = directiveName;\n          if (newIsolateScopeDirective === directive || directive.$$isolateScope) {\n            pre = cloneAndAnnotateFn(pre, {isolateScope: true});\n          }\n          preLinkFns.push(pre);\n        }\n        if (post) {\n          if (attrStart) post = groupElementsLinkFnWrapper(post, attrStart, attrEnd);\n          post.require = directive.require;\n          post.directiveName = directiveName;\n          if (newIsolateScopeDirective === directive || directive.$$isolateScope) {\n            post = cloneAndAnnotateFn(post, {isolateScope: true});\n          }\n          postLinkFns.push(post);\n        }\n      }\n\n\n      function getControllers(directiveName, require, $element, elementControllers) {\n        var value, retrievalMethod = 'data', optional = false;\n        var $searchElement = $element;\n        var match;\n        if (isString(require)) {\n          match = require.match(REQUIRE_PREFIX_REGEXP);\n          require = require.substring(match[0].length);\n\n          if (match[3]) {\n            if (match[1]) match[3] = null;\n            else match[1] = match[3];\n          }\n          if (match[1] === '^') {\n            retrievalMethod = 'inheritedData';\n          } else if (match[1] === '^^') {\n            retrievalMethod = 'inheritedData';\n            $searchElement = $element.parent();\n          }\n          if (match[2] === '?') {\n            optional = true;\n          }\n\n          value = null;\n\n          if (elementControllers && retrievalMethod === 'data') {\n            if (value = elementControllers[require]) {\n              value = value.instance;\n            }\n          }\n          value = value || $searchElement[retrievalMethod]('$' + require + 'Controller');\n\n          if (!value && !optional) {\n            throw $compileMinErr('ctreq',\n                \"Controller '{0}', required by directive '{1}', can't be found!\",\n                require, directiveName);\n          }\n          return value || null;\n        } else if (isArray(require)) {\n          value = [];\n          forEach(require, function(require) {\n            value.push(getControllers(directiveName, require, $element, elementControllers));\n          });\n        }\n        return value;\n      }\n\n\n      function nodeLinkFn(childLinkFn, scope, linkNode, $rootElement, boundTranscludeFn) {\n        var i, ii, linkFn, controller, isolateScope, elementControllers, transcludeFn, $element,\n            attrs;\n\n        if (compileNode === linkNode) {\n          attrs = templateAttrs;\n          $element = templateAttrs.$$element;\n        } else {\n          $element = jqLite(linkNode);\n          attrs = new Attributes($element, templateAttrs);\n        }\n\n        if (newIsolateScopeDirective) {\n          isolateScope = scope.$new(true);\n        }\n\n        if (boundTranscludeFn) {\n          // track `boundTranscludeFn` so it can be unwrapped if `transcludeFn`\n          // is later passed as `parentBoundTranscludeFn` to `publicLinkFn`\n          transcludeFn = controllersBoundTransclude;\n          transcludeFn.$$boundTransclude = boundTranscludeFn;\n        }\n\n        if (controllerDirectives) {\n          // TODO: merge `controllers` and `elementControllers` into single object.\n          controllers = {};\n          elementControllers = {};\n          forEach(controllerDirectives, function(directive) {\n            var locals = {\n              $scope: directive === newIsolateScopeDirective || directive.$$isolateScope ? isolateScope : scope,\n              $element: $element,\n              $attrs: attrs,\n              $transclude: transcludeFn\n            }, controllerInstance;\n\n            controller = directive.controller;\n            if (controller == '@') {\n              controller = attrs[directive.name];\n            }\n\n            controllerInstance = $controller(controller, locals, true, directive.controllerAs);\n\n            // For directives with element transclusion the element is a comment,\n            // but jQuery .data doesn't support attaching data to comment nodes as it's hard to\n            // clean up (http://bugs.jquery.com/ticket/8335).\n            // Instead, we save the controllers for the element in a local hash and attach to .data\n            // later, once we have the actual element.\n            elementControllers[directive.name] = controllerInstance;\n            if (!hasElementTranscludeDirective) {\n              $element.data('$' + directive.name + 'Controller', controllerInstance.instance);\n            }\n\n            controllers[directive.name] = controllerInstance;\n          });\n        }\n\n        if (newIsolateScopeDirective) {\n          compile.$$addScopeInfo($element, isolateScope, true, !(templateDirective && (templateDirective === newIsolateScopeDirective ||\n              templateDirective === newIsolateScopeDirective.$$originalDirective)));\n          compile.$$addScopeClass($element, true);\n\n          var isolateScopeController = controllers && controllers[newIsolateScopeDirective.name];\n          var isolateBindingContext = isolateScope;\n          if (isolateScopeController && isolateScopeController.identifier &&\n              newIsolateScopeDirective.bindToController === true) {\n            isolateBindingContext = isolateScopeController.instance;\n          }\n\n          forEach(isolateScope.$$isolateBindings = newIsolateScopeDirective.$$isolateBindings, function(definition, scopeName) {\n            var attrName = definition.attrName,\n                optional = definition.optional,\n                mode = definition.mode, // @, =, or &\n                lastValue,\n                parentGet, parentSet, compare;\n\n            switch (mode) {\n\n              case '@':\n                attrs.$observe(attrName, function(value) {\n                  isolateBindingContext[scopeName] = value;\n                });\n                attrs.$$observers[attrName].$$scope = scope;\n                if (attrs[attrName]) {\n                  // If the attribute has been provided then we trigger an interpolation to ensure\n                  // the value is there for use in the link fn\n                  isolateBindingContext[scopeName] = $interpolate(attrs[attrName])(scope);\n                }\n                break;\n\n              case '=':\n                if (optional && !attrs[attrName]) {\n                  return;\n                }\n                parentGet = $parse(attrs[attrName]);\n                if (parentGet.literal) {\n                  compare = equals;\n                } else {\n                  compare = function(a, b) { return a === b || (a !== a && b !== b); };\n                }\n                parentSet = parentGet.assign || function() {\n                  // reset the change, or we will throw this exception on every $digest\n                  lastValue = isolateBindingContext[scopeName] = parentGet(scope);\n                  throw $compileMinErr('nonassign',\n                      \"Expression '{0}' used with directive '{1}' is non-assignable!\",\n                      attrs[attrName], newIsolateScopeDirective.name);\n                };\n                lastValue = isolateBindingContext[scopeName] = parentGet(scope);\n                var parentValueWatch = function parentValueWatch(parentValue) {\n                  if (!compare(parentValue, isolateBindingContext[scopeName])) {\n                    // we are out of sync and need to copy\n                    if (!compare(parentValue, lastValue)) {\n                      // parent changed and it has precedence\n                      isolateBindingContext[scopeName] = parentValue;\n                    } else {\n                      // if the parent can be assigned then do so\n                      parentSet(scope, parentValue = isolateBindingContext[scopeName]);\n                    }\n                  }\n                  return lastValue = parentValue;\n                };\n                parentValueWatch.$stateful = true;\n                var unwatch;\n                if (definition.collection) {\n                  unwatch = scope.$watchCollection(attrs[attrName], parentValueWatch);\n                } else {\n                  unwatch = scope.$watch($parse(attrs[attrName], parentValueWatch), null, parentGet.literal);\n                }\n                isolateScope.$on('$destroy', unwatch);\n                break;\n\n              case '&':\n                parentGet = $parse(attrs[attrName]);\n                isolateBindingContext[scopeName] = function(locals) {\n                  return parentGet(scope, locals);\n                };\n                break;\n            }\n          });\n        }\n        if (controllers) {\n          forEach(controllers, function(controller) {\n            controller();\n          });\n          controllers = null;\n        }\n\n        // PRELINKING\n        for (i = 0, ii = preLinkFns.length; i < ii; i++) {\n          linkFn = preLinkFns[i];\n          invokeLinkFn(linkFn,\n              linkFn.isolateScope ? isolateScope : scope,\n              $element,\n              attrs,\n              linkFn.require && getControllers(linkFn.directiveName, linkFn.require, $element, elementControllers),\n              transcludeFn\n          );\n        }\n\n        // RECURSION\n        // We only pass the isolate scope, if the isolate directive has a template,\n        // otherwise the child elements do not belong to the isolate directive.\n        var scopeToChild = scope;\n        if (newIsolateScopeDirective && (newIsolateScopeDirective.template || newIsolateScopeDirective.templateUrl === null)) {\n          scopeToChild = isolateScope;\n        }\n        childLinkFn && childLinkFn(scopeToChild, linkNode.childNodes, undefined, boundTranscludeFn);\n\n        // POSTLINKING\n        for (i = postLinkFns.length - 1; i >= 0; i--) {\n          linkFn = postLinkFns[i];\n          invokeLinkFn(linkFn,\n              linkFn.isolateScope ? isolateScope : scope,\n              $element,\n              attrs,\n              linkFn.require && getControllers(linkFn.directiveName, linkFn.require, $element, elementControllers),\n              transcludeFn\n          );\n        }\n\n        // This is the function that is injected as `$transclude`.\n        // Note: all arguments are optional!\n        function controllersBoundTransclude(scope, cloneAttachFn, futureParentElement) {\n          var transcludeControllers;\n\n          // No scope passed in:\n          if (!isScope(scope)) {\n            futureParentElement = cloneAttachFn;\n            cloneAttachFn = scope;\n            scope = undefined;\n          }\n\n          if (hasElementTranscludeDirective) {\n            transcludeControllers = elementControllers;\n          }\n          if (!futureParentElement) {\n            futureParentElement = hasElementTranscludeDirective ? $element.parent() : $element;\n          }\n          return boundTranscludeFn(scope, cloneAttachFn, transcludeControllers, futureParentElement, scopeToChild);\n        }\n      }\n    }\n\n    function markDirectivesAsIsolate(directives) {\n      // mark all directives as needing isolate scope.\n      for (var j = 0, jj = directives.length; j < jj; j++) {\n        directives[j] = inherit(directives[j], {$$isolateScope: true});\n      }\n    }\n\n    /**\n     * looks up the directive and decorates it with exception handling and proper parameters. We\n     * call this the boundDirective.\n     *\n     * @param {string} name name of the directive to look up.\n     * @param {string} location The directive must be found in specific format.\n     *   String containing any of theses characters:\n     *\n     *   * `E`: element name\n     *   * `A': attribute\n     *   * `C`: class\n     *   * `M`: comment\n     * @returns {boolean} true if directive was added.\n     */\n    function addDirective(tDirectives, name, location, maxPriority, ignoreDirective, startAttrName,\n                          endAttrName) {\n      if (name === ignoreDirective) return null;\n      var match = null;\n      if (hasDirectives.hasOwnProperty(name)) {\n        for (var directive, directives = $injector.get(name + Suffix),\n            i = 0, ii = directives.length; i < ii; i++) {\n          try {\n            directive = directives[i];\n            if ((maxPriority === undefined || maxPriority > directive.priority) &&\n                 directive.restrict.indexOf(location) != -1) {\n              if (startAttrName) {\n                directive = inherit(directive, {$$start: startAttrName, $$end: endAttrName});\n              }\n              tDirectives.push(directive);\n              match = directive;\n            }\n          } catch (e) { $exceptionHandler(e); }\n        }\n      }\n      return match;\n    }\n\n\n    /**\n     * looks up the directive and returns true if it is a multi-element directive,\n     * and therefore requires DOM nodes between -start and -end markers to be grouped\n     * together.\n     *\n     * @param {string} name name of the directive to look up.\n     * @returns true if directive was registered as multi-element.\n     */\n    function directiveIsMultiElement(name) {\n      if (hasDirectives.hasOwnProperty(name)) {\n        for (var directive, directives = $injector.get(name + Suffix),\n            i = 0, ii = directives.length; i < ii; i++) {\n          directive = directives[i];\n          if (directive.multiElement) {\n            return true;\n          }\n        }\n      }\n      return false;\n    }\n\n    /**\n     * When the element is replaced with HTML template then the new attributes\n     * on the template need to be merged with the existing attributes in the DOM.\n     * The desired effect is to have both of the attributes present.\n     *\n     * @param {object} dst destination attributes (original DOM)\n     * @param {object} src source attributes (from the directive template)\n     */\n    function mergeTemplateAttributes(dst, src) {\n      var srcAttr = src.$attr,\n          dstAttr = dst.$attr,\n          $element = dst.$$element;\n\n      // reapply the old attributes to the new element\n      forEach(dst, function(value, key) {\n        if (key.charAt(0) != '$') {\n          if (src[key] && src[key] !== value) {\n            value += (key === 'style' ? ';' : ' ') + src[key];\n          }\n          dst.$set(key, value, true, srcAttr[key]);\n        }\n      });\n\n      // copy the new attributes on the old attrs object\n      forEach(src, function(value, key) {\n        if (key == 'class') {\n          safeAddClass($element, value);\n          dst['class'] = (dst['class'] ? dst['class'] + ' ' : '') + value;\n        } else if (key == 'style') {\n          $element.attr('style', $element.attr('style') + ';' + value);\n          dst['style'] = (dst['style'] ? dst['style'] + ';' : '') + value;\n          // `dst` will never contain hasOwnProperty as DOM parser won't let it.\n          // You will get an \"InvalidCharacterError: DOM Exception 5\" error if you\n          // have an attribute like \"has-own-property\" or \"data-has-own-property\", etc.\n        } else if (key.charAt(0) != '$' && !dst.hasOwnProperty(key)) {\n          dst[key] = value;\n          dstAttr[key] = srcAttr[key];\n        }\n      });\n    }\n\n\n    function compileTemplateUrl(directives, $compileNode, tAttrs,\n        $rootElement, childTranscludeFn, preLinkFns, postLinkFns, previousCompileContext) {\n      var linkQueue = [],\n          afterTemplateNodeLinkFn,\n          afterTemplateChildLinkFn,\n          beforeTemplateCompileNode = $compileNode[0],\n          origAsyncDirective = directives.shift(),\n          derivedSyncDirective = inherit(origAsyncDirective, {\n            templateUrl: null, transclude: null, replace: null, $$originalDirective: origAsyncDirective\n          }),\n          templateUrl = (isFunction(origAsyncDirective.templateUrl))\n              ? origAsyncDirective.templateUrl($compileNode, tAttrs)\n              : origAsyncDirective.templateUrl,\n          templateNamespace = origAsyncDirective.templateNamespace;\n\n      $compileNode.empty();\n\n      $templateRequest($sce.getTrustedResourceUrl(templateUrl))\n        .then(function(content) {\n          var compileNode, tempTemplateAttrs, $template, childBoundTranscludeFn;\n\n          content = denormalizeTemplate(content);\n\n          if (origAsyncDirective.replace) {\n            if (jqLiteIsTextNode(content)) {\n              $template = [];\n            } else {\n              $template = removeComments(wrapTemplate(templateNamespace, trim(content)));\n            }\n            compileNode = $template[0];\n\n            if ($template.length != 1 || compileNode.nodeType !== NODE_TYPE_ELEMENT) {\n              throw $compileMinErr('tplrt',\n                  \"Template for directive '{0}' must have exactly one root element. {1}\",\n                  origAsyncDirective.name, templateUrl);\n            }\n\n            tempTemplateAttrs = {$attr: {}};\n            replaceWith($rootElement, $compileNode, compileNode);\n            var templateDirectives = collectDirectives(compileNode, [], tempTemplateAttrs);\n\n            if (isObject(origAsyncDirective.scope)) {\n              markDirectivesAsIsolate(templateDirectives);\n            }\n            directives = templateDirectives.concat(directives);\n            mergeTemplateAttributes(tAttrs, tempTemplateAttrs);\n          } else {\n            compileNode = beforeTemplateCompileNode;\n            $compileNode.html(content);\n          }\n\n          directives.unshift(derivedSyncDirective);\n\n          afterTemplateNodeLinkFn = applyDirectivesToNode(directives, compileNode, tAttrs,\n              childTranscludeFn, $compileNode, origAsyncDirective, preLinkFns, postLinkFns,\n              previousCompileContext);\n          forEach($rootElement, function(node, i) {\n            if (node == compileNode) {\n              $rootElement[i] = $compileNode[0];\n            }\n          });\n          afterTemplateChildLinkFn = compileNodes($compileNode[0].childNodes, childTranscludeFn);\n\n          while (linkQueue.length) {\n            var scope = linkQueue.shift(),\n                beforeTemplateLinkNode = linkQueue.shift(),\n                linkRootElement = linkQueue.shift(),\n                boundTranscludeFn = linkQueue.shift(),\n                linkNode = $compileNode[0];\n\n            if (scope.$$destroyed) continue;\n\n            if (beforeTemplateLinkNode !== beforeTemplateCompileNode) {\n              var oldClasses = beforeTemplateLinkNode.className;\n\n              if (!(previousCompileContext.hasElementTranscludeDirective &&\n                  origAsyncDirective.replace)) {\n                // it was cloned therefore we have to clone as well.\n                linkNode = jqLiteClone(compileNode);\n              }\n              replaceWith(linkRootElement, jqLite(beforeTemplateLinkNode), linkNode);\n\n              // Copy in CSS classes from original node\n              safeAddClass(jqLite(linkNode), oldClasses);\n            }\n            if (afterTemplateNodeLinkFn.transcludeOnThisElement) {\n              childBoundTranscludeFn = createBoundTranscludeFn(scope, afterTemplateNodeLinkFn.transclude, boundTranscludeFn);\n            } else {\n              childBoundTranscludeFn = boundTranscludeFn;\n            }\n            afterTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, linkNode, $rootElement,\n              childBoundTranscludeFn);\n          }\n          linkQueue = null;\n        });\n\n      return function delayedNodeLinkFn(ignoreChildLinkFn, scope, node, rootElement, boundTranscludeFn) {\n        var childBoundTranscludeFn = boundTranscludeFn;\n        if (scope.$$destroyed) return;\n        if (linkQueue) {\n          linkQueue.push(scope,\n                         node,\n                         rootElement,\n                         childBoundTranscludeFn);\n        } else {\n          if (afterTemplateNodeLinkFn.transcludeOnThisElement) {\n            childBoundTranscludeFn = createBoundTranscludeFn(scope, afterTemplateNodeLinkFn.transclude, boundTranscludeFn);\n          }\n          afterTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, node, rootElement, childBoundTranscludeFn);\n        }\n      };\n    }\n\n\n    /**\n     * Sorting function for bound directives.\n     */\n    function byPriority(a, b) {\n      var diff = b.priority - a.priority;\n      if (diff !== 0) return diff;\n      if (a.name !== b.name) return (a.name < b.name) ? -1 : 1;\n      return a.index - b.index;\n    }\n\n\n    function assertNoDuplicate(what, previousDirective, directive, element) {\n      if (previousDirective) {\n        throw $compileMinErr('multidir', 'Multiple directives [{0}, {1}] asking for {2} on: {3}',\n            previousDirective.name, directive.name, what, startingTag(element));\n      }\n    }\n\n\n    function addTextInterpolateDirective(directives, text) {\n      var interpolateFn = $interpolate(text, true);\n      if (interpolateFn) {\n        directives.push({\n          priority: 0,\n          compile: function textInterpolateCompileFn(templateNode) {\n            var templateNodeParent = templateNode.parent(),\n                hasCompileParent = !!templateNodeParent.length;\n\n            // When transcluding a template that has bindings in the root\n            // we don't have a parent and thus need to add the class during linking fn.\n            if (hasCompileParent) compile.$$addBindingClass(templateNodeParent);\n\n            return function textInterpolateLinkFn(scope, node) {\n              var parent = node.parent();\n              if (!hasCompileParent) compile.$$addBindingClass(parent);\n              compile.$$addBindingInfo(parent, interpolateFn.expressions);\n              scope.$watch(interpolateFn, function interpolateFnWatchAction(value) {\n                node[0].nodeValue = value;\n              });\n            };\n          }\n        });\n      }\n    }\n\n\n    function wrapTemplate(type, template) {\n      type = lowercase(type || 'html');\n      switch (type) {\n      case 'svg':\n      case 'math':\n        var wrapper = document.createElement('div');\n        wrapper.innerHTML = '<' + type + '>' + template + '</' + type + '>';\n        return wrapper.childNodes[0].childNodes;\n      default:\n        return template;\n      }\n    }\n\n\n    function getTrustedContext(node, attrNormalizedName) {\n      if (attrNormalizedName == \"srcdoc\") {\n        return $sce.HTML;\n      }\n      var tag = nodeName_(node);\n      // maction[xlink:href] can source SVG.  It's not limited to <maction>.\n      if (attrNormalizedName == \"xlinkHref\" ||\n          (tag == \"form\" && attrNormalizedName == \"action\") ||\n          (tag != \"img\" && (attrNormalizedName == \"src\" ||\n                            attrNormalizedName == \"ngSrc\"))) {\n        return $sce.RESOURCE_URL;\n      }\n    }\n\n\n    function addAttrInterpolateDirective(node, directives, value, name, allOrNothing) {\n      var trustedContext = getTrustedContext(node, name);\n      allOrNothing = ALL_OR_NOTHING_ATTRS[name] || allOrNothing;\n\n      var interpolateFn = $interpolate(value, true, trustedContext, allOrNothing);\n\n      // no interpolation found -> ignore\n      if (!interpolateFn) return;\n\n\n      if (name === \"multiple\" && nodeName_(node) === \"select\") {\n        throw $compileMinErr(\"selmulti\",\n            \"Binding to the 'multiple' attribute is not supported. Element: {0}\",\n            startingTag(node));\n      }\n\n      directives.push({\n        priority: 100,\n        compile: function() {\n            return {\n              pre: function attrInterpolatePreLinkFn(scope, element, attr) {\n                var $$observers = (attr.$$observers || (attr.$$observers = {}));\n\n                if (EVENT_HANDLER_ATTR_REGEXP.test(name)) {\n                  throw $compileMinErr('nodomevents',\n                      \"Interpolations for HTML DOM event attributes are disallowed.  Please use the \" +\n                          \"ng- versions (such as ng-click instead of onclick) instead.\");\n                }\n\n                // If the attribute has changed since last $interpolate()ed\n                var newValue = attr[name];\n                if (newValue !== value) {\n                  // we need to interpolate again since the attribute value has been updated\n                  // (e.g. by another directive's compile function)\n                  // ensure unset/empty values make interpolateFn falsy\n                  interpolateFn = newValue && $interpolate(newValue, true, trustedContext, allOrNothing);\n                  value = newValue;\n                }\n\n                // if attribute was updated so that there is no interpolation going on we don't want to\n                // register any observers\n                if (!interpolateFn) return;\n\n                // initialize attr object so that it's ready in case we need the value for isolate\n                // scope initialization, otherwise the value would not be available from isolate\n                // directive's linking fn during linking phase\n                attr[name] = interpolateFn(scope);\n\n                ($$observers[name] || ($$observers[name] = [])).$$inter = true;\n                (attr.$$observers && attr.$$observers[name].$$scope || scope).\n                  $watch(interpolateFn, function interpolateFnWatchAction(newValue, oldValue) {\n                    //special case for class attribute addition + removal\n                    //so that class changes can tap into the animation\n                    //hooks provided by the $animate service. Be sure to\n                    //skip animations when the first digest occurs (when\n                    //both the new and the old values are the same) since\n                    //the CSS classes are the non-interpolated values\n                    if (name === 'class' && newValue != oldValue) {\n                      attr.$updateClass(newValue, oldValue);\n                    } else {\n                      attr.$set(name, newValue);\n                    }\n                  });\n              }\n            };\n          }\n      });\n    }\n\n\n    /**\n     * This is a special jqLite.replaceWith, which can replace items which\n     * have no parents, provided that the containing jqLite collection is provided.\n     *\n     * @param {JqLite=} $rootElement The root of the compile tree. Used so that we can replace nodes\n     *                               in the root of the tree.\n     * @param {JqLite} elementsToRemove The jqLite element which we are going to replace. We keep\n     *                                  the shell, but replace its DOM node reference.\n     * @param {Node} newNode The new DOM node.\n     */\n    function replaceWith($rootElement, elementsToRemove, newNode) {\n      var firstElementToRemove = elementsToRemove[0],\n          removeCount = elementsToRemove.length,\n          parent = firstElementToRemove.parentNode,\n          i, ii;\n\n      if ($rootElement) {\n        for (i = 0, ii = $rootElement.length; i < ii; i++) {\n          if ($rootElement[i] == firstElementToRemove) {\n            $rootElement[i++] = newNode;\n            for (var j = i, j2 = j + removeCount - 1,\n                     jj = $rootElement.length;\n                 j < jj; j++, j2++) {\n              if (j2 < jj) {\n                $rootElement[j] = $rootElement[j2];\n              } else {\n                delete $rootElement[j];\n              }\n            }\n            $rootElement.length -= removeCount - 1;\n\n            // If the replaced element is also the jQuery .context then replace it\n            // .context is a deprecated jQuery api, so we should set it only when jQuery set it\n            // http://api.jquery.com/context/\n            if ($rootElement.context === firstElementToRemove) {\n              $rootElement.context = newNode;\n            }\n            break;\n          }\n        }\n      }\n\n      if (parent) {\n        parent.replaceChild(newNode, firstElementToRemove);\n      }\n\n      // TODO(perf): what's this document fragment for? is it needed? can we at least reuse it?\n      var fragment = document.createDocumentFragment();\n      fragment.appendChild(firstElementToRemove);\n\n      // Copy over user data (that includes Angular's $scope etc.). Don't copy private\n      // data here because there's no public interface in jQuery to do that and copying over\n      // event listeners (which is the main use of private data) wouldn't work anyway.\n      jqLite(newNode).data(jqLite(firstElementToRemove).data());\n\n      // Remove data of the replaced element. We cannot just call .remove()\n      // on the element it since that would deallocate scope that is needed\n      // for the new node. Instead, remove the data \"manually\".\n      if (!jQuery) {\n        delete jqLite.cache[firstElementToRemove[jqLite.expando]];\n      } else {\n        // jQuery 2.x doesn't expose the data storage. Use jQuery.cleanData to clean up after\n        // the replaced element. The cleanData version monkey-patched by Angular would cause\n        // the scope to be trashed and we do need the very same scope to work with the new\n        // element. However, we cannot just cache the non-patched version and use it here as\n        // that would break if another library patches the method after Angular does (one\n        // example is jQuery UI). Instead, set a flag indicating scope destroying should be\n        // skipped this one time.\n        skipDestroyOnNextJQueryCleanData = true;\n        jQuery.cleanData([firstElementToRemove]);\n      }\n\n      for (var k = 1, kk = elementsToRemove.length; k < kk; k++) {\n        var element = elementsToRemove[k];\n        jqLite(element).remove(); // must do this way to clean up expando\n        fragment.appendChild(element);\n        delete elementsToRemove[k];\n      }\n\n      elementsToRemove[0] = newNode;\n      elementsToRemove.length = 1;\n    }\n\n\n    function cloneAndAnnotateFn(fn, annotation) {\n      return extend(function() { return fn.apply(null, arguments); }, fn, annotation);\n    }\n\n\n    function invokeLinkFn(linkFn, scope, $element, attrs, controllers, transcludeFn) {\n      try {\n        linkFn(scope, $element, attrs, controllers, transcludeFn);\n      } catch (e) {\n        $exceptionHandler(e, startingTag($element));\n      }\n    }\n  }];\n}\n\nvar PREFIX_REGEXP = /^((?:x|data)[\\:\\-_])/i;\n/**\n * Converts all accepted directives format into proper directive name.\n * @param name Name to normalize\n */\nfunction directiveNormalize(name) {\n  return camelCase(name.replace(PREFIX_REGEXP, ''));\n}\n\n/**\n * @ngdoc type\n * @name $compile.directive.Attributes\n *\n * @description\n * A shared object between directive compile / linking functions which contains normalized DOM\n * element attributes. The values reflect current binding state `{{ }}`. The normalization is\n * needed since all of these are treated as equivalent in Angular:\n *\n * ```\n *    <span ng:bind=\"a\" ng-bind=\"a\" data-ng-bind=\"a\" x-ng-bind=\"a\">\n * ```\n */\n\n/**\n * @ngdoc property\n * @name $compile.directive.Attributes#$attr\n *\n * @description\n * A map of DOM element attribute names to the normalized name. This is\n * needed to do reverse lookup from normalized name back to actual name.\n */\n\n\n/**\n * @ngdoc method\n * @name $compile.directive.Attributes#$set\n * @kind function\n *\n * @description\n * Set DOM element attribute value.\n *\n *\n * @param {string} name Normalized element attribute name of the property to modify. The name is\n *          reverse-translated using the {@link ng.$compile.directive.Attributes#$attr $attr}\n *          property to the original name.\n * @param {string} value Value to set the attribute to. The value can be an interpolated string.\n */\n\n\n\n/**\n * Closure compiler type information\n */\n\nfunction nodesetLinkingFn(\n  /* angular.Scope */ scope,\n  /* NodeList */ nodeList,\n  /* Element */ rootElement,\n  /* function(Function) */ boundTranscludeFn\n) {}\n\nfunction directiveLinkingFn(\n  /* nodesetLinkingFn */ nodesetLinkingFn,\n  /* angular.Scope */ scope,\n  /* Node */ node,\n  /* Element */ rootElement,\n  /* function(Function) */ boundTranscludeFn\n) {}\n\nfunction tokenDifference(str1, str2) {\n  var values = '',\n      tokens1 = str1.split(/\\s+/),\n      tokens2 = str2.split(/\\s+/);\n\n  outer:\n  for (var i = 0; i < tokens1.length; i++) {\n    var token = tokens1[i];\n    for (var j = 0; j < tokens2.length; j++) {\n      if (token == tokens2[j]) continue outer;\n    }\n    values += (values.length > 0 ? ' ' : '') + token;\n  }\n  return values;\n}\n\nfunction removeComments(jqNodes) {\n  jqNodes = jqLite(jqNodes);\n  var i = jqNodes.length;\n\n  if (i <= 1) {\n    return jqNodes;\n  }\n\n  while (i--) {\n    var node = jqNodes[i];\n    if (node.nodeType === NODE_TYPE_COMMENT) {\n      splice.call(jqNodes, i, 1);\n    }\n  }\n  return jqNodes;\n}\n\nvar $controllerMinErr = minErr('$controller');\n\n/**\n * @ngdoc provider\n * @name $controllerProvider\n * @description\n * The {@link ng.$controller $controller service} is used by Angular to create new\n * controllers.\n *\n * This provider allows controller registration via the\n * {@link ng.$controllerProvider#register register} method.\n */\nfunction $ControllerProvider() {\n  var controllers = {},\n      globals = false,\n      CNTRL_REG = /^(\\S+)(\\s+as\\s+(\\w+))?$/;\n\n\n  /**\n   * @ngdoc method\n   * @name $controllerProvider#register\n   * @param {string|Object} name Controller name, or an object map of controllers where the keys are\n   *    the names and the values are the constructors.\n   * @param {Function|Array} constructor Controller constructor fn (optionally decorated with DI\n   *    annotations in the array notation).\n   */\n  this.register = function(name, constructor) {\n    assertNotHasOwnProperty(name, 'controller');\n    if (isObject(name)) {\n      extend(controllers, name);\n    } else {\n      controllers[name] = constructor;\n    }\n  };\n\n  /**\n   * @ngdoc method\n   * @name $controllerProvider#allowGlobals\n   * @description If called, allows `$controller` to find controller constructors on `window`\n   */\n  this.allowGlobals = function() {\n    globals = true;\n  };\n\n\n  this.$get = ['$injector', '$window', function($injector, $window) {\n\n    /**\n     * @ngdoc service\n     * @name $controller\n     * @requires $injector\n     *\n     * @param {Function|string} constructor If called with a function then it's considered to be the\n     *    controller constructor function. Otherwise it's considered to be a string which is used\n     *    to retrieve the controller constructor using the following steps:\n     *\n     *    * check if a controller with given name is registered via `$controllerProvider`\n     *    * check if evaluating the string on the current scope returns a constructor\n     *    * if $controllerProvider#allowGlobals, check `window[constructor]` on the global\n     *      `window` object (not recommended)\n     *\n     *    The string can use the `controller as property` syntax, where the controller instance is published\n     *    as the specified property on the `scope`; the `scope` must be injected into `locals` param for this\n     *    to work correctly.\n     *\n     * @param {Object} locals Injection locals for Controller.\n     * @return {Object} Instance of given controller.\n     *\n     * @description\n     * `$controller` service is responsible for instantiating controllers.\n     *\n     * It's just a simple call to {@link auto.$injector $injector}, but extracted into\n     * a service, so that one can override this service with [BC version](https://gist.github.com/1649788).\n     */\n    return function(expression, locals, later, ident) {\n      // PRIVATE API:\n      //   param `later` --- indicates that the controller's constructor is invoked at a later time.\n      //                     If true, $controller will allocate the object with the correct\n      //                     prototype chain, but will not invoke the controller until a returned\n      //                     callback is invoked.\n      //   param `ident` --- An optional label which overrides the label parsed from the controller\n      //                     expression, if any.\n      var instance, match, constructor, identifier;\n      later = later === true;\n      if (ident && isString(ident)) {\n        identifier = ident;\n      }\n\n      if (isString(expression)) {\n        match = expression.match(CNTRL_REG);\n        if (!match) {\n          throw $controllerMinErr('ctrlfmt',\n            \"Badly formed controller string '{0}'. \" +\n            \"Must match `__name__ as __id__` or `__name__`.\", expression);\n        }\n        constructor = match[1],\n        identifier = identifier || match[3];\n        expression = controllers.hasOwnProperty(constructor)\n            ? controllers[constructor]\n            : getter(locals.$scope, constructor, true) ||\n                (globals ? getter($window, constructor, true) : undefined);\n\n        assertArgFn(expression, constructor, true);\n      }\n\n      if (later) {\n        // Instantiate controller later:\n        // This machinery is used to create an instance of the object before calling the\n        // controller's constructor itself.\n        //\n        // This allows properties to be added to the controller before the constructor is\n        // invoked. Primarily, this is used for isolate scope bindings in $compile.\n        //\n        // This feature is not intended for use by applications, and is thus not documented\n        // publicly.\n        // Object creation: http://jsperf.com/create-constructor/2\n        var controllerPrototype = (isArray(expression) ?\n          expression[expression.length - 1] : expression).prototype;\n        instance = Object.create(controllerPrototype || null);\n\n        if (identifier) {\n          addIdentifier(locals, identifier, instance, constructor || expression.name);\n        }\n\n        return extend(function() {\n          $injector.invoke(expression, instance, locals, constructor);\n          return instance;\n        }, {\n          instance: instance,\n          identifier: identifier\n        });\n      }\n\n      instance = $injector.instantiate(expression, locals, constructor);\n\n      if (identifier) {\n        addIdentifier(locals, identifier, instance, constructor || expression.name);\n      }\n\n      return instance;\n    };\n\n    function addIdentifier(locals, identifier, instance, name) {\n      if (!(locals && isObject(locals.$scope))) {\n        throw minErr('$controller')('noscp',\n          \"Cannot export controller '{0}' as '{1}'! No $scope object provided via `locals`.\",\n          name, identifier);\n      }\n\n      locals.$scope[identifier] = instance;\n    }\n  }];\n}\n\n/**\n * @ngdoc service\n * @name $document\n * @requires $window\n *\n * @description\n * A {@link angular.element jQuery or jqLite} wrapper for the browser's `window.document` object.\n *\n * @example\n   <example module=\"documentExample\">\n     <file name=\"index.html\">\n       <div ng-controller=\"ExampleController\">\n         <p>$document title: <b ng-bind=\"title\"></b></p>\n         <p>window.document title: <b ng-bind=\"windowTitle\"></b></p>\n       </div>\n     </file>\n     <file name=\"script.js\">\n       angular.module('documentExample', [])\n         .controller('ExampleController', ['$scope', '$document', function($scope, $document) {\n           $scope.title = $document[0].title;\n           $scope.windowTitle = angular.element(window.document)[0].title;\n         }]);\n     </file>\n   </example>\n */\nfunction $DocumentProvider() {\n  this.$get = ['$window', function(window) {\n    return jqLite(window.document);\n  }];\n}\n\n/**\n * @ngdoc service\n * @name $exceptionHandler\n * @requires ng.$log\n *\n * @description\n * Any uncaught exception in angular expressions is delegated to this service.\n * The default implementation simply delegates to `$log.error` which logs it into\n * the browser console.\n *\n * In unit tests, if `angular-mocks.js` is loaded, this service is overridden by\n * {@link ngMock.$exceptionHandler mock $exceptionHandler} which aids in testing.\n *\n * ## Example:\n *\n * ```js\n *   angular.module('exceptionOverride', []).factory('$exceptionHandler', function() {\n *     return function(exception, cause) {\n *       exception.message += ' (caused by \"' + cause + '\")';\n *       throw exception;\n *     };\n *   });\n * ```\n *\n * This example will override the normal action of `$exceptionHandler`, to make angular\n * exceptions fail hard when they happen, instead of just logging to the console.\n *\n * <hr />\n * Note, that code executed in event-listeners (even those registered using jqLite's `on`/`bind`\n * methods) does not delegate exceptions to the {@link ng.$exceptionHandler $exceptionHandler}\n * (unless executed during a digest).\n *\n * If you wish, you can manually delegate exceptions, e.g.\n * `try { ... } catch(e) { $exceptionHandler(e); }`\n *\n * @param {Error} exception Exception associated with the error.\n * @param {string=} cause optional information about the context in which\n *       the error was thrown.\n *\n */\nfunction $ExceptionHandlerProvider() {\n  this.$get = ['$log', function($log) {\n    return function(exception, cause) {\n      $log.error.apply($log, arguments);\n    };\n  }];\n}\n\nvar APPLICATION_JSON = 'application/json';\nvar CONTENT_TYPE_APPLICATION_JSON = {'Content-Type': APPLICATION_JSON + ';charset=utf-8'};\nvar JSON_START = /^\\[|^\\{(?!\\{)/;\nvar JSON_ENDS = {\n  '[': /]$/,\n  '{': /}$/\n};\nvar JSON_PROTECTION_PREFIX = /^\\)\\]\\}',?\\n/;\n\nfunction defaultHttpResponseTransform(data, headers) {\n  if (isString(data)) {\n    // Strip json vulnerability protection prefix and trim whitespace\n    var tempData = data.replace(JSON_PROTECTION_PREFIX, '').trim();\n\n    if (tempData) {\n      var contentType = headers('Content-Type');\n      if ((contentType && (contentType.indexOf(APPLICATION_JSON) === 0)) || isJsonLike(tempData)) {\n        data = fromJson(tempData);\n      }\n    }\n  }\n\n  return data;\n}\n\nfunction isJsonLike(str) {\n    var jsonStart = str.match(JSON_START);\n    return jsonStart && JSON_ENDS[jsonStart[0]].test(str);\n}\n\n/**\n * Parse headers into key value object\n *\n * @param {string} headers Raw headers as a string\n * @returns {Object} Parsed headers as key value object\n */\nfunction parseHeaders(headers) {\n  var parsed = createMap(), key, val, i;\n\n  if (!headers) return parsed;\n\n  forEach(headers.split('\\n'), function(line) {\n    i = line.indexOf(':');\n    key = lowercase(trim(line.substr(0, i)));\n    val = trim(line.substr(i + 1));\n\n    if (key) {\n      parsed[key] = parsed[key] ? parsed[key] + ', ' + val : val;\n    }\n  });\n\n  return parsed;\n}\n\n\n/**\n * Returns a function that provides access to parsed headers.\n *\n * Headers are lazy parsed when first requested.\n * @see parseHeaders\n *\n * @param {(string|Object)} headers Headers to provide access to.\n * @returns {function(string=)} Returns a getter function which if called with:\n *\n *   - if called with single an argument returns a single header value or null\n *   - if called with no arguments returns an object containing all headers.\n */\nfunction headersGetter(headers) {\n  var headersObj = isObject(headers) ? headers : undefined;\n\n  return function(name) {\n    if (!headersObj) headersObj =  parseHeaders(headers);\n\n    if (name) {\n      var value = headersObj[lowercase(name)];\n      if (value === void 0) {\n        value = null;\n      }\n      return value;\n    }\n\n    return headersObj;\n  };\n}\n\n\n/**\n * Chain all given functions\n *\n * This function is used for both request and response transforming\n *\n * @param {*} data Data to transform.\n * @param {function(string=)} headers HTTP headers getter fn.\n * @param {number} status HTTP status code of the response.\n * @param {(Function|Array.<Function>)} fns Function or an array of functions.\n * @returns {*} Transformed data.\n */\nfunction transformData(data, headers, status, fns) {\n  if (isFunction(fns))\n    return fns(data, headers, status);\n\n  forEach(fns, function(fn) {\n    data = fn(data, headers, status);\n  });\n\n  return data;\n}\n\n\nfunction isSuccess(status) {\n  return 200 <= status && status < 300;\n}\n\n\n/**\n * @ngdoc provider\n * @name $httpProvider\n * @description\n * Use `$httpProvider` to change the default behavior of the {@link ng.$http $http} service.\n * */\nfunction $HttpProvider() {\n  /**\n   * @ngdoc property\n   * @name $httpProvider#defaults\n   * @description\n   *\n   * Object containing default values for all {@link ng.$http $http} requests.\n   *\n   * - **`defaults.cache`** - {Object} - an object built with {@link ng.$cacheFactory `$cacheFactory`}\n   * that will provide the cache for all requests who set their `cache` property to `true`.\n   * If you set the `default.cache = false` then only requests that specify their own custom\n   * cache object will be cached. See {@link $http#caching $http Caching} for more information.\n   *\n   * - **`defaults.xsrfCookieName`** - {string} - Name of cookie containing the XSRF token.\n   * Defaults value is `'XSRF-TOKEN'`.\n   *\n   * - **`defaults.xsrfHeaderName`** - {string} - Name of HTTP header to populate with the\n   * XSRF token. Defaults value is `'X-XSRF-TOKEN'`.\n   *\n   * - **`defaults.headers`** - {Object} - Default headers for all $http requests.\n   * Refer to {@link ng.$http#setting-http-headers $http} for documentation on\n   * setting default headers.\n   *     - **`defaults.headers.common`**\n   *     - **`defaults.headers.post`**\n   *     - **`defaults.headers.put`**\n   *     - **`defaults.headers.patch`**\n   *\n   **/\n  var defaults = this.defaults = {\n    // transform incoming response data\n    transformResponse: [defaultHttpResponseTransform],\n\n    // transform outgoing request data\n    transformRequest: [function(d) {\n      return isObject(d) && !isFile(d) && !isBlob(d) && !isFormData(d) ? toJson(d) : d;\n    }],\n\n    // default headers\n    headers: {\n      common: {\n        'Accept': 'application/json, text/plain, */*'\n      },\n      post:   shallowCopy(CONTENT_TYPE_APPLICATION_JSON),\n      put:    shallowCopy(CONTENT_TYPE_APPLICATION_JSON),\n      patch:  shallowCopy(CONTENT_TYPE_APPLICATION_JSON)\n    },\n\n    xsrfCookieName: 'XSRF-TOKEN',\n    xsrfHeaderName: 'X-XSRF-TOKEN'\n  };\n\n  var useApplyAsync = false;\n  /**\n   * @ngdoc method\n   * @name $httpProvider#useApplyAsync\n   * @description\n   *\n   * Configure $http service to combine processing of multiple http responses received at around\n   * the same time via {@link ng.$rootScope.Scope#$applyAsync $rootScope.$applyAsync}. This can result in\n   * significant performance improvement for bigger applications that make many HTTP requests\n   * concurrently (common during application bootstrap).\n   *\n   * Defaults to false. If no value is specifed, returns the current configured value.\n   *\n   * @param {boolean=} value If true, when requests are loaded, they will schedule a deferred\n   *    \"apply\" on the next tick, giving time for subsequent requests in a roughly ~10ms window\n   *    to load and share the same digest cycle.\n   *\n   * @returns {boolean|Object} If a value is specified, returns the $httpProvider for chaining.\n   *    otherwise, returns the current configured value.\n   **/\n  this.useApplyAsync = function(value) {\n    if (isDefined(value)) {\n      useApplyAsync = !!value;\n      return this;\n    }\n    return useApplyAsync;\n  };\n\n  /**\n   * @ngdoc property\n   * @name $httpProvider#interceptors\n   * @description\n   *\n   * Array containing service factories for all synchronous or asynchronous {@link ng.$http $http}\n   * pre-processing of request or postprocessing of responses.\n   *\n   * These service factories are ordered by request, i.e. they are applied in the same order as the\n   * array, on request, but reverse order, on response.\n   *\n   * {@link ng.$http#interceptors Interceptors detailed info}\n   **/\n  var interceptorFactories = this.interceptors = [];\n\n  this.$get = ['$httpBackend', '$browser', '$cacheFactory', '$rootScope', '$q', '$injector',\n      function($httpBackend, $browser, $cacheFactory, $rootScope, $q, $injector) {\n\n    var defaultCache = $cacheFactory('$http');\n\n    /**\n     * Interceptors stored in reverse order. Inner interceptors before outer interceptors.\n     * The reversal is needed so that we can build up the interception chain around the\n     * server request.\n     */\n    var reversedInterceptors = [];\n\n    forEach(interceptorFactories, function(interceptorFactory) {\n      reversedInterceptors.unshift(isString(interceptorFactory)\n          ? $injector.get(interceptorFactory) : $injector.invoke(interceptorFactory));\n    });\n\n    /**\n     * @ngdoc service\n     * @kind function\n     * @name $http\n     * @requires ng.$httpBackend\n     * @requires $cacheFactory\n     * @requires $rootScope\n     * @requires $q\n     * @requires $injector\n     *\n     * @description\n     * The `$http` service is a core Angular service that facilitates communication with the remote\n     * HTTP servers via the browser's [XMLHttpRequest](https://developer.mozilla.org/en/xmlhttprequest)\n     * object or via [JSONP](http://en.wikipedia.org/wiki/JSONP).\n     *\n     * For unit testing applications that use `$http` service, see\n     * {@link ngMock.$httpBackend $httpBackend mock}.\n     *\n     * For a higher level of abstraction, please check out the {@link ngResource.$resource\n     * $resource} service.\n     *\n     * The $http API is based on the {@link ng.$q deferred/promise APIs} exposed by\n     * the $q service. While for simple usage patterns this doesn't matter much, for advanced usage\n     * it is important to familiarize yourself with these APIs and the guarantees they provide.\n     *\n     *\n     * ## General usage\n     * The `$http` service is a function which takes a single argument — a configuration object —\n     * that is used to generate an HTTP request and returns  a {@link ng.$q promise}\n     * with two $http specific methods: `success` and `error`.\n     *\n     * ```js\n     *   // Simple GET request example :\n     *   $http.get('/someUrl').\n     *     success(function(data, status, headers, config) {\n     *       // this callback will be called asynchronously\n     *       // when the response is available\n     *     }).\n     *     error(function(data, status, headers, config) {\n     *       // called asynchronously if an error occurs\n     *       // or server returns response with an error status.\n     *     });\n     * ```\n     *\n     * ```js\n     *   // Simple POST request example (passing data) :\n     *   $http.post('/someUrl', {msg:'hello word!'}).\n     *     success(function(data, status, headers, config) {\n     *       // this callback will be called asynchronously\n     *       // when the response is available\n     *     }).\n     *     error(function(data, status, headers, config) {\n     *       // called asynchronously if an error occurs\n     *       // or server returns response with an error status.\n     *     });\n     * ```\n     *\n     *\n     * Since the returned value of calling the $http function is a `promise`, you can also use\n     * the `then` method to register callbacks, and these callbacks will receive a single argument –\n     * an object representing the response. See the API signature and type info below for more\n     * details.\n     *\n     * A response status code between 200 and 299 is considered a success status and\n     * will result in the success callback being called. Note that if the response is a redirect,\n     * XMLHttpRequest will transparently follow it, meaning that the error callback will not be\n     * called for such responses.\n     *\n     * ## Writing Unit Tests that use $http\n     * When unit testing (using {@link ngMock ngMock}), it is necessary to call\n     * {@link ngMock.$httpBackend#flush $httpBackend.flush()} to flush each pending\n     * request using trained responses.\n     *\n     * ```\n     * $httpBackend.expectGET(...);\n     * $http.get(...);\n     * $httpBackend.flush();\n     * ```\n     *\n     * ## Shortcut methods\n     *\n     * Shortcut methods are also available. All shortcut methods require passing in the URL, and\n     * request data must be passed in for POST/PUT requests.\n     *\n     * ```js\n     *   $http.get('/someUrl').success(successCallback);\n     *   $http.post('/someUrl', data).success(successCallback);\n     * ```\n     *\n     * Complete list of shortcut methods:\n     *\n     * - {@link ng.$http#get $http.get}\n     * - {@link ng.$http#head $http.head}\n     * - {@link ng.$http#post $http.post}\n     * - {@link ng.$http#put $http.put}\n     * - {@link ng.$http#delete $http.delete}\n     * - {@link ng.$http#jsonp $http.jsonp}\n     * - {@link ng.$http#patch $http.patch}\n     *\n     *\n     * ## Setting HTTP Headers\n     *\n     * The $http service will automatically add certain HTTP headers to all requests. These defaults\n     * can be fully configured by accessing the `$httpProvider.defaults.headers` configuration\n     * object, which currently contains this default configuration:\n     *\n     * - `$httpProvider.defaults.headers.common` (headers that are common for all requests):\n     *   - `Accept: application/json, text/plain, * / *`\n     * - `$httpProvider.defaults.headers.post`: (header defaults for POST requests)\n     *   - `Content-Type: application/json`\n     * - `$httpProvider.defaults.headers.put` (header defaults for PUT requests)\n     *   - `Content-Type: application/json`\n     *\n     * To add or overwrite these defaults, simply add or remove a property from these configuration\n     * objects. To add headers for an HTTP method other than POST or PUT, simply add a new object\n     * with the lowercased HTTP method name as the key, e.g.\n     * `$httpProvider.defaults.headers.get = { 'My-Header' : 'value' }.\n     *\n     * The defaults can also be set at runtime via the `$http.defaults` object in the same\n     * fashion. For example:\n     *\n     * ```\n     * module.run(function($http) {\n     *   $http.defaults.headers.common.Authorization = 'Basic YmVlcDpib29w'\n     * });\n     * ```\n     *\n     * In addition, you can supply a `headers` property in the config object passed when\n     * calling `$http(config)`, which overrides the defaults without changing them globally.\n     *\n     * To explicitly remove a header automatically added via $httpProvider.defaults.headers on a per request basis,\n     * Use the `headers` property, setting the desired header to `undefined`. For example:\n     *\n     * ```js\n     * var req = {\n     *  method: 'POST',\n     *  url: 'http://example.com',\n     *  headers: {\n     *    'Content-Type': undefined\n     *  },\n     *  data: { test: 'test' },\n     * }\n     *\n     * $http(req).success(function(){...}).error(function(){...});\n     * ```\n     *\n     * ## Transforming Requests and Responses\n     *\n     * Both requests and responses can be transformed using transformation functions: `transformRequest`\n     * and `transformResponse`. These properties can be a single function that returns\n     * the transformed value (`function(data, headersGetter, status)`) or an array of such transformation functions,\n     * which allows you to `push` or `unshift` a new transformation function into the transformation chain.\n     *\n     * ### Default Transformations\n     *\n     * The `$httpProvider` provider and `$http` service expose `defaults.transformRequest` and\n     * `defaults.transformResponse` properties. If a request does not provide its own transformations\n     * then these will be applied.\n     *\n     * You can augment or replace the default transformations by modifying these properties by adding to or\n     * replacing the array.\n     *\n     * Angular provides the following default transformations:\n     *\n     * Request transformations (`$httpProvider.defaults.transformRequest` and `$http.defaults.transformRequest`):\n     *\n     * - If the `data` property of the request configuration object contains an object, serialize it\n     *   into JSON format.\n     *\n     * Response transformations (`$httpProvider.defaults.transformResponse` and `$http.defaults.transformResponse`):\n     *\n     *  - If XSRF prefix is detected, strip it (see Security Considerations section below).\n     *  - If JSON response is detected, deserialize it using a JSON parser.\n     *\n     *\n     * ### Overriding the Default Transformations Per Request\n     *\n     * If you wish override the request/response transformations only for a single request then provide\n     * `transformRequest` and/or `transformResponse` properties on the configuration object passed\n     * into `$http`.\n     *\n     * Note that if you provide these properties on the config object the default transformations will be\n     * overwritten. If you wish to augment the default transformations then you must include them in your\n     * local transformation array.\n     *\n     * The following code demonstrates adding a new response transformation to be run after the default response\n     * transformations have been run.\n     *\n     * ```js\n     * function appendTransform(defaults, transform) {\n     *\n     *   // We can't guarantee that the default transformation is an array\n     *   defaults = angular.isArray(defaults) ? defaults : [defaults];\n     *\n     *   // Append the new transformation to the defaults\n     *   return defaults.concat(transform);\n     * }\n     *\n     * $http({\n     *   url: '...',\n     *   method: 'GET',\n     *   transformResponse: appendTransform($http.defaults.transformResponse, function(value) {\n     *     return doTransform(value);\n     *   })\n     * });\n     * ```\n     *\n     *\n     * ## Caching\n     *\n     * To enable caching, set the request configuration `cache` property to `true` (to use default\n     * cache) or to a custom cache object (built with {@link ng.$cacheFactory `$cacheFactory`}).\n     * When the cache is enabled, `$http` stores the response from the server in the specified\n     * cache. The next time the same request is made, the response is served from the cache without\n     * sending a request to the server.\n     *\n     * Note that even if the response is served from cache, delivery of the data is asynchronous in\n     * the same way that real requests are.\n     *\n     * If there are multiple GET requests for the same URL that should be cached using the same\n     * cache, but the cache is not populated yet, only one request to the server will be made and\n     * the remaining requests will be fulfilled using the response from the first request.\n     *\n     * You can change the default cache to a new object (built with\n     * {@link ng.$cacheFactory `$cacheFactory`}) by updating the\n     * {@link ng.$http#defaults `$http.defaults.cache`} property. All requests who set\n     * their `cache` property to `true` will now use this cache object.\n     *\n     * If you set the default cache to `false` then only requests that specify their own custom\n     * cache object will be cached.\n     *\n     * ## Interceptors\n     *\n     * Before you start creating interceptors, be sure to understand the\n     * {@link ng.$q $q and deferred/promise APIs}.\n     *\n     * For purposes of global error handling, authentication, or any kind of synchronous or\n     * asynchronous pre-processing of request or postprocessing of responses, it is desirable to be\n     * able to intercept requests before they are handed to the server and\n     * responses before they are handed over to the application code that\n     * initiated these requests. The interceptors leverage the {@link ng.$q\n     * promise APIs} to fulfill this need for both synchronous and asynchronous pre-processing.\n     *\n     * The interceptors are service factories that are registered with the `$httpProvider` by\n     * adding them to the `$httpProvider.interceptors` array. The factory is called and\n     * injected with dependencies (if specified) and returns the interceptor.\n     *\n     * There are two kinds of interceptors (and two kinds of rejection interceptors):\n     *\n     *   * `request`: interceptors get called with a http `config` object. The function is free to\n     *     modify the `config` object or create a new one. The function needs to return the `config`\n     *     object directly, or a promise containing the `config` or a new `config` object.\n     *   * `requestError`: interceptor gets called when a previous interceptor threw an error or\n     *     resolved with a rejection.\n     *   * `response`: interceptors get called with http `response` object. The function is free to\n     *     modify the `response` object or create a new one. The function needs to return the `response`\n     *     object directly, or as a promise containing the `response` or a new `response` object.\n     *   * `responseError`: interceptor gets called when a previous interceptor threw an error or\n     *     resolved with a rejection.\n     *\n     *\n     * ```js\n     *   // register the interceptor as a service\n     *   $provide.factory('myHttpInterceptor', function($q, dependency1, dependency2) {\n     *     return {\n     *       // optional method\n     *       'request': function(config) {\n     *         // do something on success\n     *         return config;\n     *       },\n     *\n     *       // optional method\n     *      'requestError': function(rejection) {\n     *         // do something on error\n     *         if (canRecover(rejection)) {\n     *           return responseOrNewPromise\n     *         }\n     *         return $q.reject(rejection);\n     *       },\n     *\n     *\n     *\n     *       // optional method\n     *       'response': function(response) {\n     *         // do something on success\n     *         return response;\n     *       },\n     *\n     *       // optional method\n     *      'responseError': function(rejection) {\n     *         // do something on error\n     *         if (canRecover(rejection)) {\n     *           return responseOrNewPromise\n     *         }\n     *         return $q.reject(rejection);\n     *       }\n     *     };\n     *   });\n     *\n     *   $httpProvider.interceptors.push('myHttpInterceptor');\n     *\n     *\n     *   // alternatively, register the interceptor via an anonymous factory\n     *   $httpProvider.interceptors.push(function($q, dependency1, dependency2) {\n     *     return {\n     *      'request': function(config) {\n     *          // same as above\n     *       },\n     *\n     *       'response': function(response) {\n     *          // same as above\n     *       }\n     *     };\n     *   });\n     * ```\n     *\n     * ## Security Considerations\n     *\n     * When designing web applications, consider security threats from:\n     *\n     * - [JSON vulnerability](http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx)\n     * - [XSRF](http://en.wikipedia.org/wiki/Cross-site_request_forgery)\n     *\n     * Both server and the client must cooperate in order to eliminate these threats. Angular comes\n     * pre-configured with strategies that address these issues, but for this to work backend server\n     * cooperation is required.\n     *\n     * ### JSON Vulnerability Protection\n     *\n     * A [JSON vulnerability](http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx)\n     * allows third party website to turn your JSON resource URL into\n     * [JSONP](http://en.wikipedia.org/wiki/JSONP) request under some conditions. To\n     * counter this your server can prefix all JSON requests with following string `\")]}',\\n\"`.\n     * Angular will automatically strip the prefix before processing it as JSON.\n     *\n     * For example if your server needs to return:\n     * ```js\n     * ['one','two']\n     * ```\n     *\n     * which is vulnerable to attack, your server can return:\n     * ```js\n     * )]}',\n     * ['one','two']\n     * ```\n     *\n     * Angular will strip the prefix, before processing the JSON.\n     *\n     *\n     * ### Cross Site Request Forgery (XSRF) Protection\n     *\n     * [XSRF](http://en.wikipedia.org/wiki/Cross-site_request_forgery) is a technique by which\n     * an unauthorized site can gain your user's private data. Angular provides a mechanism\n     * to counter XSRF. When performing XHR requests, the $http service reads a token from a cookie\n     * (by default, `XSRF-TOKEN`) and sets it as an HTTP header (`X-XSRF-TOKEN`). Since only\n     * JavaScript that runs on your domain could read the cookie, your server can be assured that\n     * the XHR came from JavaScript running on your domain. The header will not be set for\n     * cross-domain requests.\n     *\n     * To take advantage of this, your server needs to set a token in a JavaScript readable session\n     * cookie called `XSRF-TOKEN` on the first HTTP GET request. On subsequent XHR requests the\n     * server can verify that the cookie matches `X-XSRF-TOKEN` HTTP header, and therefore be sure\n     * that only JavaScript running on your domain could have sent the request. The token must be\n     * unique for each user and must be verifiable by the server (to prevent the JavaScript from\n     * making up its own tokens). We recommend that the token is a digest of your site's\n     * authentication cookie with a [salt](https://en.wikipedia.org/wiki/Salt_(cryptography&#41;)\n     * for added security.\n     *\n     * The name of the headers can be specified using the xsrfHeaderName and xsrfCookieName\n     * properties of either $httpProvider.defaults at config-time, $http.defaults at run-time,\n     * or the per-request config object.\n     *\n     *\n     * @param {object} config Object describing the request to be made and how it should be\n     *    processed. The object has following properties:\n     *\n     *    - **method** – `{string}` – HTTP method (e.g. 'GET', 'POST', etc)\n     *    - **url** – `{string}` – Absolute or relative URL of the resource that is being requested.\n     *    - **params** – `{Object.<string|Object>}` – Map of strings or objects which will be turned\n     *      to `?key1=value1&key2=value2` after the url. If the value is not a string, it will be\n     *      JSONified.\n     *    - **data** – `{string|Object}` – Data to be sent as the request message data.\n     *    - **headers** – `{Object}` – Map of strings or functions which return strings representing\n     *      HTTP headers to send to the server. If the return value of a function is null, the\n     *      header will not be sent.\n     *    - **xsrfHeaderName** – `{string}` – Name of HTTP header to populate with the XSRF token.\n     *    - **xsrfCookieName** – `{string}` – Name of cookie containing the XSRF token.\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     *      See {@link ng.$http#overriding-the-default-transformations-per-request\n     *      Overriding the Default Transformations}\n     *    - **transformResponse** –\n     *      `{function(data, headersGetter, status)|Array.<function(data, headersGetter, status)>}` –\n     *      transform function or an array of such functions. The transform function takes the http\n     *      response body, headers and status and returns its transformed (typically deserialized) version.\n     *      See {@link ng.$http#overriding-the-default-transformations-per-request\n     *      Overriding the Default Transformations}\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}\n     *      that should abort the request when resolved.\n     *    - **withCredentials** - `{boolean}` - whether to set the `withCredentials` flag on the\n     *      XHR object. See [requests with credentials](https://developer.mozilla.org/docs/Web/HTTP/Access_control_CORS#Requests_with_credentials)\n     *      for more information.\n     *    - **responseType** - `{string}` - see\n     *      [requestType](https://developer.mozilla.org/en-US/docs/DOM/XMLHttpRequest#responseType).\n     *\n     * @returns {HttpPromise} Returns a {@link ng.$q promise} object with the\n     *   standard `then` method and two http specific methods: `success` and `error`. The `then`\n     *   method takes two arguments a success and an error callback which will be called with a\n     *   response object. The `success` and `error` methods take a single argument - a function that\n     *   will be called when the request succeeds or fails respectively. The arguments passed into\n     *   these functions are destructured representation of the response object passed into the\n     *   `then` method. The response object has these properties:\n     *\n     *   - **data** – `{string|Object}` – The response body transformed with the transform\n     *     functions.\n     *   - **status** – `{number}` – HTTP status code of the response.\n     *   - **headers** – `{function([headerName])}` – Header getter function.\n     *   - **config** – `{Object}` – The configuration object that was used to generate the request.\n     *   - **statusText** – `{string}` – HTTP status text of the response.\n     *\n     * @property {Array.<Object>} pendingRequests Array of config objects for currently pending\n     *   requests. This is primarily meant to be used for debugging purposes.\n     *\n     *\n     * @example\n<example module=\"httpExample\">\n<file name=\"index.html\">\n  <div ng-controller=\"FetchController\">\n    <select ng-model=\"method\">\n      <option>GET</option>\n      <option>JSONP</option>\n    </select>\n    <input type=\"text\" ng-model=\"url\" size=\"80\"/>\n    <button id=\"fetchbtn\" ng-click=\"fetch()\">fetch</button><br>\n    <button id=\"samplegetbtn\" ng-click=\"updateModel('GET', 'http-hello.html')\">Sample GET</button>\n    <button id=\"samplejsonpbtn\"\n      ng-click=\"updateModel('JSONP',\n                    'https://angularjs.org/greet.php?callback=JSON_CALLBACK&name=Super%20Hero')\">\n      Sample JSONP\n    </button>\n    <button id=\"invalidjsonpbtn\"\n      ng-click=\"updateModel('JSONP', 'https://angularjs.org/doesntexist&callback=JSON_CALLBACK')\">\n        Invalid JSONP\n      </button>\n    <pre>http status code: {{status}}</pre>\n    <pre>http response data: {{data}}</pre>\n  </div>\n</file>\n<file name=\"script.js\">\n  angular.module('httpExample', [])\n    .controller('FetchController', ['$scope', '$http', '$templateCache',\n      function($scope, $http, $templateCache) {\n        $scope.method = 'GET';\n        $scope.url = 'http-hello.html';\n\n        $scope.fetch = function() {\n          $scope.code = null;\n          $scope.response = null;\n\n          $http({method: $scope.method, url: $scope.url, cache: $templateCache}).\n            success(function(data, status) {\n              $scope.status = status;\n              $scope.data = data;\n            }).\n            error(function(data, status) {\n              $scope.data = data || \"Request failed\";\n              $scope.status = status;\n          });\n        };\n\n        $scope.updateModel = function(method, url) {\n          $scope.method = method;\n          $scope.url = url;\n        };\n      }]);\n</file>\n<file name=\"http-hello.html\">\n  Hello, $http!\n</file>\n<file name=\"protractor.js\" type=\"protractor\">\n  var status = element(by.binding('status'));\n  var data = element(by.binding('data'));\n  var fetchBtn = element(by.id('fetchbtn'));\n  var sampleGetBtn = element(by.id('samplegetbtn'));\n  var sampleJsonpBtn = element(by.id('samplejsonpbtn'));\n  var invalidJsonpBtn = element(by.id('invalidjsonpbtn'));\n\n  it('should make an xhr GET request', function() {\n    sampleGetBtn.click();\n    fetchBtn.click();\n    expect(status.getText()).toMatch('200');\n    expect(data.getText()).toMatch(/Hello, \\$http!/);\n  });\n\n// Commented out due to flakes. See https://github.com/angular/angular.js/issues/9185\n// it('should make a JSONP request to angularjs.org', function() {\n//   sampleJsonpBtn.click();\n//   fetchBtn.click();\n//   expect(status.getText()).toMatch('200');\n//   expect(data.getText()).toMatch(/Super Hero!/);\n// });\n\n  it('should make JSONP request to invalid URL and invoke the error handler',\n      function() {\n    invalidJsonpBtn.click();\n    fetchBtn.click();\n    expect(status.getText()).toMatch('0');\n    expect(data.getText()).toMatch('Request failed');\n  });\n</file>\n</example>\n     */\n    function $http(requestConfig) {\n\n      if (!angular.isObject(requestConfig)) {\n        throw minErr('$http')('badreq', 'Http request configuration must be an object.  Received: {0}', requestConfig);\n      }\n\n      var config = extend({\n        method: 'get',\n        transformRequest: defaults.transformRequest,\n        transformResponse: defaults.transformResponse\n      }, requestConfig);\n\n      config.headers = mergeHeaders(requestConfig);\n      config.method = uppercase(config.method);\n\n      var serverRequest = function(config) {\n        var headers = config.headers;\n        var reqData = transformData(config.data, headersGetter(headers), undefined, config.transformRequest);\n\n        // strip content-type if data is undefined\n        if (isUndefined(reqData)) {\n          forEach(headers, function(value, header) {\n            if (lowercase(header) === 'content-type') {\n                delete headers[header];\n            }\n          });\n        }\n\n        if (isUndefined(config.withCredentials) && !isUndefined(defaults.withCredentials)) {\n          config.withCredentials = defaults.withCredentials;\n        }\n\n        // send request\n        return sendReq(config, reqData).then(transformResponse, transformResponse);\n      };\n\n      var chain = [serverRequest, undefined];\n      var promise = $q.when(config);\n\n      // apply interceptors\n      forEach(reversedInterceptors, function(interceptor) {\n        if (interceptor.request || interceptor.requestError) {\n          chain.unshift(interceptor.request, interceptor.requestError);\n        }\n        if (interceptor.response || interceptor.responseError) {\n          chain.push(interceptor.response, interceptor.responseError);\n        }\n      });\n\n      while (chain.length) {\n        var thenFn = chain.shift();\n        var rejectFn = chain.shift();\n\n        promise = promise.then(thenFn, rejectFn);\n      }\n\n      promise.success = function(fn) {\n        promise.then(function(response) {\n          fn(response.data, response.status, response.headers, config);\n        });\n        return promise;\n      };\n\n      promise.error = function(fn) {\n        promise.then(null, function(response) {\n          fn(response.data, response.status, response.headers, config);\n        });\n        return promise;\n      };\n\n      return promise;\n\n      function transformResponse(response) {\n        // make a copy since the response must be cacheable\n        var resp = extend({}, response);\n        if (!response.data) {\n          resp.data = response.data;\n        } else {\n          resp.data = transformData(response.data, response.headers, response.status, config.transformResponse);\n        }\n        return (isSuccess(response.status))\n          ? resp\n          : $q.reject(resp);\n      }\n\n      function executeHeaderFns(headers) {\n        var headerContent, processedHeaders = {};\n\n        forEach(headers, function(headerFn, header) {\n          if (isFunction(headerFn)) {\n            headerContent = headerFn();\n            if (headerContent != null) {\n              processedHeaders[header] = headerContent;\n            }\n          } else {\n            processedHeaders[header] = headerFn;\n          }\n        });\n\n        return processedHeaders;\n      }\n\n      function mergeHeaders(config) {\n        var defHeaders = defaults.headers,\n            reqHeaders = extend({}, config.headers),\n            defHeaderName, lowercaseDefHeaderName, reqHeaderName;\n\n        defHeaders = extend({}, defHeaders.common, defHeaders[lowercase(config.method)]);\n\n        // using for-in instead of forEach to avoid unecessary iteration after header has been found\n        defaultHeadersIteration:\n        for (defHeaderName in defHeaders) {\n          lowercaseDefHeaderName = lowercase(defHeaderName);\n\n          for (reqHeaderName in reqHeaders) {\n            if (lowercase(reqHeaderName) === lowercaseDefHeaderName) {\n              continue defaultHeadersIteration;\n            }\n          }\n\n          reqHeaders[defHeaderName] = defHeaders[defHeaderName];\n        }\n\n        // execute if header value is a function for merged headers\n        return executeHeaderFns(reqHeaders);\n      }\n    }\n\n    $http.pendingRequests = [];\n\n    /**\n     * @ngdoc method\n     * @name $http#get\n     *\n     * @description\n     * Shortcut method to perform `GET` request.\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name $http#delete\n     *\n     * @description\n     * Shortcut method to perform `DELETE` request.\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name $http#head\n     *\n     * @description\n     * Shortcut method to perform `HEAD` request.\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name $http#jsonp\n     *\n     * @description\n     * Shortcut method to perform `JSONP` request.\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request.\n     *                     The name of the callback should be the string `JSON_CALLBACK`.\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n    createShortMethods('get', 'delete', 'head', 'jsonp');\n\n    /**\n     * @ngdoc method\n     * @name $http#post\n     *\n     * @description\n     * Shortcut method to perform `POST` request.\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {*} data Request content\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name $http#put\n     *\n     * @description\n     * Shortcut method to perform `PUT` request.\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {*} data Request content\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n     /**\n      * @ngdoc method\n      * @name $http#patch\n      *\n      * @description\n      * Shortcut method to perform `PATCH` request.\n      *\n      * @param {string} url Relative or absolute URL specifying the destination of the request\n      * @param {*} data Request content\n      * @param {Object=} config Optional configuration object\n      * @returns {HttpPromise} Future object\n      */\n    createShortMethodsWithData('post', 'put', 'patch');\n\n        /**\n         * @ngdoc property\n         * @name $http#defaults\n         *\n         * @description\n         * Runtime equivalent of the `$httpProvider.defaults` property. Allows configuration of\n         * default headers, withCredentials as well as request and response transformations.\n         *\n         * See \"Setting HTTP Headers\" and \"Transforming Requests and Responses\" sections above.\n         */\n    $http.defaults = defaults;\n\n\n    return $http;\n\n\n    function createShortMethods(names) {\n      forEach(arguments, function(name) {\n        $http[name] = function(url, config) {\n          return $http(extend(config || {}, {\n            method: name,\n            url: url\n          }));\n        };\n      });\n    }\n\n\n    function createShortMethodsWithData(name) {\n      forEach(arguments, function(name) {\n        $http[name] = function(url, data, config) {\n          return $http(extend(config || {}, {\n            method: name,\n            url: url,\n            data: data\n          }));\n        };\n      });\n    }\n\n\n    /**\n     * Makes the request.\n     *\n     * !!! ACCESSES CLOSURE VARS:\n     * $httpBackend, defaults, $log, $rootScope, defaultCache, $http.pendingRequests\n     */\n    function sendReq(config, reqData) {\n      var deferred = $q.defer(),\n          promise = deferred.promise,\n          cache,\n          cachedResp,\n          reqHeaders = config.headers,\n          url = buildUrl(config.url, config.params);\n\n      $http.pendingRequests.push(config);\n      promise.then(removePendingReq, removePendingReq);\n\n\n      if ((config.cache || defaults.cache) && config.cache !== false &&\n          (config.method === 'GET' || config.method === 'JSONP')) {\n        cache = isObject(config.cache) ? config.cache\n              : isObject(defaults.cache) ? defaults.cache\n              : defaultCache;\n      }\n\n      if (cache) {\n        cachedResp = cache.get(url);\n        if (isDefined(cachedResp)) {\n          if (isPromiseLike(cachedResp)) {\n            // cached request has already been sent, but there is no response yet\n            cachedResp.then(resolvePromiseWithResult, resolvePromiseWithResult);\n          } else {\n            // serving from cache\n            if (isArray(cachedResp)) {\n              resolvePromise(cachedResp[1], cachedResp[0], shallowCopy(cachedResp[2]), cachedResp[3]);\n            } else {\n              resolvePromise(cachedResp, 200, {}, 'OK');\n            }\n          }\n        } else {\n          // put the promise for the non-transformed response into cache as a placeholder\n          cache.put(url, promise);\n        }\n      }\n\n\n      // if we won't have the response in cache, set the xsrf headers and\n      // send the request to the backend\n      if (isUndefined(cachedResp)) {\n        var xsrfValue = urlIsSameOrigin(config.url)\n            ? $browser.cookies()[config.xsrfCookieName || defaults.xsrfCookieName]\n            : undefined;\n        if (xsrfValue) {\n          reqHeaders[(config.xsrfHeaderName || defaults.xsrfHeaderName)] = xsrfValue;\n        }\n\n        $httpBackend(config.method, url, reqData, done, reqHeaders, config.timeout,\n            config.withCredentials, config.responseType);\n      }\n\n      return promise;\n\n\n      /**\n       * Callback registered to $httpBackend():\n       *  - caches the response if desired\n       *  - resolves the raw $http promise\n       *  - calls $apply\n       */\n      function done(status, response, headersString, statusText) {\n        if (cache) {\n          if (isSuccess(status)) {\n            cache.put(url, [status, response, parseHeaders(headersString), statusText]);\n          } else {\n            // remove promise from the cache\n            cache.remove(url);\n          }\n        }\n\n        function resolveHttpPromise() {\n          resolvePromise(response, status, headersString, statusText);\n        }\n\n        if (useApplyAsync) {\n          $rootScope.$applyAsync(resolveHttpPromise);\n        } else {\n          resolveHttpPromise();\n          if (!$rootScope.$$phase) $rootScope.$apply();\n        }\n      }\n\n\n      /**\n       * Resolves the raw $http promise.\n       */\n      function resolvePromise(response, status, headers, statusText) {\n        // normalize internal statuses to 0\n        status = Math.max(status, 0);\n\n        (isSuccess(status) ? deferred.resolve : deferred.reject)({\n          data: response,\n          status: status,\n          headers: headersGetter(headers),\n          config: config,\n          statusText: statusText\n        });\n      }\n\n      function resolvePromiseWithResult(result) {\n        resolvePromise(result.data, result.status, shallowCopy(result.headers()), result.statusText);\n      }\n\n      function removePendingReq() {\n        var idx = $http.pendingRequests.indexOf(config);\n        if (idx !== -1) $http.pendingRequests.splice(idx, 1);\n      }\n    }\n\n\n    function buildUrl(url, params) {\n      if (!params) return url;\n      var parts = [];\n      forEachSorted(params, function(value, key) {\n        if (value === null || isUndefined(value)) return;\n        if (!isArray(value)) value = [value];\n\n        forEach(value, function(v) {\n          if (isObject(v)) {\n            if (isDate(v)) {\n              v = v.toISOString();\n            } else {\n              v = toJson(v);\n            }\n          }\n          parts.push(encodeUriQuery(key) + '=' +\n                     encodeUriQuery(v));\n        });\n      });\n      if (parts.length > 0) {\n        url += ((url.indexOf('?') == -1) ? '?' : '&') + parts.join('&');\n      }\n      return url;\n    }\n  }];\n}\n\nfunction createXhr() {\n    return new window.XMLHttpRequest();\n}\n\n/**\n * @ngdoc service\n * @name $httpBackend\n * @requires $window\n * @requires $document\n *\n * @description\n * HTTP backend used by the {@link ng.$http service} that delegates to\n * XMLHttpRequest object or JSONP and deals with browser incompatibilities.\n *\n * You should never need to use this service directly, instead use the higher-level abstractions:\n * {@link ng.$http $http} or {@link ngResource.$resource $resource}.\n *\n * During testing this implementation is swapped with {@link ngMock.$httpBackend mock\n * $httpBackend} which can be trained with responses.\n */\nfunction $HttpBackendProvider() {\n  this.$get = ['$browser', '$window', '$document', function($browser, $window, $document) {\n    return createHttpBackend($browser, createXhr, $browser.defer, $window.angular.callbacks, $document[0]);\n  }];\n}\n\nfunction createHttpBackend($browser, createXhr, $browserDefer, callbacks, rawDocument) {\n  // TODO(vojta): fix the signature\n  return function(method, url, post, callback, headers, timeout, withCredentials, responseType) {\n    $browser.$$incOutstandingRequestCount();\n    url = url || $browser.url();\n\n    if (lowercase(method) == 'jsonp') {\n      var callbackId = '_' + (callbacks.counter++).toString(36);\n      callbacks[callbackId] = function(data) {\n        callbacks[callbackId].data = data;\n        callbacks[callbackId].called = true;\n      };\n\n      var jsonpDone = jsonpReq(url.replace('JSON_CALLBACK', 'angular.callbacks.' + callbackId),\n          callbackId, function(status, text) {\n        completeRequest(callback, status, callbacks[callbackId].data, \"\", text);\n        callbacks[callbackId] = noop;\n      });\n    } else {\n\n      var xhr = createXhr();\n\n      xhr.open(method, url, true);\n      forEach(headers, function(value, key) {\n        if (isDefined(value)) {\n            xhr.setRequestHeader(key, value);\n        }\n      });\n\n      xhr.onload = function requestLoaded() {\n        var statusText = xhr.statusText || '';\n\n        // responseText is the old-school way of retrieving response (supported by IE8 & 9)\n        // response/responseType properties were introduced in XHR Level2 spec (supported by IE10)\n        var response = ('response' in xhr) ? xhr.response : xhr.responseText;\n\n        // normalize IE9 bug (http://bugs.jquery.com/ticket/1450)\n        var status = xhr.status === 1223 ? 204 : xhr.status;\n\n        // fix status code when it is 0 (0 status is undocumented).\n        // Occurs when accessing file resources or on Android 4.1 stock browser\n        // while retrieving files from application cache.\n        if (status === 0) {\n          status = response ? 200 : urlResolve(url).protocol == 'file' ? 404 : 0;\n        }\n\n        completeRequest(callback,\n            status,\n            response,\n            xhr.getAllResponseHeaders(),\n            statusText);\n      };\n\n      var requestError = function() {\n        // The response is always empty\n        // See https://xhr.spec.whatwg.org/#request-error-steps and https://fetch.spec.whatwg.org/#concept-network-error\n        completeRequest(callback, -1, null, null, '');\n      };\n\n      xhr.onerror = requestError;\n      xhr.onabort = requestError;\n\n      if (withCredentials) {\n        xhr.withCredentials = true;\n      }\n\n      if (responseType) {\n        try {\n          xhr.responseType = responseType;\n        } catch (e) {\n          // WebKit added support for the json responseType value on 09/03/2013\n          // https://bugs.webkit.org/show_bug.cgi?id=73648. Versions of Safari prior to 7 are\n          // known to throw when setting the value \"json\" as the response type. Other older\n          // browsers implementing the responseType\n          //\n          // The json response type can be ignored if not supported, because JSON payloads are\n          // parsed on the client-side regardless.\n          if (responseType !== 'json') {\n            throw e;\n          }\n        }\n      }\n\n      xhr.send(post || null);\n    }\n\n    if (timeout > 0) {\n      var timeoutId = $browserDefer(timeoutRequest, timeout);\n    } else if (isPromiseLike(timeout)) {\n      timeout.then(timeoutRequest);\n    }\n\n\n    function timeoutRequest() {\n      jsonpDone && jsonpDone();\n      xhr && xhr.abort();\n    }\n\n    function completeRequest(callback, status, response, headersString, statusText) {\n      // cancel timeout and subsequent timeout promise resolution\n      if (timeoutId !== undefined) {\n        $browserDefer.cancel(timeoutId);\n      }\n      jsonpDone = xhr = null;\n\n      callback(status, response, headersString, statusText);\n      $browser.$$completeOutstandingRequest(noop);\n    }\n  };\n\n  function jsonpReq(url, callbackId, done) {\n    // we can't use jQuery/jqLite here because jQuery does crazy shit with script elements, e.g.:\n    // - fetches local scripts via XHR and evals them\n    // - adds and immediately removes script elements from the document\n    var script = rawDocument.createElement('script'), callback = null;\n    script.type = \"text/javascript\";\n    script.src = url;\n    script.async = true;\n\n    callback = function(event) {\n      removeEventListenerFn(script, \"load\", callback);\n      removeEventListenerFn(script, \"error\", callback);\n      rawDocument.body.removeChild(script);\n      script = null;\n      var status = -1;\n      var text = \"unknown\";\n\n      if (event) {\n        if (event.type === \"load\" && !callbacks[callbackId].called) {\n          event = { type: \"error\" };\n        }\n        text = event.type;\n        status = event.type === \"error\" ? 404 : 200;\n      }\n\n      if (done) {\n        done(status, text);\n      }\n    };\n\n    addEventListenerFn(script, \"load\", callback);\n    addEventListenerFn(script, \"error\", callback);\n    rawDocument.body.appendChild(script);\n    return callback;\n  }\n}\n\nvar $interpolateMinErr = minErr('$interpolate');\n\n/**\n * @ngdoc provider\n * @name $interpolateProvider\n *\n * @description\n *\n * Used for configuring the interpolation markup. Defaults to `{{` and `}}`.\n *\n * @example\n<example module=\"customInterpolationApp\">\n<file name=\"index.html\">\n<script>\n  var customInterpolationApp = angular.module('customInterpolationApp', []);\n\n  customInterpolationApp.config(function($interpolateProvider) {\n    $interpolateProvider.startSymbol('//');\n    $interpolateProvider.endSymbol('//');\n  });\n\n\n  customInterpolationApp.controller('DemoController', function() {\n      this.label = \"This binding is brought you by // interpolation symbols.\";\n  });\n</script>\n<div ng-app=\"App\" ng-controller=\"DemoController as demo\">\n    //demo.label//\n</div>\n</file>\n<file name=\"protractor.js\" type=\"protractor\">\n  it('should interpolate binding with custom symbols', function() {\n    expect(element(by.binding('demo.label')).getText()).toBe('This binding is brought you by // interpolation symbols.');\n  });\n</file>\n</example>\n */\nfunction $InterpolateProvider() {\n  var startSymbol = '{{';\n  var endSymbol = '}}';\n\n  /**\n   * @ngdoc method\n   * @name $interpolateProvider#startSymbol\n   * @description\n   * Symbol to denote start of expression in the interpolated string. Defaults to `{{`.\n   *\n   * @param {string=} value new value to set the starting symbol to.\n   * @returns {string|self} Returns the symbol when used as getter and self if used as setter.\n   */\n  this.startSymbol = function(value) {\n    if (value) {\n      startSymbol = value;\n      return this;\n    } else {\n      return startSymbol;\n    }\n  };\n\n  /**\n   * @ngdoc method\n   * @name $interpolateProvider#endSymbol\n   * @description\n   * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.\n   *\n   * @param {string=} value new value to set the ending symbol to.\n   * @returns {string|self} Returns the symbol when used as getter and self if used as setter.\n   */\n  this.endSymbol = function(value) {\n    if (value) {\n      endSymbol = value;\n      return this;\n    } else {\n      return endSymbol;\n    }\n  };\n\n\n  this.$get = ['$parse', '$exceptionHandler', '$sce', function($parse, $exceptionHandler, $sce) {\n    var startSymbolLength = startSymbol.length,\n        endSymbolLength = endSymbol.length,\n        escapedStartRegexp = new RegExp(startSymbol.replace(/./g, escape), 'g'),\n        escapedEndRegexp = new RegExp(endSymbol.replace(/./g, escape), 'g');\n\n    function escape(ch) {\n      return '\\\\\\\\\\\\' + ch;\n    }\n\n    /**\n     * @ngdoc service\n     * @name $interpolate\n     * @kind function\n     *\n     * @requires $parse\n     * @requires $sce\n     *\n     * @description\n     *\n     * Compiles a string with markup into an interpolation function. This service is used by the\n     * HTML {@link ng.$compile $compile} service for data binding. See\n     * {@link ng.$interpolateProvider $interpolateProvider} for configuring the\n     * interpolation markup.\n     *\n     *\n     * ```js\n     *   var $interpolate = ...; // injected\n     *   var exp = $interpolate('Hello {{name | uppercase}}!');\n     *   expect(exp({name:'Angular'}).toEqual('Hello ANGULAR!');\n     * ```\n     *\n     * `$interpolate` takes an optional fourth argument, `allOrNothing`. If `allOrNothing` is\n     * `true`, the interpolation function will return `undefined` unless all embedded expressions\n     * evaluate to a value other than `undefined`.\n     *\n     * ```js\n     *   var $interpolate = ...; // injected\n     *   var context = {greeting: 'Hello', name: undefined };\n     *\n     *   // default \"forgiving\" mode\n     *   var exp = $interpolate('{{greeting}} {{name}}!');\n     *   expect(exp(context)).toEqual('Hello !');\n     *\n     *   // \"allOrNothing\" mode\n     *   exp = $interpolate('{{greeting}} {{name}}!', false, null, true);\n     *   expect(exp(context)).toBeUndefined();\n     *   context.name = 'Angular';\n     *   expect(exp(context)).toEqual('Hello Angular!');\n     * ```\n     *\n     * `allOrNothing` is useful for interpolating URLs. `ngSrc` and `ngSrcset` use this behavior.\n     *\n     * ####Escaped Interpolation\n     * $interpolate provides a mechanism for escaping interpolation markers. Start and end markers\n     * can be escaped by preceding each of their characters with a REVERSE SOLIDUS U+005C (backslash).\n     * It will be rendered as a regular start/end marker, and will not be interpreted as an expression\n     * or binding.\n     *\n     * This enables web-servers to prevent script injection attacks and defacing attacks, to some\n     * degree, while also enabling code examples to work without relying on the\n     * {@link ng.directive:ngNonBindable ngNonBindable} directive.\n     *\n     * **For security purposes, it is strongly encouraged that web servers escape user-supplied data,\n     * replacing angle brackets (&lt;, &gt;) with &amp;lt; and &amp;gt; respectively, and replacing all\n     * interpolation start/end markers with their escaped counterparts.**\n     *\n     * Escaped interpolation markers are only replaced with the actual interpolation markers in rendered\n     * output when the $interpolate service processes the text. So, for HTML elements interpolated\n     * by {@link ng.$compile $compile}, or otherwise interpolated with the `mustHaveExpression` parameter\n     * set to `true`, the interpolated text must contain an unescaped interpolation expression. As such,\n     * this is typically useful only when user-data is used in rendering a template from the server, or\n     * when otherwise untrusted data is used by a directive.\n     *\n     * <example>\n     *  <file name=\"index.html\">\n     *    <div ng-init=\"username='A user'\">\n     *      <p ng-init=\"apptitle='Escaping demo'\">{{apptitle}}: \\{\\{ username = \"defaced value\"; \\}\\}\n     *        </p>\n     *      <p><strong>{{username}}</strong> attempts to inject code which will deface the\n     *        application, but fails to accomplish their task, because the server has correctly\n     *        escaped the interpolation start/end markers with REVERSE SOLIDUS U+005C (backslash)\n     *        characters.</p>\n     *      <p>Instead, the result of the attempted script injection is visible, and can be removed\n     *        from the database by an administrator.</p>\n     *    </div>\n     *  </file>\n     * </example>\n     *\n     * @param {string} text The text with markup to interpolate.\n     * @param {boolean=} mustHaveExpression if set to true then the interpolation string must have\n     *    embedded expression in order to return an interpolation function. Strings with no\n     *    embedded expression will return null for the interpolation function.\n     * @param {string=} trustedContext when provided, the returned function passes the interpolated\n     *    result through {@link ng.$sce#getTrusted $sce.getTrusted(interpolatedResult,\n     *    trustedContext)} before returning it.  Refer to the {@link ng.$sce $sce} service that\n     *    provides Strict Contextual Escaping for details.\n     * @param {boolean=} allOrNothing if `true`, then the returned function returns undefined\n     *    unless all embedded expressions evaluate to a value other than `undefined`.\n     * @returns {function(context)} an interpolation function which is used to compute the\n     *    interpolated string. The function has these parameters:\n     *\n     * - `context`: evaluation context for all expressions embedded in the interpolated text\n     */\n    function $interpolate(text, mustHaveExpression, trustedContext, allOrNothing) {\n      allOrNothing = !!allOrNothing;\n      var startIndex,\n          endIndex,\n          index = 0,\n          expressions = [],\n          parseFns = [],\n          textLength = text.length,\n          exp,\n          concat = [],\n          expressionPositions = [];\n\n      while (index < textLength) {\n        if (((startIndex = text.indexOf(startSymbol, index)) != -1) &&\n             ((endIndex = text.indexOf(endSymbol, startIndex + startSymbolLength)) != -1)) {\n          if (index !== startIndex) {\n            concat.push(unescapeText(text.substring(index, startIndex)));\n          }\n          exp = text.substring(startIndex + startSymbolLength, endIndex);\n          expressions.push(exp);\n          parseFns.push($parse(exp, parseStringifyInterceptor));\n          index = endIndex + endSymbolLength;\n          expressionPositions.push(concat.length);\n          concat.push('');\n        } else {\n          // we did not find an interpolation, so we have to add the remainder to the separators array\n          if (index !== textLength) {\n            concat.push(unescapeText(text.substring(index)));\n          }\n          break;\n        }\n      }\n\n      // Concatenating expressions makes it hard to reason about whether some combination of\n      // concatenated values are unsafe to use and could easily lead to XSS.  By requiring that a\n      // single expression be used for iframe[src], object[src], etc., we ensure that the value\n      // that's used is assigned or constructed by some JS code somewhere that is more testable or\n      // make it obvious that you bound the value to some user controlled value.  This helps reduce\n      // the load when auditing for XSS issues.\n      if (trustedContext && concat.length > 1) {\n          throw $interpolateMinErr('noconcat',\n              \"Error while interpolating: {0}\\nStrict Contextual Escaping disallows \" +\n              \"interpolations that concatenate multiple expressions when a trusted value is \" +\n              \"required.  See http://docs.angularjs.org/api/ng.$sce\", text);\n      }\n\n      if (!mustHaveExpression || expressions.length) {\n        var compute = function(values) {\n          for (var i = 0, ii = expressions.length; i < ii; i++) {\n            if (allOrNothing && isUndefined(values[i])) return;\n            concat[expressionPositions[i]] = values[i];\n          }\n          return concat.join('');\n        };\n\n        var getValue = function(value) {\n          return trustedContext ?\n            $sce.getTrusted(trustedContext, value) :\n            $sce.valueOf(value);\n        };\n\n        var stringify = function(value) {\n          if (value == null) { // null || undefined\n            return '';\n          }\n          switch (typeof value) {\n            case 'string':\n              break;\n            case 'number':\n              value = '' + value;\n              break;\n            default:\n              value = toJson(value);\n          }\n\n          return value;\n        };\n\n        return extend(function interpolationFn(context) {\n            var i = 0;\n            var ii = expressions.length;\n            var values = new Array(ii);\n\n            try {\n              for (; i < ii; i++) {\n                values[i] = parseFns[i](context);\n              }\n\n              return compute(values);\n            } catch (err) {\n              var newErr = $interpolateMinErr('interr', \"Can't interpolate: {0}\\n{1}\", text,\n                  err.toString());\n              $exceptionHandler(newErr);\n            }\n\n          }, {\n          // all of these properties are undocumented for now\n          exp: text, //just for compatibility with regular watchers created via $watch\n          expressions: expressions,\n          $$watchDelegate: function(scope, listener, objectEquality) {\n            var lastValue;\n            return scope.$watchGroup(parseFns, function interpolateFnWatcher(values, oldValues) {\n              var currValue = compute(values);\n              if (isFunction(listener)) {\n                listener.call(this, currValue, values !== oldValues ? lastValue : currValue, scope);\n              }\n              lastValue = currValue;\n            }, objectEquality);\n          }\n        });\n      }\n\n      function unescapeText(text) {\n        return text.replace(escapedStartRegexp, startSymbol).\n          replace(escapedEndRegexp, endSymbol);\n      }\n\n      function parseStringifyInterceptor(value) {\n        try {\n          value = getValue(value);\n          return allOrNothing && !isDefined(value) ? value : stringify(value);\n        } catch (err) {\n          var newErr = $interpolateMinErr('interr', \"Can't interpolate: {0}\\n{1}\", text,\n            err.toString());\n          $exceptionHandler(newErr);\n        }\n      }\n    }\n\n\n    /**\n     * @ngdoc method\n     * @name $interpolate#startSymbol\n     * @description\n     * Symbol to denote the start of expression in the interpolated string. Defaults to `{{`.\n     *\n     * Use {@link ng.$interpolateProvider#startSymbol `$interpolateProvider.startSymbol`} to change\n     * the symbol.\n     *\n     * @returns {string} start symbol.\n     */\n    $interpolate.startSymbol = function() {\n      return startSymbol;\n    };\n\n\n    /**\n     * @ngdoc method\n     * @name $interpolate#endSymbol\n     * @description\n     * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.\n     *\n     * Use {@link ng.$interpolateProvider#endSymbol `$interpolateProvider.endSymbol`} to change\n     * the symbol.\n     *\n     * @returns {string} end symbol.\n     */\n    $interpolate.endSymbol = function() {\n      return endSymbol;\n    };\n\n    return $interpolate;\n  }];\n}\n\nfunction $IntervalProvider() {\n  this.$get = ['$rootScope', '$window', '$q', '$$q',\n       function($rootScope,   $window,   $q,   $$q) {\n    var intervals = {};\n\n\n     /**\n      * @ngdoc service\n      * @name $interval\n      *\n      * @description\n      * Angular's wrapper for `window.setInterval`. The `fn` function is executed every `delay`\n      * milliseconds.\n      *\n      * The return value of registering an interval function is a promise. This promise will be\n      * notified upon each tick of the interval, and will be resolved after `count` iterations, or\n      * run indefinitely if `count` is not defined. The value of the notification will be the\n      * number of iterations that have run.\n      * To cancel an interval, call `$interval.cancel(promise)`.\n      *\n      * In tests you can use {@link ngMock.$interval#flush `$interval.flush(millis)`} to\n      * move forward by `millis` milliseconds and trigger any functions scheduled to run in that\n      * time.\n      *\n      * <div class=\"alert alert-warning\">\n      * **Note**: Intervals created by this service must be explicitly destroyed when you are finished\n      * with them.  In particular they are not automatically destroyed when a controller's scope or a\n      * directive's element are destroyed.\n      * You should take this into consideration and make sure to always cancel the interval at the\n      * appropriate moment.  See the example below for more details on how and when to do this.\n      * </div>\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#$apply $apply} block.\n      * @returns {promise} A promise which will be notified on each iteration.\n      *\n      * @example\n      * <example module=\"intervalExample\">\n      * <file name=\"index.html\">\n      *   <script>\n      *     angular.module('intervalExample', [])\n      *       .controller('ExampleController', ['$scope', '$interval',\n      *         function($scope, $interval) {\n      *           $scope.format = 'M/d/yy h:mm:ss a';\n      *           $scope.blood_1 = 100;\n      *           $scope.blood_2 = 120;\n      *\n      *           var stop;\n      *           $scope.fight = function() {\n      *             // Don't start a new fight if we are already fighting\n      *             if ( angular.isDefined(stop) ) return;\n      *\n      *             stop = $interval(function() {\n      *               if ($scope.blood_1 > 0 && $scope.blood_2 > 0) {\n      *                 $scope.blood_1 = $scope.blood_1 - 3;\n      *                 $scope.blood_2 = $scope.blood_2 - 4;\n      *               } else {\n      *                 $scope.stopFight();\n      *               }\n      *             }, 100);\n      *           };\n      *\n      *           $scope.stopFight = function() {\n      *             if (angular.isDefined(stop)) {\n      *               $interval.cancel(stop);\n      *               stop = undefined;\n      *             }\n      *           };\n      *\n      *           $scope.resetFight = function() {\n      *             $scope.blood_1 = 100;\n      *             $scope.blood_2 = 120;\n      *           };\n      *\n      *           $scope.$on('$destroy', function() {\n      *             // Make sure that the interval is destroyed too\n      *             $scope.stopFight();\n      *           });\n      *         }])\n      *       // Register the 'myCurrentTime' directive factory method.\n      *       // We inject $interval and dateFilter service since the factory method is DI.\n      *       .directive('myCurrentTime', ['$interval', 'dateFilter',\n      *         function($interval, dateFilter) {\n      *           // return the directive link function. (compile function not needed)\n      *           return function(scope, element, attrs) {\n      *             var format,  // date format\n      *                 stopTime; // so that we can cancel the time updates\n      *\n      *             // used to update the UI\n      *             function updateTime() {\n      *               element.text(dateFilter(new Date(), format));\n      *             }\n      *\n      *             // watch the expression, and update the UI on change.\n      *             scope.$watch(attrs.myCurrentTime, function(value) {\n      *               format = value;\n      *               updateTime();\n      *             });\n      *\n      *             stopTime = $interval(updateTime, 1000);\n      *\n      *             // listen on DOM destroy (removal) event, and cancel the next UI update\n      *             // to prevent updating time after the DOM element was removed.\n      *             element.on('$destroy', function() {\n      *               $interval.cancel(stopTime);\n      *             });\n      *           }\n      *         }]);\n      *   </script>\n      *\n      *   <div>\n      *     <div ng-controller=\"ExampleController\">\n      *       Date format: <input ng-model=\"format\"> <hr/>\n      *       Current time is: <span my-current-time=\"format\"></span>\n      *       <hr/>\n      *       Blood 1 : <font color='red'>{{blood_1}}</font>\n      *       Blood 2 : <font color='red'>{{blood_2}}</font>\n      *       <button type=\"button\" data-ng-click=\"fight()\">Fight</button>\n      *       <button type=\"button\" data-ng-click=\"stopFight()\">StopFight</button>\n      *       <button type=\"button\" data-ng-click=\"resetFight()\">resetFight</button>\n      *     </div>\n      *   </div>\n      *\n      * </file>\n      * </example>\n      */\n    function interval(fn, delay, count, invokeApply) {\n      var setInterval = $window.setInterval,\n          clearInterval = $window.clearInterval,\n          iteration = 0,\n          skipApply = (isDefined(invokeApply) && !invokeApply),\n          deferred = (skipApply ? $$q : $q).defer(),\n          promise = deferred.promise;\n\n      count = isDefined(count) ? count : 0;\n\n      promise.then(null, null, fn);\n\n      promise.$$intervalId = setInterval(function tick() {\n        deferred.notify(iteration++);\n\n        if (count > 0 && iteration >= count) {\n          deferred.resolve(iteration);\n          clearInterval(promise.$$intervalId);\n          delete intervals[promise.$$intervalId];\n        }\n\n        if (!skipApply) $rootScope.$apply();\n\n      }, delay);\n\n      intervals[promise.$$intervalId] = deferred;\n\n      return promise;\n    }\n\n\n     /**\n      * @ngdoc method\n      * @name $interval#cancel\n      *\n      * @description\n      * Cancels a task associated with the `promise`.\n      *\n      * @param {promise} promise returned by the `$interval` function.\n      * @returns {boolean} Returns `true` if the task was successfully canceled.\n      */\n    interval.cancel = function(promise) {\n      if (promise && promise.$$intervalId in intervals) {\n        intervals[promise.$$intervalId].reject('canceled');\n        $window.clearInterval(promise.$$intervalId);\n        delete intervals[promise.$$intervalId];\n        return true;\n      }\n      return false;\n    };\n\n    return interval;\n  }];\n}\n\n/**\n * @ngdoc service\n * @name $locale\n *\n * @description\n * $locale service provides localization rules for various Angular components. As of right now the\n * only public api is:\n *\n * * `id` – `{string}` – locale id formatted as `languageId-countryId` (e.g. `en-us`)\n */\nfunction $LocaleProvider() {\n  this.$get = function() {\n    return {\n      id: 'en-us',\n\n      NUMBER_FORMATS: {\n        DECIMAL_SEP: '.',\n        GROUP_SEP: ',',\n        PATTERNS: [\n          { // Decimal Pattern\n            minInt: 1,\n            minFrac: 0,\n            maxFrac: 3,\n            posPre: '',\n            posSuf: '',\n            negPre: '-',\n            negSuf: '',\n            gSize: 3,\n            lgSize: 3\n          },{ //Currency Pattern\n            minInt: 1,\n            minFrac: 2,\n            maxFrac: 2,\n            posPre: '\\u00A4',\n            posSuf: '',\n            negPre: '(\\u00A4',\n            negSuf: ')',\n            gSize: 3,\n            lgSize: 3\n          }\n        ],\n        CURRENCY_SYM: '$'\n      },\n\n      DATETIME_FORMATS: {\n        MONTH:\n            'January,February,March,April,May,June,July,August,September,October,November,December'\n            .split(','),\n        SHORTMONTH:  'Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec'.split(','),\n        DAY: 'Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday'.split(','),\n        SHORTDAY: 'Sun,Mon,Tue,Wed,Thu,Fri,Sat'.split(','),\n        AMPMS: ['AM','PM'],\n        medium: 'MMM d, y h:mm:ss a',\n        'short': 'M/d/yy h:mm a',\n        fullDate: 'EEEE, MMMM d, y',\n        longDate: 'MMMM d, y',\n        mediumDate: 'MMM d, y',\n        shortDate: 'M/d/yy',\n        mediumTime: 'h:mm:ss a',\n        shortTime: 'h:mm a'\n      },\n\n      pluralCat: function(num) {\n        if (num === 1) {\n          return 'one';\n        }\n        return 'other';\n      }\n    };\n  };\n}\n\nvar PATH_MATCH = /^([^\\?#]*)(\\?([^#]*))?(#(.*))?$/,\n    DEFAULT_PORTS = {'http': 80, 'https': 443, 'ftp': 21};\nvar $locationMinErr = minErr('$location');\n\n\n/**\n * Encode path using encodeUriSegment, ignoring forward slashes\n *\n * @param {string} path Path to encode\n * @returns {string}\n */\nfunction encodePath(path) {\n  var segments = path.split('/'),\n      i = segments.length;\n\n  while (i--) {\n    segments[i] = encodeUriSegment(segments[i]);\n  }\n\n  return segments.join('/');\n}\n\nfunction parseAbsoluteUrl(absoluteUrl, locationObj) {\n  var parsedUrl = urlResolve(absoluteUrl);\n\n  locationObj.$$protocol = parsedUrl.protocol;\n  locationObj.$$host = parsedUrl.hostname;\n  locationObj.$$port = int(parsedUrl.port) || DEFAULT_PORTS[parsedUrl.protocol] || null;\n}\n\n\nfunction parseAppUrl(relativeUrl, locationObj) {\n  var prefixed = (relativeUrl.charAt(0) !== '/');\n  if (prefixed) {\n    relativeUrl = '/' + relativeUrl;\n  }\n  var match = urlResolve(relativeUrl);\n  locationObj.$$path = decodeURIComponent(prefixed && match.pathname.charAt(0) === '/' ?\n      match.pathname.substring(1) : match.pathname);\n  locationObj.$$search = parseKeyValue(match.search);\n  locationObj.$$hash = decodeURIComponent(match.hash);\n\n  // make sure path starts with '/';\n  if (locationObj.$$path && locationObj.$$path.charAt(0) != '/') {\n    locationObj.$$path = '/' + locationObj.$$path;\n  }\n}\n\n\n/**\n *\n * @param {string} begin\n * @param {string} whole\n * @returns {string} returns text from whole after begin or undefined if it does not begin with\n *                   expected string.\n */\nfunction beginsWith(begin, whole) {\n  if (whole.indexOf(begin) === 0) {\n    return whole.substr(begin.length);\n  }\n}\n\n\nfunction stripHash(url) {\n  var index = url.indexOf('#');\n  return index == -1 ? url : url.substr(0, index);\n}\n\nfunction trimEmptyHash(url) {\n  return url.replace(/(#.+)|#$/, '$1');\n}\n\n\nfunction stripFile(url) {\n  return url.substr(0, stripHash(url).lastIndexOf('/') + 1);\n}\n\n/* return the server only (scheme://host:port) */\nfunction serverBase(url) {\n  return url.substring(0, url.indexOf('/', url.indexOf('//') + 2));\n}\n\n\n/**\n * LocationHtml5Url represents an url\n * This object is exposed as $location service when HTML5 mode is enabled and supported\n *\n * @constructor\n * @param {string} appBase application base URL\n * @param {string} basePrefix url path prefix\n */\nfunction LocationHtml5Url(appBase, basePrefix) {\n  this.$$html5 = true;\n  basePrefix = basePrefix || '';\n  var appBaseNoFile = stripFile(appBase);\n  parseAbsoluteUrl(appBase, this);\n\n\n  /**\n   * Parse given html5 (regular) url string into properties\n   * @param {string} url HTML5 url\n   * @private\n   */\n  this.$$parse = function(url) {\n    var pathUrl = beginsWith(appBaseNoFile, url);\n    if (!isString(pathUrl)) {\n      throw $locationMinErr('ipthprfx', 'Invalid url \"{0}\", missing path prefix \"{1}\".', url,\n          appBaseNoFile);\n    }\n\n    parseAppUrl(pathUrl, this);\n\n    if (!this.$$path) {\n      this.$$path = '/';\n    }\n\n    this.$$compose();\n  };\n\n  /**\n   * Compose url and update `absUrl` property\n   * @private\n   */\n  this.$$compose = function() {\n    var search = toKeyValue(this.$$search),\n        hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';\n\n    this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;\n    this.$$absUrl = appBaseNoFile + this.$$url.substr(1); // first char is always '/'\n  };\n\n  this.$$parseLinkUrl = function(url, relHref) {\n    if (relHref && relHref[0] === '#') {\n      // special case for links to hash fragments:\n      // keep the old url and only replace the hash fragment\n      this.hash(relHref.slice(1));\n      return true;\n    }\n    var appUrl, prevAppUrl;\n    var rewrittenUrl;\n\n    if ((appUrl = beginsWith(appBase, url)) !== undefined) {\n      prevAppUrl = appUrl;\n      if ((appUrl = beginsWith(basePrefix, appUrl)) !== undefined) {\n        rewrittenUrl = appBaseNoFile + (beginsWith('/', appUrl) || appUrl);\n      } else {\n        rewrittenUrl = appBase + prevAppUrl;\n      }\n    } else if ((appUrl = beginsWith(appBaseNoFile, url)) !== undefined) {\n      rewrittenUrl = appBaseNoFile + appUrl;\n    } else if (appBaseNoFile == url + '/') {\n      rewrittenUrl = appBaseNoFile;\n    }\n    if (rewrittenUrl) {\n      this.$$parse(rewrittenUrl);\n    }\n    return !!rewrittenUrl;\n  };\n}\n\n\n/**\n * LocationHashbangUrl represents url\n * This object is exposed as $location service when developer doesn't opt into html5 mode.\n * It also serves as the base class for html5 mode fallback on legacy browsers.\n *\n * @constructor\n * @param {string} appBase application base URL\n * @param {string} hashPrefix hashbang prefix\n */\nfunction LocationHashbangUrl(appBase, hashPrefix) {\n  var appBaseNoFile = stripFile(appBase);\n\n  parseAbsoluteUrl(appBase, this);\n\n\n  /**\n   * Parse given hashbang url into properties\n   * @param {string} url Hashbang url\n   * @private\n   */\n  this.$$parse = function(url) {\n    var withoutBaseUrl = beginsWith(appBase, url) || beginsWith(appBaseNoFile, url);\n    var withoutHashUrl;\n\n    if (withoutBaseUrl.charAt(0) === '#') {\n\n      // The rest of the url starts with a hash so we have\n      // got either a hashbang path or a plain hash fragment\n      withoutHashUrl = beginsWith(hashPrefix, withoutBaseUrl);\n      if (isUndefined(withoutHashUrl)) {\n        // There was no hashbang prefix so we just have a hash fragment\n        withoutHashUrl = withoutBaseUrl;\n      }\n\n    } else {\n      // There was no hashbang path nor hash fragment:\n      // If we are in HTML5 mode we use what is left as the path;\n      // Otherwise we ignore what is left\n      withoutHashUrl = this.$$html5 ? withoutBaseUrl : '';\n    }\n\n    parseAppUrl(withoutHashUrl, this);\n\n    this.$$path = removeWindowsDriveName(this.$$path, withoutHashUrl, appBase);\n\n    this.$$compose();\n\n    /*\n     * In Windows, on an anchor node on documents loaded from\n     * the filesystem, the browser will return a pathname\n     * prefixed with the drive name ('/C:/path') when a\n     * pathname without a drive is set:\n     *  * a.setAttribute('href', '/foo')\n     *   * a.pathname === '/C:/foo' //true\n     *\n     * Inside of Angular, we're always using pathnames that\n     * do not include drive names for routing.\n     */\n    function removeWindowsDriveName(path, url, base) {\n      /*\n      Matches paths for file protocol on windows,\n      such as /C:/foo/bar, and captures only /foo/bar.\n      */\n      var windowsFilePathExp = /^\\/[A-Z]:(\\/.*)/;\n\n      var firstPathSegmentMatch;\n\n      //Get the relative path from the input URL.\n      if (url.indexOf(base) === 0) {\n        url = url.replace(base, '');\n      }\n\n      // The input URL intentionally contains a first path segment that ends with a colon.\n      if (windowsFilePathExp.exec(url)) {\n        return path;\n      }\n\n      firstPathSegmentMatch = windowsFilePathExp.exec(path);\n      return firstPathSegmentMatch ? firstPathSegmentMatch[1] : path;\n    }\n  };\n\n  /**\n   * Compose hashbang url and update `absUrl` property\n   * @private\n   */\n  this.$$compose = function() {\n    var search = toKeyValue(this.$$search),\n        hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';\n\n    this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;\n    this.$$absUrl = appBase + (this.$$url ? hashPrefix + this.$$url : '');\n  };\n\n  this.$$parseLinkUrl = function(url, relHref) {\n    if (stripHash(appBase) == stripHash(url)) {\n      this.$$parse(url);\n      return true;\n    }\n    return false;\n  };\n}\n\n\n/**\n * LocationHashbangUrl represents url\n * This object is exposed as $location service when html5 history api is enabled but the browser\n * does not support it.\n *\n * @constructor\n * @param {string} appBase application base URL\n * @param {string} hashPrefix hashbang prefix\n */\nfunction LocationHashbangInHtml5Url(appBase, hashPrefix) {\n  this.$$html5 = true;\n  LocationHashbangUrl.apply(this, arguments);\n\n  var appBaseNoFile = stripFile(appBase);\n\n  this.$$parseLinkUrl = function(url, relHref) {\n    if (relHref && relHref[0] === '#') {\n      // special case for links to hash fragments:\n      // keep the old url and only replace the hash fragment\n      this.hash(relHref.slice(1));\n      return true;\n    }\n\n    var rewrittenUrl;\n    var appUrl;\n\n    if (appBase == stripHash(url)) {\n      rewrittenUrl = url;\n    } else if ((appUrl = beginsWith(appBaseNoFile, url))) {\n      rewrittenUrl = appBase + hashPrefix + appUrl;\n    } else if (appBaseNoFile === url + '/') {\n      rewrittenUrl = appBaseNoFile;\n    }\n    if (rewrittenUrl) {\n      this.$$parse(rewrittenUrl);\n    }\n    return !!rewrittenUrl;\n  };\n\n  this.$$compose = function() {\n    var search = toKeyValue(this.$$search),\n        hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';\n\n    this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;\n    // include hashPrefix in $$absUrl when $$url is empty so IE8 & 9 do not reload page because of removal of '#'\n    this.$$absUrl = appBase + hashPrefix + this.$$url;\n  };\n\n}\n\n\nvar locationPrototype = {\n\n  /**\n   * Are we in html5 mode?\n   * @private\n   */\n  $$html5: false,\n\n  /**\n   * Has any change been replacing?\n   * @private\n   */\n  $$replace: false,\n\n  /**\n   * @ngdoc method\n   * @name $location#absUrl\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return full url representation with all segments encoded according to rules specified in\n   * [RFC 3986](http://www.ietf.org/rfc/rfc3986.txt).\n   *\n   *\n   * ```js\n   * // given url http://example.com/#/some/path?foo=bar&baz=xoxo\n   * var absUrl = $location.absUrl();\n   * // => \"http://example.com/#/some/path?foo=bar&baz=xoxo\"\n   * ```\n   *\n   * @return {string} full url\n   */\n  absUrl: locationGetter('$$absUrl'),\n\n  /**\n   * @ngdoc method\n   * @name $location#url\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return url (e.g. `/path?a=b#hash`) when called without any parameter.\n   *\n   * Change path, search and hash, when called with parameter and return `$location`.\n   *\n   *\n   * ```js\n   * // given url http://example.com/#/some/path?foo=bar&baz=xoxo\n   * var url = $location.url();\n   * // => \"/some/path?foo=bar&baz=xoxo\"\n   * ```\n   *\n   * @param {string=} url New url without base prefix (e.g. `/path?a=b#hash`)\n   * @return {string} url\n   */\n  url: function(url) {\n    if (isUndefined(url))\n      return this.$$url;\n\n    var match = PATH_MATCH.exec(url);\n    if (match[1] || url === '') this.path(decodeURIComponent(match[1]));\n    if (match[2] || match[1] || url === '') this.search(match[3] || '');\n    this.hash(match[5] || '');\n\n    return this;\n  },\n\n  /**\n   * @ngdoc method\n   * @name $location#protocol\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return protocol of current url.\n   *\n   *\n   * ```js\n   * // given url http://example.com/#/some/path?foo=bar&baz=xoxo\n   * var protocol = $location.protocol();\n   * // => \"http\"\n   * ```\n   *\n   * @return {string} protocol of current url\n   */\n  protocol: locationGetter('$$protocol'),\n\n  /**\n   * @ngdoc method\n   * @name $location#host\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return host of current url.\n   *\n   *\n   * ```js\n   * // given url http://example.com/#/some/path?foo=bar&baz=xoxo\n   * var host = $location.host();\n   * // => \"example.com\"\n   * ```\n   *\n   * @return {string} host of current url.\n   */\n  host: locationGetter('$$host'),\n\n  /**\n   * @ngdoc method\n   * @name $location#port\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return port of current url.\n   *\n   *\n   * ```js\n   * // given url http://example.com/#/some/path?foo=bar&baz=xoxo\n   * var port = $location.port();\n   * // => 80\n   * ```\n   *\n   * @return {Number} port\n   */\n  port: locationGetter('$$port'),\n\n  /**\n   * @ngdoc method\n   * @name $location#path\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return path of current url when called without any parameter.\n   *\n   * Change path when called with parameter and return `$location`.\n   *\n   * Note: Path should always begin with forward slash (/), this method will add the forward slash\n   * if it is missing.\n   *\n   *\n   * ```js\n   * // given url http://example.com/#/some/path?foo=bar&baz=xoxo\n   * var path = $location.path();\n   * // => \"/some/path\"\n   * ```\n   *\n   * @param {(string|number)=} path New path\n   * @return {string} path\n   */\n  path: locationGetterSetter('$$path', function(path) {\n    path = path !== null ? path.toString() : '';\n    return path.charAt(0) == '/' ? path : '/' + path;\n  }),\n\n  /**\n   * @ngdoc method\n   * @name $location#search\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return search part (as object) of current url when called without any parameter.\n   *\n   * Change search part when called with parameter and return `$location`.\n   *\n   *\n   * ```js\n   * // given url http://example.com/#/some/path?foo=bar&baz=xoxo\n   * var searchObject = $location.search();\n   * // => {foo: 'bar', baz: 'xoxo'}\n   *\n   * // set foo to 'yipee'\n   * $location.search('foo', 'yipee');\n   * // $location.search() => {foo: 'yipee', baz: 'xoxo'}\n   * ```\n   *\n   * @param {string|Object.<string>|Object.<Array.<string>>} search New search params - string or\n   * hash object.\n   *\n   * When called with a single argument the method acts as a setter, setting the `search` component\n   * of `$location` to the specified value.\n   *\n   * If the argument is a hash object containing an array of values, these values will be encoded\n   * as duplicate search parameters in the url.\n   *\n   * @param {(string|Number|Array<string>|boolean)=} paramValue If `search` is a string or number, then `paramValue`\n   * will override only a single search property.\n   *\n   * If `paramValue` is an array, it will override the property of the `search` component of\n   * `$location` specified via the first argument.\n   *\n   * If `paramValue` is `null`, the property specified via the first argument will be deleted.\n   *\n   * If `paramValue` is `true`, the property specified via the first argument will be added with no\n   * value nor trailing equal sign.\n   *\n   * @return {Object} If called with no arguments returns the parsed `search` object. If called with\n   * one or more arguments returns `$location` object itself.\n   */\n  search: function(search, paramValue) {\n    switch (arguments.length) {\n      case 0:\n        return this.$$search;\n      case 1:\n        if (isString(search) || isNumber(search)) {\n          search = search.toString();\n          this.$$search = parseKeyValue(search);\n        } else if (isObject(search)) {\n          search = copy(search, {});\n          // remove object undefined or null properties\n          forEach(search, function(value, key) {\n            if (value == null) delete search[key];\n          });\n\n          this.$$search = search;\n        } else {\n          throw $locationMinErr('isrcharg',\n              'The first argument of the `$location#search()` call must be a string or an object.');\n        }\n        break;\n      default:\n        if (isUndefined(paramValue) || paramValue === null) {\n          delete this.$$search[search];\n        } else {\n          this.$$search[search] = paramValue;\n        }\n    }\n\n    this.$$compose();\n    return this;\n  },\n\n  /**\n   * @ngdoc method\n   * @name $location#hash\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return hash fragment when called without any parameter.\n   *\n   * Change hash fragment when called with parameter and return `$location`.\n   *\n   *\n   * ```js\n   * // given url http://example.com/#/some/path?foo=bar&baz=xoxo#hashValue\n   * var hash = $location.hash();\n   * // => \"hashValue\"\n   * ```\n   *\n   * @param {(string|number)=} hash New hash fragment\n   * @return {string} hash\n   */\n  hash: locationGetterSetter('$$hash', function(hash) {\n    return hash !== null ? hash.toString() : '';\n  }),\n\n  /**\n   * @ngdoc method\n   * @name $location#replace\n   *\n   * @description\n   * If called, all changes to $location during current `$digest` will be replacing current history\n   * record, instead of adding new one.\n   */\n  replace: function() {\n    this.$$replace = true;\n    return this;\n  }\n};\n\nforEach([LocationHashbangInHtml5Url, LocationHashbangUrl, LocationHtml5Url], function(Location) {\n  Location.prototype = Object.create(locationPrototype);\n\n  /**\n   * @ngdoc method\n   * @name $location#state\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return the history state object when called without any parameter.\n   *\n   * Change the history state object when called with one parameter and return `$location`.\n   * The state object is later passed to `pushState` or `replaceState`.\n   *\n   * NOTE: This method is supported only in HTML5 mode and only in browsers supporting\n   * the HTML5 History API (i.e. methods `pushState` and `replaceState`). If you need to support\n   * older browsers (like IE9 or Android < 4.0), don't use this method.\n   *\n   * @param {object=} state State object for pushState or replaceState\n   * @return {object} state\n   */\n  Location.prototype.state = function(state) {\n    if (!arguments.length)\n      return this.$$state;\n\n    if (Location !== LocationHtml5Url || !this.$$html5) {\n      throw $locationMinErr('nostate', 'History API state support is available only ' +\n        'in HTML5 mode and only in browsers supporting HTML5 History API');\n    }\n    // The user might modify `stateObject` after invoking `$location.state(stateObject)`\n    // but we're changing the $$state reference to $browser.state() during the $digest\n    // so the modification window is narrow.\n    this.$$state = isUndefined(state) ? null : state;\n\n    return this;\n  };\n});\n\n\nfunction locationGetter(property) {\n  return function() {\n    return this[property];\n  };\n}\n\n\nfunction locationGetterSetter(property, preprocess) {\n  return function(value) {\n    if (isUndefined(value))\n      return this[property];\n\n    this[property] = preprocess(value);\n    this.$$compose();\n\n    return this;\n  };\n}\n\n\n/**\n * @ngdoc service\n * @name $location\n *\n * @requires $rootElement\n *\n * @description\n * The $location service parses the URL in the browser address bar (based on the\n * [window.location](https://developer.mozilla.org/en/window.location)) and makes the URL\n * available to your application. Changes to the URL in the address bar are reflected into\n * $location service and changes to $location are reflected into the browser address bar.\n *\n * **The $location service:**\n *\n * - Exposes the current URL in the browser address bar, so you can\n *   - Watch and observe the URL.\n *   - Change the URL.\n * - Synchronizes the URL with the browser when the user\n *   - Changes the address bar.\n *   - Clicks the back or forward button (or clicks a History link).\n *   - Clicks on a link.\n * - Represents the URL object as a set of methods (protocol, host, port, path, search, hash).\n *\n * For more information see {@link guide/$location Developer Guide: Using $location}\n */\n\n/**\n * @ngdoc provider\n * @name $locationProvider\n * @description\n * Use the `$locationProvider` to configure how the application deep linking paths are stored.\n */\nfunction $LocationProvider() {\n  var hashPrefix = '',\n      html5Mode = {\n        enabled: false,\n        requireBase: true,\n        rewriteLinks: true\n      };\n\n  /**\n   * @ngdoc method\n   * @name $locationProvider#hashPrefix\n   * @description\n   * @param {string=} prefix Prefix for hash part (containing path and search)\n   * @returns {*} current value if used as getter or itself (chaining) if used as setter\n   */\n  this.hashPrefix = function(prefix) {\n    if (isDefined(prefix)) {\n      hashPrefix = prefix;\n      return this;\n    } else {\n      return hashPrefix;\n    }\n  };\n\n  /**\n   * @ngdoc method\n   * @name $locationProvider#html5Mode\n   * @description\n   * @param {(boolean|Object)=} mode If boolean, sets `html5Mode.enabled` to value.\n   *   If object, sets `enabled`, `requireBase` and `rewriteLinks` to respective values. Supported\n   *   properties:\n   *   - **enabled** – `{boolean}` – (default: false) If true, will rely on `history.pushState` to\n   *     change urls where supported. Will fall back to hash-prefixed paths in browsers that do not\n   *     support `pushState`.\n   *   - **requireBase** - `{boolean}` - (default: `true`) When html5Mode is enabled, specifies\n   *     whether or not a <base> tag is required to be present. If `enabled` and `requireBase` are\n   *     true, and a base tag is not present, an error will be thrown when `$location` is injected.\n   *     See the {@link guide/$location $location guide for more information}\n   *   - **rewriteLinks** - `{boolean}` - (default: `true`) When html5Mode is enabled,\n   *     enables/disables url rewriting for relative links.\n   *\n   * @returns {Object} html5Mode object if used as getter or itself (chaining) if used as setter\n   */\n  this.html5Mode = function(mode) {\n    if (isBoolean(mode)) {\n      html5Mode.enabled = mode;\n      return this;\n    } else if (isObject(mode)) {\n\n      if (isBoolean(mode.enabled)) {\n        html5Mode.enabled = mode.enabled;\n      }\n\n      if (isBoolean(mode.requireBase)) {\n        html5Mode.requireBase = mode.requireBase;\n      }\n\n      if (isBoolean(mode.rewriteLinks)) {\n        html5Mode.rewriteLinks = mode.rewriteLinks;\n      }\n\n      return this;\n    } else {\n      return html5Mode;\n    }\n  };\n\n  /**\n   * @ngdoc event\n   * @name $location#$locationChangeStart\n   * @eventType broadcast on root scope\n   * @description\n   * Broadcasted before a URL will change.\n   *\n   * This change can be prevented by calling\n   * `preventDefault` method of the event. See {@link ng.$rootScope.Scope#$on} for more\n   * details about event object. Upon successful change\n   * {@link ng.$location#$locationChangeSuccess $locationChangeSuccess} is fired.\n   *\n   * The `newState` and `oldState` parameters may be defined only in HTML5 mode and when\n   * the browser supports the HTML5 History API.\n   *\n   * @param {Object} angularEvent Synthetic event object.\n   * @param {string} newUrl New URL\n   * @param {string=} oldUrl URL that was before it was changed.\n   * @param {string=} newState New history state object\n   * @param {string=} oldState History state object that was before it was changed.\n   */\n\n  /**\n   * @ngdoc event\n   * @name $location#$locationChangeSuccess\n   * @eventType broadcast on root scope\n   * @description\n   * Broadcasted after a URL was changed.\n   *\n   * The `newState` and `oldState` parameters may be defined only in HTML5 mode and when\n   * the browser supports the HTML5 History API.\n   *\n   * @param {Object} angularEvent Synthetic event object.\n   * @param {string} newUrl New URL\n   * @param {string=} oldUrl URL that was before it was changed.\n   * @param {string=} newState New history state object\n   * @param {string=} oldState History state object that was before it was changed.\n   */\n\n  this.$get = ['$rootScope', '$browser', '$sniffer', '$rootElement', '$window',\n      function($rootScope, $browser, $sniffer, $rootElement, $window) {\n    var $location,\n        LocationMode,\n        baseHref = $browser.baseHref(), // if base[href] is undefined, it defaults to ''\n        initialUrl = $browser.url(),\n        appBase;\n\n    if (html5Mode.enabled) {\n      if (!baseHref && html5Mode.requireBase) {\n        throw $locationMinErr('nobase',\n          \"$location in HTML5 mode requires a <base> tag to be present!\");\n      }\n      appBase = serverBase(initialUrl) + (baseHref || '/');\n      LocationMode = $sniffer.history ? LocationHtml5Url : LocationHashbangInHtml5Url;\n    } else {\n      appBase = stripHash(initialUrl);\n      LocationMode = LocationHashbangUrl;\n    }\n    $location = new LocationMode(appBase, '#' + hashPrefix);\n    $location.$$parseLinkUrl(initialUrl, initialUrl);\n\n    $location.$$state = $browser.state();\n\n    var IGNORE_URI_REGEXP = /^\\s*(javascript|mailto):/i;\n\n    function setBrowserUrlWithFallback(url, replace, state) {\n      var oldUrl = $location.url();\n      var oldState = $location.$$state;\n      try {\n        $browser.url(url, replace, state);\n\n        // Make sure $location.state() returns referentially identical (not just deeply equal)\n        // state object; this makes possible quick checking if the state changed in the digest\n        // loop. Checking deep equality would be too expensive.\n        $location.$$state = $browser.state();\n      } catch (e) {\n        // Restore old values if pushState fails\n        $location.url(oldUrl);\n        $location.$$state = oldState;\n\n        throw e;\n      }\n    }\n\n    $rootElement.on('click', function(event) {\n      // TODO(vojta): rewrite link when opening in new tab/window (in legacy browser)\n      // currently we open nice url link and redirect then\n\n      if (!html5Mode.rewriteLinks || event.ctrlKey || event.metaKey || event.shiftKey || event.which == 2 || event.button == 2) return;\n\n      var elm = jqLite(event.target);\n\n      // traverse the DOM up to find first A tag\n      while (nodeName_(elm[0]) !== 'a') {\n        // ignore rewriting if no A tag (reached root element, or no parent - removed from document)\n        if (elm[0] === $rootElement[0] || !(elm = elm.parent())[0]) return;\n      }\n\n      var absHref = elm.prop('href');\n      // get the actual href attribute - see\n      // http://msdn.microsoft.com/en-us/library/ie/dd347148(v=vs.85).aspx\n      var relHref = elm.attr('href') || elm.attr('xlink:href');\n\n      if (isObject(absHref) && absHref.toString() === '[object SVGAnimatedString]') {\n        // SVGAnimatedString.animVal should be identical to SVGAnimatedString.baseVal, unless during\n        // an animation.\n        absHref = urlResolve(absHref.animVal).href;\n      }\n\n      // Ignore when url is started with javascript: or mailto:\n      if (IGNORE_URI_REGEXP.test(absHref)) return;\n\n      if (absHref && !elm.attr('target') && !event.isDefaultPrevented()) {\n        if ($location.$$parseLinkUrl(absHref, relHref)) {\n          // We do a preventDefault for all urls that are part of the angular application,\n          // in html5mode and also without, so that we are able to abort navigation without\n          // getting double entries in the location history.\n          event.preventDefault();\n          // update location manually\n          if ($location.absUrl() != $browser.url()) {\n            $rootScope.$apply();\n            // hack to work around FF6 bug 684208 when scenario runner clicks on links\n            $window.angular['ff-684208-preventDefault'] = true;\n          }\n        }\n      }\n    });\n\n\n    // rewrite hashbang url <> html5 url\n    if (trimEmptyHash($location.absUrl()) != trimEmptyHash(initialUrl)) {\n      $browser.url($location.absUrl(), true);\n    }\n\n    var initializing = true;\n\n    // update $location when $browser url changes\n    $browser.onUrlChange(function(newUrl, newState) {\n      $rootScope.$evalAsync(function() {\n        var oldUrl = $location.absUrl();\n        var oldState = $location.$$state;\n        var defaultPrevented;\n\n        $location.$$parse(newUrl);\n        $location.$$state = newState;\n\n        defaultPrevented = $rootScope.$broadcast('$locationChangeStart', newUrl, oldUrl,\n            newState, oldState).defaultPrevented;\n\n        // if the location was changed by a `$locationChangeStart` handler then stop\n        // processing this location change\n        if ($location.absUrl() !== newUrl) return;\n\n        if (defaultPrevented) {\n          $location.$$parse(oldUrl);\n          $location.$$state = oldState;\n          setBrowserUrlWithFallback(oldUrl, false, oldState);\n        } else {\n          initializing = false;\n          afterLocationChange(oldUrl, oldState);\n        }\n      });\n      if (!$rootScope.$$phase) $rootScope.$digest();\n    });\n\n    // update browser\n    $rootScope.$watch(function $locationWatch() {\n      var oldUrl = trimEmptyHash($browser.url());\n      var newUrl = trimEmptyHash($location.absUrl());\n      var oldState = $browser.state();\n      var currentReplace = $location.$$replace;\n      var urlOrStateChanged = oldUrl !== newUrl ||\n        ($location.$$html5 && $sniffer.history && oldState !== $location.$$state);\n\n      if (initializing || urlOrStateChanged) {\n        initializing = false;\n\n        $rootScope.$evalAsync(function() {\n          var newUrl = $location.absUrl();\n          var defaultPrevented = $rootScope.$broadcast('$locationChangeStart', newUrl, oldUrl,\n              $location.$$state, oldState).defaultPrevented;\n\n          // if the location was changed by a `$locationChangeStart` handler then stop\n          // processing this location change\n          if ($location.absUrl() !== newUrl) return;\n\n          if (defaultPrevented) {\n            $location.$$parse(oldUrl);\n            $location.$$state = oldState;\n          } else {\n            if (urlOrStateChanged) {\n              setBrowserUrlWithFallback(newUrl, currentReplace,\n                                        oldState === $location.$$state ? null : $location.$$state);\n            }\n            afterLocationChange(oldUrl, oldState);\n          }\n        });\n      }\n\n      $location.$$replace = false;\n\n      // we don't need to return anything because $evalAsync will make the digest loop dirty when\n      // there is a change\n    });\n\n    return $location;\n\n    function afterLocationChange(oldUrl, oldState) {\n      $rootScope.$broadcast('$locationChangeSuccess', $location.absUrl(), oldUrl,\n        $location.$$state, oldState);\n    }\n}];\n}\n\n/**\n * @ngdoc service\n * @name $log\n * @requires $window\n *\n * @description\n * Simple service for logging. Default implementation safely writes the message\n * into the browser's console (if present).\n *\n * The main purpose of this service is to simplify debugging and troubleshooting.\n *\n * The default is to log `debug` messages. You can use\n * {@link ng.$logProvider ng.$logProvider#debugEnabled} to change this.\n *\n * @example\n   <example module=\"logExample\">\n     <file name=\"script.js\">\n       angular.module('logExample', [])\n         .controller('LogController', ['$scope', '$log', function($scope, $log) {\n           $scope.$log = $log;\n           $scope.message = 'Hello World!';\n         }]);\n     </file>\n     <file name=\"index.html\">\n       <div ng-controller=\"LogController\">\n         <p>Reload this page with open console, enter text and hit the log button...</p>\n         Message:\n         <input type=\"text\" ng-model=\"message\"/>\n         <button ng-click=\"$log.log(message)\">log</button>\n         <button ng-click=\"$log.warn(message)\">warn</button>\n         <button ng-click=\"$log.info(message)\">info</button>\n         <button ng-click=\"$log.error(message)\">error</button>\n       </div>\n     </file>\n   </example>\n */\n\n/**\n * @ngdoc provider\n * @name $logProvider\n * @description\n * Use the `$logProvider` to configure how the application logs messages\n */\nfunction $LogProvider() {\n  var debug = true,\n      self = this;\n\n  /**\n   * @ngdoc method\n   * @name $logProvider#debugEnabled\n   * @description\n   * @param {boolean=} flag enable or disable debug level messages\n   * @returns {*} current value if used as getter or itself (chaining) if used as setter\n   */\n  this.debugEnabled = function(flag) {\n    if (isDefined(flag)) {\n      debug = flag;\n    return this;\n    } else {\n      return debug;\n    }\n  };\n\n  this.$get = ['$window', function($window) {\n    return {\n      /**\n       * @ngdoc method\n       * @name $log#log\n       *\n       * @description\n       * Write a log message\n       */\n      log: consoleLog('log'),\n\n      /**\n       * @ngdoc method\n       * @name $log#info\n       *\n       * @description\n       * Write an information message\n       */\n      info: consoleLog('info'),\n\n      /**\n       * @ngdoc method\n       * @name $log#warn\n       *\n       * @description\n       * Write a warning message\n       */\n      warn: consoleLog('warn'),\n\n      /**\n       * @ngdoc method\n       * @name $log#error\n       *\n       * @description\n       * Write an error message\n       */\n      error: consoleLog('error'),\n\n      /**\n       * @ngdoc method\n       * @name $log#debug\n       *\n       * @description\n       * Write a debug message\n       */\n      debug: (function() {\n        var fn = consoleLog('debug');\n\n        return function() {\n          if (debug) {\n            fn.apply(self, arguments);\n          }\n        };\n      }())\n    };\n\n    function formatError(arg) {\n      if (arg instanceof Error) {\n        if (arg.stack) {\n          arg = (arg.message && arg.stack.indexOf(arg.message) === -1)\n              ? 'Error: ' + arg.message + '\\n' + arg.stack\n              : arg.stack;\n        } else if (arg.sourceURL) {\n          arg = arg.message + '\\n' + arg.sourceURL + ':' + arg.line;\n        }\n      }\n      return arg;\n    }\n\n    function consoleLog(type) {\n      var console = $window.console || {},\n          logFn = console[type] || console.log || noop,\n          hasApply = false;\n\n      // Note: reading logFn.apply throws an error in IE11 in IE8 document mode.\n      // The reason behind this is that console.log has type \"object\" in IE8...\n      try {\n        hasApply = !!logFn.apply;\n      } catch (e) {}\n\n      if (hasApply) {\n        return function() {\n          var args = [];\n          forEach(arguments, function(arg) {\n            args.push(formatError(arg));\n          });\n          return logFn.apply(console, args);\n        };\n      }\n\n      // we are IE which either doesn't have window.console => this is noop and we do nothing,\n      // or we are IE where console.log doesn't have apply so we log at least first 2 args\n      return function(arg1, arg2) {\n        logFn(arg1, arg2 == null ? '' : arg2);\n      };\n    }\n  }];\n}\n\nvar $parseMinErr = minErr('$parse');\n\n// Sandboxing Angular Expressions\n// ------------------------------\n// Angular expressions are generally considered safe because these expressions only have direct\n// access to `$scope` and locals. However, one can obtain the ability to execute arbitrary JS code by\n// obtaining a reference to native JS functions such as the Function constructor.\n//\n// As an example, consider the following Angular expression:\n//\n//   {}.toString.constructor('alert(\"evil JS code\")')\n//\n// This sandboxing technique is not perfect and doesn't aim to be. The goal is to prevent exploits\n// against the expression language, but not to prevent exploits that were enabled by exposing\n// sensitive JavaScript or browser APIs on Scope. Exposing such objects on a Scope is never a good\n// practice and therefore we are not even trying to protect against interaction with an object\n// explicitly exposed in this way.\n//\n// In general, it is not possible to access a Window object from an angular expression unless a\n// window or some DOM object that has a reference to window is published onto a Scope.\n// Similarly we prevent invocations of function known to be dangerous, as well as assignments to\n// native objects.\n//\n// See https://docs.angularjs.org/guide/security\n\n\nfunction ensureSafeMemberName(name, fullExpression) {\n  if (name === \"__defineGetter__\" || name === \"__defineSetter__\"\n      || name === \"__lookupGetter__\" || name === \"__lookupSetter__\"\n      || name === \"__proto__\") {\n    throw $parseMinErr('isecfld',\n        'Attempting to access a disallowed field in Angular expressions! '\n        + 'Expression: {0}', fullExpression);\n  }\n  return name;\n}\n\nfunction ensureSafeObject(obj, fullExpression) {\n  // nifty check if obj is Function that is fast and works across iframes and other contexts\n  if (obj) {\n    if (obj.constructor === obj) {\n      throw $parseMinErr('isecfn',\n          'Referencing Function in Angular expressions is disallowed! Expression: {0}',\n          fullExpression);\n    } else if (// isWindow(obj)\n        obj.window === obj) {\n      throw $parseMinErr('isecwindow',\n          'Referencing the Window in Angular expressions is disallowed! Expression: {0}',\n          fullExpression);\n    } else if (// isElement(obj)\n        obj.children && (obj.nodeName || (obj.prop && obj.attr && obj.find))) {\n      throw $parseMinErr('isecdom',\n          'Referencing DOM nodes in Angular expressions is disallowed! Expression: {0}',\n          fullExpression);\n    } else if (// block Object so that we can't get hold of dangerous Object.* methods\n        obj === Object) {\n      throw $parseMinErr('isecobj',\n          'Referencing Object in Angular expressions is disallowed! Expression: {0}',\n          fullExpression);\n    }\n  }\n  return obj;\n}\n\nvar CALL = Function.prototype.call;\nvar APPLY = Function.prototype.apply;\nvar BIND = Function.prototype.bind;\n\nfunction ensureSafeFunction(obj, fullExpression) {\n  if (obj) {\n    if (obj.constructor === obj) {\n      throw $parseMinErr('isecfn',\n        'Referencing Function in Angular expressions is disallowed! Expression: {0}',\n        fullExpression);\n    } else if (obj === CALL || obj === APPLY || obj === BIND) {\n      throw $parseMinErr('isecff',\n        'Referencing call, apply or bind in Angular expressions is disallowed! Expression: {0}',\n        fullExpression);\n    }\n  }\n}\n\n//Keyword constants\nvar CONSTANTS = createMap();\nforEach({\n  'null': function() { return null; },\n  'true': function() { return true; },\n  'false': function() { return false; },\n  'undefined': function() {}\n}, function(constantGetter, name) {\n  constantGetter.constant = constantGetter.literal = constantGetter.sharedGetter = true;\n  CONSTANTS[name] = constantGetter;\n});\n\n//Not quite a constant, but can be lex/parsed the same\nCONSTANTS['this'] = function(self) { return self; };\nCONSTANTS['this'].sharedGetter = true;\n\n\n//Operators - will be wrapped by binaryFn/unaryFn/assignment/filter\nvar OPERATORS = extend(createMap(), {\n    '+':function(self, locals, a, b) {\n      a=a(self, locals); b=b(self, locals);\n      if (isDefined(a)) {\n        if (isDefined(b)) {\n          return a + b;\n        }\n        return a;\n      }\n      return isDefined(b) ? b : undefined;},\n    '-':function(self, locals, a, b) {\n          a=a(self, locals); b=b(self, locals);\n          return (isDefined(a) ? a : 0) - (isDefined(b) ? b : 0);\n        },\n    '*':function(self, locals, a, b) {return a(self, locals) * b(self, locals);},\n    '/':function(self, locals, a, b) {return a(self, locals) / b(self, locals);},\n    '%':function(self, locals, a, b) {return a(self, locals) % b(self, locals);},\n    '===':function(self, locals, a, b) {return a(self, locals) === b(self, locals);},\n    '!==':function(self, locals, a, b) {return a(self, locals) !== b(self, locals);},\n    '==':function(self, locals, a, b) {return a(self, locals) == b(self, locals);},\n    '!=':function(self, locals, a, b) {return a(self, locals) != b(self, locals);},\n    '<':function(self, locals, a, b) {return a(self, locals) < b(self, locals);},\n    '>':function(self, locals, a, b) {return a(self, locals) > b(self, locals);},\n    '<=':function(self, locals, a, b) {return a(self, locals) <= b(self, locals);},\n    '>=':function(self, locals, a, b) {return a(self, locals) >= b(self, locals);},\n    '&&':function(self, locals, a, b) {return a(self, locals) && b(self, locals);},\n    '||':function(self, locals, a, b) {return a(self, locals) || b(self, locals);},\n    '!':function(self, locals, a) {return !a(self, locals);},\n\n    //Tokenized as operators but parsed as assignment/filters\n    '=':true,\n    '|':true\n});\nvar ESCAPE = {\"n\":\"\\n\", \"f\":\"\\f\", \"r\":\"\\r\", \"t\":\"\\t\", \"v\":\"\\v\", \"'\":\"'\", '\"':'\"'};\n\n\n/////////////////////////////////////////\n\n\n/**\n * @constructor\n */\nvar Lexer = function(options) {\n  this.options = options;\n};\n\nLexer.prototype = {\n  constructor: Lexer,\n\n  lex: function(text) {\n    this.text = text;\n    this.index = 0;\n    this.tokens = [];\n\n    while (this.index < this.text.length) {\n      var ch = this.text.charAt(this.index);\n      if (ch === '\"' || ch === \"'\") {\n        this.readString(ch);\n      } else if (this.isNumber(ch) || ch === '.' && this.isNumber(this.peek())) {\n        this.readNumber();\n      } else if (this.isIdent(ch)) {\n        this.readIdent();\n      } else if (this.is(ch, '(){}[].,;:?')) {\n        this.tokens.push({index: this.index, text: ch});\n        this.index++;\n      } else if (this.isWhitespace(ch)) {\n        this.index++;\n      } else {\n        var ch2 = ch + this.peek();\n        var ch3 = ch2 + this.peek(2);\n        var op1 = OPERATORS[ch];\n        var op2 = OPERATORS[ch2];\n        var op3 = OPERATORS[ch3];\n        if (op1 || op2 || op3) {\n          var token = op3 ? ch3 : (op2 ? ch2 : ch);\n          this.tokens.push({index: this.index, text: token, operator: true});\n          this.index += token.length;\n        } else {\n          this.throwError('Unexpected next character ', this.index, this.index + 1);\n        }\n      }\n    }\n    return this.tokens;\n  },\n\n  is: function(ch, chars) {\n    return chars.indexOf(ch) !== -1;\n  },\n\n  peek: function(i) {\n    var num = i || 1;\n    return (this.index + num < this.text.length) ? this.text.charAt(this.index + num) : false;\n  },\n\n  isNumber: function(ch) {\n    return ('0' <= ch && ch <= '9') && typeof ch === \"string\";\n  },\n\n  isWhitespace: function(ch) {\n    // IE treats non-breaking space as \\u00A0\n    return (ch === ' ' || ch === '\\r' || ch === '\\t' ||\n            ch === '\\n' || ch === '\\v' || ch === '\\u00A0');\n  },\n\n  isIdent: function(ch) {\n    return ('a' <= ch && ch <= 'z' ||\n            'A' <= ch && ch <= 'Z' ||\n            '_' === ch || ch === '$');\n  },\n\n  isExpOperator: function(ch) {\n    return (ch === '-' || ch === '+' || this.isNumber(ch));\n  },\n\n  throwError: function(error, start, end) {\n    end = end || this.index;\n    var colStr = (isDefined(start)\n            ? 's ' + start +  '-' + this.index + ' [' + this.text.substring(start, end) + ']'\n            : ' ' + end);\n    throw $parseMinErr('lexerr', 'Lexer Error: {0} at column{1} in expression [{2}].',\n        error, colStr, this.text);\n  },\n\n  readNumber: function() {\n    var number = '';\n    var start = this.index;\n    while (this.index < this.text.length) {\n      var ch = lowercase(this.text.charAt(this.index));\n      if (ch == '.' || this.isNumber(ch)) {\n        number += ch;\n      } else {\n        var peekCh = this.peek();\n        if (ch == 'e' && this.isExpOperator(peekCh)) {\n          number += ch;\n        } else if (this.isExpOperator(ch) &&\n            peekCh && this.isNumber(peekCh) &&\n            number.charAt(number.length - 1) == 'e') {\n          number += ch;\n        } else if (this.isExpOperator(ch) &&\n            (!peekCh || !this.isNumber(peekCh)) &&\n            number.charAt(number.length - 1) == 'e') {\n          this.throwError('Invalid exponent');\n        } else {\n          break;\n        }\n      }\n      this.index++;\n    }\n    this.tokens.push({\n      index: start,\n      text: number,\n      constant: true,\n      value: Number(number)\n    });\n  },\n\n  readIdent: function() {\n    var start = this.index;\n    while (this.index < this.text.length) {\n      var ch = this.text.charAt(this.index);\n      if (!(this.isIdent(ch) || this.isNumber(ch))) {\n        break;\n      }\n      this.index++;\n    }\n    this.tokens.push({\n      index: start,\n      text: this.text.slice(start, this.index),\n      identifier: true\n    });\n  },\n\n  readString: function(quote) {\n    var start = this.index;\n    this.index++;\n    var string = '';\n    var rawString = quote;\n    var escape = false;\n    while (this.index < this.text.length) {\n      var ch = this.text.charAt(this.index);\n      rawString += ch;\n      if (escape) {\n        if (ch === 'u') {\n          var hex = this.text.substring(this.index + 1, this.index + 5);\n          if (!hex.match(/[\\da-f]{4}/i))\n            this.throwError('Invalid unicode escape [\\\\u' + hex + ']');\n          this.index += 4;\n          string += String.fromCharCode(parseInt(hex, 16));\n        } else {\n          var rep = ESCAPE[ch];\n          string = string + (rep || ch);\n        }\n        escape = false;\n      } else if (ch === '\\\\') {\n        escape = true;\n      } else if (ch === quote) {\n        this.index++;\n        this.tokens.push({\n          index: start,\n          text: rawString,\n          constant: true,\n          value: string\n        });\n        return;\n      } else {\n        string += ch;\n      }\n      this.index++;\n    }\n    this.throwError('Unterminated quote', start);\n  }\n};\n\n\nfunction isConstant(exp) {\n  return exp.constant;\n}\n\n/**\n * @constructor\n */\nvar Parser = function(lexer, $filter, options) {\n  this.lexer = lexer;\n  this.$filter = $filter;\n  this.options = options;\n};\n\nParser.ZERO = extend(function() {\n  return 0;\n}, {\n  sharedGetter: true,\n  constant: true\n});\n\nParser.prototype = {\n  constructor: Parser,\n\n  parse: function(text) {\n    this.text = text;\n    this.tokens = this.lexer.lex(text);\n\n    var value = this.statements();\n\n    if (this.tokens.length !== 0) {\n      this.throwError('is an unexpected token', this.tokens[0]);\n    }\n\n    value.literal = !!value.literal;\n    value.constant = !!value.constant;\n\n    return value;\n  },\n\n  primary: function() {\n    var primary;\n    if (this.expect('(')) {\n      primary = this.filterChain();\n      this.consume(')');\n    } else if (this.expect('[')) {\n      primary = this.arrayDeclaration();\n    } else if (this.expect('{')) {\n      primary = this.object();\n    } else if (this.peek().identifier && this.peek().text in CONSTANTS) {\n      primary = CONSTANTS[this.consume().text];\n    } else if (this.peek().identifier) {\n      primary = this.identifier();\n    } else if (this.peek().constant) {\n      primary = this.constant();\n    } else {\n      this.throwError('not a primary expression', this.peek());\n    }\n\n    var next, context;\n    while ((next = this.expect('(', '[', '.'))) {\n      if (next.text === '(') {\n        primary = this.functionCall(primary, context);\n        context = null;\n      } else if (next.text === '[') {\n        context = primary;\n        primary = this.objectIndex(primary);\n      } else if (next.text === '.') {\n        context = primary;\n        primary = this.fieldAccess(primary);\n      } else {\n        this.throwError('IMPOSSIBLE');\n      }\n    }\n    return primary;\n  },\n\n  throwError: function(msg, token) {\n    throw $parseMinErr('syntax',\n        'Syntax Error: Token \\'{0}\\' {1} at column {2} of the expression [{3}] starting at [{4}].',\n          token.text, msg, (token.index + 1), this.text, this.text.substring(token.index));\n  },\n\n  peekToken: function() {\n    if (this.tokens.length === 0)\n      throw $parseMinErr('ueoe', 'Unexpected end of expression: {0}', this.text);\n    return this.tokens[0];\n  },\n\n  peek: function(e1, e2, e3, e4) {\n    return this.peekAhead(0, e1, e2, e3, e4);\n  },\n  peekAhead: function(i, e1, e2, e3, e4) {\n    if (this.tokens.length > i) {\n      var token = this.tokens[i];\n      var t = token.text;\n      if (t === e1 || t === e2 || t === e3 || t === e4 ||\n          (!e1 && !e2 && !e3 && !e4)) {\n        return token;\n      }\n    }\n    return false;\n  },\n\n  expect: function(e1, e2, e3, e4) {\n    var token = this.peek(e1, e2, e3, e4);\n    if (token) {\n      this.tokens.shift();\n      return token;\n    }\n    return false;\n  },\n\n  consume: function(e1) {\n    if (this.tokens.length === 0) {\n      throw $parseMinErr('ueoe', 'Unexpected end of expression: {0}', this.text);\n    }\n\n    var token = this.expect(e1);\n    if (!token) {\n      this.throwError('is unexpected, expecting [' + e1 + ']', this.peek());\n    }\n    return token;\n  },\n\n  unaryFn: function(op, right) {\n    var fn = OPERATORS[op];\n    return extend(function $parseUnaryFn(self, locals) {\n      return fn(self, locals, right);\n    }, {\n      constant:right.constant,\n      inputs: [right]\n    });\n  },\n\n  binaryFn: function(left, op, right, isBranching) {\n    var fn = OPERATORS[op];\n    return extend(function $parseBinaryFn(self, locals) {\n      return fn(self, locals, left, right);\n    }, {\n      constant: left.constant && right.constant,\n      inputs: !isBranching && [left, right]\n    });\n  },\n\n  identifier: function() {\n    var id = this.consume().text;\n\n    //Continue reading each `.identifier` unless it is a method invocation\n    while (this.peek('.') && this.peekAhead(1).identifier && !this.peekAhead(2, '(')) {\n      id += this.consume().text + this.consume().text;\n    }\n\n    return getterFn(id, this.options, this.text);\n  },\n\n  constant: function() {\n    var value = this.consume().value;\n\n    return extend(function $parseConstant() {\n      return value;\n    }, {\n      constant: true,\n      literal: true\n    });\n  },\n\n  statements: function() {\n    var statements = [];\n    while (true) {\n      if (this.tokens.length > 0 && !this.peek('}', ')', ';', ']'))\n        statements.push(this.filterChain());\n      if (!this.expect(';')) {\n        // optimize for the common case where there is only one statement.\n        // TODO(size): maybe we should not support multiple statements?\n        return (statements.length === 1)\n            ? statements[0]\n            : function $parseStatements(self, locals) {\n                var value;\n                for (var i = 0, ii = statements.length; i < ii; i++) {\n                  value = statements[i](self, locals);\n                }\n                return value;\n              };\n      }\n    }\n  },\n\n  filterChain: function() {\n    var left = this.expression();\n    var token;\n    while ((token = this.expect('|'))) {\n      left = this.filter(left);\n    }\n    return left;\n  },\n\n  filter: function(inputFn) {\n    var fn = this.$filter(this.consume().text);\n    var argsFn;\n    var args;\n\n    if (this.peek(':')) {\n      argsFn = [];\n      args = []; // we can safely reuse the array\n      while (this.expect(':')) {\n        argsFn.push(this.expression());\n      }\n    }\n\n    var inputs = [inputFn].concat(argsFn || []);\n\n    return extend(function $parseFilter(self, locals) {\n      var input = inputFn(self, locals);\n      if (args) {\n        args[0] = input;\n\n        var i = argsFn.length;\n        while (i--) {\n          args[i + 1] = argsFn[i](self, locals);\n        }\n\n        return fn.apply(undefined, args);\n      }\n\n      return fn(input);\n    }, {\n      constant: !fn.$stateful && inputs.every(isConstant),\n      inputs: !fn.$stateful && inputs\n    });\n  },\n\n  expression: function() {\n    return this.assignment();\n  },\n\n  assignment: function() {\n    var left = this.ternary();\n    var right;\n    var token;\n    if ((token = this.expect('='))) {\n      if (!left.assign) {\n        this.throwError('implies assignment but [' +\n            this.text.substring(0, token.index) + '] can not be assigned to', token);\n      }\n      right = this.ternary();\n      return extend(function $parseAssignment(scope, locals) {\n        return left.assign(scope, right(scope, locals), locals);\n      }, {\n        inputs: [left, right]\n      });\n    }\n    return left;\n  },\n\n  ternary: function() {\n    var left = this.logicalOR();\n    var middle;\n    var token;\n    if ((token = this.expect('?'))) {\n      middle = this.assignment();\n      if (this.consume(':')) {\n        var right = this.assignment();\n\n        return extend(function $parseTernary(self, locals) {\n          return left(self, locals) ? middle(self, locals) : right(self, locals);\n        }, {\n          constant: left.constant && middle.constant && right.constant\n        });\n      }\n    }\n\n    return left;\n  },\n\n  logicalOR: function() {\n    var left = this.logicalAND();\n    var token;\n    while ((token = this.expect('||'))) {\n      left = this.binaryFn(left, token.text, this.logicalAND(), true);\n    }\n    return left;\n  },\n\n  logicalAND: function() {\n    var left = this.equality();\n    var token;\n    while ((token = this.expect('&&'))) {\n      left = this.binaryFn(left, token.text, this.equality(), true);\n    }\n    return left;\n  },\n\n  equality: function() {\n    var left = this.relational();\n    var token;\n    while ((token = this.expect('==','!=','===','!=='))) {\n      left = this.binaryFn(left, token.text, this.relational());\n    }\n    return left;\n  },\n\n  relational: function() {\n    var left = this.additive();\n    var token;\n    while ((token = this.expect('<', '>', '<=', '>='))) {\n      left = this.binaryFn(left, token.text, this.additive());\n    }\n    return left;\n  },\n\n  additive: function() {\n    var left = this.multiplicative();\n    var token;\n    while ((token = this.expect('+','-'))) {\n      left = this.binaryFn(left, token.text, this.multiplicative());\n    }\n    return left;\n  },\n\n  multiplicative: function() {\n    var left = this.unary();\n    var token;\n    while ((token = this.expect('*','/','%'))) {\n      left = this.binaryFn(left, token.text, this.unary());\n    }\n    return left;\n  },\n\n  unary: function() {\n    var token;\n    if (this.expect('+')) {\n      return this.primary();\n    } else if ((token = this.expect('-'))) {\n      return this.binaryFn(Parser.ZERO, token.text, this.unary());\n    } else if ((token = this.expect('!'))) {\n      return this.unaryFn(token.text, this.unary());\n    } else {\n      return this.primary();\n    }\n  },\n\n  fieldAccess: function(object) {\n    var getter = this.identifier();\n\n    return extend(function $parseFieldAccess(scope, locals, self) {\n      var o = self || object(scope, locals);\n      return (o == null) ? undefined : getter(o);\n    }, {\n      assign: function(scope, value, locals) {\n        var o = object(scope, locals);\n        if (!o) object.assign(scope, o = {}, locals);\n        return getter.assign(o, value);\n      }\n    });\n  },\n\n  objectIndex: function(obj) {\n    var expression = this.text;\n\n    var indexFn = this.expression();\n    this.consume(']');\n\n    return extend(function $parseObjectIndex(self, locals) {\n      var o = obj(self, locals),\n          i = indexFn(self, locals),\n          v;\n\n      ensureSafeMemberName(i, expression);\n      if (!o) return undefined;\n      v = ensureSafeObject(o[i], expression);\n      return v;\n    }, {\n      assign: function(self, value, locals) {\n        var key = ensureSafeMemberName(indexFn(self, locals), expression);\n        // prevent overwriting of Function.constructor which would break ensureSafeObject check\n        var o = ensureSafeObject(obj(self, locals), expression);\n        if (!o) obj.assign(self, o = {}, locals);\n        return o[key] = value;\n      }\n    });\n  },\n\n  functionCall: function(fnGetter, contextGetter) {\n    var argsFn = [];\n    if (this.peekToken().text !== ')') {\n      do {\n        argsFn.push(this.expression());\n      } while (this.expect(','));\n    }\n    this.consume(')');\n\n    var expressionText = this.text;\n    // we can safely reuse the array across invocations\n    var args = argsFn.length ? [] : null;\n\n    return function $parseFunctionCall(scope, locals) {\n      var context = contextGetter ? contextGetter(scope, locals) : isDefined(contextGetter) ? undefined : scope;\n      var fn = fnGetter(scope, locals, context) || noop;\n\n      if (args) {\n        var i = argsFn.length;\n        while (i--) {\n          args[i] = ensureSafeObject(argsFn[i](scope, locals), expressionText);\n        }\n      }\n\n      ensureSafeObject(context, expressionText);\n      ensureSafeFunction(fn, expressionText);\n\n      // IE doesn't have apply for some native functions\n      var v = fn.apply\n            ? fn.apply(context, args)\n            : fn(args[0], args[1], args[2], args[3], args[4]);\n\n      if (args) {\n        // Free-up the memory (arguments of the last function call).\n        args.length = 0;\n      }\n\n      return ensureSafeObject(v, expressionText);\n      };\n  },\n\n  // This is used with json array declaration\n  arrayDeclaration: function() {\n    var elementFns = [];\n    if (this.peekToken().text !== ']') {\n      do {\n        if (this.peek(']')) {\n          // Support trailing commas per ES5.1.\n          break;\n        }\n        elementFns.push(this.expression());\n      } while (this.expect(','));\n    }\n    this.consume(']');\n\n    return extend(function $parseArrayLiteral(self, locals) {\n      var array = [];\n      for (var i = 0, ii = elementFns.length; i < ii; i++) {\n        array.push(elementFns[i](self, locals));\n      }\n      return array;\n    }, {\n      literal: true,\n      constant: elementFns.every(isConstant),\n      inputs: elementFns\n    });\n  },\n\n  object: function() {\n    var keys = [], valueFns = [];\n    if (this.peekToken().text !== '}') {\n      do {\n        if (this.peek('}')) {\n          // Support trailing commas per ES5.1.\n          break;\n        }\n        var token = this.consume();\n        if (token.constant) {\n          keys.push(token.value);\n        } else if (token.identifier) {\n          keys.push(token.text);\n        } else {\n          this.throwError(\"invalid key\", token);\n        }\n        this.consume(':');\n        valueFns.push(this.expression());\n      } while (this.expect(','));\n    }\n    this.consume('}');\n\n    return extend(function $parseObjectLiteral(self, locals) {\n      var object = {};\n      for (var i = 0, ii = valueFns.length; i < ii; i++) {\n        object[keys[i]] = valueFns[i](self, locals);\n      }\n      return object;\n    }, {\n      literal: true,\n      constant: valueFns.every(isConstant),\n      inputs: valueFns\n    });\n  }\n};\n\n\n//////////////////////////////////////////////////\n// Parser helper functions\n//////////////////////////////////////////////////\n\nfunction setter(obj, locals, path, setValue, fullExp) {\n  ensureSafeObject(obj, fullExp);\n  ensureSafeObject(locals, fullExp);\n\n  var element = path.split('.'), key;\n  for (var i = 0; element.length > 1; i++) {\n    key = ensureSafeMemberName(element.shift(), fullExp);\n    var propertyObj = (i === 0 && locals && locals[key]) || obj[key];\n    if (!propertyObj) {\n      propertyObj = {};\n      obj[key] = propertyObj;\n    }\n    obj = ensureSafeObject(propertyObj, fullExp);\n  }\n  key = ensureSafeMemberName(element.shift(), fullExp);\n  ensureSafeObject(obj[key], fullExp);\n  obj[key] = setValue;\n  return setValue;\n}\n\nvar getterFnCacheDefault = createMap();\nvar getterFnCacheExpensive = createMap();\n\nfunction isPossiblyDangerousMemberName(name) {\n  return name == 'constructor';\n}\n\n/**\n * Implementation of the \"Black Hole\" variant from:\n * - http://jsperf.com/angularjs-parse-getter/4\n * - http://jsperf.com/path-evaluation-simplified/7\n */\nfunction cspSafeGetterFn(key0, key1, key2, key3, key4, fullExp, expensiveChecks) {\n  ensureSafeMemberName(key0, fullExp);\n  ensureSafeMemberName(key1, fullExp);\n  ensureSafeMemberName(key2, fullExp);\n  ensureSafeMemberName(key3, fullExp);\n  ensureSafeMemberName(key4, fullExp);\n  var eso = function(o) {\n    return ensureSafeObject(o, fullExp);\n  };\n  var eso0 = (expensiveChecks || isPossiblyDangerousMemberName(key0)) ? eso : identity;\n  var eso1 = (expensiveChecks || isPossiblyDangerousMemberName(key1)) ? eso : identity;\n  var eso2 = (expensiveChecks || isPossiblyDangerousMemberName(key2)) ? eso : identity;\n  var eso3 = (expensiveChecks || isPossiblyDangerousMemberName(key3)) ? eso : identity;\n  var eso4 = (expensiveChecks || isPossiblyDangerousMemberName(key4)) ? eso : identity;\n\n  return function cspSafeGetter(scope, locals) {\n    var pathVal = (locals && locals.hasOwnProperty(key0)) ? locals : scope;\n\n    if (pathVal == null) return pathVal;\n    pathVal = eso0(pathVal[key0]);\n\n    if (!key1) return pathVal;\n    if (pathVal == null) return undefined;\n    pathVal = eso1(pathVal[key1]);\n\n    if (!key2) return pathVal;\n    if (pathVal == null) return undefined;\n    pathVal = eso2(pathVal[key2]);\n\n    if (!key3) return pathVal;\n    if (pathVal == null) return undefined;\n    pathVal = eso3(pathVal[key3]);\n\n    if (!key4) return pathVal;\n    if (pathVal == null) return undefined;\n    pathVal = eso4(pathVal[key4]);\n\n    return pathVal;\n  };\n}\n\nfunction getterFnWithEnsureSafeObject(fn, fullExpression) {\n  return function(s, l) {\n    return fn(s, l, ensureSafeObject, fullExpression);\n  };\n}\n\nfunction getterFn(path, options, fullExp) {\n  var expensiveChecks = options.expensiveChecks;\n  var getterFnCache = (expensiveChecks ? getterFnCacheExpensive : getterFnCacheDefault);\n  var fn = getterFnCache[path];\n  if (fn) return fn;\n\n\n  var pathKeys = path.split('.'),\n      pathKeysLength = pathKeys.length;\n\n  // http://jsperf.com/angularjs-parse-getter/6\n  if (options.csp) {\n    if (pathKeysLength < 6) {\n      fn = cspSafeGetterFn(pathKeys[0], pathKeys[1], pathKeys[2], pathKeys[3], pathKeys[4], fullExp, expensiveChecks);\n    } else {\n      fn = function cspSafeGetter(scope, locals) {\n        var i = 0, val;\n        do {\n          val = cspSafeGetterFn(pathKeys[i++], pathKeys[i++], pathKeys[i++], pathKeys[i++],\n                                pathKeys[i++], fullExp, expensiveChecks)(scope, locals);\n\n          locals = undefined; // clear after first iteration\n          scope = val;\n        } while (i < pathKeysLength);\n        return val;\n      };\n    }\n  } else {\n    var code = '';\n    if (expensiveChecks) {\n      code += 's = eso(s, fe);\\nl = eso(l, fe);\\n';\n    }\n    var needsEnsureSafeObject = expensiveChecks;\n    forEach(pathKeys, function(key, index) {\n      ensureSafeMemberName(key, fullExp);\n      var lookupJs = (index\n                      // we simply dereference 's' on any .dot notation\n                      ? 's'\n                      // but if we are first then we check locals first, and if so read it first\n                      : '((l&&l.hasOwnProperty(\"' + key + '\"))?l:s)') + '.' + key;\n      if (expensiveChecks || isPossiblyDangerousMemberName(key)) {\n        lookupJs = 'eso(' + lookupJs + ', fe)';\n        needsEnsureSafeObject = true;\n      }\n      code += 'if(s == null) return undefined;\\n' +\n              's=' + lookupJs + ';\\n';\n    });\n    code += 'return s;';\n\n    /* jshint -W054 */\n    var evaledFnGetter = new Function('s', 'l', 'eso', 'fe', code); // s=scope, l=locals, eso=ensureSafeObject\n    /* jshint +W054 */\n    evaledFnGetter.toString = valueFn(code);\n    if (needsEnsureSafeObject) {\n      evaledFnGetter = getterFnWithEnsureSafeObject(evaledFnGetter, fullExp);\n    }\n    fn = evaledFnGetter;\n  }\n\n  fn.sharedGetter = true;\n  fn.assign = function(self, value, locals) {\n    return setter(self, locals, path, value, path);\n  };\n  getterFnCache[path] = fn;\n  return fn;\n}\n\nvar objectValueOf = Object.prototype.valueOf;\n\nfunction getValueOf(value) {\n  return isFunction(value.valueOf) ? value.valueOf() : objectValueOf.call(value);\n}\n\n///////////////////////////////////\n\n/**\n * @ngdoc service\n * @name $parse\n * @kind function\n *\n * @description\n *\n * Converts Angular {@link guide/expression expression} into a function.\n *\n * ```js\n *   var getter = $parse('user.name');\n *   var setter = getter.assign;\n *   var context = {user:{name:'angular'}};\n *   var locals = {user:{name:'local'}};\n *\n *   expect(getter(context)).toEqual('angular');\n *   setter(context, 'newValue');\n *   expect(context.user.name).toEqual('newValue');\n *   expect(getter(context, locals)).toEqual('local');\n * ```\n *\n *\n * @param {string} expression String expression to compile.\n * @returns {function(context, locals)} a function which represents the compiled expression:\n *\n *    * `context` – `{object}` – an object against which any expressions embedded in the strings\n *      are evaluated against (typically a scope object).\n *    * `locals` – `{object=}` – local variables context object, useful for overriding values in\n *      `context`.\n *\n *    The returned function also has the following properties:\n *      * `literal` – `{boolean}` – whether the expression's top-level node is a JavaScript\n *        literal.\n *      * `constant` – `{boolean}` – whether the expression is made entirely of JavaScript\n *        constant literals.\n *      * `assign` – `{?function(context, value)}` – if the expression is assignable, this will be\n *        set to a function to change its value on the given context.\n *\n */\n\n\n/**\n * @ngdoc provider\n * @name $parseProvider\n *\n * @description\n * `$parseProvider` can be used for configuring the default behavior of the {@link ng.$parse $parse}\n *  service.\n */\nfunction $ParseProvider() {\n  var cacheDefault = createMap();\n  var cacheExpensive = createMap();\n\n\n\n  this.$get = ['$filter', '$sniffer', function($filter, $sniffer) {\n    var $parseOptions = {\n          csp: $sniffer.csp,\n          expensiveChecks: false\n        },\n        $parseOptionsExpensive = {\n          csp: $sniffer.csp,\n          expensiveChecks: true\n        };\n\n    function wrapSharedExpression(exp) {\n      var wrapped = exp;\n\n      if (exp.sharedGetter) {\n        wrapped = function $parseWrapper(self, locals) {\n          return exp(self, locals);\n        };\n        wrapped.literal = exp.literal;\n        wrapped.constant = exp.constant;\n        wrapped.assign = exp.assign;\n      }\n\n      return wrapped;\n    }\n\n    return function $parse(exp, interceptorFn, expensiveChecks) {\n      var parsedExpression, oneTime, cacheKey;\n\n      switch (typeof exp) {\n        case 'string':\n          cacheKey = exp = exp.trim();\n\n          var cache = (expensiveChecks ? cacheExpensive : cacheDefault);\n          parsedExpression = cache[cacheKey];\n\n          if (!parsedExpression) {\n            if (exp.charAt(0) === ':' && exp.charAt(1) === ':') {\n              oneTime = true;\n              exp = exp.substring(2);\n            }\n\n            var parseOptions = expensiveChecks ? $parseOptionsExpensive : $parseOptions;\n            var lexer = new Lexer(parseOptions);\n            var parser = new Parser(lexer, $filter, parseOptions);\n            parsedExpression = parser.parse(exp);\n\n            if (parsedExpression.constant) {\n              parsedExpression.$$watchDelegate = constantWatchDelegate;\n            } else if (oneTime) {\n              //oneTime is not part of the exp passed to the Parser so we may have to\n              //wrap the parsedExpression before adding a $$watchDelegate\n              parsedExpression = wrapSharedExpression(parsedExpression);\n              parsedExpression.$$watchDelegate = parsedExpression.literal ?\n                oneTimeLiteralWatchDelegate : oneTimeWatchDelegate;\n            } else if (parsedExpression.inputs) {\n              parsedExpression.$$watchDelegate = inputsWatchDelegate;\n            }\n\n            cache[cacheKey] = parsedExpression;\n          }\n          return addInterceptor(parsedExpression, interceptorFn);\n\n        case 'function':\n          return addInterceptor(exp, interceptorFn);\n\n        default:\n          return addInterceptor(noop, interceptorFn);\n      }\n    };\n\n    function collectExpressionInputs(inputs, list) {\n      for (var i = 0, ii = inputs.length; i < ii; i++) {\n        var input = inputs[i];\n        if (!input.constant) {\n          if (input.inputs) {\n            collectExpressionInputs(input.inputs, list);\n          } else if (list.indexOf(input) === -1) { // TODO(perf) can we do better?\n            list.push(input);\n          }\n        }\n      }\n\n      return list;\n    }\n\n    function expressionInputDirtyCheck(newValue, oldValueOfValue) {\n\n      if (newValue == null || oldValueOfValue == null) { // null/undefined\n        return newValue === oldValueOfValue;\n      }\n\n      if (typeof newValue === 'object') {\n\n        // attempt to convert the value to a primitive type\n        // TODO(docs): add a note to docs that by implementing valueOf even objects and arrays can\n        //             be cheaply dirty-checked\n        newValue = getValueOf(newValue);\n\n        if (typeof newValue === 'object') {\n          // objects/arrays are not supported - deep-watching them would be too expensive\n          return false;\n        }\n\n        // fall-through to the primitive equality check\n      }\n\n      //Primitive or NaN\n      return newValue === oldValueOfValue || (newValue !== newValue && oldValueOfValue !== oldValueOfValue);\n    }\n\n    function inputsWatchDelegate(scope, listener, objectEquality, parsedExpression) {\n      var inputExpressions = parsedExpression.$$inputs ||\n                    (parsedExpression.$$inputs = collectExpressionInputs(parsedExpression.inputs, []));\n\n      var lastResult;\n\n      if (inputExpressions.length === 1) {\n        var oldInputValue = expressionInputDirtyCheck; // init to something unique so that equals check fails\n        inputExpressions = inputExpressions[0];\n        return scope.$watch(function expressionInputWatch(scope) {\n          var newInputValue = inputExpressions(scope);\n          if (!expressionInputDirtyCheck(newInputValue, oldInputValue)) {\n            lastResult = parsedExpression(scope);\n            oldInputValue = newInputValue && getValueOf(newInputValue);\n          }\n          return lastResult;\n        }, listener, objectEquality);\n      }\n\n      var oldInputValueOfValues = [];\n      for (var i = 0, ii = inputExpressions.length; i < ii; i++) {\n        oldInputValueOfValues[i] = expressionInputDirtyCheck; // init to something unique so that equals check fails\n      }\n\n      return scope.$watch(function expressionInputsWatch(scope) {\n        var changed = false;\n\n        for (var i = 0, ii = inputExpressions.length; i < ii; i++) {\n          var newInputValue = inputExpressions[i](scope);\n          if (changed || (changed = !expressionInputDirtyCheck(newInputValue, oldInputValueOfValues[i]))) {\n            oldInputValueOfValues[i] = newInputValue && getValueOf(newInputValue);\n          }\n        }\n\n        if (changed) {\n          lastResult = parsedExpression(scope);\n        }\n\n        return lastResult;\n      }, listener, objectEquality);\n    }\n\n    function oneTimeWatchDelegate(scope, listener, objectEquality, parsedExpression) {\n      var unwatch, lastValue;\n      return unwatch = scope.$watch(function oneTimeWatch(scope) {\n        return parsedExpression(scope);\n      }, function oneTimeListener(value, old, scope) {\n        lastValue = value;\n        if (isFunction(listener)) {\n          listener.apply(this, arguments);\n        }\n        if (isDefined(value)) {\n          scope.$$postDigest(function() {\n            if (isDefined(lastValue)) {\n              unwatch();\n            }\n          });\n        }\n      }, objectEquality);\n    }\n\n    function oneTimeLiteralWatchDelegate(scope, listener, objectEquality, parsedExpression) {\n      var unwatch, lastValue;\n      return unwatch = scope.$watch(function oneTimeWatch(scope) {\n        return parsedExpression(scope);\n      }, function oneTimeListener(value, old, scope) {\n        lastValue = value;\n        if (isFunction(listener)) {\n          listener.call(this, value, old, scope);\n        }\n        if (isAllDefined(value)) {\n          scope.$$postDigest(function() {\n            if (isAllDefined(lastValue)) unwatch();\n          });\n        }\n      }, objectEquality);\n\n      function isAllDefined(value) {\n        var allDefined = true;\n        forEach(value, function(val) {\n          if (!isDefined(val)) allDefined = false;\n        });\n        return allDefined;\n      }\n    }\n\n    function constantWatchDelegate(scope, listener, objectEquality, parsedExpression) {\n      var unwatch;\n      return unwatch = scope.$watch(function constantWatch(scope) {\n        return parsedExpression(scope);\n      }, function constantListener(value, old, scope) {\n        if (isFunction(listener)) {\n          listener.apply(this, arguments);\n        }\n        unwatch();\n      }, objectEquality);\n    }\n\n    function addInterceptor(parsedExpression, interceptorFn) {\n      if (!interceptorFn) return parsedExpression;\n      var watchDelegate = parsedExpression.$$watchDelegate;\n\n      var regularWatch =\n          watchDelegate !== oneTimeLiteralWatchDelegate &&\n          watchDelegate !== oneTimeWatchDelegate;\n\n      var fn = regularWatch ? function regularInterceptedExpression(scope, locals) {\n        var value = parsedExpression(scope, locals);\n        return interceptorFn(value, scope, locals);\n      } : function oneTimeInterceptedExpression(scope, locals) {\n        var value = parsedExpression(scope, locals);\n        var result = interceptorFn(value, scope, locals);\n        // we only return the interceptor's result if the\n        // initial value is defined (for bind-once)\n        return isDefined(value) ? result : value;\n      };\n\n      // Propagate $$watchDelegates other then inputsWatchDelegate\n      if (parsedExpression.$$watchDelegate &&\n          parsedExpression.$$watchDelegate !== inputsWatchDelegate) {\n        fn.$$watchDelegate = parsedExpression.$$watchDelegate;\n      } else if (!interceptorFn.$stateful) {\n        // If there is an interceptor, but no watchDelegate then treat the interceptor like\n        // we treat filters - it is assumed to be a pure function unless flagged with $stateful\n        fn.$$watchDelegate = inputsWatchDelegate;\n        fn.inputs = [parsedExpression];\n      }\n\n      return fn;\n    }\n  }];\n}\n\n/**\n * @ngdoc service\n * @name $q\n * @requires $rootScope\n *\n * @description\n * A service that helps you run functions asynchronously, and use their return values (or exceptions)\n * when they are done processing.\n *\n * This is an implementation of promises/deferred objects inspired by\n * [Kris Kowal's Q](https://github.com/kriskowal/q).\n *\n * $q can be used in two fashions --- one which is more similar to Kris Kowal's Q or jQuery's Deferred\n * implementations, and the other which resembles ES6 promises to some degree.\n *\n * # $q constructor\n *\n * The streamlined ES6 style promise is essentially just using $q as a constructor which takes a `resolver`\n * function as the first argument. This is similar to the native Promise implementation from ES6 Harmony,\n * see [MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise).\n *\n * While the constructor-style use is supported, not all of the supporting methods from ES6 Harmony promises are\n * available yet.\n *\n * It can be used like so:\n *\n * ```js\n *   // for the purpose of this example let's assume that variables `$q` and `okToGreet`\n *   // are available in the current lexical scope (they could have been injected or passed in).\n *\n *   function asyncGreet(name) {\n *     // perform some asynchronous operation, resolve or reject the promise when appropriate.\n *     return $q(function(resolve, reject) {\n *       setTimeout(function() {\n *         if (okToGreet(name)) {\n *           resolve('Hello, ' + name + '!');\n *         } else {\n *           reject('Greeting ' + name + ' is not allowed.');\n *         }\n *       }, 1000);\n *     });\n *   }\n *\n *   var promise = asyncGreet('Robin Hood');\n *   promise.then(function(greeting) {\n *     alert('Success: ' + greeting);\n *   }, function(reason) {\n *     alert('Failed: ' + reason);\n *   });\n * ```\n *\n * Note: progress/notify callbacks are not currently supported via the ES6-style interface.\n *\n * However, the more traditional CommonJS-style usage is still available, and documented below.\n *\n * [The CommonJS Promise proposal](http://wiki.commonjs.org/wiki/Promises) describes a promise as an\n * interface for interacting with an object that represents the result of an action that is\n * performed asynchronously, and may or may not be finished at any given point in time.\n *\n * From the perspective of dealing with error handling, deferred and promise APIs are to\n * asynchronous programming what `try`, `catch` and `throw` keywords are to synchronous programming.\n *\n * ```js\n *   // for the purpose of this example let's assume that variables `$q` and `okToGreet`\n *   // are available in the current lexical scope (they could have been injected or passed in).\n *\n *   function asyncGreet(name) {\n *     var deferred = $q.defer();\n *\n *     setTimeout(function() {\n *       deferred.notify('About to greet ' + name + '.');\n *\n *       if (okToGreet(name)) {\n *         deferred.resolve('Hello, ' + name + '!');\n *       } else {\n *         deferred.reject('Greeting ' + name + ' is not allowed.');\n *       }\n *     }, 1000);\n *\n *     return deferred.promise;\n *   }\n *\n *   var promise = asyncGreet('Robin Hood');\n *   promise.then(function(greeting) {\n *     alert('Success: ' + greeting);\n *   }, function(reason) {\n *     alert('Failed: ' + reason);\n *   }, function(update) {\n *     alert('Got notification: ' + update);\n *   });\n * ```\n *\n * At first it might not be obvious why this extra complexity is worth the trouble. The payoff\n * comes in the way of guarantees that promise and deferred APIs make, see\n * https://github.com/kriskowal/uncommonjs/blob/master/promises/specification.md.\n *\n * Additionally the promise api allows for composition that is very hard to do with the\n * traditional callback ([CPS](http://en.wikipedia.org/wiki/Continuation-passing_style)) approach.\n * For more on this please see the [Q documentation](https://github.com/kriskowal/q) especially the\n * section on serial or parallel joining of promises.\n *\n * # The Deferred API\n *\n * A new instance of deferred is constructed by calling `$q.defer()`.\n *\n * The purpose of the deferred object is to expose the associated Promise instance as well as APIs\n * that can be used for signaling the successful or unsuccessful completion, as well as the status\n * of the task.\n *\n * **Methods**\n *\n * - `resolve(value)` – resolves the derived promise with the `value`. If the value is a rejection\n *   constructed via `$q.reject`, the promise will be rejected instead.\n * - `reject(reason)` – rejects the derived promise with the `reason`. This is equivalent to\n *   resolving it with a rejection constructed via `$q.reject`.\n * - `notify(value)` - provides updates on the status of the promise's execution. This may be called\n *   multiple times before the promise is either resolved or rejected.\n *\n * **Properties**\n *\n * - promise – `{Promise}` – promise object associated with this deferred.\n *\n *\n * # The Promise API\n *\n * A new promise instance is created when a deferred instance is created and can be retrieved by\n * calling `deferred.promise`.\n *\n * The purpose of the promise object is to allow for interested parties to get access to the result\n * of the deferred task when it completes.\n *\n * **Methods**\n *\n * - `then(successCallback, errorCallback, notifyCallback)` – regardless of when the promise was or\n *   will be resolved or rejected, `then` calls one of the success or error callbacks asynchronously\n *   as soon as the result is available. The callbacks are called with a single argument: the result\n *   or rejection reason. Additionally, the notify callback may be called zero or more times to\n *   provide a progress indication, before the promise is resolved or rejected.\n *\n *   This method *returns a new promise* which is resolved or rejected via the return value of the\n *   `successCallback`, `errorCallback`. It also notifies via the return value of the\n *   `notifyCallback` method. The promise cannot be resolved or rejected from the notifyCallback\n *   method.\n *\n * - `catch(errorCallback)` – shorthand for `promise.then(null, errorCallback)`\n *\n * - `finally(callback, notifyCallback)` – allows you to observe either the fulfillment or rejection of a promise,\n *   but to do so without modifying the final value. This is useful to release resources or do some\n *   clean-up that needs to be done whether the promise was rejected or resolved. See the [full\n *   specification](https://github.com/kriskowal/q/wiki/API-Reference#promisefinallycallback) for\n *   more information.\n *\n * # Chaining promises\n *\n * Because calling the `then` method of a promise returns a new derived promise, it is easily\n * possible to create a chain of promises:\n *\n * ```js\n *   promiseB = promiseA.then(function(result) {\n *     return result + 1;\n *   });\n *\n *   // promiseB will be resolved immediately after promiseA is resolved and its value\n *   // will be the result of promiseA incremented by 1\n * ```\n *\n * It is possible to create chains of any length and since a promise can be resolved with another\n * promise (which will defer its resolution further), it is possible to pause/defer resolution of\n * the promises at any point in the chain. This makes it possible to implement powerful APIs like\n * $http's response interceptors.\n *\n *\n * # Differences between Kris Kowal's Q and $q\n *\n *  There are two main differences:\n *\n * - $q is integrated with the {@link ng.$rootScope.Scope} Scope model observation\n *   mechanism in angular, which means faster propagation of resolution or rejection into your\n *   models and avoiding unnecessary browser repaints, which would result in flickering UI.\n * - Q has many more features than $q, but that comes at a cost of bytes. $q is tiny, but contains\n *   all the important functionality needed for common async tasks.\n *\n *  # Testing\n *\n *  ```js\n *    it('should simulate promise', inject(function($q, $rootScope) {\n *      var deferred = $q.defer();\n *      var promise = deferred.promise;\n *      var resolvedValue;\n *\n *      promise.then(function(value) { resolvedValue = value; });\n *      expect(resolvedValue).toBeUndefined();\n *\n *      // Simulate resolving of promise\n *      deferred.resolve(123);\n *      // Note that the 'then' function does not get called synchronously.\n *      // This is because we want the promise API to always be async, whether or not\n *      // it got called synchronously or asynchronously.\n *      expect(resolvedValue).toBeUndefined();\n *\n *      // Propagate promise resolution to 'then' functions using $apply().\n *      $rootScope.$apply();\n *      expect(resolvedValue).toEqual(123);\n *    }));\n *  ```\n *\n * @param {function(function, function)} resolver Function which is responsible for resolving or\n *   rejecting the newly created promise. The first parameter is a function which resolves the\n *   promise, the second parameter is a function which rejects the promise.\n *\n * @returns {Promise} The newly created promise.\n */\nfunction $QProvider() {\n\n  this.$get = ['$rootScope', '$exceptionHandler', function($rootScope, $exceptionHandler) {\n    return qFactory(function(callback) {\n      $rootScope.$evalAsync(callback);\n    }, $exceptionHandler);\n  }];\n}\n\nfunction $$QProvider() {\n  this.$get = ['$browser', '$exceptionHandler', function($browser, $exceptionHandler) {\n    return qFactory(function(callback) {\n      $browser.defer(callback);\n    }, $exceptionHandler);\n  }];\n}\n\n/**\n * Constructs a promise manager.\n *\n * @param {function(function)} nextTick Function for executing functions in the next turn.\n * @param {function(...*)} exceptionHandler Function into which unexpected exceptions are passed for\n *     debugging purposes.\n * @returns {object} Promise manager.\n */\nfunction qFactory(nextTick, exceptionHandler) {\n  var $qMinErr = minErr('$q', TypeError);\n  function callOnce(self, resolveFn, rejectFn) {\n    var called = false;\n    function wrap(fn) {\n      return function(value) {\n        if (called) return;\n        called = true;\n        fn.call(self, value);\n      };\n    }\n\n    return [wrap(resolveFn), wrap(rejectFn)];\n  }\n\n  /**\n   * @ngdoc method\n   * @name ng.$q#defer\n   * @kind function\n   *\n   * @description\n   * Creates a `Deferred` object which represents a task which will finish in the future.\n   *\n   * @returns {Deferred} Returns a new instance of deferred.\n   */\n  var defer = function() {\n    return new Deferred();\n  };\n\n  function Promise() {\n    this.$$state = { status: 0 };\n  }\n\n  Promise.prototype = {\n    then: function(onFulfilled, onRejected, progressBack) {\n      var result = new Deferred();\n\n      this.$$state.pending = this.$$state.pending || [];\n      this.$$state.pending.push([result, onFulfilled, onRejected, progressBack]);\n      if (this.$$state.status > 0) scheduleProcessQueue(this.$$state);\n\n      return result.promise;\n    },\n\n    \"catch\": function(callback) {\n      return this.then(null, callback);\n    },\n\n    \"finally\": function(callback, progressBack) {\n      return this.then(function(value) {\n        return handleCallback(value, true, callback);\n      }, function(error) {\n        return handleCallback(error, false, callback);\n      }, progressBack);\n    }\n  };\n\n  //Faster, more basic than angular.bind http://jsperf.com/angular-bind-vs-custom-vs-native\n  function simpleBind(context, fn) {\n    return function(value) {\n      fn.call(context, value);\n    };\n  }\n\n  function processQueue(state) {\n    var fn, promise, pending;\n\n    pending = state.pending;\n    state.processScheduled = false;\n    state.pending = undefined;\n    for (var i = 0, ii = pending.length; i < ii; ++i) {\n      promise = pending[i][0];\n      fn = pending[i][state.status];\n      try {\n        if (isFunction(fn)) {\n          promise.resolve(fn(state.value));\n        } else if (state.status === 1) {\n          promise.resolve(state.value);\n        } else {\n          promise.reject(state.value);\n        }\n      } catch (e) {\n        promise.reject(e);\n        exceptionHandler(e);\n      }\n    }\n  }\n\n  function scheduleProcessQueue(state) {\n    if (state.processScheduled || !state.pending) return;\n    state.processScheduled = true;\n    nextTick(function() { processQueue(state); });\n  }\n\n  function Deferred() {\n    this.promise = new Promise();\n    //Necessary to support unbound execution :/\n    this.resolve = simpleBind(this, this.resolve);\n    this.reject = simpleBind(this, this.reject);\n    this.notify = simpleBind(this, this.notify);\n  }\n\n  Deferred.prototype = {\n    resolve: function(val) {\n      if (this.promise.$$state.status) return;\n      if (val === this.promise) {\n        this.$$reject($qMinErr(\n          'qcycle',\n          \"Expected promise to be resolved with value other than itself '{0}'\",\n          val));\n      } else {\n        this.$$resolve(val);\n      }\n\n    },\n\n    $$resolve: function(val) {\n      var then, fns;\n\n      fns = callOnce(this, this.$$resolve, this.$$reject);\n      try {\n        if ((isObject(val) || isFunction(val))) then = val && val.then;\n        if (isFunction(then)) {\n          this.promise.$$state.status = -1;\n          then.call(val, fns[0], fns[1], this.notify);\n        } else {\n          this.promise.$$state.value = val;\n          this.promise.$$state.status = 1;\n          scheduleProcessQueue(this.promise.$$state);\n        }\n      } catch (e) {\n        fns[1](e);\n        exceptionHandler(e);\n      }\n    },\n\n    reject: function(reason) {\n      if (this.promise.$$state.status) return;\n      this.$$reject(reason);\n    },\n\n    $$reject: function(reason) {\n      this.promise.$$state.value = reason;\n      this.promise.$$state.status = 2;\n      scheduleProcessQueue(this.promise.$$state);\n    },\n\n    notify: function(progress) {\n      var callbacks = this.promise.$$state.pending;\n\n      if ((this.promise.$$state.status <= 0) && callbacks && callbacks.length) {\n        nextTick(function() {\n          var callback, result;\n          for (var i = 0, ii = callbacks.length; i < ii; i++) {\n            result = callbacks[i][0];\n            callback = callbacks[i][3];\n            try {\n              result.notify(isFunction(callback) ? callback(progress) : progress);\n            } catch (e) {\n              exceptionHandler(e);\n            }\n          }\n        });\n      }\n    }\n  };\n\n  /**\n   * @ngdoc method\n   * @name $q#reject\n   * @kind function\n   *\n   * @description\n   * Creates a promise that is resolved as rejected with the specified `reason`. This api should be\n   * used to forward rejection in a chain of promises. If you are dealing with the last promise in\n   * a promise chain, you don't need to worry about it.\n   *\n   * When comparing deferreds/promises to the familiar behavior of try/catch/throw, think of\n   * `reject` as the `throw` keyword in JavaScript. This also means that if you \"catch\" an error via\n   * a promise error callback and you want to forward the error to the promise derived from the\n   * current promise, you have to \"rethrow\" the error by returning a rejection constructed via\n   * `reject`.\n   *\n   * ```js\n   *   promiseB = promiseA.then(function(result) {\n   *     // success: do something and resolve promiseB\n   *     //          with the old or a new result\n   *     return result;\n   *   }, function(reason) {\n   *     // error: handle the error if possible and\n   *     //        resolve promiseB with newPromiseOrValue,\n   *     //        otherwise forward the rejection to promiseB\n   *     if (canHandle(reason)) {\n   *      // handle the error and recover\n   *      return newPromiseOrValue;\n   *     }\n   *     return $q.reject(reason);\n   *   });\n   * ```\n   *\n   * @param {*} reason Constant, message, exception or an object representing the rejection reason.\n   * @returns {Promise} Returns a promise that was already resolved as rejected with the `reason`.\n   */\n  var reject = function(reason) {\n    var result = new Deferred();\n    result.reject(reason);\n    return result.promise;\n  };\n\n  var makePromise = function makePromise(value, resolved) {\n    var result = new Deferred();\n    if (resolved) {\n      result.resolve(value);\n    } else {\n      result.reject(value);\n    }\n    return result.promise;\n  };\n\n  var handleCallback = function handleCallback(value, isResolved, callback) {\n    var callbackOutput = null;\n    try {\n      if (isFunction(callback)) callbackOutput = callback();\n    } catch (e) {\n      return makePromise(e, false);\n    }\n    if (isPromiseLike(callbackOutput)) {\n      return callbackOutput.then(function() {\n        return makePromise(value, isResolved);\n      }, function(error) {\n        return makePromise(error, false);\n      });\n    } else {\n      return makePromise(value, isResolved);\n    }\n  };\n\n  /**\n   * @ngdoc method\n   * @name $q#when\n   * @kind function\n   *\n   * @description\n   * Wraps an object that might be a value or a (3rd party) then-able promise into a $q promise.\n   * This is useful when you are dealing with an object that might or might not be a promise, or if\n   * the promise comes from a source that can't be trusted.\n   *\n   * @param {*} value Value or a promise\n   * @returns {Promise} Returns a promise of the passed value or promise\n   */\n\n\n  var when = function(value, callback, errback, progressBack) {\n    var result = new Deferred();\n    result.resolve(value);\n    return result.promise.then(callback, errback, progressBack);\n  };\n\n  /**\n   * @ngdoc method\n   * @name $q#all\n   * @kind function\n   *\n   * @description\n   * Combines multiple promises into a single promise that is resolved when all of the input\n   * promises are resolved.\n   *\n   * @param {Array.<Promise>|Object.<Promise>} promises An array or hash of promises.\n   * @returns {Promise} Returns a single promise that will be resolved with an array/hash of values,\n   *   each value corresponding to the promise at the same index/key in the `promises` array/hash.\n   *   If any of the promises is resolved with a rejection, this resulting promise will be rejected\n   *   with the same rejection value.\n   */\n\n  function all(promises) {\n    var deferred = new Deferred(),\n        counter = 0,\n        results = isArray(promises) ? [] : {};\n\n    forEach(promises, function(promise, key) {\n      counter++;\n      when(promise).then(function(value) {\n        if (results.hasOwnProperty(key)) return;\n        results[key] = value;\n        if (!(--counter)) deferred.resolve(results);\n      }, function(reason) {\n        if (results.hasOwnProperty(key)) return;\n        deferred.reject(reason);\n      });\n    });\n\n    if (counter === 0) {\n      deferred.resolve(results);\n    }\n\n    return deferred.promise;\n  }\n\n  var $Q = function Q(resolver) {\n    if (!isFunction(resolver)) {\n      throw $qMinErr('norslvr', \"Expected resolverFn, got '{0}'\", resolver);\n    }\n\n    if (!(this instanceof Q)) {\n      // More useful when $Q is the Promise itself.\n      return new Q(resolver);\n    }\n\n    var deferred = new Deferred();\n\n    function resolveFn(value) {\n      deferred.resolve(value);\n    }\n\n    function rejectFn(reason) {\n      deferred.reject(reason);\n    }\n\n    resolver(resolveFn, rejectFn);\n\n    return deferred.promise;\n  };\n\n  $Q.defer = defer;\n  $Q.reject = reject;\n  $Q.when = when;\n  $Q.all = all;\n\n  return $Q;\n}\n\nfunction $$RAFProvider() { //rAF\n  this.$get = ['$window', '$timeout', function($window, $timeout) {\n    var requestAnimationFrame = $window.requestAnimationFrame ||\n                                $window.webkitRequestAnimationFrame;\n\n    var cancelAnimationFrame = $window.cancelAnimationFrame ||\n                               $window.webkitCancelAnimationFrame ||\n                               $window.webkitCancelRequestAnimationFrame;\n\n    var rafSupported = !!requestAnimationFrame;\n    var raf = rafSupported\n      ? function(fn) {\n          var id = requestAnimationFrame(fn);\n          return function() {\n            cancelAnimationFrame(id);\n          };\n        }\n      : function(fn) {\n          var timer = $timeout(fn, 16.66, false); // 1000 / 60 = 16.666\n          return function() {\n            $timeout.cancel(timer);\n          };\n        };\n\n    raf.supported = rafSupported;\n\n    return raf;\n  }];\n}\n\n/**\n * DESIGN NOTES\n *\n * The design decisions behind the scope are heavily favored for speed and memory consumption.\n *\n * The typical use of scope is to watch the expressions, which most of the time return the same\n * value as last time so we optimize the operation.\n *\n * Closures construction is expensive in terms of speed as well as memory:\n *   - No closures, instead use prototypical inheritance for API\n *   - Internal state needs to be stored on scope directly, which means that private state is\n *     exposed as $$____ properties\n *\n * Loop operations are optimized by using while(count--) { ... }\n *   - this means that in order to keep the same order of execution as addition we have to add\n *     items to the array at the beginning (unshift) instead of at the end (push)\n *\n * Child scopes are created and removed often\n *   - Using an array would be slow since inserts in middle are expensive so we use linked list\n *\n * There are few watches then a lot of observers. This is why you don't want the observer to be\n * implemented in the same way as watch. Watch requires return of initialization function which\n * are expensive to construct.\n */\n\n\n/**\n * @ngdoc provider\n * @name $rootScopeProvider\n * @description\n *\n * Provider for the $rootScope service.\n */\n\n/**\n * @ngdoc method\n * @name $rootScopeProvider#digestTtl\n * @description\n *\n * Sets the number of `$digest` iterations the scope should attempt to execute before giving up and\n * assuming that the model is unstable.\n *\n * The current default is 10 iterations.\n *\n * In complex applications it's possible that the dependencies between `$watch`s will result in\n * several digest iterations. However if an application needs more than the default 10 digest\n * iterations for its model to stabilize then you should investigate what is causing the model to\n * continuously change during the digest.\n *\n * Increasing the TTL could have performance implications, so you should not change it without\n * proper justification.\n *\n * @param {number} limit The number of digest iterations.\n */\n\n\n/**\n * @ngdoc service\n * @name $rootScope\n * @description\n *\n * Every application has a single root {@link ng.$rootScope.Scope scope}.\n * All other scopes are descendant scopes of the root scope. Scopes provide separation\n * between the model and the view, via a mechanism for watching the model for changes.\n * They also provide an event emission/broadcast and subscription facility. See the\n * {@link guide/scope developer guide on scopes}.\n */\nfunction $RootScopeProvider() {\n  var TTL = 10;\n  var $rootScopeMinErr = minErr('$rootScope');\n  var lastDirtyWatch = null;\n  var applyAsyncId = null;\n\n  this.digestTtl = function(value) {\n    if (arguments.length) {\n      TTL = value;\n    }\n    return TTL;\n  };\n\n  this.$get = ['$injector', '$exceptionHandler', '$parse', '$browser',\n      function($injector, $exceptionHandler, $parse, $browser) {\n\n    /**\n     * @ngdoc type\n     * @name $rootScope.Scope\n     *\n     * @description\n     * A root scope can be retrieved using the {@link ng.$rootScope $rootScope} key from the\n     * {@link auto.$injector $injector}. Child scopes are created using the\n     * {@link ng.$rootScope.Scope#$new $new()} method. (Most scopes are created automatically when\n     * compiled HTML template is executed.)\n     *\n     * Here is a simple scope snippet to show how you can interact with the scope.\n     * ```html\n     * <file src=\"./test/ng/rootScopeSpec.js\" tag=\"docs1\" />\n     * ```\n     *\n     * # Inheritance\n     * A scope can inherit from a parent scope, as in this example:\n     * ```js\n         var parent = $rootScope;\n         var child = parent.$new();\n\n         parent.salutation = \"Hello\";\n         expect(child.salutation).toEqual('Hello');\n\n         child.salutation = \"Welcome\";\n         expect(child.salutation).toEqual('Welcome');\n         expect(parent.salutation).toEqual('Hello');\n     * ```\n     *\n     * When interacting with `Scope` in tests, additional helper methods are available on the\n     * instances of `Scope` type. See {@link ngMock.$rootScope.Scope ngMock Scope} for additional\n     * details.\n     *\n     *\n     * @param {Object.<string, function()>=} providers Map of service factory which need to be\n     *                                       provided for the current scope. Defaults to {@link ng}.\n     * @param {Object.<string, *>=} instanceCache Provides pre-instantiated services which should\n     *                              append/override services provided by `providers`. This is handy\n     *                              when unit-testing and having the need to override a default\n     *                              service.\n     * @returns {Object} Newly created scope.\n     *\n     */\n    function Scope() {\n      this.$id = nextUid();\n      this.$$phase = this.$parent = this.$$watchers =\n                     this.$$nextSibling = this.$$prevSibling =\n                     this.$$childHead = this.$$childTail = null;\n      this.$root = this;\n      this.$$destroyed = false;\n      this.$$listeners = {};\n      this.$$listenerCount = {};\n      this.$$isolateBindings = null;\n    }\n\n    /**\n     * @ngdoc property\n     * @name $rootScope.Scope#$id\n     *\n     * @description\n     * Unique scope ID (monotonically increasing) useful for debugging.\n     */\n\n     /**\n      * @ngdoc property\n      * @name $rootScope.Scope#$parent\n      *\n      * @description\n      * Reference to the parent scope.\n      */\n\n      /**\n       * @ngdoc property\n       * @name $rootScope.Scope#$root\n       *\n       * @description\n       * Reference to the root scope.\n       */\n\n    Scope.prototype = {\n      constructor: Scope,\n      /**\n       * @ngdoc method\n       * @name $rootScope.Scope#$new\n       * @kind function\n       *\n       * @description\n       * Creates a new child {@link ng.$rootScope.Scope scope}.\n       *\n       * The parent scope will propagate the {@link ng.$rootScope.Scope#$digest $digest()} event.\n       * The scope can be removed from the scope hierarchy using {@link ng.$rootScope.Scope#$destroy $destroy()}.\n       *\n       * {@link ng.$rootScope.Scope#$destroy $destroy()} must be called on a scope when it is\n       * desired for the scope and its child scopes to be permanently detached from the parent and\n       * thus stop participating in model change detection and listener notification by invoking.\n       *\n       * @param {boolean} isolate If true, then the scope does not prototypically inherit from the\n       *         parent scope. The scope is isolated, as it can not see parent scope properties.\n       *         When creating widgets, it is useful for the widget to not accidentally read parent\n       *         state.\n       *\n       * @param {Scope} [parent=this] The {@link ng.$rootScope.Scope `Scope`} that will be the `$parent`\n       *                              of the newly created scope. Defaults to `this` scope if not provided.\n       *                              This is used when creating a transclude scope to correctly place it\n       *                              in the scope hierarchy while maintaining the correct prototypical\n       *                              inheritance.\n       *\n       * @returns {Object} The newly created child scope.\n       *\n       */\n      $new: function(isolate, parent) {\n        var child;\n\n        parent = parent || this;\n\n        if (isolate) {\n          child = new Scope();\n          child.$root = this.$root;\n        } else {\n          // Only create a child scope class if somebody asks for one,\n          // but cache it to allow the VM to optimize lookups.\n          if (!this.$$ChildScope) {\n            this.$$ChildScope = function ChildScope() {\n              this.$$watchers = this.$$nextSibling =\n                  this.$$childHead = this.$$childTail = null;\n              this.$$listeners = {};\n              this.$$listenerCount = {};\n              this.$id = nextUid();\n              this.$$ChildScope = null;\n            };\n            this.$$ChildScope.prototype = this;\n          }\n          child = new this.$$ChildScope();\n        }\n        child.$parent = parent;\n        child.$$prevSibling = parent.$$childTail;\n        if (parent.$$childHead) {\n          parent.$$childTail.$$nextSibling = child;\n          parent.$$childTail = child;\n        } else {\n          parent.$$childHead = parent.$$childTail = child;\n        }\n\n        // When the new scope is not isolated or we inherit from `this`, and\n        // the parent scope is destroyed, the property `$$destroyed` is inherited\n        // prototypically. In all other cases, this property needs to be set\n        // when the parent scope is destroyed.\n        // The listener needs to be added after the parent is set\n        if (isolate || parent != this) child.$on('$destroy', destroyChild);\n\n        return child;\n\n        function destroyChild() {\n          child.$$destroyed = true;\n        }\n      },\n\n      /**\n       * @ngdoc method\n       * @name $rootScope.Scope#$watch\n       * @kind function\n       *\n       * @description\n       * Registers a `listener` callback to be executed whenever the `watchExpression` changes.\n       *\n       * - The `watchExpression` is called on every call to {@link ng.$rootScope.Scope#$digest\n       *   $digest()} and should return the value that will be watched. (Since\n       *   {@link ng.$rootScope.Scope#$digest $digest()} reruns when it detects changes the\n       *   `watchExpression` can execute multiple times per\n       *   {@link ng.$rootScope.Scope#$digest $digest()} and should be idempotent.)\n       * - The `listener` is called only when the value from the current `watchExpression` and the\n       *   previous call to `watchExpression` are not equal (with the exception of the initial run,\n       *   see below). Inequality is determined according to reference inequality,\n       *   [strict comparison](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Comparison_Operators)\n       *    via the `!==` Javascript operator, unless `objectEquality == true`\n       *   (see next point)\n       * - When `objectEquality == true`, inequality of the `watchExpression` is determined\n       *   according to the {@link angular.equals} function. To save the value of the object for\n       *   later comparison, the {@link angular.copy} function is used. This therefore means that\n       *   watching complex objects will have adverse memory and performance implications.\n       * - The watch `listener` may change the model, which may trigger other `listener`s to fire.\n       *   This is achieved by rerunning the watchers until no changes are detected. The rerun\n       *   iteration limit is 10 to prevent an infinite loop deadlock.\n       *\n       *\n       * If you want to be notified whenever {@link ng.$rootScope.Scope#$digest $digest} is called,\n       * you can register a `watchExpression` function with no `listener`. (Since `watchExpression`\n       * can execute multiple times per {@link ng.$rootScope.Scope#$digest $digest} cycle when a\n       * change is detected, be prepared for multiple calls to your listener.)\n       *\n       * After a watcher is registered with the scope, the `listener` fn is called asynchronously\n       * (via {@link ng.$rootScope.Scope#$evalAsync $evalAsync}) to initialize the\n       * watcher. In rare cases, this is undesirable because the listener is called when the result\n       * of `watchExpression` didn't change. To detect this scenario within the `listener` fn, you\n       * can compare the `newVal` and `oldVal`. If these two values are identical (`===`) then the\n       * listener was called due to initialization.\n       *\n       *\n       *\n       * # Example\n       * ```js\n           // let's assume that scope was dependency injected as the $rootScope\n           var scope = $rootScope;\n           scope.name = 'misko';\n           scope.counter = 0;\n\n           expect(scope.counter).toEqual(0);\n           scope.$watch('name', function(newValue, oldValue) {\n             scope.counter = scope.counter + 1;\n           });\n           expect(scope.counter).toEqual(0);\n\n           scope.$digest();\n           // the listener is always called during the first $digest loop after it was registered\n           expect(scope.counter).toEqual(1);\n\n           scope.$digest();\n           // but now it will not be called unless the value changes\n           expect(scope.counter).toEqual(1);\n\n           scope.name = 'adam';\n           scope.$digest();\n           expect(scope.counter).toEqual(2);\n\n\n\n           // Using a function as a watchExpression\n           var food;\n           scope.foodCounter = 0;\n           expect(scope.foodCounter).toEqual(0);\n           scope.$watch(\n             // This function returns the value being watched. It is called for each turn of the $digest loop\n             function() { return food; },\n             // This is the change listener, called when the value returned from the above function changes\n             function(newValue, oldValue) {\n               if ( newValue !== oldValue ) {\n                 // Only increment the counter if the value changed\n                 scope.foodCounter = scope.foodCounter + 1;\n               }\n             }\n           );\n           // No digest has been run so the counter will be zero\n           expect(scope.foodCounter).toEqual(0);\n\n           // Run the digest but since food has not changed count will still be zero\n           scope.$digest();\n           expect(scope.foodCounter).toEqual(0);\n\n           // Update food and run digest.  Now the counter will increment\n           food = 'cheeseburger';\n           scope.$digest();\n           expect(scope.foodCounter).toEqual(1);\n\n       * ```\n       *\n       *\n       *\n       * @param {(function()|string)} watchExpression Expression that is evaluated on each\n       *    {@link ng.$rootScope.Scope#$digest $digest} cycle. A change in the return value triggers\n       *    a call to the `listener`.\n       *\n       *    - `string`: Evaluated as {@link guide/expression expression}\n       *    - `function(scope)`: called with current `scope` as a parameter.\n       * @param {function(newVal, oldVal, scope)} listener Callback called whenever the value\n       *    of `watchExpression` changes.\n       *\n       *    - `newVal` contains the current value of the `watchExpression`\n       *    - `oldVal` contains the previous value of the `watchExpression`\n       *    - `scope` refers to the current scope\n       * @param {boolean=} objectEquality Compare for object equality using {@link angular.equals} instead of\n       *     comparing for reference equality.\n       * @returns {function()} Returns a deregistration function for this listener.\n       */\n      $watch: function(watchExp, listener, objectEquality) {\n        var get = $parse(watchExp);\n\n        if (get.$$watchDelegate) {\n          return get.$$watchDelegate(this, listener, objectEquality, get);\n        }\n        var scope = this,\n            array = scope.$$watchers,\n            watcher = {\n              fn: listener,\n              last: initWatchVal,\n              get: get,\n              exp: watchExp,\n              eq: !!objectEquality\n            };\n\n        lastDirtyWatch = null;\n\n        if (!isFunction(listener)) {\n          watcher.fn = noop;\n        }\n\n        if (!array) {\n          array = scope.$$watchers = [];\n        }\n        // we use unshift since we use a while loop in $digest for speed.\n        // the while loop reads in reverse order.\n        array.unshift(watcher);\n\n        return function deregisterWatch() {\n          arrayRemove(array, watcher);\n          lastDirtyWatch = null;\n        };\n      },\n\n      /**\n       * @ngdoc method\n       * @name $rootScope.Scope#$watchGroup\n       * @kind function\n       *\n       * @description\n       * A variant of {@link ng.$rootScope.Scope#$watch $watch()} where it watches an array of `watchExpressions`.\n       * If any one expression in the collection changes the `listener` is executed.\n       *\n       * - The items in the `watchExpressions` array are observed via standard $watch operation and are examined on every\n       *   call to $digest() to see if any items changes.\n       * - The `listener` is called whenever any expression in the `watchExpressions` array changes.\n       *\n       * @param {Array.<string|Function(scope)>} watchExpressions Array of expressions that will be individually\n       * watched using {@link ng.$rootScope.Scope#$watch $watch()}\n       *\n       * @param {function(newValues, oldValues, scope)} listener Callback called whenever the return value of any\n       *    expression in `watchExpressions` changes\n       *    The `newValues` array contains the current values of the `watchExpressions`, with the indexes matching\n       *    those of `watchExpression`\n       *    and the `oldValues` array contains the previous values of the `watchExpressions`, with the indexes matching\n       *    those of `watchExpression`\n       *    The `scope` refers to the current scope.\n       * @returns {function()} Returns a de-registration function for all listeners.\n       */\n      $watchGroup: function(watchExpressions, listener) {\n        var oldValues = new Array(watchExpressions.length);\n        var newValues = new Array(watchExpressions.length);\n        var deregisterFns = [];\n        var self = this;\n        var changeReactionScheduled = false;\n        var firstRun = true;\n\n        if (!watchExpressions.length) {\n          // No expressions means we call the listener ASAP\n          var shouldCall = true;\n          self.$evalAsync(function() {\n            if (shouldCall) listener(newValues, newValues, self);\n          });\n          return function deregisterWatchGroup() {\n            shouldCall = false;\n          };\n        }\n\n        if (watchExpressions.length === 1) {\n          // Special case size of one\n          return this.$watch(watchExpressions[0], function watchGroupAction(value, oldValue, scope) {\n            newValues[0] = value;\n            oldValues[0] = oldValue;\n            listener(newValues, (value === oldValue) ? newValues : oldValues, scope);\n          });\n        }\n\n        forEach(watchExpressions, function(expr, i) {\n          var unwatchFn = self.$watch(expr, function watchGroupSubAction(value, oldValue) {\n            newValues[i] = value;\n            oldValues[i] = oldValue;\n            if (!changeReactionScheduled) {\n              changeReactionScheduled = true;\n              self.$evalAsync(watchGroupAction);\n            }\n          });\n          deregisterFns.push(unwatchFn);\n        });\n\n        function watchGroupAction() {\n          changeReactionScheduled = false;\n\n          if (firstRun) {\n            firstRun = false;\n            listener(newValues, newValues, self);\n          } else {\n            listener(newValues, oldValues, self);\n          }\n        }\n\n        return function deregisterWatchGroup() {\n          while (deregisterFns.length) {\n            deregisterFns.shift()();\n          }\n        };\n      },\n\n\n      /**\n       * @ngdoc method\n       * @name $rootScope.Scope#$watchCollection\n       * @kind function\n       *\n       * @description\n       * Shallow watches the properties of an object and fires whenever any of the properties change\n       * (for arrays, this implies watching the array items; for object maps, this implies watching\n       * the properties). If a change is detected, the `listener` callback is fired.\n       *\n       * - The `obj` collection is observed via standard $watch operation and is examined on every\n       *   call to $digest() to see if any items have been added, removed, or moved.\n       * - The `listener` is called whenever anything within the `obj` has changed. Examples include\n       *   adding, removing, and moving items belonging to an object or array.\n       *\n       *\n       * # Example\n       * ```js\n          $scope.names = ['igor', 'matias', 'misko', 'james'];\n          $scope.dataCount = 4;\n\n          $scope.$watchCollection('names', function(newNames, oldNames) {\n            $scope.dataCount = newNames.length;\n          });\n\n          expect($scope.dataCount).toEqual(4);\n          $scope.$digest();\n\n          //still at 4 ... no changes\n          expect($scope.dataCount).toEqual(4);\n\n          $scope.names.pop();\n          $scope.$digest();\n\n          //now there's been a change\n          expect($scope.dataCount).toEqual(3);\n       * ```\n       *\n       *\n       * @param {string|function(scope)} obj Evaluated as {@link guide/expression expression}. The\n       *    expression value should evaluate to an object or an array which is observed on each\n       *    {@link ng.$rootScope.Scope#$digest $digest} cycle. Any shallow change within the\n       *    collection will trigger a call to the `listener`.\n       *\n       * @param {function(newCollection, oldCollection, scope)} listener a callback function called\n       *    when a change is detected.\n       *    - The `newCollection` object is the newly modified data obtained from the `obj` expression\n       *    - The `oldCollection` object is a copy of the former collection data.\n       *      Due to performance considerations, the`oldCollection` value is computed only if the\n       *      `listener` function declares two or more arguments.\n       *    - The `scope` argument refers to the current scope.\n       *\n       * @returns {function()} Returns a de-registration function for this listener. When the\n       *    de-registration function is executed, the internal watch operation is terminated.\n       */\n      $watchCollection: function(obj, listener) {\n        $watchCollectionInterceptor.$stateful = true;\n\n        var self = this;\n        // the current value, updated on each dirty-check run\n        var newValue;\n        // a shallow copy of the newValue from the last dirty-check run,\n        // updated to match newValue during dirty-check run\n        var oldValue;\n        // a shallow copy of the newValue from when the last change happened\n        var veryOldValue;\n        // only track veryOldValue if the listener is asking for it\n        var trackVeryOldValue = (listener.length > 1);\n        var changeDetected = 0;\n        var changeDetector = $parse(obj, $watchCollectionInterceptor);\n        var internalArray = [];\n        var internalObject = {};\n        var initRun = true;\n        var oldLength = 0;\n\n        function $watchCollectionInterceptor(_value) {\n          newValue = _value;\n          var newLength, key, bothNaN, newItem, oldItem;\n\n          // If the new value is undefined, then return undefined as the watch may be a one-time watch\n          if (isUndefined(newValue)) return;\n\n          if (!isObject(newValue)) { // if primitive\n            if (oldValue !== newValue) {\n              oldValue = newValue;\n              changeDetected++;\n            }\n          } else if (isArrayLike(newValue)) {\n            if (oldValue !== internalArray) {\n              // we are transitioning from something which was not an array into array.\n              oldValue = internalArray;\n              oldLength = oldValue.length = 0;\n              changeDetected++;\n            }\n\n            newLength = newValue.length;\n\n            if (oldLength !== newLength) {\n              // if lengths do not match we need to trigger change notification\n              changeDetected++;\n              oldValue.length = oldLength = newLength;\n            }\n            // copy the items to oldValue and look for changes.\n            for (var i = 0; i < newLength; i++) {\n              oldItem = oldValue[i];\n              newItem = newValue[i];\n\n              bothNaN = (oldItem !== oldItem) && (newItem !== newItem);\n              if (!bothNaN && (oldItem !== newItem)) {\n                changeDetected++;\n                oldValue[i] = newItem;\n              }\n            }\n          } else {\n            if (oldValue !== internalObject) {\n              // we are transitioning from something which was not an object into object.\n              oldValue = internalObject = {};\n              oldLength = 0;\n              changeDetected++;\n            }\n            // copy the items to oldValue and look for changes.\n            newLength = 0;\n            for (key in newValue) {\n              if (newValue.hasOwnProperty(key)) {\n                newLength++;\n                newItem = newValue[key];\n                oldItem = oldValue[key];\n\n                if (key in oldValue) {\n                  bothNaN = (oldItem !== oldItem) && (newItem !== newItem);\n                  if (!bothNaN && (oldItem !== newItem)) {\n                    changeDetected++;\n                    oldValue[key] = newItem;\n                  }\n                } else {\n                  oldLength++;\n                  oldValue[key] = newItem;\n                  changeDetected++;\n                }\n              }\n            }\n            if (oldLength > newLength) {\n              // we used to have more keys, need to find them and destroy them.\n              changeDetected++;\n              for (key in oldValue) {\n                if (!newValue.hasOwnProperty(key)) {\n                  oldLength--;\n                  delete oldValue[key];\n                }\n              }\n            }\n          }\n          return changeDetected;\n        }\n\n        function $watchCollectionAction() {\n          if (initRun) {\n            initRun = false;\n            listener(newValue, newValue, self);\n          } else {\n            listener(newValue, veryOldValue, self);\n          }\n\n          // make a copy for the next time a collection is changed\n          if (trackVeryOldValue) {\n            if (!isObject(newValue)) {\n              //primitive\n              veryOldValue = newValue;\n            } else if (isArrayLike(newValue)) {\n              veryOldValue = new Array(newValue.length);\n              for (var i = 0; i < newValue.length; i++) {\n                veryOldValue[i] = newValue[i];\n              }\n            } else { // if object\n              veryOldValue = {};\n              for (var key in newValue) {\n                if (hasOwnProperty.call(newValue, key)) {\n                  veryOldValue[key] = newValue[key];\n                }\n              }\n            }\n          }\n        }\n\n        return this.$watch(changeDetector, $watchCollectionAction);\n      },\n\n      /**\n       * @ngdoc method\n       * @name $rootScope.Scope#$digest\n       * @kind function\n       *\n       * @description\n       * Processes all of the {@link ng.$rootScope.Scope#$watch watchers} of the current scope and\n       * its children. Because a {@link ng.$rootScope.Scope#$watch watcher}'s listener can change\n       * the model, the `$digest()` keeps calling the {@link ng.$rootScope.Scope#$watch watchers}\n       * until no more listeners are firing. This means that it is possible to get into an infinite\n       * loop. This function will throw `'Maximum iteration limit exceeded.'` if the number of\n       * iterations exceeds 10.\n       *\n       * Usually, you don't call `$digest()` directly in\n       * {@link ng.directive:ngController controllers} or in\n       * {@link ng.$compileProvider#directive directives}.\n       * Instead, you should call {@link ng.$rootScope.Scope#$apply $apply()} (typically from within\n       * a {@link ng.$compileProvider#directive directive}), which will force a `$digest()`.\n       *\n       * If you want to be notified whenever `$digest()` is called,\n       * you can register a `watchExpression` function with\n       * {@link ng.$rootScope.Scope#$watch $watch()} with no `listener`.\n       *\n       * In unit tests, you may need to call `$digest()` to simulate the scope life cycle.\n       *\n       * # Example\n       * ```js\n           var scope = ...;\n           scope.name = 'misko';\n           scope.counter = 0;\n\n           expect(scope.counter).toEqual(0);\n           scope.$watch('name', function(newValue, oldValue) {\n             scope.counter = scope.counter + 1;\n           });\n           expect(scope.counter).toEqual(0);\n\n           scope.$digest();\n           // the listener is always called during the first $digest loop after it was registered\n           expect(scope.counter).toEqual(1);\n\n           scope.$digest();\n           // but now it will not be called unless the value changes\n           expect(scope.counter).toEqual(1);\n\n           scope.name = 'adam';\n           scope.$digest();\n           expect(scope.counter).toEqual(2);\n       * ```\n       *\n       */\n      $digest: function() {\n        var watch, value, last,\n            watchers,\n            length,\n            dirty, ttl = TTL,\n            next, current, target = this,\n            watchLog = [],\n            logIdx, logMsg, asyncTask;\n\n        beginPhase('$digest');\n        // Check for changes to browser url that happened in sync before the call to $digest\n        $browser.$$checkUrlChange();\n\n        if (this === $rootScope && applyAsyncId !== null) {\n          // If this is the root scope, and $applyAsync has scheduled a deferred $apply(), then\n          // cancel the scheduled $apply and flush the queue of expressions to be evaluated.\n          $browser.defer.cancel(applyAsyncId);\n          flushApplyAsync();\n        }\n\n        lastDirtyWatch = null;\n\n        do { // \"while dirty\" loop\n          dirty = false;\n          current = target;\n\n          while (asyncQueue.length) {\n            try {\n              asyncTask = asyncQueue.shift();\n              asyncTask.scope.$eval(asyncTask.expression, asyncTask.locals);\n            } catch (e) {\n              $exceptionHandler(e);\n            }\n            lastDirtyWatch = null;\n          }\n\n          traverseScopesLoop:\n          do { // \"traverse the scopes\" loop\n            if ((watchers = current.$$watchers)) {\n              // process our watches\n              length = watchers.length;\n              while (length--) {\n                try {\n                  watch = watchers[length];\n                  // Most common watches are on primitives, in which case we can short\n                  // circuit it with === operator, only when === fails do we use .equals\n                  if (watch) {\n                    if ((value = watch.get(current)) !== (last = watch.last) &&\n                        !(watch.eq\n                            ? equals(value, last)\n                            : (typeof value === 'number' && typeof last === 'number'\n                               && isNaN(value) && isNaN(last)))) {\n                      dirty = true;\n                      lastDirtyWatch = watch;\n                      watch.last = watch.eq ? copy(value, null) : value;\n                      watch.fn(value, ((last === initWatchVal) ? value : last), current);\n                      if (ttl < 5) {\n                        logIdx = 4 - ttl;\n                        if (!watchLog[logIdx]) watchLog[logIdx] = [];\n                        watchLog[logIdx].push({\n                          msg: isFunction(watch.exp) ? 'fn: ' + (watch.exp.name || watch.exp.toString()) : watch.exp,\n                          newVal: value,\n                          oldVal: last\n                        });\n                      }\n                    } else if (watch === lastDirtyWatch) {\n                      // If the most recently dirty watcher is now clean, short circuit since the remaining watchers\n                      // have already been tested.\n                      dirty = false;\n                      break traverseScopesLoop;\n                    }\n                  }\n                } catch (e) {\n                  $exceptionHandler(e);\n                }\n              }\n            }\n\n            // Insanity Warning: scope depth-first traversal\n            // yes, this code is a bit crazy, but it works and we have tests to prove it!\n            // this piece should be kept in sync with the traversal in $broadcast\n            if (!(next = (current.$$childHead ||\n                (current !== target && current.$$nextSibling)))) {\n              while (current !== target && !(next = current.$$nextSibling)) {\n                current = current.$parent;\n              }\n            }\n          } while ((current = next));\n\n          // `break traverseScopesLoop;` takes us to here\n\n          if ((dirty || asyncQueue.length) && !(ttl--)) {\n            clearPhase();\n            throw $rootScopeMinErr('infdig',\n                '{0} $digest() iterations reached. Aborting!\\n' +\n                'Watchers fired in the last 5 iterations: {1}',\n                TTL, watchLog);\n          }\n\n        } while (dirty || asyncQueue.length);\n\n        clearPhase();\n\n        while (postDigestQueue.length) {\n          try {\n            postDigestQueue.shift()();\n          } catch (e) {\n            $exceptionHandler(e);\n          }\n        }\n      },\n\n\n      /**\n       * @ngdoc event\n       * @name $rootScope.Scope#$destroy\n       * @eventType broadcast on scope being destroyed\n       *\n       * @description\n       * Broadcasted when a scope and its children are being destroyed.\n       *\n       * Note that, in AngularJS, there is also a `$destroy` jQuery event, which can be used to\n       * clean up DOM bindings before an element is removed from the DOM.\n       */\n\n      /**\n       * @ngdoc method\n       * @name $rootScope.Scope#$destroy\n       * @kind function\n       *\n       * @description\n       * Removes the current scope (and all of its children) from the parent scope. Removal implies\n       * that calls to {@link ng.$rootScope.Scope#$digest $digest()} will no longer\n       * propagate to the current scope and its children. Removal also implies that the current\n       * scope is eligible for garbage collection.\n       *\n       * The `$destroy()` is usually used by directives such as\n       * {@link ng.directive:ngRepeat ngRepeat} for managing the\n       * unrolling of the loop.\n       *\n       * Just before a scope is destroyed, a `$destroy` event is broadcasted on this scope.\n       * Application code can register a `$destroy` event handler that will give it a chance to\n       * perform any necessary cleanup.\n       *\n       * Note that, in AngularJS, there is also a `$destroy` jQuery event, which can be used to\n       * clean up DOM bindings before an element is removed from the DOM.\n       */\n      $destroy: function() {\n        // we can't destroy the root scope or a scope that has been already destroyed\n        if (this.$$destroyed) return;\n        var parent = this.$parent;\n\n        this.$broadcast('$destroy');\n        this.$$destroyed = true;\n        if (this === $rootScope) return;\n\n        for (var eventName in this.$$listenerCount) {\n          decrementListenerCount(this, this.$$listenerCount[eventName], eventName);\n        }\n\n        // sever all the references to parent scopes (after this cleanup, the current scope should\n        // not be retained by any of our references and should be eligible for garbage collection)\n        if (parent.$$childHead == this) parent.$$childHead = this.$$nextSibling;\n        if (parent.$$childTail == this) parent.$$childTail = this.$$prevSibling;\n        if (this.$$prevSibling) this.$$prevSibling.$$nextSibling = this.$$nextSibling;\n        if (this.$$nextSibling) this.$$nextSibling.$$prevSibling = this.$$prevSibling;\n\n        // Disable listeners, watchers and apply/digest methods\n        this.$destroy = this.$digest = this.$apply = this.$evalAsync = this.$applyAsync = noop;\n        this.$on = this.$watch = this.$watchGroup = function() { return noop; };\n        this.$$listeners = {};\n\n        // All of the code below is bogus code that works around V8's memory leak via optimized code\n        // and inline caches.\n        //\n        // see:\n        // - https://code.google.com/p/v8/issues/detail?id=2073#c26\n        // - https://github.com/angular/angular.js/issues/6794#issuecomment-38648909\n        // - https://github.com/angular/angular.js/issues/1313#issuecomment-10378451\n\n        this.$parent = this.$$nextSibling = this.$$prevSibling = this.$$childHead =\n            this.$$childTail = this.$root = this.$$watchers = null;\n      },\n\n      /**\n       * @ngdoc method\n       * @name $rootScope.Scope#$eval\n       * @kind function\n       *\n       * @description\n       * Executes the `expression` on the current scope and returns the result. Any exceptions in\n       * the expression are propagated (uncaught). This is useful when evaluating Angular\n       * expressions.\n       *\n       * # Example\n       * ```js\n           var scope = ng.$rootScope.Scope();\n           scope.a = 1;\n           scope.b = 2;\n\n           expect(scope.$eval('a+b')).toEqual(3);\n           expect(scope.$eval(function(scope){ return scope.a + scope.b; })).toEqual(3);\n       * ```\n       *\n       * @param {(string|function())=} expression An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in  {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with the current `scope` parameter.\n       *\n       * @param {(object)=} locals Local variables object, useful for overriding values in scope.\n       * @returns {*} The result of evaluating the expression.\n       */\n      $eval: function(expr, locals) {\n        return $parse(expr)(this, locals);\n      },\n\n      /**\n       * @ngdoc method\n       * @name $rootScope.Scope#$evalAsync\n       * @kind function\n       *\n       * @description\n       * Executes the expression on the current scope at a later point in time.\n       *\n       * The `$evalAsync` makes no guarantees as to when the `expression` will be executed, only\n       * that:\n       *\n       *   - it will execute after the function that scheduled the evaluation (preferably before DOM\n       *     rendering).\n       *   - at least one {@link ng.$rootScope.Scope#$digest $digest cycle} will be performed after\n       *     `expression` execution.\n       *\n       * Any exceptions from the execution of the expression are forwarded to the\n       * {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * __Note:__ if this function is called outside of a `$digest` cycle, a new `$digest` cycle\n       * will be scheduled. However, it is encouraged to always call code that changes the model\n       * from within an `$apply` call. That includes code evaluated via `$evalAsync`.\n       *\n       * @param {(string|function())=} expression An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with the current `scope` parameter.\n       *\n       * @param {(object)=} locals Local variables object, useful for overriding values in scope.\n       */\n      $evalAsync: function(expr, locals) {\n        // if we are outside of an $digest loop and this is the first time we are scheduling async\n        // task also schedule async auto-flush\n        if (!$rootScope.$$phase && !asyncQueue.length) {\n          $browser.defer(function() {\n            if (asyncQueue.length) {\n              $rootScope.$digest();\n            }\n          });\n        }\n\n        asyncQueue.push({scope: this, expression: expr, locals: locals});\n      },\n\n      $$postDigest: function(fn) {\n        postDigestQueue.push(fn);\n      },\n\n      /**\n       * @ngdoc method\n       * @name $rootScope.Scope#$apply\n       * @kind function\n       *\n       * @description\n       * `$apply()` is used to execute an expression in angular from outside of the angular\n       * framework. (For example from browser DOM events, setTimeout, XHR or third party libraries).\n       * Because we are calling into the angular framework we need to perform proper scope life\n       * cycle of {@link ng.$exceptionHandler exception handling},\n       * {@link ng.$rootScope.Scope#$digest executing watches}.\n       *\n       * ## Life cycle\n       *\n       * # Pseudo-Code of `$apply()`\n       * ```js\n           function $apply(expr) {\n             try {\n               return $eval(expr);\n             } catch (e) {\n               $exceptionHandler(e);\n             } finally {\n               $root.$digest();\n             }\n           }\n       * ```\n       *\n       *\n       * Scope's `$apply()` method transitions through the following stages:\n       *\n       * 1. The {@link guide/expression expression} is executed using the\n       *    {@link ng.$rootScope.Scope#$eval $eval()} method.\n       * 2. Any exceptions from the execution of the expression are forwarded to the\n       *    {@link ng.$exceptionHandler $exceptionHandler} service.\n       * 3. The {@link ng.$rootScope.Scope#$watch watch} listeners are fired immediately after the\n       *    expression was executed using the {@link ng.$rootScope.Scope#$digest $digest()} method.\n       *\n       *\n       * @param {(string|function())=} exp An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with current `scope` parameter.\n       *\n       * @returns {*} The result of evaluating the expression.\n       */\n      $apply: function(expr) {\n        try {\n          beginPhase('$apply');\n          return this.$eval(expr);\n        } catch (e) {\n          $exceptionHandler(e);\n        } finally {\n          clearPhase();\n          try {\n            $rootScope.$digest();\n          } catch (e) {\n            $exceptionHandler(e);\n            throw e;\n          }\n        }\n      },\n\n      /**\n       * @ngdoc method\n       * @name $rootScope.Scope#$applyAsync\n       * @kind function\n       *\n       * @description\n       * Schedule the invocation of $apply to occur at a later time. The actual time difference\n       * varies across browsers, but is typically around ~10 milliseconds.\n       *\n       * This can be used to queue up multiple expressions which need to be evaluated in the same\n       * digest.\n       *\n       * @param {(string|function())=} exp An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with current `scope` parameter.\n       */\n      $applyAsync: function(expr) {\n        var scope = this;\n        expr && applyAsyncQueue.push($applyAsyncExpression);\n        scheduleApplyAsync();\n\n        function $applyAsyncExpression() {\n          scope.$eval(expr);\n        }\n      },\n\n      /**\n       * @ngdoc method\n       * @name $rootScope.Scope#$on\n       * @kind function\n       *\n       * @description\n       * Listens on events of a given type. See {@link ng.$rootScope.Scope#$emit $emit} for\n       * discussion of event life cycle.\n       *\n       * The event listener function format is: `function(event, args...)`. The `event` object\n       * passed into the listener has the following attributes:\n       *\n       *   - `targetScope` - `{Scope}`: the scope on which the event was `$emit`-ed or\n       *     `$broadcast`-ed.\n       *   - `currentScope` - `{Scope}`: the scope that is currently handling the event. Once the\n       *     event propagates through the scope hierarchy, this property is set to null.\n       *   - `name` - `{string}`: name of the event.\n       *   - `stopPropagation` - `{function=}`: calling `stopPropagation` function will cancel\n       *     further event propagation (available only for events that were `$emit`-ed).\n       *   - `preventDefault` - `{function}`: calling `preventDefault` sets `defaultPrevented` flag\n       *     to true.\n       *   - `defaultPrevented` - `{boolean}`: true if `preventDefault` was called.\n       *\n       * @param {string} name Event name to listen on.\n       * @param {function(event, ...args)} listener Function to call when the event is emitted.\n       * @returns {function()} Returns a deregistration function for this listener.\n       */\n      $on: function(name, listener) {\n        var namedListeners = this.$$listeners[name];\n        if (!namedListeners) {\n          this.$$listeners[name] = namedListeners = [];\n        }\n        namedListeners.push(listener);\n\n        var current = this;\n        do {\n          if (!current.$$listenerCount[name]) {\n            current.$$listenerCount[name] = 0;\n          }\n          current.$$listenerCount[name]++;\n        } while ((current = current.$parent));\n\n        var self = this;\n        return function() {\n          var indexOfListener = namedListeners.indexOf(listener);\n          if (indexOfListener !== -1) {\n            namedListeners[indexOfListener] = null;\n            decrementListenerCount(self, 1, name);\n          }\n        };\n      },\n\n\n      /**\n       * @ngdoc method\n       * @name $rootScope.Scope#$emit\n       * @kind function\n       *\n       * @description\n       * Dispatches an event `name` upwards through the scope hierarchy notifying the\n       * registered {@link ng.$rootScope.Scope#$on} listeners.\n       *\n       * The event life cycle starts at the scope on which `$emit` was called. All\n       * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get\n       * notified. Afterwards, the event traverses upwards toward the root scope and calls all\n       * registered listeners along the way. The event will stop propagating if one of the listeners\n       * cancels it.\n       *\n       * Any exception emitted from the {@link ng.$rootScope.Scope#$on listeners} will be passed\n       * onto the {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {string} name Event name to emit.\n       * @param {...*} args Optional one or more arguments which will be passed onto the event listeners.\n       * @return {Object} Event object (see {@link ng.$rootScope.Scope#$on}).\n       */\n      $emit: function(name, args) {\n        var empty = [],\n            namedListeners,\n            scope = this,\n            stopPropagation = false,\n            event = {\n              name: name,\n              targetScope: scope,\n              stopPropagation: function() {stopPropagation = true;},\n              preventDefault: function() {\n                event.defaultPrevented = true;\n              },\n              defaultPrevented: false\n            },\n            listenerArgs = concat([event], arguments, 1),\n            i, length;\n\n        do {\n          namedListeners = scope.$$listeners[name] || empty;\n          event.currentScope = scope;\n          for (i = 0, length = namedListeners.length; i < length; i++) {\n\n            // if listeners were deregistered, defragment the array\n            if (!namedListeners[i]) {\n              namedListeners.splice(i, 1);\n              i--;\n              length--;\n              continue;\n            }\n            try {\n              //allow all listeners attached to the current scope to run\n              namedListeners[i].apply(null, listenerArgs);\n            } catch (e) {\n              $exceptionHandler(e);\n            }\n          }\n          //if any listener on the current scope stops propagation, prevent bubbling\n          if (stopPropagation) {\n            event.currentScope = null;\n            return event;\n          }\n          //traverse upwards\n          scope = scope.$parent;\n        } while (scope);\n\n        event.currentScope = null;\n\n        return event;\n      },\n\n\n      /**\n       * @ngdoc method\n       * @name $rootScope.Scope#$broadcast\n       * @kind function\n       *\n       * @description\n       * Dispatches an event `name` downwards to all child scopes (and their children) notifying the\n       * registered {@link ng.$rootScope.Scope#$on} listeners.\n       *\n       * The event life cycle starts at the scope on which `$broadcast` was called. All\n       * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get\n       * notified. Afterwards, the event propagates to all direct and indirect scopes of the current\n       * scope and calls all registered listeners along the way. The event cannot be canceled.\n       *\n       * Any exception emitted from the {@link ng.$rootScope.Scope#$on listeners} will be passed\n       * onto the {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {string} name Event name to broadcast.\n       * @param {...*} args Optional one or more arguments which will be passed onto the event listeners.\n       * @return {Object} Event object, see {@link ng.$rootScope.Scope#$on}\n       */\n      $broadcast: function(name, args) {\n        var target = this,\n            current = target,\n            next = target,\n            event = {\n              name: name,\n              targetScope: target,\n              preventDefault: function() {\n                event.defaultPrevented = true;\n              },\n              defaultPrevented: false\n            };\n\n        if (!target.$$listenerCount[name]) return event;\n\n        var listenerArgs = concat([event], arguments, 1),\n            listeners, i, length;\n\n        //down while you can, then up and next sibling or up and next sibling until back at root\n        while ((current = next)) {\n          event.currentScope = current;\n          listeners = current.$$listeners[name] || [];\n          for (i = 0, length = listeners.length; i < length; i++) {\n            // if listeners were deregistered, defragment the array\n            if (!listeners[i]) {\n              listeners.splice(i, 1);\n              i--;\n              length--;\n              continue;\n            }\n\n            try {\n              listeners[i].apply(null, listenerArgs);\n            } catch (e) {\n              $exceptionHandler(e);\n            }\n          }\n\n          // Insanity Warning: scope depth-first traversal\n          // yes, this code is a bit crazy, but it works and we have tests to prove it!\n          // this piece should be kept in sync with the traversal in $digest\n          // (though it differs due to having the extra check for $$listenerCount)\n          if (!(next = ((current.$$listenerCount[name] && current.$$childHead) ||\n              (current !== target && current.$$nextSibling)))) {\n            while (current !== target && !(next = current.$$nextSibling)) {\n              current = current.$parent;\n            }\n          }\n        }\n\n        event.currentScope = null;\n        return event;\n      }\n    };\n\n    var $rootScope = new Scope();\n\n    //The internal queues. Expose them on the $rootScope for debugging/testing purposes.\n    var asyncQueue = $rootScope.$$asyncQueue = [];\n    var postDigestQueue = $rootScope.$$postDigestQueue = [];\n    var applyAsyncQueue = $rootScope.$$applyAsyncQueue = [];\n\n    return $rootScope;\n\n\n    function beginPhase(phase) {\n      if ($rootScope.$$phase) {\n        throw $rootScopeMinErr('inprog', '{0} already in progress', $rootScope.$$phase);\n      }\n\n      $rootScope.$$phase = phase;\n    }\n\n    function clearPhase() {\n      $rootScope.$$phase = null;\n    }\n\n\n    function decrementListenerCount(current, count, name) {\n      do {\n        current.$$listenerCount[name] -= count;\n\n        if (current.$$listenerCount[name] === 0) {\n          delete current.$$listenerCount[name];\n        }\n      } while ((current = current.$parent));\n    }\n\n    /**\n     * function used as an initial value for watchers.\n     * because it's unique we can easily tell it apart from other values\n     */\n    function initWatchVal() {}\n\n    function flushApplyAsync() {\n      while (applyAsyncQueue.length) {\n        try {\n          applyAsyncQueue.shift()();\n        } catch (e) {\n          $exceptionHandler(e);\n        }\n      }\n      applyAsyncId = null;\n    }\n\n    function scheduleApplyAsync() {\n      if (applyAsyncId === null) {\n        applyAsyncId = $browser.defer(function() {\n          $rootScope.$apply(flushApplyAsync);\n        });\n      }\n    }\n  }];\n}\n\n/**\n * @description\n * Private service to sanitize uris for links and images. Used by $compile and $sanitize.\n */\nfunction $$SanitizeUriProvider() {\n  var aHrefSanitizationWhitelist = /^\\s*(https?|ftp|mailto|tel|file):/,\n    imgSrcSanitizationWhitelist = /^\\s*((https?|ftp|file|blob):|data:image\\/)/;\n\n  /**\n   * @description\n   * Retrieves or overrides the default regular expression that is used for whitelisting of safe\n   * urls during a[href] sanitization.\n   *\n   * The sanitization is a security measure aimed at prevent XSS attacks via html links.\n   *\n   * Any url about to be assigned to a[href] via data-binding is first normalized and turned into\n   * an absolute url. Afterwards, the url is matched against the `aHrefSanitizationWhitelist`\n   * regular expression. If a match is found, the original url is written into the dom. Otherwise,\n   * the absolute url is prefixed with `'unsafe:'` string and only then is it written into the DOM.\n   *\n   * @param {RegExp=} regexp New regexp to whitelist urls with.\n   * @returns {RegExp|ng.$compileProvider} Current RegExp if called without value or self for\n   *    chaining otherwise.\n   */\n  this.aHrefSanitizationWhitelist = function(regexp) {\n    if (isDefined(regexp)) {\n      aHrefSanitizationWhitelist = regexp;\n      return this;\n    }\n    return aHrefSanitizationWhitelist;\n  };\n\n\n  /**\n   * @description\n   * Retrieves or overrides the default regular expression that is used for whitelisting of safe\n   * urls during img[src] sanitization.\n   *\n   * The sanitization is a security measure aimed at prevent XSS attacks via html links.\n   *\n   * Any url about to be assigned to img[src] via data-binding is first normalized and turned into\n   * an absolute url. Afterwards, the url is matched against the `imgSrcSanitizationWhitelist`\n   * regular expression. If a match is found, the original url is written into the dom. Otherwise,\n   * the absolute url is prefixed with `'unsafe:'` string and only then is it written into the DOM.\n   *\n   * @param {RegExp=} regexp New regexp to whitelist urls with.\n   * @returns {RegExp|ng.$compileProvider} Current RegExp if called without value or self for\n   *    chaining otherwise.\n   */\n  this.imgSrcSanitizationWhitelist = function(regexp) {\n    if (isDefined(regexp)) {\n      imgSrcSanitizationWhitelist = regexp;\n      return this;\n    }\n    return imgSrcSanitizationWhitelist;\n  };\n\n  this.$get = function() {\n    return function sanitizeUri(uri, isImage) {\n      var regex = isImage ? imgSrcSanitizationWhitelist : aHrefSanitizationWhitelist;\n      var normalizedVal;\n      normalizedVal = urlResolve(uri).href;\n      if (normalizedVal !== '' && !normalizedVal.match(regex)) {\n        return 'unsafe:' + normalizedVal;\n      }\n      return uri;\n    };\n  };\n}\n\nvar $sceMinErr = minErr('$sce');\n\nvar SCE_CONTEXTS = {\n  HTML: 'html',\n  CSS: 'css',\n  URL: 'url',\n  // RESOURCE_URL is a subtype of URL used in contexts where a privileged resource is sourced from a\n  // url.  (e.g. ng-include, script src, templateUrl)\n  RESOURCE_URL: 'resourceUrl',\n  JS: 'js'\n};\n\n// Helper functions follow.\n\nfunction adjustMatcher(matcher) {\n  if (matcher === 'self') {\n    return matcher;\n  } else if (isString(matcher)) {\n    // Strings match exactly except for 2 wildcards - '*' and '**'.\n    // '*' matches any character except those from the set ':/.?&'.\n    // '**' matches any character (like .* in a RegExp).\n    // More than 2 *'s raises an error as it's ill defined.\n    if (matcher.indexOf('***') > -1) {\n      throw $sceMinErr('iwcard',\n          'Illegal sequence *** in string matcher.  String: {0}', matcher);\n    }\n    matcher = escapeForRegexp(matcher).\n                  replace('\\\\*\\\\*', '.*').\n                  replace('\\\\*', '[^:/.?&;]*');\n    return new RegExp('^' + matcher + '$');\n  } else if (isRegExp(matcher)) {\n    // The only other type of matcher allowed is a Regexp.\n    // Match entire URL / disallow partial matches.\n    // Flags are reset (i.e. no global, ignoreCase or multiline)\n    return new RegExp('^' + matcher.source + '$');\n  } else {\n    throw $sceMinErr('imatcher',\n        'Matchers may only be \"self\", string patterns or RegExp objects');\n  }\n}\n\n\nfunction adjustMatchers(matchers) {\n  var adjustedMatchers = [];\n  if (isDefined(matchers)) {\n    forEach(matchers, function(matcher) {\n      adjustedMatchers.push(adjustMatcher(matcher));\n    });\n  }\n  return adjustedMatchers;\n}\n\n\n/**\n * @ngdoc service\n * @name $sceDelegate\n * @kind function\n *\n * @description\n *\n * `$sceDelegate` is a service that is used by the `$sce` service to provide {@link ng.$sce Strict\n * Contextual Escaping (SCE)} services to AngularJS.\n *\n * Typically, you would configure or override the {@link ng.$sceDelegate $sceDelegate} instead of\n * the `$sce` service to customize the way Strict Contextual Escaping works in AngularJS.  This is\n * because, while the `$sce` provides numerous shorthand methods, etc., you really only need to\n * override 3 core functions (`trustAs`, `getTrusted` and `valueOf`) to replace the way things\n * work because `$sce` delegates to `$sceDelegate` for these operations.\n *\n * Refer {@link ng.$sceDelegateProvider $sceDelegateProvider} to configure this service.\n *\n * The default instance of `$sceDelegate` should work out of the box with little pain.  While you\n * can override it completely to change the behavior of `$sce`, the common case would\n * involve configuring the {@link ng.$sceDelegateProvider $sceDelegateProvider} instead by setting\n * your own whitelists and blacklists for trusting URLs used for loading AngularJS resources such as\n * templates.  Refer {@link ng.$sceDelegateProvider#resourceUrlWhitelist\n * $sceDelegateProvider.resourceUrlWhitelist} and {@link\n * ng.$sceDelegateProvider#resourceUrlBlacklist $sceDelegateProvider.resourceUrlBlacklist}\n */\n\n/**\n * @ngdoc provider\n * @name $sceDelegateProvider\n * @description\n *\n * The `$sceDelegateProvider` provider allows developers to configure the {@link ng.$sceDelegate\n * $sceDelegate} service.  This allows one to get/set the whitelists and blacklists used to ensure\n * that the URLs used for sourcing Angular templates are safe.  Refer {@link\n * ng.$sceDelegateProvider#resourceUrlWhitelist $sceDelegateProvider.resourceUrlWhitelist} and\n * {@link ng.$sceDelegateProvider#resourceUrlBlacklist $sceDelegateProvider.resourceUrlBlacklist}\n *\n * For the general details about this service in Angular, read the main page for {@link ng.$sce\n * Strict Contextual Escaping (SCE)}.\n *\n * **Example**:  Consider the following case. <a name=\"example\"></a>\n *\n * - your app is hosted at url `http://myapp.example.com/`\n * - but some of your templates are hosted on other domains you control such as\n *   `http://srv01.assets.example.com/`,  `http://srv02.assets.example.com/`, etc.\n * - and you have an open redirect at `http://myapp.example.com/clickThru?...`.\n *\n * Here is what a secure configuration for this scenario might look like:\n *\n * ```\n *  angular.module('myApp', []).config(function($sceDelegateProvider) {\n *    $sceDelegateProvider.resourceUrlWhitelist([\n *      // Allow same origin resource loads.\n *      'self',\n *      // Allow loading from our assets domain.  Notice the difference between * and **.\n *      'http://srv*.assets.example.com/**'\n *    ]);\n *\n *    // The blacklist overrides the whitelist so the open redirect here is blocked.\n *    $sceDelegateProvider.resourceUrlBlacklist([\n *      'http://myapp.example.com/clickThru**'\n *    ]);\n *  });\n * ```\n */\n\nfunction $SceDelegateProvider() {\n  this.SCE_CONTEXTS = SCE_CONTEXTS;\n\n  // Resource URLs can also be trusted by policy.\n  var resourceUrlWhitelist = ['self'],\n      resourceUrlBlacklist = [];\n\n  /**\n   * @ngdoc method\n   * @name $sceDelegateProvider#resourceUrlWhitelist\n   * @kind function\n   *\n   * @param {Array=} whitelist When provided, replaces the resourceUrlWhitelist with the value\n   *     provided.  This must be an array or null.  A snapshot of this array is used so further\n   *     changes to the array are ignored.\n   *\n   *     Follow {@link ng.$sce#resourceUrlPatternItem this link} for a description of the items\n   *     allowed in this array.\n   *\n   *     Note: **an empty whitelist array will block all URLs**!\n   *\n   * @return {Array} the currently set whitelist array.\n   *\n   * The **default value** when no whitelist has been explicitly set is `['self']` allowing only\n   * same origin resource requests.\n   *\n   * @description\n   * Sets/Gets the whitelist of trusted resource URLs.\n   */\n  this.resourceUrlWhitelist = function(value) {\n    if (arguments.length) {\n      resourceUrlWhitelist = adjustMatchers(value);\n    }\n    return resourceUrlWhitelist;\n  };\n\n  /**\n   * @ngdoc method\n   * @name $sceDelegateProvider#resourceUrlBlacklist\n   * @kind function\n   *\n   * @param {Array=} blacklist When provided, replaces the resourceUrlBlacklist with the value\n   *     provided.  This must be an array or null.  A snapshot of this array is used so further\n   *     changes to the array are ignored.\n   *\n   *     Follow {@link ng.$sce#resourceUrlPatternItem this link} for a description of the items\n   *     allowed in this array.\n   *\n   *     The typical usage for the blacklist is to **block\n   *     [open redirects](http://cwe.mitre.org/data/definitions/601.html)** served by your domain as\n   *     these would otherwise be trusted but actually return content from the redirected domain.\n   *\n   *     Finally, **the blacklist overrides the whitelist** and has the final say.\n   *\n   * @return {Array} the currently set blacklist array.\n   *\n   * The **default value** when no whitelist has been explicitly set is the empty array (i.e. there\n   * is no blacklist.)\n   *\n   * @description\n   * Sets/Gets the blacklist of trusted resource URLs.\n   */\n\n  this.resourceUrlBlacklist = function(value) {\n    if (arguments.length) {\n      resourceUrlBlacklist = adjustMatchers(value);\n    }\n    return resourceUrlBlacklist;\n  };\n\n  this.$get = ['$injector', function($injector) {\n\n    var htmlSanitizer = function htmlSanitizer(html) {\n      throw $sceMinErr('unsafe', 'Attempting to use an unsafe value in a safe context.');\n    };\n\n    if ($injector.has('$sanitize')) {\n      htmlSanitizer = $injector.get('$sanitize');\n    }\n\n\n    function matchUrl(matcher, parsedUrl) {\n      if (matcher === 'self') {\n        return urlIsSameOrigin(parsedUrl);\n      } else {\n        // definitely a regex.  See adjustMatchers()\n        return !!matcher.exec(parsedUrl.href);\n      }\n    }\n\n    function isResourceUrlAllowedByPolicy(url) {\n      var parsedUrl = urlResolve(url.toString());\n      var i, n, allowed = false;\n      // Ensure that at least one item from the whitelist allows this url.\n      for (i = 0, n = resourceUrlWhitelist.length; i < n; i++) {\n        if (matchUrl(resourceUrlWhitelist[i], parsedUrl)) {\n          allowed = true;\n          break;\n        }\n      }\n      if (allowed) {\n        // Ensure that no item from the blacklist blocked this url.\n        for (i = 0, n = resourceUrlBlacklist.length; i < n; i++) {\n          if (matchUrl(resourceUrlBlacklist[i], parsedUrl)) {\n            allowed = false;\n            break;\n          }\n        }\n      }\n      return allowed;\n    }\n\n    function generateHolderType(Base) {\n      var holderType = function TrustedValueHolderType(trustedValue) {\n        this.$$unwrapTrustedValue = function() {\n          return trustedValue;\n        };\n      };\n      if (Base) {\n        holderType.prototype = new Base();\n      }\n      holderType.prototype.valueOf = function sceValueOf() {\n        return this.$$unwrapTrustedValue();\n      };\n      holderType.prototype.toString = function sceToString() {\n        return this.$$unwrapTrustedValue().toString();\n      };\n      return holderType;\n    }\n\n    var trustedValueHolderBase = generateHolderType(),\n        byType = {};\n\n    byType[SCE_CONTEXTS.HTML] = generateHolderType(trustedValueHolderBase);\n    byType[SCE_CONTEXTS.CSS] = generateHolderType(trustedValueHolderBase);\n    byType[SCE_CONTEXTS.URL] = generateHolderType(trustedValueHolderBase);\n    byType[SCE_CONTEXTS.JS] = generateHolderType(trustedValueHolderBase);\n    byType[SCE_CONTEXTS.RESOURCE_URL] = generateHolderType(byType[SCE_CONTEXTS.URL]);\n\n    /**\n     * @ngdoc method\n     * @name $sceDelegate#trustAs\n     *\n     * @description\n     * Returns an object that is trusted by angular for use in specified strict\n     * contextual escaping contexts (such as ng-bind-html, ng-include, any src\n     * attribute interpolation, any dom event binding attribute interpolation\n     * such as for onclick,  etc.) that uses the provided value.\n     * See {@link ng.$sce $sce} for enabling strict contextual escaping.\n     *\n     * @param {string} type The kind of context in which this value is safe for use.  e.g. url,\n     *   resourceUrl, html, js and css.\n     * @param {*} value The value that that should be considered trusted/safe.\n     * @returns {*} A value that can be used to stand in for the provided `value` in places\n     * where Angular expects a $sce.trustAs() return value.\n     */\n    function trustAs(type, trustedValue) {\n      var Constructor = (byType.hasOwnProperty(type) ? byType[type] : null);\n      if (!Constructor) {\n        throw $sceMinErr('icontext',\n            'Attempted to trust a value in invalid context. Context: {0}; Value: {1}',\n            type, trustedValue);\n      }\n      if (trustedValue === null || trustedValue === undefined || trustedValue === '') {\n        return trustedValue;\n      }\n      // All the current contexts in SCE_CONTEXTS happen to be strings.  In order to avoid trusting\n      // mutable objects, we ensure here that the value passed in is actually a string.\n      if (typeof trustedValue !== 'string') {\n        throw $sceMinErr('itype',\n            'Attempted to trust a non-string value in a content requiring a string: Context: {0}',\n            type);\n      }\n      return new Constructor(trustedValue);\n    }\n\n    /**\n     * @ngdoc method\n     * @name $sceDelegate#valueOf\n     *\n     * @description\n     * If the passed parameter had been returned by a prior call to {@link ng.$sceDelegate#trustAs\n     * `$sceDelegate.trustAs`}, returns the value that had been passed to {@link\n     * ng.$sceDelegate#trustAs `$sceDelegate.trustAs`}.\n     *\n     * If the passed parameter is not a value that had been returned by {@link\n     * ng.$sceDelegate#trustAs `$sceDelegate.trustAs`}, returns it as-is.\n     *\n     * @param {*} value The result of a prior {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs`}\n     *      call or anything else.\n     * @returns {*} The `value` that was originally provided to {@link ng.$sceDelegate#trustAs\n     *     `$sceDelegate.trustAs`} if `value` is the result of such a call.  Otherwise, returns\n     *     `value` unchanged.\n     */\n    function valueOf(maybeTrusted) {\n      if (maybeTrusted instanceof trustedValueHolderBase) {\n        return maybeTrusted.$$unwrapTrustedValue();\n      } else {\n        return maybeTrusted;\n      }\n    }\n\n    /**\n     * @ngdoc method\n     * @name $sceDelegate#getTrusted\n     *\n     * @description\n     * Takes the result of a {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs`} call and\n     * returns the originally supplied value if the queried context type is a supertype of the\n     * created type.  If this condition isn't satisfied, throws an exception.\n     *\n     * @param {string} type The kind of context in which this value is to be used.\n     * @param {*} maybeTrusted The result of a prior {@link ng.$sceDelegate#trustAs\n     *     `$sceDelegate.trustAs`} call.\n     * @returns {*} The value the was originally provided to {@link ng.$sceDelegate#trustAs\n     *     `$sceDelegate.trustAs`} if valid in this context.  Otherwise, throws an exception.\n     */\n    function getTrusted(type, maybeTrusted) {\n      if (maybeTrusted === null || maybeTrusted === undefined || maybeTrusted === '') {\n        return maybeTrusted;\n      }\n      var constructor = (byType.hasOwnProperty(type) ? byType[type] : null);\n      if (constructor && maybeTrusted instanceof constructor) {\n        return maybeTrusted.$$unwrapTrustedValue();\n      }\n      // If we get here, then we may only take one of two actions.\n      // 1. sanitize the value for the requested type, or\n      // 2. throw an exception.\n      if (type === SCE_CONTEXTS.RESOURCE_URL) {\n        if (isResourceUrlAllowedByPolicy(maybeTrusted)) {\n          return maybeTrusted;\n        } else {\n          throw $sceMinErr('insecurl',\n              'Blocked loading resource from url not allowed by $sceDelegate policy.  URL: {0}',\n              maybeTrusted.toString());\n        }\n      } else if (type === SCE_CONTEXTS.HTML) {\n        return htmlSanitizer(maybeTrusted);\n      }\n      throw $sceMinErr('unsafe', 'Attempting to use an unsafe value in a safe context.');\n    }\n\n    return { trustAs: trustAs,\n             getTrusted: getTrusted,\n             valueOf: valueOf };\n  }];\n}\n\n\n/**\n * @ngdoc provider\n * @name $sceProvider\n * @description\n *\n * The $sceProvider provider allows developers to configure the {@link ng.$sce $sce} service.\n * -   enable/disable Strict Contextual Escaping (SCE) in a module\n * -   override the default implementation with a custom delegate\n *\n * Read more about {@link ng.$sce Strict Contextual Escaping (SCE)}.\n */\n\n/* jshint maxlen: false*/\n\n/**\n * @ngdoc service\n * @name $sce\n * @kind function\n *\n * @description\n *\n * `$sce` is a service that provides Strict Contextual Escaping services to AngularJS.\n *\n * # Strict Contextual Escaping\n *\n * Strict Contextual Escaping (SCE) is a mode in which AngularJS requires bindings in certain\n * contexts to result in a value that is marked as safe to use for that context.  One example of\n * such a context is binding arbitrary html controlled by the user via `ng-bind-html`.  We refer\n * to these contexts as privileged or SCE contexts.\n *\n * As of version 1.2, Angular ships with SCE enabled by default.\n *\n * Note:  When enabled (the default), IE<11 in quirks mode is not supported.  In this mode, IE<11 allow\n * one to execute arbitrary javascript by the use of the expression() syntax.  Refer\n * <http://blogs.msdn.com/b/ie/archive/2008/10/16/ending-expressions.aspx> to learn more about them.\n * You can ensure your document is in standards mode and not quirks mode by adding `<!doctype html>`\n * to the top of your HTML document.\n *\n * SCE assists in writing code in way that (a) is secure by default and (b) makes auditing for\n * security vulnerabilities such as XSS, clickjacking, etc. a lot easier.\n *\n * Here's an example of a binding in a privileged context:\n *\n * ```\n * <input ng-model=\"userHtml\">\n * <div ng-bind-html=\"userHtml\"></div>\n * ```\n *\n * Notice that `ng-bind-html` is bound to `userHtml` controlled by the user.  With SCE\n * disabled, this application allows the user to render arbitrary HTML into the DIV.\n * In a more realistic example, one may be rendering user comments, blog articles, etc. via\n * bindings.  (HTML is just one example of a context where rendering user controlled input creates\n * security vulnerabilities.)\n *\n * For the case of HTML, you might use a library, either on the client side, or on the server side,\n * to sanitize unsafe HTML before binding to the value and rendering it in the document.\n *\n * How would you ensure that every place that used these types of bindings was bound to a value that\n * was sanitized by your library (or returned as safe for rendering by your server?)  How can you\n * ensure that you didn't accidentally delete the line that sanitized the value, or renamed some\n * properties/fields and forgot to update the binding to the sanitized value?\n *\n * To be secure by default, you want to ensure that any such bindings are disallowed unless you can\n * determine that something explicitly says it's safe to use a value for binding in that\n * context.  You can then audit your code (a simple grep would do) to ensure that this is only done\n * for those values that you can easily tell are safe - because they were received from your server,\n * sanitized by your library, etc.  You can organize your codebase to help with this - perhaps\n * allowing only the files in a specific directory to do this.  Ensuring that the internal API\n * exposed by that code doesn't markup arbitrary values as safe then becomes a more manageable task.\n *\n * In the case of AngularJS' SCE service, one uses {@link ng.$sce#trustAs $sce.trustAs}\n * (and shorthand methods such as {@link ng.$sce#trustAsHtml $sce.trustAsHtml}, etc.) to\n * obtain values that will be accepted by SCE / privileged contexts.\n *\n *\n * ## How does it work?\n *\n * In privileged contexts, directives and code will bind to the result of {@link ng.$sce#getTrusted\n * $sce.getTrusted(context, value)} rather than to the value directly.  Directives use {@link\n * ng.$sce#parseAs $sce.parseAs} rather than `$parse` to watch attribute bindings, which performs the\n * {@link ng.$sce#getTrusted $sce.getTrusted} behind the scenes on non-constant literals.\n *\n * As an example, {@link ng.directive:ngBindHtml ngBindHtml} uses {@link\n * ng.$sce#parseAsHtml $sce.parseAsHtml(binding expression)}.  Here's the actual code (slightly\n * simplified):\n *\n * ```\n * var ngBindHtmlDirective = ['$sce', function($sce) {\n *   return function(scope, element, attr) {\n *     scope.$watch($sce.parseAsHtml(attr.ngBindHtml), function(value) {\n *       element.html(value || '');\n *     });\n *   };\n * }];\n * ```\n *\n * ## Impact on loading templates\n *\n * This applies both to the {@link ng.directive:ngInclude `ng-include`} directive as well as\n * `templateUrl`'s specified by {@link guide/directive directives}.\n *\n * By default, Angular only loads templates from the same domain and protocol as the application\n * document.  This is done by calling {@link ng.$sce#getTrustedResourceUrl\n * $sce.getTrustedResourceUrl} on the template URL.  To load templates from other domains and/or\n * protocols, you may either either {@link ng.$sceDelegateProvider#resourceUrlWhitelist whitelist\n * them} or {@link ng.$sce#trustAsResourceUrl wrap it} into a trusted value.\n *\n * *Please note*:\n * The browser's\n * [Same Origin Policy](https://code.google.com/p/browsersec/wiki/Part2#Same-origin_policy_for_XMLHttpRequest)\n * and [Cross-Origin Resource Sharing (CORS)](http://www.w3.org/TR/cors/)\n * policy apply in addition to this and may further restrict whether the template is successfully\n * loaded.  This means that without the right CORS policy, loading templates from a different domain\n * won't work on all browsers.  Also, loading templates from `file://` URL does not work on some\n * browsers.\n *\n * ## This feels like too much overhead\n *\n * It's important to remember that SCE only applies to interpolation expressions.\n *\n * If your expressions are constant literals, they're automatically trusted and you don't need to\n * call `$sce.trustAs` on them (remember to include the `ngSanitize` module) (e.g.\n * `<div ng-bind-html=\"'<b>implicitly trusted</b>'\"></div>`) just works.\n *\n * Additionally, `a[href]` and `img[src]` automatically sanitize their URLs and do not pass them\n * through {@link ng.$sce#getTrusted $sce.getTrusted}.  SCE doesn't play a role here.\n *\n * The included {@link ng.$sceDelegate $sceDelegate} comes with sane defaults to allow you to load\n * templates in `ng-include` from your application's domain without having to even know about SCE.\n * It blocks loading templates from other domains or loading templates over http from an https\n * served document.  You can change these by setting your own custom {@link\n * ng.$sceDelegateProvider#resourceUrlWhitelist whitelists} and {@link\n * ng.$sceDelegateProvider#resourceUrlBlacklist blacklists} for matching such URLs.\n *\n * This significantly reduces the overhead.  It is far easier to pay the small overhead and have an\n * application that's secure and can be audited to verify that with much more ease than bolting\n * security onto an application later.\n *\n * <a name=\"contexts\"></a>\n * ## What trusted context types are supported?\n *\n * | Context             | Notes          |\n * |---------------------|----------------|\n * | `$sce.HTML`         | For HTML that's safe to source into the application.  The {@link ng.directive:ngBindHtml ngBindHtml} directive uses this context for bindings. If an unsafe value is encountered and the {@link ngSanitize $sanitize} module is present this will sanitize the value instead of throwing an error. |\n * | `$sce.CSS`          | For CSS that's safe to source into the application.  Currently unused.  Feel free to use it in your own directives. |\n * | `$sce.URL`          | For URLs that are safe to follow as links.  Currently unused (`<a href=` and `<img src=` sanitize their urls and don't constitute an SCE context. |\n * | `$sce.RESOURCE_URL` | For URLs that are not only safe to follow as links, but whose contents are also safe to include in your application.  Examples include `ng-include`, `src` / `ngSrc` bindings for tags other than `IMG` (e.g. `IFRAME`, `OBJECT`, etc.)  <br><br>Note that `$sce.RESOURCE_URL` makes a stronger statement about the URL than `$sce.URL` does and therefore contexts requiring values trusted for `$sce.RESOURCE_URL` can be used anywhere that values trusted for `$sce.URL` are required. |\n * | `$sce.JS`           | For JavaScript that is safe to execute in your application's context.  Currently unused.  Feel free to use it in your own directives. |\n *\n * ## Format of items in {@link ng.$sceDelegateProvider#resourceUrlWhitelist resourceUrlWhitelist}/{@link ng.$sceDelegateProvider#resourceUrlBlacklist Blacklist} <a name=\"resourceUrlPatternItem\"></a>\n *\n *  Each element in these arrays must be one of the following:\n *\n *  - **'self'**\n *    - The special **string**, `'self'`, can be used to match against all URLs of the **same\n *      domain** as the application document using the **same protocol**.\n *  - **String** (except the special value `'self'`)\n *    - The string is matched against the full *normalized / absolute URL* of the resource\n *      being tested (substring matches are not good enough.)\n *    - There are exactly **two wildcard sequences** - `*` and `**`.  All other characters\n *      match themselves.\n *    - `*`: matches zero or more occurrences of any character other than one of the following 6\n *      characters: '`:`', '`/`', '`.`', '`?`', '`&`' and ';'.  It's a useful wildcard for use\n *      in a whitelist.\n *    - `**`: matches zero or more occurrences of *any* character.  As such, it's not\n *      not appropriate to use in for a scheme, domain, etc. as it would match too much.  (e.g.\n *      http://**.example.com/ would match http://evil.com/?ignore=.example.com/ and that might\n *      not have been the intention.)  Its usage at the very end of the path is ok.  (e.g.\n *      http://foo.example.com/templates/**).\n *  - **RegExp** (*see caveat below*)\n *    - *Caveat*:  While regular expressions are powerful and offer great flexibility,  their syntax\n *      (and all the inevitable escaping) makes them *harder to maintain*.  It's easy to\n *      accidentally introduce a bug when one updates a complex expression (imho, all regexes should\n *      have good test coverage.).  For instance, the use of `.` in the regex is correct only in a\n *      small number of cases.  A `.` character in the regex used when matching the scheme or a\n *      subdomain could be matched against a `:` or literal `.` that was likely not intended.   It\n *      is highly recommended to use the string patterns and only fall back to regular expressions\n *      if they as a last resort.\n *    - The regular expression must be an instance of RegExp (i.e. not a string.)  It is\n *      matched against the **entire** *normalized / absolute URL* of the resource being tested\n *      (even when the RegExp did not have the `^` and `$` codes.)  In addition, any flags\n *      present on the RegExp (such as multiline, global, ignoreCase) are ignored.\n *    - If you are generating your JavaScript from some other templating engine (not\n *      recommended, e.g. in issue [#4006](https://github.com/angular/angular.js/issues/4006)),\n *      remember to escape your regular expression (and be aware that you might need more than\n *      one level of escaping depending on your templating engine and the way you interpolated\n *      the value.)  Do make use of your platform's escaping mechanism as it might be good\n *      enough before coding your own.  e.g. Ruby has\n *      [Regexp.escape(str)](http://www.ruby-doc.org/core-2.0.0/Regexp.html#method-c-escape)\n *      and Python has [re.escape](http://docs.python.org/library/re.html#re.escape).\n *      Javascript lacks a similar built in function for escaping.  Take a look at Google\n *      Closure library's [goog.string.regExpEscape(s)](\n *      http://docs.closure-library.googlecode.com/git/closure_goog_string_string.js.source.html#line962).\n *\n * Refer {@link ng.$sceDelegateProvider $sceDelegateProvider} for an example.\n *\n * ## Show me an example using SCE.\n *\n * <example module=\"mySceApp\" deps=\"angular-sanitize.js\">\n * <file name=\"index.html\">\n *   <div ng-controller=\"AppController as myCtrl\">\n *     <i ng-bind-html=\"myCtrl.explicitlyTrustedHtml\" id=\"explicitlyTrustedHtml\"></i><br><br>\n *     <b>User comments</b><br>\n *     By default, HTML that isn't explicitly trusted (e.g. Alice's comment) is sanitized when\n *     $sanitize is available.  If $sanitize isn't available, this results in an error instead of an\n *     exploit.\n *     <div class=\"well\">\n *       <div ng-repeat=\"userComment in myCtrl.userComments\">\n *         <b>{{userComment.name}}</b>:\n *         <span ng-bind-html=\"userComment.htmlComment\" class=\"htmlComment\"></span>\n *         <br>\n *       </div>\n *     </div>\n *   </div>\n * </file>\n *\n * <file name=\"script.js\">\n *   angular.module('mySceApp', ['ngSanitize'])\n *     .controller('AppController', ['$http', '$templateCache', '$sce',\n *       function($http, $templateCache, $sce) {\n *         var self = this;\n *         $http.get(\"test_data.json\", {cache: $templateCache}).success(function(userComments) {\n *           self.userComments = userComments;\n *         });\n *         self.explicitlyTrustedHtml = $sce.trustAsHtml(\n *             '<span onmouseover=\"this.textContent=&quot;Explicitly trusted HTML bypasses ' +\n *             'sanitization.&quot;\">Hover over this text.</span>');\n *       }]);\n * </file>\n *\n * <file name=\"test_data.json\">\n * [\n *   { \"name\": \"Alice\",\n *     \"htmlComment\":\n *         \"<span onmouseover='this.textContent=\\\"PWN3D!\\\"'>Is <i>anyone</i> reading this?</span>\"\n *   },\n *   { \"name\": \"Bob\",\n *     \"htmlComment\": \"<i>Yes!</i>  Am I the only other one?\"\n *   }\n * ]\n * </file>\n *\n * <file name=\"protractor.js\" type=\"protractor\">\n *   describe('SCE doc demo', function() {\n *     it('should sanitize untrusted values', function() {\n *       expect(element.all(by.css('.htmlComment')).first().getInnerHtml())\n *           .toBe('<span>Is <i>anyone</i> reading this?</span>');\n *     });\n *\n *     it('should NOT sanitize explicitly trusted values', function() {\n *       expect(element(by.id('explicitlyTrustedHtml')).getInnerHtml()).toBe(\n *           '<span onmouseover=\"this.textContent=&quot;Explicitly trusted HTML bypasses ' +\n *           'sanitization.&quot;\">Hover over this text.</span>');\n *     });\n *   });\n * </file>\n * </example>\n *\n *\n *\n * ## Can I disable SCE completely?\n *\n * Yes, you can.  However, this is strongly discouraged.  SCE gives you a lot of security benefits\n * for little coding overhead.  It will be much harder to take an SCE disabled application and\n * either secure it on your own or enable SCE at a later stage.  It might make sense to disable SCE\n * for cases where you have a lot of existing code that was written before SCE was introduced and\n * you're migrating them a module at a time.\n *\n * That said, here's how you can completely disable SCE:\n *\n * ```\n * angular.module('myAppWithSceDisabledmyApp', []).config(function($sceProvider) {\n *   // Completely disable SCE.  For demonstration purposes only!\n *   // Do not use in new projects.\n *   $sceProvider.enabled(false);\n * });\n * ```\n *\n */\n/* jshint maxlen: 100 */\n\nfunction $SceProvider() {\n  var enabled = true;\n\n  /**\n   * @ngdoc method\n   * @name $sceProvider#enabled\n   * @kind function\n   *\n   * @param {boolean=} value If provided, then enables/disables SCE.\n   * @return {boolean} true if SCE is enabled, false otherwise.\n   *\n   * @description\n   * Enables/disables SCE and returns the current value.\n   */\n  this.enabled = function(value) {\n    if (arguments.length) {\n      enabled = !!value;\n    }\n    return enabled;\n  };\n\n\n  /* Design notes on the default implementation for SCE.\n   *\n   * The API contract for the SCE delegate\n   * -------------------------------------\n   * The SCE delegate object must provide the following 3 methods:\n   *\n   * - trustAs(contextEnum, value)\n   *     This method is used to tell the SCE service that the provided value is OK to use in the\n   *     contexts specified by contextEnum.  It must return an object that will be accepted by\n   *     getTrusted() for a compatible contextEnum and return this value.\n   *\n   * - valueOf(value)\n   *     For values that were not produced by trustAs(), return them as is.  For values that were\n   *     produced by trustAs(), return the corresponding input value to trustAs.  Basically, if\n   *     trustAs is wrapping the given values into some type, this operation unwraps it when given\n   *     such a value.\n   *\n   * - getTrusted(contextEnum, value)\n   *     This function should return the a value that is safe to use in the context specified by\n   *     contextEnum or throw and exception otherwise.\n   *\n   * NOTE: This contract deliberately does NOT state that values returned by trustAs() must be\n   * opaque or wrapped in some holder object.  That happens to be an implementation detail.  For\n   * instance, an implementation could maintain a registry of all trusted objects by context.  In\n   * such a case, trustAs() would return the same object that was passed in.  getTrusted() would\n   * return the same object passed in if it was found in the registry under a compatible context or\n   * throw an exception otherwise.  An implementation might only wrap values some of the time based\n   * on some criteria.  getTrusted() might return a value and not throw an exception for special\n   * constants or objects even if not wrapped.  All such implementations fulfill this contract.\n   *\n   *\n   * A note on the inheritance model for SCE contexts\n   * ------------------------------------------------\n   * I've used inheritance and made RESOURCE_URL wrapped types a subtype of URL wrapped types.  This\n   * is purely an implementation details.\n   *\n   * The contract is simply this:\n   *\n   *     getTrusted($sce.RESOURCE_URL, value) succeeding implies that getTrusted($sce.URL, value)\n   *     will also succeed.\n   *\n   * Inheritance happens to capture this in a natural way.  In some future, we\n   * may not use inheritance anymore.  That is OK because no code outside of\n   * sce.js and sceSpecs.js would need to be aware of this detail.\n   */\n\n  this.$get = ['$parse', '$sceDelegate', function(\n                $parse,   $sceDelegate) {\n    // Prereq: Ensure that we're not running in IE<11 quirks mode.  In that mode, IE < 11 allow\n    // the \"expression(javascript expression)\" syntax which is insecure.\n    if (enabled && msie < 8) {\n      throw $sceMinErr('iequirks',\n        'Strict Contextual Escaping does not support Internet Explorer version < 11 in quirks ' +\n        'mode.  You can fix this by adding the text <!doctype html> to the top of your HTML ' +\n        'document.  See http://docs.angularjs.org/api/ng.$sce for more information.');\n    }\n\n    var sce = shallowCopy(SCE_CONTEXTS);\n\n    /**\n     * @ngdoc method\n     * @name $sce#isEnabled\n     * @kind function\n     *\n     * @return {Boolean} true if SCE is enabled, false otherwise.  If you want to set the value, you\n     * have to do it at module config time on {@link ng.$sceProvider $sceProvider}.\n     *\n     * @description\n     * Returns a boolean indicating if SCE is enabled.\n     */\n    sce.isEnabled = function() {\n      return enabled;\n    };\n    sce.trustAs = $sceDelegate.trustAs;\n    sce.getTrusted = $sceDelegate.getTrusted;\n    sce.valueOf = $sceDelegate.valueOf;\n\n    if (!enabled) {\n      sce.trustAs = sce.getTrusted = function(type, value) { return value; };\n      sce.valueOf = identity;\n    }\n\n    /**\n     * @ngdoc method\n     * @name $sce#parseAs\n     *\n     * @description\n     * Converts Angular {@link guide/expression expression} into a function.  This is like {@link\n     * ng.$parse $parse} and is identical when the expression is a literal constant.  Otherwise, it\n     * wraps the expression in a call to {@link ng.$sce#getTrusted $sce.getTrusted(*type*,\n     * *result*)}\n     *\n     * @param {string} type The kind of SCE context in which this result will be used.\n     * @param {string} expression String expression to compile.\n     * @returns {function(context, locals)} a function which represents the compiled expression:\n     *\n     *    * `context` – `{object}` – an object against which any expressions embedded in the strings\n     *      are evaluated against (typically a scope object).\n     *    * `locals` – `{object=}` – local variables context object, useful for overriding values in\n     *      `context`.\n     */\n    sce.parseAs = function sceParseAs(type, expr) {\n      var parsed = $parse(expr);\n      if (parsed.literal && parsed.constant) {\n        return parsed;\n      } else {\n        return $parse(expr, function(value) {\n          return sce.getTrusted(type, value);\n        });\n      }\n    };\n\n    /**\n     * @ngdoc method\n     * @name $sce#trustAs\n     *\n     * @description\n     * Delegates to {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs`}.  As such,\n     * returns an object that is trusted by angular for use in specified strict contextual\n     * escaping contexts (such as ng-bind-html, ng-include, any src attribute\n     * interpolation, any dom event binding attribute interpolation such as for onclick,  etc.)\n     * that uses the provided value.  See * {@link ng.$sce $sce} for enabling strict contextual\n     * escaping.\n     *\n     * @param {string} type The kind of context in which this value is safe for use.  e.g. url,\n     *   resource_url, html, js and css.\n     * @param {*} value The value that that should be considered trusted/safe.\n     * @returns {*} A value that can be used to stand in for the provided `value` in places\n     * where Angular expects a $sce.trustAs() return value.\n     */\n\n    /**\n     * @ngdoc method\n     * @name $sce#trustAsHtml\n     *\n     * @description\n     * Shorthand method.  `$sce.trustAsHtml(value)` →\n     *     {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs($sce.HTML, value)`}\n     *\n     * @param {*} value The value to trustAs.\n     * @returns {*} An object that can be passed to {@link ng.$sce#getTrustedHtml\n     *     $sce.getTrustedHtml(value)} to obtain the original value.  (privileged directives\n     *     only accept expressions that are either literal constants or are the\n     *     return value of {@link ng.$sce#trustAs $sce.trustAs}.)\n     */\n\n    /**\n     * @ngdoc method\n     * @name $sce#trustAsUrl\n     *\n     * @description\n     * Shorthand method.  `$sce.trustAsUrl(value)` →\n     *     {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs($sce.URL, value)`}\n     *\n     * @param {*} value The value to trustAs.\n     * @returns {*} An object that can be passed to {@link ng.$sce#getTrustedUrl\n     *     $sce.getTrustedUrl(value)} to obtain the original value.  (privileged directives\n     *     only accept expressions that are either literal constants or are the\n     *     return value of {@link ng.$sce#trustAs $sce.trustAs}.)\n     */\n\n    /**\n     * @ngdoc method\n     * @name $sce#trustAsResourceUrl\n     *\n     * @description\n     * Shorthand method.  `$sce.trustAsResourceUrl(value)` →\n     *     {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs($sce.RESOURCE_URL, value)`}\n     *\n     * @param {*} value The value to trustAs.\n     * @returns {*} An object that can be passed to {@link ng.$sce#getTrustedResourceUrl\n     *     $sce.getTrustedResourceUrl(value)} to obtain the original value.  (privileged directives\n     *     only accept expressions that are either literal constants or are the return\n     *     value of {@link ng.$sce#trustAs $sce.trustAs}.)\n     */\n\n    /**\n     * @ngdoc method\n     * @name $sce#trustAsJs\n     *\n     * @description\n     * Shorthand method.  `$sce.trustAsJs(value)` →\n     *     {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs($sce.JS, value)`}\n     *\n     * @param {*} value The value to trustAs.\n     * @returns {*} An object that can be passed to {@link ng.$sce#getTrustedJs\n     *     $sce.getTrustedJs(value)} to obtain the original value.  (privileged directives\n     *     only accept expressions that are either literal constants or are the\n     *     return value of {@link ng.$sce#trustAs $sce.trustAs}.)\n     */\n\n    /**\n     * @ngdoc method\n     * @name $sce#getTrusted\n     *\n     * @description\n     * Delegates to {@link ng.$sceDelegate#getTrusted `$sceDelegate.getTrusted`}.  As such,\n     * takes the result of a {@link ng.$sce#trustAs `$sce.trustAs`}() call and returns the\n     * originally supplied value if the queried context type is a supertype of the created type.\n     * If this condition isn't satisfied, throws an exception.\n     *\n     * @param {string} type The kind of context in which this value is to be used.\n     * @param {*} maybeTrusted The result of a prior {@link ng.$sce#trustAs `$sce.trustAs`}\n     *                         call.\n     * @returns {*} The value the was originally provided to\n     *              {@link ng.$sce#trustAs `$sce.trustAs`} if valid in this context.\n     *              Otherwise, throws an exception.\n     */\n\n    /**\n     * @ngdoc method\n     * @name $sce#getTrustedHtml\n     *\n     * @description\n     * Shorthand method.  `$sce.getTrustedHtml(value)` →\n     *     {@link ng.$sceDelegate#getTrusted `$sceDelegate.getTrusted($sce.HTML, value)`}\n     *\n     * @param {*} value The value to pass to `$sce.getTrusted`.\n     * @returns {*} The return value of `$sce.getTrusted($sce.HTML, value)`\n     */\n\n    /**\n     * @ngdoc method\n     * @name $sce#getTrustedCss\n     *\n     * @description\n     * Shorthand method.  `$sce.getTrustedCss(value)` →\n     *     {@link ng.$sceDelegate#getTrusted `$sceDelegate.getTrusted($sce.CSS, value)`}\n     *\n     * @param {*} value The value to pass to `$sce.getTrusted`.\n     * @returns {*} The return value of `$sce.getTrusted($sce.CSS, value)`\n     */\n\n    /**\n     * @ngdoc method\n     * @name $sce#getTrustedUrl\n     *\n     * @description\n     * Shorthand method.  `$sce.getTrustedUrl(value)` →\n     *     {@link ng.$sceDelegate#getTrusted `$sceDelegate.getTrusted($sce.URL, value)`}\n     *\n     * @param {*} value The value to pass to `$sce.getTrusted`.\n     * @returns {*} The return value of `$sce.getTrusted($sce.URL, value)`\n     */\n\n    /**\n     * @ngdoc method\n     * @name $sce#getTrustedResourceUrl\n     *\n     * @description\n     * Shorthand method.  `$sce.getTrustedResourceUrl(value)` →\n     *     {@link ng.$sceDelegate#getTrusted `$sceDelegate.getTrusted($sce.RESOURCE_URL, value)`}\n     *\n     * @param {*} value The value to pass to `$sceDelegate.getTrusted`.\n     * @returns {*} The return value of `$sce.getTrusted($sce.RESOURCE_URL, value)`\n     */\n\n    /**\n     * @ngdoc method\n     * @name $sce#getTrustedJs\n     *\n     * @description\n     * Shorthand method.  `$sce.getTrustedJs(value)` →\n     *     {@link ng.$sceDelegate#getTrusted `$sceDelegate.getTrusted($sce.JS, value)`}\n     *\n     * @param {*} value The value to pass to `$sce.getTrusted`.\n     * @returns {*} The return value of `$sce.getTrusted($sce.JS, value)`\n     */\n\n    /**\n     * @ngdoc method\n     * @name $sce#parseAsHtml\n     *\n     * @description\n     * Shorthand method.  `$sce.parseAsHtml(expression string)` →\n     *     {@link ng.$sce#parseAs `$sce.parseAs($sce.HTML, value)`}\n     *\n     * @param {string} expression String expression to compile.\n     * @returns {function(context, locals)} a function which represents the compiled expression:\n     *\n     *    * `context` – `{object}` – an object against which any expressions embedded in the strings\n     *      are evaluated against (typically a scope object).\n     *    * `locals` – `{object=}` – local variables context object, useful for overriding values in\n     *      `context`.\n     */\n\n    /**\n     * @ngdoc method\n     * @name $sce#parseAsCss\n     *\n     * @description\n     * Shorthand method.  `$sce.parseAsCss(value)` →\n     *     {@link ng.$sce#parseAs `$sce.parseAs($sce.CSS, value)`}\n     *\n     * @param {string} expression String expression to compile.\n     * @returns {function(context, locals)} a function which represents the compiled expression:\n     *\n     *    * `context` – `{object}` – an object against which any expressions embedded in the strings\n     *      are evaluated against (typically a scope object).\n     *    * `locals` – `{object=}` – local variables context object, useful for overriding values in\n     *      `context`.\n     */\n\n    /**\n     * @ngdoc method\n     * @name $sce#parseAsUrl\n     *\n     * @description\n     * Shorthand method.  `$sce.parseAsUrl(value)` →\n     *     {@link ng.$sce#parseAs `$sce.parseAs($sce.URL, value)`}\n     *\n     * @param {string} expression String expression to compile.\n     * @returns {function(context, locals)} a function which represents the compiled expression:\n     *\n     *    * `context` – `{object}` – an object against which any expressions embedded in the strings\n     *      are evaluated against (typically a scope object).\n     *    * `locals` – `{object=}` – local variables context object, useful for overriding values in\n     *      `context`.\n     */\n\n    /**\n     * @ngdoc method\n     * @name $sce#parseAsResourceUrl\n     *\n     * @description\n     * Shorthand method.  `$sce.parseAsResourceUrl(value)` →\n     *     {@link ng.$sce#parseAs `$sce.parseAs($sce.RESOURCE_URL, value)`}\n     *\n     * @param {string} expression String expression to compile.\n     * @returns {function(context, locals)} a function which represents the compiled expression:\n     *\n     *    * `context` – `{object}` – an object against which any expressions embedded in the strings\n     *      are evaluated against (typically a scope object).\n     *    * `locals` – `{object=}` – local variables context object, useful for overriding values in\n     *      `context`.\n     */\n\n    /**\n     * @ngdoc method\n     * @name $sce#parseAsJs\n     *\n     * @description\n     * Shorthand method.  `$sce.parseAsJs(value)` →\n     *     {@link ng.$sce#parseAs `$sce.parseAs($sce.JS, value)`}\n     *\n     * @param {string} expression String expression to compile.\n     * @returns {function(context, locals)} a function which represents the compiled expression:\n     *\n     *    * `context` – `{object}` – an object against which any expressions embedded in the strings\n     *      are evaluated against (typically a scope object).\n     *    * `locals` – `{object=}` – local variables context object, useful for overriding values in\n     *      `context`.\n     */\n\n    // Shorthand delegations.\n    var parse = sce.parseAs,\n        getTrusted = sce.getTrusted,\n        trustAs = sce.trustAs;\n\n    forEach(SCE_CONTEXTS, function(enumValue, name) {\n      var lName = lowercase(name);\n      sce[camelCase(\"parse_as_\" + lName)] = function(expr) {\n        return parse(enumValue, expr);\n      };\n      sce[camelCase(\"get_trusted_\" + lName)] = function(value) {\n        return getTrusted(enumValue, value);\n      };\n      sce[camelCase(\"trust_as_\" + lName)] = function(value) {\n        return trustAs(enumValue, value);\n      };\n    });\n\n    return sce;\n  }];\n}\n\n/**\n * !!! This is an undocumented \"private\" service !!!\n *\n * @name $sniffer\n * @requires $window\n * @requires $document\n *\n * @property {boolean} history Does the browser support html5 history api ?\n * @property {boolean} transitions Does the browser support CSS transition events ?\n * @property {boolean} animations Does the browser support CSS animation events ?\n *\n * @description\n * This is very simple implementation of testing browser's features.\n */\nfunction $SnifferProvider() {\n  this.$get = ['$window', '$document', function($window, $document) {\n    var eventSupport = {},\n        android =\n          int((/android (\\d+)/.exec(lowercase(($window.navigator || {}).userAgent)) || [])[1]),\n        boxee = /Boxee/i.test(($window.navigator || {}).userAgent),\n        document = $document[0] || {},\n        vendorPrefix,\n        vendorRegex = /^(Moz|webkit|ms)(?=[A-Z])/,\n        bodyStyle = document.body && document.body.style,\n        transitions = false,\n        animations = false,\n        match;\n\n    if (bodyStyle) {\n      for (var prop in bodyStyle) {\n        if (match = vendorRegex.exec(prop)) {\n          vendorPrefix = match[0];\n          vendorPrefix = vendorPrefix.substr(0, 1).toUpperCase() + vendorPrefix.substr(1);\n          break;\n        }\n      }\n\n      if (!vendorPrefix) {\n        vendorPrefix = ('WebkitOpacity' in bodyStyle) && 'webkit';\n      }\n\n      transitions = !!(('transition' in bodyStyle) || (vendorPrefix + 'Transition' in bodyStyle));\n      animations  = !!(('animation' in bodyStyle) || (vendorPrefix + 'Animation' in bodyStyle));\n\n      if (android && (!transitions ||  !animations)) {\n        transitions = isString(document.body.style.webkitTransition);\n        animations = isString(document.body.style.webkitAnimation);\n      }\n    }\n\n\n    return {\n      // Android has history.pushState, but it does not update location correctly\n      // so let's not use the history API at all.\n      // http://code.google.com/p/android/issues/detail?id=17471\n      // https://github.com/angular/angular.js/issues/904\n\n      // older webkit browser (533.9) on Boxee box has exactly the same problem as Android has\n      // so let's not use the history API also\n      // We are purposefully using `!(android < 4)` to cover the case when `android` is undefined\n      // jshint -W018\n      history: !!($window.history && $window.history.pushState && !(android < 4) && !boxee),\n      // jshint +W018\n      hasEvent: function(event) {\n        // IE9 implements 'input' event it's so fubared that we rather pretend that it doesn't have\n        // it. In particular the event is not fired when backspace or delete key are pressed or\n        // when cut operation is performed.\n        // IE10+ implements 'input' event but it erroneously fires under various situations,\n        // e.g. when placeholder changes, or a form is focused.\n        if (event === 'input' && msie <= 11) return false;\n\n        if (isUndefined(eventSupport[event])) {\n          var divElm = document.createElement('div');\n          eventSupport[event] = 'on' + event in divElm;\n        }\n\n        return eventSupport[event];\n      },\n      csp: csp(),\n      vendorPrefix: vendorPrefix,\n      transitions: transitions,\n      animations: animations,\n      android: android\n    };\n  }];\n}\n\nvar $compileMinErr = minErr('$compile');\n\n/**\n * @ngdoc service\n * @name $templateRequest\n *\n * @description\n * The `$templateRequest` service downloads the provided template using `$http` and, upon success,\n * stores the contents inside of `$templateCache`. If the HTTP request fails or the response data\n * of the HTTP request is empty, a `$compile` error will be thrown (the exception can be thwarted\n * by setting the 2nd parameter of the function to true).\n *\n * @param {string} tpl The HTTP request template URL\n * @param {boolean=} ignoreRequestError Whether or not to ignore the exception when the request fails or the template is empty\n *\n * @return {Promise} the HTTP Promise for the given.\n *\n * @property {number} totalPendingRequests total amount of pending template requests being downloaded.\n */\nfunction $TemplateRequestProvider() {\n  this.$get = ['$templateCache', '$http', '$q', function($templateCache, $http, $q) {\n    function handleRequestFn(tpl, ignoreRequestError) {\n      handleRequestFn.totalPendingRequests++;\n\n      var transformResponse = $http.defaults && $http.defaults.transformResponse;\n\n      if (isArray(transformResponse)) {\n        transformResponse = transformResponse.filter(function(transformer) {\n          return transformer !== defaultHttpResponseTransform;\n        });\n      } else if (transformResponse === defaultHttpResponseTransform) {\n        transformResponse = null;\n      }\n\n      var httpOptions = {\n        cache: $templateCache,\n        transformResponse: transformResponse\n      };\n\n      return $http.get(tpl, httpOptions)\n        .finally(function() {\n          handleRequestFn.totalPendingRequests--;\n        })\n        .then(function(response) {\n          return response.data;\n        }, handleError);\n\n      function handleError(resp) {\n        if (!ignoreRequestError) {\n          throw $compileMinErr('tpload', 'Failed to load template: {0}', tpl);\n        }\n        return $q.reject(resp);\n      }\n    }\n\n    handleRequestFn.totalPendingRequests = 0;\n\n    return handleRequestFn;\n  }];\n}\n\nfunction $$TestabilityProvider() {\n  this.$get = ['$rootScope', '$browser', '$location',\n       function($rootScope,   $browser,   $location) {\n\n    /**\n     * @name $testability\n     *\n     * @description\n     * The private $$testability service provides a collection of methods for use when debugging\n     * or by automated test and debugging tools.\n     */\n    var testability = {};\n\n    /**\n     * @name $$testability#findBindings\n     *\n     * @description\n     * Returns an array of elements that are bound (via ng-bind or {{}})\n     * to expressions matching the input.\n     *\n     * @param {Element} element The element root to search from.\n     * @param {string} expression The binding expression to match.\n     * @param {boolean} opt_exactMatch If true, only returns exact matches\n     *     for the expression. Filters and whitespace are ignored.\n     */\n    testability.findBindings = function(element, expression, opt_exactMatch) {\n      var bindings = element.getElementsByClassName('ng-binding');\n      var matches = [];\n      forEach(bindings, function(binding) {\n        var dataBinding = angular.element(binding).data('$binding');\n        if (dataBinding) {\n          forEach(dataBinding, function(bindingName) {\n            if (opt_exactMatch) {\n              var matcher = new RegExp('(^|\\\\s)' + escapeForRegexp(expression) + '(\\\\s|\\\\||$)');\n              if (matcher.test(bindingName)) {\n                matches.push(binding);\n              }\n            } else {\n              if (bindingName.indexOf(expression) != -1) {\n                matches.push(binding);\n              }\n            }\n          });\n        }\n      });\n      return matches;\n    };\n\n    /**\n     * @name $$testability#findModels\n     *\n     * @description\n     * Returns an array of elements that are two-way found via ng-model to\n     * expressions matching the input.\n     *\n     * @param {Element} element The element root to search from.\n     * @param {string} expression The model expression to match.\n     * @param {boolean} opt_exactMatch If true, only returns exact matches\n     *     for the expression.\n     */\n    testability.findModels = function(element, expression, opt_exactMatch) {\n      var prefixes = ['ng-', 'data-ng-', 'ng\\\\:'];\n      for (var p = 0; p < prefixes.length; ++p) {\n        var attributeEquals = opt_exactMatch ? '=' : '*=';\n        var selector = '[' + prefixes[p] + 'model' + attributeEquals + '\"' + expression + '\"]';\n        var elements = element.querySelectorAll(selector);\n        if (elements.length) {\n          return elements;\n        }\n      }\n    };\n\n    /**\n     * @name $$testability#getLocation\n     *\n     * @description\n     * Shortcut for getting the location in a browser agnostic way. Returns\n     *     the path, search, and hash. (e.g. /path?a=b#hash)\n     */\n    testability.getLocation = function() {\n      return $location.url();\n    };\n\n    /**\n     * @name $$testability#setLocation\n     *\n     * @description\n     * Shortcut for navigating to a location without doing a full page reload.\n     *\n     * @param {string} url The location url (path, search and hash,\n     *     e.g. /path?a=b#hash) to go to.\n     */\n    testability.setLocation = function(url) {\n      if (url !== $location.url()) {\n        $location.url(url);\n        $rootScope.$digest();\n      }\n    };\n\n    /**\n     * @name $$testability#whenStable\n     *\n     * @description\n     * Calls the callback when $timeout and $http requests are completed.\n     *\n     * @param {function} callback\n     */\n    testability.whenStable = function(callback) {\n      $browser.notifyWhenNoOutstandingRequests(callback);\n    };\n\n    return testability;\n  }];\n}\n\nfunction $TimeoutProvider() {\n  this.$get = ['$rootScope', '$browser', '$q', '$$q', '$exceptionHandler',\n       function($rootScope,   $browser,   $q,   $$q,   $exceptionHandler) {\n    var deferreds = {};\n\n\n     /**\n      * @ngdoc service\n      * @name $timeout\n      *\n      * @description\n      * Angular's wrapper for `window.setTimeout`. The `fn` function is wrapped into a try/catch\n      * block and delegates any exceptions to\n      * {@link ng.$exceptionHandler $exceptionHandler} service.\n      *\n      * The return value of registering a timeout function is a promise, which will be resolved when\n      * the timeout is reached and the timeout function is executed.\n      *\n      * To cancel a timeout request, call `$timeout.cancel(promise)`.\n      *\n      * In tests you can use {@link ngMock.$timeout `$timeout.flush()`} to\n      * synchronously flush the queue of deferred functions.\n      *\n      * @param {function()} fn A function, whose execution should be delayed.\n      * @param {number=} [delay=0] Delay in milliseconds.\n      * @param {boolean=} [invokeApply=true] If set to `false` skips model dirty checking, otherwise\n      *   will invoke `fn` within the {@link ng.$rootScope.Scope#$apply $apply} block.\n      * @returns {Promise} Promise that will be resolved when the timeout is reached. The value this\n      *   promise will be resolved with is the return value of the `fn` function.\n      *\n      */\n    function timeout(fn, delay, invokeApply) {\n      var skipApply = (isDefined(invokeApply) && !invokeApply),\n          deferred = (skipApply ? $$q : $q).defer(),\n          promise = deferred.promise,\n          timeoutId;\n\n      timeoutId = $browser.defer(function() {\n        try {\n          deferred.resolve(fn());\n        } catch (e) {\n          deferred.reject(e);\n          $exceptionHandler(e);\n        }\n        finally {\n          delete deferreds[promise.$$timeoutId];\n        }\n\n        if (!skipApply) $rootScope.$apply();\n      }, delay);\n\n      promise.$$timeoutId = timeoutId;\n      deferreds[timeoutId] = deferred;\n\n      return promise;\n    }\n\n\n     /**\n      * @ngdoc method\n      * @name $timeout#cancel\n      *\n      * @description\n      * Cancels a task associated with the `promise`. As a result of this, the promise will be\n      * resolved with a rejection.\n      *\n      * @param {Promise=} promise Promise returned by the `$timeout` function.\n      * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfully\n      *   canceled.\n      */\n    timeout.cancel = function(promise) {\n      if (promise && promise.$$timeoutId in deferreds) {\n        deferreds[promise.$$timeoutId].reject('canceled');\n        delete deferreds[promise.$$timeoutId];\n        return $browser.defer.cancel(promise.$$timeoutId);\n      }\n      return false;\n    };\n\n    return timeout;\n  }];\n}\n\n// NOTE:  The usage of window and document instead of $window and $document here is\n// deliberate.  This service depends on the specific behavior of anchor nodes created by the\n// browser (resolving and parsing URLs) that is unlikely to be provided by mock objects and\n// cause us to break tests.  In addition, when the browser resolves a URL for XHR, it\n// doesn't know about mocked locations and resolves URLs to the real document - which is\n// exactly the behavior needed here.  There is little value is mocking these out for this\n// service.\nvar urlParsingNode = document.createElement(\"a\");\nvar originUrl = urlResolve(window.location.href);\n\n\n/**\n *\n * Implementation Notes for non-IE browsers\n * ----------------------------------------\n * Assigning a URL to the href property of an anchor DOM node, even one attached to the DOM,\n * results both in the normalizing and parsing of the URL.  Normalizing means that a relative\n * URL will be resolved into an absolute URL in the context of the application document.\n * Parsing means that the anchor node's host, hostname, protocol, port, pathname and related\n * properties are all populated to reflect the normalized URL.  This approach has wide\n * compatibility - Safari 1+, Mozilla 1+, Opera 7+,e etc.  See\n * http://www.aptana.com/reference/html/api/HTMLAnchorElement.html\n *\n * Implementation Notes for IE\n * ---------------------------\n * IE >= 8 and <= 10 normalizes the URL when assigned to the anchor node similar to the other\n * browsers.  However, the parsed components will not be set if the URL assigned did not specify\n * them.  (e.g. if you assign a.href = \"foo\", then a.protocol, a.host, etc. will be empty.)  We\n * work around that by performing the parsing in a 2nd step by taking a previously normalized\n * URL (e.g. by assigning to a.href) and assigning it a.href again.  This correctly populates the\n * properties such as protocol, hostname, port, etc.\n *\n * IE7 does not normalize the URL when assigned to an anchor node.  (Apparently, it does, if one\n * uses the inner HTML approach to assign the URL as part of an HTML snippet -\n * http://stackoverflow.com/a/472729)  However, setting img[src] does normalize the URL.\n * Unfortunately, setting img[src] to something like \"javascript:foo\" on IE throws an exception.\n * Since the primary usage for normalizing URLs is to sanitize such URLs, we can't use that\n * method and IE < 8 is unsupported.\n *\n * References:\n *   http://developer.mozilla.org/en-US/docs/Web/API/HTMLAnchorElement\n *   http://www.aptana.com/reference/html/api/HTMLAnchorElement.html\n *   http://url.spec.whatwg.org/#urlutils\n *   https://github.com/angular/angular.js/pull/2902\n *   http://james.padolsey.com/javascript/parsing-urls-with-the-dom/\n *\n * @kind function\n * @param {string} url The URL to be parsed.\n * @description Normalizes and parses a URL.\n * @returns {object} Returns the normalized URL as a dictionary.\n *\n *   | member name   | Description    |\n *   |---------------|----------------|\n *   | href          | A normalized version of the provided URL if it was not an absolute URL |\n *   | protocol      | The protocol including the trailing colon                              |\n *   | host          | The host and port (if the port is non-default) of the normalizedUrl    |\n *   | search        | The search params, minus the question mark                             |\n *   | hash          | The hash string, minus the hash symbol\n *   | hostname      | The hostname\n *   | port          | The port, without \":\"\n *   | pathname      | The pathname, beginning with \"/\"\n *\n */\nfunction urlResolve(url) {\n  var href = url;\n\n  if (msie) {\n    // Normalize before parse.  Refer Implementation Notes on why this is\n    // done in two steps on IE.\n    urlParsingNode.setAttribute(\"href\", href);\n    href = urlParsingNode.href;\n  }\n\n  urlParsingNode.setAttribute('href', href);\n\n  // urlParsingNode provides the UrlUtils interface - http://url.spec.whatwg.org/#urlutils\n  return {\n    href: urlParsingNode.href,\n    protocol: urlParsingNode.protocol ? urlParsingNode.protocol.replace(/:$/, '') : '',\n    host: urlParsingNode.host,\n    search: urlParsingNode.search ? urlParsingNode.search.replace(/^\\?/, '') : '',\n    hash: urlParsingNode.hash ? urlParsingNode.hash.replace(/^#/, '') : '',\n    hostname: urlParsingNode.hostname,\n    port: urlParsingNode.port,\n    pathname: (urlParsingNode.pathname.charAt(0) === '/')\n      ? urlParsingNode.pathname\n      : '/' + urlParsingNode.pathname\n  };\n}\n\n/**\n * Parse a request URL and determine whether this is a same-origin request as the application document.\n *\n * @param {string|object} requestUrl The url of the request as a string that will be resolved\n * or a parsed URL object.\n * @returns {boolean} Whether the request is for the same origin as the application document.\n */\nfunction urlIsSameOrigin(requestUrl) {\n  var parsed = (isString(requestUrl)) ? urlResolve(requestUrl) : requestUrl;\n  return (parsed.protocol === originUrl.protocol &&\n          parsed.host === originUrl.host);\n}\n\n/**\n * @ngdoc service\n * @name $window\n *\n * @description\n * A reference to the browser's `window` object. While `window`\n * is globally available in JavaScript, it causes testability problems, because\n * it is a global variable. In angular we always refer to it through the\n * `$window` service, so it may be overridden, removed or mocked for testing.\n *\n * Expressions, like the one defined for the `ngClick` directive in the example\n * below, are evaluated with respect to the current scope.  Therefore, there is\n * no risk of inadvertently coding in a dependency on a global value in such an\n * expression.\n *\n * @example\n   <example module=\"windowExample\">\n     <file name=\"index.html\">\n       <script>\n         angular.module('windowExample', [])\n           .controller('ExampleController', ['$scope', '$window', function($scope, $window) {\n             $scope.greeting = 'Hello, World!';\n             $scope.doGreeting = function(greeting) {\n               $window.alert(greeting);\n             };\n           }]);\n       </script>\n       <div ng-controller=\"ExampleController\">\n         <input type=\"text\" ng-model=\"greeting\" />\n         <button ng-click=\"doGreeting(greeting)\">ALERT</button>\n       </div>\n     </file>\n     <file name=\"protractor.js\" type=\"protractor\">\n      it('should display the greeting in the input box', function() {\n       element(by.model('greeting')).sendKeys('Hello, E2E Tests');\n       // If we click the button it will block the test runner\n       // element(':button').click();\n      });\n     </file>\n   </example>\n */\nfunction $WindowProvider() {\n  this.$get = valueFn(window);\n}\n\n/* global currencyFilter: true,\n dateFilter: true,\n filterFilter: true,\n jsonFilter: true,\n limitToFilter: true,\n lowercaseFilter: true,\n numberFilter: true,\n orderByFilter: true,\n uppercaseFilter: true,\n */\n\n/**\n * @ngdoc provider\n * @name $filterProvider\n * @description\n *\n * Filters are just functions which transform input to an output. However filters need to be\n * Dependency Injected. To achieve this a filter definition consists of a factory function which is\n * annotated with dependencies and is responsible for creating a filter function.\n *\n * ```js\n *   // Filter registration\n *   function MyModule($provide, $filterProvider) {\n *     // create a service to demonstrate injection (not always needed)\n *     $provide.value('greet', function(name){\n *       return 'Hello ' + name + '!';\n *     });\n *\n *     // register a filter factory which uses the\n *     // greet service to demonstrate DI.\n *     $filterProvider.register('greet', function(greet){\n *       // return the filter function which uses the greet service\n *       // to generate salutation\n *       return function(text) {\n *         // filters need to be forgiving so check input validity\n *         return text && greet(text) || text;\n *       };\n *     });\n *   }\n * ```\n *\n * The filter function is registered with the `$injector` under the filter name suffix with\n * `Filter`.\n *\n * ```js\n *   it('should be the same instance', inject(\n *     function($filterProvider) {\n *       $filterProvider.register('reverse', function(){\n *         return ...;\n *       });\n *     },\n *     function($filter, reverseFilter) {\n *       expect($filter('reverse')).toBe(reverseFilter);\n *     });\n * ```\n *\n *\n * For more information about how angular filters work, and how to create your own filters, see\n * {@link guide/filter Filters} in the Angular Developer Guide.\n */\n\n/**\n * @ngdoc service\n * @name $filter\n * @kind function\n * @description\n * Filters are used for formatting data displayed to the user.\n *\n * The general syntax in templates is as follows:\n *\n *         {{ expression [| filter_name[:parameter_value] ... ] }}\n *\n * @param {String} name Name of the filter function to retrieve\n * @return {Function} the filter function\n * @example\n   <example name=\"$filter\" module=\"filterExample\">\n     <file name=\"index.html\">\n       <div ng-controller=\"MainCtrl\">\n        <h3>{{ originalText }}</h3>\n        <h3>{{ filteredText }}</h3>\n       </div>\n     </file>\n\n     <file name=\"script.js\">\n      angular.module('filterExample', [])\n      .controller('MainCtrl', function($scope, $filter) {\n        $scope.originalText = 'hello';\n        $scope.filteredText = $filter('uppercase')($scope.originalText);\n      });\n     </file>\n   </example>\n  */\n$FilterProvider.$inject = ['$provide'];\nfunction $FilterProvider($provide) {\n  var suffix = 'Filter';\n\n  /**\n   * @ngdoc method\n   * @name $filterProvider#register\n   * @param {string|Object} name Name of the filter function, or an object map of filters where\n   *    the keys are the filter names and the values are the filter factories.\n   * @returns {Object} Registered filter instance, or if a map of filters was provided then a map\n   *    of the registered filter instances.\n   */\n  function register(name, factory) {\n    if (isObject(name)) {\n      var filters = {};\n      forEach(name, function(filter, key) {\n        filters[key] = register(key, filter);\n      });\n      return filters;\n    } else {\n      return $provide.factory(name + suffix, factory);\n    }\n  }\n  this.register = register;\n\n  this.$get = ['$injector', function($injector) {\n    return function(name) {\n      return $injector.get(name + suffix);\n    };\n  }];\n\n  ////////////////////////////////////////\n\n  /* global\n    currencyFilter: false,\n    dateFilter: false,\n    filterFilter: false,\n    jsonFilter: false,\n    limitToFilter: false,\n    lowercaseFilter: false,\n    numberFilter: false,\n    orderByFilter: false,\n    uppercaseFilter: false,\n  */\n\n  register('currency', currencyFilter);\n  register('date', dateFilter);\n  register('filter', filterFilter);\n  register('json', jsonFilter);\n  register('limitTo', limitToFilter);\n  register('lowercase', lowercaseFilter);\n  register('number', numberFilter);\n  register('orderBy', orderByFilter);\n  register('uppercase', uppercaseFilter);\n}\n\n/**\n * @ngdoc filter\n * @name filter\n * @kind function\n *\n * @description\n * Selects a subset of items from `array` and returns it as a new array.\n *\n * @param {Array} array The source array.\n * @param {string|Object|function()} expression The predicate to be used for selecting items from\n *   `array`.\n *\n *   Can be one of:\n *\n *   - `string`: The string is used for matching against the contents of the `array`. All strings or\n *     objects with string properties in `array` that match this string will be returned. This also\n *     applies to nested object properties.\n *     The predicate can be negated by prefixing the string with `!`.\n *\n *   - `Object`: A pattern object can be used to filter specific properties on objects contained\n *     by `array`. For example `{name:\"M\", phone:\"1\"}` predicate will return an array of items\n *     which have property `name` containing \"M\" and property `phone` containing \"1\". A special\n *     property name `$` can be used (as in `{$:\"text\"}`) to accept a match against any\n *     property of the object or its nested object properties. That's equivalent to the simple\n *     substring match with a `string` as described above. The predicate can be negated by prefixing\n *     the string with `!`.\n *     For example `{name: \"!M\"}` predicate will return an array of items which have property `name`\n *     not containing \"M\".\n *\n *     Note that a named property will match properties on the same level only, while the special\n *     `$` property will match properties on the same level or deeper. E.g. an array item like\n *     `{name: {first: 'John', last: 'Doe'}}` will **not** be matched by `{name: 'John'}`, but\n *     **will** be matched by `{$: 'John'}`.\n *\n *   - `function(value, index)`: A predicate function can be used to write arbitrary filters. The\n *     function is called for each element of `array`. The final result is an array of those\n *     elements that the predicate returned true for.\n *\n * @param {function(actual, expected)|true|undefined} comparator Comparator which is used in\n *     determining if the expected value (from the filter expression) and actual value (from\n *     the object in the array) should be considered a match.\n *\n *   Can be one of:\n *\n *   - `function(actual, expected)`:\n *     The function will be given the object value and the predicate value to compare and\n *     should return true if both values should be considered equal.\n *\n *   - `true`: A shorthand for `function(actual, expected) { return angular.equals(actual, expected)}`.\n *     This is essentially strict comparison of expected and actual.\n *\n *   - `false|undefined`: A short hand for a function which will look for a substring match in case\n *     insensitive way.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n       <div ng-init=\"friends = [{name:'John', phone:'555-1276'},\n                                {name:'Mary', phone:'800-BIG-MARY'},\n                                {name:'Mike', phone:'555-4321'},\n                                {name:'Adam', phone:'555-5678'},\n                                {name:'Julie', phone:'555-8765'},\n                                {name:'Juliette', phone:'555-5678'}]\"></div>\n\n       Search: <input ng-model=\"searchText\">\n       <table id=\"searchTextResults\">\n         <tr><th>Name</th><th>Phone</th></tr>\n         <tr ng-repeat=\"friend in friends | filter:searchText\">\n           <td>{{friend.name}}</td>\n           <td>{{friend.phone}}</td>\n         </tr>\n       </table>\n       <hr>\n       Any: <input ng-model=\"search.$\"> <br>\n       Name only <input ng-model=\"search.name\"><br>\n       Phone only <input ng-model=\"search.phone\"><br>\n       Equality <input type=\"checkbox\" ng-model=\"strict\"><br>\n       <table id=\"searchObjResults\">\n         <tr><th>Name</th><th>Phone</th></tr>\n         <tr ng-repeat=\"friendObj in friends | filter:search:strict\">\n           <td>{{friendObj.name}}</td>\n           <td>{{friendObj.phone}}</td>\n         </tr>\n       </table>\n     </file>\n     <file name=\"protractor.js\" type=\"protractor\">\n       var expectFriendNames = function(expectedNames, key) {\n         element.all(by.repeater(key + ' in friends').column(key + '.name')).then(function(arr) {\n           arr.forEach(function(wd, i) {\n             expect(wd.getText()).toMatch(expectedNames[i]);\n           });\n         });\n       };\n\n       it('should search across all fields when filtering with a string', function() {\n         var searchText = element(by.model('searchText'));\n         searchText.clear();\n         searchText.sendKeys('m');\n         expectFriendNames(['Mary', 'Mike', 'Adam'], 'friend');\n\n         searchText.clear();\n         searchText.sendKeys('76');\n         expectFriendNames(['John', 'Julie'], 'friend');\n       });\n\n       it('should search in specific fields when filtering with a predicate object', function() {\n         var searchAny = element(by.model('search.$'));\n         searchAny.clear();\n         searchAny.sendKeys('i');\n         expectFriendNames(['Mary', 'Mike', 'Julie', 'Juliette'], 'friendObj');\n       });\n       it('should use a equal comparison when comparator is true', function() {\n         var searchName = element(by.model('search.name'));\n         var strict = element(by.model('strict'));\n         searchName.clear();\n         searchName.sendKeys('Julie');\n         strict.click();\n         expectFriendNames(['Julie'], 'friendObj');\n       });\n     </file>\n   </example>\n */\nfunction filterFilter() {\n  return function(array, expression, comparator) {\n    if (!isArray(array)) return array;\n\n    var predicateFn;\n    var matchAgainstAnyProp;\n\n    switch (typeof expression) {\n      case 'function':\n        predicateFn = expression;\n        break;\n      case 'boolean':\n      case 'number':\n      case 'string':\n        matchAgainstAnyProp = true;\n        //jshint -W086\n      case 'object':\n        //jshint +W086\n        predicateFn = createPredicateFn(expression, comparator, matchAgainstAnyProp);\n        break;\n      default:\n        return array;\n    }\n\n    return array.filter(predicateFn);\n  };\n}\n\n// Helper functions for `filterFilter`\nfunction createPredicateFn(expression, comparator, matchAgainstAnyProp) {\n  var shouldMatchPrimitives = isObject(expression) && ('$' in expression);\n  var predicateFn;\n\n  if (comparator === true) {\n    comparator = equals;\n  } else if (!isFunction(comparator)) {\n    comparator = function(actual, expected) {\n      if (isObject(actual) || isObject(expected)) {\n        // Prevent an object to be considered equal to a string like `'[object'`\n        return false;\n      }\n\n      actual = lowercase('' + actual);\n      expected = lowercase('' + expected);\n      return actual.indexOf(expected) !== -1;\n    };\n  }\n\n  predicateFn = function(item) {\n    if (shouldMatchPrimitives && !isObject(item)) {\n      return deepCompare(item, expression.$, comparator, false);\n    }\n    return deepCompare(item, expression, comparator, matchAgainstAnyProp);\n  };\n\n  return predicateFn;\n}\n\nfunction deepCompare(actual, expected, comparator, matchAgainstAnyProp, dontMatchWholeObject) {\n  var actualType = typeof actual;\n  var expectedType = typeof expected;\n\n  if ((expectedType === 'string') && (expected.charAt(0) === '!')) {\n    return !deepCompare(actual, expected.substring(1), comparator, matchAgainstAnyProp);\n  } else if (isArray(actual)) {\n    // In case `actual` is an array, consider it a match\n    // if ANY of it's items matches `expected`\n    return actual.some(function(item) {\n      return deepCompare(item, expected, comparator, matchAgainstAnyProp);\n    });\n  }\n\n  switch (actualType) {\n    case 'object':\n      var key;\n      if (matchAgainstAnyProp) {\n        for (key in actual) {\n          if ((key.charAt(0) !== '$') && deepCompare(actual[key], expected, comparator, true)) {\n            return true;\n          }\n        }\n        return dontMatchWholeObject ? false : deepCompare(actual, expected, comparator, false);\n      } else if (expectedType === 'object') {\n        for (key in expected) {\n          var expectedVal = expected[key];\n          if (isFunction(expectedVal)) {\n            continue;\n          }\n\n          var matchAnyProperty = key === '$';\n          var actualVal = matchAnyProperty ? actual : actual[key];\n          if (!deepCompare(actualVal, expectedVal, comparator, matchAnyProperty, matchAnyProperty)) {\n            return false;\n          }\n        }\n        return true;\n      } else {\n        return comparator(actual, expected);\n      }\n      break;\n    case 'function':\n      return false;\n    default:\n      return comparator(actual, expected);\n  }\n}\n\n/**\n * @ngdoc filter\n * @name currency\n * @kind function\n *\n * @description\n * Formats a number as a currency (ie $1,234.56). When no currency symbol is provided, default\n * symbol for current locale is used.\n *\n * @param {number} amount Input to filter.\n * @param {string=} symbol Currency symbol or identifier to be displayed.\n * @param {number=} fractionSize Number of decimal places to round the amount to, defaults to default max fraction size for current locale\n * @returns {string} Formatted number.\n *\n *\n * @example\n   <example module=\"currencyExample\">\n     <file name=\"index.html\">\n       <script>\n         angular.module('currencyExample', [])\n           .controller('ExampleController', ['$scope', function($scope) {\n             $scope.amount = 1234.56;\n           }]);\n       </script>\n       <div ng-controller=\"ExampleController\">\n         <input type=\"number\" ng-model=\"amount\"> <br>\n         default currency symbol ($): <span id=\"currency-default\">{{amount | currency}}</span><br>\n         custom currency identifier (USD$): <span id=\"currency-custom\">{{amount | currency:\"USD$\"}}</span>\n         no fractions (0): <span id=\"currency-no-fractions\">{{amount | currency:\"USD$\":0}}</span>\n       </div>\n     </file>\n     <file name=\"protractor.js\" type=\"protractor\">\n       it('should init with 1234.56', function() {\n         expect(element(by.id('currency-default')).getText()).toBe('$1,234.56');\n         expect(element(by.id('currency-custom')).getText()).toBe('USD$1,234.56');\n         expect(element(by.id('currency-no-fractions')).getText()).toBe('USD$1,235');\n       });\n       it('should update', function() {\n         if (browser.params.browser == 'safari') {\n           // Safari does not understand the minus key. See\n           // https://github.com/angular/protractor/issues/481\n           return;\n         }\n         element(by.model('amount')).clear();\n         element(by.model('amount')).sendKeys('-1234');\n         expect(element(by.id('currency-default')).getText()).toBe('($1,234.00)');\n         expect(element(by.id('currency-custom')).getText()).toBe('(USD$1,234.00)');\n         expect(element(by.id('currency-no-fractions')).getText()).toBe('(USD$1,234)');\n       });\n     </file>\n   </example>\n */\ncurrencyFilter.$inject = ['$locale'];\nfunction currencyFilter($locale) {\n  var formats = $locale.NUMBER_FORMATS;\n  return function(amount, currencySymbol, fractionSize) {\n    if (isUndefined(currencySymbol)) {\n      currencySymbol = formats.CURRENCY_SYM;\n    }\n\n    if (isUndefined(fractionSize)) {\n      fractionSize = formats.PATTERNS[1].maxFrac;\n    }\n\n    // if null or undefined pass it through\n    return (amount == null)\n        ? amount\n        : formatNumber(amount, formats.PATTERNS[1], formats.GROUP_SEP, formats.DECIMAL_SEP, fractionSize).\n            replace(/\\u00A4/g, currencySymbol);\n  };\n}\n\n/**\n * @ngdoc filter\n * @name number\n * @kind function\n *\n * @description\n * Formats a number as text.\n *\n * If the input is not a number an empty string is returned.\n *\n * @param {number|string} number Number to format.\n * @param {(number|string)=} fractionSize Number of decimal places to round the number to.\n * If this is not provided then the fraction size is computed from the current locale's number\n * formatting pattern. In the case of the default locale, it will be 3.\n * @returns {string} Number rounded to decimalPlaces and places a “,” after each third digit.\n *\n * @example\n   <example module=\"numberFilterExample\">\n     <file name=\"index.html\">\n       <script>\n         angular.module('numberFilterExample', [])\n           .controller('ExampleController', ['$scope', function($scope) {\n             $scope.val = 1234.56789;\n           }]);\n       </script>\n       <div ng-controller=\"ExampleController\">\n         Enter number: <input ng-model='val'><br>\n         Default formatting: <span id='number-default'>{{val | number}}</span><br>\n         No fractions: <span>{{val | number:0}}</span><br>\n         Negative number: <span>{{-val | number:4}}</span>\n       </div>\n     </file>\n     <file name=\"protractor.js\" type=\"protractor\">\n       it('should format numbers', function() {\n         expect(element(by.id('number-default')).getText()).toBe('1,234.568');\n         expect(element(by.binding('val | number:0')).getText()).toBe('1,235');\n         expect(element(by.binding('-val | number:4')).getText()).toBe('-1,234.5679');\n       });\n\n       it('should update', function() {\n         element(by.model('val')).clear();\n         element(by.model('val')).sendKeys('3374.333');\n         expect(element(by.id('number-default')).getText()).toBe('3,374.333');\n         expect(element(by.binding('val | number:0')).getText()).toBe('3,374');\n         expect(element(by.binding('-val | number:4')).getText()).toBe('-3,374.3330');\n      });\n     </file>\n   </example>\n */\n\n\nnumberFilter.$inject = ['$locale'];\nfunction numberFilter($locale) {\n  var formats = $locale.NUMBER_FORMATS;\n  return function(number, fractionSize) {\n\n    // if null or undefined pass it through\n    return (number == null)\n        ? number\n        : formatNumber(number, formats.PATTERNS[0], formats.GROUP_SEP, formats.DECIMAL_SEP,\n                       fractionSize);\n  };\n}\n\nvar DECIMAL_SEP = '.';\nfunction formatNumber(number, pattern, groupSep, decimalSep, fractionSize) {\n  if (!isFinite(number) || isObject(number)) return '';\n\n  var isNegative = number < 0;\n  number = Math.abs(number);\n  var numStr = number + '',\n      formatedText = '',\n      parts = [];\n\n  var hasExponent = false;\n  if (numStr.indexOf('e') !== -1) {\n    var match = numStr.match(/([\\d\\.]+)e(-?)(\\d+)/);\n    if (match && match[2] == '-' && match[3] > fractionSize + 1) {\n      number = 0;\n    } else {\n      formatedText = numStr;\n      hasExponent = true;\n    }\n  }\n\n  if (!hasExponent) {\n    var fractionLen = (numStr.split(DECIMAL_SEP)[1] || '').length;\n\n    // determine fractionSize if it is not specified\n    if (isUndefined(fractionSize)) {\n      fractionSize = Math.min(Math.max(pattern.minFrac, fractionLen), pattern.maxFrac);\n    }\n\n    // safely round numbers in JS without hitting imprecisions of floating-point arithmetics\n    // inspired by:\n    // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/round\n    number = +(Math.round(+(number.toString() + 'e' + fractionSize)).toString() + 'e' + -fractionSize);\n\n    var fraction = ('' + number).split(DECIMAL_SEP);\n    var whole = fraction[0];\n    fraction = fraction[1] || '';\n\n    var i, pos = 0,\n        lgroup = pattern.lgSize,\n        group = pattern.gSize;\n\n    if (whole.length >= (lgroup + group)) {\n      pos = whole.length - lgroup;\n      for (i = 0; i < pos; i++) {\n        if ((pos - i) % group === 0 && i !== 0) {\n          formatedText += groupSep;\n        }\n        formatedText += whole.charAt(i);\n      }\n    }\n\n    for (i = pos; i < whole.length; i++) {\n      if ((whole.length - i) % lgroup === 0 && i !== 0) {\n        formatedText += groupSep;\n      }\n      formatedText += whole.charAt(i);\n    }\n\n    // format fraction part.\n    while (fraction.length < fractionSize) {\n      fraction += '0';\n    }\n\n    if (fractionSize && fractionSize !== \"0\") formatedText += decimalSep + fraction.substr(0, fractionSize);\n  } else {\n    if (fractionSize > 0 && number < 1) {\n      formatedText = number.toFixed(fractionSize);\n      number = parseFloat(formatedText);\n    }\n  }\n\n  if (number === 0) {\n    isNegative = false;\n  }\n\n  parts.push(isNegative ? pattern.negPre : pattern.posPre,\n             formatedText,\n             isNegative ? pattern.negSuf : pattern.posSuf);\n  return parts.join('');\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\nfunction dateGetter(name, size, offset, trim) {\n  offset = offset || 0;\n  return function(date) {\n    var value = date['get' + name]();\n    if (offset > 0 || value > -offset)\n      value += offset;\n    if (value === 0 && offset == -12) value = 12;\n    return padNumber(value, size, trim);\n  };\n}\n\nfunction dateStrGetter(name, shortForm) {\n  return function(date, formats) {\n    var value = date['get' + name]();\n    var get = uppercase(shortForm ? ('SHORT' + name) : name);\n\n    return formats[get][value];\n  };\n}\n\nfunction timeZoneGetter(date) {\n  var zone = -1 * date.getTimezoneOffset();\n  var paddedZone = (zone >= 0) ? \"+\" : \"\";\n\n  paddedZone += padNumber(Math[zone > 0 ? 'floor' : 'ceil'](zone / 60), 2) +\n                padNumber(Math.abs(zone % 60), 2);\n\n  return paddedZone;\n}\n\nfunction getFirstThursdayOfYear(year) {\n    // 0 = index of January\n    var dayOfWeekOnFirst = (new Date(year, 0, 1)).getDay();\n    // 4 = index of Thursday (+1 to account for 1st = 5)\n    // 11 = index of *next* Thursday (+1 account for 1st = 12)\n    return new Date(year, 0, ((dayOfWeekOnFirst <= 4) ? 5 : 12) - dayOfWeekOnFirst);\n}\n\nfunction getThursdayThisWeek(datetime) {\n    return new Date(datetime.getFullYear(), datetime.getMonth(),\n      // 4 = index of Thursday\n      datetime.getDate() + (4 - datetime.getDay()));\n}\n\nfunction weekGetter(size) {\n   return function(date) {\n      var firstThurs = getFirstThursdayOfYear(date.getFullYear()),\n         thisThurs = getThursdayThisWeek(date);\n\n      var diff = +thisThurs - +firstThurs,\n         result = 1 + Math.round(diff / 6.048e8); // 6.048e8 ms per week\n\n      return padNumber(result, size);\n   };\n}\n\nfunction ampmGetter(date, formats) {\n  return date.getHours() < 12 ? formats.AMPMS[0] : formats.AMPMS[1];\n}\n\nvar DATE_FORMATS = {\n  yyyy: dateGetter('FullYear', 4),\n    yy: dateGetter('FullYear', 2, 0, true),\n     y: dateGetter('FullYear', 1),\n  MMMM: dateStrGetter('Month'),\n   MMM: dateStrGetter('Month', true),\n    MM: dateGetter('Month', 2, 1),\n     M: dateGetter('Month', 1, 1),\n    dd: dateGetter('Date', 2),\n     d: dateGetter('Date', 1),\n    HH: dateGetter('Hours', 2),\n     H: dateGetter('Hours', 1),\n    hh: dateGetter('Hours', 2, -12),\n     h: dateGetter('Hours', 1, -12),\n    mm: dateGetter('Minutes', 2),\n     m: dateGetter('Minutes', 1),\n    ss: dateGetter('Seconds', 2),\n     s: dateGetter('Seconds', 1),\n     // while ISO 8601 requires fractions to be prefixed with `.` or `,`\n     // we can be just safely rely on using `sss` since we currently don't support single or two digit fractions\n   sss: dateGetter('Milliseconds', 3),\n  EEEE: dateStrGetter('Day'),\n   EEE: dateStrGetter('Day', true),\n     a: ampmGetter,\n     Z: timeZoneGetter,\n    ww: weekGetter(2),\n     w: weekGetter(1)\n};\n\nvar DATE_FORMATS_SPLIT = /((?:[^yMdHhmsaZEw']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+|H+|h+|m+|s+|a|Z|w+))(.*)/,\n    NUMBER_STRING = /^\\-?\\d+$/;\n\n/**\n * @ngdoc filter\n * @name date\n * @kind function\n *\n * @description\n *   Formats `date` to a string based on the requested `format`.\n *\n *   `format` string can be composed of the following elements:\n *\n *   * `'yyyy'`: 4 digit representation of year (e.g. AD 1 => 0001, AD 2010 => 2010)\n *   * `'yy'`: 2 digit representation of year, padded (00-99). (e.g. AD 2001 => 01, AD 2010 => 10)\n *   * `'y'`: 1 digit representation of year, e.g. (AD 1 => 1, AD 199 => 199)\n *   * `'MMMM'`: Month in year (January-December)\n *   * `'MMM'`: Month in year (Jan-Dec)\n *   * `'MM'`: Month in year, padded (01-12)\n *   * `'M'`: Month in year (1-12)\n *   * `'dd'`: Day in month, padded (01-31)\n *   * `'d'`: Day in month (1-31)\n *   * `'EEEE'`: Day in Week,(Sunday-Saturday)\n *   * `'EEE'`: Day in Week, (Sun-Sat)\n *   * `'HH'`: Hour in day, padded (00-23)\n *   * `'H'`: Hour in day (0-23)\n *   * `'hh'`: Hour in AM/PM, padded (01-12)\n *   * `'h'`: Hour in AM/PM, (1-12)\n *   * `'mm'`: Minute in hour, padded (00-59)\n *   * `'m'`: Minute in hour (0-59)\n *   * `'ss'`: Second in minute, padded (00-59)\n *   * `'s'`: Second in minute (0-59)\n *   * `'sss'`: Millisecond in second, padded (000-999)\n *   * `'a'`: AM/PM marker\n *   * `'Z'`: 4 digit (+sign) representation of the timezone offset (-1200-+1200)\n *   * `'ww'`: Week of year, padded (00-53). Week 01 is the week with the first Thursday of the year\n *   * `'w'`: Week of year (0-53). Week 1 is the week with the first Thursday of the year\n *\n *   `format` string can also be one of the following predefined\n *   {@link guide/i18n localizable formats}:\n *\n *   * `'medium'`: equivalent to `'MMM d, y h:mm:ss a'` for en_US locale\n *     (e.g. Sep 3, 2010 12:05:08 PM)\n *   * `'short'`: equivalent to `'M/d/yy h:mm a'` for en_US  locale (e.g. 9/3/10 12:05 PM)\n *   * `'fullDate'`: equivalent to `'EEEE, MMMM d, y'` for en_US  locale\n *     (e.g. Friday, September 3, 2010)\n *   * `'longDate'`: equivalent to `'MMMM d, y'` for en_US  locale (e.g. September 3, 2010)\n *   * `'mediumDate'`: equivalent to `'MMM d, y'` for en_US  locale (e.g. Sep 3, 2010)\n *   * `'shortDate'`: equivalent to `'M/d/yy'` for en_US locale (e.g. 9/3/10)\n *   * `'mediumTime'`: equivalent to `'h:mm:ss a'` for en_US locale (e.g. 12:05:08 PM)\n *   * `'shortTime'`: equivalent to `'h:mm a'` for en_US locale (e.g. 12:05 PM)\n *\n *   `format` string can contain literal values. These need to be escaped by surrounding with single quotes (e.g.\n *   `\"h 'in the morning'\"`). In order to output a single quote, escape it - i.e., two single quotes in a sequence\n *   (e.g. `\"h 'o''clock'\"`).\n *\n * @param {(Date|number|string)} date Date to format either as Date object, milliseconds (string or\n *    number) or various ISO 8601 datetime string formats (e.g. yyyy-MM-ddTHH:mm:ss.sssZ and its\n *    shorter versions like yyyy-MM-ddTHH:mmZ, yyyy-MM-dd or yyyyMMddTHHmmssZ). If no timezone is\n *    specified in the string input, the time is considered to be in the local timezone.\n * @param {string=} format Formatting rules (see Description). If not specified,\n *    `mediumDate` is used.\n * @param {string=} timezone Timezone to be used for formatting. Right now, only `'UTC'` is supported.\n *    If not specified, the timezone of the browser will be used.\n * @returns {string} Formatted string or the input if input is not recognized as date/millis.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n       <span ng-non-bindable>{{1288323623006 | date:'medium'}}</span>:\n           <span>{{1288323623006 | date:'medium'}}</span><br>\n       <span ng-non-bindable>{{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}</span>:\n          <span>{{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}</span><br>\n       <span ng-non-bindable>{{1288323623006 | date:'MM/dd/yyyy @ h:mma'}}</span>:\n          <span>{{'1288323623006' | date:'MM/dd/yyyy @ h:mma'}}</span><br>\n       <span ng-non-bindable>{{1288323623006 | date:\"MM/dd/yyyy 'at' h:mma\"}}</span>:\n          <span>{{'1288323623006' | date:\"MM/dd/yyyy 'at' h:mma\"}}</span><br>\n     </file>\n     <file name=\"protractor.js\" type=\"protractor\">\n       it('should format date', function() {\n         expect(element(by.binding(\"1288323623006 | date:'medium'\")).getText()).\n            toMatch(/Oct 2\\d, 2010 \\d{1,2}:\\d{2}:\\d{2} (AM|PM)/);\n         expect(element(by.binding(\"1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'\")).getText()).\n            toMatch(/2010\\-10\\-2\\d \\d{2}:\\d{2}:\\d{2} (\\-|\\+)?\\d{4}/);\n         expect(element(by.binding(\"'1288323623006' | date:'MM/dd/yyyy @ h:mma'\")).getText()).\n            toMatch(/10\\/2\\d\\/2010 @ \\d{1,2}:\\d{2}(AM|PM)/);\n         expect(element(by.binding(\"'1288323623006' | date:\\\"MM/dd/yyyy 'at' h:mma\\\"\")).getText()).\n            toMatch(/10\\/2\\d\\/2010 at \\d{1,2}:\\d{2}(AM|PM)/);\n       });\n     </file>\n   </example>\n */\ndateFilter.$inject = ['$locale'];\nfunction dateFilter($locale) {\n\n\n  var R_ISO8601_STR = /^(\\d{4})-?(\\d\\d)-?(\\d\\d)(?:T(\\d\\d)(?::?(\\d\\d)(?::?(\\d\\d)(?:\\.(\\d+))?)?)?(Z|([+-])(\\d\\d):?(\\d\\d))?)?$/;\n                     // 1        2       3         4          5          6          7          8  9     10      11\n  function jsonStringToDate(string) {\n    var match;\n    if (match = string.match(R_ISO8601_STR)) {\n      var date = new Date(0),\n          tzHour = 0,\n          tzMin  = 0,\n          dateSetter = match[8] ? date.setUTCFullYear : date.setFullYear,\n          timeSetter = match[8] ? date.setUTCHours : date.setHours;\n\n      if (match[9]) {\n        tzHour = int(match[9] + match[10]);\n        tzMin = int(match[9] + match[11]);\n      }\n      dateSetter.call(date, int(match[1]), int(match[2]) - 1, int(match[3]));\n      var h = int(match[4] || 0) - tzHour;\n      var m = int(match[5] || 0) - tzMin;\n      var s = int(match[6] || 0);\n      var ms = Math.round(parseFloat('0.' + (match[7] || 0)) * 1000);\n      timeSetter.call(date, h, m, s, ms);\n      return date;\n    }\n    return string;\n  }\n\n\n  return function(date, format, timezone) {\n    var text = '',\n        parts = [],\n        fn, match;\n\n    format = format || 'mediumDate';\n    format = $locale.DATETIME_FORMATS[format] || format;\n    if (isString(date)) {\n      date = NUMBER_STRING.test(date) ? int(date) : jsonStringToDate(date);\n    }\n\n    if (isNumber(date)) {\n      date = new Date(date);\n    }\n\n    if (!isDate(date)) {\n      return date;\n    }\n\n    while (format) {\n      match = DATE_FORMATS_SPLIT.exec(format);\n      if (match) {\n        parts = concat(parts, match, 1);\n        format = parts.pop();\n      } else {\n        parts.push(format);\n        format = null;\n      }\n    }\n\n    if (timezone && timezone === 'UTC') {\n      date = new Date(date.getTime());\n      date.setMinutes(date.getMinutes() + date.getTimezoneOffset());\n    }\n    forEach(parts, function(value) {\n      fn = DATE_FORMATS[value];\n      text += fn ? fn(date, $locale.DATETIME_FORMATS)\n                 : value.replace(/(^'|'$)/g, '').replace(/''/g, \"'\");\n    });\n\n    return text;\n  };\n}\n\n\n/**\n * @ngdoc filter\n * @name json\n * @kind function\n *\n * @description\n *   Allows you to convert a JavaScript object into JSON string.\n *\n *   This filter is mostly useful for debugging. When using the double curly {{value}} notation\n *   the binding is automatically converted to JSON.\n *\n * @param {*} object Any JavaScript object (including arrays and primitive types) to filter.\n * @param {number=} spacing The number of spaces to use per indentation, defaults to 2.\n * @returns {string} JSON string.\n *\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n       <pre id=\"default-spacing\">{{ {'name':'value'} | json }}</pre>\n       <pre id=\"custom-spacing\">{{ {'name':'value'} | json:4 }}</pre>\n     </file>\n     <file name=\"protractor.js\" type=\"protractor\">\n       it('should jsonify filtered objects', function() {\n         expect(element(by.id('default-spacing')).getText()).toMatch(/\\{\\n  \"name\": ?\"value\"\\n}/);\n         expect(element(by.id('custom-spacing')).getText()).toMatch(/\\{\\n    \"name\": ?\"value\"\\n}/);\n       });\n     </file>\n   </example>\n *\n */\nfunction jsonFilter() {\n  return function(object, spacing) {\n    if (isUndefined(spacing)) {\n        spacing = 2;\n    }\n    return toJson(object, spacing);\n  };\n}\n\n\n/**\n * @ngdoc filter\n * @name lowercase\n * @kind function\n * @description\n * Converts string to lowercase.\n * @see angular.lowercase\n */\nvar lowercaseFilter = valueFn(lowercase);\n\n\n/**\n * @ngdoc filter\n * @name uppercase\n * @kind function\n * @description\n * Converts string to uppercase.\n * @see angular.uppercase\n */\nvar uppercaseFilter = valueFn(uppercase);\n\n/**\n * @ngdoc filter\n * @name limitTo\n * @kind function\n *\n * @description\n * Creates a new array or string containing only a specified number of elements. The elements\n * are taken from either the beginning or the end of the source array, string or number, as specified by\n * the value and sign (positive or negative) of `limit`. If a number is used as input, it is\n * converted to a string.\n *\n * @param {Array|string|number} input Source array, string or number to be limited.\n * @param {string|number} limit The length of the returned array or string. If the `limit` number\n *     is positive, `limit` number of items from the beginning of the source array/string are copied.\n *     If the number is negative, `limit` number  of items from the end of the source array/string\n *     are copied. The `limit` will be trimmed if it exceeds `array.length`\n * @returns {Array|string} A new sub-array or substring of length `limit` or less if input array\n *     had less than `limit` elements.\n *\n * @example\n   <example module=\"limitToExample\">\n     <file name=\"index.html\">\n       <script>\n         angular.module('limitToExample', [])\n           .controller('ExampleController', ['$scope', function($scope) {\n             $scope.numbers = [1,2,3,4,5,6,7,8,9];\n             $scope.letters = \"abcdefghi\";\n             $scope.longNumber = 2345432342;\n             $scope.numLimit = 3;\n             $scope.letterLimit = 3;\n             $scope.longNumberLimit = 3;\n           }]);\n       </script>\n       <div ng-controller=\"ExampleController\">\n         Limit {{numbers}} to: <input type=\"number\" step=\"1\" ng-model=\"numLimit\">\n         <p>Output numbers: {{ numbers | limitTo:numLimit }}</p>\n         Limit {{letters}} to: <input type=\"number\" step=\"1\" ng-model=\"letterLimit\">\n         <p>Output letters: {{ letters | limitTo:letterLimit }}</p>\n         Limit {{longNumber}} to: <input type=\"number\" step=\"1\" ng-model=\"longNumberLimit\">\n         <p>Output long number: {{ longNumber | limitTo:longNumberLimit }}</p>\n       </div>\n     </file>\n     <file name=\"protractor.js\" type=\"protractor\">\n       var numLimitInput = element(by.model('numLimit'));\n       var letterLimitInput = element(by.model('letterLimit'));\n       var longNumberLimitInput = element(by.model('longNumberLimit'));\n       var limitedNumbers = element(by.binding('numbers | limitTo:numLimit'));\n       var limitedLetters = element(by.binding('letters | limitTo:letterLimit'));\n       var limitedLongNumber = element(by.binding('longNumber | limitTo:longNumberLimit'));\n\n       it('should limit the number array to first three items', function() {\n         expect(numLimitInput.getAttribute('value')).toBe('3');\n         expect(letterLimitInput.getAttribute('value')).toBe('3');\n         expect(longNumberLimitInput.getAttribute('value')).toBe('3');\n         expect(limitedNumbers.getText()).toEqual('Output numbers: [1,2,3]');\n         expect(limitedLetters.getText()).toEqual('Output letters: abc');\n         expect(limitedLongNumber.getText()).toEqual('Output long number: 234');\n       });\n\n       // There is a bug in safari and protractor that doesn't like the minus key\n       // it('should update the output when -3 is entered', function() {\n       //   numLimitInput.clear();\n       //   numLimitInput.sendKeys('-3');\n       //   letterLimitInput.clear();\n       //   letterLimitInput.sendKeys('-3');\n       //   longNumberLimitInput.clear();\n       //   longNumberLimitInput.sendKeys('-3');\n       //   expect(limitedNumbers.getText()).toEqual('Output numbers: [7,8,9]');\n       //   expect(limitedLetters.getText()).toEqual('Output letters: ghi');\n       //   expect(limitedLongNumber.getText()).toEqual('Output long number: 342');\n       // });\n\n       it('should not exceed the maximum size of input array', function() {\n         numLimitInput.clear();\n         numLimitInput.sendKeys('100');\n         letterLimitInput.clear();\n         letterLimitInput.sendKeys('100');\n         longNumberLimitInput.clear();\n         longNumberLimitInput.sendKeys('100');\n         expect(limitedNumbers.getText()).toEqual('Output numbers: [1,2,3,4,5,6,7,8,9]');\n         expect(limitedLetters.getText()).toEqual('Output letters: abcdefghi');\n         expect(limitedLongNumber.getText()).toEqual('Output long number: 2345432342');\n       });\n     </file>\n   </example>\n*/\nfunction limitToFilter() {\n  return function(input, limit) {\n    if (isNumber(input)) input = input.toString();\n    if (!isArray(input) && !isString(input)) return input;\n\n    if (Math.abs(Number(limit)) === Infinity) {\n      limit = Number(limit);\n    } else {\n      limit = int(limit);\n    }\n\n    //NaN check on limit\n    if (limit) {\n      return limit > 0 ? input.slice(0, limit) : input.slice(limit);\n    } else {\n      return isString(input) ? \"\" : [];\n    }\n  };\n}\n\n/**\n * @ngdoc filter\n * @name orderBy\n * @kind function\n *\n * @description\n * Orders a specified `array` by the `expression` predicate. It is ordered alphabetically\n * for strings and numerically for numbers. Note: if you notice numbers are not being sorted\n * correctly, make sure they are actually being saved as numbers and not strings.\n *\n * @param {Array} array The array to sort.\n * @param {function(*)|string|Array.<(function(*)|string)>=} expression A predicate to be\n *    used by the comparator to determine the order of elements.\n *\n *    Can be one of:\n *\n *    - `function`: Getter function. The result of this function will be sorted using the\n *      `<`, `=`, `>` operator.\n *    - `string`: An Angular expression. The result of this expression is used to compare elements\n *      (for example `name` to sort by a property called `name` or `name.substr(0, 3)` to sort by\n *      3 first characters of a property called `name`). The result of a constant expression\n *      is interpreted as a property name to be used in comparisons (for example `\"special name\"`\n *      to sort object by the value of their `special name` property). An expression can be\n *      optionally prefixed with `+` or `-` to control ascending or descending sort order\n *      (for example, `+name` or `-name`). If no property is provided, (e.g. `'+'`) then the array\n *      element itself is used to compare where sorting.\n *    - `Array`: An array of function or string predicates. The first predicate in the array\n *      is used for sorting, but when two items are equivalent, the next predicate is used.\n *\n *    If the predicate is missing or empty then it defaults to `'+'`.\n *\n * @param {boolean=} reverse Reverse the order of the array.\n * @returns {Array} Sorted copy of the source array.\n *\n * @example\n   <example module=\"orderByExample\">\n     <file name=\"index.html\">\n       <script>\n         angular.module('orderByExample', [])\n           .controller('ExampleController', ['$scope', function($scope) {\n             $scope.friends =\n                 [{name:'John', phone:'555-1212', age:10},\n                  {name:'Mary', phone:'555-9876', age:19},\n                  {name:'Mike', phone:'555-4321', age:21},\n                  {name:'Adam', phone:'555-5678', age:35},\n                  {name:'Julie', phone:'555-8765', age:29}];\n             $scope.predicate = '-age';\n           }]);\n       </script>\n       <div ng-controller=\"ExampleController\">\n         <pre>Sorting predicate = {{predicate}}; reverse = {{reverse}}</pre>\n         <hr/>\n         [ <a href=\"\" ng-click=\"predicate=''\">unsorted</a> ]\n         <table class=\"friend\">\n           <tr>\n             <th><a href=\"\" ng-click=\"predicate = 'name'; reverse=false\">Name</a>\n                 (<a href=\"\" ng-click=\"predicate = '-name'; reverse=false\">^</a>)</th>\n             <th><a href=\"\" ng-click=\"predicate = 'phone'; reverse=!reverse\">Phone Number</a></th>\n             <th><a href=\"\" ng-click=\"predicate = 'age'; reverse=!reverse\">Age</a></th>\n           </tr>\n           <tr ng-repeat=\"friend in friends | orderBy:predicate:reverse\">\n             <td>{{friend.name}}</td>\n             <td>{{friend.phone}}</td>\n             <td>{{friend.age}}</td>\n           </tr>\n         </table>\n       </div>\n     </file>\n   </example>\n *\n * It's also possible to call the orderBy filter manually, by injecting `$filter`, retrieving the\n * filter routine with `$filter('orderBy')`, and calling the returned filter routine with the\n * desired parameters.\n *\n * Example:\n *\n * @example\n  <example module=\"orderByExample\">\n    <file name=\"index.html\">\n      <div ng-controller=\"ExampleController\">\n        <table class=\"friend\">\n          <tr>\n            <th><a href=\"\" ng-click=\"reverse=false;order('name', false)\">Name</a>\n              (<a href=\"\" ng-click=\"order('-name',false)\">^</a>)</th>\n            <th><a href=\"\" ng-click=\"reverse=!reverse;order('phone', reverse)\">Phone Number</a></th>\n            <th><a href=\"\" ng-click=\"reverse=!reverse;order('age',reverse)\">Age</a></th>\n          </tr>\n          <tr ng-repeat=\"friend in friends\">\n            <td>{{friend.name}}</td>\n            <td>{{friend.phone}}</td>\n            <td>{{friend.age}}</td>\n          </tr>\n        </table>\n      </div>\n    </file>\n\n    <file name=\"script.js\">\n      angular.module('orderByExample', [])\n        .controller('ExampleController', ['$scope', '$filter', function($scope, $filter) {\n          var orderBy = $filter('orderBy');\n          $scope.friends = [\n            { name: 'John',    phone: '555-1212',    age: 10 },\n            { name: 'Mary',    phone: '555-9876',    age: 19 },\n            { name: 'Mike',    phone: '555-4321',    age: 21 },\n            { name: 'Adam',    phone: '555-5678',    age: 35 },\n            { name: 'Julie',   phone: '555-8765',    age: 29 }\n          ];\n          $scope.order = function(predicate, reverse) {\n            $scope.friends = orderBy($scope.friends, predicate, reverse);\n          };\n          $scope.order('-age',false);\n        }]);\n    </file>\n</example>\n */\norderByFilter.$inject = ['$parse'];\nfunction orderByFilter($parse) {\n  return function(array, sortPredicate, reverseOrder) {\n    if (!(isArrayLike(array))) return array;\n    sortPredicate = isArray(sortPredicate) ? sortPredicate : [sortPredicate];\n    if (sortPredicate.length === 0) { sortPredicate = ['+']; }\n    sortPredicate = sortPredicate.map(function(predicate) {\n      var descending = false, get = predicate || identity;\n      if (isString(predicate)) {\n        if ((predicate.charAt(0) == '+' || predicate.charAt(0) == '-')) {\n          descending = predicate.charAt(0) == '-';\n          predicate = predicate.substring(1);\n        }\n        if (predicate === '') {\n          // Effectively no predicate was passed so we compare identity\n          return reverseComparator(compare, descending);\n        }\n        get = $parse(predicate);\n        if (get.constant) {\n          var key = get();\n          return reverseComparator(function(a, b) {\n            return compare(a[key], b[key]);\n          }, descending);\n        }\n      }\n      return reverseComparator(function(a, b) {\n        return compare(get(a),get(b));\n      }, descending);\n    });\n    return slice.call(array).sort(reverseComparator(comparator, reverseOrder));\n\n    function comparator(o1, o2) {\n      for (var i = 0; i < sortPredicate.length; i++) {\n        var comp = sortPredicate[i](o1, o2);\n        if (comp !== 0) return comp;\n      }\n      return 0;\n    }\n    function reverseComparator(comp, descending) {\n      return descending\n          ? function(a, b) {return comp(b,a);}\n          : comp;\n    }\n\n    function isPrimitive(value) {\n      switch (typeof value) {\n        case 'number': /* falls through */\n        case 'boolean': /* falls through */\n        case 'string':\n          return true;\n        default:\n          return false;\n      }\n    }\n\n    function objectToString(value) {\n      if (value === null) return 'null';\n      if (typeof value.valueOf === 'function') {\n        value = value.valueOf();\n        if (isPrimitive(value)) return value;\n      }\n      if (typeof value.toString === 'function') {\n        value = value.toString();\n        if (isPrimitive(value)) return value;\n      }\n      return '';\n    }\n\n    function compare(v1, v2) {\n      var t1 = typeof v1;\n      var t2 = typeof v2;\n      if (t1 === t2 && t1 === \"object\") {\n        v1 = objectToString(v1);\n        v2 = objectToString(v2);\n      }\n      if (t1 === t2) {\n        if (t1 === \"string\") {\n           v1 = v1.toLowerCase();\n           v2 = v2.toLowerCase();\n        }\n        if (v1 === v2) return 0;\n        return v1 < v2 ? -1 : 1;\n      } else {\n        return t1 < t2 ? -1 : 1;\n      }\n    }\n  };\n}\n\nfunction ngDirective(directive) {\n  if (isFunction(directive)) {\n    directive = {\n      link: directive\n    };\n  }\n  directive.restrict = directive.restrict || 'AC';\n  return valueFn(directive);\n}\n\n/**\n * @ngdoc directive\n * @name a\n * @restrict E\n *\n * @description\n * Modifies the default behavior of the html A tag so that the default action is prevented when\n * the href attribute is empty.\n *\n * This change permits the easy creation of action links with the `ngClick` directive\n * without changing the location or causing page reloads, e.g.:\n * `<a href=\"\" ng-click=\"list.addItem()\">Add Item</a>`\n */\nvar htmlAnchorDirective = valueFn({\n  restrict: 'E',\n  compile: function(element, attr) {\n    if (!attr.href && !attr.xlinkHref && !attr.name) {\n      return function(scope, element) {\n        // If the linked element is not an anchor tag anymore, do nothing\n        if (element[0].nodeName.toLowerCase() !== 'a') return;\n\n        // SVGAElement does not use the href attribute, but rather the 'xlinkHref' attribute.\n        var href = toString.call(element.prop('href')) === '[object SVGAnimatedString]' ?\n                   'xlink:href' : 'href';\n        element.on('click', function(event) {\n          // if we have no href url, then don't navigate anywhere.\n          if (!element.attr(href)) {\n            event.preventDefault();\n          }\n        });\n      };\n    }\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ngHref\n * @restrict A\n * @priority 99\n *\n * @description\n * Using Angular markup like `{{hash}}` in an href attribute will\n * make the link go to the wrong URL if the user clicks it before\n * Angular has a chance to replace the `{{hash}}` markup with its\n * value. Until Angular replaces the markup the link will be broken\n * and will most likely return a 404 error. The `ngHref` directive\n * solves this problem.\n *\n * The wrong way to write it:\n * ```html\n * <a href=\"http://www.gravatar.com/avatar/{{hash}}\">link1</a>\n * ```\n *\n * The correct way to write it:\n * ```html\n * <a ng-href=\"http://www.gravatar.com/avatar/{{hash}}\">link1</a>\n * ```\n *\n * @element A\n * @param {template} ngHref any string which can contain `{{}}` markup.\n *\n * @example\n * This example shows various combinations of `href`, `ng-href` and `ng-click` attributes\n * in links and their different behaviors:\n    <example>\n      <file name=\"index.html\">\n        <input ng-model=\"value\" /><br />\n        <a id=\"link-1\" href ng-click=\"value = 1\">link 1</a> (link, don't reload)<br />\n        <a id=\"link-2\" href=\"\" ng-click=\"value = 2\">link 2</a> (link, don't reload)<br />\n        <a id=\"link-3\" ng-href=\"/{{'123'}}\">link 3</a> (link, reload!)<br />\n        <a id=\"link-4\" href=\"\" name=\"xx\" ng-click=\"value = 4\">anchor</a> (link, don't reload)<br />\n        <a id=\"link-5\" name=\"xxx\" ng-click=\"value = 5\">anchor</a> (no link)<br />\n        <a id=\"link-6\" ng-href=\"{{value}}\">link</a> (link, change location)\n      </file>\n      <file name=\"protractor.js\" type=\"protractor\">\n        it('should execute ng-click but not reload when href without value', function() {\n          element(by.id('link-1')).click();\n          expect(element(by.model('value')).getAttribute('value')).toEqual('1');\n          expect(element(by.id('link-1')).getAttribute('href')).toBe('');\n        });\n\n        it('should execute ng-click but not reload when href empty string', function() {\n          element(by.id('link-2')).click();\n          expect(element(by.model('value')).getAttribute('value')).toEqual('2');\n          expect(element(by.id('link-2')).getAttribute('href')).toBe('');\n        });\n\n        it('should execute ng-click and change url when ng-href specified', function() {\n          expect(element(by.id('link-3')).getAttribute('href')).toMatch(/\\/123$/);\n\n          element(by.id('link-3')).click();\n\n          // At this point, we navigate away from an Angular page, so we need\n          // to use browser.driver to get the base webdriver.\n\n          browser.wait(function() {\n            return browser.driver.getCurrentUrl().then(function(url) {\n              return url.match(/\\/123$/);\n            });\n          }, 5000, 'page should navigate to /123');\n        });\n\n        xit('should execute ng-click but not reload when href empty string and name specified', function() {\n          element(by.id('link-4')).click();\n          expect(element(by.model('value')).getAttribute('value')).toEqual('4');\n          expect(element(by.id('link-4')).getAttribute('href')).toBe('');\n        });\n\n        it('should execute ng-click but not reload when no href but name specified', function() {\n          element(by.id('link-5')).click();\n          expect(element(by.model('value')).getAttribute('value')).toEqual('5');\n          expect(element(by.id('link-5')).getAttribute('href')).toBe(null);\n        });\n\n        it('should only change url when only ng-href', function() {\n          element(by.model('value')).clear();\n          element(by.model('value')).sendKeys('6');\n          expect(element(by.id('link-6')).getAttribute('href')).toMatch(/\\/6$/);\n\n          element(by.id('link-6')).click();\n\n          // At this point, we navigate away from an Angular page, so we need\n          // to use browser.driver to get the base webdriver.\n          browser.wait(function() {\n            return browser.driver.getCurrentUrl().then(function(url) {\n              return url.match(/\\/6$/);\n            });\n          }, 5000, 'page should navigate to /6');\n        });\n      </file>\n    </example>\n */\n\n/**\n * @ngdoc directive\n * @name ngSrc\n * @restrict A\n * @priority 99\n *\n * @description\n * Using Angular markup like `{{hash}}` in a `src` attribute doesn't\n * work right: The browser will fetch from the URL with the literal\n * text `{{hash}}` until Angular replaces the expression inside\n * `{{hash}}`. The `ngSrc` directive solves this problem.\n *\n * The buggy way to write it:\n * ```html\n * <img src=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * ```\n *\n * The correct way to write it:\n * ```html\n * <img ng-src=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * ```\n *\n * @element IMG\n * @param {template} ngSrc any string which can contain `{{}}` markup.\n */\n\n/**\n * @ngdoc directive\n * @name ngSrcset\n * @restrict A\n * @priority 99\n *\n * @description\n * Using Angular markup like `{{hash}}` in a `srcset` attribute doesn't\n * work right: The browser will fetch from the URL with the literal\n * text `{{hash}}` until Angular replaces the expression inside\n * `{{hash}}`. The `ngSrcset` directive solves this problem.\n *\n * The buggy way to write it:\n * ```html\n * <img srcset=\"http://www.gravatar.com/avatar/{{hash}} 2x\"/>\n * ```\n *\n * The correct way to write it:\n * ```html\n * <img ng-srcset=\"http://www.gravatar.com/avatar/{{hash}} 2x\"/>\n * ```\n *\n * @element IMG\n * @param {template} ngSrcset any string which can contain `{{}}` markup.\n */\n\n/**\n * @ngdoc directive\n * @name ngDisabled\n * @restrict A\n * @priority 100\n *\n * @description\n *\n * We shouldn't do this, because it will make the button enabled on Chrome/Firefox but not on IE8 and older IEs:\n * ```html\n * <div ng-init=\"scope = { isDisabled: false }\">\n *  <button disabled=\"{{scope.isDisabled}}\">Disabled</button>\n * </div>\n * ```\n *\n * The HTML specification does not require browsers to preserve the values of boolean attributes\n * such as disabled. (Their presence means true and their absence means false.)\n * If we put an Angular interpolation expression into such an attribute then the\n * binding information would be lost when the browser removes the attribute.\n * The `ngDisabled` directive solves this problem for the `disabled` attribute.\n * This complementary directive is not removed by the browser and so provides\n * a permanent reliable place to store the binding information.\n *\n * @example\n    <example>\n      <file name=\"index.html\">\n        Click me to toggle: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        <button ng-model=\"button\" ng-disabled=\"checked\">Button</button>\n      </file>\n      <file name=\"protractor.js\" type=\"protractor\">\n        it('should toggle button', function() {\n          expect(element(by.css('button')).getAttribute('disabled')).toBeFalsy();\n          element(by.model('checked')).click();\n          expect(element(by.css('button')).getAttribute('disabled')).toBeTruthy();\n        });\n      </file>\n    </example>\n *\n * @element INPUT\n * @param {expression} ngDisabled If the {@link guide/expression expression} is truthy,\n *     then special attribute \"disabled\" will be set on the element\n */\n\n\n/**\n * @ngdoc directive\n * @name ngChecked\n * @restrict A\n * @priority 100\n *\n * @description\n * The HTML specification does not require browsers to preserve the values of boolean attributes\n * such as checked. (Their presence means true and their absence means false.)\n * If we put an Angular interpolation expression into such an attribute then the\n * binding information would be lost when the browser removes the attribute.\n * The `ngChecked` directive solves this problem for the `checked` attribute.\n * This complementary directive is not removed by the browser and so provides\n * a permanent reliable place to store the binding information.\n * @example\n    <example>\n      <file name=\"index.html\">\n        Check me to check both: <input type=\"checkbox\" ng-model=\"master\"><br/>\n        <input id=\"checkSlave\" type=\"checkbox\" ng-checked=\"master\">\n      </file>\n      <file name=\"protractor.js\" type=\"protractor\">\n        it('should check both checkBoxes', function() {\n          expect(element(by.id('checkSlave')).getAttribute('checked')).toBeFalsy();\n          element(by.model('master')).click();\n          expect(element(by.id('checkSlave')).getAttribute('checked')).toBeTruthy();\n        });\n      </file>\n    </example>\n *\n * @element INPUT\n * @param {expression} ngChecked If the {@link guide/expression expression} is truthy,\n *     then special attribute \"checked\" will be set on the element\n */\n\n\n/**\n * @ngdoc directive\n * @name ngReadonly\n * @restrict A\n * @priority 100\n *\n * @description\n * The HTML specification does not require browsers to preserve the values of boolean attributes\n * such as readonly. (Their presence means true and their absence means false.)\n * If we put an Angular interpolation expression into such an attribute then the\n * binding information would be lost when the browser removes the attribute.\n * The `ngReadonly` directive solves this problem for the `readonly` attribute.\n * This complementary directive is not removed by the browser and so provides\n * a permanent reliable place to store the binding information.\n * @example\n    <example>\n      <file name=\"index.html\">\n        Check me to make text readonly: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        <input type=\"text\" ng-readonly=\"checked\" value=\"I'm Angular\"/>\n      </file>\n      <file name=\"protractor.js\" type=\"protractor\">\n        it('should toggle readonly attr', function() {\n          expect(element(by.css('[type=\"text\"]')).getAttribute('readonly')).toBeFalsy();\n          element(by.model('checked')).click();\n          expect(element(by.css('[type=\"text\"]')).getAttribute('readonly')).toBeTruthy();\n        });\n      </file>\n    </example>\n *\n * @element INPUT\n * @param {expression} ngReadonly If the {@link guide/expression expression} is truthy,\n *     then special attribute \"readonly\" will be set on the element\n */\n\n\n/**\n * @ngdoc directive\n * @name ngSelected\n * @restrict A\n * @priority 100\n *\n * @description\n * The HTML specification does not require browsers to preserve the values of boolean attributes\n * such as selected. (Their presence means true and their absence means false.)\n * If we put an Angular interpolation expression into such an attribute then the\n * binding information would be lost when the browser removes the attribute.\n * The `ngSelected` directive solves this problem for the `selected` attribute.\n * This complementary directive is not removed by the browser and so provides\n * a permanent reliable place to store the binding information.\n *\n * @example\n    <example>\n      <file name=\"index.html\">\n        Check me to select: <input type=\"checkbox\" ng-model=\"selected\"><br/>\n        <select>\n          <option>Hello!</option>\n          <option id=\"greet\" ng-selected=\"selected\">Greetings!</option>\n        </select>\n      </file>\n      <file name=\"protractor.js\" type=\"protractor\">\n        it('should select Greetings!', function() {\n          expect(element(by.id('greet')).getAttribute('selected')).toBeFalsy();\n          element(by.model('selected')).click();\n          expect(element(by.id('greet')).getAttribute('selected')).toBeTruthy();\n        });\n      </file>\n    </example>\n *\n * @element OPTION\n * @param {expression} ngSelected If the {@link guide/expression expression} is truthy,\n *     then special attribute \"selected\" will be set on the element\n */\n\n/**\n * @ngdoc directive\n * @name ngOpen\n * @restrict A\n * @priority 100\n *\n * @description\n * The HTML specification does not require browsers to preserve the values of boolean attributes\n * such as open. (Their presence means true and their absence means false.)\n * If we put an Angular interpolation expression into such an attribute then the\n * binding information would be lost when the browser removes the attribute.\n * The `ngOpen` directive solves this problem for the `open` attribute.\n * This complementary directive is not removed by the browser and so provides\n * a permanent reliable place to store the binding information.\n * @example\n     <example>\n       <file name=\"index.html\">\n         Check me check multiple: <input type=\"checkbox\" ng-model=\"open\"><br/>\n         <details id=\"details\" ng-open=\"open\">\n            <summary>Show/Hide me</summary>\n         </details>\n       </file>\n       <file name=\"protractor.js\" type=\"protractor\">\n         it('should toggle open', function() {\n           expect(element(by.id('details')).getAttribute('open')).toBeFalsy();\n           element(by.model('open')).click();\n           expect(element(by.id('details')).getAttribute('open')).toBeTruthy();\n         });\n       </file>\n     </example>\n *\n * @element DETAILS\n * @param {expression} ngOpen If the {@link guide/expression expression} is truthy,\n *     then special attribute \"open\" will be set on the element\n */\n\nvar ngAttributeAliasDirectives = {};\n\n\n// boolean attrs are evaluated\nforEach(BOOLEAN_ATTR, function(propName, attrName) {\n  // binding to multiple is not supported\n  if (propName == \"multiple\") return;\n\n  var normalized = directiveNormalize('ng-' + attrName);\n  ngAttributeAliasDirectives[normalized] = function() {\n    return {\n      restrict: 'A',\n      priority: 100,\n      link: function(scope, element, attr) {\n        scope.$watch(attr[normalized], function ngBooleanAttrWatchAction(value) {\n          attr.$set(attrName, !!value);\n        });\n      }\n    };\n  };\n});\n\n// aliased input attrs are evaluated\nforEach(ALIASED_ATTR, function(htmlAttr, ngAttr) {\n  ngAttributeAliasDirectives[ngAttr] = function() {\n    return {\n      priority: 100,\n      link: function(scope, element, attr) {\n        //special case ngPattern when a literal regular expression value\n        //is used as the expression (this way we don't have to watch anything).\n        if (ngAttr === \"ngPattern\" && attr.ngPattern.charAt(0) == \"/\") {\n          var match = attr.ngPattern.match(REGEX_STRING_REGEXP);\n          if (match) {\n            attr.$set(\"ngPattern\", new RegExp(match[1], match[2]));\n            return;\n          }\n        }\n\n        scope.$watch(attr[ngAttr], function ngAttrAliasWatchAction(value) {\n          attr.$set(ngAttr, value);\n        });\n      }\n    };\n  };\n});\n\n// ng-src, ng-srcset, ng-href are interpolated\nforEach(['src', 'srcset', 'href'], function(attrName) {\n  var normalized = directiveNormalize('ng-' + attrName);\n  ngAttributeAliasDirectives[normalized] = function() {\n    return {\n      priority: 99, // it needs to run after the attributes are interpolated\n      link: function(scope, element, attr) {\n        var propName = attrName,\n            name = attrName;\n\n        if (attrName === 'href' &&\n            toString.call(element.prop('href')) === '[object SVGAnimatedString]') {\n          name = 'xlinkHref';\n          attr.$attr[name] = 'xlink:href';\n          propName = null;\n        }\n\n        attr.$observe(normalized, function(value) {\n          if (!value) {\n            if (attrName === 'href') {\n              attr.$set(name, null);\n            }\n            return;\n          }\n\n          attr.$set(name, value);\n\n          // on IE, if \"ng:src\" directive declaration is used and \"src\" attribute doesn't exist\n          // then calling element.setAttribute('src', 'foo') doesn't do anything, so we need\n          // to set the property as well to achieve the desired effect.\n          // we use attr[attrName] value since $set can sanitize the url.\n          if (msie && propName) element.prop(propName, attr[name]);\n        });\n      }\n    };\n  };\n});\n\n/* global -nullFormCtrl, -SUBMITTED_CLASS, addSetValidityMethod: true\n */\nvar nullFormCtrl = {\n  $addControl: noop,\n  $$renameControl: nullFormRenameControl,\n  $removeControl: noop,\n  $setValidity: noop,\n  $setDirty: noop,\n  $setPristine: noop,\n  $setSubmitted: noop\n},\nSUBMITTED_CLASS = 'ng-submitted';\n\nfunction nullFormRenameControl(control, name) {\n  control.$name = name;\n}\n\n/**\n * @ngdoc type\n * @name form.FormController\n *\n * @property {boolean} $pristine True if user has not interacted with the form yet.\n * @property {boolean} $dirty True if user has already interacted with the form.\n * @property {boolean} $valid True if all of the containing forms and controls are valid.\n * @property {boolean} $invalid True if at least one containing control or form is invalid.\n * @property {boolean} $submitted True if user has submitted the form even if its invalid.\n *\n * @property {Object} $error Is an object hash, containing references to controls or\n *  forms with failing validators, where:\n *\n *  - keys are validation tokens (error names),\n *  - values are arrays of controls or forms that have a failing validator for given error name.\n *\n *  Built-in validation tokens:\n *\n *  - `email`\n *  - `max`\n *  - `maxlength`\n *  - `min`\n *  - `minlength`\n *  - `number`\n *  - `pattern`\n *  - `required`\n *  - `url`\n *  - `date`\n *  - `datetimelocal`\n *  - `time`\n *  - `week`\n *  - `month`\n *\n * @description\n * `FormController` keeps track of all its controls and nested forms as well as the state of them,\n * such as being valid/invalid or dirty/pristine.\n *\n * Each {@link ng.directive:form form} directive creates an instance\n * of `FormController`.\n *\n */\n//asks for $scope to fool the BC controller module\nFormController.$inject = ['$element', '$attrs', '$scope', '$animate', '$interpolate'];\nfunction FormController(element, attrs, $scope, $animate, $interpolate) {\n  var form = this,\n      controls = [];\n\n  var parentForm = form.$$parentForm = element.parent().controller('form') || nullFormCtrl;\n\n  // init state\n  form.$error = {};\n  form.$$success = {};\n  form.$pending = undefined;\n  form.$name = $interpolate(attrs.name || attrs.ngForm || '')($scope);\n  form.$dirty = false;\n  form.$pristine = true;\n  form.$valid = true;\n  form.$invalid = false;\n  form.$submitted = false;\n\n  parentForm.$addControl(form);\n\n  /**\n   * @ngdoc method\n   * @name form.FormController#$rollbackViewValue\n   *\n   * @description\n   * Rollback all form controls pending updates to the `$modelValue`.\n   *\n   * Updates may be pending by a debounced event or because the input is waiting for a some future\n   * event defined in `ng-model-options`. This method is typically needed by the reset button of\n   * a form that uses `ng-model-options` to pend updates.\n   */\n  form.$rollbackViewValue = function() {\n    forEach(controls, function(control) {\n      control.$rollbackViewValue();\n    });\n  };\n\n  /**\n   * @ngdoc method\n   * @name form.FormController#$commitViewValue\n   *\n   * @description\n   * Commit all form controls pending updates to the `$modelValue`.\n   *\n   * Updates may be pending by a debounced event or because the input is waiting for a some future\n   * event defined in `ng-model-options`. This method is rarely needed as `NgModelController`\n   * usually handles calling this in response to input events.\n   */\n  form.$commitViewValue = function() {\n    forEach(controls, function(control) {\n      control.$commitViewValue();\n    });\n  };\n\n  /**\n   * @ngdoc method\n   * @name form.FormController#$addControl\n   *\n   * @description\n   * Register a control with the form.\n   *\n   * Input elements using ngModelController do this automatically when they are linked.\n   */\n  form.$addControl = function(control) {\n    // Breaking change - before, inputs whose name was \"hasOwnProperty\" were quietly ignored\n    // and not added to the scope.  Now we throw an error.\n    assertNotHasOwnProperty(control.$name, 'input');\n    controls.push(control);\n\n    if (control.$name) {\n      form[control.$name] = control;\n    }\n  };\n\n  // Private API: rename a form control\n  form.$$renameControl = function(control, newName) {\n    var oldName = control.$name;\n\n    if (form[oldName] === control) {\n      delete form[oldName];\n    }\n    form[newName] = control;\n    control.$name = newName;\n  };\n\n  /**\n   * @ngdoc method\n   * @name form.FormController#$removeControl\n   *\n   * @description\n   * Deregister a control from the form.\n   *\n   * Input elements using ngModelController do this automatically when they are destroyed.\n   */\n  form.$removeControl = function(control) {\n    if (control.$name && form[control.$name] === control) {\n      delete form[control.$name];\n    }\n    forEach(form.$pending, function(value, name) {\n      form.$setValidity(name, null, control);\n    });\n    forEach(form.$error, function(value, name) {\n      form.$setValidity(name, null, control);\n    });\n    forEach(form.$$success, function(value, name) {\n      form.$setValidity(name, null, control);\n    });\n\n    arrayRemove(controls, control);\n  };\n\n\n  /**\n   * @ngdoc method\n   * @name form.FormController#$setValidity\n   *\n   * @description\n   * Sets the validity of a form control.\n   *\n   * This method will also propagate to parent forms.\n   */\n  addSetValidityMethod({\n    ctrl: this,\n    $element: element,\n    set: function(object, property, controller) {\n      var list = object[property];\n      if (!list) {\n        object[property] = [controller];\n      } else {\n        var index = list.indexOf(controller);\n        if (index === -1) {\n          list.push(controller);\n        }\n      }\n    },\n    unset: function(object, property, controller) {\n      var list = object[property];\n      if (!list) {\n        return;\n      }\n      arrayRemove(list, controller);\n      if (list.length === 0) {\n        delete object[property];\n      }\n    },\n    parentForm: parentForm,\n    $animate: $animate\n  });\n\n  /**\n   * @ngdoc method\n   * @name form.FormController#$setDirty\n   *\n   * @description\n   * Sets the form to a dirty state.\n   *\n   * This method can be called to add the 'ng-dirty' class and set the form to a dirty\n   * state (ng-dirty class). This method will also propagate to parent forms.\n   */\n  form.$setDirty = function() {\n    $animate.removeClass(element, PRISTINE_CLASS);\n    $animate.addClass(element, DIRTY_CLASS);\n    form.$dirty = true;\n    form.$pristine = false;\n    parentForm.$setDirty();\n  };\n\n  /**\n   * @ngdoc method\n   * @name form.FormController#$setPristine\n   *\n   * @description\n   * Sets the form to its pristine state.\n   *\n   * This method can be called to remove the 'ng-dirty' class and set the form to its pristine\n   * state (ng-pristine class). This method will also propagate to all the controls contained\n   * in this form.\n   *\n   * Setting a form back to a pristine state is often useful when we want to 'reuse' a form after\n   * saving or resetting it.\n   */\n  form.$setPristine = function() {\n    $animate.setClass(element, PRISTINE_CLASS, DIRTY_CLASS + ' ' + SUBMITTED_CLASS);\n    form.$dirty = false;\n    form.$pristine = true;\n    form.$submitted = false;\n    forEach(controls, function(control) {\n      control.$setPristine();\n    });\n  };\n\n  /**\n   * @ngdoc method\n   * @name form.FormController#$setUntouched\n   *\n   * @description\n   * Sets the form to its untouched state.\n   *\n   * This method can be called to remove the 'ng-touched' class and set the form controls to their\n   * untouched state (ng-untouched class).\n   *\n   * Setting a form controls back to their untouched state is often useful when setting the form\n   * back to its pristine state.\n   */\n  form.$setUntouched = function() {\n    forEach(controls, function(control) {\n      control.$setUntouched();\n    });\n  };\n\n  /**\n   * @ngdoc method\n   * @name form.FormController#$setSubmitted\n   *\n   * @description\n   * Sets the form to its submitted state.\n   */\n  form.$setSubmitted = function() {\n    $animate.addClass(element, SUBMITTED_CLASS);\n    form.$submitted = true;\n    parentForm.$setSubmitted();\n  };\n}\n\n/**\n * @ngdoc directive\n * @name ngForm\n * @restrict EAC\n *\n * @description\n * Nestable alias of {@link ng.directive:form `form`} directive. HTML\n * does not allow nesting of form elements. It is useful to nest forms, for example if the validity of a\n * sub-group of controls needs to be determined.\n *\n * Note: the purpose of `ngForm` is to group controls,\n * but not to be a replacement for the `<form>` tag with all of its capabilities\n * (e.g. posting to the server, ...).\n *\n * @param {string=} ngForm|name Name of the form. If specified, the form controller will be published into\n *                       related scope, under this name.\n *\n */\n\n /**\n * @ngdoc directive\n * @name form\n * @restrict E\n *\n * @description\n * Directive that instantiates\n * {@link form.FormController FormController}.\n *\n * If the `name` attribute is specified, the form controller is published onto the current scope under\n * this name.\n *\n * # Alias: {@link ng.directive:ngForm `ngForm`}\n *\n * In Angular forms can be nested. This means that the outer form is valid when all of the child\n * forms are valid as well. However, browsers do not allow nesting of `<form>` elements, so\n * Angular provides the {@link ng.directive:ngForm `ngForm`} directive which behaves identically to\n * `<form>` but can be nested.  This allows you to have nested forms, which is very useful when\n * using Angular validation directives in forms that are dynamically generated using the\n * {@link ng.directive:ngRepeat `ngRepeat`} directive. Since you cannot dynamically generate the `name`\n * attribute of input elements using interpolation, you have to wrap each set of repeated inputs in an\n * `ngForm` directive and nest these in an outer `form` element.\n *\n *\n * # CSS classes\n *  - `ng-valid` is set if the form is valid.\n *  - `ng-invalid` is set if the form is invalid.\n *  - `ng-pristine` is set if the form is pristine.\n *  - `ng-dirty` is set if the form is dirty.\n *  - `ng-submitted` is set if the form was submitted.\n *\n * Keep in mind that ngAnimate can detect each of these classes when added and removed.\n *\n *\n * # Submitting a form and preventing the default action\n *\n * Since the role of forms in client-side Angular applications is different than in classical\n * roundtrip apps, it is desirable for the browser not to translate the form submission into a full\n * page reload that sends the data to the server. Instead some javascript logic should be triggered\n * to handle the form submission in an application-specific way.\n *\n * For this reason, Angular prevents the default action (form submission to the server) unless the\n * `<form>` element has an `action` attribute specified.\n *\n * You can use one of the following two ways to specify what javascript method should be called when\n * a form is submitted:\n *\n * - {@link ng.directive:ngSubmit ngSubmit} directive on the form element\n * - {@link ng.directive:ngClick ngClick} directive on the first\n  *  button or input field of type submit (input[type=submit])\n *\n * To prevent double execution of the handler, use only one of the {@link ng.directive:ngSubmit ngSubmit}\n * or {@link ng.directive:ngClick ngClick} directives.\n * This is because of the following form submission rules in the HTML specification:\n *\n * - If a form has only one input field then hitting enter in this field triggers form submit\n * (`ngSubmit`)\n * - if a form has 2+ input fields and no buttons or input[type=submit] then hitting enter\n * doesn't trigger submit\n * - if a form has one or more input fields and one or more buttons or input[type=submit] then\n * hitting enter in any of the input fields will trigger the click handler on the *first* button or\n * input[type=submit] (`ngClick`) *and* a submit handler on the enclosing form (`ngSubmit`)\n *\n * Any pending `ngModelOptions` changes will take place immediately when an enclosing form is\n * submitted. Note that `ngClick` events will occur before the model is updated. Use `ngSubmit`\n * to have access to the updated model.\n *\n * ## Animation Hooks\n *\n * Animations in ngForm are triggered when any of the associated CSS classes are added and removed.\n * These classes are: `.ng-pristine`, `.ng-dirty`, `.ng-invalid` and `.ng-valid` as well as any\n * other validations that are performed within the form. Animations in ngForm are similar to how\n * they work in ngClass and animations can be hooked into using CSS transitions, keyframes as well\n * as JS animations.\n *\n * The following example shows a simple way to utilize CSS transitions to style a form element\n * that has been rendered as invalid after it has been validated:\n *\n * <pre>\n * //be sure to include ngAnimate as a module to hook into more\n * //advanced animations\n * .my-form {\n *   transition:0.5s linear all;\n *   background: white;\n * }\n * .my-form.ng-invalid {\n *   background: red;\n *   color:white;\n * }\n * </pre>\n *\n * @example\n    <example deps=\"angular-animate.js\" animations=\"true\" fixBase=\"true\" module=\"formExample\">\n      <file name=\"index.html\">\n       <script>\n         angular.module('formExample', [])\n           .controller('FormController', ['$scope', function($scope) {\n             $scope.userType = 'guest';\n           }]);\n       </script>\n       <style>\n        .my-form {\n          -webkit-transition:all linear 0.5s;\n          transition:all linear 0.5s;\n          background: transparent;\n        }\n        .my-form.ng-invalid {\n          background: red;\n        }\n       </style>\n       <form name=\"myForm\" ng-controller=\"FormController\" class=\"my-form\">\n         userType: <input name=\"input\" ng-model=\"userType\" required>\n         <span class=\"error\" ng-show=\"myForm.input.$error.required\">Required!</span><br>\n         <tt>userType = {{userType}}</tt><br>\n         <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br>\n         <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br>\n        </form>\n      </file>\n      <file name=\"protractor.js\" type=\"protractor\">\n        it('should initialize to model', function() {\n          var userType = element(by.binding('userType'));\n          var valid = element(by.binding('myForm.input.$valid'));\n\n          expect(userType.getText()).toContain('guest');\n          expect(valid.getText()).toContain('true');\n        });\n\n        it('should be invalid if empty', function() {\n          var userType = element(by.binding('userType'));\n          var valid = element(by.binding('myForm.input.$valid'));\n          var userInput = element(by.model('userType'));\n\n          userInput.clear();\n          userInput.sendKeys('');\n\n          expect(userType.getText()).toEqual('userType =');\n          expect(valid.getText()).toContain('false');\n        });\n      </file>\n    </example>\n *\n * @param {string=} name Name of the form. If specified, the form controller will be published into\n *                       related scope, under this name.\n */\nvar formDirectiveFactory = function(isNgForm) {\n  return ['$timeout', function($timeout) {\n    var formDirective = {\n      name: 'form',\n      restrict: isNgForm ? 'EAC' : 'E',\n      controller: FormController,\n      compile: function ngFormCompile(formElement) {\n        // Setup initial state of the control\n        formElement.addClass(PRISTINE_CLASS).addClass(VALID_CLASS);\n\n        return {\n          pre: function ngFormPreLink(scope, formElement, attr, controller) {\n            // if `action` attr is not present on the form, prevent the default action (submission)\n            if (!('action' in attr)) {\n              // we can't use jq events because if a form is destroyed during submission the default\n              // action is not prevented. see #1238\n              //\n              // IE 9 is not affected because it doesn't fire a submit event and try to do a full\n              // page reload if the form was destroyed by submission of the form via a click handler\n              // on a button in the form. Looks like an IE9 specific bug.\n              var handleFormSubmission = function(event) {\n                scope.$apply(function() {\n                  controller.$commitViewValue();\n                  controller.$setSubmitted();\n                });\n\n                event.preventDefault();\n              };\n\n              addEventListenerFn(formElement[0], 'submit', handleFormSubmission);\n\n              // unregister the preventDefault listener so that we don't not leak memory but in a\n              // way that will achieve the prevention of the default action.\n              formElement.on('$destroy', function() {\n                $timeout(function() {\n                  removeEventListenerFn(formElement[0], 'submit', handleFormSubmission);\n                }, 0, false);\n              });\n            }\n\n            var parentFormCtrl = controller.$$parentForm,\n                alias = controller.$name;\n\n            if (alias) {\n              setter(scope, null, alias, controller, alias);\n              attr.$observe(attr.name ? 'name' : 'ngForm', function(newValue) {\n                if (alias === newValue) return;\n                setter(scope, null, alias, undefined, alias);\n                alias = newValue;\n                setter(scope, null, alias, controller, alias);\n                parentFormCtrl.$$renameControl(controller, alias);\n              });\n            }\n            formElement.on('$destroy', function() {\n              parentFormCtrl.$removeControl(controller);\n              if (alias) {\n                setter(scope, null, alias, undefined, alias);\n              }\n              extend(controller, nullFormCtrl); //stop propagating child destruction handlers upwards\n            });\n          }\n        };\n      }\n    };\n\n    return formDirective;\n  }];\n};\n\nvar formDirective = formDirectiveFactory();\nvar ngFormDirective = formDirectiveFactory(true);\n\n/* global VALID_CLASS: false,\n  INVALID_CLASS: false,\n  PRISTINE_CLASS: false,\n  DIRTY_CLASS: false,\n  UNTOUCHED_CLASS: false,\n  TOUCHED_CLASS: false,\n  $ngModelMinErr: false,\n*/\n\n// Regex code is obtained from SO: https://stackoverflow.com/questions/3143070/javascript-regex-iso-datetime#answer-3143231\nvar ISO_DATE_REGEXP = /\\d{4}-[01]\\d-[0-3]\\dT[0-2]\\d:[0-5]\\d:[0-5]\\d\\.\\d+([+-][0-2]\\d:[0-5]\\d|Z)/;\nvar URL_REGEXP = /^(ftp|http|https):\\/\\/(\\w+:{0,1}\\w*@)?(\\S+)(:[0-9]+)?(\\/|\\/([\\w#!:.?+=&%@!\\-\\/]))?$/;\nvar EMAIL_REGEXP = /^[a-z0-9!#$%&'*+\\/=?^_`{|}~.-]+@[a-z0-9]([a-z0-9-]*[a-z0-9])?(\\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)*$/i;\nvar NUMBER_REGEXP = /^\\s*(\\-|\\+)?(\\d+|(\\d*(\\.\\d*)))\\s*$/;\nvar DATE_REGEXP = /^(\\d{4})-(\\d{2})-(\\d{2})$/;\nvar DATETIMELOCAL_REGEXP = /^(\\d{4})-(\\d\\d)-(\\d\\d)T(\\d\\d):(\\d\\d)(?::(\\d\\d)(\\.\\d{1,3})?)?$/;\nvar WEEK_REGEXP = /^(\\d{4})-W(\\d\\d)$/;\nvar MONTH_REGEXP = /^(\\d{4})-(\\d\\d)$/;\nvar TIME_REGEXP = /^(\\d\\d):(\\d\\d)(?::(\\d\\d)(\\.\\d{1,3})?)?$/;\n\nvar inputType = {\n\n  /**\n   * @ngdoc input\n   * @name input[text]\n   *\n   * @description\n   * Standard HTML text input with angular data binding, inherited by most of the `input` elements.\n   *\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Adds `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength. Setting the attribute to a negative or non-numeric value, allows view values of\n   *    any length.\n   * @param {string=} pattern Similar to `ngPattern` except that the attribute value is the actual string\n   *    that contains the regular expression body that will be converted to a regular expression\n   *    as in the ngPattern directive.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the ngModel value does not match\n   *    a RegExp found by evaluating the Angular expression given in the attribute value.\n   *    If the expression evaluates to a RegExp object then this is used directly.\n   *    If the expression is a string then it will be converted to a RegExp after wrapping it in `^` and `$`\n   *    characters. For instance, `\"abc\"` will be converted to `new RegExp('^abc$')`.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   * @param {boolean=} [ngTrim=true] If set to false Angular will not automatically trim the input.\n   *    This parameter is ignored for input[type=password] controls, which will never trim the\n   *    input.\n   *\n   * @example\n      <example name=\"text-input-directive\" module=\"textInputExample\">\n        <file name=\"index.html\">\n         <script>\n           angular.module('textInputExample', [])\n             .controller('ExampleController', ['$scope', function($scope) {\n               $scope.example = {\n                 text: 'guest',\n                 word: /^\\s*\\w*\\s*$/\n               };\n             }]);\n         </script>\n         <form name=\"myForm\" ng-controller=\"ExampleController\">\n           Single word: <input type=\"text\" name=\"input\" ng-model=\"example.text\"\n                               ng-pattern=\"example.word\" required ng-trim=\"false\">\n           <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.input.$error.pattern\">\n             Single word only!</span>\n\n           <tt>text = {{example.text}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n          </form>\n        </file>\n        <file name=\"protractor.js\" type=\"protractor\">\n          var text = element(by.binding('example.text'));\n          var valid = element(by.binding('myForm.input.$valid'));\n          var input = element(by.model('example.text'));\n\n          it('should initialize to model', function() {\n            expect(text.getText()).toContain('guest');\n            expect(valid.getText()).toContain('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input.clear();\n            input.sendKeys('');\n\n            expect(text.getText()).toEqual('text =');\n            expect(valid.getText()).toContain('false');\n          });\n\n          it('should be invalid if multi word', function() {\n            input.clear();\n            input.sendKeys('hello world');\n\n            expect(valid.getText()).toContain('false');\n          });\n        </file>\n      </example>\n   */\n  'text': textInputType,\n\n    /**\n     * @ngdoc input\n     * @name input[date]\n     *\n     * @description\n     * Input with date validation and transformation. In browsers that do not yet support\n     * the HTML5 date input, a text element will be used. In that case, text must be entered in a valid ISO-8601\n     * date format (yyyy-MM-dd), for example: `2009-01-06`. Since many\n     * modern browsers do not yet support this input type, it is important to provide cues to users on the\n     * expected input format via a placeholder or label.\n     *\n     * The model must always be a Date object, otherwise Angular will throw an error.\n     * Invalid `Date` objects (dates whose `getTime()` is `NaN`) will be rendered as an empty string.\n     *\n     * The timezone to be used to read/write the `Date` instance in the model can be defined using\n     * {@link ng.directive:ngModelOptions ngModelOptions}. By default, this is the timezone of the browser.\n     *\n     * @param {string} ngModel Assignable angular expression to data-bind to.\n     * @param {string=} name Property name of the form under which the control is published.\n     * @param {string=} min Sets the `min` validation error key if the value entered is less than `min`. This must be a\n     * valid ISO date string (yyyy-MM-dd).\n     * @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`. This must be\n     * a valid ISO date string (yyyy-MM-dd).\n     * @param {string=} required Sets `required` validation error key if the value is not entered.\n     * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n     *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n     *    `required` when you want to data-bind to the `required` attribute.\n     * @param {string=} ngChange Angular expression to be executed when input changes due to user\n     *    interaction with the input element.\n     *\n     * @example\n     <example name=\"date-input-directive\" module=\"dateInputExample\">\n     <file name=\"index.html\">\n       <script>\n          angular.module('dateInputExample', [])\n            .controller('DateController', ['$scope', function($scope) {\n              $scope.example = {\n                value: new Date(2013, 9, 22)\n              };\n            }]);\n       </script>\n       <form name=\"myForm\" ng-controller=\"DateController as dateCtrl\">\n          Pick a date in 2013:\n          <input type=\"date\" id=\"exampleInput\" name=\"input\" ng-model=\"example.value\"\n              placeholder=\"yyyy-MM-dd\" min=\"2013-01-01\" max=\"2013-12-31\" required />\n          <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n              Required!</span>\n          <span class=\"error\" ng-show=\"myForm.input.$error.date\">\n              Not a valid date!</span>\n           <tt>value = {{example.value | date: \"yyyy-MM-dd\"}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n       </form>\n     </file>\n     <file name=\"protractor.js\" type=\"protractor\">\n        var value = element(by.binding('example.value | date: \"yyyy-MM-dd\"'));\n        var valid = element(by.binding('myForm.input.$valid'));\n        var input = element(by.model('example.value'));\n\n        // currently protractor/webdriver does not support\n        // sending keys to all known HTML5 input controls\n        // for various browsers (see https://github.com/angular/protractor/issues/562).\n        function setInput(val) {\n          // set the value of the element and force validation.\n          var scr = \"var ipt = document.getElementById('exampleInput'); \" +\n          \"ipt.value = '\" + val + \"';\" +\n          \"angular.element(ipt).scope().$apply(function(s) { s.myForm[ipt.name].$setViewValue('\" + val + \"'); });\";\n          browser.executeScript(scr);\n        }\n\n        it('should initialize to model', function() {\n          expect(value.getText()).toContain('2013-10-22');\n          expect(valid.getText()).toContain('myForm.input.$valid = true');\n        });\n\n        it('should be invalid if empty', function() {\n          setInput('');\n          expect(value.getText()).toEqual('value =');\n          expect(valid.getText()).toContain('myForm.input.$valid = false');\n        });\n\n        it('should be invalid if over max', function() {\n          setInput('2015-01-01');\n          expect(value.getText()).toContain('');\n          expect(valid.getText()).toContain('myForm.input.$valid = false');\n        });\n     </file>\n     </example>\n     */\n  'date': createDateInputType('date', DATE_REGEXP,\n         createDateParser(DATE_REGEXP, ['yyyy', 'MM', 'dd']),\n         'yyyy-MM-dd'),\n\n   /**\n    * @ngdoc input\n    * @name input[datetime-local]\n    *\n    * @description\n    * Input with datetime validation and transformation. In browsers that do not yet support\n    * the HTML5 date input, a text element will be used. In that case, the text must be entered in a valid ISO-8601\n    * local datetime format (yyyy-MM-ddTHH:mm:ss), for example: `2010-12-28T14:57:00`.\n    *\n    * The model must always be a Date object, otherwise Angular will throw an error.\n    * Invalid `Date` objects (dates whose `getTime()` is `NaN`) will be rendered as an empty string.\n    *\n    * The timezone to be used to read/write the `Date` instance in the model can be defined using\n    * {@link ng.directive:ngModelOptions ngModelOptions}. By default, this is the timezone of the browser.\n    *\n    * @param {string} ngModel Assignable angular expression to data-bind to.\n    * @param {string=} name Property name of the form under which the control is published.\n    * @param {string=} min Sets the `min` validation error key if the value entered is less than `min`. This must be a\n    * valid ISO datetime format (yyyy-MM-ddTHH:mm:ss).\n    * @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`. This must be\n    * a valid ISO datetime format (yyyy-MM-ddTHH:mm:ss).\n    * @param {string=} required Sets `required` validation error key if the value is not entered.\n    * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n    *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n    *    `required` when you want to data-bind to the `required` attribute.\n    * @param {string=} ngChange Angular expression to be executed when input changes due to user\n    *    interaction with the input element.\n    *\n    * @example\n    <example name=\"datetimelocal-input-directive\" module=\"dateExample\">\n    <file name=\"index.html\">\n      <script>\n        angular.module('dateExample', [])\n          .controller('DateController', ['$scope', function($scope) {\n            $scope.example = {\n              value: new Date(2010, 11, 28, 14, 57)\n            };\n          }]);\n      </script>\n      <form name=\"myForm\" ng-controller=\"DateController as dateCtrl\">\n        Pick a date between in 2013:\n        <input type=\"datetime-local\" id=\"exampleInput\" name=\"input\" ng-model=\"example.value\"\n            placeholder=\"yyyy-MM-ddTHH:mm:ss\" min=\"2001-01-01T00:00:00\" max=\"2013-12-31T00:00:00\" required />\n        <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n            Required!</span>\n        <span class=\"error\" ng-show=\"myForm.input.$error.datetimelocal\">\n            Not a valid date!</span>\n        <tt>value = {{example.value | date: \"yyyy-MM-ddTHH:mm:ss\"}}</tt><br/>\n        <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n        <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n        <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n        <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n      </form>\n    </file>\n    <file name=\"protractor.js\" type=\"protractor\">\n      var value = element(by.binding('example.value | date: \"yyyy-MM-ddTHH:mm:ss\"'));\n      var valid = element(by.binding('myForm.input.$valid'));\n      var input = element(by.model('example.value'));\n\n      // currently protractor/webdriver does not support\n      // sending keys to all known HTML5 input controls\n      // for various browsers (https://github.com/angular/protractor/issues/562).\n      function setInput(val) {\n        // set the value of the element and force validation.\n        var scr = \"var ipt = document.getElementById('exampleInput'); \" +\n        \"ipt.value = '\" + val + \"';\" +\n        \"angular.element(ipt).scope().$apply(function(s) { s.myForm[ipt.name].$setViewValue('\" + val + \"'); });\";\n        browser.executeScript(scr);\n      }\n\n      it('should initialize to model', function() {\n        expect(value.getText()).toContain('2010-12-28T14:57:00');\n        expect(valid.getText()).toContain('myForm.input.$valid = true');\n      });\n\n      it('should be invalid if empty', function() {\n        setInput('');\n        expect(value.getText()).toEqual('value =');\n        expect(valid.getText()).toContain('myForm.input.$valid = false');\n      });\n\n      it('should be invalid if over max', function() {\n        setInput('2015-01-01T23:59:00');\n        expect(value.getText()).toContain('');\n        expect(valid.getText()).toContain('myForm.input.$valid = false');\n      });\n    </file>\n    </example>\n    */\n  'datetime-local': createDateInputType('datetimelocal', DATETIMELOCAL_REGEXP,\n      createDateParser(DATETIMELOCAL_REGEXP, ['yyyy', 'MM', 'dd', 'HH', 'mm', 'ss', 'sss']),\n      'yyyy-MM-ddTHH:mm:ss.sss'),\n\n  /**\n   * @ngdoc input\n   * @name input[time]\n   *\n   * @description\n   * Input with time validation and transformation. In browsers that do not yet support\n   * the HTML5 date input, a text element will be used. In that case, the text must be entered in a valid ISO-8601\n   * local time format (HH:mm:ss), for example: `14:57:00`. Model must be a Date object. This binding will always output a\n   * Date object to the model of January 1, 1970, or local date `new Date(1970, 0, 1, HH, mm, ss)`.\n   *\n   * The model must always be a Date object, otherwise Angular will throw an error.\n   * Invalid `Date` objects (dates whose `getTime()` is `NaN`) will be rendered as an empty string.\n   *\n   * The timezone to be used to read/write the `Date` instance in the model can be defined using\n   * {@link ng.directive:ngModelOptions ngModelOptions}. By default, this is the timezone of the browser.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} min Sets the `min` validation error key if the value entered is less than `min`. This must be a\n   * valid ISO time format (HH:mm:ss).\n   * @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`. This must be a\n   * valid ISO time format (HH:mm:ss).\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n   <example name=\"time-input-directive\" module=\"timeExample\">\n   <file name=\"index.html\">\n     <script>\n      angular.module('timeExample', [])\n        .controller('DateController', ['$scope', function($scope) {\n          $scope.example = {\n            value: new Date(1970, 0, 1, 14, 57, 0)\n          };\n        }]);\n     </script>\n     <form name=\"myForm\" ng-controller=\"DateController as dateCtrl\">\n        Pick a between 8am and 5pm:\n        <input type=\"time\" id=\"exampleInput\" name=\"input\" ng-model=\"example.value\"\n            placeholder=\"HH:mm:ss\" min=\"08:00:00\" max=\"17:00:00\" required />\n        <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n            Required!</span>\n        <span class=\"error\" ng-show=\"myForm.input.$error.time\">\n            Not a valid date!</span>\n        <tt>value = {{example.value | date: \"HH:mm:ss\"}}</tt><br/>\n        <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n        <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n        <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n        <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n     </form>\n   </file>\n   <file name=\"protractor.js\" type=\"protractor\">\n      var value = element(by.binding('example.value | date: \"HH:mm:ss\"'));\n      var valid = element(by.binding('myForm.input.$valid'));\n      var input = element(by.model('example.value'));\n\n      // currently protractor/webdriver does not support\n      // sending keys to all known HTML5 input controls\n      // for various browsers (https://github.com/angular/protractor/issues/562).\n      function setInput(val) {\n        // set the value of the element and force validation.\n        var scr = \"var ipt = document.getElementById('exampleInput'); \" +\n        \"ipt.value = '\" + val + \"';\" +\n        \"angular.element(ipt).scope().$apply(function(s) { s.myForm[ipt.name].$setViewValue('\" + val + \"'); });\";\n        browser.executeScript(scr);\n      }\n\n      it('should initialize to model', function() {\n        expect(value.getText()).toContain('14:57:00');\n        expect(valid.getText()).toContain('myForm.input.$valid = true');\n      });\n\n      it('should be invalid if empty', function() {\n        setInput('');\n        expect(value.getText()).toEqual('value =');\n        expect(valid.getText()).toContain('myForm.input.$valid = false');\n      });\n\n      it('should be invalid if over max', function() {\n        setInput('23:59:00');\n        expect(value.getText()).toContain('');\n        expect(valid.getText()).toContain('myForm.input.$valid = false');\n      });\n   </file>\n   </example>\n   */\n  'time': createDateInputType('time', TIME_REGEXP,\n      createDateParser(TIME_REGEXP, ['HH', 'mm', 'ss', 'sss']),\n     'HH:mm:ss.sss'),\n\n   /**\n    * @ngdoc input\n    * @name input[week]\n    *\n    * @description\n    * Input with week-of-the-year validation and transformation to Date. In browsers that do not yet support\n    * the HTML5 week input, a text element will be used. In that case, the text must be entered in a valid ISO-8601\n    * week format (yyyy-W##), for example: `2013-W02`.\n    *\n    * The model must always be a Date object, otherwise Angular will throw an error.\n    * Invalid `Date` objects (dates whose `getTime()` is `NaN`) will be rendered as an empty string.\n    *\n    * The timezone to be used to read/write the `Date` instance in the model can be defined using\n    * {@link ng.directive:ngModelOptions ngModelOptions}. By default, this is the timezone of the browser.\n    *\n    * @param {string} ngModel Assignable angular expression to data-bind to.\n    * @param {string=} name Property name of the form under which the control is published.\n    * @param {string=} min Sets the `min` validation error key if the value entered is less than `min`. This must be a\n    * valid ISO week format (yyyy-W##).\n    * @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`. This must be\n    * a valid ISO week format (yyyy-W##).\n    * @param {string=} required Sets `required` validation error key if the value is not entered.\n    * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n    *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n    *    `required` when you want to data-bind to the `required` attribute.\n    * @param {string=} ngChange Angular expression to be executed when input changes due to user\n    *    interaction with the input element.\n    *\n    * @example\n    <example name=\"week-input-directive\" module=\"weekExample\">\n    <file name=\"index.html\">\n      <script>\n      angular.module('weekExample', [])\n        .controller('DateController', ['$scope', function($scope) {\n          $scope.example = {\n            value: new Date(2013, 0, 3)\n          };\n        }]);\n      </script>\n      <form name=\"myForm\" ng-controller=\"DateController as dateCtrl\">\n        Pick a date between in 2013:\n        <input id=\"exampleInput\" type=\"week\" name=\"input\" ng-model=\"example.value\"\n            placeholder=\"YYYY-W##\" min=\"2012-W32\" max=\"2013-W52\" required />\n        <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n            Required!</span>\n        <span class=\"error\" ng-show=\"myForm.input.$error.week\">\n            Not a valid date!</span>\n        <tt>value = {{example.value | date: \"yyyy-Www\"}}</tt><br/>\n        <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n        <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n        <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n        <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n      </form>\n    </file>\n    <file name=\"protractor.js\" type=\"protractor\">\n      var value = element(by.binding('example.value | date: \"yyyy-Www\"'));\n      var valid = element(by.binding('myForm.input.$valid'));\n      var input = element(by.model('example.value'));\n\n      // currently protractor/webdriver does not support\n      // sending keys to all known HTML5 input controls\n      // for various browsers (https://github.com/angular/protractor/issues/562).\n      function setInput(val) {\n        // set the value of the element and force validation.\n        var scr = \"var ipt = document.getElementById('exampleInput'); \" +\n        \"ipt.value = '\" + val + \"';\" +\n        \"angular.element(ipt).scope().$apply(function(s) { s.myForm[ipt.name].$setViewValue('\" + val + \"'); });\";\n        browser.executeScript(scr);\n      }\n\n      it('should initialize to model', function() {\n        expect(value.getText()).toContain('2013-W01');\n        expect(valid.getText()).toContain('myForm.input.$valid = true');\n      });\n\n      it('should be invalid if empty', function() {\n        setInput('');\n        expect(value.getText()).toEqual('value =');\n        expect(valid.getText()).toContain('myForm.input.$valid = false');\n      });\n\n      it('should be invalid if over max', function() {\n        setInput('2015-W01');\n        expect(value.getText()).toContain('');\n        expect(valid.getText()).toContain('myForm.input.$valid = false');\n      });\n    </file>\n    </example>\n    */\n  'week': createDateInputType('week', WEEK_REGEXP, weekParser, 'yyyy-Www'),\n\n  /**\n   * @ngdoc input\n   * @name input[month]\n   *\n   * @description\n   * Input with month validation and transformation. In browsers that do not yet support\n   * the HTML5 month input, a text element will be used. In that case, the text must be entered in a valid ISO-8601\n   * month format (yyyy-MM), for example: `2009-01`.\n   *\n   * The model must always be a Date object, otherwise Angular will throw an error.\n   * Invalid `Date` objects (dates whose `getTime()` is `NaN`) will be rendered as an empty string.\n   * If the model is not set to the first of the month, the next view to model update will set it\n   * to the first of the month.\n   *\n   * The timezone to be used to read/write the `Date` instance in the model can be defined using\n   * {@link ng.directive:ngModelOptions ngModelOptions}. By default, this is the timezone of the browser.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} min Sets the `min` validation error key if the value entered is less than `min`. This must be\n   * a valid ISO month format (yyyy-MM).\n   * @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`. This must\n   * be a valid ISO month format (yyyy-MM).\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n   <example name=\"month-input-directive\" module=\"monthExample\">\n   <file name=\"index.html\">\n     <script>\n      angular.module('monthExample', [])\n        .controller('DateController', ['$scope', function($scope) {\n          $scope.example = {\n            value: new Date(2013, 9, 1)\n          };\n        }]);\n     </script>\n     <form name=\"myForm\" ng-controller=\"DateController as dateCtrl\">\n       Pick a month in 2013:\n       <input id=\"exampleInput\" type=\"month\" name=\"input\" ng-model=\"example.value\"\n          placeholder=\"yyyy-MM\" min=\"2013-01\" max=\"2013-12\" required />\n       <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n          Required!</span>\n       <span class=\"error\" ng-show=\"myForm.input.$error.month\">\n          Not a valid month!</span>\n       <tt>value = {{example.value | date: \"yyyy-MM\"}}</tt><br/>\n       <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n       <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n       <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n       <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n     </form>\n   </file>\n   <file name=\"protractor.js\" type=\"protractor\">\n      var value = element(by.binding('example.value | date: \"yyyy-MM\"'));\n      var valid = element(by.binding('myForm.input.$valid'));\n      var input = element(by.model('example.value'));\n\n      // currently protractor/webdriver does not support\n      // sending keys to all known HTML5 input controls\n      // for various browsers (https://github.com/angular/protractor/issues/562).\n      function setInput(val) {\n        // set the value of the element and force validation.\n        var scr = \"var ipt = document.getElementById('exampleInput'); \" +\n        \"ipt.value = '\" + val + \"';\" +\n        \"angular.element(ipt).scope().$apply(function(s) { s.myForm[ipt.name].$setViewValue('\" + val + \"'); });\";\n        browser.executeScript(scr);\n      }\n\n      it('should initialize to model', function() {\n        expect(value.getText()).toContain('2013-10');\n        expect(valid.getText()).toContain('myForm.input.$valid = true');\n      });\n\n      it('should be invalid if empty', function() {\n        setInput('');\n        expect(value.getText()).toEqual('value =');\n        expect(valid.getText()).toContain('myForm.input.$valid = false');\n      });\n\n      it('should be invalid if over max', function() {\n        setInput('2015-01');\n        expect(value.getText()).toContain('');\n        expect(valid.getText()).toContain('myForm.input.$valid = false');\n      });\n   </file>\n   </example>\n   */\n  'month': createDateInputType('month', MONTH_REGEXP,\n     createDateParser(MONTH_REGEXP, ['yyyy', 'MM']),\n     'yyyy-MM'),\n\n  /**\n   * @ngdoc input\n   * @name input[number]\n   *\n   * @description\n   * Text input with number validation and transformation. Sets the `number` validation\n   * error if not a valid number.\n   *\n   * The model must always be a number, otherwise Angular will throw an error.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} min Sets the `min` validation error key if the value entered is less than `min`.\n   * @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength. Setting the attribute to a negative or non-numeric value, allows view values of\n   *    any length.\n   * @param {string=} pattern Similar to `ngPattern` except that the attribute value is the actual string\n   *    that contains the regular expression body that will be converted to a regular expression\n   *    as in the ngPattern directive.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the ngModel value does not match\n   *    a RegExp found by evaluating the Angular expression given in the attribute value.\n   *    If the expression evaluates to a RegExp object then this is used directly.\n   *    If the expression is a string then it will be converted to a RegExp after wrapping it in `^` and `$`\n   *    characters. For instance, `\"abc\"` will be converted to `new RegExp('^abc$')`.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <example name=\"number-input-directive\" module=\"numberExample\">\n        <file name=\"index.html\">\n         <script>\n           angular.module('numberExample', [])\n             .controller('ExampleController', ['$scope', function($scope) {\n               $scope.example = {\n                 value: 12\n               };\n             }]);\n         </script>\n         <form name=\"myForm\" ng-controller=\"ExampleController\">\n           Number: <input type=\"number\" name=\"input\" ng-model=\"example.value\"\n                          min=\"0\" max=\"99\" required>\n           <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.input.$error.number\">\n             Not valid number!</span>\n           <tt>value = {{example.value}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n          </form>\n        </file>\n        <file name=\"protractor.js\" type=\"protractor\">\n          var value = element(by.binding('example.value'));\n          var valid = element(by.binding('myForm.input.$valid'));\n          var input = element(by.model('example.value'));\n\n          it('should initialize to model', function() {\n            expect(value.getText()).toContain('12');\n            expect(valid.getText()).toContain('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input.clear();\n            input.sendKeys('');\n            expect(value.getText()).toEqual('value =');\n            expect(valid.getText()).toContain('false');\n          });\n\n          it('should be invalid if over max', function() {\n            input.clear();\n            input.sendKeys('123');\n            expect(value.getText()).toEqual('value =');\n            expect(valid.getText()).toContain('false');\n          });\n        </file>\n      </example>\n   */\n  'number': numberInputType,\n\n\n  /**\n   * @ngdoc input\n   * @name input[url]\n   *\n   * @description\n   * Text input with URL validation. Sets the `url` validation error key if the content is not a\n   * valid URL.\n   *\n   * <div class=\"alert alert-warning\">\n   * **Note:** `input[url]` uses a regex to validate urls that is derived from the regex\n   * used in Chromium. If you need stricter validation, you can use `ng-pattern` or modify\n   * the built-in validators (see the {@link guide/forms Forms guide})\n   * </div>\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength. Setting the attribute to a negative or non-numeric value, allows view values of\n   *    any length.\n   * @param {string=} pattern Similar to `ngPattern` except that the attribute value is the actual string\n   *    that contains the regular expression body that will be converted to a regular expression\n   *    as in the ngPattern directive.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the ngModel value does not match\n   *    a RegExp found by evaluating the Angular expression given in the attribute value.\n   *    If the expression evaluates to a RegExp object then this is used directly.\n   *    If the expression is a string then it will be converted to a RegExp after wrapping it in `^` and `$`\n   *    characters. For instance, `\"abc\"` will be converted to `new RegExp('^abc$')`.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <example name=\"url-input-directive\" module=\"urlExample\">\n        <file name=\"index.html\">\n         <script>\n           angular.module('urlExample', [])\n             .controller('ExampleController', ['$scope', function($scope) {\n               $scope.url = {\n                 text: 'http://google.com'\n               };\n             }]);\n         </script>\n         <form name=\"myForm\" ng-controller=\"ExampleController\">\n           URL: <input type=\"url\" name=\"input\" ng-model=\"url.text\" required>\n           <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.input.$error.url\">\n             Not valid url!</span>\n           <tt>text = {{url.text}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n           <tt>myForm.$error.url = {{!!myForm.$error.url}}</tt><br/>\n          </form>\n        </file>\n        <file name=\"protractor.js\" type=\"protractor\">\n          var text = element(by.binding('url.text'));\n          var valid = element(by.binding('myForm.input.$valid'));\n          var input = element(by.model('url.text'));\n\n          it('should initialize to model', function() {\n            expect(text.getText()).toContain('http://google.com');\n            expect(valid.getText()).toContain('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input.clear();\n            input.sendKeys('');\n\n            expect(text.getText()).toEqual('text =');\n            expect(valid.getText()).toContain('false');\n          });\n\n          it('should be invalid if not url', function() {\n            input.clear();\n            input.sendKeys('box');\n\n            expect(valid.getText()).toContain('false');\n          });\n        </file>\n      </example>\n   */\n  'url': urlInputType,\n\n\n  /**\n   * @ngdoc input\n   * @name input[email]\n   *\n   * @description\n   * Text input with email validation. Sets the `email` validation error key if not a valid email\n   * address.\n   *\n   * <div class=\"alert alert-warning\">\n   * **Note:** `input[email]` uses a regex to validate email addresses that is derived from the regex\n   * used in Chromium. If you need stricter validation (e.g. requiring a top-level domain), you can\n   * use `ng-pattern` or modify the built-in validators (see the {@link guide/forms Forms guide})\n   * </div>\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength. Setting the attribute to a negative or non-numeric value, allows view values of\n   *    any length.\n   * @param {string=} pattern Similar to `ngPattern` except that the attribute value is the actual string\n   *    that contains the regular expression body that will be converted to a regular expression\n   *    as in the ngPattern directive.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the ngModel value does not match\n   *    a RegExp found by evaluating the Angular expression given in the attribute value.\n   *    If the expression evaluates to a RegExp object then this is used directly.\n   *    If the expression is a string then it will be converted to a RegExp after wrapping it in `^` and `$`\n   *    characters. For instance, `\"abc\"` will be converted to `new RegExp('^abc$')`.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <example name=\"email-input-directive\" module=\"emailExample\">\n        <file name=\"index.html\">\n         <script>\n           angular.module('emailExample', [])\n             .controller('ExampleController', ['$scope', function($scope) {\n               $scope.email = {\n                 text: 'me@example.com'\n               };\n             }]);\n         </script>\n           <form name=\"myForm\" ng-controller=\"ExampleController\">\n             Email: <input type=\"email\" name=\"input\" ng-model=\"email.text\" required>\n             <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n               Required!</span>\n             <span class=\"error\" ng-show=\"myForm.input.$error.email\">\n               Not valid email!</span>\n             <tt>text = {{email.text}}</tt><br/>\n             <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n             <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n             <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n             <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n             <tt>myForm.$error.email = {{!!myForm.$error.email}}</tt><br/>\n           </form>\n         </file>\n        <file name=\"protractor.js\" type=\"protractor\">\n          var text = element(by.binding('email.text'));\n          var valid = element(by.binding('myForm.input.$valid'));\n          var input = element(by.model('email.text'));\n\n          it('should initialize to model', function() {\n            expect(text.getText()).toContain('me@example.com');\n            expect(valid.getText()).toContain('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input.clear();\n            input.sendKeys('');\n            expect(text.getText()).toEqual('text =');\n            expect(valid.getText()).toContain('false');\n          });\n\n          it('should be invalid if not email', function() {\n            input.clear();\n            input.sendKeys('xxx');\n\n            expect(valid.getText()).toContain('false');\n          });\n        </file>\n      </example>\n   */\n  'email': emailInputType,\n\n\n  /**\n   * @ngdoc input\n   * @name input[radio]\n   *\n   * @description\n   * HTML radio button.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string} value The value to which the expression should be set when selected.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   * @param {string} ngValue Angular expression which sets the value to which the expression should\n   *    be set when selected.\n   *\n   * @example\n      <example name=\"radio-input-directive\" module=\"radioExample\">\n        <file name=\"index.html\">\n         <script>\n           angular.module('radioExample', [])\n             .controller('ExampleController', ['$scope', function($scope) {\n               $scope.color = {\n                 name: 'blue'\n               };\n               $scope.specialValue = {\n                 \"id\": \"12345\",\n                 \"value\": \"green\"\n               };\n             }]);\n         </script>\n         <form name=\"myForm\" ng-controller=\"ExampleController\">\n           <input type=\"radio\" ng-model=\"color.name\" value=\"red\">  Red <br/>\n           <input type=\"radio\" ng-model=\"color.name\" ng-value=\"specialValue\"> Green <br/>\n           <input type=\"radio\" ng-model=\"color.name\" value=\"blue\"> Blue <br/>\n           <tt>color = {{color.name | json}}</tt><br/>\n          </form>\n          Note that `ng-value=\"specialValue\"` sets radio item's value to be the value of `$scope.specialValue`.\n        </file>\n        <file name=\"protractor.js\" type=\"protractor\">\n          it('should change state', function() {\n            var color = element(by.binding('color.name'));\n\n            expect(color.getText()).toContain('blue');\n\n            element.all(by.model('color.name')).get(0).click();\n\n            expect(color.getText()).toContain('red');\n          });\n        </file>\n      </example>\n   */\n  'radio': radioInputType,\n\n\n  /**\n   * @ngdoc input\n   * @name input[checkbox]\n   *\n   * @description\n   * HTML checkbox.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {expression=} ngTrueValue The value to which the expression should be set when selected.\n   * @param {expression=} ngFalseValue The value to which the expression should be set when not selected.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <example name=\"checkbox-input-directive\" module=\"checkboxExample\">\n        <file name=\"index.html\">\n         <script>\n           angular.module('checkboxExample', [])\n             .controller('ExampleController', ['$scope', function($scope) {\n               $scope.checkboxModel = {\n                value1 : true,\n                value2 : 'YES'\n              };\n             }]);\n         </script>\n         <form name=\"myForm\" ng-controller=\"ExampleController\">\n           Value1: <input type=\"checkbox\" ng-model=\"checkboxModel.value1\"> <br/>\n           Value2: <input type=\"checkbox\" ng-model=\"checkboxModel.value2\"\n                          ng-true-value=\"'YES'\" ng-false-value=\"'NO'\"> <br/>\n           <tt>value1 = {{checkboxModel.value1}}</tt><br/>\n           <tt>value2 = {{checkboxModel.value2}}</tt><br/>\n          </form>\n        </file>\n        <file name=\"protractor.js\" type=\"protractor\">\n          it('should change state', function() {\n            var value1 = element(by.binding('checkboxModel.value1'));\n            var value2 = element(by.binding('checkboxModel.value2'));\n\n            expect(value1.getText()).toContain('true');\n            expect(value2.getText()).toContain('YES');\n\n            element(by.model('checkboxModel.value1')).click();\n            element(by.model('checkboxModel.value2')).click();\n\n            expect(value1.getText()).toContain('false');\n            expect(value2.getText()).toContain('NO');\n          });\n        </file>\n      </example>\n   */\n  'checkbox': checkboxInputType,\n\n  'hidden': noop,\n  'button': noop,\n  'submit': noop,\n  'reset': noop,\n  'file': noop\n};\n\nfunction stringBasedInputType(ctrl) {\n  ctrl.$formatters.push(function(value) {\n    return ctrl.$isEmpty(value) ? value : value.toString();\n  });\n}\n\nfunction textInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  baseInputType(scope, element, attr, ctrl, $sniffer, $browser);\n  stringBasedInputType(ctrl);\n}\n\nfunction baseInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  var type = lowercase(element[0].type);\n\n  // In composition mode, users are still inputing intermediate text buffer,\n  // hold the listener until composition is done.\n  // More about composition events: https://developer.mozilla.org/en-US/docs/Web/API/CompositionEvent\n  if (!$sniffer.android) {\n    var composing = false;\n\n    element.on('compositionstart', function(data) {\n      composing = true;\n    });\n\n    element.on('compositionend', function() {\n      composing = false;\n      listener();\n    });\n  }\n\n  var listener = function(ev) {\n    if (timeout) {\n      $browser.defer.cancel(timeout);\n      timeout = null;\n    }\n    if (composing) return;\n    var value = element.val(),\n        event = ev && ev.type;\n\n    // By default we will trim the value\n    // If the attribute ng-trim exists we will avoid trimming\n    // If input type is 'password', the value is never trimmed\n    if (type !== 'password' && (!attr.ngTrim || attr.ngTrim !== 'false')) {\n      value = trim(value);\n    }\n\n    // If a control is suffering from bad input (due to native validators), browsers discard its\n    // value, so it may be necessary to revalidate (by calling $setViewValue again) even if the\n    // control's value is the same empty value twice in a row.\n    if (ctrl.$viewValue !== value || (value === '' && ctrl.$$hasNativeValidators)) {\n      ctrl.$setViewValue(value, event);\n    }\n  };\n\n  // if the browser does support \"input\" event, we are fine - except on IE9 which doesn't fire the\n  // input event on backspace, delete or cut\n  if ($sniffer.hasEvent('input')) {\n    element.on('input', listener);\n  } else {\n    var timeout;\n\n    var deferListener = function(ev, input, origValue) {\n      if (!timeout) {\n        timeout = $browser.defer(function() {\n          timeout = null;\n          if (!input || input.value !== origValue) {\n            listener(ev);\n          }\n        });\n      }\n    };\n\n    element.on('keydown', function(event) {\n      var key = event.keyCode;\n\n      // ignore\n      //    command            modifiers                   arrows\n      if (key === 91 || (15 < key && key < 19) || (37 <= key && key <= 40)) return;\n\n      deferListener(event, this, this.value);\n    });\n\n    // if user modifies input value using context menu in IE, we need \"paste\" and \"cut\" events to catch it\n    if ($sniffer.hasEvent('paste')) {\n      element.on('paste cut', deferListener);\n    }\n  }\n\n  // if user paste into input using mouse on older browser\n  // or form autocomplete on newer browser, we need \"change\" event to catch it\n  element.on('change', listener);\n\n  ctrl.$render = function() {\n    element.val(ctrl.$isEmpty(ctrl.$viewValue) ? '' : ctrl.$viewValue);\n  };\n}\n\nfunction weekParser(isoWeek, existingDate) {\n  if (isDate(isoWeek)) {\n    return isoWeek;\n  }\n\n  if (isString(isoWeek)) {\n    WEEK_REGEXP.lastIndex = 0;\n    var parts = WEEK_REGEXP.exec(isoWeek);\n    if (parts) {\n      var year = +parts[1],\n          week = +parts[2],\n          hours = 0,\n          minutes = 0,\n          seconds = 0,\n          milliseconds = 0,\n          firstThurs = getFirstThursdayOfYear(year),\n          addDays = (week - 1) * 7;\n\n      if (existingDate) {\n        hours = existingDate.getHours();\n        minutes = existingDate.getMinutes();\n        seconds = existingDate.getSeconds();\n        milliseconds = existingDate.getMilliseconds();\n      }\n\n      return new Date(year, 0, firstThurs.getDate() + addDays, hours, minutes, seconds, milliseconds);\n    }\n  }\n\n  return NaN;\n}\n\nfunction createDateParser(regexp, mapping) {\n  return function(iso, date) {\n    var parts, map;\n\n    if (isDate(iso)) {\n      return iso;\n    }\n\n    if (isString(iso)) {\n      // When a date is JSON'ified to wraps itself inside of an extra\n      // set of double quotes. This makes the date parsing code unable\n      // to match the date string and parse it as a date.\n      if (iso.charAt(0) == '\"' && iso.charAt(iso.length - 1) == '\"') {\n        iso = iso.substring(1, iso.length - 1);\n      }\n      if (ISO_DATE_REGEXP.test(iso)) {\n        return new Date(iso);\n      }\n      regexp.lastIndex = 0;\n      parts = regexp.exec(iso);\n\n      if (parts) {\n        parts.shift();\n        if (date) {\n          map = {\n            yyyy: date.getFullYear(),\n            MM: date.getMonth() + 1,\n            dd: date.getDate(),\n            HH: date.getHours(),\n            mm: date.getMinutes(),\n            ss: date.getSeconds(),\n            sss: date.getMilliseconds() / 1000\n          };\n        } else {\n          map = { yyyy: 1970, MM: 1, dd: 1, HH: 0, mm: 0, ss: 0, sss: 0 };\n        }\n\n        forEach(parts, function(part, index) {\n          if (index < mapping.length) {\n            map[mapping[index]] = +part;\n          }\n        });\n        return new Date(map.yyyy, map.MM - 1, map.dd, map.HH, map.mm, map.ss || 0, map.sss * 1000 || 0);\n      }\n    }\n\n    return NaN;\n  };\n}\n\nfunction createDateInputType(type, regexp, parseDate, format) {\n  return function dynamicDateInputType(scope, element, attr, ctrl, $sniffer, $browser, $filter) {\n    badInputChecker(scope, element, attr, ctrl);\n    baseInputType(scope, element, attr, ctrl, $sniffer, $browser);\n    var timezone = ctrl && ctrl.$options && ctrl.$options.timezone;\n    var previousDate;\n\n    ctrl.$$parserName = type;\n    ctrl.$parsers.push(function(value) {\n      if (ctrl.$isEmpty(value)) return null;\n      if (regexp.test(value)) {\n        // Note: We cannot read ctrl.$modelValue, as there might be a different\n        // parser/formatter in the processing chain so that the model\n        // contains some different data format!\n        var parsedDate = parseDate(value, previousDate);\n        if (timezone === 'UTC') {\n          parsedDate.setMinutes(parsedDate.getMinutes() - parsedDate.getTimezoneOffset());\n        }\n        return parsedDate;\n      }\n      return undefined;\n    });\n\n    ctrl.$formatters.push(function(value) {\n      if (value && !isDate(value)) {\n        throw $ngModelMinErr('datefmt', 'Expected `{0}` to be a date', value);\n      }\n      if (isValidDate(value)) {\n        previousDate = value;\n        if (previousDate && timezone === 'UTC') {\n          var timezoneOffset = 60000 * previousDate.getTimezoneOffset();\n          previousDate = new Date(previousDate.getTime() + timezoneOffset);\n        }\n        return $filter('date')(value, format, timezone);\n      } else {\n        previousDate = null;\n        return '';\n      }\n    });\n\n    if (isDefined(attr.min) || attr.ngMin) {\n      var minVal;\n      ctrl.$validators.min = function(value) {\n        return !isValidDate(value) || isUndefined(minVal) || parseDate(value) >= minVal;\n      };\n      attr.$observe('min', function(val) {\n        minVal = parseObservedDateValue(val);\n        ctrl.$validate();\n      });\n    }\n\n    if (isDefined(attr.max) || attr.ngMax) {\n      var maxVal;\n      ctrl.$validators.max = function(value) {\n        return !isValidDate(value) || isUndefined(maxVal) || parseDate(value) <= maxVal;\n      };\n      attr.$observe('max', function(val) {\n        maxVal = parseObservedDateValue(val);\n        ctrl.$validate();\n      });\n    }\n\n    function isValidDate(value) {\n      // Invalid Date: getTime() returns NaN\n      return value && !(value.getTime && value.getTime() !== value.getTime());\n    }\n\n    function parseObservedDateValue(val) {\n      return isDefined(val) ? (isDate(val) ? val : parseDate(val)) : undefined;\n    }\n  };\n}\n\nfunction badInputChecker(scope, element, attr, ctrl) {\n  var node = element[0];\n  var nativeValidation = ctrl.$$hasNativeValidators = isObject(node.validity);\n  if (nativeValidation) {\n    ctrl.$parsers.push(function(value) {\n      var validity = element.prop(VALIDITY_STATE_PROPERTY) || {};\n      // Detect bug in FF35 for input[email] (https://bugzilla.mozilla.org/show_bug.cgi?id=1064430):\n      // - also sets validity.badInput (should only be validity.typeMismatch).\n      // - see http://www.whatwg.org/specs/web-apps/current-work/multipage/forms.html#e-mail-state-(type=email)\n      // - can ignore this case as we can still read out the erroneous email...\n      return validity.badInput && !validity.typeMismatch ? undefined : value;\n    });\n  }\n}\n\nfunction numberInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  badInputChecker(scope, element, attr, ctrl);\n  baseInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  ctrl.$$parserName = 'number';\n  ctrl.$parsers.push(function(value) {\n    if (ctrl.$isEmpty(value))      return null;\n    if (NUMBER_REGEXP.test(value)) return parseFloat(value);\n    return undefined;\n  });\n\n  ctrl.$formatters.push(function(value) {\n    if (!ctrl.$isEmpty(value)) {\n      if (!isNumber(value)) {\n        throw $ngModelMinErr('numfmt', 'Expected `{0}` to be a number', value);\n      }\n      value = value.toString();\n    }\n    return value;\n  });\n\n  if (attr.min || attr.ngMin) {\n    var minVal;\n    ctrl.$validators.min = function(value) {\n      return ctrl.$isEmpty(value) || isUndefined(minVal) || value >= minVal;\n    };\n\n    attr.$observe('min', function(val) {\n      if (isDefined(val) && !isNumber(val)) {\n        val = parseFloat(val, 10);\n      }\n      minVal = isNumber(val) && !isNaN(val) ? val : undefined;\n      // TODO(matsko): implement validateLater to reduce number of validations\n      ctrl.$validate();\n    });\n  }\n\n  if (attr.max || attr.ngMax) {\n    var maxVal;\n    ctrl.$validators.max = function(value) {\n      return ctrl.$isEmpty(value) || isUndefined(maxVal) || value <= maxVal;\n    };\n\n    attr.$observe('max', function(val) {\n      if (isDefined(val) && !isNumber(val)) {\n        val = parseFloat(val, 10);\n      }\n      maxVal = isNumber(val) && !isNaN(val) ? val : undefined;\n      // TODO(matsko): implement validateLater to reduce number of validations\n      ctrl.$validate();\n    });\n  }\n}\n\nfunction urlInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  // Note: no badInputChecker here by purpose as `url` is only a validation\n  // in browsers, i.e. we can always read out input.value even if it is not valid!\n  baseInputType(scope, element, attr, ctrl, $sniffer, $browser);\n  stringBasedInputType(ctrl);\n\n  ctrl.$$parserName = 'url';\n  ctrl.$validators.url = function(modelValue, viewValue) {\n    var value = modelValue || viewValue;\n    return ctrl.$isEmpty(value) || URL_REGEXP.test(value);\n  };\n}\n\nfunction emailInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  // Note: no badInputChecker here by purpose as `url` is only a validation\n  // in browsers, i.e. we can always read out input.value even if it is not valid!\n  baseInputType(scope, element, attr, ctrl, $sniffer, $browser);\n  stringBasedInputType(ctrl);\n\n  ctrl.$$parserName = 'email';\n  ctrl.$validators.email = function(modelValue, viewValue) {\n    var value = modelValue || viewValue;\n    return ctrl.$isEmpty(value) || EMAIL_REGEXP.test(value);\n  };\n}\n\nfunction radioInputType(scope, element, attr, ctrl) {\n  // make the name unique, if not defined\n  if (isUndefined(attr.name)) {\n    element.attr('name', nextUid());\n  }\n\n  var listener = function(ev) {\n    if (element[0].checked) {\n      ctrl.$setViewValue(attr.value, ev && ev.type);\n    }\n  };\n\n  element.on('click', listener);\n\n  ctrl.$render = function() {\n    var value = attr.value;\n    element[0].checked = (value == ctrl.$viewValue);\n  };\n\n  attr.$observe('value', ctrl.$render);\n}\n\nfunction parseConstantExpr($parse, context, name, expression, fallback) {\n  var parseFn;\n  if (isDefined(expression)) {\n    parseFn = $parse(expression);\n    if (!parseFn.constant) {\n      throw minErr('ngModel')('constexpr', 'Expected constant expression for `{0}`, but saw ' +\n                                   '`{1}`.', name, expression);\n    }\n    return parseFn(context);\n  }\n  return fallback;\n}\n\nfunction checkboxInputType(scope, element, attr, ctrl, $sniffer, $browser, $filter, $parse) {\n  var trueValue = parseConstantExpr($parse, scope, 'ngTrueValue', attr.ngTrueValue, true);\n  var falseValue = parseConstantExpr($parse, scope, 'ngFalseValue', attr.ngFalseValue, false);\n\n  var listener = function(ev) {\n    ctrl.$setViewValue(element[0].checked, ev && ev.type);\n  };\n\n  element.on('click', listener);\n\n  ctrl.$render = function() {\n    element[0].checked = ctrl.$viewValue;\n  };\n\n  // Override the standard `$isEmpty` because the $viewValue of an empty checkbox is always set to `false`\n  // This is because of the parser below, which compares the `$modelValue` with `trueValue` to convert\n  // it to a boolean.\n  ctrl.$isEmpty = function(value) {\n    return value === false;\n  };\n\n  ctrl.$formatters.push(function(value) {\n    return equals(value, trueValue);\n  });\n\n  ctrl.$parsers.push(function(value) {\n    return value ? trueValue : falseValue;\n  });\n}\n\n\n/**\n * @ngdoc directive\n * @name textarea\n * @restrict E\n *\n * @description\n * HTML textarea element control with angular data-binding. The data-binding and validation\n * properties of this element are exactly the same as those of the\n * {@link ng.directive:input input element}.\n *\n * @param {string} ngModel Assignable angular expression to data-bind to.\n * @param {string=} name Property name of the form under which the control is published.\n * @param {string=} required Sets `required` validation error key if the value is not entered.\n * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n *    `required` when you want to data-bind to the `required` attribute.\n * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n *    minlength.\n * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n *    maxlength. Setting the attribute to a negative or non-numeric value, allows view values of any\n *    length.\n * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n *    patterns defined as scope expressions.\n * @param {string=} ngChange Angular expression to be executed when input changes due to user\n *    interaction with the input element.\n * @param {boolean=} [ngTrim=true] If set to false Angular will not automatically trim the input.\n */\n\n\n/**\n * @ngdoc directive\n * @name input\n * @restrict E\n *\n * @description\n * HTML input element control. When used together with {@link ngModel `ngModel`}, it provides data-binding,\n * input state control, and validation.\n * Input control follows HTML5 input types and polyfills the HTML5 validation behavior for older browsers.\n *\n * <div class=\"alert alert-warning\">\n * **Note:** Not every feature offered is available for all input types.\n * Specifically, data binding and event handling via `ng-model` is unsupported for `input[file]`.\n * </div>\n *\n * @param {string} ngModel Assignable angular expression to data-bind to.\n * @param {string=} name Property name of the form under which the control is published.\n * @param {string=} required Sets `required` validation error key if the value is not entered.\n * @param {boolean=} ngRequired Sets `required` attribute if set to true\n * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n *    minlength.\n * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n *    maxlength. Setting the attribute to a negative or non-numeric value, allows view values of any\n *    length.\n * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n *    patterns defined as scope expressions.\n * @param {string=} ngChange Angular expression to be executed when input changes due to user\n *    interaction with the input element.\n * @param {boolean=} [ngTrim=true] If set to false Angular will not automatically trim the input.\n *    This parameter is ignored for input[type=password] controls, which will never trim the\n *    input.\n *\n * @example\n    <example name=\"input-directive\" module=\"inputExample\">\n      <file name=\"index.html\">\n       <script>\n          angular.module('inputExample', [])\n            .controller('ExampleController', ['$scope', function($scope) {\n              $scope.user = {name: 'guest', last: 'visitor'};\n            }]);\n       </script>\n       <div ng-controller=\"ExampleController\">\n         <form name=\"myForm\">\n           User name: <input type=\"text\" name=\"userName\" ng-model=\"user.name\" required>\n           <span class=\"error\" ng-show=\"myForm.userName.$error.required\">\n             Required!</span><br>\n           Last name: <input type=\"text\" name=\"lastName\" ng-model=\"user.last\"\n             ng-minlength=\"3\" ng-maxlength=\"10\">\n           <span class=\"error\" ng-show=\"myForm.lastName.$error.minlength\">\n             Too short!</span>\n           <span class=\"error\" ng-show=\"myForm.lastName.$error.maxlength\">\n             Too long!</span><br>\n         </form>\n         <hr>\n         <tt>user = {{user}}</tt><br/>\n         <tt>myForm.userName.$valid = {{myForm.userName.$valid}}</tt><br>\n         <tt>myForm.userName.$error = {{myForm.userName.$error}}</tt><br>\n         <tt>myForm.lastName.$valid = {{myForm.lastName.$valid}}</tt><br>\n         <tt>myForm.lastName.$error = {{myForm.lastName.$error}}</tt><br>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br>\n         <tt>myForm.$error.minlength = {{!!myForm.$error.minlength}}</tt><br>\n         <tt>myForm.$error.maxlength = {{!!myForm.$error.maxlength}}</tt><br>\n       </div>\n      </file>\n      <file name=\"protractor.js\" type=\"protractor\">\n        var user = element(by.exactBinding('user'));\n        var userNameValid = element(by.binding('myForm.userName.$valid'));\n        var lastNameValid = element(by.binding('myForm.lastName.$valid'));\n        var lastNameError = element(by.binding('myForm.lastName.$error'));\n        var formValid = element(by.binding('myForm.$valid'));\n        var userNameInput = element(by.model('user.name'));\n        var userLastInput = element(by.model('user.last'));\n\n        it('should initialize to model', function() {\n          expect(user.getText()).toContain('{\"name\":\"guest\",\"last\":\"visitor\"}');\n          expect(userNameValid.getText()).toContain('true');\n          expect(formValid.getText()).toContain('true');\n        });\n\n        it('should be invalid if empty when required', function() {\n          userNameInput.clear();\n          userNameInput.sendKeys('');\n\n          expect(user.getText()).toContain('{\"last\":\"visitor\"}');\n          expect(userNameValid.getText()).toContain('false');\n          expect(formValid.getText()).toContain('false');\n        });\n\n        it('should be valid if empty when min length is set', function() {\n          userLastInput.clear();\n          userLastInput.sendKeys('');\n\n          expect(user.getText()).toContain('{\"name\":\"guest\",\"last\":\"\"}');\n          expect(lastNameValid.getText()).toContain('true');\n          expect(formValid.getText()).toContain('true');\n        });\n\n        it('should be invalid if less than required min length', function() {\n          userLastInput.clear();\n          userLastInput.sendKeys('xx');\n\n          expect(user.getText()).toContain('{\"name\":\"guest\"}');\n          expect(lastNameValid.getText()).toContain('false');\n          expect(lastNameError.getText()).toContain('minlength');\n          expect(formValid.getText()).toContain('false');\n        });\n\n        it('should be invalid if longer than max length', function() {\n          userLastInput.clear();\n          userLastInput.sendKeys('some ridiculously long name');\n\n          expect(user.getText()).toContain('{\"name\":\"guest\"}');\n          expect(lastNameValid.getText()).toContain('false');\n          expect(lastNameError.getText()).toContain('maxlength');\n          expect(formValid.getText()).toContain('false');\n        });\n      </file>\n    </example>\n */\nvar inputDirective = ['$browser', '$sniffer', '$filter', '$parse',\n    function($browser, $sniffer, $filter, $parse) {\n  return {\n    restrict: 'E',\n    require: ['?ngModel'],\n    link: {\n      pre: function(scope, element, attr, ctrls) {\n        if (ctrls[0]) {\n          (inputType[lowercase(attr.type)] || inputType.text)(scope, element, attr, ctrls[0], $sniffer,\n                                                              $browser, $filter, $parse);\n        }\n      }\n    }\n  };\n}];\n\n\n\nvar CONSTANT_VALUE_REGEXP = /^(true|false|\\d+)$/;\n/**\n * @ngdoc directive\n * @name ngValue\n *\n * @description\n * Binds the given expression to the value of `<option>` or {@link input[radio] `input[radio]`},\n * so that when the element is selected, the {@link ngModel `ngModel`} of that element is set to\n * the bound value.\n *\n * `ngValue` is useful when dynamically generating lists of radio buttons using\n * {@link ngRepeat `ngRepeat`}, as shown below.\n *\n * Likewise, `ngValue` can be used to generate `<option>` elements for\n * the {@link select `select`} element. In that case however, only strings are supported\n * for the `value `attribute, so the resulting `ngModel` will always be a string.\n * Support for `select` models with non-string values is available via `ngOptions`.\n *\n * @element input\n * @param {string=} ngValue angular expression, whose value will be bound to the `value` attribute\n *   of the `input` element\n *\n * @example\n    <example name=\"ngValue-directive\" module=\"valueExample\">\n      <file name=\"index.html\">\n       <script>\n          angular.module('valueExample', [])\n            .controller('ExampleController', ['$scope', function($scope) {\n              $scope.names = ['pizza', 'unicorns', 'robots'];\n              $scope.my = { favorite: 'unicorns' };\n            }]);\n       </script>\n        <form ng-controller=\"ExampleController\">\n          <h2>Which is your favorite?</h2>\n            <label ng-repeat=\"name in names\" for=\"{{name}}\">\n              {{name}}\n              <input type=\"radio\"\n                     ng-model=\"my.favorite\"\n                     ng-value=\"name\"\n                     id=\"{{name}}\"\n                     name=\"favorite\">\n            </label>\n          <div>You chose {{my.favorite}}</div>\n        </form>\n      </file>\n      <file name=\"protractor.js\" type=\"protractor\">\n        var favorite = element(by.binding('my.favorite'));\n\n        it('should initialize to model', function() {\n          expect(favorite.getText()).toContain('unicorns');\n        });\n        it('should bind the values to the inputs', function() {\n          element.all(by.model('my.favorite')).get(0).click();\n          expect(favorite.getText()).toContain('pizza');\n        });\n      </file>\n    </example>\n */\nvar ngValueDirective = function() {\n  return {\n    restrict: 'A',\n    priority: 100,\n    compile: function(tpl, tplAttr) {\n      if (CONSTANT_VALUE_REGEXP.test(tplAttr.ngValue)) {\n        return function ngValueConstantLink(scope, elm, attr) {\n          attr.$set('value', scope.$eval(attr.ngValue));\n        };\n      } else {\n        return function ngValueLink(scope, elm, attr) {\n          scope.$watch(attr.ngValue, function valueWatchAction(value) {\n            attr.$set('value', value);\n          });\n        };\n      }\n    }\n  };\n};\n\n/**\n * @ngdoc directive\n * @name ngBind\n * @restrict AC\n *\n * @description\n * The `ngBind` attribute tells Angular to replace the text content of the specified HTML element\n * with the value of a given expression, and to update the text content when the value of that\n * expression changes.\n *\n * Typically, you don't use `ngBind` directly, but instead you use the double curly markup like\n * `{{ expression }}` which is similar but less verbose.\n *\n * It is preferable to use `ngBind` instead of `{{ expression }}` if a template is momentarily\n * displayed by the browser in its raw state before Angular compiles it. Since `ngBind` is an\n * element attribute, it makes the bindings invisible to the user while the page is loading.\n *\n * An alternative solution to this problem would be using the\n * {@link ng.directive:ngCloak ngCloak} directive.\n *\n *\n * @element ANY\n * @param {expression} ngBind {@link guide/expression Expression} to evaluate.\n *\n * @example\n * Enter a name in the Live Preview text box; the greeting below the text box changes instantly.\n   <example module=\"bindExample\">\n     <file name=\"index.html\">\n       <script>\n         angular.module('bindExample', [])\n           .controller('ExampleController', ['$scope', function($scope) {\n             $scope.name = 'Whirled';\n           }]);\n       </script>\n       <div ng-controller=\"ExampleController\">\n         Enter name: <input type=\"text\" ng-model=\"name\"><br>\n         Hello <span ng-bind=\"name\"></span>!\n       </div>\n     </file>\n     <file name=\"protractor.js\" type=\"protractor\">\n       it('should check ng-bind', function() {\n         var nameInput = element(by.model('name'));\n\n         expect(element(by.binding('name')).getText()).toBe('Whirled');\n         nameInput.clear();\n         nameInput.sendKeys('world');\n         expect(element(by.binding('name')).getText()).toBe('world');\n       });\n     </file>\n   </example>\n */\nvar ngBindDirective = ['$compile', function($compile) {\n  return {\n    restrict: 'AC',\n    compile: function ngBindCompile(templateElement) {\n      $compile.$$addBindingClass(templateElement);\n      return function ngBindLink(scope, element, attr) {\n        $compile.$$addBindingInfo(element, attr.ngBind);\n        element = element[0];\n        scope.$watch(attr.ngBind, function ngBindWatchAction(value) {\n          element.textContent = value === undefined ? '' : value;\n        });\n      };\n    }\n  };\n}];\n\n\n/**\n * @ngdoc directive\n * @name ngBindTemplate\n *\n * @description\n * The `ngBindTemplate` directive specifies that the element\n * text content should be replaced with the interpolation of the template\n * in the `ngBindTemplate` attribute.\n * Unlike `ngBind`, the `ngBindTemplate` can contain multiple `{{` `}}`\n * expressions. This directive is needed since some HTML elements\n * (such as TITLE and OPTION) cannot contain SPAN elements.\n *\n * @element ANY\n * @param {string} ngBindTemplate template of form\n *   <tt>{{</tt> <tt>expression</tt> <tt>}}</tt> to eval.\n *\n * @example\n * Try it here: enter text in text box and watch the greeting change.\n   <example module=\"bindExample\">\n     <file name=\"index.html\">\n       <script>\n         angular.module('bindExample', [])\n           .controller('ExampleController', ['$scope', function($scope) {\n             $scope.salutation = 'Hello';\n             $scope.name = 'World';\n           }]);\n       </script>\n       <div ng-controller=\"ExampleController\">\n        Salutation: <input type=\"text\" ng-model=\"salutation\"><br>\n        Name: <input type=\"text\" ng-model=\"name\"><br>\n        <pre ng-bind-template=\"{{salutation}} {{name}}!\"></pre>\n       </div>\n     </file>\n     <file name=\"protractor.js\" type=\"protractor\">\n       it('should check ng-bind', function() {\n         var salutationElem = element(by.binding('salutation'));\n         var salutationInput = element(by.model('salutation'));\n         var nameInput = element(by.model('name'));\n\n         expect(salutationElem.getText()).toBe('Hello World!');\n\n         salutationInput.clear();\n         salutationInput.sendKeys('Greetings');\n         nameInput.clear();\n         nameInput.sendKeys('user');\n\n         expect(salutationElem.getText()).toBe('Greetings user!');\n       });\n     </file>\n   </example>\n */\nvar ngBindTemplateDirective = ['$interpolate', '$compile', function($interpolate, $compile) {\n  return {\n    compile: function ngBindTemplateCompile(templateElement) {\n      $compile.$$addBindingClass(templateElement);\n      return function ngBindTemplateLink(scope, element, attr) {\n        var interpolateFn = $interpolate(element.attr(attr.$attr.ngBindTemplate));\n        $compile.$$addBindingInfo(element, interpolateFn.expressions);\n        element = element[0];\n        attr.$observe('ngBindTemplate', function(value) {\n          element.textContent = value === undefined ? '' : value;\n        });\n      };\n    }\n  };\n}];\n\n\n/**\n * @ngdoc directive\n * @name ngBindHtml\n *\n * @description\n * Evaluates the expression and inserts the resulting HTML into the element in a secure way. By default,\n * the resulting HTML content will be sanitized using the {@link ngSanitize.$sanitize $sanitize} service.\n * To utilize this functionality, ensure that `$sanitize` is available, for example, by including {@link\n * ngSanitize} in your module's dependencies (not in core Angular). In order to use {@link ngSanitize}\n * in your module's dependencies, you need to include \"angular-sanitize.js\" in your application.\n *\n * You may also bypass sanitization for values you know are safe. To do so, bind to\n * an explicitly trusted value via {@link ng.$sce#trustAsHtml $sce.trustAsHtml}.  See the example\n * under {@link ng.$sce#show-me-an-example-using-sce- Strict Contextual Escaping (SCE)}.\n *\n * Note: If a `$sanitize` service is unavailable and the bound value isn't explicitly trusted, you\n * will have an exception (instead of an exploit.)\n *\n * @element ANY\n * @param {expression} ngBindHtml {@link guide/expression Expression} to evaluate.\n *\n * @example\n\n   <example module=\"bindHtmlExample\" deps=\"angular-sanitize.js\">\n     <file name=\"index.html\">\n       <div ng-controller=\"ExampleController\">\n        <p ng-bind-html=\"myHTML\"></p>\n       </div>\n     </file>\n\n     <file name=\"script.js\">\n       angular.module('bindHtmlExample', ['ngSanitize'])\n         .controller('ExampleController', ['$scope', function($scope) {\n           $scope.myHTML =\n              'I am an <code>HTML</code>string with ' +\n              '<a href=\"#\">links!</a> and other <em>stuff</em>';\n         }]);\n     </file>\n\n     <file name=\"protractor.js\" type=\"protractor\">\n       it('should check ng-bind-html', function() {\n         expect(element(by.binding('myHTML')).getText()).toBe(\n             'I am an HTMLstring with links! and other stuff');\n       });\n     </file>\n   </example>\n */\nvar ngBindHtmlDirective = ['$sce', '$parse', '$compile', function($sce, $parse, $compile) {\n  return {\n    restrict: 'A',\n    compile: function ngBindHtmlCompile(tElement, tAttrs) {\n      var ngBindHtmlGetter = $parse(tAttrs.ngBindHtml);\n      var ngBindHtmlWatch = $parse(tAttrs.ngBindHtml, function getStringValue(value) {\n        return (value || '').toString();\n      });\n      $compile.$$addBindingClass(tElement);\n\n      return function ngBindHtmlLink(scope, element, attr) {\n        $compile.$$addBindingInfo(element, attr.ngBindHtml);\n\n        scope.$watch(ngBindHtmlWatch, function ngBindHtmlWatchAction() {\n          // we re-evaluate the expr because we want a TrustedValueHolderType\n          // for $sce, not a string\n          element.html($sce.getTrustedHtml(ngBindHtmlGetter(scope)) || '');\n        });\n      };\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ngChange\n *\n * @description\n * Evaluate the given expression when the user changes the input.\n * The expression is evaluated immediately, unlike the JavaScript onchange event\n * which only triggers at the end of a change (usually, when the user leaves the\n * form element or presses the return key).\n *\n * The `ngChange` expression is only evaluated when a change in the input value causes\n * a new value to be committed to the model.\n *\n * It will not be evaluated:\n * * if the value returned from the `$parsers` transformation pipeline has not changed\n * * if the input has continued to be invalid since the model will stay `null`\n * * if the model is changed programmatically and not by a change to the input value\n *\n *\n * Note, this directive requires `ngModel` to be present.\n *\n * @element input\n * @param {expression} ngChange {@link guide/expression Expression} to evaluate upon change\n * in input value.\n *\n * @example\n * <example name=\"ngChange-directive\" module=\"changeExample\">\n *   <file name=\"index.html\">\n *     <script>\n *       angular.module('changeExample', [])\n *         .controller('ExampleController', ['$scope', function($scope) {\n *           $scope.counter = 0;\n *           $scope.change = function() {\n *             $scope.counter++;\n *           };\n *         }]);\n *     </script>\n *     <div ng-controller=\"ExampleController\">\n *       <input type=\"checkbox\" ng-model=\"confirmed\" ng-change=\"change()\" id=\"ng-change-example1\" />\n *       <input type=\"checkbox\" ng-model=\"confirmed\" id=\"ng-change-example2\" />\n *       <label for=\"ng-change-example2\">Confirmed</label><br />\n *       <tt>debug = {{confirmed}}</tt><br/>\n *       <tt>counter = {{counter}}</tt><br/>\n *     </div>\n *   </file>\n *   <file name=\"protractor.js\" type=\"protractor\">\n *     var counter = element(by.binding('counter'));\n *     var debug = element(by.binding('confirmed'));\n *\n *     it('should evaluate the expression if changing from view', function() {\n *       expect(counter.getText()).toContain('0');\n *\n *       element(by.id('ng-change-example1')).click();\n *\n *       expect(counter.getText()).toContain('1');\n *       expect(debug.getText()).toContain('true');\n *     });\n *\n *     it('should not evaluate the expression if changing from model', function() {\n *       element(by.id('ng-change-example2')).click();\n\n *       expect(counter.getText()).toContain('0');\n *       expect(debug.getText()).toContain('true');\n *     });\n *   </file>\n * </example>\n */\nvar ngChangeDirective = valueFn({\n  restrict: 'A',\n  require: 'ngModel',\n  link: function(scope, element, attr, ctrl) {\n    ctrl.$viewChangeListeners.push(function() {\n      scope.$eval(attr.ngChange);\n    });\n  }\n});\n\nfunction classDirective(name, selector) {\n  name = 'ngClass' + name;\n  return ['$animate', function($animate) {\n    return {\n      restrict: 'AC',\n      link: function(scope, element, attr) {\n        var oldVal;\n\n        scope.$watch(attr[name], ngClassWatchAction, true);\n\n        attr.$observe('class', function(value) {\n          ngClassWatchAction(scope.$eval(attr[name]));\n        });\n\n\n        if (name !== 'ngClass') {\n          scope.$watch('$index', function($index, old$index) {\n            // jshint bitwise: false\n            var mod = $index & 1;\n            if (mod !== (old$index & 1)) {\n              var classes = arrayClasses(scope.$eval(attr[name]));\n              mod === selector ?\n                addClasses(classes) :\n                removeClasses(classes);\n            }\n          });\n        }\n\n        function addClasses(classes) {\n          var newClasses = digestClassCounts(classes, 1);\n          attr.$addClass(newClasses);\n        }\n\n        function removeClasses(classes) {\n          var newClasses = digestClassCounts(classes, -1);\n          attr.$removeClass(newClasses);\n        }\n\n        function digestClassCounts(classes, count) {\n          var classCounts = element.data('$classCounts') || {};\n          var classesToUpdate = [];\n          forEach(classes, function(className) {\n            if (count > 0 || classCounts[className]) {\n              classCounts[className] = (classCounts[className] || 0) + count;\n              if (classCounts[className] === +(count > 0)) {\n                classesToUpdate.push(className);\n              }\n            }\n          });\n          element.data('$classCounts', classCounts);\n          return classesToUpdate.join(' ');\n        }\n\n        function updateClasses(oldClasses, newClasses) {\n          var toAdd = arrayDifference(newClasses, oldClasses);\n          var toRemove = arrayDifference(oldClasses, newClasses);\n          toAdd = digestClassCounts(toAdd, 1);\n          toRemove = digestClassCounts(toRemove, -1);\n          if (toAdd && toAdd.length) {\n            $animate.addClass(element, toAdd);\n          }\n          if (toRemove && toRemove.length) {\n            $animate.removeClass(element, toRemove);\n          }\n        }\n\n        function ngClassWatchAction(newVal) {\n          if (selector === true || scope.$index % 2 === selector) {\n            var newClasses = arrayClasses(newVal || []);\n            if (!oldVal) {\n              addClasses(newClasses);\n            } else if (!equals(newVal,oldVal)) {\n              var oldClasses = arrayClasses(oldVal);\n              updateClasses(oldClasses, newClasses);\n            }\n          }\n          oldVal = shallowCopy(newVal);\n        }\n      }\n    };\n\n    function arrayDifference(tokens1, tokens2) {\n      var values = [];\n\n      outer:\n      for (var i = 0; i < tokens1.length; i++) {\n        var token = tokens1[i];\n        for (var j = 0; j < tokens2.length; j++) {\n          if (token == tokens2[j]) continue outer;\n        }\n        values.push(token);\n      }\n      return values;\n    }\n\n    function arrayClasses(classVal) {\n      if (isArray(classVal)) {\n        return classVal;\n      } else if (isString(classVal)) {\n        return classVal.split(' ');\n      } else if (isObject(classVal)) {\n        var classes = [];\n        forEach(classVal, function(v, k) {\n          if (v) {\n            classes = classes.concat(k.split(' '));\n          }\n        });\n        return classes;\n      }\n      return classVal;\n    }\n  }];\n}\n\n/**\n * @ngdoc directive\n * @name ngClass\n * @restrict AC\n *\n * @description\n * The `ngClass` directive allows you to dynamically set CSS classes on an HTML element by databinding\n * an expression that represents all classes to be added.\n *\n * The directive operates in three different ways, depending on which of three types the expression\n * evaluates to:\n *\n * 1. If the expression evaluates to a string, the string should be one or more space-delimited class\n * names.\n *\n * 2. If the expression evaluates to an array, each element of the array should be a string that is\n * one or more space-delimited class names.\n *\n * 3. If the expression evaluates to an object, then for each key-value pair of the\n * object with a truthy value the corresponding key is used as a class name.\n *\n * The directive won't add duplicate classes if a particular class was already set.\n *\n * When the expression changes, the previously added classes are removed and only then the\n * new classes are added.\n *\n * @animations\n * **add** - happens just before the class is applied to the elements\n *\n * **remove** - happens just before the class is removed from the element\n *\n * @element ANY\n * @param {expression} ngClass {@link guide/expression Expression} to eval. The result\n *   of the evaluation can be a string representing space delimited class\n *   names, an array, or a map of class names to boolean values. In the case of a map, the\n *   names of the properties whose values are truthy will be added as css classes to the\n *   element.\n *\n * @example Example that demonstrates basic bindings via ngClass directive.\n   <example>\n     <file name=\"index.html\">\n       <p ng-class=\"{strike: deleted, bold: important, red: error}\">Map Syntax Example</p>\n       <input type=\"checkbox\" ng-model=\"deleted\"> deleted (apply \"strike\" class)<br>\n       <input type=\"checkbox\" ng-model=\"important\"> important (apply \"bold\" class)<br>\n       <input type=\"checkbox\" ng-model=\"error\"> error (apply \"red\" class)\n       <hr>\n       <p ng-class=\"style\">Using String Syntax</p>\n       <input type=\"text\" ng-model=\"style\" placeholder=\"Type: bold strike red\">\n       <hr>\n       <p ng-class=\"[style1, style2, style3]\">Using Array Syntax</p>\n       <input ng-model=\"style1\" placeholder=\"Type: bold, strike or red\"><br>\n       <input ng-model=\"style2\" placeholder=\"Type: bold, strike or red\"><br>\n       <input ng-model=\"style3\" placeholder=\"Type: bold, strike or red\"><br>\n     </file>\n     <file name=\"style.css\">\n       .strike {\n         text-decoration: line-through;\n       }\n       .bold {\n           font-weight: bold;\n       }\n       .red {\n           color: red;\n       }\n     </file>\n     <file name=\"protractor.js\" type=\"protractor\">\n       var ps = element.all(by.css('p'));\n\n       it('should let you toggle the class', function() {\n\n         expect(ps.first().getAttribute('class')).not.toMatch(/bold/);\n         expect(ps.first().getAttribute('class')).not.toMatch(/red/);\n\n         element(by.model('important')).click();\n         expect(ps.first().getAttribute('class')).toMatch(/bold/);\n\n         element(by.model('error')).click();\n         expect(ps.first().getAttribute('class')).toMatch(/red/);\n       });\n\n       it('should let you toggle string example', function() {\n         expect(ps.get(1).getAttribute('class')).toBe('');\n         element(by.model('style')).clear();\n         element(by.model('style')).sendKeys('red');\n         expect(ps.get(1).getAttribute('class')).toBe('red');\n       });\n\n       it('array example should have 3 classes', function() {\n         expect(ps.last().getAttribute('class')).toBe('');\n         element(by.model('style1')).sendKeys('bold');\n         element(by.model('style2')).sendKeys('strike');\n         element(by.model('style3')).sendKeys('red');\n         expect(ps.last().getAttribute('class')).toBe('bold strike red');\n       });\n     </file>\n   </example>\n\n   ## Animations\n\n   The example below demonstrates how to perform animations using ngClass.\n\n   <example module=\"ngAnimate\" deps=\"angular-animate.js\" animations=\"true\">\n     <file name=\"index.html\">\n      <input id=\"setbtn\" type=\"button\" value=\"set\" ng-click=\"myVar='my-class'\">\n      <input id=\"clearbtn\" type=\"button\" value=\"clear\" ng-click=\"myVar=''\">\n      <br>\n      <span class=\"base-class\" ng-class=\"myVar\">Sample Text</span>\n     </file>\n     <file name=\"style.css\">\n       .base-class {\n         -webkit-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;\n         transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;\n       }\n\n       .base-class.my-class {\n         color: red;\n         font-size:3em;\n       }\n     </file>\n     <file name=\"protractor.js\" type=\"protractor\">\n       it('should check ng-class', function() {\n         expect(element(by.css('.base-class')).getAttribute('class')).not.\n           toMatch(/my-class/);\n\n         element(by.id('setbtn')).click();\n\n         expect(element(by.css('.base-class')).getAttribute('class')).\n           toMatch(/my-class/);\n\n         element(by.id('clearbtn')).click();\n\n         expect(element(by.css('.base-class')).getAttribute('class')).not.\n           toMatch(/my-class/);\n       });\n     </file>\n   </example>\n\n\n   ## ngClass and pre-existing CSS3 Transitions/Animations\n   The ngClass directive still supports CSS3 Transitions/Animations even if they do not follow the ngAnimate CSS naming structure.\n   Upon animation ngAnimate will apply supplementary CSS classes to track the start and end of an animation, but this will not hinder\n   any pre-existing CSS transitions already on the element. To get an idea of what happens during a class-based animation, be sure\n   to view the step by step details of {@link ng.$animate#addClass $animate.addClass} and\n   {@link ng.$animate#removeClass $animate.removeClass}.\n */\nvar ngClassDirective = classDirective('', true);\n\n/**\n * @ngdoc directive\n * @name ngClassOdd\n * @restrict AC\n *\n * @description\n * The `ngClassOdd` and `ngClassEven` directives work exactly as\n * {@link ng.directive:ngClass ngClass}, except they work in\n * conjunction with `ngRepeat` and take effect only on odd (even) rows.\n *\n * This directive can be applied only within the scope of an\n * {@link ng.directive:ngRepeat ngRepeat}.\n *\n * @element ANY\n * @param {expression} ngClassOdd {@link guide/expression Expression} to eval. The result\n *   of the evaluation can be a string representing space delimited class names or an array.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <ol ng-init=\"names=['John', 'Mary', 'Cate', 'Suz']\">\n          <li ng-repeat=\"name in names\">\n           <span ng-class-odd=\"'odd'\" ng-class-even=\"'even'\">\n             {{name}}\n           </span>\n          </li>\n        </ol>\n     </file>\n     <file name=\"style.css\">\n       .odd {\n         color: red;\n       }\n       .even {\n         color: blue;\n       }\n     </file>\n     <file name=\"protractor.js\" type=\"protractor\">\n       it('should check ng-class-odd and ng-class-even', function() {\n         expect(element(by.repeater('name in names').row(0).column('name')).getAttribute('class')).\n           toMatch(/odd/);\n         expect(element(by.repeater('name in names').row(1).column('name')).getAttribute('class')).\n           toMatch(/even/);\n       });\n     </file>\n   </example>\n */\nvar ngClassOddDirective = classDirective('Odd', 0);\n\n/**\n * @ngdoc directive\n * @name ngClassEven\n * @restrict AC\n *\n * @description\n * The `ngClassOdd` and `ngClassEven` directives work exactly as\n * {@link ng.directive:ngClass ngClass}, except they work in\n * conjunction with `ngRepeat` and take effect only on odd (even) rows.\n *\n * This directive can be applied only within the scope of an\n * {@link ng.directive:ngRepeat ngRepeat}.\n *\n * @element ANY\n * @param {expression} ngClassEven {@link guide/expression Expression} to eval. The\n *   result of the evaluation can be a string representing space delimited class names or an array.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <ol ng-init=\"names=['John', 'Mary', 'Cate', 'Suz']\">\n          <li ng-repeat=\"name in names\">\n           <span ng-class-odd=\"'odd'\" ng-class-even=\"'even'\">\n             {{name}} &nbsp; &nbsp; &nbsp;\n           </span>\n          </li>\n        </ol>\n     </file>\n     <file name=\"style.css\">\n       .odd {\n         color: red;\n       }\n       .even {\n         color: blue;\n       }\n     </file>\n     <file name=\"protractor.js\" type=\"protractor\">\n       it('should check ng-class-odd and ng-class-even', function() {\n         expect(element(by.repeater('name in names').row(0).column('name')).getAttribute('class')).\n           toMatch(/odd/);\n         expect(element(by.repeater('name in names').row(1).column('name')).getAttribute('class')).\n           toMatch(/even/);\n       });\n     </file>\n   </example>\n */\nvar ngClassEvenDirective = classDirective('Even', 1);\n\n/**\n * @ngdoc directive\n * @name ngCloak\n * @restrict AC\n *\n * @description\n * The `ngCloak` directive is used to prevent the Angular html template from being briefly\n * displayed by the browser in its raw (uncompiled) form while your application is loading. Use this\n * directive to avoid the undesirable flicker effect caused by the html template display.\n *\n * The directive can be applied to the `<body>` element, but the preferred usage is to apply\n * multiple `ngCloak` directives to small portions of the page to permit progressive rendering\n * of the browser view.\n *\n * `ngCloak` works in cooperation with the following css rule embedded within `angular.js` and\n * `angular.min.js`.\n * For CSP mode please add `angular-csp.css` to your html file (see {@link ng.directive:ngCsp ngCsp}).\n *\n * ```css\n * [ng\\:cloak], [ng-cloak], [data-ng-cloak], [x-ng-cloak], .ng-cloak, .x-ng-cloak {\n *   display: none !important;\n * }\n * ```\n *\n * When this css rule is loaded by the browser, all html elements (including their children) that\n * are tagged with the `ngCloak` directive are hidden. When Angular encounters this directive\n * during the compilation of the template it deletes the `ngCloak` element attribute, making\n * the compiled element visible.\n *\n * For the best result, the `angular.js` script must be loaded in the head section of the html\n * document; alternatively, the css rule above must be included in the external stylesheet of the\n * application.\n *\n * Legacy browsers, like IE7, do not provide attribute selector support (added in CSS 2.1) so they\n * cannot match the `[ng\\:cloak]` selector. To work around this limitation, you must add the css\n * class `ng-cloak` in addition to the `ngCloak` directive as shown in the example below.\n *\n * @element ANY\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <div id=\"template1\" ng-cloak>{{ 'hello' }}</div>\n        <div id=\"template2\" ng-cloak class=\"ng-cloak\">{{ 'hello IE7' }}</div>\n     </file>\n     <file name=\"protractor.js\" type=\"protractor\">\n       it('should remove the template directive and css class', function() {\n         expect($('#template1').getAttribute('ng-cloak')).\n           toBeNull();\n         expect($('#template2').getAttribute('ng-cloak')).\n           toBeNull();\n       });\n     </file>\n   </example>\n *\n */\nvar ngCloakDirective = ngDirective({\n  compile: function(element, attr) {\n    attr.$set('ngCloak', undefined);\n    element.removeClass('ng-cloak');\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ngController\n *\n * @description\n * The `ngController` directive attaches a controller class to the view. This is a key aspect of how angular\n * supports the principles behind the Model-View-Controller design pattern.\n *\n * MVC components in angular:\n *\n * * Model — Models are the properties of a scope; scopes are attached to the DOM where scope properties\n *   are accessed through bindings.\n * * View — The template (HTML with data bindings) that is rendered into the View.\n * * Controller — The `ngController` directive specifies a Controller class; the class contains business\n *   logic behind the application to decorate the scope with functions and values\n *\n * Note that you can also attach controllers to the DOM by declaring it in a route definition\n * via the {@link ngRoute.$route $route} service. A common mistake is to declare the controller\n * again using `ng-controller` in the template itself.  This will cause the controller to be attached\n * and executed twice.\n *\n * @element ANY\n * @scope\n * @priority 500\n * @param {expression} ngController Name of a constructor function registered with the current\n * {@link ng.$controllerProvider $controllerProvider} or an {@link guide/expression expression}\n * that on the current scope evaluates to a constructor function.\n *\n * The controller instance can be published into a scope property by specifying\n * `ng-controller=\"as propertyName\"`.\n *\n * If the current `$controllerProvider` is configured to use globals (via\n * {@link ng.$controllerProvider#allowGlobals `$controllerProvider.allowGlobals()` }), this may\n * also be the name of a globally accessible constructor function (not recommended).\n *\n * @example\n * Here is a simple form for editing user contact information. Adding, removing, clearing, and\n * greeting are methods declared on the controller (see source tab). These methods can\n * easily be called from the angular markup. Any changes to the data are automatically reflected\n * in the View without the need for a manual update.\n *\n * Two different declaration styles are included below:\n *\n * * one binds methods and properties directly onto the controller using `this`:\n * `ng-controller=\"SettingsController1 as settings\"`\n * * one injects `$scope` into the controller:\n * `ng-controller=\"SettingsController2\"`\n *\n * The second option is more common in the Angular community, and is generally used in boilerplates\n * and in this guide. However, there are advantages to binding properties directly to the controller\n * and avoiding scope.\n *\n * * Using `controller as` makes it obvious which controller you are accessing in the template when\n * multiple controllers apply to an element.\n * * If you are writing your controllers as classes you have easier access to the properties and\n * methods, which will appear on the scope, from inside the controller code.\n * * Since there is always a `.` in the bindings, you don't have to worry about prototypal\n * inheritance masking primitives.\n *\n * This example demonstrates the `controller as` syntax.\n *\n * <example name=\"ngControllerAs\" module=\"controllerAsExample\">\n *   <file name=\"index.html\">\n *    <div id=\"ctrl-as-exmpl\" ng-controller=\"SettingsController1 as settings\">\n *      Name: <input type=\"text\" ng-model=\"settings.name\"/>\n *      [ <a href=\"\" ng-click=\"settings.greet()\">greet</a> ]<br/>\n *      Contact:\n *      <ul>\n *        <li ng-repeat=\"contact in settings.contacts\">\n *          <select ng-model=\"contact.type\">\n *             <option>phone</option>\n *             <option>email</option>\n *          </select>\n *          <input type=\"text\" ng-model=\"contact.value\"/>\n *          [ <a href=\"\" ng-click=\"settings.clearContact(contact)\">clear</a>\n *          | <a href=\"\" ng-click=\"settings.removeContact(contact)\">X</a> ]\n *        </li>\n *        <li>[ <a href=\"\" ng-click=\"settings.addContact()\">add</a> ]</li>\n *     </ul>\n *    </div>\n *   </file>\n *   <file name=\"app.js\">\n *    angular.module('controllerAsExample', [])\n *      .controller('SettingsController1', SettingsController1);\n *\n *    function SettingsController1() {\n *      this.name = \"John Smith\";\n *      this.contacts = [\n *        {type: 'phone', value: '408 555 1212'},\n *        {type: 'email', value: 'john.smith@example.org'} ];\n *    }\n *\n *    SettingsController1.prototype.greet = function() {\n *      alert(this.name);\n *    };\n *\n *    SettingsController1.prototype.addContact = function() {\n *      this.contacts.push({type: 'email', value: 'yourname@example.org'});\n *    };\n *\n *    SettingsController1.prototype.removeContact = function(contactToRemove) {\n *     var index = this.contacts.indexOf(contactToRemove);\n *      this.contacts.splice(index, 1);\n *    };\n *\n *    SettingsController1.prototype.clearContact = function(contact) {\n *      contact.type = 'phone';\n *      contact.value = '';\n *    };\n *   </file>\n *   <file name=\"protractor.js\" type=\"protractor\">\n *     it('should check controller as', function() {\n *       var container = element(by.id('ctrl-as-exmpl'));\n *         expect(container.element(by.model('settings.name'))\n *           .getAttribute('value')).toBe('John Smith');\n *\n *       var firstRepeat =\n *           container.element(by.repeater('contact in settings.contacts').row(0));\n *       var secondRepeat =\n *           container.element(by.repeater('contact in settings.contacts').row(1));\n *\n *       expect(firstRepeat.element(by.model('contact.value')).getAttribute('value'))\n *           .toBe('408 555 1212');\n *\n *       expect(secondRepeat.element(by.model('contact.value')).getAttribute('value'))\n *           .toBe('john.smith@example.org');\n *\n *       firstRepeat.element(by.linkText('clear')).click();\n *\n *       expect(firstRepeat.element(by.model('contact.value')).getAttribute('value'))\n *           .toBe('');\n *\n *       container.element(by.linkText('add')).click();\n *\n *       expect(container.element(by.repeater('contact in settings.contacts').row(2))\n *           .element(by.model('contact.value'))\n *           .getAttribute('value'))\n *           .toBe('yourname@example.org');\n *     });\n *   </file>\n * </example>\n *\n * This example demonstrates the \"attach to `$scope`\" style of controller.\n *\n * <example name=\"ngController\" module=\"controllerExample\">\n *  <file name=\"index.html\">\n *   <div id=\"ctrl-exmpl\" ng-controller=\"SettingsController2\">\n *     Name: <input type=\"text\" ng-model=\"name\"/>\n *     [ <a href=\"\" ng-click=\"greet()\">greet</a> ]<br/>\n *     Contact:\n *     <ul>\n *       <li ng-repeat=\"contact in contacts\">\n *         <select ng-model=\"contact.type\">\n *            <option>phone</option>\n *            <option>email</option>\n *         </select>\n *         <input type=\"text\" ng-model=\"contact.value\"/>\n *         [ <a href=\"\" ng-click=\"clearContact(contact)\">clear</a>\n *         | <a href=\"\" ng-click=\"removeContact(contact)\">X</a> ]\n *       </li>\n *       <li>[ <a href=\"\" ng-click=\"addContact()\">add</a> ]</li>\n *    </ul>\n *   </div>\n *  </file>\n *  <file name=\"app.js\">\n *   angular.module('controllerExample', [])\n *     .controller('SettingsController2', ['$scope', SettingsController2]);\n *\n *   function SettingsController2($scope) {\n *     $scope.name = \"John Smith\";\n *     $scope.contacts = [\n *       {type:'phone', value:'408 555 1212'},\n *       {type:'email', value:'john.smith@example.org'} ];\n *\n *     $scope.greet = function() {\n *       alert($scope.name);\n *     };\n *\n *     $scope.addContact = function() {\n *       $scope.contacts.push({type:'email', value:'yourname@example.org'});\n *     };\n *\n *     $scope.removeContact = function(contactToRemove) {\n *       var index = $scope.contacts.indexOf(contactToRemove);\n *       $scope.contacts.splice(index, 1);\n *     };\n *\n *     $scope.clearContact = function(contact) {\n *       contact.type = 'phone';\n *       contact.value = '';\n *     };\n *   }\n *  </file>\n *  <file name=\"protractor.js\" type=\"protractor\">\n *    it('should check controller', function() {\n *      var container = element(by.id('ctrl-exmpl'));\n *\n *      expect(container.element(by.model('name'))\n *          .getAttribute('value')).toBe('John Smith');\n *\n *      var firstRepeat =\n *          container.element(by.repeater('contact in contacts').row(0));\n *      var secondRepeat =\n *          container.element(by.repeater('contact in contacts').row(1));\n *\n *      expect(firstRepeat.element(by.model('contact.value')).getAttribute('value'))\n *          .toBe('408 555 1212');\n *      expect(secondRepeat.element(by.model('contact.value')).getAttribute('value'))\n *          .toBe('john.smith@example.org');\n *\n *      firstRepeat.element(by.linkText('clear')).click();\n *\n *      expect(firstRepeat.element(by.model('contact.value')).getAttribute('value'))\n *          .toBe('');\n *\n *      container.element(by.linkText('add')).click();\n *\n *      expect(container.element(by.repeater('contact in contacts').row(2))\n *          .element(by.model('contact.value'))\n *          .getAttribute('value'))\n *          .toBe('yourname@example.org');\n *    });\n *  </file>\n *</example>\n\n */\nvar ngControllerDirective = [function() {\n  return {\n    restrict: 'A',\n    scope: true,\n    controller: '@',\n    priority: 500\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ngCsp\n *\n * @element html\n * @description\n * Enables [CSP (Content Security Policy)](https://developer.mozilla.org/en/Security/CSP) support.\n *\n * This is necessary when developing things like Google Chrome Extensions or Universal Windows Apps.\n *\n * CSP forbids apps to use `eval` or `Function(string)` generated functions (among other things).\n * For Angular to be CSP compatible there are only two things that we need to do differently:\n *\n * - don't use `Function` constructor to generate optimized value getters\n * - don't inject custom stylesheet into the document\n *\n * AngularJS uses `Function(string)` generated functions as a speed optimization. Applying the `ngCsp`\n * directive will cause Angular to use CSP compatibility mode. When this mode is on AngularJS will\n * evaluate all expressions up to 30% slower than in non-CSP mode, but no security violations will\n * be raised.\n *\n * CSP forbids JavaScript to inline stylesheet rules. In non CSP mode Angular automatically\n * includes some CSS rules (e.g. {@link ng.directive:ngCloak ngCloak}).\n * To make those directives work in CSP mode, include the `angular-csp.css` manually.\n *\n * Angular tries to autodetect if CSP is active and automatically turn on the CSP-safe mode. This\n * autodetection however triggers a CSP error to be logged in the console:\n *\n * ```\n * Refused to evaluate a string as JavaScript because 'unsafe-eval' is not an allowed source of\n * script in the following Content Security Policy directive: \"default-src 'self'\". Note that\n * 'script-src' was not explicitly set, so 'default-src' is used as a fallback.\n * ```\n *\n * This error is harmless but annoying. To prevent the error from showing up, put the `ngCsp`\n * directive on the root element of the application or on the `angular.js` script tag, whichever\n * appears first in the html document.\n *\n * *Note: This directive is only available in the `ng-csp` and `data-ng-csp` attribute form.*\n *\n * @example\n * This example shows how to apply the `ngCsp` directive to the `html` tag.\n   ```html\n     <!doctype html>\n     <html ng-app ng-csp>\n     ...\n     ...\n     </html>\n   ```\n  * @example\n      // Note: the suffix `.csp` in the example name triggers\n      // csp mode in our http server!\n      <example name=\"example.csp\" module=\"cspExample\" ng-csp=\"true\">\n        <file name=\"index.html\">\n          <div ng-controller=\"MainController as ctrl\">\n            <div>\n              <button ng-click=\"ctrl.inc()\" id=\"inc\">Increment</button>\n              <span id=\"counter\">\n                {{ctrl.counter}}\n              </span>\n            </div>\n\n            <div>\n              <button ng-click=\"ctrl.evil()\" id=\"evil\">Evil</button>\n              <span id=\"evilError\">\n                {{ctrl.evilError}}\n              </span>\n            </div>\n          </div>\n        </file>\n        <file name=\"script.js\">\n           angular.module('cspExample', [])\n             .controller('MainController', function() {\n                this.counter = 0;\n                this.inc = function() {\n                  this.counter++;\n                };\n                this.evil = function() {\n                  // jshint evil:true\n                  try {\n                    eval('1+2');\n                  } catch (e) {\n                    this.evilError = e.message;\n                  }\n                };\n              });\n        </file>\n        <file name=\"protractor.js\" type=\"protractor\">\n          var util, webdriver;\n\n          var incBtn = element(by.id('inc'));\n          var counter = element(by.id('counter'));\n          var evilBtn = element(by.id('evil'));\n          var evilError = element(by.id('evilError'));\n\n          function getAndClearSevereErrors() {\n            return browser.manage().logs().get('browser').then(function(browserLog) {\n              return browserLog.filter(function(logEntry) {\n                return logEntry.level.value > webdriver.logging.Level.WARNING.value;\n              });\n            });\n          }\n\n          function clearErrors() {\n            getAndClearSevereErrors();\n          }\n\n          function expectNoErrors() {\n            getAndClearSevereErrors().then(function(filteredLog) {\n              expect(filteredLog.length).toEqual(0);\n              if (filteredLog.length) {\n                console.log('browser console errors: ' + util.inspect(filteredLog));\n              }\n            });\n          }\n\n          function expectError(regex) {\n            getAndClearSevereErrors().then(function(filteredLog) {\n              var found = false;\n              filteredLog.forEach(function(log) {\n                if (log.message.match(regex)) {\n                  found = true;\n                }\n              });\n              if (!found) {\n                throw new Error('expected an error that matches ' + regex);\n              }\n            });\n          }\n\n          beforeEach(function() {\n            util = require('util');\n            webdriver = require('protractor/node_modules/selenium-webdriver');\n          });\n\n          // For now, we only test on Chrome,\n          // as Safari does not load the page with Protractor's injected scripts,\n          // and Firefox webdriver always disables content security policy (#6358)\n          if (browser.params.browser !== 'chrome') {\n            return;\n          }\n\n          it('should not report errors when the page is loaded', function() {\n            // clear errors so we are not dependent on previous tests\n            clearErrors();\n            // Need to reload the page as the page is already loaded when\n            // we come here\n            browser.driver.getCurrentUrl().then(function(url) {\n              browser.get(url);\n            });\n            expectNoErrors();\n          });\n\n          it('should evaluate expressions', function() {\n            expect(counter.getText()).toEqual('0');\n            incBtn.click();\n            expect(counter.getText()).toEqual('1');\n            expectNoErrors();\n          });\n\n          it('should throw and report an error when using \"eval\"', function() {\n            evilBtn.click();\n            expect(evilError.getText()).toMatch(/Content Security Policy/);\n            expectError(/Content Security Policy/);\n          });\n        </file>\n      </example>\n  */\n\n// ngCsp is not implemented as a proper directive any more, because we need it be processed while we\n// bootstrap the system (before $parse is instantiated), for this reason we just have\n// the csp.isActive() fn that looks for ng-csp attribute anywhere in the current doc\n\n/**\n * @ngdoc directive\n * @name ngClick\n *\n * @description\n * The ngClick directive allows you to specify custom behavior when\n * an element is clicked.\n *\n * @element ANY\n * @priority 0\n * @param {expression} ngClick {@link guide/expression Expression} to evaluate upon\n * click. ({@link guide/expression#-event- Event object is available as `$event`})\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n      <button ng-click=\"count = count + 1\" ng-init=\"count=0\">\n        Increment\n      </button>\n      <span>\n        count: {{count}}\n      </span>\n     </file>\n     <file name=\"protractor.js\" type=\"protractor\">\n       it('should check ng-click', function() {\n         expect(element(by.binding('count')).getText()).toMatch('0');\n         element(by.css('button')).click();\n         expect(element(by.binding('count')).getText()).toMatch('1');\n       });\n     </file>\n   </example>\n */\n/*\n * A collection of directives that allows creation of custom event handlers that are defined as\n * angular expressions and are compiled and executed within the current scope.\n */\nvar ngEventDirectives = {};\n\n// For events that might fire synchronously during DOM manipulation\n// we need to execute their event handlers asynchronously using $evalAsync,\n// so that they are not executed in an inconsistent state.\nvar forceAsyncEvents = {\n  'blur': true,\n  'focus': true\n};\nforEach(\n  'click dblclick mousedown mouseup mouseover mouseout mousemove mouseenter mouseleave keydown keyup keypress submit focus blur copy cut paste'.split(' '),\n  function(eventName) {\n    var directiveName = directiveNormalize('ng-' + eventName);\n    ngEventDirectives[directiveName] = ['$parse', '$rootScope', function($parse, $rootScope) {\n      return {\n        restrict: 'A',\n        compile: function($element, attr) {\n          // We expose the powerful $event object on the scope that provides access to the Window,\n          // etc. that isn't protected by the fast paths in $parse.  We explicitly request better\n          // checks at the cost of speed since event handler expressions are not executed as\n          // frequently as regular change detection.\n          var fn = $parse(attr[directiveName], /* interceptorFn */ null, /* expensiveChecks */ true);\n          return function ngEventHandler(scope, element) {\n            element.on(eventName, function(event) {\n              var callback = function() {\n                fn(scope, {$event:event});\n              };\n              if (forceAsyncEvents[eventName] && $rootScope.$$phase) {\n                scope.$evalAsync(callback);\n              } else {\n                scope.$apply(callback);\n              }\n            });\n          };\n        }\n      };\n    }];\n  }\n);\n\n/**\n * @ngdoc directive\n * @name ngDblclick\n *\n * @description\n * The `ngDblclick` directive allows you to specify custom behavior on a dblclick event.\n *\n * @element ANY\n * @priority 0\n * @param {expression} ngDblclick {@link guide/expression Expression} to evaluate upon\n * a dblclick. (The Event object is available as `$event`)\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n      <button ng-dblclick=\"count = count + 1\" ng-init=\"count=0\">\n        Increment (on double click)\n      </button>\n      count: {{count}}\n     </file>\n   </example>\n */\n\n\n/**\n * @ngdoc directive\n * @name ngMousedown\n *\n * @description\n * The ngMousedown directive allows you to specify custom behavior on mousedown event.\n *\n * @element ANY\n * @priority 0\n * @param {expression} ngMousedown {@link guide/expression Expression} to evaluate upon\n * mousedown. ({@link guide/expression#-event- Event object is available as `$event`})\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n      <button ng-mousedown=\"count = count + 1\" ng-init=\"count=0\">\n        Increment (on mouse down)\n      </button>\n      count: {{count}}\n     </file>\n   </example>\n */\n\n\n/**\n * @ngdoc directive\n * @name ngMouseup\n *\n * @description\n * Specify custom behavior on mouseup event.\n *\n * @element ANY\n * @priority 0\n * @param {expression} ngMouseup {@link guide/expression Expression} to evaluate upon\n * mouseup. ({@link guide/expression#-event- Event object is available as `$event`})\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n      <button ng-mouseup=\"count = count + 1\" ng-init=\"count=0\">\n        Increment (on mouse up)\n      </button>\n      count: {{count}}\n     </file>\n   </example>\n */\n\n/**\n * @ngdoc directive\n * @name ngMouseover\n *\n * @description\n * Specify custom behavior on mouseover event.\n *\n * @element ANY\n * @priority 0\n * @param {expression} ngMouseover {@link guide/expression Expression} to evaluate upon\n * mouseover. ({@link guide/expression#-event- Event object is available as `$event`})\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n      <button ng-mouseover=\"count = count + 1\" ng-init=\"count=0\">\n        Increment (when mouse is over)\n      </button>\n      count: {{count}}\n     </file>\n   </example>\n */\n\n\n/**\n * @ngdoc directive\n * @name ngMouseenter\n *\n * @description\n * Specify custom behavior on mouseenter event.\n *\n * @element ANY\n * @priority 0\n * @param {expression} ngMouseenter {@link guide/expression Expression} to evaluate upon\n * mouseenter. ({@link guide/expression#-event- Event object is available as `$event`})\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n      <button ng-mouseenter=\"count = count + 1\" ng-init=\"count=0\">\n        Increment (when mouse enters)\n      </button>\n      count: {{count}}\n     </file>\n   </example>\n */\n\n\n/**\n * @ngdoc directive\n * @name ngMouseleave\n *\n * @description\n * Specify custom behavior on mouseleave event.\n *\n * @element ANY\n * @priority 0\n * @param {expression} ngMouseleave {@link guide/expression Expression} to evaluate upon\n * mouseleave. ({@link guide/expression#-event- Event object is available as `$event`})\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n      <button ng-mouseleave=\"count = count + 1\" ng-init=\"count=0\">\n        Increment (when mouse leaves)\n      </button>\n      count: {{count}}\n     </file>\n   </example>\n */\n\n\n/**\n * @ngdoc directive\n * @name ngMousemove\n *\n * @description\n * Specify custom behavior on mousemove event.\n *\n * @element ANY\n * @priority 0\n * @param {expression} ngMousemove {@link guide/expression Expression} to evaluate upon\n * mousemove. ({@link guide/expression#-event- Event object is available as `$event`})\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n      <button ng-mousemove=\"count = count + 1\" ng-init=\"count=0\">\n        Increment (when mouse moves)\n      </button>\n      count: {{count}}\n     </file>\n   </example>\n */\n\n\n/**\n * @ngdoc directive\n * @name ngKeydown\n *\n * @description\n * Specify custom behavior on keydown event.\n *\n * @element ANY\n * @priority 0\n * @param {expression} ngKeydown {@link guide/expression Expression} to evaluate upon\n * keydown. (Event object is available as `$event` and can be interrogated for keyCode, altKey, etc.)\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n      <input ng-keydown=\"count = count + 1\" ng-init=\"count=0\">\n      key down count: {{count}}\n     </file>\n   </example>\n */\n\n\n/**\n * @ngdoc directive\n * @name ngKeyup\n *\n * @description\n * Specify custom behavior on keyup event.\n *\n * @element ANY\n * @priority 0\n * @param {expression} ngKeyup {@link guide/expression Expression} to evaluate upon\n * keyup. (Event object is available as `$event` and can be interrogated for keyCode, altKey, etc.)\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n       <p>Typing in the input box below updates the key count</p>\n       <input ng-keyup=\"count = count + 1\" ng-init=\"count=0\"> key up count: {{count}}\n\n       <p>Typing in the input box below updates the keycode</p>\n       <input ng-keyup=\"event=$event\">\n       <p>event keyCode: {{ event.keyCode }}</p>\n       <p>event altKey: {{ event.altKey }}</p>\n     </file>\n   </example>\n */\n\n\n/**\n * @ngdoc directive\n * @name ngKeypress\n *\n * @description\n * Specify custom behavior on keypress event.\n *\n * @element ANY\n * @param {expression} ngKeypress {@link guide/expression Expression} to evaluate upon\n * keypress. ({@link guide/expression#-event- Event object is available as `$event`}\n * and can be interrogated for keyCode, altKey, etc.)\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n      <input ng-keypress=\"count = count + 1\" ng-init=\"count=0\">\n      key press count: {{count}}\n     </file>\n   </example>\n */\n\n\n/**\n * @ngdoc directive\n * @name ngSubmit\n *\n * @description\n * Enables binding angular expressions to onsubmit events.\n *\n * Additionally it prevents the default action (which for form means sending the request to the\n * server and reloading the current page), but only if the form does not contain `action`,\n * `data-action`, or `x-action` attributes.\n *\n * <div class=\"alert alert-warning\">\n * **Warning:** Be careful not to cause \"double-submission\" by using both the `ngClick` and\n * `ngSubmit` handlers together. See the\n * {@link form#submitting-a-form-and-preventing-the-default-action `form` directive documentation}\n * for a detailed discussion of when `ngSubmit` may be triggered.\n * </div>\n *\n * @element form\n * @priority 0\n * @param {expression} ngSubmit {@link guide/expression Expression} to eval.\n * ({@link guide/expression#-event- Event object is available as `$event`})\n *\n * @example\n   <example module=\"submitExample\">\n     <file name=\"index.html\">\n      <script>\n        angular.module('submitExample', [])\n          .controller('ExampleController', ['$scope', function($scope) {\n            $scope.list = [];\n            $scope.text = 'hello';\n            $scope.submit = function() {\n              if ($scope.text) {\n                $scope.list.push(this.text);\n                $scope.text = '';\n              }\n            };\n          }]);\n      </script>\n      <form ng-submit=\"submit()\" ng-controller=\"ExampleController\">\n        Enter text and hit enter:\n        <input type=\"text\" ng-model=\"text\" name=\"text\" />\n        <input type=\"submit\" id=\"submit\" value=\"Submit\" />\n        <pre>list={{list}}</pre>\n      </form>\n     </file>\n     <file name=\"protractor.js\" type=\"protractor\">\n       it('should check ng-submit', function() {\n         expect(element(by.binding('list')).getText()).toBe('list=[]');\n         element(by.css('#submit')).click();\n         expect(element(by.binding('list')).getText()).toContain('hello');\n         expect(element(by.model('text')).getAttribute('value')).toBe('');\n       });\n       it('should ignore empty strings', function() {\n         expect(element(by.binding('list')).getText()).toBe('list=[]');\n         element(by.css('#submit')).click();\n         element(by.css('#submit')).click();\n         expect(element(by.binding('list')).getText()).toContain('hello');\n        });\n     </file>\n   </example>\n */\n\n/**\n * @ngdoc directive\n * @name ngFocus\n *\n * @description\n * Specify custom behavior on focus event.\n *\n * Note: As the `focus` event is executed synchronously when calling `input.focus()`\n * AngularJS executes the expression using `scope.$evalAsync` if the event is fired\n * during an `$apply` to ensure a consistent state.\n *\n * @element window, input, select, textarea, a\n * @priority 0\n * @param {expression} ngFocus {@link guide/expression Expression} to evaluate upon\n * focus. ({@link guide/expression#-event- Event object is available as `$event`})\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n/**\n * @ngdoc directive\n * @name ngBlur\n *\n * @description\n * Specify custom behavior on blur event.\n *\n * A [blur event](https://developer.mozilla.org/en-US/docs/Web/Events/blur) fires when\n * an element has lost focus.\n *\n * Note: As the `blur` event is executed synchronously also during DOM manipulations\n * (e.g. removing a focussed input),\n * AngularJS executes the expression using `scope.$evalAsync` if the event is fired\n * during an `$apply` to ensure a consistent state.\n *\n * @element window, input, select, textarea, a\n * @priority 0\n * @param {expression} ngBlur {@link guide/expression Expression} to evaluate upon\n * blur. ({@link guide/expression#-event- Event object is available as `$event`})\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n/**\n * @ngdoc directive\n * @name ngCopy\n *\n * @description\n * Specify custom behavior on copy event.\n *\n * @element window, input, select, textarea, a\n * @priority 0\n * @param {expression} ngCopy {@link guide/expression Expression} to evaluate upon\n * copy. ({@link guide/expression#-event- Event object is available as `$event`})\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n      <input ng-copy=\"copied=true\" ng-init=\"copied=false; value='copy me'\" ng-model=\"value\">\n      copied: {{copied}}\n     </file>\n   </example>\n */\n\n/**\n * @ngdoc directive\n * @name ngCut\n *\n * @description\n * Specify custom behavior on cut event.\n *\n * @element window, input, select, textarea, a\n * @priority 0\n * @param {expression} ngCut {@link guide/expression Expression} to evaluate upon\n * cut. ({@link guide/expression#-event- Event object is available as `$event`})\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n      <input ng-cut=\"cut=true\" ng-init=\"cut=false; value='cut me'\" ng-model=\"value\">\n      cut: {{cut}}\n     </file>\n   </example>\n */\n\n/**\n * @ngdoc directive\n * @name ngPaste\n *\n * @description\n * Specify custom behavior on paste event.\n *\n * @element window, input, select, textarea, a\n * @priority 0\n * @param {expression} ngPaste {@link guide/expression Expression} to evaluate upon\n * paste. ({@link guide/expression#-event- Event object is available as `$event`})\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n      <input ng-paste=\"paste=true\" ng-init=\"paste=false\" placeholder='paste here'>\n      pasted: {{paste}}\n     </file>\n   </example>\n */\n\n/**\n * @ngdoc directive\n * @name ngIf\n * @restrict A\n *\n * @description\n * The `ngIf` directive removes or recreates a portion of the DOM tree based on an\n * {expression}. If the expression assigned to `ngIf` evaluates to a false\n * value then the element is removed from the DOM, otherwise a clone of the\n * element is reinserted into the DOM.\n *\n * `ngIf` differs from `ngShow` and `ngHide` in that `ngIf` completely removes and recreates the\n * element in the DOM rather than changing its visibility via the `display` css property.  A common\n * case when this difference is significant is when using css selectors that rely on an element's\n * position within the DOM, such as the `:first-child` or `:last-child` pseudo-classes.\n *\n * Note that when an element is removed using `ngIf` its scope is destroyed and a new scope\n * is created when the element is restored.  The scope created within `ngIf` inherits from\n * its parent scope using\n * [prototypal inheritance](https://github.com/angular/angular.js/wiki/Understanding-Scopes#javascript-prototypal-inheritance).\n * An important implication of this is if `ngModel` is used within `ngIf` to bind to\n * a javascript primitive defined in the parent scope. In this case any modifications made to the\n * variable within the child scope will override (hide) the value in the parent scope.\n *\n * Also, `ngIf` recreates elements using their compiled state. An example of this behavior\n * is if an element's class attribute is directly modified after it's compiled, using something like\n * jQuery's `.addClass()` method, and the element is later removed. When `ngIf` recreates the element\n * the added class will be lost because the original compiled state is used to regenerate the element.\n *\n * Additionally, you can provide animations via the `ngAnimate` module to animate the `enter`\n * and `leave` effects.\n *\n * @animations\n * enter - happens just after the `ngIf` contents change and a new DOM element is created and injected into the `ngIf` container\n * leave - happens just before the `ngIf` contents are removed from the DOM\n *\n * @element ANY\n * @scope\n * @priority 600\n * @param {expression} ngIf If the {@link guide/expression expression} is falsy then\n *     the element is removed from the DOM tree. If it is truthy a copy of the compiled\n *     element is added to the DOM tree.\n *\n * @example\n  <example module=\"ngAnimate\" deps=\"angular-animate.js\" animations=\"true\">\n    <file name=\"index.html\">\n      Click me: <input type=\"checkbox\" ng-model=\"checked\" ng-init=\"checked=true\" /><br/>\n      Show when checked:\n      <span ng-if=\"checked\" class=\"animate-if\">\n        This is removed when the checkbox is unchecked.\n      </span>\n    </file>\n    <file name=\"animations.css\">\n      .animate-if {\n        background:white;\n        border:1px solid black;\n        padding:10px;\n      }\n\n      .animate-if.ng-enter, .animate-if.ng-leave {\n        -webkit-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;\n        transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;\n      }\n\n      .animate-if.ng-enter,\n      .animate-if.ng-leave.ng-leave-active {\n        opacity:0;\n      }\n\n      .animate-if.ng-leave,\n      .animate-if.ng-enter.ng-enter-active {\n        opacity:1;\n      }\n    </file>\n  </example>\n */\nvar ngIfDirective = ['$animate', function($animate) {\n  return {\n    multiElement: true,\n    transclude: 'element',\n    priority: 600,\n    terminal: true,\n    restrict: 'A',\n    $$tlb: true,\n    link: function($scope, $element, $attr, ctrl, $transclude) {\n        var block, childScope, previousElements;\n        $scope.$watch($attr.ngIf, function ngIfWatchAction(value) {\n\n          if (value) {\n            if (!childScope) {\n              $transclude(function(clone, newScope) {\n                childScope = newScope;\n                clone[clone.length++] = document.createComment(' end ngIf: ' + $attr.ngIf + ' ');\n                // Note: We only need the first/last node of the cloned nodes.\n                // However, we need to keep the reference to the jqlite wrapper as it might be changed later\n                // by a directive with templateUrl when its template arrives.\n                block = {\n                  clone: clone\n                };\n                $animate.enter(clone, $element.parent(), $element);\n              });\n            }\n          } else {\n            if (previousElements) {\n              previousElements.remove();\n              previousElements = null;\n            }\n            if (childScope) {\n              childScope.$destroy();\n              childScope = null;\n            }\n            if (block) {\n              previousElements = getBlockNodes(block.clone);\n              $animate.leave(previousElements).then(function() {\n                previousElements = null;\n              });\n              block = null;\n            }\n          }\n        });\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ngInclude\n * @restrict ECA\n *\n * @description\n * Fetches, compiles and includes an external HTML fragment.\n *\n * By default, the template URL is restricted to the same domain and protocol as the\n * application document. This is done by calling {@link $sce#getTrustedResourceUrl\n * $sce.getTrustedResourceUrl} on it. To load templates from other domains or protocols\n * you may either {@link ng.$sceDelegateProvider#resourceUrlWhitelist whitelist them} or\n * {@link $sce#trustAsResourceUrl wrap them} as trusted values. Refer to Angular's {@link\n * ng.$sce Strict Contextual Escaping}.\n *\n * In addition, the browser's\n * [Same Origin Policy](https://code.google.com/p/browsersec/wiki/Part2#Same-origin_policy_for_XMLHttpRequest)\n * and [Cross-Origin Resource Sharing (CORS)](http://www.w3.org/TR/cors/)\n * policy may further restrict whether the template is successfully loaded.\n * For example, `ngInclude` won't work for cross-domain requests on all browsers and for `file://`\n * access on some browsers.\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 *\n * @param {string} ngInclude|src angular expression evaluating to URL. If the source is a string constant,\n *                 make sure you wrap it in **single** quotes, e.g. `src=\"'myPartialTemplate.html'\"`.\n * @param {string=} onload Expression to evaluate when a new partial is loaded.\n *\n * @param {string=} autoscroll Whether `ngInclude` should call {@link ng.$anchorScroll\n *                  $anchorScroll} to scroll the viewport after the content is loaded.\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 expression evaluates to truthy value.\n *\n * @example\n  <example module=\"includeExample\" deps=\"angular-animate.js\" animations=\"true\">\n    <file name=\"index.html\">\n     <div ng-controller=\"ExampleController\">\n       <select ng-model=\"template\" ng-options=\"t.name for t in templates\">\n        <option value=\"\">(blank)</option>\n       </select>\n       url of the template: <code>{{template.url}}</code>\n       <hr/>\n       <div class=\"slide-animate-container\">\n         <div class=\"slide-animate\" ng-include=\"template.url\"></div>\n       </div>\n     </div>\n    </file>\n    <file name=\"script.js\">\n      angular.module('includeExample', ['ngAnimate'])\n        .controller('ExampleController', ['$scope', function($scope) {\n          $scope.templates =\n            [ { name: 'template1.html', url: 'template1.html'},\n              { name: 'template2.html', url: 'template2.html'} ];\n          $scope.template = $scope.templates[0];\n        }]);\n     </file>\n    <file name=\"template1.html\">\n      Content of template1.html\n    </file>\n    <file name=\"template2.html\">\n      Content of template2.html\n    </file>\n    <file name=\"animations.css\">\n      .slide-animate-container {\n        position:relative;\n        background:white;\n        border:1px solid black;\n        height:40px;\n        overflow:hidden;\n      }\n\n      .slide-animate {\n        padding:10px;\n      }\n\n      .slide-animate.ng-enter, .slide-animate.ng-leave {\n        -webkit-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;\n        transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;\n\n        position:absolute;\n        top:0;\n        left:0;\n        right:0;\n        bottom:0;\n        display:block;\n        padding:10px;\n      }\n\n      .slide-animate.ng-enter {\n        top:-50px;\n      }\n      .slide-animate.ng-enter.ng-enter-active {\n        top:0;\n      }\n\n      .slide-animate.ng-leave {\n        top:0;\n      }\n      .slide-animate.ng-leave.ng-leave-active {\n        top:50px;\n      }\n    </file>\n    <file name=\"protractor.js\" type=\"protractor\">\n      var templateSelect = element(by.model('template'));\n      var includeElem = element(by.css('[ng-include]'));\n\n      it('should load template1.html', function() {\n        expect(includeElem.getText()).toMatch(/Content of template1.html/);\n      });\n\n      it('should load template2.html', function() {\n        if (browser.params.browser == 'firefox') {\n          // Firefox can't handle using selects\n          // See https://github.com/angular/protractor/issues/480\n          return;\n        }\n        templateSelect.click();\n        templateSelect.all(by.css('option')).get(2).click();\n        expect(includeElem.getText()).toMatch(/Content of template2.html/);\n      });\n\n      it('should change to blank', function() {\n        if (browser.params.browser == 'firefox') {\n          // Firefox can't handle using selects\n          return;\n        }\n        templateSelect.click();\n        templateSelect.all(by.css('option')).get(0).click();\n        expect(includeElem.isPresent()).toBe(false);\n      });\n    </file>\n  </example>\n */\n\n\n/**\n * @ngdoc event\n * @name ngInclude#$includeContentRequested\n * @eventType emit on the scope ngInclude was declared in\n * @description\n * Emitted every time the ngInclude content is requested.\n *\n * @param {Object} angularEvent Synthetic event object.\n * @param {String} src URL of content to load.\n */\n\n\n/**\n * @ngdoc event\n * @name ngInclude#$includeContentLoaded\n * @eventType emit on the current ngInclude scope\n * @description\n * Emitted every time the ngInclude content is reloaded.\n *\n * @param {Object} angularEvent Synthetic event object.\n * @param {String} src URL of content to load.\n */\n\n\n/**\n * @ngdoc event\n * @name ngInclude#$includeContentError\n * @eventType emit on the scope ngInclude was declared in\n * @description\n * Emitted when a template HTTP request yields an erroneous response (status < 200 || status > 299)\n *\n * @param {Object} angularEvent Synthetic event object.\n * @param {String} src URL of content to load.\n */\nvar ngIncludeDirective = ['$templateRequest', '$anchorScroll', '$animate', '$sce',\n                  function($templateRequest,   $anchorScroll,   $animate,   $sce) {\n  return {\n    restrict: 'ECA',\n    priority: 400,\n    terminal: true,\n    transclude: 'element',\n    controller: angular.noop,\n    compile: function(element, attr) {\n      var srcExp = attr.ngInclude || attr.src,\n          onloadExp = attr.onload || '',\n          autoScrollExp = attr.autoscroll;\n\n      return function(scope, $element, $attr, ctrl, $transclude) {\n        var changeCounter = 0,\n            currentScope,\n            previousElement,\n            currentElement;\n\n        var cleanupLastIncludeContent = function() {\n          if (previousElement) {\n            previousElement.remove();\n            previousElement = null;\n          }\n          if (currentScope) {\n            currentScope.$destroy();\n            currentScope = null;\n          }\n          if (currentElement) {\n            $animate.leave(currentElement).then(function() {\n              previousElement = null;\n            });\n            previousElement = currentElement;\n            currentElement = null;\n          }\n        };\n\n        scope.$watch($sce.parseAsResourceUrl(srcExp), function ngIncludeWatchAction(src) {\n          var afterAnimation = function() {\n            if (isDefined(autoScrollExp) && (!autoScrollExp || scope.$eval(autoScrollExp))) {\n              $anchorScroll();\n            }\n          };\n          var thisChangeId = ++changeCounter;\n\n          if (src) {\n            //set the 2nd param to true to ignore the template request error so that the inner\n            //contents and scope can be cleaned up.\n            $templateRequest(src, true).then(function(response) {\n              if (thisChangeId !== changeCounter) return;\n              var newScope = scope.$new();\n              ctrl.template = response;\n\n              // Note: This will also link all children of ng-include that were contained in the original\n              // html. If that content contains controllers, ... they could pollute/change the scope.\n              // However, using ng-include 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                cleanupLastIncludeContent();\n                $animate.enter(clone, null, $element).then(afterAnimation);\n              });\n\n              currentScope = newScope;\n              currentElement = clone;\n\n              currentScope.$emit('$includeContentLoaded', src);\n              scope.$eval(onloadExp);\n            }, function() {\n              if (thisChangeId === changeCounter) {\n                cleanupLastIncludeContent();\n                scope.$emit('$includeContentError', src);\n              }\n            });\n            scope.$emit('$includeContentRequested', src);\n          } else {\n            cleanupLastIncludeContent();\n            ctrl.template = null;\n          }\n        });\n      };\n    }\n  };\n}];\n\n// This directive is called during the $transclude call of the first `ngInclude` 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 ngInclude\n// is called.\nvar ngIncludeFillContentDirective = ['$compile',\n  function($compile) {\n    return {\n      restrict: 'ECA',\n      priority: -400,\n      require: 'ngInclude',\n      link: function(scope, $element, $attr, ctrl) {\n        if (/SVG/.test($element[0].toString())) {\n          // WebKit: https://bugs.webkit.org/show_bug.cgi?id=135698 --- SVG elements do not\n          // support innerHTML, so detect this here and try to generate the contents\n          // specially.\n          $element.empty();\n          $compile(jqLiteBuildFragment(ctrl.template, document).childNodes)(scope,\n              function namespaceAdaptedClone(clone) {\n            $element.append(clone);\n          }, {futureParentElement: $element});\n          return;\n        }\n\n        $element.html(ctrl.template);\n        $compile($element.contents())(scope);\n      }\n    };\n  }];\n\n/**\n * @ngdoc directive\n * @name ngInit\n * @restrict AC\n *\n * @description\n * The `ngInit` directive allows you to evaluate an expression in the\n * current scope.\n *\n * <div class=\"alert alert-error\">\n * The only appropriate use of `ngInit` is for aliasing special properties of\n * {@link ng.directive:ngRepeat `ngRepeat`}, as seen in the demo below. Besides this case, you\n * should use {@link guide/controller controllers} rather than `ngInit`\n * to initialize values on a scope.\n * </div>\n * <div class=\"alert alert-warning\">\n * **Note**: If you have assignment in `ngInit` along with {@link ng.$filter `$filter`}, make\n * sure you have parenthesis for correct precedence:\n * <pre class=\"prettyprint\">\n * `<div ng-init=\"test1 = (data | orderBy:'name')\"></div>`\n * </pre>\n * </div>\n *\n * @priority 450\n *\n * @element ANY\n * @param {expression} ngInit {@link guide/expression Expression} to eval.\n *\n * @example\n   <example module=\"initExample\">\n     <file name=\"index.html\">\n   <script>\n     angular.module('initExample', [])\n       .controller('ExampleController', ['$scope', function($scope) {\n         $scope.list = [['a', 'b'], ['c', 'd']];\n       }]);\n   </script>\n   <div ng-controller=\"ExampleController\">\n     <div ng-repeat=\"innerList in list\" ng-init=\"outerIndex = $index\">\n       <div ng-repeat=\"value in innerList\" ng-init=\"innerIndex = $index\">\n          <span class=\"example-init\">list[ {{outerIndex}} ][ {{innerIndex}} ] = {{value}};</span>\n       </div>\n     </div>\n   </div>\n     </file>\n     <file name=\"protractor.js\" type=\"protractor\">\n       it('should alias index positions', function() {\n         var elements = element.all(by.css('.example-init'));\n         expect(elements.get(0).getText()).toBe('list[ 0 ][ 0 ] = a;');\n         expect(elements.get(1).getText()).toBe('list[ 0 ][ 1 ] = b;');\n         expect(elements.get(2).getText()).toBe('list[ 1 ][ 0 ] = c;');\n         expect(elements.get(3).getText()).toBe('list[ 1 ][ 1 ] = d;');\n       });\n     </file>\n   </example>\n */\nvar ngInitDirective = ngDirective({\n  priority: 450,\n  compile: function() {\n    return {\n      pre: function(scope, element, attrs) {\n        scope.$eval(attrs.ngInit);\n      }\n    };\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ngList\n *\n * @description\n * Text input that converts between a delimited string and an array of strings. The default\n * delimiter is a comma followed by a space - equivalent to `ng-list=\", \"`. You can specify a custom\n * delimiter as the value of the `ngList` attribute - for example, `ng-list=\" | \"`.\n *\n * The behaviour of the directive is affected by the use of the `ngTrim` attribute.\n * * If `ngTrim` is set to `\"false\"` then whitespace around both the separator and each\n *   list item is respected. This implies that the user of the directive is responsible for\n *   dealing with whitespace but also allows you to use whitespace as a delimiter, such as a\n *   tab or newline character.\n * * Otherwise whitespace around the delimiter is ignored when splitting (although it is respected\n *   when joining the list items back together) and whitespace around each list item is stripped\n *   before it is added to the model.\n *\n * ### Example with Validation\n *\n * <example name=\"ngList-directive\" module=\"listExample\">\n *   <file name=\"app.js\">\n *      angular.module('listExample', [])\n *        .controller('ExampleController', ['$scope', function($scope) {\n *          $scope.names = ['morpheus', 'neo', 'trinity'];\n *        }]);\n *   </file>\n *   <file name=\"index.html\">\n *    <form name=\"myForm\" ng-controller=\"ExampleController\">\n *      List: <input name=\"namesInput\" ng-model=\"names\" ng-list required>\n *      <span class=\"error\" ng-show=\"myForm.namesInput.$error.required\">\n *        Required!</span>\n *      <br>\n *      <tt>names = {{names}}</tt><br/>\n *      <tt>myForm.namesInput.$valid = {{myForm.namesInput.$valid}}</tt><br/>\n *      <tt>myForm.namesInput.$error = {{myForm.namesInput.$error}}</tt><br/>\n *      <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n *      <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n *     </form>\n *   </file>\n *   <file name=\"protractor.js\" type=\"protractor\">\n *     var listInput = element(by.model('names'));\n *     var names = element(by.exactBinding('names'));\n *     var valid = element(by.binding('myForm.namesInput.$valid'));\n *     var error = element(by.css('span.error'));\n *\n *     it('should initialize to model', function() {\n *       expect(names.getText()).toContain('[\"morpheus\",\"neo\",\"trinity\"]');\n *       expect(valid.getText()).toContain('true');\n *       expect(error.getCssValue('display')).toBe('none');\n *     });\n *\n *     it('should be invalid if empty', function() {\n *       listInput.clear();\n *       listInput.sendKeys('');\n *\n *       expect(names.getText()).toContain('');\n *       expect(valid.getText()).toContain('false');\n *       expect(error.getCssValue('display')).not.toBe('none');\n *     });\n *   </file>\n * </example>\n *\n * ### Example - splitting on whitespace\n * <example name=\"ngList-directive-newlines\">\n *   <file name=\"index.html\">\n *    <textarea ng-model=\"list\" ng-list=\"&#10;\" ng-trim=\"false\"></textarea>\n *    <pre>{{ list | json }}</pre>\n *   </file>\n *   <file name=\"protractor.js\" type=\"protractor\">\n *     it(\"should split the text by newlines\", function() {\n *       var listInput = element(by.model('list'));\n *       var output = element(by.binding('list | json'));\n *       listInput.sendKeys('abc\\ndef\\nghi');\n *       expect(output.getText()).toContain('[\\n  \"abc\",\\n  \"def\",\\n  \"ghi\"\\n]');\n *     });\n *   </file>\n * </example>\n *\n * @element input\n * @param {string=} ngList optional delimiter that should be used to split the value.\n */\nvar ngListDirective = function() {\n  return {\n    restrict: 'A',\n    priority: 100,\n    require: 'ngModel',\n    link: function(scope, element, attr, ctrl) {\n      // We want to control whitespace trimming so we use this convoluted approach\n      // to access the ngList attribute, which doesn't pre-trim the attribute\n      var ngList = element.attr(attr.$attr.ngList) || ', ';\n      var trimValues = attr.ngTrim !== 'false';\n      var separator = trimValues ? trim(ngList) : ngList;\n\n      var parse = function(viewValue) {\n        // If the viewValue is invalid (say required but empty) it will be `undefined`\n        if (isUndefined(viewValue)) return;\n\n        var list = [];\n\n        if (viewValue) {\n          forEach(viewValue.split(separator), function(value) {\n            if (value) list.push(trimValues ? trim(value) : value);\n          });\n        }\n\n        return list;\n      };\n\n      ctrl.$parsers.push(parse);\n      ctrl.$formatters.push(function(value) {\n        if (isArray(value)) {\n          return value.join(ngList);\n        }\n\n        return undefined;\n      });\n\n      // Override the standard $isEmpty because an empty array means the input is empty.\n      ctrl.$isEmpty = function(value) {\n        return !value || !value.length;\n      };\n    }\n  };\n};\n\n/* global VALID_CLASS: true,\n  INVALID_CLASS: true,\n  PRISTINE_CLASS: true,\n  DIRTY_CLASS: true,\n  UNTOUCHED_CLASS: true,\n  TOUCHED_CLASS: true,\n*/\n\nvar VALID_CLASS = 'ng-valid',\n    INVALID_CLASS = 'ng-invalid',\n    PRISTINE_CLASS = 'ng-pristine',\n    DIRTY_CLASS = 'ng-dirty',\n    UNTOUCHED_CLASS = 'ng-untouched',\n    TOUCHED_CLASS = 'ng-touched',\n    PENDING_CLASS = 'ng-pending';\n\n\nvar $ngModelMinErr = new minErr('ngModel');\n\n/**\n * @ngdoc type\n * @name ngModel.NgModelController\n *\n * @property {string} $viewValue Actual string value in the view.\n * @property {*} $modelValue The value in the model that the control is bound to.\n * @property {Array.<Function>} $parsers Array of functions to execute, as a pipeline, whenever\n       the control reads value from the DOM. The functions are called in array order, each passing\n       its return value through to the next. The last return value is forwarded to the\n       {@link ngModel.NgModelController#$validators `$validators`} collection.\n\nParsers are used to sanitize / convert the {@link ngModel.NgModelController#$viewValue\n`$viewValue`}.\n\nReturning `undefined` from a parser means a parse error occurred. In that case,\nno {@link ngModel.NgModelController#$validators `$validators`} will run and the `ngModel`\nwill be set to `undefined` unless {@link ngModelOptions `ngModelOptions.allowInvalid`}\nis set to `true`. The parse error is stored in `ngModel.$error.parse`.\n\n *\n * @property {Array.<Function>} $formatters Array of functions to execute, as a pipeline, whenever\n       the model value changes. The functions are called in reverse array order, each passing the value through to the\n       next. The last return value is used as the actual DOM value.\n       Used to format / convert values for display in the control.\n * ```js\n * function formatter(value) {\n *   if (value) {\n *     return value.toUpperCase();\n *   }\n * }\n * ngModel.$formatters.push(formatter);\n * ```\n *\n * @property {Object.<string, function>} $validators A collection of validators that are applied\n *      whenever the model value changes. The key value within the object refers to the name of the\n *      validator while the function refers to the validation operation. The validation operation is\n *      provided with the model value as an argument and must return a true or false value depending\n *      on the response of that validation.\n *\n * ```js\n * ngModel.$validators.validCharacters = function(modelValue, viewValue) {\n *   var value = modelValue || viewValue;\n *   return /[0-9]+/.test(value) &&\n *          /[a-z]+/.test(value) &&\n *          /[A-Z]+/.test(value) &&\n *          /\\W+/.test(value);\n * };\n * ```\n *\n * @property {Object.<string, function>} $asyncValidators A collection of validations that are expected to\n *      perform an asynchronous validation (e.g. a HTTP request). The validation function that is provided\n *      is expected to return a promise when it is run during the model validation process. Once the promise\n *      is delivered then the validation status will be set to true when fulfilled and false when rejected.\n *      When the asynchronous validators are triggered, each of the validators will run in parallel and the model\n *      value will only be updated once all validators have been fulfilled. As long as an asynchronous validator\n *      is unfulfilled, its key will be added to the controllers `$pending` property. Also, all asynchronous validators\n *      will only run once all synchronous validators have passed.\n *\n * Please note that if $http is used then it is important that the server returns a success HTTP response code\n * in order to fulfill the validation and a status level of `4xx` in order to reject the validation.\n *\n * ```js\n * ngModel.$asyncValidators.uniqueUsername = function(modelValue, viewValue) {\n *   var value = modelValue || viewValue;\n *\n *   // Lookup user by username\n *   return $http.get('/api/users/' + value).\n *      then(function resolved() {\n *        //username exists, this means validation fails\n *        return $q.reject('exists');\n *      }, function rejected() {\n *        //username does not exist, therefore this validation passes\n *        return true;\n *      });\n * };\n * ```\n *\n * @property {Array.<Function>} $viewChangeListeners Array of functions to execute whenever the\n *     view value has changed. It is called with no arguments, and its return value is ignored.\n *     This can be used in place of additional $watches against the model value.\n *\n * @property {Object} $error An object hash with all failing validator ids as keys.\n * @property {Object} $pending An object hash with all pending validator ids as keys.\n *\n * @property {boolean} $untouched True if control has not lost focus yet.\n * @property {boolean} $touched True if control has lost focus.\n * @property {boolean} $pristine True if user has not interacted with the control yet.\n * @property {boolean} $dirty True if user has already interacted with the control.\n * @property {boolean} $valid True if there is no error.\n * @property {boolean} $invalid True if at least one error on the control.\n * @property {string} $name The name attribute of the control.\n *\n * @description\n *\n * `NgModelController` provides API for the {@link ngModel `ngModel`} directive.\n * The controller contains services for data-binding, validation, CSS updates, and value formatting\n * and parsing. It purposefully does not contain any logic which deals with DOM rendering or\n * listening to DOM events.\n * Such DOM related logic should be provided by other directives which make use of\n * `NgModelController` for data-binding to control elements.\n * Angular provides this DOM logic for most {@link input `input`} elements.\n * At the end of this page you can find a {@link ngModel.NgModelController#custom-control-example\n * custom control example} that uses `ngModelController` to bind to `contenteditable` elements.\n *\n * @example\n * ### Custom Control Example\n * This example shows how to use `NgModelController` with a custom control to achieve\n * data-binding. Notice how different directives (`contenteditable`, `ng-model`, and `required`)\n * collaborate together to achieve the desired result.\n *\n * Note that `contenteditable` is an HTML5 attribute, which tells the browser to let the element\n * contents be edited in place by the user.  This will not work on older browsers.\n *\n * We are using the {@link ng.service:$sce $sce} service here and include the {@link ngSanitize $sanitize}\n * module to automatically remove \"bad\" content like inline event listener (e.g. `<span onclick=\"...\">`).\n * However, as we are using `$sce` the model can still decide to provide unsafe content if it marks\n * that content using the `$sce` service.\n *\n * <example name=\"NgModelController\" module=\"customControl\" deps=\"angular-sanitize.js\">\n    <file name=\"style.css\">\n      [contenteditable] {\n        border: 1px solid black;\n        background-color: white;\n        min-height: 20px;\n      }\n\n      .ng-invalid {\n        border: 1px solid red;\n      }\n\n    </file>\n    <file name=\"script.js\">\n      angular.module('customControl', ['ngSanitize']).\n        directive('contenteditable', ['$sce', function($sce) {\n          return {\n            restrict: 'A', // only activate on element attribute\n            require: '?ngModel', // get a hold of NgModelController\n            link: function(scope, element, attrs, ngModel) {\n              if (!ngModel) return; // do nothing if no ng-model\n\n              // Specify how UI should be updated\n              ngModel.$render = function() {\n                element.html($sce.getTrustedHtml(ngModel.$viewValue || ''));\n              };\n\n              // Listen for change events to enable binding\n              element.on('blur keyup change', function() {\n                scope.$evalAsync(read);\n              });\n              read(); // initialize\n\n              // Write data to the model\n              function read() {\n                var html = element.html();\n                // When we clear the content editable the browser leaves a <br> behind\n                // If strip-br attribute is provided then we strip this out\n                if ( attrs.stripBr && html == '<br>' ) {\n                  html = '';\n                }\n                ngModel.$setViewValue(html);\n              }\n            }\n          };\n        }]);\n    </file>\n    <file name=\"index.html\">\n      <form name=\"myForm\">\n       <div contenteditable\n            name=\"myWidget\" ng-model=\"userContent\"\n            strip-br=\"true\"\n            required>Change me!</div>\n        <span ng-show=\"myForm.myWidget.$error.required\">Required!</span>\n       <hr>\n       <textarea ng-model=\"userContent\"></textarea>\n      </form>\n    </file>\n    <file name=\"protractor.js\" type=\"protractor\">\n    it('should data-bind and become invalid', function() {\n      if (browser.params.browser == 'safari' || browser.params.browser == 'firefox') {\n        // SafariDriver can't handle contenteditable\n        // and Firefox driver can't clear contenteditables very well\n        return;\n      }\n      var contentEditable = element(by.css('[contenteditable]'));\n      var content = 'Change me!';\n\n      expect(contentEditable.getText()).toEqual(content);\n\n      contentEditable.clear();\n      contentEditable.sendKeys(protractor.Key.BACK_SPACE);\n      expect(contentEditable.getText()).toEqual('');\n      expect(contentEditable.getAttribute('class')).toMatch(/ng-invalid-required/);\n    });\n    </file>\n * </example>\n *\n *\n */\nvar NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$parse', '$animate', '$timeout', '$rootScope', '$q', '$interpolate',\n    function($scope, $exceptionHandler, $attr, $element, $parse, $animate, $timeout, $rootScope, $q, $interpolate) {\n  this.$viewValue = Number.NaN;\n  this.$modelValue = Number.NaN;\n  this.$$rawModelValue = undefined; // stores the parsed modelValue / model set from scope regardless of validity.\n  this.$validators = {};\n  this.$asyncValidators = {};\n  this.$parsers = [];\n  this.$formatters = [];\n  this.$viewChangeListeners = [];\n  this.$untouched = true;\n  this.$touched = false;\n  this.$pristine = true;\n  this.$dirty = false;\n  this.$valid = true;\n  this.$invalid = false;\n  this.$error = {}; // keep invalid keys here\n  this.$$success = {}; // keep valid keys here\n  this.$pending = undefined; // keep pending keys here\n  this.$name = $interpolate($attr.name || '', false)($scope);\n\n\n  var parsedNgModel = $parse($attr.ngModel),\n      parsedNgModelAssign = parsedNgModel.assign,\n      ngModelGet = parsedNgModel,\n      ngModelSet = parsedNgModelAssign,\n      pendingDebounce = null,\n      ctrl = this;\n\n  this.$$setOptions = function(options) {\n    ctrl.$options = options;\n    if (options && options.getterSetter) {\n      var invokeModelGetter = $parse($attr.ngModel + '()'),\n          invokeModelSetter = $parse($attr.ngModel + '($$$p)');\n\n      ngModelGet = function($scope) {\n        var modelValue = parsedNgModel($scope);\n        if (isFunction(modelValue)) {\n          modelValue = invokeModelGetter($scope);\n        }\n        return modelValue;\n      };\n      ngModelSet = function($scope, newValue) {\n        if (isFunction(parsedNgModel($scope))) {\n          invokeModelSetter($scope, {$$$p: ctrl.$modelValue});\n        } else {\n          parsedNgModelAssign($scope, ctrl.$modelValue);\n        }\n      };\n    } else if (!parsedNgModel.assign) {\n      throw $ngModelMinErr('nonassign', \"Expression '{0}' is non-assignable. Element: {1}\",\n          $attr.ngModel, startingTag($element));\n    }\n  };\n\n  /**\n   * @ngdoc method\n   * @name ngModel.NgModelController#$render\n   *\n   * @description\n   * Called when the view needs to be updated. It is expected that the user of the ng-model\n   * directive will implement this method.\n   *\n   * The `$render()` method is invoked in the following situations:\n   *\n   * * `$rollbackViewValue()` is called.  If we are rolling back the view value to the last\n   *   committed value then `$render()` is called to update the input control.\n   * * The value referenced by `ng-model` is changed programmatically and both the `$modelValue` and\n   *   the `$viewValue` are different to last time.\n   *\n   * Since `ng-model` does not do a deep watch, `$render()` is only invoked if the values of\n   * `$modelValue` and `$viewValue` are actually different to their previous value. If `$modelValue`\n   * or `$viewValue` are objects (rather than a string or number) then `$render()` will not be\n   * invoked if you only change a property on the objects.\n   */\n  this.$render = noop;\n\n  /**\n   * @ngdoc method\n   * @name ngModel.NgModelController#$isEmpty\n   *\n   * @description\n   * This is called when we need to determine if the value of an input is empty.\n   *\n   * For instance, the required directive does this to work out if the input has data or not.\n   *\n   * The default `$isEmpty` function checks whether the value is `undefined`, `''`, `null` or `NaN`.\n   *\n   * You can override this for input directives whose concept of being empty is different to the\n   * default. The `checkboxInputType` directive does this because in its case a value of `false`\n   * implies empty.\n   *\n   * @param {*} value The value of the input to check for emptiness.\n   * @returns {boolean} True if `value` is \"empty\".\n   */\n  this.$isEmpty = function(value) {\n    return isUndefined(value) || value === '' || value === null || value !== value;\n  };\n\n  var parentForm = $element.inheritedData('$formController') || nullFormCtrl,\n      currentValidationRunId = 0;\n\n  /**\n   * @ngdoc method\n   * @name ngModel.NgModelController#$setValidity\n   *\n   * @description\n   * Change the validity state, and notify the form.\n   *\n   * This method can be called within $parsers/$formatters or a custom validation implementation.\n   * However, in most cases it should be sufficient to use the `ngModel.$validators` and\n   * `ngModel.$asyncValidators` collections which will call `$setValidity` automatically.\n   *\n   * @param {string} validationErrorKey Name of the validator. The `validationErrorKey` will be assigned\n   *        to either `$error[validationErrorKey]` or `$pending[validationErrorKey]`\n   *        (for unfulfilled `$asyncValidators`), so that it is available for data-binding.\n   *        The `validationErrorKey` should be in camelCase and will get converted into dash-case\n   *        for class name. Example: `myError` will result in `ng-valid-my-error` and `ng-invalid-my-error`\n   *        class and can be bound to as  `{{someForm.someControl.$error.myError}}` .\n   * @param {boolean} isValid Whether the current state is valid (true), invalid (false), pending (undefined),\n   *                          or skipped (null). Pending is used for unfulfilled `$asyncValidators`.\n   *                          Skipped is used by Angular when validators do not run because of parse errors and\n   *                          when `$asyncValidators` do not run because any of the `$validators` failed.\n   */\n  addSetValidityMethod({\n    ctrl: this,\n    $element: $element,\n    set: function(object, property) {\n      object[property] = true;\n    },\n    unset: function(object, property) {\n      delete object[property];\n    },\n    parentForm: parentForm,\n    $animate: $animate\n  });\n\n  /**\n   * @ngdoc method\n   * @name ngModel.NgModelController#$setPristine\n   *\n   * @description\n   * Sets the control to its pristine state.\n   *\n   * This method can be called to remove the `ng-dirty` class and set the control to its pristine\n   * state (`ng-pristine` class). A model is considered to be pristine when the control\n   * has not been changed from when first compiled.\n   */\n  this.$setPristine = function() {\n    ctrl.$dirty = false;\n    ctrl.$pristine = true;\n    $animate.removeClass($element, DIRTY_CLASS);\n    $animate.addClass($element, PRISTINE_CLASS);\n  };\n\n  /**\n   * @ngdoc method\n   * @name ngModel.NgModelController#$setDirty\n   *\n   * @description\n   * Sets the control to its dirty state.\n   *\n   * This method can be called to remove the `ng-pristine` class and set the control to its dirty\n   * state (`ng-dirty` class). A model is considered to be dirty when the control has been changed\n   * from when first compiled.\n   */\n  this.$setDirty = function() {\n    ctrl.$dirty = true;\n    ctrl.$pristine = false;\n    $animate.removeClass($element, PRISTINE_CLASS);\n    $animate.addClass($element, DIRTY_CLASS);\n    parentForm.$setDirty();\n  };\n\n  /**\n   * @ngdoc method\n   * @name ngModel.NgModelController#$setUntouched\n   *\n   * @description\n   * Sets the control to its untouched state.\n   *\n   * This method can be called to remove the `ng-touched` class and set the control to its\n   * untouched state (`ng-untouched` class). Upon compilation, a model is set as untouched\n   * by default, however this function can be used to restore that state if the model has\n   * already been touched by the user.\n   */\n  this.$setUntouched = function() {\n    ctrl.$touched = false;\n    ctrl.$untouched = true;\n    $animate.setClass($element, UNTOUCHED_CLASS, TOUCHED_CLASS);\n  };\n\n  /**\n   * @ngdoc method\n   * @name ngModel.NgModelController#$setTouched\n   *\n   * @description\n   * Sets the control to its touched state.\n   *\n   * This method can be called to remove the `ng-untouched` class and set the control to its\n   * touched state (`ng-touched` class). A model is considered to be touched when the user has\n   * first focused the control element and then shifted focus away from the control (blur event).\n   */\n  this.$setTouched = function() {\n    ctrl.$touched = true;\n    ctrl.$untouched = false;\n    $animate.setClass($element, TOUCHED_CLASS, UNTOUCHED_CLASS);\n  };\n\n  /**\n   * @ngdoc method\n   * @name ngModel.NgModelController#$rollbackViewValue\n   *\n   * @description\n   * Cancel an update and reset the input element's value to prevent an update to the `$modelValue`,\n   * which may be caused by a pending debounced event or because the input is waiting for a some\n   * future event.\n   *\n   * If you have an input that uses `ng-model-options` to set up debounced events or events such\n   * as blur you can have a situation where there is a period when the `$viewValue`\n   * is out of synch with the ngModel's `$modelValue`.\n   *\n   * In this case, you can run into difficulties if you try to update the ngModel's `$modelValue`\n   * programmatically before these debounced/future events have resolved/occurred, because Angular's\n   * dirty checking mechanism is not able to tell whether the model has actually changed or not.\n   *\n   * The `$rollbackViewValue()` method should be called before programmatically changing the model of an\n   * input which may have such events pending. This is important in order to make sure that the\n   * input field will be updated with the new model value and any pending operations are cancelled.\n   *\n   * <example name=\"ng-model-cancel-update\" module=\"cancel-update-example\">\n   *   <file name=\"app.js\">\n   *     angular.module('cancel-update-example', [])\n   *\n   *     .controller('CancelUpdateController', ['$scope', function($scope) {\n   *       $scope.resetWithCancel = function(e) {\n   *         if (e.keyCode == 27) {\n   *           $scope.myForm.myInput1.$rollbackViewValue();\n   *           $scope.myValue = '';\n   *         }\n   *       };\n   *       $scope.resetWithoutCancel = function(e) {\n   *         if (e.keyCode == 27) {\n   *           $scope.myValue = '';\n   *         }\n   *       };\n   *     }]);\n   *   </file>\n   *   <file name=\"index.html\">\n   *     <div ng-controller=\"CancelUpdateController\">\n   *       <p>Try typing something in each input.  See that the model only updates when you\n   *          blur off the input.\n   *        </p>\n   *        <p>Now see what happens if you start typing then press the Escape key</p>\n   *\n   *       <form name=\"myForm\" ng-model-options=\"{ updateOn: 'blur' }\">\n   *         <p>With $rollbackViewValue()</p>\n   *         <input name=\"myInput1\" ng-model=\"myValue\" ng-keydown=\"resetWithCancel($event)\"><br/>\n   *         myValue: \"{{ myValue }}\"\n   *\n   *         <p>Without $rollbackViewValue()</p>\n   *         <input name=\"myInput2\" ng-model=\"myValue\" ng-keydown=\"resetWithoutCancel($event)\"><br/>\n   *         myValue: \"{{ myValue }}\"\n   *       </form>\n   *     </div>\n   *   </file>\n   * </example>\n   */\n  this.$rollbackViewValue = function() {\n    $timeout.cancel(pendingDebounce);\n    ctrl.$viewValue = ctrl.$$lastCommittedViewValue;\n    ctrl.$render();\n  };\n\n  /**\n   * @ngdoc method\n   * @name ngModel.NgModelController#$validate\n   *\n   * @description\n   * Runs each of the registered validators (first synchronous validators and then\n   * asynchronous validators).\n   * If the validity changes to invalid, the model will be set to `undefined`,\n   * unless {@link ngModelOptions `ngModelOptions.allowInvalid`} is `true`.\n   * If the validity changes to valid, it will set the model to the last available valid\n   * modelValue, i.e. either the last parsed value or the last value set from the scope.\n   */\n  this.$validate = function() {\n    // ignore $validate before model is initialized\n    if (isNumber(ctrl.$modelValue) && isNaN(ctrl.$modelValue)) {\n      return;\n    }\n\n    var viewValue = ctrl.$$lastCommittedViewValue;\n    // Note: we use the $$rawModelValue as $modelValue might have been\n    // set to undefined during a view -> model update that found validation\n    // errors. We can't parse the view here, since that could change\n    // the model although neither viewValue nor the model on the scope changed\n    var modelValue = ctrl.$$rawModelValue;\n\n    // Check if the there's a parse error, so we don't unset it accidentially\n    var parserName = ctrl.$$parserName || 'parse';\n    var parserValid = ctrl.$error[parserName] ? false : undefined;\n\n    var prevValid = ctrl.$valid;\n    var prevModelValue = ctrl.$modelValue;\n\n    var allowInvalid = ctrl.$options && ctrl.$options.allowInvalid;\n\n    ctrl.$$runValidators(parserValid, modelValue, viewValue, function(allValid) {\n      // If there was no change in validity, don't update the model\n      // This prevents changing an invalid modelValue to undefined\n      if (!allowInvalid && prevValid !== allValid) {\n        // Note: Don't check ctrl.$valid here, as we could have\n        // external validators (e.g. calculated on the server),\n        // that just call $setValidity and need the model value\n        // to calculate their validity.\n        ctrl.$modelValue = allValid ? modelValue : undefined;\n\n        if (ctrl.$modelValue !== prevModelValue) {\n          ctrl.$$writeModelToScope();\n        }\n      }\n    });\n\n  };\n\n  this.$$runValidators = function(parseValid, modelValue, viewValue, doneCallback) {\n    currentValidationRunId++;\n    var localValidationRunId = currentValidationRunId;\n\n    // check parser error\n    if (!processParseErrors(parseValid)) {\n      validationDone(false);\n      return;\n    }\n    if (!processSyncValidators()) {\n      validationDone(false);\n      return;\n    }\n    processAsyncValidators();\n\n    function processParseErrors(parseValid) {\n      var errorKey = ctrl.$$parserName || 'parse';\n      if (parseValid === undefined) {\n        setValidity(errorKey, null);\n      } else {\n        setValidity(errorKey, parseValid);\n        if (!parseValid) {\n          forEach(ctrl.$validators, function(v, name) {\n            setValidity(name, null);\n          });\n          forEach(ctrl.$asyncValidators, function(v, name) {\n            setValidity(name, null);\n          });\n          return false;\n        }\n      }\n      return true;\n    }\n\n    function processSyncValidators() {\n      var syncValidatorsValid = true;\n      forEach(ctrl.$validators, function(validator, name) {\n        var result = validator(modelValue, viewValue);\n        syncValidatorsValid = syncValidatorsValid && result;\n        setValidity(name, result);\n      });\n      if (!syncValidatorsValid) {\n        forEach(ctrl.$asyncValidators, function(v, name) {\n          setValidity(name, null);\n        });\n        return false;\n      }\n      return true;\n    }\n\n    function processAsyncValidators() {\n      var validatorPromises = [];\n      var allValid = true;\n      forEach(ctrl.$asyncValidators, function(validator, name) {\n        var promise = validator(modelValue, viewValue);\n        if (!isPromiseLike(promise)) {\n          throw $ngModelMinErr(\"$asyncValidators\",\n            \"Expected asynchronous validator to return a promise but got '{0}' instead.\", promise);\n        }\n        setValidity(name, undefined);\n        validatorPromises.push(promise.then(function() {\n          setValidity(name, true);\n        }, function(error) {\n          allValid = false;\n          setValidity(name, false);\n        }));\n      });\n      if (!validatorPromises.length) {\n        validationDone(true);\n      } else {\n        $q.all(validatorPromises).then(function() {\n          validationDone(allValid);\n        }, noop);\n      }\n    }\n\n    function setValidity(name, isValid) {\n      if (localValidationRunId === currentValidationRunId) {\n        ctrl.$setValidity(name, isValid);\n      }\n    }\n\n    function validationDone(allValid) {\n      if (localValidationRunId === currentValidationRunId) {\n\n        doneCallback(allValid);\n      }\n    }\n  };\n\n  /**\n   * @ngdoc method\n   * @name ngModel.NgModelController#$commitViewValue\n   *\n   * @description\n   * Commit a pending update to the `$modelValue`.\n   *\n   * Updates may be pending by a debounced event or because the input is waiting for a some future\n   * event defined in `ng-model-options`. this method is rarely needed as `NgModelController`\n   * usually handles calling this in response to input events.\n   */\n  this.$commitViewValue = function() {\n    var viewValue = ctrl.$viewValue;\n\n    $timeout.cancel(pendingDebounce);\n\n    // If the view value has not changed then we should just exit, except in the case where there is\n    // a native validator on the element. In this case the validation state may have changed even though\n    // the viewValue has stayed empty.\n    if (ctrl.$$lastCommittedViewValue === viewValue && (viewValue !== '' || !ctrl.$$hasNativeValidators)) {\n      return;\n    }\n    ctrl.$$lastCommittedViewValue = viewValue;\n\n    // change to dirty\n    if (ctrl.$pristine) {\n      this.$setDirty();\n    }\n    this.$$parseAndValidate();\n  };\n\n  this.$$parseAndValidate = function() {\n    var viewValue = ctrl.$$lastCommittedViewValue;\n    var modelValue = viewValue;\n    var parserValid = isUndefined(modelValue) ? undefined : true;\n\n    if (parserValid) {\n      for (var i = 0; i < ctrl.$parsers.length; i++) {\n        modelValue = ctrl.$parsers[i](modelValue);\n        if (isUndefined(modelValue)) {\n          parserValid = false;\n          break;\n        }\n      }\n    }\n    if (isNumber(ctrl.$modelValue) && isNaN(ctrl.$modelValue)) {\n      // ctrl.$modelValue has not been touched yet...\n      ctrl.$modelValue = ngModelGet($scope);\n    }\n    var prevModelValue = ctrl.$modelValue;\n    var allowInvalid = ctrl.$options && ctrl.$options.allowInvalid;\n    ctrl.$$rawModelValue = modelValue;\n\n    if (allowInvalid) {\n      ctrl.$modelValue = modelValue;\n      writeToModelIfNeeded();\n    }\n\n    // Pass the $$lastCommittedViewValue here, because the cached viewValue might be out of date.\n    // This can happen if e.g. $setViewValue is called from inside a parser\n    ctrl.$$runValidators(parserValid, modelValue, ctrl.$$lastCommittedViewValue, function(allValid) {\n      if (!allowInvalid) {\n        // Note: Don't check ctrl.$valid here, as we could have\n        // external validators (e.g. calculated on the server),\n        // that just call $setValidity and need the model value\n        // to calculate their validity.\n        ctrl.$modelValue = allValid ? modelValue : undefined;\n        writeToModelIfNeeded();\n      }\n    });\n\n    function writeToModelIfNeeded() {\n      if (ctrl.$modelValue !== prevModelValue) {\n        ctrl.$$writeModelToScope();\n      }\n    }\n  };\n\n  this.$$writeModelToScope = function() {\n    ngModelSet($scope, ctrl.$modelValue);\n    forEach(ctrl.$viewChangeListeners, function(listener) {\n      try {\n        listener();\n      } catch (e) {\n        $exceptionHandler(e);\n      }\n    });\n  };\n\n  /**\n   * @ngdoc method\n   * @name ngModel.NgModelController#$setViewValue\n   *\n   * @description\n   * Update the view value.\n   *\n   * This method should be called when an input directive want to change the view value; typically,\n   * this is done from within a DOM event handler.\n   *\n   * For example {@link ng.directive:input input} calls it when the value of the input changes and\n   * {@link ng.directive:select select} calls it when an option is selected.\n   *\n   * If the new `value` is an object (rather than a string or a number), we should make a copy of the\n   * object before passing it to `$setViewValue`.  This is because `ngModel` does not perform a deep\n   * watch of objects, it only looks for a change of identity. If you only change the property of\n   * the object then ngModel will not realise that the object has changed and will not invoke the\n   * `$parsers` and `$validators` pipelines.\n   *\n   * For this reason, you should not change properties of the copy once it has been passed to\n   * `$setViewValue`. Otherwise you may cause the model value on the scope to change incorrectly.\n   *\n   * When this method is called, the new `value` will be staged for committing through the `$parsers`\n   * and `$validators` pipelines. If there are no special {@link ngModelOptions} specified then the staged\n   * value sent directly for processing, finally to be applied to `$modelValue` and then the\n   * **expression** specified in the `ng-model` attribute.\n   *\n   * Lastly, all the registered change listeners, in the `$viewChangeListeners` list, are called.\n   *\n   * In case the {@link ng.directive:ngModelOptions ngModelOptions} directive is used with `updateOn`\n   * and the `default` trigger is not listed, all those actions will remain pending until one of the\n   * `updateOn` events is triggered on the DOM element.\n   * All these actions will be debounced if the {@link ng.directive:ngModelOptions ngModelOptions}\n   * directive is used with a custom debounce for this particular event.\n   *\n   * Note that calling this function does not trigger a `$digest`.\n   *\n   * @param {string} value Value from the view.\n   * @param {string} trigger Event that triggered the update.\n   */\n  this.$setViewValue = function(value, trigger) {\n    ctrl.$viewValue = value;\n    if (!ctrl.$options || ctrl.$options.updateOnDefault) {\n      ctrl.$$debounceViewValueCommit(trigger);\n    }\n  };\n\n  this.$$debounceViewValueCommit = function(trigger) {\n    var debounceDelay = 0,\n        options = ctrl.$options,\n        debounce;\n\n    if (options && isDefined(options.debounce)) {\n      debounce = options.debounce;\n      if (isNumber(debounce)) {\n        debounceDelay = debounce;\n      } else if (isNumber(debounce[trigger])) {\n        debounceDelay = debounce[trigger];\n      } else if (isNumber(debounce['default'])) {\n        debounceDelay = debounce['default'];\n      }\n    }\n\n    $timeout.cancel(pendingDebounce);\n    if (debounceDelay) {\n      pendingDebounce = $timeout(function() {\n        ctrl.$commitViewValue();\n      }, debounceDelay);\n    } else if ($rootScope.$$phase) {\n      ctrl.$commitViewValue();\n    } else {\n      $scope.$apply(function() {\n        ctrl.$commitViewValue();\n      });\n    }\n  };\n\n  // model -> value\n  // Note: we cannot use a normal scope.$watch as we want to detect the following:\n  // 1. scope value is 'a'\n  // 2. user enters 'b'\n  // 3. ng-change kicks in and reverts scope value to 'a'\n  //    -> scope value did not change since the last digest as\n  //       ng-change executes in apply phase\n  // 4. view should be changed back to 'a'\n  $scope.$watch(function ngModelWatch() {\n    var modelValue = ngModelGet($scope);\n\n    // if scope model value and ngModel value are out of sync\n    // TODO(perf): why not move this to the action fn?\n    if (modelValue !== ctrl.$modelValue) {\n      ctrl.$modelValue = ctrl.$$rawModelValue = modelValue;\n\n      var formatters = ctrl.$formatters,\n          idx = formatters.length;\n\n      var viewValue = modelValue;\n      while (idx--) {\n        viewValue = formatters[idx](viewValue);\n      }\n      if (ctrl.$viewValue !== viewValue) {\n        ctrl.$viewValue = ctrl.$$lastCommittedViewValue = viewValue;\n        ctrl.$render();\n\n        ctrl.$$runValidators(undefined, modelValue, viewValue, noop);\n      }\n    }\n\n    return modelValue;\n  });\n}];\n\n\n/**\n * @ngdoc directive\n * @name ngModel\n *\n * @element input\n * @priority 1\n *\n * @description\n * The `ngModel` directive binds an `input`,`select`, `textarea` (or custom form control) to a\n * property on the scope using {@link ngModel.NgModelController NgModelController},\n * which is created and exposed by this directive.\n *\n * `ngModel` is responsible for:\n *\n * - Binding the view into the model, which other directives such as `input`, `textarea` or `select`\n *   require.\n * - Providing validation behavior (i.e. required, number, email, url).\n * - Keeping the state of the control (valid/invalid, dirty/pristine, touched/untouched, validation errors).\n * - Setting related css classes on the element (`ng-valid`, `ng-invalid`, `ng-dirty`, `ng-pristine`, `ng-touched`, `ng-untouched`) including animations.\n * - Registering the control with its parent {@link ng.directive:form form}.\n *\n * Note: `ngModel` will try to bind to the property given by evaluating the expression on the\n * current scope. If the property doesn't already exist on this scope, it will be created\n * implicitly and added to the scope.\n *\n * For best practices on using `ngModel`, see:\n *\n *  - [Understanding Scopes](https://github.com/angular/angular.js/wiki/Understanding-Scopes)\n *\n * For basic examples, how to use `ngModel`, see:\n *\n *  - {@link ng.directive:input input}\n *    - {@link input[text] text}\n *    - {@link input[checkbox] checkbox}\n *    - {@link input[radio] radio}\n *    - {@link input[number] number}\n *    - {@link input[email] email}\n *    - {@link input[url] url}\n *    - {@link input[date] date}\n *    - {@link input[datetime-local] datetime-local}\n *    - {@link input[time] time}\n *    - {@link input[month] month}\n *    - {@link input[week] week}\n *  - {@link ng.directive:select select}\n *  - {@link ng.directive:textarea textarea}\n *\n * # CSS classes\n * The following CSS classes are added and removed on the associated input/select/textarea element\n * depending on the validity of the model.\n *\n *  - `ng-valid`: the model is valid\n *  - `ng-invalid`: the model is invalid\n *  - `ng-valid-[key]`: for each valid key added by `$setValidity`\n *  - `ng-invalid-[key]`: for each invalid key added by `$setValidity`\n *  - `ng-pristine`: the control hasn't been interacted with yet\n *  - `ng-dirty`: the control has been interacted with\n *  - `ng-touched`: the control has been blurred\n *  - `ng-untouched`: the control hasn't been blurred\n *  - `ng-pending`: any `$asyncValidators` are unfulfilled\n *\n * Keep in mind that ngAnimate can detect each of these classes when added and removed.\n *\n * ## Animation Hooks\n *\n * Animations within models are triggered when any of the associated CSS classes are added and removed\n * on the input element which is attached to the model. These classes are: `.ng-pristine`, `.ng-dirty`,\n * `.ng-invalid` and `.ng-valid` as well as any other validations that are performed on the model itself.\n * The animations that are triggered within ngModel are similar to how they work in ngClass and\n * animations can be hooked into using CSS transitions, keyframes as well as JS animations.\n *\n * The following example shows a simple way to utilize CSS transitions to style an input element\n * that has been rendered as invalid after it has been validated:\n *\n * <pre>\n * //be sure to include ngAnimate as a module to hook into more\n * //advanced animations\n * .my-input {\n *   transition:0.5s linear all;\n *   background: white;\n * }\n * .my-input.ng-invalid {\n *   background: red;\n *   color:white;\n * }\n * </pre>\n *\n * @example\n * <example deps=\"angular-animate.js\" animations=\"true\" fixBase=\"true\" module=\"inputExample\">\n     <file name=\"index.html\">\n       <script>\n        angular.module('inputExample', [])\n          .controller('ExampleController', ['$scope', function($scope) {\n            $scope.val = '1';\n          }]);\n       </script>\n       <style>\n         .my-input {\n           -webkit-transition:all linear 0.5s;\n           transition:all linear 0.5s;\n           background: transparent;\n         }\n         .my-input.ng-invalid {\n           color:white;\n           background: red;\n         }\n       </style>\n       Update input to see transitions when valid/invalid.\n       Integer is a valid value.\n       <form name=\"testForm\" ng-controller=\"ExampleController\">\n         <input ng-model=\"val\" ng-pattern=\"/^\\d+$/\" name=\"anim\" class=\"my-input\" />\n       </form>\n     </file>\n * </example>\n *\n * ## Binding to a getter/setter\n *\n * Sometimes it's helpful to bind `ngModel` to a getter/setter function.  A getter/setter is a\n * function that returns a representation of the model when called with zero arguments, and sets\n * the internal state of a model when called with an argument. It's sometimes useful to use this\n * for models that have an internal representation that's different than what the model exposes\n * to the view.\n *\n * <div class=\"alert alert-success\">\n * **Best Practice:** It's best to keep getters fast because Angular is likely to call them more\n * frequently than other parts of your code.\n * </div>\n *\n * You use this behavior by adding `ng-model-options=\"{ getterSetter: true }\"` to an element that\n * has `ng-model` attached to it. You can also add `ng-model-options=\"{ getterSetter: true }\"` to\n * a `<form>`, which will enable this behavior for all `<input>`s within it. See\n * {@link ng.directive:ngModelOptions `ngModelOptions`} for more.\n *\n * The following example shows how to use `ngModel` with a getter/setter:\n *\n * @example\n * <example name=\"ngModel-getter-setter\" module=\"getterSetterExample\">\n     <file name=\"index.html\">\n       <div ng-controller=\"ExampleController\">\n         <form name=\"userForm\">\n           Name:\n           <input type=\"text\" name=\"userName\"\n                  ng-model=\"user.name\"\n                  ng-model-options=\"{ getterSetter: true }\" />\n         </form>\n         <pre>user.name = <span ng-bind=\"user.name()\"></span></pre>\n       </div>\n     </file>\n     <file name=\"app.js\">\n       angular.module('getterSetterExample', [])\n         .controller('ExampleController', ['$scope', function($scope) {\n           var _name = 'Brian';\n           $scope.user = {\n             name: function(newName) {\n               if (angular.isDefined(newName)) {\n                 _name = newName;\n               }\n               return _name;\n             }\n           };\n         }]);\n     </file>\n * </example>\n */\nvar ngModelDirective = ['$rootScope', function($rootScope) {\n  return {\n    restrict: 'A',\n    require: ['ngModel', '^?form', '^?ngModelOptions'],\n    controller: NgModelController,\n    // Prelink needs to run before any input directive\n    // so that we can set the NgModelOptions in NgModelController\n    // before anyone else uses it.\n    priority: 1,\n    compile: function ngModelCompile(element) {\n      // Setup initial state of the control\n      element.addClass(PRISTINE_CLASS).addClass(UNTOUCHED_CLASS).addClass(VALID_CLASS);\n\n      return {\n        pre: function ngModelPreLink(scope, element, attr, ctrls) {\n          var modelCtrl = ctrls[0],\n              formCtrl = ctrls[1] || nullFormCtrl;\n\n          modelCtrl.$$setOptions(ctrls[2] && ctrls[2].$options);\n\n          // notify others, especially parent forms\n          formCtrl.$addControl(modelCtrl);\n\n          attr.$observe('name', function(newValue) {\n            if (modelCtrl.$name !== newValue) {\n              formCtrl.$$renameControl(modelCtrl, newValue);\n            }\n          });\n\n          scope.$on('$destroy', function() {\n            formCtrl.$removeControl(modelCtrl);\n          });\n        },\n        post: function ngModelPostLink(scope, element, attr, ctrls) {\n          var modelCtrl = ctrls[0];\n          if (modelCtrl.$options && modelCtrl.$options.updateOn) {\n            element.on(modelCtrl.$options.updateOn, function(ev) {\n              modelCtrl.$$debounceViewValueCommit(ev && ev.type);\n            });\n          }\n\n          element.on('blur', function(ev) {\n            if (modelCtrl.$touched) return;\n\n            if ($rootScope.$$phase) {\n              scope.$evalAsync(modelCtrl.$setTouched);\n            } else {\n              scope.$apply(modelCtrl.$setTouched);\n            }\n          });\n        }\n      };\n    }\n  };\n}];\n\nvar DEFAULT_REGEXP = /(\\s+|^)default(\\s+|$)/;\n\n/**\n * @ngdoc directive\n * @name ngModelOptions\n *\n * @description\n * Allows tuning how model updates are done. Using `ngModelOptions` you can specify a custom list of\n * events that will trigger a model update and/or a debouncing delay so that the actual update only\n * takes place when a timer expires; this timer will be reset after another change takes place.\n *\n * Given the nature of `ngModelOptions`, the value displayed inside input fields in the view might\n * be different than the value in the actual model. This means that if you update the model you\n * should also invoke {@link ngModel.NgModelController `$rollbackViewValue`} on the relevant input field in\n * order to make sure it is synchronized with the model and that any debounced action is canceled.\n *\n * The easiest way to reference the control's {@link ngModel.NgModelController `$rollbackViewValue`}\n * method is by making sure the input is placed inside a form that has a `name` attribute. This is\n * important because `form` controllers are published to the related scope under the name in their\n * `name` attribute.\n *\n * Any pending changes will take place immediately when an enclosing form is submitted via the\n * `submit` event. Note that `ngClick` events will occur before the model is updated. Use `ngSubmit`\n * to have access to the updated model.\n *\n * `ngModelOptions` has an effect on the element it's declared on and its descendants.\n *\n * @param {Object} ngModelOptions options to apply to the current model. Valid keys are:\n *   - `updateOn`: string specifying which event should the input be bound to. You can set several\n *     events using an space delimited list. There is a special event called `default` that\n *     matches the default events belonging of the control.\n *   - `debounce`: integer value which contains the debounce model update value in milliseconds. A\n *     value of 0 triggers an immediate update. If an object is supplied instead, you can specify a\n *     custom value for each event. For example:\n *     `ng-model-options=\"{ updateOn: 'default blur', debounce: {'default': 500, 'blur': 0} }\"`\n *   - `allowInvalid`: boolean value which indicates that the model can be set with values that did\n *     not validate correctly instead of the default behavior of setting the model to undefined.\n *   - `getterSetter`: boolean value which determines whether or not to treat functions bound to\n       `ngModel` as getters/setters.\n *   - `timezone`: Defines the timezone to be used to read/write the `Date` instance in the model for\n *     `<input type=\"date\">`, `<input type=\"time\">`, ... . Right now, the only supported value is `'UTC'`,\n *     otherwise the default timezone of the browser will be used.\n *\n * @example\n\n  The following example shows how to override immediate updates. Changes on the inputs within the\n  form will update the model only when the control loses focus (blur event). If `escape` key is\n  pressed while the input field is focused, the value is reset to the value in the current model.\n\n  <example name=\"ngModelOptions-directive-blur\" module=\"optionsExample\">\n    <file name=\"index.html\">\n      <div ng-controller=\"ExampleController\">\n        <form name=\"userForm\">\n          Name:\n          <input type=\"text\" name=\"userName\"\n                 ng-model=\"user.name\"\n                 ng-model-options=\"{ updateOn: 'blur' }\"\n                 ng-keyup=\"cancel($event)\" /><br />\n\n          Other data:\n          <input type=\"text\" ng-model=\"user.data\" /><br />\n        </form>\n        <pre>user.name = <span ng-bind=\"user.name\"></span></pre>\n      </div>\n    </file>\n    <file name=\"app.js\">\n      angular.module('optionsExample', [])\n        .controller('ExampleController', ['$scope', function($scope) {\n          $scope.user = { name: 'say', data: '' };\n\n          $scope.cancel = function(e) {\n            if (e.keyCode == 27) {\n              $scope.userForm.userName.$rollbackViewValue();\n            }\n          };\n        }]);\n    </file>\n    <file name=\"protractor.js\" type=\"protractor\">\n      var model = element(by.binding('user.name'));\n      var input = element(by.model('user.name'));\n      var other = element(by.model('user.data'));\n\n      it('should allow custom events', function() {\n        input.sendKeys(' hello');\n        input.click();\n        expect(model.getText()).toEqual('say');\n        other.click();\n        expect(model.getText()).toEqual('say hello');\n      });\n\n      it('should $rollbackViewValue when model changes', function() {\n        input.sendKeys(' hello');\n        expect(input.getAttribute('value')).toEqual('say hello');\n        input.sendKeys(protractor.Key.ESCAPE);\n        expect(input.getAttribute('value')).toEqual('say');\n        other.click();\n        expect(model.getText()).toEqual('say');\n      });\n    </file>\n  </example>\n\n  This one shows how to debounce model changes. Model will be updated only 1 sec after last change.\n  If the `Clear` button is pressed, any debounced action is canceled and the value becomes empty.\n\n  <example name=\"ngModelOptions-directive-debounce\" module=\"optionsExample\">\n    <file name=\"index.html\">\n      <div ng-controller=\"ExampleController\">\n        <form name=\"userForm\">\n          Name:\n          <input type=\"text\" name=\"userName\"\n                 ng-model=\"user.name\"\n                 ng-model-options=\"{ debounce: 1000 }\" />\n          <button ng-click=\"userForm.userName.$rollbackViewValue(); user.name=''\">Clear</button><br />\n        </form>\n        <pre>user.name = <span ng-bind=\"user.name\"></span></pre>\n      </div>\n    </file>\n    <file name=\"app.js\">\n      angular.module('optionsExample', [])\n        .controller('ExampleController', ['$scope', function($scope) {\n          $scope.user = { name: 'say' };\n        }]);\n    </file>\n  </example>\n\n  This one shows how to bind to getter/setters:\n\n  <example name=\"ngModelOptions-directive-getter-setter\" module=\"getterSetterExample\">\n    <file name=\"index.html\">\n      <div ng-controller=\"ExampleController\">\n        <form name=\"userForm\">\n          Name:\n          <input type=\"text\" name=\"userName\"\n                 ng-model=\"user.name\"\n                 ng-model-options=\"{ getterSetter: true }\" />\n        </form>\n        <pre>user.name = <span ng-bind=\"user.name()\"></span></pre>\n      </div>\n    </file>\n    <file name=\"app.js\">\n      angular.module('getterSetterExample', [])\n        .controller('ExampleController', ['$scope', function($scope) {\n          var _name = 'Brian';\n          $scope.user = {\n            name: function(newName) {\n              return angular.isDefined(newName) ? (_name = newName) : _name;\n            }\n          };\n        }]);\n    </file>\n  </example>\n */\nvar ngModelOptionsDirective = function() {\n  return {\n    restrict: 'A',\n    controller: ['$scope', '$attrs', function($scope, $attrs) {\n      var that = this;\n      this.$options = $scope.$eval($attrs.ngModelOptions);\n      // Allow adding/overriding bound events\n      if (this.$options.updateOn !== undefined) {\n        this.$options.updateOnDefault = false;\n        // extract \"default\" pseudo-event from list of events that can trigger a model update\n        this.$options.updateOn = trim(this.$options.updateOn.replace(DEFAULT_REGEXP, function() {\n          that.$options.updateOnDefault = true;\n          return ' ';\n        }));\n      } else {\n        this.$options.updateOnDefault = true;\n      }\n    }]\n  };\n};\n\n\n\n// helper methods\nfunction addSetValidityMethod(context) {\n  var ctrl = context.ctrl,\n      $element = context.$element,\n      classCache = {},\n      set = context.set,\n      unset = context.unset,\n      parentForm = context.parentForm,\n      $animate = context.$animate;\n\n  classCache[INVALID_CLASS] = !(classCache[VALID_CLASS] = $element.hasClass(VALID_CLASS));\n\n  ctrl.$setValidity = setValidity;\n\n  function setValidity(validationErrorKey, state, controller) {\n    if (state === undefined) {\n      createAndSet('$pending', validationErrorKey, controller);\n    } else {\n      unsetAndCleanup('$pending', validationErrorKey, controller);\n    }\n    if (!isBoolean(state)) {\n      unset(ctrl.$error, validationErrorKey, controller);\n      unset(ctrl.$$success, validationErrorKey, controller);\n    } else {\n      if (state) {\n        unset(ctrl.$error, validationErrorKey, controller);\n        set(ctrl.$$success, validationErrorKey, controller);\n      } else {\n        set(ctrl.$error, validationErrorKey, controller);\n        unset(ctrl.$$success, validationErrorKey, controller);\n      }\n    }\n    if (ctrl.$pending) {\n      cachedToggleClass(PENDING_CLASS, true);\n      ctrl.$valid = ctrl.$invalid = undefined;\n      toggleValidationCss('', null);\n    } else {\n      cachedToggleClass(PENDING_CLASS, false);\n      ctrl.$valid = isObjectEmpty(ctrl.$error);\n      ctrl.$invalid = !ctrl.$valid;\n      toggleValidationCss('', ctrl.$valid);\n    }\n\n    // re-read the state as the set/unset methods could have\n    // combined state in ctrl.$error[validationError] (used for forms),\n    // where setting/unsetting only increments/decrements the value,\n    // and does not replace it.\n    var combinedState;\n    if (ctrl.$pending && ctrl.$pending[validationErrorKey]) {\n      combinedState = undefined;\n    } else if (ctrl.$error[validationErrorKey]) {\n      combinedState = false;\n    } else if (ctrl.$$success[validationErrorKey]) {\n      combinedState = true;\n    } else {\n      combinedState = null;\n    }\n\n    toggleValidationCss(validationErrorKey, combinedState);\n    parentForm.$setValidity(validationErrorKey, combinedState, ctrl);\n  }\n\n  function createAndSet(name, value, controller) {\n    if (!ctrl[name]) {\n      ctrl[name] = {};\n    }\n    set(ctrl[name], value, controller);\n  }\n\n  function unsetAndCleanup(name, value, controller) {\n    if (ctrl[name]) {\n      unset(ctrl[name], value, controller);\n    }\n    if (isObjectEmpty(ctrl[name])) {\n      ctrl[name] = undefined;\n    }\n  }\n\n  function cachedToggleClass(className, switchValue) {\n    if (switchValue && !classCache[className]) {\n      $animate.addClass($element, className);\n      classCache[className] = true;\n    } else if (!switchValue && classCache[className]) {\n      $animate.removeClass($element, className);\n      classCache[className] = false;\n    }\n  }\n\n  function toggleValidationCss(validationErrorKey, isValid) {\n    validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : '';\n\n    cachedToggleClass(VALID_CLASS + validationErrorKey, isValid === true);\n    cachedToggleClass(INVALID_CLASS + validationErrorKey, isValid === false);\n  }\n}\n\nfunction isObjectEmpty(obj) {\n  if (obj) {\n    for (var prop in obj) {\n      return false;\n    }\n  }\n  return true;\n}\n\n/**\n * @ngdoc directive\n * @name ngNonBindable\n * @restrict AC\n * @priority 1000\n *\n * @description\n * The `ngNonBindable` directive tells Angular not to compile or bind the contents of the current\n * DOM element. This is useful if the element contains what appears to be Angular directives and\n * bindings but which should be ignored by Angular. This could be the case if you have a site that\n * displays snippets of code, for instance.\n *\n * @element ANY\n *\n * @example\n * In this example there are two locations where a simple interpolation binding (`{{}}`) is present,\n * but the one wrapped in `ngNonBindable` is left alone.\n *\n * @example\n    <example>\n      <file name=\"index.html\">\n        <div>Normal: {{1 + 2}}</div>\n        <div ng-non-bindable>Ignored: {{1 + 2}}</div>\n      </file>\n      <file name=\"protractor.js\" type=\"protractor\">\n       it('should check ng-non-bindable', function() {\n         expect(element(by.binding('1 + 2')).getText()).toContain('3');\n         expect(element.all(by.css('div')).last().getText()).toMatch(/1 \\+ 2/);\n       });\n      </file>\n    </example>\n */\nvar ngNonBindableDirective = ngDirective({ terminal: true, priority: 1000 });\n\n/**\n * @ngdoc directive\n * @name ngPluralize\n * @restrict EA\n *\n * @description\n * `ngPluralize` is a directive that displays messages according to en-US localization rules.\n * These rules are bundled with angular.js, but can be overridden\n * (see {@link guide/i18n Angular i18n} dev guide). You configure ngPluralize directive\n * by specifying the mappings between\n * [plural categories](http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html)\n * and the strings to be displayed.\n *\n * # Plural categories and explicit number rules\n * There are two\n * [plural categories](http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html)\n * in Angular's default en-US locale: \"one\" and \"other\".\n *\n * While a plural category may match many numbers (for example, in en-US locale, \"other\" can match\n * any number that is not 1), an explicit number rule can only match one number. For example, the\n * explicit number rule for \"3\" matches the number 3. There are examples of plural categories\n * and explicit number rules throughout the rest of this documentation.\n *\n * # Configuring ngPluralize\n * You configure ngPluralize by providing 2 attributes: `count` and `when`.\n * You can also provide an optional attribute, `offset`.\n *\n * The value of the `count` attribute can be either a string or an {@link guide/expression\n * Angular expression}; these are evaluated on the current scope for its bound value.\n *\n * The `when` attribute specifies the mappings between plural categories and the actual\n * string to be displayed. The value of the attribute should be a JSON object.\n *\n * The following example shows how to configure ngPluralize:\n *\n * ```html\n * <ng-pluralize count=\"personCount\"\n                 when=\"{'0': 'Nobody is viewing.',\n *                      'one': '1 person is viewing.',\n *                      'other': '{} people are viewing.'}\">\n * </ng-pluralize>\n *```\n *\n * In the example, `\"0: Nobody is viewing.\"` is an explicit number rule. If you did not\n * specify this rule, 0 would be matched to the \"other\" category and \"0 people are viewing\"\n * would be shown instead of \"Nobody is viewing\". You can specify an explicit number rule for\n * other numbers, for example 12, so that instead of showing \"12 people are viewing\", you can\n * show \"a dozen people are viewing\".\n *\n * You can use a set of closed braces (`{}`) as a placeholder for the number that you want substituted\n * into pluralized strings. In the previous example, Angular will replace `{}` with\n * <span ng-non-bindable>`{{personCount}}`</span>. The closed braces `{}` is a placeholder\n * for <span ng-non-bindable>{{numberExpression}}</span>.\n *\n * # Configuring ngPluralize with offset\n * The `offset` attribute allows further customization of pluralized text, which can result in\n * a better user experience. For example, instead of the message \"4 people are viewing this document\",\n * you might display \"John, Kate and 2 others are viewing this document\".\n * The offset attribute allows you to offset a number by any desired value.\n * Let's take a look at an example:\n *\n * ```html\n * <ng-pluralize count=\"personCount\" offset=2\n *               when=\"{'0': 'Nobody is viewing.',\n *                      '1': '{{person1}} is viewing.',\n *                      '2': '{{person1}} and {{person2}} are viewing.',\n *                      'one': '{{person1}}, {{person2}} and one other person are viewing.',\n *                      'other': '{{person1}}, {{person2}} and {} other people are viewing.'}\">\n * </ng-pluralize>\n * ```\n *\n * Notice that we are still using two plural categories(one, other), but we added\n * three explicit number rules 0, 1 and 2.\n * When one person, perhaps John, views the document, \"John is viewing\" will be shown.\n * When three people view the document, no explicit number rule is found, so\n * an offset of 2 is taken off 3, and Angular uses 1 to decide the plural category.\n * In this case, plural category 'one' is matched and \"John, Mary and one other person are viewing\"\n * is shown.\n *\n * Note that when you specify offsets, you must provide explicit number rules for\n * numbers from 0 up to and including the offset. If you use an offset of 3, for example,\n * you must provide explicit number rules for 0, 1, 2 and 3. You must also provide plural strings for\n * plural categories \"one\" and \"other\".\n *\n * @param {string|expression} count The variable to be bound to.\n * @param {string} when The mapping between plural category to its corresponding strings.\n * @param {number=} offset Offset to deduct from the total number.\n *\n * @example\n    <example module=\"pluralizeExample\">\n      <file name=\"index.html\">\n        <script>\n          angular.module('pluralizeExample', [])\n            .controller('ExampleController', ['$scope', function($scope) {\n              $scope.person1 = 'Igor';\n              $scope.person2 = 'Misko';\n              $scope.personCount = 1;\n            }]);\n        </script>\n        <div ng-controller=\"ExampleController\">\n          Person 1:<input type=\"text\" ng-model=\"person1\" value=\"Igor\" /><br/>\n          Person 2:<input type=\"text\" ng-model=\"person2\" value=\"Misko\" /><br/>\n          Number of People:<input type=\"text\" ng-model=\"personCount\" value=\"1\" /><br/>\n\n          <!--- Example with simple pluralization rules for en locale --->\n          Without Offset:\n          <ng-pluralize count=\"personCount\"\n                        when=\"{'0': 'Nobody is viewing.',\n                               'one': '1 person is viewing.',\n                               'other': '{} people are viewing.'}\">\n          </ng-pluralize><br>\n\n          <!--- Example with offset --->\n          With Offset(2):\n          <ng-pluralize count=\"personCount\" offset=2\n                        when=\"{'0': 'Nobody is viewing.',\n                               '1': '{{person1}} is viewing.',\n                               '2': '{{person1}} and {{person2}} are viewing.',\n                               'one': '{{person1}}, {{person2}} and one other person are viewing.',\n                               'other': '{{person1}}, {{person2}} and {} other people are viewing.'}\">\n          </ng-pluralize>\n        </div>\n      </file>\n      <file name=\"protractor.js\" type=\"protractor\">\n        it('should show correct pluralized string', function() {\n          var withoutOffset = element.all(by.css('ng-pluralize')).get(0);\n          var withOffset = element.all(by.css('ng-pluralize')).get(1);\n          var countInput = element(by.model('personCount'));\n\n          expect(withoutOffset.getText()).toEqual('1 person is viewing.');\n          expect(withOffset.getText()).toEqual('Igor is viewing.');\n\n          countInput.clear();\n          countInput.sendKeys('0');\n\n          expect(withoutOffset.getText()).toEqual('Nobody is viewing.');\n          expect(withOffset.getText()).toEqual('Nobody is viewing.');\n\n          countInput.clear();\n          countInput.sendKeys('2');\n\n          expect(withoutOffset.getText()).toEqual('2 people are viewing.');\n          expect(withOffset.getText()).toEqual('Igor and Misko are viewing.');\n\n          countInput.clear();\n          countInput.sendKeys('3');\n\n          expect(withoutOffset.getText()).toEqual('3 people are viewing.');\n          expect(withOffset.getText()).toEqual('Igor, Misko and one other person are viewing.');\n\n          countInput.clear();\n          countInput.sendKeys('4');\n\n          expect(withoutOffset.getText()).toEqual('4 people are viewing.');\n          expect(withOffset.getText()).toEqual('Igor, Misko and 2 other people are viewing.');\n        });\n        it('should show data-bound names', function() {\n          var withOffset = element.all(by.css('ng-pluralize')).get(1);\n          var personCount = element(by.model('personCount'));\n          var person1 = element(by.model('person1'));\n          var person2 = element(by.model('person2'));\n          personCount.clear();\n          personCount.sendKeys('4');\n          person1.clear();\n          person1.sendKeys('Di');\n          person2.clear();\n          person2.sendKeys('Vojta');\n          expect(withOffset.getText()).toEqual('Di, Vojta and 2 other people are viewing.');\n        });\n      </file>\n    </example>\n */\nvar ngPluralizeDirective = ['$locale', '$interpolate', function($locale, $interpolate) {\n  var BRACE = /{}/g,\n      IS_WHEN = /^when(Minus)?(.+)$/;\n\n  return {\n    restrict: 'EA',\n    link: function(scope, element, attr) {\n      var numberExp = attr.count,\n          whenExp = attr.$attr.when && element.attr(attr.$attr.when), // we have {{}} in attrs\n          offset = attr.offset || 0,\n          whens = scope.$eval(whenExp) || {},\n          whensExpFns = {},\n          startSymbol = $interpolate.startSymbol(),\n          endSymbol = $interpolate.endSymbol(),\n          braceReplacement = startSymbol + numberExp + '-' + offset + endSymbol,\n          watchRemover = angular.noop,\n          lastCount;\n\n      forEach(attr, function(expression, attributeName) {\n        var tmpMatch = IS_WHEN.exec(attributeName);\n        if (tmpMatch) {\n          var whenKey = (tmpMatch[1] ? '-' : '') + lowercase(tmpMatch[2]);\n          whens[whenKey] = element.attr(attr.$attr[attributeName]);\n        }\n      });\n      forEach(whens, function(expression, key) {\n        whensExpFns[key] = $interpolate(expression.replace(BRACE, braceReplacement));\n\n      });\n\n      scope.$watch(numberExp, function ngPluralizeWatchAction(newVal) {\n        var count = parseFloat(newVal);\n        var countIsNaN = isNaN(count);\n\n        if (!countIsNaN && !(count in whens)) {\n          // If an explicit number rule such as 1, 2, 3... is defined, just use it.\n          // Otherwise, check it against pluralization rules in $locale service.\n          count = $locale.pluralCat(count - offset);\n        }\n\n        // If both `count` and `lastCount` are NaN, we don't need to re-register a watch.\n        // In JS `NaN !== NaN`, so we have to exlicitly check.\n        if ((count !== lastCount) && !(countIsNaN && isNaN(lastCount))) {\n          watchRemover();\n          watchRemover = scope.$watch(whensExpFns[count], updateElementText);\n          lastCount = count;\n        }\n      });\n\n      function updateElementText(newText) {\n        element.text(newText || '');\n      }\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ngRepeat\n *\n * @description\n * The `ngRepeat` directive instantiates a template once per item from a collection. Each template\n * instance gets its own scope, where the given loop variable is set to the current collection item,\n * and `$index` is set to the item index or key.\n *\n * Special properties are exposed on the local scope of each template instance, including:\n *\n * | Variable  | Type            | Details                                                                     |\n * |-----------|-----------------|-----------------------------------------------------------------------------|\n * | `$index`  | {@type number}  | iterator offset of the repeated element (0..length-1)                       |\n * | `$first`  | {@type boolean} | true if the repeated element is first in the iterator.                      |\n * | `$middle` | {@type boolean} | true if the repeated element is between the first and last in the iterator. |\n * | `$last`   | {@type boolean} | true if the repeated element is last in the iterator.                       |\n * | `$even`   | {@type boolean} | true if the iterator position `$index` is even (otherwise false).           |\n * | `$odd`    | {@type boolean} | true if the iterator position `$index` is odd (otherwise false).            |\n *\n * Creating aliases for these properties is possible with {@link ng.directive:ngInit `ngInit`}.\n * This may be useful when, for instance, nesting ngRepeats.\n *\n * # Iterating over object properties\n *\n * It is possible to get `ngRepeat` to iterate over the properties of an object using the following\n * syntax:\n *\n * ```js\n * <div ng-repeat=\"(key, value) in myObj\"> ... </div>\n * ```\n *\n * You need to be aware that the JavaScript specification does not define what order\n * it will return the keys for an object. In order to have a guaranteed deterministic order\n * for the keys, Angular versions up to and including 1.3 **sort the keys alphabetically**.\n *\n * If this is not desired, the recommended workaround is to convert your object into an array\n * that is sorted into the order that you prefer before providing it to `ngRepeat`.  You could\n * do this with a filter such as [toArrayFilter](http://ngmodules.org/modules/angular-toArrayFilter)\n * or implement a `$watch` on the object yourself.\n *\n * In version 1.4 we will remove the sorting, since it seems that browsers generally follow the\n * strategy of providing keys in the order in which they were defined, although there are exceptions\n * when keys are deleted and reinstated.\n *\n *\n * # Special repeat start and end points\n * To repeat a series of elements instead of just one parent element, ngRepeat (as well as other ng directives) supports extending\n * the range of the repeater by defining explicit start and end points by using **ng-repeat-start** and **ng-repeat-end** respectively.\n * The **ng-repeat-start** directive works the same as **ng-repeat**, but will repeat all the HTML code (including the tag it's defined on)\n * up to and including the ending HTML tag where **ng-repeat-end** is placed.\n *\n * The example below makes use of this feature:\n * ```html\n *   <header ng-repeat-start=\"item in items\">\n *     Header {{ item }}\n *   </header>\n *   <div class=\"body\">\n *     Body {{ item }}\n *   </div>\n *   <footer ng-repeat-end>\n *     Footer {{ item }}\n *   </footer>\n * ```\n *\n * And with an input of {@type ['A','B']} for the items variable in the example above, the output will evaluate to:\n * ```html\n *   <header>\n *     Header A\n *   </header>\n *   <div class=\"body\">\n *     Body A\n *   </div>\n *   <footer>\n *     Footer A\n *   </footer>\n *   <header>\n *     Header B\n *   </header>\n *   <div class=\"body\">\n *     Body B\n *   </div>\n *   <footer>\n *     Footer B\n *   </footer>\n * ```\n *\n * The custom start and end points for ngRepeat also support all other HTML directive syntax flavors provided in AngularJS (such\n * as **data-ng-repeat-start**, **x-ng-repeat-start** and **ng:repeat-start**).\n *\n * @animations\n * **.enter** - when a new item is added to the list or when an item is revealed after a filter\n *\n * **.leave** - when an item is removed from the list or when an item is filtered out\n *\n * **.move** - when an adjacent item is filtered out causing a reorder or when the item contents are reordered\n *\n * @element ANY\n * @scope\n * @priority 1000\n * @param {repeat_expression} ngRepeat The expression indicating how to enumerate a collection. These\n *   formats are currently supported:\n *\n *   * `variable in expression` – where variable is the user defined loop variable and `expression`\n *     is a scope expression giving the collection to enumerate.\n *\n *     For example: `album in artist.albums`.\n *\n *   * `(key, value) in expression` – where `key` and `value` can be any user defined identifiers,\n *     and `expression` is the scope expression giving the collection to enumerate.\n *\n *     For example: `(name, age) in {'adam':10, 'amalie':12}`.\n *\n *   * `variable in expression track by tracking_expression` – You can also provide an optional tracking function\n *     which can be used to associate the objects in the collection with the DOM elements. If no tracking function\n *     is specified the ng-repeat associates elements by identity in the collection. It is an error to have\n *     more than one tracking function to resolve to the same key. (This would mean that two distinct objects are\n *     mapped to the same DOM element, which is not possible.)  Filters should be applied to the expression,\n *     before specifying a tracking expression.\n *\n *     For example: `item in items` is equivalent to `item in items track by $id(item)`. This implies that the DOM elements\n *     will be associated by item identity in the array.\n *\n *     For example: `item in items track by $id(item)`. A built in `$id()` function can be used to assign a unique\n *     `$$hashKey` property to each item in the array. This property is then used as a key to associated DOM elements\n *     with the corresponding item in the array by identity. Moving the same object in array would move the DOM\n *     element in the same way in the DOM.\n *\n *     For example: `item in items track by item.id` is a typical pattern when the items come from the database. In this\n *     case the object identity does not matter. Two objects are considered equivalent as long as their `id`\n *     property is same.\n *\n *     For example: `item in items | filter:searchText track by item.id` is a pattern that might be used to apply a filter\n *     to items in conjunction with a tracking expression.\n *\n *   * `variable in expression as alias_expression` – You can also provide an optional alias expression which will then store the\n *     intermediate results of the repeater after the filters have been applied. Typically this is used to render a special message\n *     when a filter is active on the repeater, but the filtered result set is empty.\n *\n *     For example: `item in items | filter:x as results` will store the fragment of the repeated items as `results`, but only after\n *     the items have been processed through the filter.\n *\n * @example\n * This example initializes the scope to a list of names and\n * then uses `ngRepeat` to display every person:\n  <example module=\"ngAnimate\" deps=\"angular-animate.js\" animations=\"true\">\n    <file name=\"index.html\">\n      <div ng-init=\"friends = [\n        {name:'John', age:25, gender:'boy'},\n        {name:'Jessie', age:30, gender:'girl'},\n        {name:'Johanna', age:28, gender:'girl'},\n        {name:'Joy', age:15, gender:'girl'},\n        {name:'Mary', age:28, gender:'girl'},\n        {name:'Peter', age:95, gender:'boy'},\n        {name:'Sebastian', age:50, gender:'boy'},\n        {name:'Erika', age:27, gender:'girl'},\n        {name:'Patrick', age:40, gender:'boy'},\n        {name:'Samantha', age:60, gender:'girl'}\n      ]\">\n        I have {{friends.length}} friends. They are:\n        <input type=\"search\" ng-model=\"q\" placeholder=\"filter friends...\" />\n        <ul class=\"example-animate-container\">\n          <li class=\"animate-repeat\" ng-repeat=\"friend in friends | filter:q as results\">\n            [{{$index + 1}}] {{friend.name}} who is {{friend.age}} years old.\n          </li>\n          <li class=\"animate-repeat\" ng-if=\"results.length == 0\">\n            <strong>No results found...</strong>\n          </li>\n        </ul>\n      </div>\n    </file>\n    <file name=\"animations.css\">\n      .example-animate-container {\n        background:white;\n        border:1px solid black;\n        list-style:none;\n        margin:0;\n        padding:0 10px;\n      }\n\n      .animate-repeat {\n        line-height:40px;\n        list-style:none;\n        box-sizing:border-box;\n      }\n\n      .animate-repeat.ng-move,\n      .animate-repeat.ng-enter,\n      .animate-repeat.ng-leave {\n        -webkit-transition:all linear 0.5s;\n        transition:all linear 0.5s;\n      }\n\n      .animate-repeat.ng-leave.ng-leave-active,\n      .animate-repeat.ng-move,\n      .animate-repeat.ng-enter {\n        opacity:0;\n        max-height:0;\n      }\n\n      .animate-repeat.ng-leave,\n      .animate-repeat.ng-move.ng-move-active,\n      .animate-repeat.ng-enter.ng-enter-active {\n        opacity:1;\n        max-height:40px;\n      }\n    </file>\n    <file name=\"protractor.js\" type=\"protractor\">\n      var friends = element.all(by.repeater('friend in friends'));\n\n      it('should render initial data set', function() {\n        expect(friends.count()).toBe(10);\n        expect(friends.get(0).getText()).toEqual('[1] John who is 25 years old.');\n        expect(friends.get(1).getText()).toEqual('[2] Jessie who is 30 years old.');\n        expect(friends.last().getText()).toEqual('[10] Samantha who is 60 years old.');\n        expect(element(by.binding('friends.length')).getText())\n            .toMatch(\"I have 10 friends. They are:\");\n      });\n\n       it('should update repeater when filter predicate changes', function() {\n         expect(friends.count()).toBe(10);\n\n         element(by.model('q')).sendKeys('ma');\n\n         expect(friends.count()).toBe(2);\n         expect(friends.get(0).getText()).toEqual('[1] Mary who is 28 years old.');\n         expect(friends.last().getText()).toEqual('[2] Samantha who is 60 years old.');\n       });\n      </file>\n    </example>\n */\nvar ngRepeatDirective = ['$parse', '$animate', function($parse, $animate) {\n  var NG_REMOVED = '$$NG_REMOVED';\n  var ngRepeatMinErr = minErr('ngRepeat');\n\n  var updateScope = function(scope, index, valueIdentifier, value, keyIdentifier, key, arrayLength) {\n    // TODO(perf): generate setters to shave off ~40ms or 1-1.5%\n    scope[valueIdentifier] = value;\n    if (keyIdentifier) scope[keyIdentifier] = key;\n    scope.$index = index;\n    scope.$first = (index === 0);\n    scope.$last = (index === (arrayLength - 1));\n    scope.$middle = !(scope.$first || scope.$last);\n    // jshint bitwise: false\n    scope.$odd = !(scope.$even = (index&1) === 0);\n    // jshint bitwise: true\n  };\n\n  var getBlockStart = function(block) {\n    return block.clone[0];\n  };\n\n  var getBlockEnd = function(block) {\n    return block.clone[block.clone.length - 1];\n  };\n\n\n  return {\n    restrict: 'A',\n    multiElement: true,\n    transclude: 'element',\n    priority: 1000,\n    terminal: true,\n    $$tlb: true,\n    compile: function ngRepeatCompile($element, $attr) {\n      var expression = $attr.ngRepeat;\n      var ngRepeatEndComment = document.createComment(' end ngRepeat: ' + expression + ' ');\n\n      var match = expression.match(/^\\s*([\\s\\S]+?)\\s+in\\s+([\\s\\S]+?)(?:\\s+as\\s+([\\s\\S]+?))?(?:\\s+track\\s+by\\s+([\\s\\S]+?))?\\s*$/);\n\n      if (!match) {\n        throw ngRepeatMinErr('iexp', \"Expected expression in form of '_item_ in _collection_[ track by _id_]' but got '{0}'.\",\n            expression);\n      }\n\n      var lhs = match[1];\n      var rhs = match[2];\n      var aliasAs = match[3];\n      var trackByExp = match[4];\n\n      match = lhs.match(/^(?:(\\s*[\\$\\w]+)|\\(\\s*([\\$\\w]+)\\s*,\\s*([\\$\\w]+)\\s*\\))$/);\n\n      if (!match) {\n        throw ngRepeatMinErr('iidexp', \"'_item_' in '_item_ in _collection_' should be an identifier or '(_key_, _value_)' expression, but got '{0}'.\",\n            lhs);\n      }\n      var valueIdentifier = match[3] || match[1];\n      var keyIdentifier = match[2];\n\n      if (aliasAs && (!/^[$a-zA-Z_][$a-zA-Z0-9_]*$/.test(aliasAs) ||\n          /^(null|undefined|this|\\$index|\\$first|\\$middle|\\$last|\\$even|\\$odd|\\$parent|\\$root|\\$id)$/.test(aliasAs))) {\n        throw ngRepeatMinErr('badident', \"alias '{0}' is invalid --- must be a valid JS identifier which is not a reserved name.\",\n          aliasAs);\n      }\n\n      var trackByExpGetter, trackByIdExpFn, trackByIdArrayFn, trackByIdObjFn;\n      var hashFnLocals = {$id: hashKey};\n\n      if (trackByExp) {\n        trackByExpGetter = $parse(trackByExp);\n      } else {\n        trackByIdArrayFn = function(key, value) {\n          return hashKey(value);\n        };\n        trackByIdObjFn = function(key) {\n          return key;\n        };\n      }\n\n      return function ngRepeatLink($scope, $element, $attr, ctrl, $transclude) {\n\n        if (trackByExpGetter) {\n          trackByIdExpFn = function(key, value, index) {\n            // assign key, value, and $index to the locals so that they can be used in hash functions\n            if (keyIdentifier) hashFnLocals[keyIdentifier] = key;\n            hashFnLocals[valueIdentifier] = value;\n            hashFnLocals.$index = index;\n            return trackByExpGetter($scope, hashFnLocals);\n          };\n        }\n\n        // Store a list of elements from previous run. This is a hash where key is the item from the\n        // iterator, and the value is objects with following properties.\n        //   - scope: bound scope\n        //   - element: previous element.\n        //   - index: position\n        //\n        // We are using no-proto object so that we don't need to guard against inherited props via\n        // hasOwnProperty.\n        var lastBlockMap = createMap();\n\n        //watch props\n        $scope.$watchCollection(rhs, function ngRepeatAction(collection) {\n          var index, length,\n              previousNode = $element[0],     // node that cloned nodes should be inserted after\n                                              // initialized to the comment node anchor\n              nextNode,\n              // Same as lastBlockMap but it has the current state. It will become the\n              // lastBlockMap on the next iteration.\n              nextBlockMap = createMap(),\n              collectionLength,\n              key, value, // key/value of iteration\n              trackById,\n              trackByIdFn,\n              collectionKeys,\n              block,       // last object information {scope, element, id}\n              nextBlockOrder,\n              elementsToRemove;\n\n          if (aliasAs) {\n            $scope[aliasAs] = collection;\n          }\n\n          if (isArrayLike(collection)) {\n            collectionKeys = collection;\n            trackByIdFn = trackByIdExpFn || trackByIdArrayFn;\n          } else {\n            trackByIdFn = trackByIdExpFn || trackByIdObjFn;\n            // if object, extract keys, sort them and use to determine order of iteration over obj props\n            collectionKeys = [];\n            for (var itemKey in collection) {\n              if (collection.hasOwnProperty(itemKey) && itemKey.charAt(0) != '$') {\n                collectionKeys.push(itemKey);\n              }\n            }\n            collectionKeys.sort();\n          }\n\n          collectionLength = collectionKeys.length;\n          nextBlockOrder = new Array(collectionLength);\n\n          // locate existing items\n          for (index = 0; index < collectionLength; index++) {\n            key = (collection === collectionKeys) ? index : collectionKeys[index];\n            value = collection[key];\n            trackById = trackByIdFn(key, value, index);\n            if (lastBlockMap[trackById]) {\n              // found previously seen block\n              block = lastBlockMap[trackById];\n              delete lastBlockMap[trackById];\n              nextBlockMap[trackById] = block;\n              nextBlockOrder[index] = block;\n            } else if (nextBlockMap[trackById]) {\n              // if collision detected. restore lastBlockMap and throw an error\n              forEach(nextBlockOrder, function(block) {\n                if (block && block.scope) lastBlockMap[block.id] = block;\n              });\n              throw ngRepeatMinErr('dupes',\n                  \"Duplicates in a repeater are not allowed. Use 'track by' expression to specify unique keys. Repeater: {0}, Duplicate key: {1}, Duplicate value: {2}\",\n                  expression, trackById, value);\n            } else {\n              // new never before seen block\n              nextBlockOrder[index] = {id: trackById, scope: undefined, clone: undefined};\n              nextBlockMap[trackById] = true;\n            }\n          }\n\n          // remove leftover items\n          for (var blockKey in lastBlockMap) {\n            block = lastBlockMap[blockKey];\n            elementsToRemove = getBlockNodes(block.clone);\n            $animate.leave(elementsToRemove);\n            if (elementsToRemove[0].parentNode) {\n              // if the element was not removed yet because of pending animation, mark it as deleted\n              // so that we can ignore it later\n              for (index = 0, length = elementsToRemove.length; index < length; index++) {\n                elementsToRemove[index][NG_REMOVED] = true;\n              }\n            }\n            block.scope.$destroy();\n          }\n\n          // we are not using forEach for perf reasons (trying to avoid #call)\n          for (index = 0; index < collectionLength; index++) {\n            key = (collection === collectionKeys) ? index : collectionKeys[index];\n            value = collection[key];\n            block = nextBlockOrder[index];\n\n            if (block.scope) {\n              // if we have already seen this object, then we need to reuse the\n              // associated scope/element\n\n              nextNode = previousNode;\n\n              // skip nodes that are already pending removal via leave animation\n              do {\n                nextNode = nextNode.nextSibling;\n              } while (nextNode && nextNode[NG_REMOVED]);\n\n              if (getBlockStart(block) != nextNode) {\n                // existing item which got moved\n                $animate.move(getBlockNodes(block.clone), null, jqLite(previousNode));\n              }\n              previousNode = getBlockEnd(block);\n              updateScope(block.scope, index, valueIdentifier, value, keyIdentifier, key, collectionLength);\n            } else {\n              // new item which we don't know about\n              $transclude(function ngRepeatTransclude(clone, scope) {\n                block.scope = scope;\n                // http://jsperf.com/clone-vs-createcomment\n                var endNode = ngRepeatEndComment.cloneNode(false);\n                clone[clone.length++] = endNode;\n\n                // TODO(perf): support naked previousNode in `enter` to avoid creation of jqLite wrapper?\n                $animate.enter(clone, null, jqLite(previousNode));\n                previousNode = endNode;\n                // Note: We only need the first/last node of the cloned nodes.\n                // However, we need to keep the reference to the jqlite wrapper as it might be changed later\n                // by a directive with templateUrl when its template arrives.\n                block.clone = clone;\n                nextBlockMap[block.id] = block;\n                updateScope(block.scope, index, valueIdentifier, value, keyIdentifier, key, collectionLength);\n              });\n            }\n          }\n          lastBlockMap = nextBlockMap;\n        });\n      };\n    }\n  };\n}];\n\nvar NG_HIDE_CLASS = 'ng-hide';\nvar NG_HIDE_IN_PROGRESS_CLASS = 'ng-hide-animate';\n/**\n * @ngdoc directive\n * @name ngShow\n *\n * @description\n * The `ngShow` directive shows or hides the given HTML element based on the expression\n * provided to the `ngShow` attribute. The element is shown or hidden by removing or adding\n * the `.ng-hide` CSS class onto the element. The `.ng-hide` CSS class is predefined\n * in AngularJS and sets the display style to none (using an !important flag).\n * For CSP mode please add `angular-csp.css` to your html file (see {@link ng.directive:ngCsp ngCsp}).\n *\n * ```html\n * <!-- when $scope.myValue is truthy (element is visible) -->\n * <div ng-show=\"myValue\"></div>\n *\n * <!-- when $scope.myValue is falsy (element is hidden) -->\n * <div ng-show=\"myValue\" class=\"ng-hide\"></div>\n * ```\n *\n * When the `ngShow` expression evaluates to a falsy value then the `.ng-hide` CSS class is added to the class\n * attribute on the element causing it to become hidden. When truthy, the `.ng-hide` CSS class is removed\n * from the element causing the element not to appear hidden.\n *\n * ## Why is !important used?\n *\n * You may be wondering why !important is used for the `.ng-hide` CSS class. This is because the `.ng-hide` selector\n * can be easily overridden by heavier selectors. For example, something as simple\n * as changing the display style on a HTML list item would make hidden elements appear visible.\n * This also becomes a bigger issue when dealing with CSS frameworks.\n *\n * By using !important, the show and hide behavior will work as expected despite any clash between CSS selector\n * specificity (when !important isn't used with any conflicting styles). If a developer chooses to override the\n * styling to change how to hide an element then it is just a matter of using !important in their own CSS code.\n *\n * ### Overriding `.ng-hide`\n *\n * By default, the `.ng-hide` class will style the element with `display: none!important`. If you wish to change\n * the hide behavior with ngShow/ngHide then this can be achieved by restating the styles for the `.ng-hide`\n * class CSS. Note that the selector that needs to be used is actually `.ng-hide:not(.ng-hide-animate)` to cope\n * with extra animation classes that can be added.\n *\n * ```css\n * .ng-hide:not(.ng-hide-animate) {\n *   /&#42; this is just another form of hiding an element &#42;/\n *   display: block!important;\n *   position: absolute;\n *   top: -9999px;\n *   left: -9999px;\n * }\n * ```\n *\n * By default you don't need to override in CSS anything and the animations will work around the display style.\n *\n * ## A note about animations with `ngShow`\n *\n * Animations in ngShow/ngHide work with the show and hide events that are triggered when the directive expression\n * is true and false. This system works like the animation system present with ngClass except that\n * you must also include the !important flag to override the display property\n * so that you can perform an animation when the element is hidden during the time of the animation.\n *\n * ```css\n * //\n * //a working example can be found at the bottom of this page\n * //\n * .my-element.ng-hide-add, .my-element.ng-hide-remove {\n *   /&#42; this is required as of 1.3x to properly\n *      apply all styling in a show/hide animation &#42;/\n *   transition: 0s linear all;\n * }\n *\n * .my-element.ng-hide-add-active,\n * .my-element.ng-hide-remove-active {\n *   /&#42; the transition is defined in the active class &#42;/\n *   transition: 1s linear all;\n * }\n *\n * .my-element.ng-hide-add { ... }\n * .my-element.ng-hide-add.ng-hide-add-active { ... }\n * .my-element.ng-hide-remove { ... }\n * .my-element.ng-hide-remove.ng-hide-remove-active { ... }\n * ```\n *\n * Keep in mind that, as of AngularJS version 1.3.0-beta.11, there is no need to change the display\n * property to block during animation states--ngAnimate will handle the style toggling automatically for you.\n *\n * @animations\n * addClass: `.ng-hide` - happens after the `ngShow` expression evaluates to a truthy value and the just before contents are set to visible\n * removeClass: `.ng-hide` - happens after the `ngShow` expression evaluates to a non truthy value and just before the contents are set to hidden\n *\n * @element ANY\n * @param {expression} ngShow If the {@link guide/expression expression} is truthy\n *     then the element is shown or hidden respectively.\n *\n * @example\n  <example module=\"ngAnimate\" deps=\"angular-animate.js\" animations=\"true\">\n    <file name=\"index.html\">\n      Click me: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n      <div>\n        Show:\n        <div class=\"check-element animate-show\" ng-show=\"checked\">\n          <span class=\"glyphicon glyphicon-thumbs-up\"></span> I show up when your checkbox is checked.\n        </div>\n      </div>\n      <div>\n        Hide:\n        <div class=\"check-element animate-show\" ng-hide=\"checked\">\n          <span class=\"glyphicon glyphicon-thumbs-down\"></span> I hide when your checkbox is checked.\n        </div>\n      </div>\n    </file>\n    <file name=\"glyphicons.css\">\n      @import url(../../components/bootstrap-3.1.1/css/bootstrap.css);\n    </file>\n    <file name=\"animations.css\">\n      .animate-show {\n        line-height: 20px;\n        opacity: 1;\n        padding: 10px;\n        border: 1px solid black;\n        background: white;\n      }\n\n      .animate-show.ng-hide-add.ng-hide-add-active,\n      .animate-show.ng-hide-remove.ng-hide-remove-active {\n        -webkit-transition: all linear 0.5s;\n        transition: all linear 0.5s;\n      }\n\n      .animate-show.ng-hide {\n        line-height: 0;\n        opacity: 0;\n        padding: 0 10px;\n      }\n\n      .check-element {\n        padding: 10px;\n        border: 1px solid black;\n        background: white;\n      }\n    </file>\n    <file name=\"protractor.js\" type=\"protractor\">\n      var thumbsUp = element(by.css('span.glyphicon-thumbs-up'));\n      var thumbsDown = element(by.css('span.glyphicon-thumbs-down'));\n\n      it('should check ng-show / ng-hide', function() {\n        expect(thumbsUp.isDisplayed()).toBeFalsy();\n        expect(thumbsDown.isDisplayed()).toBeTruthy();\n\n        element(by.model('checked')).click();\n\n        expect(thumbsUp.isDisplayed()).toBeTruthy();\n        expect(thumbsDown.isDisplayed()).toBeFalsy();\n      });\n    </file>\n  </example>\n */\nvar ngShowDirective = ['$animate', function($animate) {\n  return {\n    restrict: 'A',\n    multiElement: true,\n    link: function(scope, element, attr) {\n      scope.$watch(attr.ngShow, function ngShowWatchAction(value) {\n        // we're adding a temporary, animation-specific class for ng-hide since this way\n        // we can control when the element is actually displayed on screen without having\n        // to have a global/greedy CSS selector that breaks when other animations are run.\n        // Read: https://github.com/angular/angular.js/issues/9103#issuecomment-58335845\n        $animate[value ? 'removeClass' : 'addClass'](element, NG_HIDE_CLASS, {\n          tempClasses: NG_HIDE_IN_PROGRESS_CLASS\n        });\n      });\n    }\n  };\n}];\n\n\n/**\n * @ngdoc directive\n * @name ngHide\n *\n * @description\n * The `ngHide` directive shows or hides the given HTML element based on the expression\n * provided to the `ngHide` attribute. The element is shown or hidden by removing or adding\n * the `ng-hide` CSS class onto the element. The `.ng-hide` CSS class is predefined\n * in AngularJS and sets the display style to none (using an !important flag).\n * For CSP mode please add `angular-csp.css` to your html file (see {@link ng.directive:ngCsp ngCsp}).\n *\n * ```html\n * <!-- when $scope.myValue is truthy (element is hidden) -->\n * <div ng-hide=\"myValue\" class=\"ng-hide\"></div>\n *\n * <!-- when $scope.myValue is falsy (element is visible) -->\n * <div ng-hide=\"myValue\"></div>\n * ```\n *\n * When the `ngHide` expression evaluates to a truthy value then the `.ng-hide` CSS class is added to the class\n * attribute on the element causing it to become hidden. When falsy, the `.ng-hide` CSS class is removed\n * from the element causing the element not to appear hidden.\n *\n * ## Why is !important used?\n *\n * You may be wondering why !important is used for the `.ng-hide` CSS class. This is because the `.ng-hide` selector\n * can be easily overridden by heavier selectors. For example, something as simple\n * as changing the display style on a HTML list item would make hidden elements appear visible.\n * This also becomes a bigger issue when dealing with CSS frameworks.\n *\n * By using !important, the show and hide behavior will work as expected despite any clash between CSS selector\n * specificity (when !important isn't used with any conflicting styles). If a developer chooses to override the\n * styling to change how to hide an element then it is just a matter of using !important in their own CSS code.\n *\n * ### Overriding `.ng-hide`\n *\n * By default, the `.ng-hide` class will style the element with `display: none!important`. If you wish to change\n * the hide behavior with ngShow/ngHide then this can be achieved by restating the styles for the `.ng-hide`\n * class in CSS:\n *\n * ```css\n * .ng-hide {\n *   /&#42; this is just another form of hiding an element &#42;/\n *   display: block!important;\n *   position: absolute;\n *   top: -9999px;\n *   left: -9999px;\n * }\n * ```\n *\n * By default you don't need to override in CSS anything and the animations will work around the display style.\n *\n * ## A note about animations with `ngHide`\n *\n * Animations in ngShow/ngHide work with the show and hide events that are triggered when the directive expression\n * is true and false. This system works like the animation system present with ngClass, except that the `.ng-hide`\n * CSS class is added and removed for you instead of your own CSS class.\n *\n * ```css\n * //\n * //a working example can be found at the bottom of this page\n * //\n * .my-element.ng-hide-add, .my-element.ng-hide-remove {\n *   transition: 0.5s linear all;\n * }\n *\n * .my-element.ng-hide-add { ... }\n * .my-element.ng-hide-add.ng-hide-add-active { ... }\n * .my-element.ng-hide-remove { ... }\n * .my-element.ng-hide-remove.ng-hide-remove-active { ... }\n * ```\n *\n * Keep in mind that, as of AngularJS version 1.3.0-beta.11, there is no need to change the display\n * property to block during animation states--ngAnimate will handle the style toggling automatically for you.\n *\n * @animations\n * removeClass: `.ng-hide` - happens after the `ngHide` expression evaluates to a truthy value and just before the contents are set to hidden\n * addClass: `.ng-hide` - happens after the `ngHide` expression evaluates to a non truthy value and just before the contents are set to visible\n *\n * @element ANY\n * @param {expression} ngHide If the {@link guide/expression expression} is truthy then\n *     the element is shown or hidden respectively.\n *\n * @example\n  <example module=\"ngAnimate\" deps=\"angular-animate.js\" animations=\"true\">\n    <file name=\"index.html\">\n      Click me: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n      <div>\n        Show:\n        <div class=\"check-element animate-hide\" ng-show=\"checked\">\n          <span class=\"glyphicon glyphicon-thumbs-up\"></span> I show up when your checkbox is checked.\n        </div>\n      </div>\n      <div>\n        Hide:\n        <div class=\"check-element animate-hide\" ng-hide=\"checked\">\n          <span class=\"glyphicon glyphicon-thumbs-down\"></span> I hide when your checkbox is checked.\n        </div>\n      </div>\n    </file>\n    <file name=\"glyphicons.css\">\n      @import url(../../components/bootstrap-3.1.1/css/bootstrap.css);\n    </file>\n    <file name=\"animations.css\">\n      .animate-hide {\n        -webkit-transition: all linear 0.5s;\n        transition: all linear 0.5s;\n        line-height: 20px;\n        opacity: 1;\n        padding: 10px;\n        border: 1px solid black;\n        background: white;\n      }\n\n      .animate-hide.ng-hide {\n        line-height: 0;\n        opacity: 0;\n        padding: 0 10px;\n      }\n\n      .check-element {\n        padding: 10px;\n        border: 1px solid black;\n        background: white;\n      }\n    </file>\n    <file name=\"protractor.js\" type=\"protractor\">\n      var thumbsUp = element(by.css('span.glyphicon-thumbs-up'));\n      var thumbsDown = element(by.css('span.glyphicon-thumbs-down'));\n\n      it('should check ng-show / ng-hide', function() {\n        expect(thumbsUp.isDisplayed()).toBeFalsy();\n        expect(thumbsDown.isDisplayed()).toBeTruthy();\n\n        element(by.model('checked')).click();\n\n        expect(thumbsUp.isDisplayed()).toBeTruthy();\n        expect(thumbsDown.isDisplayed()).toBeFalsy();\n      });\n    </file>\n  </example>\n */\nvar ngHideDirective = ['$animate', function($animate) {\n  return {\n    restrict: 'A',\n    multiElement: true,\n    link: function(scope, element, attr) {\n      scope.$watch(attr.ngHide, function ngHideWatchAction(value) {\n        // The comment inside of the ngShowDirective explains why we add and\n        // remove a temporary class for the show/hide animation\n        $animate[value ? 'addClass' : 'removeClass'](element,NG_HIDE_CLASS, {\n          tempClasses: NG_HIDE_IN_PROGRESS_CLASS\n        });\n      });\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ngStyle\n * @restrict AC\n *\n * @description\n * The `ngStyle` directive allows you to set CSS style on an HTML element conditionally.\n *\n * @element ANY\n * @param {expression} ngStyle\n *\n * {@link guide/expression Expression} which evals to an\n * object whose keys are CSS style names and values are corresponding values for those CSS\n * keys.\n *\n * Since some CSS style names are not valid keys for an object, they must be quoted.\n * See the 'background-color' style in the example below.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <input type=\"button\" value=\"set color\" ng-click=\"myStyle={color:'red'}\">\n        <input type=\"button\" value=\"set background\" ng-click=\"myStyle={'background-color':'blue'}\">\n        <input type=\"button\" value=\"clear\" ng-click=\"myStyle={}\">\n        <br/>\n        <span ng-style=\"myStyle\">Sample Text</span>\n        <pre>myStyle={{myStyle}}</pre>\n     </file>\n     <file name=\"style.css\">\n       span {\n         color: black;\n       }\n     </file>\n     <file name=\"protractor.js\" type=\"protractor\">\n       var colorSpan = element(by.css('span'));\n\n       it('should check ng-style', function() {\n         expect(colorSpan.getCssValue('color')).toBe('rgba(0, 0, 0, 1)');\n         element(by.css('input[value=\\'set color\\']')).click();\n         expect(colorSpan.getCssValue('color')).toBe('rgba(255, 0, 0, 1)');\n         element(by.css('input[value=clear]')).click();\n         expect(colorSpan.getCssValue('color')).toBe('rgba(0, 0, 0, 1)');\n       });\n     </file>\n   </example>\n */\nvar ngStyleDirective = ngDirective(function(scope, element, attr) {\n  scope.$watchCollection(attr.ngStyle, function ngStyleWatchAction(newStyles, oldStyles) {\n    if (oldStyles && (newStyles !== oldStyles)) {\n      forEach(oldStyles, function(val, style) { element.css(style, '');});\n    }\n    if (newStyles) element.css(newStyles);\n  });\n});\n\n/**\n * @ngdoc directive\n * @name ngSwitch\n * @restrict EA\n *\n * @description\n * The `ngSwitch` directive is used to conditionally swap DOM structure on your template based on a scope expression.\n * Elements within `ngSwitch` but without `ngSwitchWhen` or `ngSwitchDefault` directives will be preserved at the location\n * as specified in the template.\n *\n * The directive itself works similar to ngInclude, however, instead of downloading template code (or loading it\n * from the template cache), `ngSwitch` simply chooses one of the nested elements and makes it visible based on which element\n * matches the value obtained from the evaluated expression. In other words, you define a container element\n * (where you place the directive), place an expression on the **`on=\"...\"` attribute**\n * (or the **`ng-switch=\"...\"` attribute**), define any inner elements inside of the directive and place\n * a when attribute per element. The when attribute is used to inform ngSwitch which element to display when the on\n * expression is evaluated. If a matching expression is not found via a when attribute then an element with the default\n * attribute is displayed.\n *\n * <div class=\"alert alert-info\">\n * Be aware that the attribute values to match against cannot be expressions. They are interpreted\n * as literal string values to match against.\n * For example, **`ng-switch-when=\"someVal\"`** will match against the string `\"someVal\"` not against the\n * value of the expression `$scope.someVal`.\n * </div>\n\n * @animations\n * enter - happens after the ngSwitch contents change and the matched child element is placed inside the container\n * leave - happens just after the ngSwitch contents change and just before the former contents are removed from the DOM\n *\n * @usage\n *\n * ```\n * <ANY ng-switch=\"expression\">\n *   <ANY ng-switch-when=\"matchValue1\">...</ANY>\n *   <ANY ng-switch-when=\"matchValue2\">...</ANY>\n *   <ANY ng-switch-default>...</ANY>\n * </ANY>\n * ```\n *\n *\n * @scope\n * @priority 1200\n * @param {*} ngSwitch|on expression to match against <tt>ng-switch-when</tt>.\n * On child elements add:\n *\n * * `ngSwitchWhen`: the case statement to match against. If match then this\n *   case will be displayed. If the same match appears multiple times, all the\n *   elements will be displayed.\n * * `ngSwitchDefault`: the default case when no other case match. If there\n *   are multiple default cases, all of them will be displayed when no other\n *   case match.\n *\n *\n * @example\n  <example module=\"switchExample\" deps=\"angular-animate.js\" animations=\"true\">\n    <file name=\"index.html\">\n      <div ng-controller=\"ExampleController\">\n        <select ng-model=\"selection\" ng-options=\"item for item in items\">\n        </select>\n        <tt>selection={{selection}}</tt>\n        <hr/>\n        <div class=\"animate-switch-container\"\n          ng-switch on=\"selection\">\n            <div class=\"animate-switch\" ng-switch-when=\"settings\">Settings Div</div>\n            <div class=\"animate-switch\" ng-switch-when=\"home\">Home Span</div>\n            <div class=\"animate-switch\" ng-switch-default>default</div>\n        </div>\n      </div>\n    </file>\n    <file name=\"script.js\">\n      angular.module('switchExample', ['ngAnimate'])\n        .controller('ExampleController', ['$scope', function($scope) {\n          $scope.items = ['settings', 'home', 'other'];\n          $scope.selection = $scope.items[0];\n        }]);\n    </file>\n    <file name=\"animations.css\">\n      .animate-switch-container {\n        position:relative;\n        background:white;\n        border:1px solid black;\n        height:40px;\n        overflow:hidden;\n      }\n\n      .animate-switch {\n        padding:10px;\n      }\n\n      .animate-switch.ng-animate {\n        -webkit-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;\n        transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;\n\n        position:absolute;\n        top:0;\n        left:0;\n        right:0;\n        bottom:0;\n      }\n\n      .animate-switch.ng-leave.ng-leave-active,\n      .animate-switch.ng-enter {\n        top:-50px;\n      }\n      .animate-switch.ng-leave,\n      .animate-switch.ng-enter.ng-enter-active {\n        top:0;\n      }\n    </file>\n    <file name=\"protractor.js\" type=\"protractor\">\n      var switchElem = element(by.css('[ng-switch]'));\n      var select = element(by.model('selection'));\n\n      it('should start in settings', function() {\n        expect(switchElem.getText()).toMatch(/Settings Div/);\n      });\n      it('should change to home', function() {\n        select.all(by.css('option')).get(1).click();\n        expect(switchElem.getText()).toMatch(/Home Span/);\n      });\n      it('should select default', function() {\n        select.all(by.css('option')).get(2).click();\n        expect(switchElem.getText()).toMatch(/default/);\n      });\n    </file>\n  </example>\n */\nvar ngSwitchDirective = ['$animate', function($animate) {\n  return {\n    restrict: 'EA',\n    require: 'ngSwitch',\n\n    // asks for $scope to fool the BC controller module\n    controller: ['$scope', function ngSwitchController() {\n     this.cases = {};\n    }],\n    link: function(scope, element, attr, ngSwitchController) {\n      var watchExpr = attr.ngSwitch || attr.on,\n          selectedTranscludes = [],\n          selectedElements = [],\n          previousLeaveAnimations = [],\n          selectedScopes = [];\n\n      var spliceFactory = function(array, index) {\n          return function() { array.splice(index, 1); };\n      };\n\n      scope.$watch(watchExpr, function ngSwitchWatchAction(value) {\n        var i, ii;\n        for (i = 0, ii = previousLeaveAnimations.length; i < ii; ++i) {\n          $animate.cancel(previousLeaveAnimations[i]);\n        }\n        previousLeaveAnimations.length = 0;\n\n        for (i = 0, ii = selectedScopes.length; i < ii; ++i) {\n          var selected = getBlockNodes(selectedElements[i].clone);\n          selectedScopes[i].$destroy();\n          var promise = previousLeaveAnimations[i] = $animate.leave(selected);\n          promise.then(spliceFactory(previousLeaveAnimations, i));\n        }\n\n        selectedElements.length = 0;\n        selectedScopes.length = 0;\n\n        if ((selectedTranscludes = ngSwitchController.cases['!' + value] || ngSwitchController.cases['?'])) {\n          forEach(selectedTranscludes, function(selectedTransclude) {\n            selectedTransclude.transclude(function(caseElement, selectedScope) {\n              selectedScopes.push(selectedScope);\n              var anchor = selectedTransclude.element;\n              caseElement[caseElement.length++] = document.createComment(' end ngSwitchWhen: ');\n              var block = { clone: caseElement };\n\n              selectedElements.push(block);\n              $animate.enter(caseElement, anchor.parent(), anchor);\n            });\n          });\n        }\n      });\n    }\n  };\n}];\n\nvar ngSwitchWhenDirective = ngDirective({\n  transclude: 'element',\n  priority: 1200,\n  require: '^ngSwitch',\n  multiElement: true,\n  link: function(scope, element, attrs, ctrl, $transclude) {\n    ctrl.cases['!' + attrs.ngSwitchWhen] = (ctrl.cases['!' + attrs.ngSwitchWhen] || []);\n    ctrl.cases['!' + attrs.ngSwitchWhen].push({ transclude: $transclude, element: element });\n  }\n});\n\nvar ngSwitchDefaultDirective = ngDirective({\n  transclude: 'element',\n  priority: 1200,\n  require: '^ngSwitch',\n  multiElement: true,\n  link: function(scope, element, attr, ctrl, $transclude) {\n    ctrl.cases['?'] = (ctrl.cases['?'] || []);\n    ctrl.cases['?'].push({ transclude: $transclude, element: element });\n   }\n});\n\n/**\n * @ngdoc directive\n * @name ngTransclude\n * @restrict EAC\n *\n * @description\n * Directive that marks the insertion point for the transcluded DOM of the nearest parent directive that uses transclusion.\n *\n * Any existing content of the element that this directive is placed on will be removed before the transcluded content is inserted.\n *\n * @element ANY\n *\n * @example\n   <example module=\"transcludeExample\">\n     <file name=\"index.html\">\n       <script>\n         angular.module('transcludeExample', [])\n          .directive('pane', function(){\n             return {\n               restrict: 'E',\n               transclude: true,\n               scope: { title:'@' },\n               template: '<div style=\"border: 1px solid black;\">' +\n                           '<div style=\"background-color: gray\">{{title}}</div>' +\n                           '<ng-transclude></ng-transclude>' +\n                         '</div>'\n             };\n         })\n         .controller('ExampleController', ['$scope', function($scope) {\n           $scope.title = 'Lorem Ipsum';\n           $scope.text = 'Neque porro quisquam est qui dolorem ipsum quia dolor...';\n         }]);\n       </script>\n       <div ng-controller=\"ExampleController\">\n         <input ng-model=\"title\"> <br/>\n         <textarea ng-model=\"text\"></textarea> <br/>\n         <pane title=\"{{title}}\">{{text}}</pane>\n       </div>\n     </file>\n     <file name=\"protractor.js\" type=\"protractor\">\n        it('should have transcluded', function() {\n          var titleElement = element(by.model('title'));\n          titleElement.clear();\n          titleElement.sendKeys('TITLE');\n          var textElement = element(by.model('text'));\n          textElement.clear();\n          textElement.sendKeys('TEXT');\n          expect(element(by.binding('title')).getText()).toEqual('TITLE');\n          expect(element(by.binding('text')).getText()).toEqual('TEXT');\n        });\n     </file>\n   </example>\n *\n */\nvar ngTranscludeDirective = ngDirective({\n  restrict: 'EAC',\n  link: function($scope, $element, $attrs, controller, $transclude) {\n    if (!$transclude) {\n      throw minErr('ngTransclude')('orphan',\n       'Illegal use of ngTransclude directive in the template! ' +\n       'No parent directive that requires a transclusion found. ' +\n       'Element: {0}',\n       startingTag($element));\n    }\n\n    $transclude(function(clone) {\n      $element.empty();\n      $element.append(clone);\n    });\n  }\n});\n\n/**\n * @ngdoc directive\n * @name script\n * @restrict E\n *\n * @description\n * Load the content of a `<script>` element into {@link ng.$templateCache `$templateCache`}, so that the\n * template can be used by {@link ng.directive:ngInclude `ngInclude`},\n * {@link ngRoute.directive:ngView `ngView`}, or {@link guide/directive directives}. The type of the\n * `<script>` element must be specified as `text/ng-template`, and a cache name for the template must be\n * assigned through the element's `id`, which can then be used as a directive's `templateUrl`.\n *\n * @param {string} type Must be set to `'text/ng-template'`.\n * @param {string} id Cache name of the template.\n *\n * @example\n  <example>\n    <file name=\"index.html\">\n      <script type=\"text/ng-template\" id=\"/tpl.html\">\n        Content of the template.\n      </script>\n\n      <a ng-click=\"currentTpl='/tpl.html'\" id=\"tpl-link\">Load inlined template</a>\n      <div id=\"tpl-content\" ng-include src=\"currentTpl\"></div>\n    </file>\n    <file name=\"protractor.js\" type=\"protractor\">\n      it('should load template defined inside script tag', function() {\n        element(by.css('#tpl-link')).click();\n        expect(element(by.css('#tpl-content')).getText()).toMatch(/Content of the template/);\n      });\n    </file>\n  </example>\n */\nvar scriptDirective = ['$templateCache', function($templateCache) {\n  return {\n    restrict: 'E',\n    terminal: true,\n    compile: function(element, attr) {\n      if (attr.type == 'text/ng-template') {\n        var templateUrl = attr.id,\n            text = element[0].text;\n\n        $templateCache.put(templateUrl, text);\n      }\n    }\n  };\n}];\n\nvar ngOptionsMinErr = minErr('ngOptions');\n/**\n * @ngdoc directive\n * @name select\n * @restrict E\n *\n * @description\n * HTML `SELECT` element with angular data-binding.\n *\n * # `ngOptions`\n *\n * The `ngOptions` attribute can be used to dynamically generate a list of `<option>`\n * elements for the `<select>` element using the array or object obtained by evaluating the\n * `ngOptions` comprehension expression.\n *\n * In many cases, `ngRepeat` can be used on `<option>` elements instead of `ngOptions` to achieve a\n * similar result. However, `ngOptions` provides some benefits such as reducing memory and\n * increasing speed by not creating a new scope for each repeated instance, as well as providing\n * more flexibility in how the `<select>`'s model is assigned via the `select` **`as`** part of the\n * comprehension expression. `ngOptions` should be used when the `<select>` model needs to be bound\n *  to a non-string value. This is because an option element can only be bound to string values at\n * present.\n *\n * When an item in the `<select>` menu is selected, the array element or object property\n * represented by the selected option will be bound to the model identified by the `ngModel`\n * directive.\n *\n * Optionally, a single hard-coded `<option>` element, with the value set to an empty string, can\n * be nested into the `<select>` element. This element will then represent the `null` or \"not selected\"\n * option. See example below for demonstration.\n *\n * <div class=\"alert alert-warning\">\n * **Note:** `ngModel` compares by reference, not value. This is important when binding to an\n * array of objects. See an example [in this jsfiddle](http://jsfiddle.net/qWzTb/).\n * </div>\n *\n * ## `select` **`as`**\n *\n * Using `select` **`as`** will bind the result of the `select` expression to the model, but\n * the value of the `<select>` and `<option>` html elements will be either the index (for array data sources)\n * or property name (for object data sources) of the value within the collection. If a **`track by`** expression\n * is used, the result of that expression will be set as the value of the `option` and `select` elements.\n *\n *\n * ### `select` **`as`** and **`track by`**\n *\n * <div class=\"alert alert-warning\">\n * Do not use `select` **`as`** and **`track by`** in the same expression. They are not designed to work together.\n * </div>\n *\n * Consider the following example:\n *\n * ```html\n * <select ng-options=\"item.subItem as item.label for item in values track by item.id\" ng-model=\"selected\">\n * ```\n *\n * ```js\n * $scope.values = [{\n *   id: 1,\n *   label: 'aLabel',\n *   subItem: { name: 'aSubItem' }\n * }, {\n *   id: 2,\n *   label: 'bLabel',\n *   subItem: { name: 'bSubItem' }\n * }];\n *\n * $scope.selected = { name: 'aSubItem' };\n * ```\n *\n * With the purpose of preserving the selection, the **`track by`** expression is always applied to the element\n * of the data source (to `item` in this example). To calculate whether an element is selected, we do the\n * following:\n *\n * 1. Apply **`track by`** to the elements in the array. In the example: `[1, 2]`\n * 2. Apply **`track by`** to the already selected value in `ngModel`.\n *    In the example: this is not possible as **`track by`** refers to `item.id`, but the selected\n *    value from `ngModel` is `{name: 'aSubItem'}`, so the **`track by`** expression is applied to\n *    a wrong object, the selected element can't be found, `<select>` is always reset to the \"not\n *    selected\" option.\n *\n *\n * @param {string} ngModel Assignable angular expression to data-bind to.\n * @param {string=} name Property name of the form under which the control is published.\n * @param {string=} required The control is considered valid only if value is entered.\n * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n *    `required` when you want to data-bind to the `required` attribute.\n * @param {comprehension_expression=} ngOptions in one of the following forms:\n *\n *   * for array data sources:\n *     * `label` **`for`** `value` **`in`** `array`\n *     * `select` **`as`** `label` **`for`** `value` **`in`** `array`\n *     * `label` **`group by`** `group` **`for`** `value` **`in`** `array`\n *     * `label` **`group by`** `group` **`for`** `value` **`in`** `array` **`track by`** `trackexpr`\n *     * `label` **`for`** `value` **`in`** `array` | orderBy:`orderexpr` **`track by`** `trackexpr`\n *        (for including a filter with `track by`)\n *   * for object data sources:\n *     * `label` **`for (`**`key` **`,`** `value`**`) in`** `object`\n *     * `select` **`as`** `label` **`for (`**`key` **`,`** `value`**`) in`** `object`\n *     * `label` **`group by`** `group` **`for (`**`key`**`,`** `value`**`) in`** `object`\n *     * `select` **`as`** `label` **`group by`** `group`\n *         **`for` `(`**`key`**`,`** `value`**`) in`** `object`\n *\n * Where:\n *\n *   * `array` / `object`: an expression which evaluates to an array / object to iterate over.\n *   * `value`: local variable which will refer to each item in the `array` or each property value\n *      of `object` during iteration.\n *   * `key`: local variable which will refer to a property name in `object` during iteration.\n *   * `label`: The result of this expression will be the label for `<option>` element. The\n *     `expression` will most likely refer to the `value` variable (e.g. `value.propertyName`).\n *   * `select`: The result of this expression will be bound to the model of the parent `<select>`\n *      element. If not specified, `select` expression will default to `value`.\n *   * `group`: The result of this expression will be used to group options using the `<optgroup>`\n *      DOM element.\n *   * `trackexpr`: Used when working with an array of objects. The result of this expression will be\n *      used to identify the objects in the array. The `trackexpr` will most likely refer to the\n *     `value` variable (e.g. `value.propertyName`). With this the selection is preserved\n *      even when the options are recreated (e.g. reloaded from the server).\n *\n * @example\n    <example module=\"selectExample\">\n      <file name=\"index.html\">\n        <script>\n        angular.module('selectExample', [])\n          .controller('ExampleController', ['$scope', function($scope) {\n            $scope.colors = [\n              {name:'black', shade:'dark'},\n              {name:'white', shade:'light'},\n              {name:'red', shade:'dark'},\n              {name:'blue', shade:'dark'},\n              {name:'yellow', shade:'light'}\n            ];\n            $scope.myColor = $scope.colors[2]; // red\n          }]);\n        </script>\n        <div ng-controller=\"ExampleController\">\n          <ul>\n            <li ng-repeat=\"color in colors\">\n              Name: <input ng-model=\"color.name\">\n              [<a href ng-click=\"colors.splice($index, 1)\">X</a>]\n            </li>\n            <li>\n              [<a href ng-click=\"colors.push({})\">add</a>]\n            </li>\n          </ul>\n          <hr/>\n          Color (null not allowed):\n          <select ng-model=\"myColor\" ng-options=\"color.name for color in colors\"></select><br>\n\n          Color (null allowed):\n          <span  class=\"nullable\">\n            <select ng-model=\"myColor\" ng-options=\"color.name for color in colors\">\n              <option value=\"\">-- choose color --</option>\n            </select>\n          </span><br/>\n\n          Color grouped by shade:\n          <select ng-model=\"myColor\" ng-options=\"color.name group by color.shade for color in colors\">\n          </select><br/>\n\n\n          Select <a href ng-click=\"myColor = { name:'not in list', shade: 'other' }\">bogus</a>.<br>\n          <hr/>\n          Currently selected: {{ {selected_color:myColor} }}\n          <div style=\"border:solid 1px black; height:20px\"\n               ng-style=\"{'background-color':myColor.name}\">\n          </div>\n        </div>\n      </file>\n      <file name=\"protractor.js\" type=\"protractor\">\n         it('should check ng-options', function() {\n           expect(element(by.binding('{selected_color:myColor}')).getText()).toMatch('red');\n           element.all(by.model('myColor')).first().click();\n           element.all(by.css('select[ng-model=\"myColor\"] option')).first().click();\n           expect(element(by.binding('{selected_color:myColor}')).getText()).toMatch('black');\n           element(by.css('.nullable select[ng-model=\"myColor\"]')).click();\n           element.all(by.css('.nullable select[ng-model=\"myColor\"] option')).first().click();\n           expect(element(by.binding('{selected_color:myColor}')).getText()).toMatch('null');\n         });\n      </file>\n    </example>\n */\n\nvar ngOptionsDirective = valueFn({\n  restrict: 'A',\n  terminal: true\n});\n\n// jshint maxlen: false\nvar selectDirective = ['$compile', '$parse', function($compile,   $parse) {\n                         //000011111111110000000000022222222220000000000000000000003333333333000000000000004444444444444440000000005555555555555550000000666666666666666000000000000000777777777700000000000000000008888888888\n  var NG_OPTIONS_REGEXP = /^\\s*([\\s\\S]+?)(?:\\s+as\\s+([\\s\\S]+?))?(?:\\s+group\\s+by\\s+([\\s\\S]+?))?\\s+for\\s+(?:([\\$\\w][\\$\\w]*)|(?:\\(\\s*([\\$\\w][\\$\\w]*)\\s*,\\s*([\\$\\w][\\$\\w]*)\\s*\\)))\\s+in\\s+([\\s\\S]+?)(?:\\s+track\\s+by\\s+([\\s\\S]+?))?$/,\n      nullModelCtrl = {$setViewValue: noop};\n// jshint maxlen: 100\n\n  return {\n    restrict: 'E',\n    require: ['select', '?ngModel'],\n    controller: ['$element', '$scope', '$attrs', function($element, $scope, $attrs) {\n      var self = this,\n          optionsMap = {},\n          ngModelCtrl = nullModelCtrl,\n          nullOption,\n          unknownOption;\n\n\n      self.databound = $attrs.ngModel;\n\n\n      self.init = function(ngModelCtrl_, nullOption_, unknownOption_) {\n        ngModelCtrl = ngModelCtrl_;\n        nullOption = nullOption_;\n        unknownOption = unknownOption_;\n      };\n\n\n      self.addOption = function(value, element) {\n        assertNotHasOwnProperty(value, '\"option value\"');\n        optionsMap[value] = true;\n\n        if (ngModelCtrl.$viewValue == value) {\n          $element.val(value);\n          if (unknownOption.parent()) unknownOption.remove();\n        }\n        // Workaround for https://code.google.com/p/chromium/issues/detail?id=381459\n        // Adding an <option selected=\"selected\"> element to a <select required=\"required\"> should\n        // automatically select the new element\n        if (element && element[0].hasAttribute('selected')) {\n          element[0].selected = true;\n        }\n      };\n\n\n      self.removeOption = function(value) {\n        if (this.hasOption(value)) {\n          delete optionsMap[value];\n          if (ngModelCtrl.$viewValue === value) {\n            this.renderUnknownOption(value);\n          }\n        }\n      };\n\n\n      self.renderUnknownOption = function(val) {\n        var unknownVal = '? ' + hashKey(val) + ' ?';\n        unknownOption.val(unknownVal);\n        $element.prepend(unknownOption);\n        $element.val(unknownVal);\n        unknownOption.prop('selected', true); // needed for IE\n      };\n\n\n      self.hasOption = function(value) {\n        return optionsMap.hasOwnProperty(value);\n      };\n\n      $scope.$on('$destroy', function() {\n        // disable unknown option so that we don't do work when the whole select is being destroyed\n        self.renderUnknownOption = noop;\n      });\n    }],\n\n    link: function(scope, element, attr, ctrls) {\n      // if ngModel is not defined, we don't need to do anything\n      if (!ctrls[1]) return;\n\n      var selectCtrl = ctrls[0],\n          ngModelCtrl = ctrls[1],\n          multiple = attr.multiple,\n          optionsExp = attr.ngOptions,\n          nullOption = false, // if false, user will not be able to select it (used by ngOptions)\n          emptyOption,\n          renderScheduled = false,\n          // we can't just jqLite('<option>') since jqLite is not smart enough\n          // to create it in <select> and IE barfs otherwise.\n          optionTemplate = jqLite(document.createElement('option')),\n          optGroupTemplate =jqLite(document.createElement('optgroup')),\n          unknownOption = optionTemplate.clone();\n\n      // find \"null\" option\n      for (var i = 0, children = element.children(), ii = children.length; i < ii; i++) {\n        if (children[i].value === '') {\n          emptyOption = nullOption = children.eq(i);\n          break;\n        }\n      }\n\n      selectCtrl.init(ngModelCtrl, nullOption, unknownOption);\n\n      // required validator\n      if (multiple) {\n        ngModelCtrl.$isEmpty = function(value) {\n          return !value || value.length === 0;\n        };\n      }\n\n      if (optionsExp) setupAsOptions(scope, element, ngModelCtrl);\n      else if (multiple) setupAsMultiple(scope, element, ngModelCtrl);\n      else setupAsSingle(scope, element, ngModelCtrl, selectCtrl);\n\n\n      ////////////////////////////\n\n\n\n      function setupAsSingle(scope, selectElement, ngModelCtrl, selectCtrl) {\n        ngModelCtrl.$render = function() {\n          var viewValue = ngModelCtrl.$viewValue;\n\n          if (selectCtrl.hasOption(viewValue)) {\n            if (unknownOption.parent()) unknownOption.remove();\n            selectElement.val(viewValue);\n            if (viewValue === '') emptyOption.prop('selected', true); // to make IE9 happy\n          } else {\n            if (isUndefined(viewValue) && emptyOption) {\n              selectElement.val('');\n            } else {\n              selectCtrl.renderUnknownOption(viewValue);\n            }\n          }\n        };\n\n        selectElement.on('change', function() {\n          scope.$apply(function() {\n            if (unknownOption.parent()) unknownOption.remove();\n            ngModelCtrl.$setViewValue(selectElement.val());\n          });\n        });\n      }\n\n      function setupAsMultiple(scope, selectElement, ctrl) {\n        var lastView;\n        ctrl.$render = function() {\n          var items = new HashMap(ctrl.$viewValue);\n          forEach(selectElement.find('option'), function(option) {\n            option.selected = isDefined(items.get(option.value));\n          });\n        };\n\n        // we have to do it on each watch since ngModel watches reference, but\n        // we need to work of an array, so we need to see if anything was inserted/removed\n        scope.$watch(function selectMultipleWatch() {\n          if (!equals(lastView, ctrl.$viewValue)) {\n            lastView = shallowCopy(ctrl.$viewValue);\n            ctrl.$render();\n          }\n        });\n\n        selectElement.on('change', function() {\n          scope.$apply(function() {\n            var array = [];\n            forEach(selectElement.find('option'), function(option) {\n              if (option.selected) {\n                array.push(option.value);\n              }\n            });\n            ctrl.$setViewValue(array);\n          });\n        });\n      }\n\n      function setupAsOptions(scope, selectElement, ctrl) {\n        var match;\n\n        if (!(match = optionsExp.match(NG_OPTIONS_REGEXP))) {\n          throw ngOptionsMinErr('iexp',\n            \"Expected expression in form of \" +\n            \"'_select_ (as _label_)? for (_key_,)?_value_ in _collection_'\" +\n            \" but got '{0}'. Element: {1}\",\n            optionsExp, startingTag(selectElement));\n        }\n\n        var displayFn = $parse(match[2] || match[1]),\n            valueName = match[4] || match[6],\n            selectAs = / as /.test(match[0]) && match[1],\n            selectAsFn = selectAs ? $parse(selectAs) : null,\n            keyName = match[5],\n            groupByFn = $parse(match[3] || ''),\n            valueFn = $parse(match[2] ? match[1] : valueName),\n            valuesFn = $parse(match[7]),\n            track = match[8],\n            trackFn = track ? $parse(match[8]) : null,\n            trackKeysCache = {},\n            // This is an array of array of existing option groups in DOM.\n            // We try to reuse these if possible\n            // - optionGroupsCache[0] is the options with no option group\n            // - optionGroupsCache[?][0] is the parent: either the SELECT or OPTGROUP element\n            optionGroupsCache = [[{element: selectElement, label:''}]],\n            //re-usable object to represent option's locals\n            locals = {};\n\n        if (nullOption) {\n          // compile the element since there might be bindings in it\n          $compile(nullOption)(scope);\n\n          // remove the class, which is added automatically because we recompile the element and it\n          // becomes the compilation root\n          nullOption.removeClass('ng-scope');\n\n          // we need to remove it before calling selectElement.empty() because otherwise IE will\n          // remove the label from the element. wtf?\n          nullOption.remove();\n        }\n\n        // clear contents, we'll add what's needed based on the model\n        selectElement.empty();\n\n        selectElement.on('change', selectionChanged);\n\n        ctrl.$render = render;\n\n        scope.$watchCollection(valuesFn, scheduleRendering);\n        scope.$watchCollection(getLabels, scheduleRendering);\n\n        if (multiple) {\n          scope.$watchCollection(function() { return ctrl.$modelValue; }, scheduleRendering);\n        }\n\n        // ------------------------------------------------------------------ //\n\n        function callExpression(exprFn, key, value) {\n          locals[valueName] = value;\n          if (keyName) locals[keyName] = key;\n          return exprFn(scope, locals);\n        }\n\n        function selectionChanged() {\n          scope.$apply(function() {\n            var collection = valuesFn(scope) || [];\n            var viewValue;\n            if (multiple) {\n              viewValue = [];\n              forEach(selectElement.val(), function(selectedKey) {\n                  selectedKey = trackFn ? trackKeysCache[selectedKey] : selectedKey;\n                viewValue.push(getViewValue(selectedKey, collection[selectedKey]));\n              });\n            } else {\n              var selectedKey = trackFn ? trackKeysCache[selectElement.val()] : selectElement.val();\n              viewValue = getViewValue(selectedKey, collection[selectedKey]);\n            }\n            ctrl.$setViewValue(viewValue);\n            render();\n          });\n        }\n\n        function getViewValue(key, value) {\n          if (key === '?') {\n            return undefined;\n          } else if (key === '') {\n            return null;\n          } else {\n            var viewValueFn = selectAsFn ? selectAsFn : valueFn;\n            return callExpression(viewValueFn, key, value);\n          }\n        }\n\n        function getLabels() {\n          var values = valuesFn(scope);\n          var toDisplay;\n          if (values && isArray(values)) {\n            toDisplay = new Array(values.length);\n            for (var i = 0, ii = values.length; i < ii; i++) {\n              toDisplay[i] = callExpression(displayFn, i, values[i]);\n            }\n            return toDisplay;\n          } else if (values) {\n            // TODO: Add a test for this case\n            toDisplay = {};\n            for (var prop in values) {\n              if (values.hasOwnProperty(prop)) {\n                toDisplay[prop] = callExpression(displayFn, prop, values[prop]);\n              }\n            }\n          }\n          return toDisplay;\n        }\n\n        function createIsSelectedFn(viewValue) {\n          var selectedSet;\n          if (multiple) {\n            if (trackFn && isArray(viewValue)) {\n\n              selectedSet = new HashMap([]);\n              for (var trackIndex = 0; trackIndex < viewValue.length; trackIndex++) {\n                // tracking by key\n                selectedSet.put(callExpression(trackFn, null, viewValue[trackIndex]), true);\n              }\n            } else {\n              selectedSet = new HashMap(viewValue);\n            }\n          } else if (trackFn) {\n            viewValue = callExpression(trackFn, null, viewValue);\n          }\n\n          return function isSelected(key, value) {\n            var compareValueFn;\n            if (trackFn) {\n              compareValueFn = trackFn;\n            } else if (selectAsFn) {\n              compareValueFn = selectAsFn;\n            } else {\n              compareValueFn = valueFn;\n            }\n\n            if (multiple) {\n              return isDefined(selectedSet.remove(callExpression(compareValueFn, key, value)));\n            } else {\n              return viewValue === callExpression(compareValueFn, key, value);\n            }\n          };\n        }\n\n        function scheduleRendering() {\n          if (!renderScheduled) {\n            scope.$$postDigest(render);\n            renderScheduled = true;\n          }\n        }\n\n        /**\n         * A new labelMap is created with each render.\n         * This function is called for each existing option with added=false,\n         * and each new option with added=true.\n         * - Labels that are passed to this method twice,\n         * (once with added=true and once with added=false) will end up with a value of 0, and\n         * will cause no change to happen to the corresponding option.\n         * - Labels that are passed to this method only once with added=false will end up with a\n         * value of -1 and will eventually be passed to selectCtrl.removeOption()\n         * - Labels that are passed to this method only once with added=true will end up with a\n         * value of 1 and will eventually be passed to selectCtrl.addOption()\n        */\n        function updateLabelMap(labelMap, label, added) {\n          labelMap[label] = labelMap[label] || 0;\n          labelMap[label] += (added ? 1 : -1);\n        }\n\n        function render() {\n          renderScheduled = false;\n\n          // Temporary location for the option groups before we render them\n          var optionGroups = {'':[]},\n              optionGroupNames = [''],\n              optionGroupName,\n              optionGroup,\n              option,\n              existingParent, existingOptions, existingOption,\n              viewValue = ctrl.$viewValue,\n              values = valuesFn(scope) || [],\n              keys = keyName ? sortedKeys(values) : values,\n              key,\n              value,\n              groupLength, length,\n              groupIndex, index,\n              labelMap = {},\n              selected,\n              isSelected = createIsSelectedFn(viewValue),\n              anySelected = false,\n              lastElement,\n              element,\n              label,\n              optionId;\n\n          trackKeysCache = {};\n\n          // We now build up the list of options we need (we merge later)\n          for (index = 0; length = keys.length, index < length; index++) {\n            key = index;\n            if (keyName) {\n              key = keys[index];\n              if (key.charAt(0) === '$') continue;\n            }\n            value = values[key];\n\n            optionGroupName = callExpression(groupByFn, key, value) || '';\n            if (!(optionGroup = optionGroups[optionGroupName])) {\n              optionGroup = optionGroups[optionGroupName] = [];\n              optionGroupNames.push(optionGroupName);\n            }\n\n            selected = isSelected(key, value);\n            anySelected = anySelected || selected;\n\n            label = callExpression(displayFn, key, value); // what will be seen by the user\n\n            // doing displayFn(scope, locals) || '' overwrites zero values\n            label = isDefined(label) ? label : '';\n            optionId = trackFn ? trackFn(scope, locals) : (keyName ? keys[index] : index);\n            if (trackFn) {\n              trackKeysCache[optionId] = key;\n            }\n\n            optionGroup.push({\n              // either the index into array or key from object\n              id: optionId,\n              label: label,\n              selected: selected                   // determine if we should be selected\n            });\n          }\n          if (!multiple) {\n            if (nullOption || viewValue === null) {\n              // insert null option if we have a placeholder, or the model is null\n              optionGroups[''].unshift({id:'', label:'', selected:!anySelected});\n            } else if (!anySelected) {\n              // option could not be found, we have to insert the undefined item\n              optionGroups[''].unshift({id:'?', label:'', selected:true});\n            }\n          }\n\n          // Now we need to update the list of DOM nodes to match the optionGroups we computed above\n          for (groupIndex = 0, groupLength = optionGroupNames.length;\n               groupIndex < groupLength;\n               groupIndex++) {\n            // current option group name or '' if no group\n            optionGroupName = optionGroupNames[groupIndex];\n\n            // list of options for that group. (first item has the parent)\n            optionGroup = optionGroups[optionGroupName];\n\n            if (optionGroupsCache.length <= groupIndex) {\n              // we need to grow the optionGroups\n              existingParent = {\n                element: optGroupTemplate.clone().attr('label', optionGroupName),\n                label: optionGroup.label\n              };\n              existingOptions = [existingParent];\n              optionGroupsCache.push(existingOptions);\n              selectElement.append(existingParent.element);\n            } else {\n              existingOptions = optionGroupsCache[groupIndex];\n              existingParent = existingOptions[0];  // either SELECT (no group) or OPTGROUP element\n\n              // update the OPTGROUP label if not the same.\n              if (existingParent.label != optionGroupName) {\n                existingParent.element.attr('label', existingParent.label = optionGroupName);\n              }\n            }\n\n            lastElement = null;  // start at the beginning\n            for (index = 0, length = optionGroup.length; index < length; index++) {\n              option = optionGroup[index];\n              if ((existingOption = existingOptions[index + 1])) {\n                // reuse elements\n                lastElement = existingOption.element;\n                if (existingOption.label !== option.label) {\n                  updateLabelMap(labelMap, existingOption.label, false);\n                  updateLabelMap(labelMap, option.label, true);\n                  lastElement.text(existingOption.label = option.label);\n                  lastElement.prop('label', existingOption.label);\n                }\n                if (existingOption.id !== option.id) {\n                  lastElement.val(existingOption.id = option.id);\n                }\n                // lastElement.prop('selected') provided by jQuery has side-effects\n                if (lastElement[0].selected !== option.selected) {\n                  lastElement.prop('selected', (existingOption.selected = option.selected));\n                  if (msie) {\n                    // See #7692\n                    // The selected item wouldn't visually update on IE without this.\n                    // Tested on Win7: IE9, IE10 and IE11. Future IEs should be tested as well\n                    lastElement.prop('selected', existingOption.selected);\n                  }\n                }\n              } else {\n                // grow elements\n\n                // if it's a null option\n                if (option.id === '' && nullOption) {\n                  // put back the pre-compiled element\n                  element = nullOption;\n                } else {\n                  // jQuery(v1.4.2) Bug: We should be able to chain the method calls, but\n                  // in this version of jQuery on some browser the .text() returns a string\n                  // rather then the element.\n                  (element = optionTemplate.clone())\n                      .val(option.id)\n                      .prop('selected', option.selected)\n                      .attr('selected', option.selected)\n                      .prop('label', option.label)\n                      .text(option.label);\n                }\n\n                existingOptions.push(existingOption = {\n                    element: element,\n                    label: option.label,\n                    id: option.id,\n                    selected: option.selected\n                });\n                updateLabelMap(labelMap, option.label, true);\n                if (lastElement) {\n                  lastElement.after(element);\n                } else {\n                  existingParent.element.append(element);\n                }\n                lastElement = element;\n              }\n            }\n            // remove any excessive OPTIONs in a group\n            index++; // increment since the existingOptions[0] is parent element not OPTION\n            while (existingOptions.length > index) {\n              option = existingOptions.pop();\n              updateLabelMap(labelMap, option.label, false);\n              option.element.remove();\n            }\n          }\n          // remove any excessive OPTGROUPs from select\n          while (optionGroupsCache.length > groupIndex) {\n            // remove all the labels in the option group\n            optionGroup = optionGroupsCache.pop();\n            for (index = 1; index < optionGroup.length; ++index) {\n              updateLabelMap(labelMap, optionGroup[index].label, false);\n            }\n            optionGroup[0].element.remove();\n          }\n          forEach(labelMap, function(count, label) {\n            if (count > 0) {\n              selectCtrl.addOption(label);\n            } else if (count < 0) {\n              selectCtrl.removeOption(label);\n            }\n          });\n        }\n      }\n    }\n  };\n}];\n\nvar optionDirective = ['$interpolate', function($interpolate) {\n  var nullSelectCtrl = {\n    addOption: noop,\n    removeOption: noop\n  };\n\n  return {\n    restrict: 'E',\n    priority: 100,\n    compile: function(element, attr) {\n      if (isUndefined(attr.value)) {\n        var interpolateFn = $interpolate(element.text(), true);\n        if (!interpolateFn) {\n          attr.$set('value', element.text());\n        }\n      }\n\n      return function(scope, element, attr) {\n        var selectCtrlName = '$selectController',\n            parent = element.parent(),\n            selectCtrl = parent.data(selectCtrlName) ||\n              parent.parent().data(selectCtrlName); // in case we are in optgroup\n\n        if (!selectCtrl || !selectCtrl.databound) {\n          selectCtrl = nullSelectCtrl;\n        }\n\n        if (interpolateFn) {\n          scope.$watch(interpolateFn, function interpolateWatchAction(newVal, oldVal) {\n            attr.$set('value', newVal);\n            if (oldVal !== newVal) {\n              selectCtrl.removeOption(oldVal);\n            }\n            selectCtrl.addOption(newVal, element);\n          });\n        } else {\n          selectCtrl.addOption(attr.value, element);\n        }\n\n        element.on('$destroy', function() {\n          selectCtrl.removeOption(attr.value);\n        });\n      };\n    }\n  };\n}];\n\nvar styleDirective = valueFn({\n  restrict: 'E',\n  terminal: false\n});\n\nvar requiredDirective = function() {\n  return {\n    restrict: 'A',\n    require: '?ngModel',\n    link: function(scope, elm, attr, ctrl) {\n      if (!ctrl) return;\n      attr.required = true; // force truthy in case we are on non input element\n\n      ctrl.$validators.required = function(modelValue, viewValue) {\n        return !attr.required || !ctrl.$isEmpty(viewValue);\n      };\n\n      attr.$observe('required', function() {\n        ctrl.$validate();\n      });\n    }\n  };\n};\n\n\nvar patternDirective = function() {\n  return {\n    restrict: 'A',\n    require: '?ngModel',\n    link: function(scope, elm, attr, ctrl) {\n      if (!ctrl) return;\n\n      var regexp, patternExp = attr.ngPattern || attr.pattern;\n      attr.$observe('pattern', function(regex) {\n        if (isString(regex) && regex.length > 0) {\n          regex = new RegExp('^' + regex + '$');\n        }\n\n        if (regex && !regex.test) {\n          throw minErr('ngPattern')('noregexp',\n            'Expected {0} to be a RegExp but was {1}. Element: {2}', patternExp,\n            regex, startingTag(elm));\n        }\n\n        regexp = regex || undefined;\n        ctrl.$validate();\n      });\n\n      ctrl.$validators.pattern = function(value) {\n        return ctrl.$isEmpty(value) || isUndefined(regexp) || regexp.test(value);\n      };\n    }\n  };\n};\n\n\nvar maxlengthDirective = function() {\n  return {\n    restrict: 'A',\n    require: '?ngModel',\n    link: function(scope, elm, attr, ctrl) {\n      if (!ctrl) return;\n\n      var maxlength = -1;\n      attr.$observe('maxlength', function(value) {\n        var intVal = int(value);\n        maxlength = isNaN(intVal) ? -1 : intVal;\n        ctrl.$validate();\n      });\n      ctrl.$validators.maxlength = function(modelValue, viewValue) {\n        return (maxlength < 0) || ctrl.$isEmpty(viewValue) || (viewValue.length <= maxlength);\n      };\n    }\n  };\n};\n\nvar minlengthDirective = function() {\n  return {\n    restrict: 'A',\n    require: '?ngModel',\n    link: function(scope, elm, attr, ctrl) {\n      if (!ctrl) return;\n\n      var minlength = 0;\n      attr.$observe('minlength', function(value) {\n        minlength = int(value) || 0;\n        ctrl.$validate();\n      });\n      ctrl.$validators.minlength = function(modelValue, viewValue) {\n        return ctrl.$isEmpty(viewValue) || viewValue.length >= minlength;\n      };\n    }\n  };\n};\n\n  if (window.angular.bootstrap) {\n    //AngularJS is already loaded, so we can return here...\n    console.log('WARNING: Tried to load angular more than once.');\n    return;\n  }\n\n  //try to bind to jquery now so that one can write jqLite(document).ready()\n  //but we will rebind on bootstrap again.\n  bindJQuery();\n\n  publishExternalAPI(angular);\n\n  jqLite(document).ready(function() {\n    angularInit(document, bootstrap);\n  });\n\n})(window, document);\n\n!window.angular.$$csp() && window.angular.element(document).find('head').prepend('<style type=\"text/css\">@charset \"UTF-8\";[ng\\\\:cloak],[ng-cloak],[data-ng-cloak],[x-ng-cloak],.ng-cloak,.x-ng-cloak,.ng-hide:not(.ng-hide-animate){display:none !important;}ng\\\\:form{display:block;}</style>');"
  },
  {
    "path": "flowable-ui-web/idm/libs/autofill-events_1.0.0/autofill-event.js",
    "content": "/**\n * Autofill event polyfill ##version:1.0.0##\n * (c) 2014 Google, Inc.\n * License: MIT\n */\n(function(window) {\n  var $ = window.jQuery || window.angular.element;\n  var rootElement = window.document.documentElement,\n    $rootElement = $(rootElement);\n\n  addGlobalEventListener('change', markValue);\n  addValueChangeByJsListener(markValue);\n\n  $.prototype.checkAndTriggerAutoFillEvent = jqCheckAndTriggerAutoFillEvent;\n\n  // Need to use blur and not change event\n  // as Chrome does not fire change events in all cases an input is changed\n  // (e.g. when starting to type and then finish the input by auto filling a username)\n  addGlobalEventListener('blur', function(target) {\n    // setTimeout needed for Chrome as it fills other\n    // form fields a little later...\n    window.setTimeout(function() {\n      findParentForm(target).find('input').checkAndTriggerAutoFillEvent();\n    }, 20);\n  });\n\n  function DOMContentLoadedListener() {\n      // mark all values that are present when the DOM is ready.\n      // We don't need to trigger a change event here,\n      // as js libs start with those values already being set!\n      forEach(document.getElementsByTagName('input'), markValue);\n\n      // The timeout is needed for Chrome as it auto fills\n      // login forms some time after DOMContentLoaded!\n      window.setTimeout(function() {\n        $rootElement.find('input').checkAndTriggerAutoFillEvent();\n      }, 200);\n  }\n\n  //IE8 compatibility issue\n  if(!window.document.addEventListener){\n    window.document.attachEvent('DOMContentLoaded', DOMContentLoadedListener);    \n  }else{\n    window.document.addEventListener('DOMContentLoaded', DOMContentLoadedListener, false);\n  }\n\n  return;\n\n  // ----------\n\n  function jqCheckAndTriggerAutoFillEvent() {\n    var i, el;\n    for (i=0; i<this.length; i++) {\n      el = this[i];\n      if (!valueMarked(el)) {\n        markValue(el);\n        triggerChangeEvent(el);\n      }\n    }\n  }\n\n  function valueMarked(el) {\n    var val = el.value,\n         $$currentValue = el.$$currentValue;\n    if (!val && !$$currentValue) {\n      return true;\n    }\n    return val === $$currentValue;\n  }\n\n  function markValue(el) {\n    el.$$currentValue = el.value;\n  }\n\n  function addValueChangeByJsListener(listener) {\n    var jq = window.jQuery || window.angular.element,\n        jqProto = jq.prototype;\n    var _val = jqProto.val;\n    jqProto.val = function(newValue) {\n      var res = _val.apply(this, arguments);\n      if (arguments.length > 0) {\n        forEach(this, function(el) {\n          listener(el, newValue);\n        });\n      }\n      return res;\n    }\n  }\n\n  function addGlobalEventListener(eventName, listener) {\n      // Use a capturing event listener so that\n      // we also get the event when it's stopped!\n      // Also, the blur event does not bubble.\n      if(!rootElement.addEventListener){\n          rootElement.attachEvent(eventName, onEvent);      \n      }else{\n          rootElement.addEventListener(eventName, onEvent, true);\n      }\n\n      function onEvent(event) {\n          var target = event.target;\n          listener(target);\n      }\n  }\n\n  function findParentForm(el) {\n    while (el) {\n      if (el.nodeName === 'FORM') {\n        return $(el);\n      }\n      el = el.parentNode;\n    }\n    return $();\n  }\n\n  function forEach(arr, listener) {\n    if (arr.forEach) {\n      return arr.forEach(listener);\n    }\n    var i;\n    for (i=0; i<arr.length; i++) {\n      listener(arr[i]);\n    }\n  }\n\n  function triggerChangeEvent(element) {\n    var doc = window.document;\n    var event = doc.createEvent(\"HTMLEvents\");\n    event.initEvent(\"change\", true, true);\n    element.dispatchEvent(event);\n  }\n\n})(window);\n"
  },
  {
    "path": "flowable-ui-web/idm/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": "flowable-ui-web/idm/libs/bootstrap-daterangepicker_1.3.7/daterangepicker.js",
    "content": "/**\n * @version: 1.3.7\n * @author: Dan Grossman http://www.dangrossman.info/\n * @date: 2014-04-29\n * @copyright: Copyright (c) 2012-2014 Dan Grossman. All rights reserved.\n * @license: Licensed under Apache License v2.0. See http://www.apache.org/licenses/LICENSE-2.0\n * @website: http://www.improvely.com/\n */\n!function ($, moment) {\n\n    var DateRangePicker = function (element, options, cb) {\n\n        // by default, the daterangepicker element is placed at the bottom of HTML body\n        this.parentEl = 'body';\n\n        //element that triggered the date range picker\n        this.element = $(element);\n\n        //create the picker HTML object\n        var DRPTemplate = '<div class=\"daterangepicker dropdown-menu\">' +\n            '<div class=\"calendar left\"></div>' +\n            '<div class=\"calendar right\"></div>' +\n            '<div class=\"ranges\">' +\n            '<div class=\"range_inputs\">' +\n            '<div class=\"daterangepicker_start_input\">' +\n            '<label for=\"daterangepicker_start\"></label>' +\n            '<input class=\"input-mini\" type=\"text\" name=\"daterangepicker_start\" value=\"\" disabled=\"disabled\" />' +\n            '</div>' +\n            '<div class=\"daterangepicker_end_input\">' +\n            '<label for=\"daterangepicker_end\"></label>' +\n            '<input class=\"input-mini\" type=\"text\" name=\"daterangepicker_end\" value=\"\" disabled=\"disabled\" />' +\n            '</div>' +\n            '<button class=\"applyBtn\" disabled=\"disabled\"></button>&nbsp;' +\n            '<button class=\"cancelBtn\"></button>' +\n            '</div>' +\n            '</div>' +\n            '</div>';\n\n        //custom options\n        if (typeof options !== 'object' || options === null)\n            options = {};\n\n        this.parentEl = (typeof options === 'object' && options.parentEl && $(options.parentEl).length) ? $(options.parentEl) : $(this.parentEl);\n        this.container = $(DRPTemplate).appendTo(this.parentEl);\n\n        this.setOptions(options, cb);\n\n        //apply CSS classes and labels to buttons\n        var c = this.container;\n        $.each(this.buttonClasses, function (idx, val) {\n            c.find('button').addClass(val);\n        });\n        this.container.find('.daterangepicker_start_input label').html(this.locale.fromLabel);\n        this.container.find('.daterangepicker_end_input label').html(this.locale.toLabel);\n        if (this.applyClass.length)\n            this.container.find('.applyBtn').addClass(this.applyClass);\n        if (this.cancelClass.length)\n            this.container.find('.cancelBtn').addClass(this.cancelClass);\n        this.container.find('.applyBtn').html(this.locale.applyLabel);\n        this.container.find('.cancelBtn').html(this.locale.cancelLabel);\n\n        //event listeners\n\n        this.container.find('.calendar')\n            .on('click.daterangepicker', '.prev', $.proxy(this.clickPrev, this))\n            .on('click.daterangepicker', '.next', $.proxy(this.clickNext, this))\n            .on('click.daterangepicker', 'td.available', $.proxy(this.clickDate, this))\n            .on('mouseenter.daterangepicker', 'td.available', $.proxy(this.enterDate, this))\n            .on('mouseleave.daterangepicker', 'td.available', $.proxy(this.updateFormInputs, this))\n            .on('change.daterangepicker', 'select.yearselect', $.proxy(this.updateMonthYear, this))\n            .on('change.daterangepicker', 'select.monthselect', $.proxy(this.updateMonthYear, this))\n            .on('change.daterangepicker', 'select.hourselect,select.minuteselect,select.ampmselect', $.proxy(this.updateTime, this));\n\n        this.container.find('.ranges')\n            .on('click.daterangepicker', 'button.applyBtn', $.proxy(this.clickApply, this))\n            .on('click.daterangepicker', 'button.cancelBtn', $.proxy(this.clickCancel, this))\n            .on('click.daterangepicker', '.daterangepicker_start_input,.daterangepicker_end_input', $.proxy(this.showCalendars, this))\n            .on('click.daterangepicker', 'li', $.proxy(this.clickRange, this))\n            .on('mouseenter.daterangepicker', 'li', $.proxy(this.enterRange, this))\n            .on('mouseleave.daterangepicker', 'li', $.proxy(this.updateFormInputs, this));\n\n        if (this.element.is('input')) {\n            this.element.on({\n                'click.daterangepicker': $.proxy(this.show, this),\n                'focus.daterangepicker': $.proxy(this.show, this),\n                'keyup.daterangepicker': $.proxy(this.updateFromControl, this)\n            });\n        } else {\n            this.element.on('click.daterangepicker', $.proxy(this.toggle, this));\n        }\n\n    };\n\n    DateRangePicker.prototype = {\n\n        constructor: DateRangePicker,\n\n        setOptions: function(options, callback) {\n\n            this.startDate = moment().startOf('day');\n            this.endDate = moment().endOf('day');\n            this.minDate = false;\n            this.maxDate = false;\n            this.dateLimit = false;\n\n            this.showDropdowns = false;\n            this.showWeekNumbers = false;\n            this.timePicker = false;\n            this.timePickerIncrement = 30;\n            this.timePicker12Hour = true;\n            this.singleDatePicker = false;\n            this.ranges = {};\n\n            this.opens = 'right';\n            if (this.element.hasClass('pull-right'))\n                this.opens = 'left';\n\n            this.buttonClasses = ['btn', 'btn-small'];\n            this.applyClass = 'btn-success';\n            this.cancelClass = 'btn-default';\n\n            this.format = 'MM/DD/YYYY';\n            this.separator = ' - ';\n\n            this.locale = {\n                applyLabel: 'Apply',\n                cancelLabel: 'Cancel',\n                fromLabel: 'From',\n                toLabel: 'To',\n                weekLabel: 'W',\n                customRangeLabel: 'Custom Range',\n                daysOfWeek: moment()._lang._weekdaysMin.slice(),\n                monthNames: moment()._lang._monthsShort.slice(),\n                firstDay: 0\n            };\n\n            this.cb = function () { };\n\n            if (typeof options.format === 'string')\n                this.format = options.format;\n\n            if (typeof options.separator === 'string')\n                this.separator = options.separator;\n\n            if (typeof options.startDate === 'string')\n                this.startDate = moment(options.startDate, this.format);\n\n            if (typeof options.endDate === 'string')\n                this.endDate = moment(options.endDate, this.format);\n\n            if (typeof options.minDate === 'string')\n                this.minDate = moment(options.minDate, this.format);\n\n            if (typeof options.maxDate === 'string')\n                this.maxDate = moment(options.maxDate, this.format);\n\n            if (typeof options.startDate === 'object')\n                this.startDate = moment(options.startDate);\n\n            if (typeof options.endDate === 'object')\n                this.endDate = moment(options.endDate);\n\n            if (typeof options.minDate === 'object')\n                this.minDate = moment(options.minDate);\n\n            if (typeof options.maxDate === 'object')\n                this.maxDate = moment(options.maxDate);\n\n            if (typeof options.applyClass === 'string')\n                this.applyClass = options.applyClass;\n\n            if (typeof options.cancelClass === 'string')\n                this.cancelClass = options.cancelClass;\n\n            if (typeof options.dateLimit === 'object')\n                this.dateLimit = options.dateLimit;\n\n            // update day names order to firstDay\n            if (typeof options.locale === 'object') {\n\n                if (typeof options.locale.daysOfWeek === 'object') {\n                    // Create a copy of daysOfWeek to avoid modification of original\n                    // options object for reusability in multiple daterangepicker instances\n                    this.locale.daysOfWeek = options.locale.daysOfWeek.slice();\n                }\n\n                if (typeof options.locale.monthNames === 'object') {\n                    this.locale.monthNames = options.locale.monthNames.slice();\n                }\n\n                if (typeof options.locale.firstDay === 'number') {\n                    this.locale.firstDay = options.locale.firstDay;\n                    var iterator = options.locale.firstDay;\n                    while (iterator > 0) {\n                        this.locale.daysOfWeek.push(this.locale.daysOfWeek.shift());\n                        iterator--;\n                    }\n                }\n\n                if (typeof options.locale.applyLabel === 'string') {\n                    this.locale.applyLabel = options.locale.applyLabel;\n                }\n\n                if (typeof options.locale.cancelLabel === 'string') {\n                    this.locale.cancelLabel = options.locale.cancelLabel;\n                }\n\n                if (typeof options.locale.fromLabel === 'string') {\n                    this.locale.fromLabel = options.locale.fromLabel;\n                }\n\n                if (typeof options.locale.toLabel === 'string') {\n                    this.locale.toLabel = options.locale.toLabel;\n                }\n\n                if (typeof options.locale.weekLabel === 'string') {\n                    this.locale.weekLabel = options.locale.weekLabel;\n                }\n\n                if (typeof options.locale.customRangeLabel === 'string') {\n                    this.locale.customRangeLabel = options.locale.customRangeLabel;\n                }\n            }\n\n            if (typeof options.opens === 'string')\n                this.opens = options.opens;\n\n            if (typeof options.showWeekNumbers === 'boolean') {\n                this.showWeekNumbers = options.showWeekNumbers;\n            }\n\n            if (typeof options.buttonClasses === 'string') {\n                this.buttonClasses = [options.buttonClasses];\n            }\n\n            if (typeof options.buttonClasses === 'object') {\n                this.buttonClasses = options.buttonClasses;\n            }\n\n            if (typeof options.showDropdowns === 'boolean') {\n                this.showDropdowns = options.showDropdowns;\n            }\n\n            if (typeof options.singleDatePicker === 'boolean') {\n                this.singleDatePicker = options.singleDatePicker;\n            }\n\n            if (typeof options.timePicker === 'boolean') {\n                this.timePicker = options.timePicker;\n            }\n\n            if (typeof options.timePickerIncrement === 'number') {\n                this.timePickerIncrement = options.timePickerIncrement;\n            }\n\n            if (typeof options.timePicker12Hour === 'boolean') {\n                this.timePicker12Hour = options.timePicker12Hour;\n            }\n\n            var start, end, range;\n\n            //if no start/end dates set, check if an input element contains initial values\n            if (typeof options.startDate === 'undefined' && typeof options.endDate === 'undefined') {\n                if ($(this.element).is('input[type=text]')) {\n                    var val = $(this.element).val();\n                    var split = val.split(this.separator);\n                    start = end = null;\n                    if (split.length == 2) {\n                        start = moment(split[0], this.format);\n                        end = moment(split[1], this.format);\n                    } else if (this.singleDatePicker) {\n                        start = moment(val, this.format);\n                        end = moment(val, this.format);\n                    }\n                    if (start !== null && end !== null) {\n                        this.startDate = start;\n                        this.endDate = end;\n                    }\n                }\n            }\n\n            if (typeof options.ranges === 'object') {\n                for (range in options.ranges) {\n\n                    start = moment(options.ranges[range][0]);\n                    end = moment(options.ranges[range][1]);\n\n                    // If we have a min/max date set, bound this range\n                    // to it, but only if it would otherwise fall\n                    // outside of the min/max.\n                    if (this.minDate && start.isBefore(this.minDate))\n                        start = moment(this.minDate);\n\n                    if (this.maxDate && end.isAfter(this.maxDate))\n                        end = moment(this.maxDate);\n\n                    // If the end of the range is before the minimum (if min is set) OR\n                    // the start of the range is after the max (also if set) don't display this\n                    // range option.\n                    if ((this.minDate && end.isBefore(this.minDate)) || (this.maxDate && start.isAfter(this.maxDate))) {\n                        continue;\n                    }\n\n                    this.ranges[range] = [start, end];\n                }\n\n                var list = '<ul>';\n                for (range in this.ranges) {\n                    list += '<li>' + range + '</li>';\n                }\n                list += '<li>' + this.locale.customRangeLabel + '</li>';\n                list += '</ul>';\n                this.container.find('.ranges ul').remove();\n                this.container.find('.ranges').prepend(list);\n            }\n\n            if (typeof callback === 'function') {\n                this.cb = callback;\n            }\n\n            if (!this.timePicker) {\n                this.startDate = this.startDate.startOf('day');\n                this.endDate = this.endDate.endOf('day');\n            }\n\n            if (this.singleDatePicker) {\n                this.opens = 'right';\n                this.container.find('.calendar.right').show();\n                this.container.find('.calendar.left').hide();\n                this.container.find('.ranges').hide();\n                if (!this.container.find('.calendar.right').hasClass('single'))\n                    this.container.find('.calendar.right').addClass('single');\n            } else {\n                this.container.find('.calendar.right').removeClass('single');\n                this.container.find('.ranges').show();\n            }\n\n            this.oldStartDate = this.startDate.clone();\n            this.oldEndDate = this.endDate.clone();\n            this.oldChosenLabel = this.chosenLabel;\n\n            this.leftCalendar = {\n                month: moment([this.startDate.year(), this.startDate.month(), 1, this.startDate.hour(), this.startDate.minute()]),\n                calendar: []\n            };\n\n            this.rightCalendar = {\n                month: moment([this.endDate.year(), this.endDate.month(), 1, this.endDate.hour(), this.endDate.minute()]),\n                calendar: []\n            };\n\n            if (this.opens == 'right') {\n                //swap calendar positions\n                var left = this.container.find('.calendar.left');\n                var right = this.container.find('.calendar.right');\n                left.removeClass('left').addClass('right');\n                right.removeClass('right').addClass('left');\n            }\n\n            if (typeof options.ranges === 'undefined' && !this.singleDatePicker) {\n                this.container.addClass('show-calendar');\n            }\n\n            this.container.addClass('opens' + this.opens);\n\n            this.updateView();\n            this.updateCalendars();\n\n        },\n\n        setStartDate: function(startDate) {\n            if (typeof startDate === 'string')\n                this.startDate = moment(startDate, this.format);\n\n            if (typeof startDate === 'object')\n                this.startDate = moment(startDate);\n\n            if (!this.timePicker)\n                this.startDate = this.startDate.startOf('day');\n\n            this.oldStartDate = this.startDate.clone();\n\n            this.updateView();\n            this.updateCalendars();\n        },\n\n        setEndDate: function(endDate) {\n            if (typeof endDate === 'string')\n                this.endDate = moment(endDate, this.format);\n\n            if (typeof endDate === 'object')\n                this.endDate = moment(endDate);\n\n            if (!this.timePicker)\n                this.endDate = this.endDate.endOf('day');\n\n            this.oldEndDate = this.endDate.clone();\n\n            this.updateView();\n            this.updateCalendars();\n        },\n\n        updateView: function () {\n            this.leftCalendar.month.month(this.startDate.month()).year(this.startDate.year());\n            this.rightCalendar.month.month(this.endDate.month()).year(this.endDate.year());\n            this.updateFormInputs();\n        },\n\n        updateFormInputs: function () {\n            this.container.find('input[name=daterangepicker_start]').val(this.startDate.format(this.format));\n            this.container.find('input[name=daterangepicker_end]').val(this.endDate.format(this.format));\n\n            if (this.startDate.isSame(this.endDate) || this.startDate.isBefore(this.endDate)) {\n                this.container.find('button.applyBtn').removeAttr('disabled');\n            } else {\n                this.container.find('button.applyBtn').attr('disabled', 'disabled');\n            }\n        },\n\n        updateFromControl: function () {\n            if (!this.element.is('input')) return;\n            if (!this.element.val().length) return;\n\n            var dateString = this.element.val().split(this.separator),\n                start = null,\n                end = null;\n\n            if(dateString.length === 2) {\n                start = moment(dateString[0], this.format);\n                end = moment(dateString[1], this.format);\n            }\n\n            if (this.singleDatePicker || start === null || end === null) {\n                start = moment(this.element.val(), this.format);\n                end = start;\n            }\n\n            if (end.isBefore(start)) return;\n\n            this.oldStartDate = this.startDate.clone();\n            this.oldEndDate = this.endDate.clone();\n\n            this.startDate = start;\n            this.endDate = end;\n\n            if (!this.startDate.isSame(this.oldStartDate) || !this.endDate.isSame(this.oldEndDate))\n                this.notify();\n\n            this.updateCalendars();\n        },\n\n        notify: function () {\n            this.updateView();\n            this.cb(this.startDate, this.endDate, this.chosenLabel);\n        },\n\n        move: function () {\n            var parentOffset = { top: 0, left: 0 };\n            if (!this.parentEl.is('body')) {\n                parentOffset = {\n                    top: this.parentEl.offset().top - this.parentEl.scrollTop(),\n                    left: this.parentEl.offset().left - this.parentEl.scrollLeft()\n                };\n            }\n\n            if (this.opens == 'left') {\n                this.container.css({\n                    top: this.element.offset().top + this.element.outerHeight() - parentOffset.top,\n                    right: $(window).width() - this.element.offset().left - this.element.outerWidth() - parentOffset.left,\n                    left: 'auto'\n                });\n                if (this.container.offset().left < 0) {\n                    this.container.css({\n                        right: 'auto',\n                        left: 9\n                    });\n                }\n            } else {\n                this.container.css({\n                    top: this.element.offset().top + this.element.outerHeight() - parentOffset.top,\n                    left: this.element.offset().left - parentOffset.left,\n                    right: 'auto'\n                });\n                if (this.container.offset().left + this.container.outerWidth() > $(window).width()) {\n                    this.container.css({\n                        left: 'auto',\n                        right: 0\n                    });\n                }\n            }\n        },\n\n        toggle: function (e) {\n            if (this.element.hasClass('active')) {\n                this.hide();\n            } else {\n                this.show();\n            }\n        },\n\n        show: function (e) {\n            this.element.addClass('active');\n            this.container.show();\n            this.move();\n\n            // Create a click proxy that is private to this instance of datepicker, for unbinding\n            this._outsideClickProxy = $.proxy(function (e) { this.outsideClick(e); }, this);\n            // Bind global datepicker mousedown for hiding and\n            $(document)\n                .on('mousedown.daterangepicker', this._outsideClickProxy)\n                // also explicitly play nice with Bootstrap dropdowns, which stopPropagation when clicking them\n                .on('click.daterangepicker', '[data-toggle=dropdown]', this._outsideClickProxy)\n                // and also close when focus changes to outside the picker (eg. tabbing between controls)\n                .on('focusin.daterangepicker', this._outsideClickProxy);\n\n            this.element.trigger('show.daterangepicker', this);\n        },\n\n        outsideClick: function (e) {\n            var target = $(e.target);\n            // if the page is clicked anywhere except within the daterangerpicker/button\n            // itself then call this.hide()\n            if (\n                target.closest(this.element).length ||\n                target.closest(this.container).length ||\n                target.closest('.calendar-date').length\n                ) return;\n            this.hide();\n        },\n\n        hide: function (e) {\n            $(document)\n                .off('mousedown.daterangepicker', this._outsideClickProxy)\n                .off('click.daterangepicker', this._outsideClickProxy)\n                .off('focusin.daterangepicker', this._outsideClickProxy);\n\n            this.element.removeClass('active');\n            this.container.hide();\n\n            if (!this.startDate.isSame(this.oldStartDate) || !this.endDate.isSame(this.oldEndDate))\n                this.notify();\n\n            this.oldStartDate = this.startDate.clone();\n            this.oldEndDate = this.endDate.clone();\n\n            this.element.trigger('hide.daterangepicker', this);\n        },\n\n        enterRange: function (e) {\n            // mouse pointer has entered a range label\n            var label = e.target.innerHTML;\n            if (label == this.locale.customRangeLabel) {\n                this.updateView();\n            } else {\n                var dates = this.ranges[label];\n                this.container.find('input[name=daterangepicker_start]').val(dates[0].format(this.format));\n                this.container.find('input[name=daterangepicker_end]').val(dates[1].format(this.format));\n            }\n        },\n\n        showCalendars: function() {\n            this.container.addClass('show-calendar');\n            this.move();\n        },\n\n        hideCalendars: function() {\n            this.container.removeClass('show-calendar');\n        },\n\n        updateInputText: function() {\n            if (this.element.is('input') && !this.singleDatePicker) {\n                this.element.val(this.startDate.format(this.format) + this.separator + this.endDate.format(this.format));\n            } else if (this.element.is('input')) {\n                this.element.val(this.startDate.format(this.format));\n            }\n        },\n\n        clickRange: function (e) {\n            var label = e.target.innerHTML;\n            this.chosenLabel = label;\n            if (label == this.locale.customRangeLabel) {\n                this.showCalendars();\n            } else {\n                var dates = this.ranges[label];\n\n                this.startDate = dates[0];\n                this.endDate = dates[1];\n\n                if (!this.timePicker) {\n                    this.startDate.startOf('day');\n                    this.endDate.endOf('day');\n                }\n\n                this.leftCalendar.month.month(this.startDate.month()).year(this.startDate.year()).hour(this.startDate.hour()).minute(this.startDate.minute());\n                this.rightCalendar.month.month(this.endDate.month()).year(this.endDate.year()).hour(this.endDate.hour()).minute(this.endDate.minute());\n                this.updateCalendars();\n\n                this.updateInputText();\n\n                this.hideCalendars();\n                this.hide();\n                this.element.trigger('apply.daterangepicker', this);\n            }\n        },\n\n        clickPrev: function (e) {\n            var cal = $(e.target).parents('.calendar');\n            if (cal.hasClass('left')) {\n                this.leftCalendar.month.subtract('month', 1);\n            } else {\n                this.rightCalendar.month.subtract('month', 1);\n            }\n            this.updateCalendars();\n        },\n\n        clickNext: function (e) {\n            var cal = $(e.target).parents('.calendar');\n            if (cal.hasClass('left')) {\n                this.leftCalendar.month.add('month', 1);\n            } else {\n                this.rightCalendar.month.add('month', 1);\n            }\n            this.updateCalendars();\n        },\n\n        enterDate: function (e) {\n\n            var title = $(e.target).attr('data-title');\n            var row = title.substr(1, 1);\n            var col = title.substr(3, 1);\n            var cal = $(e.target).parents('.calendar');\n\n            if (cal.hasClass('left')) {\n                this.container.find('input[name=daterangepicker_start]').val(this.leftCalendar.calendar[row][col].format(this.format));\n            } else {\n                this.container.find('input[name=daterangepicker_end]').val(this.rightCalendar.calendar[row][col].format(this.format));\n            }\n\n        },\n\n        clickDate: function (e) {\n            var title = $(e.target).attr('data-title');\n            var row = title.substr(1, 1);\n            var col = title.substr(3, 1);\n            var cal = $(e.target).parents('.calendar');\n\n            var startDate, endDate;\n            if (cal.hasClass('left')) {\n                startDate = this.leftCalendar.calendar[row][col];\n                endDate = this.endDate;\n                if (typeof this.dateLimit === 'object') {\n                    var maxDate = moment(startDate).add(this.dateLimit).startOf('day');\n                    if (endDate.isAfter(maxDate)) {\n                        endDate = maxDate;\n                    }\n                }\n            } else {\n                startDate = this.startDate;\n                endDate = this.rightCalendar.calendar[row][col];\n                if (typeof this.dateLimit === 'object') {\n                    var minDate = moment(endDate).subtract(this.dateLimit).startOf('day');\n                    if (startDate.isBefore(minDate)) {\n                        startDate = minDate;\n                    }\n                }\n            }\n\n            if (this.singleDatePicker && cal.hasClass('left')) {\n                endDate = startDate.clone();\n            } else if (this.singleDatePicker && cal.hasClass('right')) {\n                startDate = endDate.clone();\n            }\n\n            cal.find('td').removeClass('active');\n\n            if (startDate.isSame(endDate) || startDate.isBefore(endDate)) {\n                $(e.target).addClass('active');\n                this.startDate = startDate;\n                this.endDate = endDate;\n                this.chosenLabel = this.locale.customRangeLabel;\n            } else if (startDate.isAfter(endDate)) {\n                $(e.target).addClass('active');\n                var difference = this.endDate.diff(this.startDate);\n                this.startDate = startDate;\n                this.endDate = moment(startDate).add('ms', difference);\n                this.chosenLabel = this.locale.customRangeLabel;\n            }\n\n            this.leftCalendar.month.month(this.startDate.month()).year(this.startDate.year());\n            this.rightCalendar.month.month(this.endDate.month()).year(this.endDate.year());\n            this.updateCalendars();\n\n            if (!this.timePicker)\n                endDate.endOf('day');\n\n            if (this.singleDatePicker)\n                this.clickApply();\n        },\n\n        clickApply: function (e) {\n            this.updateInputText();\n            this.hide();\n            this.element.trigger('apply.daterangepicker', this);\n        },\n\n        clickCancel: function (e) {\n            this.startDate = this.oldStartDate;\n            this.endDate = this.oldEndDate;\n            this.chosenLabel = this.oldChosenLabel;\n            this.updateView();\n            this.updateCalendars();\n            this.hide();\n            this.element.trigger('cancel.daterangepicker', this);\n        },\n\n        updateMonthYear: function (e) {\n            var isLeft = $(e.target).closest('.calendar').hasClass('left'),\n                leftOrRight = isLeft ? 'left' : 'right',\n                cal = this.container.find('.calendar.'+leftOrRight);\n\n            // Month must be Number for new moment versions\n            var month = parseInt(cal.find('.monthselect').val(), 10);\n            var year = cal.find('.yearselect').val();\n\n            this[leftOrRight+'Calendar'].month.month(month).year(year);\n            this.updateCalendars();\n        },\n\n        updateTime: function(e) {\n\n            var cal = $(e.target).closest('.calendar'),\n                isLeft = cal.hasClass('left');\n\n            var hour = parseInt(cal.find('.hourselect').val(), 10);\n            var minute = parseInt(cal.find('.minuteselect').val(), 10);\n\n            if (this.timePicker12Hour) {\n                var ampm = cal.find('.ampmselect').val();\n                if (ampm === 'PM' && hour < 12)\n                    hour += 12;\n                if (ampm === 'AM' && hour === 12)\n                    hour = 0;\n            }\n\n            if (isLeft) {\n                var start = this.startDate.clone();\n                start.hour(hour);\n                start.minute(minute);\n                this.startDate = start;\n                this.leftCalendar.month.hour(hour).minute(minute);\n            } else {\n                var end = this.endDate.clone();\n                end.hour(hour);\n                end.minute(minute);\n                this.endDate = end;\n                this.rightCalendar.month.hour(hour).minute(minute);\n            }\n\n            this.updateCalendars();\n        },\n\n        updateCalendars: function () {\n            this.leftCalendar.calendar = this.buildCalendar(this.leftCalendar.month.month(), this.leftCalendar.month.year(), this.leftCalendar.month.hour(), this.leftCalendar.month.minute(), 'left');\n            this.rightCalendar.calendar = this.buildCalendar(this.rightCalendar.month.month(), this.rightCalendar.month.year(), this.rightCalendar.month.hour(), this.rightCalendar.month.minute(), 'right');\n            this.container.find('.calendar.left').empty().html(this.renderCalendar(this.leftCalendar.calendar, this.startDate, this.minDate, this.maxDate));\n            this.container.find('.calendar.right').empty().html(this.renderCalendar(this.rightCalendar.calendar, this.endDate, this.startDate, this.maxDate));\n\n            this.container.find('.ranges li').removeClass('active');\n            var customRange = true;\n            var i = 0;\n            for (var range in this.ranges) {\n                if (this.timePicker) {\n                    if (this.startDate.isSame(this.ranges[range][0]) && this.endDate.isSame(this.ranges[range][1])) {\n                        customRange = false;\n                        this.chosenLabel = this.container.find('.ranges li:eq(' + i + ')')\n                            .addClass('active').html();\n                    }\n                } else {\n                    //ignore times when comparing dates if time picker is not enabled\n                    if (this.startDate.format('YYYY-MM-DD') == this.ranges[range][0].format('YYYY-MM-DD') && this.endDate.format('YYYY-MM-DD') == this.ranges[range][1].format('YYYY-MM-DD')) {\n                        customRange = false;\n                        this.chosenLabel = this.container.find('.ranges li:eq(' + i + ')')\n                            .addClass('active').html();\n                    }\n                }\n                i++;\n            }\n            if (customRange) {\n                this.chosenLabel = this.container.find('.ranges li:last')\n                    .addClass('active').html();\n            }\n        },\n\n        buildCalendar: function (month, year, hour, minute, side) {\n            var firstDay = moment([year, month, 1]);\n            var lastMonth = moment(firstDay).subtract('month', 1).month();\n            var lastYear = moment(firstDay).subtract('month', 1).year();\n\n            var daysInLastMonth = moment([lastYear, lastMonth]).daysInMonth();\n\n            var dayOfWeek = firstDay.day();\n\n            var i;\n\n            //initialize a 6 rows x 7 columns array for the calendar\n            var calendar = [];\n            for (i = 0; i < 6; i++) {\n                calendar[i] = [];\n            }\n\n            //populate the calendar with date objects\n            var startDay = daysInLastMonth - dayOfWeek + this.locale.firstDay + 1;\n            if (startDay > daysInLastMonth)\n                startDay -= 7;\n\n            if (dayOfWeek == this.locale.firstDay)\n                startDay = daysInLastMonth - 6;\n\n            var curDate = moment([lastYear, lastMonth, startDay, 12, minute]);\n            var col, row;\n            for (i = 0, col = 0, row = 0; i < 42; i++, col++, curDate = moment(curDate).add('hour', 24)) {\n                if (i > 0 && col % 7 === 0) {\n                    col = 0;\n                    row++;\n                }\n                calendar[row][col] = curDate.clone().hour(hour);\n                curDate.hour(12);\n            }\n\n            return calendar;\n        },\n\n        renderDropdowns: function (selected, minDate, maxDate) {\n            var currentMonth = selected.month();\n            var monthHtml = '<select class=\"monthselect\">';\n            var inMinYear = false;\n            var inMaxYear = false;\n\n            for (var m = 0; m < 12; m++) {\n                if ((!inMinYear || m >= minDate.month()) && (!inMaxYear || m <= maxDate.month())) {\n                    monthHtml += \"<option value='\" + m + \"'\" +\n                        (m === currentMonth ? \" selected='selected'\" : \"\") +\n                        \">\" + this.locale.monthNames[m] + \"</option>\";\n                }\n            }\n            monthHtml += \"</select>\";\n\n            var currentYear = selected.year();\n            var maxYear = (maxDate && maxDate.year()) || (currentYear + 5);\n            var minYear = (minDate && minDate.year()) || (currentYear - 50);\n            var yearHtml = '<select class=\"yearselect\">';\n\n            for (var y = minYear; y <= maxYear; y++) {\n                yearHtml += '<option value=\"' + y + '\"' +\n                    (y === currentYear ? ' selected=\"selected\"' : '') +\n                    '>' + y + '</option>';\n            }\n\n            yearHtml += '</select>';\n\n            return monthHtml + yearHtml;\n        },\n\n        renderCalendar: function (calendar, selected, minDate, maxDate) {\n\n            var html = '<div class=\"calendar-date\">';\n            html += '<table class=\"table-condensed\">';\n            html += '<thead>';\n            html += '<tr>';\n\n            // add empty cell for week number\n            if (this.showWeekNumbers)\n                html += '<th></th>';\n\n            if (!minDate || minDate.isBefore(calendar[1][1])) {\n                html += '<th class=\"prev available\"><i class=\"fa fa-arrow-left icon-arrow-left glyphicon glyphicon-arrow-left\"></i></th>';\n            } else {\n                html += '<th></th>';\n            }\n\n            var dateHtml = this.locale.monthNames[calendar[1][1].month()] + calendar[1][1].format(\" YYYY\");\n\n            if (this.showDropdowns) {\n                dateHtml = this.renderDropdowns(calendar[1][1], minDate, maxDate);\n            }\n\n            html += '<th colspan=\"5\" class=\"month\">' + dateHtml + '</th>';\n            if (!maxDate || maxDate.isAfter(calendar[1][1])) {\n                html += '<th class=\"next available\"><i class=\"fa fa-arrow-right icon-arrow-right glyphicon glyphicon-arrow-right\"></i></th>';\n            } else {\n                html += '<th></th>';\n            }\n\n            html += '</tr>';\n            html += '<tr>';\n\n            // add week number label\n            if (this.showWeekNumbers)\n                html += '<th class=\"week\">' + this.locale.weekLabel + '</th>';\n\n            $.each(this.locale.daysOfWeek, function (index, dayOfWeek) {\n                html += '<th>' + dayOfWeek + '</th>';\n            });\n\n            html += '</tr>';\n            html += '</thead>';\n            html += '<tbody>';\n\n            for (var row = 0; row < 6; row++) {\n                html += '<tr>';\n\n                // add week number\n                if (this.showWeekNumbers)\n                    html += '<td class=\"week\">' + calendar[row][0].week() + '</td>';\n\n                for (var col = 0; col < 7; col++) {\n                    var cname = 'available ';\n                    cname += (calendar[row][col].month() == calendar[1][1].month()) ? '' : 'off';\n\n                    if ((minDate && calendar[row][col].isBefore(minDate, 'day')) || (maxDate && calendar[row][col].isAfter(maxDate, 'day'))) {\n                        cname = ' off disabled ';\n                    } else if (calendar[row][col].format('YYYY-MM-DD') == selected.format('YYYY-MM-DD')) {\n                        cname += ' active ';\n                        if (calendar[row][col].format('YYYY-MM-DD') == this.startDate.format('YYYY-MM-DD')) {\n                            cname += ' start-date ';\n                        }\n                        if (calendar[row][col].format('YYYY-MM-DD') == this.endDate.format('YYYY-MM-DD')) {\n                            cname += ' end-date ';\n                        }\n                    } else if (calendar[row][col] >= this.startDate && calendar[row][col] <= this.endDate) {\n                        cname += ' in-range ';\n                        if (calendar[row][col].isSame(this.startDate)) { cname += ' start-date '; }\n                        if (calendar[row][col].isSame(this.endDate)) { cname += ' end-date '; }\n                    }\n\n                    var title = 'r' + row + 'c' + col;\n                    html += '<td class=\"' + cname.replace(/\\s+/g, ' ').replace(/^\\s?(.*?)\\s?$/, '$1') + '\" data-title=\"' + title + '\">' + calendar[row][col].date() + '</td>';\n                }\n                html += '</tr>';\n            }\n\n            html += '</tbody>';\n            html += '</table>';\n            html += '</div>';\n\n            var i;\n            if (this.timePicker) {\n\n                html += '<div class=\"calendar-time\">';\n                html += '<select class=\"hourselect\">';\n                var start = 0;\n                var end = 23;\n                var selected_hour = selected.hour();\n                if (this.timePicker12Hour) {\n                    start = 1;\n                    end = 12;\n                    if (selected_hour >= 12)\n                        selected_hour -= 12;\n                    if (selected_hour === 0)\n                        selected_hour = 12;\n                }\n\n                for (i = start; i <= end; i++) {\n                    if (i == selected_hour) {\n                        html += '<option value=\"' + i + '\" selected=\"selected\">' + i + '</option>';\n                    } else {\n                        html += '<option value=\"' + i + '\">' + i + '</option>';\n                    }\n                }\n\n                html += '</select> : ';\n\n                html += '<select class=\"minuteselect\">';\n\n                for (i = 0; i < 60; i += this.timePickerIncrement) {\n                    var num = i;\n                    if (num < 10)\n                        num = '0' + num;\n                    if (i == selected.minute()) {\n                        html += '<option value=\"' + i + '\" selected=\"selected\">' + num + '</option>';\n                    } else {\n                        html += '<option value=\"' + i + '\">' + num + '</option>';\n                    }\n                }\n\n                html += '</select> ';\n\n                if (this.timePicker12Hour) {\n                    html += '<select class=\"ampmselect\">';\n                    if (selected.hour() >= 12) {\n                        html += '<option value=\"AM\">AM</option><option value=\"PM\" selected=\"selected\">PM</option>';\n                    } else {\n                        html += '<option value=\"AM\" selected=\"selected\">AM</option><option value=\"PM\">PM</option>';\n                    }\n                    html += '</select>';\n                }\n\n                html += '</div>';\n\n            }\n\n            return html;\n\n        },\n\n        remove: function() {\n\n            this.container.remove();\n            this.element.off('.daterangepicker');\n            this.element.removeData('daterangepicker');\n\n        }\n\n    };\n\n    $.fn.daterangepicker = function (options, cb) {\n        this.each(function () {\n            var el = $(this);\n            if (el.data('daterangepicker'))\n                el.data('daterangepicker').remove();\n            el.data('daterangepicker', new DateRangePicker(el, options, cb));\n        });\n        return this;\n    };\n\n}(window.jQuery, window.moment);"
  },
  {
    "path": "flowable-ui-web/idm/libs/bootstrap-tour_0.9.1/bootstrap-tour.js",
    "content": "/* ===========================================================\n # bootstrap-tour - v0.9.1\n # http://bootstraptour.com\n # ==============================================================\n # Copyright 2012-2013 Ulrich Sossou\n #\n # Licensed under the Apache License, Version 2.0 (the \"License\");\n # you may not use this file except in compliance with the License.\n # You may obtain a copy of the License at\n #\n #     http://www.apache.org/licenses/LICENSE-2.0\n #\n # Unless required by applicable law or agreed to in writing, software\n # distributed under the License is distributed on an \"AS IS\" BASIS,\n # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n # See the License for the specific language governing permissions and\n # limitations under the License.\n */\n(function($, window) {\n    var Tour, document;\n    document = window.document;\n    Tour = (function() {\n        function Tour(options) {\n            this._options = $.extend({\n                name: \"tour\",\n                steps: [],\n                container: \"body\",\n                keyboard: true,\n                storage: window.localStorage,\n                debug: false,\n                backdrop: false,\n                redirect: true,\n                orphan: false,\n                duration: false,\n                basePath: \"\",\n                template: \"<div class='popover'> <div class='arrow'></div> <h3 class='popover-title'></h3> <div class='popover-content'></div> <div class='popover-navigation'> <div class='btn-group'> <button class='btn btn-sm btn-default' data-role='prev'>&laquo; Prev</button> <button class='btn btn-sm btn-default' data-role='next'>Next &raquo;</button> <button class='btn btn-sm btn-default' data-role='pause-resume' data-pause-text='Pause' data-resume-text='Resume'>Pause</button> </div> <button class='btn btn-sm btn-default' data-role='end'>End tour</button> </div> </div>\",\n                afterSetState: function(key, value) {},\n                afterGetState: function(key, value) {},\n                afterRemoveState: function(key) {},\n                onStart: function(tour) {},\n                onEnd: function(tour) {},\n                onShow: function(tour) {},\n                onShown: function(tour) {},\n                onHide: function(tour) {},\n                onHidden: function(tour) {},\n                onNext: function(tour) {},\n                onPrev: function(tour) {},\n                onPause: function(tour, duration) {},\n                onResume: function(tour, duration) {}\n            }, options);\n            this._force = false;\n            this._inited = false;\n            this.backdrop = {\n                overlay: null,\n                $element: null,\n                $background: null,\n                backgroundShown: false,\n                overlayElementShown: false\n            };\n            this;\n        }\n\n        Tour.prototype.addSteps = function(steps) {\n            var step, _i, _len;\n            for (_i = 0, _len = steps.length; _i < _len; _i++) {\n                step = steps[_i];\n                this.addStep(step);\n            }\n            return this;\n        };\n\n        Tour.prototype.addStep = function(step) {\n            this._options.steps.push(step);\n            return this;\n        };\n\n        Tour.prototype.getStep = function(i) {\n            if (this._options.steps[i] != null) {\n                return $.extend({\n                    id: \"step-\" + i,\n                    path: \"\",\n                    placement: \"right\",\n                    title: \"\",\n                    content: \"<p></p>\",\n                    next: i === this._options.steps.length - 1 ? -1 : i + 1,\n                    prev: i - 1,\n                    animation: true,\n                    container: this._options.container,\n                    backdrop: this._options.backdrop,\n                    redirect: this._options.redirect,\n                    orphan: this._options.orphan,\n                    duration: this._options.duration,\n                    template: this._options.template,\n                    onShow: this._options.onShow,\n                    onShown: this._options.onShown,\n                    onHide: this._options.onHide,\n                    onHidden: this._options.onHidden,\n                    onNext: this._options.onNext,\n                    onPrev: this._options.onPrev,\n                    onPause: this._options.onPause,\n                    onResume: this._options.onResume\n                }, this._options.steps[i]);\n            }\n        };\n\n        Tour.prototype.init = function(force) {\n            this._force = force;\n            if (this.ended()) {\n                this._debug(\"Tour ended, init prevented.\");\n                return this;\n            }\n            this.setCurrentStep();\n            this._initMouseNavigation();\n            this._initKeyboardNavigation();\n            this._onResize((function(_this) {\n                return function() {\n                    return _this.showStep(_this._current);\n                };\n            })(this));\n            if (this._current !== null) {\n                this.showStep(this._current);\n            }\n            this._inited = true;\n            return this;\n        };\n\n        Tour.prototype.start = function(force) {\n            var promise;\n            if (force == null) {\n                force = false;\n            }\n            if (!this._inited) {\n                this.init(force);\n            }\n            if (this._current === null) {\n                promise = this._makePromise(this._options.onStart != null ? this._options.onStart(this) : void 0);\n                this._callOnPromiseDone(promise, this.showStep, 0);\n            }\n            return this;\n        };\n\n        Tour.prototype.next = function() {\n            var promise;\n            promise = this.hideStep(this._current);\n            return this._callOnPromiseDone(promise, this._showNextStep);\n        };\n\n        Tour.prototype.prev = function() {\n            var promise;\n            promise = this.hideStep(this._current);\n            return this._callOnPromiseDone(promise, this._showPrevStep);\n        };\n\n        Tour.prototype.goTo = function(i) {\n            var promise;\n            promise = this.hideStep(this._current);\n            return this._callOnPromiseDone(promise, this.showStep, i);\n        };\n\n        Tour.prototype.end = function() {\n            var endHelper, promise;\n            endHelper = (function(_this) {\n                return function(e) {\n                    $(document).off(\"click.tour-\" + _this._options.name);\n                    $(document).off(\"keyup.tour-\" + _this._options.name);\n                    $(window).off(\"resize.tour-\" + _this._options.name);\n                    _this._setState(\"end\", \"yes\");\n                    _this._inited = false;\n                    _this._force = false;\n                    _this._clearTimer();\n                    if (_this._options.onEnd != null) {\n                        return _this._options.onEnd(_this);\n                    }\n                };\n            })(this);\n            promise = this.hideStep(this._current);\n            return this._callOnPromiseDone(promise, endHelper);\n        };\n\n        Tour.prototype.ended = function() {\n            return !this._force && !!this._getState(\"end\");\n        };\n\n        Tour.prototype.restart = function() {\n            this._removeState(\"current_step\");\n            this._removeState(\"end\");\n            this.setCurrentStep(0);\n            return this.start();\n        };\n\n        Tour.prototype.pause = function() {\n            var step;\n            step = this.getStep(this._current);\n            if (!(step && step.duration)) {\n                return this;\n            }\n            this._paused = true;\n            this._duration -= new Date().getTime() - this._start;\n            window.clearTimeout(this._timer);\n            this._debug(\"Paused/Stopped step \" + (this._current + 1) + \" timer (\" + this._duration + \" remaining).\");\n            if (step.onPause != null) {\n                return step.onPause(this, this._duration);\n            }\n        };\n\n        Tour.prototype.resume = function() {\n            var step;\n            step = this.getStep(this._current);\n            if (!(step && step.duration)) {\n                return this;\n            }\n            this._paused = false;\n            this._start = new Date().getTime();\n            this._duration = this._duration || step.duration;\n            this._timer = window.setTimeout((function(_this) {\n                return function() {\n                    if (_this._isLast()) {\n                        return _this.next();\n                    } else {\n                        return _this.end();\n                    }\n                };\n            })(this), this._duration);\n            this._debug(\"Started step \" + (this._current + 1) + \" timer with duration \" + this._duration);\n            if ((step.onResume != null) && this._duration !== step.duration) {\n                return step.onResume(this, this._duration);\n            }\n        };\n\n        Tour.prototype.hideStep = function(i) {\n            var hideStepHelper, promise, step;\n            step = this.getStep(i);\n            if (!step) {\n                return;\n            }\n            this._clearTimer();\n            promise = this._makePromise(step.onHide != null ? step.onHide(this, i) : void 0);\n            hideStepHelper = (function(_this) {\n                return function(e) {\n                    var $element;\n                    $element = $(step.element);\n                    if (!($element.data(\"bs.popover\") || $element.data(\"popover\"))) {\n                        $element = $(\"body\");\n                    }\n                    $element.popover(\"destroy\").removeClass(\"tour-\" + _this._options.name + \"-element tour-\" + _this._options.name + \"-\" + i + \"-element\");\n                    if (step.reflex) {\n                        $element.css(\"cursor\", \"\").off(\"click.tour-\" + _this._options.name);\n                    }\n                    if (step.backdrop) {\n                        _this._hideBackdrop();\n                    }\n                    if (step.onHidden != null) {\n                        return step.onHidden(_this);\n                    }\n                };\n            })(this);\n            this._callOnPromiseDone(promise, hideStepHelper);\n            return promise;\n        };\n\n        Tour.prototype.showStep = function(i) {\n            var promise, showStepHelper, skipToPrevious, step;\n            if (this.ended()) {\n                this._debug(\"Tour ended, showStep prevented.\");\n                return this;\n            }\n            step = this.getStep(i);\n            if (!step) {\n                return;\n            }\n            skipToPrevious = i < this._current;\n            promise = this._makePromise(step.onShow != null ? step.onShow(this, i) : void 0);\n            showStepHelper = (function(_this) {\n                return function(e) {\n                    var current_path, path;\n                    _this.setCurrentStep(i);\n                    path = (function() {\n                        switch ({}.toString.call(step.path)) {\n                            case \"[object Function]\":\n                                return step.path();\n                            case \"[object String]\":\n                                return this._options.basePath + step.path;\n                            default:\n                                return step.path;\n                        }\n                    }).call(_this);\n                    current_path = [document.location.pathname, document.location.hash].join(\"\");\n                    if (_this._isRedirect(path, current_path)) {\n                        _this._redirect(step, path);\n                        return;\n                    }\n                    if (_this._isOrphan(step)) {\n                        if (!step.orphan) {\n                            _this._debug(\"Skip the orphan step \" + (_this._current + 1) + \". Orphan option is false and the element doesn't exist or is hidden.\");\n                            if (skipToPrevious) {\n                                _this._showPrevStep();\n                            } else {\n                                _this._showNextStep();\n                            }\n                            return;\n                        }\n                        _this._debug(\"Show the orphan step \" + (_this._current + 1) + \". Orphans option is true.\");\n                    }\n                    if (step.backdrop) {\n                        _this._showBackdrop(!_this._isOrphan(step) ? step.element : void 0);\n                    }\n                    _this._scrollIntoView(step.element, function() {\n                        if ((step.element != null) && step.backdrop) {\n                            _this._showOverlayElement(step.element);\n                        }\n                        _this._showPopover(step, i);\n                        if (step.onShown != null) {\n                            step.onShown(_this);\n                        }\n                        return _this._debug(\"Step \" + (_this._current + 1) + \" of \" + _this._options.steps.length);\n                    });\n                    if (step.duration) {\n                        return _this.resume();\n                    }\n                };\n            })(this);\n            this._callOnPromiseDone(promise, showStepHelper);\n            return promise;\n        };\n\n        Tour.prototype.getCurrentStep = function() {\n            return this._current;\n        };\n\n        Tour.prototype.setCurrentStep = function(value) {\n            if (value != null) {\n                this._current = value;\n                this._setState(\"current_step\", value);\n            } else {\n                this._current = this._getState(\"current_step\");\n                this._current = this._current === null ? null : parseInt(this._current, 10);\n            }\n            return this;\n        };\n\n        Tour.prototype._setState = function(key, value) {\n            var e, keyName;\n            if (this._options.storage) {\n                keyName = \"\" + this._options.name + \"_\" + key;\n                try {\n                    this._options.storage.setItem(keyName, value);\n                } catch (_error) {\n                    e = _error;\n                    if (e.code === DOMException.QUOTA_EXCEEDED_ERR) {\n                        this.debug(\"LocalStorage quota exceeded. State storage failed.\");\n                    }\n                }\n                return this._options.afterSetState(keyName, value);\n            } else {\n                if (this._state == null) {\n                    this._state = {};\n                }\n                return this._state[key] = value;\n            }\n        };\n\n        Tour.prototype._removeState = function(key) {\n            var keyName;\n            if (this._options.storage) {\n                keyName = \"\" + this._options.name + \"_\" + key;\n                this._options.storage.removeItem(keyName);\n                return this._options.afterRemoveState(keyName);\n            } else {\n                if (this._state != null) {\n                    return delete this._state[key];\n                }\n            }\n        };\n\n        Tour.prototype._getState = function(key) {\n            var keyName, value;\n            if (this._options.storage) {\n                keyName = \"\" + this._options.name + \"_\" + key;\n                value = this._options.storage.getItem(keyName);\n            } else {\n                if (this._state != null) {\n                    value = this._state[key];\n                }\n            }\n            if (value === void 0 || value === \"null\") {\n                value = null;\n            }\n            this._options.afterGetState(key, value);\n            return value;\n        };\n\n        Tour.prototype._showNextStep = function() {\n            var promise, showNextStepHelper, step;\n            step = this.getStep(this._current);\n            showNextStepHelper = (function(_this) {\n                return function(e) {\n                    return _this.showStep(step.next);\n                };\n            })(this);\n            promise = this._makePromise(step.onNext != null ? step.onNext(this) : void 0);\n            return this._callOnPromiseDone(promise, showNextStepHelper);\n        };\n\n        Tour.prototype._showPrevStep = function() {\n            var promise, showPrevStepHelper, step;\n            step = this.getStep(this._current);\n            showPrevStepHelper = (function(_this) {\n                return function(e) {\n                    return _this.showStep(step.prev);\n                };\n            })(this);\n            promise = this._makePromise(step.onPrev != null ? step.onPrev(this) : void 0);\n            return this._callOnPromiseDone(promise, showPrevStepHelper);\n        };\n\n        Tour.prototype._debug = function(text) {\n            if (this._options.debug) {\n                return window.console.log(\"Bootstrap Tour '\" + this._options.name + \"' | \" + text);\n            }\n        };\n\n        Tour.prototype._isRedirect = function(path, currentPath) {\n            return (path != null) && path !== \"\" && ((toString.call(path) === \"[object RegExp]\" && !path.test(currentPath)) || (toString.call(path) === \"[object String]\" && path.replace(/\\?.*$/, \"\").replace(/\\/?$/, \"\") !== currentPath.replace(/\\/?$/, \"\")));\n        };\n\n        Tour.prototype._redirect = function(step, path) {\n            if ($.isFunction(step.redirect)) {\n                return step.redirect.call(this, path);\n            } else if (step.redirect === true) {\n                this._debug(\"Redirect to \" + path);\n                return document.location.href = path;\n            }\n        };\n\n        Tour.prototype._isOrphan = function(step) {\n            return (step.element == null) || !$(step.element).length || $(step.element).is(\":hidden\") && ($(step.element)[0].namespaceURI !== \"http://www.w3.org/2000/svg\");\n        };\n\n        Tour.prototype._isLast = function() {\n            return this._current < this._options.steps.length - 1;\n        };\n\n        Tour.prototype._showPopover = function(step, i) {\n            var $element, $navigation, $template, $tip, isOrphan, options;\n            options = $.extend({}, this._options);\n            $template = $.isFunction(step.template) ? $(step.template(i, step)) : $(step.template);\n            $navigation = $template.find(\".popover-navigation\");\n            isOrphan = this._isOrphan(step);\n            if (isOrphan) {\n                step.element = \"body\";\n                step.placement = \"top\";\n                $template = $template.addClass(\"orphan\");\n            }\n            $element = $(step.element);\n            $template.addClass(\"tour-\" + this._options.name + \" tour-\" + this._options.name + \"-\" + i);\n            $element.addClass(\"tour-\" + this._options.name + \"-element tour-\" + this._options.name + \"-\" + i + \"-element\");\n            if (step.options) {\n                $.extend(options, step.options);\n            }\n            if (step.reflex) {\n                $element.css(\"cursor\", \"pointer\").on(\"click.tour-\" + this._options.name, (function(_this) {\n                    return function() {\n                        if (_this._isLast()) {\n                            return _this.next();\n                        } else {\n                            return _this.end();\n                        }\n                    };\n                })(this));\n            }\n            if (step.prev < 0) {\n                $navigation.find(\"[data-role='prev']\").addClass(\"disabled\");\n            }\n            if (step.next < 0) {\n                $navigation.find(\"[data-role='next']\").addClass(\"disabled\");\n            }\n            if (!step.duration) {\n                $navigation.find(\"[data-role='pause-resume']\").remove();\n            }\n            step.template = $template.clone().wrap(\"<div>\").parent().html();\n            $element.popover({\n                placement: step.placement,\n                trigger: \"manual\",\n                title: step.title,\n                content: step.content,\n                html: true,\n                animation: step.animation,\n                container: step.container,\n                template: step.template,\n                selector: step.element\n            }).popover(\"show\");\n            $tip = $element.data(\"bs.popover\") ? $element.data(\"bs.popover\").tip() : $element.data(\"popover\").tip();\n            $tip.attr(\"id\", step.id);\n            this._reposition($tip, step);\n            if (isOrphan) {\n                return this._center($tip);\n            }\n        };\n\n        Tour.prototype._reposition = function($tip, step) {\n            var offsetBottom, offsetHeight, offsetRight, offsetWidth, originalLeft, originalTop, tipOffset;\n            offsetWidth = $tip[0].offsetWidth;\n            offsetHeight = $tip[0].offsetHeight;\n            tipOffset = $tip.offset();\n            originalLeft = tipOffset.left;\n            originalTop = tipOffset.top;\n            offsetBottom = $(document).outerHeight() - tipOffset.top - $tip.outerHeight();\n            if (offsetBottom < 0) {\n                tipOffset.top = tipOffset.top + offsetBottom;\n            }\n            offsetRight = $(\"html\").outerWidth() - tipOffset.left - $tip.outerWidth();\n            if (offsetRight < 0) {\n                tipOffset.left = tipOffset.left + offsetRight;\n            }\n            if (tipOffset.top < 0) {\n                tipOffset.top = 0;\n            }\n            if (tipOffset.left < 0) {\n                tipOffset.left = 0;\n            }\n            $tip.offset(tipOffset);\n            if (step.placement === \"bottom\" || step.placement === \"top\") {\n                if (originalLeft !== tipOffset.left) {\n                    return this._replaceArrow($tip, (tipOffset.left - originalLeft) * 2, offsetWidth, \"left\");\n                }\n            } else {\n                if (originalTop !== tipOffset.top) {\n                    return this._replaceArrow($tip, (tipOffset.top - originalTop) * 2, offsetHeight, \"top\");\n                }\n            }\n        };\n\n        Tour.prototype._center = function($tip) {\n            return $tip.css(\"top\", $(window).outerHeight() / 2 - $tip.outerHeight() / 2);\n        };\n\n        Tour.prototype._replaceArrow = function($tip, delta, dimension, position) {\n            return $tip.find(\".arrow\").css(position, delta ? 50 * (1 - delta / dimension) + \"%\" : \"\");\n        };\n\n        Tour.prototype._scrollIntoView = function(element, callback) {\n            var $element, $window, counter, offsetTop, scrollTop, windowHeight;\n            $element = $(element);\n            if (!$element.length) {\n                return callback();\n            }\n            $window = $(window);\n            offsetTop = $element.offset().top;\n            windowHeight = $window.height();\n            scrollTop = Math.max(0, offsetTop - (windowHeight / 2));\n            this._debug(\"Scroll into view. ScrollTop: \" + scrollTop + \". Element offset: \" + offsetTop + \". Window height: \" + windowHeight + \".\");\n            counter = 0;\n            return $(\"body,html\").stop(true, true).animate({\n                scrollTop: Math.ceil(scrollTop)\n            }, (function(_this) {\n                return function() {\n                    if (++counter === 2) {\n                        callback();\n                        return _this._debug(\"Scroll into view. Animation end element offset: \" + ($element.offset().top) + \". Window height: \" + ($window.height()) + \".\");\n                    }\n                };\n            })(this));\n        };\n\n        Tour.prototype._onResize = function(callback, timeout) {\n            return $(window).on(\"resize.tour-\" + this._options.name, function() {\n                clearTimeout(timeout);\n                return timeout = setTimeout(callback, 100);\n            });\n        };\n\n        Tour.prototype._initMouseNavigation = function() {\n            var _this;\n            _this = this;\n            return $(document).off(\"click.tour-\" + this._options.name, \".popover.tour-\" + this._options.name + \" *[data-role='prev']:not(.disabled)\").off(\"click.tour-\" + this._options.name, \".popover.tour-\" + this._options.name + \" *[data-role='next']:not(.disabled)\").off(\"click.tour-\" + this._options.name, \".popover.tour-\" + this._options.name + \" *[data-role='end']\").off(\"click.tour-\" + this._options.name, \".popover.tour-\" + this._options.name + \" *[data-role='pause-resume']\").on(\"click.tour-\" + this._options.name, \".popover.tour-\" + this._options.name + \" *[data-role='next']:not(.disabled)\", (function(_this) {\n                return function(e) {\n                    e.preventDefault();\n                    return _this.next();\n                };\n            })(this)).on(\"click.tour-\" + this._options.name, \".popover.tour-\" + this._options.name + \" *[data-role='prev']:not(.disabled)\", (function(_this) {\n                return function(e) {\n                    e.preventDefault();\n                    return _this.prev();\n                };\n            })(this)).on(\"click.tour-\" + this._options.name, \".popover.tour-\" + this._options.name + \" *[data-role='end']\", (function(_this) {\n                return function(e) {\n                    e.preventDefault();\n                    return _this.end();\n                };\n            })(this)).on(\"click.tour-\" + this._options.name, \".popover.tour-\" + this._options.name + \" *[data-role='pause-resume']\", function(e) {\n                var $this;\n                e.preventDefault();\n                $this = $(this);\n                $this.text(_this._paused ? $this.data(\"pause-text\") : $this.data(\"resume-text\"));\n                if (_this._paused) {\n                    return _this.resume();\n                } else {\n                    return _this.pause();\n                }\n            });\n        };\n\n        Tour.prototype._initKeyboardNavigation = function() {\n            if (!this._options.keyboard) {\n                return;\n            }\n            return $(document).on(\"keyup.tour-\" + this._options.name, (function(_this) {\n                return function(e) {\n                    if (!e.which) {\n                        return;\n                    }\n                    switch (e.which) {\n                        case 39:\n                            e.preventDefault();\n                            if (_this._isLast()) {\n                                return _this.next();\n                            } else {\n                                return _this.end();\n                            }\n                            break;\n                        case 37:\n                            e.preventDefault();\n                            if (_this._current > 0) {\n                                return _this.prev();\n                            }\n                            break;\n                        case 27:\n                            e.preventDefault();\n                            return _this.end();\n                    }\n                };\n            })(this));\n        };\n\n        Tour.prototype._makePromise = function(result) {\n            if (result && $.isFunction(result.then)) {\n                return result;\n            } else {\n                return null;\n            }\n        };\n\n        Tour.prototype._callOnPromiseDone = function(promise, cb, arg) {\n            if (promise) {\n                return promise.then((function(_this) {\n                    return function(e) {\n                        return cb.call(_this, arg);\n                    };\n                })(this));\n            } else {\n                return cb.call(this, arg);\n            }\n        };\n\n        Tour.prototype._showBackdrop = function(element) {\n            if (this.backdrop.backgroundShown) {\n                return;\n            }\n            this.backdrop = $(\"<div/>\", {\n                \"class\": \"tour-backdrop\"\n            });\n            this.backdrop.backgroundShown = true;\n            return $(\"body\").append(this.backdrop);\n        };\n\n        Tour.prototype._hideBackdrop = function() {\n            this._hideOverlayElement();\n            return this._hideBackground();\n        };\n\n        Tour.prototype._hideBackground = function() {\n            this.backdrop.remove();\n            this.backdrop.overlay = null;\n            return this.backdrop.backgroundShown = false;\n        };\n\n        Tour.prototype._showOverlayElement = function(element) {\n            var $background, $element, offset;\n            $element = $(element);\n            if (!$element || $element.length === 0 || this.backdrop.overlayElementShown) {\n                return;\n            }\n            this.backdrop.overlayElementShown = true;\n            $background = $(\"<div/>\");\n            offset = $element.offset();\n            offset.top = offset.top;\n            offset.left = offset.left;\n            $background.width($element.innerWidth()).height($element.innerHeight()).addClass(\"tour-step-background\").offset(offset);\n            $element.addClass(\"tour-step-backdrop\");\n            $(\"body\").append($background);\n            this.backdrop.$element = $element;\n            return this.backdrop.$background = $background;\n        };\n\n        Tour.prototype._hideOverlayElement = function() {\n            if (!this.backdrop.overlayElementShown) {\n                return;\n            }\n            this.backdrop.$element.removeClass(\"tour-step-backdrop\");\n            this.backdrop.$background.remove();\n            this.backdrop.$element = null;\n            this.backdrop.$background = null;\n            return this.backdrop.overlayElementShown = false;\n        };\n\n        Tour.prototype._clearTimer = function() {\n            window.clearTimeout(this._timer);\n            this._timer = null;\n            return this._duration = null;\n        };\n\n        return Tour;\n\n    })();\n    return window.Tour = Tour;\n})(jQuery, window);"
  },
  {
    "path": "flowable-ui-web/idm/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": "flowable-ui-web/idm/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": "flowable-ui-web/idm/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": "flowable-ui-web/idm/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": "flowable-ui-web/idm/libs/es5-shim-15.3.4.5/.gitignore",
    "content": "node_modules\n.DS_Store\n"
  },
  {
    "path": "flowable-ui-web/idm/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": "flowable-ui-web/idm/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": "flowable-ui-web/idm/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": "flowable-ui-web/idm/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": "flowable-ui-web/idm/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": "flowable-ui-web/idm/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": "flowable-ui-web/idm/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": "flowable-ui-web/idm/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": "flowable-ui-web/idm/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": "flowable-ui-web/idm/libs/es5-shim-15.3.4.5/tests/helpers/h.js",
    "content": "function implement() {\n    throw 'Not implemented';\n}"
  },
  {
    "path": "flowable-ui-web/idm/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": "flowable-ui-web/idm/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": "flowable-ui-web/idm/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": "flowable-ui-web/idm/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": "flowable-ui-web/idm/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": "flowable-ui-web/idm/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": "flowable-ui-web/idm/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": "flowable-ui-web/idm/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": "flowable-ui-web/idm/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": "flowable-ui-web/idm/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": "flowable-ui-web/idm/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": "flowable-ui-web/idm/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": "flowable-ui-web/idm/libs/html2canvas_0.4.1/html2canvas.js",
    "content": "/*\n  html2canvas 0.4.1 <http://html2canvas.hertzen.com>\n  Copyright (c) 2013 Niklas von Hertzen\n\n  Released under MIT License\n*/\n\n(function(window, document, undefined){\n\n\"use strict\";\n\nvar _html2canvas = {},\npreviousElement,\ncomputedCSS,\nhtml2canvas;\n\n_html2canvas.Util = {};\n\n_html2canvas.Util.log = function(a) {\n  if (_html2canvas.logging && window.console && window.console.log) {\n    window.console.log(a);\n  }\n};\n\n_html2canvas.Util.trimText = (function(isNative){\n  return function(input) {\n    return isNative ? isNative.apply(input) : ((input || '') + '').replace( /^\\s+|\\s+$/g , '' );\n  };\n})(String.prototype.trim);\n\n_html2canvas.Util.asFloat = function(v) {\n  return parseFloat(v);\n};\n\n(function() {\n  // TODO: support all possible length values\n  var TEXT_SHADOW_PROPERTY = /((rgba|rgb)\\([^\\)]+\\)(\\s-?\\d+px){0,})/g;\n  var TEXT_SHADOW_VALUES = /(-?\\d+px)|(#.+)|(rgb\\(.+\\))|(rgba\\(.+\\))/g;\n  _html2canvas.Util.parseTextShadows = function (value) {\n    if (!value || value === 'none') {\n      return [];\n    }\n\n    // find multiple shadow declarations\n    var shadows = value.match(TEXT_SHADOW_PROPERTY),\n      results = [];\n    for (var i = 0; shadows && (i < shadows.length); i++) {\n      var s = shadows[i].match(TEXT_SHADOW_VALUES);\n      results.push({\n        color: s[0],\n        offsetX: s[1] ? s[1].replace('px', '') : 0,\n        offsetY: s[2] ? s[2].replace('px', '') : 0,\n        blur: s[3] ? s[3].replace('px', '') : 0\n      });\n    }\n    return results;\n  };\n})();\n\n\n_html2canvas.Util.parseBackgroundImage = function (value) {\n    var whitespace = ' \\r\\n\\t',\n        method, definition, prefix, prefix_i, block, results = [],\n        c, mode = 0, numParen = 0, quote, args;\n\n    var appendResult = function(){\n        if(method) {\n            if(definition.substr( 0, 1 ) === '\"') {\n                definition = definition.substr( 1, definition.length - 2 );\n            }\n            if(definition) {\n                args.push(definition);\n            }\n            if(method.substr( 0, 1 ) === '-' &&\n                    (prefix_i = method.indexOf( '-', 1 ) + 1) > 0) {\n                prefix = method.substr( 0, prefix_i);\n                method = method.substr( prefix_i );\n            }\n            results.push({\n                prefix: prefix,\n                method: method.toLowerCase(),\n                value: block,\n                args: args\n            });\n        }\n        args = []; //for some odd reason, setting .length = 0 didn't work in safari\n        method =\n            prefix =\n            definition =\n            block = '';\n    };\n\n    appendResult();\n    for(var i = 0, ii = value.length; i<ii; i++) {\n        c = value[i];\n        if(mode === 0 && whitespace.indexOf( c ) > -1){\n            continue;\n        }\n        switch(c) {\n            case '\"':\n                if(!quote) {\n                    quote = c;\n                }\n                else if(quote === c) {\n                    quote = null;\n                }\n                break;\n\n            case '(':\n                if(quote) { break; }\n                else if(mode === 0) {\n                    mode = 1;\n                    block += c;\n                    continue;\n                } else {\n                    numParen++;\n                }\n                break;\n\n            case ')':\n                if(quote) { break; }\n                else if(mode === 1) {\n                    if(numParen === 0) {\n                        mode = 0;\n                        block += c;\n                        appendResult();\n                        continue;\n                    } else {\n                        numParen--;\n                    }\n                }\n                break;\n\n            case ',':\n                if(quote) { break; }\n                else if(mode === 0) {\n                    appendResult();\n                    continue;\n                }\n                else if (mode === 1) {\n                    if(numParen === 0 && !method.match(/^url$/i)) {\n                        args.push(definition);\n                        definition = '';\n                        block += c;\n                        continue;\n                    }\n                }\n                break;\n        }\n\n        block += c;\n        if(mode === 0) { method += c; }\n        else { definition += c; }\n    }\n    appendResult();\n\n    return results;\n};\n\n_html2canvas.Util.Bounds = function (element) {\n  var clientRect, bounds = {};\n\n  if (element.getBoundingClientRect){\n    clientRect = element.getBoundingClientRect();\n\n    // TODO add scroll position to bounds, so no scrolling of window necessary\n    bounds.top = clientRect.top;\n    bounds.bottom = clientRect.bottom || (clientRect.top + clientRect.height);\n    bounds.left = clientRect.left;\n\n    bounds.width = element.offsetWidth;\n    bounds.height = element.offsetHeight;\n  }\n\n  return bounds;\n};\n\n// TODO ideally, we'd want everything to go through this function instead of Util.Bounds,\n// but would require further work to calculate the correct positions for elements with offsetParents\n_html2canvas.Util.OffsetBounds = function (element) {\n  var parent = element.offsetParent ? _html2canvas.Util.OffsetBounds(element.offsetParent) : {top: 0, left: 0};\n\n  return {\n    top: element.offsetTop + parent.top,\n    bottom: element.offsetTop + element.offsetHeight + parent.top,\n    left: element.offsetLeft + parent.left,\n    width: element.offsetWidth,\n    height: element.offsetHeight\n  };\n};\n\nfunction toPX(element, attribute, value ) {\n    var rsLeft = element.runtimeStyle && element.runtimeStyle[attribute],\n        left,\n        style = element.style;\n\n    // Check if we are not dealing with pixels, (Opera has issues with this)\n    // Ported from jQuery css.js\n    // From the awesome hack by Dean Edwards\n    // http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291\n\n    // If we're not dealing with a regular pixel number\n    // but a number that has a weird ending, we need to convert it to pixels\n\n    if ( !/^-?[0-9]+\\.?[0-9]*(?:px)?$/i.test( value ) && /^-?\\d/.test(value) ) {\n        // Remember the original values\n        left = style.left;\n\n        // Put in the new values to get a computed value out\n        if (rsLeft) {\n            element.runtimeStyle.left = element.currentStyle.left;\n        }\n        style.left = attribute === \"fontSize\" ? \"1em\" : (value || 0);\n        value = style.pixelLeft + \"px\";\n\n        // Revert the changed values\n        style.left = left;\n        if (rsLeft) {\n            element.runtimeStyle.left = rsLeft;\n        }\n    }\n\n    if (!/^(thin|medium|thick)$/i.test(value)) {\n        return Math.round(parseFloat(value)) + \"px\";\n    }\n\n    return value;\n}\n\nfunction asInt(val) {\n    return parseInt(val, 10);\n}\n\nfunction parseBackgroundSizePosition(value, element, attribute, index) {\n    value = (value || '').split(',');\n    value = value[index || 0] || value[0] || 'auto';\n    value = _html2canvas.Util.trimText(value).split(' ');\n\n    if(attribute === 'backgroundSize' && (!value[0] || value[0].match(/cover|contain|auto/))) {\n        //these values will be handled in the parent function\n    } else {\n        value[0] = (value[0].indexOf( \"%\" ) === -1) ? toPX(element, attribute + \"X\", value[0]) : value[0];\n        if(value[1] === undefined) {\n            if(attribute === 'backgroundSize') {\n                value[1] = 'auto';\n                return value;\n            } else {\n                // IE 9 doesn't return double digit always\n                value[1] = value[0];\n            }\n        }\n        value[1] = (value[1].indexOf(\"%\") === -1) ? toPX(element, attribute + \"Y\", value[1]) : value[1];\n    }\n    return value;\n}\n\n_html2canvas.Util.getCSS = function (element, attribute, index) {\n    if (previousElement !== element) {\n      computedCSS = document.defaultView.getComputedStyle(element, null);\n    }\n\n    var value = computedCSS[attribute];\n\n    if (/^background(Size|Position)$/.test(attribute)) {\n        return parseBackgroundSizePosition(value, element, attribute, index);\n    } else if (/border(Top|Bottom)(Left|Right)Radius/.test(attribute)) {\n      var arr = value.split(\" \");\n      if (arr.length <= 1) {\n          arr[1] = arr[0];\n      }\n      return arr.map(asInt);\n    }\n\n  return value;\n};\n\n_html2canvas.Util.resizeBounds = function( current_width, current_height, target_width, target_height, stretch_mode ){\n  var target_ratio = target_width / target_height,\n    current_ratio = current_width / current_height,\n    output_width, output_height;\n\n  if(!stretch_mode || stretch_mode === 'auto') {\n    output_width = target_width;\n    output_height = target_height;\n  } else if(target_ratio < current_ratio ^ stretch_mode === 'contain') {\n    output_height = target_height;\n    output_width = target_height * current_ratio;\n  } else {\n    output_width = target_width;\n    output_height = target_width / current_ratio;\n  }\n\n  return {\n    width: output_width,\n    height: output_height\n  };\n};\n\nfunction backgroundBoundsFactory( prop, el, bounds, image, imageIndex, backgroundSize ) {\n    var bgposition =  _html2canvas.Util.getCSS( el, prop, imageIndex ) ,\n    topPos,\n    left,\n    percentage,\n    val;\n\n    if (bgposition.length === 1){\n      val = bgposition[0];\n\n      bgposition = [];\n\n      bgposition[0] = val;\n      bgposition[1] = val;\n    }\n\n    if (bgposition[0].toString().indexOf(\"%\") !== -1){\n      percentage = (parseFloat(bgposition[0])/100);\n      left = bounds.width * percentage;\n      if(prop !== 'backgroundSize') {\n        left -= (backgroundSize || image).width*percentage;\n      }\n    } else {\n      if(prop === 'backgroundSize') {\n        if(bgposition[0] === 'auto') {\n          left = image.width;\n        } else {\n          if (/contain|cover/.test(bgposition[0])) {\n            var resized = _html2canvas.Util.resizeBounds(image.width, image.height, bounds.width, bounds.height, bgposition[0]);\n            left = resized.width;\n            topPos = resized.height;\n          } else {\n            left = parseInt(bgposition[0], 10);\n          }\n        }\n      } else {\n        left = parseInt( bgposition[0], 10);\n      }\n    }\n\n\n    if(bgposition[1] === 'auto') {\n      topPos = left / image.width * image.height;\n    } else if (bgposition[1].toString().indexOf(\"%\") !== -1){\n      percentage = (parseFloat(bgposition[1])/100);\n      topPos =  bounds.height * percentage;\n      if(prop !== 'backgroundSize') {\n        topPos -= (backgroundSize || image).height * percentage;\n      }\n\n    } else {\n      topPos = parseInt(bgposition[1],10);\n    }\n\n    return [left, topPos];\n}\n\n_html2canvas.Util.BackgroundPosition = function( el, bounds, image, imageIndex, backgroundSize ) {\n    var result = backgroundBoundsFactory( 'backgroundPosition', el, bounds, image, imageIndex, backgroundSize );\n    return { left: result[0], top: result[1] };\n};\n\n_html2canvas.Util.BackgroundSize = function( el, bounds, image, imageIndex ) {\n    var result = backgroundBoundsFactory( 'backgroundSize', el, bounds, image, imageIndex );\n    return { width: result[0], height: result[1] };\n};\n\n_html2canvas.Util.Extend = function (options, defaults) {\n  for (var key in options) {\n    if (options.hasOwnProperty(key)) {\n      defaults[key] = options[key];\n    }\n  }\n  return defaults;\n};\n\n\n/*\n * Derived from jQuery.contents()\n * Copyright 2010, John Resig\n * Dual licensed under the MIT or GPL Version 2 licenses.\n * http://jquery.org/license\n */\n_html2canvas.Util.Children = function( elem ) {\n  var children;\n  try {\n    children = (elem.nodeName && elem.nodeName.toUpperCase() === \"IFRAME\") ? elem.contentDocument || elem.contentWindow.document : (function(array) {\n      var ret = [];\n      if (array !== null) {\n        (function(first, second ) {\n          var i = first.length,\n          j = 0;\n\n          if (typeof second.length === \"number\") {\n            for (var l = second.length; j < l; j++) {\n              first[i++] = second[j];\n            }\n          } else {\n            while (second[j] !== undefined) {\n              first[i++] = second[j++];\n            }\n          }\n\n          first.length = i;\n\n          return first;\n        })(ret, array);\n      }\n      return ret;\n    })(elem.childNodes);\n\n  } catch (ex) {\n    _html2canvas.Util.log(\"html2canvas.Util.Children failed with exception: \" + ex.message);\n    children = [];\n  }\n  return children;\n};\n\n_html2canvas.Util.isTransparent = function(backgroundColor) {\n  return (backgroundColor === \"transparent\" || backgroundColor === \"rgba(0, 0, 0, 0)\");\n};\n_html2canvas.Util.Font = (function () {\n\n  var fontData = {};\n\n  return function(font, fontSize, doc) {\n    if (fontData[font + \"-\" + fontSize] !== undefined) {\n      return fontData[font + \"-\" + fontSize];\n    }\n\n    var container = doc.createElement('div'),\n    img = doc.createElement('img'),\n    span = doc.createElement('span'),\n    sampleText = 'Hidden Text',\n    baseline,\n    middle,\n    metricsObj;\n\n    container.style.visibility = \"hidden\";\n    container.style.fontFamily = font;\n    container.style.fontSize = fontSize;\n    container.style.margin = 0;\n    container.style.padding = 0;\n\n    doc.body.appendChild(container);\n\n    // http://probablyprogramming.com/2009/03/15/the-tiniest-gif-ever (handtinywhite.gif)\n    img.src = \"data:image/gif;base64,R0lGODlhAQABAIABAP///wAAACwAAAAAAQABAAACAkQBADs=\";\n    img.width = 1;\n    img.height = 1;\n\n    img.style.margin = 0;\n    img.style.padding = 0;\n    img.style.verticalAlign = \"baseline\";\n\n    span.style.fontFamily = font;\n    span.style.fontSize = fontSize;\n    span.style.margin = 0;\n    span.style.padding = 0;\n\n    span.appendChild(doc.createTextNode(sampleText));\n    container.appendChild(span);\n    container.appendChild(img);\n    baseline = (img.offsetTop - span.offsetTop) + 1;\n\n    container.removeChild(span);\n    container.appendChild(doc.createTextNode(sampleText));\n\n    container.style.lineHeight = \"normal\";\n    img.style.verticalAlign = \"super\";\n\n    middle = (img.offsetTop-container.offsetTop) + 1;\n    metricsObj = {\n      baseline: baseline,\n      lineWidth: 1,\n      middle: middle\n    };\n\n    fontData[font + \"-\" + fontSize] = metricsObj;\n\n    doc.body.removeChild(container);\n\n    return metricsObj;\n  };\n})();\n\n(function(){\n  var Util = _html2canvas.Util,\n    Generate = {};\n\n  _html2canvas.Generate = Generate;\n\n  var reGradients = [\n  /^(-webkit-linear-gradient)\\(([a-z\\s]+)([\\w\\d\\.\\s,%\\(\\)]+)\\)$/,\n  /^(-o-linear-gradient)\\(([a-z\\s]+)([\\w\\d\\.\\s,%\\(\\)]+)\\)$/,\n  /^(-webkit-gradient)\\((linear|radial),\\s((?:\\d{1,3}%?)\\s(?:\\d{1,3}%?),\\s(?:\\d{1,3}%?)\\s(?:\\d{1,3}%?))([\\w\\d\\.\\s,%\\(\\)\\-]+)\\)$/,\n  /^(-moz-linear-gradient)\\(((?:\\d{1,3}%?)\\s(?:\\d{1,3}%?))([\\w\\d\\.\\s,%\\(\\)]+)\\)$/,\n  /^(-webkit-radial-gradient)\\(((?:\\d{1,3}%?)\\s(?:\\d{1,3}%?)),\\s(\\w+)\\s([a-z\\-]+)([\\w\\d\\.\\s,%\\(\\)]+)\\)$/,\n  /^(-moz-radial-gradient)\\(((?:\\d{1,3}%?)\\s(?:\\d{1,3}%?)),\\s(\\w+)\\s?([a-z\\-]*)([\\w\\d\\.\\s,%\\(\\)]+)\\)$/,\n  /^(-o-radial-gradient)\\(((?:\\d{1,3}%?)\\s(?:\\d{1,3}%?)),\\s(\\w+)\\s([a-z\\-]+)([\\w\\d\\.\\s,%\\(\\)]+)\\)$/\n  ];\n\n  /*\n * TODO: Add IE10 vendor prefix (-ms) support\n * TODO: Add W3C gradient (linear-gradient) support\n * TODO: Add old Webkit -webkit-gradient(radial, ...) support\n * TODO: Maybe some RegExp optimizations are possible ;o)\n */\n  Generate.parseGradient = function(css, bounds) {\n    var gradient, i, len = reGradients.length, m1, stop, m2, m2Len, step, m3, tl,tr,br,bl;\n\n    for(i = 0; i < len; i+=1){\n      m1 = css.match(reGradients[i]);\n      if(m1) {\n        break;\n      }\n    }\n\n    if(m1) {\n      switch(m1[1]) {\n        case '-webkit-linear-gradient':\n        case '-o-linear-gradient':\n\n          gradient = {\n            type: 'linear',\n            x0: null,\n            y0: null,\n            x1: null,\n            y1: null,\n            colorStops: []\n          };\n\n          // get coordinates\n          m2 = m1[2].match(/\\w+/g);\n          if(m2){\n            m2Len = m2.length;\n            for(i = 0; i < m2Len; i+=1){\n              switch(m2[i]) {\n                case 'top':\n                  gradient.y0 = 0;\n                  gradient.y1 = bounds.height;\n                  break;\n\n                case 'right':\n                  gradient.x0 = bounds.width;\n                  gradient.x1 = 0;\n                  break;\n\n                case 'bottom':\n                  gradient.y0 = bounds.height;\n                  gradient.y1 = 0;\n                  break;\n\n                case 'left':\n                  gradient.x0 = 0;\n                  gradient.x1 = bounds.width;\n                  break;\n              }\n            }\n          }\n          if(gradient.x0 === null && gradient.x1 === null){ // center\n            gradient.x0 = gradient.x1 = bounds.width / 2;\n          }\n          if(gradient.y0 === null && gradient.y1 === null){ // center\n            gradient.y0 = gradient.y1 = bounds.height / 2;\n          }\n\n          // get colors and stops\n          m2 = m1[3].match(/((?:rgb|rgba)\\(\\d{1,3},\\s\\d{1,3},\\s\\d{1,3}(?:,\\s[0-9\\.]+)?\\)(?:\\s\\d{1,3}(?:%|px))?)+/g);\n          if(m2){\n            m2Len = m2.length;\n            step = 1 / Math.max(m2Len - 1, 1);\n            for(i = 0; i < m2Len; i+=1){\n              m3 = m2[i].match(/((?:rgb|rgba)\\(\\d{1,3},\\s\\d{1,3},\\s\\d{1,3}(?:,\\s[0-9\\.]+)?\\))\\s*(\\d{1,3})?(%|px)?/);\n              if(m3[2]){\n                stop = parseFloat(m3[2]);\n                if(m3[3] === '%'){\n                  stop /= 100;\n                } else { // px - stupid opera\n                  stop /= bounds.width;\n                }\n              } else {\n                stop = i * step;\n              }\n              gradient.colorStops.push({\n                color: m3[1],\n                stop: stop\n              });\n            }\n          }\n          break;\n\n        case '-webkit-gradient':\n\n          gradient = {\n            type: m1[2] === 'radial' ? 'circle' : m1[2], // TODO: Add radial gradient support for older mozilla definitions\n            x0: 0,\n            y0: 0,\n            x1: 0,\n            y1: 0,\n            colorStops: []\n          };\n\n          // get coordinates\n          m2 = m1[3].match(/(\\d{1,3})%?\\s(\\d{1,3})%?,\\s(\\d{1,3})%?\\s(\\d{1,3})%?/);\n          if(m2){\n            gradient.x0 = (m2[1] * bounds.width) / 100;\n            gradient.y0 = (m2[2] * bounds.height) / 100;\n            gradient.x1 = (m2[3] * bounds.width) / 100;\n            gradient.y1 = (m2[4] * bounds.height) / 100;\n          }\n\n          // get colors and stops\n          m2 = m1[4].match(/((?:from|to|color-stop)\\((?:[0-9\\.]+,\\s)?(?:rgb|rgba)\\(\\d{1,3},\\s\\d{1,3},\\s\\d{1,3}(?:,\\s[0-9\\.]+)?\\)\\))+/g);\n          if(m2){\n            m2Len = m2.length;\n            for(i = 0; i < m2Len; i+=1){\n              m3 = m2[i].match(/(from|to|color-stop)\\(([0-9\\.]+)?(?:,\\s)?((?:rgb|rgba)\\(\\d{1,3},\\s\\d{1,3},\\s\\d{1,3}(?:,\\s[0-9\\.]+)?\\))\\)/);\n              stop = parseFloat(m3[2]);\n              if(m3[1] === 'from') {\n                stop = 0.0;\n              }\n              if(m3[1] === 'to') {\n                stop = 1.0;\n              }\n              gradient.colorStops.push({\n                color: m3[3],\n                stop: stop\n              });\n            }\n          }\n          break;\n\n        case '-moz-linear-gradient':\n\n          gradient = {\n            type: 'linear',\n            x0: 0,\n            y0: 0,\n            x1: 0,\n            y1: 0,\n            colorStops: []\n          };\n\n          // get coordinates\n          m2 = m1[2].match(/(\\d{1,3})%?\\s(\\d{1,3})%?/);\n\n          // m2[1] == 0%   -> left\n          // m2[1] == 50%  -> center\n          // m2[1] == 100% -> right\n\n          // m2[2] == 0%   -> top\n          // m2[2] == 50%  -> center\n          // m2[2] == 100% -> bottom\n\n          if(m2){\n            gradient.x0 = (m2[1] * bounds.width) / 100;\n            gradient.y0 = (m2[2] * bounds.height) / 100;\n            gradient.x1 = bounds.width - gradient.x0;\n            gradient.y1 = bounds.height - gradient.y0;\n          }\n\n          // get colors and stops\n          m2 = m1[3].match(/((?:rgb|rgba)\\(\\d{1,3},\\s\\d{1,3},\\s\\d{1,3}(?:,\\s[0-9\\.]+)?\\)(?:\\s\\d{1,3}%)?)+/g);\n          if(m2){\n            m2Len = m2.length;\n            step = 1 / Math.max(m2Len - 1, 1);\n            for(i = 0; i < m2Len; i+=1){\n              m3 = m2[i].match(/((?:rgb|rgba)\\(\\d{1,3},\\s\\d{1,3},\\s\\d{1,3}(?:,\\s[0-9\\.]+)?\\))\\s*(\\d{1,3})?(%)?/);\n              if(m3[2]){\n                stop = parseFloat(m3[2]);\n                if(m3[3]){ // percentage\n                  stop /= 100;\n                }\n              } else {\n                stop = i * step;\n              }\n              gradient.colorStops.push({\n                color: m3[1],\n                stop: stop\n              });\n            }\n          }\n          break;\n\n        case '-webkit-radial-gradient':\n        case '-moz-radial-gradient':\n        case '-o-radial-gradient':\n\n          gradient = {\n            type: 'circle',\n            x0: 0,\n            y0: 0,\n            x1: bounds.width,\n            y1: bounds.height,\n            cx: 0,\n            cy: 0,\n            rx: 0,\n            ry: 0,\n            colorStops: []\n          };\n\n          // center\n          m2 = m1[2].match(/(\\d{1,3})%?\\s(\\d{1,3})%?/);\n          if(m2){\n            gradient.cx = (m2[1] * bounds.width) / 100;\n            gradient.cy = (m2[2] * bounds.height) / 100;\n          }\n\n          // size\n          m2 = m1[3].match(/\\w+/);\n          m3 = m1[4].match(/[a-z\\-]*/);\n          if(m2 && m3){\n            switch(m3[0]){\n              case 'farthest-corner':\n              case 'cover': // is equivalent to farthest-corner\n              case '': // mozilla removes \"cover\" from definition :(\n                tl = Math.sqrt(Math.pow(gradient.cx, 2) + Math.pow(gradient.cy, 2));\n                tr = Math.sqrt(Math.pow(gradient.cx, 2) + Math.pow(gradient.y1 - gradient.cy, 2));\n                br = Math.sqrt(Math.pow(gradient.x1 - gradient.cx, 2) + Math.pow(gradient.y1 - gradient.cy, 2));\n                bl = Math.sqrt(Math.pow(gradient.x1 - gradient.cx, 2) + Math.pow(gradient.cy, 2));\n                gradient.rx = gradient.ry = Math.max(tl, tr, br, bl);\n                break;\n              case 'closest-corner':\n                tl = Math.sqrt(Math.pow(gradient.cx, 2) + Math.pow(gradient.cy, 2));\n                tr = Math.sqrt(Math.pow(gradient.cx, 2) + Math.pow(gradient.y1 - gradient.cy, 2));\n                br = Math.sqrt(Math.pow(gradient.x1 - gradient.cx, 2) + Math.pow(gradient.y1 - gradient.cy, 2));\n                bl = Math.sqrt(Math.pow(gradient.x1 - gradient.cx, 2) + Math.pow(gradient.cy, 2));\n                gradient.rx = gradient.ry = Math.min(tl, tr, br, bl);\n                break;\n              case 'farthest-side':\n                if(m2[0] === 'circle'){\n                  gradient.rx = gradient.ry = Math.max(\n                    gradient.cx,\n                    gradient.cy,\n                    gradient.x1 - gradient.cx,\n                    gradient.y1 - gradient.cy\n                    );\n                } else { // ellipse\n\n                  gradient.type = m2[0];\n\n                  gradient.rx = Math.max(\n                    gradient.cx,\n                    gradient.x1 - gradient.cx\n                    );\n                  gradient.ry = Math.max(\n                    gradient.cy,\n                    gradient.y1 - gradient.cy\n                    );\n                }\n                break;\n              case 'closest-side':\n              case 'contain': // is equivalent to closest-side\n                if(m2[0] === 'circle'){\n                  gradient.rx = gradient.ry = Math.min(\n                    gradient.cx,\n                    gradient.cy,\n                    gradient.x1 - gradient.cx,\n                    gradient.y1 - gradient.cy\n                    );\n                } else { // ellipse\n\n                  gradient.type = m2[0];\n\n                  gradient.rx = Math.min(\n                    gradient.cx,\n                    gradient.x1 - gradient.cx\n                    );\n                  gradient.ry = Math.min(\n                    gradient.cy,\n                    gradient.y1 - gradient.cy\n                    );\n                }\n                break;\n\n            // TODO: add support for \"30px 40px\" sizes (webkit only)\n            }\n          }\n\n          // color stops\n          m2 = m1[5].match(/((?:rgb|rgba)\\(\\d{1,3},\\s\\d{1,3},\\s\\d{1,3}(?:,\\s[0-9\\.]+)?\\)(?:\\s\\d{1,3}(?:%|px))?)+/g);\n          if(m2){\n            m2Len = m2.length;\n            step = 1 / Math.max(m2Len - 1, 1);\n            for(i = 0; i < m2Len; i+=1){\n              m3 = m2[i].match(/((?:rgb|rgba)\\(\\d{1,3},\\s\\d{1,3},\\s\\d{1,3}(?:,\\s[0-9\\.]+)?\\))\\s*(\\d{1,3})?(%|px)?/);\n              if(m3[2]){\n                stop = parseFloat(m3[2]);\n                if(m3[3] === '%'){\n                  stop /= 100;\n                } else { // px - stupid opera\n                  stop /= bounds.width;\n                }\n              } else {\n                stop = i * step;\n              }\n              gradient.colorStops.push({\n                color: m3[1],\n                stop: stop\n              });\n            }\n          }\n          break;\n      }\n    }\n\n    return gradient;\n  };\n\n  function addScrollStops(grad) {\n    return function(colorStop) {\n      try {\n        grad.addColorStop(colorStop.stop, colorStop.color);\n      }\n      catch(e) {\n        Util.log(['failed to add color stop: ', e, '; tried to add: ', colorStop]);\n      }\n    };\n  }\n\n  Generate.Gradient = function(src, bounds) {\n    if(bounds.width === 0 || bounds.height === 0) {\n      return;\n    }\n\n    var canvas = document.createElement('canvas'),\n    ctx = canvas.getContext('2d'),\n    gradient, grad;\n\n    canvas.width = bounds.width;\n    canvas.height = bounds.height;\n\n    // TODO: add support for multi defined background gradients\n    gradient = _html2canvas.Generate.parseGradient(src, bounds);\n\n    if(gradient) {\n      switch(gradient.type) {\n        case 'linear':\n          grad = ctx.createLinearGradient(gradient.x0, gradient.y0, gradient.x1, gradient.y1);\n          gradient.colorStops.forEach(addScrollStops(grad));\n          ctx.fillStyle = grad;\n          ctx.fillRect(0, 0, bounds.width, bounds.height);\n          break;\n\n        case 'circle':\n          grad = ctx.createRadialGradient(gradient.cx, gradient.cy, 0, gradient.cx, gradient.cy, gradient.rx);\n          gradient.colorStops.forEach(addScrollStops(grad));\n          ctx.fillStyle = grad;\n          ctx.fillRect(0, 0, bounds.width, bounds.height);\n          break;\n\n        case 'ellipse':\n          var canvasRadial = document.createElement('canvas'),\n            ctxRadial = canvasRadial.getContext('2d'),\n            ri = Math.max(gradient.rx, gradient.ry),\n            di = ri * 2;\n\n          canvasRadial.width = canvasRadial.height = di;\n\n          grad = ctxRadial.createRadialGradient(gradient.rx, gradient.ry, 0, gradient.rx, gradient.ry, ri);\n          gradient.colorStops.forEach(addScrollStops(grad));\n\n          ctxRadial.fillStyle = grad;\n          ctxRadial.fillRect(0, 0, di, di);\n\n          ctx.fillStyle = gradient.colorStops[gradient.colorStops.length - 1].color;\n          ctx.fillRect(0, 0, canvas.width, canvas.height);\n          ctx.drawImage(canvasRadial, gradient.cx - gradient.rx, gradient.cy - gradient.ry, 2 * gradient.rx, 2 * gradient.ry);\n          break;\n      }\n    }\n\n    return canvas;\n  };\n\n  Generate.ListAlpha = function(number) {\n    var tmp = \"\",\n    modulus;\n\n    do {\n      modulus = number % 26;\n      tmp = String.fromCharCode((modulus) + 64) + tmp;\n      number = number / 26;\n    }while((number*26) > 26);\n\n    return tmp;\n  };\n\n  Generate.ListRoman = function(number) {\n    var romanArray = [\"M\", \"CM\", \"D\", \"CD\", \"C\", \"XC\", \"L\", \"XL\", \"X\", \"IX\", \"V\", \"IV\", \"I\"],\n    decimal = [1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1],\n    roman = \"\",\n    v,\n    len = romanArray.length;\n\n    if (number <= 0 || number >= 4000) {\n      return number;\n    }\n\n    for (v=0; v < len; v+=1) {\n      while (number >= decimal[v]) {\n        number -= decimal[v];\n        roman += romanArray[v];\n      }\n    }\n\n    return roman;\n  };\n})();\nfunction h2cRenderContext(width, height) {\n  var storage = [];\n  return {\n    storage: storage,\n    width: width,\n    height: height,\n    clip: function() {\n      storage.push({\n        type: \"function\",\n        name: \"clip\",\n        'arguments': arguments\n      });\n    },\n    translate: function() {\n      storage.push({\n        type: \"function\",\n        name: \"translate\",\n        'arguments': arguments\n      });\n    },\n    fill: function() {\n      storage.push({\n        type: \"function\",\n        name: \"fill\",\n        'arguments': arguments\n      });\n    },\n    save: function() {\n      storage.push({\n        type: \"function\",\n        name: \"save\",\n        'arguments': arguments\n      });\n    },\n    restore: function() {\n      storage.push({\n        type: \"function\",\n        name: \"restore\",\n        'arguments': arguments\n      });\n    },\n    fillRect: function () {\n      storage.push({\n        type: \"function\",\n        name: \"fillRect\",\n        'arguments': arguments\n      });\n    },\n    createPattern: function() {\n      storage.push({\n        type: \"function\",\n        name: \"createPattern\",\n        'arguments': arguments\n      });\n    },\n    drawShape: function() {\n\n      var shape = [];\n\n      storage.push({\n        type: \"function\",\n        name: \"drawShape\",\n        'arguments': shape\n      });\n\n      return {\n        moveTo: function() {\n          shape.push({\n            name: \"moveTo\",\n            'arguments': arguments\n          });\n        },\n        lineTo: function() {\n          shape.push({\n            name: \"lineTo\",\n            'arguments': arguments\n          });\n        },\n        arcTo: function() {\n          shape.push({\n            name: \"arcTo\",\n            'arguments': arguments\n          });\n        },\n        bezierCurveTo: function() {\n          shape.push({\n            name: \"bezierCurveTo\",\n            'arguments': arguments\n          });\n        },\n        quadraticCurveTo: function() {\n          shape.push({\n            name: \"quadraticCurveTo\",\n            'arguments': arguments\n          });\n        }\n      };\n\n    },\n    drawImage: function () {\n      storage.push({\n        type: \"function\",\n        name: \"drawImage\",\n        'arguments': arguments\n      });\n    },\n    fillText: function () {\n      storage.push({\n        type: \"function\",\n        name: \"fillText\",\n        'arguments': arguments\n      });\n    },\n    setVariable: function (variable, value) {\n      storage.push({\n        type: \"variable\",\n        name: variable,\n        'arguments': value\n      });\n      return value;\n    }\n  };\n}\n_html2canvas.Parse = function (images, options) {\n  window.scroll(0,0);\n\n  var element = (( options.elements === undefined ) ? document.body : options.elements[0]), // select body by default\n  numDraws = 0,\n  doc = element.ownerDocument,\n  Util = _html2canvas.Util,\n  support = Util.Support(options, doc),\n  ignoreElementsRegExp = new RegExp(\"(\" + options.ignoreElements + \")\"),\n  body = doc.body,\n  getCSS = Util.getCSS,\n  pseudoHide = \"___html2canvas___pseudoelement\",\n  hidePseudoElements = doc.createElement('style');\n\n  hidePseudoElements.innerHTML = '.' + pseudoHide + '-before:before { content: \"\" !important; display: none !important; }' +\n  '.' + pseudoHide + '-after:after { content: \"\" !important; display: none !important; }';\n\n  body.appendChild(hidePseudoElements);\n\n  images = images || {};\n\n  function documentWidth () {\n    return Math.max(\n      Math.max(doc.body.scrollWidth, doc.documentElement.scrollWidth),\n      Math.max(doc.body.offsetWidth, doc.documentElement.offsetWidth),\n      Math.max(doc.body.clientWidth, doc.documentElement.clientWidth)\n      );\n  }\n\n  function documentHeight () {\n    return Math.max(\n      Math.max(doc.body.scrollHeight, doc.documentElement.scrollHeight),\n      Math.max(doc.body.offsetHeight, doc.documentElement.offsetHeight),\n      Math.max(doc.body.clientHeight, doc.documentElement.clientHeight)\n      );\n  }\n\n  function getCSSInt(element, attribute) {\n    var val = parseInt(getCSS(element, attribute), 10);\n    return (isNaN(val)) ? 0 : val; // borders in old IE are throwing 'medium' for demo.html\n  }\n\n  function renderRect (ctx, x, y, w, h, bgcolor) {\n    if (bgcolor !== \"transparent\"){\n      ctx.setVariable(\"fillStyle\", bgcolor);\n      ctx.fillRect(x, y, w, h);\n      numDraws+=1;\n    }\n  }\n\n  function capitalize(m, p1, p2) {\n    if (m.length > 0) {\n      return p1 + p2.toUpperCase();\n    }\n  }\n\n  function textTransform (text, transform) {\n    switch(transform){\n      case \"lowercase\":\n        return text.toLowerCase();\n      case \"capitalize\":\n        return text.replace( /(^|\\s|:|-|\\(|\\))([a-z])/g, capitalize);\n      case \"uppercase\":\n        return text.toUpperCase();\n      default:\n        return text;\n    }\n  }\n\n  function noLetterSpacing(letter_spacing) {\n    return (/^(normal|none|0px)$/.test(letter_spacing));\n  }\n\n  function drawText(currentText, x, y, ctx){\n    if (currentText !== null && Util.trimText(currentText).length > 0) {\n      ctx.fillText(currentText, x, y);\n      numDraws+=1;\n    }\n  }\n\n  function setTextVariables(ctx, el, text_decoration, color) {\n    var align = false,\n    bold = getCSS(el, \"fontWeight\"),\n    family = getCSS(el, \"fontFamily\"),\n    size = getCSS(el, \"fontSize\"),\n    shadows = Util.parseTextShadows(getCSS(el, \"textShadow\"));\n\n    switch(parseInt(bold, 10)){\n      case 401:\n        bold = \"bold\";\n        break;\n      case 400:\n        bold = \"normal\";\n        break;\n    }\n\n    ctx.setVariable(\"fillStyle\", color);\n    ctx.setVariable(\"font\", [getCSS(el, \"fontStyle\"), getCSS(el, \"fontVariant\"), bold, size, family].join(\" \"));\n    ctx.setVariable(\"textAlign\", (align) ? \"right\" : \"left\");\n\n    if (shadows.length) {\n      // TODO: support multiple text shadows\n      // apply the first text shadow\n      ctx.setVariable(\"shadowColor\", shadows[0].color);\n      ctx.setVariable(\"shadowOffsetX\", shadows[0].offsetX);\n      ctx.setVariable(\"shadowOffsetY\", shadows[0].offsetY);\n      ctx.setVariable(\"shadowBlur\", shadows[0].blur);\n    }\n\n    if (text_decoration !== \"none\"){\n      return Util.Font(family, size, doc);\n    }\n  }\n\n  function renderTextDecoration(ctx, text_decoration, bounds, metrics, color) {\n    switch(text_decoration) {\n      case \"underline\":\n        // Draws a line at the baseline of the font\n        // TODO As some browsers display the line as more than 1px if the font-size is big, need to take that into account both in position and size\n        renderRect(ctx, bounds.left, Math.round(bounds.top + metrics.baseline + metrics.lineWidth), bounds.width, 1, color);\n        break;\n      case \"overline\":\n        renderRect(ctx, bounds.left, Math.round(bounds.top), bounds.width, 1, color);\n        break;\n      case \"line-through\":\n        // TODO try and find exact position for line-through\n        renderRect(ctx, bounds.left, Math.ceil(bounds.top + metrics.middle + metrics.lineWidth), bounds.width, 1, color);\n        break;\n    }\n  }\n\n  function getTextBounds(state, text, textDecoration, isLast, transform) {\n    var bounds;\n    if (support.rangeBounds && !transform) {\n      if (textDecoration !== \"none\" || Util.trimText(text).length !== 0) {\n        bounds = textRangeBounds(text, state.node, state.textOffset);\n      }\n      state.textOffset += text.length;\n    } else if (state.node && typeof state.node.nodeValue === \"string\" ){\n      var newTextNode = (isLast) ? state.node.splitText(text.length) : null;\n      bounds = textWrapperBounds(state.node, transform);\n      state.node = newTextNode;\n    }\n    return bounds;\n  }\n\n  function textRangeBounds(text, textNode, textOffset) {\n    var range = doc.createRange();\n    range.setStart(textNode, textOffset);\n    range.setEnd(textNode, textOffset + text.length);\n    return range.getBoundingClientRect();\n  }\n\n  function textWrapperBounds(oldTextNode, transform) {\n    var parent = oldTextNode.parentNode,\n    wrapElement = doc.createElement('wrapper'),\n    backupText = oldTextNode.cloneNode(true);\n\n    wrapElement.appendChild(oldTextNode.cloneNode(true));\n    parent.replaceChild(wrapElement, oldTextNode);\n\n    var bounds = transform ? Util.OffsetBounds(wrapElement) : Util.Bounds(wrapElement);\n    parent.replaceChild(backupText, wrapElement);\n    return bounds;\n  }\n\n  function renderText(el, textNode, stack) {\n    var ctx = stack.ctx,\n    color = getCSS(el, \"color\"),\n    textDecoration = getCSS(el, \"textDecoration\"),\n    textAlign = getCSS(el, \"textAlign\"),\n    metrics,\n    textList,\n    state = {\n      node: textNode,\n      textOffset: 0\n    };\n\n    if (Util.trimText(textNode.nodeValue).length > 0) {\n      textNode.nodeValue = textTransform(textNode.nodeValue, getCSS(el, \"textTransform\"));\n      textAlign = textAlign.replace([\"-webkit-auto\"],[\"auto\"]);\n\n      textList = (!options.letterRendering && /^(left|right|justify|auto)$/.test(textAlign) && noLetterSpacing(getCSS(el, \"letterSpacing\"))) ?\n      textNode.nodeValue.split(/(\\b| )/)\n      : textNode.nodeValue.split(\"\");\n\n      metrics = setTextVariables(ctx, el, textDecoration, color);\n\n      if (options.chinese) {\n        textList.forEach(function(word, index) {\n          if (/.*[\\u4E00-\\u9FA5].*$/.test(word)) {\n            word = word.split(\"\");\n            word.unshift(index, 1);\n            textList.splice.apply(textList, word);\n          }\n        });\n      }\n\n      textList.forEach(function(text, index) {\n        var bounds = getTextBounds(state, text, textDecoration, (index < textList.length - 1), stack.transform.matrix);\n        if (bounds) {\n          drawText(text, bounds.left, bounds.bottom, ctx);\n          renderTextDecoration(ctx, textDecoration, bounds, metrics, color);\n        }\n      });\n    }\n  }\n\n  function listPosition (element, val) {\n    var boundElement = doc.createElement( \"boundelement\" ),\n    originalType,\n    bounds;\n\n    boundElement.style.display = \"inline\";\n\n    originalType = element.style.listStyleType;\n    element.style.listStyleType = \"none\";\n\n    boundElement.appendChild(doc.createTextNode(val));\n\n    element.insertBefore(boundElement, element.firstChild);\n\n    bounds = Util.Bounds(boundElement);\n    element.removeChild(boundElement);\n    element.style.listStyleType = originalType;\n    return bounds;\n  }\n\n  function elementIndex(el) {\n    var i = -1,\n    count = 1,\n    childs = el.parentNode.childNodes;\n\n    if (el.parentNode) {\n      while(childs[++i] !== el) {\n        if (childs[i].nodeType === 1) {\n          count++;\n        }\n      }\n      return count;\n    } else {\n      return -1;\n    }\n  }\n\n  function listItemText(element, type) {\n    var currentIndex = elementIndex(element), text;\n    switch(type){\n      case \"decimal\":\n        text = currentIndex;\n        break;\n      case \"decimal-leading-zero\":\n        text = (currentIndex.toString().length === 1) ? currentIndex = \"0\" + currentIndex.toString() : currentIndex.toString();\n        break;\n      case \"upper-roman\":\n        text = _html2canvas.Generate.ListRoman( currentIndex );\n        break;\n      case \"lower-roman\":\n        text = _html2canvas.Generate.ListRoman( currentIndex ).toLowerCase();\n        break;\n      case \"lower-alpha\":\n        text = _html2canvas.Generate.ListAlpha( currentIndex ).toLowerCase();\n        break;\n      case \"upper-alpha\":\n        text = _html2canvas.Generate.ListAlpha( currentIndex );\n        break;\n    }\n\n    return text + \". \";\n  }\n\n  function renderListItem(element, stack, elBounds) {\n    var x,\n    text,\n    ctx = stack.ctx,\n    type = getCSS(element, \"listStyleType\"),\n    listBounds;\n\n    if (/^(decimal|decimal-leading-zero|upper-alpha|upper-latin|upper-roman|lower-alpha|lower-greek|lower-latin|lower-roman)$/i.test(type)) {\n      text = listItemText(element, type);\n      listBounds = listPosition(element, text);\n      setTextVariables(ctx, element, \"none\", getCSS(element, \"color\"));\n\n      if (getCSS(element, \"listStylePosition\") === \"inside\") {\n        ctx.setVariable(\"textAlign\", \"left\");\n        x = elBounds.left;\n      } else {\n        return;\n      }\n\n      drawText(text, x, listBounds.bottom, ctx);\n    }\n  }\n\n  function loadImage (src){\n    var img = images[src];\n    return (img && img.succeeded === true) ? img.img : false;\n  }\n\n  function clipBounds(src, dst){\n    var x = Math.max(src.left, dst.left),\n    y = Math.max(src.top, dst.top),\n    x2 = Math.min((src.left + src.width), (dst.left + dst.width)),\n    y2 = Math.min((src.top + src.height), (dst.top + dst.height));\n\n    return {\n      left:x,\n      top:y,\n      width:x2-x,\n      height:y2-y\n    };\n  }\n\n  function setZ(element, stack, parentStack){\n    var newContext,\n    isPositioned = stack.cssPosition !== 'static',\n    zIndex = isPositioned ? getCSS(element, 'zIndex') : 'auto',\n    opacity = getCSS(element, 'opacity'),\n    isFloated = getCSS(element, 'cssFloat') !== 'none';\n\n    // https://developer.mozilla.org/en-US/docs/Web/Guide/CSS/Understanding_z_index/The_stacking_context\n    // When a new stacking context should be created:\n    // the root element (HTML),\n    // positioned (absolutely or relatively) with a z-index value other than \"auto\",\n    // elements with an opacity value less than 1. (See the specification for opacity),\n    // on mobile WebKit and Chrome 22+, position: fixed always creates a new stacking context, even when z-index is \"auto\" (See this post)\n\n    stack.zIndex = newContext = h2czContext(zIndex);\n    newContext.isPositioned = isPositioned;\n    newContext.isFloated = isFloated;\n    newContext.opacity = opacity;\n    newContext.ownStacking = (zIndex !== 'auto' || opacity < 1);\n\n    if (parentStack) {\n      parentStack.zIndex.children.push(stack);\n    }\n  }\n\n  function renderImage(ctx, element, image, bounds, borders) {\n\n    var paddingLeft = getCSSInt(element, 'paddingLeft'),\n    paddingTop = getCSSInt(element, 'paddingTop'),\n    paddingRight = getCSSInt(element, 'paddingRight'),\n    paddingBottom = getCSSInt(element, 'paddingBottom');\n\n    drawImage(\n      ctx,\n      image,\n      0, //sx\n      0, //sy\n      image.width, //sw\n      image.height, //sh\n      bounds.left + paddingLeft + borders[3].width, //dx\n      bounds.top + paddingTop + borders[0].width, // dy\n      bounds.width - (borders[1].width + borders[3].width + paddingLeft + paddingRight), //dw\n      bounds.height - (borders[0].width + borders[2].width + paddingTop + paddingBottom) //dh\n      );\n  }\n\n  function getBorderData(element) {\n    return [\"Top\", \"Right\", \"Bottom\", \"Left\"].map(function(side) {\n      return {\n        width: getCSSInt(element, 'border' + side + 'Width'),\n        color: getCSS(element, 'border' + side + 'Color')\n      };\n    });\n  }\n\n  function getBorderRadiusData(element) {\n    return [\"TopLeft\", \"TopRight\", \"BottomRight\", \"BottomLeft\"].map(function(side) {\n      return getCSS(element, 'border' + side + 'Radius');\n    });\n  }\n\n  var getCurvePoints = (function(kappa) {\n\n    return function(x, y, r1, r2) {\n      var ox = (r1) * kappa, // control point offset horizontal\n      oy = (r2) * kappa, // control point offset vertical\n      xm = x + r1, // x-middle\n      ym = y + r2; // y-middle\n      return {\n        topLeft: bezierCurve({\n          x:x,\n          y:ym\n        }, {\n          x:x,\n          y:ym - oy\n        }, {\n          x:xm - ox,\n          y:y\n        }, {\n          x:xm,\n          y:y\n        }),\n        topRight: bezierCurve({\n          x:x,\n          y:y\n        }, {\n          x:x + ox,\n          y:y\n        }, {\n          x:xm,\n          y:ym - oy\n        }, {\n          x:xm,\n          y:ym\n        }),\n        bottomRight: bezierCurve({\n          x:xm,\n          y:y\n        }, {\n          x:xm,\n          y:y + oy\n        }, {\n          x:x + ox,\n          y:ym\n        }, {\n          x:x,\n          y:ym\n        }),\n        bottomLeft: bezierCurve({\n          x:xm,\n          y:ym\n        }, {\n          x:xm - ox,\n          y:ym\n        }, {\n          x:x,\n          y:y + oy\n        }, {\n          x:x,\n          y:y\n        })\n      };\n    };\n  })(4 * ((Math.sqrt(2) - 1) / 3));\n\n  function bezierCurve(start, startControl, endControl, end) {\n\n    var lerp = function (a, b, t) {\n      return {\n        x:a.x + (b.x - a.x) * t,\n        y:a.y + (b.y - a.y) * t\n      };\n    };\n\n    return {\n      start: start,\n      startControl: startControl,\n      endControl: endControl,\n      end: end,\n      subdivide: function(t) {\n        var ab = lerp(start, startControl, t),\n        bc = lerp(startControl, endControl, t),\n        cd = lerp(endControl, end, t),\n        abbc = lerp(ab, bc, t),\n        bccd = lerp(bc, cd, t),\n        dest = lerp(abbc, bccd, t);\n        return [bezierCurve(start, ab, abbc, dest), bezierCurve(dest, bccd, cd, end)];\n      },\n      curveTo: function(borderArgs) {\n        borderArgs.push([\"bezierCurve\", startControl.x, startControl.y, endControl.x, endControl.y, end.x, end.y]);\n      },\n      curveToReversed: function(borderArgs) {\n        borderArgs.push([\"bezierCurve\", endControl.x, endControl.y, startControl.x, startControl.y, start.x, start.y]);\n      }\n    };\n  }\n\n  function parseCorner(borderArgs, radius1, radius2, corner1, corner2, x, y) {\n    if (radius1[0] > 0 || radius1[1] > 0) {\n      borderArgs.push([\"line\", corner1[0].start.x, corner1[0].start.y]);\n      corner1[0].curveTo(borderArgs);\n      corner1[1].curveTo(borderArgs);\n    } else {\n      borderArgs.push([\"line\", x, y]);\n    }\n\n    if (radius2[0] > 0 || radius2[1] > 0) {\n      borderArgs.push([\"line\", corner2[0].start.x, corner2[0].start.y]);\n    }\n  }\n\n  function drawSide(borderData, radius1, radius2, outer1, inner1, outer2, inner2) {\n    var borderArgs = [];\n\n    if (radius1[0] > 0 || radius1[1] > 0) {\n      borderArgs.push([\"line\", outer1[1].start.x, outer1[1].start.y]);\n      outer1[1].curveTo(borderArgs);\n    } else {\n      borderArgs.push([ \"line\", borderData.c1[0], borderData.c1[1]]);\n    }\n\n    if (radius2[0] > 0 || radius2[1] > 0) {\n      borderArgs.push([\"line\", outer2[0].start.x, outer2[0].start.y]);\n      outer2[0].curveTo(borderArgs);\n      borderArgs.push([\"line\", inner2[0].end.x, inner2[0].end.y]);\n      inner2[0].curveToReversed(borderArgs);\n    } else {\n      borderArgs.push([ \"line\", borderData.c2[0], borderData.c2[1]]);\n      borderArgs.push([ \"line\", borderData.c3[0], borderData.c3[1]]);\n    }\n\n    if (radius1[0] > 0 || radius1[1] > 0) {\n      borderArgs.push([\"line\", inner1[1].end.x, inner1[1].end.y]);\n      inner1[1].curveToReversed(borderArgs);\n    } else {\n      borderArgs.push([ \"line\", borderData.c4[0], borderData.c4[1]]);\n    }\n\n    return borderArgs;\n  }\n\n  function calculateCurvePoints(bounds, borderRadius, borders) {\n\n    var x = bounds.left,\n    y = bounds.top,\n    width = bounds.width,\n    height = bounds.height,\n\n    tlh = borderRadius[0][0],\n    tlv = borderRadius[0][1],\n    trh = borderRadius[1][0],\n    trv = borderRadius[1][1],\n    brh = borderRadius[2][0],\n    brv = borderRadius[2][1],\n    blh = borderRadius[3][0],\n    blv = borderRadius[3][1],\n\n    topWidth = width - trh,\n    rightHeight = height - brv,\n    bottomWidth = width - brh,\n    leftHeight = height - blv;\n\n    return {\n      topLeftOuter: getCurvePoints(\n        x,\n        y,\n        tlh,\n        tlv\n        ).topLeft.subdivide(0.5),\n\n      topLeftInner: getCurvePoints(\n        x + borders[3].width,\n        y + borders[0].width,\n        Math.max(0, tlh - borders[3].width),\n        Math.max(0, tlv - borders[0].width)\n        ).topLeft.subdivide(0.5),\n\n      topRightOuter: getCurvePoints(\n        x + topWidth,\n        y,\n        trh,\n        trv\n        ).topRight.subdivide(0.5),\n\n      topRightInner: getCurvePoints(\n        x + Math.min(topWidth, width + borders[3].width),\n        y + borders[0].width,\n        (topWidth > width + borders[3].width) ? 0 :trh - borders[3].width,\n        trv - borders[0].width\n        ).topRight.subdivide(0.5),\n\n      bottomRightOuter: getCurvePoints(\n        x + bottomWidth,\n        y + rightHeight,\n        brh,\n        brv\n        ).bottomRight.subdivide(0.5),\n\n      bottomRightInner: getCurvePoints(\n        x + Math.min(bottomWidth, width + borders[3].width),\n        y + Math.min(rightHeight, height + borders[0].width),\n        Math.max(0, brh - borders[1].width),\n        Math.max(0, brv - borders[2].width)\n        ).bottomRight.subdivide(0.5),\n\n      bottomLeftOuter: getCurvePoints(\n        x,\n        y + leftHeight,\n        blh,\n        blv\n        ).bottomLeft.subdivide(0.5),\n\n      bottomLeftInner: getCurvePoints(\n        x + borders[3].width,\n        y + leftHeight,\n        Math.max(0, blh - borders[3].width),\n        Math.max(0, blv - borders[2].width)\n        ).bottomLeft.subdivide(0.5)\n    };\n  }\n\n  function getBorderClip(element, borderPoints, borders, radius, bounds) {\n    var backgroundClip = getCSS(element, 'backgroundClip'),\n    borderArgs = [];\n\n    switch(backgroundClip) {\n      case \"content-box\":\n      case \"padding-box\":\n        parseCorner(borderArgs, radius[0], radius[1], borderPoints.topLeftInner, borderPoints.topRightInner, bounds.left + borders[3].width, bounds.top + borders[0].width);\n        parseCorner(borderArgs, radius[1], radius[2], borderPoints.topRightInner, borderPoints.bottomRightInner, bounds.left + bounds.width - borders[1].width, bounds.top + borders[0].width);\n        parseCorner(borderArgs, radius[2], radius[3], borderPoints.bottomRightInner, borderPoints.bottomLeftInner, bounds.left + bounds.width - borders[1].width, bounds.top + bounds.height - borders[2].width);\n        parseCorner(borderArgs, radius[3], radius[0], borderPoints.bottomLeftInner, borderPoints.topLeftInner, bounds.left + borders[3].width, bounds.top + bounds.height - borders[2].width);\n        break;\n\n      default:\n        parseCorner(borderArgs, radius[0], radius[1], borderPoints.topLeftOuter, borderPoints.topRightOuter, bounds.left, bounds.top);\n        parseCorner(borderArgs, radius[1], radius[2], borderPoints.topRightOuter, borderPoints.bottomRightOuter, bounds.left + bounds.width, bounds.top);\n        parseCorner(borderArgs, radius[2], radius[3], borderPoints.bottomRightOuter, borderPoints.bottomLeftOuter, bounds.left + bounds.width, bounds.top + bounds.height);\n        parseCorner(borderArgs, radius[3], radius[0], borderPoints.bottomLeftOuter, borderPoints.topLeftOuter, bounds.left, bounds.top + bounds.height);\n        break;\n    }\n\n    return borderArgs;\n  }\n\n  function parseBorders(element, bounds, borders){\n    var x = bounds.left,\n    y = bounds.top,\n    width = bounds.width,\n    height = bounds.height,\n    borderSide,\n    bx,\n    by,\n    bw,\n    bh,\n    borderArgs,\n    // http://www.w3.org/TR/css3-background/#the-border-radius\n    borderRadius = getBorderRadiusData(element),\n    borderPoints = calculateCurvePoints(bounds, borderRadius, borders),\n    borderData = {\n      clip: getBorderClip(element, borderPoints, borders, borderRadius, bounds),\n      borders: []\n    };\n\n    for (borderSide = 0; borderSide < 4; borderSide++) {\n\n      if (borders[borderSide].width > 0) {\n        bx = x;\n        by = y;\n        bw = width;\n        bh = height - (borders[2].width);\n\n        switch(borderSide) {\n          case 0:\n            // top border\n            bh = borders[0].width;\n\n            borderArgs = drawSide({\n              c1: [bx, by],\n              c2: [bx + bw, by],\n              c3: [bx + bw - borders[1].width, by + bh],\n              c4: [bx + borders[3].width, by + bh]\n            }, borderRadius[0], borderRadius[1],\n            borderPoints.topLeftOuter, borderPoints.topLeftInner, borderPoints.topRightOuter, borderPoints.topRightInner);\n            break;\n          case 1:\n            // right border\n            bx = x + width - (borders[1].width);\n            bw = borders[1].width;\n\n            borderArgs = drawSide({\n              c1: [bx + bw, by],\n              c2: [bx + bw, by + bh + borders[2].width],\n              c3: [bx, by + bh],\n              c4: [bx, by + borders[0].width]\n            }, borderRadius[1], borderRadius[2],\n            borderPoints.topRightOuter, borderPoints.topRightInner, borderPoints.bottomRightOuter, borderPoints.bottomRightInner);\n            break;\n          case 2:\n            // bottom border\n            by = (by + height) - (borders[2].width);\n            bh = borders[2].width;\n\n            borderArgs = drawSide({\n              c1: [bx + bw, by + bh],\n              c2: [bx, by + bh],\n              c3: [bx + borders[3].width, by],\n              c4: [bx + bw - borders[3].width, by]\n            }, borderRadius[2], borderRadius[3],\n            borderPoints.bottomRightOuter, borderPoints.bottomRightInner, borderPoints.bottomLeftOuter, borderPoints.bottomLeftInner);\n            break;\n          case 3:\n            // left border\n            bw = borders[3].width;\n\n            borderArgs = drawSide({\n              c1: [bx, by + bh + borders[2].width],\n              c2: [bx, by],\n              c3: [bx + bw, by + borders[0].width],\n              c4: [bx + bw, by + bh]\n            }, borderRadius[3], borderRadius[0],\n            borderPoints.bottomLeftOuter, borderPoints.bottomLeftInner, borderPoints.topLeftOuter, borderPoints.topLeftInner);\n            break;\n        }\n\n        borderData.borders.push({\n          args: borderArgs,\n          color: borders[borderSide].color\n        });\n\n      }\n    }\n\n    return borderData;\n  }\n\n  function createShape(ctx, args) {\n    var shape = ctx.drawShape();\n    args.forEach(function(border, index) {\n      shape[(index === 0) ? \"moveTo\" : border[0] + \"To\" ].apply(null, border.slice(1));\n    });\n    return shape;\n  }\n\n  function renderBorders(ctx, borderArgs, color) {\n    if (color !== \"transparent\") {\n      ctx.setVariable( \"fillStyle\", color);\n      createShape(ctx, borderArgs);\n      ctx.fill();\n      numDraws+=1;\n    }\n  }\n\n  function renderFormValue (el, bounds, stack){\n\n    var valueWrap = doc.createElement('valuewrap'),\n    cssPropertyArray = ['lineHeight','textAlign','fontFamily','color','fontSize','paddingLeft','paddingTop','width','height','border','borderLeftWidth','borderTopWidth'],\n    textValue,\n    textNode;\n\n    cssPropertyArray.forEach(function(property) {\n      try {\n        valueWrap.style[property] = getCSS(el, property);\n      } catch(e) {\n        // Older IE has issues with \"border\"\n        Util.log(\"html2canvas: Parse: Exception caught in renderFormValue: \" + e.message);\n      }\n    });\n\n    valueWrap.style.borderColor = \"black\";\n    valueWrap.style.borderStyle = \"solid\";\n    valueWrap.style.display = \"block\";\n    valueWrap.style.position = \"absolute\";\n\n    if (/^(submit|reset|button|text|password)$/.test(el.type) || el.nodeName === \"SELECT\"){\n      valueWrap.style.lineHeight = getCSS(el, \"height\");\n    }\n\n    valueWrap.style.top = bounds.top + \"px\";\n    valueWrap.style.left = bounds.left + \"px\";\n\n    textValue = (el.nodeName === \"SELECT\") ? (el.options[el.selectedIndex] || 0).text : el.value;\n    if(!textValue) {\n      textValue = el.placeholder;\n    }\n\n    textNode = doc.createTextNode(textValue);\n\n    valueWrap.appendChild(textNode);\n    body.appendChild(valueWrap);\n\n    renderText(el, textNode, stack);\n    body.removeChild(valueWrap);\n  }\n\n  function drawImage (ctx) {\n    ctx.drawImage.apply(ctx, Array.prototype.slice.call(arguments, 1));\n    numDraws+=1;\n  }\n\n  function getPseudoElement(el, which) {\n    var elStyle = window.getComputedStyle(el, which);\n    if(!elStyle || !elStyle.content || elStyle.content === \"none\" || elStyle.content === \"-moz-alt-content\" || elStyle.display === \"none\") {\n      return;\n    }\n    var content = elStyle.content + '',\n    first = content.substr( 0, 1 );\n    //strips quotes\n    if(first === content.substr( content.length - 1 ) && first.match(/'|\"/)) {\n      content = content.substr( 1, content.length - 2 );\n    }\n\n    var isImage = content.substr( 0, 3 ) === 'url',\n    elps = document.createElement( isImage ? 'img' : 'span' );\n\n    elps.className = pseudoHide + \"-before \" + pseudoHide + \"-after\";\n\n    Object.keys(elStyle).filter(indexedProperty).forEach(function(prop) {\n      // Prevent assigning of read only CSS Rules, ex. length, parentRule\n      try {\n        elps.style[prop] = elStyle[prop];\n      } catch (e) {\n        Util.log(['Tried to assign readonly property ', prop, 'Error:', e]);\n      }\n    });\n\n    if(isImage) {\n      elps.src = Util.parseBackgroundImage(content)[0].args[0];\n    } else {\n      elps.innerHTML = content;\n    }\n    return elps;\n  }\n\n  function indexedProperty(property) {\n    return (isNaN(window.parseInt(property, 10)));\n  }\n\n  function injectPseudoElements(el, stack) {\n    var before = getPseudoElement(el, ':before'),\n    after = getPseudoElement(el, ':after');\n    if(!before && !after) {\n      return;\n    }\n\n    if(before) {\n      el.className += \" \" + pseudoHide + \"-before\";\n      el.parentNode.insertBefore(before, el);\n      parseElement(before, stack, true);\n      el.parentNode.removeChild(before);\n      el.className = el.className.replace(pseudoHide + \"-before\", \"\").trim();\n    }\n\n    if (after) {\n      el.className += \" \" + pseudoHide + \"-after\";\n      el.appendChild(after);\n      parseElement(after, stack, true);\n      el.removeChild(after);\n      el.className = el.className.replace(pseudoHide + \"-after\", \"\").trim();\n    }\n\n  }\n\n  function renderBackgroundRepeat(ctx, image, backgroundPosition, bounds) {\n    var offsetX = Math.round(bounds.left + backgroundPosition.left),\n    offsetY = Math.round(bounds.top + backgroundPosition.top);\n\n    ctx.createPattern(image);\n    ctx.translate(offsetX, offsetY);\n    ctx.fill();\n    ctx.translate(-offsetX, -offsetY);\n  }\n\n  function backgroundRepeatShape(ctx, image, backgroundPosition, bounds, left, top, width, height) {\n    var args = [];\n    args.push([\"line\", Math.round(left), Math.round(top)]);\n    args.push([\"line\", Math.round(left + width), Math.round(top)]);\n    args.push([\"line\", Math.round(left + width), Math.round(height + top)]);\n    args.push([\"line\", Math.round(left), Math.round(height + top)]);\n    createShape(ctx, args);\n    ctx.save();\n    ctx.clip();\n    renderBackgroundRepeat(ctx, image, backgroundPosition, bounds);\n    ctx.restore();\n  }\n\n  function renderBackgroundColor(ctx, backgroundBounds, bgcolor) {\n    renderRect(\n      ctx,\n      backgroundBounds.left,\n      backgroundBounds.top,\n      backgroundBounds.width,\n      backgroundBounds.height,\n      bgcolor\n      );\n  }\n\n  function renderBackgroundRepeating(el, bounds, ctx, image, imageIndex) {\n    var backgroundSize = Util.BackgroundSize(el, bounds, image, imageIndex),\n    backgroundPosition = Util.BackgroundPosition(el, bounds, image, imageIndex, backgroundSize),\n    backgroundRepeat = getCSS(el, \"backgroundRepeat\").split(\",\").map(Util.trimText);\n\n    image = resizeImage(image, backgroundSize);\n\n    backgroundRepeat = backgroundRepeat[imageIndex] || backgroundRepeat[0];\n\n    switch (backgroundRepeat) {\n      case \"repeat-x\":\n        backgroundRepeatShape(ctx, image, backgroundPosition, bounds,\n          bounds.left, bounds.top + backgroundPosition.top, 99999, image.height);\n        break;\n\n      case \"repeat-y\":\n        backgroundRepeatShape(ctx, image, backgroundPosition, bounds,\n          bounds.left + backgroundPosition.left, bounds.top, image.width, 99999);\n        break;\n\n      case \"no-repeat\":\n        backgroundRepeatShape(ctx, image, backgroundPosition, bounds,\n          bounds.left + backgroundPosition.left, bounds.top + backgroundPosition.top, image.width, image.height);\n        break;\n\n      default:\n        renderBackgroundRepeat(ctx, image, backgroundPosition, {\n          top: bounds.top,\n          left: bounds.left,\n          width: image.width,\n          height: image.height\n        });\n        break;\n    }\n  }\n\n  function renderBackgroundImage(element, bounds, ctx) {\n    var backgroundImage = getCSS(element, \"backgroundImage\"),\n    backgroundImages = Util.parseBackgroundImage(backgroundImage),\n    image,\n    imageIndex = backgroundImages.length;\n\n    while(imageIndex--) {\n      backgroundImage = backgroundImages[imageIndex];\n\n      if (!backgroundImage.args || backgroundImage.args.length === 0) {\n        continue;\n      }\n\n      var key = backgroundImage.method === 'url' ?\n      backgroundImage.args[0] :\n      backgroundImage.value;\n\n      image = loadImage(key);\n\n      // TODO add support for background-origin\n      if (image) {\n        renderBackgroundRepeating(element, bounds, ctx, image, imageIndex);\n      } else {\n        Util.log(\"html2canvas: Error loading background:\", backgroundImage);\n      }\n    }\n  }\n\n  function resizeImage(image, bounds) {\n    if(image.width === bounds.width && image.height === bounds.height) {\n      return image;\n    }\n\n    var ctx, canvas = doc.createElement('canvas');\n    canvas.width = bounds.width;\n    canvas.height = bounds.height;\n    ctx = canvas.getContext(\"2d\");\n    drawImage(ctx, image, 0, 0, image.width, image.height, 0, 0, bounds.width, bounds.height );\n    return canvas;\n  }\n\n  function setOpacity(ctx, element, parentStack) {\n    return ctx.setVariable(\"globalAlpha\", getCSS(element, \"opacity\") * ((parentStack) ? parentStack.opacity : 1));\n  }\n\n  function removePx(str) {\n    return str.replace(\"px\", \"\");\n  }\n\n  var transformRegExp = /(matrix)\\((.+)\\)/;\n\n  function getTransform(element, parentStack) {\n    var transform = getCSS(element, \"transform\") || getCSS(element, \"-webkit-transform\") || getCSS(element, \"-moz-transform\") || getCSS(element, \"-ms-transform\") || getCSS(element, \"-o-transform\");\n    var transformOrigin = getCSS(element, \"transform-origin\") || getCSS(element, \"-webkit-transform-origin\") || getCSS(element, \"-moz-transform-origin\") || getCSS(element, \"-ms-transform-origin\") || getCSS(element, \"-o-transform-origin\") || \"0px 0px\";\n\n    transformOrigin = transformOrigin.split(\" \").map(removePx).map(Util.asFloat);\n\n    var matrix;\n    if (transform && transform !== \"none\") {\n      var match = transform.match(transformRegExp);\n      if (match) {\n        switch(match[1]) {\n          case \"matrix\":\n            matrix = match[2].split(\",\").map(Util.trimText).map(Util.asFloat);\n            break;\n        }\n      }\n    }\n\n    return {\n      origin: transformOrigin,\n      matrix: matrix\n    };\n  }\n\n  function createStack(element, parentStack, bounds, transform) {\n    var ctx = h2cRenderContext((!parentStack) ? documentWidth() : bounds.width , (!parentStack) ? documentHeight() : bounds.height),\n    stack = {\n      ctx: ctx,\n      opacity: setOpacity(ctx, element, parentStack),\n      cssPosition: getCSS(element, \"position\"),\n      borders: getBorderData(element),\n      transform: transform,\n      clip: (parentStack && parentStack.clip) ? Util.Extend( {}, parentStack.clip ) : null\n    };\n\n    setZ(element, stack, parentStack);\n\n    // TODO correct overflow for absolute content residing under a static position\n    if (options.useOverflow === true && /(hidden|scroll|auto)/.test(getCSS(element, \"overflow\")) === true && /(BODY)/i.test(element.nodeName) === false){\n      stack.clip = (stack.clip) ? clipBounds(stack.clip, bounds) : bounds;\n    }\n\n    return stack;\n  }\n\n  function getBackgroundBounds(borders, bounds, clip) {\n    var backgroundBounds = {\n      left: bounds.left + borders[3].width,\n      top: bounds.top + borders[0].width,\n      width: bounds.width - (borders[1].width + borders[3].width),\n      height: bounds.height - (borders[0].width + borders[2].width)\n    };\n\n    if (clip) {\n      backgroundBounds = clipBounds(backgroundBounds, clip);\n    }\n\n    return backgroundBounds;\n  }\n\n  function getBounds(element, transform) {\n    var bounds = (transform.matrix) ? Util.OffsetBounds(element) : Util.Bounds(element);\n    transform.origin[0] += bounds.left;\n    transform.origin[1] += bounds.top;\n    return bounds;\n  }\n\n  function renderElement(element, parentStack, pseudoElement, ignoreBackground) {\n    var transform = getTransform(element, parentStack),\n    bounds = getBounds(element, transform),\n    image,\n    stack = createStack(element, parentStack, bounds, transform),\n    borders = stack.borders,\n    ctx = stack.ctx,\n    backgroundBounds = getBackgroundBounds(borders, bounds, stack.clip),\n    borderData = parseBorders(element, bounds, borders),\n    backgroundColor = (ignoreElementsRegExp.test(element.nodeName)) ? \"#efefef\" : getCSS(element, \"backgroundColor\");\n\n\n    createShape(ctx, borderData.clip);\n\n    ctx.save();\n    ctx.clip();\n\n    if (backgroundBounds.height > 0 && backgroundBounds.width > 0 && !ignoreBackground) {\n      renderBackgroundColor(ctx, bounds, backgroundColor);\n      renderBackgroundImage(element, backgroundBounds, ctx);\n    } else if (ignoreBackground) {\n      stack.backgroundColor =  backgroundColor;\n    }\n\n    ctx.restore();\n\n    borderData.borders.forEach(function(border) {\n      renderBorders(ctx, border.args, border.color);\n    });\n\n    if (!pseudoElement) {\n      injectPseudoElements(element, stack);\n    }\n\n    switch(element.nodeName){\n      case \"IMG\":\n        if ((image = loadImage(element.getAttribute('src')))) {\n          renderImage(ctx, element, image, bounds, borders);\n        } else {\n          Util.log(\"html2canvas: Error loading <img>:\" + element.getAttribute('src'));\n        }\n        break;\n      case \"INPUT\":\n        // TODO add all relevant type's, i.e. HTML5 new stuff\n        // todo add support for placeholder attribute for browsers which support it\n        if (/^(text|url|email|submit|button|reset)$/.test(element.type) && (element.value || element.placeholder || \"\").length > 0){\n          renderFormValue(element, bounds, stack);\n        }\n        break;\n      case \"TEXTAREA\":\n        if ((element.value || element.placeholder || \"\").length > 0){\n          renderFormValue(element, bounds, stack);\n        }\n        break;\n      case \"SELECT\":\n        if ((element.options||element.placeholder || \"\").length > 0){\n          renderFormValue(element, bounds, stack);\n        }\n        break;\n      case \"LI\":\n        renderListItem(element, stack, backgroundBounds);\n        break;\n      case \"CANVAS\":\n        renderImage(ctx, element, element, bounds, borders);\n        break;\n    }\n\n    return stack;\n  }\n\n  function isElementVisible(element) {\n    return (getCSS(element, 'display') !== \"none\" && getCSS(element, 'visibility') !== \"hidden\" && !element.hasAttribute(\"data-html2canvas-ignore\"));\n  }\n\n  function parseElement (element, stack, pseudoElement) {\n    if (isElementVisible(element)) {\n      stack = renderElement(element, stack, pseudoElement, false) || stack;\n      if (!ignoreElementsRegExp.test(element.nodeName)) {\n        parseChildren(element, stack, pseudoElement);\n      }\n    }\n  }\n\n  function parseChildren(element, stack, pseudoElement) {\n    Util.Children(element).forEach(function(node) {\n      if (node.nodeType === node.ELEMENT_NODE) {\n        parseElement(node, stack, pseudoElement);\n      } else if (node.nodeType === node.TEXT_NODE) {\n        renderText(element, node, stack);\n      }\n    });\n  }\n\n  function init() {\n    var background = getCSS(document.documentElement, \"backgroundColor\"),\n      transparentBackground = (Util.isTransparent(background) && element === document.body),\n      stack = renderElement(element, null, false, transparentBackground);\n    parseChildren(element, stack);\n\n    if (transparentBackground) {\n      background = stack.backgroundColor;\n    }\n\n    body.removeChild(hidePseudoElements);\n    return {\n      backgroundColor: background,\n      stack: stack\n    };\n  }\n\n  return init();\n};\n\nfunction h2czContext(zindex) {\n  return {\n    zindex: zindex,\n    children: []\n  };\n}\n\n_html2canvas.Preload = function( options ) {\n\n  var images = {\n    numLoaded: 0,   // also failed are counted here\n    numFailed: 0,\n    numTotal: 0,\n    cleanupDone: false\n  },\n  pageOrigin,\n  Util = _html2canvas.Util,\n  methods,\n  i,\n  count = 0,\n  element = options.elements[0] || document.body,\n  doc = element.ownerDocument,\n  domImages = element.getElementsByTagName('img'), // Fetch images of the present element only\n  imgLen = domImages.length,\n  link = doc.createElement(\"a\"),\n  supportCORS = (function( img ){\n    return (img.crossOrigin !== undefined);\n  })(new Image()),\n  timeoutTimer;\n\n  link.href = window.location.href;\n  pageOrigin  = link.protocol + link.host;\n\n  function isSameOrigin(url){\n    link.href = url;\n    link.href = link.href; // YES, BELIEVE IT OR NOT, that is required for IE9 - http://jsfiddle.net/niklasvh/2e48b/\n    var origin = link.protocol + link.host;\n    return (origin === pageOrigin);\n  }\n\n  function start(){\n    Util.log(\"html2canvas: start: images: \" + images.numLoaded + \" / \" + images.numTotal + \" (failed: \" + images.numFailed + \")\");\n    if (!images.firstRun && images.numLoaded >= images.numTotal){\n      Util.log(\"Finished loading images: # \" + images.numTotal + \" (failed: \" + images.numFailed + \")\");\n\n      if (typeof options.complete === \"function\"){\n        options.complete(images);\n      }\n\n    }\n  }\n\n  // TODO modify proxy to serve images with CORS enabled, where available\n  function proxyGetImage(url, img, imageObj){\n    var callback_name,\n    scriptUrl = options.proxy,\n    script;\n\n    link.href = url;\n    url = link.href; // work around for pages with base href=\"\" set - WARNING: this may change the url\n\n    callback_name = 'html2canvas_' + (count++);\n    imageObj.callbackname = callback_name;\n\n    if (scriptUrl.indexOf(\"?\") > -1) {\n      scriptUrl += \"&\";\n    } else {\n      scriptUrl += \"?\";\n    }\n    scriptUrl += 'url=' + encodeURIComponent(url) + '&callback=' + callback_name;\n    script = doc.createElement(\"script\");\n\n    window[callback_name] = function(a){\n      if (a.substring(0,6) === \"error:\"){\n        imageObj.succeeded = false;\n        images.numLoaded++;\n        images.numFailed++;\n        start();\n      } else {\n        setImageLoadHandlers(img, imageObj);\n        img.src = a;\n      }\n      window[callback_name] = undefined; // to work with IE<9  // NOTE: that the undefined callback property-name still exists on the window object (for IE<9)\n      try {\n        delete window[callback_name];  // for all browser that support this\n      } catch(ex) {}\n      script.parentNode.removeChild(script);\n      script = null;\n      delete imageObj.script;\n      delete imageObj.callbackname;\n    };\n\n    script.setAttribute(\"type\", \"text/javascript\");\n    script.setAttribute(\"src\", scriptUrl);\n    imageObj.script = script;\n    window.document.body.appendChild(script);\n\n  }\n\n  function loadPseudoElement(element, type) {\n    var style = window.getComputedStyle(element, type),\n    content = style.content;\n    if (content.substr(0, 3) === 'url') {\n      methods.loadImage(_html2canvas.Util.parseBackgroundImage(content)[0].args[0]);\n    }\n    loadBackgroundImages(style.backgroundImage, element);\n  }\n\n  function loadPseudoElementImages(element) {\n    loadPseudoElement(element, \":before\");\n    loadPseudoElement(element, \":after\");\n  }\n\n  function loadGradientImage(backgroundImage, bounds) {\n    var img = _html2canvas.Generate.Gradient(backgroundImage, bounds);\n\n    if (img !== undefined){\n      images[backgroundImage] = {\n        img: img,\n        succeeded: true\n      };\n      images.numTotal++;\n      images.numLoaded++;\n      start();\n    }\n  }\n\n  function invalidBackgrounds(background_image) {\n    return (background_image && background_image.method && background_image.args && background_image.args.length > 0 );\n  }\n\n  function loadBackgroundImages(background_image, el) {\n    var bounds;\n\n    _html2canvas.Util.parseBackgroundImage(background_image).filter(invalidBackgrounds).forEach(function(background_image) {\n      if (background_image.method === 'url') {\n        methods.loadImage(background_image.args[0]);\n      } else if(background_image.method.match(/\\-?gradient$/)) {\n        if(bounds === undefined) {\n          bounds = _html2canvas.Util.Bounds(el);\n        }\n        loadGradientImage(background_image.value, bounds);\n      }\n    });\n  }\n\n  function getImages (el) {\n    var elNodeType = false;\n\n    // Firefox fails with permission denied on pages with iframes\n    try {\n      Util.Children(el).forEach(getImages);\n    }\n    catch( e ) {}\n\n    try {\n      elNodeType = el.nodeType;\n    } catch (ex) {\n      elNodeType = false;\n      Util.log(\"html2canvas: failed to access some element's nodeType - Exception: \" + ex.message);\n    }\n\n    if (elNodeType === 1 || elNodeType === undefined) {\n      loadPseudoElementImages(el);\n      try {\n        loadBackgroundImages(Util.getCSS(el, 'backgroundImage'), el);\n      } catch(e) {\n        Util.log(\"html2canvas: failed to get background-image - Exception: \" + e.message);\n      }\n      loadBackgroundImages(el);\n    }\n  }\n\n  function setImageLoadHandlers(img, imageObj) {\n    img.onload = function() {\n      if ( imageObj.timer !== undefined ) {\n        // CORS succeeded\n        window.clearTimeout( imageObj.timer );\n      }\n\n      images.numLoaded++;\n      imageObj.succeeded = true;\n      img.onerror = img.onload = null;\n      start();\n    };\n    img.onerror = function() {\n      if (img.crossOrigin === \"anonymous\") {\n        // CORS failed\n        window.clearTimeout( imageObj.timer );\n\n        // let's try with proxy instead\n        if ( options.proxy ) {\n          var src = img.src;\n          img = new Image();\n          imageObj.img = img;\n          img.src = src;\n\n          proxyGetImage( img.src, img, imageObj );\n          return;\n        }\n      }\n\n      images.numLoaded++;\n      images.numFailed++;\n      imageObj.succeeded = false;\n      img.onerror = img.onload = null;\n      start();\n    };\n  }\n\n  methods = {\n    loadImage: function( src ) {\n      var img, imageObj;\n      if ( src && images[src] === undefined ) {\n        img = new Image();\n        if ( src.match(/data:image\\/.*;base64,/i) ) {\n          img.src = src.replace(/url\\(['\"]{0,}|['\"]{0,}\\)$/ig, '');\n          imageObj = images[src] = {\n            img: img\n          };\n          images.numTotal++;\n          setImageLoadHandlers(img, imageObj);\n        } else if ( isSameOrigin( src ) || options.allowTaint ===  true ) {\n          imageObj = images[src] = {\n            img: img\n          };\n          images.numTotal++;\n          setImageLoadHandlers(img, imageObj);\n          img.src = src;\n        } else if ( supportCORS && !options.allowTaint && options.useCORS ) {\n          // attempt to load with CORS\n\n          img.crossOrigin = \"anonymous\";\n          imageObj = images[src] = {\n            img: img\n          };\n          images.numTotal++;\n          setImageLoadHandlers(img, imageObj);\n          img.src = src;\n        } else if ( options.proxy ) {\n          imageObj = images[src] = {\n            img: img\n          };\n          images.numTotal++;\n          proxyGetImage( src, img, imageObj );\n        }\n      }\n\n    },\n    cleanupDOM: function(cause) {\n      var img, src;\n      if (!images.cleanupDone) {\n        if (cause && typeof cause === \"string\") {\n          Util.log(\"html2canvas: Cleanup because: \" + cause);\n        } else {\n          Util.log(\"html2canvas: Cleanup after timeout: \" + options.timeout + \" ms.\");\n        }\n\n        for (src in images) {\n          if (images.hasOwnProperty(src)) {\n            img = images[src];\n            if (typeof img === \"object\" && img.callbackname && img.succeeded === undefined) {\n              // cancel proxy image request\n              window[img.callbackname] = undefined; // to work with IE<9  // NOTE: that the undefined callback property-name still exists on the window object (for IE<9)\n              try {\n                delete window[img.callbackname];  // for all browser that support this\n              } catch(ex) {}\n              if (img.script && img.script.parentNode) {\n                img.script.setAttribute(\"src\", \"about:blank\");  // try to cancel running request\n                img.script.parentNode.removeChild(img.script);\n              }\n              images.numLoaded++;\n              images.numFailed++;\n              Util.log(\"html2canvas: Cleaned up failed img: '\" + src + \"' Steps: \" + images.numLoaded + \" / \" + images.numTotal);\n            }\n          }\n        }\n\n        // cancel any pending requests\n        if(window.stop !== undefined) {\n          window.stop();\n        } else if(document.execCommand !== undefined) {\n          document.execCommand(\"Stop\", false);\n        }\n        if (document.close !== undefined) {\n          document.close();\n        }\n        images.cleanupDone = true;\n        if (!(cause && typeof cause === \"string\")) {\n          start();\n        }\n      }\n    },\n\n    renderingDone: function() {\n      if (timeoutTimer) {\n        window.clearTimeout(timeoutTimer);\n      }\n    }\n  };\n\n  if (options.timeout > 0) {\n    timeoutTimer = window.setTimeout(methods.cleanupDOM, options.timeout);\n  }\n\n  Util.log('html2canvas: Preload starts: finding background-images');\n  images.firstRun = true;\n\n  getImages(element);\n\n  Util.log('html2canvas: Preload: Finding images');\n  // load <img> images\n  for (i = 0; i < imgLen; i+=1){\n    methods.loadImage( domImages[i].getAttribute( \"src\" ) );\n  }\n\n  images.firstRun = false;\n  Util.log('html2canvas: Preload: Done.');\n  if (images.numTotal === images.numLoaded) {\n    start();\n  }\n\n  return methods;\n};\n\n_html2canvas.Renderer = function(parseQueue, options){\n\n  // http://www.w3.org/TR/CSS21/zindex.html\n  function createRenderQueue(parseQueue) {\n    var queue = [],\n    rootContext;\n\n    rootContext = (function buildStackingContext(rootNode) {\n      var rootContext = {};\n      function insert(context, node, specialParent) {\n        var zi = (node.zIndex.zindex === 'auto') ? 0 : Number(node.zIndex.zindex),\n        contextForChildren = context, // the stacking context for children\n        isPositioned = node.zIndex.isPositioned,\n        isFloated = node.zIndex.isFloated,\n        stub = {node: node},\n        childrenDest = specialParent; // where children without z-index should be pushed into\n\n        if (node.zIndex.ownStacking) {\n          // '!' comes before numbers in sorted array\n          contextForChildren = stub.context = { '!': [{node:node, children: []}]};\n          childrenDest = undefined;\n        } else if (isPositioned || isFloated) {\n          childrenDest = stub.children = [];\n        }\n\n        if (zi === 0 && specialParent) {\n          specialParent.push(stub);\n        } else {\n          if (!context[zi]) { context[zi] = []; }\n          context[zi].push(stub);\n        }\n\n        node.zIndex.children.forEach(function(childNode) {\n          insert(contextForChildren, childNode, childrenDest);\n        });\n      }\n      insert(rootContext, rootNode);\n      return rootContext;\n    })(parseQueue);\n\n    function sortZ(context) {\n      Object.keys(context).sort().forEach(function(zi) {\n        var nonPositioned = [],\n        floated = [],\n        positioned = [],\n        list = [];\n\n        // positioned after static\n        context[zi].forEach(function(v) {\n          if (v.node.zIndex.isPositioned || v.node.zIndex.opacity < 1) {\n            // http://www.w3.org/TR/css3-color/#transparency\n            // non-positioned element with opactiy < 1 should be stacked as if it were a positioned element with ‘z-index: 0’ and ‘opacity: 1’.\n            positioned.push(v);\n          } else if (v.node.zIndex.isFloated) {\n            floated.push(v);\n          } else {\n            nonPositioned.push(v);\n          }\n        });\n\n        (function walk(arr) {\n          arr.forEach(function(v) {\n            list.push(v);\n            if (v.children) { walk(v.children); }\n          });\n        })(nonPositioned.concat(floated, positioned));\n\n        list.forEach(function(v) {\n          if (v.context) {\n            sortZ(v.context);\n          } else {\n            queue.push(v.node);\n          }\n        });\n      });\n    }\n\n    sortZ(rootContext);\n\n    return queue;\n  }\n\n  function getRenderer(rendererName) {\n    var renderer;\n\n    if (typeof options.renderer === \"string\" && _html2canvas.Renderer[rendererName] !== undefined) {\n      renderer = _html2canvas.Renderer[rendererName](options);\n    } else if (typeof rendererName === \"function\") {\n      renderer = rendererName(options);\n    } else {\n      throw new Error(\"Unknown renderer\");\n    }\n\n    if ( typeof renderer !== \"function\" ) {\n      throw new Error(\"Invalid renderer defined\");\n    }\n    return renderer;\n  }\n\n  return getRenderer(options.renderer)(parseQueue, options, document, createRenderQueue(parseQueue.stack), _html2canvas);\n};\n\n_html2canvas.Util.Support = function (options, doc) {\n\n  function supportSVGRendering() {\n    var img = new Image(),\n    canvas = doc.createElement(\"canvas\"),\n    ctx = (canvas.getContext === undefined) ? false : canvas.getContext(\"2d\");\n    if (ctx === false) {\n      return false;\n    }\n    canvas.width = canvas.height = 10;\n    img.src = [\n    \"data:image/svg+xml,\",\n    \"<svg xmlns='http://www.w3.org/2000/svg' width='10' height='10'>\",\n    \"<foreignObject width='10' height='10'>\",\n    \"<div xmlns='http://www.w3.org/1999/xhtml' style='width:10;height:10;'>\",\n    \"sup\",\n    \"</div>\",\n    \"</foreignObject>\",\n    \"</svg>\"\n    ].join(\"\");\n    try {\n      ctx.drawImage(img, 0, 0);\n      canvas.toDataURL();\n    } catch(e) {\n      return false;\n    }\n    _html2canvas.Util.log('html2canvas: Parse: SVG powered rendering available');\n    return true;\n  }\n\n  // Test whether we can use ranges to measure bounding boxes\n  // Opera doesn't provide valid bounds.height/bottom even though it supports the method.\n\n  function supportRangeBounds() {\n    var r, testElement, rangeBounds, rangeHeight, support = false;\n\n    if (doc.createRange) {\n      r = doc.createRange();\n      if (r.getBoundingClientRect) {\n        testElement = doc.createElement('boundtest');\n        testElement.style.height = \"123px\";\n        testElement.style.display = \"block\";\n        doc.body.appendChild(testElement);\n\n        r.selectNode(testElement);\n        rangeBounds = r.getBoundingClientRect();\n        rangeHeight = rangeBounds.height;\n\n        if (rangeHeight === 123) {\n          support = true;\n        }\n        doc.body.removeChild(testElement);\n      }\n    }\n\n    return support;\n  }\n\n  return {\n    rangeBounds: supportRangeBounds(),\n    svgRendering: options.svgRendering && supportSVGRendering()\n  };\n};\nwindow.html2canvas = function(elements, opts) {\n  elements = (elements.length) ? elements : [elements];\n  var queue,\n  canvas,\n  options = {\n    // general\n    logging: false,\n    elements: elements,\n    background: \"#fff\",\n\n    // preload options\n    proxy: null,\n    timeout: 0,    // no timeout\n    useCORS: false, // try to load images as CORS (where available), before falling back to proxy\n    allowTaint: false, // whether to allow images to taint the canvas, won't need proxy if set to true\n\n    // parse options\n    svgRendering: false, // use svg powered rendering where available (FF11+)\n    ignoreElements: \"IFRAME|OBJECT|PARAM\",\n    useOverflow: true,\n    letterRendering: false,\n    chinese: false,\n\n    // render options\n\n    width: null,\n    height: null,\n    taintTest: true, // do a taint test with all images before applying to canvas\n    renderer: \"Canvas\"\n  };\n\n  options = _html2canvas.Util.Extend(opts, options);\n\n  _html2canvas.logging = options.logging;\n  options.complete = function( images ) {\n\n    if (typeof options.onpreloaded === \"function\") {\n      if ( options.onpreloaded( images ) === false ) {\n        return;\n      }\n    }\n    queue = _html2canvas.Parse( images, options );\n\n    if (typeof options.onparsed === \"function\") {\n      if ( options.onparsed( queue ) === false ) {\n        return;\n      }\n    }\n\n    canvas = _html2canvas.Renderer( queue, options );\n\n    if (typeof options.onrendered === \"function\") {\n      options.onrendered( canvas );\n    }\n\n\n  };\n\n  // for pages without images, we still want this to be async, i.e. return methods before executing\n  window.setTimeout( function(){\n    _html2canvas.Preload( options );\n  }, 0 );\n\n  return {\n    render: function( queue, opts ) {\n      return _html2canvas.Renderer( queue, _html2canvas.Util.Extend(opts, options) );\n    },\n    parse: function( images, opts ) {\n      return _html2canvas.Parse( images, _html2canvas.Util.Extend(opts, options) );\n    },\n    preload: function( opts ) {\n      return _html2canvas.Preload( _html2canvas.Util.Extend(opts, options) );\n    },\n    log: _html2canvas.Util.log\n  };\n};\n\nwindow.html2canvas.log = _html2canvas.Util.log; // for renderers\nwindow.html2canvas.Renderer = {\n  Canvas: undefined // We are assuming this will be used\n};\n_html2canvas.Renderer.Canvas = function(options) {\n  options = options || {};\n\n  var doc = document,\n  safeImages = [],\n  testCanvas = document.createElement(\"canvas\"),\n  testctx = testCanvas.getContext(\"2d\"),\n  Util = _html2canvas.Util,\n  canvas = options.canvas || doc.createElement('canvas');\n\n  function createShape(ctx, args) {\n    ctx.beginPath();\n    args.forEach(function(arg) {\n      ctx[arg.name].apply(ctx, arg['arguments']);\n    });\n    ctx.closePath();\n  }\n\n  function safeImage(item) {\n    if (safeImages.indexOf(item['arguments'][0].src ) === -1) {\n      testctx.drawImage(item['arguments'][0], 0, 0);\n      try {\n        testctx.getImageData(0, 0, 1, 1);\n      } catch(e) {\n        testCanvas = doc.createElement(\"canvas\");\n        testctx = testCanvas.getContext(\"2d\");\n        return false;\n      }\n      safeImages.push(item['arguments'][0].src);\n    }\n    return true;\n  }\n\n  function renderItem(ctx, item) {\n    switch(item.type){\n      case \"variable\":\n        ctx[item.name] = item['arguments'];\n        break;\n      case \"function\":\n        switch(item.name) {\n          case \"createPattern\":\n            if (item['arguments'][0].width > 0 && item['arguments'][0].height > 0) {\n              try {\n                ctx.fillStyle = ctx.createPattern(item['arguments'][0], \"repeat\");\n              }\n              catch(e) {\n                Util.log(\"html2canvas: Renderer: Error creating pattern\", e.message);\n              }\n            }\n            break;\n          case \"drawShape\":\n            createShape(ctx, item['arguments']);\n            break;\n          case \"drawImage\":\n            if (item['arguments'][8] > 0 && item['arguments'][7] > 0) {\n              if (!options.taintTest || (options.taintTest && safeImage(item))) {\n                ctx.drawImage.apply( ctx, item['arguments'] );\n              }\n            }\n            break;\n          default:\n            ctx[item.name].apply(ctx, item['arguments']);\n        }\n        break;\n    }\n  }\n\n  return function(parsedData, options, document, queue, _html2canvas) {\n    var ctx = canvas.getContext(\"2d\"),\n    newCanvas,\n    bounds,\n    fstyle,\n    zStack = parsedData.stack;\n\n    canvas.width = canvas.style.width =  options.width || zStack.ctx.width;\n    canvas.height = canvas.style.height = options.height || zStack.ctx.height;\n\n    fstyle = ctx.fillStyle;\n    ctx.fillStyle = (Util.isTransparent(zStack.backgroundColor) && options.background !== undefined) ? options.background : parsedData.backgroundColor;\n    ctx.fillRect(0, 0, canvas.width, canvas.height);\n    ctx.fillStyle = fstyle;\n\n    queue.forEach(function(storageContext) {\n      // set common settings for canvas\n      ctx.textBaseline = \"bottom\";\n      ctx.save();\n\n      if (storageContext.transform.matrix) {\n        ctx.translate(storageContext.transform.origin[0], storageContext.transform.origin[1]);\n        ctx.transform.apply(ctx, storageContext.transform.matrix);\n        ctx.translate(-storageContext.transform.origin[0], -storageContext.transform.origin[1]);\n      }\n\n      if (storageContext.clip){\n        ctx.beginPath();\n        ctx.rect(storageContext.clip.left, storageContext.clip.top, storageContext.clip.width, storageContext.clip.height);\n        ctx.clip();\n      }\n\n      if (storageContext.ctx.storage) {\n        storageContext.ctx.storage.forEach(function(item) {\n          renderItem(ctx, item);\n        });\n      }\n\n      ctx.restore();\n    });\n\n    Util.log(\"html2canvas: Renderer: Canvas renderer done - returning canvas obj\");\n\n    if (options.elements.length === 1) {\n      if (typeof options.elements[0] === \"object\" && options.elements[0].nodeName !== \"BODY\") {\n        // crop image to the bounds of selected (single) element\n        bounds = _html2canvas.Util.Bounds(options.elements[0]);\n        newCanvas = document.createElement('canvas');\n        newCanvas.width = Math.ceil(bounds.width);\n        newCanvas.height = Math.ceil(bounds.height);\n        ctx = newCanvas.getContext(\"2d\");\n\n        // fix https://github.com/niklasvh/html2canvas/commit/f61ceea01d0240624aaee5b24d02f4e2fe6a69d2\n        //ctx.drawImage(canvas, bounds.left, bounds.top, bounds.width, bounds.height, 0, 0, bounds.width, bounds.height);\n        var imgData = canvas.getContext(\"2d\").getImageData(bounds.left, bounds.top, bounds.width, bounds.height);\n        ctx.putImageData(imgData, 0, 0);\n        canvas = null;\n        return newCanvas;\n      }\n    }\n\n    return canvas;\n  };\n};\n})(window,document);"
  },
  {
    "path": "flowable-ui-web/idm/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": "flowable-ui-web/idm/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": "flowable-ui-web/idm/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": "flowable-ui-web/idm/libs/ng-file-upload/FileAPI.js",
    "content": "/*! FileAPI 2.0.7 - BSD | git://github.com/mailru/FileAPI.git\n * FileAPI — a set of  javascript tools for working with files. Multiupload, drag'n'drop and chunked file upload. Images: crop, resize and auto orientation by EXIF.\n */\n\n/*\n * JavaScript Canvas to Blob 2.0.5\n * https://github.com/blueimp/JavaScript-Canvas-to-Blob\n *\n * Copyright 2012, Sebastian Tschan\n * https://blueimp.net\n *\n * Licensed under the MIT license:\n * http://www.opensource.org/licenses/MIT\n *\n * Based on stackoverflow user Stoive's code snippet:\n * http://stackoverflow.com/q/4998908\n */\n\n/*jslint nomen: true, regexp: true */\n/*global window, atob, Blob, ArrayBuffer, Uint8Array */\n\n(function (window) {\n    'use strict';\n    var CanvasPrototype = window.HTMLCanvasElement &&\n            window.HTMLCanvasElement.prototype,\n        hasBlobConstructor = window.Blob && (function () {\n            try {\n                return Boolean(new Blob());\n            } catch (e) {\n                return false;\n            }\n        }()),\n        hasArrayBufferViewSupport = hasBlobConstructor && window.Uint8Array &&\n            (function () {\n                try {\n                    return new Blob([new Uint8Array(100)]).size === 100;\n                } catch (e) {\n                    return false;\n                }\n            }()),\n        BlobBuilder = window.BlobBuilder || window.WebKitBlobBuilder ||\n            window.MozBlobBuilder || window.MSBlobBuilder,\n        dataURLtoBlob = (hasBlobConstructor || BlobBuilder) && window.atob &&\n            window.ArrayBuffer && window.Uint8Array && function (dataURI) {\n                var byteString,\n                    arrayBuffer,\n                    intArray,\n                    i,\n                    mimeString,\n                    bb;\n                if (dataURI.split(',')[0].indexOf('base64') >= 0) {\n                    // Convert base64 to raw binary data held in a string:\n                    byteString = atob(dataURI.split(',')[1]);\n                } else {\n                    // Convert base64/URLEncoded data component to raw binary data:\n                    byteString = decodeURIComponent(dataURI.split(',')[1]);\n                }\n                // Write the bytes of the string to an ArrayBuffer:\n                arrayBuffer = new ArrayBuffer(byteString.length);\n                intArray = new Uint8Array(arrayBuffer);\n                for (i = 0; i < byteString.length; i += 1) {\n                    intArray[i] = byteString.charCodeAt(i);\n                }\n                // Separate out the mime component:\n                mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0];\n                // Write the ArrayBuffer (or ArrayBufferView) to a blob:\n                if (hasBlobConstructor) {\n                    return new Blob(\n                        [hasArrayBufferViewSupport ? intArray : arrayBuffer],\n                        {type: mimeString}\n                    );\n                }\n                bb = new BlobBuilder();\n                bb.append(arrayBuffer);\n                return bb.getBlob(mimeString);\n            };\n    if (window.HTMLCanvasElement && !CanvasPrototype.toBlob) {\n        if (CanvasPrototype.mozGetAsFile) {\n            CanvasPrototype.toBlob = function (callback, type, quality) {\n                if (quality && CanvasPrototype.toDataURL && dataURLtoBlob) {\n                    callback(dataURLtoBlob(this.toDataURL(type, quality)));\n                } else {\n                    callback(this.mozGetAsFile('blob', type));\n                }\n            };\n        } else if (CanvasPrototype.toDataURL && dataURLtoBlob) {\n            CanvasPrototype.toBlob = function (callback, type, quality) {\n                callback(dataURLtoBlob(this.toDataURL(type, quality)));\n            };\n        }\n    }\n    window.dataURLtoBlob = dataURLtoBlob;\n})(window);\n\n/*jslint evil: true */\n/*global window, URL, webkitURL, ActiveXObject */\n\n(function (window, undef){\n\t'use strict';\n\n\tvar\n\t\tgid = 1,\n\t\tnoop = function (){},\n\n\t\tdocument = window.document,\n\t\tdoctype = document.doctype || {},\n\t\tuserAgent = window.navigator.userAgent,\n\n\t\t// https://github.com/blueimp/JavaScript-Load-Image/blob/master/load-image.js#L48\n\t\tapiURL = (window.createObjectURL && window) || (window.URL && URL.revokeObjectURL && URL) || (window.webkitURL && webkitURL),\n\n\t\tBlob = window.Blob,\n\t\tFile = window.File,\n\t\tFileReader = window.FileReader,\n\t\tFormData = window.FormData,\n\n\n\t\tXMLHttpRequest = window.XMLHttpRequest,\n\t\tjQuery = window.jQuery,\n\n\t\thtml5 =    !!(File && (FileReader && (window.Uint8Array || FormData || XMLHttpRequest.prototype.sendAsBinary)))\n\t\t\t\t&& !(/safari\\//i.test(userAgent) && !/chrome\\//i.test(userAgent) && /windows/i.test(userAgent)), // BugFix: https://github.com/mailru/FileAPI/issues/25\n\n\t\tcors = html5 && ('withCredentials' in (new XMLHttpRequest)),\n\n\t\tchunked = html5 && !!Blob && !!(Blob.prototype.webkitSlice || Blob.prototype.mozSlice || Blob.prototype.slice),\n\n\t\t// https://github.com/blueimp/JavaScript-Canvas-to-Blob\n\t\tdataURLtoBlob = window.dataURLtoBlob,\n\n\n\t\t_rimg = /img/i,\n\t\t_rcanvas = /canvas/i,\n\t\t_rimgcanvas = /img|canvas/i,\n\t\t_rinput = /input/i,\n\t\t_rdata = /^data:[^,]+,/,\n\n\t\t_toString = {}.toString,\n\n\n\t\tMath = window.Math,\n\n\t\t_SIZE_CONST = function (pow){\n\t\t\tpow = new window.Number(Math.pow(1024, pow));\n\t\t\tpow.from = function (sz){ return Math.round(sz * this); };\n\t\t\treturn\tpow;\n\t\t},\n\n\t\t_elEvents = {}, // element event listeners\n\t\t_infoReader = [], // list of file info processors\n\n\t\t_readerEvents = 'abort progress error load loadend',\n\t\t_xhrPropsExport = 'status statusText readyState response responseXML responseText responseBody'.split(' '),\n\n\t\tcurrentTarget = 'currentTarget', // for minimize\n\t\tpreventDefault = 'preventDefault', // and this too\n\n\t\t_isArray = function (ar) {\n\t\t\treturn\tar && ('length' in ar);\n\t\t},\n\n\t\t/**\n\t\t * Iterate over a object or array\n\t\t */\n\t\t_each = function (obj, fn, ctx){\n\t\t\tif( obj ){\n\t\t\t\tif( _isArray(obj) ){\n\t\t\t\t\tfor( var i = 0, n = obj.length; i < n; i++ ){\n\t\t\t\t\t\tif( i in obj ){\n\t\t\t\t\t\t\tfn.call(ctx, obj[i], i, obj);\n\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\tfor( var key in obj ){\n\t\t\t\t\t\tif( obj.hasOwnProperty(key) ){\n\t\t\t\t\t\t\tfn.call(ctx, obj[key], key, obj);\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/**\n\t\t * Merge the contents of two or more objects together into the first object\n\t\t */\n\t\t_extend = function (dst){\n\t\t\tvar args = arguments, i = 1, _ext = function (val, key){ dst[key] = val; };\n\t\t\tfor( ; i < args.length; i++ ){\n\t\t\t\t_each(args[i], _ext);\n\t\t\t}\n\t\t\treturn  dst;\n\t\t},\n\n\t\t/**\n\t\t * Add event listener\n\t\t */\n\t\t_on = function (el, type, fn){\n\t\t\tif( el ){\n\t\t\t\tvar uid = api.uid(el);\n\n\t\t\t\tif( !_elEvents[uid] ){\n\t\t\t\t\t_elEvents[uid] = {};\n\t\t\t\t}\n\n\t\t\t\tvar isFileReader = (FileReader && el) && (el instanceof FileReader);\n\t\t\t\t_each(type.split(/\\s+/), function (type){\n\t\t\t\t\tif( jQuery && !isFileReader){\n\t\t\t\t\t\tjQuery.event.add(el, type, fn);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif( !_elEvents[uid][type] ){\n\t\t\t\t\t\t\t_elEvents[uid][type] = [];\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t_elEvents[uid][type].push(fn);\n\n\t\t\t\t\t\tif( el.addEventListener ){ el.addEventListener(type, fn, false); }\n\t\t\t\t\t\telse if( el.attachEvent ){ el.attachEvent('on'+type, fn); }\n\t\t\t\t\t\telse { el['on'+type] = fn; }\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t},\n\n\n\t\t/**\n\t\t * Remove event listener\n\t\t */\n\t\t_off = function (el, type, fn){\n\t\t\tif( el ){\n\t\t\t\tvar uid = api.uid(el), events = _elEvents[uid] || {};\n\n\t\t\t\tvar isFileReader = (FileReader && el) && (el instanceof FileReader);\n\t\t\t\t_each(type.split(/\\s+/), function (type){\n\t\t\t\t\tif( jQuery && !isFileReader){\n\t\t\t\t\t\tjQuery.event.remove(el, type, fn);\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\tvar fns = events[type] || [], i = fns.length;\n\n\t\t\t\t\t\twhile( i-- ){\n\t\t\t\t\t\t\tif( fns[i] === fn ){\n\t\t\t\t\t\t\t\tfns.splice(i, 1);\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\n\t\t\t\t\t\tif( el.addEventListener ){ el.removeEventListener(type, fn, false); }\n\t\t\t\t\t\telse if( el.detachEvent ){ el.detachEvent('on'+type, fn); }\n\t\t\t\t\t\telse { el['on'+type] = null; }\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t},\n\n\n\t\t_one = function(el, type, fn){\n\t\t\t_on(el, type, function _(evt){\n\t\t\t\t_off(el, type, _);\n\t\t\t\tfn(evt);\n\t\t\t});\n\t\t},\n\n\n\t\t_fixEvent = function (evt){\n\t\t\tif( !evt.target ){ evt.target = window.event && window.event.srcElement || document; }\n\t\t\tif( evt.target.nodeType === 3 ){ evt.target = evt.target.parentNode; }\n\t\t\treturn  evt;\n\t\t},\n\n\n\t\t_supportInputAttr = function (attr){\n\t\t\tvar input = document.createElement('input');\n\t\t\tinput.setAttribute('type', \"file\");\n\t\t\treturn attr in input;\n\t\t},\n\n\n\t\t/**\n\t\t * FileAPI (core object)\n\t\t */\n\t\tapi = {\n\t\t\tversion: '2.0.7',\n\n\t\t\tcors: false,\n\t\t\thtml5: true,\n\t\t\tmedia: false,\n\t\t\tformData: true,\n\t\t\tmultiPassResize: true,\n\n\t\t\tdebug: false,\n\t\t\tpingUrl: false,\n\t\t\tmultiFlash: false,\n\t\t\tflashAbortTimeout: 0,\n\t\t\twithCredentials: true,\n\n\t\t\tstaticPath: './dist/',\n\n\t\t\tflashUrl: 0, // @default: './FileAPI.flash.swf'\n\t\t\tflashImageUrl: 0, // @default: './FileAPI.flash.image.swf'\n\n\t\t\tpostNameConcat: function (name, idx){\n\t\t\t\treturn\tname + (idx != null ? '['+ idx +']' : '');\n\t\t\t},\n\n\t\t\text2mime: {\n\t\t\t\t  jpg:\t'image/jpeg'\n\t\t\t\t, tif:\t'image/tiff'\n\t\t\t\t, txt:\t'text/plain'\n\t\t\t},\n\n\t\t\t// Fallback for flash\n\t\t\taccept: {\n\t\t\t\t  'image/*': 'art bm bmp dwg dxf cbr cbz fif fpx gif ico iefs jfif jpe jpeg jpg jps jut mcf nap nif pbm pcx pgm pict pm png pnm qif qtif ras rast rf rp svf tga tif tiff xbm xbm xpm xwd'\n\t\t\t\t, 'audio/*': 'm4a flac aac rm mpa wav wma ogg mp3 mp2 m3u mod amf dmf dsm far gdm imf it m15 med okt s3m stm sfx ult uni xm sid ac3 dts cue aif aiff wpl ape mac mpc mpp shn wv nsf spc gym adplug adx dsp adp ymf ast afc hps xs'\n\t\t\t\t, 'video/*': 'm4v 3gp nsv ts ty strm rm rmvb m3u ifo mov qt divx xvid bivx vob nrg img iso pva wmv asf asx ogm m2v avi bin dat dvr-ms mpg mpeg mp4 mkv avc vp3 svq3 nuv viv dv fli flv wpl'\n\t\t\t},\n\n\t\t\tuploadRetry : 0,\n\t\t\tnetworkDownRetryTimeout : 5000, // milliseconds, don't flood when network is down\n\n\t\t\tchunkSize : 0,\n\t\t\tchunkUploadRetry : 0,\n\t\t\tchunkNetworkDownRetryTimeout : 2000, // milliseconds, don't flood when network is down\n\n\t\t\tKB: _SIZE_CONST(1),\n\t\t\tMB: _SIZE_CONST(2),\n\t\t\tGB: _SIZE_CONST(3),\n\t\t\tTB: _SIZE_CONST(4),\n\n\t\t\tEMPTY_PNG: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAC0lEQVQIW2NkAAIAAAoAAggA9GkAAAAASUVORK5CYII=',\n\n\t\t\texpando: 'fileapi' + (new Date).getTime(),\n\n\t\t\tuid: function (obj){\n\t\t\t\treturn\tobj\n\t\t\t\t\t? (obj[api.expando] = obj[api.expando] || api.uid())\n\t\t\t\t\t: (++gid, api.expando + gid)\n\t\t\t\t;\n\t\t\t},\n\n\t\t\tlog: function (){\n\t\t\t\tif( api.debug && window.console && console.log ){\n\t\t\t\t\tif( console.log.apply ){\n\t\t\t\t\t\tconsole.log.apply(console, arguments);\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\tconsole.log([].join.call(arguments, ' '));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\n\t\t\t/**\n\t\t\t * Create new image\n\t\t\t *\n\t\t\t * @param {String} [src]\n\t\t\t * @param {Function} [fn]   1. error -- boolean, 2. img -- Image element\n\t\t\t * @returns {HTMLElement}\n\t\t\t */\n\t\t\tnewImage: function (src, fn){\n\t\t\t\tvar img = document.createElement('img');\n\t\t\t\tif( fn ){\n\t\t\t\t\tapi.event.one(img, 'error load', function (evt){\n\t\t\t\t\t\tfn(evt.type == 'error', img);\n\t\t\t\t\t\timg = null;\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\timg.src = src;\n\t\t\t\treturn\timg;\n\t\t\t},\n\n\t\t\t/**\n\t\t\t * Get XHR\n\t\t\t * @returns {XMLHttpRequest}\n\t\t\t */\n\t\t\tgetXHR: function (){\n\t\t\t\tvar xhr;\n\n\t\t\t\tif( XMLHttpRequest ){\n\t\t\t\t\txhr = new XMLHttpRequest;\n\t\t\t\t}\n\t\t\t\telse if( window.ActiveXObject ){\n\t\t\t\t\ttry {\n\t\t\t\t\t\txhr = new ActiveXObject('MSXML2.XMLHttp.3.0');\n\t\t\t\t\t} catch (e) {\n\t\t\t\t\t\txhr = new ActiveXObject('Microsoft.XMLHTTP');\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn  xhr;\n\t\t\t},\n\n\t\t\tisArray: _isArray,\n\n\t\t\tsupport: {\n\t\t\t\tdnd:     cors && ('ondrop' in document.createElement('div')),\n\t\t\t\tcors:    cors,\n\t\t\t\thtml5:   html5,\n\t\t\t\tchunked: chunked,\n\t\t\t\tdataURI: true,\n\t\t\t\taccept:   _supportInputAttr('accept'),\n\t\t\t\tmultiple: _supportInputAttr('multiple')\n\t\t\t},\n\n\t\t\tevent: {\n\t\t\t\t  on: _on\n\t\t\t\t, off: _off\n\t\t\t\t, one: _one\n\t\t\t\t, fix: _fixEvent\n\t\t\t},\n\n\n\t\t\tthrottle: function(fn, delay) {\n\t\t\t\tvar id, args;\n\n\t\t\t\treturn function _throttle(){\n\t\t\t\t\targs = arguments;\n\n\t\t\t\t\tif( !id ){\n\t\t\t\t\t\tfn.apply(window, args);\n\t\t\t\t\t\tid = setTimeout(function (){\n\t\t\t\t\t\t\tid = 0;\n\t\t\t\t\t\t\tfn.apply(window, args);\n\t\t\t\t\t\t}, delay);\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\t},\n\n\n\t\t\tF: function (){},\n\n\n\t\t\tparseJSON: function (str){\n\t\t\t\tvar json;\n\t\t\t\tif( window.JSON && JSON.parse ){\n\t\t\t\t\tjson = JSON.parse(str);\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tjson = (new Function('return ('+str.replace(/([\\r\\n])/g, '\\\\$1')+');'))();\n\t\t\t\t}\n\t\t\t\treturn json;\n\t\t\t},\n\n\n\t\t\ttrim: function (str){\n\t\t\t\tstr = String(str);\n\t\t\t\treturn\tstr.trim ? str.trim() : str.replace(/^\\s+|\\s+$/g, '');\n\t\t\t},\n\n\t\t\t/**\n\t\t\t * Simple Defer\n\t\t\t * @return\t{Object}\n\t\t\t */\n\t\t\tdefer: function (){\n\t\t\t\tvar\n\t\t\t\t\t  list = []\n\t\t\t\t\t, result\n\t\t\t\t\t, error\n\t\t\t\t\t, defer = {\n\t\t\t\t\t\tresolve: function (err, res){\n\t\t\t\t\t\t\tdefer.resolve = noop;\n\t\t\t\t\t\t\terror\t= err || false;\n\t\t\t\t\t\t\tresult\t= res;\n\n\t\t\t\t\t\t\twhile( res = list.shift() ){\n\t\t\t\t\t\t\t\tres(error, result);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\n\t\t\t\t\t\tthen: function (fn){\n\t\t\t\t\t\t\tif( error !== undef ){\n\t\t\t\t\t\t\t\tfn(error, result);\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tlist.push(fn);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t};\n\n\t\t\t\treturn\tdefer;\n\t\t\t},\n\n\t\t\tqueue: function (fn){\n\t\t\t\tvar\n\t\t\t\t\t  _idx = 0\n\t\t\t\t\t, _length = 0\n\t\t\t\t\t, _fail = false\n\t\t\t\t\t, _end = false\n\t\t\t\t\t, queue = {\n\t\t\t\t\t\tinc: function (){\n\t\t\t\t\t\t\t_length++;\n\t\t\t\t\t\t},\n\n\t\t\t\t\t\tnext: function (){\n\t\t\t\t\t\t\t_idx++;\n\t\t\t\t\t\t\tsetTimeout(queue.check, 0);\n\t\t\t\t\t\t},\n\n\t\t\t\t\t\tcheck: function (){\n\t\t\t\t\t\t\t(_idx >= _length) && !_fail && queue.end();\n\t\t\t\t\t\t},\n\n\t\t\t\t\t\tisFail: function (){\n\t\t\t\t\t\t\treturn _fail;\n\t\t\t\t\t\t},\n\n\t\t\t\t\t\tfail: function (){\n\t\t\t\t\t\t\t!_fail && fn(_fail = true);\n\t\t\t\t\t\t},\n\n\t\t\t\t\t\tend: function (){\n\t\t\t\t\t\t\tif( !_end ){\n\t\t\t\t\t\t\t\t_end = true;\n\t\t\t\t\t\t\t\tfn();\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 queue;\n\t\t\t},\n\n\n\t\t\t/**\n\t\t\t * For each object\n\t\t\t *\n\t\t\t * @param\t{Object|Array}\tobj\n\t\t\t * @param\t{Function}\t\tfn\n\t\t\t * @param\t{*}\t\t\t\t[ctx]\n\t\t\t */\n\t\t\teach: _each,\n\n\n\t\t\t/**\n\t\t\t * Async for\n\t\t\t * @param {Array} array\n\t\t\t * @param {Function} callback\n\t\t\t */\n\t\t\tafor: function (array, callback){\n\t\t\t\tvar i = 0, n = array.length;\n\n\t\t\t\tif( _isArray(array) && n-- ){\n\t\t\t\t\t(function _next(){\n\t\t\t\t\t\tcallback(n != i && _next, array[i], i++);\n\t\t\t\t\t})();\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tcallback(false);\n\t\t\t\t}\n\t\t\t},\n\n\n\t\t\t/**\n\t\t\t * Merge the contents of two or more objects together into the first object\n\t\t\t *\n\t\t\t * @param\t{Object}\tdst\n\t\t\t * @return\t{Object}\n\t\t\t */\n\t\t\textend: _extend,\n\n\n\t\t\t/**\n\t\t\t * Is file?\n\t\t\t * @param  {File}  file\n\t\t\t * @return {Boolean}\n\t\t\t */\n\t\t\tisFile: function (file){\n\t\t\t\treturn _toString.call(file) === '[object File]';\n\t\t\t},\n\n\n\t\t\t/**\n\t\t\t * Is blob?\n\t\t\t * @param   {Blob}  blob\n\t\t\t * @returns {Boolean}\n\t\t\t */\n\t\t\tisBlob: function (blob) {\n\t\t\t\treturn this.isFile(blob) || (_toString.call(blob) === '[object Blob]');\n\t\t\t},\n\n\n\t\t\t/**\n\t\t\t * Is canvas element\n\t\t\t *\n\t\t\t * @param\t{HTMLElement}\tel\n\t\t\t * @return\t{Boolean}\n\t\t\t */\n\t\t\tisCanvas: function (el){\n\t\t\t\treturn\tel && _rcanvas.test(el.nodeName);\n\t\t\t},\n\n\n\t\t\tgetFilesFilter: function (filter){\n\t\t\t\tfilter = typeof filter == 'string' ? filter : (filter.getAttribute && filter.getAttribute('accept') || '');\n\t\t\t\treturn\tfilter ? new RegExp('('+ filter.replace(/\\./g, '\\\\.').replace(/,/g, '|') +')$', 'i') : /./;\n\t\t\t},\n\n\n\n\t\t\t/**\n\t\t\t * Read as DataURL\n\t\t\t *\n\t\t\t * @param {File|Element} file\n\t\t\t * @param {Function} fn\n\t\t\t */\n\t\t\treadAsDataURL: function (file, fn){\n\t\t\t\tif( api.isCanvas(file) ){\n\t\t\t\t\t_emit(file, fn, 'load', api.toDataURL(file));\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\t_readAs(file, fn, 'DataURL');\n\t\t\t\t}\n\t\t\t},\n\n\n\t\t\t/**\n\t\t\t * Read as Binary string\n\t\t\t *\n\t\t\t * @param {File} file\n\t\t\t * @param {Function} fn\n\t\t\t */\n\t\t\treadAsBinaryString: function (file, fn){\n\t\t\t\tif( _hasSupportReadAs('BinaryString') ){\n\t\t\t\t\t_readAs(file, fn, 'BinaryString');\n\t\t\t\t} else {\n\t\t\t\t\t// Hello IE10!\n\t\t\t\t\t_readAs(file, function (evt){\n\t\t\t\t\t\tif( evt.type == 'load' ){\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t// dataURL -> binaryString\n\t\t\t\t\t\t\t\tevt.result = api.toBinaryString(evt.result);\n\t\t\t\t\t\t\t} catch (e){\n\t\t\t\t\t\t\t\tevt.type = 'error';\n\t\t\t\t\t\t\t\tevt.message = e.toString();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tfn(evt);\n\t\t\t\t\t}, 'DataURL');\n\t\t\t\t}\n\t\t\t},\n\n\n\t\t\t/**\n\t\t\t * Read as ArrayBuffer\n\t\t\t *\n\t\t\t * @param {File} file\n\t\t\t * @param {Function} fn\n\t\t\t */\n\t\t\treadAsArrayBuffer: function(file, fn){\n\t\t\t\t_readAs(file, fn, 'ArrayBuffer');\n\t\t\t},\n\n\n\t\t\t/**\n\t\t\t * Read as text\n\t\t\t *\n\t\t\t * @param {File} file\n\t\t\t * @param {String} encoding\n\t\t\t * @param {Function} [fn]\n\t\t\t */\n\t\t\treadAsText: function(file, encoding, fn){\n\t\t\t\tif( !fn ){\n\t\t\t\t\tfn\t= encoding;\n\t\t\t\t\tencoding = 'utf-8';\n\t\t\t\t}\n\n\t\t\t\t_readAs(file, fn, 'Text', encoding);\n\t\t\t},\n\n\n\t\t\t/**\n\t\t\t * Convert image or canvas to DataURL\n\t\t\t *\n\t\t\t * @param   {Element}  el      Image or Canvas element\n\t\t\t * @param   {String}   [type]  mime-type\n\t\t\t * @return  {String}\n\t\t\t */\n\t\t\ttoDataURL: function (el, type){\n\t\t\t\tif( typeof el == 'string' ){\n\t\t\t\t\treturn  el;\n\t\t\t\t}\n\t\t\t\telse if( el.toDataURL ){\n\t\t\t\t\treturn  el.toDataURL(type || 'image/png');\n\t\t\t\t}\n\t\t\t},\n\n\n\t\t\t/**\n\t\t\t * Canvert string, image or canvas to binary string\n\t\t\t *\n\t\t\t * @param   {String|Element} val\n\t\t\t * @return  {String}\n\t\t\t */\n\t\t\ttoBinaryString: function (val){\n\t\t\t\treturn  window.atob(api.toDataURL(val).replace(_rdata, ''));\n\t\t\t},\n\n\n\t\t\t/**\n\t\t\t * Read file or DataURL as ImageElement\n\t\t\t *\n\t\t\t * @param\t{File|String}\tfile\n\t\t\t * @param\t{Function}\t\tfn\n\t\t\t * @param\t{Boolean}\t\t[progress]\n\t\t\t */\n\t\t\treadAsImage: function (file, fn, progress){\n\t\t\t\tif( api.isFile(file) ){\n\t\t\t\t\tif( apiURL ){\n\t\t\t\t\t\t/** @namespace apiURL.createObjectURL */\n\t\t\t\t\t\tvar data = apiURL.createObjectURL(file);\n\t\t\t\t\t\tif( data === undef ){\n\t\t\t\t\t\t\t_emit(file, fn, 'error');\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse {\n\t\t\t\t\t\t\tapi.readAsImage(data, fn, progress);\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\tapi.readAsDataURL(file, function (evt){\n\t\t\t\t\t\t\tif( evt.type == 'load' ){\n\t\t\t\t\t\t\t\tapi.readAsImage(evt.result, fn, progress);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse if( progress || evt.type == 'error' ){\n\t\t\t\t\t\t\t\t_emit(file, fn, evt, null, { loaded: evt.loaded, total: evt.total });\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\telse if( api.isCanvas(file) ){\n\t\t\t\t\t_emit(file, fn, 'load', file);\n\t\t\t\t}\n\t\t\t\telse if( _rimg.test(file.nodeName) ){\n\t\t\t\t\tif( file.complete ){\n\t\t\t\t\t\t_emit(file, fn, 'load', file);\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\tvar events = 'error abort load';\n\t\t\t\t\t\t_one(file, events, function _fn(evt){\n\t\t\t\t\t\t\tif( evt.type == 'load' && apiURL ){\n\t\t\t\t\t\t\t\t/** @namespace apiURL.revokeObjectURL */\n\t\t\t\t\t\t\t\tapiURL.revokeObjectURL(file.src);\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t_off(file, events, _fn);\n\t\t\t\t\t\t\t_emit(file, fn, evt, file);\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse if( file.iframe ){\n\t\t\t\t\t_emit(file, fn, { type: 'error' });\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\t// Created image\n\t\t\t\t\tvar img = api.newImage(file.dataURL || file);\n\t\t\t\t\tapi.readAsImage(img, fn, progress);\n\t\t\t\t}\n\t\t\t},\n\n\n\t\t\t/**\n\t\t\t * Make file by name\n\t\t\t *\n\t\t\t * @param\t{String}\tname\n\t\t\t * @return\t{Array}\n\t\t\t */\n\t\t\tcheckFileObj: function (name){\n\t\t\t\tvar file = {}, accept = api.accept;\n\n\t\t\t\tif( typeof name == 'object' ){\n\t\t\t\t\tfile = name;\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tfile.name = (name + '').split(/\\\\|\\//g).pop();\n\t\t\t\t}\n\n\t\t\t\tif( file.type == null ){\n\t\t\t\t\tfile.type = file.name.split('.').pop();\n\t\t\t\t}\n\n\t\t\t\t_each(accept, function (ext, type){\n\t\t\t\t\text = new RegExp(ext.replace(/\\s/g, '|'), 'i');\n\t\t\t\t\tif( ext.test(file.type) || api.ext2mime[file.type] ){\n\t\t\t\t\t\tfile.type = api.ext2mime[file.type] || (type.split('/')[0] +'/'+ file.type);\n\t\t\t\t\t}\n\t\t\t\t});\n\n\t\t\t\treturn\tfile;\n\t\t\t},\n\n\n\t\t\t/**\n\t\t\t * Get drop files\n\t\t\t *\n\t\t\t * @param\t{Event}\tevt\n\t\t\t * @param\t{Function} callback\n\t\t\t */\n\t\t\tgetDropFiles: function (evt, callback){\n\t\t\t\tvar\n\t\t\t\t\t  files = []\n\t\t\t\t\t, dataTransfer = _getDataTransfer(evt)\n\t\t\t\t\t, entrySupport = _isArray(dataTransfer.items) && dataTransfer.items[0] && _getAsEntry(dataTransfer.items[0])\n\t\t\t\t\t, queue = api.queue(function (){ callback(files); })\n\t\t\t\t;\n\n\t\t\t\t_each((entrySupport ? dataTransfer.items : dataTransfer.files) || [], function (item){\n\t\t\t\t\tqueue.inc();\n\n\t\t\t\t\ttry {\n\t\t\t\t\t\tif( entrySupport ){\n\t\t\t\t\t\t\t_readEntryAsFiles(item, function (err, entryFiles){\n\t\t\t\t\t\t\t\tif( err ){\n\t\t\t\t\t\t\t\t\tapi.log('[err] getDropFiles:', err);\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tfiles.push.apply(files, entryFiles);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tqueue.next();\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\t_isRegularFile(item, function (yes){\n\t\t\t\t\t\t\t\tyes && files.push(item);\n\t\t\t\t\t\t\t\tqueue.next();\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\tcatch( err ){\n\t\t\t\t\t\tqueue.next();\n\t\t\t\t\t\tapi.log('[err] getDropFiles: ', err);\n\t\t\t\t\t}\n\t\t\t\t});\n\n\t\t\t\tqueue.check();\n\t\t\t},\n\n\n\t\t\t/**\n\t\t\t * Get file list\n\t\t\t *\n\t\t\t * @param\t{HTMLInputElement|Event}\tinput\n\t\t\t * @param\t{String|Function}\t[filter]\n\t\t\t * @param\t{Function}\t\t\t[callback]\n\t\t\t * @return\t{Array|Null}\n\t\t\t */\n\t\t\tgetFiles: function (input, filter, callback){\n\t\t\t\tvar files = [];\n\n\t\t\t\tif( callback ){\n\t\t\t\t\tapi.filterFiles(api.getFiles(input), filter, callback);\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\n\t\t\t\tif( input.jquery ){\n\t\t\t\t\t// jQuery object\n\t\t\t\t\tinput.each(function (){\n\t\t\t\t\t\tfiles = files.concat(api.getFiles(this));\n\t\t\t\t\t});\n\t\t\t\t\tinput\t= files;\n\t\t\t\t\tfiles\t= [];\n\t\t\t\t}\n\n\t\t\t\tif( typeof filter == 'string' ){\n\t\t\t\t\tfilter\t= api.getFilesFilter(filter);\n\t\t\t\t}\n\n\t\t\t\tif( input.originalEvent ){\n\t\t\t\t\t// jQuery event\n\t\t\t\t\tinput = _fixEvent(input.originalEvent);\n\t\t\t\t}\n\t\t\t\telse if( input.srcElement ){\n\t\t\t\t\t// IE Event\n\t\t\t\t\tinput = _fixEvent(input);\n\t\t\t\t}\n\n\n\t\t\t\tif( input.dataTransfer ){\n\t\t\t\t\t// Drag'n'Drop\n\t\t\t\t\tinput = input.dataTransfer;\n\t\t\t\t}\n\t\t\t\telse if( input.target ){\n\t\t\t\t\t// Event\n\t\t\t\t\tinput = input.target;\n\t\t\t\t}\n\n\t\t\t\tif( input.files ){\n\t\t\t\t\t// Input[type=\"file\"]\n\t\t\t\t\tfiles = input.files;\n\n\t\t\t\t\tif( !html5 ){\n\t\t\t\t\t\t// Partial support for file api\n\t\t\t\t\t\tfiles[0].blob\t= input;\n\t\t\t\t\t\tfiles[0].iframe\t= true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse if( !html5 && isInputFile(input) ){\n\t\t\t\t\tif( api.trim(input.value) ){\n\t\t\t\t\t\tfiles = [api.checkFileObj(input.value)];\n\t\t\t\t\t\tfiles[0].blob   = input;\n\t\t\t\t\t\tfiles[0].iframe = true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse if( _isArray(input) ){\n\t\t\t\t\tfiles\t= input;\n\t\t\t\t}\n\n\t\t\t\treturn\tapi.filter(files, function (file){ return !filter || filter.test(file.name); });\n\t\t\t},\n\n\n\t\t\t/**\n\t\t\t * Get total file size\n\t\t\t * @param\t{Array}\tfiles\n\t\t\t * @return\t{Number}\n\t\t\t */\n\t\t\tgetTotalSize: function (files){\n\t\t\t\tvar size = 0, i = files && files.length;\n\t\t\t\twhile( i-- ){\n\t\t\t\t\tsize += files[i].size;\n\t\t\t\t}\n\t\t\t\treturn\tsize;\n\t\t\t},\n\n\n\t\t\t/**\n\t\t\t * Get image information\n\t\t\t *\n\t\t\t * @param\t{File}\t\tfile\n\t\t\t * @param\t{Function}\tfn\n\t\t\t */\n\t\t\tgetInfo: function (file, fn){\n\t\t\t\tvar info = {}, readers = _infoReader.concat();\n\n\t\t\t\tif( api.isFile(file) ){\n\t\t\t\t\t(function _next(){\n\t\t\t\t\t\tvar reader = readers.shift();\n\t\t\t\t\t\tif( reader ){\n\t\t\t\t\t\t\tif( reader.test(file.type) ){\n\t\t\t\t\t\t\t\treader(file, function (err, res){\n\t\t\t\t\t\t\t\t\tif( err ){\n\t\t\t\t\t\t\t\t\t\tfn(err);\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\t_extend(info, res);\n\t\t\t\t\t\t\t\t\t\t_next();\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\telse {\n\t\t\t\t\t\t\t\t_next();\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\tfn(false, info);\n\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\tfn('not_support_info', info);\n\t\t\t\t}\n\t\t\t},\n\n\n\t\t\t/**\n\t\t\t * Add information reader\n\t\t\t *\n\t\t\t * @param {RegExp} mime\n\t\t\t * @param {Function} fn\n\t\t\t */\n\t\t\taddInfoReader: function (mime, fn){\n\t\t\t\tfn.test = function (type){ return mime.test(type); };\n\t\t\t\t_infoReader.push(fn);\n\t\t\t},\n\n\n\t\t\t/**\n\t\t\t * Filter of array\n\t\t\t *\n\t\t\t * @param\t{Array}\t\tinput\n\t\t\t * @param\t{Function}\tfn\n\t\t\t * @return\t{Array}\n\t\t\t */\n\t\t\tfilter: function (input, fn){\n\t\t\t\tvar result = [], i = 0, n = input.length, val;\n\n\t\t\t\tfor( ; i < n; i++ ){\n\t\t\t\t\tif( i in input ){\n\t\t\t\t\t\tval = input[i];\n\t\t\t\t\t\tif( fn.call(val, val, i, input) ){\n\t\t\t\t\t\t\tresult.push(val);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn\tresult;\n\t\t\t},\n\n\n\t\t\t/**\n\t\t\t * Filter files\n\t\t\t *\n\t\t\t * @param\t{Array}\t\tfiles\n\t\t\t * @param\t{Function}\teachFn\n\t\t\t * @param\t{Function}\tresultFn\n\t\t\t */\n\t\t\tfilterFiles: function (files, eachFn, resultFn){\n\t\t\t\tif( files.length ){\n\t\t\t\t\t// HTML5 or Flash\n\t\t\t\t\tvar queue = files.concat(), file, result = [], deleted = [];\n\n\t\t\t\t\t(function _next(){\n\t\t\t\t\t\tif( queue.length ){\n\t\t\t\t\t\t\tfile = queue.shift();\n\t\t\t\t\t\t\tapi.getInfo(file, function (err, info){\n\t\t\t\t\t\t\t\t(eachFn(file, err ? false : info) ? result : deleted).push(file);\n\t\t\t\t\t\t\t\t_next();\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\tresultFn(result, deleted);\n\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\tresultFn([], files);\n\t\t\t\t}\n\t\t\t},\n\n\n\t\t\tupload: function (options){\n\t\t\t\toptions = _extend({\n\t\t\t\t\t  jsonp: 'callback'\n\t\t\t\t\t, prepare: api.F\n\t\t\t\t\t, beforeupload: api.F\n\t\t\t\t\t, upload: api.F\n\t\t\t\t\t, fileupload: api.F\n\t\t\t\t\t, fileprogress: api.F\n\t\t\t\t\t, filecomplete: api.F\n\t\t\t\t\t, progress: api.F\n\t\t\t\t\t, complete: api.F\n\t\t\t\t\t, pause: api.F\n\t\t\t\t\t, imageOriginal: true\n\t\t\t\t\t, chunkSize: api.chunkSize\n\t\t\t\t\t, chunkUploadRetry: api.chunkUploadRetry\n\t\t\t\t\t, uploadRetry: api.uploadRetry\n\t\t\t\t}, options);\n\n\n\t\t\t\tif( options.imageAutoOrientation && !options.imageTransform ){\n\t\t\t\t\toptions.imageTransform = { rotate: 'auto' };\n\t\t\t\t}\n\n\n\t\t\t\tvar\n\t\t\t\t\t  proxyXHR = new api.XHR(options)\n\t\t\t\t\t, dataArray = this._getFilesDataArray(options.files)\n\t\t\t\t\t, _this = this\n\t\t\t\t\t, _total = 0\n\t\t\t\t\t, _loaded = 0\n\t\t\t\t\t, _nextFile\n\t\t\t\t\t, _complete = false\n\t\t\t\t;\n\n\n\t\t\t\t// calc total size\n\t\t\t\t_each(dataArray, function (data){\n\t\t\t\t\t_total += data.size;\n\t\t\t\t});\n\n\t\t\t\t// Array of files\n\t\t\t\tproxyXHR.files = [];\n\t\t\t\t_each(dataArray, function (data){\n\t\t\t\t\tproxyXHR.files.push(data.file);\n\t\t\t\t});\n\n\t\t\t\t// Set upload status props\n\t\t\t\tproxyXHR.total\t= _total;\n\t\t\t\tproxyXHR.loaded\t= 0;\n\t\t\t\tproxyXHR.filesLeft = dataArray.length;\n\n\t\t\t\t// emit \"beforeupload\"  event\n\t\t\t\toptions.beforeupload(proxyXHR, options);\n\n\t\t\t\t// Upload by file\n\t\t\t\t_nextFile = function (){\n\t\t\t\t\tvar\n\t\t\t\t\t\t  data = dataArray.shift()\n\t\t\t\t\t\t, _file = data && data.file\n\t\t\t\t\t\t, _fileLoaded = false\n\t\t\t\t\t\t, _fileOptions = _simpleClone(options)\n\t\t\t\t\t;\n\n\t\t\t\t\tproxyXHR.filesLeft = dataArray.length;\n\n\t\t\t\t\tif( _file && _file.name === api.expando ){\n\t\t\t\t\t\t_file = null;\n\t\t\t\t\t\tapi.log('[warn] FileAPI.upload() — called without files');\n\t\t\t\t\t}\n\n\t\t\t\t\tif( ( proxyXHR.statusText != 'abort' || proxyXHR.current ) && data ){\n\t\t\t\t\t\t// Mark active job\n\t\t\t\t\t\t_complete = false;\n\n\t\t\t\t\t\t// Set current upload file\n\t\t\t\t\t\tproxyXHR.currentFile = _file;\n\n\t\t\t\t\t\t// Prepare file options\n\t\t\t\t\t\tif (_file && options.prepare(_file, _fileOptions) === false) {\n\t\t\t\t\t\t\t_nextFile.call(_this);\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t\t_fileOptions.file = _file;\n\n\t\t\t\t\t\t_this._getFormData(_fileOptions, data, function (form){\n\t\t\t\t\t\t\tif( !_loaded ){\n\t\t\t\t\t\t\t\t// emit \"upload\" event\n\t\t\t\t\t\t\t\toptions.upload(proxyXHR, options);\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tvar xhr = new api.XHR(_extend({}, _fileOptions, {\n\n\t\t\t\t\t\t\t\tupload: _file ? function (){\n\t\t\t\t\t\t\t\t\t// emit \"fileupload\" event\n\t\t\t\t\t\t\t\t\toptions.fileupload(_file, xhr, _fileOptions);\n\t\t\t\t\t\t\t\t} : noop,\n\n\t\t\t\t\t\t\t\tprogress: _file ? function (evt){\n\t\t\t\t\t\t\t\t\tif( !_fileLoaded ){\n\t\t\t\t\t\t\t\t\t\t// For ignore the double calls.\n\t\t\t\t\t\t\t\t\t\t_fileLoaded = (evt.loaded === evt.total);\n\n\t\t\t\t\t\t\t\t\t\t// emit \"fileprogress\" event\n\t\t\t\t\t\t\t\t\t\toptions.fileprogress({\n\t\t\t\t\t\t\t\t\t\t\t  type:   'progress'\n\t\t\t\t\t\t\t\t\t\t\t, total:  data.total = evt.total\n\t\t\t\t\t\t\t\t\t\t\t, loaded: data.loaded = evt.loaded\n\t\t\t\t\t\t\t\t\t\t}, _file, xhr, _fileOptions);\n\n\t\t\t\t\t\t\t\t\t\t// emit \"progress\" event\n\t\t\t\t\t\t\t\t\t\toptions.progress({\n\t\t\t\t\t\t\t\t\t\t\t  type:   'progress'\n\t\t\t\t\t\t\t\t\t\t\t, total:  _total\n\t\t\t\t\t\t\t\t\t\t\t, loaded: proxyXHR.loaded = (_loaded + data.size * (evt.loaded/evt.total))|0\n\t\t\t\t\t\t\t\t\t\t}, _file, xhr, _fileOptions);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t} : noop,\n\n\t\t\t\t\t\t\t\tcomplete: function (err){\n\t\t\t\t\t\t\t\t\t_each(_xhrPropsExport, function (name){\n\t\t\t\t\t\t\t\t\t\tproxyXHR[name] = xhr[name];\n\t\t\t\t\t\t\t\t\t});\n\n\t\t\t\t\t\t\t\t\tif( _file ){\n\t\t\t\t\t\t\t\t\t\tdata.total = (data.total || data.size);\n\t\t\t\t\t\t\t\t\t\tdata.loaded\t= data.total;\n\n\t\t\t\t\t\t\t\t\t\tif( !err ) {\n\t\t\t\t\t\t\t\t\t\t\t// emulate 100% \"progress\"\n\t\t\t\t\t\t\t\t\t\t\tthis.progress(data);\n\n\t\t\t\t\t\t\t\t\t\t\t// fixed throttle event\n\t\t\t\t\t\t\t\t\t\t\t_fileLoaded = true;\n\n\t\t\t\t\t\t\t\t\t\t\t// bytes loaded\n\t\t\t\t\t\t\t\t\t\t\t_loaded += data.size; // data.size != data.total, it's desirable fix this\n\t\t\t\t\t\t\t\t\t\t\tproxyXHR.loaded = _loaded;\n\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t// emit \"filecomplete\" event\n\t\t\t\t\t\t\t\t\t\toptions.filecomplete(err, xhr, _file, _fileOptions);\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t// upload next file\n\t\t\t\t\t\t\t\t\tsetTimeout(function () {_nextFile.call(_this);}, 0);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t})); // xhr\n\n\n\t\t\t\t\t\t\t// ...\n\t\t\t\t\t\t\tproxyXHR.abort = function (current){\n\t\t\t\t\t\t\t\tif (!current) { dataArray.length = 0; }\n\t\t\t\t\t\t\t\tthis.current = current;\n\t\t\t\t\t\t\t\txhr.abort();\n\t\t\t\t\t\t\t};\n\n\t\t\t\t\t\t\t// Start upload\n\t\t\t\t\t\t\txhr.send(form);\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\tvar successful = proxyXHR.status == 200 || proxyXHR.status == 201 || proxyXHR.status == 204;\n\t\t\t\t\t\toptions.complete(successful ? false : (proxyXHR.statusText || 'error'), proxyXHR, options);\n\t\t\t\t\t\t// Mark done state\n\t\t\t\t\t\t_complete = true;\n\t\t\t\t\t}\n\t\t\t\t};\n\n\n\t\t\t\t// Next tick\n\t\t\t\tsetTimeout(_nextFile, 0);\n\n\n\t\t\t\t// Append more files to the existing request\n\t\t\t\t// first - add them to the queue head/tail\n\t\t\t\tproxyXHR.append = function (files, first) {\n\t\t\t\t\tfiles = api._getFilesDataArray([].concat(files));\n\n\t\t\t\t\t_each(files, function (data) {\n\t\t\t\t\t\t_total += data.size;\n\t\t\t\t\t\tproxyXHR.files.push(data.file);\n\t\t\t\t\t\tif (first) {\n\t\t\t\t\t\t\tdataArray.unshift(data);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tdataArray.push(data);\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\n\t\t\t\t\tproxyXHR.statusText = \"\";\n\n\t\t\t\t\tif( _complete ){\n\t\t\t\t\t\t_nextFile.call(_this);\n\t\t\t\t\t}\n\t\t\t\t};\n\n\n\t\t\t\t// Removes file from queue by file reference and returns it\n\t\t\t\tproxyXHR.remove = function (file) {\n\t\t\t\t    var i = dataArray.length, _file;\n\t\t\t\t    while( i-- ){\n\t\t\t\t\t\tif( dataArray[i].file == file ){\n\t\t\t\t\t\t\t_file = dataArray.splice(i, 1);\n\t\t\t\t\t\t\t_total -= _file.size;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\treturn\t_file;\n\t\t\t\t};\n\n\t\t\t\treturn proxyXHR;\n\t\t\t},\n\n\n\t\t\t_getFilesDataArray: function (data){\n\t\t\t\tvar files = [], oFiles = {};\n\n\t\t\t\tif( isInputFile(data) ){\n\t\t\t\t\tvar tmp = api.getFiles(data);\n\t\t\t\t\toFiles[data.name || 'file'] = data.getAttribute('multiple') !== null ? tmp : tmp[0];\n\t\t\t\t}\n\t\t\t\telse if( _isArray(data) && isInputFile(data[0]) ){\n\t\t\t\t\t_each(data, function (input){\n\t\t\t\t\t\toFiles[input.name || 'file'] = api.getFiles(input);\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\toFiles = data;\n\t\t\t\t}\n\n\t\t\t\t_each(oFiles, function add(file, name){\n\t\t\t\t\tif( _isArray(file) ){\n\t\t\t\t\t\t_each(file, function (file){\n\t\t\t\t\t\t\tadd(file, name);\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t\telse if( file && (file.name || file.image) ){\n\t\t\t\t\t\tfiles.push({\n\t\t\t\t\t\t\t  name: name\n\t\t\t\t\t\t\t, file: file\n\t\t\t\t\t\t\t, size: file.size\n\t\t\t\t\t\t\t, total: file.size\n\t\t\t\t\t\t\t, loaded: 0\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t});\n\n\t\t\t\tif( !files.length ){\n\t\t\t\t\t// Create fake `file` object\n\t\t\t\t\tfiles.push({ file: { name: api.expando } });\n\t\t\t\t}\n\n\t\t\t\treturn\tfiles;\n\t\t\t},\n\n\n\t\t\t_getFormData: function (options, data, fn){\n\t\t\t\tvar\n\t\t\t\t\t  file = data.file\n\t\t\t\t\t, name = data.name\n\t\t\t\t\t, filename = file.name\n\t\t\t\t\t, filetype = file.type\n\t\t\t\t\t, trans = api.support.transform && options.imageTransform\n\t\t\t\t\t, Form = new api.Form\n\t\t\t\t\t, queue = api.queue(function (){ fn(Form); })\n\t\t\t\t\t, isOrignTrans = trans && _isOriginTransform(trans)\n\t\t\t\t\t, postNameConcat = api.postNameConcat\n\t\t\t\t;\n\n\t\t\t\t// Append data\n\t\t\t\t_each(options.data, function add(val, name){\n\t\t\t\t\tif( typeof val == 'object' ){\n\t\t\t\t\t\t_each(val, function (v, i){\n\t\t\t\t\t\t\tadd(v, postNameConcat(name, 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\tForm.append(name, val);\n\t\t\t\t\t}\n\t\t\t\t});\n\n\t\t\t\t(function _addFile(file/**Object*/){\n\t\t\t\t\tif( file.image ){ // This is a FileAPI.Image\n\t\t\t\t\t\tqueue.inc();\n\n\t\t\t\t\t\tfile.toData(function (err, image){\n\t\t\t\t\t\t\t// @todo: error\n\t\t\t\t\t\t\tfilename = filename || (new Date).getTime()+'.png';\n\n\t\t\t\t\t\t\t_addFile(image);\n\t\t\t\t\t\t\tqueue.next();\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t\telse if( api.Image && trans && (/^image/.test(file.type) || _rimgcanvas.test(file.nodeName)) ){\n\t\t\t\t\t\tqueue.inc();\n\n\t\t\t\t\t\tif( isOrignTrans ){\n\t\t\t\t\t\t\t// Convert to array for transform function\n\t\t\t\t\t\t\ttrans = [trans];\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tapi.Image.transform(file, trans, options.imageAutoOrientation, function (err, images){\n\t\t\t\t\t\t\tif( isOrignTrans && !err ){\n\t\t\t\t\t\t\t\tif( !dataURLtoBlob && !api.flashEngine ){\n\t\t\t\t\t\t\t\t\t// Canvas.toBlob or Flash not supported, use multipart\n\t\t\t\t\t\t\t\t\tForm.multipart = true;\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\tForm.append(name, images[0], filename,  trans[0].type || filetype);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse {\n\t\t\t\t\t\t\t\tvar addOrigin = 0;\n\n\t\t\t\t\t\t\t\tif( !err ){\n\t\t\t\t\t\t\t\t\t_each(images, function (image, idx){\n\t\t\t\t\t\t\t\t\t\tif( !dataURLtoBlob && !api.flashEngine ){\n\t\t\t\t\t\t\t\t\t\t\tForm.multipart = true;\n\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\tif( !trans[idx].postName ){\n\t\t\t\t\t\t\t\t\t\t\taddOrigin = 1;\n\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\tForm.append(trans[idx].postName || postNameConcat(name, idx), image, filename, trans[idx].type || filetype);\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\tif( err || options.imageOriginal ){\n\t\t\t\t\t\t\t\t\tForm.append(postNameConcat(name, (addOrigin ? 'original' : null)), file, filename, filetype);\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\tqueue.next();\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t\telse if( filename !== api.expando ){\n\t\t\t\t\t\tForm.append(name, file, filename);\n\t\t\t\t\t}\n\t\t\t\t})(file);\n\n\t\t\t\tqueue.check();\n\t\t\t},\n\n\n\t\t\treset: function (inp, notRemove){\n\t\t\t\tvar parent, clone;\n\n\t\t\t\tif( jQuery ){\n\t\t\t\t\tclone = jQuery(inp).clone(true).insertBefore(inp).val('')[0];\n\t\t\t\t\tif( !notRemove ){\n\t\t\t\t\t\tjQuery(inp).remove();\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tparent  = inp.parentNode;\n\t\t\t\t\tclone   = parent.insertBefore(inp.cloneNode(true), inp);\n\t\t\t\t\tclone.value = '';\n\n\t\t\t\t\tif( !notRemove ){\n\t\t\t\t\t\tparent.removeChild(inp);\n\t\t\t\t\t}\n\n\t\t\t\t\t_each(_elEvents[api.uid(inp)], function (fns, type){\n\t\t\t\t\t\t_each(fns, function (fn){\n\t\t\t\t\t\t\t_off(inp, type, fn);\n\t\t\t\t\t\t\t_on(clone, type, fn);\n\t\t\t\t\t\t});\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\treturn  clone;\n\t\t\t},\n\n\n\t\t\t/**\n\t\t\t * Load remote file\n\t\t\t *\n\t\t\t * @param   {String}    url\n\t\t\t * @param   {Function}  fn\n\t\t\t * @return  {XMLHttpRequest}\n\t\t\t */\n\t\t\tload: function (url, fn){\n\t\t\t\tvar xhr = api.getXHR();\n\t\t\t\tif( xhr ){\n\t\t\t\t\txhr.open('GET', url, true);\n\n\t\t\t\t\tif( xhr.overrideMimeType ){\n\t\t\t\t        xhr.overrideMimeType('text/plain; charset=x-user-defined');\n\t\t\t\t\t}\n\n\t\t\t\t\t_on(xhr, 'progress', function (/**Event*/evt){\n\t\t\t\t\t\t/** @namespace evt.lengthComputable */\n\t\t\t\t\t\tif( evt.lengthComputable ){\n\t\t\t\t\t\t\tfn({ type: evt.type, loaded: evt.loaded, total: evt.total }, xhr);\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\n\t\t\t\t\txhr.onreadystatechange = function(){\n\t\t\t\t\t\tif( xhr.readyState == 4 ){\n\t\t\t\t\t\t\txhr.onreadystatechange = null;\n\t\t\t\t\t\t\tif( xhr.status == 200 ){\n\t\t\t\t\t\t\t\turl = url.split('/');\n\t\t\t\t\t\t\t\t/** @namespace xhr.responseBody */\n\t\t\t\t\t\t\t\tvar file = {\n\t\t\t\t\t\t\t\t      name: url[url.length-1]\n\t\t\t\t\t\t\t\t\t, size: xhr.getResponseHeader('Content-Length')\n\t\t\t\t\t\t\t\t\t, type: xhr.getResponseHeader('Content-Type')\n\t\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\t\tfile.dataURL = 'data:'+file.type+';base64,' + api.encode64(xhr.responseBody || xhr.responseText);\n\t\t\t\t\t\t\t\tfn({ type: 'load', result: file }, xhr);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse {\n\t\t\t\t\t\t\t\tfn({ type: 'error' }, xhr);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t    }\n\t\t\t\t\t};\n\t\t\t\t    xhr.send(null);\n\t\t\t\t} else {\n\t\t\t\t\tfn({ type: 'error' });\n\t\t\t\t}\n\n\t\t\t\treturn  xhr;\n\t\t\t},\n\n\t\t\tencode64: function (str){\n\t\t\t\tvar b64 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=', outStr = '', i = 0;\n\n\t\t\t\tif( typeof str !== 'string' ){\n\t\t\t\t\tstr\t= String(str);\n\t\t\t\t}\n\n\t\t\t\twhile( i < str.length ){\n\t\t\t\t\t//all three \"& 0xff\" added below are there to fix a known bug\n\t\t\t\t\t//with bytes returned by xhr.responseText\n\t\t\t\t\tvar\n\t\t\t\t\t\t  byte1 = str.charCodeAt(i++) & 0xff\n\t\t\t\t\t\t, byte2 = str.charCodeAt(i++) & 0xff\n\t\t\t\t\t\t, byte3 = str.charCodeAt(i++) & 0xff\n\t\t\t\t\t\t, enc1 = byte1 >> 2\n\t\t\t\t\t\t, enc2 = ((byte1 & 3) << 4) | (byte2 >> 4)\n\t\t\t\t\t\t, enc3, enc4\n\t\t\t\t\t;\n\n\t\t\t\t\tif( isNaN(byte2) ){\n\t\t\t\t\t\tenc3 = enc4 = 64;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tenc3 = ((byte2 & 15) << 2) | (byte3 >> 6);\n\t\t\t\t\t\tenc4 = isNaN(byte3) ? 64 : byte3 & 63;\n\t\t\t\t\t}\n\n\t\t\t\t\toutStr += b64.charAt(enc1) + b64.charAt(enc2) + b64.charAt(enc3) + b64.charAt(enc4);\n\t\t\t\t}\n\n\t\t\t\treturn  outStr;\n\t\t\t}\n\n\t\t} // api\n\t;\n\n\n\tfunction _emit(target, fn, name, res, ext){\n\t\tvar evt = {\n\t\t\t  type:\t\tname.type || name\n\t\t\t, target:\ttarget\n\t\t\t, result:\tres\n\t\t};\n\t\t_extend(evt, ext);\n\t\tfn(evt);\n\t}\n\n\n\tfunction _hasSupportReadAs(as){\n\t\treturn\tFileReader && !!FileReader.prototype['readAs'+as];\n\t}\n\n\n\tfunction _readAs(file, fn, as, encoding){\n\t\tif( api.isBlob(file) && _hasSupportReadAs(as) ){\n\t\t\tvar Reader = new FileReader;\n\n\t\t\t// Add event listener\n\t\t\t_on(Reader, _readerEvents, function _fn(evt){\n\t\t\t\tvar type = evt.type;\n\t\t\t\tif( type == 'progress' ){\n\t\t\t\t\t_emit(file, fn, evt, evt.target.result, { loaded: evt.loaded, total: evt.total });\n\t\t\t\t}\n\t\t\t\telse if( type == 'loadend' ){\n\t\t\t\t\t_off(Reader, _readerEvents, _fn);\n\t\t\t\t\tReader = null;\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\t_emit(file, fn, evt, evt.target.result);\n\t\t\t\t}\n\t\t\t});\n\n\n\t\t\ttry {\n\t\t\t\t// ReadAs ...\n\t\t\t\tif( encoding ){\n\t\t\t\t\tReader['readAs'+as](file, encoding);\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tReader['readAs'+as](file);\n\t\t\t\t}\n\t\t\t}\n\t\t\tcatch (err){\n\t\t\t\t_emit(file, fn, 'error', undef, { error: err.toString() });\n\t\t\t}\n\t\t}\n\t\telse {\n\t\t\t_emit(file, fn, 'error', undef, { error: 'filreader_not_support_'+as });\n\t\t}\n\t}\n\n\n\tfunction _isRegularFile(file, callback){\n\t\t// http://stackoverflow.com/questions/8856628/detecting-folders-directories-in-javascript-filelist-objects\n\t\tif( !file.type && (file.size % 4096) === 0 && (file.size <= 102400) ){\n\t\t\tif( FileReader ){\n\t\t\t\ttry {\n\t\t\t\t\tvar Reader = new FileReader();\n\n\t\t\t\t\t_one(Reader, _readerEvents, function (evt){\n\t\t\t\t\t\tvar isFile = evt.type != 'error';\n\t\t\t\t\t\tcallback(isFile);\n\t\t\t\t\t\tif( isFile ){\n\t\t\t\t\t\t\tReader.abort();\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\n\t\t\t\t\tReader.readAsDataURL(file);\n\t\t\t\t} catch( err ){\n\t\t\t\t\tcallback(false);\n\t\t\t\t}\n\t\t\t}\n\t\t\telse {\n\t\t\t\tcallback(null);\n\t\t\t}\n\t\t}\n\t\telse {\n\t\t\tcallback(true);\n\t\t}\n\t}\n\n\n\tfunction _getAsEntry(item){\n\t\tvar entry;\n\t\tif( item.getAsEntry ){ entry = item.getAsEntry(); }\n\t\telse if( item.webkitGetAsEntry ){ entry = item.webkitGetAsEntry(); }\n\t\treturn\tentry;\n\t}\n\n\n\tfunction _readEntryAsFiles(entry, callback){\n\t\tif( !entry ){\n\t\t\t// error\n\t\t\tcallback('invalid entry');\n\t\t}\n\t\telse if( entry.isFile ){\n\t\t\t// Read as file\n\t\t\tentry.file(function(file){\n\t\t\t\t// success\n\t\t\t\tfile.fullPath = entry.fullPath;\n\t\t\t\tcallback(false, [file]);\n\t\t\t}, function (err){\n\t\t\t\t// error\n\t\t\t\tcallback('FileError.code: '+err.code);\n\t\t\t});\n\t\t}\n\t\telse if( entry.isDirectory ){\n\t\t\tvar reader = entry.createReader(), result = [];\n\n\t\t\treader.readEntries(function(entries){\n\t\t\t\t// success\n\t\t\t\tapi.afor(entries, function (next, entry){\n\t\t\t\t\t_readEntryAsFiles(entry, function (err, files){\n\t\t\t\t\t\tif( err ){\n\t\t\t\t\t\t\tapi.log(err);\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse {\n\t\t\t\t\t\t\tresult = result.concat(files);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif( next ){\n\t\t\t\t\t\t\tnext();\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse {\n\t\t\t\t\t\t\tcallback(false, result);\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t});\n\t\t\t}, function (err){\n\t\t\t\t// error\n\t\t\t\tcallback('directory_reader: ' + err);\n\t\t\t});\n\t\t}\n\t\telse {\n\t\t\t_readEntryAsFiles(_getAsEntry(entry), callback);\n\t\t}\n\t}\n\n\n\tfunction _simpleClone(obj){\n\t\tvar copy = {};\n\t\t_each(obj, function (val, key){\n\t\t\tif( val && (typeof val === 'object') && (val.nodeType === void 0) ){\n\t\t\t\tval = _extend({}, val);\n\t\t\t}\n\t\t\tcopy[key] = val;\n\t\t});\n\t\treturn\tcopy;\n\t}\n\n\n\tfunction isInputFile(el){\n\t\treturn\t_rinput.test(el && el.tagName);\n\t}\n\n\n\tfunction _getDataTransfer(evt){\n\t\treturn\t(evt.originalEvent || evt || '').dataTransfer || {};\n\t}\n\n\n\tfunction _isOriginTransform(trans){\n\t\tvar key;\n\t\tfor( key in trans ){\n\t\t\tif( trans.hasOwnProperty(key) ){\n\t\t\t\tif( !(trans[key] instanceof Object || key === 'overlay' || key === 'filter') ){\n\t\t\t\t\treturn\ttrue;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn\tfalse;\n\t}\n\n\n\t// Add default image info reader\n\tapi.addInfoReader(/^image/, function (file/**File*/, callback/**Function*/){\n\t\tif( !file.__dimensions ){\n\t\t\tvar defer = file.__dimensions = api.defer();\n\n\t\t\tapi.readAsImage(file, function (evt){\n\t\t\t\tvar img = evt.target;\n\t\t\t\tdefer.resolve(evt.type == 'load' ? false : 'error', {\n\t\t\t\t\t  width:  img.width\n\t\t\t\t\t, height: img.height\n\t\t\t\t});\n                img.src = api.EMPTY_PNG;\n\t\t\t\timg = null;\n\t\t\t});\n\t\t}\n\n\t\tfile.__dimensions.then(callback);\n\t});\n\n\n\t/**\n\t * Drag'n'Drop special event\n\t *\n\t * @param\t{HTMLElement}\tel\n\t * @param\t{Function}\t\tonHover\n\t * @param\t{Function}\t\tonDrop\n\t */\n\tapi.event.dnd = function (el, onHover, onDrop){\n\t\tvar _id, _type;\n\n\t\tif( !onDrop ){\n\t\t\tonDrop = onHover;\n\t\t\tonHover = api.F;\n\t\t}\n\n\t\tif( FileReader ){\n\t\t\t// Hover\n\t\t\t_on(el, 'dragenter dragleave dragover', onHover.ff = onHover.ff || function (evt){\n\t\t\t\tvar\n\t\t\t\t\t  types = _getDataTransfer(evt).types\n\t\t\t\t\t, i = types && types.length\n\t\t\t\t\t, debounceTrigger = false\n\t\t\t\t;\n\n\t\t\t\twhile( i-- ){\n\t\t\t\t\tif( ~types[i].indexOf('File') ){\n\t\t\t\t\t\tevt[preventDefault]();\n\n\t\t\t\t\t\tif( _type !== evt.type ){\n\t\t\t\t\t\t\t_type = evt.type; // Store current type of event\n\n\t\t\t\t\t\t\tif( _type != 'dragleave' ){\n\t\t\t\t\t\t\t\tonHover.call(evt[currentTarget], true, evt);\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tdebounceTrigger = true;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tbreak; // exit from \"while\"\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif( debounceTrigger ){\n\t\t\t\t\tclearTimeout(_id);\n\t\t\t\t\t_id = setTimeout(function (){\n\t\t\t\t\t\tonHover.call(evt[currentTarget], _type != 'dragleave', evt);\n\t\t\t\t\t}, 50);\n\t\t\t\t}\n\t\t\t});\n\n\n\t\t\t// Drop\n\t\t\t_on(el, 'drop', onDrop.ff = onDrop.ff || function (evt){\n\t\t\t\tevt[preventDefault]();\n\n\t\t\t\t_type = 0;\n\t\t\t\tonHover.call(evt[currentTarget], false, evt);\n\n\t\t\t\tapi.getDropFiles(evt, function (files){\n\t\t\t\t\tonDrop.call(evt[currentTarget], files, evt);\n\t\t\t\t});\n\t\t\t});\n\t\t}\n\t\telse {\n\t\t\tapi.log(\"Drag'n'Drop -- not supported\");\n\t\t}\n\t};\n\n\n\t/**\n\t * Remove drag'n'drop\n\t * @param\t{HTMLElement}\tel\n\t * @param\t{Function}\t\tonHover\n\t * @param\t{Function}\t\tonDrop\n\t */\n\tapi.event.dnd.off = function (el, onHover, onDrop){\n\t\t_off(el, 'dragenter dragleave dragover', onHover.ff);\n\t\t_off(el, 'drop', onDrop.ff);\n\t};\n\n\n\t// Support jQuery\n\tif( jQuery && !jQuery.fn.dnd ){\n\t\tjQuery.fn.dnd = function (onHover, onDrop){\n\t\t\treturn this.each(function (){\n\t\t\t\tapi.event.dnd(this, onHover, onDrop);\n\t\t\t});\n\t\t};\n\n\t\tjQuery.fn.offdnd = function (onHover, onDrop){\n\t\t\treturn this.each(function (){\n\t\t\t\tapi.event.dnd.off(this, onHover, onDrop);\n\t\t\t});\n\t\t};\n\t}\n\n\t// @export\n\twindow.FileAPI  = _extend(api, window.FileAPI);\n\n\n\t// Debug info\n\tapi.log('FileAPI: ' + api.version);\n\tapi.log('protocol: ' + window.location.protocol);\n\tapi.log('doctype: [' + doctype.name + '] ' + doctype.publicId + ' ' + doctype.systemId);\n\n\n\t// @detect 'x-ua-compatible'\n\t_each(document.getElementsByTagName('meta'), function (meta){\n\t\tif( /x-ua-compatible/i.test(meta.getAttribute('http-equiv')) ){\n\t\t\tapi.log('meta.http-equiv: ' + meta.getAttribute('content'));\n\t\t}\n\t});\n\n\n\t// @configuration\n\tif( !api.flashUrl ){ api.flashUrl = api.staticPath + 'FileAPI.flash.swf'; }\n\tif( !api.flashImageUrl ){ api.flashImageUrl = api.staticPath + 'FileAPI.flash.image.swf'; }\n\tif( !api.flashWebcamUrl ){ api.flashWebcamUrl = api.staticPath + 'FileAPI.flash.camera.swf'; }\n})(window, void 0);\n\n/*global window, FileAPI, document */\n\n(function (api, document, undef) {\n\t'use strict';\n\n\tvar\n\t\tmin = Math.min,\n\t\tround = Math.round,\n\t\tgetCanvas = function () { return document.createElement('canvas'); },\n\t\tsupport = false,\n\t\texifOrientation = {\n\t\t\t  8:\t270\n\t\t\t, 3:\t180\n\t\t\t, 6:\t90\n\t\t\t, 7:\t270\n\t\t\t, 4:\t180\n\t\t\t, 5:\t90\n\t\t}\n\t;\n\n\ttry {\n\t\tsupport = getCanvas().toDataURL('image/png').indexOf('data:image/png') > -1;\n\t}\n\tcatch (e){}\n\n\n\tfunction Image(file){\n\t\tif( file instanceof Image ){\n\t\t\tvar img = new Image(file.file);\n\t\t\tapi.extend(img.matrix, file.matrix);\n\t\t\treturn\timg;\n\t\t}\n\t\telse if( !(this instanceof Image) ){\n\t\t\treturn\tnew Image(file);\n\t\t}\n\n\t\tthis.file   = file;\n\t\tthis.size   = file.size || 100;\n\n\t\tthis.matrix\t= {\n\t\t\tsx: 0,\n\t\t\tsy: 0,\n\t\t\tsw: 0,\n\t\t\tsh: 0,\n\t\t\tdx: 0,\n\t\t\tdy: 0,\n\t\t\tdw: 0,\n\t\t\tdh: 0,\n\t\t\tresize: 0, // min, max OR preview\n\t\t\tdeg: 0,\n\t\t\tquality: 1, // jpeg quality\n\t\t\tfilter: 0\n\t\t};\n\t}\n\n\n\tImage.prototype = {\n\t\timage: true,\n\t\tconstructor: Image,\n\n\t\tset: function (attrs){\n\t\t\tapi.extend(this.matrix, attrs);\n\t\t\treturn\tthis;\n\t\t},\n\n\t\tcrop: function (x, y, w, h){\n\t\t\tif( w === undef ){\n\t\t\t\tw\t= x;\n\t\t\t\th\t= y;\n\t\t\t\tx = y = 0;\n\t\t\t}\n\t\t\treturn\tthis.set({ sx: x, sy: y, sw: w, sh: h || w });\n\t\t},\n\n\t\tresize: function (w, h, strategy){\n\t\t\tif( /min|max/.test(h) ){\n\t\t\t\tstrategy = h;\n\t\t\t\th = w;\n\t\t\t}\n\n\t\t\treturn\tthis.set({ dw: w, dh: h || w, resize: strategy });\n\t\t},\n\n\t\tpreview: function (w, h){\n\t\t\treturn\tthis.resize(w, h || w, 'preview');\n\t\t},\n\n\t\trotate: function (deg){\n\t\t\treturn\tthis.set({ deg: deg });\n\t\t},\n\n\t\tfilter: function (filter){\n\t\t\treturn\tthis.set({ filter: filter });\n\t\t},\n\n\t\toverlay: function (images){\n\t\t\treturn\tthis.set({ overlay: images });\n\t\t},\n\n\t\tclone: function (){\n\t\t\treturn\tnew Image(this);\n\t\t},\n\n\t\t_load: function (image, fn){\n\t\t\tvar self = this;\n\n\t\t\tif( /img|video/i.test(image.nodeName) ){\n\t\t\t\tfn.call(self, null, image);\n\t\t\t}\n\t\t\telse {\n\t\t\t\tapi.readAsImage(image, function (evt){\n\t\t\t\t\tfn.call(self, evt.type != 'load', evt.result);\n\t\t\t\t});\n\t\t\t}\n\t\t},\n\n\t\t_apply: function (image, fn){\n\t\t\tvar\n\t\t\t\t  canvas = getCanvas()\n\t\t\t\t, m = this.getMatrix(image)\n\t\t\t\t, ctx = canvas.getContext('2d')\n\t\t\t\t, width = image.videoWidth || image.width\n\t\t\t\t, height = image.videoHeight || image.height\n\t\t\t\t, deg = m.deg\n\t\t\t\t, dw = m.dw\n\t\t\t\t, dh = m.dh\n\t\t\t\t, w = width\n\t\t\t\t, h = height\n\t\t\t\t, filter = m.filter\n\t\t\t\t, copy // canvas copy\n\t\t\t\t, buffer = image\n\t\t\t\t, overlay = m.overlay\n\t\t\t\t, queue = api.queue(function (){ image.src = api.EMPTY_PNG; fn(false, canvas); })\n\t\t\t\t, renderImageToCanvas = api.renderImageToCanvas\n\t\t\t;\n\n\t\t\t// Normalize angle\n\t\t\tdeg = deg - Math.floor(deg/360)*360;\n\n\t\t\t// For `renderImageToCanvas`\n\t\t\timage._type = this.file.type;\n\n\t\t\twhile(m.multipass && min(w/dw, h/dh) > 2 ){\n\t\t\t\tw = (w/2 + 0.5)|0;\n\t\t\t\th = (h/2 + 0.5)|0;\n\n\t\t\t\tcopy = getCanvas();\n\t\t\t\tcopy.width  = w;\n\t\t\t\tcopy.height = h;\n\n\t\t\t\tif( buffer !== image ){\n\t\t\t\t\trenderImageToCanvas(copy, buffer, 0, 0, buffer.width, buffer.height, 0, 0, w, h);\n\t\t\t\t\tbuffer = copy;\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tbuffer = copy;\n\t\t\t\t\trenderImageToCanvas(buffer, image, m.sx, m.sy, m.sw, m.sh, 0, 0, w, h);\n\t\t\t\t\tm.sx = m.sy = m.sw = m.sh = 0;\n\t\t\t\t}\n\t\t\t}\n\n\n\t\t\tcanvas.width  = (deg % 180) ? dh : dw;\n\t\t\tcanvas.height = (deg % 180) ? dw : dh;\n\n\t\t\tcanvas.type = m.type;\n\t\t\tcanvas.quality = m.quality;\n\n\t\t\tctx.rotate(deg * Math.PI / 180);\n\t\t\trenderImageToCanvas(ctx.canvas, buffer\n\t\t\t\t, m.sx, m.sy\n\t\t\t\t, m.sw || buffer.width\n\t\t\t\t, m.sh || buffer.height\n\t\t\t\t, (deg == 180 || deg == 270 ? -dw : 0)\n\t\t\t\t, (deg == 90 || deg == 180 ? -dh : 0)\n\t\t\t\t, dw, dh\n\t\t\t);\n\t\t\tdw = canvas.width;\n\t\t\tdh = canvas.height;\n\n\t\t\t// Apply overlay\n\t\t\toverlay && api.each([].concat(overlay), function (over){\n\t\t\t\tqueue.inc();\n\t\t\t\t// preload\n\t\t\t\tvar img = new window.Image, fn = function (){\n\t\t\t\t\tvar\n\t\t\t\t\t\t  x = over.x|0\n\t\t\t\t\t\t, y = over.y|0\n\t\t\t\t\t\t, w = over.w || img.width\n\t\t\t\t\t\t, h = over.h || img.height\n\t\t\t\t\t\t, rel = over.rel\n\t\t\t\t\t;\n\n\t\t\t\t\t// center  |  right  |  left\n\t\t\t\t\tx = (rel == 1 || rel == 4 || rel == 7) ? (dw - w + x)/2 : (rel == 2 || rel == 5 || rel == 8 ? dw - (w + x) : x);\n\n\t\t\t\t\t// center  |  bottom  |  top\n\t\t\t\t\ty = (rel == 3 || rel == 4 || rel == 5) ? (dh - h + y)/2 : (rel >= 6 ? dh - (h + y) : y);\n\n\t\t\t\t\tapi.event.off(img, 'error load abort', fn);\n\n\t\t\t\t\ttry {\n\t\t\t\t\t\tctx.globalAlpha = over.opacity || 1;\n\t\t\t\t\t\tctx.drawImage(img, x, y, w, h);\n\t\t\t\t\t}\n\t\t\t\t\tcatch (er){}\n\n\t\t\t\t\tqueue.next();\n\t\t\t\t};\n\n\t\t\t\tapi.event.on(img, 'error load abort', fn);\n\t\t\t\timg.src = over.src;\n\n\t\t\t\tif( img.complete ){\n\t\t\t\t\tfn();\n\t\t\t\t}\n\t\t\t});\n\n\t\t\tif( filter ){\n\t\t\t\tqueue.inc();\n\t\t\t\tImage.applyFilter(canvas, filter, queue.next);\n\t\t\t}\n\n\t\t\tqueue.check();\n\t\t},\n\n\t\tgetMatrix: function (image){\n\t\t\tvar\n\t\t\t\t  m  = api.extend({}, this.matrix)\n\t\t\t\t, sw = m.sw = m.sw || image.videoWidth || image.naturalWidth ||  image.width\n\t\t\t\t, sh = m.sh = m.sh || image.videoHeight || image.naturalHeight || image.height\n\t\t\t\t, dw = m.dw = m.dw || sw\n\t\t\t\t, dh = m.dh = m.dh || sh\n\t\t\t\t, sf = sw/sh, df = dw/dh\n\t\t\t\t, strategy = m.resize\n\t\t\t;\n\n\t\t\tif( strategy == 'preview' ){\n\t\t\t\tif( dw != sw || dh != sh ){\n\t\t\t\t\t// Make preview\n\t\t\t\t\tvar w, h;\n\n\t\t\t\t\tif( df >= sf ){\n\t\t\t\t\t\tw\t= sw;\n\t\t\t\t\t\th\t= w / df;\n\t\t\t\t\t} else {\n\t\t\t\t\t\th\t= sh;\n\t\t\t\t\t\tw\t= h * df;\n\t\t\t\t\t}\n\n\t\t\t\t\tif( w != sw || h != sh ){\n\t\t\t\t\t\tm.sx\t= ~~((sw - w)/2);\n\t\t\t\t\t\tm.sy\t= ~~((sh - h)/2);\n\t\t\t\t\t\tsw\t\t= w;\n\t\t\t\t\t\tsh\t\t= h;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\telse if( strategy ){\n\t\t\t\tif( !(sw > dw || sh > dh) ){\n\t\t\t\t\tdw = sw;\n\t\t\t\t\tdh = sh;\n\t\t\t\t}\n\t\t\t\telse if( strategy == 'min' ){\n\t\t\t\t\tdw = round(sf < df ? min(sw, dw) : dh*sf);\n\t\t\t\t\tdh = round(sf < df ? dw/sf : min(sh, dh));\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tdw = round(sf >= df ? min(sw, dw) : dh*sf);\n\t\t\t\t\tdh = round(sf >= df ? dw/sf : min(sh, dh));\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tm.sw = sw;\n\t\t\tm.sh = sh;\n\t\t\tm.dw = dw;\n\t\t\tm.dh = dh;\n\t\t\tm.multipass = api.multiPassResize;\n\t\t\treturn\tm;\n\t\t},\n\n\t\t_trans: function (fn){\n\t\t\tthis._load(this.file, function (err, image){\n\t\t\t\tif( err ){\n\t\t\t\t\tfn(err);\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tthis._apply(image, fn);\n\t\t\t\t\t} catch (err){\n\t\t\t\t\t\tapi.log('[err] FileAPI.Image.fn._apply:', err);\n\t\t\t\t\t\tfn(err);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t},\n\n\n\t\tget: function (fn){\n\t\t\tif( api.support.transform ){\n\t\t\t\tvar _this = this, matrix = _this.matrix;\n\n\t\t\t\tif( matrix.deg == 'auto' ){\n\t\t\t\t\tapi.getInfo(_this.file, function (err, info){\n\t\t\t\t\t\t// rotate by exif orientation\n\t\t\t\t\t\tmatrix.deg = exifOrientation[info && info.exif && info.exif.Orientation] || 0;\n\t\t\t\t\t\t_this._trans(fn);\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\t_this._trans(fn);\n\t\t\t\t}\n\t\t\t}\n\t\t\telse {\n\t\t\t\tfn('not_support_transform');\n\t\t\t}\n\n\t\t\treturn this;\n\t\t},\n\n\n\t\ttoData: function (fn){\n\t\t\treturn this.get(fn);\n\t\t}\n\n\t};\n\n\n\tImage.exifOrientation = exifOrientation;\n\n\n\tImage.transform = function (file, transform, autoOrientation, fn){\n\t\tfunction _transform(err, img){\n\t\t\t// img -- info object\n\t\t\tvar\n\t\t\t\t  images = {}\n\t\t\t\t, queue = api.queue(function (err){\n\t\t\t\t\tfn(err, images);\n\t\t\t\t})\n\t\t\t;\n\n\t\t\tif( !err ){\n\t\t\t\tapi.each(transform, function (params, name){\n\t\t\t\t\tif( !queue.isFail() ){\n\t\t\t\t\t\tvar ImgTrans = new Image(img.nodeType ? img : file), isFn = typeof params == 'function';\n\n\t\t\t\t\t\tif( isFn ){\n\t\t\t\t\t\t\tparams(img, ImgTrans);\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse if( params.width ){\n\t\t\t\t\t\t\tImgTrans[params.preview ? 'preview' : 'resize'](params.width, params.height, params.strategy);\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse {\n\t\t\t\t\t\t\tif( params.maxWidth && (img.width > params.maxWidth || img.height > params.maxHeight) ){\n\t\t\t\t\t\t\t\tImgTrans.resize(params.maxWidth, params.maxHeight, 'max');\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif( params.crop ){\n\t\t\t\t\t\t\tvar crop = params.crop;\n\t\t\t\t\t\t\tImgTrans.crop(crop.x|0, crop.y|0, crop.w || crop.width, crop.h || crop.height);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif( params.rotate === undef && autoOrientation ){\n\t\t\t\t\t\t\tparams.rotate = 'auto';\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tImgTrans.set({ type: ImgTrans.matrix.type || params.type || file.type || 'image/png' });\n\n\t\t\t\t\t\tif( !isFn ){\n\t\t\t\t\t\t\tImgTrans.set({\n\t\t\t\t\t\t\t\t  deg: params.rotate\n\t\t\t\t\t\t\t\t, overlay: params.overlay\n\t\t\t\t\t\t\t\t, filter: params.filter\n\t\t\t\t\t\t\t\t, quality: params.quality || 1\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tqueue.inc();\n\t\t\t\t\t\tImgTrans.toData(function (err, image){\n\t\t\t\t\t\t\tif( err ){\n\t\t\t\t\t\t\t\tqueue.fail();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse {\n\t\t\t\t\t\t\t\timages[name] = image;\n\t\t\t\t\t\t\t\tqueue.next();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t\telse {\n\t\t\t\tqueue.fail();\n\t\t\t}\n\t\t}\n\n\n\t\t// @todo: Оло-ло, нужно рефакторить это место\n\t\tif( file.width ){\n\t\t\t_transform(false, file);\n\t\t} else {\n\t\t\tapi.getInfo(file, _transform);\n\t\t}\n\t};\n\n\n\t// @const\n\tapi.each(['TOP', 'CENTER', 'BOTTOM'], function (x, i){\n\t\tapi.each(['LEFT', 'CENTER', 'RIGHT'], function (y, j){\n\t\t\tImage[x+'_'+y] = i*3 + j;\n\t\t\tImage[y+'_'+x] = i*3 + j;\n\t\t});\n\t});\n\n\n\t/**\n\t * Trabsform element to canvas\n\t *\n\t * @param    {Image|HTMLVideoElement}   el\n\t * @returns  {Canvas}\n\t */\n\tImage.toCanvas = function(el){\n\t\tvar canvas\t\t= document.createElement('canvas');\n\t\tcanvas.width\t= el.videoWidth || el.width;\n\t\tcanvas.height\t= el.videoHeight || el.height;\n\t\tcanvas.getContext('2d').drawImage(el, 0, 0);\n\t\treturn\tcanvas;\n\t};\n\n\n\t/**\n\t * Create image from DataURL\n\t * @param  {String}  dataURL\n\t * @param  {Object}  size\n\t * @param  {Function}  callback\n\t */\n\tImage.fromDataURL = function (dataURL, size, callback){\n\t\tvar img = api.newImage(dataURL);\n\t\tapi.extend(img, size);\n\t\tcallback(img);\n\t};\n\n\n\t/**\n\t * Apply filter (caman.js)\n\t *\n\t * @param  {Canvas|Image}   canvas\n\t * @param  {String|Function}  filter\n\t * @param  {Function}  doneFn\n\t */\n\tImage.applyFilter = function (canvas, filter, doneFn){\n\t\tif( typeof filter == 'function' ){\n\t\t\tfilter(canvas, doneFn);\n\t\t}\n\t\telse if( window.Caman ){\n\t\t\t// http://camanjs.com/guides/\n\t\t\twindow.Caman(canvas.tagName == 'IMG' ? Image.toCanvas(canvas) : canvas, function (){\n\t\t\t\tif( typeof filter == 'string' ){\n\t\t\t\t\tthis[filter]();\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tapi.each(filter, function (val, method){\n\t\t\t\t\t\tthis[method](val);\n\t\t\t\t\t}, this);\n\t\t\t\t}\n\t\t\t\tthis.render(doneFn);\n\t\t\t});\n\t\t}\n\t};\n\n\n\t/**\n\t * For load-image-ios.js\n\t */\n\tapi.renderImageToCanvas = function (canvas, img, sx, sy, sw, sh, dx, dy, dw, dh){\n\t\ttry {\n\t\t\treturn canvas.getContext('2d').drawImage(img, sx, sy, sw, sh, dx, dy, dw, dh);\n\t\t} catch (ex) {\n\t\t\tapi.log('renderImageToCanvas failed');\n\t\t\tthrow ex;\n\t\t}\n\t};\n\n\n\t// @export\n\tapi.support.canvas = api.support.transform = support;\n\tapi.Image = Image;\n})(FileAPI, document);\n\n/*\n * JavaScript Load Image iOS scaling fixes 1.0.3\n * https://github.com/blueimp/JavaScript-Load-Image\n *\n * Copyright 2013, Sebastian Tschan\n * https://blueimp.net\n *\n * iOS image scaling fixes based on\n * https://github.com/stomita/ios-imagefile-megapixel\n *\n * Licensed under the MIT license:\n * http://www.opensource.org/licenses/MIT\n */\n\n/*jslint nomen: true, bitwise: true */\n/*global FileAPI, window, document */\n\n(function (factory) {\n\t'use strict';\n\tfactory(FileAPI);\n}(function (loadImage) {\n    'use strict';\n\n    // Only apply fixes on the iOS platform:\n    if (!window.navigator || !window.navigator.platform ||\n             !(/iP(hone|od|ad)/).test(window.navigator.platform)) {\n        return;\n    }\n\n    var originalRenderMethod = loadImage.renderImageToCanvas;\n\n    // Detects subsampling in JPEG images:\n    loadImage.detectSubsampling = function (img) {\n        var canvas,\n            context;\n        if (img.width * img.height > 1024 * 1024) { // only consider mexapixel images\n            canvas = document.createElement('canvas');\n            canvas.width = canvas.height = 1;\n            context = canvas.getContext('2d');\n            context.drawImage(img, -img.width + 1, 0);\n            // subsampled image becomes half smaller in rendering size.\n            // check alpha channel value to confirm image is covering edge pixel or not.\n            // if alpha value is 0 image is not covering, hence subsampled.\n            return context.getImageData(0, 0, 1, 1).data[3] === 0;\n        }\n        return false;\n    };\n\n    // Detects vertical squash in JPEG images:\n    loadImage.detectVerticalSquash = function (img, subsampled) {\n        var naturalHeight = img.naturalHeight || img.height,\n            canvas = document.createElement('canvas'),\n            context = canvas.getContext('2d'),\n            data,\n            sy,\n            ey,\n            py,\n            alpha;\n        if (subsampled) {\n            naturalHeight /= 2;\n        }\n        canvas.width = 1;\n        canvas.height = naturalHeight;\n        context.drawImage(img, 0, 0);\n        data = context.getImageData(0, 0, 1, naturalHeight).data;\n        // search image edge pixel position in case it is squashed vertically:\n        sy = 0;\n        ey = naturalHeight;\n        py = naturalHeight;\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        return (py / naturalHeight) || 1;\n    };\n\n    // Renders image to canvas while working around iOS image scaling bugs:\n    // https://github.com/blueimp/JavaScript-Load-Image/issues/13\n    loadImage.renderImageToCanvas = function (\n        canvas,\n        img,\n        sourceX,\n        sourceY,\n        sourceWidth,\n        sourceHeight,\n        destX,\n        destY,\n        destWidth,\n        destHeight\n    ) {\n        if (img._type === 'image/jpeg') {\n            var context = canvas.getContext('2d'),\n                tmpCanvas = document.createElement('canvas'),\n                tileSize = 1024,\n                tmpContext = tmpCanvas.getContext('2d'),\n                subsampled,\n                vertSquashRatio,\n                tileX,\n                tileY;\n            tmpCanvas.width = tileSize;\n            tmpCanvas.height = tileSize;\n            context.save();\n            subsampled = loadImage.detectSubsampling(img);\n            if (subsampled) {\n                sourceX /= 2;\n                sourceY /= 2;\n                sourceWidth /= 2;\n                sourceHeight /= 2;\n            }\n            vertSquashRatio = loadImage.detectVerticalSquash(img, subsampled);\n            if (subsampled || vertSquashRatio !== 1) {\n                sourceY *= vertSquashRatio;\n                destWidth = Math.ceil(tileSize * destWidth / sourceWidth);\n                destHeight = Math.ceil(\n                    tileSize * destHeight / sourceHeight / vertSquashRatio\n                );\n                destY = 0;\n                tileY = 0;\n                while (tileY < sourceHeight) {\n                    destX = 0;\n                    tileX = 0;\n                    while (tileX < sourceWidth) {\n                        tmpContext.clearRect(0, 0, tileSize, tileSize);\n                        tmpContext.drawImage(\n                            img,\n                            sourceX,\n                            sourceY,\n                            sourceWidth,\n                            sourceHeight,\n                            -tileX,\n                            -tileY,\n                            sourceWidth,\n                            sourceHeight\n                        );\n                        context.drawImage(\n                            tmpCanvas,\n                            0,\n                            0,\n                            tileSize,\n                            tileSize,\n                            destX,\n                            destY,\n                            destWidth,\n                            destHeight\n                        );\n                        tileX += tileSize;\n                        destX += destWidth;\n                    }\n                    tileY += tileSize;\n                    destY += destHeight;\n                }\n                context.restore();\n                return canvas;\n            }\n        }\n        return originalRenderMethod(\n            canvas,\n            img,\n            sourceX,\n            sourceY,\n            sourceWidth,\n            sourceHeight,\n            destX,\n            destY,\n            destWidth,\n            destHeight\n        );\n    };\n\n}));\n\n/*global window, FileAPI */\n\n(function (api, window){\n\t\"use strict\";\n\n\tvar\n\t\t  document = window.document\n\t\t, FormData = window.FormData\n\t\t, Form = function (){ this.items = []; }\n\t\t, encodeURIComponent = window.encodeURIComponent\n\t;\n\n\n\tForm.prototype = {\n\n\t\tappend: function (name, blob, file, type){\n\t\t\tthis.items.push({\n\t\t\t\t  name: name\n\t\t\t\t, blob: blob && blob.blob || (blob == void 0 ? '' : blob)\n\t\t\t\t, file: blob && (file || blob.name)\n\t\t\t\t, type:\tblob && (type || blob.type)\n\t\t\t});\n\t\t},\n\n\t\teach: function (fn){\n\t\t\tvar i = 0, n = this.items.length;\n\t\t\tfor( ; i < n; i++ ){\n\t\t\t\tfn.call(this, this.items[i]);\n\t\t\t}\n\t\t},\n\n\t\ttoData: function (fn, options){\n\t\t    // allow chunked transfer if we have only one file to send\n\t\t    // flag is used below and in XHR._send\n\t\t    options._chunked = api.support.chunked && options.chunkSize > 0 && api.filter(this.items, function (item){ return item.file; }).length == 1;\n\n\t\t\tif( !api.support.html5 ){\n\t\t\t\tapi.log('FileAPI.Form.toHtmlData');\n\t\t\t\tthis.toHtmlData(fn);\n\t\t\t}\n\t\t\telse if( !api.formData || this.multipart || !FormData ){\n\t\t\t\tapi.log('FileAPI.Form.toMultipartData');\n\t\t\t\tthis.toMultipartData(fn);\n\t\t\t}\n\t\t\telse if( options._chunked ){\n\t\t\t\tapi.log('FileAPI.Form.toPlainData');\n\t\t\t\tthis.toPlainData(fn);\n\t\t\t}\n\t\t\telse {\n\t\t\t\tapi.log('FileAPI.Form.toFormData');\n\t\t\t\tthis.toFormData(fn);\n\t\t\t}\n\t\t},\n\n\t\t_to: function (data, complete, next, arg){\n\t\t\tvar queue = api.queue(function (){\n\t\t\t\tcomplete(data);\n\t\t\t});\n\n\t\t\tthis.each(function (file){\n\t\t\t\tnext(file, data, queue, arg);\n\t\t\t});\n\n\t\t\tqueue.check();\n\t\t},\n\n\n\t\ttoHtmlData: function (fn){\n\t\t\tthis._to(document.createDocumentFragment(), fn, function (file, data/**DocumentFragment*/){\n\t\t\t\tvar blob = file.blob, hidden;\n\n\t\t\t\tif( file.file ){\n\t\t\t\t\tapi.reset(blob, true);\n\t\t\t\t\t// set new name\n\t\t\t\t\tblob.name = file.name;\n\t\t\t\t\tblob.disabled = false;\n\t\t\t\t\tdata.appendChild(blob);\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\thidden = document.createElement('input');\n\t\t\t\t\thidden.name  = file.name;\n\t\t\t\t\thidden.type  = 'hidden';\n\t\t\t\t\thidden.value = blob;\n\t\t\t\t\tdata.appendChild(hidden);\n\t\t\t\t}\n\t\t\t});\n\t\t},\n\n\t\ttoPlainData: function (fn){\n\t\t\tthis._to({}, fn, function (file, data, queue){\n\t\t\t\tif( file.file ){\n\t\t\t\t\tdata.type = file.file;\n\t\t\t\t}\n\n\t\t\t\tif( file.blob.toBlob ){\n\t\t\t\t    // canvas\n\t\t\t\t\tqueue.inc();\n\t\t\t\t\t_convertFile(file, function (file, blob){\n\t\t\t\t\t\tdata.name = file.name;\n\t\t\t\t\t\tdata.file = blob;\n\t\t\t\t\t\tdata.size = blob.length;\n\t\t\t\t\t\tdata.type = file.type;\n\t\t\t\t\t\tqueue.next();\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\telse if( file.file ){\n\t\t\t\t    // file\n\t\t\t\t\tdata.name = file.blob.name;\n\t\t\t\t\tdata.file = file.blob;\n\t\t\t\t\tdata.size = file.blob.size;\n\t\t\t\t\tdata.type = file.type;\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t    // additional data\n\t\t\t\t    if( !data.params ){\n\t\t\t\t        data.params = [];\n\t\t\t\t    }\n\t\t\t\t    data.params.push(encodeURIComponent(file.name) +\"=\"+ encodeURIComponent(file.blob));\n\t\t\t\t}\n\n\t\t\t\tdata.start = -1;\n\t\t\t\tdata.end = data.file && data.file.FileAPIReadPosition || -1;\n\t\t\t\tdata.retry = 0;\n\t\t\t});\n\t\t},\n\n\t\ttoFormData: function (fn){\n\t\t\tthis._to(new FormData, fn, function (file, data, queue){\n\t\t\t\tif( file.blob && file.blob.toBlob ){\n\t\t\t\t\tqueue.inc();\n\t\t\t\t\t_convertFile(file, function (file, blob){\n\t\t\t\t\t\tdata.append(file.name, blob, file.file);\n\t\t\t\t\t\tqueue.next();\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\telse if( file.file ){\n\t\t\t\t\tdata.append(file.name, file.blob, file.file);\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tdata.append(file.name, file.blob);\n\t\t\t\t}\n\n\t\t\t\tif( file.file ){\n\t\t\t\t\tdata.append('_'+file.name, file.file);\n\t\t\t\t}\n\t\t\t});\n\t\t},\n\n\n\t\ttoMultipartData: function (fn){\n\t\t\tthis._to([], fn, function (file, data, queue, boundary){\n\t\t\t\tqueue.inc();\n\t\t\t\t_convertFile(file, function (file, blob){\n\t\t\t\t\tdata.push(\n\t\t\t\t\t\t  '--_' + boundary + ('\\r\\nContent-Disposition: form-data; name=\"'+ file.name +'\"'+ (file.file ? '; filename=\"'+ encodeURIComponent(file.file) +'\"' : '')\n\t\t\t\t\t\t+ (file.file ? '\\r\\nContent-Type: '+ (file.type || 'application/octet-stream') : '')\n\t\t\t\t\t\t+ '\\r\\n'\n\t\t\t\t\t\t+ '\\r\\n'+ (file.file ? blob : encodeURIComponent(blob))\n\t\t\t\t\t\t+ '\\r\\n')\n\t\t\t\t\t);\n\t\t\t\t\tqueue.next();\n\t\t\t\t}, true);\n\t\t\t}, api.expando);\n\t\t}\n\t};\n\n\n\tfunction _convertFile(file, fn, useBinaryString){\n\t\tvar blob = file.blob, filename = file.file;\n\n\t\tif( filename ){\n\t\t\tif( !blob.toDataURL ){\n\t\t\t\t// The Blob is not an image.\n\t\t\t\tapi.readAsBinaryString(blob, function (evt){\n\t\t\t\t\tif( evt.type == 'load' ){\n\t\t\t\t\t\tfn(file, evt.result);\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tvar\n\t\t\t\t  mime = { 'image/jpeg': '.jpe?g', 'image/png': '.png' }\n\t\t\t\t, type = mime[file.type] ? file.type : 'image/png'\n\t\t\t\t, ext  = mime[type] || '.png'\n\t\t\t\t, quality = blob.quality || 1\n\t\t\t;\n\n\t\t\tif( !filename.match(new RegExp(ext+'$', 'i')) ){\n\t\t\t\t// Does not change the current extension, but add a new one.\n\t\t\t\tfilename += ext.replace('?', '');\n\t\t\t}\n\n\t\t\tfile.file = filename;\n\t\t\tfile.type = type;\n\n\t\t\tif( !useBinaryString && blob.toBlob ){\n\t\t\t\tblob.toBlob(function (blob){\n\t\t\t\t\tfn(file, blob);\n\t\t\t\t}, type, quality);\n\t\t\t}\n\t\t\telse {\n\t\t\t\tfn(file, api.toBinaryString(blob.toDataURL(type, quality)));\n\t\t\t}\n\t\t}\n\t\telse {\n\t\t\tfn(file, blob);\n\t\t}\n\t}\n\n\n\t// @export\n\tapi.Form = Form;\n})(FileAPI, window);\n\n/*global window, FileAPI, Uint8Array */\n\n(function (window, api){\n\t\"use strict\";\n\n\tvar\n\t\t  noop = function (){}\n\t\t, document = window.document\n\n\t\t, XHR = function (options){\n\t\t\tthis.uid = api.uid();\n\t\t\tthis.xhr = {\n\t\t\t\t  abort: noop\n\t\t\t\t, getResponseHeader: noop\n\t\t\t\t, getAllResponseHeaders: noop\n\t\t\t};\n\t\t\tthis.options = options;\n\t\t},\n\n\t\t_xhrResponsePostfix = { '': 1, XML: 1, Text: 1, Body: 1 }\n\t;\n\n\n\tXHR.prototype = {\n\t\tstatus: 0,\n\t\tstatusText: '',\n\t\tconstructor: XHR,\n\n\t\tgetResponseHeader: function (name){\n\t\t\treturn this.xhr.getResponseHeader(name);\n\t\t},\n\n\t\tgetAllResponseHeaders: function (){\n\t\t\treturn this.xhr.getAllResponseHeaders() || {};\n\t\t},\n\n\t\tend: function (status, statusText){\n\t\t\tvar _this = this, options = _this.options;\n\n\t\t\t_this.end\t\t=\n\t\t\t_this.abort\t\t= noop;\n\t\t\t_this.status\t= status;\n\n\t\t\tif( statusText ){\n\t\t\t\t_this.statusText = statusText;\n\t\t\t}\n\n\t\t\tapi.log('xhr.end:', status, statusText);\n\t\t\toptions.complete(status == 200 || status == 201 ? false : _this.statusText || 'unknown', _this);\n\n\t\t\tif( _this.xhr && _this.xhr.node ){\n\t\t\t\tsetTimeout(function (){\n\t\t\t\t\tvar node = _this.xhr.node;\n\t\t\t\t\ttry { node.parentNode.removeChild(node); } catch (e){}\n\t\t\t\t\ttry { delete window[_this.uid]; } catch (e){}\n\t\t\t\t\twindow[_this.uid] = _this.xhr.node = null;\n\t\t\t\t}, 9);\n\t\t\t}\n\t\t},\n\n\t\tabort: function (){\n\t\t\tthis.end(0, 'abort');\n\n\t\t\tif( this.xhr ){\n\t\t\t\tthis.xhr.aborted = true;\n\t\t\t\tthis.xhr.abort();\n\t\t\t}\n\t\t},\n\n\t\tsend: function (FormData){\n\t\t\tvar _this = this, options = this.options;\n\n\t\t\tFormData.toData(function (data){\n\t\t\t\t// Start uploading\n\t\t\t\toptions.upload(options, _this);\n\t\t\t\t_this._send.call(_this, options, data);\n\t\t\t}, options);\n\t\t},\n\n\t\t_send: function (options, data){\n\t\t\tvar _this = this, xhr, uid = _this.uid, onloadFuncName = _this.uid + \"Load\", url = options.url;\n\n\t\t\tapi.log('XHR._send:', data);\n\n\t\t\tif( !options.cache ){\n\t\t\t\t// No cache\n\t\t\t\turl += (~url.indexOf('?') ? '&' : '?') + api.uid();\n\t\t\t}\n\n\t\t\tif( data.nodeName ){\n\t\t\t\tvar jsonp = options.jsonp;\n\n\t\t\t\t// prepare callback in GET\n\t\t\t\turl = url.replace(/([a-z]+)=(\\?)/i, '$1='+uid);\n\n\t\t\t\t// legacy\n\t\t\t\toptions.upload(options, _this);\n\n\t\t\t\tvar\n\t\t\t\t\tonPostMessage = function (evt){\n\t\t\t\t\t\tif( ~url.indexOf(evt.origin) ){\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\tvar result = api.parseJSON(evt.data);\n\t\t\t\t\t\t\t\tif( result.id == uid ){\n\t\t\t\t\t\t\t\t\tcomplete(result.status, result.statusText, result.response);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} catch( err ){\n\t\t\t\t\t\t\t\tcomplete(0, err.message);\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// jsonp-callack\n\t\t\t\t\tcomplete = window[uid] = function (status, statusText, response){\n\t\t\t\t\t\t_this.readyState\t= 4;\n\t\t\t\t\t\t_this.responseText\t= response;\n\t\t\t\t\t\t_this.end(status, statusText);\n\n\t\t\t\t\t\tapi.event.off(window, 'message', onPostMessage);\n\t\t\t\t\t\twindow[uid] = xhr = transport = window[onloadFuncName] = null;\n\t\t\t\t\t}\n\t\t\t\t;\n\n\t\t\t\t_this.xhr.abort = function (){\n\t\t\t\t\ttry {\n\t\t\t\t\t\tif( transport.stop ){ transport.stop(); }\n\t\t\t\t\t\telse if( transport.contentWindow.stop ){ transport.contentWindow.stop(); }\n\t\t\t\t\t\telse { transport.contentWindow.document.execCommand('Stop'); }\n\t\t\t\t\t}\n\t\t\t\t\tcatch (er) {}\n\t\t\t\t\tcomplete(0, \"abort\");\n\t\t\t\t};\n\n\t\t\t\tapi.event.on(window, 'message', onPostMessage);\n\n\t\t\t\twindow[onloadFuncName] = function (){\n\t\t\t\t\ttry {\n\t\t\t\t\t\tvar\n\t\t\t\t\t\t\t  win = transport.contentWindow\n\t\t\t\t\t\t\t, doc = win.document\n\t\t\t\t\t\t\t, result = win.result || api.parseJSON(doc.body.innerHTML)\n\t\t\t\t\t\t;\n\t\t\t\t\t\tcomplete(result.status, result.statusText, result.response);\n\t\t\t\t\t} catch (e){\n\t\t\t\t\t\tapi.log('[transport.onload]', e);\n\t\t\t\t\t}\n\t\t\t\t};\n\n\t\t\t\txhr = document.createElement('div');\n\t\t\t\txhr.innerHTML = '<form target=\"'+ uid +'\" action=\"'+ url +'\" method=\"POST\" enctype=\"multipart/form-data\" style=\"position: absolute; top: -1000px; overflow: hidden; width: 1px; height: 1px;\">'\n\t\t\t\t\t\t\t+ '<iframe name=\"'+ uid +'\" src=\"javascript:false;\" onload=\"' + onloadFuncName + '()\"></iframe>'\n\t\t\t\t\t\t\t+ (jsonp && (options.url.indexOf('=?') < 0) ? '<input value=\"'+ uid +'\" name=\"'+jsonp+'\" type=\"hidden\"/>' : '')\n\t\t\t\t\t\t\t+ '</form>'\n\t\t\t\t;\n\n\t\t\t\t// get form-data & transport\n\t\t\t\tvar\n\t\t\t\t\t  form = xhr.getElementsByTagName('form')[0]\n\t\t\t\t\t, transport = xhr.getElementsByTagName('iframe')[0]\n\t\t\t\t;\n\n\t\t\t\tform.appendChild(data);\n\n\t\t\t\tapi.log(form.parentNode.innerHTML);\n\n\t\t\t\t// append to DOM\n\t\t\t\tdocument.body.appendChild(xhr);\n\n\t\t\t\t// keep a reference to node-transport\n\t\t\t\t_this.xhr.node = xhr;\n\n\t\t\t\t// send\n\t\t\t\t_this.readyState = 2; // loaded\n\t\t\t\tform.submit();\n\t\t\t\tform = null;\n\t\t\t}\n\t\t\telse {\n\t\t\t\t// Clean url\n\t\t\t\turl = url.replace(/([a-z]+)=(\\?)&?/i, '');\n\n\t\t\t\t// html5\n\t\t\t\tif (this.xhr && this.xhr.aborted) {\n\t\t\t\t\tapi.log(\"Error: already aborted\");\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\txhr = _this.xhr = api.getXHR();\n\n\t\t\t\tif (data.params) {\n\t\t\t\t\turl += (url.indexOf('?') < 0 ? \"?\" : \"&\") + data.params.join(\"&\");\n\t\t\t\t}\n\n\t\t\t\txhr.open('POST', url, true);\n\n\t\t\t\tif( api.withCredentials ){\n\t\t\t\t\txhr.withCredentials = \"true\";\n\t\t\t\t}\n\n\t\t\t\tif( !options.headers || !options.headers['X-Requested-With'] ){\n\t\t\t\t\txhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');\n\t\t\t\t}\n\n\t\t\t\tapi.each(options.headers, function (val, key){\n\t\t\t\t\txhr.setRequestHeader(key, val);\n\t\t\t\t});\n\n\n\t\t\t\tif ( options._chunked ) {\n\t\t\t\t\t// chunked upload\n\t\t\t\t\tif( xhr.upload ){\n\t\t\t\t\t\txhr.upload.addEventListener('progress', api.throttle(function (/**Event*/evt){\n\t\t\t\t\t\t\tif (!data.retry) {\n\t\t\t\t\t\t\t\t// show progress only for correct chunk uploads\n\t\t\t\t\t\t\t\toptions.progress({\n\t\t\t\t\t\t\t\t\t  type:\t\t\tevt.type\n\t\t\t\t\t\t\t\t\t, total:\t\tdata.size\n\t\t\t\t\t\t\t\t\t, loaded:\t\tdata.start + evt.loaded\n\t\t\t\t\t\t\t\t\t, totalSize:\tdata.size\n\t\t\t\t\t\t\t\t}, _this, options);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}, 100), false);\n\t\t\t\t\t}\n\n\t\t\t\t\txhr.onreadystatechange = function (){\n\t\t\t\t\t\tvar lkb = parseInt(xhr.getResponseHeader('X-Last-Known-Byte'), 10);\n\n\t\t\t\t\t\t_this.status     = xhr.status;\n\t\t\t\t\t\t_this.statusText = xhr.statusText;\n\t\t\t\t\t\t_this.readyState = xhr.readyState;\n\n\t\t\t\t\t\tif( xhr.readyState == 4 ){\n\t\t\t\t\t\t\tfor( var k in _xhrResponsePostfix ){\n\t\t\t\t\t\t\t\t_this['response'+k]  = xhr['response'+k];\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\txhr.onreadystatechange = null;\n\n\t\t\t\t\t\t\tif (!xhr.status || xhr.status - 201 > 0) {\n\t\t\t\t\t\t\t\tapi.log(\"Error: \" + xhr.status);\n\t\t\t\t\t\t\t\t// some kind of error\n\t\t\t\t\t\t\t\t// 0 - connection fail or timeout, if xhr.aborted is true, then it's not recoverable user action\n\t\t\t\t\t\t\t\t// up - server error\n\t\t\t\t\t\t\t\tif (((!xhr.status && !xhr.aborted) || 500 == xhr.status || 416 == xhr.status) && ++data.retry <= options.chunkUploadRetry) {\n\t\t\t\t\t\t\t\t\t// let's try again the same chunk\n\t\t\t\t\t\t\t\t\t// only applicable for recoverable error codes 500 && 416\n\t\t\t\t\t\t\t\t\tvar delay = xhr.status ? 0 : api.chunkNetworkDownRetryTimeout;\n\n\t\t\t\t\t\t\t\t\t// inform about recoverable problems\n\t\t\t\t\t\t\t\t\toptions.pause(data.file, options);\n\n\t\t\t\t\t\t\t\t\t// smart restart if server reports about the last known byte\n\t\t\t\t\t\t\t\t\tapi.log(\"X-Last-Known-Byte: \" + lkb);\n\t\t\t\t\t\t\t\t\tif (lkb) {\n\t\t\t\t\t\t\t\t\t\tdata.end = lkb;\n\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\tdata.end = data.start - 1;\n\t\t\t\t\t\t\t\t\t\tif (416 == xhr.status) {\n\t\t\t\t\t\t\t\t\t\t\tdata.end = data.end - options.chunkSize;\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\tsetTimeout(function () {\n\t\t\t\t\t\t\t\t\t\t_this._send(options, data);\n\t\t\t\t\t\t\t\t\t}, delay);\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t// no mo retries\n\t\t\t\t\t\t\t\t\t_this.end(xhr.status);\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\t// success\n\t\t\t\t\t\t\t\tdata.retry = 0;\n\n\t\t\t\t\t\t\t\tif (data.end == data.size - 1) {\n\t\t\t\t\t\t\t\t\t// finished\n\t\t\t\t\t\t\t\t\t_this.end(xhr.status);\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t// next chunk\n\n\t\t\t\t\t\t\t\t\t// shift position if server reports about the last known byte\n\t\t\t\t\t\t\t\t\tapi.log(\"X-Last-Known-Byte: \" + lkb);\n\t\t\t\t\t\t\t\t\tif (lkb) {\n\t\t\t\t\t\t\t\t\t\tdata.end = lkb;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tdata.file.FileAPIReadPosition = data.end;\n\n\t\t\t\t\t\t\t\t\tsetTimeout(function () {\n\t\t\t\t\t\t\t\t\t\t_this._send(options, data);\n\t\t\t\t\t\t\t\t\t}, 0);\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\txhr = null;\n\t\t\t\t\t\t}\n\t\t\t\t\t};\n\n\t\t\t\t\tdata.start = data.end + 1;\n\t\t\t\t\tdata.end = Math.max(Math.min(data.start + options.chunkSize, data.size) - 1, data.start);\n\n\t\t\t\t\t// Retrieve a slice of file\n\t\t\t\t\tvar\n\t\t\t\t\t\t  file = data.file\n\t\t\t\t\t\t, slice = (file.slice || file.mozSlice || file.webkitSlice).call(file, data.start, data.end + 1)\n\t\t\t\t\t;\n\n\t\t\t\t\tif( data.size && !slice.size ){\n\t\t\t\t\t\tsetTimeout(function (){\n\t\t\t\t\t\t\t_this.end(-1);\n\t\t\t\t\t\t});\n\t\t\t\t\t} else {\n\t\t\t\t\t\txhr.setRequestHeader(\"Content-Range\", \"bytes \" + data.start + \"-\" + data.end + \"/\" + data.size);\n\t\t\t\t\t\txhr.setRequestHeader(\"Content-Disposition\", 'attachment; filename=' + encodeURIComponent(data.name));\n\t\t\t\t\t\txhr.setRequestHeader(\"Content-Type\", data.type || \"application/octet-stream\");\n\n\t\t\t\t\t\txhr.send(slice);\n\t\t\t\t\t}\n\n\t\t\t\t\tfile = slice = null;\n\t\t\t\t} else {\n\t\t\t\t\t// single piece upload\n\t\t\t\t\tif( xhr.upload ){\n\t\t\t\t\t\t// https://github.com/blueimp/jQuery-File-Upload/wiki/Fixing-Safari-hanging-on-very-high-speed-connections-%281Gbps%29\n\t\t\t\t\t\txhr.upload.addEventListener('progress', api.throttle(function (/**Event*/evt){\n\t\t\t\t\t\t\toptions.progress(evt, _this, options);\n\t\t\t\t\t\t}, 100), false);\n\t\t\t\t\t}\n\n\t\t\t\t\txhr.onreadystatechange = function (){\n\t\t\t\t\t\t_this.status     = xhr.status;\n\t\t\t\t\t\t_this.statusText = xhr.statusText;\n\t\t\t\t\t\t_this.readyState = xhr.readyState;\n\n\t\t\t\t\t\tif( xhr.readyState == 4 ){\n\t\t\t\t\t\t\tfor( var k in _xhrResponsePostfix ){\n\t\t\t\t\t\t\t\t_this['response'+k]  = xhr['response'+k];\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\txhr.onreadystatechange = null;\n\n\t\t\t\t\t\t\tif (!xhr.status || xhr.status > 201) {\n\t\t\t\t\t\t\t\tapi.log(\"Error: \" + xhr.status);\n\t\t\t\t\t\t\t\tif (((!xhr.status && !xhr.aborted) || 500 == xhr.status) && (options.retry || 0) < options.uploadRetry) {\n\t\t\t\t\t\t\t\t\toptions.retry = (options.retry || 0) + 1;\n\t\t\t\t\t\t\t\t\tvar delay = api.networkDownRetryTimeout;\n\n\t\t\t\t\t\t\t\t\t// inform about recoverable problems\n\t\t\t\t\t\t\t\t\toptions.pause(options.file, options);\n\n\t\t\t\t\t\t\t\t\tsetTimeout(function () {\n\t\t\t\t\t\t\t\t\t\t_this._send(options, data);\n\t\t\t\t\t\t\t\t\t}, delay);\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t//success\n\t\t\t\t\t\t\t\t\t_this.end(xhr.status);\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\t//success\n\t\t\t\t\t\t\t\t_this.end(xhr.status);\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\txhr = null;\n\t\t\t\t\t\t}\n\t\t\t\t\t};\n\n\t\t\t\t\tif( api.isArray(data) ){\n\t\t\t\t\t\t// multipart\n\t\t\t\t\t\txhr.setRequestHeader('Content-Type', 'multipart/form-data; boundary=_'+api.expando);\n\t\t\t\t\t\tvar rawData = data.join('') +'--_'+ api.expando +'--';\n\n\t\t\t\t\t\t/** @namespace  xhr.sendAsBinary  https://developer.mozilla.org/ru/XMLHttpRequest#Sending_binary_content */\n\t\t\t\t\t\tif( xhr.sendAsBinary ){\n\t\t\t\t\t\t\txhr.sendAsBinary(rawData);\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse {\n\t\t\t\t\t\t\tvar bytes = Array.prototype.map.call(rawData, function(c){ return c.charCodeAt(0) & 0xff; });\n\t\t\t\t\t\t\txhr.send(new Uint8Array(bytes).buffer);\n\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// FormData\n\t\t\t\t\t\txhr.send(data);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t};\n\n\n\t// @export\n\tapi.XHR = XHR;\n})(window, FileAPI);\n\n/**\n * @class\tFileAPI.Camera\n * @author\tRubaXa\t<trash@rubaxa.org>\n * @support\tChrome 21+, FF 18+, Opera 12+\n */\n\n/*global window, FileAPI, jQuery */\n/** @namespace LocalMediaStream -- https://developer.mozilla.org/en-US/docs/WebRTC/MediaStream_API#LocalMediaStream */\n(function (window, api){\n\t\"use strict\";\n\n\tvar\n\t\tURL = window.URL || window.webkitURL,\n\n\t\tdocument = window.document,\n\t\tnavigator = window.navigator,\n\n\t\tgetMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia,\n\n\t\thtml5 = !!getMedia\n\t;\n\n\n\t// Support \"media\"\n\tapi.support.media = html5;\n\n\n\tvar Camera = function (video){\n\t\tthis.video = video;\n\t};\n\n\n\tCamera.prototype = {\n\t\tisActive: function (){\n\t\t\treturn\t!!this._active;\n\t\t},\n\n\n\t\t/**\n\t\t * Start camera streaming\n\t\t * @param\t{Function}\tcallback\n\t\t */\n\t\tstart: function (callback){\n\t\t\tvar\n\t\t\t\t  _this = this\n\t\t\t\t, video = _this.video\n\t\t\t\t, _successId\n\t\t\t\t, _failId\n\t\t\t\t, _complete = function (err){\n\t\t\t\t\t_this._active = !err;\n\t\t\t\t\tclearTimeout(_failId);\n\t\t\t\t\tclearTimeout(_successId);\n//\t\t\t\t\tapi.event.off(video, 'loadedmetadata', _complete);\n\t\t\t\t\tcallback && callback(err, _this);\n\t\t\t\t}\n\t\t\t;\n\n\t\t\tgetMedia.call(navigator, { video: true }, function (stream/**LocalMediaStream*/){\n\t\t\t\t// Success\n\t\t\t\t_this.stream = stream;\n\n//\t\t\t\tapi.event.on(video, 'loadedmetadata', function (){\n//\t\t\t\t\t_complete(null);\n//\t\t\t\t});\n\n\t\t\t\t// Set camera stream\n\t\t\t\tvideo.src = URL.createObjectURL(stream);\n\n\t\t\t\t// Note: onloadedmetadata doesn't fire in Chrome when using it with getUserMedia.\n\t\t\t\t// See crbug.com/110938.\n\t\t\t\t_successId = setInterval(function (){\n\t\t\t\t\tif( _detectVideoSignal(video) ){\n\t\t\t\t\t\t_complete(null);\n\t\t\t\t\t}\n\t\t\t\t}, 1000);\n\n\t\t\t\t_failId = setTimeout(function (){\n\t\t\t\t\t_complete('timeout');\n\t\t\t\t}, 5000);\n\n\t\t\t\t// Go-go-go!\n\t\t\t\tvideo.play();\n\t\t\t}, _complete/*error*/);\n\t\t},\n\n\n\t\t/**\n\t\t * Stop camera streaming\n\t\t */\n\t\tstop: function (){\n\t\t\ttry {\n\t\t\t\tthis._active = false;\n\t\t\t\tthis.video.pause();\n\t\t\t\tthis.stream.stop();\n\t\t\t} catch( err ){ }\n\t\t},\n\n\n\t\t/**\n\t\t * Create screenshot\n\t\t * @return {FileAPI.Camera.Shot}\n\t\t */\n\t\tshot: function (){\n\t\t\treturn\tnew Shot(this.video);\n\t\t}\n\t};\n\n\n\t/**\n\t * Get camera element from container\n\t *\n\t * @static\n\t * @param\t{HTMLElement}\tel\n\t * @return\t{Camera}\n\t */\n\tCamera.get = function (el){\n\t\treturn\tnew Camera(el.firstChild);\n\t};\n\n\n\t/**\n\t * Publish camera element into container\n\t *\n\t * @static\n\t * @param\t{HTMLElement}\tel\n\t * @param\t{Object}\t\toptions\n\t * @param\t{Function}\t\t[callback]\n\t */\n\tCamera.publish = function (el, options, callback){\n\t\tif( typeof options == 'function' ){\n\t\t\tcallback = options;\n\t\t\toptions = {};\n\t\t}\n\n\t\t// Dimensions of \"camera\"\n\t\toptions = api.extend({}, {\n\t\t\t  width:\t'100%'\n\t\t\t, height:\t'100%'\n\t\t\t, start:\ttrue\n\t\t}, options);\n\n\n\t\tif( el.jquery ){\n\t\t\t// Extract first element, from jQuery collection\n\t\t\tel = el[0];\n\t\t}\n\n\n\t\tvar doneFn = function (err){\n\t\t\tif( err ){\n\t\t\t\tcallback(err);\n\t\t\t}\n\t\t\telse {\n\t\t\t\t// Get camera\n\t\t\t\tvar cam = Camera.get(el);\n\t\t\t\tif( options.start ){\n\t\t\t\t\tcam.start(callback);\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tcallback(null, cam);\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\n\n\t\tel.style.width\t= _px(options.width);\n\t\tel.style.height\t= _px(options.height);\n\n\n\t\tif( api.html5 && html5 ){\n\t\t\t// Create video element\n\t\t\tvar video = document.createElement('video');\n\n\t\t\t// Set dimensions\n\t\t\tvideo.style.width\t= _px(options.width);\n\t\t\tvideo.style.height\t= _px(options.height);\n\n\t\t\t// Clean container\n\t\t\tif( window.jQuery ){\n\t\t\t\tjQuery(el).empty();\n\t\t\t} else {\n\t\t\t\tel.innerHTML = '';\n\t\t\t}\n\n\t\t\t// Add \"camera\" to container\n\t\t\tel.appendChild(video);\n\n\t\t\t// end\n\t\t\tdoneFn();\n\t\t}\n\t\telse {\n\t\t\tCamera.fallback(el, options, doneFn);\n\t\t}\n\t};\n\n\n\tCamera.fallback = function (el, options, callback){\n\t\tcallback('not_support_camera');\n\t};\n\n\n\t/**\n\t * @class\tFileAPI.Camera.Shot\n\t */\n\tvar Shot = function (video){\n\t\tvar canvas\t= video.nodeName ? api.Image.toCanvas(video) : video;\n\t\tvar shot\t= api.Image(canvas);\n\t\tshot.type\t= 'image/png';\n\t\tshot.width\t= canvas.width;\n\t\tshot.height\t= canvas.height;\n\t\tshot.size\t= canvas.width * canvas.height * 4;\n\t\treturn\tshot;\n\t};\n\n\n\t/**\n\t * Add \"px\" postfix, if value is a number\n\t *\n\t * @private\n\t * @param\t{*}  val\n\t * @return\t{String}\n\t */\n\tfunction _px(val){\n\t\treturn\tval >= 0 ? val + 'px' : val;\n\t}\n\n\n\t/**\n\t * @private\n\t * @param\t{HTMLVideoElement} video\n\t * @return\t{Boolean}\n\t */\n\tfunction _detectVideoSignal(video){\n\t\tvar canvas = document.createElement('canvas'), ctx, res = false;\n\t\ttry {\n\t\t\tctx = canvas.getContext('2d');\n\t\t\tctx.drawImage(video, 0, 0, 1, 1);\n\t\t\tres = ctx.getImageData(0, 0, 1, 1).data[4] != 255;\n\t\t}\n\t\tcatch( e ){}\n\t\treturn\tres;\n\t}\n\n\n\t// @export\n\tCamera.Shot\t= Shot;\n\tapi.Camera\t= Camera;\n})(window, FileAPI);\n\n/**\n * FileAPI fallback to Flash\n *\n * @flash-developer  \"Vladimir Demidov\" <v.demidov@corp.mail.ru>\n */\n\n/*global window, ActiveXObject, FileAPI */\n(function (window, jQuery, api) {\n\t\"use strict\";\n\n\tvar\n\t\t  document = window.document\n\t\t, location = window.location\n\t\t, navigator = window.navigator\n\t\t, _each = api.each\n\t;\n\n\n\tapi.support.flash = (function (){\n\t\tvar mime = navigator.mimeTypes, has = false;\n\n\t\tif( navigator.plugins && typeof navigator.plugins['Shockwave Flash'] == 'object' ){\n\t\t\thas\t= navigator.plugins['Shockwave Flash'].description && !(mime && mime['application/x-shockwave-flash'] && !mime['application/x-shockwave-flash'].enabledPlugin);\n\t\t}\n\t\telse {\n\t\t\ttry {\n\t\t\t\thas\t= !!(window.ActiveXObject && new ActiveXObject('ShockwaveFlash.ShockwaveFlash'));\n\t\t\t}\n\t\t\tcatch(er){\n\t\t\t\tapi.log('Flash -- does not supported.');\n\t\t\t}\n\t\t}\n\n\t\tif( has && /^file:/i.test(location) ){\n\t\t\tapi.log('[warn] Flash does not work on `file:` protocol.');\n\t\t}\n\n\t\treturn\thas;\n\t})();\n\n\n\t   api.support.flash\n\t&& (0\n\t\t|| !api.html5 || !api.support.html5\n\t\t|| (api.cors && !api.support.cors)\n\t\t|| (api.media && !api.support.media)\n\t)\n\t&& (function (){\n\t\tvar\n\t\t\t  _attr  = api.uid()\n\t\t\t, _retry = 0\n\t\t\t, _files = {}\n\t\t\t, _rhttp = /^https?:/i\n\n\t\t\t, flash = {\n\t\t\t\t_fn: {},\n\n\n\t\t\t\t/**\n\t\t\t\t * Initialization & preload flash object\n\t\t\t\t */\n\t\t\t\tinit: function (){\n\t\t\t\t\tvar child = document.body && document.body.firstChild;\n\n\t\t\t\t\tif( child ){\n\t\t\t\t\t\tdo {\n\t\t\t\t\t\t\tif( child.nodeType == 1 ){\n\t\t\t\t\t\t\t\tapi.log('FlashAPI.state: awaiting');\n\n\t\t\t\t\t\t\t\tvar dummy = document.createElement('div');\n\n\t\t\t\t\t\t\t\tdummy.id = '_' + _attr;\n\n\t\t\t\t\t\t\t\t_css(dummy, {\n\t\t\t\t\t\t\t\t\t  top: 1\n\t\t\t\t\t\t\t\t\t, right: 1\n\t\t\t\t\t\t\t\t\t, width: 5\n\t\t\t\t\t\t\t\t\t, height: 5\n\t\t\t\t\t\t\t\t\t, position: 'absolute'\n\t\t\t\t\t\t\t\t\t, zIndex: 1e6+'' // set max zIndex\n\t\t\t\t\t\t\t\t});\n\n\t\t\t\t\t\t\t\tchild.parentNode.insertBefore(dummy, child);\n\t\t\t\t\t\t\t\tflash.publish(dummy, _attr);\n\n\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\twhile( child = child.nextSibling );\n\t\t\t\t\t}\n\n\t\t\t\t\tif( _retry < 10 ){\n\t\t\t\t\t\tsetTimeout(flash.init, ++_retry*50);\n\t\t\t\t\t}\n\t\t\t\t},\n\n\n\t\t\t\t/**\n\t\t\t\t * Publish flash-object\n\t\t\t\t *\n\t\t\t\t * @param {HTMLElement} el\n\t\t\t\t * @param {String} id\n\t\t\t\t * @param {Object} [opts]\n\t\t\t\t */\n\t\t\t\tpublish: function (el, id, opts){\n\t\t\t\t\topts = opts || {};\n\t\t\t\t\tel.innerHTML = _makeFlashHTML({\n\t\t\t\t\t\t  id: id\n\t\t\t\t\t\t, src: _getUrl(api.flashUrl, 'r=' + api.version)\n//\t\t\t\t\t\t, src: _getUrl('http://v.demidov.boom.corp.mail.ru/uploaderfileapi/FlashFileAPI.swf?1')\n\t\t\t\t\t\t, wmode: opts.camera ? '' : 'transparent'\n\t\t\t\t\t\t, flashvars: 'callback=' + (opts.onEvent || 'FileAPI.Flash.onEvent')\n\t\t\t\t\t\t\t+ '&flashId='+ id\n\t\t\t\t\t\t\t+ '&storeKey='+ navigator.userAgent.match(/\\d/ig).join('') +'_'+ api.version\n\t\t\t\t\t\t\t+ (flash.isReady || (api.pingUrl ? '&ping='+api.pingUrl : ''))\n\t\t\t\t\t\t\t+ '&timeout='+api.flashAbortTimeout\n\t\t\t\t\t\t\t+ (opts.camera ? '&useCamera=' + _getUrl(api.flashWebcamUrl) : '')\n\t\t\t\t\t\t\t+ '&debug='+(api.debug?\"1\":\"\")\n\t\t\t\t\t}, opts);\n\t\t\t\t},\n\n\n\t\t\t\tready: function (){\n\t\t\t\t\tapi.log('FlashAPI.state: ready');\n\n\t\t\t\t\tflash.ready = api.F;\n\t\t\t\t\tflash.isReady = true;\n\t\t\t\t\tflash.patch();\n\t\t\t\t\tflash.patchCamera && flash.patchCamera();\n\t\t\t\t\tapi.event.on(document, 'mouseover', flash.mouseover);\n\t\t\t\t\tapi.event.on(document, 'click', function (evt){\n\t\t\t\t\t\tif( flash.mouseover(evt) ){\n\t\t\t\t\t\t\tevt.preventDefault\n\t\t\t\t\t\t\t\t? evt.preventDefault()\n\t\t\t\t\t\t\t\t: (evt.returnValue = 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\n\t\t\t\tgetEl: function (){\n\t\t\t\t\treturn\tdocument.getElementById('_'+_attr);\n\t\t\t\t},\n\n\n\t\t\t\tgetWrapper: function (node){\n\t\t\t\t\tdo {\n\t\t\t\t\t\tif( /js-fileapi-wrapper/.test(node.className) ){\n\t\t\t\t\t\t\treturn\tnode;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\twhile( (node = node.parentNode) && (node !== document.body) );\n\t\t\t\t},\n\t\t\t\t\n\t\t\t\tdisableMouseover: false,\n\n\t\t\t\tmouseover: function (evt){\n\t\t\t\t\tif (!flash.disableMouseover) {\n\t\t\t\t\t\tvar target = api.event.fix(evt).target;\n\t\n\t\t\t\t\t\tif( /input/i.test(target.nodeName) && target.type == 'file' && !target.disabled ){\n\t\t\t\t\t\t\tvar\n\t\t\t\t\t\t\t\t  state = target.getAttribute(_attr)\n\t\t\t\t\t\t\t\t, wrapper = flash.getWrapper(target)\n\t\t\t\t\t\t\t;\n\t\n\t\t\t\t\t\t\tif( api.multiFlash ){\n\t\t\t\t\t\t\t\t// check state:\n\t\t\t\t\t\t\t\t//   i — published\n\t\t\t\t\t\t\t\t//   i — initialization\n\t\t\t\t\t\t\t\t//   r — ready\n\t\t\t\t\t\t\t\tif( state == 'i' || state == 'r' ){\n\t\t\t\t\t\t\t\t\t// publish fail\n\t\t\t\t\t\t\t\t\treturn\tfalse;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\telse if( state != 'p' ){\n\t\t\t\t\t\t\t\t\t// set \"init\" state\n\t\t\t\t\t\t\t\t\ttarget.setAttribute(_attr, 'i');\n\t\n\t\t\t\t\t\t\t\t\tvar dummy = document.createElement('div');\n\t\n\t\t\t\t\t\t\t\t\tif( !wrapper ){\n\t\t\t\t\t\t\t\t\t\tapi.log('[err] FlashAPI.mouseover: js-fileapi-wrapper not found');\n\t\t\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t\t\t}\n\t\n\t\t\t\t\t\t\t\t\t_css(dummy, {\n\t\t\t\t\t\t\t\t\t\t  top:    0\n\t\t\t\t\t\t\t\t\t\t, left:   0\n\t\t\t\t\t\t\t\t\t\t, width:  target.offsetWidth\n\t\t\t\t\t\t\t\t\t\t, height: target.offsetHeight\n\t\t\t\t\t\t\t\t\t\t, zIndex: 1e6+'' // set max zIndex\n\t\t\t\t\t\t\t\t\t\t, position: 'absolute'\n\t\t\t\t\t\t\t\t\t});\n\t\n\t\t\t\t\t\t\t\t\twrapper.appendChild(dummy);\n\t\t\t\t\t\t\t\t\tflash.publish(dummy, api.uid());\n\t\n\t\t\t\t\t\t\t\t\t// set \"publish\" state\n\t\t\t\t\t\t\t\t\ttarget.setAttribute(_attr, 'p');\n\t\t\t\t\t\t\t\t}\n\t\n\t\t\t\t\t\t\t\treturn\ttrue;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse if( wrapper ){\n\t\t\t\t\t\t\t\t// Use one flash element\n\t\t\t\t\t\t\t\tvar box = _getDimensions(wrapper);\n\t\t\t\t\t\t\t\t_css(flash.getEl(), box);\n\t\n\t\t\t\t\t\t\t\t// Set current input\n\t\t\t\t\t\t\t\tflash.curInp = target;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse if( !/object|embed/i.test(target.nodeName) ){\n\t\t\t\t\t\t\t_css(flash.getEl(), { top: 1, left: 1, width: 5, height: 5 });\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t},\n\n\t\t\t\tonEvent: function (evt){\n\t\t\t\t\tvar type = evt.type;\n\t\t\t\t\t\n\t\t\t\t\tif( type == 'ready' ){\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t// set \"ready\" state\n\t\t\t\t\t\t\tflash.getInput(evt.flashId).setAttribute(_attr, 'r');\n\t\t\t\t\t\t} catch (e){\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tflash.ready();\n\t\t\t\t\t\tsetTimeout(function (){ flash.mouseenter(evt); }, 50);\n\t\t\t\t\t\treturn\ttrue;\n\t\t\t\t\t}\n\t\t\t\t\telse if( type === 'ping' ){\n\t\t\t\t\t\tapi.log('(flash -> js).ping:', [evt.status, evt.savedStatus], evt.error);\n\t\t\t\t\t}\n\t\t\t\t\telse if( type === 'log' ){\n\t\t\t\t\t\tapi.log('(flash -> js).log:', evt.target);\n\t\t\t\t\t}\n\t\t\t\t\telse if( type in flash ){\n\t\t\t\t\t\tsetTimeout(function (){\n\t\t\t\t\t\t\tapi.log('FlashAPI.event.'+evt.type+':', evt);\n\t\t\t\t\t\t\tflash[type](evt);\n\t\t\t\t\t\t}, 1);\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tmouseDown: function(evt) {\n\t\t\t\t\tflash.disableMouseover = true;\n\t\t\t\t},\n\t\t\t\tcancel: function(evt) {\n\t\t\t\t\tflash.disableMouseover = false;\n\t\t\t\t},\n\t\t\t\tmouseenter: function (evt){\n\t\t\t\t\tvar node = flash.getInput(evt.flashId);\n\n\t\t\t\t\tif( node ){\n\t\t\t\t\t\t// Set multiple mode\n\t\t\t\t\t\tflash.cmd(evt, 'multiple', node.getAttribute('multiple') != null);\n\n\n\t\t\t\t\t\t// Set files filter\n\t\t\t\t\t\tvar accept = [], exts = {};\n\n\t\t\t\t\t\t_each((node.getAttribute('accept') || '').split(/,\\s*/), function (mime){\n\t\t\t\t\t\t\tapi.accept[mime] && _each(api.accept[mime].split(' '), function (ext){\n\t\t\t\t\t\t\t\texts[ext] = 1;\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t});\n\n\t\t\t\t\t\t_each(exts, function (i, ext){\n\t\t\t\t\t\t\taccept.push( ext );\n\t\t\t\t\t\t});\n\n\t\t\t\t\t\tflash.cmd(evt, 'accept', accept.length ? accept.join(',')+','+accept.join(',').toUpperCase() : '*');\n\t\t\t\t\t}\n\t\t\t\t},\n\n\n\t\t\t\tget: function (id){\n\t\t\t\t\treturn\tdocument[id] || window[id] || document.embeds[id];\n\t\t\t\t},\n\n\n\t\t\t\tgetInput: function (id){\n\t\t\t\t\tif( api.multiFlash ){\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tvar node = flash.getWrapper(flash.get(id));\n\t\t\t\t\t\t\tif( node ){\n\t\t\t\t\t\t\t\treturn node.getElementsByTagName('input')[0];\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} catch (e){\n\t\t\t\t\t\t\tapi.log('[err] Can not find \"input\" by flashId:', id, e);\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\treturn\tflash.curInp;\n\t\t\t\t\t}\n\t\t\t\t},\n\n\n\t\t\t\tselect: function (evt){\n\t\t\t\t\ttry {\n\t\t\t\t\t\tvar\n\t\t\t\t\t\t\t  inp = flash.getInput(evt.flashId)\n\t\t\t\t\t\t\t, uid = api.uid(inp)\n\t\t\t\t\t\t\t, files = evt.target.files\n\t\t\t\t\t\t\t, event\n\t\t\t\t\t\t;\n\t\t\t\t\t\t_each(files, function (file){\n\t\t\t\t\t\t\tapi.checkFileObj(file);\n\t\t\t\t\t\t});\n\t\n\t\t\t\t\t\t_files[uid] = files;\n\t\n\t\t\t\t\t\tif( document.createEvent ){\n\t\t\t\t\t\t\tevent = document.createEvent('Event');\n\t\t\t\t\t\t\tevent.files = files;\n\t\t\t\t\t\t\tevent.initEvent('change', true, true);\n\t\t\t\t\t\t\tinp.dispatchEvent(event);\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse if( jQuery ){\n\t\t\t\t\t\t\tjQuery(inp).trigger({ type: 'change', files: files });\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse {\n\t\t\t\t\t\t\tevent = document.createEventObject();\n\t\t\t\t\t\t\tevent.files = files;\n\t\t\t\t\t\t\tinp.fireEvent('onchange', event);\n\t\t\t\t\t\t}\n\t\t\t\t\t} finally {\n\t\t\t\t\t\tflash.disableMouseover = false;\n\t\t\t\t\t}\n\t\t\t\t},\n\n\n\t\t\t\tcmd: function (id, name, data, last){\n\t\t\t\t\ttry {\n\t\t\t\t\t\tapi.log('(js -> flash).'+name+':', data);\n\t\t\t\t\t\treturn flash.get(id.flashId || id).cmd(name, data);\n\t\t\t\t\t} catch (e){\n\t\t\t\t\t\tapi.log('(js -> flash).onError:', e);\n\t\t\t\t\t\tif( !last ){\n\t\t\t\t\t\t\t// try again\n\t\t\t\t\t\t\tsetTimeout(function (){ flash.cmd(id, name, data, true); }, 50);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t},\n\n\n\t\t\t\tpatch: function (){\n\t\t\t\t\tapi.flashEngine = true;\n\n\t\t\t\t\t// FileAPI\n\t\t\t\t\t_inherit(api, {\n\t\t\t\t\t\tgetFiles: function (input, filter, callback){\n\t\t\t\t\t\t\tif( callback ){\n\t\t\t\t\t\t\t\tapi.filterFiles(api.getFiles(input), filter, callback);\n\t\t\t\t\t\t\t\treturn null;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tvar files = api.isArray(input) ? input : _files[api.uid(input.target || input.srcElement || input)];\n\n\n\t\t\t\t\t\t\tif( !files ){\n\t\t\t\t\t\t\t\t// Файлов нету, вызываем родительский метод\n\t\t\t\t\t\t\t\treturn\tthis.parent.apply(this, arguments);\n\t\t\t\t\t\t\t}\n\n\n\t\t\t\t\t\t\tif( filter ){\n\t\t\t\t\t\t\t\tfilter\t= api.getFilesFilter(filter);\n\t\t\t\t\t\t\t\tfiles\t= api.filter(files, function (file){ return filter.test(file.name); });\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\treturn\tfiles;\n\t\t\t\t\t\t},\n\n\n\t\t\t\t\t\tgetInfo: function (file, fn){\n\t\t\t\t\t\t\tif( _isHtmlFile(file) ){\n\t\t\t\t\t\t\t\tthis.parent.apply(this, arguments);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse if( file.isShot ){\n\t\t\t\t\t\t\t\tfn(null, file.info = {\n\t\t\t\t\t\t\t\t\twidth: file.width,\n\t\t\t\t\t\t\t\t\theight: file.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\telse {\n\t\t\t\t\t\t\t\tif( !file.__info ){\n\t\t\t\t\t\t\t\t\tvar defer = file.__info = api.defer();\n\n//\t\t\t\t\t\t\t\t\tflash.cmd(file, 'getFileInfo', {\n//\t\t\t\t\t\t\t\t\t\t  id: file.id\n//\t\t\t\t\t\t\t\t\t\t, callback: _wrap(function _(err, info){\n//\t\t\t\t\t\t\t\t\t\t\t_unwrap(_);\n//\t\t\t\t\t\t\t\t\t\t\tdefer.resolve(err, file.info = info);\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\tdefer.resolve(null, file.info = null);\n\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\tfile.__info.then(fn);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\n\n\t\t\t\t\t// FileAPI.Image\n\t\t\t\t\tapi.support.transform = true;\n\t\t\t\t\tapi.Image && _inherit(api.Image.prototype, {\n\t\t\t\t\t\tget: function (fn, scaleMode){\n\t\t\t\t\t\t\tthis.set({ scaleMode: scaleMode || 'noScale' }); // noScale, exactFit\n\t\t\t\t\t\t\treturn this.parent(fn);\n\t\t\t\t\t\t},\n\n\t\t\t\t\t\t_load: function (file, fn){\n\t\t\t\t\t\t\tapi.log('FlashAPI.Image._load:', file);\n\n\t\t\t\t\t\t\tif( _isHtmlFile(file) ){\n\t\t\t\t\t\t\t\tthis.parent.apply(this, arguments);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse {\n\t\t\t\t\t\t\t\tvar _this = this;\n\t\t\t\t\t\t\t\tapi.getInfo(file, function (err){\n\t\t\t\t\t\t\t\t\tfn.call(_this, err, file);\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_apply: function (file, fn){\n\t\t\t\t\t\t\tapi.log('FlashAPI.Image._apply:', file);\n\n\t\t\t\t\t\t\tif( _isHtmlFile(file) ){\n\t\t\t\t\t\t\t\tthis.parent.apply(this, arguments);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse {\n\t\t\t\t\t\t\t\tvar m = this.getMatrix(file.info), doneFn = fn;\n\n\t\t\t\t\t\t\t\tflash.cmd(file, 'imageTransform', {\n\t\t\t\t\t\t\t\t\t  id: file.id\n\t\t\t\t\t\t\t\t\t, matrix: m\n\t\t\t\t\t\t\t\t\t, callback: _wrap(function _(err, base64){\n\t\t\t\t\t\t\t\t\t\tapi.log('FlashAPI.Image._apply.callback:', err);\n\t\t\t\t\t\t\t\t\t\t_unwrap(_);\n\n\t\t\t\t\t\t\t\t\t\tif( err ){\n\t\t\t\t\t\t\t\t\t\t\tdoneFn(err);\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\telse if( !api.support.html5 && (!api.support.dataURI || base64.length > 3e4) ){\n\t\t\t\t\t\t\t\t\t\t\t_makeFlashImage({\n\t\t\t\t\t\t\t\t\t\t\t\t  width:\t(m.deg % 180) ? m.dh : m.dw\n\t\t\t\t\t\t\t\t\t\t\t\t, height:\t(m.deg % 180) ? m.dw : m.dh\n\t\t\t\t\t\t\t\t\t\t\t\t, scale:\tm.scaleMode\n\t\t\t\t\t\t\t\t\t\t\t}, base64, doneFn);\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\telse {\n\t\t\t\t\t\t\t\t\t\t\tif( m.filter ){\n\t\t\t\t\t\t\t\t\t\t\t\tdoneFn = function (err, img){\n\t\t\t\t\t\t\t\t\t\t\t\t\tif( err ){\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tfn(err);\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\telse {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tapi.Image.applyFilter(img, m.filter, function (){\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tfn(err, this.canvas);\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};\n\t\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t\tapi.newImage('data:'+ file.type +';base64,'+ base64, doneFn);\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\ttoData: function (fn){\n\t\t\t\t\t\t\tvar\n\t\t\t\t\t\t\t\t  file = this.file\n\t\t\t\t\t\t\t\t, info = file.info\n\t\t\t\t\t\t\t\t, matrix = this.getMatrix(info)\n\t\t\t\t\t\t\t;\n\t\t\t\t\t\t\tapi.log('FlashAPI.Image.toData');\n\n\t\t\t\t\t\t\tif( _isHtmlFile(file) ){\n\t\t\t\t\t\t\t\tthis.parent.apply(this, arguments);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse {\n\t\t\t\t\t\t\t\tif( matrix.deg == 'auto' ){\n\t\t\t\t\t\t\t\t\tmatrix.deg = api.Image.exifOrientation[info && info.exif && info.exif.Orientation] || 0;\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\tfn.call(this, !file.info, {\n\t\t\t\t\t\t\t\t\t  id:\t\tfile.id\n\t\t\t\t\t\t\t\t\t, flashId:\tfile.flashId\n\t\t\t\t\t\t\t\t\t, name:\t\tfile.name\n\t\t\t\t\t\t\t\t\t, type:\t\tfile.type\n\t\t\t\t\t\t\t\t\t, matrix:\tmatrix\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\n\n\t\t\t\t\tapi.Image && _inherit(api.Image, {\n\t\t\t\t\t\tfromDataURL: function (dataURL, size, callback){\n\t\t\t\t\t\t\tif( !api.support.dataURI || dataURL.length > 3e4 ){\n\t\t\t\t\t\t\t\t_makeFlashImage(\n\t\t\t\t\t\t\t\t\t  api.extend({ scale: 'exactFit' }, size)\n\t\t\t\t\t\t\t\t\t, dataURL.replace(/^data:[^,]+,/, '')\n\t\t\t\t\t\t\t\t\t, function (err, el){ callback(el); }\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\tthis.parent(dataURL, size, callback);\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// FileAPI.Form\n\t\t\t\t\t_inherit(api.Form.prototype, {\n\t\t\t\t\t\ttoData: function (fn){\n\t\t\t\t\t\t\tvar items = this.items, i = items.length;\n\n\t\t\t\t\t\t\tfor( ; i--; ){\n\t\t\t\t\t\t\t\tif( items[i].file && _isHtmlFile(items[i].blob) ){\n\t\t\t\t\t\t\t\t\treturn this.parent.apply(this, arguments);\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\tapi.log('FlashAPI.Form.toData');\n\t\t\t\t\t\t\tfn(items);\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\n\n\t\t\t\t\t// FileAPI.XHR\n\t\t\t\t\t_inherit(api.XHR.prototype, {\n\t\t\t\t\t\t_send: function (options, formData){\n\t\t\t\t\t\t\tif(\n\t\t\t\t\t\t\t\t   formData.nodeName\n\t\t\t\t\t\t\t\t|| formData.append && api.support.html5\n\t\t\t\t\t\t\t\t|| api.isArray(formData) && (typeof formData[0] === 'string')\n\t\t\t\t\t\t\t){\n\t\t\t\t\t\t\t\t// HTML5, Multipart or IFrame\n\t\t\t\t\t\t\t\treturn\tthis.parent.apply(this, arguments);\n\t\t\t\t\t\t\t}\n\n\n\t\t\t\t\t\t\tvar\n\t\t\t\t\t\t\t\t  data = {}\n\t\t\t\t\t\t\t\t, files = {}\n\t\t\t\t\t\t\t\t, _this = this\n\t\t\t\t\t\t\t\t, flashId\n\t\t\t\t\t\t\t\t, fileId\n\t\t\t\t\t\t\t;\n\n\t\t\t\t\t\t\t_each(formData, function (item){\n\t\t\t\t\t\t\t\tif( item.file ){\n\t\t\t\t\t\t\t\t\tfiles[item.name] = item = _getFileDescr(item.blob);\n\t\t\t\t\t\t\t\t\tfileId  = item.id;\n\t\t\t\t\t\t\t\t\tflashId = item.flashId;\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\tdata[item.name] = item.blob;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t});\n\n\t\t\t\t\t\t\tif( !fileId ){\n\t\t\t\t\t\t\t\tflashId = _attr;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tif( !flashId ){\n\t\t\t\t\t\t\t\tapi.log('[err] FlashAPI._send: flashId -- undefined');\n\t\t\t\t\t\t\t\treturn this.parent.apply(this, arguments);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse {\n\t\t\t\t\t\t\t\tapi.log('FlashAPI.XHR._send: '+ flashId +' -> '+ fileId);\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t_this.xhr = {\n\t\t\t\t\t\t\t\theaders: {},\n\t\t\t\t\t\t\t\tabort: function (){ flash.cmd(flashId, 'abort', { id: fileId }); },\n\t\t\t\t\t\t\t\tgetResponseHeader: function (name){ return this.headers[name]; },\n\t\t\t\t\t\t\t\tgetAllResponseHeaders: function (){ return this.headers; }\n\t\t\t\t\t\t\t};\n\n\t\t\t\t\t\t\tvar queue = api.queue(function (){\n\t\t\t\t\t\t\t\tflash.cmd(flashId, 'upload', {\n\t\t\t\t\t\t\t\t\t  url: _getUrl(options.url.replace(/([a-z]+)=(\\?)&?/i, ''))\n\t\t\t\t\t\t\t\t\t, data: data\n\t\t\t\t\t\t\t\t\t, files: fileId ? files : null\n\t\t\t\t\t\t\t\t\t, headers: options.headers || {}\n\t\t\t\t\t\t\t\t\t, callback: _wrap(function upload(evt){\n\t\t\t\t\t\t\t\t\t\tvar type = evt.type, result = evt.result;\n\n\t\t\t\t\t\t\t\t\t\tapi.log('FlashAPI.upload.'+type);\n\n\t\t\t\t\t\t\t\t\t\tif( type == 'progress' ){\n\t\t\t\t\t\t\t\t\t\t\tevt.loaded = Math.min(evt.loaded, evt.total); // @todo fixme\n\t\t\t\t\t\t\t\t\t\t\tevt.lengthComputable = true;\n\t\t\t\t\t\t\t\t\t\t\toptions.progress(evt);\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\telse if( type == 'complete' ){\n\t\t\t\t\t\t\t\t\t\t\t_unwrap(upload);\n\n\t\t\t\t\t\t\t\t\t\t\tif( typeof result == 'string' ){\n\t\t\t\t\t\t\t\t\t\t\t\t_this.responseText\t= result.replace(/%22/g, \"\\\"\").replace(/%5c/g, \"\\\\\").replace(/%26/g, \"&\").replace(/%25/g, \"%\");\n\t\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t\t_this.end(evt.status || 200);\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\telse if( type == 'abort' || type == 'error' ){\n\t\t\t\t\t\t\t\t\t\t\t_this.end(evt.status || 0, evt.message);\n\t\t\t\t\t\t\t\t\t\t\t_unwrap(upload);\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\n\n\t\t\t\t\t\t\t// #2174: FileReference.load() call while FileReference.upload() or vice versa\n\t\t\t\t\t\t\t_each(files, function (file){\n\t\t\t\t\t\t\t\tqueue.inc();\n\t\t\t\t\t\t\t\tapi.getInfo(file, queue.next);\n\t\t\t\t\t\t\t});\n\n\t\t\t\t\t\t\tqueue.check();\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\n\t\tfunction _makeFlashHTML(opts){\n\t\t\treturn ('<object id=\"#id#\" classid=\"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000\" width=\"'+(opts.width || '100%')+'\" height=\"'+(opts.height || '100%')+'\">'\n\t\t\t\t+ '<param name=\"movie\" value=\"#src#\" />'\n\t\t\t\t+ '<param name=\"flashvars\" value=\"#flashvars#\" />'\n\t\t\t\t+ '<param name=\"swliveconnect\" value=\"true\" />'\n\t\t\t\t+ '<param name=\"allowscriptaccess\" value=\"always\" />'\n\t\t\t\t+ '<param name=\"allownetworking\" value=\"all\" />'\n\t\t\t\t+ '<param name=\"menu\" value=\"false\" />'\n\t\t\t\t+ '<param name=\"wmode\" value=\"#wmode#\" />'\n\t\t\t\t+ '<embed flashvars=\"#flashvars#\" swliveconnect=\"true\" allownetworking=\"all\" allowscriptaccess=\"always\" name=\"#id#\" src=\"#src#\" width=\"'+(opts.width || '100%')+'\" height=\"'+(opts.height || '100%')+'\" menu=\"false\" wmode=\"transparent\" type=\"application/x-shockwave-flash\"></embed>'\n\t\t\t\t+ '</object>').replace(/#(\\w+)#/ig, function (a, name){ return opts[name]; })\n\t\t\t;\n\t\t}\n\n\n\t\tfunction _css(el, css){\n\t\t\tif( el && el.style ){\n\t\t\t\tvar key, val;\n\t\t\t\tfor( key in css ){\n\t\t\t\t\tval = css[key];\n\t\t\t\t\tif( typeof val == 'number' ){\n\t\t\t\t\t\tval += 'px';\n\t\t\t\t\t}\n\t\t\t\t\ttry { el.style[key] = val; } catch (e) {}\n\t\t\t\t}\n\t\t\t\t\n\t\t\t}\n\t\t}\n\n\n\t\tfunction _inherit(obj, methods){\n\t\t\t_each(methods, function (fn, name){\n\t\t\t\tvar prev = obj[name];\n\t\t\t\tobj[name] = function (){\n\t\t\t\t\tthis.parent = prev;\n\t\t\t\t\treturn fn.apply(this, arguments);\n\t\t\t\t};\n\t\t\t});\n\t\t}\n\n\t\tfunction _isHtmlFile(file){\n\t\t\treturn\tfile && !file.flashId;\n\t\t}\n\n\t\tfunction _wrap(fn){\n\t\t\tvar id = fn.wid = api.uid();\n\t\t\tflash._fn[id] = fn;\n\t\t\treturn\t'FileAPI.Flash._fn.'+id;\n\t\t}\n\n\n\t\tfunction _unwrap(fn){\n\t\t\ttry {\n\t\t\t\tflash._fn[fn.wid] = null;\n\t\t\t\tdelete\tflash._fn[fn.wid];\n\t\t\t}\n\t\t\tcatch(e){}\n\t\t}\n\n\n\t\tfunction _getUrl(url, params){\n\t\t\tif( !_rhttp.test(url) ){\n\t\t\t\tif( /^\\.\\//.test(url) || '/' != url.charAt(0) ){\n\t\t\t\t\tvar path = location.pathname;\n\t\t\t\t\tpath = path.substr(0, path.lastIndexOf('/'));\n\t\t\t\t\turl = (path +'/'+ url).replace('/./', '/');\n\t\t\t\t}\n\n\t\t\t\tif( '//' != url.substr(0, 2) ){\n\t\t\t\t\turl = '//' + location.host + url;\n\t\t\t\t}\n\n\t\t\t\tif( !_rhttp.test(url) ){\n\t\t\t\t\turl = location.protocol + url;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif( params ){\n\t\t\t\turl += (/\\?/.test(url) ? '&' : '?') + params;\n\t\t\t}\n\n\t\t\treturn\turl;\n\t\t}\n\n\n\t\tfunction _makeFlashImage(opts, base64, fn){\n\t\t\tvar\n\t\t\t\t  key\n\t\t\t\t, flashId = api.uid()\n\t\t\t\t, el = document.createElement('div')\n\t\t\t\t, attempts = 10\n\t\t\t;\n\n\t\t\tfor( key in opts ){\n\t\t\t\tel.setAttribute(key, opts[key]);\n\t\t\t\tel[key] = opts[key];\n\t\t\t}\n\n\t\t\t_css(el, opts);\n\n\t\t\topts.width\t= '100%';\n\t\t\topts.height\t= '100%';\n\n\t\t\tel.innerHTML = _makeFlashHTML(api.extend({\n\t\t\t\t  id: flashId\n\t\t\t\t, src: _getUrl(api.flashImageUrl, 'r='+ api.uid())\n\t\t\t\t, wmode: 'opaque'\n\t\t\t\t, flashvars: 'scale='+ opts.scale +'&callback='+_wrap(function _(){\n\t\t\t\t\t_unwrap(_);\n\t\t\t\t\tif( --attempts > 0 ){\n\t\t\t\t\t\t_setImage();\n\t\t\t\t\t}\n\t\t\t\t\treturn true;\n\t\t\t\t})\n\t\t\t}, opts));\n\n\t\t\tfunction _setImage(){\n\t\t\t\ttry {\n\t\t\t\t\t// Get flash-object by id\n\t\t\t\t\tvar img = flash.get(flashId);\n\t\t\t\t\timg.setImage(base64);\n\t\t\t\t} catch (e){\n\t\t\t\t\tapi.log('[err] FlashAPI.Preview.setImage -- can not set \"base64\":', e);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfn(false, el);\n\t\t\tel = null;\n\t\t}\n\n\n\t\tfunction _getFileDescr(file){\n\t\t\treturn\t{\n\t\t\t\t  id: file.id\n\t\t\t\t, name: file.name\n\t\t\t\t, matrix: file.matrix\n\t\t\t\t, flashId: file.flashId\n\t\t\t};\n\t\t}\n\n\n\t\tfunction _getDimensions(el){\n\t\t\tvar\n\t\t\t\t  box = el.getBoundingClientRect()\n\t\t\t\t, body = document.body\n\t\t\t\t, docEl = (el && el.ownerDocument).documentElement\n\t\t\t;\n\t\t\t\n\t\t\tfunction getOffset(obj) {\n\t\t\t    var left, top;\n\t\t\t    left = top = 0;\n\t\t\t    if (obj.offsetParent) {\n\t\t\t        do {\n\t\t\t            left += obj.offsetLeft;\n\t\t\t            top  += obj.offsetTop;\n\t\t\t        } while (obj = obj.offsetParent);\n\t\t\t    }\n\t\t\t    return {\n\t\t\t        left : left,\n\t\t\t        top : top\n\t\t\t    };\n\t\t\t};\n\t\t\t\n\t\t\treturn {\n\t\t\t\t  top:\t\tgetOffset(el).top\n\t\t\t\t, left:\t\tgetOffset(el).left\n\t\t\t\t, width:\tel.offsetWidth\n\t\t\t\t, height:\tel.offsetHeight\n\t\t\t};\n\t\t}\n\n\t\t// @export\n\t\tapi.Flash = flash;\n\n\n\t\t// Check dataURI support\n\t\tapi.newImage('data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///ywAAAAAAQABAAACAUwAOw==', function (err, img){\n\t\t\tapi.support.dataURI = !(img.width != 1 || img.height != 1);\n\t\t\tflash.init();\n\t\t});\n\t})();\n})(window, window.jQuery, FileAPI);\n\n/**\n * FileAPI fallback to Flash\n *\n * @flash-developer  \"Vladimir Demidov\" <v.demidov@corp.mail.ru>\n */\n\n/*global window, FileAPI */\n(function (window, jQuery, api) {\n    \"use strict\";\n\n    var _each = api.each,\n        _cameraQueue = [];\n\n\n    if (api.support.flash && (api.media && !api.support.media)) {\n        (function () {\n\n            function _wrap(fn) {\n                var id = fn.wid = api.uid();\n                api.Flash._fn[id] = fn;\n                return 'FileAPI.Flash._fn.' + id;\n            }\n\n\n            function _unwrap(fn) {\n                try {\n                    api.Flash._fn[fn.wid] = null;\n                    delete api.Flash._fn[fn.wid];\n                } catch (e) {\n                }\n            }\n\n            var flash = api.Flash;\n            api.extend(api.Flash, {\n\n                patchCamera: function () {\n                    api.Camera.fallback = function (el, options, callback) {\n                        var camId = api.uid();\n                        api.log('FlashAPI.Camera.publish: ' + camId);\n                        flash.publish(el, camId, api.extend(options, {\n                            camera: true,\n                            onEvent: _wrap(function _(evt) {\n                                if (evt.type === 'camera') {\n                                    _unwrap(_);\n\n                                    if (evt.error) {\n                                        api.log('FlashAPI.Camera.publish.error: ' + evt.error);\n                                        callback(evt.error);\n                                    } else {\n                                        api.log('FlashAPI.Camera.publish.success: ' + camId);\n                                        callback(null);\n                                    }\n                                }\n                            })\n                        }));\n                    };\n                    // Run\n                    _each(_cameraQueue, function (args) {\n                        api.Camera.fallback.apply(api.Camera, args);\n                    });\n                    _cameraQueue = [];\n\n\n                    // FileAPI.Camera:proto\n                    api.extend(api.Camera.prototype, {\n                        _id: function () {\n                            return this.video.id;\n                        },\n\n                        start: function (callback) {\n                            var _this = this;\n                            flash.cmd(this._id(), 'camera.on', {\n                                callback: _wrap(function _(evt) {\n                                    _unwrap(_);\n\n                                    if (evt.error) {\n                                        api.log('FlashAPI.camera.on.error: ' + evt.error);\n                                        callback(evt.error, _this);\n                                    } else {\n                                        api.log('FlashAPI.camera.on.success: ' + _this._id());\n                                        _this._active = true;\n                                        callback(null, _this);\n                                    }\n                                })\n                            });\n                        },\n\n                        stop: function () {\n                            this._active = false;\n                            flash.cmd(this._id(), 'camera.off');\n                        },\n\n                        shot: function () {\n                            api.log('FlashAPI.Camera.shot:', this._id());\n\n                            var shot = api.Flash.cmd(this._id(), 'shot', {});\n                            shot.type = 'image/png';\n                            shot.flashId = this._id();\n                            shot.isShot = true;\n\n                            return new api.Camera.Shot(shot);\n                        }\n                    });\n                }\n            });\n\n            api.Camera.fallback = function () {\n                _cameraQueue.push(arguments);\n            };\n\n        }());\n    }\n}(window, window.jQuery, FileAPI));\nif( typeof define === \"function\" && define.amd ){ define(\"FileAPI\", [], function (){ return FileAPI; }); }"
  },
  {
    "path": "flowable-ui-web/idm/libs/ng-file-upload/ng-file-upload-all.js",
    "content": "/**!\n * AngularJS file upload/drop directive and service with progress and abort\n * @author  Danial  <danial.farid@gmail.com>\n * @version 4.1.0\n */\n(function () {\n\nvar key, i;\nfunction patchXHR(fnName, newFn) {\n    window.XMLHttpRequest.prototype[fnName] = newFn(window.XMLHttpRequest.prototype[fnName]);\n}\n\nif (window.XMLHttpRequest && !window.XMLHttpRequest.__isFileAPIShim) {\n    patchXHR('setRequestHeader', function (orig) {\n        return function (header, value) {\n            if (header === '__setXHR_') {\n                var val = value(this);\n                // fix for angular < 1.2.0\n                if (val instanceof Function) {\n                    val(this);\n                }\n            } else {\n                orig.apply(this, arguments);\n            }\n        }\n    });\n}\n\nvar ngFileUpload = angular.module('ngFileUpload', []);\n\nngFileUpload.version = '4.1.0';\nngFileUpload.service('Upload', ['$http', '$q', '$timeout', function ($http, $q, $timeout) {\n    function sendHttp(config) {\n        config.method = config.method || 'POST';\n        config.headers = config.headers || {};\n        config.transformRequest = config.transformRequest || function (data, headersGetter) {\n            if (window.ArrayBuffer && data instanceof window.ArrayBuffer) {\n                return data;\n            }\n            return $http.defaults.transformRequest[0](data, headersGetter);\n        };\n        var deferred = $q.defer();\n        var promise = deferred.promise;\n\n        config.headers['__setXHR_'] = function () {\n            return function (xhr) {\n                if (!xhr) return;\n                config.__XHR = xhr;\n                config.xhrFn && config.xhrFn(xhr);\n                xhr.upload.addEventListener('progress', function (e) {\n                    e.config = config;\n                    deferred.notify ? deferred.notify(e) : promise.progress_fn && $timeout(function () {\n                        promise.progress_fn(e)\n                    });\n                }, false);\n                //fix for firefox not firing upload progress end, also IE8-9\n                xhr.upload.addEventListener('load', function (e) {\n                    if (e.lengthComputable) {\n                        e.config = config;\n                        deferred.notify ? deferred.notify(e) : promise.progress_fn && $timeout(function () {\n                            promise.progress_fn(e)\n                        });\n                    }\n                }, false);\n            };\n        };\n\n        $http(config).then(function (r) {\n            deferred.resolve(r)\n        }, function (e) {\n            deferred.reject(e)\n        }, function (n) {\n            deferred.notify(n)\n        });\n\n        promise.success = function (fn) {\n            promise.then(function (response) {\n                fn(response.data, response.status, response.headers, config);\n            });\n            return promise;\n        };\n\n        promise.error = function (fn) {\n            promise.then(null, function (response) {\n                fn(response.data, response.status, response.headers, config);\n            });\n            return promise;\n        };\n\n        promise.progress = function (fn) {\n            promise.progress_fn = fn;\n            promise.then(null, null, function (update) {\n                fn(update);\n            });\n            return promise;\n        };\n        promise.abort = function () {\n            if (config.__XHR) {\n                $timeout(function () {\n                    config.__XHR.abort();\n                });\n            }\n            return promise;\n        };\n        promise.xhr = function (fn) {\n            config.xhrFn = (function (origXhrFn) {\n                return function () {\n                    origXhrFn && origXhrFn.apply(promise, arguments);\n                    fn.apply(promise, arguments);\n                }\n            })(config.xhrFn);\n            return promise;\n        };\n\n        return promise;\n    }\n\n    this.upload = function (config) {\n        config.headers = config.headers || {};\n        config.headers['Content-Type'] = undefined;\n        config.transformRequest = config.transformRequest ?\n            (angular.isArray(config.transformRequest) ?\n                config.transformRequest : [config.transformRequest]) : [];\n        config.transformRequest.push(function (data) {\n            var formData = new FormData();\n            var allFields = {};\n            for (key in config.fields) {\n                if (config.fields.hasOwnProperty(key)) {\n                    allFields[key] = config.fields[key];\n                }\n            }\n            if (data) allFields['data'] = data;\n\n            if (config.formDataAppender) {\n                for (key in allFields) {\n                    if (allFields.hasOwnProperty(key)) {\n                        config.formDataAppender(formData, key, allFields[key]);\n                    }\n                }\n            } else {\n                for (key in allFields) {\n                    if (allFields.hasOwnProperty(key)) {\n                        var val = allFields[key];\n                        if (val !== undefined) {\n                            if (angular.isDate(val)) {\n                                val = val.toISOString();\n                            }\n                            if (angular.isString(val)) {\n                                formData.append(key, val);\n                            } else {\n                                if (config.sendObjectsAsJsonBlob && angular.isObject(val)) {\n                                    formData.append(key, new Blob([val], {type: 'application/json'}));\n                                } else {\n                                    formData.append(key, JSON.stringify(val));\n                                }\n                            }\n\n                        }\n                    }\n                }\n            }\n\n            if (config.file != null) {\n                var fileFormName = config.fileFormDataName || 'file';\n\n                if (angular.isArray(config.file)) {\n                    var isFileFormNameString = angular.isString(fileFormName);\n                    for (var i = 0; i < config.file.length; i++) {\n                        formData.append(isFileFormNameString ? fileFormName : fileFormName[i], config.file[i],\n                            (config.fileName && config.fileName[i]) || config.file[i].name);\n                    }\n                } else {\n                    formData.append(fileFormName, config.file, config.fileName || config.file.name);\n                }\n            }\n            return formData;\n        });\n\n        return sendHttp(config);\n    };\n\n    this.http = function (config) {\n        return sendHttp(config);\n    };\n}]);\n\nngFileUpload.directive('ngfSelect', ['$parse', '$timeout', '$compile',\n    function ($parse, $timeout, $compile) {\n        return {\n            restrict: 'AEC',\n            require: '?ngModel',\n            link: function (scope, elem, attr, ngModel) {\n                linkFileSelect(scope, elem, attr, ngModel, $parse, $timeout, $compile);\n            }\n        }\n    }]);\n\nfunction linkFileSelect(scope, elem, attr, ngModel, $parse, $timeout, $compile) {\n    function isInputTypeFile() {\n        return elem[0].tagName.toLowerCase() === 'input' && elem.attr('type') && elem.attr('type').toLowerCase() === 'file';\n    }\n    var changeFnAttr = attr.ngfChange || (attr.ngfSelect && attr.ngfSelect.indexOf('(') > 0);\n    var isUpdating = false;\n    function changeFn(evt) {\n        if (!isUpdating) {\n            isUpdating = true;\n            try {\n                var fileList = evt.__files_ || (evt.target && evt.target.files);\n                var files = [], rejFiles = [];\n\n                for (var i = 0; i < fileList.length; i++) {\n                    var file = fileList.item(i);\n                    if (validate(scope, $parse, attr, file, evt)) {\n                        files.push(file);\n                    } else {\n                        rejFiles.push(file);\n                    }\n                }\n                updateModel($parse, $timeout, scope, ngModel, attr, changeFnAttr, files, rejFiles, evt);\n                if (files.length == 0) evt.target.value = files;\n//                if (evt.target && evt.target.getAttribute('__ngf_gen__')) {\n//                    angular.element(evt.target).remove();\n//                }\n            } finally {\n                isUpdating = false;\n            }\n        }\n    }\n\n    function bindAttrToFileInput(fileElem) {\n        if (attr.ngfMultiple) fileElem.attr('multiple', $parse(attr.ngfMultiple)(scope));\n        if (!$parse(attr.ngfMultiple)(scope)) fileElem.attr('multiple', undefined);\n        if (attr['accept']) fileElem.attr('accept', attr['accept']);\n        if (attr.ngfCapture) fileElem.attr('capture', $parse(attr.ngfCapture)(scope));\n        if (attr.ngfDisabled) fileElem.attr('disabled', $parse(attr.ngfDisabled)(scope));\n        for (var i = 0; i < elem[0].attributes.length; i++) {\n            var attribute = elem[0].attributes[i];\n            if (attribute.name !== 'type' && attribute.name !== 'class' && attribute.name !== 'id' && attribute.name !== 'style') {\n            \tfileElem.attr(attribute.name, attribute.value);\n            }\n        }\n    }\n\n    function createFileInput(evt) {\n        if (elem.attr('disabled')) {\n            return;\n        }\n        var fileElem = angular.element('<input type=\"file\">');\n        bindAttrToFileInput(fileElem);\n\n        if (isInputTypeFile()) {\n            elem.replaceWith(fileElem);\n            elem = fileElem;\n        } else {\n            fileElem.css('display', 'none').attr('tabindex', '-1').attr('__ngf_gen__', true);\n            if (elem.__ngf_ref_elem__) {elem.__ngf_ref_elem__.remove();}\n            elem.__ngf_ref_elem__ = fileElem;\n            document.body.appendChild(fileElem[0]);\n        }\n\n        return fileElem;\n    }\n\n    function resetModel(evt) {\n        updateModel($parse, $timeout, scope, ngModel, attr, changeFnAttr, [], [], evt, true);\n    }\n\n    function clickHandler(evt) {\n    \tevt.preventDefault();\n        var fileElem = createFileInput(evt);\n        if (fileElem) {\n        \tfileElem.bind('change', changeFn);\n        \tresetModel(evt);\n\n        \tfunction clickAndAssign() {\n            \tfileElem[0].click();\n    \t        if (isInputTypeFile()) {\n    \t            elem.bind('click touchend', clickHandler);\n    \t            evt.preventDefault()\n    \t        }\n        \t}\n        \t\n        \t// fix for android native browser\n        \tif (navigator.userAgent.toLowerCase().match(/android/)) {\n                setTimeout(function() {\n                \tclickAndAssign();\n                }, 0);        \t\t\n        \t} else {\n        \t\tclickAndAssign();\n        \t}\n        }\n    }\n\n    if (window.FileAPI && window.FileAPI.ngfFixIE) {\n        window.FileAPI.ngfFixIE(elem, createFileInput, bindAttrToFileInput, changeFn, resetModel);\n    } else {\n        elem.bind('click touchend', clickHandler);\n    }\n}\n\nngFileUpload.directive('ngfDrop', ['$parse', '$timeout', '$location', function ($parse, $timeout, $location) {\n    return {\n        restrict: 'AEC',\n        require: '?ngModel',\n        link: function (scope, elem, attr, ngModel) {\n            linkDrop(scope, elem, attr, ngModel, $parse, $timeout, $location);\n        }\n    }\n}]);\n\nngFileUpload.directive('ngfNoFileDrop', function () {\n    return function (scope, elem) {\n        if (dropAvailable()) elem.css('display', 'none')\n    }\n});\n\nngFileUpload.directive('ngfDropAvailable', ['$parse', '$timeout', function ($parse, $timeout) {\n    return function (scope, elem, attr) {\n        if (dropAvailable()) {\n            var fn = $parse(attr.ngfDropAvailable);\n            $timeout(function () {\n                fn(scope);\n                if (fn.assign) {\n                    fn.assign(scope, true);                \t\n                }\n            });\n        }\n    }\n}]);\n\nfunction linkDrop(scope, elem, attr, ngModel, $parse, $timeout, $location) {\n    var available = dropAvailable();\n    if (attr.dropAvailable) {\n        $timeout(function () {\n        \tscope[attr.dropAvailable] ? scope[attr.dropAvailable].value = available : scope[attr.dropAvailable] = available;\n        });\n    }\n    if (!available) {\n        if ($parse(attr.ngfHideOnDropNotAvailable)(scope) == true) {\n            elem.css('display', 'none');\n        }\n        return;\n    }\n    var leaveTimeout = null;\n    var stopPropagation = $parse(attr.ngfStopPropagation);\n    var dragOverDelay = 1;\n    var accept = $parse(attr.ngfAccept);\n    var disabled = $parse(attr.ngfDisabled);\n    var actualDragOverClass;\n\n    elem[0].addEventListener('dragover', function (evt) {\n        if (disabled(scope)) return;\n        evt.preventDefault();\n        if (stopPropagation(scope)) evt.stopPropagation();\n        // handling dragover events from the Chrome download bar\n        if (navigator.userAgent.indexOf(\"Chrome\") > -1) {\n            var b = evt.dataTransfer.effectAllowed;\n            evt.dataTransfer.dropEffect = ('move' === b || 'linkMove' === b) ? 'move' : 'copy';\n        }\n        $timeout.cancel(leaveTimeout);\n        if (!scope.actualDragOverClass) {\n            actualDragOverClass = calculateDragOverClass(scope, attr, evt);\n        }\n        elem.addClass(actualDragOverClass);\n    }, false);\n    elem[0].addEventListener('dragenter', function (evt) {\n        if (disabled(scope)) return;\n        evt.preventDefault();\n        if (stopPropagation(scope)) evt.stopPropagation();\n    }, false);\n    elem[0].addEventListener('dragleave', function () {\n        if (disabled(scope)) return;\n        leaveTimeout = $timeout(function () {\n            elem.removeClass(actualDragOverClass);\n            actualDragOverClass = null;\n        }, dragOverDelay || 1);\n    }, false);\n    elem[0].addEventListener('drop', function (evt) {\n        if (disabled(scope)) return;\n        evt.preventDefault();\n        if (stopPropagation(scope)) evt.stopPropagation();\n        elem.removeClass(actualDragOverClass);\n        actualDragOverClass = null;\n        extractFiles(evt, function (files, rejFiles) {\n            updateModel($parse, $timeout, scope, ngModel, attr,\n                attr.ngfChange || (attr.ngfDrop && attr.ngfDrop.indexOf('(') > 0), files, rejFiles, evt)\n        }, $parse(attr.ngfAllowDir)(scope) != false, attr.multiple || $parse(attr.ngfMultiple)(scope));\n    }, false);\n\n    function calculateDragOverClass(scope, attr, evt) {\n        var accepted = true;\n        var items = evt.dataTransfer.items;\n        if (items != null) {\n            for (var i = 0; i < items.length && accepted; i++) {\n                accepted = accepted\n                    && (items[i].kind == 'file' || items[i].kind == '')\n                    && validate(scope, $parse, attr, items[i], evt);\n            }\n        }\n        var clazz = $parse(attr.ngfDragOverClass)(scope, {$event: evt});\n        if (clazz) {\n            if (clazz.delay) dragOverDelay = clazz.delay;\n            if (clazz.accept) clazz = accepted ? clazz.accept : clazz.reject;\n        }\n        return clazz || attr.ngfDragOverClass || 'dragover';\n    }\n\n    function extractFiles(evt, callback, allowDir, multiple) {\n        var files = [], rejFiles = [], items = evt.dataTransfer.items, processing = 0;\n\n        function addFile(file) {\n            if (validate(scope, $parse, attr, file, evt)) {\n                files.push(file);\n            } else {\n                rejFiles.push(file);\n            }\n        }\n\n        if (items && items.length > 0 && $location.protocol() != 'file') {\n            for (var i = 0; i < items.length; i++) {\n                if (items[i].webkitGetAsEntry && items[i].webkitGetAsEntry() && items[i].webkitGetAsEntry().isDirectory) {\n                    var entry = items[i].webkitGetAsEntry();\n                    if (entry.isDirectory && !allowDir) {\n                        continue;\n                    }\n                    if (entry != null) {\n                        traverseFileTree(files, entry);\n                    }\n                } else {\n                    var f = items[i].getAsFile();\n                    if (f != null) addFile(f);\n                }\n                if (!multiple && files.length > 0) break;\n            }\n        } else {\n            var fileList = evt.dataTransfer.files;\n            if (fileList != null) {\n                for (var i = 0; i < fileList.length; i++) {\n                    addFile(fileList.item(i));\n                    if (!multiple && files.length > 0) break;\n                }\n            }\n        }\n        var delays = 0;\n        (function waitForProcess(delay) {\n            $timeout(function () {\n                if (!processing) {\n                    if (!multiple && files.length > 1) {\n                        i = 0;\n                        while (files[i].type == 'directory') i++;\n                        files = [files[i]];\n                    }\n                    callback(files, rejFiles);\n                } else {\n                    if (delays++ * 10 < 20 * 1000) {\n                        waitForProcess(10);\n                    }\n                }\n            }, delay || 0)\n        })();\n\n        function traverseFileTree(files, entry, path) {\n            if (entry != null) {\n                if (entry.isDirectory) {\n                    var filePath = (path || '') + entry.name;\n                    addFile({name: entry.name, type: 'directory', path: filePath});\n                    var dirReader = entry.createReader();\n                    var entries = [];\n                    processing++;\n                    var readEntries = function () {\n                        dirReader.readEntries(function (results) {\n                            try {\n                                if (!results.length) {\n                                    for (var i = 0; i < entries.length; i++) {\n                                        traverseFileTree(files, entries[i], (path ? path : '') + entry.name + '/');\n                                    }\n                                    processing--;\n                                } else {\n                                    entries = entries.concat(Array.prototype.slice.call(results || [], 0));\n                                    readEntries();\n                                }\n                            } catch (e) {\n                                processing--;\n                                console.error(e);\n                            }\n                        }, function () {\n                            processing--;\n                        });\n                    };\n                    readEntries();\n                } else {\n                    processing++;\n                    entry.file(function (file) {\n                        try {\n                            processing--;\n                            file.path = (path ? path : '') + file.name;\n                            addFile(file);\n                        } catch (e) {\n                            processing--;\n                            console.error(e);\n                        }\n                    }, function () {\n                        processing--;\n                    });\n                }\n            }\n        }\n    }\n}\n\nngFileUpload.directive('ngfSrc', ['$parse', '$timeout', function ($parse, $timeout) {\n\treturn {\n\t\trestrict: 'AE',\n\t\tlink: function (scope, elem, attr, file) {\n\t\t\tif (window.FileReader) {\n\t\t\t\tscope.$watch(attr.ngfSrc, function(file) {\n\t\t\t\t\tif (file) {\n\t\t\t\t\t\t$timeout(function() {\n\t\t\t\t\t\t\tvar fileReader = new FileReader();\n\t\t\t\t\t\t\tfileReader.readAsDataURL(file);\n\t\t\t\t\t\t\tfileReader.onload = function(e) {\n\t\t\t\t\t\t\t\t$timeout(function() {\n\t\t\t\t\t\t\t\t\telem.attr('src', e.target.result);\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t});\n\t\t\t\t\t} else {\n\t\t\t\t\t\telem.attr('src', '');\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n}]);\n\nfunction dropAvailable() {\n    var div = document.createElement('div');\n    return ('draggable' in div) && ('ondrop' in div);\n}\n\nfunction updateModel($parse, $timeout, scope, ngModel, attr, fileChange, files, rejFiles, evt, noDelay) {\n    function update() {\n        if (ngModel) {\n            $parse(attr.ngModel).assign(scope, files);\n            $timeout(function () {\n                ngModel && ngModel.$setViewValue(files != null && files.length == 0 ? null : files);\n            });\n        }\n        if (attr.ngModelRejected) {\n            $parse(attr.ngModelRejected).assign(scope, rejFiles);\n        }\n        if (fileChange) {\n            $parse(fileChange)(scope, {\n                $files: files,\n                $rejectedFiles: rejFiles,\n                $event: evt\n            });\n\n        }\n    }\n    if (noDelay) {\n        update();\n    } else {\n        $timeout(function () {\n            update();\n        });\n    }\n}\n\nfunction validate(scope, $parse, attr, file, evt) {\n    var accept = $parse(attr.ngfAccept);\n    var fileSizeMax = $parse(attr.ngfMaxSize)(scope) || 9007199254740991;\n    var fileSizeMin = $parse(attr.ngfMinSize)(scope) || -1;\n    var val = accept(scope, {$file: file, $event: evt}), match = false;\n    if (val != null && angular.isString(val)) {\n        var regexp = new RegExp(globStringToRegex(val), 'gi');\n        match = (file.type != null && file.type.match(regexp)) ||\n        \t\t(file.name != null && file.name.match(regexp));\n    }\n    return (val == null || match) && (file.size == null || (file.size < fileSizeMax && file.size > fileSizeMin));\n}\n\nfunction globStringToRegex(str) {\n    if (str.length > 2 && str[0] === '/' && str[str.length - 1] === '/') {\n        return str.substring(1, str.length - 1);\n    }\n    var split = str.split(','), result = '';\n    if (split.length > 1) {\n        for (var i = 0; i < split.length; i++) {\n            result += '(' + globStringToRegex(split[i]) + ')';\n            if (i < split.length - 1) {\n                result += '|'\n            }\n        }\n    } else {\n        if (str.indexOf('.') == 0) {\n            str = '*' + str;\n        }\n        result = '^' + str.replace(new RegExp('[.\\\\\\\\+*?\\\\[\\\\^\\\\]$(){}=!<>|:\\\\' + '-]', 'g'), '\\\\$&') + '$';\n        result = result.replace(/\\\\\\*/g, '.*').replace(/\\\\\\?/g, '.');\n    }\n    return result;\n}\n\n})();\n\n/**!\n * AngularJS file upload/drop directive and service with progress and abort\n * FileAPI Flash shim for old browsers not supporting FormData \n * @author  Danial  <danial.farid@gmail.com>\n * @version 4.1.0\n */\n\n(function() {\n\nvar hasFlash = function() {\n\ttry {\n\t  var fo = new ActiveXObject('ShockwaveFlash.ShockwaveFlash');\n\t  if (fo) return true;\n\t} catch(e) {\n\t  if (navigator.mimeTypes['application/x-shockwave-flash'] != undefined) return true;\n\t}\n\treturn false;\n}\n\nfunction patchXHR(fnName, newFn) {\n\twindow.XMLHttpRequest.prototype[fnName] = newFn(window.XMLHttpRequest.prototype[fnName]);\n};\n\nif ((window.XMLHttpRequest && !window.FormData) || (window.FileAPI && FileAPI.forceLoad)) {\n\tvar initializeUploadListener = function(xhr) {\n\t\tif (!xhr.__listeners) {\n\t\t\tif (!xhr.upload) xhr.upload = {};\n\t\t\txhr.__listeners = [];\n\t\t\tvar origAddEventListener = xhr.upload.addEventListener;\n\t\t\txhr.upload.addEventListener = function(t, fn, b) {\n\t\t\t\txhr.__listeners[t] = fn;\n\t\t\t\torigAddEventListener && origAddEventListener.apply(this, arguments);\n\t\t\t};\n\t\t}\n\t}\n\t\n\tpatchXHR('open', function(orig) {\n\t\treturn function(m, url, b) {\n\t\t\tinitializeUploadListener(this);\n\t\t\tthis.__url = url;\n\t\t\ttry {\n\t\t\t\torig.apply(this, [m, url, b]);\n\t\t\t} catch (e) {\n\t\t\t\tif (e.message.indexOf('Access is denied') > -1) {\n\t\t\t\t\tthis.__origError = e;\n\t\t\t\t\torig.apply(this, [m, '_fix_for_ie_crossdomain__', b]);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t});\n\n\tpatchXHR('getResponseHeader', function(orig) {\n\t\treturn function(h) {\n\t\t\treturn this.__fileApiXHR && this.__fileApiXHR.getResponseHeader ? this.__fileApiXHR.getResponseHeader(h) : (orig == null ? null : orig.apply(this, [h]));\n\t\t};\n\t});\n\n\tpatchXHR('getAllResponseHeaders', function(orig) {\n\t\treturn function() {\n\t\t\treturn this.__fileApiXHR && this.__fileApiXHR.getAllResponseHeaders ? this.__fileApiXHR.getAllResponseHeaders() : (orig == null ? null : orig.apply(this));\n\t\t}\n\t});\n\n\tpatchXHR('abort', function(orig) {\n\t\treturn function() {\n\t\t\treturn this.__fileApiXHR && this.__fileApiXHR.abort ? this.__fileApiXHR.abort() : (orig == null ? null : orig.apply(this));\n\t\t}\n\t});\n\n\tpatchXHR('setRequestHeader', function(orig) {\n\t\treturn function(header, value) {\n\t\t\tif (header === '__setXHR_') {\n\t\t\t\tinitializeUploadListener(this);\n\t\t\t\tvar val = value(this);\n\t\t\t\t// fix for angular < 1.2.0\n\t\t\t\tif (val instanceof Function) {\n\t\t\t\t\tval(this);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tthis.__requestHeaders = this.__requestHeaders || {};\n\t\t\t\tthis.__requestHeaders[header] = value;\n\t\t\t\torig.apply(this, arguments);\n\t\t\t}\n\t\t}\n\t});\n\t\n\tfunction redefineProp(xhr, prop, fn) {\n\t\ttry {\n\t\t\tObject.defineProperty(xhr, prop, {get: fn});\n\t\t} catch (e) {/*ignore*/}\n\t}\n\n\tpatchXHR('send', function(orig) {\n\t\treturn function() {\n\t\t\tvar xhr = this;\n\t\t\tif (arguments[0] && arguments[0].__isFileAPIShim) {\n\t\t\t\tvar formData = arguments[0];\n\t\t\t\tvar config = {\n\t\t\t\t\turl: xhr.__url,\n\t\t\t\t\tjsonp: false, //removes the callback form param\n\t\t\t\t\tcache: true, //removes the ?fileapiXXX in the url\n\t\t\t\t\tcomplete: function(err, fileApiXHR) {\n\t\t\t\t\t\txhr.__completed = true;\n\t\t\t\t\t\tif (!err && xhr.__listeners['load']) \n\t\t\t\t\t\t\txhr.__listeners['load']({type: 'load', loaded: xhr.__loaded, total: xhr.__total, target: xhr, lengthComputable: true});\n\t\t\t\t\t\tif (!err && xhr.__listeners['loadend']) \n\t\t\t\t\t\t\txhr.__listeners['loadend']({type: 'loadend', loaded: xhr.__loaded, total: xhr.__total, target: xhr, lengthComputable: true});\n\t\t\t\t\t\tif (err === 'abort' && xhr.__listeners['abort']) \n\t\t\t\t\t\t\txhr.__listeners['abort']({type: 'abort', loaded: xhr.__loaded, total: xhr.__total, target: xhr, lengthComputable: true});\n\t\t\t\t\t\tif (fileApiXHR.status !== undefined) redefineProp(xhr, 'status', function() {return (fileApiXHR.status == 0 && err && err !== 'abort') ? 500 : fileApiXHR.status});\n\t\t\t\t\t\tif (fileApiXHR.statusText !== undefined) redefineProp(xhr, 'statusText', function() {return fileApiXHR.statusText});\n\t\t\t\t\t\tredefineProp(xhr, 'readyState', function() {return 4});\n\t\t\t\t\t\tif (fileApiXHR.response !== undefined) redefineProp(xhr, 'response', function() {return fileApiXHR.response});\n\t\t\t\t\t\tvar resp = fileApiXHR.responseText || (err && fileApiXHR.status == 0 && err !== 'abort' ? err : undefined);\n\t\t\t\t\t\tredefineProp(xhr, 'responseText', function() {return resp});\n\t\t\t\t\t\tredefineProp(xhr, 'response', function() {return resp});\n\t\t\t\t\t\tif (err) redefineProp(xhr, 'err', function() {return err});\n\t\t\t\t\t\txhr.__fileApiXHR = fileApiXHR;\n\t\t\t\t\t\tif (xhr.onreadystatechange) xhr.onreadystatechange();\n\t\t\t\t\t\tif (xhr.onload) xhr.onload();\n\t\t\t\t\t},\n\t\t\t\t\tfileprogress: function(e) {\n\t\t\t\t\t\te.target = xhr;\n\t\t\t\t\t\txhr.__listeners['progress'] && xhr.__listeners['progress'](e);\n\t\t\t\t\t\txhr.__total = e.total;\n\t\t\t\t\t\txhr.__loaded = e.loaded;\n\t\t\t\t\t\tif (e.total === e.loaded) {\n\t\t\t\t\t\t\t// fix flash issue that doesn't call complete if there is no response text from the server  \n\t\t\t\t\t\t\tvar _this = this\n\t\t\t\t\t\t\tsetTimeout(function() {\n\t\t\t\t\t\t\t\tif (!xhr.__completed) {\n\t\t\t\t\t\t\t\t\txhr.getAllResponseHeaders = function(){};\n\t\t\t\t\t\t\t\t\t_this.complete(null, {status: 204, statusText: 'No Content'});\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}, FileAPI.noContentTimeout || 10000);\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\theaders: xhr.__requestHeaders\n\t\t\t\t}\n\t\t\t\tconfig.data = {};\n\t\t\t\tconfig.files = {}\n\t\t\t\tfor (var i = 0; i < formData.data.length; i++) {\n\t\t\t\t\tvar item = formData.data[i];\n\t\t\t\t\tif (item.val != null && item.val.name != null && item.val.size != null && item.val.type != null) {\n\t\t\t\t\t\tconfig.files[item.key] = item.val;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tconfig.data[item.key] = item.val;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tsetTimeout(function() {\n\t\t\t\t\tif (!hasFlash()) {\n\t\t\t\t\t\tthrow 'Adode Flash Player need to be installed. To check ahead use \"FileAPI.hasFlash\"';\n\t\t\t\t\t}\n\t\t\t\t\txhr.__fileApiXHR = FileAPI.upload(config);\n\t\t\t\t}, 1);\n\t\t\t} else {\n\t\t\t\tif (this.__origError) {\n\t\t\t\t\tthrow this.__origError;\n\t\t\t\t}\n\t\t\t\torig.apply(xhr, arguments);\n\t\t\t}\n\t\t}\n\t});\n\twindow.XMLHttpRequest.__isFileAPIShim = true;\n\n\tfunction isInputTypeFile(elem) {\n\t\treturn elem[0].tagName.toLowerCase() === 'input' && elem.attr('type') && elem.attr('type').toLowerCase() === 'file';\n\t}\n\t\n\twindow.FormData = FormData = function() {\n\t\treturn {\n\t\t\tappend: function(key, val, name) {\n\t\t\t\tif (val.__isFileAPIBlobShim) {\n\t\t\t\t\tval = val.data[0];\n\t\t\t\t}\n\t\t\t\tthis.data.push({\n\t\t\t\t\tkey: key,\n\t\t\t\t\tval: val,\n\t\t\t\t\tname: name\n\t\t\t\t});\n\t\t\t},\n\t\t\tdata: [],\n\t\t\t__isFileAPIShim: true\n\t\t};\n\t};\n\n\twindow.Blob = Blob = function(b) {\n\t\treturn {\n\t\t\tdata: b,\n\t\t\t__isFileAPIBlobShim: true\n\t\t};\n\t};\n\n\t(function () {\n\t\t//load FileAPI\n\t\tif (!window.FileAPI) {\n\t\t\twindow.FileAPI = {};\n\t\t}\n\t\tif (FileAPI.forceLoad) {\n\t\t\tFileAPI.html5 = false;\n\t\t}\n\t\t\n\t\tif (!FileAPI.upload) {\n\t\t\tvar jsUrl, basePath, script = document.createElement('script'), allScripts = document.getElementsByTagName('script'), i, index, src;\n\t\t\tif (window.FileAPI.jsUrl) {\n\t\t\t\tjsUrl = window.FileAPI.jsUrl;\n\t\t\t} else if (window.FileAPI.jsPath) {\n\t\t\t\tbasePath = window.FileAPI.jsPath;\n\t\t\t} else {\n\t\t\t\tfor (i = 0; i < allScripts.length; i++) {\n\t\t\t\t\tsrc = allScripts[i].src;\n\t\t\t\t\tindex = src.search(/\\/ng\\-file\\-upload[\\-a-zA-z0-9\\.]*\\.js/)\n\t\t\t\t\tif (index > -1) {\n\t\t\t\t\t\tbasePath = src.substring(0, index + 1);\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\tif (FileAPI.staticPath == null) FileAPI.staticPath = basePath;\n\t\t\tscript.setAttribute('src', jsUrl || basePath + 'FileAPI.min.js');\n\t\t\tdocument.getElementsByTagName('head')[0].appendChild(script);\n\t\t\tFileAPI.hasFlash = hasFlash();\n\t\t}\n\t})();\n\t\n\tFileAPI.ngfFixIE = function(elem, createFileElemFn, bindAttr, changeFn, resetModel) {\n\t\tif (!hasFlash()) {\n\t\t\tthrow 'Adode Flash Player need to be installed. To check ahead use \"FileAPI.hasFlash\"';\n\t\t}\n\t\tvar makeFlashInput = function(evt) {\n\t\t\tif (elem.attr('disabled')) {\n\t\t\t\telem.__ngf_elem__.removeClass('js-fileapi-wrapper');\n\t\t\t} else {\n\t\t\t\tvar fileElem = elem.__ngf_elem__;\n\t\t\t\tif (!fileElem) {\n\t\t\t\t\tfileElem = elem.__ngf_elem__ = createFileElemFn();\n\t\t\t\t\tfileElem.addClass('js-fileapi-wrapper');\n\t\t\t\t\tif (!isInputTypeFile(elem)) {\n//\t\t\t\t\t\tif (fileElem.parent().css('position') === '' || fileElem.parent().css('position') === 'static') {\n//\t\t\t\t\t\t\tfileElem.parent().css('position', 'relative');\n//\t\t\t\t\t\t}\n//\t\t\t\t\t\telem.parent()[0].insertBefore(fileElem[0], elem[0]);\n//\t\t\t\t\t\telem.css('overflow', 'hidden');\n\t\t\t\t\t}\n\t\t\t\t\tsetTimeout(function() {\n\t\t\t\t\t\tfileElem.bind('mouseenter', makeFlashInput);\n\t\t\t\t\t}, 10);\n\t\t\t\t\tfileElem.bind('change', function(evt) {\n\t\t\t\t    \tfileApiChangeFn.apply(this, [evt]);\n\t\t\t\t\t\tchangeFn.apply(this, [evt]);\n//\t\t\t\t\t\talert('change' +  evt);\n\t\t\t\t\t});\n\t\t\t\t} else {\n\t\t\t\t\tbindAttr(elem.__ngf_elem__);\n\t\t\t\t}\n\t\t\t\tif (!isInputTypeFile(elem)) {\n\t\t\t\t\tfileElem.css('position', 'absolute')\n\t\t\t\t\t\t\t.css('top', getOffset(elem[0]).top + 'px').css('left', getOffset(elem[0]).left + 'px')\n\t\t\t\t\t\t\t.css('width', elem[0].offsetWidth + 'px').css('height', elem[0].offsetHeight + 'px')\n\t\t\t\t\t\t\t.css('filter', 'alpha(opacity=0)').css('display', elem.css('display'))\n\t\t\t\t\t\t\t.css('overflow', 'hidden').css('z-index', '900000');\n\t\t\t\t}\n\t\t\t}\n\t\t\tfunction getOffset(obj) {\n\t\t\t    var left, top;\n\t\t\t    left = top = 0;\n\t\t\t    if (obj.offsetParent) {\n\t\t\t        do {\n\t\t\t            left += obj.offsetLeft;\n\t\t\t            top  += obj.offsetTop;\n\t\t\t        } while (obj = obj.offsetParent);\n\t\t\t    }\n\t\t\t    return {\n\t\t\t        left : left,\n\t\t\t        top : top\n\t\t\t    };\n\t\t\t};\n\t\t};\n\n\t\telem.bind('mouseenter', makeFlashInput);\n\n\t\tvar fileApiChangeFn = function(evt) {\n\t\t\tvar files = FileAPI.getFiles(evt);\n\t\t\t//just a double check for #233\n\t\t\tfor (var i = 0; i < files.length; i++) {\n\t\t\t\tif (files[i].size === undefined) files[i].size = 0;\n\t\t\t\tif (files[i].name === undefined) files[i].name = 'file';\n\t\t\t\tif (files[i].type === undefined) files[i].type = 'undefined';\n\t\t\t}\n\t\t\tif (!evt.target) {\n\t\t\t\tevt.target = {};\n\t\t\t}\n\t\t\tevt.target.files = files;\n\t\t\t// if evt.target.files is not writable use helper field\n\t\t\tif (evt.target.files != files) {\n\t\t\t\tevt.__files_ = files;\n\t\t\t}\n\t\t\t(evt.__files_ || evt.target.files).item = function(i) {\n\t\t\t\treturn (evt.__files_ || evt.target.files)[i] || null;\n\t\t\t};\n\t\t};\n\t};\n\n\tFileAPI.disableFileInput = function(elem, disable) {\n\t\tif (disable) {\n\t\t\telem.removeClass('js-fileapi-wrapper')\n\t\t} else {\n\t\t\telem.addClass('js-fileapi-wrapper');\n\t\t}\n\t};\n}\n\n\nif (!window.FileReader) {\n\twindow.FileReader = function() {\n\t\tvar _this = this, loadStarted = false;\n\t\tthis.listeners = {};\n\t\tthis.addEventListener = function(type, fn) {\n\t\t\t_this.listeners[type] = _this.listeners[type] || [];\n\t\t\t_this.listeners[type].push(fn);\n\t\t};\n\t\tthis.removeEventListener = function(type, fn) {\n\t\t\t_this.listeners[type] && _this.listeners[type].splice(_this.listeners[type].indexOf(fn), 1);\n\t\t};\n\t\tthis.dispatchEvent = function(evt) {\n\t\t\tvar list = _this.listeners[evt.type];\n\t\t\tif (list) {\n\t\t\t\tfor (var i = 0; i < list.length; i++) {\n\t\t\t\t\tlist[i].call(_this, evt);\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t\tthis.onabort = this.onerror = this.onload = this.onloadstart = this.onloadend = this.onprogress = null;\n\n\t\tvar constructEvent = function(type, evt) {\n\t\t\tvar e = {type: type, target: _this, loaded: evt.loaded, total: evt.total, error: evt.error};\n\t\t\tif (evt.result != null) e.target.result = evt.result;\n\t\t\treturn e;\n\t\t};\n\t\tvar listener = function(evt) {\n\t\t\tif (!loadStarted) {\n\t\t\t\tloadStarted = true;\n\t\t\t\t_this.onloadstart && _this.onloadstart(constructEvent('loadstart', evt));\n\t\t\t}\n\t\t\tif (evt.type === 'load') {\n\t\t\t\t_this.onloadend && _this.onloadend(constructEvent('loadend', evt));\n\t\t\t\tvar e = constructEvent('load', evt);\n\t\t\t\t_this.onload && _this.onload(e);\n\t\t\t\t_this.dispatchEvent(e);\n\t\t\t} else if (evt.type === 'progress') {\n\t\t\t\tvar e = constructEvent('progress', evt);\n\t\t\t\t_this.onprogress && _this.onprogress(e);\n\t\t\t\t_this.dispatchEvent(e);\n\t\t\t} else {\n\t\t\t\tvar e = constructEvent('error', evt);\n\t\t\t\t_this.onerror && _this.onerror(e);\n\t\t\t\t_this.dispatchEvent(e);\n\t\t\t}\n\t\t};\n\t\tthis.readAsArrayBuffer = function(file) {\n\t\t\tFileAPI.readAsBinaryString(file, listener);\n\t\t}\n\t\tthis.readAsBinaryString = function(file) {\n\t\t\tFileAPI.readAsBinaryString(file, listener);\n\t\t}\n\t\tthis.readAsDataURL = function(file) {\n\t\t\tFileAPI.readAsDataURL(file, listener);\n\t\t}\n\t\tthis.readAsText = function(file) {\n\t\t\tFileAPI.readAsText(file, listener);\n\t\t}\n\t}\n}\n})();\n"
  },
  {
    "path": "flowable-ui-web/idm/libs/ng-file-upload/ng-file-upload-shim.js",
    "content": "/**!\n * AngularJS file upload/drop directive and service with progress and abort\n * FileAPI Flash shim for old browsers not supporting FormData \n * @author  Danial  <danial.farid@gmail.com>\n * @version 4.1.0\n */\n\n(function() {\n\nvar hasFlash = function() {\n\ttry {\n\t  var fo = new ActiveXObject('ShockwaveFlash.ShockwaveFlash');\n\t  if (fo) return true;\n\t} catch(e) {\n\t  if (navigator.mimeTypes['application/x-shockwave-flash'] != undefined) return true;\n\t}\n\treturn false;\n}\n\nfunction patchXHR(fnName, newFn) {\n\twindow.XMLHttpRequest.prototype[fnName] = newFn(window.XMLHttpRequest.prototype[fnName]);\n};\n\nif ((window.XMLHttpRequest && !window.FormData) || (window.FileAPI && FileAPI.forceLoad)) {\n\tvar initializeUploadListener = function(xhr) {\n\t\tif (!xhr.__listeners) {\n\t\t\tif (!xhr.upload) xhr.upload = {};\n\t\t\txhr.__listeners = [];\n\t\t\tvar origAddEventListener = xhr.upload.addEventListener;\n\t\t\txhr.upload.addEventListener = function(t, fn, b) {\n\t\t\t\txhr.__listeners[t] = fn;\n\t\t\t\torigAddEventListener && origAddEventListener.apply(this, arguments);\n\t\t\t};\n\t\t}\n\t}\n\t\n\tpatchXHR('open', function(orig) {\n\t\treturn function(m, url, b) {\n\t\t\tinitializeUploadListener(this);\n\t\t\tthis.__url = url;\n\t\t\ttry {\n\t\t\t\torig.apply(this, [m, url, b]);\n\t\t\t} catch (e) {\n\t\t\t\tif (e.message.indexOf('Access is denied') > -1) {\n\t\t\t\t\tthis.__origError = e;\n\t\t\t\t\torig.apply(this, [m, '_fix_for_ie_crossdomain__', b]);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t});\n\n\tpatchXHR('getResponseHeader', function(orig) {\n\t\treturn function(h) {\n\t\t\treturn this.__fileApiXHR && this.__fileApiXHR.getResponseHeader ? this.__fileApiXHR.getResponseHeader(h) : (orig == null ? null : orig.apply(this, [h]));\n\t\t};\n\t});\n\n\tpatchXHR('getAllResponseHeaders', function(orig) {\n\t\treturn function() {\n\t\t\treturn this.__fileApiXHR && this.__fileApiXHR.getAllResponseHeaders ? this.__fileApiXHR.getAllResponseHeaders() : (orig == null ? null : orig.apply(this));\n\t\t}\n\t});\n\n\tpatchXHR('abort', function(orig) {\n\t\treturn function() {\n\t\t\treturn this.__fileApiXHR && this.__fileApiXHR.abort ? this.__fileApiXHR.abort() : (orig == null ? null : orig.apply(this));\n\t\t}\n\t});\n\n\tpatchXHR('setRequestHeader', function(orig) {\n\t\treturn function(header, value) {\n\t\t\tif (header === '__setXHR_') {\n\t\t\t\tinitializeUploadListener(this);\n\t\t\t\tvar val = value(this);\n\t\t\t\t// fix for angular < 1.2.0\n\t\t\t\tif (val instanceof Function) {\n\t\t\t\t\tval(this);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tthis.__requestHeaders = this.__requestHeaders || {};\n\t\t\t\tthis.__requestHeaders[header] = value;\n\t\t\t\torig.apply(this, arguments);\n\t\t\t}\n\t\t}\n\t});\n\t\n\tfunction redefineProp(xhr, prop, fn) {\n\t\ttry {\n\t\t\tObject.defineProperty(xhr, prop, {get: fn});\n\t\t} catch (e) {/*ignore*/}\n\t}\n\n\tpatchXHR('send', function(orig) {\n\t\treturn function() {\n\t\t\tvar xhr = this;\n\t\t\tif (arguments[0] && arguments[0].__isFileAPIShim) {\n\t\t\t\tvar formData = arguments[0];\n\t\t\t\tvar config = {\n\t\t\t\t\turl: xhr.__url,\n\t\t\t\t\tjsonp: false, //removes the callback form param\n\t\t\t\t\tcache: true, //removes the ?fileapiXXX in the url\n\t\t\t\t\tcomplete: function(err, fileApiXHR) {\n\t\t\t\t\t\txhr.__completed = true;\n\t\t\t\t\t\tif (!err && xhr.__listeners['load']) \n\t\t\t\t\t\t\txhr.__listeners['load']({type: 'load', loaded: xhr.__loaded, total: xhr.__total, target: xhr, lengthComputable: true});\n\t\t\t\t\t\tif (!err && xhr.__listeners['loadend']) \n\t\t\t\t\t\t\txhr.__listeners['loadend']({type: 'loadend', loaded: xhr.__loaded, total: xhr.__total, target: xhr, lengthComputable: true});\n\t\t\t\t\t\tif (err === 'abort' && xhr.__listeners['abort']) \n\t\t\t\t\t\t\txhr.__listeners['abort']({type: 'abort', loaded: xhr.__loaded, total: xhr.__total, target: xhr, lengthComputable: true});\n\t\t\t\t\t\tif (fileApiXHR.status !== undefined) redefineProp(xhr, 'status', function() {return (fileApiXHR.status == 0 && err && err !== 'abort') ? 500 : fileApiXHR.status});\n\t\t\t\t\t\tif (fileApiXHR.statusText !== undefined) redefineProp(xhr, 'statusText', function() {return fileApiXHR.statusText});\n\t\t\t\t\t\tredefineProp(xhr, 'readyState', function() {return 4});\n\t\t\t\t\t\tif (fileApiXHR.response !== undefined) redefineProp(xhr, 'response', function() {return fileApiXHR.response});\n\t\t\t\t\t\tvar resp = fileApiXHR.responseText || (err && fileApiXHR.status == 0 && err !== 'abort' ? err : undefined);\n\t\t\t\t\t\tredefineProp(xhr, 'responseText', function() {return resp});\n\t\t\t\t\t\tredefineProp(xhr, 'response', function() {return resp});\n\t\t\t\t\t\tif (err) redefineProp(xhr, 'err', function() {return err});\n\t\t\t\t\t\txhr.__fileApiXHR = fileApiXHR;\n\t\t\t\t\t\tif (xhr.onreadystatechange) xhr.onreadystatechange();\n\t\t\t\t\t\tif (xhr.onload) xhr.onload();\n\t\t\t\t\t},\n\t\t\t\t\tfileprogress: function(e) {\n\t\t\t\t\t\te.target = xhr;\n\t\t\t\t\t\txhr.__listeners['progress'] && xhr.__listeners['progress'](e);\n\t\t\t\t\t\txhr.__total = e.total;\n\t\t\t\t\t\txhr.__loaded = e.loaded;\n\t\t\t\t\t\tif (e.total === e.loaded) {\n\t\t\t\t\t\t\t// fix flash issue that doesn't call complete if there is no response text from the server  \n\t\t\t\t\t\t\tvar _this = this\n\t\t\t\t\t\t\tsetTimeout(function() {\n\t\t\t\t\t\t\t\tif (!xhr.__completed) {\n\t\t\t\t\t\t\t\t\txhr.getAllResponseHeaders = function(){};\n\t\t\t\t\t\t\t\t\t_this.complete(null, {status: 204, statusText: 'No Content'});\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}, FileAPI.noContentTimeout || 10000);\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\theaders: xhr.__requestHeaders\n\t\t\t\t}\n\t\t\t\tconfig.data = {};\n\t\t\t\tconfig.files = {}\n\t\t\t\tfor (var i = 0; i < formData.data.length; i++) {\n\t\t\t\t\tvar item = formData.data[i];\n\t\t\t\t\tif (item.val != null && item.val.name != null && item.val.size != null && item.val.type != null) {\n\t\t\t\t\t\tconfig.files[item.key] = item.val;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tconfig.data[item.key] = item.val;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tsetTimeout(function() {\n\t\t\t\t\tif (!hasFlash()) {\n\t\t\t\t\t\tthrow 'Adode Flash Player need to be installed. To check ahead use \"FileAPI.hasFlash\"';\n\t\t\t\t\t}\n\t\t\t\t\txhr.__fileApiXHR = FileAPI.upload(config);\n\t\t\t\t}, 1);\n\t\t\t} else {\n\t\t\t\tif (this.__origError) {\n\t\t\t\t\tthrow this.__origError;\n\t\t\t\t}\n\t\t\t\torig.apply(xhr, arguments);\n\t\t\t}\n\t\t}\n\t});\n\twindow.XMLHttpRequest.__isFileAPIShim = true;\n\n\tfunction isInputTypeFile(elem) {\n\t\treturn elem[0].tagName.toLowerCase() === 'input' && elem.attr('type') && elem.attr('type').toLowerCase() === 'file';\n\t}\n\t\n\twindow.FormData = FormData = function() {\n\t\treturn {\n\t\t\tappend: function(key, val, name) {\n\t\t\t\tif (val.__isFileAPIBlobShim) {\n\t\t\t\t\tval = val.data[0];\n\t\t\t\t}\n\t\t\t\tthis.data.push({\n\t\t\t\t\tkey: key,\n\t\t\t\t\tval: val,\n\t\t\t\t\tname: name\n\t\t\t\t});\n\t\t\t},\n\t\t\tdata: [],\n\t\t\t__isFileAPIShim: true\n\t\t};\n\t};\n\n\twindow.Blob = Blob = function(b) {\n\t\treturn {\n\t\t\tdata: b,\n\t\t\t__isFileAPIBlobShim: true\n\t\t};\n\t};\n\n\t(function () {\n\t\t//load FileAPI\n\t\tif (!window.FileAPI) {\n\t\t\twindow.FileAPI = {};\n\t\t}\n\t\tif (FileAPI.forceLoad) {\n\t\t\tFileAPI.html5 = false;\n\t\t}\n\t\t\n\t\tif (!FileAPI.upload) {\n\t\t\tvar jsUrl, basePath, script = document.createElement('script'), allScripts = document.getElementsByTagName('script'), i, index, src;\n\t\t\tif (window.FileAPI.jsUrl) {\n\t\t\t\tjsUrl = window.FileAPI.jsUrl;\n\t\t\t} else if (window.FileAPI.jsPath) {\n\t\t\t\tbasePath = window.FileAPI.jsPath;\n\t\t\t} else {\n\t\t\t\tfor (i = 0; i < allScripts.length; i++) {\n\t\t\t\t\tsrc = allScripts[i].src;\n\t\t\t\t\tindex = src.search(/\\/ng\\-file\\-upload[\\-a-zA-z0-9\\.]*\\.js/)\n\t\t\t\t\tif (index > -1) {\n\t\t\t\t\t\tbasePath = src.substring(0, index + 1);\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\tif (FileAPI.staticPath == null) FileAPI.staticPath = basePath;\n\t\t\tscript.setAttribute('src', jsUrl || basePath + 'FileAPI.min.js');\n\t\t\tdocument.getElementsByTagName('head')[0].appendChild(script);\n\t\t\tFileAPI.hasFlash = hasFlash();\n\t\t}\n\t})();\n\t\n\tFileAPI.ngfFixIE = function(elem, createFileElemFn, bindAttr, changeFn, resetModel) {\n\t\tif (!hasFlash()) {\n\t\t\tthrow 'Adode Flash Player need to be installed. To check ahead use \"FileAPI.hasFlash\"';\n\t\t}\n\t\tvar makeFlashInput = function(evt) {\n\t\t\tif (elem.attr('disabled')) {\n\t\t\t\telem.__ngf_elem__.removeClass('js-fileapi-wrapper');\n\t\t\t} else {\n\t\t\t\tvar fileElem = elem.__ngf_elem__;\n\t\t\t\tif (!fileElem) {\n\t\t\t\t\tfileElem = elem.__ngf_elem__ = createFileElemFn();\n\t\t\t\t\tfileElem.addClass('js-fileapi-wrapper');\n\t\t\t\t\tif (!isInputTypeFile(elem)) {\n//\t\t\t\t\t\tif (fileElem.parent().css('position') === '' || fileElem.parent().css('position') === 'static') {\n//\t\t\t\t\t\t\tfileElem.parent().css('position', 'relative');\n//\t\t\t\t\t\t}\n//\t\t\t\t\t\telem.parent()[0].insertBefore(fileElem[0], elem[0]);\n//\t\t\t\t\t\telem.css('overflow', 'hidden');\n\t\t\t\t\t}\n\t\t\t\t\tsetTimeout(function() {\n\t\t\t\t\t\tfileElem.bind('mouseenter', makeFlashInput);\n\t\t\t\t\t}, 10);\n\t\t\t\t\tfileElem.bind('change', function(evt) {\n\t\t\t\t    \tfileApiChangeFn.apply(this, [evt]);\n\t\t\t\t\t\tchangeFn.apply(this, [evt]);\n//\t\t\t\t\t\talert('change' +  evt);\n\t\t\t\t\t});\n\t\t\t\t} else {\n\t\t\t\t\tbindAttr(elem.__ngf_elem__);\n\t\t\t\t}\n\t\t\t\tif (!isInputTypeFile(elem)) {\n\t\t\t\t\tfileElem.css('position', 'absolute')\n\t\t\t\t\t\t\t.css('top', getOffset(elem[0]).top + 'px').css('left', getOffset(elem[0]).left + 'px')\n\t\t\t\t\t\t\t.css('width', elem[0].offsetWidth + 'px').css('height', elem[0].offsetHeight + 'px')\n\t\t\t\t\t\t\t.css('filter', 'alpha(opacity=0)').css('display', elem.css('display'))\n\t\t\t\t\t\t\t.css('overflow', 'hidden').css('z-index', '900000');\n\t\t\t\t}\n\t\t\t}\n\t\t\tfunction getOffset(obj) {\n\t\t\t    var left, top;\n\t\t\t    left = top = 0;\n\t\t\t    if (obj.offsetParent) {\n\t\t\t        do {\n\t\t\t            left += obj.offsetLeft;\n\t\t\t            top  += obj.offsetTop;\n\t\t\t        } while (obj = obj.offsetParent);\n\t\t\t    }\n\t\t\t    return {\n\t\t\t        left : left,\n\t\t\t        top : top\n\t\t\t    };\n\t\t\t};\n\t\t};\n\n\t\telem.bind('mouseenter', makeFlashInput);\n\n\t\tvar fileApiChangeFn = function(evt) {\n\t\t\tvar files = FileAPI.getFiles(evt);\n\t\t\t//just a double check for #233\n\t\t\tfor (var i = 0; i < files.length; i++) {\n\t\t\t\tif (files[i].size === undefined) files[i].size = 0;\n\t\t\t\tif (files[i].name === undefined) files[i].name = 'file';\n\t\t\t\tif (files[i].type === undefined) files[i].type = 'undefined';\n\t\t\t}\n\t\t\tif (!evt.target) {\n\t\t\t\tevt.target = {};\n\t\t\t}\n\t\t\tevt.target.files = files;\n\t\t\t// if evt.target.files is not writable use helper field\n\t\t\tif (evt.target.files != files) {\n\t\t\t\tevt.__files_ = files;\n\t\t\t}\n\t\t\t(evt.__files_ || evt.target.files).item = function(i) {\n\t\t\t\treturn (evt.__files_ || evt.target.files)[i] || null;\n\t\t\t};\n\t\t};\n\t};\n\n\tFileAPI.disableFileInput = function(elem, disable) {\n\t\tif (disable) {\n\t\t\telem.removeClass('js-fileapi-wrapper')\n\t\t} else {\n\t\t\telem.addClass('js-fileapi-wrapper');\n\t\t}\n\t};\n}\n\n\nif (!window.FileReader) {\n\twindow.FileReader = function() {\n\t\tvar _this = this, loadStarted = false;\n\t\tthis.listeners = {};\n\t\tthis.addEventListener = function(type, fn) {\n\t\t\t_this.listeners[type] = _this.listeners[type] || [];\n\t\t\t_this.listeners[type].push(fn);\n\t\t};\n\t\tthis.removeEventListener = function(type, fn) {\n\t\t\t_this.listeners[type] && _this.listeners[type].splice(_this.listeners[type].indexOf(fn), 1);\n\t\t};\n\t\tthis.dispatchEvent = function(evt) {\n\t\t\tvar list = _this.listeners[evt.type];\n\t\t\tif (list) {\n\t\t\t\tfor (var i = 0; i < list.length; i++) {\n\t\t\t\t\tlist[i].call(_this, evt);\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t\tthis.onabort = this.onerror = this.onload = this.onloadstart = this.onloadend = this.onprogress = null;\n\n\t\tvar constructEvent = function(type, evt) {\n\t\t\tvar e = {type: type, target: _this, loaded: evt.loaded, total: evt.total, error: evt.error};\n\t\t\tif (evt.result != null) e.target.result = evt.result;\n\t\t\treturn e;\n\t\t};\n\t\tvar listener = function(evt) {\n\t\t\tif (!loadStarted) {\n\t\t\t\tloadStarted = true;\n\t\t\t\t_this.onloadstart && _this.onloadstart(constructEvent('loadstart', evt));\n\t\t\t}\n\t\t\tif (evt.type === 'load') {\n\t\t\t\t_this.onloadend && _this.onloadend(constructEvent('loadend', evt));\n\t\t\t\tvar e = constructEvent('load', evt);\n\t\t\t\t_this.onload && _this.onload(e);\n\t\t\t\t_this.dispatchEvent(e);\n\t\t\t} else if (evt.type === 'progress') {\n\t\t\t\tvar e = constructEvent('progress', evt);\n\t\t\t\t_this.onprogress && _this.onprogress(e);\n\t\t\t\t_this.dispatchEvent(e);\n\t\t\t} else {\n\t\t\t\tvar e = constructEvent('error', evt);\n\t\t\t\t_this.onerror && _this.onerror(e);\n\t\t\t\t_this.dispatchEvent(e);\n\t\t\t}\n\t\t};\n\t\tthis.readAsArrayBuffer = function(file) {\n\t\t\tFileAPI.readAsBinaryString(file, listener);\n\t\t}\n\t\tthis.readAsBinaryString = function(file) {\n\t\t\tFileAPI.readAsBinaryString(file, listener);\n\t\t}\n\t\tthis.readAsDataURL = function(file) {\n\t\t\tFileAPI.readAsDataURL(file, listener);\n\t\t}\n\t\tthis.readAsText = function(file) {\n\t\t\tFileAPI.readAsText(file, listener);\n\t\t}\n\t}\n}\n})();\n"
  },
  {
    "path": "flowable-ui-web/idm/libs/ng-file-upload/ng-file-upload.js",
    "content": "/**!\n * AngularJS file upload/drop directive and service with progress and abort\n * @author  Danial  <danial.farid@gmail.com>\n * @version 4.1.0\n */\n(function () {\n\nvar key, i;\nfunction patchXHR(fnName, newFn) {\n    window.XMLHttpRequest.prototype[fnName] = newFn(window.XMLHttpRequest.prototype[fnName]);\n}\n\nif (window.XMLHttpRequest && !window.XMLHttpRequest.__isFileAPIShim) {\n    patchXHR('setRequestHeader', function (orig) {\n        return function (header, value) {\n            if (header === '__setXHR_') {\n                var val = value(this);\n                // fix for angular < 1.2.0\n                if (val instanceof Function) {\n                    val(this);\n                }\n            } else {\n                orig.apply(this, arguments);\n            }\n        }\n    });\n}\n\nvar ngFileUpload = angular.module('ngFileUpload', []);\n\nngFileUpload.version = '4.1.0';\nngFileUpload.service('Upload', ['$http', '$q', '$timeout', function ($http, $q, $timeout) {\n    function sendHttp(config) {\n        config.method = config.method || 'POST';\n        config.headers = config.headers || {};\n        config.transformRequest = config.transformRequest || function (data, headersGetter) {\n            if (window.ArrayBuffer && data instanceof window.ArrayBuffer) {\n                return data;\n            }\n            return $http.defaults.transformRequest[0](data, headersGetter);\n        };\n        var deferred = $q.defer();\n        var promise = deferred.promise;\n\n        config.headers['__setXHR_'] = function () {\n            return function (xhr) {\n                if (!xhr) return;\n                config.__XHR = xhr;\n                config.xhrFn && config.xhrFn(xhr);\n                xhr.upload.addEventListener('progress', function (e) {\n                    e.config = config;\n                    deferred.notify ? deferred.notify(e) : promise.progress_fn && $timeout(function () {\n                        promise.progress_fn(e)\n                    });\n                }, false);\n                //fix for firefox not firing upload progress end, also IE8-9\n                xhr.upload.addEventListener('load', function (e) {\n                    if (e.lengthComputable) {\n                        e.config = config;\n                        deferred.notify ? deferred.notify(e) : promise.progress_fn && $timeout(function () {\n                            promise.progress_fn(e)\n                        });\n                    }\n                }, false);\n            };\n        };\n\n        $http(config).then(function (r) {\n            deferred.resolve(r)\n        }, function (e) {\n            deferred.reject(e)\n        }, function (n) {\n            deferred.notify(n)\n        });\n\n        promise.success = function (fn) {\n            promise.then(function (response) {\n                fn(response.data, response.status, response.headers, config);\n            });\n            return promise;\n        };\n\n        promise.error = function (fn) {\n            promise.then(null, function (response) {\n                fn(response.data, response.status, response.headers, config);\n            });\n            return promise;\n        };\n\n        promise.progress = function (fn) {\n            promise.progress_fn = fn;\n            promise.then(null, null, function (update) {\n                fn(update);\n            });\n            return promise;\n        };\n        promise.abort = function () {\n            if (config.__XHR) {\n                $timeout(function () {\n                    config.__XHR.abort();\n                });\n            }\n            return promise;\n        };\n        promise.xhr = function (fn) {\n            config.xhrFn = (function (origXhrFn) {\n                return function () {\n                    origXhrFn && origXhrFn.apply(promise, arguments);\n                    fn.apply(promise, arguments);\n                }\n            })(config.xhrFn);\n            return promise;\n        };\n\n        return promise;\n    }\n\n    this.upload = function (config) {\n        config.headers = config.headers || {};\n        config.headers['Content-Type'] = undefined;\n        config.transformRequest = config.transformRequest ?\n            (angular.isArray(config.transformRequest) ?\n                config.transformRequest : [config.transformRequest]) : [];\n        config.transformRequest.push(function (data) {\n            var formData = new FormData();\n            var allFields = {};\n            for (key in config.fields) {\n                if (config.fields.hasOwnProperty(key)) {\n                    allFields[key] = config.fields[key];\n                }\n            }\n            if (data) allFields['data'] = data;\n\n            if (config.formDataAppender) {\n                for (key in allFields) {\n                    if (allFields.hasOwnProperty(key)) {\n                        config.formDataAppender(formData, key, allFields[key]);\n                    }\n                }\n            } else {\n                for (key in allFields) {\n                    if (allFields.hasOwnProperty(key)) {\n                        var val = allFields[key];\n                        if (val !== undefined) {\n                            if (angular.isDate(val)) {\n                                val = val.toISOString();\n                            }\n                            if (angular.isString(val)) {\n                                formData.append(key, val);\n                            } else {\n                                if (config.sendObjectsAsJsonBlob && angular.isObject(val)) {\n                                    formData.append(key, new Blob([val], {type: 'application/json'}));\n                                } else {\n                                    formData.append(key, JSON.stringify(val));\n                                }\n                            }\n\n                        }\n                    }\n                }\n            }\n\n            if (config.file != null) {\n                var fileFormName = config.fileFormDataName || 'file';\n\n                if (angular.isArray(config.file)) {\n                    var isFileFormNameString = angular.isString(fileFormName);\n                    for (var i = 0; i < config.file.length; i++) {\n                        formData.append(isFileFormNameString ? fileFormName : fileFormName[i], config.file[i],\n                            (config.fileName && config.fileName[i]) || config.file[i].name);\n                    }\n                } else {\n                    formData.append(fileFormName, config.file, config.fileName || config.file.name);\n                }\n            }\n            return formData;\n        });\n\n        return sendHttp(config);\n    };\n\n    this.http = function (config) {\n        return sendHttp(config);\n    };\n}]);\n\nngFileUpload.directive('ngfSelect', ['$parse', '$timeout', '$compile',\n    function ($parse, $timeout, $compile) {\n        return {\n            restrict: 'AEC',\n            require: '?ngModel',\n            link: function (scope, elem, attr, ngModel) {\n                linkFileSelect(scope, elem, attr, ngModel, $parse, $timeout, $compile);\n            }\n        }\n    }]);\n\nfunction linkFileSelect(scope, elem, attr, ngModel, $parse, $timeout, $compile) {\n    function isInputTypeFile() {\n        return elem[0].tagName.toLowerCase() === 'input' && elem.attr('type') && elem.attr('type').toLowerCase() === 'file';\n    }\n    var changeFnAttr = attr.ngfChange || (attr.ngfSelect && attr.ngfSelect.indexOf('(') > 0);\n    var isUpdating = false;\n    function changeFn(evt) {\n        if (!isUpdating) {\n            isUpdating = true;\n            try {\n                var fileList = evt.__files_ || (evt.target && evt.target.files);\n                var files = [], rejFiles = [];\n\n                for (var i = 0; i < fileList.length; i++) {\n                    var file = fileList.item(i);\n                    if (validate(scope, $parse, attr, file, evt)) {\n                        files.push(file);\n                    } else {\n                        rejFiles.push(file);\n                    }\n                }\n                updateModel($parse, $timeout, scope, ngModel, attr, changeFnAttr, files, rejFiles, evt);\n                if (files.length == 0) evt.target.value = files;\n//                if (evt.target && evt.target.getAttribute('__ngf_gen__')) {\n//                    angular.element(evt.target).remove();\n//                }\n            } finally {\n                isUpdating = false;\n            }\n        }\n    }\n\n    function bindAttrToFileInput(fileElem) {\n        if (attr.ngfMultiple) fileElem.attr('multiple', $parse(attr.ngfMultiple)(scope));\n        if (!$parse(attr.ngfMultiple)(scope)) fileElem.attr('multiple', undefined);\n        if (attr['accept']) fileElem.attr('accept', attr['accept']);\n        if (attr.ngfCapture) fileElem.attr('capture', $parse(attr.ngfCapture)(scope));\n        if (attr.ngfDisabled) fileElem.attr('disabled', $parse(attr.ngfDisabled)(scope));\n        for (var i = 0; i < elem[0].attributes.length; i++) {\n            var attribute = elem[0].attributes[i];\n            if (attribute.name !== 'type' && attribute.name !== 'class' && attribute.name !== 'id' && attribute.name !== 'style') {\n            \tfileElem.attr(attribute.name, attribute.value);\n            }\n        }\n    }\n\n    function createFileInput(evt) {\n        if (elem.attr('disabled')) {\n            return;\n        }\n        var fileElem = angular.element('<input type=\"file\">');\n        bindAttrToFileInput(fileElem);\n\n        if (isInputTypeFile()) {\n            elem.replaceWith(fileElem);\n            elem = fileElem;\n        } else {\n            fileElem.css('display', 'none').attr('tabindex', '-1').attr('__ngf_gen__', true);\n            if (elem.__ngf_ref_elem__) {elem.__ngf_ref_elem__.remove();}\n            elem.__ngf_ref_elem__ = fileElem;\n            document.body.appendChild(fileElem[0]);\n        }\n\n        return fileElem;\n    }\n\n    function resetModel(evt) {\n        updateModel($parse, $timeout, scope, ngModel, attr, changeFnAttr, [], [], evt, true);\n    }\n\n    function clickHandler(evt) {\n    \tevt.preventDefault();\n        var fileElem = createFileInput(evt);\n        if (fileElem) {\n        \tfileElem.bind('change', changeFn);\n        \tresetModel(evt);\n\n        \tfunction clickAndAssign() {\n            \tfileElem[0].click();\n    \t        if (isInputTypeFile()) {\n    \t            elem.bind('click touchend', clickHandler);\n    \t            evt.preventDefault()\n    \t        }\n        \t}\n        \t\n        \t// fix for android native browser\n        \tif (navigator.userAgent.toLowerCase().match(/android/)) {\n                setTimeout(function() {\n                \tclickAndAssign();\n                }, 0);        \t\t\n        \t} else {\n        \t\tclickAndAssign();\n        \t}\n        }\n    }\n\n    if (window.FileAPI && window.FileAPI.ngfFixIE) {\n        window.FileAPI.ngfFixIE(elem, createFileInput, bindAttrToFileInput, changeFn, resetModel);\n    } else {\n        elem.bind('click touchend', clickHandler);\n    }\n}\n\nngFileUpload.directive('ngfDrop', ['$parse', '$timeout', '$location', function ($parse, $timeout, $location) {\n    return {\n        restrict: 'AEC',\n        require: '?ngModel',\n        link: function (scope, elem, attr, ngModel) {\n            linkDrop(scope, elem, attr, ngModel, $parse, $timeout, $location);\n        }\n    }\n}]);\n\nngFileUpload.directive('ngfNoFileDrop', function () {\n    return function (scope, elem) {\n        if (dropAvailable()) elem.css('display', 'none')\n    }\n});\n\nngFileUpload.directive('ngfDropAvailable', ['$parse', '$timeout', function ($parse, $timeout) {\n    return function (scope, elem, attr) {\n        if (dropAvailable()) {\n            var fn = $parse(attr.ngfDropAvailable);\n            $timeout(function () {\n                fn(scope);\n                if (fn.assign) {\n                    fn.assign(scope, true);                \t\n                }\n            });\n        }\n    }\n}]);\n\nfunction linkDrop(scope, elem, attr, ngModel, $parse, $timeout, $location) {\n    var available = dropAvailable();\n    if (attr.dropAvailable) {\n        $timeout(function () {\n        \tscope[attr.dropAvailable] ? scope[attr.dropAvailable].value = available : scope[attr.dropAvailable] = available;\n        });\n    }\n    if (!available) {\n        if ($parse(attr.ngfHideOnDropNotAvailable)(scope) == true) {\n            elem.css('display', 'none');\n        }\n        return;\n    }\n    var leaveTimeout = null;\n    var stopPropagation = $parse(attr.ngfStopPropagation);\n    var dragOverDelay = 1;\n    var accept = $parse(attr.ngfAccept);\n    var disabled = $parse(attr.ngfDisabled);\n    var actualDragOverClass;\n\n    elem[0].addEventListener('dragover', function (evt) {\n        if (disabled(scope)) return;\n        evt.preventDefault();\n        if (stopPropagation(scope)) evt.stopPropagation();\n        // handling dragover events from the Chrome download bar\n        if (navigator.userAgent.indexOf(\"Chrome\") > -1) {\n            var b = evt.dataTransfer.effectAllowed;\n            evt.dataTransfer.dropEffect = ('move' === b || 'linkMove' === b) ? 'move' : 'copy';\n        }\n        $timeout.cancel(leaveTimeout);\n        if (!scope.actualDragOverClass) {\n            actualDragOverClass = calculateDragOverClass(scope, attr, evt);\n        }\n        elem.addClass(actualDragOverClass);\n    }, false);\n    elem[0].addEventListener('dragenter', function (evt) {\n        if (disabled(scope)) return;\n        evt.preventDefault();\n        if (stopPropagation(scope)) evt.stopPropagation();\n    }, false);\n    elem[0].addEventListener('dragleave', function () {\n        if (disabled(scope)) return;\n        leaveTimeout = $timeout(function () {\n            elem.removeClass(actualDragOverClass);\n            actualDragOverClass = null;\n        }, dragOverDelay || 1);\n    }, false);\n    elem[0].addEventListener('drop', function (evt) {\n        if (disabled(scope)) return;\n        evt.preventDefault();\n        if (stopPropagation(scope)) evt.stopPropagation();\n        elem.removeClass(actualDragOverClass);\n        actualDragOverClass = null;\n        extractFiles(evt, function (files, rejFiles) {\n            updateModel($parse, $timeout, scope, ngModel, attr,\n                attr.ngfChange || (attr.ngfDrop && attr.ngfDrop.indexOf('(') > 0), files, rejFiles, evt)\n        }, $parse(attr.ngfAllowDir)(scope) != false, attr.multiple || $parse(attr.ngfMultiple)(scope));\n    }, false);\n\n    function calculateDragOverClass(scope, attr, evt) {\n        var accepted = true;\n        var items = evt.dataTransfer.items;\n        if (items != null) {\n            for (var i = 0; i < items.length && accepted; i++) {\n                accepted = accepted\n                    && (items[i].kind == 'file' || items[i].kind == '')\n                    && validate(scope, $parse, attr, items[i], evt);\n            }\n        }\n        var clazz = $parse(attr.ngfDragOverClass)(scope, {$event: evt});\n        if (clazz) {\n            if (clazz.delay) dragOverDelay = clazz.delay;\n            if (clazz.accept) clazz = accepted ? clazz.accept : clazz.reject;\n        }\n        return clazz || attr.ngfDragOverClass || 'dragover';\n    }\n\n    function extractFiles(evt, callback, allowDir, multiple) {\n        var files = [], rejFiles = [], items = evt.dataTransfer.items, processing = 0;\n\n        function addFile(file) {\n            if (validate(scope, $parse, attr, file, evt)) {\n                files.push(file);\n            } else {\n                rejFiles.push(file);\n            }\n        }\n\n        if (items && items.length > 0 && $location.protocol() != 'file') {\n            for (var i = 0; i < items.length; i++) {\n                if (items[i].webkitGetAsEntry && items[i].webkitGetAsEntry() && items[i].webkitGetAsEntry().isDirectory) {\n                    var entry = items[i].webkitGetAsEntry();\n                    if (entry.isDirectory && !allowDir) {\n                        continue;\n                    }\n                    if (entry != null) {\n                        traverseFileTree(files, entry);\n                    }\n                } else {\n                    var f = items[i].getAsFile();\n                    if (f != null) addFile(f);\n                }\n                if (!multiple && files.length > 0) break;\n            }\n        } else {\n            var fileList = evt.dataTransfer.files;\n            if (fileList != null) {\n                for (var i = 0; i < fileList.length; i++) {\n                    addFile(fileList.item(i));\n                    if (!multiple && files.length > 0) break;\n                }\n            }\n        }\n        var delays = 0;\n        (function waitForProcess(delay) {\n            $timeout(function () {\n                if (!processing) {\n                    if (!multiple && files.length > 1) {\n                        i = 0;\n                        while (files[i].type == 'directory') i++;\n                        files = [files[i]];\n                    }\n                    callback(files, rejFiles);\n                } else {\n                    if (delays++ * 10 < 20 * 1000) {\n                        waitForProcess(10);\n                    }\n                }\n            }, delay || 0)\n        })();\n\n        function traverseFileTree(files, entry, path) {\n            if (entry != null) {\n                if (entry.isDirectory) {\n                    var filePath = (path || '') + entry.name;\n                    addFile({name: entry.name, type: 'directory', path: filePath});\n                    var dirReader = entry.createReader();\n                    var entries = [];\n                    processing++;\n                    var readEntries = function () {\n                        dirReader.readEntries(function (results) {\n                            try {\n                                if (!results.length) {\n                                    for (var i = 0; i < entries.length; i++) {\n                                        traverseFileTree(files, entries[i], (path ? path : '') + entry.name + '/');\n                                    }\n                                    processing--;\n                                } else {\n                                    entries = entries.concat(Array.prototype.slice.call(results || [], 0));\n                                    readEntries();\n                                }\n                            } catch (e) {\n                                processing--;\n                                console.error(e);\n                            }\n                        }, function () {\n                            processing--;\n                        });\n                    };\n                    readEntries();\n                } else {\n                    processing++;\n                    entry.file(function (file) {\n                        try {\n                            processing--;\n                            file.path = (path ? path : '') + file.name;\n                            addFile(file);\n                        } catch (e) {\n                            processing--;\n                            console.error(e);\n                        }\n                    }, function () {\n                        processing--;\n                    });\n                }\n            }\n        }\n    }\n}\n\nngFileUpload.directive('ngfSrc', ['$parse', '$timeout', function ($parse, $timeout) {\n\treturn {\n\t\trestrict: 'AE',\n\t\tlink: function (scope, elem, attr, file) {\n\t\t\tif (window.FileReader) {\n\t\t\t\tscope.$watch(attr.ngfSrc, function(file) {\n\t\t\t\t\tif (file) {\n\t\t\t\t\t\t$timeout(function() {\n\t\t\t\t\t\t\tvar fileReader = new FileReader();\n\t\t\t\t\t\t\tfileReader.readAsDataURL(file);\n\t\t\t\t\t\t\tfileReader.onload = function(e) {\n\t\t\t\t\t\t\t\t$timeout(function() {\n\t\t\t\t\t\t\t\t\telem.attr('src', e.target.result);\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t});\n\t\t\t\t\t} else {\n\t\t\t\t\t\telem.attr('src', '');\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n}]);\n\nfunction dropAvailable() {\n    var div = document.createElement('div');\n    return ('draggable' in div) && ('ondrop' in div);\n}\n\nfunction updateModel($parse, $timeout, scope, ngModel, attr, fileChange, files, rejFiles, evt, noDelay) {\n    function update() {\n        if (ngModel) {\n            $parse(attr.ngModel).assign(scope, files);\n            $timeout(function () {\n                ngModel && ngModel.$setViewValue(files != null && files.length == 0 ? null : files);\n            });\n        }\n        if (attr.ngModelRejected) {\n            $parse(attr.ngModelRejected).assign(scope, rejFiles);\n        }\n        if (fileChange) {\n            $parse(fileChange)(scope, {\n                $files: files,\n                $rejectedFiles: rejFiles,\n                $event: evt\n            });\n\n        }\n    }\n    if (noDelay) {\n        update();\n    } else {\n        $timeout(function () {\n            update();\n        });\n    }\n}\n\nfunction validate(scope, $parse, attr, file, evt) {\n    var accept = $parse(attr.ngfAccept);\n    var fileSizeMax = $parse(attr.ngfMaxSize)(scope) || 9007199254740991;\n    var fileSizeMin = $parse(attr.ngfMinSize)(scope) || -1;\n    var val = accept(scope, {$file: file, $event: evt}), match = false;\n    if (val != null && angular.isString(val)) {\n        var regexp = new RegExp(globStringToRegex(val), 'gi');\n        match = (file.type != null && file.type.match(regexp)) ||\n        \t\t(file.name != null && file.name.match(regexp));\n    }\n    return (val == null || match) && (file.size == null || (file.size < fileSizeMax && file.size > fileSizeMin));\n}\n\nfunction globStringToRegex(str) {\n    if (str.length > 2 && str[0] === '/' && str[str.length - 1] === '/') {\n        return str.substring(1, str.length - 1);\n    }\n    var split = str.split(','), result = '';\n    if (split.length > 1) {\n        for (var i = 0; i < split.length; i++) {\n            result += '(' + globStringToRegex(split[i]) + ')';\n            if (i < split.length - 1) {\n                result += '|'\n            }\n        }\n    } else {\n        if (str.indexOf('.') == 0) {\n            str = '*' + str;\n        }\n        result = '^' + str.replace(new RegExp('[.\\\\\\\\+*?\\\\[\\\\^\\\\]$(){}=!<>|:\\\\' + '-]', 'g'), '\\\\$&') + '$';\n        result = result.replace(/\\\\\\*/g, '.*').replace(/\\\\\\?/g, '.');\n    }\n    return result;\n}\n\n})();\n"
  },
  {
    "path": "flowable-ui-web/idm/libs/sizzle_1.10.16/.bower.json",
    "content": "{\n  \"name\": \"sizzle\",\n  \"version\": \"1.10.16\",\n  \"main\": \"./dist/sizzle.js\",\n  \"devDependencies\": {\n    \"qunit\": \"~1.12.0\",\n    \"benchmark\": \"~1.0.0\",\n    \"requirejs\": \"~2.1.8\",\n    \"requirejs-domready\": \"~2.0.1\",\n    \"requirejs-text\": \"~2.0.10\"\n  },\n  \"ignore\": [\n    \"**/.*\",\n    \"package.json\",\n    \"bower.json\",\n    \"speed\",\n    \"Makefile\",\n    \"*.md\",\n    \"*.txt\",\n    \"src\",\n    \"Gruntfile.js\"\n  ],\n  \"homepage\": \"https://github.com/jquery/sizzle\",\n  \"_release\": \"1.10.16\",\n  \"_resolution\": {\n    \"type\": \"version\",\n    \"tag\": \"1.10.16\",\n    \"commit\": \"0fd151739d05648118002914c7a638411bbd0dbe\"\n  },\n  \"_source\": \"git://github.com/jquery/sizzle.git\",\n  \"_target\": \"1.10.16\",\n  \"_originalSource\": \"sizzle\"\n}"
  },
  {
    "path": "flowable-ui-web/idm/libs/sizzle_1.10.16/tasks/commit.js",
    "content": "\"use strict\";\n\nvar exec = require( \"child_process\" ).exec;\n\nmodule.exports = function( grunt ) {\n\tgrunt.registerTask( \"commit\", \"Add and commit changes\", function( message ) {\n\t\t// Always add dist directory\n\t\texec( \"git add dist && git commit -m \" + message, this.async() );\n\t});\n};\n"
  },
  {
    "path": "flowable-ui-web/idm/libs/sizzle_1.10.16/tasks/compile.js",
    "content": "\"use strict\";\n\nmodule.exports = function( grunt ) {\n\tgrunt.registerMultiTask(\n\t\t\"compile\",\n\t\t\"Compile sizzle.js to the dist directory. Embed date/version.\",\n\t\tfunction() {\n\t\t\tvar data = this.data,\n\t\t\t\tdest = data.dest,\n\t\t\t\tsrc = data.src,\n\t\t\t\tversion = grunt.config( \"pkg.version\" ),\n\t\t\t\tcompiled = grunt.file.read( src );\n\n\t\t\t// Embed version and date\n\t\t\tcompiled = compiled\n\t\t\t\t.replace( /@VERSION/g, version )\n\t\t\t\t.replace( \"@DATE\", function() {\n\t\t\t\t\tvar date = new Date();\n\n\t\t\t\t\t// YYYY-MM-DD\n\t\t\t\t\treturn [\n\t\t\t\t\t\tdate.getFullYear(),\n\t\t\t\t\t\t( \"0\" + ( date.getMonth() + 1 ) ).slice( -2 ),\n\t\t\t\t\t\t( \"0\" + date.getDate() ).slice( -2 )\n\t\t\t\t\t].join( \"-\" );\n\t\t\t\t});\n\n\t\t\t// Write source to file\n\t\t\tgrunt.file.write( dest, compiled );\n\n\t\t\tgrunt.log.ok( \"File written to \" + dest );\n\t\t}\n\t);\n};\n"
  },
  {
    "path": "flowable-ui-web/idm/libs/sizzle_1.10.16/tasks/dist.js",
    "content": "\"use strict\";\n\nvar fs = require( \"fs\" );\n\nmodule.exports = function( grunt ) {\n\tgrunt.registerTask( \"dist\", \"Process files for distribution\", function() {\n\t\tvar files = grunt.file.expand( { filter: \"isFile\" }, \"dist/*\" );\n\n\t\tfiles.forEach(function( filename ) {\n\t\t\tvar map,\n\t\t\t\ttext = fs.readFileSync( filename, \"utf8\" );\n\n\t\t\t// Modify map/min so that it points to files in the same folder;\n\t\t\t// see https://github.com/mishoo/UglifyJS2/issues/47\n\t\t\tif ( /\\.map$/.test( filename ) ) {\n\t\t\t\ttext = text.replace( /\"dist\\//g, \"\\\"\" );\n\t\t\t\tfs.writeFileSync( filename, text, \"utf-8\" );\n\t\t\t} else if ( /\\.min\\.js$/.test( filename ) ) {\n\t\t\t\t// Wrap sourceMap directive in multiline comments (#13274)\n\t\t\t\ttext = text.replace( /\\n?(\\/\\/@\\s*sourceMappingURL=)(.*)/,\n\t\t\t\t\tfunction( _, directive, path ) {\n\t\t\t\t\t\tmap = \"\\n\" + directive + path.replace( /^dist\\//, \"\" );\n\t\t\t\t\t\treturn \"\";\n\t\t\t\t\t});\n\t\t\t\tif ( map ) {\n\t\t\t\t\ttext = text.replace( /(^\\/\\*[\\w\\W]*?)\\s*\\*\\/|$/,\n\t\t\t\t\t\tfunction( _, comment ) {\n\t\t\t\t\t\t\treturn ( comment || \"\\n/*\" ) + map + \"\\n*/\";\n\t\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tfs.writeFileSync( filename, text, \"utf-8\" );\n\t\t\t}\n\t\t});\n\t});\n};\n"
  },
  {
    "path": "flowable-ui-web/idm/libs/sizzle_1.10.16/tasks/release.js",
    "content": "\"use strict\";\n\nvar exec = require( \"child_process\" ).exec;\n\nmodule.exports = function( grunt ) {\n\tvar rpreversion = /(\\d\\.\\d+\\.\\d+)-pre/;\n\n\tgrunt.registerTask( \"release\",\n\t\t\"Release a version of sizzle, updates a pre version to released, \" +\n\t\t\"inserts `next` as the new pre version\", function( next ) {\n\t\t\n\t\tif ( !rpreversion.test( next ) ) {\n\t\t\tgrunt.fatal( \"Next version should be a -pre version (x.x.x-pre): \" + next );\n\t\t\treturn;\n\t\t}\n\n\t\tvar done,\n\t\t\tversion = grunt.config( \"pkg.version\" );\n\t\tif ( !rpreversion.test( version ) ) {\n\t\t\tgrunt.fatal( \"Existing version is not a pre version: \" + version );\n\t\t\treturn;\n\t\t}\n\t\tversion = version.replace( rpreversion, \"$1\" );\n\n\t\tdone = this.async();\n\t\texec( \"git diff --quiet HEAD\", function( err ) {\n\t\t\tif ( err ) {\n\t\t\t\tgrunt.fatal( \"The working directory should be clean when releasing. Commit or stash changes.\" );\n\t\t\t\treturn;\n\t\t\t}\n\t\t\t// Build to dist directories along with a map and tag the release\n\t\t\tgrunt.task.run([\n\t\t\t\t// Commit new version\n\t\t\t\t\"version:\" + version,\n\t\t\t\t// Tag new version\n\t\t\t\t\"tag:\" + version,\n\t\t\t\t// Commit next version\n\t\t\t\t\"version:\" + next\n\t\t\t]);\n\t\t\tdone();\n\t\t});\n\t});\n};\n"
  },
  {
    "path": "flowable-ui-web/idm/libs/sizzle_1.10.16/tasks/tag.js",
    "content": "\"use strict\";\n\nvar exec = require( \"child_process\" ).exec;\n\nmodule.exports = function( grunt ) {\n\tgrunt.registerTask( \"tag\", \"Tag the specified version\", function( version ) {\n\t\texec( \"git tag \" + version, this.async() );\n\t});\n};\n"
  },
  {
    "path": "flowable-ui-web/idm/libs/sizzle_1.10.16/tasks/version.js",
    "content": "\"use strict\";\n\nvar exec = require( \"child_process\" ).exec;\n\nmodule.exports = function( grunt ) {\n\tgrunt.registerTask( \"version\", \"Commit a new version\", function( version ) {\n\t\tif ( !/\\d\\.\\d+\\.\\d+(?:-pre)?/.test( version ) ) {\n\t\t\tgrunt.fatal( \"Version must follow semver release format: \" + version );\n\t\t\treturn;\n\t\t}\n\n\t\tvar done = this.async(),\n\t\t\tfiles = grunt.config( \"version.files\" ),\n\t\t\trversion = /(\"version\":\\s*\")[^\"]+/;\n\n\t\t// Update version in specified files\n\t\tfiles.forEach(function( filename ) {\n\t\t\tvar text = grunt.file.read( filename );\n\t\t\ttext = text.replace( rversion, \"$1\" + version );\n\t\t\tgrunt.file.write( filename, text );\n\t\t});\n\n\t\t// Add files to git index\n\t\texec( \"git add -A\", function( err ) {\n\t\t\tif ( err ) {\n\t\t\t\tgrunt.fatal( err );\n\t\t\t\treturn;\n\t\t\t}\n\t\t\t// Commit next pre version\n\t\t\tgrunt.config( \"pkg.version\", version );\n\t\t\tgrunt.task.run([ \"build\", \"uglify\", \"dist\", \"commit:'Update version to \" + version + \"'\" ]);\n\t\t\tdone();\n\t\t});\n\t});\n};\n"
  },
  {
    "path": "flowable-ui-web/idm/libs/sizzle_1.10.16/test/data/empty.js",
    "content": ""
  },
  {
    "path": "flowable-ui-web/idm/libs/sizzle_1.10.16/test/data/mixed_sort.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />\n\t<script>var QUnit = parent.QUnit</script>\n\t<script src=\"testinit.js\"></script>\n\t<script src=\"../../dist/sizzle.js\"></script>\n</head>\n<body>\n\t<script>\n\t\tvar doc = parent.document,\n\t\t\tunframed = [ doc.getElementById( \"qunit-fixture\" ), doc.body, doc.documentElement ],\n\t\t\tframed = Sizzle( \"*\" );\n\n\t\twindow.parent.iframeCallback(\n\t\t\tSizzle.uniqueSort( unframed.concat( framed ) ),\n\t\t\tframed.concat( unframed.reverse() ),\n\t\t\t\"Mixed array was sorted correctly\"\n\t\t);\n\t</script>\n</body>\n</html>\n"
  },
  {
    "path": "flowable-ui-web/idm/libs/sizzle_1.10.16/test/data/testinit.js",
    "content": "var fireNative,\n\tjQuery = this.jQuery || \"jQuery\", // For testing .noConflict()\n\t$ = this.$ || \"$\",\n\toriginaljQuery = jQuery,\n\toriginal$ = $;\n\n(function() {\n\t// Config parameter to force basic code paths\n\tQUnit.config.urlConfig.push({\n\t\tid: \"basic\",\n\t\tlabel: \"Bypass optimizations\",\n\t\ttooltip: \"Force use of the most basic code by disabling native querySelectorAll; contains; compareDocumentPosition\"\n\t});\n\tif ( QUnit.urlParams.basic ) {\n\t\tdocument.querySelectorAll = null;\n\t\tdocument.documentElement.contains = null;\n\t\tdocument.documentElement.compareDocumentPosition = null;\n\t\t// Return array of length two to pass assertion\n\t\t// But support should be false as its not native\n\t\tdocument.getElementsByClassName = function() { return [ 0, 1 ]; };\n\t}\n})();\n\n/**\n * Returns an array of elements with the given IDs\n * @example q(\"main\", \"foo\", \"bar\")\n * @result [<div id=\"main\">, <span id=\"foo\">, <input id=\"bar\">]\n */\nfunction q() {\n\tvar r = [],\n\t\ti = 0;\n\n\tfor ( ; i < arguments.length; i++ ) {\n\t\tr.push( document.getElementById( arguments[i] ) );\n\t}\n\treturn r;\n}\n\n/**\n * Asserts that a select matches the given IDs\n * @param {String} a - Assertion name\n * @param {String} b - Sizzle selector\n * @param {String} c - Array of ids to construct what is expected\n * @example t(\"Check for something\", \"//[a]\", [\"foo\", \"baar\"]);\n * @result returns true if \"//[a]\" return two elements with the IDs 'foo' and 'baar'\n */\nfunction t( a, b, c ) {\n\tvar f = Sizzle(b),\n\t\ts = \"\",\n\t\ti = 0;\n\n\tfor ( ; i < f.length; i++ ) {\n\t\ts += ( s && \",\" ) + '\"' + f[ i ].id + '\"';\n\t}\n\n\tdeepEqual(f, q.apply( q, c ), a + \" (\" + b + \")\");\n}\n\n/**\n * Add random number to url to stop caching\n *\n * @example url(\"data/test.html\")\n * @result \"data/test.html?10538358428943\"\n *\n * @example url(\"data/test.php?foo=bar\")\n * @result \"data/test.php?foo=bar&10538358345554\"\n */\nfunction url( value ) {\n\treturn value + (/\\?/.test(value) ? \"&\" : \"?\") + new Date().getTime() + \"\" + parseInt(Math.random()*100000);\n}\n\nvar createWithFriesXML = function() {\n\tvar string = '<?xml version=\"1.0\" encoding=\"UTF-8\"?> \\\n\t<soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\" \\\n\t\txmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" \\\n\t\txmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"> \\\n\t\t<soap:Body> \\\n\t\t\t<jsconf xmlns=\"http://www.example.com/ns1\"> \\\n\t\t\t\t<response xmlns:ab=\"http://www.example.com/ns2\"> \\\n\t\t\t\t\t<meta> \\\n\t\t\t\t\t\t<component id=\"seite1\" class=\"component\"> \\\n\t\t\t\t\t\t\t<properties xmlns:cd=\"http://www.example.com/ns3\"> \\\n\t\t\t\t\t\t\t\t<property name=\"prop1\"> \\\n\t\t\t\t\t\t\t\t\t<thing /> \\\n\t\t\t\t\t\t\t\t\t<value>1</value> \\\n\t\t\t\t\t\t\t\t</property> \\\n\t\t\t\t\t\t\t\t<property name=\"prop2\"> \\\n\t\t\t\t\t\t\t\t\t<thing att=\"something\" /> \\\n\t\t\t\t\t\t\t\t</property> \\\n\t\t\t\t\t\t\t\t<foo_bar>foo</foo_bar> \\\n\t\t\t\t\t\t\t</properties> \\\n\t\t\t\t\t\t</component> \\\n\t\t\t\t\t</meta> \\\n\t\t\t\t</response> \\\n\t\t\t</jsconf> \\\n\t\t</soap:Body> \\\n\t</soap:Envelope>';\n\n\treturn jQuery.parseXML( string );\n};\n\nfireNative = document.createEvent ?\n\tfunction( node, type ) {\n\t\tvar event = document.createEvent(\"HTMLEvents\");\n\t\tevent.initEvent( type, true, true );\n\t\tnode.dispatchEvent( event );\n\t} :\n\tfunction( node, type ) {\n\t\tvar event = document.createEventObject();\n\t\tnode.fireEvent( \"on\" + type, event );\n\t};\n\nfunction testIframeWithCallback( title, fileName, func ) {\n\ttest( title, function() {\n\t\tvar iframe;\n\n\t\tstop();\n\t\twindow.iframeCallback = function() {\n\t\t\tvar self = this,\n\t\t\t\targs = arguments;\n\t\t\tsetTimeout(function() {\n\t\t\t\twindow.iframeCallback = undefined;\n\t\t\t\tiframe.remove();\n\t\t\t\tfunc.apply( self, args );\n\t\t\t\tfunc = function() {};\n\t\t\t\tstart();\n\t\t\t}, 0 );\n\t\t};\n\t\tiframe = jQuery( \"<div/>\" ).css({ position: \"absolute\", width: \"500px\", left: \"-600px\" })\n\t\t\t.append( jQuery( \"<iframe/>\" ).attr( \"src\", url( \"./data/\" + fileName ) ) )\n\t\t\t.appendTo( \"#qunit-fixture\" );\n\t});\n};\nwindow.iframeCallback = undefined;\n\nfunction moduleTeardown() {}\n"
  },
  {
    "path": "flowable-ui-web/idm/libs/sizzle_1.10.16/test/index.html",
    "content": "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\" dir=\"ltr\" id=\"html\">\n<head>\n\t<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />\n\t<title>Sizzle Test Suite</title>\n\t<link rel=\"Stylesheet\" media=\"screen\" href=\"libs/qunit/qunit.css\" />\n\t<script type=\"text/javascript\" src=\"libs/qunit/qunit.js\"></script>\n\t<script type=\"text/javascript\" src=\"data/testinit.js\"></script>\n\t<script type=\"text/javascript\" src=\"jquery.js\"></script>\n\t<script type=\"text/javascript\" src=\"../dist/sizzle.js\"></script>\n\t<script type=\"text/javascript\" src=\"unit/selector.js\"></script>\n\t<script type=\"text/javascript\" src=\"unit/utilities.js\"></script>\n\t<script type=\"text/javascript\" src=\"unit/extending.js\"></script>\n</head>\n\n<body id=\"body\">\n\t<div id=\"qunit\"></div>\n\n\t<!-- Test HTML -->\n\t<dl id=\"dl\" style=\"position:absolute;top:-32767px;left:-32767px;width:1px\">\n\t<div id=\"qunit-fixture\">\n\t\t<p id=\"firstp\">See <a id=\"simon1\" href=\"http://simon.incutio.com/archive/2003/03/25/#getElementsBySelector\" rel=\"bookmark\">this blog entry</a> for more information.</p>\n\t\t<p id=\"ap\">\n\t\t\tHere are some [links] in a normal paragraph: <a id=\"google\" href=\"http://www.google.com/\" title=\"Google!\">Google</a>,\n\t\t\t<a id=\"groups\" href=\"http://groups.google.com/\" class=\"GROUPS\">Google Groups (Link)</a>.\n\t\t\tThis link has <code id=\"code1\"><a href=\"http://smin\" id=\"anchor1\">class=\"blog\"</a></code>:\n\t\t\t<a href=\"http://diveintomark.org/\" class=\"blog\" hreflang=\"en\" id=\"mark\">diveintomark</a>\n\n\t\t</p>\n\t\t<div id=\"foo\">\n\t\t\t<p id=\"sndp\">Everything inside the red border is inside a div with <code>id=\"foo\"</code>.</p>\n\t\t\t<p lang=\"en\" id=\"en\">This is a normal link: <a id=\"yahoo\" href=\"http://www.yahoo.com/\" class=\"blogTest\">Yahoo</a></p>\n\t\t\t<p id=\"sap\">This link has <code><a href=\"#2\" id=\"anchor2\">class=\"blog\"</a></code>: <a href=\"http://simon.incutio.com/\" class=\"blog link\" id=\"simon\">Simon Willison's Weblog</a></p>\n\n\t\t</div>\n\t\t<div id=\"nothiddendiv\" style=\"height:1px;background:white;\" class=\"nothiddendiv\">\n\t\t\t<div id=\"nothiddendivchild\"></div>\n\t\t</div>\n\t\t<span id=\"name+value\"></span>\n\t\t<p id=\"first\">Try them out:</p>\n\t\t<ul id=\"firstUL\"></ul>\n\t\t<ol id=\"empty\"><!-- comment --></ol>\n\t\t<form id=\"form\" action=\"formaction\">\n\t\t\t<label for=\"action\" id=\"label-for\">Action:</label>\n\t\t\t<input type=\"text\" name=\"action\" value=\"Test\" id=\"text1\" maxlength=\"30\"/>\n\t\t\t<input type=\"text\" name=\"text2\" value=\"Test\" id=\"text2\" disabled=\"disabled\"/>\n\t\t\t<input type=\"radio\" name=\"radio1\" id=\"radio1\" value=\"on\"/>\n\n\t\t\t<input type=\"radio\" name=\"radio2\" id=\"radio2\" checked=\"checked\"/>\n\t\t\t<input type=\"checkbox\" name=\"check\" id=\"check1\" checked=\"checked\"/>\n\t\t\t<input type=\"checkbox\" id=\"check2\" value=\"on\"/>\n\n\t\t\t<input type=\"hidden\" name=\"hidden\" id=\"hidden1\"/>\n\t\t\t<input type=\"text\" style=\"display:none;\" name=\"foo[bar]\" id=\"hidden2\"/>\n\n\t\t\t<input type=\"text\" id=\"name\" name=\"name\" value=\"name\" />\n\t\t\t<input type=\"search\" id=\"search\" name=\"search\" value=\"search\" />\n\n\t\t\t<button id=\"button\" name=\"button\" type=\"button\">Button</button>\n\n\t\t\t<textarea id=\"area1\" maxlength=\"30\">foobar</textarea>\n\n\t\t\t<select name=\"select1\" id=\"select1\">\n\t\t\t\t<option id=\"option1a\" class=\"emptyopt\" value=\"\">Nothing</option>\n\t\t\t\t<option id=\"option1b\" value=\"1\">1</option>\n\t\t\t\t<option id=\"option1c\" value=\"2\">2</option>\n\t\t\t\t<option id=\"option1d\" value=\"3\">3</option>\n\t\t\t</select>\n\t\t\t<select name=\"select2\" id=\"select2\">\n\t\t\t\t<option id=\"option2a\" class=\"emptyopt\" value=\"\">Nothing</option>\n\t\t\t\t<option id=\"option2b\" value=\"1\">1</option>\n\t\t\t\t<option id=\"option2c\" value=\"2\">2</option>\n\t\t\t\t<option id=\"option2d\" selected=\"selected\" value=\"3\">3</option>\n\t\t\t</select>\n\t\t\t<select name=\"select3\" id=\"select3\" multiple=\"multiple\">\n\t\t\t\t<option id=\"option3a\" class=\"emptyopt\" value=\"\">Nothing</option>\n\t\t\t\t<option id=\"option3b\" selected=\"selected\" value=\"1\">1</option>\n\t\t\t\t<option id=\"option3c\" selected=\"selected\" value=\"2\">2</option>\n\t\t\t\t<option id=\"option3d\" value=\"3\">3</option>\n\t\t\t\t<option id=\"option3e\">no value</option>\n\t\t\t</select>\n\t\t\t<select name=\"select4\" id=\"select4\" multiple=\"multiple\">\n\t\t\t\t<optgroup disabled=\"disabled\">\n\t\t\t\t\t<option id=\"option4a\" class=\"emptyopt\" value=\"\">Nothing</option>\n\t\t\t\t\t<option id=\"option4b\" disabled=\"disabled\" selected=\"selected\" value=\"1\">1</option>\n\t\t\t\t\t<option id=\"option4c\" selected=\"selected\" value=\"2\">2</option>\n\t\t\t\t</optgroup>\n\t\t\t\t<option selected=\"selected\" disabled=\"disabled\" id=\"option4d\" value=\"3\">3</option>\n\t\t\t\t<option id=\"option4e\">no value</option>\n\t\t\t</select>\n\t\t\t<select name=\"select5\" id=\"select5\">\n\t\t\t\t<option id=\"option5a\" value=\"3\">1</option>\n\t\t\t\t<option id=\"option5b\" value=\"2\">2</option>\n\t\t\t\t<option id=\"option5c\" value=\"1\">3</option>\n\t\t\t</select>\n\n\t\t\t<object id=\"object1\" codebase=\"stupid\">\n\t\t\t\t<param name=\"p1\" value=\"x1\" />\n\t\t\t\t<param name=\"p2\" value=\"x2\" />\n\t\t\t</object>\n\n\t\t\t<span id=\"台北Táiběi\"></span>\n\t\t\t<span id=\"台北\" lang=\"中文\"></span>\n\t\t\t<span id=\"utf8class1\" class=\"台北Táiběi 台北\"></span>\n\t\t\t<span id=\"utf8class2\" class=\"台北\"></span>\n\t\t\t<span id=\"foo:bar\" class=\"foo:bar\"><span id=\"foo_descendent\"></span></span>\n\t\t\t<span id=\"test.foo[5]bar\" class=\"test.foo[5]bar\"></span>\n\n\t\t\t<foo_bar id=\"foobar\">test element</foo_bar>\n\t\t</form>\n\t\t<b id=\"floatTest\">Float test.</b>\n\t\t<iframe id=\"iframe\" name=\"iframe\"></iframe>\n\t\t<form id=\"lengthtest\">\n\t\t\t<input type=\"text\" id=\"length\" name=\"test\"/>\n\t\t\t<input type=\"text\" id=\"idTest\" name=\"id\"/>\n\t\t</form>\n\t\t<table id=\"table\"></table>\n\n\t\t<form id=\"name-tests\">\n\t\t\t<!-- Inputs with a grouped name attribute. -->\n\t\t\t<input name=\"types[]\" id=\"types_all\" type=\"checkbox\" value=\"all\" />\n\t\t\t<input name=\"types[]\" id=\"types_anime\" type=\"checkbox\" value=\"anime\" />\n\t\t\t<input name=\"types[]\" id=\"types_movie\" type=\"checkbox\" value=\"movie\" />\n\t\t</form>\n\n\t\t<form id=\"testForm\" action=\"#\" method=\"get\">\n\t\t\t<textarea name=\"T3\" rows=\"2\" cols=\"15\">?\nZ</textarea>\n\t\t\t<input type=\"hidden\" name=\"H1\" value=\"x\" />\n\t\t\t<input type=\"hidden\" name=\"H2\" />\n\t\t\t<input name=\"PWD\" type=\"password\" value=\"\" />\n\t\t\t<input name=\"T1\" type=\"text\" />\n\t\t\t<input name=\"T2\" type=\"text\" value=\"YES\" readonly=\"readonly\" />\n\t\t\t<input type=\"checkbox\" name=\"C1\" value=\"1\" />\n\t\t\t<input type=\"checkbox\" name=\"C2\" />\n\t\t\t<input type=\"radio\" name=\"R1\" value=\"1\" />\n\t\t\t<input type=\"radio\" name=\"R1\" value=\"2\" />\n\t\t\t<input type=\"text\" name=\"My Name\" value=\"me\" />\n\t\t\t<input type=\"reset\" name=\"reset\" value=\"NO\" />\n\t\t\t<select name=\"S1\">\n\t\t\t\t<option value=\"abc\">ABC</option>\n\t\t\t\t<option value=\"abc\">ABC</option>\n\t\t\t\t<option value=\"abc\">ABC</option>\n\t\t\t</select>\n\t\t\t<select name=\"S2\" multiple=\"multiple\" size=\"3\">\n\t\t\t\t<option value=\"abc\">ABC</option>\n\t\t\t\t<option value=\"abc\">ABC</option>\n\t\t\t\t<option value=\"abc\">ABC</option>\n\t\t\t</select>\n\t\t\t<select name=\"S3\">\n\t\t\t\t<option selected=\"selected\">YES</option>\n\t\t\t</select>\n\t\t\t<select name=\"S4\">\n\t\t\t\t<option value=\"\" selected=\"selected\">NO</option>\n\t\t\t</select>\n\t\t\t<input type=\"submit\" name=\"sub1\" value=\"NO\" />\n\t\t\t<input type=\"submit\" name=\"sub2\" value=\"NO\" />\n\t\t\t<input type=\"image\" name=\"sub3\" value=\"NO\" />\n\t\t\t<button name=\"sub4\" type=\"submit\" value=\"NO\">NO</button>\n\t\t\t<input name=\"D1\" type=\"text\" value=\"NO\" disabled=\"disabled\" />\n\t\t\t<input type=\"checkbox\" checked=\"checked\" disabled=\"disabled\" name=\"D2\" value=\"NO\" />\n\t\t\t<input type=\"radio\" name=\"D3\" value=\"NO\" checked=\"checked\" disabled=\"disabled\" />\n\t\t\t<select name=\"D4\" disabled=\"disabled\">\n\t\t\t\t<option selected=\"selected\" value=\"NO\">NO</option>\n\t\t\t</select>\n\t\t\t<input id=\"list-test\" type=\"text\" />\n\t\t\t<datalist id=\"datalist\">\n\t\t\t\t<option value=\"option\"></option>\n\t\t\t</datalist>\n\t\t</form>\n\t\t<div id=\"moretests\">\n\t\t\t<form>\n\t\t\t\t<div id=\"checkedtest\" style=\"display:none;\">\n\t\t\t\t\t<input type=\"radio\" name=\"checkedtestradios\" checked=\"checked\"/>\n\t\t\t\t\t<input type=\"radio\" name=\"checkedtestradios\" value=\"on\"/>\n\t\t\t\t\t<input type=\"checkbox\" name=\"checkedtestcheckboxes\" checked=\"checked\"/>\n\t\t\t\t\t<input type=\"checkbox\" name=\"checkedtestcheckboxes\" />\n\t\t\t\t</div>\n\t\t\t</form>\n\t\t\t<div id=\"nonnodes\"><span>hi</span> there <!-- mon ami --></div>\n\t\t\t<div id=\"t2037\">\n\t\t\t\t<div><div class=\"hidden\">hidden</div></div>\n\t\t\t</div>\n\t\t\t<div id=\"t6652\">\n\t\t\t\t<div></div>\n\t\t\t</div>\n\t\t\t<div id=\"t12087\">\n\t\t\t\t<input type=\"hidden\" id=\"el12087\" data-comma=\"0,1\"/>\n\t\t\t</div>\n\t\t\t<div id=\"no-clone-exception\"><object><embed></embed></object></div>\n\t\t\t<div id=\"names-group\">\n\t\t\t\t<span id=\"name-is-example\" name=\"example\"></span>\n\t\t\t\t<span id=\"name-is-div\" name=\"div\"></span>\n\t\t\t</div>\n\t\t\t<script id=\"script-no-src\"></script>\n\t\t\t<script id=\"script-src\" src=\"data/empty.js\"></script>\n\t\t\t<div id=\"id-name-tests\">\n\t\t\t\t<a id=\"tName1ID\" name=\"tName1\"><span></span></a>\n\t\t\t\t<a id=\"tName2ID\" name=\"tName2\"><span></span></a>\n\t\t\t\t<div id=\"tName1\"><span id=\"tName1-span\">C</span></div>\n\t\t\t</div>\n\t\t</div>\n\n\t\t<div id=\"tabindex-tests\">\n\t\t\t<ol id=\"listWithTabIndex\" tabindex=\"5\">\n\t\t\t\t<li id=\"foodWithNegativeTabIndex\" tabindex=\"-1\">Rice</li>\n\t\t\t\t<li id=\"foodNoTabIndex\">Beans</li>\n\t\t\t\t<li>Blinis</li>\n\t\t\t\t<li>Tofu</li>\n\t\t\t</ol>\n\n\t\t\t<div id=\"divWithNoTabIndex\">I'm hungry. I should...</div>\n\t\t\t<span>...</span><a href=\"#\" id=\"linkWithNoTabIndex\">Eat lots of food</a><span>...</span> |\n\t\t\t<span>...</span><a href=\"#\" id=\"linkWithTabIndex\" tabindex=\"2\">Eat a little food</a><span>...</span> |\n\t\t\t<span>...</span><a href=\"#\" id=\"linkWithNegativeTabIndex\" tabindex=\"-1\">Eat no food</a><span>...</span>\n\t\t\t<span>...</span><a id=\"linkWithNoHrefWithNoTabIndex\">Eat a burger</a><span>...</span>\n\t\t\t<span>...</span><a id=\"linkWithNoHrefWithTabIndex\" tabindex=\"1\">Eat some funyuns</a><span>...</span>\n\t\t\t<span>...</span><a id=\"linkWithNoHrefWithNegativeTabIndex\" tabindex=\"-1\">Eat some funyuns</a><span>...</span>\n\t\t</div>\n\n\t\t<div id=\"liveHandlerOrder\">\n\t\t\t<span id=\"liveSpan1\"><a href=\"#\" id=\"liveLink1\"></a></span>\n\t\t\t<span id=\"liveSpan2\"><a href=\"#\" id=\"liveLink2\"></a></span>\n\t\t</div>\n\n\t\t<div id=\"siblingTest\">\n\t\t\t<em id=\"siblingfirst\">1</em>\n\t\t\t<em id=\"siblingnext\">2</em>\n\t\t\t<em id=\"siblingthird\">\n\t\t\t\t<em id=\"siblingchild\">\n\t\t\t\t\t<em id=\"siblinggrandchild\">\n\t\t\t\t\t\t<em id=\"siblinggreatgrandchild\"></em>\n\t\t\t\t\t</em>\n\t\t\t\t</em>\n\t\t\t</em>\n\t\t\t<span id=\"siblingspan\"></span>\n\t\t</div>​\n\t</div>\n\t</dl>\n\t<br id=\"last\"/>\n</body>\n</html>\n"
  },
  {
    "path": "flowable-ui-web/idm/libs/sizzle_1.10.16/test/jquery.js",
    "content": "/*!\n * jQuery JavaScript Library v1.9.1\n * http://jquery.com/\n *\n * Includes Sizzle.js\n * http://sizzlejs.com/\n *\n * Copyright 2005, 2012 jQuery Foundation, Inc. and other contributors\n * Released under the MIT license\n * http://jquery.org/license\n *\n * Date: 2013-2-4\n */\n(function( window, undefined ) {\n\n// Can't do this because several apps including ASP.NET trace\n// the stack via arguments.caller.callee and Firefox dies if\n// you try to trace through \"use strict\" call chains. (#13335)\n// Support: Firefox 18+\n//\"use strict\";\nvar\n\t// The deferred used on DOM ready\n\treadyList,\n\n\t// A central reference to the root jQuery(document)\n\trootjQuery,\n\n\t// Support: IE<9\n\t// For `typeof node.method` instead of `node.method !== undefined`\n\tcore_strundefined = typeof undefined,\n\n\t// Use the correct document accordingly with window argument (sandbox)\n\tdocument = window.document,\n\tlocation = window.location,\n\n\t// Map over jQuery in case of overwrite\n\t_jQuery = window.jQuery,\n\n\t// Map over the $ in case of overwrite\n\t_$ = window.$,\n\n\t// [[Class]] -> type pairs\n\tclass2type = {},\n\n\t// List of deleted data cache ids, so we can reuse them\n\tcore_deletedIds = [],\n\n\tcore_version = \"1.9.1\",\n\n\t// Save a reference to some core methods\n\tcore_concat = core_deletedIds.concat,\n\tcore_push = core_deletedIds.push,\n\tcore_slice = core_deletedIds.slice,\n\tcore_indexOf = core_deletedIds.indexOf,\n\tcore_toString = class2type.toString,\n\tcore_hasOwn = class2type.hasOwnProperty,\n\tcore_trim = core_version.trim,\n\n\t// Define a local copy of jQuery\n\tjQuery = function( selector, context ) {\n\t\t// The jQuery object is actually just the init constructor 'enhanced'\n\t\treturn new jQuery.fn.init( selector, context, rootjQuery );\n\t},\n\n\t// Used for matching numbers\n\tcore_pnum = /[+-]?(?:\\d*\\.|)\\d+(?:[eE][+-]?\\d+|)/.source,\n\n\t// Used for splitting on whitespace\n\tcore_rnotwhite = /\\S+/g,\n\n\t// Make sure we trim BOM and NBSP (here's looking at you, Safari 5.0 and IE)\n\trtrim = /^[\\s\\uFEFF\\xA0]+|[\\s\\uFEFF\\xA0]+$/g,\n\n\t// A simple way to check for HTML strings\n\t// Prioritize #id over <tag> to avoid XSS via location.hash (#9521)\n\t// Strict HTML recognition (#11290: must start with <)\n\trquickExpr = /^(?:(<[\\w\\W]+>)[^>]*|#([\\w-]*))$/,\n\n\t// Match a standalone tag\n\trsingleTag = /^<(\\w+)\\s*\\/?>(?:<\\/\\1>|)$/,\n\n\t// JSON RegExp\n\trvalidchars = /^[\\],:{}\\s]*$/,\n\trvalidbraces = /(?:^|:|,)(?:\\s*\\[)+/g,\n\trvalidescape = /\\\\(?:[\"\\\\\\/bfnrt]|u[\\da-fA-F]{4})/g,\n\trvalidtokens = /\"[^\"\\\\\\r\\n]*\"|true|false|null|-?(?:\\d+\\.|)\\d+(?:[eE][+-]?\\d+|)/g,\n\n\t// Matches dashed string for camelizing\n\trmsPrefix = /^-ms-/,\n\trdashAlpha = /-([\\da-z])/gi,\n\n\t// Used by jQuery.camelCase as callback to replace()\n\tfcamelCase = function( all, letter ) {\n\t\treturn letter.toUpperCase();\n\t},\n\n\t// The ready event handler\n\tcompleted = function( event ) {\n\n\t\t// readyState === \"complete\" is good enough for us to call the dom ready in oldIE\n\t\tif ( document.addEventListener || event.type === \"load\" || document.readyState === \"complete\" ) {\n\t\t\tdetach();\n\t\t\tjQuery.ready();\n\t\t}\n\t},\n\t// Clean-up method for dom ready events\n\tdetach = function() {\n\t\tif ( document.addEventListener ) {\n\t\t\tdocument.removeEventListener( \"DOMContentLoaded\", completed, false );\n\t\t\twindow.removeEventListener( \"load\", completed, false );\n\n\t\t} else {\n\t\t\tdocument.detachEvent( \"onreadystatechange\", completed );\n\t\t\twindow.detachEvent( \"onload\", completed );\n\t\t}\n\t};\n\njQuery.fn = jQuery.prototype = {\n\t// The current version of jQuery being used\n\tjquery: core_version,\n\n\tconstructor: jQuery,\n\tinit: function( selector, context, rootjQuery ) {\n\t\tvar match, elem;\n\n\t\t// HANDLE: $(\"\"), $(null), $(undefined), $(false)\n\t\tif ( !selector ) {\n\t\t\treturn this;\n\t\t}\n\n\t\t// Handle HTML strings\n\t\tif ( typeof selector === \"string\" ) {\n\t\t\tif ( selector.charAt(0) === \"<\" && selector.charAt( selector.length - 1 ) === \">\" && selector.length >= 3 ) {\n\t\t\t\t// Assume that strings that start and end with <> are HTML and skip the regex check\n\t\t\t\tmatch = [ null, selector, null ];\n\n\t\t\t} else {\n\t\t\t\tmatch = rquickExpr.exec( selector );\n\t\t\t}\n\n\t\t\t// Match html or make sure no context is specified for #id\n\t\t\tif ( match && (match[1] || !context) ) {\n\n\t\t\t\t// HANDLE: $(html) -> $(array)\n\t\t\t\tif ( match[1] ) {\n\t\t\t\t\tcontext = context instanceof jQuery ? context[0] : context;\n\n\t\t\t\t\t// scripts is true for back-compat\n\t\t\t\t\tjQuery.merge( this, jQuery.parseHTML(\n\t\t\t\t\t\tmatch[1],\n\t\t\t\t\t\tcontext && context.nodeType ? context.ownerDocument || context : document,\n\t\t\t\t\t\ttrue\n\t\t\t\t\t) );\n\n\t\t\t\t\t// HANDLE: $(html, props)\n\t\t\t\t\tif ( rsingleTag.test( match[1] ) && jQuery.isPlainObject( context ) ) {\n\t\t\t\t\t\tfor ( match in context ) {\n\t\t\t\t\t\t\t// Properties of context are called as methods if possible\n\t\t\t\t\t\t\tif ( jQuery.isFunction( this[ match ] ) ) {\n\t\t\t\t\t\t\t\tthis[ match ]( context[ match ] );\n\n\t\t\t\t\t\t\t// ...and otherwise set as attributes\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tthis.attr( match, context[ match ] );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\treturn this;\n\n\t\t\t\t// HANDLE: $(#id)\n\t\t\t\t} else {\n\t\t\t\t\telem = document.getElementById( match[2] );\n\n\t\t\t\t\t// Check parentNode to catch when Blackberry 4.6 returns\n\t\t\t\t\t// nodes that are no longer in the document #6963\n\t\t\t\t\tif ( elem && elem.parentNode ) {\n\t\t\t\t\t\t// Handle the case where IE and Opera return items\n\t\t\t\t\t\t// by name instead of ID\n\t\t\t\t\t\tif ( elem.id !== match[2] ) {\n\t\t\t\t\t\t\treturn rootjQuery.find( selector );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Otherwise, we inject the element directly into the jQuery object\n\t\t\t\t\t\tthis.length = 1;\n\t\t\t\t\t\tthis[0] = elem;\n\t\t\t\t\t}\n\n\t\t\t\t\tthis.context = document;\n\t\t\t\t\tthis.selector = selector;\n\t\t\t\t\treturn this;\n\t\t\t\t}\n\n\t\t\t// HANDLE: $(expr, $(...))\n\t\t\t} else if ( !context || context.jquery ) {\n\t\t\t\treturn ( context || rootjQuery ).find( selector );\n\n\t\t\t// HANDLE: $(expr, context)\n\t\t\t// (which is just equivalent to: $(context).find(expr)\n\t\t\t} else {\n\t\t\t\treturn this.constructor( context ).find( selector );\n\t\t\t}\n\n\t\t// HANDLE: $(DOMElement)\n\t\t} else if ( selector.nodeType ) {\n\t\t\tthis.context = this[0] = selector;\n\t\t\tthis.length = 1;\n\t\t\treturn this;\n\n\t\t// HANDLE: $(function)\n\t\t// Shortcut for document ready\n\t\t} else if ( jQuery.isFunction( selector ) ) {\n\t\t\treturn rootjQuery.ready( selector );\n\t\t}\n\n\t\tif ( selector.selector !== undefined ) {\n\t\t\tthis.selector = selector.selector;\n\t\t\tthis.context = selector.context;\n\t\t}\n\n\t\treturn jQuery.makeArray( selector, this );\n\t},\n\n\t// Start with an empty selector\n\tselector: \"\",\n\n\t// The default length of a jQuery object is 0\n\tlength: 0,\n\n\t// The number of elements contained in the matched element set\n\tsize: function() {\n\t\treturn this.length;\n\t},\n\n\ttoArray: function() {\n\t\treturn core_slice.call( this );\n\t},\n\n\t// Get the Nth element in the matched element set OR\n\t// Get the whole matched element set as a clean array\n\tget: function( num ) {\n\t\treturn num == null ?\n\n\t\t\t// Return a 'clean' array\n\t\t\tthis.toArray() :\n\n\t\t\t// Return just the object\n\t\t\t( num < 0 ? this[ this.length + num ] : this[ num ] );\n\t},\n\n\t// Take an array of elements and push it onto the stack\n\t// (returning the new matched element set)\n\tpushStack: function( elems ) {\n\n\t\t// Build a new jQuery matched element set\n\t\tvar ret = jQuery.merge( this.constructor(), elems );\n\n\t\t// Add the old object onto the stack (as a reference)\n\t\tret.prevObject = this;\n\t\tret.context = this.context;\n\n\t\t// Return the newly-formed element set\n\t\treturn ret;\n\t},\n\n\t// Execute a callback for every element in the matched set.\n\t// (You can seed the arguments with an array of args, but this is\n\t// only used internally.)\n\teach: function( callback, args ) {\n\t\treturn jQuery.each( this, callback, args );\n\t},\n\n\tready: function( fn ) {\n\t\t// Add the callback\n\t\tjQuery.ready.promise().done( fn );\n\n\t\treturn this;\n\t},\n\n\tslice: function() {\n\t\treturn this.pushStack( core_slice.apply( this, arguments ) );\n\t},\n\n\tfirst: function() {\n\t\treturn this.eq( 0 );\n\t},\n\n\tlast: function() {\n\t\treturn this.eq( -1 );\n\t},\n\n\teq: function( i ) {\n\t\tvar len = this.length,\n\t\t\tj = +i + ( i < 0 ? len : 0 );\n\t\treturn this.pushStack( j >= 0 && j < len ? [ this[j] ] : [] );\n\t},\n\n\tmap: function( callback ) {\n\t\treturn this.pushStack( jQuery.map(this, function( elem, i ) {\n\t\t\treturn callback.call( elem, i, elem );\n\t\t}));\n\t},\n\n\tend: function() {\n\t\treturn this.prevObject || this.constructor(null);\n\t},\n\n\t// For internal use only.\n\t// Behaves like an Array's method, not like a jQuery method.\n\tpush: core_push,\n\tsort: [].sort,\n\tsplice: [].splice\n};\n\n// Give the init function the jQuery prototype for later instantiation\njQuery.fn.init.prototype = jQuery.fn;\n\njQuery.extend = jQuery.fn.extend = function() {\n\tvar src, copyIsArray, copy, name, options, clone,\n\t\ttarget = arguments[0] || {},\n\t\ti = 1,\n\t\tlength = arguments.length,\n\t\tdeep = false;\n\n\t// Handle a deep copy situation\n\tif ( typeof target === \"boolean\" ) {\n\t\tdeep = target;\n\t\ttarget = arguments[1] || {};\n\t\t// skip the boolean and the target\n\t\ti = 2;\n\t}\n\n\t// Handle case when target is a string or something (possible in deep copy)\n\tif ( typeof target !== \"object\" && !jQuery.isFunction(target) ) {\n\t\ttarget = {};\n\t}\n\n\t// extend jQuery itself if only one argument is passed\n\tif ( length === i ) {\n\t\ttarget = this;\n\t\t--i;\n\t}\n\n\tfor ( ; i < length; i++ ) {\n\t\t// Only deal with non-null/undefined values\n\t\tif ( (options = arguments[ i ]) != null ) {\n\t\t\t// Extend the base object\n\t\t\tfor ( name in options ) {\n\t\t\t\tsrc = target[ name ];\n\t\t\t\tcopy = options[ name ];\n\n\t\t\t\t// Prevent never-ending loop\n\t\t\t\tif ( target === copy ) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\t// Recurse if we're merging plain objects or arrays\n\t\t\t\tif ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {\n\t\t\t\t\tif ( copyIsArray ) {\n\t\t\t\t\t\tcopyIsArray = false;\n\t\t\t\t\t\tclone = src && jQuery.isArray(src) ? src : [];\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\tclone = src && jQuery.isPlainObject(src) ? src : {};\n\t\t\t\t\t}\n\n\t\t\t\t\t// Never move original objects, clone them\n\t\t\t\t\ttarget[ name ] = jQuery.extend( deep, clone, copy );\n\n\t\t\t\t// Don't bring in undefined values\n\t\t\t\t} else if ( copy !== undefined ) {\n\t\t\t\t\ttarget[ name ] = copy;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Return the modified object\n\treturn target;\n};\n\njQuery.extend({\n\tnoConflict: function( deep ) {\n\t\tif ( window.$ === jQuery ) {\n\t\t\twindow.$ = _$;\n\t\t}\n\n\t\tif ( deep && window.jQuery === jQuery ) {\n\t\t\twindow.jQuery = _jQuery;\n\t\t}\n\n\t\treturn jQuery;\n\t},\n\n\t// Is the DOM ready to be used? Set to true once it occurs.\n\tisReady: false,\n\n\t// A counter to track how many items to wait for before\n\t// the ready event fires. See #6781\n\treadyWait: 1,\n\n\t// Hold (or release) the ready event\n\tholdReady: function( hold ) {\n\t\tif ( hold ) {\n\t\t\tjQuery.readyWait++;\n\t\t} else {\n\t\t\tjQuery.ready( true );\n\t\t}\n\t},\n\n\t// Handle when the DOM is ready\n\tready: function( wait ) {\n\n\t\t// Abort if there are pending holds or we're already ready\n\t\tif ( wait === true ? --jQuery.readyWait : jQuery.isReady ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).\n\t\tif ( !document.body ) {\n\t\t\treturn setTimeout( jQuery.ready );\n\t\t}\n\n\t\t// Remember that the DOM is ready\n\t\tjQuery.isReady = true;\n\n\t\t// If a normal DOM Ready event fired, decrement, and wait if need be\n\t\tif ( wait !== true && --jQuery.readyWait > 0 ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// If there are functions bound, to execute\n\t\treadyList.resolveWith( document, [ jQuery ] );\n\n\t\t// Trigger any bound ready events\n\t\tif ( jQuery.fn.trigger ) {\n\t\t\tjQuery( document ).trigger(\"ready\").off(\"ready\");\n\t\t}\n\t},\n\n\t// See test/unit/core.js for details concerning isFunction.\n\t// Since version 1.3, DOM methods and functions like alert\n\t// aren't supported. They return false on IE (#2968).\n\tisFunction: function( obj ) {\n\t\treturn jQuery.type(obj) === \"function\";\n\t},\n\n\tisArray: Array.isArray || function( obj ) {\n\t\treturn jQuery.type(obj) === \"array\";\n\t},\n\n\tisWindow: function( obj ) {\n\t\treturn obj != null && obj == obj.window;\n\t},\n\n\tisNumeric: function( obj ) {\n\t\treturn !isNaN( parseFloat(obj) ) && isFinite( obj );\n\t},\n\n\ttype: function( obj ) {\n\t\tif ( obj == null ) {\n\t\t\treturn String( obj );\n\t\t}\n\t\treturn typeof obj === \"object\" || typeof obj === \"function\" ?\n\t\t\tclass2type[ core_toString.call(obj) ] || \"object\" :\n\t\t\ttypeof obj;\n\t},\n\n\tisPlainObject: function( obj ) {\n\t\t// Must be an Object.\n\t\t// Because of IE, we also have to check the presence of the constructor property.\n\t\t// Make sure that DOM nodes and window objects don't pass through, as well\n\t\tif ( !obj || jQuery.type(obj) !== \"object\" || obj.nodeType || jQuery.isWindow( obj ) ) {\n\t\t\treturn false;\n\t\t}\n\n\t\ttry {\n\t\t\t// Not own constructor property must be Object\n\t\t\tif ( obj.constructor &&\n\t\t\t\t!core_hasOwn.call(obj, \"constructor\") &&\n\t\t\t\t!core_hasOwn.call(obj.constructor.prototype, \"isPrototypeOf\") ) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t} catch ( e ) {\n\t\t\t// IE8,9 Will throw exceptions on certain host objects #9897\n\t\t\treturn false;\n\t\t}\n\n\t\t// Own properties are enumerated firstly, so to speed up,\n\t\t// if last one is own, then all properties are own.\n\n\t\tvar key;\n\t\tfor ( key in obj ) {}\n\n\t\treturn key === undefined || core_hasOwn.call( obj, key );\n\t},\n\n\tisEmptyObject: function( obj ) {\n\t\tvar name;\n\t\tfor ( name in obj ) {\n\t\t\treturn false;\n\t\t}\n\t\treturn true;\n\t},\n\n\terror: function( msg ) {\n\t\tthrow new Error( msg );\n\t},\n\n\t// data: string of html\n\t// context (optional): If specified, the fragment will be created in this context, defaults to document\n\t// keepScripts (optional): If true, will include scripts passed in the html string\n\tparseHTML: function( data, context, keepScripts ) {\n\t\tif ( !data || typeof data !== \"string\" ) {\n\t\t\treturn null;\n\t\t}\n\t\tif ( typeof context === \"boolean\" ) {\n\t\t\tkeepScripts = context;\n\t\t\tcontext = false;\n\t\t}\n\t\tcontext = context || document;\n\n\t\tvar parsed = rsingleTag.exec( data ),\n\t\t\tscripts = !keepScripts && [];\n\n\t\t// Single tag\n\t\tif ( parsed ) {\n\t\t\treturn [ context.createElement( parsed[1] ) ];\n\t\t}\n\n\t\tparsed = jQuery.buildFragment( [ data ], context, scripts );\n\t\tif ( scripts ) {\n\t\t\tjQuery( scripts ).remove();\n\t\t}\n\t\treturn jQuery.merge( [], parsed.childNodes );\n\t},\n\n\tparseJSON: function( data ) {\n\t\t// Attempt to parse using the native JSON parser first\n\t\tif ( window.JSON && window.JSON.parse ) {\n\t\t\treturn window.JSON.parse( data );\n\t\t}\n\n\t\tif ( data === null ) {\n\t\t\treturn data;\n\t\t}\n\n\t\tif ( typeof data === \"string\" ) {\n\n\t\t\t// Make sure leading/trailing whitespace is removed (IE can't handle it)\n\t\t\tdata = jQuery.trim( data );\n\n\t\t\tif ( data ) {\n\t\t\t\t// Make sure the incoming data is actual JSON\n\t\t\t\t// Logic borrowed from http://json.org/json2.js\n\t\t\t\tif ( rvalidchars.test( data.replace( rvalidescape, \"@\" )\n\t\t\t\t\t.replace( rvalidtokens, \"]\" )\n\t\t\t\t\t.replace( rvalidbraces, \"\")) ) {\n\n\t\t\t\t\treturn ( new Function( \"return \" + data ) )();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tjQuery.error( \"Invalid JSON: \" + data );\n\t},\n\n\t// Cross-browser xml parsing\n\tparseXML: function( data ) {\n\t\tvar xml, tmp;\n\t\tif ( !data || typeof data !== \"string\" ) {\n\t\t\treturn null;\n\t\t}\n\t\ttry {\n\t\t\tif ( window.DOMParser ) { // Standard\n\t\t\t\ttmp = new DOMParser();\n\t\t\t\txml = tmp.parseFromString( data , \"text/xml\" );\n\t\t\t} else { // IE\n\t\t\t\txml = new ActiveXObject( \"Microsoft.XMLDOM\" );\n\t\t\t\txml.async = \"false\";\n\t\t\t\txml.loadXML( data );\n\t\t\t}\n\t\t} catch( e ) {\n\t\t\txml = undefined;\n\t\t}\n\t\tif ( !xml || !xml.documentElement || xml.getElementsByTagName( \"parsererror\" ).length ) {\n\t\t\tjQuery.error( \"Invalid XML: \" + data );\n\t\t}\n\t\treturn xml;\n\t},\n\n\tnoop: function() {},\n\n\t// Evaluates a script in a global context\n\t// Workarounds based on findings by Jim Driscoll\n\t// http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context\n\tglobalEval: function( data ) {\n\t\tif ( data && jQuery.trim( data ) ) {\n\t\t\t// We use execScript on Internet Explorer\n\t\t\t// We use an anonymous function so that context is window\n\t\t\t// rather than jQuery in Firefox\n\t\t\t( window.execScript || function( data ) {\n\t\t\t\twindow[ \"eval\" ].call( window, data );\n\t\t\t} )( data );\n\t\t}\n\t},\n\n\t// Convert dashed to camelCase; used by the css and data modules\n\t// Microsoft forgot to hump their vendor prefix (#9572)\n\tcamelCase: function( string ) {\n\t\treturn string.replace( rmsPrefix, \"ms-\" ).replace( rdashAlpha, fcamelCase );\n\t},\n\n\tnodeName: function( elem, name ) {\n\t\treturn elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase();\n\t},\n\n\t// args is for internal usage only\n\teach: function( obj, callback, args ) {\n\t\tvar value,\n\t\t\ti = 0,\n\t\t\tlength = obj.length,\n\t\t\tisArray = isArraylike( obj );\n\n\t\tif ( args ) {\n\t\t\tif ( isArray ) {\n\t\t\t\tfor ( ; i < length; i++ ) {\n\t\t\t\t\tvalue = callback.apply( obj[ i ], args );\n\n\t\t\t\t\tif ( value === false ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tfor ( i in obj ) {\n\t\t\t\t\tvalue = callback.apply( obj[ i ], args );\n\n\t\t\t\t\tif ( value === false ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t// A special, fast, case for the most common use of each\n\t\t} else {\n\t\t\tif ( isArray ) {\n\t\t\t\tfor ( ; i < length; i++ ) {\n\t\t\t\t\tvalue = callback.call( obj[ i ], i, obj[ i ] );\n\n\t\t\t\t\tif ( value === false ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tfor ( i in obj ) {\n\t\t\t\t\tvalue = callback.call( obj[ i ], i, obj[ i ] );\n\n\t\t\t\t\tif ( value === false ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn obj;\n\t},\n\n\t// Use native String.trim function wherever possible\n\ttrim: core_trim && !core_trim.call(\"\\uFEFF\\xA0\") ?\n\t\tfunction( text ) {\n\t\t\treturn text == null ?\n\t\t\t\t\"\" :\n\t\t\t\tcore_trim.call( text );\n\t\t} :\n\n\t\t// Otherwise use our own trimming functionality\n\t\tfunction( text ) {\n\t\t\treturn text == null ?\n\t\t\t\t\"\" :\n\t\t\t\t( text + \"\" ).replace( rtrim, \"\" );\n\t\t},\n\n\t// results is for internal usage only\n\tmakeArray: function( arr, results ) {\n\t\tvar ret = results || [];\n\n\t\tif ( arr != null ) {\n\t\t\tif ( isArraylike( Object(arr) ) ) {\n\t\t\t\tjQuery.merge( ret,\n\t\t\t\t\ttypeof arr === \"string\" ?\n\t\t\t\t\t[ arr ] : arr\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\tcore_push.call( ret, arr );\n\t\t\t}\n\t\t}\n\n\t\treturn ret;\n\t},\n\n\tinArray: function( elem, arr, i ) {\n\t\tvar len;\n\n\t\tif ( arr ) {\n\t\t\tif ( core_indexOf ) {\n\t\t\t\treturn core_indexOf.call( arr, elem, i );\n\t\t\t}\n\n\t\t\tlen = arr.length;\n\t\t\ti = i ? i < 0 ? Math.max( 0, len + i ) : i : 0;\n\n\t\t\tfor ( ; i < len; i++ ) {\n\t\t\t\t// Skip accessing in sparse arrays\n\t\t\t\tif ( i in arr && arr[ i ] === elem ) {\n\t\t\t\t\treturn i;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn -1;\n\t},\n\n\tmerge: function( first, second ) {\n\t\tvar l = second.length,\n\t\t\ti = first.length,\n\t\t\tj = 0;\n\n\t\tif ( typeof l === \"number\" ) {\n\t\t\tfor ( ; j < l; j++ ) {\n\t\t\t\tfirst[ i++ ] = second[ j ];\n\t\t\t}\n\t\t} else {\n\t\t\twhile ( second[j] !== undefined ) {\n\t\t\t\tfirst[ i++ ] = second[ j++ ];\n\t\t\t}\n\t\t}\n\n\t\tfirst.length = i;\n\n\t\treturn first;\n\t},\n\n\tgrep: function( elems, callback, inv ) {\n\t\tvar retVal,\n\t\t\tret = [],\n\t\t\ti = 0,\n\t\t\tlength = elems.length;\n\t\tinv = !!inv;\n\n\t\t// Go through the array, only saving the items\n\t\t// that pass the validator function\n\t\tfor ( ; i < length; i++ ) {\n\t\t\tretVal = !!callback( elems[ i ], i );\n\t\t\tif ( inv !== retVal ) {\n\t\t\t\tret.push( elems[ i ] );\n\t\t\t}\n\t\t}\n\n\t\treturn ret;\n\t},\n\n\t// arg is for internal usage only\n\tmap: function( elems, callback, arg ) {\n\t\tvar value,\n\t\t\ti = 0,\n\t\t\tlength = elems.length,\n\t\t\tisArray = isArraylike( elems ),\n\t\t\tret = [];\n\n\t\t// Go through the array, translating each of the items to their\n\t\tif ( isArray ) {\n\t\t\tfor ( ; i < length; i++ ) {\n\t\t\t\tvalue = callback( elems[ i ], i, arg );\n\n\t\t\t\tif ( value != null ) {\n\t\t\t\t\tret[ ret.length ] = value;\n\t\t\t\t}\n\t\t\t}\n\n\t\t// Go through every key on the object,\n\t\t} else {\n\t\t\tfor ( i in elems ) {\n\t\t\t\tvalue = callback( elems[ i ], i, arg );\n\n\t\t\t\tif ( value != null ) {\n\t\t\t\t\tret[ ret.length ] = value;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Flatten any nested arrays\n\t\treturn core_concat.apply( [], ret );\n\t},\n\n\t// A global GUID counter for objects\n\tguid: 1,\n\n\t// Bind a function to a context, optionally partially applying any\n\t// arguments.\n\tproxy: function( fn, context ) {\n\t\tvar args, proxy, tmp;\n\n\t\tif ( typeof context === \"string\" ) {\n\t\t\ttmp = fn[ context ];\n\t\t\tcontext = fn;\n\t\t\tfn = tmp;\n\t\t}\n\n\t\t// Quick check to determine if target is callable, in the spec\n\t\t// this throws a TypeError, but we will just return undefined.\n\t\tif ( !jQuery.isFunction( fn ) ) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\t// Simulated bind\n\t\targs = core_slice.call( arguments, 2 );\n\t\tproxy = function() {\n\t\t\treturn fn.apply( context || this, args.concat( core_slice.call( arguments ) ) );\n\t\t};\n\n\t\t// Set the guid of unique handler to the same of original handler, so it can be removed\n\t\tproxy.guid = fn.guid = fn.guid || jQuery.guid++;\n\n\t\treturn proxy;\n\t},\n\n\t// Multifunctional method to get and set values of a collection\n\t// The value/s can optionally be executed if it's a function\n\taccess: function( elems, fn, key, value, chainable, emptyGet, raw ) {\n\t\tvar i = 0,\n\t\t\tlength = elems.length,\n\t\t\tbulk = key == null;\n\n\t\t// Sets many values\n\t\tif ( jQuery.type( key ) === \"object\" ) {\n\t\t\tchainable = true;\n\t\t\tfor ( i in key ) {\n\t\t\t\tjQuery.access( elems, fn, i, key[i], true, emptyGet, raw );\n\t\t\t}\n\n\t\t// Sets one value\n\t\t} else if ( value !== undefined ) {\n\t\t\tchainable = true;\n\n\t\t\tif ( !jQuery.isFunction( value ) ) {\n\t\t\t\traw = true;\n\t\t\t}\n\n\t\t\tif ( bulk ) {\n\t\t\t\t// Bulk operations run against the entire set\n\t\t\t\tif ( raw ) {\n\t\t\t\t\tfn.call( elems, value );\n\t\t\t\t\tfn = null;\n\n\t\t\t\t// ...except when executing function values\n\t\t\t\t} else {\n\t\t\t\t\tbulk = fn;\n\t\t\t\t\tfn = function( elem, key, value ) {\n\t\t\t\t\t\treturn bulk.call( jQuery( elem ), value );\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( fn ) {\n\t\t\t\tfor ( ; i < length; i++ ) {\n\t\t\t\t\tfn( elems[i], key, raw ? value : value.call( elems[i], i, fn( elems[i], key ) ) );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn chainable ?\n\t\t\telems :\n\n\t\t\t// Gets\n\t\t\tbulk ?\n\t\t\t\tfn.call( elems ) :\n\t\t\t\tlength ? fn( elems[0], key ) : emptyGet;\n\t},\n\n\tnow: function() {\n\t\treturn ( new Date() ).getTime();\n\t}\n});\n\njQuery.ready.promise = function( obj ) {\n\tif ( !readyList ) {\n\n\t\treadyList = jQuery.Deferred();\n\n\t\t// Catch cases where $(document).ready() is called after the browser event has already occurred.\n\t\t// we once tried to use readyState \"interactive\" here, but it caused issues like the one\n\t\t// discovered by ChrisS here: http://bugs.jquery.com/ticket/12282#comment:15\n\t\tif ( document.readyState === \"complete\" ) {\n\t\t\t// Handle it asynchronously to allow scripts the opportunity to delay ready\n\t\t\tsetTimeout( jQuery.ready );\n\n\t\t// Standards-based browsers support DOMContentLoaded\n\t\t} else if ( document.addEventListener ) {\n\t\t\t// Use the handy event callback\n\t\t\tdocument.addEventListener( \"DOMContentLoaded\", completed, false );\n\n\t\t\t// A fallback to window.onload, that will always work\n\t\t\twindow.addEventListener( \"load\", completed, false );\n\n\t\t// If IE event model is used\n\t\t} else {\n\t\t\t// Ensure firing before onload, maybe late but safe also for iframes\n\t\t\tdocument.attachEvent( \"onreadystatechange\", completed );\n\n\t\t\t// A fallback to window.onload, that will always work\n\t\t\twindow.attachEvent( \"onload\", completed );\n\n\t\t\t// If IE and not a frame\n\t\t\t// continually check to see if the document is ready\n\t\t\tvar top = false;\n\n\t\t\ttry {\n\t\t\t\ttop = window.frameElement == null && document.documentElement;\n\t\t\t} catch(e) {}\n\n\t\t\tif ( top && top.doScroll ) {\n\t\t\t\t(function doScrollCheck() {\n\t\t\t\t\tif ( !jQuery.isReady ) {\n\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t// Use the trick by Diego Perini\n\t\t\t\t\t\t\t// http://javascript.nwbox.com/IEContentLoaded/\n\t\t\t\t\t\t\ttop.doScroll(\"left\");\n\t\t\t\t\t\t} catch(e) {\n\t\t\t\t\t\t\treturn setTimeout( doScrollCheck, 50 );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// detach all dom ready events\n\t\t\t\t\t\tdetach();\n\n\t\t\t\t\t\t// and execute any waiting functions\n\t\t\t\t\t\tjQuery.ready();\n\t\t\t\t\t}\n\t\t\t\t})();\n\t\t\t}\n\t\t}\n\t}\n\treturn readyList.promise( obj );\n};\n\n// Populate the class2type map\njQuery.each(\"Boolean Number String Function Array Date RegExp Object Error\".split(\" \"), function(i, name) {\n\tclass2type[ \"[object \" + name + \"]\" ] = name.toLowerCase();\n});\n\nfunction isArraylike( obj ) {\n\tvar length = obj.length,\n\t\ttype = jQuery.type( obj );\n\n\tif ( jQuery.isWindow( obj ) ) {\n\t\treturn false;\n\t}\n\n\tif ( obj.nodeType === 1 && length ) {\n\t\treturn true;\n\t}\n\n\treturn type === \"array\" || type !== \"function\" &&\n\t\t( length === 0 ||\n\t\ttypeof length === \"number\" && length > 0 && ( length - 1 ) in obj );\n}\n\n// All jQuery objects should point back to these\nrootjQuery = jQuery(document);\n// String to Object options format cache\nvar optionsCache = {};\n\n// Convert String-formatted options into Object-formatted ones and store in cache\nfunction createOptions( options ) {\n\tvar object = optionsCache[ options ] = {};\n\tjQuery.each( options.match( core_rnotwhite ) || [], function( _, flag ) {\n\t\tobject[ flag ] = true;\n\t});\n\treturn object;\n}\n\n/*\n * Create a callback list using the following parameters:\n *\n *\toptions: an optional list of space-separated options that will change how\n *\t\t\tthe callback list behaves or a more traditional option object\n *\n * By default a callback list will act like an event callback list and can be\n * \"fired\" multiple times.\n *\n * Possible options:\n *\n *\tonce:\t\t\twill ensure the callback list can only be fired once (like a Deferred)\n *\n *\tmemory:\t\t\twill keep track of previous values and will call any callback added\n *\t\t\t\t\tafter the list has been fired right away with the latest \"memorized\"\n *\t\t\t\t\tvalues (like a Deferred)\n *\n *\tunique:\t\t\twill ensure a callback can only be added once (no duplicate in the list)\n *\n *\tstopOnFalse:\tinterrupt callings when a callback returns false\n *\n */\njQuery.Callbacks = function( options ) {\n\n\t// Convert options from String-formatted to Object-formatted if needed\n\t// (we check in cache first)\n\toptions = typeof options === \"string\" ?\n\t\t( optionsCache[ options ] || createOptions( options ) ) :\n\t\tjQuery.extend( {}, options );\n\n\tvar // Flag to know if list is currently firing\n\t\tfiring,\n\t\t// Last fire value (for non-forgettable lists)\n\t\tmemory,\n\t\t// Flag to know if list was already fired\n\t\tfired,\n\t\t// End of the loop when firing\n\t\tfiringLength,\n\t\t// Index of currently firing callback (modified by remove if needed)\n\t\tfiringIndex,\n\t\t// First callback to fire (used internally by add and fireWith)\n\t\tfiringStart,\n\t\t// Actual callback list\n\t\tlist = [],\n\t\t// Stack of fire calls for repeatable lists\n\t\tstack = !options.once && [],\n\t\t// Fire callbacks\n\t\tfire = function( data ) {\n\t\t\tmemory = options.memory && data;\n\t\t\tfired = true;\n\t\t\tfiringIndex = firingStart || 0;\n\t\t\tfiringStart = 0;\n\t\t\tfiringLength = list.length;\n\t\t\tfiring = true;\n\t\t\tfor ( ; list && firingIndex < firingLength; firingIndex++ ) {\n\t\t\t\tif ( list[ firingIndex ].apply( data[ 0 ], data[ 1 ] ) === false && options.stopOnFalse ) {\n\t\t\t\t\tmemory = false; // To prevent further calls using add\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tfiring = false;\n\t\t\tif ( list ) {\n\t\t\t\tif ( stack ) {\n\t\t\t\t\tif ( stack.length ) {\n\t\t\t\t\t\tfire( stack.shift() );\n\t\t\t\t\t}\n\t\t\t\t} else if ( memory ) {\n\t\t\t\t\tlist = [];\n\t\t\t\t} else {\n\t\t\t\t\tself.disable();\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t// Actual Callbacks object\n\t\tself = {\n\t\t\t// Add a callback or a collection of callbacks to the list\n\t\t\tadd: function() {\n\t\t\t\tif ( list ) {\n\t\t\t\t\t// First, we save the current length\n\t\t\t\t\tvar start = list.length;\n\t\t\t\t\t(function add( args ) {\n\t\t\t\t\t\tjQuery.each( args, function( _, arg ) {\n\t\t\t\t\t\t\tvar type = jQuery.type( arg );\n\t\t\t\t\t\t\tif ( type === \"function\" ) {\n\t\t\t\t\t\t\t\tif ( !options.unique || !self.has( arg ) ) {\n\t\t\t\t\t\t\t\t\tlist.push( arg );\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} else if ( arg && arg.length && type !== \"string\" ) {\n\t\t\t\t\t\t\t\t// Inspect recursively\n\t\t\t\t\t\t\t\tadd( arg );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t});\n\t\t\t\t\t})( arguments );\n\t\t\t\t\t// Do we need to add the callbacks to the\n\t\t\t\t\t// current firing batch?\n\t\t\t\t\tif ( firing ) {\n\t\t\t\t\t\tfiringLength = list.length;\n\t\t\t\t\t// With memory, if we're not firing then\n\t\t\t\t\t// we should call right away\n\t\t\t\t\t} else if ( memory ) {\n\t\t\t\t\t\tfiringStart = start;\n\t\t\t\t\t\tfire( memory );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Remove a callback from the list\n\t\t\tremove: function() {\n\t\t\t\tif ( list ) {\n\t\t\t\t\tjQuery.each( arguments, function( _, arg ) {\n\t\t\t\t\t\tvar index;\n\t\t\t\t\t\twhile( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) {\n\t\t\t\t\t\t\tlist.splice( index, 1 );\n\t\t\t\t\t\t\t// Handle firing indexes\n\t\t\t\t\t\t\tif ( firing ) {\n\t\t\t\t\t\t\t\tif ( index <= firingLength ) {\n\t\t\t\t\t\t\t\t\tfiringLength--;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif ( index <= firingIndex ) {\n\t\t\t\t\t\t\t\t\tfiringIndex--;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Check if a given callback is in the list.\n\t\t\t// If no argument is given, return whether or not list has callbacks attached.\n\t\t\thas: function( fn ) {\n\t\t\t\treturn fn ? jQuery.inArray( fn, list ) > -1 : !!( list && list.length );\n\t\t\t},\n\t\t\t// Remove all callbacks from the list\n\t\t\tempty: function() {\n\t\t\t\tlist = [];\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Have the list do nothing anymore\n\t\t\tdisable: function() {\n\t\t\t\tlist = stack = memory = undefined;\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Is it disabled?\n\t\t\tdisabled: function() {\n\t\t\t\treturn !list;\n\t\t\t},\n\t\t\t// Lock the list in its current state\n\t\t\tlock: function() {\n\t\t\t\tstack = undefined;\n\t\t\t\tif ( !memory ) {\n\t\t\t\t\tself.disable();\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Is it locked?\n\t\t\tlocked: function() {\n\t\t\t\treturn !stack;\n\t\t\t},\n\t\t\t// Call all callbacks with the given context and arguments\n\t\t\tfireWith: function( context, args ) {\n\t\t\t\targs = args || [];\n\t\t\t\targs = [ context, args.slice ? args.slice() : args ];\n\t\t\t\tif ( list && ( !fired || stack ) ) {\n\t\t\t\t\tif ( firing ) {\n\t\t\t\t\t\tstack.push( args );\n\t\t\t\t\t} else {\n\t\t\t\t\t\tfire( args );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Call all the callbacks with the given arguments\n\t\t\tfire: function() {\n\t\t\t\tself.fireWith( this, arguments );\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// To know if the callbacks have already been called at least once\n\t\t\tfired: function() {\n\t\t\t\treturn !!fired;\n\t\t\t}\n\t\t};\n\n\treturn self;\n};\njQuery.extend({\n\n\tDeferred: function( func ) {\n\t\tvar tuples = [\n\t\t\t\t// action, add listener, listener list, final state\n\t\t\t\t[ \"resolve\", \"done\", jQuery.Callbacks(\"once memory\"), \"resolved\" ],\n\t\t\t\t[ \"reject\", \"fail\", jQuery.Callbacks(\"once memory\"), \"rejected\" ],\n\t\t\t\t[ \"notify\", \"progress\", jQuery.Callbacks(\"memory\") ]\n\t\t\t],\n\t\t\tstate = \"pending\",\n\t\t\tpromise = {\n\t\t\t\tstate: function() {\n\t\t\t\t\treturn state;\n\t\t\t\t},\n\t\t\t\talways: function() {\n\t\t\t\t\tdeferred.done( arguments ).fail( arguments );\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\t\t\t\tthen: function( /* fnDone, fnFail, fnProgress */ ) {\n\t\t\t\t\tvar fns = arguments;\n\t\t\t\t\treturn jQuery.Deferred(function( newDefer ) {\n\t\t\t\t\t\tjQuery.each( tuples, function( i, tuple ) {\n\t\t\t\t\t\t\tvar action = tuple[ 0 ],\n\t\t\t\t\t\t\t\tfn = jQuery.isFunction( fns[ i ] ) && fns[ i ];\n\t\t\t\t\t\t\t// deferred[ done | fail | progress ] for forwarding actions to newDefer\n\t\t\t\t\t\t\tdeferred[ tuple[1] ](function() {\n\t\t\t\t\t\t\t\tvar returned = fn && fn.apply( this, arguments );\n\t\t\t\t\t\t\t\tif ( returned && jQuery.isFunction( returned.promise ) ) {\n\t\t\t\t\t\t\t\t\treturned.promise()\n\t\t\t\t\t\t\t\t\t\t.done( newDefer.resolve )\n\t\t\t\t\t\t\t\t\t\t.fail( newDefer.reject )\n\t\t\t\t\t\t\t\t\t\t.progress( newDefer.notify );\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tnewDefer[ action + \"With\" ]( this === promise ? newDefer.promise() : this, fn ? [ returned ] : arguments );\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t});\n\t\t\t\t\t\tfns = null;\n\t\t\t\t\t}).promise();\n\t\t\t\t},\n\t\t\t\t// Get a promise for this deferred\n\t\t\t\t// If obj is provided, the promise aspect is added to the object\n\t\t\t\tpromise: function( obj ) {\n\t\t\t\t\treturn obj != null ? jQuery.extend( obj, promise ) : promise;\n\t\t\t\t}\n\t\t\t},\n\t\t\tdeferred = {};\n\n\t\t// Keep pipe for back-compat\n\t\tpromise.pipe = promise.then;\n\n\t\t// Add list-specific methods\n\t\tjQuery.each( tuples, function( i, tuple ) {\n\t\t\tvar list = tuple[ 2 ],\n\t\t\t\tstateString = tuple[ 3 ];\n\n\t\t\t// promise[ done | fail | progress ] = list.add\n\t\t\tpromise[ tuple[1] ] = list.add;\n\n\t\t\t// Handle state\n\t\t\tif ( stateString ) {\n\t\t\t\tlist.add(function() {\n\t\t\t\t\t// state = [ resolved | rejected ]\n\t\t\t\t\tstate = stateString;\n\n\t\t\t\t// [ reject_list | resolve_list ].disable; progress_list.lock\n\t\t\t\t}, tuples[ i ^ 1 ][ 2 ].disable, tuples[ 2 ][ 2 ].lock );\n\t\t\t}\n\n\t\t\t// deferred[ resolve | reject | notify ]\n\t\t\tdeferred[ tuple[0] ] = function() {\n\t\t\t\tdeferred[ tuple[0] + \"With\" ]( this === deferred ? promise : this, arguments );\n\t\t\t\treturn this;\n\t\t\t};\n\t\t\tdeferred[ tuple[0] + \"With\" ] = list.fireWith;\n\t\t});\n\n\t\t// Make the deferred a promise\n\t\tpromise.promise( deferred );\n\n\t\t// Call given func if any\n\t\tif ( func ) {\n\t\t\tfunc.call( deferred, deferred );\n\t\t}\n\n\t\t// All done!\n\t\treturn deferred;\n\t},\n\n\t// Deferred helper\n\twhen: function( subordinate /* , ..., subordinateN */ ) {\n\t\tvar i = 0,\n\t\t\tresolveValues = core_slice.call( arguments ),\n\t\t\tlength = resolveValues.length,\n\n\t\t\t// the count of uncompleted subordinates\n\t\t\tremaining = length !== 1 || ( subordinate && jQuery.isFunction( subordinate.promise ) ) ? length : 0,\n\n\t\t\t// the master Deferred. If resolveValues consist of only a single Deferred, just use that.\n\t\t\tdeferred = remaining === 1 ? subordinate : jQuery.Deferred(),\n\n\t\t\t// Update function for both resolve and progress values\n\t\t\tupdateFunc = function( i, contexts, values ) {\n\t\t\t\treturn function( value ) {\n\t\t\t\t\tcontexts[ i ] = this;\n\t\t\t\t\tvalues[ i ] = arguments.length > 1 ? core_slice.call( arguments ) : value;\n\t\t\t\t\tif( values === progressValues ) {\n\t\t\t\t\t\tdeferred.notifyWith( contexts, values );\n\t\t\t\t\t} else if ( !( --remaining ) ) {\n\t\t\t\t\t\tdeferred.resolveWith( contexts, values );\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\t},\n\n\t\t\tprogressValues, progressContexts, resolveContexts;\n\n\t\t// add listeners to Deferred subordinates; treat others as resolved\n\t\tif ( length > 1 ) {\n\t\t\tprogressValues = new Array( length );\n\t\t\tprogressContexts = new Array( length );\n\t\t\tresolveContexts = new Array( length );\n\t\t\tfor ( ; i < length; i++ ) {\n\t\t\t\tif ( resolveValues[ i ] && jQuery.isFunction( resolveValues[ i ].promise ) ) {\n\t\t\t\t\tresolveValues[ i ].promise()\n\t\t\t\t\t\t.done( updateFunc( i, resolveContexts, resolveValues ) )\n\t\t\t\t\t\t.fail( deferred.reject )\n\t\t\t\t\t\t.progress( updateFunc( i, progressContexts, progressValues ) );\n\t\t\t\t} else {\n\t\t\t\t\t--remaining;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// if we're not waiting on anything, resolve the master\n\t\tif ( !remaining ) {\n\t\t\tdeferred.resolveWith( resolveContexts, resolveValues );\n\t\t}\n\n\t\treturn deferred.promise();\n\t}\n});\njQuery.support = (function() {\n\n\tvar support, all, a,\n\t\tinput, select, fragment,\n\t\topt, eventName, isSupported, i,\n\t\tdiv = document.createElement(\"div\");\n\n\t// Setup\n\tdiv.setAttribute( \"className\", \"t\" );\n\tdiv.innerHTML = \"  <link/><table></table><a href='/a'>a</a><input type='checkbox'/>\";\n\n\t// Support tests won't run in some limited or non-browser environments\n\tall = div.getElementsByTagName(\"*\");\n\ta = div.getElementsByTagName(\"a\")[ 0 ];\n\tif ( !all || !a || !all.length ) {\n\t\treturn {};\n\t}\n\n\t// First batch of tests\n\tselect = document.createElement(\"select\");\n\topt = select.appendChild( document.createElement(\"option\") );\n\tinput = div.getElementsByTagName(\"input\")[ 0 ];\n\n\ta.style.cssText = \"top:1px;float:left;opacity:.5\";\n\tsupport = {\n\t\t// Test setAttribute on camelCase class. If it works, we need attrFixes when doing get/setAttribute (ie6/7)\n\t\tgetSetAttribute: div.className !== \"t\",\n\n\t\t// IE strips leading whitespace when .innerHTML is used\n\t\tleadingWhitespace: div.firstChild.nodeType === 3,\n\n\t\t// Make sure that tbody elements aren't automatically inserted\n\t\t// IE will insert them into empty tables\n\t\ttbody: !div.getElementsByTagName(\"tbody\").length,\n\n\t\t// Make sure that link elements get serialized correctly by innerHTML\n\t\t// This requires a wrapper element in IE\n\t\thtmlSerialize: !!div.getElementsByTagName(\"link\").length,\n\n\t\t// Get the style information from getAttribute\n\t\t// (IE uses .cssText instead)\n\t\tstyle: /top/.test( a.getAttribute(\"style\") ),\n\n\t\t// Make sure that URLs aren't manipulated\n\t\t// (IE normalizes it by default)\n\t\threfNormalized: a.getAttribute(\"href\") === \"/a\",\n\n\t\t// Make sure that element opacity exists\n\t\t// (IE uses filter instead)\n\t\t// Use a regex to work around a WebKit issue. See #5145\n\t\topacity: /^0.5/.test( a.style.opacity ),\n\n\t\t// Verify style float existence\n\t\t// (IE uses styleFloat instead of cssFloat)\n\t\tcssFloat: !!a.style.cssFloat,\n\n\t\t// Check the default checkbox/radio value (\"\" on WebKit; \"on\" elsewhere)\n\t\tcheckOn: !!input.value,\n\n\t\t// Make sure that a selected-by-default option has a working selected property.\n\t\t// (WebKit defaults to false instead of true, IE too, if it's in an optgroup)\n\t\toptSelected: opt.selected,\n\n\t\t// Tests for enctype support on a form (#6743)\n\t\tenctype: !!document.createElement(\"form\").enctype,\n\n\t\t// Makes sure cloning an html5 element does not cause problems\n\t\t// Where outerHTML is undefined, this still works\n\t\thtml5Clone: document.createElement(\"nav\").cloneNode( true ).outerHTML !== \"<:nav></:nav>\",\n\n\t\t// jQuery.support.boxModel DEPRECATED in 1.8 since we don't support Quirks Mode\n\t\tboxModel: document.compatMode === \"CSS1Compat\",\n\n\t\t// Will be defined later\n\t\tdeleteExpando: true,\n\t\tnoCloneEvent: true,\n\t\tinlineBlockNeedsLayout: false,\n\t\tshrinkWrapBlocks: false,\n\t\treliableMarginRight: true,\n\t\tboxSizingReliable: true,\n\t\tpixelPosition: false\n\t};\n\n\t// Make sure checked status is properly cloned\n\tinput.checked = true;\n\tsupport.noCloneChecked = input.cloneNode( true ).checked;\n\n\t// Make sure that the options inside disabled selects aren't marked as disabled\n\t// (WebKit marks them as disabled)\n\tselect.disabled = true;\n\tsupport.optDisabled = !opt.disabled;\n\n\t// Support: IE<9\n\ttry {\n\t\tdelete div.test;\n\t} catch( e ) {\n\t\tsupport.deleteExpando = false;\n\t}\n\n\t// Check if we can trust getAttribute(\"value\")\n\tinput = document.createElement(\"input\");\n\tinput.setAttribute( \"value\", \"\" );\n\tsupport.input = input.getAttribute( \"value\" ) === \"\";\n\n\t// Check if an input maintains its value after becoming a radio\n\tinput.value = \"t\";\n\tinput.setAttribute( \"type\", \"radio\" );\n\tsupport.radioValue = input.value === \"t\";\n\n\t// #11217 - WebKit loses check when the name is after the checked attribute\n\tinput.setAttribute( \"checked\", \"t\" );\n\tinput.setAttribute( \"name\", \"t\" );\n\n\tfragment = document.createDocumentFragment();\n\tfragment.appendChild( input );\n\n\t// Check if a disconnected checkbox will retain its checked\n\t// value of true after appended to the DOM (IE6/7)\n\tsupport.appendChecked = input.checked;\n\n\t// WebKit doesn't clone checked state correctly in fragments\n\tsupport.checkClone = fragment.cloneNode( true ).cloneNode( true ).lastChild.checked;\n\n\t// Support: IE<9\n\t// Opera does not clone events (and typeof div.attachEvent === undefined).\n\t// IE9-10 clones events bound via attachEvent, but they don't trigger with .click()\n\tif ( div.attachEvent ) {\n\t\tdiv.attachEvent( \"onclick\", function() {\n\t\t\tsupport.noCloneEvent = false;\n\t\t});\n\n\t\tdiv.cloneNode( true ).click();\n\t}\n\n\t// Support: IE<9 (lack submit/change bubble), Firefox 17+ (lack focusin event)\n\t// Beware of CSP restrictions (https://developer.mozilla.org/en/Security/CSP), test/csp.php\n\tfor ( i in { submit: true, change: true, focusin: true }) {\n\t\tdiv.setAttribute( eventName = \"on\" + i, \"t\" );\n\n\t\tsupport[ i + \"Bubbles\" ] = eventName in window || div.attributes[ eventName ].expando === false;\n\t}\n\n\tdiv.style.backgroundClip = \"content-box\";\n\tdiv.cloneNode( true ).style.backgroundClip = \"\";\n\tsupport.clearCloneStyle = div.style.backgroundClip === \"content-box\";\n\n\t// Run tests that need a body at doc ready\n\tjQuery(function() {\n\t\tvar container, marginDiv, tds,\n\t\t\tdivReset = \"padding:0;margin:0;border:0;display:block;box-sizing:content-box;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;\",\n\t\t\tbody = document.getElementsByTagName(\"body\")[0];\n\n\t\tif ( !body ) {\n\t\t\t// Return for frameset docs that don't have a body\n\t\t\treturn;\n\t\t}\n\n\t\tcontainer = document.createElement(\"div\");\n\t\tcontainer.style.cssText = \"border:0;width:0;height:0;position:absolute;top:0;left:-9999px;margin-top:1px\";\n\n\t\tbody.appendChild( container ).appendChild( div );\n\n\t\t// Support: IE8\n\t\t// Check if table cells still have offsetWidth/Height when they are set\n\t\t// to display:none and there are still other visible table cells in a\n\t\t// table row; if so, offsetWidth/Height are not reliable for use when\n\t\t// determining if an element has been hidden directly using\n\t\t// display:none (it is still safe to use offsets if a parent element is\n\t\t// hidden; don safety goggles and see bug #4512 for more information).\n\t\tdiv.innerHTML = \"<table><tr><td></td><td>t</td></tr></table>\";\n\t\ttds = div.getElementsByTagName(\"td\");\n\t\ttds[ 0 ].style.cssText = \"padding:0;margin:0;border:0;display:none\";\n\t\tisSupported = ( tds[ 0 ].offsetHeight === 0 );\n\n\t\ttds[ 0 ].style.display = \"\";\n\t\ttds[ 1 ].style.display = \"none\";\n\n\t\t// Support: IE8\n\t\t// Check if empty table cells still have offsetWidth/Height\n\t\tsupport.reliableHiddenOffsets = isSupported && ( tds[ 0 ].offsetHeight === 0 );\n\n\t\t// Check box-sizing and margin behavior\n\t\tdiv.innerHTML = \"\";\n\t\tdiv.style.cssText = \"box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%;\";\n\t\tsupport.boxSizing = ( div.offsetWidth === 4 );\n\t\tsupport.doesNotIncludeMarginInBodyOffset = ( body.offsetTop !== 1 );\n\n\t\t// Use window.getComputedStyle because jsdom on node.js will break without it.\n\t\tif ( window.getComputedStyle ) {\n\t\t\tsupport.pixelPosition = ( window.getComputedStyle( div, null ) || {} ).top !== \"1%\";\n\t\t\tsupport.boxSizingReliable = ( window.getComputedStyle( div, null ) || { width: \"4px\" } ).width === \"4px\";\n\n\t\t\t// Check if div with explicit width and no margin-right incorrectly\n\t\t\t// gets computed margin-right based on width of container. (#3333)\n\t\t\t// Fails in WebKit before Feb 2011 nightlies\n\t\t\t// WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right\n\t\t\tmarginDiv = div.appendChild( document.createElement(\"div\") );\n\t\t\tmarginDiv.style.cssText = div.style.cssText = divReset;\n\t\t\tmarginDiv.style.marginRight = marginDiv.style.width = \"0\";\n\t\t\tdiv.style.width = \"1px\";\n\n\t\t\tsupport.reliableMarginRight =\n\t\t\t\t!parseFloat( ( window.getComputedStyle( marginDiv, null ) || {} ).marginRight );\n\t\t}\n\n\t\tif ( typeof div.style.zoom !== core_strundefined ) {\n\t\t\t// Support: IE<8\n\t\t\t// Check if natively block-level elements act like inline-block\n\t\t\t// elements when setting their display to 'inline' and giving\n\t\t\t// them layout\n\t\t\tdiv.innerHTML = \"\";\n\t\t\tdiv.style.cssText = divReset + \"width:1px;padding:1px;display:inline;zoom:1\";\n\t\t\tsupport.inlineBlockNeedsLayout = ( div.offsetWidth === 3 );\n\n\t\t\t// Support: IE6\n\t\t\t// Check if elements with layout shrink-wrap their children\n\t\t\tdiv.style.display = \"block\";\n\t\t\tdiv.innerHTML = \"<div></div>\";\n\t\t\tdiv.firstChild.style.width = \"5px\";\n\t\t\tsupport.shrinkWrapBlocks = ( div.offsetWidth !== 3 );\n\n\t\t\tif ( support.inlineBlockNeedsLayout ) {\n\t\t\t\t// Prevent IE 6 from affecting layout for positioned elements #11048\n\t\t\t\t// Prevent IE from shrinking the body in IE 7 mode #12869\n\t\t\t\t// Support: IE<8\n\t\t\t\tbody.style.zoom = 1;\n\t\t\t}\n\t\t}\n\n\t\tbody.removeChild( container );\n\n\t\t// Null elements to avoid leaks in IE\n\t\tcontainer = div = tds = marginDiv = null;\n\t});\n\n\t// Null elements to avoid leaks in IE\n\tall = select = fragment = opt = a = input = null;\n\n\treturn support;\n})();\n\nvar rbrace = /(?:\\{[\\s\\S]*\\}|\\[[\\s\\S]*\\])$/,\n\trmultiDash = /([A-Z])/g;\n\nfunction internalData( elem, name, data, pvt /* Internal Use Only */ ){\n\tif ( !jQuery.acceptData( elem ) ) {\n\t\treturn;\n\t}\n\n\tvar thisCache, ret,\n\t\tinternalKey = jQuery.expando,\n\t\tgetByName = typeof name === \"string\",\n\n\t\t// We have to handle DOM nodes and JS objects differently because IE6-7\n\t\t// can't GC object references properly across the DOM-JS boundary\n\t\tisNode = elem.nodeType,\n\n\t\t// Only DOM nodes need the global jQuery cache; JS object data is\n\t\t// attached directly to the object so GC can occur automatically\n\t\tcache = isNode ? jQuery.cache : elem,\n\n\t\t// Only defining an ID for JS objects if its cache already exists allows\n\t\t// the code to shortcut on the same path as a DOM node with no cache\n\t\tid = isNode ? elem[ internalKey ] : elem[ internalKey ] && internalKey;\n\n\t// Avoid doing any more work than we need to when trying to get data on an\n\t// object that has no data at all\n\tif ( (!id || !cache[id] || (!pvt && !cache[id].data)) && getByName && data === undefined ) {\n\t\treturn;\n\t}\n\n\tif ( !id ) {\n\t\t// Only DOM nodes need a new unique ID for each element since their data\n\t\t// ends up in the global cache\n\t\tif ( isNode ) {\n\t\t\telem[ internalKey ] = id = core_deletedIds.pop() || jQuery.guid++;\n\t\t} else {\n\t\t\tid = internalKey;\n\t\t}\n\t}\n\n\tif ( !cache[ id ] ) {\n\t\tcache[ id ] = {};\n\n\t\t// Avoids exposing jQuery metadata on plain JS objects when the object\n\t\t// is serialized using JSON.stringify\n\t\tif ( !isNode ) {\n\t\t\tcache[ id ].toJSON = jQuery.noop;\n\t\t}\n\t}\n\n\t// An object can be passed to jQuery.data instead of a key/value pair; this gets\n\t// shallow copied over onto the existing cache\n\tif ( typeof name === \"object\" || typeof name === \"function\" ) {\n\t\tif ( pvt ) {\n\t\t\tcache[ id ] = jQuery.extend( cache[ id ], name );\n\t\t} else {\n\t\t\tcache[ id ].data = jQuery.extend( cache[ id ].data, name );\n\t\t}\n\t}\n\n\tthisCache = cache[ id ];\n\n\t// jQuery data() is stored in a separate object inside the object's internal data\n\t// cache in order to avoid key collisions between internal data and user-defined\n\t// data.\n\tif ( !pvt ) {\n\t\tif ( !thisCache.data ) {\n\t\t\tthisCache.data = {};\n\t\t}\n\n\t\tthisCache = thisCache.data;\n\t}\n\n\tif ( data !== undefined ) {\n\t\tthisCache[ jQuery.camelCase( name ) ] = data;\n\t}\n\n\t// Check for both converted-to-camel and non-converted data property names\n\t// If a data property was specified\n\tif ( getByName ) {\n\n\t\t// First Try to find as-is property data\n\t\tret = thisCache[ name ];\n\n\t\t// Test for null|undefined property data\n\t\tif ( ret == null ) {\n\n\t\t\t// Try to find the camelCased property\n\t\t\tret = thisCache[ jQuery.camelCase( name ) ];\n\t\t}\n\t} else {\n\t\tret = thisCache;\n\t}\n\n\treturn ret;\n}\n\nfunction internalRemoveData( elem, name, pvt ) {\n\tif ( !jQuery.acceptData( elem ) ) {\n\t\treturn;\n\t}\n\n\tvar i, l, thisCache,\n\t\tisNode = elem.nodeType,\n\n\t\t// See jQuery.data for more information\n\t\tcache = isNode ? jQuery.cache : elem,\n\t\tid = isNode ? elem[ jQuery.expando ] : jQuery.expando;\n\n\t// If there is already no cache entry for this object, there is no\n\t// purpose in continuing\n\tif ( !cache[ id ] ) {\n\t\treturn;\n\t}\n\n\tif ( name ) {\n\n\t\tthisCache = pvt ? cache[ id ] : cache[ id ].data;\n\n\t\tif ( thisCache ) {\n\n\t\t\t// Support array or space separated string names for data keys\n\t\t\tif ( !jQuery.isArray( name ) ) {\n\n\t\t\t\t// try the string as a key before any manipulation\n\t\t\t\tif ( name in thisCache ) {\n\t\t\t\t\tname = [ name ];\n\t\t\t\t} else {\n\n\t\t\t\t\t// split the camel cased version by spaces unless a key with the spaces exists\n\t\t\t\t\tname = jQuery.camelCase( name );\n\t\t\t\t\tif ( name in thisCache ) {\n\t\t\t\t\t\tname = [ name ];\n\t\t\t\t\t} else {\n\t\t\t\t\t\tname = name.split(\" \");\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// If \"name\" is an array of keys...\n\t\t\t\t// When data is initially created, via (\"key\", \"val\") signature,\n\t\t\t\t// keys will be converted to camelCase.\n\t\t\t\t// Since there is no way to tell _how_ a key was added, remove\n\t\t\t\t// both plain key and camelCase key. #12786\n\t\t\t\t// This will only penalize the array argument path.\n\t\t\t\tname = name.concat( jQuery.map( name, jQuery.camelCase ) );\n\t\t\t}\n\n\t\t\tfor ( i = 0, l = name.length; i < l; i++ ) {\n\t\t\t\tdelete thisCache[ name[i] ];\n\t\t\t}\n\n\t\t\t// If there is no data left in the cache, we want to continue\n\t\t\t// and let the cache object itself get destroyed\n\t\t\tif ( !( pvt ? isEmptyDataObject : jQuery.isEmptyObject )( thisCache ) ) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t}\n\n\t// See jQuery.data for more information\n\tif ( !pvt ) {\n\t\tdelete cache[ id ].data;\n\n\t\t// Don't destroy the parent cache unless the internal data object\n\t\t// had been the only thing left in it\n\t\tif ( !isEmptyDataObject( cache[ id ] ) ) {\n\t\t\treturn;\n\t\t}\n\t}\n\n\t// Destroy the cache\n\tif ( isNode ) {\n\t\tjQuery.cleanData( [ elem ], true );\n\n\t// Use delete when supported for expandos or `cache` is not a window per isWindow (#10080)\n\t} else if ( jQuery.support.deleteExpando || cache != cache.window ) {\n\t\tdelete cache[ id ];\n\n\t// When all else fails, null\n\t} else {\n\t\tcache[ id ] = null;\n\t}\n}\n\njQuery.extend({\n\tcache: {},\n\n\t// Unique for each copy of jQuery on the page\n\t// Non-digits removed to match rinlinejQuery\n\texpando: \"jQuery\" + ( core_version + Math.random() ).replace( /\\D/g, \"\" ),\n\n\t// The following elements throw uncatchable exceptions if you\n\t// attempt to add expando properties to them.\n\tnoData: {\n\t\t\"embed\": true,\n\t\t// Ban all objects except for Flash (which handle expandos)\n\t\t\"object\": \"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000\",\n\t\t\"applet\": true\n\t},\n\n\thasData: function( elem ) {\n\t\telem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ];\n\t\treturn !!elem && !isEmptyDataObject( elem );\n\t},\n\n\tdata: function( elem, name, data ) {\n\t\treturn internalData( elem, name, data );\n\t},\n\n\tremoveData: function( elem, name ) {\n\t\treturn internalRemoveData( elem, name );\n\t},\n\n\t// For internal use only.\n\t_data: function( elem, name, data ) {\n\t\treturn internalData( elem, name, data, true );\n\t},\n\n\t_removeData: function( elem, name ) {\n\t\treturn internalRemoveData( elem, name, true );\n\t},\n\n\t// A method for determining if a DOM node can handle the data expando\n\tacceptData: function( elem ) {\n\t\t// Do not set data on non-element because it will not be cleared (#8335).\n\t\tif ( elem.nodeType && elem.nodeType !== 1 && elem.nodeType !== 9 ) {\n\t\t\treturn false;\n\t\t}\n\n\t\tvar noData = elem.nodeName && jQuery.noData[ elem.nodeName.toLowerCase() ];\n\n\t\t// nodes accept data unless otherwise specified; rejection can be conditional\n\t\treturn !noData || noData !== true && elem.getAttribute(\"classid\") === noData;\n\t}\n});\n\njQuery.fn.extend({\n\tdata: function( key, value ) {\n\t\tvar attrs, name,\n\t\t\telem = this[0],\n\t\t\ti = 0,\n\t\t\tdata = null;\n\n\t\t// Gets all values\n\t\tif ( key === undefined ) {\n\t\t\tif ( this.length ) {\n\t\t\t\tdata = jQuery.data( elem );\n\n\t\t\t\tif ( elem.nodeType === 1 && !jQuery._data( elem, \"parsedAttrs\" ) ) {\n\t\t\t\t\tattrs = elem.attributes;\n\t\t\t\t\tfor ( ; i < attrs.length; i++ ) {\n\t\t\t\t\t\tname = attrs[i].name;\n\n\t\t\t\t\t\tif ( !name.indexOf( \"data-\" ) ) {\n\t\t\t\t\t\t\tname = jQuery.camelCase( name.slice(5) );\n\n\t\t\t\t\t\t\tdataAttr( elem, name, data[ name ] );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tjQuery._data( elem, \"parsedAttrs\", true );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn data;\n\t\t}\n\n\t\t// Sets multiple values\n\t\tif ( typeof key === \"object\" ) {\n\t\t\treturn this.each(function() {\n\t\t\t\tjQuery.data( this, key );\n\t\t\t});\n\t\t}\n\n\t\treturn jQuery.access( this, function( value ) {\n\n\t\t\tif ( value === undefined ) {\n\t\t\t\t// Try to fetch any internally stored data first\n\t\t\t\treturn elem ? dataAttr( elem, key, jQuery.data( elem, key ) ) : null;\n\t\t\t}\n\n\t\t\tthis.each(function() {\n\t\t\t\tjQuery.data( this, key, value );\n\t\t\t});\n\t\t}, null, value, arguments.length > 1, null, true );\n\t},\n\n\tremoveData: function( key ) {\n\t\treturn this.each(function() {\n\t\t\tjQuery.removeData( this, key );\n\t\t});\n\t}\n});\n\nfunction dataAttr( elem, key, data ) {\n\t// If nothing was found internally, try to fetch any\n\t// data from the HTML5 data-* attribute\n\tif ( data === undefined && elem.nodeType === 1 ) {\n\n\t\tvar name = \"data-\" + key.replace( rmultiDash, \"-$1\" ).toLowerCase();\n\n\t\tdata = elem.getAttribute( name );\n\n\t\tif ( typeof data === \"string\" ) {\n\t\t\ttry {\n\t\t\t\tdata = data === \"true\" ? true :\n\t\t\t\t\tdata === \"false\" ? false :\n\t\t\t\t\tdata === \"null\" ? null :\n\t\t\t\t\t// Only convert to a number if it doesn't change the string\n\t\t\t\t\t+data + \"\" === data ? +data :\n\t\t\t\t\trbrace.test( data ) ? jQuery.parseJSON( data ) :\n\t\t\t\t\t\tdata;\n\t\t\t} catch( e ) {}\n\n\t\t\t// Make sure we set the data so it isn't changed later\n\t\t\tjQuery.data( elem, key, data );\n\n\t\t} else {\n\t\t\tdata = undefined;\n\t\t}\n\t}\n\n\treturn data;\n}\n\n// checks a cache object for emptiness\nfunction isEmptyDataObject( obj ) {\n\tvar name;\n\tfor ( name in obj ) {\n\n\t\t// if the public data object is empty, the private is still empty\n\t\tif ( name === \"data\" && jQuery.isEmptyObject( obj[name] ) ) {\n\t\t\tcontinue;\n\t\t}\n\t\tif ( name !== \"toJSON\" ) {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\treturn true;\n}\njQuery.extend({\n\tqueue: function( elem, type, data ) {\n\t\tvar queue;\n\n\t\tif ( elem ) {\n\t\t\ttype = ( type || \"fx\" ) + \"queue\";\n\t\t\tqueue = jQuery._data( elem, type );\n\n\t\t\t// Speed up dequeue by getting out quickly if this is just a lookup\n\t\t\tif ( data ) {\n\t\t\t\tif ( !queue || jQuery.isArray(data) ) {\n\t\t\t\t\tqueue = jQuery._data( elem, type, jQuery.makeArray(data) );\n\t\t\t\t} else {\n\t\t\t\t\tqueue.push( data );\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn queue || [];\n\t\t}\n\t},\n\n\tdequeue: function( elem, type ) {\n\t\ttype = type || \"fx\";\n\n\t\tvar queue = jQuery.queue( elem, type ),\n\t\t\tstartLength = queue.length,\n\t\t\tfn = queue.shift(),\n\t\t\thooks = jQuery._queueHooks( elem, type ),\n\t\t\tnext = function() {\n\t\t\t\tjQuery.dequeue( elem, type );\n\t\t\t};\n\n\t\t// If the fx queue is dequeued, always remove the progress sentinel\n\t\tif ( fn === \"inprogress\" ) {\n\t\t\tfn = queue.shift();\n\t\t\tstartLength--;\n\t\t}\n\n\t\thooks.cur = fn;\n\t\tif ( fn ) {\n\n\t\t\t// Add a progress sentinel to prevent the fx queue from being\n\t\t\t// automatically dequeued\n\t\t\tif ( type === \"fx\" ) {\n\t\t\t\tqueue.unshift( \"inprogress\" );\n\t\t\t}\n\n\t\t\t// clear up the last queue stop function\n\t\t\tdelete hooks.stop;\n\t\t\tfn.call( elem, next, hooks );\n\t\t}\n\n\t\tif ( !startLength && hooks ) {\n\t\t\thooks.empty.fire();\n\t\t}\n\t},\n\n\t// not intended for public consumption - generates a queueHooks object, or returns the current one\n\t_queueHooks: function( elem, type ) {\n\t\tvar key = type + \"queueHooks\";\n\t\treturn jQuery._data( elem, key ) || jQuery._data( elem, key, {\n\t\t\tempty: jQuery.Callbacks(\"once memory\").add(function() {\n\t\t\t\tjQuery._removeData( elem, type + \"queue\" );\n\t\t\t\tjQuery._removeData( elem, key );\n\t\t\t})\n\t\t});\n\t}\n});\n\njQuery.fn.extend({\n\tqueue: function( type, data ) {\n\t\tvar setter = 2;\n\n\t\tif ( typeof type !== \"string\" ) {\n\t\t\tdata = type;\n\t\t\ttype = \"fx\";\n\t\t\tsetter--;\n\t\t}\n\n\t\tif ( arguments.length < setter ) {\n\t\t\treturn jQuery.queue( this[0], type );\n\t\t}\n\n\t\treturn data === undefined ?\n\t\t\tthis :\n\t\t\tthis.each(function() {\n\t\t\t\tvar queue = jQuery.queue( this, type, data );\n\n\t\t\t\t// ensure a hooks for this queue\n\t\t\t\tjQuery._queueHooks( this, type );\n\n\t\t\t\tif ( type === \"fx\" && queue[0] !== \"inprogress\" ) {\n\t\t\t\t\tjQuery.dequeue( this, type );\n\t\t\t\t}\n\t\t\t});\n\t},\n\tdequeue: function( type ) {\n\t\treturn this.each(function() {\n\t\t\tjQuery.dequeue( this, type );\n\t\t});\n\t},\n\t// Based off of the plugin by Clint Helfers, with permission.\n\t// http://blindsignals.com/index.php/2009/07/jquery-delay/\n\tdelay: function( time, type ) {\n\t\ttime = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time;\n\t\ttype = type || \"fx\";\n\n\t\treturn this.queue( type, function( next, hooks ) {\n\t\t\tvar timeout = setTimeout( next, time );\n\t\t\thooks.stop = function() {\n\t\t\t\tclearTimeout( timeout );\n\t\t\t};\n\t\t});\n\t},\n\tclearQueue: function( type ) {\n\t\treturn this.queue( type || \"fx\", [] );\n\t},\n\t// Get a promise resolved when queues of a certain type\n\t// are emptied (fx is the type by default)\n\tpromise: function( type, obj ) {\n\t\tvar tmp,\n\t\t\tcount = 1,\n\t\t\tdefer = jQuery.Deferred(),\n\t\t\telements = this,\n\t\t\ti = this.length,\n\t\t\tresolve = function() {\n\t\t\t\tif ( !( --count ) ) {\n\t\t\t\t\tdefer.resolveWith( elements, [ elements ] );\n\t\t\t\t}\n\t\t\t};\n\n\t\tif ( typeof type !== \"string\" ) {\n\t\t\tobj = type;\n\t\t\ttype = undefined;\n\t\t}\n\t\ttype = type || \"fx\";\n\n\t\twhile( i-- ) {\n\t\t\ttmp = jQuery._data( elements[ i ], type + \"queueHooks\" );\n\t\t\tif ( tmp && tmp.empty ) {\n\t\t\t\tcount++;\n\t\t\t\ttmp.empty.add( resolve );\n\t\t\t}\n\t\t}\n\t\tresolve();\n\t\treturn defer.promise( obj );\n\t}\n});\nvar nodeHook, boolHook,\n\trclass = /[\\t\\r\\n]/g,\n\trreturn = /\\r/g,\n\trfocusable = /^(?:input|select|textarea|button|object)$/i,\n\trclickable = /^(?:a|area)$/i,\n\trboolean = /^(?:checked|selected|autofocus|autoplay|async|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped)$/i,\n\truseDefault = /^(?:checked|selected)$/i,\n\tgetSetAttribute = jQuery.support.getSetAttribute,\n\tgetSetInput = jQuery.support.input;\n\njQuery.fn.extend({\n\tattr: function( name, value ) {\n\t\treturn jQuery.access( this, jQuery.attr, name, value, arguments.length > 1 );\n\t},\n\n\tremoveAttr: function( name ) {\n\t\treturn this.each(function() {\n\t\t\tjQuery.removeAttr( this, name );\n\t\t});\n\t},\n\n\tprop: function( name, value ) {\n\t\treturn jQuery.access( this, jQuery.prop, name, value, arguments.length > 1 );\n\t},\n\n\tremoveProp: function( name ) {\n\t\tname = jQuery.propFix[ name ] || name;\n\t\treturn this.each(function() {\n\t\t\t// try/catch handles cases where IE balks (such as removing a property on window)\n\t\t\ttry {\n\t\t\t\tthis[ name ] = undefined;\n\t\t\t\tdelete this[ name ];\n\t\t\t} catch( e ) {}\n\t\t});\n\t},\n\n\taddClass: function( value ) {\n\t\tvar classes, elem, cur, clazz, j,\n\t\t\ti = 0,\n\t\t\tlen = this.length,\n\t\t\tproceed = typeof value === \"string\" && value;\n\n\t\tif ( jQuery.isFunction( value ) ) {\n\t\t\treturn this.each(function( j ) {\n\t\t\t\tjQuery( this ).addClass( value.call( this, j, this.className ) );\n\t\t\t});\n\t\t}\n\n\t\tif ( proceed ) {\n\t\t\t// The disjunction here is for better compressibility (see removeClass)\n\t\t\tclasses = ( value || \"\" ).match( core_rnotwhite ) || [];\n\n\t\t\tfor ( ; i < len; i++ ) {\n\t\t\t\telem = this[ i ];\n\t\t\t\tcur = elem.nodeType === 1 && ( elem.className ?\n\t\t\t\t\t( \" \" + elem.className + \" \" ).replace( rclass, \" \" ) :\n\t\t\t\t\t\" \"\n\t\t\t\t);\n\n\t\t\t\tif ( cur ) {\n\t\t\t\t\tj = 0;\n\t\t\t\t\twhile ( (clazz = classes[j++]) ) {\n\t\t\t\t\t\tif ( cur.indexOf( \" \" + clazz + \" \" ) < 0 ) {\n\t\t\t\t\t\t\tcur += clazz + \" \";\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\telem.className = jQuery.trim( cur );\n\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\tremoveClass: function( value ) {\n\t\tvar classes, elem, cur, clazz, j,\n\t\t\ti = 0,\n\t\t\tlen = this.length,\n\t\t\tproceed = arguments.length === 0 || typeof value === \"string\" && value;\n\n\t\tif ( jQuery.isFunction( value ) ) {\n\t\t\treturn this.each(function( j ) {\n\t\t\t\tjQuery( this ).removeClass( value.call( this, j, this.className ) );\n\t\t\t});\n\t\t}\n\t\tif ( proceed ) {\n\t\t\tclasses = ( value || \"\" ).match( core_rnotwhite ) || [];\n\n\t\t\tfor ( ; i < len; i++ ) {\n\t\t\t\telem = this[ i ];\n\t\t\t\t// This expression is here for better compressibility (see addClass)\n\t\t\t\tcur = elem.nodeType === 1 && ( elem.className ?\n\t\t\t\t\t( \" \" + elem.className + \" \" ).replace( rclass, \" \" ) :\n\t\t\t\t\t\"\"\n\t\t\t\t);\n\n\t\t\t\tif ( cur ) {\n\t\t\t\t\tj = 0;\n\t\t\t\t\twhile ( (clazz = classes[j++]) ) {\n\t\t\t\t\t\t// Remove *all* instances\n\t\t\t\t\t\twhile ( cur.indexOf( \" \" + clazz + \" \" ) >= 0 ) {\n\t\t\t\t\t\t\tcur = cur.replace( \" \" + clazz + \" \", \" \" );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\telem.className = value ? jQuery.trim( cur ) : \"\";\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\ttoggleClass: function( value, stateVal ) {\n\t\tvar type = typeof value,\n\t\t\tisBool = typeof stateVal === \"boolean\";\n\n\t\tif ( jQuery.isFunction( value ) ) {\n\t\t\treturn this.each(function( i ) {\n\t\t\t\tjQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal );\n\t\t\t});\n\t\t}\n\n\t\treturn this.each(function() {\n\t\t\tif ( type === \"string\" ) {\n\t\t\t\t// toggle individual class names\n\t\t\t\tvar className,\n\t\t\t\t\ti = 0,\n\t\t\t\t\tself = jQuery( this ),\n\t\t\t\t\tstate = stateVal,\n\t\t\t\t\tclassNames = value.match( core_rnotwhite ) || [];\n\n\t\t\t\twhile ( (className = classNames[ i++ ]) ) {\n\t\t\t\t\t// check each className given, space separated list\n\t\t\t\t\tstate = isBool ? state : !self.hasClass( className );\n\t\t\t\t\tself[ state ? \"addClass\" : \"removeClass\" ]( className );\n\t\t\t\t}\n\n\t\t\t// Toggle whole class name\n\t\t\t} else if ( type === core_strundefined || type === \"boolean\" ) {\n\t\t\t\tif ( this.className ) {\n\t\t\t\t\t// store className if set\n\t\t\t\t\tjQuery._data( this, \"__className__\", this.className );\n\t\t\t\t}\n\n\t\t\t\t// If the element has a class name or if we're passed \"false\",\n\t\t\t\t// then remove the whole classname (if there was one, the above saved it).\n\t\t\t\t// Otherwise bring back whatever was previously saved (if anything),\n\t\t\t\t// falling back to the empty string if nothing was stored.\n\t\t\t\tthis.className = this.className || value === false ? \"\" : jQuery._data( this, \"__className__\" ) || \"\";\n\t\t\t}\n\t\t});\n\t},\n\n\thasClass: function( selector ) {\n\t\tvar className = \" \" + selector + \" \",\n\t\t\ti = 0,\n\t\t\tl = this.length;\n\t\tfor ( ; i < l; i++ ) {\n\t\t\tif ( this[i].nodeType === 1 && (\" \" + this[i].className + \" \").replace(rclass, \" \").indexOf( className ) >= 0 ) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\n\t\treturn false;\n\t},\n\n\tval: function( value ) {\n\t\tvar ret, hooks, isFunction,\n\t\t\telem = this[0];\n\n\t\tif ( !arguments.length ) {\n\t\t\tif ( elem ) {\n\t\t\t\thooks = jQuery.valHooks[ elem.type ] || jQuery.valHooks[ elem.nodeName.toLowerCase() ];\n\n\t\t\t\tif ( hooks && \"get\" in hooks && (ret = hooks.get( elem, \"value\" )) !== undefined ) {\n\t\t\t\t\treturn ret;\n\t\t\t\t}\n\n\t\t\t\tret = elem.value;\n\n\t\t\t\treturn typeof ret === \"string\" ?\n\t\t\t\t\t// handle most common string cases\n\t\t\t\t\tret.replace(rreturn, \"\") :\n\t\t\t\t\t// handle cases where value is null/undef or number\n\t\t\t\t\tret == null ? \"\" : ret;\n\t\t\t}\n\n\t\t\treturn;\n\t\t}\n\n\t\tisFunction = jQuery.isFunction( value );\n\n\t\treturn this.each(function( i ) {\n\t\t\tvar val,\n\t\t\t\tself = jQuery(this);\n\n\t\t\tif ( this.nodeType !== 1 ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif ( isFunction ) {\n\t\t\t\tval = value.call( this, i, self.val() );\n\t\t\t} else {\n\t\t\t\tval = value;\n\t\t\t}\n\n\t\t\t// Treat null/undefined as \"\"; convert numbers to string\n\t\t\tif ( val == null ) {\n\t\t\t\tval = \"\";\n\t\t\t} else if ( typeof val === \"number\" ) {\n\t\t\t\tval += \"\";\n\t\t\t} else if ( jQuery.isArray( val ) ) {\n\t\t\t\tval = jQuery.map(val, function ( value ) {\n\t\t\t\t\treturn value == null ? \"\" : value + \"\";\n\t\t\t\t});\n\t\t\t}\n\n\t\t\thooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ];\n\n\t\t\t// If set returns undefined, fall back to normal setting\n\t\t\tif ( !hooks || !(\"set\" in hooks) || hooks.set( this, val, \"value\" ) === undefined ) {\n\t\t\t\tthis.value = val;\n\t\t\t}\n\t\t});\n\t}\n});\n\njQuery.extend({\n\tvalHooks: {\n\t\toption: {\n\t\t\tget: function( elem ) {\n\t\t\t\t// attributes.value is undefined in Blackberry 4.7 but\n\t\t\t\t// uses .value. See #6932\n\t\t\t\tvar val = elem.attributes.value;\n\t\t\t\treturn !val || val.specified ? elem.value : elem.text;\n\t\t\t}\n\t\t},\n\t\tselect: {\n\t\t\tget: function( elem ) {\n\t\t\t\tvar value, option,\n\t\t\t\t\toptions = elem.options,\n\t\t\t\t\tindex = elem.selectedIndex,\n\t\t\t\t\tone = elem.type === \"select-one\" || index < 0,\n\t\t\t\t\tvalues = one ? null : [],\n\t\t\t\t\tmax = one ? index + 1 : options.length,\n\t\t\t\t\ti = index < 0 ?\n\t\t\t\t\t\tmax :\n\t\t\t\t\t\tone ? index : 0;\n\n\t\t\t\t// Loop through all the selected options\n\t\t\t\tfor ( ; i < max; i++ ) {\n\t\t\t\t\toption = options[ i ];\n\n\t\t\t\t\t// oldIE doesn't update selected after form reset (#2551)\n\t\t\t\t\tif ( ( option.selected || i === index ) &&\n\t\t\t\t\t\t\t// Don't return options that are disabled or in a disabled optgroup\n\t\t\t\t\t\t\t( jQuery.support.optDisabled ? !option.disabled : option.getAttribute(\"disabled\") === null ) &&\n\t\t\t\t\t\t\t( !option.parentNode.disabled || !jQuery.nodeName( option.parentNode, \"optgroup\" ) ) ) {\n\n\t\t\t\t\t\t// Get the specific value for the option\n\t\t\t\t\t\tvalue = jQuery( option ).val();\n\n\t\t\t\t\t\t// We don't need an array for one selects\n\t\t\t\t\t\tif ( one ) {\n\t\t\t\t\t\t\treturn value;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Multi-Selects return an array\n\t\t\t\t\t\tvalues.push( value );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn values;\n\t\t\t},\n\n\t\t\tset: function( elem, value ) {\n\t\t\t\tvar values = jQuery.makeArray( value );\n\n\t\t\t\tjQuery(elem).find(\"option\").each(function() {\n\t\t\t\t\tthis.selected = jQuery.inArray( jQuery(this).val(), values ) >= 0;\n\t\t\t\t});\n\n\t\t\t\tif ( !values.length ) {\n\t\t\t\t\telem.selectedIndex = -1;\n\t\t\t\t}\n\t\t\t\treturn values;\n\t\t\t}\n\t\t}\n\t},\n\n\tattr: function( elem, name, value ) {\n\t\tvar hooks, notxml, ret,\n\t\t\tnType = elem.nodeType;\n\n\t\t// don't get/set attributes on text, comment and attribute nodes\n\t\tif ( !elem || nType === 3 || nType === 8 || nType === 2 ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Fallback to prop when attributes are not supported\n\t\tif ( typeof elem.getAttribute === core_strundefined ) {\n\t\t\treturn jQuery.prop( elem, name, value );\n\t\t}\n\n\t\tnotxml = nType !== 1 || !jQuery.isXMLDoc( elem );\n\n\t\t// All attributes are lowercase\n\t\t// Grab necessary hook if one is defined\n\t\tif ( notxml ) {\n\t\t\tname = name.toLowerCase();\n\t\t\thooks = jQuery.attrHooks[ name ] || ( rboolean.test( name ) ? boolHook : nodeHook );\n\t\t}\n\n\t\tif ( value !== undefined ) {\n\n\t\t\tif ( value === null ) {\n\t\t\t\tjQuery.removeAttr( elem, name );\n\n\t\t\t} else if ( hooks && notxml && \"set\" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) {\n\t\t\t\treturn ret;\n\n\t\t\t} else {\n\t\t\t\telem.setAttribute( name, value + \"\" );\n\t\t\t\treturn value;\n\t\t\t}\n\n\t\t} else if ( hooks && notxml && \"get\" in hooks && (ret = hooks.get( elem, name )) !== null ) {\n\t\t\treturn ret;\n\n\t\t} else {\n\n\t\t\t// In IE9+, Flash objects don't have .getAttribute (#12945)\n\t\t\t// Support: IE9+\n\t\t\tif ( typeof elem.getAttribute !== core_strundefined ) {\n\t\t\t\tret =  elem.getAttribute( name );\n\t\t\t}\n\n\t\t\t// Non-existent attributes return null, we normalize to undefined\n\t\t\treturn ret == null ?\n\t\t\t\tundefined :\n\t\t\t\tret;\n\t\t}\n\t},\n\n\tremoveAttr: function( elem, value ) {\n\t\tvar name, propName,\n\t\t\ti = 0,\n\t\t\tattrNames = value && value.match( core_rnotwhite );\n\n\t\tif ( attrNames && elem.nodeType === 1 ) {\n\t\t\twhile ( (name = attrNames[i++]) ) {\n\t\t\t\tpropName = jQuery.propFix[ name ] || name;\n\n\t\t\t\t// Boolean attributes get special treatment (#10870)\n\t\t\t\tif ( rboolean.test( name ) ) {\n\t\t\t\t\t// Set corresponding property to false for boolean attributes\n\t\t\t\t\t// Also clear defaultChecked/defaultSelected (if appropriate) for IE<8\n\t\t\t\t\tif ( !getSetAttribute && ruseDefault.test( name ) ) {\n\t\t\t\t\t\telem[ jQuery.camelCase( \"default-\" + name ) ] =\n\t\t\t\t\t\t\telem[ propName ] = false;\n\t\t\t\t\t} else {\n\t\t\t\t\t\telem[ propName ] = false;\n\t\t\t\t\t}\n\n\t\t\t\t// See #9699 for explanation of this approach (setting first, then removal)\n\t\t\t\t} else {\n\t\t\t\t\tjQuery.attr( elem, name, \"\" );\n\t\t\t\t}\n\n\t\t\t\telem.removeAttribute( getSetAttribute ? name : propName );\n\t\t\t}\n\t\t}\n\t},\n\n\tattrHooks: {\n\t\ttype: {\n\t\t\tset: function( elem, value ) {\n\t\t\t\tif ( !jQuery.support.radioValue && value === \"radio\" && jQuery.nodeName(elem, \"input\") ) {\n\t\t\t\t\t// Setting the type on a radio button after the value resets the value in IE6-9\n\t\t\t\t\t// Reset value to default in case type is set after value during creation\n\t\t\t\t\tvar val = elem.value;\n\t\t\t\t\telem.setAttribute( \"type\", value );\n\t\t\t\t\tif ( val ) {\n\t\t\t\t\t\telem.value = val;\n\t\t\t\t\t}\n\t\t\t\t\treturn value;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\n\tpropFix: {\n\t\ttabindex: \"tabIndex\",\n\t\treadonly: \"readOnly\",\n\t\t\"for\": \"htmlFor\",\n\t\t\"class\": \"className\",\n\t\tmaxlength: \"maxLength\",\n\t\tcellspacing: \"cellSpacing\",\n\t\tcellpadding: \"cellPadding\",\n\t\trowspan: \"rowSpan\",\n\t\tcolspan: \"colSpan\",\n\t\tusemap: \"useMap\",\n\t\tframeborder: \"frameBorder\",\n\t\tcontenteditable: \"contentEditable\"\n\t},\n\n\tprop: function( elem, name, value ) {\n\t\tvar ret, hooks, notxml,\n\t\t\tnType = elem.nodeType;\n\n\t\t// don't get/set properties on text, comment and attribute nodes\n\t\tif ( !elem || nType === 3 || nType === 8 || nType === 2 ) {\n\t\t\treturn;\n\t\t}\n\n\t\tnotxml = nType !== 1 || !jQuery.isXMLDoc( elem );\n\n\t\tif ( notxml ) {\n\t\t\t// Fix name and attach hooks\n\t\t\tname = jQuery.propFix[ name ] || name;\n\t\t\thooks = jQuery.propHooks[ name ];\n\t\t}\n\n\t\tif ( value !== undefined ) {\n\t\t\tif ( hooks && \"set\" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) {\n\t\t\t\treturn ret;\n\n\t\t\t} else {\n\t\t\t\treturn ( elem[ name ] = value );\n\t\t\t}\n\n\t\t} else {\n\t\t\tif ( hooks && \"get\" in hooks && (ret = hooks.get( elem, name )) !== null ) {\n\t\t\t\treturn ret;\n\n\t\t\t} else {\n\t\t\t\treturn elem[ name ];\n\t\t\t}\n\t\t}\n\t},\n\n\tpropHooks: {\n\t\ttabIndex: {\n\t\t\tget: function( elem ) {\n\t\t\t\t// elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set\n\t\t\t\t// http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/\n\t\t\t\tvar attributeNode = elem.getAttributeNode(\"tabindex\");\n\n\t\t\t\treturn attributeNode && attributeNode.specified ?\n\t\t\t\t\tparseInt( attributeNode.value, 10 ) :\n\t\t\t\t\trfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ?\n\t\t\t\t\t\t0 :\n\t\t\t\t\t\tundefined;\n\t\t\t}\n\t\t}\n\t}\n});\n\n// Hook for boolean attributes\nboolHook = {\n\tget: function( elem, name ) {\n\t\tvar\n\t\t\t// Use .prop to determine if this attribute is understood as boolean\n\t\t\tprop = jQuery.prop( elem, name ),\n\n\t\t\t// Fetch it accordingly\n\t\t\tattr = typeof prop === \"boolean\" && elem.getAttribute( name ),\n\t\t\tdetail = typeof prop === \"boolean\" ?\n\n\t\t\t\tgetSetInput && getSetAttribute ?\n\t\t\t\t\tattr != null :\n\t\t\t\t\t// oldIE fabricates an empty string for missing boolean attributes\n\t\t\t\t\t// and conflates checked/selected into attroperties\n\t\t\t\t\truseDefault.test( name ) ?\n\t\t\t\t\t\telem[ jQuery.camelCase( \"default-\" + name ) ] :\n\t\t\t\t\t\t!!attr :\n\n\t\t\t\t// fetch an attribute node for properties not recognized as boolean\n\t\t\t\telem.getAttributeNode( name );\n\n\t\treturn detail && detail.value !== false ?\n\t\t\tname.toLowerCase() :\n\t\t\tundefined;\n\t},\n\tset: function( elem, value, name ) {\n\t\tif ( value === false ) {\n\t\t\t// Remove boolean attributes when set to false\n\t\t\tjQuery.removeAttr( elem, name );\n\t\t} else if ( getSetInput && getSetAttribute || !ruseDefault.test( name ) ) {\n\t\t\t// IE<8 needs the *property* name\n\t\t\telem.setAttribute( !getSetAttribute && jQuery.propFix[ name ] || name, name );\n\n\t\t// Use defaultChecked and defaultSelected for oldIE\n\t\t} else {\n\t\t\telem[ jQuery.camelCase( \"default-\" + name ) ] = elem[ name ] = true;\n\t\t}\n\n\t\treturn name;\n\t}\n};\n\n// fix oldIE value attroperty\nif ( !getSetInput || !getSetAttribute ) {\n\tjQuery.attrHooks.value = {\n\t\tget: function( elem, name ) {\n\t\t\tvar ret = elem.getAttributeNode( name );\n\t\t\treturn jQuery.nodeName( elem, \"input\" ) ?\n\n\t\t\t\t// Ignore the value *property* by using defaultValue\n\t\t\t\telem.defaultValue :\n\n\t\t\t\tret && ret.specified ? ret.value : undefined;\n\t\t},\n\t\tset: function( elem, value, name ) {\n\t\t\tif ( jQuery.nodeName( elem, \"input\" ) ) {\n\t\t\t\t// Does not return so that setAttribute is also used\n\t\t\t\telem.defaultValue = value;\n\t\t\t} else {\n\t\t\t\t// Use nodeHook if defined (#1954); otherwise setAttribute is fine\n\t\t\t\treturn nodeHook && nodeHook.set( elem, value, name );\n\t\t\t}\n\t\t}\n\t};\n}\n\n// IE6/7 do not support getting/setting some attributes with get/setAttribute\nif ( !getSetAttribute ) {\n\n\t// Use this for any attribute in IE6/7\n\t// This fixes almost every IE6/7 issue\n\tnodeHook = jQuery.valHooks.button = {\n\t\tget: function( elem, name ) {\n\t\t\tvar ret = elem.getAttributeNode( name );\n\t\t\treturn ret && ( name === \"id\" || name === \"name\" || name === \"coords\" ? ret.value !== \"\" : ret.specified ) ?\n\t\t\t\tret.value :\n\t\t\t\tundefined;\n\t\t},\n\t\tset: function( elem, value, name ) {\n\t\t\t// Set the existing or create a new attribute node\n\t\t\tvar ret = elem.getAttributeNode( name );\n\t\t\tif ( !ret ) {\n\t\t\t\telem.setAttributeNode(\n\t\t\t\t\t(ret = elem.ownerDocument.createAttribute( name ))\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tret.value = value += \"\";\n\n\t\t\t// Break association with cloned elements by also using setAttribute (#9646)\n\t\t\treturn name === \"value\" || value === elem.getAttribute( name ) ?\n\t\t\t\tvalue :\n\t\t\t\tundefined;\n\t\t}\n\t};\n\n\t// Set contenteditable to false on removals(#10429)\n\t// Setting to empty string throws an error as an invalid value\n\tjQuery.attrHooks.contenteditable = {\n\t\tget: nodeHook.get,\n\t\tset: function( elem, value, name ) {\n\t\t\tnodeHook.set( elem, value === \"\" ? false : value, name );\n\t\t}\n\t};\n\n\t// Set width and height to auto instead of 0 on empty string( Bug #8150 )\n\t// This is for removals\n\tjQuery.each([ \"width\", \"height\" ], function( i, name ) {\n\t\tjQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], {\n\t\t\tset: function( elem, value ) {\n\t\t\t\tif ( value === \"\" ) {\n\t\t\t\t\telem.setAttribute( name, \"auto\" );\n\t\t\t\t\treturn value;\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t});\n}\n\n\n// Some attributes require a special call on IE\n// http://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx\nif ( !jQuery.support.hrefNormalized ) {\n\tjQuery.each([ \"href\", \"src\", \"width\", \"height\" ], function( i, name ) {\n\t\tjQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], {\n\t\t\tget: function( elem ) {\n\t\t\t\tvar ret = elem.getAttribute( name, 2 );\n\t\t\t\treturn ret == null ? undefined : ret;\n\t\t\t}\n\t\t});\n\t});\n\n\t// href/src property should get the full normalized URL (#10299/#12915)\n\tjQuery.each([ \"href\", \"src\" ], function( i, name ) {\n\t\tjQuery.propHooks[ name ] = {\n\t\t\tget: function( elem ) {\n\t\t\t\treturn elem.getAttribute( name, 4 );\n\t\t\t}\n\t\t};\n\t});\n}\n\nif ( !jQuery.support.style ) {\n\tjQuery.attrHooks.style = {\n\t\tget: function( elem ) {\n\t\t\t// Return undefined in the case of empty string\n\t\t\t// Note: IE uppercases css property names, but if we were to .toLowerCase()\n\t\t\t// .cssText, that would destroy case senstitivity in URL's, like in \"background\"\n\t\t\treturn elem.style.cssText || undefined;\n\t\t},\n\t\tset: function( elem, value ) {\n\t\t\treturn ( elem.style.cssText = value + \"\" );\n\t\t}\n\t};\n}\n\n// Safari mis-reports the default selected property of an option\n// Accessing the parent's selectedIndex property fixes it\nif ( !jQuery.support.optSelected ) {\n\tjQuery.propHooks.selected = jQuery.extend( jQuery.propHooks.selected, {\n\t\tget: function( elem ) {\n\t\t\tvar parent = elem.parentNode;\n\n\t\t\tif ( parent ) {\n\t\t\t\tparent.selectedIndex;\n\n\t\t\t\t// Make sure that it also works with optgroups, see #5701\n\t\t\t\tif ( parent.parentNode ) {\n\t\t\t\t\tparent.parentNode.selectedIndex;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn null;\n\t\t}\n\t});\n}\n\n// IE6/7 call enctype encoding\nif ( !jQuery.support.enctype ) {\n\tjQuery.propFix.enctype = \"encoding\";\n}\n\n// Radios and checkboxes getter/setter\nif ( !jQuery.support.checkOn ) {\n\tjQuery.each([ \"radio\", \"checkbox\" ], function() {\n\t\tjQuery.valHooks[ this ] = {\n\t\t\tget: function( elem ) {\n\t\t\t\t// Handle the case where in Webkit \"\" is returned instead of \"on\" if a value isn't specified\n\t\t\t\treturn elem.getAttribute(\"value\") === null ? \"on\" : elem.value;\n\t\t\t}\n\t\t};\n\t});\n}\njQuery.each([ \"radio\", \"checkbox\" ], function() {\n\tjQuery.valHooks[ this ] = jQuery.extend( jQuery.valHooks[ this ], {\n\t\tset: function( elem, value ) {\n\t\t\tif ( jQuery.isArray( value ) ) {\n\t\t\t\treturn ( elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0 );\n\t\t\t}\n\t\t}\n\t});\n});\nvar rformElems = /^(?:input|select|textarea)$/i,\n\trkeyEvent = /^key/,\n\trmouseEvent = /^(?:mouse|contextmenu)|click/,\n\trfocusMorph = /^(?:focusinfocus|focusoutblur)$/,\n\trtypenamespace = /^([^.]*)(?:\\.(.+)|)$/;\n\nfunction returnTrue() {\n\treturn true;\n}\n\nfunction returnFalse() {\n\treturn false;\n}\n\n/*\n * Helper functions for managing events -- not part of the public interface.\n * Props to Dean Edwards' addEvent library for many of the ideas.\n */\njQuery.event = {\n\n\tglobal: {},\n\n\tadd: function( elem, types, handler, data, selector ) {\n\t\tvar tmp, events, t, handleObjIn,\n\t\t\tspecial, eventHandle, handleObj,\n\t\t\thandlers, type, namespaces, origType,\n\t\t\telemData = jQuery._data( elem );\n\n\t\t// Don't attach events to noData or text/comment nodes (but allow plain objects)\n\t\tif ( !elemData ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Caller can pass in an object of custom data in lieu of the handler\n\t\tif ( handler.handler ) {\n\t\t\thandleObjIn = handler;\n\t\t\thandler = handleObjIn.handler;\n\t\t\tselector = handleObjIn.selector;\n\t\t}\n\n\t\t// Make sure that the handler has a unique ID, used to find/remove it later\n\t\tif ( !handler.guid ) {\n\t\t\thandler.guid = jQuery.guid++;\n\t\t}\n\n\t\t// Init the element's event structure and main handler, if this is the first\n\t\tif ( !(events = elemData.events) ) {\n\t\t\tevents = elemData.events = {};\n\t\t}\n\t\tif ( !(eventHandle = elemData.handle) ) {\n\t\t\teventHandle = elemData.handle = function( e ) {\n\t\t\t\t// Discard the second event of a jQuery.event.trigger() and\n\t\t\t\t// when an event is called after a page has unloaded\n\t\t\t\treturn typeof jQuery !== core_strundefined && (!e || jQuery.event.triggered !== e.type) ?\n\t\t\t\t\tjQuery.event.dispatch.apply( eventHandle.elem, arguments ) :\n\t\t\t\t\tundefined;\n\t\t\t};\n\t\t\t// Add elem as a property of the handle fn to prevent a memory leak with IE non-native events\n\t\t\teventHandle.elem = elem;\n\t\t}\n\n\t\t// Handle multiple events separated by a space\n\t\t// jQuery(...).bind(\"mouseover mouseout\", fn);\n\t\ttypes = ( types || \"\" ).match( core_rnotwhite ) || [\"\"];\n\t\tt = types.length;\n\t\twhile ( t-- ) {\n\t\t\ttmp = rtypenamespace.exec( types[t] ) || [];\n\t\t\ttype = origType = tmp[1];\n\t\t\tnamespaces = ( tmp[2] || \"\" ).split( \".\" ).sort();\n\n\t\t\t// If event changes its type, use the special event handlers for the changed type\n\t\t\tspecial = jQuery.event.special[ type ] || {};\n\n\t\t\t// If selector defined, determine special event api type, otherwise given type\n\t\t\ttype = ( selector ? special.delegateType : special.bindType ) || type;\n\n\t\t\t// Update special based on newly reset type\n\t\t\tspecial = jQuery.event.special[ type ] || {};\n\n\t\t\t// handleObj is passed to all event handlers\n\t\t\thandleObj = jQuery.extend({\n\t\t\t\ttype: type,\n\t\t\t\torigType: origType,\n\t\t\t\tdata: data,\n\t\t\t\thandler: handler,\n\t\t\t\tguid: handler.guid,\n\t\t\t\tselector: selector,\n\t\t\t\tneedsContext: selector && jQuery.expr.match.needsContext.test( selector ),\n\t\t\t\tnamespace: namespaces.join(\".\")\n\t\t\t}, handleObjIn );\n\n\t\t\t// Init the event handler queue if we're the first\n\t\t\tif ( !(handlers = events[ type ]) ) {\n\t\t\t\thandlers = events[ type ] = [];\n\t\t\t\thandlers.delegateCount = 0;\n\n\t\t\t\t// Only use addEventListener/attachEvent if the special events handler returns false\n\t\t\t\tif ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) {\n\t\t\t\t\t// Bind the global event handler to the element\n\t\t\t\t\tif ( elem.addEventListener ) {\n\t\t\t\t\t\telem.addEventListener( type, eventHandle, false );\n\n\t\t\t\t\t} else if ( elem.attachEvent ) {\n\t\t\t\t\t\telem.attachEvent( \"on\" + type, eventHandle );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( special.add ) {\n\t\t\t\tspecial.add.call( elem, handleObj );\n\n\t\t\t\tif ( !handleObj.handler.guid ) {\n\t\t\t\t\thandleObj.handler.guid = handler.guid;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Add to the element's handler list, delegates in front\n\t\t\tif ( selector ) {\n\t\t\t\thandlers.splice( handlers.delegateCount++, 0, handleObj );\n\t\t\t} else {\n\t\t\t\thandlers.push( handleObj );\n\t\t\t}\n\n\t\t\t// Keep track of which events have ever been used, for event optimization\n\t\t\tjQuery.event.global[ type ] = true;\n\t\t}\n\n\t\t// Nullify elem to prevent memory leaks in IE\n\t\telem = null;\n\t},\n\n\t// Detach an event or set of events from an element\n\tremove: function( elem, types, handler, selector, mappedTypes ) {\n\t\tvar j, handleObj, tmp,\n\t\t\torigCount, t, events,\n\t\t\tspecial, handlers, type,\n\t\t\tnamespaces, origType,\n\t\t\telemData = jQuery.hasData( elem ) && jQuery._data( elem );\n\n\t\tif ( !elemData || !(events = elemData.events) ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Once for each type.namespace in types; type may be omitted\n\t\ttypes = ( types || \"\" ).match( core_rnotwhite ) || [\"\"];\n\t\tt = types.length;\n\t\twhile ( t-- ) {\n\t\t\ttmp = rtypenamespace.exec( types[t] ) || [];\n\t\t\ttype = origType = tmp[1];\n\t\t\tnamespaces = ( tmp[2] || \"\" ).split( \".\" ).sort();\n\n\t\t\t// Unbind all events (on this namespace, if provided) for the element\n\t\t\tif ( !type ) {\n\t\t\t\tfor ( type in events ) {\n\t\t\t\t\tjQuery.event.remove( elem, type + types[ t ], handler, selector, true );\n\t\t\t\t}\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tspecial = jQuery.event.special[ type ] || {};\n\t\t\ttype = ( selector ? special.delegateType : special.bindType ) || type;\n\t\t\thandlers = events[ type ] || [];\n\t\t\ttmp = tmp[2] && new RegExp( \"(^|\\\\.)\" + namespaces.join(\"\\\\.(?:.*\\\\.|)\") + \"(\\\\.|$)\" );\n\n\t\t\t// Remove matching events\n\t\t\torigCount = j = handlers.length;\n\t\t\twhile ( j-- ) {\n\t\t\t\thandleObj = handlers[ j ];\n\n\t\t\t\tif ( ( mappedTypes || origType === handleObj.origType ) &&\n\t\t\t\t\t( !handler || handler.guid === handleObj.guid ) &&\n\t\t\t\t\t( !tmp || tmp.test( handleObj.namespace ) ) &&\n\t\t\t\t\t( !selector || selector === handleObj.selector || selector === \"**\" && handleObj.selector ) ) {\n\t\t\t\t\thandlers.splice( j, 1 );\n\n\t\t\t\t\tif ( handleObj.selector ) {\n\t\t\t\t\t\thandlers.delegateCount--;\n\t\t\t\t\t}\n\t\t\t\t\tif ( special.remove ) {\n\t\t\t\t\t\tspecial.remove.call( elem, handleObj );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Remove generic event handler if we removed something and no more handlers exist\n\t\t\t// (avoids potential for endless recursion during removal of special event handlers)\n\t\t\tif ( origCount && !handlers.length ) {\n\t\t\t\tif ( !special.teardown || special.teardown.call( elem, namespaces, elemData.handle ) === false ) {\n\t\t\t\t\tjQuery.removeEvent( elem, type, elemData.handle );\n\t\t\t\t}\n\n\t\t\t\tdelete events[ type ];\n\t\t\t}\n\t\t}\n\n\t\t// Remove the expando if it's no longer used\n\t\tif ( jQuery.isEmptyObject( events ) ) {\n\t\t\tdelete elemData.handle;\n\n\t\t\t// removeData also checks for emptiness and clears the expando if empty\n\t\t\t// so use it instead of delete\n\t\t\tjQuery._removeData( elem, \"events\" );\n\t\t}\n\t},\n\n\ttrigger: function( event, data, elem, onlyHandlers ) {\n\t\tvar handle, ontype, cur,\n\t\t\tbubbleType, special, tmp, i,\n\t\t\teventPath = [ elem || document ],\n\t\t\ttype = core_hasOwn.call( event, \"type\" ) ? event.type : event,\n\t\t\tnamespaces = core_hasOwn.call( event, \"namespace\" ) ? event.namespace.split(\".\") : [];\n\n\t\tcur = tmp = elem = elem || document;\n\n\t\t// Don't do events on text and comment nodes\n\t\tif ( elem.nodeType === 3 || elem.nodeType === 8 ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// focus/blur morphs to focusin/out; ensure we're not firing them right now\n\t\tif ( rfocusMorph.test( type + jQuery.event.triggered ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( type.indexOf(\".\") >= 0 ) {\n\t\t\t// Namespaced trigger; create a regexp to match event type in handle()\n\t\t\tnamespaces = type.split(\".\");\n\t\t\ttype = namespaces.shift();\n\t\t\tnamespaces.sort();\n\t\t}\n\t\tontype = type.indexOf(\":\") < 0 && \"on\" + type;\n\n\t\t// Caller can pass in a jQuery.Event object, Object, or just an event type string\n\t\tevent = event[ jQuery.expando ] ?\n\t\t\tevent :\n\t\t\tnew jQuery.Event( type, typeof event === \"object\" && event );\n\n\t\tevent.isTrigger = true;\n\t\tevent.namespace = namespaces.join(\".\");\n\t\tevent.namespace_re = event.namespace ?\n\t\t\tnew RegExp( \"(^|\\\\.)\" + namespaces.join(\"\\\\.(?:.*\\\\.|)\") + \"(\\\\.|$)\" ) :\n\t\t\tnull;\n\n\t\t// Clean up the event in case it is being reused\n\t\tevent.result = undefined;\n\t\tif ( !event.target ) {\n\t\t\tevent.target = elem;\n\t\t}\n\n\t\t// Clone any incoming data and prepend the event, creating the handler arg list\n\t\tdata = data == null ?\n\t\t\t[ event ] :\n\t\t\tjQuery.makeArray( data, [ event ] );\n\n\t\t// Allow special events to draw outside the lines\n\t\tspecial = jQuery.event.special[ type ] || {};\n\t\tif ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Determine event propagation path in advance, per W3C events spec (#9951)\n\t\t// Bubble up to document, then to window; watch for a global ownerDocument var (#9724)\n\t\tif ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) {\n\n\t\t\tbubbleType = special.delegateType || type;\n\t\t\tif ( !rfocusMorph.test( bubbleType + type ) ) {\n\t\t\t\tcur = cur.parentNode;\n\t\t\t}\n\t\t\tfor ( ; cur; cur = cur.parentNode ) {\n\t\t\t\teventPath.push( cur );\n\t\t\t\ttmp = cur;\n\t\t\t}\n\n\t\t\t// Only add window if we got to document (e.g., not plain obj or detached DOM)\n\t\t\tif ( tmp === (elem.ownerDocument || document) ) {\n\t\t\t\teventPath.push( tmp.defaultView || tmp.parentWindow || window );\n\t\t\t}\n\t\t}\n\n\t\t// Fire handlers on the event path\n\t\ti = 0;\n\t\twhile ( (cur = eventPath[i++]) && !event.isPropagationStopped() ) {\n\n\t\t\tevent.type = i > 1 ?\n\t\t\t\tbubbleType :\n\t\t\t\tspecial.bindType || type;\n\n\t\t\t// jQuery handler\n\t\t\thandle = ( jQuery._data( cur, \"events\" ) || {} )[ event.type ] && jQuery._data( cur, \"handle\" );\n\t\t\tif ( handle ) {\n\t\t\t\thandle.apply( cur, data );\n\t\t\t}\n\n\t\t\t// Native handler\n\t\t\thandle = ontype && cur[ ontype ];\n\t\t\tif ( handle && jQuery.acceptData( cur ) && handle.apply && handle.apply( cur, data ) === false ) {\n\t\t\t\tevent.preventDefault();\n\t\t\t}\n\t\t}\n\t\tevent.type = type;\n\n\t\t// If nobody prevented the default action, do it now\n\t\tif ( !onlyHandlers && !event.isDefaultPrevented() ) {\n\n\t\t\tif ( (!special._default || special._default.apply( elem.ownerDocument, data ) === false) &&\n\t\t\t\t!(type === \"click\" && jQuery.nodeName( elem, \"a\" )) && jQuery.acceptData( elem ) ) {\n\n\t\t\t\t// Call a native DOM method on the target with the same name name as the event.\n\t\t\t\t// Can't use an .isFunction() check here because IE6/7 fails that test.\n\t\t\t\t// Don't do default actions on window, that's where global variables be (#6170)\n\t\t\t\tif ( ontype && elem[ type ] && !jQuery.isWindow( elem ) ) {\n\n\t\t\t\t\t// Don't re-trigger an onFOO event when we call its FOO() method\n\t\t\t\t\ttmp = elem[ ontype ];\n\n\t\t\t\t\tif ( tmp ) {\n\t\t\t\t\t\telem[ ontype ] = null;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Prevent re-triggering of the same event, since we already bubbled it above\n\t\t\t\t\tjQuery.event.triggered = type;\n\t\t\t\t\ttry {\n\t\t\t\t\t\telem[ type ]();\n\t\t\t\t\t} catch ( e ) {\n\t\t\t\t\t\t// IE<9 dies on focus/blur to hidden element (#1486,#12518)\n\t\t\t\t\t\t// only reproducible on winXP IE8 native, not IE9 in IE8 mode\n\t\t\t\t\t}\n\t\t\t\t\tjQuery.event.triggered = undefined;\n\n\t\t\t\t\tif ( tmp ) {\n\t\t\t\t\t\telem[ ontype ] = tmp;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn event.result;\n\t},\n\n\tdispatch: function( event ) {\n\n\t\t// Make a writable jQuery.Event from the native event object\n\t\tevent = jQuery.event.fix( event );\n\n\t\tvar i, ret, handleObj, matched, j,\n\t\t\thandlerQueue = [],\n\t\t\targs = core_slice.call( arguments ),\n\t\t\thandlers = ( jQuery._data( this, \"events\" ) || {} )[ event.type ] || [],\n\t\t\tspecial = jQuery.event.special[ event.type ] || {};\n\n\t\t// Use the fix-ed jQuery.Event rather than the (read-only) native event\n\t\targs[0] = event;\n\t\tevent.delegateTarget = this;\n\n\t\t// Call the preDispatch hook for the mapped type, and let it bail if desired\n\t\tif ( special.preDispatch && special.preDispatch.call( this, event ) === false ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Determine handlers\n\t\thandlerQueue = jQuery.event.handlers.call( this, event, handlers );\n\n\t\t// Run delegates first; they may want to stop propagation beneath us\n\t\ti = 0;\n\t\twhile ( (matched = handlerQueue[ i++ ]) && !event.isPropagationStopped() ) {\n\t\t\tevent.currentTarget = matched.elem;\n\n\t\t\tj = 0;\n\t\t\twhile ( (handleObj = matched.handlers[ j++ ]) && !event.isImmediatePropagationStopped() ) {\n\n\t\t\t\t// Triggered event must either 1) have no namespace, or\n\t\t\t\t// 2) have namespace(s) a subset or equal to those in the bound event (both can have no namespace).\n\t\t\t\tif ( !event.namespace_re || event.namespace_re.test( handleObj.namespace ) ) {\n\n\t\t\t\t\tevent.handleObj = handleObj;\n\t\t\t\t\tevent.data = handleObj.data;\n\n\t\t\t\t\tret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler )\n\t\t\t\t\t\t\t.apply( matched.elem, args );\n\n\t\t\t\t\tif ( ret !== undefined ) {\n\t\t\t\t\t\tif ( (event.result = ret) === false ) {\n\t\t\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\t\t\tevent.stopPropagation();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Call the postDispatch hook for the mapped type\n\t\tif ( special.postDispatch ) {\n\t\t\tspecial.postDispatch.call( this, event );\n\t\t}\n\n\t\treturn event.result;\n\t},\n\n\thandlers: function( event, handlers ) {\n\t\tvar sel, handleObj, matches, i,\n\t\t\thandlerQueue = [],\n\t\t\tdelegateCount = handlers.delegateCount,\n\t\t\tcur = event.target;\n\n\t\t// Find delegate handlers\n\t\t// Black-hole SVG <use> instance trees (#13180)\n\t\t// Avoid non-left-click bubbling in Firefox (#3861)\n\t\tif ( delegateCount && cur.nodeType && (!event.button || event.type !== \"click\") ) {\n\n\t\t\tfor ( ; cur != this; cur = cur.parentNode || this ) {\n\n\t\t\t\t// Don't check non-elements (#13208)\n\t\t\t\t// Don't process clicks on disabled elements (#6911, #8165, #11382, #11764)\n\t\t\t\tif ( cur.nodeType === 1 && (cur.disabled !== true || event.type !== \"click\") ) {\n\t\t\t\t\tmatches = [];\n\t\t\t\t\tfor ( i = 0; i < delegateCount; i++ ) {\n\t\t\t\t\t\thandleObj = handlers[ i ];\n\n\t\t\t\t\t\t// Don't conflict with Object.prototype properties (#13203)\n\t\t\t\t\t\tsel = handleObj.selector + \" \";\n\n\t\t\t\t\t\tif ( matches[ sel ] === undefined ) {\n\t\t\t\t\t\t\tmatches[ sel ] = handleObj.needsContext ?\n\t\t\t\t\t\t\t\tjQuery( sel, this ).index( cur ) >= 0 :\n\t\t\t\t\t\t\t\tjQuery.find( sel, this, null, [ cur ] ).length;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif ( matches[ sel ] ) {\n\t\t\t\t\t\t\tmatches.push( handleObj );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif ( matches.length ) {\n\t\t\t\t\t\thandlerQueue.push({ elem: cur, handlers: matches });\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Add the remaining (directly-bound) handlers\n\t\tif ( delegateCount < handlers.length ) {\n\t\t\thandlerQueue.push({ elem: this, handlers: handlers.slice( delegateCount ) });\n\t\t}\n\n\t\treturn handlerQueue;\n\t},\n\n\tfix: function( event ) {\n\t\tif ( event[ jQuery.expando ] ) {\n\t\t\treturn event;\n\t\t}\n\n\t\t// Create a writable copy of the event object and normalize some properties\n\t\tvar i, prop, copy,\n\t\t\ttype = event.type,\n\t\t\toriginalEvent = event,\n\t\t\tfixHook = this.fixHooks[ type ];\n\n\t\tif ( !fixHook ) {\n\t\t\tthis.fixHooks[ type ] = fixHook =\n\t\t\t\trmouseEvent.test( type ) ? this.mouseHooks :\n\t\t\t\trkeyEvent.test( type ) ? this.keyHooks :\n\t\t\t\t{};\n\t\t}\n\t\tcopy = fixHook.props ? this.props.concat( fixHook.props ) : this.props;\n\n\t\tevent = new jQuery.Event( originalEvent );\n\n\t\ti = copy.length;\n\t\twhile ( i-- ) {\n\t\t\tprop = copy[ i ];\n\t\t\tevent[ prop ] = originalEvent[ prop ];\n\t\t}\n\n\t\t// Support: IE<9\n\t\t// Fix target property (#1925)\n\t\tif ( !event.target ) {\n\t\t\tevent.target = originalEvent.srcElement || document;\n\t\t}\n\n\t\t// Support: Chrome 23+, Safari?\n\t\t// Target should not be a text node (#504, #13143)\n\t\tif ( event.target.nodeType === 3 ) {\n\t\t\tevent.target = event.target.parentNode;\n\t\t}\n\n\t\t// Support: IE<9\n\t\t// For mouse/key events, metaKey==false if it's undefined (#3368, #11328)\n\t\tevent.metaKey = !!event.metaKey;\n\n\t\treturn fixHook.filter ? fixHook.filter( event, originalEvent ) : event;\n\t},\n\n\t// Includes some event props shared by KeyEvent and MouseEvent\n\tprops: \"altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which\".split(\" \"),\n\n\tfixHooks: {},\n\n\tkeyHooks: {\n\t\tprops: \"char charCode key keyCode\".split(\" \"),\n\t\tfilter: function( event, original ) {\n\n\t\t\t// Add which for key events\n\t\t\tif ( event.which == null ) {\n\t\t\t\tevent.which = original.charCode != null ? original.charCode : original.keyCode;\n\t\t\t}\n\n\t\t\treturn event;\n\t\t}\n\t},\n\n\tmouseHooks: {\n\t\tprops: \"button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement\".split(\" \"),\n\t\tfilter: function( event, original ) {\n\t\t\tvar body, eventDoc, doc,\n\t\t\t\tbutton = original.button,\n\t\t\t\tfromElement = original.fromElement;\n\n\t\t\t// Calculate pageX/Y if missing and clientX/Y available\n\t\t\tif ( event.pageX == null && original.clientX != null ) {\n\t\t\t\teventDoc = event.target.ownerDocument || document;\n\t\t\t\tdoc = eventDoc.documentElement;\n\t\t\t\tbody = eventDoc.body;\n\n\t\t\t\tevent.pageX = original.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && body.clientLeft || 0 );\n\t\t\t\tevent.pageY = original.clientY + ( doc && doc.scrollTop  || body && body.scrollTop  || 0 ) - ( doc && doc.clientTop  || body && body.clientTop  || 0 );\n\t\t\t}\n\n\t\t\t// Add relatedTarget, if necessary\n\t\t\tif ( !event.relatedTarget && fromElement ) {\n\t\t\t\tevent.relatedTarget = fromElement === event.target ? original.toElement : fromElement;\n\t\t\t}\n\n\t\t\t// Add which for click: 1 === left; 2 === middle; 3 === right\n\t\t\t// Note: button is not normalized, so don't use it\n\t\t\tif ( !event.which && button !== undefined ) {\n\t\t\t\tevent.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) );\n\t\t\t}\n\n\t\t\treturn event;\n\t\t}\n\t},\n\n\tspecial: {\n\t\tload: {\n\t\t\t// Prevent triggered image.load events from bubbling to window.load\n\t\t\tnoBubble: true\n\t\t},\n\t\tclick: {\n\t\t\t// For checkbox, fire native event so checked state will be right\n\t\t\ttrigger: function() {\n\t\t\t\tif ( jQuery.nodeName( this, \"input\" ) && this.type === \"checkbox\" && this.click ) {\n\t\t\t\t\tthis.click();\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\tfocus: {\n\t\t\t// Fire native event if possible so blur/focus sequence is correct\n\t\t\ttrigger: function() {\n\t\t\t\tif ( this !== document.activeElement && this.focus ) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tthis.focus();\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t} catch ( e ) {\n\t\t\t\t\t\t// Support: IE<9\n\t\t\t\t\t\t// If we error on focus to hidden element (#1486, #12518),\n\t\t\t\t\t\t// let .trigger() run the handlers\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\tdelegateType: \"focusin\"\n\t\t},\n\t\tblur: {\n\t\t\ttrigger: function() {\n\t\t\t\tif ( this === document.activeElement && this.blur ) {\n\t\t\t\t\tthis.blur();\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t},\n\t\t\tdelegateType: \"focusout\"\n\t\t},\n\n\t\tbeforeunload: {\n\t\t\tpostDispatch: function( event ) {\n\n\t\t\t\t// Even when returnValue equals to undefined Firefox will still show alert\n\t\t\t\tif ( event.result !== undefined ) {\n\t\t\t\t\tevent.originalEvent.returnValue = event.result;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\n\tsimulate: function( type, elem, event, bubble ) {\n\t\t// Piggyback on a donor event to simulate a different one.\n\t\t// Fake originalEvent to avoid donor's stopPropagation, but if the\n\t\t// simulated event prevents default then we do the same on the donor.\n\t\tvar e = jQuery.extend(\n\t\t\tnew jQuery.Event(),\n\t\t\tevent,\n\t\t\t{ type: type,\n\t\t\t\tisSimulated: true,\n\t\t\t\toriginalEvent: {}\n\t\t\t}\n\t\t);\n\t\tif ( bubble ) {\n\t\t\tjQuery.event.trigger( e, null, elem );\n\t\t} else {\n\t\t\tjQuery.event.dispatch.call( elem, e );\n\t\t}\n\t\tif ( e.isDefaultPrevented() ) {\n\t\t\tevent.preventDefault();\n\t\t}\n\t}\n};\n\njQuery.removeEvent = document.removeEventListener ?\n\tfunction( elem, type, handle ) {\n\t\tif ( elem.removeEventListener ) {\n\t\t\telem.removeEventListener( type, handle, false );\n\t\t}\n\t} :\n\tfunction( elem, type, handle ) {\n\t\tvar name = \"on\" + type;\n\n\t\tif ( elem.detachEvent ) {\n\n\t\t\t// #8545, #7054, preventing memory leaks for custom events in IE6-8\n\t\t\t// detachEvent needed property on element, by name of that event, to properly expose it to GC\n\t\t\tif ( typeof elem[ name ] === core_strundefined ) {\n\t\t\t\telem[ name ] = null;\n\t\t\t}\n\n\t\t\telem.detachEvent( name, handle );\n\t\t}\n\t};\n\njQuery.Event = function( src, props ) {\n\t// Allow instantiation without the 'new' keyword\n\tif ( !(this instanceof jQuery.Event) ) {\n\t\treturn new jQuery.Event( src, props );\n\t}\n\n\t// Event object\n\tif ( src && src.type ) {\n\t\tthis.originalEvent = src;\n\t\tthis.type = src.type;\n\n\t\t// Events bubbling up the document may have been marked as prevented\n\t\t// by a handler lower down the tree; reflect the correct value.\n\t\tthis.isDefaultPrevented = ( src.defaultPrevented || src.returnValue === false ||\n\t\t\tsrc.getPreventDefault && src.getPreventDefault() ) ? returnTrue : returnFalse;\n\n\t// Event type\n\t} else {\n\t\tthis.type = src;\n\t}\n\n\t// Put explicitly provided properties onto the event object\n\tif ( props ) {\n\t\tjQuery.extend( this, props );\n\t}\n\n\t// Create a timestamp if incoming event doesn't have one\n\tthis.timeStamp = src && src.timeStamp || jQuery.now();\n\n\t// Mark it as fixed\n\tthis[ jQuery.expando ] = true;\n};\n\n// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding\n// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html\njQuery.Event.prototype = {\n\tisDefaultPrevented: returnFalse,\n\tisPropagationStopped: returnFalse,\n\tisImmediatePropagationStopped: returnFalse,\n\n\tpreventDefault: function() {\n\t\tvar e = this.originalEvent;\n\n\t\tthis.isDefaultPrevented = returnTrue;\n\t\tif ( !e ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// If preventDefault exists, run it on the original event\n\t\tif ( e.preventDefault ) {\n\t\t\te.preventDefault();\n\n\t\t// Support: IE\n\t\t// Otherwise set the returnValue property of the original event to false\n\t\t} else {\n\t\t\te.returnValue = false;\n\t\t}\n\t},\n\tstopPropagation: function() {\n\t\tvar e = this.originalEvent;\n\n\t\tthis.isPropagationStopped = returnTrue;\n\t\tif ( !e ) {\n\t\t\treturn;\n\t\t}\n\t\t// If stopPropagation exists, run it on the original event\n\t\tif ( e.stopPropagation ) {\n\t\t\te.stopPropagation();\n\t\t}\n\n\t\t// Support: IE\n\t\t// Set the cancelBubble property of the original event to true\n\t\te.cancelBubble = true;\n\t},\n\tstopImmediatePropagation: function() {\n\t\tthis.isImmediatePropagationStopped = returnTrue;\n\t\tthis.stopPropagation();\n\t}\n};\n\n// Create mouseenter/leave events using mouseover/out and event-time checks\njQuery.each({\n\tmouseenter: \"mouseover\",\n\tmouseleave: \"mouseout\"\n}, function( orig, fix ) {\n\tjQuery.event.special[ orig ] = {\n\t\tdelegateType: fix,\n\t\tbindType: fix,\n\n\t\thandle: function( event ) {\n\t\t\tvar ret,\n\t\t\t\ttarget = this,\n\t\t\t\trelated = event.relatedTarget,\n\t\t\t\thandleObj = event.handleObj;\n\n\t\t\t// For mousenter/leave call the handler if related is outside the target.\n\t\t\t// NB: No relatedTarget if the mouse left/entered the browser window\n\t\t\tif ( !related || (related !== target && !jQuery.contains( target, related )) ) {\n\t\t\t\tevent.type = handleObj.origType;\n\t\t\t\tret = handleObj.handler.apply( this, arguments );\n\t\t\t\tevent.type = fix;\n\t\t\t}\n\t\t\treturn ret;\n\t\t}\n\t};\n});\n\n// IE submit delegation\nif ( !jQuery.support.submitBubbles ) {\n\n\tjQuery.event.special.submit = {\n\t\tsetup: function() {\n\t\t\t// Only need this for delegated form submit events\n\t\t\tif ( jQuery.nodeName( this, \"form\" ) ) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\t// Lazy-add a submit handler when a descendant form may potentially be submitted\n\t\t\tjQuery.event.add( this, \"click._submit keypress._submit\", function( e ) {\n\t\t\t\t// Node name check avoids a VML-related crash in IE (#9807)\n\t\t\t\tvar elem = e.target,\n\t\t\t\t\tform = jQuery.nodeName( elem, \"input\" ) || jQuery.nodeName( elem, \"button\" ) ? elem.form : undefined;\n\t\t\t\tif ( form && !jQuery._data( form, \"submitBubbles\" ) ) {\n\t\t\t\t\tjQuery.event.add( form, \"submit._submit\", function( event ) {\n\t\t\t\t\t\tevent._submit_bubble = true;\n\t\t\t\t\t});\n\t\t\t\t\tjQuery._data( form, \"submitBubbles\", true );\n\t\t\t\t}\n\t\t\t});\n\t\t\t// return undefined since we don't need an event listener\n\t\t},\n\n\t\tpostDispatch: function( event ) {\n\t\t\t// If form was submitted by the user, bubble the event up the tree\n\t\t\tif ( event._submit_bubble ) {\n\t\t\t\tdelete event._submit_bubble;\n\t\t\t\tif ( this.parentNode && !event.isTrigger ) {\n\t\t\t\t\tjQuery.event.simulate( \"submit\", this.parentNode, event, true );\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\tteardown: function() {\n\t\t\t// Only need this for delegated form submit events\n\t\t\tif ( jQuery.nodeName( this, \"form\" ) ) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\t// Remove delegated handlers; cleanData eventually reaps submit handlers attached above\n\t\t\tjQuery.event.remove( this, \"._submit\" );\n\t\t}\n\t};\n}\n\n// IE change delegation and checkbox/radio fix\nif ( !jQuery.support.changeBubbles ) {\n\n\tjQuery.event.special.change = {\n\n\t\tsetup: function() {\n\n\t\t\tif ( rformElems.test( this.nodeName ) ) {\n\t\t\t\t// IE doesn't fire change on a check/radio until blur; trigger it on click\n\t\t\t\t// after a propertychange. Eat the blur-change in special.change.handle.\n\t\t\t\t// This still fires onchange a second time for check/radio after blur.\n\t\t\t\tif ( this.type === \"checkbox\" || this.type === \"radio\" ) {\n\t\t\t\t\tjQuery.event.add( this, \"propertychange._change\", function( event ) {\n\t\t\t\t\t\tif ( event.originalEvent.propertyName === \"checked\" ) {\n\t\t\t\t\t\t\tthis._just_changed = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t\tjQuery.event.add( this, \"click._change\", function( event ) {\n\t\t\t\t\t\tif ( this._just_changed && !event.isTrigger ) {\n\t\t\t\t\t\t\tthis._just_changed = false;\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// Allow triggered, simulated change events (#11500)\n\t\t\t\t\t\tjQuery.event.simulate( \"change\", this, event, true );\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\t// Delegated event; lazy-add a change handler on descendant inputs\n\t\t\tjQuery.event.add( this, \"beforeactivate._change\", function( e ) {\n\t\t\t\tvar elem = e.target;\n\n\t\t\t\tif ( rformElems.test( elem.nodeName ) && !jQuery._data( elem, \"changeBubbles\" ) ) {\n\t\t\t\t\tjQuery.event.add( elem, \"change._change\", function( event ) {\n\t\t\t\t\t\tif ( this.parentNode && !event.isSimulated && !event.isTrigger ) {\n\t\t\t\t\t\t\tjQuery.event.simulate( \"change\", this.parentNode, event, true );\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t\tjQuery._data( elem, \"changeBubbles\", true );\n\t\t\t\t}\n\t\t\t});\n\t\t},\n\n\t\thandle: function( event ) {\n\t\t\tvar elem = event.target;\n\n\t\t\t// Swallow native change events from checkbox/radio, we already triggered them above\n\t\t\tif ( this !== elem || event.isSimulated || event.isTrigger || (elem.type !== \"radio\" && elem.type !== \"checkbox\") ) {\n\t\t\t\treturn event.handleObj.handler.apply( this, arguments );\n\t\t\t}\n\t\t},\n\n\t\tteardown: function() {\n\t\t\tjQuery.event.remove( this, \"._change\" );\n\n\t\t\treturn !rformElems.test( this.nodeName );\n\t\t}\n\t};\n}\n\n// Create \"bubbling\" focus and blur events\nif ( !jQuery.support.focusinBubbles ) {\n\tjQuery.each({ focus: \"focusin\", blur: \"focusout\" }, function( orig, fix ) {\n\n\t\t// Attach a single capturing handler while someone wants focusin/focusout\n\t\tvar attaches = 0,\n\t\t\thandler = function( event ) {\n\t\t\t\tjQuery.event.simulate( fix, event.target, jQuery.event.fix( event ), true );\n\t\t\t};\n\n\t\tjQuery.event.special[ fix ] = {\n\t\t\tsetup: function() {\n\t\t\t\tif ( attaches++ === 0 ) {\n\t\t\t\t\tdocument.addEventListener( orig, handler, true );\n\t\t\t\t}\n\t\t\t},\n\t\t\tteardown: function() {\n\t\t\t\tif ( --attaches === 0 ) {\n\t\t\t\t\tdocument.removeEventListener( orig, handler, true );\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t});\n}\n\njQuery.fn.extend({\n\n\ton: function( types, selector, data, fn, /*INTERNAL*/ one ) {\n\t\tvar type, origFn;\n\n\t\t// Types can be a map of types/handlers\n\t\tif ( typeof types === \"object\" ) {\n\t\t\t// ( types-Object, selector, data )\n\t\t\tif ( typeof selector !== \"string\" ) {\n\t\t\t\t// ( types-Object, data )\n\t\t\t\tdata = data || selector;\n\t\t\t\tselector = undefined;\n\t\t\t}\n\t\t\tfor ( type in types ) {\n\t\t\t\tthis.on( type, selector, data, types[ type ], one );\n\t\t\t}\n\t\t\treturn this;\n\t\t}\n\n\t\tif ( data == null && fn == null ) {\n\t\t\t// ( types, fn )\n\t\t\tfn = selector;\n\t\t\tdata = selector = undefined;\n\t\t} else if ( fn == null ) {\n\t\t\tif ( typeof selector === \"string\" ) {\n\t\t\t\t// ( types, selector, fn )\n\t\t\t\tfn = data;\n\t\t\t\tdata = undefined;\n\t\t\t} else {\n\t\t\t\t// ( types, data, fn )\n\t\t\t\tfn = data;\n\t\t\t\tdata = selector;\n\t\t\t\tselector = undefined;\n\t\t\t}\n\t\t}\n\t\tif ( fn === false ) {\n\t\t\tfn = returnFalse;\n\t\t} else if ( !fn ) {\n\t\t\treturn this;\n\t\t}\n\n\t\tif ( one === 1 ) {\n\t\t\torigFn = fn;\n\t\t\tfn = function( event ) {\n\t\t\t\t// Can use an empty set, since event contains the info\n\t\t\t\tjQuery().off( event );\n\t\t\t\treturn origFn.apply( this, arguments );\n\t\t\t};\n\t\t\t// Use same guid so caller can remove using origFn\n\t\t\tfn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ );\n\t\t}\n\t\treturn this.each( function() {\n\t\t\tjQuery.event.add( this, types, fn, data, selector );\n\t\t});\n\t},\n\tone: function( types, selector, data, fn ) {\n\t\treturn this.on( types, selector, data, fn, 1 );\n\t},\n\toff: function( types, selector, fn ) {\n\t\tvar handleObj, type;\n\t\tif ( types && types.preventDefault && types.handleObj ) {\n\t\t\t// ( event )  dispatched jQuery.Event\n\t\t\thandleObj = types.handleObj;\n\t\t\tjQuery( types.delegateTarget ).off(\n\t\t\t\thandleObj.namespace ? handleObj.origType + \".\" + handleObj.namespace : handleObj.origType,\n\t\t\t\thandleObj.selector,\n\t\t\t\thandleObj.handler\n\t\t\t);\n\t\t\treturn this;\n\t\t}\n\t\tif ( typeof types === \"object\" ) {\n\t\t\t// ( types-object [, selector] )\n\t\t\tfor ( type in types ) {\n\t\t\t\tthis.off( type, selector, types[ type ] );\n\t\t\t}\n\t\t\treturn this;\n\t\t}\n\t\tif ( selector === false || typeof selector === \"function\" ) {\n\t\t\t// ( types [, fn] )\n\t\t\tfn = selector;\n\t\t\tselector = undefined;\n\t\t}\n\t\tif ( fn === false ) {\n\t\t\tfn = returnFalse;\n\t\t}\n\t\treturn this.each(function() {\n\t\t\tjQuery.event.remove( this, types, fn, selector );\n\t\t});\n\t},\n\n\tbind: function( types, data, fn ) {\n\t\treturn this.on( types, null, data, fn );\n\t},\n\tunbind: function( types, fn ) {\n\t\treturn this.off( types, null, fn );\n\t},\n\n\tdelegate: function( selector, types, data, fn ) {\n\t\treturn this.on( types, selector, data, fn );\n\t},\n\tundelegate: function( selector, types, fn ) {\n\t\t// ( namespace ) or ( selector, types [, fn] )\n\t\treturn arguments.length === 1 ? this.off( selector, \"**\" ) : this.off( types, selector || \"**\", fn );\n\t},\n\n\ttrigger: function( type, data ) {\n\t\treturn this.each(function() {\n\t\t\tjQuery.event.trigger( type, data, this );\n\t\t});\n\t},\n\ttriggerHandler: function( type, data ) {\n\t\tvar elem = this[0];\n\t\tif ( elem ) {\n\t\t\treturn jQuery.event.trigger( type, data, elem, true );\n\t\t}\n\t}\n});\n/*!\n * Sizzle CSS Selector Engine\n * Copyright 2012 jQuery Foundation and other contributors\n * Released under the MIT license\n * http://sizzlejs.com/\n */\n(function( window, undefined ) {\n\nvar i,\n\tcachedruns,\n\tExpr,\n\tgetText,\n\tisXML,\n\tcompile,\n\thasDuplicate,\n\toutermostContext,\n\n\t// Local document vars\n\tsetDocument,\n\tdocument,\n\tdocElem,\n\tdocumentIsXML,\n\trbuggyQSA,\n\trbuggyMatches,\n\tmatches,\n\tcontains,\n\tsortOrder,\n\n\t// Instance-specific data\n\texpando = \"sizzle\" + -(new Date()),\n\tpreferredDoc = window.document,\n\tsupport = {},\n\tdirruns = 0,\n\tdone = 0,\n\tclassCache = createCache(),\n\ttokenCache = createCache(),\n\tcompilerCache = createCache(),\n\n\t// General-purpose constants\n\tstrundefined = typeof undefined,\n\tMAX_NEGATIVE = 1 << 31,\n\n\t// Array methods\n\tarr = [],\n\tpop = arr.pop,\n\tpush = arr.push,\n\tslice = arr.slice,\n\t// Use a stripped-down indexOf if we can't use a native one\n\tindexOf = arr.indexOf || function( elem ) {\n\t\tvar i = 0,\n\t\t\tlen = this.length;\n\t\tfor ( ; i < len; i++ ) {\n\t\t\tif ( this[i] === elem ) {\n\t\t\t\treturn i;\n\t\t\t}\n\t\t}\n\t\treturn -1;\n\t},\n\n\n\t// Regular expressions\n\n\t// Whitespace characters http://www.w3.org/TR/css3-selectors/#whitespace\n\twhitespace = \"[\\\\x20\\\\t\\\\r\\\\n\\\\f]\",\n\t// http://www.w3.org/TR/css3-syntax/#characters\n\tcharacterEncoding = \"(?:\\\\\\\\.|[\\\\w-]|[^\\\\x00-\\\\xa0])+\",\n\n\t// Loosely modeled on CSS identifier characters\n\t// An unquoted value should be a CSS identifier http://www.w3.org/TR/css3-selectors/#attribute-selectors\n\t// Proper syntax: http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier\n\tidentifier = characterEncoding.replace( \"w\", \"w#\" ),\n\n\t// Acceptable operators http://www.w3.org/TR/selectors/#attribute-selectors\n\toperators = \"([*^$|!~]?=)\",\n\tattributes = \"\\\\[\" + whitespace + \"*(\" + characterEncoding + \")\" + whitespace +\n\t\t\"*(?:\" + operators + whitespace + \"*(?:(['\\\"])((?:\\\\\\\\.|[^\\\\\\\\])*?)\\\\3|(\" + identifier + \")|)|)\" + whitespace + \"*\\\\]\",\n\n\t// Prefer arguments quoted,\n\t//   then not containing pseudos/brackets,\n\t//   then attribute selectors/non-parenthetical expressions,\n\t//   then anything else\n\t// These preferences are here to reduce the number of selectors\n\t//   needing tokenize in the PSEUDO preFilter\n\tpseudos = \":(\" + characterEncoding + \")(?:\\\\(((['\\\"])((?:\\\\\\\\.|[^\\\\\\\\])*?)\\\\3|((?:\\\\\\\\.|[^\\\\\\\\()[\\\\]]|\" + attributes.replace( 3, 8 ) + \")*)|.*)\\\\)|)\",\n\n\t// Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter\n\trtrim = new RegExp( \"^\" + whitespace + \"+|((?:^|[^\\\\\\\\])(?:\\\\\\\\.)*)\" + whitespace + \"+$\", \"g\" ),\n\n\trcomma = new RegExp( \"^\" + whitespace + \"*,\" + whitespace + \"*\" ),\n\trcombinators = new RegExp( \"^\" + whitespace + \"*([\\\\x20\\\\t\\\\r\\\\n\\\\f>+~])\" + whitespace + \"*\" ),\n\trpseudo = new RegExp( pseudos ),\n\tridentifier = new RegExp( \"^\" + identifier + \"$\" ),\n\n\tmatchExpr = {\n\t\t\"ID\": new RegExp( \"^#(\" + characterEncoding + \")\" ),\n\t\t\"CLASS\": new RegExp( \"^\\\\.(\" + characterEncoding + \")\" ),\n\t\t\"NAME\": new RegExp( \"^\\\\[name=['\\\"]?(\" + characterEncoding + \")['\\\"]?\\\\]\" ),\n\t\t\"TAG\": new RegExp( \"^(\" + characterEncoding.replace( \"w\", \"w*\" ) + \")\" ),\n\t\t\"ATTR\": new RegExp( \"^\" + attributes ),\n\t\t\"PSEUDO\": new RegExp( \"^\" + pseudos ),\n\t\t\"CHILD\": new RegExp( \"^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\\\(\" + whitespace +\n\t\t\t\"*(even|odd|(([+-]|)(\\\\d*)n|)\" + whitespace + \"*(?:([+-]|)\" + whitespace +\n\t\t\t\"*(\\\\d+)|))\" + whitespace + \"*\\\\)|)\", \"i\" ),\n\t\t// For use in libraries implementing .is()\n\t\t// We use this for POS matching in `select`\n\t\t\"needsContext\": new RegExp( \"^\" + whitespace + \"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\\\(\" +\n\t\t\twhitespace + \"*((?:-\\\\d)?\\\\d*)\" + whitespace + \"*\\\\)|)(?=[^-]|$)\", \"i\" )\n\t},\n\n\trsibling = /[\\x20\\t\\r\\n\\f]*[+~]/,\n\n\trnative = /^[^{]+\\{\\s*\\[native code/,\n\n\t// Easily-parseable/retrievable ID or TAG or CLASS selectors\n\trquickExpr = /^(?:#([\\w-]+)|(\\w+)|\\.([\\w-]+))$/,\n\n\trinputs = /^(?:input|select|textarea|button)$/i,\n\trheader = /^h\\d$/i,\n\n\trescape = /'|\\\\/g,\n\trattributeQuotes = /\\=[\\x20\\t\\r\\n\\f]*([^'\"\\]]*)[\\x20\\t\\r\\n\\f]*\\]/g,\n\n\t// CSS escapes http://www.w3.org/TR/CSS21/syndata.html#escaped-characters\n\trunescape = /\\\\([\\da-fA-F]{1,6}[\\x20\\t\\r\\n\\f]?|.)/g,\n\tfunescape = function( _, escaped ) {\n\t\tvar high = \"0x\" + escaped - 0x10000;\n\t\t// NaN means non-codepoint\n\t\treturn high !== high ?\n\t\t\tescaped :\n\t\t\t// BMP codepoint\n\t\t\thigh < 0 ?\n\t\t\t\tString.fromCharCode( high + 0x10000 ) :\n\t\t\t\t// Supplemental Plane codepoint (surrogate pair)\n\t\t\t\tString.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 );\n\t};\n\n// Use a stripped-down slice if we can't use a native one\ntry {\n\tslice.call( preferredDoc.documentElement.childNodes, 0 )[0].nodeType;\n} catch ( e ) {\n\tslice = function( i ) {\n\t\tvar elem,\n\t\t\tresults = [];\n\t\twhile ( (elem = this[i++]) ) {\n\t\t\tresults.push( elem );\n\t\t}\n\t\treturn results;\n\t};\n}\n\n/**\n * For feature detection\n * @param {Function} fn The function to test for native support\n */\nfunction isNative( fn ) {\n\treturn rnative.test( fn + \"\" );\n}\n\n/**\n * Create key-value caches of limited size\n * @returns {Function(string, Object)} Returns the Object data after storing it on itself with\n *\tproperty name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength)\n *\tdeleting the oldest entry\n */\nfunction createCache() {\n\tvar cache,\n\t\tkeys = [];\n\n\treturn (cache = function( key, value ) {\n\t\t// Use (key + \" \") to avoid collision with native prototype properties (see Issue #157)\n\t\tif ( keys.push( key += \" \" ) > Expr.cacheLength ) {\n\t\t\t// Only keep the most recent entries\n\t\t\tdelete cache[ keys.shift() ];\n\t\t}\n\t\treturn (cache[ key ] = value);\n\t});\n}\n\n/**\n * Mark a function for special use by Sizzle\n * @param {Function} fn The function to mark\n */\nfunction markFunction( fn ) {\n\tfn[ expando ] = true;\n\treturn fn;\n}\n\n/**\n * Support testing using an element\n * @param {Function} fn Passed the created div and expects a boolean result\n */\nfunction assert( fn ) {\n\tvar div = document.createElement(\"div\");\n\n\ttry {\n\t\treturn fn( div );\n\t} catch (e) {\n\t\treturn false;\n\t} finally {\n\t\t// release memory in IE\n\t\tdiv = null;\n\t}\n}\n\nfunction Sizzle( selector, context, results, seed ) {\n\tvar match, elem, m, nodeType,\n\t\t// QSA vars\n\t\ti, groups, old, nid, newContext, newSelector;\n\n\tif ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) {\n\t\tsetDocument( context );\n\t}\n\n\tcontext = context || document;\n\tresults = results || [];\n\n\tif ( !selector || typeof selector !== \"string\" ) {\n\t\treturn results;\n\t}\n\n\tif ( (nodeType = context.nodeType) !== 1 && nodeType !== 9 ) {\n\t\treturn [];\n\t}\n\n\tif ( !documentIsXML && !seed ) {\n\n\t\t// Shortcuts\n\t\tif ( (match = rquickExpr.exec( selector )) ) {\n\t\t\t// Speed-up: Sizzle(\"#ID\")\n\t\t\tif ( (m = match[1]) ) {\n\t\t\t\tif ( nodeType === 9 ) {\n\t\t\t\t\telem = context.getElementById( m );\n\t\t\t\t\t// Check parentNode to catch when Blackberry 4.6 returns\n\t\t\t\t\t// nodes that are no longer in the document #6963\n\t\t\t\t\tif ( elem && elem.parentNode ) {\n\t\t\t\t\t\t// Handle the case where IE, Opera, and Webkit return items\n\t\t\t\t\t\t// by name instead of ID\n\t\t\t\t\t\tif ( elem.id === m ) {\n\t\t\t\t\t\t\tresults.push( elem );\n\t\t\t\t\t\t\treturn results;\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\treturn results;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\t// Context is not a document\n\t\t\t\t\tif ( context.ownerDocument && (elem = context.ownerDocument.getElementById( m )) &&\n\t\t\t\t\t\tcontains( context, elem ) && elem.id === m ) {\n\t\t\t\t\t\tresults.push( elem );\n\t\t\t\t\t\treturn results;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t// Speed-up: Sizzle(\"TAG\")\n\t\t\t} else if ( match[2] ) {\n\t\t\t\tpush.apply( results, slice.call(context.getElementsByTagName( selector ), 0) );\n\t\t\t\treturn results;\n\n\t\t\t// Speed-up: Sizzle(\".CLASS\")\n\t\t\t} else if ( (m = match[3]) && support.getByClassName && context.getElementsByClassName ) {\n\t\t\t\tpush.apply( results, slice.call(context.getElementsByClassName( m ), 0) );\n\t\t\t\treturn results;\n\t\t\t}\n\t\t}\n\n\t\t// QSA path\n\t\tif ( support.qsa && !rbuggyQSA.test(selector) ) {\n\t\t\told = true;\n\t\t\tnid = expando;\n\t\t\tnewContext = context;\n\t\t\tnewSelector = nodeType === 9 && selector;\n\n\t\t\t// qSA works strangely on Element-rooted queries\n\t\t\t// We can work around this by specifying an extra ID on the root\n\t\t\t// and working up from there (Thanks to Andrew Dupont for the technique)\n\t\t\t// IE 8 doesn't work on object elements\n\t\t\tif ( nodeType === 1 && context.nodeName.toLowerCase() !== \"object\" ) {\n\t\t\t\tgroups = tokenize( selector );\n\n\t\t\t\tif ( (old = context.getAttribute(\"id\")) ) {\n\t\t\t\t\tnid = old.replace( rescape, \"\\\\$&\" );\n\t\t\t\t} else {\n\t\t\t\t\tcontext.setAttribute( \"id\", nid );\n\t\t\t\t}\n\t\t\t\tnid = \"[id='\" + nid + \"'] \";\n\n\t\t\t\ti = groups.length;\n\t\t\t\twhile ( i-- ) {\n\t\t\t\t\tgroups[i] = nid + toSelector( groups[i] );\n\t\t\t\t}\n\t\t\t\tnewContext = rsibling.test( selector ) && context.parentNode || context;\n\t\t\t\tnewSelector = groups.join(\",\");\n\t\t\t}\n\n\t\t\tif ( newSelector ) {\n\t\t\t\ttry {\n\t\t\t\t\tpush.apply( results, slice.call( newContext.querySelectorAll(\n\t\t\t\t\t\tnewSelector\n\t\t\t\t\t), 0 ) );\n\t\t\t\t\treturn results;\n\t\t\t\t} catch(qsaError) {\n\t\t\t\t} finally {\n\t\t\t\t\tif ( !old ) {\n\t\t\t\t\t\tcontext.removeAttribute(\"id\");\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// All others\n\treturn select( selector.replace( rtrim, \"$1\" ), context, results, seed );\n}\n\n/**\n * Detect xml\n * @param {Element|Object} elem An element or a document\n */\nisXML = Sizzle.isXML = function( elem ) {\n\t// documentElement is verified for cases where it doesn't yet exist\n\t// (such as loading iframes in IE - #4833)\n\tvar documentElement = elem && (elem.ownerDocument || elem).documentElement;\n\treturn documentElement ? documentElement.nodeName !== \"HTML\" : false;\n};\n\n/**\n * Sets document-related variables once based on the current document\n * @param {Element|Object} [doc] An element or document object to use to set the document\n * @returns {Object} Returns the current document\n */\nsetDocument = Sizzle.setDocument = function( node ) {\n\tvar doc = node ? node.ownerDocument || node : preferredDoc;\n\n\t// If no document and documentElement is available, return\n\tif ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) {\n\t\treturn document;\n\t}\n\n\t// Set our document\n\tdocument = doc;\n\tdocElem = doc.documentElement;\n\n\t// Support tests\n\tdocumentIsXML = isXML( doc );\n\n\t// Check if getElementsByTagName(\"*\") returns only elements\n\tsupport.tagNameNoComments = assert(function( div ) {\n\t\tdiv.appendChild( doc.createComment(\"\") );\n\t\treturn !div.getElementsByTagName(\"*\").length;\n\t});\n\n\t// Check if attributes should be retrieved by attribute nodes\n\tsupport.attributes = assert(function( div ) {\n\t\tdiv.innerHTML = \"<select></select>\";\n\t\tvar type = typeof div.lastChild.getAttribute(\"multiple\");\n\t\t// IE8 returns a string for some attributes even when not present\n\t\treturn type !== \"boolean\" && type !== \"string\";\n\t});\n\n\t// Check if getElementsByClassName can be trusted\n\tsupport.getByClassName = assert(function( div ) {\n\t\t// Opera can't find a second classname (in 9.6)\n\t\tdiv.innerHTML = \"<div class='hidden e'></div><div class='hidden'></div>\";\n\t\tif ( !div.getElementsByClassName || !div.getElementsByClassName(\"e\").length ) {\n\t\t\treturn false;\n\t\t}\n\n\t\t// Safari 3.2 caches class attributes and doesn't catch changes\n\t\tdiv.lastChild.className = \"e\";\n\t\treturn div.getElementsByClassName(\"e\").length === 2;\n\t});\n\n\t// Check if getElementById returns elements by name\n\t// Check if getElementsByName privileges form controls or returns elements by ID\n\tsupport.getByName = assert(function( div ) {\n\t\t// Inject content\n\t\tdiv.id = expando + 0;\n\t\tdiv.innerHTML = \"<a name='\" + expando + \"'></a><div name='\" + expando + \"'></div>\";\n\t\tdocElem.insertBefore( div, docElem.firstChild );\n\n\t\t// Test\n\t\tvar pass = doc.getElementsByName &&\n\t\t\t// buggy browsers will return fewer than the correct 2\n\t\t\tdoc.getElementsByName( expando ).length === 2 +\n\t\t\t// buggy browsers will return more than the correct 0\n\t\t\tdoc.getElementsByName( expando + 0 ).length;\n\t\tsupport.getIdNotName = !doc.getElementById( expando );\n\n\t\t// Cleanup\n\t\tdocElem.removeChild( div );\n\n\t\treturn pass;\n\t});\n\n\t// IE6/7 return modified attributes\n\tExpr.attrHandle = assert(function( div ) {\n\t\tdiv.innerHTML = \"<a href='#'></a>\";\n\t\treturn div.firstChild && typeof div.firstChild.getAttribute !== strundefined &&\n\t\t\tdiv.firstChild.getAttribute(\"href\") === \"#\";\n\t}) ?\n\t\t{} :\n\t\t{\n\t\t\t\"href\": function( elem ) {\n\t\t\t\treturn elem.getAttribute( \"href\", 2 );\n\t\t\t},\n\t\t\t\"type\": function( elem ) {\n\t\t\t\treturn elem.getAttribute(\"type\");\n\t\t\t}\n\t\t};\n\n\t// ID find and filter\n\tif ( support.getIdNotName ) {\n\t\tExpr.find[\"ID\"] = function( id, context ) {\n\t\t\tif ( typeof context.getElementById !== strundefined && !documentIsXML ) {\n\t\t\t\tvar m = context.getElementById( id );\n\t\t\t\t// Check parentNode to catch when Blackberry 4.6 returns\n\t\t\t\t// nodes that are no longer in the document #6963\n\t\t\t\treturn m && m.parentNode ? [m] : [];\n\t\t\t}\n\t\t};\n\t\tExpr.filter[\"ID\"] = function( id ) {\n\t\t\tvar attrId = id.replace( runescape, funescape );\n\t\t\treturn function( elem ) {\n\t\t\t\treturn elem.getAttribute(\"id\") === attrId;\n\t\t\t};\n\t\t};\n\t} else {\n\t\tExpr.find[\"ID\"] = function( id, context ) {\n\t\t\tif ( typeof context.getElementById !== strundefined && !documentIsXML ) {\n\t\t\t\tvar m = context.getElementById( id );\n\n\t\t\t\treturn m ?\n\t\t\t\t\tm.id === id || typeof m.getAttributeNode !== strundefined && m.getAttributeNode(\"id\").value === id ?\n\t\t\t\t\t\t[m] :\n\t\t\t\t\t\tundefined :\n\t\t\t\t\t[];\n\t\t\t}\n\t\t};\n\t\tExpr.filter[\"ID\"] =  function( id ) {\n\t\t\tvar attrId = id.replace( runescape, funescape );\n\t\t\treturn function( elem ) {\n\t\t\t\tvar node = typeof elem.getAttributeNode !== strundefined && elem.getAttributeNode(\"id\");\n\t\t\t\treturn node && node.value === attrId;\n\t\t\t};\n\t\t};\n\t}\n\n\t// Tag\n\tExpr.find[\"TAG\"] = support.tagNameNoComments ?\n\t\tfunction( tag, context ) {\n\t\t\tif ( typeof context.getElementsByTagName !== strundefined ) {\n\t\t\t\treturn context.getElementsByTagName( tag );\n\t\t\t}\n\t\t} :\n\t\tfunction( tag, context ) {\n\t\t\tvar elem,\n\t\t\t\ttmp = [],\n\t\t\t\ti = 0,\n\t\t\t\tresults = context.getElementsByTagName( tag );\n\n\t\t\t// Filter out possible comments\n\t\t\tif ( tag === \"*\" ) {\n\t\t\t\twhile ( (elem = results[i++]) ) {\n\t\t\t\t\tif ( elem.nodeType === 1 ) {\n\t\t\t\t\t\ttmp.push( elem );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn tmp;\n\t\t\t}\n\t\t\treturn results;\n\t\t};\n\n\t// Name\n\tExpr.find[\"NAME\"] = support.getByName && function( tag, context ) {\n\t\tif ( typeof context.getElementsByName !== strundefined ) {\n\t\t\treturn context.getElementsByName( name );\n\t\t}\n\t};\n\n\t// Class\n\tExpr.find[\"CLASS\"] = support.getByClassName && function( className, context ) {\n\t\tif ( typeof context.getElementsByClassName !== strundefined && !documentIsXML ) {\n\t\t\treturn context.getElementsByClassName( className );\n\t\t}\n\t};\n\n\t// QSA and matchesSelector support\n\n\t// matchesSelector(:active) reports false when true (IE9/Opera 11.5)\n\trbuggyMatches = [];\n\n\t// qSa(:focus) reports false when true (Chrome 21),\n\t// no need to also add to buggyMatches since matches checks buggyQSA\n\t// A support test would require too much code (would include document ready)\n\trbuggyQSA = [ \":focus\" ];\n\n\tif ( (support.qsa = isNative(doc.querySelectorAll)) ) {\n\t\t// Build QSA regex\n\t\t// Regex strategy adopted from Diego Perini\n\t\tassert(function( div ) {\n\t\t\t// Select is set to empty string on purpose\n\t\t\t// This is to test IE's treatment of not explictly\n\t\t\t// setting a boolean content attribute,\n\t\t\t// since its presence should be enough\n\t\t\t// http://bugs.jquery.com/ticket/12359\n\t\t\tdiv.innerHTML = \"<select><option selected=''></option></select>\";\n\n\t\t\t// IE8 - Some boolean attributes are not treated correctly\n\t\t\tif ( !div.querySelectorAll(\"[selected]\").length ) {\n\t\t\t\trbuggyQSA.push( \"\\\\[\" + whitespace + \"*(?:checked|disabled|ismap|multiple|readonly|selected|value)\" );\n\t\t\t}\n\n\t\t\t// Webkit/Opera - :checked should return selected option elements\n\t\t\t// http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked\n\t\t\t// IE8 throws error here and will not see later tests\n\t\t\tif ( !div.querySelectorAll(\":checked\").length ) {\n\t\t\t\trbuggyQSA.push(\":checked\");\n\t\t\t}\n\t\t});\n\n\t\tassert(function( div ) {\n\n\t\t\t// Opera 10-12/IE8 - ^= $= *= and empty values\n\t\t\t// Should not select anything\n\t\t\tdiv.innerHTML = \"<input type='hidden' i=''/>\";\n\t\t\tif ( div.querySelectorAll(\"[i^='']\").length ) {\n\t\t\t\trbuggyQSA.push( \"[*^$]=\" + whitespace + \"*(?:\\\"\\\"|'')\" );\n\t\t\t}\n\n\t\t\t// FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled)\n\t\t\t// IE8 throws error here and will not see later tests\n\t\t\tif ( !div.querySelectorAll(\":enabled\").length ) {\n\t\t\t\trbuggyQSA.push( \":enabled\", \":disabled\" );\n\t\t\t}\n\n\t\t\t// Opera 10-11 does not throw on post-comma invalid pseudos\n\t\t\tdiv.querySelectorAll(\"*,:x\");\n\t\t\trbuggyQSA.push(\",.*:\");\n\t\t});\n\t}\n\n\tif ( (support.matchesSelector = isNative( (matches = docElem.matchesSelector ||\n\t\tdocElem.mozMatchesSelector ||\n\t\tdocElem.webkitMatchesSelector ||\n\t\tdocElem.oMatchesSelector ||\n\t\tdocElem.msMatchesSelector) )) ) {\n\n\t\tassert(function( div ) {\n\t\t\t// Check to see if it's possible to do matchesSelector\n\t\t\t// on a disconnected node (IE 9)\n\t\t\tsupport.disconnectedMatch = matches.call( div, \"div\" );\n\n\t\t\t// This should fail with an exception\n\t\t\t// Gecko does not error, returns false instead\n\t\t\tmatches.call( div, \"[s!='']:x\" );\n\t\t\trbuggyMatches.push( \"!=\", pseudos );\n\t\t});\n\t}\n\n\trbuggyQSA = new RegExp( rbuggyQSA.join(\"|\") );\n\trbuggyMatches = new RegExp( rbuggyMatches.join(\"|\") );\n\n\t// Element contains another\n\t// Purposefully does not implement inclusive descendent\n\t// As in, an element does not contain itself\n\tcontains = isNative(docElem.contains) || docElem.compareDocumentPosition ?\n\t\tfunction( a, b ) {\n\t\t\tvar adown = a.nodeType === 9 ? a.documentElement : a,\n\t\t\t\tbup = b && b.parentNode;\n\t\t\treturn a === bup || !!( bup && bup.nodeType === 1 && (\n\t\t\t\tadown.contains ?\n\t\t\t\t\tadown.contains( bup ) :\n\t\t\t\t\ta.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16\n\t\t\t));\n\t\t} :\n\t\tfunction( a, b ) {\n\t\t\tif ( b ) {\n\t\t\t\twhile ( (b = b.parentNode) ) {\n\t\t\t\t\tif ( b === a ) {\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn false;\n\t\t};\n\n\t// Document order sorting\n\tsortOrder = docElem.compareDocumentPosition ?\n\tfunction( a, b ) {\n\t\tvar compare;\n\n\t\tif ( a === b ) {\n\t\t\thasDuplicate = true;\n\t\t\treturn 0;\n\t\t}\n\n\t\tif ( (compare = b.compareDocumentPosition && a.compareDocumentPosition && a.compareDocumentPosition( b )) ) {\n\t\t\tif ( compare & 1 || a.parentNode && a.parentNode.nodeType === 11 ) {\n\t\t\t\tif ( a === doc || contains( preferredDoc, a ) ) {\n\t\t\t\t\treturn -1;\n\t\t\t\t}\n\t\t\t\tif ( b === doc || contains( preferredDoc, b ) ) {\n\t\t\t\t\treturn 1;\n\t\t\t\t}\n\t\t\t\treturn 0;\n\t\t\t}\n\t\t\treturn compare & 4 ? -1 : 1;\n\t\t}\n\n\t\treturn a.compareDocumentPosition ? -1 : 1;\n\t} :\n\tfunction( a, b ) {\n\t\tvar cur,\n\t\t\ti = 0,\n\t\t\taup = a.parentNode,\n\t\t\tbup = b.parentNode,\n\t\t\tap = [ a ],\n\t\t\tbp = [ b ];\n\n\t\t// Exit early if the nodes are identical\n\t\tif ( a === b ) {\n\t\t\thasDuplicate = true;\n\t\t\treturn 0;\n\n\t\t// Parentless nodes are either documents or disconnected\n\t\t} else if ( !aup || !bup ) {\n\t\t\treturn a === doc ? -1 :\n\t\t\t\tb === doc ? 1 :\n\t\t\t\taup ? -1 :\n\t\t\t\tbup ? 1 :\n\t\t\t\t0;\n\n\t\t// If the nodes are siblings, we can do a quick check\n\t\t} else if ( aup === bup ) {\n\t\t\treturn siblingCheck( a, b );\n\t\t}\n\n\t\t// Otherwise we need full lists of their ancestors for comparison\n\t\tcur = a;\n\t\twhile ( (cur = cur.parentNode) ) {\n\t\t\tap.unshift( cur );\n\t\t}\n\t\tcur = b;\n\t\twhile ( (cur = cur.parentNode) ) {\n\t\t\tbp.unshift( cur );\n\t\t}\n\n\t\t// Walk down the tree looking for a discrepancy\n\t\twhile ( ap[i] === bp[i] ) {\n\t\t\ti++;\n\t\t}\n\n\t\treturn i ?\n\t\t\t// Do a sibling check if the nodes have a common ancestor\n\t\t\tsiblingCheck( ap[i], bp[i] ) :\n\n\t\t\t// Otherwise nodes in our document sort first\n\t\t\tap[i] === preferredDoc ? -1 :\n\t\t\tbp[i] === preferredDoc ? 1 :\n\t\t\t0;\n\t};\n\n\t// Always assume the presence of duplicates if sort doesn't\n\t// pass them to our comparison function (as in Google Chrome).\n\thasDuplicate = false;\n\t[0, 0].sort( sortOrder );\n\tsupport.detectDuplicates = hasDuplicate;\n\n\treturn document;\n};\n\nSizzle.matches = function( expr, elements ) {\n\treturn Sizzle( expr, null, null, elements );\n};\n\nSizzle.matchesSelector = function( elem, expr ) {\n\t// Set document vars if needed\n\tif ( ( elem.ownerDocument || elem ) !== document ) {\n\t\tsetDocument( elem );\n\t}\n\n\t// Make sure that attribute selectors are quoted\n\texpr = expr.replace( rattributeQuotes, \"='$1']\" );\n\n\t// rbuggyQSA always contains :focus, so no need for an existence check\n\tif ( support.matchesSelector && !documentIsXML && (!rbuggyMatches || !rbuggyMatches.test(expr)) && !rbuggyQSA.test(expr) ) {\n\t\ttry {\n\t\t\tvar ret = matches.call( elem, expr );\n\n\t\t\t// IE 9's matchesSelector returns false on disconnected nodes\n\t\t\tif ( ret || support.disconnectedMatch ||\n\t\t\t\t\t// As well, disconnected nodes are said to be in a document\n\t\t\t\t\t// fragment in IE 9\n\t\t\t\t\telem.document && elem.document.nodeType !== 11 ) {\n\t\t\t\treturn ret;\n\t\t\t}\n\t\t} catch(e) {}\n\t}\n\n\treturn Sizzle( expr, document, null, [elem] ).length > 0;\n};\n\nSizzle.contains = function( context, elem ) {\n\t// Set document vars if needed\n\tif ( ( context.ownerDocument || context ) !== document ) {\n\t\tsetDocument( context );\n\t}\n\treturn contains( context, elem );\n};\n\nSizzle.attr = function( elem, name ) {\n\tvar val;\n\n\t// Set document vars if needed\n\tif ( ( elem.ownerDocument || elem ) !== document ) {\n\t\tsetDocument( elem );\n\t}\n\n\tif ( !documentIsXML ) {\n\t\tname = name.toLowerCase();\n\t}\n\tif ( (val = Expr.attrHandle[ name ]) ) {\n\t\treturn val( elem );\n\t}\n\tif ( documentIsXML || support.attributes ) {\n\t\treturn elem.getAttribute( name );\n\t}\n\treturn ( (val = elem.getAttributeNode( name )) || elem.getAttribute( name ) ) && elem[ name ] === true ?\n\t\tname :\n\t\tval && val.specified ? val.value : null;\n};\n\nSizzle.error = function( msg ) {\n\tthrow new Error( \"Syntax error, unrecognized expression: \" + msg );\n};\n\n// Document sorting and removing duplicates\nSizzle.uniqueSort = function( results ) {\n\tvar elem,\n\t\tduplicates = [],\n\t\ti = 1,\n\t\tj = 0;\n\n\t// Unless we *know* we can detect duplicates, assume their presence\n\thasDuplicate = !support.detectDuplicates;\n\tresults.sort( sortOrder );\n\n\tif ( hasDuplicate ) {\n\t\tfor ( ; (elem = results[i]); i++ ) {\n\t\t\tif ( elem === results[ i - 1 ] ) {\n\t\t\t\tj = duplicates.push( i );\n\t\t\t}\n\t\t}\n\t\twhile ( j-- ) {\n\t\t\tresults.splice( duplicates[ j ], 1 );\n\t\t}\n\t}\n\n\treturn results;\n};\n\nfunction siblingCheck( a, b ) {\n\tvar cur = b && a,\n\t\tdiff = cur && ( ~b.sourceIndex || MAX_NEGATIVE ) - ( ~a.sourceIndex || MAX_NEGATIVE );\n\n\t// Use IE sourceIndex if available on both nodes\n\tif ( diff ) {\n\t\treturn diff;\n\t}\n\n\t// Check if b follows a\n\tif ( cur ) {\n\t\twhile ( (cur = cur.nextSibling) ) {\n\t\t\tif ( cur === b ) {\n\t\t\t\treturn -1;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn a ? 1 : -1;\n}\n\n// Returns a function to use in pseudos for input types\nfunction createInputPseudo( type ) {\n\treturn function( elem ) {\n\t\tvar name = elem.nodeName.toLowerCase();\n\t\treturn name === \"input\" && elem.type === type;\n\t};\n}\n\n// Returns a function to use in pseudos for buttons\nfunction createButtonPseudo( type ) {\n\treturn function( elem ) {\n\t\tvar name = elem.nodeName.toLowerCase();\n\t\treturn (name === \"input\" || name === \"button\") && elem.type === type;\n\t};\n}\n\n// Returns a function to use in pseudos for positionals\nfunction createPositionalPseudo( fn ) {\n\treturn markFunction(function( argument ) {\n\t\targument = +argument;\n\t\treturn markFunction(function( seed, matches ) {\n\t\t\tvar j,\n\t\t\t\tmatchIndexes = fn( [], seed.length, argument ),\n\t\t\t\ti = matchIndexes.length;\n\n\t\t\t// Match elements found at the specified indexes\n\t\t\twhile ( i-- ) {\n\t\t\t\tif ( seed[ (j = matchIndexes[i]) ] ) {\n\t\t\t\t\tseed[j] = !(matches[j] = seed[j]);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t});\n}\n\n/**\n * Utility function for retrieving the text value of an array of DOM nodes\n * @param {Array|Element} elem\n */\ngetText = Sizzle.getText = function( elem ) {\n\tvar node,\n\t\tret = \"\",\n\t\ti = 0,\n\t\tnodeType = elem.nodeType;\n\n\tif ( !nodeType ) {\n\t\t// If no nodeType, this is expected to be an array\n\t\tfor ( ; (node = elem[i]); i++ ) {\n\t\t\t// Do not traverse comment nodes\n\t\t\tret += getText( node );\n\t\t}\n\t} else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) {\n\t\t// Use textContent for elements\n\t\t// innerText usage removed for consistency of new lines (see #11153)\n\t\tif ( typeof elem.textContent === \"string\" ) {\n\t\t\treturn elem.textContent;\n\t\t} else {\n\t\t\t// Traverse its children\n\t\t\tfor ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {\n\t\t\t\tret += getText( elem );\n\t\t\t}\n\t\t}\n\t} else if ( nodeType === 3 || nodeType === 4 ) {\n\t\treturn elem.nodeValue;\n\t}\n\t// Do not include comment or processing instruction nodes\n\n\treturn ret;\n};\n\nExpr = Sizzle.selectors = {\n\n\t// Can be adjusted by the user\n\tcacheLength: 50,\n\n\tcreatePseudo: markFunction,\n\n\tmatch: matchExpr,\n\n\tfind: {},\n\n\trelative: {\n\t\t\">\": { dir: \"parentNode\", first: true },\n\t\t\" \": { dir: \"parentNode\" },\n\t\t\"+\": { dir: \"previousSibling\", first: true },\n\t\t\"~\": { dir: \"previousSibling\" }\n\t},\n\n\tpreFilter: {\n\t\t\"ATTR\": function( match ) {\n\t\t\tmatch[1] = match[1].replace( runescape, funescape );\n\n\t\t\t// Move the given value to match[3] whether quoted or unquoted\n\t\t\tmatch[3] = ( match[4] || match[5] || \"\" ).replace( runescape, funescape );\n\n\t\t\tif ( match[2] === \"~=\" ) {\n\t\t\t\tmatch[3] = \" \" + match[3] + \" \";\n\t\t\t}\n\n\t\t\treturn match.slice( 0, 4 );\n\t\t},\n\n\t\t\"CHILD\": function( match ) {\n\t\t\t/* matches from matchExpr[\"CHILD\"]\n\t\t\t\t1 type (only|nth|...)\n\t\t\t\t2 what (child|of-type)\n\t\t\t\t3 argument (even|odd|\\d*|\\d*n([+-]\\d+)?|...)\n\t\t\t\t4 xn-component of xn+y argument ([+-]?\\d*n|)\n\t\t\t\t5 sign of xn-component\n\t\t\t\t6 x of xn-component\n\t\t\t\t7 sign of y-component\n\t\t\t\t8 y of y-component\n\t\t\t*/\n\t\t\tmatch[1] = match[1].toLowerCase();\n\n\t\t\tif ( match[1].slice( 0, 3 ) === \"nth\" ) {\n\t\t\t\t// nth-* requires argument\n\t\t\t\tif ( !match[3] ) {\n\t\t\t\t\tSizzle.error( match[0] );\n\t\t\t\t}\n\n\t\t\t\t// numeric x and y parameters for Expr.filter.CHILD\n\t\t\t\t// remember that false/true cast respectively to 0/1\n\t\t\t\tmatch[4] = +( match[4] ? match[5] + (match[6] || 1) : 2 * ( match[3] === \"even\" || match[3] === \"odd\" ) );\n\t\t\t\tmatch[5] = +( ( match[7] + match[8] ) || match[3] === \"odd\" );\n\n\t\t\t// other types prohibit arguments\n\t\t\t} else if ( match[3] ) {\n\t\t\t\tSizzle.error( match[0] );\n\t\t\t}\n\n\t\t\treturn match;\n\t\t},\n\n\t\t\"PSEUDO\": function( match ) {\n\t\t\tvar excess,\n\t\t\t\tunquoted = !match[5] && match[2];\n\n\t\t\tif ( matchExpr[\"CHILD\"].test( match[0] ) ) {\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\t// Accept quoted arguments as-is\n\t\t\tif ( match[4] ) {\n\t\t\t\tmatch[2] = match[4];\n\n\t\t\t// Strip excess characters from unquoted arguments\n\t\t\t} else if ( unquoted && rpseudo.test( unquoted ) &&\n\t\t\t\t// Get excess from tokenize (recursively)\n\t\t\t\t(excess = tokenize( unquoted, true )) &&\n\t\t\t\t// advance to the next closing parenthesis\n\t\t\t\t(excess = unquoted.indexOf( \")\", unquoted.length - excess ) - unquoted.length) ) {\n\n\t\t\t\t// excess is a negative index\n\t\t\t\tmatch[0] = match[0].slice( 0, excess );\n\t\t\t\tmatch[2] = unquoted.slice( 0, excess );\n\t\t\t}\n\n\t\t\t// Return only captures needed by the pseudo filter method (type and argument)\n\t\t\treturn match.slice( 0, 3 );\n\t\t}\n\t},\n\n\tfilter: {\n\n\t\t\"TAG\": function( nodeName ) {\n\t\t\tif ( nodeName === \"*\" ) {\n\t\t\t\treturn function() { return true; };\n\t\t\t}\n\n\t\t\tnodeName = nodeName.replace( runescape, funescape ).toLowerCase();\n\t\t\treturn function( elem ) {\n\t\t\t\treturn elem.nodeName && elem.nodeName.toLowerCase() === nodeName;\n\t\t\t};\n\t\t},\n\n\t\t\"CLASS\": function( className ) {\n\t\t\tvar pattern = classCache[ className + \" \" ];\n\n\t\t\treturn pattern ||\n\t\t\t\t(pattern = new RegExp( \"(^|\" + whitespace + \")\" + className + \"(\" + whitespace + \"|$)\" )) &&\n\t\t\t\tclassCache( className, function( elem ) {\n\t\t\t\t\treturn pattern.test( elem.className || (typeof elem.getAttribute !== strundefined && elem.getAttribute(\"class\")) || \"\" );\n\t\t\t\t});\n\t\t},\n\n\t\t\"ATTR\": function( name, operator, check ) {\n\t\t\treturn function( elem ) {\n\t\t\t\tvar result = Sizzle.attr( elem, name );\n\n\t\t\t\tif ( result == null ) {\n\t\t\t\t\treturn operator === \"!=\";\n\t\t\t\t}\n\t\t\t\tif ( !operator ) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\n\t\t\t\tresult += \"\";\n\n\t\t\t\treturn operator === \"=\" ? result === check :\n\t\t\t\t\toperator === \"!=\" ? result !== check :\n\t\t\t\t\toperator === \"^=\" ? check && result.indexOf( check ) === 0 :\n\t\t\t\t\toperator === \"*=\" ? check && result.indexOf( check ) > -1 :\n\t\t\t\t\toperator === \"$=\" ? check && result.slice( -check.length ) === check :\n\t\t\t\t\toperator === \"~=\" ? ( \" \" + result + \" \" ).indexOf( check ) > -1 :\n\t\t\t\t\toperator === \"|=\" ? result === check || result.slice( 0, check.length + 1 ) === check + \"-\" :\n\t\t\t\t\tfalse;\n\t\t\t};\n\t\t},\n\n\t\t\"CHILD\": function( type, what, argument, first, last ) {\n\t\t\tvar simple = type.slice( 0, 3 ) !== \"nth\",\n\t\t\t\tforward = type.slice( -4 ) !== \"last\",\n\t\t\t\tofType = what === \"of-type\";\n\n\t\t\treturn first === 1 && last === 0 ?\n\n\t\t\t\t// Shortcut for :nth-*(n)\n\t\t\t\tfunction( elem ) {\n\t\t\t\t\treturn !!elem.parentNode;\n\t\t\t\t} :\n\n\t\t\t\tfunction( elem, context, xml ) {\n\t\t\t\t\tvar cache, outerCache, node, diff, nodeIndex, start,\n\t\t\t\t\t\tdir = simple !== forward ? \"nextSibling\" : \"previousSibling\",\n\t\t\t\t\t\tparent = elem.parentNode,\n\t\t\t\t\t\tname = ofType && elem.nodeName.toLowerCase(),\n\t\t\t\t\t\tuseCache = !xml && !ofType;\n\n\t\t\t\t\tif ( parent ) {\n\n\t\t\t\t\t\t// :(first|last|only)-(child|of-type)\n\t\t\t\t\t\tif ( simple ) {\n\t\t\t\t\t\t\twhile ( dir ) {\n\t\t\t\t\t\t\t\tnode = elem;\n\t\t\t\t\t\t\t\twhile ( (node = node[ dir ]) ) {\n\t\t\t\t\t\t\t\t\tif ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) {\n\t\t\t\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t// Reverse direction for :only-* (if we haven't yet done so)\n\t\t\t\t\t\t\t\tstart = dir = type === \"only\" && !start && \"nextSibling\";\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tstart = [ forward ? parent.firstChild : parent.lastChild ];\n\n\t\t\t\t\t\t// non-xml :nth-child(...) stores cache data on `parent`\n\t\t\t\t\t\tif ( forward && useCache ) {\n\t\t\t\t\t\t\t// Seek `elem` from a previously-cached index\n\t\t\t\t\t\t\touterCache = parent[ expando ] || (parent[ expando ] = {});\n\t\t\t\t\t\t\tcache = outerCache[ type ] || [];\n\t\t\t\t\t\t\tnodeIndex = cache[0] === dirruns && cache[1];\n\t\t\t\t\t\t\tdiff = cache[0] === dirruns && cache[2];\n\t\t\t\t\t\t\tnode = nodeIndex && parent.childNodes[ nodeIndex ];\n\n\t\t\t\t\t\t\twhile ( (node = ++nodeIndex && node && node[ dir ] ||\n\n\t\t\t\t\t\t\t\t// Fallback to seeking `elem` from the start\n\t\t\t\t\t\t\t\t(diff = nodeIndex = 0) || start.pop()) ) {\n\n\t\t\t\t\t\t\t\t// When found, cache indexes on `parent` and break\n\t\t\t\t\t\t\t\tif ( node.nodeType === 1 && ++diff && node === elem ) {\n\t\t\t\t\t\t\t\t\touterCache[ type ] = [ dirruns, nodeIndex, diff ];\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Use previously-cached element index if available\n\t\t\t\t\t\t} else if ( useCache && (cache = (elem[ expando ] || (elem[ expando ] = {}))[ type ]) && cache[0] === dirruns ) {\n\t\t\t\t\t\t\tdiff = cache[1];\n\n\t\t\t\t\t\t// xml :nth-child(...) or :nth-last-child(...) or :nth(-last)?-of-type(...)\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t// Use the same loop as above to seek `elem` from the start\n\t\t\t\t\t\t\twhile ( (node = ++nodeIndex && node && node[ dir ] ||\n\t\t\t\t\t\t\t\t(diff = nodeIndex = 0) || start.pop()) ) {\n\n\t\t\t\t\t\t\t\tif ( ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) && ++diff ) {\n\t\t\t\t\t\t\t\t\t// Cache the index of each encountered element\n\t\t\t\t\t\t\t\t\tif ( useCache ) {\n\t\t\t\t\t\t\t\t\t\t(node[ expando ] || (node[ expando ] = {}))[ type ] = [ dirruns, diff ];\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\tif ( node === elem ) {\n\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Incorporate the offset, then check against cycle size\n\t\t\t\t\t\tdiff -= last;\n\t\t\t\t\t\treturn diff === first || ( diff % first === 0 && diff / first >= 0 );\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t},\n\n\t\t\"PSEUDO\": function( pseudo, argument ) {\n\t\t\t// pseudo-class names are case-insensitive\n\t\t\t// http://www.w3.org/TR/selectors/#pseudo-classes\n\t\t\t// Prioritize by case sensitivity in case custom pseudos are added with uppercase letters\n\t\t\t// Remember that setFilters inherits from pseudos\n\t\t\tvar args,\n\t\t\t\tfn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] ||\n\t\t\t\t\tSizzle.error( \"unsupported pseudo: \" + pseudo );\n\n\t\t\t// The user may use createPseudo to indicate that\n\t\t\t// arguments are needed to create the filter function\n\t\t\t// just as Sizzle does\n\t\t\tif ( fn[ expando ] ) {\n\t\t\t\treturn fn( argument );\n\t\t\t}\n\n\t\t\t// But maintain support for old signatures\n\t\t\tif ( fn.length > 1 ) {\n\t\t\t\targs = [ pseudo, pseudo, \"\", argument ];\n\t\t\t\treturn Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ?\n\t\t\t\t\tmarkFunction(function( seed, matches ) {\n\t\t\t\t\t\tvar idx,\n\t\t\t\t\t\t\tmatched = fn( seed, argument ),\n\t\t\t\t\t\t\ti = matched.length;\n\t\t\t\t\t\twhile ( i-- ) {\n\t\t\t\t\t\t\tidx = indexOf.call( seed, matched[i] );\n\t\t\t\t\t\t\tseed[ idx ] = !( matches[ idx ] = matched[i] );\n\t\t\t\t\t\t}\n\t\t\t\t\t}) :\n\t\t\t\t\tfunction( elem ) {\n\t\t\t\t\t\treturn fn( elem, 0, args );\n\t\t\t\t\t};\n\t\t\t}\n\n\t\t\treturn fn;\n\t\t}\n\t},\n\n\tpseudos: {\n\t\t// Potentially complex pseudos\n\t\t\"not\": markFunction(function( selector ) {\n\t\t\t// Trim the selector passed to compile\n\t\t\t// to avoid treating leading and trailing\n\t\t\t// spaces as combinators\n\t\t\tvar input = [],\n\t\t\t\tresults = [],\n\t\t\t\tmatcher = compile( selector.replace( rtrim, \"$1\" ) );\n\n\t\t\treturn matcher[ expando ] ?\n\t\t\t\tmarkFunction(function( seed, matches, context, xml ) {\n\t\t\t\t\tvar elem,\n\t\t\t\t\t\tunmatched = matcher( seed, null, xml, [] ),\n\t\t\t\t\t\ti = seed.length;\n\n\t\t\t\t\t// Match elements unmatched by `matcher`\n\t\t\t\t\twhile ( i-- ) {\n\t\t\t\t\t\tif ( (elem = unmatched[i]) ) {\n\t\t\t\t\t\t\tseed[i] = !(matches[i] = elem);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}) :\n\t\t\t\tfunction( elem, context, xml ) {\n\t\t\t\t\tinput[0] = elem;\n\t\t\t\t\tmatcher( input, null, xml, results );\n\t\t\t\t\treturn !results.pop();\n\t\t\t\t};\n\t\t}),\n\n\t\t\"has\": markFunction(function( selector ) {\n\t\t\treturn function( elem ) {\n\t\t\t\treturn Sizzle( selector, elem ).length > 0;\n\t\t\t};\n\t\t}),\n\n\t\t\"contains\": markFunction(function( text ) {\n\t\t\treturn function( elem ) {\n\t\t\t\treturn ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1;\n\t\t\t};\n\t\t}),\n\n\t\t// \"Whether an element is represented by a :lang() selector\n\t\t// is based solely on the element's language value\n\t\t// being equal to the identifier C,\n\t\t// or beginning with the identifier C immediately followed by \"-\".\n\t\t// The matching of C against the element's language value is performed case-insensitively.\n\t\t// The identifier C does not have to be a valid language name.\"\n\t\t// http://www.w3.org/TR/selectors/#lang-pseudo\n\t\t\"lang\": markFunction( function( lang ) {\n\t\t\t// lang value must be a valid identifider\n\t\t\tif ( !ridentifier.test(lang || \"\") ) {\n\t\t\t\tSizzle.error( \"unsupported lang: \" + lang );\n\t\t\t}\n\t\t\tlang = lang.replace( runescape, funescape ).toLowerCase();\n\t\t\treturn function( elem ) {\n\t\t\t\tvar elemLang;\n\t\t\t\tdo {\n\t\t\t\t\tif ( (elemLang = documentIsXML ?\n\t\t\t\t\t\telem.getAttribute(\"xml:lang\") || elem.getAttribute(\"lang\") :\n\t\t\t\t\t\telem.lang) ) {\n\n\t\t\t\t\t\telemLang = elemLang.toLowerCase();\n\t\t\t\t\t\treturn elemLang === lang || elemLang.indexOf( lang + \"-\" ) === 0;\n\t\t\t\t\t}\n\t\t\t\t} while ( (elem = elem.parentNode) && elem.nodeType === 1 );\n\t\t\t\treturn false;\n\t\t\t};\n\t\t}),\n\n\t\t// Miscellaneous\n\t\t\"target\": function( elem ) {\n\t\t\tvar hash = window.location && window.location.hash;\n\t\t\treturn hash && hash.slice( 1 ) === elem.id;\n\t\t},\n\n\t\t\"root\": function( elem ) {\n\t\t\treturn elem === docElem;\n\t\t},\n\n\t\t\"focus\": function( elem ) {\n\t\t\treturn elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex);\n\t\t},\n\n\t\t// Boolean properties\n\t\t\"enabled\": function( elem ) {\n\t\t\treturn elem.disabled === false;\n\t\t},\n\n\t\t\"disabled\": function( elem ) {\n\t\t\treturn elem.disabled === true;\n\t\t},\n\n\t\t\"checked\": function( elem ) {\n\t\t\t// In CSS3, :checked should return both checked and selected elements\n\t\t\t// http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked\n\t\t\tvar nodeName = elem.nodeName.toLowerCase();\n\t\t\treturn (nodeName === \"input\" && !!elem.checked) || (nodeName === \"option\" && !!elem.selected);\n\t\t},\n\n\t\t\"selected\": function( elem ) {\n\t\t\t// Accessing this property makes selected-by-default\n\t\t\t// options in Safari work properly\n\t\t\tif ( elem.parentNode ) {\n\t\t\t\telem.parentNode.selectedIndex;\n\t\t\t}\n\n\t\t\treturn elem.selected === true;\n\t\t},\n\n\t\t// Contents\n\t\t\"empty\": function( elem ) {\n\t\t\t// http://www.w3.org/TR/selectors/#empty-pseudo\n\t\t\t// :empty is only affected by element nodes and content nodes(including text(3), cdata(4)),\n\t\t\t//   not comment, processing instructions, or others\n\t\t\t// Thanks to Diego Perini for the nodeName shortcut\n\t\t\t//   Greater than \"@\" means alpha characters (specifically not starting with \"#\" or \"?\")\n\t\t\tfor ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {\n\t\t\t\tif ( elem.nodeName > \"@\" || elem.nodeType === 3 || elem.nodeType === 4 ) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn true;\n\t\t},\n\n\t\t\"parent\": function( elem ) {\n\t\t\treturn !Expr.pseudos[\"empty\"]( elem );\n\t\t},\n\n\t\t// Element/input types\n\t\t\"header\": function( elem ) {\n\t\t\treturn rheader.test( elem.nodeName );\n\t\t},\n\n\t\t\"input\": function( elem ) {\n\t\t\treturn rinputs.test( elem.nodeName );\n\t\t},\n\n\t\t\"button\": function( elem ) {\n\t\t\tvar name = elem.nodeName.toLowerCase();\n\t\t\treturn name === \"input\" && elem.type === \"button\" || name === \"button\";\n\t\t},\n\n\t\t\"text\": function( elem ) {\n\t\t\tvar attr;\n\t\t\t// IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc)\n\t\t\t// use getAttribute instead to test this case\n\t\t\treturn elem.nodeName.toLowerCase() === \"input\" &&\n\t\t\t\telem.type === \"text\" &&\n\t\t\t\t( (attr = elem.getAttribute(\"type\")) == null || attr.toLowerCase() === elem.type );\n\t\t},\n\n\t\t// Position-in-collection\n\t\t\"first\": createPositionalPseudo(function() {\n\t\t\treturn [ 0 ];\n\t\t}),\n\n\t\t\"last\": createPositionalPseudo(function( matchIndexes, length ) {\n\t\t\treturn [ length - 1 ];\n\t\t}),\n\n\t\t\"eq\": createPositionalPseudo(function( matchIndexes, length, argument ) {\n\t\t\treturn [ argument < 0 ? argument + length : argument ];\n\t\t}),\n\n\t\t\"even\": createPositionalPseudo(function( matchIndexes, length ) {\n\t\t\tvar i = 0;\n\t\t\tfor ( ; i < length; i += 2 ) {\n\t\t\t\tmatchIndexes.push( i );\n\t\t\t}\n\t\t\treturn matchIndexes;\n\t\t}),\n\n\t\t\"odd\": createPositionalPseudo(function( matchIndexes, length ) {\n\t\t\tvar i = 1;\n\t\t\tfor ( ; i < length; i += 2 ) {\n\t\t\t\tmatchIndexes.push( i );\n\t\t\t}\n\t\t\treturn matchIndexes;\n\t\t}),\n\n\t\t\"lt\": createPositionalPseudo(function( matchIndexes, length, argument ) {\n\t\t\tvar i = argument < 0 ? argument + length : argument;\n\t\t\tfor ( ; --i >= 0; ) {\n\t\t\t\tmatchIndexes.push( i );\n\t\t\t}\n\t\t\treturn matchIndexes;\n\t\t}),\n\n\t\t\"gt\": createPositionalPseudo(function( matchIndexes, length, argument ) {\n\t\t\tvar i = argument < 0 ? argument + length : argument;\n\t\t\tfor ( ; ++i < length; ) {\n\t\t\t\tmatchIndexes.push( i );\n\t\t\t}\n\t\t\treturn matchIndexes;\n\t\t})\n\t}\n};\n\n// Add button/input type pseudos\nfor ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) {\n\tExpr.pseudos[ i ] = createInputPseudo( i );\n}\nfor ( i in { submit: true, reset: true } ) {\n\tExpr.pseudos[ i ] = createButtonPseudo( i );\n}\n\nfunction tokenize( selector, parseOnly ) {\n\tvar matched, match, tokens, type,\n\t\tsoFar, groups, preFilters,\n\t\tcached = tokenCache[ selector + \" \" ];\n\n\tif ( cached ) {\n\t\treturn parseOnly ? 0 : cached.slice( 0 );\n\t}\n\n\tsoFar = selector;\n\tgroups = [];\n\tpreFilters = Expr.preFilter;\n\n\twhile ( soFar ) {\n\n\t\t// Comma and first run\n\t\tif ( !matched || (match = rcomma.exec( soFar )) ) {\n\t\t\tif ( match ) {\n\t\t\t\t// Don't consume trailing commas as valid\n\t\t\t\tsoFar = soFar.slice( match[0].length ) || soFar;\n\t\t\t}\n\t\t\tgroups.push( tokens = [] );\n\t\t}\n\n\t\tmatched = false;\n\n\t\t// Combinators\n\t\tif ( (match = rcombinators.exec( soFar )) ) {\n\t\t\tmatched = match.shift();\n\t\t\ttokens.push( {\n\t\t\t\tvalue: matched,\n\t\t\t\t// Cast descendant combinators to space\n\t\t\t\ttype: match[0].replace( rtrim, \" \" )\n\t\t\t} );\n\t\t\tsoFar = soFar.slice( matched.length );\n\t\t}\n\n\t\t// Filters\n\t\tfor ( type in Expr.filter ) {\n\t\t\tif ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] ||\n\t\t\t\t(match = preFilters[ type ]( match ))) ) {\n\t\t\t\tmatched = match.shift();\n\t\t\t\ttokens.push( {\n\t\t\t\t\tvalue: matched,\n\t\t\t\t\ttype: type,\n\t\t\t\t\tmatches: match\n\t\t\t\t} );\n\t\t\t\tsoFar = soFar.slice( matched.length );\n\t\t\t}\n\t\t}\n\n\t\tif ( !matched ) {\n\t\t\tbreak;\n\t\t}\n\t}\n\n\t// Return the length of the invalid excess\n\t// if we're just parsing\n\t// Otherwise, throw an error or return tokens\n\treturn parseOnly ?\n\t\tsoFar.length :\n\t\tsoFar ?\n\t\t\tSizzle.error( selector ) :\n\t\t\t// Cache the tokens\n\t\t\ttokenCache( selector, groups ).slice( 0 );\n}\n\nfunction toSelector( tokens ) {\n\tvar i = 0,\n\t\tlen = tokens.length,\n\t\tselector = \"\";\n\tfor ( ; i < len; i++ ) {\n\t\tselector += tokens[i].value;\n\t}\n\treturn selector;\n}\n\nfunction addCombinator( matcher, combinator, base ) {\n\tvar dir = combinator.dir,\n\t\tcheckNonElements = base && dir === \"parentNode\",\n\t\tdoneName = done++;\n\n\treturn combinator.first ?\n\t\t// Check against closest ancestor/preceding element\n\t\tfunction( elem, context, xml ) {\n\t\t\twhile ( (elem = elem[ dir ]) ) {\n\t\t\t\tif ( elem.nodeType === 1 || checkNonElements ) {\n\t\t\t\t\treturn matcher( elem, context, xml );\n\t\t\t\t}\n\t\t\t}\n\t\t} :\n\n\t\t// Check against all ancestor/preceding elements\n\t\tfunction( elem, context, xml ) {\n\t\t\tvar data, cache, outerCache,\n\t\t\t\tdirkey = dirruns + \" \" + doneName;\n\n\t\t\t// We can't set arbitrary data on XML nodes, so they don't benefit from dir caching\n\t\t\tif ( xml ) {\n\t\t\t\twhile ( (elem = elem[ dir ]) ) {\n\t\t\t\t\tif ( elem.nodeType === 1 || checkNonElements ) {\n\t\t\t\t\t\tif ( matcher( elem, context, xml ) ) {\n\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\twhile ( (elem = elem[ dir ]) ) {\n\t\t\t\t\tif ( elem.nodeType === 1 || checkNonElements ) {\n\t\t\t\t\t\touterCache = elem[ expando ] || (elem[ expando ] = {});\n\t\t\t\t\t\tif ( (cache = outerCache[ dir ]) && cache[0] === dirkey ) {\n\t\t\t\t\t\t\tif ( (data = cache[1]) === true || data === cachedruns ) {\n\t\t\t\t\t\t\t\treturn data === true;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tcache = outerCache[ dir ] = [ dirkey ];\n\t\t\t\t\t\t\tcache[1] = matcher( elem, context, xml ) || cachedruns;\n\t\t\t\t\t\t\tif ( cache[1] === true ) {\n\t\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t};\n}\n\nfunction elementMatcher( matchers ) {\n\treturn matchers.length > 1 ?\n\t\tfunction( elem, context, xml ) {\n\t\t\tvar i = matchers.length;\n\t\t\twhile ( i-- ) {\n\t\t\t\tif ( !matchers[i]( elem, context, xml ) ) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn true;\n\t\t} :\n\t\tmatchers[0];\n}\n\nfunction condense( unmatched, map, filter, context, xml ) {\n\tvar elem,\n\t\tnewUnmatched = [],\n\t\ti = 0,\n\t\tlen = unmatched.length,\n\t\tmapped = map != null;\n\n\tfor ( ; i < len; i++ ) {\n\t\tif ( (elem = unmatched[i]) ) {\n\t\t\tif ( !filter || filter( elem, context, xml ) ) {\n\t\t\t\tnewUnmatched.push( elem );\n\t\t\t\tif ( mapped ) {\n\t\t\t\t\tmap.push( i );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn newUnmatched;\n}\n\nfunction setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) {\n\tif ( postFilter && !postFilter[ expando ] ) {\n\t\tpostFilter = setMatcher( postFilter );\n\t}\n\tif ( postFinder && !postFinder[ expando ] ) {\n\t\tpostFinder = setMatcher( postFinder, postSelector );\n\t}\n\treturn markFunction(function( seed, results, context, xml ) {\n\t\tvar temp, i, elem,\n\t\t\tpreMap = [],\n\t\t\tpostMap = [],\n\t\t\tpreexisting = results.length,\n\n\t\t\t// Get initial elements from seed or context\n\t\t\telems = seed || multipleContexts( selector || \"*\", context.nodeType ? [ context ] : context, [] ),\n\n\t\t\t// Prefilter to get matcher input, preserving a map for seed-results synchronization\n\t\t\tmatcherIn = preFilter && ( seed || !selector ) ?\n\t\t\t\tcondense( elems, preMap, preFilter, context, xml ) :\n\t\t\t\telems,\n\n\t\t\tmatcherOut = matcher ?\n\t\t\t\t// If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results,\n\t\t\t\tpostFinder || ( seed ? preFilter : preexisting || postFilter ) ?\n\n\t\t\t\t\t// ...intermediate processing is necessary\n\t\t\t\t\t[] :\n\n\t\t\t\t\t// ...otherwise use results directly\n\t\t\t\t\tresults :\n\t\t\t\tmatcherIn;\n\n\t\t// Find primary matches\n\t\tif ( matcher ) {\n\t\t\tmatcher( matcherIn, matcherOut, context, xml );\n\t\t}\n\n\t\t// Apply postFilter\n\t\tif ( postFilter ) {\n\t\t\ttemp = condense( matcherOut, postMap );\n\t\t\tpostFilter( temp, [], context, xml );\n\n\t\t\t// Un-match failing elements by moving them back to matcherIn\n\t\t\ti = temp.length;\n\t\t\twhile ( i-- ) {\n\t\t\t\tif ( (elem = temp[i]) ) {\n\t\t\t\t\tmatcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif ( seed ) {\n\t\t\tif ( postFinder || preFilter ) {\n\t\t\t\tif ( postFinder ) {\n\t\t\t\t\t// Get the final matcherOut by condensing this intermediate into postFinder contexts\n\t\t\t\t\ttemp = [];\n\t\t\t\t\ti = matcherOut.length;\n\t\t\t\t\twhile ( i-- ) {\n\t\t\t\t\t\tif ( (elem = matcherOut[i]) ) {\n\t\t\t\t\t\t\t// Restore matcherIn since elem is not yet a final match\n\t\t\t\t\t\t\ttemp.push( (matcherIn[i] = elem) );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tpostFinder( null, (matcherOut = []), temp, xml );\n\t\t\t\t}\n\n\t\t\t\t// Move matched elements from seed to results to keep them synchronized\n\t\t\t\ti = matcherOut.length;\n\t\t\t\twhile ( i-- ) {\n\t\t\t\t\tif ( (elem = matcherOut[i]) &&\n\t\t\t\t\t\t(temp = postFinder ? indexOf.call( seed, elem ) : preMap[i]) > -1 ) {\n\n\t\t\t\t\t\tseed[temp] = !(results[temp] = elem);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t// Add elements to results, through postFinder if defined\n\t\t} else {\n\t\t\tmatcherOut = condense(\n\t\t\t\tmatcherOut === results ?\n\t\t\t\t\tmatcherOut.splice( preexisting, matcherOut.length ) :\n\t\t\t\t\tmatcherOut\n\t\t\t);\n\t\t\tif ( postFinder ) {\n\t\t\t\tpostFinder( null, results, matcherOut, xml );\n\t\t\t} else {\n\t\t\t\tpush.apply( results, matcherOut );\n\t\t\t}\n\t\t}\n\t});\n}\n\nfunction matcherFromTokens( tokens ) {\n\tvar checkContext, matcher, j,\n\t\tlen = tokens.length,\n\t\tleadingRelative = Expr.relative[ tokens[0].type ],\n\t\timplicitRelative = leadingRelative || Expr.relative[\" \"],\n\t\ti = leadingRelative ? 1 : 0,\n\n\t\t// The foundational matcher ensures that elements are reachable from top-level context(s)\n\t\tmatchContext = addCombinator( function( elem ) {\n\t\t\treturn elem === checkContext;\n\t\t}, implicitRelative, true ),\n\t\tmatchAnyContext = addCombinator( function( elem ) {\n\t\t\treturn indexOf.call( checkContext, elem ) > -1;\n\t\t}, implicitRelative, true ),\n\t\tmatchers = [ function( elem, context, xml ) {\n\t\t\treturn ( !leadingRelative && ( xml || context !== outermostContext ) ) || (\n\t\t\t\t(checkContext = context).nodeType ?\n\t\t\t\t\tmatchContext( elem, context, xml ) :\n\t\t\t\t\tmatchAnyContext( elem, context, xml ) );\n\t\t} ];\n\n\tfor ( ; i < len; i++ ) {\n\t\tif ( (matcher = Expr.relative[ tokens[i].type ]) ) {\n\t\t\tmatchers = [ addCombinator(elementMatcher( matchers ), matcher) ];\n\t\t} else {\n\t\t\tmatcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches );\n\n\t\t\t// Return special upon seeing a positional matcher\n\t\t\tif ( matcher[ expando ] ) {\n\t\t\t\t// Find the next relative operator (if any) for proper handling\n\t\t\t\tj = ++i;\n\t\t\t\tfor ( ; j < len; j++ ) {\n\t\t\t\t\tif ( Expr.relative[ tokens[j].type ] ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn setMatcher(\n\t\t\t\t\ti > 1 && elementMatcher( matchers ),\n\t\t\t\t\ti > 1 && toSelector( tokens.slice( 0, i - 1 ) ).replace( rtrim, \"$1\" ),\n\t\t\t\t\tmatcher,\n\t\t\t\t\ti < j && matcherFromTokens( tokens.slice( i, j ) ),\n\t\t\t\t\tj < len && matcherFromTokens( (tokens = tokens.slice( j )) ),\n\t\t\t\t\tj < len && toSelector( tokens )\n\t\t\t\t);\n\t\t\t}\n\t\t\tmatchers.push( matcher );\n\t\t}\n\t}\n\n\treturn elementMatcher( matchers );\n}\n\nfunction matcherFromGroupMatchers( elementMatchers, setMatchers ) {\n\t// A counter to specify which element is currently being matched\n\tvar matcherCachedRuns = 0,\n\t\tbySet = setMatchers.length > 0,\n\t\tbyElement = elementMatchers.length > 0,\n\t\tsuperMatcher = function( seed, context, xml, results, expandContext ) {\n\t\t\tvar elem, j, matcher,\n\t\t\t\tsetMatched = [],\n\t\t\t\tmatchedCount = 0,\n\t\t\t\ti = \"0\",\n\t\t\t\tunmatched = seed && [],\n\t\t\t\toutermost = expandContext != null,\n\t\t\t\tcontextBackup = outermostContext,\n\t\t\t\t// We must always have either seed elements or context\n\t\t\t\telems = seed || byElement && Expr.find[\"TAG\"]( \"*\", expandContext && context.parentNode || context ),\n\t\t\t\t// Use integer dirruns iff this is the outermost matcher\n\t\t\t\tdirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1);\n\n\t\t\tif ( outermost ) {\n\t\t\t\toutermostContext = context !== document && context;\n\t\t\t\tcachedruns = matcherCachedRuns;\n\t\t\t}\n\n\t\t\t// Add elements passing elementMatchers directly to results\n\t\t\t// Keep `i` a string if there are no elements so `matchedCount` will be \"00\" below\n\t\t\tfor ( ; (elem = elems[i]) != null; i++ ) {\n\t\t\t\tif ( byElement && elem ) {\n\t\t\t\t\tj = 0;\n\t\t\t\t\twhile ( (matcher = elementMatchers[j++]) ) {\n\t\t\t\t\t\tif ( matcher( elem, context, xml ) ) {\n\t\t\t\t\t\t\tresults.push( elem );\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif ( outermost ) {\n\t\t\t\t\t\tdirruns = dirrunsUnique;\n\t\t\t\t\t\tcachedruns = ++matcherCachedRuns;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Track unmatched elements for set filters\n\t\t\t\tif ( bySet ) {\n\t\t\t\t\t// They will have gone through all possible matchers\n\t\t\t\t\tif ( (elem = !matcher && elem) ) {\n\t\t\t\t\t\tmatchedCount--;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Lengthen the array for every element, matched or not\n\t\t\t\t\tif ( seed ) {\n\t\t\t\t\t\tunmatched.push( elem );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Apply set filters to unmatched elements\n\t\t\tmatchedCount += i;\n\t\t\tif ( bySet && i !== matchedCount ) {\n\t\t\t\tj = 0;\n\t\t\t\twhile ( (matcher = setMatchers[j++]) ) {\n\t\t\t\t\tmatcher( unmatched, setMatched, context, xml );\n\t\t\t\t}\n\n\t\t\t\tif ( seed ) {\n\t\t\t\t\t// Reintegrate element matches to eliminate the need for sorting\n\t\t\t\t\tif ( matchedCount > 0 ) {\n\t\t\t\t\t\twhile ( i-- ) {\n\t\t\t\t\t\t\tif ( !(unmatched[i] || setMatched[i]) ) {\n\t\t\t\t\t\t\t\tsetMatched[i] = pop.call( results );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Discard index placeholder values to get only actual matches\n\t\t\t\t\tsetMatched = condense( setMatched );\n\t\t\t\t}\n\n\t\t\t\t// Add matches to results\n\t\t\t\tpush.apply( results, setMatched );\n\n\t\t\t\t// Seedless set matches succeeding multiple successful matchers stipulate sorting\n\t\t\t\tif ( outermost && !seed && setMatched.length > 0 &&\n\t\t\t\t\t( matchedCount + setMatchers.length ) > 1 ) {\n\n\t\t\t\t\tSizzle.uniqueSort( results );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Override manipulation of globals by nested matchers\n\t\t\tif ( outermost ) {\n\t\t\t\tdirruns = dirrunsUnique;\n\t\t\t\toutermostContext = contextBackup;\n\t\t\t}\n\n\t\t\treturn unmatched;\n\t\t};\n\n\treturn bySet ?\n\t\tmarkFunction( superMatcher ) :\n\t\tsuperMatcher;\n}\n\ncompile = Sizzle.compile = function( selector, group /* Internal Use Only */ ) {\n\tvar i,\n\t\tsetMatchers = [],\n\t\telementMatchers = [],\n\t\tcached = compilerCache[ selector + \" \" ];\n\n\tif ( !cached ) {\n\t\t// Generate a function of recursive functions that can be used to check each element\n\t\tif ( !group ) {\n\t\t\tgroup = tokenize( selector );\n\t\t}\n\t\ti = group.length;\n\t\twhile ( i-- ) {\n\t\t\tcached = matcherFromTokens( group[i] );\n\t\t\tif ( cached[ expando ] ) {\n\t\t\t\tsetMatchers.push( cached );\n\t\t\t} else {\n\t\t\t\telementMatchers.push( cached );\n\t\t\t}\n\t\t}\n\n\t\t// Cache the compiled function\n\t\tcached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) );\n\t}\n\treturn cached;\n};\n\nfunction multipleContexts( selector, contexts, results ) {\n\tvar i = 0,\n\t\tlen = contexts.length;\n\tfor ( ; i < len; i++ ) {\n\t\tSizzle( selector, contexts[i], results );\n\t}\n\treturn results;\n}\n\nfunction select( selector, context, results, seed ) {\n\tvar i, tokens, token, type, find,\n\t\tmatch = tokenize( selector );\n\n\tif ( !seed ) {\n\t\t// Try to minimize operations if there is only one group\n\t\tif ( match.length === 1 ) {\n\n\t\t\t// Take a shortcut and set the context if the root selector is an ID\n\t\t\ttokens = match[0] = match[0].slice( 0 );\n\t\t\tif ( tokens.length > 2 && (token = tokens[0]).type === \"ID\" &&\n\t\t\t\t\tcontext.nodeType === 9 && !documentIsXML &&\n\t\t\t\t\tExpr.relative[ tokens[1].type ] ) {\n\n\t\t\t\tcontext = Expr.find[\"ID\"]( token.matches[0].replace( runescape, funescape ), context )[0];\n\t\t\t\tif ( !context ) {\n\t\t\t\t\treturn results;\n\t\t\t\t}\n\n\t\t\t\tselector = selector.slice( tokens.shift().value.length );\n\t\t\t}\n\n\t\t\t// Fetch a seed set for right-to-left matching\n\t\t\ti = matchExpr[\"needsContext\"].test( selector ) ? 0 : tokens.length;\n\t\t\twhile ( i-- ) {\n\t\t\t\ttoken = tokens[i];\n\n\t\t\t\t// Abort if we hit a combinator\n\t\t\t\tif ( Expr.relative[ (type = token.type) ] ) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tif ( (find = Expr.find[ type ]) ) {\n\t\t\t\t\t// Search, expanding context for leading sibling combinators\n\t\t\t\t\tif ( (seed = find(\n\t\t\t\t\t\ttoken.matches[0].replace( runescape, funescape ),\n\t\t\t\t\t\trsibling.test( tokens[0].type ) && context.parentNode || context\n\t\t\t\t\t)) ) {\n\n\t\t\t\t\t\t// If seed is empty or no tokens remain, we can return early\n\t\t\t\t\t\ttokens.splice( i, 1 );\n\t\t\t\t\t\tselector = seed.length && toSelector( tokens );\n\t\t\t\t\t\tif ( !selector ) {\n\t\t\t\t\t\t\tpush.apply( results, slice.call( seed, 0 ) );\n\t\t\t\t\t\t\treturn results;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Compile and execute a filtering function\n\t// Provide `match` to avoid retokenization if we modified the selector above\n\tcompile( selector, match )(\n\t\tseed,\n\t\tcontext,\n\t\tdocumentIsXML,\n\t\tresults,\n\t\trsibling.test( selector )\n\t);\n\treturn results;\n}\n\n// Deprecated\nExpr.pseudos[\"nth\"] = Expr.pseudos[\"eq\"];\n\n// Easy API for creating new setFilters\nfunction setFilters() {}\nExpr.filters = setFilters.prototype = Expr.pseudos;\nExpr.setFilters = new setFilters();\n\n// Initialize with the default document\nsetDocument();\n\n// Override sizzle attribute retrieval\nSizzle.attr = jQuery.attr;\njQuery.find = Sizzle;\njQuery.expr = Sizzle.selectors;\njQuery.expr[\":\"] = jQuery.expr.pseudos;\njQuery.unique = Sizzle.uniqueSort;\njQuery.text = Sizzle.getText;\njQuery.isXMLDoc = Sizzle.isXML;\njQuery.contains = Sizzle.contains;\n\n\n})( window );\nvar runtil = /Until$/,\n\trparentsprev = /^(?:parents|prev(?:Until|All))/,\n\tisSimple = /^.[^:#\\[\\.,]*$/,\n\trneedsContext = jQuery.expr.match.needsContext,\n\t// methods guaranteed to produce a unique set when starting from a unique set\n\tguaranteedUnique = {\n\t\tchildren: true,\n\t\tcontents: true,\n\t\tnext: true,\n\t\tprev: true\n\t};\n\njQuery.fn.extend({\n\tfind: function( selector ) {\n\t\tvar i, ret, self,\n\t\t\tlen = this.length;\n\n\t\tif ( typeof selector !== \"string\" ) {\n\t\t\tself = this;\n\t\t\treturn this.pushStack( jQuery( selector ).filter(function() {\n\t\t\t\tfor ( i = 0; i < len; i++ ) {\n\t\t\t\t\tif ( jQuery.contains( self[ i ], this ) ) {\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}) );\n\t\t}\n\n\t\tret = [];\n\t\tfor ( i = 0; i < len; i++ ) {\n\t\t\tjQuery.find( selector, this[ i ], ret );\n\t\t}\n\n\t\t// Needed because $( selector, context ) becomes $( context ).find( selector )\n\t\tret = this.pushStack( len > 1 ? jQuery.unique( ret ) : ret );\n\t\tret.selector = ( this.selector ? this.selector + \" \" : \"\" ) + selector;\n\t\treturn ret;\n\t},\n\n\thas: function( target ) {\n\t\tvar i,\n\t\t\ttargets = jQuery( target, this ),\n\t\t\tlen = targets.length;\n\n\t\treturn this.filter(function() {\n\t\t\tfor ( i = 0; i < len; i++ ) {\n\t\t\t\tif ( jQuery.contains( this, targets[i] ) ) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t},\n\n\tnot: function( selector ) {\n\t\treturn this.pushStack( winnow(this, selector, false) );\n\t},\n\n\tfilter: function( selector ) {\n\t\treturn this.pushStack( winnow(this, selector, true) );\n\t},\n\n\tis: function( selector ) {\n\t\treturn !!selector && (\n\t\t\ttypeof selector === \"string\" ?\n\t\t\t\t// If this is a positional/relative selector, check membership in the returned set\n\t\t\t\t// so $(\"p:first\").is(\"p:last\") won't return true for a doc with two \"p\".\n\t\t\t\trneedsContext.test( selector ) ?\n\t\t\t\t\tjQuery( selector, this.context ).index( this[0] ) >= 0 :\n\t\t\t\t\tjQuery.filter( selector, this ).length > 0 :\n\t\t\t\tthis.filter( selector ).length > 0 );\n\t},\n\n\tclosest: function( selectors, context ) {\n\t\tvar cur,\n\t\t\ti = 0,\n\t\t\tl = this.length,\n\t\t\tret = [],\n\t\t\tpos = rneedsContext.test( selectors ) || typeof selectors !== \"string\" ?\n\t\t\t\tjQuery( selectors, context || this.context ) :\n\t\t\t\t0;\n\n\t\tfor ( ; i < l; i++ ) {\n\t\t\tcur = this[i];\n\n\t\t\twhile ( cur && cur.ownerDocument && cur !== context && cur.nodeType !== 11 ) {\n\t\t\t\tif ( pos ? pos.index(cur) > -1 : jQuery.find.matchesSelector(cur, selectors) ) {\n\t\t\t\t\tret.push( cur );\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcur = cur.parentNode;\n\t\t\t}\n\t\t}\n\n\t\treturn this.pushStack( ret.length > 1 ? jQuery.unique( ret ) : ret );\n\t},\n\n\t// Determine the position of an element within\n\t// the matched set of elements\n\tindex: function( elem ) {\n\n\t\t// No argument, return index in parent\n\t\tif ( !elem ) {\n\t\t\treturn ( this[0] && this[0].parentNode ) ? this.first().prevAll().length : -1;\n\t\t}\n\n\t\t// index in selector\n\t\tif ( typeof elem === \"string\" ) {\n\t\t\treturn jQuery.inArray( this[0], jQuery( elem ) );\n\t\t}\n\n\t\t// Locate the position of the desired element\n\t\treturn jQuery.inArray(\n\t\t\t// If it receives a jQuery object, the first element is used\n\t\t\telem.jquery ? elem[0] : elem, this );\n\t},\n\n\tadd: function( selector, context ) {\n\t\tvar set = typeof selector === \"string\" ?\n\t\t\t\tjQuery( selector, context ) :\n\t\t\t\tjQuery.makeArray( selector && selector.nodeType ? [ selector ] : selector ),\n\t\t\tall = jQuery.merge( this.get(), set );\n\n\t\treturn this.pushStack( jQuery.unique(all) );\n\t},\n\n\taddBack: function( selector ) {\n\t\treturn this.add( selector == null ?\n\t\t\tthis.prevObject : this.prevObject.filter(selector)\n\t\t);\n\t}\n});\n\njQuery.fn.andSelf = jQuery.fn.addBack;\n\nfunction sibling( cur, dir ) {\n\tdo {\n\t\tcur = cur[ dir ];\n\t} while ( cur && cur.nodeType !== 1 );\n\n\treturn cur;\n}\n\njQuery.each({\n\tparent: function( elem ) {\n\t\tvar parent = elem.parentNode;\n\t\treturn parent && parent.nodeType !== 11 ? parent : null;\n\t},\n\tparents: function( elem ) {\n\t\treturn jQuery.dir( elem, \"parentNode\" );\n\t},\n\tparentsUntil: function( elem, i, until ) {\n\t\treturn jQuery.dir( elem, \"parentNode\", until );\n\t},\n\tnext: function( elem ) {\n\t\treturn sibling( elem, \"nextSibling\" );\n\t},\n\tprev: function( elem ) {\n\t\treturn sibling( elem, \"previousSibling\" );\n\t},\n\tnextAll: function( elem ) {\n\t\treturn jQuery.dir( elem, \"nextSibling\" );\n\t},\n\tprevAll: function( elem ) {\n\t\treturn jQuery.dir( elem, \"previousSibling\" );\n\t},\n\tnextUntil: function( elem, i, until ) {\n\t\treturn jQuery.dir( elem, \"nextSibling\", until );\n\t},\n\tprevUntil: function( elem, i, until ) {\n\t\treturn jQuery.dir( elem, \"previousSibling\", until );\n\t},\n\tsiblings: function( elem ) {\n\t\treturn jQuery.sibling( ( elem.parentNode || {} ).firstChild, elem );\n\t},\n\tchildren: function( elem ) {\n\t\treturn jQuery.sibling( elem.firstChild );\n\t},\n\tcontents: function( elem ) {\n\t\treturn jQuery.nodeName( elem, \"iframe\" ) ?\n\t\t\telem.contentDocument || elem.contentWindow.document :\n\t\t\tjQuery.merge( [], elem.childNodes );\n\t}\n}, function( name, fn ) {\n\tjQuery.fn[ name ] = function( until, selector ) {\n\t\tvar ret = jQuery.map( this, fn, until );\n\n\t\tif ( !runtil.test( name ) ) {\n\t\t\tselector = until;\n\t\t}\n\n\t\tif ( selector && typeof selector === \"string\" ) {\n\t\t\tret = jQuery.filter( selector, ret );\n\t\t}\n\n\t\tret = this.length > 1 && !guaranteedUnique[ name ] ? jQuery.unique( ret ) : ret;\n\n\t\tif ( this.length > 1 && rparentsprev.test( name ) ) {\n\t\t\tret = ret.reverse();\n\t\t}\n\n\t\treturn this.pushStack( ret );\n\t};\n});\n\njQuery.extend({\n\tfilter: function( expr, elems, not ) {\n\t\tif ( not ) {\n\t\t\texpr = \":not(\" + expr + \")\";\n\t\t}\n\n\t\treturn elems.length === 1 ?\n\t\t\tjQuery.find.matchesSelector(elems[0], expr) ? [ elems[0] ] : [] :\n\t\t\tjQuery.find.matches(expr, elems);\n\t},\n\n\tdir: function( elem, dir, until ) {\n\t\tvar matched = [],\n\t\t\tcur = elem[ dir ];\n\n\t\twhile ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) {\n\t\t\tif ( cur.nodeType === 1 ) {\n\t\t\t\tmatched.push( cur );\n\t\t\t}\n\t\t\tcur = cur[dir];\n\t\t}\n\t\treturn matched;\n\t},\n\n\tsibling: function( n, elem ) {\n\t\tvar r = [];\n\n\t\tfor ( ; n; n = n.nextSibling ) {\n\t\t\tif ( n.nodeType === 1 && n !== elem ) {\n\t\t\t\tr.push( n );\n\t\t\t}\n\t\t}\n\n\t\treturn r;\n\t}\n});\n\n// Implement the identical functionality for filter and not\nfunction winnow( elements, qualifier, keep ) {\n\n\t// Can't pass null or undefined to indexOf in Firefox 4\n\t// Set to 0 to skip string check\n\tqualifier = qualifier || 0;\n\n\tif ( jQuery.isFunction( qualifier ) ) {\n\t\treturn jQuery.grep(elements, function( elem, i ) {\n\t\t\tvar retVal = !!qualifier.call( elem, i, elem );\n\t\t\treturn retVal === keep;\n\t\t});\n\n\t} else if ( qualifier.nodeType ) {\n\t\treturn jQuery.grep(elements, function( elem ) {\n\t\t\treturn ( elem === qualifier ) === keep;\n\t\t});\n\n\t} else if ( typeof qualifier === \"string\" ) {\n\t\tvar filtered = jQuery.grep(elements, function( elem ) {\n\t\t\treturn elem.nodeType === 1;\n\t\t});\n\n\t\tif ( isSimple.test( qualifier ) ) {\n\t\t\treturn jQuery.filter(qualifier, filtered, !keep);\n\t\t} else {\n\t\t\tqualifier = jQuery.filter( qualifier, filtered );\n\t\t}\n\t}\n\n\treturn jQuery.grep(elements, function( elem ) {\n\t\treturn ( jQuery.inArray( elem, qualifier ) >= 0 ) === keep;\n\t});\n}\nfunction createSafeFragment( document ) {\n\tvar list = nodeNames.split( \"|\" ),\n\t\tsafeFrag = document.createDocumentFragment();\n\n\tif ( safeFrag.createElement ) {\n\t\twhile ( list.length ) {\n\t\t\tsafeFrag.createElement(\n\t\t\t\tlist.pop()\n\t\t\t);\n\t\t}\n\t}\n\treturn safeFrag;\n}\n\nvar nodeNames = \"abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|\" +\n\t\t\"header|hgroup|mark|meter|nav|output|progress|section|summary|time|video\",\n\trinlinejQuery = / jQuery\\d+=\"(?:null|\\d+)\"/g,\n\trnoshimcache = new RegExp(\"<(?:\" + nodeNames + \")[\\\\s/>]\", \"i\"),\n\trleadingWhitespace = /^\\s+/,\n\trxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\\w:]+)[^>]*)\\/>/gi,\n\trtagName = /<([\\w:]+)/,\n\trtbody = /<tbody/i,\n\trhtml = /<|&#?\\w+;/,\n\trnoInnerhtml = /<(?:script|style|link)/i,\n\tmanipulation_rcheckableType = /^(?:checkbox|radio)$/i,\n\t// checked=\"checked\" or checked\n\trchecked = /checked\\s*(?:[^=]|=\\s*.checked.)/i,\n\trscriptType = /^$|\\/(?:java|ecma)script/i,\n\trscriptTypeMasked = /^true\\/(.*)/,\n\trcleanScript = /^\\s*<!(?:\\[CDATA\\[|--)|(?:\\]\\]|--)>\\s*$/g,\n\n\t// We have to close these tags to support XHTML (#13200)\n\twrapMap = {\n\t\toption: [ 1, \"<select multiple='multiple'>\", \"</select>\" ],\n\t\tlegend: [ 1, \"<fieldset>\", \"</fieldset>\" ],\n\t\tarea: [ 1, \"<map>\", \"</map>\" ],\n\t\tparam: [ 1, \"<object>\", \"</object>\" ],\n\t\tthead: [ 1, \"<table>\", \"</table>\" ],\n\t\ttr: [ 2, \"<table><tbody>\", \"</tbody></table>\" ],\n\t\tcol: [ 2, \"<table><tbody></tbody><colgroup>\", \"</colgroup></table>\" ],\n\t\ttd: [ 3, \"<table><tbody><tr>\", \"</tr></tbody></table>\" ],\n\n\t\t// IE6-8 can't serialize link, script, style, or any html5 (NoScope) tags,\n\t\t// unless wrapped in a div with non-breaking characters in front of it.\n\t\t_default: jQuery.support.htmlSerialize ? [ 0, \"\", \"\" ] : [ 1, \"X<div>\", \"</div>\"  ]\n\t},\n\tsafeFragment = createSafeFragment( document ),\n\tfragmentDiv = safeFragment.appendChild( document.createElement(\"div\") );\n\nwrapMap.optgroup = wrapMap.option;\nwrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;\nwrapMap.th = wrapMap.td;\n\njQuery.fn.extend({\n\ttext: function( value ) {\n\t\treturn jQuery.access( this, function( value ) {\n\t\t\treturn value === undefined ?\n\t\t\t\tjQuery.text( this ) :\n\t\t\t\tthis.empty().append( ( this[0] && this[0].ownerDocument || document ).createTextNode( value ) );\n\t\t}, null, value, arguments.length );\n\t},\n\n\twrapAll: function( html ) {\n\t\tif ( jQuery.isFunction( html ) ) {\n\t\t\treturn this.each(function(i) {\n\t\t\t\tjQuery(this).wrapAll( html.call(this, i) );\n\t\t\t});\n\t\t}\n\n\t\tif ( this[0] ) {\n\t\t\t// The elements to wrap the target around\n\t\t\tvar wrap = jQuery( html, this[0].ownerDocument ).eq(0).clone(true);\n\n\t\t\tif ( this[0].parentNode ) {\n\t\t\t\twrap.insertBefore( this[0] );\n\t\t\t}\n\n\t\t\twrap.map(function() {\n\t\t\t\tvar elem = this;\n\n\t\t\t\twhile ( elem.firstChild && elem.firstChild.nodeType === 1 ) {\n\t\t\t\t\telem = elem.firstChild;\n\t\t\t\t}\n\n\t\t\t\treturn elem;\n\t\t\t}).append( this );\n\t\t}\n\n\t\treturn this;\n\t},\n\n\twrapInner: function( html ) {\n\t\tif ( jQuery.isFunction( html ) ) {\n\t\t\treturn this.each(function(i) {\n\t\t\t\tjQuery(this).wrapInner( html.call(this, i) );\n\t\t\t});\n\t\t}\n\n\t\treturn this.each(function() {\n\t\t\tvar self = jQuery( this ),\n\t\t\t\tcontents = self.contents();\n\n\t\t\tif ( contents.length ) {\n\t\t\t\tcontents.wrapAll( html );\n\n\t\t\t} else {\n\t\t\t\tself.append( html );\n\t\t\t}\n\t\t});\n\t},\n\n\twrap: function( html ) {\n\t\tvar isFunction = jQuery.isFunction( html );\n\n\t\treturn this.each(function(i) {\n\t\t\tjQuery( this ).wrapAll( isFunction ? html.call(this, i) : html );\n\t\t});\n\t},\n\n\tunwrap: function() {\n\t\treturn this.parent().each(function() {\n\t\t\tif ( !jQuery.nodeName( this, \"body\" ) ) {\n\t\t\t\tjQuery( this ).replaceWith( this.childNodes );\n\t\t\t}\n\t\t}).end();\n\t},\n\n\tappend: function() {\n\t\treturn this.domManip(arguments, true, function( elem ) {\n\t\t\tif ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {\n\t\t\t\tthis.appendChild( elem );\n\t\t\t}\n\t\t});\n\t},\n\n\tprepend: function() {\n\t\treturn this.domManip(arguments, true, function( elem ) {\n\t\t\tif ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {\n\t\t\t\tthis.insertBefore( elem, this.firstChild );\n\t\t\t}\n\t\t});\n\t},\n\n\tbefore: function() {\n\t\treturn this.domManip( arguments, false, function( elem ) {\n\t\t\tif ( this.parentNode ) {\n\t\t\t\tthis.parentNode.insertBefore( elem, this );\n\t\t\t}\n\t\t});\n\t},\n\n\tafter: function() {\n\t\treturn this.domManip( arguments, false, function( elem ) {\n\t\t\tif ( this.parentNode ) {\n\t\t\t\tthis.parentNode.insertBefore( elem, this.nextSibling );\n\t\t\t}\n\t\t});\n\t},\n\n\t// keepData is for internal use only--do not document\n\tremove: function( selector, keepData ) {\n\t\tvar elem,\n\t\t\ti = 0;\n\n\t\tfor ( ; (elem = this[i]) != null; i++ ) {\n\t\t\tif ( !selector || jQuery.filter( selector, [ elem ] ).length > 0 ) {\n\t\t\t\tif ( !keepData && elem.nodeType === 1 ) {\n\t\t\t\t\tjQuery.cleanData( getAll( elem ) );\n\t\t\t\t}\n\n\t\t\t\tif ( elem.parentNode ) {\n\t\t\t\t\tif ( keepData && jQuery.contains( elem.ownerDocument, elem ) ) {\n\t\t\t\t\t\tsetGlobalEval( getAll( elem, \"script\" ) );\n\t\t\t\t\t}\n\t\t\t\t\telem.parentNode.removeChild( elem );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\tempty: function() {\n\t\tvar elem,\n\t\t\ti = 0;\n\n\t\tfor ( ; (elem = this[i]) != null; i++ ) {\n\t\t\t// Remove element nodes and prevent memory leaks\n\t\t\tif ( elem.nodeType === 1 ) {\n\t\t\t\tjQuery.cleanData( getAll( elem, false ) );\n\t\t\t}\n\n\t\t\t// Remove any remaining nodes\n\t\t\twhile ( elem.firstChild ) {\n\t\t\t\telem.removeChild( elem.firstChild );\n\t\t\t}\n\n\t\t\t// If this is a select, ensure that it displays empty (#12336)\n\t\t\t// Support: IE<9\n\t\t\tif ( elem.options && jQuery.nodeName( elem, \"select\" ) ) {\n\t\t\t\telem.options.length = 0;\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\tclone: function( dataAndEvents, deepDataAndEvents ) {\n\t\tdataAndEvents = dataAndEvents == null ? false : dataAndEvents;\n\t\tdeepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents;\n\n\t\treturn this.map( function () {\n\t\t\treturn jQuery.clone( this, dataAndEvents, deepDataAndEvents );\n\t\t});\n\t},\n\n\thtml: function( value ) {\n\t\treturn jQuery.access( this, function( value ) {\n\t\t\tvar elem = this[0] || {},\n\t\t\t\ti = 0,\n\t\t\t\tl = this.length;\n\n\t\t\tif ( value === undefined ) {\n\t\t\t\treturn elem.nodeType === 1 ?\n\t\t\t\t\telem.innerHTML.replace( rinlinejQuery, \"\" ) :\n\t\t\t\t\tundefined;\n\t\t\t}\n\n\t\t\t// See if we can take a shortcut and just use innerHTML\n\t\t\tif ( typeof value === \"string\" && !rnoInnerhtml.test( value ) &&\n\t\t\t\t( jQuery.support.htmlSerialize || !rnoshimcache.test( value )  ) &&\n\t\t\t\t( jQuery.support.leadingWhitespace || !rleadingWhitespace.test( value ) ) &&\n\t\t\t\t!wrapMap[ ( rtagName.exec( value ) || [\"\", \"\"] )[1].toLowerCase() ] ) {\n\n\t\t\t\tvalue = value.replace( rxhtmlTag, \"<$1></$2>\" );\n\n\t\t\t\ttry {\n\t\t\t\t\tfor (; i < l; i++ ) {\n\t\t\t\t\t\t// Remove element nodes and prevent memory leaks\n\t\t\t\t\t\telem = this[i] || {};\n\t\t\t\t\t\tif ( elem.nodeType === 1 ) {\n\t\t\t\t\t\t\tjQuery.cleanData( getAll( elem, false ) );\n\t\t\t\t\t\t\telem.innerHTML = value;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\telem = 0;\n\n\t\t\t\t// If using innerHTML throws an exception, use the fallback method\n\t\t\t\t} catch(e) {}\n\t\t\t}\n\n\t\t\tif ( elem ) {\n\t\t\t\tthis.empty().append( value );\n\t\t\t}\n\t\t}, null, value, arguments.length );\n\t},\n\n\treplaceWith: function( value ) {\n\t\tvar isFunc = jQuery.isFunction( value );\n\n\t\t// Make sure that the elements are removed from the DOM before they are inserted\n\t\t// this can help fix replacing a parent with child elements\n\t\tif ( !isFunc && typeof value !== \"string\" ) {\n\t\t\tvalue = jQuery( value ).not( this ).detach();\n\t\t}\n\n\t\treturn this.domManip( [ value ], true, function( elem ) {\n\t\t\tvar next = this.nextSibling,\n\t\t\t\tparent = this.parentNode;\n\n\t\t\tif ( parent ) {\n\t\t\t\tjQuery( this ).remove();\n\t\t\t\tparent.insertBefore( elem, next );\n\t\t\t}\n\t\t});\n\t},\n\n\tdetach: function( selector ) {\n\t\treturn this.remove( selector, true );\n\t},\n\n\tdomManip: function( args, table, callback ) {\n\n\t\t// Flatten any nested arrays\n\t\targs = core_concat.apply( [], args );\n\n\t\tvar first, node, hasScripts,\n\t\t\tscripts, doc, fragment,\n\t\t\ti = 0,\n\t\t\tl = this.length,\n\t\t\tset = this,\n\t\t\tiNoClone = l - 1,\n\t\t\tvalue = args[0],\n\t\t\tisFunction = jQuery.isFunction( value );\n\n\t\t// We can't cloneNode fragments that contain checked, in WebKit\n\t\tif ( isFunction || !( l <= 1 || typeof value !== \"string\" || jQuery.support.checkClone || !rchecked.test( value ) ) ) {\n\t\t\treturn this.each(function( index ) {\n\t\t\t\tvar self = set.eq( index );\n\t\t\t\tif ( isFunction ) {\n\t\t\t\t\targs[0] = value.call( this, index, table ? self.html() : undefined );\n\t\t\t\t}\n\t\t\t\tself.domManip( args, table, callback );\n\t\t\t});\n\t\t}\n\n\t\tif ( l ) {\n\t\t\tfragment = jQuery.buildFragment( args, this[ 0 ].ownerDocument, false, this );\n\t\t\tfirst = fragment.firstChild;\n\n\t\t\tif ( fragment.childNodes.length === 1 ) {\n\t\t\t\tfragment = first;\n\t\t\t}\n\n\t\t\tif ( first ) {\n\t\t\t\ttable = table && jQuery.nodeName( first, \"tr\" );\n\t\t\t\tscripts = jQuery.map( getAll( fragment, \"script\" ), disableScript );\n\t\t\t\thasScripts = scripts.length;\n\n\t\t\t\t// Use the original fragment for the last item instead of the first because it can end up\n\t\t\t\t// being emptied incorrectly in certain situations (#8070).\n\t\t\t\tfor ( ; i < l; i++ ) {\n\t\t\t\t\tnode = fragment;\n\n\t\t\t\t\tif ( i !== iNoClone ) {\n\t\t\t\t\t\tnode = jQuery.clone( node, true, true );\n\n\t\t\t\t\t\t// Keep references to cloned scripts for later restoration\n\t\t\t\t\t\tif ( hasScripts ) {\n\t\t\t\t\t\t\tjQuery.merge( scripts, getAll( node, \"script\" ) );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tcallback.call(\n\t\t\t\t\t\ttable && jQuery.nodeName( this[i], \"table\" ) ?\n\t\t\t\t\t\t\tfindOrAppend( this[i], \"tbody\" ) :\n\t\t\t\t\t\t\tthis[i],\n\t\t\t\t\t\tnode,\n\t\t\t\t\t\ti\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\tif ( hasScripts ) {\n\t\t\t\t\tdoc = scripts[ scripts.length - 1 ].ownerDocument;\n\n\t\t\t\t\t// Reenable scripts\n\t\t\t\t\tjQuery.map( scripts, restoreScript );\n\n\t\t\t\t\t// Evaluate executable scripts on first document insertion\n\t\t\t\t\tfor ( i = 0; i < hasScripts; i++ ) {\n\t\t\t\t\t\tnode = scripts[ i ];\n\t\t\t\t\t\tif ( rscriptType.test( node.type || \"\" ) &&\n\t\t\t\t\t\t\t!jQuery._data( node, \"globalEval\" ) && jQuery.contains( doc, node ) ) {\n\n\t\t\t\t\t\t\tif ( node.src ) {\n\t\t\t\t\t\t\t\t// Hope ajax is available...\n\t\t\t\t\t\t\t\tjQuery.ajax({\n\t\t\t\t\t\t\t\t\turl: node.src,\n\t\t\t\t\t\t\t\t\ttype: \"GET\",\n\t\t\t\t\t\t\t\t\tdataType: \"script\",\n\t\t\t\t\t\t\t\t\tasync: false,\n\t\t\t\t\t\t\t\t\tglobal: false,\n\t\t\t\t\t\t\t\t\t\"throws\": true\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tjQuery.globalEval( ( node.text || node.textContent || node.innerHTML || \"\" ).replace( rcleanScript, \"\" ) );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Fix #11809: Avoid leaking memory\n\t\t\t\tfragment = first = null;\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t}\n});\n\nfunction findOrAppend( elem, tag ) {\n\treturn elem.getElementsByTagName( tag )[0] || elem.appendChild( elem.ownerDocument.createElement( tag ) );\n}\n\n// Replace/restore the type attribute of script elements for safe DOM manipulation\nfunction disableScript( elem ) {\n\tvar attr = elem.getAttributeNode(\"type\");\n\telem.type = ( attr && attr.specified ) + \"/\" + elem.type;\n\treturn elem;\n}\nfunction restoreScript( elem ) {\n\tvar match = rscriptTypeMasked.exec( elem.type );\n\tif ( match ) {\n\t\telem.type = match[1];\n\t} else {\n\t\telem.removeAttribute(\"type\");\n\t}\n\treturn elem;\n}\n\n// Mark scripts as having already been evaluated\nfunction setGlobalEval( elems, refElements ) {\n\tvar elem,\n\t\ti = 0;\n\tfor ( ; (elem = elems[i]) != null; i++ ) {\n\t\tjQuery._data( elem, \"globalEval\", !refElements || jQuery._data( refElements[i], \"globalEval\" ) );\n\t}\n}\n\nfunction cloneCopyEvent( src, dest ) {\n\n\tif ( dest.nodeType !== 1 || !jQuery.hasData( src ) ) {\n\t\treturn;\n\t}\n\n\tvar type, i, l,\n\t\toldData = jQuery._data( src ),\n\t\tcurData = jQuery._data( dest, oldData ),\n\t\tevents = oldData.events;\n\n\tif ( events ) {\n\t\tdelete curData.handle;\n\t\tcurData.events = {};\n\n\t\tfor ( type in events ) {\n\t\t\tfor ( i = 0, l = events[ type ].length; i < l; i++ ) {\n\t\t\t\tjQuery.event.add( dest, type, events[ type ][ i ] );\n\t\t\t}\n\t\t}\n\t}\n\n\t// make the cloned public data object a copy from the original\n\tif ( curData.data ) {\n\t\tcurData.data = jQuery.extend( {}, curData.data );\n\t}\n}\n\nfunction fixCloneNodeIssues( src, dest ) {\n\tvar nodeName, e, data;\n\n\t// We do not need to do anything for non-Elements\n\tif ( dest.nodeType !== 1 ) {\n\t\treturn;\n\t}\n\n\tnodeName = dest.nodeName.toLowerCase();\n\n\t// IE6-8 copies events bound via attachEvent when using cloneNode.\n\tif ( !jQuery.support.noCloneEvent && dest[ jQuery.expando ] ) {\n\t\tdata = jQuery._data( dest );\n\n\t\tfor ( e in data.events ) {\n\t\t\tjQuery.removeEvent( dest, e, data.handle );\n\t\t}\n\n\t\t// Event data gets referenced instead of copied if the expando gets copied too\n\t\tdest.removeAttribute( jQuery.expando );\n\t}\n\n\t// IE blanks contents when cloning scripts, and tries to evaluate newly-set text\n\tif ( nodeName === \"script\" && dest.text !== src.text ) {\n\t\tdisableScript( dest ).text = src.text;\n\t\trestoreScript( dest );\n\n\t// IE6-10 improperly clones children of object elements using classid.\n\t// IE10 throws NoModificationAllowedError if parent is null, #12132.\n\t} else if ( nodeName === \"object\" ) {\n\t\tif ( dest.parentNode ) {\n\t\t\tdest.outerHTML = src.outerHTML;\n\t\t}\n\n\t\t// This path appears unavoidable for IE9. When cloning an object\n\t\t// element in IE9, the outerHTML strategy above is not sufficient.\n\t\t// If the src has innerHTML and the destination does not,\n\t\t// copy the src.innerHTML into the dest.innerHTML. #10324\n\t\tif ( jQuery.support.html5Clone && ( src.innerHTML && !jQuery.trim(dest.innerHTML) ) ) {\n\t\t\tdest.innerHTML = src.innerHTML;\n\t\t}\n\n\t} else if ( nodeName === \"input\" && manipulation_rcheckableType.test( src.type ) ) {\n\t\t// IE6-8 fails to persist the checked state of a cloned checkbox\n\t\t// or radio button. Worse, IE6-7 fail to give the cloned element\n\t\t// a checked appearance if the defaultChecked value isn't also set\n\n\t\tdest.defaultChecked = dest.checked = src.checked;\n\n\t\t// IE6-7 get confused and end up setting the value of a cloned\n\t\t// checkbox/radio button to an empty string instead of \"on\"\n\t\tif ( dest.value !== src.value ) {\n\t\t\tdest.value = src.value;\n\t\t}\n\n\t// IE6-8 fails to return the selected option to the default selected\n\t// state when cloning options\n\t} else if ( nodeName === \"option\" ) {\n\t\tdest.defaultSelected = dest.selected = src.defaultSelected;\n\n\t// IE6-8 fails to set the defaultValue to the correct value when\n\t// cloning other types of input fields\n\t} else if ( nodeName === \"input\" || nodeName === \"textarea\" ) {\n\t\tdest.defaultValue = src.defaultValue;\n\t}\n}\n\njQuery.each({\n\tappendTo: \"append\",\n\tprependTo: \"prepend\",\n\tinsertBefore: \"before\",\n\tinsertAfter: \"after\",\n\treplaceAll: \"replaceWith\"\n}, function( name, original ) {\n\tjQuery.fn[ name ] = function( selector ) {\n\t\tvar elems,\n\t\t\ti = 0,\n\t\t\tret = [],\n\t\t\tinsert = jQuery( selector ),\n\t\t\tlast = insert.length - 1;\n\n\t\tfor ( ; i <= last; i++ ) {\n\t\t\telems = i === last ? this : this.clone(true);\n\t\t\tjQuery( insert[i] )[ original ]( elems );\n\n\t\t\t// Modern browsers can apply jQuery collections as arrays, but oldIE needs a .get()\n\t\t\tcore_push.apply( ret, elems.get() );\n\t\t}\n\n\t\treturn this.pushStack( ret );\n\t};\n});\n\nfunction getAll( context, tag ) {\n\tvar elems, elem,\n\t\ti = 0,\n\t\tfound = typeof context.getElementsByTagName !== core_strundefined ? context.getElementsByTagName( tag || \"*\" ) :\n\t\t\ttypeof context.querySelectorAll !== core_strundefined ? context.querySelectorAll( tag || \"*\" ) :\n\t\t\tundefined;\n\n\tif ( !found ) {\n\t\tfor ( found = [], elems = context.childNodes || context; (elem = elems[i]) != null; i++ ) {\n\t\t\tif ( !tag || jQuery.nodeName( elem, tag ) ) {\n\t\t\t\tfound.push( elem );\n\t\t\t} else {\n\t\t\t\tjQuery.merge( found, getAll( elem, tag ) );\n\t\t\t}\n\t\t}\n\t}\n\n\treturn tag === undefined || tag && jQuery.nodeName( context, tag ) ?\n\t\tjQuery.merge( [ context ], found ) :\n\t\tfound;\n}\n\n// Used in buildFragment, fixes the defaultChecked property\nfunction fixDefaultChecked( elem ) {\n\tif ( manipulation_rcheckableType.test( elem.type ) ) {\n\t\telem.defaultChecked = elem.checked;\n\t}\n}\n\njQuery.extend({\n\tclone: function( elem, dataAndEvents, deepDataAndEvents ) {\n\t\tvar destElements, node, clone, i, srcElements,\n\t\t\tinPage = jQuery.contains( elem.ownerDocument, elem );\n\n\t\tif ( jQuery.support.html5Clone || jQuery.isXMLDoc(elem) || !rnoshimcache.test( \"<\" + elem.nodeName + \">\" ) ) {\n\t\t\tclone = elem.cloneNode( true );\n\n\t\t// IE<=8 does not properly clone detached, unknown element nodes\n\t\t} else {\n\t\t\tfragmentDiv.innerHTML = elem.outerHTML;\n\t\t\tfragmentDiv.removeChild( clone = fragmentDiv.firstChild );\n\t\t}\n\n\t\tif ( (!jQuery.support.noCloneEvent || !jQuery.support.noCloneChecked) &&\n\t\t\t\t(elem.nodeType === 1 || elem.nodeType === 11) && !jQuery.isXMLDoc(elem) ) {\n\n\t\t\t// We eschew Sizzle here for performance reasons: http://jsperf.com/getall-vs-sizzle/2\n\t\t\tdestElements = getAll( clone );\n\t\t\tsrcElements = getAll( elem );\n\n\t\t\t// Fix all IE cloning issues\n\t\t\tfor ( i = 0; (node = srcElements[i]) != null; ++i ) {\n\t\t\t\t// Ensure that the destination node is not null; Fixes #9587\n\t\t\t\tif ( destElements[i] ) {\n\t\t\t\t\tfixCloneNodeIssues( node, destElements[i] );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Copy the events from the original to the clone\n\t\tif ( dataAndEvents ) {\n\t\t\tif ( deepDataAndEvents ) {\n\t\t\t\tsrcElements = srcElements || getAll( elem );\n\t\t\t\tdestElements = destElements || getAll( clone );\n\n\t\t\t\tfor ( i = 0; (node = srcElements[i]) != null; i++ ) {\n\t\t\t\t\tcloneCopyEvent( node, destElements[i] );\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tcloneCopyEvent( elem, clone );\n\t\t\t}\n\t\t}\n\n\t\t// Preserve script evaluation history\n\t\tdestElements = getAll( clone, \"script\" );\n\t\tif ( destElements.length > 0 ) {\n\t\t\tsetGlobalEval( destElements, !inPage && getAll( elem, \"script\" ) );\n\t\t}\n\n\t\tdestElements = srcElements = node = null;\n\n\t\t// Return the cloned set\n\t\treturn clone;\n\t},\n\n\tbuildFragment: function( elems, context, scripts, selection ) {\n\t\tvar j, elem, contains,\n\t\t\ttmp, tag, tbody, wrap,\n\t\t\tl = elems.length,\n\n\t\t\t// Ensure a safe fragment\n\t\t\tsafe = createSafeFragment( context ),\n\n\t\t\tnodes = [],\n\t\t\ti = 0;\n\n\t\tfor ( ; i < l; i++ ) {\n\t\t\telem = elems[ i ];\n\n\t\t\tif ( elem || elem === 0 ) {\n\n\t\t\t\t// Add nodes directly\n\t\t\t\tif ( jQuery.type( elem ) === \"object\" ) {\n\t\t\t\t\tjQuery.merge( nodes, elem.nodeType ? [ elem ] : elem );\n\n\t\t\t\t// Convert non-html into a text node\n\t\t\t\t} else if ( !rhtml.test( elem ) ) {\n\t\t\t\t\tnodes.push( context.createTextNode( elem ) );\n\n\t\t\t\t// Convert html into DOM nodes\n\t\t\t\t} else {\n\t\t\t\t\ttmp = tmp || safe.appendChild( context.createElement(\"div\") );\n\n\t\t\t\t\t// Deserialize a standard representation\n\t\t\t\t\ttag = ( rtagName.exec( elem ) || [\"\", \"\"] )[1].toLowerCase();\n\t\t\t\t\twrap = wrapMap[ tag ] || wrapMap._default;\n\n\t\t\t\t\ttmp.innerHTML = wrap[1] + elem.replace( rxhtmlTag, \"<$1></$2>\" ) + wrap[2];\n\n\t\t\t\t\t// Descend through wrappers to the right content\n\t\t\t\t\tj = wrap[0];\n\t\t\t\t\twhile ( j-- ) {\n\t\t\t\t\t\ttmp = tmp.lastChild;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Manually add leading whitespace removed by IE\n\t\t\t\t\tif ( !jQuery.support.leadingWhitespace && rleadingWhitespace.test( elem ) ) {\n\t\t\t\t\t\tnodes.push( context.createTextNode( rleadingWhitespace.exec( elem )[0] ) );\n\t\t\t\t\t}\n\n\t\t\t\t\t// Remove IE's autoinserted <tbody> from table fragments\n\t\t\t\t\tif ( !jQuery.support.tbody ) {\n\n\t\t\t\t\t\t// String was a <table>, *may* have spurious <tbody>\n\t\t\t\t\t\telem = tag === \"table\" && !rtbody.test( elem ) ?\n\t\t\t\t\t\t\ttmp.firstChild :\n\n\t\t\t\t\t\t\t// String was a bare <thead> or <tfoot>\n\t\t\t\t\t\t\twrap[1] === \"<table>\" && !rtbody.test( elem ) ?\n\t\t\t\t\t\t\t\ttmp :\n\t\t\t\t\t\t\t\t0;\n\n\t\t\t\t\t\tj = elem && elem.childNodes.length;\n\t\t\t\t\t\twhile ( j-- ) {\n\t\t\t\t\t\t\tif ( jQuery.nodeName( (tbody = elem.childNodes[j]), \"tbody\" ) && !tbody.childNodes.length ) {\n\t\t\t\t\t\t\t\telem.removeChild( tbody );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tjQuery.merge( nodes, tmp.childNodes );\n\n\t\t\t\t\t// Fix #12392 for WebKit and IE > 9\n\t\t\t\t\ttmp.textContent = \"\";\n\n\t\t\t\t\t// Fix #12392 for oldIE\n\t\t\t\t\twhile ( tmp.firstChild ) {\n\t\t\t\t\t\ttmp.removeChild( tmp.firstChild );\n\t\t\t\t\t}\n\n\t\t\t\t\t// Remember the top-level container for proper cleanup\n\t\t\t\t\ttmp = safe.lastChild;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Fix #11356: Clear elements from fragment\n\t\tif ( tmp ) {\n\t\t\tsafe.removeChild( tmp );\n\t\t}\n\n\t\t// Reset defaultChecked for any radios and checkboxes\n\t\t// about to be appended to the DOM in IE 6/7 (#8060)\n\t\tif ( !jQuery.support.appendChecked ) {\n\t\t\tjQuery.grep( getAll( nodes, \"input\" ), fixDefaultChecked );\n\t\t}\n\n\t\ti = 0;\n\t\twhile ( (elem = nodes[ i++ ]) ) {\n\n\t\t\t// #4087 - If origin and destination elements are the same, and this is\n\t\t\t// that element, do not do anything\n\t\t\tif ( selection && jQuery.inArray( elem, selection ) !== -1 ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tcontains = jQuery.contains( elem.ownerDocument, elem );\n\n\t\t\t// Append to fragment\n\t\t\ttmp = getAll( safe.appendChild( elem ), \"script\" );\n\n\t\t\t// Preserve script evaluation history\n\t\t\tif ( contains ) {\n\t\t\t\tsetGlobalEval( tmp );\n\t\t\t}\n\n\t\t\t// Capture executables\n\t\t\tif ( scripts ) {\n\t\t\t\tj = 0;\n\t\t\t\twhile ( (elem = tmp[ j++ ]) ) {\n\t\t\t\t\tif ( rscriptType.test( elem.type || \"\" ) ) {\n\t\t\t\t\t\tscripts.push( elem );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\ttmp = null;\n\n\t\treturn safe;\n\t},\n\n\tcleanData: function( elems, /* internal */ acceptData ) {\n\t\tvar elem, type, id, data,\n\t\t\ti = 0,\n\t\t\tinternalKey = jQuery.expando,\n\t\t\tcache = jQuery.cache,\n\t\t\tdeleteExpando = jQuery.support.deleteExpando,\n\t\t\tspecial = jQuery.event.special;\n\n\t\tfor ( ; (elem = elems[i]) != null; i++ ) {\n\n\t\t\tif ( acceptData || jQuery.acceptData( elem ) ) {\n\n\t\t\t\tid = elem[ internalKey ];\n\t\t\t\tdata = id && cache[ id ];\n\n\t\t\t\tif ( data ) {\n\t\t\t\t\tif ( data.events ) {\n\t\t\t\t\t\tfor ( type in data.events ) {\n\t\t\t\t\t\t\tif ( special[ type ] ) {\n\t\t\t\t\t\t\t\tjQuery.event.remove( elem, type );\n\n\t\t\t\t\t\t\t// This is a shortcut to avoid jQuery.event.remove's overhead\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tjQuery.removeEvent( elem, type, data.handle );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Remove cache only if it was not already removed by jQuery.event.remove\n\t\t\t\t\tif ( cache[ id ] ) {\n\n\t\t\t\t\t\tdelete cache[ id ];\n\n\t\t\t\t\t\t// IE does not allow us to delete expando properties from nodes,\n\t\t\t\t\t\t// nor does it have a removeAttribute function on Document nodes;\n\t\t\t\t\t\t// we must handle all of these cases\n\t\t\t\t\t\tif ( deleteExpando ) {\n\t\t\t\t\t\t\tdelete elem[ internalKey ];\n\n\t\t\t\t\t\t} else if ( typeof elem.removeAttribute !== core_strundefined ) {\n\t\t\t\t\t\t\telem.removeAttribute( internalKey );\n\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\telem[ internalKey ] = null;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tcore_deletedIds.push( id );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n});\nvar iframe, getStyles, curCSS,\n\tralpha = /alpha\\([^)]*\\)/i,\n\tropacity = /opacity\\s*=\\s*([^)]*)/,\n\trposition = /^(top|right|bottom|left)$/,\n\t// swappable if display is none or starts with table except \"table\", \"table-cell\", or \"table-caption\"\n\t// see here for display values: https://developer.mozilla.org/en-US/docs/CSS/display\n\trdisplayswap = /^(none|table(?!-c[ea]).+)/,\n\trmargin = /^margin/,\n\trnumsplit = new RegExp( \"^(\" + core_pnum + \")(.*)$\", \"i\" ),\n\trnumnonpx = new RegExp( \"^(\" + core_pnum + \")(?!px)[a-z%]+$\", \"i\" ),\n\trrelNum = new RegExp( \"^([+-])=(\" + core_pnum + \")\", \"i\" ),\n\telemdisplay = { BODY: \"block\" },\n\n\tcssShow = { position: \"absolute\", visibility: \"hidden\", display: \"block\" },\n\tcssNormalTransform = {\n\t\tletterSpacing: 0,\n\t\tfontWeight: 400\n\t},\n\n\tcssExpand = [ \"Top\", \"Right\", \"Bottom\", \"Left\" ],\n\tcssPrefixes = [ \"Webkit\", \"O\", \"Moz\", \"ms\" ];\n\n// return a css property mapped to a potentially vendor prefixed property\nfunction vendorPropName( style, name ) {\n\n\t// shortcut for names that are not vendor prefixed\n\tif ( name in style ) {\n\t\treturn name;\n\t}\n\n\t// check for vendor prefixed names\n\tvar capName = name.charAt(0).toUpperCase() + name.slice(1),\n\t\torigName = name,\n\t\ti = cssPrefixes.length;\n\n\twhile ( i-- ) {\n\t\tname = cssPrefixes[ i ] + capName;\n\t\tif ( name in style ) {\n\t\t\treturn name;\n\t\t}\n\t}\n\n\treturn origName;\n}\n\nfunction isHidden( elem, el ) {\n\t// isHidden might be called from jQuery#filter function;\n\t// in that case, element will be second argument\n\telem = el || elem;\n\treturn jQuery.css( elem, \"display\" ) === \"none\" || !jQuery.contains( elem.ownerDocument, elem );\n}\n\nfunction showHide( elements, show ) {\n\tvar display, elem, hidden,\n\t\tvalues = [],\n\t\tindex = 0,\n\t\tlength = elements.length;\n\n\tfor ( ; index < length; index++ ) {\n\t\telem = elements[ index ];\n\t\tif ( !elem.style ) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tvalues[ index ] = jQuery._data( elem, \"olddisplay\" );\n\t\tdisplay = elem.style.display;\n\t\tif ( show ) {\n\t\t\t// Reset the inline display of this element to learn if it is\n\t\t\t// being hidden by cascaded rules or not\n\t\t\tif ( !values[ index ] && display === \"none\" ) {\n\t\t\t\telem.style.display = \"\";\n\t\t\t}\n\n\t\t\t// Set elements which have been overridden with display: none\n\t\t\t// in a stylesheet to whatever the default browser style is\n\t\t\t// for such an element\n\t\t\tif ( elem.style.display === \"\" && isHidden( elem ) ) {\n\t\t\t\tvalues[ index ] = jQuery._data( elem, \"olddisplay\", css_defaultDisplay(elem.nodeName) );\n\t\t\t}\n\t\t} else {\n\n\t\t\tif ( !values[ index ] ) {\n\t\t\t\thidden = isHidden( elem );\n\n\t\t\t\tif ( display && display !== \"none\" || !hidden ) {\n\t\t\t\t\tjQuery._data( elem, \"olddisplay\", hidden ? display : jQuery.css( elem, \"display\" ) );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Set the display of most of the elements in a second loop\n\t// to avoid the constant reflow\n\tfor ( index = 0; index < length; index++ ) {\n\t\telem = elements[ index ];\n\t\tif ( !elem.style ) {\n\t\t\tcontinue;\n\t\t}\n\t\tif ( !show || elem.style.display === \"none\" || elem.style.display === \"\" ) {\n\t\t\telem.style.display = show ? values[ index ] || \"\" : \"none\";\n\t\t}\n\t}\n\n\treturn elements;\n}\n\njQuery.fn.extend({\n\tcss: function( name, value ) {\n\t\treturn jQuery.access( this, function( elem, name, value ) {\n\t\t\tvar len, styles,\n\t\t\t\tmap = {},\n\t\t\t\ti = 0;\n\n\t\t\tif ( jQuery.isArray( name ) ) {\n\t\t\t\tstyles = getStyles( elem );\n\t\t\t\tlen = name.length;\n\n\t\t\t\tfor ( ; i < len; i++ ) {\n\t\t\t\t\tmap[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles );\n\t\t\t\t}\n\n\t\t\t\treturn map;\n\t\t\t}\n\n\t\t\treturn value !== undefined ?\n\t\t\t\tjQuery.style( elem, name, value ) :\n\t\t\t\tjQuery.css( elem, name );\n\t\t}, name, value, arguments.length > 1 );\n\t},\n\tshow: function() {\n\t\treturn showHide( this, true );\n\t},\n\thide: function() {\n\t\treturn showHide( this );\n\t},\n\ttoggle: function( state ) {\n\t\tvar bool = typeof state === \"boolean\";\n\n\t\treturn this.each(function() {\n\t\t\tif ( bool ? state : isHidden( this ) ) {\n\t\t\t\tjQuery( this ).show();\n\t\t\t} else {\n\t\t\t\tjQuery( this ).hide();\n\t\t\t}\n\t\t});\n\t}\n});\n\njQuery.extend({\n\t// Add in style property hooks for overriding the default\n\t// behavior of getting and setting a style property\n\tcssHooks: {\n\t\topacity: {\n\t\t\tget: function( elem, computed ) {\n\t\t\t\tif ( computed ) {\n\t\t\t\t\t// We should always get a number back from opacity\n\t\t\t\t\tvar ret = curCSS( elem, \"opacity\" );\n\t\t\t\t\treturn ret === \"\" ? \"1\" : ret;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\n\t// Exclude the following css properties to add px\n\tcssNumber: {\n\t\t\"columnCount\": true,\n\t\t\"fillOpacity\": true,\n\t\t\"fontWeight\": true,\n\t\t\"lineHeight\": true,\n\t\t\"opacity\": true,\n\t\t\"orphans\": true,\n\t\t\"widows\": true,\n\t\t\"zIndex\": true,\n\t\t\"zoom\": true\n\t},\n\n\t// Add in properties whose names you wish to fix before\n\t// setting or getting the value\n\tcssProps: {\n\t\t// normalize float css property\n\t\t\"float\": jQuery.support.cssFloat ? \"cssFloat\" : \"styleFloat\"\n\t},\n\n\t// Get and set the style property on a DOM Node\n\tstyle: function( elem, name, value, extra ) {\n\t\t// Don't set styles on text and comment nodes\n\t\tif ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Make sure that we're working with the right name\n\t\tvar ret, type, hooks,\n\t\t\torigName = jQuery.camelCase( name ),\n\t\t\tstyle = elem.style;\n\n\t\tname = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( style, origName ) );\n\n\t\t// gets hook for the prefixed version\n\t\t// followed by the unprefixed version\n\t\thooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];\n\n\t\t// Check if we're setting a value\n\t\tif ( value !== undefined ) {\n\t\t\ttype = typeof value;\n\n\t\t\t// convert relative number strings (+= or -=) to relative numbers. #7345\n\t\t\tif ( type === \"string\" && (ret = rrelNum.exec( value )) ) {\n\t\t\t\tvalue = ( ret[1] + 1 ) * ret[2] + parseFloat( jQuery.css( elem, name ) );\n\t\t\t\t// Fixes bug #9237\n\t\t\t\ttype = \"number\";\n\t\t\t}\n\n\t\t\t// Make sure that NaN and null values aren't set. See: #7116\n\t\t\tif ( value == null || type === \"number\" && isNaN( value ) ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// If a number was passed in, add 'px' to the (except for certain CSS properties)\n\t\t\tif ( type === \"number\" && !jQuery.cssNumber[ origName ] ) {\n\t\t\t\tvalue += \"px\";\n\t\t\t}\n\n\t\t\t// Fixes #8908, it can be done more correctly by specifing setters in cssHooks,\n\t\t\t// but it would mean to define eight (for every problematic property) identical functions\n\t\t\tif ( !jQuery.support.clearCloneStyle && value === \"\" && name.indexOf(\"background\") === 0 ) {\n\t\t\t\tstyle[ name ] = \"inherit\";\n\t\t\t}\n\n\t\t\t// If a hook was provided, use that value, otherwise just set the specified value\n\t\t\tif ( !hooks || !(\"set\" in hooks) || (value = hooks.set( elem, value, extra )) !== undefined ) {\n\n\t\t\t\t// Wrapped to prevent IE from throwing errors when 'invalid' values are provided\n\t\t\t\t// Fixes bug #5509\n\t\t\t\ttry {\n\t\t\t\t\tstyle[ name ] = value;\n\t\t\t\t} catch(e) {}\n\t\t\t}\n\n\t\t} else {\n\t\t\t// If a hook was provided get the non-computed value from there\n\t\t\tif ( hooks && \"get\" in hooks && (ret = hooks.get( elem, false, extra )) !== undefined ) {\n\t\t\t\treturn ret;\n\t\t\t}\n\n\t\t\t// Otherwise just get the value from the style object\n\t\t\treturn style[ name ];\n\t\t}\n\t},\n\n\tcss: function( elem, name, extra, styles ) {\n\t\tvar num, val, hooks,\n\t\t\torigName = jQuery.camelCase( name );\n\n\t\t// Make sure that we're working with the right name\n\t\tname = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( elem.style, origName ) );\n\n\t\t// gets hook for the prefixed version\n\t\t// followed by the unprefixed version\n\t\thooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];\n\n\t\t// If a hook was provided get the computed value from there\n\t\tif ( hooks && \"get\" in hooks ) {\n\t\t\tval = hooks.get( elem, true, extra );\n\t\t}\n\n\t\t// Otherwise, if a way to get the computed value exists, use that\n\t\tif ( val === undefined ) {\n\t\t\tval = curCSS( elem, name, styles );\n\t\t}\n\n\t\t//convert \"normal\" to computed value\n\t\tif ( val === \"normal\" && name in cssNormalTransform ) {\n\t\t\tval = cssNormalTransform[ name ];\n\t\t}\n\n\t\t// Return, converting to number if forced or a qualifier was provided and val looks numeric\n\t\tif ( extra === \"\" || extra ) {\n\t\t\tnum = parseFloat( val );\n\t\t\treturn extra === true || jQuery.isNumeric( num ) ? num || 0 : val;\n\t\t}\n\t\treturn val;\n\t},\n\n\t// A method for quickly swapping in/out CSS properties to get correct calculations\n\tswap: function( elem, options, callback, args ) {\n\t\tvar ret, name,\n\t\t\told = {};\n\n\t\t// Remember the old values, and insert the new ones\n\t\tfor ( name in options ) {\n\t\t\told[ name ] = elem.style[ name ];\n\t\t\telem.style[ name ] = options[ name ];\n\t\t}\n\n\t\tret = callback.apply( elem, args || [] );\n\n\t\t// Revert the old values\n\t\tfor ( name in options ) {\n\t\t\telem.style[ name ] = old[ name ];\n\t\t}\n\n\t\treturn ret;\n\t}\n});\n\n// NOTE: we've included the \"window\" in window.getComputedStyle\n// because jsdom on node.js will break without it.\nif ( window.getComputedStyle ) {\n\tgetStyles = function( elem ) {\n\t\treturn window.getComputedStyle( elem, null );\n\t};\n\n\tcurCSS = function( elem, name, _computed ) {\n\t\tvar width, minWidth, maxWidth,\n\t\t\tcomputed = _computed || getStyles( elem ),\n\n\t\t\t// getPropertyValue is only needed for .css('filter') in IE9, see #12537\n\t\t\tret = computed ? computed.getPropertyValue( name ) || computed[ name ] : undefined,\n\t\t\tstyle = elem.style;\n\n\t\tif ( computed ) {\n\n\t\t\tif ( ret === \"\" && !jQuery.contains( elem.ownerDocument, elem ) ) {\n\t\t\t\tret = jQuery.style( elem, name );\n\t\t\t}\n\n\t\t\t// A tribute to the \"awesome hack by Dean Edwards\"\n\t\t\t// Chrome < 17 and Safari 5.0 uses \"computed value\" instead of \"used value\" for margin-right\n\t\t\t// Safari 5.1.7 (at least) returns percentage for a larger set of values, but width seems to be reliably pixels\n\t\t\t// this is against the CSSOM draft spec: http://dev.w3.org/csswg/cssom/#resolved-values\n\t\t\tif ( rnumnonpx.test( ret ) && rmargin.test( name ) ) {\n\n\t\t\t\t// Remember the original values\n\t\t\t\twidth = style.width;\n\t\t\t\tminWidth = style.minWidth;\n\t\t\t\tmaxWidth = style.maxWidth;\n\n\t\t\t\t// Put in the new values to get a computed value out\n\t\t\t\tstyle.minWidth = style.maxWidth = style.width = ret;\n\t\t\t\tret = computed.width;\n\n\t\t\t\t// Revert the changed values\n\t\t\t\tstyle.width = width;\n\t\t\t\tstyle.minWidth = minWidth;\n\t\t\t\tstyle.maxWidth = maxWidth;\n\t\t\t}\n\t\t}\n\n\t\treturn ret;\n\t};\n} else if ( document.documentElement.currentStyle ) {\n\tgetStyles = function( elem ) {\n\t\treturn elem.currentStyle;\n\t};\n\n\tcurCSS = function( elem, name, _computed ) {\n\t\tvar left, rs, rsLeft,\n\t\t\tcomputed = _computed || getStyles( elem ),\n\t\t\tret = computed ? computed[ name ] : undefined,\n\t\t\tstyle = elem.style;\n\n\t\t// Avoid setting ret to empty string here\n\t\t// so we don't default to auto\n\t\tif ( ret == null && style && style[ name ] ) {\n\t\t\tret = style[ name ];\n\t\t}\n\n\t\t// From the awesome hack by Dean Edwards\n\t\t// http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291\n\n\t\t// If we're not dealing with a regular pixel number\n\t\t// but a number that has a weird ending, we need to convert it to pixels\n\t\t// but not position css attributes, as those are proportional to the parent element instead\n\t\t// and we can't measure the parent instead because it might trigger a \"stacking dolls\" problem\n\t\tif ( rnumnonpx.test( ret ) && !rposition.test( name ) ) {\n\n\t\t\t// Remember the original values\n\t\t\tleft = style.left;\n\t\t\trs = elem.runtimeStyle;\n\t\t\trsLeft = rs && rs.left;\n\n\t\t\t// Put in the new values to get a computed value out\n\t\t\tif ( rsLeft ) {\n\t\t\t\trs.left = elem.currentStyle.left;\n\t\t\t}\n\t\t\tstyle.left = name === \"fontSize\" ? \"1em\" : ret;\n\t\t\tret = style.pixelLeft + \"px\";\n\n\t\t\t// Revert the changed values\n\t\t\tstyle.left = left;\n\t\t\tif ( rsLeft ) {\n\t\t\t\trs.left = rsLeft;\n\t\t\t}\n\t\t}\n\n\t\treturn ret === \"\" ? \"auto\" : ret;\n\t};\n}\n\nfunction setPositiveNumber( elem, value, subtract ) {\n\tvar matches = rnumsplit.exec( value );\n\treturn matches ?\n\t\t// Guard against undefined \"subtract\", e.g., when used as in cssHooks\n\t\tMath.max( 0, matches[ 1 ] - ( subtract || 0 ) ) + ( matches[ 2 ] || \"px\" ) :\n\t\tvalue;\n}\n\nfunction augmentWidthOrHeight( elem, name, extra, isBorderBox, styles ) {\n\tvar i = extra === ( isBorderBox ? \"border\" : \"content\" ) ?\n\t\t// If we already have the right measurement, avoid augmentation\n\t\t4 :\n\t\t// Otherwise initialize for horizontal or vertical properties\n\t\tname === \"width\" ? 1 : 0,\n\n\t\tval = 0;\n\n\tfor ( ; i < 4; i += 2 ) {\n\t\t// both box models exclude margin, so add it if we want it\n\t\tif ( extra === \"margin\" ) {\n\t\t\tval += jQuery.css( elem, extra + cssExpand[ i ], true, styles );\n\t\t}\n\n\t\tif ( isBorderBox ) {\n\t\t\t// border-box includes padding, so remove it if we want content\n\t\t\tif ( extra === \"content\" ) {\n\t\t\t\tval -= jQuery.css( elem, \"padding\" + cssExpand[ i ], true, styles );\n\t\t\t}\n\n\t\t\t// at this point, extra isn't border nor margin, so remove border\n\t\t\tif ( extra !== \"margin\" ) {\n\t\t\t\tval -= jQuery.css( elem, \"border\" + cssExpand[ i ] + \"Width\", true, styles );\n\t\t\t}\n\t\t} else {\n\t\t\t// at this point, extra isn't content, so add padding\n\t\t\tval += jQuery.css( elem, \"padding\" + cssExpand[ i ], true, styles );\n\n\t\t\t// at this point, extra isn't content nor padding, so add border\n\t\t\tif ( extra !== \"padding\" ) {\n\t\t\t\tval += jQuery.css( elem, \"border\" + cssExpand[ i ] + \"Width\", true, styles );\n\t\t\t}\n\t\t}\n\t}\n\n\treturn val;\n}\n\nfunction getWidthOrHeight( elem, name, extra ) {\n\n\t// Start with offset property, which is equivalent to the border-box value\n\tvar valueIsBorderBox = true,\n\t\tval = name === \"width\" ? elem.offsetWidth : elem.offsetHeight,\n\t\tstyles = getStyles( elem ),\n\t\tisBorderBox = jQuery.support.boxSizing && jQuery.css( elem, \"boxSizing\", false, styles ) === \"border-box\";\n\n\t// some non-html elements return undefined for offsetWidth, so check for null/undefined\n\t// svg - https://bugzilla.mozilla.org/show_bug.cgi?id=649285\n\t// MathML - https://bugzilla.mozilla.org/show_bug.cgi?id=491668\n\tif ( val <= 0 || val == null ) {\n\t\t// Fall back to computed then uncomputed css if necessary\n\t\tval = curCSS( elem, name, styles );\n\t\tif ( val < 0 || val == null ) {\n\t\t\tval = elem.style[ name ];\n\t\t}\n\n\t\t// Computed unit is not pixels. Stop here and return.\n\t\tif ( rnumnonpx.test(val) ) {\n\t\t\treturn val;\n\t\t}\n\n\t\t// we need the check for style in case a browser which returns unreliable values\n\t\t// for getComputedStyle silently falls back to the reliable elem.style\n\t\tvalueIsBorderBox = isBorderBox && ( jQuery.support.boxSizingReliable || val === elem.style[ name ] );\n\n\t\t// Normalize \"\", auto, and prepare for extra\n\t\tval = parseFloat( val ) || 0;\n\t}\n\n\t// use the active box-sizing model to add/subtract irrelevant styles\n\treturn ( val +\n\t\taugmentWidthOrHeight(\n\t\t\telem,\n\t\t\tname,\n\t\t\textra || ( isBorderBox ? \"border\" : \"content\" ),\n\t\t\tvalueIsBorderBox,\n\t\t\tstyles\n\t\t)\n\t) + \"px\";\n}\n\n// Try to determine the default display value of an element\nfunction css_defaultDisplay( nodeName ) {\n\tvar doc = document,\n\t\tdisplay = elemdisplay[ nodeName ];\n\n\tif ( !display ) {\n\t\tdisplay = actualDisplay( nodeName, doc );\n\n\t\t// If the simple way fails, read from inside an iframe\n\t\tif ( display === \"none\" || !display ) {\n\t\t\t// Use the already-created iframe if possible\n\t\t\tiframe = ( iframe ||\n\t\t\t\tjQuery(\"<iframe frameborder='0' width='0' height='0'/>\")\n\t\t\t\t.css( \"cssText\", \"display:block !important\" )\n\t\t\t).appendTo( doc.documentElement );\n\n\t\t\t// Always write a new HTML skeleton so Webkit and Firefox don't choke on reuse\n\t\t\tdoc = ( iframe[0].contentWindow || iframe[0].contentDocument ).document;\n\t\t\tdoc.write(\"<!doctype html><html><body>\");\n\t\t\tdoc.close();\n\n\t\t\tdisplay = actualDisplay( nodeName, doc );\n\t\t\tiframe.detach();\n\t\t}\n\n\t\t// Store the correct default display\n\t\telemdisplay[ nodeName ] = display;\n\t}\n\n\treturn display;\n}\n\n// Called ONLY from within css_defaultDisplay\nfunction actualDisplay( name, doc ) {\n\tvar elem = jQuery( doc.createElement( name ) ).appendTo( doc.body ),\n\t\tdisplay = jQuery.css( elem[0], \"display\" );\n\telem.remove();\n\treturn display;\n}\n\njQuery.each([ \"height\", \"width\" ], function( i, name ) {\n\tjQuery.cssHooks[ name ] = {\n\t\tget: function( elem, computed, extra ) {\n\t\t\tif ( computed ) {\n\t\t\t\t// certain elements can have dimension info if we invisibly show them\n\t\t\t\t// however, it must have a current display style that would benefit from this\n\t\t\t\treturn elem.offsetWidth === 0 && rdisplayswap.test( jQuery.css( elem, \"display\" ) ) ?\n\t\t\t\t\tjQuery.swap( elem, cssShow, function() {\n\t\t\t\t\t\treturn getWidthOrHeight( elem, name, extra );\n\t\t\t\t\t}) :\n\t\t\t\t\tgetWidthOrHeight( elem, name, extra );\n\t\t\t}\n\t\t},\n\n\t\tset: function( elem, value, extra ) {\n\t\t\tvar styles = extra && getStyles( elem );\n\t\t\treturn setPositiveNumber( elem, value, extra ?\n\t\t\t\taugmentWidthOrHeight(\n\t\t\t\t\telem,\n\t\t\t\t\tname,\n\t\t\t\t\textra,\n\t\t\t\t\tjQuery.support.boxSizing && jQuery.css( elem, \"boxSizing\", false, styles ) === \"border-box\",\n\t\t\t\t\tstyles\n\t\t\t\t) : 0\n\t\t\t);\n\t\t}\n\t};\n});\n\nif ( !jQuery.support.opacity ) {\n\tjQuery.cssHooks.opacity = {\n\t\tget: function( elem, computed ) {\n\t\t\t// IE uses filters for opacity\n\t\t\treturn ropacity.test( (computed && elem.currentStyle ? elem.currentStyle.filter : elem.style.filter) || \"\" ) ?\n\t\t\t\t( 0.01 * parseFloat( RegExp.$1 ) ) + \"\" :\n\t\t\t\tcomputed ? \"1\" : \"\";\n\t\t},\n\n\t\tset: function( elem, value ) {\n\t\t\tvar style = elem.style,\n\t\t\t\tcurrentStyle = elem.currentStyle,\n\t\t\t\topacity = jQuery.isNumeric( value ) ? \"alpha(opacity=\" + value * 100 + \")\" : \"\",\n\t\t\t\tfilter = currentStyle && currentStyle.filter || style.filter || \"\";\n\n\t\t\t// IE has trouble with opacity if it does not have layout\n\t\t\t// Force it by setting the zoom level\n\t\t\tstyle.zoom = 1;\n\n\t\t\t// if setting opacity to 1, and no other filters exist - attempt to remove filter attribute #6652\n\t\t\t// if value === \"\", then remove inline opacity #12685\n\t\t\tif ( ( value >= 1 || value === \"\" ) &&\n\t\t\t\t\tjQuery.trim( filter.replace( ralpha, \"\" ) ) === \"\" &&\n\t\t\t\t\tstyle.removeAttribute ) {\n\n\t\t\t\t// Setting style.filter to null, \"\" & \" \" still leave \"filter:\" in the cssText\n\t\t\t\t// if \"filter:\" is present at all, clearType is disabled, we want to avoid this\n\t\t\t\t// style.removeAttribute is IE Only, but so apparently is this code path...\n\t\t\t\tstyle.removeAttribute( \"filter\" );\n\n\t\t\t\t// if there is no filter style applied in a css rule or unset inline opacity, we are done\n\t\t\t\tif ( value === \"\" || currentStyle && !currentStyle.filter ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// otherwise, set new filter values\n\t\t\tstyle.filter = ralpha.test( filter ) ?\n\t\t\t\tfilter.replace( ralpha, opacity ) :\n\t\t\t\tfilter + \" \" + opacity;\n\t\t}\n\t};\n}\n\n// These hooks cannot be added until DOM ready because the support test\n// for it is not run until after DOM ready\njQuery(function() {\n\tif ( !jQuery.support.reliableMarginRight ) {\n\t\tjQuery.cssHooks.marginRight = {\n\t\t\tget: function( elem, computed ) {\n\t\t\t\tif ( computed ) {\n\t\t\t\t\t// WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right\n\t\t\t\t\t// Work around by temporarily setting element display to inline-block\n\t\t\t\t\treturn jQuery.swap( elem, { \"display\": \"inline-block\" },\n\t\t\t\t\t\tcurCSS, [ elem, \"marginRight\" ] );\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t}\n\n\t// Webkit bug: https://bugs.webkit.org/show_bug.cgi?id=29084\n\t// getComputedStyle returns percent when specified for top/left/bottom/right\n\t// rather than make the css module depend on the offset module, we just check for it here\n\tif ( !jQuery.support.pixelPosition && jQuery.fn.position ) {\n\t\tjQuery.each( [ \"top\", \"left\" ], function( i, prop ) {\n\t\t\tjQuery.cssHooks[ prop ] = {\n\t\t\t\tget: function( elem, computed ) {\n\t\t\t\t\tif ( computed ) {\n\t\t\t\t\t\tcomputed = curCSS( elem, prop );\n\t\t\t\t\t\t// if curCSS returns percentage, fallback to offset\n\t\t\t\t\t\treturn rnumnonpx.test( computed ) ?\n\t\t\t\t\t\t\tjQuery( elem ).position()[ prop ] + \"px\" :\n\t\t\t\t\t\t\tcomputed;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t};\n\t\t});\n\t}\n\n});\n\nif ( jQuery.expr && jQuery.expr.filters ) {\n\tjQuery.expr.filters.hidden = function( elem ) {\n\t\t// Support: Opera <= 12.12\n\t\t// Opera reports offsetWidths and offsetHeights less than zero on some elements\n\t\treturn elem.offsetWidth <= 0 && elem.offsetHeight <= 0 ||\n\t\t\t(!jQuery.support.reliableHiddenOffsets && ((elem.style && elem.style.display) || jQuery.css( elem, \"display\" )) === \"none\");\n\t};\n\n\tjQuery.expr.filters.visible = function( elem ) {\n\t\treturn !jQuery.expr.filters.hidden( elem );\n\t};\n}\n\n// These hooks are used by animate to expand properties\njQuery.each({\n\tmargin: \"\",\n\tpadding: \"\",\n\tborder: \"Width\"\n}, function( prefix, suffix ) {\n\tjQuery.cssHooks[ prefix + suffix ] = {\n\t\texpand: function( value ) {\n\t\t\tvar i = 0,\n\t\t\t\texpanded = {},\n\n\t\t\t\t// assumes a single number if not a string\n\t\t\t\tparts = typeof value === \"string\" ? value.split(\" \") : [ value ];\n\n\t\t\tfor ( ; i < 4; i++ ) {\n\t\t\t\texpanded[ prefix + cssExpand[ i ] + suffix ] =\n\t\t\t\t\tparts[ i ] || parts[ i - 2 ] || parts[ 0 ];\n\t\t\t}\n\n\t\t\treturn expanded;\n\t\t}\n\t};\n\n\tif ( !rmargin.test( prefix ) ) {\n\t\tjQuery.cssHooks[ prefix + suffix ].set = setPositiveNumber;\n\t}\n});\nvar r20 = /%20/g,\n\trbracket = /\\[\\]$/,\n\trCRLF = /\\r?\\n/g,\n\trsubmitterTypes = /^(?:submit|button|image|reset|file)$/i,\n\trsubmittable = /^(?:input|select|textarea|keygen)/i;\n\njQuery.fn.extend({\n\tserialize: function() {\n\t\treturn jQuery.param( this.serializeArray() );\n\t},\n\tserializeArray: function() {\n\t\treturn this.map(function(){\n\t\t\t// Can add propHook for \"elements\" to filter or add form elements\n\t\t\tvar elements = jQuery.prop( this, \"elements\" );\n\t\t\treturn elements ? jQuery.makeArray( elements ) : this;\n\t\t})\n\t\t.filter(function(){\n\t\t\tvar type = this.type;\n\t\t\t// Use .is(\":disabled\") so that fieldset[disabled] works\n\t\t\treturn this.name && !jQuery( this ).is( \":disabled\" ) &&\n\t\t\t\trsubmittable.test( this.nodeName ) && !rsubmitterTypes.test( type ) &&\n\t\t\t\t( this.checked || !manipulation_rcheckableType.test( type ) );\n\t\t})\n\t\t.map(function( i, elem ){\n\t\t\tvar val = jQuery( this ).val();\n\n\t\t\treturn val == null ?\n\t\t\t\tnull :\n\t\t\t\tjQuery.isArray( val ) ?\n\t\t\t\t\tjQuery.map( val, function( val ){\n\t\t\t\t\t\treturn { name: elem.name, value: val.replace( rCRLF, \"\\r\\n\" ) };\n\t\t\t\t\t}) :\n\t\t\t\t\t{ name: elem.name, value: val.replace( rCRLF, \"\\r\\n\" ) };\n\t\t}).get();\n\t}\n});\n\n//Serialize an array of form elements or a set of\n//key/values into a query string\njQuery.param = function( a, traditional ) {\n\tvar prefix,\n\t\ts = [],\n\t\tadd = function( key, value ) {\n\t\t\t// If value is a function, invoke it and return its value\n\t\t\tvalue = jQuery.isFunction( value ) ? value() : ( value == null ? \"\" : value );\n\t\t\ts[ s.length ] = encodeURIComponent( key ) + \"=\" + encodeURIComponent( value );\n\t\t};\n\n\t// Set traditional to true for jQuery <= 1.3.2 behavior.\n\tif ( traditional === undefined ) {\n\t\ttraditional = jQuery.ajaxSettings && jQuery.ajaxSettings.traditional;\n\t}\n\n\t// If an array was passed in, assume that it is an array of form elements.\n\tif ( jQuery.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) {\n\t\t// Serialize the form elements\n\t\tjQuery.each( a, function() {\n\t\t\tadd( this.name, this.value );\n\t\t});\n\n\t} else {\n\t\t// If traditional, encode the \"old\" way (the way 1.3.2 or older\n\t\t// did it), otherwise encode params recursively.\n\t\tfor ( prefix in a ) {\n\t\t\tbuildParams( prefix, a[ prefix ], traditional, add );\n\t\t}\n\t}\n\n\t// Return the resulting serialization\n\treturn s.join( \"&\" ).replace( r20, \"+\" );\n};\n\nfunction buildParams( prefix, obj, traditional, add ) {\n\tvar name;\n\n\tif ( jQuery.isArray( obj ) ) {\n\t\t// Serialize array item.\n\t\tjQuery.each( obj, function( i, v ) {\n\t\t\tif ( traditional || rbracket.test( prefix ) ) {\n\t\t\t\t// Treat each array item as a scalar.\n\t\t\t\tadd( prefix, v );\n\n\t\t\t} else {\n\t\t\t\t// Item is non-scalar (array or object), encode its numeric index.\n\t\t\t\tbuildParams( prefix + \"[\" + ( typeof v === \"object\" ? i : \"\" ) + \"]\", v, traditional, add );\n\t\t\t}\n\t\t});\n\n\t} else if ( !traditional && jQuery.type( obj ) === \"object\" ) {\n\t\t// Serialize object item.\n\t\tfor ( name in obj ) {\n\t\t\tbuildParams( prefix + \"[\" + name + \"]\", obj[ name ], traditional, add );\n\t\t}\n\n\t} else {\n\t\t// Serialize scalar item.\n\t\tadd( prefix, obj );\n\t}\n}\njQuery.each( (\"blur focus focusin focusout load resize scroll unload click dblclick \" +\n\t\"mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave \" +\n\t\"change select submit keydown keypress keyup error contextmenu\").split(\" \"), function( i, name ) {\n\n\t// Handle event binding\n\tjQuery.fn[ name ] = function( data, fn ) {\n\t\treturn arguments.length > 0 ?\n\t\t\tthis.on( name, null, data, fn ) :\n\t\t\tthis.trigger( name );\n\t};\n});\n\njQuery.fn.hover = function( fnOver, fnOut ) {\n\treturn this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );\n};\nvar\n\t// Document location\n\tajaxLocParts,\n\tajaxLocation,\n\tajax_nonce = jQuery.now(),\n\n\tajax_rquery = /\\?/,\n\trhash = /#.*$/,\n\trts = /([?&])_=[^&]*/,\n\trheaders = /^(.*?):[ \\t]*([^\\r\\n]*)\\r?$/mg, // IE leaves an \\r character at EOL\n\t// #7653, #8125, #8152: local protocol detection\n\trlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/,\n\trnoContent = /^(?:GET|HEAD)$/,\n\trprotocol = /^\\/\\//,\n\trurl = /^([\\w.+-]+:)(?:\\/\\/([^\\/?#:]*)(?::(\\d+)|)|)/,\n\n\t// Keep a copy of the old load method\n\t_load = jQuery.fn.load,\n\n\t/* Prefilters\n\t * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example)\n\t * 2) These are called:\n\t *    - BEFORE asking for a transport\n\t *    - AFTER param serialization (s.data is a string if s.processData is true)\n\t * 3) key is the dataType\n\t * 4) the catchall symbol \"*\" can be used\n\t * 5) execution will start with transport dataType and THEN continue down to \"*\" if needed\n\t */\n\tprefilters = {},\n\n\t/* Transports bindings\n\t * 1) key is the dataType\n\t * 2) the catchall symbol \"*\" can be used\n\t * 3) selection will start with transport dataType and THEN go to \"*\" if needed\n\t */\n\ttransports = {},\n\n\t// Avoid comment-prolog char sequence (#10098); must appease lint and evade compression\n\tallTypes = \"*/\".concat(\"*\");\n\n// #8138, IE may throw an exception when accessing\n// a field from window.location if document.domain has been set\ntry {\n\tajaxLocation = location.href;\n} catch( e ) {\n\t// Use the href attribute of an A element\n\t// since IE will modify it given document.location\n\tajaxLocation = document.createElement( \"a\" );\n\tajaxLocation.href = \"\";\n\tajaxLocation = ajaxLocation.href;\n}\n\n// Segment location into parts\najaxLocParts = rurl.exec( ajaxLocation.toLowerCase() ) || [];\n\n// Base \"constructor\" for jQuery.ajaxPrefilter and jQuery.ajaxTransport\nfunction addToPrefiltersOrTransports( structure ) {\n\n\t// dataTypeExpression is optional and defaults to \"*\"\n\treturn function( dataTypeExpression, func ) {\n\n\t\tif ( typeof dataTypeExpression !== \"string\" ) {\n\t\t\tfunc = dataTypeExpression;\n\t\t\tdataTypeExpression = \"*\";\n\t\t}\n\n\t\tvar dataType,\n\t\t\ti = 0,\n\t\t\tdataTypes = dataTypeExpression.toLowerCase().match( core_rnotwhite ) || [];\n\n\t\tif ( jQuery.isFunction( func ) ) {\n\t\t\t// For each dataType in the dataTypeExpression\n\t\t\twhile ( (dataType = dataTypes[i++]) ) {\n\t\t\t\t// Prepend if requested\n\t\t\t\tif ( dataType[0] === \"+\" ) {\n\t\t\t\t\tdataType = dataType.slice( 1 ) || \"*\";\n\t\t\t\t\t(structure[ dataType ] = structure[ dataType ] || []).unshift( func );\n\n\t\t\t\t// Otherwise append\n\t\t\t\t} else {\n\t\t\t\t\t(structure[ dataType ] = structure[ dataType ] || []).push( func );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t};\n}\n\n// Base inspection function for prefilters and transports\nfunction inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR ) {\n\n\tvar inspected = {},\n\t\tseekingTransport = ( structure === transports );\n\n\tfunction inspect( dataType ) {\n\t\tvar selected;\n\t\tinspected[ dataType ] = true;\n\t\tjQuery.each( structure[ dataType ] || [], function( _, prefilterOrFactory ) {\n\t\t\tvar dataTypeOrTransport = prefilterOrFactory( options, originalOptions, jqXHR );\n\t\t\tif( typeof dataTypeOrTransport === \"string\" && !seekingTransport && !inspected[ dataTypeOrTransport ] ) {\n\t\t\t\toptions.dataTypes.unshift( dataTypeOrTransport );\n\t\t\t\tinspect( dataTypeOrTransport );\n\t\t\t\treturn false;\n\t\t\t} else if ( seekingTransport ) {\n\t\t\t\treturn !( selected = dataTypeOrTransport );\n\t\t\t}\n\t\t});\n\t\treturn selected;\n\t}\n\n\treturn inspect( options.dataTypes[ 0 ] ) || !inspected[ \"*\" ] && inspect( \"*\" );\n}\n\n// A special extend for ajax options\n// that takes \"flat\" options (not to be deep extended)\n// Fixes #9887\nfunction ajaxExtend( target, src ) {\n\tvar deep, key,\n\t\tflatOptions = jQuery.ajaxSettings.flatOptions || {};\n\n\tfor ( key in src ) {\n\t\tif ( src[ key ] !== undefined ) {\n\t\t\t( flatOptions[ key ] ? target : ( deep || (deep = {}) ) )[ key ] = src[ key ];\n\t\t}\n\t}\n\tif ( deep ) {\n\t\tjQuery.extend( true, target, deep );\n\t}\n\n\treturn target;\n}\n\njQuery.fn.load = function( url, params, callback ) {\n\tif ( typeof url !== \"string\" && _load ) {\n\t\treturn _load.apply( this, arguments );\n\t}\n\n\tvar selector, response, type,\n\t\tself = this,\n\t\toff = url.indexOf(\" \");\n\n\tif ( off >= 0 ) {\n\t\tselector = url.slice( off, url.length );\n\t\turl = url.slice( 0, off );\n\t}\n\n\t// If it's a function\n\tif ( jQuery.isFunction( params ) ) {\n\n\t\t// We assume that it's the callback\n\t\tcallback = params;\n\t\tparams = undefined;\n\n\t// Otherwise, build a param string\n\t} else if ( params && typeof params === \"object\" ) {\n\t\ttype = \"POST\";\n\t}\n\n\t// If we have elements to modify, make the request\n\tif ( self.length > 0 ) {\n\t\tjQuery.ajax({\n\t\t\turl: url,\n\n\t\t\t// if \"type\" variable is undefined, then \"GET\" method will be used\n\t\t\ttype: type,\n\t\t\tdataType: \"html\",\n\t\t\tdata: params\n\t\t}).done(function( responseText ) {\n\n\t\t\t// Save response for use in complete callback\n\t\t\tresponse = arguments;\n\n\t\t\tself.html( selector ?\n\n\t\t\t\t// If a selector was specified, locate the right elements in a dummy div\n\t\t\t\t// Exclude scripts to avoid IE 'Permission Denied' errors\n\t\t\t\tjQuery(\"<div>\").append( jQuery.parseHTML( responseText ) ).find( selector ) :\n\n\t\t\t\t// Otherwise use the full result\n\t\t\t\tresponseText );\n\n\t\t}).complete( callback && function( jqXHR, status ) {\n\t\t\tself.each( callback, response || [ jqXHR.responseText, status, jqXHR ] );\n\t\t});\n\t}\n\n\treturn this;\n};\n\n// Attach a bunch of functions for handling common AJAX events\njQuery.each( [ \"ajaxStart\", \"ajaxStop\", \"ajaxComplete\", \"ajaxError\", \"ajaxSuccess\", \"ajaxSend\" ], function( i, type ){\n\tjQuery.fn[ type ] = function( fn ){\n\t\treturn this.on( type, fn );\n\t};\n});\n\njQuery.each( [ \"get\", \"post\" ], function( i, method ) {\n\tjQuery[ method ] = function( url, data, callback, type ) {\n\t\t// shift arguments if data argument was omitted\n\t\tif ( jQuery.isFunction( data ) ) {\n\t\t\ttype = type || callback;\n\t\t\tcallback = data;\n\t\t\tdata = undefined;\n\t\t}\n\n\t\treturn jQuery.ajax({\n\t\t\turl: url,\n\t\t\ttype: method,\n\t\t\tdataType: type,\n\t\t\tdata: data,\n\t\t\tsuccess: callback\n\t\t});\n\t};\n});\n\njQuery.extend({\n\n\t// Counter for holding the number of active queries\n\tactive: 0,\n\n\t// Last-Modified header cache for next request\n\tlastModified: {},\n\tetag: {},\n\n\tajaxSettings: {\n\t\turl: ajaxLocation,\n\t\ttype: \"GET\",\n\t\tisLocal: rlocalProtocol.test( ajaxLocParts[ 1 ] ),\n\t\tglobal: true,\n\t\tprocessData: true,\n\t\tasync: true,\n\t\tcontentType: \"application/x-www-form-urlencoded; charset=UTF-8\",\n\t\t/*\n\t\ttimeout: 0,\n\t\tdata: null,\n\t\tdataType: null,\n\t\tusername: null,\n\t\tpassword: null,\n\t\tcache: null,\n\t\tthrows: false,\n\t\ttraditional: false,\n\t\theaders: {},\n\t\t*/\n\n\t\taccepts: {\n\t\t\t\"*\": allTypes,\n\t\t\ttext: \"text/plain\",\n\t\t\thtml: \"text/html\",\n\t\t\txml: \"application/xml, text/xml\",\n\t\t\tjson: \"application/json, text/javascript\"\n\t\t},\n\n\t\tcontents: {\n\t\t\txml: /xml/,\n\t\t\thtml: /html/,\n\t\t\tjson: /json/\n\t\t},\n\n\t\tresponseFields: {\n\t\t\txml: \"responseXML\",\n\t\t\ttext: \"responseText\"\n\t\t},\n\n\t\t// Data converters\n\t\t// Keys separate source (or catchall \"*\") and destination types with a single space\n\t\tconverters: {\n\n\t\t\t// Convert anything to text\n\t\t\t\"* text\": window.String,\n\n\t\t\t// Text to html (true = no transformation)\n\t\t\t\"text html\": true,\n\n\t\t\t// Evaluate text as a json expression\n\t\t\t\"text json\": jQuery.parseJSON,\n\n\t\t\t// Parse text as xml\n\t\t\t\"text xml\": jQuery.parseXML\n\t\t},\n\n\t\t// For options that shouldn't be deep extended:\n\t\t// you can add your own custom options here if\n\t\t// and when you create one that shouldn't be\n\t\t// deep extended (see ajaxExtend)\n\t\tflatOptions: {\n\t\t\turl: true,\n\t\t\tcontext: true\n\t\t}\n\t},\n\n\t// Creates a full fledged settings object into target\n\t// with both ajaxSettings and settings fields.\n\t// If target is omitted, writes into ajaxSettings.\n\tajaxSetup: function( target, settings ) {\n\t\treturn settings ?\n\n\t\t\t// Building a settings object\n\t\t\tajaxExtend( ajaxExtend( target, jQuery.ajaxSettings ), settings ) :\n\n\t\t\t// Extending ajaxSettings\n\t\t\tajaxExtend( jQuery.ajaxSettings, target );\n\t},\n\n\tajaxPrefilter: addToPrefiltersOrTransports( prefilters ),\n\tajaxTransport: addToPrefiltersOrTransports( transports ),\n\n\t// Main method\n\tajax: function( url, options ) {\n\n\t\t// If url is an object, simulate pre-1.5 signature\n\t\tif ( typeof url === \"object\" ) {\n\t\t\toptions = url;\n\t\t\turl = undefined;\n\t\t}\n\n\t\t// Force options to be an object\n\t\toptions = options || {};\n\n\t\tvar // Cross-domain detection vars\n\t\t\tparts,\n\t\t\t// Loop variable\n\t\t\ti,\n\t\t\t// URL without anti-cache param\n\t\t\tcacheURL,\n\t\t\t// Response headers as string\n\t\t\tresponseHeadersString,\n\t\t\t// timeout handle\n\t\t\ttimeoutTimer,\n\n\t\t\t// To know if global events are to be dispatched\n\t\t\tfireGlobals,\n\n\t\t\ttransport,\n\t\t\t// Response headers\n\t\t\tresponseHeaders,\n\t\t\t// Create the final options object\n\t\t\ts = jQuery.ajaxSetup( {}, options ),\n\t\t\t// Callbacks context\n\t\t\tcallbackContext = s.context || s,\n\t\t\t// Context for global events is callbackContext if it is a DOM node or jQuery collection\n\t\t\tglobalEventContext = s.context && ( callbackContext.nodeType || callbackContext.jquery ) ?\n\t\t\t\tjQuery( callbackContext ) :\n\t\t\t\tjQuery.event,\n\t\t\t// Deferreds\n\t\t\tdeferred = jQuery.Deferred(),\n\t\t\tcompleteDeferred = jQuery.Callbacks(\"once memory\"),\n\t\t\t// Status-dependent callbacks\n\t\t\tstatusCode = s.statusCode || {},\n\t\t\t// Headers (they are sent all at once)\n\t\t\trequestHeaders = {},\n\t\t\trequestHeadersNames = {},\n\t\t\t// The jqXHR state\n\t\t\tstate = 0,\n\t\t\t// Default abort message\n\t\t\tstrAbort = \"canceled\",\n\t\t\t// Fake xhr\n\t\t\tjqXHR = {\n\t\t\t\treadyState: 0,\n\n\t\t\t\t// Builds headers hashtable if needed\n\t\t\t\tgetResponseHeader: function( key ) {\n\t\t\t\t\tvar match;\n\t\t\t\t\tif ( state === 2 ) {\n\t\t\t\t\t\tif ( !responseHeaders ) {\n\t\t\t\t\t\t\tresponseHeaders = {};\n\t\t\t\t\t\t\twhile ( (match = rheaders.exec( responseHeadersString )) ) {\n\t\t\t\t\t\t\t\tresponseHeaders[ match[1].toLowerCase() ] = match[ 2 ];\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tmatch = responseHeaders[ key.toLowerCase() ];\n\t\t\t\t\t}\n\t\t\t\t\treturn match == null ? null : match;\n\t\t\t\t},\n\n\t\t\t\t// Raw string\n\t\t\t\tgetAllResponseHeaders: function() {\n\t\t\t\t\treturn state === 2 ? responseHeadersString : null;\n\t\t\t\t},\n\n\t\t\t\t// Caches the header\n\t\t\t\tsetRequestHeader: function( name, value ) {\n\t\t\t\t\tvar lname = name.toLowerCase();\n\t\t\t\t\tif ( !state ) {\n\t\t\t\t\t\tname = requestHeadersNames[ lname ] = requestHeadersNames[ lname ] || name;\n\t\t\t\t\t\trequestHeaders[ name ] = value;\n\t\t\t\t\t}\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\n\t\t\t\t// Overrides response content-type header\n\t\t\t\toverrideMimeType: function( type ) {\n\t\t\t\t\tif ( !state ) {\n\t\t\t\t\t\ts.mimeType = type;\n\t\t\t\t\t}\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\n\t\t\t\t// Status-dependent callbacks\n\t\t\t\tstatusCode: function( map ) {\n\t\t\t\t\tvar code;\n\t\t\t\t\tif ( map ) {\n\t\t\t\t\t\tif ( state < 2 ) {\n\t\t\t\t\t\t\tfor ( code in map ) {\n\t\t\t\t\t\t\t\t// Lazy-add the new callback in a way that preserves old ones\n\t\t\t\t\t\t\t\tstatusCode[ code ] = [ statusCode[ code ], map[ code ] ];\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t// Execute the appropriate callbacks\n\t\t\t\t\t\t\tjqXHR.always( map[ jqXHR.status ] );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\n\t\t\t\t// Cancel the request\n\t\t\t\tabort: function( statusText ) {\n\t\t\t\t\tvar finalText = statusText || strAbort;\n\t\t\t\t\tif ( transport ) {\n\t\t\t\t\t\ttransport.abort( finalText );\n\t\t\t\t\t}\n\t\t\t\t\tdone( 0, finalText );\n\t\t\t\t\treturn this;\n\t\t\t\t}\n\t\t\t};\n\n\t\t// Attach deferreds\n\t\tdeferred.promise( jqXHR ).complete = completeDeferred.add;\n\t\tjqXHR.success = jqXHR.done;\n\t\tjqXHR.error = jqXHR.fail;\n\n\t\t// Remove hash character (#7531: and string promotion)\n\t\t// Add protocol if not provided (#5866: IE7 issue with protocol-less urls)\n\t\t// Handle falsy url in the settings object (#10093: consistency with old signature)\n\t\t// We also use the url parameter if available\n\t\ts.url = ( ( url || s.url || ajaxLocation ) + \"\" ).replace( rhash, \"\" ).replace( rprotocol, ajaxLocParts[ 1 ] + \"//\" );\n\n\t\t// Alias method option to type as per ticket #12004\n\t\ts.type = options.method || options.type || s.method || s.type;\n\n\t\t// Extract dataTypes list\n\t\ts.dataTypes = jQuery.trim( s.dataType || \"*\" ).toLowerCase().match( core_rnotwhite ) || [\"\"];\n\n\t\t// A cross-domain request is in order when we have a protocol:host:port mismatch\n\t\tif ( s.crossDomain == null ) {\n\t\t\tparts = rurl.exec( s.url.toLowerCase() );\n\t\t\ts.crossDomain = !!( parts &&\n\t\t\t\t( parts[ 1 ] !== ajaxLocParts[ 1 ] || parts[ 2 ] !== ajaxLocParts[ 2 ] ||\n\t\t\t\t\t( parts[ 3 ] || ( parts[ 1 ] === \"http:\" ? 80 : 443 ) ) !=\n\t\t\t\t\t\t( ajaxLocParts[ 3 ] || ( ajaxLocParts[ 1 ] === \"http:\" ? 80 : 443 ) ) )\n\t\t\t);\n\t\t}\n\n\t\t// Convert data if not already a string\n\t\tif ( s.data && s.processData && typeof s.data !== \"string\" ) {\n\t\t\ts.data = jQuery.param( s.data, s.traditional );\n\t\t}\n\n\t\t// Apply prefilters\n\t\tinspectPrefiltersOrTransports( prefilters, s, options, jqXHR );\n\n\t\t// If request was aborted inside a prefilter, stop there\n\t\tif ( state === 2 ) {\n\t\t\treturn jqXHR;\n\t\t}\n\n\t\t// We can fire global events as of now if asked to\n\t\tfireGlobals = s.global;\n\n\t\t// Watch for a new set of requests\n\t\tif ( fireGlobals && jQuery.active++ === 0 ) {\n\t\t\tjQuery.event.trigger(\"ajaxStart\");\n\t\t}\n\n\t\t// Uppercase the type\n\t\ts.type = s.type.toUpperCase();\n\n\t\t// Determine if request has content\n\t\ts.hasContent = !rnoContent.test( s.type );\n\n\t\t// Save the URL in case we're toying with the If-Modified-Since\n\t\t// and/or If-None-Match header later on\n\t\tcacheURL = s.url;\n\n\t\t// More options handling for requests with no content\n\t\tif ( !s.hasContent ) {\n\n\t\t\t// If data is available, append data to url\n\t\t\tif ( s.data ) {\n\t\t\t\tcacheURL = ( s.url += ( ajax_rquery.test( cacheURL ) ? \"&\" : \"?\" ) + s.data );\n\t\t\t\t// #9682: remove data so that it's not used in an eventual retry\n\t\t\t\tdelete s.data;\n\t\t\t}\n\n\t\t\t// Add anti-cache in url if needed\n\t\t\tif ( s.cache === false ) {\n\t\t\t\ts.url = rts.test( cacheURL ) ?\n\n\t\t\t\t\t// If there is already a '_' parameter, set its value\n\t\t\t\t\tcacheURL.replace( rts, \"$1_=\" + ajax_nonce++ ) :\n\n\t\t\t\t\t// Otherwise add one to the end\n\t\t\t\t\tcacheURL + ( ajax_rquery.test( cacheURL ) ? \"&\" : \"?\" ) + \"_=\" + ajax_nonce++;\n\t\t\t}\n\t\t}\n\n\t\t// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.\n\t\tif ( s.ifModified ) {\n\t\t\tif ( jQuery.lastModified[ cacheURL ] ) {\n\t\t\t\tjqXHR.setRequestHeader( \"If-Modified-Since\", jQuery.lastModified[ cacheURL ] );\n\t\t\t}\n\t\t\tif ( jQuery.etag[ cacheURL ] ) {\n\t\t\t\tjqXHR.setRequestHeader( \"If-None-Match\", jQuery.etag[ cacheURL ] );\n\t\t\t}\n\t\t}\n\n\t\t// Set the correct header, if data is being sent\n\t\tif ( s.data && s.hasContent && s.contentType !== false || options.contentType ) {\n\t\t\tjqXHR.setRequestHeader( \"Content-Type\", s.contentType );\n\t\t}\n\n\t\t// Set the Accepts header for the server, depending on the dataType\n\t\tjqXHR.setRequestHeader(\n\t\t\t\"Accept\",\n\t\t\ts.dataTypes[ 0 ] && s.accepts[ s.dataTypes[0] ] ?\n\t\t\t\ts.accepts[ s.dataTypes[0] ] + ( s.dataTypes[ 0 ] !== \"*\" ? \", \" + allTypes + \"; q=0.01\" : \"\" ) :\n\t\t\t\ts.accepts[ \"*\" ]\n\t\t);\n\n\t\t// Check for headers option\n\t\tfor ( i in s.headers ) {\n\t\t\tjqXHR.setRequestHeader( i, s.headers[ i ] );\n\t\t}\n\n\t\t// Allow custom headers/mimetypes and early abort\n\t\tif ( s.beforeSend && ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || state === 2 ) ) {\n\t\t\t// Abort if not done already and return\n\t\t\treturn jqXHR.abort();\n\t\t}\n\n\t\t// aborting is no longer a cancellation\n\t\tstrAbort = \"abort\";\n\n\t\t// Install callbacks on deferreds\n\t\tfor ( i in { success: 1, error: 1, complete: 1 } ) {\n\t\t\tjqXHR[ i ]( s[ i ] );\n\t\t}\n\n\t\t// Get transport\n\t\ttransport = inspectPrefiltersOrTransports( transports, s, options, jqXHR );\n\n\t\t// If no transport, we auto-abort\n\t\tif ( !transport ) {\n\t\t\tdone( -1, \"No Transport\" );\n\t\t} else {\n\t\t\tjqXHR.readyState = 1;\n\n\t\t\t// Send global event\n\t\t\tif ( fireGlobals ) {\n\t\t\t\tglobalEventContext.trigger( \"ajaxSend\", [ jqXHR, s ] );\n\t\t\t}\n\t\t\t// Timeout\n\t\t\tif ( s.async && s.timeout > 0 ) {\n\t\t\t\ttimeoutTimer = setTimeout(function() {\n\t\t\t\t\tjqXHR.abort(\"timeout\");\n\t\t\t\t}, s.timeout );\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tstate = 1;\n\t\t\t\ttransport.send( requestHeaders, done );\n\t\t\t} catch ( e ) {\n\t\t\t\t// Propagate exception as error if not done\n\t\t\t\tif ( state < 2 ) {\n\t\t\t\t\tdone( -1, e );\n\t\t\t\t// Simply rethrow otherwise\n\t\t\t\t} else {\n\t\t\t\t\tthrow e;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Callback for when everything is done\n\t\tfunction done( status, nativeStatusText, responses, headers ) {\n\t\t\tvar isSuccess, success, error, response, modified,\n\t\t\t\tstatusText = nativeStatusText;\n\n\t\t\t// Called once\n\t\t\tif ( state === 2 ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// State is \"done\" now\n\t\t\tstate = 2;\n\n\t\t\t// Clear timeout if it exists\n\t\t\tif ( timeoutTimer ) {\n\t\t\t\tclearTimeout( timeoutTimer );\n\t\t\t}\n\n\t\t\t// Dereference transport for early garbage collection\n\t\t\t// (no matter how long the jqXHR object will be used)\n\t\t\ttransport = undefined;\n\n\t\t\t// Cache response headers\n\t\t\tresponseHeadersString = headers || \"\";\n\n\t\t\t// Set readyState\n\t\t\tjqXHR.readyState = status > 0 ? 4 : 0;\n\n\t\t\t// Get response data\n\t\t\tif ( responses ) {\n\t\t\t\tresponse = ajaxHandleResponses( s, jqXHR, responses );\n\t\t\t}\n\n\t\t\t// If successful, handle type chaining\n\t\t\tif ( status >= 200 && status < 300 || status === 304 ) {\n\n\t\t\t\t// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.\n\t\t\t\tif ( s.ifModified ) {\n\t\t\t\t\tmodified = jqXHR.getResponseHeader(\"Last-Modified\");\n\t\t\t\t\tif ( modified ) {\n\t\t\t\t\t\tjQuery.lastModified[ cacheURL ] = modified;\n\t\t\t\t\t}\n\t\t\t\t\tmodified = jqXHR.getResponseHeader(\"etag\");\n\t\t\t\t\tif ( modified ) {\n\t\t\t\t\t\tjQuery.etag[ cacheURL ] = modified;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// if no content\n\t\t\t\tif ( status === 204 ) {\n\t\t\t\t\tisSuccess = true;\n\t\t\t\t\tstatusText = \"nocontent\";\n\n\t\t\t\t// if not modified\n\t\t\t\t} else if ( status === 304 ) {\n\t\t\t\t\tisSuccess = true;\n\t\t\t\t\tstatusText = \"notmodified\";\n\n\t\t\t\t// If we have data, let's convert it\n\t\t\t\t} else {\n\t\t\t\t\tisSuccess = ajaxConvert( s, response );\n\t\t\t\t\tstatusText = isSuccess.state;\n\t\t\t\t\tsuccess = isSuccess.data;\n\t\t\t\t\terror = isSuccess.error;\n\t\t\t\t\tisSuccess = !error;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// We extract error from statusText\n\t\t\t\t// then normalize statusText and status for non-aborts\n\t\t\t\terror = statusText;\n\t\t\t\tif ( status || !statusText ) {\n\t\t\t\t\tstatusText = \"error\";\n\t\t\t\t\tif ( status < 0 ) {\n\t\t\t\t\t\tstatus = 0;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Set data for the fake xhr object\n\t\t\tjqXHR.status = status;\n\t\t\tjqXHR.statusText = ( nativeStatusText || statusText ) + \"\";\n\n\t\t\t// Success/Error\n\t\t\tif ( isSuccess ) {\n\t\t\t\tdeferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] );\n\t\t\t} else {\n\t\t\t\tdeferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] );\n\t\t\t}\n\n\t\t\t// Status-dependent callbacks\n\t\t\tjqXHR.statusCode( statusCode );\n\t\t\tstatusCode = undefined;\n\n\t\t\tif ( fireGlobals ) {\n\t\t\t\tglobalEventContext.trigger( isSuccess ? \"ajaxSuccess\" : \"ajaxError\",\n\t\t\t\t\t[ jqXHR, s, isSuccess ? success : error ] );\n\t\t\t}\n\n\t\t\t// Complete\n\t\t\tcompleteDeferred.fireWith( callbackContext, [ jqXHR, statusText ] );\n\n\t\t\tif ( fireGlobals ) {\n\t\t\t\tglobalEventContext.trigger( \"ajaxComplete\", [ jqXHR, s ] );\n\t\t\t\t// Handle the global AJAX counter\n\t\t\t\tif ( !( --jQuery.active ) ) {\n\t\t\t\t\tjQuery.event.trigger(\"ajaxStop\");\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn jqXHR;\n\t},\n\n\tgetScript: function( url, callback ) {\n\t\treturn jQuery.get( url, undefined, callback, \"script\" );\n\t},\n\n\tgetJSON: function( url, data, callback ) {\n\t\treturn jQuery.get( url, data, callback, \"json\" );\n\t}\n});\n\n/* Handles responses to an ajax request:\n * - sets all responseXXX fields accordingly\n * - finds the right dataType (mediates between content-type and expected dataType)\n * - returns the corresponding response\n */\nfunction ajaxHandleResponses( s, jqXHR, responses ) {\n\tvar firstDataType, ct, finalDataType, type,\n\t\tcontents = s.contents,\n\t\tdataTypes = s.dataTypes,\n\t\tresponseFields = s.responseFields;\n\n\t// Fill responseXXX fields\n\tfor ( type in responseFields ) {\n\t\tif ( type in responses ) {\n\t\t\tjqXHR[ responseFields[type] ] = responses[ type ];\n\t\t}\n\t}\n\n\t// Remove auto dataType and get content-type in the process\n\twhile( dataTypes[ 0 ] === \"*\" ) {\n\t\tdataTypes.shift();\n\t\tif ( ct === undefined ) {\n\t\t\tct = s.mimeType || jqXHR.getResponseHeader(\"Content-Type\");\n\t\t}\n\t}\n\n\t// Check if we're dealing with a known content-type\n\tif ( ct ) {\n\t\tfor ( type in contents ) {\n\t\t\tif ( contents[ type ] && contents[ type ].test( ct ) ) {\n\t\t\t\tdataTypes.unshift( type );\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\t// Check to see if we have a response for the expected dataType\n\tif ( dataTypes[ 0 ] in responses ) {\n\t\tfinalDataType = dataTypes[ 0 ];\n\t} else {\n\t\t// Try convertible dataTypes\n\t\tfor ( type in responses ) {\n\t\t\tif ( !dataTypes[ 0 ] || s.converters[ type + \" \" + dataTypes[0] ] ) {\n\t\t\t\tfinalDataType = type;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif ( !firstDataType ) {\n\t\t\t\tfirstDataType = type;\n\t\t\t}\n\t\t}\n\t\t// Or just use first one\n\t\tfinalDataType = finalDataType || firstDataType;\n\t}\n\n\t// If we found a dataType\n\t// We add the dataType to the list if needed\n\t// and return the corresponding response\n\tif ( finalDataType ) {\n\t\tif ( finalDataType !== dataTypes[ 0 ] ) {\n\t\t\tdataTypes.unshift( finalDataType );\n\t\t}\n\t\treturn responses[ finalDataType ];\n\t}\n}\n\n// Chain conversions given the request and the original response\nfunction ajaxConvert( s, response ) {\n\tvar conv2, current, conv, tmp,\n\t\tconverters = {},\n\t\ti = 0,\n\t\t// Work with a copy of dataTypes in case we need to modify it for conversion\n\t\tdataTypes = s.dataTypes.slice(),\n\t\tprev = dataTypes[ 0 ];\n\n\t// Apply the dataFilter if provided\n\tif ( s.dataFilter ) {\n\t\tresponse = s.dataFilter( response, s.dataType );\n\t}\n\n\t// Create converters map with lowercased keys\n\tif ( dataTypes[ 1 ] ) {\n\t\tfor ( conv in s.converters ) {\n\t\t\tconverters[ conv.toLowerCase() ] = s.converters[ conv ];\n\t\t}\n\t}\n\n\t// Convert to each sequential dataType, tolerating list modification\n\tfor ( ; (current = dataTypes[++i]); ) {\n\n\t\t// There's only work to do if current dataType is non-auto\n\t\tif ( current !== \"*\" ) {\n\n\t\t\t// Convert response if prev dataType is non-auto and differs from current\n\t\t\tif ( prev !== \"*\" && prev !== current ) {\n\n\t\t\t\t// Seek a direct converter\n\t\t\t\tconv = converters[ prev + \" \" + current ] || converters[ \"* \" + current ];\n\n\t\t\t\t// If none found, seek a pair\n\t\t\t\tif ( !conv ) {\n\t\t\t\t\tfor ( conv2 in converters ) {\n\n\t\t\t\t\t\t// If conv2 outputs current\n\t\t\t\t\t\ttmp = conv2.split(\" \");\n\t\t\t\t\t\tif ( tmp[ 1 ] === current ) {\n\n\t\t\t\t\t\t\t// If prev can be converted to accepted input\n\t\t\t\t\t\t\tconv = converters[ prev + \" \" + tmp[ 0 ] ] ||\n\t\t\t\t\t\t\t\tconverters[ \"* \" + tmp[ 0 ] ];\n\t\t\t\t\t\t\tif ( conv ) {\n\t\t\t\t\t\t\t\t// Condense equivalence converters\n\t\t\t\t\t\t\t\tif ( conv === true ) {\n\t\t\t\t\t\t\t\t\tconv = converters[ conv2 ];\n\n\t\t\t\t\t\t\t\t// Otherwise, insert the intermediate dataType\n\t\t\t\t\t\t\t\t} else if ( converters[ conv2 ] !== true ) {\n\t\t\t\t\t\t\t\t\tcurrent = tmp[ 0 ];\n\t\t\t\t\t\t\t\t\tdataTypes.splice( i--, 0, current );\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Apply converter (if not an equivalence)\n\t\t\t\tif ( conv !== true ) {\n\n\t\t\t\t\t// Unless errors are allowed to bubble, catch and return them\n\t\t\t\t\tif ( conv && s[\"throws\"] ) {\n\t\t\t\t\t\tresponse = conv( response );\n\t\t\t\t\t} else {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tresponse = conv( response );\n\t\t\t\t\t\t} catch ( e ) {\n\t\t\t\t\t\t\treturn { state: \"parsererror\", error: conv ? e : \"No conversion from \" + prev + \" to \" + current };\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Update prev for next iteration\n\t\t\tprev = current;\n\t\t}\n\t}\n\n\treturn { state: \"success\", data: response };\n}\n// Install script dataType\njQuery.ajaxSetup({\n\taccepts: {\n\t\tscript: \"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript\"\n\t},\n\tcontents: {\n\t\tscript: /(?:java|ecma)script/\n\t},\n\tconverters: {\n\t\t\"text script\": function( text ) {\n\t\t\tjQuery.globalEval( text );\n\t\t\treturn text;\n\t\t}\n\t}\n});\n\n// Handle cache's special case and global\njQuery.ajaxPrefilter( \"script\", function( s ) {\n\tif ( s.cache === undefined ) {\n\t\ts.cache = false;\n\t}\n\tif ( s.crossDomain ) {\n\t\ts.type = \"GET\";\n\t\ts.global = false;\n\t}\n});\n\n// Bind script tag hack transport\njQuery.ajaxTransport( \"script\", function(s) {\n\n\t// This transport only deals with cross domain requests\n\tif ( s.crossDomain ) {\n\n\t\tvar script,\n\t\t\thead = document.head || jQuery(\"head\")[0] || document.documentElement;\n\n\t\treturn {\n\n\t\t\tsend: function( _, callback ) {\n\n\t\t\t\tscript = document.createElement(\"script\");\n\n\t\t\t\tscript.async = true;\n\n\t\t\t\tif ( s.scriptCharset ) {\n\t\t\t\t\tscript.charset = s.scriptCharset;\n\t\t\t\t}\n\n\t\t\t\tscript.src = s.url;\n\n\t\t\t\t// Attach handlers for all browsers\n\t\t\t\tscript.onload = script.onreadystatechange = function( _, isAbort ) {\n\n\t\t\t\t\tif ( isAbort || !script.readyState || /loaded|complete/.test( script.readyState ) ) {\n\n\t\t\t\t\t\t// Handle memory leak in IE\n\t\t\t\t\t\tscript.onload = script.onreadystatechange = null;\n\n\t\t\t\t\t\t// Remove the script\n\t\t\t\t\t\tif ( script.parentNode ) {\n\t\t\t\t\t\t\tscript.parentNode.removeChild( script );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Dereference the script\n\t\t\t\t\t\tscript = null;\n\n\t\t\t\t\t\t// Callback if not abort\n\t\t\t\t\t\tif ( !isAbort ) {\n\t\t\t\t\t\t\tcallback( 200, \"success\" );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t};\n\n\t\t\t\t// Circumvent IE6 bugs with base elements (#2709 and #4378) by prepending\n\t\t\t\t// Use native DOM manipulation to avoid our domManip AJAX trickery\n\t\t\t\thead.insertBefore( script, head.firstChild );\n\t\t\t},\n\n\t\t\tabort: function() {\n\t\t\t\tif ( script ) {\n\t\t\t\t\tscript.onload( undefined, true );\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t}\n});\nvar oldCallbacks = [],\n\trjsonp = /(=)\\?(?=&|$)|\\?\\?/;\n\n// Default jsonp settings\njQuery.ajaxSetup({\n\tjsonp: \"callback\",\n\tjsonpCallback: function() {\n\t\tvar callback = oldCallbacks.pop() || ( jQuery.expando + \"_\" + ( ajax_nonce++ ) );\n\t\tthis[ callback ] = true;\n\t\treturn callback;\n\t}\n});\n\n// Detect, normalize options and install callbacks for jsonp requests\njQuery.ajaxPrefilter( \"json jsonp\", function( s, originalSettings, jqXHR ) {\n\n\tvar callbackName, overwritten, responseContainer,\n\t\tjsonProp = s.jsonp !== false && ( rjsonp.test( s.url ) ?\n\t\t\t\"url\" :\n\t\t\ttypeof s.data === \"string\" && !( s.contentType || \"\" ).indexOf(\"application/x-www-form-urlencoded\") && rjsonp.test( s.data ) && \"data\"\n\t\t);\n\n\t// Handle iff the expected data type is \"jsonp\" or we have a parameter to set\n\tif ( jsonProp || s.dataTypes[ 0 ] === \"jsonp\" ) {\n\n\t\t// Get callback name, remembering preexisting value associated with it\n\t\tcallbackName = s.jsonpCallback = jQuery.isFunction( s.jsonpCallback ) ?\n\t\t\ts.jsonpCallback() :\n\t\t\ts.jsonpCallback;\n\n\t\t// Insert callback into url or form data\n\t\tif ( jsonProp ) {\n\t\t\ts[ jsonProp ] = s[ jsonProp ].replace( rjsonp, \"$1\" + callbackName );\n\t\t} else if ( s.jsonp !== false ) {\n\t\t\ts.url += ( ajax_rquery.test( s.url ) ? \"&\" : \"?\" ) + s.jsonp + \"=\" + callbackName;\n\t\t}\n\n\t\t// Use data converter to retrieve json after script execution\n\t\ts.converters[\"script json\"] = function() {\n\t\t\tif ( !responseContainer ) {\n\t\t\t\tjQuery.error( callbackName + \" was not called\" );\n\t\t\t}\n\t\t\treturn responseContainer[ 0 ];\n\t\t};\n\n\t\t// force json dataType\n\t\ts.dataTypes[ 0 ] = \"json\";\n\n\t\t// Install callback\n\t\toverwritten = window[ callbackName ];\n\t\twindow[ callbackName ] = function() {\n\t\t\tresponseContainer = arguments;\n\t\t};\n\n\t\t// Clean-up function (fires after converters)\n\t\tjqXHR.always(function() {\n\t\t\t// Restore preexisting value\n\t\t\twindow[ callbackName ] = overwritten;\n\n\t\t\t// Save back as free\n\t\t\tif ( s[ callbackName ] ) {\n\t\t\t\t// make sure that re-using the options doesn't screw things around\n\t\t\t\ts.jsonpCallback = originalSettings.jsonpCallback;\n\n\t\t\t\t// save the callback name for future use\n\t\t\t\toldCallbacks.push( callbackName );\n\t\t\t}\n\n\t\t\t// Call if it was a function and we have a response\n\t\t\tif ( responseContainer && jQuery.isFunction( overwritten ) ) {\n\t\t\t\toverwritten( responseContainer[ 0 ] );\n\t\t\t}\n\n\t\t\tresponseContainer = overwritten = undefined;\n\t\t});\n\n\t\t// Delegate to script\n\t\treturn \"script\";\n\t}\n});\nvar xhrCallbacks, xhrSupported,\n\txhrId = 0,\n\t// #5280: Internet Explorer will keep connections alive if we don't abort on unload\n\txhrOnUnloadAbort = window.ActiveXObject && function() {\n\t\t// Abort all pending requests\n\t\tvar key;\n\t\tfor ( key in xhrCallbacks ) {\n\t\t\txhrCallbacks[ key ]( undefined, true );\n\t\t}\n\t};\n\n// Functions to create xhrs\nfunction createStandardXHR() {\n\ttry {\n\t\treturn new window.XMLHttpRequest();\n\t} catch( e ) {}\n}\n\nfunction createActiveXHR() {\n\ttry {\n\t\treturn new window.ActiveXObject(\"Microsoft.XMLHTTP\");\n\t} catch( e ) {}\n}\n\n// Create the request object\n// (This is still attached to ajaxSettings for backward compatibility)\njQuery.ajaxSettings.xhr = window.ActiveXObject ?\n\t/* Microsoft failed to properly\n\t * implement the XMLHttpRequest in IE7 (can't request local files),\n\t * so we use the ActiveXObject when it is available\n\t * Additionally XMLHttpRequest can be disabled in IE7/IE8 so\n\t * we need a fallback.\n\t */\n\tfunction() {\n\t\treturn !this.isLocal && createStandardXHR() || createActiveXHR();\n\t} :\n\t// For all other browsers, use the standard XMLHttpRequest object\n\tcreateStandardXHR;\n\n// Determine support properties\nxhrSupported = jQuery.ajaxSettings.xhr();\njQuery.support.cors = !!xhrSupported && ( \"withCredentials\" in xhrSupported );\nxhrSupported = jQuery.support.ajax = !!xhrSupported;\n\n// Create transport if the browser can provide an xhr\nif ( xhrSupported ) {\n\n\tjQuery.ajaxTransport(function( s ) {\n\t\t// Cross domain only allowed if supported through XMLHttpRequest\n\t\tif ( !s.crossDomain || jQuery.support.cors ) {\n\n\t\t\tvar callback;\n\n\t\t\treturn {\n\t\t\t\tsend: function( headers, complete ) {\n\n\t\t\t\t\t// Get a new xhr\n\t\t\t\t\tvar handle, i,\n\t\t\t\t\t\txhr = s.xhr();\n\n\t\t\t\t\t// Open the socket\n\t\t\t\t\t// Passing null username, generates a login popup on Opera (#2865)\n\t\t\t\t\tif ( s.username ) {\n\t\t\t\t\t\txhr.open( s.type, s.url, s.async, s.username, s.password );\n\t\t\t\t\t} else {\n\t\t\t\t\t\txhr.open( s.type, s.url, s.async );\n\t\t\t\t\t}\n\n\t\t\t\t\t// Apply custom fields if provided\n\t\t\t\t\tif ( s.xhrFields ) {\n\t\t\t\t\t\tfor ( i in s.xhrFields ) {\n\t\t\t\t\t\t\txhr[ i ] = s.xhrFields[ i ];\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Override mime type if needed\n\t\t\t\t\tif ( s.mimeType && xhr.overrideMimeType ) {\n\t\t\t\t\t\txhr.overrideMimeType( s.mimeType );\n\t\t\t\t\t}\n\n\t\t\t\t\t// X-Requested-With header\n\t\t\t\t\t// For cross-domain requests, seeing as conditions for a preflight are\n\t\t\t\t\t// akin to a jigsaw puzzle, we simply never set it to be sure.\n\t\t\t\t\t// (it can always be set on a per-request basis or even using ajaxSetup)\n\t\t\t\t\t// For same-domain requests, won't change header if already provided.\n\t\t\t\t\tif ( !s.crossDomain && !headers[\"X-Requested-With\"] ) {\n\t\t\t\t\t\theaders[\"X-Requested-With\"] = \"XMLHttpRequest\";\n\t\t\t\t\t}\n\n\t\t\t\t\t// Need an extra try/catch for cross domain requests in Firefox 3\n\t\t\t\t\ttry {\n\t\t\t\t\t\tfor ( i in headers ) {\n\t\t\t\t\t\t\txhr.setRequestHeader( i, headers[ i ] );\n\t\t\t\t\t\t}\n\t\t\t\t\t} catch( err ) {}\n\n\t\t\t\t\t// Do send the request\n\t\t\t\t\t// This may raise an exception which is actually\n\t\t\t\t\t// handled in jQuery.ajax (so no try/catch here)\n\t\t\t\t\txhr.send( ( s.hasContent && s.data ) || null );\n\n\t\t\t\t\t// Listener\n\t\t\t\t\tcallback = function( _, isAbort ) {\n\t\t\t\t\t\tvar status, responseHeaders, statusText, responses;\n\n\t\t\t\t\t\t// Firefox throws exceptions when accessing properties\n\t\t\t\t\t\t// of an xhr when a network error occurred\n\t\t\t\t\t\t// http://helpful.knobs-dials.com/index.php/Component_returned_failure_code:_0x80040111_(NS_ERROR_NOT_AVAILABLE)\n\t\t\t\t\t\ttry {\n\n\t\t\t\t\t\t\t// Was never called and is aborted or complete\n\t\t\t\t\t\t\tif ( callback && ( isAbort || xhr.readyState === 4 ) ) {\n\n\t\t\t\t\t\t\t\t// Only called once\n\t\t\t\t\t\t\t\tcallback = undefined;\n\n\t\t\t\t\t\t\t\t// Do not keep as active anymore\n\t\t\t\t\t\t\t\tif ( handle ) {\n\t\t\t\t\t\t\t\t\txhr.onreadystatechange = jQuery.noop;\n\t\t\t\t\t\t\t\t\tif ( xhrOnUnloadAbort ) {\n\t\t\t\t\t\t\t\t\t\tdelete xhrCallbacks[ handle ];\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t// If it's an abort\n\t\t\t\t\t\t\t\tif ( isAbort ) {\n\t\t\t\t\t\t\t\t\t// Abort it manually if needed\n\t\t\t\t\t\t\t\t\tif ( xhr.readyState !== 4 ) {\n\t\t\t\t\t\t\t\t\t\txhr.abort();\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tresponses = {};\n\t\t\t\t\t\t\t\t\tstatus = xhr.status;\n\t\t\t\t\t\t\t\t\tresponseHeaders = xhr.getAllResponseHeaders();\n\n\t\t\t\t\t\t\t\t\t// When requesting binary data, IE6-9 will throw an exception\n\t\t\t\t\t\t\t\t\t// on any attempt to access responseText (#11426)\n\t\t\t\t\t\t\t\t\tif ( typeof xhr.responseText === \"string\" ) {\n\t\t\t\t\t\t\t\t\t\tresponses.text = xhr.responseText;\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t// Firefox throws an exception when accessing\n\t\t\t\t\t\t\t\t\t// statusText for faulty cross-domain requests\n\t\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\t\tstatusText = xhr.statusText;\n\t\t\t\t\t\t\t\t\t} catch( e ) {\n\t\t\t\t\t\t\t\t\t\t// We normalize with Webkit giving an empty statusText\n\t\t\t\t\t\t\t\t\t\tstatusText = \"\";\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t// Filter status for non standard behaviors\n\n\t\t\t\t\t\t\t\t\t// If the request is local and we have data: assume a success\n\t\t\t\t\t\t\t\t\t// (success with no data won't get notified, that's the best we\n\t\t\t\t\t\t\t\t\t// can do given current implementations)\n\t\t\t\t\t\t\t\t\tif ( !status && s.isLocal && !s.crossDomain ) {\n\t\t\t\t\t\t\t\t\t\tstatus = responses.text ? 200 : 404;\n\t\t\t\t\t\t\t\t\t// IE - #1450: sometimes returns 1223 when it should be 204\n\t\t\t\t\t\t\t\t\t} else if ( status === 1223 ) {\n\t\t\t\t\t\t\t\t\t\tstatus = 204;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} catch( firefoxAccessException ) {\n\t\t\t\t\t\t\tif ( !isAbort ) {\n\t\t\t\t\t\t\t\tcomplete( -1, firefoxAccessException );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Call complete if needed\n\t\t\t\t\t\tif ( responses ) {\n\t\t\t\t\t\t\tcomplete( status, statusText, responses, responseHeaders );\n\t\t\t\t\t\t}\n\t\t\t\t\t};\n\n\t\t\t\t\tif ( !s.async ) {\n\t\t\t\t\t\t// if we're in sync mode we fire the callback\n\t\t\t\t\t\tcallback();\n\t\t\t\t\t} else if ( xhr.readyState === 4 ) {\n\t\t\t\t\t\t// (IE6 & IE7) if it's in cache and has been\n\t\t\t\t\t\t// retrieved directly we need to fire the callback\n\t\t\t\t\t\tsetTimeout( callback );\n\t\t\t\t\t} else {\n\t\t\t\t\t\thandle = ++xhrId;\n\t\t\t\t\t\tif ( xhrOnUnloadAbort ) {\n\t\t\t\t\t\t\t// Create the active xhrs callbacks list if needed\n\t\t\t\t\t\t\t// and attach the unload handler\n\t\t\t\t\t\t\tif ( !xhrCallbacks ) {\n\t\t\t\t\t\t\t\txhrCallbacks = {};\n\t\t\t\t\t\t\t\tjQuery( window ).unload( xhrOnUnloadAbort );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t// Add to list of active xhrs callbacks\n\t\t\t\t\t\t\txhrCallbacks[ handle ] = callback;\n\t\t\t\t\t\t}\n\t\t\t\t\t\txhr.onreadystatechange = callback;\n\t\t\t\t\t}\n\t\t\t\t},\n\n\t\t\t\tabort: function() {\n\t\t\t\t\tif ( callback ) {\n\t\t\t\t\t\tcallback( undefined, true );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t};\n\t\t}\n\t});\n}\nvar fxNow, timerId,\n\trfxtypes = /^(?:toggle|show|hide)$/,\n\trfxnum = new RegExp( \"^(?:([+-])=|)(\" + core_pnum + \")([a-z%]*)$\", \"i\" ),\n\trrun = /queueHooks$/,\n\tanimationPrefilters = [ defaultPrefilter ],\n\ttweeners = {\n\t\t\"*\": [function( prop, value ) {\n\t\t\tvar end, unit,\n\t\t\t\ttween = this.createTween( prop, value ),\n\t\t\t\tparts = rfxnum.exec( value ),\n\t\t\t\ttarget = tween.cur(),\n\t\t\t\tstart = +target || 0,\n\t\t\t\tscale = 1,\n\t\t\t\tmaxIterations = 20;\n\n\t\t\tif ( parts ) {\n\t\t\t\tend = +parts[2];\n\t\t\t\tunit = parts[3] || ( jQuery.cssNumber[ prop ] ? \"\" : \"px\" );\n\n\t\t\t\t// We need to compute starting value\n\t\t\t\tif ( unit !== \"px\" && start ) {\n\t\t\t\t\t// Iteratively approximate from a nonzero starting point\n\t\t\t\t\t// Prefer the current property, because this process will be trivial if it uses the same units\n\t\t\t\t\t// Fallback to end or a simple constant\n\t\t\t\t\tstart = jQuery.css( tween.elem, prop, true ) || end || 1;\n\n\t\t\t\t\tdo {\n\t\t\t\t\t\t// If previous iteration zeroed out, double until we get *something*\n\t\t\t\t\t\t// Use a string for doubling factor so we don't accidentally see scale as unchanged below\n\t\t\t\t\t\tscale = scale || \".5\";\n\n\t\t\t\t\t\t// Adjust and apply\n\t\t\t\t\t\tstart = start / scale;\n\t\t\t\t\t\tjQuery.style( tween.elem, prop, start + unit );\n\n\t\t\t\t\t// Update scale, tolerating zero or NaN from tween.cur()\n\t\t\t\t\t// And breaking the loop if scale is unchanged or perfect, or if we've just had enough\n\t\t\t\t\t} while ( scale !== (scale = tween.cur() / target) && scale !== 1 && --maxIterations );\n\t\t\t\t}\n\n\t\t\t\ttween.unit = unit;\n\t\t\t\ttween.start = start;\n\t\t\t\t// If a +=/-= token was provided, we're doing a relative animation\n\t\t\t\ttween.end = parts[1] ? start + ( parts[1] + 1 ) * end : end;\n\t\t\t}\n\t\t\treturn tween;\n\t\t}]\n\t};\n\n// Animations created synchronously will run synchronously\nfunction createFxNow() {\n\tsetTimeout(function() {\n\t\tfxNow = undefined;\n\t});\n\treturn ( fxNow = jQuery.now() );\n}\n\nfunction createTweens( animation, props ) {\n\tjQuery.each( props, function( prop, value ) {\n\t\tvar collection = ( tweeners[ prop ] || [] ).concat( tweeners[ \"*\" ] ),\n\t\t\tindex = 0,\n\t\t\tlength = collection.length;\n\t\tfor ( ; index < length; index++ ) {\n\t\t\tif ( collection[ index ].call( animation, prop, value ) ) {\n\n\t\t\t\t// we're done with this property\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t});\n}\n\nfunction Animation( elem, properties, options ) {\n\tvar result,\n\t\tstopped,\n\t\tindex = 0,\n\t\tlength = animationPrefilters.length,\n\t\tdeferred = jQuery.Deferred().always( function() {\n\t\t\t// don't match elem in the :animated selector\n\t\t\tdelete tick.elem;\n\t\t}),\n\t\ttick = function() {\n\t\t\tif ( stopped ) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tvar currentTime = fxNow || createFxNow(),\n\t\t\t\tremaining = Math.max( 0, animation.startTime + animation.duration - currentTime ),\n\t\t\t\t// archaic crash bug won't allow us to use 1 - ( 0.5 || 0 ) (#12497)\n\t\t\t\ttemp = remaining / animation.duration || 0,\n\t\t\t\tpercent = 1 - temp,\n\t\t\t\tindex = 0,\n\t\t\t\tlength = animation.tweens.length;\n\n\t\t\tfor ( ; index < length ; index++ ) {\n\t\t\t\tanimation.tweens[ index ].run( percent );\n\t\t\t}\n\n\t\t\tdeferred.notifyWith( elem, [ animation, percent, remaining ]);\n\n\t\t\tif ( percent < 1 && length ) {\n\t\t\t\treturn remaining;\n\t\t\t} else {\n\t\t\t\tdeferred.resolveWith( elem, [ animation ] );\n\t\t\t\treturn false;\n\t\t\t}\n\t\t},\n\t\tanimation = deferred.promise({\n\t\t\telem: elem,\n\t\t\tprops: jQuery.extend( {}, properties ),\n\t\t\topts: jQuery.extend( true, { specialEasing: {} }, options ),\n\t\t\toriginalProperties: properties,\n\t\t\toriginalOptions: options,\n\t\t\tstartTime: fxNow || createFxNow(),\n\t\t\tduration: options.duration,\n\t\t\ttweens: [],\n\t\t\tcreateTween: function( prop, end ) {\n\t\t\t\tvar tween = jQuery.Tween( elem, animation.opts, prop, end,\n\t\t\t\t\t\tanimation.opts.specialEasing[ prop ] || animation.opts.easing );\n\t\t\t\tanimation.tweens.push( tween );\n\t\t\t\treturn tween;\n\t\t\t},\n\t\t\tstop: function( gotoEnd ) {\n\t\t\t\tvar index = 0,\n\t\t\t\t\t// if we are going to the end, we want to run all the tweens\n\t\t\t\t\t// otherwise we skip this part\n\t\t\t\t\tlength = gotoEnd ? animation.tweens.length : 0;\n\t\t\t\tif ( stopped ) {\n\t\t\t\t\treturn this;\n\t\t\t\t}\n\t\t\t\tstopped = true;\n\t\t\t\tfor ( ; index < length ; index++ ) {\n\t\t\t\t\tanimation.tweens[ index ].run( 1 );\n\t\t\t\t}\n\n\t\t\t\t// resolve when we played the last frame\n\t\t\t\t// otherwise, reject\n\t\t\t\tif ( gotoEnd ) {\n\t\t\t\t\tdeferred.resolveWith( elem, [ animation, gotoEnd ] );\n\t\t\t\t} else {\n\t\t\t\t\tdeferred.rejectWith( elem, [ animation, gotoEnd ] );\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t}\n\t\t}),\n\t\tprops = animation.props;\n\n\tpropFilter( props, animation.opts.specialEasing );\n\n\tfor ( ; index < length ; index++ ) {\n\t\tresult = animationPrefilters[ index ].call( animation, elem, props, animation.opts );\n\t\tif ( result ) {\n\t\t\treturn result;\n\t\t}\n\t}\n\n\tcreateTweens( animation, props );\n\n\tif ( jQuery.isFunction( animation.opts.start ) ) {\n\t\tanimation.opts.start.call( elem, animation );\n\t}\n\n\tjQuery.fx.timer(\n\t\tjQuery.extend( tick, {\n\t\t\telem: elem,\n\t\t\tanim: animation,\n\t\t\tqueue: animation.opts.queue\n\t\t})\n\t);\n\n\t// attach callbacks from options\n\treturn animation.progress( animation.opts.progress )\n\t\t.done( animation.opts.done, animation.opts.complete )\n\t\t.fail( animation.opts.fail )\n\t\t.always( animation.opts.always );\n}\n\nfunction propFilter( props, specialEasing ) {\n\tvar value, name, index, easing, hooks;\n\n\t// camelCase, specialEasing and expand cssHook pass\n\tfor ( index in props ) {\n\t\tname = jQuery.camelCase( index );\n\t\teasing = specialEasing[ name ];\n\t\tvalue = props[ index ];\n\t\tif ( jQuery.isArray( value ) ) {\n\t\t\teasing = value[ 1 ];\n\t\t\tvalue = props[ index ] = value[ 0 ];\n\t\t}\n\n\t\tif ( index !== name ) {\n\t\t\tprops[ name ] = value;\n\t\t\tdelete props[ index ];\n\t\t}\n\n\t\thooks = jQuery.cssHooks[ name ];\n\t\tif ( hooks && \"expand\" in hooks ) {\n\t\t\tvalue = hooks.expand( value );\n\t\t\tdelete props[ name ];\n\n\t\t\t// not quite $.extend, this wont overwrite keys already present.\n\t\t\t// also - reusing 'index' from above because we have the correct \"name\"\n\t\t\tfor ( index in value ) {\n\t\t\t\tif ( !( index in props ) ) {\n\t\t\t\t\tprops[ index ] = value[ index ];\n\t\t\t\t\tspecialEasing[ index ] = easing;\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tspecialEasing[ name ] = easing;\n\t\t}\n\t}\n}\n\njQuery.Animation = jQuery.extend( Animation, {\n\n\ttweener: function( props, callback ) {\n\t\tif ( jQuery.isFunction( props ) ) {\n\t\t\tcallback = props;\n\t\t\tprops = [ \"*\" ];\n\t\t} else {\n\t\t\tprops = props.split(\" \");\n\t\t}\n\n\t\tvar prop,\n\t\t\tindex = 0,\n\t\t\tlength = props.length;\n\n\t\tfor ( ; index < length ; index++ ) {\n\t\t\tprop = props[ index ];\n\t\t\ttweeners[ prop ] = tweeners[ prop ] || [];\n\t\t\ttweeners[ prop ].unshift( callback );\n\t\t}\n\t},\n\n\tprefilter: function( callback, prepend ) {\n\t\tif ( prepend ) {\n\t\t\tanimationPrefilters.unshift( callback );\n\t\t} else {\n\t\t\tanimationPrefilters.push( callback );\n\t\t}\n\t}\n});\n\nfunction defaultPrefilter( elem, props, opts ) {\n\t/*jshint validthis:true */\n\tvar prop, index, length,\n\t\tvalue, dataShow, toggle,\n\t\ttween, hooks, oldfire,\n\t\tanim = this,\n\t\tstyle = elem.style,\n\t\torig = {},\n\t\thandled = [],\n\t\thidden = elem.nodeType && isHidden( elem );\n\n\t// handle queue: false promises\n\tif ( !opts.queue ) {\n\t\thooks = jQuery._queueHooks( elem, \"fx\" );\n\t\tif ( hooks.unqueued == null ) {\n\t\t\thooks.unqueued = 0;\n\t\t\toldfire = hooks.empty.fire;\n\t\t\thooks.empty.fire = function() {\n\t\t\t\tif ( !hooks.unqueued ) {\n\t\t\t\t\toldfire();\n\t\t\t\t}\n\t\t\t};\n\t\t}\n\t\thooks.unqueued++;\n\n\t\tanim.always(function() {\n\t\t\t// doing this makes sure that the complete handler will be called\n\t\t\t// before this completes\n\t\t\tanim.always(function() {\n\t\t\t\thooks.unqueued--;\n\t\t\t\tif ( !jQuery.queue( elem, \"fx\" ).length ) {\n\t\t\t\t\thooks.empty.fire();\n\t\t\t\t}\n\t\t\t});\n\t\t});\n\t}\n\n\t// height/width overflow pass\n\tif ( elem.nodeType === 1 && ( \"height\" in props || \"width\" in props ) ) {\n\t\t// Make sure that nothing sneaks out\n\t\t// Record all 3 overflow attributes because IE does not\n\t\t// change the overflow attribute when overflowX and\n\t\t// overflowY are set to the same value\n\t\topts.overflow = [ style.overflow, style.overflowX, style.overflowY ];\n\n\t\t// Set display property to inline-block for height/width\n\t\t// animations on inline elements that are having width/height animated\n\t\tif ( jQuery.css( elem, \"display\" ) === \"inline\" &&\n\t\t\t\tjQuery.css( elem, \"float\" ) === \"none\" ) {\n\n\t\t\t// inline-level elements accept inline-block;\n\t\t\t// block-level elements need to be inline with layout\n\t\t\tif ( !jQuery.support.inlineBlockNeedsLayout || css_defaultDisplay( elem.nodeName ) === \"inline\" ) {\n\t\t\t\tstyle.display = \"inline-block\";\n\n\t\t\t} else {\n\t\t\t\tstyle.zoom = 1;\n\t\t\t}\n\t\t}\n\t}\n\n\tif ( opts.overflow ) {\n\t\tstyle.overflow = \"hidden\";\n\t\tif ( !jQuery.support.shrinkWrapBlocks ) {\n\t\t\tanim.always(function() {\n\t\t\t\tstyle.overflow = opts.overflow[ 0 ];\n\t\t\t\tstyle.overflowX = opts.overflow[ 1 ];\n\t\t\t\tstyle.overflowY = opts.overflow[ 2 ];\n\t\t\t});\n\t\t}\n\t}\n\n\n\t// show/hide pass\n\tfor ( index in props ) {\n\t\tvalue = props[ index ];\n\t\tif ( rfxtypes.exec( value ) ) {\n\t\t\tdelete props[ index ];\n\t\t\ttoggle = toggle || value === \"toggle\";\n\t\t\tif ( value === ( hidden ? \"hide\" : \"show\" ) ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\thandled.push( index );\n\t\t}\n\t}\n\n\tlength = handled.length;\n\tif ( length ) {\n\t\tdataShow = jQuery._data( elem, \"fxshow\" ) || jQuery._data( elem, \"fxshow\", {} );\n\t\tif ( \"hidden\" in dataShow ) {\n\t\t\thidden = dataShow.hidden;\n\t\t}\n\n\t\t// store state if its toggle - enables .stop().toggle() to \"reverse\"\n\t\tif ( toggle ) {\n\t\t\tdataShow.hidden = !hidden;\n\t\t}\n\t\tif ( hidden ) {\n\t\t\tjQuery( elem ).show();\n\t\t} else {\n\t\t\tanim.done(function() {\n\t\t\t\tjQuery( elem ).hide();\n\t\t\t});\n\t\t}\n\t\tanim.done(function() {\n\t\t\tvar prop;\n\t\t\tjQuery._removeData( elem, \"fxshow\" );\n\t\t\tfor ( prop in orig ) {\n\t\t\t\tjQuery.style( elem, prop, orig[ prop ] );\n\t\t\t}\n\t\t});\n\t\tfor ( index = 0 ; index < length ; index++ ) {\n\t\t\tprop = handled[ index ];\n\t\t\ttween = anim.createTween( prop, hidden ? dataShow[ prop ] : 0 );\n\t\t\torig[ prop ] = dataShow[ prop ] || jQuery.style( elem, prop );\n\n\t\t\tif ( !( prop in dataShow ) ) {\n\t\t\t\tdataShow[ prop ] = tween.start;\n\t\t\t\tif ( hidden ) {\n\t\t\t\t\ttween.end = tween.start;\n\t\t\t\t\ttween.start = prop === \"width\" || prop === \"height\" ? 1 : 0;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunction Tween( elem, options, prop, end, easing ) {\n\treturn new Tween.prototype.init( elem, options, prop, end, easing );\n}\njQuery.Tween = Tween;\n\nTween.prototype = {\n\tconstructor: Tween,\n\tinit: function( elem, options, prop, end, easing, unit ) {\n\t\tthis.elem = elem;\n\t\tthis.prop = prop;\n\t\tthis.easing = easing || \"swing\";\n\t\tthis.options = options;\n\t\tthis.start = this.now = this.cur();\n\t\tthis.end = end;\n\t\tthis.unit = unit || ( jQuery.cssNumber[ prop ] ? \"\" : \"px\" );\n\t},\n\tcur: function() {\n\t\tvar hooks = Tween.propHooks[ this.prop ];\n\n\t\treturn hooks && hooks.get ?\n\t\t\thooks.get( this ) :\n\t\t\tTween.propHooks._default.get( this );\n\t},\n\trun: function( percent ) {\n\t\tvar eased,\n\t\t\thooks = Tween.propHooks[ this.prop ];\n\n\t\tif ( this.options.duration ) {\n\t\t\tthis.pos = eased = jQuery.easing[ this.easing ](\n\t\t\t\tpercent, this.options.duration * percent, 0, 1, this.options.duration\n\t\t\t);\n\t\t} else {\n\t\t\tthis.pos = eased = percent;\n\t\t}\n\t\tthis.now = ( this.end - this.start ) * eased + this.start;\n\n\t\tif ( this.options.step ) {\n\t\t\tthis.options.step.call( this.elem, this.now, this );\n\t\t}\n\n\t\tif ( hooks && hooks.set ) {\n\t\t\thooks.set( this );\n\t\t} else {\n\t\t\tTween.propHooks._default.set( this );\n\t\t}\n\t\treturn this;\n\t}\n};\n\nTween.prototype.init.prototype = Tween.prototype;\n\nTween.propHooks = {\n\t_default: {\n\t\tget: function( tween ) {\n\t\t\tvar result;\n\n\t\t\tif ( tween.elem[ tween.prop ] != null &&\n\t\t\t\t(!tween.elem.style || tween.elem.style[ tween.prop ] == null) ) {\n\t\t\t\treturn tween.elem[ tween.prop ];\n\t\t\t}\n\n\t\t\t// passing an empty string as a 3rd parameter to .css will automatically\n\t\t\t// attempt a parseFloat and fallback to a string if the parse fails\n\t\t\t// so, simple values such as \"10px\" are parsed to Float.\n\t\t\t// complex values such as \"rotate(1rad)\" are returned as is.\n\t\t\tresult = jQuery.css( tween.elem, tween.prop, \"\" );\n\t\t\t// Empty strings, null, undefined and \"auto\" are converted to 0.\n\t\t\treturn !result || result === \"auto\" ? 0 : result;\n\t\t},\n\t\tset: function( tween ) {\n\t\t\t// use step hook for back compat - use cssHook if its there - use .style if its\n\t\t\t// available and use plain properties where available\n\t\t\tif ( jQuery.fx.step[ tween.prop ] ) {\n\t\t\t\tjQuery.fx.step[ tween.prop ]( tween );\n\t\t\t} else if ( tween.elem.style && ( tween.elem.style[ jQuery.cssProps[ tween.prop ] ] != null || jQuery.cssHooks[ tween.prop ] ) ) {\n\t\t\t\tjQuery.style( tween.elem, tween.prop, tween.now + tween.unit );\n\t\t\t} else {\n\t\t\t\ttween.elem[ tween.prop ] = tween.now;\n\t\t\t}\n\t\t}\n\t}\n};\n\n// Remove in 2.0 - this supports IE8's panic based approach\n// to setting things on disconnected nodes\n\nTween.propHooks.scrollTop = Tween.propHooks.scrollLeft = {\n\tset: function( tween ) {\n\t\tif ( tween.elem.nodeType && tween.elem.parentNode ) {\n\t\t\ttween.elem[ tween.prop ] = tween.now;\n\t\t}\n\t}\n};\n\njQuery.each([ \"toggle\", \"show\", \"hide\" ], function( i, name ) {\n\tvar cssFn = jQuery.fn[ name ];\n\tjQuery.fn[ name ] = function( speed, easing, callback ) {\n\t\treturn speed == null || typeof speed === \"boolean\" ?\n\t\t\tcssFn.apply( this, arguments ) :\n\t\t\tthis.animate( genFx( name, true ), speed, easing, callback );\n\t};\n});\n\njQuery.fn.extend({\n\tfadeTo: function( speed, to, easing, callback ) {\n\n\t\t// show any hidden elements after setting opacity to 0\n\t\treturn this.filter( isHidden ).css( \"opacity\", 0 ).show()\n\n\t\t\t// animate to the value specified\n\t\t\t.end().animate({ opacity: to }, speed, easing, callback );\n\t},\n\tanimate: function( prop, speed, easing, callback ) {\n\t\tvar empty = jQuery.isEmptyObject( prop ),\n\t\t\toptall = jQuery.speed( speed, easing, callback ),\n\t\t\tdoAnimation = function() {\n\t\t\t\t// Operate on a copy of prop so per-property easing won't be lost\n\t\t\t\tvar anim = Animation( this, jQuery.extend( {}, prop ), optall );\n\t\t\t\tdoAnimation.finish = function() {\n\t\t\t\t\tanim.stop( true );\n\t\t\t\t};\n\t\t\t\t// Empty animations, or finishing resolves immediately\n\t\t\t\tif ( empty || jQuery._data( this, \"finish\" ) ) {\n\t\t\t\t\tanim.stop( true );\n\t\t\t\t}\n\t\t\t};\n\t\t\tdoAnimation.finish = doAnimation;\n\n\t\treturn empty || optall.queue === false ?\n\t\t\tthis.each( doAnimation ) :\n\t\t\tthis.queue( optall.queue, doAnimation );\n\t},\n\tstop: function( type, clearQueue, gotoEnd ) {\n\t\tvar stopQueue = function( hooks ) {\n\t\t\tvar stop = hooks.stop;\n\t\t\tdelete hooks.stop;\n\t\t\tstop( gotoEnd );\n\t\t};\n\n\t\tif ( typeof type !== \"string\" ) {\n\t\t\tgotoEnd = clearQueue;\n\t\t\tclearQueue = type;\n\t\t\ttype = undefined;\n\t\t}\n\t\tif ( clearQueue && type !== false ) {\n\t\t\tthis.queue( type || \"fx\", [] );\n\t\t}\n\n\t\treturn this.each(function() {\n\t\t\tvar dequeue = true,\n\t\t\t\tindex = type != null && type + \"queueHooks\",\n\t\t\t\ttimers = jQuery.timers,\n\t\t\t\tdata = jQuery._data( this );\n\n\t\t\tif ( index ) {\n\t\t\t\tif ( data[ index ] && data[ index ].stop ) {\n\t\t\t\t\tstopQueue( data[ index ] );\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tfor ( index in data ) {\n\t\t\t\t\tif ( data[ index ] && data[ index ].stop && rrun.test( index ) ) {\n\t\t\t\t\t\tstopQueue( data[ index ] );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfor ( index = timers.length; index--; ) {\n\t\t\t\tif ( timers[ index ].elem === this && (type == null || timers[ index ].queue === type) ) {\n\t\t\t\t\ttimers[ index ].anim.stop( gotoEnd );\n\t\t\t\t\tdequeue = false;\n\t\t\t\t\ttimers.splice( index, 1 );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// start the next in the queue if the last step wasn't forced\n\t\t\t// timers currently will call their complete callbacks, which will dequeue\n\t\t\t// but only if they were gotoEnd\n\t\t\tif ( dequeue || !gotoEnd ) {\n\t\t\t\tjQuery.dequeue( this, type );\n\t\t\t}\n\t\t});\n\t},\n\tfinish: function( type ) {\n\t\tif ( type !== false ) {\n\t\t\ttype = type || \"fx\";\n\t\t}\n\t\treturn this.each(function() {\n\t\t\tvar index,\n\t\t\t\tdata = jQuery._data( this ),\n\t\t\t\tqueue = data[ type + \"queue\" ],\n\t\t\t\thooks = data[ type + \"queueHooks\" ],\n\t\t\t\ttimers = jQuery.timers,\n\t\t\t\tlength = queue ? queue.length : 0;\n\n\t\t\t// enable finishing flag on private data\n\t\t\tdata.finish = true;\n\n\t\t\t// empty the queue first\n\t\t\tjQuery.queue( this, type, [] );\n\n\t\t\tif ( hooks && hooks.cur && hooks.cur.finish ) {\n\t\t\t\thooks.cur.finish.call( this );\n\t\t\t}\n\n\t\t\t// look for any active animations, and finish them\n\t\t\tfor ( index = timers.length; index--; ) {\n\t\t\t\tif ( timers[ index ].elem === this && timers[ index ].queue === type ) {\n\t\t\t\t\ttimers[ index ].anim.stop( true );\n\t\t\t\t\ttimers.splice( index, 1 );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// look for any animations in the old queue and finish them\n\t\t\tfor ( index = 0; index < length; index++ ) {\n\t\t\t\tif ( queue[ index ] && queue[ index ].finish ) {\n\t\t\t\t\tqueue[ index ].finish.call( this );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// turn off finishing flag\n\t\t\tdelete data.finish;\n\t\t});\n\t}\n});\n\n// Generate parameters to create a standard animation\nfunction genFx( type, includeWidth ) {\n\tvar which,\n\t\tattrs = { height: type },\n\t\ti = 0;\n\n\t// if we include width, step value is 1 to do all cssExpand values,\n\t// if we don't include width, step value is 2 to skip over Left and Right\n\tincludeWidth = includeWidth? 1 : 0;\n\tfor( ; i < 4 ; i += 2 - includeWidth ) {\n\t\twhich = cssExpand[ i ];\n\t\tattrs[ \"margin\" + which ] = attrs[ \"padding\" + which ] = type;\n\t}\n\n\tif ( includeWidth ) {\n\t\tattrs.opacity = attrs.width = type;\n\t}\n\n\treturn attrs;\n}\n\n// Generate shortcuts for custom animations\njQuery.each({\n\tslideDown: genFx(\"show\"),\n\tslideUp: genFx(\"hide\"),\n\tslideToggle: genFx(\"toggle\"),\n\tfadeIn: { opacity: \"show\" },\n\tfadeOut: { opacity: \"hide\" },\n\tfadeToggle: { opacity: \"toggle\" }\n}, function( name, props ) {\n\tjQuery.fn[ name ] = function( speed, easing, callback ) {\n\t\treturn this.animate( props, speed, easing, callback );\n\t};\n});\n\njQuery.speed = function( speed, easing, fn ) {\n\tvar opt = speed && typeof speed === \"object\" ? jQuery.extend( {}, speed ) : {\n\t\tcomplete: fn || !fn && easing ||\n\t\t\tjQuery.isFunction( speed ) && speed,\n\t\tduration: speed,\n\t\teasing: fn && easing || easing && !jQuery.isFunction( easing ) && easing\n\t};\n\n\topt.duration = jQuery.fx.off ? 0 : typeof opt.duration === \"number\" ? opt.duration :\n\t\topt.duration in jQuery.fx.speeds ? jQuery.fx.speeds[ opt.duration ] : jQuery.fx.speeds._default;\n\n\t// normalize opt.queue - true/undefined/null -> \"fx\"\n\tif ( opt.queue == null || opt.queue === true ) {\n\t\topt.queue = \"fx\";\n\t}\n\n\t// Queueing\n\topt.old = opt.complete;\n\n\topt.complete = function() {\n\t\tif ( jQuery.isFunction( opt.old ) ) {\n\t\t\topt.old.call( this );\n\t\t}\n\n\t\tif ( opt.queue ) {\n\t\t\tjQuery.dequeue( this, opt.queue );\n\t\t}\n\t};\n\n\treturn opt;\n};\n\njQuery.easing = {\n\tlinear: function( p ) {\n\t\treturn p;\n\t},\n\tswing: function( p ) {\n\t\treturn 0.5 - Math.cos( p*Math.PI ) / 2;\n\t}\n};\n\njQuery.timers = [];\njQuery.fx = Tween.prototype.init;\njQuery.fx.tick = function() {\n\tvar timer,\n\t\ttimers = jQuery.timers,\n\t\ti = 0;\n\n\tfxNow = jQuery.now();\n\n\tfor ( ; i < timers.length; i++ ) {\n\t\ttimer = timers[ i ];\n\t\t// Checks the timer has not already been removed\n\t\tif ( !timer() && timers[ i ] === timer ) {\n\t\t\ttimers.splice( i--, 1 );\n\t\t}\n\t}\n\n\tif ( !timers.length ) {\n\t\tjQuery.fx.stop();\n\t}\n\tfxNow = undefined;\n};\n\njQuery.fx.timer = function( timer ) {\n\tif ( timer() && jQuery.timers.push( timer ) ) {\n\t\tjQuery.fx.start();\n\t}\n};\n\njQuery.fx.interval = 13;\n\njQuery.fx.start = function() {\n\tif ( !timerId ) {\n\t\ttimerId = setInterval( jQuery.fx.tick, jQuery.fx.interval );\n\t}\n};\n\njQuery.fx.stop = function() {\n\tclearInterval( timerId );\n\ttimerId = null;\n};\n\njQuery.fx.speeds = {\n\tslow: 600,\n\tfast: 200,\n\t// Default speed\n\t_default: 400\n};\n\n// Back Compat <1.8 extension point\njQuery.fx.step = {};\n\nif ( jQuery.expr && jQuery.expr.filters ) {\n\tjQuery.expr.filters.animated = function( elem ) {\n\t\treturn jQuery.grep(jQuery.timers, function( fn ) {\n\t\t\treturn elem === fn.elem;\n\t\t}).length;\n\t};\n}\njQuery.fn.offset = function( options ) {\n\tif ( arguments.length ) {\n\t\treturn options === undefined ?\n\t\t\tthis :\n\t\t\tthis.each(function( i ) {\n\t\t\t\tjQuery.offset.setOffset( this, options, i );\n\t\t\t});\n\t}\n\n\tvar docElem, win,\n\t\tbox = { top: 0, left: 0 },\n\t\telem = this[ 0 ],\n\t\tdoc = elem && elem.ownerDocument;\n\n\tif ( !doc ) {\n\t\treturn;\n\t}\n\n\tdocElem = doc.documentElement;\n\n\t// Make sure it's not a disconnected DOM node\n\tif ( !jQuery.contains( docElem, elem ) ) {\n\t\treturn box;\n\t}\n\n\t// If we don't have gBCR, just use 0,0 rather than error\n\t// BlackBerry 5, iOS 3 (original iPhone)\n\tif ( typeof elem.getBoundingClientRect !== core_strundefined ) {\n\t\tbox = elem.getBoundingClientRect();\n\t}\n\twin = getWindow( doc );\n\treturn {\n\t\ttop: box.top  + ( win.pageYOffset || docElem.scrollTop )  - ( docElem.clientTop  || 0 ),\n\t\tleft: box.left + ( win.pageXOffset || docElem.scrollLeft ) - ( docElem.clientLeft || 0 )\n\t};\n};\n\njQuery.offset = {\n\n\tsetOffset: function( elem, options, i ) {\n\t\tvar position = jQuery.css( elem, \"position\" );\n\n\t\t// set position first, in-case top/left are set even on static elem\n\t\tif ( position === \"static\" ) {\n\t\t\telem.style.position = \"relative\";\n\t\t}\n\n\t\tvar curElem = jQuery( elem ),\n\t\t\tcurOffset = curElem.offset(),\n\t\t\tcurCSSTop = jQuery.css( elem, \"top\" ),\n\t\t\tcurCSSLeft = jQuery.css( elem, \"left\" ),\n\t\t\tcalculatePosition = ( position === \"absolute\" || position === \"fixed\" ) && jQuery.inArray(\"auto\", [curCSSTop, curCSSLeft]) > -1,\n\t\t\tprops = {}, curPosition = {}, curTop, curLeft;\n\n\t\t// need to be able to calculate position if either top or left is auto and position is either absolute or fixed\n\t\tif ( calculatePosition ) {\n\t\t\tcurPosition = curElem.position();\n\t\t\tcurTop = curPosition.top;\n\t\t\tcurLeft = curPosition.left;\n\t\t} else {\n\t\t\tcurTop = parseFloat( curCSSTop ) || 0;\n\t\t\tcurLeft = parseFloat( curCSSLeft ) || 0;\n\t\t}\n\n\t\tif ( jQuery.isFunction( options ) ) {\n\t\t\toptions = options.call( elem, i, curOffset );\n\t\t}\n\n\t\tif ( options.top != null ) {\n\t\t\tprops.top = ( options.top - curOffset.top ) + curTop;\n\t\t}\n\t\tif ( options.left != null ) {\n\t\t\tprops.left = ( options.left - curOffset.left ) + curLeft;\n\t\t}\n\n\t\tif ( \"using\" in options ) {\n\t\t\toptions.using.call( elem, props );\n\t\t} else {\n\t\t\tcurElem.css( props );\n\t\t}\n\t}\n};\n\n\njQuery.fn.extend({\n\n\tposition: function() {\n\t\tif ( !this[ 0 ] ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar offsetParent, offset,\n\t\t\tparentOffset = { top: 0, left: 0 },\n\t\t\telem = this[ 0 ];\n\n\t\t// fixed elements are offset from window (parentOffset = {top:0, left: 0}, because it is it's only offset parent\n\t\tif ( jQuery.css( elem, \"position\" ) === \"fixed\" ) {\n\t\t\t// we assume that getBoundingClientRect is available when computed position is fixed\n\t\t\toffset = elem.getBoundingClientRect();\n\t\t} else {\n\t\t\t// Get *real* offsetParent\n\t\t\toffsetParent = this.offsetParent();\n\n\t\t\t// Get correct offsets\n\t\t\toffset = this.offset();\n\t\t\tif ( !jQuery.nodeName( offsetParent[ 0 ], \"html\" ) ) {\n\t\t\t\tparentOffset = offsetParent.offset();\n\t\t\t}\n\n\t\t\t// Add offsetParent borders\n\t\t\tparentOffset.top  += jQuery.css( offsetParent[ 0 ], \"borderTopWidth\", true );\n\t\t\tparentOffset.left += jQuery.css( offsetParent[ 0 ], \"borderLeftWidth\", true );\n\t\t}\n\n\t\t// Subtract parent offsets and element margins\n\t\t// note: when an element has margin: auto the offsetLeft and marginLeft\n\t\t// are the same in Safari causing offset.left to incorrectly be 0\n\t\treturn {\n\t\t\ttop:  offset.top  - parentOffset.top - jQuery.css( elem, \"marginTop\", true ),\n\t\t\tleft: offset.left - parentOffset.left - jQuery.css( elem, \"marginLeft\", true)\n\t\t};\n\t},\n\n\toffsetParent: function() {\n\t\treturn this.map(function() {\n\t\t\tvar offsetParent = this.offsetParent || document.documentElement;\n\t\t\twhile ( offsetParent && ( !jQuery.nodeName( offsetParent, \"html\" ) && jQuery.css( offsetParent, \"position\") === \"static\" ) ) {\n\t\t\t\toffsetParent = offsetParent.offsetParent;\n\t\t\t}\n\t\t\treturn offsetParent || document.documentElement;\n\t\t});\n\t}\n});\n\n\n// Create scrollLeft and scrollTop methods\njQuery.each( {scrollLeft: \"pageXOffset\", scrollTop: \"pageYOffset\"}, function( method, prop ) {\n\tvar top = /Y/.test( prop );\n\n\tjQuery.fn[ method ] = function( val ) {\n\t\treturn jQuery.access( this, function( elem, method, val ) {\n\t\t\tvar win = getWindow( elem );\n\n\t\t\tif ( val === undefined ) {\n\t\t\t\treturn win ? (prop in win) ? win[ prop ] :\n\t\t\t\t\twin.document.documentElement[ method ] :\n\t\t\t\t\telem[ method ];\n\t\t\t}\n\n\t\t\tif ( win ) {\n\t\t\t\twin.scrollTo(\n\t\t\t\t\t!top ? val : jQuery( win ).scrollLeft(),\n\t\t\t\t\ttop ? val : jQuery( win ).scrollTop()\n\t\t\t\t);\n\n\t\t\t} else {\n\t\t\t\telem[ method ] = val;\n\t\t\t}\n\t\t}, method, val, arguments.length, null );\n\t};\n});\n\nfunction getWindow( elem ) {\n\treturn jQuery.isWindow( elem ) ?\n\t\telem :\n\t\telem.nodeType === 9 ?\n\t\t\telem.defaultView || elem.parentWindow :\n\t\t\tfalse;\n}\n// Create innerHeight, innerWidth, height, width, outerHeight and outerWidth methods\njQuery.each( { Height: \"height\", Width: \"width\" }, function( name, type ) {\n\tjQuery.each( { padding: \"inner\" + name, content: type, \"\": \"outer\" + name }, function( defaultExtra, funcName ) {\n\t\t// margin is only for outerHeight, outerWidth\n\t\tjQuery.fn[ funcName ] = function( margin, value ) {\n\t\t\tvar chainable = arguments.length && ( defaultExtra || typeof margin !== \"boolean\" ),\n\t\t\t\textra = defaultExtra || ( margin === true || value === true ? \"margin\" : \"border\" );\n\n\t\t\treturn jQuery.access( this, function( elem, type, value ) {\n\t\t\t\tvar doc;\n\n\t\t\t\tif ( jQuery.isWindow( elem ) ) {\n\t\t\t\t\t// As of 5/8/2012 this will yield incorrect results for Mobile Safari, but there\n\t\t\t\t\t// isn't a whole lot we can do. See pull request at this URL for discussion:\n\t\t\t\t\t// https://github.com/jquery/jquery/pull/764\n\t\t\t\t\treturn elem.document.documentElement[ \"client\" + name ];\n\t\t\t\t}\n\n\t\t\t\t// Get document width or height\n\t\t\t\tif ( elem.nodeType === 9 ) {\n\t\t\t\t\tdoc = elem.documentElement;\n\n\t\t\t\t\t// Either scroll[Width/Height] or offset[Width/Height] or client[Width/Height], whichever is greatest\n\t\t\t\t\t// unfortunately, this causes bug #3838 in IE6/8 only, but there is currently no good, small way to fix it.\n\t\t\t\t\treturn Math.max(\n\t\t\t\t\t\telem.body[ \"scroll\" + name ], doc[ \"scroll\" + name ],\n\t\t\t\t\t\telem.body[ \"offset\" + name ], doc[ \"offset\" + name ],\n\t\t\t\t\t\tdoc[ \"client\" + name ]\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\treturn value === undefined ?\n\t\t\t\t\t// Get width or height on the element, requesting but not forcing parseFloat\n\t\t\t\t\tjQuery.css( elem, type, extra ) :\n\n\t\t\t\t\t// Set width or height on the element\n\t\t\t\t\tjQuery.style( elem, type, value, extra );\n\t\t\t}, type, chainable ? margin : undefined, chainable, null );\n\t\t};\n\t});\n});\n// Limit scope pollution from any deprecated API\n// (function() {\n\n// })();\n// Expose jQuery to the global object\nwindow.jQuery = window.$ = jQuery;\n\n// Expose jQuery as an AMD module, but only for AMD loaders that\n// understand the issues with loading multiple versions of jQuery\n// in a page that all might call define(). The loader will indicate\n// they have special allowances for multiple jQuery versions by\n// specifying define.amd.jQuery = true. Register as a named module,\n// since jQuery can be concatenated with other files that may use define,\n// but not use a proper concatenation script that understands anonymous\n// AMD modules. A named AMD is safest and most robust way to register.\n// Lowercase jquery is used because AMD module names are derived from\n// file names, and jQuery is normally delivered in a lowercase file name.\n// Do this after creating the global so that if an AMD module wants to call\n// noConflict to hide this version of jQuery, it will work.\nif ( typeof define === \"function\" && define.amd && define.amd.jQuery ) {\n\tdefine( \"jquery\", [], function () { return jQuery; } );\n}\n\n})( window );"
  },
  {
    "path": "flowable-ui-web/idm/libs/sizzle_1.10.16/test/libs/qunit/qunit.css",
    "content": "/**\n * QUnit v1.12.0 - A JavaScript Unit Testing Framework\n *\n * http://qunitjs.com\n *\n * Copyright 2012 jQuery Foundation and other contributors\n * Released under the MIT license.\n * http://jquery.org/license\n */\n\n/** Font Family and Sizes */\n\n#qunit-tests, #qunit-header, #qunit-banner, #qunit-testrunner-toolbar, #qunit-userAgent, #qunit-testresult {\n\tfont-family: \"Helvetica Neue Light\", \"HelveticaNeue-Light\", \"Helvetica Neue\", Calibri, Helvetica, Arial, sans-serif;\n}\n\n#qunit-testrunner-toolbar, #qunit-userAgent, #qunit-testresult, #qunit-tests li { font-size: small; }\n#qunit-tests { font-size: smaller; }\n\n\n/** Resets */\n\n#qunit-tests, #qunit-header, #qunit-banner, #qunit-userAgent, #qunit-testresult, #qunit-modulefilter {\n\tmargin: 0;\n\tpadding: 0;\n}\n\n\n/** Header */\n\n#qunit-header {\n\tpadding: 0.5em 0 0.5em 1em;\n\n\tcolor: #8699a4;\n\tbackground-color: #0d3349;\n\n\tfont-size: 1.5em;\n\tline-height: 1em;\n\tfont-weight: normal;\n\n\tborder-radius: 5px 5px 0 0;\n\t-moz-border-radius: 5px 5px 0 0;\n\t-webkit-border-top-right-radius: 5px;\n\t-webkit-border-top-left-radius: 5px;\n}\n\n#qunit-header a {\n\ttext-decoration: none;\n\tcolor: #c2ccd1;\n}\n\n#qunit-header a:hover,\n#qunit-header a:focus {\n\tcolor: #fff;\n}\n\n#qunit-testrunner-toolbar label {\n\tdisplay: inline-block;\n\tpadding: 0 .5em 0 .1em;\n}\n\n#qunit-banner {\n\theight: 5px;\n}\n\n#qunit-testrunner-toolbar {\n\tpadding: 0.5em 0 0.5em 2em;\n\tcolor: #5E740B;\n\tbackground-color: #eee;\n\toverflow: hidden;\n}\n\n#qunit-userAgent {\n\tpadding: 0.5em 0 0.5em 2.5em;\n\tbackground-color: #2b81af;\n\tcolor: #fff;\n\ttext-shadow: rgba(0, 0, 0, 0.5) 2px 2px 1px;\n}\n\n#qunit-modulefilter-container {\n\tfloat: right;\n}\n\n/** Tests: Pass/Fail */\n\n#qunit-tests {\n\tlist-style-position: inside;\n}\n\n#qunit-tests li {\n\tpadding: 0.4em 0.5em 0.4em 2.5em;\n\tborder-bottom: 1px solid #fff;\n\tlist-style-position: inside;\n}\n\n#qunit-tests.hidepass li.pass, #qunit-tests.hidepass li.running  {\n\tdisplay: none;\n}\n\n#qunit-tests li strong {\n\tcursor: pointer;\n}\n\n#qunit-tests li a {\n\tpadding: 0.5em;\n\tcolor: #c2ccd1;\n\ttext-decoration: none;\n}\n#qunit-tests li a:hover,\n#qunit-tests li a:focus {\n\tcolor: #000;\n}\n\n#qunit-tests li .runtime {\n\tfloat: right;\n\tfont-size: smaller;\n}\n\n.qunit-assert-list {\n\tmargin-top: 0.5em;\n\tpadding: 0.5em;\n\n\tbackground-color: #fff;\n\n\tborder-radius: 5px;\n\t-moz-border-radius: 5px;\n\t-webkit-border-radius: 5px;\n}\n\n.qunit-collapsed {\n\tdisplay: none;\n}\n\n#qunit-tests table {\n\tborder-collapse: collapse;\n\tmargin-top: .2em;\n}\n\n#qunit-tests th {\n\ttext-align: right;\n\tvertical-align: top;\n\tpadding: 0 .5em 0 0;\n}\n\n#qunit-tests td {\n\tvertical-align: top;\n}\n\n#qunit-tests pre {\n\tmargin: 0;\n\twhite-space: pre-wrap;\n\tword-wrap: break-word;\n}\n\n#qunit-tests del {\n\tbackground-color: #e0f2be;\n\tcolor: #374e0c;\n\ttext-decoration: none;\n}\n\n#qunit-tests ins {\n\tbackground-color: #ffcaca;\n\tcolor: #500;\n\ttext-decoration: none;\n}\n\n/*** Test Counts */\n\n#qunit-tests b.counts                       { color: black; }\n#qunit-tests b.passed                       { color: #5E740B; }\n#qunit-tests b.failed                       { color: #710909; }\n\n#qunit-tests li li {\n\tpadding: 5px;\n\tbackground-color: #fff;\n\tborder-bottom: none;\n\tlist-style-position: inside;\n}\n\n/*** Passing Styles */\n\n#qunit-tests li li.pass {\n\tcolor: #3c510c;\n\tbackground-color: #fff;\n\tborder-left: 10px solid #C6E746;\n}\n\n#qunit-tests .pass                          { color: #528CE0; background-color: #D2E0E6; }\n#qunit-tests .pass .test-name               { color: #366097; }\n\n#qunit-tests .pass .test-actual,\n#qunit-tests .pass .test-expected           { color: #999999; }\n\n#qunit-banner.qunit-pass                    { background-color: #C6E746; }\n\n/*** Failing Styles */\n\n#qunit-tests li li.fail {\n\tcolor: #710909;\n\tbackground-color: #fff;\n\tborder-left: 10px solid #EE5757;\n\twhite-space: pre;\n}\n\n#qunit-tests > li:last-child {\n\tborder-radius: 0 0 5px 5px;\n\t-moz-border-radius: 0 0 5px 5px;\n\t-webkit-border-bottom-right-radius: 5px;\n\t-webkit-border-bottom-left-radius: 5px;\n}\n\n#qunit-tests .fail                          { color: #000000; background-color: #EE5757; }\n#qunit-tests .fail .test-name,\n#qunit-tests .fail .module-name             { color: #000000; }\n\n#qunit-tests .fail .test-actual             { color: #EE5757; }\n#qunit-tests .fail .test-expected           { color: green;   }\n\n#qunit-banner.qunit-fail                    { background-color: #EE5757; }\n\n\n/** Result */\n\n#qunit-testresult {\n\tpadding: 0.5em 0.5em 0.5em 2.5em;\n\n\tcolor: #2b81af;\n\tbackground-color: #D2E0E6;\n\n\tborder-bottom: 1px solid white;\n}\n#qunit-testresult .module-name {\n\tfont-weight: bold;\n}\n\n/** Fixture */\n\n#qunit-fixture {\n\tposition: absolute;\n\ttop: -10000px;\n\tleft: -10000px;\n\twidth: 1000px;\n\theight: 1000px;\n}\n"
  },
  {
    "path": "flowable-ui-web/idm/libs/sizzle_1.10.16/test/libs/qunit/qunit.js",
    "content": "/**\n * QUnit v1.12.0 - A JavaScript Unit Testing Framework\n *\n * http://qunitjs.com\n *\n * Copyright 2013 jQuery Foundation and other contributors\n * Released under the MIT license.\n * https://jquery.org/license/\n */\n\n(function( window ) {\n\nvar QUnit,\n\tassert,\n\tconfig,\n\tonErrorFnPrev,\n\ttestId = 0,\n\tfileName = (sourceFromStacktrace( 0 ) || \"\" ).replace(/(:\\d+)+\\)?/, \"\").replace(/.+\\//, \"\"),\n\ttoString = Object.prototype.toString,\n\thasOwn = Object.prototype.hasOwnProperty,\n\t// Keep a local reference to Date (GH-283)\n\tDate = window.Date,\n\tsetTimeout = window.setTimeout,\n\tdefined = {\n\t\tsetTimeout: typeof window.setTimeout !== \"undefined\",\n\t\tsessionStorage: (function() {\n\t\t\tvar x = \"qunit-test-string\";\n\t\t\ttry {\n\t\t\t\tsessionStorage.setItem( x, x );\n\t\t\t\tsessionStorage.removeItem( x );\n\t\t\t\treturn true;\n\t\t\t} catch( e ) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}())\n\t},\n\t/**\n\t * Provides a normalized error string, correcting an issue\n\t * with IE 7 (and prior) where Error.prototype.toString is\n\t * not properly implemented\n\t *\n\t * Based on http://es5.github.com/#x15.11.4.4\n\t *\n\t * @param {String|Error} error\n\t * @return {String} error message\n\t */\n\terrorString = function( error ) {\n\t\tvar name, message,\n\t\t\terrorString = error.toString();\n\t\tif ( errorString.substring( 0, 7 ) === \"[object\" ) {\n\t\t\tname = error.name ? error.name.toString() : \"Error\";\n\t\t\tmessage = error.message ? error.message.toString() : \"\";\n\t\t\tif ( name && message ) {\n\t\t\t\treturn name + \": \" + message;\n\t\t\t} else if ( name ) {\n\t\t\t\treturn name;\n\t\t\t} else if ( message ) {\n\t\t\t\treturn message;\n\t\t\t} else {\n\t\t\t\treturn \"Error\";\n\t\t\t}\n\t\t} else {\n\t\t\treturn errorString;\n\t\t}\n\t},\n\t/**\n\t * Makes a clone of an object using only Array or Object as base,\n\t * and copies over the own enumerable properties.\n\t *\n\t * @param {Object} obj\n\t * @return {Object} New object with only the own properties (recursively).\n\t */\n\tobjectValues = function( obj ) {\n\t\t// Grunt 0.3.x uses an older version of jshint that still has jshint/jshint#392.\n\t\t/*jshint newcap: false */\n\t\tvar key, val,\n\t\t\tvals = QUnit.is( \"array\", obj ) ? [] : {};\n\t\tfor ( key in obj ) {\n\t\t\tif ( hasOwn.call( obj, key ) ) {\n\t\t\t\tval = obj[key];\n\t\t\t\tvals[key] = val === Object(val) ? objectValues(val) : val;\n\t\t\t}\n\t\t}\n\t\treturn vals;\n\t};\n\nfunction Test( settings ) {\n\textend( this, settings );\n\tthis.assertions = [];\n\tthis.testNumber = ++Test.count;\n}\n\nTest.count = 0;\n\nTest.prototype = {\n\tinit: function() {\n\t\tvar a, b, li,\n\t\t\ttests = id( \"qunit-tests\" );\n\n\t\tif ( tests ) {\n\t\t\tb = document.createElement( \"strong\" );\n\t\t\tb.innerHTML = this.nameHtml;\n\n\t\t\t// `a` initialized at top of scope\n\t\t\ta = document.createElement( \"a\" );\n\t\t\ta.innerHTML = \"Rerun\";\n\t\t\ta.href = QUnit.url({ testNumber: this.testNumber });\n\n\t\t\tli = document.createElement( \"li\" );\n\t\t\tli.appendChild( b );\n\t\t\tli.appendChild( a );\n\t\t\tli.className = \"running\";\n\t\t\tli.id = this.id = \"qunit-test-output\" + testId++;\n\n\t\t\ttests.appendChild( li );\n\t\t}\n\t},\n\tsetup: function() {\n\t\tif (\n\t\t\t// Emit moduleStart when we're switching from one module to another\n\t\t\tthis.module !== config.previousModule ||\n\t\t\t\t// They could be equal (both undefined) but if the previousModule property doesn't\n\t\t\t\t// yet exist it means this is the first test in a suite that isn't wrapped in a\n\t\t\t\t// module, in which case we'll just emit a moduleStart event for 'undefined'.\n\t\t\t\t// Without this, reporters can get testStart before moduleStart  which is a problem.\n\t\t\t\t!hasOwn.call( config, \"previousModule\" )\n\t\t) {\n\t\t\tif ( hasOwn.call( config, \"previousModule\" ) ) {\n\t\t\t\trunLoggingCallbacks( \"moduleDone\", QUnit, {\n\t\t\t\t\tname: config.previousModule,\n\t\t\t\t\tfailed: config.moduleStats.bad,\n\t\t\t\t\tpassed: config.moduleStats.all - config.moduleStats.bad,\n\t\t\t\t\ttotal: config.moduleStats.all\n\t\t\t\t});\n\t\t\t}\n\t\t\tconfig.previousModule = this.module;\n\t\t\tconfig.moduleStats = { all: 0, bad: 0 };\n\t\t\trunLoggingCallbacks( \"moduleStart\", QUnit, {\n\t\t\t\tname: this.module\n\t\t\t});\n\t\t}\n\n\t\tconfig.current = this;\n\n\t\tthis.testEnvironment = extend({\n\t\t\tsetup: function() {},\n\t\t\tteardown: function() {}\n\t\t}, this.moduleTestEnvironment );\n\n\t\tthis.started = +new Date();\n\t\trunLoggingCallbacks( \"testStart\", QUnit, {\n\t\t\tname: this.testName,\n\t\t\tmodule: this.module\n\t\t});\n\n\t\t/*jshint camelcase:false */\n\n\n\t\t/**\n\t\t * Expose the current test environment.\n\t\t *\n\t\t * @deprecated since 1.12.0: Use QUnit.config.current.testEnvironment instead.\n\t\t */\n\t\tQUnit.current_testEnvironment = this.testEnvironment;\n\n\t\t/*jshint camelcase:true */\n\n\t\tif ( !config.pollution ) {\n\t\t\tsaveGlobal();\n\t\t}\n\t\tif ( config.notrycatch ) {\n\t\t\tthis.testEnvironment.setup.call( this.testEnvironment, QUnit.assert );\n\t\t\treturn;\n\t\t}\n\t\ttry {\n\t\t\tthis.testEnvironment.setup.call( this.testEnvironment, QUnit.assert );\n\t\t} catch( e ) {\n\t\t\tQUnit.pushFailure( \"Setup failed on \" + this.testName + \": \" + ( e.message || e ), extractStacktrace( e, 1 ) );\n\t\t}\n\t},\n\trun: function() {\n\t\tconfig.current = this;\n\n\t\tvar running = id( \"qunit-testresult\" );\n\n\t\tif ( running ) {\n\t\t\trunning.innerHTML = \"Running: <br/>\" + this.nameHtml;\n\t\t}\n\n\t\tif ( this.async ) {\n\t\t\tQUnit.stop();\n\t\t}\n\n\t\tthis.callbackStarted = +new Date();\n\n\t\tif ( config.notrycatch ) {\n\t\t\tthis.callback.call( this.testEnvironment, QUnit.assert );\n\t\t\tthis.callbackRuntime = +new Date() - this.callbackStarted;\n\t\t\treturn;\n\t\t}\n\n\t\ttry {\n\t\t\tthis.callback.call( this.testEnvironment, QUnit.assert );\n\t\t\tthis.callbackRuntime = +new Date() - this.callbackStarted;\n\t\t} catch( e ) {\n\t\t\tthis.callbackRuntime = +new Date() - this.callbackStarted;\n\n\t\t\tQUnit.pushFailure( \"Died on test #\" + (this.assertions.length + 1) + \" \" + this.stack + \": \" + ( e.message || e ), extractStacktrace( e, 0 ) );\n\t\t\t// else next test will carry the responsibility\n\t\t\tsaveGlobal();\n\n\t\t\t// Restart the tests if they're blocking\n\t\t\tif ( config.blocking ) {\n\t\t\t\tQUnit.start();\n\t\t\t}\n\t\t}\n\t},\n\tteardown: function() {\n\t\tconfig.current = this;\n\t\tif ( config.notrycatch ) {\n\t\t\tif ( typeof this.callbackRuntime === \"undefined\" ) {\n\t\t\t\tthis.callbackRuntime = +new Date() - this.callbackStarted;\n\t\t\t}\n\t\t\tthis.testEnvironment.teardown.call( this.testEnvironment, QUnit.assert );\n\t\t\treturn;\n\t\t} else {\n\t\t\ttry {\n\t\t\t\tthis.testEnvironment.teardown.call( this.testEnvironment, QUnit.assert );\n\t\t\t} catch( e ) {\n\t\t\t\tQUnit.pushFailure( \"Teardown failed on \" + this.testName + \": \" + ( e.message || e ), extractStacktrace( e, 1 ) );\n\t\t\t}\n\t\t}\n\t\tcheckPollution();\n\t},\n\tfinish: function() {\n\t\tconfig.current = this;\n\t\tif ( config.requireExpects && this.expected === null ) {\n\t\t\tQUnit.pushFailure( \"Expected number of assertions to be defined, but expect() was not called.\", this.stack );\n\t\t} else if ( this.expected !== null && this.expected !== this.assertions.length ) {\n\t\t\tQUnit.pushFailure( \"Expected \" + this.expected + \" assertions, but \" + this.assertions.length + \" were run\", this.stack );\n\t\t} else if ( this.expected === null && !this.assertions.length ) {\n\t\t\tQUnit.pushFailure( \"Expected at least one assertion, but none were run - call expect(0) to accept zero assertions.\", this.stack );\n\t\t}\n\n\t\tvar i, assertion, a, b, time, li, ol,\n\t\t\ttest = this,\n\t\t\tgood = 0,\n\t\t\tbad = 0,\n\t\t\ttests = id( \"qunit-tests\" );\n\n\t\tthis.runtime = +new Date() - this.started;\n\t\tconfig.stats.all += this.assertions.length;\n\t\tconfig.moduleStats.all += this.assertions.length;\n\n\t\tif ( tests ) {\n\t\t\tol = document.createElement( \"ol\" );\n\t\t\tol.className = \"qunit-assert-list\";\n\n\t\t\tfor ( i = 0; i < this.assertions.length; i++ ) {\n\t\t\t\tassertion = this.assertions[i];\n\n\t\t\t\tli = document.createElement( \"li\" );\n\t\t\t\tli.className = assertion.result ? \"pass\" : \"fail\";\n\t\t\t\tli.innerHTML = assertion.message || ( assertion.result ? \"okay\" : \"failed\" );\n\t\t\t\tol.appendChild( li );\n\n\t\t\t\tif ( assertion.result ) {\n\t\t\t\t\tgood++;\n\t\t\t\t} else {\n\t\t\t\t\tbad++;\n\t\t\t\t\tconfig.stats.bad++;\n\t\t\t\t\tconfig.moduleStats.bad++;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// store result when possible\n\t\t\tif ( QUnit.config.reorder && defined.sessionStorage ) {\n\t\t\t\tif ( bad ) {\n\t\t\t\t\tsessionStorage.setItem( \"qunit-test-\" + this.module + \"-\" + this.testName, bad );\n\t\t\t\t} else {\n\t\t\t\t\tsessionStorage.removeItem( \"qunit-test-\" + this.module + \"-\" + this.testName );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( bad === 0 ) {\n\t\t\t\taddClass( ol, \"qunit-collapsed\" );\n\t\t\t}\n\n\t\t\t// `b` initialized at top of scope\n\t\t\tb = document.createElement( \"strong\" );\n\t\t\tb.innerHTML = this.nameHtml + \" <b class='counts'>(<b class='failed'>\" + bad + \"</b>, <b class='passed'>\" + good + \"</b>, \" + this.assertions.length + \")</b>\";\n\n\t\t\taddEvent(b, \"click\", function() {\n\t\t\t\tvar next = b.parentNode.lastChild,\n\t\t\t\t\tcollapsed = hasClass( next, \"qunit-collapsed\" );\n\t\t\t\t( collapsed ? removeClass : addClass )( next, \"qunit-collapsed\" );\n\t\t\t});\n\n\t\t\taddEvent(b, \"dblclick\", function( e ) {\n\t\t\t\tvar target = e && e.target ? e.target : window.event.srcElement;\n\t\t\t\tif ( target.nodeName.toLowerCase() === \"span\" || target.nodeName.toLowerCase() === \"b\" ) {\n\t\t\t\t\ttarget = target.parentNode;\n\t\t\t\t}\n\t\t\t\tif ( window.location && target.nodeName.toLowerCase() === \"strong\" ) {\n\t\t\t\t\twindow.location = QUnit.url({ testNumber: test.testNumber });\n\t\t\t\t}\n\t\t\t});\n\n\t\t\t// `time` initialized at top of scope\n\t\t\ttime = document.createElement( \"span\" );\n\t\t\ttime.className = \"runtime\";\n\t\t\ttime.innerHTML = this.runtime + \" ms\";\n\n\t\t\t// `li` initialized at top of scope\n\t\t\tli = id( this.id );\n\t\t\tli.className = bad ? \"fail\" : \"pass\";\n\t\t\tli.removeChild( li.firstChild );\n\t\t\ta = li.firstChild;\n\t\t\tli.appendChild( b );\n\t\t\tli.appendChild( a );\n\t\t\tli.appendChild( time );\n\t\t\tli.appendChild( ol );\n\n\t\t} else {\n\t\t\tfor ( i = 0; i < this.assertions.length; i++ ) {\n\t\t\t\tif ( !this.assertions[i].result ) {\n\t\t\t\t\tbad++;\n\t\t\t\t\tconfig.stats.bad++;\n\t\t\t\t\tconfig.moduleStats.bad++;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\trunLoggingCallbacks( \"testDone\", QUnit, {\n\t\t\tname: this.testName,\n\t\t\tmodule: this.module,\n\t\t\tfailed: bad,\n\t\t\tpassed: this.assertions.length - bad,\n\t\t\ttotal: this.assertions.length,\n\t\t\tduration: this.runtime\n\t\t});\n\n\t\tQUnit.reset();\n\n\t\tconfig.current = undefined;\n\t},\n\n\tqueue: function() {\n\t\tvar bad,\n\t\t\ttest = this;\n\n\t\tsynchronize(function() {\n\t\t\ttest.init();\n\t\t});\n\t\tfunction run() {\n\t\t\t// each of these can by async\n\t\t\tsynchronize(function() {\n\t\t\t\ttest.setup();\n\t\t\t});\n\t\t\tsynchronize(function() {\n\t\t\t\ttest.run();\n\t\t\t});\n\t\t\tsynchronize(function() {\n\t\t\t\ttest.teardown();\n\t\t\t});\n\t\t\tsynchronize(function() {\n\t\t\t\ttest.finish();\n\t\t\t});\n\t\t}\n\n\t\t// `bad` initialized at top of scope\n\t\t// defer when previous test run passed, if storage is available\n\t\tbad = QUnit.config.reorder && defined.sessionStorage &&\n\t\t\t\t\t\t+sessionStorage.getItem( \"qunit-test-\" + this.module + \"-\" + this.testName );\n\n\t\tif ( bad ) {\n\t\t\trun();\n\t\t} else {\n\t\t\tsynchronize( run, true );\n\t\t}\n\t}\n};\n\n// Root QUnit object.\n// `QUnit` initialized at top of scope\nQUnit = {\n\n\t// call on start of module test to prepend name to all tests\n\tmodule: function( name, testEnvironment ) {\n\t\tconfig.currentModule = name;\n\t\tconfig.currentModuleTestEnvironment = testEnvironment;\n\t\tconfig.modules[name] = true;\n\t},\n\n\tasyncTest: function( testName, expected, callback ) {\n\t\tif ( arguments.length === 2 ) {\n\t\t\tcallback = expected;\n\t\t\texpected = null;\n\t\t}\n\n\t\tQUnit.test( testName, expected, callback, true );\n\t},\n\n\ttest: function( testName, expected, callback, async ) {\n\t\tvar test,\n\t\t\tnameHtml = \"<span class='test-name'>\" + escapeText( testName ) + \"</span>\";\n\n\t\tif ( arguments.length === 2 ) {\n\t\t\tcallback = expected;\n\t\t\texpected = null;\n\t\t}\n\n\t\tif ( config.currentModule ) {\n\t\t\tnameHtml = \"<span class='module-name'>\" + escapeText( config.currentModule ) + \"</span>: \" + nameHtml;\n\t\t}\n\n\t\ttest = new Test({\n\t\t\tnameHtml: nameHtml,\n\t\t\ttestName: testName,\n\t\t\texpected: expected,\n\t\t\tasync: async,\n\t\t\tcallback: callback,\n\t\t\tmodule: config.currentModule,\n\t\t\tmoduleTestEnvironment: config.currentModuleTestEnvironment,\n\t\t\tstack: sourceFromStacktrace( 2 )\n\t\t});\n\n\t\tif ( !validTest( test ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\ttest.queue();\n\t},\n\n\t// Specify the number of expected assertions to guarantee that failed test (no assertions are run at all) don't slip through.\n\texpect: function( asserts ) {\n\t\tif (arguments.length === 1) {\n\t\t\tconfig.current.expected = asserts;\n\t\t} else {\n\t\t\treturn config.current.expected;\n\t\t}\n\t},\n\n\tstart: function( count ) {\n\t\t// QUnit hasn't been initialized yet.\n\t\t// Note: RequireJS (et al) may delay onLoad\n\t\tif ( config.semaphore === undefined ) {\n\t\t\tQUnit.begin(function() {\n\t\t\t\t// This is triggered at the top of QUnit.load, push start() to the event loop, to allow QUnit.load to finish first\n\t\t\t\tsetTimeout(function() {\n\t\t\t\t\tQUnit.start( count );\n\t\t\t\t});\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\n\t\tconfig.semaphore -= count || 1;\n\t\t// don't start until equal number of stop-calls\n\t\tif ( config.semaphore > 0 ) {\n\t\t\treturn;\n\t\t}\n\t\t// ignore if start is called more often then stop\n\t\tif ( config.semaphore < 0 ) {\n\t\t\tconfig.semaphore = 0;\n\t\t\tQUnit.pushFailure( \"Called start() while already started (QUnit.config.semaphore was 0 already)\", null, sourceFromStacktrace(2) );\n\t\t\treturn;\n\t\t}\n\t\t// A slight delay, to avoid any current callbacks\n\t\tif ( defined.setTimeout ) {\n\t\t\tsetTimeout(function() {\n\t\t\t\tif ( config.semaphore > 0 ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tif ( config.timeout ) {\n\t\t\t\t\tclearTimeout( config.timeout );\n\t\t\t\t}\n\n\t\t\t\tconfig.blocking = false;\n\t\t\t\tprocess( true );\n\t\t\t}, 13);\n\t\t} else {\n\t\t\tconfig.blocking = false;\n\t\t\tprocess( true );\n\t\t}\n\t},\n\n\tstop: function( count ) {\n\t\tconfig.semaphore += count || 1;\n\t\tconfig.blocking = true;\n\n\t\tif ( config.testTimeout && defined.setTimeout ) {\n\t\t\tclearTimeout( config.timeout );\n\t\t\tconfig.timeout = setTimeout(function() {\n\t\t\t\tQUnit.ok( false, \"Test timed out\" );\n\t\t\t\tconfig.semaphore = 1;\n\t\t\t\tQUnit.start();\n\t\t\t}, config.testTimeout );\n\t\t}\n\t}\n};\n\n// `assert` initialized at top of scope\n// Assert helpers\n// All of these must either call QUnit.push() or manually do:\n// - runLoggingCallbacks( \"log\", .. );\n// - config.current.assertions.push({ .. });\n// We attach it to the QUnit object *after* we expose the public API,\n// otherwise `assert` will become a global variable in browsers (#341).\nassert = {\n\t/**\n\t * Asserts rough true-ish result.\n\t * @name ok\n\t * @function\n\t * @example ok( \"asdfasdf\".length > 5, \"There must be at least 5 chars\" );\n\t */\n\tok: function( result, msg ) {\n\t\tif ( !config.current ) {\n\t\t\tthrow new Error( \"ok() assertion outside test context, was \" + sourceFromStacktrace(2) );\n\t\t}\n\t\tresult = !!result;\n\t\tmsg = msg || (result ? \"okay\" : \"failed\" );\n\n\t\tvar source,\n\t\t\tdetails = {\n\t\t\t\tmodule: config.current.module,\n\t\t\t\tname: config.current.testName,\n\t\t\t\tresult: result,\n\t\t\t\tmessage: msg\n\t\t\t};\n\n\t\tmsg = \"<span class='test-message'>\" + escapeText( msg ) + \"</span>\";\n\n\t\tif ( !result ) {\n\t\t\tsource = sourceFromStacktrace( 2 );\n\t\t\tif ( source ) {\n\t\t\t\tdetails.source = source;\n\t\t\t\tmsg += \"<table><tr class='test-source'><th>Source: </th><td><pre>\" + escapeText( source ) + \"</pre></td></tr></table>\";\n\t\t\t}\n\t\t}\n\t\trunLoggingCallbacks( \"log\", QUnit, details );\n\t\tconfig.current.assertions.push({\n\t\t\tresult: result,\n\t\t\tmessage: msg\n\t\t});\n\t},\n\n\t/**\n\t * Assert that the first two arguments are equal, with an optional message.\n\t * Prints out both actual and expected values.\n\t * @name equal\n\t * @function\n\t * @example equal( format( \"Received {0} bytes.\", 2), \"Received 2 bytes.\", \"format() replaces {0} with next argument\" );\n\t */\n\tequal: function( actual, expected, message ) {\n\t\t/*jshint eqeqeq:false */\n\t\tQUnit.push( expected == actual, actual, expected, message );\n\t},\n\n\t/**\n\t * @name notEqual\n\t * @function\n\t */\n\tnotEqual: function( actual, expected, message ) {\n\t\t/*jshint eqeqeq:false */\n\t\tQUnit.push( expected != actual, actual, expected, message );\n\t},\n\n\t/**\n\t * @name propEqual\n\t * @function\n\t */\n\tpropEqual: function( actual, expected, message ) {\n\t\tactual = objectValues(actual);\n\t\texpected = objectValues(expected);\n\t\tQUnit.push( QUnit.equiv(actual, expected), actual, expected, message );\n\t},\n\n\t/**\n\t * @name notPropEqual\n\t * @function\n\t */\n\tnotPropEqual: function( actual, expected, message ) {\n\t\tactual = objectValues(actual);\n\t\texpected = objectValues(expected);\n\t\tQUnit.push( !QUnit.equiv(actual, expected), actual, expected, message );\n\t},\n\n\t/**\n\t * @name deepEqual\n\t * @function\n\t */\n\tdeepEqual: function( actual, expected, message ) {\n\t\tQUnit.push( QUnit.equiv(actual, expected), actual, expected, message );\n\t},\n\n\t/**\n\t * @name notDeepEqual\n\t * @function\n\t */\n\tnotDeepEqual: function( actual, expected, message ) {\n\t\tQUnit.push( !QUnit.equiv(actual, expected), actual, expected, message );\n\t},\n\n\t/**\n\t * @name strictEqual\n\t * @function\n\t */\n\tstrictEqual: function( actual, expected, message ) {\n\t\tQUnit.push( expected === actual, actual, expected, message );\n\t},\n\n\t/**\n\t * @name notStrictEqual\n\t * @function\n\t */\n\tnotStrictEqual: function( actual, expected, message ) {\n\t\tQUnit.push( expected !== actual, actual, expected, message );\n\t},\n\n\t\"throws\": function( block, expected, message ) {\n\t\tvar actual,\n\t\t\texpectedOutput = expected,\n\t\t\tok = false;\n\n\t\t// 'expected' is optional\n\t\tif ( typeof expected === \"string\" ) {\n\t\t\tmessage = expected;\n\t\t\texpected = null;\n\t\t}\n\n\t\tconfig.current.ignoreGlobalErrors = true;\n\t\ttry {\n\t\t\tblock.call( config.current.testEnvironment );\n\t\t} catch (e) {\n\t\t\tactual = e;\n\t\t}\n\t\tconfig.current.ignoreGlobalErrors = false;\n\n\t\tif ( actual ) {\n\t\t\t// we don't want to validate thrown error\n\t\t\tif ( !expected ) {\n\t\t\t\tok = true;\n\t\t\t\texpectedOutput = null;\n\t\t\t// expected is a regexp\n\t\t\t} else if ( QUnit.objectType( expected ) === \"regexp\" ) {\n\t\t\t\tok = expected.test( errorString( actual ) );\n\t\t\t// expected is a constructor\n\t\t\t} else if ( actual instanceof expected ) {\n\t\t\t\tok = true;\n\t\t\t// expected is a validation function which returns true is validation passed\n\t\t\t} else if ( expected.call( {}, actual ) === true ) {\n\t\t\t\texpectedOutput = null;\n\t\t\t\tok = true;\n\t\t\t}\n\n\t\t\tQUnit.push( ok, actual, expectedOutput, message );\n\t\t} else {\n\t\t\tQUnit.pushFailure( message, null, \"No exception was thrown.\" );\n\t\t}\n\t}\n};\n\n/**\n * @deprecated since 1.8.0\n * Kept assertion helpers in root for backwards compatibility.\n */\nextend( QUnit, assert );\n\n/**\n * @deprecated since 1.9.0\n * Kept root \"raises()\" for backwards compatibility.\n * (Note that we don't introduce assert.raises).\n */\nQUnit.raises = assert[ \"throws\" ];\n\n/**\n * @deprecated since 1.0.0, replaced with error pushes since 1.3.0\n * Kept to avoid TypeErrors for undefined methods.\n */\nQUnit.equals = function() {\n\tQUnit.push( false, false, false, \"QUnit.equals has been deprecated since 2009 (e88049a0), use QUnit.equal instead\" );\n};\nQUnit.same = function() {\n\tQUnit.push( false, false, false, \"QUnit.same has been deprecated since 2009 (e88049a0), use QUnit.deepEqual instead\" );\n};\n\n// We want access to the constructor's prototype\n(function() {\n\tfunction F() {}\n\tF.prototype = QUnit;\n\tQUnit = new F();\n\t// Make F QUnit's constructor so that we can add to the prototype later\n\tQUnit.constructor = F;\n}());\n\n/**\n * Config object: Maintain internal state\n * Later exposed as QUnit.config\n * `config` initialized at top of scope\n */\nconfig = {\n\t// The queue of tests to run\n\tqueue: [],\n\n\t// block until document ready\n\tblocking: true,\n\n\t// when enabled, show only failing tests\n\t// gets persisted through sessionStorage and can be changed in UI via checkbox\n\thidepassed: false,\n\n\t// by default, run previously failed tests first\n\t// very useful in combination with \"Hide passed tests\" checked\n\treorder: true,\n\n\t// by default, modify document.title when suite is done\n\taltertitle: true,\n\n\t// when enabled, all tests must call expect()\n\trequireExpects: false,\n\n\t// add checkboxes that are persisted in the query-string\n\t// when enabled, the id is set to `true` as a `QUnit.config` property\n\turlConfig: [\n\t\t{\n\t\t\tid: \"noglobals\",\n\t\t\tlabel: \"Check for Globals\",\n\t\t\ttooltip: \"Enabling this will test if any test introduces new properties on the `window` object. Stored as query-strings.\"\n\t\t},\n\t\t{\n\t\t\tid: \"notrycatch\",\n\t\t\tlabel: \"No try-catch\",\n\t\t\ttooltip: \"Enabling this will run tests outside of a try-catch block. Makes debugging exceptions in IE reasonable. Stored as query-strings.\"\n\t\t}\n\t],\n\n\t// Set of all modules.\n\tmodules: {},\n\n\t// logging callback queues\n\tbegin: [],\n\tdone: [],\n\tlog: [],\n\ttestStart: [],\n\ttestDone: [],\n\tmoduleStart: [],\n\tmoduleDone: []\n};\n\n// Export global variables, unless an 'exports' object exists,\n// in that case we assume we're in CommonJS (dealt with on the bottom of the script)\nif ( typeof exports === \"undefined\" ) {\n\textend( window, QUnit.constructor.prototype );\n\n\t// Expose QUnit object\n\twindow.QUnit = QUnit;\n}\n\n// Initialize more QUnit.config and QUnit.urlParams\n(function() {\n\tvar i,\n\t\tlocation = window.location || { search: \"\", protocol: \"file:\" },\n\t\tparams = location.search.slice( 1 ).split( \"&\" ),\n\t\tlength = params.length,\n\t\turlParams = {},\n\t\tcurrent;\n\n\tif ( params[ 0 ] ) {\n\t\tfor ( i = 0; i < length; i++ ) {\n\t\t\tcurrent = params[ i ].split( \"=\" );\n\t\t\tcurrent[ 0 ] = decodeURIComponent( current[ 0 ] );\n\t\t\t// allow just a key to turn on a flag, e.g., test.html?noglobals\n\t\t\tcurrent[ 1 ] = current[ 1 ] ? decodeURIComponent( current[ 1 ] ) : true;\n\t\t\turlParams[ current[ 0 ] ] = current[ 1 ];\n\t\t}\n\t}\n\n\tQUnit.urlParams = urlParams;\n\n\t// String search anywhere in moduleName+testName\n\tconfig.filter = urlParams.filter;\n\n\t// Exact match of the module name\n\tconfig.module = urlParams.module;\n\n\tconfig.testNumber = parseInt( urlParams.testNumber, 10 ) || null;\n\n\t// Figure out if we're running the tests from a server or not\n\tQUnit.isLocal = location.protocol === \"file:\";\n}());\n\n// Extend QUnit object,\n// these after set here because they should not be exposed as global functions\nextend( QUnit, {\n\tassert: assert,\n\n\tconfig: config,\n\n\t// Initialize the configuration options\n\tinit: function() {\n\t\textend( config, {\n\t\t\tstats: { all: 0, bad: 0 },\n\t\t\tmoduleStats: { all: 0, bad: 0 },\n\t\t\tstarted: +new Date(),\n\t\t\tupdateRate: 1000,\n\t\t\tblocking: false,\n\t\t\tautostart: true,\n\t\t\tautorun: false,\n\t\t\tfilter: \"\",\n\t\t\tqueue: [],\n\t\t\tsemaphore: 1\n\t\t});\n\n\t\tvar tests, banner, result,\n\t\t\tqunit = id( \"qunit\" );\n\n\t\tif ( qunit ) {\n\t\t\tqunit.innerHTML =\n\t\t\t\t\"<h1 id='qunit-header'>\" + escapeText( document.title ) + \"</h1>\" +\n\t\t\t\t\"<h2 id='qunit-banner'></h2>\" +\n\t\t\t\t\"<div id='qunit-testrunner-toolbar'></div>\" +\n\t\t\t\t\"<h2 id='qunit-userAgent'></h2>\" +\n\t\t\t\t\"<ol id='qunit-tests'></ol>\";\n\t\t}\n\n\t\ttests = id( \"qunit-tests\" );\n\t\tbanner = id( \"qunit-banner\" );\n\t\tresult = id( \"qunit-testresult\" );\n\n\t\tif ( tests ) {\n\t\t\ttests.innerHTML = \"\";\n\t\t}\n\n\t\tif ( banner ) {\n\t\t\tbanner.className = \"\";\n\t\t}\n\n\t\tif ( result ) {\n\t\t\tresult.parentNode.removeChild( result );\n\t\t}\n\n\t\tif ( tests ) {\n\t\t\tresult = document.createElement( \"p\" );\n\t\t\tresult.id = \"qunit-testresult\";\n\t\t\tresult.className = \"result\";\n\t\t\ttests.parentNode.insertBefore( result, tests );\n\t\t\tresult.innerHTML = \"Running...<br/>&nbsp;\";\n\t\t}\n\t},\n\n\t// Resets the test setup. Useful for tests that modify the DOM.\n\t/*\n\tDEPRECATED: Use multiple tests instead of resetting inside a test.\n\tUse testStart or testDone for custom cleanup.\n\tThis method will throw an error in 2.0, and will be removed in 2.1\n\t*/\n\treset: function() {\n\t\tvar fixture = id( \"qunit-fixture\" );\n\t\tif ( fixture ) {\n\t\t\tfixture.innerHTML = config.fixture;\n\t\t}\n\t},\n\n\t// Trigger an event on an element.\n\t// @example triggerEvent( document.body, \"click\" );\n\ttriggerEvent: function( elem, type, event ) {\n\t\tif ( document.createEvent ) {\n\t\t\tevent = document.createEvent( \"MouseEvents\" );\n\t\t\tevent.initMouseEvent(type, true, true, elem.ownerDocument.defaultView,\n\t\t\t\t0, 0, 0, 0, 0, false, false, false, false, 0, null);\n\n\t\t\telem.dispatchEvent( event );\n\t\t} else if ( elem.fireEvent ) {\n\t\t\telem.fireEvent( \"on\" + type );\n\t\t}\n\t},\n\n\t// Safe object type checking\n\tis: function( type, obj ) {\n\t\treturn QUnit.objectType( obj ) === type;\n\t},\n\n\tobjectType: function( obj ) {\n\t\tif ( typeof obj === \"undefined\" ) {\n\t\t\t\treturn \"undefined\";\n\t\t// consider: typeof null === object\n\t\t}\n\t\tif ( obj === null ) {\n\t\t\t\treturn \"null\";\n\t\t}\n\n\t\tvar match = toString.call( obj ).match(/^\\[object\\s(.*)\\]$/),\n\t\t\ttype = match && match[1] || \"\";\n\n\t\tswitch ( type ) {\n\t\t\tcase \"Number\":\n\t\t\t\tif ( isNaN(obj) ) {\n\t\t\t\t\treturn \"nan\";\n\t\t\t\t}\n\t\t\t\treturn \"number\";\n\t\t\tcase \"String\":\n\t\t\tcase \"Boolean\":\n\t\t\tcase \"Array\":\n\t\t\tcase \"Date\":\n\t\t\tcase \"RegExp\":\n\t\t\tcase \"Function\":\n\t\t\t\treturn type.toLowerCase();\n\t\t}\n\t\tif ( typeof obj === \"object\" ) {\n\t\t\treturn \"object\";\n\t\t}\n\t\treturn undefined;\n\t},\n\n\tpush: function( result, actual, expected, message ) {\n\t\tif ( !config.current ) {\n\t\t\tthrow new Error( \"assertion outside test context, was \" + sourceFromStacktrace() );\n\t\t}\n\n\t\tvar output, source,\n\t\t\tdetails = {\n\t\t\t\tmodule: config.current.module,\n\t\t\t\tname: config.current.testName,\n\t\t\t\tresult: result,\n\t\t\t\tmessage: message,\n\t\t\t\tactual: actual,\n\t\t\t\texpected: expected\n\t\t\t};\n\n\t\tmessage = escapeText( message ) || ( result ? \"okay\" : \"failed\" );\n\t\tmessage = \"<span class='test-message'>\" + message + \"</span>\";\n\t\toutput = message;\n\n\t\tif ( !result ) {\n\t\t\texpected = escapeText( QUnit.jsDump.parse(expected) );\n\t\t\tactual = escapeText( QUnit.jsDump.parse(actual) );\n\t\t\toutput += \"<table><tr class='test-expected'><th>Expected: </th><td><pre>\" + expected + \"</pre></td></tr>\";\n\n\t\t\tif ( actual !== expected ) {\n\t\t\t\toutput += \"<tr class='test-actual'><th>Result: </th><td><pre>\" + actual + \"</pre></td></tr>\";\n\t\t\t\toutput += \"<tr class='test-diff'><th>Diff: </th><td><pre>\" + QUnit.diff( expected, actual ) + \"</pre></td></tr>\";\n\t\t\t}\n\n\t\t\tsource = sourceFromStacktrace();\n\n\t\t\tif ( source ) {\n\t\t\t\tdetails.source = source;\n\t\t\t\toutput += \"<tr class='test-source'><th>Source: </th><td><pre>\" + escapeText( source ) + \"</pre></td></tr>\";\n\t\t\t}\n\n\t\t\toutput += \"</table>\";\n\t\t}\n\n\t\trunLoggingCallbacks( \"log\", QUnit, details );\n\n\t\tconfig.current.assertions.push({\n\t\t\tresult: !!result,\n\t\t\tmessage: output\n\t\t});\n\t},\n\n\tpushFailure: function( message, source, actual ) {\n\t\tif ( !config.current ) {\n\t\t\tthrow new Error( \"pushFailure() assertion outside test context, was \" + sourceFromStacktrace(2) );\n\t\t}\n\n\t\tvar output,\n\t\t\tdetails = {\n\t\t\t\tmodule: config.current.module,\n\t\t\t\tname: config.current.testName,\n\t\t\t\tresult: false,\n\t\t\t\tmessage: message\n\t\t\t};\n\n\t\tmessage = escapeText( message ) || \"error\";\n\t\tmessage = \"<span class='test-message'>\" + message + \"</span>\";\n\t\toutput = message;\n\n\t\toutput += \"<table>\";\n\n\t\tif ( actual ) {\n\t\t\toutput += \"<tr class='test-actual'><th>Result: </th><td><pre>\" + escapeText( actual ) + \"</pre></td></tr>\";\n\t\t}\n\n\t\tif ( source ) {\n\t\t\tdetails.source = source;\n\t\t\toutput += \"<tr class='test-source'><th>Source: </th><td><pre>\" + escapeText( source ) + \"</pre></td></tr>\";\n\t\t}\n\n\t\toutput += \"</table>\";\n\n\t\trunLoggingCallbacks( \"log\", QUnit, details );\n\n\t\tconfig.current.assertions.push({\n\t\t\tresult: false,\n\t\t\tmessage: output\n\t\t});\n\t},\n\n\turl: function( params ) {\n\t\tparams = extend( extend( {}, QUnit.urlParams ), params );\n\t\tvar key,\n\t\t\tquerystring = \"?\";\n\n\t\tfor ( key in params ) {\n\t\t\tif ( hasOwn.call( params, key ) ) {\n\t\t\t\tquerystring += encodeURIComponent( key ) + \"=\" +\n\t\t\t\t\tencodeURIComponent( params[ key ] ) + \"&\";\n\t\t\t}\n\t\t}\n\t\treturn window.location.protocol + \"//\" + window.location.host +\n\t\t\twindow.location.pathname + querystring.slice( 0, -1 );\n\t},\n\n\textend: extend,\n\tid: id,\n\taddEvent: addEvent,\n\taddClass: addClass,\n\thasClass: hasClass,\n\tremoveClass: removeClass\n\t// load, equiv, jsDump, diff: Attached later\n});\n\n/**\n * @deprecated: Created for backwards compatibility with test runner that set the hook function\n * into QUnit.{hook}, instead of invoking it and passing the hook function.\n * QUnit.constructor is set to the empty F() above so that we can add to it's prototype here.\n * Doing this allows us to tell if the following methods have been overwritten on the actual\n * QUnit object.\n */\nextend( QUnit.constructor.prototype, {\n\n\t// Logging callbacks; all receive a single argument with the listed properties\n\t// run test/logs.html for any related changes\n\tbegin: registerLoggingCallback( \"begin\" ),\n\n\t// done: { failed, passed, total, runtime }\n\tdone: registerLoggingCallback( \"done\" ),\n\n\t// log: { result, actual, expected, message }\n\tlog: registerLoggingCallback( \"log\" ),\n\n\t// testStart: { name }\n\ttestStart: registerLoggingCallback( \"testStart\" ),\n\n\t// testDone: { name, failed, passed, total, duration }\n\ttestDone: registerLoggingCallback( \"testDone\" ),\n\n\t// moduleStart: { name }\n\tmoduleStart: registerLoggingCallback( \"moduleStart\" ),\n\n\t// moduleDone: { name, failed, passed, total }\n\tmoduleDone: registerLoggingCallback( \"moduleDone\" )\n});\n\nif ( typeof document === \"undefined\" || document.readyState === \"complete\" ) {\n\tconfig.autorun = true;\n}\n\nQUnit.load = function() {\n\trunLoggingCallbacks( \"begin\", QUnit, {} );\n\n\t// Initialize the config, saving the execution queue\n\tvar banner, filter, i, label, len, main, ol, toolbar, userAgent, val,\n\t\turlConfigCheckboxesContainer, urlConfigCheckboxes, moduleFilter,\n\t\tnumModules = 0,\n\t\tmoduleNames = [],\n\t\tmoduleFilterHtml = \"\",\n\t\turlConfigHtml = \"\",\n\t\toldconfig = extend( {}, config );\n\n\tQUnit.init();\n\textend(config, oldconfig);\n\n\tconfig.blocking = false;\n\n\tlen = config.urlConfig.length;\n\n\tfor ( i = 0; i < len; i++ ) {\n\t\tval = config.urlConfig[i];\n\t\tif ( typeof val === \"string\" ) {\n\t\t\tval = {\n\t\t\t\tid: val,\n\t\t\t\tlabel: val,\n\t\t\t\ttooltip: \"[no tooltip available]\"\n\t\t\t};\n\t\t}\n\t\tconfig[ val.id ] = QUnit.urlParams[ val.id ];\n\t\turlConfigHtml += \"<input id='qunit-urlconfig-\" + escapeText( val.id ) +\n\t\t\t\"' name='\" + escapeText( val.id ) +\n\t\t\t\"' type='checkbox'\" + ( config[ val.id ] ? \" checked='checked'\" : \"\" ) +\n\t\t\t\" title='\" + escapeText( val.tooltip ) +\n\t\t\t\"'><label for='qunit-urlconfig-\" + escapeText( val.id ) +\n\t\t\t\"' title='\" + escapeText( val.tooltip ) + \"'>\" + val.label + \"</label>\";\n\t}\n\tfor ( i in config.modules ) {\n\t\tif ( config.modules.hasOwnProperty( i ) ) {\n\t\t\tmoduleNames.push(i);\n\t\t}\n\t}\n\tnumModules = moduleNames.length;\n\tmoduleNames.sort( function( a, b ) {\n\t\treturn a.localeCompare( b );\n\t});\n\tmoduleFilterHtml += \"<label for='qunit-modulefilter'>Module: </label><select id='qunit-modulefilter' name='modulefilter'><option value='' \" +\n\t\t( config.module === undefined  ? \"selected='selected'\" : \"\" ) +\n\t\t\">< All Modules ></option>\";\n\n\n\tfor ( i = 0; i < numModules; i++) {\n\t\t\tmoduleFilterHtml += \"<option value='\" + escapeText( encodeURIComponent(moduleNames[i]) ) + \"' \" +\n\t\t\t\t( config.module === moduleNames[i] ? \"selected='selected'\" : \"\" ) +\n\t\t\t\t\">\" + escapeText(moduleNames[i]) + \"</option>\";\n\t}\n\tmoduleFilterHtml += \"</select>\";\n\n\t// `userAgent` initialized at top of scope\n\tuserAgent = id( \"qunit-userAgent\" );\n\tif ( userAgent ) {\n\t\tuserAgent.innerHTML = navigator.userAgent;\n\t}\n\n\t// `banner` initialized at top of scope\n\tbanner = id( \"qunit-header\" );\n\tif ( banner ) {\n\t\tbanner.innerHTML = \"<a href='\" + QUnit.url({ filter: undefined, module: undefined, testNumber: undefined }) + \"'>\" + banner.innerHTML + \"</a> \";\n\t}\n\n\t// `toolbar` initialized at top of scope\n\ttoolbar = id( \"qunit-testrunner-toolbar\" );\n\tif ( toolbar ) {\n\t\t// `filter` initialized at top of scope\n\t\tfilter = document.createElement( \"input\" );\n\t\tfilter.type = \"checkbox\";\n\t\tfilter.id = \"qunit-filter-pass\";\n\n\t\taddEvent( filter, \"click\", function() {\n\t\t\tvar tmp,\n\t\t\t\tol = document.getElementById( \"qunit-tests\" );\n\n\t\t\tif ( filter.checked ) {\n\t\t\t\tol.className = ol.className + \" hidepass\";\n\t\t\t} else {\n\t\t\t\ttmp = \" \" + ol.className.replace( /[\\n\\t\\r]/g, \" \" ) + \" \";\n\t\t\t\tol.className = tmp.replace( / hidepass /, \" \" );\n\t\t\t}\n\t\t\tif ( defined.sessionStorage ) {\n\t\t\t\tif (filter.checked) {\n\t\t\t\t\tsessionStorage.setItem( \"qunit-filter-passed-tests\", \"true\" );\n\t\t\t\t} else {\n\t\t\t\t\tsessionStorage.removeItem( \"qunit-filter-passed-tests\" );\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\tif ( config.hidepassed || defined.sessionStorage && sessionStorage.getItem( \"qunit-filter-passed-tests\" ) ) {\n\t\t\tfilter.checked = true;\n\t\t\t// `ol` initialized at top of scope\n\t\t\tol = document.getElementById( \"qunit-tests\" );\n\t\t\tol.className = ol.className + \" hidepass\";\n\t\t}\n\t\ttoolbar.appendChild( filter );\n\n\t\t// `label` initialized at top of scope\n\t\tlabel = document.createElement( \"label\" );\n\t\tlabel.setAttribute( \"for\", \"qunit-filter-pass\" );\n\t\tlabel.setAttribute( \"title\", \"Only show tests and assertions that fail. Stored in sessionStorage.\" );\n\t\tlabel.innerHTML = \"Hide passed tests\";\n\t\ttoolbar.appendChild( label );\n\n\t\turlConfigCheckboxesContainer = document.createElement(\"span\");\n\t\turlConfigCheckboxesContainer.innerHTML = urlConfigHtml;\n\t\turlConfigCheckboxes = urlConfigCheckboxesContainer.getElementsByTagName(\"input\");\n\t\t// For oldIE support:\n\t\t// * Add handlers to the individual elements instead of the container\n\t\t// * Use \"click\" instead of \"change\"\n\t\t// * Fallback from event.target to event.srcElement\n\t\taddEvents( urlConfigCheckboxes, \"click\", function( event ) {\n\t\t\tvar params = {},\n\t\t\t\ttarget = event.target || event.srcElement;\n\t\t\tparams[ target.name ] = target.checked ? true : undefined;\n\t\t\twindow.location = QUnit.url( params );\n\t\t});\n\t\ttoolbar.appendChild( urlConfigCheckboxesContainer );\n\n\t\tif (numModules > 1) {\n\t\t\tmoduleFilter = document.createElement( \"span\" );\n\t\t\tmoduleFilter.setAttribute( \"id\", \"qunit-modulefilter-container\" );\n\t\t\tmoduleFilter.innerHTML = moduleFilterHtml;\n\t\t\taddEvent( moduleFilter.lastChild, \"change\", function() {\n\t\t\t\tvar selectBox = moduleFilter.getElementsByTagName(\"select\")[0],\n\t\t\t\t\tselectedModule = decodeURIComponent(selectBox.options[selectBox.selectedIndex].value);\n\n\t\t\t\twindow.location = QUnit.url({\n\t\t\t\t\tmodule: ( selectedModule === \"\" ) ? undefined : selectedModule,\n\t\t\t\t\t// Remove any existing filters\n\t\t\t\t\tfilter: undefined,\n\t\t\t\t\ttestNumber: undefined\n\t\t\t\t});\n\t\t\t});\n\t\t\ttoolbar.appendChild(moduleFilter);\n\t\t}\n\t}\n\n\t// `main` initialized at top of scope\n\tmain = id( \"qunit-fixture\" );\n\tif ( main ) {\n\t\tconfig.fixture = main.innerHTML;\n\t}\n\n\tif ( config.autostart ) {\n\t\tQUnit.start();\n\t}\n};\n\naddEvent( window, \"load\", QUnit.load );\n\n// `onErrorFnPrev` initialized at top of scope\n// Preserve other handlers\nonErrorFnPrev = window.onerror;\n\n// Cover uncaught exceptions\n// Returning true will suppress the default browser handler,\n// returning false will let it run.\nwindow.onerror = function ( error, filePath, linerNr ) {\n\tvar ret = false;\n\tif ( onErrorFnPrev ) {\n\t\tret = onErrorFnPrev( error, filePath, linerNr );\n\t}\n\n\t// Treat return value as window.onerror itself does,\n\t// Only do our handling if not suppressed.\n\tif ( ret !== true ) {\n\t\tif ( QUnit.config.current ) {\n\t\t\tif ( QUnit.config.current.ignoreGlobalErrors ) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\tQUnit.pushFailure( error, filePath + \":\" + linerNr );\n\t\t} else {\n\t\t\tQUnit.test( \"global failure\", extend( function() {\n\t\t\t\tQUnit.pushFailure( error, filePath + \":\" + linerNr );\n\t\t\t}, { validTest: validTest } ) );\n\t\t}\n\t\treturn false;\n\t}\n\n\treturn ret;\n};\n\nfunction done() {\n\tconfig.autorun = true;\n\n\t// Log the last module results\n\tif ( config.currentModule ) {\n\t\trunLoggingCallbacks( \"moduleDone\", QUnit, {\n\t\t\tname: config.currentModule,\n\t\t\tfailed: config.moduleStats.bad,\n\t\t\tpassed: config.moduleStats.all - config.moduleStats.bad,\n\t\t\ttotal: config.moduleStats.all\n\t\t});\n\t}\n\tdelete config.previousModule;\n\n\tvar i, key,\n\t\tbanner = id( \"qunit-banner\" ),\n\t\ttests = id( \"qunit-tests\" ),\n\t\truntime = +new Date() - config.started,\n\t\tpassed = config.stats.all - config.stats.bad,\n\t\thtml = [\n\t\t\t\"Tests completed in \",\n\t\t\truntime,\n\t\t\t\" milliseconds.<br/>\",\n\t\t\t\"<span class='passed'>\",\n\t\t\tpassed,\n\t\t\t\"</span> assertions of <span class='total'>\",\n\t\t\tconfig.stats.all,\n\t\t\t\"</span> passed, <span class='failed'>\",\n\t\t\tconfig.stats.bad,\n\t\t\t\"</span> failed.\"\n\t\t].join( \"\" );\n\n\tif ( banner ) {\n\t\tbanner.className = ( config.stats.bad ? \"qunit-fail\" : \"qunit-pass\" );\n\t}\n\n\tif ( tests ) {\n\t\tid( \"qunit-testresult\" ).innerHTML = html;\n\t}\n\n\tif ( config.altertitle && typeof document !== \"undefined\" && document.title ) {\n\t\t// show ✖ for good, ✔ for bad suite result in title\n\t\t// use escape sequences in case file gets loaded with non-utf-8-charset\n\t\tdocument.title = [\n\t\t\t( config.stats.bad ? \"\\u2716\" : \"\\u2714\" ),\n\t\t\tdocument.title.replace( /^[\\u2714\\u2716] /i, \"\" )\n\t\t].join( \" \" );\n\t}\n\n\t// clear own sessionStorage items if all tests passed\n\tif ( config.reorder && defined.sessionStorage && config.stats.bad === 0 ) {\n\t\t// `key` & `i` initialized at top of scope\n\t\tfor ( i = 0; i < sessionStorage.length; i++ ) {\n\t\t\tkey = sessionStorage.key( i++ );\n\t\t\tif ( key.indexOf( \"qunit-test-\" ) === 0 ) {\n\t\t\t\tsessionStorage.removeItem( key );\n\t\t\t}\n\t\t}\n\t}\n\n\t// scroll back to top to show results\n\tif ( window.scrollTo ) {\n\t\twindow.scrollTo(0, 0);\n\t}\n\n\trunLoggingCallbacks( \"done\", QUnit, {\n\t\tfailed: config.stats.bad,\n\t\tpassed: passed,\n\t\ttotal: config.stats.all,\n\t\truntime: runtime\n\t});\n}\n\n/** @return Boolean: true if this test should be ran */\nfunction validTest( test ) {\n\tvar include,\n\t\tfilter = config.filter && config.filter.toLowerCase(),\n\t\tmodule = config.module && config.module.toLowerCase(),\n\t\tfullName = (test.module + \": \" + test.testName).toLowerCase();\n\n\t// Internally-generated tests are always valid\n\tif ( test.callback && test.callback.validTest === validTest ) {\n\t\tdelete test.callback.validTest;\n\t\treturn true;\n\t}\n\n\tif ( config.testNumber ) {\n\t\treturn test.testNumber === config.testNumber;\n\t}\n\n\tif ( module && ( !test.module || test.module.toLowerCase() !== module ) ) {\n\t\treturn false;\n\t}\n\n\tif ( !filter ) {\n\t\treturn true;\n\t}\n\n\tinclude = filter.charAt( 0 ) !== \"!\";\n\tif ( !include ) {\n\t\tfilter = filter.slice( 1 );\n\t}\n\n\t// If the filter matches, we need to honour include\n\tif ( fullName.indexOf( filter ) !== -1 ) {\n\t\treturn include;\n\t}\n\n\t// Otherwise, do the opposite\n\treturn !include;\n}\n\n// so far supports only Firefox, Chrome and Opera (buggy), Safari (for real exceptions)\n// Later Safari and IE10 are supposed to support error.stack as well\n// See also https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error/Stack\nfunction extractStacktrace( e, offset ) {\n\toffset = offset === undefined ? 3 : offset;\n\n\tvar stack, include, i;\n\n\tif ( e.stacktrace ) {\n\t\t// Opera\n\t\treturn e.stacktrace.split( \"\\n\" )[ offset + 3 ];\n\t} else if ( e.stack ) {\n\t\t// Firefox, Chrome\n\t\tstack = e.stack.split( \"\\n\" );\n\t\tif (/^error$/i.test( stack[0] ) ) {\n\t\t\tstack.shift();\n\t\t}\n\t\tif ( fileName ) {\n\t\t\tinclude = [];\n\t\t\tfor ( i = offset; i < stack.length; i++ ) {\n\t\t\t\tif ( stack[ i ].indexOf( fileName ) !== -1 ) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tinclude.push( stack[ i ] );\n\t\t\t}\n\t\t\tif ( include.length ) {\n\t\t\t\treturn include.join( \"\\n\" );\n\t\t\t}\n\t\t}\n\t\treturn stack[ offset ];\n\t} else if ( e.sourceURL ) {\n\t\t// Safari, PhantomJS\n\t\t// hopefully one day Safari provides actual stacktraces\n\t\t// exclude useless self-reference for generated Error objects\n\t\tif ( /qunit.js$/.test( e.sourceURL ) ) {\n\t\t\treturn;\n\t\t}\n\t\t// for actual exceptions, this is useful\n\t\treturn e.sourceURL + \":\" + e.line;\n\t}\n}\nfunction sourceFromStacktrace( offset ) {\n\ttry {\n\t\tthrow new Error();\n\t} catch ( e ) {\n\t\treturn extractStacktrace( e, offset );\n\t}\n}\n\n/**\n * Escape text for attribute or text content.\n */\nfunction escapeText( s ) {\n\tif ( !s ) {\n\t\treturn \"\";\n\t}\n\ts = s + \"\";\n\t// Both single quotes and double quotes (for attributes)\n\treturn s.replace( /['\"<>&]/g, function( s ) {\n\t\tswitch( s ) {\n\t\t\tcase \"'\":\n\t\t\t\treturn \"&#039;\";\n\t\t\tcase \"\\\"\":\n\t\t\t\treturn \"&quot;\";\n\t\t\tcase \"<\":\n\t\t\t\treturn \"&lt;\";\n\t\t\tcase \">\":\n\t\t\t\treturn \"&gt;\";\n\t\t\tcase \"&\":\n\t\t\t\treturn \"&amp;\";\n\t\t}\n\t});\n}\n\nfunction synchronize( callback, last ) {\n\tconfig.queue.push( callback );\n\n\tif ( config.autorun && !config.blocking ) {\n\t\tprocess( last );\n\t}\n}\n\nfunction process( last ) {\n\tfunction next() {\n\t\tprocess( last );\n\t}\n\tvar start = new Date().getTime();\n\tconfig.depth = config.depth ? config.depth + 1 : 1;\n\n\twhile ( config.queue.length && !config.blocking ) {\n\t\tif ( !defined.setTimeout || config.updateRate <= 0 || ( ( new Date().getTime() - start ) < config.updateRate ) ) {\n\t\t\tconfig.queue.shift()();\n\t\t} else {\n\t\t\tsetTimeout( next, 13 );\n\t\t\tbreak;\n\t\t}\n\t}\n\tconfig.depth--;\n\tif ( last && !config.blocking && !config.queue.length && config.depth === 0 ) {\n\t\tdone();\n\t}\n}\n\nfunction saveGlobal() {\n\tconfig.pollution = [];\n\n\tif ( config.noglobals ) {\n\t\tfor ( var key in window ) {\n\t\t\tif ( hasOwn.call( window, key ) ) {\n\t\t\t\t// in Opera sometimes DOM element ids show up here, ignore them\n\t\t\t\tif ( /^qunit-test-output/.test( key ) ) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tconfig.pollution.push( key );\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunction checkPollution() {\n\tvar newGlobals,\n\t\tdeletedGlobals,\n\t\told = config.pollution;\n\n\tsaveGlobal();\n\n\tnewGlobals = diff( config.pollution, old );\n\tif ( newGlobals.length > 0 ) {\n\t\tQUnit.pushFailure( \"Introduced global variable(s): \" + newGlobals.join(\", \") );\n\t}\n\n\tdeletedGlobals = diff( old, config.pollution );\n\tif ( deletedGlobals.length > 0 ) {\n\t\tQUnit.pushFailure( \"Deleted global variable(s): \" + deletedGlobals.join(\", \") );\n\t}\n}\n\n// returns a new Array with the elements that are in a but not in b\nfunction diff( a, b ) {\n\tvar i, j,\n\t\tresult = a.slice();\n\n\tfor ( i = 0; i < result.length; i++ ) {\n\t\tfor ( j = 0; j < b.length; j++ ) {\n\t\t\tif ( result[i] === b[j] ) {\n\t\t\t\tresult.splice( i, 1 );\n\t\t\t\ti--;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\treturn result;\n}\n\nfunction extend( a, b ) {\n\tfor ( var prop in b ) {\n\t\tif ( hasOwn.call( b, prop ) ) {\n\t\t\t// Avoid \"Member not found\" error in IE8 caused by messing with window.constructor\n\t\t\tif ( !( prop === \"constructor\" && a === window ) ) {\n\t\t\t\tif ( b[ prop ] === undefined ) {\n\t\t\t\t\tdelete a[ prop ];\n\t\t\t\t} else {\n\t\t\t\t\ta[ prop ] = b[ prop ];\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn a;\n}\n\n/**\n * @param {HTMLElement} elem\n * @param {string} type\n * @param {Function} fn\n */\nfunction addEvent( elem, type, fn ) {\n\t// Standards-based browsers\n\tif ( elem.addEventListener ) {\n\t\telem.addEventListener( type, fn, false );\n\t// IE\n\t} else {\n\t\telem.attachEvent( \"on\" + type, fn );\n\t}\n}\n\n/**\n * @param {Array|NodeList} elems\n * @param {string} type\n * @param {Function} fn\n */\nfunction addEvents( elems, type, fn ) {\n\tvar i = elems.length;\n\twhile ( i-- ) {\n\t\taddEvent( elems[i], type, fn );\n\t}\n}\n\nfunction hasClass( elem, name ) {\n\treturn (\" \" + elem.className + \" \").indexOf(\" \" + name + \" \") > -1;\n}\n\nfunction addClass( elem, name ) {\n\tif ( !hasClass( elem, name ) ) {\n\t\telem.className += (elem.className ? \" \" : \"\") + name;\n\t}\n}\n\nfunction removeClass( elem, name ) {\n\tvar set = \" \" + elem.className + \" \";\n\t// Class name may appear multiple times\n\twhile ( set.indexOf(\" \" + name + \" \") > -1 ) {\n\t\tset = set.replace(\" \" + name + \" \" , \" \");\n\t}\n\t// If possible, trim it for prettiness, but not necessarily\n\telem.className = typeof set.trim === \"function\" ? set.trim() : set.replace(/^\\s+|\\s+$/g, \"\");\n}\n\nfunction id( name ) {\n\treturn !!( typeof document !== \"undefined\" && document && document.getElementById ) &&\n\t\tdocument.getElementById( name );\n}\n\nfunction registerLoggingCallback( key ) {\n\treturn function( callback ) {\n\t\tconfig[key].push( callback );\n\t};\n}\n\n// Supports deprecated method of completely overwriting logging callbacks\nfunction runLoggingCallbacks( key, scope, args ) {\n\tvar i, callbacks;\n\tif ( QUnit.hasOwnProperty( key ) ) {\n\t\tQUnit[ key ].call(scope, args );\n\t} else {\n\t\tcallbacks = config[ key ];\n\t\tfor ( i = 0; i < callbacks.length; i++ ) {\n\t\t\tcallbacks[ i ].call( scope, args );\n\t\t}\n\t}\n}\n\n// Test for equality any JavaScript type.\n// Author: Philippe Rathé <prathe@gmail.com>\nQUnit.equiv = (function() {\n\n\t// Call the o related callback with the given arguments.\n\tfunction bindCallbacks( o, callbacks, args ) {\n\t\tvar prop = QUnit.objectType( o );\n\t\tif ( prop ) {\n\t\t\tif ( QUnit.objectType( callbacks[ prop ] ) === \"function\" ) {\n\t\t\t\treturn callbacks[ prop ].apply( callbacks, args );\n\t\t\t} else {\n\t\t\t\treturn callbacks[ prop ]; // or undefined\n\t\t\t}\n\t\t}\n\t}\n\n\t// the real equiv function\n\tvar innerEquiv,\n\t\t// stack to decide between skip/abort functions\n\t\tcallers = [],\n\t\t// stack to avoiding loops from circular referencing\n\t\tparents = [],\n\t\tparentsB = [],\n\n\t\tgetProto = Object.getPrototypeOf || function ( obj ) {\n\t\t\t/*jshint camelcase:false */\n\t\t\treturn obj.__proto__;\n\t\t},\n\t\tcallbacks = (function () {\n\n\t\t\t// for string, boolean, number and null\n\t\t\tfunction useStrictEquality( b, a ) {\n\t\t\t\t/*jshint eqeqeq:false */\n\t\t\t\tif ( b instanceof a.constructor || a instanceof b.constructor ) {\n\t\t\t\t\t// to catch short annotation VS 'new' annotation of a\n\t\t\t\t\t// declaration\n\t\t\t\t\t// e.g. var i = 1;\n\t\t\t\t\t// var j = new Number(1);\n\t\t\t\t\treturn a == b;\n\t\t\t\t} else {\n\t\t\t\t\treturn a === b;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\t\"string\": useStrictEquality,\n\t\t\t\t\"boolean\": useStrictEquality,\n\t\t\t\t\"number\": useStrictEquality,\n\t\t\t\t\"null\": useStrictEquality,\n\t\t\t\t\"undefined\": useStrictEquality,\n\n\t\t\t\t\"nan\": function( b ) {\n\t\t\t\t\treturn isNaN( b );\n\t\t\t\t},\n\n\t\t\t\t\"date\": function( b, a ) {\n\t\t\t\t\treturn QUnit.objectType( b ) === \"date\" && a.valueOf() === b.valueOf();\n\t\t\t\t},\n\n\t\t\t\t\"regexp\": function( b, a ) {\n\t\t\t\t\treturn QUnit.objectType( b ) === \"regexp\" &&\n\t\t\t\t\t\t// the regex itself\n\t\t\t\t\t\ta.source === b.source &&\n\t\t\t\t\t\t// and its modifiers\n\t\t\t\t\t\ta.global === b.global &&\n\t\t\t\t\t\t// (gmi) ...\n\t\t\t\t\t\ta.ignoreCase === b.ignoreCase &&\n\t\t\t\t\t\ta.multiline === b.multiline &&\n\t\t\t\t\t\ta.sticky === b.sticky;\n\t\t\t\t},\n\n\t\t\t\t// - skip when the property is a method of an instance (OOP)\n\t\t\t\t// - abort otherwise,\n\t\t\t\t// initial === would have catch identical references anyway\n\t\t\t\t\"function\": function() {\n\t\t\t\t\tvar caller = callers[callers.length - 1];\n\t\t\t\t\treturn caller !== Object && typeof caller !== \"undefined\";\n\t\t\t\t},\n\n\t\t\t\t\"array\": function( b, a ) {\n\t\t\t\t\tvar i, j, len, loop, aCircular, bCircular;\n\n\t\t\t\t\t// b could be an object literal here\n\t\t\t\t\tif ( QUnit.objectType( b ) !== \"array\" ) {\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\n\t\t\t\t\tlen = a.length;\n\t\t\t\t\tif ( len !== b.length ) {\n\t\t\t\t\t\t// safe and faster\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\n\t\t\t\t\t// track reference to avoid circular references\n\t\t\t\t\tparents.push( a );\n\t\t\t\t\tparentsB.push( b );\n\t\t\t\t\tfor ( i = 0; i < len; i++ ) {\n\t\t\t\t\t\tloop = false;\n\t\t\t\t\t\tfor ( j = 0; j < parents.length; j++ ) {\n\t\t\t\t\t\t\taCircular = parents[j] === a[i];\n\t\t\t\t\t\t\tbCircular = parentsB[j] === b[i];\n\t\t\t\t\t\t\tif ( aCircular || bCircular ) {\n\t\t\t\t\t\t\t\tif ( a[i] === b[i] || aCircular && bCircular ) {\n\t\t\t\t\t\t\t\t\tloop = true;\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tparents.pop();\n\t\t\t\t\t\t\t\t\tparentsB.pop();\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}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif ( !loop && !innerEquiv(a[i], b[i]) ) {\n\t\t\t\t\t\t\tparents.pop();\n\t\t\t\t\t\t\tparentsB.pop();\n\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tparents.pop();\n\t\t\t\t\tparentsB.pop();\n\t\t\t\t\treturn true;\n\t\t\t\t},\n\n\t\t\t\t\"object\": function( b, a ) {\n\t\t\t\t\t/*jshint forin:false */\n\t\t\t\t\tvar i, j, loop, aCircular, bCircular,\n\t\t\t\t\t\t// Default to true\n\t\t\t\t\t\teq = true,\n\t\t\t\t\t\taProperties = [],\n\t\t\t\t\t\tbProperties = [];\n\n\t\t\t\t\t// comparing constructors is more strict than using\n\t\t\t\t\t// instanceof\n\t\t\t\t\tif ( a.constructor !== b.constructor ) {\n\t\t\t\t\t\t// Allow objects with no prototype to be equivalent to\n\t\t\t\t\t\t// objects with Object as their constructor.\n\t\t\t\t\t\tif ( !(( getProto(a) === null && getProto(b) === Object.prototype ) ||\n\t\t\t\t\t\t\t( getProto(b) === null && getProto(a) === Object.prototype ) ) ) {\n\t\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// stack constructor before traversing properties\n\t\t\t\t\tcallers.push( a.constructor );\n\n\t\t\t\t\t// track reference to avoid circular references\n\t\t\t\t\tparents.push( a );\n\t\t\t\t\tparentsB.push( b );\n\n\t\t\t\t\t// be strict: don't ensure hasOwnProperty and go deep\n\t\t\t\t\tfor ( i in a ) {\n\t\t\t\t\t\tloop = false;\n\t\t\t\t\t\tfor ( j = 0; j < parents.length; j++ ) {\n\t\t\t\t\t\t\taCircular = parents[j] === a[i];\n\t\t\t\t\t\t\tbCircular = parentsB[j] === b[i];\n\t\t\t\t\t\t\tif ( aCircular || bCircular ) {\n\t\t\t\t\t\t\t\tif ( a[i] === b[i] || aCircular && bCircular ) {\n\t\t\t\t\t\t\t\t\tloop = true;\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\teq = false;\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\taProperties.push(i);\n\t\t\t\t\t\tif ( !loop && !innerEquiv(a[i], b[i]) ) {\n\t\t\t\t\t\t\teq = false;\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\tparents.pop();\n\t\t\t\t\tparentsB.pop();\n\t\t\t\t\tcallers.pop(); // unstack, we are done\n\n\t\t\t\t\tfor ( i in b ) {\n\t\t\t\t\t\tbProperties.push( i ); // collect b's properties\n\t\t\t\t\t}\n\n\t\t\t\t\t// Ensures identical properties name\n\t\t\t\t\treturn eq && innerEquiv( aProperties.sort(), bProperties.sort() );\n\t\t\t\t}\n\t\t\t};\n\t\t}());\n\n\tinnerEquiv = function() { // can take multiple arguments\n\t\tvar args = [].slice.apply( arguments );\n\t\tif ( args.length < 2 ) {\n\t\t\treturn true; // end transition\n\t\t}\n\n\t\treturn (function( a, b ) {\n\t\t\tif ( a === b ) {\n\t\t\t\treturn true; // catch the most you can\n\t\t\t} else if ( a === null || b === null || typeof a === \"undefined\" ||\n\t\t\t\t\ttypeof b === \"undefined\" ||\n\t\t\t\t\tQUnit.objectType(a) !== QUnit.objectType(b) ) {\n\t\t\t\treturn false; // don't lose time with error prone cases\n\t\t\t} else {\n\t\t\t\treturn bindCallbacks(a, callbacks, [ b, a ]);\n\t\t\t}\n\n\t\t\t// apply transition with (1..n) arguments\n\t\t}( args[0], args[1] ) && innerEquiv.apply( this, args.splice(1, args.length - 1 )) );\n\t};\n\n\treturn innerEquiv;\n}());\n\n/**\n * jsDump Copyright (c) 2008 Ariel Flesler - aflesler(at)gmail(dot)com |\n * http://flesler.blogspot.com Licensed under BSD\n * (http://www.opensource.org/licenses/bsd-license.php) Date: 5/15/2008\n *\n * @projectDescription Advanced and extensible data dumping for Javascript.\n * @version 1.0.0\n * @author Ariel Flesler\n * @link {http://flesler.blogspot.com/2008/05/jsdump-pretty-dump-of-any-javascript.html}\n */\nQUnit.jsDump = (function() {\n\tfunction quote( str ) {\n\t\treturn \"\\\"\" + str.toString().replace( /\"/g, \"\\\\\\\"\" ) + \"\\\"\";\n\t}\n\tfunction literal( o ) {\n\t\treturn o + \"\";\n\t}\n\tfunction join( pre, arr, post ) {\n\t\tvar s = jsDump.separator(),\n\t\t\tbase = jsDump.indent(),\n\t\t\tinner = jsDump.indent(1);\n\t\tif ( arr.join ) {\n\t\t\tarr = arr.join( \",\" + s + inner );\n\t\t}\n\t\tif ( !arr ) {\n\t\t\treturn pre + post;\n\t\t}\n\t\treturn [ pre, inner + arr, base + post ].join(s);\n\t}\n\tfunction array( arr, stack ) {\n\t\tvar i = arr.length, ret = new Array(i);\n\t\tthis.up();\n\t\twhile ( i-- ) {\n\t\t\tret[i] = this.parse( arr[i] , undefined , stack);\n\t\t}\n\t\tthis.down();\n\t\treturn join( \"[\", ret, \"]\" );\n\t}\n\n\tvar reName = /^function (\\w+)/,\n\t\tjsDump = {\n\t\t\t// type is used mostly internally, you can fix a (custom)type in advance\n\t\t\tparse: function( obj, type, stack ) {\n\t\t\t\tstack = stack || [ ];\n\t\t\t\tvar inStack, res,\n\t\t\t\t\tparser = this.parsers[ type || this.typeOf(obj) ];\n\n\t\t\t\ttype = typeof parser;\n\t\t\t\tinStack = inArray( obj, stack );\n\n\t\t\t\tif ( inStack !== -1 ) {\n\t\t\t\t\treturn \"recursion(\" + (inStack - stack.length) + \")\";\n\t\t\t\t}\n\t\t\t\tif ( type === \"function\" )  {\n\t\t\t\t\tstack.push( obj );\n\t\t\t\t\tres = parser.call( this, obj, stack );\n\t\t\t\t\tstack.pop();\n\t\t\t\t\treturn res;\n\t\t\t\t}\n\t\t\t\treturn ( type === \"string\" ) ? parser : this.parsers.error;\n\t\t\t},\n\t\t\ttypeOf: function( obj ) {\n\t\t\t\tvar type;\n\t\t\t\tif ( obj === null ) {\n\t\t\t\t\ttype = \"null\";\n\t\t\t\t} else if ( typeof obj === \"undefined\" ) {\n\t\t\t\t\ttype = \"undefined\";\n\t\t\t\t} else if ( QUnit.is( \"regexp\", obj) ) {\n\t\t\t\t\ttype = \"regexp\";\n\t\t\t\t} else if ( QUnit.is( \"date\", obj) ) {\n\t\t\t\t\ttype = \"date\";\n\t\t\t\t} else if ( QUnit.is( \"function\", obj) ) {\n\t\t\t\t\ttype = \"function\";\n\t\t\t\t} else if ( typeof obj.setInterval !== undefined && typeof obj.document !== \"undefined\" && typeof obj.nodeType === \"undefined\" ) {\n\t\t\t\t\ttype = \"window\";\n\t\t\t\t} else if ( obj.nodeType === 9 ) {\n\t\t\t\t\ttype = \"document\";\n\t\t\t\t} else if ( obj.nodeType ) {\n\t\t\t\t\ttype = \"node\";\n\t\t\t\t} else if (\n\t\t\t\t\t// native arrays\n\t\t\t\t\ttoString.call( obj ) === \"[object Array]\" ||\n\t\t\t\t\t// NodeList objects\n\t\t\t\t\t( typeof obj.length === \"number\" && typeof obj.item !== \"undefined\" && ( obj.length ? obj.item(0) === obj[0] : ( obj.item( 0 ) === null && typeof obj[0] === \"undefined\" ) ) )\n\t\t\t\t) {\n\t\t\t\t\ttype = \"array\";\n\t\t\t\t} else if ( obj.constructor === Error.prototype.constructor ) {\n\t\t\t\t\ttype = \"error\";\n\t\t\t\t} else {\n\t\t\t\t\ttype = typeof obj;\n\t\t\t\t}\n\t\t\t\treturn type;\n\t\t\t},\n\t\t\tseparator: function() {\n\t\t\t\treturn this.multiline ?\tthis.HTML ? \"<br />\" : \"\\n\" : this.HTML ? \"&nbsp;\" : \" \";\n\t\t\t},\n\t\t\t// extra can be a number, shortcut for increasing-calling-decreasing\n\t\t\tindent: function( extra ) {\n\t\t\t\tif ( !this.multiline ) {\n\t\t\t\t\treturn \"\";\n\t\t\t\t}\n\t\t\t\tvar chr = this.indentChar;\n\t\t\t\tif ( this.HTML ) {\n\t\t\t\t\tchr = chr.replace( /\\t/g, \"   \" ).replace( / /g, \"&nbsp;\" );\n\t\t\t\t}\n\t\t\t\treturn new Array( this.depth + ( extra || 0 ) ).join(chr);\n\t\t\t},\n\t\t\tup: function( a ) {\n\t\t\t\tthis.depth += a || 1;\n\t\t\t},\n\t\t\tdown: function( a ) {\n\t\t\t\tthis.depth -= a || 1;\n\t\t\t},\n\t\t\tsetParser: function( name, parser ) {\n\t\t\t\tthis.parsers[name] = parser;\n\t\t\t},\n\t\t\t// The next 3 are exposed so you can use them\n\t\t\tquote: quote,\n\t\t\tliteral: literal,\n\t\t\tjoin: join,\n\t\t\t//\n\t\t\tdepth: 1,\n\t\t\t// This is the list of parsers, to modify them, use jsDump.setParser\n\t\t\tparsers: {\n\t\t\t\twindow: \"[Window]\",\n\t\t\t\tdocument: \"[Document]\",\n\t\t\t\terror: function(error) {\n\t\t\t\t\treturn \"Error(\\\"\" + error.message + \"\\\")\";\n\t\t\t\t},\n\t\t\t\tunknown: \"[Unknown]\",\n\t\t\t\t\"null\": \"null\",\n\t\t\t\t\"undefined\": \"undefined\",\n\t\t\t\t\"function\": function( fn ) {\n\t\t\t\t\tvar ret = \"function\",\n\t\t\t\t\t\t// functions never have name in IE\n\t\t\t\t\t\tname = \"name\" in fn ? fn.name : (reName.exec(fn) || [])[1];\n\n\t\t\t\t\tif ( name ) {\n\t\t\t\t\t\tret += \" \" + name;\n\t\t\t\t\t}\n\t\t\t\t\tret += \"( \";\n\n\t\t\t\t\tret = [ ret, QUnit.jsDump.parse( fn, \"functionArgs\" ), \"){\" ].join( \"\" );\n\t\t\t\t\treturn join( ret, QUnit.jsDump.parse(fn,\"functionCode\" ), \"}\" );\n\t\t\t\t},\n\t\t\t\tarray: array,\n\t\t\t\tnodelist: array,\n\t\t\t\t\"arguments\": array,\n\t\t\t\tobject: function( map, stack ) {\n\t\t\t\t\t/*jshint forin:false */\n\t\t\t\t\tvar ret = [ ], keys, key, val, i;\n\t\t\t\t\tQUnit.jsDump.up();\n\t\t\t\t\tkeys = [];\n\t\t\t\t\tfor ( key in map ) {\n\t\t\t\t\t\tkeys.push( key );\n\t\t\t\t\t}\n\t\t\t\t\tkeys.sort();\n\t\t\t\t\tfor ( i = 0; i < keys.length; i++ ) {\n\t\t\t\t\t\tkey = keys[ i ];\n\t\t\t\t\t\tval = map[ key ];\n\t\t\t\t\t\tret.push( QUnit.jsDump.parse( key, \"key\" ) + \": \" + QUnit.jsDump.parse( val, undefined, stack ) );\n\t\t\t\t\t}\n\t\t\t\t\tQUnit.jsDump.down();\n\t\t\t\t\treturn join( \"{\", ret, \"}\" );\n\t\t\t\t},\n\t\t\t\tnode: function( node ) {\n\t\t\t\t\tvar len, i, val,\n\t\t\t\t\t\topen = QUnit.jsDump.HTML ? \"&lt;\" : \"<\",\n\t\t\t\t\t\tclose = QUnit.jsDump.HTML ? \"&gt;\" : \">\",\n\t\t\t\t\t\ttag = node.nodeName.toLowerCase(),\n\t\t\t\t\t\tret = open + tag,\n\t\t\t\t\t\tattrs = node.attributes;\n\n\t\t\t\t\tif ( attrs ) {\n\t\t\t\t\t\tfor ( i = 0, len = attrs.length; i < len; i++ ) {\n\t\t\t\t\t\t\tval = attrs[i].nodeValue;\n\t\t\t\t\t\t\t// IE6 includes all attributes in .attributes, even ones not explicitly set.\n\t\t\t\t\t\t\t// Those have values like undefined, null, 0, false, \"\" or \"inherit\".\n\t\t\t\t\t\t\tif ( val && val !== \"inherit\" ) {\n\t\t\t\t\t\t\t\tret += \" \" + attrs[i].nodeName + \"=\" + QUnit.jsDump.parse( val, \"attribute\" );\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\tret += close;\n\n\t\t\t\t\t// Show content of TextNode or CDATASection\n\t\t\t\t\tif ( node.nodeType === 3 || node.nodeType === 4 ) {\n\t\t\t\t\t\tret += node.nodeValue;\n\t\t\t\t\t}\n\n\t\t\t\t\treturn ret + open + \"/\" + tag + close;\n\t\t\t\t},\n\t\t\t\t// function calls it internally, it's the arguments part of the function\n\t\t\t\tfunctionArgs: function( fn ) {\n\t\t\t\t\tvar args,\n\t\t\t\t\t\tl = fn.length;\n\n\t\t\t\t\tif ( !l ) {\n\t\t\t\t\t\treturn \"\";\n\t\t\t\t\t}\n\n\t\t\t\t\targs = new Array(l);\n\t\t\t\t\twhile ( l-- ) {\n\t\t\t\t\t\t// 97 is 'a'\n\t\t\t\t\t\targs[l] = String.fromCharCode(97+l);\n\t\t\t\t\t}\n\t\t\t\t\treturn \" \" + args.join( \", \" ) + \" \";\n\t\t\t\t},\n\t\t\t\t// object calls it internally, the key part of an item in a map\n\t\t\t\tkey: quote,\n\t\t\t\t// function calls it internally, it's the content of the function\n\t\t\t\tfunctionCode: \"[code]\",\n\t\t\t\t// node calls it internally, it's an html attribute value\n\t\t\t\tattribute: quote,\n\t\t\t\tstring: quote,\n\t\t\t\tdate: quote,\n\t\t\t\tregexp: literal,\n\t\t\t\tnumber: literal,\n\t\t\t\t\"boolean\": literal\n\t\t\t},\n\t\t\t// if true, entities are escaped ( <, >, \\t, space and \\n )\n\t\t\tHTML: false,\n\t\t\t// indentation unit\n\t\t\tindentChar: \"  \",\n\t\t\t// if true, items in a collection, are separated by a \\n, else just a space.\n\t\t\tmultiline: true\n\t\t};\n\n\treturn jsDump;\n}());\n\n// from jquery.js\nfunction inArray( elem, array ) {\n\tif ( array.indexOf ) {\n\t\treturn array.indexOf( elem );\n\t}\n\n\tfor ( var i = 0, length = array.length; i < length; i++ ) {\n\t\tif ( array[ i ] === elem ) {\n\t\t\treturn i;\n\t\t}\n\t}\n\n\treturn -1;\n}\n\n/*\n * Javascript Diff Algorithm\n *  By John Resig (http://ejohn.org/)\n *  Modified by Chu Alan \"sprite\"\n *\n * Released under the MIT license.\n *\n * More Info:\n *  http://ejohn.org/projects/javascript-diff-algorithm/\n *\n * Usage: QUnit.diff(expected, actual)\n *\n * QUnit.diff( \"the quick brown fox jumped over\", \"the quick fox jumps over\" ) == \"the  quick <del>brown </del> fox <del>jumped </del><ins>jumps </ins> over\"\n */\nQUnit.diff = (function() {\n\t/*jshint eqeqeq:false, eqnull:true */\n\tfunction diff( o, n ) {\n\t\tvar i,\n\t\t\tns = {},\n\t\t\tos = {};\n\n\t\tfor ( i = 0; i < n.length; i++ ) {\n\t\t\tif ( !hasOwn.call( ns, n[i] ) ) {\n\t\t\t\tns[ n[i] ] = {\n\t\t\t\t\trows: [],\n\t\t\t\t\to: null\n\t\t\t\t};\n\t\t\t}\n\t\t\tns[ n[i] ].rows.push( i );\n\t\t}\n\n\t\tfor ( i = 0; i < o.length; i++ ) {\n\t\t\tif ( !hasOwn.call( os, o[i] ) ) {\n\t\t\t\tos[ o[i] ] = {\n\t\t\t\t\trows: [],\n\t\t\t\t\tn: null\n\t\t\t\t};\n\t\t\t}\n\t\t\tos[ o[i] ].rows.push( i );\n\t\t}\n\n\t\tfor ( i in ns ) {\n\t\t\tif ( hasOwn.call( ns, i ) ) {\n\t\t\t\tif ( ns[i].rows.length === 1 && hasOwn.call( os, i ) && os[i].rows.length === 1 ) {\n\t\t\t\t\tn[ ns[i].rows[0] ] = {\n\t\t\t\t\t\ttext: n[ ns[i].rows[0] ],\n\t\t\t\t\t\trow: os[i].rows[0]\n\t\t\t\t\t};\n\t\t\t\t\to[ os[i].rows[0] ] = {\n\t\t\t\t\t\ttext: o[ os[i].rows[0] ],\n\t\t\t\t\t\trow: ns[i].rows[0]\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 < n.length - 1; i++ ) {\n\t\t\tif ( n[i].text != null && n[ i + 1 ].text == null && n[i].row + 1 < o.length && o[ n[i].row + 1 ].text == null &&\n\t\t\t\t\t\tn[ i + 1 ] == o[ n[i].row + 1 ] ) {\n\n\t\t\t\tn[ i + 1 ] = {\n\t\t\t\t\ttext: n[ i + 1 ],\n\t\t\t\t\trow: n[i].row + 1\n\t\t\t\t};\n\t\t\t\to[ n[i].row + 1 ] = {\n\t\t\t\t\ttext: o[ n[i].row + 1 ],\n\t\t\t\t\trow: i + 1\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\n\t\tfor ( i = n.length - 1; i > 0; i-- ) {\n\t\t\tif ( n[i].text != null && n[ i - 1 ].text == null && n[i].row > 0 && o[ n[i].row - 1 ].text == null &&\n\t\t\t\t\t\tn[ i - 1 ] == o[ n[i].row - 1 ]) {\n\n\t\t\t\tn[ i - 1 ] = {\n\t\t\t\t\ttext: n[ i - 1 ],\n\t\t\t\t\trow: n[i].row - 1\n\t\t\t\t};\n\t\t\t\to[ n[i].row - 1 ] = {\n\t\t\t\t\ttext: o[ n[i].row - 1 ],\n\t\t\t\t\trow: i - 1\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\n\t\treturn {\n\t\t\to: o,\n\t\t\tn: n\n\t\t};\n\t}\n\n\treturn function( o, n ) {\n\t\to = o.replace( /\\s+$/, \"\" );\n\t\tn = n.replace( /\\s+$/, \"\" );\n\n\t\tvar i, pre,\n\t\t\tstr = \"\",\n\t\t\tout = diff( o === \"\" ? [] : o.split(/\\s+/), n === \"\" ? [] : n.split(/\\s+/) ),\n\t\t\toSpace = o.match(/\\s+/g),\n\t\t\tnSpace = n.match(/\\s+/g);\n\n\t\tif ( oSpace == null ) {\n\t\t\toSpace = [ \" \" ];\n\t\t}\n\t\telse {\n\t\t\toSpace.push( \" \" );\n\t\t}\n\n\t\tif ( nSpace == null ) {\n\t\t\tnSpace = [ \" \" ];\n\t\t}\n\t\telse {\n\t\t\tnSpace.push( \" \" );\n\t\t}\n\n\t\tif ( out.n.length === 0 ) {\n\t\t\tfor ( i = 0; i < out.o.length; i++ ) {\n\t\t\t\tstr += \"<del>\" + out.o[i] + oSpace[i] + \"</del>\";\n\t\t\t}\n\t\t}\n\t\telse {\n\t\t\tif ( out.n[0].text == null ) {\n\t\t\t\tfor ( n = 0; n < out.o.length && out.o[n].text == null; n++ ) {\n\t\t\t\t\tstr += \"<del>\" + out.o[n] + oSpace[n] + \"</del>\";\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfor ( i = 0; i < out.n.length; i++ ) {\n\t\t\t\tif (out.n[i].text == null) {\n\t\t\t\t\tstr += \"<ins>\" + out.n[i] + nSpace[i] + \"</ins>\";\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\t// `pre` initialized at top of scope\n\t\t\t\t\tpre = \"\";\n\n\t\t\t\t\tfor ( n = out.n[i].row + 1; n < out.o.length && out.o[n].text == null; n++ ) {\n\t\t\t\t\t\tpre += \"<del>\" + out.o[n] + oSpace[n] + \"</del>\";\n\t\t\t\t\t}\n\t\t\t\t\tstr += \" \" + out.n[i].text + nSpace[i] + pre;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn str;\n\t};\n}());\n\n// for CommonJS environments, export everything\nif ( typeof exports !== \"undefined\" ) {\n\textend( exports, QUnit.constructor.prototype );\n}\n\n// get at whatever the global object is, like window in browsers\n}( (function() {return this;}.call()) ));\n"
  },
  {
    "path": "flowable-ui-web/idm/libs/sizzle_1.10.16/test/unit/extending.js",
    "content": "module(\"extending\", { teardown: moduleTeardown });\n\ntest(\"custom pseudos\", function() {\n\texpect( 6 );\n\n\tSizzle.selectors.filters.foundation = Sizzle.selectors.filters.root;\n\tdeepEqual( Sizzle(\":foundation\"), [ document.documentElement ], \"Copy element filter with new name\" );\n\tdelete Sizzle.selectors.filters.foundation;\n\n\tSizzle.selectors.setFilters.primary = Sizzle.selectors.setFilters.first;\n\tt( \"Copy set filter with new name\", \"div:primary\", [\"qunit\"] );\n\tdelete Sizzle.selectors.setFilters.primary;\n\n\tSizzle.selectors.filters.aristotlean = Sizzle.selectors.createPseudo(function() {\n\t\treturn function( elem ) {\n\t\t\treturn !!elem.id;\n\t\t};\n\t});\n\tt( \"Custom element filter\", \"#foo :aristotlean\", [ \"sndp\", \"en\", \"yahoo\", \"sap\", \"anchor2\", \"simon\" ] );\n\tdelete Sizzle.selectors.filters.aristotlean;\n\n\tSizzle.selectors.filters.endswith = Sizzle.selectors.createPseudo(function( text ) {\n\t\treturn function( elem ) {\n\t\t\treturn Sizzle.getText( elem ).slice( -text.length ) === text;\n\t\t};\n\t});\n\tt( \"Custom element filter with argument\", \"a:endswith(ogle)\", [\"google\"] );\n\tdelete Sizzle.selectors.filters.endswith;\n\n\tSizzle.selectors.setFilters.second = Sizzle.selectors.createPseudo(function() {\n\t\treturn Sizzle.selectors.createPseudo(function( seed, matches ) {\n\t\t\tif ( seed[1] ) {\n\t\t\t\tmatches[1] = seed[1];\n\t\t\t\tseed[1] = false;\n\t\t\t}\n\t\t});\n\t});\n\tt( \"Custom set filter\", \"#qunit-fixture p:second\", [\"ap\"] );\n\tdelete Sizzle.selectors.filters.second;\n\n\tSizzle.selectors.setFilters.slice = Sizzle.selectors.createPseudo(function( argument ) {\n\t\tvar bounds = argument.split(\":\");\n\t\treturn Sizzle.selectors.createPseudo(function( seed, matches ) {\n\t\t\tvar i = bounds[1];\n\n\t\t\t// Match elements found at the specified indexes\n\t\t\twhile ( --i >= bounds[0] ) {\n\t\t\t\tif ( seed[i] ) {\n\t\t\t\t\tmatches[i] = seed[i];\n\t\t\t\t\tseed[i] = false;\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t});\n\tt( \"Custom set filter with argument\", \"#qunit-fixture p:slice(1:3)\", [ \"ap\", \"sndp\" ] );\n\tdelete Sizzle.selectors.filters.slice;\n});\n\ntest(\"backwards-compatible custom pseudos\", function() {\n\texpect( 3 );\n\n\tSizzle.selectors.filters.icontains = function( elem, i, match ) {\n\t\treturn Sizzle.getText( elem ).toLowerCase().indexOf( (match[3] || \"\").toLowerCase() ) > -1;\n\t};\n\tt( \"Custom element filter with argument\", \"a:icontains(THIS BLOG ENTRY)\", [\"simon1\"] );\n\tdelete Sizzle.selectors.filters.icontains;\n\n\tSizzle.selectors.setFilters.podium = function( elements, argument ) {\n\t\tvar count = argument == null || argument === \"\" ? 3 : +argument;\n\t\treturn elements.slice( 0, count );\n\t};\n\t// Using TAG as the first token here forces this setMatcher into a fail state\n\t// Where the descendent combinator was lost\n\tt( \"Custom setFilter\", \"form#form :PODIUM\", [\"label-for\", \"text1\", \"text2\"] );\n\tt( \"Custom setFilter with argument\", \"#form input:Podium(1)\", [\"text1\"] );\n\tdelete Sizzle.selectors.setFilters.podium;\n});\n\ntest(\"custom attribute getters\", function() {\n\texpect( 2 );\n\n\tvar original = Sizzle.selectors.attrHandle.hreflang,\n\t\tselector = \"a:contains('mark')[hreflang='http://diveintomark.org/en']\";\n\n\tSizzle.selectors.attrHandle.hreflang = function( elem, name ) {\n\t\tvar href = elem.getAttribute(\"href\"),\n\t\t\tlang = elem.getAttribute( name );\n\t\treturn lang && ( href + lang );\n\t};\n\n\tdeepEqual( Sizzle(selector, createWithFriesXML()), [], \"Custom attrHandle (preferred document)\" );\n\tt( \"Custom attrHandle (preferred document)\", selector, [\"mark\"] );\n\n\tSizzle.selectors.attrHandle.hreflang = original;\n});\n"
  },
  {
    "path": "flowable-ui-web/idm/libs/sizzle_1.10.16/test/unit/selector.js",
    "content": "module(\"selector\", { teardown: moduleTeardown });\n\n// #### NOTE: ####\n// jQuery should not be used in this module\n// except for DOM manipulation\n// If jQuery is mandatory for the selection, move the test to jquery/test/unit/selector.js\n// Use t() or Sizzle()\n// ###############\n\n/*\n\t======== QUnit Reference ========\n\thttp://docs.jquery.com/QUnit\n\n\tTest methods:\n\t\texpect(numAssertions)\n\t\tstop()\n\t\tstart()\n\t\t\tnote: QUnit's eventual addition of an argument to stop/start is ignored in this test suite\n\t\t\tso that start and stop can be passed as callbacks without worrying about\n\t\t\t\ttheir parameters\n\tTest assertions:\n\t\tok(value, [message])\n\t\tequal(actual, expected, [message])\n\t\tnotEqual(actual, expected, [message])\n\t\tdeepEqual(actual, expected, [message])\n\t\tnotDeepEqual(actual, expected, [message])\n\t\tstrictEqual(actual, expected, [message])\n\t\tnotStrictEqual(actual, expected, [message])\n\t\traises(block, [expected], [message])\n\n\t======== testinit.js reference ========\n\tSee data/testinit.js\n\n\tq(...);\n\t\tReturns an array of elements with the given IDs\n\t\t@example q(\"main\", \"foo\", \"bar\") => [<div id=\"main\">, <span id=\"foo\">, <input id=\"bar\">]\n\n\tt( testName, selector, [ \"array\", \"of\", \"ids\" ] );\n\t\tAsserts that a select matches the given IDs\n\t\t@example t(\"Check for something\", \"//[a]\", [\"foo\", \"baar\"]);\n\n\turl( \"some/url.php\" );\n\t\tAdd random number to url to stop caching\n\t\t@example url(\"data/test.html\") => \"data/test.html?10538358428943\"\n\t\t@example url(\"data/test.php?foo=bar\") => \"data/test.php?foo=bar&10538358345554\"\n*/\n\ntest(\"element\", function() {\n\texpect( 39 );\n\n\tvar form, all, good, i, obj1, lengthtest,\n\t\tsiblingTest, siblingNext, iframe, iframeDoc, html;\n\n\tequal( Sizzle(\"\").length, 0, \"Empty selector returns an empty array\" );\n\tdeepEqual( Sizzle(\"div\", document.createTextNode(\"\")), [], \"Text element as context fails silently\" );\n\tform = document.getElementById(\"form\");\n\tok( !Sizzle.matchesSelector( form, \"\" ), \"Empty string passed to matchesSelector does not match\" );\n\tequal( Sizzle(\" \").length, 0, \"Empty selector returns an empty array\" );\n\tequal( Sizzle(\"\\t\").length, 0, \"Empty selector returns an empty array\" );\n\n\tok( Sizzle(\"*\").length >= 30, \"Select all\" );\n\tall = Sizzle(\"*\");\n\tgood = true;\n\tfor ( i = 0; i < all.length; i++ ) {\n\t\tif ( all[i].nodeType === 8 ) {\n\t\t\tgood = false;\n\t\t}\n\t}\n\tok( good, \"Select all elements, no comment nodes\" );\n\tt( \"Element Selector\", \"html\", [\"html\"] );\n\tt( \"Element Selector\", \"body\", [\"body\"] );\n\tt( \"Element Selector\", \"#qunit-fixture p\", [\"firstp\",\"ap\",\"sndp\",\"en\",\"sap\",\"first\"] );\n\n\tt( \"Leading space\", \" #qunit-fixture p\", [\"firstp\",\"ap\",\"sndp\",\"en\",\"sap\",\"first\"] );\n\tt( \"Leading tab\", \"\\t#qunit-fixture p\", [\"firstp\",\"ap\",\"sndp\",\"en\",\"sap\",\"first\"] );\n\tt( \"Leading carriage return\", \"\\r#qunit-fixture p\", [\"firstp\",\"ap\",\"sndp\",\"en\",\"sap\",\"first\"] );\n\tt( \"Leading line feed\", \"\\n#qunit-fixture p\", [\"firstp\",\"ap\",\"sndp\",\"en\",\"sap\",\"first\"] );\n\tt( \"Leading form feed\", \"\\f#qunit-fixture p\", [\"firstp\",\"ap\",\"sndp\",\"en\",\"sap\",\"first\"] );\n\tt( \"Trailing space\", \"#qunit-fixture p \", [\"firstp\",\"ap\",\"sndp\",\"en\",\"sap\",\"first\"] );\n\tt( \"Trailing tab\", \"#qunit-fixture p\\t\", [\"firstp\",\"ap\",\"sndp\",\"en\",\"sap\",\"first\"] );\n\tt( \"Trailing carriage return\", \"#qunit-fixture p\\r\", [\"firstp\",\"ap\",\"sndp\",\"en\",\"sap\",\"first\"] );\n\tt( \"Trailing line feed\", \"#qunit-fixture p\\n\", [\"firstp\",\"ap\",\"sndp\",\"en\",\"sap\",\"first\"] );\n\tt( \"Trailing form feed\", \"#qunit-fixture p\\f\", [\"firstp\",\"ap\",\"sndp\",\"en\",\"sap\",\"first\"] );\n\n\tt( \"Parent Element\", \"dl ol\", [\"empty\", \"listWithTabIndex\"] );\n\tt( \"Parent Element (non-space descendant combinator)\", \"dl\\tol\", [\"empty\", \"listWithTabIndex\"] );\n\tobj1 = document.getElementById(\"object1\");\n\tequal( Sizzle(\"param\", obj1).length, 2, \"Object/param as context\" );\n\n\tdeepEqual( Sizzle(\"select\", form), q(\"select1\",\"select2\",\"select3\",\"select4\",\"select5\"), \"Finding selects with a context.\" );\n\n\t// Check for unique-ness and sort order\n\tdeepEqual( Sizzle(\"p, div p\"), Sizzle(\"p\"), \"Check for duplicates: p, div p\" );\n\n\tt( \"Checking sort order\", \"h2, h1\", [\"qunit-header\", \"qunit-banner\", \"qunit-userAgent\"] );\n\tt( \"Checking sort order\", \"h2:first, h1:first\", [\"qunit-header\", \"qunit-banner\"] );\n\tt( \"Checking sort order\", \"#qunit-fixture p, #qunit-fixture p a\", [\"firstp\", \"simon1\", \"ap\", \"google\", \"groups\", \"anchor1\", \"mark\", \"sndp\", \"en\", \"yahoo\", \"sap\", \"anchor2\", \"simon\", \"first\"] );\n\n\t// Test Conflict ID\n\tlengthtest = document.getElementById(\"lengthtest\");\n\tdeepEqual( Sizzle(\"#idTest\", lengthtest), q(\"idTest\"), \"Finding element with id of ID.\" );\n\tdeepEqual( Sizzle(\"[name='id']\", lengthtest), q(\"idTest\"), \"Finding element with id of ID.\" );\n\tdeepEqual( Sizzle(\"input[id='idTest']\", lengthtest), q(\"idTest\"), \"Finding elements with id of ID.\" );\n\n\tsiblingTest = document.getElementById(\"siblingTest\");\n\tdeepEqual( Sizzle(\"div em\", siblingTest), [], \"Element-rooted QSA does not select based on document context\" );\n\tdeepEqual( Sizzle(\"div em, div em, div em:not(div em)\", siblingTest), [], \"Element-rooted QSA does not select based on document context\" );\n\tdeepEqual( Sizzle(\"div em, em\\\\,\", siblingTest), [], \"Escaped commas do not get treated with an id in element-rooted QSA\" );\n\n\tsiblingNext = document.getElementById(\"siblingnext\");\n\tdocument.createDocumentFragment().appendChild( siblingTest );\n\tdeepEqual( Sizzle( \"em + :not(:has(*)):not(:empty), foo\", siblingTest ), [ siblingNext ],\n\t\t\"Non-qSA path correctly sets detached context for sibling selectors (jQuery #14351)\" );\n\n\tiframe = document.getElementById(\"iframe\"),\n\t\tiframeDoc = iframe.contentDocument || iframe.contentWindow.document;\n\tiframeDoc.open();\n\tiframeDoc.write(\"<body><p id='foo'>bar</p></body>\");\n\tiframeDoc.close();\n\tdeepEqual(\n\t\tSizzle( \"p:contains(bar)\", iframeDoc ),\n\t\t[ iframeDoc.getElementById(\"foo\") ],\n\t\t\"Other document as context\"\n\t);\n\n\thtml = \"\";\n\tfor ( i = 0; i < 100; i++ ) {\n\t\thtml = \"<div>\" + html + \"</div>\";\n\t}\n\thtml = jQuery( html ).appendTo( document.body );\n\tok( !!Sizzle(\"body div div div\").length, \"No stack or performance problems with large amounts of descendents\" );\n\tok( !!Sizzle(\"body>div div div\").length, \"No stack or performance problems with large amounts of descendents\" );\n\thtml.remove();\n\n\t// Real use case would be using .watch in browsers with window.watch (see Issue #157)\n\tq(\"qunit-fixture\")[0].appendChild( document.createElement(\"toString\") ).id = \"toString\";\n\tt( \"Element name matches Object.prototype property\", \"toString#toString\", [\"toString\"] );\n});\n\ntest(\"XML Document Selectors\", function() {\n\tvar xml = createWithFriesXML();\n\texpect( 11 );\n\n\tequal( Sizzle(\"foo_bar\", xml).length, 1, \"Element Selector with underscore\" );\n\tequal( Sizzle(\".component\", xml).length, 1, \"Class selector\" );\n\tequal( Sizzle(\"[class*=component]\", xml).length, 1, \"Attribute selector for class\" );\n\tequal( Sizzle(\"property[name=prop2]\", xml).length, 1, \"Attribute selector with name\" );\n\tequal( Sizzle(\"[name=prop2]\", xml).length, 1, \"Attribute selector with name\" );\n\tequal( Sizzle(\"#seite1\", xml).length, 1, \"Attribute selector with ID\" );\n\tequal( Sizzle(\"component#seite1\", xml).length, 1, \"Attribute selector with ID\" );\n\tequal( Sizzle.matches( \"#seite1\", Sizzle(\"component\", xml) ).length, 1, \"Attribute selector filter with ID\" );\n\tequal( Sizzle(\"meta property thing\", xml).length, 2, \"Descendent selector and dir caching\" );\n\tok( Sizzle.matchesSelector( xml.lastChild, \"soap\\\\:Envelope\" ), \"Check for namespaced element\" );\n\n\txml = jQuery.parseXML(\"<?xml version='1.0' encoding='UTF-8'?><root><elem id='1'/></root>\");\n\tequal( Sizzle( \"elem:not(:has(*))\", xml ).length, 1,\n\t\t\"Non-qSA path correctly handles numeric ids (jQuery #14142)\" );\n});\n\ntest(\"broken\", function() {\n\texpect( 26 );\n\n\tvar attrbad,\n\t\tbroken = function( name, selector ) {\n\t\t\traises(function() {\n\t\t\t\t// Setting context to null here somehow avoids QUnit's window.error handling\n\t\t\t\t// making the e & e.message correct\n\t\t\t\t// For whatever reason, without this,\n\t\t\t\t// Sizzle.error will be called but no error will be seen in oldIE\n\t\t\t\tSizzle.call( null, selector );\n\t\t\t}, function( e ) {\n\t\t\t\treturn e.message.indexOf(\"Syntax error\") >= 0;\n\t\t\t}, name + \": \" + selector );\n\t\t};\n\n\tbroken( \"Broken Selector\", \"[\" );\n\tbroken( \"Broken Selector\", \"(\" );\n\tbroken( \"Broken Selector\", \"{\" );\n\tbroken( \"Broken Selector\", \"<\" );\n\tbroken( \"Broken Selector\", \"()\" );\n\tbroken( \"Broken Selector\", \"<>\" );\n\tbroken( \"Broken Selector\", \"{}\" );\n\tbroken( \"Broken Selector\", \",\" );\n\tbroken( \"Broken Selector\", \",a\" );\n\tbroken( \"Broken Selector\", \"a,\" );\n\t// Hangs on IE 9 if regular expression is inefficient\n\tbroken( \"Broken Selector\", \"[id=012345678901234567890123456789\");\n\tbroken( \"Doesn't exist\", \":visble\" );\n\tbroken( \"Nth-child\", \":nth-child\" );\n\t// Sigh again. IE 9 thinks this is also a real selector\n\t// not super critical that we fix this case\n\t//broken( \"Nth-child\", \":nth-child(-)\" );\n\t// Sigh. WebKit thinks this is a real selector in qSA\n\t// They've already fixed this and it'll be coming into\n\t// current browsers soon. Currently, Safari 5.0 still has this problem\n\t// broken( \"Nth-child\", \":nth-child(asdf)\", [] );\n\tbroken( \"Nth-child\", \":nth-child(2n+-0)\" );\n\tbroken( \"Nth-child\", \":nth-child(2+0)\" );\n\tbroken( \"Nth-child\", \":nth-child(- 1n)\" );\n\tbroken( \"Nth-child\", \":nth-child(-1 n)\" );\n\tbroken( \"First-child\", \":first-child(n)\" );\n\tbroken( \"Last-child\", \":last-child(n)\" );\n\tbroken( \"Only-child\", \":only-child(n)\" );\n\tbroken( \"Nth-last-last-child\", \":nth-last-last-child(1)\" );\n\tbroken( \"First-last-child\", \":first-last-child\" );\n\tbroken( \"Last-last-child\", \":last-last-child\" );\n\tbroken( \"Only-last-child\", \":only-last-child\" );\n\n\t// Make sure attribute value quoting works correctly. See: #6093\n\tattrbad = jQuery(\"<input type='hidden' value='2' name='foo.baz' id='attrbad1'/><input type='hidden' value='2' name='foo[baz]' id='attrbad2'/>\").appendTo(\"#qunit-fixture\");\n\n\tbroken( \"Attribute not escaped\", \"input[name=foo.baz]\", [] );\n\t// Shouldn't be matching those inner brackets\n\tbroken( \"Attribute not escaped\", \"input[name=foo[baz]]\", [] );\n});\n\ntest(\"id\", function() {\n\texpect( 34 );\n\n\tvar fiddle, a;\n\n\tt( \"ID Selector\", \"#body\", [\"body\"] );\n\tt( \"ID Selector w/ Element\", \"body#body\", [\"body\"] );\n\tt( \"ID Selector w/ Element\", \"ul#first\", [] );\n\tt( \"ID selector with existing ID descendant\", \"#firstp #simon1\", [\"simon1\"] );\n\tt( \"ID selector with non-existant descendant\", \"#firstp #foobar\", [] );\n\tt( \"ID selector using UTF8\", \"#台北Táiběi\", [\"台北Táiběi\"] );\n\tt( \"Multiple ID selectors using UTF8\", \"#台北Táiběi, #台北\", [\"台北Táiběi\",\"台北\"] );\n\tt( \"Descendant ID selector using UTF8\", \"div #台北\", [\"台北\"] );\n\tt( \"Child ID selector using UTF8\", \"form > #台北\", [\"台北\"] );\n\n\tt( \"Escaped ID\", \"#foo\\\\:bar\", [\"foo:bar\"] );\n\tt( \"Escaped ID with descendent\", \"#foo\\\\:bar span:not(:input)\", [\"foo_descendent\"] );\n\tt( \"Escaped ID\", \"#test\\\\.foo\\\\[5\\\\]bar\", [\"test.foo[5]bar\"] );\n\tt( \"Descendant escaped ID\", \"div #foo\\\\:bar\", [\"foo:bar\"] );\n\tt( \"Descendant escaped ID\", \"div #test\\\\.foo\\\\[5\\\\]bar\", [\"test.foo[5]bar\"] );\n\tt( \"Child escaped ID\", \"form > #foo\\\\:bar\", [\"foo:bar\"] );\n\tt( \"Child escaped ID\", \"form > #test\\\\.foo\\\\[5\\\\]bar\", [\"test.foo[5]bar\"] );\n\n\tfiddle = jQuery(\"<div id='fiddle\\\\Foo'><span id='fiddleSpan'></span></div>\").appendTo(\"#qunit-fixture\");\n\tdeepEqual( Sizzle( \"> span\", Sizzle(\"#fiddle\\\\\\\\Foo\")[0] ), q([ \"fiddleSpan\" ]), \"Escaped ID as context\" );\n\tfiddle.remove();\n\n\tt( \"ID Selector, child ID present\", \"#form > #radio1\", [\"radio1\"] ); // bug #267\n\tt( \"ID Selector, not an ancestor ID\", \"#form #first\", [] );\n\tt( \"ID Selector, not a child ID\", \"#form > #option1a\", [] );\n\n\tt( \"All Children of ID\", \"#foo > *\", [\"sndp\", \"en\", \"sap\"] );\n\tt( \"All Children of ID with no children\", \"#firstUL > *\", [] );\n\n\tequal( Sizzle(\"#tName1\")[0].id, \"tName1\", \"ID selector with same value for a name attribute\" );\n\tt( \"ID selector non-existing but name attribute on an A tag\",         \"#tName2\",      [] );\n\tt( \"Leading ID selector non-existing but name attribute on an A tag\", \"#tName2 span\", [] );\n\tt( \"Leading ID selector existing, retrieving the child\",              \"#tName1 span\", [\"tName1-span\"] );\n\tequal( Sizzle(\"div > div #tName1\")[0].id, Sizzle(\"#tName1-span\")[0].parentNode.id, \"Ending with ID\" );\n\n\ta = jQuery(\"<a id='backslash\\\\foo'></a>\").appendTo(\"#qunit-fixture\");\n\tt( \"ID Selector contains backslash\", \"#backslash\\\\\\\\foo\", [\"backslash\\\\foo\"] );\n\n\tt( \"ID Selector on Form with an input that has a name of 'id'\", \"#lengthtest\", [\"lengthtest\"] );\n\n\tt( \"ID selector with non-existant ancestor\", \"#asdfasdf #foobar\", [] ); // bug #986\n\n\tdeepEqual( Sizzle(\"div#form\", document.body), [], \"ID selector within the context of another element\" );\n\n\tt( \"Underscore ID\", \"#types_all\", [\"types_all\"] );\n\tt( \"Dash ID\", \"#qunit-fixture\", [\"qunit-fixture\"] );\n\n\tt( \"ID with weird characters in it\", \"#name\\\\+value\", [\"name+value\"] );\n});\n\ntest(\"class\", function() {\n\texpect( 26 );\n\n\tt( \"Class Selector\", \".blog\", [\"mark\",\"simon\"] );\n\tt( \"Class Selector\", \".GROUPS\", [\"groups\"] );\n\tt( \"Class Selector\", \".blog.link\", [\"simon\"] );\n\tt( \"Class Selector w/ Element\", \"a.blog\", [\"mark\",\"simon\"] );\n\tt( \"Parent Class Selector\", \"p .blog\", [\"mark\",\"simon\"] );\n\n\tt( \"Class selector using UTF8\", \".台北Táiběi\", [\"utf8class1\"] );\n\t//t( \"Class selector using UTF8\", \".台北\", [\"utf8class1\",\"utf8class2\"] );\n\tt( \"Class selector using UTF8\", \".台北Táiběi.台北\", [\"utf8class1\"] );\n\tt( \"Class selector using UTF8\", \".台北Táiběi, .台北\", [\"utf8class1\",\"utf8class2\"] );\n\tt( \"Descendant class selector using UTF8\", \"div .台北Táiběi\", [\"utf8class1\"] );\n\tt( \"Child class selector using UTF8\", \"form > .台北Táiběi\", [\"utf8class1\"] );\n\n\tt( \"Escaped Class\", \".foo\\\\:bar\", [\"foo:bar\"] );\n\tt( \"Escaped Class\", \".test\\\\.foo\\\\[5\\\\]bar\", [\"test.foo[5]bar\"] );\n\tt( \"Descendant escaped Class\", \"div .foo\\\\:bar\", [\"foo:bar\"] );\n\tt( \"Descendant escaped Class\", \"div .test\\\\.foo\\\\[5\\\\]bar\", [\"test.foo[5]bar\"] );\n\tt( \"Child escaped Class\", \"form > .foo\\\\:bar\", [\"foo:bar\"] );\n\tt( \"Child escaped Class\", \"form > .test\\\\.foo\\\\[5\\\\]bar\", [\"test.foo[5]bar\"] );\n\n\tvar div = document.createElement(\"div\");\n\tdiv.innerHTML = \"<div class='test e'></div><div class='test'></div>\";\n\tdeepEqual( Sizzle(\".e\", div), [ div.firstChild ], \"Finding a second class.\" );\n\n\tdiv.lastChild.className = \"e\";\n\n\tdeepEqual( Sizzle(\".e\", div), [ div.firstChild, div.lastChild ], \"Finding a modified class.\" );\n\n\tok( !Sizzle.matchesSelector( div, \".null\"), \".null does not match an element with no class\" );\n\tok( !Sizzle.matchesSelector( div.firstChild, \".null div\"), \".null does not match an element with no class\" );\n\tdiv.className = \"null\";\n\tok( Sizzle.matchesSelector( div, \".null\"), \".null matches element with class 'null'\" );\n\tok( Sizzle.matchesSelector( div.firstChild, \".null div\"), \"caching system respects DOM changes\" );\n\tok( !Sizzle.matchesSelector( document, \".foo\" ), \"testing class on document doesn't error\" );\n\tok( !Sizzle.matchesSelector( window, \".foo\" ), \"testing class on window doesn't error\" );\n\n\tdiv.lastChild.className += \" hasOwnProperty toString\";\n\tdeepEqual( Sizzle(\".e.hasOwnProperty.toString\", div), [ div.lastChild ], \"Classes match Object.prototype properties\" );\n\n\tdiv = jQuery(\"<div><svg width='200' height='250' version='1.1' xmlns='http://www.w3.org/2000/svg'><rect x='10' y='10' width='30' height='30' class='foo'></rect></svg></div>\")[0];\n\tequal( Sizzle(\".foo\", div).length, 1, \"Class selector against SVG\" );\n});\n\ntest(\"name\", function() {\n\texpect( 14 );\n\n\tvar form;\n\n\tt( \"Name selector\", \"input[name=action]\", [\"text1\"] );\n\tt( \"Name selector with single quotes\", \"input[name='action']\", [\"text1\"] );\n\tt( \"Name selector with double quotes\", \"input[name=\\\"action\\\"]\", [\"text1\"] );\n\n\tt( \"Name selector non-input\", \"[name=example]\", [\"name-is-example\"] );\n\tt( \"Name selector non-input\", \"[name=div]\", [\"name-is-div\"] );\n\tt( \"Name selector non-input\", \"*[name=iframe]\", [\"iframe\"] );\n\n\tt( \"Name selector for grouped input\", \"input[name='types[]']\", [\"types_all\", \"types_anime\", \"types_movie\"] );\n\n\tform = document.getElementById(\"form\");\n\tdeepEqual( Sizzle(\"input[name=action]\", form), q(\"text1\"), \"Name selector within the context of another element\" );\n\tdeepEqual( Sizzle(\"input[name='foo[bar]']\", form), q(\"hidden2\"), \"Name selector for grouped form element within the context of another element\" );\n\n\tform = jQuery(\"<form><input name='id'/></form>\").appendTo(\"body\");\n\tequal( Sizzle(\"input\", form[0]).length, 1, \"Make sure that rooted queries on forms (with possible expandos) work.\" );\n\n\tform.remove();\n\n\tt( \"Find elements that have similar IDs\", \"[name=tName1]\", [\"tName1ID\"] );\n\tt( \"Find elements that have similar IDs\", \"[name=tName2]\", [\"tName2ID\"] );\n\tt( \"Find elements that have similar IDs\", \"#tName2ID\", [\"tName2ID\"] );\n\n\tt( \"Case-sensitivity\", \"[name=tname1]\", [] );\n});\n\ntest(\"multiple\", function() {\n\texpect(6);\n\n\tt( \"Comma Support\", \"h2, #qunit-fixture p\", [\"qunit-banner\",\"qunit-userAgent\",\"firstp\",\"ap\",\"sndp\",\"en\",\"sap\",\"first\"] );\n\tt( \"Comma Support\", \"h2 , #qunit-fixture p\", [\"qunit-banner\",\"qunit-userAgent\",\"firstp\",\"ap\",\"sndp\",\"en\",\"sap\",\"first\"] );\n\tt( \"Comma Support\", \"h2 , #qunit-fixture p\", [\"qunit-banner\",\"qunit-userAgent\",\"firstp\",\"ap\",\"sndp\",\"en\",\"sap\",\"first\"] );\n\tt( \"Comma Support\", \"h2,#qunit-fixture p\", [\"qunit-banner\",\"qunit-userAgent\",\"firstp\",\"ap\",\"sndp\",\"en\",\"sap\",\"first\"] );\n\tt( \"Comma Support\", \"h2,#qunit-fixture p \", [\"qunit-banner\",\"qunit-userAgent\",\"firstp\",\"ap\",\"sndp\",\"en\",\"sap\",\"first\"] );\n\tt( \"Comma Support\", \"h2\\t,\\r#qunit-fixture p\\n\", [\"qunit-banner\",\"qunit-userAgent\",\"firstp\",\"ap\",\"sndp\",\"en\",\"sap\",\"first\"] );\n});\n\ntest(\"child and adjacent\", function() {\n\texpect( 42 );\n\n\tvar siblingFirst, en, nothiddendiv;\n\n\tt( \"Child\", \"p > a\", [\"simon1\",\"google\",\"groups\",\"mark\",\"yahoo\",\"simon\"] );\n\tt( \"Child\", \"p> a\", [\"simon1\",\"google\",\"groups\",\"mark\",\"yahoo\",\"simon\"] );\n\tt( \"Child\", \"p >a\", [\"simon1\",\"google\",\"groups\",\"mark\",\"yahoo\",\"simon\"] );\n\tt( \"Child\", \"p>a\", [\"simon1\",\"google\",\"groups\",\"mark\",\"yahoo\",\"simon\"] );\n\tt( \"Child w/ Class\", \"p > a.blog\", [\"mark\",\"simon\"] );\n\tt( \"All Children\", \"code > *\", [\"anchor1\",\"anchor2\"] );\n\tt( \"All Grandchildren\", \"p > * > *\", [\"anchor1\",\"anchor2\"] );\n\tt( \"Adjacent\", \"#qunit-fixture a + a\", [\"groups\", \"tName2ID\"] );\n\tt( \"Adjacent\", \"#qunit-fixture a +a\", [\"groups\", \"tName2ID\"] );\n\tt( \"Adjacent\", \"#qunit-fixture a+ a\", [\"groups\", \"tName2ID\"] );\n\tt( \"Adjacent\", \"#qunit-fixture a+a\", [\"groups\", \"tName2ID\"] );\n\tt( \"Adjacent\", \"p + p\", [\"ap\",\"en\",\"sap\"] );\n\tt( \"Adjacent\", \"p#firstp + p\", [\"ap\"] );\n\tt( \"Adjacent\", \"p[lang=en] + p\", [\"sap\"] );\n\tt( \"Adjacent\", \"a.GROUPS + code + a\", [\"mark\"] );\n\tt( \"Comma, Child, and Adjacent\", \"#qunit-fixture a + a, code > a\", [\"groups\",\"anchor1\",\"anchor2\",\"tName2ID\"] );\n\tt( \"Element Preceded By\", \"#qunit-fixture p ~ div\", [\"foo\", \"nothiddendiv\", \"moretests\",\"tabindex-tests\", \"liveHandlerOrder\", \"siblingTest\"] );\n\tt( \"Element Preceded By\", \"#first ~ div\", [\"moretests\",\"tabindex-tests\", \"liveHandlerOrder\", \"siblingTest\"] );\n\tt( \"Element Preceded By\", \"#groups ~ a\", [\"mark\"] );\n\tt( \"Element Preceded By\", \"#length ~ input\", [\"idTest\"] );\n\tt( \"Element Preceded By\", \"#siblingfirst ~ em\", [\"siblingnext\", \"siblingthird\"] );\n\tt( \"Element Preceded By (multiple)\", \"#siblingTest em ~ em ~ em ~ span\", [\"siblingspan\"] );\n\tt( \"Element Preceded By, Containing\", \"#liveHandlerOrder ~ div em:contains('1')\", [\"siblingfirst\"] );\n\n\tsiblingFirst = document.getElementById(\"siblingfirst\");\n\n\tdeepEqual( Sizzle(\"~ em\", siblingFirst), q(\"siblingnext\", \"siblingthird\"), \"Element Preceded By with a context.\" );\n\tdeepEqual( Sizzle(\"+ em\", siblingFirst), q(\"siblingnext\"), \"Element Directly Preceded By with a context.\" );\n\tdeepEqual( Sizzle(\"~ em:first\", siblingFirst), q(\"siblingnext\"), \"Element Preceded By positional with a context.\" );\n\n\ten = document.getElementById(\"en\");\n\tdeepEqual( Sizzle(\"+ p, a\", en), q(\"yahoo\", \"sap\"), \"Compound selector with context, beginning with sibling test.\" );\n\tdeepEqual( Sizzle(\"a, + p\", en), q(\"yahoo\", \"sap\"), \"Compound selector with context, containing sibling test.\" );\n\n\tt( \"Multiple combinators selects all levels\", \"#siblingTest em *\", [\"siblingchild\", \"siblinggrandchild\", \"siblinggreatgrandchild\"] );\n\tt( \"Multiple combinators selects all levels\", \"#siblingTest > em *\", [\"siblingchild\", \"siblinggrandchild\", \"siblinggreatgrandchild\"] );\n\tt( \"Multiple sibling combinators doesn't miss general siblings\", \"#siblingTest > em:first-child + em ~ span\", [\"siblingspan\"] );\n\tt( \"Combinators are not skipped when mixing general and specific\", \"#siblingTest > em:contains('x') + em ~ span\", [] );\n\n\tequal( Sizzle(\"#listWithTabIndex\").length, 1, \"Parent div for next test is found via ID (#8310)\" );\n\tequal( Sizzle(\"#listWithTabIndex li:eq(2) ~ li\").length, 1, \"Find by general sibling combinator (#8310)\" );\n\tequal( Sizzle(\"#__sizzle__\").length, 0, \"Make sure the temporary id assigned by sizzle is cleared out (#8310)\" );\n\tequal( Sizzle(\"#listWithTabIndex\").length, 1, \"Parent div for previous test is still found via ID (#8310)\" );\n\n\tt( \"Verify deep class selector\", \"div.blah > p > a\", [] );\n\n\tt( \"No element deep selector\", \"div.foo > span > a\", [] );\n\n\tnothiddendiv = document.getElementById(\"nothiddendiv\");\n\tdeepEqual( Sizzle(\"> :first\", nothiddendiv), q(\"nothiddendivchild\"), \"Verify child context positional selector\" );\n\tdeepEqual( Sizzle(\"> :eq(0)\", nothiddendiv), q(\"nothiddendivchild\"), \"Verify child context positional selector\" );\n\tdeepEqual( Sizzle(\"> *:first\", nothiddendiv), q(\"nothiddendivchild\"), \"Verify child context positional selector\" );\n\n\tt( \"Non-existant ancestors\", \".fototab > .thumbnails > a\", [] );\n});\n\ntest(\"attributes\", function() {\n\texpect( 76 );\n\n\tvar opt, input, attrbad, div;\n\n\tt( \"Attribute Exists\", \"#qunit-fixture a[title]\", [\"google\"] );\n\tt( \"Attribute Exists (case-insensitive)\", \"#qunit-fixture a[TITLE]\", [\"google\"] );\n\tt( \"Attribute Exists\", \"#qunit-fixture *[title]\", [\"google\"] );\n\tt( \"Attribute Exists\", \"#qunit-fixture [title]\", [\"google\"] );\n\tt( \"Attribute Exists\", \"#qunit-fixture a[ title ]\", [\"google\"] );\n\n\tt( \"Boolean attribute exists\", \"#select2 option[selected]\", [\"option2d\"]);\n\tt( \"Boolean attribute equals\", \"#select2 option[selected='selected']\", [\"option2d\"]);\n\n\tt( \"Attribute Equals\", \"#qunit-fixture a[rel='bookmark']\", [\"simon1\"] );\n\tt( \"Attribute Equals\", \"#qunit-fixture a[rel='bookmark']\", [\"simon1\"] );\n\tt( \"Attribute Equals\", \"#qunit-fixture a[rel=bookmark]\", [\"simon1\"] );\n\tt( \"Attribute Equals\", \"#qunit-fixture a[href='http://www.google.com/']\", [\"google\"] );\n\tt( \"Attribute Equals\", \"#qunit-fixture a[ rel = 'bookmark' ]\", [\"simon1\"] );\n\tt( \"Attribute Equals Number\", \"#qunit-fixture option[value=1]\", [\"option1b\",\"option2b\",\"option3b\",\"option4b\",\"option5c\"] );\n\tt( \"Attribute Equals Number\", \"#qunit-fixture li[tabIndex=-1]\", [\"foodWithNegativeTabIndex\"] );\n\n\tdocument.getElementById(\"anchor2\").href = \"#2\";\n\tt( \"href Attribute\", \"p a[href^=#]\", [\"anchor2\"] );\n\tt( \"href Attribute\", \"p a[href*=#]\", [\"simon1\", \"anchor2\"] );\n\n\tt( \"for Attribute\", \"form label[for]\", [\"label-for\"] );\n\tt( \"for Attribute in form\", \"#form [for=action]\", [\"label-for\"] );\n\n\tt( \"Attribute containing []\", \"input[name^='foo[']\", [\"hidden2\"] );\n\tt( \"Attribute containing []\", \"input[name^='foo[bar]']\", [\"hidden2\"] );\n\tt( \"Attribute containing []\", \"input[name*='[bar]']\", [\"hidden2\"] );\n\tt( \"Attribute containing []\", \"input[name$='bar]']\", [\"hidden2\"] );\n\tt( \"Attribute containing []\", \"input[name$='[bar]']\", [\"hidden2\"] );\n\tt( \"Attribute containing []\", \"input[name$='foo[bar]']\", [\"hidden2\"] );\n\tt( \"Attribute containing []\", \"input[name*='foo[bar]']\", [\"hidden2\"] );\n\n\tdeepEqual( Sizzle( \"input[data-comma='0,1']\" ), [ document.getElementById(\"el12087\") ], \"Without context, single-quoted attribute containing ','\" );\n\tdeepEqual( Sizzle( \"input[data-comma=\\\"0,1\\\"]\" ), [ document.getElementById(\"el12087\") ], \"Without context, double-quoted attribute containing ','\" );\n\tdeepEqual( Sizzle( \"input[data-comma='0,1']\", document.getElementById(\"t12087\") ), [ document.getElementById(\"el12087\") ], \"With context, single-quoted attribute containing ','\" );\n\tdeepEqual( Sizzle( \"input[data-comma=\\\"0,1\\\"]\", document.getElementById(\"t12087\") ), [ document.getElementById(\"el12087\") ], \"With context, double-quoted attribute containing ','\" );\n\n\tt( \"Multiple Attribute Equals\", \"#form input[type='radio'], #form input[type='hidden']\", [\"radio1\", \"radio2\", \"hidden1\"] );\n\tt( \"Multiple Attribute Equals\", \"#form input[type='radio'], #form input[type=\\\"hidden\\\"]\", [\"radio1\", \"radio2\", \"hidden1\"] );\n\tt( \"Multiple Attribute Equals\", \"#form input[type='radio'], #form input[type=hidden]\", [\"radio1\", \"radio2\", \"hidden1\"] );\n\n\tt( \"Attribute selector using UTF8\", \"span[lang=中文]\", [\"台北\"] );\n\n\tt( \"Attribute Begins With\", \"a[href ^= 'http://www']\", [\"google\",\"yahoo\"] );\n\tt( \"Attribute Ends With\", \"a[href $= 'org/']\", [\"mark\"] );\n\tt( \"Attribute Contains\", \"a[href *= 'google']\", [\"google\",\"groups\"] );\n\tt( \"Attribute Is Not Equal\", \"#ap a[hreflang!='en']\", [\"google\",\"groups\",\"anchor1\"] );\n\n\topt = document.getElementById(\"option1a\");\n\topt.setAttribute( \"test\", \"\" );\n\n\tok( Sizzle.matchesSelector( opt, \"[id*=option1][type!=checkbox]\" ), \"Attribute Is Not Equal Matches\" );\n\tok( Sizzle.matchesSelector( opt, \"[id*=option1]\" ), \"Attribute With No Quotes Contains Matches\" );\n\tok( Sizzle.matchesSelector( opt, \"[test=]\" ), \"Attribute With No Quotes No Content Matches\" );\n\tok( !Sizzle.matchesSelector( opt, \"[test^='']\" ), \"Attribute with empty string value does not match startsWith selector (^=)\" );\n\tok( Sizzle.matchesSelector( opt, \"[id=option1a]\" ), \"Attribute With No Quotes Equals Matches\" );\n\tok( Sizzle.matchesSelector( document.getElementById(\"simon1\"), \"a[href*=#]\" ), \"Attribute With No Quotes Href Contains Matches\" );\n\n\tt( \"Empty values\", \"#select1 option[value='']\", [\"option1a\"] );\n\tt( \"Empty values\", \"#select1 option[value!='']\", [\"option1b\",\"option1c\",\"option1d\"] );\n\n\tt( \"Select options via :selected\", \"#select1 option:selected\", [\"option1a\"] );\n\tt( \"Select options via :selected\", \"#select2 option:selected\", [\"option2d\"] );\n\tt( \"Select options via :selected\", \"#select3 option:selected\", [\"option3b\", \"option3c\"] );\n\tt( \"Select options via :selected\", \"select[name='select2'] option:selected\", [\"option2d\"] );\n\n\tt( \"Grouped Form Elements\", \"input[name='foo[bar]']\", [\"hidden2\"] );\n\n\tinput = document.getElementById(\"text1\");\n\tinput.title = \"Don't click me\";\n\n\tok( Sizzle.matchesSelector( input, \"input[title=\\\"Don't click me\\\"]\" ), \"Quote within attribute value does not mess up tokenizer\" );\n\n\t// Uncomment if the boolHook is removed\n\t// var check2 = document.getElementById(\"check2\");\n\t// check2.checked = true;\n\t// ok( !Sizzle.matches(\"[checked]\", [ check2 ] ), \"Dynamic boolean attributes match when they should with Sizzle.matches (#11115)\" );\n\n\t// jQuery #12303\n\tinput.setAttribute( \"data-pos\", \":first\" );\n\tok( Sizzle.matchesSelector( input, \"input[data-pos=\\\\:first]\"), \"POS within attribute value is treated as an attribute value\" );\n\tok( Sizzle.matchesSelector( input, \"input[data-pos=':first']\"), \"POS within attribute value is treated as an attribute value\" );\n\tok( Sizzle.matchesSelector( input, \":input[data-pos=':first']\"), \"POS within attribute value after pseudo is treated as an attribute value\" );\n\tinput.removeAttribute(\"data-pos\");\n\n\t// Make sure attribute value quoting works correctly. See jQuery #6093; #6428; #13894\n\t// Use seeded results to bypass querySelectorAll optimizations\n\tattrbad = jQuery(\n\t\t\"<input type='hidden' id='attrbad_space' name='foo bar'/>\" +\n\t\t\"<input type='hidden' id='attrbad_dot' value='2' name='foo.baz'/>\" +\n\t\t\"<input type='hidden' id='attrbad_brackets' value='2' name='foo[baz]'/>\" +\n\t\t\"<input type='hidden' id='attrbad_injection' data-attr='foo_baz&#39;]'/>\" +\n\t\t\"<input type='hidden' id='attrbad_quote' data-attr='&#39;'/>\" +\n\t\t\"<input type='hidden' id='attrbad_backslash' data-attr='&#92;'/>\" +\n\t\t\"<input type='hidden' id='attrbad_backslash_quote' data-attr='&#92;&#39;'/>\" +\n\t\t\"<input type='hidden' id='attrbad_backslash_backslash' data-attr='&#92;&#92;'/>\" +\n\t\t\"<input type='hidden' id='attrbad_unicode' data-attr='&#x4e00;'/>\"\n\t).appendTo(\"#qunit-fixture\").get();\n\n\tt( \"Underscores don't need escaping\", \"input[id=types_all]\", [\"types_all\"] );\n\n\tdeepEqual( Sizzle( \"input[name=foo\\\\ bar]\", null, null, attrbad ), q(\"attrbad_space\"),\n\t\t\"Escaped space\" );\n\tdeepEqual( Sizzle( \"input[name=foo\\\\.baz]\", null, null, attrbad ), q(\"attrbad_dot\"),\n\t\t\"Escaped dot\" );\n\tdeepEqual( Sizzle( \"input[name=foo\\\\[baz\\\\]]\", null, null, attrbad ), q(\"attrbad_brackets\"),\n\t\t\"Escaped brackets\" );\n\tdeepEqual( Sizzle( \"input[data-attr='foo_baz\\\\']']\", null, null, attrbad ), q(\"attrbad_injection\"),\n\t\t\"Escaped quote + right bracket\" );\n\n\tdeepEqual( Sizzle( \"input[data-attr='\\\\'']\", null, null, attrbad ), q(\"attrbad_quote\"),\n\t\t\"Quoted quote\" );\n\tdeepEqual( Sizzle( \"input[data-attr='\\\\\\\\']\", null, null, attrbad ), q(\"attrbad_backslash\"),\n\t\t\"Quoted backslash\" );\n\tdeepEqual( Sizzle( \"input[data-attr='\\\\\\\\\\\\'']\", null, null, attrbad ), q(\"attrbad_backslash_quote\"),\n\t\t\"Quoted backslash quote\" );\n\tdeepEqual( Sizzle( \"input[data-attr='\\\\\\\\\\\\\\\\']\", null, null, attrbad ), q(\"attrbad_backslash_backslash\"),\n\t\t\"Quoted backslash backslash\" );\n\n\tdeepEqual( Sizzle( \"input[data-attr='\\\\5C\\\\\\\\']\", null, null, attrbad ), q(\"attrbad_backslash_backslash\"),\n\t\t\"Quoted backslash backslash (numeric escape)\" );\n\tdeepEqual( Sizzle( \"input[data-attr='\\\\5C \\\\\\\\']\", null, null, attrbad ), q(\"attrbad_backslash_backslash\"),\n\t\t\"Quoted backslash backslash (numeric escape with trailing space)\" );\n\tdeepEqual( Sizzle( \"input[data-attr='\\\\5C\\t\\\\\\\\']\", null, null, attrbad ), q(\"attrbad_backslash_backslash\"),\n\t\t\"Quoted backslash backslash (numeric escape with trailing tab)\" );\n\tdeepEqual( Sizzle( \"input[data-attr='\\\\04e00']\", null, null, attrbad ), q(\"attrbad_unicode\"),\n\t\t\"Long numeric escape (BMP)\" );\n\tdocument.getElementById(\"attrbad_unicode\").setAttribute( \"data-attr\", \"\\uD834\\uDF06A\" );\n\t// It was too much code to fix Safari 5.x Supplemental Plane crashes (see ba5f09fa404379a87370ec905ffa47f8ac40aaa3)\n\t// deepEqual( Sizzle( \"input[data-attr='\\\\01D306A']\", null, null, attrbad ), q(\"attrbad_unicode\"),\n\t// \t\"Long numeric escape (non-BMP)\" );\n\n\tt( \"input[type=text]\", \"#form input[type=text]\", [\"text1\", \"text2\", \"hidden2\", \"name\"] );\n\tt( \"input[type=search]\", \"#form input[type=search]\", [\"search\"] );\n\tt( \"script[src] (jQuery #13777)\", \"#moretests script[src]\", [\"script-src\"] );\n\n\t// #3279\n\tdiv = document.createElement(\"div\");\n\tdiv.innerHTML = \"<div id='foo' xml:test='something'></div>\";\n\n\tdeepEqual( Sizzle( \"[xml\\\\:test]\", div ), [ div.firstChild ], \"Finding by attribute with escaped characters.\" );\n\n\tdiv = document.getElementById(\"foo\");\n\tt( \"Object.prototype property \\\"constructor\\\" (negative)\", \"[constructor]\", [] );\n\tt( \"Gecko Object.prototype property \\\"watch\\\" (negative)\", \"[watch]\", [] );\n\tdiv.setAttribute( \"constructor\", \"foo\" );\n\tdiv.setAttribute( \"watch\", \"bar\" );\n\tt( \"Object.prototype property \\\"constructor\\\"\", \"[constructor='foo']\", [\"foo\"] );\n\tt( \"Gecko Object.prototype property \\\"watch\\\"\", \"[watch='bar']\", [\"foo\"] );\n\n\tt( \"Value attribute is retrieved correctly\", \"input[value=Test]\", [\"text1\", \"text2\"] );\n});\n\ntest(\"pseudo - (parent|empty)\", function() {\n\texpect( 3 );\n\tt( \"Empty\", \"ul:empty\", [\"firstUL\"] );\n\tt( \"Empty with comment node\", \"ol:empty\", [\"empty\"] );\n\tt( \"Is A Parent\", \"#qunit-fixture p:parent\", [\"firstp\",\"ap\",\"sndp\",\"en\",\"sap\",\"first\"] );\n});\n\ntest(\"pseudo - (first|last|only)-(child|of-type)\", function() {\n\texpect( 12 );\n\n\tt( \"First Child\", \"p:first-child\", [\"firstp\",\"sndp\"] );\n\tt( \"First Child (leading id)\", \"#qunit-fixture p:first-child\", [\"firstp\",\"sndp\"] );\n\tt( \"First Child (leading class)\", \".nothiddendiv div:first-child\", [\"nothiddendivchild\"] );\n\tt( \"First Child (case-insensitive)\", \"#qunit-fixture p:FIRST-CHILD\", [\"firstp\",\"sndp\"] );\n\n\tt( \"Last Child\", \"p:last-child\", [\"sap\"] );\n\tt( \"Last Child (leading id)\", \"#qunit-fixture a:last-child\", [\"simon1\",\"anchor1\",\"mark\",\"yahoo\",\"anchor2\",\"simon\",\"liveLink1\",\"liveLink2\"] );\n\n\tt( \"Only Child\", \"#qunit-fixture a:only-child\", [\"simon1\",\"anchor1\",\"yahoo\",\"anchor2\",\"liveLink1\",\"liveLink2\"] );\n\n\tt( \"First-of-type\", \"#qunit-fixture > p:first-of-type\", [\"firstp\"] );\n\tt( \"Last-of-type\", \"#qunit-fixture > p:last-of-type\", [\"first\"] );\n\tt( \"Only-of-type\", \"#qunit-fixture > :only-of-type\", [\"name+value\", \"firstUL\", \"empty\", \"floatTest\", \"iframe\", \"table\"] );\n\n\t// Verify that the child position isn't being cached improperly\n\tvar secondChildren = jQuery(\"p:nth-child(2)\").before(\"<div></div>\");\n\n\tt( \"No longer second child\", \"p:nth-child(2)\", [] );\n\tsecondChildren.prev().remove();\n\tt( \"Restored second child\", \"p:nth-child(2)\", [\"ap\",\"en\"] );\n});\n\ntest(\"pseudo - nth-child\", function() {\n\texpect( 30 );\n\n\tt( \"Nth-child\", \"p:nth-child(1)\", [\"firstp\",\"sndp\"] );\n\tt( \"Nth-child (with whitespace)\", \"p:nth-child( 1 )\", [\"firstp\",\"sndp\"] );\n\tt( \"Nth-child (case-insensitive)\", \"#form select:first option:NTH-child(3)\", [\"option1c\"] );\n\tt( \"Not nth-child\", \"#qunit-fixture p:not(:nth-child(1))\", [\"ap\",\"en\",\"sap\",\"first\"] );\n\n\tt( \"Nth-child(2)\", \"#qunit-fixture form#form > *:nth-child(2)\", [\"text1\"] );\n\tt( \"Nth-child(2)\", \"#qunit-fixture form#form > :nth-child(2)\", [\"text1\"] );\n\n\tt( \"Nth-child(-1)\", \"#form select:first option:nth-child(-1)\", [] );\n\tt( \"Nth-child(3)\", \"#form select:first option:nth-child(3)\", [\"option1c\"] );\n\tt( \"Nth-child(0n+3)\", \"#form select:first option:nth-child(0n+3)\", [\"option1c\"] );\n\tt( \"Nth-child(1n+0)\", \"#form select:first option:nth-child(1n+0)\", [\"option1a\", \"option1b\", \"option1c\", \"option1d\"] );\n\tt( \"Nth-child(1n)\", \"#form select:first option:nth-child(1n)\", [\"option1a\", \"option1b\", \"option1c\", \"option1d\"] );\n\tt( \"Nth-child(n)\", \"#form select:first option:nth-child(n)\", [\"option1a\", \"option1b\", \"option1c\", \"option1d\"] );\n\tt( \"Nth-child(even)\", \"#form select:first option:nth-child(even)\", [\"option1b\", \"option1d\"] );\n\tt( \"Nth-child(odd)\", \"#form select:first option:nth-child(odd)\", [\"option1a\", \"option1c\"] );\n\tt( \"Nth-child(2n)\", \"#form select:first option:nth-child(2n)\", [\"option1b\", \"option1d\"] );\n\tt( \"Nth-child(2n+1)\", \"#form select:first option:nth-child(2n+1)\", [\"option1a\", \"option1c\"] );\n\tt( \"Nth-child(2n + 1)\", \"#form select:first option:nth-child(2n + 1)\", [\"option1a\", \"option1c\"] );\n\tt( \"Nth-child(+2n + 1)\", \"#form select:first option:nth-child(+2n + 1)\", [\"option1a\", \"option1c\"] );\n\tt( \"Nth-child(3n)\", \"#form select:first option:nth-child(3n)\", [\"option1c\"] );\n\tt( \"Nth-child(3n+1)\", \"#form select:first option:nth-child(3n+1)\", [\"option1a\", \"option1d\"] );\n\tt( \"Nth-child(3n+2)\", \"#form select:first option:nth-child(3n+2)\", [\"option1b\"] );\n\tt( \"Nth-child(3n+3)\", \"#form select:first option:nth-child(3n+3)\", [\"option1c\"] );\n\tt( \"Nth-child(3n-1)\", \"#form select:first option:nth-child(3n-1)\", [\"option1b\"] );\n\tt( \"Nth-child(3n-2)\", \"#form select:first option:nth-child(3n-2)\", [\"option1a\", \"option1d\"] );\n\tt( \"Nth-child(3n-3)\", \"#form select:first option:nth-child(3n-3)\", [\"option1c\"] );\n\tt( \"Nth-child(3n+0)\", \"#form select:first option:nth-child(3n+0)\", [\"option1c\"] );\n\tt( \"Nth-child(-1n+3)\", \"#form select:first option:nth-child(-1n+3)\", [\"option1a\", \"option1b\", \"option1c\"] );\n\tt( \"Nth-child(-n+3)\", \"#form select:first option:nth-child(-n+3)\", [\"option1a\", \"option1b\", \"option1c\"] );\n\tt( \"Nth-child(-1n + 3)\", \"#form select:first option:nth-child(-1n + 3)\", [\"option1a\", \"option1b\", \"option1c\"] );\n\n\tdeepEqual( Sizzle( \":nth-child(n)\", null, null, [ document.createElement(\"a\") ].concat( q(\"ap\") ) ), q(\"ap\"), \"Seeded nth-child\" );\n});\n\ntest(\"pseudo - nth-last-child\", function() {\n\texpect( 30 );\n\n\tt( \"Nth-last-child\", \"form:nth-last-child(5)\", [\"testForm\"] );\n\tt( \"Nth-last-child (with whitespace)\", \"form:nth-last-child( 5 )\", [\"testForm\"] );\n\tt( \"Nth-last-child (case-insensitive)\", \"#form select:first option:NTH-last-child(3)\", [\"option1b\"] );\n\tt( \"Not nth-last-child\", \"#qunit-fixture p:not(:nth-last-child(1))\", [\"firstp\", \"ap\", \"sndp\", \"en\", \"first\"] );\n\n\tt( \"Nth-last-child(-1)\", \"#form select:first option:nth-last-child(-1)\", [] );\n\tt( \"Nth-last-child(3)\", \"#form select:first :nth-last-child(3)\", [\"option1b\"] );\n\tt( \"Nth-last-child(3)\", \"#form select:first *:nth-last-child(3)\", [\"option1b\"] );\n\tt( \"Nth-last-child(3)\", \"#form select:first option:nth-last-child(3)\", [\"option1b\"] );\n\tt( \"Nth-last-child(0n+3)\", \"#form select:first option:nth-last-child(0n+3)\", [\"option1b\"] );\n\tt( \"Nth-last-child(1n+0)\", \"#form select:first option:nth-last-child(1n+0)\", [\"option1a\", \"option1b\", \"option1c\", \"option1d\"] );\n\tt( \"Nth-last-child(1n)\", \"#form select:first option:nth-last-child(1n)\", [\"option1a\", \"option1b\", \"option1c\", \"option1d\"] );\n\tt( \"Nth-last-child(n)\", \"#form select:first option:nth-last-child(n)\", [\"option1a\", \"option1b\", \"option1c\", \"option1d\"] );\n\tt( \"Nth-last-child(even)\", \"#form select:first option:nth-last-child(even)\", [\"option1a\", \"option1c\"] );\n\tt( \"Nth-last-child(odd)\", \"#form select:first option:nth-last-child(odd)\", [\"option1b\", \"option1d\"] );\n\tt( \"Nth-last-child(2n)\", \"#form select:first option:nth-last-child(2n)\", [\"option1a\", \"option1c\"] );\n\tt( \"Nth-last-child(2n+1)\", \"#form select:first option:nth-last-child(2n+1)\", [\"option1b\", \"option1d\"] );\n\tt( \"Nth-last-child(2n + 1)\", \"#form select:first option:nth-last-child(2n + 1)\", [\"option1b\", \"option1d\"] );\n\tt( \"Nth-last-child(+2n + 1)\", \"#form select:first option:nth-last-child(+2n + 1)\", [\"option1b\", \"option1d\"] );\n\tt( \"Nth-last-child(3n)\", \"#form select:first option:nth-last-child(3n)\", [\"option1b\"] );\n\tt( \"Nth-last-child(3n+1)\", \"#form select:first option:nth-last-child(3n+1)\", [\"option1a\", \"option1d\"] );\n\tt( \"Nth-last-child(3n+2)\", \"#form select:first option:nth-last-child(3n+2)\", [\"option1c\"] );\n\tt( \"Nth-last-child(3n+3)\", \"#form select:first option:nth-last-child(3n+3)\", [\"option1b\"] );\n\tt( \"Nth-last-child(3n-1)\", \"#form select:first option:nth-last-child(3n-1)\", [\"option1c\"] );\n\tt( \"Nth-last-child(3n-2)\", \"#form select:first option:nth-last-child(3n-2)\", [\"option1a\", \"option1d\"] );\n\tt( \"Nth-last-child(3n-3)\", \"#form select:first option:nth-last-child(3n-3)\", [\"option1b\"] );\n\tt( \"Nth-last-child(3n+0)\", \"#form select:first option:nth-last-child(3n+0)\", [\"option1b\"] );\n\tt( \"Nth-last-child(-1n+3)\", \"#form select:first option:nth-last-child(-1n+3)\", [\"option1b\", \"option1c\", \"option1d\"] );\n\tt( \"Nth-last-child(-n+3)\", \"#form select:first option:nth-last-child(-n+3)\", [\"option1b\", \"option1c\", \"option1d\"] );\n\tt( \"Nth-last-child(-1n + 3)\", \"#form select:first option:nth-last-child(-1n + 3)\", [\"option1b\", \"option1c\", \"option1d\"] );\n\n\tdeepEqual( Sizzle( \":nth-last-child(n)\", null, null, [ document.createElement(\"a\") ].concat( q(\"ap\") ) ), q(\"ap\"), \"Seeded nth-last-child\" );\n});\n\ntest(\"pseudo - nth-of-type\", function() {\n\texpect( 9 );\n\tt( \"Nth-of-type(-1)\", \":nth-of-type(-1)\", [] );\n\tt( \"Nth-of-type(3)\", \"#ap :nth-of-type(3)\", [\"mark\"] );\n\tt( \"Nth-of-type(n)\", \"#ap :nth-of-type(n)\", [\"google\", \"groups\", \"code1\", \"anchor1\", \"mark\"] );\n\tt( \"Nth-of-type(0n+3)\", \"#ap :nth-of-type(0n+3)\", [\"mark\"] );\n\tt( \"Nth-of-type(2n)\", \"#ap :nth-of-type(2n)\", [\"groups\"] );\n\tt( \"Nth-of-type(even)\", \"#ap :nth-of-type(even)\", [\"groups\"] );\n\tt( \"Nth-of-type(2n+1)\", \"#ap :nth-of-type(2n+1)\", [\"google\", \"code1\", \"anchor1\", \"mark\"] );\n\tt( \"Nth-of-type(odd)\", \"#ap :nth-of-type(odd)\", [\"google\", \"code1\", \"anchor1\", \"mark\"] );\n\tt( \"Nth-of-type(-n+2)\", \"#qunit-fixture > :nth-of-type(-n+2)\", [\"firstp\", \"ap\", \"foo\", \"nothiddendiv\", \"name+value\", \"firstUL\", \"empty\", \"form\", \"floatTest\", \"iframe\", \"lengthtest\", \"table\"] );\n});\n\ntest(\"pseudo - nth-last-of-type\", function() {\n\texpect( 9 );\n\tt( \"Nth-last-of-type(-1)\", \":nth-last-of-type(-1)\", [] );\n\tt( \"Nth-last-of-type(3)\", \"#ap :nth-last-of-type(3)\", [\"google\"] );\n\tt( \"Nth-last-of-type(n)\", \"#ap :nth-last-of-type(n)\", [\"google\", \"groups\", \"code1\", \"anchor1\", \"mark\"] );\n\tt( \"Nth-last-of-type(0n+3)\", \"#ap :nth-last-of-type(0n+3)\", [\"google\"] );\n\tt( \"Nth-last-of-type(2n)\", \"#ap :nth-last-of-type(2n)\", [\"groups\"] );\n\tt( \"Nth-last-of-type(even)\", \"#ap :nth-last-of-type(even)\", [\"groups\"] );\n\tt( \"Nth-last-of-type(2n+1)\", \"#ap :nth-last-of-type(2n+1)\", [\"google\", \"code1\", \"anchor1\", \"mark\"] );\n\tt( \"Nth-last-of-type(odd)\", \"#ap :nth-last-of-type(odd)\", [\"google\", \"code1\", \"anchor1\", \"mark\"] );\n\tt( \"Nth-last-of-type(-n+2)\", \"#qunit-fixture > :nth-last-of-type(-n+2)\", [\"ap\", \"name+value\", \"first\", \"firstUL\", \"empty\", \"floatTest\", \"iframe\", \"table\", \"name-tests\", \"testForm\", \"liveHandlerOrder\", \"siblingTest\"] );\n});\n\ntest(\"pseudo - has\", function() {\n\texpect( 3 );\n\n\tt( \"Basic test\", \"p:has(a)\", [\"firstp\",\"ap\",\"en\",\"sap\"] );\n\tt( \"Basic test (irrelevant whitespace)\", \"p:has( a )\", [\"firstp\",\"ap\",\"en\",\"sap\"] );\n\tt( \"Nested with overlapping candidates\", \"#qunit-fixture div:has(div:has(div:not([id])))\", [ \"moretests\", \"t2037\" ] );\n});\n\ntest(\"pseudo - misc\", function() {\n\texpect( 39 );\n\n\tvar select, tmp, input;\n\n\tt( \"Headers\", \":header\", [\"qunit-header\", \"qunit-banner\", \"qunit-userAgent\"] );\n\tt( \"Headers(case-insensitive)\", \":Header\", [\"qunit-header\", \"qunit-banner\", \"qunit-userAgent\"] );\n\tt( \"Multiple matches with the same context (cache check)\", \"#form select:has(option:first-child:contains('o'))\", [\"select1\", \"select2\", \"select3\", \"select4\"] );\n\n\tok( Sizzle(\"#qunit-fixture :not(:has(:has(*)))\").length, \"All not grandparents\" );\n\n\tselect = document.getElementById(\"select1\");\n\tok( Sizzle.matchesSelector( select, \":has(option)\" ), \"Has Option Matches\" );\n\n\tok( Sizzle(\"a:contains('')\").length, \"Empty string contains\" );\n\tt( \"Text Contains\", \"a:contains(Google)\", [\"google\",\"groups\"] );\n\tt( \"Text Contains\", \"a:contains(Google Groups)\", [\"groups\"] );\n\n\tt( \"Text Contains\", \"a:contains('Google Groups (Link)')\", [\"groups\"] );\n\tt( \"Text Contains\", \"a:contains(\\\"(Link)\\\")\", [\"groups\"] );\n\tt( \"Text Contains\", \"a:contains(Google Groups (Link))\", [\"groups\"] );\n\tt( \"Text Contains\", \"a:contains((Link))\", [\"groups\"] );\n\n\n\ttmp = document.createElement(\"div\");\n\ttmp.id = \"tmp_input\";\n\tdocument.body.appendChild( tmp );\n\n\tjQuery.each( [ \"button\", \"submit\", \"reset\" ], function( i, type ) {\n\t\tvar els = jQuery(\n\t\t\t\"<input id='input_%' type='%'/><button id='button_%' type='%'>test</button>\"\n\t\t\t.replace( /%/g, type )\n\t\t).appendTo( tmp );\n\n\t\tt( \"Input Buttons :\" + type, \"#tmp_input :\" + type, [ \"input_\" + type, \"button_\" + type ] );\n\n\t\tok( Sizzle.matchesSelector( els[0], \":\" + type ), \"Input Matches :\" + type );\n\t\tok( Sizzle.matchesSelector( els[1], \":\" + type ), \"Button Matches :\" + type );\n\t});\n\n\tdocument.body.removeChild( tmp );\n\n\t// Recreate tmp\n\ttmp = document.createElement(\"div\");\n\ttmp.id = \"tmp_input\";\n\ttmp.innerHTML = \"<span>Hello I am focusable.</span>\";\n\t// Setting tabIndex should make the element focusable\n\t// http://dev.w3.org/html5/spec/single-page.html#focus-management\n\tdocument.body.appendChild( tmp );\n\ttmp.tabIndex = 0;\n\ttmp.focus();\n\tif ( document.activeElement !== tmp || (document.hasFocus && !document.hasFocus()) ||\n\t\t(document.querySelectorAll && !document.querySelectorAll(\"div:focus\").length) ) {\n\t\tok( true, \"The div was not focused. Skip checking the :focus match.\" );\n\t\tok( true, \"The div was not focused. Skip checking the :focus match.\" );\n\t} else {\n\t\tt( \"tabIndex element focused\", \":focus\", [ \"tmp_input\" ] );\n\t\tok( Sizzle.matchesSelector( tmp, \":focus\" ), \":focus matches tabIndex div\" );\n\t}\n\n\t// Blur tmp\n\ttmp.blur();\n\tdocument.body.focus();\n\tok( !Sizzle.matchesSelector( tmp, \":focus\" ), \":focus doesn't match tabIndex div\" );\n\tdocument.body.removeChild( tmp );\n\n\t// Input focus/active\n\tinput = document.createElement(\"input\");\n\tinput.type = \"text\";\n\tinput.id = \"focus-input\";\n\n\tdocument.body.appendChild( input );\n\tinput.focus();\n\n\t// Inputs can't be focused unless the document has focus\n\tif ( document.activeElement !== input || (document.hasFocus && !document.hasFocus()) ||\n\t\t(document.querySelectorAll && !document.querySelectorAll(\"input:focus\").length) ) {\n\t\tok( true, \"The input was not focused. Skip checking the :focus match.\" );\n\t\tok( true, \"The input was not focused. Skip checking the :focus match.\" );\n\t} else {\n\t\tt( \"Element focused\", \"input:focus\", [ \"focus-input\" ] );\n\t\tok( Sizzle.matchesSelector( input, \":focus\" ), \":focus matches\" );\n\t}\n\n\tinput.blur();\n\n\t// When IE is out of focus, blur does not work. Force it here.\n\tif ( document.activeElement === input ) {\n\t\tdocument.body.focus();\n\t}\n\n\tok( !Sizzle.matchesSelector( input, \":focus\" ), \":focus doesn't match\" );\n\tdocument.body.removeChild( input );\n\n\n\n\tdeepEqual(\n\t\tSizzle( \"[id='select1'] *:not(:last-child), [id='select2'] *:not(:last-child)\", q(\"qunit-fixture\")[0] ),\n\t\tq( \"option1a\", \"option1b\", \"option1c\", \"option2a\", \"option2b\", \"option2c\" ),\n\t\t\"caching system tolerates recursive selection\"\n\t);\n\n\t// Tokenization edge cases\n\tt( \"Sequential pseudos\", \"#qunit-fixture p:has(:contains(mark)):has(code)\", [\"ap\"] );\n\tt( \"Sequential pseudos\", \"#qunit-fixture p:has(:contains(mark)):has(code):contains(This link)\", [\"ap\"] );\n\n\tt( \"Pseudo argument containing ')'\", \"p:has(>a.GROUPS[src!=')'])\", [\"ap\"] );\n\tt( \"Pseudo argument containing ')'\", \"p:has(>a.GROUPS[src!=')'])\", [\"ap\"] );\n\tt( \"Pseudo followed by token containing ')'\", \"p:contains(id=\\\"foo\\\")[id!=\\\\)]\", [\"sndp\"] );\n\tt( \"Pseudo followed by token containing ')'\", \"p:contains(id=\\\"foo\\\")[id!=')']\", [\"sndp\"] );\n\n\tt( \"Multi-pseudo\", \"#ap:has(*), #ap:has(*)\", [\"ap\"] );\n\tt( \"Multi-positional\", \"#ap:gt(0), #ap:lt(1)\", [\"ap\"] );\n\tt( \"Multi-pseudo with leading nonexistent id\", \"#nonexistent:has(*), #ap:has(*)\", [\"ap\"] );\n\tt( \"Multi-positional with leading nonexistent id\", \"#nonexistent:gt(0), #ap:lt(1)\", [\"ap\"] );\n\n\tt( \"Tokenization stressor\", \"a[class*=blog]:not(:has(*, :contains(!)), :contains(!)), br:contains(]), p:contains(]), :not(:empty):not(:parent)\", [\"ap\", \"mark\",\"yahoo\",\"simon\"] );\n});\n\n\ntest(\"pseudo - :not\", function() {\n\texpect( 43 );\n\n\tt( \"Not\", \"a.blog:not(.link)\", [\"mark\"] );\n\tt( \":not() with :first\", \"#foo p:not(:first) .link\", [\"simon\"] );\n\n\tt( \"Not - multiple\", \"#form option:not(:contains(Nothing),#option1b,:selected)\", [\"option1c\", \"option1d\", \"option2b\", \"option2c\", \"option3d\", \"option3e\", \"option4e\", \"option5b\", \"option5c\"] );\n\tt( \"Not - recursive\", \"#form option:not(:not(:selected))[id^='option3']\", [ \"option3b\", \"option3c\"] );\n\n\tt( \":not() failing interior\", \"#qunit-fixture p:not(.foo)\", [\"firstp\",\"ap\",\"sndp\",\"en\",\"sap\",\"first\"] );\n\tt( \":not() failing interior\", \"#qunit-fixture p:not(div.foo)\", [\"firstp\",\"ap\",\"sndp\",\"en\",\"sap\",\"first\"] );\n\tt( \":not() failing interior\", \"#qunit-fixture p:not(p.foo)\", [\"firstp\",\"ap\",\"sndp\",\"en\",\"sap\",\"first\"] );\n\tt( \":not() failing interior\", \"#qunit-fixture p:not(#blargh)\", [\"firstp\",\"ap\",\"sndp\",\"en\",\"sap\",\"first\"] );\n\tt( \":not() failing interior\", \"#qunit-fixture p:not(div#blargh)\", [\"firstp\",\"ap\",\"sndp\",\"en\",\"sap\",\"first\"] );\n\tt( \":not() failing interior\", \"#qunit-fixture p:not(p#blargh)\", [\"firstp\",\"ap\",\"sndp\",\"en\",\"sap\",\"first\"] );\n\n\tt( \":not Multiple\", \"#qunit-fixture p:not(a)\", [\"firstp\",\"ap\",\"sndp\",\"en\",\"sap\",\"first\"] );\n\tt( \":not Multiple\", \"#qunit-fixture p:not( a )\", [\"firstp\",\"ap\",\"sndp\",\"en\",\"sap\",\"first\"] );\n\tt( \":not Multiple\", \"#qunit-fixture p:not( p )\", [] );\n\tt( \":not Multiple\", \"#qunit-fixture p:not(a, b)\", [\"firstp\",\"ap\",\"sndp\",\"en\",\"sap\",\"first\"] );\n\tt( \":not Multiple\", \"#qunit-fixture p:not(a, b, div)\", [\"firstp\",\"ap\",\"sndp\",\"en\",\"sap\",\"first\"] );\n\tt( \":not Multiple\", \"p:not(p)\", [] );\n\tt( \":not Multiple\", \"p:not(a,p)\", [] );\n\tt( \":not Multiple\", \"p:not(p,a)\", [] );\n\tt( \":not Multiple\", \"p:not(a,p,b)\", [] );\n\tt( \":not Multiple\", \":input:not(:image,:input,:submit)\", [] );\n\tt( \":not Multiple\", \"#qunit-fixture p:not(:has(a), :nth-child(1))\", [\"first\"] );\n\n\tt( \"No element not selector\", \".container div:not(.excluded) div\", [] );\n\n\tt( \":not() Existing attribute\", \"#form select:not([multiple])\", [\"select1\", \"select2\", \"select5\"]);\n\tt( \":not() Equals attribute\", \"#form select:not([name=select1])\", [\"select2\", \"select3\", \"select4\",\"select5\"]);\n\tt( \":not() Equals quoted attribute\", \"#form select:not([name='select1'])\", [\"select2\", \"select3\", \"select4\", \"select5\"]);\n\n\tt( \":not() Multiple Class\", \"#foo a:not(.blog)\", [\"yahoo\", \"anchor2\"] );\n\tt( \":not() Multiple Class\", \"#foo a:not(.link)\", [\"yahoo\", \"anchor2\"] );\n\tt( \":not() Multiple Class\", \"#foo a:not(.blog.link)\", [\"yahoo\", \"anchor2\"] );\n\n\tt( \":not chaining (compound)\", \"#qunit-fixture div[id]:not(:has(div, span)):not(:has(*))\", [\"nothiddendivchild\", \"divWithNoTabIndex\"] );\n\tt( \":not chaining (with attribute)\", \"#qunit-fixture form[id]:not([action$='formaction']):not(:button)\", [\"lengthtest\", \"name-tests\", \"testForm\"] );\n\tt( \":not chaining (colon in attribute)\", \"#qunit-fixture form[id]:not([action='form:action']):not(:button)\", [\"form\", \"lengthtest\", \"name-tests\", \"testForm\"] );\n\tt( \":not chaining (colon in attribute and nested chaining)\", \"#qunit-fixture form[id]:not([action='form:action']:button):not(:input)\", [\"form\", \"lengthtest\", \"name-tests\", \"testForm\"] );\n\tt( \":not chaining\", \"#form select:not(.select1):contains(Nothing) > option:not(option)\", [] );\n\n\tt( \"positional :not()\", \"#foo p:not(:last)\", [\"sndp\", \"en\"] );\n\tt( \"positional :not() prefix\", \"#foo p:not(:last) a\", [\"yahoo\"] );\n\tt( \"compound positional :not()\", \"#foo p:not(:first, :last)\", [\"en\"] );\n\tt( \"compound positional :not()\", \"#foo p:not(:first, :even)\", [\"en\"] );\n\tt( \"compound positional :not()\", \"#foo p:not(:first, :odd)\", [\"sap\"] );\n\tt( \"reordered compound positional :not()\", \"#foo p:not(:odd, :first)\", [\"sap\"] );\n\n\tt( \"positional :not() with pre-filter\", \"#foo p:not([id]:first)\", [\"en\", \"sap\"] );\n\tt( \"positional :not() with post-filter\", \"#foo p:not(:first[id])\", [\"en\", \"sap\"] );\n\tt( \"positional :not() with pre-filter\", \"#foo p:not([lang]:first)\", [\"sndp\", \"sap\"] );\n\tt( \"positional :not() with post-filter\", \"#foo p:not(:first[lang])\", [\"sndp\", \"en\", \"sap\"] );\n});\n\ntest(\"pseudo - position\", function() {\n\texpect( 33 );\n\n\tt( \"First element\", \"div:first\", [\"qunit\"] );\n\tt( \"First element(case-insensitive)\", \"div:fiRst\", [\"qunit\"] );\n\tt( \"nth Element\", \"#qunit-fixture p:nth(1)\", [\"ap\"] );\n\tt( \"First Element\", \"#qunit-fixture p:first\", [\"firstp\"] );\n\tt( \"Last Element\", \"p:last\", [\"first\"] );\n\tt( \"Even Elements\", \"#qunit-fixture p:even\", [\"firstp\",\"sndp\",\"sap\"] );\n\tt( \"Odd Elements\", \"#qunit-fixture p:odd\", [\"ap\",\"en\",\"first\"] );\n\tt( \"Position Equals\", \"#qunit-fixture p:eq(1)\", [\"ap\"] );\n\tt( \"Position Equals (negative)\", \"#qunit-fixture p:eq(-1)\", [\"first\"] );\n\tt( \"Position Greater Than\", \"#qunit-fixture p:gt(0)\", [\"ap\",\"sndp\",\"en\",\"sap\",\"first\"] );\n\tt( \"Position Less Than\", \"#qunit-fixture p:lt(3)\", [\"firstp\",\"ap\",\"sndp\"] );\n\n\tt( \"Check position filtering\", \"div#nothiddendiv:eq(0)\", [\"nothiddendiv\"] );\n\tt( \"Check position filtering\", \"div#nothiddendiv:last\", [\"nothiddendiv\"] );\n\tt( \"Check position filtering\", \"div#nothiddendiv:not(:gt(0))\", [\"nothiddendiv\"] );\n\tt( \"Check position filtering\", \"#foo > :not(:first)\", [\"en\", \"sap\"] );\n\tt( \"Check position filtering\", \"#qunit-fixture select > :not(:gt(2))\", [\"option1a\", \"option1b\", \"option1c\"] );\n\tt( \"Check position filtering\", \"#qunit-fixture select:lt(2) :not(:first)\", [\"option1b\", \"option1c\", \"option1d\", \"option2a\", \"option2b\", \"option2c\", \"option2d\"] );\n\tt( \"Check position filtering\", \"div.nothiddendiv:eq(0)\", [\"nothiddendiv\"] );\n\tt( \"Check position filtering\", \"div.nothiddendiv:last\", [\"nothiddendiv\"] );\n\tt( \"Check position filtering\", \"div.nothiddendiv:not(:lt(0))\", [\"nothiddendiv\"] );\n\n\tt( \"Check element position\", \"#qunit-fixture div div:eq(0)\", [\"nothiddendivchild\"] );\n\tt( \"Check element position\", \"#select1 option:eq(3)\", [\"option1d\"] );\n\tt( \"Check element position\", \"#qunit-fixture div div:eq(10)\", [\"names-group\"] );\n\tt( \"Check element position\", \"#qunit-fixture div div:first\", [\"nothiddendivchild\"] );\n\tt( \"Check element position\", \"#qunit-fixture div > div:first\", [\"nothiddendivchild\"] );\n\tt( \"Check element position\", \"#dl div:first div:first\", [\"foo\"] );\n\tt( \"Check element position\", \"#dl div:first > div:first\", [\"foo\"] );\n\tt( \"Check element position\", \"div#nothiddendiv:first > div:first\", [\"nothiddendivchild\"] );\n\tt( \"Chained pseudo after a pos pseudo\", \"#listWithTabIndex li:eq(0):contains(Rice)\", [\"foodWithNegativeTabIndex\"] );\n\n\tt( \"Check sort order with POS and comma\", \"#qunit-fixture em>em>em>em:first-child,div>em:first\", [\"siblingfirst\", \"siblinggreatgrandchild\"] );\n\n\tt( \"Isolated position\", \":last\", [\"last\"] );\n\n\tdeepEqual( Sizzle( \"*:lt(2) + *\", null, [], Sizzle(\"#qunit-fixture > p\") ), q(\"ap\"), \"Seeded pos with trailing relative\" );\n\n\t// jQuery #12526\n\tvar context = jQuery(\"#qunit-fixture\").append(\"<div id='jquery12526'></div>\")[0];\n\tdeepEqual( Sizzle( \":last\", context ), q(\"jquery12526\"), \"Post-manipulation positional\" );\n});\n\ntest(\"pseudo - form\", function() {\n\texpect( 10 );\n\n\tvar extraTexts = jQuery(\"<input id=\\\"impliedText\\\"/><input id=\\\"capitalText\\\" type=\\\"TEXT\\\">\").appendTo(\"#form\");\n\n\tt( \"Form element :input\", \"#form :input\", [\"text1\", \"text2\", \"radio1\", \"radio2\", \"check1\", \"check2\", \"hidden1\", \"hidden2\", \"name\", \"search\", \"button\", \"area1\", \"select1\", \"select2\", \"select3\", \"select4\", \"select5\", \"impliedText\", \"capitalText\"] );\n\tt( \"Form element :radio\", \"#form :radio\", [\"radio1\", \"radio2\"] );\n\tt( \"Form element :checkbox\", \"#form :checkbox\", [\"check1\", \"check2\"] );\n\tt( \"Form element :text\", \"#form :text\", [\"text1\", \"text2\", \"hidden2\", \"name\", \"impliedText\", \"capitalText\"] );\n\tt( \"Form element :radio:checked\", \"#form :radio:checked\", [\"radio2\"] );\n\tt( \"Form element :checkbox:checked\", \"#form :checkbox:checked\", [\"check1\"] );\n\tt( \"Form element :radio:checked, :checkbox:checked\", \"#form :radio:checked, #form :checkbox:checked\", [\"radio2\", \"check1\"] );\n\n\tt( \"Selected Option Element\", \"#form option:selected\", [\"option1a\",\"option2d\",\"option3b\",\"option3c\",\"option4b\",\"option4c\",\"option4d\",\"option5a\"] );\n\tt( \"Selected Option Element are also :checked\", \"#form option:checked\", [\"option1a\",\"option2d\",\"option3b\",\"option3c\",\"option4b\",\"option4c\",\"option4d\",\"option5a\"] );\n\tt( \"Hidden inputs should be treated as enabled. See QSA test.\", \"#hidden1:enabled\", [\"hidden1\"] );\n\n\textraTexts.remove();\n});\n\ntest(\"pseudo - :target and :root\", function() {\n\texpect( 2 );\n\n\t// Target\n\tvar oldHash,\n\t$link = jQuery(\"<a/>\").attr({\n\t\thref: \"#\",\n\t\tid: \"new-link\"\n\t}).appendTo(\"#qunit-fixture\");\n\n\toldHash = window.location.hash;\n\twindow.location.hash = \"new-link\";\n\n\tt( \":target\", \":target\", [\"new-link\"] );\n\n\t$link.remove();\n\twindow.location.hash = oldHash;\n\n\t// Root\n\tequal( Sizzle(\":root\")[0], document.documentElement, \":root selector\" );\n});\n\ntest(\"pseudo - :lang\", function() {\n\texpect( 105 );\n\n\tvar docElem = document.documentElement,\n\t\tdocXmlLang = docElem.getAttribute(\"xml:lang\"),\n\t\tdocLang = docElem.lang,\n\t\tfoo = document.getElementById(\"foo\"),\n\t\tanchor = document.getElementById(\"anchor2\"),\n\t\txml = createWithFriesXML(),\n\t\ttestLang = function( text, elem, container, lang, extra ) {\n\t\t\tvar message,\n\t\t\t\tfull = lang + \"-\" + extra;\n\n\t\t\tmessage = \"lang=\" + lang + \" \" + text;\n\t\t\tcontainer.setAttribute( container.ownerDocument.documentElement.nodeName === \"HTML\" ? \"lang\" : \"xml:lang\", lang );\n\t\t\tassertMatch( message, elem, \":lang(\" + lang + \")\" );\n\t\t\tassertMatch( message, elem, \":lang(\" + mixCase(lang) + \")\" );\n\t\t\tassertNoMatch( message, elem, \":lang(\" + full + \")\" );\n\t\t\tassertNoMatch( message, elem, \":lang(\" + mixCase(full) + \")\" );\n\t\t\tassertNoMatch( message, elem, \":lang(\" + lang + \"-)\" );\n\t\t\tassertNoMatch( message, elem, \":lang(\" + full + \"-)\" );\n\t\t\tassertNoMatch( message, elem, \":lang(\" + lang + \"glish)\" );\n\t\t\tassertNoMatch( message, elem, \":lang(\" + full + \"glish)\" );\n\n\t\t\tmessage = \"lang=\" + full + \" \" + text;\n\t\t\tcontainer.setAttribute( container.ownerDocument.documentElement.nodeName === \"HTML\" ? \"lang\" : \"xml:lang\", full );\n\t\t\tassertMatch( message, elem, \":lang(\" + lang + \")\" );\n\t\t\tassertMatch( message, elem, \":lang(\" + mixCase(lang) + \")\" );\n\t\t\tassertMatch( message, elem, \":lang(\" + full + \")\" );\n\t\t\tassertMatch( message, elem, \":lang(\" + mixCase(full) + \")\" );\n\t\t\tassertNoMatch( message, elem, \":lang(\" + lang + \"-)\" );\n\t\t\tassertNoMatch( message, elem, \":lang(\" + full + \"-)\" );\n\t\t\tassertNoMatch( message, elem, \":lang(\" + lang + \"glish)\" );\n\t\t\tassertNoMatch( message, elem, \":lang(\" + full + \"glish)\" );\n\t\t},\n\t\tmixCase = function( str ) {\n\t\t\tvar ret = str.split(\"\"),\n\t\t\t\ti = ret.length;\n\t\t\twhile ( i-- ) {\n\t\t\t\tif ( i & 1 ) {\n\t\t\t\t\tret[i] = ret[i].toUpperCase();\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn ret.join(\"\");\n\t\t},\n\t\tassertMatch = function( text, elem, selector ) {\n\t\t\tok( Sizzle.matchesSelector( elem, selector ), text + \" match \" + selector );\n\t\t},\n\t\tassertNoMatch = function( text, elem, selector ) {\n\t\t\tok( !Sizzle.matchesSelector( elem, selector ), text + \" fail \" + selector );\n\t\t};\n\n\t// Prefixing and inheritance\n\tok( Sizzle.matchesSelector( docElem, \":lang(\" + docElem.lang + \")\" ), \"starting :lang\" );\n\ttestLang( \"document\", anchor, docElem, \"en\", \"us\" );\n\ttestLang( \"grandparent\", anchor, anchor.parentNode.parentNode, \"yue\", \"hk\" );\n\tok( !Sizzle.matchesSelector( anchor, \":lang(en), :lang(en-us)\" ),\n\t\t\":lang does not look above an ancestor with specified lang\" );\n\ttestLang( \"self\", anchor, anchor, \"es\", \"419\" );\n\tok( !Sizzle.matchesSelector( anchor, \":lang(en), :lang(en-us), :lang(yue), :lang(yue-hk)\" ),\n\t\t\":lang does not look above self with specified lang\" );\n\n\t// Searching by language tag\n\tanchor.parentNode.parentNode.lang = \"arab\";\n\tanchor.parentNode.lang = anchor.parentNode.id = \"ara-sa\";\n\tanchor.lang = \"ara\";\n\tdeepEqual( Sizzle( \":lang(ara)\", foo ), [ anchor.parentNode, anchor ], \"Find by :lang\" );\n\n\t// Selector validity\n\tanchor.parentNode.lang = \"ara\";\n\tanchor.lang = \"ara\\\\b\";\n\tdeepEqual( Sizzle( \":lang(ara\\\\b)\", foo ), [], \":lang respects backslashes\" );\n\tdeepEqual( Sizzle( \":lang(ara\\\\\\\\b)\", foo ), [ anchor ], \":lang respects escaped backslashes\" );\n\traises(function() {\n\t\tSizzle.call( null, \"dl:lang(c++)\" );\n\t}, function( e ) {\n\t\treturn e.message.indexOf(\"Syntax error\") >= 0;\n\t}, \":lang value must be a valid identifier\" );\n\n\t// XML\n\tfoo = jQuery( \"response\", xml )[0];\n\tanchor = jQuery( \"#seite1\", xml )[0];\n\ttestLang( \"XML document\", anchor, xml.documentElement, \"en\", \"us\" );\n\ttestLang( \"XML grandparent\", anchor, foo, \"yue\", \"hk\" );\n\tok( !Sizzle.matchesSelector( anchor, \":lang(en), :lang(en-us)\" ),\n\t\t\"XML :lang does not look above an ancestor with specified lang\" );\n\ttestLang( \"XML self\", anchor, anchor, \"es\", \"419\" );\n\tok( !Sizzle.matchesSelector( anchor, \":lang(en), :lang(en-us), :lang(yue), :lang(yue-hk)\" ),\n\t\t\"XML :lang does not look above self with specified lang\" );\n\n\t// Cleanup\n\tif ( docXmlLang == null ) {\n\t\tdocElem.removeAttribute(\"xml:lang\");\n\t} else {\n\t\tdocElem.setAttribute( \"xml:lang\", docXmlLang );\n\t}\n\tdocElem.lang = docLang;\n});\n\ntest(\"caching\", function() {\n\texpect( 2 );\n\tSizzle( \":not(code)\", document.getElementById(\"ap\") );\n\tdeepEqual( Sizzle( \":not(code)\", document.getElementById(\"foo\") ), q(\"sndp\", \"en\", \"yahoo\", \"sap\", \"anchor2\", \"simon\"), \"Reusing selector with new context\" );\n\n\tt( \"Deep ancestry caching in post-positional element matcher (jQuery #14657)\",\n\t\t\"#qunit-fixture a:lt(3):parent\",\n\t\t[ \"simon1\", \"google\", \"groups\" ] );\n});\n\nasyncTest( \"Iframe dispatch should not affect Sizzle, see jQuery #13936\", 1, function() {\n\tvar loaded = false,\n\t\tthrown = false,\n\t\tiframe = document.getElementById(\"iframe\"),\n\t\tiframeDoc = iframe.contentDocument || iframe.contentWindow.document;\n\n\tjQuery( iframe ).on( \"load\", function() {\n\t\tvar form;\n\n\t\ttry {\n\t\t\tiframeDoc = this.contentDocument || this.contentWindow.document;\n\t\t\tform = Sizzle( \"#navigate\", iframeDoc )[ 0 ];\n\t\t} catch ( e ) {\n\t\t\tthrown = e;\n\t\t}\n\n\t\tif ( loaded ) {\n\t\t\tstrictEqual( thrown, false, \"No error thrown from post-reload Sizzle call\" );\n\t\t\tstart();\n\t\t} else {\n\t\t\tloaded = true;\n\t\t\tform.submit();\n\t\t}\n\t});\n\n\tiframeDoc.open();\n\tiframeDoc.write(\"<body><form id='navigate'></form></body>\");\n\tiframeDoc.close();\n});\n\ntest(\"matchesSelector\", function() {\n\texpect( 6 );\n\n\tvar el = document.getElementById(\"simon1\"),\n\t\tdisconnected = document.createElement(\"div\");\n\n\tok( Sizzle.matchesSelector( el, \"[rel='bookmark']\" ), \"quoted attribute\" );\n\tok( Sizzle.matchesSelector( el, \"[rel=bookmark]\" ), \"unquoted attribute\" );\n\tok( Sizzle.matchesSelector( el, \"[\\nrel = bookmark\\t]\" ), \"unquoted attribute with non-semantic whitespace\" );\n\n\tok( Sizzle.matchesSelector( disconnected, \"div\" ), \"disconnected element\" );\n\n\tok( Sizzle.matchesSelector( el, \"* > *\" ), \"child combinator (matching)\" );\n\tok( !Sizzle.matchesSelector( disconnected, \"* > *\" ), \"child combinator (not matching)\" );\n});\n"
  },
  {
    "path": "flowable-ui-web/idm/libs/sizzle_1.10.16/test/unit/utilities.js",
    "content": "module(\"utilities\", { teardown: moduleTeardown });\n\nfunction testAttr( doc ) {\n\texpect( 9 );\n\n\tvar el;\n\tif ( doc ) {\n\t\t// XML\n\t\tel = doc.createElement( \"input\" );\n\t\tel.setAttribute( \"type\", \"checkbox\" );\n\t} else {\n\t\t// Set checked on creation by creating with a fragment\n\t\t// See http://jsfiddle.net/8sVgA/1/show/light in oldIE\n\t\tel = jQuery( \"<input type='checkbox' checked='checked' />\" )[0];\n\t}\n\n\t// Set it again for good measure\n\tel.setAttribute( \"checked\", \"checked\" );\n\tel.setAttribute( \"id\", \"id\" );\n\tel.setAttribute( \"value\", \"on\" );\n\n\tstrictEqual( Sizzle.attr( el, \"nonexistent\" ), null, \"nonexistent\" );\n\tstrictEqual( Sizzle.attr( el, \"id\" ), \"id\", \"existent\" );\n\tstrictEqual( Sizzle.attr( el, \"value\" ), \"on\", \"value\" );\n\tstrictEqual( Sizzle.attr( el, \"checked\" ), \"checked\", \"boolean\" );\n\tstrictEqual( Sizzle.attr( el, \"href\" ), null, \"interpolation risk\" );\n\tstrictEqual( Sizzle.attr( el, \"constructor\" ), null,\n\t\t\"Object.prototype property \\\"constructor\\\" (negative)\" );\n\tstrictEqual( Sizzle.attr( el, \"watch\" ), null,\n\t\t\"Gecko Object.prototype property \\\"watch\\\" (negative)\" );\n\tel.setAttribute( \"constructor\", \"foo\" );\n\tel.setAttribute( \"watch\", \"bar\" );\n\tstrictEqual( Sizzle.attr( el, \"constructor\" ), \"foo\",\n\t\t\"Object.prototype property \\\"constructor\\\"\" );\n\tstrictEqual( Sizzle.attr( el, \"watch\" ), \"bar\",\n\t\t\"Gecko Object.prototype property \\\"watch\\\"\" );\n}\n\ntest(\"Sizzle.attr (HTML)\", function() {\n\ttestAttr();\n});\n\ntest(\"Sizzle.attr (XML)\", function() {\n\ttestAttr( jQuery.parseXML(\"<root/>\") );\n});\n\ntest(\"Sizzle.contains\", function() {\n\texpect( 16 );\n\n\tvar container = document.getElementById(\"nonnodes\"),\n\t\telement = container.firstChild,\n\t\ttext = element.nextSibling,\n\t\tnonContained = container.nextSibling,\n\t\tdetached = document.createElement(\"a\");\n\tok( element && element.nodeType === 1, \"preliminary: found element\" );\n\tok( text && text.nodeType === 3, \"preliminary: found text\" );\n\tok( nonContained, \"preliminary: found non-descendant\" );\n\tok( Sizzle.contains(container, element), \"child\" );\n\tok( Sizzle.contains(container.parentNode, element), \"grandchild\" );\n\tok( Sizzle.contains(container, text), \"text child\" );\n\tok( Sizzle.contains(container.parentNode, text), \"text grandchild\" );\n\tok( !Sizzle.contains(container, container), \"self\" );\n\tok( !Sizzle.contains(element, container), \"parent\" );\n\tok( !Sizzle.contains(container, nonContained), \"non-descendant\" );\n\tok( !Sizzle.contains(container, document), \"document\" );\n\tok( !Sizzle.contains(container, document.documentElement), \"documentElement (negative)\" );\n\tok( !Sizzle.contains(container, null), \"Passing null does not throw an error\" );\n\tok( Sizzle.contains(document, document.documentElement), \"documentElement (positive)\" );\n\tok( Sizzle.contains(document, element), \"document container (positive)\" );\n\tok( !Sizzle.contains(document, detached), \"document container (negative)\" );\n});\n\nif ( jQuery(\"<svg xmlns='http://www.w3.org/2000/svg' version='1.1' height='1' width='1'><g/></svg>\")[0].firstChild ) {\n\ttest(\"Sizzle.contains in SVG (jQuery #10832)\", function() {\n\t\texpect( 4 );\n\n\t\tvar svg = jQuery(\n\t\t\t\"<svg xmlns='http://www.w3.org/2000/svg' version='1.1' height='1' width='1'>\" +\n\t\t\t\t\"<g><circle cx='1' cy='1' r='1' /></g>\" +\n\t\t\t\"</svg>\"\n\t\t).appendTo(\"#qunit-fixture\")[0];\n\n\t\tok( Sizzle.contains( svg, svg.firstChild ), \"root child\" );\n\t\tok( Sizzle.contains( svg.firstChild, svg.firstChild.firstChild ), \"element child\" );\n\t\tok( Sizzle.contains( svg, svg.firstChild.firstChild ), \"root granchild\" );\n\t\tok( !Sizzle.contains( svg.firstChild.firstChild, svg.firstChild ), \"parent (negative)\" );\n\t});\n}\n\ntest(\"Sizzle.uniqueSort\", function() {\n\texpect( 14 );\n\n\tfunction Arrayish( arr ) {\n\t\tvar i = this.length = arr.length;\n\t\twhile ( i-- ) {\n\t\t\tthis[ i ] = arr[ i ];\n\t\t}\n\t}\n\tArrayish.prototype = {\n\t\tslice: [].slice,\n\t\tsort: [].sort,\n\t\tsplice: [].splice\n\t};\n\n\tvar i, tests,\n\t\tdetached = [],\n\t\tbody = document.body,\n\t\tfixture = document.getElementById(\"qunit-fixture\"),\n\t\tdetached1 = document.createElement(\"p\"),\n\t\tdetached2 = document.createElement(\"ul\"),\n\t\tdetachedChild = detached1.appendChild( document.createElement(\"a\") ),\n\t\tdetachedGrandchild = detachedChild.appendChild( document.createElement(\"b\") );\n\n\tfor ( i = 0; i < 12; i++ ) {\n\t\tdetached.push( document.createElement(\"li\") );\n\t\tdetached[i].id = \"detached\" + i;\n\t\tdetached2.appendChild( document.createElement(\"li\") ).id = \"detachedChild\" + i;\n\t}\n\n\ttests = {\n\t\t\"Empty\": {\n\t\t\tinput: [],\n\t\t\texpected: []\n\t\t},\n\t\t\"Single-element\": {\n\t\t\tinput: [ fixture ],\n\t\t\texpected: [ fixture ]\n\t\t},\n\t\t\"No duplicates\": {\n\t\t\tinput: [ fixture, body ],\n\t\t\texpected: [ body, fixture ]\n\t\t},\n\t\t\"Duplicates\": {\n\t\t\tinput: [ body, fixture, fixture, body ],\n\t\t\texpected: [ body, fixture ]\n\t\t},\n\t\t\"Detached\": {\n\t\t\tinput: detached.slice( 0 ),\n\t\t\texpected: detached.slice( 0 )\n\t\t},\n\t\t\"Detached children\": {\n\t\t\tinput: [\n\t\t\t\tdetached2.childNodes[0],\n\t\t\t\tdetached2.childNodes[1],\n\t\t\t\tdetached2.childNodes[2],\n\t\t\t\tdetached2.childNodes[3]\n\t\t\t],\n\t\t\texpected: [\n\t\t\t\tdetached2.childNodes[0],\n\t\t\t\tdetached2.childNodes[1],\n\t\t\t\tdetached2.childNodes[2],\n\t\t\t\tdetached2.childNodes[3]\n\t\t\t]\n\t\t},\n\t\t\"Attached/detached mixture\": {\n\t\t\tinput: [ detached1, fixture, detached2, document, detachedChild, body, detachedGrandchild ],\n\t\t\texpected: [ document, body, fixture ],\n\t\t\tlength: 3\n\t\t}\n\t};\n\n\tjQuery.each( tests, function( label, test ) {\n\t\tvar length = test.length || test.input.length;\n\t\tdeepEqual( Sizzle.uniqueSort( test.input ).slice( 0, length ), test.expected, label + \" (array)\" );\n\t\tdeepEqual( Sizzle.uniqueSort( new Arrayish(test.input) ).slice( 0, length ), test.expected, label + \" (quasi-array)\" );\n\t});\n});\n\ntestIframeWithCallback( \"Sizzle.uniqueSort works cross-window (jQuery #14381)\", \"mixed_sort.html\", deepEqual );\n"
  },
  {
    "path": "flowable-ui-web/idm/libs/ui-grid_3.0.0/ui-grid.css",
    "content": "/*!\n * ui-grid - v3.0.0-rc.19 - 2015-02-11\n * Copyright (c) 2015 ; License: MIT \n */\n.ui-grid {\n  border: 1px solid #d4d4d4;\n  box-sizing: content-box;\n  -webkit-border-radius: 0px;\n  -moz-border-radius: 0px;\n  border-radius: 0px;\n  -webkit-transform: translateZ(0);\n  -moz-transform: translateZ(0);\n  -o-transform: translateZ(0);\n  -ms-transform: translateZ(0);\n  transform: translateZ(0);\n}\n.ui-grid-vertical-bar {\n  position: absolute;\n  right: 0;\n  width: 0;\n}\n.ui-grid-header-cell:not(:last-child) .ui-grid-vertical-bar,\n.ui-grid-cell:not(:last-child) .ui-grid-vertical-bar {\n  width: 1px;\n}\n.ui-grid-header-cell:not(:last-child) .ui-grid-vertical-bar {\n  background-color: #d4d4d4;\n}\n.ui-grid-cell:not(:last-child) .ui-grid-vertical-bar {\n  background-color: #d4d4d4;\n}\n.ui-grid-header-cell:last-child .ui-grid-vertical-bar {\n  right: -1px;\n  width: 1px;\n  background-color: #d4d4d4;\n}\n.ui-grid-clearfix:before,\n.ui-grid-clearfix:after {\n  content: \"\";\n  display: table;\n}\n.ui-grid-clearfix:after {\n  clear: both;\n}\n.ui-grid-invisible {\n  visibility: hidden;\n}\n.ui-grid-top-panel-background {\n  background: #f3f3f3;\n  background: -webkit-gradient(linear, left bottom, left top, color-stop(0, #eeeeee), color-stop(1, #ffffff));\n  background: -ms-linear-gradient(bottom, #eeeeee, #ffffff);\n  background: -moz-linear-gradient(center bottom, #eeeeee 0%, #ffffff 100%);\n  background: -o-linear-gradient(#ffffff, #eeeeee);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#eeeeee', GradientType=0);\n}\n.ui-grid-header {\n  border-bottom: 1px solid #d4d4d4;\n  box-sizing: content-box;\n}\n.ui-grid-top-panel {\n  position: relative;\n  overflow: hidden;\n  font-weight: bold;\n  background: #f3f3f3;\n  background: -webkit-gradient(linear, left bottom, left top, color-stop(0, #eeeeee), color-stop(1, #ffffff));\n  background: -ms-linear-gradient(bottom, #eeeeee, #ffffff);\n  background: -moz-linear-gradient(center bottom, #eeeeee 0%, #ffffff 100%);\n  background: -o-linear-gradient(#ffffff, #eeeeee);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#eeeeee', GradientType=0);\n  -webkit-border-top-right-radius: -1px;\n  -webkit-border-bottom-right-radius: 0;\n  -webkit-border-bottom-left-radius: 0;\n  -webkit-border-top-left-radius: -1px;\n  -moz-border-radius-topright: -1px;\n  -moz-border-radius-bottomright: 0;\n  -moz-border-radius-bottomleft: 0;\n  -moz-border-radius-topleft: -1px;\n  border-top-right-radius: -1px;\n  border-bottom-right-radius: 0;\n  border-bottom-left-radius: 0;\n  border-top-left-radius: -1px;\n  -moz-background-clip: padding-box;\n  -webkit-background-clip: padding-box;\n  background-clip: padding-box;\n}\n.ui-grid-header-viewport {\n  overflow: hidden;\n}\n.ui-grid-header-canvas {\n  position: relative;\n}\n.ui-grid-header-canvas:before,\n.ui-grid-header-canvas:after {\n  content: \"\";\n  display: table;\n  line-height: 0;\n}\n.ui-grid-header-canvas:after {\n  clear: both;\n}\n.ui-grid-header-cell {\n  position: relative;\n  box-sizing: border-box;\n  float: left;\n  top: 0;\n  bottom: 0;\n  background-color: inherit;\n  border-right: 1px solid;\n  border-color: #d4d4d4;\n  -webkit-user-select: none;\n  -moz-user-select: none;\n  -ms-user-select: none;\n  user-select: none;\n  width: 0;\n}\n.ui-grid-header-cell .sortable {\n  cursor: pointer;\n}\n.ui-grid-header .ui-grid-vertical-bar {\n  top: 0;\n  bottom: 0;\n}\n.ui-grid-column-menu-button {\n  position: absolute;\n  right: 1px;\n  top: 0;\n}\n.ui-grid-column-menu-button .ui-grid-icon-angle-down {\n  vertical-align: sub;\n}\n.ui-grid-column-menu-button-last-col {\n  margin-right: 25px;\n}\n.ui-grid-column-menu {\n  position: absolute;\n}\n/* Slide up/down animations */\n.ui-grid-column-menu .ui-grid-menu .ui-grid-menu-mid.ng-hide-add,\n.ui-grid-column-menu .ui-grid-menu .ui-grid-menu-mid.ng-hide-remove {\n  -webkit-transition: all 0.05s linear;\n  -moz-transition: all 0.05s linear;\n  -o-transition: all 0.05s linear;\n  transition: all 0.05s linear;\n  display: block !important;\n}\n.ui-grid-column-menu .ui-grid-menu .ui-grid-menu-mid.ng-hide-add.ng-hide-add-active,\n.ui-grid-column-menu .ui-grid-menu .ui-grid-menu-mid.ng-hide-remove {\n  -webkit-transform: translateY(-100%);\n  -moz-transform: translateY(-100%);\n  -o-transform: translateY(-100%);\n  -ms-transform: translateY(-100%);\n  transform: translateY(-100%);\n}\n.ui-grid-column-menu .ui-grid-menu .ui-grid-menu-mid.ng-hide-add,\n.ui-grid-column-menu .ui-grid-menu .ui-grid-menu-mid.ng-hide-remove.ng-hide-remove-active {\n  -webkit-transform: translateY(0);\n  -moz-transform: translateY(0);\n  -o-transform: translateY(0);\n  -ms-transform: translateY(0);\n  transform: translateY(0);\n}\n/* Slide up/down animations */\n.ui-grid-menu-button .ui-grid-menu .ui-grid-menu-mid.ng-hide-add,\n.ui-grid-menu-button .ui-grid-menu .ui-grid-menu-mid.ng-hide-remove {\n  -webkit-transition: all 0.05s linear;\n  -moz-transition: all 0.05s linear;\n  -o-transition: all 0.05s linear;\n  transition: all 0.05s linear;\n  display: block !important;\n}\n.ui-grid-menu-button .ui-grid-menu .ui-grid-menu-mid.ng-hide-add.ng-hide-add-active,\n.ui-grid-menu-button .ui-grid-menu .ui-grid-menu-mid.ng-hide-remove {\n  -webkit-transform: translateY(-100%);\n  -moz-transform: translateY(-100%);\n  -o-transform: translateY(-100%);\n  -ms-transform: translateY(-100%);\n  transform: translateY(-100%);\n}\n.ui-grid-menu-button .ui-grid-menu .ui-grid-menu-mid.ng-hide-add,\n.ui-grid-menu-button .ui-grid-menu .ui-grid-menu-mid.ng-hide-remove.ng-hide-remove-active {\n  -webkit-transform: translateY(0);\n  -moz-transform: translateY(0);\n  -o-transform: translateY(0);\n  -ms-transform: translateY(0);\n  transform: translateY(0);\n}\n.ui-grid-filter-container {\n  padding: 4px 10px;\n  position: relative;\n}\n.ui-grid-filter-container .ui-grid-filter-button {\n  position: absolute;\n  top: 0;\n  bottom: 0;\n  right: 0;\n}\n.ui-grid-filter-container .ui-grid-filter-button [class^=\"ui-grid-icon\"] {\n  position: absolute;\n  top: 50%;\n  line-height: 32px;\n  margin-top: -16px;\n  right: 10px;\n  opacity: 0.66;\n}\n.ui-grid-filter-container .ui-grid-filter-button [class^=\"ui-grid-icon\"]:hover {\n  opacity: 1;\n}\ninput[type=\"text\"].ui-grid-filter-input {\n  padding: 0;\n  margin: 0;\n  border: 0;\n  width: 100%;\n  border: 1px solid #d4d4d4;\n  -webkit-border-top-right-radius: 0px;\n  -webkit-border-bottom-right-radius: 0;\n  -webkit-border-bottom-left-radius: 0;\n  -webkit-border-top-left-radius: 0;\n  -moz-border-radius-topright: 0px;\n  -moz-border-radius-bottomright: 0;\n  -moz-border-radius-bottomleft: 0;\n  -moz-border-radius-topleft: 0;\n  border-top-right-radius: 0px;\n  border-bottom-right-radius: 0;\n  border-bottom-left-radius: 0;\n  border-top-left-radius: 0;\n  -moz-background-clip: padding-box;\n  -webkit-background-clip: padding-box;\n  background-clip: padding-box;\n}\ninput[type=\"text\"].ui-grid-filter-input:hover {\n  border: 1px solid #d4d4d4;\n}\n.ui-grid-render-container {\n  position: inherit;\n  -webkit-border-top-right-radius: 0;\n  -webkit-border-bottom-right-radius: 0px;\n  -webkit-border-bottom-left-radius: 0px;\n  -webkit-border-top-left-radius: 0;\n  -moz-border-radius-topright: 0;\n  -moz-border-radius-bottomright: 0px;\n  -moz-border-radius-bottomleft: 0px;\n  -moz-border-radius-topleft: 0;\n  border-top-right-radius: 0;\n  border-bottom-right-radius: 0px;\n  border-bottom-left-radius: 0px;\n  border-top-left-radius: 0;\n  -moz-background-clip: padding-box;\n  -webkit-background-clip: padding-box;\n  background-clip: padding-box;\n}\n.ui-grid-render-container:focus {\n  outline: none;\n}\n.ui-grid-viewport {\n  min-height: 20px;\n  position: relative;\n  overflow-y: scroll;\n  -webkit-overflow-scrolling: touch;\n}\n.ui-grid-viewport :focus {\n  outline: none;\n}\n.ui-grid-canvas {\n  position: relative;\n  padding-top: 1px;\n}\n.ui-grid-row:nth-child(odd) .ui-grid-cell {\n  background-color: #fdfdfd;\n}\n.ui-grid-row:nth-child(even) .ui-grid-cell {\n  background-color: #f3f3f3;\n}\n.ui-grid-row:last-child .ui-grid-cell {\n  border-bottom-color: #d4d4d4;\n  border-bottom-style: solid;\n}\n.ui-grid-no-row-overlay {\n  position: absolute;\n  top: 0;\n  bottom: 0;\n  left: 0;\n  right: 0;\n  margin: 10%;\n  background: #f3f3f3;\n  background: -webkit-gradient(linear, left bottom, left top, color-stop(0, #eeeeee), color-stop(1, #ffffff));\n  background: -ms-linear-gradient(bottom, #eeeeee, #ffffff);\n  background: -moz-linear-gradient(center bottom, #eeeeee 0%, #ffffff 100%);\n  background: -o-linear-gradient(#ffffff, #eeeeee);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#eeeeee', GradientType=0);\n  -webkit-border-top-right-radius: 0px;\n  -webkit-border-bottom-right-radius: 0;\n  -webkit-border-bottom-left-radius: 0;\n  -webkit-border-top-left-radius: 0;\n  -moz-border-radius-topright: 0px;\n  -moz-border-radius-bottomright: 0;\n  -moz-border-radius-bottomleft: 0;\n  -moz-border-radius-topleft: 0;\n  border-top-right-radius: 0px;\n  border-bottom-right-radius: 0;\n  border-bottom-left-radius: 0;\n  border-top-left-radius: 0;\n  -moz-background-clip: padding-box;\n  -webkit-background-clip: padding-box;\n  background-clip: padding-box;\n  border: 1px solid #d4d4d4;\n  font-size: 2em;\n  text-align: center;\n}\n.ui-grid-no-row-overlay > * {\n  position: absolute;\n  display: table;\n  margin: auto 0;\n  width: 100%;\n  top: 0;\n  bottom: 0;\n  left: 0;\n  right: 0;\n  opacity: 0.66;\n}\n.ui-grid-cell {\n  overflow: hidden;\n  float: left;\n  background-color: inherit;\n  border-right: 1px solid;\n  border-color: #d4d4d4;\n  box-sizing: border-box;\n}\n.ui-grid-cell-contents {\n  padding: 5px;\n  -moz-box-sizing: border-box;\n  -webkit-box-sizing: border-box;\n  box-sizing: border-box;\n  white-space: nowrap;\n  -ms-text-overflow: ellipsis;\n  -o-text-overflow: ellipsis;\n  text-overflow: ellipsis;\n  overflow: hidden;\n  height: 100%;\n}\n.ui-grid-cell-contents-hidden {\n  visibility: hidden;\n  width: 0;\n  height: 0;\n  display: none;\n}\n.ui-grid-row-header-cell {\n  background-color: #F0F0EE !important;\n  border-bottom: solid 1px #d4d4d4;\n}\n.ui-grid-footer-panel-background {\n  background: #f3f3f3;\n  background: -webkit-gradient(linear, left bottom, left top, color-stop(0, #eeeeee), color-stop(1, #ffffff));\n  background: -ms-linear-gradient(bottom, #eeeeee, #ffffff);\n  background: -moz-linear-gradient(center bottom, #eeeeee 0%, #ffffff 100%);\n  background: -o-linear-gradient(#ffffff, #eeeeee);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#eeeeee', GradientType=0);\n}\n.ui-grid-footer-panel {\n  position: relative;\n  border-bottom: 1px solid #d4d4d4;\n  border-top: 1px solid #d4d4d4;\n  overflow: hidden;\n  font-weight: bold;\n  background: #f3f3f3;\n  background: -webkit-gradient(linear, left bottom, left top, color-stop(0, #eeeeee), color-stop(1, #ffffff));\n  background: -ms-linear-gradient(bottom, #eeeeee, #ffffff);\n  background: -moz-linear-gradient(center bottom, #eeeeee 0%, #ffffff 100%);\n  background: -o-linear-gradient(#ffffff, #eeeeee);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#eeeeee', GradientType=0);\n  -webkit-border-top-right-radius: -1px;\n  -webkit-border-bottom-right-radius: 0;\n  -webkit-border-bottom-left-radius: 0;\n  -webkit-border-top-left-radius: -1px;\n  -moz-border-radius-topright: -1px;\n  -moz-border-radius-bottomright: 0;\n  -moz-border-radius-bottomleft: 0;\n  -moz-border-radius-topleft: -1px;\n  border-top-right-radius: -1px;\n  border-bottom-right-radius: 0;\n  border-bottom-left-radius: 0;\n  border-top-left-radius: -1px;\n  -moz-background-clip: padding-box;\n  -webkit-background-clip: padding-box;\n  background-clip: padding-box;\n}\n.ui-grid-grid-footer {\n  float: left;\n  width: 100%;\n}\n.ui-grid-footer-viewport {\n  overflow: hidden;\n}\n.ui-grid-footer-canvas {\n  position: relative;\n}\n.ui-grid-footer-canvas:before,\n.ui-grid-footer-canvas:after {\n  content: \"\";\n  display: table;\n  line-height: 0;\n}\n.ui-grid-footer-canvas:after {\n  clear: both;\n}\n.ui-grid-footer-cell {\n  overflow: hidden;\n  float: left;\n  background-color: inherit;\n  border-right: 1px solid;\n  border-color: #d4d4d4;\n  box-sizing: border-box;\n}\n.ui-grid-footer-cell:last-child {\n  border-right: 0;\n}\ninput[type=\"text\"].ui-grid-filter-input {\n  padding: 0;\n  margin: 0;\n  border: 0;\n  width: 100%;\n  border: 1px solid #d4d4d4;\n  -webkit-border-top-right-radius: 0px;\n  -webkit-border-bottom-right-radius: 0;\n  -webkit-border-bottom-left-radius: 0;\n  -webkit-border-top-left-radius: 0;\n  -moz-border-radius-topright: 0px;\n  -moz-border-radius-bottomright: 0;\n  -moz-border-radius-bottomleft: 0;\n  -moz-border-radius-topleft: 0;\n  border-top-right-radius: 0px;\n  border-bottom-right-radius: 0;\n  border-bottom-left-radius: 0;\n  border-top-left-radius: 0;\n  -moz-background-clip: padding-box;\n  -webkit-background-clip: padding-box;\n  background-clip: padding-box;\n}\ninput[type=\"text\"].ui-grid-filter-input:hover {\n  border: 1px solid #d4d4d4;\n}\n.ui-grid-menu-button {\n  z-index: 2;\n  position: absolute;\n  right: 0;\n  background: #f3f3f3;\n  border: 1px solid #d4d4d4;\n  cursor: pointer;\n  min-height: 27px;\n  font-weight: normal;\n}\n.ui-grid-menu-button .ui-grid-icon-container {\n  margin-top: 3px;\n}\n.ui-grid-menu-button .ui-grid-menu {\n  right: 0;\n}\n.ui-grid-menu-button .ui-grid-menu .ui-grid-menu-mid {\n  overflow-y: scroll;\n  max-height: 300px;\n  border: 1px solid #d4d4d4;\n}\n.ui-grid-menu {\n  z-index: 2;\n  position: absolute;\n  overflow: hidden;\n  padding: 0 10px 20px 10px;\n  cursor: pointer;\n  box-sizing: content-box;\n}\n.ui-grid-menu .ui-grid-menu-inner {\n  background: #f3f3f3;\n  border: 1px solid #d4d4d4;\n  position: relative;\n  white-space: nowrap;\n  -webkit-border-radius: 0px;\n  -moz-border-radius: 0px;\n  border-radius: 0px;\n  -webkit-box-shadow: 0 10px 20px rgba(0, 0, 0, 0.2), inset 0 12px 12px -14px rgba(0, 0, 0, 0.2);\n  -moz-box-shadow: 0 10px 20px rgba(0, 0, 0, 0.2), inset 0 12px 12px -14px rgba(0, 0, 0, 0.2);\n  box-shadow: 0 10px 20px rgba(0, 0, 0, 0.2), inset 0 12px 12px -14px rgba(0, 0, 0, 0.2);\n}\n.ui-grid-menu .ui-grid-menu-inner ul {\n  margin: 0;\n  padding: 0;\n  list-style-type: none;\n}\n.ui-grid-menu .ui-grid-menu-inner ul li {\n  padding: 8px;\n  cursor: pointer;\n}\n.ui-grid-menu .ui-grid-menu-inner ul li:hover {\n  -webkit-box-shadow: inset 0 0 14px rgba(0, 0, 0, 0.2);\n  -moz-box-shadow: inset 0 0 14px rgba(0, 0, 0, 0.2);\n  box-shadow: inset 0 0 14px rgba(0, 0, 0, 0.2);\n}\n.ui-grid-menu .ui-grid-menu-inner ul li.ui-grid-menu-item-active {\n  -webkit-box-shadow: inset 0 0 14px rgba(0, 0, 0, 0.2);\n  -moz-box-shadow: inset 0 0 14px rgba(0, 0, 0, 0.2);\n  box-shadow: inset 0 0 14px rgba(0, 0, 0, 0.2);\n  background-color: #cecece;\n}\n.ui-grid-menu .ui-grid-menu-inner ul li:not(:last-child) {\n  border-bottom: 1px solid #d4d4d4;\n}\n.ui-grid-sortarrow {\n  right: 5px;\n  position: absolute;\n  width: 20px;\n  top: 0;\n  bottom: 0;\n  background-position: center;\n}\n.ui-grid-sortarrow.down {\n  -webkit-transform: rotate(180deg);\n  -moz-transform: rotate(180deg);\n  -o-transform: rotate(180deg);\n  -ms-transform: rotate(180deg);\n  transform: rotate(180deg);\n}\n@font-face {\n  font-family: 'ui-grid';\n  src: url('ui-grid.eot');\n  src: url('ui-grid.eot#iefix') format('embedded-opentype'), url('ui-grid.woff') format('woff'), url('ui-grid.ttf?') format('truetype'), url('ui-grid.svg?#ui-grid') format('svg');\n  font-weight: normal;\n  font-style: normal;\n}\n/* Chrome hack: SVG is rendered more smooth in Windozze. 100% magic, uncomment if you need it. */\n/* Note, that will break hinting! In other OS-es font will be not as sharp as it could be */\n/*\n@media screen and (-webkit-min-device-pixel-ratio:0) {\n  @font-face {\n    font-family: 'ui-grid';\n    src: url('../font/ui-grid.svg?12312827#ui-grid') format('svg');\n  }\n}\n*/\n[class^=\"ui-grid-icon\"]:before,\n[class*=\" ui-grid-icon\"]:before {\n  font-family: \"ui-grid\";\n  font-style: normal;\n  font-weight: normal;\n  speak: none;\n  display: inline-block;\n  text-decoration: inherit;\n  width: 1em;\n  margin-right: .2em;\n  text-align: center;\n  /* opacity: .8; */\n  /* For safety - reset parent styles, that can break glyph codes*/\n  font-variant: normal;\n  text-transform: none;\n  /* fix buttons height, for twitter bootstrap */\n  line-height: 1em;\n  /* Animation center compensation - margins should be symmetric */\n  /* remove if not needed */\n  margin-left: .2em;\n  /* you can be more comfortable with increased icons size */\n  /* font-size: 120%; */\n  /* Uncomment for 3D effect */\n  /* text-shadow: 1px 1px 1px rgba(127, 127, 127, 0.3); */\n}\n.ui-grid-icon-blank::before {\n  width: 1em;\n  content: ' ';\n}\n/*\n* RTL Styles\n*/\n.ui-grid[dir=rtl] .ui-grid-header-cell,\n.ui-grid[dir=rtl] .ui-grid-footer-cell,\n.ui-grid[dir=rtl] .ui-grid-cell {\n  float: right !important;\n}\n.ui-grid[dir=rtl] .ui-grid-column-menu-button {\n  position: absolute;\n  left: 1px;\n  top: 0;\n  right: inherit;\n}\n.ui-grid[dir=rtl] .ui-grid-cell:first-child,\n.ui-grid[dir=rtl] .ui-grid-header-cell:first-child,\n.ui-grid[dir=rtl] .ui-grid-footer-cell:first-child {\n  border-right: 0;\n}\n.ui-grid[dir=rtl] .ui-grid-cell:last-child,\n.ui-grid[dir=rtl] .ui-grid-header-cell:last-child {\n  border-left: 1px solid;\n  border-color: #d4d4d4;\n}\n.ui-grid[dir=rtl] .ui-grid-header-cell:first-child .ui-grid-vertical-bar,\n.ui-grid[dir=rtl] .ui-grid-footer-cell:first-child .ui-grid-vertical-bar,\n.ui-grid[dir=rtl] .ui-grid-cell:first-child .ui-grid-vertical-bar {\n  width: 0;\n}\n.ui-grid[dir=rtl] .ui-grid-menu-button {\n  z-index: 2;\n  position: absolute;\n  left: 0;\n  right: auto;\n  background: #f3f3f3;\n  border: 1px solid #d4d4d4;\n  cursor: pointer;\n  min-height: 27px;\n  font-weight: normal;\n}\n.ui-grid[dir=rtl] .ui-grid-menu-button .ui-grid-menu {\n  left: 0;\n  right: auto;\n}\n.ui-grid[dir=rtl] .ui-grid-filter-container .ui-grid-filter-button {\n  right: initial;\n  left: 0;\n}\n.ui-grid[dir=rtl] .ui-grid-filter-container .ui-grid-filter-button [class^=\"ui-grid-icon\"] {\n  right: initial;\n  left: 10px;\n}\n/*\n   Animation example, for spinners\n*/\n.ui-grid-animate-spin {\n  -moz-animation: ui-grid-spin 2s infinite linear;\n  -o-animation: ui-grid-spin 2s infinite linear;\n  -webkit-animation: ui-grid-spin 2s infinite linear;\n  animation: ui-grid-spin 2s infinite linear;\n  display: inline-block;\n}\n@-moz-keyframes ui-grid-spin {\n  0% {\n    -moz-transform: rotate(0deg);\n    -o-transform: rotate(0deg);\n    -webkit-transform: rotate(0deg);\n    transform: rotate(0deg);\n  }\n  100% {\n    -moz-transform: rotate(359deg);\n    -o-transform: rotate(359deg);\n    -webkit-transform: rotate(359deg);\n    transform: rotate(359deg);\n  }\n}\n@-webkit-keyframes ui-grid-spin {\n  0% {\n    -moz-transform: rotate(0deg);\n    -o-transform: rotate(0deg);\n    -webkit-transform: rotate(0deg);\n    transform: rotate(0deg);\n  }\n  100% {\n    -moz-transform: rotate(359deg);\n    -o-transform: rotate(359deg);\n    -webkit-transform: rotate(359deg);\n    transform: rotate(359deg);\n  }\n}\n@-o-keyframes ui-grid-spin {\n  0% {\n    -moz-transform: rotate(0deg);\n    -o-transform: rotate(0deg);\n    -webkit-transform: rotate(0deg);\n    transform: rotate(0deg);\n  }\n  100% {\n    -moz-transform: rotate(359deg);\n    -o-transform: rotate(359deg);\n    -webkit-transform: rotate(359deg);\n    transform: rotate(359deg);\n  }\n}\n@-ms-keyframes ui-grid-spin {\n  0% {\n    -moz-transform: rotate(0deg);\n    -o-transform: rotate(0deg);\n    -webkit-transform: rotate(0deg);\n    transform: rotate(0deg);\n  }\n  100% {\n    -moz-transform: rotate(359deg);\n    -o-transform: rotate(359deg);\n    -webkit-transform: rotate(359deg);\n    transform: rotate(359deg);\n  }\n}\n@keyframes ui-grid-spin {\n  0% {\n    -moz-transform: rotate(0deg);\n    -o-transform: rotate(0deg);\n    -webkit-transform: rotate(0deg);\n    transform: rotate(0deg);\n  }\n  100% {\n    -moz-transform: rotate(359deg);\n    -o-transform: rotate(359deg);\n    -webkit-transform: rotate(359deg);\n    transform: rotate(359deg);\n  }\n}\n/*---------------------------------------------------\n    LESS Elements 0.9\n  ---------------------------------------------------\n    A set of useful LESS mixins\n    More info at: http://lesselements.com\n  ---------------------------------------------------*/\n/* This file contains variable declarations (do not remove this line) */\n/*-- VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/\n/**\n* @section Grid styles\n*/\n/**\n* @section Header styles\n*/\n/** @description Colors for header gradient */\n/**\n* @section Grid body styles\n*/\n/** @description Colors used for row alternation */\n/**\n* @section Sort arrow colors\n*/\n/**\n* @section Scrollbar styles\n*/\n/**\n* @section font library path\n*/\n/*-- END VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/\n\n/* This file contains variable declarations (do not remove this line) */\n/*-- VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/\n/**\n* @section Grid styles\n*/\n/**\n* @section Header styles\n*/\n/** @description Colors for header gradient */\n/**\n* @section Grid body styles\n*/\n/** @description Colors used for row alternation */\n/**\n* @section Sort arrow colors\n*/\n/**\n* @section Scrollbar styles\n*/\n/**\n* @section font library path\n*/\n/*-- END VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/\n.ui-grid-cell-focus {\n  outline: 0;\n  background-color: #b3c4c7;\n}\n\n/* This file contains variable declarations (do not remove this line) */\n/*-- VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/\n/**\n* @section Grid styles\n*/\n/**\n* @section Header styles\n*/\n/** @description Colors for header gradient */\n/**\n* @section Grid body styles\n*/\n/** @description Colors used for row alternation */\n/**\n* @section Sort arrow colors\n*/\n/**\n* @section Scrollbar styles\n*/\n/**\n* @section font library path\n*/\n/*-- END VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/\ndiv.ui-grid-cell input {\n  border-radius: inherit;\n  padding: 0;\n  width: 100%;\n  color: inherit;\n  height: auto;\n  font: inherit;\n  outline: none;\n}\ndiv.ui-grid-cell input:focus {\n  color: inherit;\n  outline: none;\n}\ndiv.ui-grid-cell input[type=\"checkbox\"] {\n  margin: 9px 0 0 6px;\n  width: auto;\n}\ndiv.ui-grid-cell input.ng-invalid {\n  border: 1px solid #fc8f8f;\n}\ndiv.ui-grid-cell input.ng-valid {\n  border: 1px solid #d4d4d4;\n}\n\n/* This file contains variable declarations (do not remove this line) */\n/*-- VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/\n/**\n* @section Grid styles\n*/\n/**\n* @section Header styles\n*/\n/** @description Colors for header gradient */\n/**\n* @section Grid body styles\n*/\n/** @description Colors used for row alternation */\n/**\n* @section Sort arrow colors\n*/\n/**\n* @section Scrollbar styles\n*/\n/**\n* @section font library path\n*/\n/*-- END VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/\n.expandableRow .ui-grid-row:nth-child(odd) .ui-grid-cell {\n  background-color: #fdfdfd;\n}\n.expandableRow .ui-grid-row:nth-child(even) .ui-grid-cell {\n  background-color: #f3f3f3;\n}\n\n/* This file contains variable declarations (do not remove this line) */\n/*-- VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/\n/**\n* @section Grid styles\n*/\n/**\n* @section Header styles\n*/\n/** @description Colors for header gradient */\n/**\n* @section Grid body styles\n*/\n/** @description Colors used for row alternation */\n/**\n* @section Sort arrow colors\n*/\n/**\n* @section Scrollbar styles\n*/\n/**\n* @section font library path\n*/\n/*-- END VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/\n\n/* This file contains variable declarations (do not remove this line) */\n/*-- VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/\n/**\n* @section Grid styles\n*/\n/**\n* @section Header styles\n*/\n/** @description Colors for header gradient */\n/**\n* @section Grid body styles\n*/\n/** @description Colors used for row alternation */\n/**\n* @section Sort arrow colors\n*/\n/**\n* @section Scrollbar styles\n*/\n/**\n* @section font library path\n*/\n/*-- END VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/\n\n/* This file contains variable declarations (do not remove this line) */\n/*-- VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/\n/**\n* @section Grid styles\n*/\n/**\n* @section Header styles\n*/\n/** @description Colors for header gradient */\n/**\n* @section Grid body styles\n*/\n/** @description Colors used for row alternation */\n/**\n* @section Sort arrow colors\n*/\n/**\n* @section Scrollbar styles\n*/\n/**\n* @section font library path\n*/\n/*-- END VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/\n.movingColumn {\n  position: fixed;\n  border: 1px solid #d4d4d4;\n  box-shadow: inset 0 0 14px rgba(0, 0, 0, 0.2);\n}\n.movingColumn .ui-grid-icon-angle-down {\n  display: none;\n}\n\n.ui-grid-pager-panel {\n  position: absolute;\n  left: 0;\n  bottom: 0;\n  width: 100%;\n  padding-top: 3px;\n  padding-bottom: 3px;\n}\n.ui-grid-pager-container {\n  float: left;\n}\n.ui-grid-pager-control {\n  margin-right: 10px;\n  margin-left: 10px;\n  min-width: 135px;\n  float: left;\n}\n.ui-grid-pager-control button {\n  height: 25px;\n  min-width: 26px;\n}\n.ui-grid-pager-control input {\n  height: 26px;\n  width: 50px;\n  vertical-align: top;\n}\n.ui-grid-pager-control .first-bar {\n  width: 10px;\n  border-left: 2px solid #4d4d4d;\n  margin-top: -6px;\n  height: 12px;\n  margin-left: -3px;\n}\n.ui-grid-pager-control .first-triangle {\n  width: 0;\n  height: 0;\n  border-style: solid;\n  border-width: 5px 8.7px 5px 0;\n  border-color: transparent #4d4d4d transparent transparent;\n  margin-left: 2px;\n}\n.ui-grid-pager-control .next-triangle {\n  margin-left: 1px;\n}\n.ui-grid-pager-control .prev-triangle {\n  margin-left: 0;\n}\n.ui-grid-pager-control .last-triangle {\n  width: 0;\n  height: 0;\n  border-style: solid;\n  border-width: 5px 0 5px 8.7px;\n  border-color: transparent transparent transparent #4d4d4d;\n  margin-left: -1px;\n}\n.ui-grid-pager-control .last-bar {\n  width: 10px;\n  border-left: 2px solid #4d4d4d;\n  margin-top: -6px;\n  height: 12px;\n  margin-left: 1px;\n}\n.ui-grid-pager-row-count-picker {\n  float: left;\n}\n.ui-grid-pager-row-count-picker select {\n  height: 26px;\n  width: 60px;\n}\n.ui-grid-pager-row-count-picker .ui-grid-pager-row-count-label {\n  margin-top: 3px;\n}\n.ui-grid-pager-count-container {\n  float: right;\n  margin-top: 4px;\n  min-width: 50px;\n}\n.ui-grid-pager-count-container .ui-grid-pager-count {\n  margin-right: 10px;\n  margin-left: 10px;\n  float: right;\n}\n\n/* This file contains variable declarations (do not remove this line) */\n/*-- VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/\n/**\n* @section Grid styles\n*/\n/**\n* @section Header styles\n*/\n/** @description Colors for header gradient */\n/**\n* @section Grid body styles\n*/\n/** @description Colors used for row alternation */\n/**\n* @section Sort arrow colors\n*/\n/**\n* @section Scrollbar styles\n*/\n/**\n* @section font library path\n*/\n/*-- END VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/\n.ui-grid-pinned-container {\n  float: left;\n}\n.ui-grid-pinned-container.ui-grid-pinned-container-left .ui-grid-header-cell:last-child {\n  box-sizing: border-box;\n  border-right: 1px solid;\n  border-width: 1px;\n  border-color: #aeaeae;\n}\n.ui-grid-pinned-container.ui-grid-pinned-container-left .ui-grid-cell:last-child {\n  box-sizing: border-box;\n  border-right: 1px solid;\n  border-width: 1px;\n  border-color: #aeaeae;\n}\n.ui-grid-pinned-container.ui-grid-pinned-container-left .ui-grid-header-cell:not(:last-child) .ui-grid-vertical-bar,\n.ui-grid-pinned-container .ui-grid-cell:not(:last-child) .ui-grid-vertical-bar {\n  width: 1px;\n}\n.ui-grid-pinned-container.ui-grid-pinned-container-left .ui-grid-header-cell:not(:last-child) .ui-grid-vertical-bar {\n  background-color: #d4d4d4;\n}\n.ui-grid-pinned-container.ui-grid-pinned-container-left .ui-grid-cell:not(:last-child) .ui-grid-vertical-bar {\n  background-color: #aeaeae;\n}\n.ui-grid-pinned-container.ui-grid-pinned-container-left .ui-grid-header-cell:last-child .ui-grid-vertical-bar {\n  right: -1px;\n  width: 1px;\n  background-color: #aeaeae;\n}\n.ui-grid-pinned-container.ui-grid-pinned-container-right .ui-grid-header-cell:first-child {\n  box-sizing: border-box;\n  border-left: 1px solid;\n  border-width: 1px;\n  border-color: #aeaeae;\n}\n.ui-grid-pinned-container.ui-grid-pinned-container-right .ui-grid-cell:first-child {\n  box-sizing: border-box;\n  border-left: 1px solid;\n  border-width: 1px;\n  border-color: #aeaeae;\n}\n.ui-grid-pinned-container.ui-grid-pinned-container-right .ui-grid-header-cell:not(:first-child) .ui-grid-vertical-bar,\n.ui-grid-pinned-container .ui-grid-cell:not(:first-child) .ui-grid-vertical-bar {\n  width: 1px;\n}\n.ui-grid-pinned-container.ui-grid-pinned-container-right .ui-grid-header-cell:not(:first-child) .ui-grid-vertical-bar {\n  background-color: #d4d4d4;\n}\n.ui-grid-pinned-container.ui-grid-pinned-container-right .ui-grid-cell:not(:last-child) .ui-grid-vertical-bar {\n  background-color: #aeaeae;\n}\n.ui-grid-pinned-container.ui-grid-pinned-container-first .ui-grid-header-cell:first-child .ui-grid-vertical-bar {\n  left: -1px;\n  width: 1px;\n  background-color: #aeaeae;\n}\n.ui-grid-render-container-body {\n  float: left;\n}\n\n/* This file contains variable declarations (do not remove this line) */\n/*-- VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/\n/**\n* @section Grid styles\n*/\n/**\n* @section Header styles\n*/\n/** @description Colors for header gradient */\n/**\n* @section Grid body styles\n*/\n/** @description Colors used for row alternation */\n/**\n* @section Sort arrow colors\n*/\n/**\n* @section Scrollbar styles\n*/\n/**\n* @section font library path\n*/\n/*-- END VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/\n.ui-grid-column-resizer {\n  top: 0;\n  bottom: 0;\n  width: 5px;\n  position: absolute;\n  cursor: col-resize;\n}\n.ui-grid-column-resizer.left {\n  left: 0;\n}\n.ui-grid-column-resizer.right {\n  right: 0;\n}\n.ui-grid.column-resizing {\n  cursor: col-resize;\n}\n.ui-grid.column-resizing .ui-grid-resize-overlay {\n  position: absolute;\n  top: 0;\n  height: 100%;\n  width: 1px;\n  background-color: #aeaeae;\n}\n\n/* This file contains variable declarations (do not remove this line) */\n/*-- VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/\n/**\n* @section Grid styles\n*/\n/**\n* @section Header styles\n*/\n/** @description Colors for header gradient */\n/**\n* @section Grid body styles\n*/\n/** @description Colors used for row alternation */\n/**\n* @section Sort arrow colors\n*/\n/**\n* @section Scrollbar styles\n*/\n/**\n* @section font library path\n*/\n/*-- END VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/\n.ui-grid-row-saving .ui-grid-cell {\n  color: #848484 !important;\n}\n.ui-grid-row-dirty .ui-grid-cell {\n  color: #610b38;\n}\n.ui-grid-row-error .ui-grid-cell {\n  color: #ff0000 !important;\n}\n\n/* This file contains variable declarations (do not remove this line) */\n/*-- VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/\n/**\n* @section Grid styles\n*/\n/**\n* @section Header styles\n*/\n/** @description Colors for header gradient */\n/**\n* @section Grid body styles\n*/\n/** @description Colors used for row alternation */\n/**\n* @section Sort arrow colors\n*/\n/**\n* @section Scrollbar styles\n*/\n/**\n* @section font library path\n*/\n/*-- END VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/\n.ui-grid-row-selected > [ui-grid-row] > .ui-grid-cell {\n  background-color: #c9dde1 !important;\n}\n.ui-grid-disable-selection {\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  cursor: default;\n}\n.ui-grid-selection-row-header-buttons {\n  cursor: pointer;\n  opacity: 0.1;\n}\n.ui-grid-selection-row-header-buttons.ui-grid-row-selected {\n  opacity: 1;\n}\n.ui-grid-selection-row-header-buttons.ui-grid-all-selected {\n  opacity: 1;\n}\n\n.ui-grid-icon-plus-squared:before {\n  content: '\\c350';\n}\n/* '썐' */\n.ui-grid-icon-minus-squared:before {\n  content: '\\c351';\n}\n/* '썑' */\n.ui-grid-icon-search:before {\n  content: '\\c352';\n}\n/* '썒' */\n.ui-grid-icon-cancel:before {\n  content: '\\c353';\n}\n/* '썓' */\n.ui-grid-icon-info-circled:before {\n  content: '\\c354';\n}\n/* '썔' */\n.ui-grid-icon-lock:before {\n  content: '\\c355';\n}\n/* '썕' */\n.ui-grid-icon-lock-open:before {\n  content: '\\c356';\n}\n/* '썖' */\n.ui-grid-icon-pencil:before {\n  content: '\\c357';\n}\n/* '썗' */\n.ui-grid-icon-down-dir:before {\n  content: '\\c358';\n}\n/* '썘' */\n.ui-grid-icon-up-dir:before {\n  content: '\\c359';\n}\n/* '썙' */\n.ui-grid-icon-left-dir:before {\n  content: '\\c35a';\n}\n/* '썚' */\n.ui-grid-icon-right-dir:before {\n  content: '\\c35b';\n}\n/* '썛' */\n.ui-grid-icon-left-open:before {\n  content: '\\c35c';\n}\n/* '썜' */\n.ui-grid-icon-right-open:before {\n  content: '\\c35d';\n}\n/* '썝' */\n.ui-grid-icon-angle-down:before {\n  content: '\\c35e';\n}\n/* '썞' */\n.ui-grid-icon-filter:before {\n  content: '\\c35f';\n}\n/* '썟' */\n.ui-grid-icon-sort-alt-up:before {\n  content: '\\c360';\n}\n/* '썠' */\n.ui-grid-icon-sort-alt-down:before {\n  content: '\\c361';\n}\n/* '썡' */\n.ui-grid-icon-ok:before {\n  content: '\\c362';\n}\n/* '썢' */\n.ui-grid-icon-menu:before {\n  content: '\\c363';\n}\n/* '썣' */\n.ui-grid-icon-spin5:before {\n  content: '\\ea61';\n}\n/* '' */\n"
  },
  {
    "path": "flowable-ui-web/idm/libs/ui-grid_3.0.0/ui-grid.js",
    "content": "/*!\n * ui-grid - v3.0.0-rc.19 - 2015-02-11\n * Copyright (c) 2015 ; License: MIT \n */\n\n(function () {\n  'use strict';\n  angular.module('ui.grid.i18n', []);\n  angular.module('ui.grid', ['ui.grid.i18n']);\n})();\n(function () {\n  'use strict';\n  angular.module('ui.grid').constant('uiGridConstants', {\n    LOG_DEBUG_MESSAGES: true,\n    LOG_WARN_MESSAGES: true,\n    LOG_ERROR_MESSAGES: true,\n    CUSTOM_FILTERS: /CUSTOM_FILTERS/g,\n    COL_FIELD: /COL_FIELD/g,\n    MODEL_COL_FIELD: /MODEL_COL_FIELD/g,\n    DISPLAY_CELL_TEMPLATE: /DISPLAY_CELL_TEMPLATE/g,\n    TEMPLATE_REGEXP: /<.+>/,\n    FUNC_REGEXP: /(\\([^)]*\\))?$/,\n    DOT_REGEXP: /\\./g,\n    APOS_REGEXP: /'/g,\n    BRACKET_REGEXP: /^(.*)((?:\\s*\\[\\s*\\d+\\s*\\]\\s*)|(?:\\s*\\[\\s*\"(?:[^\"\\\\]|\\\\.)*\"\\s*\\]\\s*)|(?:\\s*\\[\\s*'(?:[^'\\\\]|\\\\.)*'\\s*\\]\\s*))(.*)$/,\n    COL_CLASS_PREFIX: 'ui-grid-col',\n    events: {\n      GRID_SCROLL: 'uiGridScroll',\n      COLUMN_MENU_SHOWN: 'uiGridColMenuShown',\n      ITEM_DRAGGING: 'uiGridItemDragStart', // For any item being dragged\n      COLUMN_HEADER_CLICK: 'uiGridColumnHeaderClick'\n    },\n    // copied from http://www.lsauer.com/2011/08/javascript-keymap-keycodes-in-json.html\n    keymap: {\n      TAB: 9,\n      STRG: 17,\n      CTRL: 17,\n      CTRLRIGHT: 18,\n      CTRLR: 18,\n      SHIFT: 16,\n      RETURN: 13,\n      ENTER: 13,\n      BACKSPACE: 8,\n      BCKSP: 8,\n      ALT: 18,\n      ALTR: 17,\n      ALTRIGHT: 17,\n      SPACE: 32,\n      WIN: 91,\n      MAC: 91,\n      FN: null,\n      PG_UP: 33,\n      PG_DOWN: 34,\n      UP: 38,\n      DOWN: 40,\n      LEFT: 37,\n      RIGHT: 39,\n      ESC: 27,\n      DEL: 46,\n      F1: 112,\n      F2: 113,\n      F3: 114,\n      F4: 115,\n      F5: 116,\n      F6: 117,\n      F7: 118,\n      F8: 119,\n      F9: 120,\n      F10: 121,\n      F11: 122,\n      F12: 123\n    },\n    ASC: 'asc',\n    DESC: 'desc',\n    filter: {\n      STARTS_WITH: 2,\n      ENDS_WITH: 4,\n      EXACT: 8,\n      CONTAINS: 16,\n      GREATER_THAN: 32,\n      GREATER_THAN_OR_EQUAL: 64,\n      LESS_THAN: 128,\n      LESS_THAN_OR_EQUAL: 256,\n      NOT_EQUAL: 512\n    },\n\n    aggregationTypes: {\n      sum: 2,\n      count: 4,\n      avg: 8,\n      min: 16,\n      max: 32\n    },\n\n    // TODO(c0bra): Create full list of these somehow. NOTE: do any allow a space before or after them?\n    CURRENCY_SYMBOLS: ['ƒ', '$', '£', '$', '¤', '¥', '៛', '₩', '₱', '฿', '₫'],\n\n    scrollDirection: {\n      UP: 'up',\n      DOWN: 'down',\n      LEFT: 'left',\n      RIGHT: 'right',\n      NONE: 'none'\n\n    },\n\n    dataChange: {\n      ALL: 'all',\n      EDIT: 'edit',\n      ROW: 'row',\n      COLUMN: 'column',\n      OPTIONS: 'options'\n    },\n    scrollbars: {\n      NEVER: 0,\n      ALWAYS: 1\n      //WHEN_NEEDED: 2\n    }\n  });\n\n})();\nangular.module('ui.grid').directive('uiGridCell', ['$compile', '$parse', 'gridUtil', 'uiGridConstants', function ($compile, $parse, gridUtil, uiGridConstants) {\n  var uiGridCell = {\n    priority: 0,\n    scope: false,\n    require: '?^uiGrid',\n    compile: function() {\n      return {\n        pre: function($scope, $elm, $attrs, uiGridCtrl) {\n          function compileTemplate() {\n            var compiledElementFn = $scope.col.compiledElementFn;\n\n            compiledElementFn($scope, function(clonedElement, scope) {\n              $elm.append(clonedElement);\n            });\n          }\n\n          // If the grid controller is present, use it to get the compiled cell template function\n          if (uiGridCtrl && $scope.col.compiledElementFn) {\n             compileTemplate();\n          }\n          // No controller, compile the element manually (for unit tests)\n          else {\n            if ( uiGridCtrl && !$scope.col.compiledElementFn ){\n              // gridUtil.logError('Render has been called before precompile.  Please log a ui-grid issue');  \n\n              $scope.col.getCompiledElementFn()\n                .then(function (compiledElementFn) {\n                  compiledElementFn($scope, function(clonedElement, scope) {\n                    $elm.append(clonedElement);\n                  });\n                });\n            }\n            else {\n              var html = $scope.col.cellTemplate\n                .replace(uiGridConstants.MODEL_COL_FIELD, 'row.entity.' + gridUtil.preEval($scope.col.field))\n                .replace(uiGridConstants.COL_FIELD, 'grid.getCellValue(row, col)');\n\n              var cellElement = $compile(html)($scope);\n              $elm.append(cellElement);\n            }\n          }\n        },\n        post: function($scope, $elm, $attrs, uiGridCtrl) {\n          var initColClass = $scope.col.getColClass(false);\n          $elm.addClass(initColClass);\n\n          var classAdded;\n          var updateClass = function( grid ){\n            var contents = $elm;\n            if ( classAdded ){\n              contents.removeClass( classAdded );\n              classAdded = null;\n            }\n\n            if (angular.isFunction($scope.col.cellClass)) {\n              classAdded = $scope.col.cellClass($scope.grid, $scope.row, $scope.col, $scope.rowRenderIndex, $scope.colRenderIndex);\n            }\n            else {\n              classAdded = $scope.col.cellClass;\n            }\n            contents.addClass(classAdded);\n          };\n\n          if ($scope.col.cellClass) {\n            updateClass();\n          }\n          \n          // Register a data change watch that would get triggered whenever someone edits a cell or modifies column defs\n          var dataChangeDereg = $scope.grid.registerDataChangeCallback( updateClass, [uiGridConstants.dataChange.COLUMN, uiGridConstants.dataChange.EDIT]);\n          \n          // watch the col and row to see if they change - which would indicate that we've scrolled or sorted or otherwise\n          // changed the row/col that this cell relates to, and we need to re-evaluate cell classes and maybe other things\n          var cellChangeFunction = function( n, o ){\n            if ( n !== o ) {\n              if ( classAdded || $scope.col.cellClass ){\n                updateClass();\n              }\n\n              // See if the column's internal class has changed\n              var newColClass = $scope.col.getColClass(false);\n              if (newColClass !== initColClass) {\n                $elm.removeClass(initColClass);\n                $elm.addClass(newColClass);\n                initColClass = newColClass;\n              }\n            }\n          };\n\n          // TODO(c0bra): Turn this into a deep array watch\n          var colWatchDereg = $scope.$watch( 'col', cellChangeFunction );\n          var rowWatchDereg = $scope.$watch( 'row', cellChangeFunction );\n          \n          \n          var deregisterFunction = function() {\n            dataChangeDereg();\n            colWatchDereg();\n            rowWatchDereg(); \n          };\n          \n          $scope.$on( '$destroy', deregisterFunction );\n          $elm.on( '$destroy', deregisterFunction );\n        }\n      };\n    }\n  };\n\n  return uiGridCell;\n}]);\n\n\n(function(){\n\nangular.module('ui.grid')\n.service('uiGridColumnMenuService', [ 'i18nService', 'uiGridConstants', 'gridUtil', \nfunction ( i18nService, uiGridConstants, gridUtil ) {\n/**\n *  @ngdoc service\n *  @name ui.grid.service:uiGridColumnMenuService\n *\n *  @description Services for working with column menus, factored out\n *  to make the code easier to understand\n */\n\n  var service = {\n    /**\n     * @ngdoc method\n     * @methodOf ui.grid.service:uiGridColumnMenuService\n     * @name initialize\n     * @description  Sets defaults, puts a reference to the $scope on \n     * the uiGridController\n     * @param {$scope} $scope the $scope from the uiGridColumnMenu\n     * @param {controller} uiGridCtrl the uiGridController for the grid\n     * we're on\n     * \n     */\n    initialize: function( $scope, uiGridCtrl ){\n      $scope.grid = uiGridCtrl.grid;\n\n      // Store a reference to this link/controller in the main uiGrid controller\n      // to allow showMenu later\n      uiGridCtrl.columnMenuScope = $scope;\n      \n      // Save whether we're shown or not so the columns can check\n      $scope.menuShown = false;\n    },\n    \n    \n    /**\n     * @ngdoc method\n     * @methodOf ui.grid.service:uiGridColumnMenuService\n     * @name setColMenuItemWatch\n     * @description  Setup a watch on $scope.col.menuItems, and update\n     * menuItems based on this.  $scope.col needs to be set by the column\n     * before calling the menu.\n     * @param {$scope} $scope the $scope from the uiGridColumnMenu\n     * @param {controller} uiGridCtrl the uiGridController for the grid\n     * we're on\n     * \n     */    \n    setColMenuItemWatch: function ( $scope ){\n      var deregFunction = $scope.$watch('col.menuItems', function (n, o) {\n        if (typeof(n) !== 'undefined' && n && angular.isArray(n)) {\n          n.forEach(function (item) {\n            if (typeof(item.context) === 'undefined' || !item.context) {\n              item.context = {};\n            }\n            item.context.col = $scope.col;\n          });\n\n          $scope.menuItems = $scope.defaultMenuItems.concat(n);\n        }\n        else {\n          $scope.menuItems = $scope.defaultMenuItems;\n        }\n      }); \n      \n      $scope.$on( '$destroy', deregFunction );     \n    },\n\n\n    /**\n     * @ngdoc boolean\n     * @name enableSorting\n     * @propertyOf ui.grid.class:GridOptions.columnDef\n     * @description (optional) True by default. When enabled, this setting adds sort\n     * widgets to the column header, allowing sorting of the data in the individual column.\n     */\n    /**\n     * @ngdoc method\n     * @methodOf ui.grid.service:uiGridColumnMenuService\n     * @name sortable\n     * @description  determines whether this column is sortable\n     * @param {$scope} $scope the $scope from the uiGridColumnMenu\n     * \n     */    \n    sortable: function( $scope ) {\n      if ( $scope.grid.options.enableSorting && typeof($scope.col) !== 'undefined' && $scope.col && $scope.col.enableSorting) {\n        return true;\n      }\n      else {\n        return false;\n      }\n    },\n    \n    /**\n     * @ngdoc method\n     * @methodOf ui.grid.service:uiGridColumnMenuService\n     * @name isActiveSort\n     * @description  determines whether the requested sort direction is current active, to \n     * allow highlighting in the menu\n     * @param {$scope} $scope the $scope from the uiGridColumnMenu\n     * @param {string} direction the direction that we'd have selected for us to be active\n     * \n     */  \n    isActiveSort: function( $scope, direction ){\n      return (typeof($scope.col) !== 'undefined' && typeof($scope.col.sort) !== 'undefined' && \n              typeof($scope.col.sort.direction) !== 'undefined' && $scope.col.sort.direction === direction);\n      \n    },\n    \n    /**\n     * @ngdoc boolean\n     * @name suppressRemoveSort\n     * @propertyOf ui.grid.class:GridOptions.columnDef\n     * @description (optional) False by default. When enabled, this setting hides the removeSort option\n     * in the menu.\n     */\n    /**\n     * @ngdoc method\n     * @methodOf ui.grid.service:uiGridColumnMenuService\n     * @name suppressRemoveSort\n     * @description  determines whether we should suppress the removeSort option\n     * @param {$scope} $scope the $scope from the uiGridColumnMenu\n     * \n     */  \n    suppressRemoveSort: function( $scope ) {\n      if ($scope.col && $scope.col.colDef && $scope.col.colDef.suppressRemoveSort) {\n        return true;\n      }\n      else {\n        return false;\n      }\n    },       \n\n\n    /**\n     * @ngdoc boolean\n     * @name enableHiding\n     * @propertyOf ui.grid.class:GridOptions.columnDef\n     * @description (optional) True by default. When set to false, this setting prevents a user from hiding the column\n     * using the column menu or the grid menu.\n     */\n    /**\n     * @ngdoc method\n     * @methodOf ui.grid.service:uiGridColumnMenuService\n     * @name hideable\n     * @description  determines whether a column can be hidden, by checking the enableHiding columnDef option\n     * @param {$scope} $scope the $scope from the uiGridColumnMenu\n     * \n     */  \n    hideable: function( $scope ) {\n      if (typeof($scope.col) !== 'undefined' && $scope.col && $scope.col.colDef && $scope.col.colDef.enableHiding === false ) {\n        return false;\n      }\n      else {\n        return true;\n      }\n    },     \n\n\n    /**\n     * @ngdoc method\n     * @methodOf ui.grid.service:uiGridColumnMenuService\n     * @name getDefaultMenuItems\n     * @description  returns the default menu items for a column menu\n     * @param {$scope} $scope the $scope from the uiGridColumnMenu\n     * \n     */     \n    getDefaultMenuItems: function( $scope ){\n      return [\n        {\n          title: i18nService.getSafeText('sort.ascending'),\n          icon: 'ui-grid-icon-sort-alt-up',\n          action: function($event) {\n            $event.stopPropagation();\n            $scope.sortColumn($event, uiGridConstants.ASC);\n          },\n          shown: function () {\n            return service.sortable( $scope );\n          },\n          active: function() {\n            return service.isActiveSort( $scope, uiGridConstants.ASC);\n          }\n        },\n        {\n          title: i18nService.getSafeText('sort.descending'),\n          icon: 'ui-grid-icon-sort-alt-down',\n          action: function($event) {\n            $event.stopPropagation();\n            $scope.sortColumn($event, uiGridConstants.DESC);\n          },\n          shown: function() {\n            return service.sortable( $scope );\n          },\n          active: function() {\n            return service.isActiveSort( $scope, uiGridConstants.DESC);\n          }\n        },\n        {\n          title: i18nService.getSafeText('sort.remove'),\n          icon: 'ui-grid-icon-cancel',\n          action: function ($event) {\n            $event.stopPropagation();\n            $scope.unsortColumn();\n          },\n          shown: function() {\n            return service.sortable( $scope ) && \n                   typeof($scope.col) !== 'undefined' && (typeof($scope.col.sort) !== 'undefined' && \n                   typeof($scope.col.sort.direction) !== 'undefined') && $scope.col.sort.direction !== null &&\n                  !service.suppressRemoveSort( $scope );\n          }\n        },\n        {\n          title: i18nService.getSafeText('column.hide'),\n          icon: 'ui-grid-icon-cancel',\n          shown: function() {\n            return service.hideable( $scope );\n          },\n          action: function ($event) {\n            $event.stopPropagation();\n            $scope.hideColumn();\n          }\n        }\n      ];\n    },\n    \n\n    /**\n     * @ngdoc method\n     * @methodOf ui.grid.service:uiGridColumnMenuService\n     * @name getColumnElementPosition\n     * @description  gets the position information needed to place the column\n     * menu below the column header\n     * @param {$scope} $scope the $scope from the uiGridColumnMenu\n     * @param {GridCol} column the column we want to position below\n     * @param {element} $columnElement the column element we want to position below\n     * @returns {hash} containing left, top, offset, height, width\n     * \n     */  \n    getColumnElementPosition: function( $scope, column, $columnElement ){\n      var positionData = {};\n      positionData.left = $columnElement[0].offsetLeft;\n      positionData.top = $columnElement[0].offsetTop;\n\n      // Get the grid scrollLeft\n      positionData.offset = 0;\n      if (column.grid.options.offsetLeft) {\n        positionData.offset = column.grid.options.offsetLeft;\n      }\n\n      positionData.height = gridUtil.elementHeight($columnElement, true);\n      positionData.width = gridUtil.elementWidth($columnElement, true);\n      \n      return positionData;\n    },\n    \n\n    /**\n     * @ngdoc method\n     * @methodOf ui.grid.service:uiGridColumnMenuService\n     * @name repositionMenu\n     * @description  Reposition the menu below the new column.  If the menu has no child nodes \n     * (i.e. it's not currently visible) then we guess it's width at 100, we'll be called again\n     * later to fix it\n     * @param {$scope} $scope the $scope from the uiGridColumnMenu\n     * @param {GridCol} column the column we want to position below\n     * @param {hash} positionData a hash containing left, top, offset, height, width\n     * @param {element} $elm the column menu element that we want to reposition\n     * @param {element} $columnElement the column element that we want to reposition underneath\n     * \n     */  \n    repositionMenu: function( $scope, column, positionData, $elm, $columnElement ) {\n      var menu = $elm[0].querySelectorAll('.ui-grid-menu');\n      var containerId = column.renderContainer ? column.renderContainer : 'body';\n      var renderContainer = column.grid.renderContainers[containerId];\n\n      // It's possible that the render container of the column we're attaching to is \n      // offset from the grid (i.e. pinned containers), we need to get the difference in the offsetLeft \n      // between the render container and the grid\n      var renderContainerElm = gridUtil.closestElm($columnElement, '.ui-grid-render-container');\n      var renderContainerOffset = renderContainerElm.getBoundingClientRect().left - $scope.grid.element[0].getBoundingClientRect().left;\n\n      var containerScrollLeft = renderContainerElm.querySelectorAll('.ui-grid-viewport')[0].scrollLeft;\n\n      // default value the last width for _this_ column, otherwise last width for _any_ column, otherwise default to 170\n      var myWidth = column.lastMenuWidth ? column.lastMenuWidth : ( $scope.lastMenuWidth ? $scope.lastMenuWidth : 170);\n      var paddingRight = column.lastMenuPaddingRight ? column.lastMenuPaddingRight : ( $scope.lastMenuPaddingRight ? $scope.lastMenuPaddingRight : 10);\n      \n      if ( menu.length !== 0 ){\n        var mid = menu[0].querySelectorAll('.ui-grid-menu-mid'); \n        if ( mid.length !== 0 && !angular.element(mid).hasClass('ng-hide') ) {\n          myWidth = gridUtil.elementWidth(menu, true);\n          $scope.lastMenuWidth = myWidth;\n          column.lastMenuWidth = myWidth;\n  \n          // TODO(c0bra): use padding-left/padding-right based on document direction (ltr/rtl), place menu on proper side\n          // Get the column menu right padding\n          paddingRight = parseInt(gridUtil.getStyles(angular.element(menu)[0])['paddingRight'], 10);\n          $scope.lastMenuPaddingRight = paddingRight;\n          column.lastMenuPaddingRight = paddingRight;\n        }\n      }\n      \n      var left = positionData.left + renderContainerOffset - containerScrollLeft + positionData.width - myWidth + paddingRight;\n      if (left < positionData.offset){\n        left = positionData.offset;\n      }\n\n      $elm.css('left', left + 'px');\n      $elm.css('top', (positionData.top + positionData.height) + 'px');\n    }    \n\n  };\n  \n  return service;\n}])\n\n\n.directive('uiGridColumnMenu', ['$timeout', 'gridUtil', 'uiGridConstants', 'uiGridColumnMenuService', \nfunction ($timeout, gridUtil, uiGridConstants, uiGridColumnMenuService) {\n/**\n * @ngdoc directive\n * @name ui.grid.directive:uiGridColumnMenu\n * @description  Provides the column menu framework, leverages uiGridMenu underneath\n * \n */\n\n  var uiGridColumnMenu = {\n    priority: 0,\n    scope: true,\n    require: '?^uiGrid',\n    templateUrl: 'ui-grid/uiGridColumnMenu',\n    replace: true,\n    link: function ($scope, $elm, $attrs, uiGridCtrl) {\n      var self = this;\n      \n      uiGridColumnMenuService.initialize( $scope, uiGridCtrl );\n\n      $scope.defaultMenuItems = uiGridColumnMenuService.getDefaultMenuItems( $scope );\n\n      // Set the menu items for use with the column menu. The user can later add additional items via the watch\n      $scope.menuItems = $scope.defaultMenuItems;\n      uiGridColumnMenuService.setColMenuItemWatch( $scope );\n\n  \n      /**\n       * @ngdoc method\n       * @methodOf ui.grid.directive:uiGridColumnMenu\n       * @name showMenu\n       * @description Shows the column menu.  If the menu is already displayed it\n       * calls the menu to ask it to hide (it will animate), then it repositions the menu\n       * to the right place whilst hidden (it will make an assumption on menu width), \n       * then it asks the menu to show (it will animate), then it repositions the menu again \n       * once we can calculate it's size.\n       * @param {GridCol} column the column we want to position below\n       * @param {element} $columnElement the column element we want to position below\n       */\n      $scope.showMenu = function(column, $columnElement, event) {\n        // Swap to this column\n        $scope.col = column;\n\n        // Get the position information for the column element\n        var colElementPosition = uiGridColumnMenuService.getColumnElementPosition( $scope, column, $columnElement );\n\n        if ($scope.menuShown) {\n          // we want to hide, then reposition, then show, but we want to wait for animations\n          // we set a variable, and then rely on the menu-hidden event to call the reposition and show\n          $scope.colElement = $columnElement;\n          $scope.colElementPosition = colElementPosition;\n          $scope.hideThenShow = true;\n\n          $scope.$broadcast('hide-menu', { originalEvent: event });\n        } else {\n          self.shown = $scope.menuShown = true;\n          uiGridColumnMenuService.repositionMenu( $scope, column, colElementPosition, $elm, $columnElement );\n\n          $scope.colElement = $columnElement;\n          $scope.colElementPosition = colElementPosition;\n          $scope.$broadcast('show-menu', { originalEvent: event });\n        } \n\n      };\n\n\n      /**\n       * @ngdoc method\n       * @methodOf ui.grid.directive:uiGridColumnMenu\n       * @name hideMenu\n       * @description Hides the column menu.\n       * @param {boolean} broadcastTrigger true if we were triggered by a broadcast\n       * from the menu itself - in which case don't broadcast again as we'll get\n       * an infinite loop\n       */\n      $scope.hideMenu = function( broadcastTrigger ) {\n        // delete $scope.col;\n        $scope.menuShown = false;\n        \n        if ( !broadcastTrigger ){\n          $scope.$broadcast('hide-menu');\n        }\n      };\n\n      \n      $scope.$on('menu-hidden', function() {\n        if ( $scope.hideThenShow ){\n          delete $scope.hideThenShow;\n\n          uiGridColumnMenuService.repositionMenu( $scope, $scope.col, $scope.colElementPosition, $elm, $scope.colElement );\n          $scope.$broadcast('show-menu');\n\n          $scope.menuShown = true;\n        } else {\n          $scope.hideMenu( true );\n        }\n      });\n      \n      $scope.$on('menu-shown', function() {\n        $timeout( function() {\n          uiGridColumnMenuService.repositionMenu( $scope, $scope.col, $scope.colElementPosition, $elm, $scope.colElement );\n          delete $scope.colElementPosition;\n          delete $scope.columnElement;\n        }, 200);\n      });\n\n \n      /* Column methods */\n      $scope.sortColumn = function (event, dir) {\n        event.stopPropagation();\n\n        $scope.grid.sortColumn($scope.col, dir, true)\n          .then(function () {\n            $scope.grid.refresh();\n            $scope.hideMenu();\n          });\n      };\n\n      $scope.unsortColumn = function () {\n        $scope.col.unsort();\n\n        $scope.grid.refresh();\n        $scope.hideMenu();\n      };\n\n      $scope.hideColumn = function () {\n        $scope.col.colDef.visible = false;\n\n        $scope.grid.refresh();\n        $scope.hideMenu();\n        $scope.grid.api.core.notifyDataChange( uiGridConstants.dataChange.COLUMN );\n        $scope.grid.api.core.raise.columnVisibilityChanged( $scope.col );        \n      };\n    },\n    \n    \n    \n    controller: ['$scope', function ($scope) {\n      var self = this;\n      \n      $scope.$watch('menuItems', function (n, o) {\n        self.menuItems = n;\n      });\n    }]\n  };\n\n  return uiGridColumnMenu;\n\n}]);\n\n})();\n(function () {\n  'use strict';\n\n  angular.module('ui.grid').directive('uiGridFooterCell', ['$timeout', 'gridUtil', 'uiGridConstants', '$compile',\n  function ($timeout, gridUtil, uiGridConstants, $compile) {\n    var uiGridFooterCell = {\n      priority: 0,\n      scope: {\n        col: '=',\n        row: '=',\n        renderIndex: '='\n      },\n      replace: true,\n      require: '^uiGrid',\n      compile: function compile(tElement, tAttrs, transclude) {\n        return {\n          pre: function ($scope, $elm, $attrs, uiGridCtrl) {\n            var cellFooter = $compile($scope.col.footerCellTemplate)($scope);\n            $elm.append(cellFooter);\n          },\n          post: function ($scope, $elm, $attrs, uiGridCtrl) {\n            //$elm.addClass($scope.col.getColClass(false));\n            $scope.grid = uiGridCtrl.grid;\n\n            $elm.addClass($scope.col.getColClass(false));\n\n            // apply any footerCellClass\n            var classAdded;\n            var updateClass = function( grid ){\n              var contents = $elm;\n              if ( classAdded ){\n                contents.removeClass( classAdded );\n                classAdded = null;\n              }\n  \n              if (angular.isFunction($scope.col.footerCellClass)) {\n                classAdded = $scope.col.footerCellClass($scope.grid, $scope.row, $scope.col, $scope.rowRenderIndex, $scope.colRenderIndex);\n              }\n              else {\n                classAdded = $scope.col.footerCellClass;\n              }\n              contents.addClass(classAdded);\n            };\n  \n            if ($scope.col.footerCellClass) {\n              updateClass();\n            }\n\n            // Register a data change watch that would get triggered whenever someone edits a cell or modifies column defs\n            var dataChangeDereg = $scope.grid.registerDataChangeCallback( updateClass, [uiGridConstants.dataChange.COLUMN]);\n\n            $scope.$on( '$destroy', dataChangeDereg );\n          }\n        };\n      }\n    };\n\n    return uiGridFooterCell;\n  }]);\n\n})();\n\n(function () {\n  'use strict';\n\n  angular.module('ui.grid').directive('uiGridFooter', ['$templateCache', '$compile', 'uiGridConstants', 'gridUtil', '$timeout', function ($templateCache, $compile, uiGridConstants, gridUtil, $timeout) {\n    var defaultTemplate = 'ui-grid/ui-grid-footer';\n\n    return {\n      restrict: 'EA',\n      replace: true,\n      // priority: 1000,\n      require: ['^uiGrid', '^uiGridRenderContainer'],\n      scope: true,\n      compile: function ($elm, $attrs) {\n        return {\n          pre: function ($scope, $elm, $attrs, controllers) {\n            var uiGridCtrl = controllers[0];\n            var containerCtrl = controllers[1];\n\n            $scope.grid = uiGridCtrl.grid;\n            $scope.colContainer = containerCtrl.colContainer;\n\n            containerCtrl.footer = $elm;\n\n            var footerTemplate = ($scope.grid.options.footerTemplate) ? $scope.grid.options.footerTemplate : defaultTemplate;\n            gridUtil.getTemplate(footerTemplate)\n              .then(function (contents) {\n                var template = angular.element(contents);\n\n                var newElm = $compile(template)($scope);\n                $elm.append(newElm);\n\n                if (containerCtrl) {\n                  // Inject a reference to the footer viewport (if it exists) into the grid controller for use in the horizontal scroll handler below\n                  var footerViewport = $elm[0].getElementsByClassName('ui-grid-footer-viewport')[0];\n\n                  if (footerViewport) {\n                    containerCtrl.footerViewport = footerViewport;\n                  }\n                }\n              });\n          },\n\n          post: function ($scope, $elm, $attrs, controllers) {\n            var uiGridCtrl = controllers[0];\n            var containerCtrl = controllers[1];\n\n            // gridUtil.logDebug('ui-grid-footer link');\n\n            var grid = uiGridCtrl.grid;\n\n            // Don't animate footer cells\n            gridUtil.disableAnimations($elm);\n\n            containerCtrl.footer = $elm;\n\n            var footerViewport = $elm[0].getElementsByClassName('ui-grid-footer-viewport')[0];\n            if (footerViewport) {\n              containerCtrl.footerViewport = footerViewport;\n            }\n          }\n        };\n      }\n    };\n  }]);\n\n})();\n(function () {\n  'use strict';\n\n  angular.module('ui.grid').directive('uiGridGridFooter', ['$templateCache', '$compile', 'uiGridConstants', 'gridUtil', '$timeout', function ($templateCache, $compile, uiGridConstants, gridUtil, $timeout) {\n    var defaultTemplate = 'ui-grid/ui-grid-grid-footer';\n\n    return {\n      restrict: 'EA',\n      replace: true,\n      // priority: 1000,\n      require: '^uiGrid',\n      scope: true,\n      compile: function ($elm, $attrs) {\n        return {\n          pre: function ($scope, $elm, $attrs, uiGridCtrl) {\n\n            $scope.grid = uiGridCtrl.grid;\n\n            var footerTemplate = ($scope.grid.options.gridFooterTemplate) ? $scope.grid.options.gridFooterTemplate : defaultTemplate;\n            gridUtil.getTemplate(footerTemplate)\n              .then(function (contents) {\n                var template = angular.element(contents);\n\n                var newElm = $compile(template)($scope);\n                $elm.append(newElm);\n              });\n          },\n\n          post: function ($scope, $elm, $attrs, controllers) {\n\n          }\n        };\n      }\n    };\n  }]);\n\n})();\n(function(){\n  'use strict';\n\n  angular.module('ui.grid').directive('uiGridGroupPanel', [\"$compile\", \"uiGridConstants\", \"gridUtil\", function($compile, uiGridConstants, gridUtil) {\n    var defaultTemplate = 'ui-grid/ui-grid-group-panel';\n\n    return {\n      restrict: 'EA',\n      replace: true,\n      require: '?^uiGrid',\n      scope: false,\n      compile: function($elm, $attrs) {\n        return {\n          pre: function ($scope, $elm, $attrs, uiGridCtrl) {\n            var groupPanelTemplate = $scope.grid.options.groupPanelTemplate  || defaultTemplate;\n\n             gridUtil.getTemplate(groupPanelTemplate)\n              .then(function (contents) {\n                var template = angular.element(contents);\n                \n                var newElm = $compile(template)($scope);\n                $elm.append(newElm);\n              });\n          },\n\n          post: function ($scope, $elm, $attrs, uiGridCtrl) {\n            $elm.bind('$destroy', function() {\n              // scrollUnbinder();\n            });\n          }\n        };\n      }\n    };\n  }]);\n\n})();\n(function(){\n  'use strict';\n\n  angular.module('ui.grid').directive('uiGridHeaderCell', ['$compile', '$timeout', '$window', '$document', 'gridUtil', 'uiGridConstants', 'ScrollEvent',\n  function ($compile, $timeout, $window, $document, gridUtil, uiGridConstants, ScrollEvent) {\n    // Do stuff after mouse has been down this many ms on the header cell\n    var mousedownTimeout = 500;\n\n    var uiGridHeaderCell = {\n      priority: 0,\n      scope: {\n        col: '=',\n        row: '=',\n        renderIndex: '='\n      },\n      require: ['?^uiGrid', '^uiGridRenderContainer'],\n      replace: true,\n      compile: function() {\n        return {\n          pre: function ($scope, $elm, $attrs) {\n            var cellHeader = $compile($scope.col.headerCellTemplate)($scope);\n            $elm.append(cellHeader);\n          },\n          \n          post: function ($scope, $elm, $attrs, controllers) {\n            var uiGridCtrl = controllers[0];\n            var renderContainerCtrl = controllers[1];\n\n            $scope.grid = uiGridCtrl.grid;\n\n            $scope.renderContainer = uiGridCtrl.grid.renderContainers[renderContainerCtrl.containerId];\n            \n            var initColClass = $scope.col.getColClass(false);\n            $elm.addClass(initColClass);\n    \n            // Hide the menu by default\n            $scope.menuShown = false;\n    \n            // Put asc and desc sort directions in scope\n            $scope.asc = uiGridConstants.ASC;\n            $scope.desc = uiGridConstants.DESC;\n    \n            // Store a reference to menu element\n            var $colMenu = angular.element( $elm[0].querySelectorAll('.ui-grid-header-cell-menu') );\n    \n            var $contentsElm = angular.element( $elm[0].querySelectorAll('.ui-grid-cell-contents') );\n    \n\n            // apply any headerCellClass\n            var classAdded;\n            var updateClass = function( grid ){\n              var contents = $elm;\n              if ( classAdded ){\n                contents.removeClass( classAdded );\n                classAdded = null;\n              }\n  \n              if (angular.isFunction($scope.col.headerCellClass)) {\n                classAdded = $scope.col.headerCellClass($scope.grid, $scope.row, $scope.col, $scope.rowRenderIndex, $scope.colRenderIndex);\n              }\n              else {\n                classAdded = $scope.col.headerCellClass;\n              }\n              contents.addClass(classAdded);\n              \n              var rightMostContainer = $scope.grid.renderContainers['right'] ? $scope.grid.renderContainers['right'] : $scope.grid.renderContainers['body'];\n              $scope.isLastCol = ( $scope.col === rightMostContainer.visibleColumnCache[ rightMostContainer.visibleColumnCache.length - 1 ] );\n            };\n\n            $scope.$watch('col', function (n, o) {\n              if (n !== o) {\n                // See if the column's internal class has changed\n                var newColClass = $scope.col.getColClass(false);\n                if (newColClass !== initColClass) {\n                  $elm.removeClass(initColClass);\n                  $elm.addClass(newColClass);\n                  initColClass = newColClass;\n                }\n              }\n            });\n  \n            updateClass();\n            \n            // Register a data change watch that would get triggered whenever someone edits a cell or modifies column defs\n            var dataChangeDereg = $scope.grid.registerDataChangeCallback( updateClass, [uiGridConstants.dataChange.COLUMN]);\n\n            $scope.$on( '$destroy', dataChangeDereg );            \n\n\n            // Figure out whether this column is sortable or not\n            if (uiGridCtrl.grid.options.enableSorting && $scope.col.enableSorting) {\n              $scope.sortable = true;\n            }\n            else {\n              $scope.sortable = false;\n            }\n    \n            // Figure out whether this column is filterable or not\n            if (uiGridCtrl.grid.options.enableFiltering && $scope.col.enableFiltering) {\n              $scope.filterable = true;\n            }\n            else {\n              $scope.filterable = false;\n            }\n            \n            // figure out whether we support column menus\n            if ($scope.col.grid.options && $scope.col.grid.options.enableColumnMenus !== false && \n                    $scope.col.colDef && $scope.col.colDef.enableColumnMenu !== false){\n              $scope.colMenu = true;\n            } else {\n              $scope.colMenu = false;\n            }\n    \n            function handleClick(event) {\n              // If the shift key is being held down, add this column to the sort\n              var add = false;\n              if (event.shiftKey) {\n                add = true;\n              }\n    \n              // Sort this column then rebuild the grid's rows\n              uiGridCtrl.grid.sortColumn($scope.col, add)\n                .then(function () {\n                  if (uiGridCtrl.columnMenuScope) { uiGridCtrl.columnMenuScope.hideMenu(); }\n                  uiGridCtrl.grid.refresh();\n                });\n            }\n    \n            /**\n            * @ngdoc property\n            * @name enableColumnMenu\n            * @propertyOf ui.grid.class:GridOptions.columnDef\n            * @description if column menus are enabled, controls the column menus for this specific\n            * column (i.e. if gridOptions.enableColumnMenus, then you can control column menus\n            * using this option. If gridOptions.enableColumnMenus === false then you get no column\n            * menus irrespective of the value of this option ).  Defaults to true.\n            *\n            */\n            /**\n            * @ngdoc property\n            * @name enableColumnMenus\n            * @propertyOf ui.grid.class:GridOptions.columnDef\n            * @description Override for column menus everywhere - if set to false then you get no\n            * column menus.  Defaults to true.\n            *\n            */\n\n            if ($scope.sortable || $scope.colMenu) {\n              // Long-click (for mobile)\n              var cancelMousedownTimeout;\n              var mousedownStartTime = 0;\n\n              var downEvent = gridUtil.isTouchEnabled() ? 'touchstart' : 'mousedown';\n              $contentsElm.on(downEvent, function(event) {\n                event.stopPropagation();\n\n                if (typeof(event.originalEvent) !== 'undefined' && event.originalEvent !== undefined) {\n                  event = event.originalEvent;\n                }\n      \n                // Don't show the menu if it's not the left button\n                if (event.button && event.button !== 0) {\n                  return;\n                }\n      \n                mousedownStartTime = (new Date()).getTime();\n      \n                cancelMousedownTimeout = $timeout(function() { }, mousedownTimeout);\n      \n                cancelMousedownTimeout.then(function () {\n                  if ( $scope.colMenu ) {\n                    uiGridCtrl.columnMenuScope.showMenu($scope.col, $elm, event);\n                  }\n                });\n\n                uiGridCtrl.fireEvent(uiGridConstants.events.COLUMN_HEADER_CLICK, {event: event, columnName: $scope.col.colDef.name});\n              });\n        \n              var upEvent = gridUtil.isTouchEnabled() ? 'touchend' : 'mouseup';\n              $contentsElm.on(upEvent, function () {\n                $timeout.cancel(cancelMousedownTimeout);\n              });\n  \n              $scope.$on('$destroy', function () {\n                $contentsElm.off('mousedown touchstart');\n              });\n            }\n\n\n            $scope.toggleMenu = function(event) {\n              event.stopPropagation();\n    \n              // If the menu is already showing...\n              if (uiGridCtrl.columnMenuScope.menuShown) {\n                // ... and we're the column the menu is on...\n                if (uiGridCtrl.columnMenuScope.col === $scope.col) {\n                  // ... hide it\n                  uiGridCtrl.columnMenuScope.hideMenu();\n                }\n                // ... and we're NOT the column the menu is on\n                else {\n                  // ... move the menu to our column\n                  uiGridCtrl.columnMenuScope.showMenu($scope.col, $elm);\n                }\n              }\n              // If the menu is NOT showing\n              else {\n                // ... show it on our column\n                uiGridCtrl.columnMenuScope.showMenu($scope.col, $elm);\n              }\n            };\n    \n            // If this column is sortable, add a click event handler\n            if ($scope.sortable) {\n              var clickEvent = gridUtil.isTouchEnabled() ? 'touchend' : 'click';\n              $contentsElm.on(clickEvent, function(event) {\n                event.stopPropagation();\n    \n                $timeout.cancel(cancelMousedownTimeout);\n    \n                var mousedownEndTime = (new Date()).getTime();\n                var mousedownTime = mousedownEndTime - mousedownStartTime;\n    \n                if (mousedownTime > mousedownTimeout) {\n                  // long click, handled above with mousedown\n                }\n                else {\n                  // short click\n                  handleClick(event);\n                }\n              });\n    \n              $scope.$on('$destroy', function () {\n                // Cancel any pending long-click timeout\n                $timeout.cancel(cancelMousedownTimeout);\n              });\n            }\n    \n            if ($scope.filterable) {\n              var filterDeregisters = [];\n              angular.forEach($scope.col.filters, function(filter, i) {\n                filterDeregisters.push($scope.$watch('col.filters[' + i + '].term', function(n, o) {\n                  if (n !== o) {\n                    uiGridCtrl.grid.api.core.raise.filterChanged();\n                    uiGridCtrl.grid.refresh()\n                      .then(function () {\n                        if (uiGridCtrl.prevScrollArgs && uiGridCtrl.prevScrollArgs.y && uiGridCtrl.prevScrollArgs.y.percentage) {\n                          var scrollEvent = new ScrollEvent(uiGridCtrl.grid,null,null,'uiGridHeaderCell.toggleMenu');\n                          scrollEvent.y.percentage = uiGridCtrl.prevScrollArgs.y.percentage;\n                          scrollEvent.fireScrollingEvent();\n                        }\n                      });\n                  }\n                }));  \n              });\n              $scope.$on('$destroy', function() {\n                angular.forEach(filterDeregisters, function(filterDeregister) {\n                  filterDeregister();\n                });\n              });\n            }\n          }\n        };\n      }\n    };\n\n    return uiGridHeaderCell;\n  }]);\n\n})();\n\n(function(){\n  'use strict';\n\n  angular.module('ui.grid').directive('uiGridHeader', ['$templateCache', '$compile', 'uiGridConstants', 'gridUtil', '$timeout', function($templateCache, $compile, uiGridConstants, gridUtil, $timeout) {\n    var defaultTemplate = 'ui-grid/ui-grid-header';\n    var emptyTemplate = 'ui-grid/ui-grid-no-header';\n\n    return {\n      restrict: 'EA',\n      // templateUrl: 'ui-grid/ui-grid-header',\n      replace: true,\n      // priority: 1000,\n      require: ['^uiGrid', '^uiGridRenderContainer'],\n      scope: true,\n      compile: function($elm, $attrs) {\n        return {\n          pre: function ($scope, $elm, $attrs, controllers) {\n            var uiGridCtrl = controllers[0];\n            var containerCtrl = controllers[1];\n\n            $scope.grid = uiGridCtrl.grid;\n            $scope.colContainer = containerCtrl.colContainer;\n\n\n\n            containerCtrl.header = $elm;\n            containerCtrl.colContainer.header = $elm;\n            \n            var headerTemplate;\n            if (!$scope.grid.options.showHeader) {\n              headerTemplate = emptyTemplate;\n            }\n            else {\n              headerTemplate = ($scope.grid.options.headerTemplate) ? $scope.grid.options.headerTemplate : defaultTemplate;            \n            }\n\n             gridUtil.getTemplate(headerTemplate)\n              .then(function (contents) {\n                var template = angular.element(contents);\n                \n                var newElm = $compile(template)($scope);\n                $elm.replaceWith(newElm);\n\n                // Replace the reference to the container's header element with this new element\n                containerCtrl.header = newElm;\n                containerCtrl.colContainer.header = newElm;\n\n                // And update $elm to be the new element\n                $elm = newElm;\n\n                if (containerCtrl) {\n                  // Inject a reference to the header viewport (if it exists) into the grid controller for use in the horizontal scroll handler below\n                  var headerViewport = $elm[0].getElementsByClassName('ui-grid-header-viewport')[0];\n\n                  if (headerViewport) {\n                    containerCtrl.headerViewport = headerViewport;\n                  }\n                }\n              });\n          },\n\n          post: function ($scope, $elm, $attrs, controllers) {\n            var uiGridCtrl = controllers[0];\n            var containerCtrl = controllers[1];\n\n            // gridUtil.logDebug('ui-grid-header link');\n\n            var grid = uiGridCtrl.grid;\n\n            // Don't animate header cells\n            gridUtil.disableAnimations($elm);\n\n            function updateColumnWidths() {\n              // Get the width of the viewport\n              var availableWidth = containerCtrl.colContainer.getViewportWidth();\n\n              //if (typeof(uiGridCtrl.grid.verticalScrollbarWidth) !== 'undefined' && uiGridCtrl.grid.verticalScrollbarWidth !== undefined && uiGridCtrl.grid.verticalScrollbarWidth > 0) {\n              //  availableWidth = availableWidth + uiGridCtrl.grid.verticalScrollbarWidth;\n              //}\n\n              // The total number of columns\n              // var equalWidthColumnCount = columnCount = uiGridCtrl.grid.options.columnDefs.length;\n              // var equalWidth = availableWidth / equalWidthColumnCount;\n\n              var columnCache = containerCtrl.colContainer.visibleColumnCache,\n                  canvasWidth = 0,\n                  asteriskNum = 0,\n                  oneAsterisk = 0,\n                  leftoverWidth = availableWidth,\n                  hasVariableWidth = false;\n              \n              var getColWidth = function(column){\n                if (column.widthType === \"manual\"){ \n                  return +column.width; \n                }\n                else if (column.widthType === \"percent\"){ \n                  return parseInt(column.width.replace(/%/g, ''), 10) * availableWidth / 100;\n                }\n                else if (column.widthType === \"auto\"){\n                  // leftOverWidth is subtracted from after each call to this\n                  // function so we need to calculate oneAsterisk size only once\n                  if (oneAsterisk === 0) {\n                    oneAsterisk = parseInt(leftoverWidth / asteriskNum, 10);\n                  }\n                  return column.width.length * oneAsterisk; \n                }\n              };\n              \n              // Populate / determine column width types:\n              columnCache.forEach(function(column){\n                column.widthType = null;\n                if (isFinite(+column.width)){\n                  column.widthType = \"manual\";\n                }\n                else if (gridUtil.endsWith(column.width, \"%\")){\n                  column.widthType = \"percent\";\n                  hasVariableWidth = true;\n                }\n                else if (angular.isString(column.width) && column.width.indexOf('*') !== -1){\n                  column.widthType = \"auto\";\n                  asteriskNum += column.width.length;\n                  hasVariableWidth = true;\n                }\n              });\n              \n              // For sorting, calculate width from first to last:\n              var colWidthPriority = [\"manual\", \"percent\", \"auto\"];\n              columnCache.filter(function(column){\n                // Only draw visible items with a widthType\n                return (column.visible && column.widthType); \n              }).sort(function(a,b){\n                // Calculate widths in order, so that manual comes first, etc.\n                return colWidthPriority.indexOf(a.widthType) - colWidthPriority.indexOf(b.widthType);\n              }).forEach(function(column){\n                // Calculate widths:\n                var colWidth = getColWidth(column);\n                if (column.minWidth){\n                  colWidth = Math.max(colWidth, column.minWidth);\n                }\n                if (column.maxWidth){\n                  colWidth = Math.min(colWidth, column.maxWidth);\n                }\n                column.drawnWidth = Math.floor(colWidth);\n                canvasWidth += column.drawnWidth;\n                leftoverWidth -= column.drawnWidth;\n              });\n\n              // If the grid width didn't divide evenly into the column widths and we have pixels left over, dole them out to the columns one by one to make everything fit\n              if (hasVariableWidth && leftoverWidth > 0 && canvasWidth > 0 && canvasWidth < availableWidth) {\n                var remFn = function (column) {\n                  if (leftoverWidth > 0 && (column.widthType === \"auto\" || column.widthType === \"percent\")) {\n                    column.drawnWidth = column.drawnWidth + 1;\n                    canvasWidth = canvasWidth + 1;\n                    leftoverWidth--;\n                  }\n                };\n                var prevLeftover = 0;\n                do {\n                  prevLeftover = leftoverWidth;\n                  columnCache.forEach(remFn);\n                } while (leftoverWidth > 0 && leftoverWidth !== prevLeftover );\n              }\n              canvasWidth = Math.max(canvasWidth, availableWidth);\n\n              // Build the CSS\n              // uiGridCtrl.grid.columns.forEach(function (column) {\n              var ret = '';\n              columnCache.forEach(function (column) {\n                ret = ret + column.getColClassDefinition();\n              });\n\n              // Add the vertical scrollbar width back in to the canvas width, it's taken out in getViewportWidth\n              //if (grid.verticalScrollbarWidth) {\n              //  canvasWidth = canvasWidth + grid.verticalScrollbarWidth;\n              //}\n              // canvasWidth = canvasWidth + 1;\n\n              // if we have a grid menu, then we prune the width of the last column header\n              // to allow room for the button whilst still getting to the column menu\n              if (columnCache.length > 0) { // && grid.options.enableGridMenu) {\n                columnCache[columnCache.length - 1].headerWidth = columnCache[columnCache.length - 1].drawnWidth - 30;\n              }\n\n              containerCtrl.colContainer.canvasWidth = parseInt(canvasWidth, 10);\n\n              // Return the styles back to buildStyles which pops them into the `customStyles` scope variable\n              return ret;\n            }\n            \n            containerCtrl.header = $elm;\n            \n            var headerViewport = $elm[0].getElementsByClassName('ui-grid-header-viewport')[0];\n            if (headerViewport) {\n              containerCtrl.headerViewport = headerViewport;\n            }\n\n            //todo: remove this if by injecting gridCtrl into unit tests\n            if (uiGridCtrl) {\n              uiGridCtrl.grid.registerStyleComputation({\n                priority: 5,\n                func: updateColumnWidths\n              });\n            }\n          }\n        };\n      }\n    };\n  }]);\n\n})();\n\n(function(){\n\nangular.module('ui.grid')\n.service('uiGridGridMenuService', [ 'gridUtil', 'i18nService', 'uiGridConstants', function( gridUtil, i18nService, uiGridConstants ) {\n  /**\n   *  @ngdoc service\n   *  @name ui.grid.gridMenuService\n   *\n   *  @description Methods for working with the grid menu\n   */\n\n  var service = {\n    /**\n     * @ngdoc method\n     * @methodOf ui.grid.gridMenuService\n     * @name initialize\n     * @description Sets up the gridMenu. Most importantly, sets our\n     * scope onto the grid object as grid.gridMenuScope, allowing us\n     * to operate when passed only the grid.  Second most importantly, \n     * we register the 'addToGridMenu' and 'removeFromGridMenu' methods\n     * on the core api.\n     * @param {$scope} $scope the scope of this gridMenu\n     * @param {Grid} grid the grid to which this gridMenu is associated\n     */\n    initialize: function( $scope, grid ){\n      grid.gridMenuScope = $scope;\n      $scope.grid = grid;\n      $scope.registeredMenuItems = [];\n      \n      // not certain this is needed, but would be bad to create a memory leak\n      $scope.$on('$destroy', function() {\n        if ( $scope.grid && $scope.grid.gridMenuScope ){\n          $scope.grid.gridMenuScope = null;\n        }\n        if ( $scope.grid ){\n          $scope.grid = null;\n        }\n        if ( $scope.registeredMenuItems ){\n          $scope.registeredMenuItems = null;\n        }\n      });\n      \n      $scope.registeredMenuItems = [];\n\n      /**\n       * @ngdoc function\n       * @name addToGridMenu\n       * @methodOf ui.grid.core.api:PublicApi\n       * @description add items to the grid menu.  Used by features\n       * to add their menu items if they are enabled, can also be used by\n       * end users to add menu items.  This method has the advantage of allowing\n       * remove again, which can simplify management of which items are included\n       * in the menu when.  (Noting that in most cases the shown and active functions\n       * provide a better way to handle visibility of menu items)\n       * @param {Grid} grid the grid on which we are acting\n       * @param {array} items menu items in the format as described in the tutorial, with \n       * the added note that if you want to use remove you must also specify an `id` field,\n       * which is provided when you want to remove an item.  The id should be unique.\n       * \n       */\n      grid.api.registerMethod( 'core', 'addToGridMenu', service.addToGridMenu );\n  \n      /**\n       * @ngdoc function\n       * @name removeFromGridMenu\n       * @methodOf ui.grid.core.api:PublicApi\n       * @description Remove an item from the grid menu based on a provided id. Assumes\n       * that the id is unique, removes only the last instance of that id. Does nothing if\n       * the specified id is not found\n       * @param {Grid} grid the grid on which we are acting\n       * @param {string} id the id we'd like to remove from the menu\n       * \n       */\n      grid.api.registerMethod( 'core', 'removeFromGridMenu', service.removeFromGridMenu );\n    },\n \n    \n    /**\n     * @ngdoc function\n     * @name addToGridMenu\n     * @propertyOf ui.grid.class:GridOptions\n     * @description add items to the grid menu.  Used by features\n     * to add their menu items if they are enabled, can also be used by\n     * end users to add menu items.  This method has the advantage of allowing\n     * remove again, which can simplify management of which items are included\n     * in the menu when.  (Noting that in most cases the shown and active functions\n     * provide a better way to handle visibility of menu items)\n     * @param {Grid} grid the grid on which we are acting\n     * @param {array} items menu items in the format as described in the tutorial, with \n     * the added note that if you want to use remove you must also specify an `id` field,\n     * which is provided when you want to remove an item.  The id should be unique.\n     * \n     */\n    addToGridMenu: function( grid, menuItems ) {\n      if ( !angular.isArray( menuItems ) ) {\n        gridUtil.logError( 'addToGridMenu: menuItems must be an array, and is not, not adding any items');\n      } else {\n        if ( grid.gridMenuScope ){\n          grid.gridMenuScope.registeredMenuItems = grid.gridMenuScope.registeredMenuItems ? grid.gridMenuScope.registeredMenuItems : [];\n          grid.gridMenuScope.registeredMenuItems = grid.gridMenuScope.registeredMenuItems.concat( menuItems );\n        } else {\n          gridUtil.logError( 'Asked to addToGridMenu, but gridMenuScope not present.  Timing issue?  Please log issue with ui-grid');\n        }\n      }  \n    },\n    \n\n    /**\n     * @ngdoc function\n     * @name removeFromGridMenu\n     * @methodOf ui.grid.core.api:PublicApi\n     * @description Remove an item from the grid menu based on a provided id.  Assumes\n     * that the id is unique, removes only the last instance of that id.  Does nothing if\n     * the specified id is not found.  If there is no gridMenuScope or registeredMenuItems\n     * then do nothing silently - the desired result is those menu items not be present and they\n     * aren't.\n     * @param {Grid} grid the grid on which we are acting\n     * @param {string} id the id we'd like to remove from the menu\n     * \n     */    \n    removeFromGridMenu: function( grid, id ){\n      var foundIndex = -1;\n      \n      if ( grid && grid.gridMenuScope ){\n        grid.gridMenuScope.registeredMenuItems.forEach( function( value, index ) {\n          if ( value.id === id ){\n            if (foundIndex > -1) {\n              gridUtil.logError( 'removeFromGridMenu: found multiple items with the same id, removing only the last' );\n            } else {\n              \n              foundIndex = index;\n            }\n          }\n        });\n      }\n\n      if ( foundIndex > -1 ){\n        grid.gridMenuScope.registeredMenuItems.splice( foundIndex, 1 );\n      }\n    },\n    \n        \n    /**\n     * @ngdoc array\n     * @name gridMenuCustomItems\n     * @propertyOf ui.grid.class:GridOptions\n     * @description (optional) An array of menu items that should be added to\n     * the gridMenu.  Follow the format documented in the tutorial for column\n     * menu customisation.  The context provided to the action function will \n     * include context.grid.  An alternative if working with dynamic menus is to use the \n     * provided api - core.addToGridMenu and core.removeFromGridMenu, which handles\n     * some of the management of items for you.\n     * \n     */\n    /**\n     * @ngdoc boolean\n     * @name gridMenuShowHideColumns\n     * @propertyOf ui.grid.class:GridOptions\n     * @description true by default, whether the grid menu should allow hide/show\n     * of columns\n     * \n     */\n    /**\n     * @ngdoc method\n     * @methodOf ui.grid.gridMenuService\n     * @name getMenuItems\n     * @description Decides the menu items to show in the menu.  This is a\n     * combination of:\n     * \n     * - the default menu items that are always included, \n     * - any menu items that have been provided through the addMenuItem api. These\n     *   are typically added by features within the grid\n     * - any menu items included in grid.options.gridMenuCustomItems.  These can be\n     *   changed dynamically, as they're always recalculated whenever we show the\n     *   menu\n     * @param {$scope} $scope the scope of this gridMenu, from which we can find all \n     * the information that we need\n     * @returns {array} an array of menu items that can be shown \n     */\n    getMenuItems: function( $scope ) {\n      var menuItems = [\n        // this is where we add any menu items we want to always include\n      ];\n      \n      if ( $scope.grid.options.gridMenuCustomItems ){\n        if ( !angular.isArray( $scope.grid.options.gridMenuCustomItems ) ){ \n          gridUtil.logError( 'gridOptions.gridMenuCustomItems must be an array, and is not'); \n        } else {\n          menuItems = menuItems.concat( $scope.grid.options.gridMenuCustomItems );\n        }\n      }\n  \n      menuItems = menuItems.concat( $scope.registeredMenuItems );\n      \n      if ( $scope.grid.options.gridMenuShowHideColumns !== false ){\n        menuItems = menuItems.concat( service.showHideColumns( $scope ) );\n      }\n      \n      return menuItems;\n    },\n    \n    \n    /**\n     * @ngdoc array\n     * @name gridMenuTitleFilter\n     * @propertyOf ui.grid.class:GridOptions\n     * @description (optional) A function that takes a title string \n     * (usually the col.displayName), and converts it into a display value.  The function\n     * must return either a string or a promise.\n     * \n     * Used for internationalization of the grid menu column names - for angular-translate\n     * you can pass $translate as the function, for i18nService you can pass getSafeText as the \n     * function\n     * @example\n     * <pre>\n     *   gridOptions = {\n     *     gridMenuTitleFilter: $translate\n     *   }\n     * </pre>\n     */\n    /**\n     * @ngdoc method\n     * @methodOf ui.grid.gridMenuService\n     * @name showHideColumns\n     * @description Adds two menu items for each of the columns in columnDefs.  One\n     * menu item for hide, one menu item for show.  Each is visible when appropriate\n     * (show when column is not visible, hide when column is visible).  Each toggles\n     * the visible property on the columnDef using toggleColumnVisibility\n     * @param {$scope} $scope of a gridMenu, which contains a reference to the grid\n     */\n    showHideColumns: function( $scope ){\n      var showHideColumns = [];\n      if ( !$scope.grid.options.columnDefs || $scope.grid.options.columnDefs.length === 0 || $scope.grid.columns.length === 0 ) {\n        return showHideColumns;\n      }\n      \n      // add header for columns\n      showHideColumns.push({\n        title: i18nService.getSafeText('gridMenu.columns')\n      });\n      \n      $scope.grid.options.gridMenuTitleFilter = $scope.grid.options.gridMenuTitleFilter ? $scope.grid.options.gridMenuTitleFilter : function( title ) { return title; };  \n      \n      $scope.grid.options.columnDefs.forEach( function( colDef, index ){\n        if ( colDef.enableHiding !== false ){\n          // add hide menu item - shows an OK icon as we only show when column is already visible\n          var menuItem = {\n            icon: 'ui-grid-icon-ok',\n            action: function($event) {\n              $event.stopPropagation();\n              service.toggleColumnVisibility( this.context.gridCol );\n            },\n            shown: function() {\n              return this.context.gridCol.colDef.visible === true || this.context.gridCol.colDef.visible === undefined;\n            },\n            context: { gridCol: $scope.grid.getColumn(colDef.name || colDef.field) }\n          };\n          service.setMenuItemTitle( menuItem, colDef, $scope.grid );\n          showHideColumns.push( menuItem );\n\n          // add show menu item - shows no icon as we only show when column is invisible\n          menuItem = {\n            icon: 'ui-grid-icon-cancel',\n            action: function($event) {\n              $event.stopPropagation();\n              service.toggleColumnVisibility( this.context.gridCol );\n            },\n            shown: function() {\n              return !(this.context.gridCol.colDef.visible === true || this.context.gridCol.colDef.visible === undefined);\n            },\n            context: { gridCol: $scope.grid.getColumn(colDef.name || colDef.field) }\n          };\n          service.setMenuItemTitle( menuItem, colDef, $scope.grid );\n          showHideColumns.push( menuItem );\n        }\n      });\n      return showHideColumns;\n    },\n    \n    \n    /**\n     * @ngdoc method\n     * @methodOf ui.grid.gridMenuService\n     * @name setMenuItemTitle\n     * @description Handles the response from gridMenuTitleFilter, adding it directly to the menu\n     * item if it returns a string, otherwise waiting for the promise to resolve or reject then\n     * putting the result into the title \n     * @param {object} menuItem the menuItem we want to put the title on\n     * @param {object} colDef the colDef from which we can get displayName, name or field\n     * @param {Grid} grid the grid, from which we can get the options.gridMenuTitleFilter\n     * \n     */\n    setMenuItemTitle: function( menuItem, colDef, grid ){\n      var title = grid.options.gridMenuTitleFilter( colDef.displayName || colDef.name || colDef.field );\n      \n      if ( typeof(title) === 'string' ){\n        menuItem.title = title;\n      } else if ( title.then ){\n        // must be a promise\n        menuItem.title = \"\";\n        title.then( function( successValue ) {\n          menuItem.title = successValue;\n        }, function( errorValue ) {\n          menuItem.title = errorValue;\n        });\n      } else {\n        gridUtil.logError('Expected gridMenuTitleFilter to return a string or a promise, it has returned neither, bad config');\n        menuItem.title = 'badconfig';\n      }\n    },\n\n    /**\n     * @ngdoc method\n     * @methodOf ui.grid.gridMenuService\n     * @name toggleColumnVisibility\n     * @description Toggles the visibility of an individual column.  Expects to be\n     * provided a context that has on it a gridColumn, which is the column that\n     * we'll operate upon.  We change the visibility, and refresh the grid as appropriate\n     * @param {GridCol} gridCol the column that we want to toggle\n     * \n     */\n    toggleColumnVisibility: function( gridCol ) {\n      gridCol.colDef.visible = !( gridCol.colDef.visible === true || gridCol.colDef.visible === undefined ); \n      \n      gridCol.grid.refresh();\n      gridCol.grid.api.core.notifyDataChange( uiGridConstants.dataChange.COLUMN );\n      gridCol.grid.api.core.raise.columnVisibilityChanged( gridCol );\n    }\n  };\n  \n  return service;\n}])\n\n\n\n.directive('uiGridMenuButton', ['gridUtil', 'uiGridConstants', 'uiGridGridMenuService', \nfunction (gridUtil, uiGridConstants, uiGridGridMenuService) {\n\n  return {\n    priority: 0,\n    scope: true,\n    require: ['?^uiGrid'],\n    templateUrl: 'ui-grid/ui-grid-menu-button',\n    replace: true,\n\n\n    link: function ($scope, $elm, $attrs, controllers) {\n      var uiGridCtrl = controllers[0];\n\n      uiGridGridMenuService.initialize($scope, uiGridCtrl.grid);\n      \n      $scope.shown = false;\n\n      $scope.toggleMenu = function () {\n        if ( $scope.shown ){\n          $scope.$broadcast('hide-menu');\n          $scope.shown = false;\n        } else {\n          $scope.menuItems = uiGridGridMenuService.getMenuItems( $scope );\n          $scope.$broadcast('show-menu');\n          $scope.shown = true;\n        }\n      };\n      \n      $scope.$on('menu-hidden', function() {\n        $scope.shown = false;\n      });\n    }\n  };\n\n}]);\n\n})();\n(function(){\n\n/**\n * @ngdoc directive\n * @name ui.grid.directive:uiGridColumnMenu\n * @element style\n * @restrict A\n *\n * @description\n * Allows us to interpolate expressions in `<style>` elements. Angular doesn't do this by default as it can/will/might? break in IE8.\n *\n * @example\n <doc:example module=\"app\">\n <doc:source>\n <script>\n var app = angular.module('app', ['ui.grid']);\n\n app.controller('MainCtrl', ['$scope', function ($scope) {\n   \n }]);\n </script>\n\n <div ng-controller=\"MainCtrl\">\n   <div ui-grid-menu shown=\"true\"  ></div>\n </div>\n </doc:source>\n <doc:scenario>\n </doc:scenario>\n </doc:example>\n */\nangular.module('ui.grid')\n\n.directive('uiGridMenu', ['$compile', '$timeout', '$window', '$document', 'gridUtil', 'uiGridConstants', \nfunction ($compile, $timeout, $window, $document, gridUtil, uiGridConstants) {\n  var uiGridMenu = {\n    priority: 0,\n    scope: {\n      // shown: '&',\n      menuItems: '=',\n      autoHide: '=?'\n    },\n    require: '?^uiGrid',\n    templateUrl: 'ui-grid/uiGridMenu',\n    replace: false,\n    link: function ($scope, $elm, $attrs, uiGridCtrl) {\n      var self = this;\n      var menuMid;\n      var $animate;\n     \n    // *** Show/Hide functions ******\n      self.showMenu = $scope.showMenu = function(event, args) {\n        if ( !$scope.shown ){\n\n          /*\n           * In order to animate cleanly we remove the ng-if, wait a digest cycle, then\n           * animate the removal of the ng-hide.  We can't successfully (so far as I can tell)\n           * animate removal of the ng-if, as the menu items aren't there yet.  And we don't want\n           * to rely on ng-show only, as that leaves elements in the DOM that are needlessly evaluated\n           * on scroll events.\n           * \n           * Note when testing animation that animations don't run on the tutorials.  When debugging it looks\n           * like they do, but angular has a default $animate provider that is just a stub, and that's what's\n           * being called.  ALso don't be fooled by the fact that your browser has actually loaded the \n           * angular-translate.js, it's not using it.  You need to test animations in an external application. \n           */\n          $scope.shown = true;\n\n          $timeout( function() {\n            $scope.shownMid = true;\n            $scope.$emit('menu-shown');\n          });\n        } else if ( !$scope.shownMid ) {\n          // we're probably doing a hide then show, so we don't need to wait for ng-if\n          $scope.shownMid = true;\n          $scope.$emit('menu-shown');\n        }\n\n        var docEventType = 'click';\n        if (args && args.originalEvent && args.originalEvent.type && args.originalEvent.type === 'touchstart') {\n          docEventType = args.originalEvent.type;\n        }\n\n        // Turn off an existing document click handler\n        angular.element(document).off('click touchstart', applyHideMenu);\n\n        // Turn on the document click handler, but in a timeout so it doesn't apply to THIS click if there is one\n        $timeout(function() {\n          angular.element(document).on(docEventType, applyHideMenu);\n        });\n      };\n\n\n      self.hideMenu = $scope.hideMenu = function(event, args) {\n        if ( $scope.shown ){\n          /*\n           * In order to animate cleanly we animate the addition of ng-hide, then use a $timeout to\n           * set the ng-if (shown = false) after the animation runs.  In theory we can cascade off the\n           * callback on the addClass method, but it is very unreliable with unit tests for no discernable reason.\n           *   \n           * The user may have clicked on the menu again whilst\n           * we're waiting, so we check that the mid isn't shown before applying the ng-if.\n           */\n          $scope.shownMid = false;\n          $timeout( function() {\n            if ( !$scope.shownMid ){\n              $scope.shown = false;\n              $scope.$emit('menu-hidden');\n            }\n          }, 200);\n        }\n\n        angular.element(document).off('click touchstart', applyHideMenu);\n      };\n\n      $scope.$on('hide-menu', function (event, args) {\n        $scope.hideMenu(event, args);\n      });\n\n      $scope.$on('show-menu', function (event, args) {\n        $scope.showMenu(event, args);\n      });\n\n      \n    // *** Auto hide when click elsewhere ******\n      var applyHideMenu = function(){\n        if ($scope.shown) {\n          $scope.$apply(function () {\n            $scope.hideMenu();\n          });\n        }\n      };\n    \n      if (typeof($scope.autoHide) === 'undefined' || $scope.autoHide === undefined) {\n        $scope.autoHide = true;\n      }\n\n      if ($scope.autoHide) {\n        angular.element($window).on('resize', applyHideMenu);\n      }\n\n      $scope.$on('$destroy', function () {\n        angular.element(document).off('click touchstart', applyHideMenu);\n      });\n      \n\n      $scope.$on('$destroy', function() {\n        angular.element($window).off('resize', applyHideMenu);\n      });\n\n      if (uiGridCtrl) {\n       $scope.$on('$destroy', uiGridCtrl.grid.api.core.on.scrollEvent($scope, applyHideMenu ));\n      }\n\n      $scope.$on('$destroy', $scope.$on(uiGridConstants.events.ITEM_DRAGGING, applyHideMenu ));\n    },\n    \n    \n    controller: ['$scope', '$element', '$attrs', function ($scope, $element, $attrs) {\n      var self = this;\n    }]\n  };\n\n  return uiGridMenu;\n}])\n\n.directive('uiGridMenuItem', ['gridUtil', '$compile', 'i18nService', function (gridUtil, $compile, i18nService) {\n  var uiGridMenuItem = {\n    priority: 0,\n    scope: {\n      name: '=',\n      active: '=',\n      action: '=',\n      icon: '=',\n      shown: '=',\n      context: '=',\n      templateUrl: '='\n    },\n    require: ['?^uiGrid', '^uiGridMenu'],\n    templateUrl: 'ui-grid/uiGridMenuItem',\n    replace: true,\n    compile: function($elm, $attrs) {\n      return {\n        pre: function ($scope, $elm, $attrs, controllers) {\n          var uiGridCtrl = controllers[0],\n              uiGridMenuCtrl = controllers[1];\n          \n          if ($scope.templateUrl) {\n            gridUtil.getTemplate($scope.templateUrl)\n                .then(function (contents) {\n                  var template = angular.element(contents);\n                    \n                  var newElm = $compile(template)($scope);\n                  $elm.replaceWith(newElm);\n                });\n          }\n        },\n        post: function ($scope, $elm, $attrs, controllers) {\n          var uiGridCtrl = controllers[0],\n              uiGridMenuCtrl = controllers[1];\n\n          // TODO(c0bra): validate that shown and active are functions if they're defined. An exception is already thrown above this though\n          // if (typeof($scope.shown) !== 'undefined' && $scope.shown && typeof($scope.shown) !== 'function') {\n          //   throw new TypeError(\"$scope.shown is defined but not a function\");\n          // }\n          if (typeof($scope.shown) === 'undefined' || $scope.shown === null) {\n            $scope.shown = function() { return true; };\n          }\n\n          $scope.itemShown = function () {\n            var context = {};\n            if ($scope.context) {\n              context.context = $scope.context;\n            }\n\n            if (typeof(uiGridCtrl) !== 'undefined' && uiGridCtrl) {\n              context.grid = uiGridCtrl.grid;\n            }\n\n            return $scope.shown.call(context);\n          };\n\n          $scope.itemAction = function($event,title) {\n            // gridUtil.logDebug('itemAction');\n            $event.stopPropagation();\n\n            if (typeof($scope.action) === 'function') {\n              var context = {};\n\n              if ($scope.context) {\n                context.context = $scope.context;\n              }\n\n              // Add the grid to the function call context if the uiGrid controller is present\n              if (typeof(uiGridCtrl) !== 'undefined' && uiGridCtrl) {\n                context.grid = uiGridCtrl.grid;\n              }\n\n              $scope.action.call(context, $event, title);\n\n              $scope.$emit('hide-menu');\n            }\n          };\n\n          $scope.i18n = i18nService.get();\n        }\n      };\n    }\n  };\n\n  return uiGridMenuItem;\n}]);\n\n})();\n(function () {\n  'use strict';\n\n  var module = angular.module('ui.grid');\n  \n  module.directive('uiGridRenderContainer', ['$timeout', '$document', 'uiGridConstants', 'gridUtil', 'ScrollEvent',\n    function($timeout, $document, uiGridConstants, gridUtil, ScrollEvent) {\n    return {\n      replace: true,\n      transclude: true,\n      templateUrl: 'ui-grid/uiGridRenderContainer',\n      require: ['^uiGrid', 'uiGridRenderContainer'],\n      scope: {\n        containerId: '=',\n        rowContainerName: '=',\n        colContainerName: '=',\n        bindScrollHorizontal: '=',\n        bindScrollVertical: '=',\n        enableVerticalScrollbar: '=',\n        enableHorizontalScrollbar: '='\n      },\n      controller: 'uiGridRenderContainer as RenderContainer',\n      compile: function () {\n        return {\n          pre: function prelink($scope, $elm, $attrs, controllers) {\n            // gridUtil.logDebug('render container ' + $scope.containerId + ' pre-link');\n\n            var uiGridCtrl = controllers[0];\n            var containerCtrl = controllers[1];\n\n            var grid = $scope.grid = uiGridCtrl.grid;\n\n            // Verify that the render container for this element exists\n            if (!$scope.rowContainerName) {\n              throw \"No row render container name specified\";\n            }\n            if (!$scope.colContainerName) {\n              throw \"No column render container name specified\";\n            }\n\n            if (!grid.renderContainers[$scope.rowContainerName]) {\n              throw \"Row render container '\" + $scope.rowContainerName + \"' is not registered.\";\n            }\n            if (!grid.renderContainers[$scope.colContainerName]) {\n              throw \"Column render container '\" + $scope.colContainerName + \"' is not registered.\";\n            }\n\n            var rowContainer = $scope.rowContainer = grid.renderContainers[$scope.rowContainerName];\n            var colContainer = $scope.colContainer = grid.renderContainers[$scope.colContainerName];\n            \n            containerCtrl.containerId = $scope.containerId;\n            containerCtrl.rowContainer = rowContainer;\n            containerCtrl.colContainer = colContainer;\n          },\n          post: function postlink($scope, $elm, $attrs, controllers) {\n            // gridUtil.logDebug('render container ' + $scope.containerId + ' post-link');\n\n            var uiGridCtrl = controllers[0];\n            var containerCtrl = controllers[1];\n\n            var grid = uiGridCtrl.grid;\n            var rowContainer = containerCtrl.rowContainer;\n            var colContainer = containerCtrl.colContainer;\n\n            var renderContainer = grid.renderContainers[$scope.containerId];\n\n            // Put the container name on this element as a class\n            $elm.addClass('ui-grid-render-container-' + $scope.containerId);\n\n            // Bind to left/right-scroll events\n            if ($scope.bindScrollHorizontal || $scope.bindScrollVertical) {\n              grid.api.core.on.scrollEvent($scope,scrollHandler);\n            }\n\n            function scrollHandler (args) {\n              // exit if not for this grid\n              if (args.grid && args.grid.id !== grid.id){\n                return;\n              }\n\n              \n              // Vertical scroll\n              if (args.y && $scope.bindScrollVertical) {\n                containerCtrl.prevScrollArgs = args;\n\n                var newScrollTop = args.getNewScrollTop(rowContainer,containerCtrl.viewport);\n\n                //only set scrollTop if we coming from something other than viewPort scrollBar or\n                //another column container\n                if (args.source !== ScrollEvent.Sources.ViewPortScroll ||\n                    args.sourceColContainer !== colContainer) {\n                  containerCtrl.viewport[0].scrollTop = newScrollTop;\n                }\n\n              }\n\n              // Horizontal scroll\n              if (args.x && $scope.bindScrollHorizontal) {\n                containerCtrl.prevScrollArgs = args;\n                var newScrollLeft = args.getNewScrollLeft(colContainer,containerCtrl.viewport);\n\n                // Make the current horizontal scroll position available in the $scope\n                $scope.newScrollLeft = newScrollLeft;                \n\n                if (containerCtrl.headerViewport) {\n                  containerCtrl.headerViewport.scrollLeft = gridUtil.denormalizeScrollLeft(containerCtrl.headerViewport, newScrollLeft);\n                }\n\n                if (containerCtrl.footerViewport) {\n                  containerCtrl.footerViewport.scrollLeft = gridUtil.denormalizeScrollLeft(containerCtrl.footerViewport, newScrollLeft);\n                }\n\n                //scroll came from somewhere else, so the viewport must be positioned\n                if (args.source !== ScrollEvent.Sources.ViewPortScroll) {\n                  containerCtrl.viewport[0].scrollLeft = newScrollLeft;\n                }\n\n                containerCtrl.prevScrollLeft = newScrollLeft;\n              }\n            }\n\n            // Scroll the render container viewport when the mousewheel is used\n            $elm.bind('wheel mousewheel DomMouseScroll MozMousePixelScroll', function(evt) {\n              // use wheelDeltaY\n\n              var newEvent = gridUtil.normalizeWheelEvent(evt);\n\n              var scrollEvent = new ScrollEvent(grid, rowContainer, colContainer, ScrollEvent.Sources.RenderContainerMouseWheel);\n              if (newEvent.deltaY !== 0) {\n                var scrollYAmount = newEvent.deltaY * -120;\n\n                // Get the scroll percentage\n                var scrollYPercentage = (containerCtrl.viewport[0].scrollTop + scrollYAmount) / rowContainer.getVerticalScrollLength();\n\n                // Keep scrollPercentage within the range 0-1.\n                if (scrollYPercentage < 0) { scrollYPercentage = 0; }\n                else if (scrollYPercentage > 1) { scrollYPercentage = 1; }\n\n                scrollEvent.y = { percentage: scrollYPercentage, pixels: scrollYAmount };\n              }\n              if (newEvent.deltaX !== 0) {\n                var scrollXAmount = newEvent.deltaX * -120;\n\n                // Get the scroll percentage\n                var scrollLeft = gridUtil.normalizeScrollLeft(containerCtrl.viewport);\n                var scrollXPercentage = (scrollLeft + scrollXAmount) / (colContainer.getCanvasWidth() - colContainer.getViewportWidth());\n\n                // Keep scrollPercentage within the range 0-1.\n                if (scrollXPercentage < 0) { scrollXPercentage = 0; }\n                else if (scrollXPercentage > 1) { scrollXPercentage = 1; }\n\n                scrollEvent.x = { percentage: scrollXPercentage, pixels: scrollXAmount };\n              }\n\n              // todo: this isn't working when scrolling down.  it works fine for up.  tested on Chrome\n              // Let the parent container scroll if the grid is already at the top/bottom\n                if ((scrollEvent.y && scrollEvent.y.percentage !== 0 && scrollEvent.y.percentage !== 1 && containerCtrl.viewport[0].scrollTop !== 0 ) ||\n                    (scrollEvent.x && scrollEvent.x.percentage !== 0 && scrollEvent.x.percentage !== 1)) {\n                  evt.preventDefault();\n              }\n\n              scrollEvent.fireThrottledScrollingEvent();\n            });\n\n            var startY = 0,\n            startX = 0,\n            scrollTopStart = 0,\n            scrollLeftStart = 0,\n            directionY = 1,\n            directionX = 1,\n            moveStart;\n\n            function touchmove(event) {\n              if (event.originalEvent) {\n                event = event.originalEvent;\n              }\n\n              var deltaX, deltaY, newX, newY;\n              newX = event.targetTouches[0].screenX;\n              newY = event.targetTouches[0].screenY;\n              deltaX = -(newX - startX);\n              deltaY = -(newY - startY);\n\n              directionY = (deltaY < 1) ? -1 : 1;\n              directionX = (deltaX < 1) ? -1 : 1;\n\n              deltaY *= 2;\n              deltaX *= 2;\n\n              var scrollEvent = new ScrollEvent(grid, rowContainer, colContainer, ScrollEvent.Sources.RenderContainerTouchMove);\n\n              if (deltaY !== 0) {\n                var scrollYPercentage = (scrollTopStart + deltaY) / rowContainer.getVerticalScrollLength();\n\n                if (scrollYPercentage > 1) { scrollYPercentage = 1; }\n                else if (scrollYPercentage < 0) { scrollYPercentage = 0; }\n\n                scrollEvent.y = { percentage: scrollYPercentage, pixels: deltaY };\n              }\n              if (deltaX !== 0) {\n                var scrollXPercentage = (scrollLeftStart + deltaX) / (colContainer.getCanvasWidth() - colContainer.getViewportWidth());\n\n                if (scrollXPercentage > 1) { scrollXPercentage = 1; }\n                else if (scrollXPercentage < 0) { scrollXPercentage = 0; }\n\n                scrollEvent.x = { percentage: scrollXPercentage, pixels: deltaX };\n              }\n\n              // Let the parent container scroll if the grid is already at the top/bottom\n              if ((scrollEvent.y && scrollEvent.y.percentage !== 0 && scrollEvent.y.percentage !== 1) ||\n                  (scrollEvent.x && scrollEvent.x.percentage !== 0 && scrollEvent.x.percentage !== 1)) {\n                event.preventDefault();\n              }\n              scrollEvent.fireScrollingEvent();\n            }\n            \n            function touchend(event) {\n              if (event.originalEvent) {\n                event = event.originalEvent;\n              }\n\n              $document.unbind('touchmove', touchmove);\n              $document.unbind('touchend', touchend);\n              $document.unbind('touchcancel', touchend);\n\n              // Get the distance we moved on the Y axis\n              var scrollTopEnd = containerCtrl.viewport[0].scrollTop;\n              var scrollLeftEnd = containerCtrl.viewport[0].scrollTop;\n              var deltaY = Math.abs(scrollTopEnd - scrollTopStart);\n              var deltaX = Math.abs(scrollLeftEnd - scrollLeftStart);\n\n              // Get the duration it took to move this far\n              var moveDuration = (new Date()) - moveStart;\n\n              // Scale the amount moved by the time it took to move it (i.e. quicker, longer moves == more scrolling after the move is over)\n              var moveYScale = deltaY / moveDuration;\n              var moveXScale = deltaX / moveDuration;\n\n              var decelerateInterval = 63; // 1/16th second\n              var decelerateCount = 8; // == 1/2 second\n              var scrollYLength = 120 * directionY * moveYScale;\n              var scrollXLength = 120 * directionX * moveXScale;\n\n              //function decelerate() {\n              //  $timeout(function() {\n              //    var args = new ScrollEvent(grid, rowContainer, colContainer, ScrollEvent.Sources.RenderContainerTouchMove);\n              //\n              //    if (scrollYLength !== 0) {\n              //      var scrollYPercentage = (containerCtrl.viewport[0].scrollTop + scrollYLength) / rowContainer.getVerticalScrollLength();\n              //\n              //      args.y = { percentage: scrollYPercentage, pixels: scrollYLength };\n              //    }\n              //\n              //    if (scrollXLength !== 0) {\n              //      var scrollXPercentage = (containerCtrl.viewport[0].scrollLeft + scrollXLength) / (colContainer.getCanvasWidth() - colContainer.getViewportWidth());\n              //      args.x = { percentage: scrollXPercentage, pixels: scrollXLength };\n              //    }\n              //\n              //    uiGridCtrl.fireScrollingEvent(args);\n              //\n              //    decelerateCount = decelerateCount -1;\n              //    scrollYLength = scrollYLength / 2;\n              //    scrollXLength = scrollXLength / 2;\n              //\n              //    if (decelerateCount > 0) {\n              //      decelerate();\n              //    }\n              //    else {\n              //      uiGridCtrl.scrollbars.forEach(function (sbar) {\n              //        sbar.removeClass('ui-grid-scrollbar-visible');\n              //        sbar.removeClass('ui-grid-scrolling');\n              //      });\n              //    }\n              //  }, decelerateInterval);\n              //}\n\n              // decelerate();\n            }\n\n            if (gridUtil.isTouchEnabled()) {\n              $elm.bind('touchstart', function (event) {\n                if (event.originalEvent) {\n                  event = event.originalEvent;\n                }\n\n                //uiGridCtrl.scrollbars.forEach(function (sbar) {\n                //  sbar.addClass('ui-grid-scrollbar-visible');\n                //  sbar.addClass('ui-grid-scrolling');\n                //});\n\n                moveStart = new Date();\n                startY = event.targetTouches[0].screenY;\n                startX = event.targetTouches[0].screenX;\n                scrollTopStart = containerCtrl.viewport[0].scrollTop;\n                scrollLeftStart = containerCtrl.viewport[0].scrollLeft;\n                \n                $document.on('touchmove', touchmove);\n                $document.on('touchend touchcancel', touchend);\n              });\n            }\n\n            $elm.bind('$destroy', function() {\n              $elm.unbind('keydown');\n\n              ['touchstart', 'touchmove', 'touchend','keydown', 'wheel', 'mousewheel', 'DomMouseScroll', 'MozMousePixelScroll'].forEach(function (eventName) {\n                $elm.unbind(eventName);\n              });\n            });\n            \n            // TODO(c0bra): Handle resizing the inner canvas based on the number of elements\n            function update() {\n              var ret = '';\n\n              var canvasWidth = colContainer.getCanvasWidth();\n              var viewportWidth = colContainer.getViewportWidth();\n\n              var canvasHeight = rowContainer.getCanvasHeight();\n\n              //add additional height for scrollbar on left and right container\n              if ($scope.containerId !== 'body') {\n                canvasHeight += grid.scrollbarHeight;\n              }\n\n              var viewportHeight = rowContainer.getViewportHeight();\n\n              var headerViewportWidth = colContainer.getHeaderViewportWidth();\n              var footerViewportWidth = colContainer.getHeaderViewportWidth();\n              \n              // Set canvas dimensions\n              ret += '\\n .grid' + uiGridCtrl.grid.id + ' .ui-grid-render-container-' + $scope.containerId + ' .ui-grid-canvas { width: ' + canvasWidth + 'px; height: ' + canvasHeight + 'px; }';\n\n              ret += '\\n .grid' + uiGridCtrl.grid.id + ' .ui-grid-render-container-' + $scope.containerId + ' .ui-grid-header-canvas { width: ' + (canvasWidth + grid.scrollbarWidth) + 'px; }';\n              \n              ret += '\\n .grid' + uiGridCtrl.grid.id + ' .ui-grid-render-container-' + $scope.containerId + ' .ui-grid-viewport { width: ' + viewportWidth + 'px; height: ' + viewportHeight + 'px; }';\n              ret += '\\n .grid' + uiGridCtrl.grid.id + ' .ui-grid-render-container-' + $scope.containerId + ' .ui-grid-header-viewport { width: ' + headerViewportWidth + 'px; }';\n\n              ret += '\\n .grid' + uiGridCtrl.grid.id + ' .ui-grid-render-container-' + $scope.containerId + ' .ui-grid-footer-canvas { width: ' + canvasWidth + grid.scrollbarWidth + 'px; }';\n              ret += '\\n .grid' + uiGridCtrl.grid.id + ' .ui-grid-render-container-' + $scope.containerId + ' .ui-grid-footer-viewport { width: ' + footerViewportWidth + 'px; }';\n\n              // If the render container has an \"explicit\" header height (such as in the case that its header is smaller than the other headers and needs to be explicitly set to be the same, ue thae)\n              if (renderContainer.explicitHeaderHeight !== undefined && renderContainer.explicitHeaderHeight !== null && renderContainer.explicitHeaderHeight > 0) {\n                ret += '\\n .grid' + uiGridCtrl.grid.id + ' .ui-grid-render-container-' + $scope.containerId + ' .ui-grid-header-cell { height: ' + renderContainer.explicitHeaderHeight + 'px; }';\n              }\n              // Otherwise if the render container has an INNER header height, use that on the header cells (so that all the header cells are the same height and those that have less elements don't have undersized borders)\n              else if (renderContainer.innerHeaderHeight !== undefined && renderContainer.innerHeaderHeight !== null && renderContainer.innerHeaderHeight > 0) {\n                ret += '\\n .grid' + uiGridCtrl.grid.id + ' .ui-grid-render-container-' + $scope.containerId + ' .ui-grid-header-cell { height: ' + renderContainer.innerHeaderHeight + 'px; }';\n              }\n\n              return ret;\n            }\n            \n            uiGridCtrl.grid.registerStyleComputation({\n              priority: 6,\n              func: update\n            });\n          }\n        };\n      }\n    };\n\n  }]);\n\n  module.controller('uiGridRenderContainer', ['$scope', 'gridUtil', function ($scope, gridUtil) {\n    var self = this;\n\n    self.rowStyle = function (index) {\n      var renderContainer = $scope.grid.renderContainers[$scope.containerId];\n\n      var styles = {};\n      \n      if (!renderContainer.disableRowOffset) {\n        if (index === 0 && self.currentTopRow !== 0) {\n          // The row offset-top is just the height of the rows above the current top-most row, which are no longer rendered\n          var hiddenRowWidth = ($scope.rowContainer.currentTopRow) *\n            $scope.rowContainer.visibleRowCache[$scope.rowContainer.currentTopRow].height;\n\n          // return { 'margin-top': hiddenRowWidth + 'px' };\n          //gridUtil.logDebug('margin-top ' + hiddenRowWidth );\n          styles['margin-top'] = hiddenRowWidth + 'px';\n        }\n      }\n      \n      if (!renderContainer.disableColumnOffset && $scope.colContainer.currentFirstColumn !== 0) {\n        if ($scope.grid.isRTL()) {\n          styles['margin-right'] = $scope.colContainer.columnOffset + 'px';\n        }\n        else {\n          styles['margin-left'] = $scope.colContainer.columnOffset + 'px';\n        }\n      }\n\n      return styles;\n    };\n\n    self.columnStyle = function (index) {\n      var renderContainer = $scope.grid.renderContainers[$scope.containerId];\n\n      var self = this;\n\n      if (!renderContainer.disableColumnOffset) {\n        if (index === 0 && $scope.colContainer.currentFirstColumn !== 0) {\n          var offset = $scope.colContainer.columnOffset;\n\n          if ($scope.grid.isRTL()) {\n            return { 'margin-right': offset + 'px' };\n          }\n          else {\n            return { 'margin-left': offset + 'px' }; \n          }\n        }\n      }\n\n      return null;\n    };\n  }]);\n\n})();\n\n(function(){\n  'use strict';\n\n  angular.module('ui.grid').directive('uiGridRow', ['gridUtil', function(gridUtil) {\n    return {\n      replace: true,\n      // priority: 2001,\n      // templateUrl: 'ui-grid/ui-grid-row',\n      require: ['^uiGrid', '^uiGridRenderContainer'],\n      scope: {\n         row: '=uiGridRow',\n         //rowRenderIndex is added to scope to give the true visual index of the row to any directives that need it\n         rowRenderIndex: '='\n      },\n      compile: function() {\n        return {\n          pre: function($scope, $elm, $attrs, controllers) {\n            var uiGridCtrl = controllers[0];\n            var containerCtrl = controllers[1];\n\n            var grid = uiGridCtrl.grid;\n\n            $scope.grid = uiGridCtrl.grid;\n            $scope.colContainer = containerCtrl.colContainer;\n\n            // Function for attaching the template to this scope\n            var clonedElement, cloneScope;\n            function compileTemplate() {\n              $scope.row.getRowTemplateFn.then(function (compiledElementFn) {\n                // var compiledElementFn = $scope.row.compiledElementFn;\n\n                // Create a new scope for the contents of this row, so we can destroy it later if need be\n                var newScope = $scope.$new();\n\n                compiledElementFn(newScope, function (newElm, scope) {\n                  // If we already have a cloned element, we need to remove it and destroy its scope\n                  if (clonedElement) {\n                    clonedElement.remove();\n                    cloneScope.$destroy();\n                  }\n\n                  // Empty the row and append the new element\n                  $elm.empty().append(newElm);\n\n                  // Save the new cloned element and scope\n                  clonedElement = newElm;\n                  cloneScope = newScope;\n                });\n              });\n            }\n\n            // Initially attach the compiled template to this scope\n            compileTemplate();\n\n            // If the row's compiled element function changes, we need to replace this element's contents with the new compiled template\n            $scope.$watch('row.getRowTemplateFn', function (newFunc, oldFunc) {\n              if (newFunc !== oldFunc) {\n                compileTemplate();\n              }\n            });\n          },\n          post: function($scope, $elm, $attrs, controllers) {\n\n          }\n        };\n      }\n    };\n  }]);\n\n})();\n(function(){\n// 'use strict';\n\n  /**\n   * @ngdoc directive\n   * @name ui.grid.directive:uiGridStyle\n   * @element style\n   * @restrict A\n   *\n   * @description\n   * Allows us to interpolate expressions in `<style>` elements. Angular doesn't do this by default as it can/will/might? break in IE8.\n   *\n   * @example\n   <doc:example module=\"app\">\n   <doc:source>\n   <script>\n   var app = angular.module('app', ['ui.grid']);\n\n   app.controller('MainCtrl', ['$scope', function ($scope) {\n          $scope.myStyle = '.blah { border: 1px solid }';\n        }]);\n   </script>\n\n   <div ng-controller=\"MainCtrl\">\n   <style ui-grid-style>{{ myStyle }}</style>\n   <span class=\"blah\">I am in a box.</span>\n   </div>\n   </doc:source>\n   <doc:scenario>\n   it('should apply the right class to the element', function () {\n        element(by.css('.blah')).getCssValue('border')\n          .then(function(c) {\n            expect(c).toContain('1px solid');\n          });\n      });\n   </doc:scenario>\n   </doc:example>\n   */\n\n\n  angular.module('ui.grid').directive('uiGridStyle', ['gridUtil', '$interpolate', function(gridUtil, $interpolate) {\n    return {\n      // restrict: 'A',\n      // priority: 1000,\n      // require: '?^uiGrid',\n      link: function($scope, $elm, $attrs, uiGridCtrl) {\n        // gridUtil.logDebug('ui-grid-style link');\n        // if (uiGridCtrl === undefined) {\n        //    gridUtil.logWarn('[ui-grid-style link] uiGridCtrl is undefined!');\n        // }\n\n        var interpolateFn = $interpolate($elm.text(), true);\n\n        if (interpolateFn) {\n          $scope.$watch(interpolateFn, function(value) {\n            $elm.text(value);\n          });\n        }\n\n          // uiGridCtrl.recalcRowStyles = function() {\n          //   var offset = (scope.options.offsetTop || 0) - (scope.options.excessRows * scope.options.rowHeight);\n          //   var rowHeight = scope.options.rowHeight;\n\n          //   var ret = '';\n          //   var rowStyleCount = uiGridCtrl.minRowsToRender() + (scope.options.excessRows * 2);\n          //   for (var i = 1; i <= rowStyleCount; i++) {\n          //     ret = ret + ' .grid' + scope.gridId + ' .ui-grid-row:nth-child(' + i + ') { top: ' + offset + 'px; }';\n          //     offset = offset + rowHeight;\n          //   }\n\n          //   scope.rowStyles = ret;\n          // };\n\n          // uiGridCtrl.styleComputions.push(uiGridCtrl.recalcRowStyles);\n\n      }\n    };\n  }]);\n\n})();\n(function(){\n  'use strict';\n\n  angular.module('ui.grid').directive('uiGridViewport', ['gridUtil','ScrollEvent','uiGridConstants',\n    function(gridUtil, ScrollEvent, uiGridConstants) {\n      return {\n        replace: true,\n        scope: {},\n        templateUrl: 'ui-grid/uiGridViewport',\n        require: ['^uiGrid', '^uiGridRenderContainer'],\n        link: function($scope, $elm, $attrs, controllers) {\n          // gridUtil.logDebug('viewport post-link');\n\n          var uiGridCtrl = controllers[0];\n          var containerCtrl = controllers[1];\n\n          $scope.containerCtrl = containerCtrl;\n\n          var rowContainer = containerCtrl.rowContainer;\n          var colContainer = containerCtrl.colContainer;\n\n          var grid = uiGridCtrl.grid;\n\n          $scope.grid = uiGridCtrl.grid;\n\n          // Put the containers in scope so we can get rows and columns from them\n          $scope.rowContainer = containerCtrl.rowContainer;\n          $scope.colContainer = containerCtrl.colContainer;\n\n          // Register this viewport with its container \n          containerCtrl.viewport = $elm;\n\n          $elm.on('scroll', function (evt) {\n            var newScrollTop = $elm[0].scrollTop;\n            // var newScrollLeft = $elm[0].scrollLeft;\n            var newScrollLeft = gridUtil.normalizeScrollLeft($elm);\n            var horizScrollPercentage = -1;\n            var vertScrollPercentage = -1;\n\n            // Handle RTL here\n\n            if (newScrollLeft !== colContainer.prevScrollLeft) {\n              grid.flagScrollingHorizontally();\n              var xDiff = newScrollLeft - colContainer.prevScrollLeft;\n\n              if (xDiff > 0) { grid.scrollDirection = uiGridConstants.scrollDirection.RIGHT; }\n              if (xDiff < 0) { grid.scrollDirection = uiGridConstants.scrollDirection.LEFT; }\n\n              var horizScrollLength = (colContainer.getCanvasWidth() - colContainer.getViewportWidth());\n              if (horizScrollLength !== 0) {\n                horizScrollPercentage = newScrollLeft / horizScrollLength;\n              }\n              else {\n                horizScrollPercentage = 0;\n              }\n\n              colContainer.adjustScrollHorizontal(newScrollLeft, horizScrollPercentage);\n            }\n\n            if (newScrollTop !== rowContainer.prevScrollTop) {\n              grid.flagScrollingVertically();\n              var yDiff = newScrollTop - rowContainer.prevScrollTop;\n\n              if (yDiff > 0 ) { grid.scrollDirection = uiGridConstants.scrollDirection.DOWN; }\n              if (yDiff < 0 ) { grid.scrollDirection = uiGridConstants.scrollDirection.UP; }\n\n              var vertScrollLength = rowContainer.getVerticalScrollLength();\n\n              vertScrollPercentage = newScrollTop / vertScrollLength;\n\n              if (vertScrollPercentage > 1) { vertScrollPercentage = 1; }\n              if (vertScrollPercentage < 0) { vertScrollPercentage = 0; }\n              \n              rowContainer.adjustScrollVertical(newScrollTop, vertScrollPercentage);\n            }\n\n              var scrollEvent = new ScrollEvent(grid, rowContainer, colContainer, ScrollEvent.Sources.ViewPortScroll);\n              scrollEvent.newScrollLeft = newScrollLeft;\n              scrollEvent.newScrollTop = newScrollTop;\n              if ( horizScrollPercentage > -1 ){\n                scrollEvent.x = { percentage: horizScrollPercentage };\n              }\n\n              if ( vertScrollPercentage > -1 ){\n                scrollEvent.y = { percentage: vertScrollPercentage };\n              }\n              scrollEvent.fireScrollingEvent();\n          });\n        }\n      };\n    }\n  ]);\n\n})();\n(function() {\n\nangular.module('ui.grid')\n.directive('uiGridVisible', function uiGridVisibleAction() {\n  return function ($scope, $elm, $attr) {\n    $scope.$watch($attr.uiGridVisible, function (visible) {\n        // $elm.css('visibility', visible ? 'visible' : 'hidden');\n        $elm[visible ? 'removeClass' : 'addClass']('ui-grid-invisible');\n    });\n  };\n});\n\n})();\n(function () {\n  'use strict';\n\n  angular.module('ui.grid').controller('uiGridController', ['$scope', '$element', '$attrs', 'gridUtil', '$q', 'uiGridConstants',\n                    '$templateCache', 'gridClassFactory', '$timeout', '$parse', '$compile', 'ScrollEvent',\n    function ($scope, $elm, $attrs, gridUtil, $q, uiGridConstants,\n              $templateCache, gridClassFactory, $timeout, $parse, $compile, ScrollEvent) {\n      // gridUtil.logDebug('ui-grid controller');\n\n      var self = this;\n\n      self.grid = gridClassFactory.createGrid($scope.uiGrid);\n\n      //assign $scope.$parent if appScope not already assigned\n      self.grid.appScope = self.grid.appScope || $scope.$parent;\n\n      $elm.addClass('grid' + self.grid.id);\n      self.grid.rtl = gridUtil.getStyles($elm[0])['direction'] === 'rtl';\n\n\n      // angular.extend(self.grid.options, );\n\n      //all properties of grid are available on scope\n      $scope.grid = self.grid;\n\n      if ($attrs.uiGridColumns) {\n        $attrs.$observe('uiGridColumns', function(value) {\n          self.grid.options.columnDefs = value;\n          self.grid.buildColumns()\n            .then(function(){\n              self.grid.preCompileCellTemplates();\n\n              self.grid.refreshCanvas(true);\n            });\n        });\n      }\n\n\n      var dataWatchCollectionDereg;\n      if (angular.isString($scope.uiGrid.data)) {\n        dataWatchCollectionDereg = $scope.$parent.$watchCollection($scope.uiGrid.data, dataWatchFunction);\n      }\n      else {\n        dataWatchCollectionDereg = $scope.$parent.$watchCollection(function() { return $scope.uiGrid.data; }, dataWatchFunction);\n      }\n\n      var columnDefWatchCollectionDereg = $scope.$parent.$watchCollection(function() { return $scope.uiGrid.columnDefs; }, columnDefsWatchFunction);\n\n      function columnDefsWatchFunction(n, o) {\n        if (n && n !== o) {\n          self.grid.options.columnDefs = n;\n          self.grid.buildColumns({ orderByColumnDefs: true })\n            .then(function(){\n\n              self.grid.preCompileCellTemplates();\n\n              self.grid.callDataChangeCallbacks(uiGridConstants.dataChange.COLUMN);\n            });\n        }\n      }\n\n      function adjustInfiniteScrollPosition (scrollToRow) {\n\n        var scrollEvent = new ScrollEvent(self.grid, null, null, 'ui.grid.adjustInfiniteScrollPosition');\n        var totalRows = self.grid.renderContainers.body.visibleRowCache.length;\n        var percentage = ( scrollToRow + ( scrollToRow / ( totalRows - 1 ) ) ) / totalRows;\n\n        //for infinite scroll, never allow it to be at the zero position so the up button can be active\n        if ( percentage === 0 ) {\n          scrollEvent.y = {pixels: 1};\n        }\n        else {\n          scrollEvent.y = {percentage: percentage};\n        }\n        scrollEvent.fireScrollingEvent();\n\n      }\n\n      function dataWatchFunction(newData) {\n        // gridUtil.logDebug('dataWatch fired');\n        var promises = [];\n        \n        if (newData) {\n          if (\n            // If we have no columns (i.e. columns length is either 0 or equal to the number of row header columns, which don't count because they're created automatically)\n            self.grid.columns.length === (self.grid.rowHeaderColumns ? self.grid.rowHeaderColumns.length : 0) &&\n            // ... and we don't have a ui-grid-columns attribute, which would define columns for us\n            !$attrs.uiGridColumns &&\n            // ... and we have no pre-defined columns\n            self.grid.options.columnDefs.length === 0 &&\n            // ... but we DO have data\n            newData.length > 0\n          ) {\n            // ... then build the column definitions from the data that we have\n            self.grid.buildColumnDefsFromData(newData);\n          }\n\n          // If we either have some columns defined, or some data defined\n          if (self.grid.options.columnDefs.length > 0 || newData.length > 0) {\n            // Build the column set, then pre-compile the column cell templates\n            promises.push(self.grid.buildColumns()\n              .then(function() {\n                self.grid.preCompileCellTemplates();\n              }));\n          }\n\n          $q.all(promises).then(function() {\n            self.grid.modifyRows(newData)\n              .then(function () {\n                // if (self.viewport) {\n                  self.grid.redrawInPlace();\n                // }\n\n                $scope.$evalAsync(function() {\n                  self.grid.refreshCanvas(true);\n                  self.grid.callDataChangeCallbacks(uiGridConstants.dataChange.ROW);\n\n                  $timeout(function () {\n                    //Process post load scroll events if using infinite scroll\n                    if ( self.grid.options.enableInfiniteScroll ) {\n                      //If first load, seed the scrollbar down a little to activate the button\n                      if ( self.grid.renderContainers.body.prevRowScrollIndex === 0 ) {\n                        adjustInfiniteScrollPosition(0);\n                      }\n                      //If we are scrolling up, we need to reseed the grid.\n                      if (self.grid.scrollDirection === uiGridConstants.scrollDirection.UP) {\n                        adjustInfiniteScrollPosition(self.grid.renderContainers.body.prevRowScrollIndex + 1 + self.grid.options.excessRows);\n                      }\n                    }\n                    }, 0);\n                });\n              });\n          });\n        }\n      }\n\n      $scope.$on('$destroy', function() {\n        dataWatchCollectionDereg();\n        columnDefWatchCollectionDereg();\n      });\n\n      $scope.$watch(function () { return self.grid.styleComputations; }, function() {\n        self.grid.refreshCanvas(true);\n      });\n\n\n      self.fireEvent = function(eventName, args) {\n        // Add the grid to the event arguments if it's not there\n        if (typeof(args) === 'undefined' || args === undefined) {\n          args = {};\n        }\n\n        if (typeof(args.grid) === 'undefined' || args.grid === undefined) {\n          args.grid = self.grid;\n        }\n\n        $scope.$broadcast(eventName, args);\n      };\n\n      self.innerCompile = function innerCompile(elm) {\n        $compile(elm)($scope);\n      };\n\n    }]);\n\n/**\n *  @ngdoc directive\n *  @name ui.grid.directive:uiGrid\n *  @element div\n *  @restrict EA\n *  @param {Object} uiGrid Options for the grid to use\n *\n *  @description Create a very basic grid.\n *\n *  @example\n    <example module=\"app\">\n      <file name=\"app.js\">\n        var app = angular.module('app', ['ui.grid']);\n\n        app.controller('MainCtrl', ['$scope', function ($scope) {\n          $scope.data = [\n            { name: 'Bob', title: 'CEO' },\n            { name: 'Frank', title: 'Lowly Developer' }\n          ];\n        }]);\n      </file>\n      <file name=\"index.html\">\n        <div ng-controller=\"MainCtrl\">\n          <div ui-grid=\"{ data: data }\"></div>\n        </div>\n      </file>\n    </example>\n */\nangular.module('ui.grid').directive('uiGrid',\n  [\n    '$compile',\n    '$templateCache',\n    'gridUtil',\n    '$window',\n    'uiGridConstants',\n    function(\n      $compile,\n      $templateCache,\n      gridUtil,\n      $window,\n      uiGridConstants\n      ) {\n      return {\n        templateUrl: 'ui-grid/ui-grid',\n        scope: {\n          uiGrid: '='\n        },\n        replace: true,\n        transclude: true,\n        controller: 'uiGridController',\n        compile: function () {\n          return {\n            post: function ($scope, $elm, $attrs, uiGridCtrl) {\n              // gridUtil.logDebug('ui-grid postlink');\n\n              var grid = uiGridCtrl.grid;\n\n              // Initialize scrollbars (TODO: move to controller??)\n              uiGridCtrl.scrollbars = [];\n\n              //todo: assume it is ok to communicate that rendering is complete??\n              grid.renderingComplete();\n\n              grid.element = $elm;\n\n              grid.gridWidth = $scope.gridWidth = gridUtil.elementWidth($elm);\n\n              // Default canvasWidth to the grid width, in case we don't get any column definitions to calculate it from\n              grid.canvasWidth = uiGridCtrl.grid.gridWidth;\n\n              grid.gridHeight = $scope.gridHeight = gridUtil.elementHeight($elm);\n\n              // If the grid isn't tall enough to fit a single row, it's kind of useless. Resize it to fit a minimum number of rows\n              if (grid.gridHeight < grid.options.rowHeight) {\n                // Figure out the new height\n                var contentHeight = grid.options.minRowsToShow * grid.options.rowHeight;\n                var headerHeight = grid.options.showHeader ? grid.options.headerRowHeight : 0;\n                var footerHeight = grid.calcFooterHeight();\n                \n                var scrollbarHeight = 0;\n                if (grid.options.enableHorizontalScrollbar === uiGridConstants.scrollbars.ALWAYS) {\n                  scrollbarHeight = gridUtil.getScrollbarWidth();\n                }\n\n                var maxNumberOfFilters = 0;\n                // Calculates the maximum number of filters in the columns\n                angular.forEach(grid.options.columnDefs, function(col) {\n                  if (col.hasOwnProperty('filter')) {\n                    if (maxNumberOfFilters < 1) {\n                        maxNumberOfFilters = 1;\n                    }\n                  }\n                  else if (col.hasOwnProperty('filters')) {\n                    if (maxNumberOfFilters < col.filters.length) {\n                        maxNumberOfFilters = col.filters.length;\n                    }\n                  }\n                });\n                var filterHeight = maxNumberOfFilters * headerHeight;\n\n                var newHeight = headerHeight + contentHeight + footerHeight + scrollbarHeight + filterHeight;\n\n                $elm.css('height', newHeight + 'px');\n\n                grid.gridHeight = $scope.gridHeight = gridUtil.elementHeight($elm);\n              }\n\n              // Run initial canvas refresh\n              grid.refreshCanvas();\n\n              //if we add a left container after render, we need to watch and react\n              $scope.$watch(function () { return grid.hasLeftContainer();}, function (newValue, oldValue) {\n                if (newValue === oldValue) {\n                  return;\n                }\n                grid.refreshCanvas(true);\n              });\n\n              //if we add a right container after render, we need to watch and react\n              $scope.$watch(function () { return grid.hasRightContainer();}, function (newValue, oldValue) {\n                if (newValue === oldValue) {\n                  return;\n                }\n                grid.refreshCanvas(true);\n              });\n\n\n              // Resize the grid on window resize events\n              function gridResize($event) {\n                grid.gridWidth = $scope.gridWidth = gridUtil.elementWidth($elm);\n                grid.gridHeight = $scope.gridHeight = gridUtil.elementHeight($elm);\n\n                grid.refreshCanvas(true);\n              }\n\n              angular.element($window).on('resize', gridResize);\n\n              // Unbind from window resize events when the grid is destroyed\n              $elm.on('$destroy', function () {\n                angular.element($window).off('resize', gridResize);\n              });\n            }\n          };\n        }\n      };\n    }\n  ]);\n\n})();\n\n(function(){\n  'use strict';\n\n  angular.module('ui.grid').directive('uiGridPinnedContainer', ['gridUtil', function (gridUtil) {\n    return {\n      restrict: 'EA',\n      replace: true,\n      template: '<div class=\"ui-grid-pinned-container\"><div ui-grid-render-container container-id=\"side\" row-container-name=\"\\'body\\'\" col-container-name=\"side\" bind-scroll-vertical=\"true\" class=\"{{ side }} ui-grid-render-container-{{ side }}\"></div></div>',\n      scope: {\n        side: '=uiGridPinnedContainer'\n      },\n      require: '^uiGrid',\n      compile: function compile() {\n        return {\n          post: function ($scope, $elm, $attrs, uiGridCtrl) {\n            // gridUtil.logDebug('ui-grid-pinned-container ' + $scope.side + ' link');\n\n            var grid = uiGridCtrl.grid;\n\n            var myWidth = 0;\n\n            $elm.addClass('ui-grid-pinned-container-' + $scope.side);\n\n            function updateContainerWidth() {\n              if ($scope.side === 'left' || $scope.side === 'right') {\n                var cols = grid.renderContainers[$scope.side].visibleColumnCache;\n                var width = 0;\n                for (var i = 0; i < cols.length; i++) {\n                  var col = cols[i];\n                  width += col.drawnWidth || col.width || 0;\n                }\n\n                myWidth = width;\n              }              \n            }\n            \n            function updateContainerDimensions() {\n              // gridUtil.logDebug('update ' + $scope.side + ' dimensions');\n\n              var ret = '';\n              \n              // Column containers\n              if ($scope.side === 'left' || $scope.side === 'right') {\n                updateContainerWidth();\n\n                // gridUtil.logDebug('myWidth', myWidth);\n\n                // TODO(c0bra): Subtract sum of col widths from grid viewport width and update it\n                $elm.attr('style', null);\n\n                var myHeight = grid.renderContainers.body.getViewportHeight(); // + grid.horizontalScrollbarHeight;\n\n                ret += '.grid' + grid.id + ' .ui-grid-pinned-container-' + $scope.side + ', .grid' + grid.id + ' .ui-grid-pinned-container-' + $scope.side + ' .ui-grid-render-container-' + $scope.side + ' .ui-grid-viewport { width: ' + myWidth + 'px; height: ' + myHeight + 'px; } ';\n              }\n\n              return ret;\n            }\n\n            grid.renderContainers.body.registerViewportAdjuster(function (adjustment) {\n              if ( myWidth === 0 || !myWidth ){\n                updateContainerWidth();\n              }\n              // Subtract our own width\n              adjustment.width -= myWidth;\n\n              return adjustment;\n            });\n\n            // Register style computation to adjust for columns in `side`'s render container\n            grid.registerStyleComputation({\n              priority: 15,\n              func: updateContainerDimensions\n            });\n          }\n        };\n      }\n    };\n  }]);\n})();\n(function(){\n\nangular.module('ui.grid')\n.factory('Grid', ['$q', '$compile', '$parse', 'gridUtil', 'uiGridConstants', 'GridOptions', 'GridColumn', 'GridRow', 'GridApi', 'rowSorter', 'rowSearcher', 'GridRenderContainer', '$timeout',\n    function($q, $compile, $parse, gridUtil, uiGridConstants, GridOptions, GridColumn, GridRow, GridApi, rowSorter, rowSearcher, GridRenderContainer, $timeout) {\n\n  /**\n   * @ngdoc object\n   * @name ui.grid.core.api:PublicApi\n   * @description Public Api for the core grid features\n   *\n   */\n  \n  /**\n   * @ngdoc function\n   * @name ui.grid.class:Grid\n   * @description Grid is the main viewModel.  Any properties or methods needed to maintain state are defined in\n   * this prototype.  One instance of Grid is created per Grid directive instance.\n   * @param {object} options Object map of options to pass into the grid. An 'id' property is expected.\n   */\n  var Grid = function Grid(options) {\n    var self = this;\n    // Get the id out of the options, then remove it\n    if (options !== undefined && typeof(options.id) !== 'undefined' && options.id) {\n      if (!/^[_a-zA-Z0-9-]+$/.test(options.id)) {\n        throw new Error(\"Grid id '\" + options.id + '\" is invalid. It must follow CSS selector syntax rules.');\n      }\n    }\n    else {\n      throw new Error('No ID provided. An ID must be given when creating a grid.');\n    }\n  \n    self.id = options.id;\n    delete options.id;\n  \n    // Get default options\n    self.options = GridOptions.initialize( options );\n\n    /**\n     * @ngdoc object\n     * @name appScope\n     * @propertyOf ui.grid.class:Grid\n     * @description reference to the application scope (the parent scope of the ui-grid element).  Assigned in ui-grid controller\n     * <br/>\n     * use gridOptions.appScopeProvider to override the default assignment of $scope.$parent with any reference\n     */\n    self.appScope = self.options.appScopeProvider;\n  \n    self.headerHeight = self.options.headerRowHeight;\n\n\n    self.footerHeight = self.calcFooterHeight();\n\n    self.rtl = false;\n    self.gridHeight = 0;\n    self.gridWidth = 0;\n    self.columnBuilders = [];\n    self.rowBuilders = [];\n    self.rowsProcessors = [];\n    self.columnsProcessors = [];\n    self.styleComputations = [];\n    self.viewportAdjusters = [];\n    self.rowHeaderColumns = [];\n    self.dataChangeCallbacks = {};\n  \n    // self.visibleRowCache = [];\n  \n    // Set of 'render' containers for self grid, which can render sets of rows\n    self.renderContainers = {};\n  \n    // Create a\n    self.renderContainers.body = new GridRenderContainer('body', self);\n  \n    self.cellValueGetterCache = {};\n  \n    // Cached function to use with custom row templates\n    self.getRowTemplateFn = null;\n  \n  \n    //representation of the rows on the grid.\n    //these are wrapped references to the actual data rows (options.data)\n    self.rows = [];\n  \n    //represents the columns on the grid\n    self.columns = [];\n  \n    /**\n     * @ngdoc boolean\n     * @name isScrollingVertically\n     * @propertyOf ui.grid.class:Grid\n     * @description set to true when Grid is scrolling vertically. Set to false via debounced method\n     */\n    self.isScrollingVertically = false;\n  \n    /**\n     * @ngdoc boolean\n     * @name isScrollingHorizontally\n     * @propertyOf ui.grid.class:Grid\n     * @description set to true when Grid is scrolling horizontally. Set to false via debounced method\n     */\n    self.isScrollingHorizontally = false;\n\n    /**\n     * @ngdoc property\n     * @name scrollDirection\n     * @propertyOf ui.grid.class:Grid\n     * @description set one of the uiGridConstants.scrollDirection values (UP, DOWN, LEFT, RIGHT, NONE), which tells\n     * us which direction we are scrolling. Set to NONE via debounced method\n     */\n    self.scrollDirection = uiGridConstants.scrollDirection.NONE;\n\n    var debouncedVertical = gridUtil.debounce(function () {\n      self.isScrollingVertically = false;\n      self.scrollDirection = uiGridConstants.scrollDirection.NONE;\n    }, 1000);\n  \n    var debouncedHorizontal = gridUtil.debounce(function () {\n      self.isScrollingHorizontally = false;\n      self.scrollDirection = uiGridConstants.scrollDirection.NONE;\n    }, 1000);\n  \n  \n    /**\n     * @ngdoc function\n     * @name flagScrollingVertically\n     * @methodOf ui.grid.class:Grid\n     * @description sets isScrollingVertically to true and sets it to false in a debounced function\n     */\n    self.flagScrollingVertically = function() {\n      self.isScrollingVertically = true;\n      debouncedVertical();\n    };\n  \n    /**\n     * @ngdoc function\n     * @name flagScrollingHorizontally\n     * @methodOf ui.grid.class:Grid\n     * @description sets isScrollingHorizontally to true and sets it to false in a debounced function\n     */\n    self.flagScrollingHorizontally = function() {\n      self.isScrollingHorizontally = true;\n      debouncedHorizontal();\n    };\n\n    self.scrollbarHeight = 0;\n    self.scrollbarWidth = 0;\n    if (self.options.enableHorizontalScrollbar === uiGridConstants.scrollbars.ALWAYS) {\n      self.scrollbarHeight = gridUtil.getScrollbarWidth();\n    }\n\n    if (self.options.enableVerticalScrollbar === uiGridConstants.scrollbars.ALWAYS) {\n      self.scrollbarWidth = gridUtil.getScrollbarWidth();\n    }\n  \n  \n  \n    self.api = new GridApi(self);\n  \n    /**\n     * @ngdoc function\n     * @name refresh\n     * @methodOf ui.grid.core.api:PublicApi\n     * @description Refresh the rendered grid on screen.\n     * \n     */\n    self.api.registerMethod( 'core', 'refresh', this.refresh );\n  \n    /**\n     * @ngdoc function\n     * @name refreshRows\n     * @methodOf ui.grid.core.api:PublicApi\n     * @description Refresh the rendered grid on screen?  Note: not functional at present\n     * @returns {promise} promise that is resolved when render completes?\n     * \n     */\n    self.api.registerMethod( 'core', 'refreshRows', this.refreshRows );\n  \n    /**\n     * @ngdoc function\n     * @name handleWindowResize\n     * @methodOf ui.grid.core.api:PublicApi\n     * @description Trigger a grid resize, normally this would be picked\n     * up by a watch on window size, but in some circumstances it is necessary\n     * to call this manually\n     * @returns {promise} promise that is resolved when render completes?\n     * \n     */\n    self.api.registerMethod( 'core', 'handleWindowResize', this.handleWindowResize );\n  \n  \n    /**\n     * @ngdoc function\n     * @name addRowHeaderColumn\n     * @methodOf ui.grid.core.api:PublicApi\n     * @description adds a row header column to the grid\n     * @param {object} column def\n     * \n     */\n    self.api.registerMethod( 'core', 'addRowHeaderColumn', this.addRowHeaderColumn );\n  \n  \n    /**\n     * @ngdoc function\n     * @name sortHandleNulls\n     * @methodOf ui.grid.core.api:PublicApi\n     * @description A null handling method that can be used when building custom sort\n     * functions\n     * @example\n     * <pre>\n     *   mySortFn = function(a, b) {\n     *   var nulls = $scope.gridApi.core.sortHandleNulls(a, b);\n     *   if ( nulls !== null ){\n     *     return nulls;\n     *   } else {\n     *     // your code for sorting here\n     *   };\n     * </pre>\n     * @param {object} a sort value a\n     * @param {object} b sort value b\n     * @returns {number} null if there were no nulls/undefineds, otherwise returns\n     * a sort value that should be passed back from the sort function\n     * \n     */\n    self.api.registerMethod( 'core', 'sortHandleNulls', rowSorter.handleNulls );\n  \n  \n    /**\n     * @ngdoc function\n     * @name sortChanged\n     * @methodOf  ui.grid.core.api:PublicApi\n     * @description The sort criteria on one or more columns has\n     * changed.  Provides as parameters the grid and the output of\n     * getColumnSorting, which is an array of gridColumns\n     * that have sorting on them, sorted in priority order. \n     * \n     * @param {Grid} grid the grid\n     * @param {array} sortColumns an array of columns with \n     * sorts on them, in priority order\n     * \n     * @example\n     * <pre>\n     *      gridApi.core.on.sortChanged( grid, sortColumns );\n     * </pre>\n     */\n    self.api.registerEvent( 'core', 'sortChanged' );\n  \n      /**\n     * @ngdoc function\n     * @name columnVisibilityChanged\n     * @methodOf  ui.grid.core.api:PublicApi\n     * @description The visibility of a column has changed,\n     * the column itself is passed out as a parameter of the event. \n     * \n     * @param {GridCol} column the column that changed\n     * \n     * @example\n     * <pre>\n     *      gridApi.core.on.columnVisibilityChanged( $scope, function (column) {\n     *        // do something\n     *      } );\n     * </pre>\n     */\n    self.api.registerEvent( 'core', 'columnVisibilityChanged' );\n  \n    /**\n     * @ngdoc method\n     * @name notifyDataChange\n     * @methodOf ui.grid.core.api:PublicApi\n     * @description Notify the grid that a data or config change has occurred,\n     * where that change isn't something the grid was otherwise noticing.  This \n     * might be particularly relevant where you've changed values within the data\n     * and you'd like cell classes to be re-evaluated, or changed config within \n     * the columnDef and you'd like headerCellClasses to be re-evaluated.\n     * @param {string} type one of the \n     * uiGridConstants.dataChange values (ALL, ROW, EDIT, COLUMN), which tells\n     * us which refreshes to fire.\n     * \n     */\n    self.api.registerMethod( 'core', 'notifyDataChange', this.notifyDataChange );\n    \n    self.registerDataChangeCallback( self.columnRefreshCallback, [uiGridConstants.dataChange.COLUMN]);\n    self.registerDataChangeCallback( self.processRowsCallback, [uiGridConstants.dataChange.EDIT]);\n\n    self.registerStyleComputation({\n      priority: 10,\n      func: self.getFooterStyles\n    });\n  };\n\n   Grid.prototype.calcFooterHeight = function () {\n     if (!this.hasFooter()) {\n       return 0;\n     }\n\n     var height = 0;\n     if (this.options.showGridFooter) {\n       height += this.options.gridFooterHeight;\n     }\n\n     if (this.options.showColumnFooter) {\n       height += this.options.columnFooterHeight;\n     }\n\n     return height;\n   };\n\n   Grid.prototype.getFooterStyles = function () {\n     var style = '.grid' + this.id + ' .ui-grid-footer-aggregates-row { height: ' + this.options.columnFooterHeight + 'px; }';\n     style += ' .grid' + this.id + ' .ui-grid-footer-info { height: ' + this.options.gridFooterHeight + 'px; }';\n     return style;\n   };\n\n  Grid.prototype.hasFooter = function () {\n   return this.options.showGridFooter || this.options.showColumnFooter;\n  };\n\n  /**\n   * @ngdoc function\n   * @name isRTL\n   * @methodOf ui.grid.class:Grid\n   * @description Returns true if grid is RightToLeft\n   */\n  Grid.prototype.isRTL = function () {\n    return this.rtl;\n  };\n\n\n  /**\n   * @ngdoc function\n   * @name registerColumnBuilder\n   * @methodOf ui.grid.class:Grid\n   * @description When the build creates columns from column definitions, the columnbuilders will be called to add\n   * additional properties to the column.\n   * @param {function(colDef, col, gridOptions)} columnsProcessor function to be called\n   */\n  Grid.prototype.registerColumnBuilder = function registerColumnBuilder(columnBuilder) {\n    this.columnBuilders.push(columnBuilder);\n  };\n\n  /**\n   * @ngdoc function\n   * @name buildColumnDefsFromData\n   * @methodOf ui.grid.class:Grid\n   * @description Populates columnDefs from the provided data\n   * @param {function(colDef, col, gridOptions)} rowBuilder function to be called\n   */\n  Grid.prototype.buildColumnDefsFromData = function (dataRows){\n    this.options.columnDefs =  gridUtil.getColumnsFromData(dataRows, this.options.excludeProperties);\n  };\n\n  /**\n   * @ngdoc function\n   * @name registerRowBuilder\n   * @methodOf ui.grid.class:Grid\n   * @description When the build creates rows from gridOptions.data, the rowBuilders will be called to add\n   * additional properties to the row.\n   * @param {function(row, gridOptions)} rowBuilder function to be called\n   */\n  Grid.prototype.registerRowBuilder = function registerRowBuilder(rowBuilder) {\n    this.rowBuilders.push(rowBuilder);\n  };\n\n\n  /**\n   * @ngdoc function\n   * @name registerDataChangeCallback\n   * @methodOf ui.grid.class:Grid\n   * @description When a data change occurs, the data change callbacks of the specified type\n   * will be called.  The rules are:\n   * \n   * - when the data watch fires, that is considered a ROW change (the data watch only notices\n   *   added or removed rows)\n   * - when the api is called to inform us of a change, the declared type of that change is used\n   * - when a cell edit completes, the EDIT callbacks are triggered\n   * - when the columnDef watch fires, the COLUMN callbacks are triggered\n   * - when the options watch fires, the OPTIONS callbacks are triggered\n   * \n   * For a given event:\n   * - ALL calls ROW, EDIT, COLUMN, OPTIONS and ALL callbacks\n   * - ROW calls ROW and ALL callbacks\n   * - EDIT calls EDIT and ALL callbacks\n   * - COLUMN calls COLUMN and ALL callbacks\n   * - OPTIONS calls OPTIONS and ALL callbacks\n   * \n   * @param {function(grid)} callback function to be called\n   * @param {array} types the types of data change you want to be informed of.  Values from \n   * the uiGridConstants.dataChange values ( ALL, EDIT, ROW, COLUMN, OPTIONS ).  Optional and defaults to\n   * ALL \n   * @returns {function} deregister function - a function that can be called to deregister this callback\n   */\n  Grid.prototype.registerDataChangeCallback = function registerDataChangeCallback(callback, types, _this) {\n    var uid = gridUtil.nextUid();\n    if ( !types ){\n      types = [uiGridConstants.dataChange.ALL];\n    }\n    if ( !Array.isArray(types)){\n      gridUtil.logError(\"Expected types to be an array or null in registerDataChangeCallback, value passed was: \" + types );\n    }\n    this.dataChangeCallbacks[uid] = { callback: callback, types: types, _this:_this };\n    \n    var self = this;\n    var deregisterFunction = function() {\n      delete self.dataChangeCallbacks[uid];\n    };\n    return deregisterFunction;\n  };\n\n  /**\n   * @ngdoc function\n   * @name callDataChangeCallbacks\n   * @methodOf ui.grid.class:Grid\n   * @description Calls the callbacks based on the type of data change that\n   * has occurred. Always calls the ALL callbacks, calls the ROW, EDIT, COLUMN and OPTIONS callbacks if the \n   * event type is matching, or if the type is ALL.\n   * @param {number} type the type of event that occurred - one of the \n   * uiGridConstants.dataChange values (ALL, ROW, EDIT, COLUMN, OPTIONS)\n   */\n  Grid.prototype.callDataChangeCallbacks = function callDataChangeCallbacks(type, options) {\n    angular.forEach( this.dataChangeCallbacks, function( callback, uid ){\n      if ( callback.types.indexOf( uiGridConstants.dataChange.ALL ) !== -1 ||\n           callback.types.indexOf( type ) !== -1 ||\n           type === uiGridConstants.dataChange.ALL ) {\n        if (callback._this) {\n           callback.callback.apply(callback._this,this);\n        }\n        else {\n          callback.callback( this );\n        }\n      }\n    }, this);\n  };\n  \n  /**\n   * @ngdoc function\n   * @name notifyDataChange\n   * @methodOf ui.grid.class:Grid\n   * @description Notifies us that a data change has occurred, used in the public\n   * api for users to tell us when they've changed data or some other event that \n   * our watches cannot pick up\n   * @param {string} type the type of event that occurred - one of the \n   * uiGridConstants.dataChange values (ALL, ROW, EDIT, COLUMN)\n   */\n  Grid.prototype.notifyDataChange = function notifyDataChange(type) {\n    var constants = uiGridConstants.dataChange;\n    if ( type === constants.ALL || \n         type === constants.COLUMN ||\n         type === constants.EDIT ||\n         type === constants.ROW ||\n         type === constants.OPTIONS ){\n      this.callDataChangeCallbacks( type );\n    } else {\n      gridUtil.logError(\"Notified of a data change, but the type was not recognised, so no action taken, type was: \" + type);\n    }\n  };\n  \n  \n  /**\n   * @ngdoc function\n   * @name columnRefreshCallback\n   * @methodOf ui.grid.class:Grid\n   * @description refreshes the grid when a column refresh\n   * is notified, which triggers handling of the visible flag. \n   * This is called on uiGridConstants.dataChange.COLUMN, and is \n   * registered as a dataChangeCallback in grid.js\n   * @param {string} name column name\n   */\n  Grid.prototype.columnRefreshCallback = function columnRefreshCallback( grid ){\n    grid.buildColumns();\n    grid.refresh();\n  };\n\n\n  /**\n   * @ngdoc function\n   * @name processRowsCallback\n   * @methodOf ui.grid.class:Grid\n   * @description calls the row processors, specifically\n   * intended to reset the sorting when an edit is called,\n   * registered as a dataChangeCallback on uiGridConstants.dataChange.EDIT\n   * @param {string} name column name\n   */\n  Grid.prototype.processRowsCallback = function processRowsCallback( grid ){\n    grid.refreshRows();\n  };\n    \n\n  /**\n   * @ngdoc function\n   * @name getColumn\n   * @methodOf ui.grid.class:Grid\n   * @description returns a grid column for the column name\n   * @param {string} name column name\n   */\n  Grid.prototype.getColumn = function getColumn(name) {\n    var columns = this.columns.filter(function (column) {\n      return column.colDef.name === name;\n    });\n    return columns.length > 0 ? columns[0] : null;\n  };\n\n  /**\n   * @ngdoc function\n   * @name getColDef\n   * @methodOf ui.grid.class:Grid\n   * @description returns a grid colDef for the column name\n   * @param {string} name column.field\n   */\n  Grid.prototype.getColDef = function getColDef(name) {\n    var colDefs = this.options.columnDefs.filter(function (colDef) {\n      return colDef.name === name;\n    });\n    return colDefs.length > 0 ? colDefs[0] : null;\n  };\n\n  /**\n   * @ngdoc function\n   * @name assignTypes\n   * @methodOf ui.grid.class:Grid\n   * @description uses the first row of data to assign colDef.type for any types not defined.\n   */\n  /**\n   * @ngdoc property\n   * @name type\n   * @propertyOf ui.grid.class:GridOptions.columnDef\n   * @description the type of the column, used in sorting.  If not provided then the \n   * grid will guess the type.  Add this only if the grid guessing is not to your\n   * satisfaction.  Refer to {@link ui.grid.service:GridUtil.guessType gridUtil.guessType} for\n   * a list of values the grid knows about.\n   *\n   */\n  Grid.prototype.assignTypes = function(){\n    var self = this;\n    self.options.columnDefs.forEach(function (colDef, index) {\n\n      //Assign colDef type if not specified\n      if (!colDef.type) {\n        var col = new GridColumn(colDef, index, self);\n        var firstRow = self.rows.length > 0 ? self.rows[0] : null;\n        if (firstRow) {\n          colDef.type = gridUtil.guessType(self.getCellValue(firstRow, col));\n        }\n        else {\n          gridUtil.logWarn('Unable to assign type from data, so defaulting to string');\n          colDef.type = 'string';\n        }\n      }\n    });\n  };\n\n  /**\n  * @ngdoc function\n  * @name addRowHeaderColumn\n  * @methodOf ui.grid.class:Grid\n  * @description adds a row header column to the grid\n  * @param {object} column def\n  */\n  Grid.prototype.addRowHeaderColumn = function addRowHeaderColumn(colDef) {\n    var self = this;\n    //self.createLeftContainer();\n    var rowHeaderCol = new GridColumn(colDef, self.rowHeaderColumns.length, self);\n    rowHeaderCol.isRowHeader = true;\n    if (self.isRTL()) {\n      self.createRightContainer();\n      rowHeaderCol.renderContainer = 'right';\n    }\n    else {\n      self.createLeftContainer();\n      rowHeaderCol.renderContainer = 'left';\n    }\n\n    // relies on the default column builder being first in array, as it is instantiated\n    // as part of grid creation\n    self.columnBuilders[0](colDef,rowHeaderCol,self.options)\n      .then(function(){\n        rowHeaderCol.enableFiltering = false;\n        rowHeaderCol.enableSorting = false;\n        rowHeaderCol.enableHiding = false;\n        self.rowHeaderColumns.push(rowHeaderCol);\n        self.buildColumns()\n          .then( function() {\n            self.preCompileCellTemplates();\n            self.refresh();\n          });\n      });\n  };\n\n  /**\n   * @ngdoc function\n   * @name buildColumns\n   * @methodOf ui.grid.class:Grid\n   * @description creates GridColumn objects from the columnDefinition.  Calls each registered\n   * columnBuilder to further process the column\n   * @param {object} options  An object contains options to use when building columns\n   *\n   * * **orderByColumnDefs**: defaults to **false**. When true, `buildColumns` will reorder existing columns according to the order within the column definitions.\n   *\n   * @returns {Promise} a promise to load any needed column resources\n   */\n  Grid.prototype.buildColumns = function buildColumns(opts) {\n    var options = {\n      orderByColumnDefs: false\n    };\n\n    angular.extend(options, opts);\n\n    // gridUtil.logDebug('buildColumns');\n    var self = this;\n    var builderPromises = [];\n    var headerOffset = self.rowHeaderColumns.length;\n    var i;\n\n    // Remove any columns for which a columnDef cannot be found\n    // Deliberately don't use forEach, as it doesn't like splice being called in the middle\n    // Also don't cache columns.length, as it will change during this operation\n    for (i = 0; i < self.columns.length; i++){\n      if (!self.getColDef(self.columns[i].name)) {\n        self.columns.splice(i, 1);\n        i--;\n      }\n    }\n\n    //add row header columns to the grid columns array _after_ columns without columnDefs have been removed\n    self.rowHeaderColumns.forEach(function (rowHeaderColumn) {\n      self.columns.unshift(rowHeaderColumn);\n    });\n\n\n    // look at each column def, and update column properties to match.  If the column def\n    // doesn't have a column, then splice in a new gridCol\n    self.options.columnDefs.forEach(function (colDef, index) {\n      self.preprocessColDef(colDef);\n      var col = self.getColumn(colDef.name);\n\n      if (!col) {\n        col = new GridColumn(colDef, gridUtil.nextUid(), self);\n        self.columns.splice(index + headerOffset, 0, col);\n      }\n      else {\n        // tell updateColumnDef that the column was pre-existing\n        col.updateColumnDef(colDef, false);\n      }\n\n      self.columnBuilders.forEach(function (builder) {\n        builderPromises.push(builder.call(self, colDef, col, self.options));\n      });\n    });\n\n    /*** Reorder columns if necessary ***/\n    if (!!options.orderByColumnDefs) {\n      // Create a shallow copy of the columns as a cache\n      var columnCache = self.columns.slice(0);\n\n      // We need to allow for the \"row headers\" when mapping from the column defs array to the columns array\n      //   If we have a row header in columns[0] and don't account for it   we'll overwrite it with the column in columnDefs[0]\n\n      // Go through all the column defs\n      for (i = 0; i < self.options.columnDefs.length; i++) {\n        // If the column at this index has a different name than the column at the same index in the column defs...\n        if (self.columns[i + headerOffset].name !== self.options.columnDefs[i].name) {\n          // Replace the one in the cache with the appropriate column\n          columnCache[i + headerOffset] = self.getColumn(self.options.columnDefs[i].name);\n        }\n        else {\n          // Otherwise just copy over the one from the initial columns\n          columnCache[i + headerOffset] = self.columns[i + headerOffset];\n        }\n      }\n\n      // Empty out the columns array, non-destructively\n      self.columns.length = 0;\n\n      // And splice in the updated, ordered columns from the cache\n      Array.prototype.splice.apply(self.columns, [0, 0].concat(columnCache));\n    }\n\n    return $q.all(builderPromises).then(function(){\n      if (self.rows.length > 0){\n        self.assignTypes();\n      }\n    });\n  };\n\n/**\n * @ngdoc function\n * @name preCompileCellTemplates\n * @methodOf ui.grid.class:Grid\n * @description precompiles all cell templates\n */\n  Grid.prototype.preCompileCellTemplates = function() {\n    var self = this;\n    this.columns.forEach(function (col) {\n      var html = col.cellTemplate.replace(uiGridConstants.MODEL_COL_FIELD, self.getQualifiedColField(col));\n      html = html.replace(uiGridConstants.COL_FIELD, 'grid.getCellValue(row, col)');\n\n\n      var compiledElementFn = $compile(html);\n      col.compiledElementFn = compiledElementFn;\n\n      if (col.compiledElementFnDefer) {\n        col.compiledElementFnDefer.resolve(col.compiledElementFn);\n      }\n    });\n  };\n\n  /**\n   * @ngdoc function\n   * @name getGridQualifiedColField\n   * @methodOf ui.grid.class:Grid\n   * @description Returns the $parse-able accessor for a column within its $scope\n   * @param {GridColumn} col col object\n   */\n  Grid.prototype.getQualifiedColField = function (col) {\n    return 'row.entity.' + gridUtil.preEval(col.field);\n  };\n\n  /**\n   * @ngdoc function\n   * @name createLeftContainer\n   * @methodOf ui.grid.class:Grid\n   * @description creates the left render container if it doesn't already exist\n   */\n  Grid.prototype.createLeftContainer = function() {\n    if (!this.hasLeftContainer()) {\n      this.renderContainers.left = new GridRenderContainer('left', this, { disableColumnOffset: true });\n    }\n  };\n\n  /**\n   * @ngdoc function\n   * @name createRightContainer\n   * @methodOf ui.grid.class:Grid\n   * @description creates the right render container if it doesn't already exist\n   */\n  Grid.prototype.createRightContainer = function() {\n    if (!this.hasRightContainer()) {\n      this.renderContainers.right = new GridRenderContainer('right', this, { disableColumnOffset: true });\n    }\n  };\n\n  /**\n   * @ngdoc function\n   * @name hasLeftContainer\n   * @methodOf ui.grid.class:Grid\n   * @description returns true if leftContainer exists\n   */\n  Grid.prototype.hasLeftContainer = function() {\n    return this.renderContainers.left !== undefined;\n  };\n\n  /**\n   * @ngdoc function\n   * @name hasLeftContainer\n   * @methodOf ui.grid.class:Grid\n   * @description returns true if rightContainer exists\n   */\n  Grid.prototype.hasRightContainer = function() {\n    return this.renderContainers.right !== undefined;\n  };\n\n\n      /**\n   * undocumented function\n   * @name preprocessColDef\n   * @methodOf ui.grid.class:Grid\n   * @description defaults the name property from field to maintain backwards compatibility with 2.x\n   * validates that name or field is present\n   */\n  Grid.prototype.preprocessColDef = function preprocessColDef(colDef) {\n    var self = this;\n\n    if (!colDef.field && !colDef.name) {\n      throw new Error('colDef.name or colDef.field property is required');\n    }\n\n    //maintain backwards compatibility with 2.x\n    //field was required in 2.x.  now name is required\n    if (colDef.name === undefined && colDef.field !== undefined) {\n      // See if the column name already exists:\n      var foundName = self.getColumn(colDef.field);\n\n      // If a column with this name already  exists, we will add an incrementing number to the end of the new column name\n      if (foundName) {\n        // Search through the columns for names in the format: <name><1, 2 ... N>, i.e. 'Age1, Age2, Age3',\n        var nameRE = new RegExp('^' + colDef.field + '(\\\\d+)$', 'i');\n\n        var foundColumns = self.columns.filter(function (column) {\n          // Test against the displayName, as that's what'll have the incremented number\n          return nameRE.test(column.displayName);\n        })\n        // Sort the found columns by the end-number\n        .sort(function (a, b) {\n          if (a === b) {\n            return 0;\n          }\n          else {\n            var numA = a.match(nameRE)[1];\n            var numB = b.match(nameRE)[1];\n\n            return parseInt(numA, 10) > parseInt(numB, 10) ? 1 : -1;\n          }\n        });\n\n        // Not columns found, so start with number \"2\"\n        if (foundColumns.length === 0) {\n          colDef.name = colDef.field + '2';\n        }\n        else {\n          // Get the number from the final column\n          var lastNum = foundColumns[foundColumns.length-1].displayName.match(nameRE)[1];\n\n          // Make sure to parse to an int\n          lastNum = parseInt(lastNum, 10);\n\n          // Add 1 to the number from the last column and tack it on to the field to be the name for this new column \n          colDef.name = colDef.field + (lastNum + 1);\n        }\n      }\n      // ... otherwise just use the field as the column name\n      else {\n        colDef.name = colDef.field;\n      }\n    }\n\n  };\n\n  // Return a list of items that exist in the `n` array but not the `o` array. Uses optional property accessors passed as third & fourth parameters\n  Grid.prototype.newInN = function newInN(o, n, oAccessor, nAccessor) {\n    var self = this;\n\n    var t = [];\n    for (var i = 0; i < n.length; i++) {\n      var nV = nAccessor ? n[i][nAccessor] : n[i];\n      \n      var found = false;\n      for (var j = 0; j < o.length; j++) {\n        var oV = oAccessor ? o[j][oAccessor] : o[j];\n        if (self.options.rowEquality(nV, oV)) {\n          found = true;\n          break;\n        }\n      }\n      if (!found) {\n        t.push(nV);\n      }\n    }\n    \n    return t;\n  };\n\n    /**\n     * @ngdoc function\n     * @name getRow\n     * @methodOf ui.grid.class:Grid\n     * @description returns the GridRow that contains the rowEntity\n     * @param {object} rowEntity the gridOptions.data array element instance\n     */\n    Grid.prototype.getRow = function getRow(rowEntity) {\n      var self = this;\n      var rows = this.rows.filter(function (row) {\n        return self.options.rowEquality(row.entity, rowEntity);\n      });\n      return rows.length > 0 ? rows[0] : null;\n    };\n\n\n      /**\n   * @ngdoc function\n   * @name modifyRows\n   * @methodOf ui.grid.class:Grid\n   * @description creates or removes GridRow objects from the newRawData array.  Calls each registered\n   * rowBuilder to further process the row\n   *\n   * Rows are identified using the gridOptions.rowEquality function\n   */\n  Grid.prototype.modifyRows = function modifyRows(newRawData) {\n    var self = this,\n        i,\n        rowhash,\n        found,\n        newRow;\n    if ((self.options.useExternalSorting || self.getColumnSorting().length === 0) && newRawData.length > 0) {\n        var oldRowHash = self.rowHashMap;\n        if (!oldRowHash) {\n           oldRowHash = {get: function(){return null;}};\n        }\n        self.createRowHashMap();\n        rowhash = self.rowHashMap;\n        var wasEmpty = self.rows.length === 0;\n        self.rows.length = 0;\n        for (i = 0; i < newRawData.length; i++) {\n            var newRawRow = newRawData[i];\n            found = oldRowHash.get(newRawRow);\n            if (found) {\n              newRow = found.row; \n            }\n            else {\n              newRow = self.processRowBuilders(new GridRow(newRawRow, i, self));\n            }\n            self.rows.push(newRow);\n            rowhash.put(newRawRow, {\n                i: i,\n                entity: newRawRow,\n                row:newRow\n            });\n        }\n        //now that we have data, it is save to assign types to colDefs\n//        if (wasEmpty) {\n           self.assignTypes();\n//        }\n    } else {\n    if (self.rows.length === 0 && newRawData.length > 0) {\n      if (self.options.enableRowHashing) {\n        if (!self.rowHashMap) {\n          self.createRowHashMap();\n        }\n\n        for (i = 0; i < newRawData.length; i++) {\n          newRow = newRawData[i];\n\n          self.rowHashMap.put(newRow, {\n            i: i,\n            entity: newRow\n          });\n        }\n      }\n\n      self.addRows(newRawData);\n      //now that we have data, it is save to assign types to colDefs\n      self.assignTypes();\n    }\n    else if (newRawData.length > 0) {\n      var unfoundNewRows, unfoundOldRows, unfoundNewRowsToFind;\n\n      // If row hashing is turned on\n      if (self.options.enableRowHashing) {\n        // Array of new rows that haven't been found in the old rowset\n        unfoundNewRows = [];\n        // Array of new rows that we explicitly HAVE to search for manually in the old row set. They cannot be looked up by their identity (because it doesn't exist).\n        unfoundNewRowsToFind = [];\n        // Map of rows that have been found in the new rowset\n        var foundOldRows = {};\n        // Array of old rows that have NOT been found in the new rowset\n        unfoundOldRows = [];\n\n        // Create the row HashMap if it doesn't exist already\n        if (!self.rowHashMap) {\n          self.createRowHashMap();\n        }\n        rowhash = self.rowHashMap;\n        \n        // Make sure every new row has a hash\n        for (i = 0; i < newRawData.length; i++) {\n          newRow = newRawData[i];\n\n          // Flag this row as needing to be manually found if it didn't come in with a $$hashKey\n          var mustFind = false;\n          if (!self.options.getRowIdentity(newRow)) {\n            mustFind = true;\n          }\n\n          // See if the new row is already in the rowhash\n          found = rowhash.get(newRow);\n          // If so...\n          if (found) {\n            // See if it's already being used by as GridRow\n            if (found.row) {\n              // If so, mark this new row as being found\n              foundOldRows[self.options.rowIdentity(newRow)] = true;\n            }\n          }\n          else {\n            // Put the row in the hashmap with the index it corresponds to\n            rowhash.put(newRow, {\n              i: i,\n              entity: newRow\n            });\n            \n            // This row has to be searched for manually in the old row set\n            if (mustFind) {\n              unfoundNewRowsToFind.push(newRow);\n            }\n            else {\n              unfoundNewRows.push(newRow);\n            }\n          }\n        }\n\n        // Build the list of unfound old rows\n        for (i = 0; i < self.rows.length; i++) {\n          var row = self.rows[i];\n          var hash = self.options.rowIdentity(row.entity);\n          if (!foundOldRows[hash]) {\n            unfoundOldRows.push(row);\n          }\n        }\n      }\n\n      // Look for new rows\n      var newRows = unfoundNewRows || [];\n\n      // The unfound new rows is either `unfoundNewRowsToFind`, if row hashing is turned on, or straight `newRawData` if it isn't\n      var unfoundNew = (unfoundNewRowsToFind || newRawData);\n\n      // Search for real new rows in `unfoundNew` and concat them onto `newRows`\n      newRows = newRows.concat(self.newInN(self.rows, unfoundNew, 'entity'));\n      \n      self.addRows(newRows); \n      \n      var deletedRows = self.getDeletedRows((unfoundOldRows || self.rows), newRawData);\n\n      for (i = 0; i < deletedRows.length; i++) {\n        if (self.options.enableRowHashing) {\n          self.rowHashMap.remove(deletedRows[i].entity);\n        }\n\n        self.rows.splice( self.rows.indexOf(deletedRows[i]), 1 );\n      }\n    }\n    // Empty data set\n    else {\n      // Reset the row HashMap\n      self.createRowHashMap();\n\n      // Reset the rows length!\n      self.rows.length = 0;\n    }\n    }\n    \n    var p1 = $q.when(self.processRowsProcessors(self.rows))\n      .then(function (renderableRows) {\n        return self.setVisibleRows(renderableRows);\n      });\n\n    var p2 = $q.when(self.processColumnsProcessors(self.columns))\n      .then(function (renderableColumns) {\n        return self.setVisibleColumns(renderableColumns);\n      });\n\n    return $q.all([p1, p2]);\n  };\n\n  Grid.prototype.getDeletedRows = function(oldRows, newRows) {\n    var self = this;\n\n    var olds = oldRows.filter(function (oldRow) {\n      return !newRows.some(function (newItem) {\n        return self.options.rowEquality(newItem, oldRow.entity);\n      });\n    });\n    // var olds = self.newInN(newRows, oldRows, null, 'entity');\n    // dump('olds', olds);\n    return olds;\n  };\n\n  /**\n   * Private Undocumented Method\n   * @name addRows\n   * @methodOf ui.grid.class:Grid\n   * @description adds the newRawData array of rows to the grid and calls all registered\n   * rowBuilders. this keyword will reference the grid\n   */\n  Grid.prototype.addRows = function addRows(newRawData) {\n    var self = this;\n\n    var existingRowCount = self.rows.length;\n    for (var i = 0; i < newRawData.length; i++) {\n      var newRow = self.processRowBuilders(new GridRow(newRawData[i], i + existingRowCount, self));\n\n      if (self.options.enableRowHashing) {\n        var found = self.rowHashMap.get(newRow.entity);\n        if (found) {\n          found.row = newRow;\n        }\n      }\n\n      self.rows.push(newRow);\n    }\n  };\n\n  /**\n   * @ngdoc function\n   * @name processRowBuilders\n   * @methodOf ui.grid.class:Grid\n   * @description processes all RowBuilders for the gridRow\n   * @param {GridRow} gridRow reference to gridRow\n   * @returns {GridRow} the gridRow with all additional behavior added\n   */\n  Grid.prototype.processRowBuilders = function processRowBuilders(gridRow) {\n    var self = this;\n\n    self.rowBuilders.forEach(function (builder) {\n      builder.call(self, gridRow, self.options);\n    });\n\n    return gridRow;\n  };\n\n  /**\n   * @ngdoc function\n   * @name registerStyleComputation\n   * @methodOf ui.grid.class:Grid\n   * @description registered a styleComputation function\n   * \n   * If the function returns a value it will be appended into the grid's `<style>` block\n   * @param {function($scope)} styleComputation function\n   */\n  Grid.prototype.registerStyleComputation = function registerStyleComputation(styleComputationInfo) {\n    this.styleComputations.push(styleComputationInfo);\n  };\n\n\n  // NOTE (c0bra): We already have rowBuilders. I think these do exactly the same thing...\n  // Grid.prototype.registerRowFilter = function(filter) {\n  //   // TODO(c0bra): validate filter?\n\n  //   this.rowFilters.push(filter);\n  // };\n\n  // Grid.prototype.removeRowFilter = function(filter) {\n  //   var idx = this.rowFilters.indexOf(filter);\n\n  //   if (typeof(idx) !== 'undefined' && idx !== undefined) {\n  //     this.rowFilters.slice(idx, 1);\n  //   }\n  // };\n  \n  // Grid.prototype.processRowFilters = function(rows) {\n  //   var self = this;\n  //   self.rowFilters.forEach(function (filter) {\n  //     filter.call(self, rows);\n  //   });\n  // };\n\n\n  /**\n   * @ngdoc function\n   * @name registerRowsProcessor\n   * @methodOf ui.grid.class:Grid\n   * @param {function(renderableRows)} rows processor function\n   * @returns {Array[GridRow]} Updated renderable rows\n   * @description\n\n     Register a \"rows processor\" function. When the rows are updated,\n     the grid calls each registered \"rows processor\", which has a chance\n     to alter the set of rows (sorting, etc) as long as the count is not\n     modified.\n   */\n  Grid.prototype.registerRowsProcessor = function registerRowsProcessor(processor) {\n    if (!angular.isFunction(processor)) {\n      throw 'Attempt to register non-function rows processor: ' + processor;\n    }\n\n    this.rowsProcessors.push(processor);\n  };\n\n  /**\n   * @ngdoc function\n   * @name removeRowsProcessor\n   * @methodOf ui.grid.class:Grid\n   * @param {function(renderableRows)} rows processor function\n   * @description Remove a registered rows processor\n   */\n  Grid.prototype.removeRowsProcessor = function removeRowsProcessor(processor) {\n    var idx = this.rowsProcessors.indexOf(processor);\n\n    if (typeof(idx) !== 'undefined' && idx !== undefined) {\n      this.rowsProcessors.splice(idx, 1);\n    }\n  };\n  \n  /**\n   * Private Undocumented Method\n   * @name processRowsProcessors\n   * @methodOf ui.grid.class:Grid\n   * @param {Array[GridRow]} The array of \"renderable\" rows\n   * @param {Array[GridColumn]} The array of columns\n   * @description Run all the registered rows processors on the array of renderable rows\n   */\n  Grid.prototype.processRowsProcessors = function processRowsProcessors(renderableRows) {\n    var self = this;\n\n    // Create a shallow copy of the rows so that we can safely sort them without altering the original grid.rows sort order\n    var myRenderableRows = renderableRows.slice(0);\n    \n    // self.rowsProcessors.forEach(function (processor) {\n    //   myRenderableRows = processor.call(self, myRenderableRows, self.columns);\n\n    //   if (!renderableRows) {\n    //     throw \"Processor at index \" + i + \" did not return a set of renderable rows\";\n    //   }\n\n    //   if (!angular.isArray(renderableRows)) {\n    //     throw \"Processor at index \" + i + \" did not return an array\";\n    //   }\n\n    //   i++;\n    // });\n\n    // Return myRenderableRows with no processing if we have no rows processors \n    if (self.rowsProcessors.length === 0) {\n      return $q.when(myRenderableRows);\n    }\n  \n    // Counter for iterating through rows processors\n    var i = 0;\n    \n    // Promise for when we're done with all the processors\n    var finished = $q.defer();\n\n    // This function will call the processor in self.rowsProcessors at index 'i', and then\n    //   when done will call the next processor in the list, using the output from the processor\n    //   at i as the argument for 'renderedRowsToProcess' on the next iteration.\n    //  \n    //   If we're at the end of the list of processors, we resolve our 'finished' callback with\n    //   the result.\n    function startProcessor(i, renderedRowsToProcess) {\n      // Get the processor at 'i'\n      var processor = self.rowsProcessors[i];\n\n      // Call the processor, passing in the rows to process and the current columns\n      //   (note: it's wrapped in $q.when() in case the processor does not return a promise)\n      return $q.when( processor.call(self, renderedRowsToProcess, self.columns) )\n        .then(function handleProcessedRows(processedRows) {\n          // Check for errors\n          if (!processedRows) {\n            throw \"Processor at index \" + i + \" did not return a set of renderable rows\";\n          }\n\n          if (!angular.isArray(processedRows)) {\n            throw \"Processor at index \" + i + \" did not return an array\";\n          }\n\n          // Processor is done, increment the counter\n          i++;\n\n          // If we're not done with the processors, call the next one\n          if (i <= self.rowsProcessors.length - 1) {\n            return startProcessor(i, processedRows);\n          }\n          // We're done! Resolve the 'finished' promise\n          else {\n            finished.resolve(processedRows);\n          }\n        });\n    }\n\n    // Start on the first processor\n    startProcessor(0, myRenderableRows);\n    \n    return finished.promise;\n  };\n\n  Grid.prototype.setVisibleRows = function setVisibleRows(rows) {\n    // gridUtil.logDebug('setVisibleRows');\n\n    var self = this;\n\n    //var newVisibleRowCache = [];\n\n    // Reset all the render container row caches\n    for (var i in self.renderContainers) {\n      var container = self.renderContainers[i];\n\n      container.canvasHeightShouldUpdate = true;\n      \n      if ( typeof(container.visibleRowCache) === 'undefined' ){\n        container.visibleRowCache = [];  \n      } else {\n        container.visibleRowCache.length = 0;  \n      }\n    }\n    \n    // rows.forEach(function (row) {\n    for (var ri = 0; ri < rows.length; ri++) {\n      var row = rows[ri];\n\n      // If the row is visible\n      if (row.visible) {\n        // newVisibleRowCache.push(row);\n\n        // If the row has a container specified\n        if (typeof(row.renderContainer) !== 'undefined' && row.renderContainer) {\n          self.renderContainers[row.renderContainer].visibleRowCache.push(row);\n        }\n        // If not, put it into the body container\n        else {\n          self.renderContainers.body.visibleRowCache.push(row);\n        }\n      }\n    }\n    self.api.core.raise.rowsRendered(this.api);\n  };\n\n  /**\n   * @ngdoc function\n   * @name registerColumnsProcessor\n   * @methodOf ui.grid.class:Grid\n   * @param {function(renderableColumns)} rows processor function\n   * @returns {Array[GridColumn]} Updated renderable columns\n   * @description\n\n     Register a \"columns processor\" function. When the columns are updated,\n     the grid calls each registered \"columns processor\", which has a chance\n     to alter the set of columns, as long as the count is not modified.\n   */\n  Grid.prototype.registerColumnsProcessor = function registerColumnsProcessor(processor) {\n    if (!angular.isFunction(processor)) {\n      throw 'Attempt to register non-function rows processor: ' + processor;\n    }\n\n    this.columnsProcessors.push(processor);\n  };\n\n  Grid.prototype.removeColumnsProcessor = function removeColumnsProcessor(processor) {\n    var idx = this.columnsProcessors.indexOf(processor);\n\n    if (typeof(idx) !== 'undefined' && idx !== undefined) {\n      this.columnsProcessors.splice(idx, 1);\n    }\n  };\n\n  Grid.prototype.processColumnsProcessors = function processColumnsProcessors(renderableColumns) {\n    var self = this;\n\n    // Create a shallow copy of the rows so that we can safely sort them without altering the original grid.rows sort order\n    var myRenderableColumns = renderableColumns.slice(0);\n\n    // Return myRenderableRows with no processing if we have no rows processors \n    if (self.columnsProcessors.length === 0) {\n      return $q.when(myRenderableColumns);\n    }\n  \n    // Counter for iterating through rows processors\n    var i = 0;\n    \n    // Promise for when we're done with all the processors\n    var finished = $q.defer();\n\n    // This function will call the processor in self.rowsProcessors at index 'i', and then\n    //   when done will call the next processor in the list, using the output from the processor\n    //   at i as the argument for 'renderedRowsToProcess' on the next iteration.\n    //  \n    //   If we're at the end of the list of processors, we resolve our 'finished' callback with\n    //   the result.\n    function startProcessor(i, renderedColumnsToProcess) {\n      // Get the processor at 'i'\n      var processor = self.columnsProcessors[i];\n\n      // Call the processor, passing in the rows to process and the current columns\n      //   (note: it's wrapped in $q.when() in case the processor does not return a promise)\n      return $q.when( processor.call(self, renderedColumnsToProcess, self.rows) )\n        .then(function handleProcessedRows(processedColumns) {\n          // Check for errors\n          if (!processedColumns) {\n            throw \"Processor at index \" + i + \" did not return a set of renderable rows\";\n          }\n\n          if (!angular.isArray(processedColumns)) {\n            throw \"Processor at index \" + i + \" did not return an array\";\n          }\n\n          // Processor is done, increment the counter\n          i++;\n\n          // If we're not done with the processors, call the next one\n          if (i <= self.columnsProcessors.length - 1) {\n            return startProcessor(i, myRenderableColumns);\n          }\n          // We're done! Resolve the 'finished' promise\n          else {\n            finished.resolve(myRenderableColumns);\n          }\n        });\n    }\n\n    // Start on the first processor\n    startProcessor(0, myRenderableColumns);\n    \n    return finished.promise;\n  };\n\n  Grid.prototype.setVisibleColumns = function setVisibleColumns(columns) {\n    // gridUtil.logDebug('setVisibleColumns');\n\n    var self = this;\n\n    // Reset all the render container row caches\n    for (var i in self.renderContainers) {\n      var container = self.renderContainers[i];\n\n      container.visibleColumnCache.length = 0;\n    }\n\n    for (var ci = 0; ci < columns.length; ci++) {\n      var column = columns[ci];\n\n      // If the column is visible\n      if (column.visible) {\n        // If the column has a container specified\n        if (typeof(column.renderContainer) !== 'undefined' && column.renderContainer) {\n          self.renderContainers[column.renderContainer].visibleColumnCache.push(column);\n        }\n        // If not, put it into the body container\n        else {\n          self.renderContainers.body.visibleColumnCache.push(column);\n        }\n      }\n    }\n  };\n\n  /**\n   * @ngdoc function\n   * @name handleWindowResize\n   * @methodOf ui.grid.class:Grid\n   * @description Triggered when the browser window resizes; automatically resizes the grid\n   */\n  Grid.prototype.handleWindowResize = function handleWindowResize($event) {\n    var self = this;\n\n    self.gridWidth = gridUtil.elementWidth(self.element);\n    self.gridHeight = gridUtil.elementHeight(self.element);\n\n    self.queueRefresh();\n  };\n\n  /**\n   * @ngdoc function\n   * @name queueRefresh\n   * @methodOf ui.grid.class:Grid\n   * @description todo: @c0bra can you document this method?\n   */\n  Grid.prototype.queueRefresh = function queueRefresh() {\n    var self = this;\n\n    if (self.refreshCanceller) {\n      $timeout.cancel(self.refreshCanceller);\n    }\n\n    self.refreshCanceller = $timeout(function () {\n      self.refreshCanvas(true);\n    });\n\n    self.refreshCanceller.then(function () {\n      self.refreshCanceller = null;\n    });\n\n    return self.refreshCanceller;\n  };\n\n  /**\n   * @ngdoc function\n   * @name updateCanvasHeight\n   * @methodOf ui.grid.class:Grid\n   * @description flags all render containers to update their canvas height\n   */\n  Grid.prototype.updateCanvasHeight = function updateCanvasHeight() {\n    var self = this;\n\n    for (var containerId in self.renderContainers) {\n      if (self.renderContainers.hasOwnProperty(containerId)) {\n        var container = self.renderContainers[containerId];\n        container.canvasHeightShouldUpdate = true;\n      }\n    }\n  };\n\n  /**\n   * @ngdoc function\n   * @name buildStyles\n   * @methodOf ui.grid.class:Grid\n   * @description calls each styleComputation function\n   */\n  // TODO: this used to take $scope, but couldn't see that it was used\n  Grid.prototype.buildStyles = function buildStyles() {\n    // gridUtil.logDebug('buildStyles');\n\n    var self = this;\n    \n    self.customStyles = '';\n\n    self.styleComputations\n      .sort(function(a, b) {\n        if (a.priority === null) { return 1; }\n        if (b.priority === null) { return -1; }\n        if (a.priority === null && b.priority === null) { return 0; }\n        return a.priority - b.priority;\n      })\n      .forEach(function (compInfo) {\n        // this used to provide $scope as a second parameter, but I couldn't find any \n        // style builders that used it, so removed it as part of moving to grid from controller\n        var ret = compInfo.func.call(self);\n\n        if (angular.isString(ret)) {\n          self.customStyles += '\\n' + ret;\n        }\n      });\n  };\n\n\n  Grid.prototype.minColumnsToRender = function minColumnsToRender() {\n    var self = this;\n    var viewport = this.getViewportWidth();\n\n    var min = 0;\n    var totalWidth = 0;\n    self.columns.forEach(function(col, i) {\n      if (totalWidth < viewport) {\n        totalWidth += col.drawnWidth;\n        min++;\n      }\n      else {\n        var currWidth = 0;\n        for (var j = i; j >= i - min; j--) {\n          currWidth += self.columns[j].drawnWidth;\n        }\n        if (currWidth < viewport) {\n          min++;\n        }\n      }\n    });\n\n    return min;\n  };\n\n  Grid.prototype.getBodyHeight = function getBodyHeight() {\n    // Start with the viewportHeight\n    var bodyHeight = this.getViewportHeight();\n\n    // Add the horizontal scrollbar height if there is one\n    //if (typeof(this.horizontalScrollbarHeight) !== 'undefined' && this.horizontalScrollbarHeight !== undefined && this.horizontalScrollbarHeight > 0) {\n    //  bodyHeight = bodyHeight + this.horizontalScrollbarHeight;\n    //}\n\n    return bodyHeight;\n  };\n\n  // NOTE: viewport drawable height is the height of the grid minus the header row height (including any border)\n  // TODO(c0bra): account for footer height\n  Grid.prototype.getViewportHeight = function getViewportHeight() {\n    var self = this;\n\n    var viewPortHeight = this.gridHeight - this.headerHeight - this.footerHeight;\n\n    // Account for native horizontal scrollbar, if present\n    //if (typeof(this.horizontalScrollbarHeight) !== 'undefined' && this.horizontalScrollbarHeight !== undefined && this.horizontalScrollbarHeight > 0) {\n    //  viewPortHeight = viewPortHeight - this.horizontalScrollbarHeight;\n    //}\n\n    var adjustment = self.getViewportAdjustment();\n    \n    viewPortHeight = viewPortHeight + adjustment.height;\n\n    //gridUtil.logDebug('viewPortHeight', viewPortHeight);\n\n    return viewPortHeight;\n  };\n\n  Grid.prototype.getViewportWidth = function getViewportWidth() {\n    var self = this;\n\n    var viewPortWidth = this.gridWidth;\n\n    //if (typeof(this.verticalScrollbarWidth) !== 'undefined' && this.verticalScrollbarWidth !== undefined && this.verticalScrollbarWidth > 0) {\n    //  viewPortWidth = viewPortWidth - this.verticalScrollbarWidth;\n    //}\n\n    var adjustment = self.getViewportAdjustment();\n    \n    viewPortWidth = viewPortWidth + adjustment.width;\n\n    //gridUtil.logDebug('getviewPortWidth', viewPortWidth);\n\n    return viewPortWidth;\n  };\n\n  Grid.prototype.getHeaderViewportWidth = function getHeaderViewportWidth() {\n    var viewPortWidth = this.getViewportWidth();\n\n    //if (typeof(this.verticalScrollbarWidth) !== 'undefined' && this.verticalScrollbarWidth !== undefined && this.verticalScrollbarWidth > 0) {\n    //  viewPortWidth = viewPortWidth + this.verticalScrollbarWidth;\n    //}\n\n    return viewPortWidth;\n  };\n\n  Grid.prototype.registerViewportAdjuster = function registerViewportAdjuster(func) {\n    this.viewportAdjusters.push(func);\n  };\n\n  Grid.prototype.removeViewportAdjuster = function registerViewportAdjuster(func) {\n    var idx = this.viewportAdjusters.indexOf(func);\n\n    if (typeof(idx) !== 'undefined' && idx !== undefined) {\n      this.viewportAdjusters.splice(idx, 1);\n    }\n  };\n\n  Grid.prototype.getViewportAdjustment = function getViewportAdjustment() {\n    var self = this;\n\n    var adjustment = { height: 0, width: 0 };\n\n    self.viewportAdjusters.forEach(function (func) {\n      adjustment = func.call(this, adjustment);\n    });\n\n    return adjustment;\n  };\n\n  Grid.prototype.getVisibleRowCount = function getVisibleRowCount() {\n    // var count = 0;\n\n    // this.rows.forEach(function (row) {\n    //   if (row.visible) {\n    //     count++;\n    //   }\n    // });\n\n    // return this.visibleRowCache.length;\n    return this.renderContainers.body.visibleRowCache.length;\n  };\n\n   Grid.prototype.getVisibleRows = function getVisibleRows() {\n    return this.renderContainers.body.visibleRowCache;\n   };\n\n  Grid.prototype.getVisibleColumnCount = function getVisibleColumnCount() {\n    // var count = 0;\n\n    // this.rows.forEach(function (row) {\n    //   if (row.visible) {\n    //     count++;\n    //   }\n    // });\n\n    // return this.visibleRowCache.length;\n    return this.renderContainers.body.visibleColumnCache.length;\n  };\n\n\n  Grid.prototype.searchRows = function searchRows(renderableRows) {\n    return rowSearcher.search(this, renderableRows, this.columns);\n  };\n\n  Grid.prototype.sortByColumn = function sortByColumn(renderableRows) {\n    return rowSorter.sort(this, renderableRows, this.columns);\n  };\n\n  /**\n   * @ngdoc function\n   * @name getCellValue\n   * @methodOf ui.grid.class:Grid\n   * @description Gets the value of a cell for a particular row and column\n   * @param {GridRow} row Row to access\n   * @param {GridColumn} col Column to access\n   */\n  Grid.prototype.getCellValue = function getCellValue(row, col){\n    var self = this;\n\n    if (!self.cellValueGetterCache[col.colDef.name]) {\n      self.cellValueGetterCache[col.colDef.name] = $parse(row.getEntityQualifiedColField(col));\n    }\n\n    return self.cellValueGetterCache[col.colDef.name](row);\n  };\n\n  \n  Grid.prototype.getNextColumnSortPriority = function getNextColumnSortPriority() {\n    var self = this,\n        p = 0;\n\n    self.columns.forEach(function (col) {\n      if (col.sort && col.sort.priority && col.sort.priority > p) {\n        p = col.sort.priority;\n      }\n    });\n\n    return p + 1;\n  };\n\n  /**\n   * @ngdoc function\n   * @name resetColumnSorting\n   * @methodOf ui.grid.class:Grid\n   * @description Return the columns that the grid is currently being sorted by\n   * @param {GridColumn} [excludedColumn] Optional GridColumn to exclude from having its sorting reset\n   */\n  Grid.prototype.resetColumnSorting = function resetColumnSorting(excludeCol) {\n    var self = this;\n\n    self.columns.forEach(function (col) {\n      if (col !== excludeCol && !col.colDef.suppressRemoveSort) {\n        col.sort = {};\n      }\n    });\n  };\n\n  /**\n   * @ngdoc function\n   * @name getColumnSorting\n   * @methodOf ui.grid.class:Grid\n   * @description Return the columns that the grid is currently being sorted by\n   * @returns {Array[GridColumn]} An array of GridColumn objects\n   */\n  Grid.prototype.getColumnSorting = function getColumnSorting() {\n    var self = this;\n\n    var sortedCols = [], myCols;\n\n    // Iterate through all the columns, sorted by priority\n    // Make local copy of column list, because sorting is in-place and we do not want to\n    // change the original sequence of columns\n    myCols = self.columns.slice(0);\n    myCols.sort(rowSorter.prioritySort).forEach(function (col) {\n      if (col.sort && typeof(col.sort.direction) !== 'undefined' && col.sort.direction && (col.sort.direction === uiGridConstants.ASC || col.sort.direction === uiGridConstants.DESC)) {\n        sortedCols.push(col);\n      }\n    });\n\n    return sortedCols;\n  };\n\n  /**\n   * @ngdoc function\n   * @name sortColumn\n   * @methodOf ui.grid.class:Grid\n   * @description Set the sorting on a given column, optionally resetting any existing sorting on the Grid.\n   * Emits the sortChanged event whenever the sort criteria are changed.\n   * @param {GridColumn} column Column to set the sorting on\n   * @param {uiGridConstants.ASC|uiGridConstants.DESC} [direction] Direction to sort by, either descending or ascending.\n   *   If not provided, the column will iterate through the sort directions: ascending, descending, unsorted.\n   * @param {boolean} [add] Add this column to the sorting. If not provided or set to `false`, the Grid will reset any existing sorting and sort\n   *   by this column only\n   * @returns {Promise} A resolved promise that supplies the column.\n   */\n  \n  Grid.prototype.sortColumn = function sortColumn(column, directionOrAdd, add) {\n    var self = this,\n        direction = null;\n\n    if (typeof(column) === 'undefined' || !column) {\n      throw new Error('No column parameter provided');\n    }\n\n    // Second argument can either be a direction or whether to add this column to the existing sort.\n    //   If it's a boolean, it's an add, otherwise, it's a direction\n    if (typeof(directionOrAdd) === 'boolean') {\n      add = directionOrAdd;\n    }\n    else {\n      direction = directionOrAdd;\n    }\n    \n    if (!add) {\n      self.resetColumnSorting(column);\n      column.sort.priority = 0;\n    }\n    else {\n      column.sort.priority = self.getNextColumnSortPriority();\n    }\n\n    if (!direction) {\n      // Figure out the sort direction\n      if (column.sort.direction && column.sort.direction === uiGridConstants.ASC) {\n        column.sort.direction = uiGridConstants.DESC;\n      }\n      else if (column.sort.direction && column.sort.direction === uiGridConstants.DESC) {\n        if ( column.colDef && column.colDef.suppressRemoveSort ){\n          column.sort.direction = uiGridConstants.ASC;\n        } else {\n          column.sort.direction = null;\n        }\n      }\n      else {\n        column.sort.direction = uiGridConstants.ASC;\n      }\n    }\n    else {\n      column.sort.direction = direction;\n    }\n    \n    self.api.core.raise.sortChanged( self, self.getColumnSorting() );\n\n    return $q.when(column);\n  };\n  \n  /**\n   * communicate to outside world that we are done with initial rendering\n   */\n  Grid.prototype.renderingComplete = function(){\n    if (angular.isFunction(this.options.onRegisterApi)) {\n      this.options.onRegisterApi(this.api);\n    }\n    this.api.core.raise.renderingComplete( this.api );\n  };\n\n  Grid.prototype.createRowHashMap = function createRowHashMap() {\n    var self = this;\n\n    var hashMap = new RowHashMap();\n    hashMap.grid = self;\n\n    self.rowHashMap = hashMap;\n  };\n  \n  \n  /**\n   * @ngdoc function\n   * @name refresh\n   * @methodOf ui.grid.class:Grid\n   * @description Refresh the rendered grid on screen.\n   * \n   */\n  Grid.prototype.refresh = function refresh() {\n    // gridUtil.logDebug('grid refresh');\n    \n    var self = this;\n    \n    var p1 = self.processRowsProcessors(self.rows).then(function (renderableRows) {\n      self.setVisibleRows(renderableRows);\n    });\n\n    var p2 = self.processColumnsProcessors(self.columns).then(function (renderableColumns) {\n      self.setVisibleColumns(renderableColumns);\n    });\n\n    return $q.all([p1, p2]).then(function () {\n      self.redrawInPlace();\n\n      self.refreshCanvas(true);\n    });\n  };  \n  \n  /**\n   * @ngdoc function\n   * @name refreshRows\n   * @methodOf ui.grid.class:Grid\n   * @description Refresh the rendered rows on screen?  Note: not functional at present \n   * @returns {promise} promise that is resolved when render completes?\n   * \n   */\n  Grid.prototype.refreshRows = function refreshRows() {\n    var self = this;\n    \n    return self.processRowsProcessors(self.rows)\n      .then(function (renderableRows) {\n        self.setVisibleRows(renderableRows);\n\n        self.redrawInPlace();\n\n        self.refreshCanvas( true );\n      });\n  };\n\n  /**\n   * @ngdoc function\n   * @name redrawCanvas\n   * @methodOf ui.grid.class:Grid\n   * @description TBD\n   * @params {object} buildStyles optional parameter.  Use TBD\n   * @returns {promise} promise that is resolved when the canvas\n   * has been refreshed\n   * \n   */\n  Grid.prototype.refreshCanvas = function(buildStyles) {\n    var self = this;\n\n    if (buildStyles) {\n      self.buildStyles();\n    }\n\n    var p = $q.defer();\n\n    // Get all the header heights\n    var containerHeadersToRecalc = [];\n    for (var containerId in self.renderContainers) {\n      if (self.renderContainers.hasOwnProperty(containerId)) {\n        var container = self.renderContainers[containerId];\n\n        // Skip containers that have no canvasWidth set yet\n        if (container.canvasWidth === null || isNaN(container.canvasWidth)) {\n          continue;\n        }\n\n        if (container.header) {\n          containerHeadersToRecalc.push(container);\n        }\n      }\n    }\n\n    if (containerHeadersToRecalc.length > 0) {\n      // Putting in a timeout as it's not calculating after the grid element is rendered and filled out\n      $timeout(function() {\n        // var oldHeaderHeight = self.grid.headerHeight;\n        // self.grid.headerHeight = gridUtil.outerElementHeight(self.header);\n\n        var rebuildStyles = false;\n\n        // Get all the header heights\n        var maxHeight = 0;\n        var i, container;\n        for (i = 0; i < containerHeadersToRecalc.length; i++) {\n          container = containerHeadersToRecalc[i];\n\n          // Skip containers that have no canvasWidth set yet\n          if (container.canvasWidth === null || isNaN(container.canvasWidth)) {\n            continue;\n          }\n\n          if (container.header) {\n            var oldHeaderHeight = container.headerHeight;\n            var headerHeight = gridUtil.outerElementHeight(container.header);\n\n            container.headerHeight = parseInt(headerHeight, 10);\n\n            if (oldHeaderHeight !== headerHeight) {\n              rebuildStyles = true;\n            }\n\n            // Get the \"inner\" header height, that is the height minus the top and bottom borders, if present. We'll use it to make sure all the headers have a consistent height\n            var topBorder = gridUtil.getBorderSize(container.header, 'top');\n            var bottomBorder = gridUtil.getBorderSize(container.header, 'bottom');\n            var innerHeaderHeight = parseInt(headerHeight - topBorder - bottomBorder, 10);\n\n            innerHeaderHeight  = innerHeaderHeight < 0 ? 0 : innerHeaderHeight;\n\n            container.innerHeaderHeight = innerHeaderHeight;\n\n            // Save the largest header height for use later\n            if (innerHeaderHeight > maxHeight) {\n              maxHeight = innerHeaderHeight;\n            }\n          }\n        }\n\n        // Go through all the headers\n        for (i = 0; i < containerHeadersToRecalc.length; i++) {\n          container = containerHeadersToRecalc[i];\n\n          // If this header's height is less than another header's height, then explicitly set it so they're the same and one isn't all offset and weird looking\n          if (container.headerHeight < maxHeight) {\n            container.explicitHeaderHeight = maxHeight;\n          }\n        }\n\n        // Rebuild styles if the header height has changed\n        //   The header height is used in body/viewport calculations and those are then used in other styles so we need it to be available\n        if (buildStyles && rebuildStyles) {\n          self.buildStyles();\n        }\n\n        p.resolve();\n      });\n    }\n    else {\n      // Timeout still needs to be here to trigger digest after styles have been rebuilt\n      $timeout(function() {\n        p.resolve();\n      });\n    }\n\n    return p.promise;\n  };\n\n\n  /**\n   * @ngdoc function\n   * @name redrawCanvas\n   * @methodOf ui.grid.class:Grid\n   * @description Redraw the rows and columns based on our current scroll position\n   * \n   */\n  Grid.prototype.redrawInPlace = function redrawInPlace() {\n    // gridUtil.logDebug('redrawInPlace');\n    \n    var self = this;\n\n    for (var i in self.renderContainers) {\n      var container = self.renderContainers[i];\n\n      // gridUtil.logDebug('redrawing container', i);\n\n      container.adjustRows(null, container.prevScrolltopPercentage, true);\n      container.adjustColumns(null, container.prevScrollleftPercentage);\n    }\n  };\n\n    /**\n     * @ngdoc function\n     * @name hasLeftContainerColumns\n     * @methodOf ui.grid.class:Grid\n     * @description returns true if leftContainer has columns\n     */\n    Grid.prototype.hasLeftContainerColumns = function () {\n      return this.hasLeftContainer() && this.renderContainers.left.renderedColumns.length > 0;\n    };\n\n    /**\n     * @ngdoc function\n     * @name hasRightContainerColumns\n     * @methodOf ui.grid.class:Grid\n     * @description returns true if rightContainer has columns\n     */\n    Grid.prototype.hasRightContainerColumns = function () {\n      return this.hasRightContainer() && this.renderContainers.right.renderedColumns.length > 0;\n    };\n\n\n\n\n  // Blatantly stolen from Angular as it isn't exposed (yet? 2.0?)\n  function RowHashMap() {}\n\n  RowHashMap.prototype = {\n    /**\n     * Store key value pair\n     * @param key key to store can be any type\n     * @param value value to store can be any type\n     */\n    put: function(key, value) {\n      this[this.grid.options.rowIdentity(key)] = value;\n    },\n\n    /**\n     * @param key\n     * @returns {Object} the value for the key\n     */\n    get: function(key) {\n      return this[this.grid.options.rowIdentity(key)];\n    },\n\n    /**\n     * Remove the key/value pair\n     * @param key\n     */\n    remove: function(key) {\n      var value = this[key = this.grid.options.rowIdentity(key)];\n      delete this[key];\n      return value;\n    }\n  };\n\n\n\n  return Grid;\n\n}]);\n\n})();\n\n(function () {\n\n  angular.module('ui.grid')\n    .factory('GridApi', ['$q', '$rootScope', 'gridUtil', 'uiGridConstants', 'GridRow', 'uiGridGridMenuService',\n      function ($q, $rootScope, gridUtil, uiGridConstants, GridRow, uiGridGridMenuService) {\n        /**\n         * @ngdoc function\n         * @name ui.grid.class:GridApi\n         * @description GridApi provides the ability to register public methods events inside the grid and allow\n         * for other components to use the api via featureName.raise.methodName and featureName.on.eventName(function(args){}.\n         * <br/>\n         * To listen to events, you must add a callback to gridOptions.onRegisterApi\n         * <pre>\n         *   $scope.gridOptions.onRegisterApi = function(gridApi){\n         *      gridApi.cellNav.on.navigate($scope,function(newRowCol, oldRowCol){\n         *          $log.log('navigation event');\n         *      });\n         *   };\n         * </pre>\n         * @param {object} grid grid that owns api\n         */\n        var GridApi = function GridApi(grid) {\n          this.grid = grid;\n          this.listeners = [];\n          \n          /**\n           * @ngdoc function\n           * @name renderingComplete\n           * @methodOf  ui.grid.core.api:PublicApi\n           * @description Rendering is complete, called at the same\n           * time as `onRegisterApi`, but provides a way to obtain\n           * that same event within features without stopping end\n           * users from getting at the onRegisterApi method.\n           * \n           * Included in gridApi so that it's always there - otherwise\n           * there is still a timing problem with when a feature can\n           * call this. \n           * \n           * @param {GridApi} gridApi the grid api, as normally \n           * returned in the onRegisterApi method\n           * \n           * @example\n           * <pre>\n           *      gridApi.core.on.renderingComplete( grid );\n           * </pre>\n           */\n          this.registerEvent( 'core', 'renderingComplete' );\n\n          /**\n           * @ngdoc event\n           * @name filterChanged\n           * @eventOf  ui.grid.core.api:PublicApi\n           * @description  is raised after the filter is changed.  The nature\n           * of the watch expression doesn't allow notification of what changed,\n           * so the receiver of this event will need to re-extract the filter \n           * conditions from the columns.\n           * \n           */\n          this.registerEvent( 'core', 'filterChanged' );\n\n          /**\n           * @ngdoc function\n           * @name setRowInvisible\n           * @methodOf  ui.grid.core.api:PublicApi\n           * @description Sets an override on the row to make it always invisible,\n           * which will override any filtering or other visibility calculations.  \n           * If the row is currently visible then sets it to invisible and calls\n           * both grid refresh and emits the rowsVisibleChanged event\n           * @param {object} rowEntity gridOptions.data[] array instance\n           */\n          this.registerMethod( 'core', 'setRowInvisible', GridRow.prototype.setRowInvisible );\n      \n          /**\n           * @ngdoc function\n           * @name clearRowInvisible\n           * @methodOf  ui.grid.core.api:PublicApi\n           * @description Clears any override on visibility for the row so that it returns to \n           * using normal filtering and other visibility calculations.  \n           * If the row is currently invisible then sets it to visible and calls\n           * both grid refresh and emits the rowsVisibleChanged event\n           * TODO: if a filter is active then we can't just set it to visible?\n           * @param {object} rowEntity gridOptions.data[] array instance\n           */\n          this.registerMethod( 'core', 'clearRowInvisible', GridRow.prototype.clearRowInvisible );\n      \n          /**\n           * @ngdoc function\n           * @name getVisibleRows\n           * @methodOf  ui.grid.core.api:PublicApi\n           * @description Returns all visible rows\n           * @param {Grid} grid the grid you want to get visible rows from\n           * @returns {array} an array of gridRow\n           */\n          this.registerMethod( 'core', 'getVisibleRows', this.grid.getVisibleRows );\n          \n          /**\n           * @ngdoc event\n           * @name rowsVisibleChanged\n           * @eventOf  ui.grid.core.api:PublicApi\n           * @description  is raised after the rows that are visible\n           * change.  The filtering is zero-based, so it isn't possible\n           * to say which rows changed (unlike in the selection feature).\n           * We can plausibly know which row was changed when setRowInvisible\n           * is called, but in that situation the user already knows which row\n           * they changed.  When a filter runs we don't know what changed,\n           * and that is the one that would have been useful.\n           *\n           */\n          this.registerEvent( 'core', 'rowsVisibleChanged' );\n\n          /**\n           * @ngdoc event\n           * @name rowsRendered\n           * @eventOf  ui.grid.core.api:PublicApi\n           * @description  is raised after the cache of visible rows is changed.\n           */\n          this.registerEvent( 'core', 'rowsRendered' );\n\n\n          /**\n           * @ngdoc event\n           * @name scrollEvent\n           * @eventOf  ui.grid.core.api:PublicApi\n           * @description  is raised on a scroll Event.  Called frequently so be careful what you do with it\n           */\n          this.registerEvent( 'core', 'scrollEvent' );\n\n          /**\n           * @ngdoc event\n           * @name canvasHeightChanged\n           * @eventOf  ui.grid.core.api:PublicApi\n           * @description  is raised when the canvas height has changed\n           * <br/>\n           * arguments: oldHeight, newHeight\n           */\n          this.registerEvent( 'core', 'canvasHeightChanged');\n        };\n\n        /**\n         * @ngdoc function\n         * @name ui.grid.class:suppressEvents\n         * @methodOf ui.grid.class:GridApi\n         * @description Used to execute a function while disabling the specified event listeners.\n         * Disables the listenerFunctions, executes the callbackFn, and then enables\n         * the listenerFunctions again\n         * @param {object} listenerFuncs listenerFunc or array of listenerFuncs to suppress. These must be the same\n         * functions that were used in the .on.eventName method\n         * @param {object} callBackFn function to execute\n         * @example\n         * <pre>\n         *    var navigate = function (newRowCol, oldRowCol){\n         *       //do something on navigate\n         *    }\n         *\n         *    gridApi.cellNav.on.navigate(scope,navigate);\n         *\n         *\n         *    //call the scrollTo event and suppress our navigate listener\n         *    //scrollTo will still raise the event for other listeners\n         *    gridApi.suppressEvents(navigate, function(){\n         *       gridApi.cellNav.scrollTo(aRow, aCol);\n         *    });\n         *\n         * </pre>\n         */\n        GridApi.prototype.suppressEvents = function (listenerFuncs, callBackFn) {\n          var self = this;\n          var listeners = angular.isArray(listenerFuncs) ? listenerFuncs : [listenerFuncs];\n\n          //find all registered listeners\n          var foundListeners = [];\n          listeners.forEach(function (l) {\n            foundListeners = self.listeners.filter(function (lstnr) {\n              return l === lstnr.handler;\n            });\n          });\n\n          //deregister all the listeners\n          foundListeners.forEach(function(l){\n            l.dereg();\n          });\n\n          callBackFn();\n\n          //reregister all the listeners\n          foundListeners.forEach(function(l){\n              l.dereg = registerEventWithAngular(l.eventId, l.handler, self.grid, l._this);\n          });\n\n        };\n\n        /**\n         * @ngdoc function\n         * @name registerEvent\n         * @methodOf ui.grid.class:GridApi\n         * @description Registers a new event for the given feature.  The event will get a\n         * .raise and .on prepended to it\n         * <br>\n         * .raise.eventName() - takes no arguments\n         * <br/>\n         * <br/>\n         * .on.eventName(scope, callBackFn, _this)\n         * <br/>\n         * scope - a scope reference to add a deregister call to the scopes .$on('destroy')\n         * <br/>\n         * callBackFn - The function to call\n         * <br/>\n         * _this - optional this context variable for callbackFn. If omitted, grid.api will be used for the context\n         * <br/>\n         * .on.eventName returns a dereg funtion that will remove the listener.  It's not necessary to use it as the listener\n         * will be removed when the scope is destroyed.\n         * @param {string} featureName name of the feature that raises the event\n         * @param {string} eventName  name of the event\n         */\n        GridApi.prototype.registerEvent = function (featureName, eventName) {\n          var self = this;\n          if (!self[featureName]) {\n            self[featureName] = {};\n          }\n\n          var feature = self[featureName];\n          if (!feature.on) {\n            feature.on = {};\n            feature.raise = {};\n          }\n\n          var eventId = self.grid.id + featureName + eventName;\n\n          // gridUtil.logDebug('Creating raise event method ' + featureName + '.raise.' + eventName);\n          feature.raise[eventName] = function () {\n            $rootScope.$emit.apply($rootScope, [eventId].concat(Array.prototype.slice.call(arguments)));\n          };\n\n          // gridUtil.logDebug('Creating on event method ' + featureName + '.on.' + eventName);\n          feature.on[eventName] = function (scope, handler, _this) {\n            var deregAngularOn = registerEventWithAngular(eventId, handler, self.grid, _this);\n\n            //track our listener so we can turn off and on\n            var listener = {handler: handler, dereg: deregAngularOn, eventId: eventId, scope: scope, _this:_this};\n            self.listeners.push(listener);\n\n            var removeListener = function(){\n              listener.dereg();\n              var index = self.listeners.indexOf(listener);\n              self.listeners.splice(index,1);\n            };\n\n            //destroy tracking when scope is destroyed\n            scope.$on('$destroy', function() {\n              removeListener();\n            });\n\n            return removeListener;\n          };\n        };\n\n        function registerEventWithAngular(eventId, handler, grid, _this) {\n          return $rootScope.$on(eventId, function (event) {\n            var args = Array.prototype.slice.call(arguments);\n            args.splice(0, 1); //remove evt argument\n            handler.apply(_this ? _this : grid.api, args);\n          });\n        }\n\n        /**\n         * @ngdoc function\n         * @name registerEventsFromObject\n         * @methodOf ui.grid.class:GridApi\n         * @description Registers features and events from a simple objectMap.\n         * eventObjectMap must be in this format (multiple features allowed)\n         * <pre>\n         * {featureName:\n         *        {\n         *          eventNameOne:function(args){},\n         *          eventNameTwo:function(args){}\n         *        }\n         *  }\n         * </pre>\n         * @param {object} eventObjectMap map of feature/event names\n         */\n        GridApi.prototype.registerEventsFromObject = function (eventObjectMap) {\n          var self = this;\n          var features = [];\n          angular.forEach(eventObjectMap, function (featProp, featPropName) {\n            var feature = {name: featPropName, events: []};\n            angular.forEach(featProp, function (prop, propName) {\n              feature.events.push(propName);\n            });\n            features.push(feature);\n          });\n\n          features.forEach(function (feature) {\n            feature.events.forEach(function (event) {\n              self.registerEvent(feature.name, event);\n            });\n          });\n\n        };\n\n        /**\n         * @ngdoc function\n         * @name registerMethod\n         * @methodOf ui.grid.class:GridApi\n         * @description Registers a new event for the given feature\n         * @param {string} featureName name of the feature\n         * @param {string} methodName  name of the method\n         * @param {object} callBackFn function to execute\n         * @param {object} _this binds callBackFn 'this' to _this.  Defaults to gridApi.grid\n         */\n        GridApi.prototype.registerMethod = function (featureName, methodName, callBackFn, _this) {\n          if (!this[featureName]) {\n            this[featureName] = {};\n          }\n\n          var feature = this[featureName];\n\n          feature[methodName] = gridUtil.createBoundedWrapper(_this || this.grid, callBackFn);\n        };\n\n        /**\n         * @ngdoc function\n         * @name registerMethodsFromObject\n         * @methodOf ui.grid.class:GridApi\n         * @description Registers features and methods from a simple objectMap.\n         * eventObjectMap must be in this format (multiple features allowed)\n         * <br>\n         * {featureName:\n         *        {\n         *          methodNameOne:function(args){},\n         *          methodNameTwo:function(args){}\n         *        }\n         * @param {object} eventObjectMap map of feature/event names\n         * @param {object} _this binds this to _this for all functions.  Defaults to gridApi.grid\n         */\n        GridApi.prototype.registerMethodsFromObject = function (methodMap, _this) {\n          var self = this;\n          var features = [];\n          angular.forEach(methodMap, function (featProp, featPropName) {\n            var feature = {name: featPropName, methods: []};\n            angular.forEach(featProp, function (prop, propName) {\n              feature.methods.push({name: propName, fn: prop});\n            });\n            features.push(feature);\n          });\n\n          features.forEach(function (feature) {\n            feature.methods.forEach(function (method) {\n              self.registerMethod(feature.name, method.name, method.fn, _this);\n            });\n          });\n\n        };\n        \n        return GridApi;\n\n      }]);\n\n})();\n\n(function(){\n\nangular.module('ui.grid')\n.factory('GridColumn', ['gridUtil', 'uiGridConstants', 'i18nService', function(gridUtil, uiGridConstants, i18nService) {\n\n  /**\n   * @ngdoc function\n   * @name ui.grid.class:GridColumn\n   * @description Represents the viewModel for each column.  Any state or methods needed for a Grid Column\n   * are defined on this prototype\n   * @param {ColDef} colDef Column definition.\n   * @param {number} index the current position of the column in the array\n   * @param {Grid} grid reference to the grid\n   */\n   \n  /**\n   * ******************************************************************************************\n   * PaulL1: Ugly hack here in documentation.  These properties are clearly properties of GridColumn, \n   * and need to be noted as such for those extending and building ui-grid itself.\n   * However, from an end-developer perspective, they interact with all these through columnDefs,\n   * and they really need to be documented there.  I feel like they're relatively static, and\n   * I can't find an elegant way for ngDoc to reference to both....so I've duplicated each\n   * comment block.  Ugh.\n   * \n   */\n\n  /** \n   * @ngdoc property\n   * @name name\n   * @propertyOf ui.grid.class:GridColumn\n   * @description (mandatory) each column should have a name, although for backward\n   * compatibility with 2.x name can be omitted if field is present\n   *\n   */\n\n  /** \n   * @ngdoc property\n   * @name name\n   * @propertyOf ui.grid.class:GridOptions.columnDef\n   * @description (mandatory) each column should have a name, although for backward\n   * compatibility with 2.x name can be omitted if field is present\n   *\n   */\n    \n  /** \n   * @ngdoc property\n   * @name displayName\n   * @propertyOf ui.grid.class:GridColumn\n   * @description Column name that will be shown in the header.  If displayName is not\n   * provided then one is generated using the name.\n   *\n   */\n\n  /** \n   * @ngdoc property\n   * @name displayName\n   * @propertyOf ui.grid.class:GridOptions.columnDef\n   * @description Column name that will be shown in the header.  If displayName is not\n   * provided then one is generated using the name.\n   *\n   */\n       \n  /** \n   * @ngdoc property\n   * @name field\n   * @propertyOf ui.grid.class:GridColumn\n   * @description field must be provided if you wish to bind to a \n   * property in the data source.  Should be an angular expression that evaluates against grid.options.data \n   * array element.  Can be a complex expression: <code>employee.address.city</code>, or can be a function: <code>employee.getFullAddress()</code>.\n   * See the angular docs on binding expressions.\n   *\n   */\n    \n  /** \n   * @ngdoc property\n   * @name field\n   * @propertyOf ui.grid.class:GridOptions.columnDef\n   * @description field must be provided if you wish to bind to a \n   * property in the data source.  Should be an angular expression that evaluates against grid.options.data \n   * array element.  Can be a complex expression: <code>employee.address.city</code>, or can be a function: <code>employee.getFullAddress()</code>.    * See the angular docs on binding expressions.    *\n   */\n    \n  /** \n   * @ngdoc property\n   * @name filter\n   * @propertyOf ui.grid.class:GridColumn\n   * @description Filter on this column.  \n   * @example\n   * <pre>{ term: 'text', condition: uiGridConstants.filter.STARTS_WITH, placeholder: 'type to filter...', flags: { caseSensitive: false } }</pre>\n   *\n   */\n    \n  /**\n   * @ngdoc method\n   * @methodOf ui.grid.class:GridColumn\n   * @name GridColumn\n   * @description Initializes a gridColumn\n   * @param {ColumnDef} colDef the column def to associate with this column\n   * @param {number} uid the unique and immutable uid we'd like to allocate to this column\n   * @param {Grid} grid the grid we'd like to create this column in\n   */ \n  function GridColumn(colDef, uid, grid) {\n    var self = this;\n\n    self.grid = grid;\n    self.uid = uid;\n\n    self.updateColumnDef(colDef, true);\n  }\n\n\n  /**\n   * @ngdoc method\n   * @methodOf ui.grid.class:GridColumn\n   * @name setPropertyOrDefault\n   * @description Sets a property on the column using the passed in columnDef, and\n   * setting the defaultValue if the value cannot be found on the colDef\n   * @param {ColumnDef} colDef the column def to look in for the property value\n   * @param {string} propName the property name we'd like to set\n   * @param {object} defaultValue the value to use if the colDef doesn't provide the setting\n   */ \n  GridColumn.prototype.setPropertyOrDefault = function (colDef, propName, defaultValue) {\n    var self = this;\n\n    // Use the column definition filter if we were passed it\n    if (typeof(colDef[propName]) !== 'undefined' && colDef[propName]) {\n      self[propName] = colDef[propName];\n    }\n    // Otherwise use our own if it's set\n    else if (typeof(self[propName]) !== 'undefined') {\n      self[propName] = self[propName];\n    }\n    // Default to empty object for the filter\n    else {\n      self[propName] = defaultValue ? defaultValue : {};\n    }\n  };\n\n  \n  \n  /** \n   * @ngdoc property\n   * @name width\n   * @propertyOf ui.grid.class:GridOptions.columnDef\n   * @description sets the column width.  Can be either \n   * a number or a percentage, or an * for auto.\n   * @example\n   * <pre>  $scope.gridOptions.columnDefs = [ { field: 'field1', width: 100},\n   *                                          { field: 'field2', width: '20%'},\n   *                                          { field: 'field3', width: '*' }]; </pre>\n   *\n   */\n\n  /** \n   * @ngdoc property\n   * @name minWidth\n   * @propertyOf ui.grid.class:GridOptions.columnDef\n   * @description sets the minimum column width.  Should be a number.\n   * @example\n   * <pre>  $scope.gridOptions.columnDefs = [ { field: 'field1', minWidth: 100}]; </pre>\n   *\n   */\n\n  /** \n   * @ngdoc property\n   * @name maxWidth\n   * @propertyOf ui.grid.class:GridOptions.columnDef\n   * @description sets the maximum column width.  Should be a number.\n   * @example\n   * <pre>  $scope.gridOptions.columnDefs = [ { field: 'field1', maxWidth: 100}]; </pre>\n   *\n   */\n\n  /** \n   * @ngdoc property\n   * @name visible\n   * @propertyOf ui.grid.class:GridOptions.columnDef\n   * @description sets whether or not the column is visible\n   * </br>Default is true\n   * @example\n   * <pre>  $scope.gridOptions.columnDefs = [ \n   *     { field: 'field1', visible: true},\n   *     { field: 'field2', visible: false }\n   *   ]; </pre>\n   *\n   */\n   \n  /**\n   * @ngdoc property\n   * @name sort\n   * @propertyOf ui.grid.class:GridOptions.columnDef\n   * @description Can be used to set the sort direction for the column, values are\n   * uiGridConstants.ASC or uiGridConstants.DESC\n   * @example\n   * <pre>  $scope.gridOptions.columnDefs = [ { field: 'field1', sort: { direction: uiGridConstants.ASC }}] </pre>\n   */\n  \n\n  /** \n   * @ngdoc property\n   * @name sortingAlgorithm\n   * @propertyOf ui.grid.class:GridColumn\n   * @description Algorithm to use for sorting this column. Takes 'a' and 'b' parameters \n   * like any normal sorting function.\n   *\n   */\n\n  /** \n   * @ngdoc property\n   * @name sortingAlgorithm\n   * @propertyOf ui.grid.class:GridOptions.columnDef\n   * @description Algorithm to use for sorting this column. Takes 'a' and 'b' parameters \n   * like any normal sorting function.\n   *\n   */\n      \n  /** \n   * @ngdoc array\n   * @name filters\n   * @propertyOf ui.grid.class:GridOptions.columnDef\n   * @description Specify multiple filter fields.\n   * @example\n   * <pre>$scope.gridOptions.columnDefs = [ \n   *   {\n   *     field: 'field1', filters: [\n   *       {\n   *         term: 'aa',\n   *         condition: uiGridConstants.filter.STARTS_WITH,\n   *         placeholder: 'starts with...',\n   *         flags: { caseSensitive: false }\n   *       },\n   *       {\n   *         condition: uiGridConstants.filter.ENDS_WITH,\n   *         placeholder: 'ends with...'\n   *       }\n   *     ]\n   *   }\n   * ]; </pre>\n   *\n   * \n   */ \n   \n  /** \n   * @ngdoc array\n   * @name filters\n   * @propertyOf ui.grid.class:GridColumn\n   * @description Filters for this column. Includes 'term' property bound to filter input elements.\n   * @example\n   * <pre>[\n   *   {\n   *     term: 'foo', // ngModel for <input>\n   *     condition: uiGridConstants.filter.STARTS_WITH,\n   *     placeholder: 'starts with...',\n   *     flags: { caseSensitive: false }\n   *   },\n   *   {\n   *     term: 'baz',\n   *     condition: uiGridConstants.filter.ENDS_WITH,\n   *     placeholder: 'ends with...'\n   *   }\n   * ] </pre>\n   *\n   * \n   */   \n\n  /** \n   * @ngdoc array\n   * @name menuItems\n   * @propertyOf ui.grid.class:GridOptions.columnDef\n   * @description used to add menu items to a column.  Refer to the tutorial on this \n   * functionality.  A number of settings are supported:\n   * \n   * - title: controls the title that is displayed in the menu\n   * - icon: the icon shown alongside that title\n   * - action: the method to call when the menu is clicked\n   * - shown: a function to evaluate to determine whether or not to show the item\n   * - active: a function to evaluate to determine whether or not the item is currently selected\n   * - context: context to pass to the action function??\n   * @example\n   * <pre>  $scope.gridOptions.columnDefs = [ \n   *   { field: 'field1', menuItems: [\n   *     {\n   *       title: 'Outer Scope Alert',\n   *       icon: 'ui-grid-icon-info-circled',\n   *       action: function($event) {\n   *         this.context.blargh(); // $scope.blargh() would work too, this is just an example\n   *       },\n   *       shown: function() { return true; },\n   *       active: function() { return true; },\n   *       context: $scope\n   *     },\n   *     {\n   *       title: 'Grid ID',\n   *       action: function() {\n   *         alert('Grid ID: ' + this.grid.id);\n   *       }\n   *     }\n   *   ] }]; </pre>\n   *\n   */   \n\n  /**\n   * @ngdoc method\n   * @methodOf ui.grid.class:GridColumn\n   * @name updateColumnDef\n   * @description Moves settings from the columnDef down onto the column,\n   * and sets properties as appropriate\n   * @param {ColumnDef} colDef the column def to look in for the property value\n   * @param {boolean} isNew whether the column is being newly created, if not\n   * we're updating an existing column, and some items such as the sort shouldn't\n   * be copied down\n   */ \n  GridColumn.prototype.updateColumnDef = function(colDef, isNew) {\n    var self = this;\n\n    self.colDef = colDef;\n\n    if (colDef.name === undefined) {\n      throw new Error('colDef.name is required for column at index ' + self.grid.options.columnDefs.indexOf(colDef));\n    }\n\n    self.displayName = (colDef.displayName === undefined) ? gridUtil.readableColumnName(colDef.name) : colDef.displayName;\n    \n    var parseErrorMsg = \"Cannot parse column width '\" + colDef.width + \"' for column named '\" + colDef.name + \"'\";\n\n    // If width is not defined, set it to a single star\n    if (gridUtil.isNullOrUndefined(self.width) || !angular.isNumber(self.width)) {\n      if (gridUtil.isNullOrUndefined(colDef.width)) {\n        self.width = '*';\n      }\n      else {\n        // If the width is not a number\n        if (!angular.isNumber(colDef.width)) {\n          // See if it ends with a percent\n          if (gridUtil.endsWith(colDef.width, '%')) {\n            // If so we should be able to parse the non-percent-sign part to a number\n            var percentStr = colDef.width.replace(/%/g, '');\n            var percent = parseInt(percentStr, 10);\n            if (isNaN(percent)) {\n              throw new Error(parseErrorMsg);\n            }\n            self.width = colDef.width;\n          }\n          // And see if it's a number string\n          else if (colDef.width.match(/^(\\d+)$/)) {\n            self.width = parseInt(colDef.width.match(/^(\\d+)$/)[1], 10);\n          }\n          // Otherwise it should be a string of asterisks\n          else if (colDef.width.match(/^\\*+$/)) {\n            self.width = colDef.width;\n          }\n          // No idea, throw an Error\n          else {\n            throw new Error(parseErrorMsg);\n          }\n        }\n        // Is a number, use it as the width\n        else {\n          self.width = colDef.width;\n        }\n      }\n    }\n\n    self.minWidth = !colDef.minWidth ? 30 : colDef.minWidth;\n    self.maxWidth = !colDef.maxWidth ? 9000 : colDef.maxWidth;\n\n    //use field if it is defined; name if it is not\n    self.field = (colDef.field === undefined) ? colDef.name : colDef.field;\n    \n    if ( typeof( self.field ) !== 'string' ){\n      gridUtil.logError( 'Field is not a string, this is likely to break the code, Field is: ' + self.field );\n    }\n    \n    self.name = colDef.name;\n\n    // Use colDef.displayName as long as it's not undefined, otherwise default to the field name\n    self.displayName = (colDef.displayName === undefined) ? gridUtil.readableColumnName(colDef.name) : colDef.displayName;\n\n    //self.originalIndex = index;\n\n    self.aggregationType = angular.isDefined(colDef.aggregationType) ? colDef.aggregationType : null;\n    self.footerCellTemplate = angular.isDefined(colDef.footerCellTemplate) ? colDef.footerCellTemplate : null;\n\n    /**\n     * @ngdoc property\n     * @name footerCellClass\n     * @propertyOf ui.grid.class:GridOptions.columnDef\n     * @description footerCellClass can be a string specifying the class to append to a cell\n     * or it can be a function(row,rowRenderIndex, col, colRenderIndex) that returns a class name\n     *\n     */\n    self.footerCellClass = colDef.footerCellClass;\n\n    /**\n     * @ngdoc property\n     * @name cellClass\n     * @propertyOf ui.grid.class:GridOptions.columnDef\n     * @description cellClass can be a string specifying the class to append to a cell\n     * or it can be a function(row,rowRenderIndex, col, colRenderIndex) that returns a class name\n     *\n     */\n    self.cellClass = colDef.cellClass;\n\n    /**\n     * @ngdoc property\n     * @name headerCellClass\n     * @propertyOf ui.grid.class:GridOptions.columnDef\n     * @description headerCellClass can be a string specifying the class to append to a cell\n     * or it can be a function(row,rowRenderIndex, col, colRenderIndex) that returns a class name\n     *\n     */\n    self.headerCellClass = colDef.headerCellClass;\n\n    /**\n     * @ngdoc property\n     * @name cellFilter\n     * @propertyOf ui.grid.class:GridOptions.columnDef\n     * @description cellFilter is a filter to apply to the content of each cell\n     * @example\n     * <pre>\n     *   gridOptions.columnDefs[0].cellFilter = 'date'\n     *\n     */\n    self.cellFilter = colDef.cellFilter ? colDef.cellFilter : \"\";\n\n    /**\n     * @ngdoc property\n     * @name headerCellFilter\n     * @propertyOf ui.grid.class:GridOptions.columnDef\n     * @description headerCellFilter is a filter to apply to the content of the column header\n     * @example\n     * <pre>\n     *   gridOptions.columnDefs[0].headerCellFilter = 'translate'\n     *\n     */\n    self.headerCellFilter = colDef.headerCellFilter ? colDef.headerCellFilter : \"\";\n\n    /**\n     * @ngdoc property\n     * @name footerCellFilter\n     * @propertyOf ui.grid.class:GridOptions.columnDef\n     * @description footerCellFilter is a filter to apply to the content of the column footer\n     * @example\n     * <pre>\n     *   gridOptions.columnDefs[0].footerCellFilter = 'date'\n     *\n     */\n    self.footerCellFilter = colDef.footerCellFilter ? colDef.footerCellFilter : \"\";\n\n    self.visible = gridUtil.isNullOrUndefined(colDef.visible) || colDef.visible;\n\n    self.headerClass = colDef.headerClass;\n    //self.cursor = self.sortable ? 'pointer' : 'default';\n\n    // Turn on sorting by default\n    self.enableSorting = typeof(colDef.enableSorting) !== 'undefined' ? colDef.enableSorting : true;\n    self.sortingAlgorithm = colDef.sortingAlgorithm;\n\n    /**\n     * @ngdoc property\n     * @name enableFiltering\n     * @propertyOf ui.grid.class:GridOptions.columnDef\n     * @description turn off filtering for an individual column, where\n     * you've turned on filtering for the overall grid\n     * @example\n     * <pre>\n     *   gridOptions.columnDefs[0].enableFiltering = false;\n     *\n     */\n    // Turn on filtering by default (it's disabled by default at the Grid level)\n    self.enableFiltering = typeof(colDef.enableFiltering) !== 'undefined' ? colDef.enableFiltering : true;\n\n    // self.menuItems = colDef.menuItems;\n    self.setPropertyOrDefault(colDef, 'menuItems', []);\n\n    // Use the column definition sort if we were passed it, but only if this is a newly added column\n    if ( isNew ){\n      self.setPropertyOrDefault(colDef, 'sort');\n    }\n\n    // Set up default filters array for when one is not provided.\n    //   In other words, this (in column def):\n    //   \n    //       filter: { term: 'something', flags: {}, condition: [CONDITION] }\n    //       \n    //   is just shorthand for this:\n    //   \n    //       filters: [{ term: 'something', flags: {}, condition: [CONDITION] }]\n    //       \n    var defaultFilters = [];\n    if (colDef.filter) {\n      defaultFilters.push(colDef.filter);\n    }\n    else if (self.enableFiltering && self.grid.options.enableFiltering) {\n      // Add an empty filter definition object, which will\n      // translate to a guessed condition and no pre-populated\n      // value for the filter <input>.\n      defaultFilters.push({});\n    }\n\n    /** \n     * @ngdoc property\n     * @name filter\n     * @propertyOf ui.grid.class:GridOptions.columnDef\n     * @description Specify a single filter field on this column.\n     * \n     * A filter consists of a condition, a term, and a placeholder:\n     * \n     * - condition defines how rows are chosen as matching the filter term. This can be set to\n     * one of the constants in uiGridConstants.filter, or you can supply a custom filter function\n     * that gets passed the following arguments: [searchTerm, cellValue, row, column].\n     * - term: If set, the filter field will be pre-populated\n     * with this value.\n     * - placeholder: String that will be set to the `<input>.placeholder` attribute.\n     * - noTerm: set this to true if you have defined a custom function in condition, and\n     * your custom function doesn't require a term (so it can run even when the term is null)\n     * - flags: only flag currently available is `caseSensitive`, set to false if you don't want\n     * case sensitive matching\n     * @example\n     * <pre>$scope.gridOptions.columnDefs = [ \n     *   {\n     *     field: 'field1',\n     *     filter: {\n     *       term: 'xx',\n     *       condition: uiGridConstants.filter.STARTS_WITH,\n     *       placeholder: 'starts with...',\n     *       flags: { caseSensitive: false }\n     *     }\n     *   }\n     * ]; </pre>\n     *\n     */\n  \n    /*\n\n      self.filters = [\n        {\n          term: 'search term'\n          condition: uiGridConstants.filter.CONTAINS,\n          placeholder: 'my placeholder',\n          flags: {\n            caseSensitive: true\n          }\n        }\n      ]\n\n    */\n\n    // Only set filter if this is a newly added column, if we're updating an existing\n    // column then we don't want to put the default filter back if the user may have already\n    // removed it.\n    if ( isNew ) {\n      self.setPropertyOrDefault(colDef, 'filter');\n      self.setPropertyOrDefault(colDef, 'filters', defaultFilters);\n    }\n\n    // Remove this column from the grid sorting, include inside build columns so has\n    // access to self - all seems a bit dodgy but doesn't work otherwise so have left\n    // as is\n    GridColumn.prototype.unsort = function () {\n      this.sort = {};\n      self.grid.api.core.raise.sortChanged( self, self.grid.getColumnSorting() );\n    };\n  \n  };\n\n\n  /**\n   * @ngdoc function\n   * @name getColClass\n   * @methodOf ui.grid.class:GridColumn\n   * @description Returns the class name for the column\n   * @param {bool} prefixDot  if true, will return .className instead of className\n   */\n  GridColumn.prototype.getColClass = function (prefixDot) {\n    var cls = uiGridConstants.COL_CLASS_PREFIX + this.uid;\n\n    return prefixDot ? '.' + cls : cls;\n  };\n\n  /**\n   * @ngdoc function\n   * @name getColClassDefinition\n   * @methodOf ui.grid.class:GridColumn\n   * @description Returns the class definition for th column\n   */\n  GridColumn.prototype.getColClassDefinition = function () {\n    return ' .grid' + this.grid.id + ' ' + this.getColClass(true) + ' { width: ' + this.drawnWidth + 'px; }';\n  };\n\n  /**\n   * @ngdoc function\n   * @name getRenderContainer\n   * @methodOf ui.grid.class:GridColumn\n   * @description Returns the render container object that this column belongs to.\n   *\n   * Columns will be default be in the `body` render container if they aren't allocated to one specifically.\n   */\n  GridColumn.prototype.getRenderContainer = function getRenderContainer() {\n    var self = this;\n\n    var containerId = self.renderContainer;\n\n    if (containerId === null || containerId === '' || containerId === undefined) {\n      containerId = 'body';\n    }\n\n    return self.grid.renderContainers[containerId];\n  };\n\n  /**\n   * @ngdoc function\n   * @name showColumn\n   * @methodOf ui.grid.class:GridColumn\n   * @description Makes the column visible by setting colDef.visible = true\n   */\n  GridColumn.prototype.showColumn = function() {\n      this.colDef.visible = true;\n  };\n\n  /**\n   * @ngdoc function\n   * @name hideColumn\n   * @methodOf ui.grid.class:GridColumn\n   * @description Hides the column by setting colDef.visible = false\n   */\n  GridColumn.prototype.hideColumn = function() {\n      this.colDef.visible = false;\n  };\n\n  /**\n   * @ngdoc function\n   * @name getAggregationValue\n   * @methodOf ui.grid.class:GridColumn\n   * @description gets the aggregation value based on the aggregation type for this column\n   */\n  GridColumn.prototype.getAggregationValue = function () {\n    var self = this;\n    var result = 0;\n    var visibleRows = self.grid.getVisibleRows();\n\n    var cellValues = function(){\n      var values = [];\n      angular.forEach(visibleRows, function (row) {\n        var cellValue = self.grid.getCellValue(row, self);\n        if (angular.isNumber(cellValue)) {\n          values.push(cellValue);\n        }\n      });\n      return values;\n    };\n\n    if (angular.isFunction(self.aggregationType)) {\n      return self.aggregationType(visibleRows, self);\n    }\n    else if (self.aggregationType === uiGridConstants.aggregationTypes.count) {\n      return self.grid.getVisibleRowCount();\n    }\n    else if (self.aggregationType === uiGridConstants.aggregationTypes.sum) {\n      angular.forEach(cellValues(), function (value) {\n        result += value;\n      });\n      return result;\n    }\n    else if (self.aggregationType === uiGridConstants.aggregationTypes.avg) {\n      angular.forEach(cellValues(), function (value) {\n        result += value;\n      });\n      result = result / cellValues().length;\n      return result;\n    }\n    else if (self.aggregationType === uiGridConstants.aggregationTypes.min) {\n      return Math.min.apply(null, cellValues());\n    }\n    else if (self.aggregationType === uiGridConstants.aggregationTypes.max) {\n      return Math.max.apply(null, cellValues());\n    }\n    else {\n      return '\\u00A0';\n    }\n  };\n    \n  /** \n   * @ngdoc property\n   * @name aggregationHideLabel\n   * @propertyOf ui.grid.class:GridOptions.columnDef\n   * @description defaults to false, if set to true hides the label text\n   * in the aggregation footer, so only the value is displayed.\n   *\n   */\n  /**\n   * @ngdoc function\n   * @name getAggregationText\n   * @methodOf ui.grid.class:GridColumn\n   * @description Gets the aggregation label from colDef.aggregationLabel if\n   * specified or by using i18n, including deciding whether or not to display\n   * based on colDef.aggregationHideLabel.\n   *\n   * @param {string} label the i18n lookup value to use for the column label\n   * \n   */\n  GridColumn.prototype.getAggregationText = function () {\n    var self = this;\n    if ( self.colDef.aggregationHideLabel ){\n      return '';\n    }\n    else if ( self.colDef.aggregationLabel ) {\n      return self.colDef.aggregationLabel;\n    }\n    else {\n      switch ( self.colDef.aggregationType ){\n        case uiGridConstants.aggregationTypes.count:\n          return i18nService.getSafeText('aggregation.count');\n        case uiGridConstants.aggregationTypes.sum:\n          return i18nService.getSafeText('aggregation.sum');\n        case uiGridConstants.aggregationTypes.avg:\n          return i18nService.getSafeText('aggregation.avg');\n        case uiGridConstants.aggregationTypes.min:\n          return i18nService.getSafeText('aggregation.min');\n        case uiGridConstants.aggregationTypes.max:\n          return i18nService.getSafeText('aggregation.max');\n        default:\n          return '';\n      }\n    }\n  };\n\n  GridColumn.prototype.getCellTemplate = function () {\n    var self = this;\n\n    return self.cellTemplatePromise;\n  };\n\n  GridColumn.prototype.getCompiledElementFn = function () {\n    var self = this;\n\n    return self.compiledElementFnDefer.promise;\n  };\n\n  return GridColumn;\n}]);\n\n})();\n\n  (function(){\n\nangular.module('ui.grid')\n.factory('GridOptions', ['gridUtil','uiGridConstants', function(gridUtil,uiGridConstants) {\n\n  /**\n   * @ngdoc function\n   * @name ui.grid.class:GridOptions\n   * @description Default GridOptions class.  GridOptions are defined by the application developer and overlaid\n   * over this object.  Setting gridOptions within your controller is the most common method for an application \n   * developer to configure the behaviour of their ui-grid\n   * \n   * @example To define your gridOptions within your controller:\n   * <pre>$scope.gridOptions = {\n   *   data: $scope.myData,\n   *   columnDefs: [ \n   *     { name: 'field1', displayName: 'pretty display name' },\n   *     { name: 'field2', visible: false }\n   *  ]\n   * };</pre>\n   * \n   * You can then use this within your html template, when you define your grid:\n   * <pre>&lt;div ui-grid=\"gridOptions\"&gt;&lt;/div&gt;</pre>\n   *\n   * To provide default options for all of the grids within your application, use an angular\n   * decorator to modify the GridOptions factory.\n   * <pre>\n   * app.config(function($provide){\n   *   $provide.decorator('GridOptions',function($delegate){\n   *     var gridOptions;\n   *     gridOptions = angular.copy($delegate);\n   *     gridOptions.initialize = function(options) {\n   *       var initOptions;\n   *       initOptions = $delegate.initialize(options);\n   *       initOptions.enableColumnMenus = false;\n   *       return initOptions;\n   *     };\n   *     return gridOptions;\n   *   });\n   * });\n   * </pre>\n   */\n  return {\n    initialize: function( baseOptions ){\n      /**\n       * @ngdoc function\n       * @name onRegisterApi\n       * @propertyOf ui.grid.class:GridOptions\n       * @description A callback that returns the gridApi once the grid is instantiated, which is \n       * then used to interact with the grid programatically.\n       * \n       * Note that the gridApi.core.renderingComplete event is identical to this \n       * callback, but has the advantage that it can be called from multiple places\n       * if needed\n       * \n       * @example\n       * <pre>\n       *   $scope.gridOptions.onRegisterApi = function ( gridApi ) {\n       *     $scope.gridApi = gridApi;\n       *     $scope.gridApi.selection.selectAllRows( $scope.gridApi.grid );\n       *   };\n       * </pre>\n       * \n       */\n      baseOptions.onRegisterApi = baseOptions.onRegisterApi || angular.noop();\n  \n      /**\n       * @ngdoc object\n       * @name data\n       * @propertyOf ui.grid.class:GridOptions\n       * @description (mandatory) Array of data to be rendered into the grid, providing the data source or data binding for \n       * the grid.  The most common case is an array of objects, where each object has a number of attributes.\n       * Each attribute automatically becomes a column in your grid.  This array could, for example, be sourced from\n       * an angularJS $resource query request.  The array can also contain complex objects.\n       * \n       */\n      baseOptions.data = baseOptions.data || [];\n  \n      /**\n       * @ngdoc array\n       * @name columnDefs\n       * @propertyOf  ui.grid.class:GridOptions\n       * @description Array of columnDef objects.  Only required property is name.\n       * The individual options available in columnDefs are documented in the\n       * {@link ui.grid.class:GridOptions.columnDef columnDef} section\n       * </br>_field property can be used in place of name for backwards compatibility with 2.x_\n       *  @example\n       *\n       * <pre>var columnDefs = [{name:'field1'}, {name:'field2'}];</pre>\n       *\n       */\n      baseOptions.columnDefs = baseOptions.columnDefs || [];\n  \n      /**\n       * @ngdoc object\n       * @name ui.grid.class:GridOptions.columnDef\n       * @description Definition / configuration of an individual column, which would typically be\n       * one of many column definitions within the gridOptions.columnDefs array\n       * @example\n       * <pre>{name:'field1', field: 'field1', filter: { term: 'xxx' }}</pre>\n       *\n       */\n  \n          \n      /**\n       * @ngdoc array\n       * @name excludeProperties\n       * @propertyOf  ui.grid.class:GridOptions\n       * @description Array of property names in data to ignore when auto-generating column names.  Provides the\n       * inverse of columnDefs - columnDefs is a list of columns to include, excludeProperties is a list of columns\n       * to exclude. \n       * \n       * If columnDefs is defined, this will be ignored.\n       * \n       * Defaults to ['$$hashKey']\n       */\n      \n      baseOptions.excludeProperties = baseOptions.excludeProperties || ['$$hashKey'];\n  \n      /**\n       * @ngdoc boolean\n       * @name enableRowHashing\n       * @propertyOf ui.grid.class:GridOptions\n       * @description True by default. When enabled, this setting allows uiGrid to add\n       * `$$hashKey`-type properties (similar to Angular) to elements in the `data` array. This allows\n       * the grid to maintain state while vastly speeding up the process of altering `data` by adding/moving/removing rows.\n       * \n       * Note that this DOES add properties to your data that you may not want, but they are stripped out when using `angular.toJson()`. IF\n       * you do not want this at all you can disable this setting but you will take a performance hit if you are using large numbers of rows\n       * and are altering the data set often.\n       */\n      baseOptions.enableRowHashing = baseOptions.enableRowHashing !== false;\n  \n      /**\n       * @ngdoc function\n       * @name rowIdentity\n       * @methodOf ui.grid.class:GridOptions\n       * @description This function is used to get and, if necessary, set the value uniquely identifying this row (i.e. if an identity is not present it will set one).\n       * \n       * By default it returns the `$$hashKey` property if it exists. If it doesn't it uses gridUtil.nextUid() to generate one\n       */\n      baseOptions.rowIdentity = baseOptions.rowIdentity || function rowIdentity(row) {\n        return gridUtil.hashKey(row);\n      };\n  \n      /**\n       * @ngdoc function\n       * @name getRowIdentity\n       * @methodOf ui.grid.class:GridOptions\n       * @description This function returns the identity value uniquely identifying this row, if one is not present it does not set it.\n       * \n       * By default it returns the `$$hashKey` property but can be overridden to use any property or set of properties you want.\n       */\n      baseOptions.getRowIdentity = baseOptions.getRowIdentity || function getRowIdentity(row) {\n        return row.$$hashKey;\n      };\n\n      /**\n       * @ngdoc property\n       * @name showHeader\n       * @propertyOf ui.grid.class:GridOptions\n       * @description True by default. When set to false, this setting will replace the\n       * standard header template with '<div></div>', resulting in no header being shown.\n       *\n       * It will also set the `headerRowHeight` option to 0.\n       */\n      baseOptions.showHeader = typeof(baseOptions.showHeader) !== \"undefined\" ? baseOptions.showHeader : true;\n\n      /**\n       * @ngdoc property\n       * @name headerRowHeight\n       * @propertyOf ui.grid.class:GridOptions\n       * @description The height of the header in pixels, defaults to 30\n       *\n       */\n      if (!baseOptions.showHeader) {\n        baseOptions.headerRowHeight = 0;\n      }\n      else {\n        baseOptions.headerRowHeight = typeof(baseOptions.headerRowHeight) !== \"undefined\" ? baseOptions.headerRowHeight : 30;\n      }\n\n      /**\n       * @ngdoc property\n       * @name rowHeight\n       * @propertyOf ui.grid.class:GridOptions\n       * @description The height of the row in pixels, defaults to 30\n       *\n       */\n      baseOptions.rowHeight = baseOptions.rowHeight || 30;\n  \n      /**\n       * @ngdoc integer\n       * @name minRowsToShow\n       * @propertyOf ui.grid.class:GridOptions\n       * @description Minimum number of rows to show when the grid doesn't have a defined height. Defaults to \"10\".\n       */\n      baseOptions.minRowsToShow = typeof(baseOptions.minRowsToShow) !== \"undefined\" ? baseOptions.minRowsToShow : 10;\n  \n      /**\n       * @ngdoc property\n       * @name showGridFooter\n       * @propertyOf ui.grid.class:GridOptions\n       * @description Whether or not to show the footer, defaults to false\n       * The footer display Total Rows and Visible Rows (filtered rows)\n       */\n      baseOptions.showGridFooter = baseOptions.showGridFooter === true;\n\n      /**\n       * @ngdoc property\n       * @name showColumnFooter\n       * @propertyOf ui.grid.class:GridOptions\n       * @description Whether or not to show the column footer, defaults to false\n       * The column footer displays column aggregates\n       */\n      baseOptions.showColumnFooter = baseOptions.showColumnFooter === true;\n\n      /**\n       * @ngdoc property\n       * @name columnFooterHeight\n       * @propertyOf ui.grid.class:GridOptions\n       * @description The height of the footer rows (column footer and grid footer) in pixels\n       *\n       */\n      baseOptions.columnFooterHeight = typeof(baseOptions.columnFooterHeight) !== \"undefined\" ? baseOptions.columnFooterHeight : 30;\n      baseOptions.gridFooterHeight = typeof(baseOptions.gridFooterHeight) !== \"undefined\" ? baseOptions.gridFooterHeight : 30;\n\n      baseOptions.columnWidth = typeof(baseOptions.columnWidth) !== \"undefined\" ? baseOptions.columnWidth : 50;\n\n      /**\n       * @ngdoc property\n       * @name maxVisibleColumnCount\n       * @propertyOf ui.grid.class:GridOptions\n       * @description Defaults to 200\n       *\n       */\n      baseOptions.maxVisibleColumnCount = typeof(baseOptions.maxVisibleColumnCount) !== \"undefined\" ? baseOptions.maxVisibleColumnCount : 200;\n  \n      /**\n       * @ngdoc property\n       * @name virtualizationThreshold\n       * @propertyOf ui.grid.class:GridOptions\n       * @description Turn virtualization on when number of data elements goes over this number, defaults to 20\n       */\n      baseOptions.virtualizationThreshold = typeof(baseOptions.virtualizationThreshold) !== \"undefined\" ? baseOptions.virtualizationThreshold : 20;\n  \n      /**\n       * @ngdoc property\n       * @name columnVirtualizationThreshold\n       * @propertyOf ui.grid.class:GridOptions\n       * @description Turn virtualization on when number of columns goes over this number, defaults to 10\n       */\n      baseOptions.columnVirtualizationThreshold = typeof(baseOptions.columnVirtualizationThreshold) !== \"undefined\" ? baseOptions.columnVirtualizationThreshold : 10;\n  \n      /**\n       * @ngdoc property\n       * @name excessRows\n       * @propertyOf ui.grid.class:GridOptions\n       * @description Extra rows to to render outside of the viewport, which helps with smoothness of scrolling.\n       * Defaults to 4\n       */\n      baseOptions.excessRows = typeof(baseOptions.excessRows) !== \"undefined\" ? baseOptions.excessRows : 4;\n      /**\n       * @ngdoc property\n       * @name scrollThreshold\n       * @propertyOf ui.grid.class:GridOptions\n       * @description Defaults to 4\n       */\n      baseOptions.scrollThreshold = typeof(baseOptions.scrollThreshold) !== \"undefined\" ? baseOptions.scrollThreshold : 4;\n  \n      /**\n       * @ngdoc property\n       * @name excessColumns\n       * @propertyOf ui.grid.class:GridOptions\n       * @description Extra columns to to render outside of the viewport, which helps with smoothness of scrolling.\n       * Defaults to 4\n       */\n      baseOptions.excessColumns = typeof(baseOptions.excessColumns) !== \"undefined\" ? baseOptions.excessColumns : 4;\n      /**\n       * @ngdoc property\n       * @name horizontalScrollThreshold\n       * @propertyOf ui.grid.class:GridOptions\n       * @description Defaults to 4\n       */\n      baseOptions.horizontalScrollThreshold = typeof(baseOptions.horizontalScrollThreshold) !== \"undefined\" ? baseOptions.horizontalScrollThreshold : 2;\n  \n      /**\n       * @ngdoc property\n       * @name scrollThrottle\n       * @propertyOf ui.grid.class:GridOptions\n       * @description Default time to throttle scroll events to, defaults to 70ms\n       */\n      baseOptions.scrollThrottle = typeof(baseOptions.scrollThrottle) !== \"undefined\" ? baseOptions.scrollThrottle : 70;\n  \n      /**\n       * @ngdoc boolean\n       * @name enableSorting\n       * @propertyOf ui.grid.class:GridOptions\n       * @description True by default. When enabled, this setting adds sort\n       * widgets to the column headers, allowing sorting of the data for the entire grid.\n       * Sorting can then be disabled on individual columns using the columnDefs.\n       */\n      baseOptions.enableSorting = baseOptions.enableSorting !== false;\n  \n      /**\n       * @ngdoc boolean\n       * @name enableFiltering\n       * @propertyOf ui.grid.class:GridOptions\n       * @description False by default. When enabled, this setting adds filter \n       * boxes to each column header, allowing filtering within the column for the entire grid.\n       * Filtering can then be disabled on individual columns using the columnDefs. \n       */\n      baseOptions.enableFiltering = baseOptions.enableFiltering === true;\n  \n      /**\n       * @ngdoc boolean\n       * @name enableColumnMenus\n       * @propertyOf ui.grid.class:GridOptions\n       * @description True by default. When enabled, this setting displays a column\n       * menu within each column.\n       */\n      baseOptions.enableColumnMenus = baseOptions.enableColumnMenus !== false;\n  \n      /**\n       * @ngdoc boolean\n       * @name enableVerticalScrollbar\n       * @propertyOf ui.grid.class:GridOptions\n       * @description uiGridConstants.scrollbars.ALWAYS by default. This settings controls the vertical scrollbar for the grid.\n       * Supported values: uiGridConstants.scrollbars.ALWAYS, uiGridConstants.scrollbars.NEVER\n       */\n      baseOptions.enableVerticalScrollbar = typeof(baseOptions.enableVerticalScrollbar) !== \"undefined\" ? baseOptions.enableVerticalScrollbar : uiGridConstants.scrollbars.ALWAYS;\n      \n      /**\n       * @ngdoc boolean\n       * @name enableHorizontalScrollbar\n       * @propertyOf ui.grid.class:GridOptions\n       * @description uiGridConstants.scrollbars.ALWAYS by default. This settings controls the horizontal scrollbar for the grid.\n       * Supported values: uiGridConstants.scrollbars.ALWAYS, uiGridConstants.scrollbars.NEVER\n       */\n      baseOptions.enableHorizontalScrollbar = typeof(baseOptions.enableHorizontalScrollbar) !== \"undefined\" ? baseOptions.enableHorizontalScrollbar : uiGridConstants.scrollbars.ALWAYS;\n  \n      /**\n       * @ngdoc boolean\n       * @name minimumColumnSize\n       * @propertyOf ui.grid.class:GridOptions\n       * @description Columns can't be smaller than this, defaults to 10 pixels\n       */\n      baseOptions.minimumColumnSize = typeof(baseOptions.minimumColumnSize) !== \"undefined\" ? baseOptions.minimumColumnSize : 10;\n  \n      /**\n       * @ngdoc function\n       * @name rowEquality\n       * @methodOf ui.grid.class:GridOptions\n       * @description By default, rows are compared using object equality.  This option can be overridden\n       * to compare on any data item property or function\n       * @param {object} entityA First Data Item to compare\n       * @param {object} entityB Second Data Item to compare\n       */\n      baseOptions.rowEquality = baseOptions.rowEquality || function(entityA, entityB) {\n        return entityA === entityB;\n      };\n  \n      /**\n       * @ngdoc string\n       * @name headerTemplate\n       * @propertyOf ui.grid.class:GridOptions\n       * @description Null by default. When provided, this setting uses a custom header\n       * template, rather than the default template. Can be set to either the name of a template file:\n       * <pre>  $scope.gridOptions.headerTemplate = 'header_template.html';</pre>\n       * inline html \n       * <pre>  $scope.gridOptions.headerTemplate = '<div class=\"ui-grid-top-panel\" style=\"text-align: center\">I am a Custom Grid Header</div>'</pre>\n       * or the id of a precompiled template (TBD how to use this).  \n       * </br>Refer to the custom header tutorial for more information.\n       * If you want no header at all, you can set to an empty div:\n       * <pre>  $scope.gridOptions.headerTemplate = '<div></div>';</pre>\n       * \n       * If you want to only have a static header, then you can set to static content.  If\n       * you want to tailor the existing column headers, then you should look at the\n       * current 'ui-grid-header.html' template in github as your starting point.\n       * \n       */\n      baseOptions.headerTemplate = baseOptions.headerTemplate || null;\n  \n      /**\n       * @ngdoc string\n       * @name footerTemplate\n       * @propertyOf ui.grid.class:GridOptions\n       * @description (optional) Null by default. When provided, this setting uses a custom footer\n       * template. Can be set to either the name of a template file 'footer_template.html', inline html\n       * <pre>'<div class=\"ui-grid-bottom-panel\" style=\"text-align: center\">I am a Custom Grid Footer</div>'</pre>, or the id\n       * of a precompiled template (TBD how to use this).  Refer to the custom footer tutorial for more information.\n       */\n      baseOptions.footerTemplate = baseOptions.footerTemplate || null;\n  \n      /**\n       * @ngdoc string\n       * @name rowTemplate\n       * @propertyOf ui.grid.class:GridOptions\n       * @description 'ui-grid/ui-grid-row' by default. When provided, this setting uses a \n       * custom row template.  Can be set to either the name of a template file:\n       * <pre> $scope.gridOptions.rowTemplate = 'row_template.html';</pre>\n       * inline html \n       * <pre>  $scope.gridOptions.rowTemplate = '<div style=\"background-color: aquamarine\" ng-click=\"grid.appScope.fnOne(row)\" ng-repeat=\"col in colContainer.renderedColumns track by col.colDef.name\" class=\"ui-grid-cell\" ui-grid-cell></div>';</pre>\n       * or the id of a precompiled template (TBD how to use this) can be provided.  \n       * </br>Refer to the custom row template tutorial for more information.\n       */\n      baseOptions.rowTemplate = baseOptions.rowTemplate || 'ui-grid/ui-grid-row';\n\n      /**\n       * @ngdoc object\n       * @name appScopeProvider\n       * @propertyOf ui.grid.class:GridOptions\n       * @description by default, the parent scope of the ui-grid element will be assigned to grid.appScope\n       * this property allows you to assign any reference you want to grid.appScope\n       */\n      baseOptions.appScopeProvider = baseOptions.appScopeProvider || null;\n      \n      return baseOptions;\n    }     \n  };\n\n\n}]);\n\n})();\n\n(function(){\n\nangular.module('ui.grid')\n  \n  /**\n   * @ngdoc function\n   * @name ui.grid.class:GridRenderContainer\n   * @description The grid has render containers, allowing the ability to have pinned columns.  If the grid\n   * is right-to-left then there may be a right render container, if left-to-right then there may \n   * be a left render container.  There is always a body render container.\n   * @param {string} name The name of the render container ('body', 'left', or 'right')\n   * @param {Grid} grid the grid the render container is in\n   * @param {object} options the render container options\n   */\n.factory('GridRenderContainer', ['gridUtil', 'uiGridConstants', function(gridUtil, uiGridConstants) {\n  function GridRenderContainer(name, grid, options) {\n    var self = this;\n\n    // if (gridUtil.type(grid) !== 'Grid') {\n    //   throw new Error('Grid argument is not a Grid object');\n    // }\n\n    self.name = name;\n\n    self.grid = grid;\n    \n    // self.rowCache = [];\n    // self.columnCache = [];\n\n    self.visibleRowCache = [];\n    self.visibleColumnCache = [];\n\n    self.renderedRows = [];\n    self.renderedColumns = [];\n\n    self.prevScrollTop = 0;\n    self.prevScrolltopPercentage = 0;\n    self.prevRowScrollIndex = 0;\n\n    self.prevScrollLeft = 0;\n    self.prevScrollleftPercentage = 0;\n    self.prevColumnScrollIndex = 0;\n\n    self.columnStyles = \"\";\n\n    self.viewportAdjusters = [];\n\n    /**\n     *  @ngdoc boolean\n     *  @name canvasHeightShouldUpdate\n     *  @propertyOf  ui.grid.class:GridRenderContainer\n     *  @description flag to signal that container should recalculate the canvas size\n     */\n    self.canvasHeightShouldUpdate = true;\n\n    /**\n     *  @ngdoc boolean\n     *  @name canvasHeight\n     *  @propertyOf  ui.grid.class:GridRenderContainer\n     *  @description last calculated canvas height value\n     */\n    self.$$canvasHeight = 0;\n\n    if (options && angular.isObject(options)) {\n      angular.extend(self, options);\n    }\n\n    grid.registerStyleComputation({\n      priority: 5,\n      func: function () {\n        return self.columnStyles;\n      }\n    });\n  }\n\n  // GridRenderContainer.prototype.addRenderable = function addRenderable(renderable) {\n  //   this.renderables.push(renderable);\n  // };\n\n  GridRenderContainer.prototype.reset = function reset() {\n    // this.rowCache.length = 0;\n    // this.columnCache.length = 0;\n\n    this.visibleColumnCache.length = 0;\n    this.visibleRowCache.length = 0;\n\n    this.renderedRows.length = 0;\n    this.renderedColumns.length = 0;\n  };\n\n  // TODO(c0bra): calculate size?? Should this be in a stackable directive?\n\n  GridRenderContainer.prototype.minRowsToRender = function minRowsToRender() {\n    var self = this;\n    var minRows = 0;\n    var rowAddedHeight = 0;\n    var viewPortHeight = self.getViewportHeight();\n    for (var i = self.visibleRowCache.length - 1; rowAddedHeight < viewPortHeight && i >= 0; i--) {\n      rowAddedHeight += self.visibleRowCache[i].height;\n      minRows++;\n    }\n    return minRows;\n  };\n\n  GridRenderContainer.prototype.minColumnsToRender = function minColumnsToRender() {\n    var self = this;\n    var viewportWidth = this.getViewportWidth();\n\n    var min = 0;\n    var totalWidth = 0;\n    // self.columns.forEach(function(col, i) {\n    for (var i = 0; i < self.visibleColumnCache.length; i++) {\n      var col = self.visibleColumnCache[i];\n\n      if (totalWidth < viewportWidth) {\n        totalWidth += col.drawnWidth ? col.drawnWidth : 0;\n        min++;\n      }\n      else {\n        var currWidth = 0;\n        for (var j = i; j >= i - min; j--) {\n          currWidth += self.visibleColumnCache[j].drawnWidth ? self.visibleColumnCache[j].drawnWidth : 0;\n        }\n        if (currWidth < viewportWidth) {\n          min++;\n        }\n      }\n    }\n\n    return min;\n  };\n\n  GridRenderContainer.prototype.getVisibleRowCount = function getVisibleRowCount() {\n    return this.visibleRowCache.length;\n  };\n\n  /**\n   * @ngdoc function\n   * @name registerViewportAdjuster\n   * @methodOf ui.grid.class:GridRenderContainer\n   * @description Registers an adjuster to the render container's available width or height.  Adjusters are used\n   * to tell the render container that there is something else consuming space, and to adjust it's size\n   * appropriately.  \n   * @param {function} func the adjuster function we want to register\n   */\n\n  GridRenderContainer.prototype.registerViewportAdjuster = function registerViewportAdjuster(func) {\n    this.viewportAdjusters.push(func);\n  };\n\n  /**\n   * @ngdoc function\n   * @name removeViewportAdjuster\n   * @methodOf ui.grid.class:GridRenderContainer\n   * @description Removes an adjuster, should be used when your element is destroyed\n   * @param {function} func the adjuster function we want to remove\n   */\n  GridRenderContainer.prototype.removeViewportAdjuster = function registerViewportAdjuster(func) {\n    var idx = this.viewportAdjusters.indexOf(func);\n\n    if (typeof(idx) !== 'undefined' && idx !== undefined) {\n      this.viewportAdjusters.splice(idx, 1);\n    }\n  };\n\n  /**\n   * @ngdoc function\n   * @name getViewportAdjustment\n   * @methodOf ui.grid.class:GridRenderContainer\n   * @description Gets the adjustment based on the viewportAdjusters.  \n   * @returns {object} a hash of { height: x, width: y }.  Usually the values will be negative\n   */\n  GridRenderContainer.prototype.getViewportAdjustment = function getViewportAdjustment() {\n    var self = this;\n\n    var adjustment = { height: 0, width: 0 };\n\n    self.viewportAdjusters.forEach(function (func) {\n      adjustment = func.call(this, adjustment);\n    });\n\n    return adjustment;\n  };\n\n  GridRenderContainer.prototype.getViewportHeight = function getViewportHeight() {\n    var self = this;\n\n    var headerHeight = (self.headerHeight) ? self.headerHeight : self.grid.headerHeight;\n\n    var viewPortHeight = self.grid.gridHeight - headerHeight - self.grid.footerHeight;\n\n\n    var adjustment = self.getViewportAdjustment();\n    \n    viewPortHeight = viewPortHeight + adjustment.height;\n\n    return viewPortHeight;\n  };\n\n  GridRenderContainer.prototype.getViewportWidth = function getViewportWidth() {\n    var self = this;\n\n    var viewPortWidth = self.grid.gridWidth;\n\n    //if (typeof(self.grid.verticalScrollbarWidth) !== 'undefined' && self.grid.verticalScrollbarWidth !== undefined && self.grid.verticalScrollbarWidth > 0) {\n    //  viewPortWidth = viewPortWidth - self.grid.verticalScrollbarWidth;\n    //}\n\n    var adjustment = self.getViewportAdjustment();\n    \n    viewPortWidth = viewPortWidth + adjustment.width;\n\n    return viewPortWidth;\n  };\n\n  GridRenderContainer.prototype.getHeaderViewportWidth = function getHeaderViewportWidth() {\n    var self = this;\n\n    var viewPortWidth = this.getViewportWidth();\n\n    //if (typeof(self.grid.verticalScrollbarWidth) !== 'undefined' && self.grid.verticalScrollbarWidth !== undefined && self.grid.verticalScrollbarWidth > 0) {\n    //  viewPortWidth = viewPortWidth + self.grid.verticalScrollbarWidth;\n    //}\n\n    // var adjustment = self.getViewportAdjustment();\n    // viewPortWidth = viewPortWidth + adjustment.width;\n\n    return viewPortWidth;\n  };\n\n\n  /**\n   * @ngdoc function\n   * @name getCanvasHeight\n   * @methodOf ui.grid.class:GridRenderContainer\n   * @description Returns the total canvas height.   Only recalculates if canvasHeightShouldUpdate = false\n   * @returns {number} total height of all the visible rows in the container\n   */\n  GridRenderContainer.prototype.getCanvasHeight = function getCanvasHeight() {\n    var self = this;\n\n    if (!self.canvasHeightShouldUpdate) {\n      return self.$$canvasHeight;\n    }\n\n    var oldCanvasHeight = self.$$canvasHeight;\n\n    self.$$canvasHeight =  0;\n\n    self.visibleRowCache.forEach(function(row){\n      self.$$canvasHeight += row.height;\n    });\n\n\n    self.canvasHeightShouldUpdate = false;\n\n    self.grid.api.core.raise.canvasHeightChanged(oldCanvasHeight, self.$$canvasHeight);\n\n    return self.$$canvasHeight;\n  };\n\n  GridRenderContainer.prototype.getVerticalScrollLength = function getVerticalScrollLength() {\n    return this.getCanvasHeight() - this.getViewportHeight();\n  };\n\n  GridRenderContainer.prototype.getCanvasWidth = function getCanvasWidth() {\n    var self = this;\n\n    var ret = self.canvasWidth;\n\n    //if (typeof(self.verticalScrollbarWidth) !== 'undefined' && self.verticalScrollbarWidth !== undefined && self.verticalScrollbarWidth > 0) {\n    //  ret = ret - self.verticalScrollbarWidth;\n    //}\n\n    return ret;\n  };\n\n  GridRenderContainer.prototype.setRenderedRows = function setRenderedRows(newRows) {\n    this.renderedRows.length = newRows.length;\n    for (var i = 0; i < newRows.length; i++) {\n      this.renderedRows[i] = newRows[i];\n    }\n  };\n\n  GridRenderContainer.prototype.setRenderedColumns = function setRenderedColumns(newColumns) {\n    var self = this;\n\n    // OLD:\n    this.renderedColumns.length = newColumns.length;\n    for (var i = 0; i < newColumns.length; i++) {\n      this.renderedColumns[i] = newColumns[i];\n    }\n    \n    this.updateColumnOffset();\n  };\n\n  GridRenderContainer.prototype.updateColumnOffset = function updateColumnOffset() {\n    // Calculate the width of the columns on the left side that are no longer rendered.\n    //  That will be the offset for the columns as we scroll horizontally.\n    var hiddenColumnsWidth = 0;\n    for (var i = 0; i < this.currentFirstColumn; i++) {\n      hiddenColumnsWidth += this.visibleColumnCache[i].drawnWidth;\n    }\n\n    this.columnOffset = hiddenColumnsWidth;\n  };\n\n  GridRenderContainer.prototype.adjustScrollVertical = function adjustScrollVertical(scrollTop, scrollPercentage, force) {\n    if (this.prevScrollTop === scrollTop && !force) {\n      return;\n    }\n\n    if (typeof(scrollTop) === 'undefined' || scrollTop === undefined || scrollTop === null) {\n      scrollTop = (this.getCanvasHeight() - this.getCanvasWidth()) * scrollPercentage;\n    }\n\n    this.adjustRows(scrollTop, scrollPercentage, false);\n\n    this.prevScrollTop = scrollTop;\n    this.prevScrolltopPercentage = scrollPercentage;\n\n    this.grid.queueRefresh();\n  };\n\n  GridRenderContainer.prototype.adjustScrollHorizontal = function adjustScrollHorizontal(scrollLeft, scrollPercentage, force) {\n    if (this.prevScrollLeft === scrollLeft && !force) {\n      return;\n    }\n\n    if (typeof(scrollLeft) === 'undefined' || scrollLeft === undefined || scrollLeft === null) {\n      scrollLeft = (this.getCanvasWidth() - this.getViewportWidth()) * scrollPercentage;\n    }\n\n    this.adjustColumns(scrollLeft, scrollPercentage);\n\n    this.prevScrollLeft = scrollLeft;\n    this.prevScrollleftPercentage = scrollPercentage;\n\n    this.grid.queueRefresh();\n  };\n\n  GridRenderContainer.prototype.adjustRows = function adjustRows(scrollTop, scrollPercentage, postDataLoaded) {\n    var self = this;\n\n    var minRows = self.minRowsToRender();\n\n    var rowCache = self.visibleRowCache;\n\n    var maxRowIndex = rowCache.length - minRows;\n\n    // Calculate the scroll percentage according to the scrollTop location, if no percentage was provided\n    if ((typeof(scrollPercentage) === 'undefined' || scrollPercentage === null) && scrollTop) {\n      scrollPercentage = scrollTop / self.getVerticalScrollLength();\n    }\n    \n    var rowIndex = Math.ceil(Math.min(maxRowIndex, maxRowIndex * scrollPercentage));\n\n    // Define a max row index that we can't scroll past\n    if (rowIndex > maxRowIndex) {\n      rowIndex = maxRowIndex;\n    }\n\n    var newRange = [];\n    if (rowCache.length > self.grid.options.virtualizationThreshold) {\n      if (!(typeof(scrollTop) === 'undefined' || scrollTop === null)) {\n        // Have we hit the threshold going down?\n        if (!self.grid.options.enableInfiniteScroll && self.prevScrollTop < scrollTop && rowIndex < self.prevRowScrollIndex + self.grid.options.scrollThreshold && rowIndex < maxRowIndex) {\n          return;\n        }\n        //Have we hit the threshold going up?\n        if (!self.grid.options.enableInfiniteScroll && self.prevScrollTop > scrollTop && rowIndex > self.prevRowScrollIndex - self.grid.options.scrollThreshold && rowIndex < maxRowIndex) {\n          return;\n        }\n      }\n      var rangeStart = {};\n      var rangeEnd = {};\n\n      //If infinite scroll is enabled, and we loaded more data coming from redrawInPlace, then recalculate the range and set rowIndex to proper place to scroll to\n      if ( self.grid.options.enableInfiniteScroll && self.grid.scrollDirection !== uiGridConstants.scrollDirection.NONE && postDataLoaded ) {\n        var findIndex = null;\n        var i = null;\n        if ( self.grid.scrollDirection === uiGridConstants.scrollDirection.UP ) {\n          findIndex = rowIndex > 0 ? self.grid.options.excessRows : 0;\n          for ( i = 0; i < rowCache.length; i++) {\n            if (rowCache[i].entity.$$hashKey === self.renderedRows[findIndex].entity.$$hashKey) {\n              rowIndex = i;\n              break;\n            }\n          }\n          rangeStart = Math.max(0, rowIndex);\n          rangeEnd = Math.min(rowCache.length, rangeStart + self.grid.options.excessRows + minRows);\n        }\n        else if ( self.grid.scrollDirection === uiGridConstants.scrollDirection.DOWN ) {\n          findIndex = minRows;\n          for ( i = 0; i < rowCache.length; i++) {\n            if (rowCache[i].entity.$$hashKey === self.renderedRows[findIndex].entity.$$hashKey) {\n              rowIndex = i;\n              break;\n            }\n          }\n          rangeStart = Math.max(0, rowIndex - self.grid.options.excessRows - minRows);\n          rangeEnd = Math.min(rowCache.length, rowIndex + minRows + self.grid.options.excessRows);\n        }\n      }\n      else {\n        rangeStart = Math.max(0, rowIndex - self.grid.options.excessRows);\n        rangeEnd = Math.min(rowCache.length, rowIndex + minRows + self.grid.options.excessRows);\n      }\n\n      newRange = [rangeStart, rangeEnd];\n    }\n    else {\n      var maxLen = self.visibleRowCache.length;\n      newRange = [0, Math.max(maxLen, minRows + self.grid.options.excessRows)];\n    }\n\n    self.updateViewableRowRange(newRange);\n\n    self.prevRowScrollIndex = rowIndex;\n  };\n\n  GridRenderContainer.prototype.adjustColumns = function adjustColumns(scrollLeft, scrollPercentage) {\n    var self = this;\n\n    var minCols = self.minColumnsToRender();\n\n    var columnCache = self.visibleColumnCache;\n    var maxColumnIndex = columnCache.length - minCols;\n\n    // Calculate the scroll percentage according to the scrollTop location, if no percentage was provided\n    if ((typeof(scrollPercentage) === 'undefined' || scrollPercentage === null) && scrollLeft) {\n      scrollPercentage = scrollLeft / self.getCanvasWidth();\n    }\n\n    var colIndex = Math.ceil(Math.min(maxColumnIndex, maxColumnIndex * scrollPercentage));\n\n    // Define a max row index that we can't scroll past\n    if (colIndex > maxColumnIndex) {\n      colIndex = maxColumnIndex;\n    }\n    \n    var newRange = [];\n    if (columnCache.length > self.grid.options.columnVirtualizationThreshold && self.getCanvasWidth() > self.getViewportWidth()) {\n      /* Commented the following lines because otherwise the moved column wasn't visible immediately on the new position\n       * in the case of many columns with horizontal scroll, one had to scroll left or right and then return in order to see it\n      // Have we hit the threshold going down?\n      if (self.prevScrollLeft < scrollLeft && colIndex < self.prevColumnScrollIndex + self.grid.options.horizontalScrollThreshold && colIndex < maxColumnIndex) {\n        return;\n      }\n      //Have we hit the threshold going up?\n      if (self.prevScrollLeft > scrollLeft && colIndex > self.prevColumnScrollIndex - self.grid.options.horizontalScrollThreshold && colIndex < maxColumnIndex) {\n        return;\n      }*/\n\n      var rangeStart = Math.max(0, colIndex - self.grid.options.excessColumns);\n      var rangeEnd = Math.min(columnCache.length, colIndex + minCols + self.grid.options.excessColumns);\n\n      newRange = [rangeStart, rangeEnd];\n    }\n    else {\n      var maxLen = self.visibleColumnCache.length;\n\n      newRange = [0, Math.max(maxLen, minCols + self.grid.options.excessColumns)];\n    }\n    \n    self.updateViewableColumnRange(newRange);\n\n    self.prevColumnScrollIndex = colIndex;\n  };\n\n  // Method for updating the visible rows\n  GridRenderContainer.prototype.updateViewableRowRange = function updateViewableRowRange(renderedRange) {\n    // Slice out the range of rows from the data\n    // var rowArr = uiGridCtrl.grid.rows.slice(renderedRange[0], renderedRange[1]);\n    var rowArr = this.visibleRowCache.slice(renderedRange[0], renderedRange[1]);\n\n    // Define the top-most rendered row\n    this.currentTopRow = renderedRange[0];\n\n    // TODO(c0bra): make this method!\n    this.setRenderedRows(rowArr);\n  };\n\n  // Method for updating the visible columns\n  GridRenderContainer.prototype.updateViewableColumnRange = function updateViewableColumnRange(renderedRange) {\n    // Slice out the range of rows from the data\n    // var columnArr = uiGridCtrl.grid.columns.slice(renderedRange[0], renderedRange[1]);\n    var columnArr = this.visibleColumnCache.slice(renderedRange[0], renderedRange[1]);\n\n    // Define the left-most rendered columns\n    this.currentFirstColumn = renderedRange[0];\n\n    this.setRenderedColumns(columnArr);\n  };\n\n  GridRenderContainer.prototype.rowStyle = function (index) {\n    var self = this;\n\n    var styles = {};\n    \n    if (index === 0 && self.currentTopRow !== 0) {\n      // The row offset-top is just the height of the rows above the current top-most row, which are no longer rendered\n      var hiddenRowWidth = (self.currentTopRow) * self.grid.options.rowHeight;\n\n      // return { 'margin-top': hiddenRowWidth + 'px' };\n      styles['margin-top'] = hiddenRowWidth + 'px';\n    }\n\n    if (self.currentFirstColumn !== 0) {\n      if (self.grid.isRTL()) {\n        styles['margin-right'] = self.columnOffset + 'px';\n      }\n      else {\n        styles['margin-left'] = self.columnOffset + 'px';\n      }\n    }\n\n    return styles;\n  };\n\n  GridRenderContainer.prototype.columnStyle = function (index) {\n    var self = this;\n    \n    if (index === 0 && self.currentFirstColumn !== 0) {\n      var offset = self.columnOffset;\n\n      if (self.grid.isRTL()) {\n        return { 'margin-right': offset + 'px' };\n      }\n      else {\n        return { 'margin-left': offset + 'px' };\n      }\n    }\n\n    return null;\n  };\n\n  GridRenderContainer.prototype.updateColumnWidths = function () {\n    var self = this;\n\n    var asterisksArray = [],\n        percentArray = [],\n        manualArray = [],\n        asteriskNum = 0,\n        totalWidth = 0;\n\n    // Get the width of the viewport\n    var availableWidth = self.getViewportWidth();\n\n    //if (typeof(self.grid.verticalScrollbarWidth) !== 'undefined' && self.grid.verticalScrollbarWidth !== undefined && self.grid.verticalScrollbarWidth > 0) {\n    //  availableWidth = availableWidth + self.grid.verticalScrollbarWidth;\n    //}\n\n    // The total number of columns\n    // var equalWidthColumnCount = columnCount = uiGridCtrl.grid.options.columnDefs.length;\n    // var equalWidth = availableWidth / equalWidthColumnCount;\n\n    // The last column we processed\n    var lastColumn;\n\n    var manualWidthSum = 0;\n\n    var canvasWidth = 0;\n\n    var ret = '';\n\n\n    // uiGridCtrl.grid.columns.forEach(function(column, i) {\n\n    var columnCache = self.visibleColumnCache;\n\n    columnCache.forEach(function(column, i) {\n      // ret = ret + ' .grid' + uiGridCtrl.grid.id + ' .col' + i + ' { width: ' + equalWidth + 'px; left: ' + left + 'px; }';\n      //var colWidth = (typeof(c.width) !== 'undefined' && c.width !== undefined) ? c.width : equalWidth;\n\n      // Skip hidden columns\n      if (!column.visible) { return; }\n\n      var colWidth,\n          isPercent = false;\n\n      if (!angular.isNumber(column.width)) {\n        isPercent = isNaN(column.width) && gridUtil.endsWith(column.width, \"%\");\n      }\n\n      if (angular.isString(column.width) && column.width.indexOf('*') !== -1) { //  we need to save it until the end to do the calulations on the remaining width.\n        asteriskNum = parseInt(asteriskNum + column.width.length, 10);\n        \n        asterisksArray.push(column);\n      }\n      else if (isPercent) { // If the width is a percentage, save it until the very last.\n        percentArray.push(column);\n      }\n      else if (angular.isNumber(column.width)) {\n        manualWidthSum = parseInt(manualWidthSum + column.width, 10);\n        \n        canvasWidth = parseInt(canvasWidth, 10) + parseInt(column.width, 10);\n\n        column.drawnWidth = column.width;\n      }\n    });\n\n    // Get the remaining width (available width subtracted by the manual widths sum)\n    var remainingWidth = availableWidth - manualWidthSum;\n\n    var i, column, colWidth;\n\n    if (percentArray.length > 0) {\n      // Pre-process to make sure they're all within any min/max values\n      for (i = 0; i < percentArray.length; i++) {\n        column = percentArray[i];\n\n        var percent = parseInt(column.width.replace(/%/g, ''), 10) / 100;\n\n        colWidth = parseInt(percent * remainingWidth, 10);\n\n        if (column.colDef.minWidth && colWidth < column.colDef.minWidth) {\n          colWidth = column.colDef.minWidth;\n\n          remainingWidth = remainingWidth - colWidth;\n\n          canvasWidth += colWidth;\n          column.drawnWidth = colWidth;\n\n          // Remove this element from the percent array so it's not processed below\n          percentArray.splice(i, 1);\n        }\n        else if (column.colDef.maxWidth && colWidth > column.colDef.maxWidth) {\n          colWidth = column.colDef.maxWidth;\n\n          remainingWidth = remainingWidth - colWidth;\n\n          canvasWidth += colWidth;\n          column.drawnWidth = colWidth;\n\n          // Remove this element from the percent array so it's not processed below\n          percentArray.splice(i, 1);\n        }\n      }\n\n      percentArray.forEach(function(column) {\n        var percent = parseInt(column.width.replace(/%/g, ''), 10) / 100;\n        var colWidth = parseInt(percent * remainingWidth, 10);\n\n        canvasWidth += colWidth;\n\n        column.drawnWidth = colWidth;\n      });\n    }\n\n    if (asterisksArray.length > 0) {\n      var asteriskVal = parseInt(remainingWidth / asteriskNum, 10);\n\n       // Pre-process to make sure they're all within any min/max values\n      for (i = 0; i < asterisksArray.length; i++) {\n        column = asterisksArray[i];\n\n        colWidth = parseInt(asteriskVal * column.width.length, 10);\n\n        if (column.colDef.minWidth && colWidth < column.colDef.minWidth) {\n          colWidth = column.colDef.minWidth;\n\n          remainingWidth = remainingWidth - colWidth;\n          asteriskNum--;\n\n          canvasWidth += colWidth;\n          column.drawnWidth = colWidth;\n\n          lastColumn = column;\n\n          // Remove this element from the percent array so it's not processed below\n          asterisksArray.splice(i, 1);\n        }\n        else if (column.colDef.maxWidth && colWidth > column.colDef.maxWidth) {\n          colWidth = column.colDef.maxWidth;\n\n          remainingWidth = remainingWidth - colWidth;\n          asteriskNum--;\n\n          canvasWidth += colWidth;\n          column.drawnWidth = colWidth;\n\n          // Remove this element from the percent array so it's not processed below\n          asterisksArray.splice(i, 1);\n        }\n      }\n\n      // Redo the asterisk value, as we may have removed columns due to width constraints\n      asteriskVal = parseInt(remainingWidth / asteriskNum, 10);\n\n      asterisksArray.forEach(function(column) {\n        var colWidth = parseInt(asteriskVal * column.width.length, 10);\n\n        canvasWidth += colWidth;\n\n        column.drawnWidth = colWidth;\n      });\n    }\n\n    // If the grid width didn't divide evenly into the column widths and we have pixels left over, dole them out to the columns one by one to make everything fit\n    var leftoverWidth = availableWidth - parseInt(canvasWidth, 10);\n\n    if (leftoverWidth > 0 && canvasWidth > 0 && canvasWidth < availableWidth) {\n      var variableColumn = false;\n      // uiGridCtrl.grid.columns.forEach(function(col) {\n      columnCache.forEach(function(col) {\n        if (col.width && !angular.isNumber(col.width)) {\n          variableColumn = true;\n        }\n      });\n\n      if (variableColumn) {\n        var remFn = function (column) {\n          if (leftoverWidth > 0) {\n            column.drawnWidth = column.drawnWidth + 1;\n            canvasWidth = canvasWidth + 1;\n            leftoverWidth--;\n          }\n        };\n        while (leftoverWidth > 0) {\n          columnCache.forEach(remFn);\n        }\n      }\n    }\n\n    if (canvasWidth < availableWidth) {\n      canvasWidth = availableWidth;\n    }\n\n    // Build the CSS\n    columnCache.forEach(function (column) {\n      ret = ret + column.getColClassDefinition();\n    });\n\n    // Add the vertical scrollbar width back in to the canvas width, it's taken out in getCanvasWidth\n    //if (self.grid.verticalScrollbarWidth) {\n    //  canvasWidth = canvasWidth + self.grid.verticalScrollbarWidth;\n    //}\n    // canvasWidth = canvasWidth + 1;\n\n    self.canvasWidth = parseInt(canvasWidth, 10);\n\n    // Return the styles back to buildStyles which pops them into the `customStyles` scope variable\n    // return ret;\n\n    // Set this render container's column styles so they can be used in style computation\n    this.columnStyles = ret;\n  };\n\n  GridRenderContainer.prototype.getViewPortStyle = function () {\n    var self = this;\n    var styles = {};\n\n    if (self.name === 'body') {\n      styles['overflow-x'] = self.grid.options.enableHorizontalScrollbar === uiGridConstants.scrollbars.NEVER ? 'hidden' : 'scroll';\n      if (!self.grid.isRTL()) {\n        if (self.grid.hasRightContainerColumns()) {\n          styles['overflow-y'] = 'hidden';\n        }\n        else {\n          styles['overflow-y'] = self.grid.options.enableVerticalScrollbar === uiGridConstants.scrollbars.NEVER ? 'hidden' : 'scroll';\n        }\n      }\n      else {\n        if (self.grid.hasLeftContainerColumns()) {\n          styles['overflow-y'] = 'hidden';\n        }\n        else {\n          styles['overflow-y'] = self.grid.options.enableVerticalScrollbar === uiGridConstants.scrollbars.NEVER ? 'hidden' : 'scroll';\n        }\n      }\n    }\n    else if (self.name === 'left') {\n      styles['overflow-x'] = 'hidden';\n      styles['overflow-y'] = self.grid.isRTL() ? (self.grid.options.enableVerticalScrollbar === uiGridConstants.scrollbars.NEVER ? 'hidden' : 'scroll') : 'hidden';\n    }\n    else {\n      styles['overflow-x'] = 'hidden';\n      styles['overflow-y'] = !self.grid.isRTL() ? (self.grid.options.enableVerticalScrollbar === uiGridConstants.scrollbars.NEVER ? 'hidden' : 'scroll') : 'hidden';\n    }\n\n    return styles;\n\n\n  };\n\n  return GridRenderContainer;\n}]);\n\n})();\n\n(function(){\n\nangular.module('ui.grid')\n.factory('GridRow', ['gridUtil', function(gridUtil) {\n\n   /**\n   * @ngdoc function\n   * @name ui.grid.class:GridRow\n   * @description GridRow is the viewModel for one logical row on the grid.  A grid Row is not necessarily a one-to-one\n   * relation to gridOptions.data.\n   * @param {object} entity the array item from GridOptions.data\n   * @param {number} index the current position of the row in the array\n   * @param {Grid} reference to the parent grid\n   */\n  function GridRow(entity, index, grid) {\n\n     /**\n      *  @ngdoc object\n      *  @name grid\n      *  @propertyOf  ui.grid.class:GridRow\n      *  @description A reference back to the grid\n      */\n     this.grid = grid;\n\n     /**\n      *  @ngdoc object\n      *  @name entity\n      *  @propertyOf  ui.grid.class:GridRow\n      *  @description A reference to an item in gridOptions.data[]\n      */\n    this.entity = entity;\n\n     /**\n      *  @ngdoc object\n      *  @name uid\n      *  @propertyOf  ui.grid.class:GridRow\n      *  @description  UniqueId of row\n      */\n     this.uid = gridUtil.nextUid();\n\n     /**\n      *  @ngdoc object\n      *  @name visible\n      *  @propertyOf  ui.grid.class:GridRow\n      *  @description If true, the row will be rendered\n      */\n    // Default to true\n    this.visible = true;\n\n\n    this.$$height = grid.options.rowHeight;\n\n  }\n\n    /**\n     *  @ngdoc object\n     *  @name height\n     *  @propertyOf  ui.grid.class:GridRow\n     *  @description height of each individual row. changing the height will flag all\n     *  row renderContainers to recalculate their canvas height\n     */\n    Object.defineProperty(GridRow.prototype, 'height', {\n      get: function() {\n        return this.$$height;\n      },\n      set: function(height) {\n        if (height !== this.$$height) {\n          this.grid.updateCanvasHeight();\n          this.$$height = height;\n        }\n      }\n    });\n\n  /**\n   * @ngdoc function\n   * @name getQualifiedColField\n   * @methodOf ui.grid.class:GridRow\n   * @description returns the qualified field name as it exists on scope\n   * ie: row.entity.fieldA\n   * @param {GridCol} col column instance\n   * @returns {string} resulting name that can be evaluated on scope\n   */\n    GridRow.prototype.getQualifiedColField = function(col) {\n      return 'row.' + this.getEntityQualifiedColField(col);\n    };\n\n    /**\n     * @ngdoc function\n     * @name getEntityQualifiedColField\n     * @methodOf ui.grid.class:GridRow\n     * @description returns the qualified field name minus the row path\n     * ie: entity.fieldA\n     * @param {GridCol} col column instance\n     * @returns {string} resulting name that can be evaluated against a row\n     */\n  GridRow.prototype.getEntityQualifiedColField = function(col) {\n    return gridUtil.preEval('entity.' + col.field);\n  };\n  \n  \n  /**\n   * @ngdoc function\n   * @name setRowInvisible\n   * @methodOf  ui.grid.class:GridRow\n   * @description Sets an override on the row that forces it to always\n   * be invisible, and if the row is currently visible then marks it\n   * as invisible and refreshes the grid.  Emits the rowsVisibleChanged\n   * event if it changed the row visibility\n   * @param {GridRow} row row to force invisible, needs to be a GridRow,\n   * which can be found from your data entity using grid.findRow\n   */\n  GridRow.prototype.setRowInvisible = function (row) {\n    if (row !== null) {\n      row.forceInvisible = true;\n      \n      if ( row.visible ){\n        row.visible = false;\n        row.grid.refresh();\n        row.grid.api.core.raise.rowsVisibleChanged();\n      }\n    }        \n  };\n\n  /**\n   * @ngdoc function\n   * @name clearRowInvisible\n   * @methodOf ui.grid.class:GridRow\n   * @description Clears any override on the row visibility, returning it \n   * to normal visibility calculations.  If the row is currently invisible\n   * then sets it to visible and calls refresh and emits the rowsVisibleChanged\n   * event\n   * TODO: if filter in action, then is this right?\n   * @param {GridRow} row row clear force invisible, needs to be a GridRow,\n   * which can be found from your data entity using grid.findRow\n   */\n  GridRow.prototype.clearRowInvisible = function (row) {\n    if (row !== null) {\n      row.forceInvisible = false;\n      \n      if ( !row.visible ){\n        row.visible = true;\n        row.grid.refresh();\n        row.grid.api.core.raise.rowsVisibleChanged();\n      }\n    }        \n  };\n\n  return GridRow;\n}]);\n\n})();\n(function () {\n  angular.module('ui.grid')\n    .factory('ScrollEvent', ['gridUtil', function (gridUtil) {\n\n      /**\n       * @ngdoc function\n       * @name ui.grid.class:ScrollEvent\n       * @description Model for all scrollEvents\n       * @param {Grid} grid that owns the scroll event\n       * @param {GridRenderContainer} sourceRowContainer that owns the scroll event. Can be null\n       * @param {GridRenderContainer} sourceColContainer that owns the scroll event. Can be null\n       * @param {string} source the source of the event - from uiGridConstants.scrollEventSources or a string value of directive/service/factory.functionName\n       */\n      function ScrollEvent(grid, sourceRowContainer, sourceColContainer, source) {\n        var self = this;\n        if (!grid) {\n          throw new Error(\"grid argument is required\");\n        }\n\n        /**\n         *  @ngdoc object\n         *  @name grid\n         *  @propertyOf  ui.grid.class:ScrollEvent\n         *  @description A reference back to the grid\n         */\n         self.grid = grid;\n\n\n\n        /**\n         *  @ngdoc object\n         *  @name entity\n         *  @propertyOf  ui.grid.class:ScrollEvent\n         *  @description the source of the scroll event. limited to values from uiGridConstants.scrollEventSources\n         */\n        self.source = source;\n\n        self.sourceRowContainer = sourceRowContainer;\n        self.sourceColContainer = sourceColContainer;\n\n        self.newScrollLeft = null;\n        self.newScrollTop = null;\n        self.x = null;\n        self.y = null;\n\n\n        /**\n         *  @ngdoc function\n         *  @name fireThrottledScrollingEvent\n         *  @methodOf  ui.grid.class:ScrollEvent\n         *  @description fires a throttled event using grid.api.core.raise.scrollEvent\n         */\n        self.fireThrottledScrollingEvent = gridUtil.throttle(function() {\n          self.grid.api.core.raise.scrollEvent(self);\n        }, self.grid.options.scrollThrottle, {trailing: true});\n\n      }\n\n      /**\n       *  @ngdoc function\n       *  @name fireScrollingEvent\n       *  @methodOf  ui.grid.class:ScrollEvent\n       *  @description fires an event using grid.api.core.raise.scrollEvent\n       */\n      ScrollEvent.prototype.fireScrollingEvent = function() {\n        this.grid.api.core.raise.scrollEvent(this);\n      };\n\n\n      /**\n       *  @ngdoc function\n       *  @name getNewScrollLeft\n       *  @methodOf  ui.grid.class:ScrollEvent\n       *  @description returns newScrollLeft property if available; calculates a new value if it isn't\n       */\n      ScrollEvent.prototype.getNewScrollLeft = function(colContainer, viewport){\n        var self = this;\n\n        if (!self.newScrollLeft){\n          var scrollWidth = (colContainer.getCanvasWidth() - colContainer.getViewportWidth());\n\n          var oldScrollLeft = gridUtil.normalizeScrollLeft(viewport);\n\n          var scrollXPercentage;\n          if (typeof(self.x.percentage) !== 'undefined' && self.x.percentage !== undefined) {\n            scrollXPercentage = self.x.percentage;\n          }\n          else if (typeof(self.x.pixels) !== 'undefined' && self.x.pixels !== undefined) {\n            scrollXPercentage = self.x.percentage = (oldScrollLeft + self.x.pixels) / scrollWidth;\n          }\n          else {\n            throw new Error(\"No percentage or pixel value provided for scroll event X axis\");\n          }\n\n          return Math.max(0, scrollXPercentage * scrollWidth);\n        }\n\n        return self.newScrollLeft;\n      };\n\n\n      /**\n       *  @ngdoc function\n       *  @name getNewScrollTop\n       *  @methodOf  ui.grid.class:ScrollEvent\n       *  @description returns newScrollTop property if available; calculates a new value if it isn't\n       */\n      ScrollEvent.prototype.getNewScrollTop = function(rowContainer, viewport){\n        var self = this;\n\n\n        if (!self.newScrollTop){\n          var scrollLength = rowContainer.getVerticalScrollLength();\n\n          var oldScrollTop = viewport[0].scrollTop;\n\n          var scrollYPercentage;\n          if (typeof(self.y.percentage) !== 'undefined' && self.y.percentage !== undefined) {\n            scrollYPercentage = self.y.percentage;\n          }\n          else if (typeof(self.y.pixels) !== 'undefined' && self.y.pixels !== undefined) {\n            scrollYPercentage = self.y.percentage = (oldScrollTop + self.y.pixels) / scrollLength;\n          }\n          else {\n            throw new Error(\"No percentage or pixel value provided for scroll event Y axis\");\n          }\n\n          return Math.max(0, scrollYPercentage * scrollLength);\n        }\n\n        return self.newScrollTop;\n      };\n\n\n      ScrollEvent.Sources = {\n        ViewPortScroll: 'ViewPortScroll',\n        RenderContainerMouseWheel: 'RenderContainerMouseWheel',\n        RenderContainerTouchMove: 'RenderContainerTouchMove',\n        Other: 99\n      };\n\n      return ScrollEvent;\n    }]);\n\n\n\n})();\n(function () {\n  'use strict';\n  /**\n   *  @ngdoc object\n   *  @name ui.grid.service:gridClassFactory\n   *\n   *  @description factory to return dom specific instances of a grid\n   *\n   */\n  angular.module('ui.grid').service('gridClassFactory', ['gridUtil', '$q', '$compile', '$templateCache', 'uiGridConstants', 'Grid', 'GridColumn', 'GridRow',\n    function (gridUtil, $q, $compile, $templateCache, uiGridConstants, Grid, GridColumn, GridRow) {\n\n      var service = {\n        /**\n         * @ngdoc method\n         * @name createGrid\n         * @methodOf ui.grid.service:gridClassFactory\n         * @description Creates a new grid instance. Each instance will have a unique id\n         * @param {object} options An object map of options to pass into the created grid instance.\n         * @returns {Grid} grid\n         */\n        createGrid : function(options) {\n          options = (typeof(options) !== 'undefined') ? options : {};\n          options.id = gridUtil.newId();\n          var grid = new Grid(options);\n\n          // NOTE/TODO: rowTemplate should always be defined...\n          if (grid.options.rowTemplate) {\n            var rowTemplateFnPromise = $q.defer();\n            grid.getRowTemplateFn = rowTemplateFnPromise.promise;\n            \n            gridUtil.getTemplate(grid.options.rowTemplate)\n              .then(\n                function (template) {\n                  var rowTemplateFn = $compile(template);\n                  rowTemplateFnPromise.resolve(rowTemplateFn);\n                },\n                function (res) {\n                  // Todo handle response error here?\n                  throw new Error(\"Couldn't fetch/use row template '\" + grid.options.rowTemplate + \"'\");\n                });\n          }\n\n          grid.registerColumnBuilder(service.defaultColumnBuilder);\n\n          // Row builder for custom row templates\n          grid.registerRowBuilder(service.rowTemplateAssigner);\n\n          // Reset all rows to visible initially\n          grid.registerRowsProcessor(function allRowsVisible(rows) {\n            rows.forEach(function (row) {\n              row.visible = !row.forceInvisible;\n            });\n\n            return rows;\n          });\n\n          grid.registerColumnsProcessor(function allColumnsVisible(columns) {\n            columns.forEach(function (column) {\n              column.visible = true;\n            });\n\n            return columns;\n          });\n\n          grid.registerColumnsProcessor(function(renderableColumns) {\n              renderableColumns.forEach(function (column) {\n                  if (column.colDef.visible === false) {\n                      column.visible = false;\n                  }\n              });\n\n              return renderableColumns;\n          });\n\n\n\n          if (grid.options.enableFiltering) {\n            grid.registerRowsProcessor(grid.searchRows);\n          }\n\n          // Register the default row processor, it sorts rows by selected columns\n          if (grid.options.externalSort && angular.isFunction(grid.options.externalSort)) {\n            grid.registerRowsProcessor(grid.options.externalSort);\n          }\n          else {\n            grid.registerRowsProcessor(grid.sortByColumn);\n          }\n\n          return grid;\n        },\n\n        /**\n         * @ngdoc function\n         * @name defaultColumnBuilder\n         * @methodOf ui.grid.service:gridClassFactory\n         * @description Processes designTime column definitions and applies them to col for the\n         *              core grid features\n         * @param {object} colDef reference to column definition\n         * @param {GridColumn} col reference to gridCol\n         * @param {object} gridOptions reference to grid options\n         */\n        defaultColumnBuilder: function (colDef, col, gridOptions) {\n\n          var templateGetPromises = [];\n\n          /**\n           * @ngdoc property\n           * @name headerCellTemplate\n           * @propertyOf ui.grid.class:GridOptions.columnDef\n           * @description a custom template for the header for this column.  The default\n           * is ui-grid/uiGridHeaderCell\n           *\n           */\n          if (!colDef.headerCellTemplate) {\n            col.providedHeaderCellTemplate = 'ui-grid/uiGridHeaderCell';\n          } else {\n            col.providedHeaderCellTemplate = colDef.headerCellTemplate;\n          }\n\n          /**\n           * @ngdoc property\n           * @name cellTemplate\n           * @propertyOf ui.grid.class:GridOptions.columnDef\n           * @description a custom template for each cell in this column.  The default\n           * is ui-grid/uiGridCell.  If you are using the cellNav feature, this template\n           * must contain a div that can receive focus.\n           *\n           */\n          if (!colDef.cellTemplate) {\n            col.providedCellTemplate = 'ui-grid/uiGridCell';\n          } else {\n            col.providedCellTemplate = colDef.cellTemplate;\n          }\n\n          /**\n           * @ngdoc property\n           * @name footerCellTemplate\n           * @propertyOf ui.grid.class:GridOptions.columnDef\n           * @description a custom template for the footer for this column.  The default\n           * is ui-grid/uiGridFooterCell\n           *\n           */\n          if (!colDef.footerCellTemplate) {\n            col.providedFooterCellTemplate = 'ui-grid/uiGridFooterCell';\n          } else {\n            col.providedFooterCellTemplate = colDef.footerCellTemplate;\n          }\n\n          col.cellTemplatePromise = gridUtil.getTemplate(col.providedCellTemplate);\n          templateGetPromises.push(col.cellTemplatePromise\n            .then(\n              function (template) {\n                col.cellTemplate = template.replace(uiGridConstants.CUSTOM_FILTERS, col.cellFilter ? \"|\" + col.cellFilter : \"\");\n              },\n              function (res) {\n                throw new Error(\"Couldn't fetch/use colDef.cellTemplate '\" + colDef.cellTemplate + \"'\");\n              })\n          );\n\n          templateGetPromises.push(gridUtil.getTemplate(col.providedHeaderCellTemplate)\n              .then(\n              function (template) {\n                col.headerCellTemplate = template.replace(uiGridConstants.CUSTOM_FILTERS, col.headerCellFilter ? \"|\" + col.headerCellFilter : \"\");\n              },\n              function (res) {\n                throw new Error(\"Couldn't fetch/use colDef.headerCellTemplate '\" + colDef.headerCellTemplate + \"'\");\n              })\n          );\n\n          templateGetPromises.push(gridUtil.getTemplate(col.providedFooterCellTemplate)\n              .then(\n              function (template) {\n                col.footerCellTemplate = template.replace(uiGridConstants.CUSTOM_FILTERS, col.footerCellFilter ? \"|\" + col.footerCellFilter : \"\");\n              },\n              function (res) {\n                throw new Error(\"Couldn't fetch/use colDef.footerCellTemplate '\" + colDef.footerCellTemplate + \"'\");\n              })\n          );\n\n          // Create a promise for the compiled element function\n          col.compiledElementFnDefer = $q.defer();\n\n          return $q.all(templateGetPromises);\n        },\n\n        rowTemplateAssigner: function rowTemplateAssigner(row) {\n          var grid = this;\n\n          // Row has no template assigned to it\n          if (!row.rowTemplate) {\n            // Use the default row template from the grid\n            row.rowTemplate = grid.options.rowTemplate;\n\n            // Use the grid's function for fetching the compiled row template function\n            row.getRowTemplateFn = grid.getRowTemplateFn;\n          }\n          // Row has its own template assigned\n          else {\n            // Create a promise for the compiled row template function\n            var perRowTemplateFnPromise = $q.defer();\n            row.getRowTemplateFn = perRowTemplateFnPromise.promise;\n\n            // Get the row template\n            gridUtil.getTemplate(row.rowTemplate)\n              .then(function (template) {\n                // Compile the template\n                var rowTemplateFn = $compile(template);\n                \n                // Resolve the compiled template function promise\n                perRowTemplateFnPromise.resolve(rowTemplateFn);\n              },\n              function (res) {\n                // Todo handle response error here?\n                throw new Error(\"Couldn't fetch/use row template '\" + row.rowTemplate + \"'\");\n              });\n          }\n\n          return row.getRowTemplateFn;\n        }\n      };\n\n      //class definitions (moved to separate factories)\n\n      return service;\n    }]);\n\n})();\n(function() {\n\nvar module = angular.module('ui.grid');\n\nfunction escapeRegExp(str) {\n  return str.replace(/[\\-\\[\\]\\/\\{\\}\\(\\)\\*\\+\\?\\.\\\\\\^\\$\\|]/g, \"\\\\$&\");\n}\n\n\n/**\n *  @ngdoc service\n *  @name ui.grid.service:rowSearcher\n *\n *  @description Service for searching/filtering rows based on column value conditions.\n */\nmodule.service('rowSearcher', ['gridUtil', 'uiGridConstants', function (gridUtil, uiGridConstants) {\n  var defaultCondition = uiGridConstants.filter.STARTS_WITH;\n\n  var rowSearcher = {};\n\n  /**\n   * @ngdoc function\n   * @name getTerm\n   * @methodOf ui.grid.service:rowSearcher\n   * @description Get the term from a filter\n   * Trims leading and trailing whitespace\n   * @param {object} filter object to use\n   * @returns {object} Parsed term\n   */\n  rowSearcher.getTerm = function getTerm(filter) {\n    if (typeof(filter.term) === 'undefined') { return filter.term; }\n    \n    var term = filter.term;\n\n    // Strip leading and trailing whitespace if the term is a string\n    if (typeof(term) === 'string') {\n      term = term.trim();\n    }\n\n    return term;\n  };\n\n  /**\n   * @ngdoc function\n   * @name stripTerm\n   * @methodOf ui.grid.service:rowSearcher\n   * @description Remove leading and trailing asterisk (*) from the filter's term\n   * @param {object} filter object to use\n   * @returns {uiGridConstants.filter<int>} Value representing the condition constant value\n   */\n  rowSearcher.stripTerm = function stripTerm(filter) {\n    var term = rowSearcher.getTerm(filter);\n\n    if (typeof(term) === 'string') {\n      return escapeRegExp(term.replace(/(^\\*|\\*$)/g, ''));\n    }\n    else {\n      return term;\n    }\n  };\n  \n\n  /**\n   * @ngdoc function\n   * @name guessCondition\n   * @methodOf ui.grid.service:rowSearcher\n   * @description Guess the condition for a filter based on its term\n   * <br>\n   * Defaults to STARTS_WITH. Uses CONTAINS for strings beginning and ending with *s (*bob*).\n   * Uses STARTS_WITH for strings ending with * (bo*). Uses ENDS_WITH for strings starting with * (*ob).\n   * @param {object} filter object to use\n   * @returns {uiGridConstants.filter<int>} Value representing the condition constant value\n   */\n  rowSearcher.guessCondition = function guessCondition(filter) {\n    if (typeof(filter.term) === 'undefined' || !filter.term) {\n      return defaultCondition;\n    }\n\n    var term = rowSearcher.getTerm(filter);\n    \n    if (/\\*/.test(term)) {\n      var regexpFlags = '';\n      if (!filter.flags || !filter.flags.caseSensitive) {\n        regexpFlags += 'i';\n      }\n\n      var reText = term.replace(/(\\\\)?\\*/g, function ($0, $1) { return $1 ? $0 : '[\\\\s\\\\S]*?'; });\n      return new RegExp('^' + reText + '$', regexpFlags);\n    }\n    // Otherwise default to default condition\n    else {\n      return defaultCondition;\n    }\n  };\n  \n  \n  /**\n   * @ngdoc function\n   * @name setupFilters\n   * @methodOf ui.grid.service:rowSearcher\n   * @description For a given columns filters (either col.filters, or [col.filter] can be passed in),\n   * do all the parsing and pre-processing and store that data into a new filters object.  The object\n   * has the condition, the flags, the stripped term, and a parsed reg exp if there was one.\n   * \n   * We could use a forEach in here, since it's much less performance sensitive, but since we're using \n   * for loops everywhere else in this module...\n   * \n   * @param {array} filters the filters from the column (col.filters or [col.filter])\n   * @returns {array} An array of parsed/preprocessed filters\n   */\n  rowSearcher.setupFilters = function setupFilters( filters ){\n    var newFilters = [];\n    \n    var filtersLength = filters.length;\n    for ( var i = 0; i < filtersLength; i++ ){\n      var filter = filters[i];\n      if ( filter.noTerm || filter.term ){\n        var newFilter = {};\n        \n        var regexpFlags = '';\n        if (!filter.flags || !filter.flags.caseSensitive) {\n          regexpFlags += 'i';\n        }\n    \n        if ( filter.term ){\n          // it is possible to have noTerm.  We don't need to copy that across, it was just a flag to avoid\n          // getting the filter ignored if the filter was a function that didn't use a term\n          newFilter.term = rowSearcher.stripTerm(filter);\n        }\n        \n        if ( filter.condition ){\n          newFilter.condition = filter.condition;\n        } else {\n          newFilter.condition = rowSearcher.guessCondition(filter);\n        }\n\n        newFilter.flags = angular.extend( { caseSensitive: false }, filter.flags );\n\n        if (newFilter.condition === uiGridConstants.filter.STARTS_WITH) {\n          newFilter.startswithRE = new RegExp('^' + newFilter.term, regexpFlags);\n        }\n        \n         if (newFilter.condition === uiGridConstants.filter.ENDS_WITH) {\n          newFilter.endswithRE = new RegExp(newFilter.term + '$', regexpFlags);\n        }\n\n        if (newFilter.condition === uiGridConstants.filter.CONTAINS) {\n          newFilter.containsRE = new RegExp(newFilter.term, regexpFlags);\n        }\n\n        if (newFilter.condition === uiGridConstants.filter.EXACT) {\n          newFilter.exactRE = new RegExp('^' + newFilter.term + '$', regexpFlags);\n        }\n        \n        newFilters.push(newFilter);\n      }\n    }\n    return newFilters;\n  };\n  \n\n  /**\n   * @ngdoc function\n   * @name runColumnFilter\n   * @methodOf ui.grid.service:rowSearcher\n   * @description Runs a single pre-parsed filter against a cell, returning true\n   * if the cell matches that one filter.\n   * \n   * @param {Grid} grid the grid we're working against\n   * @param {GridRow} row the row we're matching against\n   * @param {GridCol} column the column that we're working against\n   * @param {object} filter the specific, preparsed, filter that we want to test\n   * @returns {boolean} true if we match (row stays visible)\n   */\n  rowSearcher.runColumnFilter = function runColumnFilter(grid, row, column, filter) {\n    // Cache typeof condition\n    var conditionType = typeof(filter.condition);\n\n    // Term to search for.\n    var term = filter.term;\n\n    // Get the column value for this row\n    var value = grid.getCellValue(row, column);\n    \n    // If the filter's condition is a RegExp, then use it\n    if (filter.condition instanceof RegExp) {\n      return filter.condition.test(value);\n    }\n\n    // If the filter's condition is a function, run it\n    if (conditionType === 'function') {\n      return filter.condition(term, value, row, column);\n    }\n    \n    if (filter.startswithRE) {\n      return filter.startswithRE.test(value);\n    }\n    \n    if (filter.endswithRE) {\n      return filter.endswithRE.test(value);\n    }\n    \n    if (filter.containsRE) {\n      return filter.containsRE.test(value);\n    }\n    \n    if (filter.exactRE) {\n      return filter.exactRE.test(value);\n    }\n\n    if (filter.condition === uiGridConstants.filter.NOT_EQUAL) {\n      var regex = new RegExp('^' + term + '$');\n      return !regex.exec(value);\n    }\n\n    if (typeof(value) === 'number'){\n      // if the term has a decimal in it, it comes through as '9\\.4', we need to take out the \\\n      var tempFloat = parseFloat(term.replace(/\\\\./,'.'));\n      if (!isNaN(tempFloat)) {\n        term = tempFloat;\n      }\n    }\n\n    if (filter.condition === uiGridConstants.filter.GREATER_THAN) {\n      return (value > term);\n    }\n\n    if (filter.condition === uiGridConstants.filter.GREATER_THAN_OR_EQUAL) {\n      return (value >= term);\n    }\n\n    if (filter.condition === uiGridConstants.filter.LESS_THAN) {\n      return (value < term);\n    }\n    \n    if (filter.condition === uiGridConstants.filter.LESS_THAN_OR_EQUAL) {\n      return (value <= term);\n    }\n    \n    return true;\n  };\n\n\n  /**\n   * @ngdoc boolean\n   * @name useExternalFiltering\n   * @propertyOf ui.grid.class:GridOptions\n   * @description False by default. When enabled, this setting suppresses the internal filtering.\n   * All UI logic will still operate, allowing filter conditions to be set and modified.\n   * \n   * The external filter logic can listen for the `filterChange` event, which fires whenever\n   * a filter has been adjusted.\n   */\n  /**\n   * @ngdoc function\n   * @name searchColumn\n   * @methodOf ui.grid.service:rowSearcher\n   * @description Process provided filters on provided column against a given row. If the row meets \n   * the conditions on all the filters, return true.\n   * @param {Grid} grid Grid to search in\n   * @param {GridRow} row Row to search on\n   * @param {GridCol} column Column with the filters to use\n   * @param {array} filters array of pre-parsed/preprocessed filters to apply\n   * @returns {boolean} Whether the column matches or not.\n   */\n  rowSearcher.searchColumn = function searchColumn(grid, row, column, filters) {\n    if (grid.options.useExternalFiltering) {\n      return true;\n    }\n    \n    var filtersLength = filters.length;\n    for (var i = 0; i < filtersLength; i++) {\n      var filter = filters[i];\n      \n      var ret = rowSearcher.runColumnFilter(grid, row, column, filter);\n      if (!ret) {\n        return false;\n      }\n    }\n\n    return true;\n  };\n\n\n  /**\n   * @ngdoc function\n   * @name search\n   * @methodOf ui.grid.service:rowSearcher\n   * @description Run a search across the given rows and columns, marking any rows that don't \n   * match the stored col.filters or col.filter as invisible.\n   * @param {Grid} grid Grid instance to search inside\n   * @param {Array[GridRow]} rows GridRows to filter\n   * @param {Array[GridColumn]} columns GridColumns with filters to process\n   */\n  rowSearcher.search = function search(grid, rows, columns) {\n    /*\n     * Added performance optimisations into this code base, as this logic creates deeply nested\n     * loops and is therefore very performance sensitive.  In particular, avoiding forEach as\n     * this impacts some browser optimisers (particularly Chrome), using iterators instead\n     */\n    \n    // Don't do anything if we weren't passed any rows\n    if (!rows) {\n      return;\n    }\n\n    // Build list of filters to apply\n    var filterData = [];\n\n    var colsLength = columns.length;\n    for (var i = 0; i < colsLength; i++) {\n      var col = columns[i];\n      \n      if (typeof(col.filters) !== 'undefined' && ( col.filters.length > 1 || col.filters.length === 1 && ( typeof(col.filters[0].term) !== 'undefined' && col.filters[0].term || col.filters[0].noTerm ) ) ) {\n        filterData.push( { col: col, filters: rowSearcher.setupFilters(col.filters) } );\n      }\n      else if (typeof(col.filter) !== 'undefined' && col.filter && ( typeof(col.filter.term) !== 'undefined' && col.filter.term || col.filter.noTerm ) ) {\n        filterData.push( { col: col, filters: rowSearcher.setupFilters([col.filter]) } );\n      }\n    }\n    \n    if (filterData.length > 0) {\n      // define functions outside the loop, performance optimisation\n      var foreachRow = function(grid, row, col, filters){\n        if (row.forceInvisible || !rowSearcher.searchColumn(grid, row, col, filters)) {\n          row.visible = false;\n        }\n      };\n      \n      var foreachFilterCol = function(grid, filterData){\n        var rowsLength = rows.length;\n        for ( var i = 0; i < rowsLength; i++){\n          foreachRow(grid, rows[i], filterData.col, filterData.filters);  \n        }\n      };\n\n      // nested loop itself - foreachFilterCol, which in turn calls foreachRow\n      var filterDataLength = filterData.length;\n      for ( var j = 0; j < filterDataLength; j++){\n        foreachFilterCol( grid, filterData[j] );  \n      }\n\n      if (grid.api.core.raise.rowsVisibleChanged) {\n        grid.api.core.raise.rowsVisibleChanged();\n      }\n    }\n\n    return rows;\n  };\n\n  return rowSearcher;\n}]);\n\n})();\n(function() {\n\nvar module = angular.module('ui.grid');\n\n/**\n * @ngdoc object\n * @name ui.grid.class:RowSorter\n * @description RowSorter provides the default sorting mechanisms, \n * including guessing column types and applying appropriate sort \n * algorithms\n * \n */ \n\nmodule.service('rowSorter', ['$parse', 'uiGridConstants', function ($parse, uiGridConstants) {\n  var currencyRegexStr = \n    '(' +\n    uiGridConstants.CURRENCY_SYMBOLS\n      .map(function (a) { return '\\\\' + a; }) // Escape all the currency symbols ($ at least will jack up this regex)\n      .join('|') + // Join all the symbols together with |s\n    ')?';\n\n  // /^[-+]?[£$¤¥]?[\\d,.]+%?$/\n  var numberStrRegex = new RegExp('^[-+]?' + currencyRegexStr + '[\\\\d,.]+' + currencyRegexStr + '%?$');\n\n  var rowSorter = {\n    // Cache of sorting functions. Once we create them, we don't want to keep re-doing it\n    //   this takes a piece of data from the cell and tries to determine its type and what sorting\n    //   function to use for it\n    colSortFnCache: []\n  };\n\n\n  /**\n   * @ngdoc method\n   * @methodOf ui.grid.class:RowSorter\n   * @name guessSortFn\n   * @description Assigns a sort function to use based on the itemType in the column\n   * @param {string} itemType one of 'number', 'boolean', 'string', 'date', 'object'.  And\n   * error will be thrown for any other type.\n   * @returns {function} a sort function that will sort that type\n   */\n  rowSorter.guessSortFn = function guessSortFn(itemType) {\n    switch (itemType) {\n      case \"number\":\n        return rowSorter.sortNumber;\n      case \"boolean\":\n        return rowSorter.sortBool;\n      case \"string\":\n        return rowSorter.sortAlpha;\n      case \"date\":\n        return rowSorter.sortDate;\n      case \"object\":\n        return rowSorter.basicSort;\n      default:\n        throw new Error('No sorting function found for type:' + itemType);\n    }\n  };\n\n\n  /**\n   * @ngdoc method\n   * @methodOf ui.grid.class:RowSorter\n   * @name handleNulls\n   * @description Sorts nulls and undefined to the bottom (top when\n   * descending).  Called by each of the internal sorters before\n   * attempting to sort.  Note that this method is available on the core api\n   * via gridApi.core.sortHandleNulls\n   * @param {object} a sort value a\n   * @param {object} b sort value b\n   * @returns {number} null if there were no nulls/undefineds, otherwise returns\n   * a sort value that should be passed back from the sort function\n   */\n  rowSorter.handleNulls = function handleNulls(a, b) {\n    // We want to allow zero values and false values to be evaluated in the sort function\n    if ((!a && a !== 0 && a !== false) || (!b && b !== 0 && b !== false)) {\n      // We want to force nulls and such to the bottom when we sort... which effectively is \"greater than\"\n      if ((!a && a !== 0 && a !== false) && (!b && b !== 0 && b !== false)) {\n        return 0;\n      }\n      else if (!a && a !== 0 && a !== false) {\n        return 1;\n      }\n      else if (!b && b !== 0 && b !== false) {\n        return -1;\n      }\n    }\n    return null;\n  };\n\n\n  /**\n   * @ngdoc method\n   * @methodOf ui.grid.class:RowSorter\n   * @name basicSort\n   * @description Sorts any values that provide the < method, including strings\n   * or numbers.  Handles nulls and undefined through calling handleNulls \n   * @param {object} a sort value a\n   * @param {object} b sort value b\n   * @returns {number} normal sort function, returns -ve, 0, +ve\n   */\n  rowSorter.basicSort = function basicSort(a, b) {\n    var nulls = rowSorter.handleNulls(a, b);\n    if ( nulls !== null ){\n      return nulls;\n    } else {\n      if (a === b) {\n        return 0;\n      }\n      if (a < b) {\n        return -1;\n      }\n      return 1;\n    }\n  };\n\n\n  /**\n   * @ngdoc method\n   * @methodOf ui.grid.class:RowSorter\n   * @name sortNumber\n   * @description Sorts numerical values.  Handles nulls and undefined through calling handleNulls \n   * @param {object} a sort value a\n   * @param {object} b sort value b\n   * @returns {number} normal sort function, returns -ve, 0, +ve\n   */\n  rowSorter.sortNumber = function sortNumber(a, b) {\n    var nulls = rowSorter.handleNulls(a, b);\n    if ( nulls !== null ){\n      return nulls;\n    } else {\n      return a - b;\n    }\n  };\n\n\n  /**\n   * @ngdoc method\n   * @methodOf ui.grid.class:RowSorter\n   * @name sortNumberStr\n   * @description Sorts numerical values that are stored in a string (i.e. parses them to numbers first).  \n   * Handles nulls and undefined through calling handleNulls \n   * @param {object} a sort value a\n   * @param {object} b sort value b\n   * @returns {number} normal sort function, returns -ve, 0, +ve\n   */\n  rowSorter.sortNumberStr = function sortNumberStr(a, b) {\n    var nulls = rowSorter.handleNulls(a, b);\n    if ( nulls !== null ){\n      return nulls;\n    } else {\n      var numA, // The parsed number form of 'a'\n          numB, // The parsed number form of 'b'\n          badA = false,\n          badB = false;\n  \n      // Try to parse 'a' to a float\n      numA = parseFloat(a.replace(/[^0-9.-]/g, ''));\n  \n      // If 'a' couldn't be parsed to float, flag it as bad\n      if (isNaN(numA)) {\n          badA = true;\n      }\n  \n      // Try to parse 'b' to a float\n      numB = parseFloat(b.replace(/[^0-9.-]/g, ''));\n  \n      // If 'b' couldn't be parsed to float, flag it as bad\n      if (isNaN(numB)) {\n          badB = true;\n      }\n  \n      // We want bad ones to get pushed to the bottom... which effectively is \"greater than\"\n      if (badA && badB) {\n          return 0;\n      }\n  \n      if (badA) {\n          return 1;\n      }\n  \n      if (badB) {\n          return -1;\n      }\n  \n      return numA - numB;\n    }\n  };\n\n\n  /**\n   * @ngdoc method\n   * @methodOf ui.grid.class:RowSorter\n   * @name sortAlpha\n   * @description Sorts string values. Handles nulls and undefined through calling handleNulls \n   * @param {object} a sort value a\n   * @param {object} b sort value b\n   * @returns {number} normal sort function, returns -ve, 0, +ve\n   */\n  rowSorter.sortAlpha = function sortAlpha(a, b) {\n    var nulls = rowSorter.handleNulls(a, b);\n    if ( nulls !== null ){\n      return nulls;\n    } else {\n      var strA = a.toString().toLowerCase(),\n          strB = b.toString().toLowerCase();\n  \n      return strA === strB ? 0 : (strA < strB ? -1 : 1);\n    }\n  };\n\n\n  /**\n   * @ngdoc method\n   * @methodOf ui.grid.class:RowSorter\n   * @name sortDate\n   * @description Sorts date values. Handles nulls and undefined through calling handleNulls \n   * @param {object} a sort value a\n   * @param {object} b sort value b\n   * @returns {number} normal sort function, returns -ve, 0, +ve\n   */\n  rowSorter.sortDate = function sortDate(a, b) {\n    var nulls = rowSorter.handleNulls(a, b);\n    if ( nulls !== null ){\n      return nulls;\n    } else {\n      var timeA = a.getTime(),\n          timeB = b.getTime();\n  \n      return timeA === timeB ? 0 : (timeA < timeB ? -1 : 1);\n    }\n  };\n\n\n  /**\n   * @ngdoc method\n   * @methodOf ui.grid.class:RowSorter\n   * @name sortBool\n   * @description Sorts boolean values, true is considered larger than false. \n   * Handles nulls and undefined through calling handleNulls \n   * @param {object} a sort value a\n   * @param {object} b sort value b\n   * @returns {number} normal sort function, returns -ve, 0, +ve\n   */\n  rowSorter.sortBool = function sortBool(a, b) {\n    var nulls = rowSorter.handleNulls(a, b);\n    if ( nulls !== null ){\n      return nulls;\n    } else {\n      if (a && b) {\n        return 0;\n      }\n  \n      if (!a && !b) {\n        return 0;\n      }\n      else {\n        return a ? 1 : -1;\n      }\n    }\n  };\n\n\n  /**\n   * @ngdoc method\n   * @methodOf ui.grid.class:RowSorter\n   * @name getSortFn\n   * @description Get the sort function for the column.  Looks first in \n   * rowSorter.colSortFnCache using the column name, failing that it\n   * looks at col.sortingAlgorithm (and puts it in the cache), failing that\n   * it guesses the sort algorithm based on the data type.\n   * \n   * The cache currently seems a bit pointless, as none of the work we do is\n   * processor intensive enough to need caching.  Presumably in future we might\n   * inspect the row data itself to guess the sort function, and in that case\n   * it would make sense to have a cache, the infrastructure is in place to allow\n   * that.\n   * \n   * @param {Grid} grid the grid to consider\n   * @param {GridCol} col the column to find a function for\n   * @param {array} rows an array of grid rows.  Currently unused, but presumably in future\n   * we might inspect the rows themselves to decide what sort of data might be there\n   * @returns {function} the sort function chosen for the column\n   */\n  rowSorter.getSortFn = function getSortFn(grid, col, rows) {\n    var sortFn, item;\n\n    // See if we already figured out what to use to sort the column and have it in the cache\n    if (rowSorter.colSortFnCache[col.colDef.name]) {\n      sortFn = rowSorter.colSortFnCache[col.colDef.name];\n    }\n    // If the column has its OWN sorting algorithm, use that\n    else if (col.sortingAlgorithm !== undefined) {\n      sortFn = col.sortingAlgorithm;\n      rowSorter.colSortFnCache[col.colDef.name] = col.sortingAlgorithm;\n    }\n    // Try and guess what sort function to use\n    else {\n      // Guess the sort function\n      sortFn = rowSorter.guessSortFn(col.colDef.type);\n\n      // If we found a sort function, cache it\n      if (sortFn) {\n        rowSorter.colSortFnCache[col.colDef.name] = sortFn;\n      }\n      else {\n        // We assign the alpha sort because anything that is null/undefined will never get passed to\n        // the actual sorting function. It will get caught in our null check and returned to be sorted\n        // down to the bottom\n        sortFn = rowSorter.sortAlpha;\n      }\n    }\n\n    return sortFn;\n  };\n\n\n\n  /**\n   * @ngdoc method\n   * @methodOf ui.grid.class:RowSorter\n   * @name prioritySort\n   * @description Used where multiple columns are present in the sort criteria,\n   * we determine which column should take precedence in the sort by sorting\n   * the columns based on their sort.priority\n   * \n   * @param {gridColumn} a column a\n   * @param {gridColumn} b column b\n   * @returns {number} normal sort function, returns -ve, 0, +ve\n   */\n  rowSorter.prioritySort = function (a, b) {\n    // Both columns have a sort priority\n    if (a.sort.priority !== undefined && b.sort.priority !== undefined) {\n      // A is higher priority\n      if (a.sort.priority < b.sort.priority) {\n        return -1;\n      }\n      // Equal\n      else if (a.sort.priority === b.sort.priority) {\n        return 0;\n      }\n      // B is higher\n      else {\n        return 1;\n      }\n    }\n    // Only A has a priority\n    else if (a.sort.priority || a.sort.priority === 0) {\n      return -1;\n    }\n    // Only B has a priority\n    else if (b.sort.priority || b.sort.priority === 0) {\n      return 1;\n    }\n    // Neither has a priority\n    else {\n      return 0;\n    }\n  };\n\n\n  /**\n   * @ngdoc object\n   * @name useExternalSorting\n   * @propertyOf ui.grid.class:GridOptions\n   * @description Prevents the internal sorting from executing.  Events will\n   * still be fired when the sort changes, and the sort information on\n   * the columns will be updated, allowing an external sorter (for example,\n   * server sorting) to be implemented.  Defaults to false. \n   * \n   */\n  /**\n   * @ngdoc method\n   * @methodOf ui.grid.class:RowSorter\n   * @name sort\n   * @description sorts the grid \n   * @param {Object} grid the grid itself\n   * @param {Object} rows the rows to be sorted\n   * @param {Object} columns the columns in which to look\n   * for sort criteria\n   */\n  rowSorter.sort = function rowSorterSort(grid, rows, columns) {\n    // first make sure we are even supposed to do work\n    if (!rows) {\n      return;\n    }\n    \n    if (grid.options.useExternalSorting){\n      return rows;\n    }\n\n    // Build the list of columns to sort by\n    var sortCols = [];\n    columns.forEach(function (col) {\n      if (col.sort && col.sort.direction && (col.sort.direction === uiGridConstants.ASC || col.sort.direction === uiGridConstants.DESC)) {\n        sortCols.push(col);\n      }\n    });\n\n    // Sort the \"sort columns\" by their sort priority\n    sortCols = sortCols.sort(rowSorter.prioritySort);\n\n    // Now rows to sort by, maintain original order\n    if (sortCols.length === 0) {\n      return rows;\n    }\n    \n    // Re-usable variables\n    var col, direction;\n\n    // IE9-11 HACK.... the 'rows' variable would be empty where we call rowSorter.getSortFn(...) below. We have to use a separate reference\n    // var d = data.slice(0);\n    var r = rows.slice(0);\n    \n    // put a custom index field on each row, used to make a stable sort out of unstable sorts (e.g. Chrome)\n    angular.forEach( rows, function ( row, idx ) {\n      row.entity.$uiGridIndex = idx;\n    });\n\n    // Now actually sort the data\n    var newRows = rows.sort(function rowSortFn(rowA, rowB) {\n      var tem = 0,\n          idx = 0,\n          sortFn;\n\n      while (tem === 0 && idx < sortCols.length) {\n        // grab the metadata for the rest of the logic\n        col = sortCols[idx];\n        direction = sortCols[idx].sort.direction;\n\n        sortFn = rowSorter.getSortFn(grid, col, r);\n        \n        var propA = grid.getCellValue(rowA, col);\n        var propB = grid.getCellValue(rowB, col);\n\n        tem = sortFn(propA, propB);\n\n        idx++;\n      }\n\n      // Chrome doesn't implement a stable sort function.  If our sort returns 0 \n      // (i.e. the items are equal), then return the previous order using our custom\n      // index variable\n      if (tem === 0 ) {\n        return rowA.entity.$uiGridIndex - rowB.entity.$uiGridIndex;\n      }\n      \n      // Made it this far, we don't have to worry about null & undefined\n      if (direction === uiGridConstants.ASC) {\n        return tem;\n      } else {\n        return 0 - tem;\n      }\n    });\n    \n    // remove the custom index field on each row, used to make a stable sort out of unstable sorts (e.g. Chrome)\n    angular.forEach( newRows, function ( row, idx ) {\n      delete row.entity.$uiGridIndex;\n    });\n    \n    return newRows;\n  };\n\n  return rowSorter;\n}]);\n\n})();\n(function() {\n\nvar module = angular.module('ui.grid');\n\nfunction getStyles (elem) {\n  var e = elem;\n  if (typeof(e.length) !== 'undefined' && e.length) {\n    e = elem[0];\n  }\n\n  return e.ownerDocument.defaultView.getComputedStyle(e, null);\n}\n\nvar rnumnonpx = new RegExp( \"^(\" + (/[+-]?(?:\\d*\\.|)\\d+(?:[eE][+-]?\\d+|)/).source + \")(?!px)[a-z%]+$\", \"i\" ),\n    // swappable if display is none or starts with table except \"table\", \"table-cell\", or \"table-caption\"\n    // see here for display values: https://developer.mozilla.org/en-US/docs/CSS/display\n    rdisplayswap = /^(block|none|table(?!-c[ea]).+)/,\n    cssShow = { position: \"absolute\", visibility: \"hidden\", display: \"block\" };\n\nfunction augmentWidthOrHeight( elem, name, extra, isBorderBox, styles ) {\n  var i = extra === ( isBorderBox ? 'border' : 'content' ) ?\n          // If we already have the right measurement, avoid augmentation\n          4 :\n          // Otherwise initialize for horizontal or vertical properties\n          name === 'width' ? 1 : 0,\n\n          val = 0;\n\n  var sides = ['Top', 'Right', 'Bottom', 'Left'];\n  \n  for ( ; i < 4; i += 2 ) {\n    var side = sides[i];\n    // dump('side', side);\n\n    // both box models exclude margin, so add it if we want it\n    if ( extra === 'margin' ) {\n      var marg = parseFloat(styles[extra + side]);\n      if (!isNaN(marg)) {\n        val += marg;\n      }\n    }\n    // dump('val1', val);\n\n    if ( isBorderBox ) {\n      // border-box includes padding, so remove it if we want content\n      if ( extra === 'content' ) {\n        var padd = parseFloat(styles['padding' + side]);\n        if (!isNaN(padd)) {\n          val -= padd;\n          // dump('val2', val);\n        }\n      }\n\n      // at this point, extra isn't border nor margin, so remove border\n      if ( extra !== 'margin' ) {\n        var bordermarg = parseFloat(styles['border' + side + 'Width']);\n        if (!isNaN(bordermarg)) {\n          val -= bordermarg;\n          // dump('val3', val);\n        }\n      }\n    }\n    else {\n      // at this point, extra isn't content, so add padding\n      var nocontentPad = parseFloat(styles['padding' + side]);\n      if (!isNaN(nocontentPad)) {\n        val += nocontentPad;\n        // dump('val4', val);\n      }\n\n      // at this point, extra isn't content nor padding, so add border\n      if ( extra !== 'padding') {\n        var nocontentnopad = parseFloat(styles['border' + side + 'Width']);\n        if (!isNaN(nocontentnopad)) {\n          val += nocontentnopad;\n          // dump('val5', val);\n        }\n      }\n    }\n  }\n\n  // dump('augVal', val);\n\n  return val;\n}\n\nfunction getWidthOrHeight( elem, name, extra ) {\n  // Start with offset property, which is equivalent to the border-box value\n  var valueIsBorderBox = true,\n          val,\n          styles = getStyles(elem),\n          isBorderBox = styles['boxSizing'] === 'border-box';\n\n  // some non-html elements return undefined for offsetWidth, so check for null/undefined\n  // svg - https://bugzilla.mozilla.org/show_bug.cgi?id=649285\n  // MathML - https://bugzilla.mozilla.org/show_bug.cgi?id=491668\n  if ( val <= 0 || val == null ) {\n    // Fall back to computed then uncomputed css if necessary\n    val = styles[name];\n    if ( val < 0 || val == null ) {\n      val = elem.style[ name ];\n    }\n\n    // Computed unit is not pixels. Stop here and return.\n    if ( rnumnonpx.test(val) ) {\n      return val;\n    }\n\n    // we need the check for style in case a browser which returns unreliable values\n    // for getComputedStyle silently falls back to the reliable elem.style\n    valueIsBorderBox = isBorderBox &&\n            ( true || val === elem.style[ name ] ); // use 'true' instead of 'support.boxSizingReliable()'\n\n    // Normalize \"\", auto, and prepare for extra\n    val = parseFloat( val ) || 0;\n  }\n\n  // use the active box-sizing model to add/subtract irrelevant styles\n  var ret = ( val +\n    augmentWidthOrHeight(\n      elem,\n      name,\n      extra || ( isBorderBox ? \"border\" : \"content\" ),\n      valueIsBorderBox,\n      styles\n    )\n  );\n\n  // dump('ret', ret, val);\n  return ret;\n}\n\nvar uid = ['0', '0', '0'];\nvar uidPrefix = 'uiGrid-';\n\n/**\n *  @ngdoc service\n *  @name ui.grid.service:GridUtil\n *  \n *  @description Grid utility functions\n */\nmodule.service('gridUtil', ['$log', '$window', '$document', '$http', '$templateCache', '$timeout', '$injector', '$q', '$interpolate', 'uiGridConstants',\n  function ($log, $window, $document, $http, $templateCache, $timeout, $injector, $q, $interpolate, uiGridConstants) {\n  var s = {\n\n    getStyles: getStyles,\n\n    /**\n     * @ngdoc method\n     * @name createBoundedWrapper\n     * @methodOf ui.grid.service:GridUtil\n     *\n     * @param {object} Object to bind 'this' to\n     * @param {method} Method to bind\n     * @returns {Function} The wrapper that performs the binding\n     *\n     * @description\n     * Binds given method to given object.\n     *\n     * By means of a wrapper, ensures that ``method`` is always bound to\n     * ``object`` regardless of its calling environment.\n     * Iow, inside ``method``, ``this`` always points to ``object``.\n     *\n     * See http://alistapart.com/article/getoutbindingsituations\n     *\n     */\n    createBoundedWrapper: function(object, method) {\n        return function() {\n            return method.apply(object, arguments);\n        };\n    },\n\n\n    /**\n     * @ngdoc method\n     * @name readableColumnName\n     * @methodOf ui.grid.service:GridUtil\n     *\n     * @param {string} columnName Column name as a string\n     * @returns {string} Column name appropriately capitalized and split apart\n     *\n       @example\n       <example module=\"app\">\n        <file name=\"app.js\">\n          var app = angular.module('app', ['ui.grid']);\n\n          app.controller('MainCtrl', ['$scope', 'gridUtil', function ($scope, gridUtil) {\n            $scope.name = 'firstName';\n            $scope.columnName = function(name) {\n              return gridUtil.readableColumnName(name);\n            };\n          }]);\n        </file>\n        <file name=\"index.html\">\n          <div ng-controller=\"MainCtrl\">\n            <strong>Column name:</strong> <input ng-model=\"name\" />\n            <br>\n            <strong>Output:</strong> <span ng-bind=\"columnName(name)\"></span>\n          </div>\n        </file>\n      </example>\n     */\n    readableColumnName: function (columnName) {\n      // Convert underscores to spaces\n      if (typeof(columnName) === 'undefined' || columnName === undefined || columnName === null) { return columnName; }\n\n      if (typeof(columnName) !== 'string') {\n        columnName = String(columnName);\n      }\n\n      return columnName.replace(/_+/g, ' ')\n        // Replace a completely all-capsed word with a first-letter-capitalized version\n        .replace(/^[A-Z]+$/, function (match) {\n          return angular.lowercase(angular.uppercase(match.charAt(0)) + match.slice(1));\n        })\n        // Capitalize the first letter of words\n        .replace(/(\\w+)/g, function (match) {\n          return angular.uppercase(match.charAt(0)) + match.slice(1);\n        })\n        // Put a space in between words that have partial capilizations (i.e. 'firstName' becomes 'First Name')\n        // .replace(/([A-Z]|[A-Z]\\w+)([A-Z])/g, \"$1 $2\");\n        // .replace(/(\\w+?|\\w)([A-Z])/g, \"$1 $2\");\n        .replace(/(\\w+?(?=[A-Z]))/g, '$1 ');\n    },\n\n    /**\n     * @ngdoc method\n     * @name getColumnsFromData\n     * @methodOf ui.grid.service:GridUtil\n     * @description Return a list of column names, given a data set\n     *\n     * @param {string} data Data array for grid\n     * @returns {Object} Column definitions with field accessor and column name\n     *\n     * @example\n       <pre>\n         var data = [\n           { firstName: 'Bob', lastName: 'Jones' },\n           { firstName: 'Frank', lastName: 'Smith' }\n         ];\n\n         var columnDefs = GridUtil.getColumnsFromData(data, excludeProperties);\n\n         columnDefs == [\n          {\n            field: 'firstName',\n            name: 'First Name'\n          },\n          {\n            field: 'lastName',\n            name: 'Last Name'\n          }\n         ];\n       </pre>\n     */\n    getColumnsFromData: function (data, excludeProperties) {\n      var columnDefs = [];\n\n      if (!data || typeof(data[0]) === 'undefined' || data[0] === undefined) { return []; }\n      if (angular.isUndefined(excludeProperties)) { excludeProperties = []; }\n\n      var item = data[0];\n      \n      angular.forEach(item,function (prop, propName) {\n        if ( excludeProperties.indexOf(propName) === -1){\n          columnDefs.push({\n            name: propName\n          });\n        }\n      });\n\n      return columnDefs;\n    },\n\n    /**\n     * @ngdoc method\n     * @name newId\n     * @methodOf ui.grid.service:GridUtil\n     * @description Return a unique ID string\n     *\n     * @returns {string} Unique string\n     *\n     * @example\n       <pre>\n        var id = GridUtil.newId();\n\n        # 1387305700482;\n       </pre>\n     */\n    newId: (function() {\n      var seedId = new Date().getTime();\n      return function() {\n          return seedId += 1;\n      };\n    })(),\n\n\n    /**\n     * @ngdoc method\n     * @name getTemplate\n     * @methodOf ui.grid.service:GridUtil\n     * @description Get's template from cache / element / url\n     *\n     * @param {string|element|promise} Either a string representing the template id, a string representing the template url,\n     *   an jQuery/Angualr element, or a promise that returns the template contents to use.\n     * @returns {object} a promise resolving to template contents\n     *\n     * @example\n     <pre>\n     GridUtil.getTemplate(url).then(function (contents) {\n          alert(contents);\n        })\n     </pre>\n     */\n    getTemplate: function (template) {\n      // Try to fetch the template out of the templateCache\n      if ($templateCache.get(template)) {\n        return s.postProcessTemplate($templateCache.get(template));\n      }\n\n      // See if the template is itself a promise\n      if (template.hasOwnProperty('then')) {\n        return template.then(s.postProcessTemplate);\n      }\n\n      // If the template is an element, return the element\n      try {\n        if (angular.element(template).length > 0) {\n          return $q.when(template).then(s.postProcessTemplate);\n        }\n      }\n      catch (err){\n        //do nothing; not valid html\n      }\n\n      s.logDebug('fetching url', template);\n\n      // Default to trying to fetch the template as a url with $http\n      return $http({ method: 'GET', url: template})\n        .then(\n          function (result) {\n            var templateHtml = result.data.trim();\n            //put in templateCache for next call\n            $templateCache.put(template, templateHtml);\n            return templateHtml;\n          },\n          function (err) {\n            throw new Error(\"Could not get template \" + template + \": \" + err);\n          }\n        )\n        .then(s.postProcessTemplate);\n    },\n\n    // \n    postProcessTemplate: function (template) {\n      var startSym = $interpolate.startSymbol(),\n          endSym = $interpolate.endSymbol();\n\n      // If either of the interpolation symbols have been changed, we need to alter this template\n      if (startSym !== '{{' || endSym !== '}}') {\n        template = template.replace(/\\{\\{/g, startSym);\n        template = template.replace(/\\}\\}/g, endSym);\n      }\n\n      return $q.when(template);\n    },\n\n    /**\n     * @ngdoc method\n     * @name guessType\n     * @methodOf ui.grid.service:GridUtil\n     * @description guesses the type of an argument\n     *\n     * @param {string/number/bool/object} item variable to examine\n     * @returns {string} one of the following\n     * 'string'\n     * 'boolean'\n     * 'number'\n     * 'date'\n     * 'object'\n     */\n    guessType : function (item) {\n      var itemType = typeof(item);\n\n      // Check for numbers and booleans\n      switch (itemType) {\n        case \"number\":\n        case \"boolean\":\n        case \"string\":\n          return itemType;\n        default:\n          if (angular.isDate(item)) {\n            return \"date\";\n          }\n          return \"object\";\n      }\n    },\n\n\n  /**\n    * @ngdoc method\n    * @name elementWidth\n    * @methodOf ui.grid.service:GridUtil\n    *\n    * @param {element} element DOM element\n    * @param {string} [extra] Optional modifier for calculation. Use 'margin' to account for margins on element\n    *\n    * @returns {number} Element width in pixels, accounting for any borders, etc.\n    */\n    elementWidth: function (elem) {\n      \n    },\n\n    /**\n    * @ngdoc method\n    * @name elementHeight\n    * @methodOf ui.grid.service:GridUtil\n    *\n    * @param {element} element DOM element\n    * @param {string} [extra] Optional modifier for calculation. Use 'margin' to account for margins on element\n    *\n    * @returns {number} Element height in pixels, accounting for any borders, etc.\n    */\n    elementHeight: function (elem) {\n      \n    },\n\n    // Thanks to http://stackoverflow.com/a/13382873/888165\n    getScrollbarWidth: function() {\n        var outer = document.createElement(\"div\");\n        outer.style.visibility = \"hidden\";\n        outer.style.width = \"100px\";\n        outer.style.msOverflowStyle = \"scrollbar\"; // needed for WinJS apps\n\n        document.body.appendChild(outer);\n\n        var widthNoScroll = outer.offsetWidth;\n        // force scrollbars\n        outer.style.overflow = \"scroll\";\n\n        // add innerdiv\n        var inner = document.createElement(\"div\");\n        inner.style.width = \"100%\";\n        outer.appendChild(inner);        \n\n        var widthWithScroll = inner.offsetWidth;\n\n        // remove divs\n        outer.parentNode.removeChild(outer);\n\n        return widthNoScroll - widthWithScroll;\n    },\n\n    swap: function( elem, options, callback, args ) {\n      var ret, name,\n              old = {};\n\n      // Remember the old values, and insert the new ones\n      for ( name in options ) {\n        old[ name ] = elem.style[ name ];\n        elem.style[ name ] = options[ name ];\n      }\n\n      ret = callback.apply( elem, args || [] );\n\n      // Revert the old values\n      for ( name in options ) {\n        elem.style[ name ] = old[ name ];\n      }\n\n      return ret;\n    },\n\n    fakeElement: function( elem, options, callback, args ) {\n      var ret, name,\n          newElement = angular.element(elem).clone()[0];\n\n      for ( name in options ) {\n        newElement.style[ name ] = options[ name ];\n      }\n\n      angular.element(document.body).append(newElement);\n\n      ret = callback.call( newElement, newElement );\n\n      angular.element(newElement).remove();\n\n      return ret;\n    },\n\n    /**\n    * @ngdoc method\n    * @name normalizeWheelEvent\n    * @methodOf ui.grid.service:GridUtil\n    *\n    * @param {event} event A mouse wheel event\n    *\n    * @returns {event} A normalized event\n    *\n    * @description\n    * Given an event from this list:\n    *\n    * `wheel, mousewheel, DomMouseScroll, MozMousePixelScroll`\n    *\n    * \"normalize\" it\n    * so that it stays consistent no matter what browser it comes from (i.e. scale it correctly and make sure the direction is right.)\n    */\n    normalizeWheelEvent: function (event) {\n      // var toFix = ['wheel', 'mousewheel', 'DOMMouseScroll', 'MozMousePixelScroll'];\n      // var toBind = 'onwheel' in document || document.documentMode >= 9 ? ['wheel'] : ['mousewheel', 'DomMouseScroll', 'MozMousePixelScroll'];\n      var lowestDelta, lowestDeltaXY;\n      \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          absDeltaXY = 0,\n          fn;\n\n      // event = $.event.fix(orgEvent);\n      // event.type = 'mousewheel';\n\n      // NOTE: jQuery masks the event and stores it in the event as originalEvent\n      if (orgEvent.originalEvent) {\n        orgEvent = orgEvent.originalEvent;\n      }\n\n      // Old school scrollwheel delta\n      if ( orgEvent.wheelDelta ) { delta = orgEvent.wheelDelta; }\n      if ( orgEvent.detail )     { delta = orgEvent.detail * -1; }\n\n      // At a minimum, setup the deltaY to be delta\n      deltaY = delta;\n\n      // Firefox < 17 related to DOMMouseScroll event\n      if ( orgEvent.axis !== undefined && orgEvent.axis === orgEvent.HORIZONTAL_AXIS ) {\n          deltaY = 0;\n          deltaX = delta * -1;\n      }\n\n      // New school wheel delta (wheel event)\n      if ( orgEvent.deltaY ) {\n          deltaY = orgEvent.deltaY * -1;\n          delta  = deltaY;\n      }\n      if ( orgEvent.deltaX ) {\n          deltaX = orgEvent.deltaX;\n          delta  = deltaX * -1;\n      }\n\n      // Webkit\n      if ( orgEvent.wheelDeltaY !== undefined ) { deltaY = orgEvent.wheelDeltaY; }\n      if ( orgEvent.wheelDeltaX !== undefined ) { deltaX = orgEvent.wheelDeltaX; }\n\n      // Look for lowest delta to normalize the delta values\n      absDelta = Math.abs(delta);\n      if ( !lowestDelta || absDelta < lowestDelta ) { lowestDelta = absDelta; }\n      absDeltaXY = Math.max(Math.abs(deltaY), Math.abs(deltaX));\n      if ( !lowestDeltaXY || absDeltaXY < lowestDeltaXY ) { lowestDeltaXY = absDeltaXY; }\n\n      // Get a whole value for the deltas\n      fn     = delta > 0 ? 'floor' : 'ceil';\n      delta  = Math[fn](delta  / lowestDelta);\n      deltaX = Math[fn](deltaX / lowestDeltaXY);\n      deltaY = Math[fn](deltaY / lowestDeltaXY);\n\n      return {\n        delta: delta,\n        deltaX: deltaX,\n        deltaY: deltaY\n      };\n    },\n\n    // Stolen from Modernizr\n    // TODO: make this, and everythign that flows from it, robust\n    //http://www.stucox.com/blog/you-cant-detect-a-touchscreen/\n    isTouchEnabled: function() {\n      var bool;\n\n      if (('ontouchstart' in $window) || $window.DocumentTouch && $document instanceof DocumentTouch) {\n        bool = true;\n      }\n\n      return bool;\n    },\n\n    isNullOrUndefined: function(obj) {\n      if (obj === undefined || obj === null) {\n        return true;\n      }\n      return false;\n    },\n\n    endsWith: function(str, suffix) {\n      if (!str || !suffix || typeof str !== \"string\") {\n        return false;\n      }\n      return str.indexOf(suffix, str.length - suffix.length) !== -1;\n    },\n\n    arrayContainsObjectWithProperty: function(array, propertyName, propertyValue) {\n        var found = false;\n        angular.forEach(array, function (object) {\n            if (object[propertyName] === propertyValue) {\n                found = true;\n            }\n        });\n        return found;\n    },\n\n    // Shim requestAnimationFrame\n    requestAnimationFrame: $window.requestAnimationFrame && $window.requestAnimationFrame.bind($window) ||\n                           $window.webkitRequestAnimationFrame && $window.webkitRequestAnimationFrame.bind($window) ||\n                           function(fn) {\n                             return $timeout(fn, 10, false);\n                           },\n\n    numericAndNullSort: function (a, b) {\n      if (a === null) { return 1; }\n      if (b === null) { return -1; }\n      if (a === null && b === null) { return 0; }\n      return a - b;\n    },\n\n    // Disable ngAnimate animations on an element\n    disableAnimations: function (element) {\n      var $animate;\n      try {\n        $animate = $injector.get('$animate');\n        $animate.enabled(false, element);\n      }\n      catch (e) {}\n    },\n\n    enableAnimations: function (element) {\n      var $animate;\n      try {\n        $animate = $injector.get('$animate');\n        $animate.enabled(true, element);\n        return $animate;\n      }\n      catch (e) {}\n    },\n\n    // Blatantly stolen from Angular as it isn't exposed (yet. 2.0 maybe?)\n    nextUid: function nextUid() {\n      var index = uid.length;\n      var digit;\n\n      while (index) {\n        index--;\n        digit = uid[index].charCodeAt(0);\n        if (digit === 57 /*'9'*/) {\n          uid[index] = 'A';\n          return uidPrefix + uid.join('');\n        }\n        if (digit === 90  /*'Z'*/) {\n          uid[index] = '0';\n        } else {\n          uid[index] = String.fromCharCode(digit + 1);\n          return uidPrefix + uid.join('');\n        }\n      }\n      uid.unshift('0');\n\n      return uidPrefix + uid.join('');\n    },\n\n    // Blatantly stolen from Angular as it isn't exposed (yet. 2.0 maybe?)\n    hashKey: function hashKey(obj) {\n      var objType = typeof obj,\n          key;\n\n      if (objType === 'object' && obj !== null) {\n        if (typeof (key = obj.$$hashKey) === 'function') {\n          // must invoke on object to keep the right this\n          key = obj.$$hashKey();\n        }\n        else if (typeof(obj.$$hashKey) !== 'undefined' && obj.$$hashKey) {\n          key = obj.$$hashKey;\n        }\n        else if (key === undefined) {\n          key = obj.$$hashKey = s.nextUid();\n        }\n      }\n      else {\n        key = obj;\n      }\n\n      return objType + ':' + key;\n    },\n\n    resetUids: function () {\n      uid = ['0', '0', '0'];\n    },\n    \n    /**\n     * @ngdoc method\n     * @methodOf ui.grid.service:GridUtil\n     * @name logError\n     * @description wraps the $log method, allowing us to choose different\n     * treatment within ui-grid if we so desired.  At present we only log\n     * error messages if uiGridConstants.LOG_ERROR_MESSAGES is set to true\n     * @param {string} logMessage message to be logged to the console\n     * \n     */\n    logError: function( logMessage ){\n      if ( uiGridConstants.LOG_ERROR_MESSAGES ){\n        $log.error( logMessage );\n      }\n    },\n\n    /**\n     * @ngdoc method\n     * @methodOf ui.grid.service:GridUtil\n     * @name logWarn\n     * @description wraps the $log method, allowing us to choose different\n     * treatment within ui-grid if we so desired.  At present we only log\n     * warning messages if uiGridConstants.LOG_WARN_MESSAGES is set to true\n     * @param {string} logMessage message to be logged to the console\n     * \n     */\n    logWarn: function( logMessage ){\n      if ( uiGridConstants.LOG_WARN_MESSAGES ){\n        $log.warn( logMessage );\n      }\n    },\n\n    /**\n     * @ngdoc method\n     * @methodOf ui.grid.service:GridUtil\n     * @name logDebug\n     * @description wraps the $log method, allowing us to choose different\n     * treatment within ui-grid if we so desired.  At present we only log\n     * debug messages if uiGridConstants.LOG_DEBUG_MESSAGES is set to true\n     * \n     */\n    logDebug: function() {\n      if ( uiGridConstants.LOG_DEBUG_MESSAGES ){\n        $log.debug.apply($log, arguments);\n      }\n    }\n\n  };\n\n  ['width', 'height'].forEach(function (name) {\n    var capsName = angular.uppercase(name.charAt(0)) + name.substr(1);\n    s['element' + capsName] = function (elem, extra) {\n      var e = elem;\n      if (e && typeof(e.length) !== 'undefined' && e.length) {\n        e = elem[0];\n      }\n\n      if (e) {\n        var styles = getStyles(e);\n        return e.offsetWidth === 0 && rdisplayswap.test(styles.display) ?\n                  s.fakeElement(e, cssShow, function(newElm) {\n                    return getWidthOrHeight( newElm, name, extra );\n                  }) :\n                  getWidthOrHeight( e, name, extra );\n      }\n      else {\n        return null;\n      }\n    };\n\n    s['outerElement' + capsName] = function (elem, margin) {\n      return elem ? s['element' + capsName].call(this, elem, margin ? 'margin' : 'border') : null;\n    };\n  });\n\n  // http://stackoverflow.com/a/24107550/888165\n  s.closestElm = function closestElm(el, selector) {\n    if (typeof(el.length) !== 'undefined' && el.length) {\n      el = el[0];\n    }\n\n    var matchesFn;\n\n    // find vendor prefix\n    ['matches','webkitMatchesSelector','mozMatchesSelector','msMatchesSelector','oMatchesSelector'].some(function(fn) {\n        if (typeof document.body[fn] === 'function') {\n            matchesFn = fn;\n            return true;\n        }\n        return false;\n    });\n\n    // traverse parents\n    var parent;\n    while (el !== null) {\n      parent = el.parentElement;\n      if (parent !== null && parent[matchesFn](selector)) {\n          return parent;\n      }\n      el = parent;\n    }\n\n    return null;\n  };\n\n  s.type = function (obj) {\n    var text = Function.prototype.toString.call(obj.constructor);\n    return text.match(/function (.*?)\\(/)[1];\n  };\n\n  s.getBorderSize = function getBorderSize(elem, borderType) {\n    if (typeof(elem.length) !== 'undefined' && elem.length) {\n      elem = elem[0];\n    }\n\n    var styles = getStyles(elem);\n\n    // If a specific border is supplied, like 'top', read the 'borderTop' style property\n    if (borderType) {\n      borderType = 'border' + borderType.charAt(0).toUpperCase() + borderType.slice(1);\n    }\n    else {\n      borderType = 'border';\n    }\n\n    borderType += 'Width';\n\n    var val = parseInt(styles[borderType], 10);\n\n    if (isNaN(val)) {\n      return 0;\n    }\n    else {\n      return val;\n    }\n  };\n\n  // http://stackoverflow.com/a/22948274/888165\n  // TODO: Opera? Mobile?\n  s.detectBrowser = function detectBrowser() {\n    var userAgent = $window.navigator.userAgent;\n\n    var browsers = {chrome: /chrome/i, safari: /safari/i, firefox: /firefox/i, ie: /internet explorer|trident\\//i};\n\n    for (var key in browsers) {\n      if (browsers[key].test(userAgent)) {\n        return key;\n      }\n    }\n\n    return 'unknown';\n  };\n\n  /**\n    * @ngdoc method\n    * @name normalizeScrollLeft\n    * @methodOf ui.grid.service:GridUtil\n    *\n    * @param {element} element The element to get the `scrollLeft` from.\n    *\n    * @returns {int} A normalized scrollLeft value for the current browser.\n    *\n    * @description\n    * Browsers currently handle RTL in different ways, resulting in inconsistent scrollLeft values. This method normalizes them\n    */\n  s.normalizeScrollLeft = function normalizeScrollLeft(element) {\n    if (typeof(element.length) !== 'undefined' && element.length) {\n      element = element[0];\n    }\n\n    var browser = s.detectBrowser();\n\n    var scrollLeft = element.scrollLeft;\n    \n    var dir = s.getStyles(element)['direction'];\n\n    // IE stays normal in RTL\n    if (browser === 'ie') {\n      return scrollLeft;\n    }\n    // Chrome doesn't alter the scrollLeft value. So with RTL on a 400px-wide grid, the right-most position will still be 400 and the left-most will still be 0;\n    else if (browser === 'chrome') {\n      if (dir === 'rtl') {\n        // Get the max scroll for the element\n        var maxScrollLeft = element.scrollWidth - element.clientWidth;\n\n        // Subtract the current scroll amount from the max scroll\n        return maxScrollLeft - scrollLeft;\n      }\n      else {\n        return scrollLeft;\n      }\n    }\n    // Firefox goes negative!\n    else if (browser === 'firefox') {\n      return Math.abs(scrollLeft);\n    }\n    else {\n      // TODO(c0bra): Handle other browsers? Android? iOS? Opera?\n      return scrollLeft;\n    }\n  };\n\n  /**\n  * @ngdoc method\n  * @name normalizeScrollLeft\n  * @methodOf ui.grid.service:GridUtil\n  *\n  * @param {element} element The element to normalize the `scrollLeft` value for\n  * @param {int} scrollLeft The `scrollLeft` value to denormalize.\n  *\n  * @returns {int} A normalized scrollLeft value for the current browser.\n  *\n  * @description\n  * Browsers currently handle RTL in different ways, resulting in inconsistent scrollLeft values. This method denormalizes a value for the current browser.\n  */\n  s.denormalizeScrollLeft = function denormalizeScrollLeft(element, scrollLeft) {\n    if (typeof(element.length) !== 'undefined' && element.length) {\n      element = element[0];\n    }\n\n    var browser = s.detectBrowser();\n\n    var dir = s.getStyles(element)['direction'];\n\n    // IE stays normal in RTL\n    if (browser === 'ie') {\n      return scrollLeft;\n    }\n    // Chrome doesn't alter the scrollLeft value. So with RTL on a 400px-wide grid, the right-most position will still be 400 and the left-most will still be 0;\n    else if (browser === 'chrome') {\n      if (dir === 'rtl') {\n        // Get the max scroll for the element\n        var maxScrollLeft = element.scrollWidth - element.clientWidth;\n\n        // Subtract the current scroll amount from the max scroll\n        return maxScrollLeft - scrollLeft;\n      }\n      else {\n        return scrollLeft;\n      }\n    }\n    // Firefox goes negative!\n    else if (browser === 'firefox') {\n      if (dir === 'rtl') {\n        return scrollLeft * -1;\n      }\n      else {\n        return scrollLeft;\n      }\n    }\n    else {\n      // TODO(c0bra): Handle other browsers? Android? iOS? Opera?\n      return scrollLeft;\n    }\n  };\n\n    /**\n     * @ngdoc method\n     * @name preEval\n     * @methodOf ui.grid.service:GridUtil\n     *\n     * @param {string} path Path to evaluate\n     *\n     * @returns {string} A path that is normalized.\n     *\n     * @description\n     * Takes a field path and converts it to bracket notation to allow for special characters in path\n     * @example\n     * <pre>\n     * gridUtil.preEval('property') == 'property'\n     * gridUtil.preEval('nested.deep.prop-erty') = \"nested['deep']['prop-erty']\"\n     * </pre>\n     */\n  s.preEval = function (path) {\n    var m = uiGridConstants.BRACKET_REGEXP.exec(path);\n    if (m) {\n      return (m[1] ? s.preEval(m[1]) : m[1]) + m[2] + (m[3] ? s.preEval(m[3]) : m[3]);\n    } else {\n      path = path.replace(uiGridConstants.APOS_REGEXP, '\\\\\\'');\n      var parts = path.split(uiGridConstants.DOT_REGEXP);\n      var preparsed = [parts.shift()];    // first item must be var notation, thus skip\n      angular.forEach(parts, function (part) {\n        preparsed.push(part.replace(uiGridConstants.FUNC_REGEXP, '\\']$1'));\n      });\n      return preparsed.join('[\\'');\n    }\n  };\n\n  /**\n   * @ngdoc method\n   * @name debounce\n   * @methodOf ui.grid.service:GridUtil\n   *\n   * @param {function} func function to debounce\n   * @param {number} wait milliseconds to delay\n   * @param {bool} immediate execute before delay\n   *\n   * @returns {function} A function that can be executed as debounced function\n   *\n   * @description\n   * Copied from https://github.com/shahata/angular-debounce\n   * Takes a function, decorates it to execute only 1 time after multiple calls, and returns the decorated function\n   * @example\n   * <pre>\n   * var debouncedFunc =  gridUtil.debounce(function(){alert('debounced');}, 500);\n   * debouncedFunc();\n   * debouncedFunc();\n   * debouncedFunc();\n   * </pre>\n   */\n  s.debounce =  function (func, wait, immediate) {\n    var timeout, args, context, result;\n    function debounce() {\n      /* jshint validthis:true */\n      context = this;\n      args = arguments;\n      var later = function () {\n        timeout = null;\n        if (!immediate) {\n          result = func.apply(context, args);\n        }\n      };\n      var callNow = immediate && !timeout;\n      if (timeout) {\n        $timeout.cancel(timeout);\n      }\n      timeout = $timeout(later, wait);\n      if (callNow) {\n        result = func.apply(context, args);\n      }\n      return result;\n    }\n    debounce.cancel = function () {\n      $timeout.cancel(timeout);\n      timeout = null;\n    };\n    return debounce;\n  };\n\n  /**\n   * @ngdoc method\n   * @name throttle\n   * @methodOf ui.grid.service:GridUtil\n   *\n   * @param {function} func function to throttle\n   * @param {number} wait milliseconds to delay after first trigger\n   * @param {Object} params to use in throttle.\n   *\n   * @returns {function} A function that can be executed as throttled function\n   *\n   * @description\n   * Adapted from debounce function (above)\n   * Potential keys for Params Object are:\n   *    trailing (bool) - whether to trigger after throttle time ends if called multiple times\n   * @example\n   * <pre>\n   * var throttledFunc =  gridUtil.throttle(function(){console.log('throttled');}, 500, {trailing: true});\n   * throttledFunc(); //=> logs throttled\n   * throttledFunc(); //=> queues attempt to log throttled for ~500ms (since trailing param is truthy)\n   * throttledFunc(); //=> updates arguments to keep most-recent request, but does not do anything else.\n   * </pre>\n   */\n  s.throttle = function(func, wait, options){\n    options = options || {};\n    var lastCall = 0, queued = null, context, args;\n\n    function runFunc(endDate){\n      lastCall = +new Date();\n      func.apply(context, args);\n      $timeout(function(){ queued = null; }, 0);\n    }\n\n    return function(){\n      /* jshint validthis:true */\n      context = this;\n      args = arguments;\n      if (queued === null){\n        var sinceLast = +new Date() - lastCall;\n        if (sinceLast > wait){\n          runFunc();\n        }\n        else if (options.trailing){\n          queued = $timeout(runFunc, wait - sinceLast);\n        }\n      }\n    };\n  };\n\n  return s;\n}]);\n\n// Add 'px' to the end of a number string if it doesn't have it already\nmodule.filter('px', function() {\n  return function(str) {\n    if (str.match(/^[\\d\\.]+$/)) {\n      return str + 'px';\n    }\n    else {\n      return str;\n    }\n  };\n});\n\n})();\n\n(function(){\n  angular.module('ui.grid').config(['$provide', function($provide) {\n    $provide.decorator('i18nService', ['$delegate', function($delegate) {\n      $delegate.add('da', {\n        aggregate:{\n          label: 'artikler'\n        },\n        groupPanel:{\n          description: 'Grupér rækker udfra en kolonne ved at trække dens overskift hertil.'\n        },\n        search:{\n          placeholder: 'Søg...',\n          showingItems: 'Viste rækker:',\n          selectedItems: 'Valgte rækker:',\n          totalItems: 'Rækker totalt:',\n          size: 'Side størrelse:',\n          first: 'Første side',\n          next: 'Næste side',\n          previous: 'Forrige side',\n          last: 'Sidste side'\n        },\n        menu:{\n          text: 'Vælg kolonner:'\n        },\n        column: {\n          hide: 'Skjul kolonne'\n        },\n        aggregation: {\n          count: 'samlede rækker: ',\n          sum: 'smalede: ',\n          avg: 'gns: ',\n          min: 'min: ',\n          max: 'max: '\n        },\n        gridMenu: {\n          columns: 'Columns:',\n          importerTitle: 'Import file',\n          exporterAllAsCsv: 'Export all data as csv',\n          exporterVisibleAsCsv: 'Export visible data as csv',\n          exporterSelectedAsCsv: 'Export selected data as csv',\n          exporterAllAsPdf: 'Export all data as pdf',\n          exporterVisibleAsPdf: 'Export visible data as pdf',\n          exporterSelectedAsPdf: 'Export selected data as pdf'\n        },\n        importer: {\n          noHeaders: 'Column names were unable to be derived, does the file have a header?',\n          noObjects: 'Objects were not able to be derived, was there data in the file other than headers?',\n          invalidCsv: 'File was unable to be processed, is it valid CSV?',\n          invalidJson: 'File was unable to be processed, is it valid Json?',\n          jsonNotArray: 'Imported json file must contain an array, aborting.'\n        }\n      });\n      return $delegate;\n    }]);\n  }]);\n})();\n(function () {\n  angular.module('ui.grid').config(['$provide', function ($provide) {\n    $provide.decorator('i18nService', ['$delegate', function ($delegate) {\n      $delegate.add('de', {\n        aggregate: {\n          label: 'eintrag'\n        },\n        groupPanel: {\n          description: 'Ziehen Sie eine Spaltenüberschrift hierhin, um nach dieser Spalte zu gruppieren.'\n        },\n        search: {\n          placeholder: 'Suche...',\n          showingItems: 'Zeige Einträge:',\n          selectedItems: 'Ausgewählte Einträge:',\n          totalItems: 'Einträge gesamt:',\n          size: 'Einträge pro Seite:',\n          first: 'Erste Seite',\n          next: 'Nächste Seite',\n          previous: 'Vorherige Seite',\n          last: 'Letzte Seite'\n        },\n        menu: {\n          text: 'Spalten auswählen:'\n        },\n        sort: {\n          ascending: 'aufsteigend sortieren',\n          descending: 'absteigend sortieren',\n          remove: 'Sortierung zurücksetzen'\n        },\n        column: {\n          hide: 'Spalte ausblenden'\n        },\n        aggregation: {\n          count: 'Zeilen insgesamt: ',\n          sum: 'gesamt: ',\n          avg: 'Durchschnitt: ',\n          min: 'min: ',\n          max: 'max: '\n        },\n        gridMenu: {\n          columns: 'Spalten:',\n          importerTitle: 'Datei importieren',\n          exporterAllAsCsv: 'Alle Daten als CSV exportieren',\n          exporterVisibleAsCsv: 'sichtbare Daten als CSV exportieren',\n          exporterSelectedAsCsv: 'markierte Daten als CSV exportieren',\n          exporterAllAsPdf: 'Alle Daten als PDF exportieren',\n          exporterVisibleAsPdf: 'sichtbare Daten als PDF exportieren',\n          exporterSelectedAsPdf: 'markierte Daten als CSV exportieren'\n        },\n        importer: {\n          noHeaders: 'Es konnten keine Spaltennamen ermittelt werden. Sind in der Datei Spaltendefinitionen enthalten?',\n          noObjects: 'Es konnten keine Zeileninformationen gelesen werden, Sind in der Datei außer den Spaltendefinitionen auch Daten enthalten?',\n          invalidCsv: 'Die Datei konnte nicht eingelesen werden, ist es eine gültige CSV-Datei?',\n          invalidJson: 'Die Datei konnte nicht eingelesen werden. Enthält sie gültiges JSON?',\n          jsonNotArray: 'Die importierte JSON-Datei muß ein Array enthalten. Breche Import ab.'\n        }\n      });\n      return $delegate;\n    }]);\n  }]);\n})();\n\n(function () {\n  angular.module('ui.grid').config(['$provide', function($provide) {\n    $provide.decorator('i18nService', ['$delegate', function($delegate) {\n      $delegate.add('en', {\n        aggregate: {\n          label: 'items'\n        },\n        groupPanel: {\n          description: 'Drag a column header here and drop it to group by that column.'\n        },\n        search: {\n          placeholder: 'Search...',\n          showingItems: 'Showing Items:',\n          selectedItems: 'Selected Items:',\n          totalItems: 'Total Items:',\n          size: 'Page Size:',\n          first: 'First Page',\n          next: 'Next Page',\n          previous: 'Previous Page',\n          last: 'Last Page'\n        },\n        menu: {\n          text: 'Choose Columns:'\n        },\n        sort: {\n          ascending: 'Sort Ascending',\n          descending: 'Sort Descending',\n          remove: 'Remove Sort'\n        },\n        column: {\n          hide: 'Hide Column'\n        },\n        aggregation: {\n          count: 'total rows: ',\n          sum: 'total: ',\n          avg: 'avg: ',\n          min: 'min: ',\n          max: 'max: '\n        },\n        pinning: {\n         pinLeft: 'Pin Left',\n          pinRight: 'Pin Right',\n          unpin: 'Unpin'\n        },\n        gridMenu: {\n          columns: 'Columns:',\n          importerTitle: 'Import file',\n          exporterAllAsCsv: 'Export all data as csv',\n          exporterVisibleAsCsv: 'Export visible data as csv',\n          exporterSelectedAsCsv: 'Export selected data as csv',\n          exporterAllAsPdf: 'Export all data as pdf',\n          exporterVisibleAsPdf: 'Export visible data as pdf',\n          exporterSelectedAsPdf: 'Export selected data as pdf'\n        },\n        importer: {\n          noHeaders: 'Column names were unable to be derived, does the file have a header?',\n          noObjects: 'Objects were not able to be derived, was there data in the file other than headers?',\n          invalidCsv: 'File was unable to be processed, is it valid CSV?',\n          invalidJson: 'File was unable to be processed, is it valid Json?',\n          jsonNotArray: 'Imported json file must contain an array, aborting.'\n        },\n        pagination: {\n          sizes: 'items per page',\n          totalItems: 'items'\n        }\n      });\n      return $delegate;\n    }]);\n  }]);\n})();\n\n(function () {\n  angular.module('ui.grid').config(['$provide', function($provide) {\n    $provide.decorator('i18nService', ['$delegate', function($delegate) {\n      $delegate.add('es', {\n        aggregate: {\n          label: 'Artículos'\n        },\n        groupPanel: {\n          description: 'Arrastre un encabezado de columna aquí y suéltelo para agrupar por esa columna.'\n        },\n        search: {\n          placeholder: 'Buscar...',\n          showingItems: 'Artículos Mostrados:',\n          selectedItems: 'Artículos Seleccionados:',\n          totalItems: 'Artículos Totales:',\n          size: 'Tamaño de Página:',\n          first: 'Primera Página',\n          next: 'Página Siguiente',\n          previous: 'Página Anterior',\n          last: 'Última Página'\n        },\n        menu: {\n          text: 'Elegir columnas:'\n        },\n        sort: {\n          ascending: 'Orden Ascendente',\n          descending: 'Orden Descendente',\n          remove: 'Sin Ordenar'\n        },\n        column: {\n          hide: 'Ocultar la columna'\n        },\n        aggregation: {\n          count: 'filas totales: ',\n          sum: 'total: ',\n          avg: 'media: ',\n          min: 'min: ',\n          max: 'max: '\n        },\n        pinning: {\n          pinLeft: 'Fijar a la Izquierda',\n          pinRight: 'Fijar a la Derecha',\n          unpin: 'Quitar Fijación'\n        },\n        gridMenu: {\n          columns: 'Columnas:',\n          importerTitle: 'Importar archivo',\n          exporterAllAsCsv: 'Exportar todo como csv',\n          exporterVisibleAsCsv: 'Exportar vista como csv',\n          exporterSelectedAsCsv: 'Exportar selección como csv',\n          exporterAllAsPdf: 'Exportar todo como pdf',\n          exporterVisibleAsPdf: 'Exportar vista como pdf',\n          exporterSelectedAsPdf: 'Exportar selección como pdf'\n        },\n        importer: {\n          noHeaders: 'No fue posible derivar los nombres de las columnas, ¿tiene encabezados el archivo?',\n          noObjects: 'No fue posible obtener registros, ¿contiene datos el archivo, aparte de los encabezados?',\n          invalidCsv: 'No fue posible procesar el archivo, ¿es un CSV válido?',\n          invalidJson: 'No fue posible procesar el archivo, ¿es un Json válido?',\n          jsonNotArray: 'El archivo json importado debe contener un array, abortando.'\n        }\n      });\n      return $delegate;\n    }]);\n}]);\n})();\n\n(function () {\n  angular.module('ui.grid').config(['$provide', function($provide) {\n    $provide.decorator('i18nService', ['$delegate', function($delegate) {\n      $delegate.add('fa', {\n        aggregate: {\n          label: 'موردها'\n        },\n        groupPanel: {\n          description: 'یک عنوان ستون اینجا را بردار و به گروهی از آن ستون بیانداز.'\n        },\n        search: {\n          placeholder: 'جستجو...',\n          showingItems: 'نمایش موردها:',\n          selectedItems: 'موردهای انتخاب\\u200cشده:',\n          totalItems: 'همهٔ موردها:',\n          size: 'اندازهٔ صفحه:',\n          first: 'صفحهٔ اول',\n          next: 'صفحهٔ بعد',\n          previous: 'صفحهٔ قبل',\n          last: 'آخرین صفحه'\n        },\n        menu: {\n          text: 'انتخاب ستون\\u200cها:'\n        },\n        column: {\n          hide: 'ستون پنهان کن'\n        },\n        aggregation: {\n          count: 'total rows: ',\n          sum: 'total: ',\n          avg: 'avg: ',\n          min: 'min: ',\n          max: 'max: '\n        },\n        gridMenu: {\n          columns: 'Columns:',\n          importerTitle: 'Import file',\n          exporterAllAsCsv: 'Export all data as csv',\n          exporterVisibleAsCsv: 'Export visible data as csv',\n          exporterSelectedAsCsv: 'Export selected data as csv',\n          exporterAllAsPdf: 'Export all data as pdf',\n          exporterVisibleAsPdf: 'Export visible data as pdf',\n          exporterSelectedAsPdf: 'Export selected data as pdf'\n        },\n        importer: {\n          noHeaders: 'Column names were unable to be derived, does the file have a header?',\n          noObjects: 'Objects were not able to be derived, was there data in the file other than headers?',\n          invalidCsv: 'File was unable to be processed, is it valid CSV?',\n          invalidJson: 'File was unable to be processed, is it valid Json?',\n          jsonNotArray: 'Imported json file must contain an array, aborting.'\n        }\n      });\n      return $delegate;\n    }]);\n}]);\n})();\n(function () {\n  angular.module('ui.grid').config(['$provide', function($provide) {\n    $provide.decorator('i18nService', ['$delegate', function($delegate) {\n      $delegate.add('fi', {\n        aggregate: {\n          label: 'rivit'\n        },\n        groupPanel: {\n          description: 'Raahaa ja pudota otsikko tähän ryhmittääksesi sarakkeen mukaan.'\n        },\n        search: {\n          placeholder: 'Hae...',\n          showingItems: 'Näytetään rivejä:',\n          selectedItems: 'Valitut rivit:',\n          totalItems: 'Rivejä yht.:',\n          size: 'Näytä:',\n          first: 'Ensimmäinen sivu',\n          next: 'Seuraava sivu',\n          previous: 'Edellinen sivu',\n          last: 'Viimeinen sivu'\n        },\n        menu: {\n          text: 'Valitse sarakkeet:'\n        },\n        sort: {\n          ascending: 'Järjestä nouseva',\n          descending: 'Järjestä laskeva',\n          remove: 'Poista järjestys'\n        },\n        column: {\n          hide: 'Piilota sarake'\n        },\n        aggregation: {\n          count: 'Rivejä yht.: ',\n          sum: 'Summa: ',\n          avg: 'K.a.: ',\n          min: 'Min: ',\n          max: 'Max: '\n        },\n        pinning: {\n         pinLeft: 'Lukitse vasemmalle',\n          pinRight: 'Lukitse oikealle',\n          unpin: 'Poista lukitus'\n        },\n        gridMenu: {\n          columns: 'Sarakkeet:',\n          importerTitle: 'Tuo tiedosto',\n          exporterAllAsCsv: 'Vie tiedot csv-muodossa',\n          exporterVisibleAsCsv: 'Vie näkyvä tieto csv-muodossa',\n          exporterSelectedAsCsv: 'Vie valittu tieto csv-muodossa',\n          exporterAllAsPdf: 'Vie tiedot pdf-muodossa',\n          exporterVisibleAsPdf: 'Vie näkyvä tieto pdf-muodossa',\n          exporterSelectedAsPdf: 'Vie valittu tieto pdf-muodossa'\n        },\n        importer: {\n          noHeaders: 'Sarakkeen nimiä ei voitu päätellä, onko tiedostossa otsikkoriviä?',\n          noObjects: 'Tietoja ei voitu lukea, onko tiedostossa muuta kuin otsikkot?',\n          invalidCsv: 'Tiedostoa ei voitu käsitellä, oliko se CSV-muodossa?',\n          invalidJson: 'Tiedostoa ei voitu käsitellä, oliko se JSON-muodossa?',\n          jsonNotArray: 'Tiedosto ei sisältänyt taulukkoa, lopetetaan.'\n        }\n      });\n      return $delegate;\n    }]);\n  }]);\n})();\n\n(function () {\n  angular.module('ui.grid').config(['$provide', function($provide) {\n    $provide.decorator('i18nService', ['$delegate', function($delegate) {\n      $delegate.add('fr', {\n        aggregate: {\n          label: 'articles'\n        },\n        groupPanel: {\n          description: 'Faites glisser un en-tête de colonne ici et déposez-le vers un groupe par cette colonne.'\n        },\n        search: {\n          placeholder: 'Recherche...',\n          showingItems: 'Articles Affichage des:',\n          selectedItems: 'Éléments Articles:',\n          totalItems: 'Nombre total d\\'articles:',\n          size: 'Taille de page:',\n          first: 'Première page',\n          next: 'Page Suivante',\n          previous: 'Page précédente',\n          last: 'Dernière page'\n        },\n        menu: {\n          text: 'Choisir des colonnes:'\n        },\n        sort: {\n          ascending: 'Trier par ordre croissant',\n          descending: 'Trier par ordre décroissant',\n          remove: 'Enlever le tri'\n        },\n        column: {\n          hide: 'Cacher la colonne'\n        },\n        aggregation: {\n          count: 'total lignes: ',\n          sum: 'total: ',\n          avg: 'moy: ',\n          min: 'min: ',\n          max: 'max: '\n        },\n        pinning: {\n          pinLeft: 'Épingler à gauche',\n          pinRight: 'Épingler à droite',\n          unpin: 'Détacher'\n        },\n        gridMenu: {\n          columns: 'Colonnes:',\n          importerTitle: 'Importer un fichier',\n          exporterAllAsCsv: 'Exporter toutes les données en CSV',\n          exporterVisibleAsCsv: 'Exporter les données visibles en CSV',\n          exporterSelectedAsCsv: 'Exporter les données sélectionnées en CSV',\n          exporterAllAsPdf: 'Exporter toutes les données en PDF',\n          exporterVisibleAsPdf: 'Exporter les données visibles en PDF',\n          exporterSelectedAsPdf: 'Exporter les données sélectionnées en PDF'\n        },\n        importer: {\n          noHeaders: 'Impossible de déterminer le nom des colonnes, le fichier possède-t-il un en-tête ?',\n          noObjects: 'Aucun objet trouvé, le fichier possède-t-il des données autres que l\\'en-tête ?',\n          invalidCsv: 'Le fichier n\\'a pas pu être traité, le CSV est-il valide ?',\n          invalidJson: 'Le fichier n\\'a pas pu être traité, le JSON est-il valide ?',\n          jsonNotArray: 'Le fichier JSON importé doit contenir un tableau. Abandon.'\n        },\n        pagination: {\n          sizes: 'articles par page',\n          totalItems: 'articles'\n        }\n      });\n      return $delegate;\n    }]);\n}]);\n})();\n(function () {\n  angular.module('ui.grid').config(['$provide', function ($provide) {\n    $provide.decorator('i18nService', ['$delegate', function ($delegate) {\n      $delegate.add('he', {\n        aggregate: {\n          label: 'items'\n        },\n        groupPanel: {\n          description: 'גרור עמודה לכאן ושחרר בכדי לקבץ עמודה זו.'\n        },\n        search: {\n          placeholder: 'חפש...',\n          showingItems: 'מציג:',\n          selectedItems: 'סה\"כ נבחרו:',\n          totalItems: 'סה\"כ רשומות:',\n          size: 'תוצאות בדף:',\n          first: 'דף ראשון',\n          next: 'דף הבא',\n          previous: 'דף קודם',\n          last: 'דף אחרון'\n        },\n        menu: {\n          text: 'בחר עמודות:'\n        },\n        sort: {\n          ascending: 'סדר עולה',\n          descending: 'סדר יורד',\n          remove: 'בטל'\n        },\n        column: {\n          hide: 'טור הסתר'\n        },\n        aggregation: {\n          count: 'total rows: ',\n          sum: 'total: ',\n          avg: 'avg: ',\n          min: 'min: ',\n          max: 'max: '\n        },\n        gridMenu: {\n          columns: 'Columns:',\n          importerTitle: 'Import file',\n          exporterAllAsCsv: 'Export all data as csv',\n          exporterVisibleAsCsv: 'Export visible data as csv',\n          exporterSelectedAsCsv: 'Export selected data as csv',\n          exporterAllAsPdf: 'Export all data as pdf',\n          exporterVisibleAsPdf: 'Export visible data as pdf',\n          exporterSelectedAsPdf: 'Export selected data as pdf'\n        },\n        importer: {\n          noHeaders: 'Column names were unable to be derived, does the file have a header?',\n          noObjects: 'Objects were not able to be derived, was there data in the file other than headers?',\n          invalidCsv: 'File was unable to be processed, is it valid CSV?',\n          invalidJson: 'File was unable to be processed, is it valid Json?',\n          jsonNotArray: 'Imported json file must contain an array, aborting.'\n        }\n      });\n      return $delegate;\n    }]);\n  }]);\n})();\n(function () {\n  angular.module('ui.grid').config(['$provide', function($provide) {\n    $provide.decorator('i18nService', ['$delegate', function($delegate) {\n      $delegate.add('it', {\n        aggregate: {\n          label: 'elementi'\n        },\n        groupPanel: {\n          description: 'Trascina un\\'intestazione all\\'interno del gruppo della colonna.'\n        },\n        search: {\n          placeholder: 'Ricerca...',\n          showingItems: 'Mostra:',\n          selectedItems: 'Selezionati:',\n          totalItems: 'Totali:',\n          size: 'Tot Pagine:',\n          first: 'Prima',\n          next: 'Prossima',\n          previous: 'Precedente',\n          last: 'Ultima'\n        },\n        menu: {\n          text: 'Scegli le colonne:'\n        },\n        sort: {\n          ascending: 'Asc.',\n          descending: 'Desc.',\n          remove: 'Annulla ordinamento'\n        },\n        column: {\n          hide: 'Nascondi'\n        },\n        aggregation: {\n          count: 'righe totali: ',\n          sum: 'tot: ',\n          avg: 'media: ',\n          min: 'minimo: ',\n          max: 'massimo: '\n        },\n        pinning: {\n         pinLeft: 'Blocca a sx',\n          pinRight: 'Blocca a dx',\n          unpin: 'Blocca in alto'\n        },\n        gridMenu: {\n          columns: 'Colonne:',\n          importerTitle: 'Importa',\n          exporterAllAsCsv: 'Esporta tutti i dati in CSV',\n          exporterVisibleAsCsv: 'Esporta i dati visibili in CSV',\n          exporterSelectedAsCsv: 'Esporta i dati selezionati in CSV',\n          exporterAllAsPdf: 'Esporta tutti i dati in PDF',\n          exporterVisibleAsPdf: 'Esporta i dati visibili in PDF',\n          exporterSelectedAsPdf: 'Esporta i dati selezionati in PDF'\n        },\n        importer: {\n          noHeaders: 'Impossibile reperire i nomi delle colonne, sicuro che siano indicati all\\'interno del file?',\n          noObjects: 'Impossibile reperire gli oggetti, sicuro che siano indicati all\\'interno del file?',\n          invalidCsv: 'Impossibile elaborare il file, sicuro che sia un CSV?',\n          invalidJson: 'Impossibile elaborare il file, sicuro che sia un JSON valido?',\n          jsonNotArray: 'Errore! Il file JSON da importare deve contenere un array.'\n        }\n      });\n      return $delegate;\n    }]);\n  }]);\n})();\n(function() {\n  angular.module('ui.grid').config(['$provide', function($provide) {\n    $provide.decorator('i18nService', ['$delegate', function($delegate) {\n      $delegate.add('ja', {\n        aggregate: {\n          label: '件'\n        },\n        groupPanel: {\n          description: '列名部分をここにドラッグアンドドロップすることで列ごとにグループ分けを行うことができます。'\n        },\n        search: {\n          placeholder: '検索...',\n          showingItems: '絞込み件数:',\n          selectedItems: '選択件数:',\n          totalItems: '全件数:',\n          size: 'ページサイズ: ',\n          first: '最初のページ',\n          next: '次のページ',\n          previous: '前のページ',\n          last: '最後のページ'\n        },\n        menu: {\n          text: '列選択:'\n        },\n        sort: {\n          ascending: '昇順ソート',\n          descending: '降順ソート',\n          remove: 'ソート取消'\n        },\n        column: {\n          hide: '列を隠す'\n        },\n        aggregation: {\n          count: '合計件数: ',\n          sum: '合計: ',\n          avg: '平均: ',\n          min: '最小値: ',\n          max: '最大値: '\n        },\n        pinning: {\n          pinLeft: '左にピン留め',\n          pinRight: '右にピン留め',\n          unpin: 'ピン留め取消'\n        },\n        gridMenu: {\n          columns: '列:',\n          importerTitle: 'インポートファイル',\n          exporterAllAsCsv: '全てのデータをCSV形式でエクスポート',\n          exporterVisibleAsCsv: '絞込み済みデータをCSV形式でエクスポート',\n          exporterSelectedAsCsv: '選択しているデータをCSV形式でエクスポート',\n          exporterAllAsPdf: '全てのデータをPDFでエクスポート',\n          exporterVisibleAsPdf: '絞込み済みデータをPDFでエクスポート',\n          exporterSelectedAsPdf: '選択しているデータをPDFでエクスポート'\n        },\n        importer: {\n          noHeaders: '列名が抽出できません。ヘッダーは設定されていますか？',\n          noObjects: 'データが抽出できません。ファイルにデータは含まれていますか？',\n          invalidCsv: '処理を行うことができません。ファイルは有効なCSVファイルですか？',\n          invalidJson: '処理を行うことができません。ファイルは有効なJSONファイルですか？',\n          jsonNotArray: 'JSONファイルは配列を含んでいる必要があります。処理を中断します。'\n        },\n        pagination: {\n          sizes: '件 / ページ',\n          totalItems: '件'\n        }\n      });\n      return $delegate;\n    }]);\n  }]);\n})();\n\n(function () {\n  angular.module('ui.grid').config(['$provide', function($provide) {\n    $provide.decorator('i18nService', ['$delegate', function($delegate) {\n      $delegate.add('nl', {\n        aggregate: {\n          label: 'items'\n        },\n        groupPanel: {\n          description: 'Sleep hier een kolomnaam heen om op te groeperen.'\n        },\n        search: {\n          placeholder: 'Zoeken...',\n          showingItems: 'Getoonde items:',\n          selectedItems: 'Geselecteerde items:',\n          totalItems: 'Totaal aantal items:',\n          size: 'Items per pagina:',\n          first: 'Eerste pagina',\n          next: 'Volgende pagina',\n          previous: 'Vorige pagina',\n          last: 'Laatste pagina'\n        },\n        menu: {\n          text: 'Kies kolommen:'\n        },\n        sort: {\n          ascending: 'Sorteer oplopend',\n          descending: 'Sorteer aflopend',\n          remove: 'Verwijder sortering'\n        },\n        column: {\n          hide: 'Verberg kolom'\n        },\n        aggregation: {\n          count: 'Aantal rijen: ',\n          sum: 'Som: ',\n          avg: 'Gemiddelde: ',\n          min: 'Min: ',\n          max: 'Max: '\n        },\n        pinning: {\n          pinLeft: 'Zet links vast',\n          pinRight: 'Zet rechts vast',\n          unpin: 'Maak los'\n        },\n        gridMenu: {\n          columns: 'Kolommen:',\n          importerTitle: 'Importeer bestand',\n          exporterAllAsCsv: 'Exporteer alle data als csv',\n          exporterVisibleAsCsv: 'Exporteer zichtbare data als csv',\n          exporterSelectedAsCsv: 'Exporteer geselecteerde data als csv',\n          exporterAllAsPdf: 'Exporteer alle data als pdf',\n          exporterVisibleAsPdf: 'Exporteer zichtbare data als pdf',\n          exporterSelectedAsPdf: 'Exporteer geselecteerde data als pdf'\n        },\n        importer: {\n          noHeaders: 'Kolomnamen kunnen niet worden afgeleid. Heeft het bestand een header?',\n          noObjects: 'Objecten kunnen niet worden afgeleid. Bevat het bestand data naast de headers?',\n          invalidCsv: 'Het bestand kan niet verwerkt worden. Is het een valide csv bestand?',\n          invalidJson: 'Het bestand kan niet verwerkt worden. Is het valide json?',\n          jsonNotArray: 'Het json bestand moet een array bevatten. De actie wordt geannuleerd.'\n        }\n      });\n      return $delegate;\n    }]);\n  }]);\n})();\n(function () {\n  angular.module('ui.grid').config(['$provide', function($provide) {\n    $provide.decorator('i18nService', ['$delegate', function($delegate) {\n      $delegate.add('pt-br', {\n        aggregate: {\n          label: 'itens'\n        },\n        groupPanel: {\n          description: 'Arraste e solte uma coluna aqui para agrupar por essa coluna'\n        },\n        search: {\n          placeholder: 'Procurar...',\n          showingItems: 'Mostrando os Itens:',\n          selectedItems: 'Items Selecionados:',\n          totalItems: 'Total de Itens:',\n          size: 'Tamanho da Página:',\n          first: 'Primeira Página',\n          next: 'Próxima Página',\n          previous: 'Página Anterior',\n          last: 'Última Página'\n        },\n        menu: {\n          text: 'Selecione as colunas:'\n        },\n        sort: {\n          ascending: 'Ordenar Ascendente',\n          descending: 'Ordenar Descendente',\n          remove: 'Remover Ordenação'\n        },\n        column: {\n          hide: 'Esconder coluna'\n        },\n        aggregation: {\n          count: 'total de linhas: ',\n          sum: 'total: ',\n          avg: 'med: ',\n          min: 'min: ',\n          max: 'max: '\n        },\n        pinning: {\n          pinLeft: 'Fixar Esquerda',\n          pinRight: 'Fixar Direita',\n          unpin: 'Desprender'\n        },\n        gridMenu: {\n          columns: 'Colunas:',\n          exporterAllAsCsv: 'Exportar todos os dados como csv',\n          exporterVisibleAsCsv: 'Exportar dados visíveis como csv',\n          exporterSelectedAsCsv: 'Exportar dados selecionados como csv',\n          exporterAllAsPdf: 'Exportar todos os dados como pdf',\n          exporterVisibleAsPdf: 'Exportar dados visíveis como pdf',\n          exporterSelectedAsPdf: 'Exportar dados selecionados como pdf'\n        },\n        importer: {\n          noHeaders: 'Nomes de colunas não puderam ser derivados. O arquivo tem um cabeçalho?',\n          noObjects: 'Objetos não puderam ser derivados. Havia dados no arquivo, além dos cabeçalhos?',\n          invalidCsv: 'Arquivo não pode ser processado. É um CSV válido?',\n          invalidJson: 'Arquivo não pode ser processado. É um Json válido?',\n          jsonNotArray: 'Arquivo json importado tem que conter um array. Abortando.'\n        }\n      });\n      return $delegate;\n    }]);\n}]);\n})();\n(function () {\n  angular.module('ui.grid').config(['$provide', function($provide) {\n    $provide.decorator('i18nService', ['$delegate', function($delegate) {\n      $delegate.add('ru', {\n        aggregate: {\n          label: 'элементы'\n        },\n        groupPanel: {\n          description: 'Для группировки по столбцу перетащите сюда его название.'\n        },\n        search: {\n          placeholder: 'Поиск...',\n          showingItems: 'Показать элементы:',\n          selectedItems: 'Выбранные элементы:',\n          totalItems: 'Всего элементов:',\n          size: 'Размер страницы:',\n          first: 'Первая страница',\n          next: 'Следующая страница',\n          previous: 'Предыдущая страница',\n          last: 'Последняя страница'\n        },\n        menu: {\n          text: 'Выбрать столбцы:'\n        },\n        sort: {\n          ascending: 'По возрастанию',\n          descending: 'По убыванию',\n          remove: 'Убрать сортировку'\n        },\n        column: {\n          hide: 'спрятать столбец'\n        },\n        aggregation: {\n          count: 'всего строк: ',\n          sum: 'итого: ',\n          avg: 'среднее: ',\n          min: 'мин: ',\n          max: 'макс: '\n        },\n        gridMenu: {\n          columns: 'Столбцы:',\n          importerTitle: 'Import file',\n          exporterAllAsCsv: 'Экспортировать всё в CSV',\n          exporterVisibleAsCsv: 'Экспортировать видимые данные в CSV',\n          exporterSelectedAsCsv: 'Экспортировать выбранные данные в CSV',\n          exporterAllAsPdf: 'Экспортировать всё в PDF',\n          exporterVisibleAsPdf: 'Экспортировать видимые данные в PDF',\n          exporterSelectedAsPdf: 'Экспортировать выбранные данные в PDF'\n        },\n        importer: {\n          noHeaders: 'Column names were unable to be derived, does the file have a header?',\n          noObjects: 'Objects were not able to be derived, was there data in the file other than headers?',\n          invalidCsv: 'File was unable to be processed, is it valid CSV?',\n          invalidJson: 'File was unable to be processed, is it valid Json?',\n          jsonNotArray: 'Imported json file must contain an array, aborting.'\n        }\n      });\n      return $delegate;\n    }]);\n  }]);\n})();\n\n(function () {\n  angular.module('ui.grid').config(['$provide', function($provide) {\n    $provide.decorator('i18nService', ['$delegate', function($delegate) {\n      $delegate.add('sk', {\n        aggregate: {\n          label: 'items'\n        },\n        groupPanel: {\n          description: 'Pretiahni sem názov stĺpca pre zoskupenie podľa toho stĺpca.'\n        },\n        search: {\n          placeholder: 'Hľadaj...',\n          showingItems: 'Zobrazujem položky:',\n          selectedItems: 'Vybraté položky:',\n          totalItems: 'Počet položiek:',\n          size: 'Počet:',\n          first: 'Prvá strana',\n          next: 'Ďalšia strana',\n          previous: 'Predchádzajúca strana',\n          last: 'Posledná strana'\n        },\n        menu: {\n          text: 'Vyberte stĺpce:'\n        },\n        sort: {\n          ascending: 'Zotriediť vzostupne',\n          descending: 'Zotriediť zostupne',\n          remove: 'Vymazať triedenie'\n        },\n        aggregation: {\n          count: 'total rows: ',\n          sum: 'total: ',\n          avg: 'avg: ',\n          min: 'min: ',\n          max: 'max: '\n        },\n        gridMenu: {\n          columns: 'Columns:',\n          importerTitle: 'Import file',\n          exporterAllAsCsv: 'Export all data as csv',\n          exporterVisibleAsCsv: 'Export visible data as csv',\n          exporterSelectedAsCsv: 'Export selected data as csv',\n          exporterAllAsPdf: 'Export all data as pdf',\n          exporterVisibleAsPdf: 'Export visible data as pdf',\n          exporterSelectedAsPdf: 'Export selected data as pdf'\n        },\n        importer: {\n          noHeaders: 'Column names were unable to be derived, does the file have a header?',\n          noObjects: 'Objects were not able to be derived, was there data in the file other than headers?',\n          invalidCsv: 'File was unable to be processed, is it valid CSV?',\n          invalidJson: 'File was unable to be processed, is it valid Json?',\n          jsonNotArray: 'Imported json file must contain an array, aborting.'\n        }\n      });\n      return $delegate;\n    }]);\n  }]);\n})();\n\n(function () {\n  angular.module('ui.grid').config(['$provide', function($provide) {\n    $provide.decorator('i18nService', ['$delegate', function($delegate) {\n      $delegate.add('sv', {\n        aggregate: {\n          label: 'Artiklar'\n        },\n        groupPanel: {\n          description: 'Dra en kolumnrubrik hit och släpp den för att gruppera efter den kolumnen.'\n        },\n        search: {\n          placeholder: 'Sök...',\n          showingItems: 'Visar artiklar:',\n          selectedItems: 'Valda artiklar:',\n          totalItems: 'Antal artiklar:',\n          size: 'Sidstorlek:',\n          first: 'Första sidan',\n          next: 'Nästa sida',\n          previous: 'Föregående sida',\n          last: 'Sista sidan'\n        },\n        menu: {\n          text: 'Välj kolumner:'\n        },\n        sort: {\n          ascending: 'Sortera stigande',\n          descending: 'Sortera fallande',\n          remove: 'Inaktivera sortering'\n        },\n        column: {\n          hide: 'Göm kolumn'\n        },\n        aggregation: {\n          count: 'Antal rader: ',\n          sum: 'Summa: ',\n          avg: 'Genomsnitt: ',\n          min: 'Min: ',\n          max: 'Max: '\n        },\n        pinning: {\n          pinLeft: 'Fäst vänster',\n          pinRight: 'Fäst höger',\n          unpin: 'Lösgör'\n        },\n        gridMenu: {\n          columns: 'Kolumner:',\n          importerTitle: 'Importera fil',\n          exporterAllAsCsv: 'Exportera all data som CSV',\n          exporterVisibleAsCsv: 'Exportera synlig data som CSV',\n          exporterSelectedAsCsv: 'Exportera markerad data som CSV',\n          exporterAllAsPdf: 'Exportera all data som PDF',\n          exporterVisibleAsPdf: 'Exportera synlig data som PDF',\n          exporterSelectedAsPdf: 'Exportera markerad data som PDF'\n        },\n        importer: {\n          noHeaders: 'Kolumnnamn kunde inte härledas. Har filen ett sidhuvud?',\n          noObjects: 'Objekt kunde inte härledas. Har filen data undantaget sidhuvud?',\n          invalidCsv: 'Filen kunde inte behandlas, är den en giltig CSV?',\n          invalidJson: 'Filen kunde inte behandlas, är den en giltig JSON?',\n          jsonNotArray: 'Importerad JSON-fil måste innehålla ett fält. Import avbruten.'\n        },\n        pagination: {\n          sizes: 'Artiklar per sida',\n          totalItems: 'Artiklar'\n        }\n      });\n      return $delegate;\n    }]);\n  }]);\n})();\n\n/**\n * @ngdoc overview\n * @name ui.grid.i18n\n * @description\n *\n *  # ui.grid.i18n\n * This module provides i18n functions to ui.grid and any application that wants to use it\n\n *\n * <div doc-module-components=\"ui.grid.i18n\"></div>\n */\n\n(function () {\n  var DIRECTIVE_ALIASES = ['uiT', 'uiTranslate'];\n  var FILTER_ALIASES = ['t', 'uiTranslate'];\n\n  var module = angular.module('ui.grid.i18n');\n\n\n  /**\n   *  @ngdoc object\n   *  @name ui.grid.i18n.constant:i18nConstants\n   *\n   *  @description constants available in i18n module\n   */\n  module.constant('i18nConstants', {\n    MISSING: '[MISSING]',\n    UPDATE_EVENT: '$uiI18n',\n\n    LOCALE_DIRECTIVE_ALIAS: 'uiI18n',\n    // default to english\n    DEFAULT_LANG: 'en'\n  });\n\n//    module.config(['$provide', function($provide) {\n//        $provide.decorator('i18nService', ['$delegate', function($delegate) {}])}]);\n\n  /**\n   *  @ngdoc service\n   *  @name ui.grid.i18n.service:i18nService\n   *\n   *  @description Services for i18n\n   */\n  module.service('i18nService', ['$log', 'i18nConstants', '$rootScope',\n    function ($log, i18nConstants, $rootScope) {\n\n      var langCache = {\n        _langs: {},\n        current: null,\n        get: function (lang) {\n          return this._langs[lang.toLowerCase()];\n        },\n        add: function (lang, strings) {\n          var lower = lang.toLowerCase();\n          if (!this._langs[lower]) {\n            this._langs[lower] = {};\n          }\n          angular.extend(this._langs[lower], strings);\n        },\n        getAllLangs: function () {\n          var langs = [];\n          if (!this._langs) {\n            return langs;\n          }\n\n          for (var key in this._langs) {\n            langs.push(key);\n          }\n\n          return langs;\n        },\n        setCurrent: function (lang) {\n          this.current = lang.toLowerCase();\n        },\n        getCurrentLang: function () {\n          return this.current;\n        }\n      };\n\n      var service = {\n\n        /**\n         * @ngdoc service\n         * @name add\n         * @methodOf ui.grid.i18n.service:i18nService\n         * @description  Adds the languages and strings to the cache. Decorate this service to\n         * add more translation strings\n         * @param {string} lang language to add\n         * @param {object} stringMaps of strings to add grouped by property names\n         * @example\n         * <pre>\n         *      i18nService.add('en', {\n         *         aggregate: {\n         *                 label1: 'items',\n         *                 label2: 'some more items'\n         *                 }\n         *         },\n         *         groupPanel: {\n         *              description: 'Drag a column header here and drop it to group by that column.'\n         *           }\n         *      }\n         * </pre>\n         */\n        add: function (langs, stringMaps) {\n          if (typeof(langs) === 'object') {\n            angular.forEach(langs, function (lang) {\n              if (lang) {\n                langCache.add(lang, stringMaps);\n              }\n            });\n          } else {\n            langCache.add(langs, stringMaps);\n          }\n        },\n\n        /**\n         * @ngdoc service\n         * @name getAllLangs\n         * @methodOf ui.grid.i18n.service:i18nService\n         * @description  return all currently loaded languages\n         * @returns {array} string\n         */\n        getAllLangs: function () {\n          return langCache.getAllLangs();\n        },\n\n        /**\n         * @ngdoc service\n         * @name get\n         * @methodOf ui.grid.i18n.service:i18nService\n         * @description  return all currently loaded languages\n         * @param {string} lang to return.  If not specified, returns current language\n         * @returns {object} the translation string maps for the language\n         */\n        get: function (lang) {\n          var language = lang ? lang : service.getCurrentLang();\n          return langCache.get(language);\n        },\n\n        /**\n         * @ngdoc service\n         * @name getSafeText\n         * @methodOf ui.grid.i18n.service:i18nService\n         * @description  returns the text specified in the path or a Missing text if text is not found\n         * @param {string} path property path to use for retrieving text from string map\n         * @param {string} lang to return.  If not specified, returns current language\n         * @returns {object} the translation for the path\n         * @example\n         * <pre>\n         * i18nService.getSafeText('sort.ascending')\n         * </pre>\n         */\n        getSafeText: function (path, lang) {\n          var language = lang ? lang : service.getCurrentLang();\n          var trans = langCache.get(language);\n\n          if (!trans) {\n            return i18nConstants.MISSING;\n          }\n\n          var paths = path.split('.');\n          var current = trans;\n\n          for (var i = 0; i < paths.length; ++i) {\n            if (current[paths[i]] === undefined || current[paths[i]] === null) {\n              return i18nConstants.MISSING;\n            } else {\n              current = current[paths[i]];\n            }\n          }\n\n          return current;\n\n        },\n\n        /**\n         * @ngdoc service\n         * @name setCurrentLang\n         * @methodOf ui.grid.i18n.service:i18nService\n         * @description sets the current language to use in the application\n         * $broadcasts the Update_Event on the $rootScope\n         * @param {string} lang to set\n         * @example\n         * <pre>\n         * i18nService.setCurrentLang('fr');\n         * </pre>\n         */\n\n        setCurrentLang: function (lang) {\n          if (lang) {\n            langCache.setCurrent(lang);\n            $rootScope.$broadcast(i18nConstants.UPDATE_EVENT);\n          }\n        },\n\n        /**\n         * @ngdoc service\n         * @name getCurrentLang\n         * @methodOf ui.grid.i18n.service:i18nService\n         * @description returns the current language used in the application\n         */\n        getCurrentLang: function () {\n          var lang = langCache.getCurrentLang();\n          if (!lang) {\n            lang = i18nConstants.DEFAULT_LANG;\n            langCache.setCurrent(lang);\n          }\n          return lang;\n        }\n\n      };\n\n      return service;\n\n    }]);\n\n  var localeDirective = function (i18nService, i18nConstants) {\n    return {\n      compile: function () {\n        return {\n          pre: function ($scope, $elm, $attrs) {\n            var alias = i18nConstants.LOCALE_DIRECTIVE_ALIAS;\n            // check for watchable property\n            var lang = $scope.$eval($attrs[alias]);\n            if (lang) {\n              $scope.$watch($attrs[alias], function () {\n                i18nService.setCurrentLang(lang);\n              });\n            } else if ($attrs.$$observers) {\n              $attrs.$observe(alias, function () {\n                i18nService.setCurrentLang($attrs[alias] || i18nConstants.DEFAULT_LANG);\n              });\n            }\n          }\n        };\n      }\n    };\n  };\n\n  module.directive('uiI18n', ['i18nService', 'i18nConstants', localeDirective]);\n\n  // directive syntax\n  var uitDirective = function ($parse, i18nService, i18nConstants) {\n    return {\n      restrict: 'EA',\n      compile: function () {\n        return {\n          pre: function ($scope, $elm, $attrs) {\n            var alias1 = DIRECTIVE_ALIASES[0],\n              alias2 = DIRECTIVE_ALIASES[1];\n            var token = $attrs[alias1] || $attrs[alias2] || $elm.html();\n            var missing = i18nConstants.MISSING + token;\n            var observer;\n            if ($attrs.$$observers) {\n              var prop = $attrs[alias1] ? alias1 : alias2;\n              observer = $attrs.$observe(prop, function (result) {\n                if (result) {\n                  $elm.html($parse(result)(i18nService.getCurrentLang()) || missing);\n                }\n              });\n            }\n            var getter = $parse(token);\n            var listener = $scope.$on(i18nConstants.UPDATE_EVENT, function (evt) {\n              if (observer) {\n                observer($attrs[alias1] || $attrs[alias2]);\n              } else {\n                // set text based on i18n current language\n                $elm.html(getter(i18nService.get()) || missing);\n              }\n            });\n            $scope.$on('$destroy', listener);\n\n            $elm.html(getter(i18nService.get()) || missing);\n          }\n        };\n      }\n    };\n  };\n\n  angular.forEach( DIRECTIVE_ALIASES, function ( alias ) {\n    module.directive( alias, ['$parse', 'i18nService', 'i18nConstants', uitDirective] );\n  } );\n\n  // optional filter syntax\n  var uitFilter = function ($parse, i18nService, i18nConstants) {\n    return function (data) {\n      var getter = $parse(data);\n      // set text based on i18n current language\n      return getter(i18nService.get()) || i18nConstants.MISSING + data;\n    };\n  };\n\n  angular.forEach( FILTER_ALIASES, function ( alias ) {\n    module.filter( alias, ['$parse', 'i18nService', 'i18nConstants', uitFilter] );\n  } );\n\n\n})();\n(function() {\n  angular.module('ui.grid').config(['$provide', function($provide) {\n    $provide.decorator('i18nService', ['$delegate', function($delegate) {\n      $delegate.add('zh-cn', {\n        aggregate: {\n          label: '行'\n        },\n        groupPanel: {\n          description: '拖曳表头到此处进行分组'\n        },\n        search: {\n          placeholder: '查找',\n          showingItems: '已显示行数：',\n          selectedItems: '已选择行数：',\n          totalItems: '总行数：',\n          size: '每页显示行数：',\n          first: '首页',\n          next: '下一页',\n          previous: '上一页',\n          last: '末页'\n        },\n        menu: {\n          text: '选择列：'\n        },\n        sort: {\n          ascending: '升序',\n          descending: '降序',\n          remove: '取消排序'\n        },\n        column: {\n          hide: '隐藏列'\n        },\n        aggregation: {\n          count: '计数：',\n          sum: '求和：',\n          avg: '均值：',\n          min: '最小值：',\n          max: '最大值：'\n        },\n        pinning: {\n          pinLeft: '左侧固定',\n          pinRight: '右侧固定',\n          unpin: '取消固定'\n        },\n        gridMenu: {\n          columns: '列：',\n          importerTitle: '导入文件',\n          exporterAllAsCsv: '导出全部数据到CSV',\n          exporterVisibleAsCsv: '导出可见数据到CSV',\n          exporterSelectedAsCsv: '导出已选数据到CSV',\n          exporterAllAsPdf: '导出全部数据到PDF',\n          exporterVisibleAsPdf: '导出可见数据到PDF',\n          exporterSelectedAsPdf: '导出已选数据到PDF'\n        },\n        importer: {\n          noHeaders: '无法获取列名，确定文件包含表头？',\n          noObjects: '无法获取数据，确定文件包含数据？',\n          invalidCsv: '无法处理文件，确定是合法的CSV文件？',\n          invalidJson: '无法处理文件，确定是合法的JSON文件？',\n          jsonNotArray: '导入的文件不是JSON数组！'\n        },\n        pagination: {\n          sizes: '行每页',\n          totalItems: '行'\n        }\n      });\n      return $delegate;\n    }]);\n  }]);\n})();\n\n(function() {\n  angular.module('ui.grid').config(['$provide', function($provide) {\n    $provide.decorator('i18nService', ['$delegate', function($delegate) {\n      $delegate.add('zh-tw', {\n        aggregate: {\n          label: '行'\n        },\n        groupPanel: {\n          description: '拖曳表頭到此處進行分組'\n        },\n        search: {\n          placeholder: '查找',\n          showingItems: '已顯示行數：',\n          selectedItems: '已選擇行數：',\n          totalItems: '總行數：',\n          size: '每頁顯示行數：',\n          first: '首頁',\n          next: '下壹頁',\n          previous: '上壹頁',\n          last: '末頁'\n        },\n        menu: {\n          text: '選擇列：'\n        },\n        sort: {\n          ascending: '升序',\n          descending: '降序',\n          remove: '取消排序'\n        },\n        column: {\n          hide: '隱藏列'\n        },\n        aggregation: {\n          count: '計數：',\n          sum: '求和：',\n          avg: '均值：',\n          min: '最小值：',\n          max: '最大值：'\n        },\n        pinning: {\n          pinLeft: '左側固定',\n          pinRight: '右側固定',\n          unpin: '取消固定'\n        },\n        gridMenu: {\n          columns: '列：',\n          importerTitle: '導入文件',\n          exporterAllAsCsv: '導出全部數據到CSV',\n          exporterVisibleAsCsv: '導出可見數據到CSV',\n          exporterSelectedAsCsv: '導出已選數據到CSV',\n          exporterAllAsPdf: '導出全部數據到PDF',\n          exporterVisibleAsPdf: '導出可見數據到PDF',\n          exporterSelectedAsPdf: '導出已選數據到PDF'\n        },\n        importer: {\n          noHeaders: '無法獲取列名，確定文件包含表頭？',\n          noObjects: '無法獲取數據，確定文件包含數據？',\n          invalidCsv: '無法處理文件，確定是合法的CSV文件？',\n          invalidJson: '無法處理文件，確定是合法的JSON文件？',\n          jsonNotArray: '導入的文件不是JSON數組！'\n        },\n        pagination: {\n          sizes: '行每頁',\n          totalItems: '行'\n        }\n      });\n      return $delegate;\n    }]);\n  }]);\n})();\n\n(function() {\n  'use strict';\n  /**\n   *  @ngdoc overview\n   *  @name ui.grid.autoResize\n   *\n   *  @description \n   *\n   *  #ui.grid.autoResize\n   *  This module provides auto-resizing functionality to ui-grid\n   *\n   */\n  var module = angular.module('ui.grid.autoResize', ['ui.grid']);\n  \n\n  module.directive('uiGridAutoResize', ['$timeout', 'gridUtil', function ($timeout, gridUtil) {\n    return {\n      require: 'uiGrid',\n      scope: false,\n      link: function ($scope, $elm, $attrs, uiGridCtrl) {\n        var prevGridWidth, prevGridHeight;\n\n        function getDimensions() {\n          prevGridHeight = gridUtil.elementHeight($elm);\n          prevGridWidth = gridUtil.elementWidth($elm);\n        }\n\n        // Initialize the dimensions\n        getDimensions();\n\n        var resizeTimeoutId;\n        function startTimeout() {\n          clearTimeout(resizeTimeoutId);\n\n          resizeTimeoutId = setTimeout(function () {\n            var newGridHeight = gridUtil.elementHeight($elm);\n            var newGridWidth = gridUtil.elementWidth($elm);\n\n            if (newGridHeight !== prevGridHeight || newGridWidth !== prevGridWidth) {\n              uiGridCtrl.grid.gridHeight = newGridHeight;\n              uiGridCtrl.grid.gridWidth = newGridWidth;\n\n              $scope.$apply(function () {\n                uiGridCtrl.grid.refresh()\n                  .then(function () {\n                    getDimensions();\n\n                    startTimeout();\n                  });\n              });\n            }\n            else {\n              startTimeout();\n            }\n          }, 250);\n        }\n\n        startTimeout();\n\n        $scope.$on('$destroy', function() {\n          clearTimeout(resizeTimeoutId);\n        });\n      }\n    };\n  }]);\n})();\n(function () {\n  'use strict';\n  var module = angular.module('ui.grid.cellNav', ['ui.grid']);\n\n  function RowCol(row, col) {\n    this.row = row;\n    this.col = col;\n  }\n\n  /**\n   *  @ngdoc object\n   *  @name ui.grid.cellNav.constant:uiGridCellNavConstants\n   *\n   *  @description constants available in cellNav\n   */\n  module.constant('uiGridCellNavConstants', {\n    FEATURE_NAME: 'gridCellNav',\n    CELL_NAV_EVENT: 'cellNav',\n    direction: {LEFT: 0, RIGHT: 1, UP: 2, DOWN: 3, PG_UP: 4, PG_DOWN: 5},\n    EVENT_TYPE: {\n      KEYDOWN: 0,\n      CLICK: 1\n    }\n  });\n\n\n  module.factory('uiGridCellNavFactory', ['gridUtil', 'uiGridConstants', 'uiGridCellNavConstants', '$q',\n    function (gridUtil, uiGridConstants, uiGridCellNavConstants, $q) {\n      /**\n       *  @ngdoc object\n       *  @name ui.grid.cellNav.object:CellNav\n       *  @description returns a CellNav prototype function\n       *  @param {object} rowContainer container for rows\n       *  @param {object} colContainer parent column container\n       *  @param {object} leftColContainer column container to the left of parent\n       *  @param {object} rightColContainer column container to the right of parent\n       */\n      var UiGridCellNav = function UiGridCellNav(rowContainer, colContainer, leftColContainer, rightColContainer) {\n        this.rows = rowContainer.visibleRowCache;\n        this.columns = colContainer.visibleColumnCache;\n        this.leftColumns = leftColContainer ? leftColContainer.visibleColumnCache : [];\n        this.rightColumns = rightColContainer ? rightColContainer.visibleColumnCache : [];\n        this.bodyContainer = rowContainer;\n      };\n\n      /** returns focusable columns of all containers */\n      UiGridCellNav.prototype.getFocusableCols = function () {\n        var allColumns = this.leftColumns.concat(this.columns, this.rightColumns);\n\n        return allColumns.filter(function (col) {\n          return col.colDef.allowCellFocus;\n        });\n      };\n\n      /**\n       *  @ngdoc object\n       *  @name ui.grid.cellNav.api:GridRow\n       *\n       *  @description GridRow settings for cellNav feature, these are available to be\n       *  set only internally (for example, by other features)\n       */\n\n      /**\n       *  @ngdoc object\n       *  @name allowCellFocus\n       *  @propertyOf  ui.grid.cellNav.api:GridRow\n       *  @description Enable focus on a cell within this row.  If set to false then no cells\n       *  in this row can be focused - group header rows as an example would set this to false.\n       *  <br/>Defaults to true\n       */\n      /** returns focusable rows */\n      UiGridCellNav.prototype.getFocusableRows = function () {\n        return this.rows.filter(function(row) {\n          return row.allowCellFocus !== false;\n        });\n      };\n\n      UiGridCellNav.prototype.getNextRowCol = function (direction, curRow, curCol) {\n        switch (direction) {\n          case uiGridCellNavConstants.direction.LEFT:\n            return this.getRowColLeft(curRow, curCol);\n          case uiGridCellNavConstants.direction.RIGHT:\n            return this.getRowColRight(curRow, curCol);\n          case uiGridCellNavConstants.direction.UP:\n            return this.getRowColUp(curRow, curCol);\n          case uiGridCellNavConstants.direction.DOWN:\n            return this.getRowColDown(curRow, curCol);\n          case uiGridCellNavConstants.direction.PG_UP:\n            return this.getRowColPageUp(curRow, curCol);\n          case uiGridCellNavConstants.direction.PG_DOWN:\n            return this.getRowColPageDown(curRow, curCol);\n        }\n\n      };\n\n      UiGridCellNav.prototype.getRowColLeft = function (curRow, curCol) {\n        var focusableCols = this.getFocusableCols();\n        var focusableRows = this.getFocusableRows();\n        var curColIndex = focusableCols.indexOf(curCol);\n        var curRowIndex = focusableRows.indexOf(curRow);\n\n        //could not find column in focusable Columns so set it to 1\n        if (curColIndex === -1) {\n          curColIndex = 1;\n        }\n\n        var nextColIndex = curColIndex === 0 ? focusableCols.length - 1 : curColIndex - 1;\n\n        //get column to left\n        if (nextColIndex > curColIndex) {\n          if (curRowIndex === 0) {\n            return new RowCol(curRow, focusableCols[nextColIndex]); //return same row\n          }\n          else {\n            //up one row and far right column\n            return new RowCol(focusableRows[curRowIndex - 1], focusableCols[nextColIndex]);\n          }\n        }\n        else {\n          return new RowCol(curRow, focusableCols[nextColIndex]);\n        }\n      };\n\n      UiGridCellNav.prototype.getRowColRight = function (curRow, curCol) {\n        var focusableCols = this.getFocusableCols();\n        var focusableRows = this.getFocusableRows();\n        var curColIndex = focusableCols.indexOf(curCol);\n        var curRowIndex = focusableRows.indexOf(curRow);\n\n        //could not find column in focusable Columns so set it to 0\n        if (curColIndex === -1) {\n          curColIndex = 0;\n        }\n        var nextColIndex = curColIndex === focusableCols.length - 1 ? 0 : curColIndex + 1;\n\n        if (nextColIndex < curColIndex) {\n          if (curRowIndex === focusableRows.length - 1) {\n            return new RowCol(curRow, focusableCols[nextColIndex]); //return same row\n          }\n          else {\n            //down one row and far left column\n            return new RowCol(focusableRows[curRowIndex + 1], focusableCols[nextColIndex]);\n          }\n        }\n        else {\n          return new RowCol(curRow, focusableCols[nextColIndex]);\n        }\n      };\n\n      UiGridCellNav.prototype.getRowColDown = function (curRow, curCol) {\n        var focusableCols = this.getFocusableCols();\n        var focusableRows = this.getFocusableRows();\n        var curColIndex = focusableCols.indexOf(curCol);\n        var curRowIndex = focusableRows.indexOf(curRow);\n\n        //could not find column in focusable Columns so set it to 0\n        if (curColIndex === -1) {\n          curColIndex = 0;\n        }\n\n        if (curRowIndex === focusableRows.length - 1) {\n          return new RowCol(curRow, focusableCols[curColIndex]); //return same row\n        }\n        else {\n          //down one row\n          return new RowCol(focusableRows[curRowIndex + 1], focusableCols[curColIndex]);\n        }\n      };\n\n      UiGridCellNav.prototype.getRowColPageDown = function (curRow, curCol) {\n        var focusableCols = this.getFocusableCols();\n        var focusableRows = this.getFocusableRows();\n        var curColIndex = focusableCols.indexOf(curCol);\n        var curRowIndex = focusableRows.indexOf(curRow);\n\n        //could not find column in focusable Columns so set it to 0\n        if (curColIndex === -1) {\n          curColIndex = 0;\n        }\n\n        var pageSize = this.bodyContainer.minRowsToRender();\n        if (curRowIndex >= focusableRows.length - pageSize) {\n          return new RowCol(focusableRows[focusableRows.length - 1], focusableCols[curColIndex]); //return last row\n        }\n        else {\n          //down one page\n          return new RowCol(focusableRows[curRowIndex + pageSize], focusableCols[curColIndex]);\n        }\n      };\n\n      UiGridCellNav.prototype.getRowColUp = function (curRow, curCol) {\n        var focusableCols = this.getFocusableCols();\n        var focusableRows = this.getFocusableRows();\n        var curColIndex = focusableCols.indexOf(curCol);\n        var curRowIndex = focusableRows.indexOf(curRow);\n\n        //could not find column in focusable Columns so set it to 0\n        if (curColIndex === -1) {\n          curColIndex = 0;\n        }\n\n        if (curRowIndex === 0) {\n          return new RowCol(curRow, focusableCols[curColIndex]); //return same row\n        }\n        else {\n          //up one row\n          return new RowCol(focusableRows[curRowIndex - 1], focusableCols[curColIndex]);\n        }\n      };\n\n      UiGridCellNav.prototype.getRowColPageUp = function (curRow, curCol) {\n        var focusableCols = this.getFocusableCols();\n        var focusableRows = this.getFocusableRows();\n        var curColIndex = focusableCols.indexOf(curCol);\n        var curRowIndex = focusableRows.indexOf(curRow);\n\n        //could not find column in focusable Columns so set it to 0\n        if (curColIndex === -1) {\n          curColIndex = 0;\n        }\n\n        var pageSize = this.bodyContainer.minRowsToRender();\n        if (curRowIndex - pageSize < 0) {\n          return new RowCol(focusableRows[0], focusableCols[curColIndex]); //return first row\n        }\n        else {\n          //up one page\n          return new RowCol(focusableRows[curRowIndex - pageSize], focusableCols[curColIndex]);\n        }\n      };\n      return UiGridCellNav;\n    }]);\n\n  /**\n   *  @ngdoc service\n   *  @name ui.grid.cellNav.service:uiGridCellNavService\n   *\n   *  @description Services for cell navigation features. If you don't like the key maps we use,\n   *  or the direction cells navigation, override with a service decorator (see angular docs)\n   */\n  module.service('uiGridCellNavService', ['gridUtil', 'uiGridConstants', 'uiGridCellNavConstants', '$q', 'uiGridCellNavFactory', 'ScrollEvent',\n    function (gridUtil, uiGridConstants, uiGridCellNavConstants, $q, UiGridCellNav, ScrollEvent) {\n\n      var service = {\n\n        initializeGrid: function (grid) {\n          grid.registerColumnBuilder(service.cellNavColumnBuilder);\n\n          //create variables for state\n          grid.cellNav = {};\n          grid.cellNav.lastRowCol = null;\n          grid.cellNav.focusedCells = [];\n\n          service.defaultGridOptions(grid.options);\n\n          /**\n           *  @ngdoc object\n           *  @name ui.grid.cellNav.api:PublicApi\n           *\n           *  @description Public Api for cellNav feature\n           */\n          var publicApi = {\n            events: {\n              cellNav: {\n                /**\n                 * @ngdoc event\n                 * @name navigate\n                 * @eventOf  ui.grid.cellNav.api:PublicApi\n                 * @description raised when the active cell is changed\n                 * <pre>\n                 *      gridApi.cellNav.on.navigate(scope,function(newRowcol, oldRowCol){})\n                 * </pre>\n                 * @param {object} newRowCol new position\n                 * @param {object} oldRowCol old position\n                 */\n                navigate: function (newRowCol, oldRowCol) {\n                }\n              }\n            },\n            methods: {\n              cellNav: {\n                /**\n                 * @ngdoc function\n                 * @name scrollTo\n                 * @methodOf  ui.grid.cellNav.api:PublicApi\n                 * @description brings the specified row and column into view\n                 * @param {object} rowEntity gridOptions.data[] array instance to make visible\n                 * @param {object} colDef to make visible\n                 */\n                scrollTo: function (rowEntity, colDef) {\n                  service.scrollTo(grid, rowEntity, colDef);\n                },\n\n                /**\n                 * @ngdoc function\n                 * @name scrollToFocus\n                 * @methodOf  ui.grid.cellNav.api:PublicApi\n                 * @description brings the specified row and column into view, and sets focus\n                 * to that cell\n                 * @param {object} rowEntity gridOptions.data[] array instance to make visible and set focus\n                 * @param {object} colDef to make visible and set focus\n                 */\n                scrollToFocus: function (rowEntity, colDef) {\n                  service.scrollToFocus(grid, rowEntity, colDef);\n                },\n\n                /**\n                 * @ngdoc function\n                 * @name scrollToFocus\n                 * @methodOf  ui.grid.cellNav.api:PublicApi\n                 * @description brings the specified row and column fully into view if it isn't already\n                 * @param {GridRow} row grid row that we should make fully visible\n                 * @param {GridCol} col grid col to make fully visible\n                 */\n                scrollToIfNecessary: function (row, col) {\n                  service.scrollToIfNecessary(grid, row, col);\n                },\n\n                /**\n                 * @ngdoc function\n                 * @name getFocusedCell\n                 * @methodOf  ui.grid.cellNav.api:PublicApi\n                 * @description returns the current (or last if Grid does not have focus) focused row and column\n                 * <br> value is null if no selection has occurred\n                 */\n                getFocusedCell: function () {\n                  return grid.cellNav.lastRowCol;\n                },\n\n                /**\n                 * @ngdoc function\n                 * @name getCurrentSelection\n                 * @methodOf  ui.grid.cellNav.api:PublicApi\n                 * @description returns an array containing the current selection\n                 * <br> array is empty if no selection has occurred\n                 */\n                getCurrentSelection: function () {\n                  return grid.cellNav.focusedCells;\n                },\n\n                /**\n                 * @ngdoc function\n                 * @name rowColSelectIndex\n                 * @methodOf  ui.grid.cellNav.api:PublicApi\n                 * @description returns the index in the order in which the RowCol was selected, returns -1 if the RowCol\n                 * isn't selected\n                 * @param {object} rowCol the rowCol to evaluate\n                 */\n                rowColSelectIndex: function (rowCol) {\n                  //return gridUtil.arrayContainsObjectWithProperty(grid.cellNav.focusedCells, 'col.uid', rowCol.col.uid) &&\n                  var index = -1;\n                  for (var i = 0; i < grid.cellNav.focusedCells.length; i++) {\n                    if (grid.cellNav.focusedCells[i].col.uid === rowCol.col.uid &&\n                      grid.cellNav.focusedCells[i].row.uid === rowCol.row.uid) {\n                      index = i;\n                      break;\n                    }\n                  }\n                  return index;\n                }\n              }\n            }\n          };\n\n          grid.api.registerEventsFromObject(publicApi.events);\n\n          grid.api.registerMethodsFromObject(publicApi.methods);\n\n        },\n\n        defaultGridOptions: function (gridOptions) {\n          /**\n           *  @ngdoc object\n           *  @name ui.grid.cellNav.api:GridOptions\n           *\n           *  @description GridOptions for cellNav feature, these are available to be\n           *  set using the ui-grid {@link ui.grid.class:GridOptions gridOptions}\n           */\n\n          /**\n           *  @ngdoc object\n           *  @name modifierKeysToMultiSelectCells\n           *  @propertyOf  ui.grid.cellNav.api:GridOptions\n           *  @description Enable multiple cell selection only when using the ctrlKey or shiftKey.\n           *  <br/>Defaults to false\n           */\n          gridOptions.modifierKeysToMultiSelectCells = gridOptions.modifierKeysToMultiSelectCells === true;\n\n        },\n\n        /**\n         * @ngdoc service\n         * @name decorateRenderContainers\n         * @methodOf ui.grid.cellNav.service:uiGridCellNavService\n         * @description  decorates grid renderContainers with cellNav functions\n         */\n        decorateRenderContainers: function (grid) {\n\n          var rightContainer = grid.hasRightContainer() ? grid.renderContainers.right : null;\n          var leftContainer = grid.hasLeftContainer() ? grid.renderContainers.left : null;\n\n          if (leftContainer !== null) {\n            grid.renderContainers.left.cellNav = new UiGridCellNav(grid.renderContainers.body, leftContainer, rightContainer, grid.renderContainers.body);\n          }\n          if (rightContainer !== null) {\n            grid.renderContainers.right.cellNav = new UiGridCellNav(grid.renderContainers.body, rightContainer, grid.renderContainers.body, leftContainer);\n          }\n\n          grid.renderContainers.body.cellNav = new UiGridCellNav(grid.renderContainers.body, grid.renderContainers.body, leftContainer, rightContainer);\n        },\n\n        /**\n         * @ngdoc service\n         * @name getDirection\n         * @methodOf ui.grid.cellNav.service:uiGridCellNavService\n         * @description  determines which direction to for a given keyDown event\n         * @returns {uiGridCellNavConstants.direction} direction\n         */\n        getDirection: function (evt) {\n          if (evt.keyCode === uiGridConstants.keymap.LEFT ||\n            (evt.keyCode === uiGridConstants.keymap.TAB && evt.shiftKey)) {\n            return uiGridCellNavConstants.direction.LEFT;\n          }\n          if (evt.keyCode === uiGridConstants.keymap.RIGHT ||\n            evt.keyCode === uiGridConstants.keymap.TAB) {\n            return uiGridCellNavConstants.direction.RIGHT;\n          }\n\n          if (evt.keyCode === uiGridConstants.keymap.UP ||\n            (evt.keyCode === uiGridConstants.keymap.ENTER && evt.shiftKey) ) {\n            return uiGridCellNavConstants.direction.UP;\n          }\n\n          if (evt.keyCode === uiGridConstants.keymap.PG_UP){\n            return uiGridCellNavConstants.direction.PG_UP;\n          }\n\n          if (evt.keyCode === uiGridConstants.keymap.DOWN ||\n            evt.keyCode === uiGridConstants.keymap.ENTER) {\n            return uiGridCellNavConstants.direction.DOWN;\n          }\n\n          if (evt.keyCode === uiGridConstants.keymap.PG_DOWN){\n            return uiGridCellNavConstants.direction.PG_DOWN;\n          }\n\n          return null;\n        },\n\n        /**\n         * @ngdoc service\n         * @name cellNavColumnBuilder\n         * @methodOf ui.grid.cellNav.service:uiGridCellNavService\n         * @description columnBuilder function that adds cell navigation properties to grid column\n         * @returns {promise} promise that will load any needed templates when resolved\n         */\n        cellNavColumnBuilder: function (colDef, col, gridOptions) {\n          var promises = [];\n\n          /**\n           *  @ngdoc object\n           *  @name ui.grid.cellNav.api:ColumnDef\n           *\n           *  @description Column Definitions for cellNav feature, these are available to be\n           *  set using the ui-grid {@link ui.grid.class:GridOptions.columnDef gridOptions.columnDefs}\n           */\n\n          /**\n           *  @ngdoc object\n           *  @name allowCellFocus\n           *  @propertyOf  ui.grid.cellNav.api:ColumnDef\n           *  @description Enable focus on a cell within this column.\n           *  <br/>Defaults to true\n           */\n          colDef.allowCellFocus = colDef.allowCellFocus === undefined ? true : colDef.allowCellFocus;\n\n          return $q.all(promises);\n        },\n\n        /**\n         * @ngdoc method\n         * @methodOf ui.grid.cellNav.service:uiGridCellNavService\n         * @name scrollTo\n         * @description Scroll the grid such that the specified\n         * row and column is in view\n         * @param {Grid} grid the grid you'd like to act upon, usually available\n         * from gridApi.grid\n         * @param {object} rowEntity gridOptions.data[] array instance to make visible\n         * @param {object} colDef to make visible\n         */\n        scrollTo: function (grid, rowEntity, colDef) {\n          var gridRow = null, gridCol = null;\n\n          if (rowEntity !== null && typeof(rowEntity) !== 'undefined' ) {\n            gridRow = grid.getRow(rowEntity);\n          }\n\n          if (colDef !== null && typeof(colDef) !== 'undefined' ) {\n            gridCol = grid.getColumn(colDef.name ? colDef.name : colDef.field);\n          }\n          this.scrollToInternal(grid, gridRow, gridCol);\n        },\n\n        /**\n         * @ngdoc method\n         * @methodOf ui.grid.cellNav.service:uiGridCellNavService\n         * @name scrollToFocus\n         * @description Scroll the grid such that the specified\n         * row and column is in view, and set focus to the cell in that row and column\n         * @param {Grid} grid the grid you'd like to act upon, usually available\n         * from gridApi.grid\n         * @param {object} rowEntity gridOptions.data[] array instance to make visible and set focus to\n         * @param {object} colDef to make visible and set focus to\n         */\n        scrollToFocus: function (grid, rowEntity, colDef) {\n          var gridRow = null, gridCol = null;\n\n          if (rowEntity !== null) {\n            gridRow = grid.getRow(rowEntity);\n          }\n\n          if (colDef !== null) {\n            gridCol = grid.getColumn(colDef.name ? colDef.name : colDef.field);\n          }\n          this.scrollToInternal(grid, gridRow, gridCol);\n\n          var rowCol = { row: gridRow, col: gridCol };\n\n          // Broadcast the navigation\n          grid.cellNav.broadcastCellNav(rowCol);\n\n        },\n\n        /**\n         * @ngdoc method\n         * @methodOf ui.grid.cellNav.service:uiGridCellNavService\n         * @name scrollToInternal\n         * @description Like scrollTo, but takes gridRow and gridCol.\n         * In calculating the scroll height we have to deal with wanting\n         * 0% for the first row, and 100% for the last row.  Normal maths\n         * for a 10 row list would return 1/10 = 10% for the first row, so\n         * we need to tweak the numbers to add an extra 10% somewhere.  The\n         * formula if we're trying to get to row 0 in a 10 row list (assuming our\n         * index is zero based, so the last row is row 9) is:\n         * <pre>\n         *   0 + 0 / 10 = 0%\n         * </pre>\n         *\n         * To get to row 9 (i.e. the last row) in the same list, we want to\n         * go to:\n         * <pre>\n         *  ( 9 + 1 ) / 10 = 100%\n         * </pre>\n         * So we need to apportion one whole row within the overall grid scroll,\n         * the formula is:\n         * <pre>\n         *   ( index + ( index / (total rows - 1) ) / total rows\n         * </pre>\n         * @param {Grid} grid the grid you'd like to act upon, usually available\n         * from gridApi.grid\n         * @param {GridRow} gridRow row to make visible\n         * @param {GridCol} gridCol column to make visible\n         */\n        scrollToInternal: function (grid, gridRow, gridCol) {\n          var scrollEvent = new ScrollEvent(grid,null,null,'uiGridCellNavService.scrollToInternal');\n\n          if (gridRow !== null) {\n            var seekRowIndex = grid.renderContainers.body.visibleRowCache.indexOf(gridRow);\n            var totalRows = grid.renderContainers.body.visibleRowCache.length;\n            var percentage = ( seekRowIndex + ( seekRowIndex / ( totalRows - 1 ) ) ) / totalRows;\n            scrollEvent.y = { percentage:  percentage  };\n          }\n\n          if (gridCol !== null) {\n            scrollEvent.x = { percentage: this.getLeftWidth(grid, gridCol) / this.getLeftWidth(grid, grid.renderContainers.body.visibleColumnCache[grid.renderContainers.body.visibleColumnCache.length - 1] ) };\n          }\n\n          if (scrollEvent.y || scrollEvent.x) {\n            scrollEvent.fireScrollingEvent();\n          }\n        },\n\n        /**\n         * @ngdoc method\n         * @methodOf ui.grid.cellNav.service:uiGridCellNavService\n         * @name scrollToIfNecessary\n         * @description Scrolls the grid to make a certain row and column combo visible,\n         *   in the case that it is not completely visible on the screen already.\n         * @param {Grid} grid the grid you'd like to act upon, usually available\n         * from gridApi.grid\n         * @param {GridRow} gridRow row to make visible\n         * @param {GridCol} gridCol column to make visible\n         */\n        scrollToIfNecessary: function (grid, gridRow, gridCol) {\n          var scrollEvent = new ScrollEvent(grid, 'uiGridCellNavService.scrollToIfNecessary');\n\n          // Alias the visible row and column caches\n          var visRowCache = grid.renderContainers.body.visibleRowCache;\n          var visColCache = grid.renderContainers.body.visibleColumnCache;\n\n          /*-- Get the top, left, right, and bottom \"scrolled\" edges of the grid --*/\n\n          // The top boundary is the current Y scroll position PLUS the header height, because the header can obscure rows when the grid is scrolled downwards\n          var topBound = grid.renderContainers.body.prevScrollTop + grid.headerHeight;\n\n          // Don't the let top boundary be less than 0\n          topBound = (topBound < 0) ? 0 : topBound;\n\n          // The left boundary is the current X scroll position\n          var leftBound = grid.renderContainers.body.prevScrollLeft;\n\n          // The bottom boundary is the current Y scroll position, plus the height of the grid, but minus the header height.\n          //   Basically this is the viewport height added on to the scroll position\n          var bottomBound = grid.renderContainers.body.prevScrollTop + grid.gridHeight - grid.headerHeight;\n\n          // If there's a horizontal scrollbar, remove its height from the bottom boundary, otherwise we'll be letting it obscure rows\n          //if (grid.horizontalScrollbarHeight) {\n          //  bottomBound = bottomBound - grid.horizontalScrollbarHeight;\n          //}\n\n          // The right position is the current X scroll position minus the grid width\n          var rightBound = grid.renderContainers.body.prevScrollLeft + Math.ceil(grid.gridWidth);\n\n          // If there's a vertical scrollbar, subtract it from the right boundary or we'll allow it to obscure cells\n          //if (grid.verticalScrollbarWidth) {\n          //  rightBound = rightBound - grid.verticalScrollbarWidth;\n          //}\n\n          // We were given a row to scroll to\n          if (gridRow !== null) {\n            // This is the index of the row we want to scroll to, within the list of rows that can be visible\n            var seekRowIndex = visRowCache.indexOf(gridRow);\n\n            // Total vertical scroll length of the grid\n            var scrollLength = (grid.renderContainers.body.getCanvasHeight() - grid.renderContainers.body.getViewportHeight());\n\n            // Add the height of the native horizontal scrollbar to the scroll length, if it's there. Otherwise it will mask over the final row\n            //if (grid.horizontalScrollbarHeight && grid.horizontalScrollbarHeight > 0) {\n            //  scrollLength = scrollLength + grid.horizontalScrollbarHeight;\n            //}\n\n            // This is the minimum amount of pixels we need to scroll vertical in order to see this row.\n            var pixelsToSeeRow = ((seekRowIndex + 1) * grid.options.rowHeight);\n\n            // Don't let the pixels required to see the row be less than zero\n            pixelsToSeeRow = (pixelsToSeeRow < 0) ? 0 : pixelsToSeeRow;\n\n            var scrollPixels, percentage;\n\n            // If the scroll position we need to see the row is LESS than the top boundary, i.e. obscured above the top of the grid...\n            if (pixelsToSeeRow < topBound) {\n              // Get the different between the top boundary and the required scroll position and subtract it from the current scroll position\\\n              //   to get the full position we need\n              scrollPixels = grid.renderContainers.body.prevScrollTop - (topBound - pixelsToSeeRow);\n\n              // Turn the scroll position into a percentage and make it an argument for a scroll event\n              percentage = scrollPixels / scrollLength;\n              scrollEvent.y = { percentage: percentage  };\n            }\n            // Otherwise if the scroll position we need to see the row is MORE than the bottom boundary, i.e. obscured below the bottom of the grid...\n            else if (pixelsToSeeRow > bottomBound) {\n              // Get the different between the bottom boundary and the required scroll position and add it to the current scroll position\n              //   to get the full position we need\n              scrollPixels = pixelsToSeeRow - bottomBound + grid.renderContainers.body.prevScrollTop;\n\n              // Turn the scroll position into a percentage and make it an argument for a scroll event\n              percentage = scrollPixels / scrollLength;\n              scrollEvent.y = { percentage: percentage  };\n            }\n          }\n\n          // We were given a column to scroll to\n          if (gridCol !== null) {\n            // This is the index of the row we want to scroll to, within the list of rows that can be visible\n            var seekColumnIndex = visColCache.indexOf(gridCol);\n\n            // Total vertical scroll length of the grid\n            var horizScrollLength = (grid.renderContainers.body.getCanvasWidth() - grid.renderContainers.body.getViewportWidth());\n\n            // Add the height of the native horizontal scrollbar to the scroll length, if it's there. Otherwise it will mask over the final row\n            // if (grid.verticalScrollbarWidth && grid.verticalScrollbarWidth > 0) {\n            //   horizScrollLength = horizScrollLength + grid.verticalScrollbarWidth;\n            // }\n\n            // This is the minimum amount of pixels we need to scroll vertical in order to see this column\n            var columnLeftEdge = 0;\n            for (var i = 0; i < seekColumnIndex; i++) {\n              var col = visColCache[i];\n              columnLeftEdge += col.drawnWidth;\n            }\n            columnLeftEdge = (columnLeftEdge < 0) ? 0 : columnLeftEdge;\n\n            var columnRightEdge = columnLeftEdge + gridCol.drawnWidth;\n\n            // Don't let the pixels required to see the column be less than zero\n            columnRightEdge = (columnRightEdge < 0) ? 0 : columnRightEdge;\n\n            var horizScrollPixels, horizPercentage;\n\n            // If the scroll position we need to see the row is LESS than the top boundary, i.e. obscured above the top of the grid...\n            if (columnLeftEdge < leftBound) {\n              // Get the different between the top boundary and the required scroll position and subtract it from the current scroll position\\\n              //   to get the full position we need\n              horizScrollPixels = grid.renderContainers.body.prevScrollLeft - (leftBound - columnLeftEdge);\n\n              // Turn the scroll position into a percentage and make it an argument for a scroll event\n              horizPercentage = horizScrollPixels / horizScrollLength;\n              horizPercentage = (horizPercentage > 1) ? 1 : horizPercentage;\n              scrollEvent.x = { percentage: horizPercentage  };\n            }\n            // Otherwise if the scroll position we need to see the row is MORE than the bottom boundary, i.e. obscured below the bottom of the grid...\n            else if (columnRightEdge > rightBound) {\n              // Get the different between the bottom boundary and the required scroll position and add it to the current scroll position\n              //   to get the full position we need\n              horizScrollPixels = columnRightEdge - rightBound + grid.renderContainers.body.prevScrollLeft;\n\n              // Turn the scroll position into a percentage and make it an argument for a scroll event\n              horizPercentage = horizScrollPixels / horizScrollLength;\n              horizPercentage = (horizPercentage > 1) ? 1 : horizPercentage;\n              scrollEvent.x = { percentage: horizPercentage  };\n            }\n          }\n\n          // If we need to scroll on either the x or y axes, fire a scroll event\n          if (scrollEvent.y || scrollEvent.x) {\n            scrollEvent.fireScrollingEvent();\n          }\n        },\n\n        /**\n         * @ngdoc method\n         * @methodOf ui.grid.cellNav.service:uiGridCellNavService\n         * @name getLeftWidth\n         * @description Get the current drawn width of the columns in the\n         * grid up to the numbered column, and add an apportionment for the\n         * column that we're on.  So if we are on column 0, we want to scroll\n         * 0% (i.e. exclude this column from calc).  If we're on the last column\n         * we want to scroll to 100% (i.e. include this column in the calc). So\n         * we include (thisColIndex / totalNumberCols) % of this column width\n         * @param {Grid} grid the grid you'd like to act upon, usually available\n         * from gridApi.grid\n         * @param {gridCol} upToCol the column to total up to and including\n         */\n        getLeftWidth: function (grid, upToCol) {\n          var width = 0;\n\n          if (!upToCol) {\n            return width;\n          }\n\n          var lastIndex = grid.renderContainers.body.visibleColumnCache.indexOf( upToCol );\n\n          // total column widths up-to but not including the passed in column\n          grid.renderContainers.body.visibleColumnCache.forEach( function( col, index ) {\n            if ( index < lastIndex ){\n              width += col.drawnWidth;\n            }\n          });\n\n          // pro-rata the final column based on % of total columns.\n          var percentage = lastIndex === 0 ? 0 : (lastIndex + 1) / grid.renderContainers.body.visibleColumnCache.length;\n          width += upToCol.drawnWidth * percentage;\n\n          return width;\n        }\n      };\n\n      return service;\n    }]);\n\n  /**\n   *  @ngdoc directive\n   *  @name ui.grid.cellNav.directive:uiCellNav\n   *  @element div\n   *  @restrict EA\n   *\n   *  @description Adds cell navigation features to the grid columns\n   *\n   *  @example\n   <example module=\"app\">\n   <file name=\"app.js\">\n   var app = angular.module('app', ['ui.grid', 'ui.grid.cellNav']);\n\n   app.controller('MainCtrl', ['$scope', function ($scope) {\n      $scope.data = [\n        { name: 'Bob', title: 'CEO' },\n            { name: 'Frank', title: 'Lowly Developer' }\n      ];\n\n      $scope.columnDefs = [\n        {name: 'name'},\n        {name: 'title'}\n      ];\n    }]);\n   </file>\n   <file name=\"index.html\">\n   <div ng-controller=\"MainCtrl\">\n   <div ui-grid=\"{ data: data, columnDefs: columnDefs }\" ui-grid-cellnav></div>\n   </div>\n   </file>\n   </example>\n   */\n  module.directive('uiGridCellnav', ['gridUtil', 'uiGridCellNavService', 'uiGridCellNavConstants',\n    function (gridUtil, uiGridCellNavService, uiGridCellNavConstants) {\n      return {\n        replace: true,\n        priority: -150,\n        require: '^uiGrid',\n        scope: false,\n        controller: function () {},\n        compile: function () {\n          return {\n            pre: function ($scope, $elm, $attrs, uiGridCtrl) {\n              var _scope = $scope;\n\n              var grid = uiGridCtrl.grid;\n              uiGridCellNavService.initializeGrid(grid);\n\n              uiGridCtrl.cellNav = {};\n\n              uiGridCtrl.cellNav.focusCell = function (row, col) {\n                uiGridCtrl.cellNav.broadcastCellNav({ row: row, col: col });\n              };\n\n              //  gridUtil.logDebug('uiGridEdit preLink');\n              uiGridCtrl.cellNav.broadcastCellNav = grid.cellNav.broadcastCellNav = function (newRowCol, modifierDown) {\n                modifierDown = !(modifierDown === undefined || !modifierDown);\n                uiGridCtrl.cellNav.broadcastFocus(newRowCol, modifierDown);\n                _scope.$broadcast(uiGridCellNavConstants.CELL_NAV_EVENT, newRowCol, modifierDown);\n              };\n\n              uiGridCtrl.cellNav.broadcastFocus = function (rowCol, modifierDown) {\n                modifierDown = !(modifierDown === undefined || !modifierDown);\n\n                var row = rowCol.row,\n                  col = rowCol.col;\n\n                var rowColSelectIndex = uiGridCtrl.grid.api.cellNav.rowColSelectIndex(rowCol);\n\n                if (grid.cellNav.lastRowCol === null || rowColSelectIndex === -1) {\n                  var newRowCol = new RowCol(row, col);\n                  grid.api.cellNav.raise.navigate(newRowCol, grid.cellNav.lastRowCol);\n                  grid.cellNav.lastRowCol = newRowCol;\n                  if (uiGridCtrl.grid.options.modifierKeysToMultiSelectCells && modifierDown) {\n                    grid.cellNav.focusedCells.push(rowCol);\n                  } else {\n                    grid.cellNav.focusedCells = [rowCol];\n                  }\n                } else if (grid.options.modifierKeysToMultiSelectCells && modifierDown &&\n                  rowColSelectIndex >= 0) {\n\n                  grid.cellNav.focusedCells.splice(rowColSelectIndex, 1);\n                }\n              };\n\n              uiGridCtrl.cellNav.handleKeyDown = function (evt) {\n                var direction = uiGridCellNavService.getDirection(evt);\n                if (direction === null) {\n                  return true;\n                }\n\n                var containerId = 'body';\n                if (evt.uiGridTargetRenderContainerId) {\n                  containerId = evt.uiGridTargetRenderContainerId;\n                }\n\n                // Get the last-focused row+col combo\n                var lastRowCol = uiGridCtrl.grid.api.cellNav.getFocusedCell();\n                if (lastRowCol) {\n                  // Figure out which new row+combo we're navigating to\n                  var rowCol = uiGridCtrl.grid.renderContainers[containerId].cellNav.getNextRowCol(direction, lastRowCol.row, lastRowCol.col);\n\n                  rowCol.eventType = uiGridCellNavConstants.EVENT_TYPE.KEYDOWN;\n\n                  // Broadcast the navigation\n                  uiGridCtrl.cellNav.broadcastCellNav(rowCol);\n\n                  // Scroll to the new cell, if it's not completely visible within the render container's viewport\n                  uiGridCellNavService.scrollToIfNecessary(grid, rowCol.row, rowCol.col);\n\n                  evt.stopPropagation();\n                  evt.preventDefault();\n\n                  return false;\n                }\n              };\n            },\n            post: function ($scope, $elm, $attrs, uiGridCtrl) {\n            }\n          };\n        }\n      };\n    }]);\n\n  module.directive('uiGridRenderContainer', ['$timeout', '$document', 'gridUtil', 'uiGridConstants', 'uiGridCellNavService', 'uiGridCellNavConstants',\n    function ($timeout, $document, gridUtil, uiGridConstants, uiGridCellNavService, uiGridCellNavConstants) {\n      return {\n        replace: true,\n        priority: -99999, //this needs to run very last\n        require: ['^uiGrid', 'uiGridRenderContainer', '?^uiGridCellnav'],\n        scope: false,\n        compile: function () {\n          return {\n            post: function ($scope, $elm, $attrs, controllers) {\n              var uiGridCtrl = controllers[0],\n                 renderContainerCtrl = controllers[1];\n\n              // Skip attaching cell-nav specific logic if the directive is not attached above us\n              if (!uiGridCtrl.grid.api.cellNav) { return; }\n\n              var containerId = renderContainerCtrl.containerId;\n\n              var grid = uiGridCtrl.grid;\n\n              // Needs to run last after all renderContainers are built\n              uiGridCellNavService.decorateRenderContainers(grid);\n\n              // Let the render container be focus-able\n              $elm.attr(\"tabindex\", -1);\n\n              // Bind to keydown events in the render container\n              $elm.on('keydown', function (evt) {\n                evt.uiGridTargetRenderContainerId = containerId;\n                return uiGridCtrl.cellNav.handleKeyDown(evt);\n              });\n\n              var needFocus = false;\n              \n              // When there's a scroll event we need to make sure to re-focus the right row, because the cell contents may have changed\n              grid.api.core.on.scrollEvent($scope, function (args) {\n                // Skip if not this grid that the event was broadcast for\n                if (args.grid && args.grid.id !== uiGridCtrl.grid.id) {\n                  return;\n                }\n\n                // Skip if there's no currently-focused cell\n                if (uiGridCtrl.grid.api.cellNav.getFocusedCell() == null) {\n                  return;\n                }\n                \n                /*\n                 * If we have scrolled due to cellNav, we want to set the focus to the new cell after the \n                 * virtualisation has run, and after scroll.  If we scrolled through the browser scroll\n                 * bar or other user action, we're going to discard the focus, because it will no longer \n                 * be valid (and, noting #2423, trying to keep it causes problems)\n                 * \n                 * If cellNav triggers the scroll, we get a scrollToIfNecessary, then a viewport scroll. We\n                 * want to wait for the viewport scroll to finish, then do a refocus.  \n                 * \n                 * If someone manually scrolls we get just the viewport scroll, no scrollToIfNecessary.  We\n                 * want to just clear the focus\n                 * \n                 * Logic is:\n                 *  - if cellNav scroll, set a flag that will be resolved in the native scroll\n                 *  - if native scroll, look for the cellNav promise and resolve it\n                 *    - if not present, then use a timeout to clear focus\n                 *    - if it is present, then instead use a timeout to set focus\n                 */ \n                \n                // We have to wrap in TWO timeouts so that we run AFTER the scroll event is resolved.\n                if ( args.source === 'uiGridCellNavService.scrollToIfNecessary'){\n                  needFocus = true;\n/*\n                  focusTimeout = $timeout(function () {\n                    if ( clearFocusTimeout ){\n                      $timeout.cancel(clearFocusTimeout);\n                    }\n                    focusTimeout = $timeout(function () {\n                      if ( clearFocusTimeout ){\n                        $timeout.cancel(clearFocusTimeout);\n                      }\n                      // Get the last row+col combo\n                      var lastRowCol = uiGridCtrl.grid.api.cellNav.getFocusedCell();\n  \n                      // If the body element becomes active, re-focus on the render container so we can capture cellNav events again.\n                      //   NOTE: this happens when we navigate LET from the left-most cell (RIGHT from the right-most) and have to re-render a new\n                      //   set of cells. The cell element we are navigating to doesn't exist and focus gets lost. This will re-capture it, imperfectly...\n                      if ($document.activeElement === $document.body) {\n                        $elm[0].focus();\n                      }\n  \n                      // broadcast a cellNav event so we clear the focus on all cells\n                      uiGridCtrl.cellNav.broadcastCellNav(lastRowCol);\n                    });\n                  });\n                  */\n                } else {\n                  if ( needFocus ){\n                    $timeout(function () {\n                      $timeout(function () {\n                        // Get the last row+col combo\n                        var lastRowCol = uiGridCtrl.grid.api.cellNav.getFocusedCell();\n    \n                        // If the body element becomes active, re-focus on the render container so we can capture cellNav events again.\n                        //   NOTE: this happens when we navigate LET from the left-most cell (RIGHT from the right-most) and have to re-render a new\n                        //   set of cells. The cell element we are navigating to doesn't exist and focus gets lost. This will re-capture it, imperfectly...\n                        if ($document.activeElement === $document.body) {\n                          $elm[0].focus();\n                        }\n    \n                        // broadcast a cellNav event so we clear the focus on all cells\n                        uiGridCtrl.cellNav.broadcastCellNav(lastRowCol);\n                        \n                        needFocus = false;\n                      });\n                    });\n                  }\n                }\n              });  \n             \n            }\n          };\n        }\n      };\n    }]);\n\n  /**\n   *  @ngdoc directive\n   *  @name ui.grid.cellNav.directive:uiGridCell\n   *  @element div\n   *  @restrict A\n   *  @description Stacks on top of ui.grid.uiGridCell to provide cell navigation\n   */\n  module.directive('uiGridCell', ['$timeout', '$document', 'uiGridCellNavService', 'gridUtil', 'uiGridCellNavConstants', 'uiGridConstants',\n    function ($timeout, $document, uiGridCellNavService, gridUtil, uiGridCellNavConstants, uiGridConstants) {\n      return {\n        priority: -150, // run after default uiGridCell directive and ui.grid.edit uiGridCell\n        restrict: 'A',\n        require: '^uiGrid',\n        scope: false,\n        link: function ($scope, $elm, $attrs, uiGridCtrl) {\n          // Skip attaching cell-nav specific logic if the directive is not attached above us\n          if (!uiGridCtrl.grid.api.cellNav) { return; }\n\n          if (!$scope.col.colDef.allowCellFocus) {\n            return;\n          }\n\n          setTabEnabled();\n\n          // When a cell is clicked, broadcast a cellNav event saying that this row+col combo is now focused\n          $elm.find('div').on('click', function (evt) {\n            uiGridCtrl.cellNav.broadcastCellNav(new RowCol($scope.row, $scope.col), evt.ctrlKey || evt.metaKey);\n\n            evt.stopPropagation();\n          });\n\n          // This event is fired for all cells.  If the cell matches, then focus is set\n          $scope.$on(uiGridCellNavConstants.CELL_NAV_EVENT, function (evt, rowCol, modifierDown) {\n            if (rowCol.row === $scope.row &&\n              rowCol.col === $scope.col) {\n              if (uiGridCtrl.grid.options.modifierKeysToMultiSelectCells && modifierDown &&\n                uiGridCtrl.grid.api.cellNav.rowColSelectIndex(rowCol) === -1) {\n                clearFocus();\n              } else {\n                setFocused();\n              }\n\n              // This cellNav event came from a keydown event so we can safely refocus\n              if (rowCol.hasOwnProperty('eventType') && rowCol.eventType === uiGridCellNavConstants.EVENT_TYPE.KEYDOWN) {\n                $elm.find('div')[0].focus();\n              }\n            }\n            else if (!(uiGridCtrl.grid.options.modifierKeysToMultiSelectCells && modifierDown)) {\n              clearFocus();\n            }\n          });\n\n          function setTabEnabled() {\n            $elm.find('div').attr(\"tabindex\", -1);\n          }\n\n          function setFocused() {\n            var div = $elm.find('div');\n            div.addClass('ui-grid-cell-focus');\n          }\n\n          function clearFocus() {\n            var div = $elm.find('div');\n            div.removeClass('ui-grid-cell-focus');\n          }\n\n          $scope.$on('$destroy', function () {\n            $elm.find('div').off('click');\n          });\n        }\n      };\n    }]);\n\n})();\n\n(function () {\n  'use strict';\n\n  /**\n   * @ngdoc overview\n   * @name ui.grid.edit\n   * @description\n   *\n   *  # ui.grid.edit\n   * This module provides cell editing capability to ui.grid. The goal was to emulate keying data in a spreadsheet via\n   * a keyboard.\n   * <br/>\n   * <br/>\n   * To really get the full spreadsheet-like data entry, the ui.grid.cellNav module should be used. This will allow the\n   * user to key data and then tab, arrow, or enter to the cells beside or below.\n   *\n   * <div doc-module-components=\"ui.grid.edit\"></div>\n   */\n\n  var module = angular.module('ui.grid.edit', ['ui.grid']);\n\n  /**\n   *  @ngdoc object\n   *  @name ui.grid.edit.constant:uiGridEditConstants\n   *\n   *  @description constants available in edit module\n   */\n  module.constant('uiGridEditConstants', {\n    EDITABLE_CELL_TEMPLATE: /EDITABLE_CELL_TEMPLATE/g,\n    //must be lowercase because template bulder converts to lower\n    EDITABLE_CELL_DIRECTIVE: /editable_cell_directive/g,\n    events: {\n      BEGIN_CELL_EDIT: 'uiGridEventBeginCellEdit',\n      END_CELL_EDIT: 'uiGridEventEndCellEdit',\n      CANCEL_CELL_EDIT: 'uiGridEventCancelCellEdit'\n    }\n  });\n\n  /**\n   *  @ngdoc service\n   *  @name ui.grid.edit.service:uiGridEditService\n   *\n   *  @description Services for editing features\n   */\n  module.service('uiGridEditService', ['$q', '$templateCache', 'uiGridConstants', 'gridUtil',\n    function ($q, $templateCache, uiGridConstants, gridUtil) {\n\n      var service = {\n\n        initializeGrid: function (grid) {\n\n          service.defaultGridOptions(grid.options);\n\n          grid.registerColumnBuilder(service.editColumnBuilder);\n\n          /**\n           *  @ngdoc object\n           *  @name ui.grid.edit.api:PublicApi\n           *\n           *  @description Public Api for edit feature\n           */\n          var publicApi = {\n            events: {\n              edit: {\n                /**\n                 * @ngdoc event\n                 * @name afterCellEdit\n                 * @eventOf  ui.grid.edit.api:PublicApi\n                 * @description raised when cell editing is complete\n                 * <pre>\n                 *      gridApi.edit.on.afterCellEdit(scope,function(rowEntity, colDef){})\n                 * </pre>\n                 * @param {object} rowEntity the options.data element that was edited\n                 * @param {object} colDef the column that was edited\n                 * @param {object} newValue new value\n                 * @param {object} oldValue old value\n                 */\n                afterCellEdit: function (rowEntity, colDef, newValue, oldValue) {\n                },\n                /**\n                 * @ngdoc event\n                 * @name beginCellEdit\n                 * @eventOf  ui.grid.edit.api:PublicApi\n                 * @description raised when cell editing starts on a cell\n                 * <pre>\n                 *      gridApi.edit.on.beginCellEdit(scope,function(rowEntity, colDef){})\n                 * </pre>\n                 * @param {object} rowEntity the options.data element that was edited\n                 * @param {object} colDef the column that was edited\n                 */\n                beginCellEdit: function (rowEntity, colDef) {\n                },\n                /**\n                 * @ngdoc event\n                 * @name cancelCellEdit\n                 * @eventOf  ui.grid.edit.api:PublicApi\n                 * @description raised when cell editing is cancelled on a cell\n                 * <pre>\n                 *      gridApi.edit.on.cancelCellEdit(scope,function(rowEntity, colDef){})\n                 * </pre>\n                 * @param {object} rowEntity the options.data element that was edited\n                 * @param {object} colDef the column that was edited\n                 */\n                cancelCellEdit: function (rowEntity, colDef) {\n                }\n              }\n            },\n            methods: {\n              edit: { }\n            }\n          };\n\n          grid.api.registerEventsFromObject(publicApi.events);\n          //grid.api.registerMethodsFromObject(publicApi.methods);\n\n        },\n\n        defaultGridOptions: function (gridOptions) {\n\n          /**\n           *  @ngdoc object\n           *  @name ui.grid.edit.api:GridOptions\n           *\n           *  @description Options for configuring the edit feature, these are available to be\n           *  set using the ui-grid {@link ui.grid.class:GridOptions gridOptions}\n           */\n\n          /**\n           *  @ngdoc object\n           *  @name enableCellEdit\n           *  @propertyOf  ui.grid.edit.api:GridOptions\n           *  @description If defined, sets the default value for the editable flag on each individual colDefs\n           *  if their individual enableCellEdit configuration is not defined. Defaults to undefined.\n           */\n\n          /**\n           *  @ngdoc object\n           *  @name cellEditableCondition\n           *  @propertyOf  ui.grid.edit.api:GridOptions\n           *  @description If specified, either a value or function to be used by all columns before editing.\n           *  If falsy, then editing of cell is not allowed.\n           *  @example\n           *  <pre>\n           *  function($scope){\n           *    //use $scope.row.entity and $scope.col.colDef to determine if editing is allowed\n           *    return true;\n           *  }\n           *  </pre>\n           */\n          gridOptions.cellEditableCondition = gridOptions.cellEditableCondition === undefined ? true : gridOptions.cellEditableCondition;\n\n          /**\n           *  @ngdoc object\n           *  @name editableCellTemplate\n           *  @propertyOf  ui.grid.edit.api:GridOptions\n           *  @description If specified, cellTemplate to use as the editor for all columns.\n           *  <br/> defaults to 'ui-grid/cellTextEditor'\n           */\n\n          /**\n           *  @ngdoc object\n           *  @name enableCellEditOnFocus\n           *  @propertyOf  ui.grid.edit.api:GridOptions\n           *  @description If true, then editor is invoked as soon as cell receives focus. Default false.\n           *  <br/>_requires cellNav feature and the edit feature to be enabled_\n           */\n            //enableCellEditOnFocus can only be used if cellnav module is used\n          gridOptions.enableCellEditOnFocus = gridOptions.enableCellEditOnFocus === undefined ? false : gridOptions.enableCellEditOnFocus;\n        },\n\n        /**\n         * @ngdoc service\n         * @name editColumnBuilder\n         * @methodOf ui.grid.edit.service:uiGridEditService\n         * @description columnBuilder function that adds edit properties to grid column\n         * @returns {promise} promise that will load any needed templates when resolved\n         */\n        editColumnBuilder: function (colDef, col, gridOptions) {\n\n          var promises = [];\n\n          /**\n           *  @ngdoc object\n           *  @name ui.grid.edit.api:ColumnDef\n           *\n           *  @description Column Definition for edit feature, these are available to be\n           *  set using the ui-grid {@link ui.grid.class:GridOptions.columnDef gridOptions.columnDefs}\n           */\n\n          /**\n           *  @ngdoc object\n           *  @name enableCellEdit\n           *  @propertyOf  ui.grid.edit.api:ColumnDef\n           *  @description enable editing on column\n           */\n          colDef.enableCellEdit = colDef.enableCellEdit === undefined ? (gridOptions.enableCellEdit === undefined ?\n            (colDef.type !== 'object') : gridOptions.enableCellEdit) : colDef.enableCellEdit;\n\n          /**\n           *  @ngdoc object\n           *  @name cellEditableCondition\n           *  @propertyOf  ui.grid.edit.api:ColumnDef\n           *  @description If specified, either a value or function evaluated before editing cell.  If falsy, then editing of cell is not allowed.\n           *  @example\n           *  <pre>\n           *  function($scope){\n           *    //use $scope.row.entity and $scope.col.colDef to determine if editing is allowed\n           *    return true;\n           *  }\n           *  </pre>\n           */\n          colDef.cellEditableCondition = colDef.cellEditableCondition === undefined ? gridOptions.cellEditableCondition :  colDef.cellEditableCondition;\n\n          /**\n           *  @ngdoc object\n           *  @name editableCellTemplate\n           *  @propertyOf  ui.grid.edit.api:ColumnDef\n           *  @description cell template to be used when editing this column. Can be Url or text template\n           *  <br/>Defaults to gridOptions.editableCellTemplate\n           */\n          if (colDef.enableCellEdit) {\n            colDef.editableCellTemplate = colDef.editableCellTemplate || gridOptions.editableCellTemplate || 'ui-grid/cellEditor';\n\n            promises.push(gridUtil.getTemplate(colDef.editableCellTemplate)\n              .then(\n              function (template) {\n                col.editableCellTemplate = template;\n              },\n              function (res) {\n                // Todo handle response error here?\n                throw new Error(\"Couldn't fetch/use colDef.editableCellTemplate '\" + colDef.editableCellTemplate + \"'\");\n              }));\n          }\n\n          /**\n           *  @ngdoc object\n           *  @name enableCellEditOnFocus\n           *  @propertyOf  ui.grid.edit.api:ColumnDef\n           *  @requires ui.grid.cellNav\n           *  @description If true, then editor is invoked as soon as cell receives focus. Default false.\n           *  <br>_requires both the cellNav feature and the edit feature to be enabled_\n           */\n            //enableCellEditOnFocus can only be used if cellnav module is used\n          colDef.enableCellEditOnFocus = colDef.enableCellEditOnFocus === undefined ? gridOptions.enableCellEditOnFocus : colDef.enableCellEditOnFocus;\n\n          return $q.all(promises);\n        },\n\n        /**\n         * @ngdoc service\n         * @name isStartEditKey\n         * @methodOf ui.grid.edit.service:uiGridEditService\n         * @description  Determines if a keypress should start editing.  Decorate this service to override with your\n         * own key events.  See service decorator in angular docs.\n         * @param {Event} evt keydown event\n         * @returns {boolean} true if an edit should start\n         */\n        isStartEditKey: function (evt) {\n          if (evt.keyCode === uiGridConstants.keymap.LEFT ||\n            (evt.keyCode === uiGridConstants.keymap.TAB && evt.shiftKey) ||\n\n            evt.keyCode === uiGridConstants.keymap.RIGHT ||\n            evt.keyCode === uiGridConstants.keymap.TAB ||\n\n            evt.keyCode === uiGridConstants.keymap.UP ||\n            (evt.keyCode === uiGridConstants.keymap.ENTER && evt.shiftKey) ||\n\n            evt.keyCode === uiGridConstants.keymap.DOWN ||\n            evt.keyCode === uiGridConstants.keymap.ENTER) {\n            return false;\n\n          }\n          return true;\n        }\n\n\n      };\n\n      return service;\n\n    }]);\n\n  /**\n   *  @ngdoc directive\n   *  @name ui.grid.edit.directive:uiGridEdit\n   *  @element div\n   *  @restrict A\n   *\n   *  @description Adds editing features to the ui-grid directive.\n   *\n   *  @example\n   <example module=\"app\">\n   <file name=\"app.js\">\n   var app = angular.module('app', ['ui.grid', 'ui.grid.edit']);\n\n   app.controller('MainCtrl', ['$scope', function ($scope) {\n      $scope.data = [\n        { name: 'Bob', title: 'CEO' },\n            { name: 'Frank', title: 'Lowly Developer' }\n      ];\n\n      $scope.columnDefs = [\n        {name: 'name', enableCellEdit: true},\n        {name: 'title', enableCellEdit: true}\n      ];\n    }]);\n   </file>\n   <file name=\"index.html\">\n   <div ng-controller=\"MainCtrl\">\n   <div ui-grid=\"{ data: data, columnDefs: columnDefs }\" ui-grid-edit></div>\n   </div>\n   </file>\n   </example>\n   */\n  module.directive('uiGridEdit', ['gridUtil', 'uiGridEditService', function (gridUtil, uiGridEditService) {\n    return {\n      replace: true,\n      priority: 0,\n      require: '^uiGrid',\n      scope: false,\n      compile: function () {\n        return {\n          pre: function ($scope, $elm, $attrs, uiGridCtrl) {\n            uiGridEditService.initializeGrid(uiGridCtrl.grid);\n          },\n          post: function ($scope, $elm, $attrs, uiGridCtrl) {\n          }\n        };\n      }\n    };\n  }]);\n\n  /**\n   *  @ngdoc directive\n   *  @name ui.grid.edit.directive:uiGridCell\n   *  @element div\n   *  @restrict A\n   *\n   *  @description Stacks on top of ui.grid.uiGridCell to provide in-line editing capabilities to the cell\n   *  Editing Actions.\n   *\n   *  Binds edit start events to the uiGridCell element.  When the events fire, the gridCell element is appended\n   *  with the columnDef.editableCellTemplate element ('cellEditor.html' by default).\n   *\n   *  The editableCellTemplate should respond to uiGridEditConstants.events.BEGIN\\_CELL\\_EDIT angular event\n   *  and do the initial steps needed to edit the cell (setfocus on input element, etc).\n   *\n   *  When the editableCellTemplate recognizes that the editing is ended (blur event, Enter key, etc.)\n   *  it should emit the uiGridEditConstants.events.END\\_CELL\\_EDIT event.\n   *\n   *  If editableCellTemplate recognizes that the editing has been cancelled (esc key)\n   *  it should emit the uiGridEditConstants.events.CANCEL\\_CELL\\_EDIT event.  The original value\n   *  will be set back on the model by the uiGridCell directive.\n   *\n   *  Events that invoke editing:\n   *    - dblclick\n   *    - F2 keydown (when using cell selection)\n   *\n   *  Events that end editing:\n   *    - Dependent on the specific editableCellTemplate\n   *    - Standards should be blur and enter keydown\n   *\n   *  Events that cancel editing:\n   *    - Dependent on the specific editableCellTemplate\n   *    - Standards should be Esc keydown\n   *\n   *  Grid Events that end editing:\n   *    - uiGridConstants.events.GRID_SCROLL\n   *\n   */\n\n  /**\n   *  @ngdoc object\n   *  @name ui.grid.edit.api:GridRow\n   *\n   *  @description GridRow options for edit feature, these are available to be\n   *  set internally only, by other features\n   */\n\n  /**\n   *  @ngdoc object\n   *  @name enableCellEdit\n   *  @propertyOf  ui.grid.edit.api:GridRow\n   *  @description enable editing on row, grouping for example might disable editing on group header rows\n   */\n\n  module.directive('uiGridCell',\n    ['$compile', '$injector', '$timeout', 'uiGridConstants', 'uiGridEditConstants', 'gridUtil', '$parse', 'uiGridEditService',\n      function ($compile, $injector, $timeout, uiGridConstants, uiGridEditConstants, gridUtil, $parse, uiGridEditService) {\n        var touchstartTimeout = 500;\n\n        return {\n          priority: -100, // run after default uiGridCell directive\n          restrict: 'A',\n          scope: false,\n          require: '?^uiGrid',\n          link: function ($scope, $elm, $attrs, uiGridCtrl) {\n            if (!$scope.col.colDef.enableCellEdit || $scope.row.enableCellEdit === false) {\n              return;\n            }\n\n            var html;\n            var origCellValue;\n            var inEdit = false;\n            var isFocusedBeforeEdit = false;\n            var cellModel;\n            var cancelTouchstartTimeout;\n\n            var editCellScope;\n\n            registerBeginEditEvents();\n\n            function registerBeginEditEvents() {\n              $elm.on('dblclick', beginEdit);\n              $elm.on('keydown', beginEditKeyDown);\n              if ($scope.col.colDef.enableCellEditOnFocus) {\n                $elm.find('div').on('focus', beginEditFocus);\n              }\n\n              // Add touchstart handling. If the users starts a touch and it doesn't end after X milliseconds, then start the edit\n              $elm.on('touchstart', touchStart);\n            }\n\n            function touchStart(event) {\n              // jQuery masks events\n              if (typeof(event.originalEvent) !== 'undefined' && event.originalEvent !== undefined) {\n                event = event.originalEvent;\n              }\n\n              // Bind touchend handler\n              $elm.on('touchend', touchEnd);\n\n              // Start a timeout\n              cancelTouchstartTimeout = $timeout(function() { }, touchstartTimeout);\n\n              // Timeout's done! Start the edit\n              cancelTouchstartTimeout.then(function () {\n                // Use setTimeout to start the edit because beginEdit expects to be outside of $digest\n                setTimeout(beginEdit, 0);\n\n                // Undbind the touchend handler, we don't need it anymore\n                $elm.off('touchend', touchEnd);\n              });\n            }\n\n            // Cancel any touchstart timeout\n            function touchEnd(event) {\n              $timeout.cancel(cancelTouchstartTimeout);\n              $elm.off('touchend', touchEnd);\n            }\n\n            function cancelBeginEditEvents() {\n              $elm.off('dblclick', beginEdit);\n              $elm.off('keydown', beginEditKeyDown);\n              if ($scope.col.colDef.enableCellEditOnFocus) {\n                $elm.find('div').off('focus', beginEditFocus);\n              }\n              $elm.off('touchstart', touchStart);\n            }\n\n            function beginEditFocus(evt) {\n              // gridUtil.logDebug('begin edit');\n              if (uiGridCtrl && uiGridCtrl.cellNav) {\n                // NOTE(c0bra): This is causing a loop where focusCell causes beginEditFocus to be called....\n                uiGridCtrl.cellNav.focusCell($scope.row, $scope.col);\n              }\n\n              evt.stopPropagation();\n              beginEdit();\n            }\n\n            // If the cellNagv module is installed and we can get the uiGridCellNavConstants value injected,\n            //   then if the column has enableCellEditOnFocus set to true, we need to listen for cellNav events\n            //   to this cell and start editing when the \"focus\" reaches us\n            try {\n              var uiGridCellNavConstants = $injector.get('uiGridCellNavConstants');\n\n              if ($scope.col.colDef.enableCellEditOnFocus) {\n                $scope.$on(uiGridCellNavConstants.CELL_NAV_EVENT, function (evt, rowCol) {\n                  if (rowCol.row === $scope.row && rowCol.col === $scope.col) {\n                    beginEdit();\n                  }\n                  else {\n                    endEdit();\n                  }\n                });\n              }\n            }\n            catch (e) {}\n\n            function beginEditKeyDown(evt) {\n              if (uiGridEditService.isStartEditKey(evt)) {\n                beginEdit();\n              }\n            }\n\n            function shouldEdit(col, row) {\n              return !row.isSaving &&\n                ( angular.isFunction(col.colDef.cellEditableCondition) ?\n                    col.colDef.cellEditableCondition($scope) :\n                    col.colDef.cellEditableCondition );\n            }\n\n\n            /**\n             *  @ngdoc property\n             *  @name editDropdownOptionsArray\n             *  @propertyOf ui.grid.edit.api:ColumnDef\n             *  @description an array of values in the format\n             *  [ {id: xxx, value: xxx} ], which is populated\n             *  into the edit dropdown\n             *\n             */\n            /**\n             *  @ngdoc property\n             *  @name editDropdownIdLabel\n             *  @propertyOf ui.grid.edit.api:ColumnDef\n             *  @description the label for the \"id\" field\n             *  in the editDropdownOptionsArray.  Defaults\n             *  to 'id'\n             *  @example\n             *  <pre>\n             *    $scope.gridOptions = {\n             *      columnDefs: [\n             *        {name: 'status', editableCellTemplate: 'ui-grid/dropdownEditor',\n             *          editDropdownOptionsArray: [{code: 1, status: 'active'}, {code: 2, status: 'inactive'}],\n             *          editDropdownIdLabel: 'code', editDropdownValueLabel: 'status' }\n             *      ],\n             *  </pre>\n             *\n             */\n            /**\n             *  @ngdoc property\n             *  @name editDropdownRowEntityOptionsArrayPath\n             *  @propertyOf ui.grid.edit.api:ColumnDef\n             *  @description a path to a property on row.entity containing an\n             *  array of values in the format\n             *  [ {id: xxx, value: xxx} ], which will be used to populate\n             *  the edit dropdown.  This can be used when the dropdown values are dependent on\n             *  the backing row entity.\n             *  If this property is set then editDropdownOptionsArray will be ignored.\n             *  @example\n             *  <pre>\n             *    $scope.gridOptions = {\n             *      columnDefs: [\n             *        {name: 'status', editableCellTemplate: 'ui-grid/dropdownEditor',\n             *          editDropdownRowEntityOptionsArrayPath: 'foo.bars[0].baz',\n             *          editDropdownIdLabel: 'code', editDropdownValueLabel: 'status' }\n             *      ],\n             *  </pre>\n             *\n             */\n            /**\n             *  @ngdoc property\n             *  @name editDropdownValueLabel\n             *  @propertyOf ui.grid.edit.api:ColumnDef\n             *  @description the label for the \"value\" field\n             *  in the editDropdownOptionsArray.  Defaults\n             *  to 'value'\n             *  @example\n             *  <pre>\n             *    $scope.gridOptions = {\n             *      columnDefs: [\n             *        {name: 'status', editableCellTemplate: 'ui-grid/dropdownEditor',\n             *          editDropdownOptionsArray: [{code: 1, status: 'active'}, {code: 2, status: 'inactive'}],\n             *          editDropdownIdLabel: 'code', editDropdownValueLabel: 'status' }\n             *      ],\n             *  </pre>\n             *\n             */\n            /**\n             *  @ngdoc property\n             *  @name editDropdownFilter\n             *  @propertyOf ui.grid.edit.api:ColumnDef\n             *  @description A filter that you would like to apply to the values in the options list\n             *  of the dropdown.  For example if you were using angular-translate you might set this\n             *  to `'translate'`\n             *  @example\n             *  <pre>\n             *    $scope.gridOptions = {\n             *      columnDefs: [\n             *        {name: 'status', editableCellTemplate: 'ui-grid/dropdownEditor',\n             *          editDropdownOptionsArray: [{code: 1, status: 'active'}, {code: 2, status: 'inactive'}],\n             *          editDropdownIdLabel: 'code', editDropdownValueLabel: 'status', editDropdownFilter: 'translate' }\n             *      ],\n             *  </pre>\n             *\n             */\n            function beginEdit() {\n              // If we are already editing, then just skip this so we don't try editing twice...\n              if (inEdit) {\n                return;\n              }\n\n              if (!shouldEdit($scope.col, $scope.row)) {\n                return;\n              }\n\n              // if the cell isn't fully visible, and cellNav is present, scroll it to be fully visible before we start\n              if ( $scope.grid.api.cellNav ){\n                $scope.grid.api.cellNav.scrollToIfNecessary( $scope, $scope.row, $scope.col );\n              }\n              \n              cellModel = $parse($scope.row.getQualifiedColField($scope.col));\n              //get original value from the cell\n              origCellValue = cellModel($scope);\n\n              html = $scope.col.editableCellTemplate;\n              html = html.replace(uiGridConstants.MODEL_COL_FIELD, $scope.row.getQualifiedColField($scope.col));\n\n              var optionFilter = $scope.col.colDef.editDropdownFilter ? '|' + $scope.col.colDef.editDropdownFilter : '';\n              html = html.replace(uiGridConstants.CUSTOM_FILTERS, optionFilter);\n\n              var inputType = 'text';\n              switch ($scope.col.colDef.type){\n                case 'boolean':\n                  inputType = 'checkbox';\n                  break;\n                case 'number':\n                  inputType = 'number';\n                  break;\n                case 'date':\n                  inputType = 'date';\n                  break;\n              }\n              html = html.replace('INPUT_TYPE', inputType);\n\n              var editDropdownRowEntityOptionsArrayPath = $scope.col.colDef.editDropdownRowEntityOptionsArrayPath;\n              if (editDropdownRowEntityOptionsArrayPath) {\n                $scope.editDropdownOptionsArray =  resolveObjectFromPath($scope.row.entity, editDropdownRowEntityOptionsArrayPath);\n              }\n              else {\n                $scope.editDropdownOptionsArray = $scope.col.colDef.editDropdownOptionsArray;\n              }\n              $scope.editDropdownIdLabel = $scope.col.colDef.editDropdownIdLabel ? $scope.col.colDef.editDropdownIdLabel : 'id';\n              $scope.editDropdownValueLabel = $scope.col.colDef.editDropdownValueLabel ? $scope.col.colDef.editDropdownValueLabel : 'value';\n\n              var cellElement;\n              $scope.$apply(function () {\n                inEdit = true;\n                cancelBeginEditEvents();\n                var cellElement = angular.element(html);\n                $elm.append(cellElement);\n                editCellScope = $scope.$new();\n                $compile(cellElement)(editCellScope);\n                var gridCellContentsEl = angular.element($elm.children()[0]);\n                isFocusedBeforeEdit = gridCellContentsEl.hasClass('ui-grid-cell-focus');\n                gridCellContentsEl.addClass('ui-grid-cell-contents-hidden');\n              });\n\n              //stop editing when grid is scrolled\n              var deregOnGridScroll = $scope.col.grid.api.core.on.scrollEvent($scope, function () {\n                endEdit(true);\n                $scope.grid.api.edit.raise.afterCellEdit($scope.row.entity, $scope.col.colDef, cellModel($scope), origCellValue);\n                deregOnGridScroll();\n                deregOnEndCellEdit();\n                deregOnCancelCellEdit();\n              });\n\n              //end editing\n              var deregOnEndCellEdit = $scope.$on(uiGridEditConstants.events.END_CELL_EDIT, function (evt, retainFocus) {\n                endEdit(retainFocus);\n                $scope.grid.api.edit.raise.afterCellEdit($scope.row.entity, $scope.col.colDef, cellModel($scope), origCellValue);\n                deregOnEndCellEdit();\n                deregOnGridScroll();\n                deregOnCancelCellEdit();\n              });\n\n              //cancel editing\n              var deregOnCancelCellEdit = $scope.$on(uiGridEditConstants.events.CANCEL_CELL_EDIT, function () {\n                cancelEdit();\n                deregOnCancelCellEdit();\n                deregOnGridScroll();\n                deregOnEndCellEdit();\n              });\n\n              $scope.$broadcast(uiGridEditConstants.events.BEGIN_CELL_EDIT);\n              $scope.grid.api.edit.raise.beginCellEdit($scope.row.entity, $scope.col.colDef);\n            }\n\n            function endEdit(retainFocus) {\n              if (!inEdit) {\n                return;\n              }\n              var gridCellContentsEl = angular.element($elm.children()[0]);\n              //remove edit element\n              editCellScope.$destroy();\n              angular.element($elm.children()[1]).remove();\n              gridCellContentsEl.removeClass('ui-grid-cell-contents-hidden');\n              if (retainFocus && isFocusedBeforeEdit) {\n                gridCellContentsEl[0].focus();\n              }\n              isFocusedBeforeEdit = false;\n              inEdit = false;\n              registerBeginEditEvents();\n              $scope.grid.api.core.notifyDataChange( uiGridConstants.dataChange.EDIT );\n            }\n\n            function cancelEdit() {\n              if (!inEdit) {\n                return;\n              }\n              cellModel.assign($scope, origCellValue);\n              $scope.$apply();\n\n              $scope.grid.api.edit.raise.cancelCellEdit($scope.row.entity, $scope.col.colDef);\n              endEdit(true);\n            }\n\n            // resolves a string path against the given object\n            // shamelessly borrowed from\n            // http://stackoverflow.com/questions/6491463/accessing-nested-javascript-objects-with-string-key\n            function resolveObjectFromPath(object, path) {\n              path = path.replace(/\\[(\\w+)\\]/g, '.$1'); // convert indexes to properties\n              path = path.replace(/^\\./, '');           // strip a leading dot\n              var a = path.split('.');\n              while (a.length) {\n                  var n = a.shift();\n                  if (n in object) {\n                      object = object[n];\n                  } else {\n                      return;\n                  }\n              }\n              return object;\n            }\n\n          }\n        };\n      }]);\n\n  /**\n   *  @ngdoc directive\n   *  @name ui.grid.edit.directive:uiGridEditor\n   *  @element div\n   *  @restrict A\n   *\n   *  @description input editor directive for editable fields.\n   *  Provides EndEdit and CancelEdit events\n   *\n   *  Events that end editing:\n   *     blur and enter keydown\n   *\n   *  Events that cancel editing:\n   *    - Esc keydown\n   *\n   */\n  module.directive('uiGridEditor',\n    ['gridUtil', 'uiGridConstants', 'uiGridEditConstants',\n      function (gridUtil, uiGridConstants, uiGridEditConstants) {\n        return {\n          scope: true,\n          require: ['?^uiGrid', '?^uiGridRenderContainer'],\n          compile: function () {\n            return {\n              pre: function ($scope, $elm, $attrs) {\n\n              },\n              post: function ($scope, $elm, $attrs, controllers) {\n                var uiGridCtrl, renderContainerCtrl;\n                if (controllers[0]) { uiGridCtrl = controllers[0]; }\n                if (controllers[1]) { renderContainerCtrl = controllers[1]; }\n\n                //set focus at start of edit\n                $scope.$on(uiGridEditConstants.events.BEGIN_CELL_EDIT, function () {\n                  $elm[0].focus();\n                  $elm[0].select();\n                  $elm.on('blur', function (evt) {\n                    $scope.stopEdit(evt);\n                  });\n                });\n\n\n               $scope.deepEdit = false;\n\n               $scope.stopEdit = function (evt) {\n                  if ($scope.inputForm && !$scope.inputForm.$valid) {\n                    evt.stopPropagation();\n                    $scope.$emit(uiGridEditConstants.events.CANCEL_CELL_EDIT);\n                  }\n                  else {\n                    $scope.$emit(uiGridEditConstants.events.END_CELL_EDIT);\n                  }\n                  $scope.deepEdit = false;\n                };\n\n                $elm.on('click', function (evt) {\n                  $scope.deepEdit = true;\n                });\n\n                $elm.on('keydown', function (evt) {\n                  switch (evt.keyCode) {\n                    case uiGridConstants.keymap.ESC:\n                      evt.stopPropagation();\n                      $scope.$emit(uiGridEditConstants.events.CANCEL_CELL_EDIT);\n                      break;\n                    case uiGridConstants.keymap.ENTER: // Enter (Leave Field)\n                      $scope.stopEdit(evt);\n                      break;\n                    case uiGridConstants.keymap.TAB:\n                      $scope.stopEdit(evt);\n                      break;\n                  }\n\n                  if ($scope.deepEdit) {\n                    switch (evt.keyCode) {\n                      case uiGridConstants.keymap.LEFT:\n                        evt.stopPropagation();\n                        break;\n                      case uiGridConstants.keymap.RIGHT:\n                        evt.stopPropagation();\n                        break;\n                      case uiGridConstants.keymap.UP:\n                        evt.stopPropagation();\n                        break;\n                      case uiGridConstants.keymap.DOWN:\n                        evt.stopPropagation();\n                        break;\n                    }\n                  }\n                  // Pass the keydown event off to the cellNav service, if it exists\n                  else if (uiGridCtrl && uiGridCtrl.hasOwnProperty('cellNav') && renderContainerCtrl) {\n                    evt.uiGridTargetRenderContainerId = renderContainerCtrl.containerId;\n                    uiGridCtrl.cellNav.handleKeyDown(evt);\n                  }\n\n                  return true;\n                });\n              }\n            };\n          }\n        };\n      }]);\n\n  /**\n   *  @ngdoc directive\n   *  @name ui.grid.edit.directive:input\n   *  @element input\n   *  @restrict E\n   *\n   *  @description directive to provide binding between input[date] value and ng-model for angular 1.2\n   *  It is similar to input[date] directive of angular 1.3\n   *\n   *  Supported date format for input is 'yyyy-MM-dd'\n   *  The directive will set the $valid property of input element and the enclosing form to false if\n   *  model is invalid date or value of input is entered wrong.\n   *\n   */\n    module.directive('uiGridEditor', ['$filter', function ($filter) {\n      function parseDateString(dateString) {\n        if (typeof(dateString) === 'undefined' || dateString === '') {\n          return null;\n        }\n        var parts = dateString.split('-');\n        if (parts.length !== 3) {\n          return null;\n        }\n        var year = parseInt(parts[0], 10);\n        var month = parseInt(parts[1], 10);\n        var day = parseInt(parts[2], 10);\n\n        if (month < 1 || year < 1 || day < 1) {\n          return null;\n        }\n        return new Date(year, (month - 1), day);\n      }\n      return {\n        priority: -100, // run after default uiGridEditor directive\n        require: '?ngModel',\n        link: function (scope, element, attrs, ngModel) {\n\n          if (angular.version.minor === 2 && attrs.type && attrs.type === 'date' && ngModel) {\n\n            ngModel.$formatters.push(function (modelValue) {\n              ngModel.$setValidity(null,(!modelValue || !isNaN(modelValue.getTime())));\n              return $filter('date')(modelValue, 'yyyy-MM-dd');\n            });\n\n            ngModel.$parsers.push(function (viewValue) {\n              if (viewValue && viewValue.length > 0) {\n                var dateValue = parseDateString(viewValue);\n                ngModel.$setValidity(null, (dateValue && !isNaN(dateValue.getTime())));\n                return dateValue;\n              }\n              else {\n                ngModel.$setValidity(null, true);\n                return null;\n              }\n            });\n          }\n        }\n      };\n    }]);\n\n\n  /**\n   *  @ngdoc directive\n   *  @name ui.grid.edit.directive:uiGridEditDropdown\n   *  @element div\n   *  @restrict A\n   *\n   *  @description dropdown editor for editable fields.\n   *  Provides EndEdit and CancelEdit events\n   *\n   *  Events that end editing:\n   *     blur and enter keydown, and any left/right nav\n   *\n   *  Events that cancel editing:\n   *    - Esc keydown\n   *\n   */\n  module.directive('uiGridEditDropdown',\n    ['uiGridConstants', 'uiGridEditConstants',\n      function (uiGridConstants, uiGridEditConstants) {\n        return {\n          scope: true,\n          compile: function () {\n            return {\n              pre: function ($scope, $elm, $attrs) {\n\n              },\n              post: function ($scope, $elm, $attrs) {\n\n                //set focus at start of edit\n                $scope.$on(uiGridEditConstants.events.BEGIN_CELL_EDIT, function () {\n                  $elm[0].focus();\n                  $elm[0].style.width = ($elm[0].parentElement.offsetWidth - 1) + 'px';\n                  $elm.on('blur', function (evt) {\n                    $scope.stopEdit(evt);\n                  });\n                });\n\n\n                $scope.stopEdit = function (evt) {\n                  // no need to validate a dropdown - invalid values shouldn't be\n                  // available in the list\n                  $scope.$emit(uiGridEditConstants.events.END_CELL_EDIT);\n                };\n\n                $elm.on('keydown', function (evt) {\n                  switch (evt.keyCode) {\n                    case uiGridConstants.keymap.ESC:\n                      evt.stopPropagation();\n                      $scope.$emit(uiGridEditConstants.events.CANCEL_CELL_EDIT);\n                      break;\n                    case uiGridConstants.keymap.ENTER: // Enter (Leave Field)\n                      $scope.stopEdit(evt);\n                      break;\n                    case uiGridConstants.keymap.LEFT:\n                      $scope.stopEdit(evt);\n                      break;\n                    case uiGridConstants.keymap.RIGHT:\n                      $scope.stopEdit(evt);\n                      break;\n                    case uiGridConstants.keymap.UP:\n                      evt.stopPropagation();\n                      break;\n                    case uiGridConstants.keymap.DOWN:\n                      evt.stopPropagation();\n                      break;\n                    case uiGridConstants.keymap.TAB:\n                      $scope.stopEdit(evt);\n                      break;\n                  }\n                  return true;\n                });\n              }\n            };\n          }\n        };\n      }]);\n\n})();\n\n(function () {\n  'use strict';\n\n  /**\n   * @ngdoc overview\n   * @name ui.grid.expandable\n   * @description\n   *\n   *  # ui.grid.expandable\n   * This module provides the ability to create subgrids with the ability to expand a row\n   * to show the subgrid.\n   *\n   * <div doc-module-components=\"ui.grid.expandable\"></div>\n   */\n  var module = angular.module('ui.grid.expandable', ['ui.grid']);\n\n  /**\n   *  @ngdoc service\n   *  @name ui.grid.expandable.service:uiGridExpandableService\n   *\n   *  @description Services for the expandable grid\n   */\n  module.service('uiGridExpandableService', ['gridUtil', '$compile', function (gridUtil, $compile) {\n    var service = {\n      initializeGrid: function (grid) {\n        \n        grid.expandable = {};\n        grid.expandable.expandedAll = false;\n\n        /**\n         *  @ngdoc object\n         *  @name enableExpandable\n         *  @propertyOf  ui.grid.expandable.api:GridOptions\n         *  @description Whether or not to use expandable feature, allows you to turn off expandable on specific grids\n         *  within your application, or in specific modes on _this_ grid. Defaults to true.  \n         *  @example\n         *  <pre>\n         *    $scope.gridOptions = {\n         *      enableExpandable: false\n         *    }\n         *  </pre>  \n         */\n        grid.options.enableExpandable = grid.options.enableExpandable !== false;\n        \n        /**\n         *  @ngdoc object\n         *  @name expandableRowHeight\n         *  @propertyOf  ui.grid.expandable.api:GridOptions\n         *  @description Height in pixels of the expanded subgrid.  Defaults to\n         *  150\n         *  @example\n         *  <pre>\n         *    $scope.gridOptions = {\n         *      expandableRowHeight: 150\n         *    }\n         *  </pre>  \n         */\n        grid.options.expandableRowHeight = grid.options.expandableRowHeight || 150;\n\n        /**\n         *  @ngdoc object\n         *  @name \n         *  @propertyOf  ui.grid.expandable.api:GridOptions\n         *  @description Width in pixels of the expandable column. Defaults to 40\n         *  @example\n         *  <pre>\n         *    $scope.gridOptions = {\n         *      expandableRowHeaderWidth: 40\n         *    }\n         *  </pre>  \n         */\n        grid.options.expandableRowHeaderWidth = grid.options.expandableRowHeaderWidth || 40;\n\n        /**\n         *  @ngdoc object\n         *  @name expandableRowTemplate\n         *  @propertyOf  ui.grid.expandable.api:GridOptions\n         *  @description Mandatory. The template for your expanded row\n         *  @example\n         *  <pre>\n         *    $scope.gridOptions = {\n         *      expandableRowTemplate: 'expandableRowTemplate.html'\n         *    }\n         *  </pre>  \n         */\n        if ( grid.options.enableExpandable && !grid.options.expandableRowTemplate ){\n          gridUtil.logError( 'You have not set the expandableRowTemplate, disabling expandable module' );\n          grid.options.enableExpandable = false;\n        }\n\n        /**\n         *  @ngdoc object\n         *  @name ui.grid.expandable.api:PublicApi\n         *\n         *  @description Public Api for expandable feature\n         */\n        /**\n         *  @ngdoc object\n         *  @name ui.grid.expandable.api:GridOptions\n         *\n         *  @description Options for configuring the expandable feature, these are available to be  \n         *  set using the ui-grid {@link ui.grid.class:GridOptions gridOptions}\n         */\n        var publicApi = {\n          events: {\n            expandable: {\n              /**\n               * @ngdoc event\n               * @name rowExpandedStateChanged\n               * @eventOf  ui.grid.expandable.api:PublicApi\n               * @description raised when cell editing is complete\n               * <pre>\n               *      gridApi.expandable.on.rowExpandedStateChanged(scope,function(row){})\n               * </pre>\n               * @param {GridRow} row the row that was expanded\n               */\n              rowExpandedStateChanged: function (scope, row) {\n              }\n            }\n          },\n          \n          methods: {\n            expandable: {\n              /**\n               * @ngdoc method\n               * @name toggleRowExpansion\n               * @methodOf  ui.grid.expandable.api:PublicApi\n               * @description Toggle a specific row\n               * <pre>\n               *      gridApi.expandable.toggleRowExpansion(rowEntity);\n               * </pre>\n               * @param {object} rowEntity the data entity for the row you want to expand\n               */              \n              toggleRowExpansion: function (rowEntity) {\n                var row = grid.getRow(rowEntity);\n                if (row !== null) {\n                  service.toggleRowExpansion(grid, row);\n                }\n              },\n\n              /**\n               * @ngdoc method\n               * @name expandAllRows\n               * @methodOf  ui.grid.expandable.api:PublicApi\n               * @description Expand all subgrids.\n               * <pre>\n               *      gridApi.expandable.expandAllRows();\n               * </pre>\n               */              \n              expandAllRows: function() {\n                service.expandAllRows(grid);\n              },\n\n              /**\n               * @ngdoc method\n               * @name collapseAllRows\n               * @methodOf  ui.grid.expandable.api:PublicApi\n               * @description Collapse all subgrids.\n               * <pre>\n               *      gridApi.expandable.collapseAllRows();\n               * </pre>\n               */              \n              collapseAllRows: function() {\n                service.collapseAllRows(grid);\n              },\n\n              /**\n               * @ngdoc method\n               * @name toggleAllRows\n               * @methodOf  ui.grid.expandable.api:PublicApi\n               * @description Toggle all subgrids.\n               * <pre>\n               *      gridApi.expandable.toggleAllRows();\n               * </pre>\n               */              \n              toggleAllRows: function() {\n                service.toggleAllRows(grid);\n              }\n            }\n          }\n        };\n        grid.api.registerEventsFromObject(publicApi.events);\n        grid.api.registerMethodsFromObject(publicApi.methods);\n      },\n      \n      toggleRowExpansion: function (grid, row) {\n        row.isExpanded = !row.isExpanded;\n        if (row.isExpanded) {\n          row.height = row.grid.options.rowHeight + grid.options.expandableRowHeight;\n        }\n        else {\n          row.height = row.grid.options.rowHeight;\n          grid.expandable.expandedAll = false;\n        }\n        grid.api.expandable.raise.rowExpandedStateChanged(row);\n      },\n      \n      expandAllRows: function(grid, $scope) {\n        angular.forEach(grid.renderContainers.body.visibleRowCache, function(row) {\n          if (!row.isExpanded) {\n            service.toggleRowExpansion(grid, row);\n          }\n        });\n        grid.expandable.expandedAll = true;\n        grid.refresh();\n      },\n      \n      collapseAllRows: function(grid) {\n        angular.forEach(grid.renderContainers.body.visibleRowCache, function(row) {\n          if (row.isExpanded) {\n            service.toggleRowExpansion(grid, row);\n          }\n        });\n        grid.expandable.expandedAll = false;\n        grid.refresh();\n      },\n\n      toggleAllRows: function(grid) {\n        if (grid.expandable.expandedAll) {\n          service.collapseAllRows(grid);\n        }\n        else {\n          service.expandAllRows(grid);\n        }\n      }\n    };\n    return service;\n  }]);\n\n  /**\n   *  @ngdoc object\n   *  @name enableExpandableRowHeader\n   *  @propertyOf  ui.grid.expandable.api:GridOptions\n   *  @description Show a rowHeader to provide the expandable buttons.  If set to false then implies\n   *  you're going to use a custom method for expanding and collapsing the subgrids. Defaults to true.\n   *  @example\n   *  <pre>\n   *    $scope.gridOptions = {\n   *      enableExpandableRowHeader: false\n   *    }\n   *  </pre>  \n   */\n  module.directive('uiGridExpandable', ['uiGridExpandableService', '$templateCache',\n    function (uiGridExpandableService, $templateCache) {\n      return {\n        replace: true,\n        priority: 0,\n        require: '^uiGrid',\n        scope: false,\n        compile: function () {\n          return {\n            pre: function ($scope, $elm, $attrs, uiGridCtrl) {\n              if ( uiGridCtrl.grid.options.enableExpandableRowHeader !== false ) {\n                var expandableRowHeaderColDef = {\n                  name: 'expandableButtons', \n                  displayName: '', \n                  exporterSuppressExport: true, \n                  enableColumnResizing: false, \n                  enableColumnMenu: false,\n                  width: uiGridCtrl.grid.options.expandableRowHeaderWidth || 40\n                };\n                expandableRowHeaderColDef.cellTemplate = $templateCache.get('ui-grid/expandableRowHeader');\n                expandableRowHeaderColDef.headerCellTemplate = $templateCache.get('ui-grid/expandableTopRowHeader');\n                uiGridCtrl.grid.addRowHeaderColumn(expandableRowHeaderColDef);\n              }\n              uiGridExpandableService.initializeGrid(uiGridCtrl.grid);\n            },\n            post: function ($scope, $elm, $attrs, uiGridCtrl) {\n            }\n          };\n        }\n      };\n    }]);\n\n  /**\n   *  @ngdoc directive\n   *  @name ui.grid.expandable.directive:uiGrid\n   *  @description stacks on the uiGrid directive to register child grid with parent row when child is created\n   */\n  module.directive('uiGrid', ['uiGridExpandableService', '$templateCache',\n    function (uiGridExpandableService, $templateCache) {\n      return {\n        replace: true,\n        priority: 1000,\n        require: '^uiGrid',\n        scope: false,\n        compile: function () {\n          return {\n            pre: function ($scope, $elm, $attrs, uiGridCtrl) {\n\n              uiGridCtrl.grid.api.core.on.renderingComplete($scope, function() {\n                //if a parent grid row is on the scope, then add the parentRow property to this childGrid\n                if ($scope.row && $scope.row.grid && $scope.row.grid.options && $scope.row.grid.options.enableExpandable) {\n\n                  /**\n                   *  @ngdoc directive\n                   *  @name ui.grid.expandable.class:Grid\n                   *  @description Additional Grid properties added by expandable module\n                   */\n\n                  /**\n                   *  @ngdoc object\n                   *  @name parentRow\n                   *  @propertyOf ui.grid.expandable.class:Grid\n                   *  @description reference to the expanded parent row that owns this grid\n                   */\n                  uiGridCtrl.grid.parentRow = $scope.row;\n\n                  //todo: adjust height on parent row when child grid height changes. we need some sort of gridHeightChanged event\n                 // uiGridCtrl.grid.core.on.canvasHeightChanged($scope, function(oldHeight, newHeight) {\n                 //   uiGridCtrl.grid.parentRow = newHeight;\n                 // });\n                }\n\n              });\n            },\n            post: function ($scope, $elm, $attrs, uiGridCtrl) {\n\n            }\n          };\n        }\n      };\n    }]);\n\n  /**\n   *  @ngdoc directive\n   *  @name ui.grid.expandable.directive:uiGridExpandableRow\n   *  @description directive to render the expandable row template\n   */\n  module.directive('uiGridExpandableRow',\n  ['uiGridExpandableService', '$timeout', '$compile', 'uiGridConstants','gridUtil','$interval', '$log',\n    function (uiGridExpandableService, $timeout, $compile, uiGridConstants, gridUtil, $interval, $log) {\n\n      return {\n        replace: false,\n        priority: 0,\n        scope: false,\n\n        compile: function () {\n          return {\n            pre: function ($scope, $elm, $attrs, uiGridCtrl) {\n              gridUtil.getTemplate($scope.grid.options.expandableRowTemplate).then(\n                function (template) {\n                  if ($scope.grid.options.expandableRowScope) {\n                    var expandableRowScope = $scope.grid.options.expandableRowScope;\n                    for (var property in expandableRowScope) {\n                      if (expandableRowScope.hasOwnProperty(property)) {\n                        $scope[property] = expandableRowScope[property];\n                      }\n                    }\n                  }\n                  var expandedRowElement = $compile(template)($scope);\n                  $elm.append(expandedRowElement);\n                  $scope.row.expandedRendered = true;\n              });\n            },\n\n            post: function ($scope, $elm, $attrs, uiGridCtrl) {\n              $scope.$on('$destroy', function() {\n                $scope.row.expandedRendered = false;\n              });\n            }\n          };\n        }\n      };\n    }]);\n\n  /**\n   *  @ngdoc directive\n   *  @name ui.grid.expandable.directive:uiGridRow\n   *  @description stacks on the uiGridRow directive to add support for expandable rows\n   */\n  module.directive('uiGridRow',\n    ['$compile', 'gridUtil', '$templateCache',\n      function ($compile, gridUtil, $templateCache) {\n        return {\n          priority: -200,\n          scope: false,\n          compile: function ($elm, $attrs) {\n            return {\n              pre: function ($scope, $elm, $attrs, controllers) {\n\n                $scope.expandableRow = {};\n\n                $scope.expandableRow.shouldRenderExpand = function () {\n                  var ret = $scope.colContainer.name === 'body' &&  $scope.grid.options.enableExpandable !== false && $scope.row.isExpanded && (!$scope.grid.isScrollingVertically || $scope.row.expandedRendered);\n                  return ret;\n                };\n\n                $scope.expandableRow.shouldRenderFiller = function () {\n                  var ret = $scope.row.isExpanded && ( $scope.colContainer.name !== 'body' || ($scope.grid.isScrollingVertically && !$scope.row.expandedRendered));\n                  return ret;\n                };\n\n                  function updateRowContainerWidth() {\n                      var grid = $scope.grid;\n                      var colWidth = 0;\n                      angular.forEach(grid.columns, function (column) {\n                          if (column.renderContainer === 'left') {\n                            colWidth += column.width;\n                          }\n                      });\n                      colWidth = Math.floor(colWidth);\n                      return '.grid' + grid.id + ' .ui-grid-pinned-container-' + $scope.colContainer.name + ', .grid' + grid.id +\n                          ' .ui-grid-pinned-container-' + $scope.colContainer.name + ' .ui-grid-render-container-' + $scope.colContainer.name +\n                          ' .ui-grid-viewport .ui-grid-canvas .ui-grid-row { width: ' + colWidth + 'px; }';\n                  }\n\n                  if ($scope.colContainer.name === 'left') {\n                      $scope.grid.registerStyleComputation({\n                          priority: 15,\n                          func: updateRowContainerWidth\n                      });\n                  }\n\n              },\n              post: function ($scope, $elm, $attrs, controllers) {\n              }\n            };\n          }\n        };\n      }]);\n\n  /**\n   *  @ngdoc directive\n   *  @name ui.grid.expandable.directive:uiGridViewport\n   *  @description stacks on the uiGridViewport directive to append the expandable row html elements to the\n   *  default gridRow template\n   */\n  module.directive('uiGridViewport',\n    ['$compile', 'gridUtil', '$templateCache',\n      function ($compile, gridUtil, $templateCache) {\n        return {\n          priority: -200,\n          scope: false,\n          compile: function ($elm, $attrs) {\n            var rowRepeatDiv = angular.element($elm.children().children()[0]);\n            var expandedRowFillerElement = $templateCache.get('ui-grid/expandableScrollFiller');\n            var expandedRowElement = $templateCache.get('ui-grid/expandableRow');\n            rowRepeatDiv.append(expandedRowElement);\n            rowRepeatDiv.append(expandedRowFillerElement);\n            return {\n              pre: function ($scope, $elm, $attrs, controllers) {\n              },\n              post: function ($scope, $elm, $attrs, controllers) {\n              }\n            };\n          }\n        };\n      }]);\n\n})();\n\n/* global console */\n\n(function () {\n  'use strict';\n\n  /**\n   * @ngdoc overview\n   * @name ui.grid.exporter\n   * @description\n   *\n   *  # ui.grid.exporter\n   * This module provides the ability to exporter data from the grid.  \n   * \n   * Data can be exported in a range of formats, and all data, visible \n   * data, or selected rows can be exported, with all columns or visible\n   * columns.\n   * \n   * No UI is provided, the caller should provide their own UI/buttons \n   * as appropriate, or enable the gridMenu\n   * \n   * <br/>\n   * <br/>\n   *\n   * <div doc-module-components=\"ui.grid.exporter\"></div>\n   */\n\n  var module = angular.module('ui.grid.exporter', ['ui.grid']);\n\n  /**\n   *  @ngdoc object\n   *  @name ui.grid.exporter.constant:uiGridExporterConstants\n   *\n   *  @description constants available in exporter module\n   */\n  /**\n   * @ngdoc property\n   * @propertyOf ui.grid.exporter.constant:uiGridExporterConstants\n   * @name ALL\n   * @description export all data, including data not visible.  Can\n   * be set for either rowTypes or colTypes\n   */\n  /**\n   * @ngdoc property\n   * @propertyOf ui.grid.exporter.constant:uiGridExporterConstants\n   * @name VISIBLE\n   * @description export only visible data, including data not visible.  Can\n   * be set for either rowTypes or colTypes\n   */\n  /**\n   * @ngdoc property\n   * @propertyOf ui.grid.exporter.constant:uiGridExporterConstants\n   * @name SELECTED\n   * @description export all data, including data not visible.  Can\n   * be set only for rowTypes, selection of only some columns is \n   * not supported\n   */\n  module.constant('uiGridExporterConstants', {\n    featureName: 'exporter',\n    ALL: 'all',\n    VISIBLE: 'visible',\n    SELECTED: 'selected',\n    CSV_CONTENT: 'CSV_CONTENT',\n    BUTTON_LABEL: 'BUTTON_LABEL',\n    FILE_NAME: 'FILE_NAME'\n  });\n\n  /**\n   *  @ngdoc service\n   *  @name ui.grid.exporter.service:uiGridExporterService\n   *\n   *  @description Services for exporter feature\n   */\n  module.service('uiGridExporterService', ['$q', 'uiGridExporterConstants', 'uiGridSelectionConstants', 'gridUtil', '$compile', '$interval', 'i18nService',\n    function ($q, uiGridExporterConstants, uiGridSelectionConstants, gridUtil, $compile, $interval, i18nService) {\n\n      var service = {\n\n        initializeGrid: function (grid) {\n\n          //add feature namespace and any properties to grid for needed state\n          grid.exporter = {};\n          this.defaultGridOptions(grid.options);\n\n          /**\n           *  @ngdoc object\n           *  @name ui.grid.exporter.api:PublicApi\n           *\n           *  @description Public Api for exporter feature\n           */\n          var publicApi = {\n            events: {\n              exporter: {\n              }\n            },\n            methods: {\n              exporter: {\n                /**\n                 * @ngdoc function\n                 * @name csvExport\n                 * @methodOf  ui.grid.exporter.api:PublicApi\n                 * @description Exports rows from the grid in csv format, \n                 * the data exported is selected based on the provided options\n                 * @param {string} rowTypes which rows to export, valid values are\n                 * uiGridExporterConstants.ALL, uiGridExporterConstants.VISIBLE,\n                 * uiGridExporterConstants.SELECTED\n                 * @param {string} colTypes which columns to export, valid values are\n                 * uiGridExporterConstants.ALL, uiGridExporterConstants.VISIBLE\n                 */\n                csvExport: function (rowTypes, colTypes) {\n                  service.csvExport(grid, rowTypes, colTypes);\n                },\n                /**\n                 * @ngdoc function\n                 * @name pdfExport\n                 * @methodOf  ui.grid.exporter.api:PublicApi\n                 * @description Exports rows from the grid in pdf format, \n                 * the data exported is selected based on the provided options\n                 * Note that this function has a dependency on pdfMake, all\n                 * going well this has been installed for you.\n                 * The resulting pdf opens in a new browser window.\n                 * @param {string} rowTypes which rows to export, valid values are\n                 * uiGridExporterConstants.ALL, uiGridExporterConstants.VISIBLE,\n                 * uiGridExporterConstants.SELECTED\n                 * @param {string} colTypes which columns to export, valid values are\n                 * uiGridExporterConstants.ALL, uiGridExporterConstants.VISIBLE\n                 */\n                pdfExport: function (rowTypes, colTypes) {\n                  service.pdfExport(grid, rowTypes, colTypes);\n                }\n              }\n            }\n          };\n\n          grid.api.registerEventsFromObject(publicApi.events);\n\n          grid.api.registerMethodsFromObject(publicApi.methods);\n          \n          if (grid.api.core.addToGridMenu){\n            service.addToMenu( grid );\n          } else {\n            // order of registration is not guaranteed, register in a little while\n            $interval( function() {\n              if (grid.api.core.addToGridMenu){\n                service.addToMenu( grid );\n              }              \n            }, 100, 1);\n          }\n\n        },\n\n        defaultGridOptions: function (gridOptions) {\n          //default option to true unless it was explicitly set to false\n          /**\n           * @ngdoc object\n           * @name ui.grid.exporter.api:GridOptions\n           *\n           * @description GridOptions for exporter feature, these are available to be  \n           * set using the ui-grid {@link ui.grid.class:GridOptions gridOptions}\n           */\n          /**\n           * @ngdoc object\n           * @name ui.grid.exporter.api:ColumnDef\n           * @description ColumnDef settings for exporter\n           */\n          /**\n           * @ngdoc object\n           * @name exporterSuppressMenu\n           * @propertyOf  ui.grid.exporter.api:GridOptions\n           * @description Don't show the export menu button, implying the user\n           * will roll their own UI for calling the exporter\n           * <br/>Defaults to false\n           */\n          gridOptions.exporterSuppressMenu = gridOptions.exporterSuppressMenu === true;\n          /**\n           * @ngdoc object\n           * @name exporterMenuLabel\n           * @propertyOf  ui.grid.exporter.api:GridOptions\n           * @description The text to show on the exporter menu button\n           * link\n           * <br/>Defaults to 'Export'\n           */\n          gridOptions.exporterMenuLabel = gridOptions.exporterMenuLabel ? gridOptions.exporterMenuLabel : 'Export';\n          /**\n           * @ngdoc object\n           * @name exporterSuppressColumns\n           * @propertyOf  ui.grid.exporter.api:GridOptions\n           * @description Columns that should not be exported.  The selectionRowHeader is already automatically\n           * suppressed, but if you had a button column or some other \"system\" column that shouldn't be shown in the\n           * output then add it in this list.  You should provide an array of column names.\n           * <br/>Defaults to: []\n           * <pre>\n           *   gridOptions.exporterSuppressColumns = [ 'buttons' ];\n           * </pre>\n           */\n          gridOptions.exporterSuppressColumns = gridOptions.exporterSuppressColumns ? gridOptions.exporterSuppressColumns : [];\n          /**\n           * @ngdoc object\n           * @name exporterCsvColumnSeparator\n           * @propertyOf  ui.grid.exporter.api:GridOptions\n           * @description The character to use as column separator\n           * link\n           * <br/>Defaults to ','\n           */\n          gridOptions.exporterCsvColumnSeparator = gridOptions.exporterCsvColumnSeparator ? gridOptions.exporterCsvColumnSeparator : ',';\n          /**\n           * @ngdoc object\n           * @name exporterCsvFilename\n           * @propertyOf  ui.grid.exporter.api:GridOptions\n           * @description The default filename to use when saving the downloaded csv.  \n           * This will only work in some browsers.\n           * <br/>Defaults to 'download.csv'\n           */\n          gridOptions.exporterCsvFilename = gridOptions.exporterCsvFilename ? gridOptions.exporterCsvFilename : 'download.csv';\n          /**\n           * @ngdoc object\n           * @name exporterPdfDefaultStyle\n           * @propertyOf  ui.grid.exporter.api:GridOptions\n           * @description The default style in pdfMake format\n           * <br/>Defaults to:\n           * <pre>\n           *   {\n           *     fontSize: 11\n           *   }\n           * </pre>\n           */\n          gridOptions.exporterPdfDefaultStyle = gridOptions.exporterPdfDefaultStyle ? gridOptions.exporterPdfDefaultStyle : { fontSize: 11 };\n          /**\n           * @ngdoc object\n           * @name exporterPdfTableStyle\n           * @propertyOf  ui.grid.exporter.api:GridOptions\n           * @description The table style in pdfMake format\n           * <br/>Defaults to:\n           * <pre>\n           *   {\n           *     margin: [0, 5, 0, 15]\n           *   }\n           * </pre>\n           */\n          gridOptions.exporterPdfTableStyle = gridOptions.exporterPdfTableStyle ? gridOptions.exporterPdfTableStyle : { margin: [0, 5, 0, 15] };\n          /**\n           * @ngdoc object\n           * @name exporterPdfTableHeaderStyle\n           * @propertyOf  ui.grid.exporter.api:GridOptions\n           * @description The tableHeader style in pdfMake format\n           * <br/>Defaults to:\n           * <pre>\n           *   {\n           *     bold: true,\n           *     fontSize: 12,\n           *     color: 'black'\n           *   }\n           * </pre>\n           */\n          gridOptions.exporterPdfTableHeaderStyle = gridOptions.exporterPdfTableHeaderStyle ? gridOptions.exporterPdfTableHeaderStyle : { bold: true, fontSize: 12, color: 'black' };\n          /**\n           * @ngdoc object\n           * @name exporterPdfHeader\n           * @propertyOf  ui.grid.exporter.api:GridOptions\n           * @description The header section for pdf exports.  Can be\n           * simple text:\n           * <pre>\n           *   gridOptions.exporterPdfHeader = 'My Header';\n           * </pre>\n           * Can be a more complex object in pdfMake format:\n           * <pre>\n           *   gridOptions.exporterPdfHeader = {\n           *     columns: [\n           *       'Left part',\n           *       { text: 'Right part', alignment: 'right' }\n           *     ]\n           *   };\n           * </pre>\n           * Or can be a function, allowing page numbers and the like\n           * <pre>\n           *   gridOptions.exporterPdfHeader: function(currentPage, pageCount) { return currentPage.toString() + ' of ' + pageCount; };\n           * </pre>\n           */\n          gridOptions.exporterPdfHeader = gridOptions.exporterPdfHeader ? gridOptions.exporterPdfHeader : null;\n          /**\n           * @ngdoc object\n           * @name exporterPdfFooter\n           * @propertyOf  ui.grid.exporter.api:GridOptions\n           * @description The header section for pdf exports.  Can be\n           * simple text:\n           * <pre>\n           *   gridOptions.exporterPdfFooter = 'My Footer';\n           * </pre>\n           * Can be a more complex object in pdfMake format:\n           * <pre>\n           *   gridOptions.exporterPdfFooter = {\n           *     columns: [\n           *       'Left part',\n           *       { text: 'Right part', alignment: 'right' }\n           *     ]\n           *   };\n           * </pre>\n           * Or can be a function, allowing page numbers and the like\n           * <pre>\n           *   gridOptions.exporterPdfFooter: function(currentPage, pageCount) { return currentPage.toString() + ' of ' + pageCount; };\n           * </pre>\n           */\n          gridOptions.exporterPdfFooter = gridOptions.exporterPdfFooter ? gridOptions.exporterPdfFooter : null;\n          /**\n           * @ngdoc object\n           * @name exporterPdfOrientation\n           * @propertyOf  ui.grid.exporter.api:GridOptions\n           * @description The orientation, should be a valid pdfMake value,\n           * 'landscape' or 'portrait'\n           * <br/>Defaults to landscape\n           */\n          gridOptions.exporterPdfOrientation = gridOptions.exporterPdfOrientation ? gridOptions.exporterPdfOrientation : 'landscape';\n          /**\n           * @ngdoc object\n           * @name exporterPdfPageSize\n           * @propertyOf  ui.grid.exporter.api:GridOptions\n           * @description The orientation, should be a valid pdfMake\n           * paper size, usually 'A4' or 'LETTER'\n           * {@link https://github.com/bpampuch/pdfmake/blob/master/src/standardPageSizes.js pdfMake page sizes}\n           * <br/>Defaults to A4\n           */\n          gridOptions.exporterPdfPageSize = gridOptions.exporterPdfPageSize ? gridOptions.exporterPdfPageSize : 'A4';\n          /**\n           * @ngdoc object\n           * @name exporterPdfMaxGridWidth\n           * @propertyOf  ui.grid.exporter.api:GridOptions\n           * @description The maxium grid width - the current grid width \n           * will be scaled to match this, with any fixed width columns\n           * being adjusted accordingly.\n           * <br/>Defaults to 720 (for A4 landscape), use 670 for LETTER \n           */\n          gridOptions.exporterPdfMaxGridWidth = gridOptions.exporterPdfMaxGridWidth ? gridOptions.exporterPdfMaxGridWidth : 720;\n          /**\n           * @ngdoc object\n           * @name exporterPdfTableLayout\n           * @propertyOf  ui.grid.exporter.api:GridOptions\n           * @description A tableLayout in pdfMake format, \n           * controls gridlines and the like.  We use the default\n           * layout usually.\n           * <br/>Defaults to null, which means no layout \n           */\n\n          /**\n           * @ngdoc object\n           * @name exporterMenuCsv\n           * @propertyOf  ui.grid.exporter.api:GridOptions\n           * @description Add csv export menu items to the ui-grid grid menu, if it's present.  Defaults to true.\n           */\n          gridOptions.exporterMenuCsv = gridOptions.exporterMenuCsv !== undefined ? gridOptions.exporterMenuCsv : true;\n\n          /**\n           * @ngdoc object\n           * @name exporterMenuPdf\n           * @propertyOf  ui.grid.exporter.api:GridOptions\n           * @description Add pdf export menu items to the ui-grid grid menu, if it's present.  Defaults to true.\n           */\n          gridOptions.exporterMenuPdf = gridOptions.exporterMenuPdf !== undefined ? gridOptions.exporterMenuPdf : true;\n          \n          /**\n           * @ngdoc object\n           * @name exporterPdfCustomFormatter\n           * @propertyOf  ui.grid.exporter.api:GridOptions\n           * @description A custom callback routine that changes the pdf document, adding any\n           * custom styling or content that is supported by pdfMake.  Takes in the complete docDefinition, and\n           * must return an updated docDefinition ready for pdfMake.\n           * @example\n           * In this example we add a style to the style array, so that we can use it in our\n           * footer definition.\n           * <pre>\n           *   gridOptions.exporterPdfCustomFormatter = function ( docDefinition ) {\n           *     docDefinition.styles.footerStyle = { bold: true, fontSize: 10 };\n           *     return docDefinition;\n           *   }\n           * \n           *   gridOptions.exporterPdfFooter = { text: 'My footer', style: 'footerStyle' }\n           * </pre>\n           */\n          gridOptions.exporterPdfCustomFormatter = ( gridOptions.exporterPdfCustomFormatter && typeof( gridOptions.exporterPdfCustomFormatter ) === 'function' ) ? gridOptions.exporterPdfCustomFormatter : function ( docDef ) { return docDef; };\n          \n          /**\n           * @ngdoc object\n           * @name exporterHeaderFilterUseName\n           * @propertyOf  ui.grid.exporter.api:GridOptions\n           * @description Defaults to false, which leads to `displayName` being passed into the headerFilter.\n           * If set to true, then will pass `name` instead.\n           * \n           * \n           * @example\n           * <pre>\n           *   gridOptions.exporterHeaderFilterUseName = true;\n           * </pre>\n           */\n          gridOptions.exporterHeaderFilterUseName = gridOptions.exporterHeaderFilterUseName === true;          \n\n          /**\n           * @ngdoc object\n           * @name exporterHeaderFilter\n           * @propertyOf  ui.grid.exporter.api:GridOptions\n           * @description A function to apply to the header displayNames before exporting.  Useful for internationalisation,\n           * for example if you were using angular-translate you'd set this to `$translate.instant`.  Note that this\n           * call must be synchronous, it cannot be a call that returns a promise.\n           * \n           * Behaviour can be changed to pass in `name` instead of `displayName` through use of `exporterHeaderFilterUseName: true`.\n           * \n           * @example\n           * <pre>\n           *   gridOptions.exporterHeaderFilter = function( displayName ){ return 'col: ' + name; };\n           * </pre>\n           * OR\n           * <pre>\n           *   gridOptions.exporterHeaderFilter = $translate.instant;\n           * </pre>\n           */\n          \n          /**\n           * @ngdoc function\n           * @name exporterFieldCallback\n           * @propertyOf  ui.grid.exporter.api:GridOptions\n           * @description A function to call for each field before exporting it.  Allows \n           * massaging of raw data into a display format, for example if you have applied \n           * filters to convert codes into decodes, or you require\n           * a specific date format in the exported content.\n           * \n           * The method is called once for each field exported, and provides the grid, the\n           * gridCol and the GridRow for you to use as context in massaging the data.\n           * \n           * @param {Grid} grid provides the grid in case you have need of it\n           * @param {GridRow} row the row from which the data comes\n           * @param {GridCol} col the column from which the data comes\n           * @param {object} value the value for your massaging\n           * @returns {object} you must return the massaged value ready for exporting\n           * \n           * @example\n           * <pre>\n           *   gridOptions.exporterFieldCallback = function ( grid, row, col, value ){\n           *     if ( col.name === 'status' ){\n           *       value = decodeStatus( value );\n           *     }\n           *     return value;\n           *   }\n           * </pre>\n           */\n          gridOptions.exporterFieldCallback = gridOptions.exporterFieldCallback ? gridOptions.exporterFieldCallback : function( grid, row, col, value ) { return value; };\n        },\n\n\n        /**\n         * @ngdoc function\n         * @name addToMenu\n         * @methodOf  ui.grid.exporter.service:uiGridExporterService\n         * @description Adds export items to the grid menu,\n         * allowing the user to select export options \n         * @param {Grid} grid the grid from which data should be exported\n         */\n        addToMenu: function ( grid ) {\n          grid.api.core.addToGridMenu( grid, [\n            {\n              title: i18nService.getSafeText('gridMenu.exporterAllAsCsv'),\n              action: function ($event) {\n                this.grid.api.exporter.csvExport( uiGridExporterConstants.ALL, uiGridExporterConstants.ALL );\n              },\n              shown: function() {\n                return this.grid.options.exporterMenuCsv; \n              }\n            },\n            {\n              title: i18nService.getSafeText('gridMenu.exporterVisibleAsCsv'),\n              action: function ($event) {\n                this.grid.api.exporter.csvExport( uiGridExporterConstants.VISIBLE, uiGridExporterConstants.VISIBLE );\n              },\n              shown: function() {\n                return this.grid.options.exporterMenuCsv; \n              }\n            },\n            {\n              title: i18nService.getSafeText('gridMenu.exporterSelectedAsCsv'),\n              action: function ($event) {\n                this.grid.api.exporter.csvExport( uiGridExporterConstants.SELECTED, uiGridExporterConstants.VISIBLE );\n              },\n              shown: function() {\n                return this.grid.options.exporterMenuCsv &&\n                       ( this.grid.api.selection && this.grid.api.selection.getSelectedRows().length > 0 ); \n              }\n            },\n            {\n              title: i18nService.getSafeText('gridMenu.exporterAllAsPdf'),\n              action: function ($event) {\n                this.grid.api.exporter.pdfExport( uiGridExporterConstants.ALL, uiGridExporterConstants.ALL );\n              },\n              shown: function() {\n                return this.grid.options.exporterMenuPdf; \n              }\n            },\n            {\n              title: i18nService.getSafeText('gridMenu.exporterVisibleAsPdf'),\n              action: function ($event) {\n                this.grid.api.exporter.pdfExport( uiGridExporterConstants.VISIBLE, uiGridExporterConstants.VISIBLE );\n              },\n              shown: function() {\n                return this.grid.options.exporterMenuPdf; \n              }\n            },\n            {\n              title: i18nService.getSafeText('gridMenu.exporterSelectedAsPdf'),\n              action: function ($event) {\n                this.grid.api.exporter.pdfExport( uiGridExporterConstants.SELECTED, uiGridExporterConstants.VISIBLE );\n              },\n              shown: function() {\n                return this.grid.options.exporterMenuPdf &&\n                       ( this.grid.api.selection && this.grid.api.selection.getSelectedRows().length > 0 ); \n              }\n            }\n          ]);\n        },\n        \n\n        /**\n         * @ngdoc function\n         * @name csvExport\n         * @methodOf  ui.grid.exporter.service:uiGridExporterService\n         * @description Exports rows from the grid in csv format, \n         * the data exported is selected based on the provided options\n         * @param {Grid} grid the grid from which data should be exported\n         * @param {string} rowTypes which rows to export, valid values are\n         * uiGridExporterConstants.ALL, uiGridExporterConstants.VISIBLE,\n         * uiGridExporterConstants.SELECTED\n         * @param {string} colTypes which columns to export, valid values are\n         * uiGridExporterConstants.ALL, uiGridExporterConstants.VISIBLE,\n         * uiGridExporterConstants.SELECTED\n         */\n        csvExport: function (grid, rowTypes, colTypes) {\n          var exportColumnHeaders = this.getColumnHeaders(grid, colTypes);\n          var exportData = this.getData(grid, rowTypes, colTypes);\n          var csvContent = this.formatAsCsv(exportColumnHeaders, exportData, grid.options.exporterCsvColumnSeparator);\n          \n          this.downloadFile (grid.options.exporterCsvFilename, csvContent);\n        },\n        \n        \n        /** \n         * @ngdoc property\n         * @propertyOf ui.grid.exporter.api:ColumnDef\n         * @name exporterSuppressExport\n         * @description Suppresses export for this column.  Used by selection and expandable.\n         */\n\n        /**\n         * @ngdoc function\n         * @name getColumnHeaders\n         * @methodOf  ui.grid.exporter.service:uiGridExporterService\n         * @description Gets the column headers from the grid to use\n         * as a title row for the exported file, all headers have \n         * headerCellFilters applied as appropriate.\n         * \n         * Column headers are an array of objects, each object has\n         * name, displayName, width and align attributes.  Only name is\n         * used for csv, all attributes are used for pdf.\n         * \n         * @param {Grid} grid the grid from which data should be exported\n         * @param {string} colTypes which columns to export, valid values are\n         * uiGridExporterConstants.ALL, uiGridExporterConstants.VISIBLE,\n         * uiGridExporterConstants.SELECTED\n         */\n        getColumnHeaders: function (grid, colTypes) {\n          var headers = [];\n          angular.forEach(grid.columns, function( gridCol, index ) {\n            if ( (gridCol.visible || colTypes === uiGridExporterConstants.ALL ) && \n                 gridCol.colDef.exporterSuppressExport !== true &&\n                 grid.options.exporterSuppressColumns.indexOf( gridCol.name ) === -1 ){\n              headers.push({\n                name: gridCol.field,\n                displayName: grid.options.exporterHeaderFilter ? ( grid.options.exporterHeaderFilterUseName ? grid.options.exporterHeaderFilter(gridCol.name) : grid.options.exporterHeaderFilter(gridCol.displayName) ) : gridCol.displayName,\n                width: gridCol.drawnWidth ? gridCol.drawnWidth : gridCol.width,\n                align: gridCol.colDef.type === 'number' ? 'right' : 'left'\n              });\n            }\n          });\n          \n          return headers;\n        },\n        \n        \n        /** \n         * @ngdoc property\n         * @propertyOf ui.grid.exporter.api:ColumnDef\n         * @name exporterPdfAlign\n         * @description the alignment you'd like for this specific column when\n         * exported into a pdf.  Can be 'left', 'right', 'center' or any other\n         * valid pdfMake alignment option.\n         */\n\n\n        /**\n         * @ngdoc object\n         * @name ui.grid.exporter.api:GridRow\n         * @description GridRow settings for exporter\n         */\n        /**\n         * @ngdoc object\n         * @name exporterEnableExporting\n         * @propertyOf  ui.grid.exporter.api:GridRow\n         * @description If set to false, then don't export this row, notwithstanding visible or \n         * other settings\n         * <br/>Defaults to true\n         */\n\n        /**\n         * @ngdoc function\n         * @name getData\n         * @methodOf  ui.grid.exporter.service:uiGridExporterService\n         * @description Gets data from the grid based on the provided options,\n         * all cells have cellFilters applied as appropriate.  Any rows marked\n         * `exporterEnableExporting: false` will not be exported\n         * @param {Grid} grid the grid from which data should be exported\n         * @param {string} rowTypes which rows to export, valid values are\n         * uiGridExporterConstants.ALL, uiGridExporterConstants.VISIBLE,\n         * uiGridExporterConstants.SELECTED\n         * @param {string} colTypes which columns to export, valid values are\n         * uiGridExporterConstants.ALL, uiGridExporterConstants.VISIBLE,\n         * uiGridExporterConstants.SELECTED\n         */\n        getData: function (grid, rowTypes, colTypes) {\n          var data = [];\n          \n          var rows;\n          \n          switch ( rowTypes ) {\n            case uiGridExporterConstants.ALL:\n              rows = grid.rows; \n              break;\n            case uiGridExporterConstants.VISIBLE:\n              rows = grid.getVisibleRows();\n              break;\n            case uiGridExporterConstants.SELECTED:\n              if ( grid.api.selection ){\n                rows = grid.api.selection.getSelectedGridRows();\n              } else {\n                gridUtil.logError('selection feature must be enabled to allow selected rows to be exported');\n              }\n              break;\n          }\n          \n          angular.forEach(rows, function( row, index ) {\n\n            if (row.exporterEnableExporting !== false) {\n              var extractedRow = [];\n              angular.forEach(grid.columns, function( gridCol, index ) {\n              if ( (gridCol.visible || colTypes === uiGridExporterConstants.ALL ) && \n                   gridCol.colDef.exporterSuppressExport !== true &&\n                   grid.options.exporterSuppressColumns.indexOf( gridCol.name ) === -1 ){\n                  var extractedField = { value: grid.options.exporterFieldCallback( grid, row, gridCol, grid.getCellValue( row, gridCol ) ) };\n                  if ( gridCol.colDef.exporterPdfAlign ) {\n                    extractedField.alignment = gridCol.colDef.exporterPdfAlign;                 \n                  }\n                  extractedRow.push(extractedField);\n                }\n              });\n              \n              data.push(extractedRow);\n            }\n          });\n          \n          return data;\n        },\n\n\n        /**\n         * @ngdoc function\n         * @name formatAsCSV\n         * @methodOf  ui.grid.exporter.service:uiGridExporterService\n         * @description Formats the column headers and data as a CSV, \n         * and sends that data to the user\n         * @param {array} exportColumnHeaders an array of column headers, \n         * where each header is an object with name, width and maybe alignment\n         * @param {array} exportData an array of rows, where each row is\n         * an array of column data\n         * @returns {string} csv the formatted csv as a string\n         */\n        formatAsCsv: function (exportColumnHeaders, exportData, separator) {\n          var self = this;\n          \n          var bareHeaders = exportColumnHeaders.map(function(header){return { value: header.displayName };});\n          \n          var csv = self.formatRowAsCsv(this, separator)(bareHeaders) + '\\n';\n          \n          csv += exportData.map(this.formatRowAsCsv(this, separator)).join('\\n');\n          \n          return csv;\n        },\n\n        /**\n         * @ngdoc function\n         * @name formatRowAsCsv\n         * @methodOf  ui.grid.exporter.service:uiGridExporterService\n         * @description Renders a single field as a csv field, including\n         * quotes around the value\n         * @param {exporterService} exporter pass in exporter \n         * @param {array} row the row to be turned into a csv string\n         * @returns {string} a csv-ified version of the row\n         */\n        formatRowAsCsv: function (exporter, separator) {\n          return function (row) {\n            return row.map(exporter.formatFieldAsCsv).join(separator);\n          };\n        },\n        \n        /**\n         * @ngdoc function\n         * @name formatFieldAsCsv\n         * @methodOf  ui.grid.exporter.service:uiGridExporterService\n         * @description Renders a single field as a csv field, including\n         * quotes around the value\n         * @param {field} field the field to be turned into a csv string,\n         * may be of any type\n         * @returns {string} a csv-ified version of the field\n         */\n        formatFieldAsCsv: function (field) {\n          if (field.value == null) { // we want to catch anything null-ish, hence just == not ===\n            return '';\n          }\n          if (typeof(field.value) === 'number') {\n            return field.value;\n          }\n          if (typeof(field.value) === 'boolean') {\n            return (field.value ? 'TRUE' : 'FALSE') ;\n          }\n          if (typeof(field.value) === 'string') {\n            return '\"' + field.value.replace(/\"/g,'\"\"') + '\"';\n          }\n\n          return JSON.stringify(field.value);        \n        },\n\n\n        /**\n         * @ngdoc function\n         * @name downloadFile\n         * @methodOf  ui.grid.exporter.service:uiGridExporterService\n         * @description Triggers download of a csv file.  Logic provided\n         * by @cssensei (from his colleagues at https://github.com/ifeelgoods) in issue #2391\n         * @param {string} fileName the filename we'd like our file to be\n         * given\n         * @param {string} csvContent the csv content that we'd like to \n         * download as a file\n         */\n        downloadFile: function (fileName, csvContent) {\n          var D = document;\n          var a = D.createElement('a');\n          var strMimeType = 'application/octet-stream;charset=utf-8';\n          var rawFile;\n      \n          // IE10+\n          if (navigator.msSaveBlob) {\n            return navigator.msSaveBlob(new Blob([\"\\ufeff\", csvContent], {\n              type: strMimeType\n            }), fileName);\n          }\n      \n          //html5 A[download]\n          if ('download' in a) {\n            var blob = new Blob([csvContent], {\n              type: strMimeType\n            });\n            rawFile = URL.createObjectURL(blob);\n            a.setAttribute('download', fileName);\n          } else {\n            rawFile = 'data:' + strMimeType + ',' + encodeURIComponent(csvContent);\n            a.setAttribute('target', '_blank');\n          }\n      \n          a.href = rawFile;\n          a.setAttribute('style', 'display:none;');\n          D.body.appendChild(a);\n          setTimeout(function() {\n            if (a.click) {\n              a.click();\n              // Workaround for Safari 5\n            } else if (document.createEvent) {\n              var eventObj = document.createEvent('MouseEvents');\n              eventObj.initEvent('click', true, true);\n              a.dispatchEvent(eventObj);\n            }\n            D.body.removeChild(a);\n    \n          }, 100);\n        },\n\n        /**\n         * @ngdoc function\n         * @name pdfExport\n         * @methodOf  ui.grid.exporter.service:uiGridExporterService\n         * @description Exports rows from the grid in pdf format, \n         * the data exported is selected based on the provided options.\n         * Note that this function has a dependency on pdfMake, which must\n         * be installed.  The resulting pdf opens in a new\n         * browser window.\n         * @param {Grid} grid the grid from which data should be exported\n         * @param {string} rowTypes which rows to export, valid values are\n         * uiGridExporterConstants.ALL, uiGridExporterConstants.VISIBLE,\n         * uiGridExporterConstants.SELECTED\n         * @param {string} colTypes which columns to export, valid values are\n         * uiGridExporterConstants.ALL, uiGridExporterConstants.VISIBLE,\n         * uiGridExporterConstants.SELECTED\n         */\n        pdfExport: function (grid, rowTypes, colTypes) {\n          var exportColumnHeaders = this.getColumnHeaders(grid, colTypes);\n          var exportData = this.getData(grid, rowTypes, colTypes);\n          var docDefinition = this.prepareAsPdf(grid, exportColumnHeaders, exportData);\n          \n          pdfMake.createPdf(docDefinition).open();\n        },\n        \n        \n        /**\n         * @ngdoc function\n         * @name renderAsPdf\n         * @methodOf  ui.grid.exporter.service:uiGridExporterService\n         * @description Renders the data into a pdf, and opens that pdf.\n         * \n         * @param {Grid} grid the grid from which data should be exported\n         * @param {array} exportColumnHeaders an array of column headers, \n         * where each header is an object with name, width and maybe alignment\n         * @param {array} exportData an array of rows, where each row is\n         * an array of column data\n         * @returns {object} a pdfMake format document definition, ready \n         * for generation\n         */        \n        prepareAsPdf: function(grid, exportColumnHeaders, exportData) {\n          var headerWidths = this.calculatePdfHeaderWidths( grid, exportColumnHeaders );\n          \n          var headerColumns = exportColumnHeaders.map( function( header ) {\n            return { text: header.displayName, style: 'tableHeader' }; \n          });\n          \n          var stringData = exportData.map(this.formatRowAsPdf(this));\n          \n          var allData = [headerColumns].concat(stringData);\n          \n          var docDefinition = {\n            pageOrientation: grid.options.exporterPdfOrientation,\n            pageSize: grid.options.exporterPdfPageSize,\n            content: [{\n              style: 'tableStyle',\n              table: {\n                headerRows: 1,\n                widths: headerWidths,\n                body: allData \n              }\n            }],\n            styles: {\n              tableStyle: grid.options.exporterPdfTableStyle,\n              tableHeader: grid.options.exporterPdfTableHeaderStyle\n            },\n            defaultStyle: grid.options.exporterPdfDefaultStyle\n          };\n          \n          if ( grid.options.exporterPdfLayout ){\n            docDefinition.layout = grid.options.exporterPdfLayout;\n          }\n          \n          if ( grid.options.exporterPdfHeader ){\n            docDefinition.header = grid.options.exporterPdfHeader;\n          }\n          \n          if ( grid.options.exporterPdfFooter ){\n            docDefinition.footer = grid.options.exporterPdfFooter;\n          }\n          \n          if ( grid.options.exporterPdfCustomFormatter ){\n            docDefinition = grid.options.exporterPdfCustomFormatter( docDefinition );\n          }\n          return docDefinition;\n          \n        },\n        \n                \n        /**\n         * @ngdoc function\n         * @name calculatePdfHeaderWidths\n         * @methodOf  ui.grid.exporter.service:uiGridExporterService\n         * @description Determines the column widths base on the \n         * widths we got from the grid.  If the column is drawn\n         * then we have a drawnWidth.  If the column is not visible\n         * then we have '*', 'x%' or a width.  When columns are\n         * not visible they don't contribute to the overall gridWidth,\n         * so we need to adjust to allow for extra columns\n         * \n         * Our basic heuristic is to take the current gridWidth, plus \n         * numeric columns and call this the base gridwidth.\n         * \n         * To that we add 100 for any '*' column, and x% of the base gridWidth\n         * for any column that is a %\n         *  \n         * @param {Grid} grid the grid from which data should be exported\n         * @param {object} exportHeaders array of header information \n         * @returns {object} an array of header widths\n         */\n        calculatePdfHeaderWidths: function ( grid, exportHeaders ) {\n          var baseGridWidth = 0;\n          angular.forEach(exportHeaders, function(value){\n            if (typeof(value.width) === 'number'){\n              baseGridWidth += value.width;\n            }\n          });\n          \n          var extraColumns = 0;\n          angular.forEach(exportHeaders, function(value){\n            if (value.width === '*'){\n              extraColumns += 100;\n            }\n            if (typeof(value.width) === 'string' && value.width.match(/(\\d)*%/)) {\n              var percent = parseInt(value.width.match(/(\\d)*%/)[0]);\n              \n              value.width = baseGridWidth * percent / 100;\n              extraColumns += value.width;\n            }\n          });\n          \n          var gridWidth = baseGridWidth + extraColumns;\n          \n          return exportHeaders.map(function( header ) {\n            return header.width === '*' ? header.width : header.width * grid.options.exporterPdfMaxGridWidth / gridWidth;\n          });\n          \n        },\n        \n        /**\n         * @ngdoc function\n         * @name formatRowAsPdf\n         * @methodOf  ui.grid.exporter.service:uiGridExporterService\n         * @description Renders a row in a format consumable by PDF,\n         * mainly meaning casting everything to a string\n         * @param {exporterService} exporter pass in exporter \n         * @param {array} row the row to be turned into a csv string\n         * @returns {string} a csv-ified version of the row\n         */\n        formatRowAsPdf: function ( exporter ) {\n          return function( row ) {\n            return row.map(exporter.formatFieldAsPdfString);\n          };\n        },\n        \n        \n        /**\n         * @ngdoc function\n         * @name formatFieldAsCsv\n         * @methodOf  ui.grid.exporter.service:uiGridExporterService\n         * @description Renders a single field as a pdf-able field, which\n         * is different from a csv field only in that strings don't have quotes\n         * around them\n         * @param {field} field the field to be turned into a pdf string,\n         * may be of any type\n         * @returns {string} a string-ified version of the field\n         */\n        formatFieldAsPdfString: function (field) {\n          var returnVal;\n          if (field.value == null) { // we want to catch anything null-ish, hence just == not ===\n            returnVal = '';\n          } else if (typeof(field.value) === 'number') {\n            returnVal = field.value.toString();\n          } else if (typeof(field.value) === 'boolean') {\n            returnVal = (field.value ? 'TRUE' : 'FALSE') ;\n          } else if (typeof(field.value) === 'string') {\n            returnVal = field.value.replace(/\"/g,'\"\"');\n          } else {\n            returnVal = JSON.stringify(field.value).replace(/^\"/,'').replace(/\"$/,'');        \n          }\n          \n          if (field.alignment && typeof(field.alignment) === 'string' ){\n            returnVal = { text: returnVal, alignment: field.alignment };\n          }\n          \n          return returnVal;\n        }\n      };\n\n      return service;\n\n    }\n  ]);\n\n  /**\n   *  @ngdoc directive\n   *  @name ui.grid.exporter.directive:uiGridExporter\n   *  @element div\n   *  @restrict A\n   *\n   *  @description Adds exporter features to grid\n   *\n   *  @example\n   <example module=\"app\">\n   <file name=\"app.js\">\n   var app = angular.module('app', ['ui.grid', 'ui.grid.exporter']);\n\n   app.controller('MainCtrl', ['$scope', function ($scope) {\n      $scope.data = [\n        { name: 'Bob', title: 'CEO' },\n            { name: 'Frank', title: 'Lowly Developer' }\n      ];\n\n      $scope.gridOptions = {\n        enableGridMenu: true,\n        exporterMenuCsv: false,\n        columnDefs: [\n          {name: 'name', enableCellEdit: true},\n          {name: 'title', enableCellEdit: true}\n        ],\n        data: $scope.data\n      };\n    }]);\n   </file>\n   <file name=\"index.html\">\n   <div ng-controller=\"MainCtrl\">\n   <div ui-grid=\"gridOptions\" ui-grid-exporter></div>\n   </div>\n   </file>\n   </example>\n   */\n  module.directive('uiGridExporter', ['uiGridExporterConstants', 'uiGridExporterService', 'gridUtil', '$compile',\n    function (uiGridExporterConstants, uiGridExporterService, gridUtil, $compile) {\n      return {\n        replace: true,\n        priority: 0,\n        require: '^uiGrid',\n        scope: false,\n        link: function ($scope, $elm, $attrs, uiGridCtrl) {\n          uiGridExporterService.initializeGrid(uiGridCtrl.grid);\n          uiGridCtrl.grid.exporter.$scope = $scope;\n        }\n      };\n    }\n  ]);\n})();\n\n(function () {\n  'use strict';\n\n  /**\n   * @ngdoc overview\n   * @name ui.grid.importer\n   * @description\n   *\n   *  # ui.grid.importer\n   * This module provides the ability to import data into the grid. It\n   * uses the column defs to work out which data belongs in which column, \n   * and creates entities from a configured class (typically a $resource).\n   * \n   * If the rowEdit feature is enabled, it also calls save on those newly \n   * created objects, and then displays any errors in the imported data.  \n   * \n   * Currently the importer imports only CSV and json files, although provision has been\n   * made to process other file formats, and these can be added over time.  \n   * \n   * For json files, the properties within each object in the json must match the column names\n   * (to put it another way, the importer doesn't process the json, it just copies the objects\n   * within the json into a new instance of the specified object type)\n   * \n   * For CSV import, the default column identification relies on each column in the\n   * header row matching a column.name or column.displayName. Optionally, a column identification \n   * callback can be used.  This allows matching using other attributes, which is particularly\n   * useful if your application has internationalised column headings (i.e. the headings that \n   * the user sees don't match the column names).\n   * \n   * The importer makes use of the grid menu as the UI for requesting an\n   * import. \n   *\n   * <div ui-grid-importer></div>\n   */\n\n  var module = angular.module('ui.grid.importer', ['ui.grid']);\n\n  /**\n   *  @ngdoc object\n   *  @name ui.grid.importer.constant:uiGridImporterConstants\n   *\n   *  @description constants available in importer module\n   */\n\n  module.constant('uiGridImporterConstants', {\n    featureName: 'importer'\n  });\n\n  /**\n   *  @ngdoc service\n   *  @name ui.grid.importer.service:uiGridImporterService\n   *\n   *  @description Services for importer feature\n   */\n  module.service('uiGridImporterService', ['$q', 'uiGridConstants', 'uiGridImporterConstants', 'gridUtil', '$compile', '$interval', 'i18nService', '$window',\n    function ($q, uiGridConstants, uiGridImporterConstants, gridUtil, $compile, $interval, i18nService, $window) {\n\n      var service = {\n\n        initializeGrid: function ($scope, grid) {\n\n          //add feature namespace and any properties to grid for needed state\n          grid.importer = {\n            $scope: $scope \n          };\n          \n          this.defaultGridOptions(grid.options);\n\n          /**\n           *  @ngdoc object\n           *  @name ui.grid.importer.api:PublicApi\n           *\n           *  @description Public Api for importer feature\n           */\n          var publicApi = {\n            events: {\n              importer: {\n              }\n            },\n            methods: {\n              importer: {\n                /**\n                 * @ngdoc function\n                 * @name importFile\n                 * @methodOf  ui.grid.importer.api:PublicApi\n                 * @description Imports a file into the grid using the file object \n                 * provided.  Bypasses the grid menu\n                 * @param {File} fileObject the file we want to import, as a javascript\n                 * File object\n                 */\n                importFile: function ( fileObject ) {\n                  service.importThisFile( grid, fileObject );\n                }\n              }\n            }\n          };\n\n          grid.api.registerEventsFromObject(publicApi.events);\n\n          grid.api.registerMethodsFromObject(publicApi.methods);\n\n          if ( grid.options.enableImporter && grid.options.importerShowMenu ){\n            if ( grid.api.core.addToGridMenu ){\n              service.addToMenu( grid );\n            } else {\n              // order of registration is not guaranteed, register in a little while\n              $interval( function() {\n                if (grid.api.core.addToGridMenu){\n                  service.addToMenu( grid );\n                }             \n              }, 100, 1);\n            }\n          }\n        },\n        \n\n        defaultGridOptions: function (gridOptions) {\n          //default option to true unless it was explicitly set to false\n          /**\n           * @ngdoc object\n           * @name ui.grid.importer.api:GridOptions\n           *\n           * @description GridOptions for importer feature, these are available to be  \n           * set using the ui-grid {@link ui.grid.class:GridOptions gridOptions}\n           */\n\n          /**\n           * @ngdoc property\n           * @propertyOf ui.grid.importer.api:GridOptions\n           * @name enableImporter\n           * @description Whether or not importer is enabled.  Automatically set\n           * to false if the user's browser does not support the required fileApi.\n           * Otherwise defaults to true.\n           * \n           */\n          if (gridOptions.enableImporter  || gridOptions.enableImporter === undefined) {\n            if ( !($window.hasOwnProperty('File') && $window.hasOwnProperty('FileReader') && $window.hasOwnProperty('FileList') && $window.hasOwnProperty('Blob')) ) {\n              gridUtil.logError('The File APIs are not fully supported in this browser, grid importer cannot be used.');\n              gridOptions.enableImporter = false;\n            } else {\n              gridOptions.enableImporter = true;\n            }\n          } else {\n            gridOptions.enableImporter = false;\n          }\n          \n          /**\n           * @ngdoc method\n           * @name importerProcessHeaders\n           * @methodOf ui.grid.importer.api:GridOptions\n           * @description A callback function that will process headers using custom\n           * logic.  Set this callback function if the headers that your user will provide in their \n           * import file don't necessarily match the grid header or field names.  This might commonly\n           * occur where your application is internationalised, and therefore the field names\n           * that the user recognises are in a different language than the field names that\n           * ui-grid knows about.\n           * \n           * Defaults to the internal `processHeaders` method, which seeks to match using both\n           * displayName and column.name.  Any non-matching columns are discarded.\n           * \n           * Your callback routine should respond by processing the header array, and returning an array\n           * of matching column names.  A null value in any given position means \"don't import this column\"\n           * \n           * <pre>\n           *      gridOptions.importerProcessHeaders: function( headerArray ) {\n           *        var myHeaderColumns = [];\n           *        var thisCol;\n           *        headerArray.forEach( function( value, index ) {\n           *          thisCol = mySpecialLookupFunction( value );\n           *          myHeaderColumns.push( thisCol.name ); \n           *        });\n           *        \n           *        return myHeaderCols;\n           *      })\n           * </pre>\n           * @param {Grid} grid the grid we're importing into\n           * @param {array} headerArray an array of the text from the first row of the csv file,\n           * which you need to match to column.names\n           * @returns {array} array of matching column names, in the same order as the headerArray\n           * \n           */\n          gridOptions.importerProcessHeaders = gridOptions.importerProcessHeaders || service.processHeaders;\n\n          /**\n           * @ngdoc method\n           * @name importerHeaderFilter\n           * @methodOf ui.grid.importer.api:GridOptions\n           * @description A callback function that will filter (usually translate) a single\n           * header.  Used when you want to match the passed in column names to the column\n           * displayName after the header filter.\n           * \n           * Your callback routine needs to return the filtered header value. \n           * <pre>\n           *      gridOptions.importerHeaderFilter: function( displayName ) {\n           *        return $translate.instant( displayName );\n           *      })\n           * </pre>\n           * \n           * or:\n           * <pre>\n           *      gridOptions.importerHeaderFilter: $translate.instant\n           * </pre>\n           * @param {string} displayName the displayName that we'd like to translate\n           * @returns {string} the translated name\n           * \n           */\n          gridOptions.importerHeaderFilter = gridOptions.importerHeaderFilter || function( displayName ) { return displayName; };\n\n          /**\n           * @ngdoc method\n           * @name importerErrorCallback\n           * @methodOf ui.grid.importer.api:GridOptions\n           * @description A callback function that provides custom error handling, rather\n           * than the standard grid behaviour of an alert box and a console message.  You \n           * might use this to internationalise the console log messages, or to write to a \n           * custom logging routine that returned errors to the server.\n           * \n           * <pre>\n           *      gridOptions.importerErrorCallback: function( grid, errorKey, consoleMessage, context ) {\n           *        myUserDisplayRoutine( errorKey );\n           *        myLoggingRoutine( consoleMessage, context );\n           *      })\n           * </pre>\n           * @param {Grid} grid the grid we're importing into, may be useful if you're positioning messages\n           * in some way\n           * @param {string} errorKey one of the i18n keys the importer can return - importer.noHeaders, \n           * importer.noObjects, importer.invalidCsv, importer.invalidJson, importer.jsonNotArray\n           * @param {string} consoleMessage the English console message that importer would have written\n           * @param {object} context the context data that importer would have appended to that console message,\n           * often the file content itself or the element that is in error\n           * \n           */\n          if ( !gridOptions.importerErrorCallback ||  typeof(gridOptions.importerErrorCallback) !== 'function' ){\n            delete gridOptions.importerErrorCallback;  \n          }\n\n          /**\n           * @ngdoc method\n           * @name importerDataAddCallback\n           * @methodOf ui.grid.importer.api:GridOptions\n           * @description A mandatory callback function that adds data to the source data array.  The grid\n           * generally doesn't add rows to the source data array, it is tidier to handle this through a user\n           * callback.\n           * \n           * <pre>\n           *      gridOptions.importerDataAddCallback: function( grid, newObjects ) {\n           *        $scope.myData = $scope.myData.concat( newObjects );\n           *      })\n           * </pre>\n           * @param {Grid} grid the grid we're importing into, may be useful in some way\n           * @param {array} newObjects an array of new objects that you should add to your data\n           * \n           */\n          if ( gridOptions.enableImporter === true && !gridOptions.importerDataAddCallback ) {\n            gridUtil.logError(\"You have not set an importerDataAddCallback, importer is disabled\");\n            gridOptions.enableImporter = false;\n          }\n                    \n          /**\n           * @ngdoc object\n           * @name importerNewObject\n           * @propertyOf  ui.grid.importer.api:GridOptions\n           * @description An object on which we call `new` to create each new row before inserting it into\n           * the data array.  Typically this would be a $resource entity, which means that if you're using \n           * the rowEdit feature, you can directly call save on this entity when the save event is triggered.\n           * \n           * Defaults to a vanilla javascript object\n           * \n           * @example\n           * <pre>\n           *   gridOptions.importerNewObject = MyRes;\n           * </pre>\n           * \n           */\n\n          /**\n           * @ngdoc property\n           * @propertyOf ui.grid.importer.api:GridOptions\n           * @name importerShowMenu\n           * @description Whether or not to show an item in the grid menu.  Defaults to true.\n           * \n           */\n          gridOptions.importerShowMenu = gridOptions.importerShowMenu !== false;\n          \n          /**\n           * @ngdoc method\n           * @methodOf ui.grid.importer.api:GridOptions\n           * @name importerObjectCallback\n           * @description A callback that massages the data for each object.  For example,\n           * you might have data stored as a code value, but display the decode.  This callback\n           * can be used to change the decoded value back into a code.  Defaults to doing nothing.\n           * @param {Grid} grid in case you need it\n           * @param {object} newObject the new object as importer has created it, modify it\n           * then return the modified version\n           * @returns {object} the modified object\n           * @example\n           * <pre>\n           *   gridOptions.importerObjectCallback = function ( grid, newObject ) {\n           *     switch newObject.status {\n           *       case 'Active':\n           *         newObject.status = 1;\n           *         break;\n           *       case 'Inactive':\n           *         newObject.status = 2;\n           *         break;\n           *     }\n           *     return newObject;\n           *   };\n           * </pre>\n           */\n          gridOptions.importerObjectCallback = gridOptions.importerObjectCallback || function( grid, newObject ) { return newObject; };\n        },\n\n\n        /**\n         * @ngdoc function\n         * @name addToMenu\n         * @methodOf  ui.grid.importer.service:uiGridImporterService\n         * @description Adds import menu item to the grid menu,\n         * allowing the user to request import of a file \n         * @param {Grid} grid the grid into which data should be imported\n         */\n        addToMenu: function ( grid ) {\n          grid.api.core.addToGridMenu( grid, [\n            {\n              title: i18nService.getSafeText('gridMenu.importerTitle')\n            },\n            {\n              templateUrl: 'ui-grid/importerMenuItemContainer',\n              action: function ($event) {\n                this.grid.api.importer.importAFile( grid );\n              }\n            }\n          ]);\n        },\n        \n        \n        /**\n         * @ngdoc function\n         * @name importThisFile\n         * @methodOf ui.grid.importer.service:uiGridImporterService\n         * @description Imports the provided file into the grid using the file object \n         * provided.  Bypasses the grid menu\n         * @param {Grid} grid the grid we're importing into\n         * @param {File} fileObject the file we want to import, as returned from the File\n         * javascript object\n         */\n        importThisFile: function ( grid, fileObject ) {\n          if (!fileObject){\n            gridUtil.logError( 'No file object provided to importThisFile, should be impossible, aborting');\n            return;\n          }\n          \n          var reader = new FileReader();\n          \n          switch ( fileObject.type ){\n            case 'application/json':\n              reader.onload = service.importJsonClosure( grid );\n              break;\n            default:\n              reader.onload = service.importCsvClosure( grid );\n              break;\n          }\n          \n          reader.readAsText( fileObject );\n        },\n        \n        \n        /**\n         * @ngdoc function\n         * @name importJson\n         * @methodOf ui.grid.importer.service:uiGridImporterService\n         * @description Creates a function that imports a json file into the grid.\n         * The json data is imported into new objects of type `gridOptions.importerNewObject`,\n         * and if the rowEdit feature is enabled the rows are marked as dirty\n         * @param {Grid} grid the grid we want to import into\n         * @param {FileObject} importFile the file that we want to import, as \n         * a FileObject\n         */\n        importJsonClosure: function( grid ) {\n          return function( importFile ){\n            var newObjects = [];\n            var newObject;\n            \n            angular.forEach( service.parseJson( grid, importFile ), function( value, index ) {\n              newObject = service.newObject( grid );\n              angular.extend( newObject, value );\n              newObject = grid.options.importerObjectCallback( grid, newObject );\n              newObjects.push( newObject );\n            });\n            \n            service.addObjects( grid, newObjects );\n            \n          };\n        },\n\n\n        /**\n         * @ngdoc function\n         * @name parseJson\n         * @methodOf ui.grid.importer.service:uiGridImporterService\n         * @description Parses a json file, returns the parsed data.\n         * Displays an error if file doesn't parse\n         * @param {Grid} grid the grid that we want to import into \n         * @param {FileObject} importFile the file that we want to import, as \n         * a FileObject\n         * @returns {array} array of objects from the imported json\n         */\n        parseJson: function( grid, importFile ){\n          var loadedObjects;\n          try {\n            loadedObjects = JSON.parse( importFile.target.result );\n          } catch (e) {\n            service.alertError( grid, 'importer.invalidJson', 'File could not be processed, is it valid json? Content was: ', importFile.target.result );\n            return;\n          }\n          \n          if ( !Array.isArray( loadedObjects ) ){\n            service.alertError( grid, 'importer.jsonNotarray', 'Import failed, file is not an array, file was: ', importFile.target.result );\n            return [];\n          } else {\n            return loadedObjects;\n          }\n        },\n        \n        \n        \n        /**\n         * @ngdoc function\n         * @name importCsvClosure\n         * @methodOf ui.grid.importer.service:uiGridImporterService\n         * @description Creates a function that imports a csv file into the grid\n         * (allowing it to be used in the reader.onload event)\n         * @param {Grid} grid the grid that we want to import into \n         * @param {FileObject} importFile the file that we want to import, as \n         * a file object\n         */\n        importCsvClosure: function( grid ) {\n          return function( importFile ){\n            var importArray = service.parseCsv( importFile );\n            if ( !importArray || importArray.length < 1 ){ \n              service.alertError( grid, 'importer.invalidCsv', 'File could not be processed, is it valid csv? Content was: ', importFile.target.result );\n              return; \n            }\n            \n            var newObjects = service.createCsvObjects( grid, importArray );\n            if ( !newObjects || newObjects.length === 0 ){\n              service.alertError( grid, 'importer.noObjects', 'Objects were not able to be derived, content was: ', importFile.target.result );\n              return;\n            }\n            \n            service.addObjects( grid, newObjects );\n          };\n        },\n        \n        \n        /**\n         * @ngdoc function\n         * @name parseCsv\n         * @methodOf ui.grid.importer.service:uiGridImporterService\n         * @description Parses a csv file into an array of arrays, with the first\n         * array being the headers, and the remaining arrays being the data.\n         * The logic for this comes from https://github.com/thetalecrafter/excel.js/blob/master/src/csv.js, \n         * which is noted as being under the MIT license.  The code is modified to pass the jscs yoda condition\n         * checker\n         * @param {FileObject} importFile the file that we want to import, as a \n         * file object\n         */\n        parseCsv: function( importFile ) {\n          var csv = importFile.target.result;\n          \n          // use the CSV-JS library to parse\n          return CSV.parse(csv);\n        },\n        \n\n        /**\n         * @ngdoc function\n         * @name createCsvObjects\n         * @methodOf ui.grid.importer.service:uiGridImporterService\n         * @description Converts an array of arrays (representing the csv file)\n         * into a set of objects.  Uses the provided `gridOptions.importerNewObject`\n         * to create the objects, and maps the header row into the individual columns \n         * using either `gridOptions.importerProcessHeaders`, or by using a native method\n         * of matching to either the displayName, column name or column field of\n         * the columns in the column defs.  The resulting objects will have attributes\n         * that are named based on the column.field or column.name, in that order.\n         * @param {Grid} grid the grid that we want to import into \n         * @param {FileObject} importFile the file that we want to import, as a \n         * file object\n         */\n        createCsvObjects: function( grid, importArray ){\n          // pull off header row and turn into headers\n          var headerMapping = grid.options.importerProcessHeaders( grid, importArray.shift() );\n          if ( !headerMapping || headerMapping.length === 0 ){\n            service.alertError( grid, 'importer.noHeaders', 'Column names could not be derived, content was: ', importArray );\n            return [];\n          }\n          \n          var newObjects = [];\n          var newObject;\n          angular.forEach( importArray, function( row, index ) {\n            newObject = service.newObject( grid );\n            angular.forEach( row, function( field, index ){\n              if ( headerMapping[index] !== null ){\n                newObject[ headerMapping[index] ] = field;\n              }\n            });\n            newObject = grid.options.importerObjectCallback( grid, newObject );\n            newObjects.push( newObject );\n          });\n          \n          return newObjects;\n        },\n        \n        \n        /**\n         * @ngdoc function\n         * @name processHeaders\n         * @methodOf ui.grid.importer.service:uiGridImporterService\n         * @description Determines the columns that the header row from\n         * a csv (or other) file represents.\n         * @param {Grid} grid the grid we're importing into\n         * @param {array} headerRow the header row that we wish to match against\n         * the column definitions\n         * @returns {array} an array of the attribute names that should be used\n         * for that column, based on matching the headers or creating the headers\n         * \n         */\n        processHeaders: function( grid, headerRow ) {\n          var headers = [];\n          if ( !grid.options.columnDefs || grid.options.columnDefs.length === 0 ){\n            // we are going to create new columnDefs for all these columns, so just remove\n            // spaces from the names to create fields\n            angular.forEach( headerRow, function( value, index ) {\n              headers.push( value.replace( /[^0-9a-zA-Z\\-_]/g, '_' ) );\n            });\n            return headers;\n          } else {\n            var lookupHash = service.flattenColumnDefs( grid, grid.options.columnDefs );\n            angular.forEach( headerRow, function( value, index ) {\n              if ( lookupHash[value] ) {\n                headers.push( lookupHash[value] );\n              } else if ( lookupHash[ value.toLowerCase() ] ) {\n                headers.push( lookupHash[ value.toLowerCase() ] );\n              } else {\n                headers.push( null );\n              }\n            });\n            return headers;\n          }\n        },\n        \n        \n        /**\n         * @name flattenColumnDefs\n         * @methodOf ui.grid.importer.service:uiGridImporterService\n         * @description Runs through the column defs and creates a hash of\n         * the displayName, name and field, and of each of those values forced to lower case,\n         * with each pointing to the field or name\n         * (whichever is present).  Used to lookup column headers and decide what \n         * attribute name to give to the resulting field. \n         * @param {Grid} grid the grid we're importing into\n         * @param {array} columnDefs the columnDefs that we should flatten\n         * @returns {hash} the flattened version of the column def information, allowing\n         * us to look up a value by `flattenedHash[ headerValue ]`\n         */\n        flattenColumnDefs: function( grid, columnDefs ){\n          var flattenedHash = {};\n          angular.forEach( columnDefs, function( columnDef, index) {\n            if ( columnDef.name ){\n              flattenedHash[ columnDef.name ] = columnDef.field || columnDef.name;\n              flattenedHash[ columnDef.name.toLowerCase() ] = columnDef.field || columnDef.name;\n            }\n            \n            if ( columnDef.field ){\n              flattenedHash[ columnDef.field ] = columnDef.field || columnDef.name;\n              flattenedHash[ columnDef.field.toLowerCase() ] = columnDef.field || columnDef.name;\n            }\n            \n            if ( columnDef.displayName ){\n              flattenedHash[ columnDef.displayName ] = columnDef.field || columnDef.name;\n              flattenedHash[ columnDef.displayName.toLowerCase() ] = columnDef.field || columnDef.name;\n            }\n            \n            if ( columnDef.displayName && grid.options.importerHeaderFilter ){\n              flattenedHash[ grid.options.importerHeaderFilter(columnDef.displayName) ] = columnDef.field || columnDef.name;\n              flattenedHash[ grid.options.importerHeaderFilter(columnDef.displayName).toLowerCase() ] = columnDef.field || columnDef.name;\n            }\n          });\n          \n          return flattenedHash;\n        },\n        \n        \n        /**\n         * @ngdoc function\n         * @name addObjects\n         * @methodOf ui.grid.importer.service:uiGridImporterService\n         * @description Inserts our new objects into the grid data, and\n         * sets the rows to dirty if the rowEdit feature is being used\n         * \n         * Does this by registering a watch on dataChanges, which essentially\n         * is waiting on the result of the grid data watch, and downstream processing.\n         * \n         * When the callback is called, it deregisters itself - we don't want to run\n         * again next time data is added.\n         * \n         * If we never get called, we deregister on destroy.\n         * \n         * @param {Grid} grid the grid we're importing into\n         * @param {array} newObjects the objects we want to insert into the grid data\n         * @returns {object} the new object\n         */\n        addObjects: function( grid, newObjects, $scope ){\n          if ( grid.api.rowEdit ){\n            var dataChangeDereg = grid.registerDataChangeCallback( function() {\n              grid.api.rowEdit.setRowsDirty( newObjects );\n              dataChangeDereg();\n            }, [uiGridConstants.dataChange.ROW] );\n            \n            grid.importer.$scope.$on( '$destroy', dataChangeDereg );\n          }\n\n          grid.importer.$scope.$apply( grid.options.importerDataAddCallback( grid, newObjects ) );\n          \n        },\n        \n        \n        /**\n         * @ngdoc function\n         * @name newObject\n         * @methodOf ui.grid.importer.service:uiGridImporterService\n         * @description Makes a new object based on `gridOptions.importerNewObject`,\n         * or based on an empty object if not present\n         * @param {Grid} grid the grid we're importing into\n         * @returns {object} the new object\n         */\n        newObject: function( grid ){\n          if ( typeof(grid.options) !== \"undefined\" && typeof(grid.options.importerNewObject) !== \"undefined\" ){\n            return new grid.options.importerNewObject();\n          } else {\n            return {};\n          }\n        },\n        \n        \n        /**\n         * @ngdoc function\n         * @name alertError\n         * @methodOf ui.grid.importer.service:uiGridImporterService\n         * @description Provides an internationalised user alert for the failure,\n         * and logs a console message including diagnostic content.\n         * Optionally, if the the `gridOptions.importerErrorCallback` routine\n         * is defined, then calls that instead, allowing user specified error routines\n         * @param {Grid} grid the grid we're importing into\n         * @param {array} headerRow the header row that we wish to match against\n         * the column definitions\n         */\n        alertError: function( grid, alertI18nToken, consoleMessage, context ){\n          if ( grid.options.importerErrorCallback ){\n            grid.options.importerErrorCallback( grid, alertI18nToken, consoleMessage, context );\n          } else {\n            $window.alert(i18nService.getSafeText( alertI18nToken )); \n            gridUtil.logError(consoleMessage + context ); \n          }\n        }\n      };\n\n      return service;\n\n    }\n  ]);\n\n  /**\n   *  @ngdoc directive\n   *  @name ui.grid.importer.directive:uiGridImporter\n   *  @element div\n   *  @restrict A\n   *\n   *  @description Adds importer features to grid\n   *\n   */\n  module.directive('uiGridImporter', ['uiGridImporterConstants', 'uiGridImporterService', 'gridUtil', '$compile',\n    function (uiGridImporterConstants, uiGridImporterService, gridUtil, $compile) {\n      return {\n        replace: true,\n        priority: 0,\n        require: '^uiGrid',\n        scope: false,\n        link: function ($scope, $elm, $attrs, uiGridCtrl) {\n          uiGridImporterService.initializeGrid($scope, uiGridCtrl.grid);\n        }\n      };\n    }\n  ]);\n  \n  /**\n   *  @ngdoc directive\n   *  @name ui.grid.importer.directive:uiGridImporterMenuItem\n   *  @element div\n   *  @restrict A\n   *\n   *  @description Handles the processing from the importer menu item - once a file is\n   *  selected\n   *\n   */\n  module.directive('uiGridImporterMenuItem', ['uiGridImporterConstants', 'uiGridImporterService', 'gridUtil', '$compile',\n    function (uiGridImporterConstants, uiGridImporterService, gridUtil, $compile) {\n      return {\n        replace: true,\n        priority: 0,\n        require: '^uiGrid',\n        scope: false,\n        templateUrl: 'ui-grid/importerMenuItem',\n        link: function ($scope, $elm, $attrs, uiGridCtrl) {\n          var handleFileSelect = function( event ){\n            var target = event.srcElement || event.target;\n            \n            if (target && target.files && target.files.length === 1) {\n              var fileObject = target.files[0];\n              uiGridImporterService.importThisFile( grid, fileObject );\n              target.form.reset();\n            }\n          };\n\n          var fileChooser = $elm[0].querySelectorAll('.ui-grid-importer-file-chooser');\n          var grid = uiGridCtrl.grid;\n          \n          if ( fileChooser.length !== 1 ){\n            gridUtil.logError('Found > 1 or < 1 file choosers within the menu item, error, cannot continue');\n          } else {\n            fileChooser[0].addEventListener('change', handleFileSelect, false);  // TODO: why the false on the end?  Google  \n          }\n        }\n      };\n    }\n  ]);  \n})();\n(function() {\n  'use strict';\n  /**\n   *  @ngdoc overview\n   *  @name ui.grid.infiniteScroll\n   *\n   *  @description\n   *\n   *   #ui.grid.infiniteScroll\n   * This module provides infinite scroll functionality to ui-grid\n   *\n   */\n  var module = angular.module('ui.grid.infiniteScroll', ['ui.grid']);\n  /**\n   *  @ngdoc service\n   *  @name ui.grid.infiniteScroll.service:uiGridInfiniteScrollService\n   *\n   *  @description Service for infinite scroll features\n   */\n  module.service('uiGridInfiniteScrollService', ['gridUtil', '$compile', '$timeout', 'uiGridConstants', function (gridUtil, $compile, $timeout, uiGridConstants) {\n\n    var service = {\n\n      /**\n       * @ngdoc function\n       * @name initializeGrid\n       * @methodOf ui.grid.infiniteScroll.service:uiGridInfiniteScrollService\n       * @description This method register events and methods into grid public API\n       */\n\n      initializeGrid: function(grid) {\n        service.defaultGridOptions(grid.options);\n\n        /**\n         *  @ngdoc object\n         *  @name ui.grid.infiniteScroll.api:PublicAPI\n         *\n         *  @description Public API for infinite scroll feature\n         */\n        var publicApi = {\n          events: {\n            infiniteScroll: {\n\n              /**\n               * @ngdoc event\n               * @name needLoadMoreData\n               * @eventOf ui.grid.infiniteScroll.api:PublicAPI\n               * @description This event fires when scroll reached bottom percentage of grid\n               * and needs to load data\n               */\n\n              needLoadMoreData: function ($scope, fn) {\n              },\n\n              /**\n               * @ngdoc event\n               * @name needLoadMoreDataTop\n               * @eventOf ui.grid.infiniteScroll.api:PublicAPI\n               * @description This event fires when scroll reached top percentage of grid\n               * and needs to load data\n               */\n\n              needLoadMoreDataTop: function ($scope, fn) {\n              }\n            }\n          },\n          methods: {\n            infiniteScroll: {\n\n              /**\n               * @ngdoc function\n               * @name dataLoaded\n               * @methodOf ui.grid.infiniteScroll.api:PublicAPI\n               * @description This function is used as a promise when data finished loading.\n               * See infinite_scroll ngdoc for example of usage\n               */\n\n              dataLoaded: function() {\n                grid.options.loadTimout = false;\n              }\n            }\n          }\n        };\n        grid.options.loadTimout = false;\n        grid.api.registerEventsFromObject(publicApi.events);\n        grid.api.registerMethodsFromObject(publicApi.methods);\n      },\n      defaultGridOptions: function (gridOptions) {\n        //default option to true unless it was explicitly set to false\n        /**\n         *  @ngdoc object\n         *  @name ui.grid.infiniteScroll.api:GridOptions\n         *\n         *  @description GridOptions for infinite scroll feature, these are available to be\n         *  set using the ui-grid {@link ui.grid.class:GridOptions gridOptions}\n         */\n\n        /**\n         *  @ngdoc object\n         *  @name enableInfiniteScroll\n         *  @propertyOf  ui.grid.infiniteScroll.api:GridOptions\n         *  @description Enable infinite scrolling for this grid\n         *  <br/>Defaults to true\n         */\n        gridOptions.enableInfiniteScroll = gridOptions.enableInfiniteScroll !== false;\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name loadData\n       * @methodOf ui.grid.infiniteScroll.service:uiGridInfiniteScrollService\n       * @description This function fires 'needLoadMoreData' or 'needLoadMoreDataTop' event based on scrollDirection\n       */\n\n      loadData: function (grid) {\n        grid.options.loadTimout = true;\n        if (grid.scrollDirection === uiGridConstants.scrollDirection.UP) {\n          grid.api.infiniteScroll.raise.needLoadMoreDataTop();\n          return;\n        }\n        grid.api.infiniteScroll.raise.needLoadMoreData();\n      },\n\n      /**\n       * @ngdoc function\n       * @name checkScroll\n       * @methodOf ui.grid.infiniteScroll.service:uiGridInfiniteScrollService\n       * @description This function checks scroll position inside grid and\n       * calls 'loadData' function when scroll reaches 'infiniteScrollPercentage'\n       */\n\n      checkScroll: function(grid, scrollTop) {\n\n        /* Take infiniteScrollPercentage value or use 20% as default */\n        var infiniteScrollPercentage = grid.options.infiniteScrollPercentage ? grid.options.infiniteScrollPercentage : 20;\n\n        if (!grid.options.loadTimout && scrollTop <= infiniteScrollPercentage) {\n          this.loadData(grid);\n          return true;\n        }\n        return false;\n      }\n      /**\n       * @ngdoc property\n       * @name infiniteScrollPercentage\n       * @propertyOf ui.grid.class:GridOptions\n       * @description This setting controls at what percentage of the scroll more data\n       * is requested by the infinite scroll\n       */\n    };\n    return service;\n  }]);\n  /**\n   *  @ngdoc directive\n   *  @name ui.grid.infiniteScroll.directive:uiGridInfiniteScroll\n   *  @element div\n   *  @restrict A\n   *\n   *  @description Adds infinite scroll features to grid\n   *\n   *  @example\n   <example module=\"app\">\n   <file name=\"app.js\">\n   var app = angular.module('app', ['ui.grid', 'ui.grid.infiniteScroll']);\n\n   app.controller('MainCtrl', ['$scope', function ($scope) {\n      $scope.data = [\n        { name: 'Alex', car: 'Toyota' },\n            { name: 'Sam', car: 'Lexus' }\n      ];\n\n      $scope.columnDefs = [\n        {name: 'name'},\n        {name: 'car'}\n      ];\n    }]);\n   </file>\n   <file name=\"index.html\">\n   <div ng-controller=\"MainCtrl\">\n   <div ui-grid=\"{ data: data, columnDefs: columnDefs }\" ui-grid-infinite-scroll=\"20\"></div>\n   </div>\n   </file>\n   </example>\n   */\n\n  module.directive('uiGridInfiniteScroll', ['uiGridInfiniteScrollService',\n    function (uiGridInfiniteScrollService) {\n      return {\n        priority: -200,\n        scope: false,\n        require: '^uiGrid',\n        compile: function($scope, $elm, $attr){\n          return {\n            pre: function($scope, $elm, $attr, uiGridCtrl) {\n              uiGridInfiniteScrollService.initializeGrid(uiGridCtrl.grid);\n            },\n            post: function($scope, $elm, $attr) {\n            }\n          };\n        }\n      };\n    }]);\n\n  module.directive('uiGridViewport',\n    ['$compile', 'gridUtil', 'uiGridInfiniteScrollService', 'uiGridConstants',\n      function ($compile, gridUtil, uiGridInfiniteScrollService, uiGridConstants) {\n        return {\n          priority: -200,\n          scope: false,\n          link: function ($scope, $elm, $attr){\n            if ($scope.grid.options.enableInfiniteScroll) {\n              $scope.grid.api.core.on.scrollEvent($scope, function (args) {\n                  //Prevent circular scroll references, if source is coming from ui.grid.adjustInfiniteScrollPosition() function\n                  if (args.y && (args.source !== 'ui.grid.adjustInfiniteScrollPosition')) {\n                    var percentage = 100 - (args.y.percentage * 100);\n                    if ($scope.grid.scrollDirection === uiGridConstants.scrollDirection.UP) {\n                      percentage = (args.y.percentage * 100);\n                    }\n                    uiGridInfiniteScrollService.checkScroll($scope.grid, percentage);\n                  }\n              });\n            }\n          }\n        };\n      }]);\n})();\n(function () {\n  'use strict';\n\n  /**\n   * @ngdoc overview\n   * @name ui.grid.moveColumns\n   * @description\n   * # ui.grid.moveColumns\n   * This module provides column moving capability to ui.grid. It enables to change the position of columns.\n   * <div doc-module-components=\"ui.grid.moveColumns\"></div>\n   */\n  var module = angular.module('ui.grid.moveColumns', ['ui.grid']);\n\n  /**\n   *  @ngdoc service\n   *  @name ui.grid.moveColumns.service:uiGridMoveColumnService\n   *  @description Service for column moving feature.\n   */\n  module.service('uiGridMoveColumnService', ['$q', '$timeout', '$log', 'ScrollEvent', 'uiGridConstants', function ($q, $timeout, $log, ScrollEvent, uiGridConstants) {\n\n    var service = {\n      initializeGrid: function (grid) {\n        var self = this;\n        this.registerPublicApi(grid);\n        this.defaultGridOptions(grid.options);\n        grid.registerColumnBuilder(self.movableColumnBuilder);\n      },\n      registerPublicApi: function (grid) {\n        var self = this;\n        /**\n         *  @ngdoc object\n         *  @name ui.grid.moveColumns.api:PublicApi\n         *  @description Public Api for column moving feature.\n         */\n        var publicApi = {\n          events: {\n            /**\n             * @ngdoc event\n             * @name columnPositionChanged\n             * @eventOf  ui.grid.moveColumns.api:PublicApi\n             * @description raised when column is moved\n             * <pre>\n             *      gridApi.colMovable.on.columnPositionChanged(scope,function(colDef, originalPosition, newPosition){})\n             * </pre>\n             * @param {object} colDef the column that was moved\n             * @param {integer} originalPosition of the column\n             * @param {integer} finalPosition of the column\n             */\n            colMovable: {\n              columnPositionChanged: function (colDef, originalPosition, newPosition) {\n              }\n            }\n          },\n          methods: {\n            /**\n             * @ngdoc method\n             * @name moveColumn\n             * @methodOf  ui.grid.moveColumns.api:PublicApi\n             * @description Method can be used to change column position.\n             * <pre>\n             *      gridApi.colMovable.moveColumn(oldPosition, newPosition)\n             * </pre>\n             * @param {integer} originalPosition of the column\n             * @param {integer} finalPosition of the column\n             */\n            colMovable: {\n              moveColumn: function (originalPosition, finalPosition) {\n                var columns = grid.columns;\n                if (!angular.isNumber(originalPosition) || !angular.isNumber(finalPosition)) {\n                  console.log('Please provide valid values for originalPosition and finalPosition');\n                  return;\n                }\n                var nonMovableColumns = 0;\n                for (var i = 0; i < columns.length; i++) {\n                  if ((angular.isDefined(columns[i].colDef.visible) && columns[i].colDef.visible === false) || columns[i].isRowHeader === true) {\n                    nonMovableColumns++;\n                  }\n                }\n                if (originalPosition >= (columns.length - nonMovableColumns) || finalPosition >= (columns.length - nonMovableColumns)) {\n                  console.log('Invalid values for originalPosition, finalPosition');\n                  return;\n                }\n                var findPositionForRenderIndex = function (index) {\n                  var position = index;\n                  for (var i = 0; i <= position; i++) {\n                    if (angular.isDefined(columns[i]) && ((angular.isDefined(columns[i].colDef.visible) && columns[i].colDef.visible === false) || columns[i].isRowHeader === true)) {\n                      position++;\n                    }\n                  }\n                  return position;\n                };\n                self.redrawColumnAtPosition(grid, findPositionForRenderIndex(originalPosition), findPositionForRenderIndex(finalPosition));\n              }\n            }\n          }\n        };\n        grid.api.registerEventsFromObject(publicApi.events);\n        grid.api.registerMethodsFromObject(publicApi.methods);\n      },\n      defaultGridOptions: function (gridOptions) {\n        /**\n         *  @ngdoc object\n         *  @name ui.grid.moveColumns.api:GridOptions\n         *\n         *  @description Options for configuring the move column feature, these are available to be\n         *  set using the ui-grid {@link ui.grid.class:GridOptions gridOptions}\n         */\n        /**\n         *  @ngdoc object\n         *  @name enableColumnMoving\n         *  @propertyOf  ui.grid.moveColumns.api:GridOptions\n         *  @description If defined, sets the default value for the colMovable flag on each individual colDefs\n         *  if their individual enableColumnMoving configuration is not defined. Defaults to true.\n         */\n        gridOptions.enableColumnMoving = gridOptions.enableColumnMoving !== false;\n      },\n      movableColumnBuilder: function (colDef, col, gridOptions) {\n        var promises = [];\n        /**\n         *  @ngdoc object\n         *  @name ui.grid.moveColumns.api:ColumnDef\n         *\n         *  @description Column Definition for move column feature, these are available to be\n         *  set using the ui-grid {@link ui.grid.class:GridOptions.columnDef gridOptions.columnDefs}\n         */\n        /**\n         *  @ngdoc object\n         *  @name enableColumnMoving\n         *  @propertyOf  ui.grid.moveColumns.api:ColumnDef\n         *  @description Enable column moving for the column.\n         */\n        colDef.enableColumnMoving = colDef.enableColumnMoving === undefined ? gridOptions.enableColumnMoving\n          : colDef.enableColumnMoving;\n        return $q.all(promises);\n      },\n      redrawColumnAtPosition: function (grid, originalPosition, newPosition) {\n\n        var columns = grid.columns;\n\n        var originalColumn = columns[originalPosition];\n        if (originalColumn.colDef.enableColumnMoving) {\n          if (originalPosition > newPosition) {\n            for (var i1 = originalPosition; i1 > newPosition; i1--) {\n              columns[i1] = columns[i1 - 1];\n            }\n          }\n          else if (newPosition > originalPosition) {\n            for (var i2 = originalPosition; i2 < newPosition; i2++) {\n              columns[i2] = columns[i2 + 1];\n            }\n          }\n          columns[newPosition] = originalColumn;\n          $timeout(function () {\n            grid.refresh();\n            grid.api.colMovable.raise.columnPositionChanged(originalColumn.colDef, originalPosition, newPosition);\n            grid.api.core.notifyDataChange( uiGridConstants.dataChange.COLUMN );\n          });\n        }\n      }\n    };\n    return service;\n  }]);\n\n  /**\n   *  @ngdoc directive\n   *  @name ui.grid.moveColumns.directive:uiGridMoveColumns\n   *  @element div\n   *  @restrict A\n   *  @description Adds column moving features to the ui-grid directive.\n   *  @example\n   <example module=\"app\">\n   <file name=\"app.js\">\n   var app = angular.module('app', ['ui.grid', 'ui.grid.moveColumns']);\n   app.controller('MainCtrl', ['$scope', function ($scope) {\n        $scope.data = [\n          { name: 'Bob', title: 'CEO', age: 45 },\n          { name: 'Frank', title: 'Lowly Developer', age: 25 },\n          { name: 'Jenny', title: 'Highly Developer', age: 35 }\n        ];\n        $scope.columnDefs = [\n          {name: 'name'},\n          {name: 'title'},\n          {name: 'age'}\n        ];\n      }]);\n   </file>\n   <file name=\"main.css\">\n   .grid {\n      width: 100%;\n      height: 150px;\n    }\n   </file>\n   <file name=\"index.html\">\n   <div ng-controller=\"MainCtrl\">\n   <div class=\"grid\" ui-grid=\"{ data: data, columnDefs: columnDefs }\" ui-grid-move-columns></div>\n   </div>\n   </file>\n   </example>\n   */\n  module.directive('uiGridMoveColumns', ['uiGridMoveColumnService', function (uiGridMoveColumnService) {\n    return {\n      replace: true,\n      priority: 0,\n      require: '^uiGrid',\n      scope: false,\n      compile: function () {\n        return {\n          pre: function ($scope, $elm, $attrs, uiGridCtrl) {\n            uiGridMoveColumnService.initializeGrid(uiGridCtrl.grid);\n          },\n          post: function ($scope, $elm, $attrs, uiGridCtrl) {\n          }\n        };\n      }\n    };\n  }]);\n\n  /**\n   *  @ngdoc directive\n   *  @name ui.grid.moveColumns.directive:uiGridHeaderCell\n   *  @element div\n   *  @restrict A\n   *\n   *  @description Stacks on top of ui.grid.uiGridHeaderCell to provide capability to be able to move it to reposition column.\n   *\n   *  On receiving mouseDown event headerCell is cloned, now as the mouse moves the cloned header cell also moved in the grid.\n   *  In case the moving cloned header cell reaches the left or right extreme of grid, grid scrolling is triggered (if horizontal scroll exists).\n   *  On mouseUp event column is repositioned at position where mouse is released and cloned header cell is removed.\n   *\n   *  Events that invoke cloning of header cell:\n   *    - mousedown\n   *\n   *  Events that invoke movement of cloned header cell:\n   *    - mousemove\n   *\n   *  Events that invoke repositioning of column:\n   *    - mouseup\n   */\n  module.directive('uiGridHeaderCell', ['$q', 'gridUtil', 'uiGridMoveColumnService', '$document', '$log', 'uiGridConstants', 'ScrollEvent',\n    function ($q, gridUtil, uiGridMoveColumnService, $document, $log, uiGridConstants, ScrollEvent) {\n      return {\n        priority: -10,\n        require: '^uiGrid',\n        compile: function () {\n          return {\n            post: function ($scope, $elm, $attrs, uiGridCtrl) {\n\n              if ($scope.col.colDef.enableColumnMoving) {\n\n                $scope.$on(uiGridConstants.events.COLUMN_HEADER_CLICK, function (event, args) {\n\n                  if (args.columnName === $scope.col.colDef.name && !$scope.col.renderContainer) {\n\n                    var evt = args.event;\n                    if (evt.target.className !== 'ui-grid-icon-angle-down' && evt.target.tagName !== 'I' &&\n                      evt.target.className.indexOf('ui-grid-filter-input') < 0) {\n\n                      //Setting some variables required for calculations.\n                      var gridLeft = $scope.grid.element[0].getBoundingClientRect().left;\n                      var previousMouseX = evt.pageX;\n                      var totalMouseMovement = 0;\n                      var rightMoveLimit = gridLeft + $scope.grid.getViewportWidth();// - $scope.grid.verticalScrollbarWidth;\n\n                      //Clone element should move horizontally with mouse.\n                      var elmCloned = false;\n                      var movingElm;\n                      var reducedWidth;\n\n                      var cloneElement = function () {\n                        elmCloned = true;\n\n                        //Cloning header cell and appending to current header cell.\n                        movingElm = $elm.clone();\n                        $elm.parent().append(movingElm);\n\n                        //Left of cloned element should be aligned to original header cell.\n                        movingElm.addClass('movingColumn');\n                        var movingElementStyles = {};\n                        var elmLeft = $elm[0].getBoundingClientRect().left;\n                        movingElementStyles.left = (elmLeft - gridLeft) + 'px';\n                        var gridRight = $scope.grid.element[0].getBoundingClientRect().right;\n                        var elmRight = $elm[0].getBoundingClientRect().right;\n                        if (elmRight > gridRight) {\n                          reducedWidth = $scope.col.drawnWidth + (gridRight - elmRight);\n                          movingElementStyles.width = reducedWidth + 'px';\n                        }\n                        movingElm.css(movingElementStyles);\n                      };\n\n                      var moveElement = function (changeValue) {\n                        //Hide column menu\n                        uiGridCtrl.fireEvent('hide-menu');\n\n                        //Calculate total column width\n                        var columns = $scope.grid.columns;\n                        var totalColumnWidth = 0;\n                        for (var i = 0; i < columns.length; i++) {\n                          if (angular.isUndefined(columns[i].colDef.visible) || columns[i].colDef.visible === true) {\n                            totalColumnWidth += columns[i].drawnWidth || columns[i].width || columns[i].colDef.width;\n                          }\n                        }\n\n                        //Calculate new position of left of column\n                        var currentElmLeft = movingElm[0].getBoundingClientRect().left - 1;\n                        var currentElmRight = movingElm[0].getBoundingClientRect().right;\n                        var newElementLeft;\n                        if (gridUtil.detectBrowser() === 'ie') {\n                          newElementLeft = currentElmLeft + changeValue;\n                        }\n                        else {\n                          newElementLeft = currentElmLeft - gridLeft + changeValue;\n                        }\n                        newElementLeft = newElementLeft < rightMoveLimit ? newElementLeft : rightMoveLimit;\n\n                        //Update css of moving column to adjust to new left value or fire scroll in case column has reached edge of grid\n                        if ((currentElmLeft >= gridLeft || changeValue > 0) && (currentElmRight <= rightMoveLimit || changeValue < 0)) {\n                          movingElm.css({visibility: 'visible', 'left': newElementLeft + 'px'});\n                        }\n                        else if (totalColumnWidth > Math.ceil(uiGridCtrl.grid.gridWidth)) {\n                          changeValue *= 8;\n                          var scrollEvent = new ScrollEvent($scope.col.grid, null, null, 'uiGridHeaderCell.moveElement');\n                          scrollEvent.x = {pixels: changeValue};\n                          scrollEvent.fireScrollingEvent();\n                        }\n\n                        //Calculate total width of columns on the left of the moving column and the mouse movement\n                        var totalColumnsLeftWidth = 0;\n                        for (var il = 0; il < columns.length; il++) {\n                          if (angular.isUndefined(columns[il].colDef.visible) || columns[il].colDef.visible === true) {\n                            if (columns[il].colDef.name !== $scope.col.colDef.name) {\n                              totalColumnsLeftWidth += columns[il].drawnWidth || columns[il].width || columns[il].colDef.width;\n                            }\n                            else {\n                              break;\n                            }\n                          }\n                        }\n                        if ($scope.newScrollLeft === undefined) {\n                          totalMouseMovement += changeValue;\n                        }\n                        else {\n                          totalMouseMovement = $scope.newScrollLeft + newElementLeft - totalColumnsLeftWidth;\n                        }\n\n                        //Increase width of moving column, in case the rightmost column was moved and its width was\n                        //decreased because of overflow\n                        if (reducedWidth < $scope.col.drawnWidth) {\n                          reducedWidth += Math.abs(changeValue);\n                          movingElm.css({'width': reducedWidth + 'px'});\n                        }\n                      };\n\n                      var mouseMoveHandler = function (evt) {\n                        //Disable text selection in Chrome during column move\n                        document.onselectstart = function() { return false; };\n\n                        var changeValue = evt.pageX - previousMouseX;\n                        if (!elmCloned && Math.abs(changeValue) > 50) {\n                          cloneElement();\n                        }\n                        else if (elmCloned) {\n                          moveElement(changeValue);\n                          previousMouseX = evt.pageX;\n                        }\n                      };\n\n                      /*\n                       //Commenting these lines as they are creating trouble with column moving when grid has huge scroll\n                       // On scope destroy, remove the mouse event handlers from the document body\n                       $scope.$on('$destroy', function () {\n                       $document.off('mousemove', mouseMoveHandler);\n                       $document.off('mouseup', mouseUpHandler);\n                       });\n                       */\n                      $document.on('mousemove', mouseMoveHandler);\n\n                      var mouseUpHandler = function (evt) {\n                        //Re-enable text selection after column move\n                        document.onselectstart = null;\n\n                        //Remove the cloned element on mouse up.\n                        if (movingElm) {\n                          movingElm.remove();\n                        }\n\n                        var columns = $scope.grid.columns;\n                        var columnIndex = 0;\n                        for (var i = 0; i < columns.length; i++) {\n                          if (columns[i].colDef.name !== $scope.col.colDef.name) {\n                            columnIndex++;\n                          }\n                          else {\n                            break;\n                          }\n                        }\n\n                        //Case where column should be moved to a position on its left\n                        if (totalMouseMovement < 0) {\n                          var totalColumnsLeftWidth = 0;\n                          for (var il = columnIndex - 1; il >= 0; il--) {\n                            if (angular.isUndefined(columns[il].colDef.visible) || columns[il].colDef.visible === true) {\n                              totalColumnsLeftWidth += columns[il].drawnWidth || columns[il].width || columns[il].colDef.width;\n                              if (totalColumnsLeftWidth > Math.abs(totalMouseMovement)) {\n                                uiGridMoveColumnService.redrawColumnAtPosition\n                                ($scope.grid, columnIndex, il + 1);\n                                break;\n                              }\n                            }\n                          }\n                          //Case where column should be moved to beginning of the grid.\n                          if (totalColumnsLeftWidth < Math.abs(totalMouseMovement)) {\n                            uiGridMoveColumnService.redrawColumnAtPosition\n                            ($scope.grid, columnIndex, 0);\n                          }\n                        }\n\n                        //Case where column should be moved to a position on its right\n                        else if (totalMouseMovement > 0) {\n                          var totalColumnsRightWidth = 0;\n                          for (var ir = columnIndex + 1; ir < columns.length; ir++) {\n                            if (angular.isUndefined(columns[ir].colDef.visible) || columns[ir].colDef.visible === true) {\n                              totalColumnsRightWidth += columns[ir].drawnWidth || columns[ir].width || columns[ir].colDef.width;\n                              if (totalColumnsRightWidth > totalMouseMovement) {\n                                uiGridMoveColumnService.redrawColumnAtPosition\n                                ($scope.grid, columnIndex, ir - 1);\n                                break;\n                              }\n                            }\n                          }\n                          //Case where column should be moved to end of the grid.\n                          if (totalColumnsRightWidth < totalMouseMovement) {\n                            uiGridMoveColumnService.redrawColumnAtPosition\n                            ($scope.grid, columnIndex, columns.length - 1);\n                          }\n                        }\n/*\n                        else if (totalMouseMovement === 0) {\n                          if (uiGridCtrl.grid.options.enableSorting && $scope.col.enableSorting) {\n                            //sort the current column\n                            var add = false;\n                            if (evt.shiftKey) {\n                              add = true;\n                            }\n                            // Sort this column then rebuild the grid's rows\n                            uiGridCtrl.grid.sortColumn($scope.col, add)\n                              .then(function () {\n                                if (uiGridCtrl.columnMenuScope) {\n                                  uiGridCtrl.columnMenuScope.hideMenu();\n                                }\n                                uiGridCtrl.grid.refresh();\n                              });\n                          }\n                        }\n*/\n                        $document.off('mousemove', mouseMoveHandler);\n                        $document.off('mouseup', mouseUpHandler);\n                      };\n\n                      //Binding the mouseup event handler\n                      $document.on('mouseup', mouseUpHandler);\n                    }\n                  }\n                });\n              }\n            }\n          };\n        }\n      };\n    }]);\n})();\n\n(function() {\n  'use strict';\n\n  /**\n   * @ngdoc overview\n   * @name ui.grid.pagination\n   *\n   * @description\n   *\n   * #ui.grid.pagination\n   * This module provides pagination support to ui-grid\n   */\n  var module = angular.module('ui.grid.pagination', ['ng', 'ui.grid']);\n\n  /**\n   * @ngdoc service\n   * @name ui.grid.pagination.service:uiGridPaginationService\n   *\n   * @description Service for the pagination feature\n   */\n  module.service('uiGridPaginationService', ['gridUtil',\n    function (gridUtil) {\n      var service = {\n        /**\n         * @ngdoc method\n         * @name initializeGrid\n         * @methodOf ui.grid.pagination.service:uiGridPaginationService\n         * @description Attaches the service to a certain grid\n         * @param {Grid} grid The grid we want to work with\n         */\n        initializeGrid: function (grid) {\n          service.defaultGridOptions(grid.options);\n\n          /**\n          * @ngdoc object\n          * @name ui.grid.pagination.api:PublicAPI\n          *\n          * @description Public API for the pagination feature\n          */\n          var publicApi = {\n            events: {\n              pagination: {\n              /**\n               * @ngdoc event\n               * @name paginationChanged\n               * @eventOf ui.grid.pagination.api:PublicAPI\n               * @description This event fires when the pageSize or currentPage changes\n               * @param {int} currentPage requested page number\n               * @param {int} pageSize requested page size\n               */\n                paginationChanged: function (currentPage, pageSize) { }\n              }\n            },\n            methods: {\n              pagination: {\n                /**\n                 * @ngdoc method\n                 * @name getPage\n                 * @methodOf ui.grid.pagination.api:PublicAPI\n                 * @description Returns the number of the current page\n                 */\n                getPage: function () {\n                  return grid.options.enablePagination ? grid.options.paginationCurrentPage : null;\n                },\n                /**\n                 * @ngdoc method\n                 * @name getTotalPages\n                 * @methodOf ui.grid.pagination.api:PublicAPI\n                 * @description Returns the total number of pages\n                 */\n                getTotalPages: function () {\n                  if (!grid.options.enablePagination) {\n                    return null;\n                  }\n\n                  return (grid.options.totalItems === 0) ? 1 : Math.ceil(grid.options.totalItems / grid.options.paginationPageSize);\n                },\n                /**\n                 * @ngdoc method\n                 * @name nextPage\n                 * @methodOf ui.grid.pagination.api:PublicAPI\n                 * @description Moves to the next page, if possible\n                 */\n                nextPage: function () {\n                  if (!grid.options.enablePagination) {\n                    return;\n                  }\n\n                  if (grid.options.totalItems > 0) {\n                    grid.options.paginationCurrentPage = Math.min(\n                      grid.options.paginationCurrentPage + 1,\n                      publicApi.methods.pagination.getTotalPages()\n                    );\n                  } else {\n                    grid.options.paginationCurrentPage++;\n                  }\n                },\n                /**\n                 * @ngdoc method\n                 * @name previousPage\n                 * @methodOf ui.grid.pagination.api:PublicAPI\n                 * @description Moves to the previous page, if we're not on the first page\n                 */\n                previousPage: function () {\n                  if (!grid.options.enablePagination) {\n                    return;\n                  }\n\n                  grid.options.paginationCurrentPage = Math.max(grid.options.paginationCurrentPage - 1, 1);\n                },\n                /**\n                 * @ngdoc method\n                 * @name seek\n                 * @methodOf ui.grid.pagination.api:PublicAPI\n                 * @description Moves to the requested page\n                 * @param {int} page The number of the page that should be displayed\n                 */\n                seek: function (page) {\n                  if (!grid.options.enablePagination) {\n                    return;\n                  }\n                  if (!angular.isNumber(page) || page < 1) {\n                    throw 'Invalid page number: ' + page;\n                  }\n\n                  grid.options.paginationCurrentPage = Math.min(page, publicApi.methods.pagination.getTotalPages());\n                }\n              }\n            }\n          };\n\n          grid.api.registerEventsFromObject(publicApi.events);\n          grid.api.registerMethodsFromObject(publicApi.methods);\n          grid.registerRowsProcessor(function (renderableRows) {\n            if (grid.options.useExternalPagination || !grid.options.enablePagination) {\n              return renderableRows;\n            }\n            //client side pagination\n            var pageSize = parseInt(grid.options.paginationPageSize, 10);\n            var currentPage = parseInt(grid.options.paginationCurrentPage, 10);\n            \n            var visibleRows = renderableRows.filter(function (row) { return row.visible; });\n            grid.options.totalItems = visibleRows.length;\n\n            var firstRow = (currentPage - 1) * pageSize;\n            if (firstRow > visibleRows.length) {\n              currentPage = grid.options.paginationCurrentPage = 1;\n              firstRow = (currentPage - 1) * pageSize;\n            }\n            return visibleRows.slice(firstRow, firstRow + pageSize);\n          });\n\n        },\n        defaultGridOptions: function (gridOptions) {\n          /**\n           * @ngdoc object\n           * @name ui.grid.pagination.api:GridOptions\n           *\n           * @description GridOptions for the pagination feature, these are available to be\n           * set using the ui-grid {@link ui.grid.class:GridOptions gridOptions}\n           */\n\n          /**\n           * @ngdoc property\n           * @name enablePagination\n           * @propertyOf ui.grid.pagination.api:GridOptions\n           * @description Enables pagination, defaults to true\n           */\n          gridOptions.enablePagination = gridOptions.enablePagination !== false;\n          /**\n           * @ngdoc property\n           * @name enablePaginationControls\n           * @propertyOf ui.grid.pagination.api:GridOptions\n           * @description Enables the paginator at the bottom of the grid. Turn this off, if you want to implement your\n           *              own controls outside the grid.\n           */\n          gridOptions.enablePaginationControls = gridOptions.enablePaginationControls !== false;\n          /**\n           * @ngdoc property\n           * @name useExternalPagination\n           * @propertyOf ui.grid.pagination.api:GridOptions\n           * @description Disables client side pagination. When true, handle the paginationChanged event and set data\n           *              and totalItems, defaults to `false`\n           */\n          gridOptions.useExternalPagination = gridOptions.useExternalPagination === true;\n          /**\n           * @ngdoc property\n           * @name totalItems\n           * @propertyOf ui.grid.pagination.api:GridOptions\n           * @description Total number of items, set automatically when client side pagination, needs set by user\n           *              for server side pagination\n           */\n          if (gridUtil.isNullOrUndefined(gridOptions.totalItems)) {\n            gridOptions.totalItems = 0;\n          }\n          /**\n           * @ngdoc property\n           * @name paginationPageSizes\n           * @propertyOf ui.grid.pagination.api:GridOptions\n           * @description Array of page sizes, defaults to `[250, 500, 1000]`\n           */\n          if (gridUtil.isNullOrUndefined(gridOptions.paginationPageSizes)) {\n            gridOptions.paginationPageSizes = [250, 500, 1000];\n          }\n          /**\n           * @ngdoc property\n           * @name paginationPageSize\n           * @propertyOf ui.grid.pagination.api:GridOptions\n           * @description Page size, defaults to the first item in paginationPageSizes, or 0 if paginationPageSizes is empty\n           */\n          if (gridUtil.isNullOrUndefined(gridOptions.paginationPageSize)) {\n            if (gridOptions.paginationPageSizes.length > 0) {\n              gridOptions.paginationPageSize = gridOptions.paginationPageSizes[0];\n            } else {              \n              gridOptions.paginationPageSize = 0;\n            }\n          }\n          /**\n           * @ngdoc property\n           * @name paginationCurrentPage\n           * @propertyOf ui.grid.pagination.api:GridOptions\n           * @description Current page number, defaults to 1\n           */\n          if (gridUtil.isNullOrUndefined(gridOptions.paginationCurrentPage)) {\n            gridOptions.paginationCurrentPage = 1;\n          }\n\n          /**\n           * @ngdoc property\n           * @name paginationTemplate\n           * @propertyOf ui.grid.pagination.api:GridOptions\n           * @description A custom template for the pager, defaults to `ui-grid/pagination`\n           */\n          if (gridUtil.isNullOrUndefined(gridOptions.paginationTemplate)) {\n            gridOptions.paginationTemplate = 'ui-grid/pagination';\n          }\n        },\n        /**\n         * @ngdoc method\n         * @methodOf ui.grid.pagination.service:uiGridPaginationService\n         * @name uiGridPaginationService\n         * @description  Raises paginationChanged and calls refresh for client side pagination\n         * @param {Grid} grid the grid for which the pagination changed\n         * @param {int} currentPage requested page number\n         * @param {int} pageSize requested page size\n         */\n        onPaginationChanged: function (grid, currentPage, pageSize) {\n            grid.api.pagination.raise.paginationChanged(currentPage, pageSize);\n            if (!grid.options.useExternalPagination) {\n              grid.refresh(); //client side pagination\n            }\n        }\n      };\n      \n      return service;\n    }\n  ]);\n  /**\n   *  @ngdoc directive\n   *  @name ui.grid.pagination.directive:uiGridPagination\n   *  @element div\n   *  @restrict A\n   *\n   *  @description Adds pagination features to grid\n   *  @example\n   <example module=\"app\">\n   <file name=\"app.js\">\n   var app = angular.module('app', ['ui.grid', 'ui.grid.pagination']);\n\n   app.controller('MainCtrl', ['$scope', function ($scope) {\n      $scope.data = [\n        { name: 'Alex', car: 'Toyota' },\n        { name: 'Sam', car: 'Lexus' },\n        { name: 'Joe', car: 'Dodge' },\n        { name: 'Bob', car: 'Buick' },\n        { name: 'Cindy', car: 'Ford' },\n        { name: 'Brian', car: 'Audi' },\n        { name: 'Malcom', car: 'Mercedes Benz' },\n        { name: 'Dave', car: 'Ford' },\n        { name: 'Stacey', car: 'Audi' },\n        { name: 'Amy', car: 'Acura' },\n        { name: 'Scott', car: 'Toyota' },\n        { name: 'Ryan', car: 'BMW' },\n      ];\n\n      $scope.gridOptions = {\n        data: 'data',\n        paginationPageSizes: [5, 10, 25],\n        paginationPageSize: 5,\n        columnDefs: [\n          {name: 'name'},\n          {name: 'car'}\n        ];\n       }\n    }]);\n   </file>\n   <file name=\"index.html\">\n   <div ng-controller=\"MainCtrl\">\n   <div ui-grid=\"gridOptions\" ui-grid-pagination></div>\n   </div>\n   </file>\n   </example>\n   */\n  module.directive('uiGridPagination', ['gridUtil', 'uiGridPaginationService',\n    function (gridUtil, uiGridPaginationService) {\n      return {\n        priority: -200,\n        scope: false,\n        require: 'uiGrid',\n        link: {\n          pre: function ($scope, $elm, $attr, uiGridCtrl) {\n            uiGridPaginationService.initializeGrid(uiGridCtrl.grid);\n\n            gridUtil.getTemplate(uiGridCtrl.grid.options.paginationTemplate)\n              .then(function (contents) {\n                var template = angular.element(contents);\n                $elm.append(template);\n                uiGridCtrl.innerCompile(template);\n              });\n          }\n        }\n      };\n    }\n  ]);\n\n  /**\n   *  @ngdoc directive\n   *  @name ui.grid.pagination.directive:uiGridPager\n   *  @element div\n   *\n   *  @description Panel for handling pagination\n   */\n  module.directive('uiGridPager', ['uiGridPaginationService', 'uiGridConstants', 'gridUtil', 'i18nService',\n    function (uiGridPaginationService, uiGridConstants, gridUtil, i18nService) {\n      return {\n        priority: -200,\n        scope: true,\n        require: '^uiGrid',\n        link: function ($scope, $elm, $attr, uiGridCtrl) {\n          $scope.paginationApi = uiGridCtrl.grid.api.pagination;\n          $scope.sizesLabel = i18nService.getSafeText('pagination.sizes');\n          $scope.totalItemsLabel = i18nService.getSafeText('pagination.totalItems');\n          \n          var options = uiGridCtrl.grid.options;\n          \n          uiGridCtrl.grid.renderContainers.body.registerViewportAdjuster(function (adjustment) {\n            adjustment.height = adjustment.height - gridUtil.elementHeight($elm);\n            return adjustment;\n          });\n          \n          var dataChangeDereg = uiGridCtrl.grid.registerDataChangeCallback(function (grid) {\n            if (!grid.options.useExternalPagination) {\n              grid.options.totalItems = grid.rows.length;\n            }\n          }, [uiGridConstants.dataChange.ROW]);\n          \n          $scope.$on('$destroy', dataChangeDereg);\n\n          var setShowing = function () {\n            $scope.showingLow = ((options.paginationCurrentPage - 1) * options.paginationPageSize) + 1;\n            $scope.showingHigh = Math.min(options.paginationCurrentPage * options.paginationPageSize, options.totalItems);\n          };\n\n          var deregT = $scope.$watch('grid.options.totalItems + grid.options.paginationPageSize', setShowing);\n\n          var deregP = $scope.$watch('grid.options.paginationCurrentPage + grid.options.paginationPageSize', function (newValues, oldValues) {\n              if (newValues === oldValues) { \n                return; \n              }\n\n              if (!angular.isNumber(options.paginationCurrentPage) || options.paginationCurrentPage < 1) {\n                options.paginationCurrentPage = 1;\n                return;\n              }\n\n              if (options.totalItems > 0 && options.paginationCurrentPage > $scope.paginationApi.getTotalPages()) {\n                options.paginationCurrentPage = $scope.paginationApi.getTotalPages();\n                return;\n              }\n\n              setShowing();\n              uiGridPaginationService.onPaginationChanged($scope.grid, options.paginationCurrentPage, options.paginationPageSize);\n            }\n          );\n\n          $scope.$on('$destroy', function() {\n            deregT();\n            deregP();\n          });\n\n          $scope.cantPageForward = function () {\n            if (options.totalItems > 0) {\n              return options.paginationCurrentPage >= $scope.paginationApi.getTotalPages();\n            } else {\n              return options.data.length < 1;\n            }\n          };\n          \n          $scope.cantPageToLast = function () {\n            if (options.totalItems > 0) {\n              return $scope.cantPageForward();\n            } else {\n              return true;\n            }\n          };\n          \n          $scope.cantPageBackward = function () {\n            return options.paginationCurrentPage <= 1;\n          };\n        }\n      };\n    }\n  ]);\n})();\n\n(function () {\n  'use strict';\n\n  /**\n   * @ngdoc overview\n   * @name ui.grid.pinning\n   * @description\n   *\n   *  # ui.grid.pinning\n   * This module provides column pinning to the end user via menu options in the column header\n   * <br/>\n   * <br/>\n   *\n   * <div doc-module-components=\"ui.grid.pinning\"></div>\n   */\n\n  var module = angular.module('ui.grid.pinning', ['ui.grid']);\n\n  module.service('uiGridPinningService', ['gridUtil', 'GridRenderContainer', 'i18nService', function (gridUtil, GridRenderContainer, i18nService) {\n    var service = {\n\n      initializeGrid: function (grid) {\n        service.defaultGridOptions(grid.options);\n\n        // Register a column builder to add new menu items for pinning left and right\n        grid.registerColumnBuilder(service.pinningColumnBuilder);\n      },\n\n      defaultGridOptions: function (gridOptions) {\n        //default option to true unless it was explicitly set to false\n        /**\n         *  @ngdoc object\n         *  @name ui.grid.pinning.api:GridOptions\n         *\n         *  @description GridOptions for pinning feature, these are available to be  \n           *  set using the ui-grid {@link ui.grid.class:GridOptions gridOptions}\n         */\n\n        /**\n         *  @ngdoc object\n         *  @name enablePinning\n         *  @propertyOf  ui.grid.pinning.api:GridOptions\n         *  @description Enable pinning for the entire grid.  \n         *  <br/>Defaults to true\n         */\n        gridOptions.enablePinning = gridOptions.enablePinning !== false;\n\n      },\n\n      pinningColumnBuilder: function (colDef, col, gridOptions) {\n        //default to true unless gridOptions or colDef is explicitly false\n\n        /**\n         *  @ngdoc object\n         *  @name ui.grid.pinning.api:ColumnDef\n         *\n         *  @description ColumnDef for pinning feature, these are available to be \n         *  set using the ui-grid {@link ui.grid.class:GridOptions.columnDef gridOptions.columnDefs}\n         */\n\n        /**\n         *  @ngdoc object\n         *  @name enablePinning\n         *  @propertyOf  ui.grid.pinning.api:ColumnDef\n         *  @description Enable pinning for the individual column.  \n         *  <br/>Defaults to true\n         */\n        colDef.enablePinning = colDef.enablePinning === undefined ? gridOptions.enablePinning : colDef.enablePinning;\n\n\n        /**\n         *  @ngdoc object\n         *  @name pinnedLeft\n         *  @propertyOf  ui.grid.pinning.api:ColumnDef\n         *  @description Column is pinned left when grid is rendered\n         *  <br/>Defaults to false\n         */\n\n        /**\n         *  @ngdoc object\n         *  @name pinnedRight\n         *  @propertyOf  ui.grid.pinning.api:ColumnDef\n         *  @description Column is pinned right when grid is rendered\n         *  <br/>Defaults to false\n         */\n        if (colDef.pinnedLeft) {\n          if (col.width === '*') {\n            // Need to refresh so the width can be calculated.\n            col.grid.refresh()\n                .then(function () {\n                    col.renderContainer = 'left';\n                    // Need to calculate the width. If col.drawnWidth is used instead then the width\n                    // will be 100% if it's the first column, 50% if it's the second etc.\n                    col.width = col.grid.canvasWidth / col.grid.columns.length;\n                    col.grid.createLeftContainer();\n            });\n          }\n          else {\n            col.renderContainer = 'left';\n            col.grid.createLeftContainer();\n          }\n        }\n        else if (colDef.pinnedRight) {\n            if (col.width === '*') {\n                // Need to refresh so the width can be calculated.\n                col.grid.refresh()\n                    .then(function () {\n                        col.renderContainer = 'right';\n                        // Need to calculate the width. If col.drawnWidth is used instead then the width\n                        // will be 100% if it's the first column, 50% if it's the second etc.\n                        col.width = col.grid.canvasWidth / col.grid.columns.length;\n                        col.grid.createRightContainer();\n                    });\n            }\n            else {\n                col.renderContainer = 'right';\n                col.grid.createRightContainer();\n            }\n        }\n\n        if (!colDef.enablePinning) {\n          return;\n        }\n\n        var pinColumnLeftAction = {\n          name: 'ui.grid.pinning.pinLeft',\n          title: i18nService.get().pinning.pinLeft,\n          icon: 'ui-grid-icon-left-open',\n          shown: function () {\n            return typeof(this.context.col.renderContainer) === 'undefined' || !this.context.col.renderContainer || this.context.col.renderContainer !== 'left';\n          },\n          action: function () {\n            this.context.col.renderContainer = 'left';\n            this.context.col.width = this.context.col.drawnWidth;\n            this.context.col.grid.createLeftContainer();\n\n            // Need to call refresh twice; once to move our column over to the new render container and then\n            //   a second time to update the grid viewport dimensions with our adjustments\n            col.grid.refresh()\n              .then(function () {\n                col.grid.refresh();\n              });\n          }\n        };\n\n        var pinColumnRightAction = {\n          name: 'ui.grid.pinning.pinRight',\n          title: i18nService.get().pinning.pinRight,\n          icon: 'ui-grid-icon-right-open',\n          shown: function () {\n            return typeof(this.context.col.renderContainer) === 'undefined' || !this.context.col.renderContainer || this.context.col.renderContainer !== 'right';\n          },\n          action: function () {\n            this.context.col.renderContainer = 'right';\n            this.context.col.width = this.context.col.drawnWidth;\n            this.context.col.grid.createRightContainer();\n\n\n            // Need to call refresh twice; once to move our column over to the new render container and then\n            //   a second time to update the grid viewport dimensions with our adjustments\n            col.grid.refresh()\n              .then(function () {\n                col.grid.refresh();\n              });\n          }\n        };\n\n        var removePinAction = {\n          name: 'ui.grid.pinning.unpin',\n          title: i18nService.get().pinning.unpin,\n          icon: 'ui-grid-icon-cancel',\n          shown: function () {\n            return typeof(this.context.col.renderContainer) !== 'undefined' && this.context.col.renderContainer !== null && this.context.col.renderContainer !== 'body';\n          },\n          action: function () {\n            this.context.col.renderContainer = null;\n\n            // Need to call refresh twice; once to move our column over to the new render container and then\n            //   a second time to update the grid viewport dimensions with our adjustments\n            col.grid.refresh()\n              .then(function () {\n                col.grid.refresh();\n              });\n          }\n        };\n\n        if (!gridUtil.arrayContainsObjectWithProperty(col.menuItems, 'name', 'ui.grid.pinning.pinLeft')) {\n          col.menuItems.push(pinColumnLeftAction);\n        }\n        if (!gridUtil.arrayContainsObjectWithProperty(col.menuItems, 'name', 'ui.grid.pinning.pinRight')) {\n          col.menuItems.push(pinColumnRightAction);\n        }\n        if (!gridUtil.arrayContainsObjectWithProperty(col.menuItems, 'name', 'ui.grid.pinning.unpin')) {\n          col.menuItems.push(removePinAction);\n        }\n      }\n    };\n\n    return service;\n  }]);\n\n  module.directive('uiGridPinning', ['gridUtil', 'uiGridPinningService',\n    function (gridUtil, uiGridPinningService) {\n      return {\n        require: 'uiGrid',\n        scope: false,\n        compile: function () {\n          return {\n            pre: function ($scope, $elm, $attrs, uiGridCtrl) {\n              uiGridPinningService.initializeGrid(uiGridCtrl.grid);\n            },\n            post: function ($scope, $elm, $attrs, uiGridCtrl) {\n            }\n          };\n        }\n      };\n    }]);\n\n\n})();\n\n(function(){\n  'use strict';\n\n  var module = angular.module('ui.grid.resizeColumns', ['ui.grid']);\n\n  module.service('uiGridResizeColumnsService', ['gridUtil', '$q', '$timeout',\n    function (gridUtil, $q, $timeout) {\n\n      var service = {\n        defaultGridOptions: function(gridOptions){\n          //default option to true unless it was explicitly set to false\n          /**\n           *  @ngdoc object\n           *  @name ui.grid.resizeColumns.api:GridOptions\n           *\n           *  @description GridOptions for resizeColumns feature, these are available to be  \n           *  set using the ui-grid {@link ui.grid.class:GridOptions gridOptions}\n           */\n\n          /**\n           *  @ngdoc object\n           *  @name enableColumnResizing\n           *  @propertyOf  ui.grid.resizeColumns.api:GridOptions\n           *  @description Enable column resizing on the entire grid \n           *  <br/>Defaults to true\n           */\n          gridOptions.enableColumnResizing = gridOptions.enableColumnResizing !== false;\n\n          //legacy support\n          //use old name if it is explicitly false\n          if (gridOptions.enableColumnResize === false){\n            gridOptions.enableColumnResizing = false;\n          }\n        },\n\n        colResizerColumnBuilder: function (colDef, col, gridOptions) {\n\n          var promises = [];\n          /**\n           *  @ngdoc object\n           *  @name ui.grid.resizeColumns.api:ColumnDef\n           *\n           *  @description ColumnDef for resizeColumns feature, these are available to be \n           *  set using the ui-grid {@link ui.grid.class:GridOptions.columnDef gridOptions.columnDefs}\n           */\n\n          /**\n           *  @ngdoc object\n           *  @name enableColumnResizing\n           *  @propertyOf  ui.grid.resizeColumns.api:ColumnDef\n           *  @description Enable column resizing on an individual column\n           *  <br/>Defaults to GridOptions.enableColumnResizing\n           */\n          //default to true unless gridOptions or colDef is explicitly false\n          colDef.enableColumnResizing = colDef.enableColumnResizing === undefined ? gridOptions.enableColumnResizing : colDef.enableColumnResizing;\n\n\n          //legacy support of old option name\n          if (colDef.enableColumnResize === false){\n            colDef.enableColumnResizing = false;\n          }\n\n          return $q.all(promises);\n        },\n        \n        registerPublicApi: function (grid) {\n            /**\n             *  @ngdoc object\n             *  @name ui.grid.resizeColumns.api:PublicApi\n             *  @description Public Api for column resize feature.\n             */\n            var publicApi = {\n              events: {\n                /**\n                 * @ngdoc event\n                 * @name columnSizeChanged\n                 * @eventOf  ui.grid.resizeColumns.api:PublicApi\n                 * @description raised when column is resized\n                 * <pre>\n                 *      gridApi.colResizable.on.columnSizeChanged(scope,function(colDef, deltaChange){})\n                 * </pre>\n                 * @param {object} colDef the column that was resized\n                 * @param {integer} delta of the column size change\n                 */\n                colResizable: {\n                  columnSizeChanged: function (colDef, deltaChange) {\n                  }\n                }\n              }\n            };\n            grid.api.registerEventsFromObject(publicApi.events);\n        },\n        \n        fireColumnSizeChanged: function (grid, colDef, deltaChange) {\n          $timeout(function () {\n            grid.api.colResizable.raise.columnSizeChanged(colDef, deltaChange);\n          });\n        },\n        \n        // get either this column, or the column next to this column, to resize,\n        // returns the column we're going to resize\n        findTargetCol: function(col, position, rtlMultiplier){\n          var renderContainer = col.getRenderContainer();\n\n          if (position === 'left') {\n            // Get the column to the left of this one\n            var colIndex = renderContainer.visibleColumnCache.indexOf(col);          \n            return renderContainer.visibleColumnCache[colIndex - 1 * rtlMultiplier];\n          } else {\n            return col;\n          }\n        }\n        \n      };\n\n      return service;\n\n    }]);\n\n\n  /**\n   * @ngdoc directive\n   * @name ui.grid.resizeColumns.directive:uiGridResizeColumns\n   * @element div\n   * @restrict A\n   * @description\n   * Enables resizing for all columns on the grid. If, for some reason, you want to use the ui-grid-resize-columns directive, but not allow column resizing, you can explicitly set the\n   * option to false. This prevents resizing for the entire grid, regardless of individual columnDef options.\n   *\n   * @example\n   <doc:example module=\"app\">\n   <doc:source>\n   <script>\n   var app = angular.module('app', ['ui.grid', 'ui.grid.resizeColumns']);\n\n   app.controller('MainCtrl', ['$scope', function ($scope) {\n          $scope.gridOpts = {\n            data: [\n              { \"name\": \"Ethel Price\", \"gender\": \"female\", \"company\": \"Enersol\" },\n              { \"name\": \"Claudine Neal\", \"gender\": \"female\", \"company\": \"Sealoud\" },\n              { \"name\": \"Beryl Rice\", \"gender\": \"female\", \"company\": \"Velity\" },\n              { \"name\": \"Wilder Gonzales\", \"gender\": \"male\", \"company\": \"Geekko\" }\n            ]\n          };\n        }]);\n   </script>\n\n   <div ng-controller=\"MainCtrl\">\n   <div class=\"testGrid\" ui-grid=\"gridOpts\" ui-grid-resize-columns ></div>\n   </div>\n   </doc:source>\n   <doc:scenario>\n\n   </doc:scenario>\n   </doc:example>\n   */\n  module.directive('uiGridResizeColumns', ['gridUtil', 'uiGridResizeColumnsService', function (gridUtil, uiGridResizeColumnsService) {\n    return {\n      replace: true,\n      priority: 0,\n      require: '^uiGrid',\n      scope: false,\n      compile: function () {\n        return {\n          pre: function ($scope, $elm, $attrs, uiGridCtrl) {            \n            uiGridResizeColumnsService.defaultGridOptions(uiGridCtrl.grid.options);\n            uiGridCtrl.grid.registerColumnBuilder( uiGridResizeColumnsService.colResizerColumnBuilder);\n            uiGridResizeColumnsService.registerPublicApi(uiGridCtrl.grid);\n          },\n          post: function ($scope, $elm, $attrs, uiGridCtrl) {\n          }\n        };\n      }\n    };\n  }]);\n\n  // Extend the uiGridHeaderCell directive\n  module.directive('uiGridHeaderCell', ['gridUtil', '$templateCache', '$compile', '$q', 'uiGridResizeColumnsService', 'uiGridConstants', '$timeout', function (gridUtil, $templateCache, $compile, $q, uiGridResizeColumnsService, uiGridConstants, $timeout) {\n    return {\n      // Run after the original uiGridHeaderCell\n      priority: -10,\n      require: '^uiGrid',\n      // scope: false,\n      compile: function() {\n        return {\n          post: function ($scope, $elm, $attrs, uiGridCtrl) {\n            var grid = uiGridCtrl.grid;\n\n            if (grid.options.enableColumnResizing) {\n              var columnResizerElm = $templateCache.get('ui-grid/columnResizer');\n    \n              var rtlMultiplier = 1;\n              //when in RTL mode reverse the direction using the rtlMultiplier and change the position to left\n              if (grid.isRTL()) {\n                $scope.position = 'left';\n                rtlMultiplier = -1;\n              }\n\n              var displayResizers = function(){\n                \n                // remove any existing resizers.  \n                var resizers = $elm[0].getElementsByClassName('ui-grid-column-resizer');\n                for ( var i = 0; i < resizers.length; i++ ){\n                  angular.element(resizers[i]).remove();\n                } \n                \n                // get the target column for the left resizer\n                var otherCol = uiGridResizeColumnsService.findTargetCol($scope.col, 'left', rtlMultiplier);\n                var renderContainer = $scope.col.getRenderContainer();\n              \n                // Don't append the left resizer if this is the first column or the column to the left of this one has resizing disabled\n                if (otherCol && renderContainer.visibleColumnCache.indexOf($scope.col) !== 0 && otherCol.colDef.enableColumnResizing !== false) {\n                  var resizerLeft = angular.element(columnResizerElm).clone();\n                  resizerLeft.attr('position', 'left');\n\n                  $elm.prepend(resizerLeft);\n                  $compile(resizerLeft)($scope);\n                }\n                \n                // Don't append the right resizer if this column has resizing disabled\n                if ($scope.col.colDef.enableColumnResizing !== false) {\n                  var resizerRight = angular.element(columnResizerElm).clone();\n                  resizerRight.attr('position', 'right');\n\n                  $elm.append(resizerRight);\n                  $compile(resizerRight)($scope);\n                }\n              };\n\n              displayResizers();\n              \n              var waitDisplay = function(){\n                $timeout(displayResizers);\n              };\n              \n              var dataChangeDereg = grid.registerDataChangeCallback( waitDisplay, [uiGridConstants.dataChange.COLUMN] );\n              \n              $scope.$on( '$destroy', dataChangeDereg );\n            }\n          }\n        };\n      }\n    };\n  }]);\n\n\n  \n  /**\n   * @ngdoc directive\n   * @name ui.grid.resizeColumns.directive:uiGridColumnResizer\n   * @element div\n   * @restrict A\n   *\n   * @description\n   * Draggable handle that controls column resizing.\n   * \n   * @example\n   <doc:example module=\"app\">\n     <doc:source>\n       <script>\n        var app = angular.module('app', ['ui.grid', 'ui.grid.resizeColumns']);\n\n        app.controller('MainCtrl', ['$scope', function ($scope) {\n          $scope.gridOpts = {\n            enableColumnResizing: true,\n            data: [\n              { \"name\": \"Ethel Price\", \"gender\": \"female\", \"company\": \"Enersol\" },\n              { \"name\": \"Claudine Neal\", \"gender\": \"female\", \"company\": \"Sealoud\" },\n              { \"name\": \"Beryl Rice\", \"gender\": \"female\", \"company\": \"Velity\" },\n              { \"name\": \"Wilder Gonzales\", \"gender\": \"male\", \"company\": \"Geekko\" }\n            ]\n          };\n        }]);\n       </script>\n\n       <div ng-controller=\"MainCtrl\">\n        <div class=\"testGrid\" ui-grid=\"gridOpts\"></div>\n       </div>\n     </doc:source>\n     <doc:scenario>\n      // TODO: e2e specs?\n        // TODO: Obey minWidth and maxWIdth;\n\n      // TODO: post-resize a horizontal scroll event should be fired\n     </doc:scenario>\n   </doc:example>\n   */  \n  module.directive('uiGridColumnResizer', ['$document', 'gridUtil', 'uiGridConstants', 'uiGridResizeColumnsService', function ($document, gridUtil, uiGridConstants, uiGridResizeColumnsService) {\n    var resizeOverlay = angular.element('<div class=\"ui-grid-resize-overlay\"></div>');\n\n    var downEvent, upEvent, moveEvent;\n\n    if (gridUtil.isTouchEnabled()) {\n      downEvent = 'touchstart';\n      upEvent = 'touchend';\n      moveEvent = 'touchmove';\n    }\n    else {\n      downEvent = 'mousedown';\n      upEvent = 'mouseup';\n      moveEvent = 'mousemove';\n    }\n\n    var resizer = {\n      priority: 0,\n      scope: {\n        col: '=',\n        position: '@',\n        renderIndex: '='\n      },\n      require: '?^uiGrid',\n      link: function ($scope, $elm, $attrs, uiGridCtrl) {\n        var startX = 0,\n            x = 0,\n            gridLeft = 0,\n            rtlMultiplier = 1;\n\n        //when in RTL mode reverse the direction using the rtlMultiplier and change the position to left\n        if (uiGridCtrl.grid.isRTL()) {\n          $scope.position = 'left';\n          rtlMultiplier = -1;\n        }\n\n        if ($scope.position === 'left') {\n          $elm.addClass('left');\n        }\n        else if ($scope.position === 'right') {\n          $elm.addClass('right');\n        }\n\n        // Resize all the other columns around col\n        function resizeAroundColumn(col) {\n          // Get this column's render container\n          var renderContainer = col.getRenderContainer();\n\n          renderContainer.visibleColumnCache.forEach(function (column) {\n            // Skip the column we just resized\n            if (column === col) { return; }\n            \n            var colDef = column.colDef;\n            if (!colDef.width || (angular.isString(colDef.width) && (colDef.width.indexOf('*') !== -1 || colDef.width.indexOf('%') !== -1))) {\n              column.width = column.drawnWidth;\n            }\n          });\n        }\n\n        // Build the columns then refresh the grid canvas\n        //   takes an argument representing the diff along the X-axis that the resize had\n        function buildColumnsAndRefresh(xDiff) {\n          // Build the columns\n          uiGridCtrl.grid.buildColumns()\n            .then(function() {\n              // Then refresh the grid canvas, rebuilding the styles so that the scrollbar updates its size\n              uiGridCtrl.grid.refreshCanvas(true).then( function() {\n                uiGridCtrl.grid.refresh();\n              });\n            });\n        }\n\n        // Check that the requested width isn't wider than the maxWidth, or narrower than the minWidth\n        // Returns the new recommended with, after constraints applied\n        function constrainWidth(col, width){\n          var newWidth = width;\n\n          // If the new width would be less than the column's allowably minimum width, don't allow it\n          if (col.colDef.minWidth && newWidth < col.colDef.minWidth) {\n            newWidth = col.colDef.minWidth;\n          }\n          else if (col.colDef.maxWidth && newWidth > col.colDef.maxWidth) {\n            newWidth = col.colDef.maxWidth;\n          }\n          \n          return newWidth;\n        }\n        \n        \n        function mousemove(event, args) {\n          if (event.originalEvent) { event = event.originalEvent; }\n          event.preventDefault();\n\n          x = (event.targetTouches ? event.targetTouches[0] : event).clientX - gridLeft;\n\n          if (x < 0) { x = 0; }\n          else if (x > uiGridCtrl.grid.gridWidth) { x = uiGridCtrl.grid.gridWidth; }\n\n          var col = uiGridResizeColumnsService.findTargetCol($scope.col, $scope.position, rtlMultiplier);\n\n          // Don't resize if it's disabled on this column\n          if (col.colDef.enableColumnResizing === false) {\n            return;\n          }\n\n          if (!uiGridCtrl.grid.element.hasClass('column-resizing')) {\n            uiGridCtrl.grid.element.addClass('column-resizing');\n          }\n\n          // Get the diff along the X axis\n          var xDiff = x - startX;\n\n          // Get the width that this mouse would give the column\n          var newWidth = parseInt(col.drawnWidth + xDiff * rtlMultiplier, 10);\n\n          // check we're not outside the allowable bounds for this column\n          x = x + ( constrainWidth(col, newWidth) - newWidth ) * rtlMultiplier;\n          \n          resizeOverlay.css({ left: x + 'px' });\n\n          uiGridCtrl.fireEvent(uiGridConstants.events.ITEM_DRAGGING);\n        }\n        \n\n        function mouseup(event, args) {\n          if (event.originalEvent) { event = event.originalEvent; }\n          event.preventDefault();\n\n          uiGridCtrl.grid.element.removeClass('column-resizing');\n\n          resizeOverlay.remove();\n\n          // Resize the column\n          x = (event.changedTouches ? event.changedTouches[0] : event).clientX - gridLeft;\n          var xDiff = x - startX;\n\n          if (xDiff === 0) {\n            $document.off(upEvent, mouseup);\n            $document.off(moveEvent, mousemove);\n            return;\n          }\n\n          var col = uiGridResizeColumnsService.findTargetCol($scope.col, $scope.position, rtlMultiplier);\n\n          // Don't resize if it's disabled on this column\n          if (col.colDef.enableColumnResizing === false) {\n            return;\n          }\n\n          // Get the new width\n          var newWidth = parseInt(col.drawnWidth + xDiff * rtlMultiplier, 10);\n\n          // check we're not outside the allowable bounds for this column\n          col.width = constrainWidth(col, newWidth);\n\n          // All other columns because fixed to their drawn width, if they aren't already\n          resizeAroundColumn(col);\n\n          buildColumnsAndRefresh(xDiff);\n\n          uiGridResizeColumnsService.fireColumnSizeChanged(uiGridCtrl.grid, col.colDef, xDiff);\n\n          $document.off(upEvent, mouseup);\n          $document.off(moveEvent, mousemove);\n        }\n\n\n        $elm.on(downEvent, function(event, args) {\n          if (event.originalEvent) { event = event.originalEvent; }\n          event.stopPropagation();\n\n          // Get the left offset of the grid\n          // gridLeft = uiGridCtrl.grid.element[0].offsetLeft;\n          gridLeft = uiGridCtrl.grid.element[0].getBoundingClientRect().left;\n\n          // Get the starting X position, which is the X coordinate of the click minus the grid's offset\n          startX = (event.targetTouches ? event.targetTouches[0] : event).clientX - gridLeft;\n\n          // Append the resizer overlay\n          uiGridCtrl.grid.element.append(resizeOverlay);\n\n          // Place the resizer overlay at the start position\n          resizeOverlay.css({ left: startX });\n\n          // Add handlers for mouse move and up events\n          $document.on(upEvent, mouseup);\n          $document.on(moveEvent, mousemove);\n        });\n\n\n        // On doubleclick, resize to fit all rendered cells\n        $elm.on('dblclick', function(event, args) {\n          event.stopPropagation();\n\n          var col = uiGridResizeColumnsService.findTargetCol($scope.col, $scope.position, rtlMultiplier);\n\n          // Don't resize if it's disabled on this column\n          if (col.colDef.enableColumnResizing === false) {\n            return;\n          }\n\n          // Go through the rendered rows and find out the max size for the data in this column\n          var maxWidth = 0;\n          var xDiff = 0;\n\n          // Get the parent render container element\n          var renderContainerElm = gridUtil.closestElm($elm, '.ui-grid-render-container');\n\n          // Get the cell contents so we measure correctly. For the header cell we have to account for the sort icon and the menu buttons, if present\n          var cells = renderContainerElm.querySelectorAll('.' + uiGridConstants.COL_CLASS_PREFIX + col.uid + ' .ui-grid-cell-contents');\n          Array.prototype.forEach.call(cells, function (cell) {\n              // Get the cell width\n              // gridUtil.logDebug('width', gridUtil.elementWidth(cell));\n\n              // Account for the menu button if it exists\n              var menuButton;\n              if (angular.element(cell).parent().hasClass('ui-grid-header-cell')) {\n                menuButton = angular.element(cell).parent()[0].querySelectorAll('.ui-grid-column-menu-button');\n              }\n\n              gridUtil.fakeElement(cell, {}, function(newElm) {\n                // Make the element float since it's a div and can expand to fill its container\n                var e = angular.element(newElm);\n                e.attr('style', 'float: left');\n\n                var width = gridUtil.elementWidth(e);\n\n                if (menuButton) {\n                  var menuButtonWidth = gridUtil.elementWidth(menuButton);\n                  width = width + menuButtonWidth;\n                }\n\n                if (width > maxWidth) {\n                  maxWidth = width;\n                  xDiff = maxWidth - width;\n                }\n              });\n            });\n\n          // check we're not outside the allowable bounds for this column\n          col.width = constrainWidth(col, maxWidth);\n          \n          // All other columns because fixed to their drawn width, if they aren't already\n          resizeAroundColumn(col);\n\n          buildColumnsAndRefresh(xDiff);\n          \n          uiGridResizeColumnsService.fireColumnSizeChanged(uiGridCtrl.grid, col.colDef, xDiff);\n        });\n\n        $elm.on('$destroy', function() {\n          $elm.off(downEvent);\n          $elm.off('dblclick');\n          $document.off(moveEvent, mousemove);\n          $document.off(upEvent, mouseup);\n        });\n      }\n    };\n\n    return resizer;\n  }]);\n\n})();\n(function () {\n  'use strict';\n\n  /**\n   * @ngdoc overview\n   * @name ui.grid.rowEdit\n   * @description\n   *\n   *  # ui.grid.rowEdit\n   * This module extends the edit feature to provide tracking and saving of rows\n   * of data.  The tutorial provides more information on how this feature is best\n   * used {@link tutorial/205_row_editable here}.\n   * <br/>\n   * This feature depends on usage of the ui-grid-edit feature, and also benefits\n   * from use of ui-grid-cellNav to provide the full spreadsheet-like editing \n   * experience\n   * \n   */\n\n  var module = angular.module('ui.grid.rowEdit', ['ui.grid', 'ui.grid.edit', 'ui.grid.cellNav']);\n\n  /**\n   *  @ngdoc object\n   *  @name ui.grid.rowEdit.constant:uiGridRowEditConstants\n   *\n   *  @description constants available in row edit module\n   */\n  module.constant('uiGridRowEditConstants', {\n  });\n\n  /**\n   *  @ngdoc service\n   *  @name ui.grid.rowEdit.service:uiGridRowEditService\n   *\n   *  @description Services for row editing features\n   */\n  module.service('uiGridRowEditService', ['$interval', '$q', 'uiGridConstants', 'uiGridRowEditConstants', 'gridUtil', \n    function ($interval, $q, uiGridConstants, uiGridRowEditConstants, gridUtil) {\n\n      var service = {\n\n        initializeGrid: function (scope, grid) {\n          /**\n           *  @ngdoc object\n           *  @name ui.grid.rowEdit.api:PublicApi\n           *\n           *  @description Public Api for rowEdit feature\n           */\n          \n          grid.rowEdit = {};\n          \n          var publicApi = {\n            events: {\n              rowEdit: {\n                /**\n                 * @ngdoc event\n                 * @eventOf ui.grid.rowEdit.api:PublicApi\n                 * @name saveRow\n                 * @description raised when a row is ready for saving.  Once your\n                 * row has saved you may need to use angular.extend to update the\n                 * data entity with any changed data from your save (for example, \n                 * lock version information if you're using optimistic locking,\n                 * or last update time/user information).\n                 * \n                 * Your method should call setSavePromise somewhere in the body before\n                 * returning control.  The feature will then wait, with the gridRow greyed out \n                 * whilst this promise is being resolved.\n                 * \n                 * <pre>\n                 *      gridApi.rowEdit.on.saveRow(scope,function(rowEntity){})\n                 * </pre>\n                 * and somewhere within the event handler:\n                 * <pre>\n                 *      gridApi.rowEdit.setSavePromise( grid, rowEntity, savePromise)\n                 * </pre>\n                 * @param {object} rowEntity the options.data element that was edited\n                 * @returns {promise} Your saveRow method should return a promise, the\n                 * promise should either be resolved (implying successful save), or \n                 * rejected (implying an error).\n                 */\n                saveRow: function (rowEntity) {\n                }\n              }\n            },\n            methods: {\n              rowEdit: {\n                /**\n                 * @ngdoc method\n                 * @methodOf ui.grid.rowEdit.api:PublicApi\n                 * @name setSavePromise\n                 * @description Sets the promise associated with the row save, mandatory that\n                 * the saveRow event handler calls this method somewhere before returning.\n                 * <pre>\n                 *      gridApi.rowEdit.setSavePromise(grid, rowEntity)\n                 * </pre>\n                 * @param {object} rowEntity a data row from the grid for which a save has\n                 * been initiated\n                 * @param {promise} savePromise the promise that will be resolved when the\n                 * save is successful, or rejected if the save fails\n                 * \n                 */\n                setSavePromise: function ( rowEntity, savePromise) {\n                  service.setSavePromise(grid, rowEntity, savePromise);\n                },\n                /**\n                 * @ngdoc method\n                 * @methodOf ui.grid.rowEdit.api:PublicApi\n                 * @name getDirtyRows\n                 * @description Returns all currently dirty rows\n                 * <pre>\n                 *      gridApi.rowEdit.getDirtyRows(grid)\n                 * </pre>\n                 * @returns {array} An array of gridRows that are currently dirty\n                 * \n                 */\n                getDirtyRows: function () {\n                  return grid.rowEdit.dirtyRows ? grid.rowEdit.dirtyRows : [];\n                },\n                /**\n                 * @ngdoc method\n                 * @methodOf ui.grid.rowEdit.api:PublicApi\n                 * @name getErrorRows\n                 * @description Returns all currently errored rows\n                 * <pre>\n                 *      gridApi.rowEdit.getErrorRows(grid)\n                 * </pre>\n                 * @returns {array} An array of gridRows that are currently in error\n                 * \n                 */\n                getErrorRows: function () {\n                  return grid.rowEdit.errorRows ? grid.rowEdit.errorRows : [];\n                },\n                /**\n                 * @ngdoc method\n                 * @methodOf ui.grid.rowEdit.api:PublicApi\n                 * @name flushDirtyRows\n                 * @description Triggers a save event for all currently dirty rows, could\n                 * be used where user presses a save button or navigates away from the page\n                 * <pre>\n                 *      gridApi.rowEdit.flushDirtyRows(grid)\n                 * </pre>\n                 * @returns {promise} a promise that represents the aggregate of all\n                 * of the individual save promises - i.e. it will be resolved when all\n                 * the individual save promises have been resolved.\n                 * \n                 */\n                flushDirtyRows: function () {\n                  return service.flushDirtyRows(grid);\n                },\n                \n                /**\n                 * @ngdoc method\n                 * @methodOf ui.grid.rowEdit.api:PublicApi\n                 * @name setRowsDirty\n                 * @description Sets each of the rows passed in dataRows\n                 * to be dirty.  note that if you have only just inserted the\n                 * rows into your data you will need to wait for a $digest cycle\n                 * before the gridRows are present - so often you would wrap this\n                 * call in a $interval or $timeout\n                 * <pre>\n                 *      $interval( function() {\n                 *        gridApi.rowEdit.setRowsDirty(grid, myDataRows);\n                 *      }, 0, 1);\n                 * </pre>\n                 * @param {array} dataRows the data entities for which the gridRows\n                 * should be set dirty.  \n                 * \n                 */\n                setRowsDirty: function ( dataRows) {\n                  service.setRowsDirty(grid, dataRows);\n                }\n              }\n            }\n          };\n\n          grid.api.registerEventsFromObject(publicApi.events);\n          grid.api.registerMethodsFromObject(publicApi.methods);\n          \n          grid.api.core.on.renderingComplete( scope, function ( gridApi ) {\n            grid.api.edit.on.afterCellEdit( scope, service.endEditCell );\n            grid.api.edit.on.beginCellEdit( scope, service.beginEditCell );\n            grid.api.edit.on.cancelCellEdit( scope, service.cancelEditCell );\n            \n            if ( grid.api.cellNav ) {\n              grid.api.cellNav.on.navigate( scope, service.navigate );\n            }              \n          });\n\n        },\n\n        defaultGridOptions: function (gridOptions) {\n\n          /**\n           *  @ngdoc object\n           *  @name ui.grid.rowEdit.api:GridOptions\n           *\n           *  @description Options for configuring the rowEdit feature, these are available to be  \n           *  set using the ui-grid {@link ui.grid.class:GridOptions gridOptions}\n           */\n\n        },\n\n\n        /**\n         * @ngdoc method\n         * @methodOf ui.grid.rowEdit.service:uiGridRowEditService\n         * @name saveRow\n         * @description  Returns a function that saves the specified row from the grid,\n         * and returns a promise\n         * @param {object} grid the grid for which dirty rows should be flushed\n         * @param {GridRow} gridRow the row that should be saved\n         * @returns {function} the saveRow function returns a function.  That function\n         * in turn, when called, returns a promise relating to the save callback\n         */\n        saveRow: function ( grid, gridRow ) {\n          var self = this;\n\n          return function() {\n            gridRow.isSaving = true;\n\n            var promise = grid.api.rowEdit.raise.saveRow( gridRow.entity );\n            \n            if ( gridRow.rowEditSavePromise ){\n              gridRow.rowEditSavePromise.then( self.processSuccessPromise( grid, gridRow ), self.processErrorPromise( grid, gridRow ));\n            } else {\n              gridUtil.logError( 'A promise was not returned when saveRow event was raised, either nobody is listening to event, or event handler did not return a promise' );\n            }\n            return promise;\n          };\n        },\n        \n\n        /**\n         * @ngdoc method\n         * @methodOf  ui.grid.rowEdit.service:uiGridRowEditService\n         * @name setSavePromise\n         * @description Sets the promise associated with the row save, mandatory that\n         * the saveRow event handler calls this method somewhere before returning.\n         * <pre>\n         *      gridApi.rowEdit.setSavePromise(grid, rowEntity)\n         * </pre>\n         * @param {object} grid the grid for which dirty rows should be returned\n         * @param {object} rowEntity a data row from the grid for which a save has\n         * been initiated\n         * @param {promise} savePromise the promise that will be resolved when the\n         * save is successful, or rejected if the save fails\n         * \n         */\n        setSavePromise: function (grid, rowEntity, savePromise) {\n          var gridRow = grid.getRow( rowEntity );\n          gridRow.rowEditSavePromise = savePromise;\n        },\n\n\n        /**\n         * @ngdoc method\n         * @methodOf ui.grid.rowEdit.service:uiGridRowEditService\n         * @name processSuccessPromise\n         * @description  Returns a function that processes the successful\n         * resolution of a save promise  \n         * @param {object} grid the grid for which the promise should be processed\n         * @param {GridRow} gridRow the row that has been saved\n         * @returns {function} the success handling function\n         */\n        processSuccessPromise: function ( grid, gridRow ) {\n          var self = this;\n          \n          return function() {\n            delete gridRow.isSaving;\n            delete gridRow.isDirty;\n            delete gridRow.isError;\n            delete gridRow.rowEditSaveTimer;\n            self.removeRow( grid.rowEdit.errorRows, gridRow );\n            self.removeRow( grid.rowEdit.dirtyRows, gridRow );\n          };\n        },\n        \n\n        /**\n         * @ngdoc method\n         * @methodOf ui.grid.rowEdit.service:uiGridRowEditService\n         * @name processErrorPromise\n         * @description  Returns a function that processes the failed\n         * resolution of a save promise  \n         * @param {object} grid the grid for which the promise should be processed\n         * @param {GridRow} gridRow the row that is now in error\n         * @returns {function} the error handling function\n         */\n        processErrorPromise: function ( grid, gridRow ) {\n          return function() {\n            delete gridRow.isSaving;\n            delete gridRow.rowEditSaveTimer;\n\n            gridRow.isError = true;\n            \n            if (!grid.rowEdit.errorRows){\n              grid.rowEdit.errorRows = [];\n            }\n            if (!service.isRowPresent( grid.rowEdit.errorRows, gridRow ) ){\n              grid.rowEdit.errorRows.push( gridRow );\n            }\n          };\n        },\n        \n        \n        /**\n         * @ngdoc method\n         * @methodOf ui.grid.rowEdit.service:uiGridRowEditService\n         * @name removeRow\n         * @description  Removes a row from a cache of rows - either\n         * grid.rowEdit.errorRows or grid.rowEdit.dirtyRows.  If the row\n         * is not present silently does nothing. \n         * @param {array} rowArray the array from which to remove the row\n         * @param {GridRow} gridRow the row that should be removed\n         */\n        removeRow: function( rowArray, removeGridRow ){\n          angular.forEach( rowArray, function( gridRow, index ){\n            if ( gridRow.uid === removeGridRow.uid ){\n              rowArray.splice( index, 1);\n            }\n          });\n        },\n        \n        \n        /**\n         * @ngdoc method\n         * @methodOf ui.grid.rowEdit.service:uiGridRowEditService\n         * @name isRowPresent\n         * @description  Checks whether a row is already present\n         * in the given array \n         * @param {array} rowArray the array in which to look for the row\n         * @param {GridRow} gridRow the row that should be looked for\n         */\n        isRowPresent: function( rowArray, removeGridRow ){\n          var present = false;\n          angular.forEach( rowArray, function( gridRow, index ){\n            if ( gridRow.uid === removeGridRow.uid ){\n              present = true;\n            }\n          });\n          return present;\n        },\n\n        \n        /**\n         * @ngdoc method\n         * @methodOf ui.grid.rowEdit.service:uiGridRowEditService\n         * @name flushDirtyRows\n         * @description Triggers a save event for all currently dirty rows, could\n         * be used where user presses a save button or navigates away from the page\n         * <pre>\n         *      gridApi.rowEdit.flushDirtyRows(grid)\n         * </pre>\n         * @param {object} grid the grid for which dirty rows should be flushed\n         * @returns {promise} a promise that represents the aggregate of all\n         * of the individual save promises - i.e. it will be resolved when all\n         * the individual save promises have been resolved.\n         * \n         */\n        flushDirtyRows: function(grid){\n          var promises = [];\n          angular.forEach(grid.rowEdit.dirtyRows, function( gridRow ){\n            service.saveRow( grid, gridRow )();\n            promises.push( gridRow.rowEditSavePromise );\n          });\n          \n          return $q.all( promises );\n        },\n        \n        \n        /**\n         * @ngdoc method\n         * @methodOf ui.grid.rowEdit.service:uiGridRowEditService\n         * @name endEditCell\n         * @description Receives an afterCellEdit event from the edit function,\n         * and sets flags as appropriate.  Only the rowEntity parameter\n         * is processed, although other params are available.  Grid\n         * is automatically provided by the gridApi. \n         * @param {object} rowEntity the data entity for which the cell\n         * was edited\n         */        \n        endEditCell: function( rowEntity, colDef, newValue, previousValue ){\n          var grid = this.grid;\n          var gridRow = grid.getRow( rowEntity );\n          if ( !gridRow ){ gridUtil.logError( 'Unable to find rowEntity in grid data, dirty flag cannot be set' ); return; }\n\n          if ( newValue !== previousValue || gridRow.isDirty ){\n            if ( !grid.rowEdit.dirtyRows ){\n              grid.rowEdit.dirtyRows = [];\n            }\n            \n            if ( !gridRow.isDirty ){\n              gridRow.isDirty = true;\n              grid.rowEdit.dirtyRows.push( gridRow );\n            }\n            \n            delete gridRow.isError;\n            \n            service.considerSetTimer( grid, gridRow );\n          }\n        },\n        \n        \n        /**\n         * @ngdoc method\n         * @methodOf ui.grid.rowEdit.service:uiGridRowEditService\n         * @name beginEditCell\n         * @description Receives a beginCellEdit event from the edit function,\n         * and cancels any rowEditSaveTimers if present, as the user is still editing\n         * this row.  Only the rowEntity parameter\n         * is processed, although other params are available.  Grid\n         * is automatically provided by the gridApi. \n         * @param {object} rowEntity the data entity for which the cell\n         * editing has commenced\n         */\n        beginEditCell: function( rowEntity, colDef ){\n          var grid = this.grid;\n          var gridRow = grid.getRow( rowEntity );\n          if ( !gridRow ){ gridUtil.logError( 'Unable to find rowEntity in grid data, timer cannot be cancelled' ); return; }\n          \n          service.cancelTimer( grid, gridRow );\n        },\n\n\n        /**\n         * @ngdoc method\n         * @methodOf ui.grid.rowEdit.service:uiGridRowEditService\n         * @name cancelEditCell\n         * @description Receives a cancelCellEdit event from the edit function,\n         * and if the row was already dirty, restarts the save timer.  If the row\n         * was not already dirty, then it's not dirty now either and does nothing.\n         * \n         * Only the rowEntity parameter\n         * is processed, although other params are available.  Grid\n         * is automatically provided by the gridApi.\n         *  \n         * @param {object} rowEntity the data entity for which the cell\n         * editing was cancelled\n         */        \n        cancelEditCell: function( rowEntity, colDef ){\n          var grid = this.grid;\n          var gridRow = grid.getRow( rowEntity );\n          if ( !gridRow ){ gridUtil.logError( 'Unable to find rowEntity in grid data, timer cannot be set' ); return; }\n          \n          service.considerSetTimer( grid, gridRow );\n        },\n        \n        \n        /**\n         * @ngdoc method\n         * @methodOf ui.grid.rowEdit.service:uiGridRowEditService\n         * @name navigate\n         * @description cellNav tells us that the selected cell has changed.  If\n         * the new row had a timer running, then stop it similar to in a beginCellEdit\n         * call.  If the old row is dirty and not the same as the new row, then \n         * start a timer on it.\n         * @param {object} newRowCol the row and column that were selected\n         * @param {object} oldRowCol the row and column that was left\n         * \n         */\n        navigate: function( newRowCol, oldRowCol ){\n          var grid = this.grid;\n          if ( newRowCol.row.rowEditSaveTimer ){\n            service.cancelTimer( grid, newRowCol.row );\n          }\n\n          if ( oldRowCol && oldRowCol.row && oldRowCol.row !== newRowCol.row ){\n            service.considerSetTimer( grid, oldRowCol.row );\n          }\n        },\n        \n        \n        /**\n         * @ngdoc property\n         * @propertyOf ui.grid.rowEdit.api:GridOptions\n         * @name rowEditWaitInterval\n         * @description How long the grid should wait for another change on this row\n         * before triggering a save (in milliseconds).  If set to -1, then saves are \n         * never triggered by timer (implying that the user will call flushDirtyRows() \n         * manually)\n         * \n         * @example\n         * Setting the wait interval to 4 seconds\n         * <pre>\n         *   $scope.gridOptions = { rowEditWaitInterval: 4000 }\n         * </pre>\n         * \n         */\n        /**\n         * @ngdoc method\n         * @methodOf ui.grid.rowEdit.service:uiGridRowEditService\n         * @name considerSetTimer\n         * @description Consider setting a timer on this row (if it is dirty).  if there is a timer running \n         * on the row and the row isn't currently saving, cancel it, using cancelTimer, then if the row is \n         * dirty and not currently saving then set a new timer\n         * @param {object} grid the grid for which we are processing\n         * @param {GridRow} gridRow the row for which the timer should be adjusted\n         * \n         */\n        considerSetTimer: function( grid, gridRow ){\n          service.cancelTimer( grid, gridRow );\n          \n          if ( gridRow.isDirty && !gridRow.isSaving ){\n            if ( grid.options.rowEditWaitInterval !== -1 ){\n              var waitTime = grid.options.rowEditWaitInterval ? grid.options.rowEditWaitInterval : 2000;\n              gridRow.rowEditSaveTimer = $interval( service.saveRow( grid, gridRow ), waitTime, 1);\n            }\n          }\n        },\n        \n\n        /**\n         * @ngdoc method\n         * @methodOf ui.grid.rowEdit.service:uiGridRowEditService\n         * @name cancelTimer\n         * @description cancel the $interval for any timer running on this row\n         * then delete the timer itself\n         * @param {object} grid the grid for which we are processing\n         * @param {GridRow} gridRow the row for which the timer should be adjusted\n         * \n         */\n        cancelTimer: function( grid, gridRow ){\n          if ( gridRow.rowEditSaveTimer && !gridRow.isSaving ){\n            $interval.cancel(gridRow.rowEditSaveTimer);\n            delete gridRow.rowEditSaveTimer;\n          }\n        },\n\n\n        /**\n         * @ngdoc method\n         * @methodOf ui.grid.rowEdit.service:uiGridRowEditService\n         * @name setRowsDirty\n         * @description Sets each of the rows passed in dataRows\n         * to be dirty.  note that if you have only just inserted the\n         * rows into your data you will need to wait for a $digest cycle\n         * before the gridRows are present - so often you would wrap this\n         * call in a $interval or $timeout\n         * <pre>\n         *      $interval( function() {\n         *        gridApi.rowEdit.setRowsDirty( myDataRows);\n         *      }, 0, 1);\n         * </pre>\n         * @param {object} grid the grid for which rows should be set dirty\n         * @param {array} dataRows the data entities for which the gridRows\n         * should be set dirty.  \n         * \n         */\n        setRowsDirty: function( grid, myDataRows ) {\n          var gridRow;\n          myDataRows.forEach( function( value, index ){\n            gridRow = grid.getRow( value );\n            if ( gridRow ){\n              if ( !grid.rowEdit.dirtyRows ){\n                grid.rowEdit.dirtyRows = [];\n              }\n              \n              if ( !gridRow.isDirty ){\n                gridRow.isDirty = true;\n                grid.rowEdit.dirtyRows.push( gridRow );\n              }\n              \n              delete gridRow.isError;\n              \n              service.considerSetTimer( grid, gridRow );\n            } else {\n              gridUtil.logError( \"requested row not found in rowEdit.setRowsDirty, row was: \" + value );\n            }\n          });\n        }\n        \n        \n      };\n\n      return service;\n\n    }]);\n\n  /**\n   *  @ngdoc directive\n   *  @name ui.grid.rowEdit.directive:uiGridEdit\n   *  @element div\n   *  @restrict A\n   *\n   *  @description Adds row editing features to the ui-grid-edit directive.\n   *\n   */\n  module.directive('uiGridRowEdit', ['gridUtil', 'uiGridRowEditService', 'uiGridEditConstants', \n  function (gridUtil, uiGridRowEditService, uiGridEditConstants) {\n    return {\n      replace: true,\n      priority: 0,\n      require: '^uiGrid',\n      scope: false,\n      compile: function () {\n        return {\n          pre: function ($scope, $elm, $attrs, uiGridCtrl) {\n            uiGridRowEditService.initializeGrid($scope, uiGridCtrl.grid);\n          },\n          post: function ($scope, $elm, $attrs, uiGridCtrl) {            \n          }\n        };\n      }\n    };\n  }]);\n\n\n  /**\n   *  @ngdoc directive\n   *  @name ui.grid.rowEdit.directive:uiGridViewport\n   *  @element div\n   *\n   *  @description Stacks on top of ui.grid.uiGridViewport to alter the attributes used\n   *  for the grid row to allow coloring of saving and error rows\n   */\n  module.directive('uiGridViewport',\n    ['$compile', 'uiGridConstants', 'gridUtil', '$parse',\n      function ($compile, uiGridConstants, gridUtil, $parse) {\n        return {\n          priority: -200, // run after default  directive\n          scope: false,\n          compile: function ($elm, $attrs) {\n            var rowRepeatDiv = angular.element($elm.children().children()[0]);\n            \n            var existingNgClass = rowRepeatDiv.attr(\"ng-class\");\n            var newNgClass = '';\n            if ( existingNgClass ) {\n              newNgClass = existingNgClass.slice(0, -1) + \", 'ui-grid-row-dirty': row.isDirty, 'ui-grid-row-saving': row.isSaving, 'ui-grid-row-error': row.isError}\";\n            } else {\n              newNgClass = \"{'ui-grid-row-dirty': row.isDirty, 'ui-grid-row-saving': row.isSaving, 'ui-grid-row-error': row.isError}\";\n            }\n            rowRepeatDiv.attr(\"ng-class\", newNgClass);\n\n            return {\n              pre: function ($scope, $elm, $attrs, controllers) {\n\n              },\n              post: function ($scope, $elm, $attrs, controllers) {\n              }\n            };\n          }\n        };\n      }]);\n\n})();\n\n(function () {\n  'use strict';\n\n  /**\n   * @ngdoc overview\n   * @name ui.grid.saveState\n   * @description\n   *\n   *  # ui.grid.saveState\n   * This module provides the ability to save the grid state, and restore\n   * it when the user returns to the page.  \n   * \n   * No UI is provided, the caller should provide their own UI/buttons \n   * as appropriate. Usually the navigate events would be used to save\n   * the grid state and restore it.\n   * \n   * <br/>\n   * <br/>\n   *\n   * <div doc-module-components=\"ui.grid.save-state\"></div>\n   */\n\n  var module = angular.module('ui.grid.saveState', ['ui.grid', 'ui.grid.selection', 'ui.grid.cellNav']);\n\n  /**\n   *  @ngdoc object\n   *  @name ui.grid.saveState.constant:uiGridSaveStateConstants\n   *\n   *  @description constants available in save state module\n   */\n\n  module.constant('uiGridSaveStateConstants', {\n    featureName: 'saveState'\n  });\n\n  /**\n   *  @ngdoc service\n   *  @name ui.grid.saveState.service:uiGridSaveStateService\n   *\n   *  @description Services for saveState feature\n   */\n  module.service('uiGridSaveStateService', ['$q', 'uiGridSaveStateConstants', 'gridUtil', '$compile', '$interval', 'uiGridConstants',\n    function ($q, uiGridSaveStateConstants, gridUtil, $compile, $interval, uiGridConstants ) {\n\n      var service = {\n\n        initializeGrid: function (grid) {\n\n          //add feature namespace and any properties to grid for needed state\n          grid.saveState = {};\n          this.defaultGridOptions(grid.options);\n\n          /**\n           *  @ngdoc object\n           *  @name ui.grid.saveState.api:PublicApi\n           *\n           *  @description Public Api for saveState feature\n           */\n          var publicApi = {\n            events: {\n              saveState: {\n              }\n            },\n            methods: {\n              saveState: {\n                /**\n                 * @ngdoc function\n                 * @name save\n                 * @methodOf  ui.grid.saveState.api:PublicApi\n                 * @description Packages the current state of the grid into \n                 * an object, and provides it to the user for saving\n                 * @returns {object} the state as a javascript object that can be saved\n                 */\n                save: function () {\n                  return service.save(grid);\n                },\n                /**\n                 * @ngdoc function\n                 * @name restore\n                 * @methodOf  ui.grid.saveState.api:PublicApi\n                 * @description Restores the provided state into the grid\n                 * @param {scope} $scope a scope that we can broadcast on\n                 * @param {object} state the state that should be restored into the grid\n                 */\n                restore: function ( $scope, state) {\n                  service.restore(grid, $scope, state);\n                }\n              }\n            }\n          };\n\n          grid.api.registerEventsFromObject(publicApi.events);\n\n          grid.api.registerMethodsFromObject(publicApi.methods);\n          \n        },\n\n        defaultGridOptions: function (gridOptions) {\n          //default option to true unless it was explicitly set to false\n          /**\n           * @ngdoc object\n           * @name ui.grid.saveState.api:GridOptions\n           *\n           * @description GridOptions for saveState feature, these are available to be  \n           * set using the ui-grid {@link ui.grid.class:GridOptions gridOptions}\n           */\n          /**\n           * @ngdoc object\n           * @name saveWidths\n           * @propertyOf  ui.grid.saveState.api:GridOptions\n           * @description Save the current column widths.  Note that unless\n           * you've provided the user with some way to resize their columns (say\n           * the resize columns feature), then this makes little sense.\n           * <br/>Defaults to true\n           */\n          gridOptions.saveWidths = gridOptions.saveWidths !== false;\n          /**\n           * @ngdoc object\n           * @name saveOrder\n           * @propertyOf  ui.grid.saveState.api:GridOptions\n           * @description Save the current column order.  Note that unless\n           * you've provided the user with some way to reorder their columns (for\n           * example the move columns feature), this makes little sense.\n           * <br/>Defaults to true\n           */\n          gridOptions.saveOrder = gridOptions.saveOrder !== false;\n          /**\n           * @ngdoc object\n           * @name saveScroll\n           * @propertyOf  ui.grid.saveState.api:GridOptions\n           * @description Save the current scroll position.  Note that this\n           * is saved as the percentage of the grid scrolled - so if your\n           * user returns to a grid with a significantly different number of \n           * rows (perhaps some data has been deleted) then the scroll won't \n           * actually show the same rows as before.  If you want to scroll to\n           * a specific row then you should instead use the saveFocus option, which\n           * is the default.\n           * \n           * Note that this element will only be saved if the cellNav feature is\n           * enabled\n           * <br/>Defaults to false\n           */\n          gridOptions.saveScroll = gridOptions.saveScroll === true;\n          /**\n           * @ngdoc object\n           * @name saveFocus\n           * @propertyOf  ui.grid.saveState.api:GridOptions\n           * @description Save the current focused cell.  On returning\n           * to this focused cell we'll also scroll.  This option is\n           * preferred to the saveScroll option, so is set to true by\n           * default.  If saveScroll is set to true then this option will \n           * be disabled.  \n           * \n           * By default this option saves the current row number and column \n           * number, and returns to that row and column.  However, if you define\n           * a saveRowIdentity function, then it will return you to the currently \n           * selected column within that row (in a business sense - so if some\n           * rows have been deleted, it will still find the same data, presuming it \n           * still exists in the list.  If it isn't in the list then it will instead\n           * return to the same row number - i.e. scroll percentage)\n           * \n           * Note that this option will do nothing if the cellNav\n           * feature is not enabled.\n           * \n           * <br/>Defaults to true (unless saveScroll is true)\n           */\n          gridOptions.saveFocus = gridOptions.saveScroll !== true && gridOptions.saveFocus !== false;\n          /**\n           * @ngdoc object\n           * @name saveRowIdentity\n           * @propertyOf  ui.grid.saveState.api:GridOptions\n           * @description A function that can be called, passing in a rowEntity, \n           * and that will return a unique id for that row.  This might simply \n           * return the `id` field from that row (if you have one), or it might\n           * concatenate some fields within the row to make a unique value.\n           * \n           * This value will be used to find the same row again and set the focus \n           * to it, if it exists when we return.\n           * \n           * <br/>Defaults to undefined\n           */\n          /**\n           * @ngdoc object\n           * @name saveVisible\n           * @propertyOf  ui.grid.saveState.api:GridOptions\n           * @description Save whether or not columns are visible.\n           * \n           * <br/>Defaults to true\n           */\n          gridOptions.saveVisible = gridOptions.saveVisible !== false;          \n          /**\n           * @ngdoc object\n           * @name saveSort\n           * @propertyOf  ui.grid.saveState.api:GridOptions\n           * @description Save the current sort state for each column\n           * \n           * <br/>Defaults to true\n           */\n          gridOptions.saveSort = gridOptions.saveSort !== false;         \n          /**\n           * @ngdoc object\n           * @name saveFilter\n           * @propertyOf  ui.grid.saveState.api:GridOptions\n           * @description Save the current filter state for each column\n           * \n           * <br/>Defaults to true\n           */\n          gridOptions.saveFilter = gridOptions.saveFilter !== false;\n          /**\n           * @ngdoc object\n           * @name saveSelection\n           * @propertyOf  ui.grid.saveState.api:GridOptions\n           * @description Save the currently selected rows.  If the `saveRowIdentity` callback\n           * is defined, then it will save the id of the row and select that.  If not, then\n           * it will attempt to select the rows by row number, which will give the wrong results\n           * if the data set has changed in the mean-time.\n           * \n           * Note that this option only does anything\n           * if the selection feature is enabled.  \n           * \n           * <br/>Defaults to true\n           */\n          gridOptions.saveSelection = gridOptions.saveSelection !== false;          \n        },\n\n\n\n        /**\n         * @ngdoc function\n         * @name save\n         * @methodOf  ui.grid.saveState.service:uiGridSaveStateService\n         * @description Saves the current grid state into an object, and\n         * passes that object back to the caller\n         * @param {Grid} grid the grid whose state we'd like to save\n         * @returns {object} the state ready to be saved\n         */\n        save: function (grid) {\n          var savedState = {};\n          \n          savedState.columns = service.saveColumns( grid );\n          savedState.scrollFocus = service.saveScrollFocus( grid );\n          savedState.selection = service.saveSelection( grid );\n          \n          return savedState;\n        },\n        \n        \n        /**\n         * @ngdoc function\n         * @name restore\n         * @methodOf  ui.grid.saveState.service:uiGridSaveStateService\n         * @description Applies the provided state to the grid\n         * \n         * @param {Grid} grid the grid whose state we'd like to restore\n         * @param {scope} $scope a scope that we can broadcast on\n         * @param {object} state the state we'd like to restore\n         */\n        restore: function( grid, $scope, state ){\n          if ( state.columns ) {\n            service.restoreColumns( grid, state.columns );\n          }\n          \n          if ( state.scrollFocus ){\n            service.restoreScrollFocus( grid, $scope, state.scrollFocus );\n          }\n          \n          if ( state.selection ){\n            service.restoreSelection( grid, state.selection );\n          }\n          \n          grid.refresh();\n        },\n        \n        \n        /**\n         * @ngdoc function\n         * @name saveColumns\n         * @methodOf  ui.grid.saveState.service:uiGridSaveStateService\n         * @description Saves the column setup, including sort, filters, ordering\n         * and column widths.\n         * \n         * Works through the current columns, storing them in order.  Stores the\n         * column name, then the visible flag, width, sort and filters for each column.\n         *\n         * @param {Grid} grid the grid whose state we'd like to save\n         * @returns {array} the columns state ready to be saved\n         */\n        saveColumns: function( grid ) {\n          var columns = [];\n          angular.forEach( grid.columns, function( column ) {\n            var savedColumn = {};\n            savedColumn.name = column.name;\n            savedColumn.visible = column.visible;\n            savedColumn.width = column.width;\n            \n            // these two must be copied, not just pointed too - otherwise our saved state is pointing to the same object as current state\n            savedColumn.sort = angular.copy( column.sort );\n            savedColumn.filters = angular.copy ( column.filters );\n            columns.push( savedColumn );\n          });\n          \n          return columns;\n        },\n        \n\n        /**\n         * @ngdoc function\n         * @name saveScrollFocus\n         * @methodOf  ui.grid.saveState.service:uiGridSaveStateService\n         * @description Saves the currently scroll or focus.\n         * \n         * If cellNav isn't present then does nothing - we can't return\n         * to the scroll position without cellNav anyway.\n         * \n         * If the cellNav module is present, and saveFocus is true, then\n         * it saves the currently focused cell.  If rowIdentity is present\n         * then saves using rowIdentity, otherwise saves visibleRowNum.\n         * \n         * If the cellNav module is not present, and saveScroll is true, then\n         * it approximates the current scroll row and column, and saves that.\n         * \n         * @param {Grid} grid the grid whose state we'd like to save\n         * @returns {object} the selection state ready to be saved\n         */\n        saveScrollFocus: function( grid ){\n          if ( !grid.api.cellNav ){\n            return {};\n          }\n          \n          var scrollFocus = {};\n          if ( grid.options.saveFocus ){\n            scrollFocus.focus = true;\n            var rowCol = grid.api.cellNav.getFocusedCell();\n            if ( rowCol !== null ) {\n              scrollFocus.colName = rowCol.col.colDef.name;\n              scrollFocus.rowVal = service.getRowVal( grid, rowCol.row );\n            }\n          } else if ( grid.options.saveScroll ) {\n            scrollFocus.focus = false;\n            if ( grid.renderContainers.body.prevRowScrollIndex ){\n              scrollFocus.rowVal = service.getRowVal( grid, grid.renderContainers.body.visibleRowCache[ grid.renderContainers.body.prevRowScrollIndex ]);\n            }\n            \n            if ( grid.renderContainers.body.prevColScrollIndex ){\n              scrollFocus.colName = grid.renderContainers.body.visibleColumnCache[ grid.renderContainers.body.prevColScrollIndex ].name;\n            }\n          }        \n          \n          return scrollFocus;\n        },\n        \n\n        /**\n         * @ngdoc function\n         * @name saveSelection\n         * @methodOf  ui.grid.saveState.service:uiGridSaveStateService\n         * @description Saves the currently selected rows, if the selection feature is enabled\n         * @param {Grid} grid the grid whose state we'd like to save\n         * @returns {object} the selection state ready to be saved\n         */\n        saveSelection: function( grid ){\n          if ( !grid.api.selection ){\n            return {};\n          }\n          \n          var selection = grid.api.selection.getSelectedGridRows().map( function( gridRow ) {\n            return service.getRowVal( grid, gridRow );\n          });\n          \n          return selection;\n        },\n        \n        \n        /**\n         * @ngdoc function\n         * @name getRowVal\n         * @methodOf  ui.grid.saveState.service:uiGridSaveStateService\n         * @description Helper function that gets either the rowNum or\n         * the saveRowIdentity, given a gridRow \n         * @param {Grid} grid the grid the row is in\n         * @param {GridRow} gridRow the row we want the rowNum for\n         * @returns {object} an object containing { identity: true/false, row: rowNumber/rowIdentity }\n         * \n         */\n        getRowVal: function( grid, gridRow ){\n          if ( !gridRow ) {\n            return null;\n          }\n          \n          var rowVal = {};\n          if ( grid.options.saveRowIdentity ){\n            rowVal.identity = true;\n            rowVal.row = grid.options.saveRowIdentity( gridRow.entity );\n          } else {\n            rowVal.identity = false;\n            rowVal.row = grid.renderContainers.body.visibleRowCache.indexOf( gridRow );\n          }\n          return rowVal;\n        },\n        \n        \n        /**\n         * @ngdoc function\n         * @name restoreColumns\n         * @methodOf  ui.grid.saveState.service:uiGridSaveStateService\n         * @description Restores the columns, including order, visible, width\n         * sort and filters.\n         * \n         * @param {Grid} grid the grid whose state we'd like to restore\n         * @param {object} columnsState the list of columns we had before, with their state\n         */\n        restoreColumns: function( grid, columnsState ){\n          angular.forEach( columnsState, function( columnState, index ) {\n            var currentCol = grid.columns.filter( function( column ) {\n              return column.name === columnState.name;\n            });\n            \n            if ( currentCol.length > 0 ){\n              var currentIndex = grid.columns.indexOf( currentCol[0] );\n              \n              if ( grid.columns[currentIndex].visible !== columnState.visible ||\n                   grid.columns[currentIndex].colDef.visible !== columnState.visible ){\n                grid.columns[currentIndex].visible = columnState.visible;\n                grid.columns[currentIndex].colDef.visible = columnState.visible;\n                grid.api.core.raise.columnVisibilityChanged( grid.columns[currentIndex]);\n              }\n              \n              grid.columns[currentIndex].width = columnState.width;\n\n              if ( !angular.equals(grid.columns[currentIndex].sort, columnState.sort && \n                   !( grid.columns[currentIndex].sort === undefined && angular.isEmpty(columnState.sort) ) ) ){\n                grid.columns[currentIndex].sort = angular.copy( columnState.sort );\n                grid.api.core.raise.sortChanged();\n              }\n\n              if ( !angular.equals(grid.columns[currentIndex].filters, columnState.filters ) ){\n                grid.columns[currentIndex].filters = angular.copy( columnState.filters );\n                grid.api.core.raise.filterChanged();\n              }\n              \n              if ( currentIndex !== index ){\n                var column = grid.columns.splice( currentIndex, 1 )[0];\n                grid.columns.splice( index, 0, column );\n              }\n            }\n          });\n        },\n        \n\n        /**\n         * @ngdoc function\n         * @name restoreScrollFocus\n         * @methodOf  ui.grid.saveState.service:uiGridSaveStateService\n         * @description Scrolls to the position that was saved.  If focus is true, then\n         * sets focus to the specified row/col.  If focus is false, then scrolls to the \n         * specified row/col.\n         * \n         * @param {Grid} grid the grid whose state we'd like to restore\n         * @param {scope} $scope a scope that we can broadcast on\n         * @param {object} scrollFocusState the scroll/focus state ready to be restored\n         */\n        restoreScrollFocus: function( grid, $scope, scrollFocusState ){\n          if ( !grid.api.cellNav ){\n            return;\n          }\n          \n          var colDef, row;\n          if ( scrollFocusState.colName ){\n            var colDefs = grid.options.columnDefs.filter( function( colDef ) { return colDef.name === scrollFocusState.colName; });\n            if ( colDefs.length > 0 ){\n              colDef = colDefs[0];\n            }\n          }\n          \n          if ( scrollFocusState.rowVal && scrollFocusState.rowVal.row ){\n            if ( scrollFocusState.rowVal.identity ){\n              row = service.findRowByIdentity( grid, scrollFocusState.rowVal );\n            } else {\n              row = grid.renderContainers.body.visibleRowCache[ scrollFocusState.rowVal.row ];\n            }\n          }\n          \n          var entity = row && row.entity ? row.entity : null ;\n\n          if ( colDef || entity ) {          \n            if (scrollFocusState.focus ){\n              grid.api.cellNav.scrollToFocus( $scope, entity, colDef );\n            } else {\n              grid.api.cellNav.scrollTo( $scope, entity, colDef );\n            }\n          }\n        },\n        \n\n        /**\n         * @ngdoc function\n         * @name restoreSelection\n         * @methodOf  ui.grid.saveState.service:uiGridSaveStateService\n         * @description Selects the rows that are provided in the selection\n         * state.  If you are using `saveRowIdentity` and more than one row matches the identity\n         * function then only the first is selected.\n         * @param {Grid} grid the grid whose state we'd like to restore\n         * @param {object} selectionState the selection state ready to be restored\n         */\n        restoreSelection: function( grid, selectionState ){\n          if ( !grid.api.selection ){\n            return;\n          }\n          \n          grid.api.selection.clearSelectedRows();\n\n          angular.forEach( selectionState, function( rowVal ) {\n            if ( rowVal.identity ){\n              var foundRow = service.findRowByIdentity( grid, rowVal );\n              \n              if ( foundRow ){\n                grid.api.selection.selectRow( foundRow.entity );\n              }\n              \n            } else {\n              grid.api.selection.selectRowByVisibleIndex( rowVal.row );\n            }\n          });\n        },\n        \n        \n        /**\n         * @ngdoc function\n         * @name findRowByIdentity\n         * @methodOf  ui.grid.saveState.service:uiGridSaveStateService\n         * @description Finds a row given it's identity value, returns the first found row\n         * if any are found, otherwise returns null if no rows are found.\n         * @param {Grid} grid the grid whose state we'd like to restore\n         * @param {object} rowVal the row we'd like to find\n         * @returns {gridRow} the found row, or null if none found\n         */\n        findRowByIdentity: function( grid, rowVal ){\n          if ( !grid.options.saveRowIdentity ){\n            return null;\n          }\n          \n          var filteredRows = grid.rows.filter( function( gridRow ) {\n            if ( grid.options.saveRowIdentity( gridRow.entity ) === rowVal.row ){\n              return true;\n            } else {\n              return false;\n            }\n          });\n          \n          if ( filteredRows.length > 0 ){\n            return filteredRows[0];\n          } else {\n            return null;\n          }\n        }\n      };\n\n      return service;\n\n    }\n  ]);\n\n  /**\n   *  @ngdoc directive\n   *  @name ui.grid.saveState.directive:uiGridSaveState\n   *  @element div\n   *  @restrict A\n   *\n   *  @description Adds saveState features to grid\n   *\n   *  @example\n   <example module=\"app\">\n   <file name=\"app.js\">\n   var app = angular.module('app', ['ui.grid', 'ui.grid.saveState']);\n\n   app.controller('MainCtrl', ['$scope', function ($scope) {\n      $scope.data = [\n        { name: 'Bob', title: 'CEO' },\n        { name: 'Frank', title: 'Lowly Developer' }\n      ];\n\n      $scope.gridOptions = {\n        columnDefs: [\n          {name: 'name'},\n          {name: 'title', enableCellEdit: true}\n        ],\n        data: $scope.data\n      };\n    }]);\n   </file>\n   <file name=\"index.html\">\n   <div ng-controller=\"MainCtrl\">\n   <div ui-grid=\"gridOptions\" ui-grid-save-state></div>\n   </div>\n   </file>\n   </example>\n   */\n  module.directive('uiGridSaveState', ['uiGridSaveStateConstants', 'uiGridSaveStateService', 'gridUtil', '$compile',\n    function (uiGridSaveStateConstants, uiGridSaveStateService, gridUtil, $compile) {\n      return {\n        replace: true,\n        priority: 0,\n        require: '^uiGrid',\n        scope: false,\n        link: function ($scope, $elm, $attrs, uiGridCtrl) {\n          uiGridSaveStateService.initializeGrid(uiGridCtrl.grid);\n        }\n      };\n    }\n  ]);\n})();\n\n(function () {\n  'use strict';\n\n  /**\n   * @ngdoc overview\n   * @name ui.grid.selection\n   * @description\n   *\n   *  # ui.grid.selection\n   * This module provides row selection\n   * <br/>\n   * <br/>\n   *\n   * <div doc-module-components=\"ui.grid.selection\"></div>\n   */\n\n  var module = angular.module('ui.grid.selection', ['ui.grid']);\n\n  /**\n   *  @ngdoc object\n   *  @name ui.grid.selection.constant:uiGridSelectionConstants\n   *\n   *  @description constants available in selection module\n   */\n  module.constant('uiGridSelectionConstants', {\n    featureName: \"selection\",\n    selectionRowHeaderColName: 'selectionRowHeaderCol'\n  });\n\n  //add methods to GridRow\n  angular.module('ui.grid').config(['$provide', function($provide) {\n    $provide.decorator('GridRow', ['$delegate', function($delegate) {\n\n      /**\n       *  @ngdoc object\n       *  @name ui.grid.selection.api:GridRow\n       *\n       *  @description GridRow prototype functions added for selection\n       */\n\n      /**\n       *  @ngdoc object\n       *  @name enableSelection\n       *  @propertyOf  ui.grid.selection.api:GridRow\n       *  @description Enable row selection for this row, only settable by internal code.\n       *\n       *  The grouping feature, for example, might set group header rows to not be selectable.\n       *  <br/>Defaults to true\n       */\n\n      /**\n       *  @ngdoc object\n       *  @name isSelected\n       *  @propertyOf  ui.grid.selection.api:GridRow\n       *  @description Selected state of row.  Should be readonly. Make any changes to selected state using setSelected().\n       *  <br/>Defaults to false\n       */\n\n\n        /**\n         * @ngdoc function\n         * @name setSelected\n         * @methodOf ui.grid.selection.api:GridRow\n         * @description Sets the isSelected property and updates the selectedCount\n         * Changes to isSelected state should only be made via this function\n         * @param {bool} selelected value to set\n         */\n        $delegate.prototype.setSelected = function(selected) {\n          this.isSelected = selected;\n          if (selected) {\n            this.grid.selection.selectedCount++;\n          }\n          else {\n            this.grid.selection.selectedCount--;\n          }\n        };\n\n      return $delegate;\n    }]);\n  }]);\n\n  /**\n   *  @ngdoc service\n   *  @name ui.grid.selection.service:uiGridSelectionService\n   *\n   *  @description Services for selection features\n   */\n  module.service('uiGridSelectionService', ['$q', '$templateCache', 'uiGridSelectionConstants', 'gridUtil',\n    function ($q, $templateCache, uiGridSelectionConstants, gridUtil) {\n\n      var service = {\n\n        initializeGrid: function (grid) {\n\n          //add feature namespace and any properties to grid for needed\n          /**\n           *  @ngdoc object\n           *  @name ui.grid.selection.grid:selection\n           *\n           *  @description Grid properties and functions added for selection\n           */\n          grid.selection = {};\n          grid.selection.lastSelectedRow = null;\n          grid.selection.selectAll = false;\n\n\n          /**\n           *  @ngdoc object\n           *  @name selectedCount\n           *  @propertyOf  ui.grid.selection.grid:selection\n           *  @description Current count of selected rows\n           *  @example\n           *  var count = grid.selection.selectedCount\n           */\n          grid.selection.selectedCount = 0;\n\n          service.defaultGridOptions(grid.options);\n\n          /**\n           *  @ngdoc object\n           *  @name ui.grid.selection.api:PublicApi\n           *\n           *  @description Public Api for selection feature\n           */\n          var publicApi = {\n            events: {\n              selection: {\n                /**\n                 * @ngdoc event\n                 * @name rowSelectionChanged\n                 * @eventOf  ui.grid.selection.api:PublicApi\n                 * @description  is raised after the row.isSelected state is changed\n                 * @param {GridRow} row the row that was selected/deselected\n                 * @param {Event} event object if raised from an event\n                 */\n                rowSelectionChanged: function (scope, row, evt) {\n                },\n                /**\n                 * @ngdoc event\n                 * @name rowSelectionChangedBatch\n                 * @eventOf  ui.grid.selection.api:PublicApi\n                 * @description  is raised after the row.isSelected state is changed\n                 * in bulk, if the `enableSelectionBatchEvent` option is set to true\n                 * (which it is by default).  This allows more efficient processing\n                 * of bulk events.\n                 * @param {array} rows the rows that were selected/deselected\n                 * @param {Event} event object if raised from an event\n                 */\n                rowSelectionChangedBatch: function (scope, rows, evt) {\n                }\n              }\n            },\n            methods: {\n              selection: {\n                /**\n                 * @ngdoc function\n                 * @name toggleRowSelection\n                 * @methodOf  ui.grid.selection.api:PublicApi\n                 * @description Toggles data row as selected or unselected\n                 * @param {object} rowEntity gridOptions.data[] array instance\n                 * @param {Event} event object if raised from an event\n                 */\n                toggleRowSelection: function (rowEntity, evt) {\n                  var row = grid.getRow(rowEntity);\n                  if (row !== null && row.enableSelection !== false) {\n                    service.toggleRowSelection(grid, row, evt, grid.options.multiSelect, grid.options.noUnselect);\n                  }\n                },\n                /**\n                 * @ngdoc function\n                 * @name selectRow\n                 * @methodOf  ui.grid.selection.api:PublicApi\n                 * @description Select the data row\n                 * @param {object} rowEntity gridOptions.data[] array instance\n                 * @param {Event} event object if raised from an event\n                 */\n                selectRow: function (rowEntity, evt) {\n                  var row = grid.getRow(rowEntity);\n                  if (row !== null && !row.isSelected && row.enableSelection !== false) {\n                    service.toggleRowSelection(grid, row, evt, grid.options.multiSelect, grid.options.noUnselect);\n                  }\n                },\n                /**\n                 * @ngdoc function\n                 * @name selectRowByVisibleIndex\n                 * @methodOf  ui.grid.selection.api:PublicApi\n                 * @description Select the specified row by visible index (i.e. if you\n                 * specify row 0 you'll get the first visible row selected).  In this context\n                 * visible means of those rows that are theoretically visible (i.e. not filtered),\n                 * rather than rows currently rendered on the screen.\n                 * @param {number} index index within the rowsVisible array\n                 * @param {Event} event object if raised from an event\n                 */\n                selectRowByVisibleIndex: function ( rowNum, evt ) {\n                  var row = grid.renderContainers.body.visibleRowCache[rowNum];\n                  if (row !== null && typeof(row) !== 'undefined' && !row.isSelected && row.enableSelection !== false) {\n                    service.toggleRowSelection(grid, row, evt, grid.options.multiSelect, grid.options.noUnselect);\n                  }\n                },\n                /**\n                 * @ngdoc function\n                 * @name unSelectRow\n                 * @methodOf  ui.grid.selection.api:PublicApi\n                 * @description UnSelect the data row\n                 * @param {object} rowEntity gridOptions.data[] array instance\n                 * @param {Event} event object if raised from an event\n                 */\n                unSelectRow: function (rowEntity, evt) {\n                  var row = grid.getRow(rowEntity);\n                  if (row !== null && row.isSelected) {\n                    service.toggleRowSelection(grid, row, evt, grid.options.multiSelect, grid.options.noUnselect);\n                  }\n                },\n                /**\n                 * @ngdoc function\n                 * @name selectAllRows\n                 * @methodOf  ui.grid.selection.api:PublicApi\n                 * @description Selects all rows.  Does nothing if multiSelect = false\n                 * @param {Event} event object if raised from an event\n                 */\n                selectAllRows: function (evt) {\n                  if (grid.options.multiSelect === false) {\n                    return;\n                  }\n\n                  var changedRows = [];\n                  grid.rows.forEach(function (row) {\n                    if ( !row.isSelected && row.enableSelection !== false ){\n                      row.setSelected(true);\n                      service.decideRaiseSelectionEvent( grid, row, changedRows, evt );\n                    }\n                  });\n                  service.decideRaiseSelectionBatchEvent( grid, changedRows, evt );\n                  grid.selection.selectAll = true;\n                },\n                /**\n                 * @ngdoc function\n                 * @name selectAllVisibleRows\n                 * @methodOf  ui.grid.selection.api:PublicApi\n                 * @description Selects all visible rows.  Does nothing if multiSelect = false\n                 * @param {Event} event object if raised from an event\n                 */\n                selectAllVisibleRows: function (evt) {\n                  if (grid.options.multiSelect === false) {\n                    return;\n                  }\n\n                  var changedRows = [];\n                  grid.rows.forEach(function (row) {\n                    if (row.visible) {\n                      if (!row.isSelected && row.enableSelection !== false){\n                        row.setSelected(true);\n                        service.decideRaiseSelectionEvent( grid, row, changedRows, evt );\n                      }\n                    } else {\n                      if (row.isSelected){\n                        row.setSelected(false);\n                        service.decideRaiseSelectionEvent( grid, row, changedRows, evt );\n                      }\n                    }\n                  });\n                  service.decideRaiseSelectionBatchEvent( grid, changedRows, evt );\n                  grid.selection.selectAll = true;\n                },\n                /**\n                 * @ngdoc function\n                 * @name clearSelectedRows\n                 * @methodOf  ui.grid.selection.api:PublicApi\n                 * @description Unselects all rows\n                 * @param {Event} event object if raised from an event\n                 */\n                clearSelectedRows: function (evt) {\n                  service.clearSelectedRows(grid, evt);\n                },\n                /**\n                 * @ngdoc function\n                 * @name getSelectedRows\n                 * @methodOf  ui.grid.selection.api:PublicApi\n                 * @description returns all selectedRow's entity references\n                 */\n                getSelectedRows: function () {\n                  return service.getSelectedRows(grid).map(function (gridRow) {\n                    return gridRow.entity;\n                  });\n                },\n                /**\n                 * @ngdoc function\n                 * @name getSelectedGridRows\n                 * @methodOf  ui.grid.selection.api:PublicApi\n                 * @description returns all selectedRow's as gridRows\n                 */\n                getSelectedGridRows: function () {\n                  return service.getSelectedRows(grid);\n                },\n                /**\n                 * @ngdoc function\n                 * @name setMultiSelect\n                 * @methodOf  ui.grid.selection.api:PublicApi\n                 * @description Sets the current gridOption.multiSelect to true or false\n                 * @param {bool} multiSelect true to allow multiple rows\n                 */\n                setMultiSelect: function (multiSelect) {\n                  grid.options.multiSelect = multiSelect;\n                },\n                /**\n                 * @ngdoc function\n                 * @name setModifierKeysToMultiSelect\n                 * @methodOf  ui.grid.selection.api:PublicApi\n                 * @description Sets the current gridOption.modifierKeysToMultiSelect to true or false\n                 * @param {bool} modifierKeysToMultiSelect true to only allow multiple rows when using ctrlKey or shiftKey is used\n                 */\n                setModifierKeysToMultiSelect: function (modifierKeysToMultiSelect) {\n                  grid.options.modifierKeysToMultiSelect = modifierKeysToMultiSelect;\n                },\n                /**\n                 * @ngdoc function\n                 * @name getSelectAllState\n                 * @methodOf  ui.grid.selection.api:PublicApi\n                 * @description Returns whether or not the selectAll checkbox is currently ticked.  The\n                 * grid doesn't automatically select rows when you add extra data - so when you add data\n                 * you need to explicitly check whether the selectAll is set, and then call setVisible rows\n                 * if it is\n                 */\n                getSelectAllState: function () {\n                  return grid.selection.selectAll;\n                }\n\n              }\n            }\n          };\n\n          grid.api.registerEventsFromObject(publicApi.events);\n\n          grid.api.registerMethodsFromObject(publicApi.methods);\n\n        },\n\n        defaultGridOptions: function (gridOptions) {\n          //default option to true unless it was explicitly set to false\n          /**\n           *  @ngdoc object\n           *  @name ui.grid.selection.api:GridOptions\n           *\n           *  @description GridOptions for selection feature, these are available to be\n           *  set using the ui-grid {@link ui.grid.class:GridOptions gridOptions}\n           */\n\n          /**\n           *  @ngdoc object\n           *  @name enableRowSelection\n           *  @propertyOf  ui.grid.selection.api:GridOptions\n           *  @description Enable row selection for entire grid.\n           *  <br/>Defaults to true\n           */\n          gridOptions.enableRowSelection = gridOptions.enableRowSelection !== false;\n          /**\n           *  @ngdoc object\n           *  @name multiSelect\n           *  @propertyOf  ui.grid.selection.api:GridOptions\n           *  @description Enable multiple row selection for entire grid\n           *  <br/>Defaults to true\n           */\n          gridOptions.multiSelect = gridOptions.multiSelect !== false;\n          /**\n           *  @ngdoc object\n           *  @name noUnselect\n           *  @propertyOf  ui.grid.selection.api:GridOptions\n           *  @description Prevent a row from being unselected.  Works in conjunction\n           *  with `multiselect = false` and `gridApi.selection.selectRow()` to allow\n           *  you to create a single selection only grid - a row is always selected, you\n           *  can only select different rows, you can't unselect the row.\n           *  <br/>Defaults to false\n           */\n          gridOptions.noUnselect = gridOptions.noUnselect === true;\n          /**\n           *  @ngdoc object\n           *  @name modifierKeysToMultiSelect\n           *  @propertyOf  ui.grid.selection.api:GridOptions\n           *  @description Enable multiple row selection only when using the ctrlKey or shiftKey. Requires multiSelect to be true.\n           *  <br/>Defaults to false\n           */\n          gridOptions.modifierKeysToMultiSelect = gridOptions.modifierKeysToMultiSelect === true;\n          /**\n           *  @ngdoc object\n           *  @name enableRowHeaderSelection\n           *  @propertyOf  ui.grid.selection.api:GridOptions\n           *  @description Enable a row header to be used for selection\n           *  <br/>Defaults to true\n           */\n          gridOptions.enableRowHeaderSelection = gridOptions.enableRowHeaderSelection !== false;\n          /**\n           *  @ngdoc object\n           *  @name enableSelectAll\n           *  @propertyOf  ui.grid.selection.api:GridOptions\n           *  @description Enable the select all checkbox at the top of the selectionRowHeader\n           *  <br/>Defaults to true\n           */\n          gridOptions.enableSelectAll = gridOptions.enableSelectAll !== false;\n          /**\n           *  @ngdoc object\n           *  @name enableSelectionBatchEvent\n           *  @propertyOf  ui.grid.selection.api:GridOptions\n           *  @description If selected rows are changed in bulk, either via the API or\n           *  via the selectAll checkbox, then a separate event is fired.  Setting this\n           *  option to false will cause the rowSelectionChanged event to be called multiple times\n           *  instead\n           *  <br/>Defaults to true\n           */\n          gridOptions.enableSelectionBatchEvent = gridOptions.enableSelectionBatchEvent !== false;\n          /**\n           *  @ngdoc object\n           *  @name selectionRowHeaderWidth\n           *  @propertyOf  ui.grid.selection.api:GridOptions\n           *  @description can be used to set a custom width for the row header selection column\n           *  <br/>Defaults to 30px\n           */\n          gridOptions.selectionRowHeaderWidth = angular.isDefined(gridOptions.selectionRowHeaderWidth) ? gridOptions.selectionRowHeaderWidth : 30;\n\n          /**\n           *  @ngdoc object\n           *  @name enableFooterTotalSelected\n           *  @propertyOf  ui.grid.selection.api:GridOptions\n           *  @description Shows the total number of selected items in footer if true.\n           *  <br/>Defaults to true.\n           *  <br/>GridOptions.showFooter must also be set to true.\n           */\n          gridOptions.enableFooterTotalSelected = gridOptions.enableFooterTotalSelected !== false;\n\n          /**\n           *  @ngdoc object\n           *  @name isRowSelectable\n           *  @propertyOf  ui.grid.selection.api:GridOptions\n           *  @description Makes it possible to specify a method that evaluates for each and sets its \"enableSelection\" property.\n           */\n\n          gridOptions.isRowSelectable = angular.isDefined(gridOptions.isRowSelectable) ? gridOptions.isRowSelectable : angular.noop;\n        },\n\n        /**\n         * @ngdoc function\n         * @name toggleRowSelection\n         * @methodOf  ui.grid.selection.service:uiGridSelectionService\n         * @description Toggles row as selected or unselected\n         * @param {Grid} grid grid object\n         * @param {GridRow} row row to select or deselect\n         * @param {Event} event object if resulting from event\n         * @param {bool} multiSelect if false, only one row at time can be selected\n         * @param {bool} noUnselect if true then rows cannot be unselected\n         */\n        toggleRowSelection: function (grid, row, evt, multiSelect, noUnselect) {\n          var selected = row.isSelected;\n\n          if (!multiSelect && !selected) {\n            service.clearSelectedRows(grid, evt);\n          } else if (!multiSelect && selected) {\n            var selectedRows = service.getSelectedRows(grid);\n            if (selectedRows.length > 1) {\n              selected = false; // Enable reselect of the row\n              service.clearSelectedRows(grid, evt);\n            }\n          }\n\n          if (selected && noUnselect){\n            // don't deselect the row \n          } else if (row.enableSelection !== false) {\n            row.setSelected(!selected);\n            if (row.isSelected === true) {\n              grid.selection.lastSelectedRow = row;\n            } else {\n              grid.selection.selectAll = false;\n            }\n            grid.api.selection.raise.rowSelectionChanged(row, evt);\n          }\n        },\n        /**\n         * @ngdoc function\n         * @name shiftSelect\n         * @methodOf  ui.grid.selection.service:uiGridSelectionService\n         * @description selects a group of rows from the last selected row using the shift key\n         * @param {Grid} grid grid object\n         * @param {GridRow} clicked row\n         * @param {Event} event object if raised from an event\n         * @param {bool} multiSelect if false, does nothing this is for multiSelect only\n         */\n        shiftSelect: function (grid, row, evt, multiSelect) {\n          if (!multiSelect) {\n            return;\n          }\n          var selectedRows = service.getSelectedRows(grid);\n          var fromRow = selectedRows.length > 0 ? grid.renderContainers.body.visibleRowCache.indexOf(grid.selection.lastSelectedRow) : 0;\n          var toRow = grid.renderContainers.body.visibleRowCache.indexOf(row);\n          //reverse select direction\n          if (fromRow > toRow) {\n            var tmp = fromRow;\n            fromRow = toRow;\n            toRow = tmp;\n          }\n\n          var changedRows = [];\n          for (var i = fromRow; i <= toRow; i++) {\n            var rowToSelect = grid.renderContainers.body.visibleRowCache[i];\n            if (rowToSelect) {\n              if ( !rowToSelect.isSelected && rowToSelect.enableSelection !== false ){\n                rowToSelect.setSelected(true);\n                grid.selection.lastSelectedRow = rowToSelect;\n                service.decideRaiseSelectionEvent( grid, rowToSelect, changedRows, evt );\n              }\n            }\n          }\n          service.decideRaiseSelectionBatchEvent( grid, changedRows, evt );\n        },\n        /**\n         * @ngdoc function\n         * @name getSelectedRows\n         * @methodOf  ui.grid.selection.service:uiGridSelectionService\n         * @description Returns all the selected rows\n         * @param {Grid} grid grid object\n         */\n        getSelectedRows: function (grid) {\n          return grid.rows.filter(function (row) {\n            return row.isSelected;\n          });\n        },\n\n        /**\n         * @ngdoc function\n         * @name clearSelectedRows\n         * @methodOf  ui.grid.selection.service:uiGridSelectionService\n         * @description Clears all selected rows\n         * @param {Grid} grid grid object\n         * @param {Event} event object if raised from an event\n         */\n        clearSelectedRows: function (grid, evt) {\n          var changedRows = [];\n          service.getSelectedRows(grid).forEach(function (row) {\n            if ( row.isSelected ){\n              row.setSelected(false);\n              service.decideRaiseSelectionEvent( grid, row, changedRows, evt );\n            }\n          });\n          service.decideRaiseSelectionBatchEvent( grid, changedRows, evt );\n          grid.selection.selectAll = false;\n        },\n\n        /**\n         * @ngdoc function\n         * @name decideRaiseSelectionEvent\n         * @methodOf  ui.grid.selection.service:uiGridSelectionService\n         * @description Decides whether to raise a single event or a batch event\n         * @param {Grid} grid grid object\n         * @param {GridRow} row row that has changed\n         * @param {array} changedRows an array to which we can append the changed\n         * @param {Event} event object if raised from an event\n         * row if we're doing batch events\n         */\n        decideRaiseSelectionEvent: function( grid, row, changedRows, evt ){\n          if ( !grid.options.enableSelectionBatchEvent ){\n            grid.api.selection.raise.rowSelectionChanged(row, evt);\n          } else {\n            changedRows.push(row);\n          }\n        },\n\n        /**\n         * @ngdoc function\n         * @name raiseSelectionEvent\n         * @methodOf  ui.grid.selection.service:uiGridSelectionService\n         * @description Decides whether we need to raise a batch event, and\n         * raises it if we do.\n         * @param {Grid} grid grid object\n         * @param {array} changedRows an array of changed rows, only populated\n         * @param {Event} event object if raised from an event\n         * if we're doing batch events\n         */\n        decideRaiseSelectionBatchEvent: function( grid, changedRows, evt ){\n          if ( changedRows.length > 0 ){\n            grid.api.selection.raise.rowSelectionChangedBatch(changedRows, evt);\n          }\n        }\n      };\n\n      return service;\n\n    }]);\n\n  /**\n   *  @ngdoc directive\n   *  @name ui.grid.selection.directive:uiGridSelection\n   *  @element div\n   *  @restrict A\n   *\n   *  @description Adds selection features to grid\n   *\n   *  @example\n   <example module=\"app\">\n   <file name=\"app.js\">\n   var app = angular.module('app', ['ui.grid', 'ui.grid.selection']);\n\n   app.controller('MainCtrl', ['$scope', function ($scope) {\n      $scope.data = [\n        { name: 'Bob', title: 'CEO' },\n            { name: 'Frank', title: 'Lowly Developer' }\n      ];\n\n      $scope.columnDefs = [\n        {name: 'name', enableCellEdit: true},\n        {name: 'title', enableCellEdit: true}\n      ];\n    }]);\n   </file>\n   <file name=\"index.html\">\n   <div ng-controller=\"MainCtrl\">\n   <div ui-grid=\"{ data: data, columnDefs: columnDefs }\" ui-grid-selection></div>\n   </div>\n   </file>\n   </example>\n   */\n  module.directive('uiGridSelection', ['uiGridSelectionConstants', 'uiGridSelectionService', '$templateCache',\n    function (uiGridSelectionConstants, uiGridSelectionService, $templateCache) {\n      return {\n        replace: true,\n        priority: 0,\n        require: '^uiGrid',\n        scope: false,\n        compile: function () {\n          return {\n            pre: function ($scope, $elm, $attrs, uiGridCtrl) {\n              uiGridSelectionService.initializeGrid(uiGridCtrl.grid);\n              if (uiGridCtrl.grid.options.enableRowHeaderSelection) {\n                var selectionRowHeaderDef = {\n                  name: uiGridSelectionConstants.selectionRowHeaderColName,\n                  displayName: '',\n                  width:  uiGridCtrl.grid.options.selectionRowHeaderWidth,\n                  minWidth: 10,\n                  cellTemplate: 'ui-grid/selectionRowHeader',\n                  headerCellTemplate: 'ui-grid/selectionHeaderCell',\n                  enableColumnResizing: false,\n                  enableColumnMenu: false,\n                  exporterSuppressExport: true \n                };\n\n                uiGridCtrl.grid.addRowHeaderColumn(selectionRowHeaderDef);\n              }\n              \n              if (uiGridCtrl.grid.options.isRowSelectable !== angular.noop) {\n                uiGridCtrl.grid.registerRowBuilder(function(row, options) {\n                  row.enableSelection = uiGridCtrl.grid.options.isRowSelectable(row);\n                });\n              }\n            },\n            post: function ($scope, $elm, $attrs, uiGridCtrl) {\n\n            }\n          };\n        }\n      };\n    }]);\n\n  module.directive('uiGridSelectionRowHeaderButtons', ['$templateCache', 'uiGridSelectionService',\n    function ($templateCache, uiGridSelectionService) {\n      return {\n        replace: true,\n        restrict: 'E',\n        template: $templateCache.get('ui-grid/selectionRowHeaderButtons'),\n        scope: true,\n        require: '^uiGrid',\n        link: function($scope, $elm, $attrs, uiGridCtrl) {\n          var self = uiGridCtrl.grid;\n          $scope.selectButtonClick = function(row, evt) {\n            if (evt.shiftKey) {\n              uiGridSelectionService.shiftSelect(self, row, evt, self.options.multiSelect);\n            }\n            else if (evt.ctrlKey || evt.metaKey) {\n              uiGridSelectionService.toggleRowSelection(self, row, evt, self.options.multiSelect, self.options.noUnselect);\n            }\n            else {\n              uiGridSelectionService.toggleRowSelection(self, row, evt, (self.options.multiSelect && !self.options.modifierKeysToMultiSelect), self.options.noUnselect);\n            }\n          };\n        }\n      };\n    }]);\n\n  module.directive('uiGridSelectionSelectAllButtons', ['$templateCache', 'uiGridSelectionService',\n    function ($templateCache, uiGridSelectionService) {\n      return {\n        replace: true,\n        restrict: 'E',\n        template: $templateCache.get('ui-grid/selectionSelectAllButtons'),\n        scope: false,\n        link: function($scope, $elm, $attrs, uiGridCtrl) {\n          var self = $scope.col.grid;\n\n          $scope.headerButtonClick = function(row, evt) {\n            if ( self.selection.selectAll ){\n              uiGridSelectionService.clearSelectedRows(self, evt);\n              if ( self.options.noUnselect ){\n                self.api.selection.selectRowByVisibleIndex(0, evt);\n              }\n              self.selection.selectAll = false;\n            } else {\n              if ( self.options.multiSelect ){\n                self.api.selection.selectAllVisibleRows(evt);\n                self.selection.selectAll = true;\n              }\n            }\n          };\n        }\n      };\n    }]);\n\n  /**\n   *  @ngdoc directive\n   *  @name ui.grid.selection.directive:uiGridViewport\n   *  @element div\n   *\n   *  @description Stacks on top of ui.grid.uiGridViewport to alter the attributes used\n   *  for the grid row\n   */\n  module.directive('uiGridViewport',\n    ['$compile', 'uiGridConstants', 'uiGridSelectionConstants', 'gridUtil', '$parse', 'uiGridSelectionService',\n      function ($compile, uiGridConstants, uiGridSelectionConstants, gridUtil, $parse, uiGridSelectionService) {\n        return {\n          priority: -200, // run after default  directive\n          scope: false,\n          compile: function ($elm, $attrs) {\n            var rowRepeatDiv = angular.element($elm.children().children()[0]);\n\n            var existingNgClass = rowRepeatDiv.attr(\"ng-class\");\n            var newNgClass = '';\n            if ( existingNgClass ) {\n              newNgClass = existingNgClass.slice(0, -1) + \",'ui-grid-row-selected': row.isSelected}\";\n            } else {\n              newNgClass = \"{'ui-grid-row-selected': row.isSelected}\";\n            }\n            rowRepeatDiv.attr(\"ng-class\", newNgClass);\n\n            return {\n              pre: function ($scope, $elm, $attrs, controllers) {\n\n              },\n              post: function ($scope, $elm, $attrs, controllers) {\n              }\n            };\n          }\n        };\n      }]);\n\n  /**\n   *  @ngdoc directive\n   *  @name ui.grid.selection.directive:uiGridCell\n   *  @element div\n   *  @restrict A\n   *\n   *  @description Stacks on top of ui.grid.uiGridCell to provide selection feature\n   */\n  module.directive('uiGridCell',\n    ['$compile', 'uiGridConstants', 'uiGridSelectionConstants', 'gridUtil', '$parse', 'uiGridSelectionService',\n      function ($compile, uiGridConstants, uiGridSelectionConstants, gridUtil, $parse, uiGridSelectionService) {\n        return {\n          priority: -200, // run after default uiGridCell directive\n          restrict: 'A',\n          scope: false,\n          link: function ($scope, $elm, $attrs) {\n\n            var touchStartTime = 0;\n            var touchTimeout = 300;\n            var selectCells = function(evt){\n              if (evt.shiftKey) {\n                uiGridSelectionService.shiftSelect($scope.grid, $scope.row, evt, $scope.grid.options.multiSelect);\n              }\n              else if (evt.ctrlKey || evt.metaKey) {\n                uiGridSelectionService.toggleRowSelection($scope.grid, $scope.row, evt, $scope.grid.options.multiSelect, $scope.grid.options.noUnselect);\n              }\n              else {\n                uiGridSelectionService.toggleRowSelection($scope.grid, $scope.row, evt, ($scope.grid.options.multiSelect && !$scope.grid.options.modifierKeysToMultiSelect), $scope.grid.options.noUnselect);\n              }\n              $scope.$apply();\n            };\n\n            var touchStart = function(evt){\n              touchStartTime = (new Date()).getTime();\n            };\n\n            var touchEnd = function(evt) {\n              var touchEndTime = (new Date()).getTime();\n              var touchTime = touchEndTime - touchStartTime;\n\n              if (touchTime < touchTimeout ) {\n                // short touch\n                selectCells(evt);\n              }\n            };\n\n            function registerRowSelectionEvents() {\n              if ($scope.grid.options.enableRowSelection && !$scope.grid.options.enableRowHeaderSelection) {\n                $elm.addClass('ui-grid-disable-selection');\n                $elm.on('touchstart', touchStart);\n                $elm.on('touchend', touchEnd);\n                $elm.on('click', selectCells);\n\n                $scope.registered = true;\n              }\n            }\n\n            function deregisterRowSelectionEvents() {\n              if ($scope.registered){\n                $elm.removeClass('ui-grid-disable-selection');\n\n                $elm.off('touchstart', touchStart);\n                $elm.off('touchend', touchEnd);\n                $elm.off('click', selectCells);\n\n                $scope.registered = false;\n              }\n            }\n\n            registerRowSelectionEvents();\n            // register a dataChange callback so that we can change the selection configuration dynamically\n            // if the user changes the options\n            var dataChangeDereg = $scope.grid.registerDataChangeCallback( function() {\n              if ( $scope.grid.options.enableRowSelection && !$scope.grid.options.enableRowHeaderSelection &&\n                !$scope.registered ){\n                registerRowSelectionEvents();\n              } else if ( ( !$scope.grid.options.enableRowSelection || $scope.grid.options.enableRowHeaderSelection ) &&\n                $scope.registered ){\n                deregisterRowSelectionEvents();\n              }\n            }, [uiGridConstants.dataChange.OPTIONS] );\n\n            $elm.on( '$destroy', dataChangeDereg);\n          }\n        };\n      }]);\n\n  module.directive('uiGridGridFooter', ['$compile', 'uiGridConstants', 'gridUtil', function ($compile, uiGridConstants, gridUtil) {\n    return {\n      restrict: 'EA',\n      replace: true,\n      priority: -1000,\n      require: '^uiGrid',\n      scope: true,\n      compile: function ($elm, $attrs) {\n        return {\n          pre: function ($scope, $elm, $attrs, uiGridCtrl) {\n\n            if (!uiGridCtrl.grid.options.showGridFooter) {\n              return;\n            }\n\n\n            gridUtil.getTemplate('ui-grid/gridFooterSelectedItems')\n              .then(function (contents) {\n                var template = angular.element(contents);\n\n                var newElm = $compile(template)($scope);\n\n                angular.element($elm[0].getElementsByClassName('ui-grid-grid-footer')[0]).append(newElm);\n              });\n          },\n\n          post: function ($scope, $elm, $attrs, controllers) {\n\n          }\n        };\n      }\n    };\n  }]);\n\n})();\n\nangular.module('ui.grid').run(['$templateCache', function($templateCache) {\n  'use strict';\n\n  $templateCache.put('ui-grid/ui-grid-footer',\n    \"<div class=\\\"ui-grid-footer-panel ui-grid-footer-aggregates-row\\\"><div class=\\\"ui-grid-footer ui-grid-footer-viewport\\\"><div class=\\\"ui-grid-footer-canvas\\\"><div ng-repeat=\\\"col in colContainer.renderedColumns track by col.colDef.name\\\" ui-grid-footer-cell col=\\\"col\\\" render-index=\\\"$index\\\" class=\\\"ui-grid-footer-cell ui-grid-clearfix\\\" ng-style=\\\"$index === 0 && colContainer.columnStyle($index)\\\"></div></div></div></div>\"\n  );\n\n\n  $templateCache.put('ui-grid/ui-grid-grid-footer',\n    \"<div class=\\\"ui-grid-footer-info ui-grid-grid-footer\\\"><span>{{'search.totalItems' | t}} {{grid.rows.length}}</span> <span ng-if=\\\"grid.renderContainers.body.visibleRowCache.length !== grid.rows.length\\\" class=\\\"ngLabel\\\">({{\\\"search.showingItems\\\" | t}} {{grid.renderContainers.body.visibleRowCache.length}})</span></div>\"\n  );\n\n\n  $templateCache.put('ui-grid/ui-grid-group-panel',\n    \"<div class=\\\"ui-grid-group-panel\\\"><div ui-t=\\\"groupPanel.description\\\" class=\\\"description\\\" ng-show=\\\"groupings.length == 0\\\"></div><ul ng-show=\\\"groupings.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>\"\n  );\n\n\n  $templateCache.put('ui-grid/ui-grid-header',\n    \"<div class=\\\"ui-grid-header\\\"><div class=\\\"ui-grid-top-panel\\\"><div class=\\\"ui-grid-header-viewport\\\"><div class=\\\"ui-grid-header-canvas\\\"><div class=\\\"ui-grid-header-cell ui-grid-clearfix\\\" ng-repeat=\\\"col in colContainer.renderedColumns track by col.colDef.name\\\" ui-grid-header-cell col=\\\"col\\\" render-index=\\\"$index\\\" ng-style=\\\"$index === 0 && colContainer.columnStyle($index)\\\"></div></div></div><div ui-grid-menu></div></div></div>\"\n  );\n\n\n  $templateCache.put('ui-grid/ui-grid-menu-button',\n    \"<div class=\\\"ui-grid-menu-button\\\" ng-click=\\\"toggleMenu()\\\"><div class=\\\"ui-grid-icon-container\\\"><i class=\\\"ui-grid-icon-menu\\\">&nbsp;</i></div><div ui-grid-menu menu-items=\\\"menuItems\\\"></div></div>\"\n  );\n\n\n  $templateCache.put('ui-grid/ui-grid-no-header',\n    \"<div class=\\\"ui-grid-top-panel\\\"></div>\"\n  );\n\n\n  $templateCache.put('ui-grid/ui-grid-row',\n    \"<div ng-repeat=\\\"(colRenderIndex, col) in colContainer.renderedColumns track by col.colDef.name\\\" class=\\\"ui-grid-cell\\\" ng-class=\\\"{ 'ui-grid-row-header-cell': col.isRowHeader }\\\" ui-grid-cell></div>\"\n  );\n\n\n  $templateCache.put('ui-grid/ui-grid',\n    \"<div ui-i18n=\\\"en\\\" class=\\\"ui-grid\\\"><!-- TODO (c0bra): add \\\"scoped\\\" attr here, eventually? --><style ui-grid-style>.grid{{ grid.id }} {\\n\" +\n    \"      /* Styles for the grid */\\n\" +\n    \"    }\\n\" +\n    \"\\n\" +\n    \"    .grid{{ grid.id }} .ui-grid-row, .grid{{ grid.id }} .ui-grid-cell, .grid{{ grid.id }} .ui-grid-cell .ui-grid-vertical-bar {\\n\" +\n    \"      height: {{ grid.options.rowHeight }}px;\\n\" +\n    \"    }\\n\" +\n    \"\\n\" +\n    \"    .grid{{ grid.id }} .ui-grid-row:last-child .ui-grid-cell {\\n\" +\n    \"      border-bottom-width: {{ ((grid.getTotalRowHeight() < grid.getViewportHeight()) && '1') || '0' }}px;\\n\" +\n    \"    }\\n\" +\n    \"\\n\" +\n    \"    {{ grid.verticalScrollbarStyles }}\\n\" +\n    \"    {{ grid.horizontalScrollbarStyles }}\\n\" +\n    \"\\n\" +\n    \"    /*\\n\" +\n    \"    .ui-grid[dir=rtl] .ui-grid-viewport {\\n\" +\n    \"      padding-left: {{ grid.verticalScrollbarWidth }}px;\\n\" +\n    \"    }\\n\" +\n    \"    */\\n\" +\n    \"\\n\" +\n    \"    {{ grid.customStyles }}</style><div ui-grid-menu-button ng-if=\\\"grid.options.enableGridMenu\\\"></div><div ng-if=\\\"grid.hasLeftContainer()\\\" style=\\\"width: 0\\\" ui-grid-pinned-container=\\\"'left'\\\"></div><div ui-grid-render-container container-id=\\\"'body'\\\" col-container-name=\\\"'body'\\\" row-container-name=\\\"'body'\\\" bind-scroll-horizontal=\\\"true\\\" bind-scroll-vertical=\\\"true\\\" enable-horizontal-scrollbar=\\\"grid.options.enableHorizontalScrollbar\\\" enable-vertical-scrollbar=\\\"grid.options.enableVerticalScrollbar\\\"></div><div ng-if=\\\"grid.hasRightContainer()\\\" style=\\\"width: 0\\\" ui-grid-pinned-container=\\\"'right'\\\"></div><div ui-grid-grid-footer ng-if=\\\"grid.options.showGridFooter\\\"></div><div ui-grid-column-menu ng-if=\\\"grid.options.enableColumnMenus\\\"></div><div ng-transclude></div></div>\"\n  );\n\n\n  $templateCache.put('ui-grid/uiGridCell',\n    \"<div class=\\\"ui-grid-cell-contents\\\">{{COL_FIELD CUSTOM_FILTERS}}</div>\"\n  );\n\n\n  $templateCache.put('ui-grid/uiGridColumnFilter',\n    \"<li class=\\\"ui-grid-menu-item ui-grid-clearfix ui-grid-column-filter\\\" ng-show=\\\"itemShown()\\\" ng-click=\\\"$event.stopPropagation();\\\"><div class=\\\"input-container\\\"><input class=\\\"column-filter-input\\\" type=\\\"text\\\" ng-model=\\\"item.model\\\" placeholder=\\\"{{ i18n.search.placeholder }}\\\"><div class=\\\"column-filter-cancel-icon-container\\\"><i class=\\\"ui-grid-filter-cancel ui-grid-icon-cancel column-filter-cancel-icon\\\">&nbsp;</i></div></div><div style=\\\"button-container\\\" ng-click=\\\"item.action($event)\\\"><div class=\\\"ui-grid-button\\\"><i class=\\\"ui-grid-icon-search\\\">&nbsp;</i></div></div></li>\"\n  );\n\n\n  $templateCache.put('ui-grid/uiGridColumnMenu',\n    \"<div class=\\\"ui-grid-column-menu\\\"><div ui-grid-menu menu-items=\\\"menuItems\\\"><!-- <div class=\\\"ui-grid-column-menu\\\">\\n\" +\n    \"    <div class=\\\"inner\\\" ng-show=\\\"menuShown\\\">\\n\" +\n    \"      <ul>\\n\" +\n    \"        <div ng-show=\\\"grid.options.enableSorting\\\">\\n\" +\n    \"          <li ng-click=\\\"sortColumn($event, asc)\\\" ng-class=\\\"{ 'selected' : col.sort.direction == asc }\\\"><i class=\\\"ui-grid-icon-sort-alt-up\\\"></i> Sort Ascending</li>\\n\" +\n    \"          <li ng-click=\\\"sortColumn($event, desc)\\\" ng-class=\\\"{ 'selected' : col.sort.direction == desc }\\\"><i class=\\\"ui-grid-icon-sort-alt-down\\\"></i> Sort Descending</li>\\n\" +\n    \"          <li ng-show=\\\"col.sort.direction\\\" ng-click=\\\"unsortColumn()\\\"><i class=\\\"ui-grid-icon-cancel\\\"></i> Remove Sort</li>\\n\" +\n    \"        </div>\\n\" +\n    \"      </ul>\\n\" +\n    \"    </div>\\n\" +\n    \"  </div> --></div></div>\"\n  );\n\n\n  $templateCache.put('ui-grid/uiGridFooterCell',\n    \"<div class=\\\"ui-grid-cell-contents\\\" col-index=\\\"renderIndex\\\"><div>{{ col.getAggregationText() + ( col.getAggregationValue() CUSTOM_FILTERS ) }}</div></div>\"\n  );\n\n\n  $templateCache.put('ui-grid/uiGridHeaderCell',\n    \"<div ng-class=\\\"{ 'sortable': sortable }\\\"><!-- <div class=\\\"ui-grid-vertical-bar\\\">&nbsp;</div> --><div class=\\\"ui-grid-cell-contents\\\" col-index=\\\"renderIndex\\\"><span>{{ col.displayName CUSTOM_FILTERS }}</span> <span ui-grid-visible=\\\"col.sort.direction\\\" ng-class=\\\"{ 'ui-grid-icon-up-dir': col.sort.direction == asc, 'ui-grid-icon-down-dir': col.sort.direction == desc, 'ui-grid-icon-blank': !col.sort.direction }\\\">&nbsp;</span></div><div class=\\\"ui-grid-column-menu-button\\\" ng-if=\\\"grid.options.enableColumnMenus && !col.isRowHeader  && col.colDef.enableColumnMenu !== false\\\" ng-click=\\\"toggleMenu($event)\\\" ng-class=\\\"{'ui-grid-column-menu-button-last-col': isLastCol}\\\"><i class=\\\"ui-grid-icon-angle-down\\\">&nbsp;</i></div><div ng-if=\\\"filterable\\\" class=\\\"ui-grid-filter-container\\\" ng-repeat=\\\"colFilter in col.filters\\\"><input type=\\\"text\\\" class=\\\"ui-grid-filter-input\\\" ng-model=\\\"colFilter.term\\\" ng-attr-placeholder=\\\"{{colFilter.placeholder || ''}}\\\"><div class=\\\"ui-grid-filter-button\\\" ng-click=\\\"colFilter.term = null\\\"><i class=\\\"ui-grid-icon-cancel\\\" ng-show=\\\"!!colFilter.term\\\">&nbsp;</i><!-- use !! because angular interprets 'f' as false --></div></div></div>\"\n  );\n\n\n  $templateCache.put('ui-grid/uiGridMenu',\n    \"<div class=\\\"ui-grid-menu\\\" ng-if=\\\"shown\\\"><div class=\\\"ui-grid-menu-mid\\\" ng-show=\\\"shownMid\\\"><div class=\\\"ui-grid-menu-inner\\\"><ul class=\\\"ui-grid-menu-items\\\"><li ng-repeat=\\\"item in menuItems\\\" ui-grid-menu-item action=\\\"item.action\\\" name=\\\"item.title\\\" active=\\\"item.active\\\" icon=\\\"item.icon\\\" shown=\\\"item.shown\\\" context=\\\"item.context\\\" template-url=\\\"item.templateUrl\\\"></li></ul></div></div></div>\"\n  );\n\n\n  $templateCache.put('ui-grid/uiGridMenuItem',\n    \"<li class=\\\"ui-grid-menu-item\\\" ng-click=\\\"itemAction($event, title)\\\" ng-show=\\\"itemShown()\\\" ng-class=\\\"{ 'ui-grid-menu-item-active' : active() }\\\"><i ng-class=\\\"icon\\\"></i> {{ name }}</li>\"\n  );\n\n\n  $templateCache.put('ui-grid/uiGridRenderContainer',\n    \"<div class=\\\"ui-grid-render-container\\\"><div ui-grid-header></div><div ui-grid-viewport></div><div ui-grid-footer ng-if=\\\"grid.options.showColumnFooter\\\"></div></div>\"\n  );\n\n\n  $templateCache.put('ui-grid/uiGridViewport',\n    \"<div class=\\\"ui-grid-viewport\\\" ng-style=\\\"containerCtrl.colContainer.getViewPortStyle()\\\"><div class=\\\"ui-grid-canvas\\\"><div ng-repeat=\\\"(rowRenderIndex, row) in rowContainer.renderedRows track by $index\\\" class=\\\"ui-grid-row\\\" ng-style=\\\"containerCtrl.rowStyle(rowRenderIndex)\\\"><div ui-grid-row=\\\"row\\\" row-render-index=\\\"rowRenderIndex\\\"></div></div></div></div>\"\n  );\n\n\n  $templateCache.put('ui-grid/cellEditor',\n    \"<div><form name=\\\"inputForm\\\"><input type=\\\"INPUT_TYPE\\\" ng-class=\\\"'colt' + col.uid\\\" ui-grid-editor ng-model=\\\"MODEL_COL_FIELD\\\"></form></div>\"\n  );\n\n\n  $templateCache.put('ui-grid/dropdownEditor',\n    \"<div><form name=\\\"inputForm\\\"><select ng-class=\\\"'colt' + col.uid\\\" ui-grid-edit-dropdown ng-model=\\\"MODEL_COL_FIELD\\\" ng-options=\\\"field[editDropdownIdLabel] as field[editDropdownValueLabel] CUSTOM_FILTERS for field in editDropdownOptionsArray\\\"></select></form></div>\"\n  );\n\n\n  $templateCache.put('ui-grid/expandableRow',\n    \"<div ui-grid-expandable-row ng-if=\\\"expandableRow.shouldRenderExpand()\\\" class=\\\"expandableRow\\\" style=\\\"float:left; margin-top: 1px; margin-bottom: 1px\\\" ng-style=\\\"{width: (grid.renderContainers.body.getCanvasWidth()) + 'px'\\n\" +\n    \"     , height: grid.options.expandableRowHeight + 'px'}\\\"></div>\"\n  );\n\n\n  $templateCache.put('ui-grid/expandableRowHeader',\n    \"<div class=\\\"ui-grid-row-header-cell ui-grid-expandable-buttons-cell\\\"><div class=\\\"ui-grid-cell-contents\\\"><i ng-class=\\\"{ 'ui-grid-icon-plus-squared' : !row.isExpanded, 'ui-grid-icon-minus-squared' : row.isExpanded }\\\" ng-click=\\\"grid.api.expandable.toggleRowExpansion(row.entity)\\\"></i></div></div>\"\n  );\n\n\n  $templateCache.put('ui-grid/expandableScrollFiller',\n    \"<div ng-if=\\\"expandableRow.shouldRenderFiller()\\\" style=\\\"float:left; margin-top: 2px; margin-bottom: 2px\\\" ng-style=\\\"{ width: (grid.getViewportWidth()) + 'px',\\n\" +\n    \"              height: grid.options.expandableRowHeight + 'px', 'margin-left': grid.options.rowHeader.rowHeaderWidth + 'px' }\\\"><i class=\\\"ui-grid-icon-spin5 ui-grid-animate-spin\\\" ng-style=\\\"{ 'margin-top': ( grid.options.expandableRowHeight/2 - 5) + 'px',\\n\" +\n    \"            'margin-left' : ((grid.getViewportWidth() - grid.options.rowHeader.rowHeaderWidth)/2 - 5) + 'px' }\\\"></i></div>\"\n  );\n\n\n  $templateCache.put('ui-grid/expandableTopRowHeader',\n    \"<div class=\\\"ui-grid-row-header-cell ui-grid-expandable-buttons-cell\\\"><div class=\\\"ui-grid-cell-contents\\\"><i ng-class=\\\"{ 'ui-grid-icon-plus-squared' : !grid.expandable.expandedAll, 'ui-grid-icon-minus-squared' : grid.expandable.expandedAll }\\\" ng-click=\\\"grid.api.expandable.toggleAllRows()\\\"></i></div></div>\"\n  );\n\n\n  $templateCache.put('ui-grid/csvLink',\n    \"<span class=\\\"ui-grid-exporter-csv-link-span\\\"><a href=\\\"data:text/csv;charset=UTF-8,CSV_CONTENT\\\" download=\\\"FILE_NAME\\\">LINK_LABEL</a></span>\"\n  );\n\n\n  $templateCache.put('ui-grid/importerMenuItem',\n    \"<li class=\\\"ui-grid-menu-item\\\"><form><input class=\\\"ui-grid-importer-file-chooser\\\" type=\\\"file\\\" id=\\\"files\\\" name=\\\"files[]\\\"></form></li>\"\n  );\n\n\n  $templateCache.put('ui-grid/importerMenuItemContainer',\n    \"<div ui-grid-importer-menu-item></div>\"\n  );\n\n\n  $templateCache.put('ui-grid/pagination',\n    \"<div class=\\\"ui-grid-pager-panel\\\" ui-grid-pager ng-show=\\\"grid.options.enablePaginationControls\\\"><div class=\\\"ui-grid-pager-container\\\"><div class=\\\"ui-grid-pager-control\\\"><button type=\\\"button\\\" ng-click=\\\"paginationApi.seek(1)\\\" ng-disabled=\\\"cantPageBackward()\\\"><div class=\\\"first-triangle\\\"><div class=\\\"first-bar\\\"></div></div></button> <button type=\\\"button\\\" ng-click=\\\"paginationApi.previousPage()\\\" ng-disabled=\\\"cantPageBackward()\\\"><div class=\\\"first-triangle prev-triangle\\\"></div></button> <input type=\\\"number\\\" ng-model=\\\"grid.options.paginationCurrentPage\\\" min=\\\"1\\\" max=\\\"{{ paginationApi.getTotalPages() }}\\\" required> <span class=\\\"ui-grid-pager-max-pages-number\\\" ng-show=\\\"paginationApi.getTotalPages() > 0\\\">/ {{ paginationApi.getTotalPages() }}</span> <button type=\\\"button\\\" ng-click=\\\"paginationApi.nextPage()\\\" ng-disabled=\\\"cantPageForward()\\\"><div class=\\\"last-triangle next-triangle\\\"></div></button> <button type=\\\"button\\\" ng-click=\\\"paginationApi.seek(paginationApi.getTotalPages())\\\" ng-disabled=\\\"cantPageToLast()\\\"><div class=\\\"last-triangle\\\"><div class=\\\"last-bar\\\"></div></div></button></div><div class=\\\"ui-grid-pager-row-count-picker\\\"><select ng-model=\\\"grid.options.paginationPageSize\\\" ng-options=\\\"o as o for o in grid.options.paginationPageSizes\\\"></select><span class=\\\"ui-grid-pager-row-count-label\\\">&nbsp;{{sizesLabel}}</span></div></div><div class=\\\"ui-grid-pager-count-container\\\"><div class=\\\"ui-grid-pager-count\\\"><span ng-show=\\\"grid.options.totalItems > 0\\\">{{showingLow}} - {{showingHigh}} of {{grid.options.totalItems}} {{totalItemsLabel}}</span></div></div></div>\"\n  );\n\n\n  $templateCache.put('ui-grid/columnResizer',\n    \"<div ui-grid-column-resizer ng-if=\\\"grid.options.enableColumnResizing\\\" class=\\\"ui-grid-column-resizer\\\" col=\\\"col\\\" position=\\\"right\\\" render-index=\\\"renderIndex\\\"></div>\"\n  );\n\n\n  $templateCache.put('ui-grid/gridFooterSelectedItems',\n    \"<span ng-if=\\\"grid.selection.selectedCount !== 0 && grid.options.enableFooterTotalSelected\\\">({{\\\"search.selectedItems\\\" | t}} {{grid.selection.selectedCount}})</span>\"\n  );\n\n\n  $templateCache.put('ui-grid/selectionHeaderCell',\n    \"<div><!-- <div class=\\\"ui-grid-vertical-bar\\\">&nbsp;</div> --><div class=\\\"ui-grid-cell-contents\\\" col-index=\\\"renderIndex\\\"><ui-grid-selection-select-all-buttons ng-if=\\\"grid.options.enableSelectAll\\\"></ui-grid-selection-select-all-buttons></div></div>\"\n  );\n\n\n  $templateCache.put('ui-grid/selectionRowHeader',\n    \"<div class=\\\"ui-grid-disable-selection\\\"><div class=\\\"ui-grid-cell-contents\\\"><ui-grid-selection-row-header-buttons></ui-grid-selection-row-header-buttons></div></div>\"\n  );\n\n\n  $templateCache.put('ui-grid/selectionRowHeaderButtons',\n    \"<div class=\\\"ui-grid-selection-row-header-buttons ui-grid-icon-ok\\\" ng-class=\\\"{'ui-grid-row-selected': row.isSelected}\\\" ng-click=\\\"selectButtonClick(row, $event)\\\">&nbsp;</div>\"\n  );\n\n\n  $templateCache.put('ui-grid/selectionSelectAllButtons',\n    \"<div class=\\\"ui-grid-selection-row-header-buttons ui-grid-icon-ok\\\" ng-class=\\\"{'ui-grid-all-selected': grid.selection.selectAll}\\\" ng-click=\\\"headerButtonClick($event)\\\"></div>\"\n  );\n\n}]);\n"
  },
  {
    "path": "flowable-ui-web/idm/manifest.json",
    "content": "{\n\t\"name\": \"\",\n\t\"icons\": [\n\t\t{\n\t\t\t\"src\": \"images\\/android-chrome-192x192.png?v=Om5N75Y123\",\n\t\t\t\"sizes\": \"192x192\",\n\t\t\t\"type\": \"image\\/png\"\n\t\t},\n\t\t{\n\t\t\t\"src\": \"images\\/android-chrome-384x384.png?v=Om5N75Y123\",\n\t\t\t\"sizes\": \"384x384\",\n\t\t\t\"type\": \"image\\/png\"\n\t\t}\n\t],\n\t\"theme_color\": \"#ffffff\",\n\t\"display\": \"standalone\"\n}\n"
  },
  {
    "path": "flowable-ui-web/idm/scripts/app-cfg.js",
    "content": "/* Copyright 2005-2015 Alfresco Software, Ltd.\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'use strict';\n\nvar FLOWABLE = FLOWABLE || {};\n\nvar pathname = window.location.pathname.replace(/^(\\/[^\\/]*)(\\/.*)?$/, '$1').replace(/\\/$/, '');\n\nFLOWABLE.CONFIG = {\n\t'onPremise' : true,\n\t'contextRoot' : '/flowable_idm',\n\t'webContextRoot' : pathname,\n    'datesLocalization' : false\n};\n\n//\n// DEV ENV OVERRIDES\n//\n\n"
  },
  {
    "path": "flowable-ui-web/idm/scripts/common/directives.js",
    "content": "/* 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 */\nflowableModule\n  .directive('restrictInput', [\"$parse\", function ($parse) {\n    return {\n      restrict: 'A',\n      require: 'ngModel',\n      priority: 1002,\n\n      link: function postLink(scope, elm, attrs, ctrl) {\n\n        var acceptedFormat = attrs[\"restrictInput\"];\n        if (acceptedFormat == undefined || acceptedFormat == null || acceptedFormat == \"\") {\n           acceptedFormat = attrs[\"dateFormat\"];\n        }\n\n        scope.field.acceptedFormat=acceptedFormat;\n\n        function calculateAcceptedFormats(format) {\n          var format1 = format.toUpperCase(); //d-m-yyyy\n          var format2 = format1.replace(/-D-/,\"-DD-\").replace(/^D-/,\"DD-\").replace(/-D$/,\"-DD\"); //dd-m-yyyy\n          var format3 = format1.replace(/-M-/,\"-MM-\").replace(/^M-/,\"MM-\").replace(/-M$/,\"-MM\");  //d-mm-yyyy\n          var format4 = format2.replace(/-M-/,\"-MM-\").replace(/^M-/,\"MM-\").replace(/-M$/,\"-MM\");  //dd-mm-yyyy\n          return [format1,format2,format3,format4];\n        }\n\n        var acceptedFormats = calculateAcceptedFormats(acceptedFormat);\n        var skipValidation = false;\n\n        if (acceptedFormat == undefined || acceptedFormat == null || acceptedFormat == \"\") {\n          skipValidation = true;\n        }\n        var oldRenderer = ctrl.$render;\n\n        ctrl.$render = function () {\n          elm.val(ctrl.$viewValue);\n          if (ctrl.$dateValue && !isNaN(ctrl.$dateValue.getTime())) {\n            if (oldRenderer) {\n              oldRenderer();\n            }\n          }\n        };\n\n        function isValidText(viewValue, format) {\n          if (viewValue === undefined || viewValue == null || viewValue ==='') return true;\n          if (viewValue.length > format.length) return false;\n\n           for (var i = 0; i < Math.min(format.length, viewValue.length); i++) {\n             var charType = format[i];\n             if (charType.toUpperCase().match(/D|M|Y/)) {\n               if (viewValue[i].match(/\\d/) == null) return false;\n             }else {\n               if (viewValue[i] != charType) return false;\n             }\n           }\n           return true;\n         }\n\n        ctrl.$parsers.unshift(function (viewValue) {\n\n          if (skipValidation) return viewValue; //just skip this parser\n\n          var isValid = false;\n          for(var i =0 ; i < acceptedFormats.length && !isValid; i++){\n            isValid |= isValidText(viewValue,acceptedFormats[i]);\n          }\n\n          if (!isValid) {\n            //should restore to the latest known well formated date.\n            ctrl.$dateValue = null;\n          } else {\n            ctrl.$lastValidText = viewValue;\n\n              //by default the date picker in angular strap does not reset the dateValue if the viewValue is null or empty.\n              if (viewValue === undefined || viewValue == null || viewValue === '') {\n                  ctrl.$dateValue = null;\n              }\n\n            return viewValue;\n          }\n\n          ctrl.$setViewValue(ctrl.$lastValidText);\n          ctrl.$render();\n          return ctrl.$lastValidText;\n        });\n\n      }\n    }\n  }\n  ]);\n\n\nflowableModule\n    .directive('autoHeight', ['$rootScope', '$timeout', function($rootScope, $timeout) {\n        return {\n            restrict: 'AC',\n            scope: {\n              'toWatch': '=autoHeight'\n            },\n            compile: function (element, attr) {\n                return function ($scope, $element, $attrs) {\n                    var offset = 0;\n                    if($attrs['offset']) {\n                        offset = parseInt($attrs['offset']);\n                        if(isNaN(offset) || offset == undefined) {\n                            offset = 0;\n                        }\n                    }\n\n                    var update = function($element) {\n                        // Get hold of parent and iterate all the children to get available height\n\n                        $timeout(function() {\n                            var total = $element.parent().outerHeight() - offset;\n                            var found = false;\n                            $element.parent().children().each(function() {\n                                if(!found) {\n                                    if($element[0] == this) {\n                                        found = true;\n                                    } else {\n                                        // Substract preceding child's height\n                                        total -= angular.element(this).outerHeight();\n                                    }\n                                }\n                            });\n\n                            if(found) {\n                                $element.height(total);\n                            }\n                        }, 0);\n                    };\n\n                    if($scope.unregisterWatcher) {\n                        $scope.unregisterWatcher();\n                    }\n                    $scope.unregisterWatcher = $rootScope.$watch('window.height', function(windowHeight) {\n                        update($element);\n                    });\n\n                    if($scope.unregisterForceWatcher) {\n                        $scope.unregisterForceWatcher();\n                    }\n                    $scope.unregisterForceWatcher = $rootScope.$watch('window.forceRefresh', function(forceValue) {\n                        update($element);\n                    });\n\n\n                    $scope.$on('$destroy', function() {\n                        // Cleanup watcher for window-height\n                        if($scope.unregisterWatcher) {\n                            $scope.unregisterWatcher();\n                        }\n                        if($scope.unregisterForceWatcher) {\n                            $scope.unregisterForceWatcher();\n                        }\n                    });\n                }\n            }\n        };\n    }]);\n\n/**\n * Directive that ensures the child-element with class .active is visible and scrolls if needed. Watches the value\n * of the directive and will re-apply if this value is changes.\n */\nflowableModule\n    .directive('scrollToActive', ['$timeout', function($timeout) {\n        return {\n            restrict: 'AC',\n            scope: {\n                toWatch: \"=scrollToActiveModel\"\n            },\n            compile: function (element, attr) {\n                return function ($scope, $element, $attrs) {\n                    $scope.$watch('toWatch', function() {\n                        $timeout(function() {\n                            var useParent = $attrs['useParent'];\n                            var offsetTop = $attrs['offsetTop'];\n                            if(offsetTop) {\n                                offsetTop = parseInt(offsetTop);\n                                if(isNaN(offsetTop)) {\n                                    offsetTop = 0;\n                                }\n                            }\n                            if (!offsetTop) {\n                                offsetTop = 0;\n                            }\n\n                            var selectedArr = $element.children('.active');\n                            if(selectedArr && selectedArr.length > 0) {\n                                var selected = angular.element(selectedArr[0]);\n\n                                if(useParent) {\n                                    $element = angular.element($element.parent());\n                                }\n                                var selectedTop = selected.position().top - $element.position().top + $element.scrollTop();\n                                var selectedBottom = selectedTop + selected.outerHeight();\n                                var elementBottom = $element.scrollTop() + $element.innerHeight();\n                                var elementTop = elementBottom - $element.innerHeight();\n\n                                if(selectedTop <= elementTop) {\n                                    // scroll up\n                                    $element.scrollTop(selectedTop - selected.outerHeight() - offsetTop);\n                                } else if(selectedBottom > elementBottom) {\n                                    // scroll down\n                                    $element.scrollTop(elementTop + selected.outerHeight() - offsetTop);\n                                }\n                            }\n                        }, 0);\n                    });\n                }\n            }\n        };\n    }]);\n\n/**\n * Directive that ensures the popup is scrolled into view, using the first parent as scroll-pane that has\n * a class 'scroll-container' set on it. Is applied when the popup is shown.\n */\nflowableModule\n    .directive('autoScroll', ['$timeout', function($timeout) {\n        return {\n            restrict: 'AC',\n            compile: function (element, attr) {\n                return function ($scope, $element, $attrs) {\n                    $scope.$on('tooltip.show', function() {\n                        $timeout(function() {\n                            // Find appropriate parent\n                            var parent = $element[0];\n                            while(parent) {\n                                if(parent.className && parent.className.indexOf('scroll-container') >= 0) {\n                                    break;\n                                }\n                                parent = parent.parentNode;\n                            }\n\n                            if(parent) {\n                                parent = angular.element(parent);\n                                var selectedTop = $element.offset().top  - parent.offset().top + $element.scrollTop();\n                                var selectedBottom = selectedTop + $element.outerHeight();\n\n                                if(selectedBottom + 30 >= parent.outerHeight()) {\n                                    parent.scrollTop(selectedTop);\n                                }\n                            }\n                        }, 50);\n                    });\n                }\n            }\n        };\n    }]);\n\nflowableModule\n    .directive('userName', function() {\n        var directive = {};\n        directive.template = '{{user.firstName && user.firstName || \"\"}} {{user.lastName && user.lastName || \"\"}} {{ (user.email && !user.firstName && !user.lastName) && user.email || \"\"}}';\n        directive.scope = {\n            user: \"=userName\"\n        };\n        return directive;\n    });\n\n\n/**\n * Executes the method that is set on the directive attribute value when ANY OTHER element is clicked, which is not the element the\n * directive is on, or any of it's children.\n *\n */\nflowableModule\n    .directive('clickAnywhere', [\"$document\", \"$parse\", function ($document, $parse) {\n\n        var linkFunction = function ($scope, $element, $attributes) {\n\n            var scopeExpression = $attributes.clickAnywhere;\n            var invoker = $parse(scopeExpression);\n\n            var ignoreId = $attributes.ignore;\n            var ignoreClass = $attributes.ignoreClass;\n            var ignorePopupEvents = $attributes.ignorePopupEvents == 'true';\n\n            var handler = function (event) {\n                // Check source of event\n                var parent = event.target;\n                while(parent) {\n                    if(parent == $element[0] ||\n                        (ignoreId && parent.id == ignoreId) ||\n                        (ignoreClass && parent.className && parent.className.indexOf(ignoreClass) >= 0)) {\n\n                        event.stopPropagation();\n                        event.preventDefault();\n                        return;\n                    }\n                    parent = parent.parentNode;\n                }\n\n                $scope.$apply(\n                    function () {\n                        invoker($scope, {$event: event});\n                    }\n                );\n            };\n\n            $document.on(\"click\", handler);\n\n            $scope.$on('$destroy', function () {\n                $document.off(\"click\", handler);\n            });\n\n            // Special handling for tooltips which don't destroy the scope\n            var hideReg = $scope.$on('tooltip.hide', function () {\n                if(!ignorePopupEvents) {\n                    $document.off(\"click\", handler);\n                    hideReg();\n                }\n            });\n\n        };\n\n        // Return the linking function.\n        return( linkFunction );\n    }\n    ]);\n\n\n\n\nflowableModule\n    .directive('autoFocus', ['$timeout', '$parse', function($timeout, $parse) {\n        return {\n            restrict: 'AC',\n            compile: function($element, attr) {\n                var selectText;\n\n                if(attr[\"selectText\"]) {\n                    selectText = $parse(attr[\"selectText\"]);\n                }\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                                if(selectText && selectText(_scope.$parent)) {\n                                    input[0].setSelectionRange(0,input[0].value.length);\n                                }\n                            }\n                        } else {\n                            // Focus element where the directive is put on\n                            _element[0].focus();\n                            if(selectText && selectText(_scope.$parent)) {\n                                _element[0].setSelectionRange(0,_element[0].value.length);\n                            }\n                        }\n                    }, 100);\n                }\n            }\n        };\n    }]);\n\nflowableModule\n    .directive('focusWhen', ['$timeout', function ($timeout) {\n        return {\n            link: function (scope, element, attrs) {\n                scope.$watch(attrs.ngFocus, function (val) {\n                    if (angular.isDefined(val) && val) {\n                        $timeout(function () {\n                            element[0].focus();\n                        });\n                    }\n                }, true);\n\n                element.bind('blur', function () {\n                    if (angular.isDefined(attrs.ngFocusLost)) {\n                        scope.safeApply(attrs.ngFocusLost);\n                    }\n                });\n            }\n        };\n    }]);\n\n\nflowableModule\n    .directive('loading', [function() {\n        var directive = {};\n        directive.restrict = 'A';\n        directive.template = '<div class=\"loading\" ng-show=\"loading\"><div class=\"l1\"></div><div class=\"l2\"></div><div class=\"l3\"></div></div>';\n        directive.scope = {\n            loading : \"=loading\",\n            loadingText: \"=loadingText\"\n        };\n        return directive;\n    }]);\n\n// Workaround for https://github.com/twbs/bootstrap/issues/8379 :\n// prototype.js interferes with regular dropdown behavior\nflowableModule\n    .directive('activitiFixDropdownBug', function() {\n        return {\n            restrict: 'AEC',\n            link: function(scope, element, attrs) {\n                element.on('hidden.bs.dropdown', function () {\n                    element.show(); // evil prototype.js has added display:none to it ...\n                })\n            }\n        };\n    });\n\n/**\n * Directive for rendering user link.\n */\nflowableModule\n  .directive('userLink', function() {\n    var directive = {};\n    directive.template = '{{user.firstName && user.firstName || \"\"}} {{user.lastName && user.lastName || \"\"}} {{ (user.email && !user.firstName && !user.lastName) && user.email || \"\"}}';\n    directive.scope = {\n        user: \"=userLink\"\n    };\n\n    directive.compile = function(element, attributes) {\n        element.addClass('people-link');\n    };\n\n    return directive;\n});\n\n/**\n * Directive for rendering a form field.\n */\nflowableModule\n    .directive('formField', function () {\n        var directive = {};\n\n        directive.template = ' {{field.name || \"\"}} - {{field.id}}';\n        directive.scope = {\n            field: \"=formField\"\n        };\n\n        directive.compile = function (element, attributes) {\n            element.addClass('form-field');\n        };\n        return directive;\n    });\n/**\n * Directive to capture mouse up, down, enter and escape on input fields (eg. list navigation)\n */\nflowableModule\n    .directive('customKeys', [\"$parse\", function ($parse) {\n        var directive = {};\n        directive.compile = function($element, attr) {\n            var up, down, enter, escape;\n\n            if(attr[\"upPressed\"]) {\n                up = $parse(attr[\"upPressed\"]);\n            }\n            if(attr[\"downPressed\"]) {\n                down = $parse(attr[\"downPressed\"]);\n            }\n            if(attr[\"enterPressed\"]) {\n                enter = $parse(attr[\"enterPressed\"]);\n            }\n\n            if(attr[\"escapePressed\"]) {\n                escape = $parse(attr[\"escapePressed\"]);\n            }\n\n            return function(scope, element, attr) {\n                element.on('keyup', function(e) {\n                    if(e.keyCode === 38) {\n                        scope.$apply(function() {\n                            if(up) {\n                                up(scope, {$event:e});\n                            }\n                        });\n                    } else if(e.keyCode === 40) {\n                        scope.$apply(function() {\n                            if(down) {\n                                down(scope, {$event:e});\n                            }\n                        });\n                    } else if(e.keyCode === 13) {\n                        scope.$apply(function() {\n                            if(enter) {\n                                enter(scope, {$event:e});\n                            }\n                        });\n                    } else if(e.keyCode === 27) {\n                    scope.$apply(function() {\n                        if(escape) {\n                            escape(scope, {$event:e});\n                        }\n                    });\n                }\n                });\n\n                element.on('keydown', element, function (e) {\n                    if (e.keyCode === 38 || e.keyCode === 40 || e.keyCode === 13 || e.keyCode === 27)\n                        e.preventDefault();\n                });\n            };\n    };\n    return directive;\n}]);\n\n// Delayed setting of model value in scope, based on input value unchanged after a number of millis\n// See below: ngDebounce is preferred (as it hooks into ngModel, meaning that ng-change will keep working - but not with delayedModel)\nflowableModule\n    .directive('delayedModel', ['$timeout', function($timeout) {\n    return {\n        scope: {\n            targetModel: '=delayedModel'\n        },\n        link: function(scope, element, attrs) {\n\n            element.val(scope.targetModel);\n\n            // Also watch model for any changes not triggered by timer\n            scope.$watch('targetModel', function(newVal, oldVal) {\n                if(scheduled) {\n                    $timeout.cancel(scheduled);\n                }\n                if (newVal !== oldVal) {\n                    element.val(scope.targetModel);\n                }\n            });\n\n            var scheduled;\n            element.on('keyup paste search', function() {\n                if(element.val() !== scope.targetModel) {\n                    if(scheduled) {\n                        $timeout.cancel(scheduled);\n                    }\n                    scheduled = $timeout(function() {\n                        scope.targetModel = element[0].value;\n                        element.val(scope.targetModel);\n                        scope.$apply();\n                    }, attrs.delay || 200);\n                }\n            });\n        }\n    };\n}]);\n\n\n// From https://gist.github.com/benbrandt22/bb44184a2eddcd4b0b8a\nflowableModule.directive('ngDebounce', ['$timeout', function($timeout) {\n    return {\n        restrict: 'A',\n        require: 'ngModel',\n        priority: 99,\n        link: function(scope, elm, attr, ngModelCtrl) {\n            if (attr.type === 'radio' || attr.type === 'checkbox') return;\n\n            elm.unbind('input');\n\n            var debounce;\n            elm.bind('input', function() {\n                $timeout.cancel(debounce);\n                debounce = $timeout( function() {\n                    scope.$apply(function() {\n                        ngModelCtrl.$setViewValue(elm.val());\n                    });\n                }, attr.ngDebounce || 1000);\n            });\n            elm.bind('blur', function() {\n                scope.$apply(function() {\n                    ngModelCtrl.$setViewValue(elm.val());\n                });\n            });\n        }\n\n    }\n}]);\n\nflowableModule.directive('externalContent', ['$parse', '$timeout', 'appResourceRoot', function ($parse, $timeout, appResourceRoot) {\n    var directive = {};\n    directive.restrict = 'A';\n    directive.templateUrl = appResourceRoot + '../views/common/templates/external-content-template.html';\n\n    directive.scope = {\n        taskId : '=taskId',\n        processInstanceId: '=formDefinition',\n        caseInstanceId: '=caseInstanceId',\n        folderSelect: '=folderSelect',\n        linkOnly: '=linkOnly',\n        preSelectedAlfrescoAccount: '=account',\n        uploadInProgress: '=uploadInProgress'\n    };\n    directive.link = function ($scope, $element, $attributes) {\n\n        if($attributes[\"onContentUpload\"]) {\n            $scope.uploadedCallback = $parse($attributes['onContentUpload']);\n        }\n\n        if($attributes[\"onFolderSelect\"]) {\n            $scope.folderSelectCallback = $parse($attributes['onFolderSelect']);\n        }\n\n        if($attributes[\"onUploadInProgress\"]) {\n            $scope.uploadInProgressCallback = $parse($attributes['onUploadInProgress']);\n        }\n\n        // Schedule hooking in of click-listener. we cannot use angular ng-click since this\n        // will force a new $apply/$digest to happen when the click() is called on the button\n        $timeout(function() {\n            $element.find('div.select-file').click(function() {\n                $element.find('input[type=\"file\"]').click();\n            });\n        }, 200);\n    };\n    directive.controller = ['$scope', '$element', 'RelatedContentService', '$modal', '$window', '$translate', '$rootScope',  function($scope, $element, RelatedContentService, $modal, $window, $translate, $rootScope) {\n        $scope.uploadModel = {uploading: false};\n\n        $scope.clearPopupError = function() {\n        };\n\n        $scope.openFileSelect = function(element) {\n            $scope.errorMessage = undefined;\n            var parent = angular.element(element).parent();\n            parent.children('input').click();\n        };\n\n        $scope.onFileSelect = function ($files, isIE) {\n            $scope.errorMessage = undefined;\n            if(!$scope.linkOnly) {\n                $scope.errorMessage = undefined;\n                if(!$scope.folderSelect && !$scope.uploadModel.uploading && $files.length > 0) {\n                    if ($scope.uploadInProgressCallback) {\n                        $scope.uploadInProgressCallback($scope.$parent, {status: true});\n                    }\n\n                    $scope.uploadModel.uploading = true;\n                    var file = $files[0];\n\n                    $scope.clearPopupError();\n                    RelatedContentService.addRelatedContent($scope.taskId, $scope.processInstanceId, $scope.caseInstanceId, file, isIE).progress(function (evt) {\n                        $scope.uploadModel.uploadProgress = parseInt(100.0 * evt.loaded / evt.total);\n                    }).then(function (data) {\n                        if ($scope.uploadInProgressCallback) {\n                            $scope.uploadInProgressCallback($scope.$parent, {status: false});\n\n                        }\n\n                        $scope.uploadModel.uploading = false;\n                        if($scope.uploadedCallback) {\n                            $scope.uploadedCallback($scope.$parent, {'content': data});\n                        }\n                    }, function (error) {\n                        // Error callback\n                        if ($scope.uploadInProgressCallback) {\n                            $scope.uploadInProgressCallback($scope.$parent, {status: false});\n                        }\n\n                        if(error && error.messageKey) {\n                            var formattedData = {};\n                            if(error.customData) {\n                                formattedData.quota =  $scope.formatFileSize(error.customData.quota)\n                            };\n\n                            $translate(error.messageKey, formattedData).then(function(message) {\n                                $scope.errorMessage = message;\n                            });\n                        }\n                        $scope.uploadModel.uploading = false;\n                    });\n                }\n            }\n        };\n\n    }];\n\n    return directive;\n}]);\n\n\nflowableModule.\n    directive('selectPeoplePopover', ['$rootScope', '$http', '$popover', 'appResourceRoot', 'UserService', '$parse', function($rootScope, $http, $popover, appResourceRoot, UserService, $parse) {\n        var directive = {};\n        directive.restrict = 'A';\n\n        directive.scope = {\n            excludeTaskId: '=excludeTaskId',\n            excludeProcessId: '=excludeProcessId',\n            excludeUserId: '=excludeUserId',\n            excludeUserIds: '=excludeUserIds',\n            tenantId: '=tenantId',\n            type: '=type',\n            restrictWithGroup: '=restrictWithGroup',\n            selectPeopleFormFields: '=selectPeopleFormFields',\n            ignoreContainer: '=ignoreContainer'\n        };\n\n        directive.link = function($scope, $element, attrs) {\n            // Set defaults\n            var placement = \"bottom\";\n\n            $element.addClass(\"toggle-people-select\");\n\n            if(attrs.placement) {\n                placement = attrs.placement;\n            }\n\n            var closeOnSelect = true;\n            if(attrs.closeOnSelect !== undefined) {\n                closeOnSelect = attrs.closeOnSelect;\n            }\n\n            if ($scope.ignoreContainer) {\n                $scope.popover = $popover($element, {template: appResourceRoot + 'views/common/popover/select-people-popover.html?'  +\n                    Date.now(), placement: placement});\n\n            } else {\n                $scope.popover = $popover($element, {template: appResourceRoot + 'views/common/popover/select-people-popover.html?'  +\n                    Date.now(), placement: placement, container: 'body'});\n            }\n\n            // Parse callbacks\n            var selectedCallback, cancelledCallback, emailSelectedCallback;\n            if (attrs['onPeopleSelected']) {\n                selectedCallback = $parse(attrs['onPeopleSelected']);\n            }\n            if (attrs['onCancel']) {\n                cancelledCallback = $parse(attrs['onCancel']);\n            }\n            if (attrs['onEmailSelected']) {\n                emailSelectedCallback = $parse(attrs['onEmailSelected']);\n            }\n\n            // Parse type\n            // Can be 'workflow' or 'idm'. In 'workflow', the users are retrieved for filling task assignments etc. This is the default if this param is omitted. 'idm' is more strict.\n            var backendType = 'workflow';\n            if ($scope.type !== null && $scope.type !== undefined) {\n                backendType = $scope.type;\n            }\n\n            var popoverScope = $scope.popover.$scope;\n            popoverScope.title = attrs['popoverTitle'];\n\n            popoverScope.popupModel = {\n                emailMode: false,\n                showRecentResults: false, // Disabled recent for the moment. Put this on true to set it back\n                userResults: [],\n                userField: {},\n                userFieldFilter: ['people']\n            };\n\n            if ($scope.selectPeopleFormFields) {\n                popoverScope.popupModel.formFields = $scope.selectPeopleFormFields;\n            }\n\n            if (attrs['emailModeDisabled']) {\n                var emailModeDisabledValue = attrs['emailModeDisabled'];\n                if (emailModeDisabledValue === 'true') {\n                    popoverScope.popupModel.emailDisabled = true;\n                }\n            }\n\n            popoverScope.popupModel.emailMode = false;\n\n\n            popoverScope.setSearchType = function() {\n                popoverScope.popupModel.userSourceType = 'search';\n            };\n\n            popoverScope.setFormFieldType = function() {\n                popoverScope.popupModel.userSourceType = 'field';\n            };\n\n            popoverScope.$watch('popupModel.userField', function() {\n                if (popoverScope.popupModel.userField && popoverScope.popupModel.userField.id) {\n                    if (selectedCallback) {\n                        // Run callback in parent scope of directive\n                        var simpleUserField = {\n                                id: popoverScope.popupModel.userField.id,\n                                name: popoverScope.popupModel.userField.name,\n                                type: popoverScope.popupModel.userField.type\n                        }\n\n                        selectedCallback($scope.$parent, {'userField': simpleUserField});\n                        popoverScope.popupModel.userField = {};\n                    }\n\n                    if (closeOnSelect || closeOnSelect === 'true') {\n                        popoverScope.$hide();\n                    }\n                }\n            });\n\n            popoverScope.$watch('popupModel.filter', function() {\n                if (popoverScope.popupModel.filter && popoverScope.popupModel.filter.length > 0) {\n\n                    var userGetPromise;\n                    if (backendType === 'idm') {\n                        userGetPromise = UserService.getFilteredUsersStrict(popoverScope.popupModel.filter, $scope.tenantId, $scope.restrictWithGroup);\n                    } else {\n                        // Default: go to workflow users backend\n                        userGetPromise = UserService.getFilteredUsers(popoverScope.popupModel.filter, $scope.excludeTaskId,\n                                $scope.excludeProcessId, $scope.tenantId, $scope.restrictWithGroup);\n                    }\n\n                    userGetPromise.then(function(result) {\n                        popoverScope.popupModel.showRecentResults =  false;\n\n                        var users = [];\n                        var excludeUserIdSet = $scope.excludeUserId !== null && $scope.excludeUserId !== undefined;\n                        var excludeUserIdsSet = $scope.excludeUserIds !== null && $scope.excludeUserIds !== undefined;\n                        if (excludeUserIdSet === true || excludeUserIdsSet === true) {\n                            for (var userIndex=0; userIndex < result.data.length; userIndex++) {\n\n                                var userExcluded = false;\n                                if (excludeUserIdSet === true && result.data[userIndex].id === $scope.excludeUserId) {\n                                    userExcluded = true;\n                                }\n                                if (excludeUserIdsSet === true && $scope.excludeUserIds.indexOf(result.data[userIndex].id) >= 0) {\n                                    userExcluded = true;\n                                }\n\n                                if (!userExcluded) {\n                                    users.push(result.data[userIndex]);\n                                }\n\n                            }\n                        } else {\n                            users = result.data;\n                        }\n                        popoverScope.popupModel.userResults = users;\n                        popoverScope.resetSelection();\n                    });\n                } else {\n                    popoverScope.resetSelection();\n                    popoverScope.popupModel.userResults = [];\n                }\n            });\n\n            popoverScope.resetSelection = function() {\n                popoverScope.popupModel.selectedUser = undefined;\n                popoverScope.popupModel.selectedIndex = -1;\n            };\n\n            popoverScope.nextUser = function() {\n                var users = popoverScope.popupModel.userResults;\n                if(users && users.length > 0 && popoverScope.popupModel.selectedIndex < users.length -1) {\n                    popoverScope.popupModel.selectedIndex+=1;\n                    popoverScope.popupModel.selectedUser = users[popoverScope.popupModel.selectedIndex];\n                }\n            };\n\n            popoverScope.previousUser = function() {\n                var users = popoverScope.popupModel.userResults;\n                if(users && users.length > 0 && popoverScope.popupModel.selectedIndex > 0) {\n                    popoverScope.popupModel.selectedIndex-=1;\n                    popoverScope.popupModel.selectedUser = users[popoverScope.popupModel.selectedIndex];\n                }\n            };\n\n            popoverScope.confirmUser = function(user) {\n                if (!user) {\n                    // Selection is done with keyboard, use selection index\n                    var users = popoverScope.popupModel.userResults;\n                    if (popoverScope.popupModel.selectedIndex >= 0 && popoverScope.popupModel.selectedIndex <users.length) {\n                        user = users[popoverScope.popupModel.selectedIndex];\n                    }\n                }\n\n                if (user) {\n                    if (selectedCallback) {\n                        // Run callback in parent scope of directive\n                        selectedCallback($scope.$parent, {'user': user});\n                    }\n\n                    if (closeOnSelect === 'true') {\n                        popoverScope.$hide();\n                    } else {\n                        var users = popoverScope.popupModel.userResults;\n                        users.splice(jQuery.inArray(user, users),1);\n                        popoverScope.popupModel.selectedIndex=0;\n                        popoverScope.popupModel.selectedUser = users[popoverScope.popupModel.selectedIndex];\n                    }\n                }\n            };\n\n            popoverScope.selectPersonByEmail = function(validEmail) { // Not so nice we have to pass the valid email agrument, but couldnt make it work properly\n                if (validEmail) {\n                    if (emailSelectedCallback) {\n                        emailSelectedCallback($scope.$parent, {email: popoverScope.popupModel.email});\n                        popoverScope.$hide();\n                    }\n                }\n            };\n\n            popoverScope.$on('tooltip.hide', function() {\n                // Invalidate recent results\n                if(popoverScope.popupModel.showRecentResults && popoverScope.popupModel.added) {\n                    popoverScope.popupModel.recentUsers = [];\n                }\n                popoverScope.popupModel.userResults = [];\n                popoverScope.popupModel.filter = '';\n                popoverScope.popupModel.emailMode = false;\n\n                if(popoverScope.popupModel.added) {\n                    popoverScope.popupModel.added = false;\n                } else {\n                    if(cancelledCallback) {\n                        // Run callback in parent scope of directive\n                        cancelledCallback($scope.$parent);\n                    }\n                }\n            });\n\n        };\n        return directive;\n    }]);\n\nflowableModule.\ndirective('selectGroupPopover', ['$rootScope', '$http', '$popover','appResourceRoot', 'GroupService', '$parse',\n    function($rootScope, $http, $popover, appResourceRoot, GroupService, $parse) {\n\n    var directive = {};\n    directive.restrict = 'A';\n\n    directive.scope = {\n        type: '=type',\n        ignoreContainer: '=ignoreContainer',\n        restrictWithGroup: '=restrictWithGroup',\n        excludeGroupIds: '=excludeGroupIds'\n    };\n\n    directive.link = function($scope, $element, attrs) {\n        // Set defaults\n        var placement = \"bottom\";\n\n        $element.addClass(\"toggle-functional-group-select\");\n\n        if (attrs.placement) {\n            placement = attrs.placement;\n        }\n\n        var closeOnSelect = true;\n        if (attrs.closeOnSelect !== undefined) {\n            closeOnSelect = attrs.closeOnSelect;\n        }\n\n        if ($scope.ignoreContainer) {\n            $scope.popover = $popover($element, {template: appResourceRoot + 'views/common/popover/select--group-popover.html?' +\n                Date.now(), placement: placement});\n\n        } else {\n            $scope.popover = $popover($element, {template: appResourceRoot + 'views/common/popover/select-group-popover.html?' +\n                Date.now(), placement: placement, container: 'body'});\n        }\n\n        // Parse callbacks\n        var selectedCallback, cancelledCallback;\n        if (attrs['onGroupSelected']) {\n            selectedCallback = $parse(attrs['onGroupSelected']);\n        }\n        if (attrs['onCancel']) {\n            cancelledCallback = $parse(attrs['onCancel']);\n        }\n\n        var popoverScope = $scope.popover.$scope;\n        popoverScope.title = attrs['popoverTitle'];\n\n        popoverScope.popupModel = {\n            groupResults: []\n        };\n\n        popoverScope.$watch('popupModel.filter', function() {\n            if (popoverScope.popupModel.filter && popoverScope.popupModel.filter.length > 0) {\n\n               GroupService.getFilteredGroups(popoverScope.popupModel.filter, $scope.restrictWithGroup).then(function(result) {\n                    var groups = [];\n                    if ($scope.excludeGroupId != null && $scope.excludeGroupId) {\n                        for (var groupIndex=0; groupIndex < result.data.length; groupIndex++) {\n                            if (result.data[groupIndex].id !== $scope.excludeGroupId) {\n                                groups.push(result.data[groupIndex]);\n                            }\n                        }\n                    } else if ($scope.excludeGroupIds != null && $scope.excludeGroupIds !== undefined) {\n                        for (var groupIndex=0; groupIndex < result.data.length; groupIndex++) {\n                            if ($scope.excludeGroupIds.indexOf(result.data[groupIndex].id) < 0) {\n                                groups.push(result.data[groupIndex]);\n                            }\n                        }\n                    } else {\n                        groups = result;\n                    }\n                    popoverScope.popupModel.groupResults = groups;\n                    popoverScope.resetSelection();\n                });\n            } else {\n                popoverScope.resetSelection();\n                popoverScope.popupModel.groupResults = [];\n            }\n        });\n\n        popoverScope.resetSelection = function() {\n            popoverScope.popupModel.selectedGroup = undefined;\n            popoverScope.popupModel.selectedIndex = -1;\n        };\n\n        popoverScope.nextGroup = function() {\n            var groups = popoverScope.popupModel.groupResults;\n            if (groups && groups.length > 0 && popoverScope.popupModel.selectedIndex < groups.length -1) {\n                popoverScope.popupModel.selectedIndex+=1;\n                popoverScope.popupModel.groupUser = groups[popoverScope.popupModel.selectedIndex];\n            }\n        };\n\n        popoverScope.previousGroup = function() {\n            var groups = popoverScope.popupModel.groupResults;\n            if (groups && groups.length > 0 && popoverScope.popupModel.selectedIndex > 0) {\n                popoverScope.popupModel.selectedIndex-=1;\n                popoverScope.popupModel.selectedGroup = groups[popoverScope.popupModel.selectedIndex];\n            }\n        };\n\n        popoverScope.confirmGroup = function(group) {\n            if (!group) {\n                // Selection is done with keyboard, use selection index\n                var groups = popoverScope.popupModel.groupResults;\n                if (popoverScope.popupModel.selectedIndex >= 0 && popoverScope.popupModel.selectedIndex < groups.length) {\n                    group = groups[popoverScope.popupModel.selectedIndex];\n                }\n            }\n\n            if (group) {\n                if(selectedCallback) {\n                    // Run callback in parent scope of directive\n                    selectedCallback($scope.$parent, {'group': group});\n                }\n\n                if (closeOnSelect === 'true') {\n                    popoverScope.$hide();\n                } else {\n                    var groups = popoverScope.popupModel.groupResults;\n                    groups.splice(jQuery.inArray(group, groups), 1);\n                    popoverScope.popupModel.selectedIndex = 0;\n                    popoverScope.popupModel.selectedGroup = groups[popoverScope.popupModel.selectedIndex];\n                }\n            }\n        };\n\n        popoverScope.$on('tooltip.hide', function() {\n            popoverScope.popupModel.groupResults = [];\n            popoverScope.popupModel.filter = '';\n\n            if (popoverScope.popupModel.added) {\n                popoverScope.popupModel.added = false;\n            } else {\n                if (cancelledCallback) {\n                    // Run callback in parent scope of directive\n                    cancelledCallback($scope.$parent);\n                }\n            }\n        });\n\n    };\n    return directive;\n}]);\n\nflowableModule.directive('tabControl', ['$compile', '$http', '$templateCache', function($compile, $http, $templateCache) {\n\n        var updateTemplate = function($scope, element, attributes) {\n            if(!$scope.activeTemplate || $scope.activeTemplate != $scope.activeTab.id) {\n                // Check if current loaded template is still the right one\n                var contentDiv = $(element.children()[1]);\n\n                var childScope = angular.element(element.children()[1]).scope();\n                if($scope.activeTemplate && childScope != $scope) {\n                    // Child-scope created by the included element, should be destroyed\n                    childScope.$destroy();\n                }\n\n                if($scope.activeTab && $scope.activeTab.templateUrl) {\n                    // Load the HTML-fragment or get from cache\n                    var loader = $http.get($scope.activeTab.templateUrl, {cache: $templateCache});\n                    var promise = loader.success(function(html) {\n                        contentDiv.html(html);\n                    }).then(function (response) {\n                        $scope.activeTemplate = $scope.activeTab.id;\n                        contentDiv.replaceWith($compile(contentDiv.html())($scope));\n                    });\n                } else {\n                    // No templates are being used, no need to use the contentDiv for this tab, clear it\n                    contentDiv.empty();\n                }\n            }\n        };\n\n        var directive = {};\n        directive.restrict = 'A';\n        directive.replace = true;\n        directive.transclude = true;\n        directive.template = '<div><div class=\"clearfix\"><ul class=\"tabs clearfix\">' +\n            '<li ng-repeat=\"tab in tabs\" ng-class=\"{\\'active\\': tab.id == activeTab.id}\"><a ng-click=\"tabClicked(tab)\">{{tab.title && (tab.title | translate) || (tab.name | translate)}}</a></li>' +\n            '</ul></div>' +\n            '<div></div>' +\n            '</div>';\n\n        directive.scope = {\n            possibleTabs : \"=tabControl\",\n            model: \"=model\",\n            activeTabReference: \"=activeTab\"\n        };\n\n\n        directive.controller = ['$scope', '$element', function($scope, $element) {\n\n            $scope.refreshTabs = function() {\n                var tabs = [];\n                for(var i=0; i < $scope.possibleTabs.length; i++) {\n                    var tab = $scope.possibleTabs[i];\n                    if(!tab.hide) {\n                        tabs.push(tab);\n                    }\n                }\n                $scope.tabs = tabs;\n            };\n\n            $scope.$watch('possibleTabs', function() {\n                $scope.refreshTabs();\n            }, true);\n\n            $scope.$watch('activeTabReference', function(newValue, oldValue) {\n                if(!$scope.activeTab || $scope.activeTab.id != newValue) {\n                    // Active tab ID changed from outside of the directive controller, need to switch to the\n                    // right tab within this scope\n                    var newTab = $scope.findTab(newValue);\n                    if(newTab) {\n                        $scope.tabClicked(newTab);\n                    }\n                }\n            });\n\n            $scope.findTab = function(tabId) {\n                if($scope.possibleTabs) {\n                    for(var i=0; i< $scope.possibleTabs.length; i++) {\n                        if($scope.possibleTabs[i].id == tabId) {\n                            return $scope.possibleTabs[i];\n                        }\n                    }\n                }\n                return undefined;\n            };\n\n            $scope.tabClicked = function(tab) {\n                if (tab.hide) {\n                    tab.hide = false;\n                    $scope.refreshTabs();\n                }\n                $scope.activeTab = tab;\n                if (tab) {\n                    $scope.activeTabReference = tab.id;\n                } else {\n                    $scope.activeTabReference = undefined;\n                }\n                updateTemplate($scope, $element);\n            };\n\n            $scope.refreshTabs();\n\n            if($scope.tabs && $scope.tabs.length > 0) {\n                if($scope.activeTabReference) {\n                    $scope.activeTab = $scope.findTab($scope.activeTabReference);\n                }\n\n                if(!$scope.activeTab) {\n                    // Revert to the first tab, if no tab is forced to be shown first\n                    $scope.activeTab = $scope.tabs[0];\n                }\n                $scope.tabClicked($scope.activeTab);\n            }\n        }];\n\n        directive.link = updateTemplate;\n\n        return directive;\n    }]);\n\n/**\n * Directive that calls the function present in the toggle-dragover attribute with a single parameter (over) when\n * dragging over the element has started (over = true) or ended (over = false)\n */\nflowableModule\n    .directive('toggleDragover', [\"$document\", \"$parse\", function ($document, $parse) {\n        var linkFunction = function ($scope, $element, $attributes) {\n\n\n            var toggleFunction = $attributes.toggleDragover;\n            var callback = $parse(toggleFunction);\n\n            var el = $element[0];\n\n            el.addEventListener('dragenter',function(e) {\n                    $scope.$apply(function() {\n                        callback($scope, {'over': true});\n                    });\n                    return false;\n                },\n                false\n            );\n\n            el.addEventListener('dragleave', function(e) {\n                    $scope.$apply(function() {\n                        callback($scope, {'over': false});\n                    });\n                    return false;\n                },\n                false\n            );\n        };\n\n        return( linkFunction );\n    }]);\n\nflowableModule.directive('editInPlace', function () {\n    return {\n        restrict: 'E',\n        scope: {\n            value: '='\n        },\n        template: '<span ng-click=\"edit()\" ng-bind=\"value\"></span><span class=\"glyphicon glyphicon-pencil edit-in-place-icon\"></span><input ng-model=\"value\" class=\"inline-edit-value form-control\" ng-blur=\"stopEdit()\" custom-keys enter-pressed=\"stopEdit()\">',\n        link: function ($scope, element, attrs) {\n\n            var iconElement = angular.element(element.children()[1]);\n            var inputElement = angular.element(element.children()[2]);\n\n            // This directive should have a set class so we can style it.\n            element.addClass('edit-in-place');\n\n            // Initially, we're not editing.\n            $scope.editing = false;\n\n            // ng-click handler to activate edit-in-place\n            $scope.edit = function () {\n                $scope.editing = true;\n\n                // We control display through a class on the directive itself. See the CSS.\n                element.addClass('active');\n\n                // And we must focus the element.\n                // `angular.element()` provides a chainable array, like jQuery so to access a native DOM function,\n                // we have to reference the first element in the array.\n                inputElement[0].focus();\n            };\n\n            $scope.stopEdit = function() {\n                $scope.editing = false;\n                element.removeClass('active');\n            };\n\n//            // When we leave the input, we're done editing.\n//            inputElement.prop('onblur', function () {\n//                console.log('ONBLUR');\n//                $scope.editing = false;\n//                element.removeClass('active');\n//            });\n        }\n    };\n});\n\n\n/* UTILITY METHODS */\n\n/**\n * This creates a modal window that auto closes on route change.\n * By default, this is NOT the case, and leads to some funny behaviour.\n *\n * Use this method vs the default $modal({myJson}) approach\n */\nvar _internalCreateModal = function(modalConfig, $modal, $scope) {\n\n    if ($scope !== null && $scope !== undefined) {\n        $scope.modal = $modal(modalConfig);\n\n        $scope.$on('$routeChangeStart', function () {\n            if ($scope.modal) {\n                $scope.modal.hide();\n            }\n        });\n\n        return $scope.modal;\n    } else {\n        return $modal(modalConfig);\n    }\n\n};\n\nflowableModule.\n    directive('numberInputCheck', function() {\n\n        return {\n            require: 'ngModel',\n            link: function(scope, element, attrs, modelCtrl) {\n\n                modelCtrl.$parsers.push(function (inputValue) {\n\n                    var transformedInput;\n                    if (inputValue && inputValue.indexOf('-') == 0) {\n                        transformedInput = inputValue.substr(1).replace(/([^0-9])/g, '');\n                        transformedInput = '-' + transformedInput;\n                    } else {\n                        transformedInput = inputValue.replace(/([^0-9])/g, '');\n                    }\n\n                    if (transformedInput != inputValue) {\n                        modelCtrl.$setViewValue(transformedInput);\n                        modelCtrl.$render();\n                    }\n\n                    return transformedInput;\n                });\n            }\n        };\n    });\n"
  },
  {
    "path": "flowable-ui-web/idm/scripts/common/providers-config.js",
    "content": "/* 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 * Configure the HTTP provider such that no caching happens when fetching\n * a resource using $http.\n */\nflowableModule.config(['$httpProvider', function($httpProvider) {\n\n    if (!$httpProvider.defaults.headers.get) {\n        $httpProvider.defaults.headers.get = {};\n    }\n\n    $httpProvider.defaults.headers.get['Cache-Control'] = 'no-cache, no-store, must-revalidate';\n    $httpProvider.defaults.headers.get['Pragma'] = 'no-cache';\n    $httpProvider.defaults.headers.get['Expires'] = '0';\n\n}]);"
  },
  {
    "path": "flowable-ui-web/idm/scripts/common/services/authentication-service.js",
    "content": "/* 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'use strict';\n\n/**\n * @license HTTP Auth Interceptor Module for AngularJS\n * (c) 2012 Witold Szczerba\n * License: MIT\n */\n(function () {\n    angular.module('http-auth-interceptor', ['http-auth-interceptor-buffer'])\n\n        .factory('authService', ['$rootScope','httpBuffer', function($rootScope, httpBuffer) {\n            return {\n                /**\n                 * Call this function to indicate that authentication was successfull and trigger a\n                 * retry of all deferred requests.\n                 * @param data an optional argument to pass on to $broadcast which may be useful for\n                 * example if you need to pass through details of the user that was logged in\n                 */\n                loginConfirmed: function(data, configUpdater) {\n                    var updater = configUpdater || function(config) {return config;};\n                    $rootScope.$broadcast('event:auth-loginConfirmed', data);\n                    httpBuffer.retryAll(updater);\n                },\n\n                /**\n                 * Call this function to indicate that authentication should not proceed.\n                 * All deferred requests will be abandoned or rejected (if reason is provided).\n                 * @param data an optional argument to pass on to $broadcast.\n                 * @param reason if provided, the requests are rejected; abandoned otherwise.\n                 */\n                loginCancelled: function(data, reason) {\n                    httpBuffer.rejectAll(reason);\n                    $rootScope.$broadcast('event:auth-loginCancelled', data);\n                }\n            };\n        }])\n\n        /**\n         * $http interceptor.\n         * On 401 response (without 'ignoreAuthModule' option) stores the request\n         * and broadcasts 'event:angular-auth-loginRequired'.\n         */\n        .config(['$httpProvider', function($httpProvider) {\n            var interceptor = ['$rootScope', '$q', 'httpBuffer', '$translate', function($rootScope, $q, httpBuffer, $translate) {\n                return {\n                    responseError: function(response) {\n                        if ( (response.status === 401 || response.status === 403) && !response.config.ignoreAuthModule) {\n                            $rootScope.invalidCredentials = true;\n                            var deferred = $q.defer();\n                            httpBuffer.append(response.config, deferred);\n                            $rootScope.$broadcast('event:auth-loginRequired', response);\n                            return deferred.promise;\n                        } else if (response.status === 401) {\n                            $rootScope.invalidCredentials = true;\n                        }\n\n                        if(response.status >= 500 && response.status <= 599 && response.config && !response.config.ignoreErrors) {\n                            if(response.data && response.data.messageKey) {\n                                // Use message key to translate error\n                                $rootScope.addAlertPromise($translate(response.data.messageKey), 'error');\n                            } else if(response.data && response.data.message) {\n                                // Extract error-message\n                                $rootScope.addAlert(response.data.message, 'error');\n                            } else {\n                                // Use default error-message\n                                $rootScope.addAlertPromise($translate('GENERAL.ERROR.GENERIC'), 'error');\n                            }\n                        }\n\n                        // otherwise, default behaviour\n                        return $q.reject(response);\n                    }\n                };\n\n            }];\n\n            $httpProvider.interceptors.push(interceptor);\n        }]);\n\n    /**\n     * Private module, a utility, required internally by 'http-auth-interceptor'.\n     */\n    angular.module('http-auth-interceptor-buffer', [])\n\n        .factory('httpBuffer', ['$injector', function($injector) {\n            /** Holds all the requests, so they can be re-requested in future. */\n            var buffer = [];\n\n            /** Service initialized later because of circular dependency problem. */\n            var $http;\n\n            function retryHttpRequest(config, deferred) {\n                function successCallback(response) {\n                    deferred.resolve(response);\n                }\n                function errorCallback(response) {\n                    deferred.reject(response);\n                }\n                $http = $http || $injector.get('$http');\n                $http(config).then(successCallback, errorCallback);\n            }\n\n            return {\n                /**\n                 * Appends HTTP request configuration object with deferred response attached to buffer.\n                 */\n                append: function(config, deferred) {\n                    buffer.push({\n                        config: config,\n                        deferred: deferred\n                    });\n                },\n\n                /**\n                 * Abandon or reject (if reason provided) all the buffered requests.\n                 */\n                rejectAll: function(reason) {\n                    if (reason) {\n                        for (var i = 0; i < buffer.length; ++i) {\n                            buffer[i].deferred.reject(reason);\n                        }\n                    }\n                    buffer = [];\n                },\n\n                /**\n                 * Retries all the buffered requests clears the buffer.\n                 */\n                retryAll: function(updater) {\n                    for (var i = 0; i < buffer.length; ++i) {\n                        retryHttpRequest(updater(buffer[i].config), buffer[i].deferred);\n                    }\n                    buffer = [];\n                }\n            };\n        }]);\n})();\n/* Services */\n\n// Add authentication factories\nflowableApp.factory('AuthenticationSharedService', ['$rootScope', '$http', 'authService', '$q', '$location', '$window',\n    function ($rootScope, $http, authService, $q, $location, $window) {\n      return {\n        authenticate: function() {\n          var deferred = $q.defer();\n          $http.get(FLOWABLE.CONFIG.contextRoot + '/app/rest/authenticate', {ignoreErrors: true, ignoreAuthModule: 'ignoreAuthModule'})\n              .success(function (data, status, headers, config) {\n\n                  var redirectOnAuthSuccess = $location.search().redirectOnAuthSuccess;\n                  if (!redirectOnAuthSuccess) {\n                    var authUrl = FLOWABLE.CONFIG.contextRoot + '/app/rest/account';\n                    $http.get(authUrl)\n                        .success(function (data, status, headers, config) {\n                            $rootScope.account = data;\n                            $rootScope.invalidCredentials = false;\n                            $rootScope.$broadcast('event:auth-authConfirmed');\n\n                            deferred.resolve();\n                        })\n                        .error(function(data, status, headers, config) {\n                            // Reject promise and broadcast login required event\n                            deferred.reject(data);\n                            $rootScope.$broadcast('event:auth-loginRequired');\n                        });\n                  } else {\n                      $rootScope.$broadcast('event:auth-authConfirmed');\n                      deferred.resolve();\n                  }\n              })\n              .error(function(data, status, headers, config) {\n                  // Reject promise and broadcast login required event\n                  deferred.reject(data);\n                  $rootScope.$broadcast('event:auth-loginRequired');\n              });\n\n          return deferred.promise;\n        },\n          \n        login: function (param) {\n            var data =\"j_username=\" + encodeURIComponent(param.username) +\"&j_password=\" + encodeURIComponent(param.password) +\"&_spring_security_remember_me=true&submit=Login\";\n            $http.post(FLOWABLE.CONFIG.contextRoot + '/app/authentication', data, {\n                headers: {\n                    \"Content-Type\": \"application/x-www-form-urlencoded\"\n                },\n                ignoreAuthModule: 'ignoreAuthModule'\n                \n            }).success(function (data, status, headers, config) {\n                $rootScope.authenticationError = false;\n\n                if (param.success){\n                    param.success(data, status, headers, config);\n                }\n                authService.loginConfirmed();\n                \n            }).error(function (data, status, headers, config) {\n                $rootScope.$broadcast('event:auth-loginFailed');\n                if(param.error){\n                    param.error(data, status, headers, config);\n                }\n            });\n        },\n        logout: function () {\n            $rootScope.authenticated = false;\n            $rootScope.authenticationError = false;\n            $http.get(FLOWABLE.CONFIG.contextRoot + '/app/logout')\n                .success(function (data, status, headers, config) {\n                    $rootScope.login = null;\n                    $rootScope.authenticated = false;\n                    authService.loginCancelled({isFromLogout: true});\n                });\n        }\n\n      };\n    }]);\n"
  },
  {
    "path": "flowable-ui-web/idm/scripts/common/services/group-service.js",
    "content": "/* 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'use strict';\n\n// User service\nflowableModule.service('GroupService', ['$http', '$q',\n    function ($http, $q) {\n\n        var httpAsPromise = function(options) {\n            var deferred = $q.defer();\n            $http(options).\n                success(function (response, status, headers, config) {\n                    deferred.resolve(response);\n                })\n                .error(function (response, status, headers, config) {\n                    deferred.reject(response);\n                });\n            return deferred.promise;\n        };\n\n        this.getFilteredGroups = function(filterText, group, tenantId) {\n\n            var params = {};\n\n            if (filterText !== null && filterText !== undefined) {\n                params.filter = filterText;\n            }\n            \n            if (group && group.id) {\n                params.groupId = group.id;\n            }\n\n            return httpAsPromise(\n                {\n                    method: 'GET',\n                    url: FLOWABLE.CONFIG.contextRoot + '/app/rest/admin/groups',\n                    params: params\n                }\n            )\n        };\n    }]);\n"
  },
  {
    "path": "flowable-ui-web/idm/scripts/common/services/recursion-helper.js",
    "content": "/* 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'use strict';\n\n// Recursion Helper service, makes it possible to use nested directives of the same type\nflowableModule.factory('RecursionHelper', ['$compile', function($compile){\n    return {\n        /**\n         * Manually compiles the element, fixing the recursion loop.\n         * @param element\n         * @param [link] A post-link function, or an object with function(s) registered via pre and post properties.\n         * @returns An object containing the linking functions.\n         */\n        compile: function(element, link){\n            // Normalize the link parameter\n            if(angular.isFunction(link)){\n                link = { post: link };\n            }\n\n            // Break the recursion loop by removing the contents\n            var contents = element.contents().remove();\n            var compiledContents;\n            return {\n                pre: (link && link.pre) ? link.pre : null,\n                /**\n                 * Compiles and re-adds the contents\n                 */\n                post: function(scope, element){\n                    // Compile the contents\n                    if(!compiledContents){\n                        compiledContents = $compile(contents);\n                    }\n                    // Re-add the compiled contents to the element\n                    compiledContents(scope, function(clone){\n                        element.append(clone);\n                    });\n\n                    // Call the post-linking function, if any\n                    if(link && link.post){\n                        link.post.apply(null, arguments);\n                    }\n                }\n            };\n        }\n    };\n}]);"
  },
  {
    "path": "flowable-ui-web/idm/scripts/common/services/resource-service.js",
    "content": "/* 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'use strict';\n\n// User service\nflowableModule.service('ResourceService', ['$http', '$q', 'appResourceRoot',\n    function ($http, $q, appResourceRoot) {\n\n        var loadedResources = {};\n\n        function loadStylesheet(relativeUrl, cache)\n        {\n            var url = appResourceRoot + relativeUrl;\n            if (!cache || !loadedResources[url])\n            {\n                if (cache) {\n                    loadedResources[url] = true;\n                }\n                if (document.createStyleSheet)\n                {\n                    try\n                    {\n                        document.createStyleSheet();\n                    } catch (e) { }\n                }\n                else {\n                    var link = document.createElement(\"link\");\n                    link.rel = \"stylesheet\";\n                    link.type = \"text/css\";\n                    link.media = \"all\";\n                    link.href = url;\n                    document.getElementsByTagName(\"head\")[0].appendChild(link);\n                }\n            }\n        }\n\n        function loadScript(relativeUrl, callback, cache)\n        {\n            var url = appResourceRoot + relativeUrl;\n            if (cache && loadedResources[url] && callback)\n            {\n                callback();\n            }\n            else\n            {\n                if (cache) {\n                    loadedResources[url] = true;\n                }\n\n                // Insert the node so it gets loaded\n                var script = document.createElement(\"script\");\n                script.type=\"text/javascript\";\n                script.src = url;\n\n                if (callback) {\n                    var done = false;\n\n                    // Attach handlers for all browsers\n                    script.onload = script.onreadystatechange = function()\n                    {\n                        if (!done && (!this.readyState || this.readyState == \"loaded\" || this.readyState == \"complete\"))\n                        {\n                            done = true;\n                            callback();\n                        }\n                    };\n                }\n                var el = document.getElementsByTagName(\"head\")[0];\n                el.appendChild(script);\n            }\n        }\n\n        function loadScripts(relativeUrls, callback, cache)\n        {\n            function loadNext()\n            {\n                var relativeUrl = relativeUrls.shift();\n                if (relativeUrl)\n                {\n                    loadScript.call(this, relativeUrl, loadNext.bind(this), cache);\n                }\n                else\n                {\n                    if (callback)\n                    {\n                        callback();\n                    }\n                }\n            }\n            loadNext.call(this);\n        }\n\n        function loadFromHtml(url, callback, cache)\n        {\n            $http.get(url).success(function(responseText)\n            {\n                var xmlDoc;\n                if (window.DOMParser)\n                {\n                    var parser = new DOMParser();\n                    xmlDoc = parser.parseFromString(responseText, \"text/xml\");\n                }\n                else // Internet Explorer\n                {\n                    xmlDoc = new ActiveXObject(\"Microsoft.XMLDOM\");\n                    xmlDoc.async = false;\n                    xmlDoc.loadXML(responseText);\n                }\n                var resources = xmlDoc.getElementsByTagName(\"link\");\n                var resourceUrl;\n                var resourceUrls = [];\n                for (var i = 0, il = resources.length; i < il; i++)\n                {\n                    resourceUrl = resources[i].getAttribute(\"href\");\n                    if (resourceUrl)\n                    {\n                        loadStylesheet(resourceUrl, cache);\n                    }\n                }\n                resources = xmlDoc.getElementsByTagName(\"script\");\n                for (i = 0, il = resources.length; i < il; i++)\n                {\n                    resourceUrl = resources[i].getAttribute(\"src\");\n                    if (resourceUrl)\n                    {\n                        resourceUrls.push(resourceUrl);\n                    }\n                }\n                loadScripts(resourceUrls, callback, cache);\n            });\n        }\n\n        this.loadFromHtml = loadFromHtml;\n        this.loadScript = loadScript;\n        this.loadStylesheet = loadStylesheet;\n    }]);\n"
  },
  {
    "path": "flowable-ui-web/idm/scripts/common/services/user-service.js",
    "content": "/* 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'use strict';\n\n// User service\nflowableModule.service('UserService', ['$http', '$q',\n    function ($http, $q) {\n\n        var httpAsPromise = function(options) {\n            var deferred = $q.defer();\n            $http(options).\n                success(function (response, status, headers, config) {\n                    deferred.resolve(response);\n                })\n                .error(function (response, status, headers, config) {\n                    deferred.reject(response);\n                });\n            return deferred.promise;\n        };\n\n        /*\n         * Filter users based on a filter text, in the context of workflow: for tasks, processes, etc.\n         */\n        this.getFilteredUsers = function (filterText, taskId, processInstanceId, tenantId, group) {\n            var params = {};\n            if (typeof filterText === 'string') {\n               params.filter = filterText;\n            }\n            else {\n               // Could be i.e. { email: 'user@domain.com' } or { externalId: 'externalUserId' }\n               params = filterText;\n            }\n            if(taskId) {\n                params.excludeTaskId = taskId;\n            }\n            if (processInstanceId) {\n                params.excludeProcessId = processInstanceId;\n            }\n\n            if (group && group.id) {\n                params.groupId = group.id;\n            }\n\n            return httpAsPromise({\n                method: 'GET',\n                url: FLOWABLE.CONFIG.contextRoot + '/app/rest/workflow-users',\n                params: params\n            });\n        };\n\n        /*\n         * Filter users based on a filter text, in the context of IDM: use no context (contrary to the getFilteredUsers method).\n         */\n        this.getFilteredUsersStrict = function(filterText, tenantId, group) {\n\n            var params = {};\n\n            params.status = 'active';\n\n            if (filterText !== null && filterText !== undefined) {\n                params.filter = filterText;\n            }\n\n            if (group && group.id) {\n                params.groupId = group.id;\n            }\n\n            return httpAsPromise(\n                {\n                    method: 'GET',\n                    url: FLOWABLE.CONFIG.contextRoot + '/app/rest/admin/users',\n                    params: params\n                }\n            )\n        };\n\n    }]);\n"
  },
  {
    "path": "flowable-ui-web/idm/scripts/controllers.js",
    "content": "/* 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 */\nflowableApp.controller('LoginController', ['$scope', '$location', 'AuthenticationSharedService', '$timeout',\n    function ($scope, $location, AuthenticationSharedService, $timeout) {\n\n        $scope.model = {\n            loading: false\n        };\n        $scope.login = function () {\n\n            $scope.model.loading = true;\n\n            jQuery('#username').trigger('change');\n            jQuery('#password').trigger('change');\n\n            $timeout(function() {\n                AuthenticationSharedService.login({\n                    username: $scope.username,\n                    password: $scope.password,\n                    success: function () {\n                        $scope.model.loading = false;\n                    },\n                    error: function() {\n                        $scope.model.loading = false;\n                    }\n                });\n            });\n\n\n        };\n    }]\n);"
  },
  {
    "path": "flowable-ui-web/idm/scripts/idm-app.js",
    "content": "/* 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'use strict';\n\nvar flowableApp = angular.module('flowableApp', [\n  \t'http-auth-interceptor',\n  \t'ngCookies',\n  \t'ngResource',\n  \t'ngSanitize',\n  \t'ngRoute',\n  \t'mgcrea.ngStrap',\n  \t'ngAnimate',\n  \t'ngFileUpload',\n  \t'pascalprecht.translate',\n  \t'ui.grid',\n    'ui.grid.edit',\n    'ui.grid.selection',\n    'ui.grid.autoResize',\n    'ui.grid.cellNav'\n]);\n\nvar flowableModule = flowableApp;\nflowableApp\n  // Initialize routes\n  .config(['$provide', '$routeProvider', '$selectProvider', '$datepickerProvider', '$translateProvider', function ($provide, $routeProvider, $selectProvider, $datepickerProvider, $translateProvider) {\n\n    var appName = '';\n    $provide.value('appName', appName);\n\n    var ctx = FLOWABLE.CONFIG.webContextRoot;\n    var appResourceRoot = ctx + (ctx && ctx.charAt(ctx.length - 1) !== '/' ? '/' : '');\n    $provide.value('appResourceRoot', appResourceRoot);\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    // Override carets for bs-datepicker directive\n    angular.extend($datepickerProvider.defaults, {\n        iconLeft: 'icon icon-caret-left',\n        iconRight: 'icon icon-caret-right'\n    });\n\n    /*\n     * Route resolver for all authenticated routes\n     */\n    var authRouteResolver = ['$rootScope', 'AuthenticationSharedService', function($rootScope, AuthenticationSharedService) {\n\n        if(!$rootScope.authenticated) {\n          // Return auth-promise. On success, the promise resolves and user is assumed authenticated from now on. If\n          // promise is rejected, route will not be followed (no unneeded HTTP-calls will be done, which case a 401 in the end, anyway)\n          return AuthenticationSharedService.authenticate();\n\n        } else {\n          // Authentication done on rootscope, no need to call service again. Any unauthenticated access to REST will result in\n          // a 401 and will redirect to login anyway. Done to prevent additional call to authenticate every route-change\n          $rootScope.authenticated = true;\n          return true;\n        }\n    }];\n\n    /*\n     * Route resolver for all unauthenticated routes\n     */\n    var unauthRouteResolver = ['$rootScope', function($rootScope) {\n      $rootScope.authenticationChecked = true;\n    }];\n\n    $routeProvider\n        .when('/login', {\n            templateUrl: 'views/login.html',\n            controller: 'LoginController',\n            resolve: {\n                verify: unauthRouteResolver\n            }\n        })\n        .when('/user-mgmt', {\n            controller: 'IdmUserMgmtController',\n            templateUrl: appResourceRoot + 'views/idm-user-mgmt.html',\n            resolve: {\n                verify: authRouteResolver\n            }\n        })\n        .when('/group-mgmt', {\n            controller: 'GroupMgmtController',\n            templateUrl: appResourceRoot + 'views/idm-group-mgmt.html',\n            resolve: {\n                verify: authRouteResolver\n            }\n        })\n        .when('/privilege-mgmt', {\n            controller: 'PrivilegeMgmtController',\n            templateUrl: appResourceRoot + 'views/idm-privilege-mgmt.html',\n            resolve: {\n                verify: authRouteResolver\n            }\n        })\n        .when('/logout', {\n            templateUrl: appResourceRoot + 'views/empty.html',\n            controller: 'LogoutController'\n        })\n        .otherwise({\n            redirectTo: FLOWABLE.CONFIG.appDefaultRoute || '/user-mgmt'\n        });\n    \n        // Initialize angular-translate\n        $translateProvider.useStaticFilesLoader({\n            prefix: './i18n/',\n            suffix: '.json'\n        })\n        /*\n            This can be used to map multiple browser language keys to a\n            angular translate language key.\n        */\n        // .registerAvailableLanguageKeys(['en'], {\n        //     'en-*': 'en'\n        // })\n        .useSanitizeValueStrategy('escapeParameters')\n        .uniformLanguageTag('bcp47')\n        .determinePreferredLanguage();\n    }])\n    .run(['$rootScope', function($rootScope) {\n        $rootScope.$on( \"$routeChangeStart\", function(event, next, current) {\n            if (next !== null && next !== undefined) {\n                $rootScope.onLogin = next.templateUrl === 'views/login.html';\n            }\n        });\n    }])\n    .run(['$rootScope', '$timeout', '$translate', '$location', '$window', 'AuthenticationSharedService',\n        function($rootScope, $timeout, $translate, $location, $window, AuthenticationSharedService) {\n\n            // set angular translate fallback language\n            $translate.fallbackLanguage(['en']);\n\n            // setting Moment-JS (global) locale\n            if (FLOWABLE.CONFIG.datesLocalization) {\n                moment.locale($translate.proposedLanguage());\n            }\n\n            // Common model (eg selected tenant id)\n            $rootScope.common = {};\n\n            $rootScope.webRootUrl = function() {\n                return FLOWABLE.CONFIG.webContextRoot;\n            };\n\n            $rootScope.restRootUrl = function() {\n                return FLOWABLE.CONFIG.contextRoot;\n            };\n\n            // Needed for auto-height\n            $rootScope.window = {};\n            var updateWindowSize = function() {\n                $rootScope.window.width = $window.innerWidth;\n                $rootScope.window.height  = $window.innerHeight;\n            };\n\n            // Window resize hook\n            angular.element($window).bind('resize', function() {\n                $rootScope.$apply(updateWindowSize());\n            });\n\n            $rootScope.$watch('window.forceRefresh', function(newValue) {\n                if(newValue) {\n                    $timeout(function() {\n                        updateWindowSize();\n                        $rootScope.window.forceRefresh = false;\n                    });\n                }\n            });\n\n            updateWindowSize();\n\n            // Main navigation depends on the account being fetched\n            $rootScope.$watch('account', function() {\n                $rootScope.mainNavigation = [\n                    {\n                        id: 'userMgmt',\n                        title: 'IDM.GENERAL.NAVIGATION.USER-MGMT',\n                        path: '/user-mgmt'\n                    },\n                    {\n                        id: 'groupMgmt',\n                        title: 'IDM.GENERAL.NAVIGATION.GROUP-MGMT',\n                        path: '/group-mgmt'\n                    },\n                    {\n                        id: 'privilegeMgmt',\n                        title: 'IDM.GENERAL.NAVIGATION.PRIVILEGE-MGMT',\n                        path: '/privilege-mgmt'\n                    }\n                ];\n\n\n                /*\n                 * Set the current main page, using the page object. If the page is already active,\n                 * this is a no-op.\n                 */\n                $rootScope.setMainPage = function(mainPage) {\n                    $rootScope.mainPage = mainPage;\n                    $location.path($rootScope.mainPage.path);\n                };\n\n                /*\n                 * Set the current main page, using the page ID. If the page is already active,\n                 * this is a no-op.\n                 */\n                $rootScope.setMainPageById = function(mainPageId) {\n                    for (var i=0; i<$rootScope.mainNavigation.length; i++) {\n                        if (mainPageId == $rootScope.mainNavigation[i].id) {\n                            $rootScope.mainPage = $rootScope.mainNavigation[i];\n                            break;\n                        }\n                    }\n                };\n            });\n        }\n    ])\n    .run(['$rootScope', '$timeout', '$translate', '$location', '$http', '$window', '$popover', 'appResourceRoot',\n        function($rootScope, $timeout, $translate, $location, $http, $window, $popover, appResourceRoot) {\n\n        $rootScope.appResourceRoot = appResourceRoot;\n\n        // Alerts\n        $rootScope.alerts = {\n            queue: []\n        };\n        \n        $rootScope.webRootUrl = function() {\n            return FLOWABLE.CONFIG.webContextRoot;\n        };\n        \n        $rootScope.restRootUrl = function() {\n            return FLOWABLE.CONFIG.contextRoot;\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     .run(['$rootScope', '$location', '$window', 'AuthenticationSharedService', '$translate', '$modal',\n        function($rootScope, $location, $window, AuthenticationSharedService, $translate, $modal) {\n\n        /* Auto-height */\n\n        $rootScope.window = {};\n        var updateWindowSize = function() {\n            $rootScope.window.width = $window.innerWidth;\n            $rootScope.window.height  = $window.innerHeight;\n        };\n\n        // Window resize hook\n        angular.element($window).bind('resize', function() {\n            $rootScope.$apply(updateWindowSize());\n        });\n\n        $rootScope.$watch('window.forceRefresh', function(newValue) {\n            if(newValue) {\n                $timeout(function() {\n                    updateWindowSize();\n                    $rootScope.window.forceRefresh = false;\n                });\n            }\n        });\n\n        updateWindowSize();\n\n        $rootScope.logout = function() {\n            AuthenticationSharedService.logout();\n        };\n\n        // Call when the 401 response is returned by the client\n        $rootScope.$on('event:auth-loginRequired', function(rejection) {\n            $rootScope.authenticated = false;\n            $rootScope.authenticationChecked = true;\n            if (FLOWABLE.CONFIG.loginUrl) {\n                $window.location.href = FLOWABLE.CONFIG.loginUrl.replace(\"{url}\", $location.absUrl());\n                $window.reload();\n            }\n            else {\n                $location.path('/login').replace();\n            }\n        });\n\n        // Call when the user is authenticated\n        $rootScope.$on('event:auth-authConfirmed', function(event, data) {\n        \n            $rootScope.authenticated = true;\n            $rootScope.authenticationChecked = true;\n\n            var redirectUrl = $location.search().redirectUrl;\n            if (redirectUrl !== null && redirectUrl !== undefined && redirectUrl.length > 0) {\n                $window.location.href = redirectUrl;\n            } else {\n                var locationPath = $location.path();\n                if (locationPath == '' || locationPath == '#' || locationPath == '/login'\n                    || locationPath.indexOf('/account/activate/') >= 0 || locationPath.indexOf('/account/reset-password/') >= 0) {\n                      \n                    $location.path('/');\n                }\n            }\n        });\n\n        // Call when the user logs in\n        $rootScope.$on('event:auth-loginConfirmed', function() {\n            AuthenticationSharedService.authenticate();\n        });\n\n        // Call when the user logs out\n        $rootScope.$on('event:auth-loginCancelled', function() {\n            $rootScope.authenticated = false;\n            $location.path('/login');\n        });\n\n        // Call when login fails\n        $rootScope.$on('event:auth-loginFailed', function() {\n            $rootScope.addAlertPromise($translate('LOGIN.MESSAGES.ERROR.AUTHENTICATION'), 'error'); \n        });\n\n        $rootScope.backToLanding = function() {\n            var baseUrl = $location.absUrl();\n            var index = baseUrl.indexOf('/#');\n            if (index >= 0) {\n                baseUrl = baseUrl.substring(0, index);\n                baseUrl += '/';\n            }\n            $window.location.href = baseUrl;\n        };\n}])\n\t\n\t// 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": "flowable-ui-web/idm/scripts/idm-group-mgmt-controller.js",
    "content": "/* 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 */\nflowableApp.controller('GroupMgmtController', ['$rootScope', '$scope', '$translate', '$http', '$timeout','$location', '$modal', '$popover', 'IdmService',\n    function ($rootScope, $scope, $translate, $http, $timeout, $location, $modal, $popover, IdmService) {\n\n        var validUser = true;\n\n        $rootScope.setMainPageById('groupMgmt');\n\n        $scope.model = {\n            loading: true,\n            expanded: {}\n        };\n\n        $scope.showCreateGroupPopup = function() {\n            $scope.model.editedGroup  = {};\n            $scope.model.mode = 'create';\n            _internalCreateModal({\n                scope: $scope,\n                template: 'views/popup/idm-group-create.html',\n                show: true\n            }, $modal, $scope);\n        };\n\n        var fetchUserPage = function() {\n            $scope.model.loadingUsers = true;\n            IdmService.getUsersForGroup($scope.model.selectedGroup.id, $scope.model.userFilter ,$scope.model.userPage, $scope.model.pageSize).then(function(data) {\n                $scope.model.users = data;\n                $scope.model.moreUsers = $scope.model.selectedGroup.userCount > (($scope.model.userPage+1 ) * $scope.model.pageSize);\n                $scope.model.loadingUsers = false;\n            });\n        };\n\n        $scope.selectGroup = function(groupId) {\n            $scope.model.loadingGroup = true;\n            IdmService.getGroup(groupId).then(function (data) {\n                $scope.model.selectedGroup = data;\n\n                $scope.model.userPage = 0;\n                $scope.model.pageSize = 50;\n                fetchUserPage();\n\n                $scope.model.loadingGroup = false;\n            });\n        };\n\n        $scope.showPreviousUsers = function() {\n            $scope.model.userPage--;\n            fetchUserPage();\n        };\n\n        $scope.showNextUsers = function() {\n            $scope.model.userPage++;\n            fetchUserPage();\n        };\n\n        $scope.refreshDelayed = function() {\n            // If already waiting, another wait-cycle will be done\n            // after the current wait is over\n            if($scope.model.waiting) {\n                $scope.model.delayed = true;\n            } else {\n                $scope.scheduleDelayedRefresh();\n            }\n        };\n\n        $scope.scheduleDelayedRefresh = function() {\n            $scope.model.waiting = true;\n\n            $timeout(function() {\n                $scope.model.waiting = false;\n                if( $scope.model.delayed) {\n                    $scope.model.delayed = false;\n                    // Delay again\n                    $scope.scheduleDelayedRefresh();\n                } else {\n                    $scope.model.userPage = 0;\n                    fetchUserPage();\n                }\n            }, 100);\n        };\n\n        $scope.createGroup = function() {\n            $scope.model.loading = true;\n            IdmService.createGroup($scope.model.editedGroup).then(function (data) {\n                $scope.fetchGroups(data.id);\n                $scope.model.loading = false;\n            });\n        };\n\n        $scope.updateGroup = function() {\n            $scope.model.loadingGroup = true;\n            IdmService.updateGroup($scope.model.editedGroup.id, $scope.model.editedGroup).then(function (data) {\n                $scope.model.selectedGroup = data;\n\n                // Find the entry in the list on the left, and update its name\n                for (var i=0; i<$scope.model.groups.length; i++){\n                    if ($scope.model.groups[i].id === data.id) {\n                        $scope.model.groups[i].name = data.name;\n                    }\n                }\n\n                $scope.model.loadingGroup = false;\n            });\n        };\n\n        $scope.showDeleteGroupModal = function() {\n            _internalCreateModal({\n                scope: $scope,\n                template: 'views/popup/idm-delete-group.html',\n                show: true\n            }, $modal, $scope);\n        };\n\n        $scope.deleteGroup = function() {\n            $scope.model.loading = true;\n            IdmService.deleteGroup($scope.model.selectedGroup.id).then(function() {\n                $scope.model.loading = false;\n                clearSelection();\n                $scope.fetchGroups();\n            });\n        };\n\n        $scope.showActivateGroupModal = function() {\n            _internalCreateModal({\n                scope: $scope,\n                template: 'views/popup/idm-activate-group.html',\n                show: true\n            }, $modal, $scope);\n        };\n\n        $scope.activateGroup = function() {\n            $scope.model.loading = true;\n            IdmService.activateGroup($scope.model.selectedGroup.id).then(function() {\n                $scope.model.loading = false;\n                clearSelection();\n                $scope.fetchGroups();\n            });\n        };\n\n        // Clear any selected tenant\n        var clearSelection = function() {\n            delete $scope.model.groups;\n            delete $scope.model.selectedGroup;\n        };\n\n        $scope.showEditGroupModal = function() {\n            $scope.model.editedGroup  = $scope.model.selectedGroup;\n            $scope.model.mode = 'edit';\n            _internalCreateModal({\n                scope: $scope,\n                template: 'views/popup/idm-group-create.html',\n                show: true\n            }, $modal, $scope);\n        };\n\n        $scope.showRemoveMemberModal = function(user) {\n            $scope.model.userToRemove = user;\n            _internalCreateModal({\n                scope: $scope,\n                template: 'views/popup/idm-group-member-delete.html',\n                show: true\n            }, $modal, $scope);\n        };\n\n        $scope.deleteGroupMember = function() {\n            IdmService.deleteGroupMember($scope.model.selectedGroup.id, $scope.model.userToRemove.id).then(function(data) {\n                for (var i=0; i<$scope.model.users.data.length; i++) {\n                    if ($scope.model.users.data[i].id === $scope.model.userToRemove.id) {\n                        $scope.model.users.data.splice(i, 1);\n                        delete $scope.model.userToRemove;\n                        break;\n                    }\n                }\n                fetchUserPage();\n            });\n        };\n\n        $scope.addGroupMember = function(user) {\n            IdmService.addGroupMember($scope.model.selectedGroup.id, user.id).then(function() {\n                $scope.selectGroup($scope.model.selectedGroup.id, true);\n            });\n        };\n\n        // Load the groups\n        $scope.fetchGroups = function(groupIdToSelect) {\n            $scope.model.loading = true;\n            clearSelection();\n\n            IdmService.getFunctionalGroups().then(function(data) {\n                $scope.model.groups = data;\n\n                var groupIndex;\n                $scope.model.expanded = {};\n\n                // Select a group\n                if (groupIdToSelect) {\n                    $scope.selectGroup(groupIdToSelect);\n                }\n\n                // By default, open first level of groups\n                for (groupIndex = 0; groupIndex < data.length; groupIndex++) {\n                    $scope.model.expanded[data[groupIndex].id] = true;\n                }\n\n                $scope.model.loading = false;\n            });\n        };\n\n        if(validUser) {\n            $scope.fetchGroups();\n        }\n\n    }]);\n\n"
  },
  {
    "path": "flowable-ui-web/idm/scripts/idm-privilege-mgmt-controller.js",
    "content": "/* 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 */\nflowableApp.controller('PrivilegeMgmtController', ['$rootScope', '$scope', '$translate', '$http', '$timeout','$location', '$modal', '$popover', 'IdmService',\n    function ($rootScope, $scope, $translate, $http, $timeout, $location, $modal, $popover, IdmService) {\n\n        $rootScope.setMainPageById('privilegeMgmt');\n\n        $scope.model = {\n            loading: true,\n            loadingPrivilege: false,\n            expanded: {}\n        };\n\n        $scope.selectPrivilege = function(privilege) {\n            $scope.model.loadingPrivilege = true;\n            IdmService.getPrivilege(privilege.id).then(function(data) {\n                $scope.model.selectedPrivilege = data;\n                $scope.model.loadingPrivilege = false;\n            });\n        };\n\n        $scope.addUserPrivilege = function(user) {\n            IdmService.addUserPrivilege($scope.model.selectedPrivilege.id, user.id).then(function(data) {\n                $scope.selectPrivilege($scope.model.selectedPrivilege);\n            });\n        };\n\n        $scope.deleteUserPrivilege = function(user) {\n            IdmService.deleteUserPrivilege($scope.model.selectedPrivilege.id, user.id).then(function(data) {\n                $scope.selectPrivilege($scope.model.selectedPrivilege);\n            });\n        }\n\n        $scope.addGroupPrivilege = function(group) {\n            IdmService.addGroupPrivilege($scope.model.selectedPrivilege.id, group.id).then(function(data) {\n                $scope.selectPrivilege($scope.model.selectedPrivilege);\n            });\n        };\n\n        $scope.deleteGroupPrivilege = function(group) {\n            IdmService.deleteGroupPrivilege($scope.model.selectedPrivilege.id, group.id).then(function(data) {\n                $scope.selectPrivilege($scope.model.selectedPrivilege);\n            });\n        }\n\n        // Load privileges when page is loaded\n        IdmService.getPrivileges().then(function(data) {\n            $scope.model.privileges = data;\n            $scope.model.loading = false;\n         });\n\n    }]);\n\n    \n\n"
  },
  {
    "path": "flowable-ui-web/idm/scripts/idm-profile-mgmt-controller.js",
    "content": "/* 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 * Controller for profile mgmt\n */\nflowableApp.controller('IdmProfileMgmtController', ['$rootScope', '$scope', '$modal', 'IdmService', '$translate',\n    function ($rootScope, $scope, $modal, IdmService, $translate) {\n\n        $rootScope.setMainPageById('profile');\n\n        $scope.model = {\n            loading: true\n        };\n\n        $scope.showUploadPictureModal = function() {\n            _internalCreateModal({\n                scope: $scope,\n                template: 'views/popup/idm-profile-picture-upload.html',\n                show: true\n            }, $modal, $scope);\n        };\n\n        $scope.emailChanged = function() {\n            $scope.model.profile.emailErrorMessage = undefined;\n            if ($scope.model.profile.email !== null\n                && $scope.model.profile.email !== undefined\n                && $scope.model.profile.email !== '') {\n                $scope.model.loading = true;\n\n                IdmService.updateProfileDetails($scope.model.profile, function (response) {\n                    $scope.model.editingEmail = false;\n                    $scope.loadProfile(); // reload values from server\n                }, function (data, status) {\n                    $scope.model.loading = false;\n                    if (status === 409) {\n                        $scope.model.profile.emailErrorMessage = $translate.instant(data.message);\n                    }\n                });\n            } else {\n                // Reset if invalid value\n                $scope.model.profile.email = $scope.model.originalEmail;\n            }\n        };\n\n        $scope.firstNameChanged = function() {\n            $scope.model.loading = true;\n            IdmService.updateProfileDetails($scope.model.profile, function (response) {\n                $scope.model.editingFirstName = false;\n                $scope.model.loading = false;\n            });\n        };\n\n        $scope.lastNameChanged = function() {\n            $scope.model.loading = true;\n            IdmService.updateProfileDetails($scope.model.profile, function () {\n                $scope.model.editingLastName = false;\n                $scope.model.loading = false;\n            });\n        };\n\n        $scope.companyChanged = function() {\n            $scope.model.loading = true;\n            IdmService.updateProfileDetails($scope.model.profile, function () {\n                $scope.model.editingCompany = false;\n                $scope.model.loading = false;\n            });\n        };\n\n        $scope.showChangePasswordModal = function() {\n            $scope.model.changePassword = {};\n            _internalCreateModal({\n                scope: $scope,\n                template: 'views/popup/idm-change-password.html',\n                show: true\n            }, $modal, $scope);\n        };\n\n        // To fix cache\n        $scope.cacheBuster = function(force) {\n            if (!$scope.model.cacheBuster || force) {\n                $scope.model.cacheBuster = new Date().getTime();\n            } else {\n                return $scope.model.cacheBuster;\n            }\n        };\n\n        // Fetch profile when page is shown\n        $scope.loadProfile = function() {\n            IdmService.getProfile().then(function (profileData) {\n                $scope.model.originalEmail = profileData.email; // Storing it extra, so we're able to reset\n                $scope.model.profile = profileData;\n                $scope.model.loading = false;\n            });\n        };\n        $scope.loadProfile();\n\n    }]);\n\nflowableApp.\n    controller('UploadUserPictureController', ['$rootScope', '$scope', 'Upload', function ($rootScope, $scope, Upload) {\n\n        $scope.popup = {\n            loading: false\n        };\n\n        $scope.onFileSelect = function($files) {\n\n            $scope.popup.loading = true;\n\n            for (var i = 0; i < $files.length; i++) {\n                var file = $files[i];\n                Upload.upload({\n                    url: FLOWABLE.CONFIG.contextRoot + '/app/rest/admin/profile-picture',\n                    method: 'POST',\n                    file: file\n                }).progress(function(evt) {\n                    $scope.popup.uploadProgress = parseInt(100.0 * evt.loaded / evt.total);\n\n                }).success(function(data, status, headers, config) {\n                    $scope.popup.loading = false;\n                    $scope.$hide();\n                    $scope.cacheBuster(true);\n                    $scope.loadProfile();\n                }).error(function(data, status, headers, config) {\n\n                    if (data && data.message) {\n                        $scope.popup.errorMessage = data.message;\n                    }\n\n                    $scope.popup.error = true;\n                    $scope.popup.loading = false;\n                });\n            }\n        };\n\n        $scope.cancel = function () {\n            if(!$scope.popup.loading) {\n                $scope.$hide();\n            }\n        };\n\n    }]);\n\nflowableApp.\n    controller('IdmChangePasswordController', ['$rootScope', '$scope', 'IdmService', function ($rootScope, $scope, IdmService) {\n\n        $scope.isConfirmButtonDisabled = function() {\n            return !$scope.model.changePassword.originalPassword\n                || $scope.model.changePassword.originalPassword.length == 0\n                || !$scope.model.changePassword.newPassword\n                || $scope.model.changePassword.newPassword.length === 0\n                || !$scope.model.changePassword.newPassword2\n                || $scope.model.changePassword.newPassword2.length === 0\n                || $scope.model.changePassword.newPassword !== $scope.model.changePassword.newPassword2;\n        };\n\n        $scope.showPasswordsDontMatch = function() {\n            return $scope.model.changePassword.originalPassword\n                && $scope.model.changePassword.originalPassword.length > 0\n                && $scope.model.changePassword.newPassword\n                && $scope.model.changePassword.newPassword.length > 0\n                && $scope.model.changePassword.newPassword2\n                && $scope.model.changePassword.newPassword2.length > 0\n                && $scope.model.changePassword.newPassword !== $scope.model.changePassword.newPassword2;\n\n        };\n\n        $scope.changePassword = function() {\n            $scope.model.changePassword.error = false;\n            IdmService.changePassword($scope.model.changePassword.originalPassword,  $scope.model.changePassword.newPassword)\n                .then(function() {\n                    $scope.$hide();\n                }, function() {\n                    $scope.model.changePassword.error = true\n                });\n        };\n\n    }]);\n\n\n\n\n\n\n\n"
  },
  {
    "path": "flowable-ui-web/idm/scripts/idm-service.js",
    "content": "/* 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'use strict';\n\nangular.module('flowableApp').service('IdmService', ['$http', '$q', '$rootScope',\n    function ($http, $q, $rootScope) {\n\n        var httpAsPromise = function (options) {\n            var deferred = $q.defer();\n            $http(options).\n                success(function (response, status, headers, config) {\n                    deferred.resolve(response);\n                })\n                .error(function (response, status, headers, config) {\n                    deferred.reject(response);\n                });\n            return deferred.promise;\n        };\n\n        /*\n            PROFILE\n        */\n\n        this.getProfile = function () {\n            return httpAsPromise(\n                {\n                    method: 'GET',\n                    url: FLOWABLE.CONFIG.contextRoot + '/app/rest/admin/profile'\n                }\n            )\n        };\n\n        this.updateProfileDetails = function(userData, successCallback, errorCallback) {\n            var deferred = $q.defer();\n            $http({\n                method: 'POST',\n                url: FLOWABLE.CONFIG.contextRoot + '/app/rest/admin/profile',\n                data: userData\n            }).success(function (response, status, headers, config) {\n                if (successCallback) {\n                    successCallback(response);\n                }\n                deferred.resolve(response);\n            }).error(function (response, status, headers, config) {\n                if (errorCallback) {\n                    errorCallback(response, status);\n                }\n                deferred.reject(response);\n            });\n\n            var promise = deferred.promise;\n            return promise;\n        };\n\n        this.changePassword = function(oldPassword, newPassword) {\n            return httpAsPromise(\n                {\n                    method: 'POST',\n                    url: FLOWABLE.CONFIG.contextRoot + '/app/rest/admin/profile-password',\n                    data: {originalPassword: oldPassword, newPassword: newPassword}\n                }\n            )\n        };\n\n\n        /*\n            GROUPS\n        */\n\n        this.getGroups = function() {\n\n            var params = {};\n            return httpAsPromise(\n                {\n                    method: 'GET',\n                    url: FLOWABLE.CONFIG.contextRoot + '/app/rest/admin/groups',\n                    params: params\n                }\n            )\n        };\n\n        this.getFunctionalGroups = function() {\n\n            var params = {};\n            params.functional = 'true';\n\n            return httpAsPromise(\n                {\n                    method: 'GET',\n                    url: FLOWABLE.CONFIG.contextRoot + '/app/rest/admin/groups',\n                    params: params\n                }\n            )\n        };\n\n        this.getGroup = function (groupId, includeAllUsers) {\n\n            var params = {};\n            if (includeAllUsers !== null && includeAllUsers !== undefined) {\n                params.includeAllUsers = includeAllUsers;\n            }\n\n            return httpAsPromise(\n                {\n                    method: 'GET',\n                    url: FLOWABLE.CONFIG.contextRoot + '/app/rest/admin/groups/' + groupId,\n                    params: params\n                }\n            )\n        };\n\n        this.getUsersForGroup = function(groupId, filter, page, pageSize) {\n\n            var params = {};\n\n            if (filter !== null && filter !== undefined) {\n                params.filter = filter;\n            }\n\n            if (page !== null && page !== undefined) {\n                params.page = page;\n            }\n\n            if (pageSize !== null && pageSize !== undefined) {\n                params.pageSize = pageSize\n            }\n\n            return httpAsPromise(\n                {\n                    method: 'GET',\n                    url: FLOWABLE.CONFIG.contextRoot + '/app/rest/admin/groups/' + groupId + '/users',\n                    params: params\n                }\n            )\n\n        };\n\n        this.createGroup = function (createGroupData) {\n\n            return httpAsPromise(\n                {\n                    method: 'POST',\n                    url: FLOWABLE.CONFIG.contextRoot + '/app/rest/admin/groups',\n                    data: createGroupData\n                }\n            )\n        };\n\n\n        this.updateGroup = function (groupId, updatedGroupData) {\n\n            var data = {name: updatedGroupData.name};\n            return httpAsPromise(\n                {\n                    method: 'PUT',\n                    url: FLOWABLE.CONFIG.contextRoot + '/app/rest/admin/groups/' + groupId ,\n                    data: data\n                }\n            )\n        };\n\n        this.deleteGroup = function(groupId) {\n            return httpAsPromise(\n                {\n                    method: 'DELETE',\n                    url: FLOWABLE.CONFIG.contextRoot + '/app/rest/admin/groups/' + groupId\n                }\n            )\n        };\n\n        this.activateGroup = function(groupId) {\n            return httpAsPromise(\n                {\n                    method: 'POST',\n                    url: FLOWABLE.CONFIG.contextRoot + '/app/rest/admin/groups/' + groupId + '/action/activate'\n                }\n            )\n        };\n\n        this.deleteGroupMember = function(groupId, userId) {\n            return httpAsPromise(\n                {\n                    method: 'DELETE',\n                    url: FLOWABLE.CONFIG.contextRoot + '/app/rest/admin/groups/' + groupId + '/members/' + userId\n                }\n            )\n        };\n\n        this.addGroupMember = function(groupId, userId) {\n            return httpAsPromise(\n                {\n                    method: 'POST',\n                    url: FLOWABLE.CONFIG.contextRoot + '/app/rest/admin/groups/' + groupId + '/members/' + userId\n                }\n            )\n        };\n\n        this.getPrivileges = function() {\n            return httpAsPromise({\n                method: 'GET',\n                url: FLOWABLE.CONFIG.contextRoot + '/app/rest/admin/privileges'\n            })\n        };\n\n        this.getPrivilege = function(privilegeId) {\n            return httpAsPromise({\n                method: 'GET',\n                url: FLOWABLE.CONFIG.contextRoot + '/app/rest/admin/privileges/' + privilegeId\n            });\n        };\n\n        this.addUserPrivilege = function(privilegeId, userId) {\n            return httpAsPromise(\n                {\n                    method: 'POST',\n                    url: FLOWABLE.CONFIG.contextRoot + '/app/rest/admin/privileges/' + privilegeId + '/users',\n                    data: { userId : userId}\n                }\n            )\n        };\n\n        this.deleteUserPrivilege = function(privilegeId, userId) {\n            return httpAsPromise(\n                {\n                    method: 'DELETE',\n                    url: FLOWABLE.CONFIG.contextRoot + '/app/rest/admin/privileges/' + privilegeId + '/users/' + userId\n                }\n            )\n        };\n\n        this.addGroupPrivilege = function(privilegeId, groupId) {\n            return httpAsPromise(\n                {\n                    method: 'POST',\n                    url: FLOWABLE.CONFIG.contextRoot + '/app/rest/admin/privileges/' + privilegeId + '/groups',\n                    data: { groupId : groupId}\n                }\n            )\n        };\n\n        this.deleteGroupPrivilege = function(privilegeId, groupId) {\n            return httpAsPromise(\n                {\n                    method: 'DELETE',\n                    url: FLOWABLE.CONFIG.contextRoot + '/app/rest/admin/privileges/' + privilegeId + '/groups/' + groupId\n                }\n            )\n        };\n\n    }]);\n"
  },
  {
    "path": "flowable-ui-web/idm/scripts/idm-user-mgmt-controller.js",
    "content": "/* 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 * Controller for user mgmt\n */\nflowableApp.controller('IdmUserMgmtController', ['$rootScope', '$scope', '$translate', '$http', '$timeout','$location', '$modal',\n    function ($rootScope, $scope, $translate, $http, $timeout, $location, $modal) {\n\n        $rootScope.setMainPageById('userMgmt');\n\n        $scope.model = {\n            loading: false,\n            sorts: [\n                {id: 'idAsc', name: $translate.instant('IDM.USER-MGMT.FILTERS.SORT-ID-A')},\n                {id: 'idDesc', name: $translate.instant('IDM.USER-MGMT.FILTERS.SORT-ID-Z')},\n                {id: 'emailAsc', name: $translate.instant('IDM.USER-MGMT.FILTERS.SORT-EMAIL-A')},\n                {id: 'emailDesc', name: $translate.instant('IDM.USER-MGMT.FILTERS.SORT-EMAIL-Z')}\n            ],\n            waiting: false,\n            delayed: false,\n            selectedUsers: {},\n            selectedUserCount: 0,\n            start: 0\n        };\n\n        $scope.model.activeSort = $scope.model.sorts[0];\n\n        $scope.clearSelectedUsers = function() {\n            $scope.model.selectedUsers = {};\n            $scope.model.selectedUserCount = 0;\n        };\n\n        $scope.loadUsers = function() {\n            $scope.clearSelectedUsers();\n            $scope.model.loading = true;\n            var params = {\n                filter: $scope.model.pendingFilterText,\n                company: $scope.model.pendingCompanyText,\n                sort: $scope.model.activeSort.id,\n                start: $scope.model.start\n            };\n\n            $http({method: 'GET', url: FLOWABLE.CONFIG.contextRoot + '/app/rest/admin/users', params: params}).\n                success(function(data, status, headers, config) {\n                    data.moreUsers = data.start + data.size < data.total;\n                    $scope.model.users = data;\n                    $scope.model.loading = false;\n                }).\n                error(function(data, status, headers, config) {\n                    $scope.model.loading = false;\n                });\n        };\n\n\n        $scope.refreshDelayed = function() {\n            // If already waiting, another wait-cycle will be done\n            // after the current wait is over\n            if($scope.model.waiting) {\n                $scope.model.delayed = true;\n            } else {\n                $scope.scheduleDelayedRefresh();\n            }\n        };\n\n        $scope.scheduleDelayedRefresh = function() {\n            $scope.model.waiting = true;\n\n            $timeout(function() {\n                $scope.model.waiting = false;\n                if( $scope.model.delayed) {\n                    $scope.model.delayed = false;\n                    // Delay again\n                    $scope.scheduleDelayedRefresh();\n                } else {\n                    // Actually do the refresh-call, after resetting start\n                    $scope.model.start = 0;\n                    $scope.loadUsers();\n                }\n            }, 100);\n        };\n\n        $scope.showNextUsers = function() {\n            if($scope.model.users) {\n                $scope.model.start = $scope.model.users.start + $scope.model.users.size;\n                $scope.loadUsers();\n            }\n        };\n\n        $scope.showPreviousUsers = function() {\n            if($scope.model.users) {\n                $scope.model.start = Math.max(0, $scope.model.users.start - $scope.model.users.size);\n                $scope.loadUsers();\n            }\n        };\n\n        $scope.activateSort = function(sort) {\n            $scope.model.activeSort = sort;\n            $scope.model.start = 0;\n            $scope.loadUsers();\n        };\n\n        $scope.toggleUserSelection = function(user) {\n            if($scope.model.selectedUsers[user.id]) {\n                delete $scope.model.selectedUsers[user.id];\n                $scope.model.selectedUserCount -= 1;\n            }  else {\n                $scope.model.selectedUsers[user.id] = true;\n                $scope.model.selectedUserCount +=1;\n            }\n\n        };\n\n        $scope.addUser = function() {\n            $scope.model.errorMessage = undefined;\n            $scope.model.user = undefined;\n            $scope.model.mode = 'create';\n            _internalCreateModal({\n                scope: $scope,\n                template: 'views/popup/idm-user-create.html?version=' + new Date().getTime(),\n                show: true\n            }, $modal, $scope);\n        };\n\n        $scope.editUserAccountType = function() {\n\n            $scope.model.mode = 'type';\n\n            _internalCreateModal({\n                scope: $scope,\n                template: 'views/popup/idm-user-type-edit.html',\n                show: true\n            }, $modal, $scope);\n\n        };\n\n        $scope.editUserDetails = function() {\n\n            $scope.model.user = undefined;\n            $scope.model.mode = 'edit';\n            var selectedUsers = $scope.getSelectedUsers();\n            if (selectedUsers && selectedUsers.length == 1) {\n                $scope.model.user = selectedUsers[0];\n            }\n\n            $scope.model.errorMessage = undefined;\n            _internalCreateModal({\n                scope: $scope,\n                template: 'views/popup/idm-user-create.html?version=' + new Date().getTime(),\n                show: true\n            }, $modal, $scope);\n        };\n\n        $scope.editUserPassword = function() {\n\n            $scope.model.mode = 'password';\n\n            _internalCreateModal({\n                scope: $scope,\n                template: 'views/popup/idm-user-password-change.html',\n                show: true\n            }, $modal, $scope);\n\n        };\n\n        $scope.deleteUsers = function() {\n            $scope.model.loading = true;\n            $scope.getSelectedUsers().forEach(function(selectedUser) {\n                $http({method: 'DELETE', url: FLOWABLE.CONFIG.contextRoot + '/app/rest/admin/users/' + selectedUser.id}).\n                    success(function (data, status, headers, config) {\n\n                        $rootScope.addAlert('User deleted', 'info');\n                        $scope.loadUsers();\n\n                        $scope.model.loading = false;\n                    }).\n                    error(function (data, status, headers, config) {\n                        $scope.model.loading = false;\n                        if (data && data.message) {\n                            $rootScope.addAlert(data.message, 'error');\n                        } else {\n                            $rootScope.addAlert('Error while deleting user', 'error');\n                        }\n                    });\n            });\n        };\n\n        $scope.getSelectedUsers = function() {\n            var selected = [];\n            for(var i = 0; i<$scope.model.users.size; i++) {\n                var user = $scope.model.users.data[i];\n                if(user) {\n                    for(var prop in $scope.model.selectedUsers) {\n                        if(user.id == prop) {\n                            selected.push(user);\n                            break;\n                        }\n                    }\n                }\n            }\n\n            return selected;\n        };\n\n        $scope.loadUsers();\n\n    }]);\n\n\n/**\n * Controller for the create user dialog\n */\nflowableApp.controller('IdmCreateUserPopupController', ['$rootScope', '$scope', '$http',\n    function ($rootScope, $scope, $http) {\n\n\n        if ($scope.model.user === null || $scope.model.user === undefined) {\n            $scope.model.user = {};\n        }\n\n        $scope.createNewUser = function () {\n            if (!$scope.model.user.id) {\n                return;\n            }\n\n            var model = $scope.model;\n            model.loading = true;\n\n            var data = {\n                id: model.user.id,\n                email: model.user.email,\n                firstName: model.user.firstName,\n                lastName: model.user.lastName,\n                password: model.user.password,\n            };\n\n            $http({method: 'POST', url: FLOWABLE.CONFIG.contextRoot + '/app/rest/admin/users', data: data}).\n                success(function (data, status, headers, config) {\n\n                    $rootScope.addAlert('New user created', 'info');\n                    $scope.loadUsers();\n\n                    $scope.model.loading = false;\n                    $scope.$hide();\n                }).\n                error(function (data, status, headers, config) {\n                    $scope.model.loading = false;\n                    if (data && data.message) {\n                        $rootScope.addAlert(data.message, 'error');\n                    } else {\n                        $rootScope.addAlert('Error while updating user status', 'error');\n                    }\n\n                    if (status == 403) {\n                        $scope.model.errorMessage = \"Forbidden\";\n                    } else if (status == 409) {\n                        $scope.model.errorMessage = \"A user with that email address already exists\";\n                    } else {\n                        $scope.$hide();\n                    }\n                });\n        };\n\n        $scope.editUserDetails = function() {\n            if (!$scope.model.user.id) {\n                return;\n            }\n\n            var model = $scope.model;\n            model.loading = true;\n\n            var data = {\n                id: model.user.id,\n                email: model.user.email,\n                firstName: model.user.firstName,\n                lastName: model.user.lastName,\n            };\n\n            $http({method: 'PUT', url: FLOWABLE.CONFIG.contextRoot + '/app/rest/admin/users/' + $scope.model.user.id, data: data}).\n                success(function (data, status, headers, config) {\n\n                    $scope.loadUsers();\n\n                    $scope.model.loading = false;\n                    $scope.$hide();\n                }).\n                error(function (data, status, headers, config) {\n                    $scope.model.loading = false;\n                    if (data && data.message) {\n                        $rootScope.addAlert(data.message, 'error');\n                    } else {\n                        $rootScope.addAlert('Error while updating user status', 'error');\n                    }\n\n                    if (status == 403) {\n                        $scope.model.errorMessage = \"Forbidden\";\n                    } else if (status == 409) {\n                        $scope.model.errorMessage = \"A user with that email address already exists\";\n                    } else {\n                        $scope.$hide();\n                    }\n                });\n        };\n\n        $scope.cancel = function () {\n            if (!$scope.model.loading) {\n                $scope.$hide();\n            }\n        };\n\n    }]);\n\n/**\n * Controller for the bulk update dialog\n */\nflowableApp.controller('IdmUserBulkUpdatePopupController', ['$rootScope', '$scope', '$http',\n  function ($rootScope, $scope, $http) {\n\n      if ($scope.model.mode == 'password') {\n          $scope.model.updateUsers = {\n              password: ''\n          };\n      }\n\n     $scope.updateUsers = function () {\n       $scope.model.loading = true;\n       var users = $scope.getSelectedUsers();\n       var userIds = [];\n       for(var i=0; i<users.length; i++) {\n         var user = users[i];\n         if(user && user.id) {\n           userIds.push(user.id);\n         }\n       }\n\n       var data = {\n           users: userIds\n       };\n\n       if ($scope.model.mode == 'password') {\n         data.password = $scope.model.updateUsers.password;\n       }\n\n       $http({method: 'PUT', url: FLOWABLE.CONFIG.contextRoot + '/app/rest/admin/users', data: data})\n           .success(function(data, status, headers, config) {\n                $scope.$hide();\n                $scope.model.loading = false;\n                $rootScope.addAlert($scope.model.selectedUserCount + ' user(s) updated', 'info');\n                $scope.loadUsers();\n\n         }).\n         error(function(data, status, headers, config) {\n            $scope.model.loading = false;\n            if(data && data.message) {\n              $rootScope.addAlert(data.message, 'error');\n            } else {\n              $rootScope.addAlert('Error while updating user status', 'error');\n            }\n            $scope.$hide();\n         });\n    };\n\n    $scope.setStatus = function(newStatus) {\n      $scope.model.updateUsers.status = newStatus;\n    };\n\n    $scope.setType = function(newType) {\n      $scope.model.updateUsers.type = newType;\n    };\n\n    $scope.cancel = function () {\n      if(!$scope.model.loading) {\n        $scope.$hide();\n      }\n    };\n\n}]);\n\n"
  },
  {
    "path": "flowable-ui-web/idm/scripts/resource-loader.js",
    "content": "/* Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n(function(resources){\n\n    if (resources) {\n\n        // Pause angular bootstrap so we have time to register and override angular services/directives etc\n        window.name = 'NG_DEFER_BOOTSTRAP!';\n\n        function load(res, node, callback, scope) {\n            var resource;\n            if (res.tag === 'script') {\n                resource = document.createElement('script');\n                resource.type = res.type || 'text/javascript';\n                resource.src = res.src;\n\n                if (callback) {\n                    var done = false;\n\n                    // Attach handlers for all browsers\n                    resource.onload = resource.onreadystatechange = function()\n                    {\n                        if (!done && (!this.readyState || this.readyState == \"loaded\" || this.readyState == \"complete\"))\n                        {\n                            done = true;\n                            callback.call(scope ? scope : this, res);\n                        }\n                    };\n                }\n            }\n            else if (res.tag === 'link') {\n                resource = document.createElement('link');\n                resource.rel = res.rel || 'stylesheet';\n                resource.href = res.href;\n            }\n\n            if (node.nextSibling) {\n                node.parentNode.insertBefore(resource, node.nextSibling);\n            }\n            else {\n                node.parentNode.appendChild(resource);\n            }\n\n            if (res.tag === 'link' && callback) {\n                callback.call(scope ? scope : this, res);\n            }\n        }\n\n        function getResourceLoaderElement() {\n            var scripts = document.getElementsByTagName('script');\n            for (var i = 0, il = scripts.length; i < il; i++) {\n                if (scripts[i].src.indexOf('scripts/resource-loader.js') != -1) {\n                    return scripts[i];\n                }\n            }\n            return null;\n        }\n\n        var res = resources['*'];\n        var resourceLoaderElement = getResourceLoaderElement();\n        var appName = resourceLoaderElement.getAttribute('app');\n        if (resources.hasOwnProperty(appName)) {\n            res = resources[appName];\n        }\n\n        var loadedResources = 0;\n        for (var i = 0, il = res.length; i < il; i++) {\n            load(res[i], resourceLoaderElement, function(){\n                loadedResources++;\n                if (loadedResources == res.length) {\n                    // Let angular resume bootstrap\n                    var interval = window.setInterval(function(){\n                        if (angular && typeof angular.resumeBootstrap == 'function') {\n                            angular.resumeBootstrap();\n                            window.clearInterval(interval);\n                        }\n                    }, 20);\n\n                }\n            });\n        }\n    }\n\n})(FLOWABLE.CONFIG.resources);"
  },
  {
    "path": "flowable-ui-web/idm/styles/common/style.css",
    "content": "/**\n Colors:\n\n  - Header: #1f3245\n  - Subheader: #e8edf1\n  - Subheader border: #a4acb9\n  - Highlight buttons/text: #2980b9\n  - Text color: #1a1a1a\n  - Filter color: #373e48\n  - Dark highlight: #606b7d\n*/\n\n@font-face {\n    font-family: 'cherokeeregular';\n    src: url('../../fonts/cherokee-webfont.eot');\n    src: url('../../fonts/cherokee-webfont.eot?#iefix') format('embedded-opentype'),\n    url('../../fonts/cherokee-webfont.woff') format('woff'),\n    url('../../fonts/cherokee-webfont.ttf') format('truetype'),\n    url('../../fonts/cherokee-webfont.svg#cherokeeregular') format('svg');\n    font-weight: normal;\n    font-style: normal;\n}\n\n@font-face {\n    font-family: 'Titillium Web';\n    font-style: normal;\n    font-weight: normal;\n    url('../../fonts/TitilliumWeb-Regular.ttf') format('truetype');\n}\n\n@font-face {\n    font-family: 'Titillium Web';\n    font-style: normal;\n    font-weight: bold;\n    url('../../fonts/TitilliumWeb-Bold.ttf') format('truetype');\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,\nbody pre {\n    font-family: 'Titillium Web', sans-serif;\n}\n\nbody pre {\n    border: none;\n    padding: 0;\n    background: transparent;\n}\n\n.form-wrapper textarea {\n    width: 100%;\n    max-width: 100%;\n    min-width: 100%;\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:hover {\n    font-weight: bolder;\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: #2980b9;\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.btn[disabled]:hover, .btn[disabled].active, .btn[disabled]:focus {\n    background-color: #3990c9;\n    border-color: #ffffff;\n    color: #ffffff;\n}\n\n.btn[disabled]:active, .btn[disabled].active {\n    outline: 0;\n    background-image: none;\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\n.btn.disabled, .btn[disabled], .btn[disabled]:active, .btn[disabled]:hover {\n    background-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: #2980b9;\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: #2980b9;\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: 350px;\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: #1f3245;\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    width: 180px;\n}\n\n\n.navbar-nav {\n    height: 40px;\n    margin-left: 50px;\n}\n\n.navbar-inverse .navbar-nav > li > a {\n\tcolor: #a8bac1;\n}\n\n.navbar-inverse .navbar-nav > .active > a {\n\tbackground-color: #1f3245;\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    content: \" \";\n    height: 0;\n    width: 0;\n    position: absolute;\n    pointer-events: none;\n    border: 6px solid rgba(0, 0, 0, 0);\n    border-top-color: #1f3245;\n    margin-left: -6px;\n}\n\n.navbar-nav > li.active:hover:after {\n    border-top-color: #000000;\n}\n\n.navbar-nav > li.active {\n    background-color: #000000;\n    position: relative;\n}\n\n.navbar-nav > li.active > a {\n    color: #2980b9;\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: 'Titillium Web', 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: #2980b9;\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    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: 1;\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    background-color: #ffffff;\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: #2980b9;\n}\n\n.main-list .list-subheader {\n    margin-top: 40px;\n    position: relative;\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: #2980b9;\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: #2980b9;\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: #2980b9;\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: #2980b9;\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\nh3+div > .dropzone {\n    margin-top: 5px;\n}\n\n.dropzone {\n    position: relative;\n    margin: 0px;\n    padding: 10px 10px;\n    text-align: center;\n}\n\n.dropzone .error, .error-message {\n    background-color: #e9af9f;\n    border: 1px solid #e4593d;\n    background-color: rgba(228, 89, 61, .7);\n    padding: 5px;\n    margin-bottom: 5px;\n    font-size: 14px;\n    color:white;\n}\n\n.dropzone.selection {\n    text-align: left;\n    padding-left: 5px;\n}\n\n.dropzone .select-file {\n    line-height: 40px;\n}\n\n.dropzone.dragover {\n    border: 1px dotted #2980b9;\n}\n\n.dropzone .message {\n    color: #999999;\n    line-height: 22px;\n    visibility: hidden;\n    position: absolute;\n    top: 20px;\n    left: 10px;\n    right: 10px;\n    text-align: center;\n}\n\n.dropzone.dragover .message {\n    color: #2980b9;\n    font-size: 20px;\n    visibility: inherit;\n}\n\n\n.dropzone.uploading .message {\n    visibility: hidden;\n}\n\n.dropzone input[type=file] {\n    width: 100%;\n    display: none;\n    visibility: hidden;\n}\n\n.dropzone.dragover input, .dropzone.dragover .account, .dropzone.dragover .select-file {\n    visibility: hidden;\n}\n\n.dropzone .account {\n    float: left;\n    text-align: center;\n    width: 50px;\n\n    padding: 0px 0px 0px 3px;\n    border-left: 1px solid #eeeeee;\n}\n\n.dropzone .no-upload .account {\n    border-left: none;\n    border-right: 1px solid #eeeeee;\n}\n.dropzone .account:first-child {\n    padding-left: 0;\n}\n\n.dropzone .account > div {\n    height: 40px;\n    cursor: pointer;\n}\n\n.dropzone.uploading .account > div {\n    cursor: not-allowed;\n}\n\n.account .google-drive {\n    background: transparent url('../../images/google-drive.png') 50% 50% no-repeat;\n}\n\n.account .alfresco {\n    background: transparent url('../../images/alfresco.png') 50% 50% no-repeat;\n}\n\n.account .alfresco-cloud {\n    background: transparent url('../../images/alfresco-cloud.png') 50% 50% no-repeat;\n}\n\n.dropzone .loading {\n    position: absolute;\n    left: 50%;\n    margin-left: -15px;\n    line-height: 30px;\n    top: 0px;\n}\n\n.dropzoneIE9.selectionIE9 {\n    text-align: left;\n    padding-left: 5px;\n}\n.dropzoneIE9 {\n    position: relative;\n    margin: 0px;\n    padding: 10px 10px;\n    text-align: center;\n}\n.selectionIE9 {\n    position: relative;\n    margin: 0;\n    padding: 6px 8px;\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    font-size: 14px;\n    cursor: pointer;\n}\n\n.selectionIE9 .actions {\n    float: right;\n}\n\n.dropzoneIE9 .account:first-child {\n    padding-left: 0;\n}\n\n.dropzoneIE9 .account {\n    float: left;\n    text-align: center;\n    width: 50px;\n    padding: 0px 0px 0px 3px;\n    border-left: 1px solid #eeeeee;\n}\n\n.dropzoneIE9 .account > div {\n    height: 40px;\n    cursor: pointer;\n}\n\n.dropzoneIE9 .select-file {\n    line-height: 40px;\n}\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}\n\n\n.read-only-select {\n    overflow: auto;\n}\n.read-only-select .selection {\n    overflow: hidden;\n    width:100%;\n    text-align: left;\n}\n\n/** people select */\n\n.people-select {\n    overflow: auto;\n    max-width: 300px;\n}\n\n.popover .people-select {\n    font-size: 13px;\n}\n\n.popover .people-select .simple-list {\n    height: 180px;\n    overflow: auto;\n    border-bottom: 1px solid #eeeeee;\n}\n\n.people-select-link {\n    color: #428bca;\n    cursor: pointer;\n}\n\n/** date select */\n\n.form-field {\n    overflow: auto;\n    max-width: 100%;\n}\n\n.popover .form-field {\n    font-size: 13px;\n}\n\n.popover .form-field .simple-list {\n    height: 180px;\n    overflow: auto;\n    border-bottom: 1px solid #eeeeee;\n}\n\n.form-field-link {\n    color: #428bca;\n    cursor: pointer;\n}\n\n.dropdown-menu.datepicker .calendar-grid .btn {\n    background-color: #ffffff;\n    color: #1a1a1a;\n    border: none;\n\n    -webkit-border-radius: 0;\n    -moz-border-radius: 0;\n    border-radius: 0;\n}\n\n.dropdown-menu.datepicker th {\n    background-color: #e8edf1;\n}\n.dropdown-menu.datepicker th .btn {\n    background-color: #e8edf1;\n    color: #1a1a1a;\n    border-color: #e8edf1;\n}\n\n.dropdown-menu.datepicker th .btn:hover, .dropdown-menu.datepicker th .btn:focus {\n    color: #2980b9;\n}\n\n.dropdown-menu.datepicker .calendar-grid .btn:hover, .dropdown-menu.datepicker .calendar-grid .btn:focus {\n    background-color: #f8f8f9;\n    border: none;\n    color: #1a1a1a;\n}\n\n.dropdown-menu.datepicker .calendar-grid .btn-today, .dropdown-menu.datepicker .calendar-grid .btn-today:focus, .dropdown-menu.datepicker .calendar-grid .btn-today:hover {\n    background-color: #b8dde7;\n}\n\n.dropdown-menu.datepicker .calendar-grid .btn-primary, .dropdown-menu.datepicker .calendar-grid .btn-primary:hover, .dropdown-menu.datepicker .calendar-grid .btn-primary:focus {\n    background-color: #2980b9;\n    color: #ffffff;\n}\n\n.dropdown-menu.datepicker .custom-buttons .btn {\n    border-color: #ffffff;\n}\n\n.comments > li {\n    padding: 8px 6px;\n}\n\n.comments > li > .title {\n\n    color: #888888;\n    font-size: 13px;\n    margin: 0 0 3px 0;\n}\n\n.comments > li > .message {\n    text-align: left;\n    color: #3a3a3a;\n    padding-left: 3px;\n    word-wrap: break-word;\n}\n\n.comments > li > .message:before, .comments > li > .message:after {\n    font-style: italic;\n}\n\n.comments > li > .message:before {\n    content: open-quote;\n    padding-right: 2px;\n}\n\n.comments > li > .message:after {\n    content: close-quote;\n    padding-left: 2px;\n}\n\n\n.form-wrapper {\n    margin: 10px 0 20px 0;\n}\n\n.form-wrapper .well-sm {\n    padding: 6px 9px;\n}\n\n.checklist.simple-list .user-picture {\n    margin-top: 2px;\n    width: 32px;\n    height: 32px;\n    background-size: 32px 32px;\n    line-height: 32px;\n    font-size: 15px;\n}\n\n.checklist.simple-list > li {\n    cursor: pointer;\n}\n\n.diagram-popup-wrapper {\n    min-width: 1000px;\n    max-width: 1400px;\n    min-height: 300px;\n    z-index: 1005;\n}\n\n.model-preview-wrapper {\n    width: 100%;\n    height:100%;\n    padding: 10px;\n    overflow: auto;\n}\n\n.upload-image-form {\n    margin: 0 20% 0 20%;\n    text-align: center;\n}\n\n.upload-image-dropbox {\n    background: #F8F8F8;\n    border: 5px dashed #DDD;\n    color: #8e8e8e;\n    text-align: center;\n    padding: 35px 0 35px 0;\n    margin: 20px 0 20px 0;\n}\n\n.upload-image-dropbox.dragover {\n    border: 5px dashed #55ae4d;\n    color: #55ae4d;\n}\n\n\n.google-drive-browse .simple-list, .alfresco-cloud-browse .simple-list {\n    position: relative;\n    max-height: 350px;\n    min-height: 350px;\n    height: 350px;\n    overflow: auto;\n}\n\n.alfresco-cloud-browse .col-xs-6 {\n    padding: 0 0 0 10px;\n}\n\n.alfresco-cloud-browse .col-xs-6:first-child {\n    padding-left: 0;\n}\n\n.crumbs {\n    margin: 5px 0px;\n    color: #666666;\n}\n\n.crumb {\n    color: #666666;\n    cursor: pointer;\n}\n\n.crumb i {\n    font-size: 80%;\n}\n\n.crumb:hover {\n    color: #2980b9;\n    text-decoration: underline;\n}\n.crumb:hover i {\n    color: #666666;\n}\n\n/** Apps */\n.apps-wrapper {\n    padding-top: 55px;\n    width: 1200px;\n    margin: 0 auto;\n}\n\n.app-wrapper {\n    float: left;\n    width: 300px;\n}\n\n.app {\n    margin: 10px 10px;\n    height: 200px;\n    border-left: 8px solid transparent;\n    overflow: hidden;\n    position: relative;\n    cursor: pointer;\n}\n\n.app .backdrop, .app .logo {\n    position: absolute;\n    text-shadow: none;\n\n    -webkit-transition: all 1s ease;\n    -moz-transition: all 1s ease;\n    -o-transition: all 1s ease;\n    transition: all 1s ease;\n\n    z-index: 4;\n}\n\n.app .backdrop {\n    font-size: 300px;\n    right: 50px;\n    top: -100px;\n}\n\n.app .logo {\n    font-size: 150px;\n    right: 20px;\n    top: 20px;\n}\n\n.app:hover .backdrop {\n    top: -55px;\n}\n\n.app:hover .logo {\n    right: -10px\n}\n\n.app h3 {\n    margin: 15px 10px 0px 10px;\n    position: relative;\n}\n\n.app-content {\n    color: #ffffff;\n    position: relative;\n    z-index: 5;\n}\n\n\n.app-content p {\n    display: none;\n    margin: 10px 0px 10px 10px;\n    padding: 10px 10px 0 0;\n    border-top: 1px solid #ffffff;\n    border-color: rgba(255,255,255, .1);\n}\n\n.app:hover .app-content p {\n    display: inherit;\n}\n\n.app .actions {\n    position: absolute;\n    top: 0px;\n    right: 0;\n    width: 40px;\n    height: 49px;\n    background-color: transparent;\n    line-height: 50px;\n    text-align: center;\n    z-index: 6;\n    visibility: hidden;\n    font-size: 16px;\n    color: #ffffff;\n    border-right: 2px solid transparent;\n    border-top: 2px solid transparent;\n}\n\n.app .selection-marker {\n    position: absolute;\n    top: 0px;\n    right: 5px;\n    width: 50px;\n    height: 48px;\n    font-size: 45px;\n    color: #ffffff;\n    z-index: 6;\n}\n\n.app:hover .actions {\n    visibility: visible;\n}\n.app .actions:hover {\n    background-color: #ffffff;\n    background-color: rgba(255,255,255, .7);\n    text-shadow: none;\n}\n\n.app .actions+.dropdown-menu {\n    background-color: #ffffff;\n    background-color: rgba(255,255,255, .8);\n    text-shadow: none;\n}\n.app-indicator {\n    position: relative;\n    padding-left: 20px;\n    color: #ffffff;\n}\n\n.app-indicator > span {\n    margin-right: 10px;\n    margin-left: 25px;\n    font-size: 16px;\n    padding-right: 15px;\n    white-space: nowrap;\n    text-overflow: ellipsis;\n}\n\n.app-indicator > .btn-group {\n    border-left: 1px solid #999999;\n}\n\n.app-indicator > i {\n    position: absolute;\n    left: 5px;\n    top:6px;\n    font-size: 28px;\n    color: #ffffff;\n    color: rgba(255, 255, 255, .5);\n}\n\n.popover.app-links-popover {\n    margin-top: 0;\n    padding: 5px;\n    width: 446px;\n    max-width: 446px;\n    overflow: auto;\n    max-height: calc(100vh - 40px);\n}\n.app-link-wrapper {\n    float: left;\n    display: inline-block;\n    min-height: 80px;\n    width: 90px;\n    margin: 5px;\n    text-align: center;\n    padding: 5px;\n    padding-top: 10px;\n    -webkit-transition: background-color 0.5s ease-out;\n    -moz-transition: background-color 0.5s ease-out;\n    -o-transition: background-color 0.5s ease-out;\n    transition: background-color 0.5s ease-out;\n    cursor: pointer;\n}\n.app-link-wrapper:hover,\n.app-link-wrapper:active {\n    background-color: #eee;\n}\n.app-link-name  {\n    word-wrap: break-word;\n    color: black;\n    opacity: 0.9;\n    margin-top: 5px;\n}\n.app-link-icon {\n    border-radius: 50%;\n    height: 50px;\n    width: 50px;\n    display: inline-block;\n}\n.app-link-icon > i {\n    color: white;\n    opacity: 0.5;\n    border-radius: 50%;\n    margin-bottom: 5px;\n    padding: 10px;\n    font-size: 30px;\n}\n.app-link-icon > span {\n    color: black;\n}\n\n.app-link-icon.theme-1,\n.app.theme-1 {\n    background-color: #269abc;\n}\n.app.theme-1 {\n    border-color: #269abc;\n    text-shadow: 1px 1px #168aac;\n}\n\n.app-indicator.theme-1 {\n    background: #269abc;\n    background: -moz-linear-gradient(left,  rgba(38,154,188,0) 0%, rgba(38,154,188,0.02) 1%, rgba(38,154,188,1) 30%, rgba(38,154,188,1) 100%); /* FF3.6+ */\n    background: -webkit-linear-gradient(left,  rgba(38,154,188,0) 0%,rgba(38,154,188,0.02) 1%,rgba(38,154,188,1) 30%,rgba(38,154,188,1) 100%); /* Chrome10+,Safari5.1+ */\n    background: -ms-linear-gradient(left,  rgba(38,154,188,0) 0%,rgba(38,154,188,0.02) 1%,rgba(38,154,188,1) 30%,rgba(38,154,188,1) 100%); /* IE10+ */\n    background: linear-gradient(to right,  rgba(38,154,188,0) 0%,rgba(38,154,188,0.02) 1%,rgba(38,154,188,1) 30%,rgba(38,154,188,1) 100%); /* W3C */\n    filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#00269abc', endColorstr='#269abc',GradientType=1 ); /* IE6-9 */\n}\n\n.app-indicator.theme-1 > .btn-group {\n    border-color: #168aac;\n}\n\n.app-indicator.theme-1 > .btn-group .btn-default:hover, .app-indicator.theme-1 > .btn-group .btn-default:focus {\n    background-color: #168aac;\n}\n\n.app.theme-1  .actions+.dropdown-menu li:hover a {\n    background-color: #168aac;\n}\n\n.app.theme-1 .backdrop i {\n    color: #2a9ec0;\n}\n\n.app.theme-1 .logo i {\n    color: #168aac;\n}\n\n.active > .app.preview.theme-1, .app.theme-1:hover {\n    border-color: #168aac;\n}\n\n.app.theme-1 .actions:hover {\n    border-color: #269abc;\n    color: #269abc;\n}\n\n.app-link-icon.theme-2,\n.app.theme-2 {\n    background-color: #7da9b0;\n}\n.app.theme-2 {\n    border-color: #7da9b0;\n    text-shadow: 1px 1px #6d99a0;\n}\n\n.app-indicator.theme-2 {\n    background: #7da9b0;\n    background: -moz-linear-gradient(left,  rgba(125,169,176,0) 0%, rgba(125,169,176,0.02) 1%, rgba(125,169,176,1) 30%, rgba(125,169,176,1) 100%); /* FF3.6+ */\n    background: -webkit-linear-gradient(left,  rgba(125,169,176,0) 0%,rgba(125,169,176,0.02) 1%,rgba(125,169,176,1) 30%,rgba(125,169,176,1) 100%); /* Chrome10+,Safari5.1+ */\n    background: -ms-linear-gradient(left,  rgba(125,169,176,0) 0%,rgba(125,169,176,0.02) 1%,rgba(125,169,176,1) 30%,rgba(125,169,176,1) 100%); /* IE10+ */\n    background: linear-gradient(to right,  rgba(125,169,176,0) 0%,rgba(125,169,176,0.02) 1%,rgba(125,169,176,1) 30%,rgba(125,169,176,1) 100%); /* W3C */\n    filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#00269abc', endColorstr='#269abc',GradientType=1 ); /* IE6-9 */\n}\n\n.app-indicator.theme-2 > .btn-group {\n    border-color: #6d99a0;\n}\n\n.app-indicator.theme-2 > .btn-group .btn-default:hover, .app-indicator.theme-2 > .btn-group .btn-default:focus {\n    background-color: #6d99a0;\n}\n\n.app.theme-2 .actions+.dropdown-menu li:hover a {\n    background-color: #6d99a0;\n}\n\n.app.theme-2 .backdrop i {\n    color: #81adb4;\n}\n\n.app.theme-2 .logo i {\n    color: #6d99a0;\n}\n\n.active > .app.preview.theme-2, .app.theme-2:hover {\n    border-color: #6d99a0;\n}\n\n.app.theme-2 .actions:hover {\n    border-color: #7da9b0;\n    color: #7da9b0;\n}\n\n.app-link-icon.theme-3,\n.app.theme-3 {\n    background-color: #7689ab;\n}\n.app.theme-3 {\n    border-color: #7689ab;\n    text-shadow: 1px 1px #66799b;\n}\n\n.app-indicator.theme-3 {\n    background: #7689ab;\n    background: -moz-linear-gradient(left,  rgba(118,137,171,0) 0%, rgba(118,137,171,0.02) 1%, rgba(118,137,171,1) 30%, rgba(118,137,171,1) 100%); /* FF3.6+ */\n    background: -webkit-linear-gradient(left,  rgba(118,137,171,0) 0%,rgba(118,137,171,0.02) 1%,rgba(118,137,171,1) 30%,rgba(118,137,171,1) 100%); /* Chrome10+,Safari5.1+ */\n    background: -ms-linear-gradient(left,  rgba(118,137,171,0) 0%,rgba(118,137,171,0.02) 1%,rgba(118,137,171,1) 30%,rgba(118,137,171,1) 100%); /* IE10+ */\n    background: linear-gradient(to right,  rgba(118,137,171,0) 0%,rgba(118,137,171,0.02) 1%,rgba(118,137,171,1) 30%,rgba(118,137,171,1) 100%); /* W3C */\n    filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#00269abc', endColorstr='#269abc',GradientType=1 ); /* IE6-9 */\n}\n\n.app-indicator.theme-3 > .btn-group {\n    border-color: #66799b;\n}\n\n.app-indicator.theme-3 > .btn-group .btn-default:hover, .app-indicator.theme-3 > .btn-group .btn-default:focus {\n    background-color: #66799b;\n}\n\n.app.theme-3 .actions+.dropdown-menu li:hover a {\n    background-color: #66799b;\n}\n\n.app.theme-3 .backdrop i {\n    color: #7a8daf;\n}\n\n.app.theme-3 .logo i {\n    color: #66799b;\n}\n\n.active > .app.preview.theme-3, .app.theme-3:hover {\n    border-color: #66799b;\n}\n\n.app.theme-3 .actions:hover {\n    border-color: #7689ab;\n    color: #7689ab;\n}\n\n.app-link-icon.theme-4,\n.app.theme-4 {\n    background-color: #c74e3e;\n}\n.app.theme-4 {\n    border-color: #c74e3e;\n    text-shadow: 1px 1px #b73e2e;\n}\n\n.app-indicator.theme-4 {\n    background: #c74e3e;\n    background: -moz-linear-gradient(left,  rgba(199,78,62,0) 0%, rgba(199,78,62,0.02) 1%, rgba(199,78,62,1) 30%, rgba(199,78,62,1) 100%); /* FF3.6+ */\n    background: -webkit-linear-gradient(left,  rgba(199,78,62,0) 0%,rgba(199,78,62,0.02) 1%,rgba(199,78,62,1) 30%,rgba(199,78,62,1) 100%); /* Chrome10+,Safari5.1+ */\n    background: -ms-linear-gradient(left,  rgba(199,78,62,0) 0%,rgba(199,78,62,0.02) 1%,rgba(199,78,62,1) 30%,rgba(199,78,62,1) 100%); /* IE10+ */\n    background: linear-gradient(to right,  rgba(199,78,62,0) 0%,rgba(199,78,62,0.02) 1%,rgba(199,78,62,1) 30%,rgba(199,78,62,1) 100%); /* W3C */\n    filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#00269abc', endColorstr='#269abc',GradientType=1 ); /* IE6-9 */\n}\n\n.app-indicator.theme-4 > .btn-group {\n    border-color: #b73e2e;\n}\n\n.app-indicator.theme-4 > .btn-group .btn-default:hover, .app-indicator.theme-4 > .btn-group .btn-default:focus {\n    background-color: #b73e2e;\n}\n\n.app.theme-4 .actions+.dropdown-menu li:hover a {\n    background-color: #b73e2e;\n}\n\n\n.app.theme-4 .backdrop i {\n    color: #cb5245;\n}\n\n.app.theme-4 .logo i {\n    color: #b73e2e;\n}\n\n.active > .app.preview.theme-4, .app.theme-4:hover {\n    border-color: #b73e2e;\n}\n\n.app.theme-4 .actions:hover {\n    border-color: #c74e3e;\n    color: #c74e3e;\n}\n\n.app-link-icon.theme-5,\n.app.theme-5 {\n    background-color: #fab96c;\n}\n.app.theme-5 {\n    border-color: #fab96c;\n    text-shadow: 1px 1px #eaa95c;\n}\n\n.app-indicator.theme-5 {\n    background: #fab96c;\n    background: -moz-linear-gradient(left,  rgba(250,185,108,0) 0%, rgba(250,185,108,0.02) 1%, rgba(250,185,108,1) 30%, rgba(250,185,108,1) 100%); /* FF3.6+ */\n    background: -webkit-linear-gradient(left,  rgba(250,185,108,0) 0%,rgba(250,185,108,0.02) 1%,rgba(250,185,108,1) 30%,rgba(250,185,108,1) 100%); /* Chrome10+,Safari5.1+ */\n    background: -ms-linear-gradient(left,  rgba(250,185,108,0) 0%,rgba(250,185,108,0.02) 1%,rgba(250,185,108,1) 30%,rgba(250,185,108,1) 100%); /* IE10+ */\n    background: linear-gradient(to right,  rgba(250,185,108,0) 0%,rgba(250,185,108,0.02) 1%,rgba(250,185,108,1) 30%,rgba(250,185,108,1) 100%); /* W3C */\n    filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#00269abc', endColorstr='#269abc',GradientType=1 ); /* IE6-9 */\n}\n\n.app-indicator.theme-5 > .btn-group {\n    border-color: #eaa95c;\n}\n\n.app-indicator.theme-5 > .btn-group .btn-default:hover, .app-indicator.theme-5 > .btn-group .btn-default:focus {\n    background-color: #eaa95c;\n}\n\n.app.theme-5 .actions+.dropdown-menu li:hover a {\n    background-color: #eaa95c;\n}\n\n.app.theme-5 .backdrop i {\n    color: #febd70;\n}\n\n.app.theme-5 .logo i {\n    color: #eaa95c;\n}\n\n.active > .app.preview.theme-5, .app.theme-5:hover {\n    border-color: #eaa95c;\n}\n\n.app.theme-5 .actions:hover {\n    border-color: #fab96c;\n    color: #fab96c;\n}\n\n.app-link-icon.theme-6,\n.app.theme-6 {\n    background-color: #759d4c;\n}\n.app.theme-6 {\n    border-color: #759d4c;\n    text-shadow: 1px 1px #658d3c;\n}\n\n.app-indicator.theme-6 {\n    background: #759d4c;\n    background: -moz-linear-gradient(left,  rgba(117,157,76,0) 0%, rgba(117,157,76,0.02) 1%, rgba(117,157,76,1) 30%, rgba(117,157,76,1) 100%); /* FF3.6+ */\n    background: -webkit-linear-gradient(left,  rgba(117,157,76,0) 0%,rgba(117,157,76,0.02) 1%,rgba(117,157,76,1) 30%,rgba(117,157,76,1) 100%); /* Chrome10+,Safari5.1+ */\n    background: -ms-linear-gradient(left,  rgba(117,157,76,0) 0%,rgba(117,157,76,0.02) 1%,rgba(117,157,76,1) 30%,rgba(117,157,76,1) 100%); /* IE10+ */\n    background: linear-gradient(to right,  rgba(117,157,76,0) 0%,rgba(117,157,76,0.02) 1%,rgba(117,157,76,1) 30%,rgba(117,157,76,1) 100%); /* W3C */\n    filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#00269abc', endColorstr='#269abc',GradientType=1 ); /* IE6-9 */\n}\n\n.app-indicator.theme-6 > .btn-group {\n    border-color: #658d3c;\n}\n\n.app-indicator.theme-6 > .btn-group .btn-default:hover, .app-indicator.theme-6 > .btn-group .btn-default:focus {\n    background-color: #658d3c;\n}\n\n.app.theme-6 .actions+.dropdown-menu li:hover a {\n    background-color: #658d3c;\n}\n\n.app.theme-6 .backdrop i {\n    color: #79a150;\n}\n\n.app.theme-6 .logo i {\n    color: #658d3c;\n}\n\n.active > .app.preview.theme-6, .app.theme-6:hover {\n    border-color: #658d3c;\n}\n\n.app.theme-6 .actions:hover {\n    border-color: #759d4c;\n    color: #759d4c;\n}\n\n.app-link-icon.theme-7,\n.app.theme-7 {\n    background-color: #b1b489;\n}\n.app.theme-7 {\n    border-color: #b1b489;\n    text-shadow: 1px 1px #a1a479;\n}\n\n.app-indicator.theme-7 {\n    background: #b1b489;\n    background: -moz-linear-gradient(left,  rgba(177,180,137,0) 0%, rgba(177,180,137,0.02) 1%, rgba(177,180,137,1) 30%, rgba(177,180,137,1) 100%); /* FF3.6+ */\n    background: -webkit-linear-gradient(left,  rgba(177,180,137,0) 0%,rgba(177,180,137,0.02) 1%,rgba(177,180,137,1) 30%,rgba(177,180,137,1) 100%); /* Chrome10+,Safari5.1+ */\n    background: -ms-linear-gradient(left,  rgba(177,180,137,0) 0%,rgba(177,180,137,0.02) 1%,rgba(177,180,137,1) 30%,rgba(177,180,137,1) 100%); /* IE10+ */\n    background: linear-gradient(to right,  rgba(177,180,137,0) 0%,rgba(177,180,137,0.02) 1%,rgba(177,180,137,1) 30%,rgba(177,180,137,1) 100%); /* W3C */\n    filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#00269abc', endColorstr='#269abc',GradientType=1 ); /* IE6-9 */\n}\n\n.app-indicator.theme-7 > .btn-group {\n    border-color: #a1a479;\n}\n\n.app-indicator.theme-7 > .btn-group .btn-default:hover, .app-indicator.theme-7 > .btn-group .btn-default:focus {\n    background-color: #a1a479;\n}\n\n.app.theme-7 .actions+.dropdown-menu li:hover a {\n    background-color: #a1a479;\n}\n\n.app.theme-7 .backdrop i {\n    color: #b5b98d;\n}\n\n.app.theme-7 .logo i {\n    color: #a1a479;\n}\n\n.active > .app.preview.theme-7, .app.theme-7:hover {\n    border-color: #a1a479;\n}\n\n.app.theme-7 .actions:hover {\n    border-color: #b1b489;\n    color: #b1b489;\n}\n\n.app-link-icon.theme-8,\n.app.theme-8 {\n    background-color: #a17299;\n}\n.app.theme-8 {\n    border-color: #a17299;\n    text-shadow: 1px 1px #916289;\n}\n\n.app-indicator.theme-8 {\n    background: #a17299;\n    background: -moz-linear-gradient(left,  rgba(161,114,153,0) 0%, rgba(161,114,153,0.02) 1%, rgba(161,114,153,1) 30%, rgba(161,114,153,1) 100%); /* FF3.6+ */\n    background: -webkit-linear-gradient(left,  rgba(161,114,153,0) 0%,rgba(161,114,153,0.02) 1%,rgba(161,114,153,1) 30%,rgba(161,114,153,1) 100%); /* Chrome10+,Safari5.1+ */\n    background: -ms-linear-gradient(left,  rgba(161,114,153,0) 0%,rgba(161,114,153,0.02) 1%,rgba(161,114,153,1) 30%,rgba(161,114,153,1) 100%); /* IE10+ */\n    background: linear-gradient(to right,  rgba(161,114,153,0) 0%,rgba(161,114,153,0.02) 1%,rgba(161,114,153,1) 30%,rgba(161,114,153,1) 100%); /* W3C */\n    filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#00269abc', endColorstr='#269abc',GradientType=1 ); /* IE6-9 */\n}\n\n.app-indicator.theme-8 > .btn-group {\n    border-color: #916289;\n}\n\n.app-indicator.theme-8 > .btn-group .btn-default:hover, .app-indicator.theme-8 > .btn-group .btn-default:focus {\n    background-color: #916289;\n}\n\n.app.theme-8 .actions+.dropdown-menu li:hover a {\n    background-color: #916289;\n}\n\n.app.theme-8 .backdrop i {\n    color: #a5769d;\n}\n\n.app.theme-8 .logo i {\n    color: #916289;\n}\n\n.active > .app.preview.theme-8, .app.theme-8:hover {\n    border-color: #916289;\n}\n\n.app.theme-8 .actions:hover {\n    border-color: #a17299;\n    color: #a17299;\n}\n\n.app-link-icon.theme-9,\n.app.theme-9 {\n    background-color: #696c67;\n}\n.app.theme-9 {\n    border-color: #696c67;\n    text-shadow: 1px 1px #595c57;\n}\n\n.app-indicator.theme-9 {\n    background: #696c67;\n    background: -moz-linear-gradient(left,  rgba(105,108,103,0) 0%, rgba(105,108,103,0.02) 1%, rgba(105,108,103,1) 30%, rgba(105,108,103,1) 100%); /* FF3.6+ */\n    background: -webkit-linear-gradient(left,  rgba(105,108,103,0) 0%,rgba(105,108,103,0.02) 1%,rgba(105,108,103,1) 30%,rgba(105,108,103,1) 100%); /* Chrome10+,Safari5.1+ */\n    background: -ms-linear-gradient(left,  rgba(105,108,103,0) 0%,rgba(105,108,103,0.02) 1%,rgba(105,108,103,1) 30%,rgba(105,108,103,1) 100%); /* IE10+ */\n    background: linear-gradient(to right,  rgba(105,108,103,0) 0%,rgba(105,108,103,0.02) 1%,rgba(105,108,103,1) 30%,rgba(105,108,103,1) 100%); /* W3C */\n    filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#00269abc', endColorstr='#269abc',GradientType=1 ); /* IE6-9 */\n}\n\n.app-indicator.theme-9 > .btn-group {\n    border-color: #595c57;\n}\n\n.app-indicator.theme-9 > .btn-group .btn-default:hover, .app-indicator.theme-9 > .btn-group .btn-default:focus {\n    background-color: #595c57;\n}\n\n.app.theme-9 .actions+.dropdown-menu li:hover a {\n    background-color: #595c57;\n}\n\n.app.theme-9 .backdrop i {\n    color: #6d706b;\n}\n\n.app.theme-9 .logo i {\n    color: #595c57;\n}\n\n.active > .app.preview.theme-9, .app.theme-9:hover {\n    border-color: #595c57;\n}\n\n.app.theme-9 .actions:hover {\n    border-color: #696c67;\n    color: #696c67;\n}\n\n.app-link-icon.theme-10,\n.app.theme-10 {\n    background-color: #cabb33;\n}\n.app.theme-10 {\n    border-color: #cabb33;\n    text-shadow: 1px 1px #baab23;\n}\n\n.app-indicator.theme-10 {\n    background: #cabb33;\n    background: -moz-linear-gradient(left,  rgba(202,187,51,0) 0%, rgba(202,187,51,0.02) 1%, rgba(202,187,51,1) 30%, rgba(202,187,51,1) 100%); /* FF3.6+ */\n    background: -webkit-linear-gradient(left,  rgba(202,187,51,0) 0%,rgba(202,187,51,0.02) 1%,rgba(202,187,51,1) 30%,rgba(202,187,51,1) 100%); /* Chrome10+,Safari5.1+ */\n    background: -ms-linear-gradient(left,  rgba(202,187,51,0) 0%,rgba(202,187,51,0.02) 1%,rgba(202,187,51,1) 30%,rgba(202,187,51,1) 100%); /* IE10+ */\n    background: linear-gradient(to right,  rgba(202,187,51,0) 0%,rgba(202,187,51,0.02) 1%,rgba(202,187,51,1) 30%,rgba(202,187,51,1) 100%); /* W3C */\n    filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#00269abc', endColorstr='#269abc',GradientType=1 ); /* IE6-9 */\n}\n\n.app-indicator.theme-10 > .btn-group {\n    border-color: #baab23;\n}\n\n.app-indicator.theme-10 > .btn-group .btn-default:hover, .app-indicator.theme-10 > .btn-group .btn-default:focus {\n    background-color: #baab23;\n}\n\n.app.theme-10 .actions+.dropdown-menu li:hover a {\n    background-color: #baab23;\n}\n\n.app.theme-10 .backdrop i {\n    color: #cebf37;\n}\n\n.app.theme-10 .logo i {\n    color: #baab23;\n}\n\n.active > .app.preview.theme-10, .app.theme-10:hover {\n    border-color: #baab23;\n}\n\n.app.theme-10 .actions:hover {\n    border-color: #cabb33;\n    color: #cabb33;\n}\n\n.create-app {\n    margin: 10px;\n    height: 200px;\n    padding: 5px;\n    background-color: #f8f8f7;\n}\n\n.create-app h3 {\n    font-size: 24px;\n    color: #666666;\n    line-height: 180px;\n    text-align: center;\n\n    -webkit-transition: font-size .2s ease;\n    -moz-transition: font-size .2s ease;\n    -o-transition: font-size .2s ease;\n    transition: font-size .2s ease;\n}\n\n.app.create-app:hover {\n    border-color: #eeeeee;\n}\n\n.app.create-app:hover h3{\n    font-size: 110px;\n}\n\n.app.create-app .fixed {\n    position: absolute;\n    top: 40px;\n    left: 0;\n    right: 0;\n    color: #666666;\n    visibility: hidden;\n    text-align: center;\n    font-size: 24px;\n}\n\n.app.create-app:hover .fixed {\n    visibility: visible;\n}\n\n.app.create-app .backdrop  {\n    color: #eeeeee;\n    top: -100px;\n}\n\n.app.create-app:hover .backdrop  {\n    top: -85px;\n}\n\n/** Landing logo (shared between apps) */\n\n.landing-logo {\n    line-height: 40px;\n    height: 40px;\n    width: 180px;\n    float: left;\n    cursor: pointer;\n}\n\n.landing-logo img {\n    max-height: 35px;\n    margin-top: -3px;\n    margin-left: 10px;\n}\n\n/** Password strength indicator */\n\n\nul#strength {\n    display:inline;\n    list-style:none;\n    margin:0;\n    margin-left:15px;\n    padding:0;\n    vertical-align:2px;\n}\n\nul#strength li {\n    background-color:#DDD;\n    border-radius:2px;\n    display:inline-block;\n    height:5px;\n    margin-right:1px;\n    width:20px;\n}\n\nul#strength li.pwd-very-weak {\n    background-color: #a02c2c;\n}\n\nul#strength li.pwd-weak {\n    background-color: #d45500;\n}\n\nul#strength li.pwd-good {\n    background-color: #ffcc00;\n}\n\nul#strength li.pwd-strong {\n    background-color: #aad400;\n}\n\nul#strength li.pwd-very-strong {\n    background-color: #71c837;\n}\n\nul#strength span {\n    font-weight: bold;\n    padding-left: 5px;\n}\n\nul#strength span.pwd-very-weak {\n    color: #a02c2c;\n}\n\nul#strength span.pwd-weak {\n    color: #d45500;\n}\n\nul#strength span.pwd-good {\n    color: #ffcc00;\n}\n\nul#strength span.pwd-strong {\n    color: #aad400;\n}\n\nul#strength span.pwd-very-strong {\n    color: #71c837;\n}\n\n\nul#strength > li:last-child {\n    margin:0;\n}\n\n.modal-body.content-preview-wrapper {\n    background-color: #404040;\n    padding: 0;\n}\n.modal-body.content-preview-wrapper .nothing-to-see {\n    background-color: #ffffff;\n    padding: 20px 0 0 0;\n    height: 480px;\n    text-align: center;\n    font-size: 15px;\n    color: #666666;\n}\n\n/**\n * Some modal windows need to have a scrollbar inside the modal window.\n * Use the following classes to do so.\n */\n\n.modal-body-with-overflow {\n    max-height: 500px;\n    overflow: auto;\n}\n\n.preview-image {\n    max-width: 100%;\n    max-height: 100%;\n    display: block;\n    margin-left: auto;\n    margin-right: auto;\n}\n\n@media (min-width: 1400px) {\n    .apps-wrapper {\n        width: 1400px;\n    }\n\n    .app-wrapper {\n        float: left;\n        width: 350px;\n    }\n}\n\n@media (max-width: 1200px) {\n    .apps-wrapper {\n        width: 900px;\n    }\n}\n\n\n/** Task details **/\n.summary-header {\n    margin-top: 10px;\n}\n.summary-header > div{\n    float: left;\n    margin-right: 15px;\n    border-left: 1px solid #cccccc;\n    padding-left: 15px;\n    min-height: 32px;\n}\n\n.summary-header.pack > div {\n    min-height: 32px;\n}\n\n.summary-header.pack  .title.title-lg {\n}\n\n.summary-header > div:first-child {\n    border-left: none;\n    padding-left: 0;\n}\n\n.summary-header .btn.btn-xs {\n    background-color: transparent;\n    border: 1px solid #bbbbbb;\n    color: #666666;\n    margin-top: 3px;\n}\n\n.summary-header .btn.btn-xs:hover, .summary-header .btn.btn-xs:active, .summary-header .btn.btn-xs:focus{\n    border: 1px solid #bbbbbb;\n    color: #666666;\n}\n\n.user-picture {\n    text-align: center;\n    font-size: 15px;\n    height: 32px;\n    width: 32px;\n    line-height: 32px;\n    padding: 0;\n    margin: 0 2px 0 0;\n    overflow: hidden;\n    color: #ffffff;\n    background: #2980b9 no-repeat center center;\n    background-size: 32px 32px;\n    cursor: pointer;\n    border: 1px solid transparent;\n}\n\n.summary-header .user-picture {\n    float: left;\n}\n\n.user-picture.no-picture {\n    border-color: #2980b9;\n}\n\n.user-picture span {\n    visibility: hidden;\n}\n\n.user-picture.more {\n    background-color: #6fc2d7;\n    color: #f6f6f6;\n}\n\n.user-picture.add {\n    background-color: #6fc2d7;\n    color: #f6f6f6;\n    font-size: 20px;\n    margin-left: 5px;\n}\n\n.user-picture:hover span, .user-picture.no-picture span, .user-picture.more span, .user-picture.add span {\n    visibility: visible;\n}\n\n.user-picture.no-picture:hover {\n    border-color: #32a3c0;\n}\n\n.summary-header .title {\n    margin-bottom: 2px;\n    font-size: 12px;\n    color: #666666;\n    cursor: pointer;\n}\n\n.summary-header .title.title-lg {\n    margin-top: 5px;\n    font-size: 14px;\n}\n\n.summary-header .title.title-lg > span {\n    font-size: 15px;\n}\n\n.summary-header .title > span {\n    font-size: 13px;\n    color: #555555;\n}\n\n.related-content {\n    float: left;\n    text-align: center;\n    height: 32px;\n    width: 32px;\n    line-height: 32px;\n    padding: 0;\n    margin: 0;\n    overflow: hidden;\n    cursor: pointer;\n}\n\n.related-content i.icon {\n    line-height: 32px;\n    font-size: 26px;\n}\n\n.related-content.more {\n    font-size: 15px;\n    color: #999999;\n    text-align: left;\n    padding: 0 5px;\n    width: auto;\n}\n\n.summary-header .title+.related-content {\n    margin-left: -4px;\n}\n\n\n.tabs {\n    list-style: none inside;\n    padding:0;\n    margin: 0;\n    border-bottom: 1px solid #bbbbbb;\n}\n\n.tabs > li {\n    display: block;\n    float: left;\n    margin-bottom: -1px;\n    border: 1px solid transparent;\n    border-bottom-color: #bbbbbb;\n}\n\n.tabs > li a {\n    display: block;\n    padding: 8px 40px;\n    text-decoration: none;\n    color: #888a85;\n    font-size: 16px;\n}\n.tabs > li a .badge {\n    min-width: 10px;\n    font-size: 12px;\n    margin-left: 4px;\n    padding: 2px 4px;\n    background-color: #5f8dd3;\n}\n\n.tabs > li a:hover {\n    text-decoration: none;\n    color: #5f8dd3;\n}\n\n.tabs > li.active {\n    border-color: #bbbbbb;\n    border-bottom-color: #ffffff;\n\n    -moz-border-radius-topleft: 5px;\n    -webkit-border-top-left-radius: 5px;\n    border-top-left-radius: 5px;\n    -moz-border-radius-topright: 5px;\n    -webkit-border-top-right-radius: 5px;\n    border-top-right-radius: 5px;\n\n}\n\n.tabs > li.active a {\n    color: #000000;\n    cursor: default;\n}\n\n.main-content .tabs {\n    padding: 0 0 0 10px;\n    margin-bottom: 5px;\n    margin-top: 8px;\n}\n\n.people-list.simple-list li {\n    line-height: 24px;\n    padding: 4px;\n}\n\n.people-list li .actions {\n    margin-top: 4px;\n}\n.simple-list .user-picture {\n    float: left;\n    font-size: 12px;\n    width: 24px;\n    height: 24px;\n    line-height: 24px;\n    background-size: 24px 24px;\n    margin-right: 6px;\n    border: none;\n}\n\n.content-group {\n    border-bottom: 1px dotted #eeeeee;\n    margin: 5px 0;\n}\n\n.content-group:last-child {\n    border: none;\n}\n\n/* Help */\n\n.help-container {\n    display: table;\n    height: 100%;\n    padding: 0 30px;\n    margin: 0px auto;\n}\n\n.help-container.fixed {\n    padding-top: 40px;\n}\n\n.help-container > div {\n    display: table-cell;\n    vertical-align: middle;\n    position: relative;\n}\n\n.help-text {\n    margin-top: 10px;\n    color: #636363;\n    background: #eee;\n    padding: 20px;\n    -webkit-border-radius: 10px;\n    -moz-border-radius: 10px;\n    border-radius: 10px;\n    max-width: 450px;\n    font-size: 14px;\n    position: relative;\n}\n\n.help-text.wide {\n    max-width: 550px;\n}\n\n.help-text .description {\n    margin-bottom: 25px;\n}\n\n.help-text .description:last-child {\n    margin-bottom: 0px;\n}\n\n.help-entry {\n    margin: 5px 0 5px 10px;\n    cursor: pointer;\n    padding: 5px;\n}\n\n.help-entry:hover, .help-entry.active {\n    background-color: #f6f6f7;\n}\n\n.help-entry.active {\n    padding: 10px;\n}\n\n.help-entry:hover > span {\n    color: #2980b9;\n}\n\n.help-entry.active:hover > span {\n    color: #636363;\n}\n\n.help-entry .pull-right > .btn {\n    border: none;\n}\n\n.help-entry .note, .action-note {\n    font-size: 12px;\n    color: #999999;\n    padding-left: 38px;\n}\n\n.help-entry:hover .note {\n    color: #999999;\n    text-decoration: none;\n}\n\n.action-note:hover {\n    text-decoration: underline;\n    cursor: pointer;\n}\n\n.help-entry > .glyphicon {\n    margin-right: 5px;\n}\n\n.help-entry > .icon {\n    margin-right: 5px;\n    font-size: 110%;\n}\n\n.help-text > a {\n    color: #636363;\n}\n\n.help-entry:hover > .glyphicon {\n    text-decoration: none;\n}\n\n.no-custom-apps .help-container {\n    float: left;\n    padding-left: 50px;\n}\n\n.content-list.simple-list li {\n    width: 50%;\n    float: left;\n    padding: 5px 10px;\n    margin-bottom: 10px;\n\n    white-space: nowrap;\n    overflow: hidden;\n    text-overflow: ellipsis;\n}\n\n.content-list.simple-list li .subtle {\n    white-space: nowrap;\n    overflow: hidden;\n    text-overflow: ellipsis;\n}\n\n.content-list.simple-list li:hover {\n    background-color: #ffffff;\n}\n\n.content-list.simple-list li .actions {\n    background-color: #ffffff;\n    border: 1px solid #eeeeee;\n    padding: 5px 4px 0 4px;\n    display: inline-block;\n    right: 0px;\n}\n\n.content-list.simple-list .subtle {\n    font-size: 12px;\n}\n.content-list.simple-list .nothing-to-see {\n    border: 1px solid #999999;\n    box-shadow: 1px 1px 2px #dddddd;\n    background-color: #ffffff;\n    width: 130px;\n    height: 155px;\n    padding: 50px 0 0 0;\n    text-align: center;\n}\n\n.content-list.simple-list .nothing-to-see .loading {\n    display: inline-block;\n    position: relative;\n    margin: 3px;\n    left: 0;\n}\n\n.frame {\n    white-space: nowrap;\n    text-align: left;\n    margin-bottom: 5px;\n    width: 100%;\n}\n\n.helper {\n    display: inline-block;\n}\n\n.frame img {\n    max-height: 155px;\n    padding: 5px;\n\n    border: 1px solid #999999;\n    box-shadow: 1px 1px 2px #dddddd;\n    background-color: #ffffff;\n}\n\n.content-list.simple-list li .frame .thumb-wrapper {\n    padding: 10px;\n    background-color: transparent;\n    display: inline-block;\n}\n.content-list.simple-list li:hover .frame .thumb-wrapper {\n    background-color: #eeeeee;\n}\n\n.form-wrapper .col-md-12 .content-list.simple-list li {\n    width: 25%;\n}\n\n.dynamicTableContainer {\n    /*min-height: 165px;*/\n}\n\n.dynamicTable {\n  border: 1px solid rgb(212,212,212) !important;\n  border-radius: 4px;\n  border-spacing: 2px;\n  display: block;\n  width: 100%;\n  height: 180px;\n  border-collapse: collapse;\n  margin-bottom: 5px;\n}\n\n.dynamicTable td, .dynamicTable tr {\n  border: 1px solid rgb(212,212,212) !important;\n  padding: 6px;\n}\n\n.dynamicTableContainer .control-buttons {\n  margin-bottom: 10px;\n}\n\n.edit-in-place-icon {\n    font-size: 20px;\n    color: darkgrey;\n    display: none;\n    margin-left: 5px;\n}\n.edit-in-place span {\n    cursor: pointer;\n}\n.edit-in-place:hover span {\n    display: inline-block;\n}\n.edit-in-place input {\n    display: none;\n}\n.edit-in-place.active span {\n    display: none;\n}\n.edit-in-place.active input {\n    display: inline-block;\n}\n\n.has-error .dynamicTable {\n  border: 1px solid #a94442 !important;\n}\n\n.noHeight {\n  height:auto;\n}\n\n"
  },
  {
    "path": "flowable-ui-web/idm/styles/style-idm.css",
    "content": "/** Copyright 2005-2015 Alfresco Software, Ltd.\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/* Login \n *\n * Based on http://bootsnipp.com/snippets/featured/custom-login-registration-amp-forgot-password \n * (MIT license) (see http://bootsnipp.com/license)\n *\n * Snippets License (MIT license)\n * Copyright (c) 2013 Bootsnipp.com\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), \n * 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 *\n * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n *\n * THE 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.login-container {\n    display: flex;\n    justify-content: center;\n    align-items: center;\n    background: #efefef;\n    height:100%;\n    width:100%\n}\n.login-form-1 {\n  max-width: 300px;\n  border-radius: 5px;\n  display: inline-block;\n}\n.main-login-form {\n  position: relative;\n}\n.login-form-1 .form-control {\n  border: 0;\n  box-shadow: 0 0 0;\n  border-radius: 0;\n  background: transparent;\n  color: #555555;\n  padding: 7px 0;\n  font-weight: bold;\n  height:auto;\n}\n.login-form-1 .form-control::-webkit-input-placeholder {\n  color: #999999;\n}\n.login-form-1 .form-control:-moz-placeholder,\n.login-form-1 .form-control::-moz-placeholder,\n.login-form-1 .form-control:-ms-input-placeholder {\n  color: #999999;\n}\n.login-form-1 .form-group {\n  margin-bottom: 0;\n  border-bottom: 2px solid #efefef;\n  padding-right: 20px;\n  position: relative;\n}\n.login-form-1 .form-group:last-child {\n  border-bottom: 0;\n}\n.login-group {\n  background: #ffffff;\n  color: #999999;\n  border-radius: 8px;\n  padding: 10px 20px;\n}\n.login-group-checkbox {\n  padding: 5px 0;\n}\n.login-form-1 .login-button {\n  position: absolute;\n  right: -25px;\n  top: 50%;\n  background: #ffffff;\n  color: #999999;\n  padding: 11px 0;\n  width: 50px;\n  height: 50px;\n  margin-top: -25px;\n  border: 5px solid #efefef;\n  border-radius: 50%;\n  transition: all ease-in-out 500ms;\n}\n.login-form-1 .login-button:hover {\n  color: #555555;\n  transform: rotate(450deg);\n}\n.login-form-1 .login-button.clicked {\n  color: #555555;\n}\n.login-form-1 .login-button.clicked:hover {\n  transform: none;\n}\n.login-form-1 .login-button.clicked.success {\n  color: #2ecc71;\n}\n.login-form-1 .login-button.clicked.error {\n  color: #e74c3c;\n}\n.login-form-main-message {\n  background: #ffffff;\n  color: #999999;\n  border-left: 3px solid transparent;\n  border-radius: 3px;\n  margin-bottom: 8px;\n  font-weight: bold;\n  height: 0;\n  padding: 0 20px 0 17px;\n  opacity: 0;\n  transition: all ease-in-out 200ms;\n}\n.login-form-main-message.show {\n  height: auto;\n  opacity: 1;\n  padding: 10px 20px 10px 17px;\n}\n.login-form-main-message.success {\n  border-left-color: #2ecc71;\n}\n.login-form-main-message.error {\n  border-left-color: #e74c3c;\n}\n.logo {\n  font-size: 25px;\n  color: #aaaaaa;\n  font-weight: bold;\n}\n.logo img {\n    width: 400px;\n    margin-bottom: 50px;\n}\n.login-error{\n    color: #e74c3c;\n    padding: 10px;\n}\n\n/**\n Colors:\n \n  - Header: #333333\n  - Subheader: #e8edf1\n  - Subheader border: #a4acb9\n  - Highlight buttons/text: #2980b9\n  - Text color: #1a1a1a\n  - Filter color: #373e48\n  - Dark highlight: #606b7d\n\n*/\n\nbody {\n\tbackground-color: #ffffff;\n\tpadding-bottom: 15px;\n}\n\n.btn .badge {\n\tbackground-color: #ffffff;\n\tcolor: #2980b9;\n}\n\n.item-wrapper > div {\n\tmargin-right: 5px;\n}\n\n.filter-list.compact {\n\tpadding-top: 0px;\t\n}\n\n ul {\n\tlist-style: none;\n\tlist-style-position: inside;\n\tpadding-left: 5px;\n}\n\n.box > div {\n\tmin-height: 50px;\n}\n.box h2 {\n\tmargin: 5px;\n\tfont-size: 18px;\n\tcolor: #606b7d;\n}\n.summaries {\n\twidth: 50%;\n}\n\n.user-summary {\n\ttext-align: center;\n\tmargin: 5px 1%;\n\tfloat: left;\n\twidth: 23%;\n}\n\n.user-summary .icon {\n\tfont-size: 30px;\n\theight: 30px;\n\tpadding: 0;\n\tmargin: 5px 0 0 0;\n\tline-height: 30px;\n\tcolor: #606b7d;\n}\n\n\n.user-summary span {\n\tline-height: 30px;\n}\n\n.item-wrapper .message a {\n\tpadding: 0 10px;\n}\n\n.users td {\n\tborder: 1px solid #f1f1f1;\n\tpadding: 5px;\n\tcolor: #373e48;\n}\n\ntd.control {\n\ttext-align: center;\n}\n\n.users tr.selected td {\n\t\tbackground-color: #f4f4f4;\n}\n\n.users tr:hover td{\n\tbackground-color: #e8edf1;\n\tborder: 1px solid #e8edf1;\n\tcursor: pointer;\n}\n\n\n.users th {\n\theight: 20px;\n\tbackground-color:#a4acb9;\n\tcolor: #ffffff;\n\tpadding: 5px;\n}\n\nul.user-list {\n\tpadding-left: 10px;\n}\nul.user-list i {\n\tpadding-right: 5px;\t\n}\n\nul.user-list li span {\n\tcolor: #666666;\n}\n\n.bar {\n\twidth: 100%;\n\tmargin: 5px 5px 5px 0px;\n\tpadding-right: 10px;\n\theight: 10px;\n\toverflow: hidden;\n}\n\n.bar > div {\n\theight: 10px;\n\tfloat: left;\n}\n\ni.user-active {\n\tcolor: #2980b9;\n}\n\ndiv.user-active {\n\tbackground-color: #2980b9;\n}\n\ni.user-inactive {\n\tcolor: #a4acb9;\n}\n\ndiv.user-inactive {\n\tbackground-color: #a4acb9;\n}\n\ni.user-deleted {\n\tcolor: #FF5741;\n}\n\ndiv.user-deleted {\n\tbackground-color: #FF5741;\n}\n\ni.user-pending {\n\tcolor: #FFC541;\n}\n\ndiv.user-pending {\n\tbackground-color: #FFC541;\n}\n\ni.user-trial {\n\tcolor: #a4acb9;\n}\n\ndiv.user-trial {\n\tbackground-color: #a4acb9;\n}\n\ni.user-enterprise {\n\tcolor: #2980b9;\n}\n\ndiv.user-enterprise {\n\tbackground-color: #2980b9;\n}\n\n.nopadding > div {\n\tpadding: 0px;\n}\n\n.nopadding .form-group {\n\tpadding-right: 5px;\n}\n\n/* List Filter */\n.filter-wrapper {\n    min-height: 400px;\n    margin-top: 10px;\n}\n\nul.filter-list {\n    list-style: none;\n    list-style-position: inside;\n    padding-left: 0px;\n    padding-top: 10px;\n}\n\nul.filter-list li a {\n    display: block;\n    color: #373e48;\n    font-size: 17px;\n    margin: 10px 5px 10px 0px;\n    padding-left: 10px;\n}\n\nul.filter-list li.current a {\n    color: #2980b9;\n    padding-left: 5px;\n    border-left: 4px solid #2980b9;\n}\n\nul.filter-list li a:hover, ul.filter-list li a:focus {\n    text-decoration: none;\n    background-color: #e8edf1;\n}\n\nul.filter-list li.current a:hover, ul.filter-list li.current a:focus {\n    background-color: transparent;\n    color: #2980b9;\n    cursor: default;\n    text-decoration: none;\n}\n\n.user-detail {\n    padding: 5px 40px 5px 0;\n}\n\n.users-details .glyphicon {\n    margin-right: 5px;\n}\n\n.subtle-event {\n    color: #606b7d;\n}\n\n/* Groups */\n\n.group-member .glyphicon {\n    margin-right: 5px;\n}\n\n.potential-group-member { \n    cursor: pointer;\n    font-size: 16px;\n}\n\n.potential-group-member-selected {\n    color: #2980b9;\n}\n\n.subgroup {\n    cursor: pointer;\n}\n\n.disabled-group {\n    text-decoration: line-through;\n    color: #808080;\n}\n\n/* Inspired by http://jsfiddle.net/mehmetatas/fXzHS/2/ */\n\n.group-tree li {\n    margin: 0px 0;\n    list-style-type: none;\n    position: relative;\n    padding: 20px 5px 0px 10px;\n}\n\n.group-tree ul {\n    padding-left: 10px;\n}\n\n.group-tree li::before {\n    content:'';\n    position: absolute;\n    top: 0;\n    width: 1px;\n    height: 100%;\n    right: auto;\n    left: 0px;\n    border-left: 1px solid #ccc;\n    bottom: 50px;\n}\n.group-tree li::after {\n    content:'';\n    position: absolute;\n    top: 35px;\n    width: 10px;\n    height: 20px;\n    right: auto;\n    left: 0px;\n    border-top: 1px solid #ccc;\n}\n.group-tree li a {\n    display: inline-block;\n    font-size: 16px;\n    border: 1px solid #ccc;\n    padding: 5px 16px;\n    text-decoration: none;\n    color: #000;\n    border-radius: 5px;\n    -webkit-border-radius: 5px;\n    -moz-border-radius: 5px;\n}\n\n.group-tree li a.active {\n    background-color: #c8e4f8;\n}\n\n.group-tree .group-icon {\n    font-size: 14px;\n    color: #999;\n    padding-right: 5px;\n}\n\n/*Remove connectors before root*/\n.group-tree > ul > li::before, .group-tree > ul > li::after {\n    border: 0;\n}\n/*Remove connectors after last child*/\n.group-tree li:last-child::before {\n    height: 35px;\n}\n\n/*We will apply the hover effect the lineage of the element also*/\n.group-tree li a:hover, .group-tree li a:hover+ul li a {\n    background-color: #eeeeee;\n    color: #000;\n}\n/*Connector styles on hover*/\n.group-tree li a:hover+ul li::after, .group-tree li a:hover+ul li::before, .group-tree li a:hover+ul::before, .group-tree li a:hover+ul ul::before {\n    border-color: #94a0b4;\n}\n\n.user-search-field {\n    margin: 20px 0 15px 0;\n    width: 40%;\n}\n\n/* profile */\n\n.profile-detail {\n    padding: 5px 0 5px 5px;\n    margin: 0 0 5px -5px;\n}\n\n.profile-detail:hover {\n    cursor: pointer;\n    background:  #e8edf1;\n}\n\n.profile-detail .nothing-to-see {\n    padding: 0px;\n    color: #999999;\n}\n\n.list-wrapper h4 {\n    font-size: 13px;\n    font-weight: normal;\n    text-transform: uppercase;\n    margin: 20px 0 5px 0;\n    color: #1a1a1a;\n}\n\n.main-content > .nothing-to-see {\n    margin: 20px 15px 10px 30px;\n    text-align: center;\n}\n\n.clickable {\n    cursor: pointer;\n}\n\n.tenant-logo-preview {\n    margin: 10px;\n}\n\n.table .actions {\n    text-align: right;\n}\n.table .actions > button {\n    padding: 3px 10px;\n    margin: 0px;\n    border: none;\n    background-color: transparent;\n    margin: 0;\n}\n.table .actions > button:hover {\n    background-color: #ffffff;\n    border: none;\n}\n\n.modal.modal-wide .modal-dialog {\n    width: 1000px;\n}\n\n.modal-dialog.modal-wide {\n    width: 1000px;\n}\n\n.modal-dialog.modal-maxheight {\n    max-height: 724px;\n    overflow-y: auto;\n}\n\n"
  },
  {
    "path": "flowable-ui-web/idm/views/common/popover/select-group-popover.html",
    "content": "<div class=\"popover\" click-anywhere=\"$hide()\" ignore-class=\"toggle-functional-group-select\">\n    <div class=\"arrow\"></div>\n    <div class=\"popover-header\">\n        <span class=\"title\">{{title && (title | translate) || ('GENERAL.TITLE.SELECT-GROUP' | translate)}}</span>\n\n        <div class=\"actions\">\n            <a ng-click=\"$hide()\">{{'GENERAL.ACTION.CLOSE' | translate}}</a>\n        </div>\n    </div>\n\n    <div class=\"popover-wrapper\">\n    \n        <div class=\"form-group\">\n            <input class=\"form-control\" type=\"text\" id=\"people-select-input\" placeholder=\"{{ 'GENERAL.MESSAGE.SELECT-GROUP-SEARCH-PLACEHOLDER' | translate }}\" auto-focus\n                   custom-keys up-pressed=\"previousGroup()\" down-pressed=\"nextGroup()\" enter-pressed=\"confirmGroup()\"\n                   delayed-model=\"popupModel.filter\" delay=\"200\"/>\n        </div>\n        <h4>\n            <span translate=\"GENERAL.TITLE.MATCHING-GROUPS\"></span>\n        </h4>\n        <div class=\"people-select\">\n            <div class=\"no-results\" ng-show=\"popupModel.groupResults.length == 0\">\n                <span>{{'GENERAL.MESSAGE.SELECT-GROUP-NO-MATCHING-RESULTS' | translate}}</span>\n            </div>\n            <ul class=\"simple-list selectable pack\" ng-show=\"popupModel.groupResults.length > 0\" scroll-to-active scroll-to-active-model=\"popupModel.selectedGroup.id\">\n                <li ng-click=\"confirmGroup(group);\" ng-repeat=\"group in popupModel.groupResults\"\n                    ng-class=\"{'active': group.id === popupModel.selectedGroup.id}\">\n                    <span>{{group.name}}</span>\n                </li>\n            </ul>\n        </div>\n        \n    </div>\n</div>"
  },
  {
    "path": "flowable-ui-web/idm/views/common/popover/select-people-popover.html",
    "content": "<div class=\"popover\" click-anywhere=\"$hide()\" ignore-class=\"toggle-people-select\">\n    <div class=\"arrow\"></div>\n    <div class=\"popover-header\">\n        <span class=\"title\">{{title && (title | translate) || ('GENERAL.TITLE.INVOLVE-PEOPLE' | translate)}}</span>\n\n        <div class=\"actions\">\n            <a ng-click=\"$hide()\" ng-show=\"!newTask.loading\">\n                {{'GENERAL.ACTION.CLOSE' | translate}}</a>\n        </div>\n    </div>\n\n    <div class=\"popover-wrapper\" ng-if=\"!popupModel.emailMode\">\n\n        <div class=\"form-group\" ng-if=\"popupModel.formFields\">\n            <div class=\"col-xs-4\">\n                <label>{{'INVOLVE-PEOPLE.SOURCE.TYPE' | translate}}</label>\n            </div>\n            <div class=\"col-xs-8\">\n                <div class=\"btn-group btn-group-justified\">\n                  <div class=\"btn-group\">\n                    <button type=\"button\" class=\"btn btn-default\" ng-click=\"setSearchType()\" ng-model=\"popupModel.userSourceType\" ng-class=\"{'active' : (!popupModel.userSourceType || popupModel.userSourceType == 'search')}\">{{'INVOLVE-PEOPLE.SOURCE.SEARCH-OPTION' | translate}}</button>\n                  </div>\n                  <div class=\"btn-group\">\n                    <button type=\"button\" class=\"btn btn-default\" ng-click=\"setFormFieldType()\" ng-model=\"popupModel.userSourceType\" ng-class=\"{'active' : popupModel.userSourceType == 'field'}\">{{'INVOLVE-PEOPLE.SOURCE.FIELD-OPTION' | translate}}</button>\n                  </div>\n                </div>\n            </div>\n        </div>\n        \n        <div ng-if=\"popupModel.formFields\" class=\"col-xs-12\" style=\"margin-bottom:10px\" />\n\n        <div ng-show=\"(!popupModel.userSourceType || popupModel.userSourceType == 'search')\">\n            <div class=\"form-group\">\n                <input class=\"form-control\" type=\"text\" id=\"people-select-input\" placeholder=\"{{ 'INVOLVE-PEOPLE.SEARCH-PLACEHOLDER' | translate }}\" auto-focus\n                       custom-keys up-pressed=\"previousUser()\" down-pressed=\"nextUser()\" enter-pressed=\"confirmUser()\"\n                       delayed-model=\"popupModel.filter\" delay=\"200\"/>\n                <div class=\"subtle\" translate=\"GENERAL.MESSAGE.SELECT-PEOPLE-HELP\" style=\"padding: 5px 0 0 1px;\"></div>\n            </div>\n            <h4>\n                <!--<span translate=\"GENERAL.TITLE.RECENT-PEOPLE\" ng-show=\"popupModel.showRecentResults\"></span>-->\n                <span translate=\"GENERAL.TITLE.MATCHING-PEOPLE\" ng-if=\"!popupModel.showRecentResults\"></span>\n            </h4>\n            <div class=\"people-select\">\n                <div class=\"no-results\" ng-show=\"popupModel.userResults.length == 0\">\n                    <span>{{'INVOLVE-PEOPLE.NO-MATCHING-RESULTS' | translate}}</span>\n                    <span class=\"people-select-link\"\n                          ng-click=\"$event.stopPropagation(); popupModel.emailMode = true\"\n                          ng-if=\"popupModel.emailDisabled == null || popupModel.emailDisabled == undefined || popupModel.emailDisabled == false\">\n                        {{'INVOLVE-PEOPLE.USE-EMAIL' | translate}}\n                    </span>\n                </div>\n                <ul class=\"simple-list selectable pack\" ng-show=\"popupModel.userResults.length > 0\" scroll-to-active scroll-to-active-model=\"popupModel.selectedUser.id\">\n                    <li ng-click=\"confirmUser(user);\" ng-repeat=\"user in popupModel.userResults\"\n                        ng-class=\"{'active': user.id === popupModel.selectedUser.id}\">\n                        <i class=\"icon icon-user\"></i><span user-name=\"user\"></span>\n                    </li>\n                </ul>\n            </div>\n        </div>\n        \n        <div ng-show=\"popupModel.userSourceType == 'field'\" class=\"form-group clearfix\">\n            <div class=\"col-xs-4\">\n                <label>{{'PROCESS-BUILDER.PUBLISH-STEP.SOURCE.FORM-FIELD' | translate}}:</label>\n            </div>\n            <div class=\"col-xs-8\">\n                <div id=\"userFormField\" variables-select include-type=\"false\" expand-relative=\"true\" field-type-filter=\"popupModel.userFieldFilter\"\n                       select-title=\"'FORM-BUILDER.MESSAGE.READONLY-TEXT-INSERT-FIELD'\" fields=\"popupModel.formFields\" selected-field=\"popupModel.userField\" ignore-selection=\"true\"></div>\n            </div>\n        </div>\n        \n    </div>\n\n    <div class=\"popover-wrapper\" ng-if=\"popupModel.emailMode && (popupModel.emailDisabled == null || popupModel.emailDisabled == undefined || popupModel.emailDisabled == false)\">\n        <form name=\"emailForm\" class=\"form-group\">\n            <div class=\"people-select\">\n                <div class=\"input-group\">\n                    <input name=\"emailInput\" class=\"form-control\" type=\"email\" placeholder=\"{{ 'INVOLVE-PEOPLE.EMAIL-PLACEHOLDER' | translate }}\"\n                           ng-model=\"popupModel.email\"\n                           custom-keys enter-pressed=\"selectPersonByEmail(!emailForm.emailInput.$error.email)\"\n                           auto-focus/>\n                    <span class=\"input-group-btn\">\n                        <button class=\"btn btn-sm\" type=\"button\" ng-disabled=\"popupModel.email == null || popupModel.email == undefined || popupModel.email.length == 0 || emailForm.emailInput.$error.email\"\n                                ng-click=\"selectPersonByEmail(!emailForm.emailInput.$error.email)\">{{'INVOLVE-PEOPLE.ACTION-SELECT' | translate}}</button>\n                    </span>\n                </div>\n                <div class=\"subtle\" translate=\"INVOLVE-PEOPLE.EMAIL-HELP\" style=\"padding: 5px 0 0 1px;\"></div>\n                <div class=\"clearfix\"></div>\n                <div class=\"people-select-link\" style=\"margin-top: 20px\"\n                     ng-click=\"$event.stopPropagation(); popupModel.emailMode = false\">\n                    <span ng-if=\"account.tenantId != null && account.tenantId != undefined\" class=\"glyphicon glyphicon-search\">&nbsp;</span>\n                    <span ng-if=\"account.tenantId != null && account.tenantId != undefined\" style=\"margin-left: -12px;\">{{'INVOLVE-PEOPLE.BACK-TO-SEARCH' | translate}}</span>\n                </div>\n            </div>\n        </form>\n    </div>\n</div>"
  },
  {
    "path": "flowable-ui-web/idm/views/empty.html",
    "content": "\n"
  },
  {
    "path": "flowable-ui-web/idm/views/idm-group-mgmt.html",
    "content": "\n<div class=\"main-list\" id=\"main-list\">\n    <div class=\"list-subheader clearfix\" style=\"margin-top: 0px; min-height: 60px\">\n        <div class=\"btn-group pull-right\">\n            <button class=\"btn\" translate=\"IDM.FUNCTIONAL-GROUP-MGMT.CREATE\" ng-click=\"showCreateGroupPopup()\">&nbsp;</button>\n        </div>\n    </div>\n    <div class=\"list-wrapper\" auto-height>\n\n        <span loading=\"model.loading\"></span>\n\n        <div class=\"list-wrapper\" ng-show=\"!model.loading\">\n\n            <ul class=\"full-list\" offset-top=\"100\">\n                <li ng-repeat=\"group in model.groups\" ng-class=\"{'active': model.selectedGroup.id == group.id}\" ng-click=\"selectGroup(group.id)\">\n                    <div>\n                        <div class=\"title\">\n                            {{group.name}}\n                        </div>\n                    </div>\n                </li>\n            </ul>\n            <div class=\"nothing-to-see\" ng-show=\"model.tasks.length == 0\">\n                <span  translate=\"TASK.MESSAGE.NO-TASKS\"></span>\n            </div>\n        </div>\n\n\n        <div class=\"nothing-to-see\" ng-if=\"model.groups.length == 0\">\n            <span  translate=\"IDM.FUNCTIONAL-GROUP-MGMT.NO-GROUPS\"></span>\n        </div>\n\n    </div>\n</div>\n\n<div class=\"main-content-wrapper\">\n\n    <div class=\"main-content\" ng-show=\"!model.loadingGroup\">\n\n        <div class=\"header\" ng-if=\"model.selectedGroup\">\n\n            <div class=\"pull-right\">\n                <button class=\"btn btn-clean\" ng-click=\"showEditGroupModal()\">\n                    <span class=\"glyphicon glyphicon-pencil\"></span>\n                </button>\n                <button class=\"btn btn-clean\" ng-click=\"showActivateGroupModal()\" ng-if=\"model.selectedGroup.status == 'inactive'\">\n                    <span class=\"glyphicon glyphicon-ok\"></span>\n                </button>\n                <button class=\"btn btn-clean\" ng-click=\"showDeleteGroupModal()\">\n                    <span class=\"glyphicon glyphicon-trash\"></span>\n                </button>\n            </div>\n\n            <h2>\n                <span>{{model.selectedGroup.name}}</span>\n                <span ng-if=\"model.selectedGroup.status == 'inactive'\">({{'IDM.FUNCTIONAL-GROUP-MGMT.INACTIVE' | translate}})</span>\n            </h2>\n\n        </div>\n\n        <div class=\"content\" ng-show=\"model.selectedGroup\" auto-height offset=\"70\">\n\n            <span loading=\"model.loadingGroup\"></span>\n\n            <div ng-if=\"!model.loadingGroup\">\n\n                <div class=\"col-xs-12\">\n\n                    <div class=\"section\" style=\"min-height: 0; font-style: italic;\" ng-if=\"model.selectedGroup.status == 'inactive'\">\n                        <blockquote>\n                            {{'IDM.FUNCTIONAL-GROUP-MGMT.INACTIVE-DESCRIPTION' | translate}}\n                        </blockquote>\n                    </div>\n\n                    <!-- Users -->\n                    <div class=\"section\" style=\"min-height: 0\">\n\n                        <h3 style=\"margin-bottom: 10px;\">\n                            {{'IDM.FUNCTIONAL-GROUP-MGMT.MEMBERS' | translate}}\n                            <span class=\"action\">\n                                 <a id=\"toggle-add-group-member\"\n                                    select-people-popover\n                                    popover-title=\"IDM.FUNCTIONAL-GROUP-MGMT.ADD-POPOVER-TITLE\"\n                                    placement=\"bottom\"\n                                    on-people-selected=\"addGroupMember(user)\"\n                                    email-mode-disabled=\"true\"\n                                    tenant-id=\"common.selectedTenantId\"\n                                    type=\"'idm'\"\n                                    style=\"font-weight: normal\">\n                                     {{'IDM.FUNCTIONAL-GROUP-MGMT.ADD-USER' | translate}}\n                                 </a>\n                            </span>\n                        </h3>\n\n                        <div class=\"input-group user-search-field\">\n                        <span class=\"input-group-addon\">\n                            <i class=\"glyphicon glyphicon-search\"></i>\n                        </span>\n                            <input type=\"text\" ng-model=\"model.userFilter\" class=\"form-control\" ng-change=\"refreshDelayed()\">\n                        </div>\n\n                        <span loading=\"model.loadingUsers\"></span>\n\n                    <span ng-if=\"model.users.data && model.users.data.length > 0\">\n                        {{'IDM.USER-MGMT.MATCHING-USERS' | translate:model.users}}\n    \t\t\t\t\t<a ng-click=\"showPreviousUsers()\" ng-show=\"model.userPage > 0\">&laquo; {{'IDM.USER-MGMT.SHOW-PREVIOUS' | translate}} {{model.pageSize}}</a>\n\t\t\t\t\t\t<span ng-show=\"model.userPage > 0 && model.moreUsers\">|</span>\n\t\t\t\t\t\t<a ng-click=\"showNextUsers()\" ng-show=\"model.moreUsers\">{{'IDM.USER-MGMT.SHOW-NEXT' | translate}} {{model.pageSize}} &raquo;</a>\n\t\t\t\t\t</span>\n\n                        <table width=\"100%\" class=\"users\" ng-if=\"model.users.data && model.users.data.length > 0\">\n                            <tr>\n                                <th width=\"30%\">{{'IDM.USER-MGMT.ID' | translate}}</th>\n                                <th width=\"30%\">{{'IDM.USER-MGMT.EMAIL' | translate}}</th>\n                                <th width=\"30%%\">{{'IDM.USER-MGMT.NAME' | translate}}</th>\n                                <th width=\"10%\"></th>\n                            </tr>\n                            <tr ng-repeat=\"user in model.users.data\">\n                                <td>{{user.id}}</td>\n                                <td>{{user.email}}</td>\n                                <td>{{user.firstName}} {{user.lastName}}</td>\n                                <td align=\"center\" ng-click=\"showRemoveMemberModal(user)\"><i class=\"glyphicon glyphicon-trash\" ></i></td>\n                            </tr>\n                        </table>\n\n                        <div ng-if=\"!model.users || model.users.length == 0\">\n                            <span>{{'IDM.FUNCTIONAL-GROUP-MGMT.NO-MEMBERS' | translate}}</span>\n                        </div>\n                    </div>\n\n                </div>\n\n            </div>\n\n        </div>\n\n        <div class=\"nothing-to-see\" ng-if=\"model.groups.length > 0 && !model.selectedGroup && !model.loading\">\n            <span>{{'IDM.FUNCTIONAL-GROUP-MGMT.NO-SELECTION' | translate}}</span>\n        </div>\n\n    </div>\n\n</div>\n"
  },
  {
    "path": "flowable-ui-web/idm/views/idm-privilege-mgmt.html",
    "content": "<div class=\"main-list\" id=\"main-list\">\n    <div class=\"list-wrapper\" auto-height>\n\n        <span loading=\"model.loading\"></span>\n\n        <div class=\"list-wrapper\" ng-show=\"!model.loading\">\n            <ul class=\"full-list\" offset-top=\"100\">\n                <li ng-repeat=\"privilege in model.privileges\" ng-class=\"{'active': model.selectedPrivilege.id == privilege.id}\" ng-click=\"selectPrivilege(privilege)\">\n                    <div>\n                        <div class=\"title\">\n                            {{'IDM.PRIVILEGE-MGMT.' + privilege.name | translate}}\n                        </div>\n                    </div>\n                </li>\n            </ul>\n        </div>\n\n    </div>\n</div>\n\n<div class=\"main-content-wrapper\">\n\n    <div class=\"main-content\" ng-show=\"!model.loadingPrivilege\">\n\n        <div class=\"header\" ng-if=\"model.selectedPrivilege\">\n\n            <h2>\n                <span>{{'IDM.PRIVILEGE-MGMT.' + model.selectedPrivilege.name | translate}}</span>\n            </h2>\n\n        </div>\n\n        <div class=\"content\" ng-show=\"model.selectedPrivilege\" auto-height offset=\"70\">\n            <div style=\"margin-top:10px\">\n\n                <ul class=\"nav nav-tabs\" role=\"tablist\">\n                    <li role=\"presentation\" class=\"active\">\n                        <a data-target=\"#users\" aria-controls=\"users\" role=\"tab\" data-toggle=\"tab\">\n                            {{'IDM.PRIVILEGE-MGMT.USERS' | translate}}\n                        </a>\n                    </li>\n                    <li role=\"presentation\">\n                        <a data-target=\"#groups\" aria-controls=\"groups\" role=\"tab\" data-toggle=\"tab\">\n                            {{'IDM.PRIVILEGE-MGMT.GROUPS' | translate}}\n                        </a>\n                    </li>\n                </ul>\n\n                <div class=\"tab-content\" style=\"padding:10px\">\n\n                    <div role=\"tabpanel\" class=\"tab-pane active\" id=\"users\">\n\n                        <span class=\"action\">\n                            <a id=\"toggle-add-group-member\"\n                                    select-people-popover\n                                    popover-title=\"IDM.PRIVILEGE-MGMT.POPOVER-SELECT-USER-TITLE\"\n                                    placement=\"bottom\"\n                                    on-people-selected=\"addUserPrivilege(user)\"\n                                    email-mode-disabled=\"true\"\n                                    type=\"'idm'\"\n                                    style=\"font-weight: normal\">\n                                    <span ng-if=\"!model.selectedPrivilege.users || model.selectedPrivilege.users.length == 0\">\n                                        {{'IDM.PRIVILEGE-MGMT.NO-USERS' | translate}}\n                                    </span>\n                                    <span ng-if=\"model.selectedPrivilege.users && model.selectedPrivilege.users.length != 0\">\n                                        {{'IDM.PRIVILEGE-MGMT.ADD-USER' | translate}}\n                                    </span>     \n                            </a>\n                        </span>\n\n                        <div class=\"section\" ng-if=\"model.selectedPrivilege.users && model.selectedPrivilege.users.length != 0\">\n\n                            <table width=\"100%\" class=\"users\">\n                                <tr>\n                                    <th width=\"30%\">{{'IDM.USER-MGMT.ID' | translate}}</th>\n                                    <th width=\"30%\">{{'IDM.USER-MGMT.EMAIL' | translate}}</th>\n                                    <th width=\"30%%\">{{'IDM.USER-MGMT.NAME' | translate}}</th>\n                                    <th width=\"10%\"></th>\n                                </tr>\n                                <tr ng-repeat=\"user in model.selectedPrivilege.users\">\n                                    <td>{{user.id}}</td>\n                                    <td>{{user.email}}</td>\n                                    <td>{{user.firstName}} {{user.lastName}}</td>\n                                    <td align=\"center\" ng-click=\"deleteUserPrivilege(user)\"><i class=\"glyphicon glyphicon-trash\"></i></td>\n                                </tr>\n                            </table>\n                        </div>\n\n                    </div>\n\n                    <div role=\"tabpanel\" class=\"tab-pane\" id=\"groups\">\n\n                        <span class=\"action\">\n                            <a id=\"toggle-add-group-member\"\n                                    select-group-popover\n                                    popover-title=\"IDM.PRIVILEGE-MGMT.POPOVER-SELECT-GROUP-TITLE\"\n                                    placement=\"bottom\"\n                                    on-group-selected=\"addGroupPrivilege(group)\"\n                                    email-mode-disabled=\"true\"\n                                    type=\"'idm'\"\n                                    style=\"font-weight: normal\">\n                                    <span ng-if=\"!model.selectedPrivilege.groups || model.selectedPrivilege.groups.length == 0\">\n                                        {{'IDM.PRIVILEGE-MGMT.NO-GROUPS' | translate}}\n                                    </span>\n                                    <span ng-if=\"model.selectedPrivilege.groups && model.selectedPrivilege.groups.length != 0\">\n                                        {{'IDM.PRIVILEGE-MGMT.ADD-GROUP' | translate}}\n                                    </span>     \n                            </a>\n                        </span>\n\n                        <div class=\"section\" ng-if=\"model.selectedPrivilege.groups && model.selectedPrivilege.groups.length != 0\">\n\n                            <table width=\"100%\" class=\"users\">\n                                <tr>\n                                    <th width=\"30%\">{{'IDM.PRIVILEGE-MGMT.GROUP-ID' | translate}}</th>\n                                    <th width=\"30%%\">{{'IDM.PRIVILEGE-MGMT.GROUP-NAME' | translate}}</th>\n                                    <th width=\"10%\"></th>\n                                </tr>\n                                <tr ng-repeat=\"group in model.selectedPrivilege.groups\">\n                                    <td>{{group.id}}</td>\n                                    <td>{{group.name}}</td>\n                                    <td align=\"center\" ng-click=\"deleteGroupPrivilege(group)\"><i class=\"glyphicon glyphicon-trash\"></i></td>\n                                </tr>\n                            </table>\n                        </div>\n\n                    </div>\n\n                </div>\n\n            </div>\n\n        </div>\n\n        <div class=\"nothing-to-see\" ng-if=\"!model.selectedPrivilege\">\n            <span>{{'IDM.PRIVILEGE-MGMT.NO-SELECTION' | translate}}</span>\n        </div>\n\n    </div>\n\n</div>"
  },
  {
    "path": "flowable-ui-web/idm/views/idm-profile-mgmt.html",
    "content": "\n<div class=\"main-content-wrapper\">\n\n    <span loading=\"model.loading\"></span>\n\n    <div class=\"main-content\" ng-if=\"!model.loading\">\n\n        <div class=\"header\">\n\n            <div class=\"pull-right\">\n                <button class=\"btn btn-clean\" ng-click=\"showChangePasswordModal()\">\n                    <span>{{'IDM.PROFILE-MGMT.CHANGE-PASSWORD' | translate}}</span>\n                </button>\n            </div>\n\n            <div style=\"float:left; width:60px;\">\n                <img ng-src=\"{{restRootUrl()}}/app/rest/admin/profile-picture?{{cacheBuster()}}\"\n                     style=\"width:60px; height: 60px;\"\n                     class=\"img-thumbnail clickable\"\n                     ng-click=\"showUploadPictureModal()\">\n            </div>\n\n            <div>\n                <h2 style=\"margin-left:70px;margin-top:15px;\">{{model.profile.firstName}} {{model.profile.lastName}}</h2>\n            </div>\n\n        </div>\n\n        <div class=\"content\" auto-height offset=\"6\">\n\n            <div style=\"margin-left:15px;\">\n                <h2>{{'IDM.PROFILE-MGMT.DETAILS' | translate}}</h2>\n                <h5>{{'IDM.PROFILE-MGMT.DETAILS-DESCRIPTION' | translate}}</h5>\n            </div>\n\n            <div class=\"row section\">\n\n                <div class=\"col-xs-12\">\n\n                    <div>\n\n                        <h4 class=\"control-label\">{{'IDM.PROFILE-MGMT.FIRST-NAME' | translate}}</h4>\n\n                        <div ng-if=\"!model.editingFirstName\" class=\"profile-detail\"\n                             ng-click=\"model.editingFirstName = true\">\n                            <span ng-if=\"model.profile.firstName != null  && model.profile.firstName !== undefined\">{{model.profile.firstName}}</span>\n                            <span ng-if=\"model.profile.firstName == null || model.profile.firstName == undefined || model.profile.firstName == ''\" class=\"nothing-to-see\">{{'IDM.PROFILE-MGMT.NOTHING-SET' | translate}}</span>\n                        </div>\n                        <div class=\"form-group\" ng-if=\"model.editingFirstName\">\n                            <input type=\"text\" class=\"form-control\" auto-focus ng-model=\"model.profile.firstName\"\n                                   ng-blur=\"firstNameChanged()\"\n                                   custom-keys enter-pressed=\"firstNameChanged()\">\n                        </div>\n\n                        <h4 class=\"control-label\">{{'IDM.PROFILE-MGMT.LAST-NAME' | translate}}</h4>\n\n                        <div ng-if=\"!model.editingLastName\" class=\"profile-detail\"\n                             ng-click=\"model.editingLastName = true\">\n                            <span ng-if=\"model.profile.lastName != null && model.profile.lastName !== undefined\">{{model.profile.lastName}}</span>\n                            <span ng-if=\"model.profile.lastName == null || model.profile.lastName == undefined || model.profile.lastName == ''\" class=\"nothing-to-see\">{{'IDM.PROFILE-MGMT.NOTHING-SET' | translate}}</span>\n                        </div>\n                        <div class=\"form-group\" ng-if=\"model.editingLastName\">\n                            <input type=\"text\" class=\"form-control\" auto-focus ng-model=\"model.profile.lastName\"\n                                   ng-blur=\"lastNameChanged()\"\n                                   custom-keys enter-pressed=\"lastNameChanged()\">\n                        </div>\n\n                        <h4 class=\"control-label\">\n                            <span>{{'IDM.PROFILE-MGMT.EMAIL' | translate}}</span>\n                            <span ng-if=\"model.profile.emailErrorMessage\" style=\"color:red; font-size: 12px\">{{model.profile.emailErrorMessage | translate}}</span>\n                        </h4>\n\n                        <div ng-if=\"!model.editingEmail\" class=\"profile-detail\" ng-click=\"model.editingEmail = true\">\n                            <span ng-if=\"model.profile.email != null && model.profile.email != undefined\">{{model.profile.email}}</span>\n                            <span ng-if=\"model.profile.email == null || model.profile.email == undefined\" class=\"nothing-to-see\">{{'IDM.PROFILE-MGMT.NOTHING-SET' | translate}}</span>\n                            {{model.profile.emailErrorMessage | translate}}\n                        </div>\n                        <div class=\"form-group\" ng-if=\"model.editingEmail\">\n                            <input type=\"text\" class=\"form-control\" auto-focus ng-model=\"model.profile.email\"\n                                   ng-blur=\"emailChanged()\"\n                                   custom-keys enter-pressed=\"emailChanged()\">\n                        </div>\n\n                    </div>\n                </div>\n\n            </div>\n\n            <div clas=\"section\" class=\"col-xs-12\" ng-if=\"model.profile.groups && model.profile.groups.length > 0\">\n\n                <h2>{{'IDM.PROFILE-MGMT.GROUPS' | translate}}</h2>\n                <ul class=\"simple-list\">\n                    <li ng-repeat=\"group in model.profile.groups\">\n                        <span style=\"margin-right: 5px;\" class=\"glyphicon glyphicon-folder-close\"></span>\n                        <span>{{group.name}}</span>\n                    </li>\n                </ul>\n            </div>\n\n\n        </div>\n\n    </div>\n\n</div>"
  },
  {
    "path": "flowable-ui-web/idm/views/idm-user-mgmt.html",
    "content": "\n<div class=\"main-list\" id=\"main-list\">\n    <div class=\"list-subheader clearfix\" style=\"margin-top: 0px\">\n        <div class=\"btn-group pull-right\">\n            <button class=\"btn\" translate=\"IDM.USER-MGMT.CREATE-USER\" ng-click=\"addUser()\">&nbsp;</button>\n        </div>\n    </div>\n    <div class=\"list-wrapper\" auto-height>\n\n        <div style=\"padding: 0 15px 15px 15px;\">\n\n            <h4>{{'IDM.USER-MGMT.NAME-SEARCH' | translate}}</h4>\n            <div class=\"input-group\">\n                <span class=\"input-group-addon\">\n                    <i class=\"glyphicon glyphicon-search\"></i>\n                </span>\n                <input type=\"text\" ng-model=\"model.pendingFilterText\" class=\"form-control\" ng-change=\"refreshDelayed()\">\n            </div>\n        </div>\n\n    </div>\n</div>\n\n<div class=\"main-content-wrapper\">\n\n    <div class=\"main-content\" ng-show=\"!model.loadingTenant\">\n\n        <div class=\"header\">\n\n            <div class=\"pull-right\">\n                <div class=\"btn-group\">\n                    <button type=\"button\" class=\"btn btn-default\" ng-disabled=\"model.selectedUserCount == 0\">{{'IDM.USER-MGMT.ACTIONS' | translate}}</button>\n                    <button type=\"button\" class=\"btn btn-default dropdown-toggle\" data-toggle=\"dropdown\" ng-disabled=\"model.selectedUserCount == 0\">\n                        <span class=\"caret\"></span>\n                    </button>\n                    <ul class=\"dropdown-menu\" role=\"menu\">\n                        <li ng-click=\"editUserDetails()\" ng-if=\"model.selectedUserCount == 1\"><a href=\"\">{{'IDM.USER-MGMT.EDIT-USER' | translate}}</a></li>\n                        <li ng-click=\"editUserPassword()\"><a href=\"\">{{'IDM.USER-MGMT.CHANGE-PASSWORD' | translate}}</a></li>\n                        <li ng-click=\"deleteUsers()\"><a href=\"\">{{'IDM.USER-MGMT.DELETE-USERS' | translate}}</a></li>\n                    </ul>\n                </div>\n\n            </div>\n            <div>\n                <h2>{{'IDM.USER-MGMT.TITLE' | translate}}</h2>\n            </div>\n\n        </div>\n\n        <div class=\"content\" auto-height offset=\"6\">\n            <div style=\"margin-top: 10px;\">\n                <div class=\"dropdown-subtle pull-right\">\n                    <div class=\"btn-group btn-group-sm\" style=\"margin-bottom: 5px;\">\n                        <button type=\"button\" class=\"btn btn-default dropdown-toggle\"\n                                data-toggle=\"dropdown\">{{'IDM.USER-MGMT.ORDER-BY' | translate}} {{model.activeSort.name}} <i class=\"caret\"></i></button>\n                        <ul class=\"dropdown-menu pull-right\">\n                            <li ng-repeat=\"sort in model.sorts\">\n                                <a ng-click=\"activateSort(sort)\">{{sort.name}}</a>\n                            </li>\n                        </ul>\n                    </div>\n                </div>\n                <div class=\"message clearfix\">\n                    <div ng-if=\"!model.loading\">\n\t\t\t\t\t\t\t\t<span ng-if=\"model.users && model.users.data.length > 0\">\n                                    {{'IDM.USER-MGMT.MATCHING-USERS' | translate:model.users}}\n\t\t\t\t\t\t\t\t\t<a ng-click=\"showPreviousUsers()\" ng-show=\"model.users.start > 0\">&laquo; {{'IDM.USER-MGMT.SHOW-PREVIOUS' | translate}} {{model.users.size}}</a>\n\t\t\t\t\t\t\t\t\t<span ng-show=\"model.users.start > 0 && model.users.moreUsers\">|</span>\n\t\t\t\t\t\t\t\t\t<a ng-click=\"showNextUsers()\" ng-show=\"model.users.moreUsers\">{{'IDM.USER-MGMT.SHOW-NEXT' | translate}} {{model.users.size}} &raquo;</a>\n\t\t\t\t\t\t\t\t</span>\n                        <span ng-if=\"!model.users || model.users.total == 0\">{{'IDM.USER-MGMT.NO-MATCHING-USERS' | translate}}</span>\n                    </div>\n\n                    <table width=\"100%\" class=\"users\" ng-if=\"model.users && model.users.data.length > 0\">\n                        <tr>\n                            <th width=\"4%\"></th>\n                            <th width=\"20%\">{{'IDM.USER-MGMT.ID' | translate}}</th>\n                            <th width=\"30%\">{{'IDM.USER-MGMT.EMAIL' | translate}}</th>\n                            <th width=\"30%\">{{'IDM.USER-MGMT.NAME' | translate}}</th>\n                        </tr>\n                        <tr ng-repeat=\"user in model.users.data\" ng-click=\"toggleUserSelection(user)\" ng-class=\"{'selected': model.selectedUsers[user.id]}\">\n                            <td class=\"control\"><input type=\"checkbox\" ng-checked=\"model.selectedUsers[user.id]\"></td>\n                            <td>{{user.id}}</td>\n                            <td>{{user.email}}</td>\n                            <td>{{user.fullName}}</td>\n                        </tr>\n                    </table>\n                </div>\n            </div>\n        </div>\n\n    </div>\n\n</div>\n"
  },
  {
    "path": "flowable-ui-web/idm/views/login.html",
    "content": "<div class=\"login-container\">\n    <div class=\"text-center\" style=\"padding:50px 0\">\n        <div class=\"logo\">\n            <img src=\"images/logo-login.png\" srcset=\"images/logo-login.png 1x, images/logo-login@2x.png 2x\">\n        </div>\n        <div class=\"login-form-1\">\n            <form id=\"login-form\" class=\"text-left\">\n                <div class=\"login-form-main-message\"></div>\n                <div class=\"main-login-form\">\n                    <div class=\"login-group\">\n                        <div class=\"form-group\">\n                            <input type=\"text\" class=\"form-control\" id=\"username\" placeholder=\"{{'LOGIN.USERNAME-PLACEHOLDER' | translate}}\" ng-model=\"username\" auto-focus>\n                        </div>\n                        <div class=\"form-group\">\n                            <input type=\"password\" class=\"form-control\" id=\"password\" placeholder=\"{{'LOGIN.PASSWORD-PLACEHOLDER' | translate}}\" ng-model=\"password\" >\n                        </div>\n                    </div>\n                    <button type=\"submit\" class=\"login-button\"  ng-click=\"login()\" ng-disabled=\"model.loading\">\n                        <i class=\"glyphicon glyphicon-chevron-right\"></i>\n                    </button>\n                </div>\n\n                <div ng-if=\"invalidCredentials\" class=\"login-error\">\n                    <p translate=\"LOGIN.INVALID-CREDENTIALS\"></p>\n                </div>\n            </form>\n        </div>\n    </div>\n</div>"
  },
  {
    "path": "flowable-ui-web/idm/views/popup/idm-activate-group.html",
    "content": "\n<div class=\"modal\" tabindex=\"-1\" role=\"dialog\">\n    <div class=\"modal-dialog\">\n        <div class=\"modal-content\">\n            <div class=\"modal-header\">\n                <button type=\"button\" class=\"close\" ng-click=\"$hide()\">&times;</button>\n\n                <h4 class=\"modal-title\">\n                    {{'IDM.FUNCTIONAL-GROUP-MGMT.POPUP.ACTIVATE-TITLE' | translate}}\n                </h4>\n\n            </div>\n            <div class=\"modal-body\">\n\n                <div>\n                    {{'IDM.FUNCTIONAL-GROUP-MGMT.POPUP.ACTIVATE-DESCRIPTION' | translate}}\n                </div>\n\n\n            </div>\n\n            <div class=\"modal-footer\">\n                <button type=\"button\" class=\"btn btn-default\" ng-click=\"$hide()\">{{'IDM.GENERAL.ACTION.CANCEL' | translate}}</button>\n                <button type=\"button\" class=\"btn btn-primary\" ng-click=\"activateGroup(); $hide()\">{{'IDM.FUNCTIONAL-GROUP-MGMT.POPUP.ACTIVATE-CONFIRM' | translate}}</button>\n            </div>\n\n        </div>\n    </div>\n</div>"
  },
  {
    "path": "flowable-ui-web/idm/views/popup/idm-change-password.html",
    "content": "\n<div class=\"modal\" tabindex=\"-1\" role=\"dialog\" ng-controller=\"IdmChangePasswordController\">\n    <div class=\"modal-dialog\">\n        <div class=\"modal-content\">\n            <div class=\"modal-header\">\n                <button type=\"button\" class=\"close\" ng-click=\"$hide()\">&times;</button>\n                <h4 class=\"modal-title\">{{'IDM.PROFILE-MGMT.POPUP.CHANGE-PASSWORD-TITLE' | translate}}</h4>\n            </div>\n            <div class=\"modal-body\">\n\n                <div clas=\"form-group\">\n\n                    <label>{{'IDM.PROFILE-MGMT.POPUP.CHANGE-PASSWORD-ORIGINAL' | translate}}</label>\n                    <input auto-focus type=\"password\" class=\"form-control\" ng-model=\"model.changePassword.originalPassword\">\n\n                    <label>{{'IDM.PROFILE-MGMT.POPUP.CHANGE-PASSWORD-NEW-PASSWORD' | translate}}</label>\n                    <input type=\"password\" class=\"form-control\" ng-model=\"model.changePassword.newPassword\">\n\n                    <label>{{'IDM.PROFILE-MGMT.POPUP.CHANGE-PASSWORD-NEW-PASSWORD2' | translate}}</label>\n                    <input type=\"password\" class=\"form-control\" ng-model=\"model.changePassword.newPassword2\">\n\n                </div>\n\n                <div ng-if=\"showPasswordsDontMatch()\" style=\"color: red\">\n                    <span>{{'IDM.PROFILE-MGMT.POPUP.CHANGE-PASSWORD-NOT-MATCHING' | translate}}</span>\n                </div>\n\n\n            </div>\n\n            <div class=\"modal-footer\">\n                <div class=\"pull-left\" ng-if=\"model.changePassword.error\" style=\"color: red\">\n                    <span>{{'IDM.PROFILE-MGMT.POPUP.CHANGE-PASSWORD-INVALID' | translate}}</span>\n                </div>\n\n                <button type=\"button\" class=\"btn btn-default\" ng-click=\"$hide()\">{{'IDM.GENERAL.ACTION.CANCEL' | translate}}</button>\n                <button type=\"button\" class=\"btn btn-primary\" ng-disabled=\"isConfirmButtonDisabled()\" ng-click=\"changePassword();\">{{'IDM.PROFILE-MGMT.POPUP.CHANGE-PASSWORD-CONFIRM' | translate}}</button>\n            </div>\n\n        </div>\n    </div>\n</div>"
  },
  {
    "path": "flowable-ui-web/idm/views/popup/idm-delete-group.html",
    "content": "\n<div class=\"modal\" tabindex=\"-1\" role=\"dialog\">\n    <div class=\"modal-dialog\">\n        <div class=\"modal-content\">\n            <div class=\"modal-header\">\n                <button type=\"button\" class=\"close\" ng-click=\"$hide()\">&times;</button>\n\n                <h4 class=\"modal-title\" ng-if=\"model.selectedGroup.type == 0 || (model.selectedGroup.type == 1 && model.selectedGroup.status == 'inactive')\">\n                    {{'IDM.SYSTEM-GROUP-MGMT.POPUP.DELETE-TITLE' | translate}}\n                </h4>\n\n                <h4 class=\"modal-title\" ng-if=\"model.selectedGroup.type == 1 && model.selectedGroup.status != 'inactive'\">\n                    {{'IDM.FUNCTIONAL-GROUP-MGMT.POPUP.DEACTIVATE-TITLE' | translate}}\n                </h4>\n\n            </div>\n            <div class=\"modal-body\">\n\n                <div>\n                    {{'IDM.FUNCTIONAL-GROUP-MGMT.POPUP.DELETE-DESCRIPTION' | translate}}\n                </div>\n\n            </div>\n\n            <div class=\"modal-footer\">\n                <button type=\"button\" class=\"btn btn-default\" ng-click=\"$hide()\">{{'IDM.GENERAL.ACTION.CANCEL' | translate}}</button>\n                <button type=\"button\" class=\"btn btn-primary\" ng-click=\"deleteGroup(); $hide()\">{{'IDM.FUNCTIONAL-GROUP-MGMT.POPUP.DELETE-CONFIRM' | translate}}</button>\n            </div>\n\n        </div>\n    </div>\n</div>"
  },
  {
    "path": "flowable-ui-web/idm/views/popup/idm-group-create.html",
    "content": "\n<div class=\"modal\" tabindex=\"-1\" role=\"dialog\">\n    <div class=\"modal-dialog\">\n        <div class=\"modal-content\">\n\n            <div class=\"modal-header\">\n                <button type=\"button\" class=\"close\" ng-click=\"$hide()\">&times;</button>\n                <h4 class=\"modal-title\" ng-if=\"model.mode == 'create'\">\n                    {{'IDM.FUNCTIONAL-GROUP-MGMT.POPUP.CREATE-TITLE' | translate}}\n                </h4>\n                <h4 class=\"modal-title\" ng-if=\"model.mode == 'edit'\">\n                    {{'IDM.FUNCTIONAL-GROUP-MGMT.POPUP.EDIT-TITLE' | translate}}\n                </h4>\n            </div>\n\n            <div class=\"modal-body\">\n\n                <div class=\"form-group\" ng-if=\"model.mode == 'create'\">\n\n                    <label class=\"control-label\">{{'IDM.FUNCTIONAL-GROUP-MGMT.POPUP.CREATE-ID' | translate}}</label>\n                    <input type=\"text\" class=\"form-control\" ng-model=\"model.editedGroup.id\" auto-focus>\n\n                </div>\n\n                <div class=\"form-group\">\n\n                    <label class=\"control-label\">{{'IDM.FUNCTIONAL-GROUP-MGMT.POPUP.CREATE-NAME' | translate}}</label>\n                    <input type=\"text\" class=\"form-control\" ng-model=\"model.editedGroup.name\">\n\n                </div>\n\n            </div>\n\n            <div class=\"modal-footer\">\n                <button type=\"button\" class=\"btn btn-default\" ng-click=\"$hide()\">{{'IDM.GENERAL.ACTION.CANCEL' | translate}}</button>\n                <button type=\"button\" ng-if=\"model.mode == 'create'\" class=\"btn btn-primary\" ng-disabled=\"!model.editedGroup.id || !model.editedGroup.name || model.editedGroup.name.length == 0\"\n                        ng-click=\"createGroup(); $hide()\">{{'IDM.GENERAL.ACTION.SAVE' | translate}}</button>\n                <button type=\"button\" ng-if=\"model.mode == 'edit'\" class=\"btn btn-primary\" ng-disabled=\"!model.editedGroup.id || !model.editedGroup.name || model.editedGroup.name.length == 0\"\n                        ng-click=\"updateGroup(); $hide()\">{{'IDM.GENERAL.ACTION.SAVE' | translate}}</button>\n            </div>\n\n        </div>\n    </div>\n</div>\n"
  },
  {
    "path": "flowable-ui-web/idm/views/popup/idm-group-member-delete.html",
    "content": "\n<div class=\"modal\" tabindex=\"-1\" role=\"dialog\">\n    <div class=\"modal-dialog\">\n        <div class=\"modal-content\">\n            <div class=\"modal-header\">\n                <button type=\"button\" class=\"close\" ng-click=\"$hide()\">&times;</button>\n                <h4 class=\"modal-title\">{{'IDM.FUNCTIONAL-GROUP-MGMT.POPUP.DELETE-MEMBER-TITLE' | translate}}</h4>\n            </div>\n            <div class=\"modal-body\">\n\n                <div>\n                    {{'IDM.FUNCTIONAL-GROUP-MGMT.POPUP.DELETE-MEMBER-DESCRIPTION' | translate}}\n                </div>\n\n            </div>\n\n            <div class=\"modal-footer\">\n                <button type=\"button\" class=\"btn btn-default\" ng-click=\"$hide()\">{{'IDM.GENERAL.ACTION.CANCEL' | translate}}</button>\n                <button type=\"button\" class=\"btn btn-primary\" ng-click=\"deleteGroupMember(); $hide()\">{{'IDM.FUNCTIONAL-GROUP-MGMT.POPUP.DELETE-CONFIRM' | translate}}</button>\n            </div>\n\n        </div>\n    </div>\n</div>"
  },
  {
    "path": "flowable-ui-web/idm/views/popup/idm-profile-picture-upload.html",
    "content": "\n<div class=\"modal\" ng-controller=\"UploadUserPictureController\">\n    <div class=\"modal-dialog\">\n        <div class=\"modal-content\">\n\n            <div class=\"modal-header-wrapper\">\n                <div class=\"modal-header\">\n                    <button type=\"button\" class=\"close\" ng-click=\"$hide()\">&times;</button>\n                    <h2 class=\"modal-title\">{{'IDM.PROFILE-MGMT.POPUP.UPLOAD-PICTURE-TITLE' | translate}}</h2>\n                </div>\n            </div>\n\n            <div class=\"modal-body\">\n            \n                <p>\n                    <i class=\"glyphicon glyphicon-info-sign\"></i>\n                    {{'IDM.PROFILE-MGMT.POPUP.UPLOAD-PICTURE-DESCRIPTION' | translate}}\n                </p>\n            \n                <div class=\"upload-image-form\">\n            \n                    <input type=\"file\" ngf-select=\"\" ngf-change=\"onFileSelect($files)\" style=\"font-size: smaller; padding-top:6px;\" >\n                    <div class=\"upload-image-dropbox\"\n                         ngf-drop ngf-change=\"onFileSelect($files)\"\n                         ngf-drag-over-class=\"dragover\"\n                         ng-show=\"dropSupported\">\n                        {{'IDM.PROFILE-MGMT.POPUP.UPLOAD-PICTURE-DROPZONE' | translate}}\n                    </div>\n                    <div ngf-drop-available=\"dropSupported=true\"\n                         ng-show=\"!dropSupported\">{{'IDM.PROFILE-MGMT.POPUP.UPLOAD-PICTURE-NO-DROP' | translate}}</div>\n                    <div class=\"graph-wrapper\" ng-show=\"status.loading\" style=\"margin: 10px 0 10px 0\">\n                        <div class=\"graph-bar\" ng-style=\"{width: popup.uploadProgress + '%'}\"></div>\n                    </div>\n                    <button class=\"btn btn-danger btn-sm\"\n                            ng-click=\"upload.abort()\"\n                            ng-disabled=\"!status.loading\"\n                            style=\"margin-bottom: 20px\">\n                        {{'IDM.PROFILE-MGMT.POPUP.UPLOAD-PICTURE-CANCEL-UPLOAD' | translate}}\n                    </button>\n            \n                </div>\n            \n            </div>\n            \n            <div class=\"modal-footer-wrapper\">\n                <div class=\"modal-footer\">\n                    <span loading=\"popup.loading\"></span>\n                    <div class=\"pull-right\" ng-if=\"popup.error\">\n                        <span>{{'IDM.PROFILE-MGMT.POPUP.UPLOAD-PICTURE-ERROR' | translate}} <span ng-if=\"popup.errorMessage\"> : </span>{{popup.errorMessage}}</span>\n                    </div>\n                </div>\n            </div>\n        </div>\n    </div>\n</div>"
  },
  {
    "path": "flowable-ui-web/idm/views/popup/idm-user-create.html",
    "content": "\n<div class=\"modal\" ng-controller=\"IdmCreateUserPopupController\">\n    <div class=\"modal-dialog\">\n        <div class=\"modal-content\">\n\n            <div class=\"modal-header-wrapper\">\n                <div class=\"modal-header\">\n                    <button type=\"button\" class=\"close\" ng-click=\"$hide()\">&times;</button>\n                    <h2 class=\"modal-title\" ng-if=\"model.mode == 'create'\">\n                        {{'IDM.USER-MGMT.POPUP.CREATE-TITLE' | translate}}\n                    </h2>\n                    <h2 class=\"modal-title\" ng-if=\"model.mode == 'edit'\">\n                        {{'IDM.USER-MGMT.POPUP.EDIT-TITLE' | translate}}\n                    </h2>\n                </div>\n\n            </div>\n\n            <div  class=\"modal-body\">\n\n                <form name=\"newUserForm\" class=\"row\">\n\n                    <div class=\"col-xs-12\" ng-if=\"model.mode == 'create'\">\n                        <div class=\"form-group\">\n                            <label class=\"control-label\">{{'IDM.USER-MGMT.POPUP.CREATE-ID' | translate}}</label>\n                            <input name=\"idInput\" type=\"text\" class=\"form-control\" auto-focus ng-model=\"model.user.id\">\n                        </div>\n                    </div>\n                    <div class=\"col-xs-12\">\n                        <div class=\"form-group\">\n                            <label class=\"control-label\">{{'IDM.USER-MGMT.POPUP.CREATE-EMAIL' | translate}}</label>\n                            <span style=\"color:white; background-color: red; padding: 0 5px 0 5px\" ng-show=\"newUserForm.emailInput.$error.email\">\n                                {{'IDM.USER-MGMT.POPUP.CREATE-INVALID-EMAIL' | translate}}\n                            </span>\n                            <input name=\"emailInput\" type=\"email\" class=\"form-control\" ng-model=\"model.user.email\">\n                        </div>\n                    </div>\n                    <div class=\"col-xs-12\" ng-if=\"model.mode == 'create'\">\n                        <div class=\"form-group\">\n                            <label class=\"control-label\">{{'IDM.USER-MGMT.POPUP.CREATE-PASSWORD' | translate}}</label>\n                            <input type=\"password\" class=\"form-control\" ng-model=\"model.user.password\">\n                        </div>\n                    </div>\n                    <div class=\"col-xs-6\">\n                        <div class=\"form-group\">\n                            <label class=\"control-label\">{{'IDM.USER-MGMT.POPUP.CREATE-FIRSTNAME' | translate}}</label>\n                            <input type=\"text\" class=\"form-control\" ng-model=\"model.user.firstName\">\n                        </div>\n                    </div>\n                    <div class=\"col-xs-6\">\n                        <div class=\"form-group\">\n                            <label class=\"control-label\">{{'IDM.USER-MGMT.POPUP.CREATE-LASTNAME' | translate}}</label>\n                            <input type=\"text\" class=\"form-control\" ng-model=\"model.user.lastName\">\n                        </div>\n                    </div>\n\n                </form>\n\n                <div class=\"alert error\" ng-if=\"model.errorMessage\">\n                    {{model.errorMessage}}\n                </div>\n\n            </div>\n\n            <div class=\"modal-footer-wrapper\">\n                <div class=\"modal-footer\">\n                    <button type=\"button\" class=\"btn btn-default\" ng-click=\"$hide()\">{{'IDM.GENERAL.ACTION.CANCEL' | translate}}</button>\n                    <button ng-if=\"model.mode == 'create'\"\n                            type=\"button\"\n                            class=\"btn btn-primary\"\n                            ng-disabled=\"model.loading || !model.user.id || !model.user.password || !model.user.firstName\"\n                            ng-click=\"createNewUser();\">{{'IDM.GENERAL.ACTION.SAVE' | translate}}\n                    </button>\n                    <button ng-if=\"model.mode == 'edit'\"\n                            type=\"button\"\n                            class=\"btn btn-primary\"\n                            ng-disabled=\"model.loading || !model.user.id || !model.user.lastName\"\n                            ng-click=\"editUserDetails();\">{{'IDM.GENERAL.ACTION.SAVE' | translate}}\n                    </button>\n                </div>\n            </div>\n\n        </div>\n\n    </div>\n</div>\n\n"
  },
  {
    "path": "flowable-ui-web/idm/views/popup/idm-user-password-change.html",
    "content": "\n<div class=\"modal\" ng-controller=\"IdmUserBulkUpdatePopupController\">\n    <div class=\"modal-dialog\">\n        <div class=\"modal-content\">\n\n            <div class=\"modal-header-wrapper\">\n                <div class=\"modal-header\">\n                    <button type=\"button\" class=\"close\" ng-click=\"$hide()\">&times;</button>\n                    <h2 class=\"modal-title\">{{'IDM.USER-MGMT.POPUP.BULK-UPDATE-PASSWORD-TITLE' | translate}}</h2>\n                </div>\n            </div>\n\n            <div class=\"modal-body\">\n\n                <form role=\"form\">\n                    <div class=\"form-group\">\n                        <label for=\"password\">{{'IDM.USER-MGMT.POPUP.BULK-UPDATE-PASSWORD' | translate}}</label><br />\n                        <input id=\"password\" type=\"password\" class=\"form-control\" ng-model=\"model.updateUsers.password\" auto-focus>\n                    </div>\n                    <div class=\"form-group\">\n                        <label for=\"passwordRepeat\">{{'IDM.USER-MGMT.POPUP.BULK-UPDATE-PASSWORD-REPEAT' | translate}}</label><br />\n                        <input id=\"passwordRepeat\" type=\"password\" class=\"form-control\" ng-model=\"model.updateUsers.repeatPassword\">\n                    </div>\n                </form>\n                <div class=\"well\">\n                    <p>{{'IDM.USER-MGMT.POPUP.BULK-UPDATE-STATUS-USERS' | translate: getSelectedUsers()}}</p>\n                    <ul class=\"user-list\">\n                        <li ng-repeat=\"user in getSelectedUsers()\">\n                            <i class=\"glyphicon glyphicon-user\"></i> {{user.fullname}} <span>({{user.type}} - {{user.email}})</span>\n                        </li>\n                    </ul>\n                </div>\n\n            </div>\n\n            <div class=\"modal-footer-wrapper\">\n                <div class=\"modal-footer\">\n                    <div class=\"pull-right\">\n                        <button type=\"button\" class=\"btn btn-sm btn-default\" ng-click=\"$hide()\" ng-disabled=\"model.loading\">\n                            {{'IDM.USER-MGMT.POPUP.BULK-UPDATE-CANCEL' | translate}}\n                        </button>\n                        <button type=\"button\" class=\"btn btn-sm btn-default\" ng-click=\"updateUsers();$hide()\"\n                                ng-disabled=\"model.loading || model.updateUsers.password.length==0 || (model.updateUsers.password != model.updateUsers.repeatPassword)\">\n                            {{'IDM.USER-MGMT.POPUP.BULK-UPDATE-PASSWORD-CONFIRM' | translate}}\n                        </button>\n                    </div>\n                </div>\n            </div>\n        </div>\n    </div>\n</div>"
  },
  {
    "path": "flowable-ui-web/idm/views/popup/idm-user-status-edit.html",
    "content": "\n<div class=\"modal\" ng-controller=\"IdmUserBulkUpdatePopupController\">\n    <div class=\"modal-dialog\">\n        <div class=\"modal-content\">\n\n            <div class=\"modal-header-wrapper\">\n                <div class=\"modal-header\">\n                    <button type=\"button\" class=\"close\" ng-click=\"$hide()\">&times;</button>\n                    <h2 class=\"modal-title\">{{'IDM.USER-MGMT.POPUP.BULK-UPDATE-TITLE' | translate}}</h2>\n                </div>\n            </div>\n\n            <div class=\"modal-body\">\n\n                <div class=\"form-group\">\n                    <label>{{'IDM.USER-MGMT.POPUP.BULK-UPDATE-NEW-STATUS' | translate}}</label><br />\n                    <div class=\"btn-group\">\n                        <button type=\"button\" class=\"btn btn-default dropdown-toggle\"\n                                data-toggle=\"dropdown\">\n                            {{model.updateUsers.status.name}} <i class=\"caret\"></i>\n                        </button>\n                        <ul class=\"dropdown-menu pull-left\">\n                            <li ng-repeat=\"status in model.statusFilters\" ng-if=\"status.id != 'all'\"><a ng-click=\"setStatus(status)\">{{status.name}}</a></li>\n                        </ul>\n                    </div>\n                </div>\n                <div class=\"checkbox\">\n                    <label>\n                        <input type=\"checkbox\" value=\"\" ng-model=\"model.updateUsers.sendNotifications\">\n                        {{'IDM.USER-MGMT.POPUP.BULK-UPDATE-EMAIL-NOTIFICATIONS' | translate}}\n                    </label>\n                </div>\n                <div class=\"well\">\n                    <p>{{'IDM.USER-MGMT.POPUP.BULK-UPDATE-STATUS-USERS' | translate: getSelectedUsers()}}</p>\n                    <ul class=\"user-list\">\n                        <li ng-repeat=\"user in getSelectedUsers()\">\n                            <i class=\"glyphicon glyphicon-user\"></i> {{user.fullname}} <span>({{user.status}} - {{user.email}})</span>\n                        </li>\n                    </ul>\n                </div>\n            </div>\n\n            <div class=\"modal-footer-wrapper\">\n                <div class=\"modal-footer\">\n                    <div class=\"pull-right\">\n                        <button type=\"button\" class=\"btn btn-sm btn-default\" ng-click=\"$hide()\" ng-disabled=\"model.loading\">\n                            {{'IDM.USER-MGMT.POPUP.BULK-UPDATE-CANCEL' | translate}}\n                        </button>\n                        <button type=\"button\" class=\"btn btn-sm btn-default\" ng-click=\"updateUsers();$hide()\" ng-disabled=\"model.loading || !model.updateUsers.status\">\n                            {{'IDM.USER-MGMT.POPUP.BULK-UPDATE-CONFIRM' | translate}}\n                        </button>\n                    </div>\n                </div>\n            </div>\n        </div>\n    </div>\n</div>"
  },
  {
    "path": "flowable-ui-web/idm/views/popup/idm-user-type-edit.html",
    "content": "<div class=\"modal\" ng-controller=\"IdmUserBulkUpdatePopupController\">\n    <div class=\"modal-dialog\">\n        <div class=\"modal-content\">\n\n            <div class=\"modal-header-wrapper\">\n                <div class=\"modal-header\">\n                    <button type=\"button\" class=\"close\" ng-click=\"$hide()\">&times;</button>\n                    <h2 class=\"modal-title\">{{'IDM.USER-MGMT.POPUP.BULK-UPDATE-TITLE' | translate}}</h2>\n                </div>\n            </div>\n\n            <div class=\"modal-body\">\n\n                <div class=\"form-group\">\n                    <label>{{'IDM.USER-MGMT.POPUP.BULK-UPDATE-NEW-TYPE' | translate}}</label><br />\n                    <div class=\"btn-group\">\n                        <button type=\"button\" class=\"btn btn-default dropdown-toggle\"\n                                data-toggle=\"dropdown\">\n                            {{model.updateUsers.type.name}} <i class=\"caret\"></i>\n                        </button>\n                        <ul class=\"dropdown-menu pull-left\">\n                            <li ng-repeat=\"type in model.typeFilters\" ng-if=\"type.id != 'all'\"><a ng-click=\"setType(type)\">{{type.name}}</a></li>\n                        </ul>\n                    </div>\n                </div>\n                <div class=\"well\">\n                    <p>{{'IDM.USER-MGMT.POPUP.BULK-UPDATE-STATUS-USERS' | translate: getSelectedUsers()}}</p>\n                    <ul class=\"user-list\">\n                        <li ng-repeat=\"user in getSelectedUsers()\">\n                            <i class=\"glyphicon glyphicon-user\"></i> {{user.fullname}} <span>({{user.type}} - {{user.email}})</span>\n                        </li>\n                    </ul>\n                </div>\n\n            </div>\n\n            <div class=\"modal-footer-wrapper\">\n                <div class=\"modal-footer\">\n                    <div class=\"pull-right\">\n                        <button type=\"button\" class=\"btn btn-sm btn-default\" ng-click=\"$hide()\" ng-disabled=\"model.loading\">\n                            {{'IDM.USER-MGMT.POPUP.BULK-UPDATE-CANCEL' | translate}}\n                        </button>\n                        <button type=\"button\" class=\"btn btn-sm btn-default\" ng-click=\"updateUsers();$hide()\" ng-disabled=\"model.loading || !model.updateUsers.type\">\n                            {{'IDM.USER-MGMT.POPUP.BULK-UPDATE-CONFIRM' | translate}}\n                        </button>\n                    </div>\n                </div>\n            </div>\n        </div>\n    </div>\n</div>"
  },
  {
    "path": "flowable-ui-web/modeler/404.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"utf-8\">\n    <title>Page Not Found :(</title>\n    <style>\n      ::-moz-selection {\n        background: #b3d4fc;\n        text-shadow: none;\n      }\n\n      ::selection {\n        background: #b3d4fc;\n        text-shadow: none;\n      }\n\n      html {\n        padding: 30px 10px;\n        font-size: 20px;\n        line-height: 1.4;\n        color: #737373;\n        background: #f0f0f0;\n        -webkit-text-size-adjust: 100%;\n        -ms-text-size-adjust: 100%;\n      }\n\n      html,\n      input {\n        font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n      }\n\n      body {\n        max-width: 500px;\n        _width: 500px;\n        padding: 30px 20px 50px;\n        border: 1px solid #b3b3b3;\n        border-radius: 4px;\n        margin: 0 auto;\n        box-shadow: 0 1px 10px #a7a7a7, inset 0 1px 0 #fff;\n        background: #fcfcfc;\n      }\n\n      h1 {\n        margin: 0 10px;\n        font-size: 50px;\n        text-align: center;\n      }\n\n      h1 span {\n        color: #bbb;\n      }\n\n      h3 {\n        margin: 1.5em 0 0.5em;\n      }\n\n      p {\n        margin: 1em 0;\n      }\n\n      ul {\n        padding: 0 0 0 40px;\n        margin: 1em 0;\n      }\n\n      .container {\n        max-width: 380px;\n        _width: 380px;\n        margin: 0 auto;\n      }\n\n      /* google search */\n\n      #goog-fixurl ul {\n        list-style: none;\n        padding: 0;\n        margin: 0;\n      }\n\n      #goog-fixurl form {\n        margin: 0;\n      }\n\n      #goog-wm-qt,\n      #goog-wm-sb {\n        border: 1px solid #bbb;\n        font-size: 16px;\n        line-height: normal;\n        vertical-align: top;\n        color: #444;\n        border-radius: 2px;\n      }\n\n      #goog-wm-qt {\n        width: 220px;\n        height: 20px;\n        padding: 5px;\n        margin: 5px 10px 0 0;\n        box-shadow: inset 0 1px 1px #ccc;\n      }\n\n      #goog-wm-sb {\n        display: inline-block;\n        height: 32px;\n        padding: 0 10px;\n        margin: 5px 0 0;\n        white-space: nowrap;\n        cursor: pointer;\n        background-color: #f5f5f5;\n        background-image: -webkit-linear-gradient(rgba(255,255,255,0), #f1f1f1);\n        background-image: -moz-linear-gradient(rgba(255,255,255,0), #f1f1f1);\n        background-image: -ms-linear-gradient(rgba(255,255,255,0), #f1f1f1);\n        background-image: -o-linear-gradient(rgba(255,255,255,0), #f1f1f1);\n        -webkit-appearance: none;\n        -moz-appearance: none;\n        appearance: none;\n        *overflow: visible;\n        *display: inline;\n        *zoom: 1;\n      }\n\n      #goog-wm-sb:hover,\n      #goog-wm-sb:focus {\n        border-color: #aaa;\n        box-shadow: 0 1px 1px rgba(0, 0, 0, 0.1);\n        background-color: #f8f8f8;\n      }\n\n      #goog-wm-qt:hover,\n      #goog-wm-qt:focus {\n        border-color: #105cb6;\n        outline: 0;\n        color: #222;\n      }\n\n      input::-moz-focus-inner {\n        padding: 0;\n        border: 0;\n      }\n    </style>\n  </head>\n  <body>\n    <div class=\"container\">\n      <h1>Not found <span>:(</span></h1>\n      <p>Sorry, but the page you were trying to view does not exist.</p>\n      <p>It looks like this was the result of either:</p>\n      <ul>\n        <li>a mistyped address</li>\n        <li>an out-of-date link</li>\n      </ul>\n      <script>\n        var GOOG_FIXURL_LANG = (navigator.language || '').slice(0,2),GOOG_FIXURL_SITE = location.host;\n      </script>\n      <script src=\"//linkhelp.clients.google.com/tbproxy/lh/wm/fixurl.js\"></script>\n    </div>\n  </body>\n</html>\n"
  },
  {
    "path": "flowable-ui-web/modeler/browserconfig.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<browserconfig>\n  <msapplication>\n    <tile>\n      <square150x150logo src=\"images/mstile-150x150.png?v=Om5N75Y123\"/>\n      <TileColor>#da532c</TileColor>\n    </tile>\n  </msapplication>\n</browserconfig>\n"
  },
  {
    "path": "flowable-ui-web/modeler/display/.gitignore",
    "content": "/dist\n/node_modules\n/displaymodel_temp.html\n"
  },
  {
    "path": "flowable-ui-web/modeler/display/Gruntfile.js",
    "content": "/* 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'use strict';\n\nmodule.exports = function (grunt) {\n\n    require('load-grunt-tasks')(grunt);\n    require('time-grunt')(grunt);\n\n    grunt.initConfig({\n        yeoman: {\n            app: require('./package.json').appPath || 'app',\n            dist: 'dist'\n        },\n        clean: {\n            dist: {\n                files: [\n                    {\n                        dot: true,\n                        src: [\n                            '.tmp',\n                            '<%= yeoman.dist %>/*',\n                            '!<%= yeoman.dist %>/.git*'\n                        ]\n                    }\n                ]\n            },\n            server: '.tmp'\n        },\n        useminPrepare: {\n            html: 'displaymodel.html',\n            options: {\n                dest: '<%= yeoman.dist %>/'\n            }\n        },\n        usemin: {\n            html: ['<%= yeoman.dist %>/{,*/}*.html'],\n            css: ['<%= yeoman.dist %>/display/styles/{,*/}*.css'],\n            options: {\n                dirs: ['<%= yeoman.dist %>']\n            }\n        },\n        // Put files not handled in other tasks here\n        copy: {\n          dist: {\n            files: [{\n              expand: true,\n              dot: true,\n              cwd: '.',\n              dest: '<%= yeoman.dist %>',\n              src: [\n                'fonts/*'\n              ]\n            }, {\n              expand: true,\n              cwd: '.tmp/images',\n              dest: '<%= yeoman.dist %>/images',\n              src: [\n                'generated/*'\n              ]\n            }]\n          },\n          styles: {\n            expand: true,\n            cwd: 'styles',\n            dest: '.tmp/styles/',\n            src: '{,*/}*.css'\n          },\n          index: {\n            expand: true,\n            cwd: './',\n            src: ['*.html', 'views/**/**.html'],\n            dest: '<%= yeoman.dist %>'\n          },\n          copyCss : {\n            files: [\n          {expand: true, cwd:'.tmp/concat/display/styles/', src:'*.css', dest:'<%= yeoman.dist %>/display/styles/', filter: 'isFile'}\n            ]\n          },\n          copyJs : {\n            files: [\n          {expand: true, cwd:'.tmp/concat/display/scripts', src:'*.js', dest:'<%= yeoman.dist %>/display/scripts/', filter: 'isFile'}\n            ]\n          },\n        },  \n        ngAnnotate: {\n            dist: {\n                files: [\n                    {\n                        expand: true,\n                        cwd: '.tmp/concat/display/scripts',\n                        src: '*.js',\n                        dest: '.tmp/concat/display/scripts'\n                    }\n                ]\n            }\n        },\n        uglify: {\n            dist: {\n                options: {\n                    mangle: true\n                },\n                files: {\n                    '<%= yeoman.dist %>/display/scripts/displaymodel-logic.js': [\n                        '<%= yeoman.dist %>/display/scripts/displaymodel-logic.js'\n                    ]\n                }\n            }\n        },\n        rev: {\n            dist: {\n                files: {\n                    src: [\n                        '<%= yeoman.dist %>/display/{,*/}*.js',\n                        '<%= yeoman.dist %>/display/{,*/}*.css',\n                        '<%= yeoman.dist %>/{,*/}*.{png,jpg,jpeg,gif,webp,svg}'\n                    ]\n                }\n            }\n        }\n    });\n\n    grunt.registerTask('buildApp', [\n        'clean:dist',\n        'useminPrepare',\n        'copy:styles',\n        'concat',\n        'copy:dist',\n        'ngAnnotate',\n        'copy:copyCss',\n        'copy:copyJs',\n        'copy:index',\n        'uglify',\n        'rev',\n        'usemin'\n    ]);\n\n\n    grunt.registerTask('default', [\n        'buildApp'\n    ]);\n\n};\n"
  },
  {
    "path": "flowable-ui-web/modeler/display/Polyline.js",
    "content": "/* Copyright 2005-2015 Alfresco Software, Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n * \n *      http://www.apache.org/licenses/LICENSE-2.0\n * \n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Class to generate polyline\n *\n * @author Dmitry Farafonov\n */\n \nvar ANCHOR_TYPE= {\n\tmain: \"main\",\n\tmiddle: \"middle\",\n\tfirst: \"first\",\n\tlast: \"last\"\n};\n\nfunction Anchor(uuid, type, x, y) {\n\tthis.uuid = uuid; \n\tthis.x = x;\n\tthis.y = y;\n\tthis.type = (type == ANCHOR_TYPE.middle) ? ANCHOR_TYPE.middle : ANCHOR_TYPE.main;\n};\nAnchor.prototype = {\n\tuuid: null,\n\tx: 0,\n\ty: 0,\n\ttype: ANCHOR_TYPE.main,\n\tisFirst: false,\n\tisLast: false,\n\tndex: 0,\n\ttypeIndex: 0\n};\n\nfunction Polyline(uuid, points, strokeWidth, paper) {\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.paper = paper;\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: 1,\n\tshowDetails: false,\n\tpaper: null,\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{\n\t\t\tvar line1 = this.getLine(i-1);\n\t\t\tthis.pushAnchor(ANCHOR_TYPE.main,  line1.x2, line1.y2);\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    if (this.points.length > i && this.points[i]) {\n\t        return {x1: this.points[i].x, y1: this.points[i].y, x2: this.points[i+1].x, y2: this.points[i+1].y};\n\t    } else {\n\t        return undefined;\n\t    }\n\t},\n\tgetLine: function(i){\n\t\tvar line = this._getLine(i);\n\t\tif (line != undefined) {\n\t\t    line.angle = this.getLineAngle(i);\n\t\t}\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\treturn Math.sqrt(Math.pow(this.getLineLengthX(i), 2) + Math.pow(this.getLineLengthY(i), 2));\n\t},\n\t\n\tgetAnchors: function(){\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\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\t\t\t// 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\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} 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}\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{\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{\n\t\tthis.element.transform(transformation);\n\t},\n\tattr: function(attrs)\n\t{\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\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"
  },
  {
    "path": "flowable-ui-web/modeler/display/bpmn-draw.js",
    "content": "/* Copyright 2005-2015 Alfresco Software, Ltd.\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 */\nfunction _bpmnGetColor(element, defaultColor)\n{\n    var strokeColor;\n    if(element.current) {\n        strokeColor = CURRENT_COLOR;\n    } else if(element.completed) {\n        strokeColor = COMPLETED_COLOR;\n    } else {\n        strokeColor = defaultColor;\n    }\n    return strokeColor;\n}\n\nfunction _drawPool(pool)\n{\n\tvar rect = paper.rect(pool.x, pool.y, pool.width, pool.height);\n\n\trect.attr({\"stroke-width\": 1,\n\t\t\"stroke\": \"#000000\",\n\t\t\"fill\": \"white\"\n \t});\n\n\tif (pool.name)\n\t{\n\t\tvar poolName = paper.text(pool.x + 14, pool.y + (pool.height / 2), pool.name).attr({\n\t        \"text-anchor\" : \"middle\",\n\t        \"font-family\" : \"Arial\",\n\t        \"font-size\" : \"12\",\n\t        \"fill\" : \"#000000\"\n\t  \t});\n\n\t\tpoolName.transform(\"r270\");\n\t}\n\n\tif (pool.lanes)\n\t{\n\t\tfor (var i = 0; i < pool.lanes.length; i++)\n\t\t{\n\t\t\tvar lane = pool.lanes[i];\n\t\t\t_drawLane(lane);\n\t\t}\n\t}\n}\n\nfunction _drawLane(lane)\n{\n\tvar rect = paper.rect(lane.x, lane.y, lane.width, lane.height);\n\n\trect.attr({\"stroke-width\": 1,\n\t\t\"stroke\": \"#000000\",\n\t\t\"fill\": \"white\"\n \t});\n\n\tif (lane.name)\n\t{\n\t\tvar laneName = paper.text(lane.x + 10, lane.y + (lane.height / 2), lane.name).attr({\n\t        \"text-anchor\" : \"middle\",\n\t        \"font-family\" : \"Arial\",\n\t        \"font-size\" : \"12\",\n\t        \"fill\" : \"#000000\"\n\t  \t});\n\n\t\tlaneName.transform(\"r270\");\n\t}\n}\n\nfunction _drawSubProcess(element)\n{\n\tvar rect = paper.rect(element.x, element.y, element.width, element.height, 4);\n\n\tvar strokeColor = _bpmnGetColor(element, MAIN_STROKE_COLOR);\n\n\trect.attr({\"stroke-width\": 1,\n\t\t\"stroke\": strokeColor,\n\t\t\"fill\": \"white\"\n \t});\n}\n\nfunction _drawTransaction(element)\n{\n\tvar rect = paper.rect(element.x, element.y, element.width, element.height, 4);\n\n\tvar strokeColor = _bpmnGetColor(element, MAIN_STROKE_COLOR);\n\n\trect.attr({\"stroke-width\": 1,\n\t\t\"stroke\": strokeColor,\n\t\t\"fill\": \"white\"\n \t});\n\n\tvar borderRect = paper.rect(element.x + 2, element.y + 2, element.width - 4, element.height -4, 4);\n\n\tborderRect.attr({\"stroke-width\": 1,\n\t\t\"stroke\": \"black\",\n\t\t\"fill\": \"none\"\n \t});\n}\n\nfunction _drawEventSubProcess(element)\n{\n\tvar rect = paper.rect(element.x, element.y, element.width, element.height, 4);\n\tvar strokeColor = _bpmnGetColor(element, MAIN_STROKE_COLOR);\n\n\trect.attr({\"stroke-width\": 1,\n\t\t\"stroke\": strokeColor,\n\t\t\"stroke-dasharray\": \".\",\n\t\t\"fill\": \"white\"\n \t});\n}\n\nfunction _drawAdhocSubProcess(element)\n{\n\tvar rect = paper.rect(element.x, element.y, element.width, element.height, 4);\n\n\tvar strokeColor = _bpmnGetColor(element, MAIN_STROKE_COLOR);\n\n\trect.attr({\"stroke-width\": 1,\n\t\t\"stroke\": strokeColor,\n\t\t\"fill\": \"white\"\n \t});\n\n \tpaper.text(element.x + (element.width / 2), element.y + element.height - 8).attr({\n        \"text-anchor\" : \"middle\",\n        \"font-family\" : \"Arial\",\n        \"font-size\" : 20,\n        \"text\" : \"~\",\n        \"fill\" : \"#373e48\"\n  \t});\n}\n\nfunction _drawStartEvent(element)\n{\n\tvar startEvent = _drawEvent(element, NORMAL_STROKE, 15);\n\tstartEvent.click(function() {\n\t\t_zoom(true);\n\t});\n\t_addHoverLogic(element, \"circle\", MAIN_STROKE_COLOR);\n}\n\nfunction _drawEndEvent(element)\n{\n\tvar endEvent = _drawEvent(element, ENDEVENT_STROKE, 14);\n\tendEvent.click(function() {\n\t\t_zoom(false);\n\t});\n\t_addHoverLogic(element, \"circle\", MAIN_STROKE_COLOR);\n}\n\nfunction _drawEvent(element, strokeWidth, radius)\n{\n\tvar x = element.x + (element.width / 2);\n\tvar y = element.y + (element.height / 2);\n\n\tvar circle = paper.circle(x, y, radius);\n\n\tvar strokeColor = _bpmnGetColor(element, MAIN_STROKE_COLOR);\n\n    // Fill\n    var eventFillColor = _determineCustomFillColor(element, \"#ffffff\");\n\n    // Opacity\n    var eventOpacity = 1.0;\n    if (customActivityBackgroundOpacity) {\n        eventOpacity = customActivityBackgroundOpacity;\n    }\n\n\tif (element.interrupting === undefined || element.interrupting) {\n\t\tcircle.attr({\n\t\t    \"stroke-width\": strokeWidth,\n\t\t\t\"stroke\": strokeColor,\n\t\t\t\"fill\": eventFillColor,\n\t        \"fill-opacity\": eventOpacity\n\t \t});\n\n\t} else {\n\t\tcircle.attr({\n\t\t    \"stroke-width\": strokeWidth,\n\t\t\t\"stroke\": strokeColor,\n\t\t\t\"stroke-dasharray\": \".\",\n\t\t\t\"fill\": eventFillColor,\n\t        \"fill-opacity\": eventOpacity\n\t \t});\n\t}\n\n\tcircle.id = element.id;\n\n\t_drawEventIcon(paper, element);\n\n\treturn circle;\n}\n\nfunction _drawServiceTask(element)\n{\n\t_drawTask(element);\n\tif (element.taskType === \"mail\")\n\t{\n\t\t_drawSendTaskIcon(paper, element.x + 4, element.y + 4);\n\t}\n\telse if (element.taskType === \"camel\")\n\t{\n\t\t_drawCamelTaskIcon(paper, element.x + 4, element.y + 4);\n\t}\n\telse if (element.taskType === \"mule\")\n\t{\n\t\t_drawMuleTaskIcon(paper, element.x + 4, element.y + 4);\n\t}\n    else if (element.taskType === \"http\")\n    {\n        _drawHttpTaskIcon(paper, element.x + 4, element.y + 4);\n    }\n    else if (element.taskType === \"shell\")\n    {\n        _drawShellTaskIcon(paper, element.x + 4, element.y + 4);\n    }\n    else if (element.taskType === \"dmn\") {\n        _drawDecisionTaskIcon(paper, element.x + 4, element.y + 4);\n    }\n    else if (element.stencilIconId)\n\t{\n\t\tpaper.image(\"../service/stencilitem/\" + element.stencilIconId + \"/icon\", element.x + 4, element.y + 4, 16, 16);\n\t}\n\telse\n\t{\n\t\t_drawServiceTaskIcon(paper, element.x + 4, element.y + 4);\n\t}\n\t_addHoverLogic(element, \"rect\", ACTIVITY_STROKE_COLOR);\n}\n\nfunction _drawHttpServiceTask(element)\n{\n    _drawTask(element);\n    _drawHttpTaskIcon(paper, element.x + 4, element.y + 4);\n    _addHoverLogic(element, \"rect\", ACTIVITY_STROKE_COLOR);\n}\n\nfunction _drawCallActivity(element)\n{\n    var width = element.width - (CALL_ACTIVITY_STROKE / 2);\n    var height = element.height - (CALL_ACTIVITY_STROKE / 2);\n\n    var rect = paper.rect(element.x, element.y, width, height, 4);\n\n    var strokeColor = _bpmnGetColor(element, ACTIVITY_STROKE_COLOR);\n\n    // Fill\n    var callActivityFillColor = _determineCustomFillColor(element, ACTIVITY_FILL_COLOR);\n\n    // Opacity\n    var callActivityOpacity = 1.0;\n    if (customActivityBackgroundOpacity) {\n        callActivityOpacity = customActivityBackgroundOpacity;\n    }\n\n    rect.attr({\"stroke-width\": CALL_ACTIVITY_STROKE,\n        \"stroke\": strokeColor,\n        \"fill\": callActivityFillColor,\n        \"fill-opacity\": callActivityOpacity\n    });\n\n    rect.id = element.id;\n\n    if (element.name) {\n        this._drawMultilineText(element.name, element.x, element.y, element.width, element.height, \"middle\", \"middle\", 11);\n    }\n    _addHoverLogic(element, \"rect\", ACTIVITY_STROKE_COLOR);\n}\n\nfunction _drawScriptTask(element)\n{\n\t_drawTask(element);\n\t_drawScriptTaskIcon(paper, element.x + 4, element.y + 4);\n\t_addHoverLogic(element, \"rect\", ACTIVITY_STROKE_COLOR);\n}\n\nfunction _drawUserTask(element)\n{\n\t_drawTask(element);\n\t_drawUserTaskIcon(paper, element.x + 4, element.y + 4);\n\t_addHoverLogic(element, \"rect\", ACTIVITY_STROKE_COLOR);\n}\n\nfunction _drawBusinessRuleTask(element)\n{\n\t_drawTask(element);\n\t_drawBusinessRuleTaskIcon(paper, element.x + 4, element.y + 4);\n\t_addHoverLogic(element, \"rect\", ACTIVITY_STROKE_COLOR);\n}\n\nfunction _drawManualTask(element)\n{\n\t_drawTask(element);\n\t_drawManualTaskIcon(paper, element.x + 4, element.y + 4);\n\t_addHoverLogic(element, \"rect\", ACTIVITY_STROKE_COLOR);\n}\n\nfunction _drawSendTask(element)\n{\n    _drawTask(element);\n    _drawSendTaskIcon(paper, element.x + 4, element.y + 4);\n    _addHoverLogic(element, \"rect\", ACTIVITY_STROKE_COLOR);\n}\n\nfunction _drawReceiveTask(element)\n{\n\t_drawTask(element);\n\t_drawReceiveTaskIcon(paper, element.x, element.y);\n\t_addHoverLogic(element, \"rect\", ACTIVITY_STROKE_COLOR);\n}\n\nfunction _drawTask(element)\n{\n    var rectAttrs = {};\n\n    // Stroke\n    var strokeColor = _bpmnGetColor(element, ACTIVITY_STROKE_COLOR);\n    rectAttrs['stroke'] = strokeColor;\n\n    var strokeWidth;\n    if (strokeColor === ACTIVITY_STROKE_COLOR) {\n        strokeWidth = TASK_STROKE;\n    } else {\n        strokeWidth = TASK_HIGHLIGHT_STROKE;\n    }\n\n\tvar width = element.width - (strokeWidth / 2);\n\tvar height = element.height - (strokeWidth / 2);\n\n\tvar rect = paper.rect(element.x, element.y, width, height, 4);\n    rectAttrs['stroke-width'] = strokeWidth;\n\n    // Fill\n\tvar fillColor = _determineCustomFillColor(element, ACTIVITY_FILL_COLOR);\n    rectAttrs['fill'] = fillColor;\n\n    // Opacity\n    if (customActivityBackgroundOpacity) {\n        rectAttrs['fill-opacity'] = customActivityBackgroundOpacity;\n    }\n\n\trect.attr(rectAttrs);\n\trect.id = element.id;\n\n\tif (element.name) {\n\t\tthis._drawMultilineText(element.name, element.x, element.y, element.width, element.height, \"middle\", \"middle\", 11);\n\t}\n}\n\nfunction _drawExclusiveGateway(element)\n{\n\t_drawGateway(element);\n\tvar quarterWidth = element.width / 4;\n\tvar quarterHeight = element.height / 4;\n\n\tvar iks = paper.path(\n\t\t\"M\" + (element.x + quarterWidth + 3) + \" \" + (element.y + quarterHeight + 3) +\n\t\t\"L\" + (element.x + 3 * quarterWidth - 3) + \" \" + (element.y + 3 * quarterHeight - 3) +\n\t\t\"M\" + (element.x + quarterWidth + 3) + \" \" + (element.y + 3 * quarterHeight - 3) +\n\t\t\"L\" + (element.x + 3 * quarterWidth - 3) + \" \" + (element.y + quarterHeight + 3)\n\t);\n\n\tvar strokeColor = _bpmnGetColor(element, MAIN_STROKE_COLOR);\n\n    // Fill\n    var gatewayFillColor = _determineCustomFillColor(element, ACTIVITY_FILL_COLOR);\n\n    // Opacity\n    var gatewayOpacity = 1.0;\n    if (customActivityBackgroundOpacity) {\n        gatewayOpacity = customActivityBackgroundOpacity;\n    }\n\n\n    iks.attr({\"stroke-width\": 3, \"stroke\": strokeColor, \"fill\": gatewayFillColor, \"fill-opacity\": gatewayOpacity});\n\n\t_addHoverLogic(element, \"rhombus\", MAIN_STROKE_COLOR);\n}\n\nfunction _drawParallelGateway(element)\n{\n\t_drawGateway(element);\n\n\tvar strokeColor = _bpmnGetColor(element, MAIN_STROKE_COLOR);\n\n\tvar path1 = paper.path(\"M 6.75,16 L 25.75,16 M 16,6.75 L 16,25.75\");\n\n    // Fill\n    var gatewayFillColor = _determineCustomFillColor(element, ACTIVITY_FILL_COLOR);\n\n    // Opacity\n    var gatewayOpacity = 1.0;\n    if (customActivityBackgroundOpacity) {\n        gatewayOpacity = customActivityBackgroundOpacity;\n    }\n\n\tpath1.attr({\n\t\t\"stroke-width\": 3,\n\t\t\"stroke\": strokeColor,\n\t\t\"fill\": gatewayFillColor,\n        \"fill-opacity\": gatewayOpacity\n\t});\n\n\tpath1.transform(\"T\" + (element.x + 4) + \",\" + (element.y + 4));\n\n\t_addHoverLogic(element, \"rhombus\", MAIN_STROKE_COLOR);\n}\n\nfunction _drawInclusiveGateway(element)\n{\n\t_drawGateway(element);\n\n\tvar strokeColor = _bpmnGetColor(element, MAIN_STROKE_COLOR);\n\n\tvar circle1 = paper.circle(element.x + (element.width / 2), element.y + (element.height / 2), 9.75);\n\n    // Fill\n    var gatewayFillColor = _determineCustomFillColor(element, ACTIVITY_FILL_COLOR);\n\n    // Opacity\n    var gatewayOpacity = 1.0;\n    if (customActivityBackgroundOpacity) {\n        gatewayOpacity = customActivityBackgroundOpacity;\n    }\n\n\tcircle1.attr({\n\t\t\"stroke-width\": 2.5,\n\t\t\"stroke\": strokeColor,\n\t\t\"fill\": gatewayFillColor,\n        \"fill-opacity\": gatewayOpacity\n\t});\n\n\t_addHoverLogic(element, \"rhombus\", MAIN_STROKE_COLOR);\n}\n\nfunction _drawEventGateway(element)\n{\n\t_drawGateway(element);\n\n\tvar strokeColor = _bpmnGetColor(element, MAIN_STROKE_COLOR);\n\n\tvar circle1 = paper.circle(element.x + (element.width / 2), element.y + (element.height / 2), 10.4);\n\n    // Fill\n    var gatewayFillColor = _determineCustomFillColor(element, ACTIVITY_FILL_COLOR);\n\n    // Opacity\n    var gatewayOpacity = 1.0;\n    if (customActivityBackgroundOpacity) {\n        gatewayOpacity = customActivityBackgroundOpacity;\n    }\n\n\tcircle1.attr({\n\t\t\"stroke-width\": 0.5,\n\t\t\"stroke\": strokeColor,\n\t\t\"fill\": gatewayFillColor,\n        \"fill-opacity\": gatewayOpacity\n    });\n\n\tvar circle2 = paper.circle(element.x + (element.width / 2), element.y + (element.height / 2), 11.7);\n\tcircle2.attr({\n\t\t\"stroke-width\": 0.5,\n\t\t\"stroke\": strokeColor,\n        \"fill\": gatewayFillColor,\n        \"fill-opacity\": gatewayOpacity\n\t});\n\n\tvar path1 = paper.path(\"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\tpath1.attr({\n\t\t\"stroke-width\": 1.39999998,\n\t\t\"stroke\": strokeColor,\n        \"fill\": gatewayFillColor,\n        \"fill-opacity\": gatewayOpacity,\n\t\t\"stroke-linejoin\": \"bevel\"\n\t});\n\n\tpath1.transform(\"T\" + (element.x + 4) + \",\" + (element.y + 4));\n\n\t_addHoverLogic(element, \"rhombus\", MAIN_STROKE_COLOR);\n}\n\nfunction _drawGateway(element)\n{\n    var strokeColor = _bpmnGetColor(element, MAIN_STROKE_COLOR);\n\n\tvar rhombus = paper.path(\"M\" + element.x + \" \" + (element.y + (element.height / 2)) +\n\t\t\"L\" + (element.x + (element.width / 2)) + \" \" + (element.y + element.height) +\n\t\t\"L\" + (element.x + element.width) + \" \" + (element.y + (element.height / 2)) +\n\t\t\"L\" + (element.x + (element.width / 2)) + \" \" + element.y + \"z\"\n\t);\n\n    // Fill\n    var gatewayFillColor = _determineCustomFillColor(element, ACTIVITY_FILL_COLOR);\n\n    // Opacity\n    var gatewayOpacity = 1.0;\n    if (customActivityBackgroundOpacity) {\n        gatewayOpacity = customActivityBackgroundOpacity;\n    }\n\n\trhombus.attr(\"stroke-width\", 2);\n\trhombus.attr(\"stroke\", strokeColor);\n\trhombus.attr(\"fill\", gatewayFillColor);\n    rhombus.attr(\"fill-opacity\", gatewayOpacity);\n\n\trhombus.id = element.id;\n\n\treturn rhombus;\n}\n\nfunction _drawBoundaryEvent(element)\n{\n\tvar x = element.x + (element.width / 2);\n\tvar y = element.y + (element.height / 2);\n\n\tvar circle = paper.circle(x, y, 15);\n\n\tvar strokeColor = _bpmnGetColor(element, MAIN_STROKE_COLOR);\n\n \tif (element.cancelActivity)  {\n\t\tcircle.attr({\n\t\t    \"stroke-width\": 1,\n\t\t\t\"stroke\": strokeColor,\n\t\t\t\"fill\": \"white\"\n\t \t});\n\n\t} else {\n\t\tcircle.attr({\n\t\t    \"stroke-width\": 1,\n\t\t    \"stroke-dasharray\": \".\",\n\t\t\t\"stroke\": strokeColor,\n\t\t\t\"fill\": \"white\"\n\t \t});\n\t}\n\n\tvar innerCircle = paper.circle(x, y, 12);\n\n\tif (element.cancelActivity)  {\n\t\tinnerCircle.attr({\"stroke-width\": 1,\n\t\t\t\"stroke\": strokeColor,\n\t\t\t\"fill\": \"none\"\n\t \t});\n\n\t} else {\n\t\tinnerCircle.attr({\n\t\t    \"stroke-width\": 1,\n\t\t    \"stroke-dasharray\": \".\",\n\t\t\t\"stroke\": strokeColor,\n\t\t\t\"fill\": \"none\"\n\t \t});\n\t}\n\n\t_drawEventIcon(paper, element);\n\t_addHoverLogic(element, \"circle\", MAIN_STROKE_COLOR);\n\n\tcircle.id = element.id;\n\tinnerCircle.id = element.id + \"_inner\";\n}\n\nfunction _drawIntermediateCatchEvent(element)\n{\n\tvar x = element.x + (element.width / 2);\n\tvar y = element.y + (element.height / 2);\n\n\tvar circle = paper.circle(x, y, 15);\n\n\tvar strokeColor = _bpmnGetColor(element, MAIN_STROKE_COLOR);\n\n\tcircle.attr({\"stroke-width\": 1,\n\t\t\"stroke\": strokeColor,\n\t\t\"fill\": \"white\"\n \t});\n\n\tvar innerCircle = paper.circle(x, y, 12);\n\n\tinnerCircle.attr({\"stroke-width\": 1,\n\t\t\"stroke\": strokeColor,\n\t\t\"fill\": \"none\"\n \t});\n\n\t_drawEventIcon(paper, element);\n\t_addHoverLogic(element, \"circle\", MAIN_STROKE_COLOR);\n\n\tcircle.id = element.id;\n\tinnerCircle.id = element.id + \"_inner\";\n}\n\nfunction _drawThrowEvent(element)\n{\n\tvar x = element.x + (element.width / 2);\n\tvar y = element.y + (element.height / 2);\n\n\tvar circle = paper.circle(x, y, 15);\n\n\tvar strokeColor = _bpmnGetColor(element, MAIN_STROKE_COLOR);\n\n\tcircle.attr({\"stroke-width\": 1,\n\t\t\"stroke\": strokeColor,\n\t\t\"fill\": \"white\"\n \t});\n\n\tvar innerCircle = paper.circle(x, y, 12);\n\n\tinnerCircle.attr({\"stroke-width\": 1,\n\t\t\"stroke\": strokeColor,\n\t\t\"fill\": \"none\"\n \t});\n\n\t_drawEventIcon(paper, element);\n\t_addHoverLogic(element, \"circle\", MAIN_STROKE_COLOR);\n\n\tcircle.id = element.id;\n\tinnerCircle.id = element.id + \"_inner\";\n}\n\nfunction _drawMultilineText(text, x, y, boxWidth, boxHeight, horizontalAnchor, verticalAnchor, fontSize)\n{\n\tif (!text || text == \"\")\n\t{\n\t\treturn;\n\t}\n\n\tvar textBoxX, textBoxY;\n    var width = boxWidth - (2 * TEXT_PADDING);\n\n    if (horizontalAnchor === \"middle\")\n    {\n    \ttextBoxX = x + (boxWidth / 2);\n    }\n    else if (horizontalAnchor === \"start\")\n    {\n    \ttextBoxX = x;\n    }\n\n    textBoxY = y + (boxHeight / 2);\n\n \tvar t = paper.text(textBoxX + TEXT_PADDING, textBoxY + TEXT_PADDING).attr({\n        \"text-anchor\" : horizontalAnchor,\n        \"font-family\" : \"Arial\",\n        \"font-size\" : fontSize,\n        \"fill\" : \"#373e48\"\n  \t});\n\n    var abc = \"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ\";\n    t.attr({\n        \"text\" : abc\n    });\n    var letterWidth = t.getBBox().width / abc.length;\n\n    t.attr({\n        \"text\" : text\n    });\n    var removedLineBreaks = text.split(\"\\n\");\n    var x = 0, s = [];\n    for (var r = 0; r < removedLineBreaks.length; r++)\n    {\n  \t    var words = removedLineBreaks[r].split(\" \");\n  \t    for ( var i = 0; i < words.length; i++) {\n\n  \t        var l = words[i].length;\n  \t        if (x + (l * letterWidth) > width) {\n  \t            s.push(\"\\n\");\n  \t            x = 0;\n  \t        }\n  \t        x += l * letterWidth;\n  \t        s.push(words[i] + \" \");\n  \t    }\n\t  \ts.push(\"\\n\");\n        x = 0;\n    }\n    t.attr({\n    \t\"text\" : s.join(\"\")\n    });\n\n    if (verticalAnchor && verticalAnchor === \"top\")\n    {\n    \tt.attr({\"y\": y + (t.getBBox().height / 2)});\n    }\n}\n\nfunction _drawTextAnnotation(element)\n{\n\tvar path1 = paper.path(\"M20,1 L1,1 L1,50 L20,50\");\n\tpath1.attr({\n\t\t\"stroke\": \"#585858\",\n\t\t\"fill\": \"none\"\n \t});\n\n\tvar annotation = paper.set();\n\tannotation.push(path1);\n\n\tannotation.transform(\"T\" + element.x + \",\" + element.y);\n\n\tif (element.text) {\n\t\tthis._drawMultilineText(element.text, element.x + 2, element.y, element.width, element.height, \"start\", \"middle\", 11);\n\t}\n}\n\nfunction _drawFlow(flow){\n\n\tvar polyline = new Polyline(flow.id, flow.waypoints, SEQUENCEFLOW_STROKE, paper);\n\n\tvar strokeColor = _bpmnGetColor(flow, MAIN_STROKE_COLOR);\n\n\tpolyline.element = paper.path(polyline.path);\n\tpolyline.element.attr({\"stroke-width\":SEQUENCEFLOW_STROKE});\n\tpolyline.element.attr({\"stroke\":strokeColor});\n\n\tpolyline.element.id = flow.id;\n\n\tvar lastLineIndex = polyline.getLinesCount() - 1;\n\tvar line = polyline.getLine(lastLineIndex);\n\n\tif (line == undefined) return;\n\n\tif (flow.type == \"connection\" && flow.conditions)\n\t{\n\t\tvar middleX = (line.x1 + line.x2) / 2;\n\t\tvar middleY = (line.y1 + line.y2) / 2;\n\t\tvar image = paper.image(\"../editor/images/condition-flow.png\", middleX - 8, middleY - 8, 16, 16);\n\t}\n\n\tvar polylineInvisible = new Polyline(flow.id, flow.waypoints, SEQUENCEFLOW_STROKE, paper);\n\n\tpolylineInvisible.element = paper.path(polyline.path);\n\tpolylineInvisible.element.attr({\n\t\t\t\"opacity\": 0,\n\t\t\t\"stroke-width\": 8,\n            \"stroke\" : \"#000000\"\n\t});\n\n    if (flow.name) {\n        var firstLine = polyline.getLine(0);\n\n        var angle;\n        if (firstLine.x1 !== firstLine.x2) {\n            angle = Math.atan((firstLine.y2 - firstLine.y1) / (firstLine.x2 - firstLine.x1));\n        } else if (firstLine.y1 < firstLine.y2) {\n            angle = Math.PI / 2;\n        } else {\n            angle = -Math.PI / 2;\n\t\t}\n\t\tvar flowName = paper.text(firstLine.x1, firstLine.y1, flow.name).attr({\n\t\t\t\"text-anchor\": \"middle\",\n\t\t\t\"font-family\" : \"Arial\",\n\t\t\t\"font-size\" : \"12\",\n\t\t\t\"fill\" : \"#000000\"\n\t\t});\n\n        var offsetX = (flowName.getBBox().width / 2 + 5);\n        var offsetY = -(flowName.getBBox().height / 2 + 5);\n\n        if (firstLine.x1 > firstLine.x2) {\n            offsetX = -offsetX;\n        }\n        var rotatedOffsetX = offsetX * Math.cos(angle) - offsetY * Math.sin(angle);\n        var rotatedOffsetY = offsetX * Math.sin(angle) + offsetY * Math.cos(angle);\n\n        flowName.attr({\n\t\t\tx: firstLine.x1 + rotatedOffsetX,\n\t\t\ty: firstLine.y1 + rotatedOffsetY\n\t\t});\n\n        flowName.transform(\"r\" + ((angle) * 180) / Math.PI);\n    }\n\n\t_showTip(jQuery(polylineInvisible.element.node), flow);\n\n\tpolylineInvisible.element.mouseover(function() {\n\t\tpaper.getById(polyline.element.id).attr({\"stroke\":\"blue\"});\n\t});\n\n\tpolylineInvisible.element.mouseout(function() {\n\t\tpaper.getById(polyline.element.id).attr({\"stroke\":\"#585858\"});\n\t});\n\n\t_drawArrowHead(line);\n}\n\nfunction _drawAssociation(flow){\n\n\tvar polyline = new Polyline(flow.id, flow.waypoints, ASSOCIATION_STROKE, paper);\n\n\tpolyline.element = paper.path(polyline.path);\n\tpolyline.element.attr({\"stroke-width\": ASSOCIATION_STROKE});\n\tpolyline.element.attr({\"stroke-dasharray\": \". \"});\n\tpolyline.element.attr({\"stroke\":\"#585858\"});\n\n\tpolyline.element.id = flow.id;\n\n\tvar polylineInvisible = new Polyline(flow.id, flow.waypoints, ASSOCIATION_STROKE, paper);\n\n\tpolylineInvisible.element = paper.path(polyline.path);\n\tpolylineInvisible.element.attr({\n\t\t\t\"opacity\": 0,\n\t\t\t\"stroke-width\": 8,\n            \"stroke\" : \"#000000\"\n\t});\n\n\t_showTip(jQuery(polylineInvisible.element.node), flow);\n\n\tpolylineInvisible.element.mouseover(function() {\n\t\tpaper.getById(polyline.element.id).attr({\"stroke\":\"blue\"});\n\t});\n\n\tpolylineInvisible.element.mouseout(function() {\n\t\tpaper.getById(polyline.element.id).attr({\"stroke\":\"#585858\"});\n\t});\n}\n\nfunction _drawArrowHead(line, connectionType)\n{\n\tvar doubleArrowWidth = 2 * ARROW_WIDTH;\n\n\tvar arrowHead = paper.path(\"M0 0L-\" + (ARROW_WIDTH / 2 + .5) + \" -\" + doubleArrowWidth + \"L\" + (ARROW_WIDTH/2 + .5) + \" -\" + doubleArrowWidth + \"z\");\n\n\t// anti smoothing\n\tif (this.strokeWidth%2 == 1)\n\t\tline.x2 += .5, line.y2 += .5;\n\n\tarrowHead.transform(\"t\" + line.x2 + \",\" + line.y2 + \"\");\n\tarrowHead.transform(\"...r\" + Raphael.deg(line.angle - Math.PI / 2) + \" \" + 0 + \" \" + 0);\n\n\tarrowHead.attr(\"fill\", \"#585858\");\n\n\tarrowHead.attr(\"stroke-width\", SEQUENCEFLOW_STROKE);\n\tarrowHead.attr(\"stroke\", \"#585858\");\n\n\treturn arrowHead;\n}\n\nfunction _determineCustomFillColor(element, defaultColor) {\n\n    var color;\n\n    // By name\n    if (customActivityColors && customActivityColors[element.name]) {\n        color = customActivityColors[element.name];\n    }\n\n    if (color !== null && color !== undefined) {\n        return color;\n    }\n\n    // By id\n    if (customActivityColors && customActivityColors[element.id]) {\n        color = customActivityColors[element.id];\n    }\n\n    if (color !== null && color !== undefined) {\n        return color;\n    }\n\n    return defaultColor;\n}\n"
  },
  {
    "path": "flowable-ui-web/modeler/display/bpmn-icons.js",
    "content": "/* 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 */\nfunction _drawUserTaskIcon(paper, startX, startY)\n{\n\tvar path1 = paper.path(\"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\tpath1.attr({\n\t\t\"opacity\": 1,\n\t\t\"stroke\": \"none\",\n\t\t\"fill\": \"#d1b575\"\n \t});\n\n\tvar userTaskIcon = paper.set();\n\tuserTaskIcon.push(path1);\n\n\tuserTaskIcon.transform(\"T\" + startX + \",\" + startY);\n}\n\nfunction _drawServiceTaskIcon(paper, startX, startY)\n{\n\tvar path1 = paper.path(\"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\tpath1.attr({\n\t\t\"opacity\": 1,\n\t\t\"stroke\": \"none\",\n\t\t\"fill\": \"#72a7d0\"\n \t});\n\n\tvar serviceTaskIcon = paper.set();\n\tserviceTaskIcon.push(path1);\n\n\tserviceTaskIcon.transform(\"T\" + startX + \",\" + startY);\n}\n\nfunction _drawScriptTaskIcon(paper, startX, startY)\n{\n\tvar path1 = paper.path(\"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\tpath1.attr({\n\t\t\"opacity\": 1,\n\t\t\"stroke\": \"none\",\n\t\t\"fill\": \"#72a7d0\"\n \t});\n\n\tvar scriptTaskIcon = paper.set();\n\tscriptTaskIcon.push(path1);\n\n\tscriptTaskIcon.transform(\"T\" + startX + \",\" + startY);\n}\n\nfunction _drawBusinessRuleTaskIcon(paper, startX, startY)\n{\n\tvar path1 = paper.path(\"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\tpath1.attr({\n\t\t\"stroke\": \"none\",\n\t\t\"fill\": \"#72a7d0\"\n \t});\n\n\tvar businessRuleTaskIcon = paper.set();\n\tbusinessRuleTaskIcon.push(path1);\n\n\tbusinessRuleTaskIcon.transform(\"T\" + startX + \",\" + startY);\n}\n\nfunction _drawSendTaskIcon(paper, startX, startY)\n{\n\tvar path1 = paper.path(\"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\tpath1.attr({\n\t\t\"stroke\": \"none\",\n\t\t\"fill\": \"#16964d\"\n \t});\n\n\tvar sendTaskIcon = paper.set();\n\tsendTaskIcon.push(path1);\n\n\tsendTaskIcon.transform(\"T\" + startX + \",\" + startY);\n}\n\nfunction _drawManualTaskIcon(paper, startX, startY)\n{\n\tvar path1 = paper.path(\"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\tpath1.attr({\n\t\t\"opacity\": 1,\n\t\t\"stroke\": \"none\",\n\t\t\"fill\": \"#d1b575\"\n \t});\n\n\tvar manualTaskIcon = paper.set();\n\tmanualTaskIcon.push(path1);\n\n\tmanualTaskIcon.transform(\"T\" + startX + \",\" + startY);\n}\n\nfunction _drawReceiveTaskIcon(paper, startX, startY)\n{\n\tvar path = paper.path(\"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\tpath.attr({\n\t\t\"opacity\": 1,\n\t\t\"stroke\": \"none\",\n\t\t\"fill\": \"#16964d\"\n \t});\n\n\tstartX += 4;\n\tstartY += 2;\n\n\tpath.transform(\"T\" + startX + \",\" + startY);\n\n}\n\nfunction _drawCamelTaskIcon(paper, startX, startY)\n{\n\tvar path = paper.path(\"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\tpath.attr({\n\t\t\"opacity\": 1,\n\t\t\"stroke\": \"none\",\n\t\t\"fill\": \"#bd4848\"\n \t});\n\n\tstartX += 4;\n\tstartY += 2;\n\n\tpath.transform(\"T\" + startX + \",\" + startY);\n\n}\n\nfunction _drawMuleTaskIcon(paper, startX, startY)\n{\n\tvar path = paper.path(\"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\tpath.attr({\n\t\t\"opacity\": 1,\n\t\t\"stroke\": \"none\",\n\t\t\"fill\": \"#bd4848\"\n \t});\n\n\tstartX += 4;\n\tstartY += 2;\n\n\tpath.transform(\"T\" + startX + \",\" + startY);\n\n}\n\nfunction _drawAlfrescoPublishTaskIcon(paper, startX, startY)\n{\n\n    startX += 2;\n    startY += 2;\n\n    var path = paper.path(\"M4.11870968,2.12890323 L6.12954839,0.117935484 L3.10993548,0.118064516 L3.10270968,0.118064516 C1.42941935,0.118064516 0.0729032258,1.47458065 0.0729032258,3.14774194 C0.0729032258,4.82116129 1.42929032,6.17754839 3.10258065,6.17754839 C3.22967742,6.17754839 3.35470968,6.16877419 3.47767742,6.15354839 C2.8163871,4.85083871 3.02954839,3.21793548 4.11870968,2.12890323M6.57032258,3.144 L6.57032258,0.300258065 L4.43522581,2.4356129 L4.43006452,2.44064516 C3.24683871,3.62387097 3.24683871,5.54219355 4.43006452,6.72541935 C5.61329032,7.90864516 7.5316129,7.90864516 8.71483871,6.72541935 C8.80464516,6.6356129 8.88529032,6.54025806 8.96154839,6.44270968 C7.57341935,5.98864516 6.57045161,4.68387097 6.57032258,3.144\");\n    path.attr({\"fill\": \"#87C040\"});\n\n    var startX1 = startX + 1.419355;\n    var startY1 = startY + 8.387097;\n    path.transform(\"T\" + startX1 + \",\" + startY1);\n\n    path = paper.path(\"M10.4411613,10.5153548 L8.43032258,8.50451613 L8.43032258,11.5313548 C8.43032258,13.2047742 9.78683871,14.5611613 11.460129,14.5611613 C13.1334194,14.5611613 14.4899355,13.2047742 14.4899355,11.5314839 C14.4899355,11.4043871 14.4811613,11.2793548 14.4659355,11.1563871 C13.1632258,11.8178065 11.5303226,11.6045161 10.4411613,10.5153548M15.0376774,5.91935484 C14.947871,5.82954839 14.8526452,5.74890323 14.7550968,5.67264516 C14.3010323,7.06064516 12.996129,8.06374194 11.4563871,8.06374194 L8.61277419,8.06374194 L10.7529032,10.204 C11.936129,11.3872258 13.8545806,11.3872258 15.0376774,10.204 C16.2209032,9.02077419 16.2209032,7.10245161 15.0376774,5.91935484\");\n    path.attr({\"fill\": \"#87C040\"});\n    path.transform(\"T\" + startX + \",\" + startY);\n\n    path = paper.path(\"M5.9083871,1.5636129 C5.78129032,1.5636129 5.65625806,1.57225806 5.53329032,1.58748387 C6.19458065,2.89032258 5.98141935,4.52309677 4.89225806,5.61225806 L2.88154839,7.62309677 L5.9083871,7.62309677 C7.58154839,7.62309677 8.93806452,6.26658065 8.93806452,4.59329032 C8.93819355,2.92 7.58167742,1.5636129 5.9083871,1.5636129\");\n    path.attr({\"fill\": \"#ED9A2D\"});\n    var startX2 = startX + 5.548387;\n    path.transform(\"T\" + startX2 + \",\" + startY);\n    path = paper.path(\"M4.58090323,1.0156129 C3.39767742,-0.167483871 1.47935484,-0.167483871 0.296129032,1.01574194 C0.206451613,1.10554839 0.125806452,1.20077419 0.0495483871,1.29845161 C1.43754839,1.75251613 2.44064516,3.05729032 2.44064516,4.59703226 L2.44064516,7.44077419 L4.57574194,5.30554839 L4.58090323,5.30051613 C5.76412903,4.11729032 5.76412903,2.19896774 4.58090323,1.0156129\");\n    path.attr({\"fill\": \"#5698C6\"});\n    path.transform(\"T\" + startX2 + \",\" + startY);\n\n    path = paper.path(\"M5.54051613,5.61432258 L5.62670968,5.70425806 L7.54632258,7.62387097 L7.5483871,7.62387097 L7.5483871,4.604 L7.5483871,4.59677419 C7.5483871,2.92348387 6.19187097,1.56696774 4.51858065,1.56696774 C2.84529032,1.56696774 1.48877419,2.92335484 1.48890323,4.59664516 C1.48890323,4.72348387 1.49754839,4.84812903 1.51264516,4.97083871 C2.81625806,4.30993548 4.45122581,4.52503226 5.54051613,5.61432258M1.23251613,10.4292903 C1.25625806,10.3588387 1.28180645,10.2894194 1.30980645,10.2210323 C1.31329032,10.2123871 1.3163871,10.2036129 1.32,10.1952258 C1.35070968,10.1216774 1.38451613,10.0500645 1.42,9.97935484 C1.42774194,9.96374194 1.43574194,9.9483871 1.44387097,9.93277419 C1.4803871,9.86258065 1.51883871,9.79354839 1.55987097,9.72632258 C1.56425806,9.71909677 1.56903226,9.71225806 1.57341935,9.70529032 C1.6123871,9.64245161 1.65354839,9.58141935 1.6963871,9.52141935 C1.70516129,9.50903226 1.71380645,9.49651613 1.72283871,9.48425806 C1.76890323,9.42154839 1.81690323,9.36064516 1.86683871,9.30129032 C1.87703226,9.28916129 1.88735484,9.27741935 1.89780645,9.26567742 C1.94658065,9.20916129 1.99690323,9.15406452 2.04916129,9.10090323 C2.05380645,9.09625806 2.05806452,9.09135484 2.06270968,9.08670968 C2.11832258,9.03083871 2.17625806,8.97741935 2.23548387,8.92554839 C2.2483871,8.91419355 2.26129032,8.90296774 2.27432258,8.89187097 C2.33393548,8.84103226 2.39496774,8.79212903 2.45780645,8.74529032 C2.46606452,8.73922581 2.47470968,8.73354839 2.48296774,8.7276129 C2.54167742,8.68490323 2.60180645,8.64412903 2.66322581,8.60503226 C2.67535484,8.59729032 2.68735484,8.58929032 2.6996129,8.58167742 C2.76593548,8.54064516 2.83380645,8.50206452 2.90296774,8.46541935 C2.91754839,8.45780645 2.93225806,8.45045161 2.94696774,8.44296774 C3.016,8.40774194 3.08593548,8.37406452 3.15741935,8.34348387 C3.16090323,8.34206452 3.16425806,8.3403871 3.16774194,8.33883871 C3.24167742,8.30748387 3.31729032,8.27948387 3.39380645,8.25316129 C3.41032258,8.24748387 3.42670968,8.24180645 3.44335484,8.2363871 C3.51909677,8.21174194 3.59587097,8.18903226 3.67380645,8.16929032 C3.68567742,8.16645161 3.69793548,8.16387097 3.70980645,8.16116129 C3.78206452,8.14374194 3.85509677,8.12877419 3.92890323,8.116 C3.94270968,8.11367742 3.9563871,8.11083871 3.97019355,8.10877419 C4.05032258,8.09587097 4.13148387,8.08619355 4.21329032,8.07896774 C4.23096774,8.07741935 4.24877419,8.07625806 4.26645161,8.07483871 C4.35109677,8.06877419 4.43612903,8.06451613 4.52232258,8.06451613 L7.36606452,8.0643871 L5.22580645,5.92412903 C4.04258065,4.74103226 2.12412903,4.74090323 0.941032258,5.92412903 C-0.242193548,7.10735484 -0.242193548,9.02567742 0.941032258,10.2089032 C1.03070968,10.2985806 1.12464516,10.3814194 1.22206452,10.4575484 C1.22529032,10.448 1.22929032,10.4388387 1.23251613,10.4292903\");\n    path.attr({\"fill\": \"#5698C6\"});\n    path.transform(\"T\" + startX + \",\" + startY);\n\n    path = paper.path(\"M5.23290323,5.92412903 L6.92748387,7.61870968 L4.64980645,7.61870968 L4.52064516,7.62141935 C3.13354839,7.62141935 1.96425806,6.68929032 1.60477419,5.41729032 C2.75870968,4.77019355 4.24619355,4.93754839 5.22787097,5.91909677 L5.23290323,5.92412903M7.54722581,4.59612903 L7.54722581,6.99264516 L5.93664516,5.38206452 L5.84348387,5.29264516 C4.86258065,4.31187097 4.69483871,2.82580645 5.34012903,1.67225806 C6.61367742,2.03070968 7.54722581,3.20090323 7.54722581,4.58890323 L7.54722581,4.59612903M10.1385806,5.29819355 L8.444,6.99290323 L8.444,4.71522581 L8.44129032,4.58606452 C8.44129032,3.19896774 9.37341935,2.02954839 10.6454194,1.67019355 C11.2925161,2.82412903 11.1251613,4.3116129 10.1436129,5.29316129 L10.1385806,5.29819355\");\n    path.attr({\"fill\": \"#446BA5\"});\n    path.transform(\"T\" + startX + \",\" + startY);\n\n    path = paper.path(\"M11.4548387,7.61677419 L9.05832258,7.61677419 L10.6689032,6.00619355 L10.7583226,5.91303226 C11.7390968,4.93212903 13.2251613,4.7643871 14.3787097,5.40967742 C14.0202581,6.68322581 12.8500645,7.61677419 11.4620645,7.61677419 L11.4548387,7.61677419\");\n    path.attr({\"fill\": \"#FFF101\"});\n    path.transform(\"T\" + startX + \",\" + startY);\n\n    path = paper.path(\"M10.7470968,10.192 L9.05251613,8.49741935 L11.3301935,8.49741935 L11.4593548,8.49470968 C12.8464516,8.49483871 14.0157419,9.42696774 14.3752258,10.6989677 C13.2211613,11.3459355 11.7338065,11.1787097 10.752129,10.1970323 L10.7470968,10.192M8.43729032,11.5174194 L8.43729032,9.12090323 L10.047871,10.7314839 L10.1411613,10.8209032 C11.1219355,11.8018065 11.2896774,13.2876129 10.6443871,14.4412903 C9.37083871,14.0828387 8.43729032,12.9127742 8.43729032,11.5245161 L8.43729032,11.5174194M5.86193548,10.8296774 L7.55651613,9.13496774 L7.55651613,11.4126452 L7.55922581,11.5418065 C7.55922581,12.9289032 6.62709677,14.0983226 5.35509677,14.4578065 C4.708,13.3036129 4.87535484,11.8162581 5.85690323,10.8347097 L5.86193548,10.8296774M4.53251613,8.50993548 L6.92903226,8.50993548 L5.31845161,10.1205161 L5.22903226,10.2136774 C4.24812903,11.1945806 2.76219355,11.3623226 1.60851613,10.7170323 C1.96709677,9.44335484 3.13716129,8.50993548 4.52529032,8.50993548 L4.53251613,8.50993548\");\n    path.attr({\"fill\": \"#45AB47\"});\n    path.transform(\"T\" + startX + \",\" + startY);\n}\n\nfunction _drawHttpTaskIcon(paper, startX, startY)\n{\n    var path = paper.path(\"m 16.704699,5.9229055 q 0.358098,0 0.608767,0.2506681 0.250669,0.250668 0.250669,0.6087677 0,0.3580997 -0.250669,0.6087677 -0.250669,0.2506679 -0.608767,0.2506679 -0.358098,0 -0.608767,-0.2506679 -0.250669,-0.250668 -0.250669,-0.6087677 0,-0.3580997 0.250669,-0.6087677 0.250669,-0.2506681 0.608767,-0.2506681 z m 2.578308,-2.0053502 q -2.229162,0 -3.854034,0.6759125 -1.624871,0.6759067 -3.227361,2.2694472 -0.716197,0.725146 -1.575633,1.7457293 L 7.2329969,8.7876913 Q 7.0897576,8.8055849 7.000233,8.9309334 L 4.9948821,12.368677 q -0.035811,0.06267 -0.035811,0.143242 0,0.107426 0.080572,0.205905 l 0.5729577,0.572957 q 0.125334,0.116384 0.2864786,0.07162 l 2.4708789,-0.760963 2.5156417,2.515645 -0.76096,2.470876 q -0.009,0.02687 -0.009,0.08057 0,0.125338 0.08058,0.205905 l 0.572957,0.572958 q 0.170096,0.152194 0.349146,0.04476 l 3.437744,-2.005351 q 0.125335,-0.08953 0.143239,-0.232763 l 0.17905,-3.392986 q 1.02058,-0.859435 1.745729,-1.575629 1.67411,-1.6830612 2.309735,-3.2049805 0.635625,-1.5219191 0.635625,-3.8585111 0,-0.1253369 -0.08505,-0.2148575 -0.08505,-0.089526 -0.201431,-0.089526 z\");\n    path.attr({\n        \"opacity\": 1,\n        \"stroke\": \"none\",\n        \"fill\": \"#16964d\"\n    });\n\n    startX += -2;\n    startY += -2;\n\n    path.transform(\"T\" + startX + \",\" + startY);\n\n}\n\nfunction _drawShellTaskIcon(paper, startX, startY) {\n    var path = paper.path(\"m 1,2 0,14 16,0 0,-14 z m 1.4,3 12.7,0 0,10 -12.7,0 z\");\n    path.attr({\n        \"opacity\": 1,\n        \"stroke\": \"none\",\n        \"fill\": \"#16964d\"\n    });\n    var text = paper.text(3, 9, \">_\").attr({\n        \"font-size\": \"5px\",\n        \"fill\": \"#16964d\"\n    });\n\n    startY += -2;\n    text.transform(\"T\" + startX + \",\" + startY);\n    startX += -2;\n    path.transform(\"T\" + startX + \",\" + startY);\n}\n\nfunction _drawDecisionTaskIcon(paper, startX, startY) {\n    var path1 = paper.path(\"m 1,2 0,14 16,0 0,-14 z m 1.9,2.4000386 3.7,0 0,2.7999224 -3.7,0 z m 4.36364,0 3.7,0 0,2.7999224 -3.7,0 z m 4.36364,0 3.7,0 0,2.7999224 -3.7,0 z m -8.67364,3.9 3.7,0 0,2.7999224 -3.7,0 z m 4.36364,0 3.7,0 0,2.7999224 -3.7,0 z m 4.36364,0 3.7,0 0,2.7999224 -3.7,0 z m -8.67364,3.9 3.7,0 0,2.7999224 -3.7,0 z m 4.36364,0 3.7,0 0,2.7999224 -3.7,0 z m 4.36364,0 3.7,0 0,2.7999224 -3.7,0 z\");\n    path1.attr({\n        \"opacity\": 1,\n        \"stroke\": \"#000000\",\n        \"fill\": \"#F4F6F7\"\n    });\n\n    var decisionTaskIcon = paper.set();\n    decisionTaskIcon.push(path1);\n\n    decisionTaskIcon.translate(startX, startY);\n    decisionTaskIcon.scale(0.7, 0.7);\n}\n\nfunction _drawEventIcon(paper, element)\n{\n\tif (element.eventDefinition && element.eventDefinition.type)\n\t{\n\t\tif (\"timer\" === element.eventDefinition.type)\n\t\t{\n\t\t\t_drawTimerIcon(paper, element);\n\t\t}\n\t\telse if (\"error\" === element.eventDefinition.type)\n\t\t{\n\t\t\t_drawErrorIcon(paper, element);\n\t\t}\n\t\telse if (\"signal\" === element.eventDefinition.type)\n\t\t{\n\t\t\t_drawSignalIcon(paper, element);\n\t\t}\n\t\telse if (\"message\" === element.eventDefinition.type)\n\t\t{\n\t\t\t_drawMessageIcon(paper, element);\n\t\t}\n\t}\n}\n\nfunction _drawTimerIcon(paper, element)\n{\n\tvar x = element.x + (element.width / 2);\n\tvar y = element.y + (element.height / 2);\n\n\tvar circle = paper.circle(x, y, 10);\n\n\tcircle.attr({\"stroke-width\": 1,\n\t\t\"stroke\": \"black\",\n\t\t\"fill\": \"none\"\n \t});\n\n\tvar path = paper.path(\"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\tpath.attr({\n\t\t\"stroke\": \"none\",\n\t\t\"fill\": \"#585858\"\n \t});\n\tpath.transform(\"T\" + (element.x + 5) + \",\" + (element.y + 5));\n\treturn path;\n}\n\nfunction _drawErrorIcon(paper, element)\n{\n\tvar path = paper.path(\"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\n\tvar fill = \"none\";\n\tvar x = element.x - 1;\n\tvar y = element.y - 1;\n\tif (element.type === \"EndEvent\")\n\t{\n\t\tfill = \"black\";\n\t\tx -= 1;\n\t\ty -= 1;\n\t}\n\n\tpath.attr({\n\t\t\"stroke\": \"black\",\n\t\t\"stroke-width\": 1,\n\t\t\"fill\": fill\n \t});\n\n\tpath.transform(\"T\" + x + \",\" + y);\n\treturn path;\n}\n\nfunction _drawSignalIcon(paper, element)\n{\n\tvar fill = \"none\";\n\tif (element.type === \"ThrowEvent\")\n\t{\n\t\tfill = \"black\";\n\t}\n\n\tvar path = paper.path(\"M 8.7124971,21.247342 L 23.333334,21.247342 L 16.022915,8.5759512 L 8.7124971,21.247342 z\");\n\tpath.attr({\n\t\t\"stroke\": \"black\",\n\t\t\"stroke-width\": 1,\n\t\t\"fill\": fill\n \t});\n\tpath.transform(\"T\" + (element.x - 1) + \",\" + (element.y - 1));\n\treturn path;\n}\n\nfunction _drawMessageIcon(paper, element)\n{\n    var fill = \"none\";\n    if (element.type === \"ThrowEvent\")\n    {\n        fill = \"black\";\n    }\n\n\tvar path = paper.path(\"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\tpath.attr({\n\t\t\"stroke\": \"black\",\n\t\t\"stroke-width\": 1,\n\t\t\"fill\": fill\n \t});\n\tpath.transform(\"T\" + (element.x + 6) + \",\" + (element.y + 6));\n\treturn path;\n}\n"
  },
  {
    "path": "flowable-ui-web/modeler/display/displaymodel.css",
    "content": "div[class*='ui-tooltip-kisbpm-'] {\n    background-color: #ffffff;\n    border-color: #c5c5c5;\n    color: #4a4a4a;\n    font-family: Verdana;\n    font-size: 12px;\n}\n\ndiv[class*='ui-tooltip-kisbpm-'] .qtip-content {\n  color: #4a4a4a;\n  background-color: #ffffff;\n  font-family: Verdana;\n  font-size: 12px;\n}\n\n.ui-tooltip-kisbpm-bpmn .qtip-titlebar {\n  color: #FFFFFF;\n  font-size: 12px;\n  background: #2B414F;\n}\n\n.ui-tooltip-kisbpm-bpmn .qtip-tip {\n  background-color: #2B414F;\n}\n"
  },
  {
    "path": "flowable-ui-web/modeler/display/displaymodel.html",
    "content": "<html>  \n    <head>\n\n        <!-- build:css display/styles/displaymodel-style.css -->\n        <link type=\"text/css\" rel=\"stylesheet\" href=\"display/jquery.qtip.min.css\" />\n        <link type=\"text/css\" rel=\"stylesheet\" href=\"display/displaymodel.css\" />\n        <!-- endbuild -->\n\n        <!-- build:js display/scripts/displaymodel-logic.js -->\n        <script type=\"text/javascript\" src=\"display/jquery.qtip.min.js\"></script>\n        <script type=\"text/javascript\" src=\"display/raphael.min.js\"></script>\n        <script type=\"text/javascript\" src=\"display/bpmn-draw.js\"></script>\n        <script type=\"text/javascript\" src=\"display/bpmn-icons.js\"></script>\n        <script type=\"text/javascript\" src=\"display/Polyline.js\"></script>\n        <script type=\"text/javascript\" src=\"display/displaymodel.js\"></script>\n        <!-- endbuild -->\n\n    </head>\n</html>"
  },
  {
    "path": "flowable-ui-web/modeler/display/displaymodel.js",
    "content": "/* 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 */\nvar NORMAL_STROKE = 1;\nvar SEQUENCEFLOW_STROKE = 1.5;\nvar ASSOCIATION_STROKE = 2;\nvar TASK_STROKE = 1;\nvar TASK_HIGHLIGHT_STROKE = 2;\nvar CALL_ACTIVITY_STROKE = 2;\nvar ENDEVENT_STROKE = 3;\n\nvar COMPLETED_COLOR= \"#2632aa\";\nvar TEXT_COLOR= \"#373e48\";\nvar CURRENT_COLOR= \"#017501\";\nvar HOVER_COLOR= \"#666666\";\nvar ACTIVITY_STROKE_COLOR = \"#bbbbbb\";\nvar ACTIVITY_FILL_COLOR = \"#f9f9f9\";\nvar MAIN_STROKE_COLOR = \"#585858\";\n\nvar TEXT_PADDING = 3;\nvar ARROW_WIDTH = 4;\nvar MARKER_WIDTH = 12;\n\nvar TASK_FONT = {font: \"11px Arial\", opacity: 1, fill: Raphael.rgb(0, 0, 0)};\n\n// icons\nvar ICON_SIZE = 16;\nvar ICON_PADDING = 4;\n\nvar INITIAL_CANVAS_WIDTH;\nvar INITIAL_CANVAS_HEIGHT;\n\nvar paper;\nvar viewBox;\nvar viewBoxWidth;\nvar viewBoxHeight;\n\nvar canvasWidth;\nvar canvasHeight;\n\nvar modelDiv = jQuery('#bpmnModel');\nvar modelId = modelDiv.attr('data-model-id');\nvar historyModelId = modelDiv.attr('data-history-id');\nvar processDefinitionId = modelDiv.attr('data-process-definition-id');\nvar modelType = modelDiv.attr('data-model-type');\n\n// Support for custom background colors for activities\nvar customActivityColors = modelDiv.attr('data-activity-color-mapping');\nif (customActivityColors !== null && customActivityColors !== undefined && customActivityColors.length > 0) {\n    // Stored on the attribute as a string\n    customActivityColors = JSON.parse(customActivityColors);\n}\n\nvar customActivityToolTips = modelDiv.attr('data-activity-tooltips');\nif (customActivityToolTips !== null && customActivityToolTips !== undefined && customActivityToolTips.length > 0) {\n    // Stored on the attribute as a string\n    customActivityToolTips = JSON.parse(customActivityToolTips);\n}\n\n// Support for custom opacity for activity backgrounds\nvar customActivityBackgroundOpacity = modelDiv.attr('data-activity-opacity');\n\nvar elementsAdded = new Array();\nvar elementsRemoved = new Array();\n\nfunction _showTip(htmlNode, element)\n{\n\n    // Custom tooltip\n    var documentation = undefined;\n    if (customActivityToolTips) {\n        if (customActivityToolTips[element.name]) {\n            documentation = customActivityToolTips[element.name];\n        } else if (customActivityToolTips[element.id]) {\n            documentation = customActivityToolTips[element.id];\n        } else {\n            documentation = ''; // Show nothing if custom tool tips are enabled\n        }\n    }\n\n    // Default tooltip, no custom tool tip set\n    if (documentation === undefined) {\n        var documentation = \"\";\n        if (element.name && element.name.length > 0) {\n            documentation += \"<b>Name</b>: <i>\" + element.name + \"</i><br/><br/>\";\n        }\n\n        if (element.properties) {\n            for (var i = 0; i < element.properties.length; i++) {\n                var propName = element.properties[i].name;\n                if (element.properties[i].type && element.properties[i].type === 'list') {\n                    documentation += '<b>' + propName + '</b>:<br/>';\n                    for (var j = 0; j < element.properties[i].value.length; j++) {\n                        documentation += '<i>' + element.properties[i].value[j] + '</i><br/>';\n                    }\n                }\n                else {\n                    documentation += '<b>' + propName + '</b>: <i>' + element.properties[i].value + '</i><br/>';\n                }\n            }\n        }\n    }\n\n    var text = element.type + \" \";\n    if (element.name && element.name.length > 0)\n    {\n        text += element.name;\n    }\n    else\n    {\n        text += element.id;\n    }\n\n    htmlNode.qtip({\n        content: {\n            text: documentation,\n            title: {\n                text: text\n            }\n        },\n        position: {\n            my: 'top left',\n            at: 'bottom center',\n            viewport: jQuery('#bpmnModel')\n        },\n        hide: {\n            fixed: true, delay: 500,\n            event: 'click mouseleave'\n        },\n        style: {\n            classes: 'ui-tooltip-kisbpm-bpmn'\n        }\n    });\n}\n\nfunction _addHoverLogic(element, type, defaultColor)\n{\n    var strokeColor = _bpmnGetColor(element, defaultColor);\n    var topBodyRect = null;\n    if (type === \"rect\")\n    {\n        topBodyRect = paper.rect(element.x, element.y, element.width, element.height);\n    }\n    else if (type === \"circle\")\n    {\n        var x = element.x + (element.width / 2);\n        var y = element.y + (element.height / 2);\n        topBodyRect = paper.circle(x, y, 15);\n    }\n    else if (type === \"rhombus\")\n    {\n        topBodyRect = paper.path(\"M\" + element.x + \" \" + (element.y + (element.height / 2)) +\n            \"L\" + (element.x + (element.width / 2)) + \" \" + (element.y + element.height) +\n            \"L\" + (element.x + element.width) + \" \" + (element.y + (element.height / 2)) +\n            \"L\" + (element.x + (element.width / 2)) + \" \" + element.y + \"z\"\n        );\n    }\n\n    var opacity = 0;\n    var fillColor = \"#ffffff\";\n    if (jQuery.inArray(element.id, elementsAdded) >= 0)\n    {\n        opacity = 0.2;\n        fillColor = \"green\";\n    }\n\n    if (jQuery.inArray(element.id, elementsRemoved) >= 0)\n    {\n        opacity = 0.2;\n        fillColor = \"red\";\n    }\n\n    topBodyRect.attr({\n        \"opacity\": opacity,\n        \"stroke\" : \"none\",\n        \"fill\" : fillColor\n    });\n    _showTip(jQuery(topBodyRect.node), element);\n\n    topBodyRect.mouseover(function() {\n        paper.getById(element.id).attr({\"stroke\":HOVER_COLOR});\n    });\n\n    topBodyRect.mouseout(function() {\n        paper.getById(element.id).attr({\"stroke\":strokeColor});\n    });\n}\n\nfunction _zoom(zoomIn)\n{\n    var tmpCanvasWidth, tmpCanvasHeight;\n    if (zoomIn)\n    {\n        tmpCanvasWidth = canvasWidth * (1.0/0.90);\n        tmpCanvasHeight = canvasHeight * (1.0/0.90);\n    }\n    else\n    {\n        tmpCanvasWidth = canvasWidth * (1.0/1.10);\n        tmpCanvasHeight = canvasHeight * (1.0/1.10);\n    }\n\n    if (tmpCanvasWidth != canvasWidth || tmpCanvasHeight != canvasHeight)\n    {\n        canvasWidth = tmpCanvasWidth;\n        canvasHeight = tmpCanvasHeight;\n        paper.setSize(canvasWidth, canvasHeight);\n    }\n}\n\nvar modelUrl;\n\nif (modelType == 'runtime') {\n\tif (historyModelId) {\n    \tmodelUrl = FLOWABLE.APP_URL.getProcessInstanceModelJsonHistoryUrl(historyModelId);\n\t} else {\n    \tmodelUrl = FLOWABLE.APP_URL.getProcessInstanceModelJsonUrl(modelId);\n\t}\n} else if (modelType == 'design') {\n\tif (historyModelId) {\n    \tmodelUrl = FLOWABLE.APP_URL.getModelHistoryModelJsonUrl(modelId, historyModelId);\n\t} else {\n    \tmodelUrl = FLOWABLE.APP_URL.getModelModelJsonUrl(modelId);\n\t}\n} else if (modelType == 'process-definition') {\n    modelUrl = FLOWABLE.APP_URL.getProcessDefinitionModelJsonUrl(processDefinitionId);\n}\n\nvar request = jQuery.ajax({\n    type: 'get',\n    url: modelUrl + '?nocaching=' + new Date().getTime()\n});\n\nrequest.success(function(data, textStatus, jqXHR) {\n\n    if ((!data.elements || data.elements.length == 0) && (!data.pools || data.pools.length == 0)) return;\n\n    INITIAL_CANVAS_WIDTH = data.diagramWidth;\n\n    if (modelType == 'design') {\n    \tINITIAL_CANVAS_WIDTH += 20;\n    } else {\n        INITIAL_CANVAS_WIDTH += 30;\n    }\n\n    INITIAL_CANVAS_HEIGHT = data.diagramHeight + 50;\n    canvasWidth = INITIAL_CANVAS_WIDTH;\n    canvasHeight = INITIAL_CANVAS_HEIGHT;\n    viewBoxWidth = INITIAL_CANVAS_WIDTH;\n    viewBoxHeight = INITIAL_CANVAS_HEIGHT;\n\n    if (modelType == 'design') {\n    \tvar headerBarHeight = 170;\n    \tvar offsetY = 0;\n    \tif (jQuery(window).height() > (canvasHeight + headerBarHeight))\n    \t{\n        \toffsetY = (jQuery(window).height() - headerBarHeight - canvasHeight) / 2;\n    \t}\n\n    \tif (offsetY > 50) {\n        \toffsetY = 50;\n    \t}\n\n    \tjQuery('#bpmnModel').css('marginTop', offsetY);\n    }\n\n    jQuery('#bpmnModel').width(INITIAL_CANVAS_WIDTH);\n    jQuery('#bpmnModel').height(INITIAL_CANVAS_HEIGHT);\n    paper = Raphael(document.getElementById('bpmnModel'), canvasWidth, canvasHeight);\n    paper.setViewBox(0, 0, viewBoxWidth, viewBoxHeight, false);\n    paper.renderfix();\n\n    if (data.pools)\n    {\n        for (var i = 0; i < data.pools.length; i++)\n        {\n            var pool = data.pools[i];\n            _drawPool(pool);\n        }\n    }\n\n    var modelElements = data.elements;\n    for (var i = 0; i < modelElements.length; i++)\n    {\n        var element = modelElements[i];\n        //try {\n        var drawFunction = eval(\"_draw\" + element.type);\n        drawFunction(element);\n        //} catch(err) {console.log(err);}\n    }\n\n    if (data.flows)\n    {\n        for (var i = 0; i < data.flows.length; i++)\n        {\n            var flow = data.flows[i];\n            if (flow.type === 'sequenceFlow') {\n                _drawFlow(flow);\n            } else if (flow.type === 'association') {\n                _drawAssociation(flow);\n            }\n        }\n    }\n});\n\nrequest.error(function(jqXHR, textStatus, errorThrown) {\n    alert(\"error\");\n});\n"
  },
  {
    "path": "flowable-ui-web/modeler/display/package.json",
    "content": "{\n  \"name\": \"displaymodel\",\n  \"version\": \"1.0.0\",\n  \"dependencies\": {},\n  \"devDependencies\": {\n    \"grunt\": \"0.4.2\",\n    \"grunt-autoprefixer\": \"0.4.0\",\n    \"grunt-bower-install\": \"0.7.0\",\n    \"grunt-concurrent\": \"0.4.1\",\n    \"grunt-contrib-clean\": \"0.5.0\",\n    \"grunt-contrib-coffee\": \"0.7.0\",\n    \"grunt-contrib-compass\": \"0.6.0\",\n    \"grunt-contrib-concat\": \"0.3.0\",\n    \"grunt-contrib-connect\": \"0.5.0\",\n    \"grunt-contrib-copy\": \"0.4.1\",\n    \"grunt-contrib-cssmin\": \"0.7.0\",\n    \"grunt-contrib-htmlmin\": \"0.1.3\",\n    \"grunt-contrib-imagemin\": \"0.3.0\",\n    \"grunt-contrib-jshint\": \"0.7.1\",\n    \"grunt-contrib-uglify\": \"0.2.0\",\n    \"grunt-contrib-watch\": \"0.5.2\",\n    \"grunt-google-cdn\": \"0.2.0\",\n    \"grunt-newer\": \"0.5.4\",\n    \"grunt-ng-annotate\": \"0.5.0\",\n    \"grunt-rev\": \"0.1.0\",\n    \"grunt-svgmin\": \"0.2.0\",\n    \"grunt-usemin\": \"2.0.0\",\n    \"jshint-stylish\": \"0.1.3\",\n    \"load-grunt-tasks\": \"0.2.0\",\n    \"time-grunt\": \"0.2.1\",\n    \"grunt-text-replace\": \"0.3.11\",\n    \"grunt-contrib-rename\": \"0.0.3\"\n  },\n  \"engines\": {\n    \"node\": \">=0.8.0\"\n  }\n}\n"
  },
  {
    "path": "flowable-ui-web/modeler/display-cmmn/cmmn-draw.js",
    "content": "/* 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\nfunction _cmmnGetColor(element, defaultColor)\n{\n    var strokeColor;\n    if(element.current) {\n        strokeColor = CURRENT_COLOR;\n    } else if(element.completed) {\n        strokeColor = COMPLETED_COLOR;\n    } else {\n        strokeColor = defaultColor;\n    }\n    return strokeColor;\n}\n\nfunction _drawPlanModel(planModel)\n{\n\tvar rect = paper.rect(planModel.x, planModel.y, planModel.width, planModel.height);\n\n\trect.attr({\"stroke-width\": 1,\n\t\t\"stroke\": \"#000000\",\n\t\t\"fill\": \"white\"\n \t});\n\n\tif (planModel.name)\n\t{\n\t\tvar planModelName = paper.text(planModel.x + 14, planModel.y + (planModel.height / 2), planModel.name).attr({\n\t        \"text-anchor\" : \"middle\",\n\t        \"font-family\" : \"Arial\",\n\t        \"font-size\" : \"12\",\n\t        \"fill\" : \"#000000\"\n\t  \t});\n\n\t\tplanModelName.transform(\"r270\");\n\t}\n}\n\nfunction _drawSubProcess(element)\n{\n\tvar rect = paper.rect(element.x, element.y, element.width, element.height, 4);\n\n\tvar strokeColor = _cmmnGetColor(element, MAIN_STROKE_COLOR);\n\n\trect.attr({\"stroke-width\": 1,\n\t\t\"stroke\": strokeColor,\n\t\t\"fill\": \"white\"\n \t});\n}\n\nfunction _drawVariableServiceTaskIcon(element)\n{\n\t_drawTask(element);\n\tif (element.taskType === \"mail\")\n\t{\n\t\t_drawSendTaskIcon(paper, element.x + 4, element.y + 4);\n\t}\n\telse if (element.taskType === \"camel\")\n\t{\n\t\t_drawCamelTaskIcon(paper, element.x + 4, element.y + 4);\n\t}\n\telse if (element.taskType === \"mule\")\n\t{\n\t\t_drawMuleTaskIcon(paper, element.x + 4, element.y + 4);\n\t}\n    else if (element.taskType === \"http\")\n    {\n        _drawHttpTaskIcon(paper, element.x + 4, element.y + 4);\n    }\n\telse if (element.stencilIconId)\n\t{\n\t\tpaper.image(\"../service/stencilitem/\" + element.stencilIconId + \"/icon\", element.x + 4, element.y + 4, 16, 16);\n\t}\n\telse\n\t{\n\t\t_drawServiceTaskIcon(paper, element.x + 4, element.y + 4);\n\t}\n\t_addHoverLogic(element, \"rect\", ACTIVITY_STROKE_COLOR);\n}\n\nfunction _drawHttpServiceTask(element)\n{\n    _drawTask(element);\n    _drawHttpTaskIcon(paper, element.x + 4, element.y + 4);\n    _addHoverLogic(element, \"rect\", ACTIVITY_STROKE_COLOR);\n}\n\nfunction _drawHumanTask(element)\n{\n\t_drawTask(element);\n\t_drawHumanTaskIcon(paper, element.x + 4, element.y + 4);\n\t_addHoverLogic(element, \"rect\", ACTIVITY_STROKE_COLOR);\n}\n\nfunction _drawCaseTask(element)\n{\n    _drawTask(element);\n    _drawCaseTaskIcon(paper, element.x + 1, element.y + 1);\n    _addHoverLogic(element, \"rect\", ACTIVITY_STROKE_COLOR);\n}\n\nfunction _drawProcessTask(element)\n{\n    _drawTask(element);\n    _drawProcessTaskIcon(paper, element.x + 1, element.y + 1);\n    _addHoverLogic(element, \"rect\", ACTIVITY_STROKE_COLOR);\n}\n\nfunction _drawScriptTaskIcon(paper, startX, startY)\n{\n\tvar path1 = paper.path(\"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\tpath1.attr({\n\t\t\"opacity\": 1,\n\t\t\"stroke\": \"none\",\n\t\t\"fill\": \"#72a7d0\"\n \t});\n\n\tvar scriptTaskIcon = paper.set();\n\tscriptTaskIcon.push(path1);\n\n\tscriptTaskIcon.transform(\"T\" + startX + \",\" + startY);\n}\n\nfunction _drawScriptServiceTask(element)\n{\n\t_drawTask(element);\n\t_drawScriptTaskIcon(paper, element.x + 4, element.y + 4);\n\t_addHoverLogic(element, \"rect\", ACTIVITY_STROKE_COLOR);\n}\n\nfunction _drawDecisionTask(element)\n{\n    _drawTask(element);\n    _drawDecisionTaskIcon(paper, element.x + 1, element.y + 1);\n    _addHoverLogic(element, \"rect\", ACTIVITY_STROKE_COLOR);\n}\n\nfunction _drawServiceTask(element)\n{\n    _drawTask(element);\n    _drawVariableServiceTaskIcon(element);\n    _addHoverLogic(element, \"rect\", ACTIVITY_STROKE_COLOR);\n}\n\nfunction _drawTask(element)\n{\n    var rectAttrs = {};\n\n    // Stroke\n    var strokeColor = _cmmnGetColor(element, ACTIVITY_STROKE_COLOR);\n    rectAttrs['stroke'] = strokeColor;\n\n    var strokeWidth;\n    if (strokeColor === ACTIVITY_STROKE_COLOR) {\n        strokeWidth = TASK_STROKE;\n    } else {\n        strokeWidth = TASK_HIGHLIGHT_STROKE;\n    }\n\n\tvar width = element.width - (strokeWidth / 2);\n\tvar height = element.height - (strokeWidth / 2);\n\n\tvar rect = paper.rect(element.x, element.y, width, height, 4);\n    rectAttrs['stroke-width'] = strokeWidth;\n\n    // Fill\n\trectAttrs['fill'] = ACTIVITY_FILL_COLOR;\n\n    rect.attr(rectAttrs);\n\trect.id = element.id;\n\n\tif (element.name) {\n\t\tthis._drawMultilineText(element.name, element.x, element.y, element.width, element.height, \"middle\", \"middle\", 11);\n\t}\n}\n\nfunction _drawTimerEventListener(element)\n{\n    _drawEventListener(element);\n    _drawTimerEventListenerIcon(paper, element);\n    _addHoverLogic(element, \"rect\", ACTIVITY_STROKE_COLOR);\n}\n\nfunction _drawUserEventListener(element)\n{\n    _drawEventListener(element);\n    _drawUserEventListenerIcon(paper, element);\n    _addHoverLogic(element, \"rect\", ACTIVITY_STROKE_COLOR);\n}\n\nfunction _drawGenericEventListener(element)\n{\n    _drawEventListener(element);\n    _addHoverLogic(element, \"rect\", ACTIVITY_STROKE_COLOR);\n}\n\nfunction _drawEventListener(element)\n{\n    var x = element.x + (element.width / 2);\n\tvar y = element.y + (element.height / 2);\n\n\tvar circle = paper.circle(x, y, 15);\n\n    circle.attr({\"stroke-width\": 1,\n        \"stroke\": \"black\",\n        \"fill\": \"white\"\n    });\n\n\tcircle.id = element.id;\n}\n\nfunction _drawMilestone(element)\n{\n    var rectAttrs = {};\n\n    // Stroke\n    var strokeColor = _cmmnGetColor(element, ACTIVITY_STROKE_COLOR);\n    rectAttrs['stroke'] = strokeColor;\n\n    var strokeWidth;\n    if (strokeColor === ACTIVITY_STROKE_COLOR) {\n        strokeWidth = TASK_STROKE;\n    } else {\n        strokeWidth = TASK_HIGHLIGHT_STROKE;\n    }\n\n    var width = element.width - (strokeWidth / 2);\n    var height = element.height - (strokeWidth / 2);\n\n    var rect = paper.rect(element.x, element.y, width, height, 24);\n    rectAttrs['stroke-width'] = strokeWidth;\n\n    // Fill\n    rectAttrs['fill'] = WHITE_FILL_COLOR;\n\n    rect.attr(rectAttrs);\n    rect.id = element.id;\n\n    if (element.name) {\n        this._drawMultilineText(element.name, element.x, element.y, element.width, element.height, \"middle\", \"middle\", 11);\n    }\n}\n\nfunction _drawStage(element)\n{\n    var rectAttrs = {};\n\n    // Stroke\n    var strokeColor = _cmmnGetColor(element, ACTIVITY_STROKE_COLOR);\n    rectAttrs['stroke'] = strokeColor;\n\n    var strokeWidth;\n    if (strokeColor === ACTIVITY_STROKE_COLOR) {\n        strokeWidth = TASK_STROKE;\n    } else {\n        strokeWidth = TASK_HIGHLIGHT_STROKE;\n    }\n\n    var width = element.width - (strokeWidth / 2);\n    var height = element.height - (strokeWidth / 2);\n\n    var rect = paper.rect(element.x, element.y, width, height, 16);\n    rectAttrs['stroke-width'] = strokeWidth;\n\n    // Fill\n    rectAttrs['fill'] = WHITE_FILL_COLOR;\n\n    rect.attr(rectAttrs);\n    rect.id = element.id;\n\n    if (element.name) {\n        this._drawMultilineText(element.name, element.x + 10, element.y + 5, element.width, element.height, \"start\", \"top\", 11);\n    }\n}\n\nfunction _drawPlanModel(element)\n{\n    var rectAttrs = {};\n\n    // Stroke\n    var strokeColor = _cmmnGetColor(element, ACTIVITY_STROKE_COLOR);\n    rectAttrs['stroke'] = strokeColor;\n\n    var strokeWidth;\n    if (strokeColor === ACTIVITY_STROKE_COLOR) {\n        strokeWidth = TASK_STROKE;\n    } else {\n        strokeWidth = TASK_HIGHLIGHT_STROKE;\n    }\n\n    var width = element.width - (strokeWidth / 2);\n    var height = element.height - (strokeWidth / 2);\n\n    var rect = paper.rect(element.x, element.y, width, height, 4);\n    rectAttrs['stroke-width'] = strokeWidth;\n\n    // Fill\n    rectAttrs['fill'] = WHITE_FILL_COLOR;\n\n    rect.attr(rectAttrs);\n    rect.id = element.id;\n\n    var path1 = paper.path(\"M20 55 L37 34 L275 34 L291 55\");\n    path1.attr({\n        \"opacity\": 1,\n        \"stroke\": strokeColor,\n        \"fill\": \"#ffffff\"\n    });\n\n    var planModelHeader = paper.set();\n    planModelHeader.push(path1);\n\n    planModelHeader.translate(element.x, element.y - 55);\n    if (element.name) {\n        this._drawMultilineText(element.name, element.x + 10, element.y - 16, 275, element.height, \"middle\", \"top\", 11);\n    }\n}\n\nfunction _drawEntryCriterion(element)\n{\n    var strokeColor = _cmmnGetColor(element, MAIN_STROKE_COLOR);\n\n    var rhombus = paper.path(\"M\" + element.x + \" \" + (element.y + (element.height / 2)) +\n        \"L\" + (element.x + (element.width / 2)) + \" \" + (element.y + element.height) +\n        \"L\" + (element.x + element.width) + \" \" + (element.y + (element.height / 2)) +\n        \"L\" + (element.x + (element.width / 2)) + \" \" + element.y + \"z\"\n    );\n\n    // Fill\n    var gatewayFillColor = WHITE_FILL_COLOR;\n\n    // Opacity\n    var gatewayOpacity = 1.0;\n\n    rhombus.attr(\"stroke-width\", 1);\n    rhombus.attr(\"stroke\", strokeColor);\n    rhombus.attr(\"fill\", gatewayFillColor);\n    rhombus.attr(\"fill-opacity\", gatewayOpacity);\n\n    rhombus.id = element.id;\n}\n\nfunction _drawExitCriterion(element)\n{\n    var strokeColor = _cmmnGetColor(element, MAIN_STROKE_COLOR);\n\n    var rhombus = paper.path(\"M\" + element.x + \" \" + (element.y + (element.height / 2)) +\n        \"L\" + (element.x + (element.width / 2)) + \" \" + (element.y + element.height) +\n        \"L\" + (element.x + element.width) + \" \" + (element.y + (element.height / 2)) +\n        \"L\" + (element.x + (element.width / 2)) + \" \" + element.y + \"z\"\n    );\n\n    // Fill\n    var gatewayFillColor = '#000000';\n\n    // Opacity\n    var gatewayOpacity = 1.0;\n\n    rhombus.attr(\"stroke-width\", 1);\n    rhombus.attr(\"stroke\", strokeColor);\n    rhombus.attr(\"fill\", gatewayFillColor);\n    rhombus.attr(\"fill-opacity\", gatewayOpacity);\n\n    rhombus.id = element.id;\n}\n\nfunction _drawMultilineText(text, x, y, boxWidth, boxHeight, horizontalAnchor, verticalAnchor, fontSize)\n{\n\tif (!text || text == \"\")\n\t{\n\t\treturn;\n\t}\n\n\tvar textBoxX, textBoxY;\n    var width = boxWidth - (2 * TEXT_PADDING);\n\n    if (horizontalAnchor === \"middle\")\n    {\n    \ttextBoxX = x + (boxWidth / 2);\n    }\n    else if (horizontalAnchor === \"start\")\n    {\n    \ttextBoxX = x;\n    }\n\n    textBoxY = y + (boxHeight / 2);\n\n \tvar t = paper.text(textBoxX + TEXT_PADDING, textBoxY + TEXT_PADDING).attr({\n        \"text-anchor\" : horizontalAnchor,\n        \"font-family\" : \"Arial\",\n        \"font-size\" : fontSize,\n        \"fill\" : \"#373e48\"\n  \t});\n\n    var abc = \"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ\";\n    t.attr({\n        \"text\" : abc\n    });\n    var letterWidth = t.getBBox().width / abc.length;\n\n    t.attr({\n        \"text\" : text\n    });\n    var removedLineBreaks = text.split(\"\\n\");\n    var x = 0, s = [];\n    for (var r = 0; r < removedLineBreaks.length; r++)\n    {\n  \t    var words = removedLineBreaks[r].split(\" \");\n  \t    for ( var i = 0; i < words.length; i++) {\n\n  \t        var l = words[i].length;\n  \t        if (x + (l * letterWidth) > width) {\n  \t            s.push(\"\\n\");\n  \t            x = 0;\n  \t        }\n  \t        x += l * letterWidth;\n  \t        s.push(words[i] + \" \");\n  \t    }\n\t  \ts.push(\"\\n\");\n        x = 0;\n    }\n    t.attr({\n    \t\"text\" : s.join(\"\")\n    });\n\n    if (verticalAnchor && verticalAnchor === \"top\")\n    {\n    \tt.attr({\"y\": y + (t.getBBox().height / 2)});\n    }\n}\n\nfunction _drawAssociation(flow){\n\n\tvar polyline = new Polyline(flow.id, flow.waypoints, ASSOCIATION_STROKE, paper);\n\tpolyline.element = paper.path(polyline.path);\n\tpolyline.element.attr({\"stroke-width\": ASSOCIATION_STROKE});\n\tpolyline.element.attr({\"stroke-dasharray\": \". \"});\n\tpolyline.element.attr({\"stroke\":\"#585858\"});\n\n\tpolyline.element.id = flow.id;\n\n\tvar polylineInvisible = new Polyline(flow.id, flow.waypoints, ASSOCIATION_STROKE, paper);\n\n\tpolylineInvisible.element = paper.path(polyline.path);\n\tpolylineInvisible.element.attr({\n\t\t\t\"opacity\": 0,\n\t\t\t\"stroke-width\": 8,\n            \"stroke\" : \"#000000\"\n\t});\n\n\t_showTip(jQuery(polylineInvisible.element.node), flow);\n\n\tpolylineInvisible.element.mouseover(function() {\n\t\tpaper.getById(polyline.element.id).attr({\"stroke\":\"blue\"});\n\t});\n\n\tpolylineInvisible.element.mouseout(function() {\n\t\tpaper.getById(polyline.element.id).attr({\"stroke\":\"#585858\"});\n\t});\n}\n\nfunction _drawArrowHead(line, connectionType)\n{\n\tvar doubleArrowWidth = 2 * ARROW_WIDTH;\n\n\tvar arrowHead = paper.path(\"M0 0L-\" + (ARROW_WIDTH / 2 + .5) + \" -\" + doubleArrowWidth + \"L\" + (ARROW_WIDTH/2 + .5) + \" -\" + doubleArrowWidth + \"z\");\n\n\t// anti smoothing\n\tif (this.strokeWidth%2 == 1)\n\t\tline.x2 += .5, line.y2 += .5;\n\n\tarrowHead.transform(\"t\" + line.x2 + \",\" + line.y2 + \"\");\n\tarrowHead.transform(\"...r\" + Raphael.deg(line.angle - Math.PI / 2) + \" \" + 0 + \" \" + 0);\n\n\tarrowHead.attr(\"fill\", \"#585858\");\n\n\tarrowHead.attr(\"stroke-width\", SEQUENCEFLOW_STROKE);\n\tarrowHead.attr(\"stroke\", \"#585858\");\n\n\treturn arrowHead;\n}\n"
  },
  {
    "path": "flowable-ui-web/modeler/display-cmmn/cmmn-icons.js",
    "content": "/* 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\nfunction _drawHumanTaskIcon(paper, startX, startY)\n{\n\tvar path1 = paper.path(\"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\tpath1.attr({\n\t\t\"opacity\": 1,\n\t\t\"stroke\": \"none\",\n\t\t\"fill\": \"#d1b575\"\n \t});\n\n\tvar userTaskIcon = paper.set();\n\tuserTaskIcon.push(path1);\n\n\tuserTaskIcon.transform(\"T\" + startX + \",\" + startY);\n}\n\nfunction _drawServiceTaskIcon(paper, startX, startY)\n{\n\tvar path1 = paper.path(\"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\tpath1.attr({\n\t\t\"opacity\": 1,\n\t\t\"stroke\": \"none\",\n\t\t\"fill\": \"#72a7d0\"\n \t});\n\n\tvar serviceTaskIcon = paper.set();\n\tserviceTaskIcon.push(path1);\n\n\tserviceTaskIcon.transform(\"T\" + startX + \",\" + startY);\n}\n\nfunction _drawCaseTaskIcon(paper, startX, startY)\n{\n    var path1 = paper.path(\"M5 8 L9 4 L18 4 L 21 7\");\n    path1.attr({\n        \"opacity\": 1,\n        \"stroke\": \"#000000\",\n        \"fill\": \"#000000\"\n    });\n\n    var path2 = paper.path(\"M1 23 L1 4 L30 4 L30 23z\");\n    path2.attr({\n        \"opacity\": 1,\n        \"stroke\": \"#000000\",\n        \"fill\": \"#F4F6F7\"\n    });\n\n    var caseTaskIcon = paper.set();\n    caseTaskIcon.push(path1);\n    caseTaskIcon.push(path2);\n\n    caseTaskIcon.translate(startX, startY);\n    caseTaskIcon.scale(0.7, 0.7);\n}\n\nfunction _drawProcessTaskIcon(paper, startX, startY)\n{\n    var path1 = paper.path(\"M1 23 L7 11 L1 0 L30 0 L 35 11 L 30 23z\");\n    path1.attr({\n        \"opacity\": 1,\n        \"stroke\": \"#000000\",\n        \"fill\": \"#F4F6F7\"\n    });\n\n    var processTaskIcon = paper.set();\n    processTaskIcon.push(path1);\n\n    processTaskIcon.translate(startX, startY);\n    processTaskIcon.scale(0.7, 0.7);\n}\n\nfunction _drawDecisionTaskIcon(paper, startX, startY)\n{\n    var path1 = paper.path(\"m 1,2 0,14 16,0 0,-14 z m 1.9,2.4000386 3.7,0 0,2.7999224 -3.7,0 z m 4.36364,0 3.7,0 0,2.7999224 -3.7,0 z m 4.36364,0 3.7,0 0,2.7999224 -3.7,0 z m -8.67364,3.9 3.7,0 0,2.7999224 -3.7,0 z m 4.36364,0 3.7,0 0,2.7999224 -3.7,0 z m 4.36364,0 3.7,0 0,2.7999224 -3.7,0 z m -8.67364,3.9 3.7,0 0,2.7999224 -3.7,0 z m 4.36364,0 3.7,0 0,2.7999224 -3.7,0 z m 4.36364,0 3.7,0 0,2.7999224 -3.7,0 z\");\n    path1.attr({\n        \"opacity\": 1,\n        \"stroke\": \"#000000\",\n        \"fill\": \"#F4F6F7\"\n    });\n\n    var decisionTaskIcon = paper.set();\n    decisionTaskIcon.push(path1);\n\n    decisionTaskIcon.translate(startX, startY);\n    decisionTaskIcon.scale(0.7, 0.7);\n}\n\nfunction _drawHttpTaskIcon(paper, startX, startY)\n{\n    var path = paper.path(\"m 16.704699,5.9229055 q 0.358098,0 0.608767,0.2506681 0.250669,0.250668 0.250669,0.6087677 0,0.3580997 -0.250669,0.6087677 -0.250669,0.2506679 -0.608767,0.2506679 -0.358098,0 -0.608767,-0.2506679 -0.250669,-0.250668 -0.250669,-0.6087677 0,-0.3580997 0.250669,-0.6087677 0.250669,-0.2506681 0.608767,-0.2506681 z m 2.578308,-2.0053502 q -2.229162,0 -3.854034,0.6759125 -1.624871,0.6759067 -3.227361,2.2694472 -0.716197,0.725146 -1.575633,1.7457293 L 7.2329969,8.7876913 Q 7.0897576,8.8055849 7.000233,8.9309334 L 4.9948821,12.368677 q -0.035811,0.06267 -0.035811,0.143242 0,0.107426 0.080572,0.205905 l 0.5729577,0.572957 q 0.125334,0.116384 0.2864786,0.07162 l 2.4708789,-0.760963 2.5156417,2.515645 -0.76096,2.470876 q -0.009,0.02687 -0.009,0.08057 0,0.125338 0.08058,0.205905 l 0.572957,0.572958 q 0.170096,0.152194 0.349146,0.04476 l 3.437744,-2.005351 q 0.125335,-0.08953 0.143239,-0.232763 l 0.17905,-3.392986 q 1.02058,-0.859435 1.745729,-1.575629 1.67411,-1.6830612 2.309735,-3.2049805 0.635625,-1.5219191 0.635625,-3.8585111 0,-0.1253369 -0.08505,-0.2148575 -0.08505,-0.089526 -0.201431,-0.089526 z\");\n    path.attr({\n        \"opacity\": 1,\n        \"stroke\": \"none\",\n        \"fill\": \"#16964d\"\n    });\n\n    startX += -2;\n    startY += -2;\n\n    path.transform(\"T\" + startX + \",\" + startY);\n\n}\n\nfunction _drawBusinessRuleTaskIcon(paper, startX, startY) {\n    var path1 = paper.path(\"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    path1.attr({\n        \"stroke\": \"none\",\n        \"fill\": \"#72a7d0\"\n    });\n\n    var businessRuleTaskIcon = paper.set();\n    businessRuleTaskIcon.push(path1);\n\n    businessRuleTaskIcon.transform(\"T\" + startX + \",\" + startY);\n}\n\nfunction _drawTimerEventListenerIcon(paper, element)\n{\n\tvar x = element.x + (element.width / 2);\n    var y = element.y + (element.height / 2);\n\n\tvar circle = paper.circle(x, y, 10);\n\n\tcircle.attr({\"stroke-width\": 1,\n\t\t\"stroke\": \"black\",\n\t\t\"fill\": \"none\"\n \t});\n\n\tvar path = paper.path(\"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\tpath.attr({\n\t\t\"stroke\": \"none\",\n\t\t\"fill\": \"#585858\"\n \t});\n\tpath.transform(\"T\" + (element.x + 5) + \",\" + (element.y + 5));\n\treturn path;\n}\n\nfunction _drawUserEventListenerIcon(paper, element) {\n    var userTaskIcon = paper.set();\n    var path1 = paper.path(\"M0.585,24.167h24.083v-7.833c0,0-2.333-3.917-7.083-5.167h-9.25 c-4.417,1.333-7.833,5.75-7.833,5.75L0.585,24.167z\");\n    path1.attr({\"opacity\": 1, \"stroke\": \"none\", \"fill\": \"#F4F6F7\"});\n    userTaskIcon.push(path1);\n\n    var path2 = paper.path(\"M6,20L6,24\");\n    path2.attr({\"opacity\": 1, \"stroke\": \"white\", \"fill\": \"none\"});\n    userTaskIcon.push(path2);\n\n    var path3 = paper.path(\"M20,20L20,24\");\n    path3.attr({\"opacity\": 1, \"stroke\": \"white\", \"fill\": \"none\"});\n    userTaskIcon.push(path3);\n\n    var circle = paper.circle(13.002, 5.916, 5.417);\n    circle.attr({\"stroke-width\": 1, \"stroke\": \"black\", \"fill\": \"#000000\"});\n    userTaskIcon.push(circle);\n\n    var path4 = paper.path(\"M8.043,7.083c0,0,2.814-2.426,5.376-1.807s4.624-0.693,4.624-0.693 c0.25,1.688,0.042,3.75-1.458,5.584c0,0,1.083,0.75,1.083,1.5s0.125,1.875-1,3s-5.5,1.25-6.75,0S8.668,12.834,8.668,12 s0.583-1.25,1.25-1.917C8.835,9.5,7.419,7.708,8.043,7.083z\");\n    path4.attr({\"opacity\": 1, \"stroke\": \"none\", \"fill\": \"#F0EFF0\"});\n    userTaskIcon.push(path4);\n\n    var x = (element.width / 2) - 2;\n    var y = (element.height / 2) - 2;\n    var circle2 = paper.circle(x, y, 17);\n    circle2.attr({\"stroke-width\": 1, \"stroke\": \"#F0EFF0\", \"fill\": \"none\"});\n    userTaskIcon.push(circle2);\n\n    userTaskIcon.transform(\"S0.7,0.7\" + \"T\" + (element.x + 2) + \",\" + (element.y + 2));\n    return userTaskIcon;\n}\n"
  },
  {
    "path": "flowable-ui-web/modeler/display-cmmn/displaymodel.css",
    "content": "div[class*='ui-tooltip-flowable-'] {\n    background-color: #ffffff;\n    border-color: #c5c5c5;\n    color: #4a4a4a;\n    font-family: Verdana;\n    font-size: 12px;\n}\n\ndiv[class*='ui-tooltip-flowable-'] .qtip-content {\n  color: #4a4a4a;\n  background-color: #ffffff;\n  font-family: Verdana;\n  font-size: 12px;\n}\n\n.ui-tooltip-flowable-cmmn .qtip-titlebar {\n  color: #FFFFFF;\n  font-size: 12px;\n  background: #2B414F;\n}\n\n.ui-tooltip-flowable-cmmn .qtip-tip {\n  background-color: #2B414F;\n}\n"
  },
  {
    "path": "flowable-ui-web/modeler/display-cmmn/displaymodel.html",
    "content": "<html>  \n    <head>\n\n        <link type=\"text/css\" rel=\"stylesheet\" href=\"display/jquery.qtip.min.css\" />\n        <link type=\"text/css\" rel=\"stylesheet\" href=\"display-cmmn/displaymodel.css\" />\n\n        <script type=\"text/javascript\" src=\"display/jquery.qtip.min.js\"></script>\n        <script type=\"text/javascript\" src=\"display/raphael.min.js\"></script>\n        <script type=\"text/javascript\" src=\"display-cmmn/cmmn-draw.js\"></script>\n        <script type=\"text/javascript\" src=\"display-cmmn/cmmn-icons.js\"></script>\n        <script type=\"text/javascript\" src=\"display/Polyline.js\"></script>\n        <script type=\"text/javascript\" src=\"display-cmmn/displaymodel.js\"></script>\n\n    </head>\n</html>"
  },
  {
    "path": "flowable-ui-web/modeler/display-cmmn/displaymodel.js",
    "content": "/* 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 */\nvar NORMAL_STROKE = 1;\nvar ASSOCIATION_STROKE = 2;\nvar TASK_STROKE = 1;\nvar TASK_HIGHLIGHT_STROKE = 2;\n\nvar TEXT_COLOR= \"#373e48\";\nvar CURRENT_COLOR= \"#017501\";\nvar HOVER_COLOR= \"#666666\";\nvar ACTIVITY_STROKE_COLOR = \"#bbbbbb\";\nvar ACTIVITY_FILL_COLOR = \"#f9f9f9\";\nvar WHITE_FILL_COLOR = \"#ffffff\";\nvar MAIN_STROKE_COLOR = \"#585858\";\n\nvar TEXT_PADDING = 3;\nvar ARROW_WIDTH = 4;\nvar MARKER_WIDTH = 12;\n\nvar TASK_FONT = {font: \"11px Arial\", opacity: 1, fill: Raphael.rgb(0, 0, 0)};\n\n// icons\nvar ICON_SIZE = 16;\nvar ICON_PADDING = 4;\n\nvar INITIAL_CANVAS_WIDTH;\nvar INITIAL_CANVAS_HEIGHT;\n\nvar paper;\nvar viewBox;\nvar viewBoxWidth;\nvar viewBoxHeight;\n\nvar canvasWidth;\nvar canvasHeight;\n\nvar modelDiv = jQuery('#cmmnModel');\nvar modelId = modelDiv.attr('data-model-id');\nvar historyModelId = modelDiv.attr('data-history-id');\nvar caseDefinitionId = modelDiv.attr('data-case-definition-id');\nvar modelType = modelDiv.attr('data-model-type');\n\nvar elementsAdded = new Array();\nvar elementsRemoved = new Array();\n\nfunction _showTip(htmlNode, element)\n{\n    // Default tooltip, no custom tool tip set\n    if (documentation === undefined) {\n        var documentation = \"\";\n        if (element.name && element.name.length > 0) {\n            documentation += \"<b>Name</b>: <i>\" + element.name + \"</i><br/><br/>\";\n        }\n\n        if (element.properties) {\n            for (var i = 0; i < element.properties.length; i++) {\n                var propName = element.properties[i].name;\n                if (element.properties[i].type && element.properties[i].type === 'list') {\n                    documentation += '<b>' + propName + '</b>:<br/>';\n                    for (var j = 0; j < element.properties[i].value.length; j++) {\n                        documentation += '<i>' + element.properties[i].value[j] + '</i><br/>';\n                    }\n                }\n                else {\n                    documentation += '<b>' + propName + '</b>: <i>' + element.properties[i].value + '</i><br/>';\n                }\n            }\n        }\n    }\n\n    var text = element.type + \" \";\n    if (element.name && element.name.length > 0)\n    {\n        text += element.name;\n    }\n    else\n    {\n        text += element.id;\n    }\n\n    htmlNode.qtip({\n        content: {\n            text: documentation,\n            title: {\n                text: text\n            }\n        },\n        position: {\n            my: 'top left',\n            at: 'bottom center',\n            viewport: jQuery('#cmmnModel')\n        },\n        hide: {\n            fixed: true, delay: 500,\n            event: 'click mouseleave'\n        },\n        style: {\n            classes: 'ui-tooltip-flowable-cmmn'\n        }\n    });\n}\n\nfunction _addHoverLogic(element, type, defaultColor)\n{\n    var strokeColor = _cmmnGetColor(element, defaultColor);\n    var topBodyRect = null;\n    if (type === \"rect\")\n    {\n        topBodyRect = paper.rect(element.x, element.y, element.width, element.height);\n    }\n    else if (type === \"circle\")\n    {\n        var x = element.x + (element.width / 2);\n        var y = element.y + (element.height / 2);\n        topBodyRect = paper.circle(x, y, 15);\n    }\n    else if (type === \"rhombus\")\n    {\n        topBodyRect = paper.path(\"M\" + element.x + \" \" + (element.y + (element.height / 2)) +\n            \"L\" + (element.x + (element.width / 2)) + \" \" + (element.y + element.height) +\n            \"L\" + (element.x + element.width) + \" \" + (element.y + (element.height / 2)) +\n            \"L\" + (element.x + (element.width / 2)) + \" \" + element.y + \"z\"\n        );\n    }\n\n    var opacity = 0;\n    var fillColor = \"#ffffff\";\n    if (jQuery.inArray(element.id, elementsAdded) >= 0)\n    {\n        opacity = 0.2;\n        fillColor = \"green\";\n    }\n\n    if (jQuery.inArray(element.id, elementsRemoved) >= 0)\n    {\n        opacity = 0.2;\n        fillColor = \"red\";\n    }\n\n    topBodyRect.attr({\n        \"opacity\": opacity,\n        \"stroke\" : \"none\",\n        \"fill\" : fillColor\n    });\n    _showTip(jQuery(topBodyRect.node), element);\n\n    topBodyRect.mouseover(function() {\n        paper.getById(element.id).attr({\"stroke\":HOVER_COLOR});\n    });\n\n    topBodyRect.mouseout(function() {\n        paper.getById(element.id).attr({\"stroke\":strokeColor});\n    });\n}\n\nfunction _zoom(zoomIn)\n{\n    var tmpCanvasWidth, tmpCanvasHeight;\n    if (zoomIn)\n    {\n        tmpCanvasWidth = canvasWidth * (1.0/0.90);\n        tmpCanvasHeight = canvasHeight * (1.0/0.90);\n    }\n    else\n    {\n        tmpCanvasWidth = canvasWidth * (1.0/1.10);\n        tmpCanvasHeight = canvasHeight * (1.0/1.10);\n    }\n\n    if (tmpCanvasWidth != canvasWidth || tmpCanvasHeight != canvasHeight)\n    {\n        canvasWidth = tmpCanvasWidth;\n        canvasHeight = tmpCanvasHeight;\n        paper.setSize(canvasWidth, canvasHeight);\n    }\n}\n\nvar modelUrl;\n\nif (modelType == 'runtime') {\n\tif (historyModelId) {\n    \tmodelUrl = FLOWABLE.APP_URL.getCaseInstancesHistoryModelJsonUrl(historyModelId);\n\t} else {\n    \tmodelUrl = FLOWABLE.APP_URL.getCaseInstancesModelJsonUrl(modelId);\n\t}\n} else if (modelType == 'design') {\n\tif (historyModelId) {\n    \tmodelUrl = FLOWABLE.APP_URL.getModelHistoryModelJsonUrl(modelId, historyModelId);\n\t} else {\n    \tmodelUrl = FLOWABLE.APP_URL.getModelModelJsonUrl(modelId);\n\t}\n} else if (modelType == 'case-definition') {\n    modelUrl = FLOWABLE.APP_URL.getCaseDefinitionModelJsonUrl(caseDefinitionId);\n}\n\nvar request = jQuery.ajax({\n    type: 'get',\n    url: modelUrl + '?nocaching=' + new Date().getTime()\n});\n\nrequest.success(function(data, textStatus, jqXHR) {\n\n    if ((!data.elements || data.elements.length == 0) && (!data.pools || data.pools.length == 0)) return;\n\n    INITIAL_CANVAS_WIDTH = data.diagramWidth;\n    \n    if (modelType == 'design') {\n    \tINITIAL_CANVAS_WIDTH += 20;\n    } else {\n        INITIAL_CANVAS_WIDTH += 30;\n    }\n    \n    INITIAL_CANVAS_HEIGHT = data.diagramHeight + 50;\n    canvasWidth = INITIAL_CANVAS_WIDTH;\n    canvasHeight = INITIAL_CANVAS_HEIGHT;\n    viewBoxWidth = INITIAL_CANVAS_WIDTH;\n    viewBoxHeight = INITIAL_CANVAS_HEIGHT;\n    \n    if (modelType == 'design') {\n    \tvar headerBarHeight = 170;\n    \tvar offsetY = 0;\n    \tif (jQuery(window).height() > (canvasHeight + headerBarHeight))\n    \t{\n        \toffsetY = (jQuery(window).height() - headerBarHeight - canvasHeight) / 2;\n    \t}\n\n    \tif (offsetY > 50) {\n        \toffsetY = 50;\n    \t}\n\n    \tjQuery('#cmmnModel').css('marginTop', offsetY);\n    }\n\n    jQuery('#cmmnModel').width(INITIAL_CANVAS_WIDTH);\n    jQuery('#cmmnModel').height(INITIAL_CANVAS_HEIGHT);\n    paper = Raphael(document.getElementById('cmmnModel'), canvasWidth, canvasHeight);\n    paper.setViewBox(0, 0, viewBoxWidth, viewBoxHeight, false);\n    paper.renderfix();\n\n    var modelElements = data.elements;\n    for (var i = 0; i < modelElements.length; i++)\n    {\n        var element = modelElements[i];\n        //try {\n        var drawFunction = eval(\"_draw\" + element.type);\n        drawFunction(element);\n        //} catch(err) {console.log(err);}\n    }\n\n    if (data.flows)\n    {\n        for (var i = 0; i < data.flows.length; i++)\n        {\n            var flow = data.flows[i];\n            _drawAssociation(flow);\n        }\n    }\n});\n\nrequest.error(function(jqXHR, textStatus, errorThrown) {\n    alert(\"error\");\n});\n"
  },
  {
    "path": "flowable-ui-web/modeler/editor-app/configuration/flowable-header-custom.js",
    "content": "/* 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'use strict';\n\nFLOWABLE.HEADER_CONFIG.showAppTitle = false;\nFLOWABLE.HEADER_CONFIG.showHeaderMenu = false;\nFLOWABLE.HEADER_CONFIG.showMainNavigation = false;\nFLOWABLE.HEADER_CONFIG.showPageHeader = false;"
  },
  {
    "path": "flowable-ui-web/modeler/editor-app/configuration/flowable-toolbar-custom-actions.js",
    "content": "/* 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// Create custom functions for the FLOWABLE-editor\nFLOWABLE.TOOLBAR.ACTIONS.closeEditor =  function(services) {\n    if (services.editorManager && services.editorManager.getStencilData()) {\n        var stencilNameSpace = services.editorManager.getStencilData().namespace;\n        if (stencilNameSpace !== undefined && stencilNameSpace !== null && stencilNameSpace.indexOf('cmmn1.1') !== -1) {\n            services.$location.path(\"/casemodels\");\n            return;\n        }\n    }\n\tservices.$location.path(\"/processes\");\n};\n\nFLOWABLE.TOOLBAR.ACTIONS.navigateToProcess = function(processId) {\n    var navigateEvent = {\n        type: FLOWABLE.eventBus.EVENT_TYPE_NAVIGATE_TO_PROCESS,\n        processId: processId\n    };\n    FLOWABLE.eventBus.dispatch(FLOWABLE.eventBus.EVENT_TYPE_NAVIGATE_TO_PROCESS, navigateEvent);\n},\n\n// Add custom buttons \nFLOWABLE.TOOLBAR_CONFIG.secondaryItems.push( \n\t{\n        \"type\" : \"button\",\n        \"title\" : \"Close\",\n        \"cssClass\" : \"glyphicon glyphicon-remove\",\n        \"action\" : \"FLOWABLE.TOOLBAR.ACTIONS.closeEditor\"\n    }\n);\n\n\n\n\n"
  },
  {
    "path": "flowable-ui-web/modeler/editor-app/configuration/properties/assignment-display-template.html",
    "content": "\n<span ng-if=\"property.value.assignment.type != 'idm' && property.value.assignment.assignee\">{{'PROPERTY.ASSIGNMENT.ASSIGNEE_DISPLAY' | translate:property.value.assignment }} </span>\n<span ng-if=\"property.value.assignment.type != 'idm' && property.value.assignment.candidateUsers.length > 0\">{{'PROPERTY.ASSIGNMENT.CANDIDATE_USERS_DISPLAY' | translate:property.value.assignment.candidateUsers}} </span>\n<span ng-if=\"property.value.assignment.type != 'idm' && property.value.assignment.candidateGroups.length > 0\">{{'PROPERTY.ASSIGNMENT.CANDIDATE_GROUPS_DISPLAY' | translate:property.value.assignment.candidateGroups}} </span>\n<span ng-if=\"property.value.assignment.type == 'idm' && property.value.assignment.idm.assignee && property.value.assignment.idm.assignee.id\">{{'PROPERTY.ASSIGNMENT.USER_IDM_DISPLAY' | translate:property.value.assignment.idm.assignee }} </span>\n<span ng-if=\"property.value.assignment.type == 'idm' && property.value.assignment.idm.assignee && !property.value.assignment.idm.assignee.id\">{{'PROPERTY.ASSIGNMENT.USER_IDM_EMAIL_DISPLAY' | translate:property.value.assignment.idm.assignee }} </span>\n<span ng-if=\"property.value.assignment.type == 'idm' && property.value.assignment.idm.assigneeField && property.value.assignment.idm.assigneeField.id\">{{'PROPERTY.ASSIGNMENT.USER_IDM_FIELD_DISPLAY' | translate:property.value.assignment.idm.assigneeField }} </span>\n<span ng-if=\"property.value.assignment.type == 'idm' && property.value.assignment.idm.candidateUsers && property.value.assignment.idm.candidateUsers.length > 0 && (!property.value.assignment.idm.candidateUserFields || property.value.assignment.idm.candidateUserFields.length === 0)\">{{'PROPERTY.ASSIGNMENT.CANDIDATE_USERS_DISPLAY' | translate:property.value.assignment.idm.candidateUsers}} </span>\n<span ng-if=\"property.value.assignment.type == 'idm' && property.value.assignment.idm.candidateGroups && property.value.assignment.idm.candidateGroups.length > 0 && (!property.value.assignment.idm.candidateGroupFields || property.value.assignment.idm.candidateGroupFields.length === 0)\">{{'PROPERTY.ASSIGNMENT.CANDIDATE_GROUPS_DISPLAY' | translate:property.value.assignment.idm.candidateGroups}} </span>\n<span ng-if=\"property.value.assignment.type == 'idm' && property.value.assignment.idm.candidateUserFields && property.value.assignment.idm.candidateUserFields.length > 0 && (!property.value.assignment.idm.candidateUsers || property.value.assignment.idm.candidateUsers.length === 0)\">{{'PROPERTY.ASSIGNMENT.CANDIDATE_USERS_DISPLAY' | translate:property.value.assignment.idm.candidateUserFields}} </span>\n<span ng-if=\"property.value.assignment.type == 'idm' && property.value.assignment.idm.candidateGroupFields && property.value.assignment.idm.candidateGroupFields.length > 0 && (!property.value.assignment.idm.candidateGroups || property.value.assignment.idm.candidateGroups.length === 0)\">{{'PROPERTY.ASSIGNMENT.CANDIDATE_GROUPS_DISPLAY' | translate:property.value.assignment.idm.candidateGroupFields}} </span>\n<span ng-if=\"property.value.assignment.type == 'idm' && property.value.assignment.idm.candidateUserFields && property.value.assignment.idm.candidateUserFields.length > 0 && property.value.assignment.idm.candidateUsers && property.value.assignment.idm.candidateUsers.length > 0\">{{'PROPERTY.ASSIGNMENT.CANDIDATE_USERS_DISPLAY' | translate:property.value.assignment.idm.candidateUserFields.concat(property.value.assignment.idm.candidateUsers)}} </span>\n<span ng-if=\"property.value.assignment.type == 'idm' && property.value.assignment.idm.candidateGroupFields && property.value.assignment.idm.candidateGroupFields.length > 0 && property.value.assignment.idm.candidateGroups && property.value.assignment.idm.candidateGroups.length > 0\">{{'PROPERTY.ASSIGNMENT.CANDIDATE_GROUPS_DISPLAY' | translate:property.value.assignment.idm.candidateGroupFields.concat(property.value.assignment.idm.candidateGroups)}} </span>\n<span ng-if=\"property.value.assignment.type != 'idm' && !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>\n<span ng-if=\"property.value.assignment.type == 'idm' && !property.value.assignment.idm.assignee && !property.value.assignment.idm.assigneeField && (!property.value.assignment.idm.candidateUsers || property.value.assignment.idm.candidateUsers.length == 0) && (!property.value.assignment.idm.candidateUserFields || property.value.assignment.idm.candidateUserFields.length == 0) && (!property.value.assignment.idm.candidateGroups || property.value.assignment.idm.candidateGroups.length == 0) && (!property.value.assignment.idm.candidateGroupFields || property.value.assignment.idm.candidateGroupFields.length == 0)\" translate>PROPERTY.ASSIGNMENT.IDM_EMPTY</span>"
  },
  {
    "path": "flowable-ui-web/modeler/editor-app/configuration/properties/assignment-popup.html",
    "content": "<div class=\"modal\" ng-controller=\"FlowableAssignmentPopupCtrl\">\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                <div class=\"detail-group clearfix\">\n\n                    <div class=\"form-group clearfix\">\n                        <div class=\"col-xs-12\">\n                            <label class=\"col-xs-4\">{{'PROPERTY.ASSIGNMENT.TYPE' | translate}}</label>\n\n                            <div class=\"col-xs-8\">\n                                <div class=\"btn-group btn-group-justified\">\n                                    <div class=\"btn-group\">\n                                        <button type=\"button\" class=\"btn btn-default\" ng-click=\"popup.assignmentObject.type = 'idm'\"\n                                                ng-model=\"popup.assignmentObject.type\" ng-class=\"{'active' : popup.assignmentObject.type == 'idm'}\">\n                                            {{'PROPERTY.ASSIGNMENT.TYPE.IDENTITYSTORE' | translate}}\n                                        </button>\n                                    </div>\n                                    <div class=\"btn-group\">\n                                        <button type=\"button\" class=\"btn btn-default\" ng-click=\"popup.assignmentObject.type = 'static'\"\n                                                ng-model=\"popup.assignmentObject.type\" ng-class=\"{'active' : popup.assignmentObject.type != 'idm'}\">\n                                            {{'PROPERTY.ASSIGNMENT.TYPE.STATIC' | translate}}\n                                        </button>\n                                    </div>\n                                </div>\n                            </div>\n                        </div>\n                    </div>\n\n                    <div class=\"form-group clearfix\" ng-show=\"popup.assignmentObject.type != 'idm'\">\n                        <div class=\"col-xs-12\">\n                            <label>{{'PROPERTY.ASSIGNMENT.ASSIGNEE' | translate}}</label>\n                        </div>\n                        <div class=\"col-xs-12\">\n                            <input type=\"text\" id=\"assigneeField\" class=\"form-control\" ng-model=\"popup.assignmentObject.static.assignee\"\n                                   placeholder=\"{{'PROPERTY.ASSIGNMENT.ASSIGNEE_PLACEHOLDER' | translate}}\"/>\n                        </div>\n                    </div>\n\n                    <div class=\"form-group clearfix\" ng-show=\"popup.assignmentObject.type != 'idm'\">\n                        <div class=\"col-xs-12\">\n                            <label>{{'PROPERTY.ASSIGNMENT.CANDIDATE_USERS' | translate}}</label>\n                        </div>\n                        <div class=\"col-xs-12\" ng-repeat=\"candidateUser in popup.assignmentObject.static.candidateUsers\">\n                            <input id=\"userField\" class=\"form-control\" type=\"text\" ng-model=\"candidateUser.value\"/>\n                            <i ng-if=\"popup.assignmentObject.static.candidateUsers.length >1\" class=\"glyphicon glyphicon-minus clickable-property\"\n                               ng-click=\"removeCandidateUserValue($index)\"></i>\n                            <i ng-if=\"$index == (popup.assignmentObject.static.candidateUsers.length - 1)\" class=\"glyphicon glyphicon-plus clickable-property\"\n                               ng-click=\"addCandidateUserValue($index)\"></i>\n                        </div>\n                    </div>\n\n                    <div class=\"form-group clearfix\" ng-show=\"popup.assignmentObject.type != 'idm'\">\n                        <div class=\"col-xs-12\">\n                            <label>{{'PROPERTY.ASSIGNMENT.CANDIDATE_GROUPS' | translate}}</label>\n                        </div>\n                        <div class=\"col-xs-12\" ng-repeat=\"candidateGroup in popup.assignmentObject.static.candidateGroups\">\n                            <input id=\"groupField\" class=\"form-control\" type=\"text\" ng-model=\"candidateGroup.value\"/>\n                            <i ng-if=\"popup.assignmentObject.static.candidateGroups.length >1\" class=\"glyphicon glyphicon-minus clickable-property\"\n                               ng-click=\"removeCandidateGroupValue($index)\"></i>\n                            <i ng-if=\"$index == (popup.assignmentObject.static.candidateGroups.length - 1)\" class=\"glyphicon glyphicon-plus clickable-property\"\n                               ng-click=\"addCandidateGroupValue($index)\"></i>\n                        </div>\n                    </div>\n\n                    <div class=\"form-group clearfix\" ng-show=\"popup.assignmentObject.type == 'idm'\">\n                        <div class=\"col-xs-12\">\n                            <div class=\"col-xs-4\">\n                                <label>{{'PROPERTY.ASSIGNMENT.IDM.TYPE' | translate}}</label>\n                            </div>\n                            <div class=\"col-xs-8\">\n                                <div class=\"btn-group span\">\n                                    <button class=\"selection\" ng-options=\"option as (option.title | translate) for option in assignmentOptions\"\n                                            bs-select ng-model=\"assignmentOption\" activiti-fix-dropdown-bug>\n                                    </button>\n                                </div>\n                            </div>\n                        </div>\n                    </div>\n\n                    <div class=\"form-group clearfix\" ng-show=\"popup.assignmentObject.type == 'idm' && assignmentOption.id == 'users'\">\n                        <div class=\"col-xs-12\">\n                            <div class=\"col-xs-4\">\n                                <label>{{'PROPERTY.ASSIGNMENT.CANDIDATE_USERS' | translate}}</label>\n                            </div>\n                            <div class=\"col-xs-8 clearfix\">\n                                <ul class=\"simple-list\"\n                                    ng-show=\"popup.assignmentObject.idm.candidateUsers.length || popup.assignmentObject.idm.candidateUserFields.length\">\n                                    <li ng-repeat=\"user in popup.assignmentObject.idm.candidateUsers\">\n                                        <i class=\"icon icon-user\"></i>\n                                        <span user-name=\"user\"></span>\n\n                                        <div class=\"actions\">\n                                            <a ng-click=\"removeCandidateUser(user)\"><i class=\"icon icon-remove\"></i></a>\n                                        </div>\n                                    </li>\n                                    <li ng-repeat=\"userField in popup.assignmentObject.idm.candidateUserFields\">\n                                        <i class=\"icon icon-user\"></i>\n                                        <span>{{userField.name}}</span>\n                                        <span class=\"field-type\"> - {{userFieldField.id}}</span>\n\n                                        <div class=\"actions\">\n                                            <a ng-click=\"removeCandidateUserField(userField)\"><i class=\"icon icon-remove\"></i></a>\n                                        </div>\n                                    </li>\n                                </ul>\n                                <div class=\"no-results\"\n                                     ng-if=\"(!popup.assignmentObject.idm.candidateUsers || !popup.assignmentObject.idm.candidateUsers.length) && (!popup.assignmentObject.idm.candidateUserFields || !popup.assignmentObject.idm.candidateUserFields.length)\">\n                                    {{'PROPERTY.ASSIGNMENT.IDM.NO_CANDIDATE_USERS' | translate}}\n                                </div>\n                            </div>\n                        </div>\n                    </div>\n\n                    <div class=\"form-group clearfix\" ng-show=\"popup.assignmentObject.type == 'idm' && assignmentOption.id == 'groups'\">\n                        <div class=\"col-xs-12\">\n                            <div class=\"col-xs-4\">\n                                <label>{{'PROPERTY.ASSIGNMENT.CANDIDATE_GROUPS' | translate}}</label>\n                            </div>\n                            <div class=\"col-xs-8 clearfix\">\n                                <ul class=\"simple-list\"\n                                    ng-show=\"popup.assignmentObject.idm.candidateGroups.length || popup.assignmentObject.idm.candidateGroupFields.length\">\n                                    <li ng-repeat=\"group in popup.assignmentObject.idm.candidateGroups\">\n                                        {{group.name}}\n                                        <div class=\"actions\">\n                                            <a ng-click=\"removeCandidateGroup(group)\"><i class=\"icon icon-remove\"></i></a>\n                                        </div>\n                                    </li>\n                                    <li ng-repeat=\"groupField in popup.assignmentObject.idm.candidateGroupFields\">\n                                        {{groupField.name}}\n                                        <div class=\"actions\">\n                                            <a ng-click=\"removeCandidateGroupField(groupField)\"><i class=\"icon icon-remove\"></i></a>\n                                        </div>\n                                    </li>\n                                </ul>\n                                <div class=\"no-results\"\n                                     ng-if=\"(!popup.assignmentObject.idm.candidateGroups || !popup.assignmentObject.idm.candidateGroups.length) && (!popup.assignmentObject.idm.candidateGroupFields || !popup.assignmentObject.idm.candidateGroupFields.length)\">\n                                    {{'PROPERTY.ASSIGNMENT.IDM.NO_CANDIDATE_GROUPS' | translate}}\n                                </div>\n                            </div>\n                        </div>\n                    </div>\n\n                    <div class=\"form-group clearfix\" ng-show=\"popup.assignmentObject.type == 'idm' && assignmentOption.id == 'user'\">\n                        <div class=\"col-xs-12\">\n                            <div class=\"col-xs-4\">\n                                <label>{{'PROPERTY.ASSIGNMENT.ASSIGNEE' | translate}}</label>\n                            </div>\n                            <div class=\"col-xs-8\">\n                                <label ng-if=\"!popup.assignmentObject.idm.assignee && !popup.assignmentObject.idm.assigneeField\">{{'PROPERTY.ASSIGNMENT.NONE' | translate}}</label>\n                                <ul class=\"simple-list\" ng-if=\"popup.assignmentObject.idm.assignee || popup.assignmentObject.idm.assigneeField\">\n                                    <li>\n                                        <i class=\"icon icon-user\"></i>\n                                        <span ng-if=\"popup.assignmentObject.idm.assignee\" user-name=\"popup.assignmentObject.idm.assignee\"></span>\n                                        <span ng-if=\"popup.assignmentObject.idm.assigneeField\">{{popup.assignmentObject.idm.assigneeField.name}}</span>\n                                        <span ng-if=\"popup.assignmentObject.idm.assigneeField\"\n                                              class=\"field-type\"> - {{popup.assignmentObject.idm.assigneeField.id}}</span>\n\n                                        <div class=\"actions\" ng-if=\"popup.assignmentObject.idm.assignee || popup.assignmentObject.idm.assigneeField\">\n                                            <a ng-click=\"removeAssignee()\"><i class=\"icon icon-remove\"></i></a>\n                                        </div>\n                                    </li>\n                                </ul>\n                            </div>\n                        </div>\n                    </div>\n\n                    <div class=\"form-group clearfix\"\n                         ng-if=\"popup.assignmentObject.type == 'idm' && (!popup.assignmentObject.assignmentSourceType || popup.assignmentObject.assignmentSourceType == 'search') && (assignmentOption.id == 'user' || assignmentOption.id == 'users')\">\n                        <div class=\"col-xs-12\">\n                            <div class=\"col-xs-4\">\n                                <label>{{'PROPERTY.ASSIGNMENT.SEARCH' | translate}}</label>\n                            </div>\n                            <div class=\"col-xs-8\">\n                                <input class=\"form-control\" type=\"text\" id=\"people-select-input\" placeholder=\"{{'PROPERTY.ASSIGNMENT.PLACEHOLDER-SEARCHUSER' | translate}}\" auto-focus custom-keys\n                                       up-pressed=\"previousUser()\" down-pressed=\"nextUser()\" enter-pressed=\"confirmUser()\" delayed-model=\"popup.filter\" delay=\"200\"/>\n                            </div>\n                        </div>\n                        <div class=\"col-xs-12\">\n                            <div class=\"col-xs-4\">\n                                <label></label>\n                            </div>\n                            <div class=\"col-xs-8\">\n                                <div class=\"subtle\" style=\"margin: 2px 0 2px 0\">\n                                    <span translate=\"PROPERTY.ASSIGNMENT.MATCHING\"></span>\n                                </div>\n                            </div>\n                        </div>\n                        <div class=\"col-xs-12\">\n                            <div class=\"col-xs-4\">\n                                <label></label>\n                            </div>\n                            <div class=\"col-xs-8\">\n                                <div class=\"inline-people-select\">\n                                    <ul class=\"simple-list\">\n                                        <li ng-click=\"confirmUser(user)\" ng-repeat=\"user in popup.userResults\" ng-class=\"{'active': $index == popup.selectedIndex}\">\n                                            <div user-picture=\"user\" user-index=\"$index\" user-name=\"user\"></div>\n                                        </li>\n                                    </ul>\n                                    <div class=\"nothing-to-see\" translate=\"GENERAL.MESSAGE.PEOPLE-NO-MATCHING-RESULTS\" ng-show=\"popup.userResults.length == 0\"></div>\n                                </div>\n                            </div>\n                        </div>\n                    </div>\n\n                    <div class=\"form-group clearfix\"\n                         ng-if=\"popup.assignmentObject.type == 'idm' && (!popup.assignmentObject.assignmentSourceType || popup.assignmentObject.assignmentSourceType == 'search') && assignmentOption.id == 'groups'\">\n                        <div class=\"col-xs-12\">\n                            <div class=\"col-xs-4\">\n                                <label>{{'PROPERTY.ASSIGNMENT.SEARCH' | translate}}</label>\n                            </div>\n                            <div class=\"col-xs-8\">\n                                <input class=\"form-control\" type=\"text\" id=\"people-select-input\" placeholder=\"{{'PROPERTY.ASSIGNMENT.PLACEHOLDER-SEARCHGROUP' | translate}}\" auto-focus custom-keys\n                                       up-pressed=\"previousGroup()\" down-pressed=\"nextGroup()\" enter-pressed=\"confirmGroup()\" delayed-model=\"popup.groupFilter\"\n                                       delay=\"200\"/>\n                            </div>\n                        </div>\n                        <div class=\"col-xs-12\">\n                            <div class=\"col-xs-4\">\n                                <label></label>\n                            </div>\n                            <div class=\"col-xs-8\">\n                                <div class=\"subtle\">\n                                    <span translate=\"PROPERTY.ASSIGNMENT.MATCHING\"></span>\n                                </div>\n                            </div>\n                        </div>\n                        <div class=\"col-xs-12\">\n                            <div class=\"col-xs-4\">\n                                <label></label>\n                            </div>\n                            <div class=\"col-xs-8\">\n                                <div class=\"inline-people-select\">\n                                    <ul class=\"simple-list\">\n                                        <li ng-click=\"confirmGroup(group);\" ng-repeat=\"group in popup.groupResults\"\n                                            ng-class=\"{'active': $index == popup.selectedGroupIndex}\">\n                                            {{group.name}}\n                                        </li>\n                                    </ul>\n                                    <div class=\"nothing-to-see\" translate=\"GENERAL.MESSAGE.GROUP-NO-MATCHING-RESULTS\" ng-show=\"popup.groupResults.length == 0\"></div>\n                                </div>\n                            </div>\n                        </div>\n                    </div>\n\n                    <div class=\"form-group clearfix\">\n                        <div class=\"col-xs-12\">\n                            <div class=\"col-xs-12\">\n                                <label>\n                                    <input type=\"checkbox\" ng-model=\"assignment.initiatorCanCompleteTask\">\n                                    &nbsp;{{'PROPERTY.ASSIGNMENT.INITIATOR-CAN-COMPLETE' | translate}}\n                                </label>\n                            </div>\n                        </div>\n                    </div>\n\n                </div>\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"
  },
  {
    "path": "flowable-ui-web/modeler/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=\"FlowableAssignmentCtrl\">\n</span>"
  },
  {
    "path": "flowable-ui-web/modeler/editor-app/configuration/properties/boolean-property-template.html",
    "content": "\n<div ng-controller=\"FlowableBooleanPropertyCtrl\">\n    <input type=\"checkbox\" ng-model=\"property.value\" ng-change=\"changeValue()\"/>\n</div>"
  },
  {
    "path": "flowable-ui-web/modeler/editor-app/configuration/properties/calledelementtype-property-write-template.html",
    "content": "\n<div ng-controller=\"FlowableCalledElementTypeCtrl\">\n    <select ng-model=\"property.value\" ng-change=\"calledElementTypeChanged ()\">\n    \t<option>key</option>\n    \t<option>id</option>\n    </select>\n</div>"
  },
  {
    "path": "flowable-ui-web/modeler/editor-app/configuration/properties/case-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.CASEREFERENCE.EMPTY</span>\n"
  },
  {
    "path": "flowable-ui-web/modeler/editor-app/configuration/properties/case-reference-popup.html",
    "content": "\n<div class=\"modal\" ng-controller=\"FlowableCaseReferencePopupCtrl\">\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>\n                    {{'PROPERTY.CASEREFERENCE.TITLE' | translate}}\n                    <span ng-show=\"selectedCase != null\"> - {{selectedCase.name}}</span>\n                    <span ng-show=\"selectedCase == null\"> - {{'PROPERTY.CASEREFERENCE.EMPTY' | translate}}</span>\n\n                </h2>\n            </div>\n            <div class=\"modal-body-with-overflow\">\n                <div class=\"detail-group clearfix\">\n                    <div class=\"col-xs-12\">\n                        <div class=\"alert alert-error\" ng-show=\"!state.loadingCases && state.caseError\" translate>PROPERTY.CASEREFERENCE.ERROR.FORM</div>\n                    </div>\n                </div>\n                <div class=\"detail-group clearfix\">\n                    <div class=\"col-xs-12 editor-item-picker\">\n                        <div ng-if=\"!state.loadingCases && !state.caseError\" class=\"col-xs-4 editor-item-picker-component\" ng-repeat=\"caseModel in caseModels\" ng-class=\"{'selected' : caseModel.id == selectedCase.id}\" ng-click=\"selectCase(caseModel, $event)\">\n                           <div class=\"controls\">\n                               <input type=\"checkbox\" value=\"option1\" ng-click=\"selectCase(caseModel, $event)\" ng-checked=\"caseModel.id == selectedCase.id\" />\n                           </div>\n                           <h4>{{caseModel.name}}</h4>\n                           <img ng-src=\"{{getModelThumbnailUrl(caseModel.id)}}\" />\n                         </div>\n                         <div ng-show=\"state.loadingCases\">\n                            <p class=\"loading\" translate>PROPERTY.CASEREFERENCE.CASE.LOADING</p>\n                         </div>\n                         <div ng-show=\"!state.loadingCases && caseModels.length == 0\">\n                            <p translate>PROPERTY.CASEREFERENCE.CASE.EMPTY</p>\n                         </div>\n                    </div>\n                </div>\n            </div>\n            <div class=\"modal-footer\">\n                <button ng-click=\"close()\" class=\"btn btn-primary\" translate>GENERAL.ACTION.CANCEL</button>\n            \t<button ng-disabled=\"!selectedCase || state.caseError\" ng-click=\"open()\" class=\"btn btn-primary\" translate>GENERAL.ACTION.OPEN</button>\n                <button ng-disabled=\"state.caseError\" ng-click=\"save()\" class=\"btn btn-primary\" translate>GENERAL.ACTION.SAVE</button>\n            </div>\n        </div>\n    </div>\n</div>\n"
  },
  {
    "path": "flowable-ui-web/modeler/editor-app/configuration/properties/case-reference-write-template.html",
    "content": "<span ng-controller=\"FlowableCaseReferenceCtrl\">\n</span>\n"
  },
  {
    "path": "flowable-ui-web/modeler/editor-app/configuration/properties/condition-expression-display-template.html",
    "content": "<span ng-if=\"property.value.expression.type != 'variables' && property.value.expression.staticValue\">{{property.value.expression.staticValue|limitTo:20}}</span>\n<span ng-if=\"property.value && !property.value.expression\">{{property.value|limitTo:20}}</span>\n<span ng-if=\"!property.value\">{{'PROPERTY.SEQUENCEFLOW.CONDITION.NO-CONDITION-DISPLAY' | translate}}</span>"
  },
  {
    "path": "flowable-ui-web/modeler/editor-app/configuration/properties/condition-expression-popup.html",
    "content": "<div class=\"modal\" ng-controller=\"FlowableConditionExpressionPopupCtrl\">\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 translate>PROPERTY.SEQUENCEFLOW.CONDITION.TITLE</h2>\n</div>\n<div class=\"modal-body\">\n\n    <div class=\"detail-group clearfix\">\n        \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=\"expression.staticValue\" style=\"width:70%; height:100%; max-width: 100%; max-height: 100%; min-height: 50px\"/>\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": "flowable-ui-web/modeler/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=\"FlowableConditionExpressionCtrl\">\n</span>"
  },
  {
    "path": "flowable-ui-web/modeler/editor-app/configuration/properties/data-properties-display-template.html",
    "content": "\n<span ng-if=\"property.value.items && property.value.items.length > 0\">{{'PROPERTY.DATAPROPERTIES.VALUES' | translate:property.value.items}}</span>\n<span ng-if=\"!property.value.items || property.value.items.length == 0\" translate>PROPERTY.DATAPROPERTIES.EMPTY</span>"
  },
  {
    "path": "flowable-ui-web/modeler/editor-app/configuration/properties/data-properties-popup.html",
    "content": "\n<div class=\"modal\" ng-controller=\"FlowableDataPropertiesPopupCtrl\">\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.title | translate}}\"</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\" ui-grid=\"gridOptions\" ui-grid-selection></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=\"selectedProperty\">\n            \n                            <div class=\"form-group\">\n            \t\t\t   \t\t<label for=\"idField\">{{'PROPERTY.DATAPROPERTIES.ID' | translate}}</label>\n            \t\t\t   \t\t<input id=\"idField\" class=\"form-control\" type=\"text\" ng-model=\"selectedProperty.dataproperty_id\" placeholder=\"{{'PROPERTY.DATAPROPERTIES.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.DATAPROPERTIES.NAME' | translate}}</label>\n            \t\t\t   \t\t<input id=\"nameField\" class=\"form-control\" type=\"text\" ng-model=\"selectedProperty.dataproperty_name\" placeholder=\"{{'PROPERTY.DATAPROPERTIES.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.DATAPROPERTIES.TYPE' | translate}}</label>\n            \t\t\t   \t\t<select id=\"typeField\" class=\"form-control\" ng-model=\"selectedProperty.dataproperty_type\" ng-change=\"propertyTypeChanged()\">\n                                    <option selected>string</option>\n                                    <option>boolean</option>\n                                    <option>datetime</option>\n                                    <option>double</option>\n                                    <option>int</option>\n                                    <option>long</option>\n                                </select>\n            \t\t\t\t</div>\n                            <div class=\"form-group\">\n            \t\t\t   \t\t<label for=\"valueField\">{{'PROPERTY.DATAPROPERTIES.VALUE' | translate}}</label>\n            \t\t\t   \t\t<input id=\"valueField\" class=\"form-control\" type=\"text\" ng-model=\"selectedProperty.dataproperty_value\" placeholder=\"{{'PROPERTY.DATAPROPERTIES.VALUE.PLACEHOLDER' | translate }}\" />\n            \t\t\t\t</div>\n                        </div>\n                        <div ng-show=\"!selectedProperty\" class=\"muted no-property-selected\" translate>PROPERTY.DATAPROPERTIES.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": "flowable-ui-web/modeler/editor-app/configuration/properties/data-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=\"FlowableDataPropertiesCtrl\">\n</span>"
  },
  {
    "path": "flowable-ui-web/modeler/editor-app/configuration/properties/decisiontable-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.DECISIONTABLEREFERENCE.EMPTY</span>\n"
  },
  {
    "path": "flowable-ui-web/modeler/editor-app/configuration/properties/decisiontable-reference-popup.html",
    "content": "\n<div class=\"modal\" ng-controller=\"FlowableDecisionTableReferencePopupCtrl\">\n    <div class=\"modal-dialog modal-wide\">\n        <div class=\"modal-content\">\n            <div class=\"modal-header\" ng-if=\"popup.state == 'decisionTableReference'\">\n                <button type=\"button\" class=\"close\" data-dismiss=\"modal\" aria-hidden=\"true\" ng-click=\"close()\">&times;</button>\n                <h2>\n                    {{'PROPERTY.DECISIONTABLEREFERENCE.TITLE' | translate}}\n                    <span ng-show=\"selectedDecisionTable != null\"> - {{selectedDecisionTable.name}}</span>\n                    <span ng-show=\"selectedDecisionTable == null\"> - {{'PROPERTY.DECISIONTABLEREFERENCE.EMPTY' | translate}}</span>\n\n                </h2>\n            </div>\n            <div class=\"modal-header\" ng-if=\"popup.state == 'newDecisionTable'\"><h2>{{'DECISION-TABLE.POPUP.CREATE-TITLE' | translate}}</h2></div>\n            <div class=\"modal-body-with-overflow\" ng-if=\"popup.state == 'decisionTableReference'\">\n                <div class=\"detail-group clearfix\">\n                    <div class=\"col-xs-12\">\n                        <div class=\"alert alert-error\" ng-show=\"!state.loadingDecisionTables && state.decisionTableError\" translate>PROPERTY.DECISIONTABLEREFERENCE.ERROR.FORM</div>\n                    </div>\n                </div>\n                <div class=\"detail-group clearfix\">\n                    <div class=\"col-xs-12 editor-item-picker\">\n                        <div ng-if=\"!state.loadingDecisionTables && !state.decisionTableError\" class=\"col-xs-4 editor-item-picker-component\" ng-repeat=\"decisionTable in decisionTables\" ng-class=\"{'selected' : decisionTable.decisionTableId == selectedDecisionTable.decisionTableId}\" ng-click=\"selectDecisionTable(decisionTable, $event)\">\n                           <div class=\"controls\">\n                               <input type=\"checkbox\" value=\"option1\" ng-click=\"selectDecisionTable(decisionTable, $event)\" ng-checked=\"decisionTable.id == selectedDecisionTable.id\" />\n                           </div>\n                           <h4>{{decisionTable.name}}</h4>\n                           <img ng-src=\"{{getModelThumbnailUrl(decisionTable.id)}}\" />\n                         </div>\n                         <div ng-show=\"state.loadingDecisionTables\">\n                            <p class=\"loading\" translate>PROPERTY.DECISIONTABLEREFERENCE.DECISIONTABLE.LOADING</p>\n                         </div>\n                         <div ng-show=\"!state.loadingDecisionTables && decisionTables.length == 0\">\n                            <p translate>PROPERTY.DECISIONTABLEREFERENCE.DECISIONTABLE.EMPTY</p>\n                         </div>\n                    </div>\n                </div>\n            </div>\n            <div class=\"modal-body\" ng-if=\"popup.state == 'newDecisionTable'\">\n                <p>{{'DECISION-TABLE.POPUP.CREATE-DESCRIPTION' | translate}}</p>\n                <div ng-if=\"model.errorMessage && model.errorMessage.length > 0\" class=\"alert error\" style=\"font-size: 14px; margin-top:20px\">\n                  <div class=\"popup-error\" style=\"font-size: 14px\">\n                    <span class=\"glyphicon glyphicon-remove-circle\"></span>\n                    <span>{{model.errorMessage}}</span>\n                  </div>\n                </div>\n                <div class=\"form-group\">\n                    <label for=\"newDecisionTableName\">{{'DECISION-TABLE.NAME' | translate}}</label>\n                    <input ng-disabled=\"model.loading\" type=\"text\" class=\"form-control\"\n                           id=\"newDecisionTableName\" ng-model=\"model.decisionTable.name\" custom-keys enter-pressed=\"ok()\" auto-focus editor-input-check>\n                </div>\n                <div class=\"form-group\">\n                    <label for=\"newDecisionTableKey\">{{'DECISION-TABLE.KEY' | translate}}</label>\n                    <input ng-disabled=\"model.loading\" type=\"text\" class=\"form-control\"\n                           id=\"newDecisionTableKey\" ng-model=\"model.decisionTable.key\" editor-input-check>\n                </div>\n                <div class=\"form-group\">\n                    <label for=\"newDecisionTableDescription\">{{'DECISION-TABLE.DESCRIPTION' | translate}}</label>\n                    <textarea ng-disabled=\"model.loading\" class=\"form-control\" id=\"newDecisionTableDescription\" rows=\"5\" ng-model=\"model.decisionTable.description\"></textarea>\n                </div>\n            </div>\n            <div class=\"modal-footer\" ng-if=\"popup.state == 'decisionTableReference'\">\n                <button ng-click=\"cancel()\" class=\"btn btn-primary\" translate>GENERAL.ACTION.CANCEL</button>\n            \t<button ng-disabled=\"state.decisionTableError\" ng-click=\"newDecisionTable()\" class=\"btn btn-primary\" translate>GENERAL.ACTION.NEW-DECISION-TABLE</button>\n            \t<button ng-disabled=\"!selectedDecisionTable || state.decisionTableError\" ng-click=\"open()\" class=\"btn btn-primary\" translate>GENERAL.ACTION.OPEN</button>\n                <button ng-disabled=\"state.decisionTableError\" ng-click=\"save()\" class=\"btn btn-primary\" translate>GENERAL.ACTION.SAVE</button>\n            </div>\n            <div class=\"modal-footer\" ng-if=\"popup.state == 'newDecisionTable'\">\n                <button ng-click=\"cancel()\" class=\"btn btn-primary\" translate>GENERAL.ACTION.CANCEL</button>\n                <button ng-disabled=\"state.decisionTableError || model.decisionTable.name.length == 0 || model.decisionTable.key.length == 0\" ng-click=\"createDecisionTable()\" class=\"btn btn-primary\" translate>GENERAL.ACTION.CREATE-DECISION-TABLE</button>\n            </div>\n        </div>\n    </div>\n</div>\n"
  },
  {
    "path": "flowable-ui-web/modeler/editor-app/configuration/properties/decisiontable-reference-write-template.html",
    "content": "<span ng-controller=\"FlowableDecisionTableReferenceCtrl\">\n</span>\n"
  },
  {
    "path": "flowable-ui-web/modeler/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": "flowable-ui-web/modeler/editor-app/configuration/properties/duedate-display-template.html",
    "content": "\n<span ng-if=\"property.value && property.value.duedate && property.value.duedate.field || property.value.duedate.field.taskDueDateField\" translate>PROPERTY.DUEDATE.DEFINED</span>\n<span ng-if=\"property.value && property.value.duedate && property.value.duedate.fixed\" translate>PROPERTY.DUEDATE.DEFINED</span>\n<span ng-if=\"property.value && property.value.duedateExpression\">{{property.value.duedateExpression}}</span>\n<span ng-if=\"property.value && property.value.length > 0 && !property.value.duedate && !property.value.duedateExpression\">{{property.value}}</span>\n<span ng-if=\"!property.value || property.value.length === 0\" translate>PROPERTY.DUEDATE.EMPTY</span>"
  },
  {
    "path": "flowable-ui-web/modeler/editor-app/configuration/properties/duedate-popup.html",
    "content": "\n<div class=\"modal\" ng-controller=\"BpmnEditorDueDatePopupCtrl\">\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.DUEDATE.TITLE</h2>\n</div>\n<div class=\"modal-body\">\n    \n    <div class=\"clearfix first\">\n        <div class=\"col-xs-12\">\n            <div class=\"col-xs-12\">\n                <div class=\"btn-group span\">\n                    <button class=\"selection\" data-toggle=\"dropdown\" ng-options=\"option.id as (option.title | translate) for option in taskDueDateOptions\"\n                        bs-select ng-model=\"popup.selectedDueDateOption\" ng-change=\"dueDateOptionChanged()\" activiti-fix-dropdown-bug>\n                       <i class=\"icon icon-caret-down\"></i>\n                   </button>\n                </div>\n            </div>\n        </div>\n    </div>\n    \n    <div class=\"clearfix first\" ng-if=\"popup.selectedDueDateOption === 'expression'\" style=\"padding-top: 10px\">\n        <div class=\"col-xs-12\">\n            <div class=\"col-xs-4\">\n                <label>{{'PROPERTY.DUEDATE.EXPRESSION-LABEL' | translate}}: </label>\n            </div>\n            <div class=\"col-xs-8\">\n                <input id=\"expression\" type=\"text\" class=\"form-control\" ng-model=\"popup.duedateExpression\">\n            </div>\n        </div>\n    </div>\n    \n    <div class=\"clearfix first\" ng-if=\"popup.selectedDueDateOption === 'field'\" style=\"padding-top: 10px\">\n        <div class=\"col-xs-12\">\n            <div class=\"col-xs-4\">\n                <label>{{'PROCESS-BUILDER.FIELD.TIMER.DATE-FIELD' | translate}}: </label>\n            </div>\n            <div class=\"col-xs-8\">\n                <div field-select=\"popup.duedate.field.taskDueDateField\" editor-type=\"bpmn\" all-steps=\"allSteps\" step-id=\"selectedShape.resourceId\" field-type-filter=\"['date']\"></div>\n            </div>\n        </div>\n    </div>\n    \n    <div class=\"clearfix first\" ng-if=\"popup.selectedDueDateOption === 'field'\" style=\"padding-top: 10px\">\n        <div class=\"col-xs-12\">\n            <div class=\"col-xs-4\">\n                <label>{{'PROCESS-BUILDER.FIELD.DUEDATE.CALCULATION-TYPE' | translate}}: </label>\n            </div>\n            <div class=\"col-xs-8\">\n                <div class=\"btn-group btn-group-justified\">\n                  <div class=\"btn-group\">\n                    <button type=\"button\" class=\"btn btn-default\" ng-click=\"setAddCalculationType()\" ng-model=\"popup.duedate.field.taskDueDateCalculationType\" ng-class=\"{'active' : (!popup.duedate.field.taskDueDateCalculationType || popup.duedate.field.taskDueDateCalculationType == 'add')}\">{{'PROCESS-BUILDER.FIELD.DUEDATE.CALCULATION-OPTIONS.ADD' | translate}}</button>\n                  </div>\n                  <div class=\"btn-group\">\n                    <button type=\"button\" class=\"btn btn-default\" ng-click=\"setSubtractCalculationType()\" ng-model=\"popup.duedate.field.taskDueDateCalculationType\" ng-class=\"{'active' : popup.duedate.field.taskDueDateCalculationType == 'subtract'}\">{{'PROCESS-BUILDER.FIELD.DUEDATE.CALCULATION-OPTIONS.SUBTRACT' | translate}}</button>\n                  </div>\n                </div>\n            </div>\n        </div>\n    </div>\n    \n    <div class=\"clearfix first\" ng-if=\"popup.selectedDueDateOption === 'field'\" style=\"padding-top: 10px\">\n        <div class=\"col-xs-12\">\n            <div class=\"col-xs-4\">\n                {{'PROCESS-BUILDER.FIELD.TIMER.YEARS' | translate}}:<input type=\"number\" class=\"form-control\" ng-model=\"popup.duedate.field.years\">\n            </div>\n            <div class=\"col-xs-4\">\n                {{'PROCESS-BUILDER.FIELD.TIMER.MONTHS' | translate}}:<input type=\"number\" class=\"form-control\" ng-model=\"popup.duedate.field.months\">\n            </div>\n            <div class=\"col-xs-4\">\n                {{'PROCESS-BUILDER.FIELD.TIMER.DAYS' | translate}}:<input type=\"number\" class=\"form-control\" ng-model=\"popup.duedate.field.days\">\n            </div>\n        </div>\n        <div class=\"col-xs-12\">\n            <div class=\"col-xs-4\">\n                {{'PROCESS-BUILDER.FIELD.TIMER.HOURS' | translate}}:<input type=\"number\" class=\"form-control\" ng-model=\"popup.duedate.field.hours\">\n            </div>\n            <div class=\"col-xs-4\">\n                {{'PROCESS-BUILDER.FIELD.TIMER.MINUTES' | translate}}:<input type=\"number\" class=\"form-control\" ng-model=\"popup.duedate.field.minutes\">\n            </div>\n            <div class=\"col-xs-4\">\n                {{'PROCESS-BUILDER.FIELD.TIMER.SECONDS' | translate}}:<input type=\"number\" class=\"form-control\" ng-model=\"popup.duedate.field.seconds\">\n            </div>\n        </div>\n    </div>\n    \n    <div class=\"clearfix first\" ng-if=\"popup.selectedDueDateOption === 'static'\" style=\"padding-top: 10px\">\n        <div class=\"col-xs-12\">\n            <div class=\"col-xs-4\">\n                {{'PROCESS-BUILDER.FIELD.TIMER.YEARS' | translate}}:<input type=\"number\" class=\"form-control\" ng-model=\"popup.duedate.fixed.years\">\n            </div>\n            <div class=\"col-xs-4\">\n                {{'PROCESS-BUILDER.FIELD.TIMER.MONTHS' | translate}}:<input type=\"number\" class=\"form-control\" ng-model=\"popup.duedate.fixed.months\">\n            </div>\n            <div class=\"col-xs-4\">\n                {{'PROCESS-BUILDER.FIELD.TIMER.DAYS' | translate}}:<input type=\"number\" class=\"form-control\" ng-model=\"popup.duedate.fixed.days\">\n            </div>\n        </div>\n        <div class=\"col-xs-12\">\n            <div class=\"col-xs-4\">\n                {{'PROCESS-BUILDER.FIELD.TIMER.HOURS' | translate}}:<input type=\"number\" class=\"form-control\" ng-model=\"popup.duedate.fixed.hours\">\n            </div>\n            <div class=\"col-xs-4\">\n                {{'PROCESS-BUILDER.FIELD.TIMER.MINUTES' | translate}}:<input type=\"number\" class=\"form-control\" ng-model=\"popup.duedate.fixed.minutes\">\n            </div>\n            <div class=\"col-xs-4\">\n                {{'PROCESS-BUILDER.FIELD.TIMER.SECONDS' | translate}}:<input type=\"number\" class=\"form-control\" ng-model=\"popup.duedate.fixed.seconds\">\n            </div>\n        </div>\n    </div>\n\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": "flowable-ui-web/modeler/editor-app/configuration/properties/duedate-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=\"BpmnEditorDueDateCtrl\">\n</span>"
  },
  {
    "path": "flowable-ui-web/modeler/editor-app/configuration/properties/errorgrid-critical.html",
    "content": "<div class=\"ui-grid-cell-contents flowable-status\">\n\t<!-- we inverse the logic here. A false warning is critical. A true warning is a warning -->\n\t<div class=\"flowable-warning\" ng-if=\"row.entity.warning\">Warning</div>\n\t<div class=\"flowable-critical\" ng-if=\"!row.entity.warning\">Critical</div>\n</div>"
  },
  {
    "path": "flowable-ui-web/modeler/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": "flowable-ui-web/modeler/editor-app/configuration/properties/event-listeners-popup.html",
    "content": "\n<div class=\"modal\" ng-controller=\"FlowableEventListenersPopupCtrl\">\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.title | translate}}\"</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\" ui-grid=\"gridOptions\" ui-grid-selection></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\n            \t<div class=\"row row-no-gutter\">\n                  <div ng-if=\"translationsRetrieved\" ng-show=\"selectedListener\" class=\"col-xs-6\">\n                    <div class=\"form-group\">\n            \t        \t<label>{{'PROPERTY.EVENTLISTENERS.EVENTS' | translate}}</label>\n            \t            <div ng-repeat=\"eventDefinition in selectedListener.events\">\n            \t            \t  <select id=\"eventField\" class=\"form-control\" ng-model=\"eventDefinition.event\" ng-change=\"listenerDetailsChanged()\"\n                                          style=\"display:inline-block; width:80%;margin-bottom: 10px;\">\n                                  <option>ACTIVITY_CANCELLED</option>\n                                  <option title=\"{{'EVENT_TYPE.ACTIVITY.COMPENSATE.TOOLTIP' | translate}}\">ACTIVITY_COMPENSATE</option>\n                                  <option title=\"{{'EVENT_TYPE.ACTIVITY.COMPLETED.TOOLTIP' | translate}}\">ACTIVITY_COMPLETED</option>\n                                  <option title=\"bla\">ACTIVITY_ERROR_RECEIVED</option>\n                                  <option>ACTIVITY_MESSAGE_CANCELLED</option>\n                                  <option>ACTIVITY_MESSAGE_RECEIVED</option>\n                                  <option>ACTIVITY_MESSAGE_WAITING</option>\n                                  <option>ACTIVITY_SIGNALED</option>\n                                  <option>ACTIVITY_SIGNAL_WAITING</option>\n                                  <option>ACTIVITY_STARTED</option>\n                                  <option>CUSTOM</option>\n                                  <option>ENGINE_CLOSED</option>\n                                  <option>ENGINE_CREATED</option>\n                                  <option>ENTITY_ACTIVATED</option>\n                                  <option>ENTITY_CREATED</option>\n                                  <option>ENTITY_DELETED</option>\n                                  <option>ENTITY_INITIALIZED</option>\n                                  <option>ENTITY_SUSPENDED</option>\n                                  <option>ENTITY_UPDATED</option>\n                                  <option>HISTORIC_ACTIVITY_INSTANCE_CREATED</option>\n                                  <option>HISTORIC_ACTIVITY_INSTANCE_ENDED</option>\n                                  <option>HISTORIC_PROCESS_INSTANCE_CREATED</option>\n                                  <option>HISTORIC_PROCESS_INSTANCE_ENDED</option>\n                                  <option>JOB_CANCELED</option>\n                                  <option>JOB_EXECUTION_FAILURE</option>\n                                  <option>JOB_EXECUTION_SUCCESS</option>\n                                  <option>JOB_RESCHEDULED</option>\n                                  <option>JOB_RETRIES_DECREMENTED</option>\n                                  <option title=\"{{'EVENT_TYPE.MEMBERSHIP.CREATED.TOOLTIP' | translate}}\">MEMBERSHIP_CREATED</option>\n                                  <option title=\"{{'EVENT_TYPE.MEMBERSHIP.DELETED.TOOLTIP' | translate}}\">MEMBERSHIP_DELETED</option>\n                                  <option title=\"{{'EVENT_TYPE.MEMBERSHIPS.DELETED.TOOLTIP' | translate}}\">MEMBERSHIPS_DELETED</option>\n                                  <option>MULTI_INSTANCE_ACTIVITY_CANCELLED</option>\n                                  <option>MULTI_INSTANCE_ACTIVITY_COMPLETED</option>\n                                  <option>MULTI_INSTANCE_ACTIVITY_COMPLETED_WITH_CONDITION</option>\n                                  <option>MULTI_INSTANCE_ACTIVITY_STARTED</option>\n                                  <option>PROCESS_CANCELLED</option>\n                                  <option>PROCESS_COMPLETED</option>\n                                  <option>PROCESS_COMPLETED_WITH_TERMINATE_END_EVENT</option>\n                                  <option>PROCESS_COMPLETED_WITH_ERROR_END_EVENT</option>\n                                  <option>PROCESS_CREATED</option>\n                                  <option>PROCESS_STARTED</option>\n                                  <option>SEQUENCEFLOW_TAKEN</option>\n                                  <option title=\"{{'EVENT_TYPE.TASK.ASSIGNED.TOOLTIP' | translate}}\">TASK_ASSIGNED</option>\n                                  <option title=\"{{'EVENT_TYPE.TASK.COMPLETED.TOOLTIP' | translate}}\">TASK_COMPLETED</option>\n                                  <option>TASK_CREATED</option>\n                                  <option>TIMER_FIRED</option>\n                                  <option>TIMER_SCHEDULED</option>\n                                  <option title=\"{{'EVENT_TYPE.UNCAUGHT.BPMNERROR.TOOLTIP' | translate}}\">UNCAUGHT_BPMN_ERROR</option>\n                                  <option title=\"{{'EVENT_TYPE.VARIABLE.CREATED.TOOLTIP' | translate}}\">VARIABLE_CREATED</option>\n                                  <option title=\"{{'EVENT_TYPE.VARIABLE.DELETED.TOOLTIP' | translate}}\">VARIABLE_DELETED</option>\n                                  <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)\"\n                                   style=\"margin: 5px 0 5px 10px; font-size: 16px; cursor:pointer;\"></i>\n            \t\t            <i class=\"glyphicon glyphicon-plus clickable-property\" ng-click=\"addEventValue($index)\"\n                                   style=\"margin: 5px 0 5px 10px; font-size: 16px; cursor:pointer;\"></i>\n            \t            </div>\n\n            \t            <div class=\"form-group\" ng-show=\"selectedListener.event\" style=\"margin-top: 10px;\">\n                                <input type=\"checkbox\" id=\"rethrowField\" class=\"checkbox\" ng-model=\"selectedListener.rethrowEvent\" ng-change=\"listenerDetailsChanged()\" style=\"display:inline-block;\"/>\n                                <label for=\"classField\" ng-click=\"selectedListener.rethrowEvent = !selectedListener.rethrowEvent\" style=\"cursor:pointer;\">{{'PROPERTY.EVENTLISTENERS.RETHROW' | translate}}</label>\n                            </div>\n            \t       \t  </div>\n                     </div>\n                     <div ng-show=\"selectedListener && selectedListener.events[0].event\" class=\"col-xs-6\">\n                     \t<div class=\"form-group\" ng-if=\"!selectedListener.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=\"selectedListener.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=\"!selectedListener.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=\"selectedListener.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=\"!selectedListener.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=\"selectedListener.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=\"selectedListener.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=\"selectedListener.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=\"selectedListener.rethrowEvent && selectedListener.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=\"selectedListener.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=\"selectedListener.rethrowEvent && selectedListener.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=\"selectedListener.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=\"selectedListener.rethrowEvent && (selectedListener.rethrowType === 'signal' || selectedListener.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=\"selectedListener.signalname\" ng-change=\"listenerDetailsChanged()\" placeholder=\"{{'PROPERTY.EVENTLISTENERS.SIGNALNAME.PLACEHOLDER' | translate}}\" />\n            \t\t\t</div>\n                     </div>\n                     <div ng-show=\"!selectedListener\" 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>\n"
  },
  {
    "path": "flowable-ui-web/modeler/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=\"FlowableEventListenersCtrl\">\n</span>"
  },
  {
    "path": "flowable-ui-web/modeler/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": "flowable-ui-web/modeler/editor-app/configuration/properties/execution-listeners-popup.html",
    "content": "\n<div class=\"modal\" ng-controller=\"FlowableExecutionListenersPopupCtrl\">\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.title | translate}}\"</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\" ui-grid=\"gridOptions\" ui-grid-selection></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=\"selectedListener\">\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=\"selectedListener.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=\"selectedListener.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=\"selectedListener.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=\"selectedListener.delegateExpression\" ng-change=\"listenerDetailsChanged()\" placeholder=\"{{'PROPERTY.EXECUTIONLISTENERS.DELEGATEEXPRESSION.PLACEHOLDER' | translate}}\" />\n            \t\t\t\t</div>\n                        </div>\n                        <div ng-show=\"!selectedListener\" 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\" ui-grid=\"gridFieldOptions\" ui-grid-selection></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=\"selectedField\">\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=\"selectedField.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=\"selectedField.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=\"selectedField.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=\"selectedField.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=\"!selectedField\" 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": "flowable-ui-web/modeler/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=\"FlowableExecutionListenersCtrl\">\n</span>"
  },
  {
    "path": "flowable-ui-web/modeler/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": "flowable-ui-web/modeler/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": "flowable-ui-web/modeler/editor-app/configuration/properties/fields-popup.html",
    "content": "\n<div class=\"modal\" ng-controller=\"FlowableFieldsPopupCtrl\">\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.title | translate}}\"</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\t\t\t            <div ng-if=\"translationsRetrieved\" class=\"kis-listener-grid\" ui-grid=\"gridOptions\" ui-grid-selection></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\n\t\t\t        <div class=\"col-xs-6\">\n\t\t\t             <div ng-show=\"selectedField\">\n\n\t\t\t                 <div class=\"form-group\">\n\t\t\t                     <label translate>PROPERTY.FIELDS.NAME</label>\n\t\t\t                     <input type=\"text\" class=\"form-control\" ng-model=\"selectedField.name\" placeholder=\"{{'PROPERTY.FIELDS.NAME.PLACEHOLDER' | translate}}\" />\n\t\t\t                 </div>\n\t\t\t                 <div>\n\t\t\t                     <label translate>PROPERTY.FIELDS.STRINGVALUE</label>\n\t\t\t                     <input type=\"text\" class=\"form-control\" ng-model=\"selectedField.stringValue\" ng-change=\"fieldDetailsChanged()\" placeholder=\"{{'PROPERTY.FIELDS.STRINGVALUE.PLACEHOLDER' | translate}}\" />\n\t\t\t                 </div>\n\t\t\t                 <div>\n\t\t\t                     <label translate>PROPERTY.FIELDS.EXPRESSION</label>\n\t\t\t                     <input type=\"text\" class=\"form-control\" ng-model=\"selectedField.expression\" ng-change=\"fieldDetailsChanged()\" placeholder=\"{{'PROPERTY.FIELDS.EXPRESSION.PLACEHOLDER' | translate}}\" />\n\t\t\t                 </div>\n\t\t\t                 <div>\n\t\t\t                     <label translate>PROPERTY.FIELDS.STRING</label>\n\t\t\t                     <textarea type=\"text\" class=\"form-control\" ng-model=\"selectedField.string\" ng-change=\"fieldDetailsChanged()\" placeholder=\"{{'PROPERTY.FIELDS.STRING.PLACEHOLDER' | translate}}\"></textarea>\n\t\t\t                 </div>\n\n\t\t\t            </div>\n\t\t\t            <div ng-show=\"!selectedField\" class=\"muted no-property-selected\" translate>PROPERTY.FIELDS.EMPTY</div>\n\t\t\t        </div>\n\t\t\t    </div>\n\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": "flowable-ui-web/modeler/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=\"FlowableFieldsCtrl\">\n</span>"
  },
  {
    "path": "flowable-ui-web/modeler/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": "flowable-ui-web/modeler/editor-app/configuration/properties/form-properties-popup.html",
    "content": "\n<div class=\"modal\" ng-controller=\"FlowableFormPropertiesPopupCtrl\">\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.title | translate}}\"</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\" ui-grid=\"gridOptions\" ui-grid-selection></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=\"selectedProperty\">\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=\"selectedProperty.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=\"selectedProperty.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=\"selectedProperty.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=\"selectedProperty.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=\"selectedProperty.datePattern\" placeholder=\"{{'PROPERTY.FORMPROPERTIES.DATEPATTERN.PLACEHOLDER' | translate }}\" />\n            \t\t\t\t</div>\n                            <div ng-show=\"selectedProperty.type == 'enum'\" style=\"padding-bottom:10px\">\n                                <div class=\"row row-no-gutter\">\n                                    <div class=\"col-xs-6\">\n                                        <div ng-if=\"translationsRetrieved\" class=\"kis-listener-grid\" ui-grid=\"enumGridOptions\" ui-grid-selection ui-grid-auto-resize></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=\"moveEnumValueUp()\"><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=\"moveEnumValueDown()\"><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=\"addNewEnumValue()\"><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=\"removeEnumValue()\"><i class=\"glyphicon glyphicon-minus\"></i></a>\n                                            </div>\n                                        </div>\n                                    </div>\n                            \n                                    <div class=\"col-xs-6\">\n                                        <div ng-show=\"selectedEnumValue\">\n                            \n                                            <div class=\"form-group\">\n                                                <label for=\"classField\">{{'PROPERTY.FORMPROPERTIES.VALUES.ID' | translate}}</label>\n                                                <input type=\"text\" id=\"classField\" class=\"form-control\" ng-model=\"selectedEnumValue.id\" placeholder=\"{{'PROPERTY.FORMPROPERTIES.VALUES.ID.PLACEHOLDER' | translate}}\" />\n                                            </div>\n                                            <div class=\"form-group\">\n                                                <label for=\"classField\">{{'PROPERTY.FORMPROPERTIES.VALUES.NAME' | translate}}</label>\n                                                <input type=\"text\" id=\"classField\" class=\"form-control\" ng-model=\"selectedEnumValue.name\" placeholder=\"{{'PROPERTY.FORMPROPERTIES.VALUES.NAME.PLACEHOLDER' | translate}}\" />\n                                            </div>\n                                        </div>\n                                        <div ng-show=\"!selectedEnumValue\" class=\"muted no-property-selected\" translate>PROPERTY.FORMPROPERTIES.ENUMVALUES.EMPTY</div>\n                                    </div>\n                                </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=\"selectedProperty.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=\"selectedProperty.variable\" placeholder=\"{{'PROPERTY.FORMPROPERTIES.VARIABLE.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=\"defaultField\">{{'PROPERTY.FORMPROPERTIES.DEFAULT' | translate}}</label>\n            \t\t\t   \t\t<input id=\"defaultField\" class=\"form-control\" type=\"text\" ng-model=\"selectedProperty.default\" placeholder=\"{{'PROPERTY.FORMPROPERTIES.DEFAULT.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=\"checkbox\" type=\"checkbox\" ng-model=\"selectedProperty.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=\"checkbox\" type=\"checkbox\" ng-model=\"selectedProperty.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=\"checkbox\" type=\"checkbox\" ng-model=\"selectedProperty.writable\" />\n            \t\t\t\t\t</div>\n            \t\t\t\t</div>\n                        </div>\n                        <div ng-show=\"!selectedProperty\" 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": "flowable-ui-web/modeler/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=\"FlowableFormPropertiesCtrl\">\n</span>"
  },
  {
    "path": "flowable-ui-web/modeler/editor-app/configuration/properties/form-reference-display-template.html",
    "content": "<div ng-controller=\"FlowableFormReferenceDisplayCtrl\">\n\t<span ng-if=\"property.value && property.value.id\">{{form.name}}</span>\n\t<span ng-if=\"!property.value || !property.value.id\" translate>PROPERTY.FORMREFERENCE.EMPTY</span>\n</div>\n"
  },
  {
    "path": "flowable-ui-web/modeler/editor-app/configuration/properties/form-reference-popup.html",
    "content": "\n<div class=\"modal\" ng-controller=\"FlowableFormReferencePopupCtrl\">\n    <div class=\"modal-dialog modal-wide\">\n        <div class=\"modal-content\">\n            <div class=\"modal-header\" ng-if=\"popup.state != 'newForm'\">\n                <button type=\"button\" class=\"close\" data-dismiss=\"modal\" aria-hidden=\"true\" ng-click=\"close()\">&times;</button>\n                <h2>\n                    {{'PROPERTY.FORMREFERENCE.TITLE' | translate}}\n                    <span ng-show=\"selectedForm != null\"> - {{selectedForm.name}}</span>\n                    <span ng-show=\"selectedForm == null\"> - {{'PROPERTY.FORMREFERENCE.EMPTY' | translate}}</span> \n                \n                </h2>\n            </div>\n            <div class=\"modal-header\" ng-if=\"popup.state == 'newForm'\"><h2>{{'FORM.POPUP.CREATE-TITLE' | translate}}</h2></div>\n            <div class=\"modal-body-with-overflow\" ng-if=\"popup.state != 'newForm'\">\n                <div class=\"detail-group clearfix\">\n                    <div class=\"col-xs-12\">\n                        <div class=\"alert alert-error\" ng-show=\"!state.loadingForms && state.formError\" translate>PROPERTY.FORMREFERENCE.ERROR.FORM</div>\n                    </div>\n                </div>\n                <div class=\"detail-group clearfix\">\n                    <div class=\"col-xs-12 editor-item-picker\">\n                        <div ng-if=\"!state.loadingForms && !state.formError\" class=\"col-xs-4 editor-item-picker-component\" ng-repeat=\"form in forms\" ng-class=\"{'selected' : form.formId == selectedForm.formId}\" ng-click=\"selectForm(form, $event)\">\n                           <div class=\"controls\">\n                               <input type=\"checkbox\" value=\"option1\" ng-click=\"selectForm(form, $event)\" ng-checked=\"form.id == selectedForm.id\" />\n                           </div>\n                           <h4>{{form.name}}</h4>\n                           <img ng-src=\"{{getModelThumbnailUrl(form.id)}}\" />\n                         </div>\n                         <div ng-show=\"state.loadingForms\">\n                            <p class=\"loading\" translate>PROPERTY.FORMREFERENCE.FORM.LOADING</p>\n                         </div>\n                         <div ng-show=\"!state.loadingForms && forms.length == 0\">\n                            <p translate>PROPERTY.FORMREFERENCE.FORM.EMPTY</p>\n                         </div>\n                    </div>\n                </div>\n            </div>\n            <div class=\"modal-body\" ng-if=\"popup.state == 'newForm'\">\n                <p>{{'FORM.POPUP.CREATE-DESCRIPTION' | translate}}</p>\n                <div ng-if=\"model.errorMessage && model.errorMessage.length > 0\" class=\"alert error\" style=\"font-size: 14px; margin-top:20px\">\n                  <div class=\"popup-error\" style=\"font-size: 14px\">\n                    <span class=\"glyphicon glyphicon-remove-circle\"></span>\n                    <span>{{model.errorMessage}}</span>\n                  </div>\n                </div>\n                <div class=\"form-group\">\n                    <label for=\"newFormName\">{{'FORM.NAME' | translate}}</label>\n                    <input ng-disabled=\"model.loading\" type=\"text\" class=\"form-control\"\n                           id=\"newFormName\" ng-model=\"model.form.name\" custom-keys enter-pressed=\"ok()\" auto-focus editor-input-check>\n                </div>\n                <div class=\"form-group\">\n                    <label for=\"newFormKey\">{{'FORM.KEY' | translate}}</label>\n                    <input ng-disabled=\"model.loading\" type=\"text\" class=\"form-control\"\n                           id=\"newFormKey\" ng-model=\"model.form.key\" editor-input-check>\n                </div>\n                <div class=\"form-group\">\n                    <label for=\"newFormDescription\">{{'FORM.DESCRIPTION' | translate}}</label>\n                    <textarea ng-disabled=\"model.loading\" class=\"form-control\" id=\"newFormDescription\" rows=\"5\" ng-model=\"model.form.description\"></textarea>\n                </div>\n            </div>\n            <div class=\"modal-footer\" ng-if=\"popup.state != 'newForm'\">\n            \t<button ng-click=\"cancel()\" class=\"btn btn-primary\" translate>GENERAL.ACTION.CANCEL</button>\n            \t<button ng-disabled=\"state.formError\" ng-click=\"newForm()\" class=\"btn btn-primary\" translate>GENERAL.ACTION.NEW-FORM</button>\n            \t<button ng-disabled=\"!selectedForm || state.formError\" ng-click=\"open()\" class=\"btn btn-primary\" translate>GENERAL.ACTION.OPEN</button>\n                <button ng-disabled=\"state.formError\" ng-click=\"save()\" class=\"btn btn-primary\" translate>GENERAL.ACTION.SAVE</button>\n            </div>\n            <div class=\"modal-footer\" ng-if=\"popup.state == 'newForm'\">\n                <button ng-click=\"cancel()\" class=\"btn btn-primary\" translate>GENERAL.ACTION.CANCEL</button>\n                <button ng-disabled=\"state.formError || model.form.name.length == 0 || model.form.key.length == 0\" ng-click=\"createForm()\" class=\"btn btn-primary\" translate>GENERAL.ACTION.CREATE-FORM</button>\n            </div>\n        </div>\n    </div>\n</div>\n"
  },
  {
    "path": "flowable-ui-web/modeler/editor-app/configuration/properties/form-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=\"FlowableFormReferenceCtrl\">\n</span>"
  },
  {
    "path": "flowable-ui-web/modeler/editor-app/configuration/properties/http-request-method-display-template.html",
    "content": "\n<span ng-if=\"!property.noValue\">{{property.value}}</span>\n<span ng-if=\"property.noValue\">GET</span>"
  },
  {
    "path": "flowable-ui-web/modeler/editor-app/configuration/properties/http-request-method-property-write-template.html",
    "content": "<div ng-controller=\"FlowableHttpRequestMethodCtrl\">\n    <select ng-model=\"property.value\" ng-change=\"httpRequestMethodChanged()\">\n        <option>GET</option>\n        <option>POST</option>\n        <option>PUT</option>\n        <option>DELETE</option>\n    </select>\n</div>"
  },
  {
    "path": "flowable-ui-web/modeler/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": "flowable-ui-web/modeler/editor-app/configuration/properties/in-parameters-popup.html",
    "content": "\n<div class=\"modal\" ng-controller=\"FlowableInParametersPopupCtrl\">\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.title | translate}}\"</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                        <div ng-if=\"translationsRetrieved\" class=\"kis-listener-grid\" ui-grid=\"gridOptions\" ui-grid-selection></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=\"selectedParameter\">\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=\"selectedParameter.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=\"selectedParameter.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=\"selectedParameter.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=\"!selectedParameter\" 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": "flowable-ui-web/modeler/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=\"FlowableInParametersCtrl\">\n</span>"
  },
  {
    "path": "flowable-ui-web/modeler/editor-app/configuration/properties/message-definitions-display-template.html",
    "content": "\n<span ng-if=\"!property.noValue\">{{'PROPERTY.MESSAGEDEFINITIONS.DISPLAY' | translate:property.value}}</span>\n<span ng-if=\"property.noValue\" translate>PROPERTY.MESSAGEDEFINITIONS.EMPTY</span>"
  },
  {
    "path": "flowable-ui-web/modeler/editor-app/configuration/properties/message-definitions-popup.html",
    "content": "<div class=\"modal\" ng-controller=\"FlowableMessageDefinitionsPopupCtrl\">\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.title | translate}}\"</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\" ui-grid=\"gridOptions\" ui-grid-selection></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=\"selectedMessageDefinition\">\n\n                        <div class=\"form-group\">\n                            <label>{{'PROPERTY.MESSAGEDEFINITIONS.ID' | translate}}</label>\n                            <input type=\"text\" class=\"form-control\" ng-model=\"selectedMessageDefinition.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=\"selectedMessageDefinition.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": "flowable-ui-web/modeler/editor-app/configuration/properties/message-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=\"FlowableMessageDefinitionsCtrl\">\n</span>"
  },
  {
    "path": "flowable-ui-web/modeler/editor-app/configuration/properties/message-property-write-template.html",
    "content": "<div ng-controller=\"FlowableMessageRefCtrl\">\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": "flowable-ui-web/modeler/editor-app/configuration/properties/multiinstance-property-write-template.html",
    "content": "\n<div ng-controller=\"FlowableMultiInstanceCtrl\">\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": "flowable-ui-web/modeler/editor-app/configuration/properties/ordering-property-write-template.html",
    "content": "\n<div ng-controller=\"FlowableOrderingCtrl\">\n    <select ng-model=\"property.value\" ng-change=\"orderingChanged()\">\n    \t<option>Parallel</option>\n    \t<option>Sequential</option>\n    </select>\n</div>"
  },
  {
    "path": "flowable-ui-web/modeler/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": "flowable-ui-web/modeler/editor-app/configuration/properties/out-parameters-popup.html",
    "content": "\n<div class=\"modal\" ng-controller=\"FlowableOutParametersPopupCtrl\">\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.title | translate}}\"</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                        <div ng-if=\"translationsRetrieved\" class=\"kis-listener-grid\" ui-grid=\"gridOptions\" ui-grid-selection></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=\"selectedParameter\">\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=\"selectedParameter.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=\"selectedParameter.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=\"selectedParameter.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=\"!selectedParameter\" 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": "flowable-ui-web/modeler/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=\"FlowableOutParametersCtrl\">\n</span>"
  },
  {
    "path": "flowable-ui-web/modeler/editor-app/configuration/properties/plan-item-lifecycle-listeners-display-template.html",
    "content": "\n<span ng-if=\"!property.noValue\">{{'PROPERTY.PLANITEMLIFECYCLELISTENERS.VALUE' | translate:property.value.planItemLifecycleListeners}}</span>\n<span ng-if=\"property.noValue\" translate>PROPERTY.PLANITEMLIFECYCLELISTENERS.EMPTY</span>"
  },
  {
    "path": "flowable-ui-web/modeler/editor-app/configuration/properties/plan-item-lifecycle-listeners-popup.html",
    "content": "\n<div class=\"modal\" ng-controller=\"FlowablePlanItemLifecycleListenersPopupCtrl\">\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.title | translate}}\"</h2>\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\t\t\t            <div ng-if=\"translationsRetrieved\" class=\"kis-listener-grid\" ui-grid=\"gridOptions\" ui-grid-selection></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\n\t\t\t        <div class=\"col-xs-6\">\n\t\t\t            <div ng-show=\"selectedListener\">\n\n\t\t\t                <div class=\"form-group\">\n\t\t\t\t\t\t   \t\t<label for=\"sourceStateField\">{{'PROPERTY.PLANITEMLIFECYCLELISTENERS.SOURCE_STATE' | translate}}</label>\n\t\t\t\t\t\t   \t\t<select id=\"sourceStateField\" class=\"form-control\" ng-model=\"selectedListener.sourceState\">\n\t\t\t                        <option>active</option>\n\t\t\t\t\t\t\t\t\t<option>available</option>\n\t\t\t\t\t\t\t\t\t<option>enabled</option>\n\t\t\t\t\t\t\t\t\t<option>disabled</option>\n\t\t\t\t\t\t\t\t\t<option>completed</option>\n\t\t\t\t\t\t\t\t\t<option>failed</option>\n\t\t\t\t\t\t\t\t\t<option>suspended</option>\n\t\t\t\t\t\t\t\t\t<option>closed</option>\n\t\t\t\t\t\t\t\t\t<option>terminated</option>\n\t\t\t\t\t\t\t\t\t<option>wait_repetition</option>\n\t\t\t\t\t\t\t\t\t<option>async-active</option>\n\t\t\t\t\t\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=\"targetStateField\">{{'PROPERTY.PLANITEMLIFECYCLELISTENERS.TARGET_STATE' | translate}}</label>\n\t\t\t\t\t\t\t\t<select id=\"targetStateField\" class=\"form-control\" ng-model=\"selectedListener.targetState\">\n\t\t\t\t\t\t\t\t\t<option>active</option>\n\t\t\t\t\t\t\t\t\t<option>available</option>\n\t\t\t\t\t\t\t\t\t<option>enabled</option>\n\t\t\t\t\t\t\t\t\t<option>disabled</option>\n\t\t\t\t\t\t\t\t\t<option>completed</option>\n\t\t\t\t\t\t\t\t\t<option>failed</option>\n\t\t\t\t\t\t\t\t\t<option>suspended</option>\n\t\t\t\t\t\t\t\t\t<option>closed</option>\n\t\t\t\t\t\t\t\t\t<option>terminated</option>\n\t\t\t\t\t\t\t\t\t<option>wait_repetition</option>\n\t\t\t\t\t\t\t\t\t<option>async-active</option>\n\t\t\t\t\t\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.PLANITEMLIFECYCLELISTENERS.CLASS' | translate}}</label>\n\t\t\t\t\t\t   \t\t<input type=\"text\" id=\"classField\" class=\"form-control\" ng-model=\"selectedListener.className\" ng-change=\"listenerDetailsChanged()\" placeholder=\"{{'PROPERTY.PLANITEMLIFECYCLELISTENERS.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.PLANITEMLIFECYCLELISTENERS.EXPRESSION' | translate}}</label>\n\t\t\t\t\t\t   \t\t<input type=\"text\" id=\"expressionField\" class=\"form-control\" ng-model=\"selectedListener.expression\" ng-change=\"listenerDetailsChanged()\" placeholder=\"{{'PROPERTY.PLANITEMLIFECYCLELISTENERS.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.PLANITEMLIFECYCLELISTENERS.DELEGATEEXPRESSION' | translate}}</label>\n\t\t\t\t\t\t   \t\t<input type=\"text\" id=\"delegateExpressionField\" class=\"form-control\" ng-model=\"selectedListener.delegateExpression\" ng-change=\"listenerDetailsChanged()\" placeholder=\"{{'PROPERTY.PLANITEMLIFECYCLELISTENERS.DELEGATEEXPRESSION.PLACEHOLDER' | translate}}\" />\n\t\t\t\t\t\t\t</div>\n\t\t\t            </div>\n\t\t\t            <div ng-show=\"!selectedListener\" class=\"muted no-property-selected\" translate>PROPERTY.PLANITEMLIFECYCLELISTENERS.UNSELECTED</div>\n\t\t\t        </div>\n\t\t\t    </div>\n\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\" ui-grid=\"gridFieldOptions\" ui-grid-selection></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\n\t\t\t        <div class=\"col-xs-6\">\n\t\t\t            <div ng-show=\"selectedField\">\n\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.PLANITEMLIFECYCLELISTENERS.FIELDS.NAME' | translate}}</label>\n\t\t\t\t\t\t   \t\t<input type=\"text\" id=\"nameField\" class=\"form-control\" ng-model=\"selectedField.name\" placeholder=\"{{'PROPERTY.PLANITEMLIFECYCLELISTENERS.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.PLANITEMLIFECYCLELISTENERS.FIELDS.STRINGVALUE' | translate}}</label>\n\t\t\t\t\t\t   \t\t<input type=\"text\" id=\"stringValueField\" class=\"form-control\" ng-model=\"selectedField.stringValue\" ng-change=\"fieldDetailsChanged()\" placeholder=\"{{'PROPERTY.PLANITEMLIFECYCLELISTENERS.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.PLANITEMLIFECYCLELISTENERS.FIELDS.EXPRESSION' | translate}}</label>\n\t\t\t\t\t\t   \t\t<input type=\"text\" id=\"expressionField\" class=\"form-control\" ng-model=\"selectedField.expression\" ng-change=\"fieldDetailsChanged()\" placeholder=\"{{'PROPERTY.PLANITEMLIFECYCLELISTENERS.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.PLANITEMLIFECYCLELISTENERS.FIELDS.STRING' | translate}}</label>\n\t\t\t\t\t\t   \t\t<textarea id=\"stringField\" class=\"form-control\" ng-model=\"selectedField.string\" ng-change=\"fieldDetailsChanged()\" placeholder=\"{{'PROPERTY.PLANITEMLIFECYCLELISTENERS.FIELDS.STRING.PLACEHOLDER' | translate}}\"></textarea>\n\t\t\t\t\t\t\t</div>\n\n\t\t\t            </div>\n\t\t\t            <div ng-show=\"!selectedField\" class=\"muted no-property-selected\"translate>PROPERTY.PLANITEMLIFECYCLELISTENERS.FIELDS.EMPTY</div>\n\t\t\t        </div>\n\t\t\t    </div>\n\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": "flowable-ui-web/modeler/editor-app/configuration/properties/plan-item-lifecycle-listeners-write-template.html",
    "content": "<span ng-controller=\"FlowablePlanItemLifecycleListenersCtrl\">\n</span>"
  },
  {
    "path": "flowable-ui-web/modeler/editor-app/configuration/properties/planitem-dropdown-read-template.html",
    "content": "\n<span ng-if=\"!property.noValue\">{{property.value.name|limitTo:20}}</span>\n<span ng-if=\"!property.noValue && property.value != null && property.value.name.length > 20\">...</span>\n<span ng-if=\"property.noValue\" translate>PROPERTY.EMPTY</span>"
  },
  {
    "path": "flowable-ui-web/modeler/editor-app/configuration/properties/planitem-dropdown-write-template.html",
    "content": "\n<div ng-controller=\"FlowablePlanItemDropdownCtrl\">\n    <select ng-model=\"property.value\" ng-options=\"planItem as planItem.name for planItem in planItems\" ng-change=\"planItemChanged()\">\n    </select>\n</div>"
  },
  {
    "path": "flowable-ui-web/modeler/editor-app/configuration/properties/process-historylevel-property-write-template.html",
    "content": "\n<div ng-controller=\"FlowableProcessHistoryLevelCtrl\">\n    <select ng-model=\"property.value\" ng-change=\"historyLevelChanged()\">\n    \t<option></option>\n    \t<option>none</option>\n    \t<option>activity</option>\n    \t<option>audit</option>\n    \t<option>full</option>\n    </select>\n</div>"
  },
  {
    "path": "flowable-ui-web/modeler/editor-app/configuration/properties/process-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.PROCESSREFERENCE.EMPTY</span>\n"
  },
  {
    "path": "flowable-ui-web/modeler/editor-app/configuration/properties/process-reference-popup.html",
    "content": "\n<div class=\"modal\" ng-controller=\"FlowableProcessReferencePopupCtrl\">\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.PROCESSREFERENCE.TITLE' | translate}}\n\t\t\t        <span ng-show=\"selectedProcess != null\"> - {{selectedProcess.name}}</span>\n\t\t\t        <span ng-show=\"selectedProcess == null\"> - {{'PROPERTY.PROCESSREFERENCE.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-with-overflow\">\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.loadingProcesses) && state.processError\" translate>PROPERTY.PROCESSREFERENCE.ERROR.PROCESS</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.loadingProcesses && !state.processError\" class=\"col-xs-4 editor-item-picker-component\" ng-repeat=\"processModel in processModels\" ng-class=\"{'selected' : processModel.id == selectedProcess.id}\" ng-click=\"selectProcess(processModel, $event)\">\n\t\t\t               <div class=\"controls\">\n\t\t\t                   <input type=\"checkbox\" value=\"option1\" ng-click=\"selectProcess(processModel, $event)\" ng-checked=\"processModel.id == selectedProcess.id\" />\n\t\t\t               </div>\n\t\t\t               <h4>{{processModel.name}}</h4>\n\t\t\t               <img src=\"{{getModelThumbnailUrl(processModel.id)}}\" />\n\t\t\t             </div>\n\t\t\t             <div ng-show=\"state.loadingProcesses\">\n\t\t\t               <p class=\"loading\" translate>PROPERTY.PROCESSREFERENCE.PROCESS.LOADING</p>\n\t\t\t             </div>\n\t\t\t             <div ng-show=\"!state.loadingProcesses && processModels.length == 0\">\n\t\t\t                <p translate>PROPERTY.PROCESSREFERENCE.PROCESS.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-click=\"close()\" class=\"btn btn-primary\" translate>GENERAL.ACTION.CANCEL</button>\n                <button ng-disabled=\"!selectedProcess || state.processError\" ng-click=\"open()\" class=\"btn btn-primary\" translate>GENERAL.ACTION.OPEN</button>\n                <button ng-disabled=\"state.processError\" ng-click=\"save()\" class=\"btn btn-primary\" translate>GENERAL.ACTION.SAVE</button>\n\t\t\t</div>\n\t\t</div>\n\t</div>\n</div>\n"
  },
  {
    "path": "flowable-ui-web/modeler/editor-app/configuration/properties/process-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=\"FlowableProcessReferenceCtrl\">\n</span>"
  },
  {
    "path": "flowable-ui-web/modeler/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": "flowable-ui-web/modeler/editor-app/configuration/properties/sequenceflow-order-popup.html",
    "content": "\n<div class=\"modal\" ng-controller=\"FlowableSequenceFlowOrderPopupCtrl\">\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.title | translate}}\"</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": "flowable-ui-web/modeler/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=\"FlowableSequenceFlowOrderCtrl\">\n</span>"
  },
  {
    "path": "flowable-ui-web/modeler/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": "flowable-ui-web/modeler/editor-app/configuration/properties/signal-definitions-popup.html",
    "content": "<div class=\"modal\" ng-controller=\"FlowableSignalDefinitionsPopupCtrl\">\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.title | translate}}\"</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\" ui-grid=\"gridOptions\" ui-grid-selection></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=\"selectedSignalDefinition\">\n\n                        <div class=\"form-group\">\n                            <label>{{'PROPERTY.SIGNALDEFINITIONS.ID' | translate}}</label>\n                            <input type=\"text\" class=\"form-control\" ng-model=\"selectedSignalDefinition.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=\"selectedSignalDefinition.name\">\n                        </div>\n\n                        <div class=\"form-group\">\n                            <label>{{'PROPERTY.SIGNALDEFINITIONS.SCOPE' | translate}}</label>\n                            <select class=\"form-control\" ng-model=\"selectedSignalDefinition.scope\" ng-change=\"listenerDetailsChanged()\"\n                                    ng-options=\"option.value as option.translationId | translate for option in scopeOptions\">\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": "flowable-ui-web/modeler/editor-app/configuration/properties/signal-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=\"FlowableSignalDefinitionsCtrl\">\n</span>"
  },
  {
    "path": "flowable-ui-web/modeler/editor-app/configuration/properties/signal-property-write-template.html",
    "content": "<div ng-controller=\"FlowableSignalRefCtrl\">\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": "flowable-ui-web/modeler/editor-app/configuration/properties/string-property-write-mode-template.html",
    "content": "\n<div ng-controller=\"FlowableStringPropertyCtrl\">\n    <input type=\"text\" ng-model=\"property.value\"\n    \t   class=\"form-control\"\n           auto-focus\n           select-text=\"property.value\"\n           ng-blur=\"inputBlurred()\"\n           ng-keypress=\"enterPressed($event)\"/>\n</div>"
  },
  {
    "path": "flowable-ui-web/modeler/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": "flowable-ui-web/modeler/editor-app/configuration/properties/task-listeners-popup.html",
    "content": "\n<div class=\"modal\" ng-controller=\"FlowableTaskListenersPopupCtrl\">\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.title | translate}}\"</h2>\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\t\t\t            <div ng-if=\"translationsRetrieved\" class=\"kis-listener-grid\" ui-grid=\"gridOptions\" ui-grid-selection></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\n\t\t\t        <div class=\"col-xs-6\">\n\t\t\t            <div ng-show=\"selectedListener\">\n\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=\"selectedListener.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=\"selectedListener.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=\"selectedListener.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=\"selectedListener.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=\"!selectedListener\" class=\"muted no-property-selected\" translate>PROPERTY.TASKLISTENERS.UNSELECTED</div>\n\t\t\t        </div>\n\t\t\t    </div>\n\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\" ui-grid=\"gridFieldOptions\" ui-grid-selection></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\n\t\t\t        <div class=\"col-xs-6\">\n\t\t\t            <div ng-show=\"selectedField\">\n\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=\"selectedField.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=\"selectedField.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=\"selectedField.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=\"selectedField.string\" ng-change=\"fieldDetailsChanged()\" placeholder=\"{{'PROPERTY.TASKLISTENERS.FIELDS.STRING.PLACEHOLDER' | translate}}\"></textarea>\n\t\t\t\t\t\t\t</div>\n\n\t\t\t            </div>\n\t\t\t            <div ng-show=\"!selectedField\" class=\"muted no-property-selected\"translate>PROPERTY.TASKLISTENERS.FIELDS.EMPTY</div>\n\t\t\t        </div>\n\t\t\t    </div>\n\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": "flowable-ui-web/modeler/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=\"FlowableTaskListenersCtrl\">\n</span>"
  },
  {
    "path": "flowable-ui-web/modeler/editor-app/configuration/properties/text-popup.html",
    "content": "\n<div class=\"modal\" ng-controller=\"FlowableTextPropertyPopupCtrl\">\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.title | translate}}\"</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": "flowable-ui-web/modeler/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=\"FlowableTextPropertyCtrl\">\n</span>"
  },
  {
    "path": "flowable-ui-web/modeler/editor-app/configuration/properties/transition-event-write-template.html",
    "content": "\n<div ng-controller=\"FlowableTransitionEventCtrl\">\n    <select ng-model=\"property.value\" ng-change=\"transitionEventChanged()\">\n    \t<option>complete</option>\n    \t<option>exit</option>\n    \t<option>occur</option>\n    \t<option>start</option>\n    \t<option>terminate</option>\n    </select>\n</div>"
  },
  {
    "path": "flowable-ui-web/modeler/editor-app/configuration/properties/trigger-mode-read-template.html",
    "content": "\n<span ng-if=\"!property.noValue\">{{property.value}}</span>\n<span ng-if=\"property.noValue\">default</span>"
  },
  {
    "path": "flowable-ui-web/modeler/editor-app/configuration/properties/trigger-mode-write-template.html",
    "content": "\n<div ng-controller=\"FlowableTriggerModeCtrl\">\n    <select ng-model=\"property.value\" ng-change=\"triggerModeChanged()\">\n    \t<option>default</option>\n    \t<option>onEvent</option>\n    </select>\n</div>"
  },
  {
    "path": "flowable-ui-web/modeler/editor-app/configuration/properties-assignment-controller.js",
    "content": "/* Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n * \n *      http://www.apache.org/licenses/LICENSE-2.0\n * \n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/*\n * Assignment\n */\n'use strict';\n\nangular.module('flowableModeler').controller('FlowableAssignmentCtrl', [ '$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    _internalCreateModal(opts, $modal, $scope);\n}]);\n\nangular.module('flowableModeler').controller('FlowableAssignmentPopupCtrl',\n    [ '$rootScope', '$scope', '$translate', '$http', 'UserService', 'GroupService', function($rootScope, $scope, $translate, $http, UserService, GroupService) {\n\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        if (typeof $scope.assignment.type === 'undefined') {\n            $scope.assignment.type = 'static';\n        }\n\n    } else {\n        $scope.assignment = {type:'idm'};\n    }\n\n    $scope.popup = {\n        assignmentObject: {\n            type:$scope.assignment.type,\n            idm: {\n                type:undefined,\n                assignee: undefined,\n                candidateUsers: [],\n                candidateGroups: []\n            },\n            static: {\n                assignee: undefined,\n                candidateUsers: [],\n                candidateGroups: []\n            }\n        }\n    };\n\n\n    $scope.assignmentOptions = [\n        {id: \"initiator\", title: $translate.instant('PROPERTY.ASSIGNMENT.IDM.DROPDOWN.INITIATOR')},\n        {id: \"user\", title: $translate.instant('PROPERTY.ASSIGNMENT.IDM.DROPDOWN.USER')},\n        {id: \"users\", title: $translate.instant('PROPERTY.ASSIGNMENT.IDM.DROPDOWN.USERS')},\n        {id: \"groups\", title: $translate.instant('PROPERTY.ASSIGNMENT.IDM.DROPDOWN.GROUPS')}\n    ];\n\n    if ($scope.assignment.idm && $scope.assignment.idm.type) {\n        for (var i = 0; i < $scope.assignmentOptions.length; i++) {\n            if ($scope.assignmentOptions[i].id == $scope.assignment.idm.type) {\n                $scope.assignmentOption = $scope.assignmentOptions[i];\n                break;\n            }\n        }\n    }\n\n    // fill the IDM area\n    if (!$scope.assignmentOption) {\n        // Default, first time opening the popup\n        $scope.assignmentOption = $scope.assignmentOptions[0];\n    } else {\n        // Values already filled\n        if ($scope.assignment.idm) { //fill the IDM tab\n            if ($scope.assignment.idm.assignee) {\n                if ($scope.assignment.idm.assignee.id) {\n                    $scope.popup.assignmentObject.idm.assignee = $scope.assignment.idm.assignee;\n                } else {\n                    $scope.popup.assignmentObject.idm.assignee = {email: $scope.assignment.idm.assignee.email};\n                }\n            }\n\n            if ($scope.assignment.idm.candidateUsers && $scope.assignment.idm.candidateUsers.length > 0) {\n                for (var i = 0; i < $scope.assignment.idm.candidateUsers.length; i++) {\n                    $scope.popup.assignmentObject.idm.candidateUsers.push($scope.assignment.idm.candidateUsers[i]);\n                }\n            }\n\n            if ($scope.assignment.idm.candidateGroups && $scope.assignment.idm.candidateGroups.length > 0) {\n                for (var i = 0; i < $scope.assignment.idm.candidateGroups.length; i++) {\n                    $scope.popup.assignmentObject.idm.candidateGroups.push($scope.assignment.idm.candidateGroups[i]);\n                }\n            }\n        }\n    }\n    \n    //fill the static area\n    if ($scope.assignment.assignee) {\n        $scope.popup.assignmentObject.static.assignee = $scope.assignment.assignee;\n    }\n\n    if ($scope.assignment.candidateUsers && $scope.assignment.candidateUsers.length > 0) {\n        for (var i = 0; i < $scope.assignment.candidateUsers.length; i++) {\n            $scope.popup.assignmentObject.static.candidateUsers.push($scope.assignment.candidateUsers[i]);\n        }\n    }\n\n    if ($scope.assignment.candidateGroups && $scope.assignment.candidateGroups.length > 0) {\n        for (var i = 0; i < $scope.assignment.candidateGroups.length; i++) {\n            $scope.popup.assignmentObject.static.candidateGroups.push($scope.assignment.candidateGroups[i]);\n        }\n    }\n\n    initStaticContextForEditing($scope);\n\n    $scope.$watch('popup.groupFilter', function () {\n        $scope.updateGroupFilter();\n    });\n\n    $scope.$watch('popup.filter', function() {\n        $scope.updateFilter();\n    });\n\n    $scope.updateFilter = function() {\n        if ($scope.popup.oldFilter == undefined || $scope.popup.oldFilter != $scope.popup.filter) {\n            if (!$scope.popup.filter) {\n                $scope.popup.oldFilter = '';\n            } else {\n                $scope.popup.oldFilter = $scope.popup.filter;\n            }\n\n            if ($scope.popup.filter !== null && $scope.popup.filter !== undefined) {\n                UserService.getFilteredUsers($scope.popup.filter).then(function (result) {\n                    var filteredUsers = [];\n                    for (var i=0; i<result.data.length; i++) {\n                        var filteredUser = result.data[i];\n\n                        var foundCandidateUser = false;\n                        if ($scope.popup.assignmentObject.idm.candidateUsers !== null && $scope.popup.assignmentObject.idm.candidateUsers !== undefined) {\n                            for (var j=0; j<$scope.popup.assignmentObject.idm.candidateUsers.length; j++) {\n                                var candidateUser = $scope.popup.assignmentObject.idm.candidateUsers[j];\n                                if (candidateUser.id === filteredUser.id) {\n                                    foundCandidateUser = true;\n                                    break;\n                                }\n                            }\n                        }\n\n                        if (!foundCandidateUser) {\n                            filteredUsers.push(filteredUser);\n                        }\n\n                    }\n\n                    $scope.popup.userResults = filteredUsers;\n                    $scope.resetSelection();\n                });\n            }\n        }\n    };\n\n    $scope.updateGroupFilter = function() {\n        if ($scope.popup.oldGroupFilter == undefined || $scope.popup.oldGroupFilter != $scope.popup.groupFilter) {\n            if (!$scope.popup.groupFilter) {\n                $scope.popup.oldGroupFilter = '';\n            } else {\n                $scope.popup.oldGroupFilter = $scope.popup.groupFilter;\n            }\n\n            GroupService.getFilteredGroups($scope.popup.groupFilter).then(function(result) {\n                $scope.popup.groupResults = result.data;\n                $scope.resetGroupSelection();\n            });\n        }\n    };\n\n    $scope.confirmUser = function(user) {\n        if (!user) {\n            // Selection is done with keyboard, use selection index\n            var users = $scope.popup.userResults;\n            if ($scope.popup.selectedIndex >= 0 && $scope.popup.selectedIndex < users.length) {\n                user = users[$scope.popup.selectedIndex];\n            }\n        }\n\n        if (user) {\n            if (\"user\" == $scope.assignmentOption.id) {\n                $scope.popup.assignmentObject.idm.assignee = user;\n            } else if (\"users\" == $scope.assignmentOption.id) {\n\n                // Only add if not yet part of candidate users\n                var found = false;\n                if ($scope.popup.assignmentObject.idm.candidateUsers) {\n                    for (var i = 0; i < $scope.popup.assignmentObject.idm.candidateUsers.length; i++) {\n                        if ($scope.popup.assignmentObject.idm.candidateUsers[i].id === user.id) {\n                            found = true;\n                            break;\n                        }\n                    }\n                }\n\n                if (!found) {\n                    $scope.addCandidateUser(user);\n                }\n            }\n        }\n    };\n\n    $scope.confirmEmail = function() {\n        if (\"user\" == $scope.assignmentOption.id) {\n            $scope.popup.assignmentObject.idm.assignee = {email: $scope.popup.email};\n        } else if (\"users\" == $scope.assignmentOption.id) {\n\n            // Only add if not yet part of candidate users\n            var found = false;\n            if ($scope.popup.assignmentObject.idm.candidateUsers) {\n                for (var i = 0; i < $scope.popup.assignmentObject.idm.candidateUsers.length; i++) {\n\n                    if ($scope.popup.assignmentObject.idm.candidateUsers[i].id) {\n                        if ($scope.popup.assignmentObject.idm.candidateUsers[i].id === user.id) {\n                            found = true;\n                            break;\n                        }\n                    } else if ($scope.popup.assignmentObject.idm.candidateUsers[i].email) {\n                        if ($scope.popup.assignmentObject.idm.candidateUsers[i].email === $scope.popup.email) {\n                            found = true;\n                            break;\n                        }\n                    }\n                }\n            }\n\n            if (!found) {\n                $scope.addCandidateUser({email: $scope.popup.email});\n            }\n        }\n    };\n\n    $scope.confirmGroup = function(group) {\n        if (!group) {\n            // Selection is done with keyboard, use selection index\n            var groups = $scope.popup.groupResults;\n            if ($scope.popup.selectedGroupIndex >= 0 && $scope.popup.selectedGroupIndex < groups.length) {\n                group = groups[$scope.popup.selectedGroupIndex];\n            }\n        }\n\n        if (group) {\n            // Only add if not yet part of candidate groups\n            var found = false;\n            if ($scope.popup.assignmentObject.idm.candidateGroups) {\n                for (var i = 0; i < $scope.popup.assignmentObject.idm.candidateGroups.length; i++) {\n                    if ($scope.popup.assignmentObject.idm.candidateGroups[i].id === group.id) {\n                        found = true;\n                        break;\n                    }\n                }\n            }\n\n            if (!found) {\n                $scope.addCandidateGroup(group);\n            }\n        }\n    };\n\n    $scope.addCandidateUser = function(user) {\n        $scope.popup.assignmentObject.idm.candidateUsers.push(user);\n    };\n    \n    $scope.removeCandidateUser = function(user) {\n        var users = $scope.popup.assignmentObject.idm.candidateUsers;\n        var indexToRemove = -1;\n        for (var i = 0; i < users.length; i++) {\n            if (user.id) {\n                if (user.id === users[i].id) {\n                    indexToRemove = i;\n                    break;\n                }\n            } else {\n                if (user.email === users[i].email) {\n                    indexToRemove = i;\n                    break;\n                }\n            }\n        }\n        if (indexToRemove >= 0) {\n            users.splice(indexToRemove, 1);\n        }\n    };\n    \n    $scope.addCandidateGroup = function(group) {\n        $scope.popup.assignmentObject.idm.candidateGroups.push(group);\n    };\n    \n    $scope.removeCandidateGroup = function(group) {\n        var groups = $scope.popup.assignmentObject.idm.candidateGroups;\n        var indexToRemove = -1;\n        for (var i = 0; i < groups.length; i++) {\n            if (group.id == groups[i].id) {\n                indexToRemove = i;\n                break;\n            }\n        }\n        if (indexToRemove >= 0) {\n            groups.splice(indexToRemove, 1);\n        }\n    };\n\n    $scope.resetSelection = function() {\n        if ($scope.popup.userResults && $scope.popup.userResults.length > 0) {\n            $scope.popup.selectedIndex = 0;\n        } else {\n            $scope.popup.selectedIndex = -1;\n        }\n    };\n\n    $scope.nextUser = function() {\n        var users = $scope.popup.userResults;\n        if (users && users.length > 0 && $scope.popup.selectedIndex < users.length -1) {\n            $scope.popup.selectedIndex += 1;\n        }\n    };\n\n    $scope.previousUser = function() {\n        var users = $scope.popup.userResults;\n        if (users && users.length > 0 && $scope.popup.selectedIndex > 0) {\n            $scope.popup.selectedIndex -= 1;\n        }\n    };\n\n    $scope.resetGroupSelection = function() {\n        if ($scope.popup.groupResults && $scope.popup.groupResults.length > 0) {\n            $scope.popup.selectedGroupIndex = 0;\n        } else {\n            $scope.popup.selectedGroupIndex = -1;\n        }\n    };\n\n    $scope.nextGroup = function() {\n        var groups = $scope.popup.groupResults;\n        if (groups && groups.length > 0 && $scope.popup.selectedGroupIndex < groups.length -1) {\n            $scope.popup.selectedGroupIndex += 1;\n        }\n    };\n\n    $scope.previousGroup = function() {\n        var groups = $scope.popup.groupResults;\n        if (groups && groups.length > 0 && $scope.popup.selectedGroupIndex > 0) {\n            $scope.popup.selectedGroupIndex -= 1;\n        }\n    };\n\n    $scope.removeAssignee = function() {\n        $scope.popup.assignmentObject.idm.assignee = undefined;\n    };\n    \n    // Click handler for + button after enum value\n    $scope.addCandidateUserValue = function(index) {\n        $scope.popup.assignmentObject.static.candidateUsers.splice(index + 1, 0, {value: ''});\n    };\n\n    // Click handler for - button after enum value\n    $scope.removeCandidateUserValue = function(index) {\n        $scope.popup.assignmentObject.static.candidateUsers.splice(index, 1);\n    };\n\n    // Click handler for + button after enum value\n    $scope.addCandidateGroupValue = function(index) {\n        $scope.popup.assignmentObject.static.candidateGroups.splice(index + 1, 0, {value: ''});\n    };\n\n    // Click handler for - button after enum value\n    $scope.removeCandidateGroupValue = function(index) {\n        $scope.popup.assignmentObject.static.candidateGroups.splice(index, 1);\n    };\n    \n    $scope.setSearchType = function() {\n        $scope.popup.assignmentObject.assignmentSourceType = 'search';\n    };\n\n    $scope.allSteps = EDITOR.UTIL.collectSortedElementsFromPrecedingElements($scope.selectedShape);\n\n    $scope.save = function () {\n\n        handleAssignmentInput($scope.popup.assignmentObject.static);\n\n        $scope.assignment.type = $scope.popup.assignmentObject.type;\n\n        if ('idm' === $scope.popup.assignmentObject.type) { // IDM\n            $scope.popup.assignmentObject.static = undefined;\n\n            //Construct an IDM object to be saved to the process model.\n            var idm = {type: $scope.assignmentOption.id};\n            if ('user' == idm.type) {\n                if ($scope.popup.assignmentObject.idm.assignee) {\n                    idm.assignee = $scope.popup.assignmentObject.idm.assignee;\n                }\n            } else if ('users' == idm.type) {\n                if ($scope.popup.assignmentObject.idm.candidateUsers && $scope.popup.assignmentObject.idm.candidateUsers.length > 0) {\n                    idm.candidateUsers = $scope.popup.assignmentObject.idm.candidateUsers;\n                }\n            } else if ('groups' == idm.type) {\n                if ($scope.popup.assignmentObject.idm.candidateGroups && $scope.popup.assignmentObject.idm.candidateGroups.length > 0) {\n                    idm.candidateGroups = $scope.popup.assignmentObject.idm.candidateGroups;\n                }\n            }\n            $scope.assignment.idm = idm;\n            $scope.assignment.assignee = undefined;\n            $scope.assignment.candidateUsers = undefined;\n            $scope.assignment.candidateGroups = undefined;\n\n        }\n\n        if ('static' === $scope.popup.assignmentObject.type) { // IDM\n            $scope.popup.assignmentObject.idm = undefined;\n            $scope.assignment.idm = undefined;\n            $scope.assignment.assignee = $scope.popup.assignmentObject.static.assignee;\n            $scope.assignment.candidateUsers = $scope.popup.assignmentObject.static.candidateUsers;\n            $scope.assignment.candidateGroups = $scope.popup.assignmentObject.static.candidateGroups;\n        }\n\n        $scope.property.value = {};\n        $scope.property.value.assignment = $scope.assignment;\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\n    var handleAssignmentInput = function ($assignment) {\n    \n        function isEmptyString(value) {\n          return (value === undefined || value === null || value.trim().length === 0);\n        }\n    \n        if (isEmptyString($assignment.assignee)){\n          $assignment.assignee = undefined;\n        }\n        var toRemoveIndexes;\n        var removedItems=0;\n        var i = 0;\n        if ($assignment.candidateUsers) {\n          toRemoveIndexes = [];\n          for (i = 0; i < $assignment.candidateUsers.length; i++) {\n            if (isEmptyString($assignment.candidateUsers[i].value)) {\n              toRemoveIndexes[toRemoveIndexes.length] = i;\n            }\n          }\n    \n          if (toRemoveIndexes.length == $assignment.candidateUsers.length) {\n            $assignment.candidateUsers = undefined;\n          } else {\n             removedItems=0;\n            for (i = 0; i < toRemoveIndexes.length; i++) {\n              $assignment.candidateUsers.splice(toRemoveIndexes[i]-removedItems, 1);\n              removedItems++;\n            }\n          }\n        }\n    \n        if ($assignment.candidateGroups) {\n          toRemoveIndexes = [];\n          for (i = 0; i < $assignment.candidateGroups.length; i++) {\n            if (isEmptyString($assignment.candidateGroups[i].value)) {\n              toRemoveIndexes[toRemoveIndexes.length] = i;\n            }\n          }\n    \n          if (toRemoveIndexes.length == $assignment.candidateGroups.length) {\n            $assignment.candidateGroups = undefined;\n          } else {\n             removedItems=0;\n            for (i = 0; i < toRemoveIndexes.length; i++) {\n              $assignment.candidateGroups.splice(toRemoveIndexes[i]-removedItems, 1);\n              removedItems++;\n            }\n          }\n        }\n    };\n    \n    function initStaticContextForEditing($scope) {\n        if (!$scope.popup.assignmentObject.static.candidateUsers || $scope.popup.assignmentObject.static.candidateUsers.length==0) {\n          $scope.popup.assignmentObject.static.candidateUsers = [{value: ''}];\n        }\n        if (!$scope.popup.assignmentObject.static.candidateGroups || $scope.popup.assignmentObject.static.candidateGroups.length==0) {\n          $scope.popup.assignmentObject.static.candidateGroups = [{value: ''}];\n        }\n    }\n}]);\n"
  },
  {
    "path": "flowable-ui-web/modeler/editor-app/configuration/properties-calledelementtype-controller.js",
    "content": "/* Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n * \n *      http://www.apache.org/licenses/LICENSE-2.0\n * \n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/*\n * Call activity calledElement type property\n */\n\nangular.module('flowableModeler').controller('FlowableCalledElementTypeCtrl', [ '$scope', function($scope) {\n\n    if ($scope.property.value == undefined && $scope.property.value == null)\n    {\n    \t$scope.property.value = 'key';\n    }\n        \n    $scope.calledElementTypeChanged = function() {\n    \t$scope.updatePropertyInModel($scope.property);\n    };\n}]);"
  },
  {
    "path": "flowable-ui-web/modeler/editor-app/configuration/properties-case-reference-controller.js",
    "content": "/* 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\nangular.module('flowableModeler').controller('FlowableCaseReferenceCtrl',\n    [ '$scope', '$modal', '$http', function($scope, $modal, $http) {\n\t\n     // Config for the modal window\n     var opts = {\n         template:  'editor-app/configuration/properties/case-reference-popup.html?version=' + Date.now(),\n         scope: $scope\n     };\n\n     // Open the dialog\n        _internalCreateModal(opts, $modal, $scope);\n}]);\n\nangular.module('flowableModeler').controller('FlowableCaseReferencePopupCtrl', [ '$scope', '$http', 'editorManager', function($scope, $http, editorManager) {\n\t\n    $scope.state = {'loadingCases' : true, 'error' : false};\n    \n    // Close button handler\n    $scope.close = function() {\n    \t$scope.property.mode = 'read';\n        $scope.$hide();\n    };\n    \n    // Selecting/deselecting a case\n    $scope.selectCase = function(caseModel, $event) {\n   \t \t$event.stopPropagation();\n   \t \tif ($scope.selectedCase && $scope.selectedCase.id && caseModel.id == $scope.selectedCase.id) {\n   \t \t\t// un-select the current selection\n   \t \t\t$scope.selectedCase = null;\n   \t \t} else {\n   \t \t\t$scope.selectedCase = caseModel;\n   \t \t}\n    };\n    \n    // Saving the selected value\n    $scope.save = function() {\n   \t \tif ($scope.selectedCase) {\n   \t \t\t$scope.property.value = {'id' : $scope.selectedCase.id, 'name' : $scope.selectedCase.name};\n   \t \t} else {\n   \t \t\t$scope.property.value = null; \n   \t \t}\n   \t \t$scope.updatePropertyInModel($scope.property);\n   \t \t$scope.close();\n    };\n    \n    $scope.loadCases = function() {\n   \t    var modelMetaData = editorManager.getBaseModelData();\n    \t$http.get(FLOWABLE.APP_URL.getCaseModelsUrl('?excludeId=' + modelMetaData.modelId))\n    \t\t.success(\n    \t\t\tfunction(response) {\n    \t\t\t\t$scope.state.loadingCases = false;\n    \t\t\t\t$scope.state.caseError = false;\n    \t\t\t\t$scope.caseModels = response.data;\n    \t\t\t})\n    \t\t.error(\n    \t\t\tfunction(data, status, headers, config) {\n    \t\t\t\t$scope.state.loadingCases = false;\n    \t\t\t\t$scope.state.caseError = true;\n    \t\t\t});\n    };\n    \n    if ($scope.property && $scope.property.value && $scope.property.value.id) {\n   \t \t$scope.selectedCase = $scope.property.value;\n    }\n    \n    $scope.loadCases();  \n}]);\n"
  },
  {
    "path": "flowable-ui-web/modeler/editor-app/configuration/properties-condition-expression-controller.js",
    "content": "/* Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n * \n *      http://www.apache.org/licenses/LICENSE-2.0\n * \n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/*\n * Condition expression\n */\n\nangular.module('flowableModeler').controller('FlowableConditionExpressionCtrl', [ '$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    _internalCreateModal(opts, $modal, $scope);\n}]);\n\nangular.module('flowableModeler').controller('FlowableConditionExpressionPopupCtrl',\n    [ '$rootScope', '$scope', '$translate', 'FormBuilderService', function($rootScope, $scope, $translate, FormBuilderService) {\n    \t\n    // Put json representing assignment on scope\n    if ($scope.property.value !== undefined && $scope.property.value !== null\n        && $scope.property.value.expression !== undefined\n        && $scope.property.value.expression !== null) {\n\n        $scope.expression = $scope.property.value.expression;\n\n    } else if ($scope.property.value !== undefined && $scope.property.value !== null) {\n        $scope.expression = {type: 'static', staticValue: $scope.property.value};\n        \n    } else {\n        $scope.expression = {};\n    }\n\n    $scope.save = function() {\n        $scope.property.value = {expression: $scope.expression};\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\n}]);"
  },
  {
    "path": "flowable-ui-web/modeler/editor-app/configuration/properties-custom-controllers.js",
    "content": "/* 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"
  },
  {
    "path": "flowable-ui-web/modeler/editor-app/configuration/properties-data-properties-controller.js",
    "content": "/* Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n * \n *      http://www.apache.org/licenses/LICENSE-2.0\n * \n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/*\n * Data Properties\n */\n\nangular.module('flowableModeler').controller('FlowableDataPropertiesCtrl',\n    ['$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/data-properties-popup.html?version=' + Date.now(),\n            scope: $scope\n        };\n\n        // Open the dialog\n        _internalCreateModal(opts, $modal, $scope);\n    }]);\n\nangular.module('flowableModeler').controller('FlowableDataPropertiesPopupCtrl',\n    ['$scope', '$q', '$translate', '$timeout', function ($scope, $q, $translate, $timeout) {\n\n        // Put json representing data properties on scope\n        if ($scope.property.value !== undefined && $scope.property.value !== null\n            && $scope.property.value.items !== undefined\n            && $scope.property.value.items !== 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.dataProperties = angular.copy($scope.property.value.items);\n            \n            for (var i = 0; i < $scope.dataProperties.length; i++) {\n\t\t\t    var dataProperty = $scope.dataProperties[i];\n\t\t\t    if (dataProperty.enumValues && dataProperty.enumValues.length > 0) {\n\t\t\t\t    for (var j = 0; j < dataProperty.enumValues.length; j++) {\n\t\t\t\t\t    var enumValue = dataProperty.enumValues[j];\n\t\t\t\t\t    if (!enumValue.id && !enumValue.name && enumValue.value) {\n\t\t\t\t\t\t    enumValue.id = enumValue.value;\n\t\t\t\t\t\t    enumValue.name = enumValue.value;\n\t\t\t\t\t    }\n\t\t\t\t    }\n\t\t\t    }\n\t\t\t}\n            \n        } else {\n            $scope.dataProperties = [];\n        }\n        \n        $scope.enumValues = [];\n\n        $scope.translationsRetrieved = false;\n\n        $scope.labels = {};\n\n        var idPromise = $translate('PROPERTY.DATAPROPERTIES.ID');\n        var namePromise = $translate('PROPERTY.DATAPROPERTIES.NAME');\n        var typePromise = $translate('PROPERTY.DATAPROPERTIES.TYPE');\n        var valuePromise = $translate('PROPERTY.DATAPROPERTIES.VALUE');\n\n        $q.all([idPromise, namePromise, typePromise, valuePromise]).then(function (results) {\n            $scope.labels.idLabel = results[0];\n            $scope.labels.nameLabel = results[1];\n            $scope.labels.typeLabel = results[2];\n            $scope.labels.valueLabel = results[3];\n            $scope.translationsRetrieved = true;\n\n            // Config for grid\n            $scope.gridOptions = {\n                data: $scope.dataProperties,\n                headerRowHeight: 28,\n                enableRowSelection: true,\n                enableRowHeaderSelection: false,\n                multiSelect: false,\n                modifierKeysToMultiSelect: false,\n                enableHorizontalScrollbar: 0,\n                enableColumnMenus: false,\n                enableSorting: false,\n                columnDefs: [{field: 'dataproperty_id', displayName: $scope.labels.idLabel},\n                    {field: 'dataproperty_name', displayName: $scope.labels.nameLabel},\n                    {field: 'dataproperty_type', displayName: $scope.labels.typeLabel},\n                    {field: 'dataproperty_value', displayName: $scope.labels.valueLabel}]\n            };\n            \n            $scope.enumGridOptions = {\n    \t\t    data: $scope.enumValues,\n                headerRowHeight: 28,\n                enableRowSelection: true,\n                enableRowHeaderSelection: false,\n                multiSelect: false,\n                modifierKeysToMultiSelect: false,\n                enableHorizontalScrollbar: 0,\n                enableColumnMenus: false,\n                enableSorting: false,\n                columnDefs: [{ field: 'id', displayName: $scope.labels.idLabel },\n                { field: 'name', displayName: $scope.labels.nameLabel}]\n            }\n\n            $scope.gridOptions.onRegisterApi = function (gridApi) {\n                //set gridApi on scope\n                $scope.gridApi = gridApi;\n                gridApi.selection.on.rowSelectionChanged($scope, function (row) {\n                    $scope.selectedProperty = row.entity;\n                    $scope.selectedEnumValue = undefined;\n                    if ($scope.selectedProperty && $scope.selectedProperty.enumValues) {\n                        $scope.enumValues.length = 0;\n                        for (var i = 0; i < $scope.selectedProperty.enumValues.length; i++) {\n                            $scope.enumValues.push($scope.selectedProperty.enumValues[i]);\n                        }\n                    }\n                });\n            };\n            \n            $scope.enumGridOptions.onRegisterApi = function (gridApi) {\n                //set gridApi on scope\n                $scope.enumGridApi = gridApi;\n                gridApi.selection.on.rowSelectionChanged($scope, function (row) {\n                    $scope.selectedEnumValue = row.entity;\n                });\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.selectedProperty.type === 'date') {\n                $scope.selectedProperty.datePattern = 'MM-dd-yyyy hh:mm';\n            } else {\n                delete $scope.selectedProperty.datePattern;\n            }\n\n            // Check enum. If enum, show list of options\n            if ($scope.selectedProperty.type === 'enum') {\n                $scope.selectedProperty.enumValues = [ {id: 'value1', name: 'Value 1'}, {id: 'value2', name: 'Value 2'}];\n                $scope.enumValues.length = 0;\n                for (var i = 0; i < $scope.selectedProperty.enumValues.length; i++) {\n                    $scope.enumValues.push($scope.selectedProperty.enumValues[i]);\n                }\n                \n            } else {\n                delete $scope.selectedProperty.enumValues;\n                $scope.enumValues.length = 0;\n            }\n        };\n\n        // Click handler for add button\n        var propertyIndex = 1;\n        $scope.addNewProperty = function () {\n            var newProperty = {\n                dataproperty_id: 'new_data_object_' + propertyIndex++,\n                dataproperty_name: '',\n                dataproperty_type: 'string',\n                readable: true,\n                writable: true\n            };\n\n            $scope.dataProperties.push(newProperty);\n\n            $timeout(function () {\n                $scope.gridApi.selection.toggleRowSelection(newProperty);\n            });\n        };\n\n        // Click handler for remove button\n        $scope.removeProperty = function () {\n            var selectedItems = $scope.gridApi.selection.getSelectedRows();\n            if (selectedItems && selectedItems.length > 0) {\n                var index = $scope.dataProperties.indexOf(selectedItems[0]);\n                $scope.gridApi.selection.toggleRowSelection(selectedItems[0]);\n                $scope.dataProperties.splice(index, 1);\n\n                if ($scope.dataProperties.length == 0) {\n                    $scope.selectedProperty = undefined;\n                }\n\n                $timeout(function() {\n                    if ($scope.dataProperties.length > 0) {\n                        $scope.gridApi.selection.toggleRowSelection($scope.dataProperties[0]);\n                    }\n                });\n            }\n        };\n\n        // Click handler for up button\n        $scope.movePropertyUp = function () {\n            var selectedItems = $scope.gridApi.selection.getSelectedRows();\n            if (selectedItems && selectedItems.length > 0) {\n                var index = $scope.dataProperties.indexOf(selectedItems[0]);\n                if (index != 0) { // If it's the first, no moving up of course\n                    var temp = $scope.dataProperties[index];\n                    $scope.dataProperties.splice(index, 1);\n                    $timeout(function(){\n                        $scope.dataProperties.splice(index + -1, 0, temp);\n                        $timeout(function() {\n                            $scope.gridApi.selection.toggleRowSelection(temp);\n                        });\n                    });\n                }\n            }\n        };\n\n        // Click handler for down button\n        $scope.movePropertyDown = function () {\n            var selectedItems = $scope.gridApi.selection.getSelectedRows();\n            if (selectedItems && selectedItems.length > 0) {\n                var index = $scope.dataProperties.indexOf(selectedItems[0]);\n                if (index != $scope.dataProperties.length - 1) { // If it's the last element, no moving down of course\n                    var temp = $scope.dataProperties[index];\n                    $scope.dataProperties.splice(index, 1);\n                    $timeout(function(){\n                        $scope.dataProperties.splice(index + 1, 0, temp);\n                        $timeout(function() {\n                            $scope.gridApi.selection.toggleRowSelection(temp);\n                        });\n                    });\n                }\n            }\n        };\n        \n        $scope.addNewEnumValue = function() {\n            if ($scope.selectedProperty) {\n        \t    var newEnumValue = { id : '', name : ''};\n        \t    $scope.selectedProperty.enumValues.push(newEnumValue);\n        \t    $scope.enumValues.push(newEnumValue);\n    \t       \n    \t        $timeout(function () {\n                    $scope.enumGridApi.selection.toggleRowSelection(newEnumValue);\n                });\n        \t}\n        };\n\n        // Click handler for remove button\n        $scope.removeEnumValue = function() {\n            var selectedItems = $scope.enumGridApi.selection.getSelectedRows();\n            if (selectedItems && selectedItems.length > 0) {\n                var index = $scope.enumValues.indexOf(selectedItems[0]);\n                $scope.enumGridApi.selection.toggleRowSelection(selectedItems[0]);\n\n                $scope.enumValues.splice(index, 1);\n                $scope.selectedProperty.enumValues.splice(index, 1);\n\n                if ($scope.enumValues.length == 0) {\n                    $scope.selectedEnumValue = undefined;\n                }\n\n                $timeout(function () {\n                    if ($scope.enumValues.length > 0) {\n                        $scope.enumGridApi.selection.toggleRowSelection($scope.enumValues[0]);\n                    }\n                });\n            }\n        };\n    \n        // Click handler for up button\n        $scope.moveEnumValueUp = function() {\n            var selectedItems = $scope.enumGridApi.selection.getSelectedRows();\n            if (selectedItems && selectedItems.length > 0) {\n                var index = $scope.enumValues.indexOf(selectedItems[0]);\n                if (index != 0) { // If it's the first, no moving up of course\n                    var temp = $scope.enumValues[index];\n                    $scope.enumValues.splice(index, 1);\n                    $scope.selectedProperty.enumValues.splice(index, 1);\n                    $timeout(function () {\n                        $scope.enumValues.splice(index + -1, 0, temp);\n                        $scope.selectedProperty.enumValues.splice(index + -1, 0, temp);\n                        $timeout(function () {\n                            $scope.enumGridApi.selection.toggleRowSelection(temp);\n                        });\n                    });\n                }\n            }\n        };\n    \n        // Click handler for down button\n        $scope.moveEnumValueDown = function() {\n            var selectedItems = $scope.enumGridApi.selection.getSelectedRows();\n            if (selectedItems && selectedItems.length > 0) {\n                var index = $scope.enumValues.indexOf(selectedItems[0]);\n                if (index != $scope.enumValues.length - 1) { // If it's the last element, no moving down of course\n                    var temp = $scope.enumValues[index];\n                    $scope.enumValues.splice(index, 1);\n                    $scope.selectedProperty.enumValues.splice(index, 1);\n                    $timeout(function () {\n                        $scope.enumValues.splice(index + 1, 0, temp);\n                        $scope.selectedProperty.enumValues.splice(index + 1, 0, temp);\n                        $timeout(function () {\n                            $scope.enumGridApi.selection.toggleRowSelection(temp);\n                        });\n                    });\n                }\n            }\n        };\n\n        // Click handler for save button\n        $scope.save = function () {\n\n            if ($scope.dataProperties.length > 0) {\n                $scope.property.value = {};\n                $scope.property.value.items = $scope.dataProperties;\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    }])\n;"
  },
  {
    "path": "flowable-ui-web/modeler/editor-app/configuration/properties-decisiontable-reference-controller.js",
    "content": "/* 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\nangular.module('flowableModeler').controller('FlowableDecisionTableReferenceCtrl',\n    [ '$scope', '$modal', '$http', function($scope, $modal, $http) {\n\n     // Config for the modal window\n     var opts = {\n         template:  'editor-app/configuration/properties/decisiontable-reference-popup.html?version=' + Date.now(),\n         scope: $scope\n     };\n\n     // Open the dialog\n     _internalCreateModal(opts, $modal, $scope);\n}]);\n\nangular.module('flowableModeler').controller('FlowableDecisionTableReferencePopupCtrl', ['$rootScope', '$scope', '$http', '$location', 'editorManager',\n    function($rootScope, $scope, $http, $location, editorManager) {\n\n        $scope.state = {\n            'loadingDecisionTables': true,\n            'decisionTableError': false\n        };\n\n        $scope.popup = {\n            'state': 'decisionTableReference'\n        };\n\n        $scope.foldersBreadCrumbs = [];\n\n        // Make click outside dialog also call close.\n        $scope.$parent.$on('modal.hide.before', function() {\n            $scope.close();\n            $scope.$parent.$apply();\n        });\n\n        // Close button handler\n        $scope.close = function() {\n            $scope.property.newVariablesMapping = undefined;\n            $scope.property.mode = 'read';\n            $scope.$hide();\n        };\n\n        // Selecting/deselecting a decision table\n        $scope.selectDecisionTable = function(decisionTable, $event) {\n            $event.stopPropagation();\n            if ($scope.selectedDecisionTable && $scope.selectedDecisionTable.id && decisionTable.id == $scope.selectedDecisionTable.id) {\n                // un-select the current selection\n                $scope.selectedDecisionTable = null;\n            } else {\n                $scope.selectedDecisionTable = decisionTable;\n            }\n        };\n\n        $scope.isSelected = function () {\n            if ($scope.selectedDecisionTable && $scope.selectedDecisionTable.id) {\n                return true;\n            }\n            return false;\n        };\n\n        // Saving the selected value\n        $scope.save = function() {\n            if ($scope.selectedDecisionTable) {\n                $scope.property.value = {\n                    'id': $scope.selectedDecisionTable.id,\n                    'name': $scope.selectedDecisionTable.name,\n                    'key': $scope.selectedDecisionTable.key\n                };\n\n            } else {\n                $scope.property.value = null;\n            }\n            $scope.updatePropertyInModel($scope.property);\n            $scope.close();\n        };\n\n        // Open the selected value\n        $scope.open = function() {\n            if ($scope.selectedDecisionTable) {\n                $scope.property.value = {\n                    'id': $scope.selectedDecisionTable.id,\n                    'name': $scope.selectedDecisionTable.name,\n                    'key': $scope.selectedDecisionTable.key\n                };\n                $scope.updatePropertyInModel($scope.property);\n\n                var modelMetaData = editorManager.getBaseModelData();\n                var json = editorManager.getModel();\n                json = JSON.stringify(json);\n\n                var params = {\n                    modeltype: modelMetaData.model.modelType,\n                    json_xml: json,\n                    name: modelMetaData.name,\n                    key: modelMetaData.key,\n                    description: modelMetaData.description,\n                    newversion: false,\n                    lastUpdated: modelMetaData.lastUpdated\n                };\n\n                // Update\n                $http({\n                    method: 'POST',\n                    data: params,\n                    ignoreErrors: true,\n                    headers: {\n                        'Accept': 'application/json',\n                        'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'\n                    },\n                    transformRequest: function (obj) {\n\t                    var str = [];\n\t                    for (var p in obj) {\n\t                        str.push(encodeURIComponent(p) + \"=\" + encodeURIComponent(obj[p]));\n\t                    }\n\t                    return str.join(\"&\");\n\t                },\n                    url: FLOWABLE.URL.putModel(modelMetaData.modelId)\n                })\n\n                .success(function(data, status, headers, config) {\n                        editorManager.handleEvents({\n                            type: ORYX.CONFIG.EVENT_SAVED\n                        });\n\n\t\t\t\t\t\t$rootScope.addHistoryItem($scope.selectedShape.resourceId);\n\t\t\t\t\t\t$location.path('decision-table-editor/' + $scope.selectedDecisionTable.id);\n                    })\n                    .error(function(data, status, headers, config) {\n\n                    });\n\n                $scope.close();\n            }\n        };\n\n        $scope.newDecisionTable = function() {\n            $scope.property.value.variablesmapping = [];\n\n            $scope.popup.state = 'newDecisionTable';\n\n            var modelMetaData = editorManager.getBaseModelData();\n\n            $scope.model = {\n                loading: false,\n                decisionTable: {\n                    name: '',\n                    key: '',\n                    description: '',\n                    modelType: 4\n                },\n                defaultStencilSet: undefined,\n                decisionTableStencilSets: []\n            };\n        };\n\n        $scope.createDecisionTable = function() {\n\n            if (!$scope.model.decisionTable.name || $scope.model.decisionTable.name.length == 0 ||\n            \t!$scope.model.decisionTable.key || $scope.model.decisionTable.key.length == 0) {\n\n                return;\n            }\n\n            var stencilSetId = $scope.model.decisionTable.stencilSet;\n            $scope.model.loading = true;\n\n            $http({\n                method: 'POST',\n                url: FLOWABLE.APP_URL.getModelsUrl(),\n                data: $scope.model.decisionTable\n            }).\n            success(function(data, status, headers, config) {\n\n                var newDecisionTableId = data.id;\n                $scope.property.value = {\n                    'id': newDecisionTableId,\n                    'name': data.name,\n                    'key': data.key\n                };\n                $scope.updatePropertyInModel($scope.property);\n\n                var modelMetaData = editorManager.getBaseModelData();\n                var json = editorManager.getModel();\n                json = JSON.stringify(json);\n\n                var params = {\n                    modeltype: modelMetaData.model.modelType,\n                    json_xml: json,\n                    name: modelMetaData.name,\n                    key: modelMetaData.key,\n                    description: modelMetaData.description,\n                    newversion: false,\n                    lastUpdated: modelMetaData.lastUpdated,\n                    stencilSet: stencilSetId\n                };\n\n                // Update\n                $http({\n                    method: 'POST',\n                    data: params,\n                    ignoreErrors: true,\n                    headers: {\n                        'Accept': 'application/json',\n                        'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'\n                    },\n                    transformRequest: function (obj) {\n\t                    var str = [];\n\t                    for (var p in obj) {\n\t                        str.push(encodeURIComponent(p) + \"=\" + encodeURIComponent(obj[p]));\n\t                    }\n\t                    return str.join(\"&\");\n\t                },\n                    url: FLOWABLE.URL.putModel(modelMetaData.modelId)\n                })\n\n                .success(function(data, status, headers, config) {\n                        editorManager.handleEvents({\n                            type: ORYX.CONFIG.EVENT_SAVED\n                        });\n\n                        $scope.model.loading = false;\n                        $scope.$hide();\n\n                        $rootScope.addHistoryItem($scope.selectedShape.resourceId);\n                        $location.path('decision-table-editor/' + newDecisionTableId);\n                    })\n                    .error(function(data, status, headers, config) {\n                        $scope.model.loading = false;\n                        $scope.$hide();\n                    });\n\n            }).\n            error(function(data, status, headers, config) {\n                $scope.model.loading = false;\n                $scope.model.errorMessage = data.message;\n            });\n        };\n\n        $scope.cancel = function() {\n            $scope.close();\n        };\n\n        $scope.resetCurrent = function () {\n            for (var i = 0, found = false; i < $scope.decisionTables.length && found === false; i++) {\n                var table = $scope.decisionTables[i];\n                if (table.id === $scope.property.value.id) {\n                    $scope.selectedDecisionTable = table;\n                    found = true;\n                }\n            }\n        };\n\n        $scope.loadDecisionTables = function() {\n            var modelMetaData = editorManager.getBaseModelData();\n            $http.get(FLOWABLE.APP_URL.getDecisionTableModelsUrl())\n                .success(\n                    function(response) {\n                        $scope.state.loadingDecisionTables = false;\n                        $scope.state.decisionTableError = false;\n                        $scope.decisionTables = response.data;\n                        $scope.resetCurrent();\n                    })\n                .error(\n                    function(data, status, headers, config) {\n                        $scope.state.loadingDecisionTables = false;\n                        $scope.state.decisionTableError = true;\n                    });\n        };\n\n        if ($scope.property && $scope.property.value && $scope.property.value.id) {\n            $scope.selectedDecisionTable = $scope.property.value;\n            $scope.storedId = $scope.property.value.id;\n        }\n\n        $scope.loadDecisionTables();\n    }\n]);\n"
  },
  {
    "path": "flowable-ui-web/modeler/editor-app/configuration/properties-default-controllers.js",
    "content": "/* Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n * \n *      http://www.apache.org/licenses/LICENSE-2.0\n * \n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/*\n * String controller\n */\n\nangular.module('flowableModeler').controller('FlowableStringPropertyCtrl', [ '$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        // if enter is pressed\n        if (keyEvent && keyEvent.which === 13) {\n            keyEvent.preventDefault();\n            $scope.inputBlurred(); // we want to do the same as if the user would blur the input field\n        }\n        // else; do nothing\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\nangular.module('flowableModeler').controller('FlowableBooleanPropertyCtrl', ['$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.get('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\nangular.module('flowableModeler').controller('FlowableTextPropertyCtrl', [ '$scope', '$modal', '$timeout', function($scope, $modal, $timeout) {\n\n    var opts = {\n        template:  'editor-app/configuration/properties/text-popup.html?version=' + Date.now(),\n        scope: $scope,\n        prefixEvent: 'textModalEvent'\n    };\n    \n     $scope.$on('textModalEvent.hide.before', function() {\n        $timeout(function() {\n            $scope.property.mode = 'read';\n        }, 0);\n    });\n    \n    // Open the dialog\n    _internalCreateModal(opts, $modal, $scope);\n}]);\n\nangular.module('flowableModeler').controller('FlowableTextPropertyPopupCtrl', ['$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": "flowable-ui-web/modeler/editor-app/configuration/properties-duedate-controller.js",
    "content": "/* Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n * \n *      http://www.apache.org/licenses/LICENSE-2.0\n * \n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/*\n * Due date\n */\n'use strict';\n\nangular.module('flowableModeler').controller('BpmnEditorDueDateCtrl', [ '$scope', '$modal', function($scope, $modal) {\n\n    // Config for the modal window\n    var opts = {\n        template: 'editor-app/configuration/properties/duedate-popup.html?version=' + Date.now(),\n        scope: $scope\n    };\n\n    // Open the dialog\n    _internalCreateModal(opts, $modal, $scope);\n}]);\n\nangular.module('flowableModeler').controller('BpmnEditorDueDatePopupCtrl',\n    [ '$rootScope', '$scope', '$translate', function($rootScope, $scope, $translate) {\n\n    // Put json representing assignment on scope\n    if ($scope.property.value !== undefined && $scope.property.value !== null) {\n    \n        if ($scope.property.value.duedate !== undefined && $scope.property.value.duedate !== null) {\n            $scope.popup = {'duedate': $scope.property.value.duedate};\n        \n        } else if ($scope.property.value.duedateExpression !== undefined && $scope.property.value.duedateExpression !== null) {\n            $scope.popup = {'duedateExpression': $scope.property.value.duedateExpression};\n            \n        } else {\n            $scope.popup = {'duedateExpression': $scope.property.value};\n        }\n    \n    } else {\n        $scope.popup = {};\n    }\n    \n    $scope.taskDueDateOptions = [\n        {id: \"none\", title: $translate.instant('PROPERTY.DUEDATE.TASK-DUE-DATE-OPTIONS.NO-DUEDATE')},\n        {id: \"expression\", title: $translate.instant('PROPERTY.DUEDATE.TASK-DUE-DATE-OPTIONS.EXPRESSION')},\n        {id: \"static\", title: $translate.instant('PROPERTY.DUEDATE.TASK-DUE-DATE-OPTIONS.STATIC')},\n        {id: \"field\", title: $translate.instant('PROPERTY.DUEDATE.TASK-DUE-DATE-OPTIONS.FIELD')}\n    ];\n    \n    if (!$scope.popup.duedate && !$scope.popup.duedateExpression) {\n        // Default, first time opening the popup\n        $scope.popup.selectedDueDateOption = $scope.taskDueDateOptions[0].id;\n        \n    } else if (!$scope.popup.duedate) {\n        $scope.popup.selectedDueDateOption = $scope.taskDueDateOptions[1].id;\n        \n    } else {\n        \n        if ($scope.popup.duedate.fixed) {\n            $scope.popup.selectedDueDateOption = $scope.taskDueDateOptions[2].id;\n            \n        } else if ($scope.popup.duedate.field) {\n            $scope.popup.selectedDueDateOption = $scope.taskDueDateOptions[3].id;\n        \n        } else {\n            $scope.popup.selectedDueDateOption = $scope.taskDueDateOptions[0].id;\n        }\n    }\n    \n    $scope.dueDateOptionChanged = function() {\n        if ($scope.popup.selectedDueDateOption === 'expression') {\n            $scope.popup.duedate = undefined;\n        \n        } else if ($scope.popup.selectedDueDateOption === 'none') {\n            $scope.popup.duedate = undefined;\n            $scope.popup.duedateExpression = undefined;\n        \n        } else if ($scope.popup.selectedDueDateOption === 'static') {\n            $scope.popup.duedate = {'fixed': {}};\n            $scope.popup.duedateExpression = undefined;\n        \n        } else if ($scope.popup.selectedDueDateOption === 'field') {\n            $scope.popup.duedate = {'field': {}};\n            $scope.popup.duedateExpression = undefined;\n        }\n    };\n    \n    $scope.setAddCalculationType = function() {\n        $scope.popup.duedate.field.taskDueDateCalculationType = 'add';\n    };\n    \n    $scope.setSubtractCalculationType = function() {\n        $scope.popup.duedate.field.taskDueDateCalculationType = 'subtract';\n    };\n\n    $scope.allSteps = EDITOR.UTIL.collectSortedElementsFromPrecedingElements($scope.selectedShape);\n\n    $scope.save = function () {\n        $scope.property.value = {};\n        if ($scope.popup.duedate) {\n            $scope.property.value.duedate = $scope.popup.duedate;\n            \n        } else if ($scope.popup.duedateExpression) {\n            $scope.property.value.duedateExpression = $scope.popup.duedateExpression;\n        \n        } else {\n            $scope.property.value = '';\n        }\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}]);\n"
  },
  {
    "path": "flowable-ui-web/modeler/editor-app/configuration/properties-event-listeners-controller.js",
    "content": "/* Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n * \n *      http://www.apache.org/licenses/LICENSE-2.0\n * \n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/*\n * Execution listeners\n */\n\nangular.module('flowableModeler').controller('FlowableEventListenersCtrl',\n    ['$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        _internalCreateModal(opts, $modal, $scope);\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('flowableModeler').controller('FlowableEventListenersPopupCtrl',\n    ['$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.eventListeners !== undefined\n            && $scope.property.value.eventListeners !== null) {\n\n            if ($scope.property.value.eventListeners.constructor == String) {\n                $scope.eventListeners = JSON.parse($scope.property.value.eventListeners);\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.eventListeners = angular.copy($scope.property.value.eventListeners);\n            }\n\n        } else {\n            $scope.eventListeners = [];\n        }\n\n        $scope.translationsRetrieved = false;\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: $scope.eventListeners,\n                headerRowHeight: 28,\n                enableRowSelection: true,\n                enableRowHeaderSelection: false,\n                multiSelect: false,\n                modifierKeysToMultiSelect: false,\n                enableHorizontalScrollbar: 0,\n                enableColumnMenus: false,\n                enableSorting: false,\n                columnDefs: [{field: 'event', displayName: $scope.labels.eventLabel},\n                    {field: 'implementation', displayName: $scope.labels.implementationLabel}]\n            };\n\n            $scope.gridOptions.onRegisterApi = function (gridApi) {\n                //set gridApi on scope\n                $scope.gridApi = gridApi;\n                gridApi.selection.on.rowSelectionChanged($scope, function (row) {\n                    $scope.selectedListener = row.entity;\n\n                    if ($scope.selectedListener) {\n                        var fields = $scope.selectedListener.fields;\n                        if (fields !== undefined && fields !== null) {\n                            for (var i = 0; i < fields.length; i++) {\n                                var field = fields[i];\n                                if (field.stringValue !== undefined && field.stringValue !== '') {\n                                    field.implementation = field.stringValue;\n                                } else if (field.expression !== undefined && field.expression !== '') {\n                                    field.implementation = field.expression;\n                                } else if (field.string !== undefined && field.string !== '') {\n                                    field.implementation = field.string;\n                                }\n                            }\n                        } else {\n                            $scope.selectedListener.fields = [];\n                        }\n                        if (!$scope.selectedListener.events) {\n                            $scope.selectedListener.events = [{event: ''}];\n                        }\n                    }\n                });\n            };\n        });\n\n\n        // Click handler for + button after enum value\n        $scope.addEventValue = function (index) {\n            $scope.selectedListener.events.splice(index + 1, 0, {event: ''});\n        };\n\n        // Click handler for - button after enum value\n        $scope.removeEventValue = function (index) {\n            $scope.selectedListener.events.splice(index, 1);\n            $scope.listenerDetailsChanged();\n        };\n\n        $scope.listenerDetailsChanged = function () {\n            var listener = $scope.selectedListener;\n            if (listener.events) {\n                var eventText = '';\n                for (var i = 0; i < listener.events.length; i++) {\n                    if (i > 0) {\n                        eventText += \", \";\n                    }\n                    eventText += listener.events[i].event;\n                }\n                $scope.selectedListener.event = eventText;\n            }\n\n            if (listener.rethrowEvent) {\n                var implementationText = '';\n                if (listener.rethrowType && listener.rethrowType.length > 0) {\n                    if (listener.rethrowType === 'error' && listener.errorcode !== '') {\n                        implementationText = \"Rethrow as error \" + listener.errorcode;\n                    }\n                    else if (listener.rethrowType === 'message' && listener.messagename !== '') {\n                        implementationText = \"Rethrow as message \" + listener.messagename;\n                    }\n                    else if ((listener.rethrowType === 'signal' || listener.rethrowType === 'globalSignal') && listener.signalname !== '') {\n                        implementationText = \"Rethrow as signal \" + listener.signalname;\n                    }\n                }\n                $scope.selectedListener.implementation = implementationText;\n            }\n            else {\n                if ($scope.selectedListener.className !== '') {\n                    $scope.selectedListener.implementation = $scope.selectedListener.className;\n                }\n                else if ($scope.selectedListener.delegateExpression !== '') {\n                    $scope.selectedListener.implementation = $scope.selectedListener.delegateExpression;\n                }\n                else {\n                    $scope.selectedListener.implementation = '';\n                }\n            }\n        };\n\n        // Click handler for add button\n        $scope.addNewListener = function () {\n            var newListener = {\n                event: '',\n                implementation: '',\n                className: '',\n                delegateExpression: '',\n                retrowEvent: false\n            };\n\n            $scope.eventListeners.push(newListener);\n\n            $timeout(function () {\n                $scope.gridApi.selection.toggleRowSelection(newListener);\n            });\n        };\n\n        // Click handler for remove button\n        $scope.removeListener = function () {\n            var selectedItems = $scope.gridApi.selection.getSelectedRows();\n            if (selectedItems && selectedItems.length > 0) {\n                var index = $scope.eventListeners.indexOf(selectedItems[0]);\n                $scope.gridApi.selection.toggleRowSelection(selectedItems[0]);\n                $scope.eventListeners.splice(index, 1);\n\n                if ($scope.eventListeners.length == 0) {\n                    $scope.selectedListener = undefined;\n                }\n\n                $timeout(function () {\n                    if ($scope.eventListeners.length > 0) {\n                        $scope.gridApi.selection.toggleRowSelection($scope.eventListeners[0]);\n                    }\n                });\n            }\n        };\n\n        // Click handler for up button\n        $scope.moveListenerUp = function () {\n            var selectedItems = $scope.gridApi.selection.getSelectedRows();\n            if (selectedItems && selectedItems.length > 0) {\n                var index = $scope.eventListeners.indexOf(selectedItems[0]);\n                if (index != 0) { // If it's the first, no moving up of course\n                    var temp = $scope.eventListeners[index];\n                    $scope.eventListeners.splice(index, 1);\n                    $timeout(function () {\n                        $scope.eventListeners.splice(index + -1, 0, temp);\n                        $timeout(function () {\n                            $scope.gridApi.selection.toggleRowSelection(temp);\n                        });\n                    });\n                }\n            }\n        };\n\n        // Click handler for down button\n        $scope.moveListenerDown = function () {\n            var selectedItems = $scope.gridApi.selection.getSelectedRows();\n            if (selectedItems && selectedItems.length > 0) {\n                var index = $scope.eventListeners.indexOf(selectedItems[0]);\n                if (index != $scope.eventListeners.length - 1) { // If it's the last element, no moving down of course\n                    var temp = $scope.eventListeners[index];\n                    $scope.eventListeners.splice(index, 1);\n                    $timeout(function () {\n                        $scope.eventListeners.splice(index + 1, 0, temp);\n                        $timeout(function () {\n                            $scope.gridApi.selection.toggleRowSelection(temp);\n                        });\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            $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    }]);\n"
  },
  {
    "path": "flowable-ui-web/modeler/editor-app/configuration/properties-execution-listeners-controller.js",
    "content": "/* Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n * \n *      http://www.apache.org/licenses/LICENSE-2.0\n * \n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/*\n * Execution listeners\n */\n\nangular.module('flowableModeler').controller('FlowableExecutionListenersCtrl',\n    ['$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        _internalCreateModal(opts, $modal, $scope);\n    }]);\n\nangular.module('flowableModeler').controller('FlowableExecutionListenersPopupCtrl',\n    ['$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.executionListeners !== undefined\n            && $scope.property.value.executionListeners !== null) {\n\n            if ($scope.property.value.executionListeners.constructor == String) {\n                $scope.executionListeners = JSON.parse($scope.property.value.executionListeners);\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.executionListeners = angular.copy($scope.property.value.executionListeners);\n            }\n\n            for (var i = 0; i < $scope.executionListeners.length; i++) {\n                var executionListener = $scope.executionListeners[i];\n                if (executionListener.className !== undefined && executionListener.className !== '') {\n                    executionListener.implementation = executionListener.className;\n                }\n                else if (executionListener.expression !== undefined && executionListener.expression !== '') {\n                    executionListener.implementation = executionListener.expression;\n                }\n                else if (executionListener.delegateExpression !== undefined && executionListener.delegateExpression !== '') {\n                    executionListener.implementation = executionListener.delegateExpression;\n                }\n            }\n        } else {\n            $scope.executionListeners = [];\n        }\n\n        $scope.selectedListener = undefined;\n        $scope.selectedField = undefined;\n        $scope.fields = [];\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: $scope.executionListeners,\n                headerRowHeight: 28,\n                enableRowSelection: true,\n                enableRowHeaderSelection: false,\n                multiSelect: false,\n                modifierKeysToMultiSelect: false,\n                enableHorizontalScrollbar: 0,\n                enableColumnMenus: false,\n                enableSorting: false,\n                columnDefs: [{field: 'event', displayName: $scope.labels.eventLabel},\n                    {field: 'implementation', displayName: $scope.labels.implementationLabel}]\n            };\n\n            $scope.gridOptions.onRegisterApi = function (gridApi) {\n                //set gridApi on scope\n                $scope.gridApi = gridApi;\n                gridApi.selection.on.rowSelectionChanged($scope, function (row) {\n                    $scope.selectedListener = row.entity;\n                    $scope.selectedField = undefined;\n                    if ($scope.selectedListener) {\n                        var fields = $scope.selectedListener.fields;\n                        if (fields !== undefined && fields !== null) {\n                            for (var i = 0; i < fields.length; i++) {\n                                var field = fields[i];\n                                if (field.stringValue !== undefined && field.stringValue !== '') {\n                                    field.implementation = field.stringValue;\n                                } else if (field.expression !== undefined && field.expression !== '') {\n                                    field.implementation = field.expression;\n                                } else if (field.string !== undefined && field.string !== '') {\n                                    field.implementation = field.string;\n                                }\n                            }\n                        } else {\n                            $scope.selectedListener.fields = [];\n                        }\n\n                        $scope.fields.length = 0;\n                        for (var i = 0; i < $scope.selectedListener.fields.length; i++) {\n                            $scope.fields.push($scope.selectedListener.fields[i]);\n                        }\n                    }\n                });\n            };\n\n            // Config for field grid\n            $scope.gridFieldOptions = {\n                data: $scope.fields,\n                headerRowHeight: 28,\n                enableRowSelection: true,\n                enableRowHeaderSelection: false,\n                multiSelect: false,\n                modifierKeysToMultiSelect: false,\n                enableHorizontalScrollbar: 0,\n                enableColumnMenus: false,\n                enableSorting: false,\n                columnDefs: [{field: 'name', displayName: $scope.labels.name},\n                    {field: 'implementation', displayName: $scope.labels.implementationLabel}]\n            };\n\n            $scope.gridFieldOptions.onRegisterApi = function (gridApi) {\n                // set gridApi on scope\n                $scope.fieldGridApi = gridApi;\n                gridApi.selection.on.rowSelectionChanged($scope, function (row) {\n                    $scope.selectedField = row.entity;\n                });\n            };\n        });\n\n        $scope.listenerDetailsChanged = function () {\n            if ($scope.selectedListener.className !== '') {\n                $scope.selectedListener.implementation = $scope.selectedListener.className;\n            } else if ($scope.selectedListener.expression !== '') {\n                $scope.selectedListener.implementation = $scope.selectedListener.expression;\n            } else if ($scope.selectedListener.delegateExpression !== '') {\n                $scope.selectedListener.implementation = $scope.selectedListener.delegateExpression;\n            } else {\n                $scope.selectedListener.implementation = '';\n            }\n        };\n\n        // Click handler for add button\n        $scope.addNewListener = function () {\n            var newListener = {\n                event: 'start',\n                implementation: '',\n                className: '',\n                expression: '',\n                delegateExpression: ''\n            };\n            $scope.executionListeners.push(newListener);\n\n            $timeout(function () {\n                $scope.gridApi.selection.toggleRowSelection(newListener);\n            });\n        };\n\n        // Click handler for remove button\n        $scope.removeListener = function () {\n            var selectedItems = $scope.gridApi.selection.getSelectedRows();\n            if (selectedItems && selectedItems.length > 0) {\n                var index = $scope.executionListeners.indexOf(selectedItems[0]);\n                $scope.gridApi.selection.toggleRowSelection(selectedItems[0]);\n\n                $scope.executionListeners.splice(index, 1);\n\n                if ($scope.executionListeners.length == 0) {\n                    $scope.selectedListener = undefined;\n                }\n\n                $timeout(function () {\n                    if ($scope.executionListeners.length > 0) {\n                        $scope.gridApi.selection.toggleRowSelection($scope.executionListeners[0]);\n                    }\n                });\n            }\n        };\n\n        // Click handler for up button\n        $scope.moveListenerUp = function () {\n            var selectedItems = $scope.gridApi.selection.getSelectedRows();\n            if (selectedItems && selectedItems.length > 0) {\n                var index = $scope.executionListeners.indexOf(selectedItems[0]);\n                if (index != 0) { // If it's the first, no moving up of course\n                    var temp = $scope.executionListeners[index];\n                    $scope.executionListeners.splice(index, 1);\n                    $timeout(function () {\n                        $scope.executionListeners.splice(index + -1, 0, temp);\n                        $timeout(function () {\n                            $scope.gridApi.selection.toggleRowSelection(temp);\n                        });\n                    });\n                }\n            }\n        };\n\n        // Click handler for down button\n        $scope.moveListenerDown = function () {\n            var selectedItems = $scope.gridApi.selection.getSelectedRows();\n            if (selectedItems && selectedItems.length > 0) {\n                var index = $scope.executionListeners.indexOf(selectedItems[0]);\n                if (index != $scope.executionListeners.length - 1) { // If it's the last element, no moving down of course\n                    var temp = $scope.executionListeners[index];\n                    $scope.executionListeners.splice(index, 1);\n                    $timeout(function () {\n                        $scope.executionListeners.splice(index + 1, 0, temp);\n                        $timeout(function () {\n                            $scope.gridApi.selection.toggleRowSelection(temp);\n                        });\n                    });\n                }\n            }\n        };\n\n        $scope.fieldDetailsChanged = function () {\n            if ($scope.selectedField.stringValue != '') {\n                $scope.selectedField.implementation = $scope.selectedField.stringValue;\n            } else if ($scope.selectedField.expression != '') {\n                $scope.selectedField.implementation = $scope.selectedField.expression;\n            } else if ($scope.selectedField.string != '') {\n                $scope.selectedField.implementation = $scope.selectedField.string;\n            } else {\n                $scope.selectedField.implementation = '';\n            }\n        };\n\n        // Click handler for add button\n        $scope.addNewField = function () {\n            if ($scope.selectedListener) {\n                if ($scope.selectedListener.fields == undefined) {\n                    $scope.selectedListener.fields = [];\n                }\n\n                var newField = {\n                    name: 'fieldName',\n                    implementation: '',\n                    stringValue: '',\n                    expression: '',\n                    string: ''\n                };\n                $scope.fields.push(newField);\n                $scope.selectedListener.fields.push(newField);\n\n                $timeout(function () {\n                    $scope.fieldGridApi.selection.toggleRowSelection(newField);\n                });\n            }\n        };\n\n        // Click handler for remove button\n        $scope.removeField = function () {\n            var selectedItems = $scope.fieldGridApi.selection.getSelectedRows();\n            if (selectedItems && selectedItems.length > 0) {\n                var index = $scope.fields.indexOf(selectedItems[0]);\n                $scope.fieldGridApi.selection.toggleRowSelection(selectedItems[0]);\n\n                $scope.fields.splice(index, 1);\n                $scope.selectedListener.fields.splice(index, 1);\n\n                if ($scope.fields.length == 0) {\n                    $scope.selectedField = undefined;\n                }\n\n                $timeout(function () {\n                    if ($scope.fields.length > 0) {\n                        $scope.fieldGridApi.selection.toggleRowSelection($scope.fields[0]);\n                    }\n                });\n            }\n        };\n\n        // Click handler for up button\n        $scope.moveFieldUp = function () {\n            var selectedItems = $scope.fieldGridApi.selection.getSelectedRows();\n            if (selectedItems && selectedItems.length > 0) {\n                var index = $scope.fields.indexOf(selectedItems[0]);\n                if (index != 0) { // If it's the first, no moving up of course\n                    var temp = $scope.fields[index];\n                    $scope.fields.splice(index, 1);\n                    $scope.selectedListener.fields.splice(index, 1);\n                    $timeout(function () {\n                        $scope.fields.splice(index + -1, 0, temp);\n                        $scope.selectedListener.fields.splice(index + -1, 0, temp);\n                        $timeout(function () {\n                            $scope.fieldGridApi.selection.toggleRowSelection(temp);\n                        });\n                    });\n                }\n            }\n        };\n\n        // Click handler for down button\n        $scope.moveFieldDown = function () {\n            var selectedItems = $scope.fieldGridApi.selection.getSelectedRows();\n            if (selectedItems && selectedItems.length > 0) {\n                var index = $scope.fields.indexOf(selectedItems[0]);\n                if (index != $scope.fields.length - 1) { // If it's the last element, no moving down of course\n                    var temp = $scope.fields[index];\n                    $scope.fields.splice(index, 1);\n                    $scope.selectedListener.fields.splice(index, 1);\n                    $timeout(function () {\n                        $scope.fields.splice(index + 1, 0, temp);\n                        $scope.selectedListener.fields.splice(index + 1, 0, temp);\n                        $timeout(function () {\n                            $scope.fieldGridApi.selection.toggleRowSelection(temp);\n                        });\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    }]);\n"
  },
  {
    "path": "flowable-ui-web/modeler/editor-app/configuration/properties-fields-controller.js",
    "content": "/* Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n * \n *      http://www.apache.org/licenses/LICENSE-2.0\n * \n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/*\n * Task listeners\n */\n\nangular.module('flowableModeler').controller('FlowableFieldsCtrl',\n    ['$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?version=' + Date.now(),\n            scope: $scope\n        };\n\n        // Open the dialog\n        _internalCreateModal(opts, $modal, $scope);\n    }]);\n\nangular.module('flowableModeler').controller('FlowableFieldsPopupCtrl',\n    ['$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.fields !== undefined\n            && $scope.property.value.fields !== null) {\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.fields = angular.copy($scope.property.value.fields);\n\n            for (var i = 0; i < $scope.fields.length; i++) {\n                var field = $scope.fields[i];\n                if (field.stringValue !== undefined && field.stringValue !== '') {\n                    field.implementation = field.stringValue;\n                }\n                else if (field.expression !== undefined && field.expression !== '') {\n                    field.implementation = field.expression;\n                }\n                else if (field.string !== undefined && field.string !== '') {\n                    field.implementation = field.string;\n                }\n            }\n\n        } else {\n            $scope.fields = [];\n        }\n\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: $scope.fields,\n                headerRowHeight: 28,\n                enableRowSelection: true,\n                enableRowHeaderSelection: false,\n                multiSelect: false,\n                modifierKeysToMultiSelect: false,\n                enableHorizontalScrollbar: 0,\n                enableColumnMenus: false,\n                enableSorting: false,\n                columnDefs: [{field: 'name', displayName: $scope.labels.nameLabel},\n                    {field: 'implementation', displayName: $scope.labels.implementationLabel}]\n            };\n\n            $scope.gridOptions.onRegisterApi = function (gridApi) {\n                //set gridApi on scope\n                $scope.gridApi = gridApi;\n                gridApi.selection.on.rowSelectionChanged($scope, function (row) {\n                    $scope.selectedField = row.entity;\n                });\n            };\n        });\n\n        $scope.fieldDetailsChanged = function () {\n            if ($scope.selectedField.stringValue != '') {\n                $scope.selectedField.implementation = $scope.selectedField.stringValue;\n            }\n            else if ($scope.selectedField.expression != '') {\n                $scope.selectedField.implementation = $scope.selectedField.expression;\n            }\n            else if ($scope.selectedField.string != '') {\n                $scope.selectedField.implementation = $scope.selectedField.string;\n            }\n            else {\n                $scope.selectedField.implementation = '';\n            }\n        };\n\n        // Click handler for add button\n        $scope.addNewField = function () {\n            var newField = {\n                name: 'fieldName',\n                implementation: '',\n                stringValue: '',\n                expression: '',\n                string: ''\n            };\n\n            $scope.fields.push(newField);\n            $timeout(function () {\n                $scope.gridApi.selection.toggleRowSelection(newField);\n            });\n        };\n\n        // Click handler for remove button\n        $scope.removeField = function () {\n\n            var selectedItems = $scope.gridApi.selection.getSelectedRows();\n            if (selectedItems && selectedItems.length > 0) {\n                var index = $scope.fields.indexOf(selectedItems[0]);\n                $scope.gridApi.selection.toggleRowSelection(selectedItems[0]);\n                $scope.fields.splice(index, 1);\n\n                if ($scope.fields.length == 0) {\n                    $scope.selectedField = undefined;\n                }\n\n                $timeout(function () {\n                    if ($scope.fields.length > 0) {\n                        $scope.gridApi.selection.toggleRowSelection($scope.fields[0]);\n                    }\n                });\n            }\n        };\n\n        // Click handler for up button\n        $scope.moveFieldUp = function () {\n            var selectedItems = $scope.gridApi.selection.getSelectedRows();\n            if (selectedItems && selectedItems.length > 0) {\n                var index = $scope.fields.indexOf(selectedItems[0]);\n                if (index != 0) { // If it's the first, no moving up of course\n                    var temp = $scope.fields[index];\n                    $scope.fields.splice(index, 1);\n                    $timeout(function () {\n                        $scope.fields.splice(index + -1, 0, temp);\n                        $timeout(function () {\n                            $scope.gridApi.selection.toggleRowSelection(temp);\n                        });\n                    });\n                }\n            }\n        };\n\n        // Click handler for down button\n        $scope.moveFieldDown = function () {\n            var selectedItems = $scope.gridApi.selection.getSelectedRows();\n            if (selectedItems && selectedItems.length > 0) {\n                var index = $scope.fields.indexOf(selectedItems[0]);\n                if (index != $scope.fields.length - 1) { // If it's the last element, no moving down of course\n                    var temp = $scope.fields[index];\n                    $scope.fields.splice(index, 1);\n                    $timeout(function () {\n                        $scope.fields.splice(index + 1, 0, temp);\n                        $timeout(function () {\n                            $scope.gridApi.selection.toggleRowSelection(temp);\n                        });\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.$hide();\n        };\n\n        // Close button handler\n        $scope.close = function () {\n            $scope.property.mode = 'read';\n            $scope.$hide();\n        };\n    }]);\n"
  },
  {
    "path": "flowable-ui-web/modeler/editor-app/configuration/properties-form-properties-controller.js",
    "content": "/* Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n * \n *      http://www.apache.org/licenses/LICENSE-2.0\n * \n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/*\n * Form Properties\n */\n\nangular.module('flowableModeler').controller('FlowableFormPropertiesCtrl',\n    ['$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        _internalCreateModal(opts, $modal, $scope);\n    }]);\n\nangular.module('flowableModeler').controller('FlowableFormPropertiesPopupCtrl',\n    ['$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\t\t\t    var formProperty = $scope.formProperties[i];\n\t\t\t    if (formProperty.enumValues && formProperty.enumValues.length > 0) {\n\t\t\t\t    for (var j = 0; j < formProperty.enumValues.length; j++) {\n\t\t\t\t\t    var enumValue = formProperty.enumValues[j];\n\t\t\t\t\t    if (!enumValue.id && !enumValue.name && enumValue.value) {\n\t\t\t\t\t\t    enumValue.id = enumValue.value;\n\t\t\t\t\t\t    enumValue.name = enumValue.value;\n\t\t\t\t\t    }\n\t\t\t\t    }\n\t\t\t    }\n\t\t\t}\n            \n        } else {\n            $scope.formProperties = [];\n        }\n        \n        $scope.enumValues = [];\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            $scope.labels.idLabel = results[0];\n            $scope.labels.nameLabel = results[1];\n            $scope.labels.typeLabel = results[2];\n            $scope.translationsRetrieved = true;\n\n            // Config for grid\n            $scope.gridOptions = {\n                data: $scope.formProperties,\n                headerRowHeight: 28,\n                enableRowSelection: true,\n                enableRowHeaderSelection: false,\n                multiSelect: false,\n                modifierKeysToMultiSelect: false,\n                enableHorizontalScrollbar: 0,\n                enableColumnMenus: false,\n                enableSorting: false,\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\t    data: $scope.enumValues,\n                headerRowHeight: 28,\n                enableRowSelection: true,\n                enableRowHeaderSelection: false,\n                multiSelect: false,\n                modifierKeysToMultiSelect: false,\n                enableHorizontalScrollbar: 0,\n                enableColumnMenus: false,\n                enableSorting: false,\n                columnDefs: [{ field: 'id', displayName: $scope.labels.idLabel },\n                { field: 'name', displayName: $scope.labels.nameLabel}]\n            }\n\n            $scope.gridOptions.onRegisterApi = function (gridApi) {\n                //set gridApi on scope\n                $scope.gridApi = gridApi;\n                gridApi.selection.on.rowSelectionChanged($scope, function (row) {\n                    $scope.selectedProperty = row.entity;\n                    $scope.selectedEnumValue = undefined;\n                    if ($scope.selectedProperty && $scope.selectedProperty.enumValues) {\n                        $scope.enumValues.length = 0;\n                        for (var i = 0; i < $scope.selectedProperty.enumValues.length; i++) {\n                            $scope.enumValues.push($scope.selectedProperty.enumValues[i]);\n                        }\n                    }\n                });\n            };\n            \n            $scope.enumGridOptions.onRegisterApi = function (gridApi) {\n                //set gridApi on scope\n                $scope.enumGridApi = gridApi;\n                gridApi.selection.on.rowSelectionChanged($scope, function (row) {\n                    $scope.selectedEnumValue = row.entity;\n                });\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.selectedProperty.type === 'date') {\n                $scope.selectedProperty.datePattern = 'MM-dd-yyyy hh:mm';\n            } else {\n                delete $scope.selectedProperty.datePattern;\n            }\n\n            // Check enum. If enum, show list of options\n            if ($scope.selectedProperty.type === 'enum') {\n                $scope.selectedProperty.enumValues = [ {id: 'value1', name: 'Value 1'}, {id: 'value2', name: 'Value 2'}];\n                $scope.enumValues.length = 0;\n                for (var i = 0; i < $scope.selectedProperty.enumValues.length; i++) {\n                    $scope.enumValues.push($scope.selectedProperty.enumValues[i]);\n                }\n                \n            } else {\n                delete $scope.selectedProperty.enumValues;\n                $scope.enumValues.length = 0;\n            }\n        };\n\n        // Click handler for add button\n        var propertyIndex = 1;\n        $scope.addNewProperty = function () {\n            var newProperty = {\n                id: 'new_property_' + propertyIndex++,\n                name: '',\n                type: 'string',\n                readable: true,\n                writable: true\n            };\n\n            $scope.formProperties.push(newProperty);\n\n            $timeout(function () {\n                $scope.gridApi.selection.toggleRowSelection(newProperty);\n            });\n        };\n\n        // Click handler for remove button\n        $scope.removeProperty = function () {\n            var selectedItems = $scope.gridApi.selection.getSelectedRows();\n            if (selectedItems && selectedItems.length > 0) {\n                var index = $scope.formProperties.indexOf(selectedItems[0]);\n                $scope.gridApi.selection.toggleRowSelection(selectedItems[0]);\n                $scope.formProperties.splice(index, 1);\n\n                if ($scope.formProperties.length == 0) {\n                    $scope.selectedProperty = undefined;\n                }\n\n                $timeout(function() {\n                    if ($scope.formProperties.length > 0) {\n                        $scope.gridApi.selection.toggleRowSelection($scope.formProperties[0]);\n                    }\n                });\n            }\n        };\n\n        // Click handler for up button\n        $scope.movePropertyUp = function () {\n            var selectedItems = $scope.gridApi.selection.getSelectedRows();\n            if (selectedItems && selectedItems.length > 0) {\n                var index = $scope.formProperties.indexOf(selectedItems[0]);\n                if (index != 0) { // If it's the first, no moving up of course\n                    var temp = $scope.formProperties[index];\n                    $scope.formProperties.splice(index, 1);\n                    $timeout(function(){\n                        $scope.formProperties.splice(index + -1, 0, temp);\n                        $timeout(function() {\n                            $scope.gridApi.selection.toggleRowSelection(temp);\n                        });\n                    });\n                }\n            }\n        };\n\n        // Click handler for down button\n        $scope.movePropertyDown = function () {\n            var selectedItems = $scope.gridApi.selection.getSelectedRows();\n            if (selectedItems && selectedItems.length > 0) {\n                var index = $scope.formProperties.indexOf(selectedItems[0]);\n                if (index != $scope.formProperties.length - 1) { // If it's the last element, no moving down of course\n                    var temp = $scope.formProperties[index];\n                    $scope.formProperties.splice(index, 1);\n                    $timeout(function(){\n                        $scope.formProperties.splice(index + 1, 0, temp);\n                        $timeout(function() {\n                            $scope.gridApi.selection.toggleRowSelection(temp);\n                        });\n                    });\n                }\n            }\n        };\n        \n        $scope.addNewEnumValue = function() {\n            if ($scope.selectedProperty) {\n        \t    var newEnumValue = { id : '', name : ''};\n        \t    $scope.selectedProperty.enumValues.push(newEnumValue);\n        \t    $scope.enumValues.push(newEnumValue);\n    \t       \n    \t        $timeout(function () {\n                    $scope.enumGridApi.selection.toggleRowSelection(newEnumValue);\n                });\n        \t}\n        };\n\n        // Click handler for remove button\n        $scope.removeEnumValue = function() {\n            var selectedItems = $scope.enumGridApi.selection.getSelectedRows();\n            if (selectedItems && selectedItems.length > 0) {\n                var index = $scope.enumValues.indexOf(selectedItems[0]);\n                $scope.enumGridApi.selection.toggleRowSelection(selectedItems[0]);\n\n                $scope.enumValues.splice(index, 1);\n                $scope.selectedProperty.enumValues.splice(index, 1);\n\n                if ($scope.enumValues.length == 0) {\n                    $scope.selectedEnumValue = undefined;\n                }\n\n                $timeout(function () {\n                    if ($scope.enumValues.length > 0) {\n                        $scope.enumGridApi.selection.toggleRowSelection($scope.enumValues[0]);\n                    }\n                });\n            }\n        };\n    \n        // Click handler for up button\n        $scope.moveEnumValueUp = function() {\n            var selectedItems = $scope.enumGridApi.selection.getSelectedRows();\n            if (selectedItems && selectedItems.length > 0) {\n                var index = $scope.enumValues.indexOf(selectedItems[0]);\n                if (index != 0) { // If it's the first, no moving up of course\n                    var temp = $scope.enumValues[index];\n                    $scope.enumValues.splice(index, 1);\n                    $scope.selectedProperty.enumValues.splice(index, 1);\n                    $timeout(function () {\n                        $scope.enumValues.splice(index + -1, 0, temp);\n                        $scope.selectedProperty.enumValues.splice(index + -1, 0, temp);\n                        $timeout(function () {\n                            $scope.enumGridApi.selection.toggleRowSelection(temp);\n                        });\n                    });\n                }\n            }\n        };\n    \n        // Click handler for down button\n        $scope.moveEnumValueDown = function() {\n            var selectedItems = $scope.enumGridApi.selection.getSelectedRows();\n            if (selectedItems && selectedItems.length > 0) {\n                var index = $scope.enumValues.indexOf(selectedItems[0]);\n                if (index != $scope.enumValues.length - 1) { // If it's the last element, no moving down of course\n                    var temp = $scope.enumValues[index];\n                    $scope.enumValues.splice(index, 1);\n                    $scope.selectedProperty.enumValues.splice(index, 1);\n                    $timeout(function () {\n                        $scope.enumValues.splice(index + 1, 0, temp);\n                        $scope.selectedProperty.enumValues.splice(index + 1, 0, temp);\n                        $timeout(function () {\n                            $scope.enumGridApi.selection.toggleRowSelection(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            $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    }])\n;"
  },
  {
    "path": "flowable-ui-web/modeler/editor-app/configuration/properties-form-reference-controller.js",
    "content": "/* 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 \nangular.module('flowableModeler').controller('FlowableFormReferenceDisplayCtrl',\n    [ '$scope', '$modal', '$http', function($scope, $modal, $http) {\n    \n    if ($scope.property && $scope.property.value && $scope.property.value.id) {\n   \t\t$http.get(FLOWABLE.APP_URL.getModelUrl($scope.property.value.id))\n            .success(\n                function(response) {\n                    $scope.form = {\n                    \tid: response.id,\n                    \tname: response.name\n                    };\n                });\n    }\n\t\n}]);\n\nangular.module('flowableModeler').controller('FlowableFormReferenceCtrl',\n    [ '$scope', '$modal', '$http', function($scope, $modal, $http) {\n\t\n     // Config for the modal window\n     var opts = {\n         template:  'editor-app/configuration/properties/form-reference-popup.html?version=' + Date.now(),\n         scope: $scope\n     };\n\n     // Open the dialog\n     _internalCreateModal(opts, $modal, $scope);\n}]);\n\nangular.module('flowableModeler').controller('FlowableFormReferencePopupCtrl',\n    [ '$rootScope', '$scope', '$http', '$location', 'editorManager', function($rootScope, $scope, $http, $location, editorManager) {\n\t \n\t$scope.state = {'loadingForms' : true, 'formError' : false};\n\t\n\t$scope.popup = {'state' : 'formReference'};\n    \n    $scope.foldersBreadCrumbs = [];\n    \n    // Close button handler\n    $scope.close = function() {\n    \t$scope.property.mode = 'read';\n        $scope.$hide();\n    };\n    \n    // Selecting/deselecting a subprocess\n    $scope.selectForm = function(form, $event) {\n   \t \t$event.stopPropagation();\n   \t \tif ($scope.selectedForm && $scope.selectedForm.id && form.id == $scope.selectedForm.id) {\n   \t \t\t// un-select the current selection\n   \t \t\t$scope.selectedForm = null;\n   \t \t} else {\n   \t \t\t$scope.selectedForm = form;\n   \t \t}\n    };\n    \n    // Saving the selected value\n    $scope.save = function() {\n   \t \tif ($scope.selectedForm) {\n   \t \t\t$scope.property.value = {\n   \t \t\t\t'id' : $scope.selectedForm.id, \n   \t \t\t\t'name' : $scope.selectedForm.name,\n   \t \t\t\t'key' : $scope.selectedForm.key\n   \t \t\t};\n   \t \t\t\n   \t \t} else {\n   \t \t\t$scope.property.value = null; \n   \t \t}\n   \t \t$scope.updatePropertyInModel($scope.property);\n   \t \t$scope.close();\n    };\n    \n    // Open the selected value\n    $scope.open = function() {\n        if ($scope.selectedForm) {\n            $scope.property.value = {\n            \t'id' : $scope.selectedForm.id, \n            \t'name' : $scope.selectedForm.name,\n            \t'key' : $scope.selectedForm.key\n            };\n            \n            $scope.updatePropertyInModel($scope.property);\n            \n            var modelMetaData = editorManager.getBaseModelData();\n            var json = editorManager.getModel();\n            json = JSON.stringify(json);\n\n            var params = {\n                modeltype: modelMetaData.model.modelType,\n                json_xml: json,\n                name: modelMetaData.name,\n                key: modelMetaData.key,\n                description: modelMetaData.description,\n                newversion: false,\n                lastUpdated: modelMetaData.lastUpdated\n            };\n\n            // Update\n            $http({ method: 'POST',\n                data: params,\n                ignoreErrors: true,\n                headers: {'Accept': 'application/json',\n                          'Content-Type': 'application/x-www-form-urlencoded; 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: FLOWABLE.URL.putModel(modelMetaData.modelId)})\n\n                .success(function (data, status, headers, config) {\n                    editorManager.handleEvents({\n                        type: ORYX.CONFIG.EVENT_SAVED\n                    });\n\n                    var allSteps = EDITOR.UTIL.collectSortedElementsFromPrecedingElements($scope.selectedShape);\n\n\t\t\t\t\t$rootScope.addHistoryItem($scope.selectedShape.resourceId);\n                    $location.path('form-editor/' + $scope.selectedForm.id);\n\n                })\n                .error(function (data, status, headers, config) {\n                    \n                });\n            \n            $scope.close();\n        }\n    };\n    \n    $scope.newForm = function() {\n        $scope.popup.state = 'newForm';\n        \n        var modelMetaData = editorManager.getBaseModelData();\n        \n        $scope.model = {\n            loading: false,\n            form: {\n                 name: '',\n                 key: '',\n                 description: '',\n                 modelType: 2\n            }\n        };\n    };\n    \n    $scope.createForm = function() {\n        \n        if (!$scope.model.form.name || $scope.model.form.name.length == 0 ||\n        \t!$scope.model.form.key || $scope.model.form.key.length == 0) {\n        \t\n            return;\n        }\n\n        $scope.model.loading = true;\n\n        $http({method: 'POST', url: FLOWABLE.APP_URL.getModelsUrl(), data: $scope.model.form}).\n            success(function(data, status, headers, config) {\n                \n                var newFormId = data.id;\n                $scope.property.value = {\n                \t'id' : newFormId, \n                \t'name' : data.name,\n                \t'key' : data.key\n               \t};\n                $scope.updatePropertyInModel($scope.property);\n                \n                var modelMetaData = editorManager.getBaseModelData();\n                var json = editorManager.getModel();\n                json = JSON.stringify(json);\n\n                var params = {\n                    modeltype: modelMetaData.model.modelType,\n                    json_xml: json,\n                    name: modelMetaData.name,\n                    key: modelMetaData.key,\n                    description: modelMetaData.description,\n                    newversion: false,\n                    lastUpdated: modelMetaData.lastUpdated\n                };\n\n                // Update\n                $http({ method: 'POST',\n                    data: params,\n                    ignoreErrors: true,\n                    headers: {'Accept': 'application/json',\n                              'Content-Type': 'application/x-www-form-urlencoded; 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: FLOWABLE.URL.putModel(modelMetaData.modelId)})\n\n                    .success(function (data, status, headers, config) {\n                        editorManager.handleEvents({\n                            type: ORYX.CONFIG.EVENT_SAVED\n                        });\n                        \n                        $scope.model.loading = false;\n                        $scope.$hide();\n\n                        var allSteps = EDITOR.UTIL.collectSortedElementsFromPrecedingElements($scope.selectedShape);\n\n                        $rootScope.addHistoryItem($scope.selectedShape.resourceId);\n                        $location.path('form-editor/' + newFormId);\n\n                    })\n                    .error(function (data, status, headers, config) {\n                        $scope.model.loading = false;\n                        $scope.$hide();\n                    });\n                \n            }).\n            error(function(data, status, headers, config) {\n                $scope.model.loading = false;\n                $scope.model.errorMessage = data.message;\n            });\n    };\n    \n    $scope.cancel = function() {\n        $scope.close();\n    };\n\n    $scope.loadForms = function() {\n        var modelMetaData = editorManager.getBaseModelData();\n        $http.get(FLOWABLE.APP_URL.getFormModelsUrl())\n            .success(\n                function(response) {\n                    $scope.state.loadingForms = false;\n                    $scope.state.formError = false;\n                    $scope.forms = response.data;\n                })\n            .error(\n                function(data, status, headers, config) {\n                    $scope.state.loadingForms = false;\n                    $scope.state.formError = true;\n                });\n    };\n\n    if ($scope.property && $scope.property.value && $scope.property.value.id) {\n   \t     $scope.selectedForm = $scope.property.value;\n    }\n\n    $scope.loadForms();\n}]);\n"
  },
  {
    "path": "flowable-ui-web/modeler/editor-app/configuration/properties-httprequest-controller.js",
    "content": "/* 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\nangular.module('flowableModeler').controller('FlowableHttpRequestMethodCtrl', [ '$scope', function($scope) {\n\n    if ($scope.property.value == undefined && $scope.property.value == null)\n    {\n    \t   $scope.property.value = 'GET';\n    }\n        \n    $scope.httpRequestMethodChanged = function() {\n        \t$scope.updatePropertyInModel($scope.property);\n    };\n}]);"
  },
  {
    "path": "flowable-ui-web/modeler/editor-app/configuration/properties-in-parameters-controller.js",
    "content": "/* Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n * \n *      http://www.apache.org/licenses/LICENSE-2.0\n * \n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/*\n * Input parameters for call activity\n */\n\nangular.module('flowableModeler').controller('FlowableInParametersCtrl',\n    ['$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        _internalCreateModal(opts, $modal, $scope);\n    }]);\n\nangular.module('flowableModeler').controller('FlowableInParametersPopupCtrl',\n    ['$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.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        $scope.translationsRetrieved = false;\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: $scope.parameters,\n                headerRowHeight: 28,\n                enableRowSelection: true,\n                enableRowHeaderSelection: false,\n                multiSelect: false,\n                modifierKeysToMultiSelect: false,\n                enableHorizontalScrollbar: 0,\n                enableColumnMenus: false,\n                enableSorting: false,\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            $scope.gridOptions.onRegisterApi = function (gridApi) {\n                //set gridApi on scope\n                $scope.gridApi = gridApi;\n                gridApi.selection.on.rowSelectionChanged($scope, function (row) {\n                    $scope.selectedParameter = row.entity;\n                });\n            };\n        });\n\n        // Click handler for add button\n        $scope.addNewParameter = function () {\n            var newParameter = {\n                source: '',\n                sourceExpression: '',\n                target: ''\n            };\n\n            $scope.parameters.push(newParameter);\n\n            $timeout(function () {\n                $scope.gridApi.selection.toggleRowSelection(newParameter);\n            });\n        };\n\n        // Click handler for remove button\n        $scope.removeParameter = function () {\n\n            var selectedItems = $scope.gridApi.selection.getSelectedRows();\n            if (selectedItems && selectedItems.length > 0) {\n                var index = $scope.parameters.indexOf(selectedItems[0]);\n                $scope.gridApi.selection.toggleRowSelection(selectedItems[0]);\n                $scope.parameters.splice(index, 1);\n\n                if ($scope.parameters.length == 0) {\n                    $scope.selectedParameter = undefined;\n                }\n\n                $timeout(function () {\n                    if ($scope.parameters.length > 0) {\n                        $scope.gridApi.selection.toggleRowSelection($scope.parameters[0]);\n                    }\n                });\n            }\n        };\n\n        // Click handler for up button\n        $scope.moveParameterUp = function () {\n            var selectedItems = $scope.gridApi.selection.getSelectedRows();\n            if (selectedItems && selectedItems.length > 0) {\n                var index = $scope.parameters.indexOf(selectedItems[0]);\n                if (index != 0) { // If it's the first, no moving up of course\n                    var temp = $scope.parameters[index];\n                    $scope.parameters.splice(index, 1);\n                    $timeout(function () {\n                        $scope.parameters.splice(index + -1, 0, temp);\n                        $timeout(function () {\n                            $scope.gridApi.selection.toggleRowSelection(temp);\n                        });\n                    });\n                }\n            }\n        };\n\n        // Click handler for down button\n        $scope.moveParameterDown = function () {\n            var selectedItems = $scope.gridApi.selection.getSelectedRows();\n            if (selectedItems && selectedItems.length > 0) {\n                var index = $scope.parameters.indexOf(selectedItems[0]);\n                if (index != $scope.parameters.length - 1) { // If it's the last element, no moving down of course\n                    var temp = $scope.parameters[index];\n                    $scope.parameters.splice(index, 1);\n                    $timeout(function () {\n                        $scope.parameters.splice(index + 1, 0, temp);\n                        $timeout(function () {\n                            $scope.gridApi.selection.toggleRowSelection(temp);\n                        });\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": "flowable-ui-web/modeler/editor-app/configuration/properties-message-definitions-controller.js",
    "content": "/* Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n * \n *      http://www.apache.org/licenses/LICENSE-2.0\n * \n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/*\n * Execution listeners\n */\n\nangular.module('flowableModeler').controller('FlowableMessageDefinitionsCtrl', ['$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    _internalCreateModal(opts, $modal, $scope);\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('flowableModeler').controller('FlowableMessageDefinitionsPopupCtrl',\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.selectedMessageDefinition = undefined;\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: $scope.messageDefinitions,\n                headerRowHeight: 28,\n                enableRowSelection: true,\n                enableRowHeaderSelection: false,\n                multiSelect: false,\n                modifierKeysToMultiSelect: false,\n                enableHorizontalScrollbar: 0,\n                enableColumnMenus: false,\n                enableSorting: false,\n                columnDefs: [\n                    {field: 'id', displayName: $scope.labels.idLabel},\n                    {field: 'name', displayName: $scope.labels.nameLabel}]\n            };\n\n            $scope.gridOptions.onRegisterApi = function (gridApi) {\n                //set gridApi on scope\n                $scope.gridApi = gridApi;\n                gridApi.selection.on.rowSelectionChanged($scope, function (row) {\n                    $scope.selectedMessageDefinition = row.entity;\n                });\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                $scope.gridApi.selection.toggleRowSelection(newMessageDefinition);\n            });\n        };\n\n        // Click handler for remove button\n        $scope.removeMessageDefinition = function () {\n            var selectedItems = $scope.gridApi.selection.getSelectedRows();\n            if (selectedItems && selectedItems.length > 0) {\n                var index = $scope.messageDefinitions.indexOf(selectedItems[0]);\n                $scope.gridApi.selection.toggleRowSelection(selectedItems[0]);\n                $scope.messageDefinitions.splice(index, 1);\n\n                if ($scope.messageDefinitions.length == 0) {\n                    $scope.selectedMesageDefinition = undefined;\n                }\n\n                $timeout(function () {\n                    if ($scope.messageDefinitions.length > 0) {\n                        $scope.gridApi.selection.toggleRowSelection($scope.messageDefinitions[0]);\n                    }\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": "flowable-ui-web/modeler/editor-app/configuration/properties-message-scope-controller.js",
    "content": "/* 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 */\nangular.module('flowableModeler').controller('FlowableMessageRefCtrl', [ '$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.get('oryx-messagedefinitions')) {\n        \tmessageDefinitionsProperty = parent.properties.get('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": "flowable-ui-web/modeler/editor-app/configuration/properties-multiinstance-controller.js",
    "content": "/* 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\nangular.module('flowableModeler').controller('FlowableMultiInstanceCtrl', [ '$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": "flowable-ui-web/modeler/editor-app/configuration/properties-ordering-controller.js",
    "content": "/* Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n * \n *      http://www.apache.org/licenses/LICENSE-2.0\n * \n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/*\n * Adhoc sub process ordering property\n */\n\nangular.module('flowableModeler').controller('FlowableOrderingCtrl', [ '$scope', function($scope) {\n\n    if ($scope.property.value == undefined && $scope.property.value == null)\n    {\n    \t$scope.property.value = 'Parallel';\n    }\n        \n    $scope.orderingChanged = function() {\n    \t$scope.updatePropertyInModel($scope.property);\n    };\n}]);"
  },
  {
    "path": "flowable-ui-web/modeler/editor-app/configuration/properties-out-parameters-controller.js",
    "content": "/* Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n * \n *      http://www.apache.org/licenses/LICENSE-2.0\n * \n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/*\n * Input parameters for call activity\n */\n\nangular.module('flowableModeler').controller('FlowableOutParametersCtrl',\n    ['$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        _internalCreateModal(opts, $modal, $scope);\n    }]);\n\nangular.module('flowableModeler').controller('FlowableOutParametersPopupCtrl',\n    ['$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.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        $scope.translationsRetrieved = false;\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: $scope.parameters,\n                headerRowHeight: 28,\n                enableRowSelection: true,\n                enableRowHeaderSelection: false,\n                multiSelect: false,\n                modifierKeysToMultiSelect: false,\n                enableHorizontalScrollbar: 0,\n                enableColumnMenus: false,\n                enableSorting: false,\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            $scope.gridOptions.onRegisterApi = function (gridApi) {\n                //set gridApi on scope\n                $scope.gridApi = gridApi;\n                gridApi.selection.on.rowSelectionChanged($scope, function (row) {\n                    $scope.selectedParameter = row.entity;\n                });\n            };\n        });\n\n        // Click handler for add button\n        $scope.addNewParameter = function () {\n            var newParameter = {\n                source: '',\n                sourceExpression: '',\n                target: ''};\n\n            $scope.parameters.push(newParameter);\n            $timeout(function () {\n                $scope.gridApi.selection.toggleRowSelection(newParameter);\n            });\n        };\n\n        // Click handler for remove button\n        $scope.removeParameter = function () {\n            var selectedItems = $scope.gridApi.selection.getSelectedRows();\n            if (selectedItems && selectedItems.length > 0) {\n                var index = $scope.parameters.indexOf(selectedItems[0]);\n                $scope.gridApi.selection.toggleRowSelection(selectedItems[0]);\n                $scope.parameters.splice(index, 1);\n\n                if ($scope.parameters.length == 0) {\n                    $scope.selectedParameter = undefined;\n                }\n\n                $timeout(function () {\n                    if ($scope.parameters.length > 0) {\n                        $scope.gridApi.selection.toggleRowSelection($scope.parameters[0]);\n                    }\n                });\n            }\n        };\n\n        // Click handler for up button\n        $scope.moveParameterUp = function () {\n            var selectedItems = $scope.gridApi.selection.getSelectedRows();\n            if (selectedItems && selectedItems.length > 0) {\n                var index = $scope.parameters.indexOf(selectedItems[0]);\n                if (index != 0) { // If it's the first, no moving up of course\n                    var temp = $scope.parameters[index];\n                    $scope.parameters.splice(index, 1);\n                    $timeout(function () {\n                        $scope.parameters.splice(index + -1, 0, temp);\n                        $timeout(function () {\n                            $scope.gridApi.selection.toggleRowSelection(temp);\n                        });\n                    });\n                }\n            }\n        };\n\n        // Click handler for down button\n        $scope.moveParameterDown = function () {\n            var selectedItems = $scope.gridApi.selection.getSelectedRows();\n            if (selectedItems && selectedItems.length > 0) {\n                var index = $scope.parameters.indexOf(selectedItems[0]);\n                if (index != $scope.parameters.length - 1) { // If it's the last element, no moving down of course\n                    var temp = $scope.parameters[index];\n                    $scope.parameters.splice(index, 1);\n                    $timeout(function () {\n                        $scope.parameters.splice(index + 1, 0, temp);\n                        $timeout(function () {\n                            $scope.gridApi.selection.toggleRowSelection(temp);\n                        });\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": "flowable-ui-web/modeler/editor-app/configuration/properties-plan-item-lifecycle-listeners-controller.js",
    "content": "/* 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 */\nangular.module('flowableModeler').controller('FlowablePlanItemLifecycleListenersCtrl',\n    ['$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/plan-item-lifecycle-listeners-popup.html?version=' + Date.now(),\n            scope: $scope\n        };\n\n        // Open the dialog\n        _internalCreateModal(opts, $modal, $scope);\n    }]);\n\nangular.module('flowableModeler').controller('FlowablePlanItemLifecycleListenersPopupCtrl',\n    ['$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.planItemLifecycleListeners !== undefined\n            && $scope.property.value.planItemLifecycleListeners !== null) {\n\n            if ($scope.property.value.planItemLifecycleListeners.constructor == String) {\n                $scope.planItemLifecycleListeners = JSON.parse($scope.property.value.planItemLifecycleListeners);\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.planItemLifecycleListeners = angular.copy($scope.property.value.planItemLifecycleListeners);\n            }\n\n            for (var i = 0; i < $scope.planItemLifecycleListeners.length; i++) {\n                var planItemLifeCycleListener = $scope.planItemLifecycleListeners[i];\n                if (planItemLifeCycleListener.className !== undefined && planItemLifeCycleListener.className !== '') {\n                    planItemLifeCycleListener.implementation = planItemLifeCycleListener.className;\n                }\n                else if (planItemLifeCycleListener.expression !== undefined && planItemLifeCycleListener.expression !== '') {\n                    planItemLifeCycleListener.implementation = planItemLifeCycleListener.expression;\n                }\n                else if (planItemLifeCycleListener.delegateExpression !== undefined && planItemLifeCycleListener.delegateExpression !== '') {\n                    planItemLifeCycleListener.implementation = planItemLifeCycleListener.delegateExpression;\n                }\n            }\n        } else {\n            $scope.planItemLifecycleListeners = [];\n        }\n\n        $scope.selectedListener = undefined;\n        $scope.selectedField = undefined;\n        $scope.fields = [];\n        $scope.translationsRetrieved = false;\n\n        $scope.labels = {};\n\n        var sourceStatePromise = $translate('PROPERTY.PLANITEMLIFECYCLELISTENERS.SOURCE_STATE');\n        var targetStatePromise = $translate('PROPERTY.PLANITEMLIFECYCLELISTENERS.TARGET_STATE');\n        var implementationPromise = $translate('PROPERTY.PLANITEMLIFECYCLELISTENERS.FIELDS.IMPLEMENTATION');\n        var namePromise = $translate('PROPERTY.PLANITEMLIFECYCLELISTENERS.FIELDS.NAME');\n\n        $q.all([sourceStatePromise, targetStatePromise, implementationPromise, namePromise]).then(function (results) {\n            $scope.labels.sourceStateLabel = results[1];\n            $scope.labels.targetStateLabel = results[2];\n            $scope.labels.implementationLabel = results[3];\n            $scope.labels.nameLabel = results[4];\n            $scope.translationsRetrieved = true;\n\n            // Config for grid\n            $scope.gridOptions = {\n                data: $scope.planItemLifecycleListeners,\n                headerRowHeight: 28,\n                enableRowSelection: true,\n                enableRowHeaderSelection: false,\n                multiSelect: false,\n                modifierKeysToMultiSelect: false,\n                enableHorizontalScrollbar: 0,\n                enableColumnMenus: false,\n                enableSorting: false,\n                columnDefs: [\n                    {field: 'sourceState', displayName: $scope.labels.sourceStateLabel},\n                    {field: 'targetState', displayName: $scope.labels.targetStateLabel},\n                    {field: 'implementation', displayName: $scope.labels.implementationLabel}\n                ]\n            };\n\n            $scope.gridOptions.onRegisterApi = function (gridApi) {\n                //set gridApi on scope\n                $scope.gridApi = gridApi;\n                gridApi.selection.on.rowSelectionChanged($scope, function (row) {\n                    $scope.selectedListener = row.entity;\n                    $scope.selectedField = undefined;\n                    if ($scope.selectedListener) {\n                        var fields = $scope.selectedListener.fields;\n                        if (fields !== undefined && fields !== null) {\n                            for (var i = 0; i < fields.length; i++) {\n                                var field = fields[i];\n                                if (field.stringValue !== undefined && field.stringValue !== '') {\n                                    field.implementation = field.stringValue;\n                                } else if (field.expression !== undefined && field.expression !== '') {\n                                    field.implementation = field.expression;\n                                } else if (field.string !== undefined && field.string !== '') {\n                                    field.implementation = field.string;\n                                }\n                            }\n                        } else {\n                            $scope.selectedListener.fields = [];\n                        }\n\n                        $scope.fields.length = 0;\n                        for (var i = 0; i < $scope.selectedListener.fields.length; i++) {\n                            $scope.fields.push($scope.selectedListener.fields[i]);\n                        }\n                    }\n                });\n            };\n\n            // Config for field grid\n            $scope.gridFieldOptions = {\n                data: $scope.fields,\n                headerRowHeight: 28,\n                enableRowSelection: true,\n                enableRowHeaderSelection: false,\n                multiSelect: false,\n                modifierKeysToMultiSelect: false,\n                columnDefs: [{field: 'name', displayName: $scope.labels.name},\n                    {field: 'implementation', displayName: $scope.labels.implementationLabel}]\n            };\n\n            $scope.gridFieldOptions.onRegisterApi = function (gridApi) {\n                // set gridApi on scope\n                $scope.fieldGridApi = gridApi;\n                gridApi.selection.on.rowSelectionChanged($scope, function (row) {\n                    $scope.selectedField = row.entity;\n                });\n            };\n        });\n\n        $scope.listenerDetailsChanged = function () {\n            if ($scope.selectedListener.className !== '') {\n                $scope.selectedListener.implementation = $scope.selectedListener.className;\n            } else if ($scope.selectedListener.expression !== '') {\n                $scope.selectedListener.implementation = $scope.selectedListener.expression;\n            } else if ($scope.selectedListener.delegateExpression !== '') {\n                $scope.selectedListener.implementation = $scope.selectedListener.delegateExpression;\n            } else {\n                $scope.selectedListener.implementation = '';\n            }\n        };\n\n        // Click handler for add button\n        $scope.addNewListener = function () {\n            var newListener = {\n                sourceState: 'available',\n                targetState: 'active',\n                implementation: '',\n                className: '',\n                expression: '',\n                delegateExpression: ''\n            };\n            $scope.planItemLifecycleListeners.push(newListener);\n\n            $timeout(function () {\n                $scope.gridApi.selection.toggleRowSelection(newListener);\n            });\n        };\n\n        // Click handler for remove button\n        $scope.removeListener = function () {\n            var selectedItems = $scope.gridApi.selection.getSelectedRows();\n            if (selectedItems && selectedItems.length > 0) {\n                var index = $scope.planItemLifecycleListeners.indexOf(selectedItems[0]);\n                $scope.gridApi.selection.toggleRowSelection(selectedItems[0]);\n\n                $scope.planItemLifecycleListeners.splice(index, 1);\n\n                if ($scope.planItemLifecycleListeners.length == 0) {\n                    $scope.selectedListener = undefined;\n                }\n\n                $timeout(function () {\n                    if ($scope.planItemLifecycleListeners.length > 0) {\n                        $scope.gridApi.selection.toggleRowSelection($scope.planItemLifecycleListeners[0]);\n                    }\n                });\n            }\n        };\n\n        // Click handler for up button\n        $scope.moveListenerUp = function () {\n            var selectedItems = $scope.gridApi.selection.getSelectedRows();\n            if (selectedItems && selectedItems.length > 0) {\n                var index = $scope.planItemLifecycleListeners.indexOf(selectedItems[0]);\n                if (index != 0) { // If it's the first, no moving up of course\n                    var temp = $scope.planItemLifecycleListeners[index];\n                    $scope.planItemLifecycleListeners.splice(index, 1);\n                    $timeout(function () {\n                        $scope.planItemLifecycleListeners.splice(index + -1, 0, temp);\n                        $timeout(function () {\n                            $scope.gridApi.selection.toggleRowSelection(temp);\n                        });\n                    });\n                }\n            }\n        };\n\n        // Click handler for down button\n        $scope.moveListenerDown = function () {\n            var selectedItems = $scope.gridApi.selection.getSelectedRows();\n            if (selectedItems && selectedItems.length > 0) {\n                var index = $scope.planItemLifecycleListeners.indexOf(selectedItems[0]);\n                if (index != $scope.planItemLifecycleListeners.length - 1) { // If it's the last element, no moving down of course\n                    var temp = $scope.planItemLifecycleListeners[index];\n                    $scope.planItemLifecycleListeners.splice(index, 1);\n                    $timeout(function () {\n                        $scope.planItemLifecycleListeners.splice(index + 1, 0, temp);\n                        $timeout(function () {\n                            $scope.gridApi.selection.toggleRowSelection(temp);\n                        });\n                    });\n\n                }\n            }\n        };\n\n        $scope.fieldDetailsChanged = function () {\n            if ($scope.selectedField.stringValue != '') {\n                $scope.selectedField.implementation = $scope.selectedField.stringValue;\n            } else if ($scope.selectedField.expression != '') {\n                $scope.selectedField.implementation = $scope.selectedField.expression;\n            } else if ($scope.selectedField.string != '') {\n                $scope.selectedField.implementation = $scope.selectedField.string;\n            } else {\n                $scope.selectedField.implementation = '';\n            }\n        };\n\n        // Click handler for add button\n        $scope.addNewField = function () {\n            if ($scope.selectedListener) {\n                if ($scope.selectedListener.fields == undefined) {\n                    $scope.selectedListener.fields = [];\n                }\n\n                var newField = {\n                    name: 'fieldName',\n                    implementation: '',\n                    stringValue: '',\n                    expression: '',\n                    string: ''\n                };\n                $scope.fields.push(newField);\n                $scope.selectedListener.fields.push(newField);\n\n                $timeout(function () {\n                    $scope.fieldGridApi.selection.toggleRowSelection(newField);\n                });\n            }\n        };\n\n        // Click handler for remove button\n        $scope.removeField = function () {\n            var selectedItems = $scope.fieldGridApi.selection.getSelectedRows();\n            if (selectedItems && selectedItems.length > 0) {\n                var index = $scope.fields.indexOf(selectedItems[0]);\n                $scope.fieldGridApi.selection.toggleRowSelection(selectedItems[0]);\n\n                $scope.fields.splice(index, 1);\n                $scope.selectedListener.fields.splice(index, 1);\n\n                if ($scope.fields.length == 0) {\n                    $scope.selectedField = undefined;\n                }\n\n                $timeout(function () {\n                    if ($scope.fields.length > 0) {\n                        $scope.fieldGridApi.selection.toggleRowSelection($scope.fields[0]);\n                    }\n                });\n            }\n        };\n\n        // Click handler for up button\n        $scope.moveFieldUp = function () {\n            var selectedItems = $scope.fieldGridApi.selection.getSelectedRows();\n            if (selectedItems && selectedItems.length > 0) {\n                var index = $scope.fields.indexOf(selectedItems[0]);\n                if (index != 0) { // If it's the first, no moving up of course\n                    var temp = $scope.fields[index];\n                    $scope.fields.splice(index, 1);\n                    $scope.selectedListener.fields.splice(index, 1);\n                    $timeout(function () {\n                        $scope.fields.splice(index + -1, 0, temp);\n                        $scope.selectedListener.fields.splice(index + -1, 0, temp);\n                        $timeout(function () {\n                            $scope.fieldGridApi.selection.toggleRowSelection(temp);\n                        });\n                    });\n\n                }\n            }\n        };\n\n        // Click handler for down button\n        $scope.moveFieldDown = function () {\n            var selectedItems = $scope.fieldGridApi.selection.getSelectedRows();\n            if (selectedItems && selectedItems.length > 0) {\n                var index = $scope.fields.indexOf(selectedItems[0]);\n                if (index != $scope.fields.length - 1) { // If it's the last element, no moving down of course\n                    var temp = $scope.fields[index];\n                    $scope.fields.splice(index, 1);\n                    $scope.selectedListeners.fields.splice(index, 1);\n                    $timeout(function () {\n                        $scope.fields.splice(index + 1, 0, temp);\n                        $scope.selectedListener.fields.splice(index + 1, 0, temp);\n                        $timeout(function () {\n                            $scope.fieldGridApi.selection.toggleRowSelection(temp);\n                        });\n                    });\n                }\n            }\n        };\n\n        // Click handler for save button\n        $scope.save = function () {\n\n            if ($scope.planItemLifecycleListeners.length > 0) {\n                $scope.property.value = {};\n                $scope.property.value.planItemLifecycleListeners = $scope.planItemLifecycleListeners;\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    }]);\n"
  },
  {
    "path": "flowable-ui-web/modeler/editor-app/configuration/properties-planitem-dropdown-controller.js",
    "content": "/* 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\nangular.module('flowableModeler').controller('FlowablePlanItemDropdownCtrl', [ '$scope', function($scope) {\n\n    // Find all planitems\n    var selectedShape = $scope.selectedShape;\n    if (selectedShape) {\n        \n        // Go up in parent chain until plan model is found\n        var planModel;        \n        var parent = selectedShape.parent;\n        if (parent) {\n            while (planModel === undefined && parent !== null && parent !== undefined) {\n                if (parent.resourceId !== null && parent.resourceId !== undefined && 'casePlanModel' === parent.resourceId) {\n                    planModel = parent;                \n                } else {\n                    parent = parent.parent;\n                }\n            }\n        }\n        \n        var planItems = [];\n        if (planModel !== null && planModel !== undefined) {\n        \n            var toVisit = [];\n            for (var i=0; i<planModel.children.length; i++) {\n                toVisit.push(planModel.children[i]);\n            }\n            \n            while (toVisit.length > 0) {\n                var child = toVisit.pop();\n                if (typeof child.getStencil === 'function' \n                    && (child.getStencil()._jsonStencil.groups.indexOf('Activities') >= 0 || (child.getStencil()._jsonStencil.title === 'Stage') )) {\n                    planItems.push(child);\n                }\n                if (child.children !== null && child.children !== undefined) {\n                     for (var i=0; i<child.children.length; i++) {\n                        toVisit.push(child.children[i]);\n                    }\n                }\n            }\n        }\n        \n        var simplifiedPlanItems = [];\n        for (var i=0; i<planItems.length; i++) {\n            simplifiedPlanItems.push({ id: planItems[i].resourceId, name: planItems[i].properties.get('oryx-name') });\n        }\n        \n        if (simplifiedPlanItems.length > 0) {\n            simplifiedPlanItems.sort(function(a,b) {\n                if(a.name < b.name) {\n                    return -1;\n                } else if (a.name > b.name) {\n                    return 1;\n                } else {\n                    return 0;\n                }\n            });\n        }\n        $scope.planItems = simplifiedPlanItems;\n        \n    }\n\n    if ($scope.property.value == undefined && $scope.property.value == null) {\n    \t$scope.property.value = '';\n    }\n        \n    $scope.planItemChanged = function() {\n    \t$scope.updatePropertyInModel($scope.property);\n    };\n}]);"
  },
  {
    "path": "flowable-ui-web/modeler/editor-app/configuration/properties-process-historylevel-controller.js",
    "content": "/* 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\nangular.module('flowableModeler').controller('FlowableProcessHistoryLevelCtrl', [ '$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.historyLevelChanged = function() {\n    \t$scope.updatePropertyInModel($scope.property);\n    };\n}]);"
  },
  {
    "path": "flowable-ui-web/modeler/editor-app/configuration/properties-process-reference-controller.js",
    "content": "/* 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\nangular.module('flowableModeler').controller('FlowableProcessReferenceCtrl',\n    [ '$scope', '$modal', '$http', function($scope, $modal, $http) {\n\t\n     // Config for the modal window\n     var opts = {\n         template:  'editor-app/configuration/properties/process-reference-popup.html?version=' + Date.now(),\n         scope: $scope\n     };\n\n     // Open the dialog\n        _internalCreateModal(opts, $modal, $scope);\n}]);\n\nangular.module('flowableModeler').controller('FlowableProcessReferencePopupCtrl', [ '$scope', '$http', function($scope, $http) {\n\t\n    $scope.state = {'loadingProcesses' : true, 'error' : false};\n    \n    // Close button handler\n    $scope.close = function() {\n    \t$scope.property.mode = 'read';\n        $scope.$hide();\n    };\n    \n    // Selecting/deselecting a process\n    $scope.selectProcess = function(processModel, $event) {\n   \t \t$event.stopPropagation();\n   \t \tif ($scope.selectedProcess && $scope.selectedProcess.id && processModel.id == $scope.selectedProcess.id) {\n   \t \t\t// un-select the current selection\n   \t \t\t$scope.selectedProcess = null;\n   \t \t} else {\n   \t \t\t$scope.selectedProcess = processModel;\n   \t \t}\n    };\n    \n    // Saving the selected value\n    $scope.save = function() {\n   \t \tif ($scope.selectedProcess) {\n   \t \t\t$scope.property.value = {'id' : $scope.selectedProcess.id, 'name' : $scope.selectedProcess.name};\n   \t \t} else {\n   \t \t\t$scope.property.value = null; \n   \t \t}\n   \t \t$scope.updatePropertyInModel($scope.property);\n   \t \t$scope.close();\n    };\n    \n    $scope.loadProcesses = function() {\n   \t \n    \t$http.get(FLOWABLE.APP_URL.getModelsUrl(\"?modelType=0\"))\n    \t\t.success(\n    \t\t\tfunction(response) {\n    \t\t\t\t$scope.state.loadingProcesses = false;\n    \t\t\t\t$scope.state.processError = false;\n    \t\t\t\t$scope.processModels = response.data;\n    \t\t\t})\n    \t\t.error(\n    \t\t\tfunction(data, status, headers, config) {\n    \t\t\t\t$scope.state.loadingProcesses = false;\n    \t\t\t\t$scope.state.processError = true;\n    \t\t\t});\n    };\n    \n    if ($scope.property && $scope.property.value && $scope.property.value.id) {\n   \t \t$scope.selectedProcess = $scope.property.value;\n    }\n    \n    $scope.loadProcesses();  \n}]);\n"
  },
  {
    "path": "flowable-ui-web/modeler/editor-app/configuration/properties-sequenceflow-order-controller.js",
    "content": "/* Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n * \n *      http://www.apache.org/licenses/LICENSE-2.0\n * \n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/*\n * Sequence flow order controller\n */\n\nangular.module('flowableModeler').controller('FlowableSequenceFlowOrderCtrl',\n    [ '$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    _internalCreateModal(opts, $modal, $scope);\n}]);\n\nangular.module('flowableModeler').controller('FlowableSequenceFlowOrderPopupCtrl',\n    ['$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().idWithoutNs() === 'SequenceFlow') {\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.get('oryx-name'),\n                    targetType : $translate.instant(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": "flowable-ui-web/modeler/editor-app/configuration/properties-signal-definitions-controller.js",
    "content": "/* Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n * \n *      http://www.apache.org/licenses/LICENSE-2.0\n * \n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/*\n * Execution listeners\n */\n\nangular.module('flowableModeler').controller('FlowableSignalDefinitionsCtrl', ['$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    _internalCreateModal(opts, $modal, $scope);\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('flowableModeler').controller('FlowableSignalDefinitionsPopupCtrl',\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.selectedSignalDefinition = undefined;\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: $scope.signalDefinitions,\n                headerRowHeight: 28,\n                enableRowSelection: true,\n                enableRowHeaderSelection: false,\n                multiSelect: false,\n                modifierKeysToMultiSelect: false,\n                enableHorizontalScrollbar: 0,\n                enableColumnMenus: false,\n                enableSorting: false,\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            $scope.gridOptions.onRegisterApi = function (gridApi) {\n                //set gridApi on scope\n                $scope.gridApi = gridApi;\n                gridApi.selection.on.rowSelectionChanged($scope, function (row) {\n                    $scope.selectedSignalDefinition = row.entity;\n                });\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                $scope.gridApi.selection.toggleRowSelection(newSignalDefinition);\n            });\n        };\n\n        // Click handler for remove button\n        $scope.removeSignalDefinition = function () {\n            var selectedItems = $scope.gridApi.selection.getSelectedRows();\n            if (selectedItems && selectedItems.length > 0) {\n                var index = $scope.signalDefinitions.indexOf(selectedItems[0]);\n                $scope.gridApi.selection.toggleRowSelection(selectedItems[0]);\n                $scope.signalDefinitions.splice(index, 1);\n\n                if ($scope.signalDefinitions.length == 0) {\n                    $scope.selectedSignalDefinition = undefined;\n                }\n\n                $timeout(function () {\n                    if ($scope.signalDefinitions.length > 0) {\n                        $scope.gridApi.selection.toggleRowSelection($scope.signalDefinitions[0]);\n                    }\n                });\n            }\n        };\n\n        $scope.scopeOptions = [{'value': 'global', 'translationId': 'PROPERTY.SIGNALDEFINITIONS.SCOPE-GLOBAL'},\n                                {'value': 'processInstance', 'translationId': 'PROPERTY.SIGNALDEFINITIONS.SCOPE-PROCESSINSTANCE'}];\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": "flowable-ui-web/modeler/editor-app/configuration/properties-signal-scope-controller.js",
    "content": "/* 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\nangular.module('flowableModeler').controller('FlowableSignalRefCtrl', [ '$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.get('oryx-signaldefinitions')) {\n            signalDefinitionsProperty = parent.properties.get('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": "flowable-ui-web/modeler/editor-app/configuration/properties-task-listeners-controller.js",
    "content": "/* Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n * \n *      http://www.apache.org/licenses/LICENSE-2.0\n * \n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/*\n * Task listeners\n */\n\nangular.module('flowableModeler').controller('FlowableTaskListenersCtrl',\n    ['$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        _internalCreateModal(opts, $modal, $scope);\n    }]);\n\nangular.module('flowableModeler').controller('FlowableTaskListenersPopupCtrl',\n    ['$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.taskListeners !== undefined\n            && $scope.property.value.taskListeners !== null) {\n\n            if ($scope.property.value.taskListeners.constructor == String) {\n                $scope.taskListeners = JSON.parse($scope.property.value.taskListeners);\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.taskListeners = angular.copy($scope.property.value.taskListeners);\n            }\n\n            for (var i = 0; i < $scope.taskListeners.length; i++) {\n                var taskListener = $scope.taskListeners[i];\n                if (taskListener.className !== undefined && taskListener.className !== '') {\n                    taskListener.implementation = taskListener.className;\n                }\n                else if (taskListener.expression !== undefined && taskListener.expression !== '') {\n                    taskListener.implementation = taskListener.expression;\n                }\n                else if (taskListener.delegateExpression !== undefined && taskListener.delegateExpression !== '') {\n                    taskListener.implementation = taskListener.delegateExpression;\n                }\n            }\n        } else {\n            $scope.taskListeners = [];\n        }\n\n        $scope.selectedListener = undefined;\n        $scope.selectedField = undefined;\n        $scope.fields = [];\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: $scope.taskListeners,\n                headerRowHeight: 28,\n                enableRowSelection: true,\n                enableRowHeaderSelection: false,\n                multiSelect: false,\n                modifierKeysToMultiSelect: false,\n                enableHorizontalScrollbar: 0,\n                enableColumnMenus: false,\n                enableSorting: false,\n                columnDefs: [{field: 'event', displayName: $scope.labels.eventLabel},\n                    {field: 'implementation', displayName: $scope.labels.implementationLabel}]\n            };\n\n            $scope.gridOptions.onRegisterApi = function (gridApi) {\n                //set gridApi on scope\n                $scope.gridApi = gridApi;\n                gridApi.selection.on.rowSelectionChanged($scope, function (row) {\n                    $scope.selectedListener = row.entity;\n                    $scope.selectedField = undefined;\n                    if ($scope.selectedListener) {\n                        var fields = $scope.selectedListener.fields;\n                        if (fields !== undefined && fields !== null) {\n                            for (var i = 0; i < fields.length; i++) {\n                                var field = fields[i];\n                                if (field.stringValue !== undefined && field.stringValue !== '') {\n                                    field.implementation = field.stringValue;\n                                } else if (field.expression !== undefined && field.expression !== '') {\n                                    field.implementation = field.expression;\n                                } else if (field.string !== undefined && field.string !== '') {\n                                    field.implementation = field.string;\n                                }\n                            }\n                        } else {\n                            $scope.selectedListener.fields = [];\n                        }\n\n                        $scope.fields.length = 0;\n                        for (var i = 0; i < $scope.selectedListener.fields.length; i++) {\n                            $scope.fields.push($scope.selectedListener.fields[i]);\n                        }\n                    }\n                });\n            };\n\n            // Config for field grid\n            $scope.gridFieldOptions = {\n                data: $scope.fields,\n                headerRowHeight: 28,\n                enableRowSelection: true,\n                enableRowHeaderSelection: false,\n                multiSelect: false,\n                modifierKeysToMultiSelect: false,\n                columnDefs: [{field: 'name', displayName: $scope.labels.name},\n                    {field: 'implementation', displayName: $scope.labels.implementationLabel}]\n            };\n\n            $scope.gridFieldOptions.onRegisterApi = function (gridApi) {\n                // set gridApi on scope\n                $scope.fieldGridApi = gridApi;\n                gridApi.selection.on.rowSelectionChanged($scope, function (row) {\n                    $scope.selectedField = row.entity;\n                });\n            };\n        });\n\n        $scope.listenerDetailsChanged = function () {\n            if ($scope.selectedListener.className !== '') {\n                $scope.selectedListener.implementation = $scope.selectedListener.className;\n            } else if ($scope.selectedListener.expression !== '') {\n                $scope.selectedListener.implementation = $scope.selectedListener.expression;\n            } else if ($scope.selectedListener.delegateExpression !== '') {\n                $scope.selectedListener.implementation = $scope.selectedListener.delegateExpression;\n            } else {\n                $scope.selectedListener.implementation = '';\n            }\n        };\n\n        // Click handler for add button\n        $scope.addNewListener = function () {\n            var newListener = {\n                event: 'create',\n                implementation: '',\n                className: '',\n                expression: '',\n                delegateExpression: ''\n            };\n            $scope.taskListeners.push(newListener);\n\n            $timeout(function () {\n                $scope.gridApi.selection.toggleRowSelection(newListener);\n            });\n        };\n\n        // Click handler for remove button\n        $scope.removeListener = function () {\n            var selectedItems = $scope.gridApi.selection.getSelectedRows();\n            if (selectedItems && selectedItems.length > 0) {\n                var index = $scope.taskListeners.indexOf(selectedItems[0]);\n                $scope.gridApi.selection.toggleRowSelection(selectedItems[0]);\n\n                $scope.taskListeners.splice(index, 1);\n\n                if ($scope.taskListeners.length == 0) {\n                    $scope.selectedListener = undefined;\n                }\n\n                $timeout(function () {\n                    if ($scope.taskListeners.length > 0) {\n                        $scope.gridApi.selection.toggleRowSelection($scope.taskListeners[0]);\n                    }\n                });\n            }\n        };\n\n        // Click handler for up button\n        $scope.moveListenerUp = function () {\n            var selectedItems = $scope.gridApi.selection.getSelectedRows();\n            if (selectedItems && selectedItems.length > 0) {\n                var index = $scope.taskListeners.indexOf(selectedItems[0]);\n                if (index != 0) { // If it's the first, no moving up of course\n                    var temp = $scope.taskListeners[index];\n                    $scope.taskListeners.splice(index, 1);\n                    $timeout(function () {\n                        $scope.taskListeners.splice(index + -1, 0, temp);\n                        $timeout(function () {\n                            $scope.gridApi.selection.toggleRowSelection(temp);\n                        });\n                    });\n                }\n            }\n        };\n\n        // Click handler for down button\n        $scope.moveListenerDown = function () {\n            var selectedItems = $scope.gridApi.selection.getSelectedRows();\n            if (selectedItems && selectedItems.length > 0) {\n                var index = $scope.taskListeners.indexOf(selectedItems[0]);\n                if (index != $scope.taskListeners.length - 1) { // If it's the last element, no moving down of course\n                    var temp = $scope.taskListeners[index];\n                    $scope.taskListeners.splice(index, 1);\n                    $timeout(function () {\n                        $scope.taskListeners.splice(index + 1, 0, temp);\n                        $timeout(function () {\n                            $scope.gridApi.selection.toggleRowSelection(temp);\n                        });\n                    });\n\n                }\n            }\n        };\n\n        $scope.fieldDetailsChanged = function () {\n            if ($scope.selectedField.stringValue != '') {\n                $scope.selectedField.implementation = $scope.selectedField.stringValue;\n            } else if ($scope.selectedField.expression != '') {\n                $scope.selectedField.implementation = $scope.selectedField.expression;\n            } else if ($scope.selectedField.string != '') {\n                $scope.selectedField.implementation = $scope.selectedField.string;\n            } else {\n                $scope.selectedField.implementation = '';\n            }\n        };\n\n        // Click handler for add button\n        $scope.addNewField = function () {\n            if ($scope.selectedListener) {\n                if ($scope.selectedListener.fields == undefined) {\n                    $scope.selectedListener.fields = [];\n                }\n\n                var newField = {\n                    name: 'fieldName',\n                    implementation: '',\n                    stringValue: '',\n                    expression: '',\n                    string: ''\n                };\n                $scope.fields.push(newField);\n                $scope.selectedListener.fields.push(newField);\n\n                $timeout(function () {\n                    $scope.fieldGridApi.selection.toggleRowSelection(newField);\n                });\n            }\n        };\n\n        // Click handler for remove button\n        $scope.removeField = function () {\n            var selectedItems = $scope.fieldGridApi.selection.getSelectedRows();\n            if (selectedItems && selectedItems.length > 0) {\n                var index = $scope.fields.indexOf(selectedItems[0]);\n                $scope.fieldGridApi.selection.toggleRowSelection(selectedItems[0]);\n\n                $scope.fields.splice(index, 1);\n                $scope.selectedListener.fields.splice(index, 1);\n\n                if ($scope.fields.length == 0) {\n                    $scope.selectedField = undefined;\n                }\n\n                $timeout(function () {\n                    if ($scope.fields.length > 0) {\n                        $scope.fieldGridApi.selection.toggleRowSelection($scope.fields[0]);\n                    }\n                });\n            }\n        };\n\n        // Click handler for up button\n        $scope.moveFieldUp = function () {\n            var selectedItems = $scope.fieldGridApi.selection.getSelectedRows();\n            if (selectedItems && selectedItems.length > 0) {\n                var index = $scope.fields.indexOf(selectedItems[0]);\n                if (index != 0) { // If it's the first, no moving up of course\n                    var temp = $scope.fields[index];\n                    $scope.fields.splice(index, 1);\n                    $scope.selectedListener.fields.splice(index, 1);\n                    $timeout(function () {\n                        $scope.fields.splice(index + -1, 0, temp);\n                        $scope.selectedListener.fields.splice(index + -1, 0, temp);\n                        $timeout(function () {\n                            $scope.fieldGridApi.selection.toggleRowSelection(temp);\n                        });\n                    });\n\n                }\n            }\n        };\n\n        // Click handler for down button\n        $scope.moveFieldDown = function () {\n            var selectedItems = $scope.fieldGridApi.selection.getSelectedRows();\n            if (selectedItems && selectedItems.length > 0) {\n                var index = $scope.fields.indexOf(selectedItems[0]);\n                if (index != $scope.fields.length - 1) { // If it's the last element, no moving down of course\n                    var temp = $scope.fields[index];\n                    $scope.fields.splice(index, 1);\n                    $scope.selectedListeners.fields.splice(index, 1);\n                    $timeout(function () {\n                        $scope.fields.splice(index + 1, 0, temp);\n                        $scope.selectedListener.fields.splice(index + 1, 0, temp);\n                        $timeout(function () {\n                            $scope.fieldGridApi.selection.toggleRowSelection(temp);\n                        });\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    }]);\n"
  },
  {
    "path": "flowable-ui-web/modeler/editor-app/configuration/properties-transition-event-controller.js",
    "content": "/* Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n * \n *      http://www.apache.org/licenses/LICENSE-2.0\n * \n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/*\n * Execution listeners\n */\n\nangular.module('flowableModeler').controller('FlowableTransitionEventCtrl', [ '$scope', function($scope) {\n\n    if ($scope.property.value == undefined && $scope.property.value == null) {\n    \t$scope.property.value = 'complete';\n    }\n        \n    $scope.transitionEventChanged = function() {\n    \t$scope.updatePropertyInModel($scope.property);\n    };\n}]);"
  },
  {
    "path": "flowable-ui-web/modeler/editor-app/configuration/properties-trigger-mode-controller.js",
    "content": "/* 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\nangular.module('flowableModeler').controller('FlowableTriggerModeCtrl', [ '$scope', function($scope) {\n\n    if ($scope.property.value === undefined || $scope.property.value == null) {\n    \t$scope.property.value = 'default';\n    }\n        \n    $scope.triggerModeChanged = function() {\n    \t$scope.updatePropertyInModel($scope.property);\n    };\n}]);"
  },
  {
    "path": "flowable-ui-web/modeler/editor-app/configuration/properties.js",
    "content": "/* 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'use strict';\n\nvar FLOWABLE = FLOWABLE || {};\nFLOWABLE.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    \"flowable-calledelementtype\" : {\n        \"readModeTemplateUrl\": \"editor-app/configuration/properties/default-value-display-template.html\",\n        \"writeModeTemplateUrl\": \"editor-app/configuration/properties/calledelementtype-property-write-template.html\"\n    },\n    \"flowable-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    \"flowable-processhistorylevel\" : {\n        \"readModeTemplateUrl\": \"editor-app/configuration/properties/default-value-display-template.html\",\n        \"writeModeTemplateUrl\": \"editor-app/configuration/properties/process-historylevel-property-write-template.html\"\n    },\n    \"flowable-ordering\" : {\n        \"readModeTemplateUrl\": \"editor-app/configuration/properties/default-value-display-template.html\",\n        \"writeModeTemplateUrl\": \"editor-app/configuration/properties/ordering-property-write-template.html\"\n    },\n    \"oryx-dataproperties-complex\": {\n        \"readModeTemplateUrl\": \"editor-app/configuration/properties/data-properties-display-template.html\",\n        \"writeModeTemplateUrl\": \"editor-app/configuration/properties/data-properties-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-subprocess-link\": {\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-formreference-complex\": {\n        \"readModeTemplateUrl\": \"editor-app/configuration/properties/form-reference-display-template.html\",\n        \"writeModeTemplateUrl\": \"editor-app/configuration/properties/form-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    \"oryx-duedatedefinition-complex\": {\n        \"readModeTemplateUrl\": \"editor-app/configuration/properties/duedate-display-template.html\",\n        \"writeModeTemplateUrl\": \"editor-app/configuration/properties/duedate-write-template.html\"\n    },\n    \"oryx-decisiontaskdecisiontablereference-complex\": {\n        \"readModeTemplateUrl\": \"editor-app/configuration/properties/decisiontable-reference-display-template.html\",\n        \"writeModeTemplateUrl\": \"editor-app/configuration/properties/decisiontable-reference-write-template.html\"\n    },\n    \"oryx-casetaskcasereference-complex\": {\n        \"readModeTemplateUrl\": \"editor-app/configuration/properties/case-reference-display-template.html\",\n        \"writeModeTemplateUrl\": \"editor-app/configuration/properties/case-reference-write-template.html\"\n    },\n    \"oryx-processtaskprocessreference-complex\": {\n        \"readModeTemplateUrl\": \"editor-app/configuration/properties/process-reference-display-template.html\",\n        \"writeModeTemplateUrl\": \"editor-app/configuration/properties/process-reference-write-template.html\"\n    },\n    \"oryx-processtaskinparameters-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-processtaskoutparameters-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-planitemlifecyclelisteners-multiplecomplex\": {\n            \"readModeTemplateUrl\": \"editor-app/configuration/properties/plan-item-lifecycle-listeners-display-template.html\",\n            \"writeModeTemplateUrl\": \"editor-app/configuration/properties/plan-item-lifecycle-listeners-write-template.html\"\n     },\n    \"flowable-transitionevent\" : {\n        \"readModeTemplateUrl\": \"editor-app/configuration/properties/default-value-display-template.html\",\n        \"writeModeTemplateUrl\": \"editor-app/configuration/properties/transition-event-write-template.html\"\n    },\n    \"flowable-planitem-dropdown\" : {\n        \"readModeTemplateUrl\": \"editor-app/configuration/properties/planitem-dropdown-read-template.html\",\n        \"writeModeTemplateUrl\": \"editor-app/configuration/properties/planitem-dropdown-write-template.html\"\n    },\n    \"flowable-http-request-method\" : {\n        \"readModeTemplateUrl\": \"editor-app/configuration/properties/http-request-method-display-template.html\",\n        \"writeModeTemplateUrl\": \"editor-app/configuration/properties/http-request-method-property-write-template.html\"\n    },\n    \"flowable-triggermode\" : {\n            \"readModeTemplateUrl\": \"editor-app/configuration/properties/trigger-mode-read-template.html\",\n            \"writeModeTemplateUrl\": \"editor-app/configuration/properties/trigger-mode-write-template.html\"\n    },\n};\n"
  },
  {
    "path": "flowable-ui-web/modeler/editor-app/configuration/toolbar-custom-actions.js",
    "content": "/* 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"
  },
  {
    "path": "flowable-ui-web/modeler/editor-app/configuration/toolbar-default-actions.js",
    "content": "/* 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'use strict';\n\nvar FLOWABLE = FLOWABLE || {};\nFLOWABLE.TOOLBAR = {\n    ACTIONS: {\n    \t\n        saveModel: function (services) {\n\n            _internalCreateModal({\n                backdrop: true,\n                keyboard: true,\n                template: 'editor-app/popups/save-model.html?version=' + Date.now(),\n                scope: services.$scope\n            }, services.$modal, services.$scope);\n        },\n        \n        validate: function(services) {\n        \t\n        \t_internalCreateModal({\n                backdrop: true,\n                keyboard: true,\n                template: 'editor-app/popups/validate-model.html?version=' + Date.now(),\n                scope: services.$scope\n            }, services.$modal, services.$scope);\n\t\t},\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.editorManager.handleEvents({\n                    type: ORYX.CONFIG.EVENT_UNDO_ROLLBACK,\n                    commands: lastCommands\n                });\n                \n                // Update\n                services.editorManager.getCanvas().update();\n                services.editorManager.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 === 'FLOWABLE.TOOLBAR.ACTIONS.undo') {\n                        services.$scope.safeApply(function () {\n                            item.enabled = false;\n                        });\n                    }\n                    else if (toggleRedo && item.action === 'FLOWABLE.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.editorManager.handleEvents({\n                    type: ORYX.CONFIG.EVENT_UNDO_EXECUTE,\n                    commands: lastCommands\n                });\n\n                // Update\n                services.editorManager.getCanvas().update();\n                services.editorManager.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 === 'FLOWABLE.TOOLBAR.ACTIONS.undo') {\n                        services.$scope.safeApply(function () {\n                            item.enabled = true;\n                        });\n                    }\n                    else if (toggleRedo && item.action === 'FLOWABLE.TOOLBAR.ACTIONS.redo') {\n                        services.$scope.safeApply(function () {\n                            item.enabled = false;\n                        });\n                    }\n                }\n            }\n        },\n\n        cut: function (services) {\n            FLOWABLE.TOOLBAR.ACTIONS._getOryxEditPlugin(services).editCut();\n            for (var i = 0; i < services.$scope.items.length; i++) {\n                var item = services.$scope.items[i];\n                if (item.action === 'FLOWABLE.TOOLBAR.ACTIONS.paste') {\n                    services.$scope.safeApply(function () {\n                        item.enabled = true;\n                    });\n                }\n            }\n        },\n\n        copy: function (services) {\n            FLOWABLE.TOOLBAR.ACTIONS._getOryxEditPlugin(services).editCopy();\n            for (var i = 0; i < services.$scope.items.length; i++) {\n                var item = services.$scope.items[i];\n                if (item.action === 'FLOWABLE.TOOLBAR.ACTIONS.paste') {\n                    services.$scope.safeApply(function () {\n                        item.enabled = true;\n                    });\n                }\n            }\n        },\n\n        paste: function (services) {\n            FLOWABLE.TOOLBAR.ACTIONS._getOryxEditPlugin(services).editPaste();\n        },\n\n        deleteItem: function (services) {\n            FLOWABLE.TOOLBAR.ACTIONS._getOryxEditPlugin(services).editDelete();\n        },\n\n        addBendPoint: function (services) {\n\n            // Show the tutorial the first time\n            FLOWABLE_EDITOR_TOUR.sequenceFlowBendpoint(services.$scope, services.$translate, services.$q, true);\n\n            var dockerPlugin = FLOWABLE.TOOLBAR.ACTIONS._getOryxDockerPlugin(services);\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            // Show the tutorial the first time\n            FLOWABLE_EDITOR_TOUR.sequenceFlowBendpoint(services.$scope, services.$translate, services.$q, true);\n\n            var dockerPlugin = FLOWABLE.TOOLBAR.ACTIONS._getOryxDockerPlugin(services);\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 (services) {\n        \tvar $scope = services.$scope;\n\t\t\tvar editorManager = services.editorManager;\n            if ($scope.oryxEditPlugin === undefined || $scope.oryxEditPlugin === null) {\n                $scope.oryxEditPlugin = new ORYX.Plugins.Edit(editorManager.getEditor());\n            }\n            return $scope.oryxEditPlugin;\n        },\n\n        zoomIn: function (services) {\n            FLOWABLE.TOOLBAR.ACTIONS._getOryxViewPlugin(services).zoom([1.0 + ORYX.CONFIG.ZOOM_OFFSET]);\n        },\n\n        zoomOut: function (services) {\n            FLOWABLE.TOOLBAR.ACTIONS._getOryxViewPlugin(services).zoom([1.0 - ORYX.CONFIG.ZOOM_OFFSET]);\n        },\n        \n        zoomActual: function (services) {\n            FLOWABLE.TOOLBAR.ACTIONS._getOryxViewPlugin(services).setAFixZoomLevel(1);\n        },\n        \n        zoomFit: function (services) {\n        \tFLOWABLE.TOOLBAR.ACTIONS._getOryxViewPlugin(services).zoomFitToModel();\n        },\n        \n        alignVertical: function (services) {\n        \tFLOWABLE.TOOLBAR.ACTIONS._getOryxArrangmentPlugin(services).alignShapes([ORYX.CONFIG.EDITOR_ALIGN_CENTER]);\n        },\n        \n        alignHorizontal: function (services) {\n        \tFLOWABLE.TOOLBAR.ACTIONS._getOryxArrangmentPlugin(services).alignShapes([ORYX.CONFIG.EDITOR_ALIGN_MIDDLE]);\n        },\n        \n        sameSize: function (services) {\n        \tFLOWABLE.TOOLBAR.ACTIONS._getOryxArrangmentPlugin(services).alignShapes([ORYX.CONFIG.EDITOR_ALIGN_SIZE]);\n        },\n\n        help: function (services) {\n            FLOWABLE_EDITOR_TOUR.gettingStarted(services.$scope, services.$translate, services.$q);\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 (services) {\n        \tvar $scope = services.$scope;\n\t\t\tvar editorManager = services.editorManager;\n            if ($scope.oryxViewPlugin === undefined || $scope.oryxViewPlugin === null) {\n                $scope.oryxViewPlugin = new ORYX.Plugins.View(editorManager.getEditor());\n            }\n            return $scope.oryxViewPlugin;\n        },\n        \n        _getOryxArrangmentPlugin: function (services) {\n        \tvar $scope = services.$scope;\n\t\t\tvar editorManager = services.editorManager;\n            if ($scope.oryxArrangmentPlugin === undefined || $scope.oryxArrangmentPlugin === null) {\n                $scope.oryxArrangmentPlugin = new ORYX.Plugins.Arrangement(editorManager.getEditor());\n            }\n            return $scope.oryxArrangmentPlugin;\n        },\n\n        _getOryxDockerPlugin: function (services) {\n        \tvar $scope = services.$scope;\n\t\t\tvar editorManager = services.editorManager;\n            if ($scope.oryxDockerPlugin === undefined || $scope.oryxDockerPlugin === null) {\n                $scope.oryxDockerPlugin = new ORYX.Plugins.AddDocker(editorManager.getEditor());\n            }\n            return $scope.oryxDockerPlugin;\n        }\n    }\n};\n\n/** Custom controller for the save dialog */\nangular.module('flowableModeler').controller('SaveModelCtrl', [ '$rootScope', '$scope', '$http', '$route', '$location', 'editorManager',\n    function ($rootScope, $scope, $http, $route, $location, editorManager) {\n\n\tif (editorManager.getCurrentModelId() != editorManager.getModelId()) {\n\t\teditorManager.edit(editorManager.getModelId());\n\t}\n\t\n    var modelMetaData = editorManager.getBaseModelData();\n\n    var description = '';\n    if (modelMetaData.description) {\n    \tdescription = modelMetaData.description;\n    }\n    \n    var saveDialog = { \n    \t'name' : modelMetaData.name,\n    \t'key' : modelMetaData.key,\n        'description' : description,\n        'newVersion' : false,\n        'comment' : ''\n    };\n    \n    $scope.saveDialog = saveDialog;\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            if (editorManager.getStencilData()) {\n                var stencilNameSpace = editorManager.getStencilData().namespace;\n                if (stencilNameSpace !== undefined && stencilNameSpace !== null && stencilNameSpace.indexOf('cmmn1.1') !== -1) {\n                    $location.path(\"/casemodels\");\n                \treturn;\n            \t}\n        \t}\n        \t$location.path('/processes');\n    \t});\n    };\n    \n    $scope.save = function (successCallback) {\n\n        if (!$scope.saveDialog.name || $scope.saveDialog.name.length == 0 ||\n        \t!$scope.saveDialog.key || $scope.saveDialog.key.length == 0) {\n        \t\n            return;\n        }\n\n        // Indicator spinner image\n        $scope.status = {\n        \tloading: true\n        };\n        \n        modelMetaData.name = $scope.saveDialog.name;\n        modelMetaData.key = $scope.saveDialog.key;\n        modelMetaData.description = $scope.saveDialog.description;\n\n        var json = editorManager.getModel();\n\n        var params = {\n            modeltype: modelMetaData.model.modelType,\n            json_xml: JSON.stringify(json),\n            name: $scope.saveDialog.name,\n            key: $scope.saveDialog.key,\n            description: $scope.saveDialog.description,\n            newversion: $scope.saveDialog.newVersion,\n            comment: $scope.saveDialog.comment,\n            lastUpdated: modelMetaData.lastUpdated\n        };\n\n        if ($scope.error && $scope.error.isConflict) {\n            params.conflictResolveAction = $scope.error.conflictResolveAction;\n            if ($scope.error.conflictResolveAction === 'saveAs') {\n                params.saveAs = $scope.error.saveAs;\n            }\n        }\n\n        // Update\n        $http({    method: 'POST',\n            data: params,\n            ignoreErrors: true,\n            headers: {'Accept': 'application/json',\n                      'Content-Type': 'application/x-www-form-urlencoded; 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: FLOWABLE.URL.putModel(modelMetaData.modelId)})\n\n            .success(function (data, status, headers, config) {\n                editorManager.handleEvents({\n                    type: ORYX.CONFIG.EVENT_SAVED\n                });\n                $scope.modelData.name = $scope.saveDialog.name;\n                $scope.modelData.key = $scope.saveDialog.key;\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: FLOWABLE.eventBus.EVENT_TYPE_MODEL_SAVED,\n                    model: params,\n                    modelId: modelMetaData.modelId,\n\t\t            eventType: 'update-model'\n                };\n                FLOWABLE.eventBus.dispatch(FLOWABLE.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                if (status == 409) {\n                \t$scope.error = {};\n                    $scope.error.isConflict = true;\n                    $scope.error.userFullName = data.customData.userFullName;\n                    $scope.error.isNewVersionAllowed = data.customData.newVersionAllowed;\n                    $scope.error.saveAs = modelMetaData.name + \"_2\";\n                } else {\n                \t$scope.error = undefined;\n                    $scope.saveDialog.errorMessage = data.message;\n                }\n                $scope.status.loading = false;\n            });\n    };\n\n    $scope.isOkButtonDisabled = function() {\n        if ($scope.status.loading) {\n            return false;\n        } else if ($scope.error && $scope.error.conflictResolveAction) {\n            if ($scope.error.conflictResolveAction === 'saveAs') {\n                return !$scope.error.saveAs || $scope.error.saveAs.length == 0;\n            } else {\n                return false;\n            }\n        }\n        return true;\n    };\n\n    $scope.okClicked = function() {\n        if ($scope.error) {\n            if ($scope.error.conflictResolveAction === 'discardChanges') {\n                $scope.close();\n                $route.reload();\n            } else if ($scope.error.conflictResolveAction === 'overwrite'\n                || $scope.error.conflictResolveAction === 'newVersion') {\n                $scope.save();\n            } else if($scope.error.conflictResolveAction === 'saveAs') {\n                $scope.save(function() {\n                    $rootScope.ignoreChanges = true;  // Otherwise will get pop up that changes are not saved.\n                    if (editorManager.getStencilData()) {\n                        var stencilNameSpace = editorManager.getStencilData().namespace;\n                        if (stencilNameSpace !== undefined && stencilNameSpace !== null && stencilNameSpace.indexOf('cmmn1.1') !== -1) {\n                            $location.path(\"/casemodels\");\n                            return;\n                        }\n                    }\n                    $location.path('/processes');\n            \t});\n            }\n        }\n    };\n\n}]);\n\nangular.module('flowableModeler').controller('ValidateModelCtrl',['$scope', '$http', 'editorManager',\n    function ($scope, $http, editorManager) {\n    \n        var editor = editorManager.getEditor();\n        var model = editorManager.getModel();\n        \n        $scope.status = {\n            loading: true\n        };\n\n        $scope.model = {\n        \terrors: []\n        };\n        \n        $scope.errorGrid = {\n            data: $scope.model.errors,\n            headerRowHeight: 28,\n        \tenableRowSelection: true,\n        \tenableRowHeaderSelection: false,\n        \tmultiSelect: false,\n        \tmodifierKeysToMultiSelect: false,\n        \tenableHorizontalScrollbar: 0,\n\t\t\tenableColumnMenus: false,\n\t\t\tenableSorting: false,\n            columnDefs: [\n                {field: 'activityName', displayName: 'Name', width:125},\n                {field: 'defaultDescription', displayName: 'Description'},\n                {field: 'warning', displayName: 'Critical', cellTemplate:'editor-app/configuration/properties/errorgrid-critical.html', width: 100}\n            ]\n        };\n        \n        $scope.errorGrid.onRegisterApi = function(gridApi) {\n\t        //set gridApi on scope\n\t        $scope.gridApi = gridApi;\n\t        gridApi.selection.on.rowSelectionChanged($scope, function(row) {\n\t            if (row.isSelected) {\n\t                editorManager.navigateTo(row.entity.activityId);\n            \t\t$scope.$hide();\n\t            }\n\t        });\n\t    };\n\n        $http({\n            url: FLOWABLE.URL.validateModel(),\n            method: 'POST',\n            cache: false,\n            headers: {\n                \"Content-Type\":\"application/json;charset=utf-8\"\n            },\n            data: model\n            \n        }).then(function(response){\n        \t$scope.status.loading = false;\n            response.data.forEach(function (row) {\n                $scope.model.errors.push(row);\n            });\n            \n        },function(response){\n            console.log(response);\n        });\n    }\n]);\n"
  },
  {
    "path": "flowable-ui-web/modeler/editor-app/configuration/toolbar.js",
    "content": "/* 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'use strict';\n\nvar FLOWABLE = FLOWABLE || {};\nFLOWABLE.TOOLBAR_CONFIG = {\n    \"items\" : [\n        {\n            \"type\" : \"button\",\n            \"title\" : \"TOOLBAR.ACTION.SAVE\",\n            \"cssClass\" : \"editor-icon editor-icon-save\",\n            \"action\" : \"FLOWABLE.TOOLBAR.ACTIONS.saveModel\"\n        },\n        {\n\t\t\t\"type\" : \"button\",\n\t\t\t\"title\" : \"TOOLBAR.ACTION.VALIDATE\",\n\t\t\t\"cssClass\" : \"glyphicon glyphicon-ok\",\n\t\t\t\"action\": \"FLOWABLE.TOOLBAR.ACTIONS.validate\"\n\t\t},\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\" : \"FLOWABLE.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\" : \"FLOWABLE.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\" : \"FLOWABLE.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\" : \"FLOWABLE.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\" : \"FLOWABLE.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\" : \"FLOWABLE.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\" : \"FLOWABLE.TOOLBAR.ACTIONS.alignVertical\",\n            \"enabled\" : false,\n            \"enabledAction\" : \"element\",\n            \"disableInForm\" : true,\n            \"minSelectionCount\" : 2\n        },\n        {\n            \"type\" : \"button\",\n            \"title\" : \"TOOLBAR.ACTION.ALIGNHORIZONTAL\",\n            \"cssClass\" : \"editor-icon editor-icon-align-horizontal\",\n            \"action\" : \"FLOWABLE.TOOLBAR.ACTIONS.alignHorizontal\",\n            \"enabledAction\" : \"element\",\n            \"enabled\" : false,\n            \"disableInForm\" : true,\n            \"minSelectionCount\" : 2\n        },\n        {\n            \"type\" : \"button\",\n            \"title\" : \"TOOLBAR.ACTION.SAMESIZE\",\n            \"cssClass\" : \"editor-icon editor-icon-same-size\",\n            \"action\" : \"FLOWABLE.TOOLBAR.ACTIONS.sameSize\",\n            \"enabledAction\" : \"element\",\n            \"enabled\" : false,\n            \"disableInForm\" : true,\n            \"minSelectionCount\" : 2\n        },\n        {\n        \t\"type\" : \"separator\",\n        \t\"title\" : \"TOOLBAR.ACTION.SAVE\",\n        \t\"cssClass\" : \"toolbar-separator\",\n        \t\"disableInForm\" : true\n        },\n        {\n            \"type\" : \"button\",\n            \"title\" : \"TOOLBAR.ACTION.ZOOMIN\",\n            \"cssClass\" : \"editor-icon editor-icon-zoom-in\",\n            \"action\" : \"FLOWABLE.TOOLBAR.ACTIONS.zoomIn\"\n        },\n        {\n            \"type\" : \"button\",\n            \"title\" : \"TOOLBAR.ACTION.ZOOMOUT\",\n            \"cssClass\" : \"editor-icon editor-icon-zoom-out\",\n            \"action\" : \"FLOWABLE.TOOLBAR.ACTIONS.zoomOut\"\n        },\n        {\n            \"type\" : \"button\",\n            \"title\" : \"TOOLBAR.ACTION.ZOOMACTUAL\",\n            \"cssClass\" : \"editor-icon editor-icon-zoom-actual\",\n            \"action\" : \"FLOWABLE.TOOLBAR.ACTIONS.zoomActual\"\n        },\n        {\n            \"type\" : \"button\",\n            \"title\" : \"TOOLBAR.ACTION.ZOOMFIT\",\n            \"cssClass\" : \"editor-icon editor-icon-zoom-fit\",\n            \"action\" : \"FLOWABLE.TOOLBAR.ACTIONS.zoomFit\"\n        },\n        {\n            \"type\" : \"separator\",\n            \"title\" : \"TOOLBAR.ACTION.SAVE\",\n            \"cssClass\" : \"toolbar-separator\",\n            \"disableInForm\" : true\n        },\n    \t{\n            \"type\" : \"button\",\n            \"title\" : \"TOOLBAR.ACTION.BENDPOINT.ADD\",\n            \"cssClass\" : \"editor-icon editor-icon-bendpoint-add\",\n            \"action\" : \"FLOWABLE.TOOLBAR.ACTIONS.addBendPoint\",\n            \"id\" : \"add-bendpoint-button\",\n            \"disableInForm\" : true\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\" : \"FLOWABLE.TOOLBAR.ACTIONS.removeBendPoint\",\n    \t    \"id\" : \"remove-bendpoint-button\",\n    \t    \"disableInForm\" : true\n    \t},\n        {\n            \"type\" : \"separator\",\n            \"title\": \"\",\n            \"cssClass\" : \"toolbar-separator\",\n            \"disableInForm\" : true\n        },\n        {\n            \"type\" : \"button\",\n            \"title\" : \"TOOLBAR.ACTION.HELP\",\n            \"cssClass\" : \"glyphicon glyphicon-question-sign\",\n            \"action\" : \"FLOWABLE.TOOLBAR.ACTIONS.help\"\n        }\n    ],\n    \n    \"secondaryItems\" : []\n};"
  },
  {
    "path": "flowable-ui-web/modeler/editor-app/configuration/url-config.js",
    "content": "/* 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 */\nvar FLOWABLE = FLOWABLE || {};\n\nFLOWABLE.URL = {\n\n    getModel: function(modelId) {\n        return FLOWABLE.CONFIG.contextRoot + '/app/rest/models/' + modelId + '/editor/json?version=' + Date.now();\n    },\n\n    getStencilSet: function() {\n        return FLOWABLE.CONFIG.contextRoot + '/app/rest/stencil-sets/editor?version=' + Date.now();\n    },\n    \n    getCmmnStencilSet: function() {\n        return FLOWABLE.CONFIG.contextRoot + '/app/rest/stencil-sets/cmmneditor?version=' + Date.now();\n    },\n\n    putModel: function(modelId) {\n        return FLOWABLE.CONFIG.contextRoot + '/app/rest/models/' + modelId + '/editor/json';\n    },\n    \n    validateModel: function(){\n\t\treturn FLOWABLE.CONFIG.contextRoot + '/app/rest/model/validate';\n    }\n};"
  },
  {
    "path": "flowable-ui-web/modeler/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@font-face {\n    font-family: 'FontAwesome';\n    src: url('../fonts/fontawesome-webfont.eot?v=4.3.0');\n    src: url('../fonts/fontawesome-webfont.eot?#iefix&v=4.3.0') format('embedded-opentype'), url('../fonts/fontawesome-webfont.woff2?v=4.3.0') format('woff2'), url('../fonts/fontawesome-webfont.woff?v=4.3.0') format('woff'), url('../fonts/fontawesome-webfont.ttf?v=4.3.0') format('truetype'), url('../fonts/fontawesome-webfont.svg?v=4.3.0#fontawesomeregular') format('svg');\n    font-weight: normal;\n    font-style: normal;\n}\n\n.row-no-gutter .col-xs-9,\n.row-no-gutter .col-xs-12 {\n    padding-left: 0px;\n    padding-right: 0px;\n    z-index: 50;\n}\n\n.row-no-gutter .col-xs-3 {\n    padding-left: 0px;\n    padding-right: 0px;\n    z-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    padding-left: 5px;\n}\n\n.editor-toolbar > .btn-group {\n    margin: 12px 15px 0px 0px;\n}\n\n.editor-toolbar > .btn-group.pull-right {\n    margin: 0;\n}\n\n.editor-toolbar .btn.btn-inverse {\n    font-size: 24px;\n    color: #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\n.editor-toolbar .btn.btn-inverse.pressed {\n    background-color: #287d92;\n    color: #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    background-color: #668b94;\n    border-color: #668b94;\n}\n\n.editor-toolbar .btn.btn-inverse.separator {\n    background: transparent;\n    padding: 4px 5px 0px 5px;\n    width: 1px;\n    min-width: 1px;\n}\n\n.editor-toolbar .toolbar-separator {\n    background: #a4acb9;\n    width: 1px;\n    height: 30px;\n}\n\n.stencils {\n    border-right: 1pt solid #c7cacd;\n    overflow: auto;\n    z-index: 5000;\n}\n\n.stencils ul {\n    padding-left: 0;\n}\n\n.stencils > div {\n    margin-top: 10px;\n}\n\n.stencil-group {\n    list-style: none;\n    list-style-position: outside;\n    margin: 0px 15px 0px 0px;\n}\n\n.stencil-group > li {\n    list-style: none;\n    list-style-position: outside;\n    margin: 0px 0px 5px 15px;\n    background-color: #ffffff;\n    font-family: Arial, Regular;\n    font-size: 14px;\n    color: #323437;\n}\n\n.stencil-group > li > span {\n    margin-left: 5px;\n    padding-top: 5px;\n    padding-bottom: 5px;\n    display: block;\n    cursor: pointer;\n}\n\n.stencil-group > li > span > i {\n    font-size: 12px;\n    line-height: 17px;\n}\n\n.stencil-group > li > ul {\n    list-style: none;\n    list-style-position: inside;\n    background-color: transparent;\n    margin: 0px;\n    overflow: hidden;\n    padding-left: 20px;\n}\n\n.stencil-group.collapsed > li {\n    color: #000000;\n}\n\n.stencil-group.collapsed > li > ul {\n    max-height: 0px;\n    padding-top: 0;\n    padding-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: 14px;\n}\n\n.ui-draggable.stencil-item.stencil-item-dragged {\n    display: block;\n    text-overflow: ellipsis;\n    white-space: nowrap;\n}\n\n/* Modeling Canvas\n-------------------------------- */\ndiv.canvas-wrapper {\n    overflow: auto;\n    background-color: #F8F8F8;\n}\n\n.canvas_resize_indicator i {\n    font-size: 15px;\n    color: #ffffff;\n    cursor: pointer;\n}\n\n.canvas_resize_indicator.N, .canvas_resize_indicator.S, .canvas_resize_indicator.E, .canvas_resize_indicator.W {\n    background: #5fbcd3;\n    height: 17px;\n    width: 17px;\n    text-align: center;\n    -webkit-border-radius: 3px;\n    -moz-border-radius: 3px;\n    border-radius: 3px;\n}\n\n#canvas-grow-N.canvas_resize_indicator, #canvas-shrink-S.canvas_resize_indicator {\n    margin: 0;\n    top: auto;\n}\n\n#canvas-grow-S.canvas_resize_indicator, #canvas-shrink-N.canvas_resize_indicator {\n    margin: 0;\n    bottom: auto;\n}\n\n#canvas-grow-E.canvas_resize_indicator, #canvas-shrink-W.canvas_resize_indicator {\n    margin: 0;\n    right: auto;\n}\n\n#canvas-grow-W.canvas_resize_indicator, #canvas-shrink-E.canvas_resize_indicator {\n    margin: 0;\n    left: auto;\n}\n\n.x-panel-body.x-panel-body-noheader.x-panel-body-noborder, .ORYX_Editor x-panel {\n    background-color: #F8F8F8;\n}\n\n.canvas-message {\n    position: absolute;\n    top: 60px;\n    right: 10px;\n    background: transparent;\n    font-size: 10pt;\n}\n\ndiv.propertySection {\n    height: 250px;\n    background-color: #e8edf1;\n    margin-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    display: block;\n    color: #1a1a1a;\n}\n\n.selected-item-title .glyphicon {\n    line-height: 25px;\n    font-size: 14px;\n}\n\n.selected-item-title a:hover, .selected-item-title a:focus {\n    color: #1a1a1a;\n    text-decoration: none;\n}\n\n.selected-item-section > div > .pull-right {\n    line-height: 50px;\n    margin: 0px 10px;\n    font-size: 14px;\n}\n\n.selected-item-body .property-row {\n    float: left;\n    width: 50%;\n    border: 0;\n    margin: 0;\n    padding: 0;\n    font-size: 13px;\n    overflow: hidden;\n}\n\n.selected-item-body .property-row:hover {\n    background-color: #d7dfe6;\n}\n\n.selected-item-body {\n    padding: 0;\n    overflow: auto;\n    height: 199px;\n}\n\n.selected-item-body > div {\n    overflow: hidden;\n    margin: 5px 20px;\n}\n\n.property-row > span {\n    display: block;\n    float: left;\n    margin: 2px 2%;\n    padding: 0;\n    min-height: 25px;\n}\n\n.property-row span.value {\n    cursor: pointer;\n    width: 46%;\n    padding: 0;\n    margin: 0;\n}\n\n.property-row span.value:hover {\n    cursor: pointer;\n}\n\n.property-row span.title {\n    font-size: 13px;\n    font-weight: bold;\n    width: 46%;\n}\n\n.property-row span.title-removed {\n    font-size: 13px;\n    font-weight: normal;\n    width: 46%;\n}\n\n.propertySection.collapsed {\n    max-height: 50px;\n    height: 50px;\n    overflow: hidden;\n}\n\n.propertySection.collapsed .selected-item-title {\n    border: none;\n}\n\n.property-row input[type=\"text\"] {\n    height: 25px;\n    margin: 2px 0;\n    padding: 0px 5px;\n    width: 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.step-editor-inline-grid {\n    border: 1px solid rgb(212, 212, 212);\n    width: 550px;\n    height: 150px;\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.form-property-checkbox {\n    margin: 0;\n}\n\n/* Oryx overrides\n-------------------------------- */\nul.x-menu-list {\n    list-style: none;\n    list-style-position: inside;\n    width: 200px;\n    background-color: #FFFFFF;\n    border: 1px solid #E1E2E5;\n    -webkit-border-radius: 3px;\n    -moz-border-radius: 3px;\n    border-radius: 3px;\n    padding: 3px;\n}\n\nimg.x-menu-item-icon {\n    width: auto;\n    height: auto;\n    margin-right: 5px;\n}\n\nli.x-menu-list-item {\n    margin: 3px 0px;\n}\n\nli.x-menu-list-item.x-menu-item-active {\n    background-color: #EFEFEF;\n}\n\nli.x-menu-list-item a {\n    color: #000000;\n}\n\nli.x-menu-list-item.x-menu-item-active a {\n    text-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    position: relative;\n    top: 1px;\n    display: inline-block;\n    font-family: 'ActivitiModeler';\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.editor-icon-save:before {\n    content: 'a';\n}\n\n.editor-icon-edit:before {\n    content: 'b';\n}\n\n.editor-icon-cut:before {\n    content: 'c';\n}\n\n.editor-icon-copy:before {\n    content: 'd';\n}\n\n.editor-icon-paste:before {\n    content: 'e';\n}\n\n.editor-icon-delete:before {\n    content: 'f';\n}\n\n.editor-icon-redo:before {\n    content: 'h';\n}\n\n.editor-icon-undo:before {\n    content: 'g';\n}\n\n.editor-icon-same-size:before {\n    content: 'i';\n}\n\n.editor-icon-zoom-in:before {\n    content: 'k';\n}\n\n.editor-icon-zoom-out:before {\n    content: 'l';\n}\n\n.editor-icon-zoom-actual:before {\n    content: 'm';\n}\n\n.editor-icon-zoom-fit:before {\n    content: 'j';\n}\n\n.editor-icon-bendpoint-add:before {\n    content: 'n';\n}\n\n.editor-icon-bendpoint-remove:before {\n    content: 'o';\n}\n\n.editor-icon-align-horizontal:before {\n    content: 'p';\n}\n\n.editor-icon-align-vertical:before {\n    content: 'q';\n}\n\n.formbuilder-validation-error-icon {\n    position: relative;\n    top: -2px;\n    margin-right: 5px;\n}\n\n.modal-dialog.modal-maxheight {\n    max-height: 724px;\n    overflow-y: auto;\n}\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    transform: translate(0, 0);\n}\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\n.fa-2x {\n    font-size: 2em;\n}\n\n.fa-3x {\n    font-size: 3em;\n}\n\n.fa-4x {\n    font-size: 4em;\n}\n\n.fa-5x {\n    font-size: 5em;\n}\n\n.fa-rocket:before {\n    content: \"\\f135\";\n}\n\n.fa-share:before {\n    content: \"\\f064\";\n}\n\n.step-types .fa {\n    margin-right: 6px;\n}\n\n.decision-table-grid {\n    border: 1px solid rgb(212, 212, 212);\n    width: 100%;\n    height: 372px;\n    margin-bottom: 10px;\n}\n\n.decision-table .btn-success {\n    color: #fff;\n    background-color: #5cb85c;\n}\n\n.decision-table .btn-success:hover,\n.decision-table .btn-success:focus {\n    background-color: #419641;\n    background-position: 0 -15px;\n}\n\n.decision-table-grid .ui-grid-header-viewport, .decision-table-grid .ui-grid-header-canvas {\n    height: 70px;\n}\n\n.decision-table-grid .header-expression {\n    height: 70px;\n    border-bottom: 5px solid rgb(43, 37, 37);\n    border-bottom: 5px solid rgba(43, 37, 37, 0.22);\n}\n\n.decision-table-grid .header-input-expression {\n    /* Fallback for web browsers that doesn't support RGBa */\n    background: rgb(54, 167, 196);\n    /* RGBa with 0.6 opacity */\n    background: rgba(54, 167, 196, 0.6);\n    /*background-color: #668b94;*/\n    color: #ffffff;\n    font-size: 14px;\n}\n\n.decision-table-grid .header-output-expression {\n    border-left: 5px solid rgb(212, 212, 212);\n    /* Fallback for web browsers that doesn't support RGBa */\n    background: rgb(92, 184, 92);\n    /* RGBa with 0.6 opacity */\n    background: rgba(92, 184, 92, 0.6);\n    color: #ffffff;\n    font-size: 14px;\n}\n\n.decision-table-grid .header-output-expression ~ .header-output-expression {\n    border-left: none;\n}\n\n.decision-table-grid .cell-input-expression {\n    /* Fallback for web browsers that doesn't support RGBa */\n    background: rgb(54, 167, 196);\n    /* RGBa with 0.6 opacity */\n    background: rgba(54, 167, 196, 0.1);\n}\n\n.decision-table-grid .cell-output-expression {\n    border-left: 5px solid rgb(212, 212, 212);\n    /* Fallback for web browsers that doesn't support RGBa */\n    background: rgb(92, 184, 92);\n    /* RGBa with 0.6 opacity */\n    background: rgba(92, 184, 92, 0.1);\n    border-left: 3px solid rgb(212, 212, 212);\n}\n\n.decision-table-grid .cell-output-expression ~ .cell-output-expression {\n    border-left: none;\n}\n\n.decision-table-grid {\n    font-size: 13px;\n    line-height: 20px\n}\n\n.decision-table-grid .ui-grid-header-cell-wrapper .ui-grid-selection-row-header-buttons {\n    display: none;\n}\n\n.decision-table-output-expression-input, .decision-table-output-expression-input:active, .decision-table-output-expression-input:focus, .decision-table-output-expression-input:visited {\n    background-color: inherit;\n}\n\n.decision-table-output-expression-input:hover {\n    background-color: #287d92;\n}\n\n.decision-table-input-expression-input .caret {\n    display: none;\n}\n\n.decision-table-grid .ui-grid-row.ui-grid-row-selected .cell-input-expression > [ui-grid-row] > .ui-grid-cell {\n    background: rgba(92, 184, 92, 0.4);\n}\n\n.decision-table-grid .ui-grid-row:nth-child(odd) .ui-grid-cell.cell-output-expression,\n.decision-table-grid .ui-grid-row:nth-child(even) .ui-grid-cell.cell-output-expression {\n    background: rgb(92, 184, 92);\n    /* RGBa with 0.6 opacity */\n    background: rgba(92, 184, 92, 0.1);\n    border-bottom: 1px solid rgba(43, 37, 37, 0.22);\n}\n\n.decision-table-grid .ui-grid-row.ui-grid-row-selected:nth-child(odd) .ui-grid-cell.cell-output-expression,\n.decision-table-grid .ui-grid-row.ui-grid-row-selected:nth-child(even) .ui-grid-cell.cell-output-expression {\n    background: rgba(92, 184, 92, 0.2);\n}\n\n.decision-table-grid .ui-grid-row:nth-child(odd) .ui-grid-cell.cell-input-expression,\n.decision-table-grid .ui-grid-row:nth-child(even) .ui-grid-cell.cell-input-expression {\n    background: rgb(54, 167, 196);\n    /* RGBa with 0.6 opacity */\n    background: rgba(54, 167, 196, 0.1);\n    border-bottom: 1px solid rgba(43, 37, 37, 0.22);\n}\n\n.decision-table-grid .ui-grid-row.ui-grid-row-selected:nth-child(odd) .ui-grid-cell.cell-input-expression,\n.decision-table-grid .ui-grid-row.ui-grid-row-selected:nth-child(even) .ui-grid-cell.cell-input-expression {\n    background: rgba(54, 167, 196, 0.2);\n}\n\n.decision-table-grid .ui-grid-render-container-left .ui-grid-header-cell {\n    /* Fallback for web browsers that doesn't support RGBa */\n    background: rgb(54, 167, 196);\n    /* RGBa with 0.6 opacity */\n    background: rgba(54, 167, 196, 0.6);\n    /*background-color: #668b94;*/\n    color: #ffffff;\n    font-size: 14px;\n\n    border-bottom: 5px solid rgb(43, 37, 37);\n    border-bottom: 5px solid rgba(43, 37, 37, 0.22);\n\n}\n\n.decision-table-grid .ui-grid-pinned-container.ui-grid-pinned-container-left .ui-grid-header-cell:last-child {\n    border-top-width: 0px;\n    border-right-width: 0px;\n    border-left-width: 0px;\n    border-bottom: 5px solid rgb(43, 37, 37);\n    border-bottom: 5px solid rgba(43, 37, 37, 0.22);\n}\n\n.decision-table-grid .ui-grid-cell-focus {\n    outline: 0;\n    background-color: transparent;\n}\n\n.decision-table .ui-grid-row-selected .customRowHeader {\n    background-color: #c9dde1;\n    color: #ffffff;\n    border-bottom: 1px solid rgba(43, 37, 37, 0.22);\n}\n\n.decision-table .ui-grid-cell-contents {\n    position: relative;\n}\n\n.decision-table .ui-grid-cell-contents-empty::before {\n    content: \"-\";\n    text-align: center;\n    width: 100%;\n    position: absolute;\n    height: 100%;\n    color: gray;\n}\n\n.decision-table .ui-grid-cell-contents .show-error-icon {\n    display: none;\n}\n\n.decision-table .ui-grid-cell-contents .edit-icon {\n    position: absolute;\n    right: 0;\n}\n\n.decision-table .ui-grid-cell-contents.ui-grid-cell-contents-has-error {\n    padding-left: 20px;\n}\n\n.decision-table .decision-table-grid-wrapper {\n    position: relative;\n    margin-top: 20px;\n    width: 100%;\n}\n\n.decision-table .decision-table-grid-wrapper > span {\n    display: none;\n}\n\n.decision-table .dropdown {\n    display: inherit !important;\n}\n\n.decision-table .dropdown-menu > li.danger > a:hover {\n    background: #d35f5f;\n}\n\n.decision-table .decision-table-grid-wrapper .ui-grid-header-cell .ui-grid-cell-contents .text-center {\n    min-height: 20px;\n}\n\n.decision-table .decision-table-grid-wrapper.ui-grid-cell-contents-has-error > .decision-table-grid {\n    border: 1px solid #a94442;\n}\n\n.decision-table .ui-grid-cell-contents.ui-grid-cell-contents-has-error .contents-value,\n.decision-table .ui-grid-cell-contents.ui-grid-cell-contents-has-error .text-center {\n    color: #a94442;\n}\n\n.decision-table .ui-grid-cell-contents.ui-grid-cell-contents-has-error .show-error-icon,\n.decision-table .decision-table-grid-wrapper.ui-grid-cell-contents-has-error > .show-error-icon {\n    display: block;\n    position: absolute;\n    top: 0;\n    left: 0;\n    padding: 3px;\n    cursor: pointer;\n    z-index: 1;\n}\n\n.decision-table .row {\n    margin-left: -10px;\n    margin-right: -10px;\n}\n\nhot-table {\n    overflow: hidden;\n}\n\nhot-table .column-header {\n\n}\n\nhot-table .column-header.label {\n    font-size: 14px;\n}\n\n#decisionTableGrid .grid-controls {\n    margin-top: 40px;\n}\n\n.decision-name-container {\n    width: 340px;\n    height: 50px;\n    border-left: 1px solid rgba(51, 51, 51, 0.3);\n    border-top: 1px solid rgba(51, 51, 51, 0.3);\n    border-right: 1px solid rgba(51, 51, 51, 0.3);\n}\n\n.decision-name-container .decision-name {\n    padding: 12px;\n    font-size: 15px;\n    font-weight: bold;\n}\n\n#decisionTableGrid th .input-header {\n    font-size: 16px;\n    display: inline-block;\n    margin: 0 auto 0 -20%;\n\n    max-width: 60%;\n    min-height: 90px;\n    white-space: nowrap;\n    overflow: hidden;\n    text-overflow: ellipsis;\n}\n\n#decisionTableGrid  th .output-header {\n    font-size: 16px;\n    display: inline-block;\n    margin: 0 auto;\n\n    max-width: 150px;\n    min-height: 90px;\n    white-space: nowrap;\n    overflow: hidden;\n    text-overflow: ellipsis;\n}\n\n#decisionTableGrid th .input-header .header-label, #decisionTableGrid th .output-header .header-label {\n    font-size: 15px;\n    font-weight: 600;\n}\n\n#decisionTableGrid th .input-header a, #decisionTableGrid th .output-header a {\n    text-decoration: underline;\n}\n\n#decisionTableGrid th .input-header .header-variable, #decisionTableGrid th .output-header .header-variable {\n    font-size: 14px;\n    text-align: center;\n}\n\n#decisionTableGrid th .input-header .header-variable-type, #decisionTableGrid th .output-header .header-variable-type {\n    font-size: 13px;\n    font-style: italic;\n    text-align: center;\n}\n\n#decisionTableGrid th .input-header .header-entries, #decisionTableGrid th .output-header .header-entries {\n    font-size: 12px;\n    font-weight: lighter;\n    font-style: normal;\n    text-align: center;\n}\n\n#decisionTableGrid th .header-add-new-expression {\n    float: right;\n    position: relative;\n    padding-right: 15px;\n    top: 10px;\n    font-size: 15px;\n}\n\n#decisionTableGrid th .header-remove-expression {\n    float: left;\n    position: relative;\n    top: 10px;\n    font-size: 15px;\n    padding-left: 15px;\n}\n\n#decisionTableGrid tr .input-operator-cell {\n    text-align: center;\n    min-width: 70px; !important;\n}\n\n#decisionTableGrid td.htInvalid {\n    background-color: rgba(255, 76, 66, 0.33) !important;\n}\n\n#decisionTableGrid .selectedRow {\n    background: rgb(0, 140, 186);\n    color: rgb(250, 250, 250)\n}\n\n#decision-table-editor, #read-only-decision-table-editor {\n    background-color: rgba(243, 243, 243, 0.5);\n}\n\n#decisionTableGrid .input-operator-container {\n    width: 45px;\n    float: left;\n    border: 1px solid rgb(212, 212, 212);\n    padding: 1px;\n    margin-right: 5px;\n    text-align: center;\n}\n\n#decisionTableGrid .input-expression-container {\n    overflow: hidden;\n    border: 1px solid rgb(212, 212, 212);\n    padding: 1px;\n}\n\n#decisionTableGrid .input-expression-container {\n    overflow: hidden;\n    border: 1px solid rgb(212, 212, 212);\n    padding: 1px;\n    clear: right;\n}\n\n#decisionTableGrid .input-expression-input {\n    overflow: hidden;\n    border: none;\n    width: 100%;\n}\n\n#decisionTableGrid .input-container {\n    width: 100%;\n    margin: 0 auto;\n    overflow: hidden;\n    padding: 4px 0 4px 0;\n}\n\n#decisionTableGrid .input-operator-select {\n    width: 45px;\n    border: none;\n    box-shadow: none;\n    background: transparent none;\n    -webkit-appearance: none;\n}\n\n#decisionTableGrid .input-operator-select :focus {\n    outline: none;\n}\n\n#decisionTableGrid .input-expression-input :focus {\n    outline: none;\n}\n\n#decisionTableGrid .input-operator-select.editor :focus {\n    outline: none;\n}\n\n#decisionTableGrid th.input-expression-header, #decisionTableGrid th.input-operator-header {\n    background-color: rgba(54, 167, 196, 0.1);\n    border-bottom: 4px double rgba(51, 51, 51, 0.7);\n}\n\n#decisionTableGrid th.input-expression-header {\n    /*border-left: 1px solid rgba(54, 167, 196, 0.1);*/\n    border-left-style: hidden;\n}\n\n#decisionTableGrid th.input-expression-header.last, #decision-table-editor td.last, #decisionTableGrid td.last {\n    border-right: 4px double rgba(51, 51, 51, 0.7);\n}\n\n#decisionTableGrid th.output-header.first, #decision-table-editor td.first, #decisionTableGrid td.first {\n    border-left: 4px double rgba(51, 51, 51, 0.7);\n}\n\n#decisionTableGrid th.output-header {\n    background-color: rgba(243, 243, 243, 1);\n    border-bottom: 4px double rgba(51, 51, 51, 0.7);\n}\n\n#decisionTableGrid th.input-operator-header {\n    border-right-style: hidden;\n}\n\n#decisionTableGrid .hit-policy-container {\n    position:fixed;\n    width: 50px;\n    background-color: #f9f9f9;\n    z-index: 1035;\n}\n\n#decisionTableGrid .hit-policy-header {\n    margin-top: 5px;\n    font-size: 15px;\n    font-weight: 600;\n    cursor: pointer;\n    text-decoration: underline;\n    color: #428bca;\n}\n\n.decision-table-grid-wrapper .handsontable-container {\n    border-left: 1px solid rgba(51, 51, 51, 0.3);\n    border-bottom: 1px solid rgba(51, 51, 51, 0.3);\n    border-right: 1px solid rgba(51, 51, 51, 0.3);\n}\n\n#decisionTableGrid .handsontable th:first-child {\n    border-left: none;\n}\n\n#decisionTableGrid .handsontable.htRemoveRow th.htRemoveRow {\n    text-align: center;\n}\n\n#decisionTableGrid .handsontable.htRemoveRow th.htRemoveRow .btn {\n    background-color: #898989;\n    border-radius: 20px;\n    padding: 2px 0 0;\n    display: none;\n    color: #FFF;\n    cursor: pointer;\n    font-size: 14px;\n    font-weight: 300;\n    line-height: 1;\n    margin: 0 auto;\n    width: 20px;\n    height: 18px;\n}\n\n#decisionTableGrid .custom-expression-operator * {\n    visibility: hidden;\n}\n\n#decisionTableGrid .custom-expression-operator {\n    color: transparent;\n}\n\n#decision-table-allowed-values {\n    font-size: 14px;\n}\n\n#decision-table-allowed-values tr td:last-of-type {\n    border: none;\n    padding-left: 5px;\n}\n\n#decision-table-allowed-values .wtBorder {\n    display: none !important;\n}\n\n#decision-table-allowed-values td.highlight {\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\n#decision-table-allowed-values td.remove_container.highlight {\n    border: none;\n    -webkit-box-shadow: none;\n    box-shadow: none;\n}\n\n.handsontable.htRemoveRow th.htRemoveRow .btn:hover {\n    background-color: #777;\n}\n\n.ui-grid .ui-grid-render-container-body .ui-grid-viewport {\n    overflow-x: auto !important;\n}\n\n.validationGrid {\n    border: 1px solid rgb(212, 212, 212);\n    height: 300px;\n}\n\n.ng-hide-add-active, .ng-hide-remove {\n    display: inherit !important;\n}\n\n.ng-hide:not(.ng-animate) {\n    display: none !important;\n}\n\n.flowable-status {\n    border: 1px solid #3c3c3c;\n    margin: 2px;\n    height: 28px;\n    line-height: 20px;\n}\n\n.flowable-warning {\n    text-align: center;\n    background: yellow;\n    height: 100%;\n}\n\n.flowable-critical {\n    text-align: center;\n    background: #990000;\n    color: white;\n    height: 100%;\n}\n\n.actions {\n    padding-top: 1px;\n    padding-left: 2px;\n}\n\n/** collapse stencils **/\n#paletteSectionFooter {\n    height: 50px;\n    text-align: center;\n    background-color: #e8edf1;\n    border-top: 1px solid #a4acb9;\n    border-right: 1px solid #a4acb9;\n    cursor: pointer;\n    bottom: 0;\n}\n\n#paletteSectionFooter i {\n    line-height: 50px !important;\n}\n\n#paletteSectionOpen {\n    width: 30px;\n    height: 50px;\n    background-color: #e8edf1;\n    text-align: center;\n    bottom: 1px;\n    position: fixed;\n    z-index: 101;\n    border-top: 1px solid #a4acb9;\n    border-right: 1px solid #a4acb9;\n    cursor: pointer;\n    left: 0;\n}\n\n#paletteSectionOpen i {\n    line-height: 50px !important;\n}\n\n.hidden {\n    display: none\n}\n\n#paletteHelpWrapper {\n    float: left;\n    width: 300px;\n    transition: 0.3s width;\n}\n\n.close {\n    width: 0px !important;\n}\n\n#contentCanvasWrapper {\n    padding-left: 300px;\n    transition: 0.3s padding-left;\n}\n\n.collapsedCanvasWrapper {\n    padding-left: 0px !important;\n}\n\n/**Process navigator */\n#process-treeview-wrapper {\n    height: 200px;\n    background: #f3f3f3;\n    border-right: 1px solid #bbbbbb;\n    overflow-y: auto;\n}\n\n.process-treeview-header {\n    background: #2980b9;\n    color: white;\n    border: 1px solid #bbbbbb;\n    padding: 2px;\n    padding-left: 5px;\n    font-size: 14px;\n    font-weight: bold;\n}\n\n.process-treeview-process-title {\n    padding: 5px;\n    font-weight: bold;\n}\n\n.process-treeview {\n    margin-top: 5px;\n}\n\n.process-treeview-list {\n    padding: 0 10px;\n    list-style-type: none;\n}\n\n.process-treeview-list-item:hover {\n    cursor: pointer;\n    font-weight: bolder;\n    font-style: italic;\n}\n\n.process-treeview-body {\n\n}\n\n.current-process {\n    border: 1px solid green;\n}\n"
  },
  {
    "path": "flowable-ui-web/modeler/editor-app/define-data-controller.js",
    "content": "/* Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n * \n *      http://www.apache.org/licenses/LICENSE-2.0\n * \n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/*\n * Controller for morph shape selection\n */\n\nvar FlowableDefineDataCtrl = [ '$rootScope', '$scope', 'dialog', '$timeout', '$translate', function($rootScope, $scope, dialog, $timeout, $translate) {\n\n    $scope.definedDataItems = [];\n    $scope.selectedDataItems = [];\n    \n    // Config for grid\n    $scope.gridOptions = {\n        data: 'definedDataItems',\n        enableRowSelection: true,\n        headerRowHeight: 28,\n        multiSelect: false,\n        keepLastSelected : false,\n        selectedItems: $scope.selectedDataItems,\n        enableHorizontalScrollbar: 0,\n        enableColumnMenus: false,\n        enableSorting: false,\n        columnDefs: [{ field: 'name', displayName: 'Name'},\n            { field: 'value', displayName: 'Value'}]\n    };\n    \n    // Click handler for add button\n    $scope.addNewDataItem = function() {\n    \t$scope.definedDataItems.push({ name : '',\n            value : ''});\n    };\n\n    // Click handler for remove button\n    $scope.removeDataItem = function() {\n        if ($scope.selectedDataItems.length > 0) {\n            var index = $scope.definedDataItems.indexOf($scope.selectedDataItems[0]);\n            $scope.gridOptions.selectItem(index, false);\n            $scope.definedDataItems.splice(index, 1);\n\n            $scope.selectedDataItems.length = 0;\n            if (index < $scope.definedDataItems.length) {\n                $scope.gridOptions.selectItem(index + 1, true);\n            } else if ($scope.definedDataItems.length > 0) {\n                $scope.gridOptions.selectItem(index - 1, true);\n            }\n        }\n    };\n\n    // Click handler for up button\n    $scope.moveDataItemUp = function() {\n        if ($scope.selectedParameters.length > 0) {\n            var index = $scope.definedDataItems.indexOf($scope.selectedDataItems[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.definedDataItems[index];\n                $scope.definedDataItems.splice(index, 1);\n                $timeout(function(){\n                \t$scope.definedDataItems.splice(index + -1, 0, temp);\n                }, 100);\n\n            }\n        }\n    };\n\n    // Click handler for down button\n    $scope.moveDataItemDown = function() {\n        if ($scope.selectedParameters.length > 0) {\n            var index = $scope.definedDataItems.indexOf($scope.selectedDataItems[0]);\n            if (index != $scope.definedDataItems.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.definedDataItems[index];\n                $scope.definedDataItems.splice(index, 1);\n                $timeout(function(){\n                \t$scope.definedDataItems.splice(index + 1, 0, temp);\n                }, 100);\n\n            }\n        }\n    };\n    \n    $scope.save = function() {\n      dialog.close();\n    };\n\n    $scope.cancel = function() {\n      dialog.close();\n    };\n\n    // Close button handler\n    $scope.close = function() {\n        dialog.close();\n    };\n\n}];"
  },
  {
    "path": "flowable-ui-web/modeler/editor-app/editor/css/editor.css",
    "content": "/** Copyright 2005-2015 Alfresco Software, Ltd.\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 */\nbody, 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\t\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\t\n}\n\n.canvas_resize_indicator {\n\t\n\twidth\t\t: 15px;\n\theight\t\t: 15px;\t\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\t\n\topacity\t\t: 1.0;\n}\n/** End Resizer **/\n\n.Oryx_down {\n\t\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": "flowable-ui-web/modeler/editor-app/editor/i18n/translation_de.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 \n/**\n * @author nicolas.peters\n * \n * Contains all strings for German language.\n * Version 1 - 08/29/08\n */\nif(!ORYX) var ORYX = {};\n\nif(!ORYX.I18N) ORYX.I18N = {};\n\nORYX.I18N.Language = \"de_DE\"; //Pattern <ISO language code>_<ISO country code> in lower case!\n\nif(!ORYX.I18N.Oryx) ORYX.I18N.Oryx = {};\n\nORYX.I18N.Oryx.pleaseWait = \"Editor wird geladen. Bitte warten...\";\nORYX.I18N.Oryx.notLoggedOn = \"Nicht angemeldet\";\nORYX.I18N.Oryx.noBackendDefined\t= \"Achtung! \\n Es wurde kein Repository definiert.\\n Ihr Model kann nicht geladen werden. Bitte nutzen sie eine Editor Konfiguration mit einem Speicher Plugin.\";\n\nif(!ORYX.I18N.AddDocker) ORYX.I18N.AddDocker = {};\n\nORYX.I18N.AddDocker.group = \"Docker\";\nORYX.I18N.AddDocker.add = \"Docker Hinzufügen\";\nORYX.I18N.AddDocker.addDesc = \"Fügen Sie einer Kante einen Docker hinzu, indem Sie auf die Kante klicken\";\nORYX.I18N.AddDocker.del = \"Docker Löschen\";\nORYX.I18N.AddDocker.delDesc = \"Löscht einen Docker durch Klicken auf den zu löschenden Docker\";\n\nif(!ORYX.I18N.Arrangement) ORYX.I18N.Arrangement = {};\n\nORYX.I18N.Arrangement.groupZ = \"Z-Order\";\nORYX.I18N.Arrangement.btf = \"In den Vordergrund\";\nORYX.I18N.Arrangement.btfDesc = \"In den Vordergrund\";\nORYX.I18N.Arrangement.btb = \"In den Hintergrund\";\nORYX.I18N.Arrangement.btbDesc = \"In den Hintergrund\";\nORYX.I18N.Arrangement.bf = \"Eine Ebene nach Vorne\";\nORYX.I18N.Arrangement.bfDesc = \"Eine Ebene nach Vorne\";\nORYX.I18N.Arrangement.bb = \"Eine Ebene nach Hinten\";\nORYX.I18N.Arrangement.bbDesc = \"Eine Ebene nach Hinten\";\nORYX.I18N.Arrangement.groupA = \"Alignment\";\nORYX.I18N.Arrangement.ab = \"Unten ausrichten\";\nORYX.I18N.Arrangement.abDesc = \"Unten ausrichten\";\nORYX.I18N.Arrangement.am = \"Horizontal ausrichten\";\nORYX.I18N.Arrangement.amDesc = \"Horizontal ausrichten\";\nORYX.I18N.Arrangement.at = \"Oben ausrichten\";\nORYX.I18N.Arrangement.atDesc = \"Oben ausrichten\";\nORYX.I18N.Arrangement.al = \"Links ausrichten\";\nORYX.I18N.Arrangement.alDesc = \"Links ausrichten\";\nORYX.I18N.Arrangement.ac = \"Vertikal ausrichten\";\nORYX.I18N.Arrangement.acDesc = \"Vertikal ausrichten\";\nORYX.I18N.Arrangement.ar = \"Rechts ausrichten\";\nORYX.I18N.Arrangement.arDesc = \"Rechts ausrichten\";\nORYX.I18N.Arrangement.as = \"Größenangleichung\";\nORYX.I18N.Arrangement.asDesc = \"Größenangleichung\";\n\nif(!ORYX.I18N.Edit) ORYX.I18N.Edit = {};\n\nORYX.I18N.Edit.group = \"Edit\";\nORYX.I18N.Edit.cut = \"Ausschneiden\";\nORYX.I18N.Edit.cutDesc = \"Ausschneiden der selektierten Elemente\";\nORYX.I18N.Edit.copy = \"Kopieren\";\nORYX.I18N.Edit.copyDesc = \"Kopieren der selektierten Elemente\";\nORYX.I18N.Edit.paste = \"Einfügen\";\nORYX.I18N.Edit.pasteDesc = \"Einfügen von kopierten/ausgeschnittenen Elementen\";\nORYX.I18N.Edit.del = \"Löschen\";\nORYX.I18N.Edit.delDesc = \"Löschen der selektierten Elemente\";\n\nif(!ORYX.I18N.EPCSupport) ORYX.I18N.EPCSupport = {};\n\nORYX.I18N.EPCSupport.group = \"EPC\";\nORYX.I18N.EPCSupport.exp = \"EPML Export\";\nORYX.I18N.EPCSupport.expDesc = \"Exportieren nach EPML\";\nORYX.I18N.EPCSupport.imp = \"EPML Import\";\nORYX.I18N.EPCSupport.impDesc = \"Importieren einer EPML Datei\";\nORYX.I18N.EPCSupport.progressExp = \"Exportiere Modell\";\nORYX.I18N.EPCSupport.selectFile = \"Wählen Sie eine EPML Datei aus, die Sie importieren möchten.\";\nORYX.I18N.EPCSupport.file = \"Datei\";\nORYX.I18N.EPCSupport.impPanel = \"EPML Datei importieren\";\nORYX.I18N.EPCSupport.impBtn = \"Importieren\";\nORYX.I18N.EPCSupport.close = \"Schließen\";\nORYX.I18N.EPCSupport.error = \"Fehler\";\nORYX.I18N.EPCSupport.progressImp = \"Importiere...\";\n\nif(!ORYX.I18N.ERDFSupport) ORYX.I18N.ERDFSupport = {};\n\nORYX.I18N.ERDFSupport.exp = \"ERDF Export\";\nORYX.I18N.ERDFSupport.expDesc = \"Exportieren nach ERDF\";\nORYX.I18N.ERDFSupport.imp = \"ERDF Import\";\nORYX.I18N.ERDFSupport.impDesc = \"ERDF Datei importieren\";\nORYX.I18N.ERDFSupport.impFailed = \"Anfrage für den Import der ERDF Datei ist fehlgeschlagen.\";\nORYX.I18N.ERDFSupport.impFailed2 = \"Während des Importierens ist ein Fehler aufgetreten. <br/>Fehlermeldung: <br/><br/>\";\nORYX.I18N.ERDFSupport.error = \"Fehler\";\nORYX.I18N.ERDFSupport.noCanvas = \"Das XML Dokument enthält keinen Oryx Canvas Knoten.\";\nORYX.I18N.ERDFSupport.noSS = \"Im XML Dokument ist kein Stencil Set referenziert.\";\nORYX.I18N.ERDFSupport.wrongSS = \"Das im XML Dokument referenzierte Stencil Set passt nicht zu dem im Editor geladenen Stencil Set.\";\nORYX.I18N.ERDFSupport.selectFile = \"Wählen sie eine ERDF Datei (.xml) aus oder geben Sie den ERDF Code im Textfeld ein.\";\nORYX.I18N.ERDFSupport.file = \"Datei\";\nORYX.I18N.ERDFSupport.impERDF = \"ERDF importieren\";\nORYX.I18N.ERDFSupport.impBtn = \"Importieren\";\nORYX.I18N.ERDFSupport.impProgress = \"Importiere...\";\nORYX.I18N.ERDFSupport.close = \"Schließen\";\nORYX.I18N.ERDFSupport.deprTitle = \"Wirklich nach eRDF exportieren?\";\nORYX.I18N.ERDFSupport.deprText = \"Der Export nach eRDF wird nicht empfohlen, da dieses Format in zukünftigen Versionen des Oryx Editors nicht mehr unterstützt wird. Verwenden Sie statt dessen den Export nach JSON, falls möglich. Wollen Sie dennoch das Model nach eRDF exportieren?\";\n\nif(!ORYX.I18N.jPDLSupport) ORYX.I18N.jPDLSupport = {};\n\nORYX.I18N.jPDLSupport.group = \"ExecBPMN\";\nORYX.I18N.jPDLSupport.exp = \"jPDL Export\";\nORYX.I18N.jPDLSupport.expDesc = \"Exportieren nach jPDL\";\nORYX.I18N.jPDLSupport.imp = \"jPDL Import\";\nORYX.I18N.jPDLSupport.impDesc = \"jPDL Datei importieren\";\nORYX.I18N.jPDLSupport.impFailedReq = \"Anfrage für den Import der jPDL Datei ist fehlgeschlagen.\";\nORYX.I18N.jPDLSupport.impFailedJson = \"Transformation der jPDL Datei ist fehlgeschlagen.\";\nORYX.I18N.jPDLSupport.impFailedJsonAbort = \"Import abgebrochen.\";\nORYX.I18N.jPDLSupport.loadSseQuestionTitle = \"Stencil Set Erweiterung für jBPM muss geladen werden\"; \nORYX.I18N.jPDLSupport.loadSseQuestionBody = \"Um jPDL importieren zu können, muss die Stencil Set Erweiterung für jBPM geladen werden. Möchten Sie fortfahren?\";\nORYX.I18N.jPDLSupport.expFailedReq = \"Anfrage für den Export des Models ist fehlgeschlagen.\";\nORYX.I18N.jPDLSupport.expFailedXml = \"Export nach jPDL ist fehlgeschlagen. Exporter meldet: \";\nORYX.I18N.jPDLSupport.error = \"Fehler\";\nORYX.I18N.jPDLSupport.selectFile = \"Wählen sie eine jPDL Datei (.xml) aus oder geben Sie den jPDL Code im Textfeld ein.\";\nORYX.I18N.jPDLSupport.file = \"Datei\";\nORYX.I18N.jPDLSupport.impJPDL = \"jPDL importieren\";\nORYX.I18N.jPDLSupport.impBtn = \"Importieren\";\nORYX.I18N.jPDLSupport.impProgress = \"Importiere...\";\nORYX.I18N.jPDLSupport.close = \"Schließen\";\n\nif(!ORYX.I18N.Save) ORYX.I18N.Save = {};\n\nORYX.I18N.Save.group = \"File\";\nORYX.I18N.Save.save = \"Speichern\";\nORYX.I18N.Save.saveDesc = \"Speichern\";\nORYX.I18N.Save.saveAs = \"Speichern als...\";\nORYX.I18N.Save.saveAsDesc = \"Speichern als...\";\nORYX.I18N.Save.unsavedData = \"Das Diagramm enthält nicht gespeicherte Daten. Sind Sie sicher, daß Sie den Editor schließen möchten?\";\nORYX.I18N.Save.newProcess = \"Neuer Prozess\";\nORYX.I18N.Save.saveAsTitle = \"Speichern als...\";\nORYX.I18N.Save.saveBtn = \"Speichern\";\nORYX.I18N.Save.close = \"Schließen\";\nORYX.I18N.Save.savedAs = \"Gespeichert als\";\nORYX.I18N.Save.saved = \"Gespeichert\";\nORYX.I18N.Save.failed = \"Das Speichern ist fehlgeschlagen.\";\nORYX.I18N.Save.noRights = \"Sie haben nicht die erforderlichen Rechte, um Änderungen zu speichern.\";\nORYX.I18N.Save.saving = \"Speichern\";\nORYX.I18N.Save.saveAsHint = \"Das Diagramm wurde unter folgendem Link gespeichert:\";\n\nif(!ORYX.I18N.File) ORYX.I18N.File = {};\n\nORYX.I18N.File.group = \"File\";\nORYX.I18N.File.print = \"Drucken\";\nORYX.I18N.File.printDesc = \"Drucken\";\nORYX.I18N.File.pdf = \"PDF Export\";\nORYX.I18N.File.pdfDesc = \"Exportieren nach PDF\";\nORYX.I18N.File.info = \"Über\";\nORYX.I18N.File.infoDesc = \"Über\";\nORYX.I18N.File.genPDF = \"PDF wird generiert\";\nORYX.I18N.File.genPDFFailed = \"Die Generierung der PDF Datei ist fehlgeschlagen.\";\nORYX.I18N.File.printTitle = \"Drucken\";\nORYX.I18N.File.printMsg = \"Leider arbeitet die Druckfunktion zur Zeit nicht immer korrekt. Bitte nutzen Sie den PDF Export, und drucken Sie das PDF Dokument aus. Möchten Sie dennoch mit dem Drucken fortfahren?\";\n\nif(!ORYX.I18N.Grouping) ORYX.I18N.Grouping = {};\n\nORYX.I18N.Grouping.grouping = \"Grouping\";\nORYX.I18N.Grouping.group = \"Gruppieren\";\nORYX.I18N.Grouping.groupDesc = \"Gruppierung der selektierten Elemente\";\nORYX.I18N.Grouping.ungroup = \"Gruppierung aufheben\";\nORYX.I18N.Grouping.ungroupDesc = \"Aufheben aller Gruppierungen der selektierten Elemente\";\n\nif(!ORYX.I18N.Loading) ORYX.I18N.Loading = {};\n\nORYX.I18N.Loading.waiting =\"Bitte warten...\";\n\nif(!ORYX.I18N.PropertyWindow) ORYX.I18N.PropertyWindow = {};\n\nORYX.I18N.PropertyWindow.name = \"Name\";\nORYX.I18N.PropertyWindow.value = \"Wert\";\nORYX.I18N.PropertyWindow.selected = \"ausgewählt\";\nORYX.I18N.PropertyWindow.clickIcon = \"Symbol anklicken\";\nORYX.I18N.PropertyWindow.add = \"Hinzufügen\";\nORYX.I18N.PropertyWindow.rem = \"Löschen\";\nORYX.I18N.PropertyWindow.complex = \"Editor für komplexe Eigenschaft\";\nORYX.I18N.PropertyWindow.text = \"Editor für einen Text\";\nORYX.I18N.PropertyWindow.ok = \"Ok\";\nORYX.I18N.PropertyWindow.cancel = \"Abbrechen\";\nORYX.I18N.PropertyWindow.dateFormat = \"d/m/y\";\n\nif(!ORYX.I18N.ShapeMenuPlugin) ORYX.I18N.ShapeMenuPlugin = {};\n\nORYX.I18N.ShapeMenuPlugin.drag = \"Ziehen\";\nORYX.I18N.ShapeMenuPlugin.clickDrag = \"Klicken oder ziehen\";\nORYX.I18N.ShapeMenuPlugin.morphMsg = \"Shape morphen\";\n\nif(!ORYX.I18N.SyntaxChecker) ORYX.I18N.SyntaxChecker = {};\n\nORYX.I18N.SyntaxChecker.group = \"Verification\";\nORYX.I18N.SyntaxChecker.name = \"Syntax-Checker\";\nORYX.I18N.SyntaxChecker.desc = \"Überprüfung der Syntax\";\nORYX.I18N.SyntaxChecker.noErrors = \"Es wurden keine Syntaxfehler gefunden.\";\nORYX.I18N.SyntaxChecker.invalid = \"Ungültige Antwort vom Server.\";\nORYX.I18N.SyntaxChecker.checkingMessage = \"Überprüfung wird durchgeführt ...\";\n\nif(!ORYX.I18N.Undo) ORYX.I18N.Undo = {};\n\nORYX.I18N.Undo.group = \"Undo\";\nORYX.I18N.Undo.undo = \"Rückgängig\";\nORYX.I18N.Undo.undoDesc = \"Rückgängig\";\nORYX.I18N.Undo.redo = \"Wiederherstellen\";\nORYX.I18N.Undo.redoDesc = \"Wiederherstellen\";\n\nif(!ORYX.I18N.View) ORYX.I18N.View = {};\n\nORYX.I18N.View.group = \"Zoom\";\nORYX.I18N.View.zoomIn = \"Vergrößern\";\nORYX.I18N.View.zoomInDesc = \"Vergrößern\";\nORYX.I18N.View.zoomOut = \"Verkleinern\";\nORYX.I18N.View.zoomOutDesc = \"Verkleinern\";\nORYX.I18N.View.zoomStandard = \"Originalgröße\";\nORYX.I18N.View.zoomStandardDesc = \"Originalgröße\";\nORYX.I18N.View.zoomFitToModel = \"Modelgröße\";\nORYX.I18N.View.zoomFitToModelDesc = \"Modelgröße\";\n\n/** New Language Properties: 08.12.2008 **/\n\nORYX.I18N.PropertyWindow.title = \"Eigenschaften\";\n\nif(!ORYX.I18N.ShapeRepository) ORYX.I18N.ShapeRepository = {};\nORYX.I18N.ShapeRepository.title = \"Shape Verzeichnis\";\n\nORYX.I18N.Save.dialogDesciption = \"Bitte geben Sie einen Namen, eine Beschreibung und einen Kommentar ein.\";\nORYX.I18N.Save.dialogLabelTitle = \"Titel\";\nORYX.I18N.Save.dialogLabelDesc = \"Beschreibung\";\nORYX.I18N.Save.dialogLabelType = \"Typ\";\nORYX.I18N.Save.dialogLabelComment = \"Revisionskommentar\";\n\nif(!ORYX.I18N.Perspective) ORYX.I18N.Perspective = {};\nORYX.I18N.Perspective.no = \"Keine Perspektive\"\nORYX.I18N.Perspective.noTip = \"Zurücksetzen der aktuellen Perspektive\"\n\n/** New Language Properties: 21.04.2009 */\nORYX.I18N.JSONSupport = {\n    imp: {\n        name: \"JSON importieren\",\n        desc: \"Importiert ein neues Modell aus JSON\",\n        group: \"Export\",\n        selectFile: \"Wählen Sie eine JSON-Datei (*.json) aus, die Sie importieren möchten, oder fügen Sie JSON in das Textfeld ein.\",\n        file: \"Datei\",\n        btnImp: \"Importieren\",\n        btnClose: \"Schließen\",\n        progress: \"Importieren ...\",\n        syntaxError: \"Syntaxfehler\"\n    },\n    exp: {\n        name: \"Nach JSON exportieren\",\n        desc: \"Exportiert das aktuelle Modell nach JSON\",\n        group: \"Export\"\n    }\n};\n\n/** New Language Properties: 09.05.2009 */\nif(!ORYX.I18N.JSONImport) ORYX.I18N.JSONImport = {};\n\nORYX.I18N.JSONImport.title = \"JSON Import\";\nORYX.I18N.JSONImport.wrongSS = \"Das Stencil Set der importierten Datei ({0}) entspricht nicht dem geladenen Stencil Set ({1}).\"\n\n/** New Language Properties: 14.05.2009 */\nif(!ORYX.I18N.RDFExport) ORYX.I18N.RDFExport = {};\nORYX.I18N.RDFExport.group = \"Export\";\nORYX.I18N.RDFExport.rdfExport = \"Nach RDF exportieren\";\nORYX.I18N.RDFExport.rdfExportDescription = \"Exportiert das aktuelle Model in die XML-Serialisierung des Resource Description Frameworks (RDF)\";\n\n/** New Language Properties: 15.05.2009*/\nif(!ORYX.I18N.SyntaxChecker.BPMN) ORYX.I18N.SyntaxChecker.BPMN={};\nORYX.I18N.SyntaxChecker.BPMN_NO_SOURCE = \"Eine Kante muss einen Ursprung haben.\";\nORYX.I18N.SyntaxChecker.BPMN_NO_TARGET = \"Eine Kante muss ein Ziel haben.\";\nORYX.I18N.SyntaxChecker.BPMN_DIFFERENT_PROCESS = \"Ursprungs- und Zielknoten müssen im gleichen Prozess sein.\";\nORYX.I18N.SyntaxChecker.BPMN_SAME_PROCESS = \"Ursprungs- und Zielknoten müssen in verschiedenen Pools enthalten sein.\";\nORYX.I18N.SyntaxChecker.BPMN_FLOWOBJECT_NOT_CONTAINED_IN_PROCESS = \"Ein Kontrollflussobjekt muss sich in einem Prozess befinden.\";\nORYX.I18N.SyntaxChecker.BPMN_ENDEVENT_WITHOUT_INCOMING_CONTROL_FLOW = \"Ein End-Ereignis muss einen eingehenden Sequenzfluss haben.\";\nORYX.I18N.SyntaxChecker.BPMN_STARTEVENT_WITHOUT_OUTGOING_CONTROL_FLOW = \"Ein Start-Ereignis muss einen ausgehenden Sequenzfluss haben.\";\nORYX.I18N.SyntaxChecker.BPMN_STARTEVENT_WITH_INCOMING_CONTROL_FLOW = \"Start-Ereignisse dürfen keinen eingehenden Sequenzfluss haben.\";\nORYX.I18N.SyntaxChecker.BPMN_ATTACHEDINTERMEDIATEEVENT_WITH_INCOMING_CONTROL_FLOW = \"Angeheftete Zwischen-Ereignisse dürfen keinen eingehenden Sequenzfluss haben.\";\nORYX.I18N.SyntaxChecker.BPMN_ATTACHEDINTERMEDIATEEVENT_WITHOUT_OUTGOING_CONTROL_FLOW = \"Angeheftete Zwischen-Ereignisse müssen genau einen ausgehenden Sequenzfluss haben.\";\nORYX.I18N.SyntaxChecker.BPMN_ENDEVENT_WITH_OUTGOING_CONTROL_FLOW = \"End-Ereignisse dürfen keinen ausgehenden Sequenzfluss haben.\";\nORYX.I18N.SyntaxChecker.BPMN_EVENTBASEDGATEWAY_BADCONTINUATION = \"Auf Ereignis-basierte Gateways dürfen weder Gateways noch Subprozesse folgen.\";\nORYX.I18N.SyntaxChecker.BPMN_NODE_NOT_ALLOWED = \"Knotentyp ist nicht erlaubt.\";\n\nif(!ORYX.I18N.SyntaxChecker.IBPMN) ORYX.I18N.SyntaxChecker.IBPMN={};\nORYX.I18N.SyntaxChecker.IBPMN_NO_ROLE_SET = \"Für Interaktionen muss ein Sender und ein Empfänger definiert sein.\";\nORYX.I18N.SyntaxChecker.IBPMN_NO_INCOMING_SEQFLOW = \"Dieser Knoten muss eingehenden Sequenzfluss besitzen.\";\nORYX.I18N.SyntaxChecker.IBPMN_NO_OUTGOING_SEQFLOW = \"Dieser Knoten muss ausgehenden Sequenzfluss besitzen.\";\n\nif(!ORYX.I18N.SyntaxChecker.InteractionNet) ORYX.I18N.SyntaxChecker.InteractionNet={};\nORYX.I18N.SyntaxChecker.InteractionNet_SENDER_NOT_SET = \"Sender ist nicht definiert\";\nORYX.I18N.SyntaxChecker.InteractionNet_RECEIVER_NOT_SET = \"Empfänger ist nicht definiert\";\nORYX.I18N.SyntaxChecker.InteractionNet_MESSAGETYPE_NOT_SET = \"Nachrichtentyp ist nicht definiert.\";\nORYX.I18N.SyntaxChecker.InteractionNet_ROLE_NOT_SET = \"Rolle ist nicht definiert.\";\n\nif(!ORYX.I18N.SyntaxChecker.EPC) ORYX.I18N.SyntaxChecker.EPC={};\nORYX.I18N.SyntaxChecker.EPC_NO_SOURCE = \"Eine Kante muss einen Ursprung haben.\";\nORYX.I18N.SyntaxChecker.EPC_NO_TARGET = \"Eine Kante muss ein Ziel haben.\";\nORYX.I18N.SyntaxChecker.EPC_NOT_CONNECTED = \"Dieser Knoten muss eingehende oder ausgehende Kanten besitzen.\";\nORYX.I18N.SyntaxChecker.EPC_NOT_CONNECTED_2 = \"Dieser Knoten muss sowohl eingehende als auch ausgehende Kanten besitzen.\";\nORYX.I18N.SyntaxChecker.EPC_TOO_MANY_EDGES = \"Knoten ist mit zu vielen Kanten verbunden.\";\nORYX.I18N.SyntaxChecker.EPC_NO_CORRECT_CONNECTOR = \"Knoten ist kein korrekter Konnektor.\";\nORYX.I18N.SyntaxChecker.EPC_MANY_STARTS = \"Es darf nur ein Start-Ereignis geben.\";\nORYX.I18N.SyntaxChecker.EPC_FUNCTION_AFTER_OR = \"Funktionen hinter einem OR-/XOR-Split sind nicht erlaubt.\";\nORYX.I18N.SyntaxChecker.EPC_PI_AFTER_OR = \"Prozessschnittstellen hinter einem OR-/XOR-Split ist nicht erlaubt.\";\nORYX.I18N.SyntaxChecker.EPC_FUNCTION_AFTER_FUNCTION =  \"Auf eine Funktion darf keine Funktion folgen.\";\nORYX.I18N.SyntaxChecker.EPC_EVENT_AFTER_EVENT =  \"Auf ein Ereignis darf kein Ereignis folgen.\";\nORYX.I18N.SyntaxChecker.EPC_PI_AFTER_FUNCTION =  \"Auf eine Funktion darf keine Prozessschnittstelle folgen.\";\nORYX.I18N.SyntaxChecker.EPC_FUNCTION_AFTER_PI =  \"Auf eine Prozessschnittstelle darf keine Funktion folgen.\";\nORYX.I18N.SyntaxChecker.EPC_SOURCE_EQUALS_TARGET = \"Eine Kante muss zwei verschiedene Knoten verbinden.\"\n\nif(!ORYX.I18N.SyntaxChecker.PetriNet) ORYX.I18N.SyntaxChecker.PetriNet={};\nORYX.I18N.SyntaxChecker.PetriNet_NOT_BIPARTITE = \"Der Graph ist nicht bepartit.\";\nORYX.I18N.SyntaxChecker.PetriNet_NO_LABEL = \"Bezeichnung für einen bezeichnete Transition ist nicht gesetzt.\";\nORYX.I18N.SyntaxChecker.PetriNet_NO_ID = \"Ein Knoten besitzt keine ID.\";\nORYX.I18N.SyntaxChecker.PetriNet_SAME_SOURCE_AND_TARGET = \"Zwei Flussbeziehungen besitzen den gleichen Ursprung und das gleiche Ziel.\";\nORYX.I18N.SyntaxChecker.PetriNet_NODE_NOT_SET = \"Ein Knoten ist nicht definiert für einen Flussbeziehung.\";\n\n/** New Language Properties: 02.06.2009*/\nORYX.I18N.Edge = \"Kante\";\nORYX.I18N.Node = \"Knoten\";\n\n/** New Language Properties: 02.06.2009*/\nORYX.I18N.SyntaxChecker.notice = \"Bitte bewegen Sie den Mauszeiger über ein rotes Kreuz, um die Details zu erfahren.\";\n\n/** New Language Properties: 15.07.2009*/\nif(!ORYX.I18N.Layouting) ORYX.I18N.Layouting ={};\nORYX.I18N.Layouting.doing = \"Layouten...\";\n\n/** New Language Properties: 18.08.2009*/\nORYX.I18N.SyntaxChecker.MULT_ERRORS = \"Mehrere Fehler\";\n\n/** New Language Properties: 08.09.2009*/\nif(!ORYX.I18N.PropertyWindow) ORYX.I18N.PropertyWindow = {};\nORYX.I18N.PropertyWindow.oftenUsed = \"Hauptattribute\";\nORYX.I18N.PropertyWindow.moreProps = \"Mehr Attribute\";\n\n/** New Language Properties 01.10.2009 */\nif(!ORYX.I18N.SyntaxChecker.BPMN2) ORYX.I18N.SyntaxChecker.BPMN2 = {};\n\nORYX.I18N.SyntaxChecker.BPMN2_DATA_INPUT_WITH_INCOMING_DATA_ASSOCIATION = \"Ein Dateninput darf keine ausgehenden Datenassoziationen haben.\";\nORYX.I18N.SyntaxChecker.BPMN2_DATA_OUTPUT_WITH_OUTGOING_DATA_ASSOCIATION = \"Ein Datenoutput darf keine eingehenden Datenassoziationen haben.\";\nORYX.I18N.SyntaxChecker.BPMN2_EVENT_BASED_TARGET_WITH_TOO_MANY_INCOMING_SEQUENCE_FLOWS = \"Ziele von Ereignis-basierten Gateways dürfen nicht mehr als einen eingehenden Sequenzfluss haben.\";\n\n/** New Language Properties 02.10.2009 */\nORYX.I18N.SyntaxChecker.BPMN2_EVENT_BASED_WITH_TOO_LESS_OUTGOING_SEQUENCE_FLOWS = \"Ein Ereignis-basiertes Gateway muss 2 oder mehr ausgehende Sequenzflüsse besitzen.\";\nORYX.I18N.SyntaxChecker.BPMN2_EVENT_BASED_EVENT_TARGET_CONTRADICTION = \"Wenn Nachrichten-Zwischenereignisse im Diagramm verwendet werden, dann dürfen Receive Tasks nicht verwendet werden und umgekehrt.\";\nORYX.I18N.SyntaxChecker.BPMN2_EVENT_BASED_WRONG_TRIGGER = \"Nur die folgenden Zwischen-Ereignis-Auslöser sind hier zulässig: Nachricht, Signal, Timer, Bedingungs und Mehrfach.\";\nORYX.I18N.SyntaxChecker.BPMN2_EVENT_BASED_WRONG_CONDITION_EXPRESSION = \"Die ausgehenden Sequenzflüsse eines Ereignis-Gateways dürfen keinen Bedingungsausdruck besitzen.\";\nORYX.I18N.SyntaxChecker.BPMN2_EVENT_BASED_NOT_INSTANTIATING = \"Das Gateway erfüllt nicht die Voraussetzungen um den Prozess zu instantiieren. Bitte verwenden Sie ein Start-Ereignis oder setzen Sie die Instanziierungs-Attribute korrekt.\";\n\n/** New Language Properties 05.10.2009 */\nORYX.I18N.SyntaxChecker.BPMN2_GATEWAYDIRECTION_MIXED_FAILURE = \"Das Gateway muss mehrere eingehende und ausgehende Sequenzflüsse besitzen.\";\nORYX.I18N.SyntaxChecker.BPMN2_GATEWAYDIRECTION_CONVERGING_FAILURE = \"Das Gateway muss mehrere eingehende aber darf keine mehrfache ausgehende Sequenzflüsse besitzen.\";\nORYX.I18N.SyntaxChecker.BPMN2_GATEWAYDIRECTION_DIVERGING_FAILURE = \"Das Gateway darf keine mehrfachen eingehenden aber muss mehrfache ausgehende Sequenzflüsse besitzen.\";\nORYX.I18N.SyntaxChecker.BPMN2_GATEWAY_WITH_NO_OUTGOING_SEQUENCE_FLOW = \"Ein Gateway muss mindestens einen ausgehenden Sequenzfluss besitzen.\";\nORYX.I18N.SyntaxChecker.BPMN2_RECEIVE_TASK_WITH_ATTACHED_EVENT = \"Empfangende Tasks, die in Ereignis-Gateway-Konfigurationen benutzt werden, dürfen keine angehefteten Zwischen-Ereignisse besitzen.\";\nORYX.I18N.SyntaxChecker.BPMN2_EVENT_SUBPROCESS_BAD_CONNECTION = \"Ein Ereignis-Unterprozess darf keinen eingehenden oder ausgehenden Sequenzfluss besitzen.\";\n\n/** New Language Properties 13.10.2009 */\nORYX.I18N.SyntaxChecker.BPMN_MESSAGE_FLOW_NOT_CONNECTED = \"Mindestens ein Ende des Nachrichtenflusses muss mit einem anderen Objekt verbunden sein.\";\n\n/** New Language Properties 05.11.2009 */\nif(!ORYX.I18N.RESIZE) ORYX.I18N.RESIZE = {};\nORYX.I18N.RESIZE.tipGrow = \"Zeichenfläche vergrößern:\";\nORYX.I18N.RESIZE.tipShrink = \"Zeichenfläche verkleinern:\";\nORYX.I18N.RESIZE.N = \"Nach oben\";\nORYX.I18N.RESIZE.W = \"Nach links\";\nORYX.I18N.RESIZE.S =\"Nach unten\";\nORYX.I18N.RESIZE.E =\"Nach rechts\";\n\n/** New Language Properties 24.11.2009 */\nORYX.I18N.SyntaxChecker.BPMN2_TOO_MANY_INITIATING_MESSAGES = \"Eine Choreographie-Aktivität darf nur eine initiierende Nachricht besitzen.\";\nORYX.I18N.SyntaxChecker.BPMN_MESSAGE_FLOW_NOT_ALLOWED = \"Ein Nachrichtenfluss ist an dieser Stelle nicht erlaubt.\";\n\n/** New Language Properties 27.11.2009 */\nORYX.I18N.SyntaxChecker.BPMN2_EVENT_BASED_WITH_TOO_LESS_INCOMING_SEQUENCE_FLOWS = \"Ein Ereignis-basiertes Gateway, dass nicht instanziierend ist, muss mindestens einen eingehenden Kontrollfluss besitzen.\";\nORYX.I18N.SyntaxChecker.BPMN2_TOO_FEW_INITIATING_PARTICIPANTS = \"Eine Choreographie-Aktivität musst genau einen initiierenden Teilnehmer (weiß) besitzen.\";\nORYX.I18N.SyntaxChecker.BPMN2_TOO_MANY_INITIATING_PARTICIPANTS = \"Eine Choreographie-Aktivität darf nicht mehr als einen initiierenden Teilnehmer (weiß) besitzen.\"\n\nORYX.I18N.SyntaxChecker.COMMUNICATION_AT_LEAST_TWO_PARTICIPANTS = \"Die Kommunikation oder Sub-Konversation muss mit mindestens zwei Teilnehmern verbunden sein.\";\nORYX.I18N.SyntaxChecker.MESSAGEFLOW_START_MUST_BE_PARTICIPANT = \"Die Nachrichtenflussquelle muss ein Teilnehmer sein.\";\nORYX.I18N.SyntaxChecker.MESSAGEFLOW_END_MUST_BE_PARTICIPANT = \"Das Nachrichtenflussziel muss ein Teilnehmer sein.\";\nORYX.I18N.SyntaxChecker.CONV_LINK_CANNOT_CONNECT_CONV_NODES = \"Der Konversationslink muss eine Kommunikation oder Sub-Konversation mit einem Teilnehmer verbinden.\";\n"
  },
  {
    "path": "flowable-ui-web/modeler/editor-app/editor/i18n/translation_en_us.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 \n/**\n * @author nicolas.peters\n * \n * Contains all strings for the default language (en-us).\n * Version 1 - 08/29/08\n */\nif(!ORYX) var ORYX = {};\n\nif(!ORYX.I18N) ORYX.I18N = {};\n\nORYX.I18N.Language = \"en_us\"; //Pattern <ISO language code>_<ISO country code> in lower case!\n\nif(!ORYX.I18N.Oryx) ORYX.I18N.Oryx = {};\n\nORYX.I18N.Oryx.title\t\t= \"Oryx\";\nORYX.I18N.Oryx.noBackendDefined\t= \"Caution! \\nNo Backend defined.\\n The requested model cannot be loaded. Try to load a configuration with a save plugin.\";\nORYX.I18N.Oryx.pleaseWait \t= \"Please wait while loading...\";\nORYX.I18N.Oryx.notLoggedOn = \"Not logged on\";\nORYX.I18N.Oryx.editorOpenTimeout = \"The editor does not seem to be started yet. Please check, whether you have a popup blocker enabled and disable it or allow popups for this site. We will never display any commercials on this site.\";\n\nif(!ORYX.I18N.AddDocker) ORYX.I18N.AddDocker = {};\n\nORYX.I18N.AddDocker.group = \"Docker\";\nORYX.I18N.AddDocker.add = \"Add Docker\";\nORYX.I18N.AddDocker.addDesc = \"Add a Docker to an edge, by clicking on it\";\nORYX.I18N.AddDocker.del = \"Delete Docker\";\nORYX.I18N.AddDocker.delDesc = \"Delete a Docker\";\n\nif(!ORYX.I18N.Arrangement) ORYX.I18N.Arrangement = {};\n\nORYX.I18N.Arrangement.groupZ = \"Z-Order\";\nORYX.I18N.Arrangement.btf = \"Bring To Front\";\nORYX.I18N.Arrangement.btfDesc = \"Bring to Front\";\nORYX.I18N.Arrangement.btb = \"Bring To Back\";\nORYX.I18N.Arrangement.btbDesc = \"Bring To Back\";\nORYX.I18N.Arrangement.bf = \"Bring Forward\";\nORYX.I18N.Arrangement.bfDesc = \"Bring Forward\";\nORYX.I18N.Arrangement.bb = \"Bring Backward\";\nORYX.I18N.Arrangement.bbDesc = \"Bring Backward\";\nORYX.I18N.Arrangement.groupA = \"Alignment\";\nORYX.I18N.Arrangement.ab = \"Alignment Bottom\";\nORYX.I18N.Arrangement.abDesc = \"Bottom\";\nORYX.I18N.Arrangement.am = \"Alignment Middle\";\nORYX.I18N.Arrangement.amDesc = \"Middle\";\nORYX.I18N.Arrangement.at = \"Alignment Top\";\nORYX.I18N.Arrangement.atDesc = \"Top\";\nORYX.I18N.Arrangement.al = \"Alignment Left\";\nORYX.I18N.Arrangement.alDesc = \"Left\";\nORYX.I18N.Arrangement.ac = \"Alignment Center\";\nORYX.I18N.Arrangement.acDesc = \"Center\";\nORYX.I18N.Arrangement.ar = \"Alignment Right\";\nORYX.I18N.Arrangement.arDesc = \"Right\";\nORYX.I18N.Arrangement.as = \"Alignment Same Size\";\nORYX.I18N.Arrangement.asDesc = \"Same Size\";\n\nif(!ORYX.I18N.Edit) ORYX.I18N.Edit = {};\n\nORYX.I18N.Edit.group = \"Edit\";\nORYX.I18N.Edit.cut = \"Cut\";\nORYX.I18N.Edit.cutDesc = \"Cuts the selection into an Oryx clipboard\";\nORYX.I18N.Edit.copy = \"Copy\";\nORYX.I18N.Edit.copyDesc = \"Copies the selection into an Oryx clipboard\";\nORYX.I18N.Edit.paste = \"Paste\";\nORYX.I18N.Edit.pasteDesc = \"Pastes the Oryx clipboard to the canvas\";\nORYX.I18N.Edit.del = \"Delete\";\nORYX.I18N.Edit.delDesc = \"Deletes all selected shapes\";\n\nif(!ORYX.I18N.EPCSupport) ORYX.I18N.EPCSupport = {};\n\nORYX.I18N.EPCSupport.group = \"EPC\";\nORYX.I18N.EPCSupport.exp = \"Export EPC\";\nORYX.I18N.EPCSupport.expDesc = \"Export diagram to EPML\";\nORYX.I18N.EPCSupport.imp = \"Import EPC\";\nORYX.I18N.EPCSupport.impDesc = \"Import an EPML file\";\nORYX.I18N.EPCSupport.progressExp = \"Exporting model\";\nORYX.I18N.EPCSupport.selectFile = \"Select an EPML (.empl) file to import.\";\nORYX.I18N.EPCSupport.file = \"File\";\nORYX.I18N.EPCSupport.impPanel = \"Import EPML File\";\nORYX.I18N.EPCSupport.impBtn = \"Import\";\nORYX.I18N.EPCSupport.close = \"Close\";\nORYX.I18N.EPCSupport.error = \"Error\";\nORYX.I18N.EPCSupport.progressImp = \"Import...\";\n\nif(!ORYX.I18N.ERDFSupport) ORYX.I18N.ERDFSupport = {};\n\nORYX.I18N.ERDFSupport.exp = \"Export to ERDF\";\nORYX.I18N.ERDFSupport.expDesc = \"Export to ERDF\";\nORYX.I18N.ERDFSupport.imp = \"Import from ERDF\";\nORYX.I18N.ERDFSupport.impDesc = \"Import from ERDF\";\nORYX.I18N.ERDFSupport.impFailed = \"Request for import of ERDF failed.\";\nORYX.I18N.ERDFSupport.impFailed2 = \"An error while importing occurs! <br/>Please check error message: <br/><br/>\";\nORYX.I18N.ERDFSupport.error = \"Error\";\nORYX.I18N.ERDFSupport.noCanvas = \"The xml document has no Oryx canvas node included!\";\nORYX.I18N.ERDFSupport.noSS = \"The Oryx canvas node has no stencil set definition included!\";\nORYX.I18N.ERDFSupport.wrongSS = \"The given stencil set does not fit to the current editor!\";\nORYX.I18N.ERDFSupport.selectFile = \"Select an ERDF (.xml) file or type in the ERDF to import it!\";\nORYX.I18N.ERDFSupport.file = \"File\";\nORYX.I18N.ERDFSupport.impERDF = \"Import ERDF\";\nORYX.I18N.ERDFSupport.impBtn = \"Import\";\nORYX.I18N.ERDFSupport.impProgress = \"Importing...\";\nORYX.I18N.ERDFSupport.close = \"Close\";\nORYX.I18N.ERDFSupport.deprTitle = \"Really export to eRDF?\";\nORYX.I18N.ERDFSupport.deprText = \"Exporting to eRDF is not recommended anymore because the support will be stopped in future versions of the Oryx editor. If possible, export the model to JSON. Do you want to export anyway?\";\n\nif(!ORYX.I18N.jPDLSupport) ORYX.I18N.jPDLSupport = {};\n\nORYX.I18N.jPDLSupport.group = \"ExecBPMN\";\nORYX.I18N.jPDLSupport.exp = \"Export to jPDL\";\nORYX.I18N.jPDLSupport.expDesc = \"Export to jPDL\";\nORYX.I18N.jPDLSupport.imp = \"Import from jPDL\";\nORYX.I18N.jPDLSupport.impDesc = \"Import jPDL File\";\nORYX.I18N.jPDLSupport.impFailedReq = \"Request for import of jPDL failed.\";\nORYX.I18N.jPDLSupport.impFailedJson = \"Transformation of jPDL failed.\";\nORYX.I18N.jPDLSupport.impFailedJsonAbort = \"Import aborted.\";\nORYX.I18N.jPDLSupport.loadSseQuestionTitle = \"jBPM stencil set extension needs to be loaded\"; \nORYX.I18N.jPDLSupport.loadSseQuestionBody = \"In order to import jPDL, the stencil set extension has to be loaded. Do you want to proceed?\";\nORYX.I18N.jPDLSupport.expFailedReq = \"Request for export of model failed.\";\nORYX.I18N.jPDLSupport.expFailedXml = \"Export to jPDL failed. Exporter reported: \";\nORYX.I18N.jPDLSupport.error = \"Error\";\nORYX.I18N.jPDLSupport.selectFile = \"Select an jPDL (.xml) file or type in the jPDL to import it!\";\nORYX.I18N.jPDLSupport.file = \"File\";\nORYX.I18N.jPDLSupport.impJPDL = \"Import jPDL\";\nORYX.I18N.jPDLSupport.impBtn = \"Import\";\nORYX.I18N.jPDLSupport.impProgress = \"Importing...\";\nORYX.I18N.jPDLSupport.close = \"Close\";\n\nif(!ORYX.I18N.Save) ORYX.I18N.Save = {};\n\nORYX.I18N.Save.group = \"File\";\nORYX.I18N.Save.save = \"Save\";\nORYX.I18N.Save.saveDesc = \"Save\";\nORYX.I18N.Save.saveAs = \"Save As...\";\nORYX.I18N.Save.saveAsDesc = \"Save As...\";\nORYX.I18N.Save.unsavedData = \"There are unsaved data, please save before you leave, otherwise your changes get lost!\";\nORYX.I18N.Save.newProcess = \"New Process\";\nORYX.I18N.Save.saveAsTitle = \"Save as...\";\nORYX.I18N.Save.saveBtn = \"Save\";\nORYX.I18N.Save.close = \"Close\";\nORYX.I18N.Save.savedAs = \"Saved As\";\nORYX.I18N.Save.saved = \"Saved!\";\nORYX.I18N.Save.failed = \"Saving failed.\";\nORYX.I18N.Save.noRights = \"You have no rights to save changes.\";\nORYX.I18N.Save.saving = \"Saving\";\nORYX.I18N.Save.saveAsHint = \"The process diagram is stored under:\";\n\nif(!ORYX.I18N.File) ORYX.I18N.File = {};\n\nORYX.I18N.File.group = \"File\";\nORYX.I18N.File.print = \"Print\";\nORYX.I18N.File.printDesc = \"Print current model\";\nORYX.I18N.File.pdf = \"Export as PDF\";\nORYX.I18N.File.pdfDesc = \"Export as PDF\";\nORYX.I18N.File.info = \"Info\";\nORYX.I18N.File.infoDesc = \"Info\";\nORYX.I18N.File.genPDF = \"Generating PDF\";\nORYX.I18N.File.genPDFFailed = \"Generating PDF failed.\";\nORYX.I18N.File.printTitle = \"Print\";\nORYX.I18N.File.printMsg = \"We are currently experiencing problems with the printing function. We recommend using the PDF Export to print the diagram. Do you really want to continue printing?\";\n\nif(!ORYX.I18N.Grouping) ORYX.I18N.Grouping = {};\n\nORYX.I18N.Grouping.grouping = \"Grouping\";\nORYX.I18N.Grouping.group = \"Group\";\nORYX.I18N.Grouping.groupDesc = \"Groups all selected shapes\";\nORYX.I18N.Grouping.ungroup = \"Ungroup\";\nORYX.I18N.Grouping.ungroupDesc = \"Deletes the group of all selected Shapes\";\n\nif(!ORYX.I18N.Loading) ORYX.I18N.Loading = {};\n\nORYX.I18N.Loading.waiting =\"Please wait...\";\n\nif(!ORYX.I18N.PropertyWindow) ORYX.I18N.PropertyWindow = {};\n\nORYX.I18N.PropertyWindow.name = \"Name\";\nORYX.I18N.PropertyWindow.value = \"Value\";\nORYX.I18N.PropertyWindow.selected = \"selected\";\nORYX.I18N.PropertyWindow.clickIcon = \"Click Icon\";\nORYX.I18N.PropertyWindow.add = \"Add\";\nORYX.I18N.PropertyWindow.rem = \"Remove\";\nORYX.I18N.PropertyWindow.complex = \"Editor for a Complex Type\";\nORYX.I18N.PropertyWindow.text = \"Editor for a Text Type\";\nORYX.I18N.PropertyWindow.ok = \"Ok\";\nORYX.I18N.PropertyWindow.cancel = \"Cancel\";\nORYX.I18N.PropertyWindow.dateFormat = \"m/d/y\";\n\nif(!ORYX.I18N.ShapeMenuPlugin) ORYX.I18N.ShapeMenuPlugin = {};\n\nORYX.I18N.ShapeMenuPlugin.drag = \"Drag\";\nORYX.I18N.ShapeMenuPlugin.clickDrag = \"Click or drag\";\nORYX.I18N.ShapeMenuPlugin.morphMsg = \"Morph shape\";\n\nif(!ORYX.I18N.SyntaxChecker) ORYX.I18N.SyntaxChecker = {};\n\nORYX.I18N.SyntaxChecker.group = \"Verification\";\nORYX.I18N.SyntaxChecker.name = \"Syntax Checker\";\nORYX.I18N.SyntaxChecker.desc = \"Check Syntax\";\nORYX.I18N.SyntaxChecker.noErrors = \"There are no syntax errors.\";\nORYX.I18N.SyntaxChecker.invalid = \"Invalid answer from server.\";\nORYX.I18N.SyntaxChecker.checkingMessage = \"Checking ...\";\n\nif(!ORYX.I18N.FormHandler) ORYX.I18N.FormHandler = {};\n\nORYX.I18N.FormHandler.group = \"FormHandling\";\nORYX.I18N.FormHandler.name = \"FormHandler\";\nORYX.I18N.FormHandler.desc = \"Testing from handling\";\n\nif(!ORYX.I18N.Deployer) ORYX.I18N.Deployer = {};\n\nORYX.I18N.Deployer.group = \"Deployment\";\nORYX.I18N.Deployer.name = \"Deployer\";\nORYX.I18N.Deployer.desc = \"Deploy to engine\";\n\nif(!ORYX.I18N.Tester) ORYX.I18N.Tester = {};\n\nORYX.I18N.Tester.group = \"Testing\";\nORYX.I18N.Tester.name = \"Test process\";\nORYX.I18N.Tester.desc = \"Open the test component to test this process definition\";\n\nif(!ORYX.I18N.Undo) ORYX.I18N.Undo = {};\n\nORYX.I18N.Undo.group = \"Undo\";\nORYX.I18N.Undo.undo = \"Undo\";\nORYX.I18N.Undo.undoDesc = \"Undo the last action\";\nORYX.I18N.Undo.redo = \"Redo\";\nORYX.I18N.Undo.redoDesc = \"Redo the last undone action\";\n\nif(!ORYX.I18N.View) ORYX.I18N.View = {};\n\nORYX.I18N.View.group = \"Zoom\";\nORYX.I18N.View.zoomIn = \"Zoom In\";\nORYX.I18N.View.zoomInDesc = \"Zoom into the model\";\nORYX.I18N.View.zoomOut = \"Zoom Out\";\nORYX.I18N.View.zoomOutDesc = \"Zoom out of the model\";\nORYX.I18N.View.zoomStandard = \"Zoom Standard\";\nORYX.I18N.View.zoomStandardDesc = \"Zoom to the standard level\";\nORYX.I18N.View.zoomFitToModel = \"Zoom fit to model\";\nORYX.I18N.View.zoomFitToModelDesc = \"Zoom to fit the model size\";\n\nif(!ORYX.I18N.XFormsSerialization) ORYX.I18N.XFormsSerialization = {};\n\nORYX.I18N.XFormsSerialization.group = \"XForms Serialization\";\nORYX.I18N.XFormsSerialization.exportXForms = \"XForms Export\";\nORYX.I18N.XFormsSerialization.exportXFormsDesc = \"Export XForms+XHTML markup\";\nORYX.I18N.XFormsSerialization.importXForms = \"XForms Import\";\nORYX.I18N.XFormsSerialization.importXFormsDesc = \"Import XForms+XHTML markup\";\nORYX.I18N.XFormsSerialization.noClientXFormsSupport = \"No XForms support\";\nORYX.I18N.XFormsSerialization.noClientXFormsSupportDesc = \"<h2>Your browser does not support XForms. Please install the <a href=\\\"https://addons.mozilla.org/firefox/addon/824\\\" target=\\\"_blank\\\">Mozilla XForms Add-on</a> for Firefox.</h2>\";\nORYX.I18N.XFormsSerialization.ok = \"Ok\";\nORYX.I18N.XFormsSerialization.selectFile = \"Select a XHTML (.xhtml) file or type in the XForms+XHTML markup to import it!\";\nORYX.I18N.XFormsSerialization.selectCss = \"Please insert url of css file\";\nORYX.I18N.XFormsSerialization.file = \"File\";\nORYX.I18N.XFormsSerialization.impFailed = \"Request for import of document failed.\";\nORYX.I18N.XFormsSerialization.impTitle = \"Import XForms+XHTML document\";\nORYX.I18N.XFormsSerialization.expTitle = \"Export XForms+XHTML document\";\nORYX.I18N.XFormsSerialization.impButton = \"Import\";\nORYX.I18N.XFormsSerialization.impProgress = \"Importing...\";\nORYX.I18N.XFormsSerialization.close = \"Close\";\n\n/** New Language Properties: 08.12.2008 */\n\nORYX.I18N.PropertyWindow.title = \"Properties\";\n\nif(!ORYX.I18N.ShapeRepository) ORYX.I18N.ShapeRepository = {};\nORYX.I18N.ShapeRepository.title = \"Shape Repository\";\n\nORYX.I18N.Save.dialogDesciption = \"Please enter a name, a description and a comment.\";\nORYX.I18N.Save.dialogLabelTitle = \"Title\";\nORYX.I18N.Save.dialogLabelDesc = \"Description\";\nORYX.I18N.Save.dialogLabelType = \"Type\";\nORYX.I18N.Save.dialogLabelComment = \"Revision comment\";\n\nif(!ORYX.I18N.Perspective) ORYX.I18N.Perspective = {};\nORYX.I18N.Perspective.no = \"No Perspective\"\nORYX.I18N.Perspective.noTip = \"Unload the current perspective\"\n\n/** New Language Properties: 21.04.2009 */\nORYX.I18N.JSONSupport = {\n    imp: {\n        name: \"Import from JSON\",\n        desc: \"Imports a model from JSON\",\n        group: \"Export\",\n        selectFile: \"Select an JSON (.json) file or type in JSON to import it!\",\n        file: \"File\",\n        btnImp: \"Import\",\n        btnClose: \"Close\",\n        progress: \"Importing ...\",\n        syntaxError: \"Syntax error\"\n    },\n    exp: {\n        name: \"Export to JSON\",\n        desc: \"Exports current model to JSON\",\n        group: \"Export\"\n    }\n};\n\n/** New Language Properties: 09.05.2009 */\nif(!ORYX.I18N.JSONImport) ORYX.I18N.JSONImport = {};\n\nORYX.I18N.JSONImport.title = \"JSON Import\";\nORYX.I18N.JSONImport.wrongSS = \"The stencil set of the imported file ({0}) does not match to the loaded stencil set ({1}).\"\n\n/** New Language Properties: 14.05.2009 */\nif(!ORYX.I18N.RDFExport) ORYX.I18N.RDFExport = {};\nORYX.I18N.RDFExport.group = \"Export\";\nORYX.I18N.RDFExport.rdfExport = \"Export to RDF\";\nORYX.I18N.RDFExport.rdfExportDescription = \"Exports current model to the XML serialization defined for the Resource Description Framework (RDF)\";\n\n/** New Language Properties: 15.05.2009*/\nif(!ORYX.I18N.SyntaxChecker.BPMN) ORYX.I18N.SyntaxChecker.BPMN={};\nORYX.I18N.SyntaxChecker.BPMN_NO_SOURCE = \"An edge must have a source.\";\nORYX.I18N.SyntaxChecker.BPMN_NO_TARGET = \"An edge must have a target.\";\nORYX.I18N.SyntaxChecker.BPMN_DIFFERENT_PROCESS = \"Source and target node must be contained in the same process.\";\nORYX.I18N.SyntaxChecker.BPMN_SAME_PROCESS = \"Source and target node must be contained in different pools.\";\nORYX.I18N.SyntaxChecker.BPMN_FLOWOBJECT_NOT_CONTAINED_IN_PROCESS = \"A flow object must be contained in a process.\";\nORYX.I18N.SyntaxChecker.BPMN_ENDEVENT_WITHOUT_INCOMING_CONTROL_FLOW = \"An end event must have an incoming sequence flow.\";\nORYX.I18N.SyntaxChecker.BPMN_STARTEVENT_WITHOUT_OUTGOING_CONTROL_FLOW = \"A start event must have an outgoing sequence flow.\";\nORYX.I18N.SyntaxChecker.BPMN_STARTEVENT_WITH_INCOMING_CONTROL_FLOW = \"Start events must not have incoming sequence flows.\";\nORYX.I18N.SyntaxChecker.BPMN_ATTACHEDINTERMEDIATEEVENT_WITH_INCOMING_CONTROL_FLOW = \"Attached intermediate events must not have incoming sequence flows.\";\nORYX.I18N.SyntaxChecker.BPMN_ATTACHEDINTERMEDIATEEVENT_WITHOUT_OUTGOING_CONTROL_FLOW = \"Attached intermediate events must have exactly one outgoing sequence flow.\";\nORYX.I18N.SyntaxChecker.BPMN_ENDEVENT_WITH_OUTGOING_CONTROL_FLOW = \"End events must not have outgoing sequence flows.\";\nORYX.I18N.SyntaxChecker.BPMN_EVENTBASEDGATEWAY_BADCONTINUATION = \"Event-based gateways must not be followed by gateways or subprocesses.\";\nORYX.I18N.SyntaxChecker.BPMN_NODE_NOT_ALLOWED = \"Node type is not allowed.\";\n\nif(!ORYX.I18N.SyntaxChecker.IBPMN) ORYX.I18N.SyntaxChecker.IBPMN={};\nORYX.I18N.SyntaxChecker.IBPMN_NO_ROLE_SET = \"Interactions must have a sender and a receiver role set\";\nORYX.I18N.SyntaxChecker.IBPMN_NO_INCOMING_SEQFLOW = \"This node must have incoming sequence flow.\";\nORYX.I18N.SyntaxChecker.IBPMN_NO_OUTGOING_SEQFLOW = \"This node must have outgoing sequence flow.\";\n\nif(!ORYX.I18N.SyntaxChecker.InteractionNet) ORYX.I18N.SyntaxChecker.InteractionNet={};\nORYX.I18N.SyntaxChecker.InteractionNet_SENDER_NOT_SET = \"Sender not set\";\nORYX.I18N.SyntaxChecker.InteractionNet_RECEIVER_NOT_SET = \"Receiver not set\";\nORYX.I18N.SyntaxChecker.InteractionNet_MESSAGETYPE_NOT_SET = \"Message type not set\";\nORYX.I18N.SyntaxChecker.InteractionNet_ROLE_NOT_SET = \"Role not set\";\n\nif(!ORYX.I18N.SyntaxChecker.EPC) ORYX.I18N.SyntaxChecker.EPC={};\nORYX.I18N.SyntaxChecker.EPC_NO_SOURCE = \"Each edge must have a source.\";\nORYX.I18N.SyntaxChecker.EPC_NO_TARGET = \"Each edge must have a target.\";\nORYX.I18N.SyntaxChecker.EPC_NOT_CONNECTED = \"Node must be connected with edges.\";\nORYX.I18N.SyntaxChecker.EPC_NOT_CONNECTED_2 = \"Node must be connected with more edges.\";\nORYX.I18N.SyntaxChecker.EPC_TOO_MANY_EDGES = \"Node has too many connected edges.\";\nORYX.I18N.SyntaxChecker.EPC_NO_CORRECT_CONNECTOR = \"Node is no correct connector.\";\nORYX.I18N.SyntaxChecker.EPC_MANY_STARTS = \"There must be only one start event.\";\nORYX.I18N.SyntaxChecker.EPC_FUNCTION_AFTER_OR = \"There must be no functions after a splitting OR/XOR.\";\nORYX.I18N.SyntaxChecker.EPC_PI_AFTER_OR = \"There must be no process interface after a splitting OR/XOR.\";\nORYX.I18N.SyntaxChecker.EPC_FUNCTION_AFTER_FUNCTION =  \"There must be no function after a function.\";\nORYX.I18N.SyntaxChecker.EPC_EVENT_AFTER_EVENT =  \"There must be no event after an event.\";\nORYX.I18N.SyntaxChecker.EPC_PI_AFTER_FUNCTION =  \"There must be no process interface after a function.\";\nORYX.I18N.SyntaxChecker.EPC_FUNCTION_AFTER_PI =  \"There must be no function after a process interface.\";\nORYX.I18N.SyntaxChecker.EPC_SOURCE_EQUALS_TARGET = \"Edge must connect two distinct nodes.\"\n\nif(!ORYX.I18N.SyntaxChecker.PetriNet) ORYX.I18N.SyntaxChecker.PetriNet={};\nORYX.I18N.SyntaxChecker.PetriNet_NOT_BIPARTITE = \"The graph is not bipartite\";\nORYX.I18N.SyntaxChecker.PetriNet_NO_LABEL = \"Label not set for a labeled transition\";\nORYX.I18N.SyntaxChecker.PetriNet_NO_ID = \"There is a node without id\";\nORYX.I18N.SyntaxChecker.PetriNet_SAME_SOURCE_AND_TARGET = \"Two flow relationships have the same source and target\";\nORYX.I18N.SyntaxChecker.PetriNet_NODE_NOT_SET = \"A node is not set for a flowrelationship\";\n\n/** New Language Properties: 02.06.2009*/\nORYX.I18N.Edge = \"Edge\";\nORYX.I18N.Node = \"Node\";\n\n/** New Language Properties: 03.06.2009*/\nORYX.I18N.SyntaxChecker.notice = \"Move the mouse over a red cross icon to see the error message.\";\n\n/** New Language Properties: 05.06.2009*/\nif(!ORYX.I18N.RESIZE) ORYX.I18N.RESIZE = {};\nORYX.I18N.RESIZE.tipGrow = \"Increase canvas size:\";\nORYX.I18N.RESIZE.tipShrink = \"Decrease canvas size:\";\nORYX.I18N.RESIZE.N = \"Top\";\nORYX.I18N.RESIZE.W = \"Left\";\nORYX.I18N.RESIZE.S =\"Down\";\nORYX.I18N.RESIZE.E =\"Right\";\n\n/** New Language Properties: 15.07.2009*/\nif(!ORYX.I18N.Layouting) ORYX.I18N.Layouting ={};\nORYX.I18N.Layouting.doing = \"Layouting...\";\n\n/** New Language Properties: 18.08.2009*/\nORYX.I18N.SyntaxChecker.MULT_ERRORS = \"Multiple Errors\";\n\n/** New Language Properties: 08.09.2009*/\nif(!ORYX.I18N.PropertyWindow) ORYX.I18N.PropertyWindow = {};\nORYX.I18N.PropertyWindow.oftenUsed = \"Often used\";\nORYX.I18N.PropertyWindow.moreProps = \"More Properties\";\n\n/** New Language Properties 01.10.2009 */\nif(!ORYX.I18N.SyntaxChecker.BPMN2) ORYX.I18N.SyntaxChecker.BPMN2 = {};\n\nORYX.I18N.SyntaxChecker.BPMN2_DATA_INPUT_WITH_INCOMING_DATA_ASSOCIATION = \"A Data Input must not have any incoming Data Associations.\";\nORYX.I18N.SyntaxChecker.BPMN2_DATA_OUTPUT_WITH_OUTGOING_DATA_ASSOCIATION = \"A Data Output must not have any outgoing Data Associations.\";\nORYX.I18N.SyntaxChecker.BPMN2_EVENT_BASED_TARGET_WITH_TOO_MANY_INCOMING_SEQUENCE_FLOWS = \"Targets of Event-based Gateways may only have one incoming Sequence Flow.\";\n\n/** New Language Properties 02.10.2009 */\nORYX.I18N.SyntaxChecker.BPMN2_EVENT_BASED_WITH_TOO_LESS_OUTGOING_SEQUENCE_FLOWS = \"An Event-based Gateway must have two or more outgoing Sequence Flows.\";\nORYX.I18N.SyntaxChecker.BPMN2_EVENT_BASED_EVENT_TARGET_CONTRADICTION = \"If Message Intermediate Events are used in the configuration, then Receive Tasks must not be used and vice versa.\";\nORYX.I18N.SyntaxChecker.BPMN2_EVENT_BASED_WRONG_TRIGGER = \"Only the following Intermediate Event triggers are valid: Message, Signal, Timer, Conditional and Multiple.\";\nORYX.I18N.SyntaxChecker.BPMN2_EVENT_BASED_WRONG_CONDITION_EXPRESSION = \"The outgoing Sequence Flows of the Event Gateway must not have a condition expression.\";\nORYX.I18N.SyntaxChecker.BPMN2_EVENT_BASED_NOT_INSTANTIATING = \"The Gateway does not meet the conditions to instantiate the process. Please use a start event or an instantiating attribute for the gateway.\";\n\n/** New Language Properties 05.10.2009 */\nORYX.I18N.SyntaxChecker.BPMN2_GATEWAYDIRECTION_MIXED_FAILURE = \"The Gateway must have both multiple incoming and outgoing Sequence Flows.\";\nORYX.I18N.SyntaxChecker.BPMN2_GATEWAYDIRECTION_CONVERGING_FAILURE = \"The Gateway must have multiple incoming but most NOT have multiple outgoing Sequence Flows.\";\nORYX.I18N.SyntaxChecker.BPMN2_GATEWAYDIRECTION_DIVERGING_FAILURE = \"The Gateway must NOT have multiple incoming but must have multiple outgoing Sequence Flows.\";\nORYX.I18N.SyntaxChecker.BPMN2_GATEWAY_WITH_NO_OUTGOING_SEQUENCE_FLOW = \"A Gateway must have a minimum of one outgoing Sequence Flow.\";\nORYX.I18N.SyntaxChecker.BPMN2_RECEIVE_TASK_WITH_ATTACHED_EVENT = \"Receive Tasks used in Event Gateway configurations must not have any attached Intermediate Events.\";\nORYX.I18N.SyntaxChecker.BPMN2_EVENT_SUBPROCESS_BAD_CONNECTION = \"An Event Subprocess must not have any incoming or outgoing Sequence Flow.\";\n\n/** New Language Properties 13.10.2009 */\nORYX.I18N.SyntaxChecker.BPMN_MESSAGE_FLOW_NOT_CONNECTED = \"At least one side of the Message Flow has to be connected.\";\n\n/** New Language Properties 24.11.2009 */\nORYX.I18N.SyntaxChecker.BPMN2_TOO_MANY_INITIATING_MESSAGES = \"A Choreography Activity may only have one initiating message.\";\nORYX.I18N.SyntaxChecker.BPMN_MESSAGE_FLOW_NOT_ALLOWED = \"A Message Flow is not allowed here.\";\n\n/** New Language Properties 27.11.2009 */\nORYX.I18N.SyntaxChecker.BPMN2_EVENT_BASED_WITH_TOO_LESS_INCOMING_SEQUENCE_FLOWS = \"An Event-based Gateway that is not instantiating must have a minimum of one incoming Sequence Flow.\";\nORYX.I18N.SyntaxChecker.BPMN2_TOO_FEW_INITIATING_PARTICIPANTS = \"A Choreography Activity must have one initiating Participant (white).\";\nORYX.I18N.SyntaxChecker.BPMN2_TOO_MANY_INITIATING_PARTICIPANTS = \"A Choreography Acitivity must not have more than one initiating Participant (white).\"\n\nORYX.I18N.SyntaxChecker.COMMUNICATION_AT_LEAST_TWO_PARTICIPANTS = \"The communication must be connected to at least two participants.\";\nORYX.I18N.SyntaxChecker.MESSAGEFLOW_START_MUST_BE_PARTICIPANT = \"The message flow's source must be a participant.\";\nORYX.I18N.SyntaxChecker.MESSAGEFLOW_END_MUST_BE_PARTICIPANT = \"The message flow's target must be a participant.\";\nORYX.I18N.SyntaxChecker.CONV_LINK_CANNOT_CONNECT_CONV_NODES = \"The conversation link must connect a communication or sub conversation node with a participant.\";\n"
  },
  {
    "path": "flowable-ui-web/modeler/editor-app/editor/i18n/translation_signavio_de.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 \n﻿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": "flowable-ui-web/modeler/editor-app/editor/i18n/translation_signavio_en_us.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 \nORYX.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": "flowable-ui-web/modeler/editor-app/editor/oryx.debug.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\n/**\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 (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\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 (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\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 (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\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 (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\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 (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\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 (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\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'Flowable';\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_FLOWABLE_MULTIINSTANCE = \"flowable-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\"subprocess-link\";\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\";\nORYX.CONFIG.TYPE_FLOWABLE_HTTP_REQUEST_METHOD =        \"flowable-http-request-method\";\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_UNDO_RESET =              \"undo.reset\";\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\n//extra events\nORYX.CONFIG.EVENT_EDITOR_INIT_COMPLETED = \"editor.init.completed\";\n\n//actions events that are fired when a button or key was pressed after completing the initial logic.\nORYX.CONFIG.ACTION_DELETE_COMPLETED = 'delete.action.completed';\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 (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\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\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(plugins) {\n\t\n\t    ORYX.availablePlugins.length = 0;\n\t\n\t\t// get plugins.xml content\n\t\tvar resultXml = jQuery.parseXML(plugins); //jquery parser\n\n\t\t// TODO: Describe how properties are handled.\n\t\t// Get the globale Properties\n\t\tvar globalProperties = [];\n\t\tvar preferences = $A(resultXml.getElementsByTagName(\"properties\"));\n\t\tpreferences.each( function(p) {\n\n\t\t\tvar props = $A(p.childNodes);\n\t\t\tprops.each( function(prop) {\n\t\t\t\tvar property = new Hash();\n\n\t\t\t\t// get all attributes from the node and set to global properties\n\t\t\t\tvar attributes = $A(prop.attributes)\n\t\t\t\tattributes.each(function(attr) {\n\t\t\t\t\tproperty.set(attr.nodeName, attr.nodeValue);\n\t\t\t\t});\n\t\t\t\tif(attributes.length > 0) {\n\t\t\t\t\tglobalProperties.push(property)\n\t\t\t\t};\n\t\t\t});\n\t\t});\n\n\n\t\t// TODO Why are we using XML if we don't respect structure anyway?\n\t\t// for each plugin element in the configuration..\n\t\tvar plugin = resultXml.getElementsByTagName(\"plugin\");\n\t\t$A(plugin).each( function(node) {\n\n\t\t\t// get all element's attributes.\n\t\t\t// TODO: What about: var pluginData = $H(node.attributes) !?\n\t\t\tvar pluginData = new Hash();\n\t\t\t$A(node.attributes).each( function(attr){\n\t\t\t\tpluginData.set(attr.nodeName,attr.nodeValue);\n\t\t\t});\n\n\t\t\t// ensure there's a name attribute.\n\t\t\tif(!pluginData.get('name')) {\n\t\t\t\tORYX.Log.error(\"A plugin is not providing a name. Ingnoring this plugin.\");\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// ensure there's a source attribute.\n\t\t\tif(!pluginData.get('source')) {\n\t\t\t\tORYX.Log.error(\"Plugin with name '%0' doesn't provide a source attribute.\", pluginData.get('name'));\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Get all private Properties\n\t\t\tvar propertyNodes = node.getElementsByTagName(\"property\");\n\t\t\tvar properties = [];\n\t\t\t$A(propertyNodes).each(function(prop) {\n\t\t\t\tvar property = new Hash();\n\n\t\t\t\t// Get all Attributes from the Node\n\t\t\t\tvar attributes = $A(prop.attributes)\n\t\t\t\tattributes.each(function(attr){\n\t\t\t\t\tproperty.set(attr.nodeName,attr.nodeValue);\n\t\t\t\t});\n\n\t\t\t\tif(attributes.length > 0) {\n\t\t\t\t\tproperties.push(property)\n\t\t\t\t};\n\n\t\t\t});\n\n\t\t\t// Set all Global-Properties to the Properties\n\t\t\tproperties = properties.concat(globalProperties);\n\n\t\t\t// Set Properties to Plugin-Data\n\t\t\tpluginData.set('properties',properties);\n\n\t\t\t// Get the RequieredNodes\n\t\t\tvar requireNodes = node.getElementsByTagName(\"requires\");\n\t\t\tvar requires;\n\t\t\t$A(requireNodes).each(function(req) {\n\t\t\t\tvar namespace = $A(req.attributes).find(function(attr){ return attr.name == \"namespace\"})\n\t\t\t\tif( namespace && namespace.nodeValue ){\n\t\t\t\t\tif( !requires ){\n\t\t\t\t\t\trequires = {namespaces:[]}\n\t\t\t\t\t}\n\n\t\t\t\t\trequires.namespaces.push(namespace.nodeValue)\n\t\t\t\t}\n\t\t\t});\n\n\t\t\t// Set Requires to the Plugin-Data, if there is one\n\t\t\tif( requires ){\n\t\t\t\tpluginData.set('requires',requires);\n\t\t\t}\n\n\n\t\t\t// Get the RequieredNodes\n\t\t\tvar notUsesInNodes = node.getElementsByTagName(\"notUsesIn\");\n\t\t\tvar notUsesIn;\n\t\t\t$A(notUsesInNodes).each(function(not) {\n\t\t\t\tvar namespace = $A(not.attributes).find(function(attr){ return attr.name == \"namespace\"})\n\t\t\t\tif( namespace && namespace.nodeValue ){\n\t\t\t\t\tif( !notUsesIn ){\n\t\t\t\t\t\tnotUsesIn = {namespaces:[]}\n\t\t\t\t\t}\n\n\t\t\t\t\tnotUsesIn.namespaces.push(namespace.nodeValue)\n\t\t\t\t}\n\t\t\t});\n\n\t\t\t// Set Requires to the Plugin-Data, if there is one\n\t\t\tif( notUsesIn ){\n\t\t\t\tpluginData.set('notUsesIn',notUsesIn);\n\t\t\t}\n\n\n\t\t\tvar url = ORYX.PATH + ORYX.CONFIG.PLUGINS_FOLDER + pluginData.get('source');\n\n\t\t\tORYX.Log.debug(\"Requireing '%0'\", url);\n\n\t\t\t// Add the Script-Tag to the Site\n\t\t\t//Kickstart.require(url);\n\n\t\t\tORYX.Log.info(\"Plugin '%0' successfully loaded.\", pluginData.get('name'));\n\n\t\t\t// Add the Plugin-Data to all available Plugins\n\t\t\tORYX.availablePlugins.push(pluginData);\n\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 (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\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 (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\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 (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\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 (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\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 (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\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 (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\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', '0px');\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 (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\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 (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\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\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\t/*\n\t\tif(Prototype.Browser.WebKit) {\n\t\t\t\n\t\t\tvar req = new XMLHttpRequest;\n\t\t\treq.open(\"GET\", url, false);\n\t\t\treq.overrideMimeType('text/xml');\n\t\t\treq.send(null);\n\t\t\treq.onload = (function() { _loadSVGOnSuccess(req.responseXML); }).bind(this);\n\n\t\t// else just do it.\n\t\t} else\n\t\t*/\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 valid 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// add image path to icon\n\t\tthis._jsonStencil.icon = ORYX.CONFIG.SERVER_HANDLER_ROOT + \"/stencilsetitem/\" + this._jsonStencil.objectId + \"/image\";\n\t\n\t\t// init property packages\n\t\tif(this._jsonStencil.propertyPackages && this._jsonStencil.propertyPackages instanceof Array) {\n\t\t\t\n\t\t\tvar hiddenPropertyPackages = this._jsonStencil.hiddenPropertyPackages;\n\t\t\t\n\t\t\tthis._jsonStencil.propertyPackages.each((function(ppId) {\n\t\t\t\tvar pp = this._propertyPackages.get(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\tvar key = oProp.prefix() + \"-\" + oProp.id();\n \t\t\t\t\t\tthis._properties.set(key,oProp);\n\t\t\t\t\t\t\n\t\t\t\t\t\t// Check if we need to hide this property (ie it is there for display purposes,\n\t\t\t\t\t\t// if the user has filled it in, but it can no longer be edited)\n\t\t\t\t\t\tif (hiddenPropertyPackages.indexOf(oProp.id()) > -1) {\n\t\t\t\t\t\t\toProp.hide();\n\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}).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\tvar key = oProp.prefix() + \"-\" + oProp.id();\n\t\t\t\tthis._properties.set(key, oProp);\n\t\t\t}).bind(this));\n\t\t}\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.get(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 (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\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 (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\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 (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\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 (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\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.get('connectionRules')) {\n\t\t\t\tjsonRules.get('connectionRules').each((function(rules){\n\t\t\t\t\tif (this._isRoleOfOtherNamespace(rules.role)) {\n\t\t\t\t\t\tif (!cr.get(rules.role)) {\n\t\t\t\t\t\t\tcr.set(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.get(namespace + rules.role)) \n\t\t\t\t\t\t\tcr.set(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.get(role).get(from)) \n\t\t\t\t\t\t\tcr.get(role).set(from, toRoles);\n\t\t\t\t\t\telse \n\t\t\t\t\t\t\tcr.get(role).set(from, cr.get(role).get(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.get('cardinalityRules')) {\n\t\t\t\tjsonRules.get('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.get(cardrKey)) {\n\t\t\t\t\t\tcardr.set(cardrKey, {});\n\t\t\t\t\t\tfor (i in rules) {\n\t\t\t\t\t\t\tcardr.get(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.set(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.set(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.get(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.set(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.set(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.get(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.get('containmentRules')) {\n\t\t\t\tjsonRules.get('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.get(conrKey)) {\n\t\t\t\t\t\tconr.set(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.get(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.get(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.get('morphingRules')) {\n\t\t\t\tjsonRules.get('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.get(morphrKey)) {\n\t\t\t\t\t\tmorphr.set(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.get(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.get('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.get('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.get(layoutKey)) {\n\t\t\t\t\t\tlayoutRules.set(layoutKey,{});\n  \t\t\t\t\t}\n\t\t\t\t\tif (rules[\"in\"]){\n\t\t\t\t\t\tlayoutRules.get(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.get(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.get(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.get(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.get(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.get(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.get(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.get(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.get(role)) {\n\t\t\t\tthis._connectionRules.get(role).each(function(cr) {\n\t\t\t\t\tif (edgeRules.get(cr.key)) {\n\t\t\t\t\t\tedgeRules.set(cr.key,edgeRules.get([cr.key]).concat(cr.value));\n\t\t\t\t\t} else {\n\t\t\t\t\t\tedgeRules.set(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 (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\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(baseUrl, data) {\n\t\t\n\t\tthis._extensions = new Hash();\n        \n        this._baseUrl = baseUrl;\n        this._jsonObject = {};\n        \n        this._stencils = new Hash();\n\t\tthis._availableStencils = new Hash();\n       \tthis._init(data);\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.get(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.set(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.set(oStencil.id(),oStencil);\n\t\t\t\t\t\tthis._availableStencils.set(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\tthis._stencils.unset(oStencil.id());\n\t\t\t\t\tthis._availableStencils.unset(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.set(sId, this._stencils.get(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        this._jsonObject = response;\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.set(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.set(oStencil.id(), oStencil);\n\t\t\tthis._availableStencils.set(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 (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\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.get(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.set(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.get(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.get(editorId)) {\n\t\tORYX.Core.StencilSet._rulesByEditorInstance.set(editorId, new ORYX.Core.StencilSet.Rules());\n\t}\n\treturn ORYX.Core.StencilSet._rulesByEditorInstance.get(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, stencilSet, editorId) {\n\t\n\t//store stencil set\n\tORYX.Core.StencilSet._stencilSetsByNamespace.set(stencilSet.namespace(),stencilSet);\n\t\n\t//store stencil set by url\n \tORYX.Core.StencilSet._stencilSetsByUrl.set(url,stencilSet);\n\t\n\tvar namespace = stencilSet.namespace();\n\t\n\t//store which editorInstance loads the stencil set\n\tif(ORYX.Core.StencilSet._StencilSetNSByEditorInstance.get(editorId)) {\n\t\tORYX.Core.StencilSet._StencilSetNSByEditorInstance.get(editorId).push(namespace);\n\t} else {\n\t\tORYX.Core.StencilSet._StencilSetNSByEditorInstance.set(editorId, [namespace]);\n\t}\n\n\t//store the rules for the editor instance\n\tif(ORYX.Core.StencilSet._rulesByEditorInstance.get(editorId)) {\n\t\tORYX.Core.StencilSet._rulesByEditorInstance.get(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.set(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 (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\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 (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\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 (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\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 (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\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.set(key, property.value());\n\t\t\tthis.propertiesChanged.set(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.get(key);\n\t\t\t\tthis.properties.set(key,value);\n\t\t\t\tthis.propertiesChanged.set(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.set(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.get(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.get(key);\n\t\tif(oldValue !== value || force === true) {\n\t\t\tthis.properties.set(key, value);\n\t\t\tthis.propertiesChanged.set(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\tthis.hiddenProperties.unset(key);\n\t\t\treturn;\n\t\t}\n\t\tvar oldValue = this.hiddenProperties.get(key);\n\t\tif (oldValue !== value) {\n\t\t\tthis.hiddenProperties.set(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.get(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    \t\n    \t//upgrade to prototype 1.6/1.7 breaks the jquery extend call. rebuilding the properties here.\n\t\tvar mergedProperties = this.properties.merge(this.hiddenProperties);\n\t\tvar resultProperties = new Hash();\n\t\tmergedProperties.each(function(pair){\n\t\t\tvar key = pair.key;\n\t\t\tvar value = pair.value;\n\n\t\t\t//If complex property, value should be a json object\n\t\t\tif ( this.getStencil().property(key)\n\t\t\t\t\t&& this.getStencil().property(key).type() === ORYX.CONFIG.TYPE_COMPLEX\n\t\t\t\t\t&& Object.prototype.toString.call(value) === \"String\"){\n\n\t\t\t\ttry {value = JSON.parse(value);} catch(error){}\n\n\t\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\t\t\t// Takes \"my_property\" instead of \"oryx-my_property\" as key\n\t\t\tkey = key.replace(/^[\\w_]+-/, \"\");\n\t\t\tresultProperties.set(key,value);\n\t\t\t\n\t\t}.bind(this));\n    \n        var json = {\n            resourceId: this.resourceId,\n            properties: resultProperties.toObject(),\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 (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\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},\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\t\n\tremoveAll: function() {\n\t    var childShapes = this.getChildShapes();\n\t    for (var i = 0; i < childShapes.length; i++) {\n\t        var childObject = childShapes[i];\n\t        this.remove(childObject);\n\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(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                  var target = shape.json.target || shape.json.outgoing[0];\n                  if(target){\n                    properties.push({\n                      prefix: 'raziel',\n                      name: 'target',\n                      value: \"#\"+target.resourceId\n                    });\n                  }\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         }.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 (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 \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\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// 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\tthis.handleEvents({type: ORYX.CONFIG.EVENT_EDITOR_INIT_COMPLETED});\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.set(ORYX.CONFIG.EVENT_MOUSEDOWN,[]);\n\t\tthis.DOMEventListeners.set(ORYX.CONFIG.EVENT_MOUSEUP,[]);\n\t\tthis.DOMEventListeners.set(ORYX.CONFIG.EVENT_MOUSEOVER,[]);\n\t\tthis.DOMEventListeners.set(ORYX.CONFIG.EVENT_MOUSEOUT,[]);\n\t\tthis.DOMEventListeners.set(ORYX.CONFIG.EVENT_SELECTION_CHANGED,[]);\n\t\tthis.DOMEventListeners.set(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\tif (canvasParent.parentNode) {\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\n\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    // 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.get(\"name\"));\n\n\t\t\tif( (!value.get(\"requires\") || !value.get(\"requires\").namespaces \t|| value.get(\"requires\").namespaces.any(function(req){ return loadedStencilSetsNamespaces.indexOf(req) >= 0 }) ) &&\n\t\t\t\t(!value.get(\"notUsesIn\")|| !value.get(\"notUsesIn\").namespaces \t|| !value.get(\"notUsesIn\").namespaces.any(function(req){ return loadedStencilSetsNamespaces.indexOf(req) >= 0 }) )&&\n\t\t\t\t/*only load activated plugins or undefined */\n\t\t\t\t(value.get(\"engaged\") || (value.get(\"engaged\")===undefined)) ){\n\n\t\t\t\ttry {\n\t\t\t\t\tvar className \t= eval(value.get(\"name\")); // wow funcky code here!\n\t\t\t\t\tif( className ){\n\t\t\t\t\t\tvar plugin = new className(facade, value);\n\t\t\t\t\t\tplugin.type\t= value.get(\"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.get(\"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.get(\"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    \tvar 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.unset(eventType);\n\t\t\tthis.DOMEventListeners.set('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.unset(\"disable_\" + eventType);\n \t\t\tthis.DOMEventListeners.set(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.set(eventType,[]);\n\t\t}\n\n\t\tthis.DOMEventListeners.get(eventType).push(callback);\n\t},\n\n\tunregisterOnEvent: function(eventType, callback) {\n\t\tif(this.DOMEventListeners.keys().member(eventType)) {\n\t\t\tthis.DOMEventListeners.set(eventType,this.DOMEventListeners.get(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.get(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 (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\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 = new Hash(dockers);\n\t\t\tthis.edges = new Hash();\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 = new Hash();\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.get(edge.getId())) {\n \t\t\t\t\tthis.changes.set(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.set(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 (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\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.get(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.set(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.get(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.get(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.set(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\t\t\t\t\t\t\t    if(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_FLOWABLE_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.get(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.get(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.get(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.get(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.get(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.get(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_SUB_PROCESS_LINK:\n\t  \t\t\t\t\t\t\t\t \t    if (ref == \"subprocesslink\") {\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\tvar styleAttr = svgElem.getAttributeNodeNS('', 'style');\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\tif (onclickAttr) {\n\t  \t\t\t\t\t\t\t\t\t\t\t\tif (prop && prop.id) {\n\t  \t\t\t\t\t\t\t\t\t\t\t\t\tif (styleAttr) {\n                                                        \tstyleAttr.textContent = \"cursor:pointer;\"\n                                                    \t}\n\t  \t\t\t\t\t\t\t\t\t\t\t\t\tonclickAttr.textContent = \"FLOWABLE.TOOLBAR.ACTIONS.navigateToProcess(\" + prop.id + \");return false;\";\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\tif (styleAttr) {\n                                                        \tstyleAttr.textContent = \"cursor:default;\"\n                                                    \t}\n\t  \t\t\t\t\t\t\t    \t   \t\t\t\tonclickAttr.textContent = \"return false;\";\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}\n\t  \t\t\t\t\t\t\t\t\t\tbreak;\n\t  \t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\tcase ORYX.CONFIG.TYPE_URL:\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 (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\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 (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\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 (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\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 (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\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.set(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 (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\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.get(node.getId())) {\n\t\t\tthis.attachedNodePositionData.set(node.getId(),new Object());\n\t\t\tthis.attachedNodePositionData.get(node.getId()).relativDistanceFromDocker1 = 0;\n\t\t\tthis.attachedNodePositionData.get(node.getId()).node = node;\n\t\t\tthis.attachedNodePositionData.get(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.get(node.getId()).segment.docker1 = this.dockers[i-1];\n\t\t\t\tthis.attachedNodePositionData.get(node.getId()).segment.docker2 = this.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\tvar distanceCenterToLineOne = ORYX.Core.Math.getDistancePointToPoint(nodeCenterPoint, lineP1);\n\t\t\t\tvar distanceCenterToLineTwo = ORYX.Core.Math.getDistancePointToPoint(nodeCenterPoint, lineP2);\n\n\t\t\t\tif (distanceCenterToLineOne < distanceCenterToLineTwo) {\n\t\t\t\t\tthis.attachedNodePositionData.get(node.getId()).relativDistanceFromDocker1 = 0\n\t\t\t\t} else {\n\t\t\t\t\tthis.attachedNodePositionData.get(node.getId()).relativDistanceFromDocker1 = 1;\n\t\t\t\t}\n\t\t\t\tthis.attachedNodePositionData.get(node.getId()).segment.docker1 = this.dockers[i-1];\n\t\t\t\tthis.attachedNodePositionData.get(node.getId()).segment.docker2 = this.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.get(node.getId()).relativDistanceFromDocker1 =\n\t\t\tthis.getLineParameterForPosition(\n\t\t\t\t\tthis.attachedNodePositionData.get(node.getId()).segment.docker1,\n \t\t\t\t\tthis.attachedNodePositionData.get(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.get(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.get(shape.getId())) {\n\t\t\tthis.attachedNodePositionData.unset[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.set(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 = new Hash();\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.set(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.set(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.set(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.get(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.get(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.get(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.set(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.set(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.get(path.id).length > 2) {\n\t\t\t\t\t\t\t\tthis.removeDocker(this._dockersByPath.get(path.id)[1]);\n                            }\n                        }\n                        else {\n                            while (this._dockersByPath.get(path.id).length > 1) {\n                                this.removeDocker(this._dockersByPath.get(path.id)[0]);\n                            }\n                        }\n                        \n                        var dockersByPath = this._dockersByPath.get(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 (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\nif(!ORYX){ var ORYX = {} }\nif(!ORYX.Plugins){ ORYX.Plugins = {} }\n\n/**\n   This abstract plugin class can be used to build plugins on.\n   It provides some more basic functionality like registering events (on*-handlers)...\n   @example\n    ORYX.Plugins.MyPlugin = ORYX.Plugins.AbstractPlugin.extend({\n        construct: function() {\n            // Call super class constructor\n            arguments.callee.$.construct.apply(this, arguments);\n            \n            [...]\n        },\n        [...]\n    });\n   \n   @class ORYX.Plugins.AbstractPlugin\n   @constructor Creates a new instance\n   @author Willi Tscheschner\n*/\nORYX.Plugins.AbstractPlugin = Clazz.extend({\n    /** \n     * The facade which offer editor-specific functionality\n     * @type Facade\n     * @memberOf ORYX.Plugins.AbstractPlugin.prototype\n     */\n\tfacade: null,\n\t\n\tconstruct: function( facade ){\n\t\tthis.facade = facade;\n\t\t\n\t\tthis.facade.registerOnEvent(ORYX.CONFIG.EVENT_LOADED, this.onLoaded.bind(this));\n\t},\n        \n    /**\n       Overwrite to handle load event. TODO: Document params!!!\n       @methodOf ORYX.Plugins.AbstractPlugin.prototype\n    */\n\tonLoaded: function(){},\n\t\n    /**\n       Overwrite to handle selection changed event. TODO: Document params!!!\n       @methodOf ORYX.Plugins.AbstractPlugin.prototype\n    */\n\tonSelectionChanged: function(){},\n\t\n    /**\n       Show overlay on given shape.\n       @methodOf ORYX.Plugins.AbstractPlugin.prototype\n       @example\n       showOverlay(\n           myShape,\n           { stroke: \"green\" },\n           ORYX.Editor.graft(\"http://www.w3.org/2000/svg\", null, ['path', {\n               \"title\": \"Click the element to execute it!\",\n               \"stroke-width\": 2.0,\n               \"stroke\": \"black\",\n               \"d\": \"M0,-5 L5,0 L0,5 Z\",\n               \"line-captions\": \"round\"\n           }])\n       )\n       @param {Oryx.XXX.Shape[]} shapes One shape or array of shapes the overlay should be put on\n       @param {Oryx.XXX.Attributes} attributes some attributes...\n       @param {Oryx.svg.node} svgNode The svg node which should be used as overlay\n       @param {String} [svgNode=\"NW\"] The svg node position where the overlay should be placed\n    */\n\tshowOverlay: function(shapes, attributes, svgNode, svgNodePosition ){\n\t\t\n\t\tif( !(shapes instanceof Array) ){\n\t\t\tshapes = [shapes]\n\t\t}\n\t\t\n\t\t// Define Shapes\n\t\tshapes = shapes.map(function(shape){\n\t\t\tvar el = shape;\n\t\t\tif( typeof shape == \"string\" ){\n\t\t\t\tel = this.facade.getCanvas().getChildShapeByResourceId( shape );\n\t\t\t\tel = el || this.facade.getCanvas().getChildById( shape, true );\n\t\t\t}\n\t\t\treturn el;\n\t\t}.bind(this)).compact();\n\t\t\n\t\t// Define unified id\n\t\tif( !this.overlayID ){\n\t\t\tthis.overlayID = this.type + ORYX.Editor.provideId();\n\t\t}\n\t\t\n\t\tthis.facade.raiseEvent({\n\t\t\ttype\t\t: ORYX.CONFIG.EVENT_OVERLAY_SHOW,\n\t\t\tid\t\t\t: this.overlayID,\n\t\t\tshapes\t\t: shapes,\n\t\t\tattributes \t: attributes,\n\t\t\tnode\t\t: svgNode,\n\t\t\tnodePosition: svgNodePosition || \"NW\"\n\t\t});\n\t\t\n\t},\n\t\n    /**\n       Hide current overlay.\n       @methodOf ORYX.Plugins.AbstractPlugin.prototype\n    */\n\thideOverlay: function(){\n\t\tthis.facade.raiseEvent({\n\t\t\ttype\t: ORYX.CONFIG.EVENT_OVERLAY_HIDE,\n\t\t\tid\t\t: this.overlayID\n\t\t});\t\t\n\t},\n\t\n    /**\n       Does a transformation with the given xslt stylesheet.\n       @methodOf ORYX.Plugins.AbstractPlugin.prototype\n       @param {String} data The data (e.g. eRDF) which should be transformed\n       @param {String} stylesheet URL of a stylesheet which should be used for transforming data.\n    */\n\tdoTransform: function( data, stylesheet ) {\t\t\n\t\t\n\t\tif( !stylesheet || !data ){\n\t\t\treturn \"\"\n\t\t}\n\n        var parser \t\t= new DOMParser();\n        var parsedData \t= parser.parseFromString(data, \"text/xml\");\n\t\tsource=stylesheet;\n\t\tnew Ajax.Request(source, {\n\t\t\tasynchronous: false,\n\t\t\tmethod: 'get',\n\t\t\tonSuccess: function(transport){\n\t\t\t\txsl = transport.responseText\n\t\t\t}.bind(this),\n\t\t\tonFailure: (function(transport){\n\t\t\t\tORYX.Log.error(\"XSL load failed\" + transport);\n\t\t\t}).bind(this)\n\t\t});\n        var xsltProcessor = new XSLTProcessor();\n\t\tvar domParser = new DOMParser();\n\t\tvar xslObject = domParser.parseFromString(xsl, \"text/xml\");\n        xsltProcessor.importStylesheet(xslObject);\n        \n        try {\n        \t\n            var newData \t\t= xsltProcessor.transformToFragment(parsedData, document);\n            var serializedData \t= (new XMLSerializer()).serializeToString(newData);\n            \n           \t/* Firefox 2 to 3 problem?! */\n            serializedData = !serializedData.startsWith(\"<?xml\") ? \"<?xml version=\\\"1.0\\\" encoding=\\\"UTF-8\\\"?>\" + serializedData : serializedData;\n            \n            return serializedData;\n            \n        }catch (error) {\n            return -1;\n        }\n        \n\t},\n\t\n\t/**\n\t * Opens a new window that shows the given XML content.\n\t * @methodOf ORYX.Plugins.AbstractPlugin.prototype\n\t * @param {Object} content The XML content to be shown.\n\t * @example\n\t * openDownloadWindow( \"my.xml\", \"<exampleXML />\" );\n\t */\n\topenXMLWindow: function(content) {\n\t\tvar win = window.open(\n\t\t   'data:application/xml,' + encodeURIComponent(\n\t\t     content\n\t\t   ),\n\t\t   '_blank', \"resizable=yes,width=600,height=600,toolbar=0,scrollbars=yes\"\n\t\t);\n\t},\n\t\n    /**\n     * Opens a download window for downloading the given content.\n     * @methodOf ORYX.Plugins.AbstractPlugin.prototype\n     * @param {String} filename The content's file name\n     * @param {String} content The content to download\n     */\n\topenDownloadWindow: function(filename, content) {\n\t\tvar win = window.open(\"\");\n\t\tif (win != null) {\n\t\t\twin.document.open();\n\t\t\twin.document.write(\"<html><body>\");\n\t\t\tvar submitForm = win.document.createElement(\"form\");\n\t\t\twin.document.body.appendChild(submitForm);\n\t\t\t\n\t\t\tvar createHiddenElement = function(name, value) {\n\t\t\t\tvar newElement = document.createElement(\"input\");\n\t\t\t\tnewElement.name=name;\n\t\t\t\tnewElement.type=\"hidden\";\n\t\t\t\tnewElement.value = value;\n\t\t\t\treturn newElement\n\t\t\t}\n\t\t\t\n\t\t\tsubmitForm.appendChild( createHiddenElement(\"download\", content) );\n\t\t\tsubmitForm.appendChild( createHiddenElement(\"file\", filename) );\n\t\t\t\n\t\t\t\n\t\t\tsubmitForm.method = \"POST\";\n\t\t\twin.document.write(\"</body></html>\");\n\t\t\twin.document.close();\n\t\t\tsubmitForm.action= ORYX.PATH + \"/download\";\n\t\t\tsubmitForm.submit();\n\t\t}\t\t\n\t},\n    \n    /**\n     * Serializes DOM.\n     * @methodOf ORYX.Plugins.AbstractPlugin.prototype\n     * @type {String} Serialized DOM\n     */\n    getSerializedDOM: function(){\n        // Force to set all resource IDs\n        var serializedDOM = DataManager.serializeDOM( this.facade );\n\n        //add namespaces\n        serializedDOM = '<?xml version=\"1.0\" encoding=\"utf-8\"?>' +\n        '<html xmlns=\"http://www.w3.org/1999/xhtml\" ' +\n        'xmlns:b3mn=\"http://b3mn.org/2007/b3mn\" ' +\n        'xmlns:ext=\"http://b3mn.org/2007/ext\" ' +\n        'xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\" ' +\n        'xmlns:atom=\"http://b3mn.org/2007/atom+xhtml\">' +\n        '<head profile=\"http://purl.org/NET/erdf/profile\">' +\n        '<link rel=\"schema.dc\" href=\"http://purl.org/dc/elements/1.1/\" />' +\n        '<link rel=\"schema.dcTerms\" href=\"http://purl.org/dc/terms/ \" />' +\n        '<link rel=\"schema.b3mn\" href=\"http://b3mn.org\" />' +\n        '<link rel=\"schema.oryx\" href=\"http://oryx-editor.org/\" />' +\n        '<link rel=\"schema.raziel\" href=\"http://raziel.org/\" />' +\n        '<base href=\"' +\n        location.href.split(\"?\")[0] +\n        '\" />' +\n        '</head><body>' +\n        serializedDOM +\n        '</body></html>';\n        \n        return serializedDOM;\n    },\n    \n    /**\n     * Sets the editor in read only mode: Edges/ dockers cannot be moved anymore,\n     * shapes cannot be selected anymore.\n     * @methodOf ORYX.Plugins.AbstractPlugin.prototype\n     */\n    enableReadOnlyMode: function(){\n        //Edges cannot be moved anymore\n        this.facade.disableEvent(ORYX.CONFIG.EVENT_MOUSEDOWN);\n        \n        // Stop the user from editing the diagram while the plugin is active\n        this._stopSelectionChange = function(){\n            if(this.facade.getSelection().length > 0) {\n                this.facade.setSelection([]);\n            }\n        };\n        this.facade.registerOnEvent(ORYX.CONFIG.EVENT_SELECTION_CHANGED, this._stopSelectionChange.bind(this));\n    },\n    /**\n     * Disables read only mode, see @see\n     * @methodOf ORYX.Plugins.AbstractPlugin.prototype\n     * @see ORYX.Plugins.AbstractPlugin.prototype.enableReadOnlyMode\n     */\n    disableReadOnlyMode: function(){\n        // Edges can be moved now again\n        this.facade.enableEvent(ORYX.CONFIG.EVENT_MOUSEDOWN);\n        \n        if (this._stopSelectionChange) {\n            this.facade.unregisterOnEvent(ORYX.CONFIG.EVENT_SELECTION_CHANGED, this._stopSelectionChange.bind(this));\n            this._stopSelectionChange = undefined;\n        }\n    },\n    \n    /**\n     * Extracts RDF from DOM.\n     * @methodOf ORYX.Plugins.AbstractPlugin.prototype\n     * @type {String} Extracted RFD. Null if there are transformation errors.\n     */\n    getRDFFromDOM: function(){\n        //convert to RDF\n\t\ttry {\n\t\t\tvar xsl = \"\";\n\t\t\tsource=ORYX.PATH + \"lib/extract-rdf.xsl\";\n\t\t\tnew Ajax.Request(source, {\n\t\t\t\tasynchronous: false,\n\t\t\t\tmethod: 'get',\n\t\t\t\tonSuccess: function(transport){\n\t\t\t\t\txsl = transport.responseText\n\t\t\t\t}.bind(this),\n\t\t\t\tonFailure: (function(transport){\n\t\t\t\t\tORYX.Log.error(\"XSL load failed\" + transport);\n\t\t\t\t}).bind(this)\n\t\t\t});\n\t\t\t\n\t\t\tvar domParser = new DOMParser();\n\t\t\tvar xmlObject = domParser.parseFromString(this.getSerializedDOM(), \"text/xml\");\n\t\t\tvar xslObject = domParser.parseFromString(xsl, \"text/xml\");\n\t\t\tvar xsltProcessor = new XSLTProcessor();\n\t\t\txsltProcessor.importStylesheet(xslObject);\n\t\t\tvar result = xsltProcessor.transformToFragment(xmlObject, document);\n\t\t\t\n\t\t\tvar serializer = new XMLSerializer();\n\t\t\t\n\t\t\treturn serializer.serializeToString(result);\n\t\t} catch(e){\n\t\t\tconsole.log(\"error serializing \" + e);\n\t\t\treturn \"\";\n\t\t}\n\n\t\t\n    },\n    \n    /**\n\t * Checks if a certain stencil set is loaded right now.\n\t * \n\t */\n\tisStencilSetExtensionLoaded: function(stencilSetExtensionNamespace) {\n\t\treturn this.facade.getStencilSets().values().any(\n\t\t\tfunction(ss){ \n\t\t\t\treturn ss.extensions().keys().any(\n\t\t\t\t\tfunction(extensionKey) {\n\t\t\t\t\t\treturn extensionKey == stencilSetExtensionNamespace;\n\t\t\t\t\t}.bind(this)\n\t\t\t\t);\n\t\t\t}.bind(this)\n\t\t);\n\t},\n\t\n\t/**\n\t * Raises an event so that registered layouters does\n\t * have the posiblility to layout the given shapes \n\t * For further reading, have a look into the AbstractLayouter\n\t * class\n\t * @param {Object} shapes\n\t */\n\tdoLayout: function(shapes){\n\t\t// Raises a do layout event\n\t\tif (this.facade.raiseEvent)\n\t\t{\n\t\t\tthis.facade.raiseEvent({\n\t\t\t\ttype\t\t: ORYX.CONFIG.EVENT_LAYOUT,\n\t\t\t\tshapes\t\t: shapes\n\t\t\t});\n\t\t}\n\t\telse\n\t\t{\n\t\t\tthis.facade.handleEvents({\n\t\t\t\ttype\t\t: ORYX.CONFIG.EVENT_LAYOUT,\n\t\t\t\tshapes\t\t: shapes\n\t\t\t});\n\t\t}\n\t},\n\t\n\t\n\t/**\n\t * Does a primitive layouting with the incoming/outgoing \n\t * edges (set the dockers to the right position) and if \n\t * necessary, it will be called the real layouting \n\t * @param {ORYX.Core.Node} node\n\t * @param {Array} edges\n\t */\n\tlayoutEdges : function(node, allEdges, offset){\t\t\n\n\t\tif (!this.facade.isExecutingCommands()){ return }\t\t\n\n\t\tvar Command = ORYX.Core.Command.extend({\n\t\t\tconstruct: function(edges, node, offset, plugin){\n\t\t\t\tthis.edges = edges;\n\t\t\t\tthis.node = node;\n\t\t\t\tthis.plugin = plugin;\n\t\t\t\tthis.offset = offset;\n\t\t\t\t\n\t\t\t\t// Get the new absolute center\n\t\t\t\tvar center = node.absoluteXY();\n\t\t\t\tthis.ulo = {x: center.x - offset.x, y:center.y - offset.y};\n\t\t\t\t\n\t\t\t\t\n\t\t\t},\n\t\t\texecute: function(){\n\t\t\t\t\n\t\t\t\tif (this.changes){\n\t\t\t\t\tthis.executeAgain();\n\t\t\t\t\treturn;\n\t\t\t\t} else {\n\t\t\t\t\tthis.changes = [];\n\t\t\t\t\tthis.edges.each(function(edge){\n\t\t\t\t\t\tthis.changes.push({\n\t\t\t\t\t\t\tedge: edge,\n\t\t\t\t\t\t\toldDockerPositions: edge.dockers.map(function(r){ return r.bounds.center() })\n\t\t\t\t\t\t})\n\t\t\t\t\t}.bind(this));\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t// Find all edges, which are related to the node and\n\t\t\t\t// have more than two dockers\n\t\t\t\tthis.edges\n\t\t\t\t\t// Find all edges with more than two dockers\n\t\t\t\t\t.findAll(function(r){ return r.dockers.length > 2 }.bind(this))\n\t\t\t\t\t// For every edge, check second and one before last docker\n\t\t\t\t\t// if there are horizontal/vertical on the same level\n\t\t\t\t\t// and if so, align the the bounds \n\t\t\t\t\t.each(function(edge){\n\t\t\t\t\t\tif (edge.dockers.first().getDockedShape() === this.node){\n\t\t\t\t\t\t\tvar second = edge.dockers[1];\n\t\t\t\t\t\t\tif (this.align(second.bounds, edge.dockers.first())){ second.update(); }\n\t\t\t\t\t\t} else if (edge.dockers.last().getDockedShape() === this.node) {\n\t\t\t\t\t\t\tvar beforeLast = edge.dockers[edge.dockers.length-2];\n\t\t\t\t\t\t\tif (this.align(beforeLast.bounds, edge.dockers.last())){ beforeLast.update(); }\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t}\n\t\t\t\t\t\tedge._update(true);\n\t\t\t\t\t\tedge.removeUnusedDockers();\n\t\t\t\t\t\tif (this.isBendPointIncluded(edge)){\n\t\t\t\t\t\t\tthis.plugin.doLayout(edge);\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t}.bind(this));\n\t\t\t\t\n\t\t\t\t\n\t\t\t\t// Find all edges, which have only to dockers \n\t\t\t\t// and is located horizontal/vertical.\n\t\t\t\t// Do layout with those edges\n\t\t\t\tthis.edges\n\t\t\t\t\t// Find all edges with exactly two dockers\n\t\t\t\t\t.each(function(edge){\n\t\t\t\t\t\tif (edge.dockers.length == 2){\n\t\t\t\t\t\t\tvar p1 = edge.dockers.first().getAbsoluteReferencePoint() || edge.dockers.first().bounds.center();\n\t\t\t\t\t\t\tvar p2 = edge.dockers.last().getAbsoluteReferencePoint() || edge.dockers.first().bounds.center();\n\t\t\t\t\t\t\t// Find all horizontal/vertical edges\n\t\t\t\t\t\t\tif (Math.abs(-Math.abs(p1.x - p2.x) + Math.abs(this.offset.x)) < 2 || Math.abs(-Math.abs(p1.y - p2.y) + Math.abs(this.offset.y)) < 2){\n\t\t\t\t\t\t\t\tthis.plugin.doLayout(edge);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}.bind(this));\n\t\t\n\t\t\t\tthis.edges.each(function(edge, i){\n\t\t\t\t\tthis.changes[i].dockerPositions = edge.dockers.map(function(r){ return r.bounds.center() });\n\t\t\t\t}.bind(this));\n\t\t\t\t\n\t\t\t},\n\t\t\t/**\n\t\t\t * Align the bounds if the center is \n\t\t\t * the same than the old center\n\t\t\t * @params {Object} bounds\n\t\t\t * @params {Object} bounds2\n\t\t\t */\n\t\t\talign: function(bounds, refDocker){\n\t\t\t\t\n\t\t\t\tvar abRef = refDocker.getAbsoluteReferencePoint() || refDocker.bounds.center();\n\t\t\t\t\n\t\t\t\tvar xdif = bounds.center().x-abRef.x;\n\t\t\t\tvar ydif = bounds.center().y-abRef.y;\n\t\t\t\tif (Math.abs(-Math.abs(xdif) + Math.abs(this.offset.x)) < 3 && this.offset.xs === undefined){\n\t\t\t\t\tbounds.moveBy({x:-xdif, y:0})\n\t\t\t\t}\n\t\t\t\tif (Math.abs(-Math.abs(ydif) + Math.abs(this.offset.y)) < 3 && this.offset.ys === undefined){\n\t\t\t\t\tbounds.moveBy({y:-ydif, x:0})\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tif (this.offset.xs !== undefined || this.offset.ys !== undefined){\n\t\t\t\t\tvar absPXY = refDocker.getDockedShape().absoluteXY();\n\t\t\t\t\txdif = bounds.center().x-(absPXY.x+((abRef.x-absPXY.x)/this.offset.xs));\n\t\t\t\t\tydif = bounds.center().y-(absPXY.y+((abRef.y-absPXY.y)/this.offset.ys));\n\t\t\t\t\t\n\t\t\t\t\tif (Math.abs(-Math.abs(xdif) + Math.abs(this.offset.x)) < 3){\n\t\t\t\t\t\tbounds.moveBy({x:-(bounds.center().x-abRef.x), y:0})\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\tif (Math.abs(-Math.abs(ydif) + Math.abs(this.offset.y)) < 3){\n\t\t\t\t\t\tbounds.moveBy({y:-(bounds.center().y-abRef.y), x:0})\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\t\n\t\t\t/**\t\t\t\t\t\t\n\t\t\t * Returns a TRUE if there are bend point which overlay the shape\n\t\t\t */\n\t\t\tisBendPointIncluded: function(edge){\n\t\t\t\t// Get absolute bounds\n\t\t\t\tvar ab = edge.dockers.first().getDockedShape();\n\t\t\t\tvar bb = edge.dockers.last().getDockedShape();\n\t\t\t\t\n\t\t\t\tif (ab) {\n\t\t\t\t\tab = ab.absoluteBounds();\n\t\t\t\t\tab.widen(5);\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tif (bb) {\n\t\t\t\t\tbb = bb.absoluteBounds();\n\t\t\t\t\tbb.widen(20); // Wide with 20 because of the arrow from the edge\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\treturn edge.dockers\n\t\t\t\t\t\t.any(function(docker, i){ \n\t\t\t\t\t\t\tvar c = docker.bounds.center();\n\t\t\t\t\t\t\t\t\t// Dont count first and last\n\t\t\t\t\t\t\treturn \ti != 0 && i != edge.dockers.length-1 && \n\t\t\t\t\t\t\t\t\t// Check if the point is included to the absolute bounds\n\t\t\t\t\t\t\t\t\t((ab && ab.isIncluded(c)) || (bb && bb.isIncluded(c)))\n\t\t\t\t\t\t})\n\t\t\t},\n\t\t\t\n\t\t\tremoveAllDocker: function(edge){\n\t\t\t\tedge.dockers.slice(1, edge.dockers.length-1).each(function(docker){\n\t\t\t\t\tedge.removeDocker(docker);\n\t\t\t\t})\n\t\t\t},\n\t\t\texecuteAgain: function(){\n\t\t\t\tthis.changes.each(function(change){\n\t\t\t\t\t// Reset the dockers\n\t\t\t\t\tthis.removeAllDocker(change.edge);\n\t\t\t\t\tchange.dockerPositions.each(function(pos, i){\t\n\t\t\t\t\t\tif (i==0||i==change.dockerPositions.length-1){ return }\t\t\t\t\t\n\t\t\t\t\t\tvar docker = change.edge.createDocker(undefined, pos);\n\t\t\t\t\t\tdocker.bounds.centerMoveTo(pos);\n\t\t\t\t\t\tdocker.update();\n\t\t\t\t\t}.bind(this));\n\t\t\t\t\tchange.edge._update(true);\n\t\t\t\t}.bind(this));\n\t\t\t},\n\t\t\trollback: function(){\t\t\t\t\t\n\t\t\t\tthis.changes.each(function(change){\n\t\t\t\t\t// Reset the dockers\n\t\t\t\t\tthis.removeAllDocker(change.edge);\n\t\t\t\t\tchange.oldDockerPositions.each(function(pos, i){\t\n\t\t\t\t\t\tif (i==0||i==change.oldDockerPositions.length-1){ return }\t\t\t\t\t\n\t\t\t\t\t\tvar docker = change.edge.createDocker(undefined, pos);\n\t\t\t\t\t\tdocker.bounds.centerMoveTo(pos);\n\t\t\t\t\t\tdocker.update();\n\t\t\t\t\t}.bind(this));\n\t\t\t\t\tchange.edge._update(true);\n\t\t\t\t}.bind(this));\n\t\t\t}\n\t\t});\n\t\t\n\t\tthis.facade.executeCommands([new Command(allEdges, node, offset, this)]);\n\n\t}\n});/**\n * Copyright (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\nif(!ORYX){ var ORYX = {} }\nif(!ORYX.Plugins){ ORYX.Plugins = {} }\n\n/**\n   This abstract plugin implements the core behaviour of layout\n   \n   @class ORYX.Plugins.AbstractLayouter\n   @constructor Creates a new instance\n   @author Willi Tscheschner\n*/\nORYX.Plugins.AbstractLayouter = ORYX.Plugins.AbstractPlugin.extend({\n\t\n\t/**\n\t * 'layouted' defined all types of shapes which will be layouted. \n\t * It can be one value or an array of values. The value\n\t * can be a Stencil ID (as String) or an class type of either \n\t * a ORYX.Core.Node or ORYX.Core.Edge\n     * @type Array|String|Object\n     * @memberOf ORYX.Plugins.AbstractLayouter.prototype\n\t */\n\tlayouted : [],\n\t\n\t/**\n\t * Constructor\n\t * @param {Object} facade\n\t * @memberOf ORYX.Plugins.AbstractLayouter.prototype\n\t */\n\tconstruct: function( facade ){\n\t\targuments.callee.$.construct.apply(this, arguments);\n\t\t\t\n\t\tthis.facade.registerOnEvent(ORYX.CONFIG.EVENT_LAYOUT, this._initLayout.bind(this));\n\t},\n\t\n\t/**\n\t * Proofs if this shape should be layouted or not\n\t * @param {Object} shape\n     * @memberOf ORYX.Plugins.AbstractLayouter.prototype\n\t */\n\tisIncludedInLayout: function(shape){\n\t\tif (!(this.layouted instanceof Array)){\n\t\t\tthis.layouted = [this.layouted].compact();\n\t\t}\n\t\t\n\t\t// If there are no elements\n\t\tif (this.layouted.length <= 0) {\n\t\t\t// Return TRUE\n\t\t\treturn true;\n\t\t}\n\t\t\n\t\t// Return TRUE if there is any correlation between \n\t\t// the 'layouted' attribute and the shape themselve.\n\t\treturn this.layouted.any(function(s){\n\t\t\tif (typeof s == \"string\") {\n\t\t\t\treturn shape.getStencil().id().include(s);\n\t\t\t} else {\n\t\t\t\treturn shape instanceof s;\n\t\t\t}\n\t\t})\n\t},\n\t\n\t/**\n\t * Callback to start the layouting\n\t * @param {Object} event Layout event\n\t * @param {Object} shapes Given shapes\n     * @memberOf ORYX.Plugins.AbstractLayouter.prototype\n\t */\n\t_initLayout: function(event){\n\t\t\n\t\t// Get the shapes\n\t\tvar shapes = [event.shapes].flatten().compact();\n\t\t\n\t\t// Find all shapes which should be layouted\n\t\tvar toLayout = shapes.findAll(function(shape){\n\t\t\treturn this.isIncludedInLayout(shape) \n\t\t}.bind(this))\n\t\t\n\t\t// If there are shapes left \n\t\tif (toLayout.length > 0){\n\t\t\t// Do layout\n\t\t\tthis.layout(toLayout);\n\t\t}\n\t},\n\t\n\t/**\n\t * Implementation of layouting a set on shapes\n\t * @param {Object} shapes Given shapes\n     * @memberOf ORYX.Plugins.AbstractLayouter.prototype\n\t */\n\tlayout: function(shapes){\n\t\tthrow new Error(\"Layouter has to implement the layout function.\")\n\t}\n});/**\n * Copyright (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\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        if (selection.length > 0) {\n\t\t\t//only update the command stack if something was performed...\n\t        var clipboard = new ORYX.Plugins.Edit.ClipBoard();\n\t        clipboard.refresh(selection, this.getAllShapesToConsider(selection));\n\t        \n\t\t\tvar command = new ORYX.Plugins.Edit.DeleteCommand(clipboard , this.facade);\n\t                                       \n\t\t\tthis.facade.executeCommands([command]);\n\t\t}\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\t\tthis.facade.handleEvents({type: ORYX.CONFIG.ACTION_DELETE_COMPLETED});\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 (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\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.get('properties').each( function(property) {\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 (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 \nif(!Signavio){ var Signavio = {} };\n\tif (!Signavio.Core) { Signavio.Core = {} };\n\tSignavio.Core.Version = \"1.0\";\n\t\t\t/**\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\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 (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\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 (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 \nif (!ORYX.Plugins) {\n    ORYX.Plugins = new Object();\n}\n\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 = $$(\"#canvasSection .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 (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\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 (FLOWABLE.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.get(propId);\n\t\tthis.oldValueText = shape.properties.get(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    if (searchShape.getParentShape().getStencil().idWithoutNs() === 'BPMNDiagram' || searchShape.getParentShape().getStencil().idWithoutNs() === 'CMMNDiagram') \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 (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\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 (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\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 (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\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 (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\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 (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 \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 (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\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 (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\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 (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\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 (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\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 (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\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 (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\nif(!ORYX.Plugins) { ORYX.Plugins = {} }\nif(!ORYX.Plugins.Layouter) { ORYX.Plugins.Layouter = {} }\n\nnew function(){\n\t\n\t/**\n\t * Edge layouter is an implementation to layout an edge\n\t * @class ORYX.Plugins.Layouter.EdgeLayouter\n\t * @author Willi Tscheschner\n\t */\n\tORYX.Plugins.Layouter.EdgeLayouter = ORYX.Plugins.AbstractLayouter.extend({\n\t\t\n\t\t/**\n\t\t * Layout only Edges\n\t\t */\n\t\tlayouted : [\t\"http://b3mn.org/stencilset/bpmn1.1#SequenceFlow\", \n\t\t\t\t\t\t\"http://b3mn.org/stencilset/bpmn1.1#MessageFlow\",\n\t\t\t\t\t\t\"http://b3mn.org/stencilset/timjpdl3#SequenceFlow\", \n\t\t\t\t\t\t\"http://b3mn.org/stencilset/jbpm4#SequenceFlow\", \n\t\t\t\t\t\t\"http://b3mn.org/stencilset/bpmn2.0#MessageFlow\",\n\t\t\t\t\t\t\"http://b3mn.org/stencilset/bpmn2.0#SequenceFlow\", \n\t\t\t\t\t\t\"http://b3mn.org/stencilset/bpmn2.0choreography#MessageFlow\",\n\t\t\t\t\t\t\"http://b3mn.org/stencilset/bpmn2.0choreography#SequenceFlow\", \n\t\t\t\t\t\t\"http://b3mn.org/stencilset/bpmn2.0conversation#ConversationLink\",\n\t\t\t\t\t\t\"http://b3mn.org/stencilset/epc#ControlFlow\",\n\t\t\t\t\t\t\"http://www.signavio.com/stencilsets/processmap#ProcessLink\",\n\t\t\t\t\t\t\"http://www.signavio.com/stencilsets/organigram#connection\"],\n\t\t\n\t\t/**\n\t\t * Layout a set on edges\n\t\t * @param {Object} edges\n\t\t */\n\t\tlayout: function(edges){\n\t\t\tedges.each(function(edge){\n\t\t\t\tthis.doLayout(edge)\n\t\t\t}.bind(this))\n\t\t},\n\t\t\n\t\t/**\n\t\t * Layout one edge\n\t\t * @param {Object} edge\n\t\t */\n\t\tdoLayout: function(edge){\n\t\t\t// Get from and to node\n\t\t\tvar from \t= edge.getIncomingNodes()[0]; \n\t\t\tvar to \t\t= edge.getOutgoingNodes()[0];\n\t\t\t\n\t\t\t// Return if one is null\n\t\t\tif (!from || !to) { return }\n\t\t\t\n\t\t\tvar positions = this.getPositions(from, to, edge);\n\t\t\n\t\t\tif (positions.length > 0){\n\t\t\t\tthis.setDockers(edge, positions[0].a, positions[0].b);\n\t\t\t}\n\t\t\t\t\n\t\t},\n\t\t\n\t\t/**\n\t\t * Returns a set on positions which are not containt either \n\t\t * in the bounds in from or to.\n\t\t * @param {Object} from Shape where the edge is come from\n\t\t * @param {Object} to Shape where the edge is leading to\n\t\t * @param {Object} edge Edge between from and to\n\t\t */\n\t\tgetPositions : function(from, to, edge){\n\t\t\t\n\t\t\t// Get absolute bounds\n\t\t\tvar ab = from.absoluteBounds();\n\t\t\tvar bb = to.absoluteBounds();\n\t\t\t\n\t\t\t// Get center from and to\n\t\t\tvar a = ab.center();\n\t\t\tvar b = bb.center();\n\t\t\t\n\t\t\tvar am = ab.midPoint();\n\t\t\tvar bm = bb.midPoint();\n\t\t\n\t\t\t// Get first and last reference point\n\t\t\tvar first = Object.clone(edge.dockers.first().referencePoint);\n\t\t\tvar last = Object.clone(edge.dockers.last().referencePoint);\n\t\t\t// Get the absolute one\n\t\t\tvar aFirst = edge.dockers.first().getAbsoluteReferencePoint();\n\t\t\tvar aLast = edge.dockers.last().getAbsoluteReferencePoint(); \n\t\t\t\n\t\t\t// IF ------>\n\t\t\t// or  |\n\t\t\t//     V\n\t\t\t// Do nothing\n\t\t\tif (Math.abs(aFirst.x-aLast.x) < 1 || Math.abs(aFirst.y-aLast.y) < 1) {\n\t\t\t\treturn []\n\t\t\t}\n\t\t\t\n\t\t\t// Calc center position, between a and b\n\t\t\t// depending on there weight\n\t\t\tvar m = {}\n\t\t\tm.x = a.x < b.x ? \n\t\t\t\t\t(((b.x - bb.width()/2) - (a.x + ab.width()/2))/2) + (a.x + ab.width()/2): \n\t\t\t\t\t(((a.x - ab.width()/2) - (b.x + bb.width()/2))/2) + (b.x + bb.width()/2);\n\n\t\t\tm.y = a.y < b.y ? \n\t\t\t\t\t(((b.y - bb.height()/2) - (a.y + ab.height()/2))/2) + (a.y + ab.height()/2): \n\t\t\t\t\t(((a.y - ab.height()/2) - (b.y + bb.height()/2))/2) + (b.y + bb.height()/2);\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\n\t\t\t// Enlarge both bounds with 10\n\t\t\tab.widen(5); // Wide the from less than \n\t\t\tbb.widen(20);// the to because of the arrow from the edge\n\t\t\t\t\t\t\t\t\n\t\t\tvar positions = [];\n\t\t\tvar off = this.getOffset.bind(this);\n\t\t\t\n\t\t\t// Checks ----+\n\t\t\t//            |\n\t\t\t//            V\n\t\t\tif (!ab.isIncluded(b.x, a.y)&&!bb.isIncluded(b.x, a.y)) {\n\t\t\t\tpositions.push({\n\t\t\t\t\ta : {x:b.x+off(last,bm,\"x\"),y:a.y+off(first,am,\"y\")},\n\t\t\t\t\tz : this.getWeight(from, a.x < b.x ? \"r\" : \"l\", to, a.y < b.y ? \"t\" : \"b\", edge)\n\t\t\t\t});\n\t\t\t}\n\t\t\t\t\t\t\n\t\t\t// Checks | \n\t\t\t//        +--->\n\t\t\tif (!ab.isIncluded(a.x, b.y)&&!bb.isIncluded(a.x, b.y)) {\n\t\t\t\tpositions.push({\n\t\t\t\t\ta : {x:a.x+off(first,am,\"x\"),y:b.y+off(last,bm,\"y\")},\n\t\t\t\t\tz : this.getWeight(from, a.y < b.y ? \"b\" : \"t\", to, a.x < b.x ? \"l\" : \"r\", edge)\n\t\t\t\t});\n\t\t\t}\n\t\t\t\t\t\t\n\t\t\t// Checks  --+\n\t\t\t//           |\n\t\t\t//           +--->\n\t\t\tif (!ab.isIncluded(m.x, a.y)&&!bb.isIncluded(m.x, b.y)) {\n\t\t\t\tpositions.push({\n\t\t\t\t\ta : {x:m.x,y:a.y+off(first,am,\"y\")},\n\t\t\t\t\tb : {x:m.x,y:b.y+off(last,bm,\"y\")},\n\t\t\t\t\tz : this.getWeight(from, \"r\", to, \"l\", edge, a.x > b.x)\n\t\t\t\t});\n\t\t\t}\n\t\t\t\n\t\t\t// Checks | \n\t\t\t//        +---+\n\t\t\t//            |\n\t\t\t//            V\n\t\t\tif (!ab.isIncluded(a.x, m.y)&&!bb.isIncluded(b.x, m.y)) {\n\t\t\t\tpositions.push({\n\t\t\t\t\ta : {x:a.x+off(first,am,\"x\"),y:m.y},\n\t\t\t\t\tb : {x:b.x+off(last,bm,\"x\"),y:m.y},\n\t\t\t\t\tz : this.getWeight(from, \"b\", to, \"t\", edge, a.y > b.y)\n\t\t\t\t});\n\t\t\t}\t\n\t\t\t\n\t\t\t// Sort DESC of weights\n\t\t\treturn positions.sort(function(a,b){ return a.z < b.z ? 1 : (a.z == b.z ? -1 : -1)});\n\t\t},\n\t\t\n\t\t/**\n\t\t * Returns a offset for the pos to the center of the bounds\n\t\t * \n\t\t * @param {Object} val\n\t\t * @param {Object} pos2\n\t\t * @param {String} dir Direction x|y\n\t\t */\n\t\tgetOffset: function(pos, pos2, dir){\n\t\t\treturn pos[dir] - pos2[dir];\n\t\t},\n\t\t\n\t\t/**\n\t\t * Returns a value which shows the weight for this configuration\n\t\t * \n\t\t * @param {Object} from Shape which is coming from\n\t\t * @param {String} d1 Direction where is goes\n\t\t * @param {Object} to Shape which goes to\n\t\t * @param {String} d2 Direction where it comes to\n\t\t * @param {Object} edge Edge between from and to\n\t\t * @param {Boolean} reverse Reverse the direction (e.g. \"r\" -> \"l\")\n\t\t */\n\t\tgetWeight: function(from, d1, to, d2, edge, reverse){\n\t\t\t\n\t\t\td1 = (d1||\"\").toLowerCase();\n\t\t\td2 = (d2||\"\").toLowerCase();\n\t\t\t\n\t\t\tif (![\"t\",\"r\",\"b\",\"l\"].include(d1)){ d1 = \"r\"}\n\t\t\tif (![\"t\",\"r\",\"b\",\"l\"].include(d2)){ d1 = \"l\"}\n\t\t\t\n\t\t\t// If reverse is set\n\t\t\tif (reverse) {\n\t\t\t\t// Reverse d1 and d2\n\t\t\t\td1 = d1==\"t\"?\"b\":(d1==\"r\"?\"l\":(d1==\"b\"?\"t\":(d1==\"l\"?\"r\":\"r\")))\n\t\t\t\td2 = d2==\"t\"?\"b\":(d2==\"r\"?\"l\":(d2==\"b\"?\"t\":(d2==\"l\"?\"r\":\"r\")))\n\t\t\t}\n\t\t\t\n\t\t\t\t\t\n\t\t\tvar weight = 0;\n\t\t\t// Get rules for from \"out\" and to \"in\"\n\t\t\tvar dr1 = this.facade.getRules().getLayoutingRules(from, edge)[\"out\"];\n\t\t\tvar dr2 = this.facade.getRules().getLayoutingRules(to, edge)[\"in\"];\n\n\t\t\tvar fromWeight = dr1[d1];\n\t\t\tvar toWeight = dr2[d2];\n\n\n\t\t\t/**\n\t\t\t * Return a true if the center 1 is in the same direction than center 2\n\t\t\t * @param {Object} direction\n\t\t\t * @param {Object} center1\n\t\t\t * @param {Object} center2\n\t\t\t */\n\t\t\tvar sameDirection = function(direction, center1, center2){\n\t\t\t\tswitch(direction){\n\t\t\t\t\tcase \"t\": return Math.abs(center1.x - center2.x) < 2 && center1.y < center2.y\n\t\t\t\t\tcase \"r\": return center1.x > center2.x && Math.abs(center1.y - center2.y) < 2\n\t\t\t\t\tcase \"b\": return Math.abs(center1.x - center2.x) < 2 && center1.y > center2.y\n\t\t\t\t\tcase \"l\": return center1.x < center2.x && Math.abs(center1.y - center2.y) < 2\n\t\t\t\t\tdefault: return false;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Check if there are same incoming edges from 'from'\n\t\t\tvar sameIncomingFrom = from\n\t\t\t\t\t\t\t\t.getIncomingShapes()\n\t\t\t\t\t\t\t\t.findAll(function(a){ return a instanceof ORYX.Core.Edge})\n\t\t\t\t\t\t\t\t.any(function(e){ \n\t\t\t\t\t\t\t\t\treturn sameDirection(d1, e.dockers[e.dockers.length-2].bounds.center(), e.dockers.last().bounds.center());\n\t\t\t\t\t\t\t\t});\n\n\t\t\t// Check if there are same outgoing edges from 'to'\n\t\t\tvar sameOutgoingTo = to\n\t\t\t\t\t\t\t\t.getOutgoingShapes()\n\t\t\t\t\t\t\t\t.findAll(function(a){ return a instanceof ORYX.Core.Edge})\n\t\t\t\t\t\t\t\t.any(function(e){ \n\t\t\t\t\t\t\t\t\treturn sameDirection(d2, e.dockers[1].bounds.center(), e.dockers.first().bounds.center());\n\t\t\t\t\t\t\t\t});\n\t\t\t\n\t\t\t// If there are equivalent edges, set 0\n\t\t\t//fromWeight = sameIncomingFrom ? 0 : fromWeight;\n\t\t\t//toWeight = sameOutgoingTo ? 0 : toWeight;\n\t\t\t\n\t\t\t// Get the sum of \"out\" and the direction plus \"in\" and the direction \t\t\t\t\t\t\n\t\t\treturn (sameIncomingFrom||sameOutgoingTo?0:fromWeight+toWeight);\n\t\t},\n\t\t\n\t\t/**\n\t\t * Removes all current dockers from the node \n\t\t * (except the start and end) and adds two new\n\t\t * dockers, on the position a and b.\n\t\t * @param {Object} edge\n\t\t * @param {Object} a\n\t\t * @param {Object} b\n\t\t */\n\t\tsetDockers: function(edge, a, b){\n\t\t\tif (!edge){ return }\n\t\t\t\n\t\t\t// Remove all dockers (implicit,\n\t\t\t// start and end dockers will not removed)\n\t\t\tedge.dockers.each(function(r){\n\t\t\t\tedge.removeDocker(r);\n\t\t\t});\n\t\t\t\n\t\t\t// For a and b (if exists), create\n\t\t\t// a new docker and set position\n\t\t\t[a, b].compact().each(function(pos){\n\t\t\t\tvar docker = edge.createDocker(undefined, pos);\n\t\t\t\tdocker.bounds.centerMoveTo(pos);\n\t\t\t});\n\t\t\t\n\t\t\t// Update all dockers from the edge\n\t\t\tedge.dockers.each(function(docker){\n\t\t\t\tdocker.update()\n\t\t\t})\n\t\t\t\n\t\t\t// Update edge\n\t\t\t//edge.refresh();\n\t\t\tedge._update(true);\n\t\t\t\n\t\t}\n\t});\n\t\n\t\n}()\n/**\n * Copyright (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\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 = new Hash();\n                allLanes.each(function(lane){\n                \thashedPositions.set(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                        var caption = lanes.first().properties.get(\"oryx-name\").trim().length > 0;\n\t\t\t\t\t\tlanes.first().setProperty(\"oryx-showcaption\", caption);\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                        var poolHashedPositions = this.hashedPositions[pool.id];\n\t\t\t\t\t\tif ( poolHashedPositions && poolHashedPositions.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 = new Hash();\n                                allLanes.each(function(lane){\n\t\t\t\t\t\t\t\t\thp2.set(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": "flowable-ui-web/modeler/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=\"Flowable\";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_FLOWABLE_MULTIINSTANCE=\"flowable-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=\"subprocess-link\";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.TYPE_FLOWABLE_HTTP_REQUEST_METHOD=\"flowable-http-request-method\";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_UNDO_RESET=\"undo.reset\";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.EVENT_EDITOR_INIT_COMPLETED=\"editor.init.completed\";ORYX.CONFIG.ACTION_DELETE_COMPLETED=\"delete.action.completed\";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(b){ORYX.availablePlugins.length=0;var e=jQuery.parseXML(b);var a=[];var c=$A(e.getElementsByTagName(\"properties\"));c.each(function(g){var f=$A(g.childNodes);f.each(function(l){var k=new Hash();var h=$A(l.attributes);h.each(function(m){k.set(m.nodeName,m.nodeValue)});if(h.length>0){a.push(k)}})});var d=e.getElementsByTagName(\"plugin\");$A(d).each(function(h){var o=new Hash();$A(h.attributes).each(function(q){o.set(q.nodeName,q.nodeValue)});if(!o.get(\"name\")){ORYX.Log.error(\"A plugin is not providing a name. Ingnoring this plugin.\");return}if(!o.get(\"source\")){ORYX.Log.error(\"Plugin with name '%0' doesn't provide a source attribute.\",o.get(\"name\"));return}var m=h.getElementsByTagName(\"property\");var n=[];$A(m).each(function(s){var r=new Hash();var q=$A(s.attributes);q.each(function(t){r.set(t.nodeName,t.nodeValue)});if(q.length>0){n.push(r)}});n=n.concat(a);o.set(\"properties\",n);var k=h.getElementsByTagName(\"requires\");var p;$A(k).each(function(r){var q=$A(r.attributes).find(function(s){return s.name==\"namespace\"});if(q&&q.nodeValue){if(!p){p={namespaces:[]}}p.namespaces.push(q.nodeValue)}});if(p){o.set(\"requires\",p)}var l=h.getElementsByTagName(\"notUsesIn\");var g;$A(l).each(function(r){var q=$A(r.attributes).find(function(s){return s.name==\"namespace\"});if(q&&q.nodeValue){if(!g){g={namespaces:[]}}g.namespaces.push(q.nodeValue)}});if(g){o.set(\"notUsesIn\",g)}var f=ORYX.PATH+ORYX.CONFIG.PLUGINS_FOLDER+o.get(\"source\");ORYX.Log.debug(\"Requireing '%0'\",f);ORYX.Log.info(\"Plugin '%0' successfully loaded.\",o.get(\"name\"));ORYX.availablePlugins.push(o)})},_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\",\"0px\");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 valid SVG document.\"}}else{new Ajax.Request(c,{asynchronous:false,method:\"get\",onSuccess:this._loadSVGOnSuccess.bind(this),onFailure:this._loadSVGOnFailure.bind(this)})}},postProcessProperties:function(){this._jsonStencil.icon=ORYX.CONFIG.SERVER_HANDLER_ROOT+\"/stencilsetitem/\"+this._jsonStencil.objectId+\"/image\";if(this._jsonStencil.propertyPackages&&this._jsonStencil.propertyPackages instanceof Array){var a=this._jsonStencil.hiddenPropertyPackages;this._jsonStencil.propertyPackages.each((function(c){var b=this._propertyPackages.get(c);if(b){b.each((function(f){var d=new ORYX.Core.StencilSet.Property(f,this._namespace,this);var e=d.prefix()+\"-\"+d.id();this._properties.set(e,d);if(a.indexOf(d.id())>-1){d.hide()}}).bind(this))}}).bind(this))}if(this._jsonStencil.properties&&this._jsonStencil.properties instanceof Array){this._jsonStencil.properties.each((function(d){var b=new ORYX.Core.StencilSet.Property(d,this._namespace,this);var c=b.prefix()+\"-\"+b.id();this._properties.set(c,b)}).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.get(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.get(\"connectionRules\")){m.get(\"connectionRules\").each((function(o){if(this._isRoleOfOtherNamespace(o.role)){if(!g.get(o.role)){g.set(o.role,new Hash())}}else{if(!g.get(e+o.role)){g.set(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.get(r).get(q)){g.get(r).set(q,s)}else{g.get(r).set(q,g.get(r).get(q).concat(s))}}).bind(this))}).bind(this))}var c=this._cardinalityRules;if(m.get(\"cardinalityRules\")){m.get(\"cardinalityRules\").each((function(q){var o;if(this._isRoleOfOtherNamespace(q.role)){o=q.role}else{o=e+q.role}if(!c.get(o)){c.set(o,{});for(i in q){c.get(o)[i]=q[i]}}var r=new Hash();if(q.outgoingEdges){q.outgoingEdges.each((function(s){if(this._isRoleOfOtherNamespace(s.role)){r.set(s.role,s)}else{r.set(e+s.role,s)}}).bind(this))}c.get(o).outgoingEdges=r;var p=new Hash();if(q.incomingEdges){q.incomingEdges.each((function(s){if(this._isRoleOfOtherNamespace(s.role)){p.set(s.role,s)}else{p.set(e+s.role,s)}}).bind(this))}c.get(o).incomingEdges=p}).bind(this))}var a=this._containmentRules;if(m.get(\"containmentRules\")){m.get(\"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.get(o)){a.set(o,[])}(p.contains||[]).each((function(q){if(this._isRoleOfOtherNamespace(q)){a.get(o).push(q)}else{a.get(o).push(e+q)}}).bind(this))}).bind(this))}var d=this._morphingRules;if(m.get(\"morphingRules\")){m.get(\"morphingRules\").each((function(p){var o;if(this._isRoleOfOtherNamespace(p.role)){o=p.role}else{o=e+p.role}if(!d.get(o)){d.set(o,[])}if(!p.preserveBounds){p.preserveBounds=false}p.baseMorphs.each((function(r){var q=this._getStencilById(e+r);if(q){d.get(o).push(q)}}).bind(this))}).bind(this))}var h=this._layoutRules;if(m.get(\"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.get(\"layoutRules\").each(function(p){var o;if(this._isRoleOfOtherNamespace(p.role)){o=p.role}else{o=e+p.role}if(!h.get(o)){h.set(o,{})}if(p[\"in\"]){h.get(o)[\"in\"]=n(p[\"in\"])}if(p.ins){h.get(o)[\"ins\"]=(p.ins||[]).map(function(q){return n(q)})}if(p.out){h.get(o)[\"out\"]=n(p.out)}if(p.outs){h.get(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.get(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.get(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.get(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.get(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.get(c)){this._connectionRules.get(c).each(function(d){if(a.get(d.key)){a.set(d.key,a.get([d.key]).concat(d.value))}else{a.set(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(a,b){this._extensions=new Hash();this._baseUrl=a;this._jsonObject={};this._stencils=new Hash();this._availableStencils=new Hash();this._init(b)},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.get(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.set(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.set(oStencil.id(),oStencil);this._availableStencils.set(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);this._stencils.unset(d.id());this._availableStencils.unset(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.set(e,this._stencils.get(e))}.bind(this))}}delete this._extensions[a]},__handleStencilset:function(response){this._jsonObject=response;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.set(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.set(d.id(),d);this._availableStencils.set(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.get(b);var a=new Hash();if(c){c.each(function(e){var d=ORYX.Core.StencilSet.stencilSet(e);a.set(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.get(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.get(a)){ORYX.Core.StencilSet._rulesByEditorInstance.set(a,new ORYX.Core.StencilSet.Rules())}return ORYX.Core.StencilSet._rulesByEditorInstance.get(a)};ORYX.Core.StencilSet.loadStencilSet=function(a,d,c){ORYX.Core.StencilSet._stencilSetsByNamespace.set(d.namespace(),d);ORYX.Core.StencilSet._stencilSetsByUrl.set(a,d);var b=d.namespace();if(ORYX.Core.StencilSet._StencilSetNSByEditorInstance.get(c)){ORYX.Core.StencilSet._StencilSetNSByEditorInstance.get(c).push(b)}else{ORYX.Core.StencilSet._StencilSetNSByEditorInstance.set(c,[b])}if(ORYX.Core.StencilSet._rulesByEditorInstance.get(c)){ORYX.Core.StencilSet._rulesByEditorInstance.get(c).initializeRules(d)}else{var e=new ORYX.Core.StencilSet.Rules();e.initializeRules(d);ORYX.Core.StencilSet._rulesByEditorInstance.set(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.set(d,e.value());this.propertiesChanged.set(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.get(e);this.properties.set(e,f);this.propertiesChanged.set(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.set(m,l)}});g.keys().sort().each(function(h){a=a.concat(g.get(h))})});return a}else{return[]}},setProperty:function(b,d,c){var a=this.properties.get(b);if(a!==d||c===true){this.properties.set(b,d);this.propertiesChanged.set(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){this.hiddenProperties.unset(b);return}var a=this.hiddenProperties.get(b);if(a!==c){this.hiddenProperties.set(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.get(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 b=this.properties.merge(this.hiddenProperties);var c=new Hash();b.each(function(k){var f=k.key;var g=k.value;if(this.getStencil().property(f)&&this.getStencil().property(f).type()===ORYX.CONFIG.TYPE_COMPLEX&&Object.prototype.toString.call(g)===\"String\"){try{g=JSON.parse(g)}catch(d){}}else{if(g instanceof Date&&this.getStencil().property(f)){try{g=g.format(this.getStencil().property(f).dateFormat())}catch(h){}}}f=f.replace(/^[\\w_]+-/,\"\");c.set(f,g)}.bind(this));var a={resourceId:this.resourceId,properties:c.toObject(),stencil:{id:this.getStencil().idWithoutNs()},childShapes:this.getChildShapes().map(function(d){return d.toJSON()})};if(this.getOutgoingShapes){a.outgoing=this.getOutgoingShapes().map(function(d){return{resourceId:d.resourceId}})}if(this.bounds){a.bounds={lowerRight:this.bounds.lowerRight(),upperLeft:this.bounds.upperLeft()}}if(this.dockers){a.dockers=this.dockers.map(function(e){var f=e.getDockedShape()&&e.referencePoint?e.referencePoint:e.bounds.center();f.getDocker=function(){return e};return f})}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(){},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.\")}},removeAll:function(){var a=this.getChildShapes();for(var c=0;c<a.length;c++){var b=a[c];this.remove(b)}},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(c){this._eventsQueue=[];this.loadedPlugins=[];this.pluginsData=[];var b=c;this.id=b.modelId;if(c.model){b=c.model}if(!this.id){this.id=b.id;if(!this.id){this.id=ORYX.Editor.provideId()}}this.fullscreen=c.fullscreen!==false;this._initEventListener();this._createCanvas(b.stencil?b.stencil.id:null,b.properties);this._generateGUI();var e=false;var d=false;var a=function(){if(!e||!d){return}this._finishedLoading()}.bind(this);window.setTimeout(function(){this.loadPlugins();e=true;a()}.bind(this),100);window.setTimeout(function(){this.loadSerialized(b,true);this.getCanvas().update();d=true;a();this.handleEvents({type:ORYX.CONFIG.EVENT_EDITOR_INIT_COMPLETED})}.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.set(ORYX.CONFIG.EVENT_MOUSEDOWN,[]);this.DOMEventListeners.set(ORYX.CONFIG.EVENT_MOUSEUP,[]);this.DOMEventListeners.set(ORYX.CONFIG.EVENT_MOUSEOVER,[]);this.DOMEventListeners.set(ORYX.CONFIG.EVENT_MOUSEOUT,[]);this.DOMEventListeners.set(ORYX.CONFIG.EVENT_SELECTION_CHANGED,[]);this.DOMEventListeners.set(ORYX.CONFIG.EVENT_MOUSEMOVE,[])},_generateGUI:function(){var a=ORYX.CONFIG.WINDOW_HEIGHT;var b=this.getCanvas().rootNode.parentNode;jQuery(\"#canvasSection\").append(b);if(b.parentNode){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.get(\"name\"));if((!value.get(\"requires\")||!value.get(\"requires\").namespaces||value.get(\"requires\").namespaces.any(function(req){return loadedStencilSetsNamespaces.indexOf(req)>=0}))&&(!value.get(\"notUsesIn\")||!value.get(\"notUsesIn\").namespaces||!value.get(\"notUsesIn\").namespaces.any(function(req){return loadedStencilSetsNamespaces.indexOf(req)>=0}))&&(value.get(\"engaged\")||(value.get(\"engaged\")===undefined))){try{var className=eval(value.get(\"name\"));if(className){var plugin=new className(facade,value);plugin.type=value.get(\"name\");newPlugins.push(plugin);plugin.engaged=true}}catch(e){ORYX.Log.warn(\"Plugin %0 is not available %1\",value.get(\"name\"),e)}}else{ORYX.Log.info(\"Plugin need a stencilset which is not loaded'\",value.get(\"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(){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.unset(a);this.DOMEventListeners.set(\"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.unset(\"disable_\"+a);this.DOMEventListeners.set(a,b)}},registerOnEvent:function(a,b){if(!(this.DOMEventListeners.keys().member(a))){this.DOMEventListeners.set(a,[])}this.DOMEventListeners.get(a).push(b)},unregisterOnEvent:function(a,b){if(this.DOMEventListeners.keys().member(a)){this.DOMEventListeners.set(a,this.DOMEventListeners.get(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.get(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=new Hash(a);this.edges=new Hash()},execute:function(){if(this.changes){this.executeAgain();return}else{this.changes=new Hash()}this.dockers.values().each(function(b){var a=b.docker.parent;if(!a){return}if(!this.changes.get(a.getId())){this.changes.set(a.getId(),{edge:a,oldDockerPositions:a.dockers.map(function(c){return c.bounds.center()})})}b.docker.bounds.moveBy(b.offset);this.edges.set(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.get(b.key);var d=this.getStencil().property(b.key);if(d!=undefined){this.propertiesChanged.set(b.key,false);if(d.type()==ORYX.CONFIG.TYPE_CHOICE){d.refToView().each((function(g){if(g!==\"\"){var f=this._labels.get(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.get(h.id)||e==f.value()){h.setAttributeNS(null,\"display\",((e==f.value())?\"inherit\":\"none\"));c.set(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(g){if(g===\"\"){return}var f=this.id+g;if(d.type()===ORYX.CONFIG.TYPE_FLOWABLE_MULTIINSTANCE){if(g===\"multiinstance\"){var k=this.node.ownerDocument.getElementById(this.id+\"parallel\");if(k){if(e===\"Parallel\"){k.setAttributeNS(null,\"display\",\"inherit\")}else{k.setAttributeNS(null,\"display\",\"none\")}}var n=this.node.ownerDocument.getElementById(this.id+\"sequential\");if(n){if(e===\"Sequential\"){n.setAttributeNS(null,\"display\",\"inherit\")}else{n.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 h=this.node.ownerDocument.getElementById(f);if(!h||!(h.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\");h=$A(r).find(function(u){return u.getAttributeNS(null,\"id\")===f});if(!h){return}}else{return}}if(d.complexAttributeToView()){var p=this._labels.get(f);if(p){try{propJson=e.evalJSON();var q=propJson[d.complexAttributeToView()];p.text(q?q:e)}catch(l){p.text(e)}}}else{switch(d.type()){case ORYX.CONFIG.TYPE_BOOLEAN:if(typeof e==\"string\"){e=e===\"true\"}h.setAttributeNS(null,\"display\",(!(e===d.inverseBoolean()))?\"inherit\":\"none\");break;case ORYX.CONFIG.TYPE_COLOR:if(d.fill()){if(h.tagName.toLowerCase()===\"stop\"){if(e){if(d.lightness()&&d.lightness()!==1){e=ORYX.Utils.adjustLightness(e,d.lightness())}h.setAttributeNS(null,\"stop-color\",e);if(h.parentNode.tagName.toLowerCase()===\"radialgradient\"){ORYX.Utils.adjustGradient(h.parentNode,h)}}if(h.parentNode.tagName.toLowerCase()===\"radialgradient\"){$A(h.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{h.setAttributeNS(null,\"fill\",e)}}if(d.stroke()){h.setAttributeNS(null,\"stroke\",e)}break;case ORYX.CONFIG.TYPE_STRING:var p=this._labels.get(f);if(p){p.text(e)}break;case ORYX.CONFIG.TYPE_EXPRESSION:var p=this._labels.get(f);if(p){p.text(e)}break;case ORYX.CONFIG.TYPE_DATASOURCE:var p=this._labels.get(f);if(p){p.text(e)}break;case ORYX.CONFIG.TYPE_INTEGER:var p=this._labels.get(f);if(p){p.text(e)}break;case ORYX.CONFIG.TYPE_FLOAT:if(d.fillOpacity()){h.setAttributeNS(null,\"fill-opacity\",e)}if(d.strokeOpacity()){h.setAttributeNS(null,\"stroke-opacity\",e)}if(!d.fillOpacity()&&!d.strokeOpacity()){var p=this._labels.get(f);if(p){p.text(e)}}break;case ORYX.CONFIG.TYPE_SUB_PROCESS_LINK:if(g==\"subprocesslink\"){var m=h.getAttributeNodeNS(\"\",\"onclick\");var o=h.getAttributeNodeNS(\"\",\"style\");if(m){if(e&&e.id){if(o){o.textContent=\"cursor:pointer;\"}m.textContent=\"FLOWABLE.TOOLBAR.ACTIONS.navigateToProcess(\"+e.id+\");return false;\"}else{if(o){o.textContent=\"cursor:default;\"}m.textContent=\"return false;\"}}}break;case ORYX.CONFIG.TYPE_URL: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.set(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.get(b.getId())){this.attachedNodePositionData.set(b.getId(),new Object());this.attachedNodePositionData.get(b.getId()).relativDistanceFromDocker1=0;this.attachedNodePositionData.get(b.getId()).node=b;this.attachedNodePositionData.get(b.getId()).segment=new Object();this.findEdgeSegmentForNode(b)}else{if(b.isChanged){this.findEdgeSegmentForNode(b)}}},findEdgeSegmentForNode:function(e){var b=this.dockers.length;var k=undefined;for(i=1;i<b;i++){var f=this.dockers[i-1].bounds.center();var d=this.dockers[i].bounds.center();this.relativizePoint(f);this.relativizePoint(d);var c=e.bounds.center();var a=ORYX.Core.Math.distancePointLinie(f,d,c,true);if((a||a==0)&&((!k&&k!=0)||a<k)){k=a;this.attachedNodePositionData.get(e.getId()).segment.docker1=this.dockers[i-1];this.attachedNodePositionData.get(e.getId()).segment.docker2=this.dockers[i]}if(!a&&!k&&k!=0){var h=ORYX.Core.Math.getDistancePointToPoint(c,f);var g=ORYX.Core.Math.getDistancePointToPoint(c,d);if(h<g){this.attachedNodePositionData.get(e.getId()).relativDistanceFromDocker1=0}else{this.attachedNodePositionData.get(e.getId()).relativDistanceFromDocker1=1}this.attachedNodePositionData.get(e.getId()).segment.docker1=this.dockers[i-1];this.attachedNodePositionData.get(e.getId()).segment.docker2=this.dockers[i]}}if(k||k==0){this.attachedNodePositionData.get(e.getId()).relativDistanceFromDocker1=this.getLineParameterForPosition(this.attachedNodePositionData.get(e.getId()).segment.docker1,this.attachedNodePositionData.get(e.getId()).segment.docker2,e)}},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.get(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.get(a.getId())){this.attachedNodePositionData.unset[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.set(b.key,b.value.without(a));this.isChanged=true;this._dockerChanged();return true}}return false}).bind(this))}},removeUnusedDockers:function(){var a=new Hash();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.set(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.set(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.set(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.get(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.get(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.get(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.set(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.set(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.get(s.id).length>2){this.removeDocker(this._dockersByPath.get(s.id)[1])}}else{while(this._dockersByPath.get(s.id).length>1){this.removeDocker(this._dockersByPath.get(s.id)[0])}}var e=this._dockersByPath.get(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();if(a.length>0){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();this.facade.handleEvents({type:ORYX.CONFIG.ACTION_DELETE_COMPLETED})},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.get(\"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=$$(\"#canvasSection .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(FLOWABLE.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.get(c);this.oldValueText=l.properties.get(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\"||n.getParentShape().getStencil().idWithoutNs()===\"CMMNDiagram\"){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(v){var o=v.shape;var H=this.facade.getSelection();var z=H.include(o)?o:H.first();z=z||o;this.currentPool=o;if(!(z.getStencil().id().endsWith(\"Pool\")||z.getStencil().id().endsWith(\"Lane\"))){return}if(z!==o&&!z.isParent(o)&&!this.hashedBounds[o.id][z.id]){return}if(!this.hashedBounds[o.id]){this.hashedBounds[o.id]={}}var C=this.getLanes(o);if(C.length<=0){return}var B=this.getLanes(o,true),b;var g=B.clone();var k=new Hash();B.each(function(x){k.set(x.id,x.bounds.upperLeft())});if(C.length===1&&this.getLanes(C.first()).length<=0){var A=C.first().properties.get(\"oryx-name\").trim().length>0;C.first().setProperty(\"oryx-showcaption\",A);var d=C.first().node.getElementsByTagName(\"rect\");d[0].setAttributeNS(null,\"display\",\"none\")}else{B.invoke(\"setProperty\",\"oryx-showcaption\",true);B.each(function(x){var y=x.node.getElementsByTagName(\"rect\");y[0].removeAttributeNS(null,\"display\")})}var u=[];var n=[];var w=-1;while(++w<B.length){if(!this.hashedBounds[o.id][B[w].id]){n.push(B[w])}}if(n.length>0){z=n.first()}var E=$H(this.hashedBounds[o.id]).keys();var w=-1;while(++w<E.length){if(!B.any(function(x){return x.id==E[w]})){u.push(this.hashedBounds[o.id][E[w]]);H=H.without(function(x){return x.id==E[w]})}}var q,s,m,l;if(u.length>0||n.length>0){if(n.length===1&&this.getLanes(n[0].parent).length===1){q=this.adjustHeight(C,n[0].parent)}else{q=this.updateHeight(o)}s=this.adjustWidth(C,o.bounds.width());o.update()}else{if(o==z){if(H.length===1&&this.isResized(o,this.hashedPoolPositions[o.id])){var D=this.hashedPoolPositions[o.id].upperLeft();var f=o.bounds.upperLeft();var G=0;if(this.shouldScale(o)){var c=this.hashedPoolPositions[o.id];G=c.height()/o.bounds.height()}this.adjustLanes(o,B,D.x-f.x,D.y-f.y,G)}q=this.adjustHeight(C,undefined,o.bounds.height());s=this.adjustWidth(C,o.bounds.width())}else{if(H.length===1&&this.isResized(z,this.hashedBounds[o.id][z.id])){var D=this.hashedBounds[o.id][z.id].upperLeft();var f=z.absoluteXY();m=D.x-f.x;l=D.y-f.y;if(m||l){g=g.without(z);this.adjustLanes(o,this.getAllExcludedLanes(o,z),m,0)}var h=this.getLanes(z,true);if(h.length>0){if(this.shouldScale(z)){var c=this.hashedBounds[o.id][z.id];var G=c.height()/z.bounds.height();this.adjustLanes(o,h,m,l,G)}else{this.adjustLanes(o,h,m,l,0)}}}var F=B.map(function(x){return{shape:x,bounds:x.bounds.clone()}});q=this.adjustHeight(C,z);this.checkForChanges(B,F);s=this.adjustWidth(C,z.bounds.width()+(this.getDepth(z,o)*30))}}this.setDimensions(o,s,q,m,l);if(this.facade.isExecutingCommands()&&(u.length===0||n.length!==0)){this.updateDockers(g,o);var t=this.hashedPositions[o.id];if(t&&t.keys().any(function(y,x){return(B[x]||{}).id!==y})){var r=ORYX.Core.Command.extend({construct:function(J,I,y,K,x){this.originPosition=Object.clone(J);this.newPosition=Object.clone(I);this.lanes=y;this.plugin=K;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=new Hash();B.each(function(x){p.set(x.id,x.bounds.upperLeft())});var e=new r(k,p,B,this,o.id);this.facade.executeCommands([e])}}this.hashedBounds[o.id]={};this.hashedPositions[o.id]=k;var w=-1;while(++w<B.length){this.hashedBounds[o.id][B[w].id]=B[w].absoluteBounds();this.hashChildShapes(B[w]);this.hashedLaneDepth[B[w].id]=this.getDepth(B[w],o);this.forceToUpdateLane(B[w])}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": "flowable-ui-web/modeler/editor-app/editor-config.js",
    "content": "/* 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'use strict';\n\nvar FLOWABLE = FLOWABLE || {};\n\nFLOWABLE.UI_CONFIG = {\n\t\t'showRemovedProperties' : false\n};\n\nFLOWABLE.HEADER_CONFIG = {\n\t\t'showAppTitle' : true,\n\t\t'showHeaderMenu' : true,\n\t\t'showMainNavigation' : true,\n\t\t'showPageHeader' : true\n};"
  },
  {
    "path": "flowable-ui-web/modeler/editor-app/editor-controller.js",
    "content": "/* 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'use strict';\n\n/**\n * General bootstrap of the application.\n */\nangular.module('flowableModeler')\n    .controller('EditorController', ['$rootScope', '$scope', '$http', '$q', '$routeParams', '$timeout', '$location', '$translate', '$modal', 'editorManager', 'FormBuilderService',\n        function ($rootScope, $scope, $http, $q, $routeParams, $timeout, $location, $translate, $modal, editorManager, FormBuilderService) {\n\n    $rootScope.editorFactory = $q.defer();\n\n    $rootScope.forceSelectionRefresh = false;\n\n    $rootScope.ignoreChanges = false; // by default never ignore changes\n    \n    $rootScope.validationErrors = [];\n\n    $rootScope.staticIncludeVersion = Date.now();\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\n    /* Helper method to fetch model from server (always needed) */\n    function fetchModel() {\n\n        var modelUrl;\n        if ($routeParams.modelId) {\n            modelUrl = FLOWABLE.URL.getModel($routeParams.modelId);\n        } else {\n            modelUrl = FLOWABLE.URL.newModelInfo();\n        }\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                $location.path(\"/processes/\");\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 = editorManager.getSelection();\n\t\t\tvar subSelectionElements = editorManager.getSubSelection();\n\n            $scope.selectedElements = selectedElements;\n            $scope.subSelectionElements = subSelectionElements;\n            if (selectedElements && selectedElements.length > 0)\n            {\n            \t$rootScope.selectedElementBeforeScrolling = selectedElements[0];\n            }\n\n            jQuery('.Oryx_button').each(function(i, obj) {\n                  $scope.orginalOryxButtonStyle = obj.style.display;\n                  obj.style.display = 'none';\n            });\n            jQuery('.resizer_southeast').each(function(i, obj) {\n                  $scope.orginalResizerSEStyle = obj.style.display;\n                  obj.style.display = 'none';\n            });\n            jQuery('.resizer_northwest').each(function(i, obj) {\n                  $scope.orginalResizerNWStyle = obj.style.display;\n                  obj.style.display = 'none';\n            });\n            editorManager.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            editorManager.setSelection([]); // needed cause it checks for element changes and does nothing if the elements are the same\n            editorManager.setSelection($scope.selectedElements, $scope.subSelectionElements);\n            $scope.selectedElements = undefined;\n            $scope.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            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    if (!$rootScope.editorInitialized) {\n    \n        var paletteHelpWrapper = jQuery('#paletteHelpWrapper');\n\t\tvar paletteSectionFooter = jQuery('#paletteSectionFooter');\n\t\tvar paletteSectionOpen = jQuery('#paletteSectionOpen');\n\t\tvar contentCanvasWrapper = jQuery('#contentCanvasWrapper');\n\n\t\tpaletteSectionFooter.on('click', function() {\n\t\t\tpaletteHelpWrapper.addClass('close');\n\t\t\tcontentCanvasWrapper.addClass('collapsedCanvasWrapper');\n\t\t\tpaletteSectionOpen.removeClass('hidden');\n\t\t});\n\n\t\tpaletteSectionOpen.on('click', function () {\n\t\t\tpaletteHelpWrapper.removeClass('close');\n\t\t\tcontentCanvasWrapper.removeClass('collapsedCanvasWrapper');\n\t\t\tpaletteSectionOpen.addClass('hidden');\n\t\t});\n\n        /**\n         * A 'safer' apply that avoids concurrent updates (which $apply allows).\n         */\n        $rootScope.safeApply = function(fn) {\n        \tif (this.$root) {\n\t            var phase = this.$root.$$phase;\n\t            if(phase == '$apply' || phase == '$digest') {\n\t                if(fn && (typeof(fn) === 'function')) {\n\t                    fn();\n\t                }\n\t            } else {\n\t                this.$apply(fn);\n\t            }\n\t            \n        \t} else {\n                this.$apply(fn);\n            }\n        };\n        \n        $rootScope.addHistoryItem = function(resourceId) {\n        \tvar modelMetaData = editorManager.getBaseModelData();\n        \t\n        \tvar historyItem = {\n                id: modelMetaData.modelId, \n                name: modelMetaData.name,\n                key: modelMetaData.key,\n                stepId: resourceId,\n                type: 'bpmnmodel'\n            };\n        \t\n        \tif (editorManager.getCurrentModelId() != editorManager.getModelId()) {\n\t\t\t\thistoryItem.subProcessId = editorManager.getCurrentModelId();\n\t\t\t}\n        \t\n        \t$rootScope.editorHistory.push(historyItem);\n        };\n        \n        $rootScope.getStencilSetName = function() {\n            var modelMetaData = editorManager.getBaseModelData();\n            if (modelMetaData.model.stencilset.namespace == 'http://b3mn.org/stencilset/cmmn1.1#') {\n                return 'cmmn1.1';\n            } else {\n                return 'bpmn2.0';\n            }\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            $rootScope.formItems = undefined;\n\n            FLOWABLE.eventBus.editor = $rootScope.editor;\n\n            var eventMappings = [\n                { oryxType : ORYX.CONFIG.EVENT_SELECTION_CHANGED, flowableType : FLOWABLE.eventBus.EVENT_TYPE_SELECTION_CHANGE },\n                { oryxType : ORYX.CONFIG.EVENT_DBLCLICK, flowableType : FLOWABLE.eventBus.EVENT_TYPE_DOUBLE_CLICK },\n                { oryxType : ORYX.CONFIG.EVENT_MOUSEOUT, flowableType : FLOWABLE.eventBus.EVENT_TYPE_MOUSE_OUT },\n                { oryxType : ORYX.CONFIG.EVENT_MOUSEOVER, flowableType : FLOWABLE.eventBus.EVENT_TYPE_MOUSE_OVER },\n                { oryxType: ORYX.CONFIG.EVENT_EDITOR_INIT_COMPLETED, flowableType:FLOWABLE.eventBus.EVENT_TYPE_EDITOR_READY},\n\t\t\t\t{ oryxType: ORYX.CONFIG.EVENT_PROPERTY_CHANGED, flowableType: FLOWABLE.eventBus.EVENT_TYPE_PROPERTY_VALUE_CHANGED}\n\n            ];\n\n            eventMappings.forEach(function(eventMapping) {\n                editorManager.registerOnEvent(eventMapping.oryxType, function(event) {\n                    FLOWABLE.eventBus.dispatch(eventMapping.flowableType, event);\n                });\n            });\n\n            // Show getting started if this is the first time (boolean true for use local storage)\n            // FLOWABLE_EDITOR_TOUR.gettingStarted($scope, $translate, $q, true);\n        });\n\n        // Hook in resizing of main panels when window resizes\n        // TODO: perhaps move to a separate JS-file?\n        jQuery(window).resize(function () {\n\n            // Calculate the offset based on the bottom of the module header\n            var offset = jQuery(\"#editor-header\").offset();\n            var propSectionHeight = jQuery('#propertySection').height();\n            var canvas = jQuery('#canvasSection');\n            var mainHeader = jQuery('#main-header');\n\n            if (offset == undefined || offset === null\n                || propSectionHeight === undefined || propSectionHeight === null\n                || canvas === undefined || canvas === null || mainHeader === null) {\n                return;\n            }\n\n            if ($rootScope.editor) {\n\t        \tvar selectedElements = editorManager.getSelection();\n\t\t\t\tvar subSelectionElements = editorManager.getSelection();\n\n\t            $scope.selectedElements = selectedElements;\n\t            $scope.subSelectionElements = subSelectionElements;\n\t            if (selectedElements && selectedElements.length > 0) {\n\t            \t$rootScope.selectedElementBeforeScrolling = selectedElements[0];\n\n\t            \teditorManager.setSelection([]); // needed cause it checks for element changes and does nothing if the elements are the same\n\t                editorManager.setSelection($scope.selectedElements, $scope.subSelectionElements);\n\t                $scope.selectedElements = undefined;\n\t                $scope.subSelectionElements = undefined;\n\t            }\n        \t}\n        \t\n        \tvar totalAvailable = jQuery(window).height() - offset.top - mainHeader.height() - 21;\n\t\t\tcanvas.height(totalAvailable - propSectionHeight);\n\t\t\tvar footerHeight = jQuery('#paletteSectionFooter').height();\n\t\t\tvar treeViewHeight = jQuery('#process-treeview-wrapper').height();\n\t\t\tjQuery('#paletteSection').height(totalAvailable - treeViewHeight - footerHeight);\n      \n            // Update positions of the resize-markers, according to the canvas\n\n            var actualCanvas = null;\n            if (canvas && canvas[0].children[1]) {\n                actualCanvas = canvas[0].children[1];\n            }\n\n            var canvasTop = canvas.position().top;\n            var canvasLeft = canvas.position().left;\n            var canvasHeight = canvas[0].clientHeight;\n            var canvasWidth = canvas[0].clientWidth;\n            var iconCenterOffset = 8;\n            var widthDiff = 0;\n\n            var actualWidth = 0;\n            if (actualCanvas) {\n                // In some browsers, the SVG-element clientwidth isn't available, so we revert to the parent\n                actualWidth = actualCanvas.clientWidth || actualCanvas.parentNode.clientWidth;\n            }\n\n            if (actualWidth < canvas[0].clientWidth) {\n                widthDiff = actualWidth - canvas[0].clientWidth;\n                // In case the canvas is smaller than the actual viewport, the resizers should be moved\n                canvasLeft -= widthDiff / 2;\n                canvasWidth += widthDiff;\n            }\n\n            var iconWidth = 17;\n            var iconOffset = 20;\n\n            var north = jQuery('#canvas-grow-N');\n            north.css('top', canvasTop + iconOffset + 'px');\n            north.css('left', canvasLeft - 10 + (canvasWidth - iconWidth) / 2 + 'px');\n\n            var south = jQuery('#canvas-grow-S');\n            south.css('top', (canvasTop + canvasHeight - iconOffset - iconCenterOffset) +  'px');\n            south.css('left', canvasLeft - 10 + (canvasWidth - iconWidth) / 2 + 'px');\n\n            var east = jQuery('#canvas-grow-E');\n            east.css('top', canvasTop - 10 + (canvasHeight - iconWidth) / 2 + 'px');\n            east.css('left', (canvasLeft + canvasWidth - iconOffset - iconCenterOffset) + 'px');\n\n            var west = jQuery('#canvas-grow-W');\n            west.css('top', canvasTop -10 + (canvasHeight - iconWidth) / 2 + 'px');\n            west.css('left', canvasLeft + iconOffset + 'px');\n\n            north = jQuery('#canvas-shrink-N');\n            north.css('top', canvasTop + iconOffset + 'px');\n            north.css('left', canvasLeft + 10 + (canvasWidth - iconWidth) / 2 + 'px');\n\n            south = jQuery('#canvas-shrink-S');\n            south.css('top', (canvasTop + canvasHeight - iconOffset - iconCenterOffset) +  'px');\n            south.css('left', canvasLeft +10 + (canvasWidth - iconWidth) / 2 + 'px');\n\n            east = jQuery('#canvas-shrink-E');\n            east.css('top', canvasTop + 10 + (canvasHeight - iconWidth) / 2 +  'px');\n            east.css('left', (canvasLeft + canvasWidth - iconOffset - iconCenterOffset) + 'px');\n\n            west = jQuery('#canvas-shrink-W');\n            west.css('top', canvasTop + 10 + (canvasHeight - iconWidth) / 2 + 'px');\n            west.css('left', canvasLeft + iconOffset + 'px');\n        });\n\n        jQuery(window).trigger('resize');\n\n        jQuery.fn.scrollStopped = function(callback) {\n            jQuery(this).scroll(function(){\n                var self = this, $this = jQuery(self);\n                if ($this.data('scrollTimeout')) {\n                    clearTimeout($this.data('scrollTimeout'));\n                }\n                $this.data('scrollTimeout', setTimeout(callback,50,self));\n            });\n        };\n\n        FLOWABLE.eventBus.addListener('ORYX-EDITOR-LOADED',function(){\n\t\t\tthis.editorFactory.resolve();\n\t\t\tthis.editorInitialized = true;\n\t\t\tthis.modelData = editorManager.getBaseModelData();\n\t\t\t\n\t\t}, $rootScope);\n\t\t\n\t\tFLOWABLE.eventBus.addListener(FLOWABLE.eventBus.EVENT_TYPE_EDITOR_READY, function() {\n\t\t\tvar url = window.location.href;\n\t\t    var regex = new RegExp(\"[?&]subProcessId(=([^&#]*)|&|#|$)\");\n\t\t    var results = regex.exec(url);\n\t\t    if (results && results[2]) {\n\t\t    \teditorManager.edit(decodeURIComponent(results[2].replace(/\\+/g, \" \")));\n\t    \t}\n\t    });\n    }\n\n    $scope.$on('$locationChangeStart', function(event, next, current) {\n    \tif ($rootScope.editor && !$rootScope.ignoreChanges) {\n    \t\tvar plugins = $rootScope.editor.loadedPlugins;\n\n    \t\tvar savePlugin;\n    \t\tfor (var i=0; i<plugins.length; i++) {\n    \t\t\tif (plugins[i].type == 'ORYX.Plugins.Save') {\n    \t\t\t\tsavePlugin = plugins[i];\n    \t\t\t\tbreak;\n    \t\t\t}\n    \t\t}\n\n    \t\tif (savePlugin && savePlugin.hasChanges()) {\n    \t\t\t// Always prevent location from changing. We'll use a popup to determine the action we want to take\n    \t\t\tevent.preventDefault();\n\n    \t\t\tif (!$scope.unsavedChangesModalInstance) {\n\n    \t\t\t\tvar handleResponseFunction = function (discard) {\n    \t\t\t\t\t$scope.unsavedChangesModalInstance = undefined;\n    \t\t\t\t\tif (discard) {\n    \t\t\t\t\t\t$rootScope.ignoreChanges = true;\n    \t\t                $location.url(next.substring(next.indexOf('/#') + 2));\n    \t\t\t\t\t} else {\n    \t\t                $rootScope.ignoreChanges = false;\n    \t\t                $rootScope.setMainPageById('processes');\n    \t\t\t\t\t}\n    \t\t\t\t};\n\n    \t\t\t\t$scope.handleResponseFunction = handleResponseFunction;\n\n                    _internalCreateModal({\n    \t\t\t\t\ttemplate: 'editor-app/popups/unsaved-changes.html',\n    \t\t\t\t\tscope: $scope\n    \t\t\t\t},  $modal, $scope);\n    \t\t\t}\n    \t\t}\n    \t}\n    });\n\n    // Always needed, cause the DOM element on wich the scroll event listeners are attached are changed for every new model\n    initScrollHandling();\n    \n    var modelId = $routeParams.modelId;\n\teditorManager.setModelId(modelId);\n\t//we first initialize the stencilset used by the editor. The editorId is always the modelId.\n\t$http.get(FLOWABLE.URL.getModel(modelId)).then(function (response) {\n\t    editorManager.setModelData(response);\n\t    return response;\n\t}).then(function (modelData) {\n\t    if(modelData.data.model.stencilset.namespace == 'http://b3mn.org/stencilset/cmmn1.1#') {\n\t       return $http.get(FLOWABLE.URL.getCmmnStencilSet());\n\t    } else {\n\t       return $http.get(FLOWABLE.URL.getStencilSet());\n\t    }\n    }).then(function (response) {\n \t\tvar baseUrl = \"http://b3mn.org/stencilset/\";\n\t\teditorManager.setStencilData(response.data);\n\t\t//the stencilset alters the data ref!\n\t\tvar stencilSet = new ORYX.Core.StencilSet.StencilSet(baseUrl, response.data);\n\t\tORYX.Core.StencilSet.loadStencilSet(baseUrl, stencilSet, modelId);\n\t\t//after the stencilset is loaded we make sure the plugins.xml is loaded.\n\t\treturn $http.get(ORYX.CONFIG.PLUGINS_CONFIG);\n\t}).then(function (response) {\n\t\tORYX._loadPlugins(response.data);\n\t\treturn response;\n\t}).then(function (response) {\n\t\teditorManager.bootEditor();\n\t}).catch(function (error) {\n\t\tconsole.log(error);\n\t});\n \n \t//minihack to make sure mousebind events are processed if the modeler is used in an iframe.\n\t//selecting an element and pressing \"del\" could sometimes not trigger an event.\n\tjQuery(window).focus();\n\n}]);\n\nangular.module('flowableModeler')\n  .controller('EditorUnsavedChangesPopupCtrl', ['$rootScope', '$scope', '$http', '$location', '$window', function ($rootScope, $scope, $http, $location, $window) {\n\n    $scope.discard = function () {\n      if ($scope.handleResponseFunction) {\n        $scope.handleResponseFunction(true);\n        // Also clear any 'onbeforeunload', added by oryx\n        $window.onbeforeunload = undefined;\n      }\n      $scope.$hide();\n    };\n\n    $scope.save = function () {\n      if ($scope.handleResponseFunction) {\n        $scope.handleResponseFunction(false);\n      }\n      $scope.$hide();\n    };\n\n    $scope.cancel = function () {\n      if ($scope.handleResponseFunction) {\n        $scope.handleResponseFunction(null);\n      }\n      $scope.$hide();\n    };\n  }]);\n\n"
  },
  {
    "path": "flowable-ui-web/modeler/editor-app/editor-utils.js",
    "content": "/* 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\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    collectShapes: function (shapes, stencilId) {\n        var collectedShapes = [];\n\n        if (shapes && shapes.length > 0) {\n            for (var i = 0; i < shapes.length; i++) {\n                EDITOR.UTIL._visitShapeAndCollectShape(shapes[i], stencilId, collectedShapes);\n            }\n        }\n\n        return collectedShapes;\n    },\n\n    collectSortedElementsFromPrecedingElements: function (startElement) {\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._visitElementAndCollectAllElement(incomingShape, visitedElements, collectedElements);\n                }\n            }\n        }\n\n        return collectedElements.reverse();\n    },\n\n    _visitShapeAndCollectShape: function(shape, stencilId, collectedShapes) {\n\n        if (shape.childShapes && shape.childShapes.length > 0) {\n            for (var i = 0; i < shape.childShapes.length; i++) {\n                EDITOR.UTIL._visitShapeAndCollectShape(shape.childShapes[i], stencilId, collectedShapes);\n            }\n        }\n\n        if (shape.stencil && shape.stencil.id === stencilId) {\n            collectedShapes.push(shape);\n        }\n    },\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        var childShapesIterator = element.getChildShapes();\n        if (childShapesIterator) {\n            for (var i = 0; i < childShapesIterator.length; i++) {\n                var childShape = childShapesIterator[i];\n                if (visitedElementsArray.indexOf(childShape.id) < 0) {\n                    EDITOR.UTIL._visitElementAndCollectProperty(childShape, 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        var childShapesIterator = element.getChildShapes();\n        if (childShapesIterator) {\n            for (var i = 0; i < childShapesIterator.length; i++) {\n                var childShape = childShapesIterator[i];\n                if (visitedElementsArray.indexOf(childShape.id) < 0) {\n                    EDITOR.UTIL._visitElementAndCollectElement(childShape, stencilId, visitedElementsArray, collectedElements);\n                }\n            }\n        }\n    },\n\n    _visitElementAndCollectAllElement: function (element, visitedElementsArray, collectedElements) {\n\n        visitedElementsArray.push(element.id);\n\n        var elementStencilId = element.getStencil().id();\n        if (elementStencilId) {\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\n                if (visitedElementsArray.indexOf(incomingShape.id) < 0) {\n                    EDITOR.UTIL._visitElementAndCollectAllElement(incomingShape, visitedElementsArray, collectedElements);\n                }\n            }\n        }\n\n        var childShapesIterator = element.getChildShapes();\n        if (childShapesIterator) {\n            for (var i = 0; i < childShapesIterator.length; i++) {\n                var childShape = childShapesIterator[i];\n\n                if (visitedElementsArray.indexOf(childShape.id) < 0) {\n                    EDITOR.UTIL._visitElementAndCollectAllElement(childShape, visitedElementsArray, collectedElements);\n                }\n            }\n        }\n\n        var parent = element.getParentShape();\n        if (parent) {\n            try {\n                var incomingParentShapesIterator = parent.getIncomingShapes();\n                if (incomingParentShapesIterator) {\n                    for (var i = 0; i < incomingParentShapesIterator.length; i++) {\n                        var incomingParentShape = incomingParentShapesIterator[i];\n\n                        if (visitedElementsArray.indexOf(incomingParentShape.id) < 0) {\n                            EDITOR.UTIL._visitElementAndCollectAllElement(incomingParentShape, visitedElementsArray, collectedElements);\n                        }\n                    }\n                }\n            } catch(err) {\n                // start of model reached\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    /**\n     * Finds last element of given shapes and traverses up the chain and returns elements of the given type\n     *\n     * @param allElements\n     * @param propertyType\n     *\n     * @returns [Array] filteredSteps of given type\n     */\n    extractSortedStepsOfType: function (allElements, propertyType) {\n\n        var filteredSteps = [];\n        var sortedSteps = EDITOR.UTIL.extractSortedSteps(allElements);\n\n        if (sortedSteps && sortedSteps.length > 0) {\n            for (var i = 0; i < sortedSteps.length; i++) {\n                if (sortedSteps[i].stencil && sortedSteps[i].stencil.id === propertyType) {\n                    filteredSteps.push(sortedSteps[i]);\n                }\n            }\n        }\n\n        return filteredSteps;\n    },\n\n    extractSortedSteps: function(allElements) {\n\n        var elementsMap = {};\n        var sortedSteps = [];\n        if (allElements && allElements.length > 0) {\n            for (var i = 0; i < allElements.length; i++) {\n                elementsMap[allElements[i].resourceId] = allElements[i];\n            }\n            EDITOR.UTIL.getOutgoingElements(allElements[0], elementsMap, sortedSteps, true);\n        }\n        return sortedSteps;\n    },\n\n    getOutgoingElements: function(element, elementsMap, sortedSteps, onlySteps) {\n\n        if (element && elementsMap) {\n            if (element.outgoing && element.outgoing.length > 0) {\n                for (var i = 0; i < element.outgoing.length; i++) {\n                    if (onlySteps && EDITOR.UTIL._elementIsStep(element)) {\n                        element.id = element.resourceId;\n                        sortedSteps.push(element);\n                    } else if (!onlySteps) {\n                        element.id = element.resourceId;\n                        sortedSteps.push(element);\n                    }\n                    EDITOR.UTIL.getOutgoingElements(elementsMap[element.outgoing[i].resourceId], elementsMap, sortedSteps);\n                }\n            } else {\n                if (onlySteps && EDITOR.UTIL._elementIsStep(element)) {\n                    element.id = element.resourceId;\n                    sortedSteps.push(element);\n                } else if (!onlySteps) {\n                    element.id = element.resourceId;\n                    sortedSteps.push(element);\n                }\n            }\n        }\n    },\n\n    _elementIsStep: function(element) {\n        var isStep = false;\n        if (element && element.stencil) {\n            if (element.stencil.id != 'SequenceFlow') {\n                isStep = true;\n            }\n        }\n        return isStep;\n    },\n\n\n\n};"
  },
  {
    "path": "flowable-ui-web/modeler/editor-app/editor.html",
    "content": "\n<div ng-controller=\"StencilController\" ng-cloak=\"\">\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=6'\"></li>\n                        </ul>\n\n                        <div ng-if=\"!group.items\" ng-include=\"'editor-app/partials/root-stencil-item-template.html?version=6'\"></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 | translate}}\"\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                        <img ng-if=\"!item.customIcon\" ng-src=\"editor-app/stencilsets/{{getStencilSetName()}}/icons/{{item.icon}}\" width=\"16px;\" height=\"16px;\"/>\n                            <img ng-if=\"item.customIcon\" ng-src=\"{{getImageUrl(item.icon)}}\" width=\"16px;\" height=\"16px;\"/>\n\t                        {{item.name | translate}}\n\t                    </li>\n                    </ul>\n\t\t\t     </div>\n\t\t      </div>\n\t\t      <div id=\"process-treeview-wrapper\" ng-controller=\"ProcessNavigatorController\">\n                    <div class=\"process-treeview-header\">\n                        Process Navigator\n                    </div>\n                    <div class=\"process-treeview-body\" ng-show=\"isEditorReady\">\n                        <div class=\"process-treeview-process-title\" title=\"{{treeview.id}}\" ng-class=\"{'current-process': treeview.current}\" >\n                            Process: {{treeview.name}}\n                            <img ng-show=\"!treeview.current\" ng-src=\"editor-app/images/pencil.png\" class=\"pull-right\" ng-click=\"edit(treeview.id)\" />\n                        </div>\n                        <ul class=\"process-treeview-list\" ng-if=\"treeview.children\">\n                            <li ng-repeat=\"child in treeview.children\" ng-include=\"'editor-app/partials/process-tree-list.html?version=4'\">\n                            </li>\n                        </ul>\n                        <div ng-if=\"!treeview.children || treeview.children.length == 0\" style=\"padding-left: 5px;\">\n                            No structural elements used.\n                        </div>\n                    </div>\n              </div>\n              <div id=\"paletteSectionFooter\">\n                  <i class=\"glyphicon glyphicon-chevron-left\"></i>\n              </div>\n          </div>\n\t      <div id=\"contentCanvasWrapper\">\n                <div id=\"paletteSectionOpen\" class=\"hidden\">\n                    <i class=\"glyphicon glyphicon-chevron-right\"></i>\n                </div>\n                <div id=\"canvasHelpWrapper\" class=\"col-xs-12\">\n                    <div class=\"canvas-wrapper\" id=\"canvasSection\"\n                         ng-model=\"droppedElement\"\n                         data-drop=\"true\"\n                         data-jqyoui-options\n                         jqyoui-droppable=\"{onDrop:'dropCallback',onOver: 'overCallback', onOut: 'outCallback'}\">\n                        <div class=\"canvas-message\" id=\"model-modified-date\"></div>\n                        <div class=\"Oryx_button\"\n                             id=\"delete-button\"\n                             title=\"{{'BUTTON.ACTION.DELETE.TOOLTIP' | translate}}\"\n                             ng-click=\"deleteShape()\"\n                             style=\"display:none\">\n                            <img src=\"editor-app/images/delete.png\"/>\n                        </div>\n                        <div class=\"Oryx_button\"\n                             id=\"morph-button\"\n                             title=\"{{'BUTTON.ACTION.MORPH.TOOLTIP' | translate}}\"\n                             ng-click=\"morphShape()\"\n                             style=\"display:none\">\n                            <img src=\"editor-app/images/wrench.png\"/>\n                        </div>\n                        <div class=\"Oryx_button\" id=\"edit-button\" style=\"display:none\" ng-click=\"editShape()\">\n                            <img src=\"editor-app/images/pencil.png\"/>\n                        </div>\n                        <div class=\"Oryx_button\"\n                             ng-repeat=\"item in quickMenuItems\"\n                             id=\"{{item.id}}\"\n                             title=\"{{item.description}}\"\n                             ng-click=\"quickAddItem(item.id)\"\n                             ng-model=\"draggedElement\"\n                             data-drag=\"true\"\n                             jqyoui-draggable=\"{onStart:'startDragCallbackQuickMenu', onDrag:'dragCallbackQuickMenu'}\"\n                             data-jqyoui-options=\"{revert: 'invalid', helper: 'clone', opacity : 0.5}\"\n                             style=\"display:none\">\n                            <img ng-src=\"editor-app/stencilsets/{{getStencilSetName()}}/icons/{{item.icon}}\"/>\n                        </div>\n                    </div>\n                </div>\n                <div id=\"propertiesHelpWrapper\" class=\"col-xs-12\">\n                    <div class=\"propertySection\" id=\"propertySection\" ng-class=\"{collapsed: propertyWindowState.collapsed}\">\n                        <div class=\"selected-item-section\">\n                            <div class=\"clearfix\">\n                                <div class=\"pull-right\" ng-if=\"selectedItem.auditData.createDate\">\n                                    <strong>{{'ELEMENT.DATE_CREATED' | translate}}: </strong>\n                                    {{selectedItem.auditData.createDate}}\n                                </div>\n                                <div class=\"pull-right\" ng-if=\"selectedItem.auditData.author\">\n                                    <strong>{{'ELEMENT.AUTHOR' | translate}}: </strong>\n                                    {{selectedItem.auditData.author}}\n                                </div>\n                                <div class=\"selected-item-title\">\n                                    <a ng-click=\"propertyWindowState.toggle()\">\n                                        <i class=\"glyphicon\"\n                                           ng-class=\"{'glyphicon-chevron-right': propertyWindowState.collapsed, 'glyphicon-chevron-down': !propertyWindowState.collapsed}\"></i>\n                                        <span ng-show=\"selectedItem.title != undefined && selectedItem.title != null && selectedItem.title.length > 0\">{{selectedItem.title}}</span>\n                                        <span ng-show=\"!selectedItem || selectedItem.title == undefined || selectedItem.title == null || selectedItem.title.length == 0\">{{modelData.name}}</span>\n                                    </a>\n                                </div>\n                            </div>\n                            <div class=\"selected-item-body\">\n                                <div>\n                                    <div class=\"property-row\" ng-repeat=\"property in selectedItem.properties\"\n                                         ng-click=\"propertyClicked($index)\" ng-class=\"{'clear' : $index%2 == 0}\">\n                                        <span class=\"title\" ng-if=\"!property.hidden\">{{ property.title }}&nbsp;:</span>\n                                        <span class=\"title-removed\" ng-if=\"property.hidden\"><i>{{ property.title }}&nbsp;({{'PROPERTY.REMOVED' | translate}})&nbsp;:</i></span>\n                                        <span class=\"value\">\n\t                                    <ng-include\n                                                src=\"getPropertyTemplateUrl($index)\"\n                                                ng-if=\"!property.hasReadWriteMode\"></ng-include>\n\t                                    <ng-include src=\"getPropertyReadModeTemplateUrl($index)\"\n                                                    ng-if=\"property.hasReadWriteMode && property.mode == 'read'\"></ng-include>\n\t                                    <ng-include src=\"getPropertyWriteModeTemplateUrl($index)\"\n                                                    ng-if=\"property.hasReadWriteMode && property.mode == 'write'\"></ng-include>\n\t                                </span>\n                                    </div>\n                                </div>\n                            </div>\n                        </div>\n                    </div>\n                </div>\n            </div>\n        </div>\n    </div>\n</div>\n"
  },
  {
    "path": "flowable-ui-web/modeler/editor-app/editormanager.js",
    "content": "/* Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n * \n *      http://www.apache.org/licenses/LICENSE-2.0\n * \n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Created by Pardo David on 3/01/2017.\n * For this service to work the user must call bootEditor method\n */\nangular.module(\"flowableModeler\").factory(\"editorManager\", [\"$http\", function ($http) {\n    var editorManager = Class.create({\n        initialize: function () {\n            this.treeFilteredElements = [\"SubProcess\", \"CollapsedSubProcess\"];\n            this.canvasTracker = new Hash();\n            this.structualIcons = {\n                \"SubProcess\": \"expanded.subprocess.png\",\n                \"CollapsedSubProcess\": \"subprocess.png\",\n                \"EventSubProcess\": \"event.subprocess.png\"\n            };\n\n            this.current = this.modelId;\n            this.loading = true;\n        },\n        getModelId: function () {\n            return this.modelId;\n        },\n        setModelId: function (modelId){\n            this.modelId = modelId;\n        },\n        getCurrentModelId: function () {\n        \treturn this.current;\n        },\n        setStencilData: function(stencilData){\n            //we don't want a references!\n            this.stencilData = jQuery.extend(true, {},stencilData);\n        },\n        getStencilData: function () {\n            return this.stencilData;\n        },\n        getSelection: function () {\n            return this.editor.selection;\n        },\n        getSubSelection: function () {\n            return this.editor._subSelection;\n        },\n        handleEvents: function (events) {\n            this.editor.handleEvents(events);\n        },\n        setSelection: function (selection) {\n            this.editor.setSelection(selection);\n        },\n        registerOnEvent: function (event, callback) {\n            this.editor.registerOnEvent(event, callback);\n        },\n        getChildShapeByResourceId: function (resourceId) {\n            return this.editor.getCanvas().getChildShapeByResourceId(resourceId);\n        },\n        getJSON: function () {\n            return this.editor.getJSON();\n        },\n        getStencilSets: function () {\n            return this.editor.getStencilSets();\n        },\n        getEditor: function () {\n            return this.editor; //TODO: find out if we can avoid exposing the editor object to angular.\n        },\n        executeCommands: function (commands) {\n            this.editor.executeCommands(commands);\n        },\n        getCanvas: function () {\n            return this.editor.getCanvas();\n        },\n        getRules: function () {\n            return this.editor.getRules();\n        },\n        eventCoordinates: function (coordinates) {\n            return this.editor.eventCoordinates(coordinates);\n        },\n        eventCoordinatesXY: function (x, y) {\n            return this.editor.eventCoordinatesXY(x, y);\n        },\n        updateSelection: function () {\n            this.editor.updateSelection();\n        },\n        /**\n         * @returns the modeldata as received from the server. This does not represent the current editor data.\n         */\n        getBaseModelData: function () {\n            return this.modelData;\n        },\n        edit: function (resourceId) {\n            //Save the current canvas in the canvastracker if it is the root process.\n            this.syncCanvasTracker();\n\n            this.loading = true;\n\n            var shapes = this.getCanvas().getChildren();\n            shapes.each(function (shape) {\n                this.editor.deleteShape(shape);\n            }.bind(this));\n\n            shapes = this.canvasTracker.get(resourceId);\n            if(!shapes){\n                shapes = JSON.stringify([]);\n            }\n\n            this.editor.loadSerialized({\n                childShapes: shapes\n            });\n\n            this.getCanvas().update();\n\n            this.current = resourceId;\n\n            this.loading = false;\n            FLOWABLE.eventBus.dispatch(\"EDITORMANAGER-EDIT-ACTION\", {});\n            FLOWABLE.eventBus.dispatch(FLOWABLE.eventBus.EVENT_TYPE_UNDO_REDO_RESET, {});\n        },\n        getTree: function () {\n            //build a tree of all subprocesses and there children.\n            var result = new Hash();\n            var parent = this.getModel();\n            result.set(\"name\", parent.properties[\"name\"] || \"No name provided\");\n            result.set(\"id\", this.modelId);\n            result.set(\"type\", \"root\");\n            result.set(\"current\", this.current === this.modelId)\n            var childShapes = parent.childShapes;\n            var children = this._buildTreeChildren(childShapes);\n            result.set(\"children\", children);\n            return result.toObject();\n        },\n        _buildTreeChildren: function (childShapes) {\n            var children = [];\n            for (var i = 0; i < childShapes.length; i++) {\n                var childShape = childShapes[i];\n                var stencilId = childShape.stencil.id;\n                //we are currently only interested in the expanded subprocess and collapsed processes\n                if (stencilId && this.treeFilteredElements.indexOf(stencilId) > -1) {\n                    var child = new Hash();\n                    child.set(\"name\", childShape.properties.name || \"No name provided\");\n                    child.set(\"id\", childShape.resourceId);\n                    child.set(\"type\", stencilId);\n                    child.set(\"current\", childShape.resourceId === this.current);\n                    \n                    //check if childshapes\n\n                    if (stencilId === \"CollapsedSubProcess\") {\n                        //the save function stores the real object as a childshape\n                        //it is possible that there is no child element because the user did not open the collapsed subprocess.\n                        if (childShape.childShapes.length === 0) {\n                            child.set(\"children\", []);\n                        } else {\n                            child.set(\"children\", this._buildTreeChildren(childShape.childShapes));\n                        }\n                        child.set(\"editable\", true);\n                    } else {\n                        child.set(\"children\", this._buildTreeChildren(childShape.childShapes));\n                        child.set(\"editable\", false);\n                    }\n                    child.set(\"icon\", this.structualIcons[stencilId]);\n                    children.push(child.toObject());\n                }\n            }\n            return children;\n        },\n        syncCanvasTracker: function () {\n            var shapes = this.getCanvas().getChildren();\n            var jsonShapes = [];\n            shapes.each(function (shape) {\n                //toJson is an summary object but its not a json string.!!!!!\n                jsonShapes.push(shape.toJSON());\n            });\n            this.canvasTracker.set(this.current, JSON.stringify(jsonShapes));\n        },\n        getModel: function () {\n            this.syncCanvasTracker();\n            \n            var modelMetaData = this.getBaseModelData();\n            \n            var stencilId = undefined;\n            var stencilSetNamespace = undefined;\n            var stencilSetUrl = undefined;\n            if (modelMetaData.model.stencilset.namespace == 'http://b3mn.org/stencilset/cmmn1.1#') {\n                stencilId = 'CMMNDiagram';\n                stencilSetNamespace = 'http://b3mn.org/stencilset/cmmn1.1#';\n                stencilSetUrl = '../editor/stencilsets/cmmn1.1/cmmn1.1.json';\n            } else {\n                stencilId = 'BPMNDiagram';\n                stencilSetNamespace = 'http://b3mn.org/stencilset/bpmn2.0#';\n                stencilSetUrl = '../editor/stencilsets/bpmn2.0/bpmn2.0.json';\n            }\n\n            //this is an object.\n            var editorConfig = this.editor.getJSON();\n            var model = {\n                modelId: this.modelId,\n                bounds: editorConfig.bounds,\n                properties: editorConfig.properties,\n                childShapes: JSON.parse(this.canvasTracker.get(this.modelId)),\n                stencil: {\n                    id: stencilId,\n                },\n                stencilset: {\n                    namespace: stencilSetNamespace,\n                    url: stencilSetUrl\n                }\n            };\n\n            this._mergeCanvasToChild(model);\n\n            return model;\n        },\n        setModelData: function(response){\n            this.modelData = response.data;\n        },\n        bootEditor: function () {\n            //TODO: populate the canvas with correct json sections.\n            //resetting the state\n            this.canvasTracker = new Hash();\n            var config = jQuery.extend(true, {}, this.modelData); //avoid a reference to the original object.\n            if(!config.model.childShapes){\n                config.model.childShapes = [];\n            }\n            \n            this.findAndRegisterCanvas(config.model.childShapes); //this will remove any childshapes of a collapseable subprocess.\n            this.canvasTracker.set(config.modelId, JSON.stringify(config.model.childShapes)); //this will be overwritten almost instantly.\n\n            this.editor = new ORYX.Editor(config);\n            this.current = this.editor.id;\n            this.loading = false;\n\n            FLOWABLE.eventBus.editor = this.editor;\n            FLOWABLE.eventBus.dispatch(\"ORYX-EDITOR-LOADED\", {});\n            FLOWABLE.eventBus.dispatch(FLOWABLE.eventBus.EVENT_TYPE_EDITOR_BOOTED, {});\n        },\n        findAndRegisterCanvas: function (childShapes) {\n            for (var i = 0; i < childShapes.length; i++) {\n                var childShape = childShapes[i];\n                if (childShape.stencil.id === \"CollapsedSubProcess\") {\n                    if (childShape.childShapes.length > 0) {\n                        //the canvastracker will auto correct itself with a new canvasmodel see this.edit()...\n                        this.findAndRegisterCanvas(childShape.childShapes);\n                        //a canvas can't be nested as a child because the editor would crash on redundant information.\n                        this.canvasTracker.set(childShape.resourceId, JSON.stringify(childShape.childShapes));\n                        //reference to config will clear the value.\n                        childShape.childShapes = [];\n                    } else {\n                        this.canvasTracker.set(childShape.resourceId, '[]');\n                    }\n                }\n            }\n        },\n        _mergeCanvasToChild: function (parent) {\n            for (var i = 0; i < parent.childShapes.length; i++) {\n                var childShape = parent.childShapes[i]\n                if(childShape.stencil.id === \"CollapsedSubProcess\"){\n                    \n                    var elements = this.canvasTracker.get(childShape.resourceId);\n                    if(elements){\n                        elements = JSON.parse(elements);\n                    }else{\n                        elements = [];\n                    }\n                    childShape.childShapes = elements;\n                    this._mergeCanvasToChild(childShape);\n                }else if(childShape.stencil.id === \"SubProcess\"){\n                    this._mergeCanvasToChild(childShape);\n                }else{\n                    //do nothing?\n                }\n            }\n        },\n        dispatchOryxEvent: function (event) {\n            FLOWABLE.eventBus.dispatchOryxEvent(event);\n        },\n        isLoading: function(){\n            return this.loading;\n        },\n        navigateTo: function(resourceId){\n            //TODO: this could be improved by check if the resourceId is not equal to the current tracker...\n            this.syncCanvasTracker();\n            var found = false;\n            this.canvasTracker.each(function(pair){\n                var key = pair.key;\n                var children = JSON.parse(pair.value);\n                var targetable = this._findTarget(children, resourceId);\n                if (!found && targetable){\n                    this.edit(key);\n                    var flowableShape = this.getCanvas().getChildShapeByResourceId(targetable);\n                    this.setSelection([flowableShape],[],true);\n                    found = true;\n                }\n            },this);\n        },\n        _findTarget: function(children,resourceId){\n            for(var i =0; i < children.length; i++){\n                var child = children[i];\n                if(child.resourceId === resourceId){\n                    return child.resourceId;\n                }else if(child.properties && child.properties[\"overrideid\"] === resourceId){\n                    return child.resourceId;\n                }else{\n                    var result = this._findTarget(child.childShapes,resourceId);\n                    if(result){\n                        return result;\n                    }\n                }\n            }\n            return false;\n        }\n    });\n\n    return new editorManager();\n}]);\n"
  },
  {
    "path": "flowable-ui-web/modeler/editor-app/eventbus.js",
    "content": "/* 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 */\nvar FLOWABLE = FLOWABLE || {};\n\n/** Inspired by https://github.com/krasimir/EventBus/blob/master/src/EventBus.js */\nFLOWABLE.eventBus = {\n\n    /** Event fired when the editor is loaded and ready */\n    EVENT_TYPE_EDITOR_READY: 'event-type-editor-ready',\n    \n    EVENT_TYPE_EDITOR_BOOTED: 'event-type-editor-booted',\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    /** Event fired when the validation popup should be shown. */\n    EVENT_TYPE_SHOW_VALIDATION_POPUP: 'event-type-show-validation-popup',\n    \n    /** Event fired when a different process must be loaded. */\n    EVENT_TYPE_NAVIGATE_TO_PROCESS: 'event-type-navigate-to-process',\n    \n    EVENT_TYPE_UNDO_REDO_RESET : 'event-type-undo-redo-reset',\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        FLOWABLE.eventBus.editor.handleEvents(event, uiObject);\n    }\n\n};"
  },
  {
    "path": "flowable-ui-web/modeler/editor-app/header-controller.js",
    "content": "/* 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'use strict';\n\nangular.module('flowableModeler')\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 = FLOWABLE.HEADER_CONFIG;\n    \t\n    \t// TODO: generate setting-menu items\n    \t\n    \t// TODO: generate user-menu items\n\n}]);"
  },
  {
    "path": "flowable-ui-web/modeler/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": "flowable-ui-web/modeler/editor-app/libs/mousetrap/1.6.0/mousetrap-record.js",
    "content": "/**\n * This extension allows you to record a sequence using Mousetrap.\n *\n * @author Dan Tao <daniel.tao@gmail.com>\n */\n(function(Mousetrap) {\n    /**\n     * the sequence currently being recorded\n     *\n     * @type {Array}\n     */\n    var _recordedSequence = [],\n\n        /**\n         * a callback to invoke after recording a sequence\n         *\n         * @type {Function|null}\n         */\n        _recordedSequenceCallback = null,\n\n        /**\n         * a list of all of the keys currently held down\n         *\n         * @type {Array}\n         */\n        _currentRecordedKeys = [],\n\n        /**\n         * temporary state where we remember if we've already captured a\n         * character key in the current combo\n         *\n         * @type {boolean}\n         */\n        _recordedCharacterKey = false,\n\n        /**\n         * a handle for the timer of the current recording\n         *\n         * @type {null|number}\n         */\n        _recordTimer = null,\n\n        /**\n         * the original handleKey method to override when Mousetrap.record() is\n         * called\n         *\n         * @type {Function}\n         */\n        _origHandleKey = Mousetrap.prototype.handleKey;\n\n    /**\n     * handles a character key event\n     *\n     * @param {string} character\n     * @param {Array} modifiers\n     * @param {Event} e\n     * @returns void\n     */\n    function _handleKey(character, modifiers, e) {\n        var self = this;\n\n        if (!self.recording) {\n            _origHandleKey.apply(self, arguments);\n            return;\n        }\n\n        // remember this character if we're currently recording a sequence\n        if (e.type == 'keydown') {\n            if (character.length === 1 && _recordedCharacterKey) {\n                _recordCurrentCombo();\n            }\n\n            for (i = 0; i < modifiers.length; ++i) {\n                _recordKey(modifiers[i]);\n            }\n            _recordKey(character);\n\n            // once a key is released, all keys that were held down at the time\n            // count as a keypress\n        } else if (e.type == 'keyup' && _currentRecordedKeys.length > 0) {\n            _recordCurrentCombo();\n        }\n    }\n\n    /**\n     * marks a character key as held down while recording a sequence\n     *\n     * @param {string} key\n     * @returns void\n     */\n    function _recordKey(key) {\n        var i;\n\n        // one-off implementation of Array.indexOf, since IE6-9 don't support it\n        for (i = 0; i < _currentRecordedKeys.length; ++i) {\n            if (_currentRecordedKeys[i] === key) {\n                return;\n            }\n        }\n\n        _currentRecordedKeys.push(key);\n\n        if (key.length === 1) {\n            _recordedCharacterKey = true;\n        }\n    }\n\n    /**\n     * marks whatever key combination that's been recorded so far as finished\n     * and gets ready for the next combo\n     *\n     * @returns void\n     */\n    function _recordCurrentCombo() {\n        _recordedSequence.push(_currentRecordedKeys);\n        _currentRecordedKeys = [];\n        _recordedCharacterKey = false;\n        _restartRecordTimer();\n    }\n\n    /**\n     * ensures each combo in a sequence is in a predictable order and formats\n     * key combos to be '+'-delimited\n     *\n     * modifies the sequence in-place\n     *\n     * @param {Array} sequence\n     * @returns void\n     */\n    function _normalizeSequence(sequence) {\n        var i;\n\n        for (i = 0; i < sequence.length; ++i) {\n            sequence[i].sort(function(x, y) {\n                // modifier keys always come first, in alphabetical order\n                if (x.length > 1 && y.length === 1) {\n                    return -1;\n                } else if (x.length === 1 && y.length > 1) {\n                    return 1;\n                }\n\n                // character keys come next (list should contain no duplicates,\n                // so no need for equality check)\n                return x > y ? 1 : -1;\n            });\n\n            sequence[i] = sequence[i].join('+');\n        }\n    }\n\n    /**\n     * finishes the current recording, passes the recorded sequence to the stored\n     * callback, and sets Mousetrap.handleKey back to its original function\n     *\n     * @returns void\n     */\n    function _finishRecording() {\n        if (_recordedSequenceCallback) {\n            _normalizeSequence(_recordedSequence);\n            _recordedSequenceCallback(_recordedSequence);\n        }\n\n        // reset all recorded state\n        _recordedSequence = [];\n        _recordedSequenceCallback = null;\n        _currentRecordedKeys = [];\n    }\n\n    /**\n     * called to set a 1 second timeout on the current recording\n     *\n     * this is so after each key press in the sequence the recording will wait for\n     * 1 more second before executing the callback\n     *\n     * @returns void\n     */\n    function _restartRecordTimer() {\n        clearTimeout(_recordTimer);\n        _recordTimer = setTimeout(_finishRecording, 1000);\n    }\n\n    /**\n     * records the next sequence and passes it to a callback once it's\n     * completed\n     *\n     * @param {Function} callback\n     * @returns void\n     */\n    Mousetrap.prototype.record = function(callback) {\n        var self = this;\n        self.recording = true;\n        _recordedSequenceCallback = function() {\n            self.recording = false;\n            callback.apply(self, arguments);\n        };\n    };\n\n    Mousetrap.prototype.handleKey = function() {\n        var self = this;\n        _handleKey.apply(self, arguments);\n    };\n\n    Mousetrap.init();\n\n})(Mousetrap);"
  },
  {
    "path": "flowable-ui-web/modeler/editor-app/libs/mousetrap/1.6.0/mousetrap.js",
    "content": "/*global define:false */\n/**\n * Copyright 2016 Craig Campbell\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 * Mousetrap is a simple keyboard shortcut library for Javascript with\n * no external dependencies\n *\n * @version 1.6.0\n * @url craig.is/killing/mice\n */\n(function(window, document, undefined) {\n\n    // Check if mousetrap is used inside browser, if not, return\n    if (!window) {\n        return;\n    }\n\n    /**\n     * mapping of special keycodes to their corresponding keys\n     *\n     * everything in this dictionary cannot use keypress events\n     * so it has to be here to map to the correct keycodes for\n     * keyup/keydown events\n     *\n     * @type {Object}\n     */\n    var _MAP = {\n        8: 'backspace',\n        9: 'tab',\n        13: 'enter',\n        16: 'shift',\n        17: 'ctrl',\n        18: 'alt',\n        20: 'capslock',\n        27: 'esc',\n        32: 'space',\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: 'ins',\n        46: 'del',\n        91: 'meta',\n        93: 'meta',\n        224: 'meta'\n    };\n\n    /**\n     * mapping for special characters so they can support\n     *\n     * this dictionary is only used incase you want to bind a\n     * keyup or keydown event to one of these keys\n     *\n     * @type {Object}\n     */\n    var _KEYCODE_MAP = {\n        106: '*',\n        107: '+',\n        109: '-',\n        110: '.',\n        111 : '/',\n        186: ';',\n        187: '=',\n        188: ',',\n        189: '-',\n        190: '.',\n        191: '/',\n        192: '`',\n        219: '[',\n        220: '\\\\',\n        221: ']',\n        222: '\\''\n    };\n\n    /**\n     * this is a mapping of keys that require shift on a US keypad\n     * back to the non shift equivelents\n     *\n     * this is so you can use keyup events with these keys\n     *\n     * note that this will only work reliably on US keyboards\n     *\n     * @type {Object}\n     */\n    var _SHIFT_MAP = {\n        '~': '`',\n        '!': '1',\n        '@': '2',\n        '#': '3',\n        '$': '4',\n        '%': '5',\n        '^': '6',\n        '&': '7',\n        '*': '8',\n        '(': '9',\n        ')': '0',\n        '_': '-',\n        '+': '=',\n        ':': ';',\n        '\\\"': '\\'',\n        '<': ',',\n        '>': '.',\n        '?': '/',\n        '|': '\\\\'\n    };\n\n    /**\n     * this is a list of special strings you can use to map\n     * to modifier keys when you specify your keyboard shortcuts\n     *\n     * @type {Object}\n     */\n    var _SPECIAL_ALIASES = {\n        'option': 'alt',\n        'command': 'meta',\n        'return': 'enter',\n        'escape': 'esc',\n        'plus': '+',\n        'mod': /Mac|iPod|iPhone|iPad/.test(navigator.platform) ? 'meta' : 'ctrl'\n    };\n\n    /**\n     * variable to store the flipped version of _MAP from above\n     * needed to check if we should use keypress or not when no action\n     * is specified\n     *\n     * @type {Object|undefined}\n     */\n    var _REVERSE_MAP;\n\n    /**\n     * loop through the f keys, f1 to f19 and add them to the map\n     * programatically\n     */\n    for (var i = 1; i < 20; ++i) {\n        _MAP[111 + i] = 'f' + i;\n    }\n\n    /**\n     * loop through to map numbers on the numeric keypad\n     */\n    for (i = 0; i <= 9; ++i) {\n        _MAP[i + 96] = i;\n    }\n\n    /**\n     * cross browser add event method\n     *\n     * @param {Element|HTMLDocument} object\n     * @param {string} type\n     * @param {Function} callback\n     * @returns void\n     */\n    function _addEvent(object, type, callback) {\n        if (object.addEventListener) {\n            object.addEventListener(type, callback, false);\n            return;\n        }\n\n        object.attachEvent('on' + type, callback);\n    }\n\n    /**\n     * takes the event and returns the key character\n     *\n     * @param {Event} e\n     * @return {string}\n     */\n    function _characterFromEvent(e) {\n\n        // for keypress events we should return the character as is\n        if (e.type == 'keypress') {\n            var character = String.fromCharCode(e.which);\n\n            // if the shift key is not pressed then it is safe to assume\n            // that we want the character to be lowercase.  this means if\n            // you accidentally have caps lock on then your key bindings\n            // will continue to work\n            //\n            // the only side effect that might not be desired is if you\n            // bind something like 'A' cause you want to trigger an\n            // event when capital A is pressed caps lock will no longer\n            // trigger the event.  shift+a will though.\n            if (!e.shiftKey) {\n                character = character.toLowerCase();\n            }\n\n            return character;\n        }\n\n        // for non keypress events the special maps are needed\n        if (_MAP[e.which]) {\n            return _MAP[e.which];\n        }\n\n        if (_KEYCODE_MAP[e.which]) {\n            return _KEYCODE_MAP[e.which];\n        }\n\n        // if it is not in the special map\n\n        // with keydown and keyup events the character seems to always\n        // come in as an uppercase character whether you are pressing shift\n        // or not.  we should make sure it is always lowercase for comparisons\n        return String.fromCharCode(e.which).toLowerCase();\n    }\n\n    /**\n     * checks if two arrays are equal\n     *\n     * @param {Array} modifiers1\n     * @param {Array} modifiers2\n     * @returns {boolean}\n     */\n    function _modifiersMatch(modifiers1, modifiers2) {\n        return modifiers1.sort().join(',') === modifiers2.sort().join(',');\n    }\n\n    /**\n     * takes a key event and figures out what the modifiers are\n     *\n     * @param {Event} e\n     * @returns {Array}\n     */\n    function _eventModifiers(e) {\n        var modifiers = [];\n\n        if (e.shiftKey) {\n            modifiers.push('shift');\n        }\n\n        if (e.altKey) {\n            modifiers.push('alt');\n        }\n\n        if (e.ctrlKey) {\n            modifiers.push('ctrl');\n        }\n\n        if (e.metaKey) {\n            modifiers.push('meta');\n        }\n\n        return modifiers;\n    }\n\n    /**\n     * prevents default for this event\n     *\n     * @param {Event} e\n     * @returns void\n     */\n    function _preventDefault(e) {\n        if (e.preventDefault) {\n            e.preventDefault();\n            return;\n        }\n\n        e.returnValue = false;\n    }\n\n    /**\n     * stops propogation for this event\n     *\n     * @param {Event} e\n     * @returns void\n     */\n    function _stopPropagation(e) {\n        if (e.stopPropagation) {\n            e.stopPropagation();\n            return;\n        }\n\n        e.cancelBubble = true;\n    }\n\n    /**\n     * determines if the keycode specified is a modifier key or not\n     *\n     * @param {string} key\n     * @returns {boolean}\n     */\n    function _isModifier(key) {\n        return key == 'shift' || key == 'ctrl' || key == 'alt' || key == 'meta';\n    }\n\n    /**\n     * reverses the map lookup so that we can look for specific keys\n     * to see what can and can't use keypress\n     *\n     * @return {Object}\n     */\n    function _getReverseMap() {\n        if (!_REVERSE_MAP) {\n            _REVERSE_MAP = {};\n            for (var key in _MAP) {\n\n                // pull out the numeric keypad from here cause keypress should\n                // be able to detect the keys from the character\n                if (key > 95 && key < 112) {\n                    continue;\n                }\n\n                if (_MAP.hasOwnProperty(key)) {\n                    _REVERSE_MAP[_MAP[key]] = key;\n                }\n            }\n        }\n        return _REVERSE_MAP;\n    }\n\n    /**\n     * picks the best action based on the key combination\n     *\n     * @param {string} key - character for key\n     * @param {Array} modifiers\n     * @param {string=} action passed in\n     */\n    function _pickBestAction(key, modifiers, action) {\n\n        // if no action was picked in we should try to pick the one\n        // that we think would work best for this key\n        if (!action) {\n            action = _getReverseMap()[key] ? 'keydown' : 'keypress';\n        }\n\n        // modifier keys don't work as expected with keypress,\n        // switch to keydown\n        if (action == 'keypress' && modifiers.length) {\n            action = 'keydown';\n        }\n\n        return action;\n    }\n\n    /**\n     * Converts from a string key combination to an array\n     *\n     * @param  {string} combination like \"command+shift+l\"\n     * @return {Array}\n     */\n    function _keysFromString(combination) {\n        if (combination === '+') {\n            return ['+'];\n        }\n\n        combination = combination.replace(/\\+{2}/g, '+plus');\n        return combination.split('+');\n    }\n\n    /**\n     * Gets info for a specific key combination\n     *\n     * @param  {string} combination key combination (\"command+s\" or \"a\" or \"*\")\n     * @param  {string=} action\n     * @returns {Object}\n     */\n    function _getKeyInfo(combination, action) {\n        var keys;\n        var key;\n        var i;\n        var modifiers = [];\n\n        // take the keys from this pattern and figure out what the actual\n        // pattern is all about\n        keys = _keysFromString(combination);\n\n        for (i = 0; i < keys.length; ++i) {\n            key = keys[i];\n\n            // normalize key names\n            if (_SPECIAL_ALIASES[key]) {\n                key = _SPECIAL_ALIASES[key];\n            }\n\n            // if this is not a keypress event then we should\n            // be smart about using shift keys\n            // this will only work for US keyboards however\n            if (action && action != 'keypress' && _SHIFT_MAP[key]) {\n                key = _SHIFT_MAP[key];\n                modifiers.push('shift');\n            }\n\n            // if this key is a modifier then add it to the list of modifiers\n            if (_isModifier(key)) {\n                modifiers.push(key);\n            }\n        }\n\n        // depending on what the key combination is\n        // we will try to pick the best event for it\n        action = _pickBestAction(key, modifiers, action);\n\n        return {\n            key: key,\n            modifiers: modifiers,\n            action: action\n        };\n    }\n\n    function _belongsTo(element, ancestor) {\n        if (element === null || element === document) {\n            return false;\n        }\n\n        if (element === ancestor) {\n            return true;\n        }\n\n        return _belongsTo(element.parentNode, ancestor);\n    }\n\n    function Mousetrap(targetElement) {\n        var self = this;\n\n        targetElement = targetElement || document;\n\n        if (!(self instanceof Mousetrap)) {\n            return new Mousetrap(targetElement);\n        }\n\n        /**\n         * element to attach key events to\n         *\n         * @type {Element}\n         */\n        self.target = targetElement;\n\n        /**\n         * a list of all the callbacks setup via Mousetrap.bind()\n         *\n         * @type {Object}\n         */\n        self._callbacks = {};\n\n        /**\n         * direct map of string combinations to callbacks used for trigger()\n         *\n         * @type {Object}\n         */\n        self._directMap = {};\n\n        /**\n         * keeps track of what level each sequence is at since multiple\n         * sequences can start out with the same sequence\n         *\n         * @type {Object}\n         */\n        var _sequenceLevels = {};\n\n        /**\n         * variable to store the setTimeout call\n         *\n         * @type {null|number}\n         */\n        var _resetTimer;\n\n        /**\n         * temporary state where we will ignore the next keyup\n         *\n         * @type {boolean|string}\n         */\n        var _ignoreNextKeyup = false;\n\n        /**\n         * temporary state where we will ignore the next keypress\n         *\n         * @type {boolean}\n         */\n        var _ignoreNextKeypress = false;\n\n        /**\n         * are we currently inside of a sequence?\n         * type of action (\"keyup\" or \"keydown\" or \"keypress\") or false\n         *\n         * @type {boolean|string}\n         */\n        var _nextExpectedAction = false;\n\n        /**\n         * resets all sequence counters except for the ones passed in\n         *\n         * @param {Object} doNotReset\n         * @returns void\n         */\n        function _resetSequences(doNotReset) {\n            doNotReset = doNotReset || {};\n\n            var activeSequences = false,\n                key;\n\n            for (key in _sequenceLevels) {\n                if (doNotReset[key]) {\n                    activeSequences = true;\n                    continue;\n                }\n                _sequenceLevels[key] = 0;\n            }\n\n            if (!activeSequences) {\n                _nextExpectedAction = false;\n            }\n        }\n\n        /**\n         * finds all callbacks that match based on the keycode, modifiers,\n         * and action\n         *\n         * @param {string} character\n         * @param {Array} modifiers\n         * @param {Event|Object} e\n         * @param {string=} sequenceName - name of the sequence we are looking for\n         * @param {string=} combination\n         * @param {number=} level\n         * @returns {Array}\n         */\n        function _getMatches(character, modifiers, e, sequenceName, combination, level) {\n            var i;\n            var callback;\n            var matches = [];\n            var action = e.type;\n\n            // if there are no events related to this keycode\n            if (!self._callbacks[character]) {\n                return [];\n            }\n\n            // if a modifier key is coming up on its own we should allow it\n            if (action == 'keyup' && _isModifier(character)) {\n                modifiers = [character];\n            }\n\n            // loop through all callbacks for the key that was pressed\n            // and see if any of them match\n            for (i = 0; i < self._callbacks[character].length; ++i) {\n                callback = self._callbacks[character][i];\n\n                // if a sequence name is not specified, but this is a sequence at\n                // the wrong level then move onto the next match\n                if (!sequenceName && callback.seq && _sequenceLevels[callback.seq] != callback.level) {\n                    continue;\n                }\n\n                // if the action we are looking for doesn't match the action we got\n                // then we should keep going\n                if (action != callback.action) {\n                    continue;\n                }\n\n                // if this is a keypress event and the meta key and control key\n                // are not pressed that means that we need to only look at the\n                // character, otherwise check the modifiers as well\n                //\n                // chrome will not fire a keypress if meta or control is down\n                // safari will fire a keypress if meta or meta+shift is down\n                // firefox will fire a keypress if meta or control is down\n                if ((action == 'keypress' && !e.metaKey && !e.ctrlKey) || _modifiersMatch(modifiers, callback.modifiers)) {\n\n                    // when you bind a combination or sequence a second time it\n                    // should overwrite the first one.  if a sequenceName or\n                    // combination is specified in this call it does just that\n                    //\n                    // @todo make deleting its own method?\n                    var deleteCombo = !sequenceName && callback.combo == combination;\n                    var deleteSequence = sequenceName && callback.seq == sequenceName && callback.level == level;\n                    if (deleteCombo || deleteSequence) {\n                        self._callbacks[character].splice(i, 1);\n                    }\n\n                    matches.push(callback);\n                }\n            }\n\n            return matches;\n        }\n\n        /**\n         * actually calls the callback function\n         *\n         * if your callback function returns false this will use the jquery\n         * convention - prevent default and stop propogation on the event\n         *\n         * @param {Function} callback\n         * @param {Event} e\n         * @returns void\n         */\n        function _fireCallback(callback, e, combo, sequence) {\n\n            // if this event should not happen stop here\n            if (self.stopCallback(e, e.target || e.srcElement, combo, sequence)) {\n                return;\n            }\n\n            if (callback(e, combo) === false) {\n                _preventDefault(e);\n                _stopPropagation(e);\n            }\n        }\n\n        /**\n         * handles a character key event\n         *\n         * @param {string} character\n         * @param {Array} modifiers\n         * @param {Event} e\n         * @returns void\n         */\n        self._handleKey = function(character, modifiers, e) {\n            var callbacks = _getMatches(character, modifiers, e);\n            var i;\n            var doNotReset = {};\n            var maxLevel = 0;\n            var processedSequenceCallback = false;\n\n            // Calculate the maxLevel for sequences so we can only execute the longest callback sequence\n            for (i = 0; i < callbacks.length; ++i) {\n                if (callbacks[i].seq) {\n                    maxLevel = Math.max(maxLevel, callbacks[i].level);\n                }\n            }\n\n            // loop through matching callbacks for this key event\n            for (i = 0; i < callbacks.length; ++i) {\n\n                // fire for all sequence callbacks\n                // this is because if for example you have multiple sequences\n                // bound such as \"g i\" and \"g t\" they both need to fire the\n                // callback for matching g cause otherwise you can only ever\n                // match the first one\n                if (callbacks[i].seq) {\n\n                    // only fire callbacks for the maxLevel to prevent\n                    // subsequences from also firing\n                    //\n                    // for example 'a option b' should not cause 'option b' to fire\n                    // even though 'option b' is part of the other sequence\n                    //\n                    // any sequences that do not match here will be discarded\n                    // below by the _resetSequences call\n                    if (callbacks[i].level != maxLevel) {\n                        continue;\n                    }\n\n                    processedSequenceCallback = true;\n\n                    // keep a list of which sequences were matches for later\n                    doNotReset[callbacks[i].seq] = 1;\n                    _fireCallback(callbacks[i].callback, e, callbacks[i].combo, callbacks[i].seq);\n                    continue;\n                }\n\n                // if there were no sequence matches but we are still here\n                // that means this is a regular match so we should fire that\n                if (!processedSequenceCallback) {\n                    _fireCallback(callbacks[i].callback, e, callbacks[i].combo);\n                }\n            }\n\n            // if the key you pressed matches the type of sequence without\n            // being a modifier (ie \"keyup\" or \"keypress\") then we should\n            // reset all sequences that were not matched by this event\n            //\n            // this is so, for example, if you have the sequence \"h a t\" and you\n            // type \"h e a r t\" it does not match.  in this case the \"e\" will\n            // cause the sequence to reset\n            //\n            // modifier keys are ignored because you can have a sequence\n            // that contains modifiers such as \"enter ctrl+space\" and in most\n            // cases the modifier key will be pressed before the next key\n            //\n            // also if you have a sequence such as \"ctrl+b a\" then pressing the\n            // \"b\" key will trigger a \"keypress\" and a \"keydown\"\n            //\n            // the \"keydown\" is expected when there is a modifier, but the\n            // \"keypress\" ends up matching the _nextExpectedAction since it occurs\n            // after and that causes the sequence to reset\n            //\n            // we ignore keypresses in a sequence that directly follow a keydown\n            // for the same character\n            var ignoreThisKeypress = e.type == 'keypress' && _ignoreNextKeypress;\n            if (e.type == _nextExpectedAction && !_isModifier(character) && !ignoreThisKeypress) {\n                _resetSequences(doNotReset);\n            }\n\n            _ignoreNextKeypress = processedSequenceCallback && e.type == 'keydown';\n        };\n\n        /**\n         * handles a keydown event\n         *\n         * @param {Event} e\n         * @returns void\n         */\n        function _handleKeyEvent(e) {\n\n            // normalize e.which for key events\n            // @see http://stackoverflow.com/questions/4285627/javascript-keycode-vs-charcode-utter-confusion\n            if (typeof e.which !== 'number') {\n                e.which = e.keyCode;\n            }\n\n            var character = _characterFromEvent(e);\n\n            // no character found then stop\n            if (!character) {\n                return;\n            }\n\n            // need to use === for the character check because the character can be 0\n            if (e.type == 'keyup' && _ignoreNextKeyup === character) {\n                _ignoreNextKeyup = false;\n                return;\n            }\n\n            self.handleKey(character, _eventModifiers(e), e);\n        }\n\n        /**\n         * called to set a 1 second timeout on the specified sequence\n         *\n         * this is so after each key press in the sequence you have 1 second\n         * to press the next key before you have to start over\n         *\n         * @returns void\n         */\n        function _resetSequenceTimer() {\n            clearTimeout(_resetTimer);\n            _resetTimer = setTimeout(_resetSequences, 1000);\n        }\n\n        /**\n         * binds a key sequence to an event\n         *\n         * @param {string} combo - combo specified in bind call\n         * @param {Array} keys\n         * @param {Function} callback\n         * @param {string=} action\n         * @returns void\n         */\n        function _bindSequence(combo, keys, callback, action) {\n\n            // start off by adding a sequence level record for this combination\n            // and setting the level to 0\n            _sequenceLevels[combo] = 0;\n\n            /**\n             * callback to increase the sequence level for this sequence and reset\n             * all other sequences that were active\n             *\n             * @param {string} nextAction\n             * @returns {Function}\n             */\n            function _increaseSequence(nextAction) {\n                return function() {\n                    _nextExpectedAction = nextAction;\n                    ++_sequenceLevels[combo];\n                    _resetSequenceTimer();\n                };\n            }\n\n            /**\n             * wraps the specified callback inside of another function in order\n             * to reset all sequence counters as soon as this sequence is done\n             *\n             * @param {Event} e\n             * @returns void\n             */\n            function _callbackAndReset(e) {\n                _fireCallback(callback, e, combo);\n\n                // we should ignore the next key up if the action is key down\n                // or keypress.  this is so if you finish a sequence and\n                // release the key the final key will not trigger a keyup\n                if (action !== 'keyup') {\n                    _ignoreNextKeyup = _characterFromEvent(e);\n                }\n\n                // weird race condition if a sequence ends with the key\n                // another sequence begins with\n                setTimeout(_resetSequences, 10);\n            }\n\n            // loop through keys one at a time and bind the appropriate callback\n            // function.  for any key leading up to the final one it should\n            // increase the sequence. after the final, it should reset all sequences\n            //\n            // if an action is specified in the original bind call then that will\n            // be used throughout.  otherwise we will pass the action that the\n            // next key in the sequence should match.  this allows a sequence\n            // to mix and match keypress and keydown events depending on which\n            // ones are better suited to the key provided\n            for (var i = 0; i < keys.length; ++i) {\n                var isFinal = i + 1 === keys.length;\n                var wrappedCallback = isFinal ? _callbackAndReset : _increaseSequence(action || _getKeyInfo(keys[i + 1]).action);\n                _bindSingle(keys[i], wrappedCallback, action, combo, i);\n            }\n        }\n\n        /**\n         * binds a single keyboard combination\n         *\n         * @param {string} combination\n         * @param {Function} callback\n         * @param {string=} action\n         * @param {string=} sequenceName - name of sequence if part of sequence\n         * @param {number=} level - what part of the sequence the command is\n         * @returns void\n         */\n        function _bindSingle(combination, callback, action, sequenceName, level) {\n\n            // store a direct mapped reference for use with Mousetrap.trigger\n            self._directMap[combination + ':' + action] = callback;\n\n            // make sure multiple spaces in a row become a single space\n            combination = combination.replace(/\\s+/g, ' ');\n\n            var sequence = combination.split(' ');\n            var info;\n\n            // if this pattern is a sequence of keys then run through this method\n            // to reprocess each pattern one key at a time\n            if (sequence.length > 1) {\n                _bindSequence(combination, sequence, callback, action);\n                return;\n            }\n\n            info = _getKeyInfo(combination, action);\n\n            // make sure to initialize array if this is the first time\n            // a callback is added for this key\n            self._callbacks[info.key] = self._callbacks[info.key] || [];\n\n            // remove an existing match if there is one\n            _getMatches(info.key, info.modifiers, {type: info.action}, sequenceName, combination, level);\n\n            // add this call back to the array\n            // if it is a sequence put it at the beginning\n            // if not put it at the end\n            //\n            // this is important because the way these are processed expects\n            // the sequence ones to come first\n            self._callbacks[info.key][sequenceName ? 'unshift' : 'push']({\n                callback: callback,\n                modifiers: info.modifiers,\n                action: info.action,\n                seq: sequenceName,\n                level: level,\n                combo: combination\n            });\n        }\n\n        /**\n         * binds multiple combinations to the same callback\n         *\n         * @param {Array} combinations\n         * @param {Function} callback\n         * @param {string|undefined} action\n         * @returns void\n         */\n        self._bindMultiple = function(combinations, callback, action) {\n            for (var i = 0; i < combinations.length; ++i) {\n                _bindSingle(combinations[i], callback, action);\n            }\n        };\n\n        // start!\n        _addEvent(targetElement, 'keypress', _handleKeyEvent);\n        _addEvent(targetElement, 'keydown', _handleKeyEvent);\n        _addEvent(targetElement, 'keyup', _handleKeyEvent);\n    }\n\n    /**\n     * binds an event to mousetrap\n     *\n     * can be a single key, a combination of keys separated with +,\n     * an array of keys, or a sequence of keys separated by spaces\n     *\n     * be sure to list the modifier keys first to make sure that the\n     * correct key ends up getting bound (the last key in the pattern)\n     *\n     * @param {string|Array} keys\n     * @param {Function} callback\n     * @param {string=} action - 'keypress', 'keydown', or 'keyup'\n     * @returns void\n     */\n    Mousetrap.prototype.bind = function(keys, callback, action) {\n        var self = this;\n        keys = keys instanceof Array ? keys : [keys];\n        self._bindMultiple.call(self, keys, callback, action);\n        return self;\n    };\n\n    /**\n     * unbinds an event to mousetrap\n     *\n     * the unbinding sets the callback function of the specified key combo\n     * to an empty function and deletes the corresponding key in the\n     * _directMap dict.\n     *\n     * TODO: actually remove this from the _callbacks dictionary instead\n     * of binding an empty function\n     *\n     * the keycombo+action has to be exactly the same as\n     * it was defined in the bind method\n     *\n     * @param {string|Array} keys\n     * @param {string} action\n     * @returns void\n     */\n    Mousetrap.prototype.unbind = function(keys, action) {\n        var self = this;\n        return self.bind.call(self, keys, function() {}, action);\n    };\n\n    /**\n     * triggers an event that has already been bound\n     *\n     * @param {string} keys\n     * @param {string=} action\n     * @returns void\n     */\n    Mousetrap.prototype.trigger = function(keys, action) {\n        var self = this;\n        if (self._directMap[keys + ':' + action]) {\n            self._directMap[keys + ':' + action]({}, keys);\n        }\n        return self;\n    };\n\n    /**\n     * resets the library back to its initial state.  this is useful\n     * if you want to clear out the current keyboard shortcuts and bind\n     * new ones - for example if you switch to another page\n     *\n     * @returns void\n     */\n    Mousetrap.prototype.reset = function() {\n        var self = this;\n        self._callbacks = {};\n        self._directMap = {};\n        return self;\n    };\n\n    /**\n     * should we stop this event before firing off callbacks\n     *\n     * @param {Event} e\n     * @param {Element} element\n     * @return {boolean}\n     */\n    Mousetrap.prototype.stopCallback = function(e, element) {\n        var self = this;\n\n        // if the element has the class \"mousetrap\" then no need to stop\n        if ((' ' + element.className + ' ').indexOf(' mousetrap ') > -1) {\n            return false;\n        }\n\n        if (_belongsTo(element, self.target)) {\n            return false;\n        }\n\n        // stop for input, select, and textarea\n        return element.tagName == 'INPUT' || element.tagName == 'SELECT' || element.tagName == 'TEXTAREA' || element.isContentEditable;\n    };\n\n    /**\n     * exposes _handleKey publicly so it can be overwritten by extensions\n     */\n    Mousetrap.prototype.handleKey = function() {\n        var self = this;\n        return self._handleKey.apply(self, arguments);\n    };\n\n    /**\n     * allow custom key mappings\n     */\n    Mousetrap.addKeycodes = function(object) {\n        for (var key in object) {\n            if (object.hasOwnProperty(key)) {\n                _MAP[key] = object[key];\n            }\n        }\n        _REVERSE_MAP = null;\n    };\n\n    /**\n     * Init the global mousetrap functions\n     *\n     * This method is needed to allow the global mousetrap functions to work\n     * now that mousetrap is a constructor function.\n     */\n    Mousetrap.init = function() {\n        var documentMousetrap = Mousetrap(document);\n        for (var method in documentMousetrap) {\n            if (method.charAt(0) !== '_') {\n                Mousetrap[method] = (function(method) {\n                    return function() {\n                        return documentMousetrap[method].apply(documentMousetrap, arguments);\n                    };\n                } (method));\n            }\n        }\n    };\n\n    Mousetrap.init();\n\n    // expose mousetrap to the global object\n    window.Mousetrap = Mousetrap;\n\n    // expose as a common js module\n    if (typeof module !== 'undefined' && module.exports) {\n        module.exports = Mousetrap;\n    }\n\n    // expose mousetrap as an AMD module\n    if (typeof define === 'function' && define.amd) {\n        define(function() {\n            return Mousetrap;\n        });\n    }\n}) (typeof window !== 'undefined' ? window : null, typeof  window !== 'undefined' ? document : null);\n"
  },
  {
    "path": "flowable-ui-web/modeler/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": "flowable-ui-web/modeler/editor-app/libs/prototype-1.6.1.js",
    "content": "/*  Prototype JavaScript framework, version 1.6.1\n *  (c) 2005-2009 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.6.1',\n\n    Browser: (function(){\n        var ua = navigator.userAgent;\n        var isOpera = Object.prototype.toString.call(window.opera) == '[object Opera]';\n        return {\n            IE:             !!window.attachEvent && !isOpera,\n            Opera:          isOpera,\n            WebKit:         ua.indexOf('AppleWebKit/') > -1,\n            Gecko:          ua.indexOf('Gecko') > -1 && ua.indexOf('KHTML') === -1,\n            MobileSafari:   /Apple.*Mobile.*Safari/.test(ua)\n        }\n    })(),\n\n    BrowserFeatures: {\n        XPath: !!document.evaluate,\n        SelectorsAPI: !!document.querySelector,\n        ElementExtensions: (function() {\n            var constructor = window.Element || window.HTMLElement;\n            return !!(constructor && constructor.prototype);\n        })(),\n        SpecificElementExtensions: (function() {\n            if (typeof window.HTMLDivElement !== 'undefined')\n                return true;\n\n            var div = document.createElement('div');\n            var form = document.createElement('form');\n            var isSupported = false;\n\n            if (div['__proto__'] && (div['__proto__'] !== form['__proto__'])) {\n                isSupported = true;\n            }\n\n            div = form = null;\n\n            return isSupported;\n        })()\n    },\n\n    ScriptFragment: '<script[^>]*>([\\\\S\\\\s]*?)<\\/script>',\n    JSONFilter: /^\\/\\*-secure-([\\s\\S]*)\\*\\/\\s*$/,\n\n    emptyFunction: function() { },\n    K: function(x) { return x }\n};\n\nif (Prototype.Browser.MobileSafari)\n    Prototype.BrowserFeatures.SpecificElementExtensions = false;\n\n\nvar Abstract = { };\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/* Based on Alex Arnell's inheritance implementation. */\n\nvar Class = (function() {\n    function subclass() {};\n    function create() {\n        var parent = null, properties = $A(arguments);\n        if (Object.isFunction(properties[0]))\n            parent = properties.shift();\n\n        function klass() {\n            this.initialize.apply(this, arguments);\n        }\n\n        Object.extend(klass, Class.Methods);\n        klass.superclass = parent;\n        klass.subclasses = [];\n\n        if (parent) {\n            subclass.prototype = parent.prototype;\n            klass.prototype = new subclass;\n            parent.subclasses.push(klass);\n        }\n\n        for (var i = 0; i < properties.length; i++)\n            klass.addMethods(properties[i]);\n\n        if (!klass.prototype.initialize)\n            klass.prototype.initialize = Prototype.emptyFunction;\n\n        klass.prototype.constructor = klass;\n        return klass;\n    }\n\n    function addMethods(source) {\n        var ancestor   = this.superclass && this.superclass.prototype;\n        var properties = Object.keys(source);\n\n        if (!Object.keys({ toString: true }).length) {\n            if (source.toString != Object.prototype.toString)\n                properties.push(\"toString\");\n            if (source.valueOf != Object.prototype.valueOf)\n                properties.push(\"valueOf\");\n        }\n\n        for (var i = 0, length = properties.length; i < length; i++) {\n            var property = properties[i], value = source[property];\n            if (ancestor && Object.isFunction(value) &&\n                value.argumentNames().first() == \"$super\") {\n                var method = value;\n                value = (function(m) {\n                    return function() { return ancestor[m].apply(this, arguments); };\n                })(property).wrap(method);\n\n                value.valueOf = method.valueOf.bind(method);\n                value.toString = method.toString.bind(method);\n            }\n            this.prototype[property] = value;\n        }\n\n        return this;\n    }\n\n    return {\n        create: create,\n        Methods: {\n            addMethods: addMethods\n        }\n    };\n})();\n(function() {\n\n    var _toString = Object.prototype.toString;\n\n    function extend(destination, source) {\n        for (var property in source)\n            destination[property] = source[property];\n        return destination;\n    }\n\n    function inspect(object) {\n        try {\n            if (isUndefined(object)) return 'undefined';\n            if (object === null) return 'null';\n            return object.inspect ? object.inspect() : String(object);\n        } catch (e) {\n            if (e instanceof RangeError) return '...';\n            throw e;\n        }\n    }\n\n    function toJSON(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\n        if (object === null) return 'null';\n        if (object.toJSON) return object.toJSON();\n        if (isElement(object)) return;\n\n        var results = [];\n        for (var property in object) {\n            var value = toJSON(object[property]);\n            if (!isUndefined(value))\n                results.push(property.toJSON() + ': ' + value);\n        }\n\n        return '{' + results.join(', ') + '}';\n    }\n\n    function toQueryString(object) {\n        return $H(object).toQueryString();\n    }\n\n    function toHTML(object) {\n        return object && object.toHTML ? object.toHTML() : String.interpret(object);\n    }\n\n    function keys(object) {\n        var results = [];\n        for (var property in object)\n            results.push(property);\n        return results;\n    }\n\n    function values(object) {\n        var results = [];\n        for (var property in object)\n            results.push(object[property]);\n        return results;\n    }\n\n    function clone(object) {\n        return extend({ }, object);\n    }\n\n    function isElement(object) {\n        return !!(object && object.nodeType == 1);\n    }\n\n    function isArray(object) {\n        return _toString.call(object) == \"[object Array]\";\n    }\n\n\n    function isHash(object) {\n        return object instanceof Hash;\n    }\n\n    function isFunction(object) {\n        return typeof object === \"function\";\n    }\n\n    function isString(object) {\n        return _toString.call(object) == \"[object String]\";\n    }\n\n    function isNumber(object) {\n        return _toString.call(object) == \"[object Number]\";\n    }\n\n    function isUndefined(object) {\n        return typeof object === \"undefined\";\n    }\n\n    extend(Object, {\n        extend:        extend,\n        inspect:       inspect,\n        toJSON:        toJSON,\n        toQueryString: toQueryString,\n        toHTML:        toHTML,\n        keys:          keys,\n        values:        values,\n        clone:         clone,\n        isElement:     isElement,\n        isArray:       isArray,\n        isHash:        isHash,\n        isFunction:    isFunction,\n        isString:      isString,\n        isNumber:      isNumber,\n        isUndefined:   isUndefined\n    });\n})();\nObject.extend(Function.prototype, (function() {\n    var slice = Array.prototype.slice;\n\n    function update(array, args) {\n        var arrayLength = array.length, length = args.length;\n        while (length--) array[arrayLength + length] = args[length];\n        return array;\n    }\n\n    function merge(array, args) {\n        array = slice.call(array, 0);\n        return update(array, args);\n    }\n\n    function argumentNames() {\n        var names = this.toString().match(/^[\\s\\(]*function[^(]*\\(([^)]*)\\)/)[1]\n            .replace(/\\/\\/.*?[\\r\\n]|\\/\\*(?:.|[\\r\\n])*?\\*\\//g, '')\n            .replace(/\\s+/g, '').split(',');\n        return names.length == 1 && !names[0] ? [] : names;\n    }\n\n    function bind(context) {\n        if (arguments.length < 2 && Object.isUndefined(arguments[0])) return this;\n        var __method = this, args = slice.call(arguments, 1);\n        return function() {\n            var a = merge(args, arguments);\n            return __method.apply(context, a);\n        }\n    }\n\n    function bindAsEventListener(context) {\n        var __method = this, args = slice.call(arguments, 1);\n        return function(event) {\n            var a = update([event || window.event], args);\n            return __method.apply(context, a);\n        }\n    }\n\n    function curry() {\n        if (!arguments.length) return this;\n        var __method = this, args = slice.call(arguments, 0);\n        return function() {\n            var a = merge(args, arguments);\n            return __method.apply(this, a);\n        }\n    }\n\n    function delay(timeout) {\n        var __method = this, args = slice.call(arguments, 1);\n        timeout = timeout * 1000\n        return window.setTimeout(function() {\n            return __method.apply(__method, args);\n        }, timeout);\n    }\n\n    function defer() {\n        var args = update([0.01], arguments);\n        return this.delay.apply(this, args);\n    }\n\n    function wrap(wrapper) {\n        var __method = this;\n        return function() {\n            var a = update([__method.bind(this)], arguments);\n            return wrapper.apply(this, a);\n        }\n    }\n\n    function methodize() {\n        if (this._methodized) return this._methodized;\n        var __method = this;\n        return this._methodized = function() {\n            var a = update([this], arguments);\n            return __method.apply(null, a);\n        };\n    }\n\n    return {\n        argumentNames:       argumentNames,\n        bind:                bind,\n        bindAsEventListener: bindAsEventListener,\n        curry:               curry,\n        delay:               delay,\n        defer:               defer,\n        wrap:                wrap,\n        methodize:           methodize\n    }\n})());\n\n\nDate.prototype.toJSON = function() {\n    return '\"' + this.getUTCFullYear() + '-' +\n        (this.getUTCMonth() + 1).toPaddedString(2) + '-' +\n        this.getUTCDate().toPaddedString(2) + 'T' +\n        this.getUTCHours().toPaddedString(2) + ':' +\n        this.getUTCMinutes().toPaddedString(2) + ':' +\n        this.getUTCSeconds().toPaddedString(2) + 'Z\"';\n};\n\n\nRegExp.prototype.match = RegExp.prototype.test;\n\nRegExp.escape = function(str) {\n    return String(str).replace(/([.*+?^=!:${}()|[\\]\\/\\\\])/g, '\\\\$1');\n};\nvar PeriodicalExecuter = Class.create({\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    execute: function() {\n        this.callback(this);\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.execute();\n                this.currentlyExecuting = false;\n            } catch(e) {\n                this.currentlyExecuting = false;\n                throw e;\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, (function() {\n\n    function prepareReplacement(replacement) {\n        if (Object.isFunction(replacement)) return replacement;\n        var template = new Template(replacement);\n        return function(match) { return template.evaluate(match) };\n    }\n\n    function gsub(pattern, replacement) {\n        var result = '', source = this, match;\n        replacement = prepareReplacement(replacement);\n\n        if (Object.isString(pattern))\n            pattern = RegExp.escape(pattern);\n\n        if (!(pattern.length || pattern.source)) {\n            replacement = replacement('');\n            return replacement + source.split('').join(replacement) + replacement;\n        }\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    function sub(pattern, replacement, count) {\n        replacement = prepareReplacement(replacement);\n        count = Object.isUndefined(count) ? 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    function scan(pattern, iterator) {\n        this.gsub(pattern, iterator);\n        return String(this);\n    }\n\n    function truncate(length, truncation) {\n        length = length || 30;\n        truncation = Object.isUndefined(truncation) ? '...' : truncation;\n        return this.length > length ?\n            this.slice(0, length - truncation.length) + truncation : String(this);\n    }\n\n    function strip() {\n        return this.replace(/^\\s+/, '').replace(/\\s+$/, '');\n    }\n\n    function stripTags() {\n        return this.replace(/<\\w+(\\s+(\"[^\"]*\"|'[^']*'|[^>])+)?>|<\\/\\w+>/gi, '');\n    }\n\n    function stripScripts() {\n        return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), '');\n    }\n\n    function extractScripts() {\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    function evalScripts() {\n        return this.extractScripts().map(function(script) { return eval(script) });\n    }\n\n    function escapeHTML() {\n        return this.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;');\n    }\n\n    function unescapeHTML() {\n        return this.stripTags().replace(/&lt;/g,'<').replace(/&gt;/g,'>').replace(/&amp;/g,'&');\n    }\n\n\n    function toQueryParams(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 (!Object.isArray(hash[key])) hash[key] = [hash[key]];\n                    hash[key].push(value);\n                }\n                else hash[key] = value;\n            }\n            return hash;\n        });\n    }\n\n    function toArray() {\n        return this.split('');\n    }\n\n    function succ() {\n        return this.slice(0, this.length - 1) +\n            String.fromCharCode(this.charCodeAt(this.length - 1) + 1);\n    }\n\n    function times(count) {\n        return count < 1 ? '' : new Array(count + 1).join(this);\n    }\n\n    function camelize() {\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    function capitalize() {\n        return this.charAt(0).toUpperCase() + this.substring(1).toLowerCase();\n    }\n\n    function underscore() {\n        return this.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\n    function dasherize() {\n        return this.replace(/_/g, '-');\n    }\n\n    function inspect(useDoubleQuotes) {\n        var escapedString = this.replace(/[\\x00-\\x1f\\\\]/g, function(character) {\n            if (character in String.specialChar) {\n                return String.specialChar[character];\n            }\n            return '\\\\u00' + character.charCodeAt().toPaddedString(2, 16);\n        });\n        if (useDoubleQuotes) return '\"' + escapedString.replace(/\"/g, '\\\\\"') + '\"';\n        return \"'\" + escapedString.replace(/'/g, '\\\\\\'') + \"'\";\n    }\n\n    function toJSON() {\n        return this.inspect(true);\n    }\n\n    function unfilterJSON(filter) {\n        return this.replace(filter || Prototype.JSONFilter, '$1');\n    }\n\n    function isJSON() {\n        var str = this;\n        if (str.blank()) return false;\n        str = this.replace(/\\\\./g, '@').replace(/\"[^\"\\\\\\n\\r]*\"/g, '');\n        return (/^[,:{}\\[\\]0-9.\\-+Eaeflnr-u \\n\\r\\t]*$/).test(str);\n    }\n\n    function evalJSON(sanitize) {\n        var json = this.unfilterJSON();\n        try {\n            if (!sanitize || json.isJSON()) return eval('(' + json + ')');\n        } catch (e) { }\n        throw new SyntaxError('Badly formed JSON string: ' + this.inspect());\n    }\n\n    function include(pattern) {\n        return this.indexOf(pattern) > -1;\n    }\n\n    function startsWith(pattern) {\n        return this.indexOf(pattern) === 0;\n    }\n\n    function endsWith(pattern) {\n        var d = this.length - pattern.length;\n        return d >= 0 && this.lastIndexOf(pattern) === d;\n    }\n\n    function empty() {\n        return this == '';\n    }\n\n    function blank() {\n        return /^\\s*$/.test(this);\n    }\n\n    function interpolate(object, pattern) {\n        return new Template(this, pattern).evaluate(object);\n    }\n\n    return {\n        gsub:           gsub,\n        sub:            sub,\n        scan:           scan,\n        truncate:       truncate,\n        strip:          String.prototype.trim ? String.prototype.trim : strip,\n        stripTags:      stripTags,\n        stripScripts:   stripScripts,\n        extractScripts: extractScripts,\n        evalScripts:    evalScripts,\n        escapeHTML:     escapeHTML,\n        unescapeHTML:   unescapeHTML,\n        toQueryParams:  toQueryParams,\n        parseQuery:     toQueryParams,\n        toArray:        toArray,\n        succ:           succ,\n        times:          times,\n        camelize:       camelize,\n        capitalize:     capitalize,\n        underscore:     underscore,\n        dasherize:      dasherize,\n        inspect:        inspect,\n        toJSON:         toJSON,\n        unfilterJSON:   unfilterJSON,\n        isJSON:         isJSON,\n        evalJSON:       evalJSON,\n        include:        include,\n        startsWith:     startsWith,\n        endsWith:       endsWith,\n        empty:          empty,\n        blank:          blank,\n        interpolate:    interpolate\n    };\n})());\n\nvar Template = Class.create({\n    initialize: function(template, pattern) {\n        this.template = template.toString();\n        this.pattern = pattern || Template.Pattern;\n    },\n\n    evaluate: function(object) {\n        if (object && Object.isFunction(object.toTemplateReplacements))\n            object = object.toTemplateReplacements();\n\n        return this.template.gsub(this.pattern, function(match) {\n            if (object == null) return (match[1] + '');\n\n            var before = match[1] || '';\n            if (before == '\\\\') return match[2];\n\n            var ctx = object, expr = match[3];\n            var pattern = /^([^.[]+|\\[((?:.*?[^\\\\])?)\\])(\\.|\\[|$)/;\n            match = pattern.exec(expr);\n            if (match == null) return before;\n\n            while (match != null) {\n                var comp = match[1].startsWith('[') ? match[2].replace(/\\\\\\\\]/g, ']') : match[1];\n                ctx = ctx[comp];\n                if (null == ctx || '' == match[3]) break;\n                expr = expr.substring('[' == match[3] ? match[1].length : match[0].length);\n                match = pattern.exec(expr);\n            }\n\n            return before + String.interpret(ctx);\n        });\n    }\n});\nTemplate.Pattern = /(^|.|\\r|\\n)(#\\{(.*?)\\})/;\n\nvar $break = { };\n\nvar Enumerable = (function() {\n    function each(iterator, context) {\n        var index = 0;\n        try {\n            this._each(function(value) {\n                iterator.call(context, value, index++);\n            });\n        } catch (e) {\n            if (e != $break) throw e;\n        }\n        return this;\n    }\n\n    function eachSlice(number, iterator, context) {\n        var index = -number, slices = [], array = this.toArray();\n        if (number < 1) return array;\n        while ((index += number) < array.length)\n            slices.push(array.slice(index, index+number));\n        return slices.collect(iterator, context);\n    }\n\n    function all(iterator, context) {\n        iterator = iterator || Prototype.K;\n        var result = true;\n        this.each(function(value, index) {\n            result = result && !!iterator.call(context, value, index);\n            if (!result) throw $break;\n        });\n        return result;\n    }\n\n    function any(iterator, context) {\n        iterator = iterator || Prototype.K;\n        var result = false;\n        this.each(function(value, index) {\n            if (result = !!iterator.call(context, value, index))\n                throw $break;\n        });\n        return result;\n    }\n\n    function collect(iterator, context) {\n        iterator = iterator || Prototype.K;\n        var results = [];\n        this.each(function(value, index) {\n            results.push(iterator.call(context, value, index));\n        });\n        return results;\n    }\n\n    function detect(iterator, context) {\n        var result;\n        this.each(function(value, index) {\n            if (iterator.call(context, value, index)) {\n                result = value;\n                throw $break;\n            }\n        });\n        return result;\n    }\n\n    function findAll(iterator, context) {\n        var results = [];\n        this.each(function(value, index) {\n            if (iterator.call(context, value, index))\n                results.push(value);\n        });\n        return results;\n    }\n\n    function grep(filter, iterator, context) {\n        iterator = iterator || Prototype.K;\n        var results = [];\n\n        if (Object.isString(filter))\n            filter = new RegExp(RegExp.escape(filter));\n\n        this.each(function(value, index) {\n            if (filter.match(value))\n                results.push(iterator.call(context, value, index));\n        });\n        return results;\n    }\n\n    function include(object) {\n        if (Object.isFunction(this.indexOf))\n            if (this.indexOf(object) != -1) return true;\n\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    function inGroupsOf(number, fillWith) {\n        fillWith = Object.isUndefined(fillWith) ? null : fillWith;\n        return this.eachSlice(number, function(slice) {\n            while(slice.length < number) slice.push(fillWith);\n            return slice;\n        });\n    }\n\n    function inject(memo, iterator, context) {\n        this.each(function(value, index) {\n            memo = iterator.call(context, memo, value, index);\n        });\n        return memo;\n    }\n\n    function invoke(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    function max(iterator, context) {\n        iterator = iterator || Prototype.K;\n        var result;\n        this.each(function(value, index) {\n            value = iterator.call(context, value, index);\n            if (result == null || value >= result)\n                result = value;\n        });\n        return result;\n    }\n\n    function min(iterator, context) {\n        iterator = iterator || Prototype.K;\n        var result;\n        this.each(function(value, index) {\n            value = iterator.call(context, value, index);\n            if (result == null || value < result)\n                result = value;\n        });\n        return result;\n    }\n\n    function partition(iterator, context) {\n        iterator = iterator || Prototype.K;\n        var trues = [], falses = [];\n        this.each(function(value, index) {\n            (iterator.call(context, value, index) ?\n                trues : falses).push(value);\n        });\n        return [trues, falses];\n    }\n\n    function pluck(property) {\n        var results = [];\n        this.each(function(value) {\n            results.push(value[property]);\n        });\n        return results;\n    }\n\n    function reject(iterator, context) {\n        var results = [];\n        this.each(function(value, index) {\n            if (!iterator.call(context, value, index))\n                results.push(value);\n        });\n        return results;\n    }\n\n    function sortBy(iterator, context) {\n        return this.map(function(value, index) {\n            return {\n                value: value,\n                criteria: iterator.call(context, value, index)\n            };\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    function toArray() {\n        return this.map();\n    }\n\n    function zip() {\n        var iterator = Prototype.K, args = $A(arguments);\n        if (Object.isFunction(args.last()))\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    function size() {\n        return this.toArray().length;\n    }\n\n    function inspect() {\n        return '#<Enumerable:' + this.toArray().inspect() + '>';\n    }\n\n\n\n\n\n\n\n\n\n    return {\n        each:       each,\n        eachSlice:  eachSlice,\n        all:        all,\n        every:      all,\n        any:        any,\n        some:       any,\n        collect:    collect,\n        map:        collect,\n        detect:     detect,\n        findAll:    findAll,\n        select:     findAll,\n        filter:     findAll,\n        grep:       grep,\n        include:    include,\n        member:     include,\n        inGroupsOf: inGroupsOf,\n        inject:     inject,\n        invoke:     invoke,\n        max:        max,\n        min:        min,\n        partition:  partition,\n        pluck:      pluck,\n        reject:     reject,\n        sortBy:     sortBy,\n        toArray:    toArray,\n        entries:    toArray,\n        zip:        zip,\n        size:       size,\n        inspect:    inspect,\n        find:       detect\n    };\n})();\nfunction $A(iterable) {\n    if (!iterable) return [];\n    if ('toArray' in Object(iterable)) return iterable.toArray();\n    var length = iterable.length || 0, results = new Array(length);\n    while (length--) results[length] = iterable[length];\n    return results;\n}\n\nfunction $w(string) {\n    if (!Object.isString(string)) return [];\n    string = string.strip();\n    return string ? string.split(/\\s+/) : [];\n}\n\nArray.from = $A;\n\n\n(function() {\n    var arrayProto = Array.prototype,\n        slice = arrayProto.slice,\n        _each = arrayProto.forEach; // use native browser JS 1.6 implementation if available\n\n    function each(iterator) {\n        for (var i = 0, length = this.length; i < length; i++)\n            iterator(this[i]);\n    }\n    if (!_each) _each = each;\n\n    function clear() {\n        this.length = 0;\n        return this;\n    }\n\n    function first() {\n        return this[0];\n    }\n\n    function last() {\n        return this[this.length - 1];\n    }\n\n    function compact() {\n        return this.select(function(value) {\n            return value != null;\n        });\n    }\n\n    function flatten() {\n        return this.inject([], function(array, value) {\n            if (Object.isArray(value))\n                return array.concat(value.flatten());\n            array.push(value);\n            return array;\n        });\n    }\n\n    function without() {\n        var values = slice.call(arguments, 0);\n        return this.select(function(value) {\n            return !values.include(value);\n        });\n    }\n\n    function reverse(inline) {\n        return (inline !== false ? this : this.toArray())._reverse();\n    }\n\n    function uniq(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    function intersect(array) {\n        return this.uniq().findAll(function(item) {\n            return array.detect(function(value) { return item === value });\n        });\n    }\n\n\n    function clone() {\n        return slice.call(this, 0);\n    }\n\n    function size() {\n        return this.length;\n    }\n\n    function inspect() {\n        return '[' + this.map(Object.inspect).join(', ') + ']';\n    }\n\n    function toJSON() {\n        var results = [];\n        this.each(function(object) {\n            var value = Object.toJSON(object);\n            if (!Object.isUndefined(value)) results.push(value);\n        });\n        return '[' + results.join(', ') + ']';\n    }\n\n    function indexOf(item, i) {\n        i || (i = 0);\n        var length = this.length;\n        if (i < 0) i = length + i;\n        for (; i < length; i++)\n            if (this[i] === item) return i;\n        return -1;\n    }\n\n    function lastIndexOf(item, i) {\n        i = isNaN(i) ? this.length : (i < 0 ? this.length + i : i) + 1;\n        var n = this.slice(0, i).reverse().indexOf(item);\n        return (n < 0) ? n : i - n - 1;\n    }\n\n    function concat() {\n        var array = slice.call(this, 0), item;\n        for (var i = 0, length = arguments.length; i < length; i++) {\n            item = arguments[i];\n            if (Object.isArray(item) && !('callee' in item)) {\n                for (var j = 0, arrayLength = item.length; j < arrayLength; j++)\n                    array.push(item[j]);\n            } else {\n                array.push(item);\n            }\n        }\n        return array;\n    }\n\n    Object.extend(arrayProto, Enumerable);\n\n    if (!arrayProto._reverse)\n        arrayProto._reverse = arrayProto.reverse;\n\n    Object.extend(arrayProto, {\n        _each:     _each,\n        clear:     clear,\n        first:     first,\n        last:      last,\n        compact:   compact,\n        flatten:   flatten,\n        without:   without,\n        reverse:   reverse,\n        uniq:      uniq,\n        intersect: intersect,\n        clone:     clone,\n        toArray:   clone,\n        size:      size,\n        inspect:   inspect,\n        toJSON:    toJSON\n    });\n\n    var CONCAT_ARGUMENTS_BUGGY = (function() {\n        return [].concat(arguments)[0][0] !== 1;\n    })(1,2)\n\n    if (CONCAT_ARGUMENTS_BUGGY) arrayProto.concat = concat;\n\n    if (!arrayProto.indexOf) arrayProto.indexOf = indexOf;\n    if (!arrayProto.lastIndexOf) arrayProto.lastIndexOf = lastIndexOf;\n})();\nfunction $H(object) {\n    return new Hash(object);\n};\n\nvar Hash = Class.create(Enumerable, (function() {\n    function initialize(object) {\n        this._object = Object.isHash(object) ? object.toObject() : Object.clone(object);\n    }\n\n    function _each(iterator) {\n        for (var key in this._object) {\n            var value = this._object[key], pair = [key, value];\n            pair.key = key;\n            pair.value = value;\n            iterator(pair);\n        }\n    }\n\n    function set(key, value) {\n        return this._object[key] = value;\n    }\n\n    function get(key) {\n        if (this._object[key] !== Object.prototype[key])\n            return this._object[key];\n    }\n\n    function unset(key) {\n        var value = this._object[key];\n        delete this._object[key];\n        return value;\n    }\n\n    function toObject() {\n        return Object.clone(this._object);\n    }\n\n    function keys() {\n        return this.pluck('key');\n    }\n\n    function values() {\n        return this.pluck('value');\n    }\n\n    function index(value) {\n        var match = this.detect(function(pair) {\n            return pair.value === value;\n        });\n        return match && match.key;\n    }\n\n    function merge(object) {\n        return this.clone().update(object);\n    }\n\n    function update(object) {\n        return new Hash(object).inject(this, function(result, pair) {\n            result.set(pair.key, pair.value);\n            return result;\n        });\n    }\n\n    function toQueryPair(key, value) {\n        if (Object.isUndefined(value)) return key;\n        return key + '=' + encodeURIComponent(String.interpret(value));\n    }\n\n    function toQueryString() {\n        return this.inject([], function(results, pair) {\n            var key = encodeURIComponent(pair.key), values = pair.value;\n\n            if (values && typeof values == 'object') {\n                if (Object.isArray(values))\n                    return results.concat(values.map(toQueryPair.curry(key)));\n            } else results.push(toQueryPair(key, values));\n            return results;\n        }).join('&');\n    }\n\n    function inspect() {\n        return '#<Hash:{' + this.map(function(pair) {\n                return pair.map(Object.inspect).join(': ');\n            }).join(', ') + '}>';\n    }\n\n    function toJSON() {\n        return Object.toJSON(this.toObject());\n    }\n\n    function clone() {\n        return new Hash(this);\n    }\n\n    return {\n        initialize:             initialize,\n        _each:                  _each,\n        set:                    set,\n        get:                    get,\n        unset:                  unset,\n        toObject:               toObject,\n        toTemplateReplacements: toObject,\n        keys:                   keys,\n        values:                 values,\n        index:                  index,\n        merge:                  merge,\n        update:                 update,\n        toQueryString:          toQueryString,\n        inspect:                inspect,\n        toJSON:                 toJSON,\n        clone:                  clone\n    };\n})());\n\nHash.from = $H;\nObject.extend(Number.prototype, (function() {\n    function toColorPart() {\n        return this.toPaddedString(2, 16);\n    }\n\n    function succ() {\n        return this + 1;\n    }\n\n    function times(iterator, context) {\n        $R(0, this, true).each(iterator, context);\n        return this;\n    }\n\n    function toPaddedString(length, radix) {\n        var string = this.toString(radix || 10);\n        return '0'.times(length - string.length) + string;\n    }\n\n    function toJSON() {\n        return isFinite(this) ? this.toString() : 'null';\n    }\n\n    function abs() {\n        return Math.abs(this);\n    }\n\n    function round() {\n        return Math.round(this);\n    }\n\n    function ceil() {\n        return Math.ceil(this);\n    }\n\n    function floor() {\n        return Math.floor(this);\n    }\n\n    return {\n        toColorPart:    toColorPart,\n        succ:           succ,\n        times:          times,\n        toPaddedString: toPaddedString,\n        toJSON:         toJSON,\n        abs:            abs,\n        round:          round,\n        ceil:           ceil,\n        floor:          floor\n    };\n})());\n\nfunction $R(start, end, exclusive) {\n    return new ObjectRange(start, end, exclusive);\n}\n\nvar ObjectRange = Class.create(Enumerable, (function() {\n    function initialize(start, end, exclusive) {\n        this.start = start;\n        this.end = end;\n        this.exclusive = exclusive;\n    }\n\n    function _each(iterator) {\n        var value = this.start;\n        while (this.include(value)) {\n            iterator(value);\n            value = value.succ();\n        }\n    }\n\n    function include(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    return {\n        initialize: initialize,\n        _each:      _each,\n        include:    include\n    };\n})());\n\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 (Object.isFunction(responder[callback])) {\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() { Ajax.activeRequestCount++ },\n    onComplete: function() { Ajax.activeRequestCount-- }\n});\nAjax.Base = Class.create({\n    initialize: 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            evalJSON:     true,\n            evalJS:       true\n        };\n        Object.extend(this.options, options || { });\n\n        this.options.method = this.options.method.toLowerCase();\n\n        if (Object.isString(this.options.parameters))\n            this.options.parameters = this.options.parameters.toQueryParams();\n        else if (Object.isHash(this.options.parameters))\n            this.options.parameters = this.options.parameters.toObject();\n    }\n});\nAjax.Request = Class.create(Ajax.Base, {\n    _complete: false,\n\n    initialize: function($super, url, options) {\n        $super(options);\n        this.transport = Ajax.getTransport();\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            params['_method'] = this.method;\n            this.method = 'post';\n        }\n\n        this.parameters = params;\n\n        if (params = Object.toQueryString(params)) {\n            if (this.method == 'get')\n                this.url += (this.url.include('?') ? '&' : '?') + params;\n            else if (/Konqueror|Safari|KHTML/.test(navigator.userAgent))\n                params += '&_=';\n        }\n\n        try {\n            var response = new Ajax.Response(this);\n            if (this.options.onCreate) this.options.onCreate(response);\n            Ajax.Responders.dispatch('onCreate', this, response);\n\n            this.transport.open(this.method.toUpperCase(), this.url,\n                this.options.asynchronous);\n\n            if (this.options.asynchronous) this.respondToReadyState.bind(this).defer(1);\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        if (typeof this.options.requestHeaders == 'object') {\n            var extras = this.options.requestHeaders;\n\n            if (Object.isFunction(extras.push))\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        var status = this.getStatus();\n        return !status || (status >= 200 && status < 300);\n    },\n\n    getStatus: function() {\n        try {\n            return this.transport.status || 0;\n        } catch (e) { return 0 }\n    },\n\n    respondToReadyState: function(readyState) {\n        var state = Ajax.Request.Events[readyState], response = new Ajax.Response(this);\n\n        if (state == 'Complete') {\n            try {\n                this._complete = true;\n                (this.options['on' + response.status]\n                || this.options['on' + (this.success() ? 'Success' : 'Failure')]\n                || Prototype.emptyFunction)(response, response.headerJSON);\n            } catch (e) {\n                this.dispatchException(e);\n            }\n\n            var contentType = response.getHeader('Content-type');\n            if (this.options.evalJS == 'force'\n                || (this.options.evalJS && this.isSameOrigin() && contentType\n                && contentType.match(/^\\s*(text|application)\\/(x-)?(java|ecma)script(;.*)?\\s*$/i)))\n                this.evalResponse();\n        }\n\n        try {\n            (this.options['on' + state] || Prototype.emptyFunction)(response, response.headerJSON);\n            Ajax.Responders.dispatch('on' + state, this, response, response.headerJSON);\n        } catch (e) {\n            this.dispatchException(e);\n        }\n\n        if (state == 'Complete') {\n            this.transport.onreadystatechange = Prototype.emptyFunction;\n        }\n    },\n\n    isSameOrigin: function() {\n        var m = this.url.match(/^\\s*https?:\\/\\/[^\\/]*/);\n        return !m || (m[0] == '#{protocol}//#{domain}#{port}'.interpolate({\n                protocol: location.protocol,\n                domain: document.domain,\n                port: location.port ? ':' + location.port : ''\n            }));\n    },\n\n    getHeader: function(name) {\n        try {\n            return this.transport.getResponseHeader(name) || 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.Request.Events =\n    ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete'];\n\n\n\n\n\n\n\n\nAjax.Response = Class.create({\n    initialize: function(request){\n        this.request = request;\n        var transport  = this.transport  = request.transport,\n            readyState = this.readyState = transport.readyState;\n\n        if((readyState > 2 && !Prototype.Browser.IE) || readyState == 4) {\n            this.status       = this.getStatus();\n            this.statusText   = this.getStatusText();\n            this.responseText = String.interpret(transport.responseText);\n            this.headerJSON   = this._getHeaderJSON();\n        }\n\n        if(readyState == 4) {\n            var xml = transport.responseXML;\n            this.responseXML  = Object.isUndefined(xml) ? null : xml;\n            this.responseJSON = this._getResponseJSON();\n        }\n    },\n\n    status:      0,\n\n    statusText: '',\n\n    getStatus: Ajax.Request.prototype.getStatus,\n\n    getStatusText: function() {\n        try {\n            return this.transport.statusText || '';\n        } catch (e) { return '' }\n    },\n\n    getHeader: Ajax.Request.prototype.getHeader,\n\n    getAllHeaders: function() {\n        try {\n            return this.getAllResponseHeaders();\n        } catch (e) { return null }\n    },\n\n    getResponseHeader: function(name) {\n        return this.transport.getResponseHeader(name);\n    },\n\n    getAllResponseHeaders: function() {\n        return this.transport.getAllResponseHeaders();\n    },\n\n    _getHeaderJSON: function() {\n        var json = this.getHeader('X-JSON');\n        if (!json) return null;\n        json = decodeURIComponent(escape(json));\n        try {\n            return json.evalJSON(this.request.options.sanitizeJSON ||\n                !this.request.isSameOrigin());\n        } catch (e) {\n            this.request.dispatchException(e);\n        }\n    },\n\n    _getResponseJSON: function() {\n        var options = this.request.options;\n        if (!options.evalJSON || (options.evalJSON != 'force' &&\n            !(this.getHeader('Content-type') || '').include('application/json')) ||\n            this.responseText.blank())\n            return null;\n        try {\n            return this.responseText.evalJSON(options.sanitizeJSON ||\n                !this.request.isSameOrigin());\n        } catch (e) {\n            this.request.dispatchException(e);\n        }\n    }\n});\n\nAjax.Updater = Class.create(Ajax.Request, {\n    initialize: function($super, container, url, options) {\n        this.container = {\n            success: (container.success || container),\n            failure: (container.failure || (container.success ? null : container))\n        };\n\n        options = Object.clone(options);\n        var onComplete = options.onComplete;\n        options.onComplete = (function(response, json) {\n            this.updateContent(response.responseText);\n            if (Object.isFunction(onComplete)) onComplete(response, json);\n        }).bind(this);\n\n        $super(url, options);\n    },\n\n    updateContent: function(responseText) {\n        var receiver = this.container[this.success() ? 'success' : 'failure'],\n            options = this.options;\n\n        if (!options.evalScripts) responseText = responseText.stripScripts();\n\n        if (receiver = $(receiver)) {\n            if (options.insertion) {\n                if (Object.isString(options.insertion)) {\n                    var insertion = { }; insertion[options.insertion] = responseText;\n                    receiver.insert(insertion);\n                }\n                else options.insertion(receiver, responseText);\n            }\n            else receiver.update(responseText);\n        }\n    }\n});\n\nAjax.PeriodicalUpdater = Class.create(Ajax.Base, {\n    initialize: function($super, container, url, options) {\n        $super(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(response) {\n        if (this.options.decay) {\n            this.decay = (response.responseText == this.lastText ?\n                this.decay * this.options.decay : 1);\n\n            this.lastText = response.responseText;\n        }\n        this.timer = this.onTimerEvent.bind(this).delay(this.decay * this.frequency);\n    },\n\n    onTimerEvent: function() {\n        this.updater = new Ajax.Updater(this.container, this.url, this.options);\n    }\n});\n\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 (Object.isString(element))\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(Element.extend(query.snapshotItem(i)));\n        return results;\n    };\n}\n\n/*--------------------------------------------------------------------------*/\n\nif (!window.Node) var Node = { };\n\nif (!Node.ELEMENT_NODE) {\n    Object.extend(Node, {\n        ELEMENT_NODE: 1,\n        ATTRIBUTE_NODE: 2,\n        TEXT_NODE: 3,\n        CDATA_SECTION_NODE: 4,\n        ENTITY_REFERENCE_NODE: 5,\n        ENTITY_NODE: 6,\n        PROCESSING_INSTRUCTION_NODE: 7,\n        COMMENT_NODE: 8,\n        DOCUMENT_NODE: 9,\n        DOCUMENT_TYPE_NODE: 10,\n        DOCUMENT_FRAGMENT_NODE: 11,\n        NOTATION_NODE: 12\n    });\n}\n\n\n(function(global) {\n\n    var SETATTRIBUTE_IGNORES_NAME = (function(){\n        var elForm = document.createElement(\"form\");\n        var elInput = document.createElement(\"input\");\n        var root = document.documentElement;\n        elInput.setAttribute(\"name\", \"test\");\n        elForm.appendChild(elInput);\n        root.appendChild(elForm);\n        var isBuggy = elForm.elements\n            ? (typeof elForm.elements.test == \"undefined\")\n            : null;\n        root.removeChild(elForm);\n        elForm = elInput = null;\n        return isBuggy;\n    })();\n\n    var element = global.Element;\n    global.Element = function(tagName, attributes) {\n        attributes = attributes || { };\n        tagName = tagName.toLowerCase();\n        var cache = Element.cache;\n        if (SETATTRIBUTE_IGNORES_NAME && attributes.name) {\n            tagName = '<' + tagName + ' name=\"' + attributes.name + '\">';\n            delete attributes.name;\n            return Element.writeAttribute(document.createElement(tagName), attributes);\n        }\n        if (!cache[tagName]) cache[tagName] = Element.extend(document.createElement(tagName));\n        return Element.writeAttribute(cache[tagName].cloneNode(false), attributes);\n    };\n    Object.extend(global.Element, element || { });\n    if (element) global.Element.prototype = element.prototype;\n})(this);\n\nElement.cache = { };\nElement.idCounter = 1;\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\n    hide: function(element) {\n        element = $(element);\n        element.style.display = 'none';\n        return element;\n    },\n\n    show: function(element) {\n        element = $(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(){\n\n        var SELECT_ELEMENT_INNERHTML_BUGGY = (function(){\n            var el = document.createElement(\"select\"),\n                isBuggy = true;\n            el.innerHTML = \"<option value=\\\"test\\\">test</option>\";\n            if (el.options && el.options[0]) {\n                isBuggy = el.options[0].nodeName.toUpperCase() !== \"OPTION\";\n            }\n            el = null;\n            return isBuggy;\n        })();\n\n        var TABLE_ELEMENT_INNERHTML_BUGGY = (function(){\n            try {\n                var el = document.createElement(\"table\");\n                if (el && el.tBodies) {\n                    el.innerHTML = \"<tbody><tr><td>test</td></tr></tbody>\";\n                    var isBuggy = typeof el.tBodies[0] == \"undefined\";\n                    el = null;\n                    return isBuggy;\n                }\n            } catch (e) {\n                return true;\n            }\n        })();\n\n        var SCRIPT_ELEMENT_REJECTS_TEXTNODE_APPENDING = (function () {\n            var s = document.createElement(\"script\"),\n                isBuggy = false;\n            try {\n                s.appendChild(document.createTextNode(\"\"));\n                isBuggy = !s.firstChild ||\n                    s.firstChild && s.firstChild.nodeType !== 3;\n            } catch (e) {\n                isBuggy = true;\n            }\n            s = null;\n            return isBuggy;\n        })();\n\n        function update(element, content) {\n            element = $(element);\n\n            if (content && content.toElement)\n                content = content.toElement();\n\n            if (Object.isElement(content))\n                return element.update().insert(content);\n\n            content = Object.toHTML(content);\n\n            var tagName = element.tagName.toUpperCase();\n\n            if (tagName === 'SCRIPT' && SCRIPT_ELEMENT_REJECTS_TEXTNODE_APPENDING) {\n                element.text = content;\n                return element;\n            }\n\n            if (SELECT_ELEMENT_INNERHTML_BUGGY || TABLE_ELEMENT_INNERHTML_BUGGY) {\n                if (tagName in Element._insertionTranslations.tags) {\n                    while (element.firstChild) {\n                        element.removeChild(element.firstChild);\n                    }\n                    Element._getContentFromAnonymousElement(tagName, content.stripScripts())\n                        .each(function(node) {\n                            element.appendChild(node)\n                        });\n                }\n                else {\n                    element.innerHTML = content.stripScripts();\n                }\n            }\n            else {\n                element.innerHTML = content.stripScripts();\n            }\n\n            content.evalScripts.bind(content).defer();\n            return element;\n        }\n\n        return update;\n    })(),\n\n    replace: function(element, content) {\n        element = $(element);\n        if (content && content.toElement) content = content.toElement();\n        else if (!Object.isElement(content)) {\n            content = Object.toHTML(content);\n            var range = element.ownerDocument.createRange();\n            range.selectNode(element);\n            content.evalScripts.bind(content).defer();\n            content = range.createContextualFragment(content.stripScripts());\n        }\n        element.parentNode.replaceChild(content, element);\n        return element;\n    },\n\n    insert: function(element, insertions) {\n        element = $(element);\n\n        if (Object.isString(insertions) || Object.isNumber(insertions) ||\n            Object.isElement(insertions) || (insertions && (insertions.toElement || insertions.toHTML)))\n            insertions = {bottom:insertions};\n\n        var content, insert, tagName, childNodes;\n\n        for (var position in insertions) {\n            content  = insertions[position];\n            position = position.toLowerCase();\n            insert = Element._insertionTranslations[position];\n\n            if (content && content.toElement) content = content.toElement();\n            if (Object.isElement(content)) {\n                insert(element, content);\n                continue;\n            }\n\n            content = Object.toHTML(content);\n\n            tagName = ((position == 'before' || position == 'after')\n                ? element.parentNode : element).tagName.toUpperCase();\n\n            childNodes = Element._getContentFromAnonymousElement(tagName, content.stripScripts());\n\n            if (position == 'top' || position == 'after') childNodes.reverse();\n            childNodes.each(insert.curry(element));\n\n            content.evalScripts.bind(content).defer();\n        }\n\n        return element;\n    },\n\n    wrap: function(element, wrapper, attributes) {\n        element = $(element);\n        if (Object.isElement(wrapper))\n            $(wrapper).writeAttribute(attributes || { });\n        else if (Object.isString(wrapper)) wrapper = new Element(wrapper, attributes);\n        else wrapper = new Element('div', wrapper);\n        if (element.parentNode)\n            element.parentNode.replaceChild(wrapper, element);\n        wrapper.appendChild(element);\n        return wrapper;\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(element, 'parentNode');\n    },\n\n    descendants: function(element) {\n        return Element.select(element, \"*\");\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(element, 'previousSibling');\n    },\n\n    nextSiblings: function(element) {\n        return Element.recursivelyCollect(element, 'nextSibling');\n    },\n\n    siblings: function(element) {\n        element = $(element);\n        return Element.previousSiblings(element).reverse()\n            .concat(Element.nextSiblings(element));\n    },\n\n    match: function(element, selector) {\n        if (Object.isString(selector))\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(element);\n        return Object.isNumber(expression) ? ancestors[expression] :\n            Selector.findElement(ancestors, expression, index);\n    },\n\n    down: function(element, expression, index) {\n        element = $(element);\n        if (arguments.length == 1) return Element.firstDescendant(element);\n        return Object.isNumber(expression) ? Element.descendants(element)[expression] :\n            Element.select(element, expression)[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(element);\n        return Object.isNumber(expression) ? previousSiblings[expression] :\n            Selector.findElement(previousSiblings, expression, index);\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(element);\n        return Object.isNumber(expression) ? nextSiblings[expression] :\n            Selector.findElement(nextSiblings, expression, index);\n    },\n\n\n    select: function(element) {\n        var args = Array.prototype.slice.call(arguments, 1);\n        return Selector.findChildElements(element, args);\n    },\n\n    adjacent: function(element) {\n        var args = Array.prototype.slice.call(arguments, 1);\n        return Selector.findChildElements(element.parentNode, args).without(element);\n    },\n\n    identify: function(element) {\n        element = $(element);\n        var id = Element.readAttribute(element, 'id');\n        if (id) return id;\n        do { id = 'anonymous_element_' + Element.idCounter++ } while ($(id));\n        Element.writeAttribute(element, 'id', id);\n        return id;\n    },\n\n    readAttribute: function(element, name) {\n        element = $(element);\n        if (Prototype.Browser.IE) {\n            var t = Element._attributeTranslations.read;\n            if (t.values[name]) return t.values[name](element, name);\n            if (t.names[name]) name = t.names[name];\n            if (name.include(':')) {\n                return (!element.attributes || !element.attributes[name]) ? null :\n                    element.attributes[name].value;\n            }\n        }\n        return element.getAttribute(name);\n    },\n\n    writeAttribute: function(element, name, value) {\n        element = $(element);\n        var attributes = { }, t = Element._attributeTranslations.write;\n\n        if (typeof name == 'object') attributes = name;\n        else attributes[name] = Object.isUndefined(value) ? true : value;\n\n        for (var attr in attributes) {\n            name = t.names[attr] || attr;\n            value = attributes[attr];\n            if (t.values[attr]) name = t.values[attr](element, value);\n            if (value === false || value === null)\n                element.removeAttribute(name);\n            else if (value === true)\n                element.setAttribute(name, name);\n            else element.setAttribute(name, value);\n        }\n        return element;\n    },\n\n    getHeight: function(element) {\n        return Element.getDimensions(element).height;\n    },\n\n    getWidth: function(element) {\n        return Element.getDimensions(element).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        return (elementClassName.length > 0 && (elementClassName == className ||\n        new RegExp(\"(^|\\\\s)\" + className + \"(\\\\s|$)\").test(elementClassName)));\n    },\n\n    addClassName: function(element, className) {\n        if (!(element = $(element))) return;\n        if (!Element.hasClassName(element, className))\n            element.className += (element.className ? ' ' : '') + className;\n        return element;\n    },\n\n    removeClassName: function(element, className) {\n        if (!(element = $(element))) return;\n        element.className = element.className.replace(\n            new RegExp(\"(^|\\\\s+)\" + className + \"(\\\\s+|$)\"), ' ').strip();\n        return element;\n    },\n\n    toggleClassName: function(element, className) {\n        if (!(element = $(element))) return;\n        return Element[Element.hasClassName(element, className) ?\n            'removeClassName' : 'addClassName'](element, className);\n    },\n\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\n        if (element.compareDocumentPosition)\n            return (element.compareDocumentPosition(ancestor) & 8) === 8;\n\n        if (ancestor.contains)\n            return ancestor.contains(element) && ancestor !== element;\n\n        while (element = element.parentNode)\n            if (element == ancestor) return true;\n\n        return false;\n    },\n\n    scrollTo: function(element) {\n        element = $(element);\n        var pos = Element.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 || value == 'auto') {\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) {\n        element = $(element);\n        var elementStyle = element.style, match;\n        if (Object.isString(styles)) {\n            element.style.cssText += ';' + styles;\n            return styles.include('opacity') ?\n                element.setOpacity(styles.match(/opacity:\\s*(\\d?\\.?\\d*)/)[1]) : element;\n        }\n        for (var property in styles)\n            if (property == 'opacity') element.setOpacity(styles[property]);\n            else\n                elementStyle[(property == 'float' || property == 'cssFloat') ?\n                    (Object.isUndefined(elementStyle.styleFloat) ? 'cssFloat' : 'styleFloat') :\n                    property] = 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(element, 'display');\n        if (display != 'none' && display != null) // Safari bug\n            return {width: element.offsetWidth, height: element.offsetHeight};\n\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        if (originalPosition != 'fixed') // Switching fixed to absolute causes issues in Safari\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            if (Prototype.Browser.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.getStyle(element, 'overflow') || 'auto';\n        if (element._overflow !== '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    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 Element._returnOffset(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.toUpperCase() == 'BODY') break;\n                var p = Element.getStyle(element, 'position');\n                if (p !== 'static') break;\n            }\n        } while (element);\n        return Element._returnOffset(valueL, valueT);\n    },\n\n    absolutize: function(element) {\n        element = $(element);\n        if (Element.getStyle(element, 'position') == 'absolute') return element;\n\n        var offsets = Element.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        return element;\n    },\n\n    relativize: function(element) {\n        element = $(element);\n        if (Element.getStyle(element, 'position') == 'relative') return element;\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        return element;\n    },\n\n    cumulativeScrollOffset: 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 Element._returnOffset(valueL, valueT);\n    },\n\n    getOffsetParent: 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    viewportOffset: 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            if (element.offsetParent == document.body &&\n                Element.getStyle(element, 'position') == 'absolute') break;\n\n        } while (element = element.offsetParent);\n\n        element = forElement;\n        do {\n            if (!Prototype.Browser.Opera || (element.tagName && (element.tagName.toUpperCase() == 'BODY'))) {\n                valueT -= element.scrollTop  || 0;\n                valueL -= element.scrollLeft || 0;\n            }\n        } while (element = element.parentNode);\n\n        return Element._returnOffset(valueL, valueT);\n    },\n\n    clonePosition: function(element, source) {\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        source = $(source);\n        var p = Element.viewportOffset(source);\n\n        element = $(element);\n        var delta = [0, 0];\n        var parent = null;\n        if (Element.getStyle(element, 'position') == 'absolute') {\n            parent = Element.getOffsetParent(element);\n            delta = Element.viewportOffset(parent);\n        }\n\n        if (parent == document.body) {\n            delta[0] -= document.body.offsetLeft;\n            delta[1] -= document.body.offsetTop;\n        }\n\n        if (options.setLeft)   element.style.left  = (p[0] - delta[0] + options.offsetLeft) + 'px';\n        if (options.setTop)    element.style.top   = (p[1] - delta[1] + options.offsetTop) + 'px';\n        if (options.setWidth)  element.style.width = source.offsetWidth + 'px';\n        if (options.setHeight) element.style.height = source.offsetHeight + 'px';\n        return element;\n    }\n};\n\nObject.extend(Element.Methods, {\n    getElementsBySelector: Element.Methods.select,\n\n    childElements: Element.Methods.immediateDescendants\n});\n\nElement._attributeTranslations = {\n    write: {\n        names: {\n            className: 'class',\n            htmlFor:   'for'\n        },\n        values: { }\n    }\n};\n\nif (Prototype.Browser.Opera) {\n    Element.Methods.getStyle = Element.Methods.getStyle.wrap(\n        function(proceed, element, style) {\n            switch (style) {\n                case 'left': case 'top': case 'right': case 'bottom':\n                if (proceed(element, 'position') === 'static') return null;\n                case 'height': case 'width':\n                if (!Element.visible(element)) return null;\n\n                var dim = parseInt(proceed(element, style), 10);\n\n                if (dim !== element['offset' + style.capitalize()])\n                    return dim + 'px';\n\n                var properties;\n                if (style === 'height') {\n                    properties = ['border-top-width', 'padding-top',\n                        'padding-bottom', 'border-bottom-width'];\n                }\n                else {\n                    properties = ['border-left-width', 'padding-left',\n                        'padding-right', 'border-right-width'];\n                }\n                return properties.inject(dim, function(memo, property) {\n                        var val = proceed(element, property);\n                        return val === null ? memo : memo - parseInt(val, 10);\n                    }) + 'px';\n                default: return proceed(element, style);\n            }\n        }\n    );\n\n    Element.Methods.readAttribute = Element.Methods.readAttribute.wrap(\n        function(proceed, element, attribute) {\n            if (attribute === 'title') return element.title;\n            return proceed(element, attribute);\n        }\n    );\n}\n\nelse if (Prototype.Browser.IE) {\n    Element.Methods.getOffsetParent = Element.Methods.getOffsetParent.wrap(\n        function(proceed, element) {\n            element = $(element);\n            try { element.offsetParent }\n            catch(e) { return $(document.body) }\n            var position = element.getStyle('position');\n            if (position !== 'static') return proceed(element);\n            element.setStyle({ position: 'relative' });\n            var value = proceed(element);\n            element.setStyle({ position: position });\n            return value;\n        }\n    );\n\n    $w('positionedOffset viewportOffset').each(function(method) {\n        Element.Methods[method] = Element.Methods[method].wrap(\n            function(proceed, element) {\n                element = $(element);\n                try { element.offsetParent }\n                catch(e) { return Element._returnOffset(0,0) }\n                var position = element.getStyle('position');\n                if (position !== 'static') return proceed(element);\n                var offsetParent = element.getOffsetParent();\n                if (offsetParent && offsetParent.getStyle('position') === 'fixed')\n                    offsetParent.setStyle({ zoom: 1 });\n                element.setStyle({ position: 'relative' });\n                var value = proceed(element);\n                element.setStyle({ position: position });\n                return value;\n            }\n        );\n    });\n\n    Element.Methods.cumulativeOffset = Element.Methods.cumulativeOffset.wrap(\n        function(proceed, element) {\n            try { element.offsetParent }\n            catch(e) { return Element._returnOffset(0,0) }\n            return proceed(element);\n        }\n    );\n\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        function stripAlpha(filter){\n            return filter.replace(/alpha\\([^\\)]*\\)/gi,'');\n        }\n        element = $(element);\n        var currentStyle = element.currentStyle;\n        if ((currentStyle && !currentStyle.hasLayout) ||\n            (!currentStyle && element.style.zoom == 'normal'))\n            element.style.zoom = 1;\n\n        var filter = element.getStyle('filter'), style = element.style;\n        if (value == 1 || value === '') {\n            (filter = stripAlpha(filter)) ?\n                style.filter = filter : style.removeAttribute('filter');\n            return element;\n        } else if (value < 0.00001) value = 0;\n        style.filter = stripAlpha(filter) +\n            'alpha(opacity=' + (value * 100) + ')';\n        return element;\n    };\n\n    Element._attributeTranslations = (function(){\n\n        var classProp = 'className';\n        var forProp = 'for';\n\n        var el = document.createElement('div');\n\n        el.setAttribute(classProp, 'x');\n\n        if (el.className !== 'x') {\n            el.setAttribute('class', 'x');\n            if (el.className === 'x') {\n                classProp = 'class';\n            }\n        }\n        el = null;\n\n        el = document.createElement('label');\n        el.setAttribute(forProp, 'x');\n        if (el.htmlFor !== 'x') {\n            el.setAttribute('htmlFor', 'x');\n            if (el.htmlFor === 'x') {\n                forProp = 'htmlFor';\n            }\n        }\n        el = null;\n\n        return {\n            read: {\n                names: {\n                    'class':      classProp,\n                    'className':  classProp,\n                    'for':        forProp,\n                    'htmlFor':    forProp\n                },\n                values: {\n                    _getAttr: function(element, attribute) {\n                        return element.getAttribute(attribute);\n                    },\n                    _getAttr2: function(element, attribute) {\n                        return element.getAttribute(attribute, 2);\n                    },\n                    _getAttrNode: function(element, attribute) {\n                        var node = element.getAttributeNode(attribute);\n                        return node ? node.value : \"\";\n                    },\n                    _getEv: (function(){\n\n                        var el = document.createElement('div');\n                        el.onclick = Prototype.emptyFunction;\n                        var value = el.getAttribute('onclick');\n                        var f;\n\n                        if (String(value).indexOf('{') > -1) {\n                            f = function(element, attribute) {\n                                attribute = element.getAttribute(attribute);\n                                if (!attribute) return null;\n                                attribute = attribute.toString();\n                                attribute = attribute.split('{')[1];\n                                attribute = attribute.split('}')[0];\n                                return attribute.strip();\n                            };\n                        }\n                        else if (value === '') {\n                            f = function(element, attribute) {\n                                attribute = element.getAttribute(attribute);\n                                if (!attribute) return null;\n                                return attribute.strip();\n                            };\n                        }\n                        el = null;\n                        return f;\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                        return element.title;\n                    }\n                }\n            }\n        }\n    })();\n\n    Element._attributeTranslations.write = {\n        names: Object.extend({\n            cellpadding: 'cellPadding',\n            cellspacing: 'cellSpacing'\n        }, Element._attributeTranslations.read.names),\n        values: {\n            checked: function(element, value) {\n                element.checked = !!value;\n            },\n\n            style: function(element, value) {\n                element.style.cssText = value ? value : '';\n            }\n        }\n    };\n\n    Element._attributeTranslations.has = {};\n\n    $w('colSpan rowSpan vAlign dateTime accessKey tabIndex ' +\n        'encType maxLength readOnly longDesc frameBorder').each(function(attr) {\n        Element._attributeTranslations.write.names[attr.toLowerCase()] = attr;\n        Element._attributeTranslations.has[attr.toLowerCase()] = attr;\n    });\n\n    (function(v) {\n        Object.extend(v, {\n            href:        v._getAttr2,\n            src:         v._getAttr2,\n            type:        v._getAttr,\n            action:      v._getAttrNode,\n            disabled:    v._flag,\n            checked:     v._flag,\n            readonly:    v._flag,\n            multiple:    v._flag,\n            onload:      v._getEv,\n            onunload:    v._getEv,\n            onclick:     v._getEv,\n            ondblclick:  v._getEv,\n            onmousedown: v._getEv,\n            onmouseup:   v._getEv,\n            onmouseover: v._getEv,\n            onmousemove: v._getEv,\n            onmouseout:  v._getEv,\n            onfocus:     v._getEv,\n            onblur:      v._getEv,\n            onkeypress:  v._getEv,\n            onkeydown:   v._getEv,\n            onkeyup:     v._getEv,\n            onsubmit:    v._getEv,\n            onreset:     v._getEv,\n            onselect:    v._getEv,\n            onchange:    v._getEv\n        });\n    })(Element._attributeTranslations.read.values);\n\n    if (Prototype.BrowserFeatures.ElementExtensions) {\n        (function() {\n            function _descendants(element) {\n                var nodes = element.getElementsByTagName('*'), results = [];\n                for (var i = 0, node; node = nodes[i]; i++)\n                    if (node.tagName !== \"!\") // Filter out comment nodes.\n                        results.push(node);\n                return results;\n            }\n\n            Element.Methods.down = function(element, expression, index) {\n                element = $(element);\n                if (arguments.length == 1) return element.firstDescendant();\n                return Object.isNumber(expression) ? _descendants(element)[expression] :\n                    Element.select(element, expression)[index || 0];\n            }\n        })();\n    }\n\n}\n\nelse if (Prototype.Browser.Gecko && /rv:1\\.8\\.0/.test(navigator.userAgent)) {\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\nelse if (Prototype.Browser.WebKit) {\n    Element.Methods.setOpacity = function(element, value) {\n        element = $(element);\n        element.style.opacity = (value == 1 || value === '') ? '' :\n            (value < 0.00001) ? 0 : value;\n\n        if (value == 1)\n            if(element.tagName.toUpperCase() == 'IMG' && element.width) {\n                element.width++; element.width--;\n            } else try {\n                var n = document.createTextNode(' ');\n                element.appendChild(n);\n                element.removeChild(n);\n            } catch (e) { }\n\n        return element;\n    };\n\n    Element.Methods.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 Element._returnOffset(valueL, valueT);\n    };\n}\n\nif ('outerHTML' in document.documentElement) {\n    Element.Methods.replace = function(element, content) {\n        element = $(element);\n\n        if (content && content.toElement) content = content.toElement();\n        if (Object.isElement(content)) {\n            element.parentNode.replaceChild(content, element);\n            return element;\n        }\n\n        content = Object.toHTML(content);\n        var parent = element.parentNode, tagName = parent.tagName.toUpperCase();\n\n        if (Element._insertionTranslations.tags[tagName]) {\n            var nextSibling = element.next();\n            var fragments = Element._getContentFromAnonymousElement(tagName, content.stripScripts());\n            parent.removeChild(element);\n            if (nextSibling)\n                fragments.each(function(node) { parent.insertBefore(node, nextSibling) });\n            else\n                fragments.each(function(node) { parent.appendChild(node) });\n        }\n        else element.outerHTML = content.stripScripts();\n\n        content.evalScripts.bind(content).defer();\n        return element;\n    };\n}\n\nElement._returnOffset = function(l, t) {\n    var result = [l, t];\n    result.left = l;\n    result.top = t;\n    return result;\n};\n\nElement._getContentFromAnonymousElement = function(tagName, html) {\n    var div = new Element('div'), t = Element._insertionTranslations.tags[tagName];\n    if (t) {\n        div.innerHTML = t[0] + html + t[1];\n        t[2].times(function() { div = div.firstChild });\n    } else div.innerHTML = html;\n    return $A(div.childNodes);\n};\n\nElement._insertionTranslations = {\n    before: function(element, node) {\n        element.parentNode.insertBefore(node, element);\n    },\n    top: function(element, node) {\n        element.insertBefore(node, element.firstChild);\n    },\n    bottom: function(element, node) {\n        element.appendChild(node);\n    },\n    after: function(element, node) {\n        element.parentNode.insertBefore(node, element.nextSibling);\n    },\n    tags: {\n        TABLE:  ['<table>',                '</table>',                   1],\n        TBODY:  ['<table><tbody>',         '</tbody></table>',           2],\n        TR:     ['<table><tbody><tr>',     '</tr></tbody></table>',      3],\n        TD:     ['<table><tbody><tr><td>', '</td></tr></tbody></table>', 4],\n        SELECT: ['<select>',               '</select>',                  1]\n    }\n};\n\n(function() {\n    var tags = Element._insertionTranslations.tags;\n    Object.extend(tags, {\n        THEAD: tags.TBODY,\n        TFOOT: tags.TBODY,\n        TH:    tags.TD\n    });\n})();\n\nElement.Methods.Simulated = {\n    hasAttribute: function(element, attribute) {\n        attribute = Element._attributeTranslations.has[attribute] || attribute;\n        var node = $(element).getAttributeNode(attribute);\n        return !!(node && node.specified);\n    }\n};\n\nElement.Methods.ByTag = { };\n\nObject.extend(Element, Element.Methods);\n\n(function(div) {\n\n    if (!Prototype.BrowserFeatures.ElementExtensions && div['__proto__']) {\n        window.HTMLElement = { };\n        window.HTMLElement.prototype = div['__proto__'];\n        Prototype.BrowserFeatures.ElementExtensions = true;\n    }\n\n    div = null;\n\n})(document.createElement('div'))\n\nElement.extend = (function() {\n\n    function checkDeficiency(tagName) {\n        if (typeof window.Element != 'undefined') {\n            var proto = window.Element.prototype;\n            if (proto) {\n                var id = '_' + (Math.random()+'').slice(2);\n                var el = document.createElement(tagName);\n                proto[id] = 'x';\n                var isBuggy = (el[id] !== 'x');\n                delete proto[id];\n                el = null;\n                return isBuggy;\n            }\n        }\n        return false;\n    }\n\n    function extendElementWith(element, methods) {\n        for (var property in methods) {\n            var value = methods[property];\n            if (Object.isFunction(value) && !(property in element))\n                element[property] = value.methodize();\n        }\n    }\n\n    var HTMLOBJECTELEMENT_PROTOTYPE_BUGGY = checkDeficiency('object');\n\n    if (Prototype.BrowserFeatures.SpecificElementExtensions) {\n        if (HTMLOBJECTELEMENT_PROTOTYPE_BUGGY) {\n            return function(element) {\n                if (element && typeof element._extendedByPrototype == 'undefined') {\n                    var t = element.tagName;\n                    if (t && (/^(?:object|applet|embed)$/i.test(t))) {\n                        extendElementWith(element, Element.Methods);\n                        extendElementWith(element, Element.Methods.Simulated);\n                        extendElementWith(element, Element.Methods.ByTag[t.toUpperCase()]);\n                    }\n                }\n                return element;\n            }\n        }\n        return Prototype.K;\n    }\n\n    var Methods = { }, ByTag = Element.Methods.ByTag;\n\n    var extend = Object.extend(function(element) {\n        if (!element || typeof element._extendedByPrototype != 'undefined' ||\n            element.nodeType != 1 || element == window) return element;\n\n        var methods = Object.clone(Methods),\n            tagName = element.tagName.toUpperCase();\n\n        if (ByTag[tagName]) Object.extend(methods, ByTag[tagName]);\n\n        extendElementWith(element, methods);\n\n        element._extendedByPrototype = Prototype.emptyFunction;\n        return element;\n\n    }, {\n        refresh: function() {\n            if (!Prototype.BrowserFeatures.ElementExtensions) {\n                Object.extend(Methods, Element.Methods);\n                Object.extend(Methods, Element.Methods.Simulated);\n            }\n        }\n    });\n\n    extend.refresh();\n    return extend;\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 (Object.isArray(tagName)) 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        for (var property in methods) {\n            var value = methods[property];\n            if (!Object.isFunction(value)) continue;\n            if (!onlyIfAbsent || !(property in destination))\n                destination[property] = value.methodize();\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        var element = document.createElement(tagName);\n        var proto = element['__proto__'] || element.constructor.prototype;\n        element = null;\n        return proto;\n    }\n\n    var elementPrototype = window.HTMLElement ? HTMLElement.prototype :\n        Element.prototype;\n\n    if (F.ElementExtensions) {\n        copy(Element.Methods, elementPrototype);\n        copy(Element.Methods.Simulated, elementPrototype, true);\n    }\n\n    if (F.SpecificElementExtensions) {\n        for (var tag in Element.Methods.ByTag) {\n            var klass = findDOMClass(tag);\n            if (Object.isUndefined(klass)) continue;\n            copy(T[tag], klass.prototype);\n        }\n    }\n\n    Object.extend(Element, Element.Methods);\n    delete Element.ByTag;\n\n    if (Element.extend.refresh) Element.extend.refresh();\n    Element.cache = { };\n};\n\n\ndocument.viewport = {\n\n    getDimensions: function() {\n        return { width: this.getWidth(), height: this.getHeight() };\n    },\n\n    getScrollOffsets: function() {\n        return Element._returnOffset(\n            window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft,\n            window.pageYOffset || document.documentElement.scrollTop  || document.body.scrollTop);\n    }\n};\n\n(function(viewport) {\n    var B = Prototype.Browser, doc = document, element, property = {};\n\n    function getRootElement() {\n        if (B.WebKit && !doc.evaluate)\n            return document;\n\n        if (B.Opera && window.parseFloat(window.opera.version()) < 9.5)\n            return document.body;\n\n        return document.documentElement;\n    }\n\n    function define(D) {\n        if (!element) element = getRootElement();\n\n        property[D] = 'client' + D;\n\n        viewport['get' + D] = function() { return element[property[D]] };\n        return viewport['get' + D]();\n    }\n\n    viewport.getWidth  = define.curry('Width');\n\n    viewport.getHeight = define.curry('Height');\n})(document.viewport);\n\n\nElement.Storage = {\n    UID: 1\n};\n\nElement.addMethods({\n    getStorage: function(element) {\n        if (!(element = $(element))) return;\n\n        var uid;\n        if (element === window) {\n            uid = 0;\n        } else {\n            if (typeof element._prototypeUID === \"undefined\")\n                element._prototypeUID = [Element.Storage.UID++];\n            uid = element._prototypeUID[0];\n        }\n\n        if (!Element.Storage[uid])\n            Element.Storage[uid] = $H();\n\n        return Element.Storage[uid];\n    },\n\n    store: function(element, key, value) {\n        if (!(element = $(element))) return;\n\n        if (arguments.length === 2) {\n            Element.getStorage(element).update(key);\n        } else {\n            Element.getStorage(element).set(key, value);\n        }\n\n        return element;\n    },\n\n    retrieve: function(element, key, defaultValue) {\n        if (!(element = $(element))) return;\n        var hash = Element.getStorage(element), value = hash.get(key);\n\n        if (Object.isUndefined(value)) {\n            hash.set(key, defaultValue);\n            value = defaultValue;\n        }\n\n        return value;\n    },\n\n    clone: function(element, deep) {\n        if (!(element = $(element))) return;\n        var clone = element.cloneNode(deep);\n        clone._prototypeUID = void 0;\n        if (deep) {\n            var descendants = Element.select(clone, '*'),\n                i = descendants.length;\n            while (i--) {\n                descendants[i]._prototypeUID = void 0;\n            }\n        }\n        return Element.extend(clone);\n    }\n});\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    initialize: function(expression) {\n        this.expression = expression.strip();\n\n        if (this.shouldUseSelectorsAPI()) {\n            this.mode = 'selectorsAPI';\n        } else if (this.shouldUseXPath()) {\n            this.mode = 'xpath';\n            this.compileXPathMatcher();\n        } else {\n            this.mode = \"normal\";\n            this.compileMatcher();\n        }\n\n    },\n\n    shouldUseXPath: (function() {\n\n        var IS_DESCENDANT_SELECTOR_BUGGY = (function(){\n            var isBuggy = false;\n            if (document.evaluate && window.XPathResult) {\n                var el = document.createElement('div');\n                el.innerHTML = '<ul><li></li></ul><div><ul><li></li></ul></div>';\n\n                var xpath = \".//*[local-name()='ul' or local-name()='UL']\" +\n                    \"//*[local-name()='li' or local-name()='LI']\";\n\n                var result = document.evaluate(xpath, el, null,\n                    XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);\n\n                isBuggy = (result.snapshotLength !== 2);\n                el = null;\n            }\n            return isBuggy;\n        })();\n\n        return function() {\n            if (!Prototype.BrowserFeatures.XPath) return false;\n\n            var e = this.expression;\n\n            if (Prototype.Browser.WebKit &&\n                (e.include(\"-of-type\") || e.include(\":empty\")))\n                return false;\n\n            if ((/(\\[[\\w-]*?:|:checked)/).test(e))\n                return false;\n\n            if (IS_DESCENDANT_SELECTOR_BUGGY) return false;\n\n            return true;\n        }\n\n    })(),\n\n    shouldUseSelectorsAPI: function() {\n        if (!Prototype.BrowserFeatures.SelectorsAPI) return false;\n\n        if (Selector.CASE_INSENSITIVE_CLASS_NAMES) return false;\n\n        if (!Selector._div) Selector._div = new Element('div');\n\n        try {\n            Selector._div.querySelector(this.expression);\n        } catch(e) {\n            return false;\n        }\n\n        return true;\n    },\n\n    compileMatcher: function() {\n        var e = this.expression, ps = Selector.patterns, h = Selector.handlers,\n            c = Selector.criteria, le, p, m, len = ps.length, name;\n\n        if (Selector._cache[e]) {\n            this.matcher = Selector._cache[e];\n            return;\n        }\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 = 0; i<len; i++) {\n                p = ps[i].re;\n                name = ps[i].name;\n                if (m = e.match(p)) {\n                    this.matcher.push(Object.isFunction(c[name]) ? c[name](m) :\n                        new Template(c[name]).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, len = ps.length, name;\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 = 0; i<len; i++) {\n                name = ps[i].name;\n                if (m = e.match(ps[i].re)) {\n                    this.matcher.push(Object.isFunction(x[name]) ? x[name](m) :\n                        new Template(x[name]).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        var e = this.expression, results;\n\n        switch (this.mode) {\n            case 'selectorsAPI':\n                if (root !== document) {\n                    var oldId = root.id, id = $(root).identify();\n                    id = id.replace(/([\\.:])/g, \"\\\\$1\");\n                    e = \"#\" + id + \" \" + e;\n                }\n\n                results = $A(root.querySelectorAll(e)).map(Element.extend);\n                root.id = oldId;\n\n                return results;\n            case 'xpath':\n                return document._getElementsByXPath(this.xpath, root);\n            default:\n                return this.matcher(root);\n        }\n    },\n\n    match: function(element) {\n        this.tokens = [];\n\n        var e = this.expression, ps = Selector.patterns, as = Selector.assertions;\n        var le, p, m, len = ps.length, name;\n\n        while (e && le !== e && (/\\S/).test(e)) {\n            le = e;\n            for (var i = 0; i<len; i++) {\n                p = ps[i].re;\n                name = ps[i].name;\n                if (m = e.match(p)) {\n                    if (as[name]) {\n                        this.tokens.push([name, Object.clone(m)]);\n                        e = e.replace(m[0], '');\n                    } else {\n                        return this.findElements(document).include(element);\n                    }\n                }\n            }\n        }\n\n        var match = true, name, matches;\n        for (var i = 0, token; token = this.tokens[i]; i++) {\n            name = token[0], matches = token[1];\n            if (!Selector.assertions[name](element, matches)) {\n                match = false; break;\n            }\n        }\n\n        return match;\n    },\n\n    toString: function() {\n        return this.expression;\n    },\n\n    inspect: function() {\n        return \"#<Selector:\" + this.expression.inspect() + \">\";\n    }\n});\n\nif (Prototype.BrowserFeatures.SelectorsAPI &&\n    document.compatMode === 'BackCompat') {\n    Selector.CASE_INSENSITIVE_CLASS_NAMES = (function(){\n        var div = document.createElement('div'),\n            span = document.createElement('span');\n\n        div.id = \"prototype_test_id\";\n        span.className = 'Test';\n        div.appendChild(span);\n        var isIgnored = (div.querySelector('#prototype_test_id .test') !== null);\n        div = span = null;\n        return isIgnored;\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: function(m) {\n            m[1] = m[1].toLowerCase();\n            return new Template(\"[@#{1}]\").evaluate(m);\n        },\n        attr: function(m) {\n            m[1] = m[1].toLowerCase();\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 (Object.isFunction(h)) 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)]\",\n            'checked':     \"[@checked]\",\n            'disabled':    \"[(@disabled) and (@type!='hidden')]\",\n            'enabled':     \"[not(@disabled) and (@type!='hidden')]\",\n            'not': function(m) {\n                var e = m[6], p = Selector.patterns,\n                    x = Selector.xpath, le, v, len = p.length, name;\n\n                var exclusion = [];\n                while (e && le != e && (/\\S/).test(e)) {\n                    le = e;\n                    for (var i = 0; i<len; i++) {\n                        name = p[i].name\n                        if (m = e.match(p[i].re)) {\n                            v = Object.isFunction(x[name]) ? x[name](m) : new Template(x[name]).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); 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); 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        { name: 'laterSibling', re: /^\\s*~\\s*/ },\n        { name: 'child',        re: /^\\s*>\\s*/ },\n        { name: 'adjacent',     re: /^\\s*\\+\\s*/ },\n        { name: 'descendant',   re: /^\\s/ },\n\n        { name: 'tagName',      re: /^\\s*(\\*|[\\w\\-]+)(\\b|$)?/ },\n        { name: 'id',           re: /^#([\\w\\-\\*]+)(\\b|$)/ },\n        { name: 'className',    re: /^\\.([\\w\\-\\*]+)(\\b|$)/ },\n        { name: 'pseudo',       re: /^:((first|last|nth|nth-last|only)(-child|-of-type)|empty|checked|(en|dis)abled|not)(\\((.*?)\\))?(\\b|$|(?=\\s|[:+~>]))/ },\n        { name: 'attrPresence', re: /^\\[((?:[\\w-]+:)?[\\w-]+)\\]/ },\n        { name: 'attr',         re: /\\[((?:[\\w-]*:)?[\\w-]+)\\s*(?:([!^$*~|]?=)\\s*((['\"])([^\\4]*?)\\4|([^'\"][^\\]]*?)))?\\]/ }\n    ],\n\n    assertions: {\n        tagName: function(element, matches) {\n            return matches[1].toUpperCase() == element.tagName.toUpperCase();\n        },\n\n        className: function(element, matches) {\n            return Element.hasClassName(element, matches[1]);\n        },\n\n        id: function(element, matches) {\n            return element.id === matches[1];\n        },\n\n        attrPresence: function(element, matches) {\n            return Element.hasAttribute(element, matches[1]);\n        },\n\n        attr: function(element, matches) {\n            var nodeValue = Element.readAttribute(element, matches[1]);\n            return nodeValue && Selector.operators[matches[2]](nodeValue, matches[5] || matches[6]);\n        }\n    },\n\n    handlers: {\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        mark: function(nodes) {\n            var _true = Prototype.emptyFunction;\n            for (var i = 0, node; node = nodes[i]; i++)\n                node._countedByPrototype = _true;\n            return nodes;\n        },\n\n        unmark: (function(){\n\n            var PROPERTIES_ATTRIBUTES_MAP = (function(){\n                var el = document.createElement('div'),\n                    isBuggy = false,\n                    propName = '_countedByPrototype',\n                    value = 'x'\n                el[propName] = value;\n                isBuggy = (el.getAttribute(propName) === value);\n                el = null;\n                return isBuggy;\n            })();\n\n            return PROPERTIES_ATTRIBUTES_MAP ?\n                function(nodes) {\n                    for (var i = 0, node; node = nodes[i]; i++)\n                        node.removeAttribute('_countedByPrototype');\n                    return nodes;\n                } :\n                function(nodes) {\n                    for (var i = 0, node; node = nodes[i]; i++)\n                        node._countedByPrototype = void 0;\n                    return nodes;\n                }\n        })(),\n\n        index: function(parentNode, reverse, ofType) {\n            parentNode._countedByPrototype = Prototype.emptyFunction;\n            if (reverse) {\n                for (var nodes = parentNode.childNodes, i = nodes.length - 1, j = 1; i >= 0; i--) {\n                    var node = nodes[i];\n                    if (node.nodeType == 1 && (!ofType || node._countedByPrototype)) 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._countedByPrototype)) node.nodeIndex = j++;\n            }\n        },\n\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 (typeof (n = nodes[i])._countedByPrototype == 'undefined') {\n                    n._countedByPrototype = Prototype.emptyFunction;\n                    results.push(Element.extend(n));\n                }\n            return Selector.handlers.unmark(results);\n        },\n\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, 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                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        tagName: function(nodes, root, tagName, combinator) {\n            var uTagName = tagName.toUpperCase();\n            var results = [], h = Selector.handlers;\n            if (nodes) {\n                if (combinator) {\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() === uTagName) 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\n            if (root == document) {\n                if (!targetNode) return [];\n                if (!nodes) return [targetNode];\n            } else {\n                if (!root.sourceIndex || root.sourceIndex < 1) {\n                    var nodes = root.getElementsByTagName('*');\n                    for (var j = 0, node; node = nodes[j]; j++) {\n                        if (node.id === id) return [node];\n                    }\n                }\n            }\n\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, combinator) {\n            if (!nodes) nodes = root.getElementsByTagName(\"*\");\n            if (nodes && combinator) nodes = this[combinator](nodes);\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, combinator) {\n            if (!nodes) nodes = root.getElementsByTagName(\"*\");\n            if (nodes && combinator) nodes = this[combinator](nodes);\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        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        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._countedByPrototype) {\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                if (node.tagName == '!' || node.firstChild) 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._countedByPrototype) 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 && (!node.type || node.type !== 'hidden'))\n                    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 == v || nv && nv.startsWith(v); },\n        '$=': function(nv, v) { return nv == v || nv && nv.endsWith(v); },\n        '*=': function(nv, v) { return nv == v || nv && nv.include(v); },\n        '~=': function(nv, v) { return (' ' + nv + ' ').include(' ' + v + ' '); },\n        '|=': function(nv, v) { return ('-' + (nv || \"\").toUpperCase() +\n        '-').include('-' + (v || \"\").toUpperCase() + '-'); }\n    },\n\n    split: function(expression) {\n        var expressions = [];\n        expression.scan(/(([\\w#:.~>+()\\s-]+|\\*|\\[.*?\\])+)\\s*(,|$)/, function(m) {\n            expressions.push(m[1].strip());\n        });\n        return expressions;\n    },\n\n    matchElements: function(elements, expression) {\n        var matches = $$(expression), h = Selector.handlers;\n        h.mark(matches);\n        for (var i = 0, results = [], element; element = elements[i]; i++)\n            if (element._countedByPrototype) results.push(element);\n        h.unmark(matches);\n        return results;\n    },\n\n    findElement: function(elements, expression, index) {\n        if (Object.isNumber(expression)) {\n            index = expression; expression = false;\n        }\n        return Selector.matchElements(elements, expression || '*')[index || 0];\n    },\n\n    findChildElements: function(element, expressions) {\n        expressions = Selector.split(expressions.join(','));\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\nif (Prototype.Browser.IE) {\n    Object.extend(Selector.handlers, {\n        concat: function(a, b) {\n            for (var i = 0, node; node = b[i]; i++)\n                if (node.tagName !== \"!\") a.push(node);\n            return a;\n        }\n    });\n}\n\nfunction $$() {\n    return Selector.findChildElements(document, $A(arguments));\n}\n\nvar Form = {\n    reset: function(form) {\n        form = $(form);\n        form.reset();\n        return form;\n    },\n\n    serializeElements: function(elements, options) {\n        if (typeof options != 'object') options = { hash: !!options };\n        else if (Object.isUndefined(options.hash)) options.hash = true;\n        var key, value, submitted = false, submit = options.submit;\n\n        var data = elements.inject({ }, function(result, element) {\n            if (!element.disabled && element.name) {\n                key = element.name; value = $(element).getValue();\n                if (value != null && element.type != 'file' && (element.type != 'submit' || (!submitted &&\n                    submit !== false && (!submit || key == submit) && (submitted = true)))) {\n                    if (key in result) {\n                        if (!Object.isArray(result[key])) result[key] = [result[key]];\n                        result[key].push(value);\n                    }\n                    else result[key] = value;\n                }\n            }\n            return result;\n        });\n\n        return options.hash ? data : Object.toQueryString(data);\n    }\n};\n\nForm.Methods = {\n    serialize: function(form, options) {\n        return Form.serializeElements(Form.getElements(form), options);\n    },\n\n    getElements: function(form) {\n        var elements = $(form).getElementsByTagName('*'),\n            element,\n            arr = [ ],\n            serializers = Form.Element.Serializers;\n        for (var i = 0; element = elements[i]; i++) {\n            arr.push(element);\n        }\n        return arr.inject([], function(elements, child) {\n            if (serializers[child.tagName.toLowerCase()])\n                elements.push(Element.extend(child));\n            return elements;\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        var elements = $(form).getElements().findAll(function(element) {\n            return 'hidden' != element.type && !element.disabled;\n        });\n        var firstByIndex = elements.findAll(function(element) {\n            return element.hasAttribute('tabIndex') && element.tabIndex >= 0;\n        }).sortBy(function(element) { return element.tabIndex }).first();\n\n        return firstByIndex ? firstByIndex : elements.find(function(element) {\n                return /^(?:input|select|textarea)$/i.test(element.tagName);\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, action = form.readAttribute('action') || '';\n        if (action.blank()) action = window.location.href;\n        options.parameters = form.serialize(true);\n\n        if (params) {\n            if (Object.isString(params)) 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(action, options);\n    }\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\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 Object.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    setValue: function(element, value) {\n        element = $(element);\n        var method = element.tagName.toLowerCase();\n        Form.Element.Serializers[method](element, value);\n        return 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)$/i.test(element.type))))\n                element.select();\n        } catch (e) { }\n        return element;\n    },\n\n    disable: function(element) {\n        element = $(element);\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;\n\nvar $F = Form.Element.Methods.getValue;\n\n/*--------------------------------------------------------------------------*/\n\nForm.Element.Serializers = {\n    input: function(element, value) {\n        switch (element.type.toLowerCase()) {\n            case 'checkbox':\n            case 'radio':\n                return Form.Element.Serializers.inputSelector(element, value);\n            default:\n                return Form.Element.Serializers.textarea(element, value);\n        }\n    },\n\n    inputSelector: function(element, value) {\n        if (Object.isUndefined(value)) return element.checked ? element.value : null;\n        else element.checked = !!value;\n    },\n\n    textarea: function(element, value) {\n        if (Object.isUndefined(value)) return element.value;\n        else element.value = value;\n    },\n\n    select: function(element, value) {\n        if (Object.isUndefined(value))\n            return this[element.type == 'select-one' ?\n                'selectOne' : 'selectMany'](element);\n        else {\n            var opt, currentValue, single = !Object.isArray(value);\n            for (var i = 0, length = element.length; i < length; i++) {\n                opt = element.options[i];\n                currentValue = this.optionValue(opt);\n                if (single) {\n                    if (currentValue == value) {\n                        opt.selected = true;\n                        return;\n                    }\n                }\n                else opt.selected = value.include(currentValue);\n            }\n        }\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        return Element.extend(opt).hasAttribute('value') ? opt.value : opt.text;\n    }\n};\n\n/*--------------------------------------------------------------------------*/\n\n\nAbstract.TimedObserver = Class.create(PeriodicalExecuter, {\n    initialize: function($super, element, frequency, callback) {\n        $super(callback, frequency);\n        this.element   = $(element);\n        this.lastValue = this.getValue();\n    },\n\n    execute: function() {\n        var value = this.getValue();\n        if (Object.isString(this.lastValue) && Object.isString(value) ?\n                this.lastValue != value : String(this.lastValue) != String(value)) {\n            this.callback(this.element, value);\n            this.lastValue = value;\n        }\n    }\n});\n\nForm.Element.Observer = Class.create(Abstract.TimedObserver, {\n    getValue: function() {\n        return Form.Element.getValue(this.element);\n    }\n});\n\nForm.Observer = Class.create(Abstract.TimedObserver, {\n    getValue: function() {\n        return Form.serialize(this.element);\n    }\n});\n\n/*--------------------------------------------------------------------------*/\n\nAbstract.EventObserver = Class.create({\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, 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(Abstract.EventObserver, {\n    getValue: function() {\n        return Form.Element.getValue(this.element);\n    }\n});\n\nForm.EventObserver = Class.create(Abstract.EventObserver, {\n    getValue: function() {\n        return Form.serialize(this.element);\n    }\n});\n(function() {\n\n    var 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        KEY_INSERT:   45,\n\n        cache: {}\n    };\n\n    var docEl = document.documentElement;\n    var MOUSEENTER_MOUSELEAVE_EVENTS_SUPPORTED = 'onmouseenter' in docEl\n        && 'onmouseleave' in docEl;\n\n    var _isButton;\n    if (Prototype.Browser.IE) {\n        var buttonMap = { 0: 1, 1: 4, 2: 2 };\n        _isButton = function(event, code) {\n            return event.button === buttonMap[code];\n        };\n    } else if (Prototype.Browser.WebKit) {\n        _isButton = function(event, code) {\n            switch (code) {\n                case 0: return event.which == 1 && !event.metaKey;\n                case 1: return event.which == 1 && event.metaKey;\n                default: return false;\n            }\n        };\n    } else {\n        _isButton = function(event, code) {\n            return event.which ? (event.which === code + 1) : (event.button === code);\n        };\n    }\n\n    function isLeftClick(event)   { return _isButton(event, 0) }\n\n    function isMiddleClick(event) { return _isButton(event, 1) }\n\n    function isRightClick(event)  { return _isButton(event, 2) }\n\n    function element(event) {\n        event = Event.extend(event);\n\n        var node = event.target, type = event.type,\n            currentTarget = event.currentTarget;\n\n        if (currentTarget && currentTarget.tagName) {\n            if (type === 'load' || type === 'error' ||\n                (type === 'click' && currentTarget.tagName.toLowerCase() === 'input'\n                && currentTarget.type === 'radio'))\n                node = currentTarget;\n        }\n\n        if (node.nodeType == Node.TEXT_NODE)\n            node = node.parentNode;\n\n        return Element.extend(node);\n    }\n\n    function findElement(event, expression) {\n        var element = Event.element(event);\n        if (!expression) return element;\n        var elements = [element].concat(element.ancestors());\n        return Selector.findElement(elements, expression, 0);\n    }\n\n    function pointer(event) {\n        return { x: pointerX(event), y: pointerY(event) };\n    }\n\n    function pointerX(event) {\n        var docElement = document.documentElement,\n            body = document.body || { scrollLeft: 0 };\n\n        return event.pageX || (event.clientX +\n            (docElement.scrollLeft || body.scrollLeft) -\n            (docElement.clientLeft || 0));\n    }\n\n    function pointerY(event) {\n        var docElement = document.documentElement,\n            body = document.body || { scrollTop: 0 };\n\n        return  event.pageY || (event.clientY +\n            (docElement.scrollTop || body.scrollTop) -\n            (docElement.clientTop || 0));\n    }\n\n\n    function stop(event) {\n        Event.extend(event);\n        event.preventDefault();\n        event.stopPropagation();\n\n        event.stopped = true;\n    }\n\n    Event.Methods = {\n        isLeftClick: isLeftClick,\n        isMiddleClick: isMiddleClick,\n        isRightClick: isRightClick,\n\n        element: element,\n        findElement: findElement,\n\n        pointer: pointer,\n        pointerX: pointerX,\n        pointerY: pointerY,\n\n        stop: stop\n    };\n\n\n    var methods = Object.keys(Event.Methods).inject({ }, function(m, name) {\n        m[name] = Event.Methods[name].methodize();\n        return m;\n    });\n\n    if (Prototype.Browser.IE) {\n        function _relatedTarget(event) {\n            var element;\n            switch (event.type) {\n                case 'mouseover': element = event.fromElement; break;\n                case 'mouseout':  element = event.toElement;   break;\n                default: return null;\n            }\n            return Element.extend(element);\n        }\n\n        Object.extend(methods, {\n            stopPropagation: function() { this.cancelBubble = true },\n            preventDefault:  function() { this.returnValue = false },\n            inspect: function() { return '[object Event]' }\n        });\n\n        Event.extend = function(event, element) {\n            if (!event) return false;\n            if (event._extendedByPrototype) return event;\n\n            event._extendedByPrototype = Prototype.emptyFunction;\n            var pointer = Event.pointer(event);\n\n            Object.extend(event, {\n                target: event.srcElement || element,\n                relatedTarget: _relatedTarget(event),\n                pageX:  pointer.x,\n                pageY:  pointer.y\n            });\n\n            return Object.extend(event, methods);\n        };\n    } else {\n        Event.prototype = window.Event.prototype || document.createEvent('HTMLEvents').__proto__;\n        Object.extend(Event.prototype, methods);\n        Event.extend = Prototype.K;\n    }\n\n    function _createResponder(element, eventName, handler) {\n        var registry = Element.retrieve(element, 'prototype_event_registry');\n\n        if (Object.isUndefined(registry)) {\n            CACHE.push(element);\n            registry = Element.retrieve(element, 'prototype_event_registry', $H());\n        }\n\n        var respondersForEvent = registry.get(eventName);\n        if (Object.isUndefined(respondersForEvent)) {\n            respondersForEvent = [];\n            registry.set(eventName, respondersForEvent);\n        }\n\n        if (respondersForEvent.pluck('handler').include(handler)) return false;\n\n        var responder;\n        if (eventName.include(\":\")) {\n            responder = function(event) {\n                if (Object.isUndefined(event.eventName))\n                    return false;\n\n                if (event.eventName !== eventName)\n                    return false;\n\n                Event.extend(event, element);\n                handler.call(element, event);\n            };\n        } else {\n            if (!MOUSEENTER_MOUSELEAVE_EVENTS_SUPPORTED &&\n                (eventName === \"mouseenter\" || eventName === \"mouseleave\")) {\n                if (eventName === \"mouseenter\" || eventName === \"mouseleave\") {\n                    responder = function(event) {\n                        Event.extend(event, element);\n\n                        var parent = event.relatedTarget;\n                        while (parent && parent !== element) {\n                            try { parent = parent.parentNode; }\n                            catch(e) { parent = element; }\n                        }\n\n                        if (parent === element) return;\n\n                        handler.call(element, event);\n                    };\n                }\n            } else {\n                responder = function(event) {\n                    Event.extend(event, element);\n                    handler.call(element, event);\n                };\n            }\n        }\n\n        responder.handler = handler;\n        respondersForEvent.push(responder);\n        return responder;\n    }\n\n    function _destroyCache() {\n        for (var i = 0, length = CACHE.length; i < length; i++) {\n            Event.stopObserving(CACHE[i]);\n            CACHE[i] = null;\n        }\n    }\n\n    var CACHE = [];\n\n    if (Prototype.Browser.IE)\n        window.attachEvent('onunload', _destroyCache);\n\n    if (Prototype.Browser.WebKit)\n        window.addEventListener('unload', Prototype.emptyFunction, false);\n\n\n    var _getDOMEventName = Prototype.K;\n\n    if (!MOUSEENTER_MOUSELEAVE_EVENTS_SUPPORTED) {\n        _getDOMEventName = function(eventName) {\n            var translations = { mouseenter: \"mouseover\", mouseleave: \"mouseout\" };\n            return eventName in translations ? translations[eventName] : eventName;\n        };\n    }\n\n    function observe(element, eventName, handler) {\n        element = $(element);\n\n        var responder = _createResponder(element, eventName, handler);\n\n        if (!responder) return element;\n\n        if (eventName.include(':')) {\n            if (element.addEventListener)\n                element.addEventListener(\"dataavailable\", responder, false);\n            else {\n                element.attachEvent(\"ondataavailable\", responder);\n                element.attachEvent(\"onfilterchange\", responder);\n            }\n        } else {\n            var actualEventName = _getDOMEventName(eventName);\n\n            if (element.addEventListener)\n                element.addEventListener(actualEventName, responder, false);\n            else\n                element.attachEvent(\"on\" + actualEventName, responder);\n        }\n\n        return element;\n    }\n\n    function stopObserving(element, eventName, handler) {\n        element = $(element);\n\n        var registry = Element.retrieve(element, 'prototype_event_registry');\n\n        if (Object.isUndefined(registry)) return element;\n\n        if (eventName && !handler) {\n            var responders = registry.get(eventName);\n\n            if (Object.isUndefined(responders)) return element;\n\n            responders.each( function(r) {\n                Element.stopObserving(element, eventName, r.handler);\n            });\n            return element;\n        } else if (!eventName) {\n            registry.each( function(pair) {\n                var eventName = pair.key, responders = pair.value;\n\n                responders.each( function(r) {\n                    Element.stopObserving(element, eventName, r.handler);\n                });\n            });\n            return element;\n        }\n\n        var responders = registry.get(eventName);\n\n        if (!responders) return;\n\n        var responder = responders.find( function(r) { return r.handler === handler; });\n        if (!responder) return element;\n\n        var actualEventName = _getDOMEventName(eventName);\n\n        if (eventName.include(':')) {\n            if (element.removeEventListener)\n                element.removeEventListener(\"dataavailable\", responder, false);\n            else {\n                element.detachEvent(\"ondataavailable\", responder);\n                element.detachEvent(\"onfilterchange\",  responder);\n            }\n        } else {\n            if (element.removeEventListener)\n                element.removeEventListener(actualEventName, responder, false);\n            else\n                element.detachEvent('on' + actualEventName, responder);\n        }\n\n        registry.set(eventName, responders.without(responder));\n\n        return element;\n    }\n\n    function fire(element, eventName, memo, bubble) {\n        element = $(element);\n\n        if (Object.isUndefined(bubble))\n            bubble = true;\n\n        if (element == document && document.createEvent && !element.dispatchEvent)\n            element = document.documentElement;\n\n        var event;\n        if (document.createEvent) {\n            event = document.createEvent('HTMLEvents');\n            event.initEvent('dataavailable', true, true);\n        } else {\n            event = document.createEventObject();\n            event.eventType = bubble ? 'ondataavailable' : 'onfilterchange';\n        }\n\n        event.eventName = eventName;\n        event.memo = memo || { };\n\n        if (document.createEvent)\n            element.dispatchEvent(event);\n        else\n            element.fireEvent(event.eventType, event);\n\n        return Event.extend(event);\n    }\n\n\n    Object.extend(Event, Event.Methods);\n\n    Object.extend(Event, {\n        fire:          fire,\n        observe:       observe,\n        stopObserving: stopObserving\n    });\n\n    Element.addMethods({\n        fire:          fire,\n\n        observe:       observe,\n\n        stopObserving: stopObserving\n    });\n\n    Object.extend(document, {\n        fire:          fire.methodize(),\n\n        observe:       observe.methodize(),\n\n        stopObserving: stopObserving.methodize(),\n\n        loaded:        false\n    });\n\n    if (window.Event) Object.extend(window.Event, Event);\n    else window.Event = Event;\n})();\n\n(function() {\n    /* Support for the DOMContentLoaded event is based on work by Dan Webb,\n     Matthias Miller, Dean Edwards, John Resig, and Diego Perini. */\n\n    var timer;\n\n    function fireContentLoadedEvent() {\n        if (document.loaded) return;\n        if (timer) window.clearTimeout(timer);\n        document.loaded = true;\n        document.fire('dom:loaded');\n    }\n\n    function checkReadyState() {\n        if (document.readyState === 'complete') {\n            document.stopObserving('readystatechange', checkReadyState);\n            fireContentLoadedEvent();\n        }\n    }\n\n    function pollDoScroll() {\n        try { document.documentElement.doScroll('left'); }\n        catch(e) {\n            timer = pollDoScroll.defer();\n            return;\n        }\n        fireContentLoadedEvent();\n    }\n\n    if (document.addEventListener) {\n        document.addEventListener('DOMContentLoaded', fireContentLoadedEvent, false);\n    } else {\n        document.observe('readystatechange', checkReadyState);\n        if (window == top)\n            timer = pollDoScroll.defer();\n    }\n\n    Event.observe(window, 'load', fireContentLoadedEvent);\n})();\n\nElement.addMethods();\n\n/*------------------------------- DEPRECATED -------------------------------*/\n\nHash.toQueryString = Object.toQueryString;\n\nvar Toggle = { display: Element.toggle };\n\nElement.Methods.childOf = Element.Methods.descendantOf;\n\nvar Insertion = {\n    Before: function(element, content) {\n        return Element.insert(element, {before:content});\n    },\n\n    Top: function(element, content) {\n        return Element.insert(element, {top:content});\n    },\n\n    Bottom: function(element, content) {\n        return Element.insert(element, {bottom:content});\n    },\n\n    After: function(element, content) {\n        return Element.insert(element, {after:content});\n    }\n};\n\nvar $continue = new Error('\"throw $continue\" is deprecated, use \"return\" instead');\n\nvar Position = {\n    includeScrollOffsets: false,\n\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    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 = Element.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 = Element.cumulativeScrollOffset(element);\n\n        this.xcomp = x + offsetcache[0] - this.deltaX;\n        this.ycomp = y + offsetcache[1] - this.deltaY;\n        this.offset = Element.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    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\n    cumulativeOffset: Element.Methods.cumulativeOffset,\n\n    positionedOffset: Element.Methods.positionedOffset,\n\n    absolutize: function(element) {\n        Position.prepare();\n        return Element.absolutize(element);\n    },\n\n    relativize: function(element) {\n        Position.prepare();\n        return Element.relativize(element);\n    },\n\n    realOffset: Element.Methods.cumulativeScrollOffset,\n\n    offsetParent: Element.Methods.getOffsetParent,\n\n    page: Element.Methods.viewportOffset,\n\n    clone: function(source, target, options) {\n        options = options || { };\n        return Element.clonePosition(target, source, options);\n    }\n};\n\n/*--------------------------------------------------------------------------*/\n\nif (!document.getElementsByClassName) document.getElementsByClassName = function(instanceMethods){\n    function iter(name) {\n        return name.blank() ? null : \"[contains(concat(' ', @class, ' '), ' \" + name + \" ')]\";\n    }\n\n    instanceMethods.getElementsByClassName = Prototype.BrowserFeatures.XPath ?\n        function(element, className) {\n            className = className.toString().strip();\n            var cond = /\\s/.test(className) ? $w(className).map(iter).join('') : iter(className);\n            return cond ? document._getElementsByXPath('.//*' + cond, element) : [];\n        } : function(element, className) {\n            className = className.toString().strip();\n            var elements = [], classNames = (/\\s/.test(className) ? $w(className) : null);\n            if (!classNames && !className) return elements;\n\n            var nodes = $(element).getElementsByTagName('*');\n            className = ' ' + className + ' ';\n\n            for (var i = 0, child, cn; child = nodes[i]; i++) {\n                if (child.className && (cn = ' ' + child.className + ' ') && (cn.include(className) ||\n                    (classNames && classNames.all(function(name) {\n                        return !name.toString().blank() && cn.include(' ' + name + ' ');\n                    }))))\n                    elements.push(Element.extend(child));\n            }\n            return elements;\n        };\n\n    return function(className, parentElement) {\n        return $(parentElement || document.body).getElementsByClassName(className);\n    };\n}(Element.Methods);\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\n/*--------------------------------------------------------------------------*/"
  },
  {
    "path": "flowable-ui-web/modeler/editor-app/libs/prototype-1.7.3.js",
    "content": "/*  Prototype JavaScript framework, version 1.7.3\n *  (c) 2005-2010 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\n    Version: '1.7.3',\n\n    Browser: (function(){\n        var ua = navigator.userAgent;\n        var isOpera = Object.prototype.toString.call(window.opera) == '[object Opera]';\n        return {\n            IE:             !!window.attachEvent && !isOpera,\n            Opera:          isOpera,\n            WebKit:         ua.indexOf('AppleWebKit/') > -1,\n            Gecko:          ua.indexOf('Gecko') > -1 && ua.indexOf('KHTML') === -1,\n            MobileSafari:   /Apple.*Mobile/.test(ua)\n        }\n    })(),\n\n    BrowserFeatures: {\n        XPath: !!document.evaluate,\n\n        SelectorsAPI: !!document.querySelector,\n\n        ElementExtensions: (function() {\n            var constructor = window.Element || window.HTMLElement;\n            return !!(constructor && constructor.prototype);\n        })(),\n        SpecificElementExtensions: (function() {\n            if (typeof window.HTMLDivElement !== 'undefined')\n                return true;\n\n            var div = document.createElement('div'),\n                form = document.createElement('form'),\n                isSupported = false;\n\n            if (div['__proto__'] && (div['__proto__'] !== form['__proto__'])) {\n                isSupported = true;\n            }\n\n            div = form = null;\n\n            return isSupported;\n        })()\n    },\n\n    ScriptFragment: '<script[^>]*>([\\\\S\\\\s]*?)<\\/script\\\\s*>',\n    JSONFilter: /^\\/\\*-secure-([\\s\\S]*)\\*\\/\\s*$/,\n\n    emptyFunction: function() { },\n\n    K: function(x) { return x }\n};\n\nif (Prototype.Browser.MobileSafari)\n    Prototype.BrowserFeatures.SpecificElementExtensions = false;\n/* Based on Alex Arnell's inheritance implementation. */\n\nvar Class = (function() {\n\n    var IS_DONTENUM_BUGGY = (function(){\n        for (var p in { toString: 1 }) {\n            if (p === 'toString') return false;\n        }\n        return true;\n    })();\n\n    function subclass() {};\n    function create() {\n        var parent = null, properties = $A(arguments);\n        if (Object.isFunction(properties[0]))\n            parent = properties.shift();\n\n        function klass() {\n            this.initialize.apply(this, arguments);\n        }\n\n        Object.extend(klass, Class.Methods);\n        klass.superclass = parent;\n        klass.subclasses = [];\n\n        if (parent) {\n            subclass.prototype = parent.prototype;\n            klass.prototype = new subclass;\n            parent.subclasses.push(klass);\n        }\n\n        for (var i = 0, length = properties.length; i < length; i++)\n            klass.addMethods(properties[i]);\n\n        if (!klass.prototype.initialize)\n            klass.prototype.initialize = Prototype.emptyFunction;\n\n        klass.prototype.constructor = klass;\n        return klass;\n    }\n\n    function addMethods(source) {\n        var ancestor   = this.superclass && this.superclass.prototype,\n            properties = Object.keys(source);\n\n        if (IS_DONTENUM_BUGGY) {\n            if (source.toString != Object.prototype.toString)\n                properties.push(\"toString\");\n            if (source.valueOf != Object.prototype.valueOf)\n                properties.push(\"valueOf\");\n        }\n\n        for (var i = 0, length = properties.length; i < length; i++) {\n            var property = properties[i], value = source[property];\n            if (ancestor && Object.isFunction(value) &&\n                value.argumentNames()[0] == \"$super\") {\n                var method = value;\n                value = (function(m) {\n                    return function() { return ancestor[m].apply(this, arguments); };\n                })(property).wrap(method);\n\n                value.valueOf = (function(method) {\n                    return function() { return method.valueOf.call(method); };\n                })(method);\n\n                value.toString = (function(method) {\n                    return function() { return method.toString.call(method); };\n                })(method);\n            }\n            this.prototype[property] = value;\n        }\n\n        return this;\n    }\n\n    return {\n        create: create,\n        Methods: {\n            addMethods: addMethods\n        }\n    };\n})();\n(function() {\n\n    var _toString = Object.prototype.toString,\n        _hasOwnProperty = Object.prototype.hasOwnProperty,\n        NULL_TYPE = 'Null',\n        UNDEFINED_TYPE = 'Undefined',\n        BOOLEAN_TYPE = 'Boolean',\n        NUMBER_TYPE = 'Number',\n        STRING_TYPE = 'String',\n        OBJECT_TYPE = 'Object',\n        FUNCTION_CLASS = '[object Function]',\n        BOOLEAN_CLASS = '[object Boolean]',\n        NUMBER_CLASS = '[object Number]',\n        STRING_CLASS = '[object String]',\n        ARRAY_CLASS = '[object Array]',\n        DATE_CLASS = '[object Date]',\n        NATIVE_JSON_STRINGIFY_SUPPORT = window.JSON &&\n            typeof JSON.stringify === 'function' &&\n            JSON.stringify(0) === '0' &&\n            typeof JSON.stringify(Prototype.K) === 'undefined';\n\n\n\n    var DONT_ENUMS = ['toString', 'toLocaleString', 'valueOf',\n        'hasOwnProperty', 'isPrototypeOf', 'propertyIsEnumerable', 'constructor'];\n\n    var IS_DONTENUM_BUGGY = (function(){\n        for (var p in { toString: 1 }) {\n            if (p === 'toString') return false;\n        }\n        return true;\n    })();\n\n    function Type(o) {\n        switch(o) {\n            case null: return NULL_TYPE;\n            case (void 0): return UNDEFINED_TYPE;\n        }\n        var type = typeof o;\n        switch(type) {\n            case 'boolean': return BOOLEAN_TYPE;\n            case 'number':  return NUMBER_TYPE;\n            case 'string':  return STRING_TYPE;\n        }\n        return OBJECT_TYPE;\n    }\n\n    function extend(destination, source) {\n        for (var property in source)\n            destination[property] = source[property];\n        return destination;\n    }\n\n    function inspect(object) {\n        try {\n            if (isUndefined(object)) return 'undefined';\n            if (object === null) return 'null';\n            return object.inspect ? object.inspect() : String(object);\n        } catch (e) {\n            if (e instanceof RangeError) return '...';\n            throw e;\n        }\n    }\n\n    function toJSON(value) {\n        return Str('', { '': value }, []);\n    }\n\n    function Str(key, holder, stack) {\n        var value = holder[key];\n        if (Type(value) === OBJECT_TYPE && typeof value.toJSON === 'function') {\n            value = value.toJSON(key);\n        }\n\n        var _class = _toString.call(value);\n\n        switch (_class) {\n            case NUMBER_CLASS:\n            case BOOLEAN_CLASS:\n            case STRING_CLASS:\n                value = value.valueOf();\n        }\n\n        switch (value) {\n            case null: return 'null';\n            case true: return 'true';\n            case false: return 'false';\n        }\n\n        var type = typeof value;\n        switch (type) {\n            case 'string':\n                return value.inspect(true);\n            case 'number':\n                return isFinite(value) ? String(value) : 'null';\n            case 'object':\n\n                for (var i = 0, length = stack.length; i < length; i++) {\n                    if (stack[i] === value) {\n                        throw new TypeError(\"Cyclic reference to '\" + value + \"' in object\");\n                    }\n                }\n                stack.push(value);\n\n                var partial = [];\n                if (_class === ARRAY_CLASS) {\n                    for (var i = 0, length = value.length; i < length; i++) {\n                        var str = Str(i, value, stack);\n                        partial.push(typeof str === 'undefined' ? 'null' : str);\n                    }\n                    partial = '[' + partial.join(',') + ']';\n                } else {\n                    var keys = Object.keys(value);\n                    for (var i = 0, length = keys.length; i < length; i++) {\n                        var key = keys[i], str = Str(key, value, stack);\n                        if (typeof str !== \"undefined\") {\n                            partial.push(key.inspect(true)+ ':' + str);\n                        }\n                    }\n                    partial = '{' + partial.join(',') + '}';\n                }\n                stack.pop();\n                return partial;\n        }\n    }\n\n    function stringify(object) {\n        return JSON.stringify(object);\n    }\n\n    function toQueryString(object) {\n        return $H(object).toQueryString();\n    }\n\n    function toHTML(object) {\n        return object && object.toHTML ? object.toHTML() : String.interpret(object);\n    }\n\n    function keys(object) {\n        if (Type(object) !== OBJECT_TYPE) { throw new TypeError(); }\n        var results = [];\n        for (var property in object) {\n            if (_hasOwnProperty.call(object, property))\n                results.push(property);\n        }\n\n        if (IS_DONTENUM_BUGGY) {\n            for (var i = 0; property = DONT_ENUMS[i]; i++) {\n                if (_hasOwnProperty.call(object, property))\n                    results.push(property);\n            }\n        }\n\n        return results;\n    }\n\n    function values(object) {\n        var results = [];\n        for (var property in object)\n            results.push(object[property]);\n        return results;\n    }\n\n    function clone(object) {\n        return extend({ }, object);\n    }\n\n    function isElement(object) {\n        return !!(object && object.nodeType == 1);\n    }\n\n    function isArray(object) {\n        return _toString.call(object) === ARRAY_CLASS;\n    }\n\n    var hasNativeIsArray = (typeof Array.isArray == 'function')\n        && Array.isArray([]) && !Array.isArray({});\n\n    if (hasNativeIsArray) {\n        isArray = Array.isArray;\n    }\n\n    function isHash(object) {\n        return object instanceof Hash;\n    }\n\n    function isFunction(object) {\n        return _toString.call(object) === FUNCTION_CLASS;\n    }\n\n    function isString(object) {\n        return _toString.call(object) === STRING_CLASS;\n    }\n\n    function isNumber(object) {\n        return _toString.call(object) === NUMBER_CLASS;\n    }\n\n    function isDate(object) {\n        return _toString.call(object) === DATE_CLASS;\n    }\n\n    function isUndefined(object) {\n        return typeof object === \"undefined\";\n    }\n\n    extend(Object, {\n        extend:        extend,\n        inspect:       inspect,\n        toJSON:        NATIVE_JSON_STRINGIFY_SUPPORT ? stringify : toJSON,\n        toQueryString: toQueryString,\n        toHTML:        toHTML,\n        keys:          Object.keys || keys,\n        values:        values,\n        clone:         clone,\n        isElement:     isElement,\n        isArray:       isArray,\n        isHash:        isHash,\n        isFunction:    isFunction,\n        isString:      isString,\n        isNumber:      isNumber,\n        isDate:        isDate,\n        isUndefined:   isUndefined\n    });\n})();\nObject.extend(Function.prototype, (function() {\n    var slice = Array.prototype.slice;\n\n    function update(array, args) {\n        var arrayLength = array.length, length = args.length;\n        while (length--) array[arrayLength + length] = args[length];\n        return array;\n    }\n\n    function merge(array, args) {\n        array = slice.call(array, 0);\n        return update(array, args);\n    }\n\n    function argumentNames() {\n        var names = this.toString().match(/^[\\s\\(]*function[^(]*\\(([^)]*)\\)/)[1]\n            .replace(/\\/\\/.*?[\\r\\n]|\\/\\*(?:.|[\\r\\n])*?\\*\\//g, '')\n            .replace(/\\s+/g, '').split(',');\n        return names.length == 1 && !names[0] ? [] : names;\n    }\n\n\n    function bind(context) {\n        if (arguments.length < 2 && Object.isUndefined(arguments[0]))\n            return this;\n\n        if (!Object.isFunction(this))\n            throw new TypeError(\"The object is not callable.\");\n\n        var nop = function() {};\n        var __method = this, args = slice.call(arguments, 1);\n\n        var bound = function() {\n            var a = merge(args, arguments);\n            var c = this instanceof bound ? this : context;\n            return __method.apply(c, a);\n        };\n\n        nop.prototype   = this.prototype;\n        bound.prototype = new nop();\n\n        return bound;\n    }\n\n    function bindAsEventListener(context) {\n        var __method = this, args = slice.call(arguments, 1);\n        return function(event) {\n            var a = update([event || window.event], args);\n            return __method.apply(context, a);\n        }\n    }\n\n    function curry() {\n        if (!arguments.length) return this;\n        var __method = this, args = slice.call(arguments, 0);\n        return function() {\n            var a = merge(args, arguments);\n            return __method.apply(this, a);\n        }\n    }\n\n    function delay(timeout) {\n        var __method = this, args = slice.call(arguments, 1);\n        timeout = timeout * 1000;\n        return window.setTimeout(function() {\n            return __method.apply(__method, args);\n        }, timeout);\n    }\n\n    function defer() {\n        var args = update([0.01], arguments);\n        return this.delay.apply(this, args);\n    }\n\n    function wrap(wrapper) {\n        var __method = this;\n        return function() {\n            var a = update([__method.bind(this)], arguments);\n            return wrapper.apply(this, a);\n        }\n    }\n\n    function methodize() {\n        if (this._methodized) return this._methodized;\n        var __method = this;\n        return this._methodized = function() {\n            var a = update([this], arguments);\n            return __method.apply(null, a);\n        };\n    }\n\n    var extensions = {\n        argumentNames:       argumentNames,\n        bindAsEventListener: bindAsEventListener,\n        curry:               curry,\n        delay:               delay,\n        defer:               defer,\n        wrap:                wrap,\n        methodize:           methodize\n    };\n\n    if (!Function.prototype.bind)\n        extensions.bind = bind;\n\n    return extensions;\n})());\n\n\n\n(function(proto) {\n\n\n    function toISOString() {\n        return this.getUTCFullYear() + '-' +\n            (this.getUTCMonth() + 1).toPaddedString(2) + '-' +\n            this.getUTCDate().toPaddedString(2) + 'T' +\n            this.getUTCHours().toPaddedString(2) + ':' +\n            this.getUTCMinutes().toPaddedString(2) + ':' +\n            this.getUTCSeconds().toPaddedString(2) + 'Z';\n    }\n\n\n    function toJSON() {\n        return this.toISOString();\n    }\n\n    if (!proto.toISOString) proto.toISOString = toISOString;\n    if (!proto.toJSON) proto.toJSON = toJSON;\n\n})(Date.prototype);\n\n\nRegExp.prototype.match = RegExp.prototype.test;\n\nRegExp.escape = function(str) {\n    return String(str).replace(/([.*+?^=!:${}()|[\\]\\/\\\\])/g, '\\\\$1');\n};\nvar PeriodicalExecuter = Class.create({\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    execute: function() {\n        this.callback(this);\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.execute();\n                this.currentlyExecuting = false;\n            } catch(e) {\n                this.currentlyExecuting = false;\n                throw e;\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, (function() {\n    var NATIVE_JSON_PARSE_SUPPORT = window.JSON &&\n        typeof JSON.parse === 'function' &&\n        JSON.parse('{\"test\": true}').test;\n\n    function prepareReplacement(replacement) {\n        if (Object.isFunction(replacement)) return replacement;\n        var template = new Template(replacement);\n        return function(match) { return template.evaluate(match) };\n    }\n\n    function isNonEmptyRegExp(regexp) {\n        return regexp.source && regexp.source !== '(?:)';\n    }\n\n\n    function gsub(pattern, replacement) {\n        var result = '', source = this, match;\n        replacement = prepareReplacement(replacement);\n\n        if (Object.isString(pattern))\n            pattern = RegExp.escape(pattern);\n\n        if (!(pattern.length || isNonEmptyRegExp(pattern))) {\n            replacement = replacement('');\n            return replacement + source.split('').join(replacement) + replacement;\n        }\n\n        while (source.length > 0) {\n            match = source.match(pattern)\n            if (match && match[0].length > 0) {\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    function sub(pattern, replacement, count) {\n        replacement = prepareReplacement(replacement);\n        count = Object.isUndefined(count) ? 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    function scan(pattern, iterator) {\n        this.gsub(pattern, iterator);\n        return String(this);\n    }\n\n    function truncate(length, truncation) {\n        length = length || 30;\n        truncation = Object.isUndefined(truncation) ? '...' : truncation;\n        return this.length > length ?\n            this.slice(0, length - truncation.length) + truncation : String(this);\n    }\n\n    function strip() {\n        return this.replace(/^\\s+/, '').replace(/\\s+$/, '');\n    }\n\n    function stripTags() {\n        return this.replace(/<\\w+(\\s+(\"[^\"]*\"|'[^']*'|[^>])+)?(\\/)?>|<\\/\\w+>/gi, '');\n    }\n\n    function stripScripts() {\n        return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), '');\n    }\n\n    function extractScripts() {\n        var matchAll = new RegExp(Prototype.ScriptFragment, 'img'),\n            matchOne = new RegExp(Prototype.ScriptFragment, 'im');\n        return (this.match(matchAll) || []).map(function(scriptTag) {\n            return (scriptTag.match(matchOne) || ['', ''])[1];\n        });\n    }\n\n    function evalScripts() {\n        return this.extractScripts().map(function(script) { return eval(script); });\n    }\n\n    function escapeHTML() {\n        return this.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;');\n    }\n\n    function unescapeHTML() {\n        return this.stripTags().replace(/&lt;/g,'<').replace(/&gt;/g,'>').replace(/&amp;/g,'&');\n    }\n\n\n    function toQueryParams(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                    value = pair.length > 1 ? pair.join('=') : pair[0];\n\n                if (value != undefined) {\n                    value = value.gsub('+', ' ');\n                    value = decodeURIComponent(value);\n                }\n\n                if (key in hash) {\n                    if (!Object.isArray(hash[key])) hash[key] = [hash[key]];\n                    hash[key].push(value);\n                }\n                else hash[key] = value;\n            }\n            return hash;\n        });\n    }\n\n    function toArray() {\n        return this.split('');\n    }\n\n    function succ() {\n        return this.slice(0, this.length - 1) +\n            String.fromCharCode(this.charCodeAt(this.length - 1) + 1);\n    }\n\n    function times(count) {\n        return count < 1 ? '' : new Array(count + 1).join(this);\n    }\n\n    function camelize() {\n        return this.replace(/-+(.)?/g, function(match, chr) {\n            return chr ? chr.toUpperCase() : '';\n        });\n    }\n\n    function capitalize() {\n        return this.charAt(0).toUpperCase() + this.substring(1).toLowerCase();\n    }\n\n    function underscore() {\n        return this.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\n    function dasherize() {\n        return this.replace(/_/g, '-');\n    }\n\n    function inspect(useDoubleQuotes) {\n        var escapedString = this.replace(/[\\x00-\\x1f\\\\]/g, function(character) {\n            if (character in String.specialChar) {\n                return String.specialChar[character];\n            }\n            return '\\\\u00' + character.charCodeAt().toPaddedString(2, 16);\n        });\n        if (useDoubleQuotes) return '\"' + escapedString.replace(/\"/g, '\\\\\"') + '\"';\n        return \"'\" + escapedString.replace(/'/g, '\\\\\\'') + \"'\";\n    }\n\n    function unfilterJSON(filter) {\n        return this.replace(filter || Prototype.JSONFilter, '$1');\n    }\n\n    function isJSON() {\n        var str = this;\n        if (str.blank()) return false;\n        str = str.replace(/\\\\(?:[\"\\\\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@');\n        str = str.replace(/\"[^\"\\\\\\n\\r]*\"|true|false|null|-?\\d+(?:\\.\\d*)?(?:[eE][+\\-]?\\d+)?/g, ']');\n        str = str.replace(/(?:^|:|,)(?:\\s*\\[)+/g, '');\n        return (/^[\\],:{}\\s]*$/).test(str);\n    }\n\n    function evalJSON(sanitize) {\n        var json = this.unfilterJSON(),\n            cx = /[\\u00ad\\u0600-\\u0604\\u070f\\u17b4\\u17b5\\u200c-\\u200f\\u2028-\\u202f\\u2060-\\u206f\\ufeff\\ufff0-\\uffff\\u0000]/g;\n        if (cx.test(json)) {\n            json = json.replace(cx, function (a) {\n                return '\\\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);\n            });\n        }\n        try {\n            if (!sanitize || json.isJSON()) return eval('(' + json + ')');\n        } catch (e) { }\n        throw new SyntaxError('Badly formed JSON string: ' + this.inspect());\n    }\n\n    function parseJSON() {\n        var json = this.unfilterJSON();\n        return JSON.parse(json);\n    }\n\n    function include(pattern) {\n        return this.indexOf(pattern) > -1;\n    }\n\n    function startsWith(pattern, position) {\n        position = Object.isNumber(position) ? position : 0;\n        return this.lastIndexOf(pattern, position) === position;\n    }\n\n    function endsWith(pattern, position) {\n        pattern = String(pattern);\n        position = Object.isNumber(position) ? position : this.length;\n        if (position < 0) position = 0;\n        if (position > this.length) position = this.length;\n        var d = position - pattern.length;\n        return d >= 0 && this.indexOf(pattern, d) === d;\n    }\n\n    function empty() {\n        return this == '';\n    }\n\n    function blank() {\n        return /^\\s*$/.test(this);\n    }\n\n    function interpolate(object, pattern) {\n        return new Template(this, pattern).evaluate(object);\n    }\n\n    return {\n        gsub:           gsub,\n        sub:            sub,\n        scan:           scan,\n        truncate:       truncate,\n        strip:          String.prototype.trim || strip,\n        stripTags:      stripTags,\n        stripScripts:   stripScripts,\n        extractScripts: extractScripts,\n        evalScripts:    evalScripts,\n        escapeHTML:     escapeHTML,\n        unescapeHTML:   unescapeHTML,\n        toQueryParams:  toQueryParams,\n        parseQuery:     toQueryParams,\n        toArray:        toArray,\n        succ:           succ,\n        times:          times,\n        camelize:       camelize,\n        capitalize:     capitalize,\n        underscore:     underscore,\n        dasherize:      dasherize,\n        inspect:        inspect,\n        unfilterJSON:   unfilterJSON,\n        isJSON:         isJSON,\n        evalJSON:       NATIVE_JSON_PARSE_SUPPORT ? parseJSON : evalJSON,\n        include:        include,\n        startsWith:     String.prototype.startsWith || startsWith,\n        endsWith:       String.prototype.endsWith || endsWith,\n        empty:          empty,\n        blank:          blank,\n        interpolate:    interpolate\n    };\n})());\n\nvar Template = Class.create({\n    initialize: function(template, pattern) {\n        this.template = template.toString();\n        this.pattern = pattern || Template.Pattern;\n    },\n\n    evaluate: function(object) {\n        if (object && Object.isFunction(object.toTemplateReplacements))\n            object = object.toTemplateReplacements();\n\n        return this.template.gsub(this.pattern, function(match) {\n            if (object == null) return (match[1] + '');\n\n            var before = match[1] || '';\n            if (before == '\\\\') return match[2];\n\n            var ctx = object, expr = match[3],\n                pattern = /^([^.[]+|\\[((?:.*?[^\\\\])?)\\])(\\.|\\[|$)/;\n\n            match = pattern.exec(expr);\n            if (match == null) return before;\n\n            while (match != null) {\n                var comp = match[1].startsWith('[') ? match[2].replace(/\\\\\\\\]/g, ']') : match[1];\n                ctx = ctx[comp];\n                if (null == ctx || '' == match[3]) break;\n                expr = expr.substring('[' == match[3] ? match[1].length : match[0].length);\n                match = pattern.exec(expr);\n            }\n\n            return before + String.interpret(ctx);\n        });\n    }\n});\nTemplate.Pattern = /(^|.|\\r|\\n)(#\\{(.*?)\\})/;\n\nvar $break = { };\n\nvar Enumerable = (function() {\n    function each(iterator, context) {\n        try {\n            this._each(iterator, context);\n        } catch (e) {\n            if (e != $break) throw e;\n        }\n        return this;\n    }\n\n    function eachSlice(number, iterator, context) {\n        var index = -number, slices = [], array = this.toArray();\n        if (number < 1) return array;\n        while ((index += number) < array.length)\n            slices.push(array.slice(index, index+number));\n        return slices.collect(iterator, context);\n    }\n\n    function all(iterator, context) {\n        iterator = iterator || Prototype.K;\n        var result = true;\n        this.each(function(value, index) {\n            result = result && !!iterator.call(context, value, index, this);\n            if (!result) throw $break;\n        }, this);\n        return result;\n    }\n\n    function any(iterator, context) {\n        iterator = iterator || Prototype.K;\n        var result = false;\n        this.each(function(value, index) {\n            if (result = !!iterator.call(context, value, index, this))\n                throw $break;\n        }, this);\n        return result;\n    }\n\n    function collect(iterator, context) {\n        iterator = iterator || Prototype.K;\n        var results = [];\n        this.each(function(value, index) {\n            results.push(iterator.call(context, value, index, this));\n        }, this);\n        return results;\n    }\n\n    function detect(iterator, context) {\n        var result;\n        this.each(function(value, index) {\n            if (iterator.call(context, value, index, this)) {\n                result = value;\n                throw $break;\n            }\n        }, this);\n        return result;\n    }\n\n    function findAll(iterator, context) {\n        var results = [];\n        this.each(function(value, index) {\n            if (iterator.call(context, value, index, this))\n                results.push(value);\n        }, this);\n        return results;\n    }\n\n    function grep(filter, iterator, context) {\n        iterator = iterator || Prototype.K;\n        var results = [];\n\n        if (Object.isString(filter))\n            filter = new RegExp(RegExp.escape(filter));\n\n        this.each(function(value, index) {\n            if (filter.match(value))\n                results.push(iterator.call(context, value, index, this));\n        }, this);\n        return results;\n    }\n\n    function include(object) {\n        if (Object.isFunction(this.indexOf) && this.indexOf(object) != -1)\n            return true;\n\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    function inGroupsOf(number, fillWith) {\n        fillWith = Object.isUndefined(fillWith) ? null : fillWith;\n        return this.eachSlice(number, function(slice) {\n            while(slice.length < number) slice.push(fillWith);\n            return slice;\n        });\n    }\n\n    function inject(memo, iterator, context) {\n        this.each(function(value, index) {\n            memo = iterator.call(context, memo, value, index, this);\n        }, this);\n        return memo;\n    }\n\n    function invoke(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    function max(iterator, context) {\n        iterator = iterator || Prototype.K;\n        var result;\n        this.each(function(value, index) {\n            value = iterator.call(context, value, index, this);\n            if (result == null || value >= result)\n                result = value;\n        }, this);\n        return result;\n    }\n\n    function min(iterator, context) {\n        iterator = iterator || Prototype.K;\n        var result;\n        this.each(function(value, index) {\n            value = iterator.call(context, value, index, this);\n            if (result == null || value < result)\n                result = value;\n        }, this);\n        return result;\n    }\n\n    function partition(iterator, context) {\n        iterator = iterator || Prototype.K;\n        var trues = [], falses = [];\n        this.each(function(value, index) {\n            (iterator.call(context, value, index, this) ?\n                trues : falses).push(value);\n        }, this);\n        return [trues, falses];\n    }\n\n    function pluck(property) {\n        var results = [];\n        this.each(function(value) {\n            results.push(value[property]);\n        });\n        return results;\n    }\n\n    function reject(iterator, context) {\n        var results = [];\n        this.each(function(value, index) {\n            if (!iterator.call(context, value, index, this))\n                results.push(value);\n        }, this);\n        return results;\n    }\n\n    function sortBy(iterator, context) {\n        return this.map(function(value, index) {\n            return {\n                value: value,\n                criteria: iterator.call(context, value, index, this)\n            };\n        }, this).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    function toArray() {\n        return this.map();\n    }\n\n    function zip() {\n        var iterator = Prototype.K, args = $A(arguments);\n        if (Object.isFunction(args.last()))\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    function size() {\n        return this.toArray().length;\n    }\n\n    function inspect() {\n        return '#<Enumerable:' + this.toArray().inspect() + '>';\n    }\n\n\n\n\n\n\n\n\n\n    return {\n        each:       each,\n        eachSlice:  eachSlice,\n        all:        all,\n        every:      all,\n        any:        any,\n        some:       any,\n        collect:    collect,\n        map:        collect,\n        detect:     detect,\n        findAll:    findAll,\n        select:     findAll,\n        filter:     findAll,\n        grep:       grep,\n        include:    include,\n        member:     include,\n        inGroupsOf: inGroupsOf,\n        inject:     inject,\n        invoke:     invoke,\n        max:        max,\n        min:        min,\n        partition:  partition,\n        pluck:      pluck,\n        reject:     reject,\n        sortBy:     sortBy,\n        toArray:    toArray,\n        entries:    toArray,\n        zip:        zip,\n        size:       size,\n        inspect:    inspect,\n        find:       detect\n    };\n})();\n\nfunction $A(iterable) {\n    if (!iterable) return [];\n    if ('toArray' in Object(iterable)) return iterable.toArray();\n    var length = iterable.length || 0, results = new Array(length);\n    while (length--) results[length] = iterable[length];\n    return results;\n}\n\n\nfunction $w(string) {\n    if (!Object.isString(string)) return [];\n    string = string.strip();\n    return string ? string.split(/\\s+/) : [];\n}\n\nArray.from = $A;\n\n\n(function() {\n    var arrayProto = Array.prototype,\n        slice = arrayProto.slice,\n        _each = arrayProto.forEach; // use native browser JS 1.6 implementation if available\n\n    function each(iterator, context) {\n        for (var i = 0, length = this.length >>> 0; i < length; i++) {\n            if (i in this) iterator.call(context, this[i], i, this);\n        }\n    }\n    if (!_each) _each = each;\n\n    function clear() {\n        this.length = 0;\n        return this;\n    }\n\n    function first() {\n        return this[0];\n    }\n\n    function last() {\n        return this[this.length - 1];\n    }\n\n    function compact() {\n        return this.select(function(value) {\n            return value != null;\n        });\n    }\n\n    function flatten() {\n        return this.inject([], function(array, value) {\n            if (Object.isArray(value))\n                return array.concat(value.flatten());\n            array.push(value);\n            return array;\n        });\n    }\n\n    function without() {\n        var values = slice.call(arguments, 0);\n        return this.select(function(value) {\n            return !values.include(value);\n        });\n    }\n\n    function reverse(inline) {\n        return (inline === false ? this.toArray() : this)._reverse();\n    }\n\n    function uniq(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    function intersect(array) {\n        return this.uniq().findAll(function(item) {\n            return array.indexOf(item) !== -1;\n        });\n    }\n\n\n    function clone() {\n        return slice.call(this, 0);\n    }\n\n    function size() {\n        return this.length;\n    }\n\n    function inspect() {\n        return '[' + this.map(Object.inspect).join(', ') + ']';\n    }\n\n    function indexOf(item, i) {\n        if (this == null) throw new TypeError();\n\n        var array = Object(this), length = array.length >>> 0;\n        if (length === 0) return -1;\n\n        i = Number(i);\n        if (isNaN(i)) {\n            i = 0;\n        } else if (i !== 0 && isFinite(i)) {\n            i = (i > 0 ? 1 : -1) * Math.floor(Math.abs(i));\n        }\n\n        if (i > length) return -1;\n\n        var k = i >= 0 ? i : Math.max(length - Math.abs(i), 0);\n        for (; k < length; k++)\n            if (k in array && array[k] === item) return k;\n        return -1;\n    }\n\n\n    function lastIndexOf(item, i) {\n        if (this == null) throw new TypeError();\n\n        var array = Object(this), length = array.length >>> 0;\n        if (length === 0) return -1;\n\n        if (!Object.isUndefined(i)) {\n            i = Number(i);\n            if (isNaN(i)) {\n                i = 0;\n            } else if (i !== 0 && isFinite(i)) {\n                i = (i > 0 ? 1 : -1) * Math.floor(Math.abs(i));\n            }\n        } else {\n            i = length;\n        }\n\n        var k = i >= 0 ? Math.min(i, length - 1) :\n            length - Math.abs(i);\n\n        for (; k >= 0; k--)\n            if (k in array && array[k] === item) return k;\n        return -1;\n    }\n\n    function concat(_) {\n        var array = [], items = slice.call(arguments, 0), item, n = 0;\n        items.unshift(this);\n        for (var i = 0, length = items.length; i < length; i++) {\n            item = items[i];\n            if (Object.isArray(item) && !('callee' in item)) {\n                for (var j = 0, arrayLength = item.length; j < arrayLength; j++) {\n                    if (j in item) array[n] = item[j];\n                    n++;\n                }\n            } else {\n                array[n++] = item;\n            }\n        }\n        array.length = n;\n        return array;\n    }\n\n\n    function wrapNative(method) {\n        return function() {\n            if (arguments.length === 0) {\n                return method.call(this, Prototype.K);\n            } else if (arguments[0] === undefined) {\n                var args = slice.call(arguments, 1);\n                args.unshift(Prototype.K);\n                return method.apply(this, args);\n            } else {\n                return method.apply(this, arguments);\n            }\n        };\n    }\n\n\n    function map(iterator) {\n        if (this == null) throw new TypeError();\n        iterator = iterator || Prototype.K;\n\n        var object = Object(this);\n        var results = [], context = arguments[1], n = 0;\n\n        for (var i = 0, length = object.length >>> 0; i < length; i++) {\n            if (i in object) {\n                results[n] = iterator.call(context, object[i], i, object);\n            }\n            n++;\n        }\n        results.length = n;\n        return results;\n    }\n\n    if (arrayProto.map) {\n        map = wrapNative(Array.prototype.map);\n    }\n\n    function filter(iterator) {\n        if (this == null || !Object.isFunction(iterator))\n            throw new TypeError();\n\n        var object = Object(this);\n        var results = [], context = arguments[1], value;\n\n        for (var i = 0, length = object.length >>> 0; i < length; i++) {\n            if (i in object) {\n                value = object[i];\n                if (iterator.call(context, value, i, object)) {\n                    results.push(value);\n                }\n            }\n        }\n        return results;\n    }\n\n    if (arrayProto.filter) {\n        filter = Array.prototype.filter;\n    }\n\n    function some(iterator) {\n        if (this == null) throw new TypeError();\n        iterator = iterator || Prototype.K;\n        var context = arguments[1];\n\n        var object = Object(this);\n        for (var i = 0, length = object.length >>> 0; i < length; i++) {\n            if (i in object && iterator.call(context, object[i], i, object)) {\n                return true;\n            }\n        }\n\n        return false;\n    }\n\n    if (arrayProto.some) {\n        some = wrapNative(Array.prototype.some);\n    }\n\n    function every(iterator) {\n        if (this == null) throw new TypeError();\n        iterator = iterator || Prototype.K;\n        var context = arguments[1];\n\n        var object = Object(this);\n        for (var i = 0, length = object.length >>> 0; i < length; i++) {\n            if (i in object && !iterator.call(context, object[i], i, object)) {\n                return false;\n            }\n        }\n\n        return true;\n    }\n\n    if (arrayProto.every) {\n        every = wrapNative(Array.prototype.every);\n    }\n\n\n    Object.extend(arrayProto, Enumerable);\n\n    if (arrayProto.entries === Enumerable.entries) {\n        delete arrayProto.entries;\n    }\n\n    if (!arrayProto._reverse)\n        arrayProto._reverse = arrayProto.reverse;\n\n    Object.extend(arrayProto, {\n        _each:     _each,\n\n        map:       map,\n        collect:   map,\n        select:    filter,\n        filter:    filter,\n        findAll:   filter,\n        some:      some,\n        any:       some,\n        every:     every,\n        all:       every,\n\n        clear:     clear,\n        first:     first,\n        last:      last,\n        compact:   compact,\n        flatten:   flatten,\n        without:   without,\n        reverse:   reverse,\n        uniq:      uniq,\n        intersect: intersect,\n        clone:     clone,\n        toArray:   clone,\n        size:      size,\n        inspect:   inspect\n    });\n\n    var CONCAT_ARGUMENTS_BUGGY = (function() {\n        return [].concat(arguments)[0][0] !== 1;\n    })(1,2);\n\n    if (CONCAT_ARGUMENTS_BUGGY) arrayProto.concat = concat;\n\n    if (!arrayProto.indexOf) arrayProto.indexOf = indexOf;\n    if (!arrayProto.lastIndexOf) arrayProto.lastIndexOf = lastIndexOf;\n})();\nfunction $H(object) {\n    return new Hash(object);\n};\n\nvar Hash = Class.create(Enumerable, (function() {\n    function initialize(object) {\n        this._object = Object.isHash(object) ? object.toObject() : Object.clone(object);\n    }\n\n\n    function _each(iterator, context) {\n        var i = 0;\n        for (var key in this._object) {\n            var value = this._object[key], pair = [key, value];\n            pair.key = key;\n            pair.value = value;\n            iterator.call(context, pair, i);\n            i++;\n        }\n    }\n\n    function set(key, value) {\n        return this._object[key] = value;\n    }\n\n    function get(key) {\n        if (this._object[key] !== Object.prototype[key])\n            return this._object[key];\n    }\n\n    function unset(key) {\n        var value = this._object[key];\n        delete this._object[key];\n        return value;\n    }\n\n    function toObject() {\n        return Object.clone(this._object);\n    }\n\n\n\n    function keys() {\n        return this.pluck('key');\n    }\n\n    function values() {\n        return this.pluck('value');\n    }\n\n    function index(value) {\n        var match = this.detect(function(pair) {\n            return pair.value === value;\n        });\n        return match && match.key;\n    }\n\n    function merge(object) {\n        return this.clone().update(object);\n    }\n\n    function update(object) {\n        return new Hash(object).inject(this, function(result, pair) {\n            result.set(pair.key, pair.value);\n            return result;\n        });\n    }\n\n    function toQueryPair(key, value) {\n        if (Object.isUndefined(value)) return key;\n\n        value = String.interpret(value);\n\n        value = value.gsub(/(\\r)?\\n/, '\\r\\n');\n        value = encodeURIComponent(value);\n        value = value.gsub(/%20/, '+');\n        return key + '=' + value;\n    }\n\n    function toQueryString() {\n        return this.inject([], function(results, pair) {\n            var key = encodeURIComponent(pair.key), values = pair.value;\n\n            if (values && typeof values == 'object') {\n                if (Object.isArray(values)) {\n                    var queryValues = [];\n                    for (var i = 0, len = values.length, value; i < len; i++) {\n                        value = values[i];\n                        queryValues.push(toQueryPair(key, value));\n                    }\n                    return results.concat(queryValues);\n                }\n            } else results.push(toQueryPair(key, values));\n            return results;\n        }).join('&');\n    }\n\n    function inspect() {\n        return '#<Hash:{' + this.map(function(pair) {\n                return pair.map(Object.inspect).join(': ');\n            }).join(', ') + '}>';\n    }\n\n    function clone() {\n        return new Hash(this);\n    }\n\n    return {\n        initialize:             initialize,\n        _each:                  _each,\n        set:                    set,\n        get:                    get,\n        unset:                  unset,\n        toObject:               toObject,\n        toTemplateReplacements: toObject,\n        keys:                   keys,\n        values:                 values,\n        index:                  index,\n        merge:                  merge,\n        update:                 update,\n        toQueryString:          toQueryString,\n        inspect:                inspect,\n        toJSON:                 toObject,\n        clone:                  clone\n    };\n})());\n\nHash.from = $H;\nObject.extend(Number.prototype, (function() {\n    function toColorPart() {\n        return this.toPaddedString(2, 16);\n    }\n\n    function succ() {\n        return this + 1;\n    }\n\n    function times(iterator, context) {\n        $R(0, this, true).each(iterator, context);\n        return this;\n    }\n\n    function toPaddedString(length, radix) {\n        var string = this.toString(radix || 10);\n        return '0'.times(length - string.length) + string;\n    }\n\n    function abs() {\n        return Math.abs(this);\n    }\n\n    function round() {\n        return Math.round(this);\n    }\n\n    function ceil() {\n        return Math.ceil(this);\n    }\n\n    function floor() {\n        return Math.floor(this);\n    }\n\n    return {\n        toColorPart:    toColorPart,\n        succ:           succ,\n        times:          times,\n        toPaddedString: toPaddedString,\n        abs:            abs,\n        round:          round,\n        ceil:           ceil,\n        floor:          floor\n    };\n})());\n\nfunction $R(start, end, exclusive) {\n    return new ObjectRange(start, end, exclusive);\n}\n\nvar ObjectRange = Class.create(Enumerable, (function() {\n    function initialize(start, end, exclusive) {\n        this.start = start;\n        this.end = end;\n        this.exclusive = exclusive;\n    }\n\n    function _each(iterator, context) {\n        var value = this.start, i;\n        for (i = 0; this.include(value); i++) {\n            iterator.call(context, value, i);\n            value = value.succ();\n        }\n    }\n\n    function include(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    return {\n        initialize: initialize,\n        _each:      _each,\n        include:    include\n    };\n})());\n\n\n\nvar Abstract = { };\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\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, context) {\n        this.responders._each(iterator, context);\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 (Object.isFunction(responder[callback])) {\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() { Ajax.activeRequestCount++ },\n    onComplete: function() { Ajax.activeRequestCount-- }\n});\nAjax.Base = Class.create({\n    initialize: 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            evalJSON:     true,\n            evalJS:       true\n        };\n        Object.extend(this.options, options || { });\n\n        this.options.method = this.options.method.toLowerCase();\n\n        if (Object.isHash(this.options.parameters))\n            this.options.parameters = this.options.parameters.toObject();\n    }\n});\nAjax.Request = Class.create(Ajax.Base, {\n    _complete: false,\n\n    initialize: function($super, url, options) {\n        $super(options);\n        this.transport = Ajax.getTransport();\n        this.request(url);\n    },\n\n    request: function(url) {\n        this.url = url;\n        this.method = this.options.method;\n        var params = Object.isString(this.options.parameters) ?\n            this.options.parameters :\n            Object.toQueryString(this.options.parameters);\n\n        if (!['get', 'post'].include(this.method)) {\n            params += (params ? '&' : '') + \"_method=\" + this.method;\n            this.method = 'post';\n        }\n\n        if (params && this.method === 'get') {\n            this.url += (this.url.include('?') ? '&' : '?') + params;\n        }\n\n        this.parameters = params.toQueryParams();\n\n        try {\n            var response = new Ajax.Response(this);\n            if (this.options.onCreate) this.options.onCreate(response);\n            Ajax.Responders.dispatch('onCreate', this, response);\n\n            this.transport.open(this.method.toUpperCase(), this.url,\n                this.options.asynchronous);\n\n            if (this.options.asynchronous) this.respondToReadyState.bind(this).defer(1);\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        if (typeof this.options.requestHeaders == 'object') {\n            var extras = this.options.requestHeaders;\n\n            if (Object.isFunction(extras.push))\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            if (headers[name] != null)\n                this.transport.setRequestHeader(name, headers[name]);\n    },\n\n    success: function() {\n        var status = this.getStatus();\n        return !status || (status >= 200 && status < 300) || status == 304;\n    },\n\n    getStatus: function() {\n        try {\n            if (this.transport.status === 1223) return 204;\n            return this.transport.status || 0;\n        } catch (e) { return 0 }\n    },\n\n    respondToReadyState: function(readyState) {\n        var state = Ajax.Request.Events[readyState], response = new Ajax.Response(this);\n\n        if (state == 'Complete') {\n            try {\n                this._complete = true;\n                (this.options['on' + response.status]\n                || this.options['on' + (this.success() ? 'Success' : 'Failure')]\n                || Prototype.emptyFunction)(response, response.headerJSON);\n            } catch (e) {\n                this.dispatchException(e);\n            }\n\n            var contentType = response.getHeader('Content-type');\n            if (this.options.evalJS == 'force'\n                || (this.options.evalJS && this.isSameOrigin() && contentType\n                && contentType.match(/^\\s*(text|application)\\/(x-)?(java|ecma)script(;.*)?\\s*$/i)))\n                this.evalResponse();\n        }\n\n        try {\n            (this.options['on' + state] || Prototype.emptyFunction)(response, response.headerJSON);\n            Ajax.Responders.dispatch('on' + state, this, response, response.headerJSON);\n        } catch (e) {\n            this.dispatchException(e);\n        }\n\n        if (state == 'Complete') {\n            this.transport.onreadystatechange = Prototype.emptyFunction;\n        }\n    },\n\n    isSameOrigin: function() {\n        var m = this.url.match(/^\\s*https?:\\/\\/[^\\/]*/);\n        return !m || (m[0] == '#{protocol}//#{domain}#{port}'.interpolate({\n                protocol: location.protocol,\n                domain: document.domain,\n                port: location.port ? ':' + location.port : ''\n            }));\n    },\n\n    getHeader: function(name) {\n        try {\n            return this.transport.getResponseHeader(name) || 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.Request.Events =\n    ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete'];\n\n\n\n\n\n\n\n\nAjax.Response = Class.create({\n    initialize: function(request){\n        this.request = request;\n        var transport  = this.transport  = request.transport,\n            readyState = this.readyState = transport.readyState;\n\n        if ((readyState > 2 && !Prototype.Browser.IE) || readyState == 4) {\n            this.status       = this.getStatus();\n            this.statusText   = this.getStatusText();\n            this.responseText = String.interpret(transport.responseText);\n            this.headerJSON   = this._getHeaderJSON();\n        }\n\n        if (readyState == 4) {\n            var xml = transport.responseXML;\n            this.responseXML  = Object.isUndefined(xml) ? null : xml;\n            this.responseJSON = this._getResponseJSON();\n        }\n    },\n\n    status:      0,\n\n    statusText: '',\n\n    getStatus: Ajax.Request.prototype.getStatus,\n\n    getStatusText: function() {\n        try {\n            return this.transport.statusText || '';\n        } catch (e) { return '' }\n    },\n\n    getHeader: Ajax.Request.prototype.getHeader,\n\n    getAllHeaders: function() {\n        try {\n            return this.getAllResponseHeaders();\n        } catch (e) { return null }\n    },\n\n    getResponseHeader: function(name) {\n        return this.transport.getResponseHeader(name);\n    },\n\n    getAllResponseHeaders: function() {\n        return this.transport.getAllResponseHeaders();\n    },\n\n    _getHeaderJSON: function() {\n        var json = this.getHeader('X-JSON');\n        if (!json) return null;\n\n        try {\n            json = decodeURIComponent(escape(json));\n        } catch(e) {\n        }\n\n        try {\n            return json.evalJSON(this.request.options.sanitizeJSON ||\n                !this.request.isSameOrigin());\n        } catch (e) {\n            this.request.dispatchException(e);\n        }\n    },\n\n    _getResponseJSON: function() {\n        var options = this.request.options;\n        if (!options.evalJSON || (options.evalJSON != 'force' &&\n            !(this.getHeader('Content-type') || '').include('application/json')) ||\n            this.responseText.blank())\n            return null;\n        try {\n            return this.responseText.evalJSON(options.sanitizeJSON ||\n                !this.request.isSameOrigin());\n        } catch (e) {\n            this.request.dispatchException(e);\n        }\n    }\n});\n\nAjax.Updater = Class.create(Ajax.Request, {\n    initialize: function($super, container, url, options) {\n        this.container = {\n            success: (container.success || container),\n            failure: (container.failure || (container.success ? null : container))\n        };\n\n        options = Object.clone(options);\n        var onComplete = options.onComplete;\n        options.onComplete = (function(response, json) {\n            this.updateContent(response.responseText);\n            if (Object.isFunction(onComplete)) onComplete(response, json);\n        }).bind(this);\n\n        $super(url, options);\n    },\n\n    updateContent: function(responseText) {\n        var receiver = this.container[this.success() ? 'success' : 'failure'],\n            options = this.options;\n\n        if (!options.evalScripts) responseText = responseText.stripScripts();\n\n        if (receiver = $(receiver)) {\n            if (options.insertion) {\n                if (Object.isString(options.insertion)) {\n                    var insertion = { }; insertion[options.insertion] = responseText;\n                    receiver.insert(insertion);\n                }\n                else options.insertion(receiver, responseText);\n            }\n            else receiver.update(responseText);\n        }\n    }\n});\n\nAjax.PeriodicalUpdater = Class.create(Ajax.Base, {\n    initialize: function($super, container, url, options) {\n        $super(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(response) {\n        if (this.options.decay) {\n            this.decay = (response.responseText == this.lastText ?\n                this.decay * this.options.decay : 1);\n\n            this.lastText = response.responseText;\n        }\n        this.timer = this.onTimerEvent.bind(this).delay(this.decay * this.frequency);\n    },\n\n    onTimerEvent: function() {\n        this.updater = new Ajax.Updater(this.container, this.url, this.options);\n    }\n});\n\n(function(GLOBAL) {\n\n    var UNDEFINED;\n    var SLICE = Array.prototype.slice;\n\n    var DIV = document.createElement('div');\n\n\n    function $(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\n        if (Object.isString(element))\n            element = document.getElementById(element);\n        return Element.extend(element);\n    }\n\n    GLOBAL.$ = $;\n\n\n    if (!GLOBAL.Node) GLOBAL.Node = {};\n\n    if (!GLOBAL.Node.ELEMENT_NODE) {\n        Object.extend(GLOBAL.Node, {\n            ELEMENT_NODE:                1,\n            ATTRIBUTE_NODE:              2,\n            TEXT_NODE:                   3,\n            CDATA_SECTION_NODE:          4,\n            ENTITY_REFERENCE_NODE:       5,\n            ENTITY_NODE:                 6,\n            PROCESSING_INSTRUCTION_NODE: 7,\n            COMMENT_NODE:                8,\n            DOCUMENT_NODE:               9,\n            DOCUMENT_TYPE_NODE:         10,\n            DOCUMENT_FRAGMENT_NODE:     11,\n            NOTATION_NODE:              12\n        });\n    }\n\n    var ELEMENT_CACHE = {};\n\n    function shouldUseCreationCache(tagName, attributes) {\n        if (tagName === 'select') return false;\n        if ('type' in attributes) return false;\n        return true;\n    }\n\n    var HAS_EXTENDED_CREATE_ELEMENT_SYNTAX = (function(){\n        try {\n            var el = document.createElement('<input name=\"x\">');\n            return el.tagName.toLowerCase() === 'input' && el.name === 'x';\n        }\n        catch(err) {\n            return false;\n        }\n    })();\n\n\n    var oldElement = GLOBAL.Element;\n    function Element(tagName, attributes) {\n        attributes = attributes || {};\n        tagName = tagName.toLowerCase();\n\n        if (HAS_EXTENDED_CREATE_ELEMENT_SYNTAX && attributes.name) {\n            tagName = '<' + tagName + ' name=\"' + attributes.name + '\">';\n            delete attributes.name;\n            return Element.writeAttribute(document.createElement(tagName), attributes);\n        }\n\n        if (!ELEMENT_CACHE[tagName])\n            ELEMENT_CACHE[tagName] = Element.extend(document.createElement(tagName));\n\n        var node = shouldUseCreationCache(tagName, attributes) ?\n            ELEMENT_CACHE[tagName].cloneNode(false) : document.createElement(tagName);\n\n        return Element.writeAttribute(node, attributes);\n    }\n\n    GLOBAL.Element = Element;\n\n    Object.extend(GLOBAL.Element, oldElement || {});\n    if (oldElement) GLOBAL.Element.prototype = oldElement.prototype;\n\n    Element.Methods = { ByTag: {}, Simulated: {} };\n\n    var methods = {};\n\n    var INSPECT_ATTRIBUTES = { id: 'id', className: 'class' };\n    function inspect(element) {\n        element = $(element);\n        var result = '<' + element.tagName.toLowerCase();\n\n        var attribute, value;\n        for (var property in INSPECT_ATTRIBUTES) {\n            attribute = INSPECT_ATTRIBUTES[property];\n            value = (element[property] || '').toString();\n            if (value) result += ' ' + attribute + '=' + value.inspect(true);\n        }\n\n        return result + '>';\n    }\n\n    methods.inspect = inspect;\n\n\n    function visible(element) {\n        return $(element).getStyle('display') !== 'none';\n    }\n\n    function toggle(element, bool) {\n        element = $(element);\n        if (typeof bool !== 'boolean')\n            bool = !Element.visible(element);\n        Element[bool ? 'show' : 'hide'](element);\n\n        return element;\n    }\n\n    function hide(element) {\n        element = $(element);\n        element.style.display = 'none';\n        return element;\n    }\n\n    function show(element) {\n        element = $(element);\n        element.style.display = '';\n        return element;\n    }\n\n\n    Object.extend(methods, {\n        visible: visible,\n        toggle:  toggle,\n        hide:    hide,\n        show:    show\n    });\n\n\n    function remove(element) {\n        element = $(element);\n        element.parentNode.removeChild(element);\n        return element;\n    }\n\n    var SELECT_ELEMENT_INNERHTML_BUGGY = (function(){\n        var el = document.createElement(\"select\"),\n            isBuggy = true;\n        el.innerHTML = \"<option value=\\\"test\\\">test</option>\";\n        if (el.options && el.options[0]) {\n            isBuggy = el.options[0].nodeName.toUpperCase() !== \"OPTION\";\n        }\n        el = null;\n        return isBuggy;\n    })();\n\n    var TABLE_ELEMENT_INNERHTML_BUGGY = (function(){\n        try {\n            var el = document.createElement(\"table\");\n            if (el && el.tBodies) {\n                el.innerHTML = \"<tbody><tr><td>test</td></tr></tbody>\";\n                var isBuggy = typeof el.tBodies[0] == \"undefined\";\n                el = null;\n                return isBuggy;\n            }\n        } catch (e) {\n            return true;\n        }\n    })();\n\n    var LINK_ELEMENT_INNERHTML_BUGGY = (function() {\n        try {\n            var el = document.createElement('div');\n            el.innerHTML = \"<link />\";\n            var isBuggy = (el.childNodes.length === 0);\n            el = null;\n            return isBuggy;\n        } catch(e) {\n            return true;\n        }\n    })();\n\n    var ANY_INNERHTML_BUGGY = SELECT_ELEMENT_INNERHTML_BUGGY ||\n        TABLE_ELEMENT_INNERHTML_BUGGY || LINK_ELEMENT_INNERHTML_BUGGY;\n\n    var SCRIPT_ELEMENT_REJECTS_TEXTNODE_APPENDING = (function () {\n        var s = document.createElement(\"script\"),\n            isBuggy = false;\n        try {\n            s.appendChild(document.createTextNode(\"\"));\n            isBuggy = !s.firstChild ||\n                s.firstChild && s.firstChild.nodeType !== 3;\n        } catch (e) {\n            isBuggy = true;\n        }\n        s = null;\n        return isBuggy;\n    })();\n\n    function update(element, content) {\n        element = $(element);\n\n        var descendants = element.getElementsByTagName('*'),\n            i = descendants.length;\n        while (i--) purgeElement(descendants[i]);\n\n        if (content && content.toElement)\n            content = content.toElement();\n\n        if (Object.isElement(content))\n            return element.update().insert(content);\n\n\n        content = Object.toHTML(content);\n        var tagName = element.tagName.toUpperCase();\n\n        if (tagName === 'SCRIPT' && SCRIPT_ELEMENT_REJECTS_TEXTNODE_APPENDING) {\n            element.text = content;\n            return element;\n        }\n\n        if (ANY_INNERHTML_BUGGY) {\n            if (tagName in INSERTION_TRANSLATIONS.tags) {\n                while (element.firstChild)\n                    element.removeChild(element.firstChild);\n\n                var nodes = getContentFromAnonymousElement(tagName, content.stripScripts());\n                for (var i = 0, node; node = nodes[i]; i++)\n                    element.appendChild(node);\n\n            } else if (LINK_ELEMENT_INNERHTML_BUGGY && Object.isString(content) && content.indexOf('<link') > -1) {\n                while (element.firstChild)\n                    element.removeChild(element.firstChild);\n\n                var nodes = getContentFromAnonymousElement(tagName,\n                    content.stripScripts(), true);\n\n                for (var i = 0, node; node = nodes[i]; i++)\n                    element.appendChild(node);\n            } else {\n                element.innerHTML = content.stripScripts();\n            }\n        } else {\n            element.innerHTML = content.stripScripts();\n        }\n\n        content.evalScripts.bind(content).defer();\n        return element;\n    }\n\n    function replace(element, content) {\n        element = $(element);\n\n        if (content && content.toElement) {\n            content = content.toElement();\n        } else if (!Object.isElement(content)) {\n            content = Object.toHTML(content);\n            var range = element.ownerDocument.createRange();\n            range.selectNode(element);\n            content.evalScripts.bind(content).defer();\n            content = range.createContextualFragment(content.stripScripts());\n        }\n\n        element.parentNode.replaceChild(content, element);\n        return element;\n    }\n\n    var INSERTION_TRANSLATIONS = {\n        before: function(element, node) {\n            element.parentNode.insertBefore(node, element);\n        },\n        top: function(element, node) {\n            element.insertBefore(node, element.firstChild);\n        },\n        bottom: function(element, node) {\n            element.appendChild(node);\n        },\n        after: function(element, node) {\n            element.parentNode.insertBefore(node, element.nextSibling);\n        },\n\n        tags: {\n            TABLE:  ['<table>',                '</table>',                   1],\n            TBODY:  ['<table><tbody>',         '</tbody></table>',           2],\n            TR:     ['<table><tbody><tr>',     '</tr></tbody></table>',      3],\n            TD:     ['<table><tbody><tr><td>', '</td></tr></tbody></table>', 4],\n            SELECT: ['<select>',               '</select>',                  1]\n        }\n    };\n\n    var tags = INSERTION_TRANSLATIONS.tags;\n\n    Object.extend(tags, {\n        THEAD: tags.TBODY,\n        TFOOT: tags.TBODY,\n        TH:    tags.TD\n    });\n\n    function replace_IE(element, content) {\n        element = $(element);\n        if (content && content.toElement)\n            content = content.toElement();\n        if (Object.isElement(content)) {\n            element.parentNode.replaceChild(content, element);\n            return element;\n        }\n\n        content = Object.toHTML(content);\n        var parent = element.parentNode, tagName = parent.tagName.toUpperCase();\n\n        if (tagName in INSERTION_TRANSLATIONS.tags) {\n            var nextSibling = Element.next(element);\n            var fragments = getContentFromAnonymousElement(\n                tagName, content.stripScripts());\n\n            parent.removeChild(element);\n\n            var iterator;\n            if (nextSibling)\n                iterator = function(node) { parent.insertBefore(node, nextSibling) };\n            else\n                iterator = function(node) { parent.appendChild(node); }\n\n            fragments.each(iterator);\n        } else {\n            element.outerHTML = content.stripScripts();\n        }\n\n        content.evalScripts.bind(content).defer();\n        return element;\n    }\n\n    if ('outerHTML' in document.documentElement)\n        replace = replace_IE;\n\n    function isContent(content) {\n        if (Object.isUndefined(content) || content === null) return false;\n\n        if (Object.isString(content) || Object.isNumber(content)) return true;\n        if (Object.isElement(content)) return true;\n        if (content.toElement || content.toHTML) return true;\n\n        return false;\n    }\n\n    function insertContentAt(element, content, position) {\n        position   = position.toLowerCase();\n        var method = INSERTION_TRANSLATIONS[position];\n\n        if (content && content.toElement) content = content.toElement();\n        if (Object.isElement(content)) {\n            method(element, content);\n            return element;\n        }\n\n        content = Object.toHTML(content);\n        var tagName = ((position === 'before' || position === 'after') ?\n            element.parentNode : element).tagName.toUpperCase();\n\n        var childNodes = getContentFromAnonymousElement(tagName, content.stripScripts());\n\n        if (position === 'top' || position === 'after') childNodes.reverse();\n\n        for (var i = 0, node; node = childNodes[i]; i++)\n            method(element, node);\n\n        content.evalScripts.bind(content).defer();\n    }\n\n    function insert(element, insertions) {\n        element = $(element);\n\n        if (isContent(insertions))\n            insertions = { bottom: insertions };\n\n        for (var position in insertions)\n            insertContentAt(element, insertions[position], position);\n\n        return element;\n    }\n\n    function wrap(element, wrapper, attributes) {\n        element = $(element);\n\n        if (Object.isElement(wrapper)) {\n            $(wrapper).writeAttribute(attributes || {});\n        } else if (Object.isString(wrapper)) {\n            wrapper = new Element(wrapper, attributes);\n        } else {\n            wrapper = new Element('div', wrapper);\n        }\n\n        if (element.parentNode)\n            element.parentNode.replaceChild(wrapper, element);\n\n        wrapper.appendChild(element);\n\n        return wrapper;\n    }\n\n    function cleanWhitespace(element) {\n        element = $(element);\n        var node = element.firstChild;\n\n        while (node) {\n            var nextNode = node.nextSibling;\n            if (node.nodeType === Node.TEXT_NODE && !/\\S/.test(node.nodeValue))\n                element.removeChild(node);\n            node = nextNode;\n        }\n        return element;\n    }\n\n    function empty(element) {\n        return $(element).innerHTML.blank();\n    }\n\n    function getContentFromAnonymousElement(tagName, html, force) {\n        var t = INSERTION_TRANSLATIONS.tags[tagName], div = DIV;\n\n        var workaround = !!t;\n        if (!workaround && force) {\n            workaround = true;\n            t = ['', '', 0];\n        }\n\n        if (workaround) {\n            div.innerHTML = '&#160;' + t[0] + html + t[1];\n            div.removeChild(div.firstChild);\n            for (var i = t[2]; i--; )\n                div = div.firstChild;\n        } else {\n            div.innerHTML = html;\n        }\n\n        return $A(div.childNodes);\n    }\n\n    function clone(element, deep) {\n        if (!(element = $(element))) return;\n        var clone = element.cloneNode(deep);\n        if (!HAS_UNIQUE_ID_PROPERTY) {\n            clone._prototypeUID = UNDEFINED;\n            if (deep) {\n                var descendants = Element.select(clone, '*'),\n                    i = descendants.length;\n                while (i--)\n                    descendants[i]._prototypeUID = UNDEFINED;\n            }\n        }\n        return Element.extend(clone);\n    }\n\n    function purgeElement(element) {\n        var uid = getUniqueElementID(element);\n        if (uid) {\n            Element.stopObserving(element);\n            if (!HAS_UNIQUE_ID_PROPERTY)\n                element._prototypeUID = UNDEFINED;\n            delete Element.Storage[uid];\n        }\n    }\n\n    function purgeCollection(elements) {\n        var i = elements.length;\n        while (i--)\n            purgeElement(elements[i]);\n    }\n\n    function purgeCollection_IE(elements) {\n        var i = elements.length, element, uid;\n        while (i--) {\n            element = elements[i];\n            uid = getUniqueElementID(element);\n            delete Element.Storage[uid];\n            delete Event.cache[uid];\n        }\n    }\n\n    if (HAS_UNIQUE_ID_PROPERTY) {\n        purgeCollection = purgeCollection_IE;\n    }\n\n\n    function purge(element) {\n        if (!(element = $(element))) return;\n        purgeElement(element);\n\n        var descendants = element.getElementsByTagName('*'),\n            i = descendants.length;\n\n        while (i--) purgeElement(descendants[i]);\n\n        return null;\n    }\n\n    Object.extend(methods, {\n        remove:  remove,\n        update:  update,\n        replace: replace,\n        insert:  insert,\n        wrap:    wrap,\n        cleanWhitespace: cleanWhitespace,\n        empty:   empty,\n        clone:   clone,\n        purge:   purge\n    });\n\n\n\n    function recursivelyCollect(element, property, maximumLength) {\n        element = $(element);\n        maximumLength = maximumLength || -1;\n        var elements = [];\n\n        while (element = element[property]) {\n            if (element.nodeType === Node.ELEMENT_NODE)\n                elements.push(Element.extend(element));\n\n            if (elements.length === maximumLength) break;\n        }\n\n        return elements;\n    }\n\n\n    function ancestors(element) {\n        return recursivelyCollect(element, 'parentNode');\n    }\n\n    function descendants(element) {\n        return Element.select(element, '*');\n    }\n\n    function firstDescendant(element) {\n        element = $(element).firstChild;\n        while (element && element.nodeType !== Node.ELEMENT_NODE)\n            element = element.nextSibling;\n\n        return $(element);\n    }\n\n    function immediateDescendants(element) {\n        var results = [], child = $(element).firstChild;\n\n        while (child) {\n            if (child.nodeType === Node.ELEMENT_NODE)\n                results.push(Element.extend(child));\n\n            child = child.nextSibling;\n        }\n\n        return results;\n    }\n\n    function previousSiblings(element) {\n        return recursivelyCollect(element, 'previousSibling');\n    }\n\n    function nextSiblings(element) {\n        return recursivelyCollect(element, 'nextSibling');\n    }\n\n    function siblings(element) {\n        element = $(element);\n        var previous = previousSiblings(element),\n            next = nextSiblings(element);\n        return previous.reverse().concat(next);\n    }\n\n    function match(element, selector) {\n        element = $(element);\n\n        if (Object.isString(selector))\n            return Prototype.Selector.match(element, selector);\n\n        return selector.match(element);\n    }\n\n\n    function _recursivelyFind(element, property, expression, index) {\n        element = $(element), expression = expression || 0, index = index || 0;\n        if (Object.isNumber(expression)) {\n            index = expression, expression = null;\n        }\n\n        while (element = element[property]) {\n            if (element.nodeType !== 1) continue;\n            if (expression && !Prototype.Selector.match(element, expression))\n                continue;\n            if (--index >= 0) continue;\n\n            return Element.extend(element);\n        }\n    }\n\n\n    function up(element, expression, index) {\n        element = $(element);\n\n        if (arguments.length === 1) return $(element.parentNode);\n        return _recursivelyFind(element, 'parentNode', expression, index);\n    }\n\n    function down(element, expression, index) {\n        if (arguments.length === 1) return firstDescendant(element);\n        element = $(element), expression = expression || 0, index = index || 0;\n\n        if (Object.isNumber(expression))\n            index = expression, expression = '*';\n\n        var node = Prototype.Selector.select(expression, element)[index];\n        return Element.extend(node);\n    }\n\n    function previous(element, expression, index) {\n        return _recursivelyFind(element, 'previousSibling', expression, index);\n    }\n\n    function next(element, expression, index) {\n        return _recursivelyFind(element, 'nextSibling', expression, index);\n    }\n\n    function select(element) {\n        element = $(element);\n        var expressions = SLICE.call(arguments, 1).join(', ');\n        return Prototype.Selector.select(expressions, element);\n    }\n\n    function adjacent(element) {\n        element = $(element);\n        var expressions = SLICE.call(arguments, 1).join(', ');\n        var siblings = Element.siblings(element), results = [];\n        for (var i = 0, sibling; sibling = siblings[i]; i++) {\n            if (Prototype.Selector.match(sibling, expressions))\n                results.push(sibling);\n        }\n\n        return results;\n    }\n\n    function descendantOf_DOM(element, ancestor) {\n        element = $(element), ancestor = $(ancestor);\n        if (!element || !ancestor) return false;\n        while (element = element.parentNode)\n            if (element === ancestor) return true;\n        return false;\n    }\n\n    function descendantOf_contains(element, ancestor) {\n        element = $(element), ancestor = $(ancestor);\n        if (!element || !ancestor) return false;\n        if (!ancestor.contains) return descendantOf_DOM(element, ancestor);\n        return ancestor.contains(element) && ancestor !== element;\n    }\n\n    function descendantOf_compareDocumentPosition(element, ancestor) {\n        element = $(element), ancestor = $(ancestor);\n        if (!element || !ancestor) return false;\n        return (element.compareDocumentPosition(ancestor) & 8) === 8;\n    }\n\n    var descendantOf;\n    if (DIV.compareDocumentPosition) {\n        descendantOf = descendantOf_compareDocumentPosition;\n    } else if (DIV.contains) {\n        descendantOf = descendantOf_contains;\n    } else {\n        descendantOf = descendantOf_DOM;\n    }\n\n\n    Object.extend(methods, {\n        recursivelyCollect:   recursivelyCollect,\n        ancestors:            ancestors,\n        descendants:          descendants,\n        firstDescendant:      firstDescendant,\n        immediateDescendants: immediateDescendants,\n        previousSiblings:     previousSiblings,\n        nextSiblings:         nextSiblings,\n        siblings:             siblings,\n        match:                match,\n        up:                   up,\n        down:                 down,\n        previous:             previous,\n        next:                 next,\n        select:               select,\n        adjacent:             adjacent,\n        descendantOf:         descendantOf,\n\n        getElementsBySelector: select,\n\n        childElements:         immediateDescendants\n    });\n\n\n    var idCounter = 1;\n    function identify(element) {\n        element = $(element);\n        var id = Element.readAttribute(element, 'id');\n        if (id) return id;\n\n        do { id = 'anonymous_element_' + idCounter++ } while ($(id));\n\n        Element.writeAttribute(element, 'id', id);\n        return id;\n    }\n\n\n    function readAttribute(element, name) {\n        return $(element).getAttribute(name);\n    }\n\n    function readAttribute_IE(element, name) {\n        element = $(element);\n\n        var table = ATTRIBUTE_TRANSLATIONS.read;\n        if (table.values[name])\n            return table.values[name](element, name);\n\n        if (table.names[name]) name = table.names[name];\n\n        if (name.include(':')) {\n            if (!element.attributes || !element.attributes[name]) return null;\n            return element.attributes[name].value;\n        }\n\n        return element.getAttribute(name);\n    }\n\n    function readAttribute_Opera(element, name) {\n        if (name === 'title') return element.title;\n        return element.getAttribute(name);\n    }\n\n    var PROBLEMATIC_ATTRIBUTE_READING = (function() {\n        DIV.setAttribute('onclick', []);\n        var value = DIV.getAttribute('onclick');\n        var isFunction = Object.isArray(value);\n        DIV.removeAttribute('onclick');\n        return isFunction;\n    })();\n\n    if (PROBLEMATIC_ATTRIBUTE_READING) {\n        readAttribute = readAttribute_IE;\n    } else if (Prototype.Browser.Opera) {\n        readAttribute = readAttribute_Opera;\n    }\n\n\n    function writeAttribute(element, name, value) {\n        element = $(element);\n        var attributes = {}, table = ATTRIBUTE_TRANSLATIONS.write;\n\n        if (typeof name === 'object') {\n            attributes = name;\n        } else {\n            attributes[name] = Object.isUndefined(value) ? true : value;\n        }\n\n        for (var attr in attributes) {\n            name = table.names[attr] || attr;\n            value = attributes[attr];\n            if (table.values[attr]) {\n                value = table.values[attr](element, value);\n                if (Object.isUndefined(value)) continue;\n            }\n            if (value === false || value === null)\n                element.removeAttribute(name);\n            else if (value === true)\n                element.setAttribute(name, name);\n            else element.setAttribute(name, value);\n        }\n\n        return element;\n    }\n\n    var PROBLEMATIC_HAS_ATTRIBUTE_WITH_CHECKBOXES = (function () {\n        if (!HAS_EXTENDED_CREATE_ELEMENT_SYNTAX) {\n            return false;\n        }\n        var checkbox = document.createElement('<input type=\"checkbox\">');\n        checkbox.checked = true;\n        var node = checkbox.getAttributeNode('checked');\n        return !node || !node.specified;\n    })();\n\n    function hasAttribute(element, attribute) {\n        attribute = ATTRIBUTE_TRANSLATIONS.has[attribute] || attribute;\n        var node = $(element).getAttributeNode(attribute);\n        return !!(node && node.specified);\n    }\n\n    function hasAttribute_IE(element, attribute) {\n        if (attribute === 'checked') {\n            return element.checked;\n        }\n        return hasAttribute(element, attribute);\n    }\n\n    GLOBAL.Element.Methods.Simulated.hasAttribute =\n        PROBLEMATIC_HAS_ATTRIBUTE_WITH_CHECKBOXES ?\n            hasAttribute_IE : hasAttribute;\n\n    function classNames(element) {\n        return new Element.ClassNames(element);\n    }\n\n    var regExpCache = {};\n    function getRegExpForClassName(className) {\n        if (regExpCache[className]) return regExpCache[className];\n\n        var re = new RegExp(\"(^|\\\\s+)\" + className + \"(\\\\s+|$)\");\n        regExpCache[className] = re;\n        return re;\n    }\n\n    function hasClassName(element, className) {\n        if (!(element = $(element))) return;\n\n        var elementClassName = element.className;\n\n        if (elementClassName.length === 0) return false;\n        if (elementClassName === className) return true;\n\n        return getRegExpForClassName(className).test(elementClassName);\n    }\n\n    function addClassName(element, className) {\n        if (!(element = $(element))) return;\n\n        if (!hasClassName(element, className))\n            element.className += (element.className ? ' ' : '') + className;\n\n        return element;\n    }\n\n    function removeClassName(element, className) {\n        if (!(element = $(element))) return;\n\n        element.className = element.className.replace(\n            getRegExpForClassName(className), ' ').strip();\n\n        return element;\n    }\n\n    function toggleClassName(element, className, bool) {\n        if (!(element = $(element))) return;\n\n        if (Object.isUndefined(bool))\n            bool = !hasClassName(element, className);\n\n        var method = Element[bool ? 'addClassName' : 'removeClassName'];\n        return method(element, className);\n    }\n\n    var ATTRIBUTE_TRANSLATIONS = {};\n\n    var classProp = 'className', forProp = 'for';\n\n    DIV.setAttribute(classProp, 'x');\n    if (DIV.className !== 'x') {\n        DIV.setAttribute('class', 'x');\n        if (DIV.className === 'x')\n            classProp = 'class';\n    }\n\n    var LABEL = document.createElement('label');\n    LABEL.setAttribute(forProp, 'x');\n    if (LABEL.htmlFor !== 'x') {\n        LABEL.setAttribute('htmlFor', 'x');\n        if (LABEL.htmlFor === 'x')\n            forProp = 'htmlFor';\n    }\n    LABEL = null;\n\n    function _getAttr(element, attribute) {\n        return element.getAttribute(attribute);\n    }\n\n    function _getAttr2(element, attribute) {\n        return element.getAttribute(attribute, 2);\n    }\n\n    function _getAttrNode(element, attribute) {\n        var node = element.getAttributeNode(attribute);\n        return node ? node.value : '';\n    }\n\n    function _getFlag(element, attribute) {\n        return $(element).hasAttribute(attribute) ? attribute : null;\n    }\n\n    DIV.onclick = Prototype.emptyFunction;\n    var onclickValue = DIV.getAttribute('onclick');\n\n    var _getEv;\n\n    if (String(onclickValue).indexOf('{') > -1) {\n        _getEv = function(element, attribute) {\n            var value = element.getAttribute(attribute);\n            if (!value) return null;\n            value = value.toString();\n            value = value.split('{')[1];\n            value = value.split('}')[0];\n            return value.strip();\n        };\n    }\n    else if (onclickValue === '') {\n        _getEv = function(element, attribute) {\n            var value = element.getAttribute(attribute);\n            if (!value) return null;\n            return value.strip();\n        };\n    }\n\n    ATTRIBUTE_TRANSLATIONS.read = {\n        names: {\n            'class':     classProp,\n            'className': classProp,\n            'for':       forProp,\n            'htmlFor':   forProp\n        },\n\n        values: {\n            style: function(element) {\n                return element.style.cssText.toLowerCase();\n            },\n            title: function(element) {\n                return element.title;\n            }\n        }\n    };\n\n    ATTRIBUTE_TRANSLATIONS.write = {\n        names: {\n            className:   'class',\n            htmlFor:     'for',\n            cellpadding: 'cellPadding',\n            cellspacing: 'cellSpacing'\n        },\n\n        values: {\n            checked: function(element, value) {\n                value = !!value;\n                element.checked = value;\n                return value ? 'checked' : null;\n            },\n\n            style: function(element, value) {\n                element.style.cssText = value ? value : '';\n            }\n        }\n    };\n\n    ATTRIBUTE_TRANSLATIONS.has = { names: {} };\n\n    Object.extend(ATTRIBUTE_TRANSLATIONS.write.names,\n        ATTRIBUTE_TRANSLATIONS.read.names);\n\n    var CAMEL_CASED_ATTRIBUTE_NAMES = $w('colSpan rowSpan vAlign dateTime ' +\n        'accessKey tabIndex encType maxLength readOnly longDesc frameBorder');\n\n    for (var i = 0, attr; attr = CAMEL_CASED_ATTRIBUTE_NAMES[i]; i++) {\n        ATTRIBUTE_TRANSLATIONS.write.names[attr.toLowerCase()] = attr;\n        ATTRIBUTE_TRANSLATIONS.has.names[attr.toLowerCase()]   = attr;\n    }\n\n    Object.extend(ATTRIBUTE_TRANSLATIONS.read.values, {\n        href:        _getAttr2,\n        src:         _getAttr2,\n        type:        _getAttr,\n        action:      _getAttrNode,\n        disabled:    _getFlag,\n        checked:     _getFlag,\n        readonly:    _getFlag,\n        multiple:    _getFlag,\n        onload:      _getEv,\n        onunload:    _getEv,\n        onclick:     _getEv,\n        ondblclick:  _getEv,\n        onmousedown: _getEv,\n        onmouseup:   _getEv,\n        onmouseover: _getEv,\n        onmousemove: _getEv,\n        onmouseout:  _getEv,\n        onfocus:     _getEv,\n        onblur:      _getEv,\n        onkeypress:  _getEv,\n        onkeydown:   _getEv,\n        onkeyup:     _getEv,\n        onsubmit:    _getEv,\n        onreset:     _getEv,\n        onselect:    _getEv,\n        onchange:    _getEv\n    });\n\n\n    Object.extend(methods, {\n        identify:        identify,\n        readAttribute:   readAttribute,\n        writeAttribute:  writeAttribute,\n        classNames:      classNames,\n        hasClassName:    hasClassName,\n        addClassName:    addClassName,\n        removeClassName: removeClassName,\n        toggleClassName: toggleClassName\n    });\n\n\n    function normalizeStyleName(style) {\n        if (style === 'float' || style === 'styleFloat')\n            return 'cssFloat';\n        return style.camelize();\n    }\n\n    function normalizeStyleName_IE(style) {\n        if (style === 'float' || style === 'cssFloat')\n            return 'styleFloat';\n        return style.camelize();\n    }\n\n    function setStyle(element, styles) {\n        element = $(element);\n        var elementStyle = element.style, match;\n\n        if (Object.isString(styles)) {\n            elementStyle.cssText += ';' + styles;\n            if (styles.include('opacity')) {\n                var opacity = styles.match(/opacity:\\s*(\\d?\\.?\\d*)/)[1];\n                Element.setOpacity(element, opacity);\n            }\n            return element;\n        }\n\n        for (var property in styles) {\n            if (property === 'opacity') {\n                Element.setOpacity(element, styles[property]);\n            } else {\n                var value = styles[property];\n                if (property === 'float' || property === 'cssFloat') {\n                    property = Object.isUndefined(elementStyle.styleFloat) ?\n                        'cssFloat' : 'styleFloat';\n                }\n                elementStyle[property] = value;\n            }\n        }\n\n        return element;\n    }\n\n\n    function getStyle(element, style) {\n        element = $(element);\n        style = normalizeStyleName(style);\n\n        var value = element.style[style];\n        if (!value || value === 'auto') {\n            var css = document.defaultView.getComputedStyle(element, null);\n            value = css ? css[style] : null;\n        }\n\n        if (style === 'opacity') return value ? parseFloat(value) : 1.0;\n        return value === 'auto' ? null : value;\n    }\n\n    function getStyle_Opera(element, style) {\n        switch (style) {\n            case 'height': case 'width':\n            if (!Element.visible(element)) return null;\n\n            var dim = parseInt(getStyle(element, style), 10);\n\n            if (dim !== element['offset' + style.capitalize()])\n                return dim + 'px';\n\n            return Element.measure(element, style);\n\n            default: return getStyle(element, style);\n        }\n    }\n\n    function getStyle_IE(element, style) {\n        element = $(element);\n        style = normalizeStyleName_IE(style);\n\n        var value = element.style[style];\n        if (!value && element.currentStyle) {\n            value = element.currentStyle[style];\n        }\n\n        if (style === 'opacity') {\n            if (!STANDARD_CSS_OPACITY_SUPPORTED)\n                return getOpacity_IE(element);\n            else return value ? parseFloat(value) : 1.0;\n        }\n\n        if (value === 'auto') {\n            if ((style === 'width' || style === 'height') && Element.visible(element))\n                return Element.measure(element, style) + 'px';\n            return null;\n        }\n\n        return value;\n    }\n\n    function stripAlphaFromFilter_IE(filter) {\n        return (filter || '').replace(/alpha\\([^\\)]*\\)/gi, '');\n    }\n\n    function hasLayout_IE(element) {\n        if (!element.currentStyle || !element.currentStyle.hasLayout)\n            element.style.zoom = 1;\n        return element;\n    }\n\n    var STANDARD_CSS_OPACITY_SUPPORTED = (function() {\n        DIV.style.cssText = \"opacity:.55\";\n        return /^0.55/.test(DIV.style.opacity);\n    })();\n\n    function setOpacity(element, value) {\n        element = $(element);\n        if (value == 1 || value === '') value = '';\n        else if (value < 0.00001) value = 0;\n        element.style.opacity = value;\n        return element;\n    }\n\n    function setOpacity_IE(element, value) {\n        if (STANDARD_CSS_OPACITY_SUPPORTED)\n            return setOpacity(element, value);\n\n        element = hasLayout_IE($(element));\n        var filter = Element.getStyle(element, 'filter'),\n            style = element.style;\n\n        if (value == 1 || value === '') {\n            filter = stripAlphaFromFilter_IE(filter);\n            if (filter) style.filter = filter;\n            else style.removeAttribute('filter');\n            return element;\n        }\n\n        if (value < 0.00001) value = 0;\n\n        style.filter = stripAlphaFromFilter_IE(filter) +\n            ' alpha(opacity=' + (value * 100) + ')';\n\n        return element;\n    }\n\n\n    function getOpacity(element) {\n        return Element.getStyle(element, 'opacity');\n    }\n\n    function getOpacity_IE(element) {\n        if (STANDARD_CSS_OPACITY_SUPPORTED)\n            return getOpacity(element);\n\n        var filter = Element.getStyle(element, 'filter');\n        if (filter.length === 0) return 1.0;\n        var match = (filter || '').match(/alpha\\(opacity=(.*)\\)/i);\n        if (match && match[1]) return parseFloat(match[1]) / 100;\n        return 1.0;\n    }\n\n\n    Object.extend(methods, {\n        setStyle:   setStyle,\n        getStyle:   getStyle,\n        setOpacity: setOpacity,\n        getOpacity: getOpacity\n    });\n\n    if ('styleFloat' in DIV.style) {\n        methods.getStyle = getStyle_IE;\n        methods.setOpacity = setOpacity_IE;\n        methods.getOpacity = getOpacity_IE;\n    }\n\n    var UID = 0;\n\n    GLOBAL.Element.Storage = { UID: 1 };\n\n    function getUniqueElementID(element) {\n        if (element === window) return 0;\n\n        if (typeof element._prototypeUID === 'undefined')\n            element._prototypeUID = Element.Storage.UID++;\n        return element._prototypeUID;\n    }\n\n    function getUniqueElementID_IE(element) {\n        if (element === window) return 0;\n        if (element == document) return 1;\n        return element.uniqueID;\n    }\n\n    var HAS_UNIQUE_ID_PROPERTY = ('uniqueID' in DIV);\n    if (HAS_UNIQUE_ID_PROPERTY)\n        getUniqueElementID = getUniqueElementID_IE;\n\n    function getStorage(element) {\n        if (!(element = $(element))) return;\n\n        var uid = getUniqueElementID(element);\n\n        if (!Element.Storage[uid])\n            Element.Storage[uid] = $H();\n\n        return Element.Storage[uid];\n    }\n\n    function store(element, key, value) {\n        if (!(element = $(element))) return;\n        var storage = getStorage(element);\n        if (arguments.length === 2) {\n            storage.update(key);\n        } else {\n            storage.set(key, value);\n        }\n        return element;\n    }\n\n    function retrieve(element, key, defaultValue) {\n        if (!(element = $(element))) return;\n        var storage = getStorage(element), value = storage.get(key);\n\n        if (Object.isUndefined(value)) {\n            storage.set(key, defaultValue);\n            value = defaultValue;\n        }\n\n        return value;\n    }\n\n\n    Object.extend(methods, {\n        getStorage: getStorage,\n        store:      store,\n        retrieve:   retrieve\n    });\n\n\n    var Methods = {}, ByTag = Element.Methods.ByTag,\n        F = Prototype.BrowserFeatures;\n\n    if (!F.ElementExtensions && ('__proto__' in DIV)) {\n        GLOBAL.HTMLElement = {};\n        GLOBAL.HTMLElement.prototype = DIV['__proto__'];\n        F.ElementExtensions = true;\n    }\n\n    function checkElementPrototypeDeficiency(tagName) {\n        if (typeof window.Element === 'undefined') return false;\n        if (!HAS_EXTENDED_CREATE_ELEMENT_SYNTAX) return false;\n        var proto = window.Element.prototype;\n        if (proto) {\n            var id = '_' + (Math.random() + '').slice(2),\n                el = document.createElement(tagName);\n            proto[id] = 'x';\n            var isBuggy = (el[id] !== 'x');\n            delete proto[id];\n            el = null;\n            return isBuggy;\n        }\n\n        return false;\n    }\n\n    var HTMLOBJECTELEMENT_PROTOTYPE_BUGGY =\n        checkElementPrototypeDeficiency('object');\n\n    function extendElementWith(element, methods) {\n        for (var property in methods) {\n            var value = methods[property];\n            if (Object.isFunction(value) && !(property in element))\n                element[property] = value.methodize();\n        }\n    }\n\n    var EXTENDED = {};\n    function elementIsExtended(element) {\n        var uid = getUniqueElementID(element);\n        return (uid in EXTENDED);\n    }\n\n    function extend(element) {\n        if (!element || elementIsExtended(element)) return element;\n        if (element.nodeType !== Node.ELEMENT_NODE || element == window)\n            return element;\n\n        var methods = Object.clone(Methods),\n            tagName = element.tagName.toUpperCase();\n\n        if (ByTag[tagName]) Object.extend(methods, ByTag[tagName]);\n\n        extendElementWith(element, methods);\n        EXTENDED[getUniqueElementID(element)] = true;\n        return element;\n    }\n\n    function extend_IE8(element) {\n        if (!element || elementIsExtended(element)) return element;\n\n        var t = element.tagName;\n        if (t && (/^(?:object|applet|embed)$/i.test(t))) {\n            extendElementWith(element, Element.Methods);\n            extendElementWith(element, Element.Methods.Simulated);\n            extendElementWith(element, Element.Methods.ByTag[t.toUpperCase()]);\n        }\n\n        return element;\n    }\n\n    if (F.SpecificElementExtensions) {\n        extend = HTMLOBJECTELEMENT_PROTOTYPE_BUGGY ? extend_IE8 : Prototype.K;\n    }\n\n    function addMethodsToTagName(tagName, methods) {\n        tagName = tagName.toUpperCase();\n        if (!ByTag[tagName]) ByTag[tagName] = {};\n        Object.extend(ByTag[tagName], methods);\n    }\n\n    function mergeMethods(destination, methods, onlyIfAbsent) {\n        if (Object.isUndefined(onlyIfAbsent)) onlyIfAbsent = false;\n        for (var property in methods) {\n            var value = methods[property];\n            if (!Object.isFunction(value)) continue;\n            if (!onlyIfAbsent || !(property in destination))\n                destination[property] = value.methodize();\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        var element = document.createElement(tagName),\n            proto = element['__proto__'] || element.constructor.prototype;\n\n        element = null;\n        return proto;\n    }\n\n    function addMethods(methods) {\n        if (arguments.length === 0) addFormMethods();\n\n        if (arguments.length === 2) {\n            var tagName = methods;\n            methods = arguments[1];\n        }\n\n        if (!tagName) {\n            Object.extend(Element.Methods, methods || {});\n        } else {\n            if (Object.isArray(tagName)) {\n                for (var i = 0, tag; tag = tagName[i]; i++)\n                    addMethodsToTagName(tag, methods);\n            } else {\n                addMethodsToTagName(tagName, methods);\n            }\n        }\n\n        var ELEMENT_PROTOTYPE = window.HTMLElement ? HTMLElement.prototype :\n            Element.prototype;\n\n        if (F.ElementExtensions) {\n            mergeMethods(ELEMENT_PROTOTYPE, Element.Methods);\n            mergeMethods(ELEMENT_PROTOTYPE, Element.Methods.Simulated, true);\n        }\n\n        if (F.SpecificElementExtensions) {\n            for (var tag in Element.Methods.ByTag) {\n                var klass = findDOMClass(tag);\n                if (Object.isUndefined(klass)) continue;\n                mergeMethods(klass.prototype, ByTag[tag]);\n            }\n        }\n\n        Object.extend(Element, Element.Methods);\n        Object.extend(Element, Element.Methods.Simulated);\n        delete Element.ByTag;\n        delete Element.Simulated;\n\n        Element.extend.refresh();\n\n        ELEMENT_CACHE = {};\n    }\n\n    Object.extend(GLOBAL.Element, {\n        extend:     extend,\n        addMethods: addMethods\n    });\n\n    if (extend === Prototype.K) {\n        GLOBAL.Element.extend.refresh = Prototype.emptyFunction;\n    } else {\n        GLOBAL.Element.extend.refresh = function() {\n            if (Prototype.BrowserFeatures.ElementExtensions) return;\n            Object.extend(Methods, Element.Methods);\n            Object.extend(Methods, Element.Methods.Simulated);\n\n            EXTENDED = {};\n        };\n    }\n\n    function addFormMethods() {\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            \"BUTTON\":   Object.clone(Form.Element.Methods)\n        });\n    }\n\n    Element.addMethods(methods);\n\n    function destroyCache_IE() {\n        DIV = null;\n        ELEMENT_CACHE = null;\n    }\n\n    if (window.attachEvent)\n        window.attachEvent('onunload', destroyCache_IE);\n\n})(this);\n(function() {\n\n    function toDecimal(pctString) {\n        var match = pctString.match(/^(\\d+)%?$/i);\n        if (!match) return null;\n        return (Number(match[1]) / 100);\n    }\n\n    function getRawStyle(element, style) {\n        element = $(element);\n\n        var value = element.style[style];\n        if (!value || value === 'auto') {\n            var css = document.defaultView.getComputedStyle(element, null);\n            value = css ? css[style] : null;\n        }\n\n        if (style === 'opacity') return value ? parseFloat(value) : 1.0;\n        return value === 'auto' ? null : value;\n    }\n\n    function getRawStyle_IE(element, style) {\n        var value = element.style[style];\n        if (!value && element.currentStyle) {\n            value = element.currentStyle[style];\n        }\n        return value;\n    }\n\n    function getContentWidth(element, context) {\n        var boxWidth = element.offsetWidth;\n\n        var bl = getPixelValue(element, 'borderLeftWidth',  context) || 0;\n        var br = getPixelValue(element, 'borderRightWidth', context) || 0;\n        var pl = getPixelValue(element, 'paddingLeft',      context) || 0;\n        var pr = getPixelValue(element, 'paddingRight',     context) || 0;\n\n        return boxWidth - bl - br - pl - pr;\n    }\n\n    if (!Object.isUndefined(document.documentElement.currentStyle) && !Prototype.Browser.Opera) {\n        getRawStyle = getRawStyle_IE;\n    }\n\n\n    function getPixelValue(value, property, context) {\n        var element = null;\n        if (Object.isElement(value)) {\n            element = value;\n            value = getRawStyle(element, property);\n        }\n\n        if (value === null || Object.isUndefined(value)) {\n            return null;\n        }\n\n        if ((/^(?:-)?\\d+(\\.\\d+)?(px)?$/i).test(value)) {\n            return window.parseFloat(value);\n        }\n\n        var isPercentage = value.include('%'), isViewport = (context === document.viewport);\n\n        if (/\\d/.test(value) && element && element.runtimeStyle && !(isPercentage && isViewport)) {\n            var style = element.style.left, rStyle = element.runtimeStyle.left;\n            element.runtimeStyle.left = element.currentStyle.left;\n            element.style.left = value || 0;\n            value = element.style.pixelLeft;\n            element.style.left = style;\n            element.runtimeStyle.left = rStyle;\n\n            return value;\n        }\n\n        if (element && isPercentage) {\n            context = context || element.parentNode;\n            var decimal = toDecimal(value), whole = null;\n\n            var isHorizontal = property.include('left') || property.include('right') ||\n                property.include('width');\n\n            var isVertical   = property.include('top') || property.include('bottom') ||\n                property.include('height');\n\n            if (context === document.viewport) {\n                if (isHorizontal) {\n                    whole = document.viewport.getWidth();\n                } else if (isVertical) {\n                    whole = document.viewport.getHeight();\n                }\n            } else {\n                if (isHorizontal) {\n                    whole = $(context).measure('width');\n                } else if (isVertical) {\n                    whole = $(context).measure('height');\n                }\n            }\n\n            return (whole === null) ? 0 : whole * decimal;\n        }\n\n        return 0;\n    }\n\n    function toCSSPixels(number) {\n        if (Object.isString(number) && number.endsWith('px'))\n            return number;\n        return number + 'px';\n    }\n\n    function isDisplayed(element) {\n        while (element && element.parentNode) {\n            var display = element.getStyle('display');\n            if (display === 'none') {\n                return false;\n            }\n            element = $(element.parentNode);\n        }\n        return true;\n    }\n\n    var hasLayout = Prototype.K;\n    if ('currentStyle' in document.documentElement) {\n        hasLayout = function(element) {\n            if (!element.currentStyle.hasLayout) {\n                element.style.zoom = 1;\n            }\n            return element;\n        };\n    }\n\n    function cssNameFor(key) {\n        if (key.include('border')) key = key + '-width';\n        return key.camelize();\n    }\n\n    Element.Layout = Class.create(Hash, {\n        initialize: function($super, element, preCompute) {\n            $super();\n            this.element = $(element);\n\n            Element.Layout.PROPERTIES.each( function(property) {\n                this._set(property, null);\n            }, this);\n\n            if (preCompute) {\n                this._preComputing = true;\n                this._begin();\n                Element.Layout.PROPERTIES.each( this._compute, this );\n                this._end();\n                this._preComputing = false;\n            }\n        },\n\n        _set: function(property, value) {\n            return Hash.prototype.set.call(this, property, value);\n        },\n\n        set: function(property, value) {\n            throw \"Properties of Element.Layout are read-only.\";\n        },\n\n        get: function($super, property) {\n            var value = $super(property);\n            return value === null ? this._compute(property) : value;\n        },\n\n        _begin: function() {\n            if (this._isPrepared()) return;\n\n            var element = this.element;\n            if (isDisplayed(element)) {\n                this._setPrepared(true);\n                return;\n            }\n\n\n            var originalStyles = {\n                position:   element.style.position   || '',\n                width:      element.style.width      || '',\n                visibility: element.style.visibility || '',\n                display:    element.style.display    || ''\n            };\n\n            element.store('prototype_original_styles', originalStyles);\n\n            var position = getRawStyle(element, 'position'), width = element.offsetWidth;\n\n            if (width === 0 || width === null) {\n                element.style.display = 'block';\n                width = element.offsetWidth;\n            }\n\n            var context = (position === 'fixed') ? document.viewport :\n                element.parentNode;\n\n            var tempStyles = {\n                visibility: 'hidden',\n                display:    'block'\n            };\n\n            if (position !== 'fixed') tempStyles.position = 'absolute';\n\n            element.setStyle(tempStyles);\n\n            var positionedWidth = element.offsetWidth, newWidth;\n            if (width && (positionedWidth === width)) {\n                newWidth = getContentWidth(element, context);\n            } else if (position === 'absolute' || position === 'fixed') {\n                newWidth = getContentWidth(element, context);\n            } else {\n                var parent = element.parentNode, pLayout = $(parent).getLayout();\n\n                newWidth = pLayout.get('width') -\n                    this.get('margin-left') -\n                    this.get('border-left') -\n                    this.get('padding-left') -\n                    this.get('padding-right') -\n                    this.get('border-right') -\n                    this.get('margin-right');\n            }\n\n            element.setStyle({ width: newWidth + 'px' });\n\n            this._setPrepared(true);\n        },\n\n        _end: function() {\n            var element = this.element;\n            var originalStyles = element.retrieve('prototype_original_styles');\n            element.store('prototype_original_styles', null);\n            element.setStyle(originalStyles);\n            this._setPrepared(false);\n        },\n\n        _compute: function(property) {\n            var COMPUTATIONS = Element.Layout.COMPUTATIONS;\n            if (!(property in COMPUTATIONS)) {\n                throw \"Property not found.\";\n            }\n\n            return this._set(property, COMPUTATIONS[property].call(this, this.element));\n        },\n\n        _isPrepared: function() {\n            return this.element.retrieve('prototype_element_layout_prepared', false);\n        },\n\n        _setPrepared: function(bool) {\n            return this.element.store('prototype_element_layout_prepared', bool);\n        },\n\n        toObject: function() {\n            var args = $A(arguments);\n            var keys = (args.length === 0) ? Element.Layout.PROPERTIES :\n                args.join(' ').split(' ');\n            var obj = {};\n            keys.each( function(key) {\n                if (!Element.Layout.PROPERTIES.include(key)) return;\n                var value = this.get(key);\n                if (value != null) obj[key] = value;\n            }, this);\n            return obj;\n        },\n\n        toHash: function() {\n            var obj = this.toObject.apply(this, arguments);\n            return new Hash(obj);\n        },\n\n        toCSS: function() {\n            var args = $A(arguments);\n            var keys = (args.length === 0) ? Element.Layout.PROPERTIES :\n                args.join(' ').split(' ');\n            var css = {};\n\n            keys.each( function(key) {\n                if (!Element.Layout.PROPERTIES.include(key)) return;\n                if (Element.Layout.COMPOSITE_PROPERTIES.include(key)) return;\n\n                var value = this.get(key);\n                if (value != null) css[cssNameFor(key)] = value + 'px';\n            }, this);\n            return css;\n        },\n\n        inspect: function() {\n            return \"#<Element.Layout>\";\n        }\n    });\n\n    Object.extend(Element.Layout, {\n        PROPERTIES: $w('height width top left right bottom border-left border-right border-top border-bottom padding-left padding-right padding-top padding-bottom margin-top margin-bottom margin-left margin-right padding-box-width padding-box-height border-box-width border-box-height margin-box-width margin-box-height'),\n\n        COMPOSITE_PROPERTIES: $w('padding-box-width padding-box-height margin-box-width margin-box-height border-box-width border-box-height'),\n\n        COMPUTATIONS: {\n            'height': function(element) {\n                if (!this._preComputing) this._begin();\n\n                var bHeight = this.get('border-box-height');\n                if (bHeight <= 0) {\n                    if (!this._preComputing) this._end();\n                    return 0;\n                }\n\n                var bTop = this.get('border-top'),\n                    bBottom = this.get('border-bottom');\n\n                var pTop = this.get('padding-top'),\n                    pBottom = this.get('padding-bottom');\n\n                if (!this._preComputing) this._end();\n\n                return bHeight - bTop - bBottom - pTop - pBottom;\n            },\n\n            'width': function(element) {\n                if (!this._preComputing) this._begin();\n\n                var bWidth = this.get('border-box-width');\n                if (bWidth <= 0) {\n                    if (!this._preComputing) this._end();\n                    return 0;\n                }\n\n                var bLeft = this.get('border-left'),\n                    bRight = this.get('border-right');\n\n                var pLeft = this.get('padding-left'),\n                    pRight = this.get('padding-right');\n\n                if (!this._preComputing) this._end();\n                return bWidth - bLeft - bRight - pLeft - pRight;\n            },\n\n            'padding-box-height': function(element) {\n                var height = this.get('height'),\n                    pTop = this.get('padding-top'),\n                    pBottom = this.get('padding-bottom');\n\n                return height + pTop + pBottom;\n            },\n\n            'padding-box-width': function(element) {\n                var width = this.get('width'),\n                    pLeft = this.get('padding-left'),\n                    pRight = this.get('padding-right');\n\n                return width + pLeft + pRight;\n            },\n\n            'border-box-height': function(element) {\n                if (!this._preComputing) this._begin();\n                var height = element.offsetHeight;\n                if (!this._preComputing) this._end();\n                return height;\n            },\n\n            'border-box-width': function(element) {\n                if (!this._preComputing) this._begin();\n                var width = element.offsetWidth;\n                if (!this._preComputing) this._end();\n                return width;\n            },\n\n            'margin-box-height': function(element) {\n                var bHeight = this.get('border-box-height'),\n                    mTop = this.get('margin-top'),\n                    mBottom = this.get('margin-bottom');\n\n                if (bHeight <= 0) return 0;\n\n                return bHeight + mTop + mBottom;\n            },\n\n            'margin-box-width': function(element) {\n                var bWidth = this.get('border-box-width'),\n                    mLeft = this.get('margin-left'),\n                    mRight = this.get('margin-right');\n\n                if (bWidth <= 0) return 0;\n\n                return bWidth + mLeft + mRight;\n            },\n\n            'top': function(element) {\n                var offset = element.positionedOffset();\n                return offset.top;\n            },\n\n            'bottom': function(element) {\n                var offset = element.positionedOffset(),\n                    parent = element.getOffsetParent(),\n                    pHeight = parent.measure('height');\n\n                var mHeight = this.get('border-box-height');\n\n                return pHeight - mHeight - offset.top;\n            },\n\n            'left': function(element) {\n                var offset = element.positionedOffset();\n                return offset.left;\n            },\n\n            'right': function(element) {\n                var offset = element.positionedOffset(),\n                    parent = element.getOffsetParent(),\n                    pWidth = parent.measure('width');\n\n                var mWidth = this.get('border-box-width');\n\n                return pWidth - mWidth - offset.left;\n            },\n\n            'padding-top': function(element) {\n                return getPixelValue(element, 'paddingTop');\n            },\n\n            'padding-bottom': function(element) {\n                return getPixelValue(element, 'paddingBottom');\n            },\n\n            'padding-left': function(element) {\n                return getPixelValue(element, 'paddingLeft');\n            },\n\n            'padding-right': function(element) {\n                return getPixelValue(element, 'paddingRight');\n            },\n\n            'border-top': function(element) {\n                return getPixelValue(element, 'borderTopWidth');\n            },\n\n            'border-bottom': function(element) {\n                return getPixelValue(element, 'borderBottomWidth');\n            },\n\n            'border-left': function(element) {\n                return getPixelValue(element, 'borderLeftWidth');\n            },\n\n            'border-right': function(element) {\n                return getPixelValue(element, 'borderRightWidth');\n            },\n\n            'margin-top': function(element) {\n                return getPixelValue(element, 'marginTop');\n            },\n\n            'margin-bottom': function(element) {\n                return getPixelValue(element, 'marginBottom');\n            },\n\n            'margin-left': function(element) {\n                return getPixelValue(element, 'marginLeft');\n            },\n\n            'margin-right': function(element) {\n                return getPixelValue(element, 'marginRight');\n            }\n        }\n    });\n\n    if ('getBoundingClientRect' in document.documentElement) {\n        Object.extend(Element.Layout.COMPUTATIONS, {\n            'right': function(element) {\n                var parent = hasLayout(element.getOffsetParent());\n                var rect = element.getBoundingClientRect(),\n                    pRect = parent.getBoundingClientRect();\n\n                return (pRect.right - rect.right).round();\n            },\n\n            'bottom': function(element) {\n                var parent = hasLayout(element.getOffsetParent());\n                var rect = element.getBoundingClientRect(),\n                    pRect = parent.getBoundingClientRect();\n\n                return (pRect.bottom - rect.bottom).round();\n            }\n        });\n    }\n\n    Element.Offset = Class.create({\n        initialize: function(left, top) {\n            this.left = left.round();\n            this.top  = top.round();\n\n            this[0] = this.left;\n            this[1] = this.top;\n        },\n\n        relativeTo: function(offset) {\n            return new Element.Offset(\n                this.left - offset.left,\n                this.top  - offset.top\n            );\n        },\n\n        inspect: function() {\n            return \"#<Element.Offset left: #{left} top: #{top}>\".interpolate(this);\n        },\n\n        toString: function() {\n            return \"[#{left}, #{top}]\".interpolate(this);\n        },\n\n        toArray: function() {\n            return [this.left, this.top];\n        }\n    });\n\n    function getLayout(element, preCompute) {\n        return new Element.Layout(element, preCompute);\n    }\n\n    function measure(element, property) {\n        return $(element).getLayout().get(property);\n    }\n\n    function getHeight(element) {\n        return Element.getDimensions(element).height;\n    }\n\n    function getWidth(element) {\n        return Element.getDimensions(element).width;\n    }\n\n    function getDimensions(element) {\n        element = $(element);\n        var display = Element.getStyle(element, 'display');\n\n        if (display && display !== 'none') {\n            return { width: element.offsetWidth, height: element.offsetHeight };\n        }\n\n        var style = element.style;\n        var originalStyles = {\n            visibility: style.visibility,\n            position:   style.position,\n            display:    style.display\n        };\n\n        var newStyles = {\n            visibility: 'hidden',\n            display:    'block'\n        };\n\n        if (originalStyles.position !== 'fixed')\n            newStyles.position = 'absolute';\n\n        Element.setStyle(element, newStyles);\n\n        var dimensions = {\n            width:  element.offsetWidth,\n            height: element.offsetHeight\n        };\n\n        Element.setStyle(element, originalStyles);\n\n        return dimensions;\n    }\n\n    function getOffsetParent(element) {\n        element = $(element);\n\n        function selfOrBody(element) {\n            return isHtml(element) ? $(document.body) : $(element);\n        }\n\n        if (isDocument(element) || isDetached(element) || isBody(element) || isHtml(element))\n            return $(document.body);\n\n        var isInline = (Element.getStyle(element, 'display') === 'inline');\n        if (!isInline && element.offsetParent) return selfOrBody(element.offsetParent);\n\n        while ((element = element.parentNode) && element !== document.body) {\n            if (Element.getStyle(element, 'position') !== 'static') {\n                return selfOrBody(element);\n            }\n        }\n\n        return $(document.body);\n    }\n\n\n    function cumulativeOffset(element) {\n        element = $(element);\n        var valueT = 0, valueL = 0;\n        if (element.parentNode) {\n            do {\n                valueT += element.offsetTop  || 0;\n                valueL += element.offsetLeft || 0;\n                element = element.offsetParent;\n            } while (element);\n        }\n        return new Element.Offset(valueL, valueT);\n    }\n\n    function positionedOffset(element) {\n        element = $(element);\n\n        var layout = element.getLayout();\n\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 (isBody(element)) break;\n                var p = Element.getStyle(element, 'position');\n                if (p !== 'static') break;\n            }\n        } while (element);\n\n        valueL -= layout.get('margin-left');\n        valueT -= layout.get('margin-top');\n\n        return new Element.Offset(valueL, valueT);\n    }\n\n    function cumulativeScrollOffset(element) {\n        var valueT = 0, valueL = 0;\n        do {\n            if (element === document.body) {\n                var bodyScrollNode = document.documentElement || document.body.parentNode || document.body;\n                valueT += !Object.isUndefined(window.pageYOffset) ? window.pageYOffset : bodyScrollNode.scrollTop || 0;\n                valueL += !Object.isUndefined(window.pageXOffset) ? window.pageXOffset : bodyScrollNode.scrollLeft || 0;\n                break;\n            } else {\n                valueT += element.scrollTop  || 0;\n                valueL += element.scrollLeft || 0;\n                element = element.parentNode;\n            }\n        } while (element);\n        return new Element.Offset(valueL, valueT);\n    }\n\n    function viewportOffset(forElement) {\n        var valueT = 0, valueL = 0, docBody = document.body;\n\n        forElement = $(forElement);\n        var element = forElement;\n        do {\n            valueT += element.offsetTop  || 0;\n            valueL += element.offsetLeft || 0;\n            if (element.offsetParent == docBody &&\n                Element.getStyle(element, 'position') == 'absolute') break;\n        } while (element = element.offsetParent);\n\n        element = forElement;\n        do {\n            if (element != docBody) {\n                valueT -= element.scrollTop  || 0;\n                valueL -= element.scrollLeft || 0;\n            }\n        } while (element = element.parentNode);\n        return new Element.Offset(valueL, valueT);\n    }\n\n    function absolutize(element) {\n        element = $(element);\n\n        if (Element.getStyle(element, 'position') === 'absolute') {\n            return element;\n        }\n\n        var offsetParent = getOffsetParent(element);\n        var eOffset = element.viewportOffset(),\n            pOffset = offsetParent.viewportOffset();\n\n        var offset = eOffset.relativeTo(pOffset);\n        var layout = element.getLayout();\n\n        element.store('prototype_absolutize_original_styles', {\n            position: element.getStyle('position'),\n            left:     element.getStyle('left'),\n            top:      element.getStyle('top'),\n            width:    element.getStyle('width'),\n            height:   element.getStyle('height')\n        });\n\n        element.setStyle({\n            position: 'absolute',\n            top:    offset.top + 'px',\n            left:   offset.left + 'px',\n            width:  layout.get('width') + 'px',\n            height: layout.get('height') + 'px'\n        });\n\n        return element;\n    }\n\n    function relativize(element) {\n        element = $(element);\n        if (Element.getStyle(element, 'position') === 'relative') {\n            return element;\n        }\n\n        var originalStyles =\n            element.retrieve('prototype_absolutize_original_styles');\n\n        if (originalStyles) element.setStyle(originalStyles);\n        return element;\n    }\n\n\n    function scrollTo(element) {\n        element = $(element);\n        var pos = Element.cumulativeOffset(element);\n        window.scrollTo(pos.left, pos.top);\n        return element;\n    }\n\n\n    function makePositioned(element) {\n        element = $(element);\n        var position = Element.getStyle(element, 'position'), styles = {};\n        if (position === 'static' || !position) {\n            styles.position = 'relative';\n            if (Prototype.Browser.Opera) {\n                styles.top  = 0;\n                styles.left = 0;\n            }\n            Element.setStyle(element, styles);\n            Element.store(element, 'prototype_made_positioned', true);\n        }\n        return element;\n    }\n\n    function undoPositioned(element) {\n        element = $(element);\n        var storage = Element.getStorage(element),\n            madePositioned = storage.get('prototype_made_positioned');\n\n        if (madePositioned) {\n            storage.unset('prototype_made_positioned');\n            Element.setStyle(element, {\n                position: '',\n                top:      '',\n                bottom:   '',\n                left:     '',\n                right:    ''\n            });\n        }\n        return element;\n    }\n\n    function makeClipping(element) {\n        element = $(element);\n\n        var storage = Element.getStorage(element),\n            madeClipping = storage.get('prototype_made_clipping');\n\n        if (Object.isUndefined(madeClipping)) {\n            var overflow = Element.getStyle(element, 'overflow');\n            storage.set('prototype_made_clipping', overflow);\n            if (overflow !== 'hidden')\n                element.style.overflow = 'hidden';\n        }\n\n        return element;\n    }\n\n    function undoClipping(element) {\n        element = $(element);\n        var storage = Element.getStorage(element),\n            overflow = storage.get('prototype_made_clipping');\n\n        if (!Object.isUndefined(overflow)) {\n            storage.unset('prototype_made_clipping');\n            element.style.overflow = overflow || '';\n        }\n\n        return element;\n    }\n\n    function clonePosition(element, source, options) {\n        options = Object.extend({\n            setLeft:    true,\n            setTop:     true,\n            setWidth:   true,\n            setHeight:  true,\n            offsetTop:  0,\n            offsetLeft: 0\n        }, options || {});\n\n        var docEl = document.documentElement;\n\n        source  = $(source);\n        element = $(element);\n        var p, delta, layout, styles = {};\n\n        if (options.setLeft || options.setTop) {\n            p = Element.viewportOffset(source);\n            delta = [0, 0];\n            if (Element.getStyle(element, 'position') === 'absolute') {\n                var parent = Element.getOffsetParent(element);\n                if (parent !== document.body) delta = Element.viewportOffset(parent);\n            }\n        }\n\n        function pageScrollXY() {\n            var x = 0, y = 0;\n            if (Object.isNumber(window.pageXOffset)) {\n                x = window.pageXOffset;\n                y = window.pageYOffset;\n            } else if (document.body && (document.body.scrollLeft || document.body.scrollTop)) {\n                x = document.body.scrollLeft;\n                y = document.body.scrollTop;\n            } else if (docEl && (docEl.scrollLeft || docEl.scrollTop)) {\n                x = docEl.scrollLeft;\n                y = docEl.scrollTop;\n            }\n            return { x: x, y: y };\n        }\n\n        var pageXY = pageScrollXY();\n\n\n        if (options.setWidth || options.setHeight) {\n            layout = Element.getLayout(source);\n        }\n\n        if (options.setLeft)\n            styles.left = (p[0] + pageXY.x - delta[0] + options.offsetLeft) + 'px';\n        if (options.setTop)\n            styles.top  = (p[1] + pageXY.y - delta[1] + options.offsetTop)  + 'px';\n\n        var currentLayout = element.getLayout();\n\n        if (options.setWidth) {\n            styles.width = layout.get('width')  + 'px';\n        }\n        if (options.setHeight) {\n            styles.height = layout.get('height') + 'px';\n        }\n\n        return Element.setStyle(element, styles);\n    }\n\n\n    if (Prototype.Browser.IE) {\n        getOffsetParent = getOffsetParent.wrap(\n            function(proceed, element) {\n                element = $(element);\n\n                if (isDocument(element) || isDetached(element) || isBody(element) || isHtml(element))\n                    return $(document.body);\n\n                var position = element.getStyle('position');\n                if (position !== 'static') return proceed(element);\n\n                element.setStyle({ position: 'relative' });\n                var value = proceed(element);\n                element.setStyle({ position: position });\n                return value;\n            }\n        );\n\n        positionedOffset = positionedOffset.wrap(function(proceed, element) {\n            element = $(element);\n            if (!element.parentNode) return new Element.Offset(0, 0);\n            var position = element.getStyle('position');\n            if (position !== 'static') return proceed(element);\n\n            var offsetParent = element.getOffsetParent();\n            if (offsetParent && offsetParent.getStyle('position') === 'fixed')\n                hasLayout(offsetParent);\n\n            element.setStyle({ position: 'relative' });\n            var value = proceed(element);\n            element.setStyle({ position: position });\n            return value;\n        });\n    } else if (Prototype.Browser.Webkit) {\n        cumulativeOffset = function(element) {\n            element = $(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\n                element = element.offsetParent;\n            } while (element);\n\n            return new Element.Offset(valueL, valueT);\n        };\n    }\n\n\n    Element.addMethods({\n        getLayout:              getLayout,\n        measure:                measure,\n        getWidth:               getWidth,\n        getHeight:              getHeight,\n        getDimensions:          getDimensions,\n        getOffsetParent:        getOffsetParent,\n        cumulativeOffset:       cumulativeOffset,\n        positionedOffset:       positionedOffset,\n        cumulativeScrollOffset: cumulativeScrollOffset,\n        viewportOffset:         viewportOffset,\n        absolutize:             absolutize,\n        relativize:             relativize,\n        scrollTo:               scrollTo,\n        makePositioned:         makePositioned,\n        undoPositioned:         undoPositioned,\n        makeClipping:           makeClipping,\n        undoClipping:           undoClipping,\n        clonePosition:          clonePosition\n    });\n\n    function isBody(element) {\n        return element.nodeName.toUpperCase() === 'BODY';\n    }\n\n    function isHtml(element) {\n        return element.nodeName.toUpperCase() === 'HTML';\n    }\n\n    function isDocument(element) {\n        return element.nodeType === Node.DOCUMENT_NODE;\n    }\n\n    function isDetached(element) {\n        return element !== document.body &&\n            !Element.descendantOf(element, document.body);\n    }\n\n    if ('getBoundingClientRect' in document.documentElement) {\n        Element.addMethods({\n            viewportOffset: function(element) {\n                element = $(element);\n                if (isDetached(element)) return new Element.Offset(0, 0);\n\n                var rect = element.getBoundingClientRect(),\n                    docEl = document.documentElement;\n                return new Element.Offset(rect.left - docEl.clientLeft,\n                    rect.top - docEl.clientTop);\n            }\n        });\n    }\n\n\n})();\n\n(function() {\n\n    var IS_OLD_OPERA = Prototype.Browser.Opera &&\n        (window.parseFloat(window.opera.version()) < 9.5);\n    var ROOT = null;\n    function getRootElement() {\n        if (ROOT) return ROOT;\n        ROOT = IS_OLD_OPERA ? document.body : document.documentElement;\n        return ROOT;\n    }\n\n    function getDimensions() {\n        return { width: this.getWidth(), height: this.getHeight() };\n    }\n\n    function getWidth() {\n        return getRootElement().clientWidth;\n    }\n\n    function getHeight() {\n        return getRootElement().clientHeight;\n    }\n\n    function getScrollOffsets() {\n        var x = window.pageXOffset || document.documentElement.scrollLeft ||\n            document.body.scrollLeft;\n        var y = window.pageYOffset || document.documentElement.scrollTop ||\n            document.body.scrollTop;\n\n        return new Element.Offset(x, y);\n    }\n\n    document.viewport = {\n        getDimensions:    getDimensions,\n        getWidth:         getWidth,\n        getHeight:        getHeight,\n        getScrollOffsets: getScrollOffsets\n    };\n\n})();\nwindow.$$ = function() {\n    var expression = $A(arguments).join(', ');\n    return Prototype.Selector.select(expression, document);\n};\n\nPrototype.Selector = (function() {\n\n    function select() {\n        throw new Error('Method \"Prototype.Selector.select\" must be defined.');\n    }\n\n    function match() {\n        throw new Error('Method \"Prototype.Selector.match\" must be defined.');\n    }\n\n    function find(elements, expression, index) {\n        index = index || 0;\n        var match = Prototype.Selector.match, length = elements.length, matchIndex = 0, i;\n\n        for (i = 0; i < length; i++) {\n            if (match(elements[i], expression) && index == matchIndex++) {\n                return Element.extend(elements[i]);\n            }\n        }\n    }\n\n    function extendElements(elements) {\n        for (var i = 0, length = elements.length; i < length; i++) {\n            Element.extend(elements[i]);\n        }\n        return elements;\n    }\n\n\n    var K = Prototype.K;\n\n    return {\n        select: select,\n        match: match,\n        find: find,\n        extendElements: (Element.extend === K) ? K : extendElements,\n        extendElement: Element.extend\n    };\n})();\nPrototype._original_property = window.Sizzle;\n\n;(function () {\n    function fakeDefine(fn) {\n        Prototype._actual_sizzle = fn();\n    }\n    fakeDefine.amd = true;\n\n    if (typeof define !== 'undefined' && define.amd) {\n        Prototype._original_define = define;\n        Prototype._actual_sizzle = null;\n        window.define = fakeDefine;\n    }\n})();\n\n/*!\n * Sizzle CSS Selector Engine v1.10.18\n * http://sizzlejs.com/\n *\n * Copyright 2013 jQuery Foundation, Inc. and other contributors\n * Released under the MIT license\n * http://jquery.org/license\n *\n * Date: 2014-02-05\n */\n(function( window ) {\n\n    var i,\n        support,\n        Expr,\n        getText,\n        isXML,\n        compile,\n        select,\n        outermostContext,\n        sortInput,\n        hasDuplicate,\n\n        setDocument,\n        document,\n        docElem,\n        documentIsHTML,\n        rbuggyQSA,\n        rbuggyMatches,\n        matches,\n        contains,\n\n        expando = \"sizzle\" + -(new Date()),\n        preferredDoc = window.document,\n        dirruns = 0,\n        done = 0,\n        classCache = createCache(),\n        tokenCache = createCache(),\n        compilerCache = createCache(),\n        sortOrder = function( a, b ) {\n            if ( a === b ) {\n                hasDuplicate = true;\n            }\n            return 0;\n        },\n\n        strundefined = typeof undefined,\n        MAX_NEGATIVE = 1 << 31,\n\n        hasOwn = ({}).hasOwnProperty,\n        arr = [],\n        pop = arr.pop,\n        push_native = arr.push,\n        push = arr.push,\n        slice = arr.slice,\n        indexOf = arr.indexOf || function( elem ) {\n                var i = 0,\n                    len = this.length;\n                for ( ; i < len; i++ ) {\n                    if ( this[i] === elem ) {\n                        return i;\n                    }\n                }\n                return -1;\n            },\n\n        booleans = \"checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped\",\n\n\n        whitespace = \"[\\\\x20\\\\t\\\\r\\\\n\\\\f]\",\n        characterEncoding = \"(?:\\\\\\\\.|[\\\\w-]|[^\\\\x00-\\\\xa0])+\",\n\n        identifier = characterEncoding.replace( \"w\", \"w#\" ),\n\n        attributes = \"\\\\[\" + whitespace + \"*(\" + characterEncoding + \")\" + whitespace +\n            \"*(?:([*^$|!~]?=)\" + whitespace + \"*(?:(['\\\"])((?:\\\\\\\\.|[^\\\\\\\\])*?)\\\\3|(\" + identifier + \")|)|)\" + whitespace + \"*\\\\]\",\n\n        pseudos = \":(\" + characterEncoding + \")(?:\\\\(((['\\\"])((?:\\\\\\\\.|[^\\\\\\\\])*?)\\\\3|((?:\\\\\\\\.|[^\\\\\\\\()[\\\\]]|\" + attributes.replace( 3, 8 ) + \")*)|.*)\\\\)|)\",\n\n        rtrim = new RegExp( \"^\" + whitespace + \"+|((?:^|[^\\\\\\\\])(?:\\\\\\\\.)*)\" + whitespace + \"+$\", \"g\" ),\n\n        rcomma = new RegExp( \"^\" + whitespace + \"*,\" + whitespace + \"*\" ),\n        rcombinators = new RegExp( \"^\" + whitespace + \"*([>+~]|\" + whitespace + \")\" + whitespace + \"*\" ),\n\n        rattributeQuotes = new RegExp( \"=\" + whitespace + \"*([^\\\\]'\\\"]*?)\" + whitespace + \"*\\\\]\", \"g\" ),\n\n        rpseudo = new RegExp( pseudos ),\n        ridentifier = new RegExp( \"^\" + identifier + \"$\" ),\n\n        matchExpr = {\n            \"ID\": new RegExp( \"^#(\" + characterEncoding + \")\" ),\n            \"CLASS\": new RegExp( \"^\\\\.(\" + characterEncoding + \")\" ),\n            \"TAG\": new RegExp( \"^(\" + characterEncoding.replace( \"w\", \"w*\" ) + \")\" ),\n            \"ATTR\": new RegExp( \"^\" + attributes ),\n            \"PSEUDO\": new RegExp( \"^\" + pseudos ),\n            \"CHILD\": new RegExp( \"^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\\\(\" + whitespace +\n                \"*(even|odd|(([+-]|)(\\\\d*)n|)\" + whitespace + \"*(?:([+-]|)\" + whitespace +\n                \"*(\\\\d+)|))\" + whitespace + \"*\\\\)|)\", \"i\" ),\n            \"bool\": new RegExp( \"^(?:\" + booleans + \")$\", \"i\" ),\n            \"needsContext\": new RegExp( \"^\" + whitespace + \"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\\\(\" +\n                whitespace + \"*((?:-\\\\d)?\\\\d*)\" + whitespace + \"*\\\\)|)(?=[^-]|$)\", \"i\" )\n        },\n\n        rinputs = /^(?:input|select|textarea|button)$/i,\n        rheader = /^h\\d$/i,\n\n        rnative = /^[^{]+\\{\\s*\\[native \\w/,\n\n        rquickExpr = /^(?:#([\\w-]+)|(\\w+)|\\.([\\w-]+))$/,\n\n        rsibling = /[+~]/,\n        rescape = /'|\\\\/g,\n\n        runescape = new RegExp( \"\\\\\\\\([\\\\da-f]{1,6}\" + whitespace + \"?|(\" + whitespace + \")|.)\", \"ig\" ),\n        funescape = function( _, escaped, escapedWhitespace ) {\n            var high = \"0x\" + escaped - 0x10000;\n            return high !== high || escapedWhitespace ?\n                escaped :\n                high < 0 ?\n                    String.fromCharCode( high + 0x10000 ) :\n                    String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 );\n        };\n\n    try {\n        push.apply(\n            (arr = slice.call( preferredDoc.childNodes )),\n            preferredDoc.childNodes\n        );\n        arr[ preferredDoc.childNodes.length ].nodeType;\n    } catch ( e ) {\n        push = { apply: arr.length ?\n\n            function( target, els ) {\n                push_native.apply( target, slice.call(els) );\n            } :\n\n            function( target, els ) {\n                var j = target.length,\n                    i = 0;\n                while ( (target[j++] = els[i++]) ) {}\n                target.length = j - 1;\n            }\n        };\n    }\n\n    function Sizzle( selector, context, results, seed ) {\n        var match, elem, m, nodeType,\n            i, groups, old, nid, newContext, newSelector;\n\n        if ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) {\n            setDocument( context );\n        }\n\n        context = context || document;\n        results = results || [];\n\n        if ( !selector || typeof selector !== \"string\" ) {\n            return results;\n        }\n\n        if ( (nodeType = context.nodeType) !== 1 && nodeType !== 9 ) {\n            return [];\n        }\n\n        if ( documentIsHTML && !seed ) {\n\n            if ( (match = rquickExpr.exec( selector )) ) {\n                if ( (m = match[1]) ) {\n                    if ( nodeType === 9 ) {\n                        elem = context.getElementById( m );\n                        if ( elem && elem.parentNode ) {\n                            if ( elem.id === m ) {\n                                results.push( elem );\n                                return results;\n                            }\n                        } else {\n                            return results;\n                        }\n                    } else {\n                        if ( context.ownerDocument && (elem = context.ownerDocument.getElementById( m )) &&\n                            contains( context, elem ) && elem.id === m ) {\n                            results.push( elem );\n                            return results;\n                        }\n                    }\n\n                } else if ( match[2] ) {\n                    push.apply( results, context.getElementsByTagName( selector ) );\n                    return results;\n\n                } else if ( (m = match[3]) && support.getElementsByClassName && context.getElementsByClassName ) {\n                    push.apply( results, context.getElementsByClassName( m ) );\n                    return results;\n                }\n            }\n\n            if ( support.qsa && (!rbuggyQSA || !rbuggyQSA.test( selector )) ) {\n                nid = old = expando;\n                newContext = context;\n                newSelector = nodeType === 9 && selector;\n\n                if ( nodeType === 1 && context.nodeName.toLowerCase() !== \"object\" ) {\n                    groups = tokenize( selector );\n\n                    if ( (old = context.getAttribute(\"id\")) ) {\n                        nid = old.replace( rescape, \"\\\\$&\" );\n                    } else {\n                        context.setAttribute( \"id\", nid );\n                    }\n                    nid = \"[id='\" + nid + \"'] \";\n\n                    i = groups.length;\n                    while ( i-- ) {\n                        groups[i] = nid + toSelector( groups[i] );\n                    }\n                    newContext = rsibling.test( selector ) && testContext( context.parentNode ) || context;\n                    newSelector = groups.join(\",\");\n                }\n\n                if ( newSelector ) {\n                    try {\n                        push.apply( results,\n                            newContext.querySelectorAll( newSelector )\n                        );\n                        return results;\n                    } catch(qsaError) {\n                    } finally {\n                        if ( !old ) {\n                            context.removeAttribute(\"id\");\n                        }\n                    }\n                }\n            }\n        }\n\n        return 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     */\n    function createCache() {\n        var keys = [];\n\n        function cache( key, value ) {\n            if ( keys.push( key + \" \" ) > Expr.cacheLength ) {\n                delete cache[ keys.shift() ];\n            }\n            return (cache[ key + \" \" ] = value);\n        }\n        return cache;\n    }\n\n    /**\n     * Mark a function for special use by Sizzle\n     * @param {Function} fn The function to mark\n     */\n    function markFunction( fn ) {\n        fn[ expando ] = true;\n        return fn;\n    }\n\n    /**\n     * Support testing using an element\n     * @param {Function} fn Passed the created div and expects a boolean result\n     */\n    function assert( fn ) {\n        var div = document.createElement(\"div\");\n\n        try {\n            return !!fn( div );\n        } catch (e) {\n            return false;\n        } finally {\n            if ( div.parentNode ) {\n                div.parentNode.removeChild( div );\n            }\n            div = null;\n        }\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     */\n    function addHandle( attrs, handler ) {\n        var arr = attrs.split(\"|\"),\n            i = attrs.length;\n\n        while ( i-- ) {\n            Expr.attrHandle[ arr[i] ] = handler;\n        }\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     */\n    function siblingCheck( a, b ) {\n        var cur = b && a,\n            diff = cur && a.nodeType === 1 && b.nodeType === 1 &&\n                ( ~b.sourceIndex || MAX_NEGATIVE ) -\n                ( ~a.sourceIndex || MAX_NEGATIVE );\n\n        if ( diff ) {\n            return diff;\n        }\n\n        if ( cur ) {\n            while ( (cur = cur.nextSibling) ) {\n                if ( cur === b ) {\n                    return -1;\n                }\n            }\n        }\n\n        return a ? 1 : -1;\n    }\n\n    /**\n     * Returns a function to use in pseudos for input types\n     * @param {String} type\n     */\n    function createInputPseudo( type ) {\n        return function( elem ) {\n            var name = elem.nodeName.toLowerCase();\n            return name === \"input\" && elem.type === type;\n        };\n    }\n\n    /**\n     * Returns a function to use in pseudos for buttons\n     * @param {String} type\n     */\n    function createButtonPseudo( type ) {\n        return function( elem ) {\n            var name = elem.nodeName.toLowerCase();\n            return (name === \"input\" || name === \"button\") && elem.type === type;\n        };\n    }\n\n    /**\n     * Returns a function to use in pseudos for positionals\n     * @param {Function} fn\n     */\n    function createPositionalPseudo( fn ) {\n        return markFunction(function( argument ) {\n            argument = +argument;\n            return markFunction(function( seed, matches ) {\n                var j,\n                    matchIndexes = fn( [], seed.length, argument ),\n                    i = matchIndexes.length;\n\n                while ( i-- ) {\n                    if ( seed[ (j = matchIndexes[i]) ] ) {\n                        seed[j] = !(matches[j] = seed[j]);\n                    }\n                }\n            });\n        });\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     */\n    function testContext( context ) {\n        return context && typeof context.getElementsByTagName !== strundefined && context;\n    }\n\n    support = 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     */\n    isXML = Sizzle.isXML = function( elem ) {\n        var documentElement = elem && (elem.ownerDocument || elem).documentElement;\n        return 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     */\n    setDocument = Sizzle.setDocument = function( node ) {\n        var hasCompare,\n            doc = node ? node.ownerDocument || node : preferredDoc,\n            parent = doc.defaultView;\n\n        if ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) {\n            return document;\n        }\n\n        document = doc;\n        docElem = doc.documentElement;\n\n        documentIsHTML = !isXML( doc );\n\n        if ( parent && parent !== parent.top ) {\n            if ( parent.addEventListener ) {\n                parent.addEventListener( \"unload\", function() {\n                    setDocument();\n                }, false );\n            } else if ( parent.attachEvent ) {\n                parent.attachEvent( \"onunload\", function() {\n                    setDocument();\n                });\n            }\n        }\n\n        /* Attributes\n         ---------------------------------------------------------------------- */\n\n        support.attributes = assert(function( div ) {\n            div.className = \"i\";\n            return !div.getAttribute(\"className\");\n        });\n\n        /* getElement(s)By*\n         ---------------------------------------------------------------------- */\n\n        support.getElementsByTagName = assert(function( div ) {\n            div.appendChild( doc.createComment(\"\") );\n            return !div.getElementsByTagName(\"*\").length;\n        });\n\n        support.getElementsByClassName = rnative.test( doc.getElementsByClassName ) && assert(function( div ) {\n                div.innerHTML = \"<div class='a'></div><div class='a i'></div>\";\n\n                div.firstChild.className = \"i\";\n                return div.getElementsByClassName(\"i\").length === 2;\n            });\n\n        support.getById = assert(function( div ) {\n            docElem.appendChild( div ).id = expando;\n            return !doc.getElementsByName || !doc.getElementsByName( expando ).length;\n        });\n\n        if ( support.getById ) {\n            Expr.find[\"ID\"] = function( id, context ) {\n                if ( typeof context.getElementById !== strundefined && documentIsHTML ) {\n                    var m = context.getElementById( id );\n                    return m && m.parentNode ? [m] : [];\n                }\n            };\n            Expr.filter[\"ID\"] = function( id ) {\n                var attrId = id.replace( runescape, funescape );\n                return function( elem ) {\n                    return elem.getAttribute(\"id\") === attrId;\n                };\n            };\n        } else {\n            delete Expr.find[\"ID\"];\n\n            Expr.filter[\"ID\"] =  function( id ) {\n                var attrId = id.replace( runescape, funescape );\n                return function( elem ) {\n                    var node = typeof elem.getAttributeNode !== strundefined && elem.getAttributeNode(\"id\");\n                    return node && node.value === attrId;\n                };\n            };\n        }\n\n        Expr.find[\"TAG\"] = support.getElementsByTagName ?\n            function( tag, context ) {\n                if ( typeof context.getElementsByTagName !== strundefined ) {\n                    return context.getElementsByTagName( tag );\n                }\n            } :\n            function( tag, context ) {\n                var elem,\n                    tmp = [],\n                    i = 0,\n                    results = context.getElementsByTagName( tag );\n\n                if ( tag === \"*\" ) {\n                    while ( (elem = results[i++]) ) {\n                        if ( elem.nodeType === 1 ) {\n                            tmp.push( elem );\n                        }\n                    }\n\n                    return tmp;\n                }\n                return results;\n            };\n\n        Expr.find[\"CLASS\"] = support.getElementsByClassName && function( className, context ) {\n                if ( typeof context.getElementsByClassName !== strundefined && documentIsHTML ) {\n                    return context.getElementsByClassName( className );\n                }\n            };\n\n        /* QSA/matchesSelector\n         ---------------------------------------------------------------------- */\n\n\n        rbuggyMatches = [];\n\n        rbuggyQSA = [];\n\n        if ( (support.qsa = rnative.test( doc.querySelectorAll )) ) {\n            assert(function( div ) {\n                div.innerHTML = \"<select t=''><option selected=''></option></select>\";\n\n                if ( div.querySelectorAll(\"[t^='']\").length ) {\n                    rbuggyQSA.push( \"[*^$]=\" + whitespace + \"*(?:''|\\\"\\\")\" );\n                }\n\n                if ( !div.querySelectorAll(\"[selected]\").length ) {\n                    rbuggyQSA.push( \"\\\\[\" + whitespace + \"*(?:value|\" + booleans + \")\" );\n                }\n\n                if ( !div.querySelectorAll(\":checked\").length ) {\n                    rbuggyQSA.push(\":checked\");\n                }\n            });\n\n            assert(function( div ) {\n                var input = doc.createElement(\"input\");\n                input.setAttribute( \"type\", \"hidden\" );\n                div.appendChild( input ).setAttribute( \"name\", \"D\" );\n\n                if ( div.querySelectorAll(\"[name=d]\").length ) {\n                    rbuggyQSA.push( \"name\" + whitespace + \"*[*^$|!~]?=\" );\n                }\n\n                if ( !div.querySelectorAll(\":enabled\").length ) {\n                    rbuggyQSA.push( \":enabled\", \":disabled\" );\n                }\n\n                div.querySelectorAll(\"*,:x\");\n                rbuggyQSA.push(\",.*:\");\n            });\n        }\n\n        if ( (support.matchesSelector = rnative.test( (matches = docElem.webkitMatchesSelector ||\n                docElem.mozMatchesSelector ||\n                docElem.oMatchesSelector ||\n                docElem.msMatchesSelector) )) ) {\n\n            assert(function( div ) {\n                support.disconnectedMatch = matches.call( div, \"div\" );\n\n                matches.call( div, \"[s!='']:x\" );\n                rbuggyMatches.push( \"!=\", pseudos );\n            });\n        }\n\n        rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join(\"|\") );\n        rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join(\"|\") );\n\n        /* Contains\n         ---------------------------------------------------------------------- */\n        hasCompare = rnative.test( docElem.compareDocumentPosition );\n\n        contains = hasCompare || rnative.test( docElem.contains ) ?\n            function( a, b ) {\n                var adown = a.nodeType === 9 ? a.documentElement : a,\n                    bup = b && b.parentNode;\n                return a === bup || !!( bup && bup.nodeType === 1 && (\n                        adown.contains ?\n                            adown.contains( bup ) :\n                            a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16\n                    ));\n            } :\n            function( a, b ) {\n                if ( b ) {\n                    while ( (b = b.parentNode) ) {\n                        if ( b === a ) {\n                            return true;\n                        }\n                    }\n                }\n                return false;\n            };\n\n        /* Sorting\n         ---------------------------------------------------------------------- */\n\n        sortOrder = hasCompare ?\n            function( a, b ) {\n\n                if ( a === b ) {\n                    hasDuplicate = true;\n                    return 0;\n                }\n\n                var compare = !a.compareDocumentPosition - !b.compareDocumentPosition;\n                if ( compare ) {\n                    return compare;\n                }\n\n                compare = ( a.ownerDocument || a ) === ( b.ownerDocument || b ) ?\n                    a.compareDocumentPosition( b ) :\n\n                    1;\n\n                if ( compare & 1 ||\n                    (!support.sortDetached && b.compareDocumentPosition( a ) === compare) ) {\n\n                    if ( a === doc || a.ownerDocument === preferredDoc && contains(preferredDoc, a) ) {\n                        return -1;\n                    }\n                    if ( b === doc || b.ownerDocument === preferredDoc && contains(preferredDoc, b) ) {\n                        return 1;\n                    }\n\n                    return sortInput ?\n                        ( indexOf.call( sortInput, a ) - indexOf.call( sortInput, b ) ) :\n                        0;\n                }\n\n                return compare & 4 ? -1 : 1;\n            } :\n            function( a, b ) {\n                if ( a === b ) {\n                    hasDuplicate = true;\n                    return 0;\n                }\n\n                var cur,\n                    i = 0,\n                    aup = a.parentNode,\n                    bup = b.parentNode,\n                    ap = [ a ],\n                    bp = [ b ];\n\n                if ( !aup || !bup ) {\n                    return a === doc ? -1 :\n                        b === doc ? 1 :\n                            aup ? -1 :\n                                bup ? 1 :\n                                    sortInput ?\n                                        ( indexOf.call( sortInput, a ) - indexOf.call( sortInput, b ) ) :\n                                        0;\n\n                } else if ( aup === bup ) {\n                    return siblingCheck( a, b );\n                }\n\n                cur = a;\n                while ( (cur = cur.parentNode) ) {\n                    ap.unshift( cur );\n                }\n                cur = b;\n                while ( (cur = cur.parentNode) ) {\n                    bp.unshift( cur );\n                }\n\n                while ( ap[i] === bp[i] ) {\n                    i++;\n                }\n\n                return i ?\n                    siblingCheck( ap[i], bp[i] ) :\n\n                    ap[i] === preferredDoc ? -1 :\n                        bp[i] === preferredDoc ? 1 :\n                            0;\n            };\n\n        return doc;\n    };\n\n    Sizzle.matches = function( expr, elements ) {\n        return Sizzle( expr, null, null, elements );\n    };\n\n    Sizzle.matchesSelector = function( elem, expr ) {\n        if ( ( elem.ownerDocument || elem ) !== document ) {\n            setDocument( elem );\n        }\n\n        expr = expr.replace( rattributeQuotes, \"='$1']\" );\n\n        if ( support.matchesSelector && documentIsHTML &&\n            ( !rbuggyMatches || !rbuggyMatches.test( expr ) ) &&\n            ( !rbuggyQSA     || !rbuggyQSA.test( expr ) ) ) {\n\n            try {\n                var ret = matches.call( elem, expr );\n\n                if ( ret || support.disconnectedMatch ||\n                    elem.document && elem.document.nodeType !== 11 ) {\n                    return ret;\n                }\n            } catch(e) {}\n        }\n\n        return Sizzle( expr, document, null, [elem] ).length > 0;\n    };\n\n    Sizzle.contains = function( context, elem ) {\n        if ( ( context.ownerDocument || context ) !== document ) {\n            setDocument( context );\n        }\n        return contains( context, elem );\n    };\n\n    Sizzle.attr = function( elem, name ) {\n        if ( ( elem.ownerDocument || elem ) !== document ) {\n            setDocument( elem );\n        }\n\n        var fn = Expr.attrHandle[ name.toLowerCase() ],\n            val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ?\n                fn( elem, name, !documentIsHTML ) :\n                undefined;\n\n        return val !== undefined ?\n            val :\n            support.attributes || !documentIsHTML ?\n                elem.getAttribute( name ) :\n                (val = elem.getAttributeNode(name)) && val.specified ?\n                    val.value :\n                    null;\n    };\n\n    Sizzle.error = function( msg ) {\n        throw new Error( \"Syntax error, unrecognized expression: \" + msg );\n    };\n\n    /**\n     * Document sorting and removing duplicates\n     * @param {ArrayLike} results\n     */\n    Sizzle.uniqueSort = function( results ) {\n        var elem,\n            duplicates = [],\n            j = 0,\n            i = 0;\n\n        hasDuplicate = !support.detectDuplicates;\n        sortInput = !support.sortStable && results.slice( 0 );\n        results.sort( sortOrder );\n\n        if ( hasDuplicate ) {\n            while ( (elem = results[i++]) ) {\n                if ( elem === results[ i ] ) {\n                    j = duplicates.push( i );\n                }\n            }\n            while ( j-- ) {\n                results.splice( duplicates[ j ], 1 );\n            }\n        }\n\n        sortInput = null;\n\n        return results;\n    };\n\n    /**\n     * Utility function for retrieving the text value of an array of DOM nodes\n     * @param {Array|Element} elem\n     */\n    getText = Sizzle.getText = function( elem ) {\n        var node,\n            ret = \"\",\n            i = 0,\n            nodeType = elem.nodeType;\n\n        if ( !nodeType ) {\n            while ( (node = elem[i++]) ) {\n                ret += getText( node );\n            }\n        } else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) {\n            if ( typeof elem.textContent === \"string\" ) {\n                return elem.textContent;\n            } else {\n                for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {\n                    ret += getText( elem );\n                }\n            }\n        } else if ( nodeType === 3 || nodeType === 4 ) {\n            return elem.nodeValue;\n        }\n\n        return ret;\n    };\n\n    Expr = Sizzle.selectors = {\n\n        cacheLength: 50,\n\n        createPseudo: markFunction,\n\n        match: matchExpr,\n\n        attrHandle: {},\n\n        find: {},\n\n        relative: {\n            \">\": { dir: \"parentNode\", first: true },\n            \" \": { dir: \"parentNode\" },\n            \"+\": { dir: \"previousSibling\", first: true },\n            \"~\": { dir: \"previousSibling\" }\n        },\n\n        preFilter: {\n            \"ATTR\": function( match ) {\n                match[1] = match[1].replace( runescape, funescape );\n\n                match[3] = ( match[4] || match[5] || \"\" ).replace( runescape, funescape );\n\n                if ( match[2] === \"~=\" ) {\n                    match[3] = \" \" + match[3] + \" \";\n                }\n\n                return match.slice( 0, 4 );\n            },\n\n            \"CHILD\": function( match ) {\n                /* matches from matchExpr[\"CHILD\"]\n                 1 type (only|nth|...)\n                 2 what (child|of-type)\n                 3 argument (even|odd|\\d*|\\d*n([+-]\\d+)?|...)\n                 4 xn-component of xn+y argument ([+-]?\\d*n|)\n                 5 sign of xn-component\n                 6 x of xn-component\n                 7 sign of y-component\n                 8 y of y-component\n                 */\n                match[1] = match[1].toLowerCase();\n\n                if ( match[1].slice( 0, 3 ) === \"nth\" ) {\n                    if ( !match[3] ) {\n                        Sizzle.error( match[0] );\n                    }\n\n                    match[4] = +( match[4] ? match[5] + (match[6] || 1) : 2 * ( match[3] === \"even\" || match[3] === \"odd\" ) );\n                    match[5] = +( ( match[7] + match[8] ) || match[3] === \"odd\" );\n\n                } else if ( match[3] ) {\n                    Sizzle.error( match[0] );\n                }\n\n                return match;\n            },\n\n            \"PSEUDO\": function( match ) {\n                var excess,\n                    unquoted = !match[5] && match[2];\n\n                if ( matchExpr[\"CHILD\"].test( match[0] ) ) {\n                    return null;\n                }\n\n                if ( match[3] && match[4] !== undefined ) {\n                    match[2] = match[4];\n\n                } else if ( unquoted && rpseudo.test( unquoted ) &&\n                    (excess = tokenize( unquoted, true )) &&\n                    (excess = unquoted.indexOf( \")\", unquoted.length - excess ) - unquoted.length) ) {\n\n                    match[0] = match[0].slice( 0, excess );\n                    match[2] = unquoted.slice( 0, excess );\n                }\n\n                return match.slice( 0, 3 );\n            }\n        },\n\n        filter: {\n\n            \"TAG\": function( nodeNameSelector ) {\n                var nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase();\n                return nodeNameSelector === \"*\" ?\n                    function() { return true; } :\n                    function( elem ) {\n                        return elem.nodeName && elem.nodeName.toLowerCase() === nodeName;\n                    };\n            },\n\n            \"CLASS\": function( className ) {\n                var pattern = classCache[ className + \" \" ];\n\n                return pattern ||\n                    (pattern = new RegExp( \"(^|\" + whitespace + \")\" + className + \"(\" + whitespace + \"|$)\" )) &&\n                    classCache( className, function( elem ) {\n                        return pattern.test( typeof elem.className === \"string\" && elem.className || typeof elem.getAttribute !== strundefined && elem.getAttribute(\"class\") || \"\" );\n                    });\n            },\n\n            \"ATTR\": function( name, operator, check ) {\n                return function( elem ) {\n                    var result = Sizzle.attr( elem, name );\n\n                    if ( result == null ) {\n                        return operator === \"!=\";\n                    }\n                    if ( !operator ) {\n                        return true;\n                    }\n\n                    result += \"\";\n\n                    return operator === \"=\" ? result === check :\n                        operator === \"!=\" ? result !== check :\n                            operator === \"^=\" ? check && result.indexOf( check ) === 0 :\n                                operator === \"*=\" ? check && result.indexOf( check ) > -1 :\n                                    operator === \"$=\" ? check && result.slice( -check.length ) === check :\n                                        operator === \"~=\" ? ( \" \" + result + \" \" ).indexOf( check ) > -1 :\n                                            operator === \"|=\" ? result === check || result.slice( 0, check.length + 1 ) === check + \"-\" :\n                                                false;\n                };\n            },\n\n            \"CHILD\": function( type, what, argument, first, last ) {\n                var simple = type.slice( 0, 3 ) !== \"nth\",\n                    forward = type.slice( -4 ) !== \"last\",\n                    ofType = what === \"of-type\";\n\n                return first === 1 && last === 0 ?\n\n                    function( elem ) {\n                        return !!elem.parentNode;\n                    } :\n\n                    function( elem, context, xml ) {\n                        var cache, outerCache, node, diff, nodeIndex, start,\n                            dir = simple !== forward ? \"nextSibling\" : \"previousSibling\",\n                            parent = elem.parentNode,\n                            name = ofType && elem.nodeName.toLowerCase(),\n                            useCache = !xml && !ofType;\n\n                        if ( parent ) {\n\n                            if ( simple ) {\n                                while ( dir ) {\n                                    node = elem;\n                                    while ( (node = node[ dir ]) ) {\n                                        if ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) {\n                                            return false;\n                                        }\n                                    }\n                                    start = dir = type === \"only\" && !start && \"nextSibling\";\n                                }\n                                return true;\n                            }\n\n                            start = [ forward ? parent.firstChild : parent.lastChild ];\n\n                            if ( forward && useCache ) {\n                                outerCache = parent[ expando ] || (parent[ expando ] = {});\n                                cache = outerCache[ type ] || [];\n                                nodeIndex = cache[0] === dirruns && cache[1];\n                                diff = cache[0] === dirruns && cache[2];\n                                node = nodeIndex && parent.childNodes[ nodeIndex ];\n\n                                while ( (node = ++nodeIndex && node && node[ dir ] ||\n\n                                    (diff = nodeIndex = 0) || start.pop()) ) {\n\n                                    if ( node.nodeType === 1 && ++diff && node === elem ) {\n                                        outerCache[ type ] = [ dirruns, nodeIndex, diff ];\n                                        break;\n                                    }\n                                }\n\n                            } else if ( useCache && (cache = (elem[ expando ] || (elem[ expando ] = {}))[ type ]) && cache[0] === dirruns ) {\n                                diff = cache[1];\n\n                            } else {\n                                while ( (node = ++nodeIndex && node && node[ dir ] ||\n                                    (diff = nodeIndex = 0) || start.pop()) ) {\n\n                                    if ( ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) && ++diff ) {\n                                        if ( useCache ) {\n                                            (node[ expando ] || (node[ expando ] = {}))[ type ] = [ dirruns, diff ];\n                                        }\n\n                                        if ( node === elem ) {\n                                            break;\n                                        }\n                                    }\n                                }\n                            }\n\n                            diff -= last;\n                            return diff === first || ( diff % first === 0 && diff / first >= 0 );\n                        }\n                    };\n            },\n\n            \"PSEUDO\": function( pseudo, argument ) {\n                var args,\n                    fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] ||\n                        Sizzle.error( \"unsupported pseudo: \" + pseudo );\n\n                if ( fn[ expando ] ) {\n                    return fn( argument );\n                }\n\n                if ( fn.length > 1 ) {\n                    args = [ pseudo, pseudo, \"\", argument ];\n                    return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ?\n                        markFunction(function( seed, matches ) {\n                            var idx,\n                                matched = fn( seed, argument ),\n                                i = matched.length;\n                            while ( i-- ) {\n                                idx = indexOf.call( seed, matched[i] );\n                                seed[ idx ] = !( matches[ idx ] = matched[i] );\n                            }\n                        }) :\n                        function( elem ) {\n                            return fn( elem, 0, args );\n                        };\n                }\n\n                return fn;\n            }\n        },\n\n        pseudos: {\n            \"not\": markFunction(function( selector ) {\n                var input = [],\n                    results = [],\n                    matcher = compile( selector.replace( rtrim, \"$1\" ) );\n\n                return matcher[ expando ] ?\n                    markFunction(function( seed, matches, context, xml ) {\n                        var elem,\n                            unmatched = matcher( seed, null, xml, [] ),\n                            i = seed.length;\n\n                        while ( i-- ) {\n                            if ( (elem = unmatched[i]) ) {\n                                seed[i] = !(matches[i] = elem);\n                            }\n                        }\n                    }) :\n                    function( elem, context, xml ) {\n                        input[0] = elem;\n                        matcher( input, null, xml, results );\n                        return !results.pop();\n                    };\n            }),\n\n            \"has\": markFunction(function( selector ) {\n                return function( elem ) {\n                    return Sizzle( selector, elem ).length > 0;\n                };\n            }),\n\n            \"contains\": markFunction(function( text ) {\n                return function( elem ) {\n                    return ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1;\n                };\n            }),\n\n            \"lang\": markFunction( function( lang ) {\n                if ( !ridentifier.test(lang || \"\") ) {\n                    Sizzle.error( \"unsupported lang: \" + lang );\n                }\n                lang = lang.replace( runescape, funescape ).toLowerCase();\n                return function( elem ) {\n                    var elemLang;\n                    do {\n                        if ( (elemLang = documentIsHTML ?\n                                elem.lang :\n                                elem.getAttribute(\"xml:lang\") || elem.getAttribute(\"lang\")) ) {\n\n                            elemLang = elemLang.toLowerCase();\n                            return elemLang === lang || elemLang.indexOf( lang + \"-\" ) === 0;\n                        }\n                    } while ( (elem = elem.parentNode) && elem.nodeType === 1 );\n                    return false;\n                };\n            }),\n\n            \"target\": function( elem ) {\n                var hash = window.location && window.location.hash;\n                return hash && hash.slice( 1 ) === elem.id;\n            },\n\n            \"root\": function( elem ) {\n                return elem === docElem;\n            },\n\n            \"focus\": function( elem ) {\n                return elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex);\n            },\n\n            \"enabled\": function( elem ) {\n                return elem.disabled === false;\n            },\n\n            \"disabled\": function( elem ) {\n                return elem.disabled === true;\n            },\n\n            \"checked\": function( elem ) {\n                var nodeName = elem.nodeName.toLowerCase();\n                return (nodeName === \"input\" && !!elem.checked) || (nodeName === \"option\" && !!elem.selected);\n            },\n\n            \"selected\": function( elem ) {\n                if ( elem.parentNode ) {\n                    elem.parentNode.selectedIndex;\n                }\n\n                return elem.selected === true;\n            },\n\n            \"empty\": function( elem ) {\n                for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {\n                    if ( elem.nodeType < 6 ) {\n                        return false;\n                    }\n                }\n                return true;\n            },\n\n            \"parent\": function( elem ) {\n                return !Expr.pseudos[\"empty\"]( elem );\n            },\n\n            \"header\": function( elem ) {\n                return rheader.test( elem.nodeName );\n            },\n\n            \"input\": function( elem ) {\n                return rinputs.test( elem.nodeName );\n            },\n\n            \"button\": function( elem ) {\n                var name = elem.nodeName.toLowerCase();\n                return name === \"input\" && elem.type === \"button\" || name === \"button\";\n            },\n\n            \"text\": function( elem ) {\n                var attr;\n                return elem.nodeName.toLowerCase() === \"input\" &&\n                    elem.type === \"text\" &&\n\n                    ( (attr = elem.getAttribute(\"type\")) == null || attr.toLowerCase() === \"text\" );\n            },\n\n            \"first\": createPositionalPseudo(function() {\n                return [ 0 ];\n            }),\n\n            \"last\": createPositionalPseudo(function( matchIndexes, length ) {\n                return [ length - 1 ];\n            }),\n\n            \"eq\": createPositionalPseudo(function( matchIndexes, length, argument ) {\n                return [ argument < 0 ? argument + length : argument ];\n            }),\n\n            \"even\": createPositionalPseudo(function( matchIndexes, length ) {\n                var i = 0;\n                for ( ; i < length; i += 2 ) {\n                    matchIndexes.push( i );\n                }\n                return matchIndexes;\n            }),\n\n            \"odd\": createPositionalPseudo(function( matchIndexes, length ) {\n                var i = 1;\n                for ( ; i < length; i += 2 ) {\n                    matchIndexes.push( i );\n                }\n                return matchIndexes;\n            }),\n\n            \"lt\": createPositionalPseudo(function( matchIndexes, length, argument ) {\n                var i = argument < 0 ? argument + length : argument;\n                for ( ; --i >= 0; ) {\n                    matchIndexes.push( i );\n                }\n                return matchIndexes;\n            }),\n\n            \"gt\": createPositionalPseudo(function( matchIndexes, length, argument ) {\n                var i = argument < 0 ? argument + length : argument;\n                for ( ; ++i < length; ) {\n                    matchIndexes.push( i );\n                }\n                return matchIndexes;\n            })\n        }\n    };\n\n    Expr.pseudos[\"nth\"] = Expr.pseudos[\"eq\"];\n\n    for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) {\n        Expr.pseudos[ i ] = createInputPseudo( i );\n    }\n    for ( i in { submit: true, reset: true } ) {\n        Expr.pseudos[ i ] = createButtonPseudo( i );\n    }\n\n    function setFilters() {}\n    setFilters.prototype = Expr.filters = Expr.pseudos;\n    Expr.setFilters = new setFilters();\n\n    function tokenize( selector, parseOnly ) {\n        var matched, match, tokens, type,\n            soFar, groups, preFilters,\n            cached = tokenCache[ selector + \" \" ];\n\n        if ( cached ) {\n            return parseOnly ? 0 : cached.slice( 0 );\n        }\n\n        soFar = selector;\n        groups = [];\n        preFilters = Expr.preFilter;\n\n        while ( soFar ) {\n\n            if ( !matched || (match = rcomma.exec( soFar )) ) {\n                if ( match ) {\n                    soFar = soFar.slice( match[0].length ) || soFar;\n                }\n                groups.push( (tokens = []) );\n            }\n\n            matched = false;\n\n            if ( (match = rcombinators.exec( soFar )) ) {\n                matched = match.shift();\n                tokens.push({\n                    value: matched,\n                    type: match[0].replace( rtrim, \" \" )\n                });\n                soFar = soFar.slice( matched.length );\n            }\n\n            for ( type in Expr.filter ) {\n                if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] ||\n                    (match = preFilters[ type ]( match ))) ) {\n                    matched = match.shift();\n                    tokens.push({\n                        value: matched,\n                        type: type,\n                        matches: match\n                    });\n                    soFar = soFar.slice( matched.length );\n                }\n            }\n\n            if ( !matched ) {\n                break;\n            }\n        }\n\n        return parseOnly ?\n            soFar.length :\n            soFar ?\n                Sizzle.error( selector ) :\n                tokenCache( selector, groups ).slice( 0 );\n    }\n\n    function toSelector( tokens ) {\n        var i = 0,\n            len = tokens.length,\n            selector = \"\";\n        for ( ; i < len; i++ ) {\n            selector += tokens[i].value;\n        }\n        return selector;\n    }\n\n    function addCombinator( matcher, combinator, base ) {\n        var dir = combinator.dir,\n            checkNonElements = base && dir === \"parentNode\",\n            doneName = done++;\n\n        return combinator.first ?\n            function( elem, context, xml ) {\n                while ( (elem = elem[ dir ]) ) {\n                    if ( elem.nodeType === 1 || checkNonElements ) {\n                        return matcher( elem, context, xml );\n                    }\n                }\n            } :\n\n            function( elem, context, xml ) {\n                var oldCache, outerCache,\n                    newCache = [ dirruns, doneName ];\n\n                if ( xml ) {\n                    while ( (elem = elem[ dir ]) ) {\n                        if ( elem.nodeType === 1 || checkNonElements ) {\n                            if ( matcher( elem, context, xml ) ) {\n                                return true;\n                            }\n                        }\n                    }\n                } else {\n                    while ( (elem = elem[ dir ]) ) {\n                        if ( elem.nodeType === 1 || checkNonElements ) {\n                            outerCache = elem[ expando ] || (elem[ expando ] = {});\n                            if ( (oldCache = outerCache[ dir ]) &&\n                                oldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) {\n\n                                return (newCache[ 2 ] = oldCache[ 2 ]);\n                            } else {\n                                outerCache[ dir ] = newCache;\n\n                                if ( (newCache[ 2 ] = matcher( elem, context, xml )) ) {\n                                    return true;\n                                }\n                            }\n                        }\n                    }\n                }\n            };\n    }\n\n    function elementMatcher( matchers ) {\n        return matchers.length > 1 ?\n            function( elem, context, xml ) {\n                var i = matchers.length;\n                while ( i-- ) {\n                    if ( !matchers[i]( elem, context, xml ) ) {\n                        return false;\n                    }\n                }\n                return true;\n            } :\n            matchers[0];\n    }\n\n    function multipleContexts( selector, contexts, results ) {\n        var i = 0,\n            len = contexts.length;\n        for ( ; i < len; i++ ) {\n            Sizzle( selector, contexts[i], results );\n        }\n        return results;\n    }\n\n    function condense( unmatched, map, filter, context, xml ) {\n        var elem,\n            newUnmatched = [],\n            i = 0,\n            len = unmatched.length,\n            mapped = map != null;\n\n        for ( ; i < len; i++ ) {\n            if ( (elem = unmatched[i]) ) {\n                if ( !filter || filter( elem, context, xml ) ) {\n                    newUnmatched.push( elem );\n                    if ( mapped ) {\n                        map.push( i );\n                    }\n                }\n            }\n        }\n\n        return newUnmatched;\n    }\n\n    function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) {\n        if ( postFilter && !postFilter[ expando ] ) {\n            postFilter = setMatcher( postFilter );\n        }\n        if ( postFinder && !postFinder[ expando ] ) {\n            postFinder = setMatcher( postFinder, postSelector );\n        }\n        return markFunction(function( seed, results, context, xml ) {\n            var temp, i, elem,\n                preMap = [],\n                postMap = [],\n                preexisting = results.length,\n\n                elems = seed || multipleContexts( selector || \"*\", context.nodeType ? [ context ] : context, [] ),\n\n                matcherIn = preFilter && ( seed || !selector ) ?\n                    condense( elems, preMap, preFilter, context, xml ) :\n                    elems,\n\n                matcherOut = matcher ?\n                    postFinder || ( seed ? preFilter : preexisting || postFilter ) ?\n\n                        [] :\n\n                        results :\n                    matcherIn;\n\n            if ( matcher ) {\n                matcher( matcherIn, matcherOut, context, xml );\n            }\n\n            if ( postFilter ) {\n                temp = condense( matcherOut, postMap );\n                postFilter( temp, [], context, xml );\n\n                i = temp.length;\n                while ( i-- ) {\n                    if ( (elem = temp[i]) ) {\n                        matcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem);\n                    }\n                }\n            }\n\n            if ( seed ) {\n                if ( postFinder || preFilter ) {\n                    if ( postFinder ) {\n                        temp = [];\n                        i = matcherOut.length;\n                        while ( i-- ) {\n                            if ( (elem = matcherOut[i]) ) {\n                                temp.push( (matcherIn[i] = elem) );\n                            }\n                        }\n                        postFinder( null, (matcherOut = []), temp, xml );\n                    }\n\n                    i = matcherOut.length;\n                    while ( i-- ) {\n                        if ( (elem = matcherOut[i]) &&\n                            (temp = postFinder ? indexOf.call( seed, elem ) : preMap[i]) > -1 ) {\n\n                            seed[temp] = !(results[temp] = elem);\n                        }\n                    }\n                }\n\n            } else {\n                matcherOut = condense(\n                    matcherOut === results ?\n                        matcherOut.splice( preexisting, matcherOut.length ) :\n                        matcherOut\n                );\n                if ( postFinder ) {\n                    postFinder( null, results, matcherOut, xml );\n                } else {\n                    push.apply( results, matcherOut );\n                }\n            }\n        });\n    }\n\n    function matcherFromTokens( tokens ) {\n        var checkContext, matcher, j,\n            len = tokens.length,\n            leadingRelative = Expr.relative[ tokens[0].type ],\n            implicitRelative = leadingRelative || Expr.relative[\" \"],\n            i = leadingRelative ? 1 : 0,\n\n            matchContext = addCombinator( function( elem ) {\n                return elem === checkContext;\n            }, implicitRelative, true ),\n            matchAnyContext = addCombinator( function( elem ) {\n                return indexOf.call( checkContext, elem ) > -1;\n            }, implicitRelative, true ),\n            matchers = [ function( elem, context, xml ) {\n                return ( !leadingRelative && ( xml || context !== outermostContext ) ) || (\n                        (checkContext = context).nodeType ?\n                            matchContext( elem, context, xml ) :\n                            matchAnyContext( elem, context, xml ) );\n            } ];\n\n        for ( ; i < len; i++ ) {\n            if ( (matcher = Expr.relative[ tokens[i].type ]) ) {\n                matchers = [ addCombinator(elementMatcher( matchers ), matcher) ];\n            } else {\n                matcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches );\n\n                if ( matcher[ expando ] ) {\n                    j = ++i;\n                    for ( ; j < len; j++ ) {\n                        if ( Expr.relative[ tokens[j].type ] ) {\n                            break;\n                        }\n                    }\n                    return setMatcher(\n                        i > 1 && elementMatcher( matchers ),\n                        i > 1 && toSelector(\n                            tokens.slice( 0, i - 1 ).concat({ value: tokens[ i - 2 ].type === \" \" ? \"*\" : \"\" })\n                        ).replace( rtrim, \"$1\" ),\n                        matcher,\n                        i < j && matcherFromTokens( tokens.slice( i, j ) ),\n                        j < len && matcherFromTokens( (tokens = tokens.slice( j )) ),\n                        j < len && toSelector( tokens )\n                    );\n                }\n                matchers.push( matcher );\n            }\n        }\n\n        return elementMatcher( matchers );\n    }\n\n    function matcherFromGroupMatchers( elementMatchers, setMatchers ) {\n        var bySet = setMatchers.length > 0,\n            byElement = elementMatchers.length > 0,\n            superMatcher = function( seed, context, xml, results, outermost ) {\n                var elem, j, matcher,\n                    matchedCount = 0,\n                    i = \"0\",\n                    unmatched = seed && [],\n                    setMatched = [],\n                    contextBackup = outermostContext,\n                    elems = seed || byElement && Expr.find[\"TAG\"]( \"*\", outermost ),\n                    dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1),\n                    len = elems.length;\n\n                if ( outermost ) {\n                    outermostContext = context !== document && context;\n                }\n\n                for ( ; i !== len && (elem = elems[i]) != null; i++ ) {\n                    if ( byElement && elem ) {\n                        j = 0;\n                        while ( (matcher = elementMatchers[j++]) ) {\n                            if ( matcher( elem, context, xml ) ) {\n                                results.push( elem );\n                                break;\n                            }\n                        }\n                        if ( outermost ) {\n                            dirruns = dirrunsUnique;\n                        }\n                    }\n\n                    if ( bySet ) {\n                        if ( (elem = !matcher && elem) ) {\n                            matchedCount--;\n                        }\n\n                        if ( seed ) {\n                            unmatched.push( elem );\n                        }\n                    }\n                }\n\n                matchedCount += i;\n                if ( bySet && i !== matchedCount ) {\n                    j = 0;\n                    while ( (matcher = setMatchers[j++]) ) {\n                        matcher( unmatched, setMatched, context, xml );\n                    }\n\n                    if ( seed ) {\n                        if ( matchedCount > 0 ) {\n                            while ( i-- ) {\n                                if ( !(unmatched[i] || setMatched[i]) ) {\n                                    setMatched[i] = pop.call( results );\n                                }\n                            }\n                        }\n\n                        setMatched = condense( setMatched );\n                    }\n\n                    push.apply( results, setMatched );\n\n                    if ( outermost && !seed && setMatched.length > 0 &&\n                        ( matchedCount + setMatchers.length ) > 1 ) {\n\n                        Sizzle.uniqueSort( results );\n                    }\n                }\n\n                if ( outermost ) {\n                    dirruns = dirrunsUnique;\n                    outermostContext = contextBackup;\n                }\n\n                return unmatched;\n            };\n\n        return bySet ?\n            markFunction( superMatcher ) :\n            superMatcher;\n    }\n\n    compile = Sizzle.compile = function( selector, match /* Internal Use Only */ ) {\n        var i,\n            setMatchers = [],\n            elementMatchers = [],\n            cached = compilerCache[ selector + \" \" ];\n\n        if ( !cached ) {\n            if ( !match ) {\n                match = tokenize( selector );\n            }\n            i = match.length;\n            while ( i-- ) {\n                cached = matcherFromTokens( match[i] );\n                if ( cached[ expando ] ) {\n                    setMatchers.push( cached );\n                } else {\n                    elementMatchers.push( cached );\n                }\n            }\n\n            cached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) );\n\n            cached.selector = selector;\n        }\n        return 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     */\n    select = Sizzle.select = function( selector, context, results, seed ) {\n        var i, tokens, token, type, find,\n            compiled = typeof selector === \"function\" && selector,\n            match = !seed && tokenize( (selector = compiled.selector || selector) );\n\n        results = results || [];\n\n        if ( match.length === 1 ) {\n\n            tokens = match[0] = match[0].slice( 0 );\n            if ( tokens.length > 2 && (token = tokens[0]).type === \"ID\" &&\n                support.getById && context.nodeType === 9 && documentIsHTML &&\n                Expr.relative[ tokens[1].type ] ) {\n\n                context = ( Expr.find[\"ID\"]( token.matches[0].replace(runescape, funescape), context ) || [] )[0];\n                if ( !context ) {\n                    return results;\n\n                } else if ( compiled ) {\n                    context = context.parentNode;\n                }\n\n                selector = selector.slice( tokens.shift().value.length );\n            }\n\n            i = matchExpr[\"needsContext\"].test( selector ) ? 0 : tokens.length;\n            while ( i-- ) {\n                token = tokens[i];\n\n                if ( Expr.relative[ (type = token.type) ] ) {\n                    break;\n                }\n                if ( (find = Expr.find[ type ]) ) {\n                    if ( (seed = find(\n                            token.matches[0].replace( runescape, funescape ),\n                            rsibling.test( tokens[0].type ) && testContext( context.parentNode ) || context\n                        )) ) {\n\n                        tokens.splice( i, 1 );\n                        selector = seed.length && toSelector( tokens );\n                        if ( !selector ) {\n                            push.apply( results, seed );\n                            return results;\n                        }\n\n                        break;\n                    }\n                }\n            }\n        }\n\n        ( compiled || compile( selector, match ) )(\n            seed,\n            context,\n            !documentIsHTML,\n            results,\n            rsibling.test( selector ) && testContext( context.parentNode ) || context\n        );\n        return results;\n    };\n\n\n    support.sortStable = expando.split(\"\").sort( sortOrder ).join(\"\") === expando;\n\n    support.detectDuplicates = !!hasDuplicate;\n\n    setDocument();\n\n    support.sortDetached = assert(function( div1 ) {\n        return div1.compareDocumentPosition( document.createElement(\"div\") ) & 1;\n    });\n\n    if ( !assert(function( div ) {\n            div.innerHTML = \"<a href='#'></a>\";\n            return div.firstChild.getAttribute(\"href\") === \"#\" ;\n        }) ) {\n        addHandle( \"type|href|height|width\", function( elem, name, isXML ) {\n            if ( !isXML ) {\n                return elem.getAttribute( name, name.toLowerCase() === \"type\" ? 1 : 2 );\n            }\n        });\n    }\n\n    if ( !support.attributes || !assert(function( div ) {\n            div.innerHTML = \"<input/>\";\n            div.firstChild.setAttribute( \"value\", \"\" );\n            return div.firstChild.getAttribute( \"value\" ) === \"\";\n        }) ) {\n        addHandle( \"value\", function( elem, name, isXML ) {\n            if ( !isXML && elem.nodeName.toLowerCase() === \"input\" ) {\n                return elem.defaultValue;\n            }\n        });\n    }\n\n    if ( !assert(function( div ) {\n            return div.getAttribute(\"disabled\") == null;\n        }) ) {\n        addHandle( booleans, function( elem, name, isXML ) {\n            var val;\n            if ( !isXML ) {\n                return elem[ name ] === true ? name.toLowerCase() :\n                    (val = elem.getAttributeNode( name )) && val.specified ?\n                        val.value :\n                        null;\n            }\n        });\n    }\n\n    if ( typeof define === \"function\" && define.amd ) {\n        define(function() { return Sizzle; });\n    } else if ( typeof module !== \"undefined\" && module.exports ) {\n        module.exports = Sizzle;\n    } else {\n        window.Sizzle = Sizzle;\n    }\n\n})( window );\n\n;(function() {\n    if (typeof Sizzle !== 'undefined') {\n        return;\n    }\n\n    if (typeof define !== 'undefined' && define.amd) {\n        window.Sizzle = Prototype._actual_sizzle;\n        window.define = Prototype._original_define;\n        delete Prototype._actual_sizzle;\n        delete Prototype._original_define;\n    } else if (typeof module !== 'undefined' && module.exports) {\n        window.Sizzle = module.exports;\n        module.exports = {};\n    }\n})();\n\n;(function(engine) {\n    var extendElements = Prototype.Selector.extendElements;\n\n    function select(selector, scope) {\n        return extendElements(engine(selector, scope || document));\n    }\n\n    function match(element, selector) {\n        return engine.matches(selector, [element]).length == 1;\n    }\n\n    Prototype.Selector.engine = engine;\n    Prototype.Selector.select = select;\n    Prototype.Selector.match = match;\n})(Sizzle);\n\nwindow.Sizzle = Prototype._original_property;\ndelete Prototype._original_property;\n\nvar Form = {\n    reset: function(form) {\n        form = $(form);\n        form.reset();\n        return form;\n    },\n\n    serializeElements: function(elements, options) {\n        if (typeof options != 'object') options = { hash: !!options };\n        else if (Object.isUndefined(options.hash)) options.hash = true;\n        var key, value, submitted = false, submit = options.submit, accumulator, initial;\n\n        if (options.hash) {\n            initial = {};\n            accumulator = function(result, key, value) {\n                if (key in result) {\n                    if (!Object.isArray(result[key])) result[key] = [result[key]];\n                    result[key] = result[key].concat(value);\n                } else result[key] = value;\n                return result;\n            };\n        } else {\n            initial = '';\n            accumulator = function(result, key, values) {\n                if (!Object.isArray(values)) {values = [values];}\n                if (!values.length) {return result;}\n                var encodedKey = encodeURIComponent(key).gsub(/%20/, '+');\n                return result + (result ? \"&\" : \"\") + values.map(function (value) {\n                        value = value.gsub(/(\\r)?\\n/, '\\r\\n');\n                        value = encodeURIComponent(value);\n                        value = value.gsub(/%20/, '+');\n                        return encodedKey + \"=\" + value;\n                    }).join(\"&\");\n            };\n        }\n\n        return elements.inject(initial, function(result, element) {\n            if (!element.disabled && element.name) {\n                key = element.name; value = $(element).getValue();\n                if (value != null && element.type != 'file' && (element.type != 'submit' || (!submitted &&\n                    submit !== false && (!submit || key == submit) && (submitted = true)))) {\n                    result = accumulator(result, key, value);\n                }\n            }\n            return result;\n        });\n    }\n};\n\nForm.Methods = {\n    serialize: function(form, options) {\n        return Form.serializeElements(Form.getElements(form), options);\n    },\n\n\n    getElements: function(form) {\n        var elements = $(form).getElementsByTagName('*');\n        var element, results = [], serializers = Form.Element.Serializers;\n\n        for (var i = 0; element = elements[i]; i++) {\n            if (serializers[element.tagName.toLowerCase()])\n                results.push(Element.extend(element));\n        }\n        return results;\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        var elements = $(form).getElements().findAll(function(element) {\n            return 'hidden' != element.type && !element.disabled;\n        });\n        var firstByIndex = elements.findAll(function(element) {\n            return element.hasAttribute('tabIndex') && element.tabIndex >= 0;\n        }).sortBy(function(element) { return element.tabIndex }).first();\n\n        return firstByIndex ? firstByIndex : elements.find(function(element) {\n                return /^(?:input|select|textarea)$/i.test(element.tagName);\n            });\n    },\n\n    focusFirstElement: function(form) {\n        form = $(form);\n        var element = form.findFirstElement();\n        if (element) element.activate();\n        return form;\n    },\n\n    request: function(form, options) {\n        form = $(form), options = Object.clone(options || { });\n\n        var params = options.parameters, action = form.readAttribute('action') || '';\n        if (action.blank()) action = window.location.href;\n        options.parameters = form.serialize(true);\n\n        if (params) {\n            if (Object.isString(params)) 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(action, options);\n    }\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\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 Object.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    setValue: function(element, value) {\n        element = $(element);\n        var method = element.tagName.toLowerCase();\n        Form.Element.Serializers[method](element, value);\n        return 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)$/i.test(element.type))))\n                element.select();\n        } catch (e) { }\n        return element;\n    },\n\n    disable: function(element) {\n        element = $(element);\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;\n\nvar $F = Form.Element.Methods.getValue;\n\n/*--------------------------------------------------------------------------*/\n\nForm.Element.Serializers = (function() {\n    function input(element, value) {\n        switch (element.type.toLowerCase()) {\n            case 'checkbox':\n            case 'radio':\n                return inputSelector(element, value);\n            default:\n                return valueSelector(element, value);\n        }\n    }\n\n    function inputSelector(element, value) {\n        if (Object.isUndefined(value))\n            return element.checked ? element.value : null;\n        else element.checked = !!value;\n    }\n\n    function valueSelector(element, value) {\n        if (Object.isUndefined(value)) return element.value;\n        else element.value = value;\n    }\n\n    function select(element, value) {\n        if (Object.isUndefined(value))\n            return (element.type === 'select-one' ? selectOne : selectMany)(element);\n\n        var opt, currentValue, single = !Object.isArray(value);\n        for (var i = 0, length = element.length; i < length; i++) {\n            opt = element.options[i];\n            currentValue = this.optionValue(opt);\n            if (single) {\n                if (currentValue == value) {\n                    opt.selected = true;\n                    return;\n                }\n            }\n            else opt.selected = value.include(currentValue);\n        }\n    }\n\n    function selectOne(element) {\n        var index = element.selectedIndex;\n        return index >= 0 ? optionValue(element.options[index]) : null;\n    }\n\n    function selectMany(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(optionValue(opt));\n        }\n        return values;\n    }\n\n    function optionValue(opt) {\n        return Element.hasAttribute(opt, 'value') ? opt.value : opt.text;\n    }\n\n    return {\n        input:         input,\n        inputSelector: inputSelector,\n        textarea:      valueSelector,\n        select:        select,\n        selectOne:     selectOne,\n        selectMany:    selectMany,\n        optionValue:   optionValue,\n        button:        valueSelector\n    };\n})();\n\n/*--------------------------------------------------------------------------*/\n\n\nAbstract.TimedObserver = Class.create(PeriodicalExecuter, {\n    initialize: function($super, element, frequency, callback) {\n        $super(callback, frequency);\n        this.element   = $(element);\n        this.lastValue = this.getValue();\n    },\n\n    execute: function() {\n        var value = this.getValue();\n        if (Object.isString(this.lastValue) && Object.isString(value) ?\n                this.lastValue != value : String(this.lastValue) != String(value)) {\n            this.callback(this.element, value);\n            this.lastValue = value;\n        }\n    }\n});\n\nForm.Element.Observer = Class.create(Abstract.TimedObserver, {\n    getValue: function() {\n        return Form.Element.getValue(this.element);\n    }\n});\n\nForm.Observer = Class.create(Abstract.TimedObserver, {\n    getValue: function() {\n        return Form.serialize(this.element);\n    }\n});\n\n/*--------------------------------------------------------------------------*/\n\nAbstract.EventObserver = Class.create({\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, 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(Abstract.EventObserver, {\n    getValue: function() {\n        return Form.Element.getValue(this.element);\n    }\n});\n\nForm.EventObserver = Class.create(Abstract.EventObserver, {\n    getValue: function() {\n        return Form.serialize(this.element);\n    }\n});\n(function(GLOBAL) {\n    var DIV = document.createElement('div');\n    var docEl = document.documentElement;\n    var MOUSEENTER_MOUSELEAVE_EVENTS_SUPPORTED = 'onmouseenter' in docEl\n        && 'onmouseleave' in docEl;\n\n    var 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        KEY_INSERT:   45\n    };\n\n\n    var isIELegacyEvent = function(event) { return false; };\n\n    if (window.attachEvent) {\n        if (window.addEventListener) {\n            isIELegacyEvent = function(event) {\n                return !(event instanceof window.Event);\n            };\n        } else {\n            isIELegacyEvent = function(event) { return true; };\n        }\n    }\n\n    var _isButton;\n\n    function _isButtonForDOMEvents(event, code) {\n        return event.which ? (event.which === code + 1) : (event.button === code);\n    }\n\n    var legacyButtonMap = { 0: 1, 1: 4, 2: 2 };\n    function _isButtonForLegacyEvents(event, code) {\n        return event.button === legacyButtonMap[code];\n    }\n\n    function _isButtonForWebKit(event, code) {\n        switch (code) {\n            case 0: return event.which == 1 && !event.metaKey;\n            case 1: return event.which == 2 || (event.which == 1 && event.metaKey);\n            case 2: return event.which == 3;\n            default: return false;\n        }\n    }\n\n    if (window.attachEvent) {\n        if (!window.addEventListener) {\n            _isButton = _isButtonForLegacyEvents;\n        } else {\n            _isButton = function(event, code) {\n                return isIELegacyEvent(event) ? _isButtonForLegacyEvents(event, code) :\n                    _isButtonForDOMEvents(event, code);\n            }\n        }\n    } else if (Prototype.Browser.WebKit) {\n        _isButton = _isButtonForWebKit;\n    } else {\n        _isButton = _isButtonForDOMEvents;\n    }\n\n    function isLeftClick(event)   { return _isButton(event, 0) }\n\n    function isMiddleClick(event) { return _isButton(event, 1) }\n\n    function isRightClick(event)  { return _isButton(event, 2) }\n\n    function element(event) {\n        return Element.extend(_element(event));\n    }\n\n    function _element(event) {\n        event = Event.extend(event);\n\n        var node = event.target, type = event.type,\n            currentTarget = event.currentTarget;\n\n        if (currentTarget && currentTarget.tagName) {\n            if (type === 'load' || type === 'error' ||\n                (type === 'click' && currentTarget.tagName.toLowerCase() === 'input'\n                && currentTarget.type === 'radio'))\n                node = currentTarget;\n        }\n\n        return node.nodeType == Node.TEXT_NODE ? node.parentNode : node;\n    }\n\n    function findElement(event, expression) {\n        var element = _element(event), selector = Prototype.Selector;\n        if (!expression) return Element.extend(element);\n        while (element) {\n            if (Object.isElement(element) && selector.match(element, expression))\n                return Element.extend(element);\n            element = element.parentNode;\n        }\n    }\n\n    function pointer(event) {\n        return { x: pointerX(event), y: pointerY(event) };\n    }\n\n    function pointerX(event) {\n        var docElement = document.documentElement,\n            body = document.body || { scrollLeft: 0 };\n\n        return event.pageX || (event.clientX +\n            (docElement.scrollLeft || body.scrollLeft) -\n            (docElement.clientLeft || 0));\n    }\n\n    function pointerY(event) {\n        var docElement = document.documentElement,\n            body = document.body || { scrollTop: 0 };\n\n        return  event.pageY || (event.clientY +\n            (docElement.scrollTop || body.scrollTop) -\n            (docElement.clientTop || 0));\n    }\n\n\n    function stop(event) {\n        Event.extend(event);\n        event.preventDefault();\n        event.stopPropagation();\n\n        event.stopped = true;\n    }\n\n\n    Event.Methods = {\n        isLeftClick:   isLeftClick,\n        isMiddleClick: isMiddleClick,\n        isRightClick:  isRightClick,\n\n        element:     element,\n        findElement: findElement,\n\n        pointer:  pointer,\n        pointerX: pointerX,\n        pointerY: pointerY,\n\n        stop: stop\n    };\n\n    var methods = Object.keys(Event.Methods).inject({ }, function(m, name) {\n        m[name] = Event.Methods[name].methodize();\n        return m;\n    });\n\n    if (window.attachEvent) {\n        function _relatedTarget(event) {\n            var element;\n            switch (event.type) {\n                case 'mouseover':\n                case 'mouseenter':\n                    element = event.fromElement;\n                    break;\n                case 'mouseout':\n                case 'mouseleave':\n                    element = event.toElement;\n                    break;\n                default:\n                    return null;\n            }\n            return Element.extend(element);\n        }\n\n        var additionalMethods = {\n            stopPropagation: function() { this.cancelBubble = true },\n            preventDefault:  function() { this.returnValue = false },\n            inspect: function() { return '[object Event]' }\n        };\n\n        Event.extend = function(event, element) {\n            if (!event) return false;\n\n            if (!isIELegacyEvent(event)) return event;\n\n            if (event._extendedByPrototype) return event;\n            event._extendedByPrototype = Prototype.emptyFunction;\n\n            var pointer = Event.pointer(event);\n\n            Object.extend(event, {\n                target: event.srcElement || element,\n                relatedTarget: _relatedTarget(event),\n                pageX:  pointer.x,\n                pageY:  pointer.y\n            });\n\n            Object.extend(event, methods);\n            Object.extend(event, additionalMethods);\n\n            return event;\n        };\n    } else {\n        Event.extend = Prototype.K;\n    }\n\n    if (window.addEventListener) {\n        Event.prototype = window.Event.prototype || document.createEvent('HTMLEvents').__proto__;\n        Object.extend(Event.prototype, methods);\n    }\n\n    var EVENT_TRANSLATIONS = {\n        mouseenter: 'mouseover',\n        mouseleave: 'mouseout'\n    };\n\n    function getDOMEventName(eventName) {\n        return EVENT_TRANSLATIONS[eventName] || eventName;\n    }\n\n    if (MOUSEENTER_MOUSELEAVE_EVENTS_SUPPORTED)\n        getDOMEventName = Prototype.K;\n\n    function getUniqueElementID(element) {\n        if (element === window) return 0;\n\n        if (typeof element._prototypeUID === 'undefined')\n            element._prototypeUID = Element.Storage.UID++;\n        return element._prototypeUID;\n    }\n\n    function getUniqueElementID_IE(element) {\n        if (element === window) return 0;\n        if (element == document) return 1;\n        return element.uniqueID;\n    }\n\n    if ('uniqueID' in DIV)\n        getUniqueElementID = getUniqueElementID_IE;\n\n    function isCustomEvent(eventName) {\n        return eventName.include(':');\n    }\n\n    Event._isCustomEvent = isCustomEvent;\n\n    function getOrCreateRegistryFor(element, uid) {\n        var CACHE = GLOBAL.Event.cache;\n        if (Object.isUndefined(uid))\n            uid = getUniqueElementID(element);\n        if (!CACHE[uid]) CACHE[uid] = { element: element };\n        return CACHE[uid];\n    }\n\n    function destroyRegistryForElement(element, uid) {\n        if (Object.isUndefined(uid))\n            uid = getUniqueElementID(element);\n        delete GLOBAL.Event.cache[uid];\n    }\n\n\n    function register(element, eventName, handler) {\n        var registry = getOrCreateRegistryFor(element);\n        if (!registry[eventName]) registry[eventName] = [];\n        var entries = registry[eventName];\n\n        var i = entries.length;\n        while (i--)\n            if (entries[i].handler === handler) return null;\n\n        var uid = getUniqueElementID(element);\n        var responder = GLOBAL.Event._createResponder(uid, eventName, handler);\n        var entry = {\n            responder: responder,\n            handler:   handler\n        };\n\n        entries.push(entry);\n        return entry;\n    }\n\n    function unregister(element, eventName, handler) {\n        var registry = getOrCreateRegistryFor(element);\n        var entries = registry[eventName] || [];\n\n        var i = entries.length, entry;\n        while (i--) {\n            if (entries[i].handler === handler) {\n                entry = entries[i];\n                break;\n            }\n        }\n\n        if (entry) {\n            var index = entries.indexOf(entry);\n            entries.splice(index, 1);\n        }\n\n        if (entries.length === 0) {\n            delete registry[eventName];\n            if (Object.keys(registry).length === 1 && ('element' in registry))\n                destroyRegistryForElement(element);\n        }\n\n        return entry;\n    }\n\n\n    function observe(element, eventName, handler) {\n        element = $(element);\n        var entry = register(element, eventName, handler);\n\n        if (entry === null) return element;\n\n        var responder = entry.responder;\n        if (isCustomEvent(eventName))\n            observeCustomEvent(element, eventName, responder);\n        else\n            observeStandardEvent(element, eventName, responder);\n\n        return element;\n    }\n\n    function observeStandardEvent(element, eventName, responder) {\n        var actualEventName = getDOMEventName(eventName);\n        if (element.addEventListener) {\n            element.addEventListener(actualEventName, responder, false);\n        } else {\n            element.attachEvent('on' + actualEventName, responder);\n        }\n    }\n\n    function observeCustomEvent(element, eventName, responder) {\n        if (element.addEventListener) {\n            element.addEventListener('dataavailable', responder, false);\n        } else {\n            element.attachEvent('ondataavailable', responder);\n            element.attachEvent('onlosecapture',   responder);\n        }\n    }\n\n    function stopObserving(element, eventName, handler) {\n        element = $(element);\n        var handlerGiven = !Object.isUndefined(handler),\n            eventNameGiven = !Object.isUndefined(eventName);\n\n        if (!eventNameGiven && !handlerGiven) {\n            stopObservingElement(element);\n            return element;\n        }\n\n        if (!handlerGiven) {\n            stopObservingEventName(element, eventName);\n            return element;\n        }\n\n        var entry = unregister(element, eventName, handler);\n\n        if (!entry) return element;\n        removeEvent(element, eventName, entry.responder);\n        return element;\n    }\n\n    function stopObservingStandardEvent(element, eventName, responder) {\n        var actualEventName = getDOMEventName(eventName);\n        if (element.removeEventListener) {\n            element.removeEventListener(actualEventName, responder, false);\n        } else {\n            element.detachEvent('on' + actualEventName, responder);\n        }\n    }\n\n    function stopObservingCustomEvent(element, eventName, responder) {\n        if (element.removeEventListener) {\n            element.removeEventListener('dataavailable', responder, false);\n        } else {\n            element.detachEvent('ondataavailable', responder);\n            element.detachEvent('onlosecapture',   responder);\n        }\n    }\n\n\n\n    function stopObservingElement(element) {\n        var uid = getUniqueElementID(element), registry = GLOBAL.Event.cache[uid];\n        if (!registry) return;\n\n        destroyRegistryForElement(element, uid);\n\n        var entries, i;\n        for (var eventName in registry) {\n            if (eventName === 'element') continue;\n\n            entries = registry[eventName];\n            i = entries.length;\n            while (i--)\n                removeEvent(element, eventName, entries[i].responder);\n        }\n    }\n\n    function stopObservingEventName(element, eventName) {\n        var registry = getOrCreateRegistryFor(element);\n        var entries = registry[eventName];\n        if (entries) {\n            delete registry[eventName];\n        }\n\n        entries = entries || [];\n\n        var i = entries.length;\n        while (i--)\n            removeEvent(element, eventName, entries[i].responder);\n\n        for (var name in registry) {\n            if (name === 'element') continue;\n            return; // There is another registered event\n        }\n\n        destroyRegistryForElement(element);\n    }\n\n\n    function removeEvent(element, eventName, handler) {\n        if (isCustomEvent(eventName))\n            stopObservingCustomEvent(element, eventName, handler);\n        else\n            stopObservingStandardEvent(element, eventName, handler);\n    }\n\n\n\n    function getFireTarget(element) {\n        if (element !== document) return element;\n        if (document.createEvent && !element.dispatchEvent)\n            return document.documentElement;\n        return element;\n    }\n\n    function fire(element, eventName, memo, bubble) {\n        element = getFireTarget($(element));\n        if (Object.isUndefined(bubble)) bubble = true;\n        memo = memo || {};\n\n        var event = fireEvent(element, eventName, memo, bubble);\n        return Event.extend(event);\n    }\n\n    function fireEvent_DOM(element, eventName, memo, bubble) {\n        var event = document.createEvent('HTMLEvents');\n        event.initEvent('dataavailable', bubble, true);\n\n        event.eventName = eventName;\n        event.memo = memo;\n\n        element.dispatchEvent(event);\n        return event;\n    }\n\n    function fireEvent_IE(element, eventName, memo, bubble) {\n        var event = document.createEventObject();\n        event.eventType = bubble ? 'ondataavailable' : 'onlosecapture';\n\n        event.eventName = eventName;\n        event.memo = memo;\n\n        element.fireEvent(event.eventType, event);\n        return event;\n    }\n\n    var fireEvent = document.createEvent ? fireEvent_DOM : fireEvent_IE;\n\n\n\n    Event.Handler = Class.create({\n        initialize: function(element, eventName, selector, callback) {\n            this.element   = $(element);\n            this.eventName = eventName;\n            this.selector  = selector;\n            this.callback  = callback;\n            this.handler   = this.handleEvent.bind(this);\n        },\n\n\n        start: function() {\n            Event.observe(this.element, this.eventName, this.handler);\n            return this;\n        },\n\n        stop: function() {\n            Event.stopObserving(this.element, this.eventName, this.handler);\n            return this;\n        },\n\n        handleEvent: function(event) {\n            var element = Event.findElement(event, this.selector);\n            if (element) this.callback.call(this.element, event, element);\n        }\n    });\n\n    function on(element, eventName, selector, callback) {\n        element = $(element);\n        if (Object.isFunction(selector) && Object.isUndefined(callback)) {\n            callback = selector, selector = null;\n        }\n\n        return new Event.Handler(element, eventName, selector, callback).start();\n    }\n\n    Object.extend(Event, Event.Methods);\n\n    Object.extend(Event, {\n        fire:          fire,\n        observe:       observe,\n        stopObserving: stopObserving,\n        on:            on\n    });\n\n    Element.addMethods({\n        fire:          fire,\n\n        observe:       observe,\n\n        stopObserving: stopObserving,\n\n        on:            on\n    });\n\n    Object.extend(document, {\n        fire:          fire.methodize(),\n\n        observe:       observe.methodize(),\n\n        stopObserving: stopObserving.methodize(),\n\n        on:            on.methodize(),\n\n        loaded:        false\n    });\n\n    if (GLOBAL.Event) Object.extend(window.Event, Event);\n    else GLOBAL.Event = Event;\n\n    GLOBAL.Event.cache = {};\n\n    function destroyCache_IE() {\n        GLOBAL.Event.cache = null;\n    }\n\n    if (window.attachEvent)\n        window.attachEvent('onunload', destroyCache_IE);\n\n    DIV = null;\n    docEl = null;\n})(this);\n\n(function(GLOBAL) {\n    /* Code for creating leak-free event responders is based on work by\n     John-David Dalton. */\n\n    var docEl = document.documentElement;\n    var MOUSEENTER_MOUSELEAVE_EVENTS_SUPPORTED = 'onmouseenter' in docEl\n        && 'onmouseleave' in docEl;\n\n    function isSimulatedMouseEnterLeaveEvent(eventName) {\n        return !MOUSEENTER_MOUSELEAVE_EVENTS_SUPPORTED &&\n            (eventName === 'mouseenter' || eventName === 'mouseleave');\n    }\n\n    function createResponder(uid, eventName, handler) {\n        if (Event._isCustomEvent(eventName))\n            return createResponderForCustomEvent(uid, eventName, handler);\n        if (isSimulatedMouseEnterLeaveEvent(eventName))\n            return createMouseEnterLeaveResponder(uid, eventName, handler);\n\n        return function(event) {\n            if (!Event.cache) return;\n\n            var element = Event.cache[uid].element;\n            Event.extend(event, element);\n            handler.call(element, event);\n        };\n    }\n\n    function createResponderForCustomEvent(uid, eventName, handler) {\n        return function(event) {\n            var cache = Event.cache[uid];\n            var element =  cache && cache.element;\n\n            if (Object.isUndefined(event.eventName))\n                return false;\n\n            if (event.eventName !== eventName)\n                return false;\n\n            Event.extend(event, element);\n            handler.call(element, event);\n        };\n    }\n\n    function createMouseEnterLeaveResponder(uid, eventName, handler) {\n        return function(event) {\n            var element = Event.cache[uid].element;\n\n            Event.extend(event, element);\n            var parent = event.relatedTarget;\n\n            while (parent && parent !== element) {\n                try { parent = parent.parentNode; }\n                catch(e) { parent = element; }\n            }\n\n            if (parent === element) return;\n            handler.call(element, event);\n        }\n    }\n\n    GLOBAL.Event._createResponder = createResponder;\n    docEl = null;\n})(this);\n\n(function(GLOBAL) {\n    /* Support for the DOMContentLoaded event is based on work by Dan Webb,\n     Matthias Miller, Dean Edwards, John Resig, and Diego Perini. */\n\n    var TIMER;\n\n    function fireContentLoadedEvent() {\n        if (document.loaded) return;\n        if (TIMER) window.clearTimeout(TIMER);\n        document.loaded = true;\n        document.fire('dom:loaded');\n    }\n\n    function checkReadyState() {\n        if (document.readyState === 'complete') {\n            document.detachEvent('onreadystatechange', checkReadyState);\n            fireContentLoadedEvent();\n        }\n    }\n\n    function pollDoScroll() {\n        try {\n            document.documentElement.doScroll('left');\n        } catch (e) {\n            TIMER = pollDoScroll.defer();\n            return;\n        }\n\n        fireContentLoadedEvent();\n    }\n\n\n    if (document.readyState === 'complete') {\n        fireContentLoadedEvent();\n        return;\n    }\n\n    if (document.addEventListener) {\n        document.addEventListener('DOMContentLoaded', fireContentLoadedEvent, false);\n    } else {\n        document.attachEvent('onreadystatechange', checkReadyState);\n        if (window == top) TIMER = pollDoScroll.defer();\n    }\n\n    Event.observe(window, 'load', fireContentLoadedEvent);\n})(this);\n\n\nElement.addMethods();\n/*------------------------------- DEPRECATED -------------------------------*/\n\nHash.toQueryString = Object.toQueryString;\n\nvar Toggle = { display: Element.toggle };\n\nElement.addMethods({\n    childOf: Element.Methods.descendantOf\n});\n\nvar Insertion = {\n    Before: function(element, content) {\n        return Element.insert(element, {before:content});\n    },\n\n    Top: function(element, content) {\n        return Element.insert(element, {top:content});\n    },\n\n    Bottom: function(element, content) {\n        return Element.insert(element, {bottom:content});\n    },\n\n    After: function(element, content) {\n        return Element.insert(element, {after:content});\n    }\n};\n\nvar $continue = new Error('\"throw $continue\" is deprecated, use \"return\" instead');\n\nvar Position = {\n    includeScrollOffsets: false,\n\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    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 = Element.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 = Element.cumulativeScrollOffset(element);\n\n        this.xcomp = x + offsetcache[0] - this.deltaX;\n        this.ycomp = y + offsetcache[1] - this.deltaY;\n        this.offset = Element.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    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\n    cumulativeOffset: Element.Methods.cumulativeOffset,\n\n    positionedOffset: Element.Methods.positionedOffset,\n\n    absolutize: function(element) {\n        Position.prepare();\n        return Element.absolutize(element);\n    },\n\n    relativize: function(element) {\n        Position.prepare();\n        return Element.relativize(element);\n    },\n\n    realOffset: Element.Methods.cumulativeScrollOffset,\n\n    offsetParent: Element.Methods.getOffsetParent,\n\n    page: Element.Methods.viewportOffset,\n\n    clone: function(source, target, options) {\n        options = options || { };\n        return Element.clonePosition(target, source, options);\n    }\n};\n\n/*--------------------------------------------------------------------------*/\n\nif (!document.getElementsByClassName) document.getElementsByClassName = function(instanceMethods){\n    function iter(name) {\n        return name.blank() ? null : \"[contains(concat(' ', @class, ' '), ' \" + name + \" ')]\";\n    }\n\n    instanceMethods.getElementsByClassName = Prototype.BrowserFeatures.XPath ?\n        function(element, className) {\n            className = className.toString().strip();\n            var cond = /\\s/.test(className) ? $w(className).map(iter).join('') : iter(className);\n            return cond ? document._getElementsByXPath('.//*' + cond, element) : [];\n        } : function(element, className) {\n            className = className.toString().strip();\n            var elements = [], classNames = (/\\s/.test(className) ? $w(className) : null);\n            if (!classNames && !className) return elements;\n\n            var nodes = $(element).getElementsByTagName('*');\n            className = ' ' + className + ' ';\n\n            for (var i = 0, child, cn; child = nodes[i]; i++) {\n                if (child.className && (cn = ' ' + child.className + ' ') && (cn.include(className) ||\n                    (classNames && classNames.all(function(name) {\n                        return !name.toString().blank() && cn.include(' ' + name + ' ');\n                    }))))\n                    elements.push(Element.extend(child));\n            }\n            return elements;\n        };\n\n    return function(className, parentElement) {\n        return $(parentElement || document.body).getElementsByClassName(className);\n    };\n}(Element.Methods);\n\n/*--------------------------------------------------------------------------*/\n\nElement.ClassNames = Class.create();\nElement.ClassNames.prototype = {\n    initialize: function(element) {\n        this.element = $(element);\n    },\n\n    _each: function(iterator, context) {\n        this.element.className.split(/\\s+/).select(function(name) {\n            return name.length > 0;\n        })._each(iterator, context);\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\n/*--------------------------------------------------------------------------*/\n\n(function() {\n    window.Selector = Class.create({\n        initialize: function(expression) {\n            this.expression = expression.strip();\n        },\n\n        findElements: function(rootElement) {\n            return Prototype.Selector.select(this.expression, rootElement);\n        },\n\n        match: function(element) {\n            return Prototype.Selector.match(element, this.expression);\n        },\n\n        toString: function() {\n            return this.expression;\n        },\n\n        inspect: function() {\n            return \"#<Selector: \" + this.expression + \">\";\n        }\n    });\n\n    Object.extend(Selector, {\n        matchElements: function(elements, expression) {\n            var match = Prototype.Selector.match,\n                results = [];\n\n            for (var i = 0, length = elements.length; i < length; i++) {\n                var element = elements[i];\n                if (match(element, expression)) {\n                    results.push(Element.extend(element));\n                }\n            }\n            return results;\n        },\n\n        findElement: function(elements, expression, index) {\n            index = index || 0;\n            var matchIndex = 0, element;\n            for (var i = 0, length = elements.length; i < length; i++) {\n                element = elements[i];\n                if (Prototype.Selector.match(element, expression) && index === matchIndex++) {\n                    return Element.extend(element);\n                }\n            }\n        },\n\n        findChildElements: function(element, expressions) {\n            var selector = expressions.toArray().join(', ');\n            return Prototype.Selector.select(selector, element || document);\n        }\n    });\n})();"
  },
  {
    "path": "flowable-ui-web/modeler/editor-app/libs/ui-utils.min-0.2.1.js",
    "content": "/**\n * angular-ui-utils - Swiss-Army-Knife of AngularJS tools (with no external dependencies!)\n * @version v0.2.1 - 2015-01-02\n * @link http://angular-ui.github.com\n * @license MIT License, http://www.opensource.org/licenses/MIT\n */\nfunction uiUploader(a){\"use strict\";function b(a){for(var b=0;b<a.length;b++)i.files.push(a[b])}function c(){return i.files}function d(a){i.options=a;for(var b=0;b<i.files.length&&i.activeUploads!=i.options.concurrency;b++)i.files[b].active||h(i.files[b],i.options.url)}function e(a){i.files.splice(i.files.indexOf(a),1)}function f(){i.files.splice(0,i.files.length)}function g(a){var b=[\"n/a\",\"bytes\",\"KiB\",\"MiB\",\"GiB\",\"TB\",\"PB\",\"EiB\",\"ZiB\",\"YiB\"],c=+Math.floor(Math.log(a)/Math.log(1024));return(a/Math.pow(1024,c)).toFixed(c?1:0)+\" \"+b[isNaN(a)?0:c+1]}function h(a,b){var c,e,f,h=\"\",j=\"file\";if(i.activeUploads+=1,a.active=!0,c=new window.XMLHttpRequest,e=new window.FormData,c.open(\"POST\",b),c.upload.onloadstart=function(){},c.upload.onprogress=function(b){b.lengthComputable&&(a.loaded=b.loaded,a.humanSize=g(b.loaded),i.options.onProgress(a))},c.onload=function(){i.activeUploads-=1,d(i.options),i.options.onCompleted(a)},c.onerror=function(){},h)for(f in h)h.hasOwnProperty(f)&&e.append(f,h[f]);return e.append(j,a,a.name),c.send(e),c}var i=this;return i.files=[],i.options={},i.activeUploads=0,a.info(\"uiUploader loaded\"),{addFiles:b,getFiles:c,files:i.files,startUpload:d,removeFile:e,removeAll:f}}angular.module(\"ui.alias\",[]).config([\"$compileProvider\",\"uiAliasConfig\",function(a,b){\"use strict\";b=b||{},angular.forEach(b,function(b,c){angular.isString(b)&&(b={replace:!0,template:b}),a.directive(c,function(){return b})})}]),angular.module(\"ui.event\",[]).directive(\"uiEvent\",[\"$parse\",function(a){\"use strict\";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(){\"use strict\";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(){\"use strict\";return function(a,b,c){return a&&(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){\"use strict\";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(){\"use strict\";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(){\"use strict\";function a(a){return a=a.replace(/([A-Z])|([\\-|\\_])/g,function(a,b){return\" \"+(b||\"\")}),a.replace(/\\s\\s+/g,\" \").trim().toLowerCase().split(\" \")}function b(a){var b=[];return angular.forEach(a,function(a){b.push(a.charAt(0).toUpperCase()+a.substr(1))}),b}var c={humanize:function(c){return b(a(c)).join(\" \")},underscore:function(b){return a(b).join(\"_\")},variable:function(c){return c=a(c),c=c[0]+b(c.slice(1)).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){\"use strict\";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){\"use strict\";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){\"use strict\";return{link:function(b,c,d){a(\"keydown\",b,c,d)}}}]),angular.module(\"ui.keypress\").directive(\"uiKeypress\",[\"keypressHelper\",function(a){\"use strict\";return{link:function(b,c,d){a(\"keypress\",b,c,d)}}}]),angular.module(\"ui.keypress\").directive(\"uiKeyup\",[\"keypressHelper\",function(a){\"use strict\";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]/},clearOnBlur:!0}).directive(\"uiMask\",[\"uiMaskConfig\",\"$parse\",function(a,b){\"use strict\";return{priority:100,require:\"ngModel\",restrict:\"A\",compile:function(){var c=a;return function(a,d,e,f){function g(a){return angular.isDefined(a)?(t(a),O?(l(),m(),!0):k()):k()}function h(a){angular.isDefined(a)&&(E=a,O&&x())}function i(a){return O?(H=p(a||\"\"),J=o(H),f.$setValidity(\"mask\",J),J&&H.length?q(H):void 0):a}function j(a){return O?(H=p(a||\"\"),J=o(H),f.$viewValue=H.length?q(H):\"\",f.$setValidity(\"mask\",J),\"\"===H&&e.required&&f.$setValidity(\"required\",!f.$error.required),J?H:void 0):a}function k(){return O=!1,n(),angular.isDefined(Q)?d.attr(\"placeholder\",Q):d.removeAttr(\"placeholder\"),angular.isDefined(R)?d.attr(\"maxlength\",R):d.removeAttr(\"maxlength\"),d.val(f.$modelValue),f.$viewValue=f.$modelValue,!1}function l(){H=L=p(f.$modelValue||\"\"),I=K=q(H),J=o(H);var a=J&&H.length?I:\"\";e.maxlength&&d.attr(\"maxlength\",2*C[C.length-1]),d.attr(\"placeholder\",E),d.val(a),f.$viewValue=a}function m(){P||(d.bind(\"blur\",u),d.bind(\"mousedown mouseup\",v),d.bind(\"input keyup click focus\",x),P=!0)}function n(){P&&(d.unbind(\"blur\",u),d.unbind(\"mousedown\",v),d.unbind(\"mouseup\",v),d.unbind(\"input\",x),d.unbind(\"keyup\",x),d.unbind(\"click\",x),d.unbind(\"focus\",x),P=!1)}function o(a){return a.length?a.length>=G:!0}function p(a){var b=\"\",c=D.slice();return a=a.toString(),angular.forEach(F,function(b){a=a.replace(b,\"\")}),angular.forEach(a.split(\"\"),function(a){c.length&&c[0].test(a)&&(b+=a,c.shift())}),b}function q(a){var b=\"\",c=C.slice();return angular.forEach(E.split(\"\"),function(d,e){a.length&&e===c[0]?(b+=a.charAt(0)||\"_\",a=a.substr(1),c.shift()):b+=d}),b}function r(a){var b=e.placeholder;return\"undefined\"!=typeof b&&b[a]?b[a]:\"_\"}function s(){return E.replace(/[_]+/g,\"_\").replace(/([^_]+)([a-zA-Z0-9])([^_])/g,\"$1$2_$3\").split(\"_\")}function t(a){var b=0;if(C=[],D=[],E=\"\",\"string\"==typeof a){G=0;var c=!1,d=a.split(\"\");angular.forEach(d,function(a,d){S.maskDefinitions[a]?(C.push(b),E+=r(d),D.push(S.maskDefinitions[a]),b++,c||G++):\"?\"===a?c=!0:(E+=a,b++)})}C.push(C.slice().pop()+1),F=s(),O=C.length>1?!0:!1}function u(){S.clearOnBlur&&(M=0,N=0),J&&0!==H.length||(S.clearOnBlur&&(I=\"\",d.val(\"\")),a.$apply(function(){f.$setViewValue(\"\")}))}function v(a){\"mousedown\"===a.type?d.bind(\"mouseout\",w):d.unbind(\"mouseout\",w)}function w(){N=B(this),d.unbind(\"mouseout\",w)}function x(b){b=b||{};var c=b.which,e=b.type;if(16!==c&&91!==c){var g,h=d.val(),i=K,j=p(h),k=L,l=!1,m=z(this)||0,n=M||0,o=m-n,r=C[0],s=C[j.length]||C.slice().shift(),t=N||0,u=B(this)>0,v=t>0,w=h.length>i.length||t&&h.length>i.length-t,x=h.length<i.length||t&&h.length===i.length-t,D=c>=37&&40>=c&&b.shiftKey,E=37===c,F=8===c||\"keyup\"!==e&&x&&-1===o,G=46===c||\"keyup\"!==e&&x&&0===o&&!v,H=(E||F||\"click\"===e)&&m>r;if(N=B(this),!D&&(!u||\"click\"!==e&&\"keyup\"!==e)){if(\"input\"===e&&x&&!v&&j===k){for(;F&&m>r&&!y(m);)m--;for(;G&&s>m&&-1===C.indexOf(m);)m++;var I=C.indexOf(m);j=j.substring(0,I)+j.substring(I+1),l=!0}for(g=q(j),K=g,L=j,d.val(g),l&&a.$apply(function(){f.$setViewValue(j)}),w&&r>=m&&(m=r+1),H&&m--,m=m>s?s:r>m?r:m;!y(m)&&m>r&&s>m;)m+=H?-1:1;(H&&s>m||w&&!y(n))&&m++,M=m,A(this,m)}}}function y(a){return C.indexOf(a)>-1}function z(a){if(!a)return 0;if(void 0!==a.selectionStart)return a.selectionStart;if(document.selection){a.focus();var b=document.selection.createRange();return b.moveStart(\"character\",a.value?-a.value.length:0),b.text.length}return 0}function A(a,b){if(!a)return 0;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 B(a){return a?void 0!==a.selectionStart?a.selectionEnd-a.selectionStart:document.selection?document.selection.createRange().text.length:0:0}var C,D,E,F,G,H,I,J,K,L,M,N,O=!1,P=!1,Q=e.placeholder,R=e.maxlength,S={};e.uiOptions?(S=a.$eval(\"[\"+e.uiOptions+\"]\"),angular.isObject(S[0])&&(S=function(a,b){for(var c in a)Object.prototype.hasOwnProperty.call(a,c)&&(void 0===b[c]?b[c]=angular.copy(a[c]):angular.extend(b[c],a[c]));return b}(c,S[0]))):S=c,e.$observe(\"uiMask\",g),e.$observe(\"placeholder\",h);var T=!1;e.$observe(\"modelViewValue\",function(a){\"true\"===a&&(T=!0)}),a.$watch(e.ngModel,function(c){if(T&&c){var d=b(e.ngModel);d.assign(a,f.$viewValue)}}),f.$formatters.push(i),f.$parsers.push(j),d.bind(\"mousedown mouseup\",v),Array.prototype.indexOf||(Array.prototype.indexOf=function(a){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){\"use strict\";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(){e.$setViewValue(d.uiReset?a.$eval(d.uiReset):b),e.$render()})})}}}]),angular.module(\"ui.route\",[]).directive(\"uiRoute\",[\"$location\",\"$parse\",function(a,b){\"use strict\";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){var d=b.indexOf(\"#\");d>-1&&(b=b.substr(d+1)),(j=function(){i(c,a.path().indexOf(b)>-1)})()}function h(b){var d=b.indexOf(\"#\");d>-1&&(b=b.substr(d+1)),(j=function(){var d=new RegExp(\"^\"+b+\"$\",[\"i\"]);i(c,d.test(a.path()))})()}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.scroll.jqlite\",[\"ui.scroll\"]).service(\"jqLiteExtras\",[\"$log\",\"$window\",function(a,b){\"use strict\";return{registerFor:function(a){var c,d,e,f,g,h,i;return d=angular.element.prototype.css,a.prototype.css=function(a,b){var c,e;return e=this,c=e[0],c&&3!==c.nodeType&&8!==c.nodeType&&c.style?d.call(e,a,b):void 0},h=function(a){return a&&a.document&&a.location&&a.alert&&a.setInterval},i=function(a,b,c){var d,e,f,g,i;return d=a[0],i={top:[\"scrollTop\",\"pageYOffset\",\"scrollLeft\"],left:[\"scrollLeft\",\"pageXOffset\",\"scrollTop\"]}[b],e=i[0],g=i[1],f=i[2],h(d)?angular.isDefined(c)?d.scrollTo(a[f].call(a),c):g in d?d[g]:d.document.documentElement[e]:angular.isDefined(c)?d[e]=c:d[e]},b.getComputedStyle?(f=function(a){return b.getComputedStyle(a,null)},c=function(a,b){return parseFloat(b)}):(f=function(a){return a.currentStyle},c=function(a,b){var c,d,e,f,g,h,i;return c=/[+-]?(?:\\d*\\.|)\\d+(?:[eE][+-]?\\d+|)/.source,f=new RegExp(\"^(\"+c+\")(?!px)[a-z%]+$\",\"i\"),f.test(b)?(i=a.style,d=i.left,g=a.runtimeStyle,h=g&&g.left,g&&(g.left=i.left),i.left=b,e=i.pixelLeft,i.left=d,h&&(g.left=h),e):parseFloat(b)}),e=function(a,b){var d,e,g,i,j,k,l,m,n,o,p,q,r;return h(a)?(d=document.documentElement[{height:\"clientHeight\",width:\"clientWidth\"}[b]],{base:d,padding:0,border:0,margin:0}):(r={width:[a.offsetWidth,\"Left\",\"Right\"],height:[a.offsetHeight,\"Top\",\"Bottom\"]}[b],d=r[0],l=r[1],m=r[2],k=f(a),p=c(a,k[\"padding\"+l])||0,q=c(a,k[\"padding\"+m])||0,e=c(a,k[\"border\"+l+\"Width\"])||0,g=c(a,k[\"border\"+m+\"Width\"])||0,i=k[\"margin\"+l],j=k[\"margin\"+m],n=c(a,i)||0,o=c(a,j)||0,{base:d,padding:p+q,border:e+g,margin:n+o})},g=function(a,b,c){var d,g,h;return g=e(a,b),g.base>0?{base:g.base-g.padding-g.border,outer:g.base,outerfull:g.base+g.margin}[c]:(d=f(a),h=d[b],(0>h||null===h)&&(h=a.style[b]||0),h=parseFloat(h)||0,{base:h-g.padding-g.border,outer:h,outerfull:h+g.padding+g.border+g.margin}[c])},angular.forEach({before:function(a){var b,c,d,e,f,g,h;if(f=this,c=f[0],e=f.parent(),b=e.contents(),b[0]===c)return e.prepend(a);for(d=g=1,h=b.length-1;h>=1?h>=g:g>=h;d=h>=1?++g:--g)if(b[d]===c)return void angular.element(b[d-1]).after(a);throw new Error(\"invalid DOM structure \"+c.outerHTML)},height:function(a){var b;return b=this,angular.isDefined(a)?(angular.isNumber(a)&&(a+=\"px\"),d.call(b,\"height\",a)):g(this[0],\"height\",\"base\")},outerHeight:function(a){return g(this[0],\"height\",a?\"outerfull\":\"outer\")},offset:function(a){var b,c,d,e,f,g;if(f=this,arguments.length){if(void 0===a)return f;throw new Error(\"offset setter method is not implemented\")}return b={top:0,left:0},e=f[0],(c=e&&e.ownerDocument)?(d=c.documentElement,null!=e.getBoundingClientRect&&(b=e.getBoundingClientRect()),g=c.defaultView||c.parentWindow,{top:b.top+(g.pageYOffset||d.scrollTop)-(d.clientTop||0),left:b.left+(g.pageXOffset||d.scrollLeft)-(d.clientLeft||0)}):void 0},scrollTop:function(a){return i(this,\"top\",a)},scrollLeft:function(a){return i(this,\"left\",a)}},function(b,c){return a.prototype[c]?void 0:a.prototype[c]=b})}}}]).run([\"$log\",\"$window\",\"jqLiteExtras\",function(a,b,c){\"use strict\";return b.jQuery?void 0:c.registerFor(angular.element)}]),angular.module(\"ui.scroll\",[]).directive(\"uiScrollViewport\",[\"$log\",function(){\"use strict\";return{controller:[\"$scope\",\"$element\",function(a,b){return this.viewport=b,this}]}}]).directive(\"uiScroll\",[\"$log\",\"$injector\",\"$rootScope\",\"$timeout\",function(a,b,c,d){\"use strict\";return{require:[\"?^uiScrollViewport\"],transclude:\"element\",priority:1e3,terminal:!0,compile:function(e,f,g){return function(e,f,h,i){var j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,$,_,ab,bb,cb;if(J=a.debug||a.log,K=h.uiScroll.match(/^\\s*(\\w+)\\s+in\\s+([\\w\\.]+)\\s*$/),!K)throw new Error(\"Expected uiScroll in form of '_item_ in _datasource_' but got '\"+h.uiScroll+\"'\");if(H=K[1],u=K[2],F=function(a){return angular.isObject(a)&&a.get&&angular.isFunction(a.get)},C=function(a,b){var c;return a?(c=b.match(/^([\\w]+)\\.(.+)$/),c&&3===c.length?C(a[c[1]],c[2]):a[b]):null},t=C(e,u),!F(t)&&(t=b.get(u),!F(t)))throw new Error(\"\"+u+\" is not a valid datasource\");return q=Math.max(3,+h.bufferSize||10),p=function(){return ab.outerHeight()*Math.max(.1,+h.padding||.1)},S=function(a){var b;return null!=(b=a[0].scrollHeight)?b:a[0].document.documentElement.scrollHeight},j=null,g(W=e.$new(),function(a){var b,c,d,e,g,h;if(e=a[0].localName,\"dl\"===e)throw new Error(\"ui-scroll directive does not support <\"+a[0].localName+\"> as a repeating tag: \"+a[0].outerHTML);return\"li\"!==e&&\"tr\"!==e&&(e=\"div\"),h=i[0]&&i[0].viewport?i[0].viewport:angular.element(window),h.css({\"overflow-y\":\"auto\",display:\"block\"}),d=function(a){var b,c,d;switch(a){case\"tr\":return d=angular.element(\"<table><tr><td><div></div></td></tr></table>\"),b=d.find(\"div\"),c=d.find(\"tr\"),c.paddingHeight=function(){return b.height.apply(b,arguments)},c;default:return c=angular.element(\"<\"+a+\"></\"+a+\">\"),c.paddingHeight=c.height,c}},c=function(a,b,c){return b[{top:\"before\",bottom:\"after\"}[c]](a),{paddingHeight:function(){return a.paddingHeight.apply(a,arguments)},insert:function(b){return a[{top:\"after\",bottom:\"before\"}[c]](b)}}},g=c(d(e),f,\"top\"),b=c(d(e),f,\"bottom\"),W.$destroy(),j={viewport:h,topPadding:g.paddingHeight,bottomPadding:b.paddingHeight,append:b.insert,prepend:g.insert,bottomDataPos:function(){return S(h)-b.paddingHeight()},topDataPos:function(){return g.paddingHeight()}}}),ab=j.viewport,bb=ab.scope()||c,angular.isDefined(h.topVisible)&&(Z=function(a){return bb[h.topVisible]=a}),angular.isDefined(h.topVisibleElement)&&(Y=function(a){return bb[h.topVisibleElement]=a}),angular.isDefined(h.topVisibleScope)&&(_=function(a){return bb[h.topVisibleScope]=a}),X=function(a){return Z&&Z(a.scope[H]),Y&&Y(a.element),_&&_(a.scope),t.topVisible?t.topVisible(a):void 0},I=angular.isDefined(h.isLoading)?function(a){return bb[h.isLoading]=a,t.loading?t.loading(a):void 0}:function(a){return t.loading?t.loading(a):void 0},Q=0,B=1,L=1,o=[],M=[],x=!1,m=!1,G=!1,O=function(a,b){var c,d;for(c=d=a;b>=a?b>d:d>b;c=b>=a?++d:--d)o[c].scope.$destroy(),o[c].element.remove();return o.splice(a,b-a)},N=function(){return Q++,B=1,L=1,O(0,o.length),j.topPadding(0),j.bottomPadding(0),M=[],x=!1,m=!1,k(Q,!1)},n=function(){return ab.scrollTop()+ab.outerHeight()},$=function(){return ab.scrollTop()},T=function(){return!x&&j.bottomDataPos()<n()+p()},r=function(){var a,b,c,d,e,f,g,h,i,k;for(a=0,g=0,b=i=k=o.length-1;0>=k?0>=i:i>=0;b=0>=k?++i:--i)if(c=o[b],e=c.element.offset().top,f=h!==e,h=e,f&&(d=c.element.outerHeight(!0)),j.bottomDataPos()-a-d>n()+p())f&&(a+=d),g++,x=!1;else{if(f)break;g++}return g>0?(j.bottomPadding(j.bottomPadding()+a),O(o.length-g,o.length),L-=g,J(\"clipped off bottom \"+g+\" bottom padding \"+j.bottomPadding())):void 0},U=function(){return!m&&j.topDataPos()>$()-p()},s=function(){var a,b,c,d,e,f,g,h,i;for(g=0,e=0,h=0,i=o.length;i>h;h++)if(a=o[h],c=a.element.offset().top,d=f!==c,f=c,d&&(b=a.element.outerHeight(!0)),j.topDataPos()+g+b<$()-p())d&&(g+=b),e++,m=!1;else{if(d)break;e++}return e>0?(j.topPadding(j.topPadding()+g),O(0,e),B+=e,J(\"clipped off top \"+e+\" top padding \"+j.topPadding())):void 0},w=function(a,b,c){return G||(G=!0,I(!0)),1===M.push(b)?z(a,c):void 0},D=function(a){return a.displayTemp=a.css(\"display\"),a.css(\"display\",\"none\")},V=function(a){return a.hasOwnProperty(\"displayTemp\")?a.css(\"display\",a.displayTemp):void 0},E=function(a,b){var c,d,f;return c=e.$new(),c[H]=b,d=a>B,c.$index=a,d&&c.$index--,f={scope:c},g(c,function(b){return f.element=b,d?a===L?(D(b),j.append(b),o.push(f)):(o[a-B].element.after(b),o.splice(a-B+1,0,f)):(D(b),j.prepend(b),o.unshift(f))}),{appended:d,wrapper:f}},l=function(a,b){var c;return a?j.bottomPadding(Math.max(0,j.bottomPadding()-b.element.outerHeight(!0))):(c=j.topPadding()-b.element.outerHeight(!0),c>=0?j.topPadding(c):ab.scrollTop(ab.scrollTop()+b.element.outerHeight(!0)))},v=function(a,b,c){var d,e,f,g,h,i,k,l,m;if(J(\"top {actual=\"+j.topDataPos()+\" visible from=\"+$()+\" bottom {visible through=\"+n()+\" actual=\"+j.bottomDataPos()+\"}\"),T()?w(a,!0,b):U()&&w(a,!1,b),c&&c(a),0===M.length){for(i=0,m=[],k=0,l=o.length;l>k;k++){if(d=o[k],f=d.element.offset().top,g=h!==f,h=f,g&&(e=d.element.outerHeight(!0)),!(g&&j.topDataPos()+i+e<$())){g&&X(d);break}m.push(i+=e)}return m}},k=function(a,b,c,e){return c&&c.length?d(function(){var d,g,h,i,j,k,m,n;for(i=[],j=0,m=c.length;m>j;j++)g=c[j],f=g.wrapper.element,V(f),d=f.offset().top,h!==d&&(i.push(g),h=d);for(k=0,n=i.length;n>k;k++)g=i[k],l(g.appended,g.wrapper);return v(a,b,e)}):v(a,b,e)},A=function(a,b,c){return k(a,b,c,function(){return M.shift(),0===M.length?(G=!1,I(!1)):z(a,b)})},z=function(a,b){var c;return c=M[0],c?o.length&&!T()?A(a,b):t.get(L,q,function(c){var d,e,f,g;if(!a||a===Q){if(e=[],c.length<q&&(x=!0,j.bottomPadding(0)),c.length>0)for(s(),f=0,g=c.length;g>f;f++)d=c[f],e.push(E(++L,d));return A(a,b,e)}}):o.length&&!U()?A(a,b):t.get(B-q,q,function(c){var d,e,f,g;if(!a||a===Q){if(e=[],c.length<q&&(m=!0,j.topPadding(0)),c.length>0)for(o.length&&r(),d=f=g=c.length-1;0>=g?0>=f:f>=0;d=0>=g?++f:--f)e.unshift(E(--B,c[d]));return A(a,b,e)}})},P=function(){return c.$$phase||G?void 0:(k(null,!1),e.$apply())},ab.bind(\"resize\",P),R=function(){return c.$$phase||G?void 0:(k(null,!0),e.$apply())},ab.bind(\"scroll\",R),cb=function(a){var b,c;return b=ab[0].scrollTop,c=ab[0].scrollHeight-ab[0].clientHeight,0===b&&!m||b===c&&!x?a.preventDefault():void 0},ab.bind(\"mousewheel\",cb),e.$watch(t.revision,function(){return N()}),y=t.scope?t.scope.$new():e.$new(),e.$on(\"$destroy\",function(){return y.$destroy(),ab.unbind(\"resize\",P),ab.unbind(\"scroll\",R),ab.unbind(\"mousewheel\",cb)}),y.$on(\"update.items\",function(a,b,c){var d,e,f,g,h;if(angular.isFunction(b))for(e=function(a){return b(a.scope)},f=0,g=o.length;g>f;f++)d=o[f],e(d);else 0<=(h=b-B-1)&&h<o.length&&(o[b-B-1].scope[H]=c);return null}),y.$on(\"delete.items\",function(a,b){var c,d,e,f,g,h,i,j,l,m,n,p;if(angular.isFunction(b)){for(e=[],h=0,l=o.length;l>h;h++)d=o[h],e.unshift(d);for(g=function(a){return b(a.scope)?(O(e.length-1-c,e.length-c),L--):void 0},c=i=0,m=e.length;m>i;c=++i)f=e[c],g(f)}else 0<=(p=b-B-1)&&p<o.length&&(O(b-B-1,b-B),L--);for(c=j=0,n=o.length;n>j;c=++j)d=o[c],d.scope.$index=B+c;return k(null,!1)}),y.$on(\"insert.item\",function(a,b,c){var d,e,f,g,h;if(e=[],angular.isFunction(b))throw new Error(\"not implemented - Insert with locator function\");for(0<=(h=b-B-1)&&h<o.length&&(e.push(E(b,c)),L++),d=f=0,g=o.length;g>f;d=++f)c=o[d],c.scope.$index=B+d;return k(null,!1,e)})}}}}]),angular.module(\"ui.scrollfix\",[]).directive(\"uiScrollfix\",[\"$window\",function(a){\"use strict\";function b(){if(angular.isDefined(a.pageYOffset))return a.pageYOffset;var b=document.compatMode&&\"BackCompat\"!==document.compatMode?document.documentElement:document.body;return b.scrollTop}return{require:\"^?uiScrollfixTarget\",link:function(c,d,e,f){function g(){var a=f?i[0].scrollTop:b();!d.hasClass(\"ui-scrollfix\")&&a>e.uiScrollfix?d.addClass(\"ui-scrollfix\"):d.hasClass(\"ui-scrollfix\")&&a<e.uiScrollfix&&d.removeClass(\"ui-scrollfix\")}var h=d[0].offsetTop,i=f&&f.$element||angular.element(a);e.uiScrollfix?\"string\"==typeof e.uiScrollfix&&(\"-\"===e.uiScrollfix.charAt(0)?e.uiScrollfix=h-parseFloat(e.uiScrollfix.substr(1)):\"+\"===e.uiScrollfix.charAt(0)&&(e.uiScrollfix=h+parseFloat(e.uiScrollfix.substr(1)))):e.uiScrollfix=h,i.on(\"scroll\",g),c.$on(\"$destroy\",function(){i.off(\"scroll\",g)})}}}]).directive(\"uiScrollfixTarget\",[function(){\"use strict\";return{controller:[\"$element\",function(a){this.$element=a}]}}]),angular.module(\"ui.showhide\",[]).directive(\"uiShow\",[function(){\"use strict\";return function(a,b,c){a.$watch(c.uiShow,function(a){a?b.addClass(\"ui-show\"):b.removeClass(\"ui-show\")})}}]).directive(\"uiHide\",[function(){\"use strict\";return function(a,b,c){a.$watch(c.uiHide,function(a){a?b.addClass(\"ui-hide\"):b.removeClass(\"ui-hide\")})}}]).directive(\"uiToggle\",[function(){\"use strict\";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){\"use strict\";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.uploader\",[]).service(\"uiUploader\",uiUploader),uiUploader.$inject=[\"$log\"],angular.module(\"ui.validate\",[]).directive(\"uiValidate\",function(){\"use strict\";return{restrict:\"A\",require:\"ngModel\",link:function(a,b,c,d){function e(b){return angular.isString(b)?void a.$watch(b,function(){angular.forEach(g,function(a){a(d.$modelValue)})}):angular.isArray(b)?void angular.forEach(b,function(b){a.$watch(b,function(){angular.forEach(g,function(a){a(d.$modelValue)})})}):void(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)})})}))}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),e)},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.scroll\",\"ui.scroll.jqlite\",\"ui.showhide\",\"ui.unique\",\"ui.validate\"]);"
  },
  {
    "path": "flowable-ui-web/modeler/editor-app/libs/update-helper.js",
    "content": "/* Update Helper (c) 2008-2009 Tobie Langel\n *\n * Requires Prototype >= 1.6.0\n *\n * Update Helper is distributable under the same terms as Prototype\n * (MIT-style license). For details, see the Prototype web site:\n * http://www.prototypejs.org/\n *\n *--------------------------------------------------------------------------*/\n\nvar UpdateHelper = Class.create({\n    logLevel: 0,\n    MessageTemplate: new Template('Update Helper: #{message}\\n#{stack}'),\n    Regexp:          new RegExp(\"@\" + window.location.protocol + \".*?\\\\d+\\\\n\", \"g\"),\n\n    initialize: function(deprecatedMethods) {\n        var notify = function(message, type) {\n            this.notify(message, type);\n        }.bind(this);   // Late binding to simplify testing.\n\n        deprecatedMethods.each(function(d) {\n            var condition = d.condition,\n                type      = d.type || 'info',\n                message   = d.message,\n                namespace = d.namespace,\n                method    = d.methodName;\n\n            namespace[method] = (namespace[method] || function() {}).wrap(function(proceed) {\n                var args = $A(arguments).splice(1);\n                if (!condition || condition.apply(this, args)) notify(message, type);\n                return proceed.apply(proceed, args);\n            });\n        });\n        Element.addMethods();\n    },\n\n    notify: function(message, type) {\n        switch(type) {\n            case 'info':\n                if (this.logLevel > UpdateHelper.Info) return false;\n            case 'warn':\n                if (this.logLevel > UpdateHelper.Warn) return false;\n            default:\n                if (this.logLevel > UpdateHelper.Error) return false;\n        }\n        this.log(this.MessageTemplate.evaluate({\n            message: message,\n            stack: this.getStack()\n        }), type);\n        return true;\n    },\n\n    getStack: function() {\n        try {\n            throw new Error(\"stack\");\n        } catch(e) {\n            var match = (e.stack || '').match(this.Regexp);\n            if (match) {\n                return match.reject(function(path) {\n                    return (/(prototype|unittest|update_helper)\\.js/).test(path);\n                }).join(\"\\n\");\n            } else { return ''; }\n        }\n    },\n\n    log: function(message, type) {\n        if (type == 'error') console.error(message);\n        else if (type == 'warn') console.warn(message);\n        else console.log(message);\n    }\n});\n\nObject.extend(UpdateHelper, {\n    Info:  0,\n    Warn:  1,\n    Error: 2\n});\n\n\n//= require \"update_helper\"\n\n/* UpdateHelper for Prototype <%= PROTOTYPE_VERSION %> (c) 2008-2009 Tobie Langel\n *\n * UpdateHelper for Prototype is freely distributable under the same\n * terms as Prototype (MIT-style license).\n * For details, see the Prototype web site: http://www.prototypejs.org/\n *\n * Include this file right below prototype.js. All messages\n * will be logged to the console.\n *\n * Note: You can tune the level of warning by redefining\n * prototypeUpdateHelper.logLevel with one of the appropriate constansts\n * (UpdateHelper.Info, UpdateHelper.Warn or UpdateHelper.Error), e.g.:\n *\n *     prototypeUpdateHelper.logLevel = UpdateHelper.Warn;\n *\n * This, for example, will prevent deprecation messages from being logged.\n *\n *              THIS SCRIPT DOES NOT WORK IN INTERNET EXPLORER\n *--------------------------------------------------------------------------*/\n\nvar prototypeUpdateHelper = new UpdateHelper([\n    {\n        methodName: 'display',\n        namespace: Toggle,\n        message: 'Toggle.display has been deprecated, please use Element.toggle instead.'\n    },\n\n    {\n        methodName: 'show',\n        namespace: Element.Methods,\n        message: 'Passing an arbitrary number of elements to Element.show is no longer supported.\\n' +\n        'Use [id_1, id_2, ...].each(Element.show) or $(id_1, id_2, ...).invoke(\"show\") instead.',\n        type: 'error',\n        condition: function() { return arguments.length > 1 && !Object.isNumber(arguments[1]) }\n    },\n\n    {\n        methodName: 'hide',\n        namespace: Element.Methods,\n        message: 'Passing an arbitrary number of elements to Element.hide is no longer supported.\\n' +\n        'Use [id_1, id_2, ...].each(Element.hide) or $(id_1, id_2, ...).invoke(\"hide\") instead.',\n        type: 'error',\n        condition: function() { return arguments.length > 1 && !Object.isNumber(arguments[1]) }\n    },\n\n    {\n        methodName: 'toggle',\n        namespace: Element.Methods,\n        message: 'Passing an arbitrary number of elements to Element.toggle is no longer supported.\\n' +\n        'Use [id_1, id_2, ...].each(Element.toggle) or $(id_1, id_2, ...).invoke(\"toggle\") instead.',\n        type: 'error',\n        condition: function() { return arguments.length > 1 && !Object.isNumber(arguments[1]) }\n    },\n\n    {\n        methodName: 'clear',\n        namespace: Form.Element.Methods,\n        message: 'Passing an arbitrary number of elements to Field.clear is no longer supported.\\n' +\n        'Use [id_1, id_2, ...].each(Form.Element.clear) or $(id_1, id_2, ...).invoke(\"clear\") instead.',\n        type: 'error',\n        condition: function() { return arguments.length > 1 && !Object.isNumber(arguments[1]) }\n    },\n\n    {\n        methodName: 'present',\n        namespace: Form.Element.Methods,\n        message: 'Passing an arbitrary number of elements to Field.present is no longer supported.\\n' +\n        'Use [id_1, id_2, ...].each(Form.Element.present) or $(id_1, id_2, ...).invoke(\"present\") instead.',\n        type: 'error',\n        condition: function() { return arguments.length > 1 && !Object.isNumber(arguments[1]) }\n    },\n\n    {\n        methodName: 'childOf',\n        namespace: Element.Methods,\n        message: 'Element#childOf has been deprecated, please use Element#descendantOf instead.'\n    },\n\n    {\n        methodName: 'Before',\n        namespace: Insertion,\n        message: 'Insertion.Before has been deprecated, please use Element#insert instead.'\n    },\n\n    {\n        methodName: 'Top',\n        namespace: Insertion,\n        message: 'Insertion.Top has been deprecated, please use Element#insert instead.'\n    },\n\n    {\n        methodName: 'Bottom',\n        namespace: Insertion,\n        message: 'Insertion.Bottom has been deprecated, please use Element#insert instead.'\n    },\n\n    {\n        methodName: 'After',\n        namespace: Insertion,\n        message: 'Insertion.After has been deprecated, please use Element#insert instead.'\n    },\n\n    {\n        methodName: 'prepare',\n        namespace: Position,\n        message: 'Position.prepare has been deprecated.'\n    },\n\n    {\n        methodName: 'within',\n        namespace: Position,\n        message: 'Position.within has been deprecated.'\n    },\n\n    {\n        methodName: 'withinIncludingScrolloffsets',\n        namespace: Position,\n        message: 'Position.withinIncludingScrolloffsets has been deprecated.'\n    },\n\n    {\n        methodName: 'overlap',\n        namespace: Position,\n        message: 'Position.overlap has been deprecated.'\n    },\n\n    {\n        methodName: 'cumulativeOffset',\n        namespace: Position,\n        message: 'Position.cumulativeOffset has been deprecated, please use Element#cumulativeOffset instead.'\n    },\n\n    {\n        methodName: 'positionedOffset',\n        namespace: Position,\n        message: 'Position.positionedOffset has been deprecated, please use Element#positionedOffset instead.'\n    },\n\n    {\n        methodName: 'absolutize',\n        namespace: Position,\n        message: 'Position.absolutize has been deprecated, please use Element#absolutize instead.'\n    },\n\n    {\n        methodName: 'relativize',\n        namespace: Position,\n        message: 'Position.relativize has been deprecated, please use Element#relativize instead.'\n    },\n\n    {\n        methodName: 'realOffset',\n        namespace: Position,\n        message: 'Position.realOffset has been deprecated, please use Element#cumulativeScrollOffset instead.'\n    },\n\n    {\n        methodName: 'offsetParent',\n        namespace: Position,\n        message: 'Position.offsetParent has been deprecated, please use Element#getOffsetParent instead.'\n    },\n\n    {\n        methodName: 'page',\n        namespace: Position,\n        message: 'Position.page has been deprecated, please use Element#viewportOffset instead.'\n    },\n\n    {\n        methodName: 'clone',\n        namespace: Position,\n        message: 'Position.clone has been deprecated, please use Element#clonePosition instead.'\n    },\n\n    {\n        methodName: 'initialize',\n        namespace: Element.ClassNames.prototype,\n        message: 'Element.ClassNames has been deprecated.'\n    },\n\n    {\n        methodName: 'classNames',\n        namespace: Element.Methods,\n        message: 'Element#classNames has been deprecated.\\n' +\n        'If you need to access CSS class names as an array, try: $w(element.classname).'\n    },\n\n    {\n        methodName: 'setStyle',\n        namespace: Element.Methods,\n        message: 'Use of uncamelized style-property names is no longer supported.\\n' +\n        'Use either camelized style-property names or a regular CSS string instead (see online documentation).',\n        type: 'error',\n        condition: function(element, style) {\n            return !Object.isString(style) && Object.keys(style).join('').include('-');\n        }\n    },\n\n    {\n        methodName: 'getElementsByClassName',\n        namespace: document,\n        message: 'document.getElementsByClassName has been deprecated, please use $$ instead.'\n    },\n\n    {\n        methodName: 'getElementsByClassName',\n        namespace: Element.Methods,\n        message: 'Element#getElementsByClassName has been deprecated, please use Element#select instead.'\n    },\n\n    {\n        methodName: 'immediateDescendants',\n        namespace: Element.Methods,\n        message: 'Element#immediateDescendants has been deprecated, please use Element#childElements instead.'\n    },\n\n    {\n        methodName: 'getElementsBySelector',\n        namespace: Element.Methods,\n        message: 'Element#getElementsBySelector has been deprecated, please use Element#select instead.'\n    },\n\n    {\n        methodName: 'toQueryString',\n        namespace: Hash,\n        message: 'Hash.toQueryString has been deprecated.\\n' +\n        'Use the instance method Hash#toQueryString or Object.toQueryString instead.'\n    },\n\n    {\n        methodName: 'toJSON',\n        namespace: Hash,\n        message: 'Hash.toJSON has been removed.\\n' +\n        'Use the instance method Hash#toJSON or Object.toJSON instead.',\n        type: 'error'\n    },\n\n    {\n        methodName: 'remove',\n        namespace: Hash.prototype,\n        message: 'Hash#remove is no longer supported, use Hash#unset instead.\\n' +\n        'Please note that Hash#unset only accepts one argument.',\n        type: 'error'\n    },\n\n    {\n        methodName: 'merge',\n        namespace: Hash.prototype,\n        message: 'Hash#merge is no longer destructive and now operates on a clone of the Hash instance.\\n' +\n        'If you need a destructive merge, use Hash#update instead.',\n        type: 'warn'\n    },\n\n    {\n        methodName: 'reduce',\n        namespace: Array.prototype,\n        message: 'Array#reduce is no longer supported.\\n' +\n        'This is due to an infortunate naming collision with Mozilla\\'s own implementation of Array#reduce which differs completely from Prototype\\'s implementation (it\\'s in fact similar to Prototype\\'s Array#inject).\\n' +\n        'Mozilla\\'s Array#reduce is already implemented in Firefox 3 (as part of JavaScript 1.8) and is about to be standardized in EcmaScript 3.1.',\n        type: 'error'\n    },\n\n    {\n        methodName: 'unloadCache',\n        namespace: Event,\n        message: 'Event.unloadCache has been deprecated.',\n        type: 'error'\n    },\n\n    {\n        methodName: 'create',\n        namespace: Class,\n        message: 'The class API has been fully revised and now allows for mixins and inheritance.\\n' +\n        'You can find more about it here: http://prototypejs.org/learn/class-inheritance',\n        condition: function() { return !arguments.length }\n    },\n\n    {\n        methodName: 'initialize',\n        namespace: Selector.prototype,\n        message: 'The Selector class has been deprecated. Please use the new Prototype.Selector API instead.',\n        type: 'warn'\n    },\n\n    {\n        methodName: 'findElements',\n        namespace: Selector.prototype,\n        message: 'Selector#findElements has been deprecated. Please use the new Prototype.Selector API instead.',\n        type: 'warn'\n    },\n\n    {\n        methodName: 'match',\n        namespace: Selector.prototype,\n        message: 'Selector#match has been deprecated. Please use the new Prototype.Selector API instead.',\n        type: 'warn'\n    },\n\n    {\n        methodName: 'toString',\n        namespace: Selector.prototype,\n        message: 'Selector#toString has been deprecated. Please use the new Prototype.Selector API instead.',\n        type: 'warn'\n    },\n\n    {\n        methodName: 'inspect',\n        namespace: Selector.prototype,\n        message: 'Selector#inspect has been deprecated. Please use the new Prototype.Selector API instead.',\n        type: 'warn'\n    },\n\n    {\n        methodName: 'matchElements',\n        namespace: Selector,\n        message: 'Selector.matchElements has been deprecated. Please use the new Prototype.Selector API instead.',\n        type: 'warn'\n    },\n\n    {\n        methodName: 'findElement',\n        namespace: Selector,\n        message: 'Selector.findElement has been deprecated. Please use the new Prototype.Selector API instead.',\n        type: 'warn'\n    },\n\n    {\n        methodName: 'findChildElements',\n        namespace: Selector,\n        message: 'Selector.findChildElements has been deprecated. Please use the new Prototype.Selector API instead.',\n        type: 'warn'\n    }\n]);\n\n// Special casing for Hash.\n\n(function() {\n    var __properties = Object.keys(Hash.prototype).concat(['_object', '__properties']);\n\n    var messages = {\n        setting: new Template(\"Directly setting a property on an instance of Hash is no longer supported.\\n\" +\n            \"Please use Hash#set('#{property}', #{value}) instead.\"),\n        getting: new Template(\"Directly accessing a property of an instance of Hash is no longer supported.\\n\" +\n            \"Please use Hash#get('#{property}') instead.\")\n    };\n\n    function notify(property, value) {\n        var message = messages[arguments.length == 1 ? 'getting' : 'setting'].evaluate({\n            property: property,\n            value: Object.inspect(value)\n        });\n        prototypeUpdateHelper.notify(message, 'error');\n    }\n\n    function defineSetters(obj, prop) {\n        storeProperties(obj);\n        if (obj.__properties.include(prop)) return;\n        obj.__properties.push(prop);\n        obj.__defineGetter__(prop, function() {\n            checkProperties(this);\n            notify(prop);\n        });\n        obj.__defineSetter__(prop, function(value) {\n            checkProperties(this);\n            notify(prop, value);\n        });\n    }\n\n    function checkProperties(hash) {\n        storeProperties(hash);\n        var current = Object.keys(hash);\n        if (current.length == hash.__properties.length)\n            return;\n        current.each(function(prop) {\n            if (hash.__properties.include(prop)) return;\n            notify(prop, hash[prop]);\n            defineSetters(hash, prop);\n        });\n    }\n\n    function storeProperties(h) {\n        if (typeof h.__properties === 'undefined')\n            h.__properties = __properties.clone();\n        return h;\n    }\n\n    Hash.prototype.set = Hash.prototype.set.wrap(function(proceed, property, value) {\n        defineSetters(this, property);\n        return proceed(property, value);\n    });\n\n    $w('merge update').each(function(name) {\n        Hash.prototype[name] = Hash.prototype[name].wrap(function(proceed, object) {\n            for (var prop in object) defineSetters(this, prop);\n            return proceed(object);\n        });\n    });\n\n    $H(Hash.prototype).each(function(method) {\n        var key = method.key;\n        if (!Object.isFunction(method.value) || key == 'initialize') return;\n        Hash.prototype[key] = Hash.prototype[key].wrap(function(proceed) {\n            checkProperties(this);\n            return proceed.apply(proceed, $A(arguments).splice(1));\n        });\n    });\n\n    Hash.prototype.initialize = Hash.prototype.initialize.wrap(function(proceed, object) {\n        storeProperties(this);\n        for (var prop in object) defineSetters(this, prop);\n        proceed(object);\n    });\n})();"
  },
  {
    "path": "flowable-ui-web/modeler/editor-app/partials/process-tree-list.html",
    "content": "<div ng-click=\"showSubProcess(child)\" class=\"process-treeview-list-item\" ng-class=\"{'current-process': child.current}\">\n    <img ng-src=\"editor-app/stencilsets/{{getStencilSetName()}}/icons/activity/{{child.icon}}\" width=\"16px;\" height=\"16px;\"/> {{child.name}}\n    <img ng-show=\"!child.current && child.type === 'CollapsedSubProcess'\" ng-src=\"editor-app/images/pencil.png\" class=\"pull-right\" ng-click=\"edit(child.id)\" />\n</div>\n<ul ng-if=\"child.children\" class=\"process-treeview-list\">\n    <li ng-repeat=\"child in child.children\" ng-include=\"'editor-app/partials/process-tree-list.html?version=4'\"/>\n</ul>"
  },
  {
    "path": "flowable-ui-web/modeler/editor-app/partials/root-stencil-item-template.html",
    "content": "<span class=\"stencil-item root-stencil-item\"\n      id=\"{{group.id}}\"\n      title=\"{{group.description | translate}}\"\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        <img ng-if=\"!group.customIcon\" ng-src=\"editor-app/stencilsets/{{getStencilSetName()}}/icons/{{group.icon}}\" width=\"16px;\"\n             height=\"16px;\"/>\n        <img ng-if=\"group.customIcon\" ng-src=\"{{getImageUrl(group.icon)}}\" width=\"16px;\" height=\"16px;\"/>\n        {{group.name | translate}}\n</span>\n"
  },
  {
    "path": "flowable-ui-web/modeler/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 | translate}}\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=5'\">\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 | translate}}\"\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        <img ng-if=\"!item.customIcon\" ng-src=\"editor-app/stencilsets/{{getStencilSetName()}}/icons/{{item.icon}}\" width=\"16px;\"\n             height=\"16px;\"/>\n        <img ng-if=\"item.customIcon\" ng-src=\"{{getImageUrl(item.icon)}}\" width=\"16px;\" height=\"16px;\"/>\n        {{item.name | translate}}\n    </li>\n</ul>\n"
  },
  {
    "path": "flowable-ui-web/modeler/editor-app/plugins.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!--\n\n    Licensed under the Apache License, Version 2.0 (the \"License\");\n \tyou may not use this file except in compliance with the License.\n \tYou may obtain a copy of the License at\n \n       http://www.apache.org/licenses/LICENSE-2.0\n  \n \tUnless required by applicable law or agreed to in writing, software\n \tdistributed under the License is distributed on an \"AS IS\" BASIS,\n \tWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n \tSee the License for the specific language governing permissions and\n \tlimitations under the License.\n\n-->\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": "flowable-ui-web/modeler/editor-app/popups/define-data.html",
    "content": "\n<div class=\"modal-header\">\n    <button type=\"button\" class=\"close\" data-dismiss=\"modal\" aria-hidden=\"true\" ng-click=\"close()\">&times;</button>\n    <h3>Data definition</h3>\n</div>\n<div class=\"kis-modal-body\">\n\n    <div class=\"row-fluid\">\n        <div class=\"span6\">\n            <div class=\"kis-listener-grid\" ui-grid=\"gridOptions\"></div>\n            <div class=\"pull-right\">\n                <div class=\"btn-group\">\n                    <a href=\"#\" class=\"btn btn-icon btn-large\" rel=\"tooltip\" data-title=\"{{'ACTION.MOVE.UP' | translate}}\" data-placement=\"bottom\" data-original-title=\"\" title=\"\" ng-click=\"moveDataItemUp()\"><i class=\"icon-arrow-up\"></i></a>\n                    <a href=\"#\" class=\"btn btn-icon btn-large\" rel=\"tooltip\" data-title=\"{{'ACTION.MOVE.DOWN' | translate}}\" data-placement=\"bottom\" data-original-title=\"\" title=\"\" ng-click=\"moveDataItemDown()\"><i class=\"icon-arrow-down\"></i></a>\n                </div>\n                <div class=\"btn-group\">\n                    <a href=\"#\" class=\"btn btn-icon btn-large\" rel=\"tooltip\" data-title=\"{{'ACTION.ADD' | translate:property}}\" data-placement=\"bottom\" data-original-title=\"\" title=\"\" ng-click=\"addNewDataItem()\"><i class=\"icon-plus\"></i></a>\n                    <a href=\"#\" class=\"btn btn-icon btn-large\" rel=\"tooltip\" data-title=\"{{'ACTION.REMOVE' | translate:property}}\" data-placement=\"bottom\" data-original-title=\"\" title=\"\" ng-click=\"removeDataItem()\"><i class=\"icon-minus\"></i></a>\n                </div>\n            </div>\n        </div>\n\n        <div class=\"span6\">\n            <div ng-show=\"selectedDataItems.length > 0\">\n\n                <table>\n                    <tr>\n                        <td class=\"form-property-label\">Name</td>\n                        <td><input type=\"text\" ng-model=\"selectedDataItems[0].name\" placeholder=\"Fill-in a name\"></td>\n                    </tr>\n                    <tr>\n                        <td class=\"form-property-label\">Value</td>\n                        <td><input type=\"text\" ng-model=\"selectedDataItems[0].value\" placeholder=\"Fill-in a value\"></td>\n                    </tr>\n                </table>\n\n            </div>\n            <div ng-show=\"selectedDataItems.length == 0\" class=\"muted no-property-selected\">No data item selected</div>\n        </div>\n    </div>\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"
  },
  {
    "path": "flowable-ui-web/modeler/editor-app/popups/icon-template.html",
    "content": "<div class=\"ui-grid-cell-contents\">\n    <img ng-if=\"!row.entity.customIcon\" ng-src=\"editor-app/stencilsets/{{getStencilSetName()}}/icons/{{row.entity.icon}}\" />\n    <img ng-if=\"row.entity.customIcon\" ng-src=\"{{getImageUrl(row.entity.icon)}}\"/>\n</div>\n"
  },
  {
    "path": "flowable-ui-web/modeler/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        \t<div ng-if=\"saveDialog.errorMessage && saveDialog.errorMessage.length > 0\" class=\"alert error\" style=\"font-size: 14px; margin-top:20px\">\n                <div class=\"popup-error\" style=\"font-size: 14px\">\n                \t<span class=\"glyphicon glyphicon-remove-circle\"></span>\n                \t<span>{{saveDialog.errorMessage}}</span>\n              \t</div>\n            </div>\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 || (error && error.conflictResolveAction == 'saveAs')\"\n                       id=\"nameField\"\n                       class=\"form-control\"\n                       ng-model=\"saveDialog.name\"\n                       auto-focus />\n        \t</div>\n        \t<div class=\"form-group\">\n           \t\t<label for=\"keyField\">{{'MODEL.KEY' | translate}}</label>\n        \t\t<input type=\"text\"\n                       ng-disabled=\"status.loading || (error && error.conflictResolveAction == 'saveAs')\"\n                       id=\"keyField\"\n                       class=\"form-control\"\n                       ng-model=\"saveDialog.key\" />\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        \t<div class=\"checkbox\" ng-show=\"!error && !error.isConflict\">\n           \t\t<label>\n           \t\t\t<input type=\"checkbox\" ng-disabled=\"status.loading\" ng-model=\"saveDialog.newVersion\" >\n           \t\t\t\t{{'MODEL.SAVE.NEWVERSION' | translate}}\n           \t\t</label>\n        \t</div>\n        \t<div class=\"form-group\" ng-if=\"saveDialog.newVersion\">\n           \t\t<label for=\"commentTextArea\">{{'MODEL.SAVE.COMMENT' | translate}}</label>\n           \t\t<textarea id=\"commentTextArea\" class=\"form-control\" ng-model=\"saveDialog.comment\" ng-disabled=\"status.loading\"></textarea>\n        \t</div>\n        \t\n        \t<div ng-if=\"saveDialog.validationErrors\" class=\"alert error\" style=\"font-size: 14px; margin-top:20px\">\n        \n                <div class=\"popup-error\" style=\"font-size: 14px\">\n                    <span class=\"glyphicon glyphicon-remove-circle\"></span>\n                    <span>{{'MODEL.VALIDATIONERRORS' | translate:error}}</span>\n                </div>\n            </div>\n        \n            <div ng-if=\"error && error.isConflict && !status.loading\" class=\"alert error\" style=\"font-size: 14px; margin-top:20px\">\n        \n                <div class=\"popup-error\" style=\"font-size: 14px\">\n                    <span class=\"glyphicon glyphicon-remove-circle\"></span>\n                    <span>{{'MODEL.CONFLICT.WRITE' | translate:error}}</span>\n                </div>\n        \n                <div>\n        \n                    <div style=\"font-size: 14px; margin-bottom: 10px\">{{'MODEL.CONFLICT.WRITE.OPTIONS' | translate}}</div>\n                    <div class=\"btn-group\" data-toggle=\"buttons\">\n                        <label class=\"btn btn-danger\"\n                               ng-click=\"error.conflictResolveAction = 'overwrite'\">\n                            <input type=\"radio\" name=\"options\" id=\"option1\">\n                            {{'MODEL.CONFLICT.WRITE.OPTION.OVERWRITE' | translate}}\n                        </label>\n                        <label class=\"btn btn-danger\"\n                               ng-click=\"error.conflictResolveAction = 'discardChanges'\">\n                            <input type=\"radio\" name=\"options\" id=\"option2\">\n                            {{'MODEL.CONFLICT.WRITE.OPTION.DISCARDCHANGES' | translate}}\n                        </label>\n                        <label class=\"btn btn-danger\"\n                               ng-click=\"error.conflictResolveAction = 'saveAs'\">\n                            <input type=\"radio\" name=\"options\" id=\"option3\" ng-disabled=\"account.type != 'enterprise'\">\n                            {{'MODEL.CONFLICT.WRITE.OPTION.SAVEAS' | translate}}\n                        </label>\n                        <label class=\"btn btn-danger\"\n                               ng-click=\"error.conflictResolveAction = 'newVersion'\">\n                            <input type=\"radio\" name=\"options\" id=\"optio43\">\n                            {{'MODEL.CONFLICT.WRITE.OPTION.NEWVERSION' | translate}}\n                        </label>\n                    </div>\n        \n                    <div ng-if=\"error.conflictResolveAction == 'saveAs'\" style=\"margin-top: 10px\">\n                        <span>{{'MODEL.CONFLICT.SAVEAS' | translate}}</span>\n                        <input type=\"text\" ng-model=\"error.saveAs\" style=\"width: 300px\" auto-focus>\n                    </div>\n                </div>\n        \n            </div>\n        \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 || saveDialog.name.length == 0 || saveDialog.key.length == 0\" ng-show=\"!error && !error.isConflict\" translate>ACTION.SAVE-AND-CLOSE</button>\n            \t<button class=\"btn btn-primary\" ng-click=\"save()\" ng-disabled=\"status.loading || saveDialog.name.length == 0 || saveDialog.key.length == 0\" ng-show=\"!error && !error.isConflict\" translate>ACTION.SAVE</button>\n                <button class=\"btn btn-primary\" ng-click=\"okClicked()\" ng-disabled=\"isOkButtonDisabled()\" ng-show=\"error && error.isConflict\" translate>ACTION.OK</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": "flowable-ui-web/modeler/editor-app/popups/select-shape.html",
    "content": "\n<div class=\"modal\" ng-controller=\"FlowableBpmShapeSelectionCtrl\">\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                <div ng-if=\"gridOptions\" class=\"kis-listener-grid\" ui-grid=\"gridOptions\" ui-grid-selection></div> \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": "flowable-ui-web/modeler/editor-app/popups/unsaved-changes.html",
    "content": "\n<div class=\"modal\" ng-controller=\"EditorUnsavedChangesPopupCtrl\">\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=\"discard()\" translate=\"EDITOR.POPUP.UNSAVED-CHANGES.ACTION.DISCARD\"></button>\n                \t<button class=\"btn btn-success\" ng-click=\"save()\" ng-show=\"{{yesNoCancel}}\" translate=\"EDITOR.POPUP.UNSAVED-CHANGES.ACTION.SAVE\"></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>\n"
  },
  {
    "path": "flowable-ui-web/modeler/editor-app/popups/validate-model.html",
    "content": "<div class=\"modal\" tabindex=\"-1\" role=\"dialog\" ng-controller=\"ValidateModelCtrl\">\n\t<div class=\"modal-dialog modal-lg\">\n\t\t<div class=\"modal-content\">\n\t\t\t<div class=\"modal-header\">\n\t\t\t\t<h2>{{'MODEL.VALIDATE.TITLE' | translate}}</h2>\n\t\t\t</div>\n\t\t\t<div class=\"modal-body\">\n\t\t\t\t<div>\n\t\t\t\t\t<div class=\"alert alert-success\" role=\"alert\" ng-show=\"model.errors.length == 0 && !status.loading\">No errors detected.</div>\n\t\t\t\t\t<div ng-show=\"errorGrid && !status.loading\" class=\"validationGrid\" ui-grid=\"errorGrid\" ui-grid-selection></div>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t<div class=\"modal-footer\">\n\t\t\t\t<button type=\"button\" ng-disabled=\"status.loading\" class=\"btn btn-primary\" ng-click=\"$hide()\">Close</button>\n\t\t\t</div>\n\t\t</div>\n\t</div>\n</div>"
  },
  {
    "path": "flowable-ui-web/modeler/editor-app/process-navigator-controller.js",
    "content": "/* 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\nangular.module('flowableModeler').controller('ProcessNavigatorController',['editorManager', '$scope',function(editorManager, $scope){\n    //problem here the ORYX editor is bound to the rootscope. In theory this communication should be moved to a service.\n\n    $scope.showSubProcess = function(child){\n        var flowableShapes = editorManager.getChildShapeByResourceId(child.resourceId);\n        editorManager.setSelection([flowableShapes],[],true);\n    }\n\n    $scope.treeview = {};\n    $scope.isEditorReady = false;\n\n    $scope.edit = function(resourceId){\n        editorManager.edit(resourceId);\n    };\n\n    FLOWABLE.eventBus.addListener(FLOWABLE.eventBus.EVENT_TYPE_EDITOR_READY, function(event){\n        $scope.isEditorReady = true;\n        renderProcessHierarchy();\n\n        editorManager.registerOnEvent(ORYX.CONFIG.ACTION_DELETE_COMPLETED, filterEvent);\n\n        //always a single event.\n        editorManager.registerOnEvent(ORYX.CONFIG.EVENT_UNDO_ROLLBACK, renderProcessHierarchy);\n    })\n\n    //if an element is added te properties will catch this event.\n    FLOWABLE.eventBus.addListener(FLOWABLE.eventBus.EVENT_TYPE_PROPERTY_VALUE_CHANGED,filterEvent);\n    FLOWABLE.eventBus.addListener(FLOWABLE.eventBus.EVENT_TYPE_ITEM_DROPPED,filterEvent);\n    FLOWABLE.eventBus.addListener(\"EDITORMANAGER-EDIT-ACTION\",function(){\n        renderProcessHierarchy();\n    });\n\n    function filterEvent(event){\n        //this event is fired when the user changes a property by the property editor.\n        if(event.type === \"event-type-property-value-changed\"){\n            if(event.property.key === \"oryx-overrideid\" || event.property.key === \"oryx-name\"){\n                renderProcessHierarchy()\n            }\n            //this event is fired when the stencil / shape's text is changed / updated.\n        }else if(event.type === \"propertyChanged\"){\n            if(event.name === \"oryx-overrideid\" || event.name === \"oryx-name\"){\n                renderProcessHierarchy();\n            }\n        }else if(event.type === ORYX.CONFIG.ACTION_DELETE_COMPLETED){\n            renderProcessHierarchy();\n            //for some reason the new tree does not trigger an ui update.\n            //$scope.$apply();\n        }else if(event.type === \"event-type-item-dropped\"){\n            renderProcessHierarchy();\n        }\n    }\n\n    function renderProcessHierarchy(){\n        //only start calculating when the editor has done all his constructor work.\n        if(!$scope.isEditorReady){\n            return false;\n        }\n        \n        if (!editorManager.isLoading()){\n            //the current implementation of has a lot of eventlisteners. when calling getTree() it could manipulate\n            //the canvastracker while the canvas is stille loading stuff.\n            //TODO: check if its possible to trigger the re-rendering by a single event instead of registering on 10 events...\n            $scope.treeview = editorManager.getTree();\n        }\n\n    }\n\n}]);\n"
  },
  {
    "path": "flowable-ui-web/modeler/editor-app/select-shape-controller.js",
    "content": "/* Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n * \n *      http://www.apache.org/licenses/LICENSE-2.0\n * \n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/*\n * Controller for morph shape selection\n */\n\nangular.module('flowableModeler').controller('FlowableBpmShapeSelectionCtrl',\n    [ '$rootScope', '$scope', '$timeout', '$translate', 'editorManager', function($rootScope, $scope, $timeout, $translate, editorManager) {\n\n    $scope.currentSelectedMorph = undefined;\n    \n    $scope.availableMorphShapes = [];\n\n    for (var i = 0; i < $scope.morphShapes.length; i++) {\n    \tif ($scope.morphShapes[i].id != $scope.currentSelectedShape.getStencil().idWithoutNs()) {\n    \t\t$scope.availableMorphShapes.push($scope.morphShapes[i]);\n    \t}\n    }\n    \t\n    // Config for grid\n    $scope.gridOptions = {\n        data: $scope.availableMorphShapes,\n        headerRowHeight: 28,\n        enableRowSelection: true,\n        enableRowHeaderSelection: false,\n        multiSelect: false,\n        modifierKeysToMultiSelect: false,\n        enableHorizontalScrollbar: 0,\n\t\tenableColumnMenus: false,\n\t\tenableSorting: false,\n        columnDefs: [{ field: 'objectId', displayName: 'Icon', width: 50, cellTemplate: 'editor-app/popups/icon-template.html?version=' + Date.now() },\n            { field: 'name', displayName: 'Name', cellTemplate: '<div class=\"ui-grid-cell-contents\">{{\"\" + row.entity[col.field] | translate}}</div>'}]\n    };\n    \n    $scope.gridOptions.onRegisterApi = function(gridApi) {\n        //set gridApi on scope\n        $scope.gridApi = gridApi;\n        gridApi.selection.on.rowSelectionChanged($scope, function(row) {\n            if (row.isSelected) {\n                $scope.currentSelectedMorph = row.entity;\n            } else {\n                $scope.currentSelectedMorph = undefined;\n            }\n        });\n    };\n\n    // Click handler for save button\n    $scope.select = function() {\n\n        if ($scope.currentSelectedMorph) {\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}\n    \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 = editorManager.getStencilSets().values();\n        \t\n        \tvar stencilId = $scope.currentSelectedMorph.id;\n        \tif ($scope.currentSelectedMorph.genericTaskId) {\n        \t\tstencilId = $scope.currentSelectedMorph.genericTaskId;\n        \t}\n        \t\n        \tfor (var i = 0; i < stencilSets.length; i++) {\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\t\t\tif (nodes[j].idWithoutNs() === stencilId) {\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, editorManager.getEditor());\n    \t\teditorManager.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": "flowable-ui-web/modeler/editor-app/stencil-controller.js",
    "content": "/* 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'use strict';\n\nangular.module('flowableModeler')\n    .controller('StencilController', ['$rootScope', '$scope', '$http', '$modal', '$timeout', '$window', 'editorManager',\n                                      function ($rootScope, $scope, $http, $modal, $timeout, $window, editorManager) {\n\n        // Property window toggle state\n        $scope.propertyWindowState = {'collapsed': false};\n\n        // Add reference to global header-config\n        $scope.headerConfig = FLOWABLE.HEADER_CONFIG;\n\n        $scope.propertyWindowState.toggle = function () {\n            $scope.propertyWindowState.collapsed = !$scope.propertyWindowState.collapsed;\n            $timeout(function () {\n                $window.dispatchEvent(new Event(\"resize\"));\n            }, 100);\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        \n        \t/* 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            var data = editorManager.getStencilData();\n\n            var quickMenuDefinition = undefined;\n            var ignoreForPaletteDefinition = undefined;\n            \n            if (data.namespace == 'http://b3mn.org/stencilset/cmmn1.1#') {\n                quickMenuDefinition = ['HumanTask', 'Association'];\n                ignoreForPaletteDefinition = ['CasePlanModel'];\n                \n            } else {\n                quickMenuDefinition = ['UserTask', 'EndNoneEvent', 'ExclusiveGateway', \n                                         'CatchTimerEvent', 'ThrowNoneEvent', 'TextAnnotation',\n                                         'SequenceFlow', 'Association'];\n                                         \n                ignoreForPaletteDefinition = ['SequenceFlow', 'MessageFlow', 'Association', 'DataAssociation', 'DataStore', 'SendTask'];\n            }\n             \n            var quickMenuItems = [];\n              \n            var 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          \n            // Check all received items\n            for (var stencilIndex = 0; stencilIndex < data.stencils.length; stencilIndex++) {\n            \n                // 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                      quickMenuItems[quickMenuDefinition.indexOf(stencilItem.id)] = stencilItem;\n                    }\n                }\n                \n                if (stencilItem.id === 'TextAnnotation' || stencilItem.id === 'BoundaryCompensationEvent') {\n                  stencilItem.canConnectAssociation = true;\n                }\n                \n                for (var i = 0; i < data.stencils[stencilIndex].roles.length; i++) {\n                  var stencilRole = data.stencils[stencilIndex].roles[i];\n                  if (data.namespace == 'http://b3mn.org/stencilset/cmmn1.1#') {\n                      if (stencilRole === 'association_start') {\n                        stencilItem.canConnect = true;\n                      } else if (stencilRole === 'association_end') {\n                        stencilItem.canConnectTo = true;\n                      }\n                      \n                  } else {\n                      if (stencilRole === 'sequence_start') {\n                        stencilItem.canConnect = true;\n                      } else if (stencilRole === 'sequence_end') {\n                        stencilItem.canConnectTo = true;\n                      }\n                  }\n                  \n                  for (var j = 0; j < morphRoles.length; j++) {\n                    if (stencilRole === morphRoles[j].role) {\n                      if (!removed) {\n                        morphRoles[j].morphOptions.push(stencilItem);\n                      }\n                      stencilItem.morphRole = morphRoles[j].role;\n                      break;\n                    }\n                  }\n                }\n\n                if (currentGroup) {\n                  // Add the stencil item to the correct group\n                  currentGroup.items.push(stencilItem);\n                  if (ignoreForPaletteDefinition.indexOf(stencilItem.id) < 0) {\n                    currentGroup.paletteItems.push(stencilItem);\n                  }\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              if (stencilItemGroups[i].paletteItems && stencilItemGroups[i].paletteItems.length == 0) {\n                stencilItemGroups[i].visible = false;\n              }\n            }\n            \n            $scope.stencilItemGroups = stencilItemGroups;\n\n            var containmentRules = [];\n            for (var i = 0; i < data.rules.containmentRules.length; i++) {\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                if (quickMenuItems[i]) {\n                    availableQuickMenuItems[availableQuickMenuItems.length] = quickMenuItems[i];\n                }\n            }\n            \n            $scope.quickMenuItems = availableQuickMenuItems;\n            $scope.morphRoles = morphRoles;\n\n            /*\n             * Listen to selection change events: show properties\n             */\n            editorManager.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 = [editorManager.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 && stencil.id().indexOf('CMMNDiagram') !== -1) {\n                      // ignore canvas event because of empty selection when scrolling stops\n                      return;\n                    }\n                    \n                    if ($rootScope.selectedElementBeforeScrolling && $rootScope.selectedElementBeforeScrolling.getId() === selectedShape.getId()) {\n                      $rootScope.selectedElementBeforeScrolling = null;\n                      return;\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.get(key);\n                        }\n\n                        // First we check if there is a config for 'key-type' and then for 'type' alone\n                        var propertyConfig = FLOWABLE.PROPERTY_CONFIG[key + '-' + property.type()];\n                        if (propertyConfig === undefined || propertyConfig === null) {\n                            propertyConfig = FLOWABLE.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.get(key) === 'true') {\n                                selectedShape.properties.set(key, true);\n                            }\n                            \n                            if (FLOWABLE.UI_CONFIG.showRemovedProperties == false && property.isHidden())\n                            {\n                              continue;\n                            }\n\n                            var currentProperty = {\n                                'key': key,\n                                'title': property.title(),\n                                'description': property.description(),\n                                'type': property.type(),\n                                'mode': 'read',\n                                'hidden': property.isHidden(),\n                                'value': selectedShape.properties.get(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                              currentProperty.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            editorManager.registerOnEvent(ORYX.CONFIG.EVENT_SELECTION_CHANGED, function (event) {\n              \n              FLOWABLE.eventBus.dispatch(FLOWABLE.eventBus.EVENT_TYPE_HIDE_SHAPE_BUTTONS);\n              var shapes = event.elements;\n                \n              if (shapes && shapes.length == 1) {\n\n              \t  var selectedShape = shapes.first();\n              \n                  var a = editorManager.getCanvas().node.getScreenCTM();\n              \n\t              var absoluteXY = selectedShape.absoluteXY();\n\t              \n\t              absoluteXY.x *= a.a;\n\t              absoluteXY.y *= a.d;\n\t              \n\t              var additionalIEZoom = 1;\n\t              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\t              if (additionalIEZoom === 1) {\n\t                   absoluteXY.y = absoluteXY.y - jQuery(\"#canvasSection\").offset().top + 5;\n\t                         absoluteXY.x = absoluteXY.x - jQuery(\"#canvasSection\").offset().left;\n\t              \n\t              } else {\n\t                   var canvasOffsetLeft = jQuery(\"#canvasSection\").offset().left;\n\t                   var canvasScrollLeft = jQuery(\"#canvasSection\").scrollLeft();\n\t                   var canvasScrollTop = jQuery(\"#canvasSection\").scrollTop();\n\t                   \n\t                   var offset = a.e - (canvasOffsetLeft * additionalIEZoom);\n\t                   var additionaloffset = 0;\n\t                   if (offset > 10) {\n\t                       additionaloffset = (offset / additionalIEZoom) - offset;\n\t                   }\n\t                   absoluteXY.y = absoluteXY.y - (jQuery(\"#canvasSection\").offset().top * additionalIEZoom) + 5 + ((canvasScrollTop * additionalIEZoom) - canvasScrollTop);\n\t                         absoluteXY.x = absoluteXY.x - (canvasOffsetLeft * additionalIEZoom) + additionaloffset + ((canvasScrollLeft * additionalIEZoom) - canvasScrollLeft);\n                  }\n\t              \n\t              var 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              var shapeXY = bounds.upperLeft();\n\t              \n\t              var stencilItem = $scope.getStencilItemById(selectedShape.getStencil().idWithoutNs());\n\t              var morphShapes = [];\n\t              if (stencilItem && stencilItem.morphRole) {\n\t                  for (var i = 0; i < $scope.morphRoles.length; i++) {\n\t\t\t\t\t\t  if ($scope.morphRoles[i].role === stencilItem.morphRole) {\n\t                    \t  morphShapes = $scope.morphRoles[i].morphOptions;\n\t                      }\n\t                  }\n\t              }\n              \n              \t  var x = shapeXY.x;\n            \t  if (bounds.width() < 48) {\n              \t\t  x -= 24;\n            \t  }\n              \n              \t  if (morphShapes && morphShapes.length > 0) {\n                \t// In case the element is not wide enough, start the 2 bottom-buttons more to the left\n                \t// to prevent overflow in the right-menu\n                \n                \tvar morphButton = document.getElementById('morph-button');\n                \tmorphButton.style.display = \"block\";\n                \tmorphButton.style.left = x + 24 +'px';\n                \tmorphButton.style.top = (shapeXY.y+bounds.height() + 2) + 'px';\n              \t  }\n              \n              \t  var deleteButton = document.getElementById('delete-button');\n              \t  deleteButton.style.display = \"block\";\n              \t  deleteButton.style.left = x + 'px';\n              \t  deleteButton.style.top = (shapeXY.y+bounds.height() + 2) + 'px';\n              \t  \n              \t  var editable = selectedShape._stencil._jsonStencil.id.endsWith('CollapsedSubProcess') ;\n\t\t\t\t  var editButton = document.getElementById('edit-button');\n\t\t\t\t  if (editable) {\n\t\t\t\t      editButton.style.display = \"block\";\n \t\t\t\t\t  if (morphShapes && morphShapes.length > 0) {\n\t\t\t\t\t\teditButton.style.left = x + 24 + 24 + 'px';\n\t\t\t\t      } else {\n\t\t\t\t\t \teditButton.style.left = x + 24 +'px';\n\t\t\t\t\t  }\n\t\t\t\t\t  editButton.style.top = (shapeXY.y+bounds.height() + 2) + 'px';\n\t\t\t\t\t  \n\t\t\t\t  } else {\n\t\t\t\t\t  editButton.style.display = \"none\";\n\t\t\t\t  }\n              \n              \t  if (stencilItem && (stencilItem.canConnect || stencilItem.canConnectAssociation)) {\n\t                var quickButtonCounter = 0;\n\t                var quickButtonX = shapeXY.x+bounds.width() + 5;\n\t                var quickButtonY = shapeXY.y;\n\t                jQuery('.Oryx_button').each(function(i, obj) {\n\t                  if (obj.id !== 'morph-button' && obj.id != 'delete-button' && obj.id !== 'edit-button') {\n\t                    quickButtonCounter++;\n\t                    if (quickButtonCounter > 3) {\n\t                      quickButtonX = shapeXY.x+bounds.width() + 5;\n\t                      quickButtonY += 24;\n\t                      quickButtonCounter = 1;\n\t                      \n\t                    } else if (quickButtonCounter > 1) {\n\t                      quickButtonX += 24;\n\t                    }\n\t                    \n\t                    obj.style.display = \"block\";\n\t                    obj.style.left = quickButtonX + 'px';\n\t                    obj.style.top = quickButtonY + 'px';\n\t                  }\n\t                });\n                  }\n               }\n            });\n            \n            if (!$rootScope.stencilInitialized) {\n              FLOWABLE.eventBus.addListener(FLOWABLE.eventBus.EVENT_TYPE_HIDE_SHAPE_BUTTONS, function (event) {\n                jQuery('.Oryx_button').each(function(i, obj) {\n                  obj.style.display = \"none\";\n              });\n              });\n\n              /*\n               * Listen to property updates and act upon them\n               */\n              FLOWABLE.eventBus.addListener(FLOWABLE.eventBus.EVENT_TYPE_PROPERTY_VALUE_CHANGED, function (event) {\n                  if (event.property && event.property.key) {\n                      // If the name property is been updated, we also need to change the title of the currently selected item\n                      if (event.property.key === 'oryx-name' && $scope.selectedItem !== undefined && $scope.selectedItem !== null) {\n                          $scope.selectedItem.title = event.newValue;\n                      }\n\n                      // Update \"no value\" flag\n                      event.property.noValue = (event.property.value === undefined\n                          || event.property.value === null\n                          || event.property.value.length == 0);\n                  }\n              });\n              \n              FLOWABLE.eventBus.addListener(FLOWABLE.eventBus.EVENT_TYPE_SHOW_VALIDATION_POPUP, function (event) {\n                  // Method to open validation dialog\n                  var showValidationDialog = function() {\n                      $rootScope.currentValidationId = event.validationId;\n                      $rootScope.isOnProcessLevel = event.onProcessLevel;\n\n                      _internalCreateModal({template: 'editor-app/popups/validation-errors.html?version=' + Date.now()},  $modal, $rootScope);\n                  };\n\n                  showValidationDialog();\n              });\n              \n              FLOWABLE.eventBus.addListener(FLOWABLE.eventBus.EVENT_TYPE_NAVIGATE_TO_PROCESS, function (event) {\n                  var modelMetaData = editorManager.getBaseModelData();\n                  $rootScope.editorHistory.push({\n                        id: modelMetaData.modelId, \n                        name: modelMetaData.name, \n                        type: 'bpmnmodel'\n                  });\n                  \n              \t  $window.location.href = \"../editor/#/editor/\" + event.processId;\n              });\n              \n              $rootScope.stencilInitialized = true;\n            }\n            \n            $scope.morphShape = function() {\n              $scope.safeApply(function () {\n                \n                var shapes = editorManager.getSelection();\n                if (shapes && shapes.length == 1) {\n                  $rootScope.currentSelectedShape = shapes.first();\n                  var stencilItem = $scope.getStencilItemById($rootScope.currentSelectedShape.getStencil().idWithoutNs());\n                  var morphShapes = [];\n                  for (var i = 0; i < $scope.morphRoles.length; i++) {\n                    if ($scope.morphRoles[i].role === stencilItem.morphRole) {\n                    \tmorphShapes = $scope.morphRoles[i].morphOptions.slice();\n                    }\n                  }\n\n                  // Method to open shape select dialog (used later on)\n                        var showSelectShapeDialog = function()\n                        {\n                            $rootScope.morphShapes = morphShapes;\n                            _internalCreateModal({\n                                backdrop: false,\n                                keyboard: true,\n                                template: 'editor-app/popups/select-shape.html?version=' + Date.now()\n                            },  $modal, $rootScope);\n                        };\n\n                        showSelectShapeDialog();\n                }\n              });\n            };\n            \n            $scope.deleteShape = function() {\n              FLOWABLE.TOOLBAR.ACTIONS.deleteItem({'$scope': $scope, 'editorManager': editorManager});\n            };\n            \n            $scope.quickAddItem = function(newItemId) {\n              $scope.safeApply(function () {\n                \n                var shapes = editorManager.getSelection();\n                if (shapes && shapes.length == 1) {\n                  $rootScope.currentSelectedShape = shapes.first();\n                  \n                  var containedStencil = undefined;\n                  var stencilSets = editorManager.getStencilSets().values();\n                  for (var i = 0; i < stencilSets.length; i++) {\n                    var stencilSet = stencilSets[i];\n                  \tvar nodes = stencilSet.nodes();\n                  \tfor (var j = 0; j < nodes.length; j++) {\n                    \tif (nodes[j].idWithoutNs() === newItemId) {\n                      \t    containedStencil = nodes[j];\n                      \t\tbreak;\n                    \t}\n                    }\n                  }\n                  \n                  if (!containedStencil) return;\n                  \n                  var option = {type: $scope.currentSelectedShape.getStencil().namespace() + newItemId, namespace: $scope.currentSelectedShape.getStencil().namespace()};\n                  option['connectedShape'] = $rootScope.currentSelectedShape;\n                  option['parent'] = $rootScope.currentSelectedShape.parent;\n                  option['containedStencil'] = containedStencil;\n                \n                  var args = { sourceShape: $rootScope.currentSelectedShape, targetStencil: containedStencil };\n                  var targetStencil = editorManager.getRules().connectMorph(args);\n                  \n                  // Check if there can be a target shape\n                  if (!targetStencil) { \n                  \treturn; \n                  }\n                  \n                  option['connectingType'] = targetStencil.id();\n\n                  var command = new FLOWABLE.CreateCommand(option, undefined, undefined, editorManager.getEditor());\n                \n                  editorManager.executeCommands([command]);\n                }\n              });\n            };\n            \n            $scope.editShape = function(){\n\t\t\t\teditorManager.edit($scope.selectedShape.resourceId);\n\t\t\t};\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.get(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 = editorManager.getEditor();\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                editorManager.executeCommands([command]);\n                editorManager.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: FLOWABLE.eventBus.EVENT_TYPE_PROPERTY_VALUE_CHANGED,\n                    property: property,\n                    oldValue: oldValue,\n                    newValue: newValue\n                };\n                FLOWABLE.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          \n            editorManager.handleEvents({\n                type: ORYX.CONFIG.EVENT_HIGHLIGHT_HIDE,\n                highlightId: \"shapeRepo.attached\"\n            });\n            editorManager.handleEvents({\n                type: ORYX.CONFIG.EVENT_HIGHLIGHT_HIDE,\n                highlightId: \"shapeRepo.added\"\n            });\n            \n            editorManager.handleEvents({\n                type: ORYX.CONFIG.EVENT_HIGHLIGHT_HIDE,\n                highlightId: \"shapeMenu\"\n            });\n            \n            FLOWABLE.eventBus.dispatch(FLOWABLE.eventBus.EVENT_TYPE_HIDE_SHAPE_BUTTONS);\n\n            if ($scope.dragCanContain) {\n\n              var item = $scope.getStencilItemById(ui.draggable[0].id);\n              \n              var pos = {x: event.pageX, y: 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              var screenCTM = editorManager.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 = editorManager.getStencilSets().values();\n              for (var i = 0; i < stencilSets.length; i++) {\n                var stencilSet = stencilSets[i];\n                var nodes = stencilSet.nodes();\n                for (var j = 0; j < nodes.length; j++) {\n                  if (nodes[j].idWithoutNs() === ui.draggable[0].id) {\n                    containedStencil = nodes[j];\n                    break;\n                  }\n                }\n\n                if (!containedStencil) {\n                  var edges = stencilSet.edges();\n                  for (var j = 0; j < edges.length; j++) {\n                  if (edges[j].idWithoutNs() === ui.draggable[0].id) {\n                    containedStencil = edges[j];\n                    break;\n                  }\n                }\n              }\n            }\n\n            if (!containedStencil) return;\n\n            if ($scope.quickMenu) {\n              var shapes = editorManager.getSelection();\n              if (shapes && shapes.length == 1) {\n                var currentSelectedShape = shapes.first();\n\n                var option = {};\n                option.type = currentSelectedShape.getStencil().namespace() + ui.draggable[0].id;\n                option.namespace = currentSelectedShape.getStencil().namespace();\n                option.connectedShape = currentSelectedShape;\n                option.parent = $scope.dragCurrentParent;\n                option.containedStencil = containedStencil;\n\t                \n                // If the ctrl key is not pressed, \n                // snapp the new shape to the center \n                // if it is near to the center of the other shape\n                if (!event.ctrlKey) {\n                  // Get the center of the shape\n                  var cShape = currentSelectedShape.bounds.center();\n                  // Snapp +-20 Pixel horizontal to the center \n                  if (20 > Math.abs(cShape.x - pos.x)) {\n                    pos.x = cShape.x;\n                  }\n                  // Snapp +-20 Pixel vertical to the center \n                  if (20 > Math.abs(cShape.y - pos.y)) {\n                    pos.y = cShape.y;\n                  }\n                }\n\t                \n                option.position = pos;\n\t              \n                if (containedStencil.idWithoutNs() !== 'SequenceFlow' && containedStencil.idWithoutNs() !== 'Association' && \n                        containedStencil.idWithoutNs() !== 'MessageFlow' && containedStencil.idWithoutNs() !== 'DataAssociation') {\n\t                        \n                  var args = { sourceShape: currentSelectedShape, targetStencil: containedStencil };\n                  var targetStencil = editorManager.getRules().connectMorph(args);\n                  if (!targetStencil) { // Check if there can be a target shape\n                  \treturn; \n                  }\n                  option.connectingType = targetStencil.id();\n                }\n\t  \n                var command = new FLOWABLE.CreateCommand(option, $scope.dropTargetElement, pos, editorManager.getEditor());\n\t              \n                editorManager.executeCommands([command]);\n              }\n\t                \n            } else {\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                    \n                // Modify position, otherwise boundary event will get position related to left corner of the canvas instead of the container\n                pos = editorManager.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 = 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, editorManager.getEditor());\n              editorManager.executeCommands([command]);\n\n              // Fire event to all who want to know about this\n              var dropEvent = {\n                  type: FLOWABLE.eventBus.EVENT_TYPE_ITEM_DROPPED,\n                  droppedItem: item,\n                  position: pos\n              };\n              FLOWABLE.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          \n            if ($scope.dragModeOver != false) {\n              \n                var coord = editorManager.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 = editorManager.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                    editorManager.getCanvas().setHightlightStateBasedOnX(coord.x);\n                }\n\n                if (aShapes.length == 1 && aShapes[0] instanceof ORYX.Core.Canvas) {\n                  \tvar item = $scope.getStencilItemById(event.target.id);\n                    var parentCandidate = aShapes[0];\n\n                    if (item.id === 'Lane' || item.id === 'BoundaryErrorEvent' || item.id === 'BoundaryMessageEvent' || \n                            item.id === 'BoundarySignalEvent' || item.id === 'BoundaryTimerEvent' ||\n                            item.id === 'BoundaryCancelEvent' || item.id === 'BoundaryCompensationEvent' || \n                            item.id === 'EntryCriterion') {\n                        \n                        $scope.dragCanContain = false;\n                        \n                        // Show Highlight\n                        editorManager.handleEvents({\n                            type: ORYX.CONFIG.EVENT_HIGHLIGHT_SHOW,\n                            highlightId: 'shapeRepo.added',\n                            elements: [parentCandidate],\n                            style: ORYX.CONFIG.SELECTION_HIGHLIGHT_STYLE_RECTANGLE,\n                            color: ORYX.CONFIG.SELECTION_INVALID_COLOR\n                        });\n                        \n                    } else {\n                        $scope.dragCanContain = true;\n                        $scope.dragCurrentParent = parentCandidate;\n                        $scope.dragCurrentParentId = parentCandidate.id;\n                        \n                        editorManager.handleEvents({\n                            type: ORYX.CONFIG.EVENT_HIGHLIGHT_HIDE,\n                            highlightId: \"shapeRepo.added\"\n                        });\n                    }\n\n                    editorManager.handleEvents({\n                        type: ORYX.CONFIG.EVENT_HIGHLIGHT_HIDE,\n                        highlightId: \"shapeRepo.attached\"\n                    });\n                    \n                    return false;\n                    \n                } else  {\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                                || item.roles.indexOf('EntryCriterionOnItemBoundary') > -1\n                                || item.roles.indexOf('ExitCriterionOnItemBoundary') > -1) {\n                                _canContain = true;\n                            }\n                            \n                        } else if(parentItem.roles.indexOf('StageActivity') > -1) {\n                            if (item.roles.indexOf('EntryCriterionOnItemBoundary') > -1\n                                || item.roles.indexOf('ExitCriterionOnItemBoundary') > -1) {\n                                _canContain = true;\n                            }\n                        \n                        } else if(parentItem.roles.indexOf('StageModelActivity') > -1) { \n                            if (item.roles.indexOf('ExitCriterionOnItemBoundary') > -1) {\n                                _canContain = true;\n                            }\n                        \n                        } else if (parentCandidate.getStencil().idWithoutNs() === 'Pool') {\n                          \tif (item.id === 'Lane') {\n                            \t_canContain = true;\n                          \t}\n                        }\n                        \n                        if (_canContain) {\n                            editorManager.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                            editorManager.handleEvents({\n                                type: ORYX.CONFIG.EVENT_HIGHLIGHT_HIDE,\n                                highlightId: \"shapeRepo.added\"\n                            });\n                            \n                        } else {\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                            editorManager.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                            editorManager.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                      var canvasCandidate = editorManager.getCanvas();\n                      var canConnect = false;\n                      \n                      var targetStencil = $scope.getStencilItemById(parentCandidate.getStencil().idWithoutNs());\n\t                  if (targetStencil) {\n\t                    var associationConnect = false;\n\t                    if (stencil.idWithoutNs() === 'Association' && (curCan.getStencil().idWithoutNs() === 'TextAnnotation' || curCan.getStencil().idWithoutNs() === 'BoundaryCompensationEvent')) {\n\t                        associationConnect = true;\n\t                    } else if (stencil.idWithoutNs() === 'DataAssociation' && curCan.getStencil().idWithoutNs() === 'DataStore') {\n                            associationConnect = true;\n                        }\n\t                    \n\t                    if (targetStencil.canConnectTo || associationConnect) {\n\t                      canConnect = true;\n\t                    }\n\t                  }\n                      \n                      //Edge\n                      $scope.dragCurrentParent = canvasCandidate;\n                      $scope.dragCurrentParentId = canvasCandidate.id;\n                      $scope.dragCurrentParentStencil = canvasCandidate.getStencil().id();\n                      $scope.dragCanContain = canConnect;\n                        \n                      // Show Highlight\n                      editorManager.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                      editorManager.handleEvents({\n                            type: ORYX.CONFIG.EVENT_HIGHLIGHT_HIDE,\n                            highlightId: \"shapeRepo.attached\"\n                      });\n              \t\t}\n                }\n            }\n        };\n        \n        $scope.dragCallbackQuickMenu = function (event, ui) {\n          \n            if ($scope.dragModeOver != false) {\n                var coord = editorManager.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 = editorManager.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                    editorManager.getCanvas().setHightlightStateBasedOnX(coord.x);\n                }\n                \n                var stencil = undefined;\n                var stencilSets = editorManager.getStencilSets().values();\n                for (var i = 0; i < stencilSets.length; i++) {\n                \tvar stencilSet = stencilSets[i];\n              \t\tvar nodes = stencilSet.nodes();\n              \t\tfor (var j = 0; j < nodes.length; j++) {\n                \t\tif (nodes[j].idWithoutNs() === event.target.id) {\n                  \t\t\tstencil = nodes[j];\n                  \t\t\tbreak;\n                \t\t}\n                    }\n              \n              \t\tif (!stencil) {\n                \t\tvar edges = stencilSet.edges();\n                  \t\tfor (var j = 0; j < edges.length; j++) {\n                    \t\tif (edges[j].idWithoutNs() === event.target.id) {\n                      \t\t\tstencil = edges[j];\n                      \t\t\tbreak;\n                    \t\t}\n                      \t}\n              \t\t}\n              \t}\n            \n                var candidate = aShapes.last();\n                \n                var isValid = false;\n                if (stencil.type() === \"node\")  {\n            \t\t//check containment rules\n            \t\tvar canContain = editorManager.getRules().canContain({containingShape:candidate, containedStencil:stencil});\n            \n            \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            \n            \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      \n          \t\t} else { //Edge\n          \n            \t\tvar shapes = editorManager.getSelection();\n                \tif (shapes && shapes.length == 1) {\n                  \t\tvar currentSelectedShape = shapes.first();\n                  \t\tvar curCan = candidate;\n                  \t\tvar canConnect = false;\n                  \n                  \t\tvar targetStencil = $scope.getStencilItemById(curCan.getStencil().idWithoutNs());\n                  \t\tif (targetStencil) {\n                    \t\tvar associationConnect = false;\n                    \t\tif (stencil.idWithoutNs() === 'Association' && (curCan.getStencil().idWithoutNs() === 'TextAnnotation' || curCan.getStencil().idWithoutNs() === 'BoundaryCompensationEvent')) {\n                      \t\t\tassociationConnect = true;\n                    \t\t} else if (stencil.idWithoutNs() === 'DataAssociation' && curCan.getStencil().idWithoutNs() === 'DataStore') {\n                        \t\tassociationConnect = true;\n                    \t\t}\n                    \n                    \t\tif (targetStencil.canConnectTo || associationConnect) {\n                    \t\t\twhile (!canConnect && curCan && !(curCan instanceof ORYX.Core.Canvas)) {\n                      \t\t\t\tcandidate = curCan;\n                      \t\t\t\t//check connection rules\n                      \t\t\t\tcanConnect = editorManager.getRules().canConnect({\n\t                                  sourceShape: currentSelectedShape, \n\t                                  edgeStencil: stencil, \n\t                                  targetShape: curCan\n\t                                }); \n                      \t\t\t\tcurCan = curCan.parent;\n                    \t\t\t}\n                    \t\t}\n                  \t\t}\n                  \t\tvar parentCandidate = editorManager.getCanvas();\n                \n                \t\tisValid = canConnect;\n                \t\t$scope.dragCurrentParent = parentCandidate;\n                        $scope.dragCurrentParentId = parentCandidate.id;\n                        $scope.dragCurrentParentStencil = parentCandidate.getStencil().id();\n                \t\t$scope.dragCanContain = canConnect;\n                \t\t$scope.dropTargetElement = candidate;\n                \t}   \n            \n          \t\t} \n\n                editorManager.handleEvents({\n          \t\t\ttype:   ORYX.CONFIG.EVENT_HIGHLIGHT_SHOW, \n          \t\t\thighlightId:'shapeMenu',\n          \t\t\telements: [candidate],\n          \t\t\tcolor: isValid ? ORYX.CONFIG.SELECTION_VALID_COLOR : ORYX.CONFIG.SELECTION_INVALID_COLOR\n        \t\t});\n            }\n        };\n\n    }]);\n\nvar FLOWABLE = FLOWABLE || {};\n//create command for undo/redo\nFLOWABLE.CreateCommand = ORYX.Core.Command.extend({\n  construct: function(option, currentReference, position, facade){\n    this.option = option;\n    this.currentReference = currentReference;\n    this.position = position;\n    this.facade = facade;\n    this.shape;\n    this.edge;\n    this.targetRefPos;\n    this.sourceRefPos;\n    /*\n     * clone options parameters\n     */\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  },      \n  execute: function(){\n    \n    if (this.shape) {\n      if (this.shape instanceof ORYX.Core.Node) {\n        this.parent.add(this.shape);\n        if (this.edge) {\n          this.facade.getCanvas().add(this.edge);\n          this.edge.dockers.first().setDockedShape(this.connectedShape);\n          this.edge.dockers.first().setReferencePoint(this.sourceRefPos);\n          this.edge.dockers.last().setDockedShape(this.shape);\n          this.edge.dockers.last().setReferencePoint(this.targetRefPos);\n        }\n        \n        this.facade.setSelection([this.shape]);\n        \n      } else if (this.shape instanceof ORYX.Core.Edge) {\n        this.facade.getCanvas().add(this.shape);\n        this.shape.dockers.first().setDockedShape(this.connectedShape);\n        this.shape.dockers.first().setReferencePoint(this.sourceRefPos);\n      }\n    }\n    else {\n      this.shape = this.facade.createShape(this.option);\n      this.edge = (!(this.shape instanceof ORYX.Core.Edge)) ? this.shape.getIncomingShapes().first() : undefined;\n    }\n    \n    if (this.currentReference && this.position) {\n      \n      if (this.shape instanceof ORYX.Core.Edge) {\n      \n        if (!(this.currentReference instanceof ORYX.Core.Canvas)) {\n          this.shape.dockers.last().setDockedShape(this.currentReference);\n          \n          if (this.currentReference.getStencil().idWithoutNs() === 'TextAnnotation')\n          {\n            var midpoint = {};\n            midpoint.x = 0;\n            midpoint.y = this.currentReference.bounds.height() / 2;\n            this.shape.dockers.last().setReferencePoint(midpoint);\n          }\n          else\n          {\n            this.shape.dockers.last().setReferencePoint(this.currentReference.bounds.midPoint());\n          }\n        }\n        else {\n          this.shape.dockers.last().bounds.centerMoveTo(this.position);\n        }\n        this.sourceRefPos = this.shape.dockers.first().referencePoint;\n        this.targetRefPos = this.shape.dockers.last().referencePoint;\n        \n      } else if (this.edge){\n        this.sourceRefPos = this.edge.dockers.first().referencePoint;\n        this.targetRefPos = this.edge.dockers.last().referencePoint;\n      }\n    } else {\n      var containedStencil = this.containedStencil;\n      var connectedShape = this.connectedShape;\n      var bc = connectedShape.bounds;\n      var bs = this.shape.bounds;\n      \n      var pos = bc.center();\n      if(containedStencil.defaultAlign()===\"north\") {\n        pos.y -= (bc.height() / 2) + ORYX.CONFIG.SHAPEMENU_CREATE_OFFSET + (bs.height()/2);\n      } else if(containedStencil.defaultAlign()===\"northeast\") {\n        pos.x += (bc.width() / 2) + ORYX.CONFIG.SHAPEMENU_CREATE_OFFSET_CORNER + (bs.width()/2);\n        pos.y -= (bc.height() / 2) + ORYX.CONFIG.SHAPEMENU_CREATE_OFFSET_CORNER + (bs.height()/2);\n      } else if(containedStencil.defaultAlign()===\"southeast\") {\n        pos.x += (bc.width() / 2) + ORYX.CONFIG.SHAPEMENU_CREATE_OFFSET_CORNER + (bs.width()/2);\n        pos.y += (bc.height() / 2) + ORYX.CONFIG.SHAPEMENU_CREATE_OFFSET_CORNER + (bs.height()/2);\n      } else if(containedStencil.defaultAlign()===\"south\") {\n        pos.y += (bc.height() / 2) + ORYX.CONFIG.SHAPEMENU_CREATE_OFFSET + (bs.height()/2);\n      } else if(containedStencil.defaultAlign()===\"southwest\") {\n        pos.x -= (bc.width() / 2) + ORYX.CONFIG.SHAPEMENU_CREATE_OFFSET_CORNER + (bs.width()/2);\n        pos.y += (bc.height() / 2) + ORYX.CONFIG.SHAPEMENU_CREATE_OFFSET_CORNER + (bs.height()/2);\n      } else if(containedStencil.defaultAlign()===\"west\") {\n        pos.x -= (bc.width() / 2) + ORYX.CONFIG.SHAPEMENU_CREATE_OFFSET + (bs.width()/2);\n      } else if(containedStencil.defaultAlign()===\"northwest\") {\n        pos.x -= (bc.width() / 2) + ORYX.CONFIG.SHAPEMENU_CREATE_OFFSET_CORNER + (bs.width()/2);\n        pos.y -= (bc.height() / 2) + ORYX.CONFIG.SHAPEMENU_CREATE_OFFSET_CORNER + (bs.height()/2);\n      } else {\n        pos.x += (bc.width() / 2) + ORYX.CONFIG.SHAPEMENU_CREATE_OFFSET + (bs.width()/2);\n      }\n      \n      // Move shape to the new position\n      this.shape.bounds.centerMoveTo(pos);\n      \n      // Move all dockers of a node to the position\n      if (this.shape instanceof ORYX.Core.Node){\n        (this.shape.dockers||[]).each(function(docker){\n          docker.bounds.centerMoveTo(pos);\n        });\n      }\n      \n      //this.shape.update();\n      this.position = pos;\n      \n      if (this.edge){\n        this.sourceRefPos = this.edge.dockers.first().referencePoint;\n        this.targetRefPos = this.edge.dockers.last().referencePoint;\n      }\n    }\n    \n    this.facade.getCanvas().update();\n    this.facade.updateSelection();\n\n  },\n  rollback: function(){\n    this.facade.deleteShape(this.shape);\n    if(this.edge) {\n      this.facade.deleteShape(this.edge);\n    }\n    //this.currentParent.update();\n    this.facade.setSelection(this.facade.getSelection().without(this.shape, this.edge));\n  }\n});\n"
  },
  {
    "path": "flowable-ui-web/modeler/editor-app/toolbar-controller.js",
    "content": "/* 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'use strict';\n\nangular.module('flowableModeler')\n    .controller('ToolbarController', ['$scope', '$http', '$modal', '$q', '$rootScope', '$translate', '$location', 'editorManager',\n    \t\tfunction ($scope, $http, $modal, $q, $rootScope, $translate, $location, editorManager) {\n\n    \t$scope.editorFactory.promise.then(function () {\n\t        var toolbarItems = FLOWABLE.TOOLBAR_CONFIG.items;\n\t        $scope.items = [];\n\t        \n\t        for (var i = 0; i < toolbarItems.length; i++)\n\t        {\n\t        \tif ($rootScope.modelData.model.modelType === 'form')\n\t\t        {\n\t\t        \tif (!toolbarItems[i].disableInForm)\n\t\t        \t{\n\t\t        \t\t$scope.items.push(toolbarItems[i]);\n\t\t        \t}\n\t\t        }\n\t        \telse\n\t        \t{\n\t        \t\t$scope.items.push(toolbarItems[i]);\n\t        \t}\n\t        }\n    \t});\n        \n        $scope.secondaryItems = FLOWABLE.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, 'editorManager' : editorManager};\n            executeFunctionByName(buttonClicked.action, window, services);\n\n            // Other events\n            var event = {\n                type : FLOWABLE.eventBus.EVENT_TYPE_TOOLBAR_BUTTON_CLICKED,\n                toolbarItem : buttonClicked\n            };\n            FLOWABLE.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, 'editorManager' : editorManager};\n            executeFunctionByName(buttonClicked.action, window, services);\n        };\n        \n        /* Key bindings */\n        Mousetrap.bind('mod+z', function(e) {\n        \tvar services = { '$scope' : $scope, '$rootScope' : $rootScope, '$http' : $http, '$modal' : $modal, '$q' : $q, '$translate' : $translate, 'editorManager' : editorManager};\n        \tFLOWABLE.TOOLBAR.ACTIONS.undo(services);\n            return false;\n        });\n        \n        Mousetrap.bind('mod+y', function(e) {\n        \tvar services = { '$scope' : $scope, '$rootScope' : $rootScope, '$http' : $http, '$modal' : $modal, '$q' : $q, '$translate' : $translate, 'editorManager' : editorManager};\n        \tFLOWABLE.TOOLBAR.ACTIONS.redo(services);\n            return false;\n        });\n        \n        Mousetrap.bind('mod+c', function(e) {\n        \tvar services = { '$scope' : $scope, '$rootScope' : $rootScope, '$http' : $http, '$modal' : $modal, '$q' : $q, '$translate' : $translate, 'editorManager' : editorManager};\n        \tFLOWABLE.TOOLBAR.ACTIONS.copy(services);\n            return false;\n        });\n        \n        Mousetrap.bind('mod+v', function(e) {\n        \tvar services = { '$scope' : $scope, '$rootScope' : $rootScope, '$http' : $http, '$modal' : $modal, '$q' : $q, '$translate' : $translate, 'editorManager' : editorManager};\n        \tFLOWABLE.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, 'editorManager' : editorManager};\n        \tFLOWABLE.TOOLBAR.ACTIONS.deleteItem(services);\n            return false;\n        });\n\n        /* Undo logic */\n\n        $scope.undoStack = [];\n        $scope.redoStack = [];\n        \n        FLOWABLE.eventBus.addListener(FLOWABLE.eventBus.EVENT_TYPE_UNDO_REDO_RESET,function($scope){\n\t\t\tthis.undoStack = [];\n\t\t\tthis.redoStack = [];\n\t\t\tif (this.items) {\n\t\t\t\tfor(var i = 0; i < this.items.length; i++) {\n\t\t\t\t\tvar item = this.items[i];\n\t\t\t\t\tif (item.action === 'FLOWABLE.TOOLBAR.ACTIONS.undo' || item.action === \"FLOWABLE.TOOLBAR.ACTIONS.redo\"){\n\t\t\t\t\t\titem.enabled = false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t},$scope);\n\n        $scope.editorFactory.promise.then(function() {\n\n            // Catch all command that are executed and store them on the respective stacks\n            editorManager.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 === 'FLOWABLE.TOOLBAR.ACTIONS.undo')\n                    {\n                    \titem.enabled = true;\n                    }\n                    else if (item.action === 'FLOWABLE.TOOLBAR.ACTIONS.redo')\n                    {\n                    \titem.enabled = false;\n                    }\n        \t\t}\n\n                // Update\n                editorManager.getCanvas().update();\n                editorManager.updateSelection();\n\n            });\n\n        });\n        \n        // Handle enable/disable toolbar buttons \n        $scope.editorFactory.promise.then(function() {\n        \teditorManager.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                    var item = $scope.items[i];\n                    if (item.enabledAction && item.enabledAction === 'element') {\n                    \tvar minLength = 1;\n                    \tif (item.minSelectionCount) {\n                    \t\tminLength = item.minSelectionCount;\n                    \t}\n                    \t\n                    \tif (elements.length >= minLength && !item.enabled) {\n                    \t\t$scope.safeApply(function () {\n                    \t\t\titem.enabled = true;\n                            });\n                    \t} else 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": "flowable-ui-web/modeler/editor-app/tour.js",
    "content": "/* 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\nvar FLOWABLE_EDITOR_TOUR = {\n\n    /*\n     * General 'getting started' tutorial for the Editor.\n     */\n    gettingStarted: function($scope, $translate, $q, useLocalStorage) {\n        var userName;\n        if ($scope.account.firstName) {\n            userName = $scope.account.firstName;\n        } else {\n            userName = $scope.account.fullname;\n        }\n\n        $q.all([\n            $translate('TOUR.WELCOME-TITLE', {userName: userName}), $translate('TOUR.WELCOME-CONTENT'),\n            $translate('TOUR.PALETTE-TITLE'), $translate('TOUR.PALETTE-CONTENT'),\n            $translate('TOUR.CANVAS-TITLE'), $translate('TOUR.CANVAS-CONTENT'),\n            $translate('TOUR.DRAGDROP-TITLE'), $translate('TOUR.DRAGDROP-CONTENT'),\n            $translate('TOUR.PROPERTIES-TITLE'), $translate('TOUR.PROPERTIES-CONTENT'),\n            $translate('TOUR.TOOLBAR-TITLE'), $translate('TOUR.TOOLBAR-CONTENT'),\n            $translate('TOUR.END-TITLE'), $translate('TOUR.END-CONTENT')\n        ]).then(function(translations) {\n\n            // We're using a hack here due to https://github.com/sorich87/bootstrap-tour/issues/85:\n            // when clicking next in the tour, it always sets the 'display' css property to 'none'\n            // The hack is simple: before the next step is shown, we reset the 'display' property to 'block'\n\n            var tourStepDomElements = ['body', '#paletteHelpWrapper', '#canvasHelpWrapper', '#propertiesHelpWrapper', '#editor-header'];\n\n            var tour = new Tour({\n                name: 'activitiEditorTour',\n                storage: (useLocalStorage ? window.localStorage : false),\n                container: 'body',\n                backdrop: true,\n                keyboard: true,\n                steps: [\n                    {\n                        orphan: true,\n                        title: translations[0],\n                        content: translations[1],\n                        template: FLOWABLE_EDITOR_TOUR._buildStepTemplate(false, true, false, 300),\n                        onNext: FLOWABLE_EDITOR_TOUR._buildOnNextFunction(tourStepDomElements[0])\n                    },\n                    {\n                        element: tourStepDomElements[1],\n                        title: translations[2],\n                        content: translations[3],\n                        template: FLOWABLE_EDITOR_TOUR._buildStepTemplate(false, true, false, 400, 'images/tour/open-group.gif'),\n                        onNext: FLOWABLE_EDITOR_TOUR._buildOnNextFunction(tourStepDomElements[1])\n                    },\n                    {\n                        element: tourStepDomElements[2],\n                        title: translations[4],\n                        content: translations[5],\n                        placement: 'left',\n                        template: FLOWABLE_EDITOR_TOUR._buildStepTemplate(false, true, false),\n                        onNext: FLOWABLE_EDITOR_TOUR._buildOnNextFunction(tourStepDomElements[2])\n                    },\n                    {\n                        orphan: true,\n                        title: translations[6],\n                        content: translations[7],\n                        template: FLOWABLE_EDITOR_TOUR._buildStepTemplate(false, true, false, 720, 'images/tour/tour-dnd.gif'),\n                        onNext: FLOWABLE_EDITOR_TOUR._buildOnNextFunction(tourStepDomElements[0])\n                    },\n                    {\n                        element: tourStepDomElements[3],\n                        title: translations[8],\n                        content: translations[9],\n                        placement: 'top',\n                        template: FLOWABLE_EDITOR_TOUR._buildStepTemplate(false, true, false, 400),\n                        onNext: FLOWABLE_EDITOR_TOUR._buildOnNextFunction(tourStepDomElements[3])\n                    },\n                    {\n                        element: tourStepDomElements[4],\n                        title: translations[10],\n                        content: translations[11],\n                        placement: 'bottom',\n                        template: FLOWABLE_EDITOR_TOUR._buildStepTemplate(false, true, false, 400),\n                        onNext: FLOWABLE_EDITOR_TOUR._buildOnNextFunction(tourStepDomElements[4])\n                    },\n                    {\n                        orphan: true,\n                        title: translations[12],\n                        content: translations[13],\n                        template: FLOWABLE_EDITOR_TOUR._buildStepTemplate(false, false, true, 400),\n                        onNext: FLOWABLE_EDITOR_TOUR._buildOnNextFunction(tourStepDomElements[0])\n                    }\n                ],\n\n                onEnd: FLOWABLE_EDITOR_TOUR._buildOnEndFunction(tourStepDomElements)\n            });\n\n            tour.init();\n            tour.start();\n        })\n    },\n\n    /*\n     * Tutorial showing how to use the bendpoint functionality for sequenceflow\n     */\n    sequenceFlowBendpoint: function($scope, $translate, $q, useLocalStorage) {\n\n        $q.all([\n            $translate('FEATURE-TOUR.BENDPOINT.TITLE'), $translate('FEATURE-TOUR.BENDPOINT.DESCRIPTION')\n        ]).then(function(translations) {\n\n            // We're using a hack here due to https://github.com/sorich87/bootstrap-tour/issues/85:\n            // when clicking next in the tour, it always sets the 'display' css property to 'none'\n            // The hack is simple: before the next step is shown, we reset the 'display' property to 'block'\n\n            var tourStepDomElements = ['body'];\n\n            var tour = new Tour({\n                name: 'bendpointTour',\n                storage: (useLocalStorage ? window.localStorage : false),\n                container: 'body',\n                backdrop: true,\n                keyboard: true,\n                steps: [\n                    {\n                        orphan: true,\n                        title: translations[0],\n                        content: translations[1],\n                        template: FLOWABLE_EDITOR_TOUR._buildStepTemplate(false, false, true, 500, 'images/tour/sequenceflow-bendpoint.gif'),\n                        onNext: FLOWABLE_EDITOR_TOUR._buildOnNextFunction(tourStepDomElements[0])\n                    }\n                ],\n\n                onEnd: FLOWABLE_EDITOR_TOUR._buildOnEndFunction(tourStepDomElements)\n            });\n\n            tour.init();\n            tour.start();\n        })\n    },\n\n\n\n    _buildStepTemplate : function (addPrevButton, addNextButton, addEndTourButton, optionalForcedWidth, image) {\n\n        var width = 200;\n        if (optionalForcedWidth) {\n            width = optionalForcedWidth;\n        }\n\n        var template =\n            '<div class=\\'popover tour\\' style=\\'max-width:' + width + 'px\\'>' +\n            '<div class=\\'arrow\\'></div>' +\n            '<h3 class=\\'popover-title\\'></h3>' +\n            '<div class=\\'popover-content\\'></div>' +\n            '<div class=\\'popover-navigation\\'>';\n        if (image) {\n            template = template + '<div><img src=\\'' + image + '\\' style=\\'border 1px solid black;margin:5px 0 5px 0;\\'></img></div>';\n        }\n        if (addPrevButton) {\n            template = template + '<button class=\\'btn btn-sm btn-default \\' data-role=\\'prev\\'>« Prev</button>';\n        }\n        if (addNextButton) {\n            template = template + '<button class=\\'btn btn-sm btn-default\\' data-role=\\'next\\' style=\\'float:right\\'\">Next »</button>';\n        }\n        if (addEndTourButton) {\n            template = template + '<button class=\\'btn btn-warning btn-sm\\' data-role=\\'end\\' style=\\'float:right\\'\">Got it!</button>';\n        }\n\n        template = template + '</div>' + '</nav>' + '</div>';\n        return template;\n    },\n\n    _buildOnNextFunction: function(selector) {\n        return function () {\n            jQuery(selector).each(function (i, obj) {\n                obj.style.display = 'block';\n            })\n        };\n    },\n\n    _buildOnEndFunction: function(selectors) {\n        return function () {\n            for (var elementsToResetIndex = 0; elementsToResetIndex < selectors.length; elementsToResetIndex++) {\n                jQuery(selectors[elementsToResetIndex]).each(function (i, obj) {\n                    obj.style.display = 'block';\n                });\n            }\n        }\n    }\n\n};\n"
  },
  {
    "path": "flowable-ui-web/modeler/i18n/en.json",
    "content": "{\n    \"GENERAL\" : {\n        \"MAIN-TITLE\": \"Flowable Editor\",\n        \"NAVIGATION\" : {\n            \"PROCESSES\": \"Processes\",\n            \"CASEMODELS\": \"Case models\",\n            \"FORMS\": \"Forms\",\n            \"DECISION-TABLES\": \"Decision Tables\",\n            \"APPS\": \"Apps\"\n        },\n        \"TITLE\": {\n            \"SELECT-GROUP\" :\"Select group\",\n            \"MATCHING-GROUPS\": \"Matching groups\",\n            \"FILTER\": \"Filter\",\n            \"HISTORY\": \"History\"\n        },\n        \"ACTION\": {\n            \"LOGOUT\": \"Sign out\",\n            \"RETURN-TO-LIST\": \"Show all definitions\",\n            \"CANCEL\": \"Cancel\",\n            \"CLOSE\": \"Close\",\n            \"EDIT\": \"Edit\",\n            \"SAVE\": \"Save\",\n            \"OPEN\": \"Open\",\n            \"OK\": \"Ok\",\n            \"CONFIRM\": \"Confirm\",\n            \"CONFIRM-AND-CLOSE\": \"Confirm and close\",\n            \"NEW-FORM\": \"New form\",\n            \"CREATE-FORM\": \"Create form\",\n            \"NEW-DECISION-TABLE\": \"New Decision Table\",\n            \"CREATE-DECISION-TABLE\": \"Create Decision Table\"\n        },\n        \"MESSAGE\": {\n          \"SELECT-GROUP-HELP\": \"Use &uparrow; and &downarrow; to select and press Enter to confirm\",\n          \"PEOPLE-NO-MATCHING-RESULTS\": \"No matching users were found\",\n          \"GROUP-NO-MATCHING-RESULTS\": \"No matching groups were found\",\n          \"GROUP-SOURCE-TYPE\": \"Group source\",\n          \"GROUP-SOURCE-SEARCH-OPTION\": \"Group search\",\n          \"GROUP-SOURCE-FIELD-OPTION\": \"Form field\"\n        }\n    },\n\n    \"EDITOR\": {\n      \"POPUP\": {\n        \"UNSAVED-CHANGES\": {\n          \"TITLE\": \"You have unsaved changes\",\n          \"DESCRIPTION\": \"What do you want to do with your unsaved changes?\",\n          \"ACTION\": {\n            \"SAVE\": \"Save changes\",\n            \"DISCARD\": \"Discard changes\",\n            \"CONTINUE\": \"Continue editing\"\n          }\n        }\n      }\n    },\n\n    \"PROCESS-LIST\" : {\n        \"TITLE\" : \"Business Process Models\",\n        \"SEARCH-PLACEHOLDER\": \"Search\",\n        \"ACTION\" : {\n            \"CREATE\": \"Create Process\",\n            \"IMPORT\": \"Import Process\"\n        },\n\n        \"FILTER\" : {\n            \"PROCESSES\": \"Process models\",\n            \"PROCESSES-COUNT\": \"There are {{total}} process models\",\n            \"PROCESSES-ONE\": \"There is one process model\",\n            \"PROCESSES-EMPTY\": \"There is no process model created yet. You can design process models, user forms and then bundle them up into a process app. The first step is to create a process model:\",\n            \"PROCESSES-BPMN-HINT\": \"Create a BPMN model using the BPMN Visual Editor.\",\n            \"PROCESSES-BPMN-IMPORT-HINT\": \"You can also import existing BPMN models.\",\n            \"FILTER-TEXT\": \", matching \\\"{{filterText}}\\\"\",\n            \"FILTER-TEXT-EMPTY\": \"There are no process models matching \\\"{{filterText}}\\\"\",\n            \"RECENT\": \"Recent\",\n            \"RECENT-COUNT\": \"{{total}} recently used models\",\n            \"RECENT-ONE\": \"One recently used models\",\n            \"RECENT-EMPTY\": \"No recently used models\"\n        },\n\n        \"SORT\": {\n            \"MODIFIED-ASC\": \"Oldest\",\n            \"MODIFIED-DESC\": \"Last modified\",\n            \"NAME-ASC\": \"Name, A-Z\",\n            \"NAME-DESC\": \"Name, Z-A\"\n        }\n    },\n    \n    \"CASE-LIST\" : {\n        \"TITLE\" : \"Case Models\",\n        \"SEARCH-PLACEHOLDER\": \"Search\",\n        \"ACTION\" : {\n            \"CREATE\": \"Create Case\",\n            \"IMPORT\": \"Import Case\"\n        },\n\n        \"FILTER\" : {\n            \"CASES\": \"Case models\",\n            \"CASES-COUNT\": \"There are {{total}} case models\",\n            \"CASES-ONE\": \"There is one case model\",\n            \"CASES-EMPTY\": \"There is no case model created yet. You can design case models, user forms and then bundle them up into an app definition. The first step is to create a case model:\",\n            \"CASES-CMMN-HINT\": \"Create a CMMN model using the CMMN Visual Editor.\",\n            \"CASES-CMMN-IMPORT-HINT\": \"You can also import existing CMMN models.\",\n            \"FILTER-TEXT\": \", matching \\\"{{filterText}}\\\"\",\n            \"FILTER-TEXT-EMPTY\": \"There are no case models matching \\\"{{filterText}}\\\"\",\n            \"RECENT\": \"Recent\",\n            \"RECENT-COUNT\": \"{{total}} recently used models\",\n            \"RECENT-ONE\": \"One recently used models\",\n            \"RECENT-EMPTY\": \"No recently used models\"\n        },\n\n        \"SORT\": {\n            \"MODIFIED-ASC\": \"Oldest\",\n            \"MODIFIED-DESC\": \"Last modified\",\n            \"NAME-ASC\": \"Name, A-Z\",\n            \"NAME-DESC\": \"Name, Z-A\"\n        }\n    },\n\n    \"FORMS-LIST\" : {\n        \"TITLE\" : \"Forms\",\n        \"SEARCH-PLACEHOLDER\": \"Search\",\n        \"ACTION\" : {\n            \"CREATE\": \"Create Form\",\n            \"CREATE-INLINE\": \"Create a new form now!\",\n            \"SHOW-MORE\": \"Show more...\"\n        },\n\n        \"FILTER\" : {\n            \"FORMS\": \"Forms\",\n            \"FORMS-COUNT\": \"There are {{total}} forms\",\n            \"FORMS-ONE\": \"There is one form\",\n            \"FORMS-EMPTY\": \"There are no forms.  To add one, click Create Form.\",\n            \"FILTER-TEXT\": \", matching \\\"{{filterText}}\\\"\",\n            \"FILTER-TEXT-EMPTY\": \"There is no form matching \\\"{{filterText}}\\\"\"\n        },\n\n        \"SORT\": {\n            \"MODIFIED-ASC\": \"Oldest\",\n            \"MODIFIED-DESC\": \"Last modified\",\n            \"NAME-ASC\": \"Name, A-Z\",\n            \"NAME-DESC\": \"Name, Z-A\"\n        }\n    },\n\n    \"DECISION-TABLES-LIST\": {\n        \"TITLE\": \"Decision Tables\",\n        \"SEARCH-PLACEHOLDER\": \"Search\",\n        \"ACTION\": {\n            \"CREATE\": \"Create Decision Table\",\n            \"IMPORT\": \"Import Decision Table\",\n            \"CREATE-INLINE\": \"Create a new decision table now!\",\n            \"SHOW-MORE\": \"Show more...\"\n        },\n\n        \"FILTER\": {\n            \"DECISION-TABLES\": \"Decision tables\",\n            \"DECISION-TABLES-COUNT\": \"There are {{total}} decision tables\",\n            \"DECISION-TABLES-ONE\": \"There is one decision table\",\n            \"DECISION-TABLES-EMPTY\": \"There are no decision tables. To add one, click Create Decision Table.\",\n            \"FILTER-TEXT\": \", matching \\\"{{filterText}}\\\"\",\n            \"FILTER-TEXT-EMPTY\": \"There are no decision table matching \\\"{{filterText}}\\\"\"\n        },\n\n        \"SORT\": {\n            \"MODIFIED-ASC\": \"Oldest\",\n            \"MODIFIED-DESC\": \"Last modified\",\n            \"NAME-ASC\": \"Name, A-Z\",\n            \"NAME-DESC\": \"Name, Z-A\"\n        }\n    },\n\n    \"APPS-LIST\" : {\n        \"TITLE\" : \"App definitions\",\n        \"SEARCH-PLACEHOLDER\": \"Search\",\n        \"ACTION\" : {\n            \"CREATE\": \"Create App\",\n            \"IMPORT\": \"Import App\",\n            \"SHOW-MORE\": \"Show more...\"\n        },\n\n        \"FILTER\" : {\n            \"APPS\": \"App definitions\",\n            \"APPS-COUNT\": \"There are {{total}} app definitions\",\n            \"APPS-ONE\": \"There is one app definition\",\n            \"APPS-EMPTY\": \"There are no app definitions. To add one, click Create App Definition.\",\n            \"FILTER-TEXT\": \", matching \\\"{{filterText}}\\\"\",\n            \"FILTER-TEXT-EMPTY\": \"There are no app definitions matching \\\"{{filterText}}\\\"\",\n\n            \"NO-APPS\": \"You can create an App definition by publishing a bundle of Process Models.\",\n            \"NO-APPS-CALL-TO-ACTION\": \"You can create an App definition now.\",\n            \"NO-APPS-NOTE\": \"Remember to Publish it when you are ready to use it.\"\n        },\n\n        \"SORT\": {\n            \"MODIFIED-ASC\": \"Oldest\",\n            \"MODIFIED-DESC\": \"Last modified\",\n            \"NAME-ASC\": \"Name, A-Z\",\n            \"NAME-DESC\": \"Name, Z-A\"\n        }\n    },\n    \"PROCESS\": {\n      \"NAME\": \"Model name\",\n      \"KEY\": \"Model key\",\n      \"DESCRIPTION\": \"Description\",\n      \"VERSION-COMMENT\": \"Version comment\",\n      \"ACTION\": {\n            \"DETAILS\": \"Show details\",\n            \"EDIT\": \"Modify model properties\",\n            \"DUPLICATE\": \"Duplicate this model\",\n            \"EXPORT_BPMN20\": \"Export to BPMN 2.0\",\n            \"DELETE\": \"Delete this model\",\n            \"CREATE-CONFIRM\": \"Create new model\",\n            \"DUPLICATE-CONFIRM\": \"Duplicate the model\",\n            \"OPEN-IN-EDITOR\": \"Visual Editor\",\n            \"EDIT-CONFIRM\": \"Save\",\n            \"DELETE-CONFIRM\": \"Delete process model\",\n            \"USE-AS-NEW-VERSION\": \"Use as new version\",\n            \"FAVORITE\": \"Favorite this model\"\n\n        },\n        \"DETAILS\": {\n          \"HISTORY-TITLE\": \"History\",\n          \"LAST-UPDATED-BY\": \"Last updated by {{lastUpdatedBy}} - {{lastUpdated | dateformat}}\",\n          \"CREATED-BY\": \"Created by {{createdBy}}\",\n          \"NO-DESCRIPTION\": \"This model has no description. Modify the model properties to add one\"\n        },\n\n        \"POPUP\": {\n          \"CREATE-TITLE\": \"Create a new business process model\",\n          \"DUPLICATE-TITLE\": \"Duplicate the business process model\",\n          \"CREATE-DESCRIPTION\": \"You need to give a name for the new model and you may want to add a description at the same time.\",\n          \"DUPLICATE-DESCRIPTION\": \"You can change the name for the new model and you may want to change the description at the same time.\",\n          \"EDIT-DESCRIPTION\": \"Change any of the model properties below and then press Save to update the model.\",\n          \"DELETE-DESCRIPTION\": \"Are you sure you want to delete the process model \\\"{{name}}\\\"?\",\n          \"EDIT-TITLE\":\"Edit model details\",\n          \"DELETE-TITLE\": \"Delete model\",\n          \"DELETE-LOADING-RELATIONS\": \"Checking model usage...\",\n          \"DELETE-RELATIONS-DESCRIPTION-SINGLE\": \"This model cannot be deleted, because another model is using it:\",\n          \"DELETE-RELATIONS-DESCRIPTION\": \"This model cannot be deleted, because it is used by other models:\",\n          \"DELETE-PROCESS-RELATION\": \"Process model\",\n          \"DELETE-FORM-RELATION\": \"Form model\",\n          \"DELETE-APP-RELATION\": \"App model\",\n          \"IMPORT-DESCRIPTION\": \"Please browse for or drop a BPMN XML definition with an .bpmn or .bpmn20.xml extension\",\n          \"IMPORT-TITLE\": \"Import a process model\",\n          \"USE-AS-NEW-TITLE\": \"Use as new version\",\n          \"USE-AS-NEW-DESCRIPTION\": \"Are you sure you want to use version {{version}} to create a new version of \\\"{{name}}\\\"?\",\n          \"USE-AS-NEW-UNRESOLVED-MODELS-ERROR\": \"Could not fully restore the app model to the chosen version: some referenced models are missing due to being deleted in the past. Please update the app model accordingly. Missing models:\",\n          \"USE-AS-NEW-UNRESOLVED-MODEL\": \"Model '{{name}}' with internal id {{id}}, created by {{createdBy}}\",\n          \"SHARED-WITH\": \"Shared with\",\n          \"PERMISSION\": \"Permission\",\n          \"ACTIONS\": \"Actions\",\n          \"IMPORT\": {\n              \"DROPZONE\": \"Drop a .bpmn or .bpmn20.xml BPMN XML file\",\n              \"CANCEL-UPLOAD\": \"Cancel the upload\",\n              \"ERROR\": \"Error while processing the BPMN XML file\",\n              \"NO-DROP\": \"Drag and drop not supported\"\n          }\n        },\n        \"ALERT\": {\n          \"EDIT-CONFIRM\": \"Model updated\"\n        },\n        \"ERROR\": {\n          \"NOT-FOUND\": \"The requested model does not exist\"\n        }\n    },\n\n    \"SUBPROCESS\": {\n        \"NAME\": \"Sub process name\",\n        \"DESCRIPTION\": \"Description\",\n        \"ACTION\": {\n            \"CREATE-CONFIRM\": \"Create new sub process\"\n        },\n        \"POPUP\": {\n            \"CREATE-TITLE\": \"Create a new sub process\",\n            \"CREATE-DESCRIPTION\": \"You need to give a name for the new sub process and you may want to add a description at the same time.\"\n        }\n    },\n    \n    \"CASE\": {\n      \"NAME\": \"Model name\",\n      \"KEY\": \"Model key\",\n      \"DESCRIPTION\": \"Description\",\n      \"VERSION-COMMENT\": \"Version comment\",\n      \"ACTION\": {\n            \"DETAILS\": \"Show details\",\n            \"EDIT\": \"Modify model properties\",\n            \"DUPLICATE\": \"Duplicate this model\",\n            \"EXPORT_CMMN\": \"Export to CMMN 1.1\",\n            \"DELETE\": \"Delete this model\",\n            \"CREATE-CONFIRM\": \"Create new model\",\n            \"DUPLICATE-CONFIRM\": \"Duplicate the model\",\n            \"OPEN-IN-EDITOR\": \"Visual Editor\",\n            \"EDIT-CONFIRM\": \"Save\",\n            \"DELETE-CONFIRM\": \"Delete case model\",\n            \"USE-AS-NEW-VERSION\": \"Use as new version\",\n            \"FAVORITE\": \"Favorite this model\"\n\n        },\n        \"DETAILS\": {\n          \"HISTORY-TITLE\": \"History\",\n          \"LAST-UPDATED-BY\": \"Last updated by {{lastUpdatedBy}} - {{lastUpdated | dateformat}}\",\n          \"CREATED-BY\": \"Created by {{createdBy}}\",\n          \"NO-DESCRIPTION\": \"This model has no description. Modify the model properties to add one\"\n        },\n\n        \"POPUP\": {\n          \"CREATE-TITLE\": \"Create a new case model\",\n          \"DUPLICATE-TITLE\": \"Duplicate the case model\",\n          \"CREATE-DESCRIPTION\": \"You need to give a name for the new model and you may want to add a description at the same time.\",\n          \"DUPLICATE-DESCRIPTION\": \"You can change the name for the new model and you may want to change the description at the same time.\",\n          \"EDIT-DESCRIPTION\": \"Change any of the model properties below and then press Save to update the model.\",\n          \"DELETE-DESCRIPTION\": \"Are you sure you want to delete the process model \\\"{{name}}\\\"?\",\n          \"EDIT-TITLE\":\"Edit model details\",\n          \"DELETE-TITLE\": \"Delete model\",\n          \"DELETE-LOADING-RELATIONS\": \"Checking model usage...\",\n          \"DELETE-RELATIONS-DESCRIPTION-SINGLE\": \"This model cannot be deleted, because another model is using it:\",\n          \"DELETE-RELATIONS-DESCRIPTION\": \"This model cannot be deleted, because it is used by other models:\",\n          \"DELETE-PROCESS-RELATION\": \"Case model\",\n          \"DELETE-FORM-RELATION\": \"Form model\",\n          \"DELETE-APP-RELATION\": \"App model\",\n          \"IMPORT-DESCRIPTION\": \"Please browse for or drop a CMMN XML definition with an .cmmn or .cmmn.xml extension\",\n          \"IMPORT-TITLE\": \"Import a case model\",\n          \"USE-AS-NEW-TITLE\": \"Use as new version\",\n          \"USE-AS-NEW-DESCRIPTION\": \"Are you sure you want to use version {{version}} to create a new version of \\\"{{name}}\\\"?\",\n          \"USE-AS-NEW-UNRESOLVED-MODELS-ERROR\": \"Could not fully restore the app model to the chosen version: some referenced models are missing due to being deleted in the past. Please update the app model accordingly. Missing models:\",\n          \"USE-AS-NEW-UNRESOLVED-MODEL\": \"Model '{{name}}' with internal id {{id}}, created by {{createdBy}}\",\n          \"SHARED-WITH\": \"Shared with\",\n          \"PERMISSION\": \"Permission\",\n          \"ACTIONS\": \"Actions\",\n          \"IMPORT\": {\n              \"DROPZONE\": \"Drop a .cmmn or .cmmn.xml CMMN XML file\",\n              \"CANCEL-UPLOAD\": \"Cancel the upload\",\n              \"ERROR\": \"Error while processing the CMMN XML file\",\n              \"NO-DROP\": \"Drag and drop not supported\"\n          }\n        },\n        \"ALERT\": {\n          \"EDIT-CONFIRM\": \"Model updated\"\n        },\n        \"ERROR\": {\n          \"NOT-FOUND\": \"The requested model does not exist\"\n        }\n    },\n\n    \"FORM\": {\n      \"NAME\": \"Form name\",\n      \"KEY\": \"Form key\",\n      \"DESCRIPTION\": \"Description\",\n      \"ACTION\": {\n            \"DETAILS\": \"Show details\",\n            \"EDIT\": \"Modify model properties\",\n            \"DELETE\": \"Delete this form\",\n            \"CREATE-CONFIRM\": \"Create new form\",\n            \"DUPLICATE\": \"Duplicate this form\",\n            \"DUPLICATE-CONFIRM\": \"Duplicate the form\",\n            \"OPEN-IN-EDITOR\": \"Form Editor\",\n            \"EDIT-CONFIRM\": \"Save\",\n            \"DELETE-CONFIRM\": \"Delete form\",\n            \"USE-AS-NEW-VERSION\": \"Use as new version\"\n\n        },\n        \"DETAILS\": {\n          \"HISTORY-TITLE\": \"History\",\n          \"LAST-UPDATED-BY\": \"Last updated by {{lastUpdatedBy}} - {{lastUpdated | dateformat}}\",\n          \"CREATED-BY\": \"Created by {{createdBy}}\"\n        },\n\n        \"POPUP\": {\n          \"CREATE-TITLE\": \"Create a new form\",\n          \"DUPLICATE-TITLE\": \"Duplicate form\",\n          \"CREATE-DESCRIPTION\": \"You need to give a name for the new form and you may want to add a description at the same time.\",\n          \"DUPLICATE-DESCRIPTION\": \"You need to give a name for the new form and you may want to add a description at the same time.\",\n          \"SAVE-FORM-TITLE\": \"Save form\",\n          \"EDIT-DESCRIPTION\": \"Change any of the form properties below and then press Save to update the form.\",\n          \"DELETE-DESCRIPTION\": \"Are you sure you want to delete the form \\\"{{name}}\\\"?\",\n          \"EDIT-TITLE\":\"Edit form details\",\n          \"DELETE-TITLE\": \"Delete form\",\n          \"USE-AS-NEW-TITLE\": \"Use as new version\",\n          \"USE-AS-NEW-VERSION\": \"Use as new version\",\n          \"USE-AS-NEW-DESCRIPTION\": \"Are you sure you want to use version {{version}} to create a new version of \\\"{{name}}\\\"?\",\n          \"USE-AS-NEW-UNRESOLVED-MODELS-ERROR\": \"Could not fully restore the app model to the chosen version: some referenced models are missing due to being deleted in the past. Please update the app model accordingly. Missing models:\",\n          \"USE-AS-NEW-UNRESOLVED-MODEL\": \"Model '{{name}}' with internal id {{id}}, created by {{createdBy}}\"\n        }\n    },\n\n    \"DECISION-TABLE\": {\n        \"NAME\": \"Decision Table name\",\n        \"KEY\": \"Decision Table key\",\n        \"DESCRIPTION\": \"Description\",\n        \"VERSION-COMMENT\": \"Version comment\",\n        \"HIT-POLICY\": \"Hit Policy:\",\n        \"ACTION\": {\n            \"DETAILS\": \"Show details\",\n            \"EDIT\": \"Modify model properties\",\n            \"SHARE\": \"Share this decision table\",\n            \"DELETE\": \"Delete this decision table\",\n            \"ADD-COMMENT\": \"+ Add comment\",\n            \"CREATE-CONFIRM\": \"Create new decision table\",\n            \"OPEN-IN-EDITOR\": \"Decision Table Editor\",\n            \"EXPORT\": \"Export decision table\",\n            \"DELETE-CONFIRM\": \"Delete decision table\",\n            \"USE-AS-NEW-VERSION\": \"Use as new version\",\n            \"FAVORITE\": \"Favorite this decision table\",\n            \"DUPLICATE\": \"Duplicate this decision table\"\n        },\n        \"DETAILS\": {\n            \"HISTORY-TITLE\": \"History\",\n            \"COMMENTS-TITLE\": \"Comments\",\n            \"LAST-UPDATED-BY\": \"Last updated by {{lastUpdatedBy}} - {{lastUpdated | dateformat}}\",\n            \"CREATED-BY\": \"Created by {{createdBy}}\"\n        },\n        \"HIT-POLICIES\": {\n            \"FIRST\": \"First\",\n            \"ANY\": \"Any\",\n            \"UNIQUE\": \"Unique\",\n            \"PRIORITY\": \"Priority\",\n            \"RULE ORDER\": \"Rule Order\",\n            \"OUTPUT ORDER\": \"Output Order\",\n            \"COLLECT\": \"Collect\"\n        },\n        \"COLLECT-OPERATORS\": {\n            \"SUM\": \"Sum\",\n            \"MIN\": \"Min\",\n            \"MAX\": \"Max\",\n            \"COUNT\": \"Count\"\n        },\n        \"POPUP\": {\n            \"CREATE-TITLE\": \"Create a new decision table\",\n            \"CREATE-DESCRIPTION\": \"You need to give a name for the new decision table and you may want to add a description at the same time.\",\n            \"SAVE-DESCRIPTION\": \"You need to give a name and a unique key for the new decision table and you may want to add a description at the same time.\",\n            \"DUPLICATE-TITLE\": \"Duplicate decision table\",\n            \"DUPLICATE-DESCRIPTION\": \"You need to give a name for the new decision table and you may want to add a description at the same time.\",\n            \"DELETE-TITLE\": \"Delete decision table\",\n            \"DELETE-DESCRIPTION\": \"Are you sure you want to delete the decision table \\\"{{name}}\\\"?\",\n            \"SAVE-DECISION-TABLE-TITLE\": \"Save decision table\",\n            \"IMPORT-DESCRIPTION\": \"Please browse for or drop a DMN XML definition with an .dmn or .dmn.xml extension\",\n          \t\"IMPORT-TITLE\": \"Import a DMN model\",\n\t        \"IMPORT\": {\n\t            \"DROPZONE\": \"Drop a .dmn or .dmn.xml DMN XML file\",\n\t            \"CANCEL-UPLOAD\": \"Cancel the upload\",\n\t            \"ERROR\": \"Error while processing the DMN XML file\",\n\t            \"NO-DROP\": \"Drag and drop not supported\"\n\t        },\n            \"USE-AS-NEW-TITLE\": \"Use as new version\",\n            \"USE-AS-NEW-VERSION\": \"Use as new version\",\n            \"USE-AS-NEW-DESCRIPTION\": \"Are you sure you want to use version {{version}} to create a new version of \\\"{{name}}\\\"?\",\n            \"USE-AS-NEW-UNRESOLVED-MODELS-ERROR\": \"Could not fully restore the app model to the chosen version: some referenced models are missing due to being deleted in the past. Please update the app model accordingly. Missing models:\",\n            \"USE-AS-NEW-UNRESOLVED-MODEL\": \"Model '{{name}}' with internal id {{id}}, created by {{createdBy}}\"\n        },\n        \"ALERT\": {\n            \"FAVORITE-CONFIRM\": \"This decision table is now favorited\",\n            \"UN-FAVORITE-CONFIRM\": \"This decision table is no longer favorited\"\n        }\n    },\n\n    \"APP\": {\n        \"NAME\": \"App definition name\",\n        \"KEY\": \"App definition key\",\n        \"DESCRIPTION\": \"Description\",\n        \"ICON\": \"Icon\",\n        \"THEME\": \"Theme\",\n        \"GROUPS-ACCESS\": \"Groups access, separated by commas\",\n\t\t\"USERS-ACCESS\": \"Users access, separated by commas\",\n        \"ACTION\": {\n            \"DETAILS\": \"Show details\",\n            \"EDIT\": \"Modify app definition properties\",\n            \"DUPLICATE\": \"Duplicate this application\",\n            \"SHARE\": \"Share this app definition\",\n            \"DELETE\": \"Delete this app definition\",\n            \"CREATE-CONFIRM\": \"Create new app definition\",\n            \"DUPLICATE-CONFIRM\": \"Duplicate the app definition\",\n            \"DELETE-CONFIRM\": \"Delete app definition\",\n            \"USE-AS-NEW-VERSION\": \"Use as new version\",\n            \"OPEN-IN-EDITOR\": \"App Editor\",\n            \"PUBLISH\": \"Publish\",\n            \"PUBLISH-CONFIRM\": \"Publish app definition\",\n            \"SELECT-ICON\": \"Change icon...\",\n            \"SELECT-THEME\": \"Change theme...\",\n            \"EDIT-MODELS\": \"Edit included models\",\n            \"EXPORT-ZIP\": \"Export app definition as a zip file\",\n            \"EXPORT-BAR\": \"Export app definition as a deployable bar file\"\n\n        },\n        \"DETAILS\": {\n          \"TITLE\": \"App definition details: {{name}}\",\n          \"HISTORY-TITLE\": \"History\",\n          \"MODELS-TITLE\": \"Models included in the app definition\",\n          \"LAST-UPDATED-BY\": \"Last updated by {{lastUpdatedBy}} - {{lastUpdated | dateformat}}\",\n          \"CREATED-BY\": \"Created by {{createdBy}}\",\n          \"NO-DESCRIPTION\": \"This app definition has no description. Modify the app definition properties to add one\",\n          \"NO-MODELS-SELECTED\": \"No models are selected for this app\"\n        },\n        \"TITLE\": {\n          \"SELECT-ICON\": \"Select app icon\",\n          \"SELECT-THEME\": \"Select app colors\",\n          \"PREVIEW\": \"Preview\"\n\n        },\n        \"POPUP\": {\n          \"CREATE-TITLE\": \"Create a new app definition\",\n          \"DUPLICATE-TITLE\": \"Duplicate an app definition\",\n          \"SAVE-APP-TITLE\": \"Save app definition\",\n          \"SAVE-APP-SAVE-SUCCESS\": \"Saved app definition\",\n          \"CREATE-DESCRIPTION\": \"You need to give a name for the new app definition and you may want to add a description at the same time.\",\n          \"DUPLICATE-DESCRIPTION\": \"You can give a name for the new app definition and you may want to change the description at the same time.\",\n          \"PUBLISH-TITLE\": \"Publish app definition\",\n          \"PUBLISH-DESCRIPTION\": \"Are you sure you want to publish the app definition \\\"{{name}}\\\"? Note that this app definition will be versioned and the workflow app will be updated if existing already.\",\n          \"PUBLISH-FIELD\": \"Publish? Note that if publish is enabled, this app definition will be versioned and the workflow app will be updated if existing already.\",\n          \"PUBLISH-ERROR-PROCDEF-KEY-CONFLICT\": \"Your process model \\\"{{modelInAppName}}\\\" has the same identifier \\\"{{processDefinitionKey}}\\\" as the existing deployed process \\\"{{conflictingModelName}}\\\" of the app \\\"{{conflictingAppName}}\\\". Please change this \\\"id\\\" property of the process model to something different.\",\n          \"PUBLISH-ERROR-PROCESS-ALREADY-USED\": \"Following process models are already used in another app. Is this ok?\",\n          \"PUBLISH-ERROR-PROCESS-ALREADY-USED-APP\": \"App\",\n          \"PUBLISH-ERROR-PROCDEF-DUPLICATE-KEYS\": \"Invalid app: duplicate process identifiers found (change the \\\"id\\\" property of the offending process models):\",\n          \"DELETE-TITLE\": \"Delete app definition\",\n          \"DELETE-DESCRIPTION\": \"Are you sure you want to delete the app definition \\\"{{name}}\\\"?\",\n          \"DELETE-DESCRIPTION-WITH-RUNTIME\": \"Are you sure you want to delete the app definition \\\"{{name}}\\\"? Note that this app definition has been deployed to the task landing page and by confirming, the app will be removed from the task app landing page.\",\n          \"DELETE-CASCADE-FALSE\": \"Only delete the current version of this app definition (v{{version}})\",\n          \"DELETE-CASCADE-TRUE\": \"Also delete all previous versions of this app definition\",\n          \"HAS-CUSTOM-STENCILITEM\" : \"Model \\\"{{modelName}}\\\" uses a stencil with custom stencil items. It is not possible to use this model in an app definition.\",\n          \"HAS-VALIDATIONERROR\" : \"Model \\\"{{modelName}}\\\" has validation errors and cannot be added to an app definition. Open the model in the editor to see more details about the validation error(s).\",\n          \"IMPORT-DESCRIPTION\":\"Please browse for or drop a app definition with a .zip extension\",\n          \"IMPORT-TITLE\":\"Import an app definition model\",\n          \"IMPORT\": {\n              \"DROPZONE\": \"Drop a .zip app definition file\",\n              \"CANCEL-UPLOAD\": \"Cancel the upload\",\n              \"RENEWIDM-IDS\": \"Renew the user and group identifiers when importing step and BPMN models. This is often required when importing the app definition into a different Flowable environment. It will try to link the human steps and user tasks to the right user and group in this target environment.\",\n              \"ERROR\": \"Error while processing the app definition file\",\n              \"NO-DROP\": \"Drag and drop not supported\"\n          },\n          \"INCLUDE-MODELS-TITLE\": \"Models included in the app definition\"\n        },\n        \"ALERT\": {\n          \"DELETE-CONFIRM\": \"App definition deleted\",\n          \"PUBLISH-CONFIRM\": \"The app definition has been published\",\n          \"PUBLISH-ERROR\": \"Could not publish app definition. Please check the validity of the referenced process models\"\n        }\n    },\n\n    \"SHARE-INFO\": {\n        \"ACTION\": {\n          \"ADD\": \"Add another person\"\n        }\n    },\n\n    \"FORM-BUILDER\": {\n        \"PALLETTE\": {\n            \"TEXT\": \"Text\",\n            \"MULTILINE-TEXT\": \"Multiline text\",\n            \"PASSWORD\": \"Password\",\n            \"NUMBER\": \"Number\",\n            \"CHECKBOX\": \"Checkbox\",\n            \"DATE\": \"Date\",\n            \"DROPDOWN\": \"Dropdown\",\n            \"RADIO\": \"Radio buttons\",\n            \"PEOPLE\": \"People\",\n            \"GROUP-OF-PEOPLE\": \"Group of people\",\n            \"UPLOAD\": \"Upload\",\n            \"EXPRESSION\": \"Expression\",\n            \"DECIMAL\": \"Decimal\",\n\t    \t\"HYPERLINK\": \"Hyperlink\",\n\t    \t\"SPACER\": \"Spacer\",\n\t\t\t\"HORIZONTAL-LINE\": \"Horizontal line\",\n\t\t\t\"HEADLINE\": \"Headline\",\n\t\t\t\"HEADLINE-WITH-LINE\":\"Headline\"\n        },\n        \"TABS\": {\n            \"GENERAL\": \"General\",\n            \"OPTIONS\": \"Options\",\n            \"UPLOAD-OPTIONS\": \"Upload options\",\n\t    \"ADVANCED-OPTIONS\":\"Advanced\" \n        },\n        \"VERSION\": \"Version {{version}}\",\n        \"LAST-UPDATED\": \"Last updated by {{lastUpdatedBy}}, {{lastUpdated | dateformat}}\",\n        \"TITLE\": {\n            \"DESIGN\": \"Design\",\n            \"OUTCOME\": \"Outcomes\"\n        },\n        \"POPUP\": {\n            \"EDIT-TITLE\": \"Edit field '{{name}}'\",\n            \"EXPRESSION-TITLE\": \"Edit expression\"\n        },\n        \"MESSAGE\": {\n            \"EMPTY-EXPRESSION\": \"(No expression value)\",\n            \"EXPRESSION-HELP\": \"You can also display values previously submitted in any form, as part of the text, by referencing them using a notation as follows ${myFieldId}.\",\n            \"OPTIONS-EXPRESSION-HELP\": \"You can use an expression to dynamically populate options for example by referencing a variable like this ${optionsVariable}. The expression needs to result in either a java object (java.util.List with Option objects) or its json representation.\"\n        },\n        \"LABEL\" : {\n            \"FUNCTIONAL-GROUP\": \"Select group..\",\n            \"PERSON\": \"Select person..\"\n        },\n        \"COMPONENT\": {\n            \"LABEL\": \"Label:\",\n            \"OVERRIDEID\": \"Override id?\",\n            \"ID\": \"Id:\",\n            \"PLACEHOLDER\": \"Placeholder:\",\n            \"OPTIONS\": \"Options\",\n            \"RADIO-BUTTON-DEFAULT\": \"Option 1\",\n            \"DROPDOWN-DEFAULT-EMPTY-SELECTION\": \"Please choose one...\",\n            \"DROPDOWN-EMPTY-VALUE-HELP\": \"This is the 'empty value' option. Selecting this at runtime is the taken to mean 'no value' or 'empty'.  This is allowed for optional fields, but not allowed for required fields.\",\n            \"OPTIONS-EXPRESSION\": \"Options expression:\",\n            \"OPTIONS-EXPRESSION-ENABLED\": \"Enable options expression\",\n            \"REQUIRED\": \"Required\",\n\t          \"READONLY\": \"Read-only\",\n            \"EXPRESSION\": \"Expression\",\n            \"ADD-OPTION\": \"+ Add a new option\",\n            \"UPLOAD-ALLOW-MULTIPLE\": \"Allow uploading multiple files\",\n            \"SIZE\": \"Size\",\n\t          \"MAX-LENGTH\":\"Maximum length:\",\n            \"MIN-LENGTH\":\"Minimum length:\",\n            \"PASSWORD-UNMASK-OPTION\": \"password masking/unmasking option\",\n\t          \"HYPERLINK-URL\": \"Hyperlink URL\",\n\t          \"REGEX-PATTERN\":\"Regex standard\",\n            \"MASK\":{\n              \"TITLE\":\"Input mask\",\n              \"EXAMPLES\":{\n                \"TITLE\":\"Examples:\",\n                \"NUMBER\":\"Any number\",\n                \"LETTER\":\"Any letter\",\n                \"NUMBERORLETTER\":\"Any letter or number\",\n                \"OPTIONAL\":\"Make mask optional (not valid)\",\n                \"PHONE\":\"Phone\"\n               }\n           }\n        },\n        \"OUTCOMES\": {\n            \"DESCRIPTION\": \"You can define multiple outcomes for this task. When completing a task, the users selects one of the available outcomes, which can be used in eg. a condition further on in the process.\",\n            \"NO-OUTCOMES-OPTION\": \"Don't use custom outcomes, only show a 'Complete' button.\",\n            \"OUTCOMES-OPTION\": \"Use custom outcomes for this form.\",\n            \"POSSIBLE-OUTCOMES\": \"Possible outcomes\",\n            \"NEW-OUTCOME-PLACEHOLDER\": \"Enter new outcome\",\n            \"ADD\": \"Add outcome\",\n            \"REMOVE\": \"Remove\"\n        }\n    },\n\n    \"DECISION-TABLE-EDITOR\": {\n        \"EMPTY-MESSAGES\": {\n            \"NO-VARIABLE-SELECTED\": \"Undefined\"\n        },\n        \"POPUP\": {\n            \"EXPRESSION-EDITOR\": {\n                \"INPUT-TITLE\": \"Edit input column\",\n                \"INPUT-DESCRIPTION\": \"Select input variable as input for the column\",\n                \"OUTPUT-TITLE\": \"Edit output column\",\n                \"OUTPUT-DESCRIPTION\": \"Select an existing output variable or create a new one\",\n                \"EXPRESSION-LABEL\": \"Column label:\",\n                \"EXPRESSION-PLACEHOLDER\": \"Enter an optional label\",\n                \"EXPRESSION-VARIABLE-NAME\": \"Variable name:\",\n                \"EXPRESSION-VARIABLE-TYPE\": \"Variable type:\",\n                \"EXPRESSION-VARIABLE-NAME-PLACEHOLDER\": \"Enter a variable name\",\n                \"OUTPUT-NEW-VARIABLE-ID\": \"Variable ID:\",\n                \"OUTPUT-NEW-VARIABLE-TYPE\": \"Variable type:\",\n                \"COMPLEX-EXPRESSION-LABEL\": \"Complex expression:\",\n                \"ALLOWED-VALUES\": \"Allowed values (optional):\",\n                \"OUTPUT-VALUES\": \"Output values \",\n                \"OUTPUT-VALUES-OPTIONAL\": \"(optional):\",\n                \"OUTPUT-VALUES-NOT-OPTIONAL\": \"(drag rows for priority / output order):\"\n            }\n        },\n        \"BUTTON-ACTIONS-LABEL\": \"Actions\",\n        \"BUTTON-ADD-INPUT-LABEL\": \"Add input\",\n        \"BUTTON-ADD-OUTPUT-LABEL\": \"Add output\",\n        \"BUTTON-ADD-RULE-LABEL\": \"Add rule\",\n        \"BUTTON-MOVE-RULE-UPWARDS-LABEL\": \"Move up\",\n        \"BUTTON-MOVE-RULE-DOWNWARDS-LABEL\": \"Move down\",\n        \"BUTTON-REMOVE-RULE-LABEL\": \"Remove rule\",\n        \"ALERT\": {\n            \"EXPRESSION-VARIABLE-REQUIRED-ERROR\": \"All input and output expressions must reference a form field or variable.\",\n            \"SAVE-CONFIRM\": \"Saved decision table '{{name}}'\"\n        }\n    },\n\n    \"TOUR\": {\n        \"WELCOME-TITLE\": \"Welcome, {{userName}}\",\n        \"WELCOME-CONTENT\": \"This a short tour of the Flowable editor. The next few steps will guide you through the different sections of the application to get you started. Press the ESC key to stop at any time.\" ,\n        \"PALETTE-TITLE\": \"The Palette\",\n        \"PALETTE-CONTENT\": \"All the available constructs to create a business process can be found here. They are arranged in logical groups. To open a group simply click on it:\",\n        \"CANVAS-TITLE\": \"The Canvas\",\n        \"CANVAS-CONTENT\": \"This is the work space on which you create your business process. Drag elements from the palette on the left and drop them on this canvas to start modeling.\",\n        \"DRAGDROP-TITLE\": \"Drag and Drop Example\",\n        \"DRAGDROP-CONTENT\": \"Here is an example how you get started with modeling:\",\n        \"PROPERTIES-TITLE\": \"Properties\",\n        \"PROPERTIES-CONTENT\": \"Here you can configure the properties of a business process construct. Simply select the item on the canvas and its properties will be shown. Click on the property if you want to edit it\",\n        \"TOOLBAR-TITLE\": \"The Toolbar\",\n        \"TOOLBAR-CONTENT\": \"All the actions can be found here: saving or validating a model, copy and pasting parts of a process, and so on. Hover over the buttons to get a description for an action.\",\n        \"END-TITLE\": \"The End\",\n        \"END-CONTENT\": \"That's it! You can now start modeling your processes. If you have any questions, feel free to ask them on the <a href=\\\"http://forum.flowable.org/\\\" target=\\\"_blank\\\">Flowable Forum</a> \"\n    },\n\n    \"FEATURE-TOUR\" : {\n        \"BENDPOINT\" : {\n            \"TITLE\": \"Bend point tutorial\",\n            \"DESCRIPTION\" : \"When you are connecting process steps with each other using sequence flow (those arrows between process steps), you might find that these sequence flow cross each other or you would like to arrange them differently. To do this, you can add or remove a bend point to or from a sequence flow.<br/><br/> As shown below in the picture, you first click the 'add bendpoint' and then click on a sequence flow to add it. Note that the sequence flow will show you a subtle indication in green to show the bendpoint can be added there.<br/><br/> Removing a bendpoint again follows a similar pattern: click the 'remove bendpoint' button and click on the bend point to remove it again.\"\n        }\n    },\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    \"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.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    \"FORM_TOOLBAR.ACTION.SAVE\" : \"Save the model\",\n\n    \"APP_DEFINITION_TOOLBAR.ACTION.SAVE\" : \"Save the app definition\",\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\n    \"PROPERTY.REMOVED\" : \"removed\",\n    \"PROPERTY.EMPTY\" : \"No value\",\n    \"PROPERTY.PROPERTY.EDIT.TITLE\" : \"Change value for \",\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\" : \"Fixed 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.NONE\" : \"None ...\",\n    \"PROPERTY.ASSIGNMENT.PLACEHOLDER-SEARCHUSER\": \"Search user\",\n    \"PROPERTY.ASSIGNMENT.PLACEHOLDER-SEARCHGROUP\": \"Search group\",\n    \"PROPERTY.ASSIGNMENT.SEARCH\": \"Search: \",\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.USER_IDM_FIELD_DISPLAY\": \"Field {{name}}\",\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.INITIATOR-CAN-COMPLETE\" : \"Allow process initiator to complete task\",\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\n    \"PROPERTY.DATAPROPERTIES.VALUES\" : \"{{length}} data objects\",\n    \"PROPERTY.DATAPROPERTIES.EMPTY\" : \"No data objects configured\",\n    \"PROPERTY.DATAPROPERTIES.ID\" : \"Id\",\n    \"PROPERTY.DATAPROPERTIES.ID.PLACEHOLDER\" : \"Enter an id\",\n    \"PROPERTY.DATAPROPERTIES.NAME\" : \"Name\",\n    \"PROPERTY.DATAPROPERTIES.NAME.PLACEHOLDER\" : \"Enter a name\",\n    \"PROPERTY.DATAPROPERTIES.TYPE\" : \"Type\",\n    \"PROPERTY.DATAPROPERTIES.VALUE.PLACEHOLDER\" : \"Enter a value (optional)\",\n    \"PROPERTY.DATAPROPERTIES.VALUE\" : \"Default Value\",\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.DEFAULT\" : \"default\",\n    \"PROPERTY.FORMPROPERTIES.DEFAULT.PLACEHOLDER\" : \"Enter a default\",\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.PROCESSREFERENCE.EMPTY\" : \"No reference selected\",\n    \"PROPERTY.PROCESSREFERENCE.TITLE\" : \"Process reference\",\n    \"PROPERTY.PROCESSREFERENCE.ERROR.PROCESS\" : \"There was an error loading the processes. Try again later\",\n    \"PROPERTY.PROCESSREFERENCE.PROCESS.LOADING\" : \"Loading processes...\",\n    \"PROPERTY.PROCESSREFERENCE.PROCESS.EMPTY\" : \"This folder contains no processes\",\n\n    \"PROPERTY.FORMREFERENCE.EMPTY\" : \"No reference selected\",\n    \"PROPERTY.FORMREFERENCE.TITLE\" : \"Form reference\",\n    \"PROPERTY.FORMREFERENCE.DESCRIPTION\" : \"Reference to a form\",\n    \"PROPERTY.FORMREFERENCE.ERROR.FORM\" : \"There was an error loading the forms. Try again later\",\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.PLANITEMLIFECYCLELISTENERS.VALUE\" : \"{{length}} lifecycle listeners\",\n    \"PROPERTY.PLANITEMLIFECYCLELISTENERS.EMPTY\" : \"No lifecycle listeners configured\",\n    \"PROPERTY.PLANITEMLIFECYCLELISTENERS.EVENT\" : \"Event\",\n    \"PROPERTY.PLANITEMLIFECYCLELISTENERS.SOURCE_STATE\" : \"Source state\",\n    \"PROPERTY.PLANITEMLIFECYCLELISTENERS.TARGET_STATE\" : \"Target state\",\n    \"PROPERTY.PLANITEMLIFECYCLELISTENERS.CLASS\" : \"Class\",\n    \"PROPERTY.PLANITEMLIFECYCLELISTENERS.CLASS.PLACEHOLDER\" : \"Enter a classname\",\n    \"PROPERTY.PLANITEMLIFECYCLELISTENERS.EXPRESSION\" : \"Expression\",\n    \"PROPERTY.PLANITEMLIFECYCLELISTENERS.EXPRESSION.PLACEHOLDER\" : \"Enter an expression\",\n    \"PROPERTY.PLANITEMLIFECYCLELISTENERS.DELEGATEEXPRESSION\" : \"Delegate expression\",\n    \"PROPERTY.PLANITEMLIFECYCLELISTENERS.DELEGATEEXPRESSION.PLACEHOLDER\" : \"Enter a delegate expression\",\n    \"PROPERTY.PLANITEMLIFECYCLELISTENERS.UNSELECTED\" : \"No task listener selected\",\n    \"PROPERTY.PLANITEMLIFECYCLELISTENERS.FIELDS.NAME\" : \"Name\",\n    \"PROPERTY.PLANITEMLIFECYCLELISTENERS.FIELDS.NAME.PLACEHOLDER\" : \"Enter a name\",\n    \"PROPERTY.PLANITEMLIFECYCLELISTENERS.FIELDS.EXPRESSION\" : \"Expression\",\n    \"PROPERTY.PLANITEMLIFECYCLELISTENERS.FIELDS.EXPRESSION.PLACEHOLDER\" : \"Enter an expression\",\n    \"PROPERTY.PLANITEMLIFECYCLELISTENERS.FIELDS.STRINGVALUE\" : \"String value\",\n    \"PROPERTY.PLANITEMLIFECYCLELISTENERS.FIELDS.STRINGVALUE.PLACEHOLDER\" : \"Enter a string value\",\n    \"PROPERTY.PLANITEMLIFECYCLELISTENERS.FIELDS.STRING\" : \"String\",\n    \"PROPERTY.PLANITEMLIFECYCLELISTENERS.FIELDS.STRING.PLACEHOLDER\" : \"Enter a string\",\n    \"PROPERTY.PLANITEMLIFECYCLELISTENERS.FIELDS.IMPLEMENTATION\" : \"Implementation\",\n    \"PROPERTY.PLANITEMLIFECYCLELISTENERS.FIELDS.EMPTY\" : \"No Field 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.STATIC\" : \"Condition expression\",\n    \"PROPERTY.SEQUENCEFLOW.CONDITION.NO-CONDITION-DISPLAY\": \"No condition set\",\n\n    \"PROPERTY.DUEDATE.EMPTY\" : \"No due date\",\n    \"PROPERTY.DUEDATE.DEFINED\" : \"Due date defined\",\n    \"PROPERTY.DUEDATE.TITLE\" : \"Due date\",\n    \"PROPERTY.DUEDATE.EXPRESSION-LABEL\" : \"Due date expression\",\n    \"PROPERTY.DUEDATE.TASK-DUE-DATE-OPTIONS.NO-DUEDATE\" : \"No due date\",\n    \"PROPERTY.DUEDATE.TASK-DUE-DATE-OPTIONS.EXPRESSION\" : \"Expression definition\",\n    \"PROPERTY.DUEDATE.TASK-DUE-DATE-OPTIONS.STATIC\" : \"Fixed duration after task creation\",\n    \"PROPERTY.DUEDATE.TASK-DUE-DATE-OPTIONS.FIELD\" : \"Based on field\",\n\n    \"MODEL.SAVE.TITLE\" : \"Save model\",\n    \"MODEL.VALIDATE.TITLE\" : \"Validation results\",\n    \"MODEL.NAME\" : \"Name\",\n    \"MODEL.KEY\" : \"Key\",\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    \"MODEL.VALIDATIONERRORS\": \"Note that the model contains validation errors. This means that the model can not be deployed on the Flowable Engine in its current state.\",\n    \"MODEL.CONFLICT.WRITE\": \"Could not save model: '{{userFullName}}' has made changes to this model\",\n    \"MODEL.CONFLICT.WRITE.OPTIONS\": \"Select an option to resolve this conflict:\",\n    \"MODEL.CONFLICT.WRITE.OPTION.OVERWRITE\": \"Overwrite other model\",\n    \"MODEL.CONFLICT.WRITE.OPTION.DISCARDCHANGES\": \"Discard my changes\",\n    \"MODEL.CONFLICT.WRITE.OPTION.SAVEAS\": \"Save as new model\",\n    \"MODEL.CONFLICT.WRITE.OPTION.NEWVERSION\": \"Create new version\",\n    \"MODEL.CONFLICT.SAVEAS\" : \"Save as:\",\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\n    \"PROPERTY.DECISIONTABLEREFERENCE.EMPTY\" : \"No reference selected\",\n    \"PROPERTY.DECISIONTABLEREFERENCE.TITLE\" : \"Decision table reference\",\n    \"PROPERTY.DECISIONTABLEREFERENCE.ERROR.FORM\" : \"There was an error loading the decision tables. Try again later\",\n    \"PROPERTY.DECISIONTABLEREFERENCE.DECISIONTABLE.LOADING\" : \"Loading decision tables...\",\n    \"PROPERTY.DECISIONTABLEREFERENCE.DECISIONTABLE.EMPTY\" : \"This folder contains no decision tables\",\n    \n    \"PROPERTY.CASEREFERENCE.EMPTY\" : \"No reference selected\",\n    \"PROPERTY.CASEREFERENCE.TITLE\" : \"Case model reference\",\n    \"PROPERTY.CASEREFERENCE.ERROR.FORM\" : \"There was an error loading the case models. Try again later\",\n    \"PROPERTY.CASEREFERENCE.CASE.LOADING\" : \"Loading case models...\",\n    \"PROPERTY.CASEREFERENCE.CASE.EMPTY\" : \"This folder contains no case models\"\n}\n"
  },
  {
    "path": "flowable-ui-web/modeler/i18n/es.json",
    "content": "{\n    \"GENERAL\" : {\n        \"MAIN-TITLE\": \"Flowable Editor\",\n        \"NAVIGATION\" : {\n            \"PROCESSES\": \"Procesos\",\n            \"FORMS\": \"Formularios\",\n            \"DECISION-TABLES\": \"Tablas de decisión\",\n            \"APPS\": \"Aplicaciones\"\n        },\n        \"TITLE\": {\n            \"SELECT-GROUP\" :\"Selecciona el grupo\",\n            \"MATCHING-GROUPS\": \"Grupos coincidentes\",\n            \"FILTER\": \"Filtro\",\n            \"HISTORY\": \"Historial\"\n        },\n        \"ACTION\": {\n            \"LOGOUT\": \"Salir\",\n            \"RETURN-TO-LIST\": \"Mostrar todas las definiciones\",\n            \"CANCEL\": \"Cancelar\",\n            \"CLOSE\": \"Cerrar\",\n            \"EDIT\": \"Editar\",\n            \"SAVE\": \"Guardar\",\n            \"OPEN\": \"Abrir\",\n            \"OK\": \"Ok\",\n            \"CONFIRM\": \"Confirmar\",\n            \"CONFIRM-AND-CLOSE\": \"Confirmar y cerrar\",\n            \"NEW-FORM\": \"Nuevo formulario\",\n            \"CREATE-FORM\": \"Crear formulario\",\n            \"NEW-DECISION-TABLE\": \"Nueva tabla de decisión\",\n            \"CREATE-DECISION-TABLE\": \"Crear tabla de decisión\"\n        },\n        \"MESSAGE\": {\n          \"SELECT-GROUP-HELP\": \"Usa &uparrow; y &downarrow; para seleccionar y presiona Enter para confirmar\",\n          \"PEOPLE-NO-MATCHING-RESULTS\": \"No se encontraron usuarios similares\",\n          \"GROUP-NO-MATCHING-RESULTS\": \"No se encontraron grupos similares\",\n          \"GROUP-SOURCE-TYPE\": \"Group source\",\n          \"GROUP-SOURCE-SEARCH-OPTION\": \"Busqueda de grupo\",\n          \"GROUP-SOURCE-FIELD-OPTION\": \"Campo de formulario\"\n        }\n    },\n\n    \"EDITOR\": {\n      \"POPUP\": {\n        \"UNSAVED-CHANGES\": {\n          \"TITLE\": \"Tienes cambios sin guardar\",\n          \"DESCRIPTION\": \"Que deseas realizar con los cambios sin guardar?\",\n          \"ACTION\": {\n            \"SAVE\": \"Guardar cambios\",\n            \"DISCARD\": \"Descartar cambios\",\n            \"CONTINUE\": \"Continiar edición\"\n          }\n        }\n      }\n    },\n\n    \"PROCESS-LIST\" : {\n        \"TITLE\" : \"Modelos de procesos de negocio\",\n        \"SEARCH-PLACEHOLDER\": \"Buscar\",\n        \"ACTION\" : {\n            \"CREATE\": \"Crear Proceso\",\n            \"IMPORT\": \"Importar Proceso\"\n        },\n\n        \"FILTER\" : {\n            \"PROCESSES\": \"Modelo de proceso\",\n            \"PROCESSES-COUNT\": \"Existen {{total}} modelos de proceso\",\n            \"PROCESSES-ONE\": \"Existe un modelo de proceso\",\n            \"PROCESSES-EMPTY\": \"Aun no existe un modelo de proceso creado. puedes diseñar tus propios modelos, formularios y despues incluirlos en una aplicación. El primer paso es crear un modelo de proceso:\",\n            \"PROCESSES-BPMN-HINT\": \"Crear un modelo BPMN usando el editor visual BPMN.\",\n            \"PROCESSES-BPMN-IMPORT-HINT\": \"Tambien puede importar modelos BPMN existentes.\",\n            \"FILTER-TEXT\": \", parecido a \\\"{{filterText}}\\\"\",\n            \"FILTER-TEXT-EMPTY\": \"No existen modelos de proceso parecidos a \\\"{{filterText}}\\\"\",\n            \"RECENT\": \"Reciente\",\n            \"RECENT-COUNT\": \"{{total}} modelos usados recientemente\",\n            \"RECENT-ONE\": \"Existe un modelo usado recientemente\",\n            \"RECENT-EMPTY\": \"No existen modelos usados recientemente\"\n        },\n\n        \"SORT\": {\n            \"MODIFIED-ASC\": \"Antiguo\",\n            \"MODIFIED-DESC\": \"Ultimo modificado\",\n            \"NAME-ASC\": \"Nombre, A-Z\",\n            \"NAME-DESC\": \"Nombre, Z-A\"\n        }\n    },\n\n    \"FORMS-LIST\" : {\n        \"TITLE\" : \"Formularios\",\n        \"SEARCH-PLACEHOLDER\": \"Busqueda\",\n        \"ACTION\" : {\n            \"CREATE\": \"Crear formulario\",\n            \"CREATE-INLINE\": \"Crear un nuevo formulario ahora!\",\n            \"SHOW-MORE\": \"Mostrar más...\"\n        },\n\n        \"FILTER\" : {\n            \"FORMS\": \"Formularios\",\n            \"FORMS-COUNT\": \"Existen {{total}} formularios\",\n            \"FORMS-ONE\": \"Existe un formulario\",\n            \"FORMS-EMPTY\": \"No existen formularios. Para agregar uno da click en Crear formulario.\",\n            \"FILTER-TEXT\": \", parecido a \\\"{{filterText}}\\\"\",\n            \"FILTER-TEXT-EMPTY\": \"No existe un formulario parecido a \\\"{{filterText}}\\\"\"\n        },\n\n        \"SORT\": {\n            \"MODIFIED-ASC\": \"Antiguo\",\n            \"MODIFIED-DESC\": \"Ultimo modificado\",\n            \"NAME-ASC\": \"Nombre, A-Z\",\n            \"NAME-DESC\": \"Nombre, Z-A\"\n        }\n    },\n\n    \"DECISION-TABLES-LIST\": {\n        \"TITLE\": \"Tablas de decision\",\n        \"SEARCH-PLACEHOLDER\": \"Busqueda\",\n        \"ACTION\": {\n            \"CREATE\": \"Crear tabla de decision\",\n            \"IMPORT\": \"Importar tabla de decision\",\n            \"CREATE-INLINE\": \"Crear una tabla de decision ahora!\",\n            \"SHOW-MORE\": \"Mostrar más...\"\n        },\n\n        \"FILTER\": {\n            \"DECISION-TABLES\": \"Tablas de decision\",\n            \"DECISION-TABLES-COUNT\": \"Existen {{total}} tablas de decision\",\n            \"DECISION-TABLES-ONE\": \"Existe una tabla de decision\",\n            \"DECISION-TABLES-EMPTY\": \"No existen tablas de decision. Para agregar una da click en Crear tabla de decision.\",\n            \"FILTER-TEXT\": \", parecido a \\\"{{filterText}}\\\"\",\n            \"FILTER-TEXT-EMPTY\": \"no existen tablas de decision parecidas a \\\"{{filterText}}\\\"\"\n        },\n\n        \"SORT\": {\n            \"MODIFIED-ASC\": \"Antiguo\",\n            \"MODIFIED-DESC\": \"Ultimo modificado\",\n            \"NAME-ASC\": \"Nombre, A-Z\",\n            \"NAME-DESC\": \"Nombre, Z-A\"\n        }\n    },\n\n    \"APPS-LIST\" : {\n        \"TITLE\" : \"Aplicaciones\",\n        \"SEARCH-PLACEHOLDER\": \"Busqueda\",\n        \"ACTION\" : {\n            \"CREATE\": \"Crear App\",\n            \"IMPORT\": \"Importar App\",\n            \"SHOW-MORE\": \"Mostrar mas...\"\n        },\n\n        \"FILTER\" : {\n            \"APPS\": \"Aplicaciones\",\n            \"APPS-COUNT\": \"Existen {{total}} aplicaciones\",\n            \"APPS-ONE\": \"Existe una aplicacion\",\n            \"APPS-EMPTY\": \"No existen aplicaciones. Para agregar una da click en Crear App.\",\n            \"FILTER-TEXT\": \", parecido a \\\"{{filterText}}\\\"\",\n            \"FILTER-TEXT-EMPTY\": \"No existen aplicaciones parecidas a \\\"{{filterText}}\\\"\",\n\n            \"NO-APPS\": \"Puedes crear una aplicacion publicando un conjunto de Modelos de Proceso.\",\n            \"NO-APPS-CALL-TO-ACTION\": \"Puedes crear una aplicacion ahora.\",\n            \"NO-APPS-NOTE\": \"Recuerda publicar cuando estes listo para usar la aplicacion.\"\n        },\n\n        \"SORT\": {\n            \"MODIFIED-ASC\": \"Antiguo\",\n            \"MODIFIED-DESC\": \"Ultimo modificado\",\n            \"NAME-ASC\": \"Nombre, A-Z\",\n            \"NAME-DESC\": \"Nombre, Z-A\"\n        }\n    },\n    \"PROCESS\": {\n      \"NAME\": \"Nombre del modelo\",\n      \"KEY\": \"Identificador del modelo\",\n      \"DESCRIPTION\": \"Descripcion\",\n      \"VERSION-COMMENT\": \"Comentario de version\",\n      \"ACTION\": {\n            \"DETAILS\": \"Mostrar detalles\",\n            \"EDIT\": \"Modificar propiedades del modelo\",\n            \"DUPLICATE\": \"Duplicar este modelo\",\n            \"EXPORT_BPMN20\": \"Exportar a BPMN 2.0\",\n            \"DELETE\": \"Borrar este modelo\",\n            \"CREATE-CONFIRM\": \"Crear nuevo modelo\",\n            \"DUPLICATE-CONFIRM\": \"Duplicar el modelo\",\n            \"OPEN-IN-EDITOR\": \"Editor visual\",\n            \"EDIT-CONFIRM\": \"Guardar\",\n            \"DELETE-CONFIRM\": \"Borrar modelo de proceso\",\n            \"USE-AS-NEW-VERSION\": \"Usar como nueva version\",\n            \"FAVORITE\": \"Hacer modelo favorito\"\n\n        },\n        \"DETAILS\": {\n          \"HISTORY-TITLE\": \"Historial\",\n          \"LAST-UPDATED-BY\": \"Ultima actualizacion por {{lastUpdatedBy}} - {{lastUpdated | dateformat}}\",\n          \"CREATED-BY\": \"Creado por {{createdBy}}\",\n          \"NO-DESCRIPTION\": \"Este modelo no tiene descripcion. Modifica las propiedades del modelo para agregar una\"\n        },\n\n        \"POPUP\": {\n          \"CREATE-TITLE\": \"Crear un nuevo modelo de proceso de negocio\",\n          \"DUPLICATE-TITLE\": \"Duplicar modelo de proceso de negocio\",\n          \"CREATE-DESCRIPTION\": \"Necesitas dar un nombre para el nuevo modelo y es recomendable que agregues una descripción al mismo tiempo.\",\n          \"DUPLICATE-DESCRIPTION\": \"Puedes cambiar el nombre del modelo y es recomendable que cambies la descripción al mismo tiempo.\",\n          \"EDIT-DESCRIPTION\": \"Cambia cualquiera de las propiedades del modelo y despues presiona Guardar para actualizar el modelo.\",\n          \"DELETE-DESCRIPTION\": \"Estas seguro que deseas borral el modelo de proceso de negocio \\\"{{name}}\\\"?\",\n          \"EDIT-TITLE\":\"Editar los detalles del modelo\",\n          \"DELETE-TITLE\": \"Borrar modelo\",\n          \"DELETE-LOADING-RELATIONS\": \"Verificando el uso del modelo...\",\n          \"DELETE-RELATIONS-DESCRIPTION-SINGLE\": \"Este modelo no puede ser eliminado porque esta siendo utilizado por otro modelo:\",\n          \"DELETE-RELATIONS-DESCRIPTION\": \"Este modelo no puede ser eliminado porque esta siendo utilizado por otros modelos:\",\n          \"DELETE-PROCESS-RELATION\": \"Modelo de proceso\",\n          \"DELETE-FORM-RELATION\": \"Formulario de modelo\",\n          \"DELETE-APP-RELATION\": \"Modelo de App\",\n          \"IMPORT-DESCRIPTION\": \"Busca o arrastra una definicion BPMN XML con la extension .bpmn o .bpmn20.xml\",\n          \"IMPORT-TITLE\": \"Importar un modelo de proceso\",\n          \"USE-AS-NEW-TITLE\": \"Usar como nueva version\",\n          \"USE-AS-NEW-DESCRIPTION\": \"Estas seguro que deseas utilizar la version {{version}} para crear una nueva version de \\\"{{name}}\\\"?\",\n          \"USE-AS-NEW-UNRESOLVED-MODELS-ERROR\": \"No se pudo restaurar a la version seleccionada: Algunos modelos no se encuentran debido a que fueron borrados. Por favor actualiza el modelo de la aplicacion. Modelos faltantes:\",\n          \"USE-AS-NEW-UNRESOLVED-MODEL\": \"Modelo '{{name}}' con el id {{id}}, creado por {{createdBy}}\",\n          \"SHARED-WITH\": \"Compartido con\",\n          \"PERMISSION\": \"Permiso\",\n          \"ACTIONS\": \"Acciones\",\n          \"IMPORT\": {\n              \"DROPZONE\": \"Arrastra un archivo .bpmn or .bpmn20.xml BPMN XML\",\n              \"CANCEL-UPLOAD\": \"Cancelar la carga de archivo\",\n              \"ERROR\": \"Error al procesar el archivo BPMN XML\",\n              \"NO-DROP\": \"Arrastrar y soltar no soportado\"\n          }\n        },\n        \"ALERT\": {\n          \"EDIT-CONFIRM\": \"Modelo actualizado\"\n        },\n        \"ERROR\": {\n          \"NOT-FOUND\": \"El modelo solicitado no existe\"\n        }\n    },\n\n    \"SUBPROCESS\": {\n        \"NAME\": \"Nombre del Sub proceso\",\n        \"DESCRIPTION\": \"Descripcion\",\n        \"ACTION\": {\n            \"CREATE-CONFIRM\": \"Crear nuevo sub proceso\"\n        },\n        \"POPUP\": {\n            \"CREATE-TITLE\": \"Crear nuevo sub proceso\",\n            \"CREATE-DESCRIPTION\": \"Necesitas proporcionar un nombre para el nuevo sub proceso y es recomendable agregar una descripcion al mismo tiempo.\"\n        }\n    },\n\n    \"FORM\": {\n      \"NAME\": \"Nombre del formulario\",\n      \"KEY\": \"identificador del formulario\",\n      \"DESCRIPTION\": \"Descripcion\",\n      \"ACTION\": {\n            \"DETAILS\": \"Mostrar detalles\",\n            \"EDIT\": \"Modicar propiedades del modelo\",\n            \"DELETE\": \"Borrar este formulario\",\n            \"CREATE-CONFIRM\": \"Crear nuevo formulario\",\n            \"DUPLICATE-CONFIRM\": \"Duplicar el formulario\",\n            \"OPEN-IN-EDITOR\": \"Editor de formulario\",\n            \"EDIT-CONFIRM\": \"Guardar\",\n            \"DELETE-CONFIRM\": \"Borrar formulario\",\n            \"USE-AS-NEW-VERSION\": \"Usar como nueva version\"\n\n        },\n        \"DETAILS\": {\n          \"HISTORY-TITLE\": \"Historial\",\n          \"LAST-UPDATED-BY\": \"Ultima actualizacion por {{lastUpdatedBy}} - {{lastUpdated | dateformat}}\",\n          \"CREATED-BY\": \"Creado por {{createdBy}}\"\n        },\n\n        \"POPUP\": {\n          \"CREATE-TITLE\": \"Crear nuevo formulario\",\n          \"DUPLICATE-TITLE\": \"Duplicar formulario\",\n          \"CREATE-DESCRIPTION\": \"Necesitas proporcionar un nombre para el nuevo formulario y es recomendable agregar una descripcion al mismo tiempo.\",\n          \"DUPLICATE-DESCRIPTION\": \"Necesitas proporcionar un nombre para el nuevo formulario y es recomendable agregar una descripcion al mismo tiempo.\",\n          \"SAVE-FORM-TITLE\": \"Guardar formulario\",\n          \"EDIT-DESCRIPTION\": \"Cambia cualquiera de las propiedades debajo y despues presiona Guardar para actualizar el formulario.\",\n          \"DELETE-DESCRIPTION\": \"Estas seguro de borrar el formulario \\\"{{name}}\\\"?\",\n          \"EDIT-TITLE\":\"Editar detalles de formulario\",\n          \"DELETE-TITLE\": \"Borrar formulario\",\n          \"USE-AS-NEW-TITLE\": \"Usar como nueva version\",\n          \"USE-AS-NEW-VERSION\": \"Usar como nueva version\",\n          \"USE-AS-NEW-DESCRIPTION\": \"Estas seguro que quieres utilizar la version {{version}} para crear una nueva version de \\\"{{name}}\\\"?\",\n          \"USE-AS-NEW-UNRESOLVED-MODELS-ERROR\": \"No se pudo restaurar completamente a la version seleccionada: Algunos modelos referenciados fueron borrados. Por favor actualiza el modelo. Moodelos faltantes:\",\n          \"USE-AS-NEW-UNRESOLVED-MODEL\": \"Modelo '{{name}}' con identificador {{id}}, creado por {{createdBy}}\"\n        }\n    },\n\n    \"DECISION-TABLE\": {\n        \"NAME\": \"Nombre de la Tabla de decision\",\n        \"KEY\": \"Identificador de la Tabla de decision\",\n        \"DESCRIPTION\": \"Descripcion\",\n        \"VERSION-COMMENT\": \"Comentario de version\",\n        \"HIT-POLICY\": \"Reglas de aciertos:\",\n        \"ACTION\": {\n            \"DETAILS\": \"Mostrar detalles\",\n            \"EDIT\": \"Modificar propiedades del modelo\",\n            \"SHARE\": \"Compartir esta tabla de decision\",\n            \"DELETE\": \"Borrar esta tabla de decision\",\n            \"ADD-COMMENT\": \"+ Agregar comentario\",\n            \"CREATE-CONFIRM\": \"Crear nueva tabla de decision\",\n            \"OPEN-IN-EDITOR\": \"Editor de tabla de decision\",\n            \"EXPORT\": \"Exportar tabla de decision\",\n            \"DELETE-CONFIRM\": \"Borrar tabla de decision\",\n            \"USE-AS-NEW-VERSION\": \"Usar como nueva version\",\n            \"FAVORITE\": \"Maracar como favorita esta tabla de decision\",\n            \"DUPLICATE\": \"Duplicar esta tabla de decision\"\n        },\n        \"DETAILS\": {\n            \"HISTORY-TITLE\": \"Historial\",\n            \"COMMENTS-TITLE\": \"Comentarios\",\n            \"LAST-UPDATED-BY\": \"Ultimavez actualizado por {{lastUpdatedBy}} - {{lastUpdated | dateformat}}\",\n            \"CREATED-BY\": \"Creado por {{createdBy}}\"\n        },\n        \"HIT-POLICIES\": {\n            \"FIRST\": \"Primero (Single pass)\",\n            \"ANY\": \"Cualquiera (Single pass)\"\n        },\n        \"POPUP\": {\n            \"CREATE-TITLE\": \"Crear nueva tabla de decision\",\n            \"CREATE-DESCRIPTION\": \"Es necesario dar un nombre par a la tabla de decision, es recomendable proporcionar una descripcion al mismo tiempo.\",\n            \"DUPLICATE-TITLE\": \"Duplicar tabla de decision\",\n            \"DUPLICATE-DESCRIPTION\": \"Puedes dar un nombre para la nueba tabla de decision es recomendable proporcionar una descripcion al mismo tiempo.\",\n            \"SAVE-DESCRIPTION\": \"Es necesario proporcionar un nombre y un identificador unico para la tabla de decision, es recomendable proporcionar una descripcion al mismo tiempo\",\n            \"DELETE-TITLE\": \"Borrar tabla de decision\",\n            \"DELETE-DESCRIPTION\": \"Estas Seguro que deseas borrar esta tabla de decision \\\"{{name}}\\\"?\",\n            \"SAVE-DECISION-TABLE-TITLE\": \"Guardar tabla de decision\",\n            \"IMPORT-DESCRIPTION\": \"Busca o arrastra una definicion DMN XML con una extension .dmn o .dmn.xml\",\n          \t\"IMPORT-TITLE\": \"Importar un modelo DMN\",\n\t        \"IMPORT\": {\n\t            \"DROPZONE\": \"Arrastra un archivo.dmn o .dmn.xml DMN XML\",\n\t            \"CANCEL-UPLOAD\": \"Cancelar la carga\",\n\t            \"ERROR\": \"Error cuando se procesaba el archivo DMN XML\",\n\t            \"NO-DROP\": \"Arrastrar y soltar no soportado\"\n\t        },\n            \"USE-AS-NEW-TITLE\": \"Usar como nueva version\",\n            \"USE-AS-NEW-VERSION\": \"Usar como nueva version\",\n            \"USE-AS-NEW-DESCRIPTION\": \"Estas seguro que quieres utilizar la version {{version}} tpara crear una nueva version de \\\"{{name}}\\\"?\",\n            \"USE-AS-NEW-UNRESOLVED-MODELS-ERROR\": \"No se pudo restaurar completamente a la version seleccionada: Algunos modelos referenciados fueron borrados. Por favor actualiza el modelo. Moodelos faltantes:\",\n            \"USE-AS-NEW-UNRESOLVED-MODEL\": \"Modelo '{{name}}' con identificador {{id}}, creado por {{createdBy}}\"\n        },\n        \"ALERT\": {\n            \"FAVORITE-CONFIRM\": \"Esta tabla de decision es ahora favorita\",\n            \"UN-FAVORITE-CONFIRM\": \"Esta tabla de decision ya no es favorita\"\n        }\n    },\n\n    \"APP\": {\n        \"NAME\": \"Nombre de la App\",\n        \"KEY\": \"Identificador de la App\",\n        \"DESCRIPTION\": \"Descripcion\",\n        \"ICON\": \"Icono\",\n        \"THEME\": \"Tema\",\n        \"GROUPS-ACCESS\": \"Acceso a grupos, separado por comas\",\n        \"USERS-ACCESS\": \"Acceso a usuarios, separado por comas\",\n        \"ACTION\": {\n            \"DETAILS\": \"Mostrar detalles\",\n            \"EDIT\": \"Modificar propiedades de la App\",\n            \"DUPLICATE\": \"Duplicar esta App\",\n            \"SHARE\": \"Compartir esta App\",\n            \"DELETE\": \"Borrar esta App\",\n            \"CREATE-CONFIRM\": \"Crear nueva App\",\n            \"DUPLICATE-CONFIRM\": \"Duplicar App\",\n            \"DELETE-CONFIRM\": \"Borrar App\",\n            \"USE-AS-NEW-VERSION\": \"Usar como nueva version\",\n            \"OPEN-IN-EDITOR\": \"Editor de App\",\n            \"PUBLISH\": \"Publicar\",\n            \"PUBLISH-CONFIRM\": \"Publicar App\",\n            \"SELECT-ICON\": \"Cambiar icono...\",\n            \"SELECT-THEME\": \"Cambiar tema...\",\n            \"EDIT-MODELS\": \"Editar modelos incluidos\",\n            \"EXPORT-ZIP\": \"Exportar App como archivo zip\",\n            \"EXPORT-BAR\": \"Exportar App como archivo deployable bar\"\n\n        },\n        \"DETAILS\": {\n          \"TITLE\": \"Detalles de la App: {{name}}\",\n          \"HISTORY-TITLE\": \"Historial\",\n          \"MODELS-TITLE\": \"Modelos incluidos en la App\",\n          \"LAST-UPDATED-BY\": \"Ultima modificacion por {{lastUpdatedBy}} - {{lastUpdated | dateformat}}\",\n          \"CREATED-BY\": \"Creado por {{createdBy}}\",\n          \"NO-DESCRIPTION\": \"Esta App no tiene descripcion. Modifica las propiedades de la App para agregar una\",\n          \"NO-MODELS-SELECTED\": \"No hay modelos seleccionados para esta App\"\n        },\n        \"TITLE\": {\n          \"SELECT-ICON\": \"Seleccionar icono de la App\",\n          \"SELECT-THEME\": \"Seleccionar tema de la App\",\n          \"PREVIEW\": \"Vista previa\"\n\n        },\n        \"POPUP\": {\n          \"CREATE-TITLE\": \"Crear nueva App\",\n          \"DUPLICATE-TITLE\": \"Duplicar App\",\n          \"SAVE-APP-TITLE\": \"Guardar App\",\n          \"SAVE-APP-SAVE-SUCCESS\": \"App guardada\",\n          \"CREATE-DESCRIPTION\": \"Necesitas dar un nombre para la nueva App es recomendable proporcionar una descripcion al mismo tiempo\",\n          \"DUPLICATE-DESCRIPTION\": \"Puedes dar un nombre para la nueba App es recomendable proporcionar una descripcion al mismo tiempo\",\n          \"PUBLISH-TITLE\": \"Publicar App\",\n          \"PUBLISH-DESCRIPTION\": \"Estas seguro que deseas publicar la App \\\"{{name}}\\\"? Esta App sera versionada y actualizada en la App de workflow si ya existe.\",\n          \"PUBLISH-FIELD\": \"Publicar? Esta App sera versionada y actualizada en la App de workflow si ya existe.\",\n          \"PUBLISH-ERROR-PROCDEF-KEY-CONFLICT\": \"Tu modelo de proceso \\\"{{modelInAppName}}\\\" tiene el mismo identificador \\\"{{processDefinitionKey}}\\\" que el proceso existente deployado \\\"{{conflictingModelName}}\\\" de la App \\\"{{conflictingAppName}}\\\". Por favor cambia el \\\"id\\\" del modelo de proceso a algo diferente.\",\n          \"PUBLISH-ERROR-PROCESS-ALREADY-USED\": \"Los siguientes modelos de proceso ya son utilizados en otra App. Esto es correcto?\",\n          \"PUBLISH-ERROR-PROCESS-ALREADY-USED-APP\": \"App\",\n          \"PUBLISH-ERROR-PROCDEF-DUPLICATE-KEYS\": \"App invalida: se encontraron identificadores de proceso duplicados (cambia el \\\"id\\\" identificador de los procesos que tienen este detalle):\",\n          \"DELETE-TITLE\": \"Borrar App\",\n          \"DELETE-DESCRIPTION\": \"Estas seguro que deseas borrar la App \\\"{{name}}\\\"?\",\n          \"DELETE-DESCRIPTION-WITH-RUNTIME\": \"Estas seguro que deseas borrar la App \\\"{{name}}\\\"? Esta App se ha publicado en la vista de aplicaciones si confirmas, el acceso a la App sera removido.\",\n          \"DELETE-CASCADE-FALSE\": \"Borrar solo la version actual de la App (v{{version}})\",\n          \"DELETE-CASCADE-TRUE\": \"Borrar tambien las versiones anteriores de esta App\",\n          \"HAS-CUSTOM-STENCILITEM\" : \"Modelo \\\"{{modelName}}\\\" uses a stencil with custom stencil items. It is not possible to use this model in an App.\",\n          \"HAS-VALIDATIONERROR\" : \"Model \\\"{{modelName}}\\\" has validation errors and cannot be added to an App. Open the model in the editor to see more details about the validation error(s).\",\n          \"IMPORT-DESCRIPTION\":\"Por favor busca o arrastra una App con una extension .zip\",\n          \"IMPORT-TITLE\":\"Importar una App\",\n          \"IMPORT\": {\n              \"DROPZONE\": \"Arrastra un archivo de App .zip\",\n              \"CANCEL-UPLOAD\": \"Cancelar la carga\",\n              \"RENEWIDM-IDS\": \"Renueva los identificadores de grupo y de usuario cuando importes los modelos BPMN. Esto es comunmente requerido cuando importas la App en un ambiente de Flowable diferente. Se intentara ligar los pasos humanos y las tareas de usuario al usuario y grupo de usuarios correctos en este ambiente.\",\n              \"ERROR\": \"Error mientras se procesaba el archivo de la App\",\n              \"NO-DROP\": \"Arrastrar y soltar no soportado\"\n          },\n          \"INCLUDE-MODELS-TITLE\": \"Modelos incluidos en la App\"\n        },\n        \"ALERT\": {\n          \"DELETE-CONFIRM\": \"App Borrada\",\n          \"PUBLISH-CONFIRM\": \"La App ha sido publicada\",\n          \"PUBLISH-ERROR\": \"No se pude publicar la App. Por favor revisa que los modelos de proceso incluidos sean correctos\"\n        }\n    },\n\n    \"SHARE-INFO\": {\n        \"ACTION\": {\n          \"ADD\": \"Agregar otra persona\"\n        }\n    },\n\n    \"FORM-BUILDER\": {\n        \"PALLETTE\": {\n            \"TEXT\": \"Texto\",\n            \"PASSWORD\": \"Contraseña\",\n            \"MULTILINE-TEXT\": \"Texto en varias lineas\",\n            \"NUMBER\": \"Numero\",\n            \"CHECKBOX\": \"Checkbox\",\n            \"DATE\": \"Fecha\",\n            \"DROPDOWN\": \"Lista\",\n            \"RADIO\": \"Radio buttons\",\n            \"PEOPLE\": \"Personas\",\n            \"GROUP-OF-PEOPLE\": \"Grupo de personas\",\n            \"UPLOAD\": \"Upload\",\n            \"EXPRESSION\": \"Expresion\",\n\t    \t\"HYPERLINK\": \"Hipervínculo\",\n\t    \t\"SPACER\": \"Spacer\",\n\t\t\t\"HORIZONTAL-LINE\": \"Horizontal line\",\n\t\t\t\"HEADLINE\": \"Headline\",\n\t\t\t\"HEADLINE-WITH-LINE\":\"Headline\"\n        },\n        \"TABS\": {\n            \"GENERAL\": \"General\",\n            \"OPTIONS\": \"Opciones\",\n            \"UPLOAD-OPTIONS\": \"Opciones Upload\",\n\t    \"ADVANCED-OPTIONS\":\"Avanzado\"\t\n        },\n        \"VERSION\": \"Version {{version}}\",\n        \"LAST-UPDATED\": \"Ultima vez actualizado por {{lastUpdatedBy}}, {{lastUpdated | dateformat}}\",\n        \"TITLE\": {\n            \"DESIGN\": \"Diseño\",\n            \"OUTCOME\": \"Resultado\"\n        },\n        \"POPUP\": {\n            \"EDIT-TITLE\": \"Editar campo '{{name}}'\",\n            \"EXPRESSION-TITLE\": \"Editar expresion\"\n        },\n        \"MESSAGE\": {\n            \"EMPTY-EXPRESSION\": \"(No expression value)\",\n            \"EXPRESSION-HELP\": \"Tambien puedes mostrar valores enviados anteriormente en cualquier formulario, como parte del texto, referenciandolo utilizando una notacion como la siguiente ${myFieldId}.\",\n            \"OPTIONS-EXPRESSION-HELP\": \"Puede usar una expresión para completar dinámicamente las opciones, por ejemplo, haciendo referencia a una variable como esta ${optionsVariable}. La expresión debe dar como resultado un objeto java (java.util.List con objetos Option) o su representación json.\"\n        },\n        \"LABEL\" : {\n            \"FUNCTIONAL-GROUP\": \"Selecciona el grupo..\",\n            \"PERSON\": \"Selecciona persona...\"\n        },\n        \"COMPONENT\": {\n            \"LABEL\": \"Etiqueta:\",\n            \"OVERRIDEID\": \"Sobreescribir identificador?\",\n            \"ID\": \"Identificador:\",\n            \"PLACEHOLDER\": \"Placeholder:\",\n            \"OPTIONS\": \"Opciones\",\n            \"RADIO-BUTTON-DEFAULT\": \"Opcion 1\",\n            \"DROPDOWN-DEFAULT-EMPTY-SELECTION\": \"Por favor elige uno...\",\n            \"DROPDOWN-EMPTY-VALUE-HELP\": \"Este es la opcion 'valor vacio'. Seleccionar esto en tiempo de ejecucion es igual a 'no valor' o 'vacio'.  Esto esta permitido para campos opcionales, pero no para campos requeridos.\",\n            \"OPTIONS-EXPRESSION\": \"Expresión de opciones:\",\n            \"OPTIONS-EXPRESSION-ENABLED\": \"Habilitar expresión de opciones\",\n            \"REQUIRED\": \"Requerido\",\n            \"EXPRESSION\": \"Expresion\",\n            \"ADD-OPTION\": \"+ Agregar nueva opcion\",\n            \"UPLOAD-ALLOW-MULTIPLE\": \"Permitir subir varios archivos\",\n\t          \"MAX-LENGTH\":\"Longitud máxima:\",\n            \"MIN-LENGTH\":\"Longitud mínima:\",\n            \"PASSWORD-UNMASK-OPTION\": \"Opción de enmascaramiento/desenmascaramiento de contraseña\",\n\t          \"HYPERLINK-URL\": \"URL hiperlink\",\n\t          \"REGEX-PATTERN\":\"Estándar  Regex\",\n            \"MASK\":{\n              \"TITLE\":\"Máscara de entrada\",\n              \"EXAMPLES\":{\n                \"TITLE\":\"Ejemplos:\",\n                \"NUMBER\":\"Cualquier número\",\n                \"LETTER\":\"Cualquier letra\",\n                \"NUMBERORLETTER\":\"Cualquier letra o número\",\n                \"OPTIONAL\":\"La máscara opcional (no valida)\",\n                \"PHONE\":\"Teléfono\"\n\t              }\n            }\n        },\n        \"OUTCOMES\": {\n            \"DESCRIPTION\": \"Puedes definir multiples resultados para esta tarea. Cuando se este completando la tarea, el usuario selecciona uno de los resultados disponibles, que pueden ser utilizados por ejemplo eg. una condicion utilizada mas adelante en el proceso.\",\n            \"NO-OUTCOMES-OPTION\": \"Don't use custom outcomes, only show a 'Complete' button.\",\n            \"OUTCOMES-OPTION\": \"Usar resultados propios para este formulario.\",\n            \"POSSIBLE-OUTCOMES\": \"Posibles resultados\",\n            \"NEW-OUTCOME-PLACEHOLDER\": \"Introduce un nuevo resultado\",\n            \"ADD\": \"Agregar resultado\",\n            \"REMOVE\": \"Eliminar\"\n        }\n    },\n\n    \"DECISION-TABLE-EDITOR\": {\n        \"EMPTY-MESSAGES\": {\n            \"NO-VARIABLE-SELECTED\": \"Indefinido\"\n        },\n        \"POPUP\": {\n            \"EXPRESSION-EDITOR\": {\n                \"INPUT-TITLE\": \"Editar columna de entrada\",\n                \"INPUT-DESCRIPTION\": \"Seleccionar variable de entrada como ebtrada para la columna\",\n                \"OUTPUT-TITLE\": \"Editar columna de salida\",\n                \"OUTPUT-DESCRIPTION\": \"Selecionar una variable de salida existente o crear una nueva\",\n                \"EXPRESSION-LABEL\": \"Etiqueta de columna:\",\n                \"EXPRESSION-PLACEHOLDER\": \"Ingresar una etiqueta opcional\",\n                \"EXPRESSION-VARIABLE-NAME\": \"Nombre de variable:\",\n                \"EXPRESSION-VARIABLE-NAME-PLACEHOLDER\": \"Ingresar nombre de variable\",\n                \"OUTPUT-NEW-VARIABLE-ID\": \"Identificador de variable:\",\n                \"OUTPUT-NEW-VARIABLE-TYPE\": \"Tipo de variable:\"\n            }\n        },\n        \"BUTTON-ADD-INPUT-LABEL\": \"Agregar entrada\",\n        \"BUTTON-ADD-OUTPUT-LABEL\": \"Agregar salida\",\n        \"BUTTON-ADD-RULE-LABEL\": \"Agregar regla\",\n        \"BUTTON-MOVE-RULE-UPWARDS-LABEL\": \"Mover arriba\",\n        \"BUTTON-MOVE-RULE-DOWNWARDS-LABEL\": \"Mover abajo\",\n        \"BUTTON-REMOVE-RULE-LABEL\": \"Eliminar regla\",\n        \"ALERT\": {\n            \"EXPRESSION-VARIABLE-REQUIRED-ERROR\": \"Todas las expresiones de entrada y salida deben referenciar un campo del formulario o una variable.\",\n            \"SAVE-CONFIRM\": \"Guardar tabla de decision '{{name}}'\"\n        }\n    },\n\n    \"TOUR\": {\n        \"WELCOME-TITLE\": \"Bienvenido, {{userName}}\",\n        \"WELCOME-CONTENT\": \"Esta es una pequeña guia del Editor Flowable. Los siguientes pasos te guiaran a traves de diferentes secciones de la aplicacion.Presion ESC para detener la guia en cualquier momento.\" ,\n        \"PALETTE-TITLE\": \"Barra de dibujo\",\n        \"PALETTE-CONTENT\": \"Todos los simbolos necesarios para crear un proceso de negocio pueden ser encontrados aqui. Se encuentran agrupados de manera logica. Para abrir un grupo simplemente da click en el:\",\n        \"CANVAS-TITLE\": \"El area de trabajo\",\n        \"CANVAS-CONTENT\": \"En este espacio crea tu proceso de negocio. Arrastra elementos desde la barra de dibujoe en la izquierda y sueltalos en esta area para empezar a modelar.\",\n        \"DRAGDROP-TITLE\": \"Ejemplo arrastrar y soltar\",\n        \"DRAGDROP-CONTENT\": \"aqui esta un ejemplo de como comenzar a modelar:\",\n        \"PROPERTIES-TITLE\": \"Propiedades\",\n        \"PROPERTIES-CONTENT\": \"Aqui puedes configurar las propuedades de un proceso de negocios. Simplemente selecciona un elemento en el area de trabajo y sus propiedades serán mostradas. Da click en la propiedad si deseas editarla\",\n        \"TOOLBAR-TITLE\": \"Barra de herramientas\",\n        \"TOOLBAR-CONTENT\": \"Todas las acciones pueden ser encontradas aqui: guardar o validar un modelo, copiar y pegar partes del proceso, y continua. Pasa sobre los botnones para ver lo que realizan.\",\n        \"END-TITLE\": \"Fin\",\n        \"END-CONTENT\": \"Ahora puedes modelar tus procesos. Si tienes alguna duda, sientete libre de preguntar en <a href=\\\"http://forum.flowable.org/\\\" target=\\\"_blank\\\">Flowable Forum</a> \"\n    },\n\n    \"FEATURE-TOUR\" : {\n        \"BENDPOINT\" : {\n            \"TITLE\": \"Tutorial punto de curva\",\n            \"DESCRIPTION\" : \"Cuando estas conectando un elemento con otro usando un flujo de secuencia (Esas flechas entre los pasos del proceso), encontraras que esos flujos de secuencia se crean de manera automatica, si deseas modificar la direccione de las flechas, puedes agregar o eliminar un punto de curva de un flujo de secuencia.<br/> Como se muestra debajo en la figura, primero das click en el boton 'Agregar punto curva'y despues das click en el flujo de secuencia al que deseas agregarlo. El fluo de secuencia te indicará con un punto en verde que el punto curva puede ser agregado.<br/> Para eliminar un punto curva, click en 'eliminar punto curva' y da click en el flujo de secuencia del cual deseas eliminar.\"\n        }\n    },\n\n    \"ACTION.OK\" : \"Ok\",\n    \"ACTION.SAVE\" : \"Guardar\",\n    \"ACTION.SAVE-AND-CLOSE\" : \"Guardar y cerrar el editor\",\n    \"ACTION.SEND\" : \"Enviar\",\n    \"ACTION.CANCEL\" : \"Cancelar\",\n    \"ACTION.SELECT\" : \"Seleccionar\",\n    \"ACTION.ADD\" : \"Agregar\",\n    \"ACTION.REMOVE\" : \"Eliminar\",\n    \"ACTION.MOVE.UP\" : \"Mover arriba\",\n    \"ACTION.MOVE.DOWN\" : \"Mover abajo\",\n\n    \"TOOLBAR.ACTION.CLOSE\" : \"Cerrar el editor y volver a la pagina de previsualizacion\",\n    \"TOOLBAR.ACTION.SAVE\" : \"Guardar el modelo\",\n    \"TOOLBAR.ACTION.VALIDATE\" : \"Validar el modelo\",\n    \"TOOLBAR.ACTION.CUT\" : \"Cortar (seleciona uno o mas elementos en tu proceso de negocio)\",\n    \"TOOLBAR.ACTION.COPY\" : \"Copiar (seleciona uno o mas elementos en tu proceso de negocio)\",\n    \"TOOLBAR.ACTION.PASTE\" : \"Pegar\",\n    \"TOOLBAR.ACTION.DELETE\" : \"Borrar el elemento seleccionado\",\n    \"TOOLBAR.ACTION.UNDO\" : \"Deshacer\",\n    \"TOOLBAR.ACTION.REDO\" : \"Rehacer\",\n    \"TOOLBAR.ACTION.ZOOMIN\" : \"Zoom in\",\n    \"TOOLBAR.ACTION.ZOOMOUT\" : \"Zoom out\",\n    \"TOOLBAR.ACTION.ZOOMACTUAL\" : \"Zoom a tamaño actual\",\n    \"TOOLBAR.ACTION.ZOOMFIT\" : \"Zoom para ajustar\",\n    \"TOOLBAR.ACTION.BENDPOINT.ADD\" : \"Agregar punto de curva al flujo de secuencia seleccionado\",\n    \"TOOLBAR.ACTION.BENDPOINT.REMOVE\" : \"Eliminar punto de curva al flujo de secuencia seleccionado\",\n    \"TOOLBAR.ACTION.ALIGNHORIZONTAL\" : \"Alinear modelo horizontalmente\",\n    \"TOOLBAR.ACTION.ALIGNVERTICAL\" : \"Alinear modelo verticalmente\",\n    \"TOOLBAR.ACTION.SAMESIZE\" : \"Mismo tamaño\",\n    \"TOOLBAR.ACTION.HELP\": \"Iniciar la visita guiada\",\n    \"TOOLBAR.ACTION.FEEDBACK\": \"Proveer retroalimentacion\",\n\n    \"FORM_TOOLBAR.ACTION.SAVE\" : \"Guardar el modelo\",\n\n    \"APP_DEFINITION_TOOLBAR.ACTION.SAVE\" : \"Guardar la App\",\n\n    \"BUTTON.ACTION.DELETE.TOOLTIP\": \"Borrar elemento del modelo\",\n    \"BUTTON.ACTION.MORPH.TOOLTIP\": \"Cambiar tipo del elemento\",\n\n    \"ELEMENT.AUTHOR\" : \"Autor\",\n    \"ELEMENT.DATE_CREATED\" : \"Fecha de creacion\",\n\n    \"PROPERTY.REMOVED\" : \"eliminado\",\n    \"PROPERTY.EMPTY\" : \"Sin valor\",\n    \"PROPERTY.PROPERTY.EDIT.TITLE\" : \"Cambiar valor por\",\n\n    \"PROPERTY.FEEDBACK.TITLE\" : \"Por favor proporciona tu retroalimentacion\",\n\n    \"PROPERTY.ASSIGNMENT.TITLE\" : \"Asignacion\",\n    \"PROPERTY.ASSIGNMENT.TYPE\" : \"Tipo\",\n    \"PROPERTY.ASSIGNMENT.TYPE.IDENTITYSTORE\" : \"Almacen de identidad\",\n    \"PROPERTY.ASSIGNMENT.TYPE.STATIC\" : \"Valores arreglados\",\n    \"PROPERTY.ASSIGNMENT.ASSIGNEE\" : \"Asignado\",\n    \"PROPERTY.ASSIGNMENT.MATCHING\" : \"Usa &uparrow; y &downarrow; para seleccionar y presiona Enter para confirmar o usa el mouse\",\n    \"PROPERTY.ASSIGNMENT.ASSIGNEE_PLACEHOLDER\" : \"Introduce un asignado\",\n    \"PROPERTY.ASSIGNMENT.EMPTY\" : \"No hay asignacion seleccionada\",\n    \"PROPERTY.ASSIGNMENT.NONE\" : \"Ninguno ...\",\n    \"PROPERTY.ASSIGNMENT.PLACEHOLDER-SEARCHUSER\": \"Buscar usuario\",\n    \"PROPERTY.ASSIGNMENT.PLACEHOLDER-SEARCHGROUP\": \"Buscar grupo\",\n    \"PROPERTY.ASSIGNMENT.SEARCH\": \"Buscar: \",\n    \"PROPERTY.ASSIGNMENT.ASSIGNEE_DISPLAY\" : \"Assignado {{assignee}}\",\n    \"PROPERTY.ASSIGNMENT.CANDIDATE_USERS_DISPLAY\" : \"{{length}} Usuarios candidatos\",\n    \"PROPERTY.ASSIGNMENT.CANDIDATE_USERS\" : \"Usuarios candidatos\",\n    \"PROPERTY.ASSIGNMENT.CANDIDATE_GROUPS_DISPLAY\" :  \"{{length}} Grupos candidatos\",\n    \"PROPERTY.ASSIGNMENT.CANDIDATE_GROUPS\" :  \"Grupos candidatos\",\n    \"PROPERTY.ASSIGNMENT.USER_IDM_DISPLAY\": \"Usuario {{firstName}} {{lastName}}\",\n    \"PROPERTY.ASSIGNMENT.USER_IDM_EMAIL_DISPLAY\": \"Usuario {{email}}\",\n    \"PROPERTY.ASSIGNMENT.USER_IDM_FIELD_DISPLAY\": \"Campo {{name}}\",\n    \"PROPERTY.ASSIGNMENT.IDM_EMPTY\" : \"Iniciador del proceso\",\n    \"PROPERTY.ASSIGNMENT.IDM.TYPE\" : \"Asignacion\",\n    \"PROPERTY.ASSIGNMENT.IDM.NO_CANDIDATE_USERS\" : \"No hay usuarios candidatos seleccionados...\",\n    \"PROPERTY.ASSIGNMENT.IDM.NO_CANDIDATE_GROUPS\" : \"No hay grupos candidatos seleccionados...\",\n    \"PROPERTY.ASSIGNMENT.IDM.DROPDOWN.INITIATOR\" : \"Asignar al iniciador del proceso\",\n    \"PROPERTY.ASSIGNMENT.IDM.DROPDOWN.USER\" : \"Asignar a un solo usuario\",\n    \"PROPERTY.ASSIGNMENT.IDM.DROPDOWN.USERS\" : \"Usuarios candidatos\",\n    \"PROPERTY.ASSIGNMENT.IDM.DROPDOWN.GROUPS\" : \"Grupos candidatos\",\n    \"PROPERTY.ASSIGNMENT.INITIATOR-CAN-COMPLETE\" : \"Permitir al iniciador del proceso completar la tarea\",\n    \"PROPERTY.EXECUTIONLISTENERS.DISPLAY\" : \"{{length}} escuchadores de ejecucion\",\n    \"PROPERTY.EXECUTIONLISTENERS.EMPTY\" : \"No hay escuchadores de ejecucion configurados\",\n    \"PROPERTY.EXECUTIONLISTENERS.EVENT\" : \"Evento\",\n    \"PROPERTY.EXECUTIONLISTENERS.CLASS\" : \"Clase\",\n    \"PROPERTY.EXECUTIONLISTENERS.CLASS.PLACEHOLDER\" : \"Introduce un nombre de clase\",\n    \"PROPERTY.EXECUTIONLISTENERS.EXPRESSION\" : \"Expresion\",\n    \"PROPERTY.EXECUTIONLISTENERS.EXPRESSION.PLACEHOLDER\" : \"Introduce una expresion\",\n    \"PROPERTY.EXECUTIONLISTENERS.DELEGATEEXPRESSION\" : \"Expresion delegada\",\n    \"PROPERTY.EXECUTIONLISTENERS.DELEGATEEXPRESSION.PLACEHOLDER\" : \"Introduce una expresion delegada\",\n    \"PROPERTY.EXECUTIONLISTENERS.UNSELECTED\" : \"No hay escuchadores de ejecucion seleccionados\",\n    \"PROPERTY.EXECUTIONLISTENERS.FIELDS.NAME\" : \"Nombre\",\n    \"PROPERTY.EXECUTIONLISTENERS.FIELDS.NAME.PLACEHOLDER\" : \"Introduce un nombre\",\n    \"PROPERTY.EXECUTIONLISTENERS.FIELDS.EXPRESSION\" : \"Expresion\",\n    \"PROPERTY.EXECUTIONLISTENERS.FIELDS.EXPRESSION.PLACEHOLDER\" : \"Introduce una expresion\",\n    \"PROPERTY.EXECUTIONLISTENERS.FIELDS.STRINGVALUE\" : \"Valor cadena\",\n    \"PROPERTY.EXECUTIONLISTENERS.FIELDS.STRINGVALUE.PLACEHOLDER\" : \"Introduce una cadena\",\n    \"PROPERTY.EXECUTIONLISTENERS.FIELDS.STRING\" : \"Cadena\",\n    \"PROPERTY.EXECUTIONLISTENERS.FIELDS.STRING.PLACEHOLDER\" : \"Introduce una cadena\",\n    \"PROPERTY.EXECUTIONLISTENERS.FIELDS.IMPLEMENTATION\" : \"Implementacion\",\n    \"PROPERTY.EXECUTIONLISTENERS.FIELDS.EMPTY\" : \"No hay un campo seleccionado\",\n\n    \"PROPERTY.FIELDS\" : \"{{length}} campos\",\n    \"PROPERTY.FIELDS.EMPTY\" : \"No hay campos seleccionados\",\n    \"PROPERTY.FIELDS.NAME\" : \"Nombre\",\n    \"PROPERTY.FIELDS.NAME.PLACEHOLDER\" : \"Introduce un nombre\",\n    \"PROPERTY.FIELDS.EXPRESSION\" : \"Expresion\",\n    \"PROPERTY.FIELDS.EXPRESSION.PLACEHOLDER\" : \"Ingresa una expresion\",\n    \"PROPERTY.FIELDS.STRINGVALUE\" : \"Valor cadena\",\n    \"PROPERTY.FIELDS.STRINGVALUE.PLACEHOLDER\" : \"Introduce una cadena\",\n    \"PROPERTY.FIELDS.STRING\" : \"Cadena\",\n    \"PROPERTY.FIELDS.STRING.PLACEHOLDER\" : \"Introduce una cadena\",\n    \"PROPERTY.FIELDS.IMPLEMENTATION\" : \"Implementacion\",\n\n    \"PROPERTY.FORMPROPERTIES.VALUE\" : \"{{length}} propiedades del formulario\",\n    \"PROPERTY.FORMPROPERTIES.EMPTY\" : \"No hay propiedades del formulario seleccionadas\",\n    \"PROPERTY.FORMPROPERTIES.ID\" : \"Identificador\",\n    \"PROPERTY.FORMPROPERTIES.ID.PLACEHOLDER\" : \"Introduce un identificador\",\n    \"PROPERTY.FORMPROPERTIES.NAME\" : \"Nombre\",\n    \"PROPERTY.FORMPROPERTIES.NAME.PLACEHOLDER\" : \"Introduce un nombre\",\n    \"PROPERTY.FORMPROPERTIES.TYPE\" : \"Tipo\",\n    \"PROPERTY.FORMPROPERTIES.DATEPATTERN\" : \"Patron de fecha\",\n    \"PROPERTY.FORMPROPERTIES.DATEPATTERN.PLACEHOLDER\" : \"Introduce un patron de fecha\",\n    \"PROPERTY.FORMPROPERTIES.VALUES\" : \"Valores\",\n    \"PROPERTY.FORMPROPERTIES.ENUMVALUES.EMPTY\" : \"Nose selecciono un valor enum\",\n    \"PROPERTY.FORMPROPERTIES.VALUES.ID\" : \"Identificador\",\n    \"PROPERTY.FORMPROPERTIES.VALUES.NAME\" : \"Nombre\",\n    \"PROPERTY.FORMPROPERTIES.VALUES.ID.PLACEHOLDER\" : \"Introdice el identificador del valor\",\n  \t\"PROPERTY.FORMPROPERTIES.VALUES.NAME.PLACEHOLDER\" : \"Introduce el nombre del valor\",\n    \"PROPERTY.FORMPROPERTIES.EXPRESSION\" : \"Expresion\",\n    \"PROPERTY.FORMPROPERTIES.EXPRESSION.PLACEHOLDER\" : \"Introduce una expresion\",\n    \"PROPERTY.FORMPROPERTIES.VARIABLE\" : \"Variable\",\n    \"PROPERTY.FORMPROPERTIES.VARIABLE.PLACEHOLDER\" : \"Introduce una variable\",\n    \"PROPERTY.FORMPROPERTIES.DEFAULT\" : \"default\",\n    \"PROPERTY.FORMPROPERTIES.DEFAULT.PLACEHOLDER\" : \"Introduce una default\",\n    \"PROPERTY.FORMPROPERTIES.REQUIRED\" : \"Requerido\",\n    \"PROPERTY.FORMPROPERTIES.READABLE\" : \"Leible\",\n    \"PROPERTY.FORMPROPERTIES.WRITABLE\" : \"Escribible\",\n\n    \"PROPERTY.INPARAMETERS.VALUE\" : \"{{length}} parametros de entrada\",\n    \"PROPERTY.INPARAMETERS.EMPTY\" : \"No hay parametros de entrada configurados\",\n\n    \"PROPERTY.OUTPARAMETERS.VALUE\" : \"{{length}} parametros de salida\",\n    \"PROPERTY.OUTPARAMETERS.EMPTY\" : \"No hay parametros de salida configurados\",\n\n    \"PROPERTY.PARAMETER.SOURCE\" : \"Fuente\",\n    \"PROPERTY.PARAMETER.SOURCE.PLACEHOLDER\" : \"Introduce una fuente\",\n    \"PROPERTY.PARAMETER.SOURCEEXPRESSION\" : \"Expresion de fuente\",\n    \"PROPERTY.PARAMETER.SOURCEEXPRESSION.PLACEHOLDER\" : \"Expresion de fuente\",\n    \"PROPERTY.PARAMETER.TARGET\" : \"Objetivo\",\n    \"PROPERTY.PARAMETER.TARGET.PLACEHOLDER\" : \"Introduce un objetivo\",\n    \"PROPERTY.PARAMETER.EMPTY\" : \"No hay parametro seleccionado\",\n\n    \"PROPERTY.SUBPROCESSREFERENCE.EMPTY\" : \"No hay referencia seleccionada\",\n    \"PROPERTY.SUBPROCESSREFERENCE.TITLE\" : \"Referencia a subproceso colapsado\",\n    \"PROPERTY.SUBPROCESSREFERENCE.ERROR.SUBPROCESS\" : \"Ocurrio un error cargando subprocesos. Intenta mas tarde\",\n    \"PROPERTY.SUBPROCESSREFERENCE.SUBPROCESS.LOADING\" : \"Cargando subprocesos...\",\n    \"PROPERTY.SUBPROCESSREFERENCE.SUBPROCESS.EMPTY\" : \"Este folder no contiene subprocesos\",\n\n    \"PROPERTY.FORMREFERENCE.EMPTY\" : \"No hay referencia seleccionada\",\n    \"PROPERTY.FORMREFERENCE.TITLE\" : \"Referencia a formulario\",\n    \"PROPERTY.FORMREFERENCE.DESCRIPTION\" : \"Referencia a formulario\",\n    \"PROPERTY.FORMREFERENCE.ERROR.FORM\" : \"Ocurrio un error cargando los formularios. Intenta mas tarde\",\n    \"PROPERTY.FORMREFERENCE.FORM.LOADING\" : \"Cargando formularios...\",\n    \"PROPERTY.FORMREFERENCE.FORM.EMPTY\" : \"Este folder no contiene formularios\",\n\n    \"PROPERTY.TASKLISTENERS.VALUE\" : \"{{length}} escuchadores de tarea\",\n    \"PROPERTY.TASKLISTENERS.EMPTY\" : \"No hay escuchadores de tarea configurados\",\n    \"PROPERTY.TASKLISTENERS.EVENT\" : \"Evento\",\n    \"PROPERTY.TASKLISTENERS.CLASS\" : \"Clase\",\n    \"PROPERTY.TASKLISTENERS.CLASS.PLACEHOLDER\" : \"Introduce un nombre de clase\",\n    \"PROPERTY.TASKLISTENERS.EXPRESSION\" : \"Expresion\",\n    \"PROPERTY.TASKLISTENERS.EXPRESSION.PLACEHOLDER\" : \"Introduce una expresion\",\n    \"PROPERTY.TASKLISTENERS.DELEGATEEXPRESSION\" : \"Delegar expresion\",\n    \"PROPERTY.TASKLISTENERS.DELEGATEEXPRESSION.PLACEHOLDER\" : \"Introduce una expresion de delegado\",\n    \"PROPERTY.TASKLISTENERS.UNSELECTED\" : \"No hay escuchadores de tarea seleccionados\",\n    \"PROPERTY.TASKLISTENERS.FIELDS.NAME\" : \"Nombre\",\n    \"PROPERTY.TASKLISTENERS.FIELDS.NAME.PLACEHOLDER\" : \"Introduce un nombre\",\n    \"PROPERTY.TASKLISTENERS.FIELDS.EXPRESSION\" : \"Expresion\",\n    \"PROPERTY.TASKLISTENERS.FIELDS.EXPRESSION.PLACEHOLDER\" : \"Introduce una expresion\",\n    \"PROPERTY.TASKLISTENERS.FIELDS.STRINGVALUE\" : \"Valor cadena\",\n    \"PROPERTY.TASKLISTENERS.FIELDS.STRINGVALUE.PLACEHOLDER\" : \"Introduce una cadena\",\n    \"PROPERTY.TASKLISTENERS.FIELDS.STRING\" : \"Cadena\",\n    \"PROPERTY.TASKLISTENERS.FIELDS.STRING.PLACEHOLDER\" : \"Introduce una cadena\",\n    \"PROPERTY.TASKLISTENERS.FIELDS.IMPLEMENTATION\" : \"Implementacion\",\n    \"PROPERTY.TASKLISTENERS.FIELDS.EMPTY\" : \"No hay campo seleccionado\",\n\n    \"PROPERTY.EVENTLISTENERS.DISPLAY\" : \"{{length}} escuchadores de evento\",\n    \"PROPERTY.EVENTLISTENERS.EMPTY\" : \"No hay esuchadores de evento seleecionados\",\n    \"PROPERTY.EVENTLISTENERS.EVENTS\": \"Eventos\",\n    \"PROPERTY.EVENTLISTENERS.RETHROW\": \"Relanzar evento?\",\n    \"PROPERTY.EVENTLISTENERS.CLASS\" : \"Clase\",\n    \"PROPERTY.EVENTLISTENERS.CLASS.PLACEHOLDER\" : \"Introduce un nombre de clase\",\n    \"PROPERTY.EVENTLISTENERS.DELEGATEEXPRESSION\" : \"Expresion delegada\",\n    \"PROPERTY.EVENTLISTENERS.DELEGATEEXPRESSION.PLACEHOLDER\" : \"Introduce una expresion de delegado\",\n    \"PROPERTY.EVENTLISTENERS.ENTITYTYPE\" : \"Tipo de entidad\",\n    \"PROPERTY.EVENTLISTENERS.ENTITYTYPE.PLACEHOLDER\" : \"Introduce un tipo de entidad\",\n    \"PROPERTY.EVENTLISTENERS.RETHROWTYPE\": \"Relanzar tipo de evento\",\n    \"PROPERTY.EVENTLISTENERS.ERRORCODE\" : \"Codigo de error\",\n    \"PROPERTY.EVENTLISTENERS.ERRORCODE.PLACEHOLDER\" : \"Introduce un codigo de error\",\n    \"PROPERTY.EVENTLISTENERS.MESSAGENAME\" : \"Nombre de mensaje\",\n    \"PROPERTY.EVENTLISTENERS.MESSAGENAME.PLACEHOLDER\" : \"Introduce un nombre de mensaje\",\n    \"PROPERTY.EVENTLISTENERS.SIGNALNAME\" : \"Nombre de señal\",\n    \"PROPERTY.EVENTLISTENERS.SIGNALNAME.PLACEHOLDER\" : \"Introduce un nombre de señal\",\n    \"PROPERTY.EVENTLISTENERS.UNSELECTED\" : \"No hay escuchador de evento seleccionado\",\n\n    \"PROPERTY.PLANITEMLIFECYCLELISTENERS.VALUE\" : \"{{length}} lifecycle listeners\",\n    \"PROPERTY.PLANITEMLIFECYCLELISTENERS.EMPTY\" : \"No lifecycle listeners configured\",\n    \"PROPERTY.PLANITEMLIFECYCLELISTENERS.EVENT\" : \"Event\",\n    \"PROPERTY.PLANITEMLIFECYCLELISTENERS.SOURCE_STATE\" : \"Source state\",\n    \"PROPERTY.PLANITEMLIFECYCLELISTENERS.TARGET_STATE\" : \"Target state\",\n    \"PROPERTY.PLANITEMLIFECYCLELISTENERS.CLASS\" : \"Class\",\n    \"PROPERTY.PLANITEMLIFECYCLELISTENERS.CLASS.PLACEHOLDER\" : \"Enter a classname\",\n    \"PROPERTY.PLANITEMLIFECYCLELISTENERS.EXPRESSION\" : \"Expression\",\n    \"PROPERTY.PLANITEMLIFECYCLELISTENERS.EXPRESSION.PLACEHOLDER\" : \"Enter an expression\",\n    \"PROPERTY.PLANITEMLIFECYCLELISTENERS.DELEGATEEXPRESSION\" : \"Delegate expression\",\n    \"PROPERTY.PLANITEMLIFECYCLELISTENERS.DELEGATEEXPRESSION.PLACEHOLDER\" : \"Enter a delegate expression\",\n    \"PROPERTY.PLANITEMLIFECYCLELISTENERS.UNSELECTED\" : \"No task listener selected\",\n    \"PROPERTY.PLANITEMLIFECYCLELISTENERS.FIELDS.NAME\" : \"Name\",\n    \"PROPERTY.PLANITEMLIFECYCLELISTENERS.FIELDS.NAME.PLACEHOLDER\" : \"Enter a name\",\n    \"PROPERTY.PLANITEMLIFECYCLELISTENERS.FIELDS.EXPRESSION\" : \"Expression\",\n    \"PROPERTY.PLANITEMLIFECYCLELISTENERS.FIELDS.EXPRESSION.PLACEHOLDER\" : \"Enter an expression\",\n    \"PROPERTY.PLANITEMLIFECYCLELISTENERS.FIELDS.STRINGVALUE\" : \"String value\",\n    \"PROPERTY.PLANITEMLIFECYCLELISTENERS.FIELDS.STRINGVALUE.PLACEHOLDER\" : \"Enter a string value\",\n    \"PROPERTY.PLANITEMLIFECYCLELISTENERS.FIELDS.STRING\" : \"String\",\n    \"PROPERTY.PLANITEMLIFECYCLELISTENERS.FIELDS.STRING.PLACEHOLDER\" : \"Enter a string\",\n    \"PROPERTY.PLANITEMLIFECYCLELISTENERS.FIELDS.IMPLEMENTATION\" : \"Implementation\",\n    \"PROPERTY.PLANITEMLIFECYCLELISTENERS.FIELDS.EMPTY\" : \"No Field selected\",\n\n    \"PROPERTY.SIGNALDEFINITIONS.DISPLAY\" : \"{{length}} definiciones de señal\",\n    \"PROPERTY.SIGNALDEFINITIONS.EMPTY\" : \"No hay definiciones de señal\",\n    \"PROPERTY.SIGNALDEFINITIONS.SCOPE-GLOBAL\": \"Global\",\n    \"PROPERTY.SIGNALDEFINITIONS.SCOPE-PROCESSINSTANCE\": \"Instancia de proceso\",\n    \"PROPERTY.SIGNALDEFINITIONS.ID\" : \"Identificador\",\n    \"PROPERTY.SIGNALDEFINITIONS.NAME\" : \"Nombre\",\n    \"PROPERTY.SIGNALDEFINITIONS.SCOPE\" : \"Alcance\",\n\n    \"PROPERTY.MESSAGEDEFINITIONS.DISPLAY\" : \"{{length}} definiciones de mensaje\",\n    \"PROPERTY.MESSAGEDEFINITIONS.EMPTY\" : \"No hay definiciones de mensaje configuradas\",\n    \"PROPERTY.MESSAGEDEFINITIONS.ID\" : \"Identificador\",\n    \"PROPERTY.MESSAGEDEFINITIONS.NAME\" : \"Nombre\",\n\n    \"PROPERTY.SEQUENCEFLOW.ORDER.EMPTY\" : \"No se definio el orden de los flujos de secuencia\",\n    \"PROPERTY.SEQUENCEFLOW.ORDER.NOT.EMPTY\" : \"Orden de flujos de secuencia fijado\",\n    \"PROPERTY.SEQUENCEFLOW.ORDER.NO.OUTGOING.SEQUENCEFLOW.FOUND\" : \"No se encontro un flujo de secuencia de salida.\",\n    \"PROPERTY.SEQUENCEFLOW.ORDER.DESCRIPTION\" : \"Fijar el orden en el cual el flujo de secuencia necesita ser evaluado:\",\n    \"PROPERTY.SEQUENCEFLOW.ORDER.SEQUENCEFLOW.VALUE\" : \"Flujo de secuencia a {{targetType}} {{targetTitle}}\",\n\n    \"PROPERTY.SEQUENCEFLOW.CONDITION.TITLE\" : \"Condicion del flujo de secuencia\",\n    \"PROPERTY.SEQUENCEFLOW.CONDITION.STATIC\" : \"Expresion de la condicion\",\n    \"PROPERTY.SEQUENCEFLOW.CONDITION.NO-CONDITION-DISPLAY\": \"No hay condicion fijada\",\n\n    \"PROPERTY.DUEDATE.EMPTY\" : \"No se definio fecha de vencimiento\",\n    \"PROPERTY.DUEDATE.DEFINED\" : \"Se definio fecha de vencimiento\",\n    \"PROPERTY.DUEDATE.TITLE\" : \"Fecha de vencimiento\",\n    \"PROPERTY.DUEDATE.EXPRESSION-LABEL\" : \"Expression de fecha de vencimiento\",\n    \"PROPERTY.DUEDATE.TASK-DUE-DATE-OPTIONS.NO-DUEDATE\" : \"No hay fecha de vencimiento\",\n    \"PROPERTY.DUEDATE.TASK-DUE-DATE-OPTIONS.EXPRESSION\" : \"Definicion de expresion\",\n    \"PROPERTY.DUEDATE.TASK-DUE-DATE-OPTIONS.STATIC\" : \"Duracion arreglada despues de la creacion de la tarea\",\n    \"PROPERTY.DUEDATE.TASK-DUE-DATE-OPTIONS.FIELD\" : \"Basado en un campo\",\n\n    \"MODEL.SAVE.TITLE\" : \"Guardar modelo\",\n    \"MODEL.VALIDATE.TITLE\" : \"Resultados de validacion\",\n    \"MODEL.NAME\" : \"Nombre\",\n    \"MODEL.KEY\" : \"Llave\",\n    \"MODEL.DESCRIPTION\" : \"Descripcion\",\n    \"MODEL.SAVE.NEWVERSION\" : \"Guardar como nueva version?  Esto significa que siempre podras volver a una version anterior\",\n    \"MODEL.SAVE.COMMENT\" : \"Comentario\",\n    \"MODEL.SAVE.SAVING\" : \"Guardando modelo\",\n    \"MODEL.LASTMODIFIEDDATE\" : \"Ultimo guardado\",\n    \"MODEL.SAVE.ERROR\": \"Error inesperado: No se pudo guardar el modelo\",\n    \"MODEL.VALIDATIONERRORS\": \"El modelo tiene errores de validacion. El modelo no puede deployarse al Flowable Engine en el estado actual.\",\n    \"MODEL.CONFLICT.WRITE\": \"No se puede guardar el modelo: '{{userFullName}}' ha echo cambios a este modelo\",\n    \"MODEL.CONFLICT.WRITE.OPTIONS\": \"Selecciona una opcion para solucionar esto:\",\n    \"MODEL.CONFLICT.WRITE.OPTION.OVERWRITE\": \"Sobreescribir el otro modelo\",\n    \"MODEL.CONFLICT.WRITE.OPTION.DISCARDCHANGES\": \"Descartar mis cambios\",\n    \"MODEL.CONFLICT.WRITE.OPTION.SAVEAS\": \"Guardar como nuevo modelo\",\n    \"MODEL.CONFLICT.WRITE.OPTION.NEWVERSION\": \"Crrear una nueva version\",\n    \"MODEL.CONFLICT.SAVEAS\" : \"Guardar como:\",\n\n    \"EVENT_TYPE.ACTIVITY.COMPENSATE.TOOLTIP\": \"Una actividad esta apunto de ser ejecutada como compensacion para otra actividad. Los eventos objetivo de la actividad que esta apunto de ser ejecutada para la compensacion\",\n    \"EVENT_TYPE.ACTIVITY.COMPLETED.TOOLTIP\": \"Una actividad se ha completado exitosamente\",\n    \"EVENT_TYPE.ACTIVITY.ERROR.RECEIVED.TOOLTIP\": \"Una actividad ha recibido un mensaje de error. Enviado antes que el actual error haya sido recibido por la actividad\",\n    \"EVENT_TYPE.MEMBERSHIP.CREATED.TOOLTIP\": \"Una nueva membresia ha sido creada\",\n    \"EVENT_TYPE.MEMBERSHIP.DELETED.TOOLTIP\": \"Una sola membresia ha sido borrada\",\n    \"EVENT_TYPE.MEMBERSHIPS.DELETED.TOOLTIP\": \"Todas las membresias relacionadas a un grupo han sido borradas. No se enviaran eventos individuales debido a razones de desempeño\",\n    \"EVENT_TYPE.TASK.ASSIGNED.TOOLTIP\": \"Una tarea se ha asignado. Se lanzo junto al evento ENTITY_UPDATED\",\n    \"EVENT_TYPE.TASK.COMPLETED.TOOLTIP\": \"Una tarea ha sido completada. Antes que la entidad sea borrada\",\n    \"EVENT_TYPE.UNCAUGHT.BPMNERROR.TOOLTIP\": \"Cuando un error BPMN fue lanzado, pero no fue atrapado dentro del proceso\",\n    \"EVENT_TYPE.VARIABLE.CREATED.TOOLTIP\": \"Una nueva variable se creo\",\n    \"EVENT_TYPE.VARIABLE.DELETED.TOOLTIP\": \"Una variable existente fue borrada\",\n    \"EVENT_TYPE.VARIABLE.UPDATED.TOOLTIP\": \"Una variable existente fue actualizada\",\n\n    \"PROPERTY.DECISIONTABLEREFERENCE.EMPTY\" : \"No hay referencia selecionada\",\n    \"PROPERTY.DECISIONTABLEREFERENCE.TITLE\" : \"Tabla de decision referenciada\",\n    \"PROPERTY.DECISIONTABLEREFERENCE.ERROR.FORM\" : \"Ocurrio un error cargando la tabla de decisiones. Intenta mas tarde\",\n    \"PROPERTY.DECISIONTABLEREFERENCE.DECISIONTABLE.LOADING\" : \"Cargando tabla de decisiones...\",\n    \"PROPERTY.DECISIONTABLEREFERENCE.DECISIONTABLE.EMPTY\" : \"Este folder no contiene tablas de decisiones\"\n}\n"
  },
  {
    "path": "flowable-ui-web/modeler/i18n/fr.json",
    "content": "{\n    \"GENERAL\" : {\n        \"MAIN-TITLE\": \"Flowable Editeur\",\n        \"NAVIGATION\" : {\n            \"PROCESSES\": \"Processus\",\n            \"CASEMODELS\": \"Modèle de cas\",\n            \"FORMS\": \"Formulaires\",\n            \"DECISION-TABLES\": \"Tables de décision\",\n            \"APPS\": \"Apps\"\n        },\n        \"TITLE\": {\n            \"SELECT-GROUP\" :\"Sélectionner un groupe\",\n            \"MATCHING-GROUPS\": \"Groupes correspondants\",\n            \"FILTER\": \"Filtre\",\n            \"HISTORY\": \"Historique\"\n        },\n        \"ACTION\": {\n            \"LOGOUT\": \"Déconnexion\",\n            \"RETURN-TO-LIST\": \"Afficher toutes les définitions\",\n            \"CANCEL\": \"Annuler\",\n            \"CLOSE\": \"Fermer\",\n            \"EDIT\": \"Editer\",\n            \"SAVE\": \"Sauver\",\n            \"OPEN\": \"Ouvrir\",\n            \"OK\": \"Ok\",\n            \"CONFIRM\": \"Confirmer\",\n            \"CONFIRM-AND-CLOSE\": \"Confirmer et fermer\",\n            \"NEW-FORM\": \"Nouveau formulaire\",\n            \"CREATE-FORM\": \"Créer un formulaire\",\n            \"NEW-DECISION-TABLE\": \"Nouvelle table de décision\",\n            \"CREATE-DECISION-TABLE\": \"Créer une table de décision\"\n        },\n        \"MESSAGE\": {\n          \"SELECT-GROUP-HELP\": \"Utiliser &uparrow; et &downarrow; pour sélectionner et appuyer sur entrée pour confirmer \",\n          \"PEOPLE-NO-MATCHING-RESULTS\": \"Aucun utilisateur correspondant n'a été trouvé\",\n          \"GROUP-NO-MATCHING-RESULTS\": \"Aucun groupe correspondant n'a été trouvé\",\n          \"GROUP-SOURCE-TYPE\": \"Groupe source\",\n          \"GROUP-SOURCE-SEARCH-OPTION\": \"Recherche de Groupe\",\n          \"GROUP-SOURCE-FIELD-OPTION\": \"Champ de formulaire\"\n        }\n    },\n\n    \"EDITOR\": {\n      \"POPUP\": {\n        \"UNSAVED-CHANGES\": {\n          \"TITLE\": \"Vous avez des modifications non enregistrées \",\n          \"DESCRIPTION\": \"Que voulez vous faire des modifications non sauvegardées ?\",\n          \"ACTION\": {\n            \"SAVE\": \"Sauver\",\n            \"DISCARD\": \"Ignorer les changements\",\n            \"CONTINUE\": \"Continuer à éditer\"\n          }\n        }\n      }\n    },\n\n    \"PROCESS-LIST\" : {\n        \"TITLE\" : \"Modèles de processus métiers\",\n        \"SEARCH-PLACEHOLDER\": \"Rechercher\",\n        \"ACTION\" : {\n            \"CREATE\": \"Créer un processus\",\n            \"IMPORT\": \"Importer un processus\"\n        },\n\n        \"FILTER\" : {\n            \"PROCESSES\": \"Modèles de processus\",\n            \"PROCESSES-COUNT\": \"Il y a {{total}} modèles de processus\",\n            \"PROCESSES-ONE\": \"Il y a un modèle de processus\",\n            \"PROCESSES-EMPTY\": \"Il n'y a pas de modèle de processus encore créé. Vous pouvez créer des modèles de processus, des formulaires et les  grouper au sein d'une application. La première étpage consiste à créer ce modèle de processus:\",\n            \"PROCESSES-BPMN-HINT\": \"Créer un modèle BPMN en utilisant l'Editeur visuel BPMN.\",\n            \"PROCESSES-BPMN-IMPORT-HINT\": \"Vous pouvez aussi importer des modèles BPMN existants.\",\n            \"FILTER-TEXT\": \", correspondant à \\\"{{filterText}}\\\"\",\n            \"FILTER-TEXT-EMPTY\": \"Il n'y a pas de modèles de processus correspondant à \\\"{{filterText}}\\\"\",\n            \"RECENT\": \"Récent\",\n            \"RECENT-COUNT\": \"{{total}} modèles récemment utilisés\",\n            \"RECENT-ONE\": \"Un modèle récemment utilisé\",\n            \"RECENT-EMPTY\": \"Aucun modèle récemment utilisé\"\n        },\n\n        \"SORT\": {\n            \"MODIFIED-ASC\": \"Du plus vieux\",\n            \"MODIFIED-DESC\": \"Dernières modifications\",\n            \"NAME-ASC\": \"Nom, A-Z\",\n            \"NAME-DESC\": \"Nom, Z-A\"\n        }\n    },\n    \n    \"CASE-LIST\" : {\n        \"TITLE\" : \"Modèles de Cas\",\n        \"SEARCH-PLACEHOLDER\": \"Recherche\",\n        \"ACTION\" : {\n            \"CREATE\": \"Créer un Cas\",\n            \"IMPORT\": \"Importer un Cas\"\n        },\n\n        \"FILTER\" : {\n            \"CASES\": \"Modèles de Cas\",\n            \"CASES-COUNT\": \"Il y a {{total}} modèles de Cas\",\n            \"CASES-ONE\": \"Il y a un modèle de Cas\",\n            \"CASES-EMPTY\": \"Aucun modèle de cas n'a encore été créé. Vous pouvez créer un modèle de cas, des formulaires et les grouper au sein d'une définition d'App. La première étape consiste à créer ce modèle de Cas:\",\n            \"CASES-CMMN-HINT\": \"Créer un modèle CMMN en utilisant l'éditeur visuel CMMN.\",\n            \"CASES-CMMN-IMPORT-HINT\": \"Vous pouvez aussi importer un modèle CMMN existant.\",\n            \"FILTER-TEXT\": \", correspondant à \\\"{{filterText}}\\\"\",\n            \"FILTER-TEXT-EMPTY\": \"Il n'y a pas de modèle de cas correspondant à  \\\"{{filterText}}\\\"\",\n            \"RECENT\": \"Récent\",\n            \"RECENT-COUNT\": \"{{total}}modèles récemment utilisés\",\n            \"RECENT-ONE\": \"Un modèle récemment utilisé\",\n            \"RECENT-EMPTY\": \"Aucun modèle récemment utilisé\"\n        },\n\n        \"SORT\": {\n            \"MODIFIED-ASC\": \"Du plus vieux\",\n            \"MODIFIED-DESC\": \"Dernières modifications\",\n            \"NAME-ASC\": \"Nom, A-Z\",\n            \"NAME-DESC\": \"Nom, Z-A\"\n        }\n    },\n\n    \"FORMS-LIST\" : {\n        \"TITLE\" : \"Formulaires\",\n        \"SEARCH-PLACEHOLDER\": \"Recherche\",\n        \"ACTION\" : {\n            \"CREATE\": \"Créer un formulaire\",\n            \"CREATE-INLINE\": \"Créer un nouveau formulaire maintenant!\",\n            \"SHOW-MORE\": \"Voir plus...\"\n        },\n\n        \"FILTER\" : {\n            \"FORMS\": \"Formulaires\",\n            \"FORMS-COUNT\": \"Il y a {{total}} formulaires\",\n            \"FORMS-ONE\": \"Il y a un formulaire\",\n            \"FORMS-EMPTY\": \"Il n'y a pas formulaires.  Pour en ajouter un, cliquer sur Créer formulaire.\",\n            \"FILTER-TEXT\": \", correspondant \\\"{{filterText}}\\\"\",\n            \"FILTER-TEXT-EMPTY\": \"Il n'y a pas de formulaires correspondant à \\\"{{filterText}}\\\"\"\n        },\n\n        \"SORT\": {\n            \"MODIFIED-ASC\": \"Du plus vieux\",\n            \"MODIFIED-DESC\": \"Dernières modifications\",\n            \"NAME-ASC\": \"Nom, A-Z\",\n            \"NAME-DESC\": \"Nom, Z-A\"\n        }\n    },\n\n    \"DECISION-TABLES-LIST\": {\n        \"TITLE\": \"Tables de décision\",\n        \"SEARCH-PLACEHOLDER\": \"Recherche\",\n        \"ACTION\": {\n            \"CREATE\": \"Créer une table de décision\",\n            \"IMPORT\": \"Importer une table de décision\",\n            \"CREATE-INLINE\": \"Créer une nouvelle table de décision maintenant!\",\n            \"SHOW-MORE\": \"Voir plus...\"\n        },\n\n        \"FILTER\": {\n            \"DECISION-TABLES\": \"Table de décisions\",\n            \"DECISION-TABLES-COUNT\": \"Il y a {{total}} tables de décision\",\n            \"DECISION-TABLES-ONE\": \"Il y a une table de décision\",\n            \"DECISION-TABLES-EMPTY\": \"Il n'y a pas de table de décisions. Pour en ajouter une, cliquer sur Créer une table de décision.\",\n            \"FILTER-TEXT\": \", correspondant \\\"{{filterText}}\\\"\",\n            \"FILTER-TEXT-EMPTY\": \"Il n'y a pas de table de décision correpondants à  \\\"{{filterText}}\\\"\"\n        },\n\n        \"SORT\": {\n            \"MODIFIED-ASC\": \"Du plus vieux\",\n            \"MODIFIED-DESC\": \"Dernières modifications\",\n            \"NAME-ASC\": \"Nom, A-Z\",\n            \"NAME-DESC\": \"Nom, Z-A\"\n        }\n    },\n\n    \"APPS-LIST\" : {\n        \"TITLE\" : \"Définitions d'App\",\n        \"SEARCH-PLACEHOLDER\": \"Recherche\",\n        \"ACTION\" : {\n            \"CREATE\": \"Créer une App\",\n            \"IMPORT\": \"Importer une App\",\n            \"SHOW-MORE\": \"Voir plus...\"\n        },\n\n        \"FILTER\" : {\n            \"APPS\": \"Définitions d'App\",\n            \"APPS-COUNT\": \"Il y a {{total}} définitions d'App\",\n            \"APPS-ONE\": \"Il y a une définition d'App\",\n            \"APPS-EMPTY\": \"Il n'y a pas de définitions d'App. Pour en ajouter une, cliquer sur Créer une Définition d'App .\",\n            \"FILTER-TEXT\": \", correspondant à \\\"{{filterText}}\\\"\",\n            \"FILTER-TEXT-EMPTY\": \"Il n'y a pas de définitions d'App correpondant à \\\"{{filterText}}\\\"\",\n\n            \"NO-APPS\": \"Vous pouvez créer une définition d'App en publiant un  paquet de modèles de processus.\",\n            \"NO-APPS-CALL-TO-ACTION\": \"Vous pouvez créer une définition d'App maintenant.\",\n            \"NO-APPS-NOTE\": \"N'oubliez pas de Publier quand vous êtes prêt à l'utiliser.\"\n        },\n\n        \"SORT\": {\n            \"MODIFIED-ASC\": \"Du plus vieux\",\n            \"MODIFIED-DESC\": \"Dernières modifications\",\n            \"NAME-ASC\": \"Nom, A-Z\",\n            \"NAME-DESC\": \"Nom, Z-A\"\n        }\n    },\n    \"PROCESS\": {\n      \"NAME\": \"Nom du Modèle\",\n      \"KEY\": \"Clé du Modèle\",\n      \"DESCRIPTION\": \"Description\",\n      \"VERSION-COMMENT\": \"Commentaire de version\",\n      \"ACTION\": {\n            \"DETAILS\": \"Voir les détails\",\n            \"EDIT\": \"Modifier les propriétés du modèle\",\n            \"DUPLICATE\": \"Dupliquer le modèle\",\n            \"EXPORT_BPMN20\": \"Exporter en BPMN 2.0\",\n            \"DELETE\": \"Supprimer le modèle\",\n            \"CREATE-CONFIRM\": \"Créer un nouveau modèle\",\n            \"DUPLICATE-CONFIRM\": \"Dupliquer le modèle\",\n            \"OPEN-IN-EDITOR\": \"Editeur Visuel\",\n            \"EDIT-CONFIRM\": \"Sauvegarder\",\n            \"DELETE-CONFIRM\": \"Supprimer le modèle de processus\",\n            \"USE-AS-NEW-VERSION\": \"Utiliser en tant que nouvelle version\",\n            \"FAVORITE\": \"Mettre en favori ce modèle\"\n\n        },\n        \"DETAILS\": {\n          \"HISTORY-TITLE\": \"Historique\",\n          \"LAST-UPDATED-BY\": \"Dernière modification par {{lastUpdatedBy}} - {{lastUpdated | dateformat}}\",\n          \"CREATED-BY\": \"Créé par {{createdBy}}\",\n          \"NO-DESCRIPTION\": \"Ce modèle n'a pas de description. Modifier les propriétés du modèle pour en ajouter un.\"\n        },\n\n        \"POPUP\": {\n          \"CREATE-TITLE\": \"Créer un nouveau modèle de processus métier\",\n          \"DUPLICATE-TITLE\": \"Dupliquer un modèle de processus métier\",\n          \"CREATE-DESCRIPTION\": \"Vous devez donner un nom à ce modèle et en même temps vous devriez en profiter pour ajouter une description. \",\n          \"DUPLICATE-DESCRIPTION\": \"Vous pouvez changer le nom du nouveau modèle et en même temps vous devriez en profiter pour ajouter une description.\",\n          \"EDIT-DESCRIPTION\": \"Modifier les propriétés ci-dessous et ensuite appuyer sur Sauvegarder pour mettre à jour le modèle.\",\n          \"DELETE-DESCRIPTION\": \"Êtes-vous sûr de vouloir supprimer le modèle de processus \\\"{{name}}\\\"?\",\n          \"EDIT-TITLE\":\"Modifier les détails du modèle\",\n          \"DELETE-TITLE\": \"Supprimer le modèle\",\n          \"DELETE-LOADING-RELATIONS\": \"Vérification des usages du modèle...\",\n          \"DELETE-RELATIONS-DESCRIPTION-SINGLE\": \"Ce modèle ne peut être supprimé car un autre modèle l'utilise:\",\n          \"DELETE-RELATIONS-DESCRIPTION\": \"Ce modèle ne peut être supprimé car il est utilisé par d'autres modèles:\",\n          \"DELETE-PROCESS-RELATION\": \"Modèle de processus\",\n          \"DELETE-FORM-RELATION\": \"Modèle de formulaire\",\n          \"DELETE-APP-RELATION\": \"Modèle d'App\",\n          \"IMPORT-DESCRIPTION\": \"Veuillez naviguer vers ou déposer un fichier de défnition BPMN XML avec une extension en .bpmn ou .bpmn20.xml\",\n          \"IMPORT-TITLE\": \"Importer un modèle de processus\",\n          \"USE-AS-NEW-TITLE\": \"Utiliser en tant que nouvelle version\",\n          \"USE-AS-NEW-DESCRIPTION\": \"Êtes-vous sûr de vouloir utiliser la version {{version}} pour créer une nouvelle version de  \\\"{{name}}\\\"?\",\n          \"USE-AS-NEW-UNRESOLVED-MODELS-ERROR\": \"Impossibilité de restaurer le modèle d'App dans la version choisie: certains modèles référencés sont manquants car précédemment supprimés. Veuillez mettre à jour votre modèle d'App en conséquence. Modèles manquants:\",\n          \"USE-AS-NEW-UNRESOLVED-MODEL\": \"Modèle '{{name}}' avec un identifiant interne {{id}}, créé par {{createdBy}}\",\n          \"SHARED-WITH\": \"Partagé avec\",\n          \"PERMISSION\": \"Permission\",\n          \"ACTIONS\": \"Actions\",\n          \"IMPORT\": {\n              \"DROPZONE\": \"Déposer un fichier BPMN avec une extension en .bpmn ou .bpmn20.xml\",\n              \"CANCEL-UPLOAD\": \"Annuler l'envoi\",\n              \"ERROR\": \"Une erreur s'est produite lors du traitement du fichier BPMN XML\",\n              \"NO-DROP\": \"Glisser/déposer n'est pas supporté\"\n          }\n        },\n        \"ALERT\": {\n          \"EDIT-CONFIRM\": \"Modèle mise à jour\"\n        },\n        \"ERROR\": {\n          \"NOT-FOUND\": \"Le modèle demandé n'existe pas.\"\n        }\n    },\n\n    \"SUBPROCESS\": {\n        \"NAME\": \"Nom du sous-processus\",\n        \"DESCRIPTION\": \"Description\",\n        \"ACTION\": {\n            \"CREATE-CONFIRM\": \"Créer un nouveau sous-processus\"\n        },\n        \"POPUP\": {\n            \"CREATE-TITLE\": \"Créer un nouveau sous-processus\",\n            \"CREATE-DESCRIPTION\": \"Vous devez donner un nom au nouveau sous-processus et en même temps vous devriez ajouter une description.\"\n        }\n    },\n    \n    \"CASE\": {\n      \"NAME\": \"Nom du Modèle\",\n      \"KEY\": \"Clé du Modèle\",\n      \"DESCRIPTION\": \"Description\",\n      \"VERSION-COMMENT\": \"Commentaire de Version\",\n      \"ACTION\": {\n            \"DETAILS\": \"Voir les détails\",\n            \"EDIT\": \"Modifier les propriétés du modèle\",\n            \"DUPLICATE\": \"Dupliquer ce modèle\",\n            \"EXPORT_CMMN\": \"Exporter en CMMN 1.1\",\n            \"DELETE\": \"Supprimer ce modèle\",\n            \"CREATE-CONFIRM\": \"Créer un nouveau modèle\",\n            \"DUPLICATE-CONFIRM\": \"Dupliquer ce modèle\",\n            \"OPEN-IN-EDITOR\": \"Editeur Visuel\",\n            \"EDIT-CONFIRM\": \"Sauvegarder\",\n            \"DELETE-CONFIRM\": \"Supprimer ce modèle de Cas \",\n            \"USE-AS-NEW-VERSION\": \"Utiliser en tant que nouvelle version\",\n            \"FAVORITE\": \"Mettre en favori ce modèle\"\n\n        },\n        \"DETAILS\": {\n          \"HISTORY-TITLE\": \"Historique\",\n          \"LAST-UPDATED-BY\": \"Dernière modification par {{lastUpdatedBy}} - {{lastUpdated | dateformat}}\",\n          \"CREATED-BY\": \"Created by {{createdBy}}\",\n          \"NO-DESCRIPTION\": \"Ce modèle n'a pas de description. Modifier les propriétés du modèle pour en ajouter un.\"\n        },\n\n        \"POPUP\": {\n          \"CREATE-TITLE\": \"Créer un nouveau modèle de Cas \",\n          \"DUPLICATE-TITLE\": \"Dupliquer le modèle de Cas \",\n          \"CREATE-DESCRIPTION\": \"Vous devez donner un nom au nouveau modèle et en même temps vous devriez ajouter une description.\",\n          \"DUPLICATE-DESCRIPTION\": \"Vous pouvez changer le nom du nouveau modèle et en même temps vous devriez en profiter pour ajouter une description.\",\n          \"EDIT-DESCRIPTION\": \"Modifier les propriétés ci-dessous du modèle et appuyez sur Sauvegarder pour mettre à jour le modèle.\",\n          \"DELETE-DESCRIPTION\": \"Êtes-vous sûr de want to supprimer the modèle de processus \\\"{{name}}\\\"?\",\n          \"EDIT-TITLE\":\"Edit modèle details\",\n          \"DELETE-TITLE\": \"Supprimer modèle\",\n          \"DELETE-LOADING-RELATIONS\": \"Checking modèle usage...\",\n          \"DELETE-RELATIONS-DESCRIPTION-SINGLE\": \"This modèle cannot be deleted, because another modèle is using it:\",\n          \"DELETE-RELATIONS-DESCRIPTION\": \"This modèle cannot be deleted, because it is used by other models:\",\n          \"DELETE-PROCESS-RELATION\": \"Cas modèle\",\n          \"DELETE-FORM-RELATION\": \"formulaire modèle\",\n          \"DELETE-APP-RELATION\": \"App modèle\",\n          \"IMPORT-DESCRIPTION\": \"Please browse for or drop a CMMN XML definition with an .cmmn or .cmmn.xml extension\",\n          \"IMPORT-TITLE\": \"Import a Cas modèle\",\n          \"USE-AS-NEW-TITLE\": \"Use as new version\",\n          \"USE-AS-NEW-DESCRIPTION\": \"Êtes-vous sûr de vouloir utiliser la version {{version}} afin de créer une nouvelle  version de \\\"{{name}}\\\"?\",\n          \"USE-AS-NEW-UNRESOLVED-MODELS-ERROR\": \"Impossibilité de restaurer le modèle à la version choisie: certains modèles référencés sont manquants car précédemment supprimés. Veuillez mettre à jour votre modèle d'App en conséquence. Modèles manquants:\",\n          \"USE-AS-NEW-UNRESOLVED-MODEL\": \"Modèle '{{name}}' avec l'identifiant interne {{id}}, créé par {{createdBy}}\",\n          \"SHARED-WITH\": \"Partagé avec\",\n          \"PERMISSION\": \"Permission\",\n          \"ACTIONS\": \"Actions\",\n          \"IMPORT\": {\n              \"DROPZONE\": \"Déposer un fichier CMMN XML avec une extension .cmmn ou .cmmn.xml \",\n              \"CANCEL-UPLOAD\": \"Annuler l'envoi\",\n              \"ERROR\": \"Erreur durant le traitement du fichier CMMN XML \",\n              \"NO-DROP\": \"Glisser/Déposer n'est pas supporté.\"\n          }\n        },\n        \"ALERT\": {\n          \"EDIT-CONFIRM\": \"Modèle mis à jour\"\n        },\n        \"ERROR\": {\n          \"NOT-FOUND\": \"Le modèle demandé n'existe pas\"\n        }\n    },\n\n    \"FORM\": {\n      \"NAME\": \"Nom du formulaire\",\n      \"KEY\": \"Clé du formulaire\",\n      \"DESCRIPTION\": \"Description\",\n      \"ACTION\": {\n            \"DETAILS\": \"Afficher les détails\",\n            \"EDIT\": \"Modifier les propriétés du modèle\",\n            \"DELETE\": \"Supprimer le formulaire\",\n            \"CREATE-CONFIRM\": \"Créer un nouveau formulaire\",\n            \"DUPLICATE\": \"Dupliquer ce formulaire\",\n            \"DUPLICATE-CONFIRM\": \"Dupliquer le formulaire\",\n            \"OPEN-IN-EDITOR\": \"Editeur de formulaire\",\n            \"EDIT-CONFIRM\": \"Sauvegarder\",\n            \"DELETE-CONFIRM\": \"Supprimer le formulaire\",\n            \"USE-AS-NEW-VERSION\": \"Utiliser en tant que nouvelle version\"\n\n        },\n        \"DETAILS\": {\n          \"HISTORY-TITLE\": \"Historique\",\n          \"LAST-UPDATED-BY\": \"Dernière modification par {{lastUpdatedBy}} - {{lastUpdated | dateformat}}\",\n          \"CREATED-BY\": \"Créé par {{createdBy}}\"\n        },\n\n        \"POPUP\": {\n          \"CREATE-TITLE\": \"Créer un nouveau formulaire\",\n          \"DUPLICATE-TITLE\": \"Dupliquer le formulaire\",\n          \"CREATE-DESCRIPTION\": \"Vous devez donner un nom au nouveau formulaire et en même temps vous devriez ajouter une description.\",\n          \"DUPLICATE-DESCRIPTION\": \"Vous devez donner un nom au nouveau formulaire et en même temps vous devriez ajouter une description.\",\n          \"SAVE-FORM-TITLE\": \"Sauvegarder le formulaire\",\n          \"EDIT-DESCRIPTION\": \"Modifier les propriétés ci-dessous du formulaire et ensuite appuyer sur Sauvegarder pour mettre à jour le formulaire\",\n          \"DELETE-DESCRIPTION\": \"Êtes-vous sûr de vouloir supprimer le formulaire \\\"{{name}}\\\"?\",\n          \"EDIT-TITLE\":\"Editer les détails du formulaire\",\n          \"DELETE-TITLE\": \"Supprimer le formulaire\",\n          \"USE-AS-NEW-TITLE\": \"Utiliser en tant que nouvelle version\",\n          \"USE-AS-NEW-VERSION\": \"Utiliser en tant que nouvelle version\",\n          \"USE-AS-NEW-DESCRIPTION\": \"Êtes-vous sûr d'utiliser la version {{version}} pour créer une nouvelle version de \\\"{{name}}\\\"?\",\n          \"USE-AS-NEW-UNRESOLVED-MODELS-ERROR\": \"Impossibilité de restaurer le modèle à la version choisie: certains modèles référencés sont manquants car précédemment supprimés. Veuillez mettre à jour votre modèle d'App en conséquence. Modèles manquants:\",\n          \"USE-AS-NEW-UNRESOLVED-MODEL\": \"Modèle '{{name}}'avec l'identifiant interne {{id}}, créé par {{createdBy}}\"\n        }\n    },\n\n    \"DECISION-TABLE\": {\n        \"NAME\": \"Nom de la table de décision\",\n        \"KEY\": \"Clé de la table de décision\",\n        \"DESCRIPTION\": \"Description\",\n        \"VERSION-COMMENT\": \"Commentaire de Version\",\n        \"HIT-POLICY\": \"Hit Policy:\",\n        \"ACTION\": {\n            \"DETAILS\": \"Afficher les détails\",\n            \"EDIT\": \"Modifier les propriétés du modèle\",\n            \"SHARE\": \"Partager cette table de décision\",\n            \"DELETE\": \"Supprimer cette table de décision\",\n            \"ADD-COMMENT\": \"+ Ajouter un commentaire\",\n            \"CREATE-CONFIRM\": \"Créer une nouvelle table de décision\",\n            \"OPEN-IN-EDITOR\": \"Editeur de table de décision\",\n            \"EXPORT\": \"Exporter la table de décision\",\n            \"DELETE-CONFIRM\": \"Supprimer la table de décision\",\n            \"USE-AS-NEW-VERSION\": \"Utiliser en tant que nouvelle version\",\n            \"FAVORITE\": \"Mettre en favori cette table de décision\",\n            \"DUPLICATE\": \"Dupliquer cette table de décision\"\n        },\n        \"DETAILS\": {\n            \"HISTORY-TITLE\": \"Historique\",\n            \"COMMENTS-TITLE\": \"Commentaires\",\n            \"LAST-UPDATED-BY\": \"Dernière modification par {{lastUpdatedBy}} - {{lastUpdated | dateformat}}\",\n            \"CREATED-BY\": \"Créé par {{createdBy}}\"\n        },\n        \"HIT-POLICIES\": {\n            \"FIRST\": \"Les premiers\",\n            \"ANY\": \"Tous\",\n            \"UNIQUE\": \"Unique\",\n            \"PRIORITY\": \"Priorité\",\n            \"RULE ORDER\": \"Ordre des règles\",\n            \"OUTPUT ORDER\": \"Ordre de résultats\",\n            \"COLLECT\": \"Collecte\"\n        },\n        \"COLLECT-OPERATORS\": {\n            \"SUM\": \"Sum\",\n            \"MIN\": \"Min\",\n            \"MAX\": \"Max\",\n            \"COUNT\": \"Count\"\n        },\n        \"POPUP\": {\n            \"CREATE-TITLE\": \"Créer une nouvelle table de décision\",\n            \"CREATE-DESCRIPTION\": \"Vous devez donner un nom à la nouvelle table de décision et en même temps vous devriez ajouter une description.\",\n            \"SAVE-DESCRIPTION\": \"Vous devez donner un nom à la nouvelle table de décision ainsi qu'une clé unique et en même temps vous devriez ajouter une description.\",\n            \"DUPLICATE-TITLE\": \"Dupliquer la table de décision\",\n            \"DUPLICATE-DESCRIPTION\": \"Vous devez donner un nom à la nouvelle table de décision et en même temps vous devriez ajouter une description.\",\n            \"DELETE-TITLE\": \"Supprimer la table de décision\",\n            \"DELETE-DESCRIPTION\": \"Êtes-vous sûr de vouloir supprimer la table de décision \\\"{{name}}\\\"?\",\n            \"SAVE-DECISION-TABLE-TITLE\": \"Sauvegarder la table de décision\",\n            \"IMPORT-DESCRIPTION\": \"Veuillez naviguer vers ou déposer un fichier de définition DMN XML avec une extension en .dmn ou .dmn.xml\",\n          \t\"IMPORT-TITLE\": \"Importer un modèle DMN \",\n\t        \"IMPORT\": {\n\t            \"DROPZONE\": \"Déposer un fichier DMN XML avec une extension en a .dmn ou .dmn.xml\",\n\t            \"CANCEL-UPLOAD\": \"Annuler l'envoi\",\n\t            \"ERROR\": \"Erreurr lors du tratiement du fichier DMN XML\",\n\t            \"NO-DROP\": \"Glisser/Déposer n'est pas supporté.\"\n\t        },\n            \"USE-AS-NEW-TITLE\": \"Utiliser en tant que nouvelle version\",\n            \"USE-AS-NEW-VERSION\": \"Utiliser en tant que nouvelle version\",\n            \"USE-AS-NEW-DESCRIPTION\": \"Êtes-vous sûr de vouloir utiliser la version {{version}} pour créer une nouvelle version de \\\"{{name}}\\\"?\",\n            \"USE-AS-NEW-UNRESOLVED-MODELS-ERROR\": \"Impossibilité de restaurer le modèle à la version choisie: certains modèles référencés sont manquants car précédemment supprimés. Veuillez mettre à jour votre modèle d'App en conséquence. Modèles manquants:\",\n            \"USE-AS-NEW-UNRESOLVED-MODEL\": \"Modèle '{{name}}' avec l'identifiant interne {{id}}, créé par {{createdBy}}\"\n        },\n        \"ALERT\": {\n            \"FAVORITE-CONFIRM\": \"La table de décision est maintenant en favori\",\n            \"UN-FAVORITE-CONFIRM\": \"La table de décision n'est plus marqué en favori\"\n        }\n    },\n\n    \"APP\": {\n        \"NAME\": \"Nom de la définition d'App\",\n        \"KEY\": \"Clé de la définition d'App\",\n        \"DESCRIPTION\": \"Description\",\n        \"ICON\": \"Icône\",\n        \"THEME\": \"Thème\",\n        \"GROUPS-ACCESS\": \"Groupes avec accès, séparés par des virgules\",\n\t\t\"USERS-ACCESS\": \"Utilisateurs avec access, séparés par des virgules\",\n        \"ACTION\": {\n            \"DETAILS\": \"Afficher les détails\",\n            \"EDIT\": \"Modifier les propriétés de la définition d'App\",\n            \"DUPLICATE\": \"Dupliquer la définition\",\n            \"SHARE\": \"Partagé la définition d'App\",\n            \"DELETE\": \"Supprimer la définition d'App\",\n            \"CREATE-CONFIRM\": \"Créer une nouvelle définition d'App\",\n            \"DUPLICATE-CONFIRM\": \"Dupliquer la définition d'App\",\n            \"DELETE-CONFIRM\": \"Supprimer la définition d'App\",\n            \"USE-AS-NEW-VERSION\": \"Utiliser en tant que nouvelle version\",\n            \"OPEN-IN-EDITOR\": \"Editeur d'App\",\n            \"PUBLISH\": \"Publier\",\n            \"PUBLISH-CONFIRM\": \"Publier la définition d'App\",\n            \"SELECT-ICON\": \"Changer l'icône...\",\n            \"SELECT-THEME\": \"Change le thème...\",\n            \"EDIT-MODELS\": \"Editer les modèles inclus\",\n            \"EXPORT-ZIP\": \"Exporter la définition d'App dans un fichier zip\",\n            \"EXPORT-BAR\": \"Exporter la définition d'App en tant que fichier bar deployable\"\n\n        },\n        \"DETAILS\": {\n          \"TITLE\": \"Détails de la définition d'App: {{name}}\",\n          \"HISTORY-TITLE\": \"Historique\",\n          \"MODELS-TITLE\": \"Modèles inclus dans la définition d'App\",\n          \"LAST-UPDATED-BY\": \"Dernière modification par {{lastUpdatedBy}} - {{lastUpdated | dateformat}}\",\n          \"CREATED-BY\": \"Créé par {{createdBy}}\",\n          \"NO-DESCRIPTION\": \"La définition d'App n'a pas de description. Modifier les propriétés de la définition d'App pour en ajouter une\",\n          \"NO-MODELS-SELECTED\": \"Aucun modèle n'a été sélectionné pour cette App\"\n        },\n        \"TITLE\": {\n          \"SELECT-ICON\": \"Choisir une icône d'App\",\n          \"SELECT-THEME\": \"Choisir des couleurs d'App\",\n          \"PREVIEW\": \"Prévisualiser\"\n\n        },\n        \"POPUP\": {\n          \"CREATE-TITLE\": \"Créer une nouvelle définition d'App\",\n          \"DUPLICATE-TITLE\": \"Dupliquer une définition d'App\",\n          \"SAVE-APP-TITLE\": \"Sauvegarder la définition d'App\",\n          \"SAVE-APP-SAVE-SUCCESS\": \"La définition d'App a été sauvé\",\n          \"CREATE-DESCRIPTION\": \"Vous devez donner un nom à la nouvelle définition d'App et en même temps vous devriez ajouter une description.\",\n          \"DUPLICATE-DESCRIPTION\": \"Vous devez donner un nom à la nouvelle définition d'App et en même temps vous devriez ajouter une description.\",\n          \"PUBLISH-TITLE\": \"Publier la définition d'App\",\n          \"PUBLISH-DESCRIPTION\": \"Êtes-vous sûr de vouloir publier la définition d'App \\\"{{name}}\\\"? A noter que cette définition d'App sera versionné et l'App de sera mise à jour s'il existe\",\n          \"PUBLISH-FIELD\": \"Publier? A noter que si la publication est activé,la définition d'App sera versionné et que l'App de workflow  sera mis à jour s'il existe. .\",\n          \"PUBLISH-ERROR-PROCDEF-KEY-CONFLICT\": \"Votre modèle de processus \\\"{{modelInAppName}}\\\" a le même identifiant \\\"{{processDefinitionKey}}\\\" que le processus déjà déployé \\\"{{conflictingModelName}}\\\" de l'App \\\"{{conflictingAppName}}\\\". Veuillez changer la valeur de la propriété \\\"id\\\" du modèle de processus.\",\n          \"PUBLISH-ERROR-PROCESS-ALREADY-USED\": \"Les modèles de processus sont déjà utilisés dans d'autres applications. Est ce normal ?\",\n          \"PUBLISH-ERROR-PROCESS-ALREADY-USED-APP\": \"App\",\n          \"PUBLISH-ERROR-PROCDEF-DUPLICATE-KEYS\": \"App invalide: Duplication trouvé des identifians de processus (modifier la propriété \\\"id\\\" des modèles de processus mise en cause):\",\n          \"DELETE-TITLE\": \"Supprimer la définition d'App\",\n          \"DELETE-DESCRIPTION\": \"Êtes-vous sûr de vouloir  supprimer la définition d'App \\\"{{name}}\\\"?\",\n          \"DELETE-DESCRIPTION-WITH-RUNTIME\": \"Êtes-vous sûr de vouloir supprimer la définition d'App \\\"{{name}}\\\"? A noter que la définition d'App a été déployé sur la page d'accueil des tâches et en confirmant l'App sera supprimé des pages d'accueil.\",\n          \"DELETE-CASCADE-FALSE\": \"Supprimer uniquement la version courante de la définition d'App (v{{version}})\",\n          \"DELETE-CASCADE-TRUE\": \"Supprimer aussi toutes les versions précédentes de la définition d'App\",\n          \"HAS-CUSTOM-STENCILITEM\" : \"Modèle \\\"{{modelName}}\\\" utilise un stencil avec des objets personnalisés de stencil. Il n'est pas possible d'utiliser ce modèle dans une définition d'App.\",\n          \"HAS-VALIDATIONERROR\" : \"Modèle \\\"{{modelName}}\\\" a des erreurs de validations et ne peut être ajouté à une définition d'App. Ouvrez le modèle dans l'éditeur and vérifier les détails des erreurs.\",\n          \"IMPORT-DESCRIPTION\":\"Veuillez naviguer ou déposer une définition d'App avec une extension en .zip\",\n          \"IMPORT-TITLE\":\"Importer un modèle de définition d'App \",\n          \"IMPORT\": {\n              \"DROPZONE\": \"Déposer un fichier de définition d'App en .zip\",\n              \"CANCEL-UPLOAD\": \"Annuler l'envoi\",\n              \"RENEWIDM-IDS\": \"Renouveler les identifiants d'utilisateur et de groupe lors de l'importation de modèles d'étapes et BPMN. Ceci est souvent requis lors de l'importation de la définition d'application dans un environnement Flowable différent. Il essaiera de lier les étapes humaines et les tâches utilisateur au bon utilisateur et groupe dans cet environnement cible.\",\n              \"ERROR\": \"Une erreur s'est produite lors du traitement du fichier\",\n              \"NO-DROP\": \"Glisser/Déposer n'est pas supporté.\"\n          },\n          \"INCLUDE-MODELS-TITLE\": \"Modèles inclus dans la définition d'App\"\n        },\n        \"ALERT\": {\n          \"DELETE-CONFIRM\": \"La définition d'App a été supprimé\",\n          \"PUBLISH-CONFIRM\": \"La définition d'App a été publié\",\n          \"PUBLISH-ERROR\": \"Impossible de publier la définition d'App. Veuillez vérifier la validité des références de modèles de processus\"\n        }\n    },\n\n    \"SHARE-INFO\": {\n        \"ACTION\": {\n          \"ADD\": \"Ajouter une autre personne\"\n        }\n    },\n\n    \"FORM-BUILDER\": {\n        \"PALLETTE\": {\n            \"TEXT\": \"Texte\",\n            \"MULTILINE-TEXT\": \"Texte Multiligne\",\n            \"PASSWORD\": \"Mot de passe\",\n            \"NUMBER\": \"Nombre\",\n            \"CHECKBOX\": \"Case à cocher\",\n            \"DATE\": \"Date\",\n            \"DROPDOWN\": \"Liste déroulante\",\n            \"RADIO\": \"Boutton radio\",\n            \"PEOPLE\": \"Personnes\",\n            \"GROUP-OF-PEOPLE\": \"Groupes de personnes\",\n            \"UPLOAD\": \"Téléchargement\",\n            \"EXPRESSION\": \"Expression\",\n            \"DECIMAL\": \"Décimal\",\n\t    \t\"HYPERLINK\": \"Lien Hypertexte\",\n\t    \t\"SPACER\": \"Spacer\",\n\t\t\t\"HORIZONTAL-LINE\": \"Horizontal line\",\n\t\t\t\"HEADLINE\": \"Headline\",\n\t\t\t\"HEADLINE-WITH-LINE\":\"Headline\"\n        },\n        \"TABS\": {\n            \"GENERAL\": \"Général\",\n            \"OPTIONS\": \"Options\",\n            \"UPLOAD-OPTIONS\": \"Options de téléchargement\",\n            \"ADVANCED-OPTIONS\":\"Avancé\"\n        },\n        \"VERSION\": \"Version {{version}}\",\n        \"LAST-UPDATED\": \"Dernière modification par {{lastUpdatedBy}}, {{lastUpdated | dateformat}}\",\n        \"TITLE\": {\n            \"DESIGN\": \"Conception\",\n            \"OUTCOME\": \"Résultats\"\n        },\n        \"POPUP\": {\n            \"EDIT-TITLE\": \"Editer le champ '{{name}}'\",\n            \"EXPRESSION-TITLE\": \"Editer l'expression\"\n        },\n        \"MESSAGE\": {\n            \"EMPTY-EXPRESSION\": \"(Aucune valeur de l'expression)\",\n            \"EXPRESSION-HELP\": \"Vous pouvez également afficher les valeurs préalablement soumises dans tout formulaire, dans le cadre du texte, en utilisant une notation de référence comme ${myFieldId}.\",\n            \"OPTIONS-EXPRESSION-HELP\": \"Vous pouvez utiliser une expression pour remplir dynamiquement des options, par exemple en référençant une variable telle que ${optionsVariable}. L'expression doit aboutir à un objet java (java.util.List avec des objets Option) ou à sa représentation json.\"\n        },\n        \"LABEL\" : {\n            \"FUNCTIONAL-GROUP\": \"Sélectionner un groupe..\",\n            \"PERSON\": \"Sélectionner une personne..\"\n        },\n        \"COMPONENT\": {\n            \"LABEL\": \"Libellé:\",\n            \"OVERRIDEID\": \"Surcharger l'identifiant?\",\n            \"ID\": \"Identifiant:\",\n            \"PLACEHOLDER\": \"Paramètre fictif:\",\n            \"OPTIONS\": \"Options\",\n            \"RADIO-BUTTON-DEFAULT\": \"Option 1\",\n            \"DROPDOWN-DEFAULT-EMPTY-SELECTION\": \"Veuillez en choisir un...\",\n            \"DROPDOWN-EMPTY-VALUE-HELP\": \"Ceci est l'option pour la 'valeur à vide'. Le sélectionner lors de l'utilisation signifie 'aucune valeur' ou 'vide'.  Ceci est autorisé pour les champs optionnels mais pas pour les champs obligatoires.\",\n            \"OPTIONS-EXPRESSION\": \"Expression des options:\",\n            \"OPTIONS-EXPRESSION-ENABLED\": \"Activer l'expression des options\",\n            \"REQUIRED\": \"Requis\",\n\t          \"READONLY\": \"Lecture seul\",\n            \"EXPRESSION\": \"Expression\",\n            \"ADD-OPTION\": \"+ Ajouter une nouvelle option\",\n            \"UPLOAD-ALLOW-MULTIPLE\": \"Autoriser le téléchargement de plusieurs fichiers\",\n            \"SIZE\": \"Taille\",\n\t          \"MAX-LENGTH\":\"Longueur maximale:\",\n            \"MIN-LENGTH\":\"Longueur minimum:\",\n            \"PASSWORD-UNMASK-OPTION\": \"Option de masquage / démasquage de mot de passe\",\n\t          \"HYPERLINK-URL\": \"URL line hypertexte\",\n\t          \"REGEX-PATTERN\":\"Regex standard\",\n            \"MASK\":{\n              \"TITLE\":\"Masque de saisie\",\n              \"EXAMPLES\":{\n                \"TITLE\":\"Exemples:\",\n                \"NUMBER\":\"tous les nombres\",\n                \"LETTER\":\"toutes les lettres\",\n                \"NUMBERORLETTER\":\"N'importe quel nombre ou lettre\",\n                \"OPTIONAL\":\"Rendre le masque optionel (non valide)\",\n                \"PHONE\":\"Téléphone\"\n               }\n           }\n        },\n        \"OUTCOMES\": {\n            \"DESCRIPTION\": \"Vous pouvez définir plusieurs résultats pour cette tâche. Une fois la tâche complété, les utilisateurs choisissent la variable de résultat qui pourra ensuite être utilisé en tant que tel dans le processus.\",\n            \"NO-OUTCOMES-OPTION\": \"Ne pas utiliser les résultats personnalisés, afficher uniquement le boutton 'Terminer'\",\n            \"OUTCOMES-OPTION\": \"Utiliser des résultats personnalisés pour ce formulaire.\",\n            \"POSSIBLE-OUTCOMES\": \"Résultats possibles\",\n            \"NEW-OUTCOME-PLACEHOLDER\": \"Entrer un nouveau résultat\",\n            \"ADD\": \"Ajouter un résultat\",\n            \"REMOVE\": \"Retirer\"\n        }\n    },\n\n    \"DECISION-TABLE-EDITOR\": {\n        \"EMPTY-MESSAGES\": {\n            \"NO-VARIABLE-SELECTED\": \"Indéfini\"\n        },\n        \"POPUP\": {\n            \"EXPRESSION-EDITOR\": {\n                \"INPUT-TITLE\": \"Modifier la colonne d'entrée\",\n                \"INPUT-DESCRIPTION\": \"Sélectionnez la variable d'entrée comme entrée pour la colonne\",\n                \"OUTPUT-TITLE\": \"Modifier la colonne de sortiee\",\n                \"OUTPUT-DESCRIPTION\": \"Sélectionnez une variable de sortie existante ou créez une nouvelle\",\n                \"EXPRESSION-LABEL\": \"Libellé de colonne:\",\n                \"EXPRESSION-PLACEHOLDER\": \"Entrer un libellé optionnel\",\n                \"EXPRESSION-VARIABLE-NAME\": \"Nom de variable:\",\n                \"EXPRESSION-VARIABLE-TYPE\": \"Type de variable:\",\n                \"EXPRESSION-VARIABLE-NAME-PLACEHOLDER\": \"Entrer un nom de variable\",\n                \"OUTPUT-NEW-VARIABLE-ID\": \"Variable ID:\",\n                \"OUTPUT-NEW-VARIABLE-TYPE\": \"Type de variable:\",\n                \"COMPLEX-EXPRESSION-LABEL\": \"Expression complexe :\",\n                \"ALLOWED-VALUES\": \"Valeurs autorisées (optionel):\",\n                \"OUTPUT-VALUES\": \"Valeurs de résultats \",\n                \"OUTPUT-VALUES-OPTIONAL\": \"(optionel):\",\n                \"OUTPUT-VALUES-NOT-OPTIONAL\": \"(drag rows for priority / output order):\"\n            }\n        },\n        \"BUTTON-ACTIONS-LABEL\": \"Actions\",\n        \"BUTTON-ADD-INPUT-LABEL\": \"Ajouter une entrée\",\n        \"BUTTON-ADD-OUTPUT-LABEL\": \"Ajouter une sortie\",\n        \"BUTTON-ADD-RULE-LABEL\": \"Ajouter une règle\",\n        \"BUTTON-MOVE-RULE-UPWARDS-LABEL\": \"Déplacer vers le haut\",\n        \"BUTTON-MOVE-RULE-DOWNWARDS-LABEL\": \"Déplacer vers le bas\",\n        \"BUTTON-REMOVE-RULE-LABEL\": \"Retirer une règle\",\n        \"ALERT\": {\n            \"EXPRESSION-VARIABLE-REQUIRED-ERROR\": \"Toutes les expressions d'entrée et de sorties doivent référencer un champs de formulaire ou une variable.\",\n            \"SAVE-CONFIRM\": \"La table de décision '{{name}}' a été sauvegardée\"\n        }\n    },\n\n    \"TOUR\": {\n        \"WELCOME-TITLE\": \"Bienvenue, {{userName}}\",\n        \"WELCOME-CONTENT\": \"Ceci est une introduction à l'éditeur Flowable. Les prochaines étapes vous guideront dans les différentes sections de l'application pour vous aider à démarrer. Appuyez sur la touche ESC pour arrêter à tout moment.\" ,\n        \"PALETTE-TITLE\": \"La Palette\",\n        \"PALETTE-CONTENT\": \"Tous les éléments disponibles pour créer un processus métier peuvent être trouvées ici. Ils sont organisés dans des groupes logiques. Pour ouvrir un groupe, cliquez simplement dessus:\",\n        \"CANVAS-TITLE\": \"Le Canevas\",\n        \"CANVAS-CONTENT\": \"C'est l'espace de travail sur lequel vous créez votre processus métier. Faites glisser des éléments de la palette sur la gauche et déposez-les sur le canevas pour commencer la modélisation..\",\n        \"DRAGDROP-TITLE\": \"Exemple de glisser-déposer\",\n        \"DRAGDROP-CONTENT\": \"Voici un exemple de comment commencer avec la modélisation:\",\n        \"PROPERTIES-TITLE\": \"Propriétés\",\n        \"PROPERTIES-CONTENT\": \"Ici, vous pouvez configurer les propriétés des éléments constitutif de votre processus métier. Il suffit de sélectionner l'élément sur le canevas et ses propriétés seront affichées. Cliquez sur la propriété si vous souhaitez l'éditer\",\n        \"TOOLBAR-TITLE\": \"La Barre d'outils\",\n        \"TOOLBAR-CONTENT\": \"Toutes les actions peuvent être trouvées ici: sauvegarder ou valider un modèle, copier et coller des éléments d'un processus, etc. Survolez les boutons pour obtenir une description pour une action.\",\n        \"END-TITLE\": \"La Fin\",\n        \"END-CONTENT\": \"C'est tout! Vous pouvez maintenant commencer à modéliser vos processus. Si vous avez des questions, n'hésitez pas à les poser sur le <a href=\\\"http://forum.flowable.org/\\\" target=\\\"_blank\\\">Forum Flowable</a> \"\n    },\n\n    \"FEATURE-TOUR\" : {\n        \"BENDPOINT\" : {\n            \"TITLE\": \"Tutorial sur les points de courbure\",\n            \"DESCRIPTION\" : \"Lorsque vous connectez les étapes d'un processus l'une à l'autre en utilisant le flux de séquence (les flèches entre les étapes d'un processus), vous pourriez constater que ces flux de séquence se croisent ou que vous souhaitez les répartir différemment. Pour ce faire, vous pouvez ajouter ou supprimer un point de courbure vers ou à partir d'un flux de séquence. <br/> <br/> Comme indiqué ci-dessous dans l'image, cliquez d'abord sur 'Ajouter un point de courbure', puis cliquez sur un flux de séquence pour ajoutez-le. Notez que le flux de séquence vous montrera une indication subtile en vert pour montrer que le point de flexion peut être ajouté là. <br/> <br/> La suppression d'un point de courbure suit à nouveau un motif similaire: cliquez sur le bouton 'supprimer le point de courbure' et cliquez sur le bouton courber le point pour le retirer à nouveau.\"\n        }\n    },\n\n    \"ACTION.OK\" : \"Ok\",\n    \"ACTION.SAVE\" : \"Sauvegarder\",\n    \"ACTION.SAVE-AND-CLOSE\" : \"Sauvegarder et fermer l'éditeur\",\n    \"ACTION.SEND\" : \"Envoyer\",\n    \"ACTION.CANCEL\" : \"Annuler\",\n    \"ACTION.SELECT\" : \"Sélectionner\",\n    \"ACTION.ADD\" : \"Ajouter\",\n    \"ACTION.REMOVE\" : \"Retirer\",\n    \"ACTION.MOVE.UP\" : \"Déplacer l'entrée vers le haut\",\n    \"ACTION.MOVE.DOWN\" : \"Déplacer l'entrée vers le base\",\n\n    \"TOOLBAR.ACTION.CLOSE\" : \"Fermer l'éditeur et revenir vers la page de vue d'ensemble\",\n    \"TOOLBAR.ACTION.SAVE\" : \"Sauvegarder le modèle\",\n    \"TOOLBAR.ACTION.VALIDATE\" : \"Valider le modèle\",\n    \"TOOLBAR.ACTION.CUT\" : \"Couper (sélectionner un ou plusieurs éléments dans votre processus métier)\",\n    \"TOOLBAR.ACTION.COPY\" : \"Copier (sélectionner un ou plusieurs éléments dans votre processus métier)\",\n    \"TOOLBAR.ACTION.PASTE\" : \"Coller\",\n    \"TOOLBAR.ACTION.DELETE\" : \"Supprimer l'élément sélectionné\",\n    \"TOOLBAR.ACTION.UNDO\" : \"Annuler\",\n    \"TOOLBAR.ACTION.REDO\" : \"Refaire\",\n    \"TOOLBAR.ACTION.ZOOMIN\" : \"Zoom avant\",\n    \"TOOLBAR.ACTION.ZOOMOUT\" : \"Zoom arrière\",\n    \"TOOLBAR.ACTION.ZOOMACTUAL\" : \"Zoom en taille réelle\",\n    \"TOOLBAR.ACTION.ZOOMFIT\" : \"Zoom pour s'adapter\",\n    \"TOOLBAR.ACTION.BENDPOINT.ADD\" : \"Ajouter un point de courbure sur le flux de séquence sélectionné\",\n    \"TOOLBAR.ACTION.BENDPOINT.REMOVE\" : \"Retirer un point de courbure sur le flux de séquence sélectionné\",\n    \"TOOLBAR.ACTION.ALIGNHORIZONTAL\" : \"Aligner le modèle horizontalement\",\n    \"TOOLBAR.ACTION.ALIGNVERTICAL\" : \"Aligner modèle verticalement\",\n    \"TOOLBAR.ACTION.SAMESIZE\" : \"Même taille\",\n    \"TOOLBAR.ACTION.HELP\": \"Démarrer la visite guidée\",\n    \"TOOLBAR.ACTION.FEEDBACK\": \"Faire un retour d'information\",\n\n    \"FORM_TOOLBAR.ACTION.SAVE\" : \"Sauvegarder le modèle\",\n\n    \"APP_DEFINITION_TOOLBAR.ACTION.SAVE\" : \"Sauvegarder la définition d'App\",\n\n    \"BUTTON.ACTION.DELETE.TOOLTIP\": \"Supprimer un élément from the modèle\",\n    \"BUTTON.ACTION.MORPH.TOOLTIP\": \"Changer un type d'élément\",\n\n    \"ELEMENT.AUTHOR\" : \"Auteur\",\n    \"ELEMENT.DATE_CREATED\" : \"Date de creation\",\n\n    \"PROPERTY.REMOVED\" : \"supprimé\",\n    \"PROPERTY.EMPTY\" : \"Aucune valeur\",\n    \"PROPERTY.PROPERTY.EDIT.TITLE\" : \"Changer la valeur pour \",\n\n    \"PROPERTY.FEEDBACK.TITLE\" : \"Veuillez ajouter vos commentaires\",\n\n    \"PROPERTY.ASSIGNMENT.TITLE\" : \"Tâche\",\n    \"PROPERTY.ASSIGNMENT.TYPE\" : \"Type\",\n    \"PROPERTY.ASSIGNMENT.TYPE.IDENTITYSTORE\" : \"Identity store\",\n    \"PROPERTY.ASSIGNMENT.TYPE.STATIC\" : \"Valeurs fixées\",\n    \"PROPERTY.ASSIGNMENT.ASSIGNEE\" : \"Personne assignée\",\n    \"PROPERTY.ASSIGNMENT.MATCHING\" : \"Utiliser &uparrow; et &downarrow; pour sélectionner et appuyer sur Entrée pour confirmer ou utiliser la souris\",\n    \"PROPERTY.ASSIGNMENT.ASSIGNEE_PLACEHOLDER\" : \"Choisir une personne assignée\",\n    \"PROPERTY.ASSIGNMENT.EMPTY\" : \"Aucune personne assignée sélectionné\",\n    \"PROPERTY.ASSIGNMENT.NONE\" : \"Aucune ...\",\n    \"PROPERTY.ASSIGNMENT.PLACEHOLDER-SEARCHUSER\": \"Recherche un utilisateur\",\n    \"PROPERTY.ASSIGNMENT.PLACEHOLDER-SEARCHGROUP\": \"Recherche un groupe\",\n    \"PROPERTY.ASSIGNMENT.SEARCH\": \"Recherche: \",\n    \"PROPERTY.ASSIGNMENT.ASSIGNEE_DISPLAY\" : \"Personne assignée {{assignee}}\",\n    \"PROPERTY.ASSIGNMENT.CANDIDATE_USERS_DISPLAY\" : \"{{length}} utilisateurs candidats\",\n    \"PROPERTY.ASSIGNMENT.CANDIDATE_USERS\" : \"Utilisateurs candidats\",\n    \"PROPERTY.ASSIGNMENT.CANDIDATE_GROUPS_DISPLAY\" :  \"{{length}} groupes candidats\",\n    \"PROPERTY.ASSIGNMENT.CANDIDATE_GROUPS\" :  \"Groupes candidats\",\n    \"PROPERTY.ASSIGNMENT.USER_IDM_DISPLAY\": \"Utilisateur {{firstName}} {{lastName}}\",\n    \"PROPERTY.ASSIGNMENT.USER_IDM_EMAIL_DISPLAY\": \"Utilisateur {{email}}\",\n    \"PROPERTY.ASSIGNMENT.USER_IDM_FIELD_DISPLAY\": \"Champs {{name}}\",\n    \"PROPERTY.ASSIGNMENT.IDM_EMPTY\" : \"Initiateur de processus\",\n    \"PROPERTY.ASSIGNMENT.IDM.TYPE\" : \"Tâche\",\n    \"PROPERTY.ASSIGNMENT.IDM.NO_CANDIDATE_USERS\" : \"Aucun utilisateur candidat sélectionné...\",\n    \"PROPERTY.ASSIGNMENT.IDM.NO_CANDIDATE_GROUPS\" : \"Aucun groupe candidat sélectionné...\",\n    \"PROPERTY.ASSIGNMENT.IDM.DROPDOWN.INITIATOR\" : \"Assigné à l'initiateur de processus\",\n    \"PROPERTY.ASSIGNMENT.IDM.DROPDOWN.USER\" : \"Assigné à un seul utilisateur\",\n    \"PROPERTY.ASSIGNMENT.IDM.DROPDOWN.USERS\" : \"Utilisateurs candidats\",\n    \"PROPERTY.ASSIGNMENT.IDM.DROPDOWN.GROUPS\" : \"Groupes candidats\",\n    \"PROPERTY.ASSIGNMENT.INITIATOR-CAN-COMPLETE\" : \"Autoriser l'initiateur de processus à terminer la tâche\",\n    \"PROPERTY.EXECUTIONLISTENERS.DISPLAY\" : \"{{length}} execution listeners\",\n    \"PROPERTY.EXECUTIONLISTENERS.EMPTY\" : \"No execution listeners configured\",\n    \"PROPERTY.EXECUTIONLISTENERS.EVENT\" : \"Événement\",\n    \"PROPERTY.EXECUTIONLISTENERS.CLASS\" : \"Class\",\n    \"PROPERTY.EXECUTIONLISTENERS.CLASS.PLACEHOLDER\" : \"Entrer un classname\",\n    \"PROPERTY.EXECUTIONLISTENERS.EXPRESSION\" : \"Expression\",\n    \"PROPERTY.EXECUTIONLISTENERS.EXPRESSION.PLACEHOLDER\" : \"Entrer une expression\",\n    \"PROPERTY.EXECUTIONLISTENERS.DELEGATEEXPRESSION\" : \"Delegate expression\",\n    \"PROPERTY.EXECUTIONLISTENERS.DELEGATEEXPRESSION.PLACEHOLDER\" : \"Entrer une delegate expression\",\n    \"PROPERTY.EXECUTIONLISTENERS.UNSELECTED\" : \"Aucun execution listener sélectionné\",\n    \"PROPERTY.EXECUTIONLISTENERS.FIELDS.NAME\" : \"Nom\",\n    \"PROPERTY.EXECUTIONLISTENERS.FIELDS.NAME.PLACEHOLDER\" : \"Entrer un nom\",\n    \"PROPERTY.EXECUTIONLISTENERS.FIELDS.EXPRESSION\" : \"Expression\",\n    \"PROPERTY.EXECUTIONLISTENERS.FIELDS.EXPRESSION.PLACEHOLDER\" : \"Entrer une expression\",\n    \"PROPERTY.EXECUTIONLISTENERS.FIELDS.STRINGVALUE\" : \"valeur de chaîne\",\n    \"PROPERTY.EXECUTIONLISTENERS.FIELDS.STRINGVALUE.PLACEHOLDER\" : \"Entrer une valeur de chaîne\",\n    \"PROPERTY.EXECUTIONLISTENERS.FIELDS.STRING\" : \"String\",\n    \"PROPERTY.EXECUTIONLISTENERS.FIELDS.STRING.PLACEHOLDER\" : \"Entrer une valeur de chaîne\",\n    \"PROPERTY.EXECUTIONLISTENERS.FIELDS.IMPLEMENTATION\" : \"Implementation\",\n    \"PROPERTY.EXECUTIONLISTENERS.FIELDS.EMPTY\" : \"Aucun champ sélectionné\",\n\n    \"PROPERTY.FIELDS\" : \"{{length}} champs\",\n    \"PROPERTY.FIELDS.EMPTY\" : \"Aucun champ sélectionné\",\n    \"PROPERTY.FIELDS.NAME\" : \"Nom\",\n    \"PROPERTY.FIELDS.NAME.PLACEHOLDER\" : \"Entrer un nom\",\n    \"PROPERTY.FIELDS.EXPRESSION\" : \"Expression\",\n    \"PROPERTY.FIELDS.EXPRESSION.PLACEHOLDER\" : \"Entrer une expression\",\n    \"PROPERTY.FIELDS.STRINGVALUE\" : \"valeur de chaîne\",\n    \"PROPERTY.FIELDS.STRINGVALUE.PLACEHOLDER\" : \"Entrer a string value\",\n    \"PROPERTY.FIELDS.STRING\" : \"String\",\n    \"PROPERTY.FIELDS.STRING.PLACEHOLDER\" : \"Entrer a string\",\n    \"PROPERTY.FIELDS.IMPLEMENTATION\" : \"Implémentation\",\n\n    \"PROPERTY.DATAPROPERTIES.VALUES\" : \"{{length}} data objects\",\n    \"PROPERTY.DATAPROPERTIES.EMPTY\" : \"Aucun objet de données configuré\",\n    \"PROPERTY.DATAPROPERTIES.ID\" : \"Id\",\n    \"PROPERTY.DATAPROPERTIES.ID.PLACEHOLDER\" : \"Entrer une id\",\n    \"PROPERTY.DATAPROPERTIES.NAME\" : \"Nom\",\n    \"PROPERTY.DATAPROPERTIES.NAME.PLACEHOLDER\" : \"Entrer a nom\",\n    \"PROPERTY.DATAPROPERTIES.TYPE\" : \"Type\",\n    \"PROPERTY.DATAPROPERTIES.VALUE.PLACEHOLDER\" : \"Entrer une value (optionnel)\",\n    \"PROPERTY.DATAPROPERTIES.VALUE\" : \"Valeur par défaut\",\n\n    \"PROPERTY.FORMPROPERTIES.VALUE\" : \"{{length}} propriétés de formulaire\",\n    \"PROPERTY.FORMPROPERTIES.EMPTY\" : \"Aucune propriété du formulaire sélectionné\",\n    \"PROPERTY.FORMPROPERTIES.ID\" : \"Identifiant\",\n    \"PROPERTY.FORMPROPERTIES.ID.PLACEHOLDER\" : \"Entrer un identifiant\",\n    \"PROPERTY.FORMPROPERTIES.NAME\" : \"Nom\",\n    \"PROPERTY.FORMPROPERTIES.NAME.PLACEHOLDER\" : \"Entrer un nom\",\n    \"PROPERTY.FORMPROPERTIES.TYPE\" : \"Type\",\n    \"PROPERTY.FORMPROPERTIES.DATEPATTERN\" : \"Pattern de Date\",\n    \"PROPERTY.FORMPROPERTIES.DATEPATTERN.PLACEHOLDER\" : \"Entrer un Pattern de date\",\n    \"PROPERTY.FORMPROPERTIES.VALUES\" : \"Valeurs\",\n    \"PROPERTY.FORMPROPERTIES.ENUMVALUES.EMPTY\" : \"Aucune valeur d'énumération sélectionné\",\n    \"PROPERTY.FORMPROPERTIES.VALUES.ID\" : \"Identifiant\",\n    \"PROPERTY.FORMPROPERTIES.VALUES.NAME\" : \"Nom\",\n    \"PROPERTY.FORMPROPERTIES.VALUES.ID.PLACEHOLDER\" : \"Entrer un identifiant pour la valeur\",\n  \t\"PROPERTY.FORMPROPERTIES.VALUES.NAME.PLACEHOLDER\" : \"Entrer un nom pour la valeur\",\n    \"PROPERTY.FORMPROPERTIES.EXPRESSION\" : \"Expression\",\n    \"PROPERTY.FORMPROPERTIES.EXPRESSION.PLACEHOLDER\" : \"Entrer une expression\",\n    \"PROPERTY.FORMPROPERTIES.VARIABLE\" : \"Variable\",\n    \"PROPERTY.FORMPROPERTIES.VARIABLE.PLACEHOLDER\" : \"Entrer une variable\",\n    \"PROPERTY.FORMPROPERTIES.DEFAULT\" : \"default\",\n    \"PROPERTY.FORMPROPERTIES.DEFAULT.PLACEHOLDER\" : \"Entrer une default\",\n    \"PROPERTY.FORMPROPERTIES.REQUIRED\" : \"Requise\",\n    \"PROPERTY.FORMPROPERTIES.READABLE\" : \"Lecture\",\n    \"PROPERTY.FORMPROPERTIES.WRITABLE\" : \"Ecriture\",\n\n    \"PROPERTY.INPARAMETERS.VALUE\" : \"{{length}} paramètres d'entrée\",\n    \"PROPERTY.INPARAMETERS.EMPTY\" : \"Aucun  paramètres d'entrée configuré\",\n\n    \"PROPERTY.OUTPARAMETERS.VALUE\" : \"{{length}} paramètres de sortie\",\n    \"PROPERTY.OUTPARAMETERS.EMPTY\" : \"No paramètres de sortie configuré\",\n\n    \"PROPERTY.PARAMETER.SOURCE\" : \"Source\",\n    \"PROPERTY.PARAMETER.SOURCE.PLACEHOLDER\" : \"Entrer une source\",\n    \"PROPERTY.PARAMETER.SOURCEEXPRESSION\" : \"Expression de source\",\n    \"PROPERTY.PARAMETER.SOURCEEXPRESSION.PLACEHOLDER\" : \"Entrer une expression de source\",\n    \"PROPERTY.PARAMETER.TARGET\" : \"Cible (Target)\",\n    \"PROPERTY.PARAMETER.TARGET.PLACEHOLDER\" : \"Entrer une Cible\",\n    \"PROPERTY.PARAMETER.EMPTY\" : \"Aucun paramètre sélectionné\",\n\n    \"PROPERTY.PROCESSREFERENCE.EMPTY\" : \"Aucune référence sélectionnée\",\n    \"PROPERTY.PROCESSREFERENCE.TITLE\" : \"Référence de processus\",\n    \"PROPERTY.PROCESSREFERENCE.ERROR.SUBPROCESS\" : \"Une erreur a été rencontré lors du chargement des processus. Veuillez réessayer ultérieurement\",\n    \"PROPERTY.PROCESSREFERENCE.PROCESS.LOADING\" : \"Chargement des processus...\",\n    \"PROPERTY.PROCESSREFERENCE.PROCESS.EMPTY\" : \"Ce répertoire ne contient pas de processus\",\n\n    \"PROPERTY.FORMREFERENCE.EMPTY\" : \"Aucune reference sélectionnée\",\n    \"PROPERTY.FORMREFERENCE.TITLE\" : \"Référence de formulaire\",\n    \"PROPERTY.FORMREFERENCE.DESCRIPTION\" : \"Référence vers un formulaire\",\n    \"PROPERTY.FORMREFERENCE.ERROR.FORM\" : \"Une erreur a été rencontré lors du chargement des formulaires.  Veuillez réessayer ultérieurement\",\n    \"PROPERTY.FORMREFERENCE.FORM.LOADING\" : \"Chargement des formulaires...\",\n    \"PROPERTY.FORMREFERENCE.FORM.EMPTY\" : \"Ce répertoire ne contient pas de formulaires\",\n\n    \"PROPERTY.TASKLISTENERS.VALUE\" : \"{{length}} task listeners\",\n    \"PROPERTY.TASKLISTENERS.EMPTY\" : \"Aucun task listeners configuré\",\n    \"PROPERTY.TASKLISTENERS.EVENT\" : \"Événements\",\n    \"PROPERTY.TASKLISTENERS.CLASS\" : \"Class\",\n    \"PROPERTY.TASKLISTENERS.CLASS.PLACEHOLDER\" : \"Entrer un classname\",\n    \"PROPERTY.TASKLISTENERS.EXPRESSION\" : \"Expression\",\n    \"PROPERTY.TASKLISTENERS.EXPRESSION.PLACEHOLDER\" : \"Entrer une expression\",\n    \"PROPERTY.TASKLISTENERS.DELEGATEEXPRESSION\" : \"Delegate expression\",\n    \"PROPERTY.TASKLISTENERS.DELEGATEEXPRESSION.PLACEHOLDER\" : \"Entrer une delegate expression\",\n    \"PROPERTY.TASKLISTENERS.UNSELECTED\" : \"Aucun task listener sélectionné\",\n    \"PROPERTY.TASKLISTENERS.FIELDS.NAME\" : \"Nom\",\n    \"PROPERTY.TASKLISTENERS.FIELDS.NAME.PLACEHOLDER\" : \"Entrer un nom\",\n    \"PROPERTY.TASKLISTENERS.FIELDS.EXPRESSION\" : \"Expression\",\n    \"PROPERTY.TASKLISTENERS.FIELDS.EXPRESSION.PLACEHOLDER\" : \"Entrer une expression\",\n    \"PROPERTY.TASKLISTENERS.FIELDS.STRINGVALUE\" : \"valeur de chaîne\",\n    \"PROPERTY.TASKLISTENERS.FIELDS.STRINGVALUE.PLACEHOLDER\" : \"Entrer une valeur de chaîne\",\n    \"PROPERTY.TASKLISTENERS.FIELDS.STRING\" : \"String\",\n    \"PROPERTY.TASKLISTENERS.FIELDS.STRING.PLACEHOLDER\" : \"Entrer a string\",\n    \"PROPERTY.TASKLISTENERS.FIELDS.IMPLEMENTATION\" : \"Implémentation\",\n    \"PROPERTY.TASKLISTENERS.FIELDS.EMPTY\" : \"Aucun champ sélectionné\",\n\n    \"PROPERTY.EVENTLISTENERS.DISPLAY\" : \"{{length}} événement listeners\",\n    \"PROPERTY.EVENTLISTENERS.EMPTY\" : \"Aucun événement listeners configured\",\n    \"PROPERTY.EVENTLISTENERS.EVENTS\": \"Événements\",\n    \"PROPERTY.EVENTLISTENERS.RETHROW\": \"Renvoyer l'événement?\",\n    \"PROPERTY.EVENTLISTENERS.CLASS\" : \"Class\",\n    \"PROPERTY.EVENTLISTENERS.CLASS.PLACEHOLDER\" : \"Entrer un classname\",\n    \"PROPERTY.EVENTLISTENERS.DELEGATEEXPRESSION\" : \"Delegate expression\",\n    \"PROPERTY.EVENTLISTENERS.DELEGATEEXPRESSION.PLACEHOLDER\" : \"Entrer une delegate expression\",\n    \"PROPERTY.EVENTLISTENERS.ENTITYTYPE\" : \"Type de l'entité\",\n    \"PROPERTY.EVENTLISTENERS.ENTITYTYPE.PLACEHOLDER\" : \"Entrer le type de l'entité \",\n    \"PROPERTY.EVENTLISTENERS.RETHROWTYPE\": \"Renvoyer le type d'événement\",\n    \"PROPERTY.EVENTLISTENERS.ERRORCODE\" : \"Code d'erreur\",\n    \"PROPERTY.EVENTLISTENERS.ERRORCODE.PLACEHOLDER\" : \"Entrer un code d'erreur \",\n    \"PROPERTY.EVENTLISTENERS.MESSAGENAME\" : \"Nom du Message\",\n    \"PROPERTY.EVENTLISTENERS.MESSAGENAME.PLACEHOLDER\" : \"Entrer le nom du message\",\n    \"PROPERTY.EVENTLISTENERS.SIGNALNAME\" : \"Nom du Signal\",\n    \"PROPERTY.EVENTLISTENERS.SIGNALNAME.PLACEHOLDER\" : \"Entrer le nom du signal\",\n    \"PROPERTY.EVENTLISTENERS.UNSELECTED\" : \"Aucun événement listener sélectionné\",\n\n    \"PROPERTY.PLANITEMLIFECYCLELISTENERS.VALUE\" : \"{{length}} lifecycle listeners\",\n    \"PROPERTY.PLANITEMLIFECYCLELISTENERS.EMPTY\" : \"No lifecycle listeners configured\",\n    \"PROPERTY.PLANITEMLIFECYCLELISTENERS.EVENT\" : \"Event\",\n    \"PROPERTY.PLANITEMLIFECYCLELISTENERS.SOURCE_STATE\" : \"Source state\",\n    \"PROPERTY.PLANITEMLIFECYCLELISTENERS.TARGET_STATE\" : \"Target state\",\n    \"PROPERTY.PLANITEMLIFECYCLELISTENERS.CLASS\" : \"Class\",\n    \"PROPERTY.PLANITEMLIFECYCLELISTENERS.CLASS.PLACEHOLDER\" : \"Enter a classname\",\n    \"PROPERTY.PLANITEMLIFECYCLELISTENERS.EXPRESSION\" : \"Expression\",\n    \"PROPERTY.PLANITEMLIFECYCLELISTENERS.EXPRESSION.PLACEHOLDER\" : \"Enter an expression\",\n    \"PROPERTY.PLANITEMLIFECYCLELISTENERS.DELEGATEEXPRESSION\" : \"Delegate expression\",\n    \"PROPERTY.PLANITEMLIFECYCLELISTENERS.DELEGATEEXPRESSION.PLACEHOLDER\" : \"Enter a delegate expression\",\n    \"PROPERTY.PLANITEMLIFECYCLELISTENERS.UNSELECTED\" : \"No task listener selected\",\n    \"PROPERTY.PLANITEMLIFECYCLELISTENERS.FIELDS.NAME\" : \"Name\",\n    \"PROPERTY.PLANITEMLIFECYCLELISTENERS.FIELDS.NAME.PLACEHOLDER\" : \"Enter a name\",\n    \"PROPERTY.PLANITEMLIFECYCLELISTENERS.FIELDS.EXPRESSION\" : \"Expression\",\n    \"PROPERTY.PLANITEMLIFECYCLELISTENERS.FIELDS.EXPRESSION.PLACEHOLDER\" : \"Enter an expression\",\n    \"PROPERTY.PLANITEMLIFECYCLELISTENERS.FIELDS.STRINGVALUE\" : \"String value\",\n    \"PROPERTY.PLANITEMLIFECYCLELISTENERS.FIELDS.STRINGVALUE.PLACEHOLDER\" : \"Enter a string value\",\n    \"PROPERTY.PLANITEMLIFECYCLELISTENERS.FIELDS.STRING\" : \"String\",\n    \"PROPERTY.PLANITEMLIFECYCLELISTENERS.FIELDS.STRING.PLACEHOLDER\" : \"Enter a string\",\n    \"PROPERTY.PLANITEMLIFECYCLELISTENERS.FIELDS.IMPLEMENTATION\" : \"Implementation\",\n    \"PROPERTY.PLANITEMLIFECYCLELISTENERS.FIELDS.EMPTY\" : \"No Field selected\",\n\n    \"PROPERTY.SIGNALDEFINITIONS.DISPLAY\" : \"{{length}} définitions de signal\",\n    \"PROPERTY.SIGNALDEFINITIONS.EMPTY\" : \"Aucune définitions de signal configuré\",\n    \"PROPERTY.SIGNALDEFINITIONS.SCOPE-GLOBAL\": \"Global\",\n    \"PROPERTY.SIGNALDEFINITIONS.SCOPE-PROCESSINSTANCE\": \"Instance de processus \",\n    \"PROPERTY.SIGNALDEFINITIONS.ID\" : \"Identifiant\",\n    \"PROPERTY.SIGNALDEFINITIONS.NAME\" : \"Nom\",\n    \"PROPERTY.SIGNALDEFINITIONS.SCOPE\" : \"Portée\",\n\n    \"PROPERTY.MESSAGEDEFINITIONS.DISPLAY\" : \"{{length}} definitions de message\",\n    \"PROPERTY.MESSAGEDEFINITIONS.EMPTY\" : \"Aucune définitions de message configuré\",\n    \"PROPERTY.MESSAGEDEFINITIONS.ID\" : \"Identifiant\",\n    \"PROPERTY.MESSAGEDEFINITIONS.NAME\" : \"Nom\",\n\n    \"PROPERTY.SEQUENCEFLOW.ORDER.EMPTY\" : \"Aucune ordre de flux de séquence défini\",\n    \"PROPERTY.SEQUENCEFLOW.ORDER.NOT.EMPTY\" : \"Ordre flux de séquence order défini\",\n    \"PROPERTY.SEQUENCEFLOW.ORDER.NO.OUTGOING.SEQUENCEFLOW.FOUND\" : \"Aucun flux de séquence sortant trouvé.\",\n    \"PROPERTY.SEQUENCEFLOW.ORDER.DESCRIPTION\" : \"Définir l'ordre dans lequel le flux de séquence doit être évalué:\",\n    \"PROPERTY.SEQUENCEFLOW.ORDER.SEQUENCEFLOW.VALUE\" : \"Flux de séquence vers {{targetType}} {{targetTitle}}\",\n\n    \"PROPERTY.SEQUENCEFLOW.CONDITION.TITLE\" : \"condition du flux de séquence \",\n    \"PROPERTY.SEQUENCEFLOW.CONDITION.STATIC\" : \"Condition expression\",\n    \"PROPERTY.SEQUENCEFLOW.CONDITION.NO-CONDITION-DISPLAY\": \"Aucune condition définie\",\n\n    \"PROPERTY.DUEDATE.EMPTY\" : \"Aucune date d'échéance\",\n    \"PROPERTY.DUEDATE.DEFINED\" : \"Date d'échéance définie\",\n    \"PROPERTY.DUEDATE.TITLE\" : \"Date d'échéance\",\n    \"PROPERTY.DUEDATE.EXPRESSION-LABEL\" : \"Expression de la Date d'échéance \",\n    \"PROPERTY.DUEDATE.TASK-DUE-DATE-OPTIONS.NO-DUEDATE\" : \"Aucune date d'échéance\",\n    \"PROPERTY.DUEDATE.TASK-DUE-DATE-OPTIONS.EXPRESSION\" : \"Définition de l'expression \",\n    \"PROPERTY.DUEDATE.TASK-DUE-DATE-OPTIONS.STATIC\" : \"Durée fixe après la création de la tâche\",\n    \"PROPERTY.DUEDATE.TASK-DUE-DATE-OPTIONS.FIELD\" : \"Basé sur le champ\",\n\n    \"MODEL.SAVE.TITLE\" : \"Sauvegarder le modèle\",\n    \"MODEL.VALIDATE.TITLE\" : \"Validation des résultats\",\n    \"MODEL.NAME\" : \"Nom\",\n    \"MODEL.KEY\" : \"Clé\",\n    \"MODEL.DESCRIPTION\" : \"Description\",\n    \"MODEL.SAVE.NEWVERSION\" : \"Sauvegarder ceci en tant que nouvelle version?  Cela signifie que vous pouvez toujours revenir à une version précédente\",\n    \"MODEL.SAVE.COMMENT\" : \"Commentaire\",\n    \"MODEL.SAVE.SAVING\" : \"Sauvegarder du modèle\",\n    \"MODEL.LASTMODIFIEDDATE\" : \"Dernière sauvegarde\",\n    \"MODEL.SAVE.ERROR\": \"Erreur innatendue: impossible de sauvegarder le modèle\",\n    \"MODEL.VALIDATIONERRORS\": \"Notez que le modèle contient des erreurs de validation. Cela signifie que le modèle ne peut pas être déployé sur le Moteur Flowable dans son état actuel.\",\n    \"MODEL.CONFLICT.WRITE\": \"Impossible de sauvegarder le modèle: '{{userFullName}}' a éffectué des changements à ce modèle\",\n    \"MODEL.CONFLICT.WRITE.OPTIONS\": \"Sélectionner une option pour résoudre ce conflit:\",\n    \"MODEL.CONFLICT.WRITE.OPTION.OVERWRITE\": \"Surcharger l'autre modèle\",\n    \"MODEL.CONFLICT.WRITE.OPTION.DISCARDCHANGES\": \"Ignorer mes modifications\",\n    \"MODEL.CONFLICT.WRITE.OPTION.SAVEAS\": \"Sauvegarder en tant que nouveau modèle\",\n    \"MODEL.CONFLICT.WRITE.OPTION.NEWVERSION\": \"Créer une nouvelle version\",\n    \"MODEL.CONFLICT.SAVEAS\" : \"Sauvegarder en tant que:\",\n\n    \"EVENT_TYPE.ACTIVITY.COMPENSATE.TOOLTIP\": \"Une activité est sur le point d'être exécutée en compensation d'une autre activité. L'événement cible l'activité qui va être exécutée par compensation\",\n    \"EVENT_TYPE.ACTIVITY.COMPLETED.TOOLTIP\": \"Une activité a été terminée avec succès\",\n    \"EVENT_TYPE.ACTIVITY.ERROR.RECEIVED.TOOLTIP\": \"Une activité a reçu un événement d'erreur. Expédié avant que l'erreur réelle n'ait été reçue par l'activité\",\n    \"EVENT_TYPE.MEMBERSHIP.CREATED.TOOLTIP\": \"Une nouvelle adhésion a été créée\",\n    \"EVENT_TYPE.MEMBERSHIP.DELETED.TOOLTIP\": \"Une seule adhésion a été supprimée\",\n    \"EVENT_TYPE.MEMBERSHIPS.DELETED.TOOLTIP\": \"Toutes les adhésions au groupe concerné ont été supprimées. Aucun évènement individuel ne sera envoyé pour des raisons de performances\",\n    \"EVENT_TYPE.TASK.ASSIGNED.TOOLTIP\": \"Une tâche a été assignée. Ceci est executé en même temps qu'un événement ENTITY_UPDATED\",\n    \"EVENT_TYPE.TASK.COMPLETED.TOOLTIP\": \"Une tâche a été effectuée. Déployé avant que l'entité de tâche ne soit supprimée\",\n    \"EVENT_TYPE.UNCAUGHT.BPMNERROR.TOOLTIP\": \"Lorsqu'une erreur BPMN a été lancée, mais elle n'a pas été prise dans le processus\",\n    \"EVENT_TYPE.VARIABLE.CREATED.TOOLTIP\": \"Une nouvelle variable a été créé\",\n    \"EVENT_TYPE.VARIABLE.DELETED.TOOLTIP\": \"Une variable existante a été supprimé\",\n    \"EVENT_TYPE.VARIABLE.UPDATED.TOOLTIP\": \"Une variable existante a été mis à jour\",\n\n    \"PROPERTY.DECISIONTABLEREFERENCE.EMPTY\" : \"Aucune référence sélectionné\",\n    \"PROPERTY.DECISIONTABLEREFERENCE.TITLE\" : \"Référence de la table de décision\",\n    \"PROPERTY.DECISIONTABLEREFERENCE.ERROR.FORM\" : \"Une erreur s'est produite lors du chargement des tables de décision. Veuillez réessayer ultérieurement\",\n    \"PROPERTY.DECISIONTABLEREFERENCE.DECISIONTABLE.LOADING\" : \"Chargement des tables de décision...\",\n    \"PROPERTY.DECISIONTABLEREFERENCE.DECISIONTABLE.EMPTY\" : \"Ce répertoire ne contient pas de tables de décision\",\n\n    \"PROPERTY.CASEREFERENCE.EMPTY\" : \"Aucune référence sélectionné\",\n    \"PROPERTY.CASEREFERENCE.TITLE\" : \"Réference du modèle de cas\",\n    \"PROPERTY.CASEREFERENCE.ERROR.FORM\" : \"Une erreur a été rencontré lors du chargement des modèles de cas.  Veuillez réessayer ultérieurement\",\n    \"PROPERTY.CASEREFERENCE.CASE.LOADING\" : \"Chargement des modèles de cas...\",\n    \"PROPERTY.CASEREFERENCE.CASE.EMPTY\" : \"Ce répertoire ne contient pas de modèle de cas\"\n}\n"
  },
  {
    "path": "flowable-ui-web/modeler/i18n/pt-BR.json",
    "content": "{\n  \"GENERAL\":{\n    \"MAIN-TITLE\":\"Editor Flowable\",\n    \"NAVIGATION\":{\n      \"PROCESSES\":\"Processos\",\n      \"FORMS\":\"Formulários\",\n      \"DECISION-TABLES\":\"Tabelas de Decisão\",\n      \"APPS\":\"Aplicativos\"\n    },\n    \"TITLE\":{\n      \"SELECT-GROUP\":\"Selecionar grupo\",\n      \"MATCHING-GROUPS\":\"Grupos correspondentes\",\n      \"FILTER\":\"Filtro\",\n      \"HISTORY\":\"Histórico\"\n    },\n    \"ACTION\":{\n      \"LOGOUT\":\"Sair\",\n      \"RETURN-TO-LIST\":\"Mostrar todas as definições\",\n      \"CANCEL\":\"Cancelar\",\n      \"CLOSE\":\"Fechar\",\n      \"EDIT\":\"Editar\",\n      \"SAVE\":\"Salvar\",\n      \"OPEN\":\"Abrir\",\n      \"OK\":\"Ok\",\n      \"CONFIRM\":\"Confirmar\",\n      \"CONFIRM-AND-CLOSE\":\"Confirmar e fechar\",\n      \"NEW-FORM\":\"Novo formulário\",\n      \"CREATE-FORM\":\"Criar formulário\",\n      \"NEW-DECISION-TABLE\":\"Nova tabela de decisão\",\n      \"CREATE-DECISION-TABLE\":\"Criar tabela de decisão\"\n    },\n    \"MESSAGE\":{\n      \"SELECT-GROUP-HELP\":\"Use &uparrow; e &downarrow; para selecionar e pressione Enter para confirmar\",\n      \"PEOPLE-NO-MATCHING-RESULTS\":\"Nenhum usuário correspondente foi encontrado\",\n      \"GROUP-NO-MATCHING-RESULTS\":\"Nenhum grupo correspondente foi encontrado\",\n      \"GROUP-SOURCE-TYPE\":\"Grupo de origem\",\n      \"GROUP-SOURCE-SEARCH-OPTION\":\"Pesquisa por grupo\",\n      \"GROUP-SOURCE-FIELD-OPTION\":\"Campo de formulário\"\n    }\n  },\n  \"EDITOR\":{\n    \"POPUP\":{\n      \"UNSAVED-CHANGES\":{\n        \"TITLE\":\"Você tem alterações não salvas\",\n        \"DESCRIPTION\":\"O que deseja fazer com as suas alterações não salvas?\",\n        \"ACTION\":{\n          \"SAVE\":\"Salvar as alterações\",\n          \"DISCARD\":\"Descartar as alterações\",\n          \"CONTINUE\":\"Continuar editando\"\n        }\n      }\n    }\n  },\n  \"PROCESS-LIST\":{\n    \"TITLE\":\"Modelo de processo de negócios\",\n    \"SEARCH-PLACEHOLDER\":\"Pesquisar\",\n    \"ACTION\":{\n      \"CREATE\":\"Criar processo\",\n      \"IMPORT\":\"Importar processo\"\n    },\n    \"FILTER\":{\n      \"PROCESSES\":\"Modelos de processo\",\n      \"PROCESSES-COUNT\":\"Existem {{total}} modelos de processos\",\n      \"PROCESSES-ONE\":\"Há um modelo de processo\",\n      \"PROCESSES-EMPTY\":\"Não há modelo de processo criado ainda. Você pode projetar modelos de processos, formulários de usuário e então empacotá-los em um aplicativo de processo. O primeiro passo é criar um modelo de processo:\",\n      \"PROCESSES-BPMN-HINT\":\"Crie um modelo BPMN usando o Editor Visual de BPMN.\",\n      \"PROCESSES-BPMN-IMPORT-HINT\":\"Você também pode importar modelos BPMN existentes.\",\n      \"FILTER-TEXT\":\", correspondente a \\\"{{filterText}}\\\"\",\n      \"FILTER-TEXT-EMPTY\":\"Não há modelo de processo correspondente a \\\"{{filterText}}\\\"\",\n      \"RECENT\":\"Recente\",\n      \"RECENT-COUNT\":\"{{total}} modelos usados recentemente\",\n      \"RECENT-ONE\":\"Um modelo usado recentemente\",\n      \"RECENT-EMPTY\":\"Nenhum modelo usado recentemente\"\n    },\n    \"SORT\":{\n      \"MODIFIED-ASC\":\"Mais antigo\",\n      \"MODIFIED-DESC\":\"Modificado por último\",\n      \"NAME-ASC\":\"Nome, A-Z\",\n      \"NAME-DESC\":\"Nome, Z-A\"\n    }\n  },\n  \"FORMS-LIST\":{\n    \"TITLE\":\"Formulários\",\n    \"SEARCH-PLACEHOLDER\":\"Pesquisar\",\n    \"ACTION\":{\n      \"CREATE\":\"Criar formulário\",\n      \"CREATE-INLINE\":\"Crie um novo formulário agora!\",\n      \"SHOW-MORE\":\"Mostrar mais...\"\n    },\n    \"FILTER\":{\n      \"FORMS\":\"Formulários\",\n      \"FORMS-COUNT\":\"Existem {{total}} formulários\",\n      \"FORMS-ONE\":\"Existe um formulário\",\n      \"FORMS-EMPTY\":\"Não existem formulários.  Para adicionar um, clique em criar formulário.\",\n      \"FILTER-TEXT\":\", correspondente a \\\"{{filterText}}\\\"\",\n      \"FILTER-TEXT-EMPTY\":\"Não há formulário correspondente a \\\"{{filterText}}\\\"\"\n    },\n    \"SORT\":{\n      \"MODIFIED-ASC\":\"Mais antigo\",\n      \"MODIFIED-DESC\":\"Último Modificado\",\n      \"NAME-ASC\":\"Nome, A-Z\",\n      \"NAME-DESC\":\"Nome, Z-A\"\n    }\n  },\n  \"DECISION-TABLES-LIST\":{\n    \"TITLE\":\"Tabelas de Decisão\",\n    \"SEARCH-PLACEHOLDER\":\"Busca\",\n    \"ACTION\":{\n      \"CREATE\":\"Criar Tabela de Decisão\",\n      \"IMPORT\":\"Importar tabela de decisão\",\n      \"CREATE-INLINE\":\"Criar uma nova tabela de decisão agora!\",\n      \"SHOW-MORE\":\"Mostrar mais...\"\n    },\n    \"FILTER\":{\n      \"DECISION-TABLES\":\"Tabelas de decisão\",\n      \"DECISION-TABLES-COUNT\":\"Existem {{total}} tabelas de decisão\",\n      \"DECISION-TABLES-ONE\":\"Há uma tabela de decisão\",\n      \"DECISION-TABLES-EMPTY\":\"Não há tabela de decisão. Para adicionar uma, clique em criar tabela de decisão.\",\n      \"FILTER-TEXT\":\", correspondente a \\\"{{filterText}}\\\"\",\n      \"FILTER-TEXT-EMPTY\":\"Não há tabela de decisão correspondente a \\\"{{filterText}}\\\"\"\n    },\n    \"SORT\":{\n      \"MODIFIED-ASC\":\"Mais antigo\",\n      \"MODIFIED-DESC\":\"Modificado por último\",\n      \"NAME-ASC\":\"Nome, A-Z\",\n      \"NAME-DESC\":\"Nome, Z-A\"\n    }\n  },\n  \"APPS-LIST\":{\n    \"TITLE\":\"Definições de Aplicativo\",\n    \"SEARCH-PLACEHOLDER\":\"Pesquisar\",\n    \"ACTION\":{\n      \"CREATE\":\"Criar Aplicativo\",\n      \"IMPORT\":\"Importar aplicativo\",\n      \"SHOW-MORE\":\"Mostrar mais...\"\n    },\n    \"FILTER\":{\n      \"APPS\":\"Definições de Aplicativo\",\n      \"APPS-COUNT\":\"Existem {{total}} definições de aplicativos\",\n      \"APPS-ONE\":\"Há uma definição de aplicativo\",\n      \"APPS-EMPTY\":\"Não há definições de aplicativo. Para adicionar uma, clique em criar definição de Aplicativo.\",\n      \"FILTER-TEXT\":\", correspondente a \\\"{{filterText}}\\\"\",\n      \"FILTER-TEXT-EMPTY\":\"Não há definições de aplicativo correspondentes a \\\"{{filterText}}\\\"\",\n      \"NO-APPS\":\"Você pode criar uma definição de Aplicativo, através da publicação de um pacote de modelos de processo.\",\n      \"NO-APPS-CALL-TO-ACTION\":\"Você pode criar uma definição de Aplicativo agora.\",\n      \"NO-APPS-NOTE\":\"Lembre-se de publicá-lo quando você estiver pronto para usá-lo.\"\n    },\n    \"SORT\":{\n      \"MODIFIED-ASC\":\"Mais antigo\",\n      \"MODIFIED-DESC\":\"Modificado por último\",\n      \"NAME-ASC\":\"Nome, A-Z\",\n      \"NAME-DESC\":\"Nome, Z-A\"\n    }\n  },\n  \"PROCESS\":{\n    \"NAME\":\"Nome do modelo\",\n    \"KEY\":\"Chave do modelo\",\n    \"DESCRIPTION\":\"Descrição\",\n    \"VERSION-COMMENT\":\"Comentários da versão\",\n    \"ACTION\":{\n      \"DETAILS\":\"Mostrar detalhes\",\n      \"EDIT\":\"Modificar propriedades do modelo\",\n      \"DUPLICATE\":\"Duplicar este modelo\",\n      \"EXPORT_BPMN20\":\"Exportar para BPMN 2.0\",\n      \"DELETE\":\"Excluir este modelo\",\n      \"CREATE-CONFIRM\":\"Criar novo modelo\",\n      \"DUPLICATE-CONFIRM\":\"Duplique o modelo\",\n      \"OPEN-IN-EDITOR\":\"Editor Visual\",\n      \"EDIT-CONFIRM\":\"Salvar\",\n      \"DELETE-CONFIRM\":\"Excluir o modelo de processo\",\n      \"USE-AS-NEW-VERSION\":\"Usar como uma nova versão\",\n      \"FAVORITE\":\"Adicionar este modelo aos favoritos\"\n    },\n    \"DETAILS\":{\n      \"HISTORY-TITLE\":\"Histórico\",\n      \"LAST-UPDATED-BY\":\"Última atualização feita por {{lastUpdatedBy}} - {{lastUpdated | dateformat}}\",\n      \"CREATED-BY\":\"Criado por {{createdBy}}\",\n      \"NO-DESCRIPTION\":\"Este modelo não tem descrição. Modifique as propriedades do modelo para adicionar uma\"\n    },\n    \"POPUP\":{\n      \"CREATE-TITLE\":\"Criar um novo modelo de processo de negócio\",\n      \"DUPLICATE-TITLE\":\"Duplicar o modelo de processo de negócio\",\n      \"CREATE-DESCRIPTION\":\"Você precisa dar um nome para o novo modelo e você pode querer também adicionar uma descrição ao mesmo tempo.\",\n      \"DUPLICATE-DESCRIPTION\":\"Você pode alterar o nome para o novo modelo e você pode querer alterar a descrição ao mesmo tempo.\",\n      \"EDIT-DESCRIPTION\":\"Altere qualquer uma das propriedades modelo abaixo e em seguida pressione Salvar para atualizar o modelo.\",\n      \"DELETE-DESCRIPTION\":\"Tem certeza que deseja excluir o modelo de processo \\\"{{name}}\\\"?\",\n      \"EDIT-TITLE\":\"Editar detalhes do modelo\",\n      \"DELETE-TITLE\":\"Excluir o modelo\",\n      \"DELETE-LOADING-RELATIONS\":\"Verificar o uso de modelo...\",\n      \"DELETE-RELATIONS-DESCRIPTION-SINGLE\":\"Este modelo não pode ser excluído, porque o outro modelo está a usá-lo:\",\n      \"DELETE-RELATIONS-DESCRIPTION\":\"Este modelo não pode ser excluído, porque ele é usado por outros modelos:\",\n      \"DELETE-PROCESS-RELATION\":\"Modelos de processo\",\n      \"DELETE-FORM-RELATION\":\"Modelo de formulário\",\n      \"DELETE-APP-RELATION\":\"Modelo de aplicativo\",\n      \"IMPORT-DESCRIPTION\":\"Por favor, procure ou arraste e solte uma definição de BPMN XML com um arquivo .bpmn ou .bpmn20.xml\",\n      \"IMPORT-TITLE\":\"Importar um modelo de processo\",\n      \"USE-AS-NEW-TITLE\":\"Use como nova versão\",\n      \"USE-AS-NEW-DESCRIPTION\":\"Tem certeza que quer usar a versão {{version}} para criar uma nova versão de \\\"{{name}}\\\"?\",\n      \"USE-AS-NEW-UNRESOLVED-MODELS-ERROR\":\"Não foi possível restaurar completamente o modelo de aplicativo para a versão escolhida: alguns modelos referenciados estão ausentes poque foram excluído no passado. Por favor, atualize o modelo de aplicativo em conformidade. Modelos faltantes:\",\n      \"USE-AS-NEW-UNRESOLVED-MODEL\":\"Modelo '{{name}}' com id interno {{id}}, criado por {{createdBy}}\",\n      \"SHARED-WITH\":\"Compartilhado com\",\n      \"PERMISSION\":\"Permissão\",\n      \"ACTIONS\":\"Ações\",\n      \"IMPORT\":{\n        \"DROPZONE\":\"Arraste e solte um arquivo .bpmn ou bpmn20.xml\",\n        \"CANCEL-UPLOAD\":\"Cancelar o upload\",\n        \"ERROR\":\"Erro ao processar o arquivo XML BPMN\",\n        \"NO-DROP\":\"Arrastar e soltar não suportado\"\n      }\n    },\n    \"ALERT\":{\n      \"EDIT-CONFIRM\":\"Modelo atualizado\"\n    },\n    \"ERROR\":{\n      \"NOT-FOUND\":\"O modelo solicitado não existe\"\n    }\n  },\n  \"SUBPROCESS\":{\n    \"NAME\":\"Nome do subprocesso\",\n    \"DESCRIPTION\":\"Descrição\",\n    \"ACTION\":{\n      \"CREATE-CONFIRM\":\"Criar novo subprocesso\"\n    },\n    \"POPUP\":{\n      \"CREATE-TITLE\":\"Criar um novo subprocesso\",\n      \"CREATE-DESCRIPTION\":\"Você precisa dar um nome para o novo subprocesso e você pode querer adicionar uma descrição ao mesmo tempo.\"\n    }\n  },\n  \"FORM\":{\n    \"NAME\":\"Nome do formulário\",\n    \"KEY\":\"Chave do formulário\",\n    \"DESCRIPTION\":\"Descrição\",\n    \"ACTION\":{\n      \"DETAILS\":\"Mostrar detalhes\",\n      \"EDIT\":\"Modificar propriedades do modelo\",\n      \"DELETE\":\"Excluir este formulário\",\n      \"CREATE-CONFIRM\":\"Criar novo formulário\",\n      \"DUPLICATE-CONFIRM\":\"Duplicar o formulário\",\n      \"OPEN-IN-EDITOR\":\"Editor de formulário\",\n      \"EDIT-CONFIRM\":\"Salvar\",\n      \"DELETE-CONFIRM\":\"Excluir Formulário\",\n      \"USE-AS-NEW-VERSION\":\"Usar como uma nova versão\"\n    },\n    \"DETAILS\":{\n      \"HISTORY-TITLE\":\"Histórico\",\n      \"LAST-UPDATED-BY\":\"Última atualização feita por {{lastUpdatedBy}} - {{lastUpdated | dateformat}}\",\n      \"CREATED-BY\":\"Criado por {{createdBy}}\"\n    },\n    \"POPUP\":{\n      \"CREATE-TITLE\":\"Criar novo formulário\",\n      \"DUPLICATE-TITLE\":\"Duplicar o formulário\",\n      \"CREATE-DESCRIPTION\":\"Você precisa dar um nome para o novo formulário e você pode querer adicionar uma descrição ao mesmo tempo.\",\n      \"DUPLICATE-DESCRIPTION\":\"Você precisa dar um nome para o novo formulário e você pode querer adicionar uma descrição ao mesmo tempo.\",\n      \"SAVE-FORM-TITLE\":\"Salvar formulário\",\n      \"EDIT-DESCRIPTION\":\"Altere qualquer uma das propriedades do formulário abaixo e em seguida pressione Salvar para atualizar o formulário.\",\n      \"DELETE-DESCRIPTION\":\"Tem certeza que deseja excluir o formulário \\\"{{name}}\\\"?\",\n      \"EDIT-TITLE\":\"Editar detalhes do formulário\",\n      \"DELETE-TITLE\":\"Excluir Formulário\",\n      \"USE-AS-NEW-TITLE\":\"Usar como uma nova versão\",\n      \"USE-AS-NEW-VERSION\":\"Usar como uma nova versão\",\n      \"USE-AS-NEW-DESCRIPTION\":\"Tem certeza que quer usar a versão {{version}} para criar uma nova versão de \\\"{{name}}\\\"?\",\n      \"USE-AS-NEW-UNRESOLVED-MODELS-ERROR\":\"Não foi possível restaurar completamente o modelo de aplicativo para a versão escolhida: alguns modelos referenciados estão ausentes poque foram excluído no passado. Por favor, atualize o modelo de aplicativo em conformidade. Modelos faltantes:\",\n      \"USE-AS-NEW-UNRESOLVED-MODEL\":\"Modelo '{{name}}' com id interno {{id}}, criado por {{createdBy}}\"\n    }\n  },\n  \"DECISION-TABLE\":{\n    \"NAME\":\"Nome da tabela de decisão\",\n    \"KEY\":\"Chave de tabela de decisão\",\n    \"DESCRIPTION\":\"Descrição\",\n    \"VERSION-COMMENT\":\"Comentários da versão\",\n    \"HIT-POLICY\":\"Acertar política:\",\n    \"ACTION\":{\n      \"DETAILS\":\"Mostrar detalhes\",\n      \"EDIT\":\"Modificar propriedades do modelo\",\n      \"SHARE\":\"Compartilhar esta tabela de decisão\",\n      \"DELETE\":\"Excluir esta tabela de decisão\",\n      \"ADD-COMMENT\":\"+ Adicionar comentário\",\n      \"CREATE-CONFIRM\":\"Criar nova tabela de decisão\",\n      \"OPEN-IN-EDITOR\":\"Editor de tabela de decisão\",\n      \"EXPORT\":\"Exportar tabela de decisão\",\n      \"DELETE-CONFIRM\":\"Excluir a tabela de decisão\",\n      \"USE-AS-NEW-VERSION\":\"Usar como uma nova versão\",\n      \"FAVORITE\":\"Adicionar esta tabela de decisão aos favoritos\",\n      \"DUPLICATE\":\"Duplicar esta tabela de decisão\"\n    },\n    \"DETAILS\":{\n      \"HISTORY-TITLE\":\"Histórico\",\n      \"COMMENTS-TITLE\":\"Comentários\",\n      \"LAST-UPDATED-BY\":\"Última atualização feita por {{lastUpdatedBy}} - {{lastUpdated | dateformat}}\",\n      \"CREATED-BY\":\"Criado por {{createdBy}}\"\n    },\n    \"HIT-POLICIES\":{\n      \"FIRST\":\"Primeiro (passagem única)\",\n      \"ANY\":\"Qualquer (passagem única)\"\n    },\n    \"POPUP\":{\n      \"CREATE-TITLE\":\"Criar uma nova tabela de decisão\",\n      \"CREATE-DESCRIPTION\":\"Você precisa dar um nome para a nova tabela de decisão, e você pode querer adicionar uma descrição ao mesmo tempo.\",\n      \"SAVE-DESCRIPTION\":\"Você precisa dar um nome e uma chave exclusiva para a nova tabela de decisão, e você pode querer adicionar uma descrição ao mesmo tempo.\",\n      \"DUPLICATE-TITLE\":\"Duplicar uma tabela de decisão\",\n      \"DUPLICATE-DESCRIPTION\":\"Você pode dar um nome para a tabela de decisão, e pode querer alterar a descrição ao mesmo tempo.\",\n      \"DELETE-TITLE\":\"Excluir a tabela de decisão\",\n      \"DELETE-DESCRIPTION\":\"Tem certeza que deseja excluir a tabela de decisão \\\"{{name}}\\\"?\",\n      \"SAVE-DECISION-TABLE-TITLE\":\"Salvar a tabela de decisão\",\n      \"IMPORT-DESCRIPTION\":\"Por favor, procure ou arraste e solte uma definição de DMN XML com uma extensão .dmn ou .dmn.xml\",\n      \"IMPORT-TITLE\":\"Importar um modelo DMN\",\n      \"IMPORT\":{\n        \"DROPZONE\":\"Arraste e solte um arquivo DMN XML com extensão .dmn ou .dmn.xml\",\n        \"CANCEL-UPLOAD\":\"Cancelar o carregamento\",\n        \"ERROR\":\"Erro ao processar o arquivo XML DMN\",\n        \"NO-DROP\":\"Arrastar e soltar não suportado\"\n      },\n      \"USE-AS-NEW-TITLE\":\"Usar como uma nova versão\",\n      \"USE-AS-NEW-VERSION\":\"Usar como uma nova versão\",\n      \"USE-AS-NEW-DESCRIPTION\":\"Tem certeza que quer usar a versão {{version}} para criar uma nova versão de \\\"{{name}}\\\"?\",\n      \"USE-AS-NEW-UNRESOLVED-MODELS-ERROR\":\"Não foi possível restaurar completamente o modelo de aplicativo para a versão escolhida: alguns modelos referenciados estão ausentes poque foram excluído no passado. Por favor, atualize o modelo de aplicativo em conformidade. Modelos faltantes:\",\n      \"USE-AS-NEW-UNRESOLVED-MODEL\":\"Modelo '{{name}}' com id interno {{id}}, criado por {{createdBy}}\"\n    },\n    \"ALERT\":{\n      \"FAVORITE-CONFIRM\":\"Esta tabela de decisão agora está adicionada aos favoritos\",\n      \"UN-FAVORITE-CONFIRM\":\"Esta tabela de decisão já não está mais nos favoritos\"\n    }\n  },\n  \"APP\":{\n    \"NAME\":\"Nome de definição do Aplicativo\",\n    \"KEY\":\"Chave de definição do aplicativo\",\n    \"DESCRIPTION\":\"Descrição\",\n    \"ICON\":\"Ícone\",\n    \"THEME\":\"Tema\",\n    \"GROUPS-ACCESS\":\"Acesso de grupos, separado por vírgulas\",\n    \"USERS-ACCESS\":\"Acesso de usuários, separado por vírgulas\",\n    \"ACTION\":{\n      \"DETAILS\":\"Mostrar detalhes\",\n      \"EDIT\":\"Modificar propriedades de definição do aplicativo\",\n      \"DUPLICATE\":\"Duplique esta aplicação\",\n      \"SHARE\":\"Compartilhar esta definição de aplicativo\",\n      \"DELETE\":\"Excluir esta definição de aplicativo\",\n      \"CREATE-CONFIRM\":\"Criar nova definição de aplicativo\",\n      \"DUPLICATE-CONFIRM\":\"Duplicar a definição de aplicativo\",\n      \"DELETE-CONFIRM\":\"Excluir a definição de aplicativo\",\n      \"USE-AS-NEW-VERSION\":\"Usar como uma nova versão\",\n      \"OPEN-IN-EDITOR\":\"Editor de Aplicativo\",\n      \"PUBLISH\":\"Publicar\",\n      \"PUBLISH-CONFIRM\":\"Publicar a definição de aplicativo\",\n      \"SELECT-ICON\":\"Mudar ícone...\",\n      \"SELECT-THEME\":\"Alterar tema...\",\n      \"EDIT-MODELS\":\"Editar modelos incluídos\",\n      \"EXPORT-ZIP\":\"Exportar definição de aplicativo como um arquivo zip\",\n      \"EXPORT-BAR\":\"Exportar definição de aplicativo como um arquivo de implantação bar\"\n    },\n    \"DETAILS\":{\n      \"TITLE\":\"Detalhes da definição do aplicativo: {{name}}\",\n      \"HISTORY-TITLE\":\"Histórico\",\n      \"MODELS-TITLE\":\"Modelos incluídos na definição do aplicativo\",\n      \"LAST-UPDATED-BY\":\"Última atualização feita por {{lastUpdatedBy}} - {{lastUpdated | dateformat}}\",\n      \"CREATED-BY\":\"Criado por {{createdBy}}\",\n      \"NO-DESCRIPTION\":\"Esta definição de aplicativo não tem descrição. Modifique as propriedades de definição do aplicativo para adicionar uma\",\n      \"NO-MODELS-SELECTED\":\"Não há modelos selecionados para este aplicativo\"\n    },\n    \"TITLE\":{\n      \"SELECT-ICON\":\"Selecione o ícone para o aplicativo\",\n      \"SELECT-THEME\":\"Selecione as cores para o aplicativo\",\n      \"PREVIEW\":\"Visualizar\"\n    },\n    \"POPUP\":{\n      \"CREATE-TITLE\":\"Criar uma nova definição de aplicativo\",\n      \"DUPLICATE-TITLE\":\"Duplicar uma definição de aplicativo\",\n      \"SAVE-APP-TITLE\":\"Salvar a definição de aplicativo\",\n      \"SAVE-APP-SAVE-SUCCESS\":\"Definição de aplicativo salva\",\n      \"CREATE-DESCRIPTION\":\"Você precisa dar um nome para a nova definição do aplicativo, e você pode querer também adicionar uma descrição ao mesmo tempo.\",\n      \"DUPLICATE-DESCRIPTION\":\"Você pode dar um nome para a nova definição de aplicativo, e pode querer alterar a descrição ao mesmo tempo.\",\n      \"PUBLISH-TITLE\":\"Publicar a definição de aplicativo\",\n      \"PUBLISH-DESCRIPTION\":\"Tem certeza que deseja publicar a definição do aplicativo \\\"{{name}}\\\"? Note que esta definição de aplicativo será versionada e o aplicativo de worflow será atualizado se existente.\",\n      \"PUBLISH-FIELD\":\"Publicar? Observe que, se a publicação estiver habilitado, esta definição de aplicativo será versionada e o aplicativo de workflow será atualizado se já existente.\",\n      \"PUBLISH-ERROR-PROCDEF-KEY-CONFLICT\":\"Seu modelo de processo \\\"{{modelInAppName}}\\\" tem o mesmo identificador de \\\"{{processDefinitionKey}}\\\" com o processo previamente implantado \\\"{{conflictingModelName}}\\\" do aplicativo \\\"{{conflictingAppName}}\\\". Por favor, altere a propriedade \\\"id\\\" do modelo de processo para algo diferente.\",\n      \"PUBLISH-ERROR-PROCESS-ALREADY-USED\":\"Os seguintes modelos de processos já são utilizados em outro aplicativo. Isto está correto?\",\n      \"PUBLISH-ERROR-PROCESS-ALREADY-USED-APP\":\"Aplicativo\",\n      \"PUBLISH-ERROR-PROCDEF-DUPLICATE-KEYS\":\"Aplicativo inválido: identificadores de processo duplicados foram encontrados (altere a propriedade de \\\"id\\\" dos modelos de processo com id duplicados):\",\n      \"DELETE-TITLE\":\"Excluir a definição de aplicativo\",\n      \"DELETE-DESCRIPTION\":\"Tem certeza que deseja excluir a definição do aplicativo \\\"{{name}}\\\"?\",\n      \"DELETE-DESCRIPTION-WITH-RUNTIME\":\"Tem certeza que deseja excluir a definição do aplicativo \\\"{{name}}\\\"? Note que esta definição de aplicativo foi implantada como uma tarefa de página inicial, o aplicativo será removido da página inicial.\",\n      \"DELETE-CASCADE-FALSE\":\"Somente apagar a versão atual desta definição de aplicativo (v{{version}})\",\n      \"DELETE-CASCADE-TRUE\":\"Também excluir todas as versões anteriores desta definição de aplicativo\",\n      \"HAS-CUSTOM-STENCILITEM\":\"O modelo \\\"{{modelName}}\\\" usa um estêncil com itens de estêncil personalizado. Não é possível usar este modelo em uma definição de aplicativo.\",\n      \"HAS-VALIDATIONERROR\":\"O modelo \\\"{{modelName}}\\\" tem erros de validação e não pode ser adicionado a uma definição de aplicativo. Abra o modelo no editor para ver mais detalhes sobre o(s) erro(s) de validação.\",\n      \"IMPORT-DESCRIPTION\":\"Por favor, procure ou arraste e solte uma definição de aplicativo com a extensão .zip\",\n      \"IMPORT-TITLE\":\"Importar um modelo de definição de aplicativo\",\n      \"IMPORT\":{\n        \"DROPZONE\":\"Arraste e solte um arquivo de definição de aplicativo .zip\",\n        \"CANCEL-UPLOAD\":\"Cancelar o carregamento\",\n        \"RENEWIDM-IDS\":\"Renove os identificadores de usuário e grupo ao importar os passos e modelos BPMN. Isso é muitas vezes necessário ao importar a definição de aplicativo em um ambiente Flowable diferente. Isto vai tentar vincular o etapas humanas e tarefas de usuário para usuário e grupo correto no ambiente de destino.\",\n        \"ERROR\":\"Erro ao processar o arquivo de definição de aplicativo\",\n        \"NO-DROP\":\"Arrastar e soltar não suportado\"\n      },\n      \"INCLUDE-MODELS-TITLE\":\"Modelos incluídos na definição do aplicativo\"\n    },\n    \"ALERT\":{\n      \"DELETE-CONFIRM\":\"Definição de Aplicativo excluída\",\n      \"PUBLISH-CONFIRM\":\"A definição de aplicativo foi publicada\",\n      \"PUBLISH-ERROR\":\"Não foi possível publicar a definição de aplicativo. Por favor, verifique a validade dos modelos de processos referenciados\"\n    }\n  },\n  \"SHARE-INFO\":{\n    \"ACTION\":{\n      \"ADD\":\"Adicionar outra pessoa\"\n    }\n  },\n  \"FORM-BUILDER\":{\n    \"PALLETTE\":{\n      \"TEXT\":\"Texto\",\n      \"PASSWORD\": \"Senha\",\n      \"MULTILINE-TEXT\":\"Texto de multilinhas\",\n      \"NUMBER\":\"Número\",\n      \"CHECKBOX\":\"Caixa de seleção\",\n      \"DATE\":\"Data\",\n      \"DROPDOWN\":\"Seleção simples\",\n      \"RADIO\":\"Botões de opção\",\n      \"PEOPLE\":\"Pessoas\",\n      \"GROUP-OF-PEOPLE\":\"Grupo de pessoas\",\n      \"UPLOAD\":\"Carregar\",\n      \"EXPRESSION\":\"Expressão\",\n      \"DECIMAL\":\"Decimal\",\n      \"HYPERLINK\":\"Hiperlink\",\n      \"SPACER\": \"Spacer\",\n\t  \"HORIZONTAL-LINE\": \"Horizontal line\",\n\t  \"HEADLINE\": \"Headline\",\n\t  \"HEADLINE-WITH-LINE\":\"Headline\"\n    },\n    \"TABS\":{\n      \"GENERAL\":\"Geral\",\n      \"OPTIONS\":\"Opções\",\n      \"UPLOAD-OPTIONS\":\"Opções de carregamento\",\n      \"ADVANCED-OPTIONS\":\"Avançado\"\n    },\n    \"VERSION\":\"Versão {{version}}\",\n    \"LAST-UPDATED\":\"Última atualização feita por {{lastUpdatedBy}}, {{lastUpdated | dateformat}}\",\n    \"TITLE\":{\n      \"DESIGN\":\"Desenho\",\n      \"OUTCOME\":\"Resultados\"\n    },\n    \"POPUP\":{\n      \"EDIT-TITLE\":\"Editar o campo '{{name}}'\",\n      \"EXPRESSION-TITLE\":\"Editar expressão\"\n    },\n    \"MESSAGE\":{\n      \"EMPTY-EXPRESSION\":\"(Nenhuma expressão)\",\n      \"EXPRESSION-HELP\":\"Você também pode exibir valores anteriormente apresentados sob qualquer formulário, como parte do texto, referenciando-os usando uma notação como segue ${myFieldId}.\",\n      \"OPTIONS-EXPRESSION-HELP\": \"Você pode usar uma expressão para preencher dinamicamente opções, por exemplo, fazendo referência a uma variável como esta ${optionsVariable}. A expressão precisa resultar em um objeto java (java.util.List com objetos Option) ou sua representação json.\"\n    },\n    \"LABEL\":{\n      \"FUNCTIONAL-GROUP\":\"Selecione o grupo..\",\n      \"PERSON\":\"Selecione a pessoa..\"\n    },\n    \"COMPONENT\":{\n      \"LABEL\":\"Rótulo:\",\n      \"OVERRIDEID\":\"Substituir o id?\",\n      \"ID\":\"Id:\",\n      \"PLACEHOLDER\":\"Marcador:\",\n      \"OPTIONS\":\"Opções\",\n      \"RADIO-BUTTON-DEFAULT\":\"Opção 1\",\n      \"DROPDOWN-DEFAULT-EMPTY-SELECTION\":\"Por favor, escolha uma...\",\n      \"DROPDOWN-EMPTY-VALUE-HELP\":\"Esta é a opção 'valor vazio'. Selecionar isto em tempo de execução significa dizer 'sem valor' ou 'vazio'.  Isto é permitido para campos opcionais, mas não permitido para campos obrigatórios.\",\n      \"OPTIONS-EXPRESSION\": \"Expressão de opções:\",\n      \"OPTIONS-EXPRESSION-ENABLED\": \"Ativar expressão de opções\",\n      \"REQUIRED\":\"Obrigatório\",\n      \"READONLY\":\"Somente leitura\",\n      \"EXPRESSION\":\"Expressão\",\n      \"ADD-OPTION\":\"+ Adicionar uma nova opção\",\n      \"UPLOAD-ALLOW-MULTIPLE\":\"Permitir o upload de vários arquivos\",\n      \"MAX-LENGTH\":\"Comprimento máximo:\",\n      \"MIN-LENGTH\":\"Comprimento mínimo:\",\n      \"PASSWORD-UNMASK-OPTION\": \"opção de mascaramento/desmascarar senha\",\n      \"HYPERLINK-URL\": \"URL de hiperlink\",\n      \"REGEX-PATTERN\":\"Padrão Regex\",\n      \"MASK\":{\n        \"TITLE\":\"Máscara de entrada\",\n        \"EXAMPLES\":{\n          \"TITLE\":\"Exemplos:\",\n          \"NUMBER\":\"Qualquer número\",\n          \"LETTER\":\"Qualquer letra\",\n          \"NUMBERORLETTER\":\"Qualquer letra ou número\",\n          \"OPTIONAL\":\"Torna a máscara opcional (não valida)\",\n          \"PHONE\":\"Dinheiro\"\n        }\n      }\n    },\n    \"OUTCOMES\":{\n      \"DESCRIPTION\":\"Você pode definir várias saídas para esta tarefa. Quando concluir uma tarefa, os usuários seleciona uma das saídas disponíveis, que podem ser usados em, por exemplo, em uma condição futura no processo.\",\n      \"NO-OUTCOMES-OPTION\":\"Não use as saídas personalizados, apenas mostre um botão 'Completar'.\",\n      \"OUTCOMES-OPTION\":\"Use saídas personalizados para este formulário.\",\n      \"POSSIBLE-OUTCOMES\":\"Saídas possíveis\",\n      \"NEW-OUTCOME-PLACEHOLDER\":\"Insira uma nova saída\",\n      \"ADD\":\"Adicionar saída\",\n      \"REMOVE\":\"Excluir\"\n    }\n  },\n  \"DECISION-TABLE-EDITOR\":{\n    \"EMPTY-MESSAGES\":{\n      \"NO-VARIABLE-SELECTED\":\"Indefinido\"\n    },\n    \"POPUP\":{\n      \"EXPRESSION-EDITOR\":{\n        \"INPUT-TITLE\":\"Editar a coluna de entrada\",\n        \"INPUT-DESCRIPTION\":\"Selecione a variável de entrada como entrada para a coluna\",\n        \"OUTPUT-TITLE\":\"Editar a coluna de saída\",\n        \"OUTPUT-DESCRIPTION\":\"Selecione uma variável de saída existente ou crie uma nova\",\n        \"EXPRESSION-LABEL\":\"Rótulo de coluna:\",\n        \"EXPRESSION-PLACEHOLDER\":\"Digite um rótulo opcional\",\n        \"EXPRESSION-VARIABLE-NAME\":\"Nome da variável:\",\n        \"EXPRESSION-VARIABLE-NAME-PLACEHOLDER\":\"Entre com um nome de variável\",\n        \"OUTPUT-NEW-VARIABLE-ID\":\"ID da variável:\",\n        \"OUTPUT-NEW-VARIABLE-TYPE\":\"Tipo da variável:\"\n      }\n    },\n    \"BUTTON-ADD-INPUT-LABEL\":\"Adicionar entrada\",\n    \"BUTTON-ADD-OUTPUT-LABEL\":\"Adicionar saída\",\n    \"BUTTON-ADD-RULE-LABEL\":\"Adicionar regra\",\n    \"BUTTON-MOVE-RULE-UPWARDS-LABEL\":\"Mover para cima\",\n    \"BUTTON-MOVE-RULE-DOWNWARDS-LABEL\":\"Mover para baixo\",\n    \"BUTTON-REMOVE-RULE-LABEL\":\"Excluir Regra\",\n    \"ALERT\":{\n      \"EXPRESSION-VARIABLE-REQUIRED-ERROR\":\"Todas as expressões de entrada e saídas devem fazer referência a uma variável ou o campo do formulário.\",\n      \"SAVE-CONFIRM\":\"Tabela de decisão '{{name}}' salva\"\n    }\n  },\n  \"TOUR\":{\n    \"WELCOME-TITLE\":\"Bem-vindo, {{userName}}\",\n    \"WELCOME-CONTENT\":\"Esta uma pequena turnê do editor Flowable. Os próximos passos irão guiá-lo através de diferentes seções do aplicativo. Pressione a tecla ESC para parar a turnê a qualquer momento.\",\n    \"PALETTE-TITLE\":\"A paleta\",\n    \"PALETTE-CONTENT\":\"Todas as construções disponíveis para criar um processo de negócios podem ser encontradas aqui. Elas estão organizadas em grupos lógicos. Para abrir um grupo simplesmente clicar nele:\",\n    \"CANVAS-TITLE\":\"O Canvas\",\n    \"CANVAS-CONTENT\":\"Este é o espaço de trabalho no qual você cria seu processo de negócios. Arraste os elementos da paleta da esquerda e solte-os sobre esta tela para iniciar a modelagem.\",\n    \"DRAGDROP-TITLE\":\"Exemplo de arrastar e soltar\",\n    \"DRAGDROP-CONTENT\":\"Aqui está um exemplo de como você deve iniciar com a modelagem:\",\n    \"PROPERTIES-TITLE\":\"Propriedades\",\n    \"PROPERTIES-CONTENT\":\"Aqui você pode configurar as propriedades de uma construção de processo de negócios. Basta selecionar o item na tela e suas propriedades serão mostradas. Clique na propriedade se você quiser editá-la\",\n    \"TOOLBAR-TITLE\":\"A barra de ferramentas\",\n    \"TOOLBAR-CONTENT\":\"Todas as ações podem ser encontradas aqui: salvar ou validar um modelo, copiar e colar partes de um processo e assim por diante. Passe o mouse sobre os botões para obter uma descrição de uma ação.\",\n    \"END-TITLE\":\"Fim\",\n    \"END-CONTENT\":\"É isso! Agora você pode começar a modelagem de seus processos. Se você tiver alguma dúvida, não hesite em perguntar em <a href=\\\"http://forum.flowable.org/\\\" target=\\\"_blank\\\">Fórum Flowable</a> \"\n  },\n  \"FEATURE-TOUR\":{\n    \"BENDPOINT\":{\n      \"TITLE\":\"Tutorial de ponto curva\",\n      \"DESCRIPTION\":\"Quando você estiver se conectando as etapas do processo com o as outras usando o fluxo de sequência (as setas entre as etapas do processo), você pode achar que esses fluxo de sequência se cruzam, ou gostaria de organizá-los de forma diferente. Para fazer isso, você pode adicionar ou remover um ponto de curva para/de um fluxo de sequência. <br/><br/> Como mostrado abaixo na foto, primeiro, clique o 'Adicionar ponto de curva' e, em seguida, clique em um fluxo de sequência para adicioná-lo. Observe que o fluxo de sequência irá mostrar-lhe uma indicação sutil em verde para mostrar o ponto de curva pode ser adicionado lá. <br/><br/> Remover um ponto de curva novo segue um padrão semelhante: clique no botão 'remover ponto de curva' e clique em ponto de curva para removê-lo novamente.\"\n    }\n  },\n  \"ACTION.OK\":\"Ok\",\n  \"ACTION.SAVE\":\"Salvar\",\n  \"ACTION.SAVE-AND-CLOSE\":\"Salve e feche o editor\",\n  \"ACTION.SEND\":\"Enviar\",\n  \"ACTION.CANCEL\":\"Cancelar\",\n  \"ACTION.SELECT\":\"Selecione\",\n  \"ACTION.ADD\":\"Adicionar\",\n  \"ACTION.REMOVE\":\"Excluir\",\n  \"ACTION.MOVE.UP\":\"Mover a entrada para cima\",\n  \"ACTION.MOVE.DOWN\":\"Mover a entrada para baixo\",\n  \"TOOLBAR.ACTION.CLOSE\":\"Fechar o editor e voltar para a página de visão geral\",\n  \"TOOLBAR.ACTION.SAVE\":\"Salvar o modelo\",\n  \"TOOLBAR.ACTION.VALIDATE\":\"Validar o modelo\",\n  \"TOOLBAR.ACTION.CUT\":\"Recortar (selecione um ou mais elementos em seu processo de negócios)\",\n  \"TOOLBAR.ACTION.COPY\":\"Copiar (selecione um ou mais elementos em seu processo de negócios)\",\n  \"TOOLBAR.ACTION.PASTE\":\"Colar\",\n  \"TOOLBAR.ACTION.DELETE\":\"Excluir o elemento selecionado\",\n  \"TOOLBAR.ACTION.UNDO\":\"Desfazer\",\n  \"TOOLBAR.ACTION.REDO\":\"Refazer\",\n  \"TOOLBAR.ACTION.ZOOMIN\":\"Aumentar Zoom\",\n  \"TOOLBAR.ACTION.ZOOMOUT\":\"Diminuir o zoom\",\n  \"TOOLBAR.ACTION.ZOOMACTUAL\":\"Voltar para o tamanho real\",\n  \"TOOLBAR.ACTION.ZOOMFIT\":\"Enquadrar\",\n  \"TOOLBAR.ACTION.BENDPOINT.ADD\":\"Adicionar ponto de curva ao fluxo de sequência selecionado\",\n  \"TOOLBAR.ACTION.BENDPOINT.REMOVE\":\"Remover ponto de curva do fluxo de sequência selecionado\",\n  \"TOOLBAR.ACTION.ALIGNHORIZONTAL\":\"Alinhar o modelo horizontalmente\",\n  \"TOOLBAR.ACTION.ALIGNVERTICAL\":\"Alinhar o modelo verticalmente\",\n  \"TOOLBAR.ACTION.SAMESIZE\":\"Mesmo tamanho\",\n  \"TOOLBAR.ACTION.HELP\":\"Iniciar uma visita guiada\",\n  \"TOOLBAR.ACTION.FEEDBACK\":\"Fornecer feedback\",\n  \"FORM_TOOLBAR.ACTION.SAVE\":\"Salvar o modelo\",\n  \"APP_DEFINITION_TOOLBAR.ACTION.SAVE\":\"Salvar a definição de aplicativo\",\n  \"BUTTON.ACTION.DELETE.TOOLTIP\":\"Excluir o elemento do modelo\",\n  \"BUTTON.ACTION.MORPH.TOOLTIP\":\"Alterar o tipo do elemento\",\n  \"ELEMENT.AUTHOR\":\"Autor\",\n  \"ELEMENT.DATE_CREATED\":\"Data de criação\",\n  \"PROPERTY.REMOVED\":\"removido\",\n  \"PROPERTY.EMPTY\":\"Nenhum valor\",\n  \"PROPERTY.PROPERTY.EDIT.TITLE\":\"Altere o valor para \",\n  \"PROPERTY.FEEDBACK.TITLE\":\"Por favor, nos envie seu feedback\",\n  \"PROPERTY.ASSIGNMENT.TITLE\":\"Atribuição\",\n  \"PROPERTY.ASSIGNMENT.TYPE\":\"Tipo\",\n  \"PROPERTY.ASSIGNMENT.TYPE.IDENTITYSTORE\":\"Identidades\",\n  \"PROPERTY.ASSIGNMENT.TYPE.STATIC\":\"Valores fixos\",\n  \"PROPERTY.ASSIGNMENT.ASSIGNEE\":\"Responsável\",\n  \"PROPERTY.ASSIGNMENT.MATCHING\":\"Use &uparrow; e &downarrow; para selecionar e pressione Enter para confirmar ou use o mouse\",\n  \"PROPERTY.ASSIGNMENT.ASSIGNEE_PLACEHOLDER\":\"Insira um candidato\",\n  \"PROPERTY.ASSIGNMENT.EMPTY\":\"Nenhuma atribuição selecionada\",\n  \"PROPERTY.ASSIGNMENT.ASSIGNEE_DISPLAY\":\"Designado {{assignee}}\",\n  \"PROPERTY.ASSIGNMENT.CANDIDATE_USERS_DISPLAY\":\"{{length}} Usuários candidatos\",\n  \"PROPERTY.ASSIGNMENT.CANDIDATE_USERS\":\"Usuários candidatos\",\n  \"PROPERTY.ASSIGNMENT.CANDIDATE_GROUPS_DISPLAY\":\"{{length}} Grupos candidatos\",\n  \"PROPERTY.ASSIGNMENT.CANDIDATE_GROUPS\":\"Grupos de candidatos\",\n  \"PROPERTY.ASSIGNMENT.USER_IDM_DISPLAY\":\"Usuário {{firstName}} {{lastName}}\",\n  \"PROPERTY.ASSIGNMENT.USER_IDM_EMAIL_DISPLAY\":\"Usuário {{email}}\",\n  \"PROPERTY.ASSIGNMENT.USER_IDM_FIELD_DISPLAY\":\"Campo {{name}}\",\n  \"PROPERTY.ASSIGNMENT.IDM_EMPTY\":\"Iniciador do processo\",\n  \"PROPERTY.ASSIGNMENT.IDM.TYPE\":\"Atribuição\",\n  \"PROPERTY.ASSIGNMENT.IDM.NO_CANDIDATE_USERS\":\"Nenhum usuário candidato selecionado...\",\n  \"PROPERTY.ASSIGNMENT.IDM.NO_CANDIDATE_GROUPS\":\"Nenhum grupo candidato selecionados...\",\n  \"PROPERTY.ASSIGNMENT.IDM.DROPDOWN.INITIATOR\":\"Atribuído ao iniciador do processo\",\n  \"PROPERTY.ASSIGNMENT.IDM.DROPDOWN.USER\":\"Atribuído a um único usuário\",\n  \"PROPERTY.ASSIGNMENT.IDM.DROPDOWN.USERS\":\"Usuários candidatos\",\n  \"PROPERTY.ASSIGNMENT.IDM.DROPDOWN.GROUPS\":\"Grupos de candidatos\",\n  \"PROPERTY.ASSIGNMENT.INITIATOR-CAN-COMPLETE\":\"Permitir que o iniciador do processo complete a tarefa\",\n  \"PROPERTY.EXECUTIONLISTENERS.DISPLAY\":\"{{length}} ouvintes da execução\",\n  \"PROPERTY.EXECUTIONLISTENERS.EMPTY\":\"Nenhum ouvinte de execução configurado\",\n  \"PROPERTY.EXECUTIONLISTENERS.EVENT\":\"Evento\",\n  \"PROPERTY.EXECUTIONLISTENERS.CLASS\":\"Classe\",\n  \"PROPERTY.EXECUTIONLISTENERS.CLASS.PLACEHOLDER\":\"Digite um nome de classe\",\n  \"PROPERTY.EXECUTIONLISTENERS.EXPRESSION\":\"Expressão\",\n  \"PROPERTY.EXECUTIONLISTENERS.EXPRESSION.PLACEHOLDER\":\"Insira uma expressão\",\n  \"PROPERTY.EXECUTIONLISTENERS.DELEGATEEXPRESSION\":\"Expressão de atribuição\",\n  \"PROPERTY.EXECUTIONLISTENERS.DELEGATEEXPRESSION.PLACEHOLDER\":\"Insira uma expressão de atribuição\",\n  \"PROPERTY.EXECUTIONLISTENERS.UNSELECTED\":\"Nenhum ouvinte de execução selecionado\",\n  \"PROPERTY.EXECUTIONLISTENERS.FIELDS.NAME\":\"Nome\",\n  \"PROPERTY.EXECUTIONLISTENERS.FIELDS.NAME.PLACEHOLDER\":\"Digite um nome\",\n  \"PROPERTY.EXECUTIONLISTENERS.FIELDS.EXPRESSION\":\"Expressão\",\n  \"PROPERTY.EXECUTIONLISTENERS.FIELDS.EXPRESSION.PLACEHOLDER\":\"Insira uma expressão\",\n  \"PROPERTY.EXECUTIONLISTENERS.FIELDS.STRINGVALUE\":\"Valor da string\",\n  \"PROPERTY.EXECUTIONLISTENERS.FIELDS.STRINGVALUE.PLACEHOLDER\":\"Insira um valor da string\",\n  \"PROPERTY.EXECUTIONLISTENERS.FIELDS.STRING\":\"String\",\n  \"PROPERTY.EXECUTIONLISTENERS.FIELDS.STRING.PLACEHOLDER\":\"Entre com o texto\",\n  \"PROPERTY.EXECUTIONLISTENERS.FIELDS.IMPLEMENTATION\":\"Implementação\",\n  \"PROPERTY.EXECUTIONLISTENERS.FIELDS.EMPTY\":\"Nenhum campo selecionado\",\n  \"PROPERTY.FIELDS\":\"{{length}} campos\",\n  \"PROPERTY.FIELDS.EMPTY\":\"Nenhum campo selecionado\",\n  \"PROPERTY.ASSIGNMENT.NONE\" : \"Nenhum...\",\n  \"PROPERTY.ASSIGNMENT.PLACEHOLDER-SEARCHUSER\": \"Pesquisar usuário\",\n  \"PROPERTY.ASSIGNMENT.PLACEHOLDER-SEARCHGROUP\": \"Pesquisar grupo\",\n  \"PROPERTY.ASSIGNMENT.SEARCH\": \"Pesquisa: \",\n  \"PROPERTY.FIELDS.NAME\":\"Nome\",\n  \"PROPERTY.FIELDS.NAME.PLACEHOLDER\":\"Digite um nome\",\n  \"PROPERTY.FIELDS.EXPRESSION\":\"Expressão\",\n  \"PROPERTY.FIELDS.EXPRESSION.PLACEHOLDER\":\"Insira uma expressão\",\n  \"PROPERTY.FIELDS.STRINGVALUE\":\"Valor da string\",\n  \"PROPERTY.FIELDS.STRINGVALUE.PLACEHOLDER\":\"Insira um valor da string\",\n  \"PROPERTY.FIELDS.STRING\":\"String\",\n  \"PROPERTY.FIELDS.STRING.PLACEHOLDER\":\"Entre com o texto\",\n  \"PROPERTY.FIELDS.IMPLEMENTATION\":\"Implementação\",\n  \"PROPERTY.FORMPROPERTIES.VALUE\":\"{{length}} propriedades de formulário\",\n  \"PROPERTY.FORMPROPERTIES.EMPTY\":\"Não há propriedades de formulário selecionadas\",\n  \"PROPERTY.FORMPROPERTIES.ID\":\"Id\",\n  \"PROPERTY.FORMPROPERTIES.ID.PLACEHOLDER\":\"Entre com um id\",\n  \"PROPERTY.FORMPROPERTIES.NAME\":\"Nome\",\n  \"PROPERTY.FORMPROPERTIES.NAME.PLACEHOLDER\":\"Digite um nome\",\n  \"PROPERTY.FORMPROPERTIES.TYPE\":\"Tipo\",\n  \"PROPERTY.FORMPROPERTIES.DATEPATTERN\":\"Padrão de data\",\n  \"PROPERTY.FORMPROPERTIES.DATEPATTERN.PLACEHOLDER\":\"Digite um padrão de data\",\n  \"PROPERTY.FORMPROPERTIES.VALUES\":\"Valores\",\n  \"PROPERTY.FORMPROPERTIES.ENUMVALUES.EMPTY\":\"Nenhum valor válido (enum) foi selecionado\",\n  \"PROPERTY.FORMPROPERTIES.VALUES.ID\":\"Id\",\n  \"PROPERTY.FORMPROPERTIES.VALUES.NAME\":\"Nome\",\n  \"PROPERTY.FORMPROPERTIES.VALUES.ID.PLACEHOLDER\":\"Digite o id de um valor\",\n  \"PROPERTY.FORMPROPERTIES.VALUES.NAME.PLACEHOLDER\":\"Digite o nome do valor\",\n  \"PROPERTY.FORMPROPERTIES.EXPRESSION\":\"Expressão\",\n  \"PROPERTY.FORMPROPERTIES.EXPRESSION.PLACEHOLDER\":\"Insira uma expressão\",\n  \"PROPERTY.FORMPROPERTIES.VARIABLE\":\"Variável\",\n  \"PROPERTY.FORMPROPERTIES.VARIABLE.PLACEHOLDER\":\"Insira uma variável\",\n  \"PROPERTY.FORMPROPERTIES.DEFAULT\" : \"default\",\n  \"PROPERTY.FORMPROPERTIES.DEFAULT.PLACEHOLDER\" : \"Insira uma default\",\n  \"PROPERTY.FORMPROPERTIES.REQUIRED\":\"Obrigatório\",\n  \"PROPERTY.FORMPROPERTIES.READABLE\":\"Possibilita Leitura\",\n  \"PROPERTY.FORMPROPERTIES.WRITABLE\":\"Possibilita Escrita\",\n  \"PROPERTY.INPARAMETERS.VALUE\":\"{{length}} parâmetros de entrada\",\n  \"PROPERTY.INPARAMETERS.EMPTY\":\"Nenhum parâmetro de entrada configurado\",\n  \"PROPERTY.OUTPARAMETERS.VALUE\":\"{{length}} parâmetros de saída\",\n  \"PROPERTY.OUTPARAMETERS.EMPTY\":\"Nenhum parâmetro de saída configurado\",\n  \"PROPERTY.PARAMETER.SOURCE\":\"Origem\",\n  \"PROPERTY.PARAMETER.SOURCE.PLACEHOLDER\":\"Insira uma origem\",\n  \"PROPERTY.PARAMETER.SOURCEEXPRESSION\":\"Expressão de origem\",\n  \"PROPERTY.PARAMETER.SOURCEEXPRESSION.PLACEHOLDER\":\"Insira uma expressão de origem\",\n  \"PROPERTY.PARAMETER.TARGET\":\"Destino\",\n  \"PROPERTY.PARAMETER.TARGET.PLACEHOLDER\":\"Insira um destino\",\n  \"PROPERTY.PARAMETER.EMPTY\":\"Nenhum parâmetro selecionado\",\n  \"PROPERTY.SUBPROCESSREFERENCE.EMPTY\":\"Nenhuma referência selecionada\",\n  \"PROPERTY.SUBPROCESSREFERENCE.TITLE\":\"Referência de subprocesso recolhida\",\n  \"PROPERTY.SUBPROCESSREFERENCE.ERROR.SUBPROCESS\":\"Houve um erro ao carregar os subprocessos. Tente novamente mais tarde\",\n  \"PROPERTY.SUBPROCESSREFERENCE.SUBPROCESS.LOADING\":\"Carregando subprocessos...\",\n  \"PROPERTY.SUBPROCESSREFERENCE.SUBPROCESS.EMPTY\":\"Esta pasta não contém subprocessos\",\n  \"PROPERTY.FORMREFERENCE.EMPTY\":\"Nenhuma referência selecionada\",\n  \"PROPERTY.FORMREFERENCE.TITLE\":\"Formulário de referência\",\n  \"PROPERTY.FORMREFERENCE.DESCRIPTION\":\"Referência a um formulário\",\n  \"PROPERTY.FORMREFERENCE.ERROR.FORM\":\"Houve um erro ao carregar o formulário. Tente novamente mais tarde\",\n  \"PROPERTY.FORMREFERENCE.FORM.LOADING\":\"Carregando formulários...\",\n  \"PROPERTY.FORMREFERENCE.FORM.EMPTY\":\"Esta pasta não contém formulários\",\n  \"PROPERTY.TASKLISTENERS.VALUE\":\"{{length}} ouvintes de tarefa\",\n  \"PROPERTY.TASKLISTENERS.EMPTY\":\"Nenhum ouvintes tarefa configurado\",\n  \"PROPERTY.TASKLISTENERS.EVENT\":\"Evento\",\n  \"PROPERTY.TASKLISTENERS.CLASS\":\"Classe\",\n  \"PROPERTY.TASKLISTENERS.CLASS.PLACEHOLDER\":\"Digite um nome de classe\",\n  \"PROPERTY.TASKLISTENERS.EXPRESSION\":\"Expressão\",\n  \"PROPERTY.TASKLISTENERS.EXPRESSION.PLACEHOLDER\":\"Insira uma expressão\",\n  \"PROPERTY.TASKLISTENERS.DELEGATEEXPRESSION\":\"Expressão de atribuição\",\n  \"PROPERTY.TASKLISTENERS.DELEGATEEXPRESSION.PLACEHOLDER\":\"Insira uma expressão de atribuição\",\n  \"PROPERTY.TASKLISTENERS.UNSELECTED\":\"Nenhum ouvinte de tarefas selecionado\",\n  \"PROPERTY.TASKLISTENERS.FIELDS.NAME\":\"Nome\",\n  \"PROPERTY.TASKLISTENERS.FIELDS.NAME.PLACEHOLDER\":\"Digite um nome\",\n  \"PROPERTY.TASKLISTENERS.FIELDS.EXPRESSION\":\"Expressão\",\n  \"PROPERTY.TASKLISTENERS.FIELDS.EXPRESSION.PLACEHOLDER\":\"Insira uma expressão\",\n  \"PROPERTY.TASKLISTENERS.FIELDS.STRINGVALUE\":\"Valor da string\",\n  \"PROPERTY.TASKLISTENERS.FIELDS.STRINGVALUE.PLACEHOLDER\":\"Insira um valor da string\",\n  \"PROPERTY.TASKLISTENERS.FIELDS.STRING\":\"String\",\n  \"PROPERTY.TASKLISTENERS.FIELDS.STRING.PLACEHOLDER\":\"Entre com o texto\",\n  \"PROPERTY.TASKLISTENERS.FIELDS.IMPLEMENTATION\":\"Implementação\",\n  \"PROPERTY.TASKLISTENERS.FIELDS.EMPTY\":\"Nenhum campo selecionado\",\n  \"PROPERTY.EVENTLISTENERS.DISPLAY\":\"{{length}} ouvintes de evento\",\n  \"PROPERTY.EVENTLISTENERS.EMPTY\":\"Nenhum ouvintes de evento configurado\",\n  \"PROPERTY.EVENTLISTENERS.EVENTS\":\"Eventos\",\n  \"PROPERTY.EVENTLISTENERS.RETHROW\":\"Relançar o evento?\",\n  \"PROPERTY.EVENTLISTENERS.CLASS\":\"Classe\",\n  \"PROPERTY.EVENTLISTENERS.CLASS.PLACEHOLDER\":\"Digite um nome de classe\",\n  \"PROPERTY.EVENTLISTENERS.DELEGATEEXPRESSION\":\"Expressão de atribuição\",\n  \"PROPERTY.EVENTLISTENERS.DELEGATEEXPRESSION.PLACEHOLDER\":\"Insira uma expressão de atribuição\",\n  \"PROPERTY.EVENTLISTENERS.ENTITYTYPE\":\"Tipo de entidade\",\n  \"PROPERTY.EVENTLISTENERS.ENTITYTYPE.PLACEHOLDER\":\"Entre com um tipo de entidade\",\n  \"PROPERTY.EVENTLISTENERS.RETHROWTYPE\":\"Relançar o tipo de evento\",\n  \"PROPERTY.EVENTLISTENERS.ERRORCODE\":\"Código de erro\",\n  \"PROPERTY.EVENTLISTENERS.ERRORCODE.PLACEHOLDER\":\"Entre com um código de erro\",\n  \"PROPERTY.EVENTLISTENERS.MESSAGENAME\":\"Nome da mensagem\",\n  \"PROPERTY.EVENTLISTENERS.MESSAGENAME.PLACEHOLDER\":\"Entre com um nome de mensagem\",\n  \"PROPERTY.EVENTLISTENERS.SIGNALNAME\":\"Nome do sinal\",\n  \"PROPERTY.EVENTLISTENERS.SIGNALNAME.PLACEHOLDER\":\"Entre com o nome do sinal\",\n  \"PROPERTY.EVENTLISTENERS.UNSELECTED\":\"Nenhum ouvinte de evento selecionado\",\n  \"PROPERTY.PLANITEMLIFECYCLELISTENERS.VALUE\" : \"{{length}} lifecycle listeners\",\n  \"PROPERTY.PLANITEMLIFECYCLELISTENERS.EMPTY\" : \"No lifecycle listeners configured\",\n  \"PROPERTY.PLANITEMLIFECYCLELISTENERS.EVENT\" : \"Event\",\n  \"PROPERTY.PLANITEMLIFECYCLELISTENERS.SOURCE_STATE\" : \"Source state\",\n  \"PROPERTY.PLANITEMLIFECYCLELISTENERS.TARGET_STATE\" : \"Target state\",\n  \"PROPERTY.PLANITEMLIFECYCLELISTENERS.CLASS\" : \"Class\",\n  \"PROPERTY.PLANITEMLIFECYCLELISTENERS.CLASS.PLACEHOLDER\" : \"Enter a classname\",\n  \"PROPERTY.PLANITEMLIFECYCLELISTENERS.EXPRESSION\" : \"Expression\",\n  \"PROPERTY.PLANITEMLIFECYCLELISTENERS.EXPRESSION.PLACEHOLDER\" : \"Enter an expression\",\n  \"PROPERTY.PLANITEMLIFECYCLELISTENERS.DELEGATEEXPRESSION\" : \"Delegate expression\",\n  \"PROPERTY.PLANITEMLIFECYCLELISTENERS.DELEGATEEXPRESSION.PLACEHOLDER\" : \"Enter a delegate expression\",\n  \"PROPERTY.PLANITEMLIFECYCLELISTENERS.UNSELECTED\" : \"No task listener selected\",\n  \"PROPERTY.PLANITEMLIFECYCLELISTENERS.FIELDS.NAME\" : \"Name\",\n  \"PROPERTY.PLANITEMLIFECYCLELISTENERS.FIELDS.NAME.PLACEHOLDER\" : \"Enter a name\",\n  \"PROPERTY.PLANITEMLIFECYCLELISTENERS.FIELDS.EXPRESSION\" : \"Expression\",\n  \"PROPERTY.PLANITEMLIFECYCLELISTENERS.FIELDS.EXPRESSION.PLACEHOLDER\" : \"Enter an expression\",\n  \"PROPERTY.PLANITEMLIFECYCLELISTENERS.FIELDS.STRINGVALUE\" : \"String value\",\n  \"PROPERTY.PLANITEMLIFECYCLELISTENERS.FIELDS.STRINGVALUE.PLACEHOLDER\" : \"Enter a string value\",\n  \"PROPERTY.PLANITEMLIFECYCLELISTENERS.FIELDS.STRING\" : \"String\",\n  \"PROPERTY.PLANITEMLIFECYCLELISTENERS.FIELDS.STRING.PLACEHOLDER\" : \"Enter a string\",\n  \"PROPERTY.PLANITEMLIFECYCLELISTENERS.FIELDS.IMPLEMENTATION\" : \"Implementation\",\n  \"PROPERTY.PLANITEMLIFECYCLELISTENERS.FIELDS.EMPTY\" : \"No Field selected\",\n  \"PROPERTY.SIGNALDEFINITIONS.DISPLAY\":\"{{length}} definições de sinal\",\n  \"PROPERTY.SIGNALDEFINITIONS.EMPTY\":\"Nenhuma definição de sinal configurada\",\n  \"PROPERTY.SIGNALDEFINITIONS.SCOPE-GLOBAL\":\"Global\",\n  \"PROPERTY.SIGNALDEFINITIONS.SCOPE-PROCESSINSTANCE\":\"Instâncias de processos\",\n  \"PROPERTY.SIGNALDEFINITIONS.ID\":\"Id\",\n  \"PROPERTY.SIGNALDEFINITIONS.NAME\":\"Nome\",\n  \"PROPERTY.SIGNALDEFINITIONS.SCOPE\":\"Escopo\",\n  \"PROPERTY.MESSAGEDEFINITIONS.DISPLAY\":\"{{length}} definições de mensagem\",\n  \"PROPERTY.MESSAGEDEFINITIONS.EMPTY\":\"Nenhuma definição de mensagem configurada\",\n  \"PROPERTY.MESSAGEDEFINITIONS.ID\":\"Id\",\n  \"PROPERTY.MESSAGEDEFINITIONS.NAME\":\"Nome\",\n  \"PROPERTY.SEQUENCEFLOW.ORDER.EMPTY\":\"Nenhuma ordem de fluxo de sequência determinada\",\n  \"PROPERTY.SEQUENCEFLOW.ORDER.NOT.EMPTY\":\"Conjunto de ordem de fluxo de sequência\",\n  \"PROPERTY.SEQUENCEFLOW.ORDER.NO.OUTGOING.SEQUENCEFLOW.FOUND\":\"Não foi encontrado nenhum fluxo de sequência de saída.\",\n  \"PROPERTY.SEQUENCEFLOW.ORDER.DESCRIPTION\":\"Defina a ordem em que o fluxo de sequência precisa ser analisado:\",\n  \"PROPERTY.SEQUENCEFLOW.ORDER.SEQUENCEFLOW.VALUE\":\"Fluxo de sequência para {{targetType}} {{targetTitle}}\",\n  \"PROPERTY.SEQUENCEFLOW.CONDITION.TITLE\":\"Condição de fluxo de sequência\",\n  \"PROPERTY.SEQUENCEFLOW.CONDITION.STATIC\":\"Expressão de condição\",\n  \"PROPERTY.SEQUENCEFLOW.CONDITION.NO-CONDITION-DISPLAY\":\"Nenhum conjunto de condição\",\n  \"PROPERTY.DUEDATE.EMPTY\":\"Sem data de vencimento\",\n  \"PROPERTY.DUEDATE.DEFINED\":\"Data de vencimento definida\",\n  \"PROPERTY.DUEDATE.TITLE\":\"Data de vencimento\",\n  \"PROPERTY.DUEDATE.EXPRESSION-LABEL\":\"Expressões de data de vencimento\",\n  \"PROPERTY.DUEDATE.TASK-DUE-DATE-OPTIONS.NO-DUEDATE\":\"Sem data de vencimento\",\n  \"PROPERTY.DUEDATE.TASK-DUE-DATE-OPTIONS.EXPRESSION\":\"Definição de expressão\",\n  \"PROPERTY.DUEDATE.TASK-DUE-DATE-OPTIONS.STATIC\":\"Duração fixa após a criação da tarefa\",\n  \"PROPERTY.DUEDATE.TASK-DUE-DATE-OPTIONS.FIELD\":\"Com base no campo\",\n  \"MODEL.SAVE.TITLE\":\"Salvar modelo\",\n  \"MODEL.VALIDATE.TITLE\":\"Resultados de validação\",\n  \"MODEL.NAME\":\"Nome\",\n  \"MODEL.KEY\":\"Chave\",\n  \"MODEL.DESCRIPTION\":\"Descrição\",\n  \"MODEL.SAVE.NEWVERSION\":\"Salvar como uma nova versão?  Isto significa que você pode sempre voltar para uma versão anterior\",\n  \"MODEL.SAVE.COMMENT\":\"Comentário\",\n  \"MODEL.SAVE.SAVING\":\"Salvando modelo\",\n  \"MODEL.LASTMODIFIEDDATE\":\"Salvo pela última vez em\",\n  \"MODEL.SAVE.ERROR\":\"Erro inesperado: não foi possível salvar o modelo\",\n  \"MODEL.VALIDATIONERRORS\":\"Observe que o modelo contem erros de validação. Isto significa que o modelo não pode ser implantado no motor Flowable em seu estado atual.\",\n  \"MODEL.CONFLICT.WRITE\":\"Não foi possível salvar modelo: '{{userFullName}}' há mudanças para este modelo\",\n  \"MODEL.CONFLICT.WRITE.OPTIONS\":\"Selecione uma opção para resolver este conflito:\",\n  \"MODEL.CONFLICT.WRITE.OPTION.OVERWRITE\":\"Substituir outro modelo\",\n  \"MODEL.CONFLICT.WRITE.OPTION.DISCARDCHANGES\":\"Descartar minhas alterações\",\n  \"MODEL.CONFLICT.WRITE.OPTION.SAVEAS\":\"Salvar como novo modelo\",\n  \"MODEL.CONFLICT.WRITE.OPTION.NEWVERSION\":\"Criar uma nova versão\",\n  \"MODEL.CONFLICT.SAVEAS\":\"Salvar como:\",\n  \"EVENT_TYPE.ACTIVITY.COMPENSATE.TOOLTIP\":\"Uma atividade está prestes a ser executado como uma compensação para outra atividade. O evento destina-se a atividade que está prestes a ser executado para compensação\",\n  \"EVENT_TYPE.ACTIVITY.COMPLETED.TOOLTIP\":\"Uma atividade foi concluída com sucesso\",\n  \"EVENT_TYPE.ACTIVITY.ERROR.RECEIVED.TOOLTIP\":\"Uma atividade recebeu um evento de erro. Expedido antes que o erro real tenha sido recebido pela atividade\",\n  \"EVENT_TYPE.MEMBERSHIP.CREATED.TOOLTIP\":\"Um nova subscrição foi criada\",\n  \"EVENT_TYPE.MEMBERSHIP.DELETED.TOOLTIP\":\"Um único subscrição foi removida\",\n  \"EVENT_TYPE.MEMBERSHIPS.DELETED.TOOLTIP\":\"Todas as subscrições no grupo relacionado foram excluídas. Nenhum evento individual será despachados por razões de desempenho\",\n  \"EVENT_TYPE.TASK.ASSIGNED.TOOLTIP\":\"Uma tarefa foi atribuída. Isto é lançado como um evento ENTITY_UPDATED\",\n  \"EVENT_TYPE.TASK.COMPLETED.TOOLTIP\":\"Uma tarefa foi concluída. Expedida antes da entidade tarefa ser excluída\",\n  \"EVENT_TYPE.UNCAUGHT.BPMNERROR.TOOLTIP\":\"Quando um erro de BPMN foi acionado, mas não foi detectado dentro do processo\",\n  \"EVENT_TYPE.VARIABLE.CREATED.TOOLTIP\":\"Foi criada uma nova variável\",\n  \"EVENT_TYPE.VARIABLE.DELETED.TOOLTIP\":\"Uma variável existente foi excluída\",\n  \"EVENT_TYPE.VARIABLE.UPDATED.TOOLTIP\":\"Uma variável existente foi atualizada\",\n  \"PROPERTY.DECISIONTABLEREFERENCE.EMPTY\":\"Nenhuma referência selecionada\",\n  \"PROPERTY.DECISIONTABLEREFERENCE.TITLE\":\"Referência de tabela de decisão\",\n  \"PROPERTY.DECISIONTABLEREFERENCE.ERROR.FORM\":\"Houve um erro ao carregar as tabelas de decisão. Tente novamente mais tarde\",\n  \"PROPERTY.DECISIONTABLEREFERENCE.DECISIONTABLE.LOADING\":\"Carregando tabelas de decisão...\",\n  \"PROPERTY.DECISIONTABLEREFERENCE.DECISIONTABLE.EMPTY\":\"Esta pasta não contém tabelas de decisão\"\n}\n"
  },
  {
    "path": "flowable-ui-web/modeler/i18n/zh-CN.json",
    "content": "{\n    \"GENERAL\" : {\n        \"MAIN-TITLE\": \"Flowable编辑器\",\n        \"NAVIGATION\" : {\n            \"PROCESSES\": \"流程\",\n            \"CASEMODELS\": \"案例模型\",\n            \"FORMS\": \"表单\",\n            \"DECISION-TABLES\": \"决策表\",\n            \"APPS\": \"应用程序\"\n        },\n        \"TITLE\": {\n            \"SELECT-GROUP\" :\"选择组\",\n            \"MATCHING-GROUPS\": \"匹配组\",\n            \"FILTER\": \"过滤\",\n            \"HISTORY\": \"历史\"\n        },\n        \"ACTION\": {\n            \"LOGOUT\": \"退出\",\n            \"RETURN-TO-LIST\": \"显示所有定义\",\n            \"CANCEL\": \"取消\",\n            \"CLOSE\": \"关闭\",\n            \"EDIT\": \"编辑\",\n            \"SAVE\": \"保存\",\n            \"OPEN\": \"打开\",\n            \"OK\": \"Ok\",\n            \"CONFIRM\": \"确认\",\n            \"CONFIRM-AND-CLOSE\": \"确认并且关闭\",\n            \"NEW-FORM\": \"新表单\",\n            \"CREATE-FORM\": \"创建表单\",\n            \"NEW-DECISION-TABLE\": \"新决策表\",\n            \"CREATE-DECISION-TABLE\": \"创建决策表\"\n        },\n        \"MESSAGE\": {\n          \"SELECT-GROUP-HELP\": \"使用 &uparrow; 和 &downarrow; 选择并按回车确认\",\n          \"PEOPLE-NO-MATCHING-RESULTS\": \"没有找到匹配的用户\",\n          \"GROUP-NO-MATCHING-RESULTS\": \"没有找到匹配的组\",\n          \"GROUP-SOURCE-TYPE\": \"组源\",\n          \"GROUP-SOURCE-SEARCH-OPTION\": \"组搜索\",\n          \"GROUP-SOURCE-FIELD-OPTION\": \"表单字段\"\n        }\n    },\n\n    \"EDITOR\": {\n      \"POPUP\": {\n        \"UNSAVED-CHANGES\": {\n          \"TITLE\": \"您有未保存的更改\",\n          \"DESCRIPTION\": \"您想如何处理未保存的更改?\",\n          \"ACTION\": {\n            \"SAVE\": \"保存更改\",\n            \"DISCARD\": \"放弃更改\",\n            \"CONTINUE\": \"继续编辑\"\n          }\n        }\n      }\n    },\n\n    \"PROCESS-LIST\" : {\n        \"TITLE\" : \"业务流程模型\",\n        \"SEARCH-PLACEHOLDER\": \"搜索\",\n        \"ACTION\" : {\n            \"CREATE\": \"创建流程\",\n            \"IMPORT\": \"导入流程\"\n        },\n\n        \"FILTER\" : {\n            \"PROCESSES\": \"流程模型\",\n            \"PROCESSES-COUNT\": \"一共有 {{total}}个流程模型\",\n            \"PROCESSES-ONE\": \"有一个流程模型\",\n            \"PROCESSES-EMPTY\": \"目前还没有创建流程模型。您可以设计流程模型、用户表单，然后将它们捆绑到app中。第一步是创建流程模型:\",\n            \"PROCESSES-BPMN-HINT\": \"使用BPMN可视化编辑器创建BPMN模型.\",\n            \"PROCESSES-BPMN-IMPORT-HINT\": \"还可以导入现有的BPMN模型。\",\n            \"FILTER-TEXT\": \", 匹配 \\\"{{filterText}}\\\"\",\n            \"FILTER-TEXT-EMPTY\": \"没有匹配到流程模型 \\\"{{filterText}}\\\"\",\n            \"RECENT\": \"最近\",\n            \"RECENT-COUNT\": \"{{total}} 最近使用的模型\",\n            \"RECENT-ONE\": \"最近使用的模型\",\n            \"RECENT-EMPTY\": \"最近没有使用模型\"\n        },\n\n        \"SORT\": {\n            \"MODIFIED-ASC\": \"按照修改时间升序\",\n            \"MODIFIED-DESC\": \"按照修改时间降序\",\n            \"NAME-ASC\": \"按照名称升序\",\n            \"NAME-DESC\": \"按照名称降序\"\n        }\n    },\n    \n    \"CASE-LIST\" : {\n        \"TITLE\" : \"案例模型\",\n        \"SEARCH-PLACEHOLDER\": \"搜索\",\n        \"ACTION\" : {\n            \"CREATE\": \"创建案例\",\n            \"IMPORT\": \"导入案例\"\n        },\n\n        \"FILTER\" : {\n            \"CASES\": \"案例模型\",\n            \"CASES-COUNT\": \"一共有 {{total}}个案例模型\",\n            \"CASES-ONE\": \"有一个case模型\",\n            \"CASES-EMPTY\": \"目前还没有创建案例模型。您可以设计实例模型、用户表单，然后将它们捆绑到app应用程序定义中。第一步是创建一个案例模型。:\",\n            \"CASES-CMMN-HINT\": \"使用CMMN可视化编辑器创建CMMN模型.\",\n            \"CASES-CMMN-IMPORT-HINT\": \"还可以导入现有CMMN模型。\",\n            \"FILTER-TEXT\": \", 匹配 \\\"{{filterText}}\\\"\",\n            \"FILTER-TEXT-EMPTY\": \"没有匹配到case模型 \\\"{{filterText}}\\\"\",\n            \"RECENT\": \"最近\",\n            \"RECENT-COUNT\": \"{{total}} 最近使用的模型\",\n            \"RECENT-ONE\": \"最近使用的模型\",\n            \"RECENT-EMPTY\": \"最近没有使用模型\"\n        },\n\n        \"SORT\": {\n            \"MODIFIED-ASC\": \"按照修改时间升序\",\n            \"MODIFIED-DESC\": \"按照修改时间降序\",\n            \"NAME-ASC\": \"按照名称升序\",\n            \"NAME-DESC\": \"按照名称降序\"\n        }\n    },\n\n    \"FORMS-LIST\" : {\n        \"TITLE\" : \"表单\",\n        \"SEARCH-PLACEHOLDER\": \"搜索\",\n        \"ACTION\" : {\n            \"CREATE\": \"创建表单\",\n            \"CREATE-INLINE\": \"现在创建一个新表单!\",\n            \"SHOW-MORE\": \"显示更多...\"\n        },\n\n        \"FILTER\" : {\n            \"FORMS\": \"表单\",\n            \"FORMS-COUNT\": \"一共有{{total}} 个表单\",\n            \"FORMS-ONE\": \"有一个表单\",\n            \"FORMS-EMPTY\": \"没有表单。若要添加一个，请单击创建表单 \",\n            \"FILTER-TEXT\": \", 匹配 \\\"{{filterText}}\\\"\",\n            \"FILTER-TEXT-EMPTY\": \"没有匹配到表单 \\\"{{filterText}}\\\"\"\n        },\n\n        \"SORT\": {\n            \"MODIFIED-ASC\": \"按照修改时间升序\",\n            \"MODIFIED-DESC\": \"按照修改时间降序\",\n            \"NAME-ASC\": \"按照名称升序\",\n            \"NAME-DESC\": \"按照名称降序\"\n        }\n    },\n\n    \"DECISION-TABLES-LIST\": {\n        \"TITLE\": \"决策表\",\n        \"SEARCH-PLACEHOLDER\": \"搜索\",\n        \"ACTION\": {\n            \"CREATE\": \"创建决策表\",\n            \"IMPORT\": \"导入决策表\",\n            \"CREATE-INLINE\": \"现在创建一个新的决策表!\",\n            \"SHOW-MORE\": \"显示更多...\"\n        },\n\n        \"FILTER\": {\n            \"DECISION-TABLES\": \"决策表\",\n            \"DECISION-TABLES-COUNT\": \"一共有 {{total}} 个决策表\",\n            \"DECISION-TABLES-ONE\": \"有一个决策表\",\n            \"DECISION-TABLES-EMPTY\": \"没有决策表。若要添加一个，请单击创建决策表 \",\n            \"FILTER-TEXT\": \", 匹配 \\\"{{filterText}}\\\"\",\n            \"FILTER-TEXT-EMPTY\": \"没有匹配到决策表 \\\"{{filterText}}\\\"\"\n        },\n\n        \"SORT\": {\n            \"MODIFIED-ASC\": \"按照修改时间升序\",\n            \"MODIFIED-DESC\": \"按照修改时间降序\",\n            \"NAME-ASC\": \"按照名称升序\",\n            \"NAME-DESC\": \"按照名称降序\"\n        }\n    },\n\n    \"APPS-LIST\" : {\n        \"TITLE\" : \"应用程序定义\",\n        \"SEARCH-PLACEHOLDER\": \"搜索\",\n        \"ACTION\" : {\n            \"CREATE\": \"创建应用程序\",\n            \"IMPORT\": \"导入应用程序\",\n            \"SHOW-MORE\": \"显示更多...\"\n        },\n\n        \"FILTER\" : {\n            \"APPS\": \"应用程序定义\",\n            \"APPS-COUNT\": \"一共有 {{total}}个应用程序定义\",\n            \"APPS-ONE\": \"有一个app定义\",\n            \"APPS-EMPTY\": \"没有应用程序定义。若要添加一个，请单击创建应用程序定义\",\n            \"FILTER-TEXT\": \", 匹配 \\\"{{filterText}}\\\"\",\n            \"FILTER-TEXT-EMPTY\": \"没有匹配到应用程序定义  \\\"{{filterText}}\\\"\",\n\n            \"NO-APPS\": \" 您可以通过发布一批流程模型来创建应用程序定义\",\n            \"NO-APPS-CALL-TO-ACTION\": \"现在可以创建一个应用程序定义 \",\n            \"NO-APPS-NOTE\": \"当你准备好使用它时，记得要发布它。\"\n        },\n\n        \"SORT\": {\n            \"MODIFIED-ASC\": \"按照修改时间升序\",\n            \"MODIFIED-DESC\": \"按照修改时间降序\",\n            \"NAME-ASC\": \"按照名称升序\",\n            \"NAME-DESC\": \"按照名称降序\"\n        }\n    },\n    \"PROCESS\": {\n      \"NAME\": \"模型名称\",\n      \"KEY\": \"模型key\",\n      \"DESCRIPTION\": \"描述\",\n      \"VERSION-COMMENT\": \"版本注释\",\n      \"ACTION\": {\n            \"DETAILS\": \"显示详细信息\",\n            \"EDIT\": \"修改模型属性\",\n            \"DUPLICATE\": \"复制这个模型\",\n            \"EXPORT_BPMN20\": \"导出到BPMN2\",\n            \"DELETE\": \"删除这个模型\",\n            \"CREATE-CONFIRM\": \"创建新模型\",\n            \"DUPLICATE-CONFIRM\": \"复制这个模型\",\n            \"OPEN-IN-EDITOR\": \"可视化编辑器\",\n            \"EDIT-CONFIRM\": \"保存\",\n            \"DELETE-CONFIRM\": \"删除流程模型\",\n            \"USE-AS-NEW-VERSION\": \"作为新版本使用\",\n            \"FAVORITE\": \"喜欢这个模型\"\n\n        },\n        \"DETAILS\": {\n          \"HISTORY-TITLE\": \"历史\",\n          \"LAST-UPDATED-BY\": \"最后被{{lastUpdatedBy}} - {{lastUpdated | dateformat}}更新\",\n          \"CREATED-BY\": \"被{{createdBy}}创建\",\n          \"NO-DESCRIPTION\": \"这个模型没有描述信息，可以通过修改模型来添加一个描述\"\n        },\n\n        \"POPUP\": {\n          \"CREATE-TITLE\": \"创建一个新的业务流程模型\",\n          \"DUPLICATE-TITLE\": \"复制这个业务流程模型\",\n          \"CREATE-DESCRIPTION\": \"您需要为新模型命名，并且您可以在这个操作中添加描述信息。\",\n          \"DUPLICATE-DESCRIPTION\": \"您可以更改新模型的名称，并且此时您可以更改描述信息。\",\n          \"EDIT-DESCRIPTION\": \"更改下面的任何模型属性，然后按下保存去更新模型。\",\n          \"DELETE-DESCRIPTION\": \"确实要删除进程模型吗？ \\\"{{name}}\\\"?\",\n          \"EDIT-TITLE\":\"编辑模型详细信息\",\n          \"DELETE-TITLE\": \"删除模型\",\n          \"DELETE-LOADING-RELATIONS\": \"检查模型使用...\",\n          \"DELETE-RELATIONS-DESCRIPTION-SINGLE\": \"无法删除此模型，因为另一个模型正在使用它:\",\n          \"DELETE-RELATIONS-DESCRIPTION\": \"无法删除此模型，因为另一个模型正在使用它:\",\n          \"DELETE-PROCESS-RELATION\": \"流程模型\",\n          \"DELETE-FORM-RELATION\": \"表单模型\",\n          \"DELETE-APP-RELATION\": \"App模型\",\n          \"IMPORT-DESCRIPTION\": \"请浏览或拖拽.bpmn或.bpmn20.xml扩展名的BPMN XML定义\",\n          \"IMPORT-TITLE\": \"导入一个流程模型\",\n          \"USE-AS-NEW-TITLE\": \"作为一个新版本使用\",\n          \"USE-AS-NEW-DESCRIPTION\": \"您确定要使用 {{version}}版本 去创建一个关于 \\\"{{name}}\\\"的新版本?\",\n          \"USE-AS-NEW-UNRESOLVED-MODELS-ERROR\": \"无法完全恢复app模型到所选择的版本：由于一些引用的模型过去被删除而丢失。请相应地更新app模型。缺失模型:\",\n          \"USE-AS-NEW-UNRESOLVED-MODEL\": \"模型 '{{name}}' 内部id {{id}}, 被 {{createdBy}}创建\",\n          \"SHARED-WITH\": \"分享\",\n          \"PERMISSION\": \"许可\",\n          \"ACTIONS\": \"动作\",\n          \"IMPORT\": {\n              \"DROPZONE\": \"拖拽一个 .bpmn 或者 .bpmn20.xml BPMN XML 文件\",\n              \"CANCEL-UPLOAD\": \"取消上传\",\n              \"ERROR\": \"处理BPMN XML文件时出错\",\n              \"NO-DROP\": \"不支持拖放\"\n          }\n        },\n        \"ALERT\": {\n          \"EDIT-CONFIRM\": \"模型被更新\"\n        },\n        \"ERROR\": {\n          \"NOT-FOUND\": \"所请求的模型不存在\"\n        }\n    },\n\n    \"SUBPROCESS\": {\n        \"NAME\": \"子流程名称\",\n        \"DESCRIPTION\": \"描述信息\",\n        \"ACTION\": {\n            \"CREATE-CONFIRM\": \"创建一个子流程\"\n        },\n        \"POPUP\": {\n            \"CREATE-TITLE\": \"创建一个新的子流程\",\n            \"CREATE-DESCRIPTION\": \"您需要为新的子流程命名，并且您可能希望同时添加描述。\"\n        }\n    },\n    \n    \"CASE\": {\n      \"NAME\": \"模型名称\",\n      \"KEY\": \"模型key\",\n      \"DESCRIPTION\": \"描述信息\",\n      \"VERSION-COMMENT\": \"版本注释\",\n      \"ACTION\": {\n            \"DETAILS\": \"显示详细信息\",\n            \"EDIT\": \"修改模型属性\",\n            \"DUPLICATE\": \"复制这个模型\",\n            \"EXPORT_CMMN\": \"导出到CMMN1.1\",\n            \"DELETE\": \"删除这个模型\",\n            \"CREATE-CONFIRM\": \"创建新模型\",\n            \"DUPLICATE-CONFIRM\": \"复制这个模型\",\n            \"OPEN-IN-EDITOR\": \"可视化编辑器\",\n            \"EDIT-CONFIRM\": \"保存\",\n            \"DELETE-CONFIRM\": \"删除case模型\",\n            \"USE-AS-NEW-VERSION\": \"作为新版本使用\",\n            \"FAVORITE\": \"喜欢这个模型\"\n        },\n        \"DETAILS\": {\n          \"HISTORY-TITLE\": \"历史\",\n          \"LAST-UPDATED-BY\": \"最后被 {{lastUpdatedBy}} - {{lastUpdated | dateformat}}更新\",\n          \"CREATED-BY\": \"被{{createdBy}}创建\",\n          \"NO-DESCRIPTION\": \"这个模型没有描述信息，可以通过修改模型来添加一个描述\"\n        },\n        \"POPUP\": {\n          \"CREATE-TITLE\": \"创建一个新的案例模型\",\n          \"DUPLICATE-TITLE\": \"复制这个案例模型\",\n          \"CREATE-DESCRIPTION\": \"您需要为新模型命名，并且您可以在这个操作中添加描述信息。\",\n          \"DUPLICATE-DESCRIPTION\": \"您可以更改新模型的名称，并且此时您可以更改描述信息。\",\n          \"EDIT-DESCRIPTION\": \"更改下面的任何模型属性，然后按下保存去更新模型。\",\n          \"DELETE-DESCRIPTION\": \"确实要删除进程流程吗 \\\"{{name}}\\\"?\",\n          \"EDIT-TITLE\":\"编辑模型详细信\",\n          \"DELETE-TITLE\": \"删除模型\",\n          \"DELETE-LOADING-RELATIONS\": \"检查模型使用...\",\n          \"DELETE-RELATIONS-DESCRIPTION-SINGLE\": \"无法删除此模型，因为另一个模型正在使用它:\",\n          \"DELETE-RELATIONS-DESCRIPTION\": \"无法删除此模型，因为另一个模型正在使用它:\",\n          \"DELETE-PROCESS-RELATION\": \"案例模型\",\n          \"DELETE-FORM-RELATION\": \"表单模型\",\n          \"DELETE-APP-RELATION\": \"应用程序模型\",\n          \"IMPORT-DESCRIPTION\": \"请浏览或拖拽.cmmn 或者.cmmn.xml 扩展名的CMMN XML\",\n          \"IMPORT-TITLE\": \"导入一个案例模型\",\n          \"USE-AS-NEW-TITLE\": \"作为一个新版本使用\",\n          \"USE-AS-NEW-DESCRIPTION\": \"您确定要使用 {{version}}版本 去创建一个关于 \\\"{{name}}\\\"的新版本?\",\n          \"USE-AS-NEW-UNRESOLVED-MODELS-ERROR\": \"无法完全恢复app模型到所选择的版本：由于一些引用的模型过去被删除而丢失。请相应地更新应用程序模型。缺失模型:\",\n          \"USE-AS-NEW-UNRESOLVED-MODEL\": \"模型 '{{name}}' 内部id {{id}}, 被 {{createdBy}}创建\",\n          \"SHARED-WITH\": \"分享\",\n          \"PERMISSION\": \"许可\",\n          \"ACTIONS\": \"动作\",\n          \"IMPORT\": {\n              \"DROPZONE\": \"拖拽一个 .cmmn or .cmmn.xml CMMN XML文件\",\n              \"CANCEL-UPLOAD\": \"取消上传\",\n              \"ERROR\": \"处理CMMN XML文件时出错\",\n              \"NO-DROP\": \"不支持拖放\"\n          }\n        },\n        \"ALERT\": {\n          \"EDIT-CONFIRM\": \"模型被更新\"\n        },\n        \"ERROR\": {\n          \"NOT-FOUND\": \"所请求的模型不存在\"\n        }\n    },\n\n    \"FORM\": {\n      \"NAME\": \"表单名称\",\n      \"KEY\": \"表单key\",\n      \"DESCRIPTION\": \"描述\",\n      \"ACTION\": {\n            \"DETAILS\": \"显示详细信息\",\n            \"EDIT\": \"修改模型属性\",\n            \"DELETE\": \"复制这个表单\",\n            \"CREATE-CONFIRM\": \"创建新表单\",\n            \"DUPLICATE\": \"复制这个表单\",\n            \"DUPLICATE-CONFIRM\": \"复制这个表单\",\n            \"OPEN-IN-EDITOR\": \"表单编辑器\",\n            \"EDIT-CONFIRM\": \"保存\",\n            \"DELETE-CONFIRM\": \"删除表单\",\n            \"USE-AS-NEW-VERSION\": \"作为新版本使用\"\n\n        },\n        \"DETAILS\": {\n          \"HISTORY-TITLE\": \"历史\",\n          \"LAST-UPDATED-BY\": \"最后被{{lastUpdatedBy}} - {{lastUpdated | dateformat}}更新\",\n          \"CREATED-BY\": \"被{{createdBy}}创建\"\n        },\n\n        \"POPUP\": {\n          \"CREATE-TITLE\": \"创建一个新的表单\",\n          \"DUPLICATE-TITLE\": \"复制这个表单\",\n          \"CREATE-DESCRIPTION\": \"您需要为新表单命名，并且您可以在这个操作中添加描述信息。\",\n          \"DUPLICATE-DESCRIPTION\": \"您需要为新表单命名，并且您可以在这个操作中添加描述信息。\",\n          \"SAVE-FORM-TITLE\": \"保存表单\",\n          \"EDIT-DESCRIPTION\": \"更改下面的任何模型属性，然后按下保存去更新表单。\",\n          \"DELETE-DESCRIPTION\": \"确实要删除表单 \\\"{{name}}\\\"?\",\n          \"EDIT-TITLE\":\"编辑表单详细信息\",\n          \"DELETE-TITLE\": \"删除表单\",\n          \"USE-AS-NEW-TITLE\": \"作为一个新版本使用\",\n          \"USE-AS-NEW-VERSION\": \"作为一个新版本使用\",\n          \"USE-AS-NEW-DESCRIPTION\": \"您确定要使用 {{version}}版本 去创建一个关于 \\\"{{name}}\\\"的新版本?\",\n          \"USE-AS-NEW-UNRESOLVED-MODELS-ERROR\": \"无法完全恢复app模型到所选择的版本：由于一些引用的模型过去被删除而丢失。请相应地更新app模型。缺失模型:\",\n          \"USE-AS-NEW-UNRESOLVED-MODEL\": \"模型 '{{name}}' 内部id {{id}}, 被 {{createdBy}}创建\"\n        }\n    },\n\n    \"DECISION-TABLE\": {\n        \"NAME\": \"决策表 名称\",\n        \"KEY\": \"决策表 key\",\n        \"DESCRIPTION\": \"描述\",\n        \"VERSION-COMMENT\": \"版本注释\",\n        \"HIT-POLICY\": \"命中策略:\",\n        \"ACTION\": {\n            \"DETAILS\": \"显示详细信息\",\n            \"EDIT\": \"修改模型属性\",\n            \"SHARE\": \"分享决策表\",\n            \"DELETE\": \"删除决策表\",\n            \"ADD-COMMENT\": \"+ 添加评论\",\n            \"CREATE-CONFIRM\": \"创建新的决策表\",\n            \"OPEN-IN-EDITOR\": \"决策表编辑器\",\n            \"EXPORT\": \"Export 决策表\",\n            \"DELETE-CONFIRM\": \"删除决策表\",\n            \"USE-AS-NEW-VERSION\": \"作为新版本使用\",\n            \"FAVORITE\": \"喜欢这个决策表\",\n            \"DUPLICATE\": \"复制这个决策表\"\n        },\n        \"DETAILS\": {\n            \"HISTORY-TITLE\": \"历史\",\n            \"COMMENTS-TITLE\": \"评论\",\n            \"LAST-UPDATED-BY\": \"最后被{{lastUpdatedBy}} - {{lastUpdated | dateformat}}更新\",\n            \"CREATED-BY\": \"被{{createdBy}}创建\"\n        },\n        \"HIT-POLICIES\": {\n            \"FIRST\": \"First\",\n            \"ANY\": \"Any\",\n            \"UNIQUE\": \"Unique\",\n            \"PRIORITY\": \"Priority\",\n            \"RULE ORDER\": \"Rule Order\",\n            \"OUTPUT ORDER\": \"Output Order\",\n            \"COLLECT\": \"Collect\"\n        },\n        \"COLLECT-OPERATORS\": {\n            \"SUM\": \"和\",\n            \"MIN\": \"最小\",\n            \"MAX\": \"最大\",\n            \"COUNT\": \"总数\"\n        },\n        \"POPUP\": {\n            \"CREATE-TITLE\": \"创建一个新的决策表\",\n            \"CREATE-DESCRIPTION\": \"您需要为新决策表命名，并且您可以在这个操作中添加描述信息。\",\n            \"SAVE-DESCRIPTION\": \"您可以更改新决策表的名称，并且此时您可以更改描述信息。\",\n            \"DUPLICATE-TITLE\": \"复制决策表\",\n            \"DUPLICATE-DESCRIPTION\": \"您需要为新决策表命名，并且您可以在这个操作中添加描述信息。\",\n            \"DELETE-TITLE\": \"删除决策表\",\n            \"DELETE-DESCRIPTION\": \"确实要删除决策表 \\\"{{name}}\\\"?\",\n            \"SAVE-DECISION-TABLE-TITLE\": \"保存决策表\",\n            \"IMPORT-DESCRIPTION\": \"请浏览或拖拽.dmn or .dmn.xml扩展名的的 DMN XML文件\",\n          \t\"IMPORT-TITLE\": \"导入DMN模型\",\n\t        \"IMPORT\": {\n\t            \"DROPZONE\": \"拖拽一个 .dmn or .dmn.xml DMN XML文件\",\n\t            \"CANCEL-UPLOAD\": \"取消上传\",\n\t            \"ERROR\": \"处理DMN XML文件时出错\",\n\t            \"NO-DROP\": \"不支持拖放\"\n\t        },\n            \"USE-AS-NEW-TITLE\": \"作为一个新版本使用\",\n            \"USE-AS-NEW-VERSION\": \"作为一个新版本使用\",\n            \"USE-AS-NEW-DESCRIPTION\": \"您确定要使用 {{version}}版本 去创建一个关于 \\\"{{name}}\\\"的新版本?\",\n            \"USE-AS-NEW-UNRESOLVED-MODELS-ERROR\": \"无法完全恢复app模型到所选择的版本：由于一些引用的模型过去被删除而丢失。请相应地更新app模型。缺失模型:\",\n            \"USE-AS-NEW-UNRESOLVED-MODEL\": \"模型 '{{name}}' 内部id {{id}}, 被 {{createdBy}}创建\"\n        },\n        \"ALERT\": {\n            \"FAVORITE-CONFIRM\": \"喜欢这个决策表\",\n            \"UN-FAVORITE-CONFIRM\": \"这个决策表不再流行了\"\n        }\n    },\n\n    \"APP\": {\n        \"NAME\": \"应用程序定义名称\",\n        \"KEY\": \"应用程序定义key\",\n        \"DESCRIPTION\": \"描述\",\n        \"ICON\": \"图标\",\n        \"THEME\": \"主题\",\n        \"GROUPS-ACCESS\": \"组访问，用逗号分隔\",\n\t\t\"USERS-ACCESS\": \"用户访问，用逗号分隔\",\n        \"ACTION\": {\n            \"DETAILS\": \"显示详细信息\",\n            \"EDIT\": \"修改应用程序定义属性\",\n            \"DUPLICATE\": \"复制这个应用\",\n            \"SHARE\": \"分享应用程序定义\",\n            \"DELETE\": \"删除应用程序定义\",\n            \"CREATE-CONFIRM\": \"创建新的应用程序定义\",\n            \"DUPLICATE-CONFIRM\": \"复制这个应用程序定义\",\n            \"DELETE-CONFIRM\": \"删除应用程序定义\",\n            \"USE-AS-NEW-VERSION\": \"作为新版本使用\",\n            \"OPEN-IN-EDITOR\": \"应用程序编辑器\",\n            \"PUBLISH\": \"发布\",\n            \"PUBLISH-CONFIRM\": \"发布应用程序定义\",\n            \"SELECT-ICON\": \"修改图标...\",\n            \"SELECT-THEME\": \"修改主题...\",\n            \"EDIT-MODELS\": \"编辑包含的模型\",\n            \"EXPORT-ZIP\": \"将app定义导出为zip文件\",\n            \"EXPORT-BAR\": \"将app定义导出为可部署的bar文件\"\n\n        },\n        \"DETAILS\": {\n          \"TITLE\": \"App定义详细信息: {{name}}\",\n          \"HISTORY-TITLE\": \"历史\",\n          \"MODELS-TITLE\": \"app定义中包含的模型\",\n          \"LAST-UPDATED-BY\": \"最后被{{lastUpdatedBy}} - {{lastUpdated | dateformat}}更新\",\n          \"CREATED-BY\": \"被{{createdBy}}创建\",\n          \"NO-DESCRIPTION\": \"这个应用程序定义没有描述信息，可以通过修改应用程序定义来添加一个描述\",\n          \"NO-MODELS-SELECTED\": \"没有为这个应用程序选择模型\"\n        },\n        \"TITLE\": {\n          \"SELECT-ICON\": \"选择应用图标\",\n          \"SELECT-THEME\": \"选择应用主题\",\n          \"PREVIEW\": \"预览\"\n\n        },\n        \"POPUP\": {\n          \"CREATE-TITLE\": \"创建新的应用程序定义\",\n          \"DUPLICATE-TITLE\": \"复制一个应用程序定义\",\n          \"SAVE-APP-TITLE\": \"保存应用程序定义\",\n          \"SAVE-APP-SAVE-SUCCESS\": \"保存的应用程序定义\",\n          \"CREATE-DESCRIPTION\": \"您需要为新的应用程序定义命名，并且您可以在这个操作中添加描述信息。\",\n          \"DUPLICATE-DESCRIPTION\": \"您需要为新的应用程序定义命名，并且您可以在这个操作中添加描述信息。\",\n          \"PUBLISH-TITLE\": \"发布应用程序定义\",\n          \"PUBLISH-DESCRIPTION\": \"您确定要发布应用程序定义 \\\"{{name}}\\\"? 注意这个应用程序定义将版本化，如果已经存在，则将更新工作流应用程序。\",\n          \"PUBLISH-FIELD\": \"发布？请注意，如果启用了发布，则将版本化此应用程序定义，如果已经存在，则将更新工作流应用程序。\",\n          \"PUBLISH-ERROR-PROCDEF-KEY-CONFLICT\": \"你的流程模型 \\\"{{modelInAppName}}\\\"具有相同的标识符\\\"{{processDefinitionKey}}\\\"作为已经存在的部署流程\\\"{{conflictingModelName}}\\\" ，关于这个应用程序 \\\"{{conflictingAppName}}\\\". 请修改这个 \\\"id\\\"流程模型的属性。\",\n          \"PUBLISH-ERROR-PROCESS-ALREADY-USED\": \"下面的流程模型已经在另一个应用程序中使用了。这样行吗？\",\n          \"PUBLISH-ERROR-PROCESS-ALREADY-USED-APP\": \"应用程序\",\n          \"PUBLISH-ERROR-PROCDEF-DUPLICATE-KEYS\": \"无效的应用程序: 找到重复的流程标识符 (修改这个非法的流程模型  \\\"id\\\"属性):\",\n          \"DELETE-TITLE\": \"删除应用程序定义\",\n          \"DELETE-DESCRIPTION\": \"确实要删除应用程序定义 \\\"{{name}}\\\"?\",\n          \"DELETE-DESCRIPTION-WITH-RUNTIME\": \"确实要删应用程序定义 \\\"{{name}}\\\"? 注意，这个应用程序定义已经部署到任务landing页面，并且通过确认，该应用程序将从任务应用程序landing页面中删除。\",\n          \"DELETE-CASCADE-FALSE\": \"只删除当前版本的应用程序定义 (v{{version}})\",\n          \"DELETE-CASCADE-TRUE\": \"也删除所有以前的版本应用程序定义\",\n          \"HAS-CUSTOM-STENCILITEM\" : \"模型 \\\"{{modelName}}\\\" 使用带有自定义模板项目的模板. 在这个模型中使用这个模型是不可能的.\",\n          \"HAS-VALIDATIONERROR\" : \"模型 \\\"{{modelName}}\\\"  有验证错误，不能添加到应用程序定义.在编辑器中打开模型以查看关于验证错误的更多细节。\",\n          \"IMPORT-DESCRIPTION\":\"请使用.zip扩展的应用程序定义浏览或拖拽一个\",\n          \"IMPORT-TITLE\":\"导入应用程序定义模型\",\n          \"IMPORT\": {\n              \"DROPZONE\": \"扩拽一个.zip 应用程序定义文件\",\n              \"CANCEL-UPLOAD\": \"取消上传\",\n              \"RENEWIDM-IDS\": \"Renew the user and group identifiers when importing step and BPMN models. This is often required when importing the 应用程序定义 into a different Flowable environment. It will try to link the human steps and user tasks to the right user and group in this target environment.\",\n              \"ERROR\": \"处理应用程序定义文件时出错\",\n              \"NO-DROP\": \"不支持拖放\"\n          },\n          \"INCLUDE-MODELS-TITLE\": \"包含在应用程序定义中的模型\"\n        },\n        \"ALERT\": {\n          \"DELETE-CONFIRM\": \"应用程序定义删除了\",\n          \"PUBLISH-CONFIRM\": \"应用程序定义已经被发布了\",\n          \"PUBLISH-ERROR\": \"不能发布应用程序定义. 请检查引用的流程模型的有效性。\"\n        }\n    },\n\n    \"SHARE-INFO\": {\n        \"ACTION\": {\n          \"ADD\": \"添加另一个人\"\n        }\n    },\n\n    \"FORM-BUILDER\": {\n        \"PALLETTE\": {\n            \"TEXT\": \"文本\",\n            \"MULTILINE-TEXT\": \"多行文本\",\n            \"PASSWORD\": \"密码\",\n            \"NUMBER\": \"数字\",\n            \"CHECKBOX\": \"多选\",\n            \"DATE\": \"日期\",\n            \"DROPDOWN\": \"下拉\",\n            \"RADIO\": \"单选按钮\",\n            \"PEOPLE\": \"选择人\",\n            \"GROUP-OF-PEOPLE\": \"选择组\",\n            \"UPLOAD\": \"上传文件\",\n            \"EXPRESSION\": \"表达式\",\n            \"DECIMAL\": \"小数\",\n\t    \t\"HYPERLINK\": \"超链接\",\n\t    \t\"SPACER\": \"垫片\",\n\t\t\t\"HORIZONTAL-LINE\": \"横线\",\n\t\t\t\"HEADLINE\": \"标题\",\n\t\t\t\"HEADLINE-WITH-LINE\":\"标题和线\"\n        },\n        \"TABS\": {\n            \"GENERAL\": \"一般\",\n            \"OPTIONS\": \"选项\",\n            \"UPLOAD-OPTIONS\": \"上传选项\",\n\t    \"ADVANCED-OPTIONS\":\"高级\"\n        },\n        \"VERSION\": \"版本 {{version}}\",\n        \"LAST-UPDATED\": \"最后更新的 {{lastUpdatedBy}}, {{lastUpdated | dateformat}}\",\n        \"TITLE\": {\n            \"DESIGN\": \"设计\",\n            \"OUTCOME\": \"结果\"\n        },\n        \"POPUP\": {\n            \"EDIT-TITLE\": \"编辑字段 '{{name}}'\",\n            \"EXPRESSION-TITLE\": \"编辑表达式\"\n        },\n        \"MESSAGE\": {\n            \"EMPTY-EXPRESSION\": \"(没有表达值)\",\n            \"EXPRESSION-HELP\": \"您还可以使用如下的符号来引用先前以任何形式提交的值，作为文本的一部分 ${myFieldId}.\",\n            \"OPTIONS-EXPRESSION-HELP\": \"可以使用表达式来动态填充选项，例如通过引用这样的变量 ${optionsVariable}. 这个表达式需要产生一个java对象(java.util)。带有选项对象的列表)或其json表示。\"\n        },\n        \"LABEL\" : {\n            \"FUNCTIONAL-GROUP\": \"选择组..\",\n            \"PERSON\": \"选择人..\"\n        },\n        \"COMPONENT\": {\n            \"LABEL\": \"标签:\",\n            \"OVERRIDEID\": \"覆盖id?\",\n            \"ID\": \"Id:\",\n            \"PLACEHOLDER\": \"默认值:\",\n            \"OPTIONS\": \"选项\",\n            \"RADIO-BUTTON-DEFAULT\": \"选项 1\",\n            \"DROPDOWN-DEFAULT-EMPTY-SELECTION\": \"请选择一个...\",\n            \"DROPDOWN-EMPTY-VALUE-HELP\": \" 这是‘空值’选项。在运行时选择它意味着‘没有值’或’空’。这允许用于可选字段，但不允许用于必需字段。\",\n            \"OPTIONS-EXPRESSION\": \"选择表达:\",\n            \"OPTIONS-EXPRESSION-ENABLED\": \"启用选项表达\",\n            \"REQUIRED\": \"必填\",\n\t          \"READONLY\": \"只读\",\n            \"EXPRESSION\": \"表达式\",\n            \"ADD-OPTION\": \"+ 添加一个新选项\",\n            \"UPLOAD-ALLOW-MULTIPLE\": \"允许上传多个文件\",\n            \"SIZE\": \"大小\",\n\t          \"MAX-LENGTH\":\"最大长度:\",\n            \"MIN-LENGTH\":\"最小长度:\",\n            \"PASSWORD-UNMASK-OPTION\": \"密码屏蔽/揭露选项\",\n\t          \"HYPERLINK-URL\": \"超链接地址\",\n\t          \"REGEX-PATTERN\":\"正则表达式的标准\",\n            \"MASK\":{\n              \"TITLE\":\"输入掩码\",\n              \"EXAMPLES\":{\n                \"TITLE\":\"例子:\",\n                \"NUMBER\":\"任何数字\",\n                \"LETTER\":\"任何字母\",\n                \"NUMBERORLETTER\":\"任何字母或数字\",\n                \"OPTIONAL\":\"使蒙版可选(无效)\",\n                \"PHONE\":\"电话\"\n               }\n           }\n        },\n        \"OUTCOMES\": {\n            \"DESCRIPTION\": \"您可以为这个任务定义多个结果。在完成一个任务时，用户选择一个可用的结果，可以在eg中使用。在这个过程中进一步的条件。\",\n            \"NO-OUTCOMES-OPTION\": \"不要使用自定义结果，只显示'完成'按钮。\",\n            \"OUTCOMES-OPTION\": \"使用此表单的定制结果。\",\n            \"POSSIBLE-OUTCOMES\": \"可能的出线\",\n            \"NEW-OUTCOME-PLACEHOLDER\": \"输入新的出线\",\n            \"ADD\": \"添加出线\",\n            \"REMOVE\": \"移除\"\n        }\n    },\n\n    \"DECISION-TABLE-EDITOR\": {\n        \"EMPTY-MESSAGES\": {\n            \"NO-VARIABLE-SELECTED\": \"未定义\"\n        },\n        \"POPUP\": {\n            \"EXPRESSION-EDITOR\": {\n                \"INPUT-TITLE\": \"编辑输入列\",\n                \"INPUT-DESCRIPTION\": \"选择输入变量作为列的输入\",\n                \"OUTPUT-TITLE\": \"编辑输出列\",\n                \"OUTPUT-DESCRIPTION\": \"选择一个现有的输出变量或创建一个新的变量\",\n                \"EXPRESSION-LABEL\": \"列标签:\",\n                \"EXPRESSION-PLACEHOLDER\": \"输入可选标签\",\n                \"EXPRESSION-VARIABLE-NAME\": \"变量名称:\",\n                \"EXPRESSION-VARIABLE-TYPE\": \"变量类型:\",\n                \"EXPRESSION-VARIABLE-NAME-PLACEHOLDER\": \"输入变量名\",\n                \"OUTPUT-NEW-VARIABLE-ID\": \"变量ID:\",\n                \"OUTPUT-NEW-VARIABLE-TYPE\": \"变量类型:\",\n                \"COMPLEX-EXPRESSION-LABEL\": \"复杂表达式:\",\n                \"ALLOWED-VALUES\": \"允许值（可选）:\",\n                \"OUTPUT-VALUES\": \"输出值\",\n                \"OUTPUT-VALUES-OPTIONAL\": \"(可选):\",\n                \"OUTPUT-VALUES-NOT-OPTIONAL\": \"(为优先级/输出顺序拖动行):\"\n            }\n        },\n        \"BUTTON-ACTIONS-LABEL\": \"动作\",\n        \"BUTTON-ADD-INPUT-LABEL\": \"添加输入\",\n        \"BUTTON-ADD-OUTPUT-LABEL\": \"添加输出\",\n        \"BUTTON-ADD-RULE-LABEL\": \"添加规则\",\n        \"BUTTON-MOVE-RULE-UPWARDS-LABEL\": \"向上移动\",\n        \"BUTTON-MOVE-RULE-DOWNWARDS-LABEL\": \"向下移动\",\n        \"BUTTON-REMOVE-RULE-LABEL\": \"移除规则\",\n        \"ALERT\": {\n            \"EXPRESSION-VARIABLE-REQUIRED-ERROR\": \"所有输入和输出表达式都必须引用表单字段或变量。\",\n            \"SAVE-CONFIRM\": \"保存决策表'{{name}}'\"\n        }\n    },\n\n    \"TOUR\": {\n        \"WELCOME-TITLE\": \"欢迎, {{userName}}\",\n        \"WELCOME-CONTENT\": \"这是一个短暂的flowable编辑器. 接下来的几个步骤将指导您通过应用程序的不同部分来启动。按ESC键随时停止。\" ,\n        \"PALETTE-TITLE\": \"调色板\",\n        \"PALETTE-CONTENT\": \"在这里可以找到创建业务流程的所有可用构成。它们是按逻辑组排列的。只需点击它就可以打开一组:\",\n        \"CANVAS-TITLE\": \"画布\",\n        \"CANVAS-CONTENT\": \"这是创建业务流程的工作空间。从左侧的调色板中拖动元素，并将它们放在画布上以开始建模\",\n        \"DRAGDROP-TITLE\": \"拖放示例\",\n        \"DRAGDROP-CONTENT\": \"下面是一个如何开始建模的例子:\",\n        \"PROPERTIES-TITLE\": \"属性\",\n        \"PROPERTIES-CONTENT\": \"在这里您可以配置业务流程构造的属性。只需选择画布上的项目，它的属性就会显示出来。如果要编辑该属性，请单击该属性。\",\n        \"TOOLBAR-TITLE\": \"工具栏\",\n        \"TOOLBAR-CONTENT\": \"可以在这里找到所有的动作：保存或验证模型, 复制和粘贴一个流程的部分, 等等. 在按钮上悬停以此获得对动作的描述信息.\",\n        \"END-TITLE\": \"终点\",\n        \"END-CONTENT\": \"就是这样！现在可以开始建模过程。如果你有任何问题，可以问他们。 <a href=\\\"http://forum.flowable.org/\\\" target=\\\"_blank\\\">Flowable论坛</a> \"\n    },\n\n    \"FEATURE-TOUR\" : {\n        \"BENDPOINT\" : {\n            \"TITLE\": \"教程\",\n            \"DESCRIPTION\" : \"当使用连线流将流程按照步骤彼此连接的时候，您可能会发现，这些连线彼此交叉，或者您希望以不同的方式排列它们。这样做, 可以向连线添加或移除一个弯曲点。<br/><br/>如下图所示，你首先应该点击 '添加弯曲点' 然后单击连线添加它。注意，连线将在绿色中显示一个微妙的指示，以显示可以在那里添加弯曲点。<br/><br/>删除一个弯曲点再次遵循类似的模式: 点击 '移除弯曲点' 按钮 ，然后点击弯曲点再次移除。\"\n        }\n    },\n\n    \"ACTION.OK\" : \"Ok\",\n    \"ACTION.SAVE\" : \"保存\",\n    \"ACTION.SAVE-AND-CLOSE\" : \"保存和关闭编辑器\",\n    \"ACTION.SEND\" : \"发送\",\n    \"ACTION.CANCEL\" : \"取消\",\n    \"ACTION.SELECT\" : \"选择\",\n    \"ACTION.ADD\" : \"添加\",\n    \"ACTION.REMOVE\" : \"移除\",\n    \"ACTION.MOVE.UP\" : \"移动入口\",\n    \"ACTION.MOVE.DOWN\" : \"向下移动\",\n\n    \"TOOLBAR.ACTION.CLOSE\" : \"关闭编辑器并返回到概览页面\",\n    \"TOOLBAR.ACTION.SAVE\" : \"保存模型\",\n    \"TOOLBAR.ACTION.VALIDATE\" : \"验证模型\",\n    \"TOOLBAR.ACTION.CUT\" : \"剪切 (在业务流程中选择一个或多个元素)\",\n    \"TOOLBAR.ACTION.COPY\" : \"拷贝 (在业务流程中选择一个或多个元素)\",\n    \"TOOLBAR.ACTION.PASTE\" : \"粘贴\",\n    \"TOOLBAR.ACTION.DELETE\" : \"删除选定元素\",\n    \"TOOLBAR.ACTION.UNDO\" : \"撤消\",\n    \"TOOLBAR.ACTION.REDO\" : \"重做\",\n    \"TOOLBAR.ACTION.ZOOMIN\" : \"放大\",\n    \"TOOLBAR.ACTION.ZOOMOUT\" : \"缩小\",\n    \"TOOLBAR.ACTION.ZOOMACTUAL\" : \"缩放到实际尺寸\",\n    \"TOOLBAR.ACTION.ZOOMFIT\" : \"缩放到适当大小\",\n    \"TOOLBAR.ACTION.BENDPOINT.ADD\" : \"向选定的连线添加弯曲点\",\n    \"TOOLBAR.ACTION.BENDPOINT.REMOVE\" : \"向选定的连线移除弯曲点\",\n    \"TOOLBAR.ACTION.ALIGNHORIZONTAL\" : \"水平对齐\",\n    \"TOOLBAR.ACTION.ALIGNVERTICAL\" : \"垂直对齐\",\n    \"TOOLBAR.ACTION.SAMESIZE\" : \"相同大小\",\n    \"TOOLBAR.ACTION.HELP\": \"开始导游\",\n    \"TOOLBAR.ACTION.FEEDBACK\": \"提供反馈\",\n\n    \"FORM_TOOLBAR.ACTION.SAVE\" : \"保存模型\",\n\n    \"APP_DEFINITION_TOOLBAR.ACTION.SAVE\" : \"保存应用程序定义\",\n\n    \"BUTTON.ACTION.DELETE.TOOLTIP\": \"从模型中删除元素\",\n    \"BUTTON.ACTION.MORPH.TOOLTIP\": \"更改元素类型\",\n\n    \"ELEMENT.AUTHOR\" : \"作者\",\n    \"ELEMENT.DATE_CREATED\" : \"创建日期\",\n\n    \"PROPERTY.REMOVED\" : \"移除\",\n    \"PROPERTY.EMPTY\" : \"空值\",\n    \"PROPERTY.PROPERTY.EDIT.TITLE\" : \"更改值为\",\n\n    \"PROPERTY.FEEDBACK.TITLE\" : \"请填写您的反馈意见\",\n\n    \"PROPERTY.ASSIGNMENT.TITLE\" : \"分配\",\n    \"PROPERTY.ASSIGNMENT.TYPE\" : \"类型\",\n    \"PROPERTY.ASSIGNMENT.TYPE.IDENTITYSTORE\" : \"身份存储\",\n    \"PROPERTY.ASSIGNMENT.TYPE.STATIC\" : \"固定值\",\n    \"PROPERTY.ASSIGNMENT.ASSIGNEE\" : \"分配\",\n    \"PROPERTY.ASSIGNMENT.MATCHING\" : \"使用 &uparrow; 和 &downarrow;选择并按Enter确认或使用鼠标\",\n    \"PROPERTY.ASSIGNMENT.ASSIGNEE_PLACEHOLDER\" : \"输入分配人\",\n    \"PROPERTY.ASSIGNMENT.EMPTY\" : \"没有选择分配人\",\n    \"PROPERTY.ASSIGNMENT.NONE\" : \"未分配经办人\",\n    \"PROPERTY.ASSIGNMENT.PLACEHOLDER-SEARCHUSER\": \"搜索用户\",\n    \"PROPERTY.ASSIGNMENT.PLACEHOLDER-SEARCHGROUP\": \"搜索组\",\n    \"PROPERTY.ASSIGNMENT.SEARCH\": \"搜索: \",\n    \"PROPERTY.ASSIGNMENT.ASSIGNEE_DISPLAY\" : \"分配人 {{assignee}}\",\n    \"PROPERTY.ASSIGNMENT.CANDIDATE_USERS_DISPLAY\" : \"{{length}} 候选用户\",\n    \"PROPERTY.ASSIGNMENT.CANDIDATE_USERS\" : \"候选用户\",\n    \"PROPERTY.ASSIGNMENT.CANDIDATE_GROUPS_DISPLAY\" :  \"{{length}} 候选组\",\n    \"PROPERTY.ASSIGNMENT.CANDIDATE_GROUPS\" :  \"候选组\",\n    \"PROPERTY.ASSIGNMENT.USER_IDM_DISPLAY\": \"用户 {{firstName}} {{lastName}}\",\n    \"PROPERTY.ASSIGNMENT.USER_IDM_EMAIL_DISPLAY\": \"用户 {{email}}\",\n    \"PROPERTY.ASSIGNMENT.USER_IDM_FIELD_DISPLAY\": \"字段 {{name}}\",\n    \"PROPERTY.ASSIGNMENT.IDM_EMPTY\" : \"流程发起人\",\n    \"PROPERTY.ASSIGNMENT.IDM.TYPE\" : \"分配\",\n    \"PROPERTY.ASSIGNMENT.IDM.NO_CANDIDATE_USERS\" : \"没有选择候选人...\",\n    \"PROPERTY.ASSIGNMENT.IDM.NO_CANDIDATE_GROUPS\" : \"没有选择候选组...\",\n    \"PROPERTY.ASSIGNMENT.IDM.DROPDOWN.INITIATOR\" : \"分配给流程发起人\",\n    \"PROPERTY.ASSIGNMENT.IDM.DROPDOWN.USER\" : \"分配给单个用户\",\n    \"PROPERTY.ASSIGNMENT.IDM.DROPDOWN.USERS\" : \"候选用户\",\n    \"PROPERTY.ASSIGNMENT.IDM.DROPDOWN.GROUPS\" : \"候选组\",\n    \"PROPERTY.ASSIGNMENT.INITIATOR-CAN-COMPLETE\" : \"允许流程发起人完成任务\",\n    \"PROPERTY.EXECUTIONLISTENERS.DISPLAY\" : \"{{length}} 执行监听器\",\n    \"PROPERTY.EXECUTIONLISTENERS.EMPTY\" : \"没有配置执行监听器\",\n    \"PROPERTY.EXECUTIONLISTENERS.EVENT\" : \"事件\",\n    \"PROPERTY.EXECUTIONLISTENERS.CLASS\" : \"类\",\n    \"PROPERTY.EXECUTIONLISTENERS.CLASS.PLACEHOLDER\" : \"输入一个类名\",\n    \"PROPERTY.EXECUTIONLISTENERS.EXPRESSION\" : \"表达式\",\n    \"PROPERTY.EXECUTIONLISTENERS.EXPRESSION.PLACEHOLDER\" : \"输入一个表达式\",\n    \"PROPERTY.EXECUTIONLISTENERS.DELEGATEEXPRESSION\" : \"委托表达式\",\n    \"PROPERTY.EXECUTIONLISTENERS.DELEGATEEXPRESSION.PLACEHOLDER\" : \"输入一个委托表达式\",\n    \"PROPERTY.EXECUTIONLISTENERS.UNSELECTED\" : \"没有选择执行监听器\",\n    \"PROPERTY.EXECUTIONLISTENERS.FIELDS.NAME\" : \"名称\",\n    \"PROPERTY.EXECUTIONLISTENERS.FIELDS.NAME.PLACEHOLDER\" : \"输入一个名称\",\n    \"PROPERTY.EXECUTIONLISTENERS.FIELDS.EXPRESSION\" : \"表达式\",\n    \"PROPERTY.EXECUTIONLISTENERS.FIELDS.EXPRESSION.PLACEHOLDER\" : \"输入一个表达式\",\n    \"PROPERTY.EXECUTIONLISTENERS.FIELDS.STRINGVALUE\" : \"字符串值\",\n    \"PROPERTY.EXECUTIONLISTENERS.FIELDS.STRINGVALUE.PLACEHOLDER\" : \"输入一个字符串值\",\n    \"PROPERTY.EXECUTIONLISTENERS.FIELDS.STRING\" : \"字符串\",\n    \"PROPERTY.EXECUTIONLISTENERS.FIELDS.STRING.PLACEHOLDER\" : \"输入一个字符串\",\n    \"PROPERTY.EXECUTIONLISTENERS.FIELDS.IMPLEMENTATION\" : \"实现\",\n    \"PROPERTY.EXECUTIONLISTENERS.FIELDS.EMPTY\" : \"未选择字段\",\n\n    \"PROPERTY.FIELDS\" : \"{{length}} 字段\",\n    \"PROPERTY.FIELDS.EMPTY\" : \"未选择字段\",\n    \"PROPERTY.FIELDS.NAME\" : \"名称\",\n    \"PROPERTY.FIELDS.NAME.PLACEHOLDER\" : \"输入一个名称\",\n    \"PROPERTY.FIELDS.EXPRESSION\" : \"表达式\",\n    \"PROPERTY.FIELDS.EXPRESSION.PLACEHOLDER\" : \"输入一个表达式\",\n    \"PROPERTY.FIELDS.STRINGVALUE\" : \"字符串值\",\n    \"PROPERTY.FIELDS.STRINGVALUE.PLACEHOLDER\" : \"输入一个字符串值\",\n    \"PROPERTY.FIELDS.STRING\" : \"字符串\",\n    \"PROPERTY.FIELDS.STRING.PLACEHOLDER\" : \"输入一个字符串\",\n    \"PROPERTY.FIELDS.IMPLEMENTATION\" : \"实现\",\n\n    \"PROPERTY.DATAPROPERTIES.VALUES\" : \"{{length}} data objects\",\n    \"PROPERTY.DATAPROPERTIES.EMPTY\" : \"没有配置data objects\",\n    \"PROPERTY.DATAPROPERTIES.ID\" : \"Id\",\n    \"PROPERTY.DATAPROPERTIES.ID.PLACEHOLDER\" : \"输入一个id\",\n    \"PROPERTY.DATAPROPERTIES.NAME\" : \"名称\",\n    \"PROPERTY.DATAPROPERTIES.NAME.PLACEHOLDER\" : \"输入一个名称\",\n    \"PROPERTY.DATAPROPERTIES.TYPE\" : \"类型\",\n    \"PROPERTY.DATAPROPERTIES.VALUE.PLACEHOLDER\" : \"输入一个值 (可选)\",\n    \"PROPERTY.DATAPROPERTIES.VALUE\" : \"默认值\",\n\n    \"PROPERTY.FORMPROPERTIES.VALUE\" : \"{{length}} 表单属性\",\n    \"PROPERTY.FORMPROPERTIES.EMPTY\" : \"没有选择表单属性\",\n    \"PROPERTY.FORMPROPERTIES.ID\" : \"Id\",\n    \"PROPERTY.FORMPROPERTIES.ID.PLACEHOLDER\" : \"输入一个id\",\n    \"PROPERTY.FORMPROPERTIES.NAME\" : \"名称\",\n    \"PROPERTY.FORMPROPERTIES.NAME.PLACEHOLDER\" : \"输入一个名称\",\n    \"PROPERTY.FORMPROPERTIES.TYPE\" : \"类型\",\n    \"PROPERTY.FORMPROPERTIES.DATEPATTERN\" : \"日期格式\",\n    \"PROPERTY.FORMPROPERTIES.DATEPATTERN.PLACEHOLDER\" : \"输入日期格式\",\n    \"PROPERTY.FORMPROPERTIES.VALUES\" : \"值\",\n    \"PROPERTY.FORMPROPERTIES.ENUMVALUES.EMPTY\" : \"未选择枚举值\",\n    \"PROPERTY.FORMPROPERTIES.VALUES.ID\" : \"Id\",\n    \"PROPERTY.FORMPROPERTIES.VALUES.NAME\" : \"名称\",\n    \"PROPERTY.FORMPROPERTIES.VALUES.ID.PLACEHOLDER\" : \"输入id值\",\n  \t\"PROPERTY.FORMPROPERTIES.VALUES.NAME.PLACEHOLDER\" : \"输入名称值\",\n    \"PROPERTY.FORMPROPERTIES.EXPRESSION\" : \"表达式\",\n    \"PROPERTY.FORMPROPERTIES.EXPRESSION.PLACEHOLDER\" : \"输入一个表达式\",\n    \"PROPERTY.FORMPROPERTIES.VARIABLE\" : \"变量\",\n    \"PROPERTY.FORMPROPERTIES.VARIABLE.PLACEHOLDER\" : \"输入一个变量\",\n    \"PROPERTY.FORMPROPERTIES.DEFAULT\" : \"默认值\",\n    \"PROPERTY.FORMPROPERTIES.DEFAULT.PLACEHOLDER\" : \"输入一个默认值\",\n    \"PROPERTY.FORMPROPERTIES.REQUIRED\" : \"必须的\",\n    \"PROPERTY.FORMPROPERTIES.READABLE\" : \"可读的\",\n    \"PROPERTY.FORMPROPERTIES.WRITABLE\" : \"可写的\",\n\n    \"PROPERTY.INPARAMETERS.VALUE\" : \"{{length}} in-parameters\",\n    \"PROPERTY.INPARAMETERS.EMPTY\" : \"没有配置in-parameters \",\n\n    \"PROPERTY.OUTPARAMETERS.VALUE\" : \"{{length}} out-parameters\",\n    \"PROPERTY.OUTPARAMETERS.EMPTY\" : \"没有配置out-parameters\",\n\n    \"PROPERTY.PARAMETER.SOURCE\" : \"源\",\n    \"PROPERTY.PARAMETER.SOURCE.PLACEHOLDER\" : \"输入一个源\",\n    \"PROPERTY.PARAMETER.SOURCEEXPRESSION\" : \"源表达式\",\n    \"PROPERTY.PARAMETER.SOURCEEXPRESSION.PLACEHOLDER\" : \"输入一个源表达式\",\n    \"PROPERTY.PARAMETER.TARGET\" : \"目标\",\n    \"PROPERTY.PARAMETER.TARGET.PLACEHOLDER\" : \"输入一个目标\",\n    \"PROPERTY.PARAMETER.EMPTY\" : \"没有选择参数\",\n\n    \"PROPERTY.PROCESSREFERENCE.EMPTY\" : \"没有选择引用\",\n    \"PROPERTY.PROCESSREFERENCE.TITLE\" : \"流程参考\",\n    \"PROPERTY.PROCESSREFERENCE.ERROR.PROCESS\" : \"加载流程出错。稍后再试一次\",\n    \"PROPERTY.PROCESSREFERENCE.PROCESS.LOADING\" : \"加载流程...\",\n    \"PROPERTY.PROCESSREFERENCE.PROCESS.EMPTY\" : \"此文件夹不包含流程\",\n\n    \"PROPERTY.FORMREFERENCE.EMPTY\" : \"没有选择参考\",\n    \"PROPERTY.FORMREFERENCE.TITLE\" : \"表单引用\",\n    \"PROPERTY.FORMREFERENCE.DESCRIPTION\" : \"引用表单\",\n    \"PROPERTY.FORMREFERENCE.ERROR.FORM\" : \"加载表单出错。稍后再试一次\",\n    \"PROPERTY.FORMREFERENCE.FORM.LOADING\" : \"加载表单...\",\n    \"PROPERTY.FORMREFERENCE.FORM.EMPTY\" : \"此文件夹不包含表单\",\n\n    \"PROPERTY.TASKLISTENERS.VALUE\" : \"{{length}}任务监听器\",\n    \"PROPERTY.TASKLISTENERS.EMPTY\" : \"没有配置任务监听器\",\n    \"PROPERTY.TASKLISTENERS.EVENT\" : \"事件\",\n    \"PROPERTY.TASKLISTENERS.CLASS\" : \"类\",\n    \"PROPERTY.TASKLISTENERS.CLASS.PLACEHOLDER\" : \"输入一个类名\",\n    \"PROPERTY.TASKLISTENERS.EXPRESSION\" : \"表达式\",\n    \"PROPERTY.TASKLISTENERS.EXPRESSION.PLACEHOLDER\" : \"输入一个表达式\",\n    \"PROPERTY.TASKLISTENERS.DELEGATEEXPRESSION\" : \"委托表达式\",\n    \"PROPERTY.TASKLISTENERS.DELEGATEEXPRESSION.PLACEHOLDER\" : \"输入一个委托表达式\",\n    \"PROPERTY.TASKLISTENERS.UNSELECTED\" : \"没有选择任务监听器\",\n    \"PROPERTY.TASKLISTENERS.FIELDS.NAME\" : \"名称\",\n    \"PROPERTY.TASKLISTENERS.FIELDS.NAME.PLACEHOLDER\" : \"输入一个名称\",\n    \"PROPERTY.TASKLISTENERS.FIELDS.EXPRESSION\" : \"表达式\",\n    \"PROPERTY.TASKLISTENERS.FIELDS.EXPRESSION.PLACEHOLDER\" : \"输入一个表达式\",\n    \"PROPERTY.TASKLISTENERS.FIELDS.STRINGVALUE\" : \"字符串值\",\n    \"PROPERTY.TASKLISTENERS.FIELDS.STRINGVALUE.PLACEHOLDER\" : \"输入一个字符串值\",\n    \"PROPERTY.TASKLISTENERS.FIELDS.STRING\" : \"字符串\",\n    \"PROPERTY.TASKLISTENERS.FIELDS.STRING.PLACEHOLDER\" : \"输入一个字符串\",\n    \"PROPERTY.TASKLISTENERS.FIELDS.IMPLEMENTATION\" : \"实现\",\n    \"PROPERTY.TASKLISTENERS.FIELDS.EMPTY\" : \"没有选择字段\",\n\n    \"PROPERTY.EVENTLISTENERS.DISPLAY\" : \"{{length}} 事件监听器\",\n    \"PROPERTY.EVENTLISTENERS.EMPTY\" : \"没有配置事件监听器\",\n    \"PROPERTY.EVENTLISTENERS.EVENTS\": \"事件\",\n    \"PROPERTY.EVENTLISTENERS.RETHROW\": \"Rethrow event?\",\n    \"PROPERTY.EVENTLISTENERS.CLASS\" : \"类\",\n    \"PROPERTY.EVENTLISTENERS.CLASS.PLACEHOLDER\" : \"输入一个类名\",\n    \"PROPERTY.EVENTLISTENERS.DELEGATEEXPRESSION\" : \"委托表达式\",\n    \"PROPERTY.EVENTLISTENERS.DELEGATEEXPRESSION.PLACEHOLDER\" : \"输入一个委托表达式\",\n    \"PROPERTY.EVENTLISTENERS.ENTITYTYPE\" : \"实体类型\",\n    \"PROPERTY.EVENTLISTENERS.ENTITYTYPE.PLACEHOLDER\" : \"输入一个实体类型\",\n    \"PROPERTY.EVENTLISTENERS.RETHROWTYPE\": \"Rethrow event type\",\n    \"PROPERTY.EVENTLISTENERS.ERRORCODE\" : \"错误码\",\n    \"PROPERTY.EVENTLISTENERS.ERRORCODE.PLACEHOLDER\" : \"输入一个错误码\",\n    \"PROPERTY.EVENTLISTENERS.MESSAGENAME\" : \"消息名称\",\n    \"PROPERTY.EVENTLISTENERS.MESSAGENAME.PLACEHOLDER\" : \"输入一个消息名称\",\n    \"PROPERTY.EVENTLISTENERS.SIGNALNAME\" : \"信号名称\",\n    \"PROPERTY.EVENTLISTENERS.SIGNALNAME.PLACEHOLDER\" : \"输入信号名称\",\n    \"PROPERTY.EVENTLISTENERS.UNSELECTED\" : \"没有选择事件监听器\",\n\n    \"PROPERTY.PLANITEMLIFECYCLELISTENERS.VALUE\" : \"{{length}} lifecycle listeners\",\n    \"PROPERTY.PLANITEMLIFECYCLELISTENERS.EMPTY\" : \"No lifecycle listeners configured\",\n    \"PROPERTY.PLANITEMLIFECYCLELISTENERS.EVENT\" : \"Event\",\n    \"PROPERTY.PLANITEMLIFECYCLELISTENERS.SOURCE_STATE\" : \"Source state\",\n    \"PROPERTY.PLANITEMLIFECYCLELISTENERS.TARGET_STATE\" : \"Target state\",\n    \"PROPERTY.PLANITEMLIFECYCLELISTENERS.CLASS\" : \"Class\",\n    \"PROPERTY.PLANITEMLIFECYCLELISTENERS.CLASS.PLACEHOLDER\" : \"Enter a classname\",\n    \"PROPERTY.PLANITEMLIFECYCLELISTENERS.EXPRESSION\" : \"Expression\",\n    \"PROPERTY.PLANITEMLIFECYCLELISTENERS.EXPRESSION.PLACEHOLDER\" : \"Enter an expression\",\n    \"PROPERTY.PLANITEMLIFECYCLELISTENERS.DELEGATEEXPRESSION\" : \"Delegate expression\",\n    \"PROPERTY.PLANITEMLIFECYCLELISTENERS.DELEGATEEXPRESSION.PLACEHOLDER\" : \"Enter a delegate expression\",\n    \"PROPERTY.PLANITEMLIFECYCLELISTENERS.UNSELECTED\" : \"No task listener selected\",\n    \"PROPERTY.PLANITEMLIFECYCLELISTENERS.FIELDS.NAME\" : \"Name\",\n    \"PROPERTY.PLANITEMLIFECYCLELISTENERS.FIELDS.NAME.PLACEHOLDER\" : \"Enter a name\",\n    \"PROPERTY.PLANITEMLIFECYCLELISTENERS.FIELDS.EXPRESSION\" : \"Expression\",\n    \"PROPERTY.PLANITEMLIFECYCLELISTENERS.FIELDS.EXPRESSION.PLACEHOLDER\" : \"Enter an expression\",\n    \"PROPERTY.PLANITEMLIFECYCLELISTENERS.FIELDS.STRINGVALUE\" : \"String value\",\n    \"PROPERTY.PLANITEMLIFECYCLELISTENERS.FIELDS.STRINGVALUE.PLACEHOLDER\" : \"Enter a string value\",\n    \"PROPERTY.PLANITEMLIFECYCLELISTENERS.FIELDS.STRING\" : \"String\",\n    \"PROPERTY.PLANITEMLIFECYCLELISTENERS.FIELDS.STRING.PLACEHOLDER\" : \"Enter a string\",\n    \"PROPERTY.PLANITEMLIFECYCLELISTENERS.FIELDS.IMPLEMENTATION\" : \"Implementation\",\n    \"PROPERTY.PLANITEMLIFECYCLELISTENERS.FIELDS.EMPTY\" : \"No Field selected\",\n\n    \"PROPERTY.SIGNALDEFINITIONS.DISPLAY\" : \"{{length}} 信号定义\",\n    \"PROPERTY.SIGNALDEFINITIONS.EMPTY\" : \"没有配置信号定义\",\n    \"PROPERTY.SIGNALDEFINITIONS.SCOPE-GLOBAL\": \"全局\",\n    \"PROPERTY.SIGNALDEFINITIONS.SCOPE-PROCESSINSTANCE\": \"流程实例\",\n    \"PROPERTY.SIGNALDEFINITIONS.ID\" : \"Id\",\n    \"PROPERTY.SIGNALDEFINITIONS.NAME\" : \"名称\",\n    \"PROPERTY.SIGNALDEFINITIONS.SCOPE\" : \"Scope\",\n\n    \"PROPERTY.MESSAGEDEFINITIONS.DISPLAY\" : \"{{length}} 消息定义\",\n    \"PROPERTY.MESSAGEDEFINITIONS.EMPTY\" : \"没有配置消息定义\",\n    \"PROPERTY.MESSAGEDEFINITIONS.ID\" : \"Id\",\n    \"PROPERTY.MESSAGEDEFINITIONS.NAME\" : \"名称\",\n\n    \"PROPERTY.SEQUENCEFLOW.ORDER.EMPTY\" : \"没有确定连线的顺序\",\n    \"PROPERTY.SEQUENCEFLOW.ORDER.NOT.EMPTY\" : \"设置连线的顺序\",\n    \"PROPERTY.SEQUENCEFLOW.ORDER.NO.OUTGOING.SEQUENCEFLOW.FOUND\" : \"没有发现流出连线.\",\n    \"PROPERTY.SEQUENCEFLOW.ORDER.DESCRIPTION\" : \"设置需要评估连线的顺序:\",\n    \"PROPERTY.SEQUENCEFLOW.ORDER.SEQUENCEFLOW.VALUE\" : \"连线到 {{targetType}} {{targetTitle}}\",\n\n    \"PROPERTY.SEQUENCEFLOW.CONDITION.TITLE\" : \"连线条件\",\n    \"PROPERTY.SEQUENCEFLOW.CONDITION.STATIC\" : \"条件表达式\",\n    \"PROPERTY.SEQUENCEFLOW.CONDITION.NO-CONDITION-DISPLAY\": \"没有设置条件\",\n\n    \"PROPERTY.DUEDATE.EMPTY\" : \"没有到期\",\n    \"PROPERTY.DUEDATE.DEFINED\" : \"定义到期日\",\n    \"PROPERTY.DUEDATE.TITLE\" : \"到期日\",\n    \"PROPERTY.DUEDATE.EXPRESSION-LABEL\" : \"到期日表达式\",\n    \"PROPERTY.DUEDATE.TASK-DUE-DATE-OPTIONS.NO-DUEDATE\" : \"没有到期日\",\n    \"PROPERTY.DUEDATE.TASK-DUE-DATE-OPTIONS.EXPRESSION\" : \"表达式定义\",\n    \"PROPERTY.DUEDATE.TASK-DUE-DATE-OPTIONS.STATIC\" : \"任务创建后的固定持续时间\",\n    \"PROPERTY.DUEDATE.TASK-DUE-DATE-OPTIONS.FIELD\" : \"基于字段\",\n\n    \"MODEL.SAVE.TITLE\" : \"保存模型\",\n    \"MODEL.VALIDATE.TITLE\" : \"验证结果\",\n    \"MODEL.NAME\" : \"名称\",\n    \"MODEL.KEY\" : \"Key\",\n    \"MODEL.DESCRIPTION\" : \"描述\",\n    \"MODEL.SAVE.NEWVERSION\" : \"将此保存为新版本？这意味着你可以回到以前的版本。\",\n    \"MODEL.SAVE.COMMENT\" : \"评论\",\n    \"MODEL.SAVE.SAVING\" : \"正在保存模型\",\n    \"MODEL.LASTMODIFIEDDATE\" : \"最后保存\",\n    \"MODEL.SAVE.ERROR\": \"Unexpected error: 不能保存模型\",\n    \"MODEL.VALIDATIONERRORS\": \" 注意，模型包含验证错误。这意味着该模型在当前状态下不能部署在Flowable引擎上。\",\n    \"MODEL.CONFLICT.WRITE\": \"不能保存模型: '{{userFullName}}'对该模型进行了更改\",\n    \"MODEL.CONFLICT.WRITE.OPTIONS\": \"选择一个选项来解决此冲突:\",\n    \"MODEL.CONFLICT.WRITE.OPTION.OVERWRITE\": \"覆盖其他模型\",\n    \"MODEL.CONFLICT.WRITE.OPTION.DISCARDCHANGES\": \"放弃我的改变\",\n    \"MODEL.CONFLICT.WRITE.OPTION.SAVEAS\": \"保存为新模型\",\n    \"MODEL.CONFLICT.WRITE.OPTION.NEWVERSION\": \"创建新版本\",\n    \"MODEL.CONFLICT.SAVEAS\" : \"另存为:\",\n\n    \"EVENT_TYPE.ACTIVITY.COMPENSATE.TOOLTIP\": \"一项活动将作为对另一活动的补偿而被执行。事件针对即将执行的活动进行补偿。\",\n    \"EVENT_TYPE.ACTIVITY.COMPLETED.TOOLTIP\": \"一项活动已圆满完成。\",\n    \"EVENT_TYPE.ACTIVITY.ERROR.RECEIVED.TOOLTIP\": \"活动已接收到错误事件。在活动接收到实际错误之前发送\",\n    \"EVENT_TYPE.MEMBERSHIP.CREATED.TOOLTIP\": \"创建了新的membership\",\n    \"EVENT_TYPE.MEMBERSHIP.DELETED.TOOLTIP\": \"单个membership已被删除\",\n    \"EVENT_TYPE.MEMBERSHIPS.DELETED.TOOLTIP\": \"相关组中的所有成员已被删除。由于可能的原因，个别事件不会被派遣。\",\n    \"EVENT_TYPE.TASK.ASSIGNED.TOOLTIP\": \"一个任务已经被分配人了。这将抛出一个实体更新事件\",\n    \"EVENT_TYPE.TASK.COMPLETED.TOOLTIP\": \"一个任务已经被完成。在删除任务实体之前调度\",\n    \"EVENT_TYPE.UNCAUGHT.BPMNERROR.TOOLTIP\": \"当BPMN错误被抛出，但未在流程中捕获时\",\n    \"EVENT_TYPE.VARIABLE.CREATED.TOOLTIP\": \"已经创建了一个新的变量\",\n    \"EVENT_TYPE.VARIABLE.DELETED.TOOLTIP\": \"已删除现有变量\",\n    \"EVENT_TYPE.VARIABLE.UPDATED.TOOLTIP\": \"已更新现有变量\",\n\n    \"PROPERTY.DECISIONTABLEREFERENCE.EMPTY\" : \"没有选择引用\",\n    \"PROPERTY.DECISIONTABLEREFERENCE.TITLE\" : \"决策表引用\",\n    \"PROPERTY.DECISIONTABLEREFERENCE.ERROR.FORM\" : \"加载决策表出现错误. 稍后再试一次\",\n    \"PROPERTY.DECISIONTABLEREFERENCE.DECISIONTABLE.LOADING\" : \"加载决策表...\",\n    \"PROPERTY.DECISIONTABLEREFERENCE.DECISIONTABLE.EMPTY\" : \"此文件夹不包含任何决策表\",\n    \n    \"PROPERTY.CASEREFERENCE.EMPTY\" : \"没有选择引用\",\n    \"PROPERTY.CASEREFERENCE.TITLE\" : \"案例型引用\",\n    \"PROPERTY.CASEREFERENCE.ERROR.FORM\" : \"加载案例模型时出错。稍后再试一次\",\n    \"PROPERTY.CASEREFERENCE.CASE.LOADING\" : \"加载案例模型...\",\n    \"PROPERTY.CASEREFERENCE.CASE.EMPTY\" : \"此文件夹不包含任何案例模型\"\n}\n"
  },
  {
    "path": "flowable-ui-web/modeler/index.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>Flowable Modeler</title>\n    <link rel=\"icon\" type=\"image/ico\" href=\"favicon.ico\">\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    <meta name=\"theme-color\" content=\"#ffffff\">\n\n    <link rel=\"apple-touch-icon\" sizes=\"180x180\" href=\"images/apple-touch-icon.png?v=Om5N75Y123\">\n    <link rel=\"icon\" type=\"image/png\" href=\"images/favicon-32x32.png?v=Om5N75Y123\" sizes=\"32x32\">\n    <link rel=\"icon\" type=\"image/png\" href=\"images/favicon-16x16.png?v=Om5N75Y123\" sizes=\"16x16\">\n    <link rel=\"manifest\" href=\"manifest.json\">\n    <link rel=\"mask-icon\" href=\"images/safari-pinned-tab.svg?v=Om5N75Y123\" color=\"#506d75\">\n    <link rel=\"shortcut icon\" href=\"favicon.ico?v=Om5N75Y123\">\n    <link rel=\"Stylesheet\" href=\"libs/ui-grid_3.0.0/ui-grid.css\" type=\"text/css\"/>\n    <link rel=\"Stylesheet\" href=\"libs/handsontable_0.31.2/handsontable.full.min.css\" type=\"text/css\"/>\n\n    <!-- build:css styles/3thparty.css -->\n    <link rel=\"stylesheet\" href=\"libs/bootstrap_3.1.1/css/bootstrap.min.css\"/>\n    <link rel=\"stylesheet\" href=\"libs/bootstrap-tour_0.9.1/bootstrap-tour.min.css\"/>\n    <link rel=\"stylesheet\" href=\"libs/angular-spectrum-colorpicker_1.0.13/spectrum.css\"/>\n    <!-- endbuild -->\n\n    <link rel=\"Stylesheet\" media=\"screen\" href=\"editor-app/editor/css/editor.css?v=2\" type=\"text/css\"/>\n    <link rel=\"stylesheet\" href=\"editor-app/css/style.css?v=2\" type=\"text/css\"/>\n\n    <!-- build:css styles/style.css -->\n    <link href=\"styles/common/style.css\" rel=\"stylesheet\">\n    <link href=\"styles/common/style-retina.css\" rel=\"stylesheet\">\n    <link rel=\"stylesheet\" href=\"styles/style-editor.css\">\n    <!-- endbuild -->\n\n</head>\n<body ng-app=\"flowableModeler\" ng-cloak>\n\n    <div class=\"navbar navbar-fixed-top navbar-inverse\" role=\"navigation\" id=\"main-header\">\n        <div class=\"fixed-container\">\n            <div class=\"navbar-header\">\n                <a ng-click=\"backToLanding()\" class=\"landing-logo\" ng-if=\"account != null && account != undefined\" title=\"{{'GENERAL.MAIN-TITLE' | translate}}\">\n                    <img ng-src=\"{{appResourceRoot}}images/flowable-logo.png\" ng-srcset=\"{{appResourceRoot}}images/flowable-logo.png 1x, {{appResourceRoot}}images/flowable-logo@2x.png 2x\">\n                </a>\n                <ul class=\"nav navbar-nav\" id=\"main-nav\" ng-show=\"authenticated\">\n                    <li ng-class=\"{'active' : item.id == mainPage.id}\" ng-repeat=\"item in mainNavigation\">\n                        <a ng-click=\"setMainPage(item)\">{{item.title | translate}}</a>\n                    </li>\n                </ul>\n            </div>\n            <div class=\"pull-right {{currentAppDefinition.definition.theme}}\"\n                 ng-class=\"{'app-indicator': currentAppDefinition}\" ng-if=\"authenticated\" ng-cloack>\n                <span ng-if=\"currentAppDefinition.definition.theme\">\n                    {{currentAppDefinition.name}}\n                </span>\n                <i class=\"glyphicon {{currentAppDefinition.definition.icon}}\"></i>\n\n                <div class=\"dropdown btn-group btn-group-sm\" activiti-fix-dropdown-bug>\n                    <button type=\"button\" class=\"btn btn-default dropdown-toggle\" data-toggle=\"dropdown\">\n                    \t{{account.firstName && account.firstName != 'null' ? account.firstName : ''}} {{account.lastName && account.lastName != 'null' ? account.lastName : ''}}\n                        <span class=\"glyphicon glyphicon-chevron-down\" style=\"font-size: 10px\" aria-hidden=\"true\"></span>\n                    </button>\n                    <ul class=\"dropdown-menu pull-right\">\n                        <li><a href=\"\" ng-click=\"logout()\" translate>GENERAL.ACTION.LOGOUT</a></li>\n                    </ul>\n                </div>\n            </div>\n        </div>\n    </div>\n\n    <!--[if lt IE 9]>\n    <div class=\"unsupported-browser\">\n        <p class=\"alert error\">You are using an unsupported browser. Please upgrade your browser in order to use the\n            editor.</p>\n    </div>\n    <![endif]-->\n    <!--[if IE 9]>\n    <div id=\"no-flash-message\" class=\"unsupported-browser\" style=\"display: none\">\n        <p class=\"alert error\">No Adobe Flash installed. Please install Adobe Flash in order to use the file upload capabilities on this version of Internet Explorer.</p>\n    </div>\n    <script>\n        var hasFlash = false;\n        try {\n            hasFlash = Boolean(new ActiveXObject('ShockwaveFlash.ShockwaveFlash'));\n        } catch(exception) {\n            hasFlash = ('undefined' != typeof navigator.mimeTypes['application/x-shockwave-flash']);\n        }\n        if (!hasFlash) {\n            var showNoFlashMessage = function () {\n                var element = document.getElementById('no-flash-message');\n                element.style.display=\"block\";\n            };\n            showNoFlashMessage();\n        }\n    </script>\n    <![endif]-->\n    <div class=\"alert-wrapper\" ng-cloak>\n        <div class=\"alert fadein {{alerts.current.type}}\" ng-show=\"alerts.current\" ng-click=\"dismissAlert()\">\n            <i class=\"glyphicon\"\n               ng-class=\"{'glyphicon-ok': alerts.current.type == 'info', 'glyphicon-remove': alerts.current.type == 'error'}\"></i>\n            <span>{{alerts.current.message}}</span>\n\n            <div class=\"pull-right\" ng-show=\"alerts.queue.length > 0\">\n                <span class=\"badge\">{{alerts.queue.length + 1}}</span>\n            </div>\n        </div>\n    </div>\n\n    <div id=\"main\" class=\"wrapper full clearfix\" ng-view=\"\" ng-cloak ng-style=\"{height: window.height + 'px'}\">\n    </div>\n\n<!--[if lt IE 9]>\n<script src=\"libs/es5-shim-15.3.4.5/es5-shim.js\"></script>\n<script src=\"libs/json3_3.2.6/lib/json3.min.js\"></script>\n<![endif]-->\n\n<script src=\"libs/jquery_1.11.0/jquery.min.js\"></script>\n<script src=\"libs/jquery-ui-1.10.3.custom.min.js\"></script>\n\n<script src=\"libs/angular_1.3.13/angular.min.js\"></script>\n<script src=\"libs/angular-animate_1.3.13/angular-animate.min.js\"></script>\n<script src=\"libs/bootstrap_3.1.1/js/bootstrap.min.js\"></script>\n<script src=\"libs/angular-resource_1.3.13/angular-resource.min.js\"></script>\n<script src=\"libs/angular-cookies_1.3.13/angular-cookies.min.js\"></script>\n<script src=\"libs/angular-sanitize_1.3.13/angular-sanitize.min.js\"></script>\n<script src=\"libs/angular-route_1.3.13/angular-route.min.js\"></script>\n<script src=\"libs/angular-translate_2.15.1/angular-translate.min.js\"></script>\n<script src=\"libs/angular-translate-storage-cookie/angular-translate-storage-cookie.js\"></script>\n<script src=\"libs/angular-translate-loader-static-files/angular-translate-loader-static-files.js\"></script>\n<script src=\"libs/angular-strap_2.1.6/angular-strap.min.js\"></script>\n<script src=\"libs/angular-strap_2.1.6/angular-strap.tpl.min.js\"></script>\n<script src=\"libs/momentjs_2.18.1/momentjs.min.js\"></script>\n<script src=\"libs/bootstrap-tour_0.9.1/bootstrap-tour.min.js\"></script>\n<script src=\"libs/ng-file-upload/ng-file-upload-shim.min.js\"></script>\n<script src=\"libs/ng-file-upload/ng-file-upload.min.js\"></script>\n\n<script src=\"editor-app/libs/ui-utils.min-0.2.1.js\" type=\"text/javascript\"></script>\n<script src=\"libs/ui-grid_3.0.0/ui-grid.js\" type=\"text/javascript\"></script>\n<script src=\"libs/angular-dragdrop_1.0.11/angular-dragdrop.min.js\" type=\"text/javascript\"></script>\n<script src=\"editor-app/libs/mousetrap/1.6.0/mousetrap.min.js\" type=\"text/javascript\"></script>\n<script src=\"editor-app/libs/jquery.autogrow-textarea.js\" type=\"text/javascript\"></script>\n\n<script src=\"libs/handsontable_0.31.2/handsontable.full.min.js\" type=\"text/javascript\"></script>\n<script src=\"libs/ng-handsontable_0.13/ngHandsontable.js\" type=\"text/javascript\"></script>\n\n<script src=\"editor-app/libs/prototype-1.7.3.js\" type=\"text/javascript\"></script>\n<script src=\"editor-app/libs/path_parser.js\" type=\"text/javascript\"></script>\n\n<script src=\"libs/angular-spectrum-colorpicker_1.0.13/spectrum.js\" type=\"text/javascript\"></script>\n<script src=\"libs/angular-spectrum-colorpicker_1.0.13/angular-spectrum-colorpicker.min.js\" type=\"text/javascript\"></script>\n<script src=\"libs/angular-scroll_0.5.7/angular-scroll.min.js\" type=\"text/javascript\"></script>\n<script src=\"libs/angular-drag-and-drop-lists_1.2.0/angular-drag-and-drop-lists.js\" type=\"text/javascript\"></script>\n<script src=\"libs/html2canvas_0.4.1/html2canvas.js\"></script>\n\n<!-- Configuration -->\n<script src=\"scripts/app-cfg.js?v=2\"></script>\n\n<!-- build:js scripts/scripts.js -->\n<script src=\"editor-app/editor/i18n/translation_en_us.js\" type=\"text/javascript\"></script>\n<script src=\"editor-app/editor/i18n/translation_signavio_en_us.js\" type=\"text/javascript\"></script>\n<script src=\"editor-app/editor/oryx.debug.js\" type=\"text/javascript\"></script>\n\n<script src=\"scripts/app.js\"></script>\n<script src=\"scripts/configuration/url-config.js\"></script>\n<script src=\"scripts/editor-directives.js\"></script>\n<script src=\"scripts/controllers/processes.js\"></script>\n<script src=\"scripts/controllers/process.js\"></script>\n<script src=\"scripts/controllers/casemodels.js\"></script>\n<script src=\"scripts/controllers/casemodel.js\"></script>\n<script src=\"scripts/controllers/forms.js\"></script>\n<script src=\"scripts/controllers/form.js\"></script>\n<script src=\"scripts/controllers/decision-tables.js\"></script>\n<script src=\"scripts/controllers/decision-table.js\"></script>\n<script src=\"scripts/controllers/app-definitions.js\"></script>\n<script src=\"scripts/controllers/app-definition.js\"></script>\n<script src=\"scripts/controllers/model-common-actions.js\"></script>\n\n<script src=\"scripts/services/util-services.js\"></script>\n<script src=\"scripts/services/identity-services.js\"></script>\n\n<script src=\"scripts/services/form-services.js\"></script>\n<script src=\"scripts/controllers/form-builder.js\"></script>\n<script src=\"scripts/configuration/form-builder-toolbar-default-actions.js\" type=\"text/javascript\"></script>\n<script src=\"scripts/configuration/form-builder-toolbar.js\" type=\"text/javascript\"></script>\n<script src=\"scripts/controllers/form-toolbar-controller.js\" type=\"text/javascript\"></script>\n<script src=\"scripts/controllers/form-readonly-view.js\"></script>\n\n<script src=\"scripts/services/decision-table-service.js\"></script>\n<script src=\"scripts/controllers/decision-table-editor.js\"></script>\n<script src=\"scripts/configuration/decision-table-toolbar-default-actions.js\" type=\"text/javascript\"></script>\n<script src=\"scripts/configuration/decision-table-toolbar.js\" type=\"text/javascript\"></script>\n<script src=\"scripts/controllers/decision-table-toolbar-controller.js\" type=\"text/javascript\"></script>\n\n<script src=\"scripts/controllers/app-definition-builder.js\"></script>\n<script src=\"scripts/configuration/app-definition-toolbar-default-actions.js\" type=\"text/javascript\"></script>\n<script src=\"scripts/configuration/app-definition-toolbar.js\" type=\"text/javascript\"></script>\n<script src=\"scripts/controllers/app-definition-toolbar-controller.js\" type=\"text/javascript\"></script>\n\n<script src=\"editor-app/eventbus.js\" type=\"text/javascript\"></script>\n\n<script src=\"editor-app/editor-controller.js\" type=\"text/javascript\"></script>\n<script src=\"editor-app/stencil-controller.js\" type=\"text/javascript\"></script>\n<script src=\"editor-app/toolbar-controller.js\" type=\"text/javascript\"></script>\n<script src=\"editor-app/header-controller.js\" type=\"text/javascript\"></script>\n<script src=\"editor-app/select-shape-controller.js\" type=\"text/javascript\"></script>\n<script src=\"editor-app/define-data-controller.js\" type=\"text/javascript\"></script>\n<script src=\"editor-app/process-navigator-controller.js\" type=\"text/javascript\"></script>\n<script src=\"editor-app/editormanager.js\" type=\"text/javascript\"></script>\n\n<script src=\"editor-app/tour.js\" type=\"text/javascript\"></script>\n<script src=\"editor-app/editor-utils.js\" type=\"text/javascript\"></script>\n<script src=\"editor-app/configuration/toolbar-default-actions.js\" type=\"text/javascript\"></script>\n\n<script src=\"editor-app/configuration/properties-data-properties-controller.js\" type=\"text/javascript\"></script>\n<script src=\"editor-app/configuration/properties-default-controllers.js\" type=\"text/javascript\"></script>\n<script src=\"editor-app/configuration/properties-execution-listeners-controller.js\" type=\"text/javascript\"></script>\n<script src=\"editor-app/configuration/properties-event-listeners-controller.js\" type=\"text/javascript\"></script>\n<script src=\"editor-app/configuration/properties-assignment-controller.js\" type=\"text/javascript\"></script>\n<script src=\"editor-app/configuration/properties-fields-controller.js\" type=\"text/javascript\"></script>\n<script src=\"editor-app/configuration/properties-form-properties-controller.js\" type=\"text/javascript\"></script>\n<script src=\"editor-app/configuration/properties-in-parameters-controller.js\" type=\"text/javascript\"></script>\n<script src=\"editor-app/configuration/properties-calledelementtype-controller.js\" type=\"text/javascript\"></script>\n<script src=\"editor-app/configuration/properties-multiinstance-controller.js\" type=\"text/javascript\"></script>\n<script src=\"editor-app/configuration/properties-process-historylevel-controller.js\" type=\"text/javascript\"></script>\n<script src=\"editor-app/configuration/properties-ordering-controller.js\" type=\"text/javascript\"></script>\n<script src=\"editor-app/configuration/properties-out-parameters-controller.js\" type=\"text/javascript\"></script>\n<script src=\"editor-app/configuration/properties-task-listeners-controller.js\" type=\"text/javascript\"></script>\n<script src=\"editor-app/configuration/properties-form-reference-controller.js\" type=\"text/javascript\"></script>\n<script src=\"editor-app/configuration/properties-sequenceflow-order-controller.js\" type=\"text/javascript\"></script>\n<script src=\"editor-app/configuration/properties-condition-expression-controller.js\" type=\"text/javascript\"></script>\n<script src=\"editor-app/configuration/properties-signal-definitions-controller.js\" type=\"text/javascript\"></script>\n<script src=\"editor-app/configuration/properties-signal-scope-controller.js\" type=\"text/javascript\"></script>\n<script src=\"editor-app/configuration/properties-message-definitions-controller.js\" type=\"text/javascript\"></script>\n<script src=\"editor-app/configuration/properties-message-scope-controller.js\" type=\"text/javascript\"></script>\n<script src=\"editor-app/configuration/properties-duedate-controller.js\" type=\"text/javascript\"></script>\n<script src=\"editor-app/configuration/properties-decisiontable-reference-controller.js\" type=\"text/javascript\"></script>\n<script src=\"editor-app/configuration/properties-case-reference-controller.js\" type=\"text/javascript\"></script>\n<script src=\"editor-app/configuration/properties-process-reference-controller.js\" type=\"text/javascript\"></script>\n<script src=\"editor-app/configuration/properties-transition-event-controller.js\" type=\"text/javascript\"></script>\n<script src=\"editor-app/configuration/properties-trigger-mode-controller.js\" type=\"text/javascript\"></script>\n<script src=\"editor-app/configuration/properties-planitem-dropdown-controller.js\" type=\"text/javascript\"></script>\n<script src=\"editor-app/configuration/properties-plan-item-lifecycle-listeners-controller.js\" type=\"text/javascript\"></script>\n<script src=\"editor-app/configuration/properties-httprequest-controller.js\" type=\"text/javascript\"></script>\n\n<script src=\"editor-app/editor-config.js\" type=\"text/javascript\"></script>\n\n<script src=\"editor-app/configuration/url-config.js\" type=\"text/javascript\"></script>\n\n<script src=\"editor-app/configuration/toolbar.js\" type=\"text/javascript\"></script>\n<script src=\"editor-app/configuration/toolbar-custom-actions.js\" type=\"text/javascript\"></script>\n\n<script src=\"editor-app/configuration/properties.js\" type=\"text/javascript\"></script>\n<script src=\"editor-app/configuration/properties-custom-controllers.js\" type=\"text/javascript\"></script>\n\n<script src=\"editor-app/configuration/flowable-header-custom.js\" type=\"text/javascript\"></script>\n<script src=\"editor-app/configuration/flowable-toolbar-custom-actions.js\" type=\"text/javascript\"></script>\n\n<script src=\"scripts/common/directives.js\"></script>\n<script src=\"scripts/common/providers-config.js\"></script>\n<script src=\"scripts/common/services/resource-service.js\"></script>\n<script src=\"scripts/common/services/recursion-helper.js\"></script>\n<script src=\"scripts/common/controllers/about.js\"></script>\n<!-- endbuild -->\n\n<!-- Integration extensions -->\n<script src=\"scripts/resource-loader.js?v=2\" app=\"editor\"></script>\n\n</body>\n</html>\n"
  },
  {
    "path": "flowable-ui-web/modeler/libs/angular-animate_1.3.13/angular-animate.js",
    "content": "/**\n * @license AngularJS v1.3.13\n * (c) 2010-2014 Google, Inc. http://angularjs.org\n * License: MIT\n */\n(function(window, angular, undefined) {'use strict';\n\n/* jshint maxlen: false */\n\n/**\n * @ngdoc module\n * @name ngAnimate\n * @description\n *\n * The `ngAnimate` module provides support for JavaScript, CSS3 transition and CSS3 keyframe animation hooks within existing core and custom directives.\n *\n * <div doc-module-components=\"ngAnimate\"></div>\n *\n * # Usage\n *\n * To see animations in action, all that is required is to define the appropriate CSS classes\n * or to register a JavaScript animation via the `myModule.animation()` function. The directives that support animation automatically are:\n * `ngRepeat`, `ngInclude`, `ngIf`, `ngSwitch`, `ngShow`, `ngHide`, `ngView` and `ngClass`. Custom directives can take advantage of animation\n * by using the `$animate` service.\n *\n * Below is a more detailed breakdown of the supported animation events provided by pre-existing ng directives:\n *\n * | Directive                                                                                                | Supported Animations                                                     |\n * |----------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------|\n * | {@link ng.directive:ngRepeat#animations ngRepeat}                                                        | enter, leave and move                                                    |\n * | {@link ngRoute.directive:ngView#animations ngView}                                                       | enter and leave                                                          |\n * | {@link ng.directive:ngInclude#animations ngInclude}                                                      | enter and leave                                                          |\n * | {@link ng.directive:ngSwitch#animations ngSwitch}                                                        | enter and leave                                                          |\n * | {@link ng.directive:ngIf#animations ngIf}                                                                | enter and leave                                                          |\n * | {@link ng.directive:ngClass#animations ngClass}                                                          | add and remove (the CSS class(es) present)                               |\n * | {@link ng.directive:ngShow#animations ngShow} & {@link ng.directive:ngHide#animations ngHide}            | add and remove (the ng-hide class value)                                 |\n * | {@link ng.directive:form#animation-hooks form} & {@link ng.directive:ngModel#animation-hooks ngModel}    | add and remove (dirty, pristine, valid, invalid & all other validations) |\n * | {@link module:ngMessages#animations ngMessages}                                                          | add and remove (ng-active & ng-inactive)                                 |\n * | {@link module:ngMessages#animations ngMessage}                                                           | enter and leave                                                          |\n *\n * You can find out more information about animations upon visiting each directive page.\n *\n * Below is an example of how to apply animations to a directive that supports animation hooks:\n *\n * ```html\n * <style type=\"text/css\">\n * .slide.ng-enter, .slide.ng-leave {\n *   -webkit-transition:0.5s linear all;\n *   transition:0.5s linear all;\n * }\n *\n * .slide.ng-enter { }        /&#42; starting animations for enter &#42;/\n * .slide.ng-enter.ng-enter-active { } /&#42; terminal animations for enter &#42;/\n * .slide.ng-leave { }        /&#42; starting animations for leave &#42;/\n * .slide.ng-leave.ng-leave-active { } /&#42; terminal animations for leave &#42;/\n * </style>\n *\n * <!--\n * the animate service will automatically add .ng-enter and .ng-leave to the element\n * to trigger the CSS transition/animations\n * -->\n * <ANY class=\"slide\" ng-include=\"...\"></ANY>\n * ```\n *\n * Keep in mind that, by default, if an animation is running, any child elements cannot be animated\n * until the parent element's animation has completed. This blocking feature can be overridden by\n * placing the `ng-animate-children` attribute on a parent container tag.\n *\n * ```html\n * <div class=\"slide-animation\" ng-if=\"on\" ng-animate-children>\n *   <div class=\"fade-animation\" ng-if=\"on\">\n *     <div class=\"explode-animation\" ng-if=\"on\">\n *        ...\n *     </div>\n *   </div>\n * </div>\n * ```\n *\n * When the `on` expression value changes and an animation is triggered then each of the elements within\n * will all animate without the block being applied to child elements.\n *\n * ## Are animations run when the application starts?\n * No they are not. When an application is bootstrapped Angular will disable animations from running to avoid\n * a frenzy of animations from being triggered as soon as the browser has rendered the screen. For this to work,\n * Angular will wait for two digest cycles until enabling animations. From there on, any animation-triggering\n * layout changes in the application will trigger animations as normal.\n *\n * In addition, upon bootstrap, if the routing system or any directives or load remote data (via $http) then Angular\n * will automatically extend the wait time to enable animations once **all** of the outbound HTTP requests\n * are complete.\n *\n * ## CSS-defined Animations\n * The animate service will automatically apply two CSS classes to the animated element and these two CSS classes\n * are designed to contain the start and end CSS styling. Both CSS transitions and keyframe animations are supported\n * and can be used to play along with this naming structure.\n *\n * The following code below demonstrates how to perform animations using **CSS transitions** with Angular:\n *\n * ```html\n * <style type=\"text/css\">\n * /&#42;\n *  The animate class is apart of the element and the ng-enter class\n *  is attached to the element once the enter animation event is triggered\n * &#42;/\n * .reveal-animation.ng-enter {\n *  -webkit-transition: 1s linear all; /&#42; Safari/Chrome &#42;/\n *  transition: 1s linear all; /&#42; All other modern browsers and IE10+ &#42;/\n *\n *  /&#42; The animation preparation code &#42;/\n *  opacity: 0;\n * }\n *\n * /&#42;\n *  Keep in mind that you want to combine both CSS\n *  classes together to avoid any CSS-specificity\n *  conflicts\n * &#42;/\n * .reveal-animation.ng-enter.ng-enter-active {\n *  /&#42; The animation code itself &#42;/\n *  opacity: 1;\n * }\n * </style>\n *\n * <div class=\"view-container\">\n *   <div ng-view class=\"reveal-animation\"></div>\n * </div>\n * ```\n *\n * The following code below demonstrates how to perform animations using **CSS animations** with Angular:\n *\n * ```html\n * <style type=\"text/css\">\n * .reveal-animation.ng-enter {\n *   -webkit-animation: enter_sequence 1s linear; /&#42; Safari/Chrome &#42;/\n *   animation: enter_sequence 1s linear; /&#42; IE10+ and Future Browsers &#42;/\n * }\n * @-webkit-keyframes enter_sequence {\n *   from { opacity:0; }\n *   to { opacity:1; }\n * }\n * @keyframes enter_sequence {\n *   from { opacity:0; }\n *   to { opacity:1; }\n * }\n * </style>\n *\n * <div class=\"view-container\">\n *   <div ng-view class=\"reveal-animation\"></div>\n * </div>\n * ```\n *\n * Both CSS3 animations and transitions can be used together and the animate service will figure out the correct duration and delay timing.\n *\n * Upon DOM mutation, the event class is added first (something like `ng-enter`), then the browser prepares itself to add\n * the active class (in this case `ng-enter-active`) which then triggers the animation. The animation module will automatically\n * detect the CSS code to determine when the animation ends. Once the animation is over then both CSS classes will be\n * removed from the DOM. If a browser does not support CSS transitions or CSS animations then the animation will start and end\n * immediately resulting in a DOM element that is at its final state. This final state is when the DOM element\n * has no CSS transition/animation classes applied to it.\n *\n * ### Structural transition animations\n *\n * Structural transitions (such as enter, leave and move) will always apply a `0s none` transition\n * value to force the browser into rendering the styles defined in the setup (`.ng-enter`, `.ng-leave`\n * or `.ng-move`) class. This means that any active transition animations operating on the element\n * will be cut off to make way for the enter, leave or move animation.\n *\n * ### Class-based transition animations\n *\n * Class-based transitions refer to transition animations that are triggered when a CSS class is\n * added to or removed from the element (via `$animate.addClass`, `$animate.removeClass`,\n * `$animate.setClass`, or by directives such as `ngClass`, `ngModel` and `form`).\n * They are different when compared to structural animations since they **do not cancel existing\n * animations** nor do they **block successive transitions** from rendering on the same element.\n * This distinction allows for **multiple class-based transitions** to be performed on the same element.\n *\n * In addition to ngAnimate supporting the default (natural) functionality of class-based transition\n * animations, ngAnimate also decorates the element with starting and ending CSS classes to aid the\n * developer in further styling the element throughout the transition animation. Earlier versions\n * of ngAnimate may have caused natural CSS transitions to break and not render properly due to\n * $animate temporarily blocking transitions using `0s none` in order to allow the setup CSS class\n * (the `-add` or `-remove` class) to be applied without triggering an animation. However, as of\n * **version 1.3**, this workaround has been removed with ngAnimate and all non-ngAnimate CSS\n * class transitions are compatible with ngAnimate.\n *\n * There is, however, one special case when dealing with class-based transitions in ngAnimate.\n * When rendering class-based transitions that make use of the setup and active CSS classes\n * (e.g. `.fade-add` and `.fade-add-active` for when `.fade` is added) be sure to define\n * the transition value **on the active CSS class** and not the setup class.\n *\n * ```css\n * .fade-add {\n *   /&#42; remember to place a 0s transition here\n *      to ensure that the styles are applied instantly\n *      even if the element already has a transition style &#42;/\n *   transition:0s linear all;\n *\n *   /&#42; starting CSS styles &#42;/\n *   opacity:1;\n * }\n * .fade-add.fade-add-active {\n *   /&#42; this will be the length of the animation &#42;/\n *   transition:1s linear all;\n *   opacity:0;\n * }\n * ```\n *\n * The setup CSS class (in this case `.fade-add`) also has a transition style property, however, it\n * has a duration of zero. This may not be required, however, incase the browser is unable to render\n * the styling present in this CSS class instantly then it could be that the browser is attempting\n * to perform an unnecessary transition.\n *\n * This workaround, however, does not apply to  standard class-based transitions that are rendered\n * when a CSS class containing a transition is applied to an element:\n *\n * ```css\n * /&#42; this works as expected &#42;/\n * .fade {\n *   transition:1s linear all;\n *   opacity:0;\n * }\n * ```\n *\n * Please keep this in mind when coding the CSS markup that will be used within class-based transitions.\n * Also, try not to mix the two class-based animation flavors together since the CSS code may become\n * overly complex.\n *\n *\n * ### Preventing Collisions With Third Party Libraries\n *\n * Some third-party frameworks place animation duration defaults across many element or className\n * selectors in order to make their code small and reuseable. This can lead to issues with ngAnimate, which\n * is expecting actual animations on these elements and has to wait for their completion.\n *\n * You can prevent this unwanted behavior by using a prefix on all your animation classes:\n *\n * ```css\n * /&#42; prefixed with animate- &#42;/\n * .animate-fade-add.animate-fade-add-active {\n *   transition:1s linear all;\n *   opacity:0;\n * }\n * ```\n *\n * You then configure `$animate` to enforce this prefix:\n *\n * ```js\n * $animateProvider.classNameFilter(/animate-/);\n * ```\n * </div>\n *\n * ### CSS Staggering Animations\n * A Staggering animation is a collection of animations that are issued with a slight delay in between each successive operation resulting in a\n * curtain-like effect. The ngAnimate module (versions >=1.2) supports staggering animations and the stagger effect can be\n * performed by creating a **ng-EVENT-stagger** CSS class and attaching that class to the base CSS class used for\n * the animation. The style property expected within the stagger class can either be a **transition-delay** or an\n * **animation-delay** property (or both if your animation contains both transitions and keyframe animations).\n *\n * ```css\n * .my-animation.ng-enter {\n *   /&#42; standard transition code &#42;/\n *   -webkit-transition: 1s linear all;\n *   transition: 1s linear all;\n *   opacity:0;\n * }\n * .my-animation.ng-enter-stagger {\n *   /&#42; this will have a 100ms delay between each successive leave animation &#42;/\n *   -webkit-transition-delay: 0.1s;\n *   transition-delay: 0.1s;\n *\n *   /&#42; in case the stagger doesn't work then these two values\n *    must be set to 0 to avoid an accidental CSS inheritance &#42;/\n *   -webkit-transition-duration: 0s;\n *   transition-duration: 0s;\n * }\n * .my-animation.ng-enter.ng-enter-active {\n *   /&#42; standard transition styles &#42;/\n *   opacity:1;\n * }\n * ```\n *\n * Staggering animations work by default in ngRepeat (so long as the CSS class is defined). Outside of ngRepeat, to use staggering animations\n * on your own, they can be triggered by firing multiple calls to the same event on $animate. However, the restrictions surrounding this\n * are that each of the elements must have the same CSS className value as well as the same parent element. A stagger operation\n * will also be reset if more than 10ms has passed after the last animation has been fired.\n *\n * The following code will issue the **ng-leave-stagger** event on the element provided:\n *\n * ```js\n * var kids = parent.children();\n *\n * $animate.leave(kids[0]); //stagger index=0\n * $animate.leave(kids[1]); //stagger index=1\n * $animate.leave(kids[2]); //stagger index=2\n * $animate.leave(kids[3]); //stagger index=3\n * $animate.leave(kids[4]); //stagger index=4\n *\n * $timeout(function() {\n *   //stagger has reset itself\n *   $animate.leave(kids[5]); //stagger index=0\n *   $animate.leave(kids[6]); //stagger index=1\n * }, 100, false);\n * ```\n *\n * Stagger animations are currently only supported within CSS-defined animations.\n *\n * ## JavaScript-defined Animations\n * In the event that you do not want to use CSS3 transitions or CSS3 animations or if you wish to offer animations on browsers that do not\n * yet support CSS transitions/animations, then you can make use of JavaScript animations defined inside of your AngularJS module.\n *\n * ```js\n * //!annotate=\"YourApp\" Your AngularJS Module|Replace this or ngModule with the module that you used to define your application.\n * var ngModule = angular.module('YourApp', ['ngAnimate']);\n * ngModule.animation('.my-crazy-animation', function() {\n *   return {\n *     enter: function(element, done) {\n *       //run the animation here and call done when the animation is complete\n *       return function(cancelled) {\n *         //this (optional) function will be called when the animation\n *         //completes or when the animation is cancelled (the cancelled\n *         //flag will be set to true if cancelled).\n *       };\n *     },\n *     leave: function(element, done) { },\n *     move: function(element, done) { },\n *\n *     //animation that can be triggered before the class is added\n *     beforeAddClass: function(element, className, done) { },\n *\n *     //animation that can be triggered after the class is added\n *     addClass: function(element, className, done) { },\n *\n *     //animation that can be triggered before the class is removed\n *     beforeRemoveClass: function(element, className, done) { },\n *\n *     //animation that can be triggered after the class is removed\n *     removeClass: function(element, className, done) { }\n *   };\n * });\n * ```\n *\n * JavaScript-defined animations are created with a CSS-like class selector and a collection of events which are set to run\n * a javascript callback function. When an animation is triggered, $animate will look for a matching animation which fits\n * the element's CSS class attribute value and then run the matching animation event function (if found).\n * In other words, if the CSS classes present on the animated element match any of the JavaScript animations then the callback function will\n * be executed. It should be also noted that only simple, single class selectors are allowed (compound class selectors are not supported).\n *\n * Within a JavaScript animation, an object containing various event callback animation functions is expected to be returned.\n * As explained above, these callbacks are triggered based on the animation event. Therefore if an enter animation is run,\n * and the JavaScript animation is found, then the enter callback will handle that animation (in addition to the CSS keyframe animation\n * or transition code that is defined via a stylesheet).\n *\n *\n * ### Applying Directive-specific Styles to an Animation\n * In some cases a directive or service may want to provide `$animate` with extra details that the animation will\n * include into its animation. Let's say for example we wanted to render an animation that animates an element\n * towards the mouse coordinates as to where the user clicked last. By collecting the X/Y coordinates of the click\n * (via the event parameter) we can set the `top` and `left` styles into an object and pass that into our function\n * call to `$animate.addClass`.\n *\n * ```js\n * canvas.on('click', function(e) {\n *   $animate.addClass(element, 'on', {\n *     to: {\n *       left : e.client.x + 'px',\n *       top : e.client.y + 'px'\n *     }\n *   }):\n * });\n * ```\n *\n * Now when the animation runs, and a transition or keyframe animation is picked up, then the animation itself will\n * also include and transition the styling of the `left` and `top` properties into its running animation. If we want\n * to provide some starting animation values then we can do so by placing the starting animations styles into an object\n * called `from` in the same object as the `to` animations.\n *\n * ```js\n * canvas.on('click', function(e) {\n *   $animate.addClass(element, 'on', {\n *     from: {\n *        position: 'absolute',\n *        left: '0px',\n *        top: '0px'\n *     },\n *     to: {\n *       left : e.client.x + 'px',\n *       top : e.client.y + 'px'\n *     }\n *   }):\n * });\n * ```\n *\n * Once the animation is complete or cancelled then the union of both the before and after styles are applied to the\n * element. If `ngAnimate` is not present then the styles will be applied immediately.\n *\n */\n\nangular.module('ngAnimate', ['ng'])\n\n  /**\n   * @ngdoc provider\n   * @name $animateProvider\n   * @description\n   *\n   * The `$animateProvider` allows developers to register JavaScript animation event handlers directly inside of a module.\n   * When an animation is triggered, the $animate service will query the $animate service to find any animations that match\n   * the provided name value.\n   *\n   * Requires the {@link ngAnimate `ngAnimate`} module to be installed.\n   *\n   * Please visit the {@link ngAnimate `ngAnimate`} module overview page learn more about how to use animations in your application.\n   *\n   */\n  .directive('ngAnimateChildren', function() {\n    var NG_ANIMATE_CHILDREN = '$$ngAnimateChildren';\n    return function(scope, element, attrs) {\n      var val = attrs.ngAnimateChildren;\n      if (angular.isString(val) && val.length === 0) { //empty attribute\n        element.data(NG_ANIMATE_CHILDREN, true);\n      } else {\n        scope.$watch(val, function(value) {\n          element.data(NG_ANIMATE_CHILDREN, !!value);\n        });\n      }\n    };\n  })\n\n  //this private service is only used within CSS-enabled animations\n  //IE8 + IE9 do not support rAF natively, but that is fine since they\n  //also don't support transitions and keyframes which means that the code\n  //below will never be used by the two browsers.\n  .factory('$$animateReflow', ['$$rAF', '$document', function($$rAF, $document) {\n    var bod = $document[0].body;\n    return function(fn) {\n      //the returned function acts as the cancellation function\n      return $$rAF(function() {\n        //the line below will force the browser to perform a repaint\n        //so that all the animated elements within the animation frame\n        //will be properly updated and drawn on screen. This is\n        //required to perform multi-class CSS based animations with\n        //Firefox. DO NOT REMOVE THIS LINE.\n        var a = bod.offsetWidth + 1;\n        fn();\n      });\n    };\n  }])\n\n  .config(['$provide', '$animateProvider', function($provide, $animateProvider) {\n    var noop = angular.noop;\n    var forEach = angular.forEach;\n    var selectors = $animateProvider.$$selectors;\n    var isArray = angular.isArray;\n    var isString = angular.isString;\n    var isObject = angular.isObject;\n\n    var ELEMENT_NODE = 1;\n    var NG_ANIMATE_STATE = '$$ngAnimateState';\n    var NG_ANIMATE_CHILDREN = '$$ngAnimateChildren';\n    var NG_ANIMATE_CLASS_NAME = 'ng-animate';\n    var rootAnimateState = {running: true};\n\n    function extractElementNode(element) {\n      for (var i = 0; i < element.length; i++) {\n        var elm = element[i];\n        if (elm.nodeType == ELEMENT_NODE) {\n          return elm;\n        }\n      }\n    }\n\n    function prepareElement(element) {\n      return element && angular.element(element);\n    }\n\n    function stripCommentsFromElement(element) {\n      return angular.element(extractElementNode(element));\n    }\n\n    function isMatchingElement(elm1, elm2) {\n      return extractElementNode(elm1) == extractElementNode(elm2);\n    }\n    var $$jqLite;\n    $provide.decorator('$animate',\n        ['$delegate', '$$q', '$injector', '$sniffer', '$rootElement', '$$asyncCallback', '$rootScope', '$document', '$templateRequest', '$$jqLite',\n function($delegate,   $$q,   $injector,   $sniffer,   $rootElement,   $$asyncCallback,   $rootScope,   $document,   $templateRequest,   $$$jqLite) {\n\n      $$jqLite = $$$jqLite;\n      $rootElement.data(NG_ANIMATE_STATE, rootAnimateState);\n\n      // Wait until all directive and route-related templates are downloaded and\n      // compiled. The $templateRequest.totalPendingRequests variable keeps track of\n      // all of the remote templates being currently downloaded. If there are no\n      // templates currently downloading then the watcher will still fire anyway.\n      var deregisterWatch = $rootScope.$watch(\n        function() { return $templateRequest.totalPendingRequests; },\n        function(val, oldVal) {\n          if (val !== 0) return;\n          deregisterWatch();\n\n          // Now that all templates have been downloaded, $animate will wait until\n          // the post digest queue is empty before enabling animations. By having two\n          // calls to $postDigest calls we can ensure that the flag is enabled at the\n          // very end of the post digest queue. Since all of the animations in $animate\n          // use $postDigest, it's important that the code below executes at the end.\n          // This basically means that the page is fully downloaded and compiled before\n          // any animations are triggered.\n          $rootScope.$$postDigest(function() {\n            $rootScope.$$postDigest(function() {\n              rootAnimateState.running = false;\n            });\n          });\n        }\n      );\n\n      var globalAnimationCounter = 0;\n      var classNameFilter = $animateProvider.classNameFilter();\n      var isAnimatableClassName = !classNameFilter\n              ? function() { return true; }\n              : function(className) {\n                return classNameFilter.test(className);\n              };\n\n      function classBasedAnimationsBlocked(element, setter) {\n        var data = element.data(NG_ANIMATE_STATE) || {};\n        if (setter) {\n          data.running = true;\n          data.structural = true;\n          element.data(NG_ANIMATE_STATE, data);\n        }\n        return data.disabled || (data.running && data.structural);\n      }\n\n      function runAnimationPostDigest(fn) {\n        var cancelFn, defer = $$q.defer();\n        defer.promise.$$cancelFn = function() {\n          cancelFn && cancelFn();\n        };\n        $rootScope.$$postDigest(function() {\n          cancelFn = fn(function() {\n            defer.resolve();\n          });\n        });\n        return defer.promise;\n      }\n\n      function parseAnimateOptions(options) {\n        // some plugin code may still be passing in the callback\n        // function as the last param for the $animate methods so\n        // it's best to only allow string or array values for now\n        if (isObject(options)) {\n          if (options.tempClasses && isString(options.tempClasses)) {\n            options.tempClasses = options.tempClasses.split(/\\s+/);\n          }\n          return options;\n        }\n      }\n\n      function resolveElementClasses(element, cache, runningAnimations) {\n        runningAnimations = runningAnimations || {};\n\n        var lookup = {};\n        forEach(runningAnimations, function(data, selector) {\n          forEach(selector.split(' '), function(s) {\n            lookup[s]=data;\n          });\n        });\n\n        var hasClasses = Object.create(null);\n        forEach((element.attr('class') || '').split(/\\s+/), function(className) {\n          hasClasses[className] = true;\n        });\n\n        var toAdd = [], toRemove = [];\n        forEach((cache && cache.classes) || [], function(status, className) {\n          var hasClass = hasClasses[className];\n          var matchingAnimation = lookup[className] || {};\n\n          // When addClass and removeClass is called then $animate will check to\n          // see if addClass and removeClass cancel each other out. When there are\n          // more calls to removeClass than addClass then the count falls below 0\n          // and then the removeClass animation will be allowed. Otherwise if the\n          // count is above 0 then that means an addClass animation will commence.\n          // Once an animation is allowed then the code will also check to see if\n          // there exists any on-going animation that is already adding or remvoing\n          // the matching CSS class.\n          if (status === false) {\n            //does it have the class or will it have the class\n            if (hasClass || matchingAnimation.event == 'addClass') {\n              toRemove.push(className);\n            }\n          } else if (status === true) {\n            //is the class missing or will it be removed?\n            if (!hasClass || matchingAnimation.event == 'removeClass') {\n              toAdd.push(className);\n            }\n          }\n        });\n\n        return (toAdd.length + toRemove.length) > 0 && [toAdd.join(' '), toRemove.join(' ')];\n      }\n\n      function lookup(name) {\n        if (name) {\n          var matches = [],\n              flagMap = {},\n              classes = name.substr(1).split('.');\n\n          //the empty string value is the default animation\n          //operation which performs CSS transition and keyframe\n          //animations sniffing. This is always included for each\n          //element animation procedure if the browser supports\n          //transitions and/or keyframe animations. The default\n          //animation is added to the top of the list to prevent\n          //any previous animations from affecting the element styling\n          //prior to the element being animated.\n          if ($sniffer.transitions || $sniffer.animations) {\n            matches.push($injector.get(selectors['']));\n          }\n\n          for (var i=0; i < classes.length; i++) {\n            var klass = classes[i],\n                selectorFactoryName = selectors[klass];\n            if (selectorFactoryName && !flagMap[klass]) {\n              matches.push($injector.get(selectorFactoryName));\n              flagMap[klass] = true;\n            }\n          }\n          return matches;\n        }\n      }\n\n      function animationRunner(element, animationEvent, className, options) {\n        //transcluded directives may sometimes fire an animation using only comment nodes\n        //best to catch this early on to prevent any animation operations from occurring\n        var node = element[0];\n        if (!node) {\n          return;\n        }\n\n        if (options) {\n          options.to = options.to || {};\n          options.from = options.from || {};\n        }\n\n        var classNameAdd;\n        var classNameRemove;\n        if (isArray(className)) {\n          classNameAdd = className[0];\n          classNameRemove = className[1];\n          if (!classNameAdd) {\n            className = classNameRemove;\n            animationEvent = 'removeClass';\n          } else if (!classNameRemove) {\n            className = classNameAdd;\n            animationEvent = 'addClass';\n          } else {\n            className = classNameAdd + ' ' + classNameRemove;\n          }\n        }\n\n        var isSetClassOperation = animationEvent == 'setClass';\n        var isClassBased = isSetClassOperation\n                           || animationEvent == 'addClass'\n                           || animationEvent == 'removeClass'\n                           || animationEvent == 'animate';\n\n        var currentClassName = element.attr('class');\n        var classes = currentClassName + ' ' + className;\n        if (!isAnimatableClassName(classes)) {\n          return;\n        }\n\n        var beforeComplete = noop,\n            beforeCancel = [],\n            before = [],\n            afterComplete = noop,\n            afterCancel = [],\n            after = [];\n\n        var animationLookup = (' ' + classes).replace(/\\s+/g,'.');\n        forEach(lookup(animationLookup), function(animationFactory) {\n          var created = registerAnimation(animationFactory, animationEvent);\n          if (!created && isSetClassOperation) {\n            registerAnimation(animationFactory, 'addClass');\n            registerAnimation(animationFactory, 'removeClass');\n          }\n        });\n\n        function registerAnimation(animationFactory, event) {\n          var afterFn = animationFactory[event];\n          var beforeFn = animationFactory['before' + event.charAt(0).toUpperCase() + event.substr(1)];\n          if (afterFn || beforeFn) {\n            if (event == 'leave') {\n              beforeFn = afterFn;\n              //when set as null then animation knows to skip this phase\n              afterFn = null;\n            }\n            after.push({\n              event: event, fn: afterFn\n            });\n            before.push({\n              event: event, fn: beforeFn\n            });\n            return true;\n          }\n        }\n\n        function run(fns, cancellations, allCompleteFn) {\n          var animations = [];\n          forEach(fns, function(animation) {\n            animation.fn && animations.push(animation);\n          });\n\n          var count = 0;\n          function afterAnimationComplete(index) {\n            if (cancellations) {\n              (cancellations[index] || noop)();\n              if (++count < animations.length) return;\n              cancellations = null;\n            }\n            allCompleteFn();\n          }\n\n          //The code below adds directly to the array in order to work with\n          //both sync and async animations. Sync animations are when the done()\n          //operation is called right away. DO NOT REFACTOR!\n          forEach(animations, function(animation, index) {\n            var progress = function() {\n              afterAnimationComplete(index);\n            };\n            switch (animation.event) {\n              case 'setClass':\n                cancellations.push(animation.fn(element, classNameAdd, classNameRemove, progress, options));\n                break;\n              case 'animate':\n                cancellations.push(animation.fn(element, className, options.from, options.to, progress));\n                break;\n              case 'addClass':\n                cancellations.push(animation.fn(element, classNameAdd || className,     progress, options));\n                break;\n              case 'removeClass':\n                cancellations.push(animation.fn(element, classNameRemove || className,  progress, options));\n                break;\n              default:\n                cancellations.push(animation.fn(element, progress, options));\n                break;\n            }\n          });\n\n          if (cancellations && cancellations.length === 0) {\n            allCompleteFn();\n          }\n        }\n\n        return {\n          node: node,\n          event: animationEvent,\n          className: className,\n          isClassBased: isClassBased,\n          isSetClassOperation: isSetClassOperation,\n          applyStyles: function() {\n            if (options) {\n              element.css(angular.extend(options.from || {}, options.to || {}));\n            }\n          },\n          before: function(allCompleteFn) {\n            beforeComplete = allCompleteFn;\n            run(before, beforeCancel, function() {\n              beforeComplete = noop;\n              allCompleteFn();\n            });\n          },\n          after: function(allCompleteFn) {\n            afterComplete = allCompleteFn;\n            run(after, afterCancel, function() {\n              afterComplete = noop;\n              allCompleteFn();\n            });\n          },\n          cancel: function() {\n            if (beforeCancel) {\n              forEach(beforeCancel, function(cancelFn) {\n                (cancelFn || noop)(true);\n              });\n              beforeComplete(true);\n            }\n            if (afterCancel) {\n              forEach(afterCancel, function(cancelFn) {\n                (cancelFn || noop)(true);\n              });\n              afterComplete(true);\n            }\n          }\n        };\n      }\n\n      /**\n       * @ngdoc service\n       * @name $animate\n       * @kind object\n       *\n       * @description\n       * The `$animate` service provides animation detection support while performing DOM operations (enter, leave and move) as well as during addClass and removeClass operations.\n       * When any of these operations are run, the $animate service\n       * will examine any JavaScript-defined animations (which are defined by using the $animateProvider provider object)\n       * as well as any CSS-defined animations against the CSS classes present on the element once the DOM operation is run.\n       *\n       * The `$animate` service is used behind the scenes with pre-existing directives and animation with these directives\n       * will work out of the box without any extra configuration.\n       *\n       * Requires the {@link ngAnimate `ngAnimate`} module to be installed.\n       *\n       * Please visit the {@link ngAnimate `ngAnimate`} module overview page learn more about how to use animations in your application.\n       * ## Callback Promises\n       * With AngularJS 1.3, each of the animation methods, on the `$animate` service, return a promise when called. The\n       * promise itself is then resolved once the animation has completed itself, has been cancelled or has been\n       * skipped due to animations being disabled. (Note that even if the animation is cancelled it will still\n       * call the resolve function of the animation.)\n       *\n       * ```js\n       * $animate.enter(element, container).then(function() {\n       *   //...this is called once the animation is complete...\n       * });\n       * ```\n       *\n       * Also note that, due to the nature of the callback promise, if any Angular-specific code (like changing the scope,\n       * location of the page, etc...) is executed within the callback promise then be sure to wrap the code using\n       * `$scope.$apply(...)`;\n       *\n       * ```js\n       * $animate.leave(element).then(function() {\n       *   $scope.$apply(function() {\n       *     $location.path('/new-page');\n       *   });\n       * });\n       * ```\n       *\n       * An animation can also be cancelled by calling the `$animate.cancel(promise)` method with the provided\n       * promise that was returned when the animation was started.\n       *\n       * ```js\n       * var promise = $animate.addClass(element, 'super-long-animation');\n       * promise.then(function() {\n       *   //this will still be called even if cancelled\n       * });\n       *\n       * element.on('click', function() {\n       *   //tooo lazy to wait for the animation to end\n       *   $animate.cancel(promise);\n       * });\n       * ```\n       *\n       * (Keep in mind that the promise cancellation is unique to `$animate` since promises in\n       * general cannot be cancelled.)\n       *\n       */\n      return {\n        /**\n         * @ngdoc method\n         * @name $animate#animate\n         * @kind function\n         *\n         * @description\n         * Performs an inline animation on the element which applies the provided `to` and `from` CSS styles to the element.\n         * If any detected CSS transition, keyframe or JavaScript matches the provided `className` value then the animation\n         * will take on the provided styles. For example, if a transition animation is set for the given className then the\n         * provided `from` and `to` styles will be applied alongside the given transition. If a JavaScript animation is\n         * detected then the provided styles will be given in as function paramters.\n         *\n         * ```js\n         * ngModule.animation('.my-inline-animation', function() {\n         *   return {\n         *     animate : function(element, className, from, to, done) {\n         *       //styles\n         *     }\n         *   }\n         * });\n         * ```\n         *\n         * Below is a breakdown of each step that occurs during the `animate` animation:\n         *\n         * | Animation Step                                                                                                        | What the element class attribute looks like                  |\n         * |-----------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------|\n         * | 1. `$animate.animate(...)` is called                                                                                  | `class=\"my-animation\"`                                       |\n         * | 2. `$animate` waits for the next digest to start the animation                                                        | `class=\"my-animation ng-animate\"`                            |\n         * | 3. `$animate` runs the JavaScript-defined animations detected on the element                                          | `class=\"my-animation ng-animate\"`                            |\n         * | 4. the `className` class value is added to the element                                                                | `class=\"my-animation ng-animate className\"`                  |\n         * | 5. `$animate` scans the element styles to get the CSS transition/animation duration and delay                         | `class=\"my-animation ng-animate className\"`                  |\n         * | 6. `$animate` blocks all CSS transitions on the element to ensure the `.className` class styling is applied right away| `class=\"my-animation ng-animate className\"`                  |\n         * | 7. `$animate` applies the provided collection of `from` CSS styles to the element                                     | `class=\"my-animation ng-animate className\"`                  |\n         * | 8. `$animate` waits for a single animation frame (this performs a reflow)                                             | `class=\"my-animation ng-animate className\"`                  |\n         * | 9. `$animate` removes the CSS transition block placed on the element                                                  | `class=\"my-animation ng-animate className\"`                  |\n         * | 10. the `className-active` class is added (this triggers the CSS transition/animation)                                | `class=\"my-animation ng-animate className className-active\"` |\n         * | 11. `$animate` applies the collection of `to` CSS styles to the element which are then handled by the transition      | `class=\"my-animation ng-animate className className-active\"` |\n         * | 12. `$animate` waits for the animation to complete (via events and timeout)                                           | `class=\"my-animation ng-animate className className-active\"` |\n         * | 13. The animation ends and all generated CSS classes are removed from the element                                     | `class=\"my-animation\"`                                       |\n         * | 14. The returned promise is resolved.                                                                                 | `class=\"my-animation\"`                                       |\n         *\n         * @param {DOMElement} element the element that will be the focus of the enter animation\n         * @param {object} from a collection of CSS styles that will be applied to the element at the start of the animation\n         * @param {object} to a collection of CSS styles that the element will animate towards\n         * @param {string=} className an optional CSS class that will be added to the element for the duration of the animation (the default class is `ng-inline-animate`)\n         * @param {object=} options an optional collection of options that will be picked up by the CSS transition/animation\n         * @return {Promise} the animation callback promise\n        */\n        animate: function(element, from, to, className, options) {\n          className = className || 'ng-inline-animate';\n          options = parseAnimateOptions(options) || {};\n          options.from = to ? from : null;\n          options.to   = to ? to : from;\n\n          return runAnimationPostDigest(function(done) {\n            return performAnimation('animate', className, stripCommentsFromElement(element), null, null, noop, options, done);\n          });\n        },\n\n        /**\n         * @ngdoc method\n         * @name $animate#enter\n         * @kind function\n         *\n         * @description\n         * Appends the element to the parentElement element that resides in the document and then runs the enter animation. Once\n         * the animation is started, the following CSS classes will be present on the element for the duration of the animation:\n         *\n         * Below is a breakdown of each step that occurs during enter animation:\n         *\n         * | Animation Step                                                                                                        | What the element class attribute looks like                |\n         * |-----------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------|\n         * | 1. `$animate.enter(...)` is called                                                                                    | `class=\"my-animation\"`                                     |\n         * | 2. element is inserted into the `parentElement` element or beside the `afterElement` element                          | `class=\"my-animation\"`                                     |\n         * | 3. `$animate` waits for the next digest to start the animation                                                        | `class=\"my-animation ng-animate\"`                          |\n         * | 4. `$animate` runs the JavaScript-defined animations detected on the element                                          | `class=\"my-animation ng-animate\"`                          |\n         * | 5. the `.ng-enter` class is added to the element                                                                      | `class=\"my-animation ng-animate ng-enter\"`                 |\n         * | 6. `$animate` scans the element styles to get the CSS transition/animation duration and delay                         | `class=\"my-animation ng-animate ng-enter\"`                 |\n         * | 7. `$animate` blocks all CSS transitions on the element to ensure the `.ng-enter` class styling is applied right away | `class=\"my-animation ng-animate ng-enter\"`                 |\n         * | 8. `$animate` waits for a single animation frame (this performs a reflow)                                             | `class=\"my-animation ng-animate ng-enter\"`                 |\n         * | 9. `$animate` removes the CSS transition block placed on the element                                                  | `class=\"my-animation ng-animate ng-enter\"`                 |\n         * | 10. the `.ng-enter-active` class is added (this triggers the CSS transition/animation)                                | `class=\"my-animation ng-animate ng-enter ng-enter-active\"` |\n         * | 11. `$animate` waits for the animation to complete (via events and timeout)                                           | `class=\"my-animation ng-animate ng-enter ng-enter-active\"` |\n         * | 12. The animation ends and all generated CSS classes are removed from the element                                     | `class=\"my-animation\"`                                     |\n         * | 13. The returned promise is resolved.                                                                                 | `class=\"my-animation\"`                                     |\n         *\n         * @param {DOMElement} element the element that will be the focus of the enter animation\n         * @param {DOMElement} parentElement the parent element of the element that will be the focus of the enter animation\n         * @param {DOMElement} afterElement the sibling element (which is the previous element) of the element that will be the focus of the enter animation\n         * @param {object=} options an optional collection of options that will be picked up by the CSS transition/animation\n         * @return {Promise} the animation callback promise\n        */\n        enter: function(element, parentElement, afterElement, options) {\n          options = parseAnimateOptions(options);\n          element = angular.element(element);\n          parentElement = prepareElement(parentElement);\n          afterElement = prepareElement(afterElement);\n\n          classBasedAnimationsBlocked(element, true);\n          $delegate.enter(element, parentElement, afterElement);\n          return runAnimationPostDigest(function(done) {\n            return performAnimation('enter', 'ng-enter', stripCommentsFromElement(element), parentElement, afterElement, noop, options, done);\n          });\n        },\n\n        /**\n         * @ngdoc method\n         * @name $animate#leave\n         * @kind function\n         *\n         * @description\n         * Runs the leave animation operation and, upon completion, removes the element from the DOM. Once\n         * the animation is started, the following CSS classes will be added for the duration of the animation:\n         *\n         * Below is a breakdown of each step that occurs during leave animation:\n         *\n         * | Animation Step                                                                                                        | What the element class attribute looks like                |\n         * |-----------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------|\n         * | 1. `$animate.leave(...)` is called                                                                                    | `class=\"my-animation\"`                                     |\n         * | 2. `$animate` runs the JavaScript-defined animations detected on the element                                          | `class=\"my-animation ng-animate\"`                          |\n         * | 3. `$animate` waits for the next digest to start the animation                                                        | `class=\"my-animation ng-animate\"`                          |\n         * | 4. the `.ng-leave` class is added to the element                                                                      | `class=\"my-animation ng-animate ng-leave\"`                 |\n         * | 5. `$animate` scans the element styles to get the CSS transition/animation duration and delay                         | `class=\"my-animation ng-animate ng-leave\"`                 |\n         * | 6. `$animate` blocks all CSS transitions on the element to ensure the `.ng-leave` class styling is applied right away | `class=\"my-animation ng-animate ng-leave\"`                 |\n         * | 7. `$animate` waits for a single animation frame (this performs a reflow)                                             | `class=\"my-animation ng-animate ng-leave\"`                 |\n         * | 8. `$animate` removes the CSS transition block placed on the element                                                  | `class=\"my-animation ng-animate ng-leave\"`                 |\n         * | 9. the `.ng-leave-active` class is added (this triggers the CSS transition/animation)                                 | `class=\"my-animation ng-animate ng-leave ng-leave-active\"` |\n         * | 10. `$animate` waits for the animation to complete (via events and timeout)                                           | `class=\"my-animation ng-animate ng-leave ng-leave-active\"` |\n         * | 11. The animation ends and all generated CSS classes are removed from the element                                     | `class=\"my-animation\"`                                     |\n         * | 12. The element is removed from the DOM                                                                               | ...                                                        |\n         * | 13. The returned promise is resolved.                                                                                 | ...                                                        |\n         *\n         * @param {DOMElement} element the element that will be the focus of the leave animation\n         * @param {object=} options an optional collection of styles that will be picked up by the CSS transition/animation\n         * @return {Promise} the animation callback promise\n        */\n        leave: function(element, options) {\n          options = parseAnimateOptions(options);\n          element = angular.element(element);\n\n          cancelChildAnimations(element);\n          classBasedAnimationsBlocked(element, true);\n          return runAnimationPostDigest(function(done) {\n            return performAnimation('leave', 'ng-leave', stripCommentsFromElement(element), null, null, function() {\n              $delegate.leave(element);\n            }, options, done);\n          });\n        },\n\n        /**\n         * @ngdoc method\n         * @name $animate#move\n         * @kind function\n         *\n         * @description\n         * Fires the move DOM operation. Just before the animation starts, the animate service will either append it into the parentElement container or\n         * add the element directly after the afterElement element if present. Then the move animation will be run. Once\n         * the animation is started, the following CSS classes will be added for the duration of the animation:\n         *\n         * Below is a breakdown of each step that occurs during move animation:\n         *\n         * | Animation Step                                                                                                       | What the element class attribute looks like              |\n         * |----------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------|\n         * | 1. `$animate.move(...)` is called                                                                                    | `class=\"my-animation\"`                                   |\n         * | 2. element is moved into the parentElement element or beside the afterElement element                                | `class=\"my-animation\"`                                   |\n         * | 3. `$animate` waits for the next digest to start the animation                                                       | `class=\"my-animation ng-animate\"`                        |\n         * | 4. `$animate` runs the JavaScript-defined animations detected on the element                                         | `class=\"my-animation ng-animate\"`                        |\n         * | 5. the `.ng-move` class is added to the element                                                                      | `class=\"my-animation ng-animate ng-move\"`                |\n         * | 6. `$animate` scans the element styles to get the CSS transition/animation duration and delay                        | `class=\"my-animation ng-animate ng-move\"`                |\n         * | 7. `$animate` blocks all CSS transitions on the element to ensure the `.ng-move` class styling is applied right away | `class=\"my-animation ng-animate ng-move\"`                |\n         * | 8. `$animate` waits for a single animation frame (this performs a reflow)                                            | `class=\"my-animation ng-animate ng-move\"`                |\n         * | 9. `$animate` removes the CSS transition block placed on the element                                                 | `class=\"my-animation ng-animate ng-move\"`                |\n         * | 10. the `.ng-move-active` class is added (this triggers the CSS transition/animation)                                | `class=\"my-animation ng-animate ng-move ng-move-active\"` |\n         * | 11. `$animate` waits for the animation to complete (via events and timeout)                                          | `class=\"my-animation ng-animate ng-move ng-move-active\"` |\n         * | 12. The animation ends and all generated CSS classes are removed from the element                                    | `class=\"my-animation\"`                                   |\n         * | 13. The returned promise is resolved.                                                                                | `class=\"my-animation\"`                                   |\n         *\n         * @param {DOMElement} element the element that will be the focus of the move animation\n         * @param {DOMElement} parentElement the parentElement element of the element that will be the focus of the move animation\n         * @param {DOMElement} afterElement the sibling element (which is the previous element) of the element that will be the focus of the move animation\n         * @param {object=} options an optional collection of styles that will be picked up by the CSS transition/animation\n         * @return {Promise} the animation callback promise\n        */\n        move: function(element, parentElement, afterElement, options) {\n          options = parseAnimateOptions(options);\n          element = angular.element(element);\n          parentElement = prepareElement(parentElement);\n          afterElement = prepareElement(afterElement);\n\n          cancelChildAnimations(element);\n          classBasedAnimationsBlocked(element, true);\n          $delegate.move(element, parentElement, afterElement);\n          return runAnimationPostDigest(function(done) {\n            return performAnimation('move', 'ng-move', stripCommentsFromElement(element), parentElement, afterElement, noop, options, done);\n          });\n        },\n\n        /**\n         * @ngdoc method\n         * @name $animate#addClass\n         *\n         * @description\n         * Triggers a custom animation event based off the className variable and then attaches the className value to the element as a CSS class.\n         * Unlike the other animation methods, the animate service will suffix the className value with {@type -add} in order to provide\n         * the animate service the setup and active CSS classes in order to trigger the animation (this will be skipped if no CSS transitions\n         * or keyframes are defined on the -add-active or base CSS class).\n         *\n         * Below is a breakdown of each step that occurs during addClass animation:\n         *\n         * | Animation Step                                                                                         | What the element class attribute looks like                        |\n         * |--------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------|\n         * | 1. `$animate.addClass(element, 'super')` is called                                                     | `class=\"my-animation\"`                                             |\n         * | 2. `$animate` runs the JavaScript-defined animations detected on the element                           | `class=\"my-animation ng-animate\"`                                  |\n         * | 3. the `.super-add` class is added to the element                                                      | `class=\"my-animation ng-animate super-add\"`                        |\n         * | 4. `$animate` waits for a single animation frame (this performs a reflow)                              | `class=\"my-animation ng-animate super-add\"`                        |\n         * | 5. the `.super` and `.super-add-active` classes are added (this triggers the CSS transition/animation) | `class=\"my-animation ng-animate super super-add super-add-active\"` |\n         * | 6. `$animate` scans the element styles to get the CSS transition/animation duration and delay          | `class=\"my-animation ng-animate super super-add super-add-active\"` |\n         * | 7. `$animate` waits for the animation to complete (via events and timeout)                             | `class=\"my-animation ng-animate super super-add super-add-active\"` |\n         * | 8. The animation ends and all generated CSS classes are removed from the element                       | `class=\"my-animation super\"`                                       |\n         * | 9. The super class is kept on the element                                                              | `class=\"my-animation super\"`                                       |\n         * | 10. The returned promise is resolved.                                                                  | `class=\"my-animation super\"`                                       |\n         *\n         * @param {DOMElement} element the element that will be animated\n         * @param {string} className the CSS class that will be added to the element and then animated\n         * @param {object=} options an optional collection of styles that will be picked up by the CSS transition/animation\n         * @return {Promise} the animation callback promise\n        */\n        addClass: function(element, className, options) {\n          return this.setClass(element, className, [], options);\n        },\n\n        /**\n         * @ngdoc method\n         * @name $animate#removeClass\n         *\n         * @description\n         * Triggers a custom animation event based off the className variable and then removes the CSS class provided by the className value\n         * from the element. Unlike the other animation methods, the animate service will suffix the className value with {@type -remove} in\n         * order to provide the animate service the setup and active CSS classes in order to trigger the animation (this will be skipped if\n         * no CSS transitions or keyframes are defined on the -remove or base CSS classes).\n         *\n         * Below is a breakdown of each step that occurs during removeClass animation:\n         *\n         * | Animation Step                                                                                                       | What the element class attribute looks like                        |\n         * |----------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------|\n         * | 1. `$animate.removeClass(element, 'super')` is called                                                                | `class=\"my-animation super\"`                                       |\n         * | 2. `$animate` runs the JavaScript-defined animations detected on the element                                         | `class=\"my-animation super ng-animate\"`                            |\n         * | 3. the `.super-remove` class is added to the element                                                                 | `class=\"my-animation super ng-animate super-remove\"`               |\n         * | 4. `$animate` waits for a single animation frame (this performs a reflow)                                            | `class=\"my-animation super ng-animate super-remove\"`               |\n         * | 5. the `.super-remove-active` classes are added and `.super` is removed (this triggers the CSS transition/animation) | `class=\"my-animation ng-animate super-remove super-remove-active\"` |\n         * | 6. `$animate` scans the element styles to get the CSS transition/animation duration and delay                        | `class=\"my-animation ng-animate super-remove super-remove-active\"` |\n         * | 7. `$animate` waits for the animation to complete (via events and timeout)                                           | `class=\"my-animation ng-animate super-remove super-remove-active\"` |\n         * | 8. The animation ends and all generated CSS classes are removed from the element                                     | `class=\"my-animation\"`                                             |\n         * | 9. The returned promise is resolved.                                                                                 | `class=\"my-animation\"`                                             |\n         *\n         *\n         * @param {DOMElement} element the element that will be animated\n         * @param {string} className the CSS class that will be animated and then removed from the element\n         * @param {object=} options an optional collection of styles that will be picked up by the CSS transition/animation\n         * @return {Promise} the animation callback promise\n        */\n        removeClass: function(element, className, options) {\n          return this.setClass(element, [], className, options);\n        },\n\n        /**\n         *\n         * @ngdoc method\n         * @name $animate#setClass\n         *\n         * @description Adds and/or removes the given CSS classes to and from the element.\n         * Once complete, the `done()` callback will be fired (if provided).\n         *\n         * | Animation Step                                                                                                                               | What the element class attribute looks like                                            |\n         * |----------------------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------|\n         * | 1. `$animate.setClass(element, 'on', 'off')` is called                                                                                       | `class=\"my-animation off\"`                                                             |\n         * | 2. `$animate` runs the JavaScript-defined animations detected on the element                                                                 | `class=\"my-animation ng-animate off\"`                                                  |\n         * | 3. the `.on-add` and `.off-remove` classes are added to the element                                                                          | `class=\"my-animation ng-animate on-add off-remove off\"`                                |\n         * | 4. `$animate` waits for a single animation frame (this performs a reflow)                                                                    | `class=\"my-animation ng-animate on-add off-remove off\"`                                |\n         * | 5. the `.on`, `.on-add-active` and `.off-remove-active` classes are added and `.off` is removed (this triggers the CSS transition/animation) | `class=\"my-animation ng-animate on on-add on-add-active off-remove off-remove-active\"` |\n         * | 6. `$animate` scans the element styles to get the CSS transition/animation duration and delay                                                | `class=\"my-animation ng-animate on on-add on-add-active off-remove off-remove-active\"` |\n         * | 7. `$animate` waits for the animation to complete (via events and timeout)                                                                   | `class=\"my-animation ng-animate on on-add on-add-active off-remove off-remove-active\"` |\n         * | 8. The animation ends and all generated CSS classes are removed from the element                                                             | `class=\"my-animation on\"`                                                              |\n         * | 9. The returned promise is resolved.                                                                                                         | `class=\"my-animation on\"`                                                              |\n         *\n         * @param {DOMElement} element the element which will have its CSS classes changed\n         *   removed from it\n         * @param {string} add the CSS classes which will be added to the element\n         * @param {string} remove the CSS class which will be removed from the element\n         *   CSS classes have been set on the element\n         * @param {object=} options an optional collection of styles that will be picked up by the CSS transition/animation\n         * @return {Promise} the animation callback promise\n         */\n        setClass: function(element, add, remove, options) {\n          options = parseAnimateOptions(options);\n\n          var STORAGE_KEY = '$$animateClasses';\n          element = angular.element(element);\n          element = stripCommentsFromElement(element);\n\n          if (classBasedAnimationsBlocked(element)) {\n            return $delegate.$$setClassImmediately(element, add, remove, options);\n          }\n\n          // we're using a combined array for both the add and remove\n          // operations since the ORDER OF addClass and removeClass matters\n          var classes, cache = element.data(STORAGE_KEY);\n          var hasCache = !!cache;\n          if (!cache) {\n            cache = {};\n            cache.classes = {};\n          }\n          classes = cache.classes;\n\n          add = isArray(add) ? add : add.split(' ');\n          forEach(add, function(c) {\n            if (c && c.length) {\n              classes[c] = true;\n            }\n          });\n\n          remove = isArray(remove) ? remove : remove.split(' ');\n          forEach(remove, function(c) {\n            if (c && c.length) {\n              classes[c] = false;\n            }\n          });\n\n          if (hasCache) {\n            if (options && cache.options) {\n              cache.options = angular.extend(cache.options || {}, options);\n            }\n\n            //the digest cycle will combine all the animations into one function\n            return cache.promise;\n          } else {\n            element.data(STORAGE_KEY, cache = {\n              classes: classes,\n              options: options\n            });\n          }\n\n          return cache.promise = runAnimationPostDigest(function(done) {\n            var parentElement = element.parent();\n            var elementNode = extractElementNode(element);\n            var parentNode = elementNode.parentNode;\n            // TODO(matsko): move this code into the animationsDisabled() function once #8092 is fixed\n            if (!parentNode || parentNode['$$NG_REMOVED'] || elementNode['$$NG_REMOVED']) {\n              done();\n              return;\n            }\n\n            var cache = element.data(STORAGE_KEY);\n            element.removeData(STORAGE_KEY);\n\n            var state = element.data(NG_ANIMATE_STATE) || {};\n            var classes = resolveElementClasses(element, cache, state.active);\n            return !classes\n              ? done()\n              : performAnimation('setClass', classes, element, parentElement, null, function() {\n                  if (classes[0]) $delegate.$$addClassImmediately(element, classes[0]);\n                  if (classes[1]) $delegate.$$removeClassImmediately(element, classes[1]);\n                }, cache.options, done);\n          });\n        },\n\n        /**\n         * @ngdoc method\n         * @name $animate#cancel\n         * @kind function\n         *\n         * @param {Promise} animationPromise The animation promise that is returned when an animation is started.\n         *\n         * @description\n         * Cancels the provided animation.\n        */\n        cancel: function(promise) {\n          promise.$$cancelFn();\n        },\n\n        /**\n         * @ngdoc method\n         * @name $animate#enabled\n         * @kind function\n         *\n         * @param {boolean=} value If provided then set the animation on or off.\n         * @param {DOMElement=} element If provided then the element will be used to represent the enable/disable operation\n         * @return {boolean} Current animation state.\n         *\n         * @description\n         * Globally enables/disables animations.\n         *\n        */\n        enabled: function(value, element) {\n          switch (arguments.length) {\n            case 2:\n              if (value) {\n                cleanup(element);\n              } else {\n                var data = element.data(NG_ANIMATE_STATE) || {};\n                data.disabled = true;\n                element.data(NG_ANIMATE_STATE, data);\n              }\n            break;\n\n            case 1:\n              rootAnimateState.disabled = !value;\n            break;\n\n            default:\n              value = !rootAnimateState.disabled;\n            break;\n          }\n          return !!value;\n         }\n      };\n\n      /*\n        all animations call this shared animation triggering function internally.\n        The animationEvent variable refers to the JavaScript animation event that will be triggered\n        and the className value is the name of the animation that will be applied within the\n        CSS code. Element, `parentElement` and `afterElement` are provided DOM elements for the animation\n        and the onComplete callback will be fired once the animation is fully complete.\n      */\n      function performAnimation(animationEvent, className, element, parentElement, afterElement, domOperation, options, doneCallback) {\n        var noopCancel = noop;\n        var runner = animationRunner(element, animationEvent, className, options);\n        if (!runner) {\n          fireDOMOperation();\n          fireBeforeCallbackAsync();\n          fireAfterCallbackAsync();\n          closeAnimation();\n          return noopCancel;\n        }\n\n        animationEvent = runner.event;\n        className = runner.className;\n        var elementEvents = angular.element._data(runner.node);\n        elementEvents = elementEvents && elementEvents.events;\n\n        if (!parentElement) {\n          parentElement = afterElement ? afterElement.parent() : element.parent();\n        }\n\n        //skip the animation if animations are disabled, a parent is already being animated,\n        //the element is not currently attached to the document body or then completely close\n        //the animation if any matching animations are not found at all.\n        //NOTE: IE8 + IE9 should close properly (run closeAnimation()) in case an animation was found.\n        if (animationsDisabled(element, parentElement)) {\n          fireDOMOperation();\n          fireBeforeCallbackAsync();\n          fireAfterCallbackAsync();\n          closeAnimation();\n          return noopCancel;\n        }\n\n        var ngAnimateState  = element.data(NG_ANIMATE_STATE) || {};\n        var runningAnimations     = ngAnimateState.active || {};\n        var totalActiveAnimations = ngAnimateState.totalActive || 0;\n        var lastAnimation         = ngAnimateState.last;\n        var skipAnimation = false;\n\n        if (totalActiveAnimations > 0) {\n          var animationsToCancel = [];\n          if (!runner.isClassBased) {\n            if (animationEvent == 'leave' && runningAnimations['ng-leave']) {\n              skipAnimation = true;\n            } else {\n              //cancel all animations when a structural animation takes place\n              for (var klass in runningAnimations) {\n                animationsToCancel.push(runningAnimations[klass]);\n              }\n              ngAnimateState = {};\n              cleanup(element, true);\n            }\n          } else if (lastAnimation.event == 'setClass') {\n            animationsToCancel.push(lastAnimation);\n            cleanup(element, className);\n          } else if (runningAnimations[className]) {\n            var current = runningAnimations[className];\n            if (current.event == animationEvent) {\n              skipAnimation = true;\n            } else {\n              animationsToCancel.push(current);\n              cleanup(element, className);\n            }\n          }\n\n          if (animationsToCancel.length > 0) {\n            forEach(animationsToCancel, function(operation) {\n              operation.cancel();\n            });\n          }\n        }\n\n        if (runner.isClassBased\n            && !runner.isSetClassOperation\n            && animationEvent != 'animate'\n            && !skipAnimation) {\n          skipAnimation = (animationEvent == 'addClass') == element.hasClass(className); //opposite of XOR\n        }\n\n        if (skipAnimation) {\n          fireDOMOperation();\n          fireBeforeCallbackAsync();\n          fireAfterCallbackAsync();\n          fireDoneCallbackAsync();\n          return noopCancel;\n        }\n\n        runningAnimations     = ngAnimateState.active || {};\n        totalActiveAnimations = ngAnimateState.totalActive || 0;\n\n        if (animationEvent == 'leave') {\n          //there's no need to ever remove the listener since the element\n          //will be removed (destroyed) after the leave animation ends or\n          //is cancelled midway\n          element.one('$destroy', function(e) {\n            var element = angular.element(this);\n            var state = element.data(NG_ANIMATE_STATE);\n            if (state) {\n              var activeLeaveAnimation = state.active['ng-leave'];\n              if (activeLeaveAnimation) {\n                activeLeaveAnimation.cancel();\n                cleanup(element, 'ng-leave');\n              }\n            }\n          });\n        }\n\n        //the ng-animate class does nothing, but it's here to allow for\n        //parent animations to find and cancel child animations when needed\n        $$jqLite.addClass(element, NG_ANIMATE_CLASS_NAME);\n        if (options && options.tempClasses) {\n          forEach(options.tempClasses, function(className) {\n            $$jqLite.addClass(element, className);\n          });\n        }\n\n        var localAnimationCount = globalAnimationCounter++;\n        totalActiveAnimations++;\n        runningAnimations[className] = runner;\n\n        element.data(NG_ANIMATE_STATE, {\n          last: runner,\n          active: runningAnimations,\n          index: localAnimationCount,\n          totalActive: totalActiveAnimations\n        });\n\n        //first we run the before animations and when all of those are complete\n        //then we perform the DOM operation and run the next set of animations\n        fireBeforeCallbackAsync();\n        runner.before(function(cancelled) {\n          var data = element.data(NG_ANIMATE_STATE);\n          cancelled = cancelled ||\n                        !data || !data.active[className] ||\n                        (runner.isClassBased && data.active[className].event != animationEvent);\n\n          fireDOMOperation();\n          if (cancelled === true) {\n            closeAnimation();\n          } else {\n            fireAfterCallbackAsync();\n            runner.after(closeAnimation);\n          }\n        });\n\n        return runner.cancel;\n\n        function fireDOMCallback(animationPhase) {\n          var eventName = '$animate:' + animationPhase;\n          if (elementEvents && elementEvents[eventName] && elementEvents[eventName].length > 0) {\n            $$asyncCallback(function() {\n              element.triggerHandler(eventName, {\n                event: animationEvent,\n                className: className\n              });\n            });\n          }\n        }\n\n        function fireBeforeCallbackAsync() {\n          fireDOMCallback('before');\n        }\n\n        function fireAfterCallbackAsync() {\n          fireDOMCallback('after');\n        }\n\n        function fireDoneCallbackAsync() {\n          fireDOMCallback('close');\n          doneCallback();\n        }\n\n        //it is less complicated to use a flag than managing and canceling\n        //timeouts containing multiple callbacks.\n        function fireDOMOperation() {\n          if (!fireDOMOperation.hasBeenRun) {\n            fireDOMOperation.hasBeenRun = true;\n            domOperation();\n          }\n        }\n\n        function closeAnimation() {\n          if (!closeAnimation.hasBeenRun) {\n            if (runner) { //the runner doesn't exist if it fails to instantiate\n              runner.applyStyles();\n            }\n\n            closeAnimation.hasBeenRun = true;\n            if (options && options.tempClasses) {\n              forEach(options.tempClasses, function(className) {\n                $$jqLite.removeClass(element, className);\n              });\n            }\n\n            var data = element.data(NG_ANIMATE_STATE);\n            if (data) {\n\n              /* only structural animations wait for reflow before removing an\n                 animation, but class-based animations don't. An example of this\n                 failing would be when a parent HTML tag has a ng-class attribute\n                 causing ALL directives below to skip animations during the digest */\n              if (runner && runner.isClassBased) {\n                cleanup(element, className);\n              } else {\n                $$asyncCallback(function() {\n                  var data = element.data(NG_ANIMATE_STATE) || {};\n                  if (localAnimationCount == data.index) {\n                    cleanup(element, className, animationEvent);\n                  }\n                });\n                element.data(NG_ANIMATE_STATE, data);\n              }\n            }\n            fireDoneCallbackAsync();\n          }\n        }\n      }\n\n      function cancelChildAnimations(element) {\n        var node = extractElementNode(element);\n        if (node) {\n          var nodes = angular.isFunction(node.getElementsByClassName) ?\n            node.getElementsByClassName(NG_ANIMATE_CLASS_NAME) :\n            node.querySelectorAll('.' + NG_ANIMATE_CLASS_NAME);\n          forEach(nodes, function(element) {\n            element = angular.element(element);\n            var data = element.data(NG_ANIMATE_STATE);\n            if (data && data.active) {\n              forEach(data.active, function(runner) {\n                runner.cancel();\n              });\n            }\n          });\n        }\n      }\n\n      function cleanup(element, className) {\n        if (isMatchingElement(element, $rootElement)) {\n          if (!rootAnimateState.disabled) {\n            rootAnimateState.running = false;\n            rootAnimateState.structural = false;\n          }\n        } else if (className) {\n          var data = element.data(NG_ANIMATE_STATE) || {};\n\n          var removeAnimations = className === true;\n          if (!removeAnimations && data.active && data.active[className]) {\n            data.totalActive--;\n            delete data.active[className];\n          }\n\n          if (removeAnimations || !data.totalActive) {\n            $$jqLite.removeClass(element, NG_ANIMATE_CLASS_NAME);\n            element.removeData(NG_ANIMATE_STATE);\n          }\n        }\n      }\n\n      function animationsDisabled(element, parentElement) {\n        if (rootAnimateState.disabled) {\n          return true;\n        }\n\n        if (isMatchingElement(element, $rootElement)) {\n          return rootAnimateState.running;\n        }\n\n        var allowChildAnimations, parentRunningAnimation, hasParent;\n        do {\n          //the element did not reach the root element which means that it\n          //is not apart of the DOM. Therefore there is no reason to do\n          //any animations on it\n          if (parentElement.length === 0) break;\n\n          var isRoot = isMatchingElement(parentElement, $rootElement);\n          var state = isRoot ? rootAnimateState : (parentElement.data(NG_ANIMATE_STATE) || {});\n          if (state.disabled) {\n            return true;\n          }\n\n          //no matter what, for an animation to work it must reach the root element\n          //this implies that the element is attached to the DOM when the animation is run\n          if (isRoot) {\n            hasParent = true;\n          }\n\n          //once a flag is found that is strictly false then everything before\n          //it will be discarded and all child animations will be restricted\n          if (allowChildAnimations !== false) {\n            var animateChildrenFlag = parentElement.data(NG_ANIMATE_CHILDREN);\n            if (angular.isDefined(animateChildrenFlag)) {\n              allowChildAnimations = animateChildrenFlag;\n            }\n          }\n\n          parentRunningAnimation = parentRunningAnimation ||\n                                   state.running ||\n                                   (state.last && !state.last.isClassBased);\n        }\n        while (parentElement = parentElement.parent());\n\n        return !hasParent || (!allowChildAnimations && parentRunningAnimation);\n      }\n    }]);\n\n    $animateProvider.register('', ['$window', '$sniffer', '$timeout', '$$animateReflow',\n                           function($window,   $sniffer,   $timeout,   $$animateReflow) {\n      // Detect proper transitionend/animationend event names.\n      var CSS_PREFIX = '', TRANSITION_PROP, TRANSITIONEND_EVENT, ANIMATION_PROP, ANIMATIONEND_EVENT;\n\n      // If unprefixed events are not supported but webkit-prefixed are, use the latter.\n      // Otherwise, just use W3C names, browsers not supporting them at all will just ignore them.\n      // Note: Chrome implements `window.onwebkitanimationend` and doesn't implement `window.onanimationend`\n      // but at the same time dispatches the `animationend` event and not `webkitAnimationEnd`.\n      // Register both events in case `window.onanimationend` is not supported because of that,\n      // do the same for `transitionend` as Safari is likely to exhibit similar behavior.\n      // Also, the only modern browser that uses vendor prefixes for transitions/keyframes is webkit\n      // therefore there is no reason to test anymore for other vendor prefixes: http://caniuse.com/#search=transition\n      if (window.ontransitionend === undefined && window.onwebkittransitionend !== undefined) {\n        CSS_PREFIX = '-webkit-';\n        TRANSITION_PROP = 'WebkitTransition';\n        TRANSITIONEND_EVENT = 'webkitTransitionEnd transitionend';\n      } else {\n        TRANSITION_PROP = 'transition';\n        TRANSITIONEND_EVENT = 'transitionend';\n      }\n\n      if (window.onanimationend === undefined && window.onwebkitanimationend !== undefined) {\n        CSS_PREFIX = '-webkit-';\n        ANIMATION_PROP = 'WebkitAnimation';\n        ANIMATIONEND_EVENT = 'webkitAnimationEnd animationend';\n      } else {\n        ANIMATION_PROP = 'animation';\n        ANIMATIONEND_EVENT = 'animationend';\n      }\n\n      var DURATION_KEY = 'Duration';\n      var PROPERTY_KEY = 'Property';\n      var DELAY_KEY = 'Delay';\n      var ANIMATION_ITERATION_COUNT_KEY = 'IterationCount';\n      var ANIMATION_PLAYSTATE_KEY = 'PlayState';\n      var NG_ANIMATE_PARENT_KEY = '$$ngAnimateKey';\n      var NG_ANIMATE_CSS_DATA_KEY = '$$ngAnimateCSS3Data';\n      var ELAPSED_TIME_MAX_DECIMAL_PLACES = 3;\n      var CLOSING_TIME_BUFFER = 1.5;\n      var ONE_SECOND = 1000;\n\n      var lookupCache = {};\n      var parentCounter = 0;\n      var animationReflowQueue = [];\n      var cancelAnimationReflow;\n      function clearCacheAfterReflow() {\n        if (!cancelAnimationReflow) {\n          cancelAnimationReflow = $$animateReflow(function() {\n            animationReflowQueue = [];\n            cancelAnimationReflow = null;\n            lookupCache = {};\n          });\n        }\n      }\n\n      function afterReflow(element, callback) {\n        if (cancelAnimationReflow) {\n          cancelAnimationReflow();\n        }\n        animationReflowQueue.push(callback);\n        cancelAnimationReflow = $$animateReflow(function() {\n          forEach(animationReflowQueue, function(fn) {\n            fn();\n          });\n\n          animationReflowQueue = [];\n          cancelAnimationReflow = null;\n          lookupCache = {};\n        });\n      }\n\n      var closingTimer = null;\n      var closingTimestamp = 0;\n      var animationElementQueue = [];\n      function animationCloseHandler(element, totalTime) {\n        var node = extractElementNode(element);\n        element = angular.element(node);\n\n        //this item will be garbage collected by the closing\n        //animation timeout\n        animationElementQueue.push(element);\n\n        //but it may not need to cancel out the existing timeout\n        //if the timestamp is less than the previous one\n        var futureTimestamp = Date.now() + totalTime;\n        if (futureTimestamp <= closingTimestamp) {\n          return;\n        }\n\n        $timeout.cancel(closingTimer);\n\n        closingTimestamp = futureTimestamp;\n        closingTimer = $timeout(function() {\n          closeAllAnimations(animationElementQueue);\n          animationElementQueue = [];\n        }, totalTime, false);\n      }\n\n      function closeAllAnimations(elements) {\n        forEach(elements, function(element) {\n          var elementData = element.data(NG_ANIMATE_CSS_DATA_KEY);\n          if (elementData) {\n            forEach(elementData.closeAnimationFns, function(fn) {\n              fn();\n            });\n          }\n        });\n      }\n\n      function getElementAnimationDetails(element, cacheKey) {\n        var data = cacheKey ? lookupCache[cacheKey] : null;\n        if (!data) {\n          var transitionDuration = 0;\n          var transitionDelay = 0;\n          var animationDuration = 0;\n          var animationDelay = 0;\n\n          //we want all the styles defined before and after\n          forEach(element, function(element) {\n            if (element.nodeType == ELEMENT_NODE) {\n              var elementStyles = $window.getComputedStyle(element) || {};\n\n              var transitionDurationStyle = elementStyles[TRANSITION_PROP + DURATION_KEY];\n              transitionDuration = Math.max(parseMaxTime(transitionDurationStyle), transitionDuration);\n\n              var transitionDelayStyle = elementStyles[TRANSITION_PROP + DELAY_KEY];\n              transitionDelay  = Math.max(parseMaxTime(transitionDelayStyle), transitionDelay);\n\n              var animationDelayStyle = elementStyles[ANIMATION_PROP + DELAY_KEY];\n              animationDelay   = Math.max(parseMaxTime(elementStyles[ANIMATION_PROP + DELAY_KEY]), animationDelay);\n\n              var aDuration  = parseMaxTime(elementStyles[ANIMATION_PROP + DURATION_KEY]);\n\n              if (aDuration > 0) {\n                aDuration *= parseInt(elementStyles[ANIMATION_PROP + ANIMATION_ITERATION_COUNT_KEY], 10) || 1;\n              }\n              animationDuration = Math.max(aDuration, animationDuration);\n            }\n          });\n          data = {\n            total: 0,\n            transitionDelay: transitionDelay,\n            transitionDuration: transitionDuration,\n            animationDelay: animationDelay,\n            animationDuration: animationDuration\n          };\n          if (cacheKey) {\n            lookupCache[cacheKey] = data;\n          }\n        }\n        return data;\n      }\n\n      function parseMaxTime(str) {\n        var maxValue = 0;\n        var values = isString(str) ?\n          str.split(/\\s*,\\s*/) :\n          [];\n        forEach(values, function(value) {\n          maxValue = Math.max(parseFloat(value) || 0, maxValue);\n        });\n        return maxValue;\n      }\n\n      function getCacheKey(element) {\n        var parentElement = element.parent();\n        var parentID = parentElement.data(NG_ANIMATE_PARENT_KEY);\n        if (!parentID) {\n          parentElement.data(NG_ANIMATE_PARENT_KEY, ++parentCounter);\n          parentID = parentCounter;\n        }\n        return parentID + '-' + extractElementNode(element).getAttribute('class');\n      }\n\n      function animateSetup(animationEvent, element, className, styles) {\n        var structural = ['ng-enter','ng-leave','ng-move'].indexOf(className) >= 0;\n\n        var cacheKey = getCacheKey(element);\n        var eventCacheKey = cacheKey + ' ' + className;\n        var itemIndex = lookupCache[eventCacheKey] ? ++lookupCache[eventCacheKey].total : 0;\n\n        var stagger = {};\n        if (itemIndex > 0) {\n          var staggerClassName = className + '-stagger';\n          var staggerCacheKey = cacheKey + ' ' + staggerClassName;\n          var applyClasses = !lookupCache[staggerCacheKey];\n\n          applyClasses && $$jqLite.addClass(element, staggerClassName);\n\n          stagger = getElementAnimationDetails(element, staggerCacheKey);\n\n          applyClasses && $$jqLite.removeClass(element, staggerClassName);\n        }\n\n        $$jqLite.addClass(element, className);\n\n        var formerData = element.data(NG_ANIMATE_CSS_DATA_KEY) || {};\n        var timings = getElementAnimationDetails(element, eventCacheKey);\n        var transitionDuration = timings.transitionDuration;\n        var animationDuration = timings.animationDuration;\n\n        if (structural && transitionDuration === 0 && animationDuration === 0) {\n          $$jqLite.removeClass(element, className);\n          return false;\n        }\n\n        var blockTransition = styles || (structural && transitionDuration > 0);\n        var blockAnimation = animationDuration > 0 &&\n                             stagger.animationDelay > 0 &&\n                             stagger.animationDuration === 0;\n\n        var closeAnimationFns = formerData.closeAnimationFns || [];\n        element.data(NG_ANIMATE_CSS_DATA_KEY, {\n          stagger: stagger,\n          cacheKey: eventCacheKey,\n          running: formerData.running || 0,\n          itemIndex: itemIndex,\n          blockTransition: blockTransition,\n          closeAnimationFns: closeAnimationFns\n        });\n\n        var node = extractElementNode(element);\n\n        if (blockTransition) {\n          blockTransitions(node, true);\n          if (styles) {\n            element.css(styles);\n          }\n        }\n\n        if (blockAnimation) {\n          blockAnimations(node, true);\n        }\n\n        return true;\n      }\n\n      function animateRun(animationEvent, element, className, activeAnimationComplete, styles) {\n        var node = extractElementNode(element);\n        var elementData = element.data(NG_ANIMATE_CSS_DATA_KEY);\n        if (node.getAttribute('class').indexOf(className) == -1 || !elementData) {\n          activeAnimationComplete();\n          return;\n        }\n\n        var activeClassName = '';\n        var pendingClassName = '';\n        forEach(className.split(' '), function(klass, i) {\n          var prefix = (i > 0 ? ' ' : '') + klass;\n          activeClassName += prefix + '-active';\n          pendingClassName += prefix + '-pending';\n        });\n\n        var style = '';\n        var appliedStyles = [];\n        var itemIndex = elementData.itemIndex;\n        var stagger = elementData.stagger;\n        var staggerTime = 0;\n        if (itemIndex > 0) {\n          var transitionStaggerDelay = 0;\n          if (stagger.transitionDelay > 0 && stagger.transitionDuration === 0) {\n            transitionStaggerDelay = stagger.transitionDelay * itemIndex;\n          }\n\n          var animationStaggerDelay = 0;\n          if (stagger.animationDelay > 0 && stagger.animationDuration === 0) {\n            animationStaggerDelay = stagger.animationDelay * itemIndex;\n            appliedStyles.push(CSS_PREFIX + 'animation-play-state');\n          }\n\n          staggerTime = Math.round(Math.max(transitionStaggerDelay, animationStaggerDelay) * 100) / 100;\n        }\n\n        if (!staggerTime) {\n          $$jqLite.addClass(element, activeClassName);\n          if (elementData.blockTransition) {\n            blockTransitions(node, false);\n          }\n        }\n\n        var eventCacheKey = elementData.cacheKey + ' ' + activeClassName;\n        var timings = getElementAnimationDetails(element, eventCacheKey);\n        var maxDuration = Math.max(timings.transitionDuration, timings.animationDuration);\n        if (maxDuration === 0) {\n          $$jqLite.removeClass(element, activeClassName);\n          animateClose(element, className);\n          activeAnimationComplete();\n          return;\n        }\n\n        if (!staggerTime && styles && Object.keys(styles).length > 0) {\n          if (!timings.transitionDuration) {\n            element.css('transition', timings.animationDuration + 's linear all');\n            appliedStyles.push('transition');\n          }\n          element.css(styles);\n        }\n\n        var maxDelay = Math.max(timings.transitionDelay, timings.animationDelay);\n        var maxDelayTime = maxDelay * ONE_SECOND;\n\n        if (appliedStyles.length > 0) {\n          //the element being animated may sometimes contain comment nodes in\n          //the jqLite object, so we're safe to use a single variable to house\n          //the styles since there is always only one element being animated\n          var oldStyle = node.getAttribute('style') || '';\n          if (oldStyle.charAt(oldStyle.length - 1) !== ';') {\n            oldStyle += ';';\n          }\n          node.setAttribute('style', oldStyle + ' ' + style);\n        }\n\n        var startTime = Date.now();\n        var css3AnimationEvents = ANIMATIONEND_EVENT + ' ' + TRANSITIONEND_EVENT;\n        var animationTime     = (maxDelay + maxDuration) * CLOSING_TIME_BUFFER;\n        var totalTime         = (staggerTime + animationTime) * ONE_SECOND;\n\n        var staggerTimeout;\n        if (staggerTime > 0) {\n          $$jqLite.addClass(element, pendingClassName);\n          staggerTimeout = $timeout(function() {\n            staggerTimeout = null;\n\n            if (timings.transitionDuration > 0) {\n              blockTransitions(node, false);\n            }\n            if (timings.animationDuration > 0) {\n              blockAnimations(node, false);\n            }\n\n            $$jqLite.addClass(element, activeClassName);\n            $$jqLite.removeClass(element, pendingClassName);\n\n            if (styles) {\n              if (timings.transitionDuration === 0) {\n                element.css('transition', timings.animationDuration + 's linear all');\n              }\n              element.css(styles);\n              appliedStyles.push('transition');\n            }\n          }, staggerTime * ONE_SECOND, false);\n        }\n\n        element.on(css3AnimationEvents, onAnimationProgress);\n        elementData.closeAnimationFns.push(function() {\n          onEnd();\n          activeAnimationComplete();\n        });\n\n        elementData.running++;\n        animationCloseHandler(element, totalTime);\n        return onEnd;\n\n        // This will automatically be called by $animate so\n        // there is no need to attach this internally to the\n        // timeout done method.\n        function onEnd() {\n          element.off(css3AnimationEvents, onAnimationProgress);\n          $$jqLite.removeClass(element, activeClassName);\n          $$jqLite.removeClass(element, pendingClassName);\n          if (staggerTimeout) {\n            $timeout.cancel(staggerTimeout);\n          }\n          animateClose(element, className);\n          var node = extractElementNode(element);\n          for (var i in appliedStyles) {\n            node.style.removeProperty(appliedStyles[i]);\n          }\n        }\n\n        function onAnimationProgress(event) {\n          event.stopPropagation();\n          var ev = event.originalEvent || event;\n          var timeStamp = ev.$manualTimeStamp || ev.timeStamp || Date.now();\n\n          /* Firefox (or possibly just Gecko) likes to not round values up\n           * when a ms measurement is used for the animation */\n          var elapsedTime = parseFloat(ev.elapsedTime.toFixed(ELAPSED_TIME_MAX_DECIMAL_PLACES));\n\n          /* $manualTimeStamp is a mocked timeStamp value which is set\n           * within browserTrigger(). This is only here so that tests can\n           * mock animations properly. Real events fallback to event.timeStamp,\n           * or, if they don't, then a timeStamp is automatically created for them.\n           * We're checking to see if the timeStamp surpasses the expected delay,\n           * but we're using elapsedTime instead of the timeStamp on the 2nd\n           * pre-condition since animations sometimes close off early */\n          if (Math.max(timeStamp - startTime, 0) >= maxDelayTime && elapsedTime >= maxDuration) {\n            activeAnimationComplete();\n          }\n        }\n      }\n\n      function blockTransitions(node, bool) {\n        node.style[TRANSITION_PROP + PROPERTY_KEY] = bool ? 'none' : '';\n      }\n\n      function blockAnimations(node, bool) {\n        node.style[ANIMATION_PROP + ANIMATION_PLAYSTATE_KEY] = bool ? 'paused' : '';\n      }\n\n      function animateBefore(animationEvent, element, className, styles) {\n        if (animateSetup(animationEvent, element, className, styles)) {\n          return function(cancelled) {\n            cancelled && animateClose(element, className);\n          };\n        }\n      }\n\n      function animateAfter(animationEvent, element, className, afterAnimationComplete, styles) {\n        if (element.data(NG_ANIMATE_CSS_DATA_KEY)) {\n          return animateRun(animationEvent, element, className, afterAnimationComplete, styles);\n        } else {\n          animateClose(element, className);\n          afterAnimationComplete();\n        }\n      }\n\n      function animate(animationEvent, element, className, animationComplete, options) {\n        //If the animateSetup function doesn't bother returning a\n        //cancellation function then it means that there is no animation\n        //to perform at all\n        var preReflowCancellation = animateBefore(animationEvent, element, className, options.from);\n        if (!preReflowCancellation) {\n          clearCacheAfterReflow();\n          animationComplete();\n          return;\n        }\n\n        //There are two cancellation functions: one is before the first\n        //reflow animation and the second is during the active state\n        //animation. The first function will take care of removing the\n        //data from the element which will not make the 2nd animation\n        //happen in the first place\n        var cancel = preReflowCancellation;\n        afterReflow(element, function() {\n          //once the reflow is complete then we point cancel to\n          //the new cancellation function which will remove all of the\n          //animation properties from the active animation\n          cancel = animateAfter(animationEvent, element, className, animationComplete, options.to);\n        });\n\n        return function(cancelled) {\n          (cancel || noop)(cancelled);\n        };\n      }\n\n      function animateClose(element, className) {\n        $$jqLite.removeClass(element, className);\n        var data = element.data(NG_ANIMATE_CSS_DATA_KEY);\n        if (data) {\n          if (data.running) {\n            data.running--;\n          }\n          if (!data.running || data.running === 0) {\n            element.removeData(NG_ANIMATE_CSS_DATA_KEY);\n          }\n        }\n      }\n\n      return {\n        animate: function(element, className, from, to, animationCompleted, options) {\n          options = options || {};\n          options.from = from;\n          options.to = to;\n          return animate('animate', element, className, animationCompleted, options);\n        },\n\n        enter: function(element, animationCompleted, options) {\n          options = options || {};\n          return animate('enter', element, 'ng-enter', animationCompleted, options);\n        },\n\n        leave: function(element, animationCompleted, options) {\n          options = options || {};\n          return animate('leave', element, 'ng-leave', animationCompleted, options);\n        },\n\n        move: function(element, animationCompleted, options) {\n          options = options || {};\n          return animate('move', element, 'ng-move', animationCompleted, options);\n        },\n\n        beforeSetClass: function(element, add, remove, animationCompleted, options) {\n          options = options || {};\n          var className = suffixClasses(remove, '-remove') + ' ' +\n                          suffixClasses(add, '-add');\n          var cancellationMethod = animateBefore('setClass', element, className, options.from);\n          if (cancellationMethod) {\n            afterReflow(element, animationCompleted);\n            return cancellationMethod;\n          }\n          clearCacheAfterReflow();\n          animationCompleted();\n        },\n\n        beforeAddClass: function(element, className, animationCompleted, options) {\n          options = options || {};\n          var cancellationMethod = animateBefore('addClass', element, suffixClasses(className, '-add'), options.from);\n          if (cancellationMethod) {\n            afterReflow(element, animationCompleted);\n            return cancellationMethod;\n          }\n          clearCacheAfterReflow();\n          animationCompleted();\n        },\n\n        beforeRemoveClass: function(element, className, animationCompleted, options) {\n          options = options || {};\n          var cancellationMethod = animateBefore('removeClass', element, suffixClasses(className, '-remove'), options.from);\n          if (cancellationMethod) {\n            afterReflow(element, animationCompleted);\n            return cancellationMethod;\n          }\n          clearCacheAfterReflow();\n          animationCompleted();\n        },\n\n        setClass: function(element, add, remove, animationCompleted, options) {\n          options = options || {};\n          remove = suffixClasses(remove, '-remove');\n          add = suffixClasses(add, '-add');\n          var className = remove + ' ' + add;\n          return animateAfter('setClass', element, className, animationCompleted, options.to);\n        },\n\n        addClass: function(element, className, animationCompleted, options) {\n          options = options || {};\n          return animateAfter('addClass', element, suffixClasses(className, '-add'), animationCompleted, options.to);\n        },\n\n        removeClass: function(element, className, animationCompleted, options) {\n          options = options || {};\n          return animateAfter('removeClass', element, suffixClasses(className, '-remove'), animationCompleted, options.to);\n        }\n      };\n\n      function suffixClasses(classes, suffix) {\n        var className = '';\n        classes = isArray(classes) ? classes : classes.split(/\\s+/);\n        forEach(classes, function(klass, i) {\n          if (klass && klass.length > 0) {\n            className += (i > 0 ? ' ' : '') + klass + suffix;\n          }\n        });\n        return className;\n      }\n    }]);\n  }]);\n\n\n})(window, window.angular);\n"
  },
  {
    "path": "flowable-ui-web/modeler/libs/angular-cookies_1.3.13/angular-cookies.js",
    "content": "/**\n * @license AngularJS v1.3.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 module\n * @name ngCookies\n * @description\n *\n * # ngCookies\n *\n * The `ngCookies` module provides a convenient wrapper for reading and writing browser cookies.\n *\n *\n * <div doc-module-components=\"ngCookies\"></div>\n *\n * See {@link ngCookies.$cookies `$cookies`} and\n * {@link ngCookies.$cookieStore `$cookieStore`} for usage.\n */\n\n\nangular.module('ngCookies', ['ng']).\n  /**\n   * @ngdoc service\n   * @name $cookies\n   *\n   * @description\n   * Provides read/write access to browser's cookies.\n   *\n   * Only a simple Object is exposed and by adding or removing properties to/from this object, new\n   * cookies are created/deleted at the end of current $eval.\n   * The object's properties can only be strings.\n   *\n   * Requires the {@link ngCookies `ngCookies`} module to be installed.\n   *\n   * @example\n   *\n   * ```js\n   * angular.module('cookiesExample', ['ngCookies'])\n   *   .controller('ExampleController', ['$cookies', function($cookies) {\n   *     // Retrieving a cookie\n   *     var favoriteCookie = $cookies.myFavorite;\n   *     // Setting a cookie\n   *     $cookies.myFavorite = 'oatmeal';\n   *   }]);\n   * ```\n   */\n   factory('$cookies', ['$rootScope', '$browser', function($rootScope, $browser) {\n      var cookies = {},\n          lastCookies = {},\n          lastBrowserCookies,\n          runEval = false,\n          copy = angular.copy,\n          isUndefined = angular.isUndefined;\n\n      //creates a poller fn that copies all cookies from the $browser to service & inits the service\n      $browser.addPollFn(function() {\n        var currentCookies = $browser.cookies();\n        if (lastBrowserCookies != currentCookies) { //relies on browser.cookies() impl\n          lastBrowserCookies = currentCookies;\n          copy(currentCookies, lastCookies);\n          copy(currentCookies, cookies);\n          if (runEval) $rootScope.$apply();\n        }\n      })();\n\n      runEval = true;\n\n      //at the end of each eval, push cookies\n      //TODO: this should happen before the \"delayed\" watches fire, because if some cookies are not\n      //      strings or browser refuses to store some cookies, we update the model in the push fn.\n      $rootScope.$watch(push);\n\n      return cookies;\n\n\n      /**\n       * Pushes all the cookies from the service to the browser and verifies if all cookies were\n       * stored.\n       */\n      function push() {\n        var name,\n            value,\n            browserCookies,\n            updated;\n\n        //delete any cookies deleted in $cookies\n        for (name in lastCookies) {\n          if (isUndefined(cookies[name])) {\n            $browser.cookies(name, undefined);\n          }\n        }\n\n        //update all cookies updated in $cookies\n        for (name in cookies) {\n          value = cookies[name];\n          if (!angular.isString(value)) {\n            value = '' + value;\n            cookies[name] = value;\n          }\n          if (value !== lastCookies[name]) {\n            $browser.cookies(name, value);\n            updated = true;\n          }\n        }\n\n        //verify what was actually stored\n        if (updated) {\n          updated = false;\n          browserCookies = $browser.cookies();\n\n          for (name in cookies) {\n            if (cookies[name] !== browserCookies[name]) {\n              //delete or reset all cookies that the browser dropped from $cookies\n              if (isUndefined(browserCookies[name])) {\n                delete cookies[name];\n              } else {\n                cookies[name] = browserCookies[name];\n              }\n              updated = true;\n            }\n          }\n        }\n      }\n    }]).\n\n\n  /**\n   * @ngdoc service\n   * @name $cookieStore\n   * @requires $cookies\n   *\n   * @description\n   * Provides a key-value (string-object) storage, that is backed by session cookies.\n   * Objects put or retrieved from this storage are automatically serialized or\n   * deserialized by angular's toJson/fromJson.\n   *\n   * Requires the {@link ngCookies `ngCookies`} module to be installed.\n   *\n   * @example\n   *\n   * ```js\n   * angular.module('cookieStoreExample', ['ngCookies'])\n   *   .controller('ExampleController', ['$cookieStore', function($cookieStore) {\n   *     // Put cookie\n   *     $cookieStore.put('myFavorite','oatmeal');\n   *     // Get cookie\n   *     var favoriteCookie = $cookieStore.get('myFavorite');\n   *     // Removing a cookie\n   *     $cookieStore.remove('myFavorite');\n   *   }]);\n   * ```\n   */\n   factory('$cookieStore', ['$cookies', function($cookies) {\n\n      return {\n        /**\n         * @ngdoc method\n         * @name $cookieStore#get\n         *\n         * @description\n         * Returns the value of given cookie key\n         *\n         * @param {string} key Id to use for lookup.\n         * @returns {Object} Deserialized cookie value.\n         */\n        get: function(key) {\n          var value = $cookies[key];\n          return value ? angular.fromJson(value) : value;\n        },\n\n        /**\n         * @ngdoc method\n         * @name $cookieStore#put\n         *\n         * @description\n         * Sets a value for given cookie key\n         *\n         * @param {string} key Id for the `value`.\n         * @param {Object} value Value to be stored.\n         */\n        put: function(key, value) {\n          $cookies[key] = angular.toJson(value);\n        },\n\n        /**\n         * @ngdoc method\n         * @name $cookieStore#remove\n         *\n         * @description\n         * Remove given cookie\n         *\n         * @param {string} key Id of the key-value pair to delete.\n         */\n        remove: function(key) {\n          delete $cookies[key];\n        }\n      };\n\n    }]);\n\n\n})(window, window.angular);\n"
  },
  {
    "path": "flowable-ui-web/modeler/libs/angular-drag-and-drop-lists_1.2.0/angular-drag-and-drop-lists.js",
    "content": "/**\n * angular-drag-and-drop-lists v1.2.0\n *\n * Copyright (c) 2014 Marcel Juenemann mail@marcel-junemann.de\n * https://github.com/marceljuenemann/angular-drag-and-drop-lists\n *\n * License: MIT\n */\nangular.module('dndLists', [])\n\n  /**\n   * Use the dnd-draggable attribute to make your element draggable\n   *\n   * Attributes:\n   * - dnd-draggable      Required attribute. The value has to be an object that represents the data\n   *                      of the element. In case of a drag and drop operation the object will be\n   *                      serialized and unserialized on the receiving end.\n   * - dnd-selected       Callback that is invoked when the element was clicked but not dragged.\n   *                      The original click event will be provided in the local event variable.\n   * - dnd-effect-allowed Use this attribute to limit the operations that can be performed. Options:\n   *                      - \"move\": The drag operation will move the element. This is the default.\n   *                      - \"copy\": The drag operation will copy the element. Shows a copy cursor.\n   *                      - \"copyMove\": The user can choose between copy and move by pressing the\n   *                        ctrl or shift key. *Not supported in IE:* In Internet Explorer this\n   *                        option will be the same as \"copy\". *Not fully supported in Chrome on\n   *                        Windows:* In the Windows version of Chrome the cursor will always be the\n   *                        move cursor. However, when the user drops an element and has the ctrl\n   *                        key pressed, we will perform a copy anyways.\n   *                      - HTML5 also specifies the \"link\" option, but this library does not\n   *                        actively support it yet, so use it at your own risk.\n   * - dnd-moved          Callback that is invoked when the element was moved. Usually you will\n   *                      remove your element from the original list in this callback, since the\n   *                      directive is not doing that for you automatically. The original dragend\n   *                      event will be provided in the local event variable.\n   * - dnd-copied         Same as dnd-moved, just that it is called when the element was copied\n   *                      instead of moved. The original dragend event will be provided in the local\n   *                      event variable.\n   * - dnd-dragstart      Callback that is invoked when the element was dragged. The original\n   *                      dragstart event will be provided in the local event variable.\n   * - dnd-type           Use this attribute if you have different kinds of items in your\n   *                      application and you want to limit which items can be dropped into which\n   *                      lists. Combine with dnd-allowed-types on the dnd-list(s). This attribute\n   *                      should evaluate to a string, although this restriction is not enforced.\n   * - dnd-disable-if     You can use this attribute to dynamically disable the draggability of the\n   *                      element. This is useful if you have certain list items that you don't want\n   *                      to be draggable, or if you want to disable drag & drop completely without\n   *                      having two different code branches (e.g. only allow for admins).\n   *                      **Note**: If your element is not draggable, the user is probably able to\n   *                      select text or images inside of it. Since a selection is always draggable,\n   *                      this breaks your UI. You most likely want to disable user selection via\n   *                      CSS (see user-select).\n   *\n   * CSS classes:\n   * - dndDragging        This class will be added to the element while the element is being\n   *                      dragged. It will affect both the element you see while dragging and the\n   *                      source element that stays at it's position. Do not try to hide the source\n   *                      element with this class, because that will abort the drag operation.\n   * - dndDraggingSource  This class will be added to the element after the drag operation was\n   *                      started, meaning it only affects the original element that is still at\n   *                      it's source position, and not the \"element\" that the user is dragging with\n   *                      his mouse pointer.\n   */\n  .directive('dndDraggable', ['$parse', '$timeout', 'dndDropEffectWorkaround', 'dndDragTypeWorkaround',\n                      function($parse,   $timeout,   dndDropEffectWorkaround,   dndDragTypeWorkaround) {\n    return function(scope, element, attr) {\n      // Set the HTML5 draggable attribute on the element\n      element.attr(\"draggable\", \"true\");\n\n      // If the dnd-disable-if attribute is set, we have to watch that\n      if (attr.dndDisableIf) {\n        scope.$watch(attr.dndDisableIf, function(disabled) {\n          element.attr(\"draggable\", !disabled);\n        });\n      }\n\n      /**\n       * When the drag operation is started we have to prepare the dataTransfer object,\n       * which is the primary way we communicate with the target element\n       */\n      element.on('dragstart', function(event) {\n        event = event.originalEvent || event;\n\n        // Serialize the data associated with this element. IE only supports the Text drag type\n        event.dataTransfer.setData(\"Text\", angular.toJson(scope.$eval(attr.dndDraggable)));\n\n        // Only allow actions specified in dnd-effect-allowed attribute\n        event.dataTransfer.effectAllowed = attr.dndEffectAllowed || \"move\";\n\n        // Add CSS classes. See documentation above\n        element.addClass(\"dndDragging\");\n\n        // Workarounds for stupid browsers, see description below\n        dndDropEffectWorkaround.dropEffect = \"none\";\n        dndDragTypeWorkaround.isDragging = true;\n\n        // <FLOWABLE>\n        // This code was originally placed after element.addClass.\n        // This timeout is invoked after the 'dragend' event in IE9 (at leats on slooow virtual box)\n        // and since this class is used to hide elements it seems like the element is gone,\n        // therefor make sure the dragging still is happening when adding this class\n        $timeout(function() {\n          // Flowable This code\n          if (dndDragTypeWorkaround.isDragging) {\n            element.addClass(\"dndDraggingSource\");\n          }\n        }, 0);\n        // </FLOWABLE>\n\n        // Save type of item in global state. Usually, this would go into the dataTransfer\n        // typename, but we have to use \"Text\" there to support IE\n        dndDragTypeWorkaround.dragType = attr.dndType ? scope.$eval(attr.dndType) : undefined;\n\n        // Invoke callback\n        $parse(attr.dndDragstart)(scope, {event: event});\n\n        event.stopPropagation();\n      });\n\n      /**\n       * The dragend event is triggered when the element was dropped or when the drag\n       * operation was aborted (e.g. hit escape button). Depending on the executed action\n       * we will invoke the callbacks specified with the dnd-moved or dnd-copied attribute.\n       */\n      element.on('dragend', function(event) {\n        event = event.originalEvent || event;\n\n        // Invoke callbacks. Usually we would use event.dataTransfer.dropEffect to determine\n        // the used effect, but Chrome has not implemented that field correctly. On Windows\n        // it always sets it to 'none', while Chrome on Linux sometimes sets it to something\n        // else when it's supposed to send 'none' (drag operation aborted).\n        var dropEffect = dndDropEffectWorkaround.dropEffect;\n        scope.$apply(function() {\n          switch (dropEffect) {\n            case \"move\":\n              $parse(attr.dndMoved)(scope, {event: event});\n              break;\n\n            case \"copy\":\n              $parse(attr.dndCopied)(scope, {event: event});\n              break;\n          }\n        });\n\n        // Clean up\n        element.removeClass(\"dndDragging\");\n        element.removeClass(\"dndDraggingSource\");\n        dndDragTypeWorkaround.isDragging = false;\n        event.stopPropagation();\n      });\n\n      /**\n       * When the element is clicked we invoke the callback function\n       * specified with the dnd-selected attribute.\n       */\n      element.on('click', function(event) {\n        event = event.originalEvent || event;\n\n        scope.$apply(function() {\n          $parse(attr.dndSelected)(scope, {event: event});\n        });\n\n        event.stopPropagation();\n      });\n\n      /**\n       * Workaround to make element draggable in IE9\n       */\n      element.on('selectstart', function() {\n        if (this.dragDrop) this.dragDrop();\n        return false;\n      });\n    };\n  }])\n\n  /**\n   * Use the dnd-list attribute to make your list element a dropzone. Usually you will add a single\n   * li element as child with the ng-repeat directive. If you don't do that, we will not be able to\n   * position the dropped element correctly. If you want your list to be sortable, also add the\n   * dnd-draggable directive to your li element(s). Both the dnd-list and it's direct children must\n   * have position: relative CSS style, otherwise the positioning algorithm will not be able to\n   * determine the correct placeholder position in all browsers.\n   *\n   * Attributes:\n   * - dnd-list             Required attribute. The value has to be the array in which the data of\n   *                        the dropped element should be inserted.\n   * - dnd-allowed-types    Optional array of allowed item types. When used, only items that had a\n   *                        matching dnd-type attribute will be dropable.\n   * - dnd-disable-if       Optional boolean expresssion. When it evaluates to true, no dropping\n   *                        into the list is possible. Note that this also disables rearranging\n   *                        items inside the list.\n   * - dnd-horizontal-list  Optional boolean expresssion. When it evaluates to true, the positioning\n   *                        algorithm will use the left and right halfs of the list items instead of\n   *                        the upper and lower halfs.\n   * - dnd-dragover         Optional expression that is invoked when an element is dragged over the\n   *                        list. If the expression is set, but does not return true, the element is\n   *                        not allowed to be dropped. The following variables will be available:\n   *                        - event: The original dragover event sent by the browser.\n   *                        - index: The position in the list at which the element would be dropped.\n   *                        - type: The dnd-type set on the dnd-draggable, or undefined if unset.\n   * - dnd-drop             Optional expression that is invoked when an element is dropped over the\n   *                        list. If the expression is set, it must return the object that will be\n   *                        inserted into the list. If it returns false, the drop will be aborted\n   *                        and the event is propagated. The following variables will be available:\n   *                        - event: The original drop event sent by the browser.\n   *                        - index: The position in the list at which the element would be dropped.\n   *                        - item: The transferred object.\n   *                        - type: The dnd-type set on the dnd-draggable, or undefined if unset.\n   * - dnd-external-sources Optional boolean expression. When it evaluates to true, the list accepts\n   *                        drops from sources outside of the current browser tab. This allows to\n   *                        drag and drop accross different browser tabs. Note that this will allow\n   *                        to drop arbitrary text into the list, thus it is highly recommended to\n   *                        implement the dnd-drop callback to check the incoming element for\n   *                        sanity. Furthermore, the dnd-type of external sources can not be\n   *                        determined, therefore do not rely on restrictions of dnd-allowed-type.\n   *\n   * CSS classes:\n   * - dndPlaceholder       When an element is dragged over the list, a new placeholder child\n   *                        element will be added. This element is of type li and has the class\n   *                        dndPlaceholder set.\n   * - dndDragover          Will be added to the list while an element is dragged over the list.\n   */\n  .directive('dndList', ['$parse', '$timeout', 'dndDropEffectWorkaround', 'dndDragTypeWorkaround',\n                 function($parse,   $timeout,   dndDropEffectWorkaround,   dndDragTypeWorkaround) {\n    return function(scope, element, attr) {\n      // While an element is dragged over the list, this placeholder element is inserted\n      // at the location where the element would be inserted after dropping\n      var placeholder = angular.element(\"<li class='dndPlaceholder'></li>\");\n      var placeholderNode = placeholder[0];\n      var listNode = element[0];\n\n      var horizontal = attr.dndHorizontalList && scope.$eval(attr.dndHorizontalList);\n      var externalSources = attr.dndExternalSources && scope.$eval(attr.dndExternalSources);\n\n      /**\n       * The dragover event is triggered \"every few hundred milliseconds\" while an element\n       * is being dragged over our list, or over an child element.\n       */\n      element.on('dragover', function(event) {\n        event = event.originalEvent || event;\n\n        if (!isDropAllowed(event)) {\n            return true;\n        }\n\n        // First of all, make sure that the placeholder is shown\n        // This is especially important if the list is empty\n        if (placeholderNode.parentNode != listNode) {\n          element.append(placeholder);\n        }\n\n        if (event.target !== listNode) {\n          // Try to find the node direct directly below the list node.\n          var listItemNode = event.target;\n          while (listItemNode.parentNode !== listNode && listItemNode.parentNode) {\n            listItemNode = listItemNode.parentNode;\n          }\n\n          if (listItemNode.parentNode === listNode && listItemNode !== placeholderNode) {\n            // If the mouse pointer is in the upper half of the child element,\n            // we place it before the child element, otherwise below it.\n            if (isMouseInFirstHalf(event, listItemNode)) {\n              listNode.insertBefore(placeholderNode, listItemNode);\n            } else {\n              listNode.insertBefore(placeholderNode, listItemNode.nextSibling);\n            }\n          }\n        } else {\n          // This branch is reached when we are dragging directly over the list element.\n          // Usually we wouldn't need to do anything here, but the IE does not fire it's\n          // events for the child element, only for the list directly. Therefore we repeat\n          // the positioning algorithm for IE here.\n          if (isMouseInFirstHalf(event, placeholderNode, true)) {\n            // Check if we should move the placeholder element one spot towards the top.\n            // Note that display none elements will have offsetTop and offsetHeight set to\n            // zero, therefore we need a special check for them.\n            while (placeholderNode.previousElementSibling\n                 && (isMouseInFirstHalf(event, placeholderNode.previousElementSibling, true)\n                 || placeholderNode.previousElementSibling.offsetHeight === 0)) {\n              listNode.insertBefore(placeholderNode, placeholderNode.previousElementSibling);\n            }\n          } else {\n            // Check if we should move the placeholder element one spot towards the bottom\n            while (placeholderNode.nextElementSibling &&\n                 !isMouseInFirstHalf(event, placeholderNode.nextElementSibling, true)) {\n              listNode.insertBefore(placeholderNode,\n                  placeholderNode.nextElementSibling.nextElementSibling);\n            }\n          }\n        }\n\n        // At this point we invoke the callback, which still can disallow the drop.\n        // We can't do this earlier because we want to pass the index of the placeholder.\n        if (attr.dndDragover && !invokeCallback(attr.dndDragover, event)) {\n          return stopDragover();\n        }\n\n        element.addClass(\"dndDragover\");\n        event.preventDefault();\n        event.stopPropagation();\n        return false;\n      });\n\n      /**\n       * When the element is dropped, we use the position of the placeholder element as the\n       * position where we insert the transferred data. This assumes that the list has exactly\n       * one child element per array element.\n       */\n      element.on('drop', function(event) {\n        event = event.originalEvent || event;\n\n        if (!isDropAllowed(event)) return true;\n\n        // The default behavior in Firefox is to interpret the dropped element as URL and\n        // forward to it. We want to prevent that even if our drop is aborted.\n        event.preventDefault();\n\n        // Unserialize the data that was serialized in dragstart. According to the HTML5 specs,\n        // the \"Text\" drag type will be converted to text/plain, but IE does not do that.\n        var data = event.dataTransfer.getData(\"Text\") || event.dataTransfer.getData(\"text/plain\");\n        var transferredObject;\n        try {\n          transferredObject = JSON.parse(data);\n        } catch(e) {\n          return stopDragover();\n        }\n\n        // Invoke the callback, which can transform the transferredObject and even abort the drop.\n        if (attr.dndDrop) {\n          transferredObject = invokeCallback(attr.dndDrop, event, transferredObject);\n          if (!transferredObject) {\n            return stopDragover();\n          }\n        }\n\n        // Retrieve the JSON array and insert the transferred object into it.\n        var targetArray = scope.$eval(attr.dndList);\n        scope.$apply(function() {\n          targetArray.splice(getPlaceholderIndex(), 0, transferredObject);\n        });\n\n        // Invoke the callback, after the transfered objrct is added to the new container.\n        if (attr.dndAfterDrop) {\n           invokeCallback(attr.dndAfterDrop, event, transferredObject);\n        }\n        // In Chrome on Windows the dropEffect will always be none...\n        // We have to determine the actual effect manually from the allowed effects\n        if (event.dataTransfer.dropEffect === \"none\") {\n          if (event.dataTransfer.effectAllowed === \"copy\" ||\n              event.dataTransfer.effectAllowed === \"move\") {\n            dndDropEffectWorkaround.dropEffect = event.dataTransfer.effectAllowed;\n          } else {\n            dndDropEffectWorkaround.dropEffect = event.ctrlKey ? \"copy\" : \"move\";\n          }\n        } else {\n          dndDropEffectWorkaround.dropEffect = event.dataTransfer.dropEffect;\n        }\n\n        // Clean up\n        stopDragover();\n        event.stopPropagation();\n        return false;\n      });\n\n      /**\n       * We have to remove the placeholder when the element is no longer dragged over our list. The\n       * problem is that the dragleave event is not only fired when the element leaves our list,\n       * but also when it leaves a child element -- so practically it's fired all the time. As a\n       * workaround we wait a few milliseconds and then check if the dndDragover class was added\n       * again. If it is there, dragover must have been called in the meantime, i.e. the element\n       * is still dragging over the list. If you know a better way of doing this, please tell me!\n       */\n      element.on('dragleave', function(event) {\n        event = event.originalEvent || event;\n\n        element.removeClass(\"dndDragover\");\n        $timeout(function() {\n          if (!element.hasClass(\"dndDragover\")) {\n            placeholder.remove();\n          }\n        }, 100);\n      });\n\n      /**\n       * Checks whether the mouse pointer is in the first half of the given target element.\n       *\n       * In Chrome we can just use offsetY, but in Firefox we have to use layerY, which only\n       * works if the child element has position relative. In IE the events are only triggered\n       * on the listNode instead of the listNodeItem, therefore the mouse positions are\n       * relative to the parent element of targetNode.\n       */\n      function isMouseInFirstHalf(event, targetNode, relativeToParent) {\n        var mousePointer = horizontal ? (event.offsetX || event.layerX)\n                                      : (event.offsetY || event.layerY);\n        var targetSize = horizontal ? targetNode.offsetWidth : targetNode.offsetHeight;\n        var targetPosition = horizontal ? targetNode.offsetLeft : targetNode.offsetTop;\n        targetPosition = relativeToParent ? targetPosition : 0;\n        return mousePointer < targetPosition + targetSize / 2;\n      }\n\n        /**\n         * Flowable-patched version of isMouseInFirstHalf that uses page and bounding client rect\n         * instead of the offsetX and layerX properties to determine which half of target the mouse pointer is hovering\n         * this is more natural since th method now actually works like above, but it also adds some mild\n         * flickering when sorting inside the list, why its still not in use.\n         */\n        function isMouseInFirstHalf_new(event, targetNode, relativeToParent) {\n            var targetNodeRect = targetNode.getBoundingClientRect();\n            if (horizontal) {\n                return (event.pageX - targetNodeRect.left) < (targetNodeRect.width / 2);\n            }\n            else {\n                return (event.pageY - targetNodeRect.top) < (targetNodeRect.height / 2);\n            }\n        }\n      /**\n       * We use the position of the placeholder node to determine at which position of the array the\n       * object needs to be inserted\n       */\n      function getPlaceholderIndex() {\n        return Array.prototype.indexOf.call(listNode.children, placeholderNode);\n      }\n\n      /**\n       * Checks various conditions that must be fulfilled for a drop to be allowed\n       */\n      function isDropAllowed(event) {\n        // Disallow drop from external source unless it's allowed explicitly.\n        if (!dndDragTypeWorkaround.isDragging && !externalSources) return false;\n\n        // Check mimetype. Usually we would use a custom drag type instead of Text, but IE doesn't\n        // support that.\n        if (!hasTextMimetype(event.dataTransfer.types)) return false;\n\n        // Now check the dnd-allowed-types against the type of the incoming element. For drops from\n        // external sources we don't know the type, so it will need to be checked via dnd-drop.\n        if (attr.dndAllowedTypes && dndDragTypeWorkaround.isDragging) {\n          var allowed = scope.$eval(attr.dndAllowedTypes);\n          if (angular.isArray(allowed) && allowed.indexOf(dndDragTypeWorkaround.dragType) === -1) {\n            return false;\n          }\n        }\n\n        // Check whether droping is disabled completely\n        if (attr.dndDisableIf && scope.$eval(attr.dndDisableIf)) return false;\n\n        return true;\n      }\n\n      /**\n       * Small helper function that cleans up if we aborted a drop.\n       */\n      function stopDragover() {\n        placeholder.remove();\n        element.removeClass(\"dndDragover\");\n        return true;\n      }\n\n      /**\n       * Invokes a callback with some interesting parameters and returns the callbacks return value.\n       */\n      function invokeCallback(expression, event, item) {\n        return $parse(expression)(scope, {\n          event: event,\n          index: getPlaceholderIndex(),\n          item: item || undefined,\n          external: !dndDragTypeWorkaround.isDragging,\n          type: dndDragTypeWorkaround.isDragging ? dndDragTypeWorkaround.dragType : undefined\n        });\n      }\n\n      /**\n       * Check if the dataTransfer object contains a drag type that we can handle. In old versions\n       * of IE the types collection will not even be there, so we just assume a drop is possible.\n       */\n      function hasTextMimetype(types) {\n        if (!types) return true;\n        for (var i = 0; i < types.length; i++) {\n          if (types[i] === \"Text\" || types[i] === \"text/plain\") return true;\n        }\n\n        return false;\n      }\n    };\n  }])\n\n  /**\n   * This workaround handles the fact that Internet Explorer does not support drag types other than\n   * \"Text\" and \"URL\". That means we can not know whether the data comes from one of our elements or\n   * is just some other data like a text selection. As a workaround we save the isDragging flag in\n   * here. When a dropover event occurs, we only allow the drop if we are already dragging, because\n   * that means the element is ours.\n   */\n  .factory('dndDragTypeWorkaround', function(){ return {} })\n\n  /**\n   * Chrome on Windows does not set the dropEffect field, which we need in dragend to determine\n   * whether a drag operation was successful. Therefore we have to maintain it in this global\n   * variable. The bug report for that has been open for years:\n   * https://code.google.com/p/chromium/issues/detail?id=39399\n   */\n  .factory('dndDropEffectWorkaround', function(){ return {} });\n"
  },
  {
    "path": "flowable-ui-web/modeler/libs/angular-dragdrop_1.0.11/angular-dragdrop.js",
    "content": "/**\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\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell 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\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\n/**\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.11\n *\n * (c) 2013 Amit Gharat a.k.a codef0rmer <amit.2006.it@gmail.com> - amitgharat.wordpress.com\n */\n\n(function (window, angular, $, undefined) {\n    'use strict';\n\n    var jqyoui = angular.module('ngDragDrop', []).service('ngDragDropService', ['$timeout', '$parse', function($timeout, $parse) {\n        this.draggableScope = null;\n        this.droppableScope = null;\n\n        this.callEventCallback = function (scope, callbackName, event, ui) {\n            if (!callbackName) return;\n\n            var objExtract = extract(callbackName),\n                callback = objExtract.callback,\n                constructor = objExtract.constructor,\n                args = [event, ui].concat(objExtract.args);\n\n            // call either $scoped method i.e. $scope.dropCallback or constructor's method i.e. this.dropCallback.\n            // Removing scope.$apply call that was performance intensive (especially onDrag) and does not require it\n            // always. So call it within the callback if needed.\n            return (scope[callback] || scope[constructor][callback]).apply(scope, args);\n\n            function extract(callbackName) {\n                var atStartBracket = callbackName.indexOf('(') !== -1 ? callbackName.indexOf('(') : callbackName.length,\n                    atEndBracket = callbackName.lastIndexOf(')') !== -1 ? callbackName.lastIndexOf(')') : callbackName.length,\n                    args = callbackName.substring(atStartBracket + 1, atEndBracket), // matching function arguments inside brackets\n                    constructor = callbackName.match(/^[^.]+.\\s*/)[0].slice(0, -1); // matching a string upto a dot to check ctrl as syntax\n                constructor = scope[constructor] && typeof scope[constructor].constructor === 'function' ? constructor : null;\n\n                return {\n                    callback: callbackName.substring(constructor && constructor.length + 1 || 0, atStartBracket),\n                    args: $.map(args && args.split(',') || [], function(item) { return [$parse(item)(scope)]; }),\n                    constructor: constructor\n                }\n            }\n        };\n\n        this.invokeDrop = function ($draggable, $droppable, event, ui) {\n            var dragModel = '',\n                dropModel = '',\n                dragSettings = {},\n                dropSettings = {},\n                jqyoui_pos = null,\n                dragItem = {},\n                dropItem = {},\n                dragModelValue,\n                dropModelValue,\n                $droppableDraggable = null,\n                droppableScope = this.droppableScope,\n                draggableScope = this.draggableScope;\n\n            dragModel = $draggable.ngattr('ng-model');\n            dropModel = $droppable.ngattr('ng-model');\n            dragModelValue = draggableScope.$eval(dragModel);\n            dropModelValue = droppableScope.$eval(dropModel);\n\n            $droppableDraggable = $droppable.find('[jqyoui-draggable]:last,[data-jqyoui-draggable]:last');\n            dropSettings = droppableScope.$eval($droppable.attr('jqyoui-droppable') || $droppable.attr('data-jqyoui-droppable')) || [];\n            dragSettings = draggableScope.$eval($draggable.attr('jqyoui-draggable') || $draggable.attr('data-jqyoui-draggable')) || [];\n\n            // Helps pick up the right item\n            dragSettings.index = this.fixIndex(draggableScope, dragSettings, dragModelValue);\n            dropSettings.index = this.fixIndex(droppableScope, dropSettings, dropModelValue);\n\n            jqyoui_pos = angular.isArray(dragModelValue) ? dragSettings.index : null;\n            dragItem = angular.isArray(dragModelValue) ? dragModelValue[jqyoui_pos] : dragModelValue;\n\n            if (dragSettings.deepCopy) {\n                dragItem = angular.copy(dragItem);\n            }\n\n            if (angular.isArray(dropModelValue) && dropSettings && dropSettings.index !== undefined) {\n                dropItem = dropModelValue[dropSettings.index];\n            } else if (!angular.isArray(dropModelValue)) {\n                dropItem = dropModelValue;\n            } else {\n                dropItem = {};\n            }\n\n            if (dropSettings.deepCopy) {\n                dropItem = angular.copy(dropItem);\n            }\n\n            if (dragSettings.animate === true) {\n                this.move($draggable, $droppableDraggable.length > 0 ? $droppableDraggable : $droppable, null, 'fast', dropSettings, null);\n                this.move($droppableDraggable.length > 0 && !dropSettings.multiple ? $droppableDraggable : [], $draggable.parent('[jqyoui-droppable],[data-jqyoui-droppable]'), jqyoui.startXY, 'fast', dropSettings, angular.bind(this, function() {\n                    $timeout(angular.bind(this, function() {\n                        // Do not move this into move() to avoid flickering issue\n                        $draggable.css({'position': 'relative', 'left': '', 'top': ''});\n                        // Angular v1.2 uses ng-hide to hide an element not display property\n                        // so we've to manually remove display:none set in this.move()\n                        $droppableDraggable.css({'position': 'relative', 'left': '', 'top': '', 'display': $droppableDraggable.css('display') === 'none' ? '' : $droppableDraggable.css('display')});\n\n                        this.mutateDraggable(draggableScope, dropSettings, dragSettings, dragModel, dropModel, dropItem, $draggable);\n                        this.mutateDroppable(droppableScope, dropSettings, dragSettings, dropModel, dragItem, jqyoui_pos);\n                        this.callEventCallback(droppableScope, dropSettings.onDrop, event, ui);\n                    }));\n                }));\n            } else {\n                $timeout(angular.bind(this, function() {\n                    this.mutateDraggable(draggableScope, dropSettings, dragSettings, dragModel, dropModel, dropItem, $draggable);\n                    this.mutateDroppable(droppableScope, dropSettings, dragSettings, dropModel, dragItem, jqyoui_pos);\n                    this.callEventCallback(droppableScope, dropSettings.onDrop, event, ui);\n                }));\n            }\n        };\n\n        this.move = function($fromEl, $toEl, toPos, duration, dropSettings, callback) {\n            if ($fromEl.length === 0) {\n                if (callback) {\n                    window.setTimeout(function() {\n                        callback();\n                    }, 300);\n                }\n                return false;\n            }\n\n            var zIndex = $fromEl.css('z-index'),\n                fromPos = $fromEl[dropSettings.containment || 'offset'](),\n                displayProperty = $toEl.css('display'), // sometimes `display` is other than `block`\n                hadNgHideCls = $toEl.hasClass('ng-hide');\n\n            if (toPos === null && $toEl.length > 0) {\n                if (($toEl.attr('jqyoui-draggable') || $toEl.attr('data-jqyoui-draggable')) !== undefined && $toEl.ngattr('ng-model') !== undefined && $toEl.is(':visible') && dropSettings && dropSettings.multiple) {\n                    toPos = $toEl[dropSettings.containment || 'offset']();\n                    if (dropSettings.stack === false) {\n                        toPos.left+= $toEl.outerWidth(true);\n                    } else {\n                        toPos.top+= $toEl.outerHeight(true);\n                    }\n                } else {\n                    // Angular v1.2 uses ng-hide to hide an element\n                    // so we've to remove it in order to grab its position\n                    if (hadNgHideCls) $toEl.removeClass('ng-hide');\n                    toPos = $toEl.css({'visibility': 'hidden', 'display': 'block'})[dropSettings.containment || 'offset']();\n                    $toEl.css({'visibility': '','display': displayProperty});\n                }\n            }\n\n            $fromEl.css({'position': 'absolute', 'z-index': 9999})\n                .css(fromPos)\n                .animate(toPos, duration, function() {\n                    // Angular v1.2 uses ng-hide to hide an element\n                    // and as we remove it above, we've to put it back to\n                    // hide the element (while swapping) if it was hidden already\n                    // because we remove the display:none in this.invokeDrop()\n                    if (hadNgHideCls) $toEl.addClass('ng-hide');\n                    $fromEl.css('z-index', zIndex);\n                    if (callback) callback();\n                });\n        };\n\n        this.mutateDroppable = function(scope, dropSettings, dragSettings, dropModel, dragItem, jqyoui_pos) {\n            var dropModelValue = scope.$eval(dropModel);\n\n            scope.dndDragItem = dragItem;\n\n            if (angular.isArray(dropModelValue)) {\n                if (dropSettings && dropSettings.index >= 0) {\n                    dropModelValue[dropSettings.index] = dragItem;\n                } else {\n                    dropModelValue.push(dragItem);\n                }\n                if (dragSettings && dragSettings.placeholder === true) {\n                    dropModelValue[dropModelValue.length - 1]['jqyoui_pos'] = jqyoui_pos;\n                }\n            } else {\n                $parse(dropModel + ' = dndDragItem')(scope);\n                if (dragSettings && dragSettings.placeholder === true) {\n                    dropModelValue['jqyoui_pos'] = jqyoui_pos;\n                }\n            }\n        };\n\n        this.mutateDraggable = function(scope, dropSettings, dragSettings, dragModel, dropModel, dropItem, $draggable) {\n            var isEmpty = angular.equals(dropItem, {}) || !dropItem,\n                dragModelValue = scope.$eval(dragModel);\n\n            scope.dndDropItem = dropItem;\n\n            if (dragSettings && dragSettings.placeholder) {\n                if (dragSettings.placeholder != 'keep'){\n                    if (angular.isArray(dragModelValue) && dragSettings.index !== undefined) {\n                        dragModelValue[dragSettings.index] = dropItem;\n                    } else {\n                        $parse(dragModel + ' = dndDropItem')(scope);\n                    }\n                }\n            } else {\n                if (angular.isArray(dragModelValue)) {\n                    if (isEmpty) {\n                        if (dragSettings && ( dragSettings.placeholder !== true && dragSettings.placeholder !== 'keep' )) {\n                            dragModelValue.splice(dragSettings.index, 1);\n                        }\n                    } else {\n                        dragModelValue[dragSettings.index] = dropItem;\n                    }\n                } else {\n                    // Fix: LIST(object) to LIST(array) - model does not get updated using just scope[dragModel] = {...}\n                    // P.S.: Could not figure out why it happened\n                    $parse(dragModel + ' = dndDropItem')(scope);\n                    if (scope.$parent) {\n                        $parse(dragModel + ' = dndDropItem')(scope.$parent);\n                    }\n                }\n            }\n\n            $draggable.css({'z-index': '', 'left': '', 'top': ''});\n        };\n\n        this.fixIndex = function(scope, settings, modelValue) {\n            if (settings.applyFilter && angular.isArray(modelValue) && modelValue.length > 0) {\n                var dragModelValueFiltered = scope[settings.applyFilter](),\n                    lookup = dragModelValueFiltered[settings.index],\n                    actualIndex = undefined;\n\n                modelValue.forEach(function(item, i) {\n                    if (angular.equals(item, lookup)) {\n                        actualIndex = i;\n                    }\n                });\n\n                return actualIndex;\n            }\n\n            return settings.index;\n        };\n    }]).directive('jqyouiDraggable', ['ngDragDropService', function(ngDragDropService) {\n        return {\n            require: '?jqyouiDroppable',\n            restrict: 'A',\n            link: function(scope, element, attrs) {\n                var dragSettings, jqyouiOptions, zIndex;\n                var updateDraggable = function(newValue, oldValue) {\n                    if (newValue) {\n                        dragSettings = scope.$eval(element.attr('jqyoui-draggable') || element.attr('data-jqyoui-draggable')) || {};\n                        jqyouiOptions = scope.$eval(attrs.jqyouiOptions) || {};\n                        element\n                            .draggable({disabled: false})\n                            .draggable(jqyouiOptions)\n                            .draggable({\n                                start: function(event, ui) {\n                                    ngDragDropService.draggableScope = scope;\n                                    zIndex = angular.element(jqyouiOptions.helper ? ui.helper : this).css('z-index');\n                                    angular.element(jqyouiOptions.helper ? ui.helper : this).css('z-index', 9999);\n                                    jqyoui.startXY = angular.element(this)[dragSettings.containment || 'offset']();\n                                    ngDragDropService.callEventCallback(scope, dragSettings.onStart, event, ui);\n                                },\n                                stop: function(event, ui) {\n                                    angular.element(jqyouiOptions.helper ? ui.helper : this).css('z-index', zIndex);\n                                    ngDragDropService.callEventCallback(scope, dragSettings.onStop, event, ui);\n                                },\n                                drag: function(event, ui) {\n                                    ngDragDropService.callEventCallback(scope, dragSettings.onDrag, event, ui);\n                                }\n                            });\n                    } else {\n                        element.draggable({disabled: true});\n                    }\n                };\n                scope.$watch(function() { return scope.$eval(attrs.drag); }, updateDraggable);\n                updateDraggable();\n\n                element.on('$destroy', function() {\n                    element.draggable({disabled: true}).draggable('destroy');\n                });\n            }\n        };\n    }]).directive('jqyouiDroppable', ['ngDragDropService', '$q', function(ngDragDropService, $q) {\n        return {\n            restrict: 'A',\n            priority: 1,\n            link: function(scope, element, attrs) {\n                var dropSettings;\n                var updateDroppable = function(newValue, oldValue) {\n                    if (newValue) {\n                        dropSettings = scope.$eval(angular.element(element).attr('jqyoui-droppable') || angular.element(element).attr('data-jqyoui-droppable')) || {};\n                        element\n                            .droppable({disabled: false})\n                            .droppable(scope.$eval(attrs.jqyouiOptions) || {})\n                            .droppable({\n                                over: function(event, ui) {\n                                    ngDragDropService.callEventCallback(scope, dropSettings.onOver, event, ui);\n                                },\n                                out: function(event, ui) {\n                                    ngDragDropService.callEventCallback(scope, dropSettings.onOut, event, ui);\n                                },\n                                drop: function(event, ui) {\n                                    var beforeDropPromise = null;\n\n                                    if (dropSettings.beforeDrop) {\n                                        beforeDropPromise = ngDragDropService.callEventCallback(scope, dropSettings.beforeDrop, event, ui);\n                                    } else {\n                                        beforeDropPromise = (function() {\n                                            var deferred = $q.defer();\n                                            deferred.resolve();\n                                            return deferred.promise;\n                                        })();\n                                    }\n\n                                    beforeDropPromise.then(angular.bind(this, function() {\n                                        if (angular.element(ui.draggable).ngattr('ng-model') && attrs.ngModel) {\n                                            ngDragDropService.droppableScope = scope;\n                                            ngDragDropService.invokeDrop(angular.element(ui.draggable), angular.element(this), event, ui);\n                                        } else {\n                                            ngDragDropService.callEventCallback(scope, dropSettings.onDrop, event, ui);\n                                        }\n                                    }), function() {\n                                        ui.draggable.css({left: '', top: ''});\n                                    });\n                                }\n                            });\n                    } else {\n                        element.droppable({disabled: true});\n                    }\n                };\n\n                scope.$watch(function() { return scope.$eval(attrs.drop); }, updateDroppable);\n                updateDroppable();\n\n                element.on('$destroy', function() {\n                    element.droppable({disabled: true}).droppable('destroy');\n                });\n            }\n        };\n    }]);\n\n    angular.element.prototype.ngattr = function(name, value) {\n        var element = angular.element(this).get(0);\n\n        return element.getAttribute(name) || element.getAttribute('data-' + name);\n    };\n})(window, window.angular, window.jQuery);"
  },
  {
    "path": "flowable-ui-web/modeler/libs/angular-gridster_0.11.7/angular-gridster.js",
    "content": "(function(angular) {\n\n    'use strict';\n\n    angular.module('gridster', [])\n\n        .constant('gridsterConfig', {\n            columns: 6, // number of columns in the grid\n            pushing: true, // whether to push other items out of the way\n            floating: true, // whether to automatically float items up so they stack\n            swapping: false, // whether or not to have items switch places instead of push down if they are the same size\n            width: 'auto', // width of the grid. \"auto\" will expand the grid to its parent container\n            colWidth: 'auto', // width of grid columns. \"auto\" will divide the width of the grid evenly among the columns\n            rowHeight: 'match', // height of grid rows. 'match' will make it the same as the column width, a numeric value will be interpreted as pixels, '/2' is half the column width, '*5' is five times the column width, etc.\n            margins: [10, 10], // margins in between grid items\n            outerMargin: true,\n            isMobile: false, // toggle mobile view\n            mobileBreakPoint: 600, // width threshold to toggle mobile mode\n            mobileModeEnabled: true, // whether or not to toggle mobile mode when screen width is less than mobileBreakPoint\n            minColumns: 1, // minimum amount of columns the grid can scale down to\n            minRows: 1, // minimum amount of rows to show if the grid is empty\n            maxRows: 100, // maximum amount of rows in the grid\n            defaultSizeX: 2, // default width of an item in columns\n            defaultSizeY: 1, // default height of an item in rows\n            minSizeX: 1, // minimum column width of an item\n            maxSizeX: null, // maximum column width of an item\n            minSizeY: 1, // minumum row height of an item\n            maxSizeY: null, // maximum row height of an item\n            saveGridItemCalculatedHeightInMobile: false, // grid item height in mobile display. true- to use the calculated height by sizeY given\n            resizable: { // options to pass to resizable handler\n                enabled: true,\n                handles: ['s', 'e', 'n', 'w', 'se', 'ne', 'sw', 'nw']\n            },\n            draggable: { // options to pass to draggable handler\n                enabled: true,\n                scrollSensitivity: 20, // Distance in pixels from the edge of the viewport after which the viewport should scroll, relative to pointer\n                scrollSpeed: 15 // Speed at which the window should scroll once the mouse pointer gets within scrollSensitivity distance\n            }\n        })\n\n        .controller('GridsterCtrl', ['gridsterConfig', '$timeout',\n            function(gridsterConfig, $timeout) {\n\n                var gridster = this;\n\n                /**\n                 * Create options from gridsterConfig constant\n                 */\n                angular.extend(this, gridsterConfig);\n\n                this.resizable = angular.extend({}, gridsterConfig.resizable || {});\n                this.draggable = angular.extend({}, gridsterConfig.draggable || {});\n\n                var flag = false;\n                this.layoutChanged = function() {\n                    if (flag) {\n                        return;\n                    }\n                    flag = true;\n                    $timeout(function() {\n                        flag = false;\n                        if (gridster.loaded) {\n                            gridster.floatItemsUp();\n                        }\n                        gridster.updateHeight(gridster.movingItem ? gridster.movingItem.sizeY : 0);\n                    });\n                };\n\n                /**\n                 * A positional array of the items in the grid\n                 */\n                this.grid = [];\n\n                /**\n                 * Clean up after yourself\n                 */\n                this.destroy = function() {\n                    if (this.grid) {\n                        this.grid.length = 0;\n                        this.grid = null;\n                    }\n                };\n\n                /**\n                 * Overrides default options\n                 *\n                 * @param {object} options The options to override\n                 */\n                this.setOptions = function(options) {\n                    if (!options) {\n                        return;\n                    }\n\n                    options = angular.extend({}, options);\n\n                    // all this to avoid using jQuery...\n                    if (options.draggable) {\n                        angular.extend(this.draggable, options.draggable);\n                        delete(options.draggable);\n                    }\n                    if (options.resizable) {\n                        angular.extend(this.resizable, options.resizable);\n                        delete(options.resizable);\n                    }\n\n                    angular.extend(this, options);\n\n                    if (!this.margins || this.margins.length !== 2) {\n                        this.margins = [0, 0];\n                    } else {\n                        for (var x = 0, l = this.margins.length; x < l; ++x) {\n                            this.margins[x] = parseInt(this.margins[x], 10);\n                            if (isNaN(this.margins[x])) {\n                                this.margins[x] = 0;\n                            }\n                        }\n                    }\n                };\n\n                /**\n                 * Check if item can occupy a specified position in the grid\n                 *\n                 * @param {object} item The item in question\n                 * @param {number} row The row index\n                 * @param {number} column The column index\n                 * @returns {boolean} True if if item fits\n                 */\n                this.canItemOccupy = function(item, row, column) {\n                    return row > -1 && column > -1 && item.sizeX + column <= this.columns && item.sizeY + row <= this.maxRows;\n                };\n\n                /**\n                 * Set the item in the first suitable position\n                 *\n                 * @param {object} item The item to insert\n                 */\n                this.autoSetItemPosition = function(item) {\n                    // walk through each row and column looking for a place it will fit\n                    for (var rowIndex = 0; rowIndex < this.maxRows; ++rowIndex) {\n                        for (var colIndex = 0; colIndex < this.columns; ++colIndex) {\n                            // only insert if position is not already taken and it can fit\n                            var items = this.getItems(rowIndex, colIndex, item.sizeX, item.sizeY, item);\n                            if (items.length === 0 && this.canItemOccupy(item, rowIndex, colIndex)) {\n                                this.putItem(item, rowIndex, colIndex);\n                                return;\n                            }\n                        }\n                    }\n                    throw new Error('Unable to place item!');\n                };\n\n                /**\n                 * Gets items at a specific coordinate\n                 *\n                 * @param {number} row\n                 * @param {number} column\n                 * @param {number} sizeX\n                 * @param {number} sizeY\n                 * @param {array} excludeItems An array of items to exclude from selection\n                 * @returns {array} Items that match the criteria\n                 */\n                this.getItems = function(row, column, sizeX, sizeY, excludeItems) {\n                    var items = [];\n                    if (!sizeX || !sizeY) {\n                        sizeX = sizeY = 1;\n                    }\n                    if (excludeItems && !(excludeItems instanceof Array)) {\n                        excludeItems = [excludeItems];\n                    }\n                    for (var h = 0; h < sizeY; ++h) {\n                        for (var w = 0; w < sizeX; ++w) {\n                            var item = this.getItem(row + h, column + w, excludeItems);\n                            if (item && (!excludeItems || excludeItems.indexOf(item) === -1) && items.indexOf(item) === -1) {\n                                items.push(item);\n                            }\n                        }\n                    }\n                    return items;\n                };\n\n                this.getBoundingBox = function(items) {\n\n                    if (items.length === 0) {\n                        return null;\n                    }\n                    if (items.length === 1) {\n                        return {\n                            row: items[0].row,\n                            col: items[0].col,\n                            sizeY: items[0].sizeY,\n                            sizeX: items[0].sizeX\n                        };\n                    }\n\n                    var maxRow = 0;\n                    var maxCol = 0;\n                    var minRow = 9999;\n                    var minCol = 9999;\n\n                    for (var i = 0, l = items.length; i < l; ++i) {\n                        var item = items[i];\n                        minRow = Math.min(item.row, minRow);\n                        minCol = Math.min(item.col, minCol);\n                        maxRow = Math.max(item.row + item.sizeY, maxRow);\n                        maxCol = Math.max(item.col + item.sizeX, maxCol);\n                    }\n\n                    return {\n                        row: minRow,\n                        col: minCol,\n                        sizeY: maxRow - minRow,\n                        sizeX: maxCol - minCol\n                    };\n                };\n\n\n                /**\n                 * Removes an item from the grid\n                 *\n                 * @param {object} item\n                 */\n                this.removeItem = function(item) {\n                    for (var rowIndex = 0, l = this.grid.length; rowIndex < l; ++rowIndex) {\n                        var columns = this.grid[rowIndex];\n                        if (!columns) {\n                            continue;\n                        }\n                        var index = columns.indexOf(item);\n                        if (index !== -1) {\n                            columns[index] = null;\n                            break;\n                        }\n                    }\n                    this.layoutChanged();\n                };\n\n                /**\n                 * Returns the item at a specified coordinate\n                 *\n                 * @param {number} row\n                 * @param {number} column\n                 * @param {array} excludeitems Items to exclude from selection\n                 * @returns {object} The matched item or null\n                 */\n                this.getItem = function(row, column, excludeItems) {\n                    if (excludeItems && !(excludeItems instanceof Array)) {\n                        excludeItems = [excludeItems];\n                    }\n                    var sizeY = 1;\n                    while (row > -1) {\n                        var sizeX = 1,\n                            col = column;\n                        while (col > -1) {\n                            var items = this.grid[row];\n                            if (items) {\n                                var item = items[col];\n                                if (item && (!excludeItems || excludeItems.indexOf(item) === -1) && item.sizeX >= sizeX && item.sizeY >= sizeY) {\n                                    return item;\n                                }\n                            }\n                            ++sizeX;\n                            --col;\n                        }\n                        --row;\n                        ++sizeY;\n                    }\n                    return null;\n                };\n\n                /**\n                 * Insert an array of items into the grid\n                 *\n                 * @param {array} items An array of items to insert\n                 */\n                this.putItems = function(items) {\n                    for (var i = 0, l = items.length; i < l; ++i) {\n                        this.putItem(items[i]);\n                    }\n                };\n\n                /**\n                 * Insert a single item into the grid\n                 *\n                 * @param {object} item The item to insert\n                 * @param {number} row (Optional) Specifies the items row index\n                 * @param {number} column (Optional) Specifies the items column index\n                 * @param {array} ignoreItems\n                 */\n                this.putItem = function(item, row, column, ignoreItems) {\n                    if (typeof row === 'undefined' || row === null) {\n                        row = item.row;\n                        column = item.col;\n                        if (typeof row === 'undefined' || row === null) {\n                            this.autoSetItemPosition(item);\n                            return;\n                        }\n                    }\n                    if (!this.canItemOccupy(item, row, column)) {\n                        column = Math.min(this.columns - item.sizeX, Math.max(0, column));\n                        row = Math.min(this.maxRows - item.sizeY, Math.max(0, row));\n                    }\n\n                    if (item.oldRow !== null && typeof item.oldRow !== 'undefined') {\n                        var samePosition = item.oldRow === row && item.oldColumn === column;\n                        var inGrid = this.grid[row] && this.grid[row][column] === item;\n                        if (samePosition && inGrid) {\n                            item.row = row;\n                            item.col = column;\n                            return;\n                        } else {\n                            // remove from old position\n                            var oldRow = this.grid[item.oldRow];\n                            if (oldRow && oldRow[item.oldColumn] === item) {\n                                delete oldRow[item.oldColumn];\n                            }\n                        }\n                    }\n\n                    item.oldRow = item.row = row;\n                    item.oldColumn = item.col = column;\n\n                    this.moveOverlappingItems(item, ignoreItems);\n\n                    if (!this.grid[row]) {\n                        this.grid[row] = [];\n                    }\n                    this.grid[row][column] = item;\n\n                    if (this.movingItem === item) {\n                        this.floatItemUp(item);\n                    }\n                    this.layoutChanged();\n                };\n\n                /**\n                 * Trade row and column if item1 with item2\n                 *\n                 * @param {object} item1\n                 * @param {object} item2\n                 */\n                this.swapItems = function(item1, item2) {\n                    this.grid[item1.row][item1.col] = item2;\n                    this.grid[item2.row][item2.col] = item1;\n\n                    var item1Row = item1.row;\n                    var item1Col = item1.col;\n                    item1.row = item2.row;\n                    item1.col = item2.col;\n                    item2.row = item1Row;\n                    item2.col = item1Col;\n                };\n\n                /**\n                 * Prevents items from being overlapped\n                 *\n                 * @param {object} item The item that should remain\n                 * @param {array} ignoreItems\n                 */\n                this.moveOverlappingItems = function(item, ignoreItems) {\n                    if (ignoreItems) {\n                        if (ignoreItems.indexOf(item) === -1) {\n                            ignoreItems = ignoreItems.slice(0);\n                            ignoreItems.push(item);\n                        }\n                    } else {\n                        ignoreItems = [item];\n                    }\n                    var overlappingItems = this.getItems(\n                        item.row,\n                        item.col,\n                        item.sizeX,\n                        item.sizeY,\n                        ignoreItems\n                    );\n                    this.moveItemsDown(overlappingItems, item.row + item.sizeY, ignoreItems);\n                };\n\n                /**\n                 * Moves an array of items to a specified row\n                 *\n                 * @param {array} items The items to move\n                 * @param {number} newRow The target row\n                 * @param {array} ignoreItems\n                 */\n                this.moveItemsDown = function(items, newRow, ignoreItems) {\n                    if (!items || items.length === 0) {\n                        return;\n                    }\n                    items.sort(function(a, b) {\n                        return a.row - b.row;\n                    });\n                    ignoreItems = ignoreItems ? ignoreItems.slice(0) : [];\n                    var topRows = {},\n                        item, i, l;\n                    // calculate the top rows in each column\n                    for (i = 0, l = items.length; i < l; ++i) {\n                        item = items[i];\n                        var topRow = topRows[item.col];\n                        if (typeof topRow === 'undefined' || item.row < topRow) {\n                            topRows[item.col] = item.row;\n                        }\n                    }\n                    // move each item down from the top row in its column to the row\n                    for (i = 0, l = items.length; i < l; ++i) {\n                        item = items[i];\n                        var rowsToMove = newRow - topRows[item.col];\n                        this.moveItemDown(item, item.row + rowsToMove, ignoreItems);\n                        ignoreItems.push(item);\n                    }\n                };\n\n                this.moveItemDown = function(item, newRow, ignoreItems) {\n                    if (item.row >= newRow) {\n                        return;\n                    }\n                    while (item.row < newRow) {\n                        ++item.row;\n                        this.moveOverlappingItems(item, ignoreItems);\n                    }\n                    this.putItem(item, item.row, item.col, ignoreItems);\n                };\n\n                /**\n                 * Moves all items up as much as possible\n                 */\n                this.floatItemsUp = function() {\n                    if (this.floating === false) {\n                        return;\n                    }\n                    for (var rowIndex = 0, l = this.grid.length; rowIndex < l; ++rowIndex) {\n                        var columns = this.grid[rowIndex];\n                        if (!columns) {\n                            continue;\n                        }\n                        for (var colIndex = 0, len = columns.length; colIndex < len; ++colIndex) {\n                            var item = columns[colIndex];\n                            if (item) {\n                                this.floatItemUp(item);\n                            }\n                        }\n                    }\n                };\n\n                /**\n                 * Float an item up to the most suitable row\n                 *\n                 * @param {object} item The item to move\n                 */\n                this.floatItemUp = function(item) {\n                    if (this.floating === false) {\n                        return;\n                    }\n                    var colIndex = item.col,\n                        sizeY = item.sizeY,\n                        sizeX = item.sizeX,\n                        bestRow = null,\n                        bestColumn = null,\n                        rowIndex = item.row - 1;\n\n                    while (rowIndex > -1) {\n                        var items = this.getItems(rowIndex, colIndex, sizeX, sizeY, item);\n                        if (items.length !== 0) {\n                            break;\n                        }\n                        bestRow = rowIndex;\n                        bestColumn = colIndex;\n                        --rowIndex;\n                    }\n                    if (bestRow !== null) {\n                        this.putItem(item, bestRow, bestColumn);\n                    }\n                };\n\n                /**\n                 * Update gridsters height\n                 *\n                 * @param {number} plus (Optional) Additional height to add\n                 */\n                this.updateHeight = function(plus) {\n                    var maxHeight = this.minRows;\n                    plus = plus || 0;\n                    for (var rowIndex = this.grid.length; rowIndex >= 0; --rowIndex) {\n                        var columns = this.grid[rowIndex];\n                        if (!columns) {\n                            continue;\n                        }\n                        for (var colIndex = 0, len = columns.length; colIndex < len; ++colIndex) {\n                            if (columns[colIndex]) {\n                                maxHeight = Math.max(maxHeight, rowIndex + plus + columns[colIndex].sizeY);\n                            }\n                        }\n                    }\n                    this.gridHeight = this.maxRows - maxHeight > 0 ? Math.min(this.maxRows, maxHeight) : Math.max(this.maxRows, maxHeight);\n                };\n\n                /**\n                 * Returns the number of rows that will fit in given amount of pixels\n                 *\n                 * @param {number} pixels\n                 * @param {boolean} ceilOrFloor (Optional) Determines rounding method\n                 */\n                this.pixelsToRows = function(pixels, ceilOrFloor) {\n                    if (ceilOrFloor === true) {\n                        return Math.ceil(pixels / this.curRowHeight);\n                    } else if (ceilOrFloor === false) {\n                        return Math.floor(pixels / this.curRowHeight);\n                    }\n\n                    return Math.round(pixels / this.curRowHeight);\n                };\n\n                /**\n                 * Returns the number of columns that will fit in a given amount of pixels\n                 *\n                 * @param {number} pixels\n                 * @param {boolean} ceilOrFloor (Optional) Determines rounding method\n                 * @returns {number} The number of columns\n                 */\n                this.pixelsToColumns = function(pixels, ceilOrFloor) {\n                    if (ceilOrFloor === true) {\n                        return Math.ceil(pixels / this.curColWidth);\n                    } else if (ceilOrFloor === false) {\n                        return Math.floor(pixels / this.curColWidth);\n                    }\n\n                    return Math.round(pixels / this.curColWidth);\n                };\n\n                // unified input handling\n                // adopted from a msdn blogs sample\n                this.unifiedInput = function(target, startEvent, moveEvent, endEvent) {\n                    var lastXYById = {};\n\n                    //  Opera doesn't have Object.keys so we use this wrapper\n                    var numberOfKeys = function(theObject) {\n                        if (Object.keys) {\n                            return Object.keys(theObject).length;\n                        }\n\n                        var n = 0,\n                            key;\n                        for (key in theObject) {\n                            ++n;\n                        }\n\n                        return n;\n                    };\n\n                    //  this calculates the delta needed to convert pageX/Y to offsetX/Y because offsetX/Y don't exist in the TouchEvent object or in Firefox's MouseEvent object\n                    var computeDocumentToElementDelta = function(theElement) {\n                        var elementLeft = 0;\n                        var elementTop = 0;\n                        var oldIEUserAgent = navigator.userAgent.match(/\\bMSIE\\b/);\n\n                        for (var offsetElement = theElement; offsetElement != null; offsetElement = offsetElement.offsetParent) {\n                            //  the following is a major hack for versions of IE less than 8 to avoid an apparent problem on the IEBlog with double-counting the offsets\n                            //  this may not be a general solution to IE7's problem with offsetLeft/offsetParent\n                            if (oldIEUserAgent &&\n                                (!document.documentMode || document.documentMode < 8) &&\n                                offsetElement.currentStyle.position === 'relative' && offsetElement.offsetParent && offsetElement.offsetParent.currentStyle.position === 'relative' && offsetElement.offsetLeft === offsetElement.offsetParent.offsetLeft) {\n                                // add only the top\n                                elementTop += offsetElement.offsetTop;\n                            } else {\n                                elementLeft += offsetElement.offsetLeft;\n                                elementTop += offsetElement.offsetTop;\n                            }\n                        }\n\n                        return {\n                            x: elementLeft,\n                            y: elementTop\n                        };\n                    };\n\n                    //  cache the delta from the document to our event target (reinitialized each mousedown/MSPointerDown/touchstart)\n                    var documentToTargetDelta = computeDocumentToElementDelta(target);\n\n                    //  common event handler for the mouse/pointer/touch models and their down/start, move, up/end, and cancel events\n                    var doEvent = function(theEvtObj) {\n\n                        if (theEvtObj.type === 'mousemove' && numberOfKeys(lastXYById) === 0) {\n                            return;\n                        }\n\n                        var prevent = true;\n\n                        var pointerList = theEvtObj.changedTouches ? theEvtObj.changedTouches : [theEvtObj];\n                        for (var i = 0; i < pointerList.length; ++i) {\n                            var pointerObj = pointerList[i];\n                            var pointerId = (typeof pointerObj.identifier !== 'undefined') ? pointerObj.identifier : (typeof pointerObj.pointerId !== 'undefined') ? pointerObj.pointerId : 1;\n\n                            //  use the pageX/Y coordinates to compute target-relative coordinates when we have them (in ie < 9, we need to do a little work to put them there)\n                            if (typeof pointerObj.pageX === 'undefined') {\n                                //  initialize assuming our source element is our target\n                                pointerObj.pageX = pointerObj.offsetX + documentToTargetDelta.x;\n                                pointerObj.pageY = pointerObj.offsetY + documentToTargetDelta.y;\n\n                                if (pointerObj.srcElement.offsetParent === target && document.documentMode && document.documentMode === 8 && pointerObj.type === 'mousedown') {\n                                    //  source element is a child piece of VML, we're in IE8, and we've not called setCapture yet - add the origin of the source element\n                                    pointerObj.pageX += pointerObj.srcElement.offsetLeft;\n                                    pointerObj.pageY += pointerObj.srcElement.offsetTop;\n                                } else if (pointerObj.srcElement !== target && !document.documentMode || document.documentMode < 8) {\n                                    //  source element isn't the target (most likely it's a child piece of VML) and we're in a version of IE before IE8 -\n                                    //  the offsetX/Y values are unpredictable so use the clientX/Y values and adjust by the scroll offsets of its parents\n                                    //  to get the document-relative coordinates (the same as pageX/Y)\n                                    var sx = -2,\n                                        sy = -2; // adjust for old IE's 2-pixel border\n                                    for (var scrollElement = pointerObj.srcElement; scrollElement !== null; scrollElement = scrollElement.parentNode) {\n                                        sx += scrollElement.scrollLeft ? scrollElement.scrollLeft : 0;\n                                        sy += scrollElement.scrollTop ? scrollElement.scrollTop : 0;\n                                    }\n\n                                    pointerObj.pageX = pointerObj.clientX + sx;\n                                    pointerObj.pageY = pointerObj.clientY + sy;\n                                }\n                            }\n\n\n                            var pageX = pointerObj.pageX;\n                            var pageY = pointerObj.pageY;\n\n                            if (theEvtObj.type.match(/(start|down)$/i)) {\n                                //  clause for processing MSPointerDown, touchstart, and mousedown\n\n                                //  refresh the document-to-target delta on start in case the target has moved relative to document\n                                documentToTargetDelta = computeDocumentToElementDelta(target);\n\n                                //  protect against failing to get an up or end on this pointerId\n                                if (lastXYById[pointerId]) {\n                                    if (endEvent) {\n                                        endEvent({\n                                            target: theEvtObj.target,\n                                            which: theEvtObj.which,\n                                            pointerId: pointerId,\n                                            pageX: pageX,\n                                            pageY: pageY\n                                        });\n                                    }\n\n                                    delete lastXYById[pointerId];\n                                }\n\n                                if (startEvent) {\n                                    if (prevent) {\n                                        prevent = startEvent({\n                                            target: theEvtObj.target,\n                                            which: theEvtObj.which,\n                                            pointerId: pointerId,\n                                            pageX: pageX,\n                                            pageY: pageY\n                                        });\n                                    }\n                                }\n\n                                //  init last page positions for this pointer\n                                lastXYById[pointerId] = {\n                                    x: pageX,\n                                    y: pageY\n                                };\n\n                                // IE pointer model\n                                if (target.msSetPointerCapture) {\n                                    target.msSetPointerCapture(pointerId);\n                                } else if (theEvtObj.type === 'mousedown' && numberOfKeys(lastXYById) === 1) {\n                                    if (useSetReleaseCapture) {\n                                        target.setCapture(true);\n                                    } else {\n                                        document.addEventListener('mousemove', doEvent, false);\n                                        document.addEventListener('mouseup', doEvent, false);\n                                    }\n                                }\n                            } else if (theEvtObj.type.match(/move$/i)) {\n                                //  clause handles mousemove, MSPointerMove, and touchmove\n\n                                if (lastXYById[pointerId] && !(lastXYById[pointerId].x === pageX && lastXYById[pointerId].y === pageY)) {\n                                    //  only extend if the pointer is down and it's not the same as the last point\n\n                                    if (moveEvent && prevent) {\n                                        prevent = moveEvent({\n                                            target: theEvtObj.target,\n                                            which: theEvtObj.which,\n                                            pointerId: pointerId,\n                                            pageX: pageX,\n                                            pageY: pageY\n                                        });\n                                    }\n\n                                    //  update last page positions for this pointer\n                                    lastXYById[pointerId].x = pageX;\n                                    lastXYById[pointerId].y = pageY;\n                                }\n                            } else if (lastXYById[pointerId] && theEvtObj.type.match(/(up|end|cancel)$/i)) {\n                                //  clause handles up/end/cancel\n\n                                if (endEvent && prevent) {\n                                    prevent = endEvent({\n                                        target: theEvtObj.target,\n                                        which: theEvtObj.which,\n                                        pointerId: pointerId,\n                                        pageX: pageX,\n                                        pageY: pageY\n                                    });\n                                }\n\n                                //  delete last page positions for this pointer\n                                delete lastXYById[pointerId];\n\n                                //  in the Microsoft pointer model, release the capture for this pointer\n                                //  in the mouse model, release the capture or remove document-level event handlers if there are no down points\n                                //  nothing is required for the iOS touch model because capture is implied on touchstart\n                                if (target.msReleasePointerCapture) {\n                                    target.msReleasePointerCapture(pointerId);\n                                } else if (theEvtObj.type === 'mouseup' && numberOfKeys(lastXYById) === 0) {\n                                    if (useSetReleaseCapture) {\n                                        target.releaseCapture();\n                                    } else {\n                                        document.removeEventListener('mousemove', doEvent, false);\n                                        document.removeEventListener('mouseup', doEvent, false);\n                                    }\n                                }\n                            }\n                        }\n\n                        if (prevent) {\n                            if (theEvtObj.preventDefault) {\n                                theEvtObj.preventDefault();\n                            }\n\n                            if (theEvtObj.preventManipulation) {\n                                theEvtObj.preventManipulation();\n                            }\n\n                            if (theEvtObj.preventMouseEvent) {\n                                theEvtObj.preventMouseEvent();\n                            }\n                        }\n                    };\n\n                    var useSetReleaseCapture = false;\n                    // saving the settings for contentZooming and touchaction before activation\n                    var contentZooming, msTouchAction;\n\n                    this.enable = function() {\n\n                        if (window.navigator.msPointerEnabled) {\n                            //  Microsoft pointer model\n                            target.addEventListener('MSPointerDown', doEvent, false);\n                            target.addEventListener('MSPointerMove', doEvent, false);\n                            target.addEventListener('MSPointerUp', doEvent, false);\n                            target.addEventListener('MSPointerCancel', doEvent, false);\n\n                            //  css way to prevent panning in our target area\n                            if (typeof target.style.msContentZooming !== 'undefined') {\n                                contentZooming = target.style.msContentZooming;\n                                target.style.msContentZooming = 'none';\n                            }\n\n                            //  new in Windows Consumer Preview: css way to prevent all built-in touch actions on our target\n                            //  without this, you cannot touch draw on the element because IE will intercept the touch events\n                            if (typeof target.style.msTouchAction !== 'undefined') {\n                                msTouchAction = target.style.msTouchAction;\n                                target.style.msTouchAction = 'none';\n                            }\n                        } else if (target.addEventListener) {\n                            //  iOS touch model\n                            target.addEventListener('touchstart', doEvent, false);\n                            target.addEventListener('touchmove', doEvent, false);\n                            target.addEventListener('touchend', doEvent, false);\n                            target.addEventListener('touchcancel', doEvent, false);\n\n                            //  mouse model\n                            target.addEventListener('mousedown', doEvent, false);\n\n                            //  mouse model with capture\n                            //  rejecting gecko because, unlike ie, firefox does not send events to target when the mouse is outside target\n                            if (target.setCapture && !window.navigator.userAgent.match(/\\bGecko\\b/)) {\n                                useSetReleaseCapture = true;\n\n                                target.addEventListener('mousemove', doEvent, false);\n                                target.addEventListener('mouseup', doEvent, false);\n                            }\n                        } else if (target.attachEvent && target.setCapture) {\n                            //  legacy IE mode - mouse with capture\n                            useSetReleaseCapture = true;\n                            target.attachEvent('onmousedown', function() {\n                                doEvent(window.event);\n                                window.event.returnValue = false;\n                                return false;\n                            });\n                            target.attachEvent('onmousemove', function() {\n                                doEvent(window.event);\n                                window.event.returnValue = false;\n                                return false;\n                            });\n                            target.attachEvent('onmouseup', function() {\n                                doEvent(window.event);\n                                window.event.returnValue = false;\n                                return false;\n                            });\n                        }\n                    };\n\n                    this.disable = function() {\n                        if (window.navigator.msPointerEnabled) {\n                            //  Microsoft pointer model\n                            target.removeEventListener('MSPointerDown', doEvent, false);\n                            target.removeEventListener('MSPointerMove', doEvent, false);\n                            target.removeEventListener('MSPointerUp', doEvent, false);\n                            target.removeEventListener('MSPointerCancel', doEvent, false);\n\n                            //  reset zooming to saved value\n                            if (contentZooming) {\n                                target.style.msContentZooming = contentZooming;\n                            }\n\n                            // reset touch action setting\n                            if (msTouchAction) {\n                                target.style.msTouchAction = msTouchAction;\n                            }\n                        } else if (target.removeEventListener) {\n                            //  iOS touch model\n                            target.removeEventListener('touchstart', doEvent, false);\n                            target.removeEventListener('touchmove', doEvent, false);\n                            target.removeEventListener('touchend', doEvent, false);\n                            target.removeEventListener('touchcancel', doEvent, false);\n\n                            //  mouse model\n                            target.removeEventListener('mousedown', doEvent, false);\n\n                            //  mouse model with capture\n                            //  rejecting gecko because, unlike ie, firefox does not send events to target when the mouse is outside target\n                            if (target.setCapture && !window.navigator.userAgent.match(/\\bGecko\\b/)) {\n                                useSetReleaseCapture = true;\n\n                                target.removeEventListener('mousemove', doEvent, false);\n                                target.removeEventListener('mouseup', doEvent, false);\n                            }\n                        } else if (target.detachEvent && target.setCapture) {\n                            //  legacy IE mode - mouse with capture\n                            useSetReleaseCapture = true;\n                            target.detachEvent('onmousedown');\n                            target.detachEvent('onmousemove');\n                            target.detachEvent('onmouseup');\n                        }\n                    };\n\n                    return this;\n                };\n\n            }\n        ])\n\n    /**\n     * The gridster directive\n     *\n     * @param {object} $parse\n     * @param {object} $timeout\n     */\n        .directive('gridster', ['$timeout', '$rootScope', '$window',\n            function($timeout, $rootScope, $window) {\n                return {\n                    restrict: 'EAC',\n                    // without transclude, some child items may lose their parent scope\n                    transclude: true,\n                    replace: true,\n                    template: '<div ng-class=\"gridsterClass()\"><div ng-style=\"previewStyle()\" class=\"gridster-item gridster-preview-holder\"></div><div class=\"gridster-content\" ng-transclude></div></div>',\n                    controller: 'GridsterCtrl',\n                    controllerAs: 'gridster',\n                    scope: {\n                        config: '=?gridster'\n                    },\n                    compile: function() {\n\n                        return function(scope, $elem, attrs, gridster) {\n                            gridster.loaded = false;\n\n                            scope.gridsterClass = function() {\n                                return {\n                                    gridster: true,\n                                    'gridster-desktop': !gridster.isMobile,\n                                    'gridster-mobile': gridster.isMobile,\n                                    'gridster-loaded': gridster.loaded\n                                };\n                            };\n\n                            /**\n                             * @returns {Object} style object for preview element\n                             */\n                            scope.previewStyle = function() {\n                                if (!gridster.movingItem) {\n                                    return {\n                                        display: 'none'\n                                    };\n                                }\n\n                                return {\n                                    display: 'block',\n                                    height: (gridster.movingItem.sizeY * gridster.curRowHeight - gridster.margins[0]) + 'px',\n                                    width: (gridster.movingItem.sizeX * gridster.curColWidth - gridster.margins[1]) + 'px',\n                                    top: (gridster.movingItem.row * gridster.curRowHeight + (gridster.outerMargin ? gridster.margins[0] : 0)) + 'px',\n                                    left: (gridster.movingItem.col * gridster.curColWidth + (gridster.outerMargin ? gridster.margins[1] : 0)) + 'px'\n                                };\n                            };\n\n                            var refresh = function() {\n                                gridster.setOptions(scope.config);\n\n                                // resolve \"auto\" & \"match\" values\n                                if (gridster.width === 'auto') {\n                                    gridster.curWidth = $elem[0].offsetWidth || parseInt($elem.css('width'), 10);\n                                } else {\n                                    gridster.curWidth = gridster.width;\n                                }\n\n                                if (gridster.colWidth === 'auto') {\n                                    gridster.curColWidth = (gridster.curWidth + (gridster.outerMargin ? -gridster.margins[1] : gridster.margins[1])) / gridster.columns;\n                                } else {\n                                    gridster.curColWidth = gridster.colWidth;\n                                }\n\n                                gridster.curRowHeight = gridster.rowHeight;\n                                if (typeof gridster.rowHeight === 'string') {\n                                    if (gridster.rowHeight === 'match') {\n                                        gridster.curRowHeight = Math.round(gridster.curColWidth);\n                                    } else if (gridster.rowHeight.indexOf('*') !== -1) {\n                                        gridster.curRowHeight = Math.round(gridster.curColWidth * gridster.rowHeight.replace('*', '').replace(' ', ''));\n                                    } else if (gridster.rowHeight.indexOf('/') !== -1) {\n                                        gridster.curRowHeight = Math.round(gridster.curColWidth / gridster.rowHeight.replace('/', '').replace(' ', ''));\n                                    }\n                                }\n\n                                gridster.isMobile = gridster.mobileModeEnabled && gridster.curWidth <= gridster.mobileBreakPoint;\n\n                                // loop through all items and reset their CSS\n                                for (var rowIndex = 0, l = gridster.grid.length; rowIndex < l; ++rowIndex) {\n                                    var columns = gridster.grid[rowIndex];\n                                    if (!columns) {\n                                        continue;\n                                    }\n\n                                    for (var colIndex = 0, len = columns.length; colIndex < len; ++colIndex) {\n                                        if (columns[colIndex]) {\n                                            var item = columns[colIndex];\n                                            item.setElementPosition();\n                                            item.setElementSizeY();\n                                            item.setElementSizeX();\n                                        }\n                                    }\n                                }\n\n                                updateHeight();\n                            };\n\n                            // update grid items on config changes\n                            scope.$watch('config', refresh, true);\n\n                            scope.$watch('config.draggable', function() {\n                                $rootScope.$broadcast('gridster-draggable-changed');\n                            }, true);\n\n                            scope.$watch('config.resizable', function() {\n                                $rootScope.$broadcast('gridster-resizable-changed');\n                            }, true);\n\n                            var updateHeight = function() {\n                                $elem.css('height', (gridster.gridHeight * gridster.curRowHeight) + (gridster.outerMargin ? gridster.margins[0] : -gridster.margins[0]) + 'px');\n                            };\n\n                            scope.$watch('gridster.gridHeight', updateHeight);\n\n                            scope.$watch('gridster.movingItem', function() {\n                                gridster.updateHeight(gridster.movingItem ? gridster.movingItem.sizeY : 0);\n                            });\n\n                            var prevWidth = $elem[0].offsetWidth || parseInt($elem.css('width'), 10);\n\n                            function resize() {\n                                var width = $elem[0].offsetWidth || parseInt($elem.css('width'), 10);\n\n                                if (!width || width === prevWidth || gridster.movingItem) {\n                                    return;\n                                }\n                                prevWidth = width;\n\n                                if (gridster.loaded) {\n                                    $elem.removeClass('gridster-loaded');\n                                }\n\n                                refresh();\n\n                                if (gridster.loaded) {\n                                    $elem.addClass('gridster-loaded');\n                                }\n\n                                scope.$parent.$broadcast('gridster-resized', [width, $elem.offsetHeight]);\n                            }\n\n                            // track element width changes any way we can\n                            function onResize() {\n                                resize();\n                                $timeout(function() {\n                                    scope.$apply();\n                                });\n                            }\n                            if (typeof $elem.resize === 'function') {\n                                $elem.resize(onResize);\n                            }\n                            var $win = angular.element($window);\n                            $win.on('resize', onResize);\n\n                            scope.$watch(function() {\n                                return $elem[0].offsetWidth || parseInt($elem.css('width'), 10);\n                            }, resize);\n\n                            // be sure to cleanup\n                            scope.$on('$destroy', function() {\n                                gridster.destroy();\n                                $win.off('resize', onResize);\n                            });\n\n                            // allow a little time to place items before floating up\n                            $timeout(function() {\n                                scope.$watch('gridster.floating', function() {\n                                    gridster.floatItemsUp();\n                                });\n                                gridster.loaded = true;\n                            }, 100);\n\n\n\n                            // Custom code\n\n                            /**\n                             * Callback called when starting to drag from palette to canvas.\n                             */\n                            $rootScope.startDragCallback = function (event, ui) {\n                                $timeout(function () {\n                                    var fieldId = event.target.id;\n                                    var fieldType;\n\n                                    var colspan = 1;\n                                    if (fieldId === 'group' || fieldId === 'dynamic-table') {\n                                        colspan = 2;\n                                    }\n\n                                    var numberOfRows = 1;\n                                    if (fieldId === 'multi-line-text') {\n                                        numberOfRows = 2;\n                                    } else if (fieldId === 'dynamic-table') {\n                                        numberOfRows = 2;\n                                    }\n\n                                    scope.startDragItem = {\n                                        type: fieldId,\n                                        fieldType: fieldType,\n                                        name: 'Label',\n                                        required: false,\n                                        readOnly: false,\n                                        sizeX: colspan,\n                                        sizeY: numberOfRows,\n                                        row: -1,\n                                        col: -1\n                                    };\n\n                                    if (fieldId === 'radio-buttons' || fieldId === 'dropdown') {\n                                        scope.startDragItem.options = [\n                                            {name: 'Option 1'}\n                                        ];\n                                    }\n\n                                }, 0);\n                            };\n\n                            /**\n                             * Callback called when stopping to drag from palette to canvas.\n                             */\n                            $rootScope.dropCallback = function (event, ui) {\n                                $timeout(function () {\n                                    gridster.movingItem = null;\n                                    var offset = jQuery($elem[0]).offset();\n                                    var row = gridster.pixelsToRows(event.clientY - offset.top, true) - 1;\n                                    var column = gridster.pixelsToColumns(event.clientX - offset.left, true) - 1;\n                                    if (row >= 0 && column >= 0) {\n\n                                        scope.startDragItem.row = row;\n                                        scope.startDragItem.col = column;\n                                    }\n                                }, 0);\n                            };\n\n                            /**\n                             * Callback called during dragging from palette to canvas.\n                             */\n                            $rootScope.dragCallback = function (event, ui) {\n\n                                    var offset = jQuery($elem[0]).offset();\n                                    var row = gridster.pixelsToRows(event.clientY - offset.top, true) - 1;\n                                    var column = gridster.pixelsToColumns(event.clientX - offset.left, true) - 1;\n\n                                    if (!scope.startDragItem) {\n                                        return;\n                                    }\n\n                                    if (scope.startDragItem.row === row && scope.startDragItem.col === column) {\n                                        return;\n                                    }\n\n                                    if ( ((scope.startDragItem.row === -1 || scope.startDragItem.col === -1) && row >= 0 && column >= 0)\n                                        || (scope.startDragItem.row >= 0 && scope.startDragItem.col >= 0 && (row < 0 || column < 0)) ) {\n                                        $timeout(function () {\n                                            if ((scope.startDragItem.row === -1 || scope.startDragItem.col === -1) && row >= 0 && column >= 0) {\n                                                scope.$parent.formItems.push(scope.startDragItem);\n\n                                                gridster.movingItem = scope.startDragItem;\n                                                gridster.updateHeight(1);\n                                            }\n\n                                            if (scope.startDragItem.row >= 0 && scope.startDragItem.col >= 0 && (row < 0 || column < 0)) {\n                                                scope.$parent.formItems.pop();\n                                                gridster.movingItem = null;\n                                            }\n\n\n                                        }, 0);\n                                    }\n\n                                $timeout(function () {\n                                    scope.startDragItem.row = row;\n                                    scope.startDragItem.col = column;\n                                }, 0);\n\n                            };\n\n                            // END custom code\n\n\n                        };\n                    }\n                };\n            }\n        ])\n\n        .controller('GridsterItemCtrl', function() {\n            this.$element = null;\n            this.gridster = null;\n            this.row = null;\n            this.col = null;\n            this.sizeX = null;\n            this.sizeY = null;\n            this.minSizeX = 0;\n            this.minSizeY = 0;\n            this.maxSizeX = null;\n            this.maxSizeY = null;\n\n            this.init = function($element, gridster) {\n                this.$element = $element;\n                this.gridster = gridster;\n                this.sizeX = gridster.defaultSizeX;\n                this.sizeY = gridster.defaultSizeY;\n            };\n\n            this.destroy = function() {\n                this.gridster = null;\n                this.$element = null;\n            };\n\n            /**\n             * Returns the items most important attributes\n             */\n            this.toJSON = function() {\n                return {\n                    row: this.row,\n                    col: this.col,\n                    sizeY: this.sizeY,\n                    sizeX: this.sizeX\n                };\n            };\n\n            this.isMoving = function() {\n                return this.gridster.movingItem === this;\n            };\n\n            /**\n             * Set the items position\n             *\n             * @param {number} row\n             * @param {number} column\n             */\n            this.setPosition = function(row, column) {\n                this.gridster.putItem(this, row, column);\n\n                if (!this.isMoving()) {\n                    this.setElementPosition();\n                }\n            };\n\n            /**\n             * Sets a specified size property\n             *\n             * @param {string} key Can be either \"x\" or \"y\"\n             * @param {number} value The size amount\n             */\n            this.setSize = function(key, value, preventMove) {\n                key = key.toUpperCase();\n                var camelCase = 'size' + key,\n                    titleCase = 'Size' + key;\n                if (value === '') {\n                    return;\n                }\n                value = parseInt(value, 10);\n                if (isNaN(value) || value === 0) {\n                    value = this.gridster['default' + titleCase];\n                }\n                var max = key === 'X' ? this.gridster.columns : this.gridster.maxRows;\n                if (this['max' + titleCase]) {\n                    max = Math.min(this['max' + titleCase], max);\n                }\n                if (this.gridster['max' + titleCase]) {\n                    max = Math.min(this.gridster['max' + titleCase], max);\n                }\n                if (key === 'X' && this.cols) {\n                    max -= this.cols;\n                } else if (key === 'Y' && this.rows) {\n                    max -= this.rows;\n                }\n\n                var min = 0;\n                if (this['min' + titleCase]) {\n                    min = Math.max(this['min' + titleCase], min);\n                }\n                if (this.gridster['min' + titleCase]) {\n                    min = Math.max(this.gridster['min' + titleCase], min);\n                }\n\n                value = Math.max(Math.min(value, max), min);\n\n                var changed = (this[camelCase] !== value || (this['old' + titleCase] && this['old' + titleCase] !== value));\n                this['old' + titleCase] = this[camelCase] = value;\n\n                if (!this.isMoving()) {\n                    this['setElement' + titleCase]();\n                }\n                if (!preventMove && changed) {\n                    this.gridster.moveOverlappingItems(this);\n                    this.gridster.layoutChanged();\n                }\n\n                return changed;\n            };\n\n            /**\n             * Sets the items sizeY property\n             *\n             * @param {number} rows\n             */\n            this.setSizeY = function(rows, preventMove) {\n                return this.setSize('Y', rows, preventMove);\n            };\n\n            /**\n             * Sets the items sizeX property\n             *\n             * @param {number} rows\n             */\n            this.setSizeX = function(columns, preventMove) {\n                return this.setSize('X', columns, preventMove);\n            };\n\n            /**\n             * Sets an elements position on the page\n             *\n             * @param {number} row\n             * @param {number} column\n             */\n            this.setElementPosition = function() {\n                if (this.gridster.isMobile) {\n                    this.$element.css({\n                        marginLeft: this.gridster.margins[0] + 'px',\n                        marginRight: this.gridster.margins[0] + 'px',\n                        marginTop: this.gridster.margins[1] + 'px',\n                        marginBottom: this.gridster.margins[1] + 'px',\n                        top: '',\n                        left: ''\n                    });\n                } else {\n                    this.$element.css({\n                        margin: 0,\n                        top: (this.row * this.gridster.curRowHeight + (this.gridster.outerMargin ? this.gridster.margins[0] : 0)) + 'px',\n                        left: (this.col * this.gridster.curColWidth + (this.gridster.outerMargin ? this.gridster.margins[1] : 0)) + 'px'\n                    });\n                }\n            };\n\n            /**\n             * Sets an elements height\n             */\n            this.setElementSizeY = function() {\n                if (this.gridster.isMobile && !this.gridster.saveGridItemCalculatedHeightInMobile) {\n                    this.$element.css('height', '');\n                } else {\n                    this.$element.css('height', (this.sizeY * this.gridster.curRowHeight - this.gridster.margins[0]) + 'px');\n                }\n            };\n\n            /**\n             * Sets an elements width\n             */\n            this.setElementSizeX = function() {\n                if (this.gridster.isMobile) {\n                    this.$element.css('width', '');\n                } else {\n                    this.$element.css('width', (this.sizeX * this.gridster.curColWidth - this.gridster.margins[1]) + 'px');\n                }\n            };\n\n            /**\n             * Gets an element's width\n             */\n            this.getElementSizeX = function() {\n                return (this.sizeX * this.gridster.curColWidth - this.gridster.margins[1]);\n            };\n\n            /**\n             * Gets an element's height\n             */\n            this.getElementSizeY = function() {\n                return (this.sizeY * this.gridster.curRowHeight - this.gridster.margins[0]);\n            };\n\n        })\n\n        .factory('GridsterDraggable', ['$document', '$timeout', '$window',\n            function($document, $timeout, $window) {\n                function GridsterDraggable($el, scope, gridster, item, itemOptions) {\n\n                    var elmX, elmY, elmW, elmH,\n\n                        mouseX = 0,\n                        mouseY = 0,\n                        lastMouseX = 0,\n                        lastMouseY = 0,\n                        mOffX = 0,\n                        mOffY = 0,\n\n                        minTop = 0,\n                        maxTop = 9999,\n                        minLeft = 0,\n                        realdocument = $document[0];\n\n                    var originalCol, originalRow;\n                    var inputTags = ['select', 'input', 'textarea', 'button'];\n\n                    function mouseDown(e) {\n                        if (inputTags.indexOf(e.target.nodeName.toLowerCase()) !== -1) {\n                            return false;\n                        }\n\n                        // exit, if a resize handle was hit\n                        if (angular.element(e.target).hasClass('gridster-item-resizable-handler')) {\n                            return false;\n                        }\n\n                        // exit, if the target has it's own click event\n                        if (angular.element(e.target).attr('onclick') || angular.element(e.target).attr('ng-click')) {\n                            return false;\n                        }\n\n                        switch (e.which) {\n                            case 1:\n                                // left mouse button\n                                break;\n                            case 2:\n                            case 3:\n                                // right or middle mouse button\n                                return;\n                        }\n\n                        lastMouseX = e.pageX;\n                        lastMouseY = e.pageY;\n\n                        elmX = parseInt($el.css('left'), 10);\n                        elmY = parseInt($el.css('top'), 10);\n                        elmW = $el[0].offsetWidth;\n                        elmH = $el[0].offsetHeight;\n\n                        originalCol = item.col;\n                        originalRow = item.row;\n\n                        dragStart(e);\n\n                        return true;\n                    }\n\n                    function mouseMove(e) {\n                        if (!$el.hasClass('gridster-item-moving') || $el.hasClass('gridster-item-resizing')) {\n                            return false;\n                        }\n\n                        var maxLeft = gridster.curWidth - 1;\n\n                        // Get the current mouse position.\n                        mouseX = e.pageX;\n                        mouseY = e.pageY;\n\n                        // Get the deltas\n                        var diffX = mouseX - lastMouseX + mOffX;\n                        var diffY = mouseY - lastMouseY + mOffY;\n                        mOffX = mOffY = 0;\n\n                        // Update last processed mouse positions.\n                        lastMouseX = mouseX;\n                        lastMouseY = mouseY;\n\n                        var dX = diffX,\n                            dY = diffY;\n                        if (elmX + dX < minLeft) {\n                            diffX = minLeft - elmX;\n                            mOffX = dX - diffX;\n                        } else if (elmX + elmW + dX > maxLeft) {\n                            diffX = maxLeft - elmX - elmW;\n                            mOffX = dX - diffX;\n                        }\n\n                        if (elmY + dY < minTop) {\n                            diffY = minTop - elmY;\n                            mOffY = dY - diffY;\n                        } else if (elmY + elmH + dY > maxTop) {\n                            diffY = maxTop - elmY - elmH;\n                            mOffY = dY - diffY;\n                        }\n                        elmX += diffX;\n                        elmY += diffY;\n\n                        // set new position\n                        $el.css({\n                            'top': elmY + 'px',\n                            'left': elmX + 'px'\n                        });\n\n                        drag(e);\n\n                        return true;\n                    }\n\n                    function mouseUp(e) {\n                        if (!$el.hasClass('gridster-item-moving') || $el.hasClass('gridster-item-resizing')) {\n                            return false;\n                        }\n\n                        mOffX = mOffY = 0;\n\n                        dragStop(e);\n\n                        return true;\n                    }\n\n                    function dragStart(event) {\n                        $el.addClass('gridster-item-moving');\n                        gridster.movingItem = item;\n\n                        gridster.updateHeight(item.sizeY);\n                        scope.$apply(function() {\n                            if (gridster.draggable && gridster.draggable.start) {\n                                gridster.draggable.start(event, $el, itemOptions);\n                            }\n                        });\n                    }\n\n                    function drag(event) {\n                        var oldRow = item.row,\n                            oldCol = item.col,\n                            hasCallback = gridster.draggable && gridster.draggable.drag,\n                            scrollSensitivity = gridster.draggable.scrollSensitivity,\n                            scrollSpeed = gridster.draggable.scrollSpeed;\n\n                        var row = gridster.pixelsToRows(elmY);\n                        var col = gridster.pixelsToColumns(elmX);\n\n                        var itemsInTheWay = gridster.getItems(row, col, item.sizeX, item.sizeY, item);\n                        var hasItemsInTheWay = itemsInTheWay.length !== 0;\n\n                        if (gridster.swapping === true && hasItemsInTheWay) {\n                            var boundingBoxItem = gridster.getBoundingBox(itemsInTheWay);\n                            var sameSize = boundingBoxItem.sizeX === item.sizeX && boundingBoxItem.sizeY === item.sizeY;\n                            var sameRow = boundingBoxItem.row === row;\n                            var sameCol = boundingBoxItem.col === col;\n                            var samePosition = sameRow && sameCol;\n                            var inline = sameRow || sameCol;\n\n                            if (sameSize && itemsInTheWay.length === 1) {\n                                if (samePosition) {\n                                    gridster.swapItems(item, itemsInTheWay[0]);\n                                } else if (inline) {\n                                    return;\n                                }\n                            } else if (boundingBoxItem.sizeX <= item.sizeX && boundingBoxItem.sizeY <= item.sizeY && inline) {\n                                var emptyRow = item.row <= row ? item.row : row + item.sizeY;\n                                var emptyCol = item.col <= col ? item.col : col + item.sizeX;\n                                var rowOffset = emptyRow - boundingBoxItem.row;\n                                var colOffset = emptyCol - boundingBoxItem.col;\n\n                                for (var i = 0, l = itemsInTheWay.length; i < l; ++i) {\n                                    var itemInTheWay = itemsInTheWay[i];\n\n                                    var itemsInFreeSpace = gridster.getItems(\n                                            itemInTheWay.row + rowOffset,\n                                            itemInTheWay.col + colOffset,\n                                        itemInTheWay.sizeX,\n                                        itemInTheWay.sizeY,\n                                        item\n                                    );\n\n                                    if (itemsInFreeSpace.length === 0) {\n                                        gridster.putItem(itemInTheWay, itemInTheWay.row + rowOffset, itemInTheWay.col + colOffset);\n                                    }\n                                }\n                            }\n                        }\n\n                        if (gridster.pushing !== false || !hasItemsInTheWay) {\n                            item.row = row;\n                            item.col = col;\n                        }\n\n                        if (event.pageY - realdocument.body.scrollTop < scrollSensitivity) {\n                            realdocument.body.scrollTop = realdocument.body.scrollTop - scrollSpeed;\n                        } else if ($window.innerHeight - (event.pageY - realdocument.body.scrollTop) < scrollSensitivity) {\n                            realdocument.body.scrollTop = realdocument.body.scrollTop + scrollSpeed;\n                        }\n\n                        if (event.pageX - realdocument.body.scrollLeft < scrollSensitivity) {\n                            realdocument.body.scrollLeft = realdocument.body.scrollLeft - scrollSpeed;\n                        } else if ($window.innerWidth - (event.pageX - realdocument.body.scrollLeft) < scrollSensitivity) {\n                            realdocument.body.scrollLeft = realdocument.body.scrollLeft + scrollSpeed;\n                        }\n\n                        if (hasCallback || oldRow !== item.row || oldCol !== item.col) {\n                            scope.$apply(function() {\n                                if (hasCallback) {\n                                    gridster.draggable.drag(event, $el, itemOptions);\n                                }\n                            });\n                        }\n                    }\n\n                    function dragStop(event) {\n                        $el.removeClass('gridster-item-moving');\n                        var row = gridster.pixelsToRows(elmY);\n                        var col = gridster.pixelsToColumns(elmX);\n                        if (gridster.pushing !== false || gridster.getItems(row, col, item.sizeX, item.sizeY, item).length === 0) {\n                            item.row = row;\n                            item.col = col;\n                        }\n                        gridster.movingItem = null;\n                        item.setPosition(item.row, item.col);\n\n                        scope.$apply(function() {\n                            if (gridster.draggable && gridster.draggable.stop) {\n                                gridster.draggable.stop(event, $el, itemOptions);\n                            }\n                        });\n                    }\n\n                    var enabled = false;\n                    var $dragHandle = null;\n                    var unifiedInput;\n\n                    this.enable = function() {\n                        var self = this;\n                        // disable and timeout required for some template rendering\n                        $timeout(function() {\n                            self.disable();\n\n                            if (gridster.draggable && gridster.draggable.handle) {\n                                $dragHandle = angular.element($el[0].querySelector(gridster.draggable.handle));\n                                if ($dragHandle.length === 0) {\n                                    // fall back to element if handle not found...\n                                    $dragHandle = $el;\n                                }\n                            } else {\n                                $dragHandle = $el;\n                            }\n\n                            unifiedInput = new gridster.unifiedInput($dragHandle[0], mouseDown, mouseMove, mouseUp);\n                            unifiedInput.enable();\n\n                            enabled = true;\n                        });\n                    };\n\n                    this.disable = function() {\n                        if (!enabled) {\n                            return;\n                        }\n\n                        unifiedInput.disable();\n                        unifiedInput = undefined;\n                        enabled = false;\n                    };\n\n                    this.toggle = function(enabled) {\n                        if (enabled) {\n                            this.enable();\n                        } else {\n                            this.disable();\n                        }\n                    };\n\n                    this.destroy = function() {\n                        this.disable();\n                    };\n                }\n\n                return GridsterDraggable;\n            }\n        ])\n\n        .factory('GridsterResizable', [\n            function() {\n                function GridsterResizable($el, scope, gridster, item, itemOptions) {\n\n                    function ResizeHandle(handleClass) {\n\n                        var hClass = handleClass;\n\n                        var elmX, elmY, elmW, elmH,\n\n                            mouseX = 0,\n                            mouseY = 0,\n                            lastMouseX = 0,\n                            lastMouseY = 0,\n                            mOffX = 0,\n                            mOffY = 0,\n\n                            minTop = 0,\n                            maxTop = 9999,\n                            minLeft = 0;\n\n                        var getMinHeight = function() {\n                            return gridster.curRowHeight - gridster.margins[0];\n                        };\n                        var getMinWidth = function() {\n                            return gridster.curColWidth - gridster.margins[1];\n                        };\n\n                        var originalWidth, originalHeight;\n                        var savedDraggable;\n\n                        function mouseDown(e) {\n                            switch (e.which) {\n                                case 1:\n                                    // left mouse button\n                                    break;\n                                case 2:\n                                case 3:\n                                    // right or middle mouse button\n                                    return;\n                            }\n\n                            // save the draggable setting to restore after resize\n                            savedDraggable = gridster.draggable.enabled;\n                            if (savedDraggable) {\n                                gridster.draggable.enabled = false;\n                                scope.$broadcast('gridster-draggable-changed');\n                            }\n\n                            // Get the current mouse position.\n                            lastMouseX = e.pageX;\n                            lastMouseY = e.pageY;\n\n                            // Record current widget dimensions\n                            elmX = parseInt($el.css('left'), 10);\n                            elmY = parseInt($el.css('top'), 10);\n                            elmW = $el[0].offsetWidth;\n                            elmH = $el[0].offsetHeight;\n\n                            originalWidth = item.sizeX;\n                            originalHeight = item.sizeY;\n\n                            resizeStart(e);\n\n                            return true;\n                        }\n\n                        function resizeStart(e) {\n                            $el.addClass('gridster-item-moving');\n                            $el.addClass('gridster-item-resizing');\n\n                            gridster.movingItem = item;\n\n                            item.setElementSizeX();\n                            item.setElementSizeY();\n                            item.setElementPosition();\n                            gridster.updateHeight(1);\n\n                            scope.$apply(function() {\n                                // callback\n                                if (gridster.resizable && gridster.resizable.start) {\n                                    gridster.resizable.start(e, $el, itemOptions); // options is the item model\n                                }\n                            });\n                        }\n\n                        function mouseMove(e) {\n                            var maxLeft = gridster.curWidth - 1;\n\n                            // Get the current mouse position.\n                            mouseX = e.pageX;\n                            mouseY = e.pageY;\n\n                            // Get the deltas\n                            var diffX = mouseX - lastMouseX + mOffX;\n                            var diffY = mouseY - lastMouseY + mOffY;\n                            mOffX = mOffY = 0;\n\n                            // Update last processed mouse positions.\n                            lastMouseX = mouseX;\n                            lastMouseY = mouseY;\n\n                            var dY = diffY,\n                                dX = diffX;\n\n                            if (hClass.indexOf('n') >= 0) {\n                                if (elmH - dY < getMinHeight()) {\n                                    diffY = elmH - getMinHeight();\n                                    mOffY = dY - diffY;\n                                } else if (elmY + dY < minTop) {\n                                    diffY = minTop - elmY;\n                                    mOffY = dY - diffY;\n                                }\n                                elmY += diffY;\n                                elmH -= diffY;\n                            }\n                            if (hClass.indexOf('s') >= 0) {\n                                if (elmH + dY < getMinHeight()) {\n                                    diffY = getMinHeight() - elmH;\n                                    mOffY = dY - diffY;\n                                } else if (elmY + elmH + dY > maxTop) {\n                                    diffY = maxTop - elmY - elmH;\n                                    mOffY = dY - diffY;\n                                }\n                                elmH += diffY;\n                            }\n                            if (hClass.indexOf('w') >= 0) {\n                                if (elmW - dX < getMinWidth()) {\n                                    diffX = elmW - getMinWidth();\n                                    mOffX = dX - diffX;\n                                } else if (elmX + dX < minLeft) {\n                                    diffX = minLeft - elmX;\n                                    mOffX = dX - diffX;\n                                }\n                                elmX += diffX;\n                                elmW -= diffX;\n                            }\n                            if (hClass.indexOf('e') >= 0) {\n                                if (elmW + dX < getMinWidth()) {\n                                    diffX = getMinWidth() - elmW;\n                                    mOffX = dX - diffX;\n                                } else if (elmX + elmW + dX > maxLeft) {\n                                    diffX = maxLeft - elmX - elmW;\n                                    mOffX = dX - diffX;\n                                }\n                                elmW += diffX;\n                            }\n\n                            // set new position\n                            $el.css({\n                                'top': elmY + 'px',\n                                'left': elmX + 'px',\n                                'width': elmW + 'px',\n                                'height': elmH + 'px'\n                            });\n\n                            resize(e);\n\n                            return true;\n                        }\n\n                        function mouseUp(e) {\n                            // restore draggable setting to its original state\n                            if (gridster.draggable.enabled !== savedDraggable) {\n                                gridster.draggable.enabled = savedDraggable;\n                                scope.$broadcast('gridster-draggable-changed');\n                            }\n\n                            mOffX = mOffY = 0;\n\n                            resizeStop(e);\n\n                            return true;\n                        }\n\n                        function resize(e) {\n                            var oldRow = item.row,\n                                oldCol = item.col,\n                                oldSizeX = item.sizeX,\n                                oldSizeY = item.sizeY,\n                                hasCallback = gridster.resizable && gridster.resizable.resize;\n\n                            var col = item.col;\n                            // only change column if grabbing left edge\n                            if (['w', 'nw', 'sw'].indexOf(handleClass) !== -1) {\n                                col = gridster.pixelsToColumns(elmX, false);\n                            }\n\n                            var row = item.row;\n                            // only change row if grabbing top edge\n                            if (['n', 'ne', 'nw'].indexOf(handleClass) !== -1) {\n                                row = gridster.pixelsToRows(elmY, false);\n                            }\n\n                            var sizeX = item.sizeX;\n                            // only change row if grabbing left or right edge\n                            if (['n', 's'].indexOf(handleClass) === -1) {\n                                sizeX = gridster.pixelsToColumns(elmW, true);\n                            }\n\n                            var sizeY = item.sizeY;\n                            // only change row if grabbing top or bottom edge\n                            if (['e', 'w'].indexOf(handleClass) === -1) {\n                                sizeY = gridster.pixelsToRows(elmH, true);\n                            }\n\n                            if (gridster.pushing !== false || gridster.getItems(row, col, sizeX, sizeY, item).length === 0) {\n                                item.row = row;\n                                item.col = col;\n                                item.sizeX = sizeX;\n                                item.sizeY = sizeY;\n                            }\n                            var isChanged = item.row !== oldRow || item.col !== oldCol || item.sizeX !== oldSizeX || item.sizeY !== oldSizeY;\n\n                            if (hasCallback || isChanged) {\n                                scope.$apply(function() {\n                                    if (hasCallback) {\n                                        gridster.resizable.resize(e, $el, itemOptions); // options is the item model\n                                    }\n                                });\n                            }\n                        }\n\n                        function resizeStop(e) {\n                            $el.removeClass('gridster-item-moving');\n                            $el.removeClass('gridster-item-resizing');\n\n                            gridster.movingItem = null;\n\n                            item.setPosition(item.row, item.col);\n                            item.setSizeY(item.sizeY);\n                            item.setSizeX(item.sizeX);\n\n                            scope.$apply(function() {\n                                if (gridster.resizable && gridster.resizable.stop) {\n                                    gridster.resizable.stop(e, $el, itemOptions); // options is the item model\n                                }\n                            });\n                        }\n\n                        var $dragHandle = null;\n                        var unifiedInput;\n\n                        this.enable = function() {\n                            if (!$dragHandle) {\n                                $dragHandle = angular.element('<div class=\"gridster-item-resizable-handler handle-' + hClass + '\"></div>');\n                                $el.append($dragHandle);\n                            }\n\n                            unifiedInput = new gridster.unifiedInput($dragHandle[0], mouseDown, mouseMove, mouseUp);\n                            unifiedInput.enable();\n                        };\n\n                        this.disable = function() {\n                            if ($dragHandle) {\n                                $dragHandle.remove();\n                                $dragHandle = null;\n                            }\n\n                            unifiedInput.disable();\n                            unifiedInput = undefined;\n                        };\n\n                        this.destroy = function() {\n                            this.disable();\n                        };\n                    }\n\n                    var handles = [];\n                    var handlesOpts = gridster.resizable.handles;\n                    if (typeof handlesOpts === 'string') {\n                        handlesOpts = gridster.resizable.handles.split(',');\n                    }\n                    var enabled = false;\n\n                    for (var c = 0, l = handlesOpts.length; c < l; c++) {\n                        handles.push(new ResizeHandle(handlesOpts[c]));\n                    }\n\n                    this.enable = function() {\n                        if (enabled) {\n                            return;\n                        }\n                        for (var c = 0, l = handles.length; c < l; c++) {\n                            handles[c].enable();\n                        }\n                        enabled = true;\n                    };\n\n                    this.disable = function() {\n                        if (!enabled) {\n                            return;\n                        }\n                        for (var c = 0, l = handles.length; c < l; c++) {\n                            handles[c].disable();\n                        }\n                        enabled = false;\n                    };\n\n                    this.toggle = function(enabled) {\n                        if (enabled) {\n                            this.enable();\n                        } else {\n                            this.disable();\n                        }\n                    };\n\n                    this.destroy = function() {\n                        for (var c = 0, l = handles.length; c < l; c++) {\n                            handles[c].destroy();\n                        }\n                    };\n                }\n                return GridsterResizable;\n            }\n        ])\n\n    /**\n     * GridsterItem directive\n     */\n        .directive('gridsterItem', ['$parse', 'GridsterDraggable', 'GridsterResizable',\n            function($parse, GridsterDraggable, GridsterResizable) {\n                return {\n                    restrict: 'EA',\n                    controller: 'GridsterItemCtrl',\n                    require: ['^gridster', 'gridsterItem'],\n                    link: function(scope, $el, attrs, controllers) {\n                        var optionsKey = attrs.gridsterItem,\n                            options;\n\n                        var gridster = controllers[0],\n                            item = controllers[1];\n\n                        // bind the item's position properties\n                        if (optionsKey) {\n                            var $optionsGetter = $parse(optionsKey);\n                            options = $optionsGetter(scope) || {};\n                            if (!options && $optionsGetter.assign) {\n                                options = {\n                                    row: item.row,\n                                    col: item.col,\n                                    sizeX: item.sizeX,\n                                    sizeY: item.sizeY,\n                                    minSizeX: 0,\n                                    minSizeY: 0,\n                                    maxSizeX: null,\n                                    maxSizeY: null\n                                };\n                                $optionsGetter.assign(scope, options);\n                            }\n                        } else {\n                            options = attrs;\n                        }\n\n                        item.init($el, gridster);\n\n                        $el.addClass('gridster-item');\n\n                        var aspects = ['minSizeX', 'maxSizeX', 'minSizeY', 'maxSizeY', 'sizeX', 'sizeY', 'row', 'col'],\n                            $getters = {};\n\n                        var aspectFn = function(aspect) {\n                            var key;\n                            if (typeof options[aspect] === 'string') {\n                                key = options[aspect];\n                            } else if (typeof options[aspect.toLowerCase()] === 'string') {\n                                key = options[aspect.toLowerCase()];\n                            } else if (optionsKey) {\n                                key = $parse(optionsKey + '.' + aspect);\n                            } else {\n                                return;\n                            }\n                            $getters[aspect] = $parse(key);\n\n                            // when the value changes externally, update the internal item object\n                            scope.$watch(key, function(newVal) {\n                                newVal = parseInt(newVal, 10);\n                                if (!isNaN(newVal)) {\n                                    item[aspect] = newVal;\n                                }\n                            });\n\n                            // initial set\n                            var val = $getters[aspect](scope);\n                            if (typeof val === 'number') {\n                                item[aspect] = val;\n                            }\n                        };\n\n                        for (var i = 0, l = aspects.length; i < l; ++i) {\n                            aspectFn(aspects[i]);\n                        }\n\n                        scope.$broadcast('gridster-item-initialized', [item.sizeY, item.sizeX, item.getElementSizeY(), item.getElementSizeX()]);\n\n                        function positionChanged() {\n                            // call setPosition so the element and gridster controller are updated\n                            item.setPosition(item.row, item.col);\n\n                            // when internal item position changes, update externally bound values\n                            if ($getters.row && $getters.row.assign) {\n                                $getters.row.assign(scope, item.row);\n                            }\n                            if ($getters.col && $getters.col.assign) {\n                                $getters.col.assign(scope, item.col);\n                            }\n                        }\n                        scope.$watch(function() {\n                            return item.row + ',' + item.col;\n                        }, positionChanged);\n\n                        function sizeChanged() {\n                            var changedX = item.setSizeX(item.sizeX, true);\n                            if (changedX && $getters.sizeX && $getters.sizeX.assign) {\n                                $getters.sizeX.assign(scope, item.sizeX);\n                            }\n                            var changedY = item.setSizeY(item.sizeY, true);\n                            if (changedY && $getters.sizeY && $getters.sizeY.assign) {\n                                $getters.sizeY.assign(scope, item.sizeY);\n                            }\n\n                            if (changedX || changedY) {\n                                item.gridster.moveOverlappingItems(item);\n                                gridster.layoutChanged();\n                            }\n                        }\n                        scope.$watch(function() {\n                            return item.sizeY + ',' + item.sizeX + '|' + item.minSizeX + ',' + item.maxSizeX + ',' + item.minSizeY + ',' + item.maxSizeY;\n                        }, sizeChanged);\n\n                        var draggable = new GridsterDraggable($el, scope, gridster, item, options);\n                        var resizable = new GridsterResizable($el, scope, gridster, item, options);\n\n                        scope.$on('gridster-draggable-changed', function() {\n                            draggable.toggle(!gridster.isMobile && gridster.draggable && gridster.draggable.enabled);\n                        });\n                        scope.$on('gridster-resizable-changed', function() {\n                            resizable.toggle(!gridster.isMobile && gridster.resizable && gridster.resizable.enabled);\n                        });\n                        scope.$on('gridster-resized', function() {\n                            resizable.toggle(!gridster.isMobile && gridster.resizable && gridster.resizable.enabled);\n                        });\n                        scope.$watch(function() {\n                            return gridster.isMobile;\n                        }, function() {\n                            resizable.toggle(!gridster.isMobile && gridster.resizable && gridster.resizable.enabled);\n                            draggable.toggle(!gridster.isMobile && gridster.draggable && gridster.draggable.enabled);\n                        });\n\n                        function whichTransitionEvent() {\n                            var el = document.createElement('div');\n                            var transitions = {\n                                'transition': 'transitionend',\n                                'OTransition': 'oTransitionEnd',\n                                'MozTransition': 'transitionend',\n                                'WebkitTransition': 'webkitTransitionEnd'\n                            };\n                            for (var t in transitions) {\n                                if (el.style[t] !== undefined) {\n                                    return transitions[t];\n                                }\n                            }\n                        }\n\n                        $el.on(whichTransitionEvent(), function() {\n                            scope.$apply(function() {\n                                scope.$broadcast('gridster-item-transition-end');\n                            });\n                        });\n\n                        return scope.$on('$destroy', function() {\n                            try {\n                                resizable.destroy();\n                                draggable.destroy();\n                            } catch (e) {}\n\n                            try {\n                                gridster.removeItem(item);\n                            } catch (e) {}\n\n                            try {\n                                item.destroy();\n                            } catch (e) {}\n                        });\n                    }\n                };\n            }\n        ])\n\n    ;\n\n})(angular);"
  },
  {
    "path": "flowable-ui-web/modeler/libs/angular-hotkeys_1.4.5/hotkeys--activiti-patch.js",
    "content": "/*! \n * angular-hotkeys v1.4.5\n * https://chieffancypants.github.io/angular-hotkeys\n * Copyright (c) 2014 Wes Cruver\n * License: MIT\n */\n/*\n * angular-hotkeys\n *\n * Automatic keyboard shortcuts for your angular apps\n *\n * (c) 2014 Wes Cruver\n * License: MIT\n */\n\n(function() {\n\n  'use strict';\n\n  angular.module('cfp.hotkeys', []).provider('hotkeys', function() {\n\n    /**\n     * Configurable setting to disable the cheatsheet entirely\n     * @type {Boolean}\n     */\n    this.includeCheatSheet = true;\n\n    /**\n     * Configurable setting for the cheat sheet title\n     * @type {String}\n     */\n\n    this.templateTitle = 'Keyboard Shortcuts:';\n\n    /**\n     * Cheat sheet template in the event you want to totally customize it.\n     * @type {String}\n     */\n    this.template = '<div class=\"cfp-hotkeys-container fade\" ng-class=\"{in: helpVisible}\" style=\"display: none;\"><div class=\"cfp-hotkeys\">' +\n                      '<h4 class=\"cfp-hotkeys-title\">{{ title }}</h4>' +\n                      '<table><tbody>' +\n                        '<tr ng-repeat=\"hotkey in hotkeys | filter:{ description: \\'!$$undefined$$\\' }\">' +\n                          '<td class=\"cfp-hotkeys-keys\">' +\n                            '<span ng-repeat=\"key in hotkey.format() track by $index\" class=\"cfp-hotkeys-key\">{{ key }}</span>' +\n                          '</td>' +\n                          '<td class=\"cfp-hotkeys-text\">{{ hotkey.description }}</td>' +\n                        '</tr>' +\n                      '</tbody></table>' +\n                      '<div class=\"cfp-hotkeys-close\" ng-click=\"toggleCheatSheet()\">×</div>' +\n                    '</div></div>';\n\n    /**\n     * Configurable setting for the cheat sheet hotkey\n     * @type {String}\n     */\n    this.cheatSheetHotkey = '?';\n\n    /**\n     * Configurable setting for the cheat sheet description\n     * @type {String}\n     */\n    this.cheatSheetDescription = 'Show / hide this help menu';\n\n    this.$get = ['$rootElement', '$rootScope', '$compile', '$window', '$document', function ($rootElement, $rootScope, $compile, $window, $document) {\n\n      // monkeypatch Mousetrap's stopCallback() function\n      // this version doesn't return true when the element is an INPUT, SELECT, or TEXTAREA\n      // (instead we will perform this check per-key in the _add() method)\n      Mousetrap.stopCallback = function(event, element) {\n        // if the element has the class \"mousetrap\" then no need to stop\n        if ((' ' + element.className + ' ').indexOf(' mousetrap ') > -1) {\n          return false;\n        }\n\n        return (element.contentEditable && element.contentEditable == 'true');\n      };\n\n      /**\n       * Convert strings like cmd into symbols like ⌘\n       * @param  {String} combo Key combination, e.g. 'mod+f'\n       * @return {String}       The key combination with symbols\n       */\n      function symbolize (combo) {\n        var map = {\n          command   : '⌘',\n          shift     : '⇧',\n          left      : '←',\n          right     : '→',\n          up        : '↑',\n          down      : '↓',\n          'return'  : '↩',\n          backspace : '⌫'\n        };\n        combo = combo.split('+');\n\n        for (var i = 0; i < combo.length; i++) {\n          // try to resolve command / ctrl based on OS:\n          if (combo[i] === 'mod') {\n            if ($window.navigator && $window.navigator.platform.indexOf('Mac') >=0 ) {\n              combo[i] = 'command';\n            } else {\n              combo[i] = 'ctrl';\n            }\n          }\n\n          combo[i] = map[combo[i]] || combo[i];\n        }\n\n        return combo.join(' + ');\n      }\n\n      /**\n       * Hotkey object used internally for consistency\n       *\n       * @param {array}    combo       The keycombo. it's an array to support multiple combos\n       * @param {String}   description Description for the keycombo\n       * @param {Function} callback    function to execute when keycombo pressed\n       * @param {string}   action      the type of event to listen for (for mousetrap)\n       * @param {array}    allowIn     an array of tag names to allow this combo in ('INPUT', 'SELECT', and/or 'TEXTAREA')\n       * @param {Boolean}  persistent  Whether the hotkey persists navigation events\n       */\n      function Hotkey (combo, description, callback, action, allowIn, persistent) {\n        // TODO: Check that the values are sane because we could\n        // be trying to instantiate a new Hotkey with outside dev's\n        // supplied values\n\n        this.combo = combo instanceof Array ? combo : [combo];\n        this.description = description;\n        this.callback = callback;\n        this.action = action;\n        this.allowIn = allowIn;\n        this.persistent = persistent;\n      }\n\n      /**\n       * Helper method to format (symbolize) the key combo for display\n       *\n       * @return {[Array]} An array of the key combination sequence\n       *   for example: \"command+g c i\" becomes [\"⌘ + g\", \"c\", \"i\"]\n       *\n       * TODO: this gets called a lot.  We should cache the result\n       */\n      Hotkey.prototype.format = function() {\n\n        // Don't show all the possible key combos, just the first one.  Not sure\n        // of usecase here, so open a ticket if my assumptions are wrong\n        var combo = this.combo[0];\n\n        var sequence = combo.split(/[\\s]/);\n        for (var i = 0; i < sequence.length; i++) {\n          sequence[i] = symbolize(sequence[i]);\n        }\n\n        return sequence;\n      };\n\n      /**\n       * A new scope used internally for the cheatsheet\n       * @type {$rootScope.Scope}\n       */\n      var scope = $rootScope.$new();\n\n      /**\n       * Holds an array of Hotkey objects currently bound\n       * @type {Array}\n       */\n      scope.hotkeys = [];\n\n      /**\n       * Contains the state of the help's visibility\n       * @type {Boolean}\n       */\n      scope.helpVisible = false;\n\n      /**\n       * Holds the title string for the help menu\n       * @type {String}\n       */\n      scope.title = this.templateTitle;\n\n      /**\n       * Expose toggleCheatSheet to hotkeys scope so we can call it using\n       * ng-click from the template\n       * @type {function}\n       */\n      scope.toggleCheatSheet = toggleCheatSheet;\n\n\n      /**\n       * Holds references to the different scopes that have bound hotkeys\n       * attached.  This is useful to catch when the scopes are `$destroy`d and\n       * then automatically unbind the hotkey.\n       *\n       * @type {Array}\n       */\n      var boundScopes = [];\n\n\n      $rootScope.$on('$routeChangeSuccess', function (event, route) {\n        purgeHotkeys();\n\n        if (route && route.hotkeys) {\n          angular.forEach(route.hotkeys, function (hotkey) {\n            // a string was given, which implies this is a function that is to be\n            // $eval()'d within that controller's scope\n            // TODO: hotkey here is super confusing.  sometimes a function (that gets turned into an array), sometimes a string\n            var callback = hotkey[2];\n            if (typeof(callback) === 'string' || callback instanceof String) {\n              hotkey[2] = [callback, route];\n            }\n\n            // todo: perform check to make sure not already defined:\n            // this came from a route, so it's likely not meant to be persistent\n            hotkey[5] = false;\n            _add.apply(this, hotkey);\n          });\n        }\n      });\n\n\n      // Auto-create a help menu:\n      if (this.includeCheatSheet) {\n        var document = $document[0];\n        var element = $rootElement[0];\n        var helpMenu = angular.element(this.template);\n        _add(this.cheatSheetHotkey, this.cheatSheetDescription, toggleCheatSheet);\n\n        // If $rootElement is document or documentElement, then body must be used\n        if (element === document || element === document.documentElement) {\n          element = document.body;\n        }\n\n        angular.element(element).append($compile(helpMenu)(scope));\n      }\n\n\n      /**\n       * Purges all non-persistent hotkeys (such as those defined in routes)\n       *\n       * Without this, the same hotkey would get recreated everytime\n       * the route is accessed.\n       */\n      function purgeHotkeys() {\n        var i = scope.hotkeys.length;\n        while (i--) {\n          var hotkey = scope.hotkeys[i];\n          if (hotkey && !hotkey.persistent) {\n            _del(hotkey);\n          }\n        }\n      }\n\n      /**\n       * Toggles the help menu element's visiblity\n       */\n      var previousEsc = false;\n\n      function toggleCheatSheet() {\n        scope.helpVisible = !scope.helpVisible;\n\n        // Bind to esc to remove the cheat sheet.  Ideally, this would be done\n        // as a directive in the template, but that would create a nasty\n        // circular dependency issue that I don't feel like sorting out.\n        if (scope.helpVisible) {\n          previousEsc = _get('esc');\n          _del('esc');\n\n          // Here's an odd way to do this: we're going to use the original\n          // description of the hotkey on the cheat sheet so that it shows up.\n          // without it, no entry for esc will ever show up (#22)\n          _add('esc', previousEsc.description, toggleCheatSheet);\n        } else {\n          _del('esc');\n\n          // restore the previously bound ESC key\n          if (previousEsc !== false) {\n            _add(previousEsc);\n          }\n        }\n      }\n\n      /**\n       * Creates a new Hotkey and creates the Mousetrap binding\n       *\n       * @param {string}   combo       mousetrap key binding\n       * @param {string}   description description for the help menu\n       * @param {Function} callback    method to call when key is pressed\n       * @param {string}   action      the type of event to listen for (for mousetrap)\n       * @param {array}    allowIn     an array of tag names to allow this combo in ('INPUT', 'SELECT', and/or 'TEXTAREA')\n       * @param {boolean}  persistent  if true, the binding is preserved upon route changes\n       */\n      function _add (combo, description, callback, action, allowIn, persistent) {\n\n        // used to save original callback for \"allowIn\" wrapping:\n        var _callback;\n\n        // these elements are prevented by the default Mousetrap.stopCallback():\n        var preventIn = ['INPUT', 'SELECT', 'TEXTAREA'];\n\n        // Determine if object format was given:\n        var objType = Object.prototype.toString.call(combo);\n\n        if (objType === '[object Object]') {\n          description = combo.description;\n          callback    = combo.callback;\n          action      = combo.action;\n          persistent  = combo.persistent;\n          allowIn     = combo.allowIn;\n          combo       = combo.combo;\n        }\n\n        // description is optional:\n        if (description instanceof Function) {\n          action = callback;\n          callback = description;\n          description = '$$undefined$$';\n        } else if (angular.isUndefined(description)) {\n          description = '$$undefined$$';\n        }\n\n        // any items added through the public API are for controllers\n        // that persist through navigation, and thus undefined should mean\n        // true in this case.\n        if (persistent === undefined) {\n          persistent = true;\n        }\n\n        // if callback is defined, then wrap it in a function\n        // that checks if the event originated from a form element.\n        // the function blocks the callback from executing unless the element is specified\n        // in allowIn (emulates Mousetrap.stopCallback() on a per-key level)\n        if (typeof callback === 'function') {\n\n          // save the original callback\n          _callback = callback;\n\n          // make sure allowIn is an array\n          if (!(allowIn instanceof Array)) {\n            allowIn = [];\n          }\n\n          // remove anything from preventIn that's present in allowIn\n          var index;\n          for (var i=0; i < allowIn.length; i++) {\n            allowIn[i] = allowIn[i].toUpperCase();\n            index = preventIn.indexOf(allowIn[i]);\n            if (index !== -1) {\n              preventIn.splice(index, 1);\n            }\n          }\n\n          // create the new wrapper callback\n          callback = function(event) {\n            var shouldExecute = true;\n            var target = event.target || event.srcElement; // srcElement is IE only\n            var nodeName = target.nodeName.toUpperCase();\n\n            // check if the input has a mousetrap class, and skip checking preventIn if so\n            if ((' ' + target.className + ' ').indexOf(' mousetrap ') > -1) {\n              shouldExecute = true;\n            } else {\n              // don't execute callback if the event was fired from inside an element listed in preventIn\n              for (var i=0; i<preventIn.length; i++) {\n                if (preventIn[i] === nodeName) {\n                  shouldExecute = false;\n                  break;\n                }\n              }\n            }\n\n            if (shouldExecute) {\n              wrapApply(_callback.apply(this, arguments));\n            }\n          };\n        }\n\n        if (typeof(action) === 'string') {\n          Mousetrap.bind(combo, wrapApply(callback), action);\n        } else {\n          Mousetrap.bind(combo, wrapApply(callback));\n        }\n\n        var hotkey = new Hotkey(combo, description, callback, action, allowIn, persistent);\n        scope.hotkeys.push(hotkey);\n        return hotkey;\n      }\n\n      /**\n       * delete and unbind a Hotkey\n       *\n       * @param  {mixed} hotkey   Either the bound key or an instance of Hotkey\n       * @return {boolean}        true if successful\n       */\n      function _del (hotkey) {\n        var combo = (hotkey instanceof Hotkey) ? hotkey.combo : hotkey;\n\n        Mousetrap.unbind(combo);\n\n        if (angular.isArray(combo)) {\n          var retStatus = true;\n          var i = combo.length;\n          while (i--) {\n            retStatus = _del(combo[i]) && retStatus;\n          }\n          return retStatus;\n        } else {\n          var index = scope.hotkeys.indexOf(_get(combo));\n\n          if (index > -1) {\n            // if the combo has other combos bound, don't unbind the whole thing, just the one combo:\n            if (scope.hotkeys[index].combo.length > 1) {\n              scope.hotkeys[index].combo.splice(scope.hotkeys[index].combo.indexOf(combo), 1);\n            } else {\n              scope.hotkeys.splice(index, 1);\n            }\n            return true;\n          }\n        }\n\n        return false;\n\n      }\n\n      /**\n       * Get a Hotkey object by key binding\n       *\n       * @param  {[string]} combo  the key the Hotkey is bound to\n       * @return {Hotkey}          The Hotkey object\n       */\n      function _get (combo) {\n\n        var hotkey;\n\n        for (var i = 0; i < scope.hotkeys.length; i++) {\n          hotkey = scope.hotkeys[i];\n\n          if (hotkey.combo.indexOf(combo) > -1) {\n            return hotkey;\n          }\n        }\n\n        return false;\n      }\n\n      /**\n       * Binds the hotkey to a particular scope.  Useful if the scope is\n       * destroyed, we can automatically destroy the hotkey binding.\n       *\n       * @param  {Object} scope The scope to bind to\n       */\n      function bindTo (scope) {\n        // Only initialize once to allow multiple calls for same scope.\n        if (!(scope.$id in boundScopes)) {\n\n          // Add the scope to the list of bound scopes\n          boundScopes[scope.$id] = [];\n\n          scope.$on('$destroy', function () {\n            var i = boundScopes[scope.$id].length;\n            while (i--) {\n              _del(boundScopes[scope.$id][i]);\n              delete boundScopes[scope.$id][i];\n            }\n          });\n        }\n        // return an object with an add function so we can keep track of the\n        // hotkeys and their scope that we added via this chaining method\n        return {\n          add: function (args) {\n            var hotkey;\n\n            if (arguments.length > 1) {\n              hotkey = _add.apply(this, arguments);\n            } else {\n              hotkey = _add(args);\n            }\n\n            boundScopes[scope.$id].push(hotkey);\n            return this;\n          }\n        };\n      }\n\n      /**\n       * All callbacks sent to Mousetrap are wrapped using this function\n       * so that we can force a $scope.$apply()\n       *\n       * @param  {Function} callback [description]\n       * @return {[type]}            [description]\n       */\n      function wrapApply (callback) {\n        // return mousetrap a function to call\n        return function (event, combo) {\n\n          // if this is an array, it means we provided a route object\n          // because the scope wasn't available yet, so rewrap the callback\n          // now that the scope is available:\n          if (callback instanceof Array) {\n            var funcString = callback[0];\n            var route = callback[1];\n            callback = function (event) {\n              route.scope.$eval(funcString);\n            };\n          }\n\n          // this takes place outside angular, so we'll have to call\n          // $apply() to make sure angular's digest happens\n          $rootScope.$apply(function() {\n            // call the original hotkey callback with the keyboard event\n            callback(event, _get(combo));\n          });\n        };\n      }\n\n\n      var publicApi = {\n        add                   : _add,\n        del                   : _del,\n        get                   : _get,\n        bindTo                : bindTo,\n        template              : this.template,\n        toggleCheatSheet      : toggleCheatSheet,\n        includeCheatSheet     : this.includeCheatSheet,\n        cheatSheetHotkey      : this.cheatSheetHotkey,\n        cheatSheetDescription : this.cheatSheetDescription,\n        purgeHotkeys          : purgeHotkeys,\n        templateTitle         : this.templateTitle\n      };\n\n      return publicApi;\n\n    }];\n  })\n\n  .directive('hotkey', ['hotkeys', function (hotkeys) {\n    return {\n      restrict: 'A',\n      link: function (scope, el, attrs) {\n        var key, allowIn;\n\n        angular.forEach(scope.$eval(attrs.hotkey), function (func, hotkey) {\n          // split and trim the hotkeys string into array\n          allowIn = typeof attrs.hotkeyAllowIn === \"string\" ? attrs.hotkeyAllowIn.split(/[\\s,]+/) : [];\n\n          key = hotkey;\n\n          hotkeys.add({\n            combo: hotkey,\n            description: attrs.hotkeyDescription,\n            callback: func,\n            action: attrs.hotkeyAction,\n            allowIn: allowIn\n          });\n        });\n\n        // remove the hotkey if the directive is destroyed:\n        el.bind('$destroy', function() {\n          hotkeys.del(key);\n        });\n      }\n    };\n  }])\n\n  .run(['hotkeys', function(hotkeys) {\n    // force hotkeys to run by injecting it. Without this, hotkeys only runs\n    // when a controller or something else asks for it via DI.\n  }]);\n\n})();\n\n/*global define:false */\n/**\n * Copyright 2013 Craig Campbell\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 * Mousetrap is a simple keyboard shortcut library for Javascript with\n * no external dependencies\n *\n * @version 1.4.6\n * @url craig.is/killing/mice\n */\n(function(window, document, undefined) {\n\n    /**\n     * mapping of special keycodes to their corresponding keys\n     *\n     * everything in this dictionary cannot use keypress events\n     * so it has to be here to map to the correct keycodes for\n     * keyup/keydown events\n     *\n     * @type {Object}\n     */\n    var _MAP = {\n            8: 'backspace',\n            9: 'tab',\n            13: 'enter',\n            16: 'shift',\n            17: 'ctrl',\n            18: 'alt',\n            20: 'capslock',\n            27: 'esc',\n            32: 'space',\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: 'ins',\n            46: 'del',\n            91: 'meta',\n            93: 'meta',\n            224: 'meta'\n        },\n\n        /**\n         * mapping for special characters so they can support\n         *\n         * this dictionary is only used incase you want to bind a\n         * keyup or keydown event to one of these keys\n         *\n         * @type {Object}\n         */\n        _KEYCODE_MAP = {\n            106: '*',\n            107: '+',\n            109: '-',\n            110: '.',\n            111 : '/',\n            186: ';',\n            187: '=',\n            188: ',',\n            189: '-',\n            190: '.',\n            191: '/',\n            192: '`',\n            219: '[',\n            220: '\\\\',\n            221: ']',\n            222: '\\''\n        },\n\n        /**\n         * this is a mapping of keys that require shift on a US keypad\n         * back to the non shift equivelents\n         *\n         * this is so you can use keyup events with these keys\n         *\n         * note that this will only work reliably on US keyboards\n         *\n         * @type {Object}\n         */\n        _SHIFT_MAP = {\n            '~': '`',\n            '!': '1',\n            '@': '2',\n            '#': '3',\n            '$': '4',\n            '%': '5',\n            '^': '6',\n            '&': '7',\n            '*': '8',\n            '(': '9',\n            ')': '0',\n            '_': '-',\n            '+': '=',\n            ':': ';',\n            '\\\"': '\\'',\n            '<': ',',\n            '>': '.',\n            '?': '/',\n            '|': '\\\\'\n        },\n\n        /**\n         * this is a list of special strings you can use to map\n         * to modifier keys when you specify your keyboard shortcuts\n         *\n         * @type {Object}\n         */\n        _SPECIAL_ALIASES = {\n            'option': 'alt',\n            'command': 'meta',\n            'return': 'enter',\n            'escape': 'esc',\n            'mod': /Mac|iPod|iPhone|iPad/.test(navigator.platform) ? 'meta' : 'ctrl'\n        },\n\n        /**\n         * variable to store the flipped version of _MAP from above\n         * needed to check if we should use keypress or not when no action\n         * is specified\n         *\n         * @type {Object|undefined}\n         */\n        _REVERSE_MAP,\n\n        /**\n         * a list of all the callbacks setup via Mousetrap.bind()\n         *\n         * @type {Object}\n         */\n        _callbacks = {},\n\n        /**\n         * direct map of string combinations to callbacks used for trigger()\n         *\n         * @type {Object}\n         */\n        _directMap = {},\n\n        /**\n         * keeps track of what level each sequence is at since multiple\n         * sequences can start out with the same sequence\n         *\n         * @type {Object}\n         */\n        _sequenceLevels = {},\n\n        /**\n         * variable to store the setTimeout call\n         *\n         * @type {null|number}\n         */\n        _resetTimer,\n\n        /**\n         * temporary state where we will ignore the next keyup\n         *\n         * @type {boolean|string}\n         */\n        _ignoreNextKeyup = false,\n\n        /**\n         * temporary state where we will ignore the next keypress\n         *\n         * @type {boolean}\n         */\n        _ignoreNextKeypress = false,\n\n        /**\n         * are we currently inside of a sequence?\n         * type of action (\"keyup\" or \"keydown\" or \"keypress\") or false\n         *\n         * @type {boolean|string}\n         */\n        _nextExpectedAction = false;\n\n    /**\n     * loop through the f keys, f1 to f19 and add them to the map\n     * programatically\n     */\n    for (var i = 1; i < 20; ++i) {\n        _MAP[111 + i] = 'f' + i;\n    }\n\n    /**\n     * loop through to map numbers on the numeric keypad\n     */\n    for (i = 0; i <= 9; ++i) {\n        _MAP[i + 96] = i;\n    }\n\n    /**\n     * cross browser add event method\n     *\n     * @param {Element|HTMLDocument} object\n     * @param {string} type\n     * @param {Function} callback\n     * @returns void\n     */\n    function _addEvent(object, type, callback) {\n        if (object.addEventListener) {\n            object.addEventListener(type, callback, false);\n            return;\n        }\n\n        object.attachEvent('on' + type, callback);\n    }\n\n    /**\n     * takes the event and returns the key character\n     *\n     * @param {Event} e\n     * @return {string}\n     */\n    function _characterFromEvent(e) {\n\n        // for keypress events we should return the character as is\n        if (e.type == 'keypress') {\n            var character = String.fromCharCode(e.which);\n\n            // if the shift key is not pressed then it is safe to assume\n            // that we want the character to be lowercase.  this means if\n            // you accidentally have caps lock on then your key bindings\n            // will continue to work\n            //\n            // the only side effect that might not be desired is if you\n            // bind something like 'A' cause you want to trigger an\n            // event when capital A is pressed caps lock will no longer\n            // trigger the event.  shift+a will though.\n            if (!e.shiftKey) {\n                character = character.toLowerCase();\n            }\n\n            return character;\n        }\n\n        // for non keypress events the special maps are needed\n        if (_MAP[e.which]) {\n            return _MAP[e.which];\n        }\n\n        if (_KEYCODE_MAP[e.which]) {\n            return _KEYCODE_MAP[e.which];\n        }\n\n        // if it is not in the special map\n\n        // with keydown and keyup events the character seems to always\n        // come in as an uppercase character whether you are pressing shift\n        // or not.  we should make sure it is always lowercase for comparisons\n        return String.fromCharCode(e.which).toLowerCase();\n    }\n\n    /**\n     * checks if two arrays are equal\n     *\n     * @param {Array} modifiers1\n     * @param {Array} modifiers2\n     * @returns {boolean}\n     */\n    function _modifiersMatch(modifiers1, modifiers2) {\n        return modifiers1.sort().join(',') === modifiers2.sort().join(',');\n    }\n\n    /**\n     * resets all sequence counters except for the ones passed in\n     *\n     * @param {Object} doNotReset\n     * @returns void\n     */\n    function _resetSequences(doNotReset) {\n        doNotReset = doNotReset || {};\n\n        var activeSequences = false,\n            key;\n\n        for (key in _sequenceLevels) {\n            if (doNotReset[key]) {\n                activeSequences = true;\n                continue;\n            }\n            _sequenceLevels[key] = 0;\n        }\n\n        if (!activeSequences) {\n            _nextExpectedAction = false;\n        }\n    }\n\n    /**\n     * finds all callbacks that match based on the keycode, modifiers,\n     * and action\n     *\n     * @param {string} character\n     * @param {Array} modifiers\n     * @param {Event|Object} e\n     * @param {string=} sequenceName - name of the sequence we are looking for\n     * @param {string=} combination\n     * @param {number=} level\n     * @returns {Array}\n     */\n    function _getMatches(character, modifiers, e, sequenceName, combination, level) {\n        var i,\n            callback,\n            matches = [],\n            action = e.type;\n\n        // if there are no events related to this keycode\n        if (!_callbacks[character]) {\n            return [];\n        }\n\n        // if a modifier key is coming up on its own we should allow it\n        if (action == 'keyup' && _isModifier(character)) {\n            modifiers = [character];\n        }\n\n        // loop through all callbacks for the key that was pressed\n        // and see if any of them match\n        for (i = 0; i < _callbacks[character].length; ++i) {\n            callback = _callbacks[character][i];\n\n            // if a sequence name is not specified, but this is a sequence at\n            // the wrong level then move onto the next match\n            if (!sequenceName && callback.seq && _sequenceLevels[callback.seq] != callback.level) {\n                continue;\n            }\n\n            // if the action we are looking for doesn't match the action we got\n            // then we should keep going\n            if (action != callback.action) {\n                continue;\n            }\n\n            // if this is a keypress event and the meta key and control key\n            // are not pressed that means that we need to only look at the\n            // character, otherwise check the modifiers as well\n            //\n            // chrome will not fire a keypress if meta or control is down\n            // safari will fire a keypress if meta or meta+shift is down\n            // firefox will fire a keypress if meta or control is down\n            if ((action == 'keypress' && !e.metaKey && !e.ctrlKey) || _modifiersMatch(modifiers, callback.modifiers)) {\n\n                // when you bind a combination or sequence a second time it\n                // should overwrite the first one.  if a sequenceName or\n                // combination is specified in this call it does just that\n                //\n                // @todo make deleting its own method?\n                var deleteCombo = !sequenceName && callback.combo == combination;\n                var deleteSequence = sequenceName && callback.seq == sequenceName && callback.level == level;\n                if (deleteCombo || deleteSequence) {\n                    _callbacks[character].splice(i, 1);\n                }\n\n                matches.push(callback);\n            }\n        }\n\n        return matches;\n    }\n\n    /**\n     * takes a key event and figures out what the modifiers are\n     *\n     * @param {Event} e\n     * @returns {Array}\n     */\n    function _eventModifiers(e) {\n        var modifiers = [];\n\n        if (e.shiftKey) {\n            modifiers.push('shift');\n        }\n\n        if (e.altKey) {\n            modifiers.push('alt');\n        }\n\n        if (e.ctrlKey) {\n            modifiers.push('ctrl');\n        }\n\n        if (e.metaKey) {\n            modifiers.push('meta');\n        }\n\n        return modifiers;\n    }\n\n    /**\n     * prevents default for this event\n     *\n     * @param {Event} e\n     * @returns void\n     */\n    function _preventDefault(e) {\n        if (e.preventDefault) {\n            e.preventDefault();\n            return;\n        }\n\n        e.returnValue = false;\n    }\n\n    /**\n     * stops propogation for this event\n     *\n     * @param {Event} e\n     * @returns void\n     */\n    function _stopPropagation(e) {\n        if (e.stopPropagation) {\n            e.stopPropagation();\n            return;\n        }\n\n        e.cancelBubble = true;\n    }\n\n    /**\n     * actually calls the callback function\n     *\n     * if your callback function returns false this will use the jquery\n     * convention - prevent default and stop propogation on the event\n     *\n     * @param {Function} callback\n     * @param {Event} e\n     * @returns void\n     */\n    function _fireCallback(callback, e, combo, sequence) {\n\n        // if this event should not happen stop here\n        if (Mousetrap.stopCallback(e, e.target || e.srcElement, combo, sequence)) {\n            return;\n        }\n\n        if (callback(e, combo) === false) {\n            _preventDefault(e);\n            _stopPropagation(e);\n        }\n    }\n\n    /**\n     * handles a character key event\n     *\n     * @param {string} character\n     * @param {Array} modifiers\n     * @param {Event} e\n     * @returns void\n     */\n    function _handleKey(character, modifiers, e) {\n        var callbacks = _getMatches(character, modifiers, e),\n            i,\n            doNotReset = {},\n            maxLevel = 0,\n            processedSequenceCallback = false;\n\n        // Calculate the maxLevel for sequences so we can only execute the longest callback sequence\n        for (i = 0; i < callbacks.length; ++i) {\n            if (callbacks[i].seq) {\n                maxLevel = Math.max(maxLevel, callbacks[i].level);\n            }\n        }\n\n        // loop through matching callbacks for this key event\n        for (i = 0; i < callbacks.length; ++i) {\n\n            // fire for all sequence callbacks\n            // this is because if for example you have multiple sequences\n            // bound such as \"g i\" and \"g t\" they both need to fire the\n            // callback for matching g cause otherwise you can only ever\n            // match the first one\n            if (callbacks[i].seq) {\n\n                // only fire callbacks for the maxLevel to prevent\n                // subsequences from also firing\n                //\n                // for example 'a option b' should not cause 'option b' to fire\n                // even though 'option b' is part of the other sequence\n                //\n                // any sequences that do not match here will be discarded\n                // below by the _resetSequences call\n                if (callbacks[i].level != maxLevel) {\n                    continue;\n                }\n\n                processedSequenceCallback = true;\n\n                // keep a list of which sequences were matches for later\n                doNotReset[callbacks[i].seq] = 1;\n                _fireCallback(callbacks[i].callback, e, callbacks[i].combo, callbacks[i].seq);\n                continue;\n            }\n\n            // if there were no sequence matches but we are still here\n            // that means this is a regular match so we should fire that\n            if (!processedSequenceCallback) {\n                _fireCallback(callbacks[i].callback, e, callbacks[i].combo);\n            }\n        }\n\n        // if the key you pressed matches the type of sequence without\n        // being a modifier (ie \"keyup\" or \"keypress\") then we should\n        // reset all sequences that were not matched by this event\n        //\n        // this is so, for example, if you have the sequence \"h a t\" and you\n        // type \"h e a r t\" it does not match.  in this case the \"e\" will\n        // cause the sequence to reset\n        //\n        // modifier keys are ignored because you can have a sequence\n        // that contains modifiers such as \"enter ctrl+space\" and in most\n        // cases the modifier key will be pressed before the next key\n        //\n        // also if you have a sequence such as \"ctrl+b a\" then pressing the\n        // \"b\" key will trigger a \"keypress\" and a \"keydown\"\n        //\n        // the \"keydown\" is expected when there is a modifier, but the\n        // \"keypress\" ends up matching the _nextExpectedAction since it occurs\n        // after and that causes the sequence to reset\n        //\n        // we ignore keypresses in a sequence that directly follow a keydown\n        // for the same character\n        var ignoreThisKeypress = e.type == 'keypress' && _ignoreNextKeypress;\n        if (e.type == _nextExpectedAction && !_isModifier(character) && !ignoreThisKeypress) {\n            _resetSequences(doNotReset);\n        }\n\n        _ignoreNextKeypress = processedSequenceCallback && e.type == 'keydown';\n    }\n\n    /**\n     * handles a keydown event\n     *\n     * @param {Event} e\n     * @returns void\n     */\n    function _handleKeyEvent(e) {\n\n        // normalize e.which for key events\n        // @see http://stackoverflow.com/questions/4285627/javascript-keycode-vs-charcode-utter-confusion\n        if (typeof e.which !== 'number') {\n            e.which = e.keyCode;\n        }\n\n        var character = _characterFromEvent(e);\n\n        // no character found then stop\n        if (!character) {\n            return;\n        }\n\n        // need to use === for the character check because the character can be 0\n        if (e.type == 'keyup' && _ignoreNextKeyup === character) {\n            _ignoreNextKeyup = false;\n            return;\n        }\n\n        Mousetrap.handleKey(character, _eventModifiers(e), e);\n    }\n\n    /**\n     * determines if the keycode specified is a modifier key or not\n     *\n     * @param {string} key\n     * @returns {boolean}\n     */\n    function _isModifier(key) {\n        return key == 'shift' || key == 'ctrl' || key == 'alt' || key == 'meta';\n    }\n\n    /**\n     * called to set a 1 second timeout on the specified sequence\n     *\n     * this is so after each key press in the sequence you have 1 second\n     * to press the next key before you have to start over\n     *\n     * @returns void\n     */\n    function _resetSequenceTimer() {\n        clearTimeout(_resetTimer);\n        _resetTimer = setTimeout(_resetSequences, 1000);\n    }\n\n    /**\n     * reverses the map lookup so that we can look for specific keys\n     * to see what can and can't use keypress\n     *\n     * @return {Object}\n     */\n    function _getReverseMap() {\n        if (!_REVERSE_MAP) {\n            _REVERSE_MAP = {};\n            for (var key in _MAP) {\n\n                // pull out the numeric keypad from here cause keypress should\n                // be able to detect the keys from the character\n                if (key > 95 && key < 112) {\n                    continue;\n                }\n\n                if (_MAP.hasOwnProperty(key)) {\n                    _REVERSE_MAP[_MAP[key]] = key;\n                }\n            }\n        }\n        return _REVERSE_MAP;\n    }\n\n    /**\n     * picks the best action based on the key combination\n     *\n     * @param {string} key - character for key\n     * @param {Array} modifiers\n     * @param {string=} action passed in\n     */\n    function _pickBestAction(key, modifiers, action) {\n\n        // if no action was picked in we should try to pick the one\n        // that we think would work best for this key\n        if (!action) {\n            action = _getReverseMap()[key] ? 'keydown' : 'keypress';\n        }\n\n        // modifier keys don't work as expected with keypress,\n        // switch to keydown\n        if (action == 'keypress' && modifiers.length) {\n            action = 'keydown';\n        }\n\n        return action;\n    }\n\n    /**\n     * binds a key sequence to an event\n     *\n     * @param {string} combo - combo specified in bind call\n     * @param {Array} keys\n     * @param {Function} callback\n     * @param {string=} action\n     * @returns void\n     */\n    function _bindSequence(combo, keys, callback, action) {\n\n        // start off by adding a sequence level record for this combination\n        // and setting the level to 0\n        _sequenceLevels[combo] = 0;\n\n        /**\n         * callback to increase the sequence level for this sequence and reset\n         * all other sequences that were active\n         *\n         * @param {string} nextAction\n         * @returns {Function}\n         */\n        function _increaseSequence(nextAction) {\n            return function() {\n                _nextExpectedAction = nextAction;\n                ++_sequenceLevels[combo];\n                _resetSequenceTimer();\n            };\n        }\n\n        /**\n         * wraps the specified callback inside of another function in order\n         * to reset all sequence counters as soon as this sequence is done\n         *\n         * @param {Event} e\n         * @returns void\n         */\n        function _callbackAndReset(e) {\n            _fireCallback(callback, e, combo);\n\n            // we should ignore the next key up if the action is key down\n            // or keypress.  this is so if you finish a sequence and\n            // release the key the final key will not trigger a keyup\n            if (action !== 'keyup') {\n                _ignoreNextKeyup = _characterFromEvent(e);\n            }\n\n            // weird race condition if a sequence ends with the key\n            // another sequence begins with\n            setTimeout(_resetSequences, 10);\n        }\n\n        // loop through keys one at a time and bind the appropriate callback\n        // function.  for any key leading up to the final one it should\n        // increase the sequence. after the final, it should reset all sequences\n        //\n        // if an action is specified in the original bind call then that will\n        // be used throughout.  otherwise we will pass the action that the\n        // next key in the sequence should match.  this allows a sequence\n        // to mix and match keypress and keydown events depending on which\n        // ones are better suited to the key provided\n        for (var i = 0; i < keys.length; ++i) {\n            var isFinal = i + 1 === keys.length;\n            var wrappedCallback = isFinal ? _callbackAndReset : _increaseSequence(action || _getKeyInfo(keys[i + 1]).action);\n            _bindSingle(keys[i], wrappedCallback, action, combo, i);\n        }\n    }\n\n    /**\n     * Converts from a string key combination to an array\n     *\n     * @param  {string} combination like \"command+shift+l\"\n     * @return {Array}\n     */\n    function _keysFromString(combination) {\n        if (combination === '+') {\n            return ['+'];\n        }\n\n        return combination.split('+');\n    }\n\n    /**\n     * Gets info for a specific key combination\n     *\n     * @param  {string} combination key combination (\"command+s\" or \"a\" or \"*\")\n     * @param  {string=} action\n     * @returns {Object}\n     */\n    function _getKeyInfo(combination, action) {\n        var keys,\n            key,\n            i,\n            modifiers = [];\n\n        // take the keys from this pattern and figure out what the actual\n        // pattern is all about\n        keys = _keysFromString(combination);\n\n        for (i = 0; i < keys.length; ++i) {\n            key = keys[i];\n\n            // normalize key names\n            if (_SPECIAL_ALIASES[key]) {\n                key = _SPECIAL_ALIASES[key];\n            }\n\n            // if this is not a keypress event then we should\n            // be smart about using shift keys\n            // this will only work for US keyboards however\n            if (action && action != 'keypress' && _SHIFT_MAP[key]) {\n                key = _SHIFT_MAP[key];\n                modifiers.push('shift');\n            }\n\n            // if this key is a modifier then add it to the list of modifiers\n            if (_isModifier(key)) {\n                modifiers.push(key);\n            }\n        }\n\n        // depending on what the key combination is\n        // we will try to pick the best event for it\n        action = _pickBestAction(key, modifiers, action);\n\n        return {\n            key: key,\n            modifiers: modifiers,\n            action: action\n        };\n    }\n\n    /**\n     * binds a single keyboard combination\n     *\n     * @param {string} combination\n     * @param {Function} callback\n     * @param {string=} action\n     * @param {string=} sequenceName - name of sequence if part of sequence\n     * @param {number=} level - what part of the sequence the command is\n     * @returns void\n     */\n    function _bindSingle(combination, callback, action, sequenceName, level) {\n\n        // store a direct mapped reference for use with Mousetrap.trigger\n        _directMap[combination + ':' + action] = callback;\n\n        // make sure multiple spaces in a row become a single space\n        combination = combination.replace(/\\s+/g, ' ');\n\n        var sequence = combination.split(' '),\n            info;\n\n        // if this pattern is a sequence of keys then run through this method\n        // to reprocess each pattern one key at a time\n        if (sequence.length > 1) {\n            _bindSequence(combination, sequence, callback, action);\n            return;\n        }\n\n        info = _getKeyInfo(combination, action);\n\n        // make sure to initialize array if this is the first time\n        // a callback is added for this key\n        _callbacks[info.key] = _callbacks[info.key] || [];\n\n        // remove an existing match if there is one\n        _getMatches(info.key, info.modifiers, {type: info.action}, sequenceName, combination, level);\n\n        // add this call back to the array\n        // if it is a sequence put it at the beginning\n        // if not put it at the end\n        //\n        // this is important because the way these are processed expects\n        // the sequence ones to come first\n        _callbacks[info.key][sequenceName ? 'unshift' : 'push']({\n            callback: callback,\n            modifiers: info.modifiers,\n            action: info.action,\n            seq: sequenceName,\n            level: level,\n            combo: combination\n        });\n    }\n\n    /**\n     * binds multiple combinations to the same callback\n     *\n     * @param {Array} combinations\n     * @param {Function} callback\n     * @param {string|undefined} action\n     * @returns void\n     */\n    function _bindMultiple(combinations, callback, action) {\n        for (var i = 0; i < combinations.length; ++i) {\n            _bindSingle(combinations[i], callback, action);\n        }\n    }\n\n    // start!\n    _addEvent(document, 'keypress', _handleKeyEvent);\n    _addEvent(document, 'keydown', _handleKeyEvent);\n    _addEvent(document, 'keyup', _handleKeyEvent);\n\n    var Mousetrap = {\n\n        /**\n         * binds an event to mousetrap\n         *\n         * can be a single key, a combination of keys separated with +,\n         * an array of keys, or a sequence of keys separated by spaces\n         *\n         * be sure to list the modifier keys first to make sure that the\n         * correct key ends up getting bound (the last key in the pattern)\n         *\n         * @param {string|Array} keys\n         * @param {Function} callback\n         * @param {string=} action - 'keypress', 'keydown', or 'keyup'\n         * @returns void\n         */\n        bind: function(keys, callback, action) {\n            keys = keys instanceof Array ? keys : [keys];\n            _bindMultiple(keys, callback, action);\n            return this;\n        },\n\n        /**\n         * unbinds an event to mousetrap\n         *\n         * the unbinding sets the callback function of the specified key combo\n         * to an empty function and deletes the corresponding key in the\n         * _directMap dict.\n         *\n         * TODO: actually remove this from the _callbacks dictionary instead\n         * of binding an empty function\n         *\n         * the keycombo+action has to be exactly the same as\n         * it was defined in the bind method\n         *\n         * @param {string|Array} keys\n         * @param {string} action\n         * @returns void\n         */\n        unbind: function(keys, action) {\n            return Mousetrap.bind(keys, function() {}, action);\n        },\n\n        /**\n         * triggers an event that has already been bound\n         *\n         * @param {string} keys\n         * @param {string=} action\n         * @returns void\n         */\n        trigger: function(keys, action) {\n            if (_directMap[keys + ':' + action]) {\n                _directMap[keys + ':' + action]({}, keys);\n            }\n            return this;\n        },\n\n        /**\n         * resets the library back to its initial state.  this is useful\n         * if you want to clear out the current keyboard shortcuts and bind\n         * new ones - for example if you switch to another page\n         *\n         * @returns void\n         */\n        reset: function() {\n            _callbacks = {};\n            _directMap = {};\n            return this;\n        },\n\n       /**\n        * should we stop this event before firing off callbacks\n        *\n        * @param {Event} e\n        * @param {Element} element\n        * @return {boolean}\n        */\n        stopCallback: function(e, element) {\n\n            // if the element has the class \"mousetrap\" then no need to stop\n            if ((' ' + element.className + ' ').indexOf(' mousetrap ') > -1) {\n                return false;\n            }\n\n            // stop for input, select, and textarea\n            return element.tagName == 'INPUT' || element.tagName == 'SELECT' || element.tagName == 'TEXTAREA' || element.isContentEditable;\n        },\n\n        /**\n         * exposes _handleKey publicly so it can be overwritten by extensions\n         */\n        handleKey: _handleKey\n    };\n\n    // expose mousetrap to the global object\n    window.Mousetrap = Mousetrap;\n\n    /*\n    <FLOWABLE PATCH START>\n     Can't let hotkeys define itself as a module since it will cause Flowable to not work in Alfresco Share:\n     In Share this file is being loaded from a <script> element (and not using dojos and define/require calls)\n     dojo therefor throws an error named \"multipleDefine\" ( http://dojotoolkit.org/reference-guide/1.10/loader/amd.html )\n     and stops the app.\n\n    // expose mousetrap as an AMD module\n    if (typeof define === 'function' && define.amd) {\n        define(Mousetrap);\n    }\n\n     <FLOWABLE PATCH STOP>\n    */\n}) (window, document);\n"
  },
  {
    "path": "flowable-ui-web/modeler/libs/angular-hotkeys_1.4.5/hotkeys.css",
    "content": "/*! \n * angular-hotkeys v1.4.5\n * https://chieffancypants.github.io/angular-hotkeys\n * Copyright (c) 2014 Wes Cruver\n * License: MIT\n */\n.cfp-hotkeys-container {\n  display: table !important;\n  position: fixed;\n  width: 100%;\n  height: 100%;\n  top: 0;\n  left: 0;\n  color: #333;\n  font-size: 1em;\n  background-color: rgba(255,255,255,0.9);\n}\n\n.cfp-hotkeys-container.fade {\n  z-index: -1024;\n  visibility: hidden;\n  opacity: 0;\n  -webkit-transition: opacity 0.15s linear;\n  -moz-transition: opacity 0.15s linear;\n  -o-transition: opacity 0.15s linear;\n  transition: opacity 0.15s linear;\n}\n\n.cfp-hotkeys-container.fade.in {\n  z-index: 10002;\n  visibility: visible;\n  opacity: 1;\n}\n\n.cfp-hotkeys-title {\n  font-weight: bold;\n  text-align: center;\n  font-size: 1.2em;\n}\n\n.cfp-hotkeys {\n  width: 100%;\n  height: 100%;\n  display: table-cell;\n  vertical-align: middle;\n}\n\n.cfp-hotkeys table {\n  margin: auto;\n  color: #333;\n}\n\n.cfp-content {\n  display: table-cell;\n  vertical-align: middle;\n}\n\n.cfp-hotkeys-keys {\n  padding: 5px;\n  text-align: right;\n}\n\n.cfp-hotkeys-key {\n  display: inline-block;\n  color: #fff;\n  background-color: #333;\n  border: 1px solid #333;\n  border-radius: 5px;\n  text-align: center;\n  margin-right: 5px;\n  box-shadow: inset 0 1px 0 #666, 0 1px 0 #bbb;\n  padding: 5px 9px;\n  font-size: 1em;\n}\n\n.cfp-hotkeys-text {\n  padding-left: 10px;\n  font-size: 1em;\n}\n\n.cfp-hotkeys-close {\n  position: fixed;\n  top: 20px;\n  right: 20px;\n  font-size: 2em;\n  font-weight: bold;\n  padding: 5px 10px;\n  border: 1px solid #ddd;\n  border-radius: 5px;\n  min-height: 45px;\n  min-width: 45px;\n  text-align: center;\n}\n\n.cfp-hotkeys-close:hover {\n  background-color: #fff;\n  cursor: pointer;\n}\n\n@media all and (max-width: 500px) {\n  .cfp-hotkeys {\n    font-size: 0.8em;\n  }\n}\n\n@media all and (min-width: 750px) {\n  .cfp-hotkeys {\n    font-size: 1.2em;\n  }\n}\n"
  },
  {
    "path": "flowable-ui-web/modeler/libs/angular-hotkeys_1.4.5/hotkeys.js",
    "content": "/*! \n * angular-hotkeys v1.4.5\n * https://chieffancypants.github.io/angular-hotkeys\n * Copyright (c) 2014 Wes Cruver\n * License: MIT\n */\n/*\n * angular-hotkeys\n *\n * Automatic keyboard shortcuts for your angular apps\n *\n * (c) 2014 Wes Cruver\n * License: MIT\n */\n\n(function() {\n\n  'use strict';\n\n  angular.module('cfp.hotkeys', []).provider('hotkeys', function() {\n\n    /**\n     * Configurable setting to disable the cheatsheet entirely\n     * @type {Boolean}\n     */\n    this.includeCheatSheet = true;\n\n    /**\n     * Configurable setting for the cheat sheet title\n     * @type {String}\n     */\n\n    this.templateTitle = 'Keyboard Shortcuts:';\n\n    /**\n     * Cheat sheet template in the event you want to totally customize it.\n     * @type {String}\n     */\n    this.template = '<div class=\"cfp-hotkeys-container fade\" ng-class=\"{in: helpVisible}\" style=\"display: none;\"><div class=\"cfp-hotkeys\">' +\n                      '<h4 class=\"cfp-hotkeys-title\">{{ title }}</h4>' +\n                      '<table><tbody>' +\n                        '<tr ng-repeat=\"hotkey in hotkeys | filter:{ description: \\'!$$undefined$$\\' }\">' +\n                          '<td class=\"cfp-hotkeys-keys\">' +\n                            '<span ng-repeat=\"key in hotkey.format() track by $index\" class=\"cfp-hotkeys-key\">{{ key }}</span>' +\n                          '</td>' +\n                          '<td class=\"cfp-hotkeys-text\">{{ hotkey.description }}</td>' +\n                        '</tr>' +\n                      '</tbody></table>' +\n                      '<div class=\"cfp-hotkeys-close\" ng-click=\"toggleCheatSheet()\">×</div>' +\n                    '</div></div>';\n\n    /**\n     * Configurable setting for the cheat sheet hotkey\n     * @type {String}\n     */\n    this.cheatSheetHotkey = '?';\n\n    /**\n     * Configurable setting for the cheat sheet description\n     * @type {String}\n     */\n    this.cheatSheetDescription = 'Show / hide this help menu';\n\n    this.$get = ['$rootElement', '$rootScope', '$compile', '$window', '$document', function ($rootElement, $rootScope, $compile, $window, $document) {\n\n      // monkeypatch Mousetrap's stopCallback() function\n      // this version doesn't return true when the element is an INPUT, SELECT, or TEXTAREA\n      // (instead we will perform this check per-key in the _add() method)\n      Mousetrap.stopCallback = function(event, element) {\n        // if the element has the class \"mousetrap\" then no need to stop\n        if ((' ' + element.className + ' ').indexOf(' mousetrap ') > -1) {\n          return false;\n        }\n\n        return (element.contentEditable && element.contentEditable == 'true');\n      };\n\n      /**\n       * Convert strings like cmd into symbols like ⌘\n       * @param  {String} combo Key combination, e.g. 'mod+f'\n       * @return {String}       The key combination with symbols\n       */\n      function symbolize (combo) {\n        var map = {\n          command   : '⌘',\n          shift     : '⇧',\n          left      : '←',\n          right     : '→',\n          up        : '↑',\n          down      : '↓',\n          'return'  : '↩',\n          backspace : '⌫'\n        };\n        combo = combo.split('+');\n\n        for (var i = 0; i < combo.length; i++) {\n          // try to resolve command / ctrl based on OS:\n          if (combo[i] === 'mod') {\n            if ($window.navigator && $window.navigator.platform.indexOf('Mac') >=0 ) {\n              combo[i] = 'command';\n            } else {\n              combo[i] = 'ctrl';\n            }\n          }\n\n          combo[i] = map[combo[i]] || combo[i];\n        }\n\n        return combo.join(' + ');\n      }\n\n      /**\n       * Hotkey object used internally for consistency\n       *\n       * @param {array}    combo       The keycombo. it's an array to support multiple combos\n       * @param {String}   description Description for the keycombo\n       * @param {Function} callback    function to execute when keycombo pressed\n       * @param {string}   action      the type of event to listen for (for mousetrap)\n       * @param {array}    allowIn     an array of tag names to allow this combo in ('INPUT', 'SELECT', and/or 'TEXTAREA')\n       * @param {Boolean}  persistent  Whether the hotkey persists navigation events\n       */\n      function Hotkey (combo, description, callback, action, allowIn, persistent) {\n        // TODO: Check that the values are sane because we could\n        // be trying to instantiate a new Hotkey with outside dev's\n        // supplied values\n\n        this.combo = combo instanceof Array ? combo : [combo];\n        this.description = description;\n        this.callback = callback;\n        this.action = action;\n        this.allowIn = allowIn;\n        this.persistent = persistent;\n      }\n\n      /**\n       * Helper method to format (symbolize) the key combo for display\n       *\n       * @return {[Array]} An array of the key combination sequence\n       *   for example: \"command+g c i\" becomes [\"⌘ + g\", \"c\", \"i\"]\n       *\n       * TODO: this gets called a lot.  We should cache the result\n       */\n      Hotkey.prototype.format = function() {\n\n        // Don't show all the possible key combos, just the first one.  Not sure\n        // of usecase here, so open a ticket if my assumptions are wrong\n        var combo = this.combo[0];\n\n        var sequence = combo.split(/[\\s]/);\n        for (var i = 0; i < sequence.length; i++) {\n          sequence[i] = symbolize(sequence[i]);\n        }\n\n        return sequence;\n      };\n\n      /**\n       * A new scope used internally for the cheatsheet\n       * @type {$rootScope.Scope}\n       */\n      var scope = $rootScope.$new();\n\n      /**\n       * Holds an array of Hotkey objects currently bound\n       * @type {Array}\n       */\n      scope.hotkeys = [];\n\n      /**\n       * Contains the state of the help's visibility\n       * @type {Boolean}\n       */\n      scope.helpVisible = false;\n\n      /**\n       * Holds the title string for the help menu\n       * @type {String}\n       */\n      scope.title = this.templateTitle;\n\n      /**\n       * Expose toggleCheatSheet to hotkeys scope so we can call it using\n       * ng-click from the template\n       * @type {function}\n       */\n      scope.toggleCheatSheet = toggleCheatSheet;\n\n\n      /**\n       * Holds references to the different scopes that have bound hotkeys\n       * attached.  This is useful to catch when the scopes are `$destroy`d and\n       * then automatically unbind the hotkey.\n       *\n       * @type {Array}\n       */\n      var boundScopes = [];\n\n\n      $rootScope.$on('$routeChangeSuccess', function (event, route) {\n        purgeHotkeys();\n\n        if (route && route.hotkeys) {\n          angular.forEach(route.hotkeys, function (hotkey) {\n            // a string was given, which implies this is a function that is to be\n            // $eval()'d within that controller's scope\n            // TODO: hotkey here is super confusing.  sometimes a function (that gets turned into an array), sometimes a string\n            var callback = hotkey[2];\n            if (typeof(callback) === 'string' || callback instanceof String) {\n              hotkey[2] = [callback, route];\n            }\n\n            // todo: perform check to make sure not already defined:\n            // this came from a route, so it's likely not meant to be persistent\n            hotkey[5] = false;\n            _add.apply(this, hotkey);\n          });\n        }\n      });\n\n\n      // Auto-create a help menu:\n      if (this.includeCheatSheet) {\n        var document = $document[0];\n        var element = $rootElement[0];\n        var helpMenu = angular.element(this.template);\n        _add(this.cheatSheetHotkey, this.cheatSheetDescription, toggleCheatSheet);\n\n        // If $rootElement is document or documentElement, then body must be used\n        if (element === document || element === document.documentElement) {\n          element = document.body;\n        }\n\n        angular.element(element).append($compile(helpMenu)(scope));\n      }\n\n\n      /**\n       * Purges all non-persistent hotkeys (such as those defined in routes)\n       *\n       * Without this, the same hotkey would get recreated everytime\n       * the route is accessed.\n       */\n      function purgeHotkeys() {\n        var i = scope.hotkeys.length;\n        while (i--) {\n          var hotkey = scope.hotkeys[i];\n          if (hotkey && !hotkey.persistent) {\n            _del(hotkey);\n          }\n        }\n      }\n\n      /**\n       * Toggles the help menu element's visiblity\n       */\n      var previousEsc = false;\n\n      function toggleCheatSheet() {\n        scope.helpVisible = !scope.helpVisible;\n\n        // Bind to esc to remove the cheat sheet.  Ideally, this would be done\n        // as a directive in the template, but that would create a nasty\n        // circular dependency issue that I don't feel like sorting out.\n        if (scope.helpVisible) {\n          previousEsc = _get('esc');\n          _del('esc');\n\n          // Here's an odd way to do this: we're going to use the original\n          // description of the hotkey on the cheat sheet so that it shows up.\n          // without it, no entry for esc will ever show up (#22)\n          _add('esc', previousEsc.description, toggleCheatSheet);\n        } else {\n          _del('esc');\n\n          // restore the previously bound ESC key\n          if (previousEsc !== false) {\n            _add(previousEsc);\n          }\n        }\n      }\n\n      /**\n       * Creates a new Hotkey and creates the Mousetrap binding\n       *\n       * @param {string}   combo       mousetrap key binding\n       * @param {string}   description description for the help menu\n       * @param {Function} callback    method to call when key is pressed\n       * @param {string}   action      the type of event to listen for (for mousetrap)\n       * @param {array}    allowIn     an array of tag names to allow this combo in ('INPUT', 'SELECT', and/or 'TEXTAREA')\n       * @param {boolean}  persistent  if true, the binding is preserved upon route changes\n       */\n      function _add (combo, description, callback, action, allowIn, persistent) {\n\n        // used to save original callback for \"allowIn\" wrapping:\n        var _callback;\n\n        // these elements are prevented by the default Mousetrap.stopCallback():\n        var preventIn = ['INPUT', 'SELECT', 'TEXTAREA'];\n\n        // Determine if object format was given:\n        var objType = Object.prototype.toString.call(combo);\n\n        if (objType === '[object Object]') {\n          description = combo.description;\n          callback    = combo.callback;\n          action      = combo.action;\n          persistent  = combo.persistent;\n          allowIn     = combo.allowIn;\n          combo       = combo.combo;\n        }\n\n        // description is optional:\n        if (description instanceof Function) {\n          action = callback;\n          callback = description;\n          description = '$$undefined$$';\n        } else if (angular.isUndefined(description)) {\n          description = '$$undefined$$';\n        }\n\n        // any items added through the public API are for controllers\n        // that persist through navigation, and thus undefined should mean\n        // true in this case.\n        if (persistent === undefined) {\n          persistent = true;\n        }\n\n        // if callback is defined, then wrap it in a function\n        // that checks if the event originated from a form element.\n        // the function blocks the callback from executing unless the element is specified\n        // in allowIn (emulates Mousetrap.stopCallback() on a per-key level)\n        if (typeof callback === 'function') {\n\n          // save the original callback\n          _callback = callback;\n\n          // make sure allowIn is an array\n          if (!(allowIn instanceof Array)) {\n            allowIn = [];\n          }\n\n          // remove anything from preventIn that's present in allowIn\n          var index;\n          for (var i=0; i < allowIn.length; i++) {\n            allowIn[i] = allowIn[i].toUpperCase();\n            index = preventIn.indexOf(allowIn[i]);\n            if (index !== -1) {\n              preventIn.splice(index, 1);\n            }\n          }\n\n          // create the new wrapper callback\n          callback = function(event) {\n            var shouldExecute = true;\n            var target = event.target || event.srcElement; // srcElement is IE only\n            var nodeName = target.nodeName.toUpperCase();\n\n            // check if the input has a mousetrap class, and skip checking preventIn if so\n            if ((' ' + target.className + ' ').indexOf(' mousetrap ') > -1) {\n              shouldExecute = true;\n            } else {\n              // don't execute callback if the event was fired from inside an element listed in preventIn\n              for (var i=0; i<preventIn.length; i++) {\n                if (preventIn[i] === nodeName) {\n                  shouldExecute = false;\n                  break;\n                }\n              }\n            }\n\n            if (shouldExecute) {\n              wrapApply(_callback.apply(this, arguments));\n            }\n          };\n        }\n\n        if (typeof(action) === 'string') {\n          Mousetrap.bind(combo, wrapApply(callback), action);\n        } else {\n          Mousetrap.bind(combo, wrapApply(callback));\n        }\n\n        var hotkey = new Hotkey(combo, description, callback, action, allowIn, persistent);\n        scope.hotkeys.push(hotkey);\n        return hotkey;\n      }\n\n      /**\n       * delete and unbind a Hotkey\n       *\n       * @param  {mixed} hotkey   Either the bound key or an instance of Hotkey\n       * @return {boolean}        true if successful\n       */\n      function _del (hotkey) {\n        var combo = (hotkey instanceof Hotkey) ? hotkey.combo : hotkey;\n\n        Mousetrap.unbind(combo);\n\n        if (angular.isArray(combo)) {\n          var retStatus = true;\n          var i = combo.length;\n          while (i--) {\n            retStatus = _del(combo[i]) && retStatus;\n          }\n          return retStatus;\n        } else {\n          var index = scope.hotkeys.indexOf(_get(combo));\n\n          if (index > -1) {\n            // if the combo has other combos bound, don't unbind the whole thing, just the one combo:\n            if (scope.hotkeys[index].combo.length > 1) {\n              scope.hotkeys[index].combo.splice(scope.hotkeys[index].combo.indexOf(combo), 1);\n            } else {\n              scope.hotkeys.splice(index, 1);\n            }\n            return true;\n          }\n        }\n\n        return false;\n\n      }\n\n      /**\n       * Get a Hotkey object by key binding\n       *\n       * @param  {[string]} combo  the key the Hotkey is bound to\n       * @return {Hotkey}          The Hotkey object\n       */\n      function _get (combo) {\n\n        var hotkey;\n\n        for (var i = 0; i < scope.hotkeys.length; i++) {\n          hotkey = scope.hotkeys[i];\n\n          if (hotkey.combo.indexOf(combo) > -1) {\n            return hotkey;\n          }\n        }\n\n        return false;\n      }\n\n      /**\n       * Binds the hotkey to a particular scope.  Useful if the scope is\n       * destroyed, we can automatically destroy the hotkey binding.\n       *\n       * @param  {Object} scope The scope to bind to\n       */\n      function bindTo (scope) {\n        // Only initialize once to allow multiple calls for same scope.\n        if (!(scope.$id in boundScopes)) {\n\n          // Add the scope to the list of bound scopes\n          boundScopes[scope.$id] = [];\n\n          scope.$on('$destroy', function () {\n            var i = boundScopes[scope.$id].length;\n            while (i--) {\n              _del(boundScopes[scope.$id][i]);\n              delete boundScopes[scope.$id][i];\n            }\n          });\n        }\n        // return an object with an add function so we can keep track of the\n        // hotkeys and their scope that we added via this chaining method\n        return {\n          add: function (args) {\n            var hotkey;\n\n            if (arguments.length > 1) {\n              hotkey = _add.apply(this, arguments);\n            } else {\n              hotkey = _add(args);\n            }\n\n            boundScopes[scope.$id].push(hotkey);\n            return this;\n          }\n        };\n      }\n\n      /**\n       * All callbacks sent to Mousetrap are wrapped using this function\n       * so that we can force a $scope.$apply()\n       *\n       * @param  {Function} callback [description]\n       * @return {[type]}            [description]\n       */\n      function wrapApply (callback) {\n        // return mousetrap a function to call\n        return function (event, combo) {\n\n          // if this is an array, it means we provided a route object\n          // because the scope wasn't available yet, so rewrap the callback\n          // now that the scope is available:\n          if (callback instanceof Array) {\n            var funcString = callback[0];\n            var route = callback[1];\n            callback = function (event) {\n              route.scope.$eval(funcString);\n            };\n          }\n\n          // this takes place outside angular, so we'll have to call\n          // $apply() to make sure angular's digest happens\n          $rootScope.$apply(function() {\n            // call the original hotkey callback with the keyboard event\n            callback(event, _get(combo));\n          });\n        };\n      }\n\n\n      var publicApi = {\n        add                   : _add,\n        del                   : _del,\n        get                   : _get,\n        bindTo                : bindTo,\n        template              : this.template,\n        toggleCheatSheet      : toggleCheatSheet,\n        includeCheatSheet     : this.includeCheatSheet,\n        cheatSheetHotkey      : this.cheatSheetHotkey,\n        cheatSheetDescription : this.cheatSheetDescription,\n        purgeHotkeys          : purgeHotkeys,\n        templateTitle         : this.templateTitle\n      };\n\n      return publicApi;\n\n    }];\n  })\n\n  .directive('hotkey', ['hotkeys', function (hotkeys) {\n    return {\n      restrict: 'A',\n      link: function (scope, el, attrs) {\n        var key, allowIn;\n\n        angular.forEach(scope.$eval(attrs.hotkey), function (func, hotkey) {\n          // split and trim the hotkeys string into array\n          allowIn = typeof attrs.hotkeyAllowIn === \"string\" ? attrs.hotkeyAllowIn.split(/[\\s,]+/) : [];\n\n          key = hotkey;\n\n          hotkeys.add({\n            combo: hotkey,\n            description: attrs.hotkeyDescription,\n            callback: func,\n            action: attrs.hotkeyAction,\n            allowIn: allowIn\n          });\n        });\n\n        // remove the hotkey if the directive is destroyed:\n        el.bind('$destroy', function() {\n          hotkeys.del(key);\n        });\n      }\n    };\n  }])\n\n  .run(['hotkeys', function(hotkeys) {\n    // force hotkeys to run by injecting it. Without this, hotkeys only runs\n    // when a controller or something else asks for it via DI.\n  }]);\n\n})();\n\n/*global define:false */\n/**\n * Copyright 2013 Craig Campbell\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 * Mousetrap is a simple keyboard shortcut library for Javascript with\n * no external dependencies\n *\n * @version 1.4.6\n * @url craig.is/killing/mice\n */\n(function(window, document, undefined) {\n\n    /**\n     * mapping of special keycodes to their corresponding keys\n     *\n     * everything in this dictionary cannot use keypress events\n     * so it has to be here to map to the correct keycodes for\n     * keyup/keydown events\n     *\n     * @type {Object}\n     */\n    var _MAP = {\n            8: 'backspace',\n            9: 'tab',\n            13: 'enter',\n            16: 'shift',\n            17: 'ctrl',\n            18: 'alt',\n            20: 'capslock',\n            27: 'esc',\n            32: 'space',\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: 'ins',\n            46: 'del',\n            91: 'meta',\n            93: 'meta',\n            224: 'meta'\n        },\n\n        /**\n         * mapping for special characters so they can support\n         *\n         * this dictionary is only used incase you want to bind a\n         * keyup or keydown event to one of these keys\n         *\n         * @type {Object}\n         */\n        _KEYCODE_MAP = {\n            106: '*',\n            107: '+',\n            109: '-',\n            110: '.',\n            111 : '/',\n            186: ';',\n            187: '=',\n            188: ',',\n            189: '-',\n            190: '.',\n            191: '/',\n            192: '`',\n            219: '[',\n            220: '\\\\',\n            221: ']',\n            222: '\\''\n        },\n\n        /**\n         * this is a mapping of keys that require shift on a US keypad\n         * back to the non shift equivelents\n         *\n         * this is so you can use keyup events with these keys\n         *\n         * note that this will only work reliably on US keyboards\n         *\n         * @type {Object}\n         */\n        _SHIFT_MAP = {\n            '~': '`',\n            '!': '1',\n            '@': '2',\n            '#': '3',\n            '$': '4',\n            '%': '5',\n            '^': '6',\n            '&': '7',\n            '*': '8',\n            '(': '9',\n            ')': '0',\n            '_': '-',\n            '+': '=',\n            ':': ';',\n            '\\\"': '\\'',\n            '<': ',',\n            '>': '.',\n            '?': '/',\n            '|': '\\\\'\n        },\n\n        /**\n         * this is a list of special strings you can use to map\n         * to modifier keys when you specify your keyboard shortcuts\n         *\n         * @type {Object}\n         */\n        _SPECIAL_ALIASES = {\n            'option': 'alt',\n            'command': 'meta',\n            'return': 'enter',\n            'escape': 'esc',\n            'mod': /Mac|iPod|iPhone|iPad/.test(navigator.platform) ? 'meta' : 'ctrl'\n        },\n\n        /**\n         * variable to store the flipped version of _MAP from above\n         * needed to check if we should use keypress or not when no action\n         * is specified\n         *\n         * @type {Object|undefined}\n         */\n        _REVERSE_MAP,\n\n        /**\n         * a list of all the callbacks setup via Mousetrap.bind()\n         *\n         * @type {Object}\n         */\n        _callbacks = {},\n\n        /**\n         * direct map of string combinations to callbacks used for trigger()\n         *\n         * @type {Object}\n         */\n        _directMap = {},\n\n        /**\n         * keeps track of what level each sequence is at since multiple\n         * sequences can start out with the same sequence\n         *\n         * @type {Object}\n         */\n        _sequenceLevels = {},\n\n        /**\n         * variable to store the setTimeout call\n         *\n         * @type {null|number}\n         */\n        _resetTimer,\n\n        /**\n         * temporary state where we will ignore the next keyup\n         *\n         * @type {boolean|string}\n         */\n        _ignoreNextKeyup = false,\n\n        /**\n         * temporary state where we will ignore the next keypress\n         *\n         * @type {boolean}\n         */\n        _ignoreNextKeypress = false,\n\n        /**\n         * are we currently inside of a sequence?\n         * type of action (\"keyup\" or \"keydown\" or \"keypress\") or false\n         *\n         * @type {boolean|string}\n         */\n        _nextExpectedAction = false;\n\n    /**\n     * loop through the f keys, f1 to f19 and add them to the map\n     * programatically\n     */\n    for (var i = 1; i < 20; ++i) {\n        _MAP[111 + i] = 'f' + i;\n    }\n\n    /**\n     * loop through to map numbers on the numeric keypad\n     */\n    for (i = 0; i <= 9; ++i) {\n        _MAP[i + 96] = i;\n    }\n\n    /**\n     * cross browser add event method\n     *\n     * @param {Element|HTMLDocument} object\n     * @param {string} type\n     * @param {Function} callback\n     * @returns void\n     */\n    function _addEvent(object, type, callback) {\n        if (object.addEventListener) {\n            object.addEventListener(type, callback, false);\n            return;\n        }\n\n        object.attachEvent('on' + type, callback);\n    }\n\n    /**\n     * takes the event and returns the key character\n     *\n     * @param {Event} e\n     * @return {string}\n     */\n    function _characterFromEvent(e) {\n\n        // for keypress events we should return the character as is\n        if (e.type == 'keypress') {\n            var character = String.fromCharCode(e.which);\n\n            // if the shift key is not pressed then it is safe to assume\n            // that we want the character to be lowercase.  this means if\n            // you accidentally have caps lock on then your key bindings\n            // will continue to work\n            //\n            // the only side effect that might not be desired is if you\n            // bind something like 'A' cause you want to trigger an\n            // event when capital A is pressed caps lock will no longer\n            // trigger the event.  shift+a will though.\n            if (!e.shiftKey) {\n                character = character.toLowerCase();\n            }\n\n            return character;\n        }\n\n        // for non keypress events the special maps are needed\n        if (_MAP[e.which]) {\n            return _MAP[e.which];\n        }\n\n        if (_KEYCODE_MAP[e.which]) {\n            return _KEYCODE_MAP[e.which];\n        }\n\n        // if it is not in the special map\n\n        // with keydown and keyup events the character seems to always\n        // come in as an uppercase character whether you are pressing shift\n        // or not.  we should make sure it is always lowercase for comparisons\n        return String.fromCharCode(e.which).toLowerCase();\n    }\n\n    /**\n     * checks if two arrays are equal\n     *\n     * @param {Array} modifiers1\n     * @param {Array} modifiers2\n     * @returns {boolean}\n     */\n    function _modifiersMatch(modifiers1, modifiers2) {\n        return modifiers1.sort().join(',') === modifiers2.sort().join(',');\n    }\n\n    /**\n     * resets all sequence counters except for the ones passed in\n     *\n     * @param {Object} doNotReset\n     * @returns void\n     */\n    function _resetSequences(doNotReset) {\n        doNotReset = doNotReset || {};\n\n        var activeSequences = false,\n            key;\n\n        for (key in _sequenceLevels) {\n            if (doNotReset[key]) {\n                activeSequences = true;\n                continue;\n            }\n            _sequenceLevels[key] = 0;\n        }\n\n        if (!activeSequences) {\n            _nextExpectedAction = false;\n        }\n    }\n\n    /**\n     * finds all callbacks that match based on the keycode, modifiers,\n     * and action\n     *\n     * @param {string} character\n     * @param {Array} modifiers\n     * @param {Event|Object} e\n     * @param {string=} sequenceName - name of the sequence we are looking for\n     * @param {string=} combination\n     * @param {number=} level\n     * @returns {Array}\n     */\n    function _getMatches(character, modifiers, e, sequenceName, combination, level) {\n        var i,\n            callback,\n            matches = [],\n            action = e.type;\n\n        // if there are no events related to this keycode\n        if (!_callbacks[character]) {\n            return [];\n        }\n\n        // if a modifier key is coming up on its own we should allow it\n        if (action == 'keyup' && _isModifier(character)) {\n            modifiers = [character];\n        }\n\n        // loop through all callbacks for the key that was pressed\n        // and see if any of them match\n        for (i = 0; i < _callbacks[character].length; ++i) {\n            callback = _callbacks[character][i];\n\n            // if a sequence name is not specified, but this is a sequence at\n            // the wrong level then move onto the next match\n            if (!sequenceName && callback.seq && _sequenceLevels[callback.seq] != callback.level) {\n                continue;\n            }\n\n            // if the action we are looking for doesn't match the action we got\n            // then we should keep going\n            if (action != callback.action) {\n                continue;\n            }\n\n            // if this is a keypress event and the meta key and control key\n            // are not pressed that means that we need to only look at the\n            // character, otherwise check the modifiers as well\n            //\n            // chrome will not fire a keypress if meta or control is down\n            // safari will fire a keypress if meta or meta+shift is down\n            // firefox will fire a keypress if meta or control is down\n            if ((action == 'keypress' && !e.metaKey && !e.ctrlKey) || _modifiersMatch(modifiers, callback.modifiers)) {\n\n                // when you bind a combination or sequence a second time it\n                // should overwrite the first one.  if a sequenceName or\n                // combination is specified in this call it does just that\n                //\n                // @todo make deleting its own method?\n                var deleteCombo = !sequenceName && callback.combo == combination;\n                var deleteSequence = sequenceName && callback.seq == sequenceName && callback.level == level;\n                if (deleteCombo || deleteSequence) {\n                    _callbacks[character].splice(i, 1);\n                }\n\n                matches.push(callback);\n            }\n        }\n\n        return matches;\n    }\n\n    /**\n     * takes a key event and figures out what the modifiers are\n     *\n     * @param {Event} e\n     * @returns {Array}\n     */\n    function _eventModifiers(e) {\n        var modifiers = [];\n\n        if (e.shiftKey) {\n            modifiers.push('shift');\n        }\n\n        if (e.altKey) {\n            modifiers.push('alt');\n        }\n\n        if (e.ctrlKey) {\n            modifiers.push('ctrl');\n        }\n\n        if (e.metaKey) {\n            modifiers.push('meta');\n        }\n\n        return modifiers;\n    }\n\n    /**\n     * prevents default for this event\n     *\n     * @param {Event} e\n     * @returns void\n     */\n    function _preventDefault(e) {\n        if (e.preventDefault) {\n            e.preventDefault();\n            return;\n        }\n\n        e.returnValue = false;\n    }\n\n    /**\n     * stops propogation for this event\n     *\n     * @param {Event} e\n     * @returns void\n     */\n    function _stopPropagation(e) {\n        if (e.stopPropagation) {\n            e.stopPropagation();\n            return;\n        }\n\n        e.cancelBubble = true;\n    }\n\n    /**\n     * actually calls the callback function\n     *\n     * if your callback function returns false this will use the jquery\n     * convention - prevent default and stop propogation on the event\n     *\n     * @param {Function} callback\n     * @param {Event} e\n     * @returns void\n     */\n    function _fireCallback(callback, e, combo, sequence) {\n\n        // if this event should not happen stop here\n        if (Mousetrap.stopCallback(e, e.target || e.srcElement, combo, sequence)) {\n            return;\n        }\n\n        if (callback(e, combo) === false) {\n            _preventDefault(e);\n            _stopPropagation(e);\n        }\n    }\n\n    /**\n     * handles a character key event\n     *\n     * @param {string} character\n     * @param {Array} modifiers\n     * @param {Event} e\n     * @returns void\n     */\n    function _handleKey(character, modifiers, e) {\n        var callbacks = _getMatches(character, modifiers, e),\n            i,\n            doNotReset = {},\n            maxLevel = 0,\n            processedSequenceCallback = false;\n\n        // Calculate the maxLevel for sequences so we can only execute the longest callback sequence\n        for (i = 0; i < callbacks.length; ++i) {\n            if (callbacks[i].seq) {\n                maxLevel = Math.max(maxLevel, callbacks[i].level);\n            }\n        }\n\n        // loop through matching callbacks for this key event\n        for (i = 0; i < callbacks.length; ++i) {\n\n            // fire for all sequence callbacks\n            // this is because if for example you have multiple sequences\n            // bound such as \"g i\" and \"g t\" they both need to fire the\n            // callback for matching g cause otherwise you can only ever\n            // match the first one\n            if (callbacks[i].seq) {\n\n                // only fire callbacks for the maxLevel to prevent\n                // subsequences from also firing\n                //\n                // for example 'a option b' should not cause 'option b' to fire\n                // even though 'option b' is part of the other sequence\n                //\n                // any sequences that do not match here will be discarded\n                // below by the _resetSequences call\n                if (callbacks[i].level != maxLevel) {\n                    continue;\n                }\n\n                processedSequenceCallback = true;\n\n                // keep a list of which sequences were matches for later\n                doNotReset[callbacks[i].seq] = 1;\n                _fireCallback(callbacks[i].callback, e, callbacks[i].combo, callbacks[i].seq);\n                continue;\n            }\n\n            // if there were no sequence matches but we are still here\n            // that means this is a regular match so we should fire that\n            if (!processedSequenceCallback) {\n                _fireCallback(callbacks[i].callback, e, callbacks[i].combo);\n            }\n        }\n\n        // if the key you pressed matches the type of sequence without\n        // being a modifier (ie \"keyup\" or \"keypress\") then we should\n        // reset all sequences that were not matched by this event\n        //\n        // this is so, for example, if you have the sequence \"h a t\" and you\n        // type \"h e a r t\" it does not match.  in this case the \"e\" will\n        // cause the sequence to reset\n        //\n        // modifier keys are ignored because you can have a sequence\n        // that contains modifiers such as \"enter ctrl+space\" and in most\n        // cases the modifier key will be pressed before the next key\n        //\n        // also if you have a sequence such as \"ctrl+b a\" then pressing the\n        // \"b\" key will trigger a \"keypress\" and a \"keydown\"\n        //\n        // the \"keydown\" is expected when there is a modifier, but the\n        // \"keypress\" ends up matching the _nextExpectedAction since it occurs\n        // after and that causes the sequence to reset\n        //\n        // we ignore keypresses in a sequence that directly follow a keydown\n        // for the same character\n        var ignoreThisKeypress = e.type == 'keypress' && _ignoreNextKeypress;\n        if (e.type == _nextExpectedAction && !_isModifier(character) && !ignoreThisKeypress) {\n            _resetSequences(doNotReset);\n        }\n\n        _ignoreNextKeypress = processedSequenceCallback && e.type == 'keydown';\n    }\n\n    /**\n     * handles a keydown event\n     *\n     * @param {Event} e\n     * @returns void\n     */\n    function _handleKeyEvent(e) {\n\n        // normalize e.which for key events\n        // @see http://stackoverflow.com/questions/4285627/javascript-keycode-vs-charcode-utter-confusion\n        if (typeof e.which !== 'number') {\n            e.which = e.keyCode;\n        }\n\n        var character = _characterFromEvent(e);\n\n        // no character found then stop\n        if (!character) {\n            return;\n        }\n\n        // need to use === for the character check because the character can be 0\n        if (e.type == 'keyup' && _ignoreNextKeyup === character) {\n            _ignoreNextKeyup = false;\n            return;\n        }\n\n        Mousetrap.handleKey(character, _eventModifiers(e), e);\n    }\n\n    /**\n     * determines if the keycode specified is a modifier key or not\n     *\n     * @param {string} key\n     * @returns {boolean}\n     */\n    function _isModifier(key) {\n        return key == 'shift' || key == 'ctrl' || key == 'alt' || key == 'meta';\n    }\n\n    /**\n     * called to set a 1 second timeout on the specified sequence\n     *\n     * this is so after each key press in the sequence you have 1 second\n     * to press the next key before you have to start over\n     *\n     * @returns void\n     */\n    function _resetSequenceTimer() {\n        clearTimeout(_resetTimer);\n        _resetTimer = setTimeout(_resetSequences, 1000);\n    }\n\n    /**\n     * reverses the map lookup so that we can look for specific keys\n     * to see what can and can't use keypress\n     *\n     * @return {Object}\n     */\n    function _getReverseMap() {\n        if (!_REVERSE_MAP) {\n            _REVERSE_MAP = {};\n            for (var key in _MAP) {\n\n                // pull out the numeric keypad from here cause keypress should\n                // be able to detect the keys from the character\n                if (key > 95 && key < 112) {\n                    continue;\n                }\n\n                if (_MAP.hasOwnProperty(key)) {\n                    _REVERSE_MAP[_MAP[key]] = key;\n                }\n            }\n        }\n        return _REVERSE_MAP;\n    }\n\n    /**\n     * picks the best action based on the key combination\n     *\n     * @param {string} key - character for key\n     * @param {Array} modifiers\n     * @param {string=} action passed in\n     */\n    function _pickBestAction(key, modifiers, action) {\n\n        // if no action was picked in we should try to pick the one\n        // that we think would work best for this key\n        if (!action) {\n            action = _getReverseMap()[key] ? 'keydown' : 'keypress';\n        }\n\n        // modifier keys don't work as expected with keypress,\n        // switch to keydown\n        if (action == 'keypress' && modifiers.length) {\n            action = 'keydown';\n        }\n\n        return action;\n    }\n\n    /**\n     * binds a key sequence to an event\n     *\n     * @param {string} combo - combo specified in bind call\n     * @param {Array} keys\n     * @param {Function} callback\n     * @param {string=} action\n     * @returns void\n     */\n    function _bindSequence(combo, keys, callback, action) {\n\n        // start off by adding a sequence level record for this combination\n        // and setting the level to 0\n        _sequenceLevels[combo] = 0;\n\n        /**\n         * callback to increase the sequence level for this sequence and reset\n         * all other sequences that were active\n         *\n         * @param {string} nextAction\n         * @returns {Function}\n         */\n        function _increaseSequence(nextAction) {\n            return function() {\n                _nextExpectedAction = nextAction;\n                ++_sequenceLevels[combo];\n                _resetSequenceTimer();\n            };\n        }\n\n        /**\n         * wraps the specified callback inside of another function in order\n         * to reset all sequence counters as soon as this sequence is done\n         *\n         * @param {Event} e\n         * @returns void\n         */\n        function _callbackAndReset(e) {\n            _fireCallback(callback, e, combo);\n\n            // we should ignore the next key up if the action is key down\n            // or keypress.  this is so if you finish a sequence and\n            // release the key the final key will not trigger a keyup\n            if (action !== 'keyup') {\n                _ignoreNextKeyup = _characterFromEvent(e);\n            }\n\n            // weird race condition if a sequence ends with the key\n            // another sequence begins with\n            setTimeout(_resetSequences, 10);\n        }\n\n        // loop through keys one at a time and bind the appropriate callback\n        // function.  for any key leading up to the final one it should\n        // increase the sequence. after the final, it should reset all sequences\n        //\n        // if an action is specified in the original bind call then that will\n        // be used throughout.  otherwise we will pass the action that the\n        // next key in the sequence should match.  this allows a sequence\n        // to mix and match keypress and keydown events depending on which\n        // ones are better suited to the key provided\n        for (var i = 0; i < keys.length; ++i) {\n            var isFinal = i + 1 === keys.length;\n            var wrappedCallback = isFinal ? _callbackAndReset : _increaseSequence(action || _getKeyInfo(keys[i + 1]).action);\n            _bindSingle(keys[i], wrappedCallback, action, combo, i);\n        }\n    }\n\n    /**\n     * Converts from a string key combination to an array\n     *\n     * @param  {string} combination like \"command+shift+l\"\n     * @return {Array}\n     */\n    function _keysFromString(combination) {\n        if (combination === '+') {\n            return ['+'];\n        }\n\n        return combination.split('+');\n    }\n\n    /**\n     * Gets info for a specific key combination\n     *\n     * @param  {string} combination key combination (\"command+s\" or \"a\" or \"*\")\n     * @param  {string=} action\n     * @returns {Object}\n     */\n    function _getKeyInfo(combination, action) {\n        var keys,\n            key,\n            i,\n            modifiers = [];\n\n        // take the keys from this pattern and figure out what the actual\n        // pattern is all about\n        keys = _keysFromString(combination);\n\n        for (i = 0; i < keys.length; ++i) {\n            key = keys[i];\n\n            // normalize key names\n            if (_SPECIAL_ALIASES[key]) {\n                key = _SPECIAL_ALIASES[key];\n            }\n\n            // if this is not a keypress event then we should\n            // be smart about using shift keys\n            // this will only work for US keyboards however\n            if (action && action != 'keypress' && _SHIFT_MAP[key]) {\n                key = _SHIFT_MAP[key];\n                modifiers.push('shift');\n            }\n\n            // if this key is a modifier then add it to the list of modifiers\n            if (_isModifier(key)) {\n                modifiers.push(key);\n            }\n        }\n\n        // depending on what the key combination is\n        // we will try to pick the best event for it\n        action = _pickBestAction(key, modifiers, action);\n\n        return {\n            key: key,\n            modifiers: modifiers,\n            action: action\n        };\n    }\n\n    /**\n     * binds a single keyboard combination\n     *\n     * @param {string} combination\n     * @param {Function} callback\n     * @param {string=} action\n     * @param {string=} sequenceName - name of sequence if part of sequence\n     * @param {number=} level - what part of the sequence the command is\n     * @returns void\n     */\n    function _bindSingle(combination, callback, action, sequenceName, level) {\n\n        // store a direct mapped reference for use with Mousetrap.trigger\n        _directMap[combination + ':' + action] = callback;\n\n        // make sure multiple spaces in a row become a single space\n        combination = combination.replace(/\\s+/g, ' ');\n\n        var sequence = combination.split(' '),\n            info;\n\n        // if this pattern is a sequence of keys then run through this method\n        // to reprocess each pattern one key at a time\n        if (sequence.length > 1) {\n            _bindSequence(combination, sequence, callback, action);\n            return;\n        }\n\n        info = _getKeyInfo(combination, action);\n\n        // make sure to initialize array if this is the first time\n        // a callback is added for this key\n        _callbacks[info.key] = _callbacks[info.key] || [];\n\n        // remove an existing match if there is one\n        _getMatches(info.key, info.modifiers, {type: info.action}, sequenceName, combination, level);\n\n        // add this call back to the array\n        // if it is a sequence put it at the beginning\n        // if not put it at the end\n        //\n        // this is important because the way these are processed expects\n        // the sequence ones to come first\n        _callbacks[info.key][sequenceName ? 'unshift' : 'push']({\n            callback: callback,\n            modifiers: info.modifiers,\n            action: info.action,\n            seq: sequenceName,\n            level: level,\n            combo: combination\n        });\n    }\n\n    /**\n     * binds multiple combinations to the same callback\n     *\n     * @param {Array} combinations\n     * @param {Function} callback\n     * @param {string|undefined} action\n     * @returns void\n     */\n    function _bindMultiple(combinations, callback, action) {\n        for (var i = 0; i < combinations.length; ++i) {\n            _bindSingle(combinations[i], callback, action);\n        }\n    }\n\n    // start!\n    _addEvent(document, 'keypress', _handleKeyEvent);\n    _addEvent(document, 'keydown', _handleKeyEvent);\n    _addEvent(document, 'keyup', _handleKeyEvent);\n\n    var Mousetrap = {\n\n        /**\n         * binds an event to mousetrap\n         *\n         * can be a single key, a combination of keys separated with +,\n         * an array of keys, or a sequence of keys separated by spaces\n         *\n         * be sure to list the modifier keys first to make sure that the\n         * correct key ends up getting bound (the last key in the pattern)\n         *\n         * @param {string|Array} keys\n         * @param {Function} callback\n         * @param {string=} action - 'keypress', 'keydown', or 'keyup'\n         * @returns void\n         */\n        bind: function(keys, callback, action) {\n            keys = keys instanceof Array ? keys : [keys];\n            _bindMultiple(keys, callback, action);\n            return this;\n        },\n\n        /**\n         * unbinds an event to mousetrap\n         *\n         * the unbinding sets the callback function of the specified key combo\n         * to an empty function and deletes the corresponding key in the\n         * _directMap dict.\n         *\n         * TODO: actually remove this from the _callbacks dictionary instead\n         * of binding an empty function\n         *\n         * the keycombo+action has to be exactly the same as\n         * it was defined in the bind method\n         *\n         * @param {string|Array} keys\n         * @param {string} action\n         * @returns void\n         */\n        unbind: function(keys, action) {\n            return Mousetrap.bind(keys, function() {}, action);\n        },\n\n        /**\n         * triggers an event that has already been bound\n         *\n         * @param {string} keys\n         * @param {string=} action\n         * @returns void\n         */\n        trigger: function(keys, action) {\n            if (_directMap[keys + ':' + action]) {\n                _directMap[keys + ':' + action]({}, keys);\n            }\n            return this;\n        },\n\n        /**\n         * resets the library back to its initial state.  this is useful\n         * if you want to clear out the current keyboard shortcuts and bind\n         * new ones - for example if you switch to another page\n         *\n         * @returns void\n         */\n        reset: function() {\n            _callbacks = {};\n            _directMap = {};\n            return this;\n        },\n\n       /**\n        * should we stop this event before firing off callbacks\n        *\n        * @param {Event} e\n        * @param {Element} element\n        * @return {boolean}\n        */\n        stopCallback: function(e, element) {\n\n            // if the element has the class \"mousetrap\" then no need to stop\n            if ((' ' + element.className + ' ').indexOf(' mousetrap ') > -1) {\n                return false;\n            }\n\n            // stop for input, select, and textarea\n            return element.tagName == 'INPUT' || element.tagName == 'SELECT' || element.tagName == 'TEXTAREA' || element.isContentEditable;\n        },\n\n        /**\n         * exposes _handleKey publicly so it can be overwritten by extensions\n         */\n        handleKey: _handleKey\n    };\n\n    // expose mousetrap to the global object\n    window.Mousetrap = Mousetrap;\n\n    // expose mousetrap as an AMD module\n    if (typeof define === 'function' && define.amd) {\n        define(Mousetrap);\n    }\n}) (window, document);\n"
  },
  {
    "path": "flowable-ui-web/modeler/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": "flowable-ui-web/modeler/libs/angular-resource_1.3.13/angular-resource.js",
    "content": "/**\n * @license AngularJS v1.3.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 module\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 *\n * <div doc-module-components=\"ngResource\"></div>\n *\n * See {@link ngResource.$resource `$resource`} for usage.\n */\n\n/**\n * @ngdoc service\n * @name $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 * By default, trailing slashes will be stripped from the calculated URLs,\n * which can pose problems with server backends that do not expect that\n * behavior.  This can be disabled by configuring the `$resourceProvider` like\n * this:\n *\n * ```js\n     app.config(['$resourceProvider', function($resourceProvider) {\n       // Don't strip trailing slashes from calculated URLs\n       $resourceProvider.defaults.stripTrailingSlashes = false;\n     }]);\n * ```\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 for that parameter will be extracted\n *   from the corresponding property on the `data` object (provided when calling an action method).  For\n *   example, if the `defaultParam` object is `{someParam: '@someProp'}` then the value of `someParam`\n *   will be `data.someProp`.\n *\n * @param {Object.<Object>=} actions Hash with declaration of custom actions that should extend\n *   the default set of resource actions. The declaration should be created in the format of {@link\n *   ng.$http#usage $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} – Case insensitive HTTP method (e.g. `GET`, `POST`, `PUT`,\n *     `DELETE`, `JSONP`, etc).\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 *     By default, transformRequest will contain one function that checks if the request data is\n *     an object and serializes to using `angular.toJson`. To prevent this behavior, set\n *     `transformRequest` to an empty array: `transformRequest: []`\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 *     By default, transformResponse will contain one function that checks if the response looks like\n *     a JSON string and deserializes it using `angular.fromJson`. To prevent this behavior, set\n *     `transformResponse` to an empty array: `transformResponse: []`\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\n *     [requests with credentials](https://developer.mozilla.org/en/http_access_control#section_5)\n *     for more information.\n *   - **`responseType`** - `{string}` - see\n *     [requestType](https://developer.mozilla.org/en-US/docs/DOM/XMLHttpRequest#responseType).\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 * @param {Object} options Hash with custom settings that should extend the\n *   default `$resourceProvider` behavior.  The only supported option is\n *\n *   Where:\n *\n *   - **`stripTrailingSlashes`** – {boolean} – If true then the trailing\n *   slashes from any calculated URL will be stripped. (Defaults to true.)\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 *   ```js\n *   { 'get':    {method:'GET'},\n *     'save':   {method:'POST'},\n *     'query':  {method:'GET', isArray:true},\n *     'remove': {method:'DELETE'},\n *     'delete': {method:'DELETE'} };\n *   ```\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 *   ```js\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 *   ```\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 *     If an interceptor object was provided, the promise will instead be resolved with the value\n *     returned by the interceptor.\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 * ```js\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 * ```\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   ```js\n     var User = $resource('/user/:userId', {userId:'@id'});\n     User.get({userId:123}, function(user) {\n       user.abc = true;\n       user.$save();\n     });\n   ```\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   ```js\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   ```\n *\n * You can also access the raw `$http` promise via the `$promise` property on the object returned\n *\n   ```\n     var User = $resource('/user/:userId', {userId:'@id'});\n     User.get({userId:123})\n         .$promise.then(function(user) {\n           $scope.user = user;\n         });\n   ```\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 * ```js\n *    var app = angular.module('app', ['ngResource', 'ngRoute']);\n *\n *    // Some APIs expect a PUT request in the format URL/object/ID\n *    // Here we are creating an 'update' method\n *    app.factory('Notes', ['$resource', function($resource) {\n *    return $resource('/notes/:id', null,\n *        {\n *            'update': { method:'PUT' }\n *        });\n *    }]);\n *\n *    // In our controller we get the ID from the URL using ngRoute and $routeParams\n *    // We pass in $routeParams and our Notes factory along with $scope\n *    app.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 *    }]);\n * ```\n */\nangular.module('ngResource', ['ng']).\n  provider('$resource', function() {\n    var provider = this;\n\n    this.defaults = {\n      // Strip slashes by default\n      stripTrailingSlashes: true,\n\n      // Default actions configuration\n      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    };\n\n    this.$get = ['$http', '$q', function($http, $q) {\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\n       * (pchar) allowed in path 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 = extend({}, provider.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 (unless this behavior is specifically disabled)\n          if (self.defaults.stripTrailingSlashes) {\n            url = url.replace(/\\/+$/, '') || '/';\n          }\n\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, options) {\n        var route = new Route(url, options);\n\n        actions = extend({}, provider.defaults.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        Resource.prototype.toJSON = function() {\n          var data = extend({}, this);\n          delete data.$promise;\n          delete data.$resolved;\n          return data;\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',\n                      'Error in resource configuration for action `{0}`. Expected response to ' +\n                      'contain an {1} but got an {2}', name, action.isArray ? 'array' : 'object',\n                    angular.isArray(data) ? 'array' : 'object');\n                }\n                // jshint +W018\n                if (action.isArray) {\n                  value.length = 0;\n                  forEach(data, function(item) {\n                    if (typeof item === \"object\") {\n                      value.push(new Resource(item));\n                    } else {\n                      // Valid JSON values may be string literals, and these should not be converted\n                      // into objects. These items will not have access to the Resource prototype\n                      // methods, but unfortunately there\n                      value.push(item);\n                    }\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\n})(window, window.angular);\n"
  },
  {
    "path": "flowable-ui-web/modeler/libs/angular-route_1.3.13/angular-route.js",
    "content": "/**\n * @license AngularJS v1.3.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 module\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 *\n * <div doc-module-components=\"ngRoute\"></div>\n */\n /* global -ngRouteModule */\nvar ngRouteModule = angular.module('ngRoute', ['ng']).\n                        provider('$route', $RouteProvider),\n    $routeMinErr = angular.$$minErr('ngRoute');\n\n/**\n * @ngdoc provider\n * @name $routeProvider\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(Object.create(parent), extra);\n  }\n\n  var routes = {};\n\n  /**\n   * @ngdoc method\n   * @name $routeProvider#when\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/slashes/edit` and extract:\n   *\n   *    * `color: brown`\n   *    * `largecode: code/with/slashes`.\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 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    //copy original route object to preserve params inherited from proto chain\n    var routeCopy = angular.copy(route);\n    if (angular.isUndefined(routeCopy.reloadOnSearch)) {\n      routeCopy.reloadOnSearch = true;\n    }\n    if (angular.isUndefined(routeCopy.caseInsensitiveMatch)) {\n      routeCopy.caseInsensitiveMatch = this.caseInsensitiveMatch;\n    }\n    routes[path] = angular.extend(\n      routeCopy,\n      path && pathRegExp(path, routeCopy)\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, routeCopy)\n      );\n    }\n\n    return this;\n  };\n\n  /**\n   * @ngdoc property\n   * @name $routeProvider#caseInsensitiveMatch\n   * @description\n   *\n   * A boolean property indicating if routes defined\n   * using this provider should be matched using a case insensitive\n   * algorithm. Defaults to `false`.\n   */\n  this.caseInsensitiveMatch = false;\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 $routeProvider#otherwise\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|string} params Mapping information to be assigned to `$route.current`.\n   * If called with a string, the value maps to `redirectTo`.\n   * @returns {Object} self\n   */\n  this.otherwise = function(params) {\n    if (typeof params === 'string') {\n      params = {redirectTo: params};\n    }\n    this.when(null, params);\n    return this;\n  };\n\n\n  this.$get = ['$rootScope',\n               '$location',\n               '$routeParams',\n               '$q',\n               '$injector',\n               '$templateRequest',\n               '$sce',\n      function($rootScope, $location, $routeParams, $q, $injector, $templateRequest, $sce) {\n\n    /**\n     * @ngdoc service\n     * @name $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 {Object} routes Object with all route configuration Objects as its properties.\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     * <example name=\"$route-service\" module=\"ngRouteExample\"\n     *          deps=\"angular-route.js\" fixBase=\"true\">\n     *   <file name=\"index.html\">\n     *     <div ng-controller=\"MainController\">\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     *\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('ngRouteExample', ['ngRoute'])\n     *\n     *      .controller('MainController', function($scope, $route, $routeParams, $location) {\n     *          $scope.$route = $route;\n     *          $scope.$location = $location;\n     *          $scope.$routeParams = $routeParams;\n     *      })\n     *\n     *      .controller('BookController', function($scope, $routeParams) {\n     *          $scope.name = \"BookController\";\n     *          $scope.params = $routeParams;\n     *      })\n     *\n     *      .controller('ChapterController', function($scope, $routeParams) {\n     *          $scope.name = \"ChapterController\";\n     *          $scope.params = $routeParams;\n     *      })\n     *\n     *     .config(function($routeProvider, $locationProvider) {\n     *       $routeProvider\n     *        .when('/Book/:bookId', {\n     *         templateUrl: 'book.html',\n     *         controller: 'BookController',\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     *       .when('/Book/:bookId/ch/:chapterId', {\n     *         templateUrl: 'chapter.html',\n     *         controller: 'ChapterController'\n     *       });\n     *\n     *       // configure html5 to get links working on jsfiddle\n     *       $locationProvider.html5Mode(true);\n     *     });\n     *\n     *   </file>\n     *\n     *   <file name=\"protractor.js\" type=\"protractor\">\n     *     it('should load and compile correct template', function() {\n     *       element(by.linkText('Moby: Ch1')).click();\n     *       var content = element(by.css('[ng-view]')).getText();\n     *       expect(content).toMatch(/controller\\: ChapterController/);\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('[ng-view]')).getText();\n     *       expect(content).toMatch(/controller\\: BookController/);\n     *       expect(content).toMatch(/Book Id\\: Scarlet/);\n     *     });\n     *   </file>\n     * </example>\n     */\n\n    /**\n     * @ngdoc event\n     * @name $route#$routeChangeStart\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     * The route change (and the `$location` change that triggered it) can be prevented\n     * by calling `preventDefault` method of the event. See {@link ng.$rootScope.Scope#$on}\n     * for more details about event object.\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 $route#$routeChangeSuccess\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 $route#$routeChangeError\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 $route#$routeUpdate\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        preparedRoute,\n        preparedRouteIsUpdateOnly,\n        $route = {\n          routes: routes,\n\n          /**\n           * @ngdoc method\n           * @name $route#reload\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 and reinstantiates the controller.\n           */\n          reload: function() {\n            forceReload = true;\n            $rootScope.$evalAsync(function() {\n              // Don't support cancellation of a reload for now...\n              prepareRoute();\n              commitRoute();\n            });\n          },\n\n          /**\n           * @ngdoc method\n           * @name $route#updateParams\n           *\n           * @description\n           * Causes `$route` service to update the current URL, replacing\n           * current route parameters with those specified in `newParams`.\n           * Provided property names that match the route's path segment\n           * definitions will be interpolated into the location's path, while\n           * remaining properties will be treated as query params.\n           *\n           * @param {!Object<string, string>} newParams mapping of URL parameter names to values\n           */\n          updateParams: function(newParams) {\n            if (this.current && this.current.$$route) {\n              newParams = angular.extend({}, this.current.params, newParams);\n              $location.path(interpolate(this.current.$$route.originalPath, newParams));\n              // interpolate modifies newParams, only query params are left\n              $location.search(newParams);\n            } else {\n              throw $routeMinErr('norout', 'Tried updating route when with no current route');\n            }\n          }\n        };\n\n    $rootScope.$on('$locationChangeStart', prepareRoute);\n    $rootScope.$on('$locationChangeSuccess', commitRoute);\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 = m[i];\n\n        if (key && val) {\n          params[key.name] = val;\n        }\n      }\n      return params;\n    }\n\n    function prepareRoute($locationEvent) {\n      var lastRoute = $route.current;\n\n      preparedRoute = parseRoute();\n      preparedRouteIsUpdateOnly = preparedRoute && lastRoute && preparedRoute.$$route === lastRoute.$$route\n          && angular.equals(preparedRoute.pathParams, lastRoute.pathParams)\n          && !preparedRoute.reloadOnSearch && !forceReload;\n\n      if (!preparedRouteIsUpdateOnly && (lastRoute || preparedRoute)) {\n        if ($rootScope.$broadcast('$routeChangeStart', preparedRoute, lastRoute).defaultPrevented) {\n          if ($locationEvent) {\n            $locationEvent.preventDefault();\n          }\n        }\n      }\n    }\n\n    function commitRoute() {\n      var lastRoute = $route.current;\n      var nextRoute = preparedRoute;\n\n      if (preparedRouteIsUpdateOnly) {\n        lastRoute.params = nextRoute.params;\n        angular.copy(lastRoute.params, $routeParams);\n        $rootScope.$broadcast('$routeUpdate', lastRoute);\n      } else if (nextRoute || lastRoute) {\n        forceReload = false;\n        $route.current = nextRoute;\n        if (nextRoute) {\n          if (nextRoute.redirectTo) {\n            if (angular.isString(nextRoute.redirectTo)) {\n              $location.path(interpolate(nextRoute.redirectTo, nextRoute.params)).search(nextRoute.params)\n                       .replace();\n            } else {\n              $location.url(nextRoute.redirectTo(nextRoute.pathParams, $location.path(), $location.search()))\n                       .replace();\n            }\n          }\n        }\n\n        $q.when(nextRoute).\n          then(function() {\n            if (nextRoute) {\n              var locals = angular.extend({}, nextRoute.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, null, null, key);\n              });\n\n              if (angular.isDefined(template = nextRoute.template)) {\n                if (angular.isFunction(template)) {\n                  template = template(nextRoute.params);\n                }\n              } else if (angular.isDefined(templateUrl = nextRoute.templateUrl)) {\n                if (angular.isFunction(templateUrl)) {\n                  templateUrl = templateUrl(nextRoute.params);\n                }\n                templateUrl = $sce.getTrustedResourceUrl(templateUrl);\n                if (angular.isDefined(templateUrl)) {\n                  nextRoute.loadedTemplateUrl = templateUrl;\n                  template = $templateRequest(templateUrl);\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 (nextRoute == $route.current) {\n              if (nextRoute) {\n                nextRoute.locals = locals;\n                angular.copy(nextRoute.params, $routeParams);\n              }\n              $rootScope.$broadcast('$routeChangeSuccess', nextRoute, lastRoute);\n            }\n          }, function(error) {\n            if (nextRoute == $route.current) {\n              $rootScope.$broadcast('$routeChangeError', nextRoute, lastRoute, error);\n            }\n          });\n      }\n    }\n\n\n    /**\n     * @returns {Object} 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 {string} 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 service\n * @name $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#search `search()`} and {@link ng.$location#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 * ```js\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 * ```\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 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 name=\"ngView-directive\" module=\"ngViewExample\"\n             deps=\"angular-route.js;angular-animate.js\"\n             animations=\"true\" fixBase=\"true\">\n      <file name=\"index.html\">\n        <div ng-controller=\"MainCtrl 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>$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          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          .config(['$routeProvider', '$locationProvider',\n            function($routeProvider, $locationProvider) {\n              $routeProvider\n                .when('/Book/:bookId', {\n                  templateUrl: 'book.html',\n                  controller: 'BookCtrl',\n                  controllerAs: 'book'\n                })\n                .when('/Book/:bookId/ch/:chapterId', {\n                  templateUrl: 'chapter.html',\n                  controller: 'ChapterCtrl',\n                  controllerAs: 'chapter'\n                });\n\n              $locationProvider.html5Mode(true);\n          }])\n          .controller('MainCtrl', ['$route', '$routeParams', '$location',\n            function($route, $routeParams, $location) {\n              this.$route = $route;\n              this.$location = $location;\n              this.$routeParams = $routeParams;\n          }])\n          .controller('BookCtrl', ['$routeParams', function($routeParams) {\n            this.name = \"BookCtrl\";\n            this.params = $routeParams;\n          }])\n          .controller('ChapterCtrl', ['$routeParams', function($routeParams) {\n            this.name = \"ChapterCtrl\";\n            this.params = $routeParams;\n          }]);\n\n      </file>\n\n      <file name=\"protractor.js\" type=\"protractor\">\n        it('should load and compile correct template', function() {\n          element(by.linkText('Moby: Ch1')).click();\n          var content = element(by.css('[ng-view]')).getText();\n          expect(content).toMatch(/controller\\: ChapterCtrl/);\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('[ng-view]')).getText();\n          expect(content).toMatch(/controller\\: BookCtrl/);\n          expect(content).toMatch(/Book Id\\: Scarlet/);\n        });\n      </file>\n    </example>\n */\n\n\n/**\n * @ngdoc event\n * @name ngView#$viewContentLoaded\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            previousLeaveAnimation,\n            autoScrollExp = attr.autoscroll,\n            onloadExp = attr.onload || '';\n\n        scope.$on('$routeChangeSuccess', update);\n        update();\n\n        function cleanupLastView() {\n          if (previousLeaveAnimation) {\n            $animate.cancel(previousLeaveAnimation);\n            previousLeaveAnimation = null;\n          }\n\n          if (currentScope) {\n            currentScope.$destroy();\n            currentScope = null;\n          }\n          if (currentElement) {\n            previousLeaveAnimation = $animate.leave(currentElement);\n            previousLeaveAnimation.then(function() {\n              previousLeaveAnimation = null;\n            });\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).then(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": "flowable-ui-web/modeler/libs/angular-sanitize_1.3.13/angular-sanitize.js",
    "content": "/**\n * @license AngularJS v1.3.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 module\n * @name ngSanitize\n * @description\n *\n * # ngSanitize\n *\n * The `ngSanitize` module provides functionality to sanitize HTML.\n *\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 $sanitize\n * @kind 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. The input may also contain SVG markup.\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   <example module=\"sanitizeExample\" deps=\"angular-sanitize.js\">\n   <file name=\"index.html\">\n     <script>\n         angular.module('sanitizeExample', ['ngSanitize'])\n           .controller('ExampleController', ['$scope', '$sce', function($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=\"ExampleController\">\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   </file>\n   <file name=\"protractor.js\" type=\"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   </file>\n   </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       /^<((?:[a-zA-Z])[\\w:-]*)((?:\\s+[\\w:-]+(?:\\s*=\\s*(?:(?:\"[^\"]*\")|(?:'[^']*')|[^>\\s]+))?)*)\\s*(\\/?)\\s*(>?)/,\n  END_TAG_REGEXP = /^<\\/\\s*([\\w:-]+)[^>]*>/,\n  ATTR_REGEXP = /([\\w:-]+)(?:\\s*=\\s*(?:(?:\"((?:[^\"])*)\")|(?:'((?:[^'])*)')|([^>\\s]+)))?/g,\n  BEGIN_TAG_REGEXP = /^</,\n  BEGING_END_TAGE_REGEXP = /^<\\//,\n  COMMENT_REGEXP = /<!--(.*?)-->/g,\n  DOCTYPE_REGEXP = /<!DOCTYPE([^>]*?)>/i,\n  CDATA_REGEXP = /<!\\[CDATA\\[(.*?)]]>/g,\n  SURROGATE_PAIR_REGEXP = /[\\uD800-\\uDBFF][\\uDC00-\\uDFFF]/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// SVG Elements\n// https://wiki.whatwg.org/wiki/Sanitization_rules#svg_Elements\nvar svgElements = makeMap(\"animate,animateColor,animateMotion,animateTransform,circle,defs,\" +\n        \"desc,ellipse,font-face,font-face-name,font-face-src,g,glyph,hkern,image,linearGradient,\" +\n        \"line,marker,metadata,missing-glyph,mpath,path,polygon,polyline,radialGradient,rect,set,\" +\n        \"stop,svg,switch,text,title,tspan,use\");\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                                   svgElements);\n\n//Attributes that have href and hence need to be sanitized\nvar uriAttrs = makeMap(\"background,cite,href,longdesc,src,usemap,xlink:href\");\n\nvar htmlAttrs = makeMap('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\n// SVG attributes (without \"id\" and \"name\" attributes)\n// https://wiki.whatwg.org/wiki/Sanitization_rules#svg_Attributes\nvar svgAttrs = makeMap('accent-height,accumulate,additive,alphabetic,arabic-form,ascent,' +\n    'attributeName,attributeType,baseProfile,bbox,begin,by,calcMode,cap-height,class,color,' +\n    'color-rendering,content,cx,cy,d,dx,dy,descent,display,dur,end,fill,fill-rule,font-family,' +\n    'font-size,font-stretch,font-style,font-variant,font-weight,from,fx,fy,g1,g2,glyph-name,' +\n    'gradientUnits,hanging,height,horiz-adv-x,horiz-origin-x,ideographic,k,keyPoints,' +\n    'keySplines,keyTimes,lang,marker-end,marker-mid,marker-start,markerHeight,markerUnits,' +\n    'markerWidth,mathematical,max,min,offset,opacity,orient,origin,overline-position,' +\n    'overline-thickness,panose-1,path,pathLength,points,preserveAspectRatio,r,refX,refY,' +\n    'repeatCount,repeatDur,requiredExtensions,requiredFeatures,restart,rotate,rx,ry,slope,stemh,' +\n    'stemv,stop-color,stop-opacity,strikethrough-position,strikethrough-thickness,stroke,' +\n    'stroke-dasharray,stroke-dashoffset,stroke-linecap,stroke-linejoin,stroke-miterlimit,' +\n    'stroke-opacity,stroke-width,systemLanguage,target,text-anchor,to,transform,type,u1,u2,' +\n    'underline-position,underline-thickness,unicode,unicode-range,units-per-em,values,version,' +\n    'viewBox,visibility,width,widths,x,x-height,x1,x2,xlink:actuate,xlink:arcrole,xlink:role,' +\n    'xlink:show,xlink:title,xlink:type,xml:base,xml:lang,xml:space,xmlns,xmlns:xlink,y,y1,y2,' +\n    'zoomAndPan');\n\nvar validAttrs = angular.extend({},\n                                uriAttrs,\n                                svgAttrs,\n                                htmlAttrs);\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  if (typeof html !== 'string') {\n    if (html === null || typeof html === 'undefined') {\n      html = '';\n    } else {\n      html = '' + html;\n    }\n  }\n  var index, chars, match, stack = [], last = html, text;\n  stack.last = function() { return stack[stack.length - 1]; };\n\n  while (html) {\n    text = '';\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          // We only have a valid start-tag if there is a '>'.\n          if (match[4]) {\n            html = html.substring(match[0].length);\n            match[0].replace(START_TAG_REGEXP, parseStartTag);\n          }\n          chars = false;\n        } else {\n          // no ending tag found --- this piece should be encoded as an entity.\n          text += '<';\n          html = html.substring(1);\n        }\n      }\n\n      if (chars) {\n        index = html.indexOf(\"<\");\n\n        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      // IE versions 9 and 10 do not understand the regex '[^]', so using a workaround with [\\W\\w].\n      html = html.replace(new RegExp(\"([\\\\W\\\\w]*)<\\\\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 {string} escaped text\n */\nfunction encodeEntities(value) {\n  return value.\n    replace(/&/g, '&amp;').\n    replace(SURROGATE_PAIR_REGEXP, function(value) {\n      var hi = value.charCodeAt(0);\n      var low = value.charCodeAt(1);\n      return '&#' + (((hi - 0xD800) * 0x400) + (low - 0xDC00) + 0x10000) + ';';\n    }).\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 linky\n * @kind 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   <example module=\"linkyExample\" deps=\"angular-sanitize.js\">\n     <file name=\"index.html\">\n       <script>\n         angular.module('linkyExample', ['ngSanitize'])\n           .controller('ExampleController', ['$scope', function($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=\"ExampleController\">\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     </file>\n     <file name=\"protractor.js\" type=\"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     </file>\n   </example>\n */\nangular.module('ngSanitize').filter('linky', ['$sanitize', function($sanitize) {\n  var LINKY_URL_REGEXP =\n        /((ftp|https?):\\/\\/|(www\\.)|(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/www/mailto then assume mailto\n      if (!match[2] && !match[4]) {\n        url = (match[3] ? 'http://' : 'mailto:') + url;\n      }\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                  target,\n                  '\" ');\n      }\n      html.push('href=\"',\n                url.replace(/\"/g, '&quot;'),\n                '\">');\n      addText(text);\n      html.push('</a>');\n    }\n  };\n}]);\n\n\n})(window, window.angular);\n"
  },
  {
    "path": "flowable-ui-web/modeler/libs/angular-spectrum-colorpicker_1.0.13/spectrum.css",
    "content": "/***\nSpectrum Colorpicker v1.3.4\nhttps://github.com/bgrins/spectrum\nAuthor: Brian Grinstead\nLicense: MIT\n***/\n\n.sp-container {\n    position:absolute;\n    top:0;\n    left:0;\n    display:inline-block;\n    *display: inline;\n    *zoom: 1;\n    /* https://github.com/bgrins/spectrum/issues/40 */\n    z-index: 9999994;\n    overflow: hidden;\n}\n.sp-container.sp-flat {\n    position: relative;\n}\n\n/* Fix for * { box-sizing: border-box; } */\n.sp-container,\n.sp-container * {\n    -webkit-box-sizing: content-box;\n       -moz-box-sizing: content-box;\n            box-sizing: content-box;\n}\n\n/* http://ansciath.tumblr.com/post/7347495869/css-aspect-ratio */\n.sp-top {\n  position:relative;\n  width: 100%;\n  display:inline-block;\n}\n.sp-top-inner {\n   position:absolute;\n   top:0;\n   left:0;\n   bottom:0;\n   right:0;\n}\n.sp-color {\n    position: absolute;\n    top:0;\n    left:0;\n    bottom:0;\n    right:20%;\n}\n.sp-hue {\n    position: absolute;\n    top:0;\n    right:0;\n    bottom:0;\n    left:84%;\n    height: 100%;\n}\n\n.sp-clear-enabled .sp-hue {\n    top:33px;\n    height: 77.5%;\n}\n\n.sp-fill {\n    padding-top: 80%;\n}\n.sp-sat, .sp-val {\n    position: absolute;\n    top:0;\n    left:0;\n    right:0;\n    bottom:0;\n}\n\n.sp-alpha-enabled .sp-top {\n    margin-bottom: 18px;\n}\n.sp-alpha-enabled .sp-alpha {\n    display: block;\n}\n.sp-alpha-handle {\n    position:absolute;\n    top:-4px;\n    bottom: -4px;\n    width: 6px;\n    left: 50%;\n    cursor: pointer;\n    border: 1px solid black;\n    background: white;\n    opacity: .8;\n}\n.sp-alpha {\n    display: none;\n    position: absolute;\n    bottom: -14px;\n    right: 0;\n    left: 0;\n    height: 8px;\n}\n.sp-alpha-inner {\n    border: solid 1px #333;\n}\n\n.sp-clear {\n    display: none;\n}\n\n.sp-clear.sp-clear-display {\n    background-position: center;\n}\n\n.sp-clear-enabled .sp-clear {\n    display: block;\n    position:absolute;\n    top:0px;\n    right:0;\n    bottom:0;\n    left:84%;\n    height: 28px;\n}\n\n/* Don't allow text selection */\n.sp-container, .sp-replacer, .sp-preview, .sp-dragger, .sp-slider, .sp-alpha, .sp-clear, .sp-alpha-handle, .sp-container.sp-dragging .sp-input, .sp-container button  {\n    -webkit-user-select:none;\n    -moz-user-select: -moz-none;\n    -o-user-select:none;\n    user-select: none;\n}\n\n.sp-container.sp-input-disabled .sp-input-container {\n    display: none;\n}\n.sp-container.sp-buttons-disabled .sp-button-container {\n    display: none;\n}\n.sp-palette-only .sp-picker-container {\n    display: none;\n}\n.sp-palette-disabled .sp-palette-container {\n    display: none;\n}\n\n.sp-initial-disabled .sp-initial {\n    display: none;\n}\n\n\n/* Gradients for hue, saturation and value instead of images.  Not pretty... but it works */\n.sp-sat {\n    background-image: -webkit-gradient(linear,  0 0, 100% 0, from(#FFF), to(rgba(204, 154, 129, 0)));\n    background-image: -webkit-linear-gradient(left, #FFF, rgba(204, 154, 129, 0));\n    background-image: -moz-linear-gradient(left, #fff, rgba(204, 154, 129, 0));\n    background-image: -o-linear-gradient(left, #fff, rgba(204, 154, 129, 0));\n    background-image: -ms-linear-gradient(left, #fff, rgba(204, 154, 129, 0));\n    background-image: linear-gradient(to right, #fff, rgba(204, 154, 129, 0));\n    -ms-filter: \"progid:DXImageTransform.Microsoft.gradient(GradientType = 1, startColorstr=#FFFFFFFF, endColorstr=#00CC9A81)\";\n    filter : progid:DXImageTransform.Microsoft.gradient(GradientType = 1, startColorstr='#FFFFFFFF', endColorstr='#00CC9A81');\n}\n.sp-val {\n    background-image: -webkit-gradient(linear, 0 100%, 0 0, from(#000000), to(rgba(204, 154, 129, 0)));\n    background-image: -webkit-linear-gradient(bottom, #000000, rgba(204, 154, 129, 0));\n    background-image: -moz-linear-gradient(bottom, #000, rgba(204, 154, 129, 0));\n    background-image: -o-linear-gradient(bottom, #000, rgba(204, 154, 129, 0));\n    background-image: -ms-linear-gradient(bottom, #000, rgba(204, 154, 129, 0));\n    background-image: linear-gradient(to top, #000, rgba(204, 154, 129, 0));\n    -ms-filter: \"progid:DXImageTransform.Microsoft.gradient(startColorstr=#00CC9A81, endColorstr=#FF000000)\";\n    filter : progid:DXImageTransform.Microsoft.gradient(startColorstr='#00CC9A81', endColorstr='#FF000000');\n}\n\n.sp-hue {\n    background: -moz-linear-gradient(top, #ff0000 0%, #ffff00 17%, #00ff00 33%, #00ffff 50%, #0000ff 67%, #ff00ff 83%, #ff0000 100%);\n    background: -ms-linear-gradient(top, #ff0000 0%, #ffff00 17%, #00ff00 33%, #00ffff 50%, #0000ff 67%, #ff00ff 83%, #ff0000 100%);\n    background: -o-linear-gradient(top, #ff0000 0%, #ffff00 17%, #00ff00 33%, #00ffff 50%, #0000ff 67%, #ff00ff 83%, #ff0000 100%);\n    background: -webkit-gradient(linear, left top, left bottom, from(#ff0000), color-stop(0.17, #ffff00), color-stop(0.33, #00ff00), color-stop(0.5, #00ffff), color-stop(0.67, #0000ff), color-stop(0.83, #ff00ff), to(#ff0000));\n    background: -webkit-linear-gradient(top, #ff0000 0%, #ffff00 17%, #00ff00 33%, #00ffff 50%, #0000ff 67%, #ff00ff 83%, #ff0000 100%);\n}\n\n/* IE filters do not support multiple color stops.\n   Generate 6 divs, line them up, and do two color gradients for each.\n   Yes, really.\n */\n.sp-1 {\n    height:17%;\n    filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0000', endColorstr='#ffff00');\n}\n.sp-2 {\n    height:16%;\n    filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffff00', endColorstr='#00ff00');\n}\n.sp-3 {\n    height:17%;\n    filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#00ff00', endColorstr='#00ffff');\n}\n.sp-4 {\n    height:17%;\n    filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#00ffff', endColorstr='#0000ff');\n}\n.sp-5 {\n    height:16%;\n    filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#0000ff', endColorstr='#ff00ff');\n}\n.sp-6 {\n    height:17%;\n    filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff00ff', endColorstr='#ff0000');\n}\n\n.sp-hidden {\n    display: none !important;\n}\n\n/* Clearfix hack */\n.sp-cf:before, .sp-cf:after { content: \"\"; display: table; }\n.sp-cf:after { clear: both; }\n.sp-cf { *zoom: 1; }\n\n/* Mobile devices, make hue slider bigger so it is easier to slide */\n@media (max-device-width: 480px) {\n    .sp-color { right: 40%; }\n    .sp-hue { left: 63%; }\n    .sp-fill { padding-top: 60%; }\n}\n.sp-dragger {\n   border-radius: 5px;\n   height: 5px;\n   width: 5px;\n   border: 1px solid #fff;\n   background: #000;\n   cursor: pointer;\n   position:absolute;\n   top:0;\n   left: 0;\n}\n.sp-slider {\n    position: absolute;\n    top:0;\n    cursor:pointer;\n    height: 3px;\n    left: -1px;\n    right: -1px;\n    border: 1px solid #000;\n    background: white;\n    opacity: .8;\n}\n\n/*\nTheme authors:\nHere are the basic themeable display options (colors, fonts, global widths).\nSee http://bgrins.github.io/spectrum/themes/ for instructions.\n*/\n\n.sp-container {\n    border-radius: 0;\n    background-color: #ECECEC;\n    border: solid 1px #f0c49B;\n    padding: 0;\n}\n.sp-container, .sp-container button, .sp-container input, .sp-color, .sp-hue, .sp-clear\n{\n    font: normal 12px \"Lucida Grande\", \"Lucida Sans Unicode\", \"Lucida Sans\", Geneva, Verdana, sans-serif;\n    -webkit-box-sizing: border-box;\n    -moz-box-sizing: border-box;\n    -ms-box-sizing: border-box;\n    box-sizing: border-box;\n}\n.sp-top\n{\n    margin-bottom: 3px;\n}\n.sp-color, .sp-hue, .sp-clear\n{\n    border: solid 1px #666;\n}\n\n/* Input */\n.sp-input-container {\n    float:right;\n    width: 100px;\n    margin-bottom: 4px;\n}\n.sp-initial-disabled  .sp-input-container {\n    width: 100%;\n}\n.sp-input {\n   font-size: 12px !important;\n   border: 1px inset;\n   padding: 4px 5px;\n   margin: 0;\n   width: 100%;\n   background:transparent;\n   border-radius: 3px;\n   color: #222;\n}\n.sp-input:focus  {\n    border: 1px solid orange;\n}\n.sp-input.sp-validation-error\n{\n    border: 1px solid red;\n    background: #fdd;\n}\n.sp-picker-container , .sp-palette-container\n{\n    float:left;\n    position: relative;\n    padding: 10px;\n    padding-bottom: 300px;\n    margin-bottom: -290px;\n}\n.sp-picker-container\n{\n    width: 172px;\n    border-left: solid 1px #fff;\n}\n\n/* Palettes */\n.sp-palette-container\n{\n    border-right: solid 1px #ccc;\n}\n\n.sp-palette .sp-thumb-el {\n    display: block;\n    position:relative;\n    float:left;\n    width: 24px;\n    height: 15px;\n    margin: 3px;\n    cursor: pointer;\n    border:solid 2px transparent;\n}\n.sp-palette .sp-thumb-el:hover, .sp-palette .sp-thumb-el.sp-thumb-active {\n    border-color: orange;\n}\n.sp-thumb-el\n{\n    position:relative;\n}\n\n/* Initial */\n.sp-initial\n{\n    float: left;\n    border: solid 1px #333;\n}\n.sp-initial span {\n    width: 30px;\n    height: 25px;\n    border:none;\n    display:block;\n    float:left;\n    margin:0;\n}\n\n.sp-initial .sp-clear-display {\n    background-position: center;\n}\n\n/* Buttons */\n.sp-button-container {\n    float: right;\n}\n\n/* Replacer (the little preview div that shows up instead of the <input>) */\n.sp-replacer {\n    margin:0;\n    overflow:hidden;\n    cursor:pointer;\n    padding: 4px;\n    display:inline-block;\n    *zoom: 1;\n    *display: inline;\n    border: solid 1px #91765d;\n    background: #eee;\n    color: #333;\n    vertical-align: middle;\n}\n.sp-replacer:hover, .sp-replacer.sp-active {\n    border-color: #F0C49B;\n    color: #111;\n}\n.sp-replacer.sp-disabled {\n    cursor:default;\n    border-color: silver;\n    color: silver;\n}\n.sp-dd {\n    padding: 2px 0;\n    height: 16px;\n    line-height: 16px;\n    float:left;\n    font-size:10px;\n}\n.sp-preview\n{\n    position:relative;\n    width:25px;\n    height: 20px;\n    border: solid 1px #222;\n    margin-right: 5px;\n    float:left;\n    z-index: 0;\n}\n\n.sp-palette\n{\n    *width: 220px;\n    max-width: 220px;\n}\n.sp-palette .sp-thumb-el\n{\n    width:16px;\n    height: 16px;\n    margin:2px 1px;\n    border: solid 1px #d0d0d0;\n}\n\n.sp-container\n{\n    padding-bottom:0;\n}\n\n\n/* Buttons: http://hellohappy.org/css3-buttons/ */\n.sp-container button {\n  background-color: #eeeeee;\n  background-image: -webkit-linear-gradient(top, #eeeeee, #cccccc);\n  background-image: -moz-linear-gradient(top, #eeeeee, #cccccc);\n  background-image: -ms-linear-gradient(top, #eeeeee, #cccccc);\n  background-image: -o-linear-gradient(top, #eeeeee, #cccccc);\n  background-image: linear-gradient(to bottom, #eeeeee, #cccccc);\n  border: 1px solid #ccc;\n  border-bottom: 1px solid #bbb;\n  border-radius: 3px;\n  color: #333;\n  font-size: 14px;\n  line-height: 1;\n  padding: 5px 4px;\n  text-align: center;\n  text-shadow: 0 1px 0 #eee;\n  vertical-align: middle;\n}\n.sp-container button:hover {\n    background-color: #dddddd;\n    background-image: -webkit-linear-gradient(top, #dddddd, #bbbbbb);\n    background-image: -moz-linear-gradient(top, #dddddd, #bbbbbb);\n    background-image: -ms-linear-gradient(top, #dddddd, #bbbbbb);\n    background-image: -o-linear-gradient(top, #dddddd, #bbbbbb);\n    background-image: linear-gradient(to bottom, #dddddd, #bbbbbb);\n    border: 1px solid #bbb;\n    border-bottom: 1px solid #999;\n    cursor: pointer;\n    text-shadow: 0 1px 0 #ddd;\n}\n.sp-container button:active {\n    border: 1px solid #aaa;\n    border-bottom: 1px solid #888;\n    -webkit-box-shadow: inset 0 0 5px 2px #aaaaaa, 0 1px 0 0 #eeeeee;\n    -moz-box-shadow: inset 0 0 5px 2px #aaaaaa, 0 1px 0 0 #eeeeee;\n    -ms-box-shadow: inset 0 0 5px 2px #aaaaaa, 0 1px 0 0 #eeeeee;\n    -o-box-shadow: inset 0 0 5px 2px #aaaaaa, 0 1px 0 0 #eeeeee;\n    box-shadow: inset 0 0 5px 2px #aaaaaa, 0 1px 0 0 #eeeeee;\n}\n.sp-cancel\n{\n    font-size: 11px;\n    color: #d93f3f !important;\n    margin:0;\n    padding:2px;\n    margin-right: 5px;\n    vertical-align: middle;\n    text-decoration:none;\n\n}\n.sp-cancel:hover\n{\n    color: #d93f3f !important;\n    text-decoration: underline;\n}\n\n\n.sp-palette span:hover, .sp-palette span.sp-thumb-active\n{\n    border-color: #000;\n}\n\n.sp-preview, .sp-alpha, .sp-thumb-el\n{\n    position:relative;\n    background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAIAAADZF8uwAAAAGUlEQVQYV2M4gwH+YwCGIasIUwhT25BVBADtzYNYrHvv4gAAAABJRU5ErkJggg==);\n}\n.sp-preview-inner, .sp-alpha-inner, .sp-thumb-inner\n{\n    display:block;\n    position:absolute;\n    top:0;left:0;bottom:0;right:0;\n}\n\n.sp-palette .sp-thumb-inner\n{\n    background-position: 50% 50%;\n    background-repeat: no-repeat;\n}\n\n.sp-palette .sp-thumb-light.sp-thumb-active .sp-thumb-inner\n{\n    background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAYAAABWzo5XAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAIVJREFUeNpiYBhsgJFMffxAXABlN5JruT4Q3wfi/0DsT64h8UD8HmpIPCWG/KemIfOJCUB+Aoacx6EGBZyHBqI+WsDCwuQ9mhxeg2A210Ntfo8klk9sOMijaURm7yc1UP2RNCMbKE9ODK1HM6iegYLkfx8pligC9lCD7KmRof0ZhjQACDAAceovrtpVBRkAAAAASUVORK5CYII=);\n}\n\n.sp-palette .sp-thumb-dark.sp-thumb-active .sp-thumb-inner\n{\n    background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAYAAABWzo5XAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAadEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My41LjEwMPRyoQAAAMdJREFUOE+tkgsNwzAMRMugEAahEAahEAZhEAqlEAZhEAohEAYh81X2dIm8fKpEspLGvudPOsUYpxE2BIJCroJmEW9qJ+MKaBFhEMNabSy9oIcIPwrB+afvAUFoK4H0tMaQ3XtlrggDhOVVMuT4E5MMG0FBbCEYzjYT7OxLEvIHQLY2zWwQ3D+9luyOQTfKDiFD3iUIfPk8VqrKjgAiSfGFPecrg6HN6m/iBcwiDAo7WiBeawa+Kwh7tZoSCGLMqwlSAzVDhoK+6vH4G0P5wdkAAAAASUVORK5CYII=);\n}\n\n.sp-clear-display {\n    background-repeat:no-repeat;\n    background-position: center;\n    background-image: url(data:image/gif;base64,R0lGODlhFAAUAPcAAAAAAJmZmZ2dnZ6enqKioqOjo6SkpKWlpaampqenp6ioqKmpqaqqqqurq/Hx8fLy8vT09PX19ff39/j4+Pn5+fr6+vv7+wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAP8ALAAAAAAUABQAAAihAP9FoPCvoMGDBy08+EdhQAIJCCMybCDAAYUEARBAlFiQQoMABQhKUJBxY0SPICEYHBnggEmDKAuoPMjS5cGYMxHW3IiT478JJA8M/CjTZ0GgLRekNGpwAsYABHIypcAgQMsITDtWJYBR6NSqMico9cqR6tKfY7GeBCuVwlipDNmefAtTrkSzB1RaIAoXodsABiZAEFB06gIBWC1mLVgBa0AAOw==);\n}\n"
  },
  {
    "path": "flowable-ui-web/modeler/libs/angular-spectrum-colorpicker_1.0.13/spectrum.js",
    "content": "// Spectrum Colorpicker v1.3.4\n// https://github.com/bgrins/spectrum\n// Author: Brian Grinstead\n// License: MIT\n\n(function (window, $, undefined) {\n    var defaultOpts = {\n\n        // Callbacks\n        beforeShow: noop,\n        move: noop,\n        change: noop,\n        show: noop,\n        hide: noop,\n\n        // Options\n        color: false,\n        flat: false,\n        showInput: false,\n        allowEmpty: false,\n        showButtons: true,\n        clickoutFiresChange: false,\n        showInitial: false,\n        showPalette: false,\n        showPaletteOnly: false,\n        showSelectionPalette: true,\n        localStorageKey: false,\n        appendTo: \"body\",\n        maxSelectionSize: 7,\n        cancelText: \"cancel\",\n        chooseText: \"choose\",\n        clearText: \"Clear Color Selection\",\n        preferredFormat: false,\n        className: \"\", // Deprecated - use containerClassName and replacerClassName instead.\n        containerClassName: \"\",\n        replacerClassName: \"\",\n        showAlpha: false,\n        theme: \"sp-light\",\n        palette: [[\"#ffffff\", \"#000000\", \"#ff0000\", \"#ff8000\", \"#ffff00\", \"#008000\", \"#0000ff\", \"#4b0082\", \"#9400d3\"]],\n        selectionPalette: [],\n        disabled: false\n    },\n    spectrums = [],\n    IE = !!/msie/i.exec( window.navigator.userAgent ),\n    rgbaSupport = (function() {\n        function contains( str, substr ) {\n            return !!~('' + str).indexOf(substr);\n        }\n\n        var elem = document.createElement('div');\n        var style = elem.style;\n        style.cssText = 'background-color:rgba(0,0,0,.5)';\n        return contains(style.backgroundColor, 'rgba') || contains(style.backgroundColor, 'hsla');\n    })(),\n    inputTypeColorSupport = (function() {\n        var colorInput = $(\"<input type='color' value='!' />\")[0];\n        return colorInput.type === \"color\" && colorInput.value !== \"!\";\n    })(),\n    replaceInput = [\n        \"<div class='sp-replacer'>\",\n            \"<div class='sp-preview'><div class='sp-preview-inner'></div></div>\",\n            \"<div class='sp-dd'>&#9660;</div>\",\n        \"</div>\"\n    ].join(''),\n    markup = (function () {\n\n        // IE does not support gradients with multiple stops, so we need to simulate\n        //  that for the rainbow slider with 8 divs that each have a single gradient\n        var gradientFix = \"\";\n        if (IE) {\n            for (var i = 1; i <= 6; i++) {\n                gradientFix += \"<div class='sp-\" + i + \"'></div>\";\n            }\n        }\n\n        return [\n            \"<div class='sp-container sp-hidden'>\",\n                \"<div class='sp-palette-container'>\",\n                    \"<div class='sp-palette sp-thumb sp-cf'></div>\",\n                \"</div>\",\n                \"<div class='sp-picker-container'>\",\n                    \"<div class='sp-top sp-cf'>\",\n                        \"<div class='sp-fill'></div>\",\n                        \"<div class='sp-top-inner'>\",\n                            \"<div class='sp-color'>\",\n                                \"<div class='sp-sat'>\",\n                                    \"<div class='sp-val'>\",\n                                        \"<div class='sp-dragger'></div>\",\n                                    \"</div>\",\n                                \"</div>\",\n                            \"</div>\",\n                            \"<div class='sp-clear sp-clear-display'>\",\n                            \"</div>\",\n                            \"<div class='sp-hue'>\",\n                                \"<div class='sp-slider'></div>\",\n                                gradientFix,\n                            \"</div>\",\n                        \"</div>\",\n                        \"<div class='sp-alpha'><div class='sp-alpha-inner'><div class='sp-alpha-handle'></div></div></div>\",\n                    \"</div>\",\n                    \"<div class='sp-input-container sp-cf'>\",\n                        \"<input class='sp-input' type='text' spellcheck='false'  />\",\n                    \"</div>\",\n                    \"<div class='sp-initial sp-thumb sp-cf'></div>\",\n                    \"<div class='sp-button-container sp-cf'>\",\n                        \"<a class='sp-cancel' href='#'></a>\",\n                        \"<button type='button' class='sp-choose'></button>\",\n                    \"</div>\",\n                \"</div>\",\n            \"</div>\"\n        ].join(\"\");\n    })();\n\n    function paletteTemplate (p, color, className, tooltipFormat) {\n        var html = [];\n        for (var i = 0; i < p.length; i++) {\n            var current = p[i];\n            if(current) {\n                var tiny = tinycolor(current);\n                var c = tiny.toHsl().l < 0.5 ? \"sp-thumb-el sp-thumb-dark\" : \"sp-thumb-el sp-thumb-light\";\n                c += (tinycolor.equals(color, current)) ? \" sp-thumb-active\" : \"\";\n\n                var formattedString = tiny.toString(tooltipFormat || \"rgb\");\n                var swatchStyle = rgbaSupport ? (\"background-color:\" + tiny.toRgbString()) : \"filter:\" + tiny.toFilter();\n                html.push('<span title=\"' + formattedString + '\" data-color=\"' + tiny.toRgbString() + '\" class=\"' + c + '\"><span class=\"sp-thumb-inner\" style=\"' + swatchStyle + ';\" /></span>');\n            } else {\n                var cls = 'sp-clear-display';\n                html.push('<span title=\"No Color Selected\" data-color=\"\" style=\"background-color:transparent;\" class=\"' + cls + '\"></span>');\n            }\n        }\n        return \"<div class='sp-cf \" + className + \"'>\" + html.join('') + \"</div>\";\n    }\n\n    function hideAll() {\n        for (var i = 0; i < spectrums.length; i++) {\n            if (spectrums[i]) {\n                spectrums[i].hide();\n            }\n        }\n    }\n\n    function instanceOptions(o, callbackContext) {\n        var opts = $.extend({}, defaultOpts, o);\n        opts.callbacks = {\n            'move': bind(opts.move, callbackContext),\n            'change': bind(opts.change, callbackContext),\n            'show': bind(opts.show, callbackContext),\n            'hide': bind(opts.hide, callbackContext),\n            'beforeShow': bind(opts.beforeShow, callbackContext)\n        };\n\n        return opts;\n    }\n\n    function spectrum(element, o) {\n\n        var opts = instanceOptions(o, element),\n            flat = opts.flat,\n            showSelectionPalette = opts.showSelectionPalette,\n            localStorageKey = opts.localStorageKey,\n            theme = opts.theme,\n            callbacks = opts.callbacks,\n            resize = throttle(reflow, 10),\n            visible = false,\n            dragWidth = 0,\n            dragHeight = 0,\n            dragHelperHeight = 0,\n            slideHeight = 0,\n            slideWidth = 0,\n            alphaWidth = 0,\n            alphaSlideHelperWidth = 0,\n            slideHelperHeight = 0,\n            currentHue = 0,\n            currentSaturation = 0,\n            currentValue = 0,\n            currentAlpha = 1,\n            palette = [],\n            paletteArray = [],\n            paletteLookup = {},\n            selectionPalette = opts.selectionPalette.slice(0),\n            maxSelectionSize = opts.maxSelectionSize,\n            draggingClass = \"sp-dragging\",\n            shiftMovementDirection = null;\n\n        var doc = element.ownerDocument,\n            body = doc.body,\n            boundElement = $(element),\n            disabled = false,\n            container = $(markup, doc).addClass(theme),\n            dragger = container.find(\".sp-color\"),\n            dragHelper = container.find(\".sp-dragger\"),\n            slider = container.find(\".sp-hue\"),\n            slideHelper = container.find(\".sp-slider\"),\n            alphaSliderInner = container.find(\".sp-alpha-inner\"),\n            alphaSlider = container.find(\".sp-alpha\"),\n            alphaSlideHelper = container.find(\".sp-alpha-handle\"),\n            textInput = container.find(\".sp-input\"),\n            paletteContainer = container.find(\".sp-palette\"),\n            initialColorContainer = container.find(\".sp-initial\"),\n            cancelButton = container.find(\".sp-cancel\"),\n            clearButton = container.find(\".sp-clear\"),\n            chooseButton = container.find(\".sp-choose\"),\n            isInput = boundElement.is(\"input\"),\n            isInputTypeColor = isInput && inputTypeColorSupport && boundElement.attr(\"type\") === \"color\",\n            shouldReplace = isInput && !flat,\n            replacer = (shouldReplace) ? $(replaceInput).addClass(theme).addClass(opts.className).addClass(opts.replacerClassName) : $([]),\n            offsetElement = (shouldReplace) ? replacer : boundElement,\n            previewElement = replacer.find(\".sp-preview-inner\"),\n            initialColor = opts.color || (isInput && boundElement.val()),\n            colorOnShow = false,\n            preferredFormat = opts.preferredFormat,\n            currentPreferredFormat = preferredFormat,\n            clickoutFiresChange = !opts.showButtons || opts.clickoutFiresChange,\n            isEmpty = !initialColor,\n            allowEmpty = opts.allowEmpty && !isInputTypeColor;\n\n        function applyOptions() {\n\n            if (opts.showPaletteOnly) {\n                opts.showPalette = true;\n            }\n\n            if (opts.palette) {\n                palette = opts.palette.slice(0);\n                paletteArray = $.isArray(palette[0]) ? palette : [palette];\n                paletteLookup = {};\n                for (var i = 0; i < paletteArray.length; i++) {\n                    for (var j = 0; j < paletteArray[i].length; j++) {\n                        var rgb = tinycolor(paletteArray[i][j]).toRgbString();\n                        paletteLookup[rgb] = true;\n                    }\n                }\n            }\n\n            container.toggleClass(\"sp-flat\", flat);\n            container.toggleClass(\"sp-input-disabled\", !opts.showInput);\n            container.toggleClass(\"sp-alpha-enabled\", opts.showAlpha);\n            container.toggleClass(\"sp-clear-enabled\", allowEmpty);\n            container.toggleClass(\"sp-buttons-disabled\", !opts.showButtons);\n            container.toggleClass(\"sp-palette-disabled\", !opts.showPalette);\n            container.toggleClass(\"sp-palette-only\", opts.showPaletteOnly);\n            container.toggleClass(\"sp-initial-disabled\", !opts.showInitial);\n            container.addClass(opts.className).addClass(opts.containerClassName);\n\n            reflow();\n        }\n\n        function initialize() {\n\n            if (IE) {\n                container.find(\"*:not(input)\").attr(\"unselectable\", \"on\");\n            }\n\n            applyOptions();\n\n            if (shouldReplace) {\n                boundElement.after(replacer).hide();\n            }\n\n            if (!allowEmpty) {\n                clearButton.hide();\n            }\n\n            if (flat) {\n                boundElement.after(container).hide();\n            }\n            else {\n\n                var appendTo = opts.appendTo === \"parent\" ? boundElement.parent() : $(opts.appendTo);\n                if (appendTo.length !== 1) {\n                    appendTo = $(\"body\");\n                }\n\n                appendTo.append(container);\n            }\n\n            updateSelectionPaletteFromStorage();\n\n            offsetElement.bind(\"click.spectrum touchstart.spectrum\", function (e) {\n                if (!disabled) {\n                    toggle();\n                }\n\n                e.stopPropagation();\n\n                if (!$(e.target).is(\"input\")) {\n                    e.preventDefault();\n                }\n            });\n\n            if(boundElement.is(\":disabled\") || (opts.disabled === true)) {\n                disable();\n            }\n\n            // Prevent clicks from bubbling up to document.  This would cause it to be hidden.\n            container.click(stopPropagation);\n\n            // Handle user typed input\n            textInput.change(setFromTextInput);\n            textInput.bind(\"paste\", function () {\n                setTimeout(setFromTextInput, 1);\n            });\n            textInput.keydown(function (e) { if (e.keyCode == 13) { setFromTextInput(); } });\n\n            cancelButton.text(opts.cancelText);\n            cancelButton.bind(\"click.spectrum\", function (e) {\n                e.stopPropagation();\n                e.preventDefault();\n                hide(\"cancel\");\n            });\n\n            clearButton.attr(\"title\", opts.clearText);\n            clearButton.bind(\"click.spectrum\", function (e) {\n                e.stopPropagation();\n                e.preventDefault();\n                isEmpty = true;\n                move();\n\n                if(flat) {\n                    //for the flat style, this is a change event\n                    updateOriginalInput(true);\n                }\n            });\n\n            chooseButton.text(opts.chooseText);\n            chooseButton.bind(\"click.spectrum\", function (e) {\n                e.stopPropagation();\n                e.preventDefault();\n\n                if (isValid()) {\n                    updateOriginalInput(true);\n                    hide();\n                }\n            });\n\n            draggable(alphaSlider, function (dragX, dragY, e) {\n                currentAlpha = (dragX / alphaWidth);\n                isEmpty = false;\n                if (e.shiftKey) {\n                    currentAlpha = Math.round(currentAlpha * 10) / 10;\n                }\n\n                move();\n            }, dragStart, dragStop);\n\n            draggable(slider, function (dragX, dragY) {\n                currentHue = parseFloat(dragY / slideHeight);\n                isEmpty = false;\n                if (!opts.showAlpha) {\n                    currentAlpha = 1;\n                }\n                move();\n            }, dragStart, dragStop);\n\n            draggable(dragger, function (dragX, dragY, e) {\n\n                // shift+drag should snap the movement to either the x or y axis.\n                if (!e.shiftKey) {\n                    shiftMovementDirection = null;\n                }\n                else if (!shiftMovementDirection) {\n                    var oldDragX = currentSaturation * dragWidth;\n                    var oldDragY = dragHeight - (currentValue * dragHeight);\n                    var furtherFromX = Math.abs(dragX - oldDragX) > Math.abs(dragY - oldDragY);\n\n                    shiftMovementDirection = furtherFromX ? \"x\" : \"y\";\n                }\n\n                var setSaturation = !shiftMovementDirection || shiftMovementDirection === \"x\";\n                var setValue = !shiftMovementDirection || shiftMovementDirection === \"y\";\n\n                if (setSaturation) {\n                    currentSaturation = parseFloat(dragX / dragWidth);\n                }\n                if (setValue) {\n                    currentValue = parseFloat((dragHeight - dragY) / dragHeight);\n                }\n\n                isEmpty = false;\n                if (!opts.showAlpha) {\n                    currentAlpha = 1;\n                }\n\n                move();\n\n            }, dragStart, dragStop);\n\n            if (!!initialColor) {\n                set(initialColor);\n\n                // In case color was black - update the preview UI and set the format\n                // since the set function will not run (default color is black).\n                updateUI();\n                currentPreferredFormat = preferredFormat || tinycolor(initialColor).format;\n\n                addColorToSelectionPalette(initialColor);\n            }\n            else {\n                updateUI();\n            }\n\n            if (flat) {\n                show();\n            }\n\n            function palletElementClick(e) {\n                if (e.data && e.data.ignore) {\n                    set($(this).data(\"color\"));\n                    move();\n                }\n                else {\n                    set($(this).data(\"color\"));\n                    move();\n                    updateOriginalInput(true);\n                    hide();\n                }\n\n                return false;\n            }\n\n            var paletteEvent = IE ? \"mousedown.spectrum\" : \"click.spectrum touchstart.spectrum\";\n            paletteContainer.delegate(\".sp-thumb-el\", paletteEvent, palletElementClick);\n            initialColorContainer.delegate(\".sp-thumb-el:nth-child(1)\", paletteEvent, { ignore: true }, palletElementClick);\n        }\n\n        function updateSelectionPaletteFromStorage() {\n\n            if (localStorageKey && window.localStorage) {\n\n                // Migrate old palettes over to new format.  May want to remove this eventually.\n                try {\n                    var oldPalette = window.localStorage[localStorageKey].split(\",#\");\n                    if (oldPalette.length > 1) {\n                        delete window.localStorage[localStorageKey];\n                        $.each(oldPalette, function(i, c) {\n                             addColorToSelectionPalette(c);\n                        });\n                    }\n                }\n                catch(e) { }\n\n                try {\n                    selectionPalette = window.localStorage[localStorageKey].split(\";\");\n                }\n                catch (e) { }\n            }\n        }\n\n        function addColorToSelectionPalette(color) {\n            if (showSelectionPalette) {\n                var rgb = tinycolor(color).toRgbString();\n                if (!paletteLookup[rgb] && $.inArray(rgb, selectionPalette) === -1) {\n                    selectionPalette.push(rgb);\n                    while(selectionPalette.length > maxSelectionSize) {\n                        selectionPalette.shift();\n                    }\n                }\n\n                if (localStorageKey && window.localStorage) {\n                    try {\n                        window.localStorage[localStorageKey] = selectionPalette.join(\";\");\n                    }\n                    catch(e) { }\n                }\n            }\n        }\n\n        function getUniqueSelectionPalette() {\n            var unique = [];\n            if (opts.showPalette) {\n                for (i = 0; i < selectionPalette.length; i++) {\n                    var rgb = tinycolor(selectionPalette[i]).toRgbString();\n\n                    if (!paletteLookup[rgb]) {\n                        unique.push(selectionPalette[i]);\n                    }\n                }\n            }\n\n            return unique.reverse().slice(0, opts.maxSelectionSize);\n        }\n\n        function drawPalette() {\n\n            var currentColor = get();\n\n            var html = $.map(paletteArray, function (palette, i) {\n                return paletteTemplate(palette, currentColor, \"sp-palette-row sp-palette-row-\" + i, opts.preferredFormat);\n            });\n\n            updateSelectionPaletteFromStorage();\n\n            if (selectionPalette) {\n                html.push(paletteTemplate(getUniqueSelectionPalette(), currentColor, \"sp-palette-row sp-palette-row-selection\", opts.preferredFormat));\n            }\n\n            paletteContainer.html(html.join(\"\"));\n        }\n\n        function drawInitial() {\n            if (opts.showInitial) {\n                var initial = colorOnShow;\n                var current = get();\n                initialColorContainer.html(paletteTemplate([initial, current], current, \"sp-palette-row-initial\", opts.preferredFormat));\n            }\n        }\n\n        function dragStart() {\n            if (dragHeight <= 0 || dragWidth <= 0 || slideHeight <= 0) {\n                reflow();\n            }\n            container.addClass(draggingClass);\n            shiftMovementDirection = null;\n            boundElement.trigger('dragstart.spectrum', [ get() ]);\n        }\n\n        function dragStop() {\n            container.removeClass(draggingClass);\n            boundElement.trigger('dragstop.spectrum', [ get() ]);\n        }\n\n        function setFromTextInput() {\n\n            var value = textInput.val();\n\n            if ((value === null || value === \"\") && allowEmpty) {\n                set(null);\n                updateOriginalInput(true);\n            }\n            else {\n                var tiny = tinycolor(value);\n                if (tiny.ok) {\n                    set(tiny);\n                    updateOriginalInput(true);\n                }\n                else {\n                    textInput.addClass(\"sp-validation-error\");\n                }\n            }\n        }\n\n        function toggle() {\n            if (visible) {\n                hide();\n            }\n            else {\n                show();\n            }\n        }\n\n        function show() {\n            var event = $.Event('beforeShow.spectrum');\n\n            if (visible) {\n                reflow();\n                return;\n            }\n\n            boundElement.trigger(event, [ get() ]);\n\n            if (callbacks.beforeShow(get()) === false || event.isDefaultPrevented()) {\n                return;\n            }\n\n            hideAll();\n            visible = true;\n\n            $(doc).bind(\"click.spectrum\", hide);\n            $(window).bind(\"resize.spectrum\", resize);\n            replacer.addClass(\"sp-active\");\n            container.removeClass(\"sp-hidden\");\n\n            reflow();\n            updateUI();\n\n            colorOnShow = get();\n\n            drawInitial();\n            callbacks.show(colorOnShow);\n            boundElement.trigger('show.spectrum', [ colorOnShow ]);\n        }\n\n        function hide(e) {\n\n            // Return on right click\n            if (e && e.type == \"click\" && e.button == 2) { return; }\n\n            // Return if hiding is unnecessary\n            if (!visible || flat) { return; }\n            visible = false;\n\n            $(doc).unbind(\"click.spectrum\", hide);\n            $(window).unbind(\"resize.spectrum\", resize);\n\n            replacer.removeClass(\"sp-active\");\n            container.addClass(\"sp-hidden\");\n\n            var colorHasChanged = !tinycolor.equals(get(), colorOnShow);\n\n            if (colorHasChanged) {\n                if (clickoutFiresChange && e !== \"cancel\") {\n                    updateOriginalInput(true);\n                }\n                else {\n                    revert();\n                }\n            }\n\n            callbacks.hide(get());\n            boundElement.trigger('hide.spectrum', [ get() ]);\n        }\n\n        function revert() {\n            set(colorOnShow, true);\n        }\n\n        function set(color, ignoreFormatChange) {\n            if (tinycolor.equals(color, get())) {\n                // Update UI just in case a validation error needs\n                // to be cleared.\n                updateUI();\n                return;\n            }\n\n            var newColor, newHsv;\n            if (!color && allowEmpty) {\n                isEmpty = true;\n            } else {\n                isEmpty = false;\n                newColor = tinycolor(color);\n                newHsv = newColor.toHsv();\n\n                currentHue = (newHsv.h % 360) / 360;\n                currentSaturation = newHsv.s;\n                currentValue = newHsv.v;\n                currentAlpha = newHsv.a;\n            }\n            updateUI();\n\n            if (newColor && newColor.ok && !ignoreFormatChange) {\n                currentPreferredFormat = preferredFormat || newColor.format;\n            }\n        }\n\n        function get(opts) {\n            opts = opts || { };\n\n            if (allowEmpty && isEmpty) {\n                return null;\n            }\n\n            return tinycolor.fromRatio({\n                h: currentHue,\n                s: currentSaturation,\n                v: currentValue,\n                a: Math.round(currentAlpha * 100) / 100\n            }, { format: opts.format || currentPreferredFormat });\n        }\n\n        function isValid() {\n            return !textInput.hasClass(\"sp-validation-error\");\n        }\n\n        function move() {\n            updateUI();\n\n            callbacks.move(get());\n            boundElement.trigger('move.spectrum', [ get() ]);\n        }\n\n        function updateUI() {\n\n            textInput.removeClass(\"sp-validation-error\");\n\n            updateHelperLocations();\n\n            // Update dragger background color (gradients take care of saturation and value).\n            var flatColor = tinycolor.fromRatio({ h: currentHue, s: 1, v: 1 });\n            dragger.css(\"background-color\", flatColor.toHexString());\n\n            // Get a format that alpha will be included in (hex and names ignore alpha)\n            var format = currentPreferredFormat;\n            if (currentAlpha < 1 && !(currentAlpha === 0 && format === \"name\")) {\n                if (format === \"hex\" || format === \"hex3\" || format === \"hex6\" || format === \"name\") {\n                    format = \"rgb\";\n                }\n            }\n\n            var realColor = get({ format: format }),\n                displayColor = '';\n\n             //reset background info for preview element\n            previewElement.removeClass(\"sp-clear-display\");\n            previewElement.css('background-color', 'transparent');\n\n            if (!realColor && allowEmpty) {\n                // Update the replaced elements background with icon indicating no color selection\n                previewElement.addClass(\"sp-clear-display\");\n            }\n            else {\n                var realHex = realColor.toHexString(),\n                    realRgb = realColor.toRgbString();\n\n                // Update the replaced elements background color (with actual selected color)\n                if (rgbaSupport || realColor.alpha === 1) {\n                    previewElement.css(\"background-color\", realRgb);\n                }\n                else {\n                    previewElement.css(\"background-color\", \"transparent\");\n                    previewElement.css(\"filter\", realColor.toFilter());\n                }\n\n                if (opts.showAlpha) {\n                    var rgb = realColor.toRgb();\n                    rgb.a = 0;\n                    var realAlpha = tinycolor(rgb).toRgbString();\n                    var gradient = \"linear-gradient(left, \" + realAlpha + \", \" + realHex + \")\";\n\n                    if (IE) {\n                        alphaSliderInner.css(\"filter\", tinycolor(realAlpha).toFilter({ gradientType: 1 }, realHex));\n                    }\n                    else {\n                        alphaSliderInner.css(\"background\", \"-webkit-\" + gradient);\n                        alphaSliderInner.css(\"background\", \"-moz-\" + gradient);\n                        alphaSliderInner.css(\"background\", \"-ms-\" + gradient);\n                        // Use current syntax gradient on unprefixed property.\n                        alphaSliderInner.css(\"background\",\n                            \"linear-gradient(to right, \" + realAlpha + \", \" + realHex + \")\");\n                    }\n                }\n\n                displayColor = realColor.toString(format);\n            }\n\n            // Update the text entry input as it changes happen\n            if (opts.showInput) {\n                textInput.val(displayColor);\n            }\n\n            if (opts.showPalette) {\n                drawPalette();\n            }\n\n            drawInitial();\n        }\n\n        function updateHelperLocations() {\n            var s = currentSaturation;\n            var v = currentValue;\n\n            if(allowEmpty && isEmpty) {\n                //if selected color is empty, hide the helpers\n                alphaSlideHelper.hide();\n                slideHelper.hide();\n                dragHelper.hide();\n            }\n            else {\n                //make sure helpers are visible\n                alphaSlideHelper.show();\n                slideHelper.show();\n                dragHelper.show();\n\n                // Where to show the little circle in that displays your current selected color\n                var dragX = s * dragWidth;\n                var dragY = dragHeight - (v * dragHeight);\n                dragX = Math.max(\n                    -dragHelperHeight,\n                    Math.min(dragWidth - dragHelperHeight, dragX - dragHelperHeight)\n                );\n                dragY = Math.max(\n                    -dragHelperHeight,\n                    Math.min(dragHeight - dragHelperHeight, dragY - dragHelperHeight)\n                );\n                dragHelper.css({\n                    \"top\": dragY + \"px\",\n                    \"left\": dragX + \"px\"\n                });\n\n                var alphaX = currentAlpha * alphaWidth;\n                alphaSlideHelper.css({\n                    \"left\": (alphaX - (alphaSlideHelperWidth / 2)) + \"px\"\n                });\n\n                // Where to show the bar that displays your current selected hue\n                var slideY = (currentHue) * slideHeight;\n                slideHelper.css({\n                    \"top\": (slideY - slideHelperHeight) + \"px\"\n                });\n            }\n        }\n\n        function updateOriginalInput(fireCallback) {\n            var color = get(),\n                displayColor = '',\n                hasChanged = !tinycolor.equals(color, colorOnShow);\n\n            if (color) {\n                displayColor = color.toString(currentPreferredFormat);\n                // Update the selection palette with the current color\n                addColorToSelectionPalette(color);\n            }\n\n            if (isInput) {\n                boundElement.val(displayColor);\n            }\n\n            colorOnShow = color;\n\n            if (fireCallback && hasChanged) {\n                callbacks.change(color);\n                boundElement.trigger('change', [ color ]);\n            }\n        }\n\n        function reflow() {\n            dragWidth = dragger.width();\n            dragHeight = dragger.height();\n            dragHelperHeight = dragHelper.height();\n            slideWidth = slider.width();\n            slideHeight = slider.height();\n            slideHelperHeight = slideHelper.height();\n            alphaWidth = alphaSlider.width();\n            alphaSlideHelperWidth = alphaSlideHelper.width();\n\n            if (!flat) {\n                container.css(\"position\", \"absolute\");\n                container.offset(getOffset(container, offsetElement));\n            }\n\n            updateHelperLocations();\n\n            if (opts.showPalette) {\n                drawPalette();\n            }\n\n            boundElement.trigger('reflow.spectrum');\n        }\n\n        function destroy() {\n            boundElement.show();\n            offsetElement.unbind(\"click.spectrum touchstart.spectrum\");\n            container.remove();\n            replacer.remove();\n            spectrums[spect.id] = null;\n        }\n\n        function option(optionName, optionValue) {\n            if (optionName === undefined) {\n                return $.extend({}, opts);\n            }\n            if (optionValue === undefined) {\n                return opts[optionName];\n            }\n\n            opts[optionName] = optionValue;\n            applyOptions();\n        }\n\n        function enable() {\n            disabled = false;\n            boundElement.attr(\"disabled\", false);\n            offsetElement.removeClass(\"sp-disabled\");\n        }\n\n        function disable() {\n            hide();\n            disabled = true;\n            boundElement.attr(\"disabled\", true);\n            offsetElement.addClass(\"sp-disabled\");\n        }\n\n        initialize();\n\n        var spect = {\n            show: show,\n            hide: hide,\n            toggle: toggle,\n            reflow: reflow,\n            option: option,\n            enable: enable,\n            disable: disable,\n            set: function (c) {\n                set(c);\n                updateOriginalInput();\n            },\n            get: get,\n            destroy: destroy,\n            container: container\n        };\n\n        spect.id = spectrums.push(spect) - 1;\n\n        return spect;\n    }\n\n    /**\n    * checkOffset - get the offset below/above and left/right element depending on screen position\n    * Thanks https://github.com/jquery/jquery-ui/blob/master/ui/jquery.ui.datepicker.js\n    */\n    function getOffset(picker, input) {\n        var extraY = 0;\n        var dpWidth = picker.outerWidth();\n        var dpHeight = picker.outerHeight();\n        var inputHeight = input.outerHeight();\n        var doc = picker[0].ownerDocument;\n        var docElem = doc.documentElement;\n        var viewWidth = docElem.clientWidth + $(doc).scrollLeft();\n        var viewHeight = docElem.clientHeight + $(doc).scrollTop();\n        var offset = input.offset();\n        offset.top += inputHeight;\n\n        offset.left -=\n            Math.min(offset.left, (offset.left + dpWidth > viewWidth && viewWidth > dpWidth) ?\n            Math.abs(offset.left + dpWidth - viewWidth) : 0);\n\n        offset.top -=\n            Math.min(offset.top, ((offset.top + dpHeight > viewHeight && viewHeight > dpHeight) ?\n            Math.abs(dpHeight + inputHeight - extraY) : extraY));\n\n        return offset;\n    }\n\n    /**\n    * noop - do nothing\n    */\n    function noop() {\n\n    }\n\n    /**\n    * stopPropagation - makes the code only doing this a little easier to read in line\n    */\n    function stopPropagation(e) {\n        e.stopPropagation();\n    }\n\n    /**\n    * Create a function bound to a given object\n    * Thanks to underscore.js\n    */\n    function bind(func, obj) {\n        var slice = Array.prototype.slice;\n        var args = slice.call(arguments, 2);\n        return function () {\n            return func.apply(obj, args.concat(slice.call(arguments)));\n        };\n    }\n\n    /**\n    * Lightweight drag helper.  Handles containment within the element, so that\n    * when dragging, the x is within [0,element.width] and y is within [0,element.height]\n    */\n    function draggable(element, onmove, onstart, onstop) {\n        onmove = onmove || function () { };\n        onstart = onstart || function () { };\n        onstop = onstop || function () { };\n        var doc = element.ownerDocument || document;\n        var dragging = false;\n        var offset = {};\n        var maxHeight = 0;\n        var maxWidth = 0;\n        var hasTouch = ('ontouchstart' in window);\n\n        var duringDragEvents = {};\n        duringDragEvents[\"selectstart\"] = prevent;\n        duringDragEvents[\"dragstart\"] = prevent;\n        duringDragEvents[\"touchmove mousemove\"] = move;\n        duringDragEvents[\"touchend mouseup\"] = stop;\n\n        function prevent(e) {\n            if (e.stopPropagation) {\n                e.stopPropagation();\n            }\n            if (e.preventDefault) {\n                e.preventDefault();\n            }\n            e.returnValue = false;\n        }\n\n        function move(e) {\n            if (dragging) {\n                // Mouseup happened outside of window\n                if (IE && document.documentMode < 9 && !e.button) {\n                    return stop();\n                }\n\n                var touches = e.originalEvent.touches;\n                var pageX = touches ? touches[0].pageX : e.pageX;\n                var pageY = touches ? touches[0].pageY : e.pageY;\n\n                var dragX = Math.max(0, Math.min(pageX - offset.left, maxWidth));\n                var dragY = Math.max(0, Math.min(pageY - offset.top, maxHeight));\n\n                if (hasTouch) {\n                    // Stop scrolling in iOS\n                    prevent(e);\n                }\n\n                onmove.apply(element, [dragX, dragY, e]);\n            }\n        }\n\n        function start(e) {\n            var rightclick = (e.which) ? (e.which == 3) : (e.button == 2);\n            var touches = e.originalEvent.touches;\n\n            if (!rightclick && !dragging) {\n                if (onstart.apply(element, arguments) !== false) {\n                    dragging = true;\n                    maxHeight = $(element).height();\n                    maxWidth = $(element).width();\n                    offset = $(element).offset();\n\n                    $(doc).bind(duringDragEvents);\n                    $(doc.body).addClass(\"sp-dragging\");\n\n                    if (!hasTouch) {\n                        move(e);\n                    }\n\n                    prevent(e);\n                }\n            }\n        }\n\n        function stop() {\n            if (dragging) {\n                $(doc).unbind(duringDragEvents);\n                $(doc.body).removeClass(\"sp-dragging\");\n                onstop.apply(element, arguments);\n            }\n            dragging = false;\n        }\n\n        $(element).bind(\"touchstart mousedown\", start);\n    }\n\n    function throttle(func, wait, debounce) {\n        var timeout;\n        return function () {\n            var context = this, args = arguments;\n            var throttler = function () {\n                timeout = null;\n                func.apply(context, args);\n            };\n            if (debounce) clearTimeout(timeout);\n            if (debounce || !timeout) timeout = setTimeout(throttler, wait);\n        };\n    }\n\n    function log(){/* jshint -W021 */if(window.console){if(Function.prototype.bind)log=Function.prototype.bind.call(console.log,console);else log=function(){Function.prototype.apply.call(console.log,console,arguments);};log.apply(this,arguments);}}\n\n    /**\n    * Define a jQuery plugin\n    */\n    var dataID = \"spectrum.id\";\n    $.fn.spectrum = function (opts, extra) {\n\n        if (typeof opts == \"string\") {\n\n            var returnValue = this;\n            var args = Array.prototype.slice.call( arguments, 1 );\n\n            this.each(function () {\n                var spect = spectrums[$(this).data(dataID)];\n                if (spect) {\n                    var method = spect[opts];\n                    if (!method) {\n                        throw new Error( \"Spectrum: no such method: '\" + opts + \"'\" );\n                    }\n\n                    if (opts == \"get\") {\n                        returnValue = spect.get();\n                    }\n                    else if (opts == \"container\") {\n                        returnValue = spect.container;\n                    }\n                    else if (opts == \"option\") {\n                        returnValue = spect.option.apply(spect, args);\n                    }\n                    else if (opts == \"destroy\") {\n                        spect.destroy();\n                        $(this).removeData(dataID);\n                    }\n                    else {\n                        method.apply(spect, args);\n                    }\n                }\n            });\n\n            return returnValue;\n        }\n\n        // Initializing a new instance of spectrum\n        return this.spectrum(\"destroy\").each(function () {\n            var options = $.extend({}, opts, $(this).data());\n            var spect = spectrum(this, options);\n            $(this).data(dataID, spect.id);\n        });\n    };\n\n    $.fn.spectrum.load = true;\n    $.fn.spectrum.loadOpts = {};\n    $.fn.spectrum.draggable = draggable;\n    $.fn.spectrum.defaults = defaultOpts;\n\n    $.spectrum = { };\n    $.spectrum.localization = { };\n    $.spectrum.palettes = { };\n\n    $.fn.spectrum.processNativeColorInputs = function () {\n        if (!inputTypeColorSupport) {\n            $(\"input[type=color]\").spectrum({\n                preferredFormat: \"hex6\"\n            });\n        }\n    };\n\n    // TinyColor v0.9.17\n    // https://github.com/bgrins/TinyColor\n    // 2013-08-10, Brian Grinstead, MIT License\n\n    (function() {\n\n    var trimLeft = /^[\\s,#]+/,\n        trimRight = /\\s+$/,\n        tinyCounter = 0,\n        math = Math,\n        mathRound = math.round,\n        mathMin = math.min,\n        mathMax = math.max,\n        mathRandom = math.random;\n\n    function tinycolor (color, opts) {\n\n        color = (color) ? color : '';\n        opts = opts || { };\n\n        // If input is already a tinycolor, return itself\n        if (typeof color == \"object\" && color.hasOwnProperty(\"_tc_id\")) {\n           return color;\n        }\n\n        var rgb = inputToRGB(color);\n        var r = rgb.r,\n            g = rgb.g,\n            b = rgb.b,\n            a = rgb.a,\n            roundA = mathRound(100*a) / 100,\n            format = opts.format || rgb.format;\n\n        // Don't let the range of [0,255] come back in [0,1].\n        // Potentially lose a little bit of precision here, but will fix issues where\n        // .5 gets interpreted as half of the total, instead of half of 1\n        // If it was supposed to be 128, this was already taken care of by `inputToRgb`\n        if (r < 1) { r = mathRound(r); }\n        if (g < 1) { g = mathRound(g); }\n        if (b < 1) { b = mathRound(b); }\n\n        return {\n            ok: rgb.ok,\n            format: format,\n            _tc_id: tinyCounter++,\n            alpha: a,\n            getAlpha: function() {\n                return a;\n            },\n            setAlpha: function(value) {\n                a = boundAlpha(value);\n                roundA = mathRound(100*a) / 100;\n            },\n            toHsv: function() {\n                var hsv = rgbToHsv(r, g, b);\n                return { h: hsv.h * 360, s: hsv.s, v: hsv.v, a: a };\n            },\n            toHsvString: function() {\n                var hsv = rgbToHsv(r, g, b);\n                var h = mathRound(hsv.h * 360), s = mathRound(hsv.s * 100), v = mathRound(hsv.v * 100);\n                return (a == 1) ?\n                  \"hsv(\"  + h + \", \" + s + \"%, \" + v + \"%)\" :\n                  \"hsva(\" + h + \", \" + s + \"%, \" + v + \"%, \"+ roundA + \")\";\n            },\n            toHsl: function() {\n                var hsl = rgbToHsl(r, g, b);\n                return { h: hsl.h * 360, s: hsl.s, l: hsl.l, a: a };\n            },\n            toHslString: function() {\n                var hsl = rgbToHsl(r, g, b);\n                var h = mathRound(hsl.h * 360), s = mathRound(hsl.s * 100), l = mathRound(hsl.l * 100);\n                return (a == 1) ?\n                  \"hsl(\"  + h + \", \" + s + \"%, \" + l + \"%)\" :\n                  \"hsla(\" + h + \", \" + s + \"%, \" + l + \"%, \"+ roundA + \")\";\n            },\n            toHex: function(allow3Char) {\n                return rgbToHex(r, g, b, allow3Char);\n            },\n            toHexString: function(allow3Char) {\n                return '#' + this.toHex(allow3Char);\n            },\n            toHex8: function() {\n                return rgbaToHex(r, g, b, a);\n            },\n            toHex8String: function() {\n                return '#' + this.toHex8();\n            },\n            toRgb: function() {\n                return { r: mathRound(r), g: mathRound(g), b: mathRound(b), a: a };\n            },\n            toRgbString: function() {\n                return (a == 1) ?\n                  \"rgb(\"  + mathRound(r) + \", \" + mathRound(g) + \", \" + mathRound(b) + \")\" :\n                  \"rgba(\" + mathRound(r) + \", \" + mathRound(g) + \", \" + mathRound(b) + \", \" + roundA + \")\";\n            },\n            toPercentageRgb: function() {\n                return { r: mathRound(bound01(r, 255) * 100) + \"%\", g: mathRound(bound01(g, 255) * 100) + \"%\", b: mathRound(bound01(b, 255) * 100) + \"%\", a: a };\n            },\n            toPercentageRgbString: function() {\n                return (a == 1) ?\n                  \"rgb(\"  + mathRound(bound01(r, 255) * 100) + \"%, \" + mathRound(bound01(g, 255) * 100) + \"%, \" + mathRound(bound01(b, 255) * 100) + \"%)\" :\n                  \"rgba(\" + mathRound(bound01(r, 255) * 100) + \"%, \" + mathRound(bound01(g, 255) * 100) + \"%, \" + mathRound(bound01(b, 255) * 100) + \"%, \" + roundA + \")\";\n            },\n            toName: function() {\n                if (a === 0) {\n                    return \"transparent\";\n                }\n\n                return hexNames[rgbToHex(r, g, b, true)] || false;\n            },\n            toFilter: function(secondColor) {\n                var hex8String = '#' + rgbaToHex(r, g, b, a);\n                var secondHex8String = hex8String;\n                var gradientType = opts && opts.gradientType ? \"GradientType = 1, \" : \"\";\n\n                if (secondColor) {\n                    var s = tinycolor(secondColor);\n                    secondHex8String = s.toHex8String();\n                }\n\n                return \"progid:DXImageTransform.Microsoft.gradient(\"+gradientType+\"startColorstr=\"+hex8String+\",endColorstr=\"+secondHex8String+\")\";\n            },\n            toString: function(format) {\n                var formatSet = !!format;\n                format = format || this.format;\n\n                var formattedString = false;\n                var hasAlphaAndFormatNotSet = !formatSet && a < 1 && a > 0;\n                var formatWithAlpha = hasAlphaAndFormatNotSet && (format === \"hex\" || format === \"hex6\" || format === \"hex3\" || format === \"name\");\n\n                if (format === \"rgb\") {\n                    formattedString = this.toRgbString();\n                }\n                if (format === \"prgb\") {\n                    formattedString = this.toPercentageRgbString();\n                }\n                if (format === \"hex\" || format === \"hex6\") {\n                    formattedString = this.toHexString();\n                }\n                if (format === \"hex3\") {\n                    formattedString = this.toHexString(true);\n                }\n                if (format === \"hex8\") {\n                    formattedString = this.toHex8String();\n                }\n                if (format === \"name\") {\n                    formattedString = this.toName();\n                }\n                if (format === \"hsl\") {\n                    formattedString = this.toHslString();\n                }\n                if (format === \"hsv\") {\n                    formattedString = this.toHsvString();\n                }\n\n                if (formatWithAlpha) {\n                    return this.toRgbString();\n                }\n\n                return formattedString || this.toHexString();\n            }\n        };\n    }\n\n    // If input is an object, force 1 into \"1.0\" to handle ratios properly\n    // String input requires \"1.0\" as input, so 1 will be treated as 1\n    tinycolor.fromRatio = function(color, opts) {\n        if (typeof color == \"object\") {\n            var newColor = {};\n            for (var i in color) {\n                if (color.hasOwnProperty(i)) {\n                    if (i === \"a\") {\n                        newColor[i] = color[i];\n                    }\n                    else {\n                        newColor[i] = convertToPercentage(color[i]);\n                    }\n                }\n            }\n            color = newColor;\n        }\n\n        return tinycolor(color, opts);\n    };\n\n    // Given a string or object, convert that input to RGB\n    // Possible string inputs:\n    //\n    //     \"red\"\n    //     \"#f00\" or \"f00\"\n    //     \"#ff0000\" or \"ff0000\"\n    //     \"#ff000000\" or \"ff000000\"\n    //     \"rgb 255 0 0\" or \"rgb (255, 0, 0)\"\n    //     \"rgb 1.0 0 0\" or \"rgb (1, 0, 0)\"\n    //     \"rgba (255, 0, 0, 1)\" or \"rgba 255, 0, 0, 1\"\n    //     \"rgba (1.0, 0, 0, 1)\" or \"rgba 1.0, 0, 0, 1\"\n    //     \"hsl(0, 100%, 50%)\" or \"hsl 0 100% 50%\"\n    //     \"hsla(0, 100%, 50%, 1)\" or \"hsla 0 100% 50%, 1\"\n    //     \"hsv(0, 100%, 100%)\" or \"hsv 0 100% 100%\"\n    //\n    function inputToRGB(color) {\n\n        var rgb = { r: 0, g: 0, b: 0 };\n        var a = 1;\n        var ok = false;\n        var format = false;\n\n        if (typeof color == \"string\") {\n            color = stringInputToObject(color);\n        }\n\n        if (typeof color == \"object\") {\n            if (color.hasOwnProperty(\"r\") && color.hasOwnProperty(\"g\") && color.hasOwnProperty(\"b\")) {\n                rgb = rgbToRgb(color.r, color.g, color.b);\n                ok = true;\n                format = String(color.r).substr(-1) === \"%\" ? \"prgb\" : \"rgb\";\n            }\n            else if (color.hasOwnProperty(\"h\") && color.hasOwnProperty(\"s\") && color.hasOwnProperty(\"v\")) {\n                color.s = convertToPercentage(color.s);\n                color.v = convertToPercentage(color.v);\n                rgb = hsvToRgb(color.h, color.s, color.v);\n                ok = true;\n                format = \"hsv\";\n            }\n            else if (color.hasOwnProperty(\"h\") && color.hasOwnProperty(\"s\") && color.hasOwnProperty(\"l\")) {\n                color.s = convertToPercentage(color.s);\n                color.l = convertToPercentage(color.l);\n                rgb = hslToRgb(color.h, color.s, color.l);\n                ok = true;\n                format = \"hsl\";\n            }\n\n            if (color.hasOwnProperty(\"a\")) {\n                a = color.a;\n            }\n        }\n\n        a = boundAlpha(a);\n\n        return {\n            ok: ok,\n            format: color.format || format,\n            r: mathMin(255, mathMax(rgb.r, 0)),\n            g: mathMin(255, mathMax(rgb.g, 0)),\n            b: mathMin(255, mathMax(rgb.b, 0)),\n            a: a\n        };\n    }\n\n\n    // Conversion Functions\n    // --------------------\n\n    // `rgbToHsl`, `rgbToHsv`, `hslToRgb`, `hsvToRgb` modified from:\n    // <http://mjijackson.com/2008/02/rgb-to-hsl-and-rgb-to-hsv-color-model-conversion-algorithms-in-javascript>\n\n    // `rgbToRgb`\n    // Handle bounds / percentage checking to conform to CSS color spec\n    // <http://www.w3.org/TR/css3-color/>\n    // *Assumes:* r, g, b in [0, 255] or [0, 1]\n    // *Returns:* { r, g, b } in [0, 255]\n    function rgbToRgb(r, g, b){\n        return {\n            r: bound01(r, 255) * 255,\n            g: bound01(g, 255) * 255,\n            b: bound01(b, 255) * 255\n        };\n    }\n\n    // `rgbToHsl`\n    // Converts an RGB color value to HSL.\n    // *Assumes:* r, g, and b are contained in [0, 255] or [0, 1]\n    // *Returns:* { h, s, l } in [0,1]\n    function rgbToHsl(r, g, b) {\n\n        r = bound01(r, 255);\n        g = bound01(g, 255);\n        b = bound01(b, 255);\n\n        var max = mathMax(r, g, b), min = mathMin(r, g, b);\n        var h, s, l = (max + min) / 2;\n\n        if(max == min) {\n            h = s = 0; // achromatic\n        }\n        else {\n            var d = max - min;\n            s = l > 0.5 ? d / (2 - max - min) : d / (max + min);\n            switch(max) {\n                case r: h = (g - b) / d + (g < b ? 6 : 0); break;\n                case g: h = (b - r) / d + 2; break;\n                case b: h = (r - g) / d + 4; break;\n            }\n\n            h /= 6;\n        }\n\n        return { h: h, s: s, l: l };\n    }\n\n    // `hslToRgb`\n    // Converts an HSL color value to RGB.\n    // *Assumes:* h is contained in [0, 1] or [0, 360] and s and l are contained [0, 1] or [0, 100]\n    // *Returns:* { r, g, b } in the set [0, 255]\n    function hslToRgb(h, s, l) {\n        var r, g, b;\n\n        h = bound01(h, 360);\n        s = bound01(s, 100);\n        l = bound01(l, 100);\n\n        function hue2rgb(p, q, t) {\n            if(t < 0) t += 1;\n            if(t > 1) t -= 1;\n            if(t < 1/6) return p + (q - p) * 6 * t;\n            if(t < 1/2) return q;\n            if(t < 2/3) return p + (q - p) * (2/3 - t) * 6;\n            return p;\n        }\n\n        if(s === 0) {\n            r = g = b = l; // achromatic\n        }\n        else {\n            var q = l < 0.5 ? l * (1 + s) : l + s - l * s;\n            var p = 2 * l - q;\n            r = hue2rgb(p, q, h + 1/3);\n            g = hue2rgb(p, q, h);\n            b = hue2rgb(p, q, h - 1/3);\n        }\n\n        return { r: r * 255, g: g * 255, b: b * 255 };\n    }\n\n    // `rgbToHsv`\n    // Converts an RGB color value to HSV\n    // *Assumes:* r, g, and b are contained in the set [0, 255] or [0, 1]\n    // *Returns:* { h, s, v } in [0,1]\n    function rgbToHsv(r, g, b) {\n\n        r = bound01(r, 255);\n        g = bound01(g, 255);\n        b = bound01(b, 255);\n\n        var max = mathMax(r, g, b), min = mathMin(r, g, b);\n        var h, s, v = max;\n\n        var d = max - min;\n        s = max === 0 ? 0 : d / max;\n\n        if(max == min) {\n            h = 0; // achromatic\n        }\n        else {\n            switch(max) {\n                case r: h = (g - b) / d + (g < b ? 6 : 0); break;\n                case g: h = (b - r) / d + 2; break;\n                case b: h = (r - g) / d + 4; break;\n            }\n            h /= 6;\n        }\n        return { h: h, s: s, v: v };\n    }\n\n    // `hsvToRgb`\n    // Converts an HSV color value to RGB.\n    // *Assumes:* h is contained in [0, 1] or [0, 360] and s and v are contained in [0, 1] or [0, 100]\n    // *Returns:* { r, g, b } in the set [0, 255]\n     function hsvToRgb(h, s, v) {\n\n        h = bound01(h, 360) * 6;\n        s = bound01(s, 100);\n        v = bound01(v, 100);\n\n        var i = math.floor(h),\n            f = h - i,\n            p = v * (1 - s),\n            q = v * (1 - f * s),\n            t = v * (1 - (1 - f) * s),\n            mod = i % 6,\n            r = [v, q, p, p, t, v][mod],\n            g = [t, v, v, q, p, p][mod],\n            b = [p, p, t, v, v, q][mod];\n\n        return { r: r * 255, g: g * 255, b: b * 255 };\n    }\n\n    // `rgbToHex`\n    // Converts an RGB color to hex\n    // Assumes r, g, and b are contained in the set [0, 255]\n    // Returns a 3 or 6 character hex\n    function rgbToHex(r, g, b, allow3Char) {\n\n        var hex = [\n            pad2(mathRound(r).toString(16)),\n            pad2(mathRound(g).toString(16)),\n            pad2(mathRound(b).toString(16))\n        ];\n\n        // Return a 3 character hex if possible\n        if (allow3Char && hex[0].charAt(0) == hex[0].charAt(1) && hex[1].charAt(0) == hex[1].charAt(1) && hex[2].charAt(0) == hex[2].charAt(1)) {\n            return hex[0].charAt(0) + hex[1].charAt(0) + hex[2].charAt(0);\n        }\n\n        return hex.join(\"\");\n    }\n        // `rgbaToHex`\n        // Converts an RGBA color plus alpha transparency to hex\n        // Assumes r, g, b and a are contained in the set [0, 255]\n        // Returns an 8 character hex\n        function rgbaToHex(r, g, b, a) {\n\n            var hex = [\n                pad2(convertDecimalToHex(a)),\n                pad2(mathRound(r).toString(16)),\n                pad2(mathRound(g).toString(16)),\n                pad2(mathRound(b).toString(16))\n            ];\n\n            return hex.join(\"\");\n        }\n\n    // `equals`\n    // Can be called with any tinycolor input\n    tinycolor.equals = function (color1, color2) {\n        if (!color1 || !color2) { return false; }\n        return tinycolor(color1).toRgbString() == tinycolor(color2).toRgbString();\n    };\n    tinycolor.random = function() {\n        return tinycolor.fromRatio({\n            r: mathRandom(),\n            g: mathRandom(),\n            b: mathRandom()\n        });\n    };\n\n\n    // Modification Functions\n    // ----------------------\n    // Thanks to less.js for some of the basics here\n    // <https://github.com/cloudhead/less.js/blob/master/lib/less/functions.js>\n\n    tinycolor.desaturate = function (color, amount) {\n        amount = (amount === 0) ? 0 : (amount || 10);\n        var hsl = tinycolor(color).toHsl();\n        hsl.s -= amount / 100;\n        hsl.s = clamp01(hsl.s);\n        return tinycolor(hsl);\n    };\n    tinycolor.saturate = function (color, amount) {\n        amount = (amount === 0) ? 0 : (amount || 10);\n        var hsl = tinycolor(color).toHsl();\n        hsl.s += amount / 100;\n        hsl.s = clamp01(hsl.s);\n        return tinycolor(hsl);\n    };\n    tinycolor.greyscale = function(color) {\n        return tinycolor.desaturate(color, 100);\n    };\n    tinycolor.lighten = function(color, amount) {\n        amount = (amount === 0) ? 0 : (amount || 10);\n        var hsl = tinycolor(color).toHsl();\n        hsl.l += amount / 100;\n        hsl.l = clamp01(hsl.l);\n        return tinycolor(hsl);\n    };\n    tinycolor.darken = function (color, amount) {\n        amount = (amount === 0) ? 0 : (amount || 10);\n        var hsl = tinycolor(color).toHsl();\n        hsl.l -= amount / 100;\n        hsl.l = clamp01(hsl.l);\n        return tinycolor(hsl);\n    };\n    tinycolor.complement = function(color) {\n        var hsl = tinycolor(color).toHsl();\n        hsl.h = (hsl.h + 180) % 360;\n        return tinycolor(hsl);\n    };\n\n\n    // Combination Functions\n    // ---------------------\n    // Thanks to jQuery xColor for some of the ideas behind these\n    // <https://github.com/infusion/jQuery-xcolor/blob/master/jquery.xcolor.js>\n\n    tinycolor.triad = function(color) {\n        var hsl = tinycolor(color).toHsl();\n        var h = hsl.h;\n        return [\n            tinycolor(color),\n            tinycolor({ h: (h + 120) % 360, s: hsl.s, l: hsl.l }),\n            tinycolor({ h: (h + 240) % 360, s: hsl.s, l: hsl.l })\n        ];\n    };\n    tinycolor.tetrad = function(color) {\n        var hsl = tinycolor(color).toHsl();\n        var h = hsl.h;\n        return [\n            tinycolor(color),\n            tinycolor({ h: (h + 90) % 360, s: hsl.s, l: hsl.l }),\n            tinycolor({ h: (h + 180) % 360, s: hsl.s, l: hsl.l }),\n            tinycolor({ h: (h + 270) % 360, s: hsl.s, l: hsl.l })\n        ];\n    };\n    tinycolor.splitcomplement = function(color) {\n        var hsl = tinycolor(color).toHsl();\n        var h = hsl.h;\n        return [\n            tinycolor(color),\n            tinycolor({ h: (h + 72) % 360, s: hsl.s, l: hsl.l}),\n            tinycolor({ h: (h + 216) % 360, s: hsl.s, l: hsl.l})\n        ];\n    };\n    tinycolor.analogous = function(color, results, slices) {\n        results = results || 6;\n        slices = slices || 30;\n\n        var hsl = tinycolor(color).toHsl();\n        var part = 360 / slices;\n        var ret = [tinycolor(color)];\n\n        for (hsl.h = ((hsl.h - (part * results >> 1)) + 720) % 360; --results; ) {\n            hsl.h = (hsl.h + part) % 360;\n            ret.push(tinycolor(hsl));\n        }\n        return ret;\n    };\n    tinycolor.monochromatic = function(color, results) {\n        results = results || 6;\n        var hsv = tinycolor(color).toHsv();\n        var h = hsv.h, s = hsv.s, v = hsv.v;\n        var ret = [];\n        var modification = 1 / results;\n\n        while (results--) {\n            ret.push(tinycolor({ h: h, s: s, v: v}));\n            v = (v + modification) % 1;\n        }\n\n        return ret;\n    };\n\n\n    // Readability Functions\n    // ---------------------\n    // <http://www.w3.org/TR/AERT#color-contrast>\n\n    // `readability`\n    // Analyze the 2 colors and returns an object with the following properties:\n    //    `brightness`: difference in brightness between the two colors\n    //    `color`: difference in color/hue between the two colors\n    tinycolor.readability = function(color1, color2) {\n        var a = tinycolor(color1).toRgb();\n        var b = tinycolor(color2).toRgb();\n        var brightnessA = (a.r * 299 + a.g * 587 + a.b * 114) / 1000;\n        var brightnessB = (b.r * 299 + b.g * 587 + b.b * 114) / 1000;\n        var colorDiff = (\n            Math.max(a.r, b.r) - Math.min(a.r, b.r) +\n            Math.max(a.g, b.g) - Math.min(a.g, b.g) +\n            Math.max(a.b, b.b) - Math.min(a.b, b.b)\n        );\n\n        return {\n            brightness: Math.abs(brightnessA - brightnessB),\n            color: colorDiff\n        };\n    };\n\n    // `readable`\n    // http://www.w3.org/TR/AERT#color-contrast\n    // Ensure that foreground and background color combinations provide sufficient contrast.\n    // *Example*\n    //    tinycolor.readable(\"#000\", \"#111\") => false\n    tinycolor.readable = function(color1, color2) {\n        var readability = tinycolor.readability(color1, color2);\n        return readability.brightness > 125 && readability.color > 500;\n    };\n\n    // `mostReadable`\n    // Given a base color and a list of possible foreground or background\n    // colors for that base, returns the most readable color.\n    // *Example*\n    //    tinycolor.mostReadable(\"#123\", [\"#fff\", \"#000\"]) => \"#000\"\n    tinycolor.mostReadable = function(baseColor, colorList) {\n        var bestColor = null;\n        var bestScore = 0;\n        var bestIsReadable = false;\n        for (var i=0; i < colorList.length; i++) {\n\n            // We normalize both around the \"acceptable\" breaking point,\n            // but rank brightness constrast higher than hue.\n\n            var readability = tinycolor.readability(baseColor, colorList[i]);\n            var readable = readability.brightness > 125 && readability.color > 500;\n            var score = 3 * (readability.brightness / 125) + (readability.color / 500);\n\n            if ((readable && ! bestIsReadable) ||\n                (readable && bestIsReadable && score > bestScore) ||\n                ((! readable) && (! bestIsReadable) && score > bestScore)) {\n                bestIsReadable = readable;\n                bestScore = score;\n                bestColor = tinycolor(colorList[i]);\n            }\n        }\n        return bestColor;\n    };\n\n\n    // Big List of Colors\n    // ------------------\n    // <http://www.w3.org/TR/css3-color/#svg-color>\n    var names = tinycolor.names = {\n        aliceblue: \"f0f8ff\",\n        antiquewhite: \"faebd7\",\n        aqua: \"0ff\",\n        aquamarine: \"7fffd4\",\n        azure: \"f0ffff\",\n        beige: \"f5f5dc\",\n        bisque: \"ffe4c4\",\n        black: \"000\",\n        blanchedalmond: \"ffebcd\",\n        blue: \"00f\",\n        blueviolet: \"8a2be2\",\n        brown: \"a52a2a\",\n        burlywood: \"deb887\",\n        burntsienna: \"ea7e5d\",\n        cadetblue: \"5f9ea0\",\n        chartreuse: \"7fff00\",\n        chocolate: \"d2691e\",\n        coral: \"ff7f50\",\n        cornflowerblue: \"6495ed\",\n        cornsilk: \"fff8dc\",\n        crimson: \"dc143c\",\n        cyan: \"0ff\",\n        darkblue: \"00008b\",\n        darkcyan: \"008b8b\",\n        darkgoldenrod: \"b8860b\",\n        darkgray: \"a9a9a9\",\n        darkgreen: \"006400\",\n        darkgrey: \"a9a9a9\",\n        darkkhaki: \"bdb76b\",\n        darkmagenta: \"8b008b\",\n        darkolivegreen: \"556b2f\",\n        darkorange: \"ff8c00\",\n        darkorchid: \"9932cc\",\n        darkred: \"8b0000\",\n        darksalmon: \"e9967a\",\n        darkseagreen: \"8fbc8f\",\n        darkslateblue: \"483d8b\",\n        darkslategray: \"2f4f4f\",\n        darkslategrey: \"2f4f4f\",\n        darkturquoise: \"00ced1\",\n        darkviolet: \"9400d3\",\n        deeppink: \"ff1493\",\n        deepskyblue: \"00bfff\",\n        dimgray: \"696969\",\n        dimgrey: \"696969\",\n        dodgerblue: \"1e90ff\",\n        firebrick: \"b22222\",\n        floralwhite: \"fffaf0\",\n        forestgreen: \"228b22\",\n        fuchsia: \"f0f\",\n        gainsboro: \"dcdcdc\",\n        ghostwhite: \"f8f8ff\",\n        gold: \"ffd700\",\n        goldenrod: \"daa520\",\n        gray: \"808080\",\n        green: \"008000\",\n        greenyellow: \"adff2f\",\n        grey: \"808080\",\n        honeydew: \"f0fff0\",\n        hotpink: \"ff69b4\",\n        indianred: \"cd5c5c\",\n        indigo: \"4b0082\",\n        ivory: \"fffff0\",\n        khaki: \"f0e68c\",\n        lavender: \"e6e6fa\",\n        lavenderblush: \"fff0f5\",\n        lawngreen: \"7cfc00\",\n        lemonchiffon: \"fffacd\",\n        lightblue: \"add8e6\",\n        lightcoral: \"f08080\",\n        lightcyan: \"e0ffff\",\n        lightgoldenrodyellow: \"fafad2\",\n        lightgray: \"d3d3d3\",\n        lightgreen: \"90ee90\",\n        lightgrey: \"d3d3d3\",\n        lightpink: \"ffb6c1\",\n        lightsalmon: \"ffa07a\",\n        lightseagreen: \"20b2aa\",\n        lightskyblue: \"87cefa\",\n        lightslategray: \"789\",\n        lightslategrey: \"789\",\n        lightsteelblue: \"b0c4de\",\n        lightyellow: \"ffffe0\",\n        lime: \"0f0\",\n        limegreen: \"32cd32\",\n        linen: \"faf0e6\",\n        magenta: \"f0f\",\n        maroon: \"800000\",\n        mediumaquamarine: \"66cdaa\",\n        mediumblue: \"0000cd\",\n        mediumorchid: \"ba55d3\",\n        mediumpurple: \"9370db\",\n        mediumseagreen: \"3cb371\",\n        mediumslateblue: \"7b68ee\",\n        mediumspringgreen: \"00fa9a\",\n        mediumturquoise: \"48d1cc\",\n        mediumvioletred: \"c71585\",\n        midnightblue: \"191970\",\n        mintcream: \"f5fffa\",\n        mistyrose: \"ffe4e1\",\n        moccasin: \"ffe4b5\",\n        navajowhite: \"ffdead\",\n        navy: \"000080\",\n        oldlace: \"fdf5e6\",\n        olive: \"808000\",\n        olivedrab: \"6b8e23\",\n        orange: \"ffa500\",\n        orangered: \"ff4500\",\n        orchid: \"da70d6\",\n        palegoldenrod: \"eee8aa\",\n        palegreen: \"98fb98\",\n        paleturquoise: \"afeeee\",\n        palevioletred: \"db7093\",\n        papayawhip: \"ffefd5\",\n        peachpuff: \"ffdab9\",\n        peru: \"cd853f\",\n        pink: \"ffc0cb\",\n        plum: \"dda0dd\",\n        powderblue: \"b0e0e6\",\n        purple: \"800080\",\n        red: \"f00\",\n        rosybrown: \"bc8f8f\",\n        royalblue: \"4169e1\",\n        saddlebrown: \"8b4513\",\n        salmon: \"fa8072\",\n        sandybrown: \"f4a460\",\n        seagreen: \"2e8b57\",\n        seashell: \"fff5ee\",\n        sienna: \"a0522d\",\n        silver: \"c0c0c0\",\n        skyblue: \"87ceeb\",\n        slateblue: \"6a5acd\",\n        slategray: \"708090\",\n        slategrey: \"708090\",\n        snow: \"fffafa\",\n        springgreen: \"00ff7f\",\n        steelblue: \"4682b4\",\n        tan: \"d2b48c\",\n        teal: \"008080\",\n        thistle: \"d8bfd8\",\n        tomato: \"ff6347\",\n        turquoise: \"40e0d0\",\n        violet: \"ee82ee\",\n        wheat: \"f5deb3\",\n        white: \"fff\",\n        whitesmoke: \"f5f5f5\",\n        yellow: \"ff0\",\n        yellowgreen: \"9acd32\"\n    };\n\n    // Make it easy to access colors via `hexNames[hex]`\n    var hexNames = tinycolor.hexNames = flip(names);\n\n\n    // Utilities\n    // ---------\n\n    // `{ 'name1': 'val1' }` becomes `{ 'val1': 'name1' }`\n    function flip(o) {\n        var flipped = { };\n        for (var i in o) {\n            if (o.hasOwnProperty(i)) {\n                flipped[o[i]] = i;\n            }\n        }\n        return flipped;\n    }\n\n    // Return a valid alpha value [0,1] with all invalid values being set to 1\n    function boundAlpha(a) {\n        a = parseFloat(a);\n\n        if (isNaN(a) || a < 0 || a > 1) {\n            a = 1;\n        }\n\n        return a;\n    }\n\n    // Take input from [0, n] and return it as [0, 1]\n    function bound01(n, max) {\n        if (isOnePointZero(n)) { n = \"100%\"; }\n\n        var processPercent = isPercentage(n);\n        n = mathMin(max, mathMax(0, parseFloat(n)));\n\n        // Automatically convert percentage into number\n        if (processPercent) {\n            n = parseInt(n * max, 10) / 100;\n        }\n\n        // Handle floating point rounding errors\n        if ((math.abs(n - max) < 0.000001)) {\n            return 1;\n        }\n\n        // Convert into [0, 1] range if it isn't already\n        return (n % max) / parseFloat(max);\n    }\n\n    // Force a number between 0 and 1\n    function clamp01(val) {\n        return mathMin(1, mathMax(0, val));\n    }\n\n    // Parse a base-16 hex value into a base-10 integer\n    function parseIntFromHex(val) {\n        return parseInt(val, 16);\n    }\n\n    // Need to handle 1.0 as 100%, since once it is a number, there is no difference between it and 1\n    // <http://stackoverflow.com/questions/7422072/javascript-how-to-detect-number-as-a-decimal-including-1-0>\n    function isOnePointZero(n) {\n        return typeof n == \"string\" && n.indexOf('.') != -1 && parseFloat(n) === 1;\n    }\n\n    // Check to see if string passed in is a percentage\n    function isPercentage(n) {\n        return typeof n === \"string\" && n.indexOf('%') != -1;\n    }\n\n    // Force a hex value to have 2 characters\n    function pad2(c) {\n        return c.length == 1 ? '0' + c : '' + c;\n    }\n\n    // Replace a decimal with it's percentage value\n    function convertToPercentage(n) {\n        if (n <= 1) {\n            n = (n * 100) + \"%\";\n        }\n\n        return n;\n    }\n\n    // Converts a decimal to a hex value\n    function convertDecimalToHex(d) {\n        return Math.round(parseFloat(d) * 255).toString(16);\n    }\n    // Converts a hex value to a decimal\n    function convertHexToDecimal(h) {\n        return (parseIntFromHex(h) / 255);\n    }\n\n    var matchers = (function() {\n\n        // <http://www.w3.org/TR/css3-values/#integers>\n        var CSS_INTEGER = \"[-\\\\+]?\\\\d+%?\";\n\n        // <http://www.w3.org/TR/css3-values/#number-value>\n        var CSS_NUMBER = \"[-\\\\+]?\\\\d*\\\\.\\\\d+%?\";\n\n        // Allow positive/negative integer/number.  Don't capture the either/or, just the entire outcome.\n        var CSS_UNIT = \"(?:\" + CSS_NUMBER + \")|(?:\" + CSS_INTEGER + \")\";\n\n        // Actual matching.\n        // Parentheses and commas are optional, but not required.\n        // Whitespace can take the place of commas or opening paren\n        var PERMISSIVE_MATCH3 = \"[\\\\s|\\\\(]+(\" + CSS_UNIT + \")[,|\\\\s]+(\" + CSS_UNIT + \")[,|\\\\s]+(\" + CSS_UNIT + \")\\\\s*\\\\)?\";\n        var PERMISSIVE_MATCH4 = \"[\\\\s|\\\\(]+(\" + CSS_UNIT + \")[,|\\\\s]+(\" + CSS_UNIT + \")[,|\\\\s]+(\" + CSS_UNIT + \")[,|\\\\s]+(\" + CSS_UNIT + \")\\\\s*\\\\)?\";\n\n        return {\n            rgb: new RegExp(\"rgb\" + PERMISSIVE_MATCH3),\n            rgba: new RegExp(\"rgba\" + PERMISSIVE_MATCH4),\n            hsl: new RegExp(\"hsl\" + PERMISSIVE_MATCH3),\n            hsla: new RegExp(\"hsla\" + PERMISSIVE_MATCH4),\n            hsv: new RegExp(\"hsv\" + PERMISSIVE_MATCH3),\n            hex3: /^([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/,\n            hex6: /^([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/,\n            hex8: /^([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/\n        };\n    })();\n\n    // `stringInputToObject`\n    // Permissive string parsing.  Take in a number of formats, and output an object\n    // based on detected format.  Returns `{ r, g, b }` or `{ h, s, l }` or `{ h, s, v}`\n    function stringInputToObject(color) {\n\n        color = color.replace(trimLeft,'').replace(trimRight, '').toLowerCase();\n        var named = false;\n        if (names[color]) {\n            color = names[color];\n            named = true;\n        }\n        else if (color == 'transparent') {\n            return { r: 0, g: 0, b: 0, a: 0, format: \"name\" };\n        }\n\n        // Try to match string input using regular expressions.\n        // Keep most of the number bounding out of this function - don't worry about [0,1] or [0,100] or [0,360]\n        // Just return an object and let the conversion functions handle that.\n        // This way the result will be the same whether the tinycolor is initialized with string or object.\n        var match;\n        if ((match = matchers.rgb.exec(color))) {\n            return { r: match[1], g: match[2], b: match[3] };\n        }\n        if ((match = matchers.rgba.exec(color))) {\n            return { r: match[1], g: match[2], b: match[3], a: match[4] };\n        }\n        if ((match = matchers.hsl.exec(color))) {\n            return { h: match[1], s: match[2], l: match[3] };\n        }\n        if ((match = matchers.hsla.exec(color))) {\n            return { h: match[1], s: match[2], l: match[3], a: match[4] };\n        }\n        if ((match = matchers.hsv.exec(color))) {\n            return { h: match[1], s: match[2], v: match[3] };\n        }\n        if ((match = matchers.hex8.exec(color))) {\n            return {\n                a: convertHexToDecimal(match[1]),\n                r: parseIntFromHex(match[2]),\n                g: parseIntFromHex(match[3]),\n                b: parseIntFromHex(match[4]),\n                format: named ? \"name\" : \"hex8\"\n            };\n        }\n        if ((match = matchers.hex6.exec(color))) {\n            return {\n                r: parseIntFromHex(match[1]),\n                g: parseIntFromHex(match[2]),\n                b: parseIntFromHex(match[3]),\n                format: named ? \"name\" : \"hex\"\n            };\n        }\n        if ((match = matchers.hex3.exec(color))) {\n            return {\n                r: parseIntFromHex(match[1] + '' + match[1]),\n                g: parseIntFromHex(match[2] + '' + match[2]),\n                b: parseIntFromHex(match[3] + '' + match[3]),\n                format: named ? \"name\" : \"hex\"\n            };\n        }\n\n        return false;\n    }\n\n    // Expose tinycolor to window, does not need to run in non-browser context.\n    window.tinycolor = tinycolor;\n\n    })();\n\n\n    $(function () {\n        if ($.fn.spectrum.load) {\n            $.fn.spectrum.processNativeColorInputs();\n        }\n    });\n\n})(window, jQuery);\n"
  },
  {
    "path": "flowable-ui-web/modeler/libs/angular-strap_2.1.6/angular-strap.js",
    "content": "/**\n * angular-strap\n * @version v2.1.6 - 2015-01-11\n * @link http://mgcrea.github.io/angular-strap\n * @author Olivier Louvignes (olivier@mg-crea.com)\n * @license MIT License, http://www.opensource.org/licenses/MIT\n */\n(function(window, document, undefined) {\n'use strict';\n// Source: module.js\nangular.module('mgcrea.ngStrap', [\n  'mgcrea.ngStrap.modal',\n  'mgcrea.ngStrap.aside',\n  'mgcrea.ngStrap.alert',\n  'mgcrea.ngStrap.button',\n  'mgcrea.ngStrap.select',\n  'mgcrea.ngStrap.datepicker',\n  'mgcrea.ngStrap.timepicker',\n  'mgcrea.ngStrap.navbar',\n  'mgcrea.ngStrap.tooltip',\n  'mgcrea.ngStrap.popover',\n  'mgcrea.ngStrap.dropdown',\n  'mgcrea.ngStrap.typeahead',\n  'mgcrea.ngStrap.scrollspy',\n  'mgcrea.ngStrap.affix',\n  'mgcrea.ngStrap.tab',\n  'mgcrea.ngStrap.collapse'\n]);\n\n// Source: affix.js\nangular.module('mgcrea.ngStrap.affix', ['mgcrea.ngStrap.helpers.dimensions', 'mgcrea.ngStrap.helpers.debounce'])\n\n  .provider('$affix', function() {\n\n    var defaults = this.defaults = {\n      offsetTop: 'auto'\n    };\n\n    this.$get = [\"$window\", \"debounce\", \"dimensions\", function($window, debounce, dimensions) {\n\n      var bodyEl = angular.element($window.document.body);\n      var windowEl = angular.element($window);\n\n      function AffixFactory(element, config) {\n\n        var $affix = {};\n\n        // Common vars\n        var options = angular.extend({}, defaults, config);\n        var targetEl = options.target;\n\n        // Initial private vars\n        var reset = 'affix affix-top affix-bottom',\n            setWidth = false,\n            initialAffixTop = 0,\n            initialOffsetTop = 0,\n            offsetTop = 0,\n            offsetBottom = 0,\n            affixed = null,\n            unpin = null;\n\n        var parent = element.parent();\n        // Options: custom parent\n        if (options.offsetParent) {\n          if (options.offsetParent.match(/^\\d+$/)) {\n            for (var i = 0; i < (options.offsetParent * 1) - 1; i++) {\n              parent = parent.parent();\n            }\n          }\n          else {\n            parent = angular.element(options.offsetParent);\n          }\n        }\n\n        $affix.init = function() {\n\n          this.$parseOffsets();\n          initialOffsetTop = dimensions.offset(element[0]).top + initialAffixTop;\n          setWidth = !element[0].style.width;\n\n          // Bind events\n          targetEl.on('scroll', this.checkPosition);\n          targetEl.on('click', this.checkPositionWithEventLoop);\n          windowEl.on('resize', this.$debouncedOnResize);\n\n          // Both of these checkPosition() calls are necessary for the case where\n          // the user hits refresh after scrolling to the bottom of the page.\n          this.checkPosition();\n          this.checkPositionWithEventLoop();\n\n        };\n\n        $affix.destroy = function() {\n\n          // Unbind events\n          targetEl.off('scroll', this.checkPosition);\n          targetEl.off('click', this.checkPositionWithEventLoop);\n          windowEl.off('resize', this.$debouncedOnResize);\n\n        };\n\n        $affix.checkPositionWithEventLoop = function() {\n\n          // IE 9 throws an error if we use 'this' instead of '$affix'\n          // in this setTimeout call\n          setTimeout($affix.checkPosition, 1);\n\n        };\n\n        $affix.checkPosition = function() {\n          // if (!this.$element.is(':visible')) return\n\n          var scrollTop = getScrollTop();\n          var position = dimensions.offset(element[0]);\n          var elementHeight = dimensions.height(element[0]);\n\n          // Get required affix class according to position\n          var affix = getRequiredAffixClass(unpin, position, elementHeight);\n\n          // Did affix status changed this last check?\n          if(affixed === affix) return;\n          affixed = affix;\n\n          // Add proper affix class\n          element.removeClass(reset).addClass('affix' + ((affix !== 'middle') ? '-' + affix : ''));\n\n          if(affix === 'top') {\n            unpin = null;\n            element.css('position', (options.offsetParent) ? '' : 'relative');\n            if(setWidth) {\n              element.css('width', '');\n            }\n            element.css('top', '');\n          } else if(affix === 'bottom') {\n            if (options.offsetUnpin) {\n              unpin = -(options.offsetUnpin * 1);\n            }\n            else {\n              // Calculate unpin threshold when affixed to bottom.\n              // Hopefully the browser scrolls pixel by pixel.\n              unpin = position.top - scrollTop;\n            }\n            if(setWidth) {\n              element.css('width', '');\n            }\n            element.css('position', (options.offsetParent) ? '' : 'relative');\n            element.css('top', (options.offsetParent) ? '' : ((bodyEl[0].offsetHeight - offsetBottom - elementHeight - initialOffsetTop) + 'px'));\n          } else { // affix === 'middle'\n            unpin = null;\n            if(setWidth) {\n              element.css('width', element[0].offsetWidth + 'px');\n            }\n            element.css('position', 'fixed');\n            element.css('top', initialAffixTop + 'px');\n          }\n\n        };\n\n        $affix.$onResize = function() {\n          $affix.$parseOffsets();\n          $affix.checkPosition();\n        };\n        $affix.$debouncedOnResize = debounce($affix.$onResize, 50);\n\n        $affix.$parseOffsets = function() {\n          var initialPosition = element.css('position');\n          // Reset position to calculate correct offsetTop\n          element.css('position', (options.offsetParent) ? '' : 'relative');\n\n          if(options.offsetTop) {\n            if(options.offsetTop === 'auto') {\n              options.offsetTop = '+0';\n            }\n            if(options.offsetTop.match(/^[-+]\\d+$/)) {\n              initialAffixTop = - options.offsetTop * 1;\n              if(options.offsetParent) {\n                offsetTop = dimensions.offset(parent[0]).top + (options.offsetTop * 1);\n              }\n              else {\n                offsetTop = dimensions.offset(element[0]).top - dimensions.css(element[0], 'marginTop', true) + (options.offsetTop * 1);\n              }\n            }\n            else {\n              offsetTop = options.offsetTop * 1;\n            }\n          }\n\n          if(options.offsetBottom) {\n            if(options.offsetParent && options.offsetBottom.match(/^[-+]\\d+$/)) {\n              // add 1 pixel due to rounding problems...\n              offsetBottom = getScrollHeight() - (dimensions.offset(parent[0]).top + dimensions.height(parent[0])) + (options.offsetBottom * 1) + 1;\n            }\n            else {\n              offsetBottom = options.offsetBottom * 1;\n            }\n          }\n\n          // Bring back the element's position after calculations\n          element.css('position', initialPosition);\n        };\n\n        // Private methods\n\n        function getRequiredAffixClass(unpin, position, elementHeight) {\n\n          var scrollTop = getScrollTop();\n          var scrollHeight = getScrollHeight();\n\n          if(scrollTop <= offsetTop) {\n            return 'top';\n          } else if(unpin !== null && (scrollTop + unpin <= position.top)) {\n            return 'middle';\n          } else if(offsetBottom !== null && (position.top + elementHeight + initialAffixTop >= scrollHeight - offsetBottom)) {\n            return 'bottom';\n          } else {\n            return 'middle';\n          }\n\n        }\n\n        function getScrollTop() {\n          return targetEl[0] === $window ? $window.pageYOffset : targetEl[0].scrollTop;\n        }\n\n        function getScrollHeight() {\n          return targetEl[0] === $window ? $window.document.body.scrollHeight : targetEl[0].scrollHeight;\n        }\n\n        $affix.init();\n        return $affix;\n\n      }\n\n      return AffixFactory;\n\n    }];\n\n  })\n\n  .directive('bsAffix', [\"$affix\", \"$window\", function($affix, $window) {\n\n    return {\n      restrict: 'EAC',\n      require: '^?bsAffixTarget',\n      link: function postLink(scope, element, attr, affixTarget) {\n\n        var options = {scope: scope, offsetTop: 'auto', target: affixTarget ? affixTarget.$element : angular.element($window)};\n        angular.forEach(['offsetTop', 'offsetBottom', 'offsetParent', 'offsetUnpin'], function(key) {\n          if(angular.isDefined(attr[key])) options[key] = attr[key];\n        });\n\n        var affix = $affix(element, options);\n        scope.$on('$destroy', function() {\n          affix && affix.destroy();\n          options = null;\n          affix = null;\n        });\n\n      }\n    };\n\n  }])\n\n  .directive('bsAffixTarget', function() {\n    return {\n      controller: [\"$element\", function($element) {\n        this.$element = $element;\n      }]\n    };\n  });\n\n// Source: alert.js\n// @BUG: following snippet won't compile correctly\n// @TODO: submit issue to core\n// '<span ng-if=\"title\"><strong ng-bind=\"title\"></strong>&nbsp;</span><span ng-bind-html=\"content\"></span>' +\n\nangular.module('mgcrea.ngStrap.alert', ['mgcrea.ngStrap.modal'])\n\n  .provider('$alert', function() {\n\n    var defaults = this.defaults = {\n      animation: 'am-fade',\n      prefixClass: 'alert',\n      prefixEvent: 'alert',\n      placement: null,\n      template: 'alert/alert.tpl.html',\n      container: false,\n      element: null,\n      backdrop: false,\n      keyboard: true,\n      show: true,\n      // Specific options\n      duration: false,\n      type: false,\n      dismissable: true\n    };\n\n    this.$get = [\"$modal\", \"$timeout\", function($modal, $timeout) {\n\n      function AlertFactory(config) {\n\n        var $alert = {};\n\n        // Common vars\n        var options = angular.extend({}, defaults, config);\n\n        $alert = $modal(options);\n\n        // Support scope as string options [/*title, content, */ type, dismissable]\n        $alert.$scope.dismissable = !!options.dismissable;\n        if(options.type) {\n          $alert.$scope.type = options.type;\n        }\n\n        // Support auto-close duration\n        var show = $alert.show;\n        if(options.duration) {\n          $alert.show = function() {\n            show();\n            $timeout(function() {\n              $alert.hide();\n            }, options.duration * 1000);\n          };\n        }\n\n        return $alert;\n\n      }\n\n      return AlertFactory;\n\n    }];\n\n  })\n\n  .directive('bsAlert', [\"$window\", \"$sce\", \"$alert\", function($window, $sce, $alert) {\n\n    var requestAnimationFrame = $window.requestAnimationFrame || $window.setTimeout;\n\n    return {\n      restrict: 'EAC',\n      scope: true,\n      link: function postLink(scope, element, attr, transclusion) {\n\n        // Directive options\n        var options = {scope: scope, element: element, show: false};\n        angular.forEach(['template', 'placement', 'keyboard', 'html', 'container', 'animation', 'duration', 'dismissable'], function(key) {\n          if(angular.isDefined(attr[key])) options[key] = attr[key];\n        });\n\n        // Support scope as data-attrs\n        angular.forEach(['title', 'content', 'type'], function(key) {\n          attr[key] && attr.$observe(key, function(newValue, oldValue) {\n            scope[key] = $sce.trustAsHtml(newValue);\n          });\n        });\n\n        // Support scope as an object\n        attr.bsAlert && scope.$watch(attr.bsAlert, function(newValue, oldValue) {\n          if(angular.isObject(newValue)) {\n            angular.extend(scope, newValue);\n          } else {\n            scope.content = newValue;\n          }\n        }, true);\n\n        // Initialize alert\n        var alert = $alert(options);\n\n        // Trigger\n        element.on(attr.trigger || 'click', alert.toggle);\n\n        // Garbage collection\n        scope.$on('$destroy', function() {\n          if (alert) alert.destroy();\n          options = null;\n          alert = null;\n        });\n\n      }\n    };\n\n  }]);\n\n// Source: aside.js\nangular.module('mgcrea.ngStrap.aside', ['mgcrea.ngStrap.modal'])\n\n  .provider('$aside', function() {\n\n    var defaults = this.defaults = {\n      animation: 'am-fade-and-slide-right',\n      prefixClass: 'aside',\n      prefixEvent: 'aside',\n      placement: 'right',\n      template: 'aside/aside.tpl.html',\n      contentTemplate: false,\n      container: false,\n      element: null,\n      backdrop: true,\n      keyboard: true,\n      html: false,\n      show: true\n    };\n\n    this.$get = [\"$modal\", function($modal) {\n\n      function AsideFactory(config) {\n\n        var $aside = {};\n\n        // Common vars\n        var options = angular.extend({}, defaults, config);\n\n        $aside = $modal(options);\n\n        return $aside;\n\n      }\n\n      return AsideFactory;\n\n    }];\n\n  })\n\n  .directive('bsAside', [\"$window\", \"$sce\", \"$aside\", function($window, $sce, $aside) {\n\n    var requestAnimationFrame = $window.requestAnimationFrame || $window.setTimeout;\n\n    return {\n      restrict: 'EAC',\n      scope: true,\n      link: function postLink(scope, element, attr, transclusion) {\n        // Directive options\n        var options = {scope: scope, element: element, show: false};\n        angular.forEach(['template', 'contentTemplate', 'placement', 'backdrop', 'keyboard', 'html', 'container', 'animation'], function(key) {\n          if(angular.isDefined(attr[key])) options[key] = attr[key];\n        });\n\n        // Support scope as data-attrs\n        angular.forEach(['title', 'content'], function(key) {\n          attr[key] && attr.$observe(key, function(newValue, oldValue) {\n            scope[key] = $sce.trustAsHtml(newValue);\n          });\n        });\n\n        // Support scope as an object\n        attr.bsAside && scope.$watch(attr.bsAside, function(newValue, oldValue) {\n          if(angular.isObject(newValue)) {\n            angular.extend(scope, newValue);\n          } else {\n            scope.content = newValue;\n          }\n        }, true);\n\n        // Initialize aside\n        var aside = $aside(options);\n\n        // Trigger\n        element.on(attr.trigger || 'click', aside.toggle);\n\n        // Garbage collection\n        scope.$on('$destroy', function() {\n          if (aside) aside.destroy();\n          options = null;\n          aside = null;\n        });\n\n      }\n    };\n\n  }]);\n\n// Source: button.js\nangular.module('mgcrea.ngStrap.button', [])\n\n  .provider('$button', function() {\n\n    var defaults = this.defaults = {\n      activeClass:'active',\n      toggleEvent:'click'\n    };\n\n    this.$get = function() {\n      return {defaults: defaults};\n    };\n\n  })\n\n  .directive('bsCheckboxGroup', function() {\n\n    return {\n      restrict: 'A',\n      require: 'ngModel',\n      compile: function postLink(element, attr) {\n        element.attr('data-toggle', 'buttons');\n        element.removeAttr('ng-model');\n        var children = element[0].querySelectorAll('input[type=\"checkbox\"]');\n        angular.forEach(children, function(child) {\n          var childEl = angular.element(child);\n          childEl.attr('bs-checkbox', '');\n          childEl.attr('ng-model', attr.ngModel + '.' + childEl.attr('value'));\n        });\n      }\n\n    };\n\n  })\n\n  .directive('bsCheckbox', [\"$button\", \"$$rAF\", function($button, $$rAF) {\n\n    var defaults = $button.defaults;\n    var constantValueRegExp = /^(true|false|\\d+)$/;\n\n    return {\n      restrict: 'A',\n      require: 'ngModel',\n      link: function postLink(scope, element, attr, controller) {\n\n        var options = defaults;\n\n        // Support label > input[type=\"checkbox\"]\n        var isInput = element[0].nodeName === 'INPUT';\n        var activeElement = isInput ? element.parent() : element;\n\n        var trueValue = angular.isDefined(attr.trueValue) ? attr.trueValue : true;\n        if(constantValueRegExp.test(attr.trueValue)) {\n          trueValue = scope.$eval(attr.trueValue);\n        }\n        var falseValue = angular.isDefined(attr.falseValue) ? attr.falseValue : false;\n        if(constantValueRegExp.test(attr.falseValue)) {\n          falseValue = scope.$eval(attr.falseValue);\n        }\n\n        // Parse exotic values\n        var hasExoticValues = typeof trueValue !== 'boolean' || typeof falseValue !== 'boolean';\n        if(hasExoticValues) {\n          controller.$parsers.push(function(viewValue) {\n            // console.warn('$parser', element.attr('ng-model'), 'viewValue', viewValue);\n            return viewValue ? trueValue : falseValue;\n          });\n          // modelValue -> $formatters -> viewValue\n          controller.$formatters.push(function(modelValue) {\n             // console.warn('$formatter(\"%s\"): modelValue=%o (%o)', element.attr('ng-model'), modelValue, typeof modelValue);\n             return angular.equals(modelValue, trueValue);\n          });\n          // Fix rendering for exotic values\n          scope.$watch(attr.ngModel, function(newValue, oldValue) {\n            controller.$render();\n          });\n        }\n\n        // model -> view\n        controller.$render = function () {\n          // console.warn('$render', element.attr('ng-model'), 'controller.$modelValue', typeof controller.$modelValue, controller.$modelValue, 'controller.$viewValue', typeof controller.$viewValue, controller.$viewValue);\n          var isActive = angular.equals(controller.$modelValue, trueValue);\n          $$rAF(function() {\n            if(isInput) element[0].checked = isActive;\n            activeElement.toggleClass(options.activeClass, isActive);\n          });\n        };\n\n        // view -> model\n        element.bind(options.toggleEvent, function() {\n          scope.$apply(function () {\n            // console.warn('!click', element.attr('ng-model'), 'controller.$viewValue', typeof controller.$viewValue, controller.$viewValue, 'controller.$modelValue', typeof controller.$modelValue, controller.$modelValue);\n            if(!isInput) {\n              controller.$setViewValue(!activeElement.hasClass('active'));\n            }\n            if(!hasExoticValues) {\n              controller.$render();\n            }\n          });\n        });\n\n      }\n\n    };\n\n  }])\n\n  .directive('bsRadioGroup', function() {\n\n    return {\n      restrict: 'A',\n      require: 'ngModel',\n      compile: function postLink(element, attr) {\n        element.attr('data-toggle', 'buttons');\n        element.removeAttr('ng-model');\n        var children = element[0].querySelectorAll('input[type=\"radio\"]');\n        angular.forEach(children, function(child) {\n          angular.element(child).attr('bs-radio', '');\n          angular.element(child).attr('ng-model', attr.ngModel);\n        });\n      }\n\n    };\n\n  })\n\n  .directive('bsRadio', [\"$button\", \"$$rAF\", function($button, $$rAF) {\n\n    var defaults = $button.defaults;\n    var constantValueRegExp = /^(true|false|\\d+)$/;\n\n    return {\n      restrict: 'A',\n      require: 'ngModel',\n      link: function postLink(scope, element, attr, controller) {\n\n        var options = defaults;\n\n        // Support `label > input[type=\"radio\"]` markup\n        var isInput = element[0].nodeName === 'INPUT';\n        var activeElement = isInput ? element.parent() : element;\n\n        var value = constantValueRegExp.test(attr.value) ? scope.$eval(attr.value) : attr.value;\n\n        // model -> view\n        controller.$render = function () {\n          // console.warn('$render', element.attr('value'), 'controller.$modelValue', typeof controller.$modelValue, controller.$modelValue, 'controller.$viewValue', typeof controller.$viewValue, controller.$viewValue);\n          var isActive = angular.equals(controller.$modelValue, value);\n          $$rAF(function() {\n            if(isInput) element[0].checked = isActive;\n            activeElement.toggleClass(options.activeClass, isActive);\n          });\n        };\n\n        // view -> model\n        element.bind(options.toggleEvent, function() {\n          scope.$apply(function () {\n            // console.warn('!click', element.attr('value'), 'controller.$viewValue', typeof controller.$viewValue, controller.$viewValue, 'controller.$modelValue', typeof controller.$modelValue, controller.$modelValue);\n            controller.$setViewValue(value);\n            controller.$render();\n          });\n        });\n\n      }\n\n    };\n\n  }]);\n\n// Source: collapse.js\nangular.module('mgcrea.ngStrap.collapse', [])\n\n  .provider('$collapse', function() {\n\n    var defaults = this.defaults = {\n      animation: 'am-collapse',\n      disallowToggle: false,\n      activeClass: 'in',\n      startCollapsed: false,\n      allowMultiple: false\n    };\n\n    var controller = this.controller = function($scope, $element, $attrs) {\n      var self = this;\n\n      // Attributes options\n      self.$options = angular.copy(defaults);\n      angular.forEach(['animation', 'disallowToggle', 'activeClass', 'startCollapsed', 'allowMultiple'], function (key) {\n        if(angular.isDefined($attrs[key])) self.$options[key] = $attrs[key];\n      });\n\n      self.$toggles = [];\n      self.$targets = [];\n\n      self.$viewChangeListeners = [];\n\n      self.$registerToggle = function(element) {\n        self.$toggles.push(element);\n      };\n      self.$registerTarget = function(element) {\n        self.$targets.push(element);\n      };\n\n      self.$unregisterToggle = function(element) {\n        var index = self.$toggles.indexOf(element);\n        // remove toggle from $toggles array\n        self.$toggles.splice(index, 1);\n      };\n      self.$unregisterTarget = function(element) {\n        var index = self.$targets.indexOf(element);\n\n        // remove element from $targets array\n        self.$targets.splice(index, 1);\n\n        if (self.$options.allowMultiple) {\n          // remove target index from $active array values\n          deactivateItem(element);\n        }\n\n        // fix active item indexes\n        fixActiveItemIndexes(index);\n\n        self.$viewChangeListeners.forEach(function(fn) {\n          fn();\n        });\n      };\n\n      // use array to store all the currently open panels\n      self.$targets.$active = !self.$options.startCollapsed ? [0] : [];\n      self.$setActive = $scope.$setActive = function(value) {\n        if(angular.isArray(value)) {\n          self.$targets.$active = angular.copy(value);\n        }\n        else if(!self.$options.disallowToggle) {\n          // toogle element active status\n          isActive(value) ? deactivateItem(value) : activateItem(value);\n        } else {\n          activateItem(value);\n        }\n\n        self.$viewChangeListeners.forEach(function(fn) {\n          fn();\n        });\n      };\n\n      self.$activeIndexes = function() {\n        return self.$options.allowMultiple ? self.$targets.$active :\n          self.$targets.$active.length === 1 ? self.$targets.$active[0] : -1;\n      };\n\n      function fixActiveItemIndexes(index) {\n        // item with index was removed, so we\n        // need to adjust other items index values\n        var activeIndexes = self.$targets.$active;\n        for(var i = 0; i < activeIndexes.length; i++) {\n          if (index < activeIndexes[i]) {\n            activeIndexes[i] = activeIndexes[i] - 1;\n          }\n\n          // the last item is active, so we need to\n          // adjust its index\n          if (activeIndexes[i] === self.$targets.length) {\n            activeIndexes[i] = self.$targets.length - 1;\n          }\n        }\n      }\n\n      function isActive(value) {\n        var activeItems = self.$targets.$active;\n        return activeItems.indexOf(value) === -1 ? false : true;\n      }\n\n      function deactivateItem(value) {\n        var index = self.$targets.$active.indexOf(value);\n        if (index !== -1) {\n          self.$targets.$active.splice(index, 1);\n        }\n      }\n\n      function activateItem(value) {\n        if (!self.$options.allowMultiple) {\n          // remove current selected item\n          self.$targets.$active.splice(0, 1);\n        }\n\n        if (self.$targets.$active.indexOf(value) === -1) {\n          self.$targets.$active.push(value);\n        }\n      }\n\n    };\n\n    this.$get = function() {\n      var $collapse = {};\n      $collapse.defaults = defaults;\n      $collapse.controller = controller;\n      return $collapse;\n    };\n\n  })\n\n  .directive('bsCollapse', [\"$window\", \"$animate\", \"$collapse\", function($window, $animate, $collapse) {\n\n    var defaults = $collapse.defaults;\n\n    return {\n      require: ['?ngModel', 'bsCollapse'],\n      controller: ['$scope', '$element', '$attrs', $collapse.controller],\n      link: function postLink(scope, element, attrs, controllers) {\n\n        var ngModelCtrl = controllers[0];\n        var bsCollapseCtrl = controllers[1];\n\n        if(ngModelCtrl) {\n\n          // Update the modelValue following\n          bsCollapseCtrl.$viewChangeListeners.push(function() {\n            ngModelCtrl.$setViewValue(bsCollapseCtrl.$activeIndexes());\n          });\n\n          // modelValue -> $formatters -> viewValue\n          ngModelCtrl.$formatters.push(function(modelValue) {\n            // console.warn('$formatter(\"%s\"): modelValue=%o (%o)', element.attr('ng-model'), modelValue, typeof modelValue);\n            if (angular.isArray(modelValue)) {\n              // model value is an array, so just replace\n              // the active items directly\n              bsCollapseCtrl.$setActive(modelValue);\n            }\n            else {\n              var activeIndexes = bsCollapseCtrl.$activeIndexes();\n\n              if (angular.isArray(activeIndexes)) {\n                // we have an array of selected indexes\n                if (activeIndexes.indexOf(modelValue * 1) === -1) {\n                  // item with modelValue index is not active\n                  bsCollapseCtrl.$setActive(modelValue * 1);\n                }\n              }\n              else if (activeIndexes !== modelValue * 1) {\n                bsCollapseCtrl.$setActive(modelValue * 1);\n              }\n            }\n            return modelValue;\n          });\n\n        }\n\n      }\n    };\n\n  }])\n\n  .directive('bsCollapseToggle', function() {\n\n    return {\n      require: ['^?ngModel', '^bsCollapse'],\n      link: function postLink(scope, element, attrs, controllers) {\n\n        var ngModelCtrl = controllers[0];\n        var bsCollapseCtrl = controllers[1];\n\n        // Add base attr\n        element.attr('data-toggle', 'collapse');\n\n        // Push pane to parent bsCollapse controller\n        bsCollapseCtrl.$registerToggle(element);\n\n        // remove toggle from collapse controller when toggle is destroyed\n        scope.$on('$destroy', function() {\n          bsCollapseCtrl.$unregisterToggle(element);\n        });\n\n        element.on('click', function() {\n          var index = attrs.bsCollapseToggle || bsCollapseCtrl.$toggles.indexOf(element);\n          bsCollapseCtrl.$setActive(index * 1);\n          scope.$apply();\n        });\n\n      }\n    };\n\n  })\n\n  .directive('bsCollapseTarget', [\"$animate\", function($animate) {\n\n    return {\n      require: ['^?ngModel', '^bsCollapse'],\n      // scope: true,\n      link: function postLink(scope, element, attrs, controllers) {\n\n        var ngModelCtrl = controllers[0];\n        var bsCollapseCtrl = controllers[1];\n\n        // Add base class\n        element.addClass('collapse');\n\n        // Add animation class\n        if(bsCollapseCtrl.$options.animation) {\n          element.addClass(bsCollapseCtrl.$options.animation);\n        }\n\n        // Push pane to parent bsCollapse controller\n        bsCollapseCtrl.$registerTarget(element);\n\n        // remove pane target from collapse controller when target is destroyed\n        scope.$on('$destroy', function() {\n          bsCollapseCtrl.$unregisterTarget(element);\n        });\n\n        function render() {\n          var index = bsCollapseCtrl.$targets.indexOf(element);\n          var active = bsCollapseCtrl.$activeIndexes();\n          var action = 'removeClass';\n          if (angular.isArray(active)) {\n            if (active.indexOf(index) !== -1) {\n              action = 'addClass';\n            }\n          }\n          else if (index === active) {\n            action = 'addClass';\n          }\n\n          $animate[action](element, bsCollapseCtrl.$options.activeClass);\n        }\n\n        bsCollapseCtrl.$viewChangeListeners.push(function() {\n          render();\n        });\n        render();\n\n      }\n    };\n\n  }]);\n\n// Source: datepicker.js\nangular.module('mgcrea.ngStrap.datepicker', [\n  'mgcrea.ngStrap.helpers.dateParser',\n  'mgcrea.ngStrap.helpers.dateFormatter',\n  'mgcrea.ngStrap.tooltip'])\n\n  .provider('$datepicker', function() {\n\n    var defaults = this.defaults = {\n      animation: 'am-fade',\n      prefixClass: 'datepicker',\n      placement: 'bottom-left',\n      template: 'datepicker/datepicker.tpl.html',\n      trigger: 'focus',\n      container: false,\n      keyboard: true,\n      html: false,\n      delay: 0,\n      // lang: $locale.id,\n      useNative: false,\n      dateType: 'date',\n      dateFormat: 'shortDate',\n      modelDateFormat: null,\n      dayFormat: 'dd',\n      monthFormat: 'MMM',\n      yearFormat: 'yyyy',\n      monthTitleFormat: 'MMMM yyyy',\n      yearTitleFormat: 'yyyy',\n      strictFormat: false,\n      autoclose: false,\n      minDate: -Infinity,\n      maxDate: +Infinity,\n      startView: 0,\n      minView: 0,\n      startWeek: 0,\n      daysOfWeekDisabled: '',\n      iconLeft: 'glyphicon glyphicon-chevron-left',\n      iconRight: 'glyphicon glyphicon-chevron-right'\n    };\n\n    this.$get = [\"$window\", \"$document\", \"$rootScope\", \"$sce\", \"$dateFormatter\", \"datepickerViews\", \"$tooltip\", \"$timeout\", function($window, $document, $rootScope, $sce, $dateFormatter, datepickerViews, $tooltip, $timeout) {\n\n      var bodyEl = angular.element($window.document.body);\n      var isNative = /(ip(a|o)d|iphone|android)/ig.test($window.navigator.userAgent);\n      var isTouch = ('createTouch' in $window.document) && isNative;\n      if(!defaults.lang) defaults.lang = $dateFormatter.getDefaultLocale();\n\n      function DatepickerFactory(element, controller, config) {\n\n        var $datepicker = $tooltip(element, angular.extend({}, defaults, config));\n        var parentScope = config.scope;\n        var options = $datepicker.$options;\n        var scope = $datepicker.$scope;\n        if(options.startView) options.startView -= options.minView;\n\n        // View vars\n\n        var pickerViews = datepickerViews($datepicker);\n        $datepicker.$views = pickerViews.views;\n        var viewDate = pickerViews.viewDate;\n        scope.$mode = options.startView;\n        scope.$iconLeft = options.iconLeft;\n        scope.$iconRight = options.iconRight;\n        var $picker = $datepicker.$views[scope.$mode];\n\n        // Scope methods\n\n        scope.$select = function(date) {\n          $datepicker.select(date);\n        };\n        scope.$selectPane = function(value) {\n          $datepicker.$selectPane(value);\n        };\n        scope.$toggleMode = function() {\n          $datepicker.setMode((scope.$mode + 1) % $datepicker.$views.length);\n        };\n\n        // Public methods\n\n        $datepicker.update = function(date) {\n          // console.warn('$datepicker.update() newValue=%o', date);\n          if(angular.isDate(date) && !isNaN(date.getTime())) {\n            $datepicker.$date = date;\n            $picker.update.call($picker, date);\n          }\n          // Build only if pristine\n          $datepicker.$build(true);\n        };\n\n        $datepicker.updateDisabledDates = function(dateRanges) {\n          options.disabledDateRanges = dateRanges;\n          for(var i = 0, l = scope.rows.length; i < l; i++) {\n            angular.forEach(scope.rows[i], $datepicker.$setDisabledEl);\n          }\n        };\n\n        $datepicker.select = function(date, keep) {\n          // console.warn('$datepicker.select', date, scope.$mode);\n          if(!angular.isDate(controller.$dateValue)) controller.$dateValue = new Date(date);\n          if(!scope.$mode || keep) {\n            controller.$setViewValue(angular.copy(date));\n            controller.$render();\n            if(options.autoclose && !keep) {\n              $timeout(function() { $datepicker.hide(true); });\n            }\n          } else {\n            angular.extend(viewDate, {year: date.getFullYear(), month: date.getMonth(), date: date.getDate()});\n            $datepicker.setMode(scope.$mode - 1);\n            $datepicker.$build();\n          }\n        };\n\n        $datepicker.setMode = function(mode) {\n          // console.warn('$datepicker.setMode', mode);\n          scope.$mode = mode;\n          $picker = $datepicker.$views[scope.$mode];\n          $datepicker.$build();\n        };\n\n        // Protected methods\n\n        $datepicker.$build = function(pristine) {\n          // console.warn('$datepicker.$build() viewDate=%o', viewDate);\n          if(pristine === true && $picker.built) return;\n          if(pristine === false && !$picker.built) return;\n          $picker.build.call($picker);\n        };\n\n        $datepicker.$updateSelected = function() {\n          for(var i = 0, l = scope.rows.length; i < l; i++) {\n            angular.forEach(scope.rows[i], updateSelected);\n          }\n        };\n\n        $datepicker.$isSelected = function(date) {\n          return $picker.isSelected(date);\n        };\n\n        $datepicker.$setDisabledEl = function(el) {\n          el.disabled = $picker.isDisabled(el.date);\n        };\n\n        $datepicker.$selectPane = function(value) {\n          var steps = $picker.steps;\n          // set targetDate to first day of month to avoid problems with\n          // date values rollover. This assumes the viewDate does not\n          // depend on the day of the month\n          var targetDate = new Date(Date.UTC(viewDate.year + ((steps.year || 0) * value), viewDate.month + ((steps.month || 0) * value), 1));\n          angular.extend(viewDate, {year: targetDate.getUTCFullYear(), month: targetDate.getUTCMonth(), date: targetDate.getUTCDate()});\n          $datepicker.$build();\n        };\n\n        $datepicker.$onMouseDown = function(evt) {\n          // Prevent blur on mousedown on .dropdown-menu\n          evt.preventDefault();\n          evt.stopPropagation();\n          // Emulate click for mobile devices\n          if(isTouch) {\n            var targetEl = angular.element(evt.target);\n            if(targetEl[0].nodeName.toLowerCase() !== 'button') {\n              targetEl = targetEl.parent();\n            }\n            targetEl.triggerHandler('click');\n          }\n        };\n\n        $datepicker.$onKeyDown = function(evt) {\n          if (!/(38|37|39|40|13)/.test(evt.keyCode) || evt.shiftKey || evt.altKey) return;\n          evt.preventDefault();\n          evt.stopPropagation();\n\n          if(evt.keyCode === 13) {\n            if(!scope.$mode) {\n              return $datepicker.hide(true);\n            } else {\n              return scope.$apply(function() { $datepicker.setMode(scope.$mode - 1); });\n            }\n          }\n\n          // Navigate with keyboard\n          $picker.onKeyDown(evt);\n          parentScope.$digest();\n        };\n\n        // Private\n\n        function updateSelected(el) {\n          el.selected = $datepicker.$isSelected(el.date);\n        }\n\n        function focusElement() {\n          element[0].focus();\n        }\n\n        // Overrides\n\n        var _init = $datepicker.init;\n        $datepicker.init = function() {\n          if(isNative && options.useNative) {\n            element.prop('type', 'date');\n            element.css('-webkit-appearance', 'textfield');\n            return;\n          } else if(isTouch) {\n            element.prop('type', 'text');\n            element.attr('readonly', 'true');\n            element.on('click', focusElement);\n          }\n          _init();\n        };\n\n        var _destroy = $datepicker.destroy;\n        $datepicker.destroy = function() {\n          if(isNative && options.useNative) {\n            element.off('click', focusElement);\n          }\n          _destroy();\n        };\n\n        var _show = $datepicker.show;\n        $datepicker.show = function() {\n          _show();\n          // use timeout to hookup the events to prevent\n          // event bubbling from being processed imediately.\n          $timeout(function() {\n            // if $datepicker is no longer showing, don't setup events\n            if(!$datepicker.$isShown) return;\n            $datepicker.$element.on(isTouch ? 'touchstart' : 'mousedown', $datepicker.$onMouseDown);\n            if(options.keyboard) {\n              element.on('keydown', $datepicker.$onKeyDown);\n            }\n          }, 0, false);\n        };\n\n        var _hide = $datepicker.hide;\n        $datepicker.hide = function(blur) {\n          if(!$datepicker.$isShown) return;\n          $datepicker.$element.off(isTouch ? 'touchstart' : 'mousedown', $datepicker.$onMouseDown);\n          if(options.keyboard) {\n            element.off('keydown', $datepicker.$onKeyDown);\n          }\n          _hide(blur);\n        };\n\n        return $datepicker;\n\n      }\n\n      DatepickerFactory.defaults = defaults;\n      return DatepickerFactory;\n\n    }];\n\n  })\n\n  .directive('bsDatepicker', [\"$window\", \"$parse\", \"$q\", \"$dateFormatter\", \"$dateParser\", \"$datepicker\", function($window, $parse, $q, $dateFormatter, $dateParser, $datepicker) {\n\n    var defaults = $datepicker.defaults;\n    var isNative = /(ip(a|o)d|iphone|android)/ig.test($window.navigator.userAgent);\n\n    return {\n      restrict: 'EAC',\n      require: 'ngModel',\n      link: function postLink(scope, element, attr, controller) {\n\n        // Directive options\n        var options = {scope: scope, controller: controller};\n        angular.forEach(['placement', 'container', 'delay', 'trigger', 'keyboard', 'html', 'animation', 'template', 'autoclose', 'dateType', 'dateFormat', 'modelDateFormat', 'dayFormat', 'strictFormat', 'startWeek', 'startDate', 'useNative', 'lang', 'startView', 'minView', 'iconLeft', 'iconRight', 'daysOfWeekDisabled', 'id'], function(key) {\n          if(angular.isDefined(attr[key])) options[key] = attr[key];\n        });\n\n        // Visibility binding support\n        attr.bsShow && scope.$watch(attr.bsShow, function(newValue, oldValue) {\n          if(!datepicker || !angular.isDefined(newValue)) return;\n          if(angular.isString(newValue)) newValue = !!newValue.match(/true|,?(datepicker),?/i);\n          newValue === true ? datepicker.show() : datepicker.hide();\n        });\n\n        // Initialize datepicker\n        var datepicker = $datepicker(element, controller, options);\n        options = datepicker.$options;\n        // Set expected iOS format\n        if(isNative && options.useNative) options.dateFormat = 'yyyy-MM-dd';\n\n        var lang = options.lang;\n\n        var formatDate = function(date, format) {\n          return $dateFormatter.formatDate(date, format, lang);\n        };\n\n        var dateParser = $dateParser({format: options.dateFormat, lang: lang, strict: options.strictFormat});\n\n        // Observe attributes for changes\n        angular.forEach(['minDate', 'maxDate'], function(key) {\n          // console.warn('attr.$observe(%s)', key, attr[key]);\n          angular.isDefined(attr[key]) && attr.$observe(key, function(newValue) {\n            // console.warn('attr.$observe(%s)=%o', key, newValue);\n            datepicker.$options[key] = dateParser.getDateForAttribute(key, newValue);\n            // Build only if dirty\n            !isNaN(datepicker.$options[key]) && datepicker.$build(false);\n            validateAgainstMinMaxDate(controller.$dateValue);\n          });\n        });\n\n        // Watch model for changes\n        scope.$watch(attr.ngModel, function(newValue, oldValue) {\n          datepicker.update(controller.$dateValue);\n        }, true);\n\n        // Normalize undefined/null/empty array,\n        // so that we don't treat changing from undefined->null as a change.\n        function normalizeDateRanges(ranges) {\n          if (!ranges || !ranges.length) return null;\n          return ranges;\n        }\n\n        if (angular.isDefined(attr.disabledDates)) {\n          scope.$watch(attr.disabledDates, function(disabledRanges, previousValue) {\n            disabledRanges = normalizeDateRanges(disabledRanges);\n            previousValue = normalizeDateRanges(previousValue);\n\n            if (disabledRanges) {\n              datepicker.updateDisabledDates(disabledRanges);\n            }\n          });\n        }\n\n        function validateAgainstMinMaxDate(parsedDate) {\n          if (!angular.isDate(parsedDate)) return;\n          var isMinValid = isNaN(datepicker.$options.minDate) || parsedDate.getTime() >= datepicker.$options.minDate;\n          var isMaxValid = isNaN(datepicker.$options.maxDate) || parsedDate.getTime() <= datepicker.$options.maxDate;\n          var isValid = isMinValid && isMaxValid;\n          controller.$setValidity('date', isValid);\n          controller.$setValidity('min', isMinValid);\n          controller.$setValidity('max', isMaxValid);\n          // Only update the model when we have a valid date\n          if(isValid) controller.$dateValue = parsedDate;\n        }\n\n        // viewValue -> $parsers -> modelValue\n        controller.$parsers.unshift(function(viewValue) {\n          // console.warn('$parser(\"%s\"): viewValue=%o', element.attr('ng-model'), viewValue);\n          // Null values should correctly reset the model value & validity\n          if(!viewValue) {\n            controller.$setValidity('date', true);\n            // BREAKING CHANGE:\n            // return null (not undefined) when input value is empty, so angularjs 1.3\n            // ngModelController can go ahead and run validators, like ngRequired\n            return null;\n          }\n          var parsedDate = dateParser.parse(viewValue, controller.$dateValue);\n          if(!parsedDate || isNaN(parsedDate.getTime())) {\n            controller.$setValidity('date', false);\n            // return undefined, causes ngModelController to\n            // invalidate model value\n            return;\n          } else {\n            validateAgainstMinMaxDate(parsedDate);\n          }\n          if(options.dateType === 'string') {\n            return formatDate(parsedDate, options.modelDateFormat || options.dateFormat);\n          } else if(options.dateType === 'number') {\n            return controller.$dateValue.getTime();\n          } else if(options.dateType === 'unix') {\n            return controller.$dateValue.getTime() / 1000;\n          } else if(options.dateType === 'iso') {\n            return controller.$dateValue.toISOString();\n          } else {\n            return new Date(controller.$dateValue);\n          }\n        });\n\n        // modelValue -> $formatters -> viewValue\n        controller.$formatters.push(function(modelValue) {\n          // console.warn('$formatter(\"%s\"): modelValue=%o (%o)', element.attr('ng-model'), modelValue, typeof modelValue);\n          var date;\n          if(angular.isUndefined(modelValue) || modelValue === null) {\n            date = NaN;\n          } else if(angular.isDate(modelValue)) {\n            date = modelValue;\n          } else if(options.dateType === 'string') {\n            date = dateParser.parse(modelValue, null, options.modelDateFormat);\n          } else if(options.dateType === 'unix') {\n            date = new Date(modelValue * 1000);\n          } else {\n            date = new Date(modelValue);\n          }\n          // Setup default value?\n          // if(isNaN(date.getTime())) {\n          //   var today = new Date();\n          //   date = new Date(today.getFullYear(), today.getMonth(), today.getDate(), 0, 0, 0, 0);\n          // }\n          controller.$dateValue = date;\n          return getDateFormattedString();\n        });\n\n        // viewValue -> element\n        controller.$render = function() {\n          // console.warn('$render(\"%s\"): viewValue=%o', element.attr('ng-model'), controller.$viewValue);\n          element.val(getDateFormattedString());\n        };\n\n        function getDateFormattedString() {\n          return !controller.$dateValue || isNaN(controller.$dateValue.getTime()) ? '' : formatDate(controller.$dateValue, options.dateFormat);\n        }\n\n        // Garbage collection\n        scope.$on('$destroy', function() {\n          if(datepicker) datepicker.destroy();\n          options = null;\n          datepicker = null;\n        });\n\n      }\n    };\n\n  }])\n\n  .provider('datepickerViews', function() {\n\n    var defaults = this.defaults = {\n      dayFormat: 'dd',\n      daySplit: 7\n    };\n\n    // Split array into smaller arrays\n    function split(arr, size) {\n      var arrays = [];\n      while(arr.length > 0) {\n        arrays.push(arr.splice(0, size));\n      }\n      return arrays;\n    }\n\n    // Modulus operator\n    function mod(n, m) {\n      return ((n % m) + m) % m;\n    }\n\n    this.$get = [\"$dateFormatter\", \"$dateParser\", \"$sce\", function($dateFormatter, $dateParser, $sce) {\n\n      return function(picker) {\n\n        var scope = picker.$scope;\n        var options = picker.$options;\n\n        var lang = options.lang;\n        var formatDate = function(date, format) {\n          return $dateFormatter.formatDate(date, format, lang);\n        };\n        var dateParser = $dateParser({format: options.dateFormat, lang: lang, strict: options.strictFormat});\n\n        var weekDaysMin = $dateFormatter.weekdaysShort(lang);\n        var weekDaysLabels = weekDaysMin.slice(options.startWeek).concat(weekDaysMin.slice(0, options.startWeek));\n        var weekDaysLabelsHtml = $sce.trustAsHtml('<th class=\"dow text-center\">' + weekDaysLabels.join('</th><th class=\"dow text-center\">') + '</th>');\n\n        var startDate = picker.$date || (options.startDate ? dateParser.getDateForAttribute('startDate', options.startDate) : new Date());\n        var viewDate = {year: startDate.getFullYear(), month: startDate.getMonth(), date: startDate.getDate()};\n        var timezoneOffset = startDate.getTimezoneOffset() * 6e4;\n\n        var views = [{\n            format: options.dayFormat,\n            split: 7,\n            steps: { month: 1 },\n            update: function(date, force) {\n              if(!this.built || force || date.getFullYear() !== viewDate.year || date.getMonth() !== viewDate.month) {\n                angular.extend(viewDate, {year: picker.$date.getFullYear(), month: picker.$date.getMonth(), date: picker.$date.getDate()});\n                picker.$build();\n              } else if(date.getDate() !== viewDate.date) {\n                viewDate.date = picker.$date.getDate();\n                picker.$updateSelected();\n              }\n            },\n            build: function() {\n              var firstDayOfMonth = new Date(viewDate.year, viewDate.month, 1), firstDayOfMonthOffset = firstDayOfMonth.getTimezoneOffset();\n              var firstDate = new Date(+firstDayOfMonth - mod(firstDayOfMonth.getDay() - options.startWeek, 7) * 864e5), firstDateOffset = firstDate.getTimezoneOffset();\n              var today = new Date().toDateString();\n              // Handle daylight time switch\n              if(firstDateOffset !== firstDayOfMonthOffset) firstDate = new Date(+firstDate + (firstDateOffset - firstDayOfMonthOffset) * 60e3);\n              var days = [], day;\n              for(var i = 0; i < 42; i++) { // < 7 * 6\n                day = dateParser.daylightSavingAdjust(new Date(firstDate.getFullYear(), firstDate.getMonth(), firstDate.getDate() + i));\n                days.push({date: day, isToday: day.toDateString() === today, label: formatDate(day, this.format), selected: picker.$date && this.isSelected(day), muted: day.getMonth() !== viewDate.month, disabled: this.isDisabled(day)});\n              }\n              scope.title = formatDate(firstDayOfMonth, options.monthTitleFormat);\n              scope.showLabels = true;\n              scope.labels = weekDaysLabelsHtml;\n              scope.rows = split(days, this.split);\n              this.built = true;\n            },\n            isSelected: function(date) {\n              return picker.$date && date.getFullYear() === picker.$date.getFullYear() && date.getMonth() === picker.$date.getMonth() && date.getDate() === picker.$date.getDate();\n            },\n            isDisabled: function(date) {\n              var time = date.getTime();\n\n              // Disabled because of min/max date.\n              if (time < options.minDate || time > options.maxDate) return true;\n\n              // Disabled due to being a disabled day of the week\n              if (options.daysOfWeekDisabled.indexOf(date.getDay()) !== -1) return true;\n\n              // Disabled because of disabled date range.\n              if (options.disabledDateRanges) {\n                for (var i = 0; i < options.disabledDateRanges.length; i++) {\n                  if (time >= options.disabledDateRanges[i].start && time <= options.disabledDateRanges[i].end) {\n                    return true;\n                  }\n                }\n              }\n\n              return false;\n            },\n            onKeyDown: function(evt) {\n              if (!picker.$date) {\n                return;\n              }\n              var actualTime = picker.$date.getTime();\n              var newDate;\n\n              if(evt.keyCode === 37) newDate = new Date(actualTime - 1 * 864e5);\n              else if(evt.keyCode === 38) newDate = new Date(actualTime - 7 * 864e5);\n              else if(evt.keyCode === 39) newDate = new Date(actualTime + 1 * 864e5);\n              else if(evt.keyCode === 40) newDate = new Date(actualTime + 7 * 864e5);\n\n              if (!this.isDisabled(newDate)) picker.select(newDate, true);\n            }\n          }, {\n            name: 'month',\n            format: options.monthFormat,\n            split: 4,\n            steps: { year: 1 },\n            update: function(date, force) {\n              if(!this.built || date.getFullYear() !== viewDate.year) {\n                angular.extend(viewDate, {year: picker.$date.getFullYear(), month: picker.$date.getMonth(), date: picker.$date.getDate()});\n                picker.$build();\n              } else if(date.getMonth() !== viewDate.month) {\n                angular.extend(viewDate, {month: picker.$date.getMonth(), date: picker.$date.getDate()});\n                picker.$updateSelected();\n              }\n            },\n            build: function() {\n              var firstMonth = new Date(viewDate.year, 0, 1);\n              var months = [], month;\n              for (var i = 0; i < 12; i++) {\n                month = new Date(viewDate.year, i, 1);\n                months.push({date: month, label: formatDate(month, this.format), selected: picker.$isSelected(month), disabled: this.isDisabled(month)});\n              }\n              scope.title = formatDate(month, options.yearTitleFormat);\n              scope.showLabels = false;\n              scope.rows = split(months, this.split);\n              this.built = true;\n            },\n            isSelected: function(date) {\n              return picker.$date && date.getFullYear() === picker.$date.getFullYear() && date.getMonth() === picker.$date.getMonth();\n            },\n            isDisabled: function(date) {\n              var lastDate = +new Date(date.getFullYear(), date.getMonth() + 1, 0);\n              return lastDate < options.minDate || date.getTime() > options.maxDate;\n            },\n            onKeyDown: function(evt) {\n              if (!picker.$date) {\n                return;\n              }\n              var actualMonth = picker.$date.getMonth();\n              var newDate = new Date(picker.$date);\n\n              if(evt.keyCode === 37) newDate.setMonth(actualMonth - 1);\n              else if(evt.keyCode === 38) newDate.setMonth(actualMonth - 4);\n              else if(evt.keyCode === 39) newDate.setMonth(actualMonth + 1);\n              else if(evt.keyCode === 40) newDate.setMonth(actualMonth + 4);\n\n              if (!this.isDisabled(newDate)) picker.select(newDate, true);\n            }\n          }, {\n            name: 'year',\n            format: options.yearFormat,\n            split: 4,\n            steps: { year: 12 },\n            update: function(date, force) {\n              if(!this.built || force || parseInt(date.getFullYear()/20, 10) !== parseInt(viewDate.year/20, 10)) {\n                angular.extend(viewDate, {year: picker.$date.getFullYear(), month: picker.$date.getMonth(), date: picker.$date.getDate()});\n                picker.$build();\n              } else if(date.getFullYear() !== viewDate.year) {\n                angular.extend(viewDate, {year: picker.$date.getFullYear(), month: picker.$date.getMonth(), date: picker.$date.getDate()});\n                picker.$updateSelected();\n              }\n            },\n            build: function() {\n              var firstYear = viewDate.year - viewDate.year % (this.split * 3);\n              var years = [], year;\n              for (var i = 0; i < 12; i++) {\n                year = new Date(firstYear + i, 0, 1);\n                years.push({date: year, label: formatDate(year, this.format), selected: picker.$isSelected(year), disabled: this.isDisabled(year)});\n              }\n              scope.title = years[0].label + '-' + years[years.length - 1].label;\n              scope.showLabels = false;\n              scope.rows = split(years, this.split);\n              this.built = true;\n            },\n            isSelected: function(date) {\n              return picker.$date && date.getFullYear() === picker.$date.getFullYear();\n            },\n            isDisabled: function(date) {\n              var lastDate = +new Date(date.getFullYear() + 1, 0, 0);\n              return lastDate < options.minDate || date.getTime() > options.maxDate;\n            },\n            onKeyDown: function(evt) {\n              if (!picker.$date) {\n                return;\n              }\n              var actualYear = picker.$date.getFullYear(),\n                  newDate = new Date(picker.$date);\n\n              if(evt.keyCode === 37) newDate.setYear(actualYear - 1);\n              else if(evt.keyCode === 38) newDate.setYear(actualYear - 4);\n              else if(evt.keyCode === 39) newDate.setYear(actualYear + 1);\n              else if(evt.keyCode === 40) newDate.setYear(actualYear + 4);\n\n              if (!this.isDisabled(newDate)) picker.select(newDate, true);\n            }\n          }];\n\n        return {\n          views: options.minView ? Array.prototype.slice.call(views, options.minView) : views,\n          viewDate: viewDate\n        };\n\n      };\n\n    }];\n\n  });\n\n// Source: dropdown.js\nangular.module('mgcrea.ngStrap.dropdown', ['mgcrea.ngStrap.tooltip'])\n\n  .provider('$dropdown', function() {\n\n    var defaults = this.defaults = {\n      animation: 'am-fade',\n      prefixClass: 'dropdown',\n      placement: 'bottom-left',\n      template: 'dropdown/dropdown.tpl.html',\n      trigger: 'click',\n      container: false,\n      keyboard: true,\n      html: false,\n      delay: 0\n    };\n\n    this.$get = [\"$window\", \"$rootScope\", \"$tooltip\", \"$timeout\", function($window, $rootScope, $tooltip, $timeout) {\n\n      var bodyEl = angular.element($window.document.body);\n      var matchesSelector = Element.prototype.matchesSelector || Element.prototype.webkitMatchesSelector || Element.prototype.mozMatchesSelector || Element.prototype.msMatchesSelector || Element.prototype.oMatchesSelector;\n\n      function DropdownFactory(element, config) {\n\n        var $dropdown = {};\n\n        // Common vars\n        var options = angular.extend({}, defaults, config);\n        var scope = $dropdown.$scope = options.scope && options.scope.$new() || $rootScope.$new();\n\n        $dropdown = $tooltip(element, options);\n        var parentEl = element.parent();\n\n        // Protected methods\n\n        $dropdown.$onKeyDown = function(evt) {\n          if (!/(38|40)/.test(evt.keyCode)) return;\n          evt.preventDefault();\n          evt.stopPropagation();\n\n          // Retrieve focused index\n          var items = angular.element($dropdown.$element[0].querySelectorAll('li:not(.divider) a'));\n          if(!items.length) return;\n          var index;\n          angular.forEach(items, function(el, i) {\n            if(matchesSelector && matchesSelector.call(el, ':focus')) index = i;\n          });\n\n          // Navigate with keyboard\n          if(evt.keyCode === 38 && index > 0) index--;\n          else if(evt.keyCode === 40 && index < items.length - 1) index++;\n          else if(angular.isUndefined(index)) index = 0;\n          items.eq(index)[0].focus();\n\n        };\n\n        // Overrides\n\n        var show = $dropdown.show;\n        $dropdown.show = function() {\n          show();\n          // use timeout to hookup the events to prevent\n          // event bubbling from being processed imediately.\n          $timeout(function() {\n            options.keyboard && $dropdown.$element.on('keydown', $dropdown.$onKeyDown);\n            bodyEl.on('click', onBodyClick);\n          }, 0, false);\n          parentEl.hasClass('dropdown') && parentEl.addClass('open');\n        };\n\n        var hide = $dropdown.hide;\n        $dropdown.hide = function() {\n          if(!$dropdown.$isShown) return;\n          options.keyboard && $dropdown.$element.off('keydown', $dropdown.$onKeyDown);\n          bodyEl.off('click', onBodyClick);\n          parentEl.hasClass('dropdown') && parentEl.removeClass('open');\n          hide();\n        };\n\n        var destroy = $dropdown.destroy;\n        $dropdown.destroy = function() {\n          bodyEl.off('click', onBodyClick);\n          destroy();\n        };\n\n        // Private functions\n\n        function onBodyClick(evt) {\n          if(evt.target === element[0]) return;\n          return evt.target !== element[0] && $dropdown.hide();\n        }\n\n        return $dropdown;\n\n      }\n\n      return DropdownFactory;\n\n    }];\n\n  })\n\n  .directive('bsDropdown', [\"$window\", \"$sce\", \"$dropdown\", function($window, $sce, $dropdown) {\n\n    return {\n      restrict: 'EAC',\n      scope: true,\n      link: function postLink(scope, element, attr, transclusion) {\n\n        // Directive options\n        var options = {scope: scope};\n        angular.forEach(['placement', 'container', 'delay', 'trigger', 'keyboard', 'html', 'animation', 'template', 'id'], function(key) {\n          if(angular.isDefined(attr[key])) options[key] = attr[key];\n        });\n\n        // Support scope as an object\n        attr.bsDropdown && scope.$watch(attr.bsDropdown, function(newValue, oldValue) {\n          scope.content = newValue;\n        }, true);\n\n        // Visibility binding support\n        attr.bsShow && scope.$watch(attr.bsShow, function(newValue, oldValue) {\n          if(!dropdown || !angular.isDefined(newValue)) return;\n          if(angular.isString(newValue)) newValue = !!newValue.match(/true|,?(dropdown),?/i);\n          newValue === true ? dropdown.show() : dropdown.hide();\n        });\n\n        // Initialize dropdown\n        var dropdown = $dropdown(element, options);\n\n        // Garbage collection\n        scope.$on('$destroy', function() {\n          if (dropdown) dropdown.destroy();\n          options = null;\n          dropdown = null;\n        });\n\n      }\n    };\n\n  }]);\n\n// Source: date-formatter.js\nangular.module('mgcrea.ngStrap.helpers.dateFormatter', [])\n\n  .service('$dateFormatter', [\"$locale\", \"dateFilter\", function($locale, dateFilter) {\n\n    // The unused `lang` arguments are on purpose. The default implementation does not\n    // use them and it always uses the locale loaded into the `$locale` service.\n    // Custom implementations might use it, thus allowing different directives to\n    // have different languages.\n\n    this.getDefaultLocale = function() {\n      return $locale.id;\n    };\n\n    // Format is either a data format name, e.g. \"shortTime\" or \"fullDate\", or a date format\n    // Return either the corresponding date format or the given date format.\n    this.getDatetimeFormat = function(format, lang) {\n      return $locale.DATETIME_FORMATS[format] || format;\n    };\n\n    this.weekdaysShort = function(lang) {\n      return $locale.DATETIME_FORMATS.SHORTDAY;\n    };\n\n    function splitTimeFormat(format) {\n      return /(h+)([:\\.])?(m+)[ ]?(a?)/i.exec(format).slice(1);\n    }\n\n    // h:mm a => h\n    this.hoursFormat = function(timeFormat) {\n      return splitTimeFormat(timeFormat)[0];\n    };\n\n    // h:mm a => mm\n    this.minutesFormat = function(timeFormat) {\n      return splitTimeFormat(timeFormat)[2];\n    };\n\n    // h:mm a => :\n    this.timeSeparator = function(timeFormat) {\n      return splitTimeFormat(timeFormat)[1];\n    };\n\n    // h:mm a => true, H.mm => false\n    this.showAM = function(timeFormat) {\n      return !!splitTimeFormat(timeFormat)[3];\n    };\n\n    this.formatDate = function(date, format, lang){\n      return dateFilter(date, format);\n    };\n\n  }]);\n\n// Source: date-parser.js\nangular.module('mgcrea.ngStrap.helpers.dateParser', [])\n\n.provider('$dateParser', [\"$localeProvider\", function($localeProvider) {\n\n  // define a custom ParseDate object to use instead of native Date\n  // to avoid date values wrapping when setting date component values\n  function ParseDate() {\n    this.year = 1970;\n    this.month = 0;\n    this.day = 1;\n    this.hours = 0;\n    this.minutes = 0;\n    this.seconds = 0;\n    this.milliseconds = 0;\n  }\n\n  ParseDate.prototype.setMilliseconds = function(value) { this.milliseconds = value; };\n  ParseDate.prototype.setSeconds = function(value) { this.seconds = value; };\n  ParseDate.prototype.setMinutes = function(value) { this.minutes = value; };\n  ParseDate.prototype.setHours = function(value) { this.hours = value; };\n  ParseDate.prototype.getHours = function() { return this.hours; };\n  ParseDate.prototype.setDate = function(value) { this.day = value; };\n  ParseDate.prototype.setMonth = function(value) { this.month = value; };\n  ParseDate.prototype.setFullYear = function(value) { this.year = value; };\n  ParseDate.prototype.fromDate = function(value) {\n    this.year = value.getFullYear();\n    this.month = value.getMonth();\n    this.day = value.getDate();\n    this.hours = value.getHours();\n    this.minutes = value.getMinutes();\n    this.seconds = value.getSeconds();\n    this.milliseconds = value.getMilliseconds();\n    return this;\n  };\n\n  ParseDate.prototype.toDate = function() {\n    return new Date(this.year, this.month, this.day, this.hours, this.minutes, this.seconds, this.milliseconds);\n  };\n\n  var proto = ParseDate.prototype;\n\n  function noop() {\n  }\n\n  function isNumeric(n) {\n    return !isNaN(parseFloat(n)) && isFinite(n);\n  }\n\n  function indexOfCaseInsensitive(array, value) {\n    var len = array.length, str=value.toString().toLowerCase();\n    for (var i=0; i<len; i++) {\n      if (array[i].toLowerCase() === str) { return i; }\n    }\n    return -1; // Return -1 per the \"Array.indexOf()\" method.\n  }\n\n  var defaults = this.defaults = {\n    format: 'shortDate',\n    strict: false\n  };\n\n  this.$get = [\"$locale\", \"dateFilter\", function($locale, dateFilter) {\n\n    var DateParserFactory = function(config) {\n\n      var options = angular.extend({}, defaults, config);\n\n      var $dateParser = {};\n\n      var regExpMap = {\n        'sss'   : '[0-9]{3}',\n        'ss'    : '[0-5][0-9]',\n        's'     : options.strict ? '[1-5]?[0-9]' : '[0-9]|[0-5][0-9]',\n        'mm'    : '[0-5][0-9]',\n        'm'     : options.strict ? '[1-5]?[0-9]' : '[0-9]|[0-5][0-9]',\n        'HH'    : '[01][0-9]|2[0-3]',\n        'H'     : options.strict ? '1?[0-9]|2[0-3]' : '[01]?[0-9]|2[0-3]',\n        'hh'    : '[0][1-9]|[1][012]',\n        'h'     : options.strict ? '[1-9]|1[012]' : '0?[1-9]|1[012]',\n        'a'     : 'AM|PM',\n        'EEEE'  : $locale.DATETIME_FORMATS.DAY.join('|'),\n        'EEE'   : $locale.DATETIME_FORMATS.SHORTDAY.join('|'),\n        'dd'    : '0[1-9]|[12][0-9]|3[01]',\n        'd'     : options.strict ? '[1-9]|[1-2][0-9]|3[01]' : '0?[1-9]|[1-2][0-9]|3[01]',\n        'MMMM'  : $locale.DATETIME_FORMATS.MONTH.join('|'),\n        'MMM'   : $locale.DATETIME_FORMATS.SHORTMONTH.join('|'),\n        'MM'    : '0[1-9]|1[012]',\n        'M'     : options.strict ? '[1-9]|1[012]' : '0?[1-9]|1[012]',\n        'yyyy'  : '[1]{1}[0-9]{3}|[2]{1}[0-9]{3}',\n        'yy'    : '[0-9]{2}',\n        'y'     : options.strict ? '-?(0|[1-9][0-9]{0,3})' : '-?0*[0-9]{1,4}',\n      };\n\n      var setFnMap = {\n        'sss'   : proto.setMilliseconds,\n        'ss'    : proto.setSeconds,\n        's'     : proto.setSeconds,\n        'mm'    : proto.setMinutes,\n        'm'     : proto.setMinutes,\n        'HH'    : proto.setHours,\n        'H'     : proto.setHours,\n        'hh'    : proto.setHours,\n        'h'     : proto.setHours,\n        'EEEE'  : noop,\n        'EEE'   : noop,\n        'dd'    : proto.setDate,\n        'd'     : proto.setDate,\n        'a'     : function(value) { var hours = this.getHours() % 12; return this.setHours(value.match(/pm/i) ? hours + 12 : hours); },\n        'MMMM'  : function(value) { return this.setMonth(indexOfCaseInsensitive($locale.DATETIME_FORMATS.MONTH, value)); },\n        'MMM'   : function(value) { return this.setMonth(indexOfCaseInsensitive($locale.DATETIME_FORMATS.SHORTMONTH, value)); },\n        'MM'    : function(value) { return this.setMonth(1 * value - 1); },\n        'M'     : function(value) { return this.setMonth(1 * value - 1); },\n        'yyyy'  : proto.setFullYear,\n        'yy'    : function(value) { return this.setFullYear(2000 + 1 * value); },\n        'y'     : proto.setFullYear\n      };\n\n      var regex, setMap;\n\n      $dateParser.init = function() {\n        $dateParser.$format = $locale.DATETIME_FORMATS[options.format] || options.format;\n        regex = regExpForFormat($dateParser.$format);\n        setMap = setMapForFormat($dateParser.$format);\n      };\n\n      $dateParser.isValid = function(date) {\n        if(angular.isDate(date)) return !isNaN(date.getTime());\n        return regex.test(date);\n      };\n\n      $dateParser.parse = function(value, baseDate, format) {\n        // check for date format special names\n        if(format) format = $locale.DATETIME_FORMATS[format] || format;\n        if(angular.isDate(value)) value = dateFilter(value, format || $dateParser.$format);\n        var formatRegex = format ? regExpForFormat(format) : regex;\n        var formatSetMap = format ? setMapForFormat(format) : setMap;\n        var matches = formatRegex.exec(value);\n        if(!matches) return false;\n        // use custom ParseDate object to set parsed values\n        var date = baseDate && !isNaN(baseDate.getTime()) ? new ParseDate().fromDate(baseDate) : new ParseDate().fromDate(new Date(1970, 0, 1, 0));\n        for(var i = 0; i < matches.length - 1; i++) {\n          formatSetMap[i] && formatSetMap[i].call(date, matches[i+1]);\n        }\n        // convert back to native Date object\n        var newDate = date.toDate();\n\n        // check new native Date object for day values overflow\n        if (parseInt(date.day, 10) !== newDate.getDate()) {\n          return false;\n        }\n\n        return newDate;\n      };\n\n      $dateParser.getDateForAttribute = function(key, value) {\n        var date;\n\n        if(value === 'today') {\n          var today = new Date();\n          date = new Date(today.getFullYear(), today.getMonth(), today.getDate() + (key === 'maxDate' ? 1 : 0), 0, 0, 0, (key === 'minDate' ? 0 : -1));\n        } else if(angular.isString(value) && value.match(/^\".+\"$/)) { // Support {{ dateObj }}\n          date = new Date(value.substr(1, value.length - 2));\n        } else if(isNumeric(value)) {\n          date = new Date(parseInt(value, 10));\n        } else if (angular.isString(value) && 0 === value.length) { // Reset date\n          date = key === 'minDate' ? -Infinity : +Infinity;\n        } else {\n          date = new Date(value);\n        }\n\n        return date;\n      };\n\n      $dateParser.getTimeForAttribute = function(key, value) {\n        var time;\n\n        if(value === 'now') {\n          time = new Date().setFullYear(1970, 0, 1);\n        } else if(angular.isString(value) && value.match(/^\".+\"$/)) {\n          time = new Date(value.substr(1, value.length - 2)).setFullYear(1970, 0, 1);\n        } else if(isNumeric(value)) {\n          time = new Date(parseInt(value, 10)).setFullYear(1970, 0, 1);\n        } else if (angular.isString(value) && 0 === value.length) { // Reset time\n          time = key === 'minTime' ? -Infinity : +Infinity;\n        } else {\n          time = $dateParser.parse(value, new Date(1970, 0, 1, 0));\n        }\n\n        return time;\n      };\n\n      /* Handle switch to/from daylight saving.\n      * Hours may be non-zero on daylight saving cut-over:\n      * > 12 when midnight changeover, but then cannot generate\n      * midnight datetime, so jump to 1AM, otherwise reset.\n      * @param  date  (Date) the date to check\n      * @return  (Date) the corrected date\n      *\n      * __ copied from jquery ui datepicker __\n      */\n      $dateParser.daylightSavingAdjust = function(date) {\n        if (!date) {\n          return null;\n        }\n        date.setHours(date.getHours() > 12 ? date.getHours() + 2 : 0);\n        return date;\n      };\n\n      // Private functions\n\n      function setMapForFormat(format) {\n        var keys = Object.keys(setFnMap), i;\n        var map = [], sortedMap = [];\n        // Map to setFn\n        var clonedFormat = format;\n        for(i = 0; i < keys.length; i++) {\n          if(format.split(keys[i]).length > 1) {\n            var index = clonedFormat.search(keys[i]);\n            format = format.split(keys[i]).join('');\n            if(setFnMap[keys[i]]) {\n              map[index] = setFnMap[keys[i]];\n            }\n          }\n        }\n        // Sort result map\n        angular.forEach(map, function(v) {\n          // conditional required since angular.forEach broke around v1.2.21\n          // related pr: https://github.com/angular/angular.js/pull/8525\n          if(v) sortedMap.push(v);\n        });\n        return sortedMap;\n      }\n\n      function escapeReservedSymbols(text) {\n        return text.replace(/\\//g, '[\\\\/]').replace('/-/g', '[-]').replace(/\\./g, '[.]').replace(/\\\\s/g, '[\\\\s]');\n      }\n\n      function regExpForFormat(format) {\n        var keys = Object.keys(regExpMap), i;\n\n        var re = format;\n        // Abstract replaces to avoid collisions\n        for(i = 0; i < keys.length; i++) {\n          re = re.split(keys[i]).join('${' + i + '}');\n        }\n        // Replace abstracted values\n        for(i = 0; i < keys.length; i++) {\n          re = re.split('${' + i + '}').join('(' + regExpMap[keys[i]] + ')');\n        }\n        format = escapeReservedSymbols(format);\n\n        return new RegExp('^' + re + '$', ['i']);\n      }\n\n      $dateParser.init();\n      return $dateParser;\n\n    };\n\n    return DateParserFactory;\n\n  }];\n\n}]);\n\n// Source: debounce.js\nangular.module('mgcrea.ngStrap.helpers.debounce', [])\n\n// @source jashkenas/underscore\n// @url https://github.com/jashkenas/underscore/blob/1.5.2/underscore.js#L693\n.factory('debounce', [\"$timeout\", function($timeout) {\n  return function(func, wait, immediate) {\n    var timeout = null;\n    return function() {\n      var context = this,\n        args = arguments,\n        callNow = immediate && !timeout;\n      if(timeout) {\n        $timeout.cancel(timeout);\n      }\n      timeout = $timeout(function later() {\n        timeout = null;\n        if(!immediate) {\n          func.apply(context, args);\n        }\n      }, wait, false);\n      if(callNow) {\n        func.apply(context, args);\n      }\n      return timeout;\n    };\n  };\n}])\n\n\n// @source jashkenas/underscore\n// @url https://github.com/jashkenas/underscore/blob/1.5.2/underscore.js#L661\n.factory('throttle', [\"$timeout\", function($timeout) {\n  return function(func, wait, options) {\n    var timeout = null;\n    options || (options = {});\n    return function() {\n      var context = this,\n        args = arguments;\n      if(!timeout) {\n        if(options.leading !== false) {\n          func.apply(context, args);\n        }\n        timeout = $timeout(function later() {\n          timeout = null;\n          if(options.trailing !== false) {\n            func.apply(context, args);\n          }\n        }, wait, false);\n      }\n    };\n  };\n}]);\n\n// Source: dimensions.js\nangular.module('mgcrea.ngStrap.helpers.dimensions', [])\n\n  .factory('dimensions', [\"$document\", \"$window\", function($document, $window) {\n\n    var jqLite = angular.element;\n    var fn = {};\n\n    /**\n     * Test the element nodeName\n     * @param element\n     * @param name\n     */\n    var nodeName = fn.nodeName = function(element, name) {\n      return element.nodeName && element.nodeName.toLowerCase() === name.toLowerCase();\n    };\n\n    /**\n     * Returns the element computed style\n     * @param element\n     * @param prop\n     * @param extra\n     */\n    fn.css = function(element, prop, extra) {\n      var value;\n      if (element.currentStyle) { //IE\n        value = element.currentStyle[prop];\n      } else if (window.getComputedStyle) {\n        value = window.getComputedStyle(element)[prop];\n      } else {\n        value = element.style[prop];\n      }\n      return extra === true ? parseFloat(value) || 0 : value;\n    };\n\n    /**\n     * Provides read-only equivalent of jQuery's offset function:\n     * @required-by bootstrap-tooltip, bootstrap-affix\n     * @url http://api.jquery.com/offset/\n     * @param element\n     */\n    fn.offset = function(element) {\n      var boxRect = element.getBoundingClientRect();\n      var docElement = element.ownerDocument;\n      return {\n        width: boxRect.width || element.offsetWidth,\n        height: boxRect.height || element.offsetHeight,\n        top: boxRect.top + (window.pageYOffset || docElement.documentElement.scrollTop) - (docElement.documentElement.clientTop || 0),\n        left: boxRect.left + (window.pageXOffset || docElement.documentElement.scrollLeft) - (docElement.documentElement.clientLeft || 0)\n      };\n    };\n\n    /**\n     * Provides read-only equivalent of jQuery's position function\n     * @required-by bootstrap-tooltip, bootstrap-affix\n     * @url http://api.jquery.com/offset/\n     * @param element\n     */\n    fn.position = function(element) {\n\n      var offsetParentRect = {top: 0, left: 0},\n          offsetParentElement,\n          offset;\n\n      // Fixed elements are offset from window (parentOffset = {top:0, left: 0}, because it is it's only offset parent\n      if (fn.css(element, 'position') === 'fixed') {\n\n        // We assume that getBoundingClientRect is available when computed position is fixed\n        offset = element.getBoundingClientRect();\n\n      } else {\n\n        // Get *real* offsetParentElement\n        offsetParentElement = offsetParent(element);\n\n        // Get correct offsets\n        offset = fn.offset(element);\n        if (!nodeName(offsetParentElement, 'html')) {\n          offsetParentRect = fn.offset(offsetParentElement);\n        }\n\n        // Add offsetParent borders\n        offsetParentRect.top += fn.css(offsetParentElement, 'borderTopWidth', true);\n        offsetParentRect.left += fn.css(offsetParentElement, 'borderLeftWidth', true);\n      }\n\n      // Subtract parent offsets and element margins\n      return {\n        width: element.offsetWidth,\n        height: element.offsetHeight,\n        top: offset.top - offsetParentRect.top - fn.css(element, 'marginTop', true),\n        left: offset.left - offsetParentRect.left - fn.css(element, 'marginLeft', true)\n      };\n\n    };\n\n    /**\n     * Returns the closest, non-statically positioned offsetParent of a given element\n     * @required-by fn.position\n     * @param element\n     */\n    var offsetParent = function offsetParentElement(element) {\n      var docElement = element.ownerDocument;\n      var offsetParent = element.offsetParent || docElement;\n      if(nodeName(offsetParent, '#document')) return docElement.documentElement;\n      while(offsetParent && !nodeName(offsetParent, 'html') && fn.css(offsetParent, 'position') === 'static') {\n        offsetParent = offsetParent.offsetParent;\n      }\n      return offsetParent || docElement.documentElement;\n    };\n\n    /**\n     * Provides equivalent of jQuery's height function\n     * @required-by bootstrap-affix\n     * @url http://api.jquery.com/height/\n     * @param element\n     * @param outer\n     */\n    fn.height = function(element, outer) {\n      var value = element.offsetHeight;\n      if(outer) {\n        value += fn.css(element, 'marginTop', true) + fn.css(element, 'marginBottom', true);\n      } else {\n        value -= fn.css(element, 'paddingTop', true) + fn.css(element, 'paddingBottom', true) + fn.css(element, 'borderTopWidth', true) + fn.css(element, 'borderBottomWidth', true);\n      }\n      return value;\n    };\n\n    /**\n     * Provides equivalent of jQuery's width function\n     * @required-by bootstrap-affix\n     * @url http://api.jquery.com/width/\n     * @param element\n     * @param outer\n     */\n    fn.width = function(element, outer) {\n      var value = element.offsetWidth;\n      if(outer) {\n        value += fn.css(element, 'marginLeft', true) + fn.css(element, 'marginRight', true);\n      } else {\n        value -= fn.css(element, 'paddingLeft', true) + fn.css(element, 'paddingRight', true) + fn.css(element, 'borderLeftWidth', true) + fn.css(element, 'borderRightWidth', true);\n      }\n      return value;\n    };\n\n    return fn;\n\n  }]);\n\n// Source: parse-options.js\nangular.module('mgcrea.ngStrap.helpers.parseOptions', [])\n\n  .provider('$parseOptions', function() {\n\n    var defaults = this.defaults = {\n      regexp: /^\\s*(.*?)(?:\\s+as\\s+(.*?))?(?:\\s+group\\s+by\\s+(.*))?\\s+for\\s+(?:([\\$\\w][\\$\\w]*)|(?:\\(\\s*([\\$\\w][\\$\\w]*)\\s*,\\s*([\\$\\w][\\$\\w]*)\\s*\\)))\\s+in\\s+(.*?)(?:\\s+track\\s+by\\s+(.*?))?$/\n    };\n\n    this.$get = [\"$parse\", \"$q\", function($parse, $q) {\n\n      function ParseOptionsFactory(attr, config) {\n\n        var $parseOptions = {};\n\n        // Common vars\n        var options = angular.extend({}, defaults, config);\n        $parseOptions.$values = [];\n\n        // Private vars\n        var match, displayFn, valueName, keyName, groupByFn, valueFn, valuesFn;\n\n        $parseOptions.init = function() {\n          $parseOptions.$match = match = attr.match(options.regexp);\n          displayFn = $parse(match[2] || match[1]),\n          valueName = match[4] || match[6],\n          keyName = match[5],\n          groupByFn = $parse(match[3] || ''),\n          valueFn = $parse(match[2] ? match[1] : valueName),\n          valuesFn = $parse(match[7]);\n        };\n\n        $parseOptions.valuesFn = function(scope, controller) {\n          return $q.when(valuesFn(scope, controller))\n          .then(function(values) {\n            $parseOptions.$values = values ? parseValues(values, scope) : {};\n            return $parseOptions.$values;\n          });\n        };\n\n        $parseOptions.displayValue = function(modelValue) {\n          var scope = {};\n          scope[valueName] = modelValue;\n          return displayFn(scope);\n        };\n\n        // Private functions\n\n        function parseValues(values, scope) {\n          return values.map(function(match, index) {\n            var locals = {}, label, value;\n            locals[valueName] = match;\n            label = displayFn(scope, locals);\n            value = valueFn(scope, locals);\n            return {label: label, value: value, index: index};\n          });\n        }\n\n        $parseOptions.init();\n        return $parseOptions;\n\n      }\n\n      return ParseOptionsFactory;\n\n    }];\n\n  });\n\n// Source: raf.js\n(angular.version.minor < 3 && angular.version.dot < 14) && angular.module('ng')\n\n.factory('$$rAF', [\"$window\", \"$timeout\", function($window, $timeout) {\n\n  var requestAnimationFrame = $window.requestAnimationFrame ||\n                              $window.webkitRequestAnimationFrame ||\n                              $window.mozRequestAnimationFrame;\n\n  var cancelAnimationFrame = $window.cancelAnimationFrame ||\n                             $window.webkitCancelAnimationFrame ||\n                             $window.mozCancelAnimationFrame ||\n                             $window.webkitCancelRequestAnimationFrame;\n\n  var rafSupported = !!requestAnimationFrame;\n  var raf = rafSupported ?\n    function(fn) {\n      var id = requestAnimationFrame(fn);\n      return function() {\n        cancelAnimationFrame(id);\n      };\n    } :\n    function(fn) {\n      var timer = $timeout(fn, 16.66, false); // 1000 / 60 = 16.666\n      return function() {\n        $timeout.cancel(timer);\n      };\n    };\n\n  raf.supported = rafSupported;\n\n  return raf;\n\n}]);\n\n// .factory('$$animateReflow', function($$rAF, $document) {\n\n//   var bodyEl = $document[0].body;\n\n//   return function(fn) {\n//     //the returned function acts as the cancellation function\n//     return $$rAF(function() {\n//       //the line below will force the browser to perform a repaint\n//       //so that all the animated elements within the animation frame\n//       //will be properly updated and drawn on screen. This is\n//       //required to perform multi-class CSS based animations with\n//       //Firefox. DO NOT REMOVE THIS LINE.\n//       var a = bodyEl.offsetWidth + 1;\n//       fn();\n//     });\n//   };\n\n// });\n\n// Source: modal.js\nangular.module('mgcrea.ngStrap.modal', ['mgcrea.ngStrap.helpers.dimensions'])\n\n  .provider('$modal', function() {\n\n    var defaults = this.defaults = {\n      animation: 'am-fade',\n      backdropAnimation: 'am-fade',\n      prefixClass: 'modal',\n      prefixEvent: 'modal',\n      placement: 'top',\n      template: 'modal/modal.tpl.html',\n      contentTemplate: false,\n      container: false,\n      element: null,\n      backdrop: true,\n      keyboard: true,\n      html: false,\n      show: true\n    };\n\n    this.$get = [\"$window\", \"$rootScope\", \"$compile\", \"$q\", \"$templateCache\", \"$http\", \"$animate\", \"$timeout\", \"$sce\", \"dimensions\", function($window, $rootScope, $compile, $q, $templateCache, $http, $animate, $timeout, $sce, dimensions) {\n\n      var forEach = angular.forEach;\n      var trim = String.prototype.trim;\n      var requestAnimationFrame = $window.requestAnimationFrame || $window.setTimeout;\n      var bodyElement = angular.element($window.document.body);\n      var htmlReplaceRegExp = /ng-bind=\"/ig;\n\n      function ModalFactory(config) {\n\n        var $modal = {};\n\n        // Common vars\n        var options = $modal.$options = angular.extend({}, defaults, config);\n        $modal.$promise = fetchTemplate(options.template);\n        var scope = $modal.$scope = options.scope && options.scope.$new() || $rootScope.$new();\n        if(!options.element && !options.container) {\n          options.container = 'body';\n        }\n\n        // store $id to identify the triggering element in events\n        // give priority to options.id, otherwise, try to use\n        // element id if defined\n        $modal.$id = options.id || options.element && options.element.attr('id') || '';\n\n        // Support scope as string options\n        forEach(['title', 'content'], function(key) {\n          if(options[key]) scope[key] = $sce.trustAsHtml(options[key]);\n        });\n\n        // Provide scope helpers\n        scope.$hide = function() {\n          scope.$$postDigest(function() {\n            $modal.hide();\n          });\n        };\n        scope.$show = function() {\n          scope.$$postDigest(function() {\n            $modal.show();\n          });\n        };\n        scope.$toggle = function() {\n          scope.$$postDigest(function() {\n            $modal.toggle();\n          });\n        };\n        // Publish isShown as a protected var on scope\n        $modal.$isShown = scope.$isShown = false;\n\n        // Support contentTemplate option\n        if(options.contentTemplate) {\n          $modal.$promise = $modal.$promise.then(function(template) {\n            var templateEl = angular.element(template);\n            return fetchTemplate(options.contentTemplate)\n            .then(function(contentTemplate) {\n              var contentEl = findElement('[ng-bind=\"content\"]', templateEl[0]).removeAttr('ng-bind').html(contentTemplate);\n              // Drop the default footer as you probably don't want it if you use a custom contentTemplate\n              if(!config.template) contentEl.next().remove();\n              return templateEl[0].outerHTML;\n            });\n          });\n        }\n\n        // Fetch, compile then initialize modal\n        var modalLinker, modalElement;\n        var backdropElement = angular.element('<div class=\"' + options.prefixClass + '-backdrop\"/>');\n        $modal.$promise.then(function(template) {\n          if(angular.isObject(template)) template = template.data;\n          if(options.html) template = template.replace(htmlReplaceRegExp, 'ng-bind-html=\"');\n          template = trim.apply(template);\n          modalLinker = $compile(template);\n          $modal.init();\n        });\n\n        $modal.init = function() {\n\n          // Options: show\n          if(options.show) {\n            scope.$$postDigest(function() {\n              $modal.show();\n            });\n          }\n\n        };\n\n        $modal.destroy = function() {\n\n          // Remove element\n          if(modalElement) {\n            modalElement.remove();\n            modalElement = null;\n          }\n          if(backdropElement) {\n            backdropElement.remove();\n            backdropElement = null;\n          }\n\n          // Destroy scope\n          scope.$destroy();\n\n        };\n\n        $modal.show = function() {\n          if($modal.$isShown) return;\n\n          if(scope.$emit(options.prefixEvent + '.show.before', $modal).defaultPrevented) {\n            return;\n          }\n          var parent, after;\n          if(angular.isElement(options.container)) {\n            parent = options.container;\n            after = options.container[0].lastChild ? angular.element(options.container[0].lastChild) : null;\n          } else {\n            if (options.container) {\n              parent = findElement(options.container);\n              after = parent[0].lastChild ? angular.element(parent[0].lastChild) : null;\n            } else {\n              parent = null;\n              after = options.element;\n            }\n          }\n\n          // Fetch a cloned element linked from template\n          modalElement = $modal.$element = modalLinker(scope, function(clonedElement, scope) {});\n\n          // Set the initial positioning.\n          modalElement.css({display: 'block'}).addClass(options.placement);\n\n          // Options: animation\n          if(options.animation) {\n            if(options.backdrop) {\n              backdropElement.addClass(options.backdropAnimation);\n            }\n            modalElement.addClass(options.animation);\n          }\n\n          if(options.backdrop) {\n            $animate.enter(backdropElement, bodyElement, null);\n          }\n          // Support v1.3+ $animate\n          // https://github.com/angular/angular.js/commit/bf0f5502b1bbfddc5cdd2f138efd9188b8c652a9\n          var promise = $animate.enter(modalElement, parent, after, enterAnimateCallback);\n          if(promise && promise.then) promise.then(enterAnimateCallback);\n\n          $modal.$isShown = scope.$isShown = true;\n          safeDigest(scope);\n          // Focus once the enter-animation has started\n          // Weird PhantomJS bug hack\n          var el = modalElement[0];\n          requestAnimationFrame(function() {\n            el.focus();\n          });\n\n          bodyElement.addClass(options.prefixClass + '-open');\n          if(options.animation) {\n            bodyElement.addClass(options.prefixClass + '-with-' + options.animation);\n          }\n\n          // Bind events\n          if(options.backdrop) {\n            modalElement.on('click', hideOnBackdropClick);\n            backdropElement.on('click', hideOnBackdropClick);\n            backdropElement.on('wheel', preventEventDefault);\n          }\n          if(options.keyboard) {\n            modalElement.on('keyup', $modal.$onKeyUp);\n          }\n        };\n\n        function enterAnimateCallback() {\n          scope.$emit(options.prefixEvent + '.show', $modal);\n        }\n\n        $modal.hide = function() {\n          if(!$modal.$isShown) return;\n\n          if(scope.$emit(options.prefixEvent + '.hide.before', $modal).defaultPrevented) {\n            return;\n          }\n          var promise = $animate.leave(modalElement, leaveAnimateCallback);\n          // Support v1.3+ $animate\n          // https://github.com/angular/angular.js/commit/bf0f5502b1bbfddc5cdd2f138efd9188b8c652a9\n          if(promise && promise.then) promise.then(leaveAnimateCallback);\n\n          if(options.backdrop) {\n            $animate.leave(backdropElement);\n          }\n          $modal.$isShown = scope.$isShown = false;\n          safeDigest(scope);\n\n          // Unbind events\n          if(options.backdrop) {\n            modalElement.off('click', hideOnBackdropClick);\n            backdropElement.off('click', hideOnBackdropClick);\n            backdropElement.off('wheel', preventEventDefault);\n          }\n          if(options.keyboard) {\n            modalElement.off('keyup', $modal.$onKeyUp);\n          }\n        };\n\n        function leaveAnimateCallback() {\n          scope.$emit(options.prefixEvent + '.hide', $modal);\n          bodyElement.removeClass(options.prefixClass + '-open');\n          if(options.animation) {\n            bodyElement.removeClass(options.prefixClass + '-with-' + options.animation);\n          }\n        }\n\n        $modal.toggle = function() {\n\n          $modal.$isShown ? $modal.hide() : $modal.show();\n\n        };\n\n        $modal.focus = function() {\n          modalElement[0].focus();\n        };\n\n        // Protected methods\n\n        $modal.$onKeyUp = function(evt) {\n\n          if (evt.which === 27 && $modal.$isShown) {\n            $modal.hide();\n            evt.stopPropagation();\n          }\n\n        };\n\n        // Private methods\n\n        function hideOnBackdropClick(evt) {\n          if(evt.target !== evt.currentTarget) return;\n          options.backdrop === 'static' ? $modal.focus() : $modal.hide();\n        }\n\n        function preventEventDefault(evt) {\n          evt.preventDefault();\n        }\n\n        return $modal;\n\n      }\n\n      // Helper functions\n\n      function safeDigest(scope) {\n        scope.$$phase || (scope.$root && scope.$root.$$phase) || scope.$digest();\n      }\n\n      function findElement(query, element) {\n        return angular.element((element || document).querySelectorAll(query));\n      }\n\n      var fetchPromises = {};\n      function fetchTemplate(template) {\n        if(fetchPromises[template]) return fetchPromises[template];\n        return (fetchPromises[template] = $q.when($templateCache.get(template) || $http.get(template))\n        .then(function(res) {\n          if(angular.isObject(res)) {\n            $templateCache.put(template, res.data);\n            return res.data;\n          }\n          return res;\n        }));\n      }\n\n      return ModalFactory;\n\n    }];\n\n  })\n\n  .directive('bsModal', [\"$window\", \"$sce\", \"$modal\", function($window, $sce, $modal) {\n\n    return {\n      restrict: 'EAC',\n      scope: true,\n      link: function postLink(scope, element, attr, transclusion) {\n\n        // Directive options\n        var options = {scope: scope, element: element, show: false};\n        angular.forEach(['template', 'contentTemplate', 'placement', 'backdrop', 'keyboard', 'html', 'container', 'animation', 'id'], function(key) {\n          if(angular.isDefined(attr[key])) options[key] = attr[key];\n        });\n\n        // Support scope as data-attrs\n        angular.forEach(['title', 'content'], function(key) {\n          attr[key] && attr.$observe(key, function(newValue, oldValue) {\n            scope[key] = $sce.trustAsHtml(newValue);\n          });\n        });\n\n        // Support scope as an object\n        attr.bsModal && scope.$watch(attr.bsModal, function(newValue, oldValue) {\n          if(angular.isObject(newValue)) {\n            angular.extend(scope, newValue);\n          } else {\n            scope.content = newValue;\n          }\n        }, true);\n\n        // Initialize modal\n        var modal = $modal(options);\n\n        // Trigger\n        element.on(attr.trigger || 'click', modal.toggle);\n\n        // Garbage collection\n        scope.$on('$destroy', function() {\n          if (modal) modal.destroy();\n          options = null;\n          modal = null;\n        });\n\n      }\n    };\n\n  }]);\n\n// Source: navbar.js\nangular.module('mgcrea.ngStrap.navbar', [])\n\n  .provider('$navbar', function() {\n\n    var defaults = this.defaults = {\n      activeClass: 'active',\n      routeAttr: 'data-match-route',\n      strict: false\n    };\n\n    this.$get = function() {\n      return {defaults: defaults};\n    };\n\n  })\n\n  .directive('bsNavbar', [\"$window\", \"$location\", \"$navbar\", function($window, $location, $navbar) {\n\n    var defaults = $navbar.defaults;\n\n    return {\n      restrict: 'A',\n      link: function postLink(scope, element, attr, controller) {\n\n        // Directive options\n        var options = angular.copy(defaults);\n        angular.forEach(Object.keys(defaults), function(key) {\n          if(angular.isDefined(attr[key])) options[key] = attr[key];\n        });\n\n        // Watch for the $location\n        scope.$watch(function() {\n\n          return $location.path();\n\n        }, function(newValue, oldValue) {\n\n          var liElements = element[0].querySelectorAll('li[' + options.routeAttr + ']');\n\n          angular.forEach(liElements, function(li) {\n\n            var liElement = angular.element(li);\n            var pattern = liElement.attr(options.routeAttr).replace('/', '\\\\/');\n            if(options.strict) {\n              pattern = '^' + pattern + '$';\n            }\n            var regexp = new RegExp(pattern, ['i']);\n\n            if(regexp.test(newValue)) {\n              liElement.addClass(options.activeClass);\n            } else {\n              liElement.removeClass(options.activeClass);\n            }\n\n          });\n\n        });\n\n      }\n\n    };\n\n  }]);\n\n// Source: popover.js\nangular.module('mgcrea.ngStrap.popover', ['mgcrea.ngStrap.tooltip'])\n\n  .provider('$popover', function() {\n\n    var defaults = this.defaults = {\n      animation: 'am-fade',\n      customClass: '',\n      container: false,\n      target: false,\n      placement: 'right',\n      template: 'popover/popover.tpl.html',\n      contentTemplate: false,\n      trigger: 'click',\n      keyboard: true,\n      html: false,\n      title: '',\n      content: '',\n      delay: 0,\n      autoClose: false\n    };\n\n    this.$get = [\"$tooltip\", function($tooltip) {\n\n      function PopoverFactory(element, config) {\n\n        // Common vars\n        var options = angular.extend({}, defaults, config);\n\n        var $popover = $tooltip(element, options);\n\n        // Support scope as string options [/*title, */content]\n        if(options.content) {\n          $popover.$scope.content = options.content;\n        }\n\n        return $popover;\n\n      }\n\n      return PopoverFactory;\n\n    }];\n\n  })\n\n  .directive('bsPopover', [\"$window\", \"$sce\", \"$popover\", function($window, $sce, $popover) {\n\n    var requestAnimationFrame = $window.requestAnimationFrame || $window.setTimeout;\n\n    return {\n      restrict: 'EAC',\n      scope: true,\n      link: function postLink(scope, element, attr) {\n\n        // Directive options\n        var options = {scope: scope};\n        angular.forEach(['template', 'contentTemplate', 'placement', 'container', 'target', 'delay', 'trigger', 'keyboard', 'html', 'animation', 'customClass', 'autoClose', 'id'], function(key) {\n          if(angular.isDefined(attr[key])) options[key] = attr[key];\n        });\n\n        // Support scope as data-attrs\n        angular.forEach(['title', 'content'], function(key) {\n          attr[key] && attr.$observe(key, function(newValue, oldValue) {\n            scope[key] = $sce.trustAsHtml(newValue);\n            angular.isDefined(oldValue) && requestAnimationFrame(function() {\n              popover && popover.$applyPlacement();\n            });\n          });\n        });\n\n        // Support scope as an object\n        attr.bsPopover && scope.$watch(attr.bsPopover, function(newValue, oldValue) {\n          if(angular.isObject(newValue)) {\n            angular.extend(scope, newValue);\n          } else {\n            scope.content = newValue;\n          }\n          angular.isDefined(oldValue) && requestAnimationFrame(function() {\n            popover && popover.$applyPlacement();\n          });\n        }, true);\n\n        // Visibility binding support\n        attr.bsShow && scope.$watch(attr.bsShow, function(newValue, oldValue) {\n          if(!popover || !angular.isDefined(newValue)) return;\n          if(angular.isString(newValue)) newValue = !!newValue.match(/true|,?(popover),?/i);\n          newValue === true ? popover.show() : popover.hide();\n        });\n\n        // Initialize popover\n        var popover = $popover(element, options);\n\n        // Garbage collection\n        scope.$on('$destroy', function() {\n          if (popover) popover.destroy();\n          options = null;\n          popover = null;\n        });\n\n      }\n    };\n\n  }]);\n\n// Source: select.js\nangular.module('mgcrea.ngStrap.select', ['mgcrea.ngStrap.tooltip', 'mgcrea.ngStrap.helpers.parseOptions'])\n\n  .provider('$select', function() {\n\n    var defaults = this.defaults = {\n      animation: 'am-fade',\n      prefixClass: 'select',\n      prefixEvent: '$select',\n      placement: 'bottom-left',\n      template: 'select/select.tpl.html',\n      trigger: 'focus',\n      container: false,\n      keyboard: true,\n      html: false,\n      delay: 0,\n      multiple: false,\n      allNoneButtons: false,\n      sort: true,\n      caretHtml: '&nbsp;<span class=\"caret\"></span>',\n      placeholder: 'Choose among the following...',\n      allText: 'All',\n      noneText: 'None',\n      maxLength: 3,\n      maxLengthHtml: 'selected',\n      iconCheckmark: 'glyphicon glyphicon-ok'\n    };\n\n    this.$get = [\"$window\", \"$document\", \"$rootScope\", \"$tooltip\", \"$timeout\", function($window, $document, $rootScope, $tooltip, $timeout) {\n\n      var bodyEl = angular.element($window.document.body);\n      var isNative = /(ip(a|o)d|iphone|android)/ig.test($window.navigator.userAgent);\n      var isTouch = ('createTouch' in $window.document) && isNative;\n\n      function SelectFactory(element, controller, config) {\n\n        var $select = {};\n\n        // Common vars\n        var options = angular.extend({}, defaults, config);\n\n        $select = $tooltip(element, options);\n        var scope = $select.$scope;\n\n        scope.$matches = [];\n        scope.$activeIndex = 0;\n        scope.$isMultiple = options.multiple;\n        scope.$showAllNoneButtons = options.allNoneButtons && options.multiple;\n        scope.$iconCheckmark = options.iconCheckmark;\n        scope.$allText = options.allText;\n        scope.$noneText = options.noneText;\n\n        scope.$activate = function(index) {\n          scope.$$postDigest(function() {\n            $select.activate(index);\n          });\n        };\n\n        scope.$select = function(index, evt) {\n          scope.$$postDigest(function() {\n            $select.select(index);\n          });\n        };\n\n        scope.$isVisible = function() {\n          return $select.$isVisible();\n        };\n\n        scope.$isActive = function(index) {\n          return $select.$isActive(index);\n        };\n\n        scope.$selectAll = function () {\n          for (var i = 0; i < scope.$matches.length; i++) {\n            if (!scope.$isActive(i)) {\n              scope.$select(i);\n            }\n          }\n        };\n\n        scope.$selectNone = function () {\n          for (var i = 0; i < scope.$matches.length; i++) {\n            if (scope.$isActive(i)) {\n              scope.$select(i);\n            }\n          }\n        };\n\n        // Public methods\n\n        $select.update = function(matches) {\n          scope.$matches = matches;\n          $select.$updateActiveIndex();\n        };\n\n        $select.activate = function(index) {\n          if(options.multiple) {\n            scope.$activeIndex.sort();\n            $select.$isActive(index) ? scope.$activeIndex.splice(scope.$activeIndex.indexOf(index), 1) : scope.$activeIndex.push(index);\n            if(options.sort) scope.$activeIndex.sort();\n          } else {\n            scope.$activeIndex = index;\n          }\n          return scope.$activeIndex;\n        };\n\n        $select.select = function(index) {\n          var value = scope.$matches[index].value;\n          scope.$apply(function() {\n            $select.activate(index);\n            if(options.multiple) {\n              controller.$setViewValue(scope.$activeIndex.map(function(index) {\n                return scope.$matches[index].value;\n              }));\n            } else {\n              controller.$setViewValue(value);\n              // Hide if single select\n              $select.hide();\n            }\n          });\n          // Emit event\n          scope.$emit(options.prefixEvent + '.select', value, index, $select);\n        };\n\n        // Protected methods\n\n        $select.$updateActiveIndex = function() {\n          if(controller.$modelValue && scope.$matches.length) {\n            if(options.multiple && angular.isArray(controller.$modelValue)) {\n              scope.$activeIndex = controller.$modelValue.map(function(value) {\n                return $select.$getIndex(value);\n              });\n            } else {\n              scope.$activeIndex = $select.$getIndex(controller.$modelValue);\n            }\n          } else if(scope.$activeIndex >= scope.$matches.length) {\n            scope.$activeIndex = options.multiple ? [] : 0;\n          }\n        };\n\n        $select.$isVisible = function() {\n          if(!options.minLength || !controller) {\n            return scope.$matches.length;\n          }\n          // minLength support\n          return scope.$matches.length && controller.$viewValue.length >= options.minLength;\n        };\n\n        $select.$isActive = function(index) {\n          if(options.multiple) {\n            return scope.$activeIndex.indexOf(index) !== -1;\n          } else {\n            return scope.$activeIndex === index;\n          }\n        };\n\n        $select.$getIndex = function(value) {\n          var l = scope.$matches.length, i = l;\n          if(!l) return;\n          for(i = l; i--;) {\n            if(scope.$matches[i].value === value) break;\n          }\n          if(i < 0) return;\n          return i;\n        };\n\n        $select.$onMouseDown = function(evt) {\n          // Prevent blur on mousedown on .dropdown-menu\n          evt.preventDefault();\n          evt.stopPropagation();\n          // Emulate click for mobile devices\n          if(isTouch) {\n            var targetEl = angular.element(evt.target);\n            targetEl.triggerHandler('click');\n          }\n        };\n\n        $select.$onKeyDown = function(evt) {\n          if (!/(9|13|38|40)/.test(evt.keyCode)) return;\n          evt.preventDefault();\n          evt.stopPropagation();\n\n          // Select with enter\n          if(!options.multiple && (evt.keyCode === 13 || evt.keyCode === 9)) {\n            return $select.select(scope.$activeIndex);\n          }\n\n          // Navigate with keyboard\n          if(evt.keyCode === 38 && scope.$activeIndex > 0) scope.$activeIndex--;\n          else if(evt.keyCode === 40 && scope.$activeIndex < scope.$matches.length - 1) scope.$activeIndex++;\n          else if(angular.isUndefined(scope.$activeIndex)) scope.$activeIndex = 0;\n          scope.$digest();\n        };\n\n        // Overrides\n\n        var _show = $select.show;\n        $select.show = function() {\n          _show();\n          if(options.multiple) {\n            $select.$element.addClass('select-multiple');\n          }\n          // use timeout to hookup the events to prevent\n          // event bubbling from being processed imediately.\n          $timeout(function() {\n            $select.$element.on(isTouch ? 'touchstart' : 'mousedown', $select.$onMouseDown);\n            if(options.keyboard) {\n              element.on('keydown', $select.$onKeyDown);\n            }\n          }, 0, false);\n        };\n\n        var _hide = $select.hide;\n        $select.hide = function() {\n          $select.$element.off(isTouch ? 'touchstart' : 'mousedown', $select.$onMouseDown);\n          if(options.keyboard) {\n            element.off('keydown', $select.$onKeyDown);\n          }\n          _hide(true);\n        };\n\n        return $select;\n\n      }\n\n      SelectFactory.defaults = defaults;\n      return SelectFactory;\n\n    }];\n\n  })\n\n  .directive('bsSelect', [\"$window\", \"$parse\", \"$q\", \"$select\", \"$parseOptions\", function($window, $parse, $q, $select, $parseOptions) {\n\n    var defaults = $select.defaults;\n\n    return {\n      restrict: 'EAC',\n      require: 'ngModel',\n      link: function postLink(scope, element, attr, controller) {\n\n        // Directive options\n        var options = {scope: scope, placeholder: defaults.placeholder};\n        angular.forEach(['placement', 'container', 'delay', 'trigger', 'keyboard', 'html', 'animation', 'template', 'placeholder', 'multiple', 'allNoneButtons', 'maxLength', 'maxLengthHtml', 'allText', 'noneText', 'iconCheckmark', 'autoClose', 'id'], function(key) {\n          if(angular.isDefined(attr[key])) options[key] = attr[key];\n        });\n\n        // Add support for select markup\n        if(element[0].nodeName.toLowerCase() === 'select') {\n          var inputEl = element;\n          inputEl.css('display', 'none');\n          element = angular.element('<button type=\"button\" class=\"btn btn-default\"></button>');\n          inputEl.after(element);\n        }\n\n        // Build proper ngOptions\n        var parsedOptions = $parseOptions(attr.ngOptions);\n\n        // Initialize select\n        var select = $select(element, controller, options);\n\n        // Watch ngOptions values before filtering for changes\n        var watchedOptions = parsedOptions.$match[7].replace(/\\|.+/, '').trim();\n        scope.$watch(watchedOptions, function(newValue, oldValue) {\n          // console.warn('scope.$watch(%s)', watchedOptions, newValue, oldValue);\n          parsedOptions.valuesFn(scope, controller)\n          .then(function(values) {\n            select.update(values);\n            controller.$render();\n          });\n        }, true);\n\n        // Watch model for changes\n        scope.$watch(attr.ngModel, function(newValue, oldValue) {\n          // console.warn('scope.$watch(%s)', attr.ngModel, newValue, oldValue);\n          select.$updateActiveIndex();\n          controller.$render();\n        }, true);\n\n        // Model rendering in view\n        controller.$render = function () {\n          // console.warn('$render', element.attr('ng-model'), 'controller.$modelValue', typeof controller.$modelValue, controller.$modelValue, 'controller.$viewValue', typeof controller.$viewValue, controller.$viewValue);\n          var selected, index;\n          if(options.multiple && angular.isArray(controller.$modelValue)) {\n            selected = controller.$modelValue.map(function(value) {\n              index = select.$getIndex(value);\n              return angular.isDefined(index) ? select.$scope.$matches[index].label : false;\n            }).filter(angular.isDefined);\n            if(selected.length > (options.maxLength || defaults.maxLength)) {\n              selected = selected.length + ' ' + (options.maxLengthHtml || defaults.maxLengthHtml);\n            } else {\n              selected = selected.join(', ');\n            }\n          } else {\n            index = select.$getIndex(controller.$modelValue);\n            selected = angular.isDefined(index) ? select.$scope.$matches[index].label : false;\n          }\n          element.html((selected ? selected : options.placeholder) + defaults.caretHtml);\n        };\n\n        if(options.multiple){\n          controller.$isEmpty = function(value){\n            return !value || value.length === 0;\n          };\n        }\n\n        // Garbage collection\n        scope.$on('$destroy', function() {\n          if (select) select.destroy();\n          options = null;\n          select = null;\n        });\n\n      }\n    };\n\n  }]);\n\n// Source: tab.js\nangular.module('mgcrea.ngStrap.tab', [])\n\n  .provider('$tab', function() {\n\n    var defaults = this.defaults = {\n      animation: 'am-fade',\n      template: 'tab/tab.tpl.html',\n      navClass: 'nav-tabs',\n      activeClass: 'active'\n    };\n\n    var controller = this.controller = function($scope, $element, $attrs) {\n      var self = this;\n\n      // Attributes options\n      self.$options = angular.copy(defaults);\n      angular.forEach(['animation', 'navClass', 'activeClass'], function(key) {\n        if(angular.isDefined($attrs[key])) self.$options[key] = $attrs[key];\n      });\n\n      // Publish options on scope\n      $scope.$navClass = self.$options.navClass;\n      $scope.$activeClass = self.$options.activeClass;\n\n      self.$panes = $scope.$panes = [];\n\n      // DEPRECATED: $viewChangeListeners, please use $activePaneChangeListeners\n      // Because we deprecated ngModel usage, we rename viewChangeListeners to \n      // activePaneChangeListeners to make more sense.\n      self.$activePaneChangeListeners = self.$viewChangeListeners = [];\n\n      self.$push = function(pane) {\n        self.$panes.push(pane);\n      };\n\n      self.$remove = function(pane) {\n        var index = self.$panes.indexOf(pane);\n        var activeIndex = self.$panes.$active;\n\n        // remove pane from $panes array\n        self.$panes.splice(index, 1);\n\n        if (index < activeIndex) {\n          // we removed a pane before the active pane, so we need to \n          // decrement the active pane index\n          activeIndex--;\n        }\n        else if (index === activeIndex && activeIndex === self.$panes.length) {\n          // we remove the active pane and it was the one at the end,\n          // so select the previous one\n          activeIndex--;\n        }\n        self.$setActive(activeIndex);\n      };\n\n      self.$panes.$active = 0;\n      self.$setActive = $scope.$setActive = function(value) {\n        self.$panes.$active = value;\n        self.$activePaneChangeListeners.forEach(function(fn) {\n          fn();\n        });\n      };\n\n    };\n\n    this.$get = function() {\n      var $tab = {};\n      $tab.defaults = defaults;\n      $tab.controller = controller;\n      return $tab;\n    };\n\n  })\n\n  .directive('bsTabs', [\"$window\", \"$animate\", \"$tab\", \"$parse\", function($window, $animate, $tab, $parse) {\n\n    var defaults = $tab.defaults;\n\n    return {\n      require: ['?ngModel', 'bsTabs'],\n      transclude: true,\n      scope: true,\n      controller: ['$scope', '$element', '$attrs', $tab.controller],\n      templateUrl: function(element, attr) {\n        return attr.template || defaults.template;\n      },\n      link: function postLink(scope, element, attrs, controllers) {\n\n        var ngModelCtrl = controllers[0];\n        var bsTabsCtrl = controllers[1];\n\n        // DEPRECATED: ngModel, please use bsActivePane\n        // 'ngModel' is deprecated bacause if interferes with form validation\n        // and status, so avoid using it here.\n        if(ngModelCtrl) {\n          console.warn('Usage of ngModel is deprecated, please use bsActivePane instead!');\n\n          // Update the modelValue following\n          bsTabsCtrl.$activePaneChangeListeners.push(function() {\n            ngModelCtrl.$setViewValue(bsTabsCtrl.$panes.$active);\n          });\n\n          // modelValue -> $formatters -> viewValue\n          ngModelCtrl.$formatters.push(function(modelValue) {\n            // console.warn('$formatter(\"%s\"): modelValue=%o (%o)', element.attr('ng-model'), modelValue, typeof modelValue);\n            bsTabsCtrl.$setActive(modelValue * 1);\n            return modelValue;\n          });\n\n        }\n\n        if (attrs.bsActivePane) {\n          // adapted from angularjs ngModelController bindings\n          // https://github.com/angular/angular.js/blob/v1.3.1/src%2Fng%2Fdirective%2Finput.js#L1730\n          var parsedBsActivePane = $parse(attrs.bsActivePane);\n\n          // Update bsActivePane value with change\n          bsTabsCtrl.$activePaneChangeListeners.push(function() {\n            parsedBsActivePane.assign(scope, bsTabsCtrl.$panes.$active);\n          });\n\n          // watch bsActivePane for value changes\n          scope.$watch(attrs.bsActivePane, function(newValue, oldValue) {\n            bsTabsCtrl.$setActive(newValue * 1);\n          }, true);\n        }\n      }\n    };\n\n  }])\n\n  .directive('bsPane', [\"$window\", \"$animate\", \"$sce\", function($window, $animate, $sce) {\n\n    return {\n      require: ['^?ngModel', '^bsTabs'],\n      scope: true,\n      link: function postLink(scope, element, attrs, controllers) {\n\n        var ngModelCtrl = controllers[0];\n        var bsTabsCtrl = controllers[1];\n\n        // Add base class\n        element.addClass('tab-pane');\n\n        // Observe title attribute for change\n        attrs.$observe('title', function(newValue, oldValue) {\n          scope.title = $sce.trustAsHtml(newValue);\n        });\n\n        // Add animation class\n        if(bsTabsCtrl.$options.animation) {\n          element.addClass(bsTabsCtrl.$options.animation);\n        }\n\n        // Push pane to parent bsTabs controller\n        bsTabsCtrl.$push(scope);\n\n        // remove pane from tab controller when pane is destroyed\n        scope.$on('$destroy', function() {\n          bsTabsCtrl.$remove(scope);\n        });\n\n        function render() {\n          var index = bsTabsCtrl.$panes.indexOf(scope);\n          var active = bsTabsCtrl.$panes.$active;\n          $animate[index === active ? 'addClass' : 'removeClass'](element, bsTabsCtrl.$options.activeClass);\n        }\n\n        bsTabsCtrl.$activePaneChangeListeners.push(function() {\n          render();\n        });\n        render();\n\n      }\n    };\n\n  }]);\n\n// Source: scrollspy.js\nangular.module('mgcrea.ngStrap.scrollspy', ['mgcrea.ngStrap.helpers.debounce', 'mgcrea.ngStrap.helpers.dimensions'])\n\n  .provider('$scrollspy', function() {\n\n    // Pool of registered spies\n    var spies = this.$$spies = {};\n\n    var defaults = this.defaults = {\n      debounce: 150,\n      throttle: 100,\n      offset: 100\n    };\n\n    this.$get = [\"$window\", \"$document\", \"$rootScope\", \"dimensions\", \"debounce\", \"throttle\", function($window, $document, $rootScope, dimensions, debounce, throttle) {\n\n      var windowEl = angular.element($window);\n      var docEl = angular.element($document.prop('documentElement'));\n      var bodyEl = angular.element($window.document.body);\n\n      // Helper functions\n\n      function nodeName(element, name) {\n        return element[0].nodeName && element[0].nodeName.toLowerCase() === name.toLowerCase();\n      }\n\n      function ScrollSpyFactory(config) {\n\n        // Common vars\n        var options = angular.extend({}, defaults, config);\n        if(!options.element) options.element = bodyEl;\n        var isWindowSpy = nodeName(options.element, 'body');\n        var scrollEl = isWindowSpy ? windowEl : options.element;\n        var scrollId = isWindowSpy ? 'window' : options.id;\n\n        // Use existing spy\n        if(spies[scrollId]) {\n          spies[scrollId].$$count++;\n          return spies[scrollId];\n        }\n\n        var $scrollspy = {};\n\n        // Private vars\n        var unbindViewContentLoaded, unbindIncludeContentLoaded;\n        var trackedElements = $scrollspy.$trackedElements = [];\n        var sortedElements = [];\n        var activeTarget;\n        var debouncedCheckPosition;\n        var throttledCheckPosition;\n        var debouncedCheckOffsets;\n        var viewportHeight;\n        var scrollTop;\n\n        $scrollspy.init = function() {\n\n          // Setup internal ref counter\n          this.$$count = 1;\n\n          // Bind events\n          debouncedCheckPosition = debounce(this.checkPosition, options.debounce);\n          throttledCheckPosition = throttle(this.checkPosition, options.throttle);\n          scrollEl.on('click', this.checkPositionWithEventLoop);\n          windowEl.on('resize', debouncedCheckPosition);\n          scrollEl.on('scroll', throttledCheckPosition);\n\n          debouncedCheckOffsets = debounce(this.checkOffsets, options.debounce);\n          unbindViewContentLoaded = $rootScope.$on('$viewContentLoaded', debouncedCheckOffsets);\n          unbindIncludeContentLoaded = $rootScope.$on('$includeContentLoaded', debouncedCheckOffsets);\n          debouncedCheckOffsets();\n\n          // Register spy for reuse\n          if(scrollId) {\n            spies[scrollId] = $scrollspy;\n          }\n\n        };\n\n        $scrollspy.destroy = function() {\n\n          // Check internal ref counter\n          this.$$count--;\n          if(this.$$count > 0) {\n            return;\n          }\n\n          // Unbind events\n          scrollEl.off('click', this.checkPositionWithEventLoop);\n          windowEl.off('resize', debouncedCheckPosition);\n          scrollEl.off('scroll', throttledCheckPosition);\n          unbindViewContentLoaded();\n          unbindIncludeContentLoaded();\n          if (scrollId) {\n            delete spies[scrollId];\n          }\n        };\n\n        $scrollspy.checkPosition = function() {\n\n          // Not ready yet\n          if(!sortedElements.length) return;\n\n          // Calculate the scroll position\n          scrollTop = (isWindowSpy ? $window.pageYOffset : scrollEl.prop('scrollTop')) || 0;\n\n          // Calculate the viewport height for use by the components\n          viewportHeight = Math.max($window.innerHeight, docEl.prop('clientHeight'));\n\n          // Activate first element if scroll is smaller\n          if(scrollTop < sortedElements[0].offsetTop && activeTarget !== sortedElements[0].target) {\n            return $scrollspy.$activateElement(sortedElements[0]);\n          }\n\n          // Activate proper element\n          for (var i = sortedElements.length; i--;) {\n            if(angular.isUndefined(sortedElements[i].offsetTop) || sortedElements[i].offsetTop === null) continue;\n            if(activeTarget === sortedElements[i].target) continue;\n            if(scrollTop < sortedElements[i].offsetTop) continue;\n            if(sortedElements[i + 1] && scrollTop > sortedElements[i + 1].offsetTop) continue;\n            return $scrollspy.$activateElement(sortedElements[i]);\n          }\n\n        };\n\n        $scrollspy.checkPositionWithEventLoop = function() {\n          // IE 9 throws an error if we use 'this' instead of '$scrollspy'\n          // in this setTimeout call\n          setTimeout($scrollspy.checkPosition, 1);\n        };\n\n        // Protected methods\n\n        $scrollspy.$activateElement = function(element) {\n          if(activeTarget) {\n            var activeElement = $scrollspy.$getTrackedElement(activeTarget);\n            if(activeElement) {\n              activeElement.source.removeClass('active');\n              if(nodeName(activeElement.source, 'li') && nodeName(activeElement.source.parent().parent(), 'li')) {\n                activeElement.source.parent().parent().removeClass('active');\n              }\n            }\n          }\n          activeTarget = element.target;\n          element.source.addClass('active');\n          if(nodeName(element.source, 'li') && nodeName(element.source.parent().parent(), 'li')) {\n            element.source.parent().parent().addClass('active');\n          }\n        };\n\n        $scrollspy.$getTrackedElement = function(target) {\n          return trackedElements.filter(function(obj) {\n            return obj.target === target;\n          })[0];\n        };\n\n        // Track offsets behavior\n\n        $scrollspy.checkOffsets = function() {\n\n          angular.forEach(trackedElements, function(trackedElement) {\n            var targetElement = document.querySelector(trackedElement.target);\n            trackedElement.offsetTop = targetElement ? dimensions.offset(targetElement).top : null;\n            if(options.offset && trackedElement.offsetTop !== null) trackedElement.offsetTop -= options.offset * 1;\n          });\n\n          sortedElements = trackedElements\n          .filter(function(el) {\n            return el.offsetTop !== null;\n          })\n          .sort(function(a, b) {\n            return a.offsetTop - b.offsetTop;\n          });\n\n          debouncedCheckPosition();\n\n        };\n\n        $scrollspy.trackElement = function(target, source) {\n          trackedElements.push({target: target, source: source});\n        };\n\n        $scrollspy.untrackElement = function(target, source) {\n          var toDelete;\n          for (var i = trackedElements.length; i--;) {\n            if(trackedElements[i].target === target && trackedElements[i].source === source) {\n              toDelete = i;\n              break;\n            }\n          }\n          trackedElements = trackedElements.splice(toDelete, 1);\n        };\n\n        $scrollspy.activate = function(i) {\n          trackedElements[i].addClass('active');\n        };\n\n        // Initialize plugin\n\n        $scrollspy.init();\n        return $scrollspy;\n\n      }\n\n      return ScrollSpyFactory;\n\n    }];\n\n  })\n\n  .directive('bsScrollspy', [\"$rootScope\", \"debounce\", \"dimensions\", \"$scrollspy\", function($rootScope, debounce, dimensions, $scrollspy) {\n\n    return {\n      restrict: 'EAC',\n      link: function postLink(scope, element, attr) {\n\n        var options = {scope: scope};\n        angular.forEach(['offset', 'target'], function(key) {\n          if(angular.isDefined(attr[key])) options[key] = attr[key];\n        });\n\n        var scrollspy = $scrollspy(options);\n        scrollspy.trackElement(options.target, element);\n\n        scope.$on('$destroy', function() {\n          if (scrollspy) {\n            scrollspy.untrackElement(options.target, element);\n            scrollspy.destroy();\n          }\n          options = null;\n          scrollspy = null;\n        });\n\n      }\n    };\n\n  }])\n\n\n  .directive('bsScrollspyList', [\"$rootScope\", \"debounce\", \"dimensions\", \"$scrollspy\", function($rootScope, debounce, dimensions, $scrollspy) {\n\n    return {\n      restrict: 'A',\n      compile: function postLink(element, attr) {\n        var children = element[0].querySelectorAll('li > a[href]');\n        angular.forEach(children, function(child) {\n          var childEl = angular.element(child);\n          childEl.parent().attr('bs-scrollspy', '').attr('data-target', childEl.attr('href'));\n        });\n      }\n\n    };\n\n  }]);\n\n// Source: timepicker.js\nangular.module('mgcrea.ngStrap.timepicker', [\n  'mgcrea.ngStrap.helpers.dateParser',\n  'mgcrea.ngStrap.helpers.dateFormatter',\n  'mgcrea.ngStrap.tooltip'])\n\n  .provider('$timepicker', function() {\n\n    var defaults = this.defaults = {\n      animation: 'am-fade',\n      prefixClass: 'timepicker',\n      placement: 'bottom-left',\n      template: 'timepicker/timepicker.tpl.html',\n      trigger: 'focus',\n      container: false,\n      keyboard: true,\n      html: false,\n      delay: 0,\n      // lang: $locale.id,\n      useNative: true,\n      timeType: 'date',\n      timeFormat: 'shortTime',\n      modelTimeFormat: null,\n      autoclose: false,\n      minTime: -Infinity,\n      maxTime: +Infinity,\n      length: 5,\n      hourStep: 1,\n      minuteStep: 5,\n      iconUp: 'glyphicon glyphicon-chevron-up',\n      iconDown: 'glyphicon glyphicon-chevron-down',\n      arrowBehavior: 'pager'\n    };\n\n    this.$get = [\"$window\", \"$document\", \"$rootScope\", \"$sce\", \"$dateFormatter\", \"$tooltip\", \"$timeout\", function($window, $document, $rootScope, $sce, $dateFormatter, $tooltip, $timeout) {\n\n      var bodyEl = angular.element($window.document.body);\n      var isNative = /(ip(a|o)d|iphone|android)/ig.test($window.navigator.userAgent);\n      var isTouch = ('createTouch' in $window.document) && isNative;\n      if(!defaults.lang) defaults.lang = $dateFormatter.getDefaultLocale();\n\n      function timepickerFactory(element, controller, config) {\n\n        var $timepicker = $tooltip(element, angular.extend({}, defaults, config));\n        var parentScope = config.scope;\n        var options = $timepicker.$options;\n        var scope = $timepicker.$scope;\n\n        var lang = options.lang;\n        var formatDate = function(date, format) {\n          return $dateFormatter.formatDate(date, format, lang);\n        };\n\n        // View vars\n\n        var selectedIndex = 0;\n        var startDate = controller.$dateValue || new Date();\n        var viewDate = {hour: startDate.getHours(), meridian: startDate.getHours() < 12, minute: startDate.getMinutes(), second: startDate.getSeconds(), millisecond: startDate.getMilliseconds()};\n\n        var format = $dateFormatter.getDatetimeFormat(options.timeFormat, lang);\n\n        var hoursFormat = $dateFormatter.hoursFormat(format),\n          timeSeparator = $dateFormatter.timeSeparator(format),\n          minutesFormat = $dateFormatter.minutesFormat(format),\n          showAM = $dateFormatter.showAM(format);\n\n        scope.$iconUp = options.iconUp;\n        scope.$iconDown = options.iconDown;\n\n        // Scope methods\n\n        scope.$select = function(date, index) {\n          $timepicker.select(date, index);\n        };\n        scope.$moveIndex = function(value, index) {\n          $timepicker.$moveIndex(value, index);\n        };\n        scope.$switchMeridian = function(date) {\n          $timepicker.switchMeridian(date);\n        };\n\n        // Public methods\n\n        $timepicker.update = function(date) {\n          // console.warn('$timepicker.update() newValue=%o', date);\n          if(angular.isDate(date) && !isNaN(date.getTime())) {\n            $timepicker.$date = date;\n            angular.extend(viewDate, {hour: date.getHours(), minute: date.getMinutes(), second: date.getSeconds(), millisecond: date.getMilliseconds()});\n            $timepicker.$build();\n          } else if(!$timepicker.$isBuilt) {\n            $timepicker.$build();\n          }\n        };\n\n        $timepicker.select = function(date, index, keep) {\n          // console.warn('$timepicker.select', date, scope.$mode);\n          if(!controller.$dateValue || isNaN(controller.$dateValue.getTime())) controller.$dateValue = new Date(1970, 0, 1);\n          if(!angular.isDate(date)) date = new Date(date);\n          if(index === 0) controller.$dateValue.setHours(date.getHours());\n          else if(index === 1) controller.$dateValue.setMinutes(date.getMinutes());\n          controller.$setViewValue(angular.copy(controller.$dateValue));\n          controller.$render();\n          if(options.autoclose && !keep) {\n            $timeout(function() { $timepicker.hide(true); });\n          }\n        };\n\n        $timepicker.switchMeridian = function(date) {\n          if (!controller.$dateValue || isNaN(controller.$dateValue.getTime())) {\n            return;\n          }\n          var hours = (date || controller.$dateValue).getHours();\n          controller.$dateValue.setHours(hours < 12 ? hours + 12 : hours - 12);\n          controller.$setViewValue(angular.copy(controller.$dateValue));\n          controller.$render();\n        };\n\n        // Protected methods\n\n        $timepicker.$build = function() {\n          // console.warn('$timepicker.$build() viewDate=%o', viewDate);\n          var i, midIndex = scope.midIndex = parseInt(options.length / 2, 10);\n          var hours = [], hour;\n          for(i = 0; i < options.length; i++) {\n            hour = new Date(1970, 0, 1, viewDate.hour - (midIndex - i) * options.hourStep);\n            hours.push({date: hour, label: formatDate(hour, hoursFormat), selected: $timepicker.$date && $timepicker.$isSelected(hour, 0), disabled: $timepicker.$isDisabled(hour, 0)});\n          }\n          var minutes = [], minute;\n          for(i = 0; i < options.length; i++) {\n            minute = new Date(1970, 0, 1, 0, viewDate.minute - (midIndex - i) * options.minuteStep);\n            minutes.push({date: minute, label: formatDate(minute, minutesFormat), selected: $timepicker.$date && $timepicker.$isSelected(minute, 1), disabled: $timepicker.$isDisabled(minute, 1)});\n          }\n\n          var rows = [];\n          for(i = 0; i < options.length; i++) {\n            rows.push([hours[i], minutes[i]]);\n          }\n          scope.rows = rows;\n          scope.showAM = showAM;\n          scope.isAM = ($timepicker.$date || hours[midIndex].date).getHours() < 12;\n          scope.timeSeparator = timeSeparator;\n          $timepicker.$isBuilt = true;\n        };\n\n        $timepicker.$isSelected = function(date, index) {\n          if(!$timepicker.$date) return false;\n          else if(index === 0) {\n            return date.getHours() === $timepicker.$date.getHours();\n          } else if(index === 1) {\n            return date.getMinutes() === $timepicker.$date.getMinutes();\n          }\n        };\n\n        $timepicker.$isDisabled = function(date, index) {\n          var selectedTime;\n          if(index === 0) {\n            selectedTime = date.getTime() + viewDate.minute * 6e4;\n          } else if(index === 1) {\n            selectedTime = date.getTime() + viewDate.hour * 36e5;\n          }\n          return selectedTime < options.minTime * 1 || selectedTime > options.maxTime * 1;\n        };\n\n        scope.$arrowAction = function (value, index) {\n          if (options.arrowBehavior === 'picker') {\n            $timepicker.$setTimeByStep(value,index);\n          } else {\n            $timepicker.$moveIndex(value,index);\n          }\n        };\n\n        $timepicker.$setTimeByStep = function(value, index) {\n          var newDate = new Date($timepicker.$date);\n          var hours = newDate.getHours(), hoursLength = formatDate(newDate, hoursFormat).length;\n          var minutes = newDate.getMinutes(), minutesLength = formatDate(newDate, minutesFormat).length;\n          if (index === 0) {\n            newDate.setHours(hours - (parseInt(options.hourStep, 10) * value));\n          }\n          else {\n            newDate.setMinutes(minutes - (parseInt(options.minuteStep, 10) * value));\n          }\n          $timepicker.select(newDate, index, true);\n        };\n\n        $timepicker.$moveIndex = function(value, index) {\n          var targetDate;\n          if(index === 0) {\n            targetDate = new Date(1970, 0, 1, viewDate.hour + (value * options.length), viewDate.minute);\n            angular.extend(viewDate, {hour: targetDate.getHours()});\n          } else if(index === 1) {\n            targetDate = new Date(1970, 0, 1, viewDate.hour, viewDate.minute + (value * options.length * options.minuteStep));\n            angular.extend(viewDate, {minute: targetDate.getMinutes()});\n          }\n          $timepicker.$build();\n        };\n\n        $timepicker.$onMouseDown = function(evt) {\n          // Prevent blur on mousedown on .dropdown-menu\n          if(evt.target.nodeName.toLowerCase() !== 'input') evt.preventDefault();\n          evt.stopPropagation();\n          // Emulate click for mobile devices\n          if(isTouch) {\n            var targetEl = angular.element(evt.target);\n            if(targetEl[0].nodeName.toLowerCase() !== 'button') {\n              targetEl = targetEl.parent();\n            }\n            targetEl.triggerHandler('click');\n          }\n        };\n\n        $timepicker.$onKeyDown = function(evt) {\n          if (!/(38|37|39|40|13)/.test(evt.keyCode) || evt.shiftKey || evt.altKey) return;\n          evt.preventDefault();\n          evt.stopPropagation();\n\n          // Close on enter\n          if(evt.keyCode === 13) return $timepicker.hide(true);\n\n          // Navigate with keyboard\n          var newDate = new Date($timepicker.$date);\n          var hours = newDate.getHours(), hoursLength = formatDate(newDate, hoursFormat).length;\n          var minutes = newDate.getMinutes(), minutesLength = formatDate(newDate, minutesFormat).length;\n          var lateralMove = /(37|39)/.test(evt.keyCode);\n          var count = 2 + showAM * 1;\n\n          // Navigate indexes (left, right)\n          if (lateralMove) {\n            if(evt.keyCode === 37) selectedIndex = selectedIndex < 1 ? count - 1 : selectedIndex - 1;\n            else if(evt.keyCode === 39) selectedIndex = selectedIndex < count - 1 ? selectedIndex + 1 : 0;\n          }\n\n          // Update values (up, down)\n          var selectRange = [0, hoursLength];\n          if(selectedIndex === 0) {\n            if(evt.keyCode === 38) newDate.setHours(hours - parseInt(options.hourStep, 10));\n            else if(evt.keyCode === 40) newDate.setHours(hours + parseInt(options.hourStep, 10));\n            // re-calculate hours length because we have changed hours value\n            hoursLength = formatDate(newDate, hoursFormat).length;\n            selectRange = [0, hoursLength];\n          } else if(selectedIndex === 1) {\n            if(evt.keyCode === 38) newDate.setMinutes(minutes - parseInt(options.minuteStep, 10));\n            else if(evt.keyCode === 40) newDate.setMinutes(minutes + parseInt(options.minuteStep, 10));\n            // re-calculate minutes length because we have changes minutes value\n            minutesLength = formatDate(newDate, minutesFormat).length;\n            selectRange = [hoursLength + 1, hoursLength + 1 + minutesLength];\n          } else if(selectedIndex === 2) {\n            if(!lateralMove) $timepicker.switchMeridian();\n            selectRange = [hoursLength + 1 + minutesLength + 1, hoursLength + 1 + minutesLength + 3];\n          }\n          $timepicker.select(newDate, selectedIndex, true);\n          createSelection(selectRange[0], selectRange[1]);\n          parentScope.$digest();\n        };\n\n        // Private\n\n        function createSelection(start, end) {\n          if(element[0].createTextRange) {\n            var selRange = element[0].createTextRange();\n            selRange.collapse(true);\n            selRange.moveStart('character', start);\n            selRange.moveEnd('character', end);\n            selRange.select();\n          } else if(element[0].setSelectionRange) {\n            element[0].setSelectionRange(start, end);\n          } else if(angular.isUndefined(element[0].selectionStart)) {\n            element[0].selectionStart = start;\n            element[0].selectionEnd = end;\n          }\n        }\n\n        function focusElement() {\n          element[0].focus();\n        }\n\n        // Overrides\n\n        var _init = $timepicker.init;\n        $timepicker.init = function() {\n          if(isNative && options.useNative) {\n            element.prop('type', 'time');\n            element.css('-webkit-appearance', 'textfield');\n            return;\n          } else if(isTouch) {\n            element.prop('type', 'text');\n            element.attr('readonly', 'true');\n            element.on('click', focusElement);\n          }\n          _init();\n        };\n\n        var _destroy = $timepicker.destroy;\n        $timepicker.destroy = function() {\n          if(isNative && options.useNative) {\n            element.off('click', focusElement);\n          }\n          _destroy();\n        };\n\n        var _show = $timepicker.show;\n        $timepicker.show = function() {\n          _show();\n          // use timeout to hookup the events to prevent\n          // event bubbling from being processed imediately.\n          $timeout(function() {\n            $timepicker.$element.on(isTouch ? 'touchstart' : 'mousedown', $timepicker.$onMouseDown);\n            if(options.keyboard) {\n              element.on('keydown', $timepicker.$onKeyDown);\n            }\n          }, 0, false);\n        };\n\n        var _hide = $timepicker.hide;\n        $timepicker.hide = function(blur) {\n          if(!$timepicker.$isShown) return;\n          $timepicker.$element.off(isTouch ? 'touchstart' : 'mousedown', $timepicker.$onMouseDown);\n          if(options.keyboard) {\n            element.off('keydown', $timepicker.$onKeyDown);\n          }\n          _hide(blur);\n        };\n\n        return $timepicker;\n\n      }\n\n      timepickerFactory.defaults = defaults;\n      return timepickerFactory;\n\n    }];\n\n  })\n\n\n  .directive('bsTimepicker', [\"$window\", \"$parse\", \"$q\", \"$dateFormatter\", \"$dateParser\", \"$timepicker\", function($window, $parse, $q, $dateFormatter, $dateParser, $timepicker) {\n\n    var defaults = $timepicker.defaults;\n    var isNative = /(ip(a|o)d|iphone|android)/ig.test($window.navigator.userAgent);\n    var requestAnimationFrame = $window.requestAnimationFrame || $window.setTimeout;\n\n    return {\n      restrict: 'EAC',\n      require: 'ngModel',\n      link: function postLink(scope, element, attr, controller) {\n\n        // Directive options\n        var options = {scope: scope, controller: controller};\n        angular.forEach(['placement', 'container', 'delay', 'trigger', 'keyboard', 'html', 'animation', 'template', 'autoclose', 'timeType', 'timeFormat', 'modelTimeFormat', 'useNative', 'hourStep', 'minuteStep', 'length', 'arrowBehavior', 'iconUp', 'iconDown', 'id'], function(key) {\n          if(angular.isDefined(attr[key])) options[key] = attr[key];\n        });\n\n        // Visibility binding support\n        attr.bsShow && scope.$watch(attr.bsShow, function(newValue, oldValue) {\n          if(!timepicker || !angular.isDefined(newValue)) return;\n          if(angular.isString(newValue)) newValue = !!newValue.match(/true|,?(timepicker),?/i);\n          newValue === true ? timepicker.show() : timepicker.hide();\n        });\n\n        // Initialize timepicker\n        if(isNative && (options.useNative || defaults.useNative)) options.timeFormat = 'HH:mm';\n        var timepicker = $timepicker(element, controller, options);\n        options = timepicker.$options;\n\n        var lang = options.lang;\n        var formatDate = function(date, format) {\n          return $dateFormatter.formatDate(date, format, lang);\n        };\n\n        // Initialize parser\n        var dateParser = $dateParser({format: options.timeFormat, lang: lang});\n\n        // Observe attributes for changes\n        angular.forEach(['minTime', 'maxTime'], function(key) {\n          // console.warn('attr.$observe(%s)', key, attr[key]);\n          angular.isDefined(attr[key]) && attr.$observe(key, function(newValue) {\n            timepicker.$options[key] = dateParser.getTimeForAttribute(key, newValue);\n            !isNaN(timepicker.$options[key]) && timepicker.$build();\n            validateAgainstMinMaxTime(controller.$dateValue);\n          });\n        });\n\n        // Watch model for changes\n        scope.$watch(attr.ngModel, function(newValue, oldValue) {\n          // console.warn('scope.$watch(%s)', attr.ngModel, newValue, oldValue, controller.$dateValue);\n          timepicker.update(controller.$dateValue);\n        }, true);\n\n        function validateAgainstMinMaxTime(parsedTime) {\n          if (!angular.isDate(parsedTime)) return;\n          var isMinValid = isNaN(options.minTime) || new Date(parsedTime.getTime()).setFullYear(1970, 0, 1) >= options.minTime;\n          var isMaxValid = isNaN(options.maxTime) || new Date(parsedTime.getTime()).setFullYear(1970, 0, 1) <= options.maxTime;\n          var isValid = isMinValid && isMaxValid;\n          controller.$setValidity('date', isValid);\n          controller.$setValidity('min', isMinValid);\n          controller.$setValidity('max', isMaxValid);\n          // Only update the model when we have a valid date\n          if(!isValid) {\n              return;\n          }\n          controller.$dateValue = parsedTime;\n        }\n\n        // viewValue -> $parsers -> modelValue\n        controller.$parsers.unshift(function(viewValue) {\n          // console.warn('$parser(\"%s\"): viewValue=%o', element.attr('ng-model'), viewValue);\n          // Null values should correctly reset the model value & validity\n          if(!viewValue) {\n            // BREAKING CHANGE:\n            // return null (not undefined) when input value is empty, so angularjs 1.3\n            // ngModelController can go ahead and run validators, like ngRequired\n            controller.$setValidity('date', true);\n            return null;\n          }\n          var parsedTime = angular.isDate(viewValue) ? viewValue : dateParser.parse(viewValue, controller.$dateValue);\n          if(!parsedTime || isNaN(parsedTime.getTime())) {\n            controller.$setValidity('date', false);\n            // return undefined, causes ngModelController to\n            // invalidate model value\n            return;\n          } else {\n            validateAgainstMinMaxTime(parsedTime);\n          }\n          if(options.timeType === 'string') {\n            return formatDate(parsedTime, options.modelTimeFormat || options.timeFormat);\n          } else if(options.timeType === 'number') {\n            return controller.$dateValue.getTime();\n          } else if(options.timeType === 'unix') {\n            return controller.$dateValue.getTime() / 1000;\n          } else if(options.timeType === 'iso') {\n            return controller.$dateValue.toISOString();\n          } else {\n            return new Date(controller.$dateValue);\n          }\n        });\n\n        // modelValue -> $formatters -> viewValue\n        controller.$formatters.push(function(modelValue) {\n          // console.warn('$formatter(\"%s\"): modelValue=%o (%o)', element.attr('ng-model'), modelValue, typeof modelValue);\n          var date;\n          if(angular.isUndefined(modelValue) || modelValue === null) {\n            date = NaN;\n          } else if(angular.isDate(modelValue)) {\n            date = modelValue;\n          } else if(options.timeType === 'string') {\n            date = dateParser.parse(modelValue, null, options.modelTimeFormat);\n          } else if(options.timeType === 'unix') {\n            date = new Date(modelValue * 1000);\n          } else {\n            date = new Date(modelValue);\n          }\n          // Setup default value?\n          // if(isNaN(date.getTime())) date = new Date(new Date().setMinutes(0) + 36e5);\n          controller.$dateValue = date;\n          return getTimeFormattedString();\n        });\n\n        // viewValue -> element\n        controller.$render = function() {\n          // console.warn('$render(\"%s\"): viewValue=%o', element.attr('ng-model'), controller.$viewValue);\n          element.val(getTimeFormattedString());\n        };\n\n        function getTimeFormattedString() {\n          return !controller.$dateValue || isNaN(controller.$dateValue.getTime()) ? '' : formatDate(controller.$dateValue, options.timeFormat);\n        }\n\n        // Garbage collection\n        scope.$on('$destroy', function() {\n          if (timepicker) timepicker.destroy();\n          options = null;\n          timepicker = null;\n        });\n\n      }\n    };\n\n  }]);\n\n// Source: tooltip.js\nangular.module('mgcrea.ngStrap.tooltip', ['mgcrea.ngStrap.helpers.dimensions'])\n\n  .provider('$tooltip', function() {\n\n    var defaults = this.defaults = {\n      animation: 'am-fade',\n      customClass: '',\n      prefixClass: 'tooltip',\n      prefixEvent: 'tooltip',\n      container: false,\n      target: false,\n      placement: 'top',\n      template: 'tooltip/tooltip.tpl.html',\n      contentTemplate: false,\n      trigger: 'hover focus',\n      keyboard: false,\n      html: false,\n      show: false,\n      title: '',\n      type: '',\n      delay: 0,\n      autoClose: false,\n      bsEnabled: true\n    };\n\n    this.$get = [\"$window\", \"$rootScope\", \"$compile\", \"$q\", \"$templateCache\", \"$http\", \"$animate\", \"$sce\", \"dimensions\", \"$$rAF\", \"$timeout\", function($window, $rootScope, $compile, $q, $templateCache, $http, $animate, $sce, dimensions, $$rAF, $timeout) {\n\n      var trim = String.prototype.trim;\n      var isTouch = 'createTouch' in $window.document;\n      var htmlReplaceRegExp = /ng-bind=\"/ig;\n      var $body = angular.element($window.document);\n\n      function TooltipFactory(element, config) {\n\n        var $tooltip = {};\n\n        // Common vars\n        var nodeName = element[0].nodeName.toLowerCase();\n        var options = $tooltip.$options = angular.extend({}, defaults, config);\n        $tooltip.$promise = fetchTemplate(options.template);\n        var scope = $tooltip.$scope = options.scope && options.scope.$new() || $rootScope.$new();\n        if(options.delay && angular.isString(options.delay)) {\n          var split = options.delay.split(',').map(parseFloat);\n          options.delay = split.length > 1 ? {show: split[0], hide: split[1]} : split[0];\n        }\n\n        // store $id to identify the triggering element in events\n        // give priority to options.id, otherwise, try to use\n        // element id if defined\n        $tooltip.$id = options.id || element.attr('id') || '';\n\n        // Support scope as string options\n        if(options.title) {\n          scope.title = $sce.trustAsHtml(options.title);\n        }\n\n        // Provide scope helpers\n        scope.$setEnabled = function(isEnabled) {\n          scope.$$postDigest(function() {\n            $tooltip.setEnabled(isEnabled);\n          });\n        };\n        scope.$hide = function() {\n          scope.$$postDigest(function() {\n            $tooltip.hide();\n          });\n        };\n        scope.$show = function() {\n          scope.$$postDigest(function() {\n            $tooltip.show();\n          });\n        };\n        scope.$toggle = function() {\n          scope.$$postDigest(function() {\n            $tooltip.toggle();\n          });\n        };\n        // Publish isShown as a protected var on scope\n        $tooltip.$isShown = scope.$isShown = false;\n\n        // Private vars\n        var timeout, hoverState;\n\n        // Support contentTemplate option\n        if(options.contentTemplate) {\n          $tooltip.$promise = $tooltip.$promise.then(function(template) {\n            var templateEl = angular.element(template);\n            return fetchTemplate(options.contentTemplate)\n            .then(function(contentTemplate) {\n              var contentEl = findElement('[ng-bind=\"content\"]', templateEl[0]);\n              if(!contentEl.length) contentEl = findElement('[ng-bind=\"title\"]', templateEl[0]);\n              contentEl.removeAttr('ng-bind').html(contentTemplate);\n              return templateEl[0].outerHTML;\n            });\n          });\n        }\n\n        // Fetch, compile then initialize tooltip\n        var tipLinker, tipElement, tipTemplate, tipContainer, tipScope;\n        $tooltip.$promise.then(function(template) {\n          if(angular.isObject(template)) template = template.data;\n          if(options.html) template = template.replace(htmlReplaceRegExp, 'ng-bind-html=\"');\n          template = trim.apply(template);\n          tipTemplate = template;\n          tipLinker = $compile(template);\n          $tooltip.init();\n        });\n\n        $tooltip.init = function() {\n\n          // Options: delay\n          if (options.delay && angular.isNumber(options.delay)) {\n            options.delay = {\n              show: options.delay,\n              hide: options.delay\n            };\n          }\n\n          // Replace trigger on touch devices ?\n          // if(isTouch && options.trigger === defaults.trigger) {\n          //   options.trigger.replace(/hover/g, 'click');\n          // }\n\n          // Options : container\n          if(options.container === 'self') {\n            tipContainer = element;\n          } else if(angular.isElement(options.container)) {\n            tipContainer = options.container;\n          } else if(options.container) {\n            tipContainer = findElement(options.container);\n          }\n\n          // Options: trigger\n          bindTriggerEvents();\n\n          // Options: target\n          if(options.target) {\n            options.target = angular.isElement(options.target) ? options.target : findElement(options.target);\n          }\n\n          // Options: show\n          if(options.show) {\n            scope.$$postDigest(function() {\n              options.trigger === 'focus' ? element[0].focus() : $tooltip.show();\n            });\n          }\n\n        };\n\n        $tooltip.destroy = function() {\n\n          // Unbind events\n          unbindTriggerEvents();\n\n          // Remove element\n          destroyTipElement();\n\n          // Destroy scope\n          scope.$destroy();\n\n        };\n\n        $tooltip.enter = function() {\n\n          clearTimeout(timeout);\n          hoverState = 'in';\n          if (!options.delay || !options.delay.show) {\n            return $tooltip.show();\n          }\n\n          timeout = setTimeout(function() {\n            if (hoverState ==='in') $tooltip.show();\n          }, options.delay.show);\n\n        };\n\n        $tooltip.show = function() {\n          if (!options.bsEnabled || $tooltip.$isShown) return;\n\n          scope.$emit(options.prefixEvent + '.show.before', $tooltip);\n          var parent, after;\n          if (options.container) {\n            parent = tipContainer;\n            if (tipContainer[0].lastChild) {\n              after = angular.element(tipContainer[0].lastChild);\n            } else {\n              after = null;\n            }\n          } else {\n            parent = null;\n            after = element;\n          }\n\n\n          // Hide any existing tipElement\n          if(tipElement) destroyTipElement();\n          // Fetch a cloned element linked from template\n          tipScope = $tooltip.$scope.$new();\n          tipElement = $tooltip.$element = tipLinker(tipScope, function(clonedElement, scope) {});\n\n          // Set the initial positioning.  Make the tooltip invisible\n          // so IE doesn't try to focus on it off screen.\n          tipElement.css({top: '-9999px', left: '-9999px', display: 'block', visibility: 'hidden'});\n\n          // Options: animation\n          if(options.animation) tipElement.addClass(options.animation);\n          // Options: type\n          if(options.type) tipElement.addClass(options.prefixClass + '-' + options.type);\n          // Options: custom classes\n          if(options.customClass) tipElement.addClass(options.customClass);\n\n          // Support v1.3+ $animate\n          // https://github.com/angular/angular.js/commit/bf0f5502b1bbfddc5cdd2f138efd9188b8c652a9\n          var promise = $animate.enter(tipElement, parent, after, enterAnimateCallback);\n          if(promise && promise.then) promise.then(enterAnimateCallback);\n\n          $tooltip.$isShown = scope.$isShown = true;\n          safeDigest(scope);\n          $$rAF(function () {\n            $tooltip.$applyPlacement();\n\n            // Once placed, make the tooltip visible\n            if(tipElement) tipElement.css({visibility: 'visible'});\n          }); // var a = bodyEl.offsetWidth + 1; ?\n\n          // Bind events\n          if(options.keyboard) {\n            if(options.trigger !== 'focus') {\n              $tooltip.focus();\n            }\n            bindKeyboardEvents();\n          }\n\n          if(options.autoClose) {\n            bindAutoCloseEvents();\n          }\n\n        };\n\n        function enterAnimateCallback() {\n          scope.$emit(options.prefixEvent + '.show', $tooltip);\n        }\n\n        $tooltip.leave = function() {\n\n          clearTimeout(timeout);\n          hoverState = 'out';\n          if (!options.delay || !options.delay.hide) {\n            return $tooltip.hide();\n          }\n          timeout = setTimeout(function () {\n            if (hoverState === 'out') {\n              $tooltip.hide();\n            }\n          }, options.delay.hide);\n\n        };\n\n        var _blur;\n        var _tipToHide;\n        $tooltip.hide = function(blur) {\n\n          if(!$tooltip.$isShown) return;\n          scope.$emit(options.prefixEvent + '.hide.before', $tooltip);\n\n          // store blur value for leaveAnimateCallback to use\n          _blur = blur;\n\n          // store current tipElement reference to use\n          // in leaveAnimateCallback\n          _tipToHide = tipElement;\n\n          // Support v1.3+ $animate\n          // https://github.com/angular/angular.js/commit/bf0f5502b1bbfddc5cdd2f138efd9188b8c652a9\n          var promise = $animate.leave(tipElement, leaveAnimateCallback);\n          if(promise && promise.then) promise.then(leaveAnimateCallback);\n\n          $tooltip.$isShown = scope.$isShown = false;\n          safeDigest(scope);\n\n          // Unbind events\n          if(options.keyboard && tipElement !== null) {\n            unbindKeyboardEvents();\n          }\n\n          if(options.autoClose && tipElement !== null) {\n            unbindAutoCloseEvents();\n          }\n        };\n\n        function leaveAnimateCallback() {\n          scope.$emit(options.prefixEvent + '.hide', $tooltip);\n\n          // check if current tipElement still references\n          // the same element when hide was called\n          if (tipElement === _tipToHide) {\n            // Allow to blur the input when hidden, like when pressing enter key\n            if(_blur && options.trigger === 'focus') {\n              return element[0].blur();\n            }\n\n            // clean up child scopes\n            destroyTipElement();\n          }\n        }\n\n        $tooltip.toggle = function() {\n          $tooltip.$isShown ? $tooltip.leave() : $tooltip.enter();\n        };\n\n        $tooltip.focus = function() {\n          tipElement[0].focus();\n        };\n\n        $tooltip.setEnabled = function(isEnabled) {\n          options.bsEnabled = isEnabled;\n        };\n\n        // Protected methods\n\n        $tooltip.$applyPlacement = function() {\n          if(!tipElement) return;\n\n          // Determine if we're doing an auto or normal placement\n          var placement = options.placement,\n              autoToken = /\\s?auto?\\s?/i,\n              autoPlace  = autoToken.test(placement);\n\n          if (autoPlace) {\n            placement = placement.replace(autoToken, '') || defaults.placement;\n          }\n\n          // Need to add the position class before we get\n          // the offsets\n          tipElement.addClass(options.placement);\n\n          // Get the position of the target element\n          // and the height and width of the tooltip so we can center it.\n          var elementPosition = getPosition(),\n              tipWidth = tipElement.prop('offsetWidth'),\n              tipHeight = tipElement.prop('offsetHeight');\n\n          // If we're auto placing, we need to check the positioning\n          if (autoPlace) {\n            var originalPlacement = placement;\n            var container = options.container ? angular.element(document.querySelector(options.container)) : element.parent();\n            var containerPosition = getPosition(container);\n\n            // Determine if the vertical placement\n            if (originalPlacement.indexOf('bottom') >= 0 && elementPosition.bottom + tipHeight > containerPosition.bottom) {\n              placement = originalPlacement.replace('bottom', 'top');\n            } else if (originalPlacement.indexOf('top') >= 0 && elementPosition.top - tipHeight < containerPosition.top) {\n              placement = originalPlacement.replace('top', 'bottom');\n            }\n\n            // Determine the horizontal placement\n            // The exotic placements of left and right are opposite of the standard placements.  Their arrows are put on the left/right\n            // and flow in the opposite direction of their placement.\n            if ((originalPlacement === 'right' || originalPlacement === 'bottom-left' || originalPlacement === 'top-left') &&\n                elementPosition.right + tipWidth > containerPosition.width) {\n\n              placement = originalPlacement === 'right' ? 'left' : placement.replace('left', 'right');\n            } else if ((originalPlacement === 'left' || originalPlacement === 'bottom-right' || originalPlacement === 'top-right') &&\n                elementPosition.left - tipWidth < containerPosition.left) {\n\n              placement = originalPlacement === 'left' ? 'right' : placement.replace('right', 'left');\n            }\n\n            tipElement.removeClass(originalPlacement).addClass(placement);\n          }\n\n          // Get the tooltip's top and left coordinates to center it with this directive.\n          var tipPosition = getCalculatedOffset(placement, elementPosition, tipWidth, tipHeight);\n          applyPlacementCss(tipPosition.top, tipPosition.left);\n        };\n\n        $tooltip.$onKeyUp = function(evt) {\n          if (evt.which === 27 && $tooltip.$isShown) {\n            $tooltip.hide();\n            evt.stopPropagation();\n          }\n        };\n\n        $tooltip.$onFocusKeyUp = function(evt) {\n          if (evt.which === 27) {\n            element[0].blur();\n            evt.stopPropagation();\n          }\n        };\n\n        $tooltip.$onFocusElementMouseDown = function(evt) {\n          evt.preventDefault();\n          evt.stopPropagation();\n          // Some browsers do not auto-focus buttons (eg. Safari)\n          $tooltip.$isShown ? element[0].blur() : element[0].focus();\n        };\n\n        // bind/unbind events\n        function bindTriggerEvents() {\n          var triggers = options.trigger.split(' ');\n          angular.forEach(triggers, function(trigger) {\n            if(trigger === 'click') {\n              element.on('click', $tooltip.toggle);\n            } else if(trigger !== 'manual') {\n              element.on(trigger === 'hover' ? 'mouseenter' : 'focus', $tooltip.enter);\n              element.on(trigger === 'hover' ? 'mouseleave' : 'blur', $tooltip.leave);\n              nodeName === 'button' && trigger !== 'hover' && element.on(isTouch ? 'touchstart' : 'mousedown', $tooltip.$onFocusElementMouseDown);\n            }\n          });\n        }\n\n        function unbindTriggerEvents() {\n          var triggers = options.trigger.split(' ');\n          for (var i = triggers.length; i--;) {\n            var trigger = triggers[i];\n            if(trigger === 'click') {\n              element.off('click', $tooltip.toggle);\n            } else if(trigger !== 'manual') {\n              element.off(trigger === 'hover' ? 'mouseenter' : 'focus', $tooltip.enter);\n              element.off(trigger === 'hover' ? 'mouseleave' : 'blur', $tooltip.leave);\n              nodeName === 'button' && trigger !== 'hover' && element.off(isTouch ? 'touchstart' : 'mousedown', $tooltip.$onFocusElementMouseDown);\n            }\n          }\n        }\n\n        function bindKeyboardEvents() {\n          if(options.trigger !== 'focus') {\n            tipElement.on('keyup', $tooltip.$onKeyUp);\n          } else {\n            element.on('keyup', $tooltip.$onFocusKeyUp);\n          }\n        }\n\n        function unbindKeyboardEvents() {\n          if(options.trigger !== 'focus') {\n            tipElement.off('keyup', $tooltip.$onKeyUp);\n          } else {\n            element.off('keyup', $tooltip.$onFocusKeyUp);\n          }\n        }\n\n        var _autoCloseEventsBinded = false;\n        function bindAutoCloseEvents() {\n          // use timeout to hookup the events to prevent\n          // event bubbling from being processed imediately.\n          $timeout(function() {\n            // Stop propagation when clicking inside tooltip\n            tipElement.on('click', stopEventPropagation);\n\n            // Hide when clicking outside tooltip\n            $body.on('click', $tooltip.hide);\n\n            _autoCloseEventsBinded = true;\n          }, 0, false);\n        }\n\n        function unbindAutoCloseEvents() {\n          if (_autoCloseEventsBinded) {\n            tipElement.off('click', stopEventPropagation);\n            $body.off('click', $tooltip.hide);\n            _autoCloseEventsBinded = false;\n          }\n        }\n\n        function stopEventPropagation(event) {\n          event.stopPropagation();\n        }\n\n        // Private methods\n\n        function getPosition($element) {\n          $element = $element || (options.target || element);\n\n          var el = $element[0];\n\n          var elRect = el.getBoundingClientRect();\n          if (elRect.width === null) {\n            // width and height are missing in IE8, so compute them manually; see https://github.com/twbs/bootstrap/issues/14093\n            elRect = angular.extend({}, elRect, { width: elRect.right - elRect.left, height: elRect.bottom - elRect.top });\n          }\n\n          var elPos;\n          if (options.container === 'body') {\n            elPos = dimensions.offset(el);\n          } else {\n            elPos = dimensions.position(el);\n          }\n\n          return angular.extend({}, elRect, elPos);\n        }\n\n        function getCalculatedOffset(placement, position, actualWidth, actualHeight) {\n          var offset;\n          var split = placement.split('-');\n\n          switch (split[0]) {\n          case 'right':\n            offset = {\n              top: position.top + position.height / 2 - actualHeight / 2,\n              left: position.left + position.width\n            };\n            break;\n          case 'bottom':\n            offset = {\n              top: position.top + position.height,\n              left: position.left + position.width / 2 - actualWidth / 2\n            };\n            break;\n          case 'left':\n            offset = {\n              top: position.top + position.height / 2 - actualHeight / 2,\n              left: position.left - actualWidth\n            };\n            break;\n          default:\n            offset = {\n              top: position.top - actualHeight,\n              left: position.left + position.width / 2 - actualWidth / 2\n            };\n            break;\n          }\n\n          if(!split[1]) {\n            return offset;\n          }\n\n          // Add support for corners @todo css\n          if(split[0] === 'top' || split[0] === 'bottom') {\n            switch (split[1]) {\n            case 'left':\n              offset.left = position.left;\n              break;\n            case 'right':\n              offset.left =  position.left + position.width - actualWidth;\n            }\n          } else if(split[0] === 'left' || split[0] === 'right') {\n            switch (split[1]) {\n            case 'top':\n              offset.top = position.top - actualHeight;\n              break;\n            case 'bottom':\n              offset.top = position.top + position.height;\n            }\n          }\n\n          return offset;\n        }\n\n        function applyPlacementCss(top, left) {\n          tipElement.css({ top: top + 'px', left: left + 'px' });\n        }\n\n        function destroyTipElement() {\n          // Cancel pending callbacks\n          clearTimeout(timeout);\n\n          if($tooltip.$isShown && tipElement !== null) {\n            if(options.autoClose) {\n              unbindAutoCloseEvents();\n            }\n\n            if(options.keyboard) {\n              unbindKeyboardEvents();\n            }\n          }\n\n          if(tipScope) {\n            tipScope.$destroy();\n            tipScope = null;\n          }\n\n          if(tipElement) {\n            tipElement.remove();\n            tipElement = $tooltip.$element = null;\n          }\n        }\n\n        return $tooltip;\n\n      }\n\n      // Helper functions\n\n      function safeDigest(scope) {\n        scope.$$phase || (scope.$root && scope.$root.$$phase) || scope.$digest();\n      }\n\n      function findElement(query, element) {\n        return angular.element((element || document).querySelectorAll(query));\n      }\n\n      var fetchPromises = {};\n      function fetchTemplate(template) {\n        if(fetchPromises[template]) return fetchPromises[template];\n        return (fetchPromises[template] = $q.when($templateCache.get(template) || $http.get(template))\n        .then(function(res) {\n          if(angular.isObject(res)) {\n            $templateCache.put(template, res.data);\n            return res.data;\n          }\n          return res;\n        }));\n      }\n\n      return TooltipFactory;\n\n    }];\n\n  })\n\n  .directive('bsTooltip', [\"$window\", \"$location\", \"$sce\", \"$tooltip\", \"$$rAF\", function($window, $location, $sce, $tooltip, $$rAF) {\n\n    return {\n      restrict: 'EAC',\n      scope: true,\n      link: function postLink(scope, element, attr, transclusion) {\n\n        // Directive options\n        var options = {scope: scope};\n        angular.forEach(['template', 'contentTemplate', 'placement', 'container', 'target', 'delay', 'trigger', 'keyboard', 'html', 'animation', 'backdropAnimation', 'type', 'customClass', 'id'], function(key) {\n          if(angular.isDefined(attr[key])) options[key] = attr[key];\n        });\n\n        // overwrite inherited title value when no value specified\n        // fix for angular 1.3.1 531a8de72c439d8ddd064874bf364c00cedabb11\n        if (!scope.hasOwnProperty('title')){\n          scope.title = '';\n        }\n\n        // Observe scope attributes for change\n        attr.$observe('title', function(newValue) {\n          if (angular.isDefined(newValue) || !scope.hasOwnProperty('title')) {\n            var oldValue = scope.title;\n            scope.title = $sce.trustAsHtml(newValue);\n            angular.isDefined(oldValue) && $$rAF(function() {\n              tooltip && tooltip.$applyPlacement();\n            });\n          }\n        });\n\n        // Support scope as an object\n        attr.bsTooltip && scope.$watch(attr.bsTooltip, function(newValue, oldValue) {\n          if(angular.isObject(newValue)) {\n            angular.extend(scope, newValue);\n          } else {\n            scope.title = newValue;\n          }\n          angular.isDefined(oldValue) && $$rAF(function() {\n            tooltip && tooltip.$applyPlacement();\n          });\n        }, true);\n\n        // Visibility binding support\n        attr.bsShow && scope.$watch(attr.bsShow, function(newValue, oldValue) {\n          if(!tooltip || !angular.isDefined(newValue)) return;\n          if(angular.isString(newValue)) newValue = !!newValue.match(/true|,?(tooltip),?/i);\n          newValue === true ? tooltip.show() : tooltip.hide();\n        });\n\n        // Enabled binding support\n        attr.bsEnabled && scope.$watch(attr.bsEnabled, function(newValue, oldValue) {\n          // console.warn('scope.$watch(%s)', attr.bsEnabled, newValue, oldValue);\n          if(!tooltip || !angular.isDefined(newValue)) return;\n          if(angular.isString(newValue)) newValue = !!newValue.match(/true|1|,?(tooltip),?/i);\n          newValue === false ? tooltip.setEnabled(false) : tooltip.setEnabled(true);\n        });\n\n        // Initialize popover\n        var tooltip = $tooltip(element, options);\n\n        // Garbage collection\n        scope.$on('$destroy', function() {\n          if(tooltip) tooltip.destroy();\n          options = null;\n          tooltip = null;\n        });\n\n      }\n    };\n\n  }]);\n\n// Source: typeahead.js\nangular.module('mgcrea.ngStrap.typeahead', ['mgcrea.ngStrap.tooltip', 'mgcrea.ngStrap.helpers.parseOptions'])\n\n  .provider('$typeahead', function() {\n\n    var defaults = this.defaults = {\n      animation: 'am-fade',\n      prefixClass: 'typeahead',\n      prefixEvent: '$typeahead',\n      placement: 'bottom-left',\n      template: 'typeahead/typeahead.tpl.html',\n      trigger: 'focus',\n      container: false,\n      keyboard: true,\n      html: false,\n      delay: 0,\n      minLength: 1,\n      filter: 'filter',\n      limit: 6,\n      comparator: ''\n    };\n\n    this.$get = [\"$window\", \"$rootScope\", \"$tooltip\", \"$timeout\", function($window, $rootScope, $tooltip, $timeout) {\n\n      var bodyEl = angular.element($window.document.body);\n\n      function TypeaheadFactory(element, controller, config) {\n\n        var $typeahead = {};\n\n        // Common vars\n        var options = angular.extend({}, defaults, config);\n\n        $typeahead = $tooltip(element, options);\n        var parentScope = config.scope;\n        var scope = $typeahead.$scope;\n\n        scope.$resetMatches = function(){\n          scope.$matches = [];\n          scope.$activeIndex = 0;\n        };\n        scope.$resetMatches();\n\n        scope.$activate = function(index) {\n          scope.$$postDigest(function() {\n            $typeahead.activate(index);\n          });\n        };\n\n        scope.$select = function(index, evt) {\n          scope.$$postDigest(function() {\n            $typeahead.select(index);\n          });\n        };\n\n        scope.$isVisible = function() {\n          return $typeahead.$isVisible();\n        };\n\n        // Public methods\n\n        $typeahead.update = function(matches) {\n          scope.$matches = matches;\n          if(scope.$activeIndex >= matches.length) {\n            scope.$activeIndex = 0;\n          }\n        };\n\n        $typeahead.activate = function(index) {\n          scope.$activeIndex = index;\n        };\n\n        $typeahead.select = function(index) {\n          var value = scope.$matches[index].value;\n          // console.log('$setViewValue', value);\n          controller.$setViewValue(value);\n          controller.$render();\n          scope.$resetMatches();\n          if(parentScope) parentScope.$digest();\n          // Emit event\n          scope.$emit(options.prefixEvent + '.select', value, index, $typeahead);\n        };\n\n        // Protected methods\n\n        $typeahead.$isVisible = function() {\n          if(!options.minLength || !controller) {\n            return !!scope.$matches.length;\n          }\n          // minLength support\n          return scope.$matches.length && angular.isString(controller.$viewValue) && controller.$viewValue.length >= options.minLength;\n        };\n\n        $typeahead.$getIndex = function(value) {\n          var l = scope.$matches.length, i = l;\n          if(!l) return;\n          for(i = l; i--;) {\n            if(scope.$matches[i].value === value) break;\n          }\n          if(i < 0) return;\n          return i;\n        };\n\n        $typeahead.$onMouseDown = function(evt) {\n          // Prevent blur on mousedown\n          evt.preventDefault();\n          evt.stopPropagation();\n        };\n\n        $typeahead.$onKeyDown = function(evt) {\n          if(!/(38|40|13)/.test(evt.keyCode)) return;\n\n          // Let ngSubmit pass if the typeahead tip is hidden\n          if($typeahead.$isVisible()) {\n            evt.preventDefault();\n            evt.stopPropagation();\n          }\n\n          // Select with enter\n          if(evt.keyCode === 13 && scope.$matches.length) {\n            $typeahead.select(scope.$activeIndex);\n          }\n\n          // Navigate with keyboard\n          else if(evt.keyCode === 38 && scope.$activeIndex > 0) scope.$activeIndex--;\n          else if(evt.keyCode === 40 && scope.$activeIndex < scope.$matches.length - 1) scope.$activeIndex++;\n          else if(angular.isUndefined(scope.$activeIndex)) scope.$activeIndex = 0;\n          scope.$digest();\n        };\n\n        // Overrides\n\n        var show = $typeahead.show;\n        $typeahead.show = function() {\n          show();\n          // use timeout to hookup the events to prevent\n          // event bubbling from being processed imediately.\n          $timeout(function() {\n            $typeahead.$element.on('mousedown', $typeahead.$onMouseDown);\n            if(options.keyboard) {\n              element.on('keydown', $typeahead.$onKeyDown);\n            }\n          }, 0, false);\n        };\n\n        var hide = $typeahead.hide;\n        $typeahead.hide = function() {\n          $typeahead.$element.off('mousedown', $typeahead.$onMouseDown);\n          if(options.keyboard) {\n            element.off('keydown', $typeahead.$onKeyDown);\n          }\n          hide();\n        };\n\n        return $typeahead;\n\n      }\n\n      TypeaheadFactory.defaults = defaults;\n      return TypeaheadFactory;\n\n    }];\n\n  })\n\n  .directive('bsTypeahead', [\"$window\", \"$parse\", \"$q\", \"$typeahead\", \"$parseOptions\", function($window, $parse, $q, $typeahead, $parseOptions) {\n\n    var defaults = $typeahead.defaults;\n\n    return {\n      restrict: 'EAC',\n      require: 'ngModel',\n      link: function postLink(scope, element, attr, controller) {\n\n        // Directive options\n        var options = {scope: scope};\n        angular.forEach(['placement', 'container', 'delay', 'trigger', 'keyboard', 'html', 'animation', 'template', 'filter', 'limit', 'minLength', 'watchOptions', 'selectMode', 'comparator', 'id'], function(key) {\n          if(angular.isDefined(attr[key])) options[key] = attr[key];\n        });\n\n        // Build proper ngOptions\n        var filter = options.filter || defaults.filter;\n        var limit = options.limit || defaults.limit;\n        var comparator = options.comparator || defaults.comparator;\n\n        var ngOptions = attr.ngOptions;\n        if(filter) ngOptions += ' | ' + filter + ':$viewValue';\n        if (comparator) ngOptions += ':' + comparator;\n        if(limit) ngOptions += ' | limitTo:' + limit;\n        var parsedOptions = $parseOptions(ngOptions);\n\n        // Initialize typeahead\n        var typeahead = $typeahead(element, controller, options);\n\n        // Watch options on demand\n        if(options.watchOptions) {\n          // Watch ngOptions values before filtering for changes, drop function calls\n          var watchedOptions = parsedOptions.$match[7].replace(/\\|.+/, '').replace(/\\(.*\\)/g, '').trim();\n          scope.$watch(watchedOptions, function (newValue, oldValue) {\n            // console.warn('scope.$watch(%s)', watchedOptions, newValue, oldValue);\n            parsedOptions.valuesFn(scope, controller).then(function (values) {\n              typeahead.update(values);\n              controller.$render();\n            });\n          }, true);\n        }\n\n        // Watch model for changes\n        scope.$watch(attr.ngModel, function(newValue, oldValue) {\n          // console.warn('$watch', element.attr('ng-model'), newValue);\n          scope.$modelValue = newValue; // Publish modelValue on scope for custom templates\n          parsedOptions.valuesFn(scope, controller)\n          .then(function(values) {\n            // Prevent input with no future prospect if selectMode is truthy\n            // @TODO test selectMode\n            if(options.selectMode && !values.length && newValue.length > 0) {\n              controller.$setViewValue(controller.$viewValue.substring(0, controller.$viewValue.length - 1));\n              return;\n            }\n            if(values.length > limit) values = values.slice(0, limit);\n            var isVisible = typeahead.$isVisible();\n            isVisible && typeahead.update(values);\n            // Do not re-queue an update if a correct value has been selected\n            if(values.length === 1 && values[0].value === newValue) return;\n            !isVisible && typeahead.update(values);\n            // Queue a new rendering that will leverage collection loading\n            controller.$render();\n          });\n        });\n\n        // modelValue -> $formatters -> viewValue\n        controller.$formatters.push(function(modelValue) {\n          // console.warn('$formatter(\"%s\"): modelValue=%o (%o)', element.attr('ng-model'), modelValue, typeof modelValue);\n          var displayValue = parsedOptions.displayValue(modelValue);\n          return displayValue === undefined ? '' : displayValue;\n        });\n\n        // Model rendering in view\n        controller.$render = function () {\n          // console.warn('$render', element.attr('ng-model'), 'controller.$modelValue', typeof controller.$modelValue, controller.$modelValue, 'controller.$viewValue', typeof controller.$viewValue, controller.$viewValue);\n          if(controller.$isEmpty(controller.$viewValue)) return element.val('');\n          var index = typeahead.$getIndex(controller.$modelValue);\n          var selected = angular.isDefined(index) ? typeahead.$scope.$matches[index].label : controller.$viewValue;\n          selected = angular.isObject(selected) ? parsedOptions.displayValue(selected) : selected;\n          element.val(selected ? selected.toString().replace(/<(?:.|\\n)*?>/gm, '').trim() : '');\n        };\n\n        // Garbage collection\n        scope.$on('$destroy', function() {\n          if (typeahead) typeahead.destroy();\n          options = null;\n          typeahead = null;\n        });\n\n      }\n    };\n\n  }]);\n\n})(window, document);\n"
  },
  {
    "path": "flowable-ui-web/modeler/libs/angular-strap_2.1.6/angular-strap.tpl.js",
    "content": "/**\n * angular-strap\n * @version v2.1.6 - 2015-01-11\n * @link http://mgcrea.github.io/angular-strap\n * @author Olivier Louvignes (olivier@mg-crea.com)\n * @license MIT License, http://www.opensource.org/licenses/MIT\n */\n(function(window, document, undefined) {\n'use strict';\n\n// Source: alert.tpl.js\nangular.module('mgcrea.ngStrap.alert').run(['$templateCache', function($templateCache) {\n\n  $templateCache.put('alert/alert.tpl.html', '<div class=\"alert\" ng-class=\"[type ? \\'alert-\\' + type : null]\"><button type=\"button\" class=\"close\" ng-if=\"dismissable\" ng-click=\"$hide()\">&times;</button> <strong ng-bind=\"title\"></strong>&nbsp;<span ng-bind-html=\"content\"></span></div>');\n\n}]);\n\n// Source: aside.tpl.js\nangular.module('mgcrea.ngStrap.aside').run(['$templateCache', function($templateCache) {\n\n  $templateCache.put('aside/aside.tpl.html', '<div class=\"aside\" tabindex=\"-1\" role=\"dialog\"><div class=\"aside-dialog\"><div class=\"aside-content\"><div class=\"aside-header\" ng-show=\"title\"><button type=\"button\" class=\"close\" ng-click=\"$hide()\">&times;</button><h4 class=\"aside-title\" ng-bind=\"title\"></h4></div><div class=\"aside-body\" ng-bind=\"content\"></div><div class=\"aside-footer\"><button type=\"button\" class=\"btn btn-default\" ng-click=\"$hide()\">Close</button></div></div></div></div>');\n\n}]);\n\n// Source: datepicker.tpl.js\nangular.module('mgcrea.ngStrap.datepicker').run(['$templateCache', function($templateCache) {\n\n  $templateCache.put('datepicker/datepicker.tpl.html', '<div class=\"dropdown-menu datepicker\" ng-class=\"\\'datepicker-mode-\\' + $mode\" style=\"max-width: 320px\"><table style=\"table-layout: fixed; height: 100%; width: 100%\"><thead><tr class=\"text-center\"><th><button tabindex=\"-1\" type=\"button\" class=\"btn btn-default pull-left\" ng-click=\"$selectPane(-1)\"><i class=\"{{$iconLeft}}\"></i></button></th><th colspan=\"{{ rows[0].length - 2 }}\"><button tabindex=\"-1\" type=\"button\" class=\"btn btn-default btn-block text-strong\" ng-click=\"$toggleMode()\"><strong style=\"text-transform: capitalize\" ng-bind=\"title\"></strong></button></th><th><button tabindex=\"-1\" type=\"button\" class=\"btn btn-default pull-right\" ng-click=\"$selectPane(+1)\"><i class=\"{{$iconRight}}\"></i></button></th></tr><tr ng-show=\"showLabels\" ng-bind-html=\"labels\"></tr></thead><tbody><tr ng-repeat=\"(i, row) in rows\" height=\"{{ 100 / rows.length }}%\"><td class=\"text-center\" ng-repeat=\"(j, el) in row\"><button tabindex=\"-1\" type=\"button\" class=\"btn btn-default\" style=\"width: 100%\" ng-class=\"{\\'btn-primary\\': el.selected, \\'btn-info btn-today\\': el.isToday && !el.selected}\" ng-click=\"$select(el.date)\" ng-disabled=\"el.disabled\"><span ng-class=\"{\\'text-muted\\': el.muted}\" ng-bind=\"el.label\"></span></button></td></tr></tbody></table></div>');\n\n}]);\n\n// Source: dropdown.tpl.js\nangular.module('mgcrea.ngStrap.dropdown').run(['$templateCache', function($templateCache) {\n\n  $templateCache.put('dropdown/dropdown.tpl.html', '<ul tabindex=\"-1\" class=\"dropdown-menu\" role=\"menu\"><li role=\"presentation\" ng-class=\"{divider: item.divider}\" ng-repeat=\"item in content\"><a role=\"menuitem\" tabindex=\"-1\" ng-href=\"{{item.href}}\" ng-if=\"!item.divider && item.href\" target=\"{{item.target || \\'\\'}}\" ng-bind=\"item.text\"></a> <a role=\"menuitem\" tabindex=\"-1\" href=\"javascript:void(0)\" ng-if=\"!item.divider && item.click\" ng-click=\"$eval(item.click);$hide()\" ng-bind=\"item.text\"></a></li></ul>');\n\n}]);\n\n// Source: modal.tpl.js\nangular.module('mgcrea.ngStrap.modal').run(['$templateCache', function($templateCache) {\n\n  $templateCache.put('modal/modal.tpl.html', '<div class=\"modal\" tabindex=\"-1\" role=\"dialog\"><div class=\"modal-dialog\"><div class=\"modal-content\"><div class=\"modal-header\" ng-show=\"title\"><button type=\"button\" class=\"close\" ng-click=\"$hide()\">&times;</button><h4 class=\"modal-title\" ng-bind=\"title\"></h4></div><div class=\"modal-body\" ng-bind=\"content\"></div><div class=\"modal-footer\"><button type=\"button\" class=\"btn btn-default\" ng-click=\"$hide()\">Close</button></div></div></div></div>');\n\n}]);\n\n// Source: popover.tpl.js\nangular.module('mgcrea.ngStrap.popover').run(['$templateCache', function($templateCache) {\n\n  $templateCache.put('popover/popover.tpl.html', '<div class=\"popover\"><div class=\"arrow\"></div><h3 class=\"popover-title\" ng-bind=\"title\" ng-show=\"title\"></h3><div class=\"popover-content\" ng-bind=\"content\"></div></div>');\n\n}]);\n\n// Source: select.tpl.js\nangular.module('mgcrea.ngStrap.select').run(['$templateCache', function($templateCache) {\n\n  $templateCache.put('select/select.tpl.html', '<ul tabindex=\"-1\" class=\"select dropdown-menu\" ng-show=\"$isVisible()\" role=\"select\"><li ng-if=\"$showAllNoneButtons\"><div class=\"btn-group\" style=\"margin-bottom: 5px; margin-left: 5px\"><button type=\"button\" class=\"btn btn-default btn-xs\" ng-click=\"$selectAll()\">{{$allText}}</button> <button type=\"button\" class=\"btn btn-default btn-xs\" ng-click=\"$selectNone()\">{{$noneText}}</button></div></li><li role=\"presentation\" ng-repeat=\"match in $matches\" ng-class=\"{active: $isActive($index)}\"><a style=\"cursor: default\" role=\"menuitem\" tabindex=\"-1\" ng-click=\"$select($index, $event)\"><i class=\"{{$iconCheckmark}} pull-right\" ng-if=\"$isMultiple && $isActive($index)\"></i> <span ng-bind=\"match.label\"></span></a></li></ul>');\n\n}]);\n\n// Source: tab.tpl.js\nangular.module('mgcrea.ngStrap.tab').run(['$templateCache', function($templateCache) {\n\n  $templateCache.put('tab/tab.tpl.html', '<ul class=\"nav\" ng-class=\"$navClass\" role=\"tablist\"><li ng-repeat=\"$pane in $panes track by $index\" ng-class=\"$index == $panes.$active ? $activeClass : \\'\\'\"><a role=\"tab\" data-toggle=\"tab\" ng-click=\"$setActive($index)\" data-index=\"{{ $index }}\" ng-bind-html=\"$pane.title\"></a></li></ul><div ng-transclude class=\"tab-content\"></div>');\n\n}]);\n\n// Source: timepicker.tpl.js\nangular.module('mgcrea.ngStrap.timepicker').run(['$templateCache', function($templateCache) {\n\n  $templateCache.put('timepicker/timepicker.tpl.html', '<div class=\"dropdown-menu timepicker\" style=\"min-width: 0px;width: auto\"><table height=\"100%\"><thead><tr class=\"text-center\"><th><button tabindex=\"-1\" type=\"button\" class=\"btn btn-default pull-left\" ng-click=\"$arrowAction(-1, 0)\"><i class=\"{{ $iconUp }}\"></i></button></th><th>&nbsp;</th><th><button tabindex=\"-1\" type=\"button\" class=\"btn btn-default pull-left\" ng-click=\"$arrowAction(-1, 1)\"><i class=\"{{ $iconUp }}\"></i></button></th></tr></thead><tbody><tr ng-repeat=\"(i, row) in rows\"><td class=\"text-center\"><button tabindex=\"-1\" style=\"width: 100%\" type=\"button\" class=\"btn btn-default\" ng-class=\"{\\'btn-primary\\': row[0].selected}\" ng-click=\"$select(row[0].date, 0)\" ng-disabled=\"row[0].disabled\"><span ng-class=\"{\\'text-muted\\': row[0].muted}\" ng-bind=\"row[0].label\"></span></button></td><td><span ng-bind=\"i == midIndex ? timeSeparator : \\' \\'\"></span></td><td class=\"text-center\"><button tabindex=\"-1\" ng-if=\"row[1].date\" style=\"width: 100%\" type=\"button\" class=\"btn btn-default\" ng-class=\"{\\'btn-primary\\': row[1].selected}\" ng-click=\"$select(row[1].date, 1)\" ng-disabled=\"row[1].disabled\"><span ng-class=\"{\\'text-muted\\': row[1].muted}\" ng-bind=\"row[1].label\"></span></button></td><td ng-if=\"showAM\">&nbsp;</td><td ng-if=\"showAM\"><button tabindex=\"-1\" ng-show=\"i == midIndex - !isAM * 1\" style=\"width: 100%\" type=\"button\" ng-class=\"{\\'btn-primary\\': !!isAM}\" class=\"btn btn-default\" ng-click=\"$switchMeridian()\" ng-disabled=\"el.disabled\">AM</button> <button tabindex=\"-1\" ng-show=\"i == midIndex + 1 - !isAM * 1\" style=\"width: 100%\" type=\"button\" ng-class=\"{\\'btn-primary\\': !isAM}\" class=\"btn btn-default\" ng-click=\"$switchMeridian()\" ng-disabled=\"el.disabled\">PM</button></td></tr></tbody><tfoot><tr class=\"text-center\"><th><button tabindex=\"-1\" type=\"button\" class=\"btn btn-default pull-left\" ng-click=\"$arrowAction(1, 0)\"><i class=\"{{ $iconDown }}\"></i></button></th><th>&nbsp;</th><th><button tabindex=\"-1\" type=\"button\" class=\"btn btn-default pull-left\" ng-click=\"$arrowAction(1, 1)\"><i class=\"{{ $iconDown }}\"></i></button></th></tr></tfoot></table></div>');\n\n}]);\n\n// Source: tooltip.tpl.js\nangular.module('mgcrea.ngStrap.tooltip').run(['$templateCache', function($templateCache) {\n\n  $templateCache.put('tooltip/tooltip.tpl.html', '<div class=\"tooltip in\" ng-show=\"title\"><div class=\"tooltip-arrow\"></div><div class=\"tooltip-inner\" ng-bind=\"title\"></div></div>');\n\n}]);\n\n// Source: typeahead.tpl.js\nangular.module('mgcrea.ngStrap.typeahead').run(['$templateCache', function($templateCache) {\n\n  $templateCache.put('typeahead/typeahead.tpl.html', '<ul tabindex=\"-1\" class=\"typeahead dropdown-menu\" ng-show=\"$isVisible()\" role=\"select\"><li role=\"presentation\" ng-repeat=\"match in $matches\" ng-class=\"{active: $index == $activeIndex}\"><a role=\"menuitem\" tabindex=\"-1\" ng-click=\"$select($index, $event)\" ng-bind=\"match.label\"></a></li></ul>');\n\n}]);\n\n\n})(window, document);\n"
  },
  {
    "path": "flowable-ui-web/modeler/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": "flowable-ui-web/modeler/libs/angular-translate-loader-static-files/angular-translate-loader-static-files.js",
    "content": "/*!\n * angular-translate - v2.15.1 - 2017-03-04\n * \n * Copyright (c) 2017 The angular-translate team, Pascal Precht; Licensed MIT\n */\n(function (root, factory) {\n  if (typeof define === 'function' && define.amd) {\n    // AMD. Register as an anonymous module unless amdModuleId is set\n    define([], function () {\n      return (factory());\n    });\n  } else if (typeof exports === 'object') {\n    // Node. Does not work with strict CommonJS, but\n    // only CommonJS-like environments that support module.exports,\n    // like Node.\n    module.exports = factory();\n  } else {\n    factory();\n  }\n}(this, function () {\n\n$translateStaticFilesLoader.$inject = ['$q', '$http'];\nangular.module('pascalprecht.translate')\n/**\n * @ngdoc object\n * @name pascalprecht.translate.$translateStaticFilesLoader\n * @requires $q\n * @requires $http\n *\n * @description\n * Creates a loading function for a typical static file url pattern:\n * \"lang-en_US.json\", \"lang-de_DE.json\", etc. Using this builder,\n * the response of these urls must be an object of key-value pairs.\n *\n * @param {object} options Options object, which gets prefix, suffix, key, and fileMap\n */\n.factory('$translateStaticFilesLoader', $translateStaticFilesLoader);\n\nfunction $translateStaticFilesLoader($q, $http) {\n\n  'use strict';\n\n  return function (options) {\n\n    if (!options || (!angular.isArray(options.files) && (!angular.isString(options.prefix) || !angular.isString(options.suffix)))) {\n      throw new Error('Couldn\\'t load static files, no files and prefix or suffix specified!');\n    }\n\n    if (!options.files) {\n      options.files = [{\n        prefix: options.prefix,\n        suffix: options.suffix\n      }];\n    }\n\n    var load = function (file) {\n      if (!file || (!angular.isString(file.prefix) || !angular.isString(file.suffix))) {\n        throw new Error('Couldn\\'t load static file, no prefix or suffix specified!');\n      }\n\n      var fileUrl = [\n        file.prefix,\n        options.key,\n        file.suffix\n      ].join('');\n\n      if (angular.isObject(options.fileMap) && options.fileMap[fileUrl]) {\n        fileUrl = options.fileMap[fileUrl];\n      }\n\n      return $http(angular.extend({\n        url: fileUrl,\n        method: 'GET'\n      }, options.$http))\n        .then(function(result) {\n          return result.data;\n        }, function () {\n          return $q.reject(options.key);\n        });\n    };\n\n    var promises = [],\n        length = options.files.length;\n\n    for (var i = 0; i < length; i++) {\n      promises.push(load({\n        prefix: options.files[i].prefix,\n        key: options.key,\n        suffix: options.files[i].suffix\n      }));\n    }\n\n    return $q.all(promises)\n      .then(function (data) {\n        var length = data.length,\n            mergedData = {};\n\n        for (var i = 0; i < length; i++) {\n          for (var key in data[i]) {\n            mergedData[key] = data[i][key];\n          }\n        }\n\n        return mergedData;\n      });\n  };\n}\n\n$translateStaticFilesLoader.displayName = '$translateStaticFilesLoader';\nreturn 'pascalprecht.translate';\n\n}));\n"
  },
  {
    "path": "flowable-ui-web/modeler/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": "flowable-ui-web/modeler/libs/angular-translate-storage-cookie/angular-translate-storage-cookie.js",
    "content": "/*!\n * angular-translate - v2.15.1 - 2017-03-04\n * \n * Copyright (c) 2017 The angular-translate team, Pascal Precht; Licensed MIT\n */\n(function (root, factory) {\n  if (typeof define === 'function' && define.amd) {\n    // AMD. Register as an anonymous module unless amdModuleId is set\n    define([], function () {\n      return (factory());\n    });\n  } else if (typeof exports === 'object') {\n    // Node. Does not work with strict CommonJS, but\n    // only CommonJS-like environments that support module.exports,\n    // like Node.\n    module.exports = factory();\n  } else {\n    factory();\n  }\n}(this, function () {\n\n$translateCookieStorageFactory.$inject = ['$injector'];\nangular.module('pascalprecht.translate')\n\n/**\n * @ngdoc object\n * @name pascalprecht.translate.$translateCookieStorage\n * @requires $cookieStore\n *\n * @description\n * Abstraction layer for cookieStore. This service is used when telling angular-translate\n * to use cookieStore as storage.\n *\n */\n  .factory('$translateCookieStorage', $translateCookieStorageFactory);\n\nfunction $translateCookieStorageFactory($injector) {\n\n  'use strict';\n\n  // Since AngularJS 1.4, $cookieStore is deprecated\n  var delegate;\n  if (angular.version.major === 1 && angular.version.minor >= 4) {\n    var $cookies = $injector.get('$cookies');\n    delegate = {\n      get : function (key) {\n        return $cookies.get(key);\n      },\n      put : function (key, value) {\n        $cookies.put(key, value);\n      }\n    };\n  } else {\n    var $cookieStore = $injector.get('$cookieStore');\n    delegate = {\n      get : function (key) {\n        return $cookieStore.get(key);\n      },\n      put : function (key, value) {\n        $cookieStore.put(key, value);\n      }\n    };\n  }\n\n  var $translateCookieStorage = {\n\n    /**\n     * @ngdoc function\n     * @name pascalprecht.translate.$translateCookieStorage#get\n     * @methodOf pascalprecht.translate.$translateCookieStorage\n     *\n     * @description\n     * Returns an item from cookieStorage by given name.\n     *\n     * @param {string} name Item name\n     * @return {string} Value of item name\n     */\n    get : function (name) {\n      return delegate.get(name);\n    },\n\n    /**\n     * @ngdoc function\n     * @name pascalprecht.translate.$translateCookieStorage#set\n     * @methodOf pascalprecht.translate.$translateCookieStorage\n     *\n     * @description\n     * Sets an item in cookieStorage by given name.\n     *\n     * @deprecated use #put\n     *\n     * @param {string} name Item name\n     * @param {string} value Item value\n     */\n    set : function (name, value) {\n      delegate.put(name, value);\n    },\n\n    /**\n     * @ngdoc function\n     * @name pascalprecht.translate.$translateCookieStorage#put\n     * @methodOf pascalprecht.translate.$translateCookieStorage\n     *\n     * @description\n     * Sets an item in cookieStorage by given name.\n     *\n     * @param {string} name Item name\n     * @param {string} value Item value\n     */\n    put : function (name, value) {\n      delegate.put(name, value);\n    }\n  };\n\n  return $translateCookieStorage;\n}\n\n$translateCookieStorageFactory.displayName = '$translateCookieStorage';\nreturn 'pascalprecht.translate';\n\n}));\n"
  },
  {
    "path": "flowable-ui-web/modeler/libs/angular-translate_2.15.1/angular-translate.js",
    "content": "/*!\n * angular-translate - v2.15.1 - 2017-03-04\n * \n * Copyright (c) 2017 The angular-translate team, Pascal Precht; Licensed MIT\n */\n(function (root, factory) {\n  if (typeof define === 'function' && define.amd) {\n    // AMD. Register as an anonymous module unless amdModuleId is set\n    define([], function () {\n      return (factory());\n    });\n  } else if (typeof exports === 'object') {\n    // Node. Does not work with strict CommonJS, but\n    // only CommonJS-like environments that support module.exports,\n    // like Node.\n    module.exports = factory();\n  } else {\n    factory();\n  }\n}(this, function () {\n\n/**\n * @ngdoc overview\n * @name pascalprecht.translate\n *\n * @description\n * The main module which holds everything together.\n */\nrunTranslate.$inject = ['$translate'];\n$translate.$inject = ['$STORAGE_KEY', '$windowProvider', '$translateSanitizationProvider', 'pascalprechtTranslateOverrider'];\n$translateDefaultInterpolation.$inject = ['$interpolate', '$translateSanitization'];\ntranslateDirective.$inject = ['$translate', '$interpolate', '$compile', '$parse', '$rootScope'];\ntranslateAttrDirective.$inject = ['$translate', '$rootScope'];\ntranslateCloakDirective.$inject = ['$translate', '$rootScope'];\ntranslateFilterFactory.$inject = ['$parse', '$translate'];\n$translationCache.$inject = ['$cacheFactory'];\nangular.module('pascalprecht.translate', ['ng'])\n  .run(runTranslate);\n\nfunction runTranslate($translate) {\n\n  'use strict';\n\n  var key = $translate.storageKey(),\n    storage = $translate.storage();\n\n  var fallbackFromIncorrectStorageValue = function () {\n    var preferred = $translate.preferredLanguage();\n    if (angular.isString(preferred)) {\n      $translate.use(preferred);\n      // $translate.use() will also remember the language.\n      // So, we don't need to call storage.put() here.\n    } else {\n      storage.put(key, $translate.use());\n    }\n  };\n\n  fallbackFromIncorrectStorageValue.displayName = 'fallbackFromIncorrectStorageValue';\n\n  if (storage) {\n    if (!storage.get(key)) {\n      fallbackFromIncorrectStorageValue();\n    } else {\n      $translate.use(storage.get(key))['catch'](fallbackFromIncorrectStorageValue);\n    }\n  } else if (angular.isString($translate.preferredLanguage())) {\n    $translate.use($translate.preferredLanguage());\n  }\n}\n\nrunTranslate.displayName = 'runTranslate';\n\n/**\n * @ngdoc object\n * @name pascalprecht.translate.$translateSanitizationProvider\n *\n * @description\n *\n * Configurations for $translateSanitization\n */\nangular.module('pascalprecht.translate').provider('$translateSanitization', $translateSanitizationProvider);\n\nfunction $translateSanitizationProvider () {\n\n  'use strict';\n\n  var $sanitize,\n      $sce,\n      currentStrategy = null, // TODO change to either 'sanitize', 'escape' or ['sanitize', 'escapeParameters'] in 3.0.\n      hasConfiguredStrategy = false,\n      hasShownNoStrategyConfiguredWarning = false,\n      strategies;\n\n  /**\n   * Definition of a sanitization strategy function\n   * @callback StrategyFunction\n   * @param {string|object} value - value to be sanitized (either a string or an interpolated value map)\n   * @param {string} mode - either 'text' for a string (translation) or 'params' for the interpolated params\n   * @return {string|object}\n   */\n\n  /**\n   * @ngdoc property\n   * @name strategies\n   * @propertyOf pascalprecht.translate.$translateSanitizationProvider\n   *\n   * @description\n   * Following strategies are built-in:\n   * <dl>\n   *   <dt>sanitize</dt>\n   *   <dd>Sanitizes HTML in the translation text using $sanitize</dd>\n   *   <dt>escape</dt>\n   *   <dd>Escapes HTML in the translation</dd>\n   *   <dt>sanitizeParameters</dt>\n   *   <dd>Sanitizes HTML in the values of the interpolation parameters using $sanitize</dd>\n   *   <dt>escapeParameters</dt>\n   *   <dd>Escapes HTML in the values of the interpolation parameters</dd>\n   *   <dt>escaped</dt>\n   *   <dd>Support legacy strategy name 'escaped' for backwards compatibility (will be removed in 3.0)</dd>\n   * </dl>\n   *\n   */\n\n  strategies = {\n    sanitize: function (value, mode/*, context*/) {\n      if (mode === 'text') {\n        value = htmlSanitizeValue(value);\n      }\n      return value;\n    },\n    escape: function (value, mode/*, context*/) {\n      if (mode === 'text') {\n        value = htmlEscapeValue(value);\n      }\n      return value;\n    },\n    sanitizeParameters: function (value, mode/*, context*/) {\n      if (mode === 'params') {\n        value = mapInterpolationParameters(value, htmlSanitizeValue);\n      }\n      return value;\n    },\n    escapeParameters: function (value, mode/*, context*/) {\n      if (mode === 'params') {\n        value = mapInterpolationParameters(value, htmlEscapeValue);\n      }\n      return value;\n    },\n    sce: function (value, mode, context) {\n      if (mode === 'text') {\n        value = htmlTrustValue(value);\n      } else if (mode === 'params') {\n        if (context !== 'filter') {\n          // do html escape in filter context #1101\n          value = mapInterpolationParameters(value, htmlEscapeValue);\n        }\n      }\n      return value;\n    },\n    sceParameters: function (value, mode/*, context*/) {\n      if (mode === 'params') {\n        value = mapInterpolationParameters(value, htmlTrustValue);\n      }\n      return value;\n    }\n  };\n  // Support legacy strategy name 'escaped' for backwards compatibility.\n  // TODO should be removed in 3.0\n  strategies.escaped = strategies.escapeParameters;\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateSanitizationProvider#addStrategy\n   * @methodOf pascalprecht.translate.$translateSanitizationProvider\n   *\n   * @description\n   * Adds a sanitization strategy to the list of known strategies.\n   *\n   * @param {string} strategyName - unique key for a strategy\n   * @param {StrategyFunction} strategyFunction - strategy function\n   * @returns {object} this\n   */\n  this.addStrategy = function (strategyName, strategyFunction) {\n    strategies[strategyName] = strategyFunction;\n    return this;\n  };\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateSanitizationProvider#removeStrategy\n   * @methodOf pascalprecht.translate.$translateSanitizationProvider\n   *\n   * @description\n   * Removes a sanitization strategy from the list of known strategies.\n   *\n   * @param {string} strategyName - unique key for a strategy\n   * @returns {object} this\n   */\n  this.removeStrategy = function (strategyName) {\n    delete strategies[strategyName];\n    return this;\n  };\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateSanitizationProvider#useStrategy\n   * @methodOf pascalprecht.translate.$translateSanitizationProvider\n   *\n   * @description\n   * Selects a sanitization strategy. When an array is provided the strategies will be executed in order.\n   *\n   * @param {string|StrategyFunction|array} strategy The sanitization strategy / strategies which should be used. Either a name of an existing strategy, a custom strategy function, or an array consisting of multiple names and / or custom functions.\n   * @returns {object} this\n   */\n  this.useStrategy = function (strategy) {\n    hasConfiguredStrategy = true;\n    currentStrategy = strategy;\n    return this;\n  };\n\n  /**\n   * @ngdoc object\n   * @name pascalprecht.translate.$translateSanitization\n   * @requires $injector\n   * @requires $log\n   *\n   * @description\n   * Sanitizes interpolation parameters and translated texts.\n   *\n   */\n  this.$get = ['$injector', '$log', function ($injector, $log) {\n\n    var cachedStrategyMap = {};\n\n    var applyStrategies = function (value, mode, context, selectedStrategies) {\n      angular.forEach(selectedStrategies, function (selectedStrategy) {\n        if (angular.isFunction(selectedStrategy)) {\n          value = selectedStrategy(value, mode, context);\n        } else if (angular.isFunction(strategies[selectedStrategy])) {\n          value = strategies[selectedStrategy](value, mode, context);\n        } else if (angular.isString(strategies[selectedStrategy])) {\n          if (!cachedStrategyMap[strategies[selectedStrategy]]) {\n            try {\n              cachedStrategyMap[strategies[selectedStrategy]] = $injector.get(strategies[selectedStrategy]);\n            } catch (e) {\n              cachedStrategyMap[strategies[selectedStrategy]] = function() {};\n              throw new Error('pascalprecht.translate.$translateSanitization: Unknown sanitization strategy: \\'' + selectedStrategy + '\\'');\n            }\n          }\n          value = cachedStrategyMap[strategies[selectedStrategy]](value, mode, context);\n        } else {\n          throw new Error('pascalprecht.translate.$translateSanitization: Unknown sanitization strategy: \\'' + selectedStrategy + '\\'');\n        }\n      });\n      return value;\n    };\n\n    // TODO: should be removed in 3.0\n    var showNoStrategyConfiguredWarning = function () {\n      if (!hasConfiguredStrategy && !hasShownNoStrategyConfiguredWarning) {\n        $log.warn('pascalprecht.translate.$translateSanitization: No sanitization strategy has been configured. This can have serious security implications. See http://angular-translate.github.io/docs/#/guide/19_security for details.');\n        hasShownNoStrategyConfiguredWarning = true;\n      }\n    };\n\n    if ($injector.has('$sanitize')) {\n      $sanitize = $injector.get('$sanitize');\n    }\n    if ($injector.has('$sce')) {\n      $sce = $injector.get('$sce');\n    }\n\n    return {\n      /**\n       * @ngdoc function\n       * @name pascalprecht.translate.$translateSanitization#useStrategy\n       * @methodOf pascalprecht.translate.$translateSanitization\n       *\n       * @description\n       * Selects a sanitization strategy. When an array is provided the strategies will be executed in order.\n       *\n       * @param {string|StrategyFunction|array} strategy The sanitization strategy / strategies which should be used. Either a name of an existing strategy, a custom strategy function, or an array consisting of multiple names and / or custom functions.\n       */\n      useStrategy: (function (self) {\n        return function (strategy) {\n          self.useStrategy(strategy);\n        };\n      })(this),\n\n      /**\n       * @ngdoc function\n       * @name pascalprecht.translate.$translateSanitization#sanitize\n       * @methodOf pascalprecht.translate.$translateSanitization\n       *\n       * @description\n       * Sanitizes a value.\n       *\n       * @param {string|object} value The value which should be sanitized.\n       * @param {string} mode The current sanitization mode, either 'params' or 'text'.\n       * @param {string|StrategyFunction|array} [strategy] Optional custom strategy which should be used instead of the currently selected strategy.\n       * @param {string} [context] The context of this call: filter, service. Default is service\n       * @returns {string|object} sanitized value\n       */\n      sanitize: function (value, mode, strategy, context) {\n        if (!currentStrategy) {\n          showNoStrategyConfiguredWarning();\n        }\n\n        if (!strategy && strategy !== null) {\n          strategy = currentStrategy;\n        }\n\n        if (!strategy) {\n          return value;\n        }\n\n        if (!context) {\n          context = 'service';\n        }\n\n        var selectedStrategies = angular.isArray(strategy) ? strategy : [strategy];\n        return applyStrategies(value, mode, context, selectedStrategies);\n      }\n    };\n  }];\n\n  var htmlEscapeValue = function (value) {\n    var element = angular.element('<div></div>');\n    element.text(value); // not chainable, see #1044\n    return element.html();\n  };\n\n  var htmlSanitizeValue = function (value) {\n    if (!$sanitize) {\n      throw new Error('pascalprecht.translate.$translateSanitization: Error cannot find $sanitize service. Either include the ngSanitize module (https://docs.angularjs.org/api/ngSanitize) or use a sanitization strategy which does not depend on $sanitize, such as \\'escape\\'.');\n    }\n    return $sanitize(value);\n  };\n\n  var htmlTrustValue = function (value) {\n    if (!$sce) {\n      throw new Error('pascalprecht.translate.$translateSanitization: Error cannot find $sce service.');\n    }\n    return $sce.trustAsHtml(value);\n  };\n\n  var mapInterpolationParameters = function (value, iteratee, stack) {\n    if (angular.isDate(value)) {\n      return value;\n    } else if (angular.isObject(value)) {\n      var result = angular.isArray(value) ? [] : {};\n\n      if (!stack) {\n        stack = [];\n      } else {\n        if (stack.indexOf(value) > -1) {\n          throw new Error('pascalprecht.translate.$translateSanitization: Error cannot interpolate parameter due recursive object');\n        }\n      }\n\n      stack.push(value);\n      angular.forEach(value, function (propertyValue, propertyKey) {\n\n        /* Skipping function properties. */\n        if (angular.isFunction(propertyValue)) {\n          return;\n        }\n\n        result[propertyKey] = mapInterpolationParameters(propertyValue, iteratee, stack);\n      });\n      stack.splice(-1, 1); // remove last\n\n      return result;\n    } else if (angular.isNumber(value)) {\n      return value;\n    } else if (!angular.isUndefined(value) && value !== null) {\n      return iteratee(value);\n    } else {\n      return value;\n    }\n  };\n}\n\n/**\n * @ngdoc object\n * @name pascalprecht.translate.$translateProvider\n * @description\n *\n * $translateProvider allows developers to register translation-tables, asynchronous loaders\n * and similar to configure translation behavior directly inside of a module.\n *\n */\nangular.module('pascalprecht.translate')\n  .constant('pascalprechtTranslateOverrider', {})\n  .provider('$translate', $translate);\n\nfunction $translate($STORAGE_KEY, $windowProvider, $translateSanitizationProvider, pascalprechtTranslateOverrider) {\n\n  'use strict';\n\n  var $translationTable = {},\n    $preferredLanguage,\n    $availableLanguageKeys = [],\n    $languageKeyAliases,\n    $fallbackLanguage,\n    $fallbackWasString,\n    $uses,\n    $nextLang,\n    $storageFactory,\n    $storageKey = $STORAGE_KEY,\n    $storagePrefix,\n    $missingTranslationHandlerFactory,\n    $interpolationFactory,\n    $interpolatorFactories = [],\n    $loaderFactory,\n    $cloakClassName = 'translate-cloak',\n    $loaderOptions,\n    $notFoundIndicatorLeft,\n    $notFoundIndicatorRight,\n    $postCompilingEnabled = false,\n    $forceAsyncReloadEnabled = false,\n    $nestedObjectDelimeter = '.',\n    $isReady = false,\n    $keepContent = false,\n    loaderCache,\n    directivePriority = 0,\n    statefulFilter = true,\n    postProcessFn,\n    uniformLanguageTagResolver = 'default',\n    languageTagResolver = {\n      'default' : function (tag) {\n        return (tag || '').split('-').join('_');\n      },\n      java : function (tag) {\n        var temp = (tag || '').split('-').join('_');\n        var parts = temp.split('_');\n        return parts.length > 1 ? (parts[0].toLowerCase() + '_' + parts[1].toUpperCase()) : temp;\n      },\n      bcp47 : function (tag) {\n        var temp = (tag || '').split('_').join('-');\n        var parts = temp.split('-');\n        return parts.length > 1 ? (parts[0].toLowerCase() + '-' + parts[1].toUpperCase()) : temp;\n      },\n      'iso639-1' : function (tag) {\n        var temp = (tag || '').split('_').join('-');\n        var parts = temp.split('-');\n        return parts[0].toLowerCase();\n      }\n    };\n\n  var version = '2.15.1';\n\n  // tries to determine the browsers language\n  var getFirstBrowserLanguage = function () {\n\n    // internal purpose only\n    if (angular.isFunction(pascalprechtTranslateOverrider.getLocale)) {\n      return pascalprechtTranslateOverrider.getLocale();\n    }\n\n    var nav = $windowProvider.$get().navigator,\n      browserLanguagePropertyKeys = ['language', 'browserLanguage', 'systemLanguage', 'userLanguage'],\n      i,\n      language;\n\n    // support for HTML 5.1 \"navigator.languages\"\n    if (angular.isArray(nav.languages)) {\n      for (i = 0; i < nav.languages.length; i++) {\n        language = nav.languages[i];\n        if (language && language.length) {\n          return language;\n        }\n      }\n    }\n\n    // support for other well known properties in browsers\n    for (i = 0; i < browserLanguagePropertyKeys.length; i++) {\n      language = nav[browserLanguagePropertyKeys[i]];\n      if (language && language.length) {\n        return language;\n      }\n    }\n\n    return null;\n  };\n  getFirstBrowserLanguage.displayName = 'angular-translate/service: getFirstBrowserLanguage';\n\n  // tries to determine the browsers locale\n  var getLocale = function () {\n    var locale = getFirstBrowserLanguage() || '';\n    if (languageTagResolver[uniformLanguageTagResolver]) {\n      locale = languageTagResolver[uniformLanguageTagResolver](locale);\n    }\n    return locale;\n  };\n  getLocale.displayName = 'angular-translate/service: getLocale';\n\n  /**\n   * @name indexOf\n   * @private\n   *\n   * @description\n   * indexOf polyfill. Kinda sorta.\n   *\n   * @param {array} array Array to search in.\n   * @param {string} searchElement Element to search for.\n   *\n   * @returns {int} Index of search element.\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\n  /**\n   * @name trim\n   * @private\n   *\n   * @description\n   * trim polyfill\n   *\n   * @returns {string} The string stripped of whitespace from both ends\n   */\n  var trim = function () {\n    return this.toString().replace(/^\\s+|\\s+$/g, '');\n  };\n\n  var negotiateLocale = function (preferred) {\n    if (!preferred) {\n      return;\n    }\n\n    var avail = [],\n      locale = angular.lowercase(preferred),\n      i = 0,\n      n = $availableLanguageKeys.length;\n\n    for (; i < n; i++) {\n      avail.push(angular.lowercase($availableLanguageKeys[i]));\n    }\n\n    // Check for an exact match in our list of available keys\n    if (indexOf(avail, locale) > -1) {\n      return preferred;\n    }\n\n    if ($languageKeyAliases) {\n      var alias;\n      for (var langKeyAlias in $languageKeyAliases) {\n        if ($languageKeyAliases.hasOwnProperty(langKeyAlias)) {\n          var hasWildcardKey = false;\n          var hasExactKey = Object.prototype.hasOwnProperty.call($languageKeyAliases, langKeyAlias) &&\n            angular.lowercase(langKeyAlias) === angular.lowercase(preferred);\n\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    }\n\n    // Check for a language code without region\n    var parts = preferred.split('_');\n\n    if (parts.length > 1 && indexOf(avail, angular.lowercase(parts[0])) > -1) {\n      return parts[0];\n    }\n\n    // If everything fails, return undefined.\n    return;\n  };\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#translations\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * Registers a new translation table for specific language key.\n   *\n   * To register a translation table for specific language, pass a defined language\n   * key as first parameter.\n   *\n   * <pre>\n   *  // register translation table for language: 'de_DE'\n   *  $translateProvider.translations('de_DE', {\n   *    'GREETING': 'Hallo Welt!'\n   *  });\n   *\n   *  // register another one\n   *  $translateProvider.translations('en_US', {\n   *    'GREETING': 'Hello world!'\n   *  });\n   * </pre>\n   *\n   * When registering multiple translation tables for for the same language key,\n   * the actual translation table gets extended. This allows you to define module\n   * specific translation which only get added, once a specific module is loaded in\n   * your app.\n   *\n   * Invoking this method with no arguments returns the translation table which was\n   * registered with no language key. Invoking it with a language key returns the\n   * related translation table.\n   *\n   * @param {string} langKey A language key.\n   * @param {object} translationTable A plain old JavaScript object that represents a translation table.\n   *\n   */\n  var translations = function (langKey, translationTable) {\n\n    if (!langKey && !translationTable) {\n      return $translationTable;\n    }\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\n  this.translations = translations;\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#cloakClassName\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   *\n   * Let's you change the class name for `translate-cloak` directive.\n   * Default class name is `translate-cloak`.\n   *\n   * @param {string} name translate-cloak class name\n   */\n  this.cloakClassName = function (name) {\n    if (!name) {\n      return $cloakClassName;\n    }\n    $cloakClassName = name;\n    return this;\n  };\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#nestedObjectDelimeter\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   *\n   * Let's you change the delimiter for namespaced translations.\n   * Default delimiter is `.`.\n   *\n   * @param {string} delimiter namespace separator\n   */\n  this.nestedObjectDelimeter = function (delimiter) {\n    if (!delimiter) {\n      return $nestedObjectDelimeter;\n    }\n    $nestedObjectDelimeter = delimiter;\n    return this;\n  };\n\n  /**\n   * @name flatObject\n   * @private\n   *\n   * @description\n   * Flats an object. This function is used to flatten given translation data with\n   * namespaces, so they are later accessible via dot notation.\n   */\n  var flatObject = function (data, path, result, prevKey) {\n    var key, keyWithPath, keyWithShortPath, val;\n\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($nestedObjectDelimeter) + $nestedObjectDelimeter + key) : key;\n        if (path.length && key === prevKey) {\n          // Create shortcut path (foo.bar == foo.bar.bar)\n          keyWithShortPath = '' + path.join($nestedObjectDelimeter);\n          // Link it to original path\n          result[keyWithShortPath] = '@:' + keyWithPath;\n        }\n        result[keyWithPath] = val;\n      }\n    }\n    return result;\n  };\n  flatObject.displayName = 'flatObject';\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#addInterpolation\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * Adds interpolation services to angular-translate, so it can manage them.\n   *\n   * @param {object} factory Interpolation service factory\n   */\n  this.addInterpolation = function (factory) {\n    $interpolatorFactories.push(factory);\n    return this;\n  };\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#useMessageFormatInterpolation\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * Tells angular-translate to use interpolation functionality of messageformat.js.\n   * This is useful when having high level pluralization and gender selection.\n   */\n  this.useMessageFormatInterpolation = function () {\n    return this.useInterpolation('$translateMessageFormatInterpolation');\n  };\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#useInterpolation\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * Tells angular-translate which interpolation style to use as default, application-wide.\n   * Simply pass a factory/service name. The interpolation service has to implement\n   * the correct interface.\n   *\n   * @param {string} factory Interpolation service name.\n   */\n  this.useInterpolation = function (factory) {\n    $interpolationFactory = factory;\n    return this;\n  };\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#useSanitizeStrategy\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * Simply sets a sanitation strategy type.\n   *\n   * @param {string} value Strategy type.\n   */\n  this.useSanitizeValueStrategy = function (value) {\n    $translateSanitizationProvider.useStrategy(value);\n    return this;\n  };\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#preferredLanguage\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * Tells the module which of the registered translation tables to use for translation\n   * at initial startup by passing a language key. Similar to `$translateProvider#use`\n   * only that it says which language to **prefer**.\n   *\n   * @param {string} langKey A language key.\n   */\n  this.preferredLanguage = function (langKey) {\n    if (langKey) {\n      setupPreferredLanguage(langKey);\n      return this;\n    }\n    return $preferredLanguage;\n  };\n  var setupPreferredLanguage = function (langKey) {\n    if (langKey) {\n      $preferredLanguage = langKey;\n    }\n    return $preferredLanguage;\n  };\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#translationNotFoundIndicator\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * Sets an indicator which is used when a translation isn't found. E.g. when\n   * setting the indicator as 'X' and one tries to translate a translation id\n   * called `NOT_FOUND`, this will result in `X NOT_FOUND X`.\n   *\n   * Internally this methods sets a left indicator and a right indicator using\n   * `$translateProvider.translationNotFoundIndicatorLeft()` and\n   * `$translateProvider.translationNotFoundIndicatorRight()`.\n   *\n   * **Note**: These methods automatically add a whitespace between the indicators\n   * and the translation id.\n   *\n   * @param {string} indicator An indicator, could be any string.\n   */\n  this.translationNotFoundIndicator = function (indicator) {\n    this.translationNotFoundIndicatorLeft(indicator);\n    this.translationNotFoundIndicatorRight(indicator);\n    return this;\n  };\n\n  /**\n   * ngdoc function\n   * @name pascalprecht.translate.$translateProvider#translationNotFoundIndicatorLeft\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * Sets an indicator which is used when a translation isn't found left to the\n   * translation id.\n   *\n   * @param {string} indicator An indicator.\n   */\n  this.translationNotFoundIndicatorLeft = function (indicator) {\n    if (!indicator) {\n      return $notFoundIndicatorLeft;\n    }\n    $notFoundIndicatorLeft = indicator;\n    return this;\n  };\n\n  /**\n   * ngdoc function\n   * @name pascalprecht.translate.$translateProvider#translationNotFoundIndicatorLeft\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * Sets an indicator which is used when a translation isn't found right to the\n   * translation id.\n   *\n   * @param {string} indicator An indicator.\n   */\n  this.translationNotFoundIndicatorRight = function (indicator) {\n    if (!indicator) {\n      return $notFoundIndicatorRight;\n    }\n    $notFoundIndicatorRight = indicator;\n    return this;\n  };\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#fallbackLanguage\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * Tells the module which of the registered translation tables to use when missing translations\n   * at initial startup by passing a language key. Similar to `$translateProvider#use`\n   * only that it says which language to **fallback**.\n   *\n   * @param {string||array} langKey A language key.\n   *\n   */\n  this.fallbackLanguage = function (langKey) {\n    fallbackStack(langKey);\n    return this;\n  };\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\n      return this;\n    } else {\n      if ($fallbackWasString) {\n        return $fallbackLanguage[0];\n      } else {\n        return $fallbackLanguage;\n      }\n    }\n  };\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#use\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * Set which translation table to use for translation by given language key. When\n   * trying to 'use' a language which isn't provided, it'll throw an error.\n   *\n   * You actually don't have to use this method since `$translateProvider#preferredLanguage`\n   * does the job too.\n   *\n   * @param {string} langKey A language key.\n   */\n  this.use = function (langKey) {\n    if (langKey) {\n      if (!$translationTable[langKey] && (!$loaderFactory)) {\n        // only throw an error, when not loading translation data asynchronously\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\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#resolveClientLocale\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * This returns the current browser/client's language key. The result is processed with the configured uniform tag resolver.\n   *\n   * @returns {string} the current client/browser language key\n   */\n  this.resolveClientLocale = function () {\n    return getLocale();\n  };\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#storageKey\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * Tells the module which key must represent the choosed language by a user in the storage.\n   *\n   * @param {string} key A key for the storage.\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    return this;\n  };\n\n  this.storageKey = storageKey;\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#useUrlLoader\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * Tells angular-translate to use `$translateUrlLoader` extension service as loader.\n   *\n   * @param {string} url Url\n   * @param {Object=} options Optional configuration object\n   */\n  this.useUrlLoader = function (url, options) {\n    return this.useLoader('$translateUrlLoader', angular.extend({url : url}, options));\n  };\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#useStaticFilesLoader\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * Tells angular-translate to use `$translateStaticFilesLoader` extension service as loader.\n   *\n   * @param {Object=} options Optional configuration object\n   */\n  this.useStaticFilesLoader = function (options) {\n    return this.useLoader('$translateStaticFilesLoader', options);\n  };\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#useLoader\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * Tells angular-translate to use any other service as loader.\n   *\n   * @param {string} loaderFactory Factory name to use\n   * @param {Object=} options Optional configuration object\n   */\n  this.useLoader = function (loaderFactory, options) {\n    $loaderFactory = loaderFactory;\n    $loaderOptions = options || {};\n    return this;\n  };\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#useLocalStorage\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * Tells angular-translate to use `$translateLocalStorage` service as storage layer.\n   *\n   */\n  this.useLocalStorage = function () {\n    return this.useStorage('$translateLocalStorage');\n  };\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#useCookieStorage\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * Tells angular-translate to use `$translateCookieStorage` service as storage layer.\n   */\n  this.useCookieStorage = function () {\n    return this.useStorage('$translateCookieStorage');\n  };\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#useStorage\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * Tells angular-translate to use custom service as storage layer.\n   */\n  this.useStorage = function (storageFactory) {\n    $storageFactory = storageFactory;\n    return this;\n  };\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#storagePrefix\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * Sets prefix for storage key.\n   *\n   * @param {string} prefix Storage key prefix\n   */\n  this.storagePrefix = function (prefix) {\n    if (!prefix) {\n      return prefix;\n    }\n    $storagePrefix = prefix;\n    return this;\n  };\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#useMissingTranslationHandlerLog\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * Tells angular-translate to use built-in log handler when trying to translate\n   * a translation Id which doesn't exist.\n   *\n   * This is actually a shortcut method for `useMissingTranslationHandler()`.\n   *\n   */\n  this.useMissingTranslationHandlerLog = function () {\n    return this.useMissingTranslationHandler('$translateMissingTranslationHandlerLog');\n  };\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#useMissingTranslationHandler\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * Expects a factory name which later gets instantiated with `$injector`.\n   * This method can be used to tell angular-translate to use a custom\n   * missingTranslationHandler. Just build a factory which returns a function\n   * and expects a translation id as argument.\n   *\n   * Example:\n   * <pre>\n   *  app.config(function ($translateProvider) {\n   *    $translateProvider.useMissingTranslationHandler('customHandler');\n   *  });\n   *\n   *  app.factory('customHandler', function (dep1, dep2) {\n   *    return function (translationId) {\n   *      // something with translationId and dep1 and dep2\n   *    };\n   *  });\n   * </pre>\n   *\n   * @param {string} factory Factory name\n   */\n  this.useMissingTranslationHandler = function (factory) {\n    $missingTranslationHandlerFactory = factory;\n    return this;\n  };\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#usePostCompiling\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * If post compiling is enabled, all translated values will be processed\n   * again with AngularJS' $compile.\n   *\n   * Example:\n   * <pre>\n   *  app.config(function ($translateProvider) {\n   *    $translateProvider.usePostCompiling(true);\n   *  });\n   * </pre>\n   *\n   * @param {string} factory Factory name\n   */\n  this.usePostCompiling = function (value) {\n    $postCompilingEnabled = !(!value);\n    return this;\n  };\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#forceAsyncReload\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * If force async reload is enabled, async loader will always be called\n   * even if $translationTable already contains the language key, adding\n   * possible new entries to the $translationTable.\n   *\n   * Example:\n   * <pre>\n   *  app.config(function ($translateProvider) {\n   *    $translateProvider.forceAsyncReload(true);\n   *  });\n   * </pre>\n   *\n   * @param {boolean} value - valid values are true or false\n   */\n  this.forceAsyncReload = function (value) {\n    $forceAsyncReloadEnabled = !(!value);\n    return this;\n  };\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#uniformLanguageTag\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * Tells angular-translate which language tag should be used as a result when determining\n   * the current browser language.\n   *\n   * This setting must be set before invoking {@link pascalprecht.translate.$translateProvider#methods_determinePreferredLanguage determinePreferredLanguage()}.\n   *\n   * <pre>\n   * $translateProvider\n   *   .uniformLanguageTag('bcp47')\n   *   .determinePreferredLanguage()\n   * </pre>\n   *\n   * The resolver currently supports:\n   * * default\n   *     (traditionally: hyphens will be converted into underscores, i.e. en-US => en_US)\n   *     en-US => en_US\n   *     en_US => en_US\n   *     en-us => en_us\n   * * java\n   *     like default, but the second part will be always in uppercase\n   *     en-US => en_US\n   *     en_US => en_US\n   *     en-us => en_US\n   * * BCP 47 (RFC 4646 & 4647)\n   *     en-US => en-US\n   *     en_US => en-US\n   *     en-us => en-US\n   *\n   * See also:\n   * * http://en.wikipedia.org/wiki/IETF_language_tag\n   * * http://www.w3.org/International/core/langtags/\n   * * http://tools.ietf.org/html/bcp47\n   *\n   * @param {string|object} options - options (or standard)\n   * @param {string} options.standard - valid values are 'default', 'bcp47', 'java'\n   */\n  this.uniformLanguageTag = function (options) {\n\n    if (!options) {\n      options = {};\n    } else if (angular.isString(options)) {\n      options = {\n        standard : options\n      };\n    }\n\n    uniformLanguageTagResolver = options.standard;\n\n    return this;\n  };\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#determinePreferredLanguage\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * Tells angular-translate to try to determine on its own which language key\n   * to set as preferred language. When `fn` is given, angular-translate uses it\n   * to determine a language key, otherwise it uses the built-in `getLocale()`\n   * method.\n   *\n   * The `getLocale()` returns a language key in the format `[lang]_[country]` or\n   * `[lang]` depending on what the browser provides.\n   *\n   * Use this method at your own risk, since not all browsers return a valid\n   * locale (see {@link pascalprecht.translate.$translateProvider#methods_uniformLanguageTag uniformLanguageTag()}).\n   *\n   * @param {Function=} fn Function to determine a browser's locale\n   */\n  this.determinePreferredLanguage = function (fn) {\n\n    var locale = (fn && angular.isFunction(fn)) ? fn() : getLocale();\n\n    if (!$availableLanguageKeys.length) {\n      $preferredLanguage = locale;\n    } else {\n      $preferredLanguage = negotiateLocale(locale) || locale;\n    }\n\n    return this;\n  };\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#registerAvailableLanguageKeys\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * Registers a set of language keys the app will work with. Use this method in\n   * combination with\n   * {@link pascalprecht.translate.$translateProvider#determinePreferredLanguage determinePreferredLanguage}.\n   * When available languages keys are registered, angular-translate\n   * tries to find the best fitting language key depending on the browsers locale,\n   * considering your language key convention.\n   *\n   * @param {object} languageKeys Array of language keys the your app will use\n   * @param {object=} aliases Alias map.\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\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#useLoaderCache\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * Registers a cache for internal $http based loaders.\n   * {@link pascalprecht.translate.$translationCache $translationCache}.\n   * When false the cache will be disabled (default). When true or undefined\n   * the cache will be a default (see $cacheFactory). When an object it will\n   * be treat as a cache object itself: the usage is $http({cache: cache})\n   *\n   * @param {object} cache boolean, string or cache-object\n   */\n  this.useLoaderCache = function (cache) {\n    if (cache === false) {\n      // disable cache\n      loaderCache = undefined;\n    } else if (cache === true) {\n      // enable cache using AJS defaults\n      loaderCache = true;\n    } else if (typeof(cache) === 'undefined') {\n      // enable cache using default\n      loaderCache = '$translationCache';\n    } else if (cache) {\n      // enable cache using given one (see $cacheFactory)\n      loaderCache = cache;\n    }\n    return this;\n  };\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#directivePriority\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * Sets the default priority of the translate directive. The standard value is `0`.\n   * Calling this function without an argument will return the current value.\n   *\n   * @param {number} priority for the translate-directive\n   */\n  this.directivePriority = function (priority) {\n    if (priority === undefined) {\n      // getter\n      return directivePriority;\n    } else {\n      // setter with chaining\n      directivePriority = priority;\n      return this;\n    }\n  };\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#statefulFilter\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * Since AngularJS 1.3, filters which are not stateless (depending at the scope)\n   * have to explicit define this behavior.\n   * Sets whether the translate filter should be stateful or stateless. The standard value is `true`\n   * meaning being stateful.\n   * Calling this function without an argument will return the current value.\n   *\n   * @param {boolean} state - defines the state of the filter\n   */\n  this.statefulFilter = function (state) {\n    if (state === undefined) {\n      // getter\n      return statefulFilter;\n    } else {\n      // setter with chaining\n      statefulFilter = state;\n      return this;\n    }\n  };\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#postProcess\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * The post processor will be intercept right after the translation result. It can modify the result.\n   *\n   * @param {object} fn Function or service name (string) to be called after the translation value has been set / resolved. The function itself will enrich every value being processed and then continue the normal resolver process\n   */\n  this.postProcess = function (fn) {\n    if (fn) {\n      postProcessFn = fn;\n    } else {\n      postProcessFn = undefined;\n    }\n    return this;\n  };\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#keepContent\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * If keepContent is set to true than translate directive will always use innerHTML\n   * as a default translation\n   *\n   * Example:\n   * <pre>\n   *  app.config(function ($translateProvider) {\n   *    $translateProvider.keepContent(true);\n   *  });\n   * </pre>\n   *\n   * @param {boolean} value - valid values are true or false\n   */\n  this.keepContent = function (value) {\n    $keepContent = !(!value);\n    return this;\n  };\n\n  /**\n   * @ngdoc object\n   * @name pascalprecht.translate.$translate\n   * @requires $interpolate\n   * @requires $log\n   * @requires $rootScope\n   * @requires $q\n   *\n   * @description\n   * The `$translate` service is the actual core of angular-translate. It expects a translation id\n   * and optional interpolate parameters to translate contents.\n   *\n   * <pre>\n   *  $translate('HEADLINE_TEXT').then(function (translation) {\n   *    $scope.translatedText = translation;\n   *  });\n   * </pre>\n   *\n   * @param {string|array} translationId A token which represents a translation id\n   *                                     This can be optionally an array of translation ids which\n   *                                     results that the function returns an object where each key\n   *                                     is the translation id and the value the translation.\n   * @param {object=} interpolateParams An object hash for dynamic values\n   * @param {string} interpolationId The id of the interpolation to use\n   * @param {string} defaultTranslationText the optional default translation text that is written as\n   *                                        as default text in case it is not found in any configured language\n   * @param {string} forceLanguage A language to be used instead of the current language\n   * @returns {object} promise\n   */\n  this.$get = ['$log', '$injector', '$rootScope', '$q', function ($log, $injector, $rootScope, $q) {\n\n    var Storage,\n      defaultInterpolator = $injector.get($interpolationFactory || '$translateDefaultInterpolation'),\n      pendingLoader = false,\n      interpolatorHashMap = {},\n      langPromises = {},\n      fallbackIndex,\n      startFallbackIteration;\n\n    var $translate = function (translationId, interpolateParams, interpolationId, defaultTranslationText, forceLanguage) {\n      if (!$uses && $preferredLanguage) {\n        $uses = $preferredLanguage;\n      }\n      var uses = (forceLanguage && forceLanguage !== $uses) ? // we don't want to re-negotiate $uses\n        (negotiateLocale(forceLanguage) || forceLanguage) : $uses;\n\n      // Check forceLanguage is present\n      if (forceLanguage) {\n        loadTranslationsIfMissing(forceLanguage);\n      }\n\n      // Duck detection: If the first argument is an array, a bunch of translations was requested.\n      // The result is an object.\n      if (angular.isArray(translationId)) {\n        // Inspired by Q.allSettled by Kris Kowal\n        // https://github.com/kriskowal/q/blob/b0fa72980717dc202ffc3cbf03b936e10ebbb9d7/q.js#L1553-1563\n        // This transforms all promises regardless resolved or rejected\n        var translateAll = function (translationIds) {\n          var results = {}; // storing the actual results\n          var promises = []; // promises to wait for\n          // Wraps the promise a) being always resolved and b) storing the link id->value\n          var translate = function (translationId) {\n            var deferred = $q.defer();\n            var regardless = function (value) {\n              results[translationId] = value;\n              deferred.resolve([translationId, value]);\n            };\n            // we don't care whether the promise was resolved or rejected; just store the values\n            $translate(translationId, interpolateParams, interpolationId, defaultTranslationText, forceLanguage).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          // wait for all (including storing to results)\n          return $q.all(promises).then(function () {\n            // return the results\n            return results;\n          });\n        };\n        return translateAll(translationId);\n      }\n\n      var deferred = $q.defer();\n\n      // trim off any whitespace\n      if (translationId) {\n        translationId = trim.apply(translationId);\n      }\n\n      var promiseToWaitFor = (function () {\n        var promise = $preferredLanguage ?\n          langPromises[$preferredLanguage] :\n          langPromises[uses];\n\n        fallbackIndex = 0;\n\n        if ($storageFactory && !promise) {\n          // looks like there's no pending promise for $preferredLanguage or\n          // $uses. Maybe there's one pending for a language that comes from\n          // storage.\n          var langKey = Storage.get($storageKey);\n          promise = langPromises[langKey];\n\n          if ($fallbackLanguage && $fallbackLanguage.length) {\n            var index = indexOf($fallbackLanguage, langKey);\n            // maybe the language from storage is also defined as fallback language\n            // we increase the fallback language index to not search in that language\n            // as fallback, since it's probably the first used language\n            // in that case the index starts after the first element\n            fallbackIndex = (index === 0) ? 1 : 0;\n\n            // but we can make sure to ALWAYS fallback to preferred language at least\n            if (indexOf($fallbackLanguage, $preferredLanguage) < 0) {\n              $fallbackLanguage.push($preferredLanguage);\n            }\n          }\n        }\n        return promise;\n      }());\n\n      if (!promiseToWaitFor) {\n        // no promise to wait for? okay. Then there's no loader registered\n        // nor is a one pending for language that comes from storage.\n        // We can just translate.\n        determineTranslation(translationId, interpolateParams, interpolationId, defaultTranslationText, uses).then(deferred.resolve, deferred.reject);\n      } else {\n        var promiseResolved = function () {\n          // $uses may have changed while waiting\n          if (!forceLanguage) {\n            uses = $uses;\n          }\n          determineTranslation(translationId, interpolateParams, interpolationId, defaultTranslationText, uses).then(deferred.resolve, deferred.reject);\n        };\n        promiseResolved.displayName = 'promiseResolved';\n\n        promiseToWaitFor['finally'](promiseResolved)\n          .catch(angular.noop); // we don't care about errors here, already handled\n      }\n      return deferred.promise;\n    };\n\n    /**\n     * @name applyNotFoundIndicators\n     * @private\n     *\n     * @description\n     * Applies not fount indicators to given translation id, if needed.\n     * This function gets only executed, if a translation id doesn't exist,\n     * which is why a translation id is expected as argument.\n     *\n     * @param {string} translationId Translation id.\n     * @returns {string} Same as given translation id but applied with not found\n     * indicators.\n     */\n    var applyNotFoundIndicators = function (translationId) {\n      // applying notFoundIndicators\n      if ($notFoundIndicatorLeft) {\n        translationId = [$notFoundIndicatorLeft, translationId].join(' ');\n      }\n      if ($notFoundIndicatorRight) {\n        translationId = [translationId, $notFoundIndicatorRight].join(' ');\n      }\n      return translationId;\n    };\n\n    /**\n     * @name useLanguage\n     * @private\n     *\n     * @description\n     * Makes actual use of a language by setting a given language key as used\n     * language and informs registered interpolators to also use the given\n     * key as locale.\n     *\n     * @param {string} key Locale key.\n     */\n    var useLanguage = function (key) {\n      $uses = key;\n\n      // make sure to store new language key before triggering success event\n      if ($storageFactory) {\n        Storage.put($translate.storageKey(), $uses);\n      }\n\n      $rootScope.$emit('$translateChangeSuccess', {language : key});\n\n      // inform default interpolator\n      defaultInterpolator.setLocale($uses);\n\n      var eachInterpolator = function (interpolator, id) {\n        interpolatorHashMap[id].setLocale($uses);\n      };\n      eachInterpolator.displayName = 'eachInterpolatorLocaleSetter';\n\n      // inform all others too!\n      angular.forEach(interpolatorHashMap, eachInterpolator);\n      $rootScope.$emit('$translateChangeEnd', {language : key});\n    };\n\n    /**\n     * @name loadAsync\n     * @private\n     *\n     * @description\n     * Kicks off registered async loader using `$injector` and applies existing\n     * loader options. When resolved, it updates translation tables accordingly\n     * or rejects with given language key.\n     *\n     * @param {string} key Language key.\n     * @return {Promise} A promise.\n     */\n    var loadAsync = function (key) {\n      if (!key) {\n        throw 'No language key specified for loading.';\n      }\n\n      var deferred = $q.defer();\n\n      $rootScope.$emit('$translateLoadingStart', {language : key});\n      pendingLoader = true;\n\n      var cache = loaderCache;\n      if (typeof(cache) === 'string') {\n        // getting on-demand instance of loader\n        cache = $injector.get(cache);\n      }\n\n      var loaderOptions = angular.extend({}, $loaderOptions, {\n        key : key,\n        $http : angular.extend({}, {\n          cache : cache\n        }, $loaderOptions.$http)\n      });\n\n      var onLoaderSuccess = function (data) {\n        var translationTable = {};\n        $rootScope.$emit('$translateLoadingSuccess', {language : key});\n\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      };\n      onLoaderSuccess.displayName = 'onLoaderSuccess';\n\n      var onLoaderError = function (key) {\n        $rootScope.$emit('$translateLoadingError', {language : key});\n        deferred.reject(key);\n        $rootScope.$emit('$translateLoadingEnd', {language : key});\n      };\n      onLoaderError.displayName = 'onLoaderError';\n\n      $injector.get($loaderFactory)(loaderOptions)\n        .then(onLoaderSuccess, onLoaderError);\n\n      return deferred.promise;\n    };\n\n    if ($storageFactory) {\n      Storage = $injector.get($storageFactory);\n\n      if (!Storage.get || !Storage.put) {\n        throw new Error('Couldn\\'t use storage \\'' + $storageFactory + '\\', missing get() or put() method!');\n      }\n    }\n\n    // if we have additional interpolations that were added via\n    // $translateProvider.addInterpolation(), we have to map'em\n    if ($interpolatorFactories.length) {\n      var eachInterpolationFactory = function (interpolatorFactory) {\n        var interpolator = $injector.get(interpolatorFactory);\n        // setting initial locale for each interpolation service\n        interpolator.setLocale($preferredLanguage || $uses);\n        // make'em recognizable through id\n        interpolatorHashMap[interpolator.getInterpolationIdentifier()] = interpolator;\n      };\n      eachInterpolationFactory.displayName = 'interpolationFactoryAdder';\n\n      angular.forEach($interpolatorFactories, eachInterpolationFactory);\n    }\n\n    /**\n     * @name getTranslationTable\n     * @private\n     *\n     * @description\n     * Returns a promise that resolves to the translation table\n     * or is rejected if an error occurred.\n     *\n     * @param langKey\n     * @returns {Q.promise}\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        var onResolve = function (data) {\n          translations(data.key, data.table);\n          deferred.resolve(data.table);\n        };\n        onResolve.displayName = 'translationTableResolver';\n        langPromises[langKey].then(onResolve, deferred.reject);\n      } else {\n        deferred.reject();\n      }\n      return deferred.promise;\n    };\n\n    /**\n     * @name getFallbackTranslation\n     * @private\n     *\n     * @description\n     * Returns a promise that will resolve to the translation\n     * or be rejected if no translation was found for the language.\n     * This function is currently only used for fallback language translation.\n     *\n     * @param langKey The language to translate to.\n     * @param translationId\n     * @param interpolateParams\n     * @param Interpolator\n     * @param sanitizeStrategy\n     * @returns {Q.promise}\n     */\n    var getFallbackTranslation = function (langKey, translationId, interpolateParams, Interpolator, sanitizeStrategy) {\n      var deferred = $q.defer();\n\n      var onResolve = function (translationTable) {\n        if (Object.prototype.hasOwnProperty.call(translationTable, translationId) && translationTable[translationId] !== null) {\n          Interpolator.setLocale(langKey);\n          var translation = translationTable[translationId];\n          if (translation.substr(0, 2) === '@:') {\n            getFallbackTranslation(langKey, translation.substr(2), interpolateParams, Interpolator, sanitizeStrategy)\n              .then(deferred.resolve, deferred.reject);\n          } else {\n            var interpolatedValue = Interpolator.interpolate(translationTable[translationId], interpolateParams, 'service', sanitizeStrategy, translationId);\n            interpolatedValue = applyPostProcessing(translationId, translationTable[translationId], interpolatedValue, interpolateParams, langKey);\n\n            deferred.resolve(interpolatedValue);\n\n          }\n          Interpolator.setLocale($uses);\n        } else {\n          deferred.reject();\n        }\n      };\n      onResolve.displayName = 'fallbackTranslationResolver';\n\n      getTranslationTable(langKey).then(onResolve, deferred.reject);\n\n      return deferred.promise;\n    };\n\n    /**\n     * @name getFallbackTranslationInstant\n     * @private\n     *\n     * @description\n     * Returns a translation\n     * This function is currently only used for fallback language translation.\n     *\n     * @param langKey The language to translate to.\n     * @param translationId\n     * @param interpolateParams\n     * @param Interpolator\n     * @param sanitizeStrategy sanitize strategy override\n     *\n     * @returns {string} translation\n     */\n    var getFallbackTranslationInstant = function (langKey, translationId, interpolateParams, Interpolator, sanitizeStrategy) {\n      var result, translationTable = $translationTable[langKey];\n\n      if (translationTable && Object.prototype.hasOwnProperty.call(translationTable, translationId) && translationTable[translationId] !== null) {\n        Interpolator.setLocale(langKey);\n        result = Interpolator.interpolate(translationTable[translationId], interpolateParams, 'filter', sanitizeStrategy, translationId);\n        result = applyPostProcessing(translationId, translationTable[translationId], result, interpolateParams, langKey, sanitizeStrategy);\n        // workaround for TrustedValueHolderType\n        if (!angular.isString(result) && angular.isFunction(result.$$unwrapTrustedValue)) {\n          var result2 = result.$$unwrapTrustedValue();\n          if (result2.substr(0, 2) === '@:') {\n            return getFallbackTranslationInstant(langKey, result2.substr(2), interpolateParams, Interpolator, sanitizeStrategy);\n          }\n        } else if (result.substr(0, 2) === '@:') {\n          return getFallbackTranslationInstant(langKey, result.substr(2), interpolateParams, Interpolator, sanitizeStrategy);\n        }\n        Interpolator.setLocale($uses);\n      }\n\n      return result;\n    };\n\n\n    /**\n     * @name translateByHandler\n     * @private\n     *\n     * Translate by missing translation handler.\n     *\n     * @param translationId\n     * @param interpolateParams\n     * @param defaultTranslationText\n     * @param sanitizeStrategy sanitize strategy override\n     *\n     * @returns translation created by $missingTranslationHandler or translationId is $missingTranslationHandler is\n     * absent\n     */\n    var translateByHandler = function (translationId, interpolateParams, defaultTranslationText, sanitizeStrategy) {\n      // If we have a handler factory - we might also call it here to determine if it provides\n      // a default text for a translationid that can't be found anywhere in our tables\n      if ($missingTranslationHandlerFactory) {\n        return $injector.get($missingTranslationHandlerFactory)(translationId, $uses, interpolateParams, defaultTranslationText, sanitizeStrategy);\n      } else {\n        return translationId;\n      }\n    };\n\n    /**\n     * @name resolveForFallbackLanguage\n     * @private\n     *\n     * Recursive helper function for fallbackTranslation that will sequentially look\n     * for a translation in the fallbackLanguages starting with fallbackLanguageIndex.\n     *\n     * @param fallbackLanguageIndex\n     * @param translationId\n     * @param interpolateParams\n     * @param Interpolator\n     * @param defaultTranslationText\n     * @param sanitizeStrategy\n     * @returns {Q.promise} Promise that will resolve to the translation.\n     */\n    var resolveForFallbackLanguage = function (fallbackLanguageIndex, translationId, interpolateParams, Interpolator, defaultTranslationText, sanitizeStrategy) {\n      var deferred = $q.defer();\n\n      if (fallbackLanguageIndex < $fallbackLanguage.length) {\n        var langKey = $fallbackLanguage[fallbackLanguageIndex];\n        getFallbackTranslation(langKey, translationId, interpolateParams, Interpolator, sanitizeStrategy).then(\n          function (data) {\n            deferred.resolve(data);\n          },\n          function () {\n            // Look in the next fallback language for a translation.\n            // It delays the resolving by passing another promise to resolve.\n            return resolveForFallbackLanguage(fallbackLanguageIndex + 1, translationId, interpolateParams, Interpolator, defaultTranslationText, sanitizeStrategy).then(deferred.resolve, deferred.reject);\n          }\n        );\n      } else {\n        // No translation found in any fallback language\n        // if a default translation text is set in the directive, then return this as a result\n        if (defaultTranslationText) {\n          deferred.resolve(defaultTranslationText);\n        } else {\n          var missingTranslationHandlerTranslation = translateByHandler(translationId, interpolateParams, defaultTranslationText);\n\n          // if no default translation is set and an error handler is defined, send it to the handler\n          // and then return the result if it isn't undefined\n          if ($missingTranslationHandlerFactory && missingTranslationHandlerTranslation) {\n            deferred.resolve(missingTranslationHandlerTranslation);\n          } else {\n            deferred.reject(applyNotFoundIndicators(translationId));\n          }\n        }\n      }\n      return deferred.promise;\n    };\n\n    /**\n     * @name resolveForFallbackLanguageInstant\n     * @private\n     *\n     * Recursive helper function for fallbackTranslation that will sequentially look\n     * for a translation in the fallbackLanguages starting with fallbackLanguageIndex.\n     *\n     * @param fallbackLanguageIndex\n     * @param translationId\n     * @param interpolateParams\n     * @param Interpolator\n     * @param sanitizeStrategy\n     * @returns {string} translation\n     */\n    var resolveForFallbackLanguageInstant = function (fallbackLanguageIndex, translationId, interpolateParams, Interpolator, sanitizeStrategy) {\n      var result;\n\n      if (fallbackLanguageIndex < $fallbackLanguage.length) {\n        var langKey = $fallbackLanguage[fallbackLanguageIndex];\n        result = getFallbackTranslationInstant(langKey, translationId, interpolateParams, Interpolator, sanitizeStrategy);\n        if (!result && result !== '') {\n          result = resolveForFallbackLanguageInstant(fallbackLanguageIndex + 1, translationId, interpolateParams, Interpolator);\n        }\n      }\n      return result;\n    };\n\n    /**\n     * Translates with the usage of the fallback languages.\n     *\n     * @param translationId\n     * @param interpolateParams\n     * @param Interpolator\n     * @param defaultTranslationText\n     * @param sanitizeStrategy\n     * @returns {Q.promise} Promise, that resolves to the translation.\n     */\n    var fallbackTranslation = function (translationId, interpolateParams, Interpolator, defaultTranslationText, sanitizeStrategy) {\n      // Start with the fallbackLanguage with index 0\n      return resolveForFallbackLanguage((startFallbackIteration > 0 ? startFallbackIteration : fallbackIndex), translationId, interpolateParams, Interpolator, defaultTranslationText, sanitizeStrategy);\n    };\n\n    /**\n     * Translates with the usage of the fallback languages.\n     *\n     * @param translationId\n     * @param interpolateParams\n     * @param Interpolator\n     * @param sanitizeStrategy\n     * @returns {String} translation\n     */\n    var fallbackTranslationInstant = function (translationId, interpolateParams, Interpolator, sanitizeStrategy) {\n      // Start with the fallbackLanguage with index 0\n      return resolveForFallbackLanguageInstant((startFallbackIteration > 0 ? startFallbackIteration : fallbackIndex), translationId, interpolateParams, Interpolator, sanitizeStrategy);\n    };\n\n    var determineTranslation = function (translationId, interpolateParams, interpolationId, defaultTranslationText, uses, sanitizeStrategy) {\n\n      var deferred = $q.defer();\n\n      var table = uses ? $translationTable[uses] : $translationTable,\n        Interpolator = (interpolationId) ? interpolatorHashMap[interpolationId] : defaultInterpolator;\n\n      // if the translation id exists, we can just interpolate it\n      if (table && Object.prototype.hasOwnProperty.call(table, translationId) && table[translationId] !== null) {\n        var translation = table[translationId];\n\n        // If using link, rerun $translate with linked translationId and return it\n        if (translation.substr(0, 2) === '@:') {\n\n          $translate(translation.substr(2), interpolateParams, interpolationId, defaultTranslationText, uses)\n            .then(deferred.resolve, deferred.reject);\n        } else {\n          //\n          var resolvedTranslation = Interpolator.interpolate(translation, interpolateParams, 'service', sanitizeStrategy, translationId);\n          resolvedTranslation = applyPostProcessing(translationId, translation, resolvedTranslation, interpolateParams, uses);\n          deferred.resolve(resolvedTranslation);\n        }\n      } else {\n        var missingTranslationHandlerTranslation;\n        // for logging purposes only (as in $translateMissingTranslationHandlerLog), value is not returned to promise\n        if ($missingTranslationHandlerFactory && !pendingLoader) {\n          missingTranslationHandlerTranslation = translateByHandler(translationId, interpolateParams, defaultTranslationText);\n        }\n\n        // since we couldn't translate the inital requested translation id,\n        // we try it now with one or more fallback languages, if fallback language(s) is\n        // configured.\n        if (uses && $fallbackLanguage && $fallbackLanguage.length) {\n          fallbackTranslation(translationId, interpolateParams, Interpolator, defaultTranslationText, sanitizeStrategy)\n            .then(function (translation) {\n              deferred.resolve(translation);\n            }, function (_translationId) {\n              deferred.reject(applyNotFoundIndicators(_translationId));\n            });\n        } else if ($missingTranslationHandlerFactory && !pendingLoader && missingTranslationHandlerTranslation) {\n          // looks like the requested translation id doesn't exists.\n          // Now, if there is a registered handler for missing translations and no\n          // asyncLoader is pending, we execute the handler\n          if (defaultTranslationText) {\n            deferred.resolve(defaultTranslationText);\n          } else {\n            deferred.resolve(missingTranslationHandlerTranslation);\n          }\n        } else {\n          if (defaultTranslationText) {\n            deferred.resolve(defaultTranslationText);\n          } else {\n            deferred.reject(applyNotFoundIndicators(translationId));\n          }\n        }\n      }\n      return deferred.promise;\n    };\n\n    var determineTranslationInstant = function (translationId, interpolateParams, interpolationId, uses, sanitizeStrategy) {\n\n      var result, table = uses ? $translationTable[uses] : $translationTable,\n        Interpolator = defaultInterpolator;\n\n      // if the interpolation id exists use custom interpolator\n      if (interpolatorHashMap && Object.prototype.hasOwnProperty.call(interpolatorHashMap, interpolationId)) {\n        Interpolator = interpolatorHashMap[interpolationId];\n      }\n\n      // if the translation id exists, we can just interpolate it\n      if (table && Object.prototype.hasOwnProperty.call(table, translationId) && table[translationId] !== null) {\n        var translation = table[translationId];\n\n        // If using link, rerun $translate with linked translationId and return it\n        if (translation.substr(0, 2) === '@:') {\n          result = determineTranslationInstant(translation.substr(2), interpolateParams, interpolationId, uses, sanitizeStrategy);\n        } else {\n          result = Interpolator.interpolate(translation, interpolateParams, 'filter', sanitizeStrategy, translationId);\n          result = applyPostProcessing(translationId, translation, result, interpolateParams, uses, sanitizeStrategy);\n        }\n      } else {\n        var missingTranslationHandlerTranslation;\n        // for logging purposes only (as in $translateMissingTranslationHandlerLog), value is not returned to promise\n        if ($missingTranslationHandlerFactory && !pendingLoader) {\n          missingTranslationHandlerTranslation = translateByHandler(translationId, interpolateParams, sanitizeStrategy);\n        }\n\n        // since we couldn't translate the inital requested translation id,\n        // we try it now with one or more fallback languages, if fallback language(s) is\n        // configured.\n        if (uses && $fallbackLanguage && $fallbackLanguage.length) {\n          fallbackIndex = 0;\n          result = fallbackTranslationInstant(translationId, interpolateParams, Interpolator, sanitizeStrategy);\n        } else if ($missingTranslationHandlerFactory && !pendingLoader && missingTranslationHandlerTranslation) {\n          // looks like the requested translation id doesn't exists.\n          // Now, if there is a registered handler for missing translations and no\n          // asyncLoader is pending, we execute the handler\n          result = missingTranslationHandlerTranslation;\n        } else {\n          result = applyNotFoundIndicators(translationId);\n        }\n      }\n\n      return result;\n    };\n\n    var clearNextLangAndPromise = function (key) {\n      if ($nextLang === key) {\n        $nextLang = undefined;\n      }\n      langPromises[key] = undefined;\n    };\n\n    var applyPostProcessing = function (translationId, translation, resolvedTranslation, interpolateParams, uses, sanitizeStrategy) {\n      var fn = postProcessFn;\n\n      if (fn) {\n\n        if (typeof(fn) === 'string') {\n          // getting on-demand instance\n          fn = $injector.get(fn);\n        }\n        if (fn) {\n          return fn(translationId, translation, resolvedTranslation, interpolateParams, uses, sanitizeStrategy);\n        }\n      }\n\n      return resolvedTranslation;\n    };\n\n    var loadTranslationsIfMissing = function (key) {\n      if (!$translationTable[key] && $loaderFactory && !langPromises[key]) {\n        langPromises[key] = loadAsync(key).then(function (translation) {\n          translations(translation.key, translation.table);\n          return translation;\n        });\n      }\n    };\n\n    /**\n     * @ngdoc function\n     * @name pascalprecht.translate.$translate#preferredLanguage\n     * @methodOf pascalprecht.translate.$translate\n     *\n     * @description\n     * Returns the language key for the preferred language.\n     *\n     * @param {string} langKey language String or Array to be used as preferredLanguage (changing at runtime)\n     *\n     * @return {string} preferred language key\n     */\n    $translate.preferredLanguage = function (langKey) {\n      if (langKey) {\n        setupPreferredLanguage(langKey);\n      }\n      return $preferredLanguage;\n    };\n\n    /**\n     * @ngdoc function\n     * @name pascalprecht.translate.$translate#cloakClassName\n     * @methodOf pascalprecht.translate.$translate\n     *\n     * @description\n     * Returns the configured class name for `translate-cloak` directive.\n     *\n     * @return {string} cloakClassName\n     */\n    $translate.cloakClassName = function () {\n      return $cloakClassName;\n    };\n\n    /**\n     * @ngdoc function\n     * @name pascalprecht.translate.$translate#nestedObjectDelimeter\n     * @methodOf pascalprecht.translate.$translate\n     *\n     * @description\n     * Returns the configured delimiter for nested namespaces.\n     *\n     * @return {string} nestedObjectDelimeter\n     */\n    $translate.nestedObjectDelimeter = function () {\n      return $nestedObjectDelimeter;\n    };\n\n    /**\n     * @ngdoc function\n     * @name pascalprecht.translate.$translate#fallbackLanguage\n     * @methodOf pascalprecht.translate.$translate\n     *\n     * @description\n     * Returns the language key for the fallback languages or sets a new fallback stack.\n     *\n     * @param {string=} langKey language String or Array of fallback languages to be used (to change stack at runtime)\n     *\n     * @return {string||array} fallback language key\n     */\n    $translate.fallbackLanguage = function (langKey) {\n      if (langKey !== undefined && langKey !== null) {\n        fallbackStack(langKey);\n\n        // as we might have an async loader initiated and a new translation language might have been defined\n        // we need to add the promise to the stack also. So - iterate.\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    };\n\n    /**\n     * @ngdoc function\n     * @name pascalprecht.translate.$translate#useFallbackLanguage\n     * @methodOf pascalprecht.translate.$translate\n     *\n     * @description\n     * Sets the first key of the fallback language stack to be used for translation.\n     * Therefore all languages in the fallback array BEFORE this key will be skipped!\n     *\n     * @param {string=} langKey Contains the langKey the iteration shall start with. Set to false if you want to\n     * get back to the whole stack\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\n    };\n\n    /**\n     * @ngdoc function\n     * @name pascalprecht.translate.$translate#proposedLanguage\n     * @methodOf pascalprecht.translate.$translate\n     *\n     * @description\n     * Returns the language key of language that is currently loaded asynchronously.\n     *\n     * @return {string} language key\n     */\n    $translate.proposedLanguage = function () {\n      return $nextLang;\n    };\n\n    /**\n     * @ngdoc function\n     * @name pascalprecht.translate.$translate#storage\n     * @methodOf pascalprecht.translate.$translate\n     *\n     * @description\n     * Returns registered storage.\n     *\n     * @return {object} Storage\n     */\n    $translate.storage = function () {\n      return Storage;\n    };\n\n    /**\n     * @ngdoc function\n     * @name pascalprecht.translate.$translate#negotiateLocale\n     * @methodOf pascalprecht.translate.$translate\n     *\n     * @description\n     * Returns a language key based on available languages and language aliases. If a\n     * language key cannot be resolved, returns undefined.\n     *\n     * If no or a falsy key is given, returns undefined.\n     *\n     * @param {string} [key] Language key\n     * @return {string|undefined} Language key or undefined if no language key is found.\n     */\n    $translate.negotiateLocale = negotiateLocale;\n\n    /**\n     * @ngdoc function\n     * @name pascalprecht.translate.$translate#use\n     * @methodOf pascalprecht.translate.$translate\n     *\n     * @description\n     * Tells angular-translate which language to use by given language key. This method is\n     * used to change language at runtime. It also takes care of storing the language\n     * key in a configured store to let your app remember the choosed language.\n     *\n     * When trying to 'use' a language which isn't available it tries to load it\n     * asynchronously with registered loaders.\n     *\n     * Returns promise object with loaded language file data or string of the currently used language.\n     *\n     * If no or a falsy key is given it returns the currently used language key.\n     * The returned string will be ```undefined``` if setting up $translate hasn't finished.\n     * @example\n     * $translate.use(\"en_US\").then(function(data){\n       *   $scope.text = $translate(\"HELLO\");\n       * });\n     *\n     * @param {string} [key] Language key\n     * @return {object|string} Promise with loaded language data or the language key if a falsy param was given.\n     */\n    $translate.use = function (key) {\n      if (!key) {\n        return $uses;\n      }\n\n      var deferred = $q.defer();\n      deferred.promise.then(null, angular.noop); // AJS \"Possibly unhandled rejection\"\n\n      $rootScope.$emit('$translateChangeStart', {language : key});\n\n      // Try to get the aliased language key\n      var aliasedKey = negotiateLocale(key);\n      // Ensure only registered language keys will be loaded\n      if ($availableLanguageKeys.length > 0 && !aliasedKey) {\n        return $q.reject(key);\n      }\n\n      if (aliasedKey) {\n        key = aliasedKey;\n      }\n\n      // if there isn't a translation table for the language we've requested,\n      // we load it asynchronously\n      $nextLang = key;\n      if (($forceAsyncReloadEnabled || !$translationTable[key]) && $loaderFactory && !langPromises[key]) {\n        langPromises[key] = loadAsync(key).then(function (translation) {\n          translations(translation.key, translation.table);\n          deferred.resolve(translation.key);\n          if ($nextLang === key) {\n            useLanguage(translation.key);\n          }\n          return translation;\n        }, function (key) {\n          $rootScope.$emit('$translateChangeError', {language : key});\n          deferred.reject(key);\n          $rootScope.$emit('$translateChangeEnd', {language : key});\n          return $q.reject(key);\n        });\n        langPromises[key]['finally'](function () {\n          clearNextLangAndPromise(key);\n        }).catch(angular.noop); // we don't care about errors (clearing)\n      } else if (langPromises[key]) {\n        // we are already loading this asynchronously\n        // resolve our new deferred when the old langPromise is resolved\n        langPromises[key].then(function (translation) {\n          if ($nextLang === translation.key) {\n            useLanguage(translation.key);\n          }\n          deferred.resolve(translation.key);\n          return translation;\n        }, function (key) {\n          // find first available fallback language if that request has failed\n          if (!$uses && $fallbackLanguage && $fallbackLanguage.length > 0 && $fallbackLanguage[0] !== key) {\n            return $translate.use($fallbackLanguage[0]).then(deferred.resolve, deferred.reject);\n          } else {\n            return deferred.reject(key);\n          }\n        });\n      } else {\n        deferred.resolve(key);\n        useLanguage(key);\n      }\n\n      return deferred.promise;\n    };\n\n    /**\n     * @ngdoc function\n     * @name pascalprecht.translate.$translate#resolveClientLocale\n     * @methodOf pascalprecht.translate.$translate\n     *\n     * @description\n     * This returns the current browser/client's language key. The result is processed with the configured uniform tag resolver.\n     *\n     * @returns {string} the current client/browser language key\n     */\n    $translate.resolveClientLocale = function () {\n      return getLocale();\n    };\n\n    /**\n     * @ngdoc function\n     * @name pascalprecht.translate.$translate#storageKey\n     * @methodOf pascalprecht.translate.$translate\n     *\n     * @description\n     * Returns the key for the storage.\n     *\n     * @return {string} storage key\n     */\n    $translate.storageKey = function () {\n      return storageKey();\n    };\n\n    /**\n     * @ngdoc function\n     * @name pascalprecht.translate.$translate#isPostCompilingEnabled\n     * @methodOf pascalprecht.translate.$translate\n     *\n     * @description\n     * Returns whether post compiling is enabled or not\n     *\n     * @return {bool} storage key\n     */\n    $translate.isPostCompilingEnabled = function () {\n      return $postCompilingEnabled;\n    };\n\n    /**\n     * @ngdoc function\n     * @name pascalprecht.translate.$translate#isForceAsyncReloadEnabled\n     * @methodOf pascalprecht.translate.$translate\n     *\n     * @description\n     * Returns whether force async reload is enabled or not\n     *\n     * @return {boolean} forceAsyncReload value\n     */\n    $translate.isForceAsyncReloadEnabled = function () {\n      return $forceAsyncReloadEnabled;\n    };\n\n    /**\n     * @ngdoc function\n     * @name pascalprecht.translate.$translate#isKeepContent\n     * @methodOf pascalprecht.translate.$translate\n     *\n     * @description\n     * Returns whether keepContent or not\n     *\n     * @return {boolean} keepContent value\n     */\n    $translate.isKeepContent = function () {\n      return $keepContent;\n    };\n\n    /**\n     * @ngdoc function\n     * @name pascalprecht.translate.$translate#refresh\n     * @methodOf pascalprecht.translate.$translate\n     *\n     * @description\n     * Refreshes a translation table pointed by the given langKey. If langKey is not specified,\n     * the module will drop all existent translation tables and load new version of those which\n     * are currently in use.\n     *\n     * Refresh means that the module will drop target translation table and try to load it again.\n     *\n     * In case there are no loaders registered the refresh() method will throw an Error.\n     *\n     * If the module is able to refresh translation tables refresh() method will broadcast\n     * $translateRefreshStart and $translateRefreshEnd events.\n     *\n     * @example\n     * // this will drop all currently existent translation tables and reload those which are\n     * // currently in use\n     * $translate.refresh();\n     * // this will refresh a translation table for the en_US language\n     * $translate.refresh('en_US');\n     *\n     * @param {string} langKey A language key of the table, which has to be refreshed\n     *\n     * @return {promise} Promise, which will be resolved in case a translation tables refreshing\n     * process is finished successfully, and reject if not.\n     */\n    $translate.refresh = function (langKey) {\n      if (!$loaderFactory) {\n        throw new Error('Couldn\\'t refresh translation table, no loader registered!');\n      }\n\n      $rootScope.$emit('$translateRefreshStart', {language : langKey});\n\n      var deferred = $q.defer(), updatedLanguages = {};\n\n      //private helper\n      function loadNewData(languageKey) {\n        var promise = loadAsync(languageKey);\n        //update the load promise cache for this language\n        langPromises[languageKey] = promise;\n        //register a data handler for the promise\n        promise.then(function (data) {\n            //clear the cache for this language\n            $translationTable[languageKey] = {};\n            //add the new data for this language\n            translations(languageKey, data.table);\n            //track that we updated this language\n            updatedLanguages[languageKey] = true;\n          },\n          //handle rejection to appease the $q validation\n          angular.noop);\n        return promise;\n      }\n\n      //set up post-processing\n      deferred.promise.then(\n        function () {\n          for (var key in $translationTable) {\n            if ($translationTable.hasOwnProperty(key)) {\n              //delete cache entries that were not updated\n              if (!(key in updatedLanguages)) {\n                delete $translationTable[key];\n              }\n            }\n          }\n          if ($uses) {\n            useLanguage($uses);\n          }\n        },\n        //handle rejection to appease the $q validation\n        angular.noop\n      ).finally(\n        function () {\n          $rootScope.$emit('$translateRefreshEnd', {language : langKey});\n        }\n      );\n\n      if (!langKey) {\n        // if there's no language key specified we refresh ALL THE THINGS!\n        var languagesToReload = $fallbackLanguage && $fallbackLanguage.slice() || [];\n        if ($uses && languagesToReload.indexOf($uses) === -1) {\n          languagesToReload.push($uses);\n        }\n        $q.all(languagesToReload.map(loadNewData)).then(deferred.resolve, deferred.reject);\n\n      } else if ($translationTable[langKey]) {\n        //just refresh the specified language cache\n        loadNewData(langKey).then(deferred.resolve, deferred.reject);\n\n      } else {\n        deferred.reject();\n      }\n\n      return deferred.promise;\n    };\n\n    /**\n     * @ngdoc function\n     * @name pascalprecht.translate.$translate#instant\n     * @methodOf pascalprecht.translate.$translate\n     *\n     * @description\n     * Returns a translation instantly from the internal state of loaded translation. All rules\n     * regarding the current language, the preferred language of even fallback languages will be\n     * used except any promise handling. If a language was not found, an asynchronous loading\n     * will be invoked in the background.\n     *\n     * @param {string|array} translationId A token which represents a translation id\n     *                                     This can be optionally an array of translation ids which\n     *                                     results that the function's promise returns an object where\n     *                                     each key is the translation id and the value the translation.\n     * @param {object} interpolateParams Params\n     * @param {string} interpolationId The id of the interpolation to use\n     * @param {string} forceLanguage A language to be used instead of the current language\n     * @param {string} sanitizeStrategy force sanitize strategy for this call instead of using the configured one\n     *\n     * @return {string|object} translation\n     */\n    $translate.instant = function (translationId, interpolateParams, interpolationId, forceLanguage, sanitizeStrategy) {\n\n      // we don't want to re-negotiate $uses\n      var uses = (forceLanguage && forceLanguage !== $uses) ? // we don't want to re-negotiate $uses\n        (negotiateLocale(forceLanguage) || forceLanguage) : $uses;\n\n      // Detect undefined and null values to shorten the execution and prevent exceptions\n      if (translationId === null || angular.isUndefined(translationId)) {\n        return translationId;\n      }\n\n      // Check forceLanguage is present\n      if (forceLanguage) {\n        loadTranslationsIfMissing(forceLanguage);\n      }\n\n      // Duck detection: If the first argument is an array, a bunch of translations was requested.\n      // The result is an object.\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, forceLanguage, sanitizeStrategy);\n        }\n        return results;\n      }\n\n      // We discarded unacceptable values. So we just need to verify if translationId is empty String\n      if (angular.isString(translationId) && translationId.length < 1) {\n        return translationId;\n      }\n\n      // trim off any whitespace\n      if (translationId) {\n        translationId = trim.apply(translationId);\n      }\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, uses, sanitizeStrategy);\n          }\n        }\n        if (typeof result !== 'undefined') {\n          break;\n        }\n      }\n\n      if (!result && result !== '') {\n        if ($notFoundIndicatorLeft || $notFoundIndicatorRight) {\n          result = applyNotFoundIndicators(translationId);\n        } else {\n          // Return translation of default interpolator if not found anything.\n          result = defaultInterpolator.interpolate(translationId, interpolateParams, 'filter', sanitizeStrategy);\n\n          // looks like the requested translation id doesn't exists.\n          // Now, if there is a registered handler for missing translations and no\n          // asyncLoader is pending, we execute the handler\n          var missingTranslationHandlerTranslation;\n          if ($missingTranslationHandlerFactory && !pendingLoader) {\n            missingTranslationHandlerTranslation = translateByHandler(translationId, interpolateParams, sanitizeStrategy);\n          }\n\n          if ($missingTranslationHandlerFactory && !pendingLoader && missingTranslationHandlerTranslation) {\n            result = missingTranslationHandlerTranslation;\n          }\n        }\n      }\n\n      return result;\n    };\n\n    /**\n     * @ngdoc function\n     * @name pascalprecht.translate.$translate#versionInfo\n     * @methodOf pascalprecht.translate.$translate\n     *\n     * @description\n     * Returns the current version information for the angular-translate library\n     *\n     * @return {string} angular-translate version\n     */\n    $translate.versionInfo = function () {\n      return version;\n    };\n\n    /**\n     * @ngdoc function\n     * @name pascalprecht.translate.$translate#loaderCache\n     * @methodOf pascalprecht.translate.$translate\n     *\n     * @description\n     * Returns the defined loaderCache.\n     *\n     * @return {boolean|string|object} current value of loaderCache\n     */\n    $translate.loaderCache = function () {\n      return loaderCache;\n    };\n\n    // internal purpose only\n    $translate.directivePriority = function () {\n      return directivePriority;\n    };\n\n    // internal purpose only\n    $translate.statefulFilter = function () {\n      return statefulFilter;\n    };\n\n    /**\n     * @ngdoc function\n     * @name pascalprecht.translate.$translate#isReady\n     * @methodOf pascalprecht.translate.$translate\n     *\n     * @description\n     * Returns whether the service is \"ready\" to translate (i.e. loading 1st language).\n     *\n     * See also {@link pascalprecht.translate.$translate#methods_onReady onReady()}.\n     *\n     * @return {boolean} current value of ready\n     */\n    $translate.isReady = function () {\n      return $isReady;\n    };\n\n    var $onReadyDeferred = $q.defer();\n    $onReadyDeferred.promise.then(function () {\n      $isReady = true;\n    });\n\n    /**\n     * @ngdoc function\n     * @name pascalprecht.translate.$translate#onReady\n     * @methodOf pascalprecht.translate.$translate\n     *\n     * @description\n     * Calls the function provided or resolved the returned promise after the service is \"ready\" to translate (i.e. loading 1st language).\n     *\n     * See also {@link pascalprecht.translate.$translate#methods_isReady isReady()}.\n     *\n     * @param {Function=} fn Function to invoke when service is ready\n     * @return {object} Promise resolved when service is ready\n     */\n    $translate.onReady = function (fn) {\n      var deferred = $q.defer();\n      if (angular.isFunction(fn)) {\n        deferred.promise.then(fn);\n      }\n      if ($isReady) {\n        deferred.resolve();\n      } else {\n        $onReadyDeferred.promise.then(deferred.resolve);\n      }\n      return deferred.promise;\n    };\n\n    /**\n     * @ngdoc function\n     * @name pascalprecht.translate.$translate#getAvailableLanguageKeys\n     * @methodOf pascalprecht.translate.$translate\n     *\n     * @description\n     * This function simply returns the registered language keys being defined before in the config phase\n     * With this, an application can use the array to provide a language selection dropdown or similar\n     * without any additional effort\n     *\n     * @returns {object} returns the list of possibly registered language keys and mapping or null if not defined\n     */\n    $translate.getAvailableLanguageKeys = function () {\n      if ($availableLanguageKeys.length > 0) {\n        return $availableLanguageKeys;\n      }\n      return null;\n    };\n\n    /**\n     * @ngdoc function\n     * @name pascalprecht.translate.$translate#getTranslationTable\n     * @methodOf pascalprecht.translate.$translate\n     *\n     * @description\n     * Returns translation table by the given language key.\n     *\n     * Unless a language is provided it returns a translation table of the current one.\n     * Note: If translation dictionary is currently downloading or in progress\n     * it will return null.\n     *\n     * @param {string} langKey A token which represents a translation id\n     *\n     * @return {object} a copy of angular-translate $translationTable\n     */\n    $translate.getTranslationTable = function (langKey) {\n      langKey = langKey || $translate.use();\n      if (langKey && $translationTable[langKey]) {\n        return angular.copy($translationTable[langKey]);\n      }\n      return null;\n    };\n\n    // Whenever $translateReady is being fired, this will ensure the state of $isReady\n    var globalOnReadyListener = $rootScope.$on('$translateReady', function () {\n      $onReadyDeferred.resolve();\n      globalOnReadyListener(); // one time only\n      globalOnReadyListener = null;\n    });\n    var globalOnChangeListener = $rootScope.$on('$translateChangeEnd', function () {\n      $onReadyDeferred.resolve();\n      globalOnChangeListener(); // one time only\n      globalOnChangeListener = null;\n    });\n\n    if ($loaderFactory) {\n\n      // If at least one async loader is defined and there are no\n      // (default) translations available we should try to load them.\n      if (angular.equals($translationTable, {})) {\n        if ($translate.use()) {\n          $translate.use($translate.use());\n        }\n      }\n\n      // Also, if there are any fallback language registered, we start\n      // loading them asynchronously as soon as we can.\n      if ($fallbackLanguage && $fallbackLanguage.length) {\n        var processAsyncResult = function (translation) {\n          translations(translation.key, translation.table);\n          $rootScope.$emit('$translateChangeEnd', {language : translation.key});\n          return translation;\n        };\n        for (var i = 0, len = $fallbackLanguage.length; i < len; i++) {\n          var fallbackLanguageId = $fallbackLanguage[i];\n          if ($forceAsyncReloadEnabled || !$translationTable[fallbackLanguageId]) {\n            langPromises[fallbackLanguageId] = loadAsync(fallbackLanguageId).then(processAsyncResult);\n          }\n        }\n      }\n    } else {\n      $rootScope.$emit('$translateReady', {language : $translate.use()});\n    }\n\n    return $translate;\n  }];\n}\n\n$translate.displayName = 'displayName';\n\n/**\n * @ngdoc object\n * @name pascalprecht.translate.$translateDefaultInterpolation\n * @requires $interpolate\n *\n * @description\n * Uses angular's `$interpolate` services to interpolate strings against some values.\n *\n * Be aware to configure a proper sanitization strategy.\n *\n * See also:\n * * {@link pascalprecht.translate.$translateSanitization}\n *\n * @return {object} $translateDefaultInterpolation Interpolator service\n */\nangular.module('pascalprecht.translate').factory('$translateDefaultInterpolation', $translateDefaultInterpolation);\n\nfunction $translateDefaultInterpolation ($interpolate, $translateSanitization) {\n\n  'use strict';\n\n  var $translateInterpolator = {},\n      $locale,\n      $identifier = 'default';\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateDefaultInterpolation#setLocale\n   * @methodOf pascalprecht.translate.$translateDefaultInterpolation\n   *\n   * @description\n   * Sets current locale (this is currently not use in this interpolation).\n   *\n   * @param {string} locale Language key or locale.\n   */\n  $translateInterpolator.setLocale = function (locale) {\n    $locale = locale;\n  };\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateDefaultInterpolation#getInterpolationIdentifier\n   * @methodOf pascalprecht.translate.$translateDefaultInterpolation\n   *\n   * @description\n   * Returns an identifier for this interpolation service.\n   *\n   * @returns {string} $identifier\n   */\n  $translateInterpolator.getInterpolationIdentifier = function () {\n    return $identifier;\n  };\n\n  /**\n   * @deprecated will be removed in 3.0\n   * @see {@link pascalprecht.translate.$translateSanitization}\n   */\n  $translateInterpolator.useSanitizeValueStrategy = function (value) {\n    $translateSanitization.useStrategy(value);\n    return this;\n  };\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateDefaultInterpolation#interpolate\n   * @methodOf pascalprecht.translate.$translateDefaultInterpolation\n   *\n   * @description\n   * Interpolates given value agains given interpolate params using angulars\n   * `$interpolate` service.\n   *\n   * Since AngularJS 1.5, `value` must not be a string but can be anything input.\n   *\n   * @param {string} value translation\n   * @param {object} interpolationParams interpolation params\n   * @param {string} context current context (filter, directive, service)\n   * @param {string} sanitizeStrategy sanitize strategy\n   * @param {string} translationId current translationId\n   *\n   * @returns {string} interpolated string\n   */\n  $translateInterpolator.interpolate = function (value, interpolationParams, context, sanitizeStrategy, translationId) { // jshint ignore:line\n    interpolationParams = interpolationParams || {};\n    interpolationParams = $translateSanitization.sanitize(interpolationParams, 'params', sanitizeStrategy, context);\n\n    var interpolatedText;\n    if (angular.isNumber(value)) {\n      // numbers are safe\n      interpolatedText = '' + value;\n    } else if (angular.isString(value)) {\n      // strings must be interpolated (that's the job here)\n      interpolatedText = $interpolate(value)(interpolationParams);\n      interpolatedText = $translateSanitization.sanitize(interpolatedText, 'text', sanitizeStrategy, context);\n    } else {\n      // neither a number or a string, cant interpolate => empty string\n      interpolatedText = '';\n    }\n\n    return interpolatedText;\n  };\n\n  return $translateInterpolator;\n}\n\n$translateDefaultInterpolation.displayName = '$translateDefaultInterpolation';\n\nangular.module('pascalprecht.translate').constant('$STORAGE_KEY', 'NG_TRANSLATE_LANG_KEY');\n\nangular.module('pascalprecht.translate')\n/**\n * @ngdoc directive\n * @name pascalprecht.translate.directive:translate\n * @requires $interpolate, \n * @requires $compile, \n * @requires $parse, \n * @requires $rootScope\n * @restrict AE\n *\n * @description\n * Translates given translation id either through attribute or DOM content.\n * Internally it uses $translate service to translate the translation id. It possible to\n * pass an optional `translate-values` object literal as string into translation id.\n *\n * @param {string=} translate Translation id which could be either string or interpolated string.\n * @param {string=} translate-values Values to pass into translation id. Can be passed as object literal string or interpolated object.\n * @param {string=} translate-attr-ATTR translate Translation id and put it into ATTR attribute.\n * @param {string=} translate-default will be used unless translation was successful\n * @param {boolean=} translate-compile (default true if present) defines locally activation of {@link pascalprecht.translate.$translateProvider#methods_usePostCompiling}\n * @param {boolean=} translate-keep-content (default true if present) defines that in case a KEY could not be translated, that the existing content is left in the innerHTML}\n *\n * @example\n   <example module=\"ngView\">\n    <file name=\"index.html\">\n      <div ng-controller=\"TranslateCtrl\">\n\n        <pre translate=\"TRANSLATION_ID\"></pre>\n        <pre translate>TRANSLATION_ID</pre>\n        <pre translate translate-attr-title=\"TRANSLATION_ID\"></pre>\n        <pre translate=\"{{translationId}}\"></pre>\n        <pre translate>{{translationId}}</pre>\n        <pre translate=\"WITH_VALUES\" translate-values=\"{value: 5}\"></pre>\n        <pre translate translate-values=\"{value: 5}\">WITH_VALUES</pre>\n        <pre translate=\"WITH_VALUES\" translate-values=\"{{values}}\"></pre>\n        <pre translate translate-values=\"{{values}}\">WITH_VALUES</pre>\n        <pre translate translate-attr-title=\"WITH_VALUES\" translate-values=\"{{values}}\"></pre>\n        <pre translate=\"WITH_CAMEL_CASE_KEY\" translate-value-camel-case-key=\"Hi\"></pre>\n\n      </div>\n    </file>\n    <file name=\"script.js\">\n      angular.module('ngView', ['pascalprecht.translate'])\n\n      .config(function ($translateProvider) {\n\n        $translateProvider.translations('en',{\n          'TRANSLATION_ID': 'Hello there!',\n          'WITH_VALUES': 'The following value is dynamic: {{value}}',\n          'WITH_CAMEL_CASE_KEY': 'The interpolation key is camel cased: {{camelCaseKey}}'\n        }).preferredLanguage('en');\n\n      });\n\n      angular.module('ngView').controller('TranslateCtrl', function ($scope) {\n        $scope.translationId = 'TRANSLATION_ID';\n\n        $scope.values = {\n          value: 78\n        };\n      });\n    </file>\n    <file name=\"scenario.js\">\n      it('should translate', function () {\n        inject(function ($rootScope, $compile) {\n          $rootScope.translationId = 'TRANSLATION_ID';\n\n          element = $compile('<p translate=\"TRANSLATION_ID\"></p>')($rootScope);\n          $rootScope.$digest();\n          expect(element.text()).toBe('Hello there!');\n\n          element = $compile('<p translate=\"{{translationId}}\"></p>')($rootScope);\n          $rootScope.$digest();\n          expect(element.text()).toBe('Hello there!');\n\n          element = $compile('<p translate>TRANSLATION_ID</p>')($rootScope);\n          $rootScope.$digest();\n          expect(element.text()).toBe('Hello there!');\n\n          element = $compile('<p translate>{{translationId}}</p>')($rootScope);\n          $rootScope.$digest();\n          expect(element.text()).toBe('Hello there!');\n\n          element = $compile('<p translate translate-attr-title=\"TRANSLATION_ID\"></p>')($rootScope);\n          $rootScope.$digest();\n          expect(element.attr('title')).toBe('Hello there!');\n\n          element = $compile('<p translate=\"WITH_CAMEL_CASE_KEY\" translate-value-camel-case-key=\"Hello\"></p>')($rootScope);\n          $rootScope.$digest();\n          expect(element.text()).toBe('The interpolation key is camel cased: Hello');\n        });\n      });\n    </file>\n   </example>\n */\n.directive('translate', translateDirective);\nfunction translateDirective($translate, $interpolate, $compile, $parse, $rootScope) {\n\n  'use strict';\n\n  /**\n   * @name trim\n   * @private\n   *\n   * @description\n   * trim polyfill\n   *\n   * @returns {string} The string stripped of whitespace from both ends\n   */\n  var trim = function() {\n    return this.toString().replace(/^\\s+|\\s+$/g, '');\n  };\n\n  return {\n    restrict: 'AE',\n    scope: true,\n    priority: $translate.directivePriority(),\n    compile: function (tElement, tAttr) {\n\n      var translateValuesExist = (tAttr.translateValues) ?\n        tAttr.translateValues : undefined;\n\n      var translateInterpolation = (tAttr.translateInterpolation) ?\n        tAttr.translateInterpolation : undefined;\n\n      var translateValueExist = tElement[0].outerHTML.match(/translate-value-+/i);\n\n      var interpolateRegExp = '^(.*)(' + $interpolate.startSymbol() + '.*' + $interpolate.endSymbol() + ')(.*)',\n          watcherRegExp = '^(.*)' + $interpolate.startSymbol() + '(.*)' + $interpolate.endSymbol() + '(.*)';\n\n      return function linkFn(scope, iElement, iAttr) {\n\n        scope.interpolateParams = {};\n        scope.preText = '';\n        scope.postText = '';\n        scope.translateNamespace = getTranslateNamespace(scope);\n        var translationIds = {};\n\n        var initInterpolationParams = function (interpolateParams, iAttr, tAttr) {\n          // initial setup\n          if (iAttr.translateValues) {\n            angular.extend(interpolateParams, $parse(iAttr.translateValues)(scope.$parent));\n          }\n          // initially fetch all attributes if existing and fill the params\n          if (translateValueExist) {\n            for (var attr in tAttr) {\n              if (Object.prototype.hasOwnProperty.call(iAttr, attr) && attr.substr(0, 14) === 'translateValue' && attr !== 'translateValues') {\n                var attributeName = angular.lowercase(attr.substr(14, 1)) + attr.substr(15);\n                interpolateParams[attributeName] = tAttr[attr];\n              }\n            }\n          }\n        };\n\n        // Ensures any change of the attribute \"translate\" containing the id will\n        // be re-stored to the scope's \"translationId\".\n        // If the attribute has no content, the element's text value (white spaces trimmed off) will be used.\n        var observeElementTranslation = function (translationId) {\n\n          // Remove any old watcher\n          if (angular.isFunction(observeElementTranslation._unwatchOld)) {\n            observeElementTranslation._unwatchOld();\n            observeElementTranslation._unwatchOld = undefined;\n          }\n\n          if (angular.equals(translationId , '') || !angular.isDefined(translationId)) {\n            var iElementText = trim.apply(iElement.text());\n\n            // Resolve translation id by inner html if required\n            var interpolateMatches = iElementText.match(interpolateRegExp);\n            // Interpolate translation id if required\n            if (angular.isArray(interpolateMatches)) {\n              scope.preText = interpolateMatches[1];\n              scope.postText = interpolateMatches[3];\n              translationIds.translate = $interpolate(interpolateMatches[2])(scope.$parent);\n              var watcherMatches = iElementText.match(watcherRegExp);\n              if (angular.isArray(watcherMatches) && watcherMatches[2] && watcherMatches[2].length) {\n                observeElementTranslation._unwatchOld = scope.$watch(watcherMatches[2], function (newValue) {\n                  translationIds.translate = newValue;\n                  updateTranslations();\n                });\n              }\n            } else {\n              // do not assigne the translation id if it is empty.\n              translationIds.translate = !iElementText ? undefined : iElementText;\n            }\n          } else {\n            translationIds.translate = translationId;\n          }\n          updateTranslations();\n        };\n\n        var observeAttributeTranslation = function (translateAttr) {\n          iAttr.$observe(translateAttr, function (translationId) {\n            translationIds[translateAttr] = translationId;\n            updateTranslations();\n          });\n        };\n\n        // initial setup with values\n        initInterpolationParams(scope.interpolateParams, iAttr, tAttr);\n\n        var firstAttributeChangedEvent = true;\n        iAttr.$observe('translate', function (translationId) {\n          if (typeof translationId === 'undefined') {\n            // case of element \"<translate>xyz</translate>\"\n            observeElementTranslation('');\n          } else {\n            // case of regular attribute\n            if (translationId !== '' || !firstAttributeChangedEvent) {\n              translationIds.translate = translationId;\n              updateTranslations();\n            }\n          }\n          firstAttributeChangedEvent = false;\n        });\n\n        for (var translateAttr in iAttr) {\n          if (iAttr.hasOwnProperty(translateAttr) && translateAttr.substr(0, 13) === 'translateAttr' && translateAttr.length > 13) {\n            observeAttributeTranslation(translateAttr);\n          }\n        }\n\n        iAttr.$observe('translateDefault', function (value) {\n          scope.defaultText = value;\n          updateTranslations();\n        });\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\n        if (translateValueExist) {\n          var observeValueAttribute = function (attrName) {\n            iAttr.$observe(attrName, function (value) {\n              var attributeName = angular.lowercase(attrName.substr(14, 1)) + attrName.substr(15);\n              scope.interpolateParams[attributeName] = 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              observeValueAttribute(attr);\n            }\n          }\n        }\n\n        // Master update function\n        var updateTranslations = function () {\n          for (var key in translationIds) {\n            if (translationIds.hasOwnProperty(key) && translationIds[key] !== undefined) {\n              updateTranslation(key, translationIds[key], scope, scope.interpolateParams, scope.defaultText, scope.translateNamespace);\n            }\n          }\n        };\n\n        // Put translation processing function outside loop\n        var updateTranslation = function(translateAttr, translationId, scope, interpolateParams, defaultTranslationText, translateNamespace) {\n          if (translationId) {\n            // if translation id starts with '.' and translateNamespace given, prepend namespace\n            if (translateNamespace && translationId.charAt(0) === '.') {\n              translationId = translateNamespace + translationId;\n            }\n\n            $translate(translationId, interpolateParams, translateInterpolation, defaultTranslationText, scope.translateLanguage)\n              .then(function (translation) {\n                applyTranslation(translation, scope, true, translateAttr);\n              }, function (translationId) {\n                applyTranslation(translationId, scope, false, translateAttr);\n              });\n          } else {\n            // as an empty string cannot be translated, we can solve this using successful=false\n            applyTranslation(translationId, scope, false, translateAttr);\n          }\n        };\n\n        var applyTranslation = function (value, scope, successful, translateAttr) {\n          if (!successful) {\n            if (typeof scope.defaultText !== 'undefined') {\n              value = scope.defaultText;\n            }\n          }\n          if (translateAttr === 'translate') {\n            // default translate into innerHTML\n            if (successful || (!successful && !$translate.isKeepContent() && typeof iAttr.translateKeepContent === 'undefined')) {\n              iElement.empty().append(scope.preText + value + scope.postText);\n            }\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          } else {\n            // translate attribute\n            var attributeName = iAttr.$attr[translateAttr];\n            if (attributeName.substr(0, 5) === 'data-') {\n              // ensure html5 data prefix is stripped\n              attributeName = attributeName.substr(5);\n            }\n            attributeName = attributeName.substr(15);\n            iElement.attr(attributeName, value);\n          }\n        };\n\n        if (translateValuesExist || translateValueExist || iAttr.translateDefault) {\n          scope.$watch('interpolateParams', updateTranslations, true);\n        }\n\n        // Replaced watcher on translateLanguage with event listener\n        scope.$on('translateLanguageChanged', updateTranslations);\n\n        // Ensures the text will be refreshed after the current language was changed\n        // w/ $translate.use(...)\n        var unbind = $rootScope.$on('$translateChangeSuccess', updateTranslations);\n\n        // ensure translation will be looked up at least one\n        if (iElement.text().length) {\n          if (iAttr.translate) {\n            observeElementTranslation(iAttr.translate);\n          } else {\n            observeElementTranslation('');\n          }\n        } else if (iAttr.translate) {\n          // ensure attribute will be not skipped\n          observeElementTranslation(iAttr.translate);\n        }\n        updateTranslations();\n        scope.$on('$destroy', unbind);\n      };\n    }\n  };\n}\n\n/**\n * Returns the scope's namespace.\n * @private\n * @param scope\n * @returns {string}\n */\nfunction getTranslateNamespace(scope) {\n  'use strict';\n  if (scope.translateNamespace) {\n    return scope.translateNamespace;\n  }\n  if (scope.$parent) {\n    return getTranslateNamespace(scope.$parent);\n  }\n}\n\ntranslateDirective.displayName = 'translateDirective';\n\nangular.module('pascalprecht.translate')\n/**\n * @ngdoc directive\n * @name pascalprecht.translate.directive:translate-attr\n * @restrict A\n *\n * @description\n * Translates attributes like translate-attr-ATTR, but with an object like ng-class.\n * Internally it uses `translate` service to translate translation id. It possible to\n * pass an optional `translate-values` object literal as string into translation id.\n *\n * @param {string=} translate-attr Object literal mapping attributes to translation ids.\n * @param {string=} translate-values Values to pass into the translation ids. Can be passed as object literal string.\n *\n * @example\n   <example module=\"ngView\">\n    <file name=\"index.html\">\n      <div ng-controller=\"TranslateCtrl\">\n\n        <input translate-attr=\"{ placeholder: translationId, title: 'WITH_VALUES' }\" translate-values=\"{value: 5}\" />\n\n      </div>\n    </file>\n    <file name=\"script.js\">\n      angular.module('ngView', ['pascalprecht.translate'])\n\n      .config(function ($translateProvider) {\n\n        $translateProvider.translations('en',{\n          'TRANSLATION_ID': 'Hello there!',\n          'WITH_VALUES': 'The following value is dynamic: {{value}}',\n        }).preferredLanguage('en');\n\n      });\n\n      angular.module('ngView').controller('TranslateCtrl', function ($scope) {\n        $scope.translationId = 'TRANSLATION_ID';\n\n        $scope.values = {\n          value: 78\n        };\n      });\n    </file>\n    <file name=\"scenario.js\">\n      it('should translate', function () {\n        inject(function ($rootScope, $compile) {\n          $rootScope.translationId = 'TRANSLATION_ID';\n\n          element = $compile('<input translate-attr=\"{ placeholder: translationId, title: 'WITH_VALUES' }\" translate-values=\"{ value: 5 }\" />')($rootScope);\n          $rootScope.$digest();\n          expect(element.attr('placeholder)).toBe('Hello there!');\n          expect(element.attr('title)).toBe('The following value is dynamic: 5');\n        });\n      });\n    </file>\n   </example>\n */\n.directive('translateAttr', translateAttrDirective);\nfunction translateAttrDirective($translate, $rootScope) {\n\n  'use strict';\n\n  return {\n    restrict: 'A',\n    priority: $translate.directivePriority(),\n    link: function linkFn(scope, element, attr) {\n\n      var translateAttr,\n          translateValues,\n          previousAttributes = {};\n\n      // Main update translations function\n      var updateTranslations = function () {\n        angular.forEach(translateAttr, function (translationId, attributeName) {\n          if (!translationId) {\n            return;\n          }\n          previousAttributes[attributeName] = true;\n\n          // if translation id starts with '.' and translateNamespace given, prepend namespace\n          if (scope.translateNamespace && translationId.charAt(0) === '.') {\n            translationId = scope.translateNamespace + translationId;\n          }\n          $translate(translationId, translateValues, attr.translateInterpolation, undefined, scope.translateLanguage)\n            .then(function (translation) {\n              element.attr(attributeName, translation);\n            }, function (translationId) {\n              element.attr(attributeName, translationId);\n            });\n        });\n\n        // Removing unused attributes that were previously used\n        angular.forEach(previousAttributes, function (flag, attributeName) {\n          if (!translateAttr[attributeName]) {\n            element.removeAttr(attributeName);\n            delete previousAttributes[attributeName];\n          }\n        });\n      };\n\n      // Watch for attribute changes\n      watchAttribute(\n        scope,\n        attr.translateAttr,\n        function (newValue) { translateAttr = newValue; },\n        updateTranslations\n      );\n      // Watch for value changes\n      watchAttribute(\n        scope,\n        attr.translateValues,\n        function (newValue) { translateValues = newValue; },\n        updateTranslations\n      );\n\n      if (attr.translateValues) {\n        scope.$watch(attr.translateValues, updateTranslations, true);\n      }\n\n      // Replaced watcher on translateLanguage with event listener\n      scope.$on('translateLanguageChanged', updateTranslations);\n\n      // Ensures the text will be refreshed after the current language was changed\n      // w/ $translate.use(...)\n      var unbind = $rootScope.$on('$translateChangeSuccess', updateTranslations);\n\n      updateTranslations();\n      scope.$on('$destroy', unbind);\n    }\n  };\n}\n\nfunction watchAttribute(scope, attribute, valueCallback, changeCallback) {\n  'use strict';\n  if (!attribute) {\n    return;\n  }\n  if (attribute.substr(0, 2) === '::') {\n    attribute = attribute.substr(2);\n  } else {\n    scope.$watch(attribute, function(newValue) {\n      valueCallback(newValue);\n      changeCallback();\n    }, true);\n  }\n  valueCallback(scope.$eval(attribute));\n}\n\ntranslateAttrDirective.displayName = 'translateAttrDirective';\n\nangular.module('pascalprecht.translate')\n/**\n * @ngdoc directive\n * @name pascalprecht.translate.directive:translateCloak\n * @requires $translate\n * @restrict A\n *\n * $description\n * Adds a `translate-cloak` class name to the given element where this directive\n * is applied initially and removes it, once a loader has finished loading.\n *\n * This directive can be used to prevent initial flickering when loading translation\n * data asynchronously.\n *\n * The class name is defined in\n * {@link pascalprecht.translate.$translateProvider#cloakClassName $translate.cloakClassName()}.\n *\n * @param {string=} translate-cloak If a translationId is provided, it will be used for showing\n *                                  or hiding the cloak. Basically it relies on the translation\n *                                  resolve.\n */\n.directive('translateCloak', translateCloakDirective);\n\nfunction translateCloakDirective($translate, $rootScope) {\n\n  'use strict';\n\n  return {\n    compile : function (tElement) {\n      var applyCloak = function (element) {\n          element.addClass($translate.cloakClassName());\n        },\n        removeCloak = function (element) {\n          element.removeClass($translate.cloakClassName());\n        };\n      applyCloak(tElement);\n\n      return function linkFn(scope, iElement, iAttr) {\n        //Create bound functions that incorporate the active DOM element.\n        var iRemoveCloak = removeCloak.bind(this, iElement), iApplyCloak = applyCloak.bind(this, iElement);\n        if (iAttr.translateCloak && iAttr.translateCloak.length) {\n          // Register a watcher for the defined translation allowing a fine tuned cloak\n          iAttr.$observe('translateCloak', function (translationId) {\n            $translate(translationId).then(iRemoveCloak, iApplyCloak);\n          });\n          $rootScope.$on('$translateChangeSuccess', function () {\n            $translate(iAttr.translateCloak).then(iRemoveCloak, iApplyCloak);\n          });\n        } else {\n          $translate.onReady(iRemoveCloak);\n        }\n      };\n    }\n  };\n}\n\ntranslateCloakDirective.displayName = 'translateCloakDirective';\n\nangular.module('pascalprecht.translate')\n/**\n * @ngdoc directive\n * @name pascalprecht.translate.directive:translateNamespace\n * @restrict A\n *\n * @description\n * Translates given translation id either through attribute or DOM content.\n * Internally it uses `translate` filter to translate translation id. It possible to\n * pass an optional `translate-values` object literal as string into translation id.\n *\n * @param {string=} translate namespace name which could be either string or interpolated string.\n *\n * @example\n   <example module=\"ngView\">\n    <file name=\"index.html\">\n      <div translate-namespace=\"CONTENT\">\n\n        <div>\n            <h1 translate>.HEADERS.TITLE</h1>\n            <h1 translate>.HEADERS.WELCOME</h1>\n        </div>\n\n        <div translate-namespace=\".HEADERS\">\n            <h1 translate>.TITLE</h1>\n            <h1 translate>.WELCOME</h1>\n        </div>\n\n      </div>\n    </file>\n    <file name=\"script.js\">\n      angular.module('ngView', ['pascalprecht.translate'])\n\n      .config(function ($translateProvider) {\n\n        $translateProvider.translations('en',{\n          'TRANSLATION_ID': 'Hello there!',\n          'CONTENT': {\n            'HEADERS': {\n                TITLE: 'Title'\n            }\n          },\n          'CONTENT.HEADERS.WELCOME': 'Welcome'\n        }).preferredLanguage('en');\n\n      });\n\n    </file>\n   </example>\n */\n.directive('translateNamespace', translateNamespaceDirective);\n\nfunction translateNamespaceDirective() {\n\n  'use strict';\n\n  return {\n    restrict: 'A',\n    scope: true,\n    compile: function () {\n      return {\n        pre: function (scope, iElement, iAttrs) {\n          scope.translateNamespace = getTranslateNamespace(scope);\n\n          if (scope.translateNamespace && iAttrs.translateNamespace.charAt(0) === '.') {\n            scope.translateNamespace += iAttrs.translateNamespace;\n          } else {\n            scope.translateNamespace = iAttrs.translateNamespace;\n          }\n        }\n      };\n    }\n  };\n}\n\n/**\n * Returns the scope's namespace.\n * @private\n * @param scope\n * @returns {string}\n */\nfunction getTranslateNamespace(scope) {\n  'use strict';\n  if (scope.translateNamespace) {\n    return scope.translateNamespace;\n  }\n  if (scope.$parent) {\n    return getTranslateNamespace(scope.$parent);\n  }\n}\n\ntranslateNamespaceDirective.displayName = 'translateNamespaceDirective';\n\nangular.module('pascalprecht.translate')\n/**\n * @ngdoc directive\n * @name pascalprecht.translate.directive:translateLanguage\n * @restrict A\n *\n * @description\n * Forces the language to the directives in the underlying scope.\n *\n * @param {string=} translate language that will be negotiated.\n *\n * @example\n   <example module=\"ngView\">\n    <file name=\"index.html\">\n      <div>\n\n        <div>\n            <h1 translate>HELLO</h1>\n        </div>\n\n        <div translate-language=\"de\">\n            <h1 translate>HELLO</h1>\n        </div>\n\n      </div>\n    </file>\n    <file name=\"script.js\">\n      angular.module('ngView', ['pascalprecht.translate'])\n\n      .config(function ($translateProvider) {\n\n        $translateProvider\n          .translations('en',{\n            'HELLO': 'Hello world!'\n          })\n          .translations('de',{\n            'HELLO': 'Hallo Welt!'\n          })\n          .preferredLanguage('en');\n\n      });\n\n    </file>\n   </example>\n */\n.directive('translateLanguage', translateLanguageDirective);\n\nfunction translateLanguageDirective() {\n\n  'use strict';\n\n  return {\n    restrict: 'A',\n    scope: true,\n    compile: function () {\n      return function linkFn(scope, iElement, iAttrs) {\n\n        iAttrs.$observe('translateLanguage', function (newTranslateLanguage) {\n          scope.translateLanguage = newTranslateLanguage;\n        });\n\n        scope.$watch('translateLanguage', function(){\n          scope.$broadcast('translateLanguageChanged');\n        });\n      };\n    }\n  };\n}\n\ntranslateLanguageDirective.displayName = 'translateLanguageDirective';\n\nangular.module('pascalprecht.translate')\n/**\n * @ngdoc filter\n * @name pascalprecht.translate.filter:translate\n * @requires $parse\n * @requires pascalprecht.translate.$translate\n * @function\n *\n * @description\n * Uses `$translate` service to translate contents. Accepts interpolate parameters\n * to pass dynamized values though translation.\n *\n * @param {string} translationId A translation id to be translated.\n * @param {*=} interpolateParams Optional object literal (as hash or string) to pass values into translation.\n *\n * @returns {string} Translated text.\n *\n * @example\n   <example module=\"ngView\">\n    <file name=\"index.html\">\n      <div ng-controller=\"TranslateCtrl\">\n\n        <pre>{{ 'TRANSLATION_ID' | translate }}</pre>\n        <pre>{{ translationId | translate }}</pre>\n        <pre>{{ 'WITH_VALUES' | translate:'{value: 5}' }}</pre>\n        <pre>{{ 'WITH_VALUES' | translate:values }}</pre>\n\n      </div>\n    </file>\n    <file name=\"script.js\">\n      angular.module('ngView', ['pascalprecht.translate'])\n\n      .config(function ($translateProvider) {\n\n        $translateProvider.translations('en', {\n          'TRANSLATION_ID': 'Hello there!',\n          'WITH_VALUES': 'The following value is dynamic: {{value}}'\n        });\n        $translateProvider.preferredLanguage('en');\n\n      });\n\n      angular.module('ngView').controller('TranslateCtrl', function ($scope) {\n        $scope.translationId = 'TRANSLATION_ID';\n\n        $scope.values = {\n          value: 78\n        };\n      });\n    </file>\n   </example>\n */\n.filter('translate', translateFilterFactory);\n\nfunction translateFilterFactory($parse, $translate) {\n\n  'use strict';\n\n  var translateFilter = function (translationId, interpolateParams, interpolation, forceLanguage) {\n    if (!angular.isObject(interpolateParams)) {\n      var ctx = this || {\n        '__SCOPE_IS_NOT_AVAILABLE': 'More info at https://github.com/angular/angular.js/commit/8863b9d04c722b278fa93c5d66ad1e578ad6eb1f'\n        };\n      interpolateParams = $parse(interpolateParams)(ctx);\n    }\n\n    return $translate.instant(translationId, interpolateParams, interpolation, forceLanguage);\n  };\n\n  if ($translate.statefulFilter()) {\n    translateFilter.$stateful = true;\n  }\n\n  return translateFilter;\n}\n\ntranslateFilterFactory.displayName = 'translateFilterFactory';\n\nangular.module('pascalprecht.translate')\n\n/**\n * @ngdoc object\n * @name pascalprecht.translate.$translationCache\n * @requires $cacheFactory\n *\n * @description\n * The first time a translation table is used, it is loaded in the translation cache for quick retrieval. You\n * can load translation tables directly into the cache by consuming the\n * `$translationCache` service directly.\n *\n * @return {object} $cacheFactory object.\n */\n  .factory('$translationCache', $translationCache);\n\nfunction $translationCache($cacheFactory) {\n\n  'use strict';\n\n  return $cacheFactory('translations');\n}\n\n$translationCache.displayName = '$translationCache';\nreturn 'pascalprecht.translate';\n\n}));\n"
  },
  {
    "path": "flowable-ui-web/modeler/libs/angular_1.3.13/angular.js",
    "content": "/**\n * @license AngularJS v1.3.13\n * (c) 2010-2014 Google, Inc. http://angularjs.org\n * License: MIT\n */\n(function(window, document, undefined) {'use strict';\n\n/**\n * @description\n *\n * This object provides a utility for producing rich Error messages within\n * Angular. It can be called as follows:\n *\n * var exampleMinErr = minErr('example');\n * throw exampleMinErr('one', 'This {0} is {1}', foo, bar);\n *\n * The above creates an instance of minErr in the example namespace. The\n * resulting error will have a namespaced error code of example.one.  The\n * resulting error will replace {0} with the value of foo, and {1} with the\n * value of bar. The object is not restricted in the number of arguments it can\n * take.\n *\n * If fewer arguments are specified than necessary for interpolation, the extra\n * interpolation markers will be preserved in the final string.\n *\n * Since data will be parsed statically during a build step, some restrictions\n * are applied with respect to how minErr instances are created and called.\n * Instances should have names of the form namespaceMinErr for a minErr created\n * using minErr('namespace') . Error codes, namespaces and template strings\n * should all be static strings, not variables or general expressions.\n *\n * @param {string} module The namespace to use for the new minErr instance.\n * @param {function} ErrorConstructor Custom error constructor to be instantiated when returning\n *   error from returned function, for cases when a particular type of error is useful.\n * @returns {function(code:string, template:string, ...templateArgs): Error} minErr instance\n */\n\nfunction minErr(module, ErrorConstructor) {\n  ErrorConstructor = ErrorConstructor || Error;\n  return function() {\n    var code = arguments[0],\n      prefix = '[' + (module ? module + ':' : '') + code + '] ',\n      template = arguments[1],\n      templateArgs = arguments,\n\n      message, i;\n\n    message = prefix + template.replace(/\\{\\d+\\}/g, function(match) {\n      var index = +match.slice(1, -1), arg;\n\n      if (index + 2 < templateArgs.length) {\n        return toDebugString(templateArgs[index + 2]);\n      }\n      return match;\n    });\n\n    message = message + '\\nhttp://errors.angularjs.org/1.3.13/' +\n      (module ? module + '/' : '') + code;\n    for (i = 2; i < arguments.length; i++) {\n      message = message + (i == 2 ? '?' : '&') + 'p' + (i - 2) + '=' +\n        encodeURIComponent(toDebugString(arguments[i]));\n    }\n    return new ErrorConstructor(message);\n  };\n}\n\n/* We need to tell jshint what variables are being exported */\n/* global angular: true,\n  msie: true,\n  jqLite: true,\n  jQuery: true,\n  slice: true,\n  splice: true,\n  push: true,\n  toString: true,\n  ngMinErr: true,\n  angularModule: true,\n  uid: true,\n  REGEX_STRING_REGEXP: true,\n  VALIDITY_STATE_PROPERTY: true,\n\n  lowercase: true,\n  uppercase: true,\n  manualLowercase: true,\n  manualUppercase: true,\n  nodeName_: true,\n  isArrayLike: true,\n  forEach: true,\n  sortedKeys: true,\n  forEachSorted: true,\n  reverseParams: true,\n  nextUid: true,\n  setHashKey: true,\n  extend: true,\n  int: true,\n  inherit: true,\n  noop: true,\n  identity: true,\n  valueFn: true,\n  isUndefined: true,\n  isDefined: true,\n  isObject: true,\n  isString: true,\n  isNumber: true,\n  isDate: true,\n  isArray: true,\n  isFunction: true,\n  isRegExp: true,\n  isWindow: true,\n  isScope: true,\n  isFile: true,\n  isFormData: true,\n  isBlob: true,\n  isBoolean: true,\n  isPromiseLike: true,\n  trim: true,\n  escapeForRegexp: true,\n  isElement: true,\n  makeMap: true,\n  includes: true,\n  arrayRemove: true,\n  copy: true,\n  shallowCopy: true,\n  equals: true,\n  csp: true,\n  concat: true,\n  sliceArgs: true,\n  bind: true,\n  toJsonReplacer: true,\n  toJson: true,\n  fromJson: true,\n  startingTag: true,\n  tryDecodeURIComponent: true,\n  parseKeyValue: true,\n  toKeyValue: true,\n  encodeUriSegment: true,\n  encodeUriQuery: true,\n  angularInit: true,\n  bootstrap: true,\n  getTestability: true,\n  snake_case: true,\n  bindJQuery: true,\n  assertArg: true,\n  assertArgFn: true,\n  assertNotHasOwnProperty: true,\n  getter: true,\n  getBlockNodes: true,\n  hasOwnProperty: true,\n  createMap: true,\n\n  NODE_TYPE_ELEMENT: true,\n  NODE_TYPE_TEXT: true,\n  NODE_TYPE_COMMENT: true,\n  NODE_TYPE_DOCUMENT: true,\n  NODE_TYPE_DOCUMENT_FRAGMENT: true,\n*/\n\n////////////////////////////////////\n\n/**\n * @ngdoc module\n * @name ng\n * @module ng\n * @description\n *\n * # ng (core module)\n * The ng module is loaded by default when an AngularJS application is started. The module itself\n * contains the essential components for an AngularJS application to function. The table below\n * lists a high level breakdown of each of the services/factories, filters, directives and testing\n * components available within this core module.\n *\n * <div doc-module-components=\"ng\"></div>\n */\n\nvar REGEX_STRING_REGEXP = /^\\/(.+)\\/([a-z]*)$/;\n\n// The name of a form control's ValidityState property.\n// This is used so that it's possible for internal tests to create mock ValidityStates.\nvar VALIDITY_STATE_PROPERTY = 'validity';\n\n/**\n * @ngdoc function\n * @name angular.lowercase\n * @module ng\n * @kind function\n *\n * @description Converts the specified string to lowercase.\n * @param {string} string String to be converted to lowercase.\n * @returns {string} Lowercased string.\n */\nvar lowercase = function(string) {return isString(string) ? string.toLowerCase() : string;};\nvar hasOwnProperty = Object.prototype.hasOwnProperty;\n\n/**\n * @ngdoc function\n * @name angular.uppercase\n * @module ng\n * @kind function\n *\n * @description Converts the specified string to uppercase.\n * @param {string} string String to be converted to uppercase.\n * @returns {string} Uppercased string.\n */\nvar uppercase = function(string) {return isString(string) ? string.toUpperCase() : string;};\n\n\nvar manualLowercase = function(s) {\n  /* jshint bitwise: false */\n  return isString(s)\n      ? s.replace(/[A-Z]/g, function(ch) {return String.fromCharCode(ch.charCodeAt(0) | 32);})\n      : s;\n};\nvar manualUppercase = function(s) {\n  /* jshint bitwise: false */\n  return isString(s)\n      ? s.replace(/[a-z]/g, function(ch) {return String.fromCharCode(ch.charCodeAt(0) & ~32);})\n      : s;\n};\n\n\n// String#toLowerCase and String#toUpperCase don't produce correct results in browsers with Turkish\n// locale, for this reason we need to detect this case and redefine lowercase/uppercase methods\n// with correct but slower alternatives.\nif ('i' !== 'I'.toLowerCase()) {\n  lowercase = manualLowercase;\n  uppercase = manualUppercase;\n}\n\n\nvar\n    msie,             // holds major version number for IE, or NaN if UA is not IE.\n    jqLite,           // delay binding since jQuery could be loaded after us.\n    jQuery,           // delay binding\n    slice             = [].slice,\n    splice            = [].splice,\n    push              = [].push,\n    toString          = Object.prototype.toString,\n    ngMinErr          = minErr('ng'),\n\n    /** @name angular */\n    angular           = window.angular || (window.angular = {}),\n    angularModule,\n    uid               = 0;\n\n/**\n * documentMode is an IE-only property\n * http://msdn.microsoft.com/en-us/library/ie/cc196988(v=vs.85).aspx\n */\nmsie = document.documentMode;\n\n\n/**\n * @private\n * @param {*} obj\n * @return {boolean} Returns true if `obj` is an array or array-like object (NodeList, Arguments,\n *                   String ...)\n */\nfunction isArrayLike(obj) {\n  if (obj == null || isWindow(obj)) {\n    return false;\n  }\n\n  var length = obj.length;\n\n  if (obj.nodeType === NODE_TYPE_ELEMENT && length) {\n    return true;\n  }\n\n  return isString(obj) || isArray(obj) || length === 0 ||\n         typeof length === 'number' && length > 0 && (length - 1) in obj;\n}\n\n/**\n * @ngdoc function\n * @name angular.forEach\n * @module ng\n * @kind function\n *\n * @description\n * Invokes the `iterator` function once for each item in `obj` collection, which can be either an\n * object or an array. The `iterator` function is invoked with `iterator(value, key, obj)`, where `value`\n * is the value of an object property or an array element, `key` is the object property key or\n * array element index and obj is the `obj` itself. Specifying a `context` for the function is optional.\n *\n * It is worth noting that `.forEach` does not iterate over inherited properties because it filters\n * using the `hasOwnProperty` method.\n *\n * Unlike ES262's\n * [Array.prototype.forEach](http://www.ecma-international.org/ecma-262/5.1/#sec-15.4.4.18),\n * Providing 'undefined' or 'null' values for `obj` will not throw a TypeError, but rather just\n * return the value provided.\n *\n   ```js\n     var values = {name: 'misko', gender: 'male'};\n     var log = [];\n     angular.forEach(values, function(value, key) {\n       this.push(key + ': ' + value);\n     }, log);\n     expect(log).toEqual(['name: misko', 'gender: male']);\n   ```\n *\n * @param {Object|Array} obj Object to iterate over.\n * @param {Function} iterator Iterator function.\n * @param {Object=} context Object to become context (`this`) for the iterator function.\n * @returns {Object|Array} Reference to `obj`.\n */\n\nfunction forEach(obj, iterator, context) {\n  var key, length;\n  if (obj) {\n    if (isFunction(obj)) {\n      for (key in obj) {\n        // Need to check if hasOwnProperty exists,\n        // as on IE8 the result of querySelectorAll is an object without a hasOwnProperty function\n        if (key != 'prototype' && key != 'length' && key != 'name' && (!obj.hasOwnProperty || obj.hasOwnProperty(key))) {\n          iterator.call(context, obj[key], key, obj);\n        }\n      }\n    } else if (isArray(obj) || isArrayLike(obj)) {\n      var isPrimitive = typeof obj !== 'object';\n      for (key = 0, length = obj.length; key < length; key++) {\n        if (isPrimitive || key in obj) {\n          iterator.call(context, obj[key], key, obj);\n        }\n      }\n    } else if (obj.forEach && obj.forEach !== forEach) {\n        obj.forEach(iterator, context, obj);\n    } else {\n      for (key in obj) {\n        if (obj.hasOwnProperty(key)) {\n          iterator.call(context, obj[key], key, obj);\n        }\n      }\n    }\n  }\n  return obj;\n}\n\nfunction sortedKeys(obj) {\n  return Object.keys(obj).sort();\n}\n\nfunction forEachSorted(obj, iterator, context) {\n  var keys = sortedKeys(obj);\n  for (var i = 0; i < keys.length; i++) {\n    iterator.call(context, obj[keys[i]], keys[i]);\n  }\n  return keys;\n}\n\n\n/**\n * when using forEach the params are value, key, but it is often useful to have key, value.\n * @param {function(string, *)} iteratorFn\n * @returns {function(*, string)}\n */\nfunction reverseParams(iteratorFn) {\n  return function(value, key) { iteratorFn(key, value); };\n}\n\n/**\n * A consistent way of creating unique IDs in angular.\n *\n * Using simple numbers allows us to generate 28.6 million unique ids per second for 10 years before\n * we hit number precision issues in JavaScript.\n *\n * Math.pow(2,53) / 60 / 60 / 24 / 365 / 10 = 28.6M\n *\n * @returns {number} an unique alpha-numeric string\n */\nfunction nextUid() {\n  return ++uid;\n}\n\n\n/**\n * Set or clear the hashkey for an object.\n * @param obj object\n * @param h the hashkey (!truthy to delete the hashkey)\n */\nfunction setHashKey(obj, h) {\n  if (h) {\n    obj.$$hashKey = h;\n  } else {\n    delete obj.$$hashKey;\n  }\n}\n\n/**\n * @ngdoc function\n * @name angular.extend\n * @module ng\n * @kind function\n *\n * @description\n * Extends the destination object `dst` by copying own enumerable properties from the `src` object(s)\n * to `dst`. You can specify multiple `src` objects. If you want to preserve original objects, you can do so\n * by passing an empty object as the target: `var object = angular.extend({}, object1, object2)`.\n * Note: Keep in mind that `angular.extend` does not support recursive merge (deep copy).\n *\n * @param {Object} dst Destination object.\n * @param {...Object} src Source object(s).\n * @returns {Object} Reference to `dst`.\n */\nfunction extend(dst) {\n  var h = dst.$$hashKey;\n\n  for (var i = 1, ii = arguments.length; i < ii; i++) {\n    var obj = arguments[i];\n    if (obj) {\n      var keys = Object.keys(obj);\n      for (var j = 0, jj = keys.length; j < jj; j++) {\n        var key = keys[j];\n        dst[key] = obj[key];\n      }\n    }\n  }\n\n  setHashKey(dst, h);\n  return dst;\n}\n\nfunction int(str) {\n  return parseInt(str, 10);\n}\n\n\nfunction inherit(parent, extra) {\n  return extend(Object.create(parent), extra);\n}\n\n/**\n * @ngdoc function\n * @name angular.noop\n * @module ng\n * @kind function\n *\n * @description\n * A function that performs no operations. This function can be useful when writing code in the\n * functional style.\n   ```js\n     function foo(callback) {\n       var result = calculateResult();\n       (callback || angular.noop)(result);\n     }\n   ```\n */\nfunction noop() {}\nnoop.$inject = [];\n\n\n/**\n * @ngdoc function\n * @name angular.identity\n * @module ng\n * @kind function\n *\n * @description\n * A function that returns its first argument. This function is useful when writing code in the\n * functional style.\n *\n   ```js\n     function transformer(transformationFn, value) {\n       return (transformationFn || angular.identity)(value);\n     };\n   ```\n  * @param {*} value to be returned.\n  * @returns {*} the value passed in.\n */\nfunction identity($) {return $;}\nidentity.$inject = [];\n\n\nfunction valueFn(value) {return function() {return value;};}\n\n/**\n * @ngdoc function\n * @name angular.isUndefined\n * @module ng\n * @kind function\n *\n * @description\n * Determines if a reference is undefined.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is undefined.\n */\nfunction isUndefined(value) {return typeof value === 'undefined';}\n\n\n/**\n * @ngdoc function\n * @name angular.isDefined\n * @module ng\n * @kind function\n *\n * @description\n * Determines if a reference is defined.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is defined.\n */\nfunction isDefined(value) {return typeof value !== 'undefined';}\n\n\n/**\n * @ngdoc function\n * @name angular.isObject\n * @module ng\n * @kind function\n *\n * @description\n * Determines if a reference is an `Object`. Unlike `typeof` in JavaScript, `null`s are not\n * considered to be objects. Note that JavaScript arrays are objects.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is an `Object` but not `null`.\n */\nfunction isObject(value) {\n  // http://jsperf.com/isobject4\n  return value !== null && typeof value === 'object';\n}\n\n\n/**\n * @ngdoc function\n * @name angular.isString\n * @module ng\n * @kind function\n *\n * @description\n * Determines if a reference is a `String`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `String`.\n */\nfunction isString(value) {return typeof value === 'string';}\n\n\n/**\n * @ngdoc function\n * @name angular.isNumber\n * @module ng\n * @kind function\n *\n * @description\n * Determines if a reference is a `Number`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Number`.\n */\nfunction isNumber(value) {return typeof value === 'number';}\n\n\n/**\n * @ngdoc function\n * @name angular.isDate\n * @module ng\n * @kind function\n *\n * @description\n * Determines if a value is a date.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Date`.\n */\nfunction isDate(value) {\n  return toString.call(value) === '[object Date]';\n}\n\n\n/**\n * @ngdoc function\n * @name angular.isArray\n * @module ng\n * @kind function\n *\n * @description\n * Determines if a reference is an `Array`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is an `Array`.\n */\nvar isArray = Array.isArray;\n\n/**\n * @ngdoc function\n * @name angular.isFunction\n * @module ng\n * @kind function\n *\n * @description\n * Determines if a reference is a `Function`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Function`.\n */\nfunction isFunction(value) {return typeof value === 'function';}\n\n\n/**\n * Determines if a value is a regular expression object.\n *\n * @private\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `RegExp`.\n */\nfunction isRegExp(value) {\n  return toString.call(value) === '[object RegExp]';\n}\n\n\n/**\n * Checks if `obj` is a window object.\n *\n * @private\n * @param {*} obj Object to check\n * @returns {boolean} True if `obj` is a window obj.\n */\nfunction isWindow(obj) {\n  return obj && obj.window === obj;\n}\n\n\nfunction isScope(obj) {\n  return obj && obj.$evalAsync && obj.$watch;\n}\n\n\nfunction isFile(obj) {\n  return toString.call(obj) === '[object File]';\n}\n\n\nfunction isFormData(obj) {\n  return toString.call(obj) === '[object FormData]';\n}\n\n\nfunction isBlob(obj) {\n  return toString.call(obj) === '[object Blob]';\n}\n\n\nfunction isBoolean(value) {\n  return typeof value === 'boolean';\n}\n\n\nfunction isPromiseLike(obj) {\n  return obj && isFunction(obj.then);\n}\n\n\nvar trim = function(value) {\n  return isString(value) ? value.trim() : value;\n};\n\n// Copied from:\n// http://docs.closure-library.googlecode.com/git/local_closure_goog_string_string.js.source.html#line1021\n// Prereq: s is a string.\nvar escapeForRegexp = function(s) {\n  return s.replace(/([-()\\[\\]{}+?*.$\\^|,:#<!\\\\])/g, '\\\\$1').\n           replace(/\\x08/g, '\\\\x08');\n};\n\n\n/**\n * @ngdoc function\n * @name angular.isElement\n * @module ng\n * @kind function\n *\n * @description\n * Determines if a reference is a DOM element (or wrapped jQuery element).\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a DOM element (or wrapped jQuery element).\n */\nfunction isElement(node) {\n  return !!(node &&\n    (node.nodeName  // we are a direct element\n    || (node.prop && node.attr && node.find)));  // we have an on and find method part of jQuery API\n}\n\n/**\n * @param str 'key1,key2,...'\n * @returns {object} in the form of {key1:true, key2:true, ...}\n */\nfunction makeMap(str) {\n  var obj = {}, items = str.split(\",\"), i;\n  for (i = 0; i < items.length; i++)\n    obj[items[i]] = true;\n  return obj;\n}\n\n\nfunction nodeName_(element) {\n  return lowercase(element.nodeName || (element[0] && element[0].nodeName));\n}\n\nfunction includes(array, obj) {\n  return Array.prototype.indexOf.call(array, obj) != -1;\n}\n\nfunction arrayRemove(array, value) {\n  var index = array.indexOf(value);\n  if (index >= 0)\n    array.splice(index, 1);\n  return value;\n}\n\n/**\n * @ngdoc function\n * @name angular.copy\n * @module ng\n * @kind function\n *\n * @description\n * Creates a deep copy of `source`, which should be an object or an array.\n *\n * * If no destination is supplied, a copy of the object or array is created.\n * * If a destination is provided, all of its elements (for arrays) or properties (for objects)\n *   are deleted and then all elements/properties from the source are copied to it.\n * * If `source` is not an object or array (inc. `null` and `undefined`), `source` is returned.\n * * If `source` is identical to 'destination' an exception will be thrown.\n *\n * @param {*} source The source that will be used to make a copy.\n *                   Can be any type, including primitives, `null`, and `undefined`.\n * @param {(Object|Array)=} destination Destination into which the source is copied. If\n *     provided, must be of the same type as `source`.\n * @returns {*} The copy or updated `destination`, if `destination` was specified.\n *\n * @example\n <example module=\"copyExample\">\n <file name=\"index.html\">\n <div ng-controller=\"ExampleController\">\n <form novalidate class=\"simple-form\">\n Name: <input type=\"text\" ng-model=\"user.name\" /><br />\n E-mail: <input type=\"email\" ng-model=\"user.email\" /><br />\n Gender: <input type=\"radio\" ng-model=\"user.gender\" value=\"male\" />male\n <input type=\"radio\" ng-model=\"user.gender\" value=\"female\" />female<br />\n <button ng-click=\"reset()\">RESET</button>\n <button ng-click=\"update(user)\">SAVE</button>\n </form>\n <pre>form = {{user | json}}</pre>\n <pre>master = {{master | json}}</pre>\n </div>\n\n <script>\n  angular.module('copyExample', [])\n    .controller('ExampleController', ['$scope', function($scope) {\n      $scope.master= {};\n\n      $scope.update = function(user) {\n        // Example with 1 argument\n        $scope.master= angular.copy(user);\n      };\n\n      $scope.reset = function() {\n        // Example with 2 arguments\n        angular.copy($scope.master, $scope.user);\n      };\n\n      $scope.reset();\n    }]);\n </script>\n </file>\n </example>\n */\nfunction copy(source, destination, stackSource, stackDest) {\n  if (isWindow(source) || isScope(source)) {\n    throw ngMinErr('cpws',\n      \"Can't copy! Making copies of Window or Scope instances is not supported.\");\n  }\n\n  if (!destination) {\n    destination = source;\n    if (source) {\n      if (isArray(source)) {\n        destination = copy(source, [], stackSource, stackDest);\n      } else if (isDate(source)) {\n        destination = new Date(source.getTime());\n      } else if (isRegExp(source)) {\n        destination = new RegExp(source.source, source.toString().match(/[^\\/]*$/)[0]);\n        destination.lastIndex = source.lastIndex;\n      } else if (isObject(source)) {\n        var emptyObject = Object.create(Object.getPrototypeOf(source));\n        destination = copy(source, emptyObject, stackSource, stackDest);\n      }\n    }\n  } else {\n    if (source === destination) throw ngMinErr('cpi',\n      \"Can't copy! Source and destination are identical.\");\n\n    stackSource = stackSource || [];\n    stackDest = stackDest || [];\n\n    if (isObject(source)) {\n      var index = stackSource.indexOf(source);\n      if (index !== -1) return stackDest[index];\n\n      stackSource.push(source);\n      stackDest.push(destination);\n    }\n\n    var result;\n    if (isArray(source)) {\n      destination.length = 0;\n      for (var i = 0; i < source.length; i++) {\n        result = copy(source[i], null, stackSource, stackDest);\n        if (isObject(source[i])) {\n          stackSource.push(source[i]);\n          stackDest.push(result);\n        }\n        destination.push(result);\n      }\n    } else {\n      var h = destination.$$hashKey;\n      if (isArray(destination)) {\n        destination.length = 0;\n      } else {\n        forEach(destination, function(value, key) {\n          delete destination[key];\n        });\n      }\n      for (var key in source) {\n        if (source.hasOwnProperty(key)) {\n          result = copy(source[key], null, stackSource, stackDest);\n          if (isObject(source[key])) {\n            stackSource.push(source[key]);\n            stackDest.push(result);\n          }\n          destination[key] = result;\n        }\n      }\n      setHashKey(destination,h);\n    }\n\n  }\n  return destination;\n}\n\n/**\n * Creates a shallow copy of an object, an array or a primitive.\n *\n * Assumes that there are no proto properties for objects.\n */\nfunction shallowCopy(src, dst) {\n  if (isArray(src)) {\n    dst = dst || [];\n\n    for (var i = 0, ii = src.length; i < ii; i++) {\n      dst[i] = src[i];\n    }\n  } else if (isObject(src)) {\n    dst = dst || {};\n\n    for (var key in src) {\n      if (!(key.charAt(0) === '$' && key.charAt(1) === '$')) {\n        dst[key] = src[key];\n      }\n    }\n  }\n\n  return dst || src;\n}\n\n\n/**\n * @ngdoc function\n * @name angular.equals\n * @module ng\n * @kind function\n *\n * @description\n * Determines if two objects or two values are equivalent. Supports value types, regular\n * expressions, arrays and objects.\n *\n * Two objects or values are considered equivalent if at least one of the following is true:\n *\n * * Both objects or values pass `===` comparison.\n * * Both objects or values are of the same type and all of their properties are equal by\n *   comparing them with `angular.equals`.\n * * Both values are NaN. (In JavaScript, NaN == NaN => false. But we consider two NaN as equal)\n * * Both values represent the same regular expression (In JavaScript,\n *   /abc/ == /abc/ => false. But we consider two regular expressions as equal when their textual\n *   representation matches).\n *\n * During a property comparison, properties of `function` type and properties with names\n * that begin with `$` are ignored.\n *\n * Scope and DOMWindow objects are being compared only by identify (`===`).\n *\n * @param {*} o1 Object or value to compare.\n * @param {*} o2 Object or value to compare.\n * @returns {boolean} True if arguments are equal.\n */\nfunction equals(o1, o2) {\n  if (o1 === o2) return true;\n  if (o1 === null || o2 === null) return false;\n  if (o1 !== o1 && o2 !== o2) return true; // NaN === NaN\n  var t1 = typeof o1, t2 = typeof o2, length, key, keySet;\n  if (t1 == t2) {\n    if (t1 == 'object') {\n      if (isArray(o1)) {\n        if (!isArray(o2)) return false;\n        if ((length = o1.length) == o2.length) {\n          for (key = 0; key < length; key++) {\n            if (!equals(o1[key], o2[key])) return false;\n          }\n          return true;\n        }\n      } else if (isDate(o1)) {\n        if (!isDate(o2)) return false;\n        return equals(o1.getTime(), o2.getTime());\n      } else if (isRegExp(o1) && isRegExp(o2)) {\n        return o1.toString() == o2.toString();\n      } else {\n        if (isScope(o1) || isScope(o2) || isWindow(o1) || isWindow(o2) || isArray(o2)) return false;\n        keySet = {};\n        for (key in o1) {\n          if (key.charAt(0) === '$' || isFunction(o1[key])) continue;\n          if (!equals(o1[key], o2[key])) return false;\n          keySet[key] = true;\n        }\n        for (key in o2) {\n          if (!keySet.hasOwnProperty(key) &&\n              key.charAt(0) !== '$' &&\n              o2[key] !== undefined &&\n              !isFunction(o2[key])) return false;\n        }\n        return true;\n      }\n    }\n  }\n  return false;\n}\n\nvar csp = function() {\n  if (isDefined(csp.isActive_)) return csp.isActive_;\n\n  var active = !!(document.querySelector('[ng-csp]') ||\n                  document.querySelector('[data-ng-csp]'));\n\n  if (!active) {\n    try {\n      /* jshint -W031, -W054 */\n      new Function('');\n      /* jshint +W031, +W054 */\n    } catch (e) {\n      active = true;\n    }\n  }\n\n  return (csp.isActive_ = active);\n};\n\n\n\nfunction concat(array1, array2, index) {\n  return array1.concat(slice.call(array2, index));\n}\n\nfunction sliceArgs(args, startIndex) {\n  return slice.call(args, startIndex || 0);\n}\n\n\n/* jshint -W101 */\n/**\n * @ngdoc function\n * @name angular.bind\n * @module ng\n * @kind function\n *\n * @description\n * Returns a function which calls function `fn` bound to `self` (`self` becomes the `this` for\n * `fn`). You can supply optional `args` that are prebound to the function. This feature is also\n * known as [partial application](http://en.wikipedia.org/wiki/Partial_application), as\n * distinguished from [function currying](http://en.wikipedia.org/wiki/Currying#Contrast_with_partial_function_application).\n *\n * @param {Object} self Context which `fn` should be evaluated in.\n * @param {function()} fn Function to be bound.\n * @param {...*} args Optional arguments to be prebound to the `fn` function call.\n * @returns {function()} Function that wraps the `fn` with all the specified bindings.\n */\n/* jshint +W101 */\nfunction bind(self, fn) {\n  var curryArgs = arguments.length > 2 ? sliceArgs(arguments, 2) : [];\n  if (isFunction(fn) && !(fn instanceof RegExp)) {\n    return curryArgs.length\n      ? function() {\n          return arguments.length\n            ? fn.apply(self, concat(curryArgs, arguments, 0))\n            : fn.apply(self, curryArgs);\n        }\n      : function() {\n          return arguments.length\n            ? fn.apply(self, arguments)\n            : fn.call(self);\n        };\n  } else {\n    // in IE, native methods are not functions so they cannot be bound (note: they don't need to be)\n    return fn;\n  }\n}\n\n\nfunction toJsonReplacer(key, value) {\n  var val = value;\n\n  if (typeof key === 'string' && key.charAt(0) === '$' && key.charAt(1) === '$') {\n    val = undefined;\n  } else if (isWindow(value)) {\n    val = '$WINDOW';\n  } else if (value &&  document === value) {\n    val = '$DOCUMENT';\n  } else if (isScope(value)) {\n    val = '$SCOPE';\n  }\n\n  return val;\n}\n\n\n/**\n * @ngdoc function\n * @name angular.toJson\n * @module ng\n * @kind function\n *\n * @description\n * Serializes input into a JSON-formatted string. Properties with leading $$ characters will be\n * stripped since angular uses this notation internally.\n *\n * @param {Object|Array|Date|string|number} obj Input to be serialized into JSON.\n * @param {boolean|number=} pretty If set to true, the JSON output will contain newlines and whitespace.\n *    If set to an integer, the JSON output will contain that many spaces per indentation (the default is 2).\n * @returns {string|undefined} JSON-ified string representing `obj`.\n */\nfunction toJson(obj, pretty) {\n  if (typeof obj === 'undefined') return undefined;\n  if (!isNumber(pretty)) {\n    pretty = pretty ? 2 : null;\n  }\n  return JSON.stringify(obj, toJsonReplacer, pretty);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.fromJson\n * @module ng\n * @kind function\n *\n * @description\n * Deserializes a JSON string.\n *\n * @param {string} json JSON string to deserialize.\n * @returns {Object|Array|string|number} Deserialized JSON string.\n */\nfunction fromJson(json) {\n  return isString(json)\n      ? JSON.parse(json)\n      : json;\n}\n\n\n/**\n * @returns {string} Returns the string representation of the element.\n */\nfunction startingTag(element) {\n  element = jqLite(element).clone();\n  try {\n    // turns out IE does not let you set .html() on elements which\n    // are not allowed to have children. So we just ignore it.\n    element.empty();\n  } catch (e) {}\n  var elemHtml = jqLite('<div>').append(element).html();\n  try {\n    return element[0].nodeType === NODE_TYPE_TEXT ? lowercase(elemHtml) :\n        elemHtml.\n          match(/^(<[^>]+>)/)[1].\n          replace(/^<([\\w\\-]+)/, function(match, nodeName) { return '<' + lowercase(nodeName); });\n  } catch (e) {\n    return lowercase(elemHtml);\n  }\n\n}\n\n\n/////////////////////////////////////////////////\n\n/**\n * Tries to decode the URI component without throwing an exception.\n *\n * @private\n * @param str value potential URI component to check.\n * @returns {boolean} True if `value` can be decoded\n * with the decodeURIComponent function.\n */\nfunction tryDecodeURIComponent(value) {\n  try {\n    return decodeURIComponent(value);\n  } catch (e) {\n    // Ignore any invalid uri component\n  }\n}\n\n\n/**\n * Parses an escaped url query string into key-value pairs.\n * @returns {Object.<string,boolean|Array>}\n */\nfunction parseKeyValue(/**string*/keyValue) {\n  var obj = {}, key_value, key;\n  forEach((keyValue || \"\").split('&'), function(keyValue) {\n    if (keyValue) {\n      key_value = keyValue.replace(/\\+/g,'%20').split('=');\n      key = tryDecodeURIComponent(key_value[0]);\n      if (isDefined(key)) {\n        var val = isDefined(key_value[1]) ? tryDecodeURIComponent(key_value[1]) : true;\n        if (!hasOwnProperty.call(obj, key)) {\n          obj[key] = val;\n        } else if (isArray(obj[key])) {\n          obj[key].push(val);\n        } else {\n          obj[key] = [obj[key],val];\n        }\n      }\n    }\n  });\n  return obj;\n}\n\nfunction toKeyValue(obj) {\n  var parts = [];\n  forEach(obj, function(value, key) {\n    if (isArray(value)) {\n      forEach(value, function(arrayValue) {\n        parts.push(encodeUriQuery(key, true) +\n                   (arrayValue === true ? '' : '=' + encodeUriQuery(arrayValue, true)));\n      });\n    } else {\n    parts.push(encodeUriQuery(key, true) +\n               (value === true ? '' : '=' + encodeUriQuery(value, true)));\n    }\n  });\n  return parts.length ? parts.join('&') : '';\n}\n\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 */\nfunction 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 custom\n * method because encodeURIComponent is too aggressive and encodes stuff that doesn't have to be\n * 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 */\nfunction 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(/%3B/gi, ';').\n             replace(/%20/g, (pctEncodeSpaces ? '%20' : '+'));\n}\n\nvar ngAttrPrefixes = ['ng-', 'data-ng-', 'ng:', 'x-ng-'];\n\nfunction getNgAttribute(element, ngAttr) {\n  var attr, i, ii = ngAttrPrefixes.length;\n  element = jqLite(element);\n  for (i = 0; i < ii; ++i) {\n    attr = ngAttrPrefixes[i] + ngAttr;\n    if (isString(attr = element.attr(attr))) {\n      return attr;\n    }\n  }\n  return null;\n}\n\n/**\n * @ngdoc directive\n * @name ngApp\n * @module ng\n *\n * @element ANY\n * @param {angular.Module} ngApp an optional application\n *   {@link angular.module module} name to load.\n * @param {boolean=} ngStrictDi if this attribute is present on the app element, the injector will be\n *   created in \"strict-di\" mode. This means that the application will fail to invoke functions which\n *   do not use explicit function annotation (and are thus unsuitable for minification), as described\n *   in {@link guide/di the Dependency Injection guide}, and useful debugging info will assist in\n *   tracking down the root of these bugs.\n *\n * @description\n *\n * Use this directive to **auto-bootstrap** an AngularJS application. The `ngApp` directive\n * designates the **root element** of the application and is typically placed near the root element\n * of the page - e.g. on the `<body>` or `<html>` tags.\n *\n * Only one AngularJS application can be auto-bootstrapped per HTML document. The first `ngApp`\n * found in the document will be used to define the root element to auto-bootstrap as an\n * application. To run multiple applications in an HTML document you must manually bootstrap them using\n * {@link angular.bootstrap} instead. AngularJS applications cannot be nested within each other.\n *\n * You can specify an **AngularJS module** to be used as the root module for the application.  This\n * module will be loaded into the {@link auto.$injector} when the application is bootstrapped. It\n * should contain the application code needed or have dependencies on other modules that will\n * contain the code. See {@link angular.module} for more information.\n *\n * In the example below if the `ngApp` directive were not placed on the `html` element then the\n * document would not be compiled, the `AppController` would not be instantiated and the `{{ a+b }}`\n * would not be resolved to `3`.\n *\n * `ngApp` is the easiest, and most common way to bootstrap an application.\n *\n <example module=\"ngAppDemo\">\n   <file name=\"index.html\">\n   <div ng-controller=\"ngAppDemoController\">\n     I can add: {{a}} + {{b}} =  {{ a+b }}\n   </div>\n   </file>\n   <file name=\"script.js\">\n   angular.module('ngAppDemo', []).controller('ngAppDemoController', function($scope) {\n     $scope.a = 1;\n     $scope.b = 2;\n   });\n   </file>\n </example>\n *\n * Using `ngStrictDi`, you would see something like this:\n *\n <example ng-app-included=\"true\">\n   <file name=\"index.html\">\n   <div ng-app=\"ngAppStrictDemo\" ng-strict-di>\n       <div ng-controller=\"GoodController1\">\n           I can add: {{a}} + {{b}} =  {{ a+b }}\n\n           <p>This renders because the controller does not fail to\n              instantiate, by using explicit annotation style (see\n              script.js for details)\n           </p>\n       </div>\n\n       <div ng-controller=\"GoodController2\">\n           Name: <input ng-model=\"name\"><br />\n           Hello, {{name}}!\n\n           <p>This renders because the controller does not fail to\n              instantiate, by using explicit annotation style\n              (see script.js for details)\n           </p>\n       </div>\n\n       <div ng-controller=\"BadController\">\n           I can add: {{a}} + {{b}} =  {{ a+b }}\n\n           <p>The controller could not be instantiated, due to relying\n              on automatic function annotations (which are disabled in\n              strict mode). As such, the content of this section is not\n              interpolated, and there should be an error in your web console.\n           </p>\n       </div>\n   </div>\n   </file>\n   <file name=\"script.js\">\n   angular.module('ngAppStrictDemo', [])\n     // BadController will fail to instantiate, due to relying on automatic function annotation,\n     // rather than an explicit annotation\n     .controller('BadController', function($scope) {\n       $scope.a = 1;\n       $scope.b = 2;\n     })\n     // Unlike BadController, GoodController1 and GoodController2 will not fail to be instantiated,\n     // due to using explicit annotations using the array style and $inject property, respectively.\n     .controller('GoodController1', ['$scope', function($scope) {\n       $scope.a = 1;\n       $scope.b = 2;\n     }])\n     .controller('GoodController2', GoodController2);\n     function GoodController2($scope) {\n       $scope.name = \"World\";\n     }\n     GoodController2.$inject = ['$scope'];\n   </file>\n   <file name=\"style.css\">\n   div[ng-controller] {\n       margin-bottom: 1em;\n       -webkit-border-radius: 4px;\n       border-radius: 4px;\n       border: 1px solid;\n       padding: .5em;\n   }\n   div[ng-controller^=Good] {\n       border-color: #d6e9c6;\n       background-color: #dff0d8;\n       color: #3c763d;\n   }\n   div[ng-controller^=Bad] {\n       border-color: #ebccd1;\n       background-color: #f2dede;\n       color: #a94442;\n       margin-bottom: 0;\n   }\n   </file>\n </example>\n */\nfunction angularInit(element, bootstrap) {\n  var appElement,\n      module,\n      config = {};\n\n  // The element `element` has priority over any other element\n  forEach(ngAttrPrefixes, function(prefix) {\n    var name = prefix + 'app';\n\n    if (!appElement && element.hasAttribute && element.hasAttribute(name)) {\n      appElement = element;\n      module = element.getAttribute(name);\n    }\n  });\n  forEach(ngAttrPrefixes, function(prefix) {\n    var name = prefix + 'app';\n    var candidate;\n\n    if (!appElement && (candidate = element.querySelector('[' + name.replace(':', '\\\\:') + ']'))) {\n      appElement = candidate;\n      module = candidate.getAttribute(name);\n    }\n  });\n  if (appElement) {\n    config.strictDi = getNgAttribute(appElement, \"strict-di\") !== null;\n    bootstrap(appElement, module ? [module] : [], config);\n  }\n}\n\n/**\n * @ngdoc function\n * @name angular.bootstrap\n * @module ng\n * @description\n * Use this function to manually start up angular application.\n *\n * See: {@link guide/bootstrap Bootstrap}\n *\n * Note that Protractor based end-to-end tests cannot use this function to bootstrap manually.\n * They must use {@link ng.directive:ngApp ngApp}.\n *\n * Angular will detect if it has been loaded into the browser more than once and only allow the\n * first loaded script to be bootstrapped and will report a warning to the browser console for\n * each of the subsequent scripts. This prevents strange results in applications, where otherwise\n * multiple instances of Angular try to work on the DOM.\n *\n * ```html\n * <!doctype html>\n * <html>\n * <body>\n * <div ng-controller=\"WelcomeController\">\n *   {{greeting}}\n * </div>\n *\n * <script src=\"angular.js\"></script>\n * <script>\n *   var app = angular.module('demo', [])\n *   .controller('WelcomeController', function($scope) {\n *       $scope.greeting = 'Welcome!';\n *   });\n *   angular.bootstrap(document, ['demo']);\n * </script>\n * </body>\n * </html>\n * ```\n *\n * @param {DOMElement} element DOM element which is the root of angular application.\n * @param {Array<String|Function|Array>=} modules an array of modules to load into the application.\n *     Each item in the array should be the name of a predefined module or a (DI annotated)\n *     function that will be invoked by the injector as a `config` block.\n *     See: {@link angular.module modules}\n * @param {Object=} config an object for defining configuration options for the application. The\n *     following keys are supported:\n *\n * * `strictDi` - disable automatic function annotation for the application. This is meant to\n *   assist in finding bugs which break minified code. Defaults to `false`.\n *\n * @returns {auto.$injector} Returns the newly created injector for this app.\n */\nfunction bootstrap(element, modules, config) {\n  if (!isObject(config)) config = {};\n  var defaultConfig = {\n    strictDi: false\n  };\n  config = extend(defaultConfig, config);\n  var doBootstrap = function() {\n    element = jqLite(element);\n\n    if (element.injector()) {\n      var tag = (element[0] === document) ? 'document' : startingTag(element);\n      //Encode angle brackets to prevent input from being sanitized to empty string #8683\n      throw ngMinErr(\n          'btstrpd',\n          \"App Already Bootstrapped with this Element '{0}'\",\n          tag.replace(/</,'&lt;').replace(/>/,'&gt;'));\n    }\n\n    modules = modules || [];\n    modules.unshift(['$provide', function($provide) {\n      $provide.value('$rootElement', element);\n    }]);\n\n    if (config.debugInfoEnabled) {\n      // Pushing so that this overrides `debugInfoEnabled` setting defined in user's `modules`.\n      modules.push(['$compileProvider', function($compileProvider) {\n        $compileProvider.debugInfoEnabled(true);\n      }]);\n    }\n\n    modules.unshift('ng');\n    var injector = createInjector(modules, config.strictDi);\n    injector.invoke(['$rootScope', '$rootElement', '$compile', '$injector',\n       function bootstrapApply(scope, element, compile, injector) {\n        scope.$apply(function() {\n          element.data('$injector', injector);\n          compile(element)(scope);\n        });\n      }]\n    );\n    return injector;\n  };\n\n  var NG_ENABLE_DEBUG_INFO = /^NG_ENABLE_DEBUG_INFO!/;\n  var NG_DEFER_BOOTSTRAP = /^NG_DEFER_BOOTSTRAP!/;\n\n  if (window && NG_ENABLE_DEBUG_INFO.test(window.name)) {\n    config.debugInfoEnabled = true;\n    window.name = window.name.replace(NG_ENABLE_DEBUG_INFO, '');\n  }\n\n  if (window && !NG_DEFER_BOOTSTRAP.test(window.name)) {\n    return doBootstrap();\n  }\n\n  window.name = window.name.replace(NG_DEFER_BOOTSTRAP, '');\n  angular.resumeBootstrap = function(extraModules) {\n    forEach(extraModules, function(module) {\n      modules.push(module);\n    });\n    return doBootstrap();\n  };\n\n  if (isFunction(angular.resumeDeferredBootstrap)) {\n    angular.resumeDeferredBootstrap();\n  }\n}\n\n/**\n * @ngdoc function\n * @name angular.reloadWithDebugInfo\n * @module ng\n * @description\n * Use this function to reload the current application with debug information turned on.\n * This takes precedence over a call to `$compileProvider.debugInfoEnabled(false)`.\n *\n * See {@link ng.$compileProvider#debugInfoEnabled} for more.\n */\nfunction reloadWithDebugInfo() {\n  window.name = 'NG_ENABLE_DEBUG_INFO!' + window.name;\n  window.location.reload();\n}\n\n/**\n * @name angular.getTestability\n * @module ng\n * @description\n * Get the testability service for the instance of Angular on the given\n * element.\n * @param {DOMElement} element DOM element which is the root of angular application.\n */\nfunction getTestability(rootElement) {\n  var injector = angular.element(rootElement).injector();\n  if (!injector) {\n    throw ngMinErr('test',\n      'no injector found for element argument to getTestability');\n  }\n  return injector.get('$$testability');\n}\n\nvar SNAKE_CASE_REGEXP = /[A-Z]/g;\nfunction snake_case(name, separator) {\n  separator = separator || '_';\n  return name.replace(SNAKE_CASE_REGEXP, function(letter, pos) {\n    return (pos ? separator : '') + letter.toLowerCase();\n  });\n}\n\nvar bindJQueryFired = false;\nvar skipDestroyOnNextJQueryCleanData;\nfunction bindJQuery() {\n  var originalCleanData;\n\n  if (bindJQueryFired) {\n    return;\n  }\n\n  // bind to jQuery if present;\n  jQuery = window.jQuery;\n  // Use jQuery if it exists with proper functionality, otherwise default to us.\n  // Angular 1.2+ requires jQuery 1.7+ for on()/off() support.\n  // Angular 1.3+ technically requires at least jQuery 2.1+ but it may work with older\n  // versions. It will not work for sure with jQuery <1.7, though.\n  if (jQuery && jQuery.fn.on) {\n    jqLite = jQuery;\n    extend(jQuery.fn, {\n      scope: JQLitePrototype.scope,\n      isolateScope: JQLitePrototype.isolateScope,\n      controller: JQLitePrototype.controller,\n      injector: JQLitePrototype.injector,\n      inheritedData: JQLitePrototype.inheritedData\n    });\n\n    // All nodes removed from the DOM via various jQuery APIs like .remove()\n    // are passed through jQuery.cleanData. Monkey-patch this method to fire\n    // the $destroy event on all removed nodes.\n    originalCleanData = jQuery.cleanData;\n    jQuery.cleanData = function(elems) {\n      var events;\n      if (!skipDestroyOnNextJQueryCleanData) {\n        for (var i = 0, elem; (elem = elems[i]) != null; i++) {\n          events = jQuery._data(elem, \"events\");\n          if (events && events.$destroy) {\n            jQuery(elem).triggerHandler('$destroy');\n          }\n        }\n      } else {\n        skipDestroyOnNextJQueryCleanData = false;\n      }\n      originalCleanData(elems);\n    };\n  } else {\n    jqLite = JQLite;\n  }\n\n  angular.element = jqLite;\n\n  // Prevent double-proxying.\n  bindJQueryFired = true;\n}\n\n/**\n * throw error if the argument is falsy.\n */\nfunction assertArg(arg, name, reason) {\n  if (!arg) {\n    throw ngMinErr('areq', \"Argument '{0}' is {1}\", (name || '?'), (reason || \"required\"));\n  }\n  return arg;\n}\n\nfunction assertArgFn(arg, name, acceptArrayAnnotation) {\n  if (acceptArrayAnnotation && isArray(arg)) {\n      arg = arg[arg.length - 1];\n  }\n\n  assertArg(isFunction(arg), name, 'not a function, got ' +\n      (arg && typeof arg === 'object' ? arg.constructor.name || 'Object' : typeof arg));\n  return arg;\n}\n\n/**\n * throw error if the name given is hasOwnProperty\n * @param  {String} name    the name to test\n * @param  {String} context the context in which the name is used, such as module or directive\n */\nfunction assertNotHasOwnProperty(name, context) {\n  if (name === 'hasOwnProperty') {\n    throw ngMinErr('badname', \"hasOwnProperty is not a valid {0} name\", context);\n  }\n}\n\n/**\n * Return the value accessible from the object by path. Any undefined traversals are ignored\n * @param {Object} obj starting object\n * @param {String} path path to traverse\n * @param {boolean} [bindFnToScope=true]\n * @returns {Object} value as accessible by path\n */\n//TODO(misko): this function needs to be removed\nfunction getter(obj, path, bindFnToScope) {\n  if (!path) return obj;\n  var keys = path.split('.');\n  var key;\n  var lastInstance = obj;\n  var len = keys.length;\n\n  for (var i = 0; i < len; i++) {\n    key = keys[i];\n    if (obj) {\n      obj = (lastInstance = obj)[key];\n    }\n  }\n  if (!bindFnToScope && isFunction(obj)) {\n    return bind(lastInstance, obj);\n  }\n  return obj;\n}\n\n/**\n * Return the DOM siblings between the first and last node in the given array.\n * @param {Array} array like object\n * @returns {jqLite} jqLite collection containing the nodes\n */\nfunction getBlockNodes(nodes) {\n  // TODO(perf): just check if all items in `nodes` are siblings and if they are return the original\n  //             collection, otherwise update the original collection.\n  var node = nodes[0];\n  var endNode = nodes[nodes.length - 1];\n  var blockNodes = [node];\n\n  do {\n    node = node.nextSibling;\n    if (!node) break;\n    blockNodes.push(node);\n  } while (node !== endNode);\n\n  return jqLite(blockNodes);\n}\n\n\n/**\n * Creates a new object without a prototype. This object is useful for lookup without having to\n * guard against prototypically inherited properties via hasOwnProperty.\n *\n * Related micro-benchmarks:\n * - http://jsperf.com/object-create2\n * - http://jsperf.com/proto-map-lookup/2\n * - http://jsperf.com/for-in-vs-object-keys2\n *\n * @returns {Object}\n */\nfunction createMap() {\n  return Object.create(null);\n}\n\nvar NODE_TYPE_ELEMENT = 1;\nvar NODE_TYPE_TEXT = 3;\nvar NODE_TYPE_COMMENT = 8;\nvar NODE_TYPE_DOCUMENT = 9;\nvar NODE_TYPE_DOCUMENT_FRAGMENT = 11;\n\n/**\n * @ngdoc type\n * @name angular.Module\n * @module ng\n * @description\n *\n * Interface for configuring angular {@link angular.module modules}.\n */\n\nfunction setupModuleLoader(window) {\n\n  var $injectorMinErr = minErr('$injector');\n  var ngMinErr = minErr('ng');\n\n  function ensure(obj, name, factory) {\n    return obj[name] || (obj[name] = factory());\n  }\n\n  var angular = ensure(window, 'angular', Object);\n\n  // We need to expose `angular.$$minErr` to modules such as `ngResource` that reference it during bootstrap\n  angular.$$minErr = angular.$$minErr || minErr;\n\n  return ensure(angular, 'module', function() {\n    /** @type {Object.<string, angular.Module>} */\n    var modules = {};\n\n    /**\n     * @ngdoc function\n     * @name angular.module\n     * @module ng\n     * @description\n     *\n     * The `angular.module` is a global place for creating, registering and retrieving Angular\n     * modules.\n     * All modules (angular core or 3rd party) that should be available to an application must be\n     * registered using this mechanism.\n     *\n     * When passed two or more arguments, a new module is created.  If passed only one argument, an\n     * existing module (the name passed as the first argument to `module`) is retrieved.\n     *\n     *\n     * # Module\n     *\n     * A module is a collection of services, directives, controllers, filters, and configuration information.\n     * `angular.module` is used to configure the {@link auto.$injector $injector}.\n     *\n     * ```js\n     * // Create a new module\n     * var myModule = angular.module('myModule', []);\n     *\n     * // register a new service\n     * myModule.value('appName', 'MyCoolApp');\n     *\n     * // configure existing services inside initialization blocks.\n     * myModule.config(['$locationProvider', function($locationProvider) {\n     *   // Configure existing providers\n     *   $locationProvider.hashPrefix('!');\n     * }]);\n     * ```\n     *\n     * Then you can create an injector and load your modules like this:\n     *\n     * ```js\n     * var injector = angular.injector(['ng', 'myModule'])\n     * ```\n     *\n     * However it's more likely that you'll just use\n     * {@link ng.directive:ngApp ngApp} or\n     * {@link angular.bootstrap} to simplify this process for you.\n     *\n     * @param {!string} name The name of the module to create or retrieve.\n     * @param {!Array.<string>=} requires If specified then new module is being created. If\n     *        unspecified then the module is being retrieved for further configuration.\n     * @param {Function=} configFn Optional configuration function for the module. Same as\n     *        {@link angular.Module#config Module#config()}.\n     * @returns {module} new module with the {@link angular.Module} api.\n     */\n    return function module(name, requires, configFn) {\n      var assertNotHasOwnProperty = function(name, context) {\n        if (name === 'hasOwnProperty') {\n          throw ngMinErr('badname', 'hasOwnProperty is not a valid {0} name', context);\n        }\n      };\n\n      assertNotHasOwnProperty(name, 'module');\n      if (requires && modules.hasOwnProperty(name)) {\n        modules[name] = null;\n      }\n      return ensure(modules, name, function() {\n        if (!requires) {\n          throw $injectorMinErr('nomod', \"Module '{0}' is not available! You either misspelled \" +\n             \"the module name or forgot to load it. If registering a module ensure that you \" +\n             \"specify the dependencies as the second argument.\", name);\n        }\n\n        /** @type {!Array.<Array.<*>>} */\n        var invokeQueue = [];\n\n        /** @type {!Array.<Function>} */\n        var configBlocks = [];\n\n        /** @type {!Array.<Function>} */\n        var runBlocks = [];\n\n        var config = invokeLater('$injector', 'invoke', 'push', configBlocks);\n\n        /** @type {angular.Module} */\n        var moduleInstance = {\n          // Private state\n          _invokeQueue: invokeQueue,\n          _configBlocks: configBlocks,\n          _runBlocks: runBlocks,\n\n          /**\n           * @ngdoc property\n           * @name angular.Module#requires\n           * @module ng\n           *\n           * @description\n           * Holds the list of modules which the injector will load before the current module is\n           * loaded.\n           */\n          requires: requires,\n\n          /**\n           * @ngdoc property\n           * @name angular.Module#name\n           * @module ng\n           *\n           * @description\n           * Name of the module.\n           */\n          name: name,\n\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#provider\n           * @module ng\n           * @param {string} name service name\n           * @param {Function} providerType Construction function for creating new instance of the\n           *                                service.\n           * @description\n           * See {@link auto.$provide#provider $provide.provider()}.\n           */\n          provider: invokeLater('$provide', 'provider'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#factory\n           * @module ng\n           * @param {string} name service name\n           * @param {Function} providerFunction Function for creating new instance of the service.\n           * @description\n           * See {@link auto.$provide#factory $provide.factory()}.\n           */\n          factory: invokeLater('$provide', 'factory'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#service\n           * @module ng\n           * @param {string} name service name\n           * @param {Function} constructor A constructor function that will be instantiated.\n           * @description\n           * See {@link auto.$provide#service $provide.service()}.\n           */\n          service: invokeLater('$provide', 'service'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#value\n           * @module ng\n           * @param {string} name service name\n           * @param {*} object Service instance object.\n           * @description\n           * See {@link auto.$provide#value $provide.value()}.\n           */\n          value: invokeLater('$provide', 'value'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#constant\n           * @module ng\n           * @param {string} name constant name\n           * @param {*} object Constant value.\n           * @description\n           * Because the constant are fixed, they get applied before other provide methods.\n           * See {@link auto.$provide#constant $provide.constant()}.\n           */\n          constant: invokeLater('$provide', 'constant', 'unshift'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#animation\n           * @module ng\n           * @param {string} name animation name\n           * @param {Function} animationFactory Factory function for creating new instance of an\n           *                                    animation.\n           * @description\n           *\n           * **NOTE**: animations take effect only if the **ngAnimate** module is loaded.\n           *\n           *\n           * Defines an animation hook that can be later used with\n           * {@link ngAnimate.$animate $animate} service and directives that use this service.\n           *\n           * ```js\n           * module.animation('.animation-name', function($inject1, $inject2) {\n           *   return {\n           *     eventName : function(element, done) {\n           *       //code to run the animation\n           *       //once complete, then run done()\n           *       return function cancellationFunction(element) {\n           *         //code to cancel the animation\n           *       }\n           *     }\n           *   }\n           * })\n           * ```\n           *\n           * See {@link ng.$animateProvider#register $animateProvider.register()} and\n           * {@link ngAnimate ngAnimate module} for more information.\n           */\n          animation: invokeLater('$animateProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#filter\n           * @module ng\n           * @param {string} name Filter name.\n           * @param {Function} filterFactory Factory function for creating new instance of filter.\n           * @description\n           * See {@link ng.$filterProvider#register $filterProvider.register()}.\n           */\n          filter: invokeLater('$filterProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#controller\n           * @module ng\n           * @param {string|Object} name Controller name, or an object map of controllers where the\n           *    keys are the names and the values are the constructors.\n           * @param {Function} constructor Controller constructor function.\n           * @description\n           * See {@link ng.$controllerProvider#register $controllerProvider.register()}.\n           */\n          controller: invokeLater('$controllerProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#directive\n           * @module ng\n           * @param {string|Object} name Directive name, or an object map of directives where the\n           *    keys are the names and the values are the factories.\n           * @param {Function} directiveFactory Factory function for creating new instance of\n           * directives.\n           * @description\n           * See {@link ng.$compileProvider#directive $compileProvider.directive()}.\n           */\n          directive: invokeLater('$compileProvider', 'directive'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#config\n           * @module ng\n           * @param {Function} configFn Execute this function on module load. Useful for service\n           *    configuration.\n           * @description\n           * Use this method to register work which needs to be performed on module loading.\n           * For more about how to configure services, see\n           * {@link providers#provider-recipe Provider Recipe}.\n           */\n          config: config,\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#run\n           * @module ng\n           * @param {Function} initializationFn Execute this function after injector creation.\n           *    Useful for application initialization.\n           * @description\n           * Use this method to register work which should be performed when the injector is done\n           * loading all modules.\n           */\n          run: function(block) {\n            runBlocks.push(block);\n            return this;\n          }\n        };\n\n        if (configFn) {\n          config(configFn);\n        }\n\n        return moduleInstance;\n\n        /**\n         * @param {string} provider\n         * @param {string} method\n         * @param {String=} insertMethod\n         * @returns {angular.Module}\n         */\n        function invokeLater(provider, method, insertMethod, queue) {\n          if (!queue) queue = invokeQueue;\n          return function() {\n            queue[insertMethod || 'push']([provider, method, arguments]);\n            return moduleInstance;\n          };\n        }\n      });\n    };\n  });\n\n}\n\n/* global: toDebugString: true */\n\nfunction serializeObject(obj) {\n  var seen = [];\n\n  return JSON.stringify(obj, function(key, val) {\n    val = toJsonReplacer(key, val);\n    if (isObject(val)) {\n\n      if (seen.indexOf(val) >= 0) return '<<already seen>>';\n\n      seen.push(val);\n    }\n    return val;\n  });\n}\n\nfunction toDebugString(obj) {\n  if (typeof obj === 'function') {\n    return obj.toString().replace(/ \\{[\\s\\S]*$/, '');\n  } else if (typeof obj === 'undefined') {\n    return 'undefined';\n  } else if (typeof obj !== 'string') {\n    return serializeObject(obj);\n  }\n  return obj;\n}\n\n/* global angularModule: true,\n  version: true,\n\n  $LocaleProvider,\n  $CompileProvider,\n\n  htmlAnchorDirective,\n  inputDirective,\n  inputDirective,\n  formDirective,\n  scriptDirective,\n  selectDirective,\n  styleDirective,\n  optionDirective,\n  ngBindDirective,\n  ngBindHtmlDirective,\n  ngBindTemplateDirective,\n  ngClassDirective,\n  ngClassEvenDirective,\n  ngClassOddDirective,\n  ngCspDirective,\n  ngCloakDirective,\n  ngControllerDirective,\n  ngFormDirective,\n  ngHideDirective,\n  ngIfDirective,\n  ngIncludeDirective,\n  ngIncludeFillContentDirective,\n  ngInitDirective,\n  ngNonBindableDirective,\n  ngPluralizeDirective,\n  ngRepeatDirective,\n  ngShowDirective,\n  ngStyleDirective,\n  ngSwitchDirective,\n  ngSwitchWhenDirective,\n  ngSwitchDefaultDirective,\n  ngOptionsDirective,\n  ngTranscludeDirective,\n  ngModelDirective,\n  ngListDirective,\n  ngChangeDirective,\n  patternDirective,\n  patternDirective,\n  requiredDirective,\n  requiredDirective,\n  minlengthDirective,\n  minlengthDirective,\n  maxlengthDirective,\n  maxlengthDirective,\n  ngValueDirective,\n  ngModelOptionsDirective,\n  ngAttributeAliasDirectives,\n  ngEventDirectives,\n\n  $AnchorScrollProvider,\n  $AnimateProvider,\n  $BrowserProvider,\n  $CacheFactoryProvider,\n  $ControllerProvider,\n  $DocumentProvider,\n  $ExceptionHandlerProvider,\n  $FilterProvider,\n  $InterpolateProvider,\n  $IntervalProvider,\n  $HttpProvider,\n  $HttpBackendProvider,\n  $LocationProvider,\n  $LogProvider,\n  $ParseProvider,\n  $RootScopeProvider,\n  $QProvider,\n  $$QProvider,\n  $$SanitizeUriProvider,\n  $SceProvider,\n  $SceDelegateProvider,\n  $SnifferProvider,\n  $TemplateCacheProvider,\n  $TemplateRequestProvider,\n  $$TestabilityProvider,\n  $TimeoutProvider,\n  $$RAFProvider,\n  $$AsyncCallbackProvider,\n  $WindowProvider,\n  $$jqLiteProvider\n*/\n\n\n/**\n * @ngdoc object\n * @name angular.version\n * @module ng\n * @description\n * An object that contains information about the current AngularJS version. This object has the\n * following properties:\n *\n * - `full` – `{string}` – Full version string, such as \"0.9.18\".\n * - `major` – `{number}` – Major version number, such as \"0\".\n * - `minor` – `{number}` – Minor version number, such as \"9\".\n * - `dot` – `{number}` – Dot version number, such as \"18\".\n * - `codeName` – `{string}` – Code name of the release, such as \"jiggling-armfat\".\n */\nvar version = {\n  full: '1.3.13',    // all of these placeholder strings will be replaced by grunt's\n  major: 1,    // package task\n  minor: 3,\n  dot: 13,\n  codeName: 'meticulous-riffleshuffle'\n};\n\n\nfunction publishExternalAPI(angular) {\n  extend(angular, {\n    'bootstrap': bootstrap,\n    'copy': copy,\n    'extend': extend,\n    'equals': equals,\n    'element': jqLite,\n    'forEach': forEach,\n    'injector': createInjector,\n    'noop': noop,\n    'bind': bind,\n    'toJson': toJson,\n    'fromJson': fromJson,\n    'identity': identity,\n    'isUndefined': isUndefined,\n    'isDefined': isDefined,\n    'isString': isString,\n    'isFunction': isFunction,\n    'isObject': isObject,\n    'isNumber': isNumber,\n    'isElement': isElement,\n    'isArray': isArray,\n    'version': version,\n    'isDate': isDate,\n    'lowercase': lowercase,\n    'uppercase': uppercase,\n    'callbacks': {counter: 0},\n    'getTestability': getTestability,\n    '$$minErr': minErr,\n    '$$csp': csp,\n    'reloadWithDebugInfo': reloadWithDebugInfo\n  });\n\n  angularModule = setupModuleLoader(window);\n  try {\n    angularModule('ngLocale');\n  } catch (e) {\n    angularModule('ngLocale', []).provider('$locale', $LocaleProvider);\n  }\n\n  angularModule('ng', ['ngLocale'], ['$provide',\n    function ngModule($provide) {\n      // $$sanitizeUriProvider needs to be before $compileProvider as it is used by it.\n      $provide.provider({\n        $$sanitizeUri: $$SanitizeUriProvider\n      });\n      $provide.provider('$compile', $CompileProvider).\n        directive({\n            a: htmlAnchorDirective,\n            input: inputDirective,\n            textarea: inputDirective,\n            form: formDirective,\n            script: scriptDirective,\n            select: selectDirective,\n            style: styleDirective,\n            option: optionDirective,\n            ngBind: ngBindDirective,\n            ngBindHtml: ngBindHtmlDirective,\n            ngBindTemplate: ngBindTemplateDirective,\n            ngClass: ngClassDirective,\n            ngClassEven: ngClassEvenDirective,\n            ngClassOdd: ngClassOddDirective,\n            ngCloak: ngCloakDirective,\n            ngController: ngControllerDirective,\n            ngForm: ngFormDirective,\n            ngHide: ngHideDirective,\n            ngIf: ngIfDirective,\n            ngInclude: ngIncludeDirective,\n            ngInit: ngInitDirective,\n            ngNonBindable: ngNonBindableDirective,\n            ngPluralize: ngPluralizeDirective,\n            ngRepeat: ngRepeatDirective,\n            ngShow: ngShowDirective,\n            ngStyle: ngStyleDirective,\n            ngSwitch: ngSwitchDirective,\n            ngSwitchWhen: ngSwitchWhenDirective,\n            ngSwitchDefault: ngSwitchDefaultDirective,\n            ngOptions: ngOptionsDirective,\n            ngTransclude: ngTranscludeDirective,\n            ngModel: ngModelDirective,\n            ngList: ngListDirective,\n            ngChange: ngChangeDirective,\n            pattern: patternDirective,\n            ngPattern: patternDirective,\n            required: requiredDirective,\n            ngRequired: requiredDirective,\n            minlength: minlengthDirective,\n            ngMinlength: minlengthDirective,\n            maxlength: maxlengthDirective,\n            ngMaxlength: maxlengthDirective,\n            ngValue: ngValueDirective,\n            ngModelOptions: ngModelOptionsDirective\n        }).\n        directive({\n          ngInclude: ngIncludeFillContentDirective\n        }).\n        directive(ngAttributeAliasDirectives).\n        directive(ngEventDirectives);\n      $provide.provider({\n        $anchorScroll: $AnchorScrollProvider,\n        $animate: $AnimateProvider,\n        $browser: $BrowserProvider,\n        $cacheFactory: $CacheFactoryProvider,\n        $controller: $ControllerProvider,\n        $document: $DocumentProvider,\n        $exceptionHandler: $ExceptionHandlerProvider,\n        $filter: $FilterProvider,\n        $interpolate: $InterpolateProvider,\n        $interval: $IntervalProvider,\n        $http: $HttpProvider,\n        $httpBackend: $HttpBackendProvider,\n        $location: $LocationProvider,\n        $log: $LogProvider,\n        $parse: $ParseProvider,\n        $rootScope: $RootScopeProvider,\n        $q: $QProvider,\n        $$q: $$QProvider,\n        $sce: $SceProvider,\n        $sceDelegate: $SceDelegateProvider,\n        $sniffer: $SnifferProvider,\n        $templateCache: $TemplateCacheProvider,\n        $templateRequest: $TemplateRequestProvider,\n        $$testability: $$TestabilityProvider,\n        $timeout: $TimeoutProvider,\n        $window: $WindowProvider,\n        $$rAF: $$RAFProvider,\n        $$asyncCallback: $$AsyncCallbackProvider,\n        $$jqLite: $$jqLiteProvider\n      });\n    }\n  ]);\n}\n\n/* global JQLitePrototype: true,\n  addEventListenerFn: true,\n  removeEventListenerFn: true,\n  BOOLEAN_ATTR: true,\n  ALIASED_ATTR: true,\n*/\n\n//////////////////////////////////\n//JQLite\n//////////////////////////////////\n\n/**\n * @ngdoc function\n * @name angular.element\n * @module ng\n * @kind function\n *\n * @description\n * Wraps a raw DOM element or HTML string as a [jQuery](http://jquery.com) element.\n *\n * If jQuery is available, `angular.element` is an alias for the\n * [jQuery](http://api.jquery.com/jQuery/) function. If jQuery is not available, `angular.element`\n * delegates to Angular's built-in subset of jQuery, called \"jQuery lite\" or \"jqLite.\"\n *\n * <div class=\"alert alert-success\">jqLite is a tiny, API-compatible subset of jQuery that allows\n * Angular to manipulate the DOM in a cross-browser compatible way. **jqLite** implements only the most\n * commonly needed functionality with the goal of having a very small footprint.</div>\n *\n * To use jQuery, simply load it before `DOMContentLoaded` event fired.\n *\n * <div class=\"alert\">**Note:** all element references in Angular are always wrapped with jQuery or\n * jqLite; they are never raw DOM references.</div>\n *\n * ## Angular's jqLite\n * jqLite provides only the following jQuery methods:\n *\n * - [`addClass()`](http://api.jquery.com/addClass/)\n * - [`after()`](http://api.jquery.com/after/)\n * - [`append()`](http://api.jquery.com/append/)\n * - [`attr()`](http://api.jquery.com/attr/) - Does not support functions as parameters\n * - [`bind()`](http://api.jquery.com/bind/) - Does not support namespaces, selectors or eventData\n * - [`children()`](http://api.jquery.com/children/) - Does not support selectors\n * - [`clone()`](http://api.jquery.com/clone/)\n * - [`contents()`](http://api.jquery.com/contents/)\n * - [`css()`](http://api.jquery.com/css/) - Only retrieves inline-styles, does not call `getComputedStyle()`\n * - [`data()`](http://api.jquery.com/data/)\n * - [`detach()`](http://api.jquery.com/detach/)\n * - [`empty()`](http://api.jquery.com/empty/)\n * - [`eq()`](http://api.jquery.com/eq/)\n * - [`find()`](http://api.jquery.com/find/) - Limited to lookups by tag name\n * - [`hasClass()`](http://api.jquery.com/hasClass/)\n * - [`html()`](http://api.jquery.com/html/)\n * - [`next()`](http://api.jquery.com/next/) - Does not support selectors\n * - [`on()`](http://api.jquery.com/on/) - Does not support namespaces, selectors or eventData\n * - [`off()`](http://api.jquery.com/off/) - Does not support namespaces or selectors\n * - [`one()`](http://api.jquery.com/one/) - Does not support namespaces or selectors\n * - [`parent()`](http://api.jquery.com/parent/) - Does not support selectors\n * - [`prepend()`](http://api.jquery.com/prepend/)\n * - [`prop()`](http://api.jquery.com/prop/)\n * - [`ready()`](http://api.jquery.com/ready/)\n * - [`remove()`](http://api.jquery.com/remove/)\n * - [`removeAttr()`](http://api.jquery.com/removeAttr/)\n * - [`removeClass()`](http://api.jquery.com/removeClass/)\n * - [`removeData()`](http://api.jquery.com/removeData/)\n * - [`replaceWith()`](http://api.jquery.com/replaceWith/)\n * - [`text()`](http://api.jquery.com/text/)\n * - [`toggleClass()`](http://api.jquery.com/toggleClass/)\n * - [`triggerHandler()`](http://api.jquery.com/triggerHandler/) - Passes a dummy event object to handlers.\n * - [`unbind()`](http://api.jquery.com/unbind/) - Does not support namespaces\n * - [`val()`](http://api.jquery.com/val/)\n * - [`wrap()`](http://api.jquery.com/wrap/)\n *\n * ## jQuery/jqLite Extras\n * Angular also provides the following additional methods and events to both jQuery and jqLite:\n *\n * ### Events\n * - `$destroy` - AngularJS intercepts all jqLite/jQuery's DOM destruction apis and fires this event\n *    on all DOM nodes being removed.  This can be used to clean up any 3rd party bindings to the DOM\n *    element before it is removed.\n *\n * ### Methods\n * - `controller(name)` - retrieves the controller of the current element or its parent. By default\n *   retrieves controller associated with the `ngController` directive. If `name` is provided as\n *   camelCase directive name, then the controller for this directive will be retrieved (e.g.\n *   `'ngModel'`).\n * - `injector()` - retrieves the injector of the current element or its parent.\n * - `scope()` - retrieves the {@link ng.$rootScope.Scope scope} of the current\n *   element or its parent. Requires {@link guide/production#disabling-debug-data Debug Data} to\n *   be enabled.\n * - `isolateScope()` - retrieves an isolate {@link ng.$rootScope.Scope scope} if one is attached directly to the\n *   current element. This getter should be used only on elements that contain a directive which starts a new isolate\n *   scope. Calling `scope()` on this element always returns the original non-isolate scope.\n *   Requires {@link guide/production#disabling-debug-data Debug Data} to be enabled.\n * - `inheritedData()` - same as `data()`, but walks up the DOM until a value is found or the top\n *   parent element is reached.\n *\n * @param {string|DOMElement} element HTML string or DOMElement to be wrapped into jQuery.\n * @returns {Object} jQuery object.\n */\n\nJQLite.expando = 'ng339';\n\nvar jqCache = JQLite.cache = {},\n    jqId = 1,\n    addEventListenerFn = function(element, type, fn) {\n      element.addEventListener(type, fn, false);\n    },\n    removeEventListenerFn = function(element, type, fn) {\n      element.removeEventListener(type, fn, false);\n    };\n\n/*\n * !!! This is an undocumented \"private\" function !!!\n */\nJQLite._data = function(node) {\n  //jQuery always returns an object on cache miss\n  return this.cache[node[this.expando]] || {};\n};\n\nfunction jqNextId() { return ++jqId; }\n\n\nvar SPECIAL_CHARS_REGEXP = /([\\:\\-\\_]+(.))/g;\nvar MOZ_HACK_REGEXP = /^moz([A-Z])/;\nvar MOUSE_EVENT_MAP= { mouseleave: \"mouseout\", mouseenter: \"mouseover\"};\nvar jqLiteMinErr = minErr('jqLite');\n\n/**\n * Converts snake_case to camelCase.\n * Also there is special case for Moz prefix starting with upper case letter.\n * @param name Name to normalize\n */\nfunction camelCase(name) {\n  return name.\n    replace(SPECIAL_CHARS_REGEXP, function(_, separator, letter, offset) {\n      return offset ? letter.toUpperCase() : letter;\n    }).\n    replace(MOZ_HACK_REGEXP, 'Moz$1');\n}\n\nvar SINGLE_TAG_REGEXP = /^<(\\w+)\\s*\\/?>(?:<\\/\\1>|)$/;\nvar HTML_REGEXP = /<|&#?\\w+;/;\nvar TAG_NAME_REGEXP = /<([\\w:]+)/;\nvar XHTML_TAG_REGEXP = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\\w:]+)[^>]*)\\/>/gi;\n\nvar wrapMap = {\n  'option': [1, '<select multiple=\"multiple\">', '</select>'],\n\n  'thead': [1, '<table>', '</table>'],\n  'col': [2, '<table><colgroup>', '</colgroup></table>'],\n  'tr': [2, '<table><tbody>', '</tbody></table>'],\n  'td': [3, '<table><tbody><tr>', '</tr></tbody></table>'],\n  '_default': [0, \"\", \"\"]\n};\n\nwrapMap.optgroup = wrapMap.option;\nwrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;\nwrapMap.th = wrapMap.td;\n\n\nfunction jqLiteIsTextNode(html) {\n  return !HTML_REGEXP.test(html);\n}\n\nfunction jqLiteAcceptsData(node) {\n  // The window object can accept data but has no nodeType\n  // Otherwise we are only interested in elements (1) and documents (9)\n  var nodeType = node.nodeType;\n  return nodeType === NODE_TYPE_ELEMENT || !nodeType || nodeType === NODE_TYPE_DOCUMENT;\n}\n\nfunction jqLiteBuildFragment(html, context) {\n  var tmp, tag, wrap,\n      fragment = context.createDocumentFragment(),\n      nodes = [], i;\n\n  if (jqLiteIsTextNode(html)) {\n    // Convert non-html into a text node\n    nodes.push(context.createTextNode(html));\n  } else {\n    // Convert html into DOM nodes\n    tmp = tmp || fragment.appendChild(context.createElement(\"div\"));\n    tag = (TAG_NAME_REGEXP.exec(html) || [\"\", \"\"])[1].toLowerCase();\n    wrap = wrapMap[tag] || wrapMap._default;\n    tmp.innerHTML = wrap[1] + html.replace(XHTML_TAG_REGEXP, \"<$1></$2>\") + wrap[2];\n\n    // Descend through wrappers to the right content\n    i = wrap[0];\n    while (i--) {\n      tmp = tmp.lastChild;\n    }\n\n    nodes = concat(nodes, tmp.childNodes);\n\n    tmp = fragment.firstChild;\n    tmp.textContent = \"\";\n  }\n\n  // Remove wrapper from fragment\n  fragment.textContent = \"\";\n  fragment.innerHTML = \"\"; // Clear inner HTML\n  forEach(nodes, function(node) {\n    fragment.appendChild(node);\n  });\n\n  return fragment;\n}\n\nfunction jqLiteParseHTML(html, context) {\n  context = context || document;\n  var parsed;\n\n  if ((parsed = SINGLE_TAG_REGEXP.exec(html))) {\n    return [context.createElement(parsed[1])];\n  }\n\n  if ((parsed = jqLiteBuildFragment(html, context))) {\n    return parsed.childNodes;\n  }\n\n  return [];\n}\n\n/////////////////////////////////////////////\nfunction JQLite(element) {\n  if (element instanceof JQLite) {\n    return element;\n  }\n\n  var argIsString;\n\n  if (isString(element)) {\n    element = trim(element);\n    argIsString = true;\n  }\n  if (!(this instanceof JQLite)) {\n    if (argIsString && element.charAt(0) != '<') {\n      throw jqLiteMinErr('nosel', 'Looking up elements via selectors is not supported by jqLite! See: http://docs.angularjs.org/api/angular.element');\n    }\n    return new JQLite(element);\n  }\n\n  if (argIsString) {\n    jqLiteAddNodes(this, jqLiteParseHTML(element));\n  } else {\n    jqLiteAddNodes(this, element);\n  }\n}\n\nfunction jqLiteClone(element) {\n  return element.cloneNode(true);\n}\n\nfunction jqLiteDealoc(element, onlyDescendants) {\n  if (!onlyDescendants) jqLiteRemoveData(element);\n\n  if (element.querySelectorAll) {\n    var descendants = element.querySelectorAll('*');\n    for (var i = 0, l = descendants.length; i < l; i++) {\n      jqLiteRemoveData(descendants[i]);\n    }\n  }\n}\n\nfunction jqLiteOff(element, type, fn, unsupported) {\n  if (isDefined(unsupported)) throw jqLiteMinErr('offargs', 'jqLite#off() does not support the `selector` argument');\n\n  var expandoStore = jqLiteExpandoStore(element);\n  var events = expandoStore && expandoStore.events;\n  var handle = expandoStore && expandoStore.handle;\n\n  if (!handle) return; //no listeners registered\n\n  if (!type) {\n    for (type in events) {\n      if (type !== '$destroy') {\n        removeEventListenerFn(element, type, handle);\n      }\n      delete events[type];\n    }\n  } else {\n    forEach(type.split(' '), function(type) {\n      if (isDefined(fn)) {\n        var listenerFns = events[type];\n        arrayRemove(listenerFns || [], fn);\n        if (listenerFns && listenerFns.length > 0) {\n          return;\n        }\n      }\n\n      removeEventListenerFn(element, type, handle);\n      delete events[type];\n    });\n  }\n}\n\nfunction jqLiteRemoveData(element, name) {\n  var expandoId = element.ng339;\n  var expandoStore = expandoId && jqCache[expandoId];\n\n  if (expandoStore) {\n    if (name) {\n      delete expandoStore.data[name];\n      return;\n    }\n\n    if (expandoStore.handle) {\n      if (expandoStore.events.$destroy) {\n        expandoStore.handle({}, '$destroy');\n      }\n      jqLiteOff(element);\n    }\n    delete jqCache[expandoId];\n    element.ng339 = undefined; // don't delete DOM expandos. IE and Chrome don't like it\n  }\n}\n\n\nfunction jqLiteExpandoStore(element, createIfNecessary) {\n  var expandoId = element.ng339,\n      expandoStore = expandoId && jqCache[expandoId];\n\n  if (createIfNecessary && !expandoStore) {\n    element.ng339 = expandoId = jqNextId();\n    expandoStore = jqCache[expandoId] = {events: {}, data: {}, handle: undefined};\n  }\n\n  return expandoStore;\n}\n\n\nfunction jqLiteData(element, key, value) {\n  if (jqLiteAcceptsData(element)) {\n\n    var isSimpleSetter = isDefined(value);\n    var isSimpleGetter = !isSimpleSetter && key && !isObject(key);\n    var massGetter = !key;\n    var expandoStore = jqLiteExpandoStore(element, !isSimpleGetter);\n    var data = expandoStore && expandoStore.data;\n\n    if (isSimpleSetter) { // data('key', value)\n      data[key] = value;\n    } else {\n      if (massGetter) {  // data()\n        return data;\n      } else {\n        if (isSimpleGetter) { // data('key')\n          // don't force creation of expandoStore if it doesn't exist yet\n          return data && data[key];\n        } else { // mass-setter: data({key1: val1, key2: val2})\n          extend(data, key);\n        }\n      }\n    }\n  }\n}\n\nfunction jqLiteHasClass(element, selector) {\n  if (!element.getAttribute) return false;\n  return ((\" \" + (element.getAttribute('class') || '') + \" \").replace(/[\\n\\t]/g, \" \").\n      indexOf(\" \" + selector + \" \") > -1);\n}\n\nfunction jqLiteRemoveClass(element, cssClasses) {\n  if (cssClasses && element.setAttribute) {\n    forEach(cssClasses.split(' '), function(cssClass) {\n      element.setAttribute('class', trim(\n          (\" \" + (element.getAttribute('class') || '') + \" \")\n          .replace(/[\\n\\t]/g, \" \")\n          .replace(\" \" + trim(cssClass) + \" \", \" \"))\n      );\n    });\n  }\n}\n\nfunction jqLiteAddClass(element, cssClasses) {\n  if (cssClasses && element.setAttribute) {\n    var existingClasses = (' ' + (element.getAttribute('class') || '') + ' ')\n                            .replace(/[\\n\\t]/g, \" \");\n\n    forEach(cssClasses.split(' '), function(cssClass) {\n      cssClass = trim(cssClass);\n      if (existingClasses.indexOf(' ' + cssClass + ' ') === -1) {\n        existingClasses += cssClass + ' ';\n      }\n    });\n\n    element.setAttribute('class', trim(existingClasses));\n  }\n}\n\n\nfunction jqLiteAddNodes(root, elements) {\n  // THIS CODE IS VERY HOT. Don't make changes without benchmarking.\n\n  if (elements) {\n\n    // if a Node (the most common case)\n    if (elements.nodeType) {\n      root[root.length++] = elements;\n    } else {\n      var length = elements.length;\n\n      // if an Array or NodeList and not a Window\n      if (typeof length === 'number' && elements.window !== elements) {\n        if (length) {\n          for (var i = 0; i < length; i++) {\n            root[root.length++] = elements[i];\n          }\n        }\n      } else {\n        root[root.length++] = elements;\n      }\n    }\n  }\n}\n\n\nfunction jqLiteController(element, name) {\n  return jqLiteInheritedData(element, '$' + (name || 'ngController') + 'Controller');\n}\n\nfunction jqLiteInheritedData(element, name, value) {\n  // if element is the document object work with the html element instead\n  // this makes $(document).scope() possible\n  if (element.nodeType == NODE_TYPE_DOCUMENT) {\n    element = element.documentElement;\n  }\n  var names = isArray(name) ? name : [name];\n\n  while (element) {\n    for (var i = 0, ii = names.length; i < ii; i++) {\n      if ((value = jqLite.data(element, names[i])) !== undefined) return value;\n    }\n\n    // If dealing with a document fragment node with a host element, and no parent, use the host\n    // element as the parent. This enables directives within a Shadow DOM or polyfilled Shadow DOM\n    // to lookup parent controllers.\n    element = element.parentNode || (element.nodeType === NODE_TYPE_DOCUMENT_FRAGMENT && element.host);\n  }\n}\n\nfunction jqLiteEmpty(element) {\n  jqLiteDealoc(element, true);\n  while (element.firstChild) {\n    element.removeChild(element.firstChild);\n  }\n}\n\nfunction jqLiteRemove(element, keepData) {\n  if (!keepData) jqLiteDealoc(element);\n  var parent = element.parentNode;\n  if (parent) parent.removeChild(element);\n}\n\n\nfunction jqLiteDocumentLoaded(action, win) {\n  win = win || window;\n  if (win.document.readyState === 'complete') {\n    // Force the action to be run async for consistent behaviour\n    // from the action's point of view\n    // i.e. it will definitely not be in a $apply\n    win.setTimeout(action);\n  } else {\n    // No need to unbind this handler as load is only ever called once\n    jqLite(win).on('load', action);\n  }\n}\n\n//////////////////////////////////////////\n// Functions which are declared directly.\n//////////////////////////////////////////\nvar JQLitePrototype = JQLite.prototype = {\n  ready: function(fn) {\n    var fired = false;\n\n    function trigger() {\n      if (fired) return;\n      fired = true;\n      fn();\n    }\n\n    // check if document is already loaded\n    if (document.readyState === 'complete') {\n      setTimeout(trigger);\n    } else {\n      this.on('DOMContentLoaded', trigger); // works for modern browsers and IE9\n      // we can not use jqLite since we are not done loading and jQuery could be loaded later.\n      // jshint -W064\n      JQLite(window).on('load', trigger); // fallback to window.onload for others\n      // jshint +W064\n    }\n  },\n  toString: function() {\n    var value = [];\n    forEach(this, function(e) { value.push('' + e);});\n    return '[' + value.join(', ') + ']';\n  },\n\n  eq: function(index) {\n      return (index >= 0) ? jqLite(this[index]) : jqLite(this[this.length + index]);\n  },\n\n  length: 0,\n  push: push,\n  sort: [].sort,\n  splice: [].splice\n};\n\n//////////////////////////////////////////\n// Functions iterating getter/setters.\n// these functions return self on setter and\n// value on get.\n//////////////////////////////////////////\nvar BOOLEAN_ATTR = {};\nforEach('multiple,selected,checked,disabled,readOnly,required,open'.split(','), function(value) {\n  BOOLEAN_ATTR[lowercase(value)] = value;\n});\nvar BOOLEAN_ELEMENTS = {};\nforEach('input,select,option,textarea,button,form,details'.split(','), function(value) {\n  BOOLEAN_ELEMENTS[value] = true;\n});\nvar ALIASED_ATTR = {\n  'ngMinlength': 'minlength',\n  'ngMaxlength': 'maxlength',\n  'ngMin': 'min',\n  'ngMax': 'max',\n  'ngPattern': 'pattern'\n};\n\nfunction getBooleanAttrName(element, name) {\n  // check dom last since we will most likely fail on name\n  var booleanAttr = BOOLEAN_ATTR[name.toLowerCase()];\n\n  // booleanAttr is here twice to minimize DOM access\n  return booleanAttr && BOOLEAN_ELEMENTS[nodeName_(element)] && booleanAttr;\n}\n\nfunction getAliasedAttrName(element, name) {\n  var nodeName = element.nodeName;\n  return (nodeName === 'INPUT' || nodeName === 'TEXTAREA') && ALIASED_ATTR[name];\n}\n\nforEach({\n  data: jqLiteData,\n  removeData: jqLiteRemoveData\n}, function(fn, name) {\n  JQLite[name] = fn;\n});\n\nforEach({\n  data: jqLiteData,\n  inheritedData: jqLiteInheritedData,\n\n  scope: function(element) {\n    // Can't use jqLiteData here directly so we stay compatible with jQuery!\n    return jqLite.data(element, '$scope') || jqLiteInheritedData(element.parentNode || element, ['$isolateScope', '$scope']);\n  },\n\n  isolateScope: function(element) {\n    // Can't use jqLiteData here directly so we stay compatible with jQuery!\n    return jqLite.data(element, '$isolateScope') || jqLite.data(element, '$isolateScopeNoTemplate');\n  },\n\n  controller: jqLiteController,\n\n  injector: function(element) {\n    return jqLiteInheritedData(element, '$injector');\n  },\n\n  removeAttr: function(element, name) {\n    element.removeAttribute(name);\n  },\n\n  hasClass: jqLiteHasClass,\n\n  css: function(element, name, value) {\n    name = camelCase(name);\n\n    if (isDefined(value)) {\n      element.style[name] = value;\n    } else {\n      return element.style[name];\n    }\n  },\n\n  attr: function(element, name, value) {\n    var lowercasedName = lowercase(name);\n    if (BOOLEAN_ATTR[lowercasedName]) {\n      if (isDefined(value)) {\n        if (!!value) {\n          element[name] = true;\n          element.setAttribute(name, lowercasedName);\n        } else {\n          element[name] = false;\n          element.removeAttribute(lowercasedName);\n        }\n      } else {\n        return (element[name] ||\n                 (element.attributes.getNamedItem(name) || noop).specified)\n               ? lowercasedName\n               : undefined;\n      }\n    } else if (isDefined(value)) {\n      element.setAttribute(name, value);\n    } else if (element.getAttribute) {\n      // the extra argument \"2\" is to get the right thing for a.href in IE, see jQuery code\n      // some elements (e.g. Document) don't have get attribute, so return undefined\n      var ret = element.getAttribute(name, 2);\n      // normalize non-existing attributes to undefined (as jQuery)\n      return ret === null ? undefined : ret;\n    }\n  },\n\n  prop: function(element, name, value) {\n    if (isDefined(value)) {\n      element[name] = value;\n    } else {\n      return element[name];\n    }\n  },\n\n  text: (function() {\n    getText.$dv = '';\n    return getText;\n\n    function getText(element, value) {\n      if (isUndefined(value)) {\n        var nodeType = element.nodeType;\n        return (nodeType === NODE_TYPE_ELEMENT || nodeType === NODE_TYPE_TEXT) ? element.textContent : '';\n      }\n      element.textContent = value;\n    }\n  })(),\n\n  val: function(element, value) {\n    if (isUndefined(value)) {\n      if (element.multiple && nodeName_(element) === 'select') {\n        var result = [];\n        forEach(element.options, function(option) {\n          if (option.selected) {\n            result.push(option.value || option.text);\n          }\n        });\n        return result.length === 0 ? null : result;\n      }\n      return element.value;\n    }\n    element.value = value;\n  },\n\n  html: function(element, value) {\n    if (isUndefined(value)) {\n      return element.innerHTML;\n    }\n    jqLiteDealoc(element, true);\n    element.innerHTML = value;\n  },\n\n  empty: jqLiteEmpty\n}, function(fn, name) {\n  /**\n   * Properties: writes return selection, reads return first value\n   */\n  JQLite.prototype[name] = function(arg1, arg2) {\n    var i, key;\n    var nodeCount = this.length;\n\n    // jqLiteHasClass has only two arguments, but is a getter-only fn, so we need to special-case it\n    // in a way that survives minification.\n    // jqLiteEmpty takes no arguments but is a setter.\n    if (fn !== jqLiteEmpty &&\n        (((fn.length == 2 && (fn !== jqLiteHasClass && fn !== jqLiteController)) ? arg1 : arg2) === undefined)) {\n      if (isObject(arg1)) {\n\n        // we are a write, but the object properties are the key/values\n        for (i = 0; i < nodeCount; i++) {\n          if (fn === jqLiteData) {\n            // data() takes the whole object in jQuery\n            fn(this[i], arg1);\n          } else {\n            for (key in arg1) {\n              fn(this[i], key, arg1[key]);\n            }\n          }\n        }\n        // return self for chaining\n        return this;\n      } else {\n        // we are a read, so read the first child.\n        // TODO: do we still need this?\n        var value = fn.$dv;\n        // Only if we have $dv do we iterate over all, otherwise it is just the first element.\n        var jj = (value === undefined) ? Math.min(nodeCount, 1) : nodeCount;\n        for (var j = 0; j < jj; j++) {\n          var nodeValue = fn(this[j], arg1, arg2);\n          value = value ? value + nodeValue : nodeValue;\n        }\n        return value;\n      }\n    } else {\n      // we are a write, so apply to all children\n      for (i = 0; i < nodeCount; i++) {\n        fn(this[i], arg1, arg2);\n      }\n      // return self for chaining\n      return this;\n    }\n  };\n});\n\nfunction createEventHandler(element, events) {\n  var eventHandler = function(event, type) {\n    // jQuery specific api\n    event.isDefaultPrevented = function() {\n      return event.defaultPrevented;\n    };\n\n    var eventFns = events[type || event.type];\n    var eventFnsLength = eventFns ? eventFns.length : 0;\n\n    if (!eventFnsLength) return;\n\n    if (isUndefined(event.immediatePropagationStopped)) {\n      var originalStopImmediatePropagation = event.stopImmediatePropagation;\n      event.stopImmediatePropagation = function() {\n        event.immediatePropagationStopped = true;\n\n        if (event.stopPropagation) {\n          event.stopPropagation();\n        }\n\n        if (originalStopImmediatePropagation) {\n          originalStopImmediatePropagation.call(event);\n        }\n      };\n    }\n\n    event.isImmediatePropagationStopped = function() {\n      return event.immediatePropagationStopped === true;\n    };\n\n    // Copy event handlers in case event handlers array is modified during execution.\n    if ((eventFnsLength > 1)) {\n      eventFns = shallowCopy(eventFns);\n    }\n\n    for (var i = 0; i < eventFnsLength; i++) {\n      if (!event.isImmediatePropagationStopped()) {\n        eventFns[i].call(element, event);\n      }\n    }\n  };\n\n  // TODO: this is a hack for angularMocks/clearDataCache that makes it possible to deregister all\n  //       events on `element`\n  eventHandler.elem = element;\n  return eventHandler;\n}\n\n//////////////////////////////////////////\n// Functions iterating traversal.\n// These functions chain results into a single\n// selector.\n//////////////////////////////////////////\nforEach({\n  removeData: jqLiteRemoveData,\n\n  on: function jqLiteOn(element, type, fn, unsupported) {\n    if (isDefined(unsupported)) throw jqLiteMinErr('onargs', 'jqLite#on() does not support the `selector` or `eventData` parameters');\n\n    // Do not add event handlers to non-elements because they will not be cleaned up.\n    if (!jqLiteAcceptsData(element)) {\n      return;\n    }\n\n    var expandoStore = jqLiteExpandoStore(element, true);\n    var events = expandoStore.events;\n    var handle = expandoStore.handle;\n\n    if (!handle) {\n      handle = expandoStore.handle = createEventHandler(element, events);\n    }\n\n    // http://jsperf.com/string-indexof-vs-split\n    var types = type.indexOf(' ') >= 0 ? type.split(' ') : [type];\n    var i = types.length;\n\n    while (i--) {\n      type = types[i];\n      var eventFns = events[type];\n\n      if (!eventFns) {\n        events[type] = [];\n\n        if (type === 'mouseenter' || type === 'mouseleave') {\n          // Refer to jQuery's implementation of mouseenter & mouseleave\n          // Read about mouseenter and mouseleave:\n          // http://www.quirksmode.org/js/events_mouse.html#link8\n\n          jqLiteOn(element, MOUSE_EVENT_MAP[type], function(event) {\n            var target = this, related = event.relatedTarget;\n            // For mousenter/leave call the handler if related is outside the target.\n            // NB: No relatedTarget if the mouse left/entered the browser window\n            if (!related || (related !== target && !target.contains(related))) {\n              handle(event, type);\n            }\n          });\n\n        } else {\n          if (type !== '$destroy') {\n            addEventListenerFn(element, type, handle);\n          }\n        }\n        eventFns = events[type];\n      }\n      eventFns.push(fn);\n    }\n  },\n\n  off: jqLiteOff,\n\n  one: function(element, type, fn) {\n    element = jqLite(element);\n\n    //add the listener twice so that when it is called\n    //you can remove the original function and still be\n    //able to call element.off(ev, fn) normally\n    element.on(type, function onFn() {\n      element.off(type, fn);\n      element.off(type, onFn);\n    });\n    element.on(type, fn);\n  },\n\n  replaceWith: function(element, replaceNode) {\n    var index, parent = element.parentNode;\n    jqLiteDealoc(element);\n    forEach(new JQLite(replaceNode), function(node) {\n      if (index) {\n        parent.insertBefore(node, index.nextSibling);\n      } else {\n        parent.replaceChild(node, element);\n      }\n      index = node;\n    });\n  },\n\n  children: function(element) {\n    var children = [];\n    forEach(element.childNodes, function(element) {\n      if (element.nodeType === NODE_TYPE_ELEMENT)\n        children.push(element);\n    });\n    return children;\n  },\n\n  contents: function(element) {\n    return element.contentDocument || element.childNodes || [];\n  },\n\n  append: function(element, node) {\n    var nodeType = element.nodeType;\n    if (nodeType !== NODE_TYPE_ELEMENT && nodeType !== NODE_TYPE_DOCUMENT_FRAGMENT) return;\n\n    node = new JQLite(node);\n\n    for (var i = 0, ii = node.length; i < ii; i++) {\n      var child = node[i];\n      element.appendChild(child);\n    }\n  },\n\n  prepend: function(element, node) {\n    if (element.nodeType === NODE_TYPE_ELEMENT) {\n      var index = element.firstChild;\n      forEach(new JQLite(node), function(child) {\n        element.insertBefore(child, index);\n      });\n    }\n  },\n\n  wrap: function(element, wrapNode) {\n    wrapNode = jqLite(wrapNode).eq(0).clone()[0];\n    var parent = element.parentNode;\n    if (parent) {\n      parent.replaceChild(wrapNode, element);\n    }\n    wrapNode.appendChild(element);\n  },\n\n  remove: jqLiteRemove,\n\n  detach: function(element) {\n    jqLiteRemove(element, true);\n  },\n\n  after: function(element, newElement) {\n    var index = element, parent = element.parentNode;\n    newElement = new JQLite(newElement);\n\n    for (var i = 0, ii = newElement.length; i < ii; i++) {\n      var node = newElement[i];\n      parent.insertBefore(node, index.nextSibling);\n      index = node;\n    }\n  },\n\n  addClass: jqLiteAddClass,\n  removeClass: jqLiteRemoveClass,\n\n  toggleClass: function(element, selector, condition) {\n    if (selector) {\n      forEach(selector.split(' '), function(className) {\n        var classCondition = condition;\n        if (isUndefined(classCondition)) {\n          classCondition = !jqLiteHasClass(element, className);\n        }\n        (classCondition ? jqLiteAddClass : jqLiteRemoveClass)(element, className);\n      });\n    }\n  },\n\n  parent: function(element) {\n    var parent = element.parentNode;\n    return parent && parent.nodeType !== NODE_TYPE_DOCUMENT_FRAGMENT ? parent : null;\n  },\n\n  next: function(element) {\n    return element.nextElementSibling;\n  },\n\n  find: function(element, selector) {\n    if (element.getElementsByTagName) {\n      return element.getElementsByTagName(selector);\n    } else {\n      return [];\n    }\n  },\n\n  clone: jqLiteClone,\n\n  triggerHandler: function(element, event, extraParameters) {\n\n    var dummyEvent, eventFnsCopy, handlerArgs;\n    var eventName = event.type || event;\n    var expandoStore = jqLiteExpandoStore(element);\n    var events = expandoStore && expandoStore.events;\n    var eventFns = events && events[eventName];\n\n    if (eventFns) {\n      // Create a dummy event to pass to the handlers\n      dummyEvent = {\n        preventDefault: function() { this.defaultPrevented = true; },\n        isDefaultPrevented: function() { return this.defaultPrevented === true; },\n        stopImmediatePropagation: function() { this.immediatePropagationStopped = true; },\n        isImmediatePropagationStopped: function() { return this.immediatePropagationStopped === true; },\n        stopPropagation: noop,\n        type: eventName,\n        target: element\n      };\n\n      // If a custom event was provided then extend our dummy event with it\n      if (event.type) {\n        dummyEvent = extend(dummyEvent, event);\n      }\n\n      // Copy event handlers in case event handlers array is modified during execution.\n      eventFnsCopy = shallowCopy(eventFns);\n      handlerArgs = extraParameters ? [dummyEvent].concat(extraParameters) : [dummyEvent];\n\n      forEach(eventFnsCopy, function(fn) {\n        if (!dummyEvent.isImmediatePropagationStopped()) {\n          fn.apply(element, handlerArgs);\n        }\n      });\n    }\n  }\n}, function(fn, name) {\n  /**\n   * chaining functions\n   */\n  JQLite.prototype[name] = function(arg1, arg2, arg3) {\n    var value;\n\n    for (var i = 0, ii = this.length; i < ii; i++) {\n      if (isUndefined(value)) {\n        value = fn(this[i], arg1, arg2, arg3);\n        if (isDefined(value)) {\n          // any function which returns a value needs to be wrapped\n          value = jqLite(value);\n        }\n      } else {\n        jqLiteAddNodes(value, fn(this[i], arg1, arg2, arg3));\n      }\n    }\n    return isDefined(value) ? value : this;\n  };\n\n  // bind legacy bind/unbind to on/off\n  JQLite.prototype.bind = JQLite.prototype.on;\n  JQLite.prototype.unbind = JQLite.prototype.off;\n});\n\n\n// Provider for private $$jqLite service\nfunction $$jqLiteProvider() {\n  this.$get = function $$jqLite() {\n    return extend(JQLite, {\n      hasClass: function(node, classes) {\n        if (node.attr) node = node[0];\n        return jqLiteHasClass(node, classes);\n      },\n      addClass: function(node, classes) {\n        if (node.attr) node = node[0];\n        return jqLiteAddClass(node, classes);\n      },\n      removeClass: function(node, classes) {\n        if (node.attr) node = node[0];\n        return jqLiteRemoveClass(node, classes);\n      }\n    });\n  };\n}\n\n/**\n * Computes a hash of an 'obj'.\n * Hash of a:\n *  string is string\n *  number is number as string\n *  object is either result of calling $$hashKey function on the object or uniquely generated id,\n *         that is also assigned to the $$hashKey property of the object.\n *\n * @param obj\n * @returns {string} hash string such that the same input will have the same hash string.\n *         The resulting string key is in 'type:hashKey' format.\n */\nfunction hashKey(obj, nextUidFn) {\n  var key = obj && obj.$$hashKey;\n\n  if (key) {\n    if (typeof key === 'function') {\n      key = obj.$$hashKey();\n    }\n    return key;\n  }\n\n  var objType = typeof obj;\n  if (objType == 'function' || (objType == 'object' && obj !== null)) {\n    key = obj.$$hashKey = objType + ':' + (nextUidFn || nextUid)();\n  } else {\n    key = objType + ':' + obj;\n  }\n\n  return key;\n}\n\n/**\n * HashMap which can use objects as keys\n */\nfunction HashMap(array, isolatedUid) {\n  if (isolatedUid) {\n    var uid = 0;\n    this.nextUid = function() {\n      return ++uid;\n    };\n  }\n  forEach(array, this.put, this);\n}\nHashMap.prototype = {\n  /**\n   * Store key value pair\n   * @param key key to store can be any type\n   * @param value value to store can be any type\n   */\n  put: function(key, value) {\n    this[hashKey(key, this.nextUid)] = value;\n  },\n\n  /**\n   * @param key\n   * @returns {Object} the value for the key\n   */\n  get: function(key) {\n    return this[hashKey(key, this.nextUid)];\n  },\n\n  /**\n   * Remove the key/value pair\n   * @param key\n   */\n  remove: function(key) {\n    var value = this[key = hashKey(key, this.nextUid)];\n    delete this[key];\n    return value;\n  }\n};\n\n/**\n * @ngdoc function\n * @module ng\n * @name angular.injector\n * @kind function\n *\n * @description\n * Creates an injector object that can be used for retrieving services as well as for\n * dependency injection (see {@link guide/di dependency injection}).\n *\n * @param {Array.<string|Function>} modules A list of module functions or their aliases. See\n *     {@link angular.module}. The `ng` module must be explicitly added.\n * @param {boolean=} [strictDi=false] Whether the injector should be in strict mode, which\n *     disallows argument name annotation inference.\n * @returns {injector} Injector object. See {@link auto.$injector $injector}.\n *\n * @example\n * Typical usage\n * ```js\n *   // create an injector\n *   var $injector = angular.injector(['ng']);\n *\n *   // use the injector to kick off your application\n *   // use the type inference to auto inject arguments, or use implicit injection\n *   $injector.invoke(function($rootScope, $compile, $document) {\n *     $compile($document)($rootScope);\n *     $rootScope.$digest();\n *   });\n * ```\n *\n * Sometimes you want to get access to the injector of a currently running Angular app\n * from outside Angular. Perhaps, you want to inject and compile some markup after the\n * application has been bootstrapped. You can do this using the extra `injector()` added\n * to JQuery/jqLite elements. See {@link angular.element}.\n *\n * *This is fairly rare but could be the case if a third party library is injecting the\n * markup.*\n *\n * In the following example a new block of HTML containing a `ng-controller`\n * directive is added to the end of the document body by JQuery. We then compile and link\n * it into the current AngularJS scope.\n *\n * ```js\n * var $div = $('<div ng-controller=\"MyCtrl\">{{content.label}}</div>');\n * $(document.body).append($div);\n *\n * angular.element(document).injector().invoke(function($compile) {\n *   var scope = angular.element($div).scope();\n *   $compile($div)(scope);\n * });\n * ```\n */\n\n\n/**\n * @ngdoc module\n * @name auto\n * @description\n *\n * Implicit module which gets automatically added to each {@link auto.$injector $injector}.\n */\n\nvar FN_ARGS = /^function\\s*[^\\(]*\\(\\s*([^\\)]*)\\)/m;\nvar FN_ARG_SPLIT = /,/;\nvar FN_ARG = /^\\s*(_?)(\\S+?)\\1\\s*$/;\nvar STRIP_COMMENTS = /((\\/\\/.*$)|(\\/\\*[\\s\\S]*?\\*\\/))/mg;\nvar $injectorMinErr = minErr('$injector');\n\nfunction anonFn(fn) {\n  // For anonymous functions, showing at the very least the function signature can help in\n  // debugging.\n  var fnText = fn.toString().replace(STRIP_COMMENTS, ''),\n      args = fnText.match(FN_ARGS);\n  if (args) {\n    return 'function(' + (args[1] || '').replace(/[\\s\\r\\n]+/, ' ') + ')';\n  }\n  return 'fn';\n}\n\nfunction annotate(fn, strictDi, name) {\n  var $inject,\n      fnText,\n      argDecl,\n      last;\n\n  if (typeof fn === 'function') {\n    if (!($inject = fn.$inject)) {\n      $inject = [];\n      if (fn.length) {\n        if (strictDi) {\n          if (!isString(name) || !name) {\n            name = fn.name || anonFn(fn);\n          }\n          throw $injectorMinErr('strictdi',\n            '{0} is not using explicit annotation and cannot be invoked in strict mode', name);\n        }\n        fnText = fn.toString().replace(STRIP_COMMENTS, '');\n        argDecl = fnText.match(FN_ARGS);\n        forEach(argDecl[1].split(FN_ARG_SPLIT), function(arg) {\n          arg.replace(FN_ARG, function(all, underscore, name) {\n            $inject.push(name);\n          });\n        });\n      }\n      fn.$inject = $inject;\n    }\n  } else if (isArray(fn)) {\n    last = fn.length - 1;\n    assertArgFn(fn[last], 'fn');\n    $inject = fn.slice(0, last);\n  } else {\n    assertArgFn(fn, 'fn', true);\n  }\n  return $inject;\n}\n\n///////////////////////////////////////\n\n/**\n * @ngdoc service\n * @name $injector\n *\n * @description\n *\n * `$injector` is used to retrieve object instances as defined by\n * {@link auto.$provide provider}, instantiate types, invoke methods,\n * and load modules.\n *\n * The following always holds true:\n *\n * ```js\n *   var $injector = angular.injector();\n *   expect($injector.get('$injector')).toBe($injector);\n *   expect($injector.invoke(function($injector) {\n *     return $injector;\n *   })).toBe($injector);\n * ```\n *\n * # Injection Function Annotation\n *\n * JavaScript does not have annotations, and annotations are needed for dependency injection. The\n * following are all valid ways of annotating function with injection arguments and are equivalent.\n *\n * ```js\n *   // inferred (only works if code not minified/obfuscated)\n *   $injector.invoke(function(serviceA){});\n *\n *   // annotated\n *   function explicit(serviceA) {};\n *   explicit.$inject = ['serviceA'];\n *   $injector.invoke(explicit);\n *\n *   // inline\n *   $injector.invoke(['serviceA', function(serviceA){}]);\n * ```\n *\n * ## Inference\n *\n * In JavaScript calling `toString()` on a function returns the function definition. The definition\n * can then be parsed and the function arguments can be extracted. This method of discovering\n * annotations is disallowed when the injector is in strict mode.\n * *NOTE:* This does not work with minification, and obfuscation tools since these tools change the\n * argument names.\n *\n * ## `$inject` Annotation\n * By adding an `$inject` property onto a function the injection parameters can be specified.\n *\n * ## Inline\n * As an array of injection names, where the last item in the array is the function to call.\n */\n\n/**\n * @ngdoc method\n * @name $injector#get\n *\n * @description\n * Return an instance of the service.\n *\n * @param {string} name The name of the instance to retrieve.\n * @param {string} caller An optional string to provide the origin of the function call for error messages.\n * @return {*} The instance.\n */\n\n/**\n * @ngdoc method\n * @name $injector#invoke\n *\n * @description\n * Invoke the method and supply the method arguments from the `$injector`.\n *\n * @param {!Function} fn The function to invoke. Function parameters are injected according to the\n *   {@link guide/di $inject Annotation} rules.\n * @param {Object=} self The `this` for the invoked method.\n * @param {Object=} locals Optional object. If preset then any argument names are read from this\n *                         object first, before the `$injector` is consulted.\n * @returns {*} the value returned by the invoked `fn` function.\n */\n\n/**\n * @ngdoc method\n * @name $injector#has\n *\n * @description\n * Allows the user to query if the particular service exists.\n *\n * @param {string} name Name of the service to query.\n * @returns {boolean} `true` if injector has given service.\n */\n\n/**\n * @ngdoc method\n * @name $injector#instantiate\n * @description\n * Create a new instance of JS type. The method takes a constructor function, invokes the new\n * operator, and supplies all of the arguments to the constructor function as specified by the\n * constructor annotation.\n *\n * @param {Function} Type Annotated constructor function.\n * @param {Object=} locals Optional object. If preset then any argument names are read from this\n * object first, before the `$injector` is consulted.\n * @returns {Object} new instance of `Type`.\n */\n\n/**\n * @ngdoc method\n * @name $injector#annotate\n *\n * @description\n * Returns an array of service names which the function is requesting for injection. This API is\n * used by the injector to determine which services need to be injected into the function when the\n * function is invoked. There are three ways in which the function can be annotated with the needed\n * dependencies.\n *\n * # Argument names\n *\n * The simplest form is to extract the dependencies from the arguments of the function. This is done\n * by converting the function into a string using `toString()` method and extracting the argument\n * names.\n * ```js\n *   // Given\n *   function MyController($scope, $route) {\n *     // ...\n *   }\n *\n *   // Then\n *   expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);\n * ```\n *\n * You can disallow this method by using strict injection mode.\n *\n * This method does not work with code minification / obfuscation. For this reason the following\n * annotation strategies are supported.\n *\n * # The `$inject` property\n *\n * If a function has an `$inject` property and its value is an array of strings, then the strings\n * represent names of services to be injected into the function.\n * ```js\n *   // Given\n *   var MyController = function(obfuscatedScope, obfuscatedRoute) {\n *     // ...\n *   }\n *   // Define function dependencies\n *   MyController['$inject'] = ['$scope', '$route'];\n *\n *   // Then\n *   expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);\n * ```\n *\n * # The array notation\n *\n * It is often desirable to inline Injected functions and that's when setting the `$inject` property\n * is very inconvenient. In these situations using the array notation to specify the dependencies in\n * a way that survives minification is a better choice:\n *\n * ```js\n *   // We wish to write this (not minification / obfuscation safe)\n *   injector.invoke(function($compile, $rootScope) {\n *     // ...\n *   });\n *\n *   // We are forced to write break inlining\n *   var tmpFn = function(obfuscatedCompile, obfuscatedRootScope) {\n *     // ...\n *   };\n *   tmpFn.$inject = ['$compile', '$rootScope'];\n *   injector.invoke(tmpFn);\n *\n *   // To better support inline function the inline annotation is supported\n *   injector.invoke(['$compile', '$rootScope', function(obfCompile, obfRootScope) {\n *     // ...\n *   }]);\n *\n *   // Therefore\n *   expect(injector.annotate(\n *      ['$compile', '$rootScope', function(obfus_$compile, obfus_$rootScope) {}])\n *    ).toEqual(['$compile', '$rootScope']);\n * ```\n *\n * @param {Function|Array.<string|Function>} fn Function for which dependent service names need to\n * be retrieved as described above.\n *\n * @param {boolean=} [strictDi=false] Disallow argument name annotation inference.\n *\n * @returns {Array.<string>} The names of the services which the function requires.\n */\n\n\n\n\n/**\n * @ngdoc service\n * @name $provide\n *\n * @description\n *\n * The {@link auto.$provide $provide} service has a number of methods for registering components\n * with the {@link auto.$injector $injector}. Many of these functions are also exposed on\n * {@link angular.Module}.\n *\n * An Angular **service** is a singleton object created by a **service factory**.  These **service\n * factories** are functions which, in turn, are created by a **service provider**.\n * The **service providers** are constructor functions. When instantiated they must contain a\n * property called `$get`, which holds the **service factory** function.\n *\n * When you request a service, the {@link auto.$injector $injector} is responsible for finding the\n * correct **service provider**, instantiating it and then calling its `$get` **service factory**\n * function to get the instance of the **service**.\n *\n * Often services have no configuration options and there is no need to add methods to the service\n * provider.  The provider will be no more than a constructor function with a `$get` property. For\n * these cases the {@link auto.$provide $provide} service has additional helper methods to register\n * services without specifying a provider.\n *\n * * {@link auto.$provide#provider provider(provider)} - registers a **service provider** with the\n *     {@link auto.$injector $injector}\n * * {@link auto.$provide#constant constant(obj)} - registers a value/object that can be accessed by\n *     providers and services.\n * * {@link auto.$provide#value value(obj)} - registers a value/object that can only be accessed by\n *     services, not providers.\n * * {@link auto.$provide#factory factory(fn)} - registers a service **factory function**, `fn`,\n *     that will be wrapped in a **service provider** object, whose `$get` property will contain the\n *     given factory function.\n * * {@link auto.$provide#service service(class)} - registers a **constructor function**, `class`\n *     that will be wrapped in a **service provider** object, whose `$get` property will instantiate\n *      a new object using the given constructor function.\n *\n * See the individual methods for more information and examples.\n */\n\n/**\n * @ngdoc method\n * @name $provide#provider\n * @description\n *\n * Register a **provider function** with the {@link auto.$injector $injector}. Provider functions\n * are constructor functions, whose instances are responsible for \"providing\" a factory for a\n * service.\n *\n * Service provider names start with the name of the service they provide followed by `Provider`.\n * For example, the {@link ng.$log $log} service has a provider called\n * {@link ng.$logProvider $logProvider}.\n *\n * Service provider objects can have additional methods which allow configuration of the provider\n * and its service. Importantly, you can configure what kind of service is created by the `$get`\n * method, or how that service will act. For example, the {@link ng.$logProvider $logProvider} has a\n * method {@link ng.$logProvider#debugEnabled debugEnabled}\n * which lets you specify whether the {@link ng.$log $log} service will log debug messages to the\n * console or not.\n *\n * @param {string} name The name of the instance. NOTE: the provider will be available under `name +\n                        'Provider'` key.\n * @param {(Object|function())} provider If the provider is:\n *\n *   - `Object`: then it should have a `$get` method. The `$get` method will be invoked using\n *     {@link auto.$injector#invoke $injector.invoke()} when an instance needs to be created.\n *   - `Constructor`: a new instance of the provider will be created using\n *     {@link auto.$injector#instantiate $injector.instantiate()}, then treated as `object`.\n *\n * @returns {Object} registered provider instance\n\n * @example\n *\n * The following example shows how to create a simple event tracking service and register it using\n * {@link auto.$provide#provider $provide.provider()}.\n *\n * ```js\n *  // Define the eventTracker provider\n *  function EventTrackerProvider() {\n *    var trackingUrl = '/track';\n *\n *    // A provider method for configuring where the tracked events should been saved\n *    this.setTrackingUrl = function(url) {\n *      trackingUrl = url;\n *    };\n *\n *    // The service factory function\n *    this.$get = ['$http', function($http) {\n *      var trackedEvents = {};\n *      return {\n *        // Call this to track an event\n *        event: function(event) {\n *          var count = trackedEvents[event] || 0;\n *          count += 1;\n *          trackedEvents[event] = count;\n *          return count;\n *        },\n *        // Call this to save the tracked events to the trackingUrl\n *        save: function() {\n *          $http.post(trackingUrl, trackedEvents);\n *        }\n *      };\n *    }];\n *  }\n *\n *  describe('eventTracker', function() {\n *    var postSpy;\n *\n *    beforeEach(module(function($provide) {\n *      // Register the eventTracker provider\n *      $provide.provider('eventTracker', EventTrackerProvider);\n *    }));\n *\n *    beforeEach(module(function(eventTrackerProvider) {\n *      // Configure eventTracker provider\n *      eventTrackerProvider.setTrackingUrl('/custom-track');\n *    }));\n *\n *    it('tracks events', inject(function(eventTracker) {\n *      expect(eventTracker.event('login')).toEqual(1);\n *      expect(eventTracker.event('login')).toEqual(2);\n *    }));\n *\n *    it('saves to the tracking url', inject(function(eventTracker, $http) {\n *      postSpy = spyOn($http, 'post');\n *      eventTracker.event('login');\n *      eventTracker.save();\n *      expect(postSpy).toHaveBeenCalled();\n *      expect(postSpy.mostRecentCall.args[0]).not.toEqual('/track');\n *      expect(postSpy.mostRecentCall.args[0]).toEqual('/custom-track');\n *      expect(postSpy.mostRecentCall.args[1]).toEqual({ 'login': 1 });\n *    }));\n *  });\n * ```\n */\n\n/**\n * @ngdoc method\n * @name $provide#factory\n * @description\n *\n * Register a **service factory**, which will be called to return the service instance.\n * This is short for registering a service where its provider consists of only a `$get` property,\n * which is the given service factory function.\n * You should use {@link auto.$provide#factory $provide.factory(getFn)} if you do not need to\n * configure your service in a provider.\n *\n * @param {string} name The name of the instance.\n * @param {function()} $getFn The $getFn for the instance creation. Internally this is a short hand\n *                            for `$provide.provider(name, {$get: $getFn})`.\n * @returns {Object} registered provider instance\n *\n * @example\n * Here is an example of registering a service\n * ```js\n *   $provide.factory('ping', ['$http', function($http) {\n *     return function ping() {\n *       return $http.send('/ping');\n *     };\n *   }]);\n * ```\n * You would then inject and use this service like this:\n * ```js\n *   someModule.controller('Ctrl', ['ping', function(ping) {\n *     ping();\n *   }]);\n * ```\n */\n\n\n/**\n * @ngdoc method\n * @name $provide#service\n * @description\n *\n * Register a **service constructor**, which will be invoked with `new` to create the service\n * instance.\n * This is short for registering a service where its provider's `$get` property is the service\n * constructor function that will be used to instantiate the service instance.\n *\n * You should use {@link auto.$provide#service $provide.service(class)} if you define your service\n * as a type/class.\n *\n * @param {string} name The name of the instance.\n * @param {Function} constructor A class (constructor function) that will be instantiated.\n * @returns {Object} registered provider instance\n *\n * @example\n * Here is an example of registering a service using\n * {@link auto.$provide#service $provide.service(class)}.\n * ```js\n *   var Ping = function($http) {\n *     this.$http = $http;\n *   };\n *\n *   Ping.$inject = ['$http'];\n *\n *   Ping.prototype.send = function() {\n *     return this.$http.get('/ping');\n *   };\n *   $provide.service('ping', Ping);\n * ```\n * You would then inject and use this service like this:\n * ```js\n *   someModule.controller('Ctrl', ['ping', function(ping) {\n *     ping.send();\n *   }]);\n * ```\n */\n\n\n/**\n * @ngdoc method\n * @name $provide#value\n * @description\n *\n * Register a **value service** with the {@link auto.$injector $injector}, such as a string, a\n * number, an array, an object or a function.  This is short for registering a service where its\n * provider's `$get` property is a factory function that takes no arguments and returns the **value\n * service**.\n *\n * Value services are similar to constant services, except that they cannot be injected into a\n * module configuration function (see {@link angular.Module#config}) but they can be overridden by\n * an Angular\n * {@link auto.$provide#decorator decorator}.\n *\n * @param {string} name The name of the instance.\n * @param {*} value The value.\n * @returns {Object} registered provider instance\n *\n * @example\n * Here are some examples of creating value services.\n * ```js\n *   $provide.value('ADMIN_USER', 'admin');\n *\n *   $provide.value('RoleLookup', { admin: 0, writer: 1, reader: 2 });\n *\n *   $provide.value('halfOf', function(value) {\n *     return value / 2;\n *   });\n * ```\n */\n\n\n/**\n * @ngdoc method\n * @name $provide#constant\n * @description\n *\n * Register a **constant service**, such as a string, a number, an array, an object or a function,\n * with the {@link auto.$injector $injector}. Unlike {@link auto.$provide#value value} it can be\n * injected into a module configuration function (see {@link angular.Module#config}) and it cannot\n * be overridden by an Angular {@link auto.$provide#decorator decorator}.\n *\n * @param {string} name The name of the constant.\n * @param {*} value The constant value.\n * @returns {Object} registered instance\n *\n * @example\n * Here a some examples of creating constants:\n * ```js\n *   $provide.constant('SHARD_HEIGHT', 306);\n *\n *   $provide.constant('MY_COLOURS', ['red', 'blue', 'grey']);\n *\n *   $provide.constant('double', function(value) {\n *     return value * 2;\n *   });\n * ```\n */\n\n\n/**\n * @ngdoc method\n * @name $provide#decorator\n * @description\n *\n * Register a **service decorator** with the {@link auto.$injector $injector}. A service decorator\n * intercepts the creation of a service, allowing it to override or modify the behaviour of the\n * service. The object returned by the decorator may be the original service, or a new service\n * object which replaces or wraps and delegates to the original service.\n *\n * @param {string} name The name of the service to decorate.\n * @param {function()} decorator This function will be invoked when the service needs to be\n *    instantiated and should return the decorated service instance. The function is called using\n *    the {@link auto.$injector#invoke injector.invoke} method and is therefore fully injectable.\n *    Local injection arguments:\n *\n *    * `$delegate` - The original service instance, which can be monkey patched, configured,\n *      decorated or delegated to.\n *\n * @example\n * Here we decorate the {@link ng.$log $log} service to convert warnings to errors by intercepting\n * calls to {@link ng.$log#error $log.warn()}.\n * ```js\n *   $provide.decorator('$log', ['$delegate', function($delegate) {\n *     $delegate.warn = $delegate.error;\n *     return $delegate;\n *   }]);\n * ```\n */\n\n\nfunction createInjector(modulesToLoad, strictDi) {\n  strictDi = (strictDi === true);\n  var INSTANTIATING = {},\n      providerSuffix = 'Provider',\n      path = [],\n      loadedModules = new HashMap([], true),\n      providerCache = {\n        $provide: {\n            provider: supportObject(provider),\n            factory: supportObject(factory),\n            service: supportObject(service),\n            value: supportObject(value),\n            constant: supportObject(constant),\n            decorator: decorator\n          }\n      },\n      providerInjector = (providerCache.$injector =\n          createInternalInjector(providerCache, function(serviceName, caller) {\n            if (angular.isString(caller)) {\n              path.push(caller);\n            }\n            throw $injectorMinErr('unpr', \"Unknown provider: {0}\", path.join(' <- '));\n          })),\n      instanceCache = {},\n      instanceInjector = (instanceCache.$injector =\n          createInternalInjector(instanceCache, function(serviceName, caller) {\n            var provider = providerInjector.get(serviceName + providerSuffix, caller);\n            return instanceInjector.invoke(provider.$get, provider, undefined, serviceName);\n          }));\n\n\n  forEach(loadModules(modulesToLoad), function(fn) { instanceInjector.invoke(fn || noop); });\n\n  return instanceInjector;\n\n  ////////////////////////////////////\n  // $provider\n  ////////////////////////////////////\n\n  function supportObject(delegate) {\n    return function(key, value) {\n      if (isObject(key)) {\n        forEach(key, reverseParams(delegate));\n      } else {\n        return delegate(key, value);\n      }\n    };\n  }\n\n  function provider(name, provider_) {\n    assertNotHasOwnProperty(name, 'service');\n    if (isFunction(provider_) || isArray(provider_)) {\n      provider_ = providerInjector.instantiate(provider_);\n    }\n    if (!provider_.$get) {\n      throw $injectorMinErr('pget', \"Provider '{0}' must define $get factory method.\", name);\n    }\n    return providerCache[name + providerSuffix] = provider_;\n  }\n\n  function enforceReturnValue(name, factory) {\n    return function enforcedReturnValue() {\n      var result = instanceInjector.invoke(factory, this);\n      if (isUndefined(result)) {\n        throw $injectorMinErr('undef', \"Provider '{0}' must return a value from $get factory method.\", name);\n      }\n      return result;\n    };\n  }\n\n  function factory(name, factoryFn, enforce) {\n    return provider(name, {\n      $get: enforce !== false ? enforceReturnValue(name, factoryFn) : factoryFn\n    });\n  }\n\n  function service(name, constructor) {\n    return factory(name, ['$injector', function($injector) {\n      return $injector.instantiate(constructor);\n    }]);\n  }\n\n  function value(name, val) { return factory(name, valueFn(val), false); }\n\n  function constant(name, value) {\n    assertNotHasOwnProperty(name, 'constant');\n    providerCache[name] = value;\n    instanceCache[name] = value;\n  }\n\n  function decorator(serviceName, decorFn) {\n    var origProvider = providerInjector.get(serviceName + providerSuffix),\n        orig$get = origProvider.$get;\n\n    origProvider.$get = function() {\n      var origInstance = instanceInjector.invoke(orig$get, origProvider);\n      return instanceInjector.invoke(decorFn, null, {$delegate: origInstance});\n    };\n  }\n\n  ////////////////////////////////////\n  // Module Loading\n  ////////////////////////////////////\n  function loadModules(modulesToLoad) {\n    var runBlocks = [], moduleFn;\n    forEach(modulesToLoad, function(module) {\n      if (loadedModules.get(module)) return;\n      loadedModules.put(module, true);\n\n      function runInvokeQueue(queue) {\n        var i, ii;\n        for (i = 0, ii = queue.length; i < ii; i++) {\n          var invokeArgs = queue[i],\n              provider = providerInjector.get(invokeArgs[0]);\n\n          provider[invokeArgs[1]].apply(provider, invokeArgs[2]);\n        }\n      }\n\n      try {\n        if (isString(module)) {\n          moduleFn = angularModule(module);\n          runBlocks = runBlocks.concat(loadModules(moduleFn.requires)).concat(moduleFn._runBlocks);\n          runInvokeQueue(moduleFn._invokeQueue);\n          runInvokeQueue(moduleFn._configBlocks);\n        } else if (isFunction(module)) {\n            runBlocks.push(providerInjector.invoke(module));\n        } else if (isArray(module)) {\n            runBlocks.push(providerInjector.invoke(module));\n        } else {\n          assertArgFn(module, 'module');\n        }\n      } catch (e) {\n        if (isArray(module)) {\n          module = module[module.length - 1];\n        }\n        if (e.message && e.stack && e.stack.indexOf(e.message) == -1) {\n          // Safari & FF's stack traces don't contain error.message content\n          // unlike those of Chrome and IE\n          // So if stack doesn't contain message, we create a new string that contains both.\n          // Since error.stack is read-only in Safari, I'm overriding e and not e.stack here.\n          /* jshint -W022 */\n          e = e.message + '\\n' + e.stack;\n        }\n        throw $injectorMinErr('modulerr', \"Failed to instantiate module {0} due to:\\n{1}\",\n                  module, e.stack || e.message || e);\n      }\n    });\n    return runBlocks;\n  }\n\n  ////////////////////////////////////\n  // internal Injector\n  ////////////////////////////////////\n\n  function createInternalInjector(cache, factory) {\n\n    function getService(serviceName, caller) {\n      if (cache.hasOwnProperty(serviceName)) {\n        if (cache[serviceName] === INSTANTIATING) {\n          throw $injectorMinErr('cdep', 'Circular dependency found: {0}',\n                    serviceName + ' <- ' + path.join(' <- '));\n        }\n        return cache[serviceName];\n      } else {\n        try {\n          path.unshift(serviceName);\n          cache[serviceName] = INSTANTIATING;\n          return cache[serviceName] = factory(serviceName, caller);\n        } catch (err) {\n          if (cache[serviceName] === INSTANTIATING) {\n            delete cache[serviceName];\n          }\n          throw err;\n        } finally {\n          path.shift();\n        }\n      }\n    }\n\n    function invoke(fn, self, locals, serviceName) {\n      if (typeof locals === 'string') {\n        serviceName = locals;\n        locals = null;\n      }\n\n      var args = [],\n          $inject = createInjector.$$annotate(fn, strictDi, serviceName),\n          length, i,\n          key;\n\n      for (i = 0, length = $inject.length; i < length; i++) {\n        key = $inject[i];\n        if (typeof key !== 'string') {\n          throw $injectorMinErr('itkn',\n                  'Incorrect injection token! Expected service name as string, got {0}', key);\n        }\n        args.push(\n          locals && locals.hasOwnProperty(key)\n          ? locals[key]\n          : getService(key, serviceName)\n        );\n      }\n      if (isArray(fn)) {\n        fn = fn[length];\n      }\n\n      // http://jsperf.com/angularjs-invoke-apply-vs-switch\n      // #5388\n      return fn.apply(self, args);\n    }\n\n    function instantiate(Type, locals, serviceName) {\n      // Check if Type is annotated and use just the given function at n-1 as parameter\n      // e.g. someModule.factory('greeter', ['$window', function(renamed$window) {}]);\n      // Object creation: http://jsperf.com/create-constructor/2\n      var instance = Object.create((isArray(Type) ? Type[Type.length - 1] : Type).prototype || null);\n      var returnedValue = invoke(Type, instance, locals, serviceName);\n\n      return isObject(returnedValue) || isFunction(returnedValue) ? returnedValue : instance;\n    }\n\n    return {\n      invoke: invoke,\n      instantiate: instantiate,\n      get: getService,\n      annotate: createInjector.$$annotate,\n      has: function(name) {\n        return providerCache.hasOwnProperty(name + providerSuffix) || cache.hasOwnProperty(name);\n      }\n    };\n  }\n}\n\ncreateInjector.$$annotate = annotate;\n\n/**\n * @ngdoc provider\n * @name $anchorScrollProvider\n *\n * @description\n * Use `$anchorScrollProvider` to disable automatic scrolling whenever\n * {@link ng.$location#hash $location.hash()} changes.\n */\nfunction $AnchorScrollProvider() {\n\n  var autoScrollingEnabled = true;\n\n  /**\n   * @ngdoc method\n   * @name $anchorScrollProvider#disableAutoScrolling\n   *\n   * @description\n   * By default, {@link ng.$anchorScroll $anchorScroll()} will automatically detect changes to\n   * {@link ng.$location#hash $location.hash()} and scroll to the element matching the new hash.<br />\n   * Use this method to disable automatic scrolling.\n   *\n   * If automatic scrolling is disabled, one must explicitly call\n   * {@link ng.$anchorScroll $anchorScroll()} in order to scroll to the element related to the\n   * current hash.\n   */\n  this.disableAutoScrolling = function() {\n    autoScrollingEnabled = false;\n  };\n\n  /**\n   * @ngdoc service\n   * @name $anchorScroll\n   * @kind function\n   * @requires $window\n   * @requires $location\n   * @requires $rootScope\n   *\n   * @description\n   * When called, it checks the current value of {@link ng.$location#hash $location.hash()} and\n   * scrolls to the related element, according to the rules specified in the\n   * [Html5 spec](http://dev.w3.org/html5/spec/Overview.html#the-indicated-part-of-the-document).\n   *\n   * It also watches the {@link ng.$location#hash $location.hash()} and automatically scrolls to\n   * match any anchor whenever it changes. This can be disabled by calling\n   * {@link ng.$anchorScrollProvider#disableAutoScrolling $anchorScrollProvider.disableAutoScrolling()}.\n   *\n   * Additionally, you can use its {@link ng.$anchorScroll#yOffset yOffset} property to specify a\n   * vertical scroll-offset (either fixed or dynamic).\n   *\n   * @property {(number|function|jqLite)} yOffset\n   * If set, specifies a vertical scroll-offset. This is often useful when there are fixed\n   * positioned elements at the top of the page, such as navbars, headers etc.\n   *\n   * `yOffset` can be specified in various ways:\n   * - **number**: A fixed number of pixels to be used as offset.<br /><br />\n   * - **function**: A getter function called everytime `$anchorScroll()` is executed. Must return\n   *   a number representing the offset (in pixels).<br /><br />\n   * - **jqLite**: A jqLite/jQuery element to be used for specifying the offset. The distance from\n   *   the top of the page to the element's bottom will be used as offset.<br />\n   *   **Note**: The element will be taken into account only as long as its `position` is set to\n   *   `fixed`. This option is useful, when dealing with responsive navbars/headers that adjust\n   *   their height and/or positioning according to the viewport's size.\n   *\n   * <br />\n   * <div class=\"alert alert-warning\">\n   * In order for `yOffset` to work properly, scrolling should take place on the document's root and\n   * not some child element.\n   * </div>\n   *\n   * @example\n     <example module=\"anchorScrollExample\">\n       <file name=\"index.html\">\n         <div id=\"scrollArea\" ng-controller=\"ScrollController\">\n           <a ng-click=\"gotoBottom()\">Go to bottom</a>\n           <a id=\"bottom\"></a> You're at the bottom!\n         </div>\n       </file>\n       <file name=\"script.js\">\n         angular.module('anchorScrollExample', [])\n           .controller('ScrollController', ['$scope', '$location', '$anchorScroll',\n             function ($scope, $location, $anchorScroll) {\n               $scope.gotoBottom = function() {\n                 // set the location.hash to the id of\n                 // the element you wish to scroll to.\n                 $location.hash('bottom');\n\n                 // call $anchorScroll()\n                 $anchorScroll();\n               };\n             }]);\n       </file>\n       <file name=\"style.css\">\n         #scrollArea {\n           height: 280px;\n           overflow: auto;\n         }\n\n         #bottom {\n           display: block;\n           margin-top: 2000px;\n         }\n       </file>\n     </example>\n   *\n   * <hr />\n   * The example below illustrates the use of a vertical scroll-offset (specified as a fixed value).\n   * See {@link ng.$anchorScroll#yOffset $anchorScroll.yOffset} for more details.\n   *\n   * @example\n     <example module=\"anchorScrollOffsetExample\">\n       <file name=\"index.html\">\n         <div class=\"fixed-header\" ng-controller=\"headerCtrl\">\n           <a href=\"\" ng-click=\"gotoAnchor(x)\" ng-repeat=\"x in [1,2,3,4,5]\">\n             Go to anchor {{x}}\n           </a>\n         </div>\n         <div id=\"anchor{{x}}\" class=\"anchor\" ng-repeat=\"x in [1,2,3,4,5]\">\n           Anchor {{x}} of 5\n         </div>\n       </file>\n       <file name=\"script.js\">\n         angular.module('anchorScrollOffsetExample', [])\n           .run(['$anchorScroll', function($anchorScroll) {\n             $anchorScroll.yOffset = 50;   // always scroll by 50 extra pixels\n           }])\n           .controller('headerCtrl', ['$anchorScroll', '$location', '$scope',\n             function ($anchorScroll, $location, $scope) {\n               $scope.gotoAnchor = function(x) {\n                 var newHash = 'anchor' + x;\n                 if ($location.hash() !== newHash) {\n                   // set the $location.hash to `newHash` and\n                   // $anchorScroll will automatically scroll to it\n                   $location.hash('anchor' + x);\n                 } else {\n                   // call $anchorScroll() explicitly,\n                   // since $location.hash hasn't changed\n                   $anchorScroll();\n                 }\n               };\n             }\n           ]);\n       </file>\n       <file name=\"style.css\">\n         body {\n           padding-top: 50px;\n         }\n\n         .anchor {\n           border: 2px dashed DarkOrchid;\n           padding: 10px 10px 200px 10px;\n         }\n\n         .fixed-header {\n           background-color: rgba(0, 0, 0, 0.2);\n           height: 50px;\n           position: fixed;\n           top: 0; left: 0; right: 0;\n         }\n\n         .fixed-header > a {\n           display: inline-block;\n           margin: 5px 15px;\n         }\n       </file>\n     </example>\n   */\n  this.$get = ['$window', '$location', '$rootScope', function($window, $location, $rootScope) {\n    var document = $window.document;\n\n    // Helper function to get first anchor from a NodeList\n    // (using `Array#some()` instead of `angular#forEach()` since it's more performant\n    //  and working in all supported browsers.)\n    function getFirstAnchor(list) {\n      var result = null;\n      Array.prototype.some.call(list, function(element) {\n        if (nodeName_(element) === 'a') {\n          result = element;\n          return true;\n        }\n      });\n      return result;\n    }\n\n    function getYOffset() {\n\n      var offset = scroll.yOffset;\n\n      if (isFunction(offset)) {\n        offset = offset();\n      } else if (isElement(offset)) {\n        var elem = offset[0];\n        var style = $window.getComputedStyle(elem);\n        if (style.position !== 'fixed') {\n          offset = 0;\n        } else {\n          offset = elem.getBoundingClientRect().bottom;\n        }\n      } else if (!isNumber(offset)) {\n        offset = 0;\n      }\n\n      return offset;\n    }\n\n    function scrollTo(elem) {\n      if (elem) {\n        elem.scrollIntoView();\n\n        var offset = getYOffset();\n\n        if (offset) {\n          // `offset` is the number of pixels we should scroll UP in order to align `elem` properly.\n          // This is true ONLY if the call to `elem.scrollIntoView()` initially aligns `elem` at the\n          // top of the viewport.\n          //\n          // IF the number of pixels from the top of `elem` to the end of the page's content is less\n          // than the height of the viewport, then `elem.scrollIntoView()` will align the `elem` some\n          // way down the page.\n          //\n          // This is often the case for elements near the bottom of the page.\n          //\n          // In such cases we do not need to scroll the whole `offset` up, just the difference between\n          // the top of the element and the offset, which is enough to align the top of `elem` at the\n          // desired position.\n          var elemTop = elem.getBoundingClientRect().top;\n          $window.scrollBy(0, elemTop - offset);\n        }\n      } else {\n        $window.scrollTo(0, 0);\n      }\n    }\n\n    function scroll() {\n      var hash = $location.hash(), elm;\n\n      // empty hash, scroll to the top of the page\n      if (!hash) scrollTo(null);\n\n      // element with given id\n      else if ((elm = document.getElementById(hash))) scrollTo(elm);\n\n      // first anchor with given name :-D\n      else if ((elm = getFirstAnchor(document.getElementsByName(hash)))) scrollTo(elm);\n\n      // no element and hash == 'top', scroll to the top of the page\n      else if (hash === 'top') scrollTo(null);\n    }\n\n    // does not scroll when user clicks on anchor link that is currently on\n    // (no url change, no $location.hash() change), browser native does scroll\n    if (autoScrollingEnabled) {\n      $rootScope.$watch(function autoScrollWatch() {return $location.hash();},\n        function autoScrollWatchAction(newVal, oldVal) {\n          // skip the initial scroll if $location.hash is empty\n          if (newVal === oldVal && newVal === '') return;\n\n          jqLiteDocumentLoaded(function() {\n            $rootScope.$evalAsync(scroll);\n          });\n        });\n    }\n\n    return scroll;\n  }];\n}\n\nvar $animateMinErr = minErr('$animate');\n\n/**\n * @ngdoc provider\n * @name $animateProvider\n *\n * @description\n * Default implementation of $animate that doesn't perform any animations, instead just\n * synchronously performs DOM\n * updates and calls done() callbacks.\n *\n * In order to enable animations the ngAnimate module has to be loaded.\n *\n * To see the functional implementation check out src/ngAnimate/animate.js\n */\nvar $AnimateProvider = ['$provide', function($provide) {\n\n\n  this.$$selectors = {};\n\n\n  /**\n   * @ngdoc method\n   * @name $animateProvider#register\n   *\n   * @description\n   * Registers a new injectable animation factory function. The factory function produces the\n   * animation object which contains callback functions for each event that is expected to be\n   * animated.\n   *\n   *   * `eventFn`: `function(Element, doneFunction)` The element to animate, the `doneFunction`\n   *   must be called once the element animation is complete. If a function is returned then the\n   *   animation service will use this function to cancel the animation whenever a cancel event is\n   *   triggered.\n   *\n   *\n   * ```js\n   *   return {\n     *     eventFn : function(element, done) {\n     *       //code to run the animation\n     *       //once complete, then run done()\n     *       return function cancellationFunction() {\n     *         //code to cancel the animation\n     *       }\n     *     }\n     *   }\n   * ```\n   *\n   * @param {string} name The name of the animation.\n   * @param {Function} factory The factory function that will be executed to return the animation\n   *                           object.\n   */\n  this.register = function(name, factory) {\n    var key = name + '-animation';\n    if (name && name.charAt(0) != '.') throw $animateMinErr('notcsel',\n        \"Expecting class selector starting with '.' got '{0}'.\", name);\n    this.$$selectors[name.substr(1)] = key;\n    $provide.factory(key, factory);\n  };\n\n  /**\n   * @ngdoc method\n   * @name $animateProvider#classNameFilter\n   *\n   * @description\n   * Sets and/or returns the CSS class regular expression that is checked when performing\n   * an animation. Upon bootstrap the classNameFilter value is not set at all and will\n   * therefore enable $animate to attempt to perform an animation on any element.\n   * When setting the classNameFilter value, animations will only be performed on elements\n   * that successfully match the filter expression. This in turn can boost performance\n   * for low-powered devices as well as applications containing a lot of structural operations.\n   * @param {RegExp=} expression The className expression which will be checked against all animations\n   * @return {RegExp} The current CSS className expression value. If null then there is no expression value\n   */\n  this.classNameFilter = function(expression) {\n    if (arguments.length === 1) {\n      this.$$classNameFilter = (expression instanceof RegExp) ? expression : null;\n    }\n    return this.$$classNameFilter;\n  };\n\n  this.$get = ['$$q', '$$asyncCallback', '$rootScope', function($$q, $$asyncCallback, $rootScope) {\n\n    var currentDefer;\n\n    function runAnimationPostDigest(fn) {\n      var cancelFn, defer = $$q.defer();\n      defer.promise.$$cancelFn = function ngAnimateMaybeCancel() {\n        cancelFn && cancelFn();\n      };\n\n      $rootScope.$$postDigest(function ngAnimatePostDigest() {\n        cancelFn = fn(function ngAnimateNotifyComplete() {\n          defer.resolve();\n        });\n      });\n\n      return defer.promise;\n    }\n\n    function resolveElementClasses(element, classes) {\n      var toAdd = [], toRemove = [];\n\n      var hasClasses = createMap();\n      forEach((element.attr('class') || '').split(/\\s+/), function(className) {\n        hasClasses[className] = true;\n      });\n\n      forEach(classes, function(status, className) {\n        var hasClass = hasClasses[className];\n\n        // If the most recent class manipulation (via $animate) was to remove the class, and the\n        // element currently has the class, the class is scheduled for removal. Otherwise, if\n        // the most recent class manipulation (via $animate) was to add the class, and the\n        // element does not currently have the class, the class is scheduled to be added.\n        if (status === false && hasClass) {\n          toRemove.push(className);\n        } else if (status === true && !hasClass) {\n          toAdd.push(className);\n        }\n      });\n\n      return (toAdd.length + toRemove.length) > 0 &&\n        [toAdd.length ? toAdd : null, toRemove.length ? toRemove : null];\n    }\n\n    function cachedClassManipulation(cache, classes, op) {\n      for (var i=0, ii = classes.length; i < ii; ++i) {\n        var className = classes[i];\n        cache[className] = op;\n      }\n    }\n\n    function asyncPromise() {\n      // only serve one instance of a promise in order to save CPU cycles\n      if (!currentDefer) {\n        currentDefer = $$q.defer();\n        $$asyncCallback(function() {\n          currentDefer.resolve();\n          currentDefer = null;\n        });\n      }\n      return currentDefer.promise;\n    }\n\n    function applyStyles(element, options) {\n      if (angular.isObject(options)) {\n        var styles = extend(options.from || {}, options.to || {});\n        element.css(styles);\n      }\n    }\n\n    /**\n     *\n     * @ngdoc service\n     * @name $animate\n     * @description The $animate service provides rudimentary DOM manipulation functions to\n     * insert, remove and move elements within the DOM, as well as adding and removing classes.\n     * This service is the core service used by the ngAnimate $animator service which provides\n     * high-level animation hooks for CSS and JavaScript.\n     *\n     * $animate is available in the AngularJS core, however, the ngAnimate module must be included\n     * to enable full out animation support. Otherwise, $animate will only perform simple DOM\n     * manipulation operations.\n     *\n     * To learn more about enabling animation support, click here to visit the {@link ngAnimate\n     * ngAnimate module page} as well as the {@link ngAnimate.$animate ngAnimate $animate service\n     * page}.\n     */\n    return {\n      animate: function(element, from, to) {\n        applyStyles(element, { from: from, to: to });\n        return asyncPromise();\n      },\n\n      /**\n       *\n       * @ngdoc method\n       * @name $animate#enter\n       * @kind function\n       * @description Inserts the element into the DOM either after the `after` element or\n       * as the first child within the `parent` element. When the function is called a promise\n       * is returned that will be resolved at a later time.\n       * @param {DOMElement} element the element which will be inserted into the DOM\n       * @param {DOMElement} parent the parent element which will append the element as\n       *   a child (if the after element is not present)\n       * @param {DOMElement} after the sibling element which will append the element\n       *   after itself\n       * @param {object=} options an optional collection of styles that will be applied to the element.\n       * @return {Promise} the animation callback promise\n       */\n      enter: function(element, parent, after, options) {\n        applyStyles(element, options);\n        after ? after.after(element)\n              : parent.prepend(element);\n        return asyncPromise();\n      },\n\n      /**\n       *\n       * @ngdoc method\n       * @name $animate#leave\n       * @kind function\n       * @description Removes the element from the DOM. When the function is called a promise\n       * is returned that will be resolved at a later time.\n       * @param {DOMElement} element the element which will be removed from the DOM\n       * @param {object=} options an optional collection of options that will be applied to the element.\n       * @return {Promise} the animation callback promise\n       */\n      leave: function(element, options) {\n        element.remove();\n        return asyncPromise();\n      },\n\n      /**\n       *\n       * @ngdoc method\n       * @name $animate#move\n       * @kind function\n       * @description Moves the position of the provided element within the DOM to be placed\n       * either after the `after` element or inside of the `parent` element. When the function\n       * is called a promise is returned that will be resolved at a later time.\n       *\n       * @param {DOMElement} element the element which will be moved around within the\n       *   DOM\n       * @param {DOMElement} parent the parent element where the element will be\n       *   inserted into (if the after element is not present)\n       * @param {DOMElement} after the sibling element where the element will be\n       *   positioned next to\n       * @param {object=} options an optional collection of options that will be applied to the element.\n       * @return {Promise} the animation callback promise\n       */\n      move: function(element, parent, after, options) {\n        // Do not remove element before insert. Removing will cause data associated with the\n        // element to be dropped. Insert will implicitly do the remove.\n        return this.enter(element, parent, after, options);\n      },\n\n      /**\n       *\n       * @ngdoc method\n       * @name $animate#addClass\n       * @kind function\n       * @description Adds the provided className CSS class value to the provided element.\n       * When the function is called a promise is returned that will be resolved at a later time.\n       * @param {DOMElement} element the element which will have the className value\n       *   added to it\n       * @param {string} className the CSS class which will be added to the element\n       * @param {object=} options an optional collection of options that will be applied to the element.\n       * @return {Promise} the animation callback promise\n       */\n      addClass: function(element, className, options) {\n        return this.setClass(element, className, [], options);\n      },\n\n      $$addClassImmediately: function(element, className, options) {\n        element = jqLite(element);\n        className = !isString(className)\n                        ? (isArray(className) ? className.join(' ') : '')\n                        : className;\n        forEach(element, function(element) {\n          jqLiteAddClass(element, className);\n        });\n        applyStyles(element, options);\n        return asyncPromise();\n      },\n\n      /**\n       *\n       * @ngdoc method\n       * @name $animate#removeClass\n       * @kind function\n       * @description Removes the provided className CSS class value from the provided element.\n       * When the function is called a promise is returned that will be resolved at a later time.\n       * @param {DOMElement} element the element which will have the className value\n       *   removed from it\n       * @param {string} className the CSS class which will be removed from the element\n       * @param {object=} options an optional collection of options that will be applied to the element.\n       * @return {Promise} the animation callback promise\n       */\n      removeClass: function(element, className, options) {\n        return this.setClass(element, [], className, options);\n      },\n\n      $$removeClassImmediately: function(element, className, options) {\n        element = jqLite(element);\n        className = !isString(className)\n                        ? (isArray(className) ? className.join(' ') : '')\n                        : className;\n        forEach(element, function(element) {\n          jqLiteRemoveClass(element, className);\n        });\n        applyStyles(element, options);\n        return asyncPromise();\n      },\n\n      /**\n       *\n       * @ngdoc method\n       * @name $animate#setClass\n       * @kind function\n       * @description Adds and/or removes the given CSS classes to and from the element.\n       * When the function is called a promise is returned that will be resolved at a later time.\n       * @param {DOMElement} element the element which will have its CSS classes changed\n       *   removed from it\n       * @param {string} add the CSS classes which will be added to the element\n       * @param {string} remove the CSS class which will be removed from the element\n       * @param {object=} options an optional collection of options that will be applied to the element.\n       * @return {Promise} the animation callback promise\n       */\n      setClass: function(element, add, remove, options) {\n        var self = this;\n        var STORAGE_KEY = '$$animateClasses';\n        var createdCache = false;\n        element = jqLite(element);\n\n        var cache = element.data(STORAGE_KEY);\n        if (!cache) {\n          cache = {\n            classes: {},\n            options: options\n          };\n          createdCache = true;\n        } else if (options && cache.options) {\n          cache.options = angular.extend(cache.options || {}, options);\n        }\n\n        var classes = cache.classes;\n\n        add = isArray(add) ? add : add.split(' ');\n        remove = isArray(remove) ? remove : remove.split(' ');\n        cachedClassManipulation(classes, add, true);\n        cachedClassManipulation(classes, remove, false);\n\n        if (createdCache) {\n          cache.promise = runAnimationPostDigest(function(done) {\n            var cache = element.data(STORAGE_KEY);\n            element.removeData(STORAGE_KEY);\n\n            // in the event that the element is removed before postDigest\n            // is run then the cache will be undefined and there will be\n            // no need anymore to add or remove and of the element classes\n            if (cache) {\n              var classes = resolveElementClasses(element, cache.classes);\n              if (classes) {\n                self.$$setClassImmediately(element, classes[0], classes[1], cache.options);\n              }\n            }\n\n            done();\n          });\n          element.data(STORAGE_KEY, cache);\n        }\n\n        return cache.promise;\n      },\n\n      $$setClassImmediately: function(element, add, remove, options) {\n        add && this.$$addClassImmediately(element, add);\n        remove && this.$$removeClassImmediately(element, remove);\n        applyStyles(element, options);\n        return asyncPromise();\n      },\n\n      enabled: noop,\n      cancel: noop\n    };\n  }];\n}];\n\nfunction $$AsyncCallbackProvider() {\n  this.$get = ['$$rAF', '$timeout', function($$rAF, $timeout) {\n    return $$rAF.supported\n      ? function(fn) { return $$rAF(fn); }\n      : function(fn) {\n        return $timeout(fn, 0, false);\n      };\n  }];\n}\n\n/* global stripHash: true */\n\n/**\n * ! This is a private undocumented service !\n *\n * @name $browser\n * @requires $log\n * @description\n * This object has two goals:\n *\n * - hide all the global state in the browser caused by the window object\n * - abstract away all the browser specific features and inconsistencies\n *\n * For tests we provide {@link ngMock.$browser mock implementation} of the `$browser`\n * service, which can be used for convenient testing of the application without the interaction with\n * the real browser apis.\n */\n/**\n * @param {object} window The global window object.\n * @param {object} document jQuery wrapped document.\n * @param {object} $log window.console or an object with the same interface.\n * @param {object} $sniffer $sniffer service\n */\nfunction Browser(window, document, $log, $sniffer) {\n  var self = this,\n      rawDocument = document[0],\n      location = window.location,\n      history = window.history,\n      setTimeout = window.setTimeout,\n      clearTimeout = window.clearTimeout,\n      pendingDeferIds = {};\n\n  self.isMock = false;\n\n  var outstandingRequestCount = 0;\n  var outstandingRequestCallbacks = [];\n\n  // TODO(vojta): remove this temporary api\n  self.$$completeOutstandingRequest = completeOutstandingRequest;\n  self.$$incOutstandingRequestCount = function() { outstandingRequestCount++; };\n\n  /**\n   * Executes the `fn` function(supports currying) and decrements the `outstandingRequestCallbacks`\n   * counter. If the counter reaches 0, all the `outstandingRequestCallbacks` are executed.\n   */\n  function completeOutstandingRequest(fn) {\n    try {\n      fn.apply(null, sliceArgs(arguments, 1));\n    } finally {\n      outstandingRequestCount--;\n      if (outstandingRequestCount === 0) {\n        while (outstandingRequestCallbacks.length) {\n          try {\n            outstandingRequestCallbacks.pop()();\n          } catch (e) {\n            $log.error(e);\n          }\n        }\n      }\n    }\n  }\n\n  function getHash(url) {\n    var index = url.indexOf('#');\n    return index === -1 ? '' : url.substr(index + 1);\n  }\n\n  /**\n   * @private\n   * Note: this method is used only by scenario runner\n   * TODO(vojta): prefix this method with $$ ?\n   * @param {function()} callback Function that will be called when no outstanding request\n   */\n  self.notifyWhenNoOutstandingRequests = function(callback) {\n    // force browser to execute all pollFns - this is needed so that cookies and other pollers fire\n    // at some deterministic time in respect to the test runner's actions. Leaving things up to the\n    // regular poller would result in flaky tests.\n    forEach(pollFns, function(pollFn) { pollFn(); });\n\n    if (outstandingRequestCount === 0) {\n      callback();\n    } else {\n      outstandingRequestCallbacks.push(callback);\n    }\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Poll Watcher API\n  //////////////////////////////////////////////////////////////\n  var pollFns = [],\n      pollTimeout;\n\n  /**\n   * @name $browser#addPollFn\n   *\n   * @param {function()} fn Poll function to add\n   *\n   * @description\n   * Adds a function to the list of functions that poller periodically executes,\n   * and starts polling if not started yet.\n   *\n   * @returns {function()} the added function\n   */\n  self.addPollFn = function(fn) {\n    if (isUndefined(pollTimeout)) startPoller(100, setTimeout);\n    pollFns.push(fn);\n    return fn;\n  };\n\n  /**\n   * @param {number} interval How often should browser call poll functions (ms)\n   * @param {function()} setTimeout Reference to a real or fake `setTimeout` function.\n   *\n   * @description\n   * Configures the poller to run in the specified intervals, using the specified\n   * setTimeout fn and kicks it off.\n   */\n  function startPoller(interval, setTimeout) {\n    (function check() {\n      forEach(pollFns, function(pollFn) { pollFn(); });\n      pollTimeout = setTimeout(check, interval);\n    })();\n  }\n\n  //////////////////////////////////////////////////////////////\n  // URL API\n  //////////////////////////////////////////////////////////////\n\n  var cachedState, lastHistoryState,\n      lastBrowserUrl = location.href,\n      baseElement = document.find('base'),\n      reloadLocation = null;\n\n  cacheState();\n  lastHistoryState = cachedState;\n\n  /**\n   * @name $browser#url\n   *\n   * @description\n   * GETTER:\n   * Without any argument, this method just returns current value of location.href.\n   *\n   * SETTER:\n   * With at least one argument, this method sets url to new value.\n   * If html5 history api supported, pushState/replaceState is used, otherwise\n   * location.href/location.replace is used.\n   * Returns its own instance to allow chaining\n   *\n   * NOTE: this api is intended for use only by the $location service. Please use the\n   * {@link ng.$location $location service} to change url.\n   *\n   * @param {string} url New url (when used as setter)\n   * @param {boolean=} replace Should new url replace current history record?\n   * @param {object=} state object to use with pushState/replaceState\n   */\n  self.url = function(url, replace, state) {\n    // In modern browsers `history.state` is `null` by default; treating it separately\n    // from `undefined` would cause `$browser.url('/foo')` to change `history.state`\n    // to undefined via `pushState`. Instead, let's change `undefined` to `null` here.\n    if (isUndefined(state)) {\n      state = null;\n    }\n\n    // Android Browser BFCache causes location, history reference to become stale.\n    if (location !== window.location) location = window.location;\n    if (history !== window.history) history = window.history;\n\n    // setter\n    if (url) {\n      var sameState = lastHistoryState === state;\n\n      // Don't change anything if previous and current URLs and states match. This also prevents\n      // IE<10 from getting into redirect loop when in LocationHashbangInHtml5Url mode.\n      // See https://github.com/angular/angular.js/commit/ffb2701\n      if (lastBrowserUrl === url && (!$sniffer.history || sameState)) {\n        return self;\n      }\n      var sameBase = lastBrowserUrl && stripHash(lastBrowserUrl) === stripHash(url);\n      lastBrowserUrl = url;\n      lastHistoryState = state;\n      // Don't use history API if only the hash changed\n      // due to a bug in IE10/IE11 which leads\n      // to not firing a `hashchange` nor `popstate` event\n      // in some cases (see #9143).\n      if ($sniffer.history && (!sameBase || !sameState)) {\n        history[replace ? 'replaceState' : 'pushState'](state, '', url);\n        cacheState();\n        // Do the assignment again so that those two variables are referentially identical.\n        lastHistoryState = cachedState;\n      } else {\n        if (!sameBase) {\n          reloadLocation = url;\n        }\n        if (replace) {\n          location.replace(url);\n        } else if (!sameBase) {\n          location.href = url;\n        } else {\n          location.hash = getHash(url);\n        }\n      }\n      return self;\n    // getter\n    } else {\n      // - reloadLocation is needed as browsers don't allow to read out\n      //   the new location.href if a reload happened.\n      // - the replacement is a workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=407172\n      return reloadLocation || location.href.replace(/%27/g,\"'\");\n    }\n  };\n\n  /**\n   * @name $browser#state\n   *\n   * @description\n   * This method is a getter.\n   *\n   * Return history.state or null if history.state is undefined.\n   *\n   * @returns {object} state\n   */\n  self.state = function() {\n    return cachedState;\n  };\n\n  var urlChangeListeners = [],\n      urlChangeInit = false;\n\n  function cacheStateAndFireUrlChange() {\n    cacheState();\n    fireUrlChange();\n  }\n\n  // This variable should be used *only* inside the cacheState function.\n  var lastCachedState = null;\n  function cacheState() {\n    // This should be the only place in $browser where `history.state` is read.\n    cachedState = window.history.state;\n    cachedState = isUndefined(cachedState) ? null : cachedState;\n\n    // Prevent callbacks fo fire twice if both hashchange & popstate were fired.\n    if (equals(cachedState, lastCachedState)) {\n      cachedState = lastCachedState;\n    }\n    lastCachedState = cachedState;\n  }\n\n  function fireUrlChange() {\n    if (lastBrowserUrl === self.url() && lastHistoryState === cachedState) {\n      return;\n    }\n\n    lastBrowserUrl = self.url();\n    lastHistoryState = cachedState;\n    forEach(urlChangeListeners, function(listener) {\n      listener(self.url(), cachedState);\n    });\n  }\n\n  /**\n   * @name $browser#onUrlChange\n   *\n   * @description\n   * Register callback function that will be called, when url changes.\n   *\n   * It's only called when the url is changed from outside of angular:\n   * - user types different url into address bar\n   * - user clicks on history (forward/back) button\n   * - user clicks on a link\n   *\n   * It's not called when url is changed by $browser.url() method\n   *\n   * The listener gets called with new url as parameter.\n   *\n   * NOTE: this api is intended for use only by the $location service. Please use the\n   * {@link ng.$location $location service} to monitor url changes in angular apps.\n   *\n   * @param {function(string)} listener Listener function to be called when url changes.\n   * @return {function(string)} Returns the registered listener fn - handy if the fn is anonymous.\n   */\n  self.onUrlChange = function(callback) {\n    // TODO(vojta): refactor to use node's syntax for events\n    if (!urlChangeInit) {\n      // We listen on both (hashchange/popstate) when available, as some browsers (e.g. Opera)\n      // don't fire popstate when user change the address bar and don't fire hashchange when url\n      // changed by push/replaceState\n\n      // html5 history api - popstate event\n      if ($sniffer.history) jqLite(window).on('popstate', cacheStateAndFireUrlChange);\n      // hashchange event\n      jqLite(window).on('hashchange', cacheStateAndFireUrlChange);\n\n      urlChangeInit = true;\n    }\n\n    urlChangeListeners.push(callback);\n    return callback;\n  };\n\n  /**\n   * Checks whether the url has changed outside of Angular.\n   * Needs to be exported to be able to check for changes that have been done in sync,\n   * as hashchange/popstate events fire in async.\n   */\n  self.$$checkUrlChange = fireUrlChange;\n\n  //////////////////////////////////////////////////////////////\n  // Misc API\n  //////////////////////////////////////////////////////////////\n\n  /**\n   * @name $browser#baseHref\n   *\n   * @description\n   * Returns current <base href>\n   * (always relative - without domain)\n   *\n   * @returns {string} The current base href\n   */\n  self.baseHref = function() {\n    var href = baseElement.attr('href');\n    return href ? href.replace(/^(https?\\:)?\\/\\/[^\\/]*/, '') : '';\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Cookies API\n  //////////////////////////////////////////////////////////////\n  var lastCookies = {};\n  var lastCookieString = '';\n  var cookiePath = self.baseHref();\n\n  function safeDecodeURIComponent(str) {\n    try {\n      return decodeURIComponent(str);\n    } catch (e) {\n      return str;\n    }\n  }\n\n  /**\n   * @name $browser#cookies\n   *\n   * @param {string=} name Cookie name\n   * @param {string=} value Cookie value\n   *\n   * @description\n   * The cookies method provides a 'private' low level access to browser cookies.\n   * It is not meant to be used directly, use the $cookie service instead.\n   *\n   * The return values vary depending on the arguments that the method was called with as follows:\n   *\n   * - cookies() -> hash of all cookies, this is NOT a copy of the internal state, so do not modify\n   *   it\n   * - cookies(name, value) -> set name to value, if value is undefined delete the cookie\n   * - cookies(name) -> the same as (name, undefined) == DELETES (no one calls it right now that\n   *   way)\n   *\n   * @returns {Object} Hash of all cookies (if called without any parameter)\n   */\n  self.cookies = function(name, value) {\n    var cookieLength, cookieArray, cookie, i, index;\n\n    if (name) {\n      if (value === undefined) {\n        rawDocument.cookie = encodeURIComponent(name) + \"=;path=\" + cookiePath +\n                                \";expires=Thu, 01 Jan 1970 00:00:00 GMT\";\n      } else {\n        if (isString(value)) {\n          cookieLength = (rawDocument.cookie = encodeURIComponent(name) + '=' + encodeURIComponent(value) +\n                                ';path=' + cookiePath).length + 1;\n\n          // per http://www.ietf.org/rfc/rfc2109.txt browser must allow at minimum:\n          // - 300 cookies\n          // - 20 cookies per unique domain\n          // - 4096 bytes per cookie\n          if (cookieLength > 4096) {\n            $log.warn(\"Cookie '\" + name +\n              \"' possibly not set or overflowed because it was too large (\" +\n              cookieLength + \" > 4096 bytes)!\");\n          }\n        }\n      }\n    } else {\n      if (rawDocument.cookie !== lastCookieString) {\n        lastCookieString = rawDocument.cookie;\n        cookieArray = lastCookieString.split(\"; \");\n        lastCookies = {};\n\n        for (i = 0; i < cookieArray.length; i++) {\n          cookie = cookieArray[i];\n          index = cookie.indexOf('=');\n          if (index > 0) { //ignore nameless cookies\n            name = safeDecodeURIComponent(cookie.substring(0, index));\n            // the first value that is seen for a cookie is the most\n            // specific one.  values for the same cookie name that\n            // follow are for less specific paths.\n            if (lastCookies[name] === undefined) {\n              lastCookies[name] = safeDecodeURIComponent(cookie.substring(index + 1));\n            }\n          }\n        }\n      }\n      return lastCookies;\n    }\n  };\n\n\n  /**\n   * @name $browser#defer\n   * @param {function()} fn A function, who's execution should be deferred.\n   * @param {number=} [delay=0] of milliseconds to defer the function execution.\n   * @returns {*} DeferId that can be used to cancel the task via `$browser.defer.cancel()`.\n   *\n   * @description\n   * Executes a fn asynchronously via `setTimeout(fn, delay)`.\n   *\n   * Unlike when calling `setTimeout` directly, in test this function is mocked and instead of using\n   * `setTimeout` in tests, the fns are queued in an array, which can be programmatically flushed\n   * via `$browser.defer.flush()`.\n   *\n   */\n  self.defer = function(fn, delay) {\n    var timeoutId;\n    outstandingRequestCount++;\n    timeoutId = setTimeout(function() {\n      delete pendingDeferIds[timeoutId];\n      completeOutstandingRequest(fn);\n    }, delay || 0);\n    pendingDeferIds[timeoutId] = true;\n    return timeoutId;\n  };\n\n\n  /**\n   * @name $browser#defer.cancel\n   *\n   * @description\n   * Cancels a deferred task identified with `deferId`.\n   *\n   * @param {*} deferId Token returned by the `$browser.defer` function.\n   * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfully\n   *                    canceled.\n   */\n  self.defer.cancel = function(deferId) {\n    if (pendingDeferIds[deferId]) {\n      delete pendingDeferIds[deferId];\n      clearTimeout(deferId);\n      completeOutstandingRequest(noop);\n      return true;\n    }\n    return false;\n  };\n\n}\n\nfunction $BrowserProvider() {\n  this.$get = ['$window', '$log', '$sniffer', '$document',\n      function($window, $log, $sniffer, $document) {\n        return new Browser($window, $document, $log, $sniffer);\n      }];\n}\n\n/**\n * @ngdoc service\n * @name $cacheFactory\n *\n * @description\n * Factory that constructs {@link $cacheFactory.Cache Cache} objects and gives access to\n * them.\n *\n * ```js\n *\n *  var cache = $cacheFactory('cacheId');\n *  expect($cacheFactory.get('cacheId')).toBe(cache);\n *  expect($cacheFactory.get('noSuchCacheId')).not.toBeDefined();\n *\n *  cache.put(\"key\", \"value\");\n *  cache.put(\"another key\", \"another value\");\n *\n *  // We've specified no options on creation\n *  expect(cache.info()).toEqual({id: 'cacheId', size: 2});\n *\n * ```\n *\n *\n * @param {string} cacheId Name or id of the newly created cache.\n * @param {object=} options Options object that specifies the cache behavior. Properties:\n *\n *   - `{number=}` `capacity` — turns the cache into LRU cache.\n *\n * @returns {object} Newly created cache object with the following set of methods:\n *\n * - `{object}` `info()` — Returns id, size, and options of cache.\n * - `{{*}}` `put({string} key, {*} value)` — Puts a new key-value pair into the cache and returns\n *   it.\n * - `{{*}}` `get({string} key)` — Returns cached value for `key` or undefined for cache miss.\n * - `{void}` `remove({string} key)` — Removes a key-value pair from the cache.\n * - `{void}` `removeAll()` — Removes all cached values.\n * - `{void}` `destroy()` — Removes references to this cache from $cacheFactory.\n *\n * @example\n   <example module=\"cacheExampleApp\">\n     <file name=\"index.html\">\n       <div ng-controller=\"CacheController\">\n         <input ng-model=\"newCacheKey\" placeholder=\"Key\">\n         <input ng-model=\"newCacheValue\" placeholder=\"Value\">\n         <button ng-click=\"put(newCacheKey, newCacheValue)\">Cache</button>\n\n         <p ng-if=\"keys.length\">Cached Values</p>\n         <div ng-repeat=\"key in keys\">\n           <span ng-bind=\"key\"></span>\n           <span>: </span>\n           <b ng-bind=\"cache.get(key)\"></b>\n         </div>\n\n         <p>Cache Info</p>\n         <div ng-repeat=\"(key, value) in cache.info()\">\n           <span ng-bind=\"key\"></span>\n           <span>: </span>\n           <b ng-bind=\"value\"></b>\n         </div>\n       </div>\n     </file>\n     <file name=\"script.js\">\n       angular.module('cacheExampleApp', []).\n         controller('CacheController', ['$scope', '$cacheFactory', function($scope, $cacheFactory) {\n           $scope.keys = [];\n           $scope.cache = $cacheFactory('cacheId');\n           $scope.put = function(key, value) {\n             if ($scope.cache.get(key) === undefined) {\n               $scope.keys.push(key);\n             }\n             $scope.cache.put(key, value === undefined ? null : value);\n           };\n         }]);\n     </file>\n     <file name=\"style.css\">\n       p {\n         margin: 10px 0 3px;\n       }\n     </file>\n   </example>\n */\nfunction $CacheFactoryProvider() {\n\n  this.$get = function() {\n    var caches = {};\n\n    function cacheFactory(cacheId, options) {\n      if (cacheId in caches) {\n        throw minErr('$cacheFactory')('iid', \"CacheId '{0}' is already taken!\", cacheId);\n      }\n\n      var size = 0,\n          stats = extend({}, options, {id: cacheId}),\n          data = {},\n          capacity = (options && options.capacity) || Number.MAX_VALUE,\n          lruHash = {},\n          freshEnd = null,\n          staleEnd = null;\n\n      /**\n       * @ngdoc type\n       * @name $cacheFactory.Cache\n       *\n       * @description\n       * A cache object used to store and retrieve data, primarily used by\n       * {@link $http $http} and the {@link ng.directive:script script} directive to cache\n       * templates and other data.\n       *\n       * ```js\n       *  angular.module('superCache')\n       *    .factory('superCache', ['$cacheFactory', function($cacheFactory) {\n       *      return $cacheFactory('super-cache');\n       *    }]);\n       * ```\n       *\n       * Example test:\n       *\n       * ```js\n       *  it('should behave like a cache', inject(function(superCache) {\n       *    superCache.put('key', 'value');\n       *    superCache.put('another key', 'another value');\n       *\n       *    expect(superCache.info()).toEqual({\n       *      id: 'super-cache',\n       *      size: 2\n       *    });\n       *\n       *    superCache.remove('another key');\n       *    expect(superCache.get('another key')).toBeUndefined();\n       *\n       *    superCache.removeAll();\n       *    expect(superCache.info()).toEqual({\n       *      id: 'super-cache',\n       *      size: 0\n       *    });\n       *  }));\n       * ```\n       */\n      return caches[cacheId] = {\n\n        /**\n         * @ngdoc method\n         * @name $cacheFactory.Cache#put\n         * @kind function\n         *\n         * @description\n         * Inserts a named entry into the {@link $cacheFactory.Cache Cache} object to be\n         * retrieved later, and incrementing the size of the cache if the key was not already\n         * present in the cache. If behaving like an LRU cache, it will also remove stale\n         * entries from the set.\n         *\n         * It will not insert undefined values into the cache.\n         *\n         * @param {string} key the key under which the cached data is stored.\n         * @param {*} value the value to store alongside the key. If it is undefined, the key\n         *    will not be stored.\n         * @returns {*} the value stored.\n         */\n        put: function(key, value) {\n          if (capacity < Number.MAX_VALUE) {\n            var lruEntry = lruHash[key] || (lruHash[key] = {key: key});\n\n            refresh(lruEntry);\n          }\n\n          if (isUndefined(value)) return;\n          if (!(key in data)) size++;\n          data[key] = value;\n\n          if (size > capacity) {\n            this.remove(staleEnd.key);\n          }\n\n          return value;\n        },\n\n        /**\n         * @ngdoc method\n         * @name $cacheFactory.Cache#get\n         * @kind function\n         *\n         * @description\n         * Retrieves named data stored in the {@link $cacheFactory.Cache Cache} object.\n         *\n         * @param {string} key the key of the data to be retrieved\n         * @returns {*} the value stored.\n         */\n        get: function(key) {\n          if (capacity < Number.MAX_VALUE) {\n            var lruEntry = lruHash[key];\n\n            if (!lruEntry) return;\n\n            refresh(lruEntry);\n          }\n\n          return data[key];\n        },\n\n\n        /**\n         * @ngdoc method\n         * @name $cacheFactory.Cache#remove\n         * @kind function\n         *\n         * @description\n         * Removes an entry from the {@link $cacheFactory.Cache Cache} object.\n         *\n         * @param {string} key the key of the entry to be removed\n         */\n        remove: function(key) {\n          if (capacity < Number.MAX_VALUE) {\n            var lruEntry = lruHash[key];\n\n            if (!lruEntry) return;\n\n            if (lruEntry == freshEnd) freshEnd = lruEntry.p;\n            if (lruEntry == staleEnd) staleEnd = lruEntry.n;\n            link(lruEntry.n,lruEntry.p);\n\n            delete lruHash[key];\n          }\n\n          delete data[key];\n          size--;\n        },\n\n\n        /**\n         * @ngdoc method\n         * @name $cacheFactory.Cache#removeAll\n         * @kind function\n         *\n         * @description\n         * Clears the cache object of any entries.\n         */\n        removeAll: function() {\n          data = {};\n          size = 0;\n          lruHash = {};\n          freshEnd = staleEnd = null;\n        },\n\n\n        /**\n         * @ngdoc method\n         * @name $cacheFactory.Cache#destroy\n         * @kind function\n         *\n         * @description\n         * Destroys the {@link $cacheFactory.Cache Cache} object entirely,\n         * removing it from the {@link $cacheFactory $cacheFactory} set.\n         */\n        destroy: function() {\n          data = null;\n          stats = null;\n          lruHash = null;\n          delete caches[cacheId];\n        },\n\n\n        /**\n         * @ngdoc method\n         * @name $cacheFactory.Cache#info\n         * @kind function\n         *\n         * @description\n         * Retrieve information regarding a particular {@link $cacheFactory.Cache Cache}.\n         *\n         * @returns {object} an object with the following properties:\n         *   <ul>\n         *     <li>**id**: the id of the cache instance</li>\n         *     <li>**size**: the number of entries kept in the cache instance</li>\n         *     <li>**...**: any additional properties from the options object when creating the\n         *       cache.</li>\n         *   </ul>\n         */\n        info: function() {\n          return extend({}, stats, {size: size});\n        }\n      };\n\n\n      /**\n       * makes the `entry` the freshEnd of the LRU linked list\n       */\n      function refresh(entry) {\n        if (entry != freshEnd) {\n          if (!staleEnd) {\n            staleEnd = entry;\n          } else if (staleEnd == entry) {\n            staleEnd = entry.n;\n          }\n\n          link(entry.n, entry.p);\n          link(entry, freshEnd);\n          freshEnd = entry;\n          freshEnd.n = null;\n        }\n      }\n\n\n      /**\n       * bidirectionally links two entries of the LRU linked list\n       */\n      function link(nextEntry, prevEntry) {\n        if (nextEntry != prevEntry) {\n          if (nextEntry) nextEntry.p = prevEntry; //p stands for previous, 'prev' didn't minify\n          if (prevEntry) prevEntry.n = nextEntry; //n stands for next, 'next' didn't minify\n        }\n      }\n    }\n\n\n  /**\n   * @ngdoc method\n   * @name $cacheFactory#info\n   *\n   * @description\n   * Get information about all the caches that have been created\n   *\n   * @returns {Object} - key-value map of `cacheId` to the result of calling `cache#info`\n   */\n    cacheFactory.info = function() {\n      var info = {};\n      forEach(caches, function(cache, cacheId) {\n        info[cacheId] = cache.info();\n      });\n      return info;\n    };\n\n\n  /**\n   * @ngdoc method\n   * @name $cacheFactory#get\n   *\n   * @description\n   * Get access to a cache object by the `cacheId` used when it was created.\n   *\n   * @param {string} cacheId Name or id of a cache to access.\n   * @returns {object} Cache object identified by the cacheId or undefined if no such cache.\n   */\n    cacheFactory.get = function(cacheId) {\n      return caches[cacheId];\n    };\n\n\n    return cacheFactory;\n  };\n}\n\n/**\n * @ngdoc service\n * @name $templateCache\n *\n * @description\n * The first time a template is used, it is loaded in the template cache for quick retrieval. You\n * can load templates directly into the cache in a `script` tag, or by consuming the\n * `$templateCache` service directly.\n *\n * Adding via the `script` tag:\n *\n * ```html\n *   <script type=\"text/ng-template\" id=\"templateId.html\">\n *     <p>This is the content of the template</p>\n *   </script>\n * ```\n *\n * **Note:** the `script` tag containing the template does not need to be included in the `head` of\n * the document, but it must be a descendent of the {@link ng.$rootElement $rootElement} (IE,\n * element with ng-app attribute), otherwise the template will be ignored.\n *\n * Adding via the $templateCache service:\n *\n * ```js\n * var myApp = angular.module('myApp', []);\n * myApp.run(function($templateCache) {\n *   $templateCache.put('templateId.html', 'This is the content of the template');\n * });\n * ```\n *\n * To retrieve the template later, simply use it in your HTML:\n * ```html\n * <div ng-include=\" 'templateId.html' \"></div>\n * ```\n *\n * or get it via Javascript:\n * ```js\n * $templateCache.get('templateId.html')\n * ```\n *\n * See {@link ng.$cacheFactory $cacheFactory}.\n *\n */\nfunction $TemplateCacheProvider() {\n  this.$get = ['$cacheFactory', function($cacheFactory) {\n    return $cacheFactory('templates');\n  }];\n}\n\n/* ! VARIABLE/FUNCTION NAMING CONVENTIONS THAT APPLY TO THIS FILE!\n *\n * DOM-related variables:\n *\n * - \"node\" - DOM Node\n * - \"element\" - DOM Element or Node\n * - \"$node\" or \"$element\" - jqLite-wrapped node or element\n *\n *\n * Compiler related stuff:\n *\n * - \"linkFn\" - linking fn of a single directive\n * - \"nodeLinkFn\" - function that aggregates all linking fns for a particular node\n * - \"childLinkFn\" -  function that aggregates all linking fns for child nodes of a particular node\n * - \"compositeLinkFn\" - function that aggregates all linking fns for a compilation root (nodeList)\n */\n\n\n/**\n * @ngdoc service\n * @name $compile\n * @kind function\n *\n * @description\n * Compiles an HTML string or DOM into a template and produces a template function, which\n * can then be used to link {@link ng.$rootScope.Scope `scope`} and the template together.\n *\n * The compilation is a process of walking the DOM tree and matching DOM elements to\n * {@link ng.$compileProvider#directive directives}.\n *\n * <div class=\"alert alert-warning\">\n * **Note:** This document is an in-depth reference of all directive options.\n * For a gentle introduction to directives with examples of common use cases,\n * see the {@link guide/directive directive guide}.\n * </div>\n *\n * ## Comprehensive Directive API\n *\n * There are many different options for a directive.\n *\n * The difference resides in the return value of the factory function.\n * You can either return a \"Directive Definition Object\" (see below) that defines the directive properties,\n * or just the `postLink` function (all other properties will have the default values).\n *\n * <div class=\"alert alert-success\">\n * **Best Practice:** It's recommended to use the \"directive definition object\" form.\n * </div>\n *\n * Here's an example directive declared with a Directive Definition Object:\n *\n * ```js\n *   var myModule = angular.module(...);\n *\n *   myModule.directive('directiveName', function factory(injectables) {\n *     var directiveDefinitionObject = {\n *       priority: 0,\n *       template: '<div></div>', // or // function(tElement, tAttrs) { ... },\n *       // or\n *       // templateUrl: 'directive.html', // or // function(tElement, tAttrs) { ... },\n *       transclude: false,\n *       restrict: 'A',\n *       templateNamespace: 'html',\n *       scope: false,\n *       controller: function($scope, $element, $attrs, $transclude, otherInjectables) { ... },\n *       controllerAs: 'stringAlias',\n *       require: 'siblingDirectiveName', // or // ['^parentDirectiveName', '?optionalDirectiveName', '?^optionalParent'],\n *       compile: function compile(tElement, tAttrs, transclude) {\n *         return {\n *           pre: function preLink(scope, iElement, iAttrs, controller) { ... },\n *           post: function postLink(scope, iElement, iAttrs, controller) { ... }\n *         }\n *         // or\n *         // return function postLink( ... ) { ... }\n *       },\n *       // or\n *       // link: {\n *       //  pre: function preLink(scope, iElement, iAttrs, controller) { ... },\n *       //  post: function postLink(scope, iElement, iAttrs, controller) { ... }\n *       // }\n *       // or\n *       // link: function postLink( ... ) { ... }\n *     };\n *     return directiveDefinitionObject;\n *   });\n * ```\n *\n * <div class=\"alert alert-warning\">\n * **Note:** Any unspecified options will use the default value. You can see the default values below.\n * </div>\n *\n * Therefore the above can be simplified as:\n *\n * ```js\n *   var myModule = angular.module(...);\n *\n *   myModule.directive('directiveName', function factory(injectables) {\n *     var directiveDefinitionObject = {\n *       link: function postLink(scope, iElement, iAttrs) { ... }\n *     };\n *     return directiveDefinitionObject;\n *     // or\n *     // return function postLink(scope, iElement, iAttrs) { ... }\n *   });\n * ```\n *\n *\n *\n * ### Directive Definition Object\n *\n * The directive definition object provides instructions to the {@link ng.$compile\n * compiler}. The attributes are:\n *\n * #### `multiElement`\n * When this property is set to true, the HTML compiler will collect DOM nodes between\n * nodes with the attributes `directive-name-start` and `directive-name-end`, and group them\n * together as the directive elements. It is recommended that this feature be used on directives\n * which are not strictly behavioural (such as {@link ngClick}), and which\n * do not manipulate or replace child nodes (such as {@link ngInclude}).\n *\n * #### `priority`\n * When there are multiple directives defined on a single DOM element, sometimes it\n * is necessary to specify the order in which the directives are applied. The `priority` is used\n * to sort the directives before their `compile` functions get called. Priority is defined as a\n * number. Directives with greater numerical `priority` are compiled first. Pre-link functions\n * are also run in priority order, but post-link functions are run in reverse order. The order\n * of directives with the same priority is undefined. The default priority is `0`.\n *\n * #### `terminal`\n * If set to true then the current `priority` will be the last set of directives\n * which will execute (any directives at the current priority will still execute\n * as the order of execution on same `priority` is undefined). Note that expressions\n * and other directives used in the directive's template will also be excluded from execution.\n *\n * #### `scope`\n * **If set to `true`,** then a new scope will be created for this directive. If multiple directives on the\n * same element request a new scope, only one new scope is created. The new scope rule does not\n * apply for the root of the template since the root of the template always gets a new scope.\n *\n * **If set to `{}` (object hash),** then a new \"isolate\" scope is created. The 'isolate' scope differs from\n * normal scope in that it does not prototypically inherit from the parent scope. This is useful\n * when creating reusable components, which should not accidentally read or modify data in the\n * parent scope.\n *\n * The 'isolate' scope takes an object hash which defines a set of local scope properties\n * derived from the parent scope. These local properties are useful for aliasing values for\n * templates. Locals definition is a hash of local scope property to its source:\n *\n * * `@` or `@attr` - bind a local scope property to the value of DOM attribute. The result is\n *   always a string since DOM attributes are strings. If no `attr` name is specified  then the\n *   attribute name is assumed to be the same as the local name.\n *   Given `<widget my-attr=\"hello {{name}}\">` and widget definition\n *   of `scope: { localName:'@myAttr' }`, then widget scope property `localName` will reflect\n *   the interpolated value of `hello {{name}}`. As the `name` attribute changes so will the\n *   `localName` property on the widget scope. The `name` is read from the parent scope (not\n *   component scope).\n *\n * * `=` or `=attr` - set up bi-directional binding between a local scope property and the\n *   parent scope property of name defined via the value of the `attr` attribute. If no `attr`\n *   name is specified then the attribute name is assumed to be the same as the local name.\n *   Given `<widget my-attr=\"parentModel\">` and widget definition of\n *   `scope: { localModel:'=myAttr' }`, then widget scope property `localModel` will reflect the\n *   value of `parentModel` on the parent scope. Any changes to `parentModel` will be reflected\n *   in `localModel` and any changes in `localModel` will reflect in `parentModel`. If the parent\n *   scope property doesn't exist, it will throw a NON_ASSIGNABLE_MODEL_EXPRESSION exception. You\n *   can avoid this behavior using `=?` or `=?attr` in order to flag the property as optional. If\n *   you want to shallow watch for changes (i.e. $watchCollection instead of $watch) you can use\n *   `=*` or `=*attr` (`=*?` or `=*?attr` if the property is optional).\n *\n * * `&` or `&attr` - provides a way to execute an expression in the context of the parent scope.\n *   If no `attr` name is specified then the attribute name is assumed to be the same as the\n *   local name. Given `<widget my-attr=\"count = count + value\">` and widget definition of\n *   `scope: { localFn:'&myAttr' }`, then isolate scope property `localFn` will point to\n *   a function wrapper for the `count = count + value` expression. Often it's desirable to\n *   pass data from the isolated scope via an expression to the parent scope, this can be\n *   done by passing a map of local variable names and values into the expression wrapper fn.\n *   For example, if the expression is `increment(amount)` then we can specify the amount value\n *   by calling the `localFn` as `localFn({amount: 22})`.\n *\n *\n * #### `bindToController`\n * When an isolate scope is used for a component (see above), and `controllerAs` is used, `bindToController: true` will\n * allow a component to have its properties bound to the controller, rather than to scope. When the controller\n * is instantiated, the initial values of the isolate scope bindings are already available.\n *\n * #### `controller`\n * Controller constructor function. The controller is instantiated before the\n * pre-linking phase and it is shared with other directives (see\n * `require` attribute). This allows the directives to communicate with each other and augment\n * each other's behavior. The controller is injectable (and supports bracket notation) with the following locals:\n *\n * * `$scope` - Current scope associated with the element\n * * `$element` - Current element\n * * `$attrs` - Current attributes object for the element\n * * `$transclude` - A transclude linking function pre-bound to the correct transclusion scope:\n *   `function([scope], cloneLinkingFn, futureParentElement)`.\n *    * `scope`: optional argument to override the scope.\n *    * `cloneLinkingFn`: optional argument to create clones of the original transcluded content.\n *    * `futureParentElement`:\n *        * defines the parent to which the `cloneLinkingFn` will add the cloned elements.\n *        * default: `$element.parent()` resp. `$element` for `transclude:'element'` resp. `transclude:true`.\n *        * only needed for transcludes that are allowed to contain non html elements (e.g. SVG elements)\n *          and when the `cloneLinkinFn` is passed,\n *          as those elements need to created and cloned in a special way when they are defined outside their\n *          usual containers (e.g. like `<svg>`).\n *        * See also the `directive.templateNamespace` property.\n *\n *\n * #### `require`\n * Require another directive and inject its controller as the fourth argument to the linking function. The\n * `require` takes a string name (or array of strings) of the directive(s) to pass in. If an array is used, the\n * injected argument will be an array in corresponding order. If no such directive can be\n * found, or if the directive does not have a controller, then an error is raised. The name can be prefixed with:\n *\n * * (no prefix) - Locate the required controller on the current element. Throw an error if not found.\n * * `?` - Attempt to locate the required controller or pass `null` to the `link` fn if not found.\n * * `^` - Locate the required controller by searching the element and its parents. Throw an error if not found.\n * * `^^` - Locate the required controller by searching the element's parents. Throw an error if not found.\n * * `?^` - Attempt to locate the required controller by searching the element and its parents or pass\n *   `null` to the `link` fn if not found.\n * * `?^^` - Attempt to locate the required controller by searching the element's parents, or pass\n *   `null` to the `link` fn if not found.\n *\n *\n * #### `controllerAs`\n * Controller alias at the directive scope. An alias for the controller so it\n * can be referenced at the directive template. The directive needs to define a scope for this\n * configuration to be used. Useful in the case when directive is used as component.\n *\n *\n * #### `restrict`\n * String of subset of `EACM` which restricts the directive to a specific directive\n * declaration style. If omitted, the defaults (elements and attributes) are used.\n *\n * * `E` - Element name (default): `<my-directive></my-directive>`\n * * `A` - Attribute (default): `<div my-directive=\"exp\"></div>`\n * * `C` - Class: `<div class=\"my-directive: exp;\"></div>`\n * * `M` - Comment: `<!-- directive: my-directive exp -->`\n *\n *\n * #### `templateNamespace`\n * String representing the document type used by the markup in the template.\n * AngularJS needs this information as those elements need to be created and cloned\n * in a special way when they are defined outside their usual containers like `<svg>` and `<math>`.\n *\n * * `html` - All root nodes in the template are HTML. Root nodes may also be\n *   top-level elements such as `<svg>` or `<math>`.\n * * `svg` - The root nodes in the template are SVG elements (excluding `<math>`).\n * * `math` - The root nodes in the template are MathML elements (excluding `<svg>`).\n *\n * If no `templateNamespace` is specified, then the namespace is considered to be `html`.\n *\n * #### `template`\n * HTML markup that may:\n * * Replace the contents of the directive's element (default).\n * * Replace the directive's element itself (if `replace` is true - DEPRECATED).\n * * Wrap the contents of the directive's element (if `transclude` is true).\n *\n * Value may be:\n *\n * * A string. For example `<div red-on-hover>{{delete_str}}</div>`.\n * * A function which takes two arguments `tElement` and `tAttrs` (described in the `compile`\n *   function api below) and returns a string value.\n *\n *\n * #### `templateUrl`\n * This is similar to `template` but the template is loaded from the specified URL, asynchronously.\n *\n * Because template loading is asynchronous the compiler will suspend compilation of directives on that element\n * for later when the template has been resolved.  In the meantime it will continue to compile and link\n * sibling and parent elements as though this element had not contained any directives.\n *\n * The compiler does not suspend the entire compilation to wait for templates to be loaded because this\n * would result in the whole app \"stalling\" until all templates are loaded asynchronously - even in the\n * case when only one deeply nested directive has `templateUrl`.\n *\n * Template loading is asynchronous even if the template has been preloaded into the {@link $templateCache}\n *\n * You can specify `templateUrl` as a string representing the URL or as a function which takes two\n * arguments `tElement` and `tAttrs` (described in the `compile` function api below) and returns\n * a string value representing the url.  In either case, the template URL is passed through {@link\n * $sce#getTrustedResourceUrl $sce.getTrustedResourceUrl}.\n *\n *\n * #### `replace` ([*DEPRECATED*!], will be removed in next major release - i.e. v2.0)\n * specify what the template should replace. Defaults to `false`.\n *\n * * `true` - the template will replace the directive's element.\n * * `false` - the template will replace the contents of the directive's element.\n *\n * The replacement process migrates all of the attributes / classes from the old element to the new\n * one. See the {@link guide/directive#template-expanding-directive\n * Directives Guide} for an example.\n *\n * There are very few scenarios where element replacement is required for the application function,\n * the main one being reusable custom components that are used within SVG contexts\n * (because SVG doesn't work with custom elements in the DOM tree).\n *\n * #### `transclude`\n * Extract the contents of the element where the directive appears and make it available to the directive.\n * The contents are compiled and provided to the directive as a **transclusion function**. See the\n * {@link $compile#transclusion Transclusion} section below.\n *\n * There are two kinds of transclusion depending upon whether you want to transclude just the contents of the\n * directive's element or the entire element:\n *\n * * `true` - transclude the content (i.e. the child nodes) of the directive's element.\n * * `'element'` - transclude the whole of the directive's element including any directives on this\n *   element that defined at a lower priority than this directive. When used, the `template`\n *   property is ignored.\n *\n *\n * #### `compile`\n *\n * ```js\n *   function compile(tElement, tAttrs, transclude) { ... }\n * ```\n *\n * The compile function deals with transforming the template DOM. Since most directives do not do\n * template transformation, it is not used often. The compile function takes the following arguments:\n *\n *   * `tElement` - template element - The element where the directive has been declared. It is\n *     safe to do template transformation on the element and child elements only.\n *\n *   * `tAttrs` - template attributes - Normalized list of attributes declared on this element shared\n *     between all directive compile functions.\n *\n *   * `transclude` -  [*DEPRECATED*!] A transclude linking function: `function(scope, cloneLinkingFn)`\n *\n * <div class=\"alert alert-warning\">\n * **Note:** The template instance and the link instance may be different objects if the template has\n * been cloned. For this reason it is **not** safe to do anything other than DOM transformations that\n * apply to all cloned DOM nodes within the compile function. Specifically, DOM listener registration\n * should be done in a linking function rather than in a compile function.\n * </div>\n\n * <div class=\"alert alert-warning\">\n * **Note:** The compile function cannot handle directives that recursively use themselves in their\n * own templates or compile functions. Compiling these directives results in an infinite loop and a\n * stack overflow errors.\n *\n * This can be avoided by manually using $compile in the postLink function to imperatively compile\n * a directive's template instead of relying on automatic template compilation via `template` or\n * `templateUrl` declaration or manual compilation inside the compile function.\n * </div>\n *\n * <div class=\"alert alert-error\">\n * **Note:** The `transclude` function that is passed to the compile function is deprecated, as it\n *   e.g. does not know about the right outer scope. Please use the transclude function that is passed\n *   to the link function instead.\n * </div>\n\n * A compile function can have a return value which can be either a function or an object.\n *\n * * returning a (post-link) function - is equivalent to registering the linking function via the\n *   `link` property of the config object when the compile function is empty.\n *\n * * returning an object with function(s) registered via `pre` and `post` properties - allows you to\n *   control when a linking function should be called during the linking phase. See info about\n *   pre-linking and post-linking functions below.\n *\n *\n * #### `link`\n * This property is used only if the `compile` property is not defined.\n *\n * ```js\n *   function link(scope, iElement, iAttrs, controller, transcludeFn) { ... }\n * ```\n *\n * The link function is responsible for registering DOM listeners as well as updating the DOM. It is\n * executed after the template has been cloned. This is where most of the directive logic will be\n * put.\n *\n *   * `scope` - {@link ng.$rootScope.Scope Scope} - The scope to be used by the\n *     directive for registering {@link ng.$rootScope.Scope#$watch watches}.\n *\n *   * `iElement` - instance element - The element where the directive is to be used. It is safe to\n *     manipulate the children of the element only in `postLink` function since the children have\n *     already been linked.\n *\n *   * `iAttrs` - instance attributes - Normalized list of attributes declared on this element shared\n *     between all directive linking functions.\n *\n *   * `controller` - a controller instance - A controller instance if at least one directive on the\n *     element defines a controller. The controller is shared among all the directives, which allows\n *     the directives to use the controllers as a communication channel.\n *\n *   * `transcludeFn` - A transclude linking function pre-bound to the correct transclusion scope.\n *     This is the same as the `$transclude`\n *     parameter of directive controllers, see there for details.\n *     `function([scope], cloneLinkingFn, futureParentElement)`.\n *\n * #### Pre-linking function\n *\n * Executed before the child elements are linked. Not safe to do DOM transformation since the\n * compiler linking function will fail to locate the correct elements for linking.\n *\n * #### Post-linking function\n *\n * Executed after the child elements are linked.\n *\n * Note that child elements that contain `templateUrl` directives will not have been compiled\n * and linked since they are waiting for their template to load asynchronously and their own\n * compilation and linking has been suspended until that occurs.\n *\n * It is safe to do DOM transformation in the post-linking function on elements that are not waiting\n * for their async templates to be resolved.\n *\n *\n * ### Transclusion\n *\n * Transclusion is the process of extracting a collection of DOM element from one part of the DOM and\n * copying them to another part of the DOM, while maintaining their connection to the original AngularJS\n * scope from where they were taken.\n *\n * Transclusion is used (often with {@link ngTransclude}) to insert the\n * original contents of a directive's element into a specified place in the template of the directive.\n * The benefit of transclusion, over simply moving the DOM elements manually, is that the transcluded\n * content has access to the properties on the scope from which it was taken, even if the directive\n * has isolated scope.\n * See the {@link guide/directive#creating-a-directive-that-wraps-other-elements Directives Guide}.\n *\n * This makes it possible for the widget to have private state for its template, while the transcluded\n * content has access to its originating scope.\n *\n * <div class=\"alert alert-warning\">\n * **Note:** When testing an element transclude directive you must not place the directive at the root of the\n * DOM fragment that is being compiled. See {@link guide/unit-testing#testing-transclusion-directives\n * Testing Transclusion Directives}.\n * </div>\n *\n * #### Transclusion Functions\n *\n * When a directive requests transclusion, the compiler extracts its contents and provides a **transclusion\n * function** to the directive's `link` function and `controller`. This transclusion function is a special\n * **linking function** that will return the compiled contents linked to a new transclusion scope.\n *\n * <div class=\"alert alert-info\">\n * If you are just using {@link ngTransclude} then you don't need to worry about this function, since\n * ngTransclude will deal with it for us.\n * </div>\n *\n * If you want to manually control the insertion and removal of the transcluded content in your directive\n * then you must use this transclude function. When you call a transclude function it returns a a jqLite/JQuery\n * object that contains the compiled DOM, which is linked to the correct transclusion scope.\n *\n * When you call a transclusion function you can pass in a **clone attach function**. This function accepts\n * two parameters, `function(clone, scope) { ... }`, where the `clone` is a fresh compiled copy of your transcluded\n * content and the `scope` is the newly created transclusion scope, to which the clone is bound.\n *\n * <div class=\"alert alert-info\">\n * **Best Practice**: Always provide a `cloneFn` (clone attach function) when you call a translude function\n * since you then get a fresh clone of the original DOM and also have access to the new transclusion scope.\n * </div>\n *\n * It is normal practice to attach your transcluded content (`clone`) to the DOM inside your **clone\n * attach function**:\n *\n * ```js\n * var transcludedContent, transclusionScope;\n *\n * $transclude(function(clone, scope) {\n *   element.append(clone);\n *   transcludedContent = clone;\n *   transclusionScope = scope;\n * });\n * ```\n *\n * Later, if you want to remove the transcluded content from your DOM then you should also destroy the\n * associated transclusion scope:\n *\n * ```js\n * transcludedContent.remove();\n * transclusionScope.$destroy();\n * ```\n *\n * <div class=\"alert alert-info\">\n * **Best Practice**: if you intend to add and remove transcluded content manually in your directive\n * (by calling the transclude function to get the DOM and and calling `element.remove()` to remove it),\n * then you are also responsible for calling `$destroy` on the transclusion scope.\n * </div>\n *\n * The built-in DOM manipulation directives, such as {@link ngIf}, {@link ngSwitch} and {@link ngRepeat}\n * automatically destroy their transluded clones as necessary so you do not need to worry about this if\n * you are simply using {@link ngTransclude} to inject the transclusion into your directive.\n *\n *\n * #### Transclusion Scopes\n *\n * When you call a transclude function it returns a DOM fragment that is pre-bound to a **transclusion\n * scope**. This scope is special, in that it is a child of the directive's scope (and so gets destroyed\n * when the directive's scope gets destroyed) but it inherits the properties of the scope from which it\n * was taken.\n *\n * For example consider a directive that uses transclusion and isolated scope. The DOM hierarchy might look\n * like this:\n *\n * ```html\n * <div ng-app>\n *   <div isolate>\n *     <div transclusion>\n *     </div>\n *   </div>\n * </div>\n * ```\n *\n * The `$parent` scope hierarchy will look like this:\n *\n * ```\n * - $rootScope\n *   - isolate\n *     - transclusion\n * ```\n *\n * but the scopes will inherit prototypically from different scopes to their `$parent`.\n *\n * ```\n * - $rootScope\n *   - transclusion\n * - isolate\n * ```\n *\n *\n * ### Attributes\n *\n * The {@link ng.$compile.directive.Attributes Attributes} object - passed as a parameter in the\n * `link()` or `compile()` functions. It has a variety of uses.\n *\n * accessing *Normalized attribute names:*\n * Directives like 'ngBind' can be expressed in many ways: 'ng:bind', `data-ng-bind`, or 'x-ng-bind'.\n * the attributes object allows for normalized access to\n *   the attributes.\n *\n * * *Directive inter-communication:* All directives share the same instance of the attributes\n *   object which allows the directives to use the attributes object as inter directive\n *   communication.\n *\n * * *Supports interpolation:* Interpolation attributes are assigned to the attribute object\n *   allowing other directives to read the interpolated value.\n *\n * * *Observing interpolated attributes:* Use `$observe` to observe the value changes of attributes\n *   that contain interpolation (e.g. `src=\"{{bar}}\"`). Not only is this very efficient but it's also\n *   the only way to easily get the actual value because during the linking phase the interpolation\n *   hasn't been evaluated yet and so the value is at this time set to `undefined`.\n *\n * ```js\n * function linkingFn(scope, elm, attrs, ctrl) {\n *   // get the attribute value\n *   console.log(attrs.ngModel);\n *\n *   // change the attribute\n *   attrs.$set('ngModel', 'new value');\n *\n *   // observe changes to interpolated attribute\n *   attrs.$observe('ngModel', function(value) {\n *     console.log('ngModel has changed value to ' + value);\n *   });\n * }\n * ```\n *\n * ## Example\n *\n * <div class=\"alert alert-warning\">\n * **Note**: Typically directives are registered with `module.directive`. The example below is\n * to illustrate how `$compile` works.\n * </div>\n *\n <example module=\"compileExample\">\n   <file name=\"index.html\">\n    <script>\n      angular.module('compileExample', [], function($compileProvider) {\n        // configure new 'compile' directive by passing a directive\n        // factory function. The factory function injects the '$compile'\n        $compileProvider.directive('compile', function($compile) {\n          // directive factory creates a link function\n          return function(scope, element, attrs) {\n            scope.$watch(\n              function(scope) {\n                 // watch the 'compile' expression for changes\n                return scope.$eval(attrs.compile);\n              },\n              function(value) {\n                // when the 'compile' expression changes\n                // assign it into the current DOM\n                element.html(value);\n\n                // compile the new DOM and link it to the current\n                // scope.\n                // NOTE: we only compile .childNodes so that\n                // we don't get into infinite loop compiling ourselves\n                $compile(element.contents())(scope);\n              }\n            );\n          };\n        });\n      })\n      .controller('GreeterController', ['$scope', function($scope) {\n        $scope.name = 'Angular';\n        $scope.html = 'Hello {{name}}';\n      }]);\n    </script>\n    <div ng-controller=\"GreeterController\">\n      <input ng-model=\"name\"> <br>\n      <textarea ng-model=\"html\"></textarea> <br>\n      <div compile=\"html\"></div>\n    </div>\n   </file>\n   <file name=\"protractor.js\" type=\"protractor\">\n     it('should auto compile', function() {\n       var textarea = $('textarea');\n       var output = $('div[compile]');\n       // The initial state reads 'Hello Angular'.\n       expect(output.getText()).toBe('Hello Angular');\n       textarea.clear();\n       textarea.sendKeys('{{name}}!');\n       expect(output.getText()).toBe('Angular!');\n     });\n   </file>\n </example>\n\n *\n *\n * @param {string|DOMElement} element Element or HTML string to compile into a template function.\n * @param {function(angular.Scope, cloneAttachFn=)} transclude function available to directives - DEPRECATED.\n *\n * <div class=\"alert alert-error\">\n * **Note:** Passing a `transclude` function to the $compile function is deprecated, as it\n *   e.g. will not use the right outer scope. Please pass the transclude function as a\n *   `parentBoundTranscludeFn` to the link function instead.\n * </div>\n *\n * @param {number} maxPriority only apply directives lower than given priority (Only effects the\n *                 root element(s), not their children)\n * @returns {function(scope, cloneAttachFn=, options=)} a link function which is used to bind template\n * (a DOM element/tree) to a scope. Where:\n *\n *  * `scope` - A {@link ng.$rootScope.Scope Scope} to bind to.\n *  * `cloneAttachFn` - If `cloneAttachFn` is provided, then the link function will clone the\n *  `template` and call the `cloneAttachFn` function allowing the caller to attach the\n *  cloned elements to the DOM document at the appropriate place. The `cloneAttachFn` is\n *  called as: <br> `cloneAttachFn(clonedElement, scope)` where:\n *\n *      * `clonedElement` - is a clone of the original `element` passed into the compiler.\n *      * `scope` - is the current scope with which the linking function is working with.\n *\n *  * `options` - An optional object hash with linking options. If `options` is provided, then the following\n *  keys may be used to control linking behavior:\n *\n *      * `parentBoundTranscludeFn` - the transclude function made available to\n *        directives; if given, it will be passed through to the link functions of\n *        directives found in `element` during compilation.\n *      * `transcludeControllers` - an object hash with keys that map controller names\n *        to controller instances; if given, it will make the controllers\n *        available to directives.\n *      * `futureParentElement` - defines the parent to which the `cloneAttachFn` will add\n *        the cloned elements; only needed for transcludes that are allowed to contain non html\n *        elements (e.g. SVG elements). See also the directive.controller property.\n *\n * Calling the linking function returns the element of the template. It is either the original\n * element passed in, or the clone of the element if the `cloneAttachFn` is provided.\n *\n * After linking the view is not updated until after a call to $digest which typically is done by\n * Angular automatically.\n *\n * If you need access to the bound view, there are two ways to do it:\n *\n * - If you are not asking the linking function to clone the template, create the DOM element(s)\n *   before you send them to the compiler and keep this reference around.\n *   ```js\n *     var element = $compile('<p>{{total}}</p>')(scope);\n *   ```\n *\n * - if on the other hand, you need the element to be cloned, the view reference from the original\n *   example would not point to the clone, but rather to the original template that was cloned. In\n *   this case, you can access the clone via the cloneAttachFn:\n *   ```js\n *     var templateElement = angular.element('<p>{{total}}</p>'),\n *         scope = ....;\n *\n *     var clonedElement = $compile(templateElement)(scope, function(clonedElement, scope) {\n *       //attach the clone to DOM document at the right place\n *     });\n *\n *     //now we have reference to the cloned DOM via `clonedElement`\n *   ```\n *\n *\n * For information on how the compiler works, see the\n * {@link guide/compiler Angular HTML Compiler} section of the Developer Guide.\n */\n\nvar $compileMinErr = minErr('$compile');\n\n/**\n * @ngdoc provider\n * @name $compileProvider\n *\n * @description\n */\n$CompileProvider.$inject = ['$provide', '$$sanitizeUriProvider'];\nfunction $CompileProvider($provide, $$sanitizeUriProvider) {\n  var hasDirectives = {},\n      Suffix = 'Directive',\n      COMMENT_DIRECTIVE_REGEXP = /^\\s*directive\\:\\s*([\\w\\-]+)\\s+(.*)$/,\n      CLASS_DIRECTIVE_REGEXP = /(([\\w\\-]+)(?:\\:([^;]+))?;?)/,\n      ALL_OR_NOTHING_ATTRS = makeMap('ngSrc,ngSrcset,src,srcset'),\n      REQUIRE_PREFIX_REGEXP = /^(?:(\\^\\^?)?(\\?)?(\\^\\^?)?)?/;\n\n  // Ref: http://developers.whatwg.org/webappapis.html#event-handler-idl-attributes\n  // The assumption is that future DOM event attribute names will begin with\n  // 'on' and be composed of only English letters.\n  var EVENT_HANDLER_ATTR_REGEXP = /^(on[a-z]+|formaction)$/;\n\n  function parseIsolateBindings(scope, directiveName) {\n    var LOCAL_REGEXP = /^\\s*([@&]|=(\\*?))(\\??)\\s*(\\w*)\\s*$/;\n\n    var bindings = {};\n\n    forEach(scope, function(definition, scopeName) {\n      var match = definition.match(LOCAL_REGEXP);\n\n      if (!match) {\n        throw $compileMinErr('iscp',\n            \"Invalid isolate scope definition for directive '{0}'.\" +\n            \" Definition: {... {1}: '{2}' ...}\",\n            directiveName, scopeName, definition);\n      }\n\n      bindings[scopeName] = {\n        mode: match[1][0],\n        collection: match[2] === '*',\n        optional: match[3] === '?',\n        attrName: match[4] || scopeName\n      };\n    });\n\n    return bindings;\n  }\n\n  /**\n   * @ngdoc method\n   * @name $compileProvider#directive\n   * @kind function\n   *\n   * @description\n   * Register a new directive with the compiler.\n   *\n   * @param {string|Object} name Name of the directive in camel-case (i.e. <code>ngBind</code> which\n   *    will match as <code>ng-bind</code>), or an object map of directives where the keys are the\n   *    names and the values are the factories.\n   * @param {Function|Array} directiveFactory An injectable directive factory function. See\n   *    {@link guide/directive} for more info.\n   * @returns {ng.$compileProvider} Self for chaining.\n   */\n   this.directive = function registerDirective(name, directiveFactory) {\n    assertNotHasOwnProperty(name, 'directive');\n    if (isString(name)) {\n      assertArg(directiveFactory, 'directiveFactory');\n      if (!hasDirectives.hasOwnProperty(name)) {\n        hasDirectives[name] = [];\n        $provide.factory(name + Suffix, ['$injector', '$exceptionHandler',\n          function($injector, $exceptionHandler) {\n            var directives = [];\n            forEach(hasDirectives[name], function(directiveFactory, index) {\n              try {\n                var directive = $injector.invoke(directiveFactory);\n                if (isFunction(directive)) {\n                  directive = { compile: valueFn(directive) };\n                } else if (!directive.compile && directive.link) {\n                  directive.compile = valueFn(directive.link);\n                }\n                directive.priority = directive.priority || 0;\n                directive.index = index;\n                directive.name = directive.name || name;\n                directive.require = directive.require || (directive.controller && directive.name);\n                directive.restrict = directive.restrict || 'EA';\n                if (isObject(directive.scope)) {\n                  directive.$$isolateBindings = parseIsolateBindings(directive.scope, directive.name);\n                }\n                directives.push(directive);\n              } catch (e) {\n                $exceptionHandler(e);\n              }\n            });\n            return directives;\n          }]);\n      }\n      hasDirectives[name].push(directiveFactory);\n    } else {\n      forEach(name, reverseParams(registerDirective));\n    }\n    return this;\n  };\n\n\n  /**\n   * @ngdoc method\n   * @name $compileProvider#aHrefSanitizationWhitelist\n   * @kind function\n   *\n   * @description\n   * Retrieves or overrides the default regular expression that is used for whitelisting of safe\n   * urls during a[href] sanitization.\n   *\n   * The sanitization is a security measure aimed at preventing XSS attacks via html links.\n   *\n   * Any url about to be assigned to a[href] via data-binding is first normalized and turned into\n   * an absolute url. Afterwards, the url is matched against the `aHrefSanitizationWhitelist`\n   * regular expression. If a match is found, the original url is written into the dom. Otherwise,\n   * the absolute url is prefixed with `'unsafe:'` string and only then is it written into the DOM.\n   *\n   * @param {RegExp=} regexp New regexp to whitelist urls with.\n   * @returns {RegExp|ng.$compileProvider} Current RegExp if called without value or self for\n   *    chaining otherwise.\n   */\n  this.aHrefSanitizationWhitelist = function(regexp) {\n    if (isDefined(regexp)) {\n      $$sanitizeUriProvider.aHrefSanitizationWhitelist(regexp);\n      return this;\n    } else {\n      return $$sanitizeUriProvider.aHrefSanitizationWhitelist();\n    }\n  };\n\n\n  /**\n   * @ngdoc method\n   * @name $compileProvider#imgSrcSanitizationWhitelist\n   * @kind function\n   *\n   * @description\n   * Retrieves or overrides the default regular expression that is used for whitelisting of safe\n   * urls during img[src] sanitization.\n   *\n   * The sanitization is a security measure aimed at prevent XSS attacks via html links.\n   *\n   * Any url about to be assigned to img[src] via data-binding is first normalized and turned into\n   * an absolute url. Afterwards, the url is matched against the `imgSrcSanitizationWhitelist`\n   * regular expression. If a match is found, the original url is written into the dom. Otherwise,\n   * the absolute url is prefixed with `'unsafe:'` string and only then is it written into the DOM.\n   *\n   * @param {RegExp=} regexp New regexp to whitelist urls with.\n   * @returns {RegExp|ng.$compileProvider} Current RegExp if called without value or self for\n   *    chaining otherwise.\n   */\n  this.imgSrcSanitizationWhitelist = function(regexp) {\n    if (isDefined(regexp)) {\n      $$sanitizeUriProvider.imgSrcSanitizationWhitelist(regexp);\n      return this;\n    } else {\n      return $$sanitizeUriProvider.imgSrcSanitizationWhitelist();\n    }\n  };\n\n  /**\n   * @ngdoc method\n   * @name  $compileProvider#debugInfoEnabled\n   *\n   * @param {boolean=} enabled update the debugInfoEnabled state if provided, otherwise just return the\n   * current debugInfoEnabled state\n   * @returns {*} current value if used as getter or itself (chaining) if used as setter\n   *\n   * @kind function\n   *\n   * @description\n   * Call this method to enable/disable various debug runtime information in the compiler such as adding\n   * binding information and a reference to the current scope on to DOM elements.\n   * If enabled, the compiler will add the following to DOM elements that have been bound to the scope\n   * * `ng-binding` CSS class\n   * * `$binding` data property containing an array of the binding expressions\n   *\n   * You may want to disable this in production for a significant performance boost. See\n   * {@link guide/production#disabling-debug-data Disabling Debug Data} for more.\n   *\n   * The default value is true.\n   */\n  var debugInfoEnabled = true;\n  this.debugInfoEnabled = function(enabled) {\n    if (isDefined(enabled)) {\n      debugInfoEnabled = enabled;\n      return this;\n    }\n    return debugInfoEnabled;\n  };\n\n  this.$get = [\n            '$injector', '$interpolate', '$exceptionHandler', '$templateRequest', '$parse',\n            '$controller', '$rootScope', '$document', '$sce', '$animate', '$$sanitizeUri',\n    function($injector,   $interpolate,   $exceptionHandler,   $templateRequest,   $parse,\n             $controller,   $rootScope,   $document,   $sce,   $animate,   $$sanitizeUri) {\n\n    var Attributes = function(element, attributesToCopy) {\n      if (attributesToCopy) {\n        var keys = Object.keys(attributesToCopy);\n        var i, l, key;\n\n        for (i = 0, l = keys.length; i < l; i++) {\n          key = keys[i];\n          this[key] = attributesToCopy[key];\n        }\n      } else {\n        this.$attr = {};\n      }\n\n      this.$$element = element;\n    };\n\n    Attributes.prototype = {\n      /**\n       * @ngdoc method\n       * @name $compile.directive.Attributes#$normalize\n       * @kind function\n       *\n       * @description\n       * Converts an attribute name (e.g. dash/colon/underscore-delimited string, optionally prefixed with `x-` or\n       * `data-`) to its normalized, camelCase form.\n       *\n       * Also there is special case for Moz prefix starting with upper case letter.\n       *\n       * For further information check out the guide on {@link guide/directive#matching-directives Matching Directives}\n       *\n       * @param {string} name Name to normalize\n       */\n      $normalize: directiveNormalize,\n\n\n      /**\n       * @ngdoc method\n       * @name $compile.directive.Attributes#$addClass\n       * @kind function\n       *\n       * @description\n       * Adds the CSS class value specified by the classVal parameter to the element. If animations\n       * are enabled then an animation will be triggered for the class addition.\n       *\n       * @param {string} classVal The className value that will be added to the element\n       */\n      $addClass: function(classVal) {\n        if (classVal && classVal.length > 0) {\n          $animate.addClass(this.$$element, classVal);\n        }\n      },\n\n      /**\n       * @ngdoc method\n       * @name $compile.directive.Attributes#$removeClass\n       * @kind function\n       *\n       * @description\n       * Removes the CSS class value specified by the classVal parameter from the element. If\n       * animations are enabled then an animation will be triggered for the class removal.\n       *\n       * @param {string} classVal The className value that will be removed from the element\n       */\n      $removeClass: function(classVal) {\n        if (classVal && classVal.length > 0) {\n          $animate.removeClass(this.$$element, classVal);\n        }\n      },\n\n      /**\n       * @ngdoc method\n       * @name $compile.directive.Attributes#$updateClass\n       * @kind function\n       *\n       * @description\n       * Adds and removes the appropriate CSS class values to the element based on the difference\n       * between the new and old CSS class values (specified as newClasses and oldClasses).\n       *\n       * @param {string} newClasses The current CSS className value\n       * @param {string} oldClasses The former CSS className value\n       */\n      $updateClass: function(newClasses, oldClasses) {\n        var toAdd = tokenDifference(newClasses, oldClasses);\n        if (toAdd && toAdd.length) {\n          $animate.addClass(this.$$element, toAdd);\n        }\n\n        var toRemove = tokenDifference(oldClasses, newClasses);\n        if (toRemove && toRemove.length) {\n          $animate.removeClass(this.$$element, toRemove);\n        }\n      },\n\n      /**\n       * Set a normalized attribute on the element in a way such that all directives\n       * can share the attribute. This function properly handles boolean attributes.\n       * @param {string} key Normalized key. (ie ngAttribute)\n       * @param {string|boolean} value The value to set. If `null` attribute will be deleted.\n       * @param {boolean=} writeAttr If false, does not write the value to DOM element attribute.\n       *     Defaults to true.\n       * @param {string=} attrName Optional none normalized name. Defaults to key.\n       */\n      $set: function(key, value, writeAttr, attrName) {\n        // TODO: decide whether or not to throw an error if \"class\"\n        //is set through this function since it may cause $updateClass to\n        //become unstable.\n\n        var node = this.$$element[0],\n            booleanKey = getBooleanAttrName(node, key),\n            aliasedKey = getAliasedAttrName(node, key),\n            observer = key,\n            nodeName;\n\n        if (booleanKey) {\n          this.$$element.prop(key, value);\n          attrName = booleanKey;\n        } else if (aliasedKey) {\n          this[aliasedKey] = value;\n          observer = aliasedKey;\n        }\n\n        this[key] = value;\n\n        // translate normalized key to actual key\n        if (attrName) {\n          this.$attr[key] = attrName;\n        } else {\n          attrName = this.$attr[key];\n          if (!attrName) {\n            this.$attr[key] = attrName = snake_case(key, '-');\n          }\n        }\n\n        nodeName = nodeName_(this.$$element);\n\n        if ((nodeName === 'a' && key === 'href') ||\n            (nodeName === 'img' && key === 'src')) {\n          // sanitize a[href] and img[src] values\n          this[key] = value = $$sanitizeUri(value, key === 'src');\n        } else if (nodeName === 'img' && key === 'srcset') {\n          // sanitize img[srcset] values\n          var result = \"\";\n\n          // first check if there are spaces because it's not the same pattern\n          var trimmedSrcset = trim(value);\n          //                (   999x   ,|   999w   ,|   ,|,   )\n          var srcPattern = /(\\s+\\d+x\\s*,|\\s+\\d+w\\s*,|\\s+,|,\\s+)/;\n          var pattern = /\\s/.test(trimmedSrcset) ? srcPattern : /(,)/;\n\n          // split srcset into tuple of uri and descriptor except for the last item\n          var rawUris = trimmedSrcset.split(pattern);\n\n          // for each tuples\n          var nbrUrisWith2parts = Math.floor(rawUris.length / 2);\n          for (var i = 0; i < nbrUrisWith2parts; i++) {\n            var innerIdx = i * 2;\n            // sanitize the uri\n            result += $$sanitizeUri(trim(rawUris[innerIdx]), true);\n            // add the descriptor\n            result += (\" \" + trim(rawUris[innerIdx + 1]));\n          }\n\n          // split the last item into uri and descriptor\n          var lastTuple = trim(rawUris[i * 2]).split(/\\s/);\n\n          // sanitize the last uri\n          result += $$sanitizeUri(trim(lastTuple[0]), true);\n\n          // and add the last descriptor if any\n          if (lastTuple.length === 2) {\n            result += (\" \" + trim(lastTuple[1]));\n          }\n          this[key] = value = result;\n        }\n\n        if (writeAttr !== false) {\n          if (value === null || value === undefined) {\n            this.$$element.removeAttr(attrName);\n          } else {\n            this.$$element.attr(attrName, value);\n          }\n        }\n\n        // fire observers\n        var $$observers = this.$$observers;\n        $$observers && forEach($$observers[observer], function(fn) {\n          try {\n            fn(value);\n          } catch (e) {\n            $exceptionHandler(e);\n          }\n        });\n      },\n\n\n      /**\n       * @ngdoc method\n       * @name $compile.directive.Attributes#$observe\n       * @kind function\n       *\n       * @description\n       * Observes an interpolated attribute.\n       *\n       * The observer function will be invoked once during the next `$digest` following\n       * compilation. The observer is then invoked whenever the interpolated value\n       * changes.\n       *\n       * @param {string} key Normalized key. (ie ngAttribute) .\n       * @param {function(interpolatedValue)} fn Function that will be called whenever\n                the interpolated value of the attribute changes.\n       *        See the {@link guide/directive#text-and-attribute-bindings Directives} guide for more info.\n       * @returns {function()} Returns a deregistration function for this observer.\n       */\n      $observe: function(key, fn) {\n        var attrs = this,\n            $$observers = (attrs.$$observers || (attrs.$$observers = createMap())),\n            listeners = ($$observers[key] || ($$observers[key] = []));\n\n        listeners.push(fn);\n        $rootScope.$evalAsync(function() {\n          if (!listeners.$$inter && attrs.hasOwnProperty(key)) {\n            // no one registered attribute interpolation function, so lets call it manually\n            fn(attrs[key]);\n          }\n        });\n\n        return function() {\n          arrayRemove(listeners, fn);\n        };\n      }\n    };\n\n\n    function safeAddClass($element, className) {\n      try {\n        $element.addClass(className);\n      } catch (e) {\n        // ignore, since it means that we are trying to set class on\n        // SVG element, where class name is read-only.\n      }\n    }\n\n\n    var startSymbol = $interpolate.startSymbol(),\n        endSymbol = $interpolate.endSymbol(),\n        denormalizeTemplate = (startSymbol == '{{' || endSymbol  == '}}')\n            ? identity\n            : function denormalizeTemplate(template) {\n              return template.replace(/\\{\\{/g, startSymbol).replace(/}}/g, endSymbol);\n        },\n        NG_ATTR_BINDING = /^ngAttr[A-Z]/;\n\n    compile.$$addBindingInfo = debugInfoEnabled ? function $$addBindingInfo($element, binding) {\n      var bindings = $element.data('$binding') || [];\n\n      if (isArray(binding)) {\n        bindings = bindings.concat(binding);\n      } else {\n        bindings.push(binding);\n      }\n\n      $element.data('$binding', bindings);\n    } : noop;\n\n    compile.$$addBindingClass = debugInfoEnabled ? function $$addBindingClass($element) {\n      safeAddClass($element, 'ng-binding');\n    } : noop;\n\n    compile.$$addScopeInfo = debugInfoEnabled ? function $$addScopeInfo($element, scope, isolated, noTemplate) {\n      var dataName = isolated ? (noTemplate ? '$isolateScopeNoTemplate' : '$isolateScope') : '$scope';\n      $element.data(dataName, scope);\n    } : noop;\n\n    compile.$$addScopeClass = debugInfoEnabled ? function $$addScopeClass($element, isolated) {\n      safeAddClass($element, isolated ? 'ng-isolate-scope' : 'ng-scope');\n    } : noop;\n\n    return compile;\n\n    //================================\n\n    function compile($compileNodes, transcludeFn, maxPriority, ignoreDirective,\n                        previousCompileContext) {\n      if (!($compileNodes instanceof jqLite)) {\n        // jquery always rewraps, whereas we need to preserve the original selector so that we can\n        // modify it.\n        $compileNodes = jqLite($compileNodes);\n      }\n      // We can not compile top level text elements since text nodes can be merged and we will\n      // not be able to attach scope data to them, so we will wrap them in <span>\n      forEach($compileNodes, function(node, index) {\n        if (node.nodeType == NODE_TYPE_TEXT && node.nodeValue.match(/\\S+/) /* non-empty */ ) {\n          $compileNodes[index] = jqLite(node).wrap('<span></span>').parent()[0];\n        }\n      });\n      var compositeLinkFn =\n              compileNodes($compileNodes, transcludeFn, $compileNodes,\n                           maxPriority, ignoreDirective, previousCompileContext);\n      compile.$$addScopeClass($compileNodes);\n      var namespace = null;\n      return function publicLinkFn(scope, cloneConnectFn, options) {\n        assertArg(scope, 'scope');\n\n        options = options || {};\n        var parentBoundTranscludeFn = options.parentBoundTranscludeFn,\n          transcludeControllers = options.transcludeControllers,\n          futureParentElement = options.futureParentElement;\n\n        // When `parentBoundTranscludeFn` is passed, it is a\n        // `controllersBoundTransclude` function (it was previously passed\n        // as `transclude` to directive.link) so we must unwrap it to get\n        // its `boundTranscludeFn`\n        if (parentBoundTranscludeFn && parentBoundTranscludeFn.$$boundTransclude) {\n          parentBoundTranscludeFn = parentBoundTranscludeFn.$$boundTransclude;\n        }\n\n        if (!namespace) {\n          namespace = detectNamespaceForChildElements(futureParentElement);\n        }\n        var $linkNode;\n        if (namespace !== 'html') {\n          // When using a directive with replace:true and templateUrl the $compileNodes\n          // (or a child element inside of them)\n          // might change, so we need to recreate the namespace adapted compileNodes\n          // for call to the link function.\n          // Note: This will already clone the nodes...\n          $linkNode = jqLite(\n            wrapTemplate(namespace, jqLite('<div>').append($compileNodes).html())\n          );\n        } else if (cloneConnectFn) {\n          // important!!: we must call our jqLite.clone() since the jQuery one is trying to be smart\n          // and sometimes changes the structure of the DOM.\n          $linkNode = JQLitePrototype.clone.call($compileNodes);\n        } else {\n          $linkNode = $compileNodes;\n        }\n\n        if (transcludeControllers) {\n          for (var controllerName in transcludeControllers) {\n            $linkNode.data('$' + controllerName + 'Controller', transcludeControllers[controllerName].instance);\n          }\n        }\n\n        compile.$$addScopeInfo($linkNode, scope);\n\n        if (cloneConnectFn) cloneConnectFn($linkNode, scope);\n        if (compositeLinkFn) compositeLinkFn(scope, $linkNode, $linkNode, parentBoundTranscludeFn);\n        return $linkNode;\n      };\n    }\n\n    function detectNamespaceForChildElements(parentElement) {\n      // TODO: Make this detect MathML as well...\n      var node = parentElement && parentElement[0];\n      if (!node) {\n        return 'html';\n      } else {\n        return nodeName_(node) !== 'foreignobject' && node.toString().match(/SVG/) ? 'svg' : 'html';\n      }\n    }\n\n    /**\n     * Compile function matches each node in nodeList against the directives. Once all directives\n     * for a particular node are collected their compile functions are executed. The compile\n     * functions return values - the linking functions - are combined into a composite linking\n     * function, which is the a linking function for the node.\n     *\n     * @param {NodeList} nodeList an array of nodes or NodeList to compile\n     * @param {function(angular.Scope, cloneAttachFn=)} transcludeFn A linking function, where the\n     *        scope argument is auto-generated to the new child of the transcluded parent scope.\n     * @param {DOMElement=} $rootElement If the nodeList is the root of the compilation tree then\n     *        the rootElement must be set the jqLite collection of the compile root. This is\n     *        needed so that the jqLite collection items can be replaced with widgets.\n     * @param {number=} maxPriority Max directive priority.\n     * @returns {Function} A composite linking function of all of the matched directives or null.\n     */\n    function compileNodes(nodeList, transcludeFn, $rootElement, maxPriority, ignoreDirective,\n                            previousCompileContext) {\n      var linkFns = [],\n          attrs, directives, nodeLinkFn, childNodes, childLinkFn, linkFnFound, nodeLinkFnFound;\n\n      for (var i = 0; i < nodeList.length; i++) {\n        attrs = new Attributes();\n\n        // we must always refer to nodeList[i] since the nodes can be replaced underneath us.\n        directives = collectDirectives(nodeList[i], [], attrs, i === 0 ? maxPriority : undefined,\n                                        ignoreDirective);\n\n        nodeLinkFn = (directives.length)\n            ? applyDirectivesToNode(directives, nodeList[i], attrs, transcludeFn, $rootElement,\n                                      null, [], [], previousCompileContext)\n            : null;\n\n        if (nodeLinkFn && nodeLinkFn.scope) {\n          compile.$$addScopeClass(attrs.$$element);\n        }\n\n        childLinkFn = (nodeLinkFn && nodeLinkFn.terminal ||\n                      !(childNodes = nodeList[i].childNodes) ||\n                      !childNodes.length)\n            ? null\n            : compileNodes(childNodes,\n                 nodeLinkFn ? (\n                  (nodeLinkFn.transcludeOnThisElement || !nodeLinkFn.templateOnThisElement)\n                     && nodeLinkFn.transclude) : transcludeFn);\n\n        if (nodeLinkFn || childLinkFn) {\n          linkFns.push(i, nodeLinkFn, childLinkFn);\n          linkFnFound = true;\n          nodeLinkFnFound = nodeLinkFnFound || nodeLinkFn;\n        }\n\n        //use the previous context only for the first element in the virtual group\n        previousCompileContext = null;\n      }\n\n      // return a linking function if we have found anything, null otherwise\n      return linkFnFound ? compositeLinkFn : null;\n\n      function compositeLinkFn(scope, nodeList, $rootElement, parentBoundTranscludeFn) {\n        var nodeLinkFn, childLinkFn, node, childScope, i, ii, idx, childBoundTranscludeFn;\n        var stableNodeList;\n\n\n        if (nodeLinkFnFound) {\n          // copy nodeList so that if a nodeLinkFn removes or adds an element at this DOM level our\n          // offsets don't get screwed up\n          var nodeListLength = nodeList.length;\n          stableNodeList = new Array(nodeListLength);\n\n          // create a sparse array by only copying the elements which have a linkFn\n          for (i = 0; i < linkFns.length; i+=3) {\n            idx = linkFns[i];\n            stableNodeList[idx] = nodeList[idx];\n          }\n        } else {\n          stableNodeList = nodeList;\n        }\n\n        for (i = 0, ii = linkFns.length; i < ii;) {\n          node = stableNodeList[linkFns[i++]];\n          nodeLinkFn = linkFns[i++];\n          childLinkFn = linkFns[i++];\n\n          if (nodeLinkFn) {\n            if (nodeLinkFn.scope) {\n              childScope = scope.$new();\n              compile.$$addScopeInfo(jqLite(node), childScope);\n            } else {\n              childScope = scope;\n            }\n\n            if (nodeLinkFn.transcludeOnThisElement) {\n              childBoundTranscludeFn = createBoundTranscludeFn(\n                  scope, nodeLinkFn.transclude, parentBoundTranscludeFn,\n                  nodeLinkFn.elementTranscludeOnThisElement);\n\n            } else if (!nodeLinkFn.templateOnThisElement && parentBoundTranscludeFn) {\n              childBoundTranscludeFn = parentBoundTranscludeFn;\n\n            } else if (!parentBoundTranscludeFn && transcludeFn) {\n              childBoundTranscludeFn = createBoundTranscludeFn(scope, transcludeFn);\n\n            } else {\n              childBoundTranscludeFn = null;\n            }\n\n            nodeLinkFn(childLinkFn, childScope, node, $rootElement, childBoundTranscludeFn);\n\n          } else if (childLinkFn) {\n            childLinkFn(scope, node.childNodes, undefined, parentBoundTranscludeFn);\n          }\n        }\n      }\n    }\n\n    function createBoundTranscludeFn(scope, transcludeFn, previousBoundTranscludeFn, elementTransclusion) {\n\n      var boundTranscludeFn = function(transcludedScope, cloneFn, controllers, futureParentElement, containingScope) {\n\n        if (!transcludedScope) {\n          transcludedScope = scope.$new(false, containingScope);\n          transcludedScope.$$transcluded = true;\n        }\n\n        return transcludeFn(transcludedScope, cloneFn, {\n          parentBoundTranscludeFn: previousBoundTranscludeFn,\n          transcludeControllers: controllers,\n          futureParentElement: futureParentElement\n        });\n      };\n\n      return boundTranscludeFn;\n    }\n\n    /**\n     * Looks for directives on the given node and adds them to the directive collection which is\n     * sorted.\n     *\n     * @param node Node to search.\n     * @param directives An array to which the directives are added to. This array is sorted before\n     *        the function returns.\n     * @param attrs The shared attrs object which is used to populate the normalized attributes.\n     * @param {number=} maxPriority Max directive priority.\n     */\n    function collectDirectives(node, directives, attrs, maxPriority, ignoreDirective) {\n      var nodeType = node.nodeType,\n          attrsMap = attrs.$attr,\n          match,\n          className;\n\n      switch (nodeType) {\n        case NODE_TYPE_ELEMENT: /* Element */\n          // use the node name: <directive>\n          addDirective(directives,\n              directiveNormalize(nodeName_(node)), 'E', maxPriority, ignoreDirective);\n\n          // iterate over the attributes\n          for (var attr, name, nName, ngAttrName, value, isNgAttr, nAttrs = node.attributes,\n                   j = 0, jj = nAttrs && nAttrs.length; j < jj; j++) {\n            var attrStartName = false;\n            var attrEndName = false;\n\n            attr = nAttrs[j];\n            name = attr.name;\n            value = trim(attr.value);\n\n            // support ngAttr attribute binding\n            ngAttrName = directiveNormalize(name);\n            if (isNgAttr = NG_ATTR_BINDING.test(ngAttrName)) {\n              name = name.replace(PREFIX_REGEXP, '')\n                .substr(8).replace(/_(.)/g, function(match, letter) {\n                  return letter.toUpperCase();\n                });\n            }\n\n            var directiveNName = ngAttrName.replace(/(Start|End)$/, '');\n            if (directiveIsMultiElement(directiveNName)) {\n              if (ngAttrName === directiveNName + 'Start') {\n                attrStartName = name;\n                attrEndName = name.substr(0, name.length - 5) + 'end';\n                name = name.substr(0, name.length - 6);\n              }\n            }\n\n            nName = directiveNormalize(name.toLowerCase());\n            attrsMap[nName] = name;\n            if (isNgAttr || !attrs.hasOwnProperty(nName)) {\n                attrs[nName] = value;\n                if (getBooleanAttrName(node, nName)) {\n                  attrs[nName] = true; // presence means true\n                }\n            }\n            addAttrInterpolateDirective(node, directives, value, nName, isNgAttr);\n            addDirective(directives, nName, 'A', maxPriority, ignoreDirective, attrStartName,\n                          attrEndName);\n          }\n\n          // use class as directive\n          className = node.className;\n          if (isObject(className)) {\n              // Maybe SVGAnimatedString\n              className = className.animVal;\n          }\n          if (isString(className) && className !== '') {\n            while (match = CLASS_DIRECTIVE_REGEXP.exec(className)) {\n              nName = directiveNormalize(match[2]);\n              if (addDirective(directives, nName, 'C', maxPriority, ignoreDirective)) {\n                attrs[nName] = trim(match[3]);\n              }\n              className = className.substr(match.index + match[0].length);\n            }\n          }\n          break;\n        case NODE_TYPE_TEXT: /* Text Node */\n          addTextInterpolateDirective(directives, node.nodeValue);\n          break;\n        case NODE_TYPE_COMMENT: /* Comment */\n          try {\n            match = COMMENT_DIRECTIVE_REGEXP.exec(node.nodeValue);\n            if (match) {\n              nName = directiveNormalize(match[1]);\n              if (addDirective(directives, nName, 'M', maxPriority, ignoreDirective)) {\n                attrs[nName] = trim(match[2]);\n              }\n            }\n          } catch (e) {\n            // turns out that under some circumstances IE9 throws errors when one attempts to read\n            // comment's node value.\n            // Just ignore it and continue. (Can't seem to reproduce in test case.)\n          }\n          break;\n      }\n\n      directives.sort(byPriority);\n      return directives;\n    }\n\n    /**\n     * Given a node with an directive-start it collects all of the siblings until it finds\n     * directive-end.\n     * @param node\n     * @param attrStart\n     * @param attrEnd\n     * @returns {*}\n     */\n    function groupScan(node, attrStart, attrEnd) {\n      var nodes = [];\n      var depth = 0;\n      if (attrStart && node.hasAttribute && node.hasAttribute(attrStart)) {\n        do {\n          if (!node) {\n            throw $compileMinErr('uterdir',\n                      \"Unterminated attribute, found '{0}' but no matching '{1}' found.\",\n                      attrStart, attrEnd);\n          }\n          if (node.nodeType == NODE_TYPE_ELEMENT) {\n            if (node.hasAttribute(attrStart)) depth++;\n            if (node.hasAttribute(attrEnd)) depth--;\n          }\n          nodes.push(node);\n          node = node.nextSibling;\n        } while (depth > 0);\n      } else {\n        nodes.push(node);\n      }\n\n      return jqLite(nodes);\n    }\n\n    /**\n     * Wrapper for linking function which converts normal linking function into a grouped\n     * linking function.\n     * @param linkFn\n     * @param attrStart\n     * @param attrEnd\n     * @returns {Function}\n     */\n    function groupElementsLinkFnWrapper(linkFn, attrStart, attrEnd) {\n      return function(scope, element, attrs, controllers, transcludeFn) {\n        element = groupScan(element[0], attrStart, attrEnd);\n        return linkFn(scope, element, attrs, controllers, transcludeFn);\n      };\n    }\n\n    /**\n     * Once the directives have been collected, their compile functions are executed. This method\n     * is responsible for inlining directive templates as well as terminating the application\n     * of the directives if the terminal directive has been reached.\n     *\n     * @param {Array} directives Array of collected directives to execute their compile function.\n     *        this needs to be pre-sorted by priority order.\n     * @param {Node} compileNode The raw DOM node to apply the compile functions to\n     * @param {Object} templateAttrs The shared attribute function\n     * @param {function(angular.Scope, cloneAttachFn=)} transcludeFn A linking function, where the\n     *                                                  scope argument is auto-generated to the new\n     *                                                  child of the transcluded parent scope.\n     * @param {JQLite} jqCollection If we are working on the root of the compile tree then this\n     *                              argument has the root jqLite array so that we can replace nodes\n     *                              on it.\n     * @param {Object=} originalReplaceDirective An optional directive that will be ignored when\n     *                                           compiling the transclusion.\n     * @param {Array.<Function>} preLinkFns\n     * @param {Array.<Function>} postLinkFns\n     * @param {Object} previousCompileContext Context used for previous compilation of the current\n     *                                        node\n     * @returns {Function} linkFn\n     */\n    function applyDirectivesToNode(directives, compileNode, templateAttrs, transcludeFn,\n                                   jqCollection, originalReplaceDirective, preLinkFns, postLinkFns,\n                                   previousCompileContext) {\n      previousCompileContext = previousCompileContext || {};\n\n      var terminalPriority = -Number.MAX_VALUE,\n          newScopeDirective,\n          controllerDirectives = previousCompileContext.controllerDirectives,\n          controllers,\n          newIsolateScopeDirective = previousCompileContext.newIsolateScopeDirective,\n          templateDirective = previousCompileContext.templateDirective,\n          nonTlbTranscludeDirective = previousCompileContext.nonTlbTranscludeDirective,\n          hasTranscludeDirective = false,\n          hasTemplate = false,\n          hasElementTranscludeDirective = previousCompileContext.hasElementTranscludeDirective,\n          $compileNode = templateAttrs.$$element = jqLite(compileNode),\n          directive,\n          directiveName,\n          $template,\n          replaceDirective = originalReplaceDirective,\n          childTranscludeFn = transcludeFn,\n          linkFn,\n          directiveValue;\n\n      // executes all directives on the current element\n      for (var i = 0, ii = directives.length; i < ii; i++) {\n        directive = directives[i];\n        var attrStart = directive.$$start;\n        var attrEnd = directive.$$end;\n\n        // collect multiblock sections\n        if (attrStart) {\n          $compileNode = groupScan(compileNode, attrStart, attrEnd);\n        }\n        $template = undefined;\n\n        if (terminalPriority > directive.priority) {\n          break; // prevent further processing of directives\n        }\n\n        if (directiveValue = directive.scope) {\n\n          // skip the check for directives with async templates, we'll check the derived sync\n          // directive when the template arrives\n          if (!directive.templateUrl) {\n            if (isObject(directiveValue)) {\n              // This directive is trying to add an isolated scope.\n              // Check that there is no scope of any kind already\n              assertNoDuplicate('new/isolated scope', newIsolateScopeDirective || newScopeDirective,\n                                directive, $compileNode);\n              newIsolateScopeDirective = directive;\n            } else {\n              // This directive is trying to add a child scope.\n              // Check that there is no isolated scope already\n              assertNoDuplicate('new/isolated scope', newIsolateScopeDirective, directive,\n                                $compileNode);\n            }\n          }\n\n          newScopeDirective = newScopeDirective || directive;\n        }\n\n        directiveName = directive.name;\n\n        if (!directive.templateUrl && directive.controller) {\n          directiveValue = directive.controller;\n          controllerDirectives = controllerDirectives || {};\n          assertNoDuplicate(\"'\" + directiveName + \"' controller\",\n              controllerDirectives[directiveName], directive, $compileNode);\n          controllerDirectives[directiveName] = directive;\n        }\n\n        if (directiveValue = directive.transclude) {\n          hasTranscludeDirective = true;\n\n          // Special case ngIf and ngRepeat so that we don't complain about duplicate transclusion.\n          // This option should only be used by directives that know how to safely handle element transclusion,\n          // where the transcluded nodes are added or replaced after linking.\n          if (!directive.$$tlb) {\n            assertNoDuplicate('transclusion', nonTlbTranscludeDirective, directive, $compileNode);\n            nonTlbTranscludeDirective = directive;\n          }\n\n          if (directiveValue == 'element') {\n            hasElementTranscludeDirective = true;\n            terminalPriority = directive.priority;\n            $template = $compileNode;\n            $compileNode = templateAttrs.$$element =\n                jqLite(document.createComment(' ' + directiveName + ': ' +\n                                              templateAttrs[directiveName] + ' '));\n            compileNode = $compileNode[0];\n            replaceWith(jqCollection, sliceArgs($template), compileNode);\n\n            childTranscludeFn = compile($template, transcludeFn, terminalPriority,\n                                        replaceDirective && replaceDirective.name, {\n                                          // Don't pass in:\n                                          // - controllerDirectives - otherwise we'll create duplicates controllers\n                                          // - newIsolateScopeDirective or templateDirective - combining templates with\n                                          //   element transclusion doesn't make sense.\n                                          //\n                                          // We need only nonTlbTranscludeDirective so that we prevent putting transclusion\n                                          // on the same element more than once.\n                                          nonTlbTranscludeDirective: nonTlbTranscludeDirective\n                                        });\n          } else {\n            $template = jqLite(jqLiteClone(compileNode)).contents();\n            $compileNode.empty(); // clear contents\n            childTranscludeFn = compile($template, transcludeFn);\n          }\n        }\n\n        if (directive.template) {\n          hasTemplate = true;\n          assertNoDuplicate('template', templateDirective, directive, $compileNode);\n          templateDirective = directive;\n\n          directiveValue = (isFunction(directive.template))\n              ? directive.template($compileNode, templateAttrs)\n              : directive.template;\n\n          directiveValue = denormalizeTemplate(directiveValue);\n\n          if (directive.replace) {\n            replaceDirective = directive;\n            if (jqLiteIsTextNode(directiveValue)) {\n              $template = [];\n            } else {\n              $template = removeComments(wrapTemplate(directive.templateNamespace, trim(directiveValue)));\n            }\n            compileNode = $template[0];\n\n            if ($template.length != 1 || compileNode.nodeType !== NODE_TYPE_ELEMENT) {\n              throw $compileMinErr('tplrt',\n                  \"Template for directive '{0}' must have exactly one root element. {1}\",\n                  directiveName, '');\n            }\n\n            replaceWith(jqCollection, $compileNode, compileNode);\n\n            var newTemplateAttrs = {$attr: {}};\n\n            // combine directives from the original node and from the template:\n            // - take the array of directives for this element\n            // - split it into two parts, those that already applied (processed) and those that weren't (unprocessed)\n            // - collect directives from the template and sort them by priority\n            // - combine directives as: processed + template + unprocessed\n            var templateDirectives = collectDirectives(compileNode, [], newTemplateAttrs);\n            var unprocessedDirectives = directives.splice(i + 1, directives.length - (i + 1));\n\n            if (newIsolateScopeDirective) {\n              markDirectivesAsIsolate(templateDirectives);\n            }\n            directives = directives.concat(templateDirectives).concat(unprocessedDirectives);\n            mergeTemplateAttributes(templateAttrs, newTemplateAttrs);\n\n            ii = directives.length;\n          } else {\n            $compileNode.html(directiveValue);\n          }\n        }\n\n        if (directive.templateUrl) {\n          hasTemplate = true;\n          assertNoDuplicate('template', templateDirective, directive, $compileNode);\n          templateDirective = directive;\n\n          if (directive.replace) {\n            replaceDirective = directive;\n          }\n\n          nodeLinkFn = compileTemplateUrl(directives.splice(i, directives.length - i), $compileNode,\n              templateAttrs, jqCollection, hasTranscludeDirective && childTranscludeFn, preLinkFns, postLinkFns, {\n                controllerDirectives: controllerDirectives,\n                newIsolateScopeDirective: newIsolateScopeDirective,\n                templateDirective: templateDirective,\n                nonTlbTranscludeDirective: nonTlbTranscludeDirective\n              });\n          ii = directives.length;\n        } else if (directive.compile) {\n          try {\n            linkFn = directive.compile($compileNode, templateAttrs, childTranscludeFn);\n            if (isFunction(linkFn)) {\n              addLinkFns(null, linkFn, attrStart, attrEnd);\n            } else if (linkFn) {\n              addLinkFns(linkFn.pre, linkFn.post, attrStart, attrEnd);\n            }\n          } catch (e) {\n            $exceptionHandler(e, startingTag($compileNode));\n          }\n        }\n\n        if (directive.terminal) {\n          nodeLinkFn.terminal = true;\n          terminalPriority = Math.max(terminalPriority, directive.priority);\n        }\n\n      }\n\n      nodeLinkFn.scope = newScopeDirective && newScopeDirective.scope === true;\n      nodeLinkFn.transcludeOnThisElement = hasTranscludeDirective;\n      nodeLinkFn.elementTranscludeOnThisElement = hasElementTranscludeDirective;\n      nodeLinkFn.templateOnThisElement = hasTemplate;\n      nodeLinkFn.transclude = childTranscludeFn;\n\n      previousCompileContext.hasElementTranscludeDirective = hasElementTranscludeDirective;\n\n      // might be normal or delayed nodeLinkFn depending on if templateUrl is present\n      return nodeLinkFn;\n\n      ////////////////////\n\n      function addLinkFns(pre, post, attrStart, attrEnd) {\n        if (pre) {\n          if (attrStart) pre = groupElementsLinkFnWrapper(pre, attrStart, attrEnd);\n          pre.require = directive.require;\n          pre.directiveName = directiveName;\n          if (newIsolateScopeDirective === directive || directive.$$isolateScope) {\n            pre = cloneAndAnnotateFn(pre, {isolateScope: true});\n          }\n          preLinkFns.push(pre);\n        }\n        if (post) {\n          if (attrStart) post = groupElementsLinkFnWrapper(post, attrStart, attrEnd);\n          post.require = directive.require;\n          post.directiveName = directiveName;\n          if (newIsolateScopeDirective === directive || directive.$$isolateScope) {\n            post = cloneAndAnnotateFn(post, {isolateScope: true});\n          }\n          postLinkFns.push(post);\n        }\n      }\n\n\n      function getControllers(directiveName, require, $element, elementControllers) {\n        var value, retrievalMethod = 'data', optional = false;\n        var $searchElement = $element;\n        var match;\n        if (isString(require)) {\n          match = require.match(REQUIRE_PREFIX_REGEXP);\n          require = require.substring(match[0].length);\n\n          if (match[3]) {\n            if (match[1]) match[3] = null;\n            else match[1] = match[3];\n          }\n          if (match[1] === '^') {\n            retrievalMethod = 'inheritedData';\n          } else if (match[1] === '^^') {\n            retrievalMethod = 'inheritedData';\n            $searchElement = $element.parent();\n          }\n          if (match[2] === '?') {\n            optional = true;\n          }\n\n          value = null;\n\n          if (elementControllers && retrievalMethod === 'data') {\n            if (value = elementControllers[require]) {\n              value = value.instance;\n            }\n          }\n          value = value || $searchElement[retrievalMethod]('$' + require + 'Controller');\n\n          if (!value && !optional) {\n            throw $compileMinErr('ctreq',\n                \"Controller '{0}', required by directive '{1}', can't be found!\",\n                require, directiveName);\n          }\n          return value || null;\n        } else if (isArray(require)) {\n          value = [];\n          forEach(require, function(require) {\n            value.push(getControllers(directiveName, require, $element, elementControllers));\n          });\n        }\n        return value;\n      }\n\n\n      function nodeLinkFn(childLinkFn, scope, linkNode, $rootElement, boundTranscludeFn) {\n        var i, ii, linkFn, controller, isolateScope, elementControllers, transcludeFn, $element,\n            attrs;\n\n        if (compileNode === linkNode) {\n          attrs = templateAttrs;\n          $element = templateAttrs.$$element;\n        } else {\n          $element = jqLite(linkNode);\n          attrs = new Attributes($element, templateAttrs);\n        }\n\n        if (newIsolateScopeDirective) {\n          isolateScope = scope.$new(true);\n        }\n\n        if (boundTranscludeFn) {\n          // track `boundTranscludeFn` so it can be unwrapped if `transcludeFn`\n          // is later passed as `parentBoundTranscludeFn` to `publicLinkFn`\n          transcludeFn = controllersBoundTransclude;\n          transcludeFn.$$boundTransclude = boundTranscludeFn;\n        }\n\n        if (controllerDirectives) {\n          // TODO: merge `controllers` and `elementControllers` into single object.\n          controllers = {};\n          elementControllers = {};\n          forEach(controllerDirectives, function(directive) {\n            var locals = {\n              $scope: directive === newIsolateScopeDirective || directive.$$isolateScope ? isolateScope : scope,\n              $element: $element,\n              $attrs: attrs,\n              $transclude: transcludeFn\n            }, controllerInstance;\n\n            controller = directive.controller;\n            if (controller == '@') {\n              controller = attrs[directive.name];\n            }\n\n            controllerInstance = $controller(controller, locals, true, directive.controllerAs);\n\n            // For directives with element transclusion the element is a comment,\n            // but jQuery .data doesn't support attaching data to comment nodes as it's hard to\n            // clean up (http://bugs.jquery.com/ticket/8335).\n            // Instead, we save the controllers for the element in a local hash and attach to .data\n            // later, once we have the actual element.\n            elementControllers[directive.name] = controllerInstance;\n            if (!hasElementTranscludeDirective) {\n              $element.data('$' + directive.name + 'Controller', controllerInstance.instance);\n            }\n\n            controllers[directive.name] = controllerInstance;\n          });\n        }\n\n        if (newIsolateScopeDirective) {\n          compile.$$addScopeInfo($element, isolateScope, true, !(templateDirective && (templateDirective === newIsolateScopeDirective ||\n              templateDirective === newIsolateScopeDirective.$$originalDirective)));\n          compile.$$addScopeClass($element, true);\n\n          var isolateScopeController = controllers && controllers[newIsolateScopeDirective.name];\n          var isolateBindingContext = isolateScope;\n          if (isolateScopeController && isolateScopeController.identifier &&\n              newIsolateScopeDirective.bindToController === true) {\n            isolateBindingContext = isolateScopeController.instance;\n          }\n\n          forEach(isolateScope.$$isolateBindings = newIsolateScopeDirective.$$isolateBindings, function(definition, scopeName) {\n            var attrName = definition.attrName,\n                optional = definition.optional,\n                mode = definition.mode, // @, =, or &\n                lastValue,\n                parentGet, parentSet, compare;\n\n            switch (mode) {\n\n              case '@':\n                attrs.$observe(attrName, function(value) {\n                  isolateBindingContext[scopeName] = value;\n                });\n                attrs.$$observers[attrName].$$scope = scope;\n                if (attrs[attrName]) {\n                  // If the attribute has been provided then we trigger an interpolation to ensure\n                  // the value is there for use in the link fn\n                  isolateBindingContext[scopeName] = $interpolate(attrs[attrName])(scope);\n                }\n                break;\n\n              case '=':\n                if (optional && !attrs[attrName]) {\n                  return;\n                }\n                parentGet = $parse(attrs[attrName]);\n                if (parentGet.literal) {\n                  compare = equals;\n                } else {\n                  compare = function(a, b) { return a === b || (a !== a && b !== b); };\n                }\n                parentSet = parentGet.assign || function() {\n                  // reset the change, or we will throw this exception on every $digest\n                  lastValue = isolateBindingContext[scopeName] = parentGet(scope);\n                  throw $compileMinErr('nonassign',\n                      \"Expression '{0}' used with directive '{1}' is non-assignable!\",\n                      attrs[attrName], newIsolateScopeDirective.name);\n                };\n                lastValue = isolateBindingContext[scopeName] = parentGet(scope);\n                var parentValueWatch = function parentValueWatch(parentValue) {\n                  if (!compare(parentValue, isolateBindingContext[scopeName])) {\n                    // we are out of sync and need to copy\n                    if (!compare(parentValue, lastValue)) {\n                      // parent changed and it has precedence\n                      isolateBindingContext[scopeName] = parentValue;\n                    } else {\n                      // if the parent can be assigned then do so\n                      parentSet(scope, parentValue = isolateBindingContext[scopeName]);\n                    }\n                  }\n                  return lastValue = parentValue;\n                };\n                parentValueWatch.$stateful = true;\n                var unwatch;\n                if (definition.collection) {\n                  unwatch = scope.$watchCollection(attrs[attrName], parentValueWatch);\n                } else {\n                  unwatch = scope.$watch($parse(attrs[attrName], parentValueWatch), null, parentGet.literal);\n                }\n                isolateScope.$on('$destroy', unwatch);\n                break;\n\n              case '&':\n                parentGet = $parse(attrs[attrName]);\n                isolateBindingContext[scopeName] = function(locals) {\n                  return parentGet(scope, locals);\n                };\n                break;\n            }\n          });\n        }\n        if (controllers) {\n          forEach(controllers, function(controller) {\n            controller();\n          });\n          controllers = null;\n        }\n\n        // PRELINKING\n        for (i = 0, ii = preLinkFns.length; i < ii; i++) {\n          linkFn = preLinkFns[i];\n          invokeLinkFn(linkFn,\n              linkFn.isolateScope ? isolateScope : scope,\n              $element,\n              attrs,\n              linkFn.require && getControllers(linkFn.directiveName, linkFn.require, $element, elementControllers),\n              transcludeFn\n          );\n        }\n\n        // RECURSION\n        // We only pass the isolate scope, if the isolate directive has a template,\n        // otherwise the child elements do not belong to the isolate directive.\n        var scopeToChild = scope;\n        if (newIsolateScopeDirective && (newIsolateScopeDirective.template || newIsolateScopeDirective.templateUrl === null)) {\n          scopeToChild = isolateScope;\n        }\n        childLinkFn && childLinkFn(scopeToChild, linkNode.childNodes, undefined, boundTranscludeFn);\n\n        // POSTLINKING\n        for (i = postLinkFns.length - 1; i >= 0; i--) {\n          linkFn = postLinkFns[i];\n          invokeLinkFn(linkFn,\n              linkFn.isolateScope ? isolateScope : scope,\n              $element,\n              attrs,\n              linkFn.require && getControllers(linkFn.directiveName, linkFn.require, $element, elementControllers),\n              transcludeFn\n          );\n        }\n\n        // This is the function that is injected as `$transclude`.\n        // Note: all arguments are optional!\n        function controllersBoundTransclude(scope, cloneAttachFn, futureParentElement) {\n          var transcludeControllers;\n\n          // No scope passed in:\n          if (!isScope(scope)) {\n            futureParentElement = cloneAttachFn;\n            cloneAttachFn = scope;\n            scope = undefined;\n          }\n\n          if (hasElementTranscludeDirective) {\n            transcludeControllers = elementControllers;\n          }\n          if (!futureParentElement) {\n            futureParentElement = hasElementTranscludeDirective ? $element.parent() : $element;\n          }\n          return boundTranscludeFn(scope, cloneAttachFn, transcludeControllers, futureParentElement, scopeToChild);\n        }\n      }\n    }\n\n    function markDirectivesAsIsolate(directives) {\n      // mark all directives as needing isolate scope.\n      for (var j = 0, jj = directives.length; j < jj; j++) {\n        directives[j] = inherit(directives[j], {$$isolateScope: true});\n      }\n    }\n\n    /**\n     * looks up the directive and decorates it with exception handling and proper parameters. We\n     * call this the boundDirective.\n     *\n     * @param {string} name name of the directive to look up.\n     * @param {string} location The directive must be found in specific format.\n     *   String containing any of theses characters:\n     *\n     *   * `E`: element name\n     *   * `A': attribute\n     *   * `C`: class\n     *   * `M`: comment\n     * @returns {boolean} true if directive was added.\n     */\n    function addDirective(tDirectives, name, location, maxPriority, ignoreDirective, startAttrName,\n                          endAttrName) {\n      if (name === ignoreDirective) return null;\n      var match = null;\n      if (hasDirectives.hasOwnProperty(name)) {\n        for (var directive, directives = $injector.get(name + Suffix),\n            i = 0, ii = directives.length; i < ii; i++) {\n          try {\n            directive = directives[i];\n            if ((maxPriority === undefined || maxPriority > directive.priority) &&\n                 directive.restrict.indexOf(location) != -1) {\n              if (startAttrName) {\n                directive = inherit(directive, {$$start: startAttrName, $$end: endAttrName});\n              }\n              tDirectives.push(directive);\n              match = directive;\n            }\n          } catch (e) { $exceptionHandler(e); }\n        }\n      }\n      return match;\n    }\n\n\n    /**\n     * looks up the directive and returns true if it is a multi-element directive,\n     * and therefore requires DOM nodes between -start and -end markers to be grouped\n     * together.\n     *\n     * @param {string} name name of the directive to look up.\n     * @returns true if directive was registered as multi-element.\n     */\n    function directiveIsMultiElement(name) {\n      if (hasDirectives.hasOwnProperty(name)) {\n        for (var directive, directives = $injector.get(name + Suffix),\n            i = 0, ii = directives.length; i < ii; i++) {\n          directive = directives[i];\n          if (directive.multiElement) {\n            return true;\n          }\n        }\n      }\n      return false;\n    }\n\n    /**\n     * When the element is replaced with HTML template then the new attributes\n     * on the template need to be merged with the existing attributes in the DOM.\n     * The desired effect is to have both of the attributes present.\n     *\n     * @param {object} dst destination attributes (original DOM)\n     * @param {object} src source attributes (from the directive template)\n     */\n    function mergeTemplateAttributes(dst, src) {\n      var srcAttr = src.$attr,\n          dstAttr = dst.$attr,\n          $element = dst.$$element;\n\n      // reapply the old attributes to the new element\n      forEach(dst, function(value, key) {\n        if (key.charAt(0) != '$') {\n          if (src[key] && src[key] !== value) {\n            value += (key === 'style' ? ';' : ' ') + src[key];\n          }\n          dst.$set(key, value, true, srcAttr[key]);\n        }\n      });\n\n      // copy the new attributes on the old attrs object\n      forEach(src, function(value, key) {\n        if (key == 'class') {\n          safeAddClass($element, value);\n          dst['class'] = (dst['class'] ? dst['class'] + ' ' : '') + value;\n        } else if (key == 'style') {\n          $element.attr('style', $element.attr('style') + ';' + value);\n          dst['style'] = (dst['style'] ? dst['style'] + ';' : '') + value;\n          // `dst` will never contain hasOwnProperty as DOM parser won't let it.\n          // You will get an \"InvalidCharacterError: DOM Exception 5\" error if you\n          // have an attribute like \"has-own-property\" or \"data-has-own-property\", etc.\n        } else if (key.charAt(0) != '$' && !dst.hasOwnProperty(key)) {\n          dst[key] = value;\n          dstAttr[key] = srcAttr[key];\n        }\n      });\n    }\n\n\n    function compileTemplateUrl(directives, $compileNode, tAttrs,\n        $rootElement, childTranscludeFn, preLinkFns, postLinkFns, previousCompileContext) {\n      var linkQueue = [],\n          afterTemplateNodeLinkFn,\n          afterTemplateChildLinkFn,\n          beforeTemplateCompileNode = $compileNode[0],\n          origAsyncDirective = directives.shift(),\n          derivedSyncDirective = inherit(origAsyncDirective, {\n            templateUrl: null, transclude: null, replace: null, $$originalDirective: origAsyncDirective\n          }),\n          templateUrl = (isFunction(origAsyncDirective.templateUrl))\n              ? origAsyncDirective.templateUrl($compileNode, tAttrs)\n              : origAsyncDirective.templateUrl,\n          templateNamespace = origAsyncDirective.templateNamespace;\n\n      $compileNode.empty();\n\n      $templateRequest($sce.getTrustedResourceUrl(templateUrl))\n        .then(function(content) {\n          var compileNode, tempTemplateAttrs, $template, childBoundTranscludeFn;\n\n          content = denormalizeTemplate(content);\n\n          if (origAsyncDirective.replace) {\n            if (jqLiteIsTextNode(content)) {\n              $template = [];\n            } else {\n              $template = removeComments(wrapTemplate(templateNamespace, trim(content)));\n            }\n            compileNode = $template[0];\n\n            if ($template.length != 1 || compileNode.nodeType !== NODE_TYPE_ELEMENT) {\n              throw $compileMinErr('tplrt',\n                  \"Template for directive '{0}' must have exactly one root element. {1}\",\n                  origAsyncDirective.name, templateUrl);\n            }\n\n            tempTemplateAttrs = {$attr: {}};\n            replaceWith($rootElement, $compileNode, compileNode);\n            var templateDirectives = collectDirectives(compileNode, [], tempTemplateAttrs);\n\n            if (isObject(origAsyncDirective.scope)) {\n              markDirectivesAsIsolate(templateDirectives);\n            }\n            directives = templateDirectives.concat(directives);\n            mergeTemplateAttributes(tAttrs, tempTemplateAttrs);\n          } else {\n            compileNode = beforeTemplateCompileNode;\n            $compileNode.html(content);\n          }\n\n          directives.unshift(derivedSyncDirective);\n\n          afterTemplateNodeLinkFn = applyDirectivesToNode(directives, compileNode, tAttrs,\n              childTranscludeFn, $compileNode, origAsyncDirective, preLinkFns, postLinkFns,\n              previousCompileContext);\n          forEach($rootElement, function(node, i) {\n            if (node == compileNode) {\n              $rootElement[i] = $compileNode[0];\n            }\n          });\n          afterTemplateChildLinkFn = compileNodes($compileNode[0].childNodes, childTranscludeFn);\n\n          while (linkQueue.length) {\n            var scope = linkQueue.shift(),\n                beforeTemplateLinkNode = linkQueue.shift(),\n                linkRootElement = linkQueue.shift(),\n                boundTranscludeFn = linkQueue.shift(),\n                linkNode = $compileNode[0];\n\n            if (scope.$$destroyed) continue;\n\n            if (beforeTemplateLinkNode !== beforeTemplateCompileNode) {\n              var oldClasses = beforeTemplateLinkNode.className;\n\n              if (!(previousCompileContext.hasElementTranscludeDirective &&\n                  origAsyncDirective.replace)) {\n                // it was cloned therefore we have to clone as well.\n                linkNode = jqLiteClone(compileNode);\n              }\n              replaceWith(linkRootElement, jqLite(beforeTemplateLinkNode), linkNode);\n\n              // Copy in CSS classes from original node\n              safeAddClass(jqLite(linkNode), oldClasses);\n            }\n            if (afterTemplateNodeLinkFn.transcludeOnThisElement) {\n              childBoundTranscludeFn = createBoundTranscludeFn(scope, afterTemplateNodeLinkFn.transclude, boundTranscludeFn);\n            } else {\n              childBoundTranscludeFn = boundTranscludeFn;\n            }\n            afterTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, linkNode, $rootElement,\n              childBoundTranscludeFn);\n          }\n          linkQueue = null;\n        });\n\n      return function delayedNodeLinkFn(ignoreChildLinkFn, scope, node, rootElement, boundTranscludeFn) {\n        var childBoundTranscludeFn = boundTranscludeFn;\n        if (scope.$$destroyed) return;\n        if (linkQueue) {\n          linkQueue.push(scope,\n                         node,\n                         rootElement,\n                         childBoundTranscludeFn);\n        } else {\n          if (afterTemplateNodeLinkFn.transcludeOnThisElement) {\n            childBoundTranscludeFn = createBoundTranscludeFn(scope, afterTemplateNodeLinkFn.transclude, boundTranscludeFn);\n          }\n          afterTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, node, rootElement, childBoundTranscludeFn);\n        }\n      };\n    }\n\n\n    /**\n     * Sorting function for bound directives.\n     */\n    function byPriority(a, b) {\n      var diff = b.priority - a.priority;\n      if (diff !== 0) return diff;\n      if (a.name !== b.name) return (a.name < b.name) ? -1 : 1;\n      return a.index - b.index;\n    }\n\n\n    function assertNoDuplicate(what, previousDirective, directive, element) {\n      if (previousDirective) {\n        throw $compileMinErr('multidir', 'Multiple directives [{0}, {1}] asking for {2} on: {3}',\n            previousDirective.name, directive.name, what, startingTag(element));\n      }\n    }\n\n\n    function addTextInterpolateDirective(directives, text) {\n      var interpolateFn = $interpolate(text, true);\n      if (interpolateFn) {\n        directives.push({\n          priority: 0,\n          compile: function textInterpolateCompileFn(templateNode) {\n            var templateNodeParent = templateNode.parent(),\n                hasCompileParent = !!templateNodeParent.length;\n\n            // When transcluding a template that has bindings in the root\n            // we don't have a parent and thus need to add the class during linking fn.\n            if (hasCompileParent) compile.$$addBindingClass(templateNodeParent);\n\n            return function textInterpolateLinkFn(scope, node) {\n              var parent = node.parent();\n              if (!hasCompileParent) compile.$$addBindingClass(parent);\n              compile.$$addBindingInfo(parent, interpolateFn.expressions);\n              scope.$watch(interpolateFn, function interpolateFnWatchAction(value) {\n                node[0].nodeValue = value;\n              });\n            };\n          }\n        });\n      }\n    }\n\n\n    function wrapTemplate(type, template) {\n      type = lowercase(type || 'html');\n      switch (type) {\n      case 'svg':\n      case 'math':\n        var wrapper = document.createElement('div');\n        wrapper.innerHTML = '<' + type + '>' + template + '</' + type + '>';\n        return wrapper.childNodes[0].childNodes;\n      default:\n        return template;\n      }\n    }\n\n\n    function getTrustedContext(node, attrNormalizedName) {\n      if (attrNormalizedName == \"srcdoc\") {\n        return $sce.HTML;\n      }\n      var tag = nodeName_(node);\n      // maction[xlink:href] can source SVG.  It's not limited to <maction>.\n      if (attrNormalizedName == \"xlinkHref\" ||\n          (tag == \"form\" && attrNormalizedName == \"action\") ||\n          (tag != \"img\" && (attrNormalizedName == \"src\" ||\n                            attrNormalizedName == \"ngSrc\"))) {\n        return $sce.RESOURCE_URL;\n      }\n    }\n\n\n    function addAttrInterpolateDirective(node, directives, value, name, allOrNothing) {\n      var trustedContext = getTrustedContext(node, name);\n      allOrNothing = ALL_OR_NOTHING_ATTRS[name] || allOrNothing;\n\n      var interpolateFn = $interpolate(value, true, trustedContext, allOrNothing);\n\n      // no interpolation found -> ignore\n      if (!interpolateFn) return;\n\n\n      if (name === \"multiple\" && nodeName_(node) === \"select\") {\n        throw $compileMinErr(\"selmulti\",\n            \"Binding to the 'multiple' attribute is not supported. Element: {0}\",\n            startingTag(node));\n      }\n\n      directives.push({\n        priority: 100,\n        compile: function() {\n            return {\n              pre: function attrInterpolatePreLinkFn(scope, element, attr) {\n                var $$observers = (attr.$$observers || (attr.$$observers = {}));\n\n                if (EVENT_HANDLER_ATTR_REGEXP.test(name)) {\n                  throw $compileMinErr('nodomevents',\n                      \"Interpolations for HTML DOM event attributes are disallowed.  Please use the \" +\n                          \"ng- versions (such as ng-click instead of onclick) instead.\");\n                }\n\n                // If the attribute has changed since last $interpolate()ed\n                var newValue = attr[name];\n                if (newValue !== value) {\n                  // we need to interpolate again since the attribute value has been updated\n                  // (e.g. by another directive's compile function)\n                  // ensure unset/empty values make interpolateFn falsy\n                  interpolateFn = newValue && $interpolate(newValue, true, trustedContext, allOrNothing);\n                  value = newValue;\n                }\n\n                // if attribute was updated so that there is no interpolation going on we don't want to\n                // register any observers\n                if (!interpolateFn) return;\n\n                // initialize attr object so that it's ready in case we need the value for isolate\n                // scope initialization, otherwise the value would not be available from isolate\n                // directive's linking fn during linking phase\n                attr[name] = interpolateFn(scope);\n\n                ($$observers[name] || ($$observers[name] = [])).$$inter = true;\n                (attr.$$observers && attr.$$observers[name].$$scope || scope).\n                  $watch(interpolateFn, function interpolateFnWatchAction(newValue, oldValue) {\n                    //special case for class attribute addition + removal\n                    //so that class changes can tap into the animation\n                    //hooks provided by the $animate service. Be sure to\n                    //skip animations when the first digest occurs (when\n                    //both the new and the old values are the same) since\n                    //the CSS classes are the non-interpolated values\n                    if (name === 'class' && newValue != oldValue) {\n                      attr.$updateClass(newValue, oldValue);\n                    } else {\n                      attr.$set(name, newValue);\n                    }\n                  });\n              }\n            };\n          }\n      });\n    }\n\n\n    /**\n     * This is a special jqLite.replaceWith, which can replace items which\n     * have no parents, provided that the containing jqLite collection is provided.\n     *\n     * @param {JqLite=} $rootElement The root of the compile tree. Used so that we can replace nodes\n     *                               in the root of the tree.\n     * @param {JqLite} elementsToRemove The jqLite element which we are going to replace. We keep\n     *                                  the shell, but replace its DOM node reference.\n     * @param {Node} newNode The new DOM node.\n     */\n    function replaceWith($rootElement, elementsToRemove, newNode) {\n      var firstElementToRemove = elementsToRemove[0],\n          removeCount = elementsToRemove.length,\n          parent = firstElementToRemove.parentNode,\n          i, ii;\n\n      if ($rootElement) {\n        for (i = 0, ii = $rootElement.length; i < ii; i++) {\n          if ($rootElement[i] == firstElementToRemove) {\n            $rootElement[i++] = newNode;\n            for (var j = i, j2 = j + removeCount - 1,\n                     jj = $rootElement.length;\n                 j < jj; j++, j2++) {\n              if (j2 < jj) {\n                $rootElement[j] = $rootElement[j2];\n              } else {\n                delete $rootElement[j];\n              }\n            }\n            $rootElement.length -= removeCount - 1;\n\n            // If the replaced element is also the jQuery .context then replace it\n            // .context is a deprecated jQuery api, so we should set it only when jQuery set it\n            // http://api.jquery.com/context/\n            if ($rootElement.context === firstElementToRemove) {\n              $rootElement.context = newNode;\n            }\n            break;\n          }\n        }\n      }\n\n      if (parent) {\n        parent.replaceChild(newNode, firstElementToRemove);\n      }\n\n      // TODO(perf): what's this document fragment for? is it needed? can we at least reuse it?\n      var fragment = document.createDocumentFragment();\n      fragment.appendChild(firstElementToRemove);\n\n      // Copy over user data (that includes Angular's $scope etc.). Don't copy private\n      // data here because there's no public interface in jQuery to do that and copying over\n      // event listeners (which is the main use of private data) wouldn't work anyway.\n      jqLite(newNode).data(jqLite(firstElementToRemove).data());\n\n      // Remove data of the replaced element. We cannot just call .remove()\n      // on the element it since that would deallocate scope that is needed\n      // for the new node. Instead, remove the data \"manually\".\n      if (!jQuery) {\n        delete jqLite.cache[firstElementToRemove[jqLite.expando]];\n      } else {\n        // jQuery 2.x doesn't expose the data storage. Use jQuery.cleanData to clean up after\n        // the replaced element. The cleanData version monkey-patched by Angular would cause\n        // the scope to be trashed and we do need the very same scope to work with the new\n        // element. However, we cannot just cache the non-patched version and use it here as\n        // that would break if another library patches the method after Angular does (one\n        // example is jQuery UI). Instead, set a flag indicating scope destroying should be\n        // skipped this one time.\n        skipDestroyOnNextJQueryCleanData = true;\n        jQuery.cleanData([firstElementToRemove]);\n      }\n\n      for (var k = 1, kk = elementsToRemove.length; k < kk; k++) {\n        var element = elementsToRemove[k];\n        jqLite(element).remove(); // must do this way to clean up expando\n        fragment.appendChild(element);\n        delete elementsToRemove[k];\n      }\n\n      elementsToRemove[0] = newNode;\n      elementsToRemove.length = 1;\n    }\n\n\n    function cloneAndAnnotateFn(fn, annotation) {\n      return extend(function() { return fn.apply(null, arguments); }, fn, annotation);\n    }\n\n\n    function invokeLinkFn(linkFn, scope, $element, attrs, controllers, transcludeFn) {\n      try {\n        linkFn(scope, $element, attrs, controllers, transcludeFn);\n      } catch (e) {\n        $exceptionHandler(e, startingTag($element));\n      }\n    }\n  }];\n}\n\nvar PREFIX_REGEXP = /^((?:x|data)[\\:\\-_])/i;\n/**\n * Converts all accepted directives format into proper directive name.\n * @param name Name to normalize\n */\nfunction directiveNormalize(name) {\n  return camelCase(name.replace(PREFIX_REGEXP, ''));\n}\n\n/**\n * @ngdoc type\n * @name $compile.directive.Attributes\n *\n * @description\n * A shared object between directive compile / linking functions which contains normalized DOM\n * element attributes. The values reflect current binding state `{{ }}`. The normalization is\n * needed since all of these are treated as equivalent in Angular:\n *\n * ```\n *    <span ng:bind=\"a\" ng-bind=\"a\" data-ng-bind=\"a\" x-ng-bind=\"a\">\n * ```\n */\n\n/**\n * @ngdoc property\n * @name $compile.directive.Attributes#$attr\n *\n * @description\n * A map of DOM element attribute names to the normalized name. This is\n * needed to do reverse lookup from normalized name back to actual name.\n */\n\n\n/**\n * @ngdoc method\n * @name $compile.directive.Attributes#$set\n * @kind function\n *\n * @description\n * Set DOM element attribute value.\n *\n *\n * @param {string} name Normalized element attribute name of the property to modify. The name is\n *          reverse-translated using the {@link ng.$compile.directive.Attributes#$attr $attr}\n *          property to the original name.\n * @param {string} value Value to set the attribute to. The value can be an interpolated string.\n */\n\n\n\n/**\n * Closure compiler type information\n */\n\nfunction nodesetLinkingFn(\n  /* angular.Scope */ scope,\n  /* NodeList */ nodeList,\n  /* Element */ rootElement,\n  /* function(Function) */ boundTranscludeFn\n) {}\n\nfunction directiveLinkingFn(\n  /* nodesetLinkingFn */ nodesetLinkingFn,\n  /* angular.Scope */ scope,\n  /* Node */ node,\n  /* Element */ rootElement,\n  /* function(Function) */ boundTranscludeFn\n) {}\n\nfunction tokenDifference(str1, str2) {\n  var values = '',\n      tokens1 = str1.split(/\\s+/),\n      tokens2 = str2.split(/\\s+/);\n\n  outer:\n  for (var i = 0; i < tokens1.length; i++) {\n    var token = tokens1[i];\n    for (var j = 0; j < tokens2.length; j++) {\n      if (token == tokens2[j]) continue outer;\n    }\n    values += (values.length > 0 ? ' ' : '') + token;\n  }\n  return values;\n}\n\nfunction removeComments(jqNodes) {\n  jqNodes = jqLite(jqNodes);\n  var i = jqNodes.length;\n\n  if (i <= 1) {\n    return jqNodes;\n  }\n\n  while (i--) {\n    var node = jqNodes[i];\n    if (node.nodeType === NODE_TYPE_COMMENT) {\n      splice.call(jqNodes, i, 1);\n    }\n  }\n  return jqNodes;\n}\n\nvar $controllerMinErr = minErr('$controller');\n\n/**\n * @ngdoc provider\n * @name $controllerProvider\n * @description\n * The {@link ng.$controller $controller service} is used by Angular to create new\n * controllers.\n *\n * This provider allows controller registration via the\n * {@link ng.$controllerProvider#register register} method.\n */\nfunction $ControllerProvider() {\n  var controllers = {},\n      globals = false,\n      CNTRL_REG = /^(\\S+)(\\s+as\\s+(\\w+))?$/;\n\n\n  /**\n   * @ngdoc method\n   * @name $controllerProvider#register\n   * @param {string|Object} name Controller name, or an object map of controllers where the keys are\n   *    the names and the values are the constructors.\n   * @param {Function|Array} constructor Controller constructor fn (optionally decorated with DI\n   *    annotations in the array notation).\n   */\n  this.register = function(name, constructor) {\n    assertNotHasOwnProperty(name, 'controller');\n    if (isObject(name)) {\n      extend(controllers, name);\n    } else {\n      controllers[name] = constructor;\n    }\n  };\n\n  /**\n   * @ngdoc method\n   * @name $controllerProvider#allowGlobals\n   * @description If called, allows `$controller` to find controller constructors on `window`\n   */\n  this.allowGlobals = function() {\n    globals = true;\n  };\n\n\n  this.$get = ['$injector', '$window', function($injector, $window) {\n\n    /**\n     * @ngdoc service\n     * @name $controller\n     * @requires $injector\n     *\n     * @param {Function|string} constructor If called with a function then it's considered to be the\n     *    controller constructor function. Otherwise it's considered to be a string which is used\n     *    to retrieve the controller constructor using the following steps:\n     *\n     *    * check if a controller with given name is registered via `$controllerProvider`\n     *    * check if evaluating the string on the current scope returns a constructor\n     *    * if $controllerProvider#allowGlobals, check `window[constructor]` on the global\n     *      `window` object (not recommended)\n     *\n     *    The string can use the `controller as property` syntax, where the controller instance is published\n     *    as the specified property on the `scope`; the `scope` must be injected into `locals` param for this\n     *    to work correctly.\n     *\n     * @param {Object} locals Injection locals for Controller.\n     * @return {Object} Instance of given controller.\n     *\n     * @description\n     * `$controller` service is responsible for instantiating controllers.\n     *\n     * It's just a simple call to {@link auto.$injector $injector}, but extracted into\n     * a service, so that one can override this service with [BC version](https://gist.github.com/1649788).\n     */\n    return function(expression, locals, later, ident) {\n      // PRIVATE API:\n      //   param `later` --- indicates that the controller's constructor is invoked at a later time.\n      //                     If true, $controller will allocate the object with the correct\n      //                     prototype chain, but will not invoke the controller until a returned\n      //                     callback is invoked.\n      //   param `ident` --- An optional label which overrides the label parsed from the controller\n      //                     expression, if any.\n      var instance, match, constructor, identifier;\n      later = later === true;\n      if (ident && isString(ident)) {\n        identifier = ident;\n      }\n\n      if (isString(expression)) {\n        match = expression.match(CNTRL_REG);\n        if (!match) {\n          throw $controllerMinErr('ctrlfmt',\n            \"Badly formed controller string '{0}'. \" +\n            \"Must match `__name__ as __id__` or `__name__`.\", expression);\n        }\n        constructor = match[1],\n        identifier = identifier || match[3];\n        expression = controllers.hasOwnProperty(constructor)\n            ? controllers[constructor]\n            : getter(locals.$scope, constructor, true) ||\n                (globals ? getter($window, constructor, true) : undefined);\n\n        assertArgFn(expression, constructor, true);\n      }\n\n      if (later) {\n        // Instantiate controller later:\n        // This machinery is used to create an instance of the object before calling the\n        // controller's constructor itself.\n        //\n        // This allows properties to be added to the controller before the constructor is\n        // invoked. Primarily, this is used for isolate scope bindings in $compile.\n        //\n        // This feature is not intended for use by applications, and is thus not documented\n        // publicly.\n        // Object creation: http://jsperf.com/create-constructor/2\n        var controllerPrototype = (isArray(expression) ?\n          expression[expression.length - 1] : expression).prototype;\n        instance = Object.create(controllerPrototype || null);\n\n        if (identifier) {\n          addIdentifier(locals, identifier, instance, constructor || expression.name);\n        }\n\n        return extend(function() {\n          $injector.invoke(expression, instance, locals, constructor);\n          return instance;\n        }, {\n          instance: instance,\n          identifier: identifier\n        });\n      }\n\n      instance = $injector.instantiate(expression, locals, constructor);\n\n      if (identifier) {\n        addIdentifier(locals, identifier, instance, constructor || expression.name);\n      }\n\n      return instance;\n    };\n\n    function addIdentifier(locals, identifier, instance, name) {\n      if (!(locals && isObject(locals.$scope))) {\n        throw minErr('$controller')('noscp',\n          \"Cannot export controller '{0}' as '{1}'! No $scope object provided via `locals`.\",\n          name, identifier);\n      }\n\n      locals.$scope[identifier] = instance;\n    }\n  }];\n}\n\n/**\n * @ngdoc service\n * @name $document\n * @requires $window\n *\n * @description\n * A {@link angular.element jQuery or jqLite} wrapper for the browser's `window.document` object.\n *\n * @example\n   <example module=\"documentExample\">\n     <file name=\"index.html\">\n       <div ng-controller=\"ExampleController\">\n         <p>$document title: <b ng-bind=\"title\"></b></p>\n         <p>window.document title: <b ng-bind=\"windowTitle\"></b></p>\n       </div>\n     </file>\n     <file name=\"script.js\">\n       angular.module('documentExample', [])\n         .controller('ExampleController', ['$scope', '$document', function($scope, $document) {\n           $scope.title = $document[0].title;\n           $scope.windowTitle = angular.element(window.document)[0].title;\n         }]);\n     </file>\n   </example>\n */\nfunction $DocumentProvider() {\n  this.$get = ['$window', function(window) {\n    return jqLite(window.document);\n  }];\n}\n\n/**\n * @ngdoc service\n * @name $exceptionHandler\n * @requires ng.$log\n *\n * @description\n * Any uncaught exception in angular expressions is delegated to this service.\n * The default implementation simply delegates to `$log.error` which logs it into\n * the browser console.\n *\n * In unit tests, if `angular-mocks.js` is loaded, this service is overridden by\n * {@link ngMock.$exceptionHandler mock $exceptionHandler} which aids in testing.\n *\n * ## Example:\n *\n * ```js\n *   angular.module('exceptionOverride', []).factory('$exceptionHandler', function() {\n *     return function(exception, cause) {\n *       exception.message += ' (caused by \"' + cause + '\")';\n *       throw exception;\n *     };\n *   });\n * ```\n *\n * This example will override the normal action of `$exceptionHandler`, to make angular\n * exceptions fail hard when they happen, instead of just logging to the console.\n *\n * <hr />\n * Note, that code executed in event-listeners (even those registered using jqLite's `on`/`bind`\n * methods) does not delegate exceptions to the {@link ng.$exceptionHandler $exceptionHandler}\n * (unless executed during a digest).\n *\n * If you wish, you can manually delegate exceptions, e.g.\n * `try { ... } catch(e) { $exceptionHandler(e); }`\n *\n * @param {Error} exception Exception associated with the error.\n * @param {string=} cause optional information about the context in which\n *       the error was thrown.\n *\n */\nfunction $ExceptionHandlerProvider() {\n  this.$get = ['$log', function($log) {\n    return function(exception, cause) {\n      $log.error.apply($log, arguments);\n    };\n  }];\n}\n\nvar APPLICATION_JSON = 'application/json';\nvar CONTENT_TYPE_APPLICATION_JSON = {'Content-Type': APPLICATION_JSON + ';charset=utf-8'};\nvar JSON_START = /^\\[|^\\{(?!\\{)/;\nvar JSON_ENDS = {\n  '[': /]$/,\n  '{': /}$/\n};\nvar JSON_PROTECTION_PREFIX = /^\\)\\]\\}',?\\n/;\n\nfunction defaultHttpResponseTransform(data, headers) {\n  if (isString(data)) {\n    // Strip json vulnerability protection prefix and trim whitespace\n    var tempData = data.replace(JSON_PROTECTION_PREFIX, '').trim();\n\n    if (tempData) {\n      var contentType = headers('Content-Type');\n      if ((contentType && (contentType.indexOf(APPLICATION_JSON) === 0)) || isJsonLike(tempData)) {\n        data = fromJson(tempData);\n      }\n    }\n  }\n\n  return data;\n}\n\nfunction isJsonLike(str) {\n    var jsonStart = str.match(JSON_START);\n    return jsonStart && JSON_ENDS[jsonStart[0]].test(str);\n}\n\n/**\n * Parse headers into key value object\n *\n * @param {string} headers Raw headers as a string\n * @returns {Object} Parsed headers as key value object\n */\nfunction parseHeaders(headers) {\n  var parsed = createMap(), key, val, i;\n\n  if (!headers) return parsed;\n\n  forEach(headers.split('\\n'), function(line) {\n    i = line.indexOf(':');\n    key = lowercase(trim(line.substr(0, i)));\n    val = trim(line.substr(i + 1));\n\n    if (key) {\n      parsed[key] = parsed[key] ? parsed[key] + ', ' + val : val;\n    }\n  });\n\n  return parsed;\n}\n\n\n/**\n * Returns a function that provides access to parsed headers.\n *\n * Headers are lazy parsed when first requested.\n * @see parseHeaders\n *\n * @param {(string|Object)} headers Headers to provide access to.\n * @returns {function(string=)} Returns a getter function which if called with:\n *\n *   - if called with single an argument returns a single header value or null\n *   - if called with no arguments returns an object containing all headers.\n */\nfunction headersGetter(headers) {\n  var headersObj = isObject(headers) ? headers : undefined;\n\n  return function(name) {\n    if (!headersObj) headersObj =  parseHeaders(headers);\n\n    if (name) {\n      var value = headersObj[lowercase(name)];\n      if (value === void 0) {\n        value = null;\n      }\n      return value;\n    }\n\n    return headersObj;\n  };\n}\n\n\n/**\n * Chain all given functions\n *\n * This function is used for both request and response transforming\n *\n * @param {*} data Data to transform.\n * @param {function(string=)} headers HTTP headers getter fn.\n * @param {number} status HTTP status code of the response.\n * @param {(Function|Array.<Function>)} fns Function or an array of functions.\n * @returns {*} Transformed data.\n */\nfunction transformData(data, headers, status, fns) {\n  if (isFunction(fns))\n    return fns(data, headers, status);\n\n  forEach(fns, function(fn) {\n    data = fn(data, headers, status);\n  });\n\n  return data;\n}\n\n\nfunction isSuccess(status) {\n  return 200 <= status && status < 300;\n}\n\n\n/**\n * @ngdoc provider\n * @name $httpProvider\n * @description\n * Use `$httpProvider` to change the default behavior of the {@link ng.$http $http} service.\n * */\nfunction $HttpProvider() {\n  /**\n   * @ngdoc property\n   * @name $httpProvider#defaults\n   * @description\n   *\n   * Object containing default values for all {@link ng.$http $http} requests.\n   *\n   * - **`defaults.cache`** - {Object} - an object built with {@link ng.$cacheFactory `$cacheFactory`}\n   * that will provide the cache for all requests who set their `cache` property to `true`.\n   * If you set the `default.cache = false` then only requests that specify their own custom\n   * cache object will be cached. See {@link $http#caching $http Caching} for more information.\n   *\n   * - **`defaults.xsrfCookieName`** - {string} - Name of cookie containing the XSRF token.\n   * Defaults value is `'XSRF-TOKEN'`.\n   *\n   * - **`defaults.xsrfHeaderName`** - {string} - Name of HTTP header to populate with the\n   * XSRF token. Defaults value is `'X-XSRF-TOKEN'`.\n   *\n   * - **`defaults.headers`** - {Object} - Default headers for all $http requests.\n   * Refer to {@link ng.$http#setting-http-headers $http} for documentation on\n   * setting default headers.\n   *     - **`defaults.headers.common`**\n   *     - **`defaults.headers.post`**\n   *     - **`defaults.headers.put`**\n   *     - **`defaults.headers.patch`**\n   *\n   **/\n  var defaults = this.defaults = {\n    // transform incoming response data\n    transformResponse: [defaultHttpResponseTransform],\n\n    // transform outgoing request data\n    transformRequest: [function(d) {\n      return isObject(d) && !isFile(d) && !isBlob(d) && !isFormData(d) ? toJson(d) : d;\n    }],\n\n    // default headers\n    headers: {\n      common: {\n        'Accept': 'application/json, text/plain, */*'\n      },\n      post:   shallowCopy(CONTENT_TYPE_APPLICATION_JSON),\n      put:    shallowCopy(CONTENT_TYPE_APPLICATION_JSON),\n      patch:  shallowCopy(CONTENT_TYPE_APPLICATION_JSON)\n    },\n\n    xsrfCookieName: 'XSRF-TOKEN',\n    xsrfHeaderName: 'X-XSRF-TOKEN'\n  };\n\n  var useApplyAsync = false;\n  /**\n   * @ngdoc method\n   * @name $httpProvider#useApplyAsync\n   * @description\n   *\n   * Configure $http service to combine processing of multiple http responses received at around\n   * the same time via {@link ng.$rootScope.Scope#$applyAsync $rootScope.$applyAsync}. This can result in\n   * significant performance improvement for bigger applications that make many HTTP requests\n   * concurrently (common during application bootstrap).\n   *\n   * Defaults to false. If no value is specifed, returns the current configured value.\n   *\n   * @param {boolean=} value If true, when requests are loaded, they will schedule a deferred\n   *    \"apply\" on the next tick, giving time for subsequent requests in a roughly ~10ms window\n   *    to load and share the same digest cycle.\n   *\n   * @returns {boolean|Object} If a value is specified, returns the $httpProvider for chaining.\n   *    otherwise, returns the current configured value.\n   **/\n  this.useApplyAsync = function(value) {\n    if (isDefined(value)) {\n      useApplyAsync = !!value;\n      return this;\n    }\n    return useApplyAsync;\n  };\n\n  /**\n   * @ngdoc property\n   * @name $httpProvider#interceptors\n   * @description\n   *\n   * Array containing service factories for all synchronous or asynchronous {@link ng.$http $http}\n   * pre-processing of request or postprocessing of responses.\n   *\n   * These service factories are ordered by request, i.e. they are applied in the same order as the\n   * array, on request, but reverse order, on response.\n   *\n   * {@link ng.$http#interceptors Interceptors detailed info}\n   **/\n  var interceptorFactories = this.interceptors = [];\n\n  this.$get = ['$httpBackend', '$browser', '$cacheFactory', '$rootScope', '$q', '$injector',\n      function($httpBackend, $browser, $cacheFactory, $rootScope, $q, $injector) {\n\n    var defaultCache = $cacheFactory('$http');\n\n    /**\n     * Interceptors stored in reverse order. Inner interceptors before outer interceptors.\n     * The reversal is needed so that we can build up the interception chain around the\n     * server request.\n     */\n    var reversedInterceptors = [];\n\n    forEach(interceptorFactories, function(interceptorFactory) {\n      reversedInterceptors.unshift(isString(interceptorFactory)\n          ? $injector.get(interceptorFactory) : $injector.invoke(interceptorFactory));\n    });\n\n    /**\n     * @ngdoc service\n     * @kind function\n     * @name $http\n     * @requires ng.$httpBackend\n     * @requires $cacheFactory\n     * @requires $rootScope\n     * @requires $q\n     * @requires $injector\n     *\n     * @description\n     * The `$http` service is a core Angular service that facilitates communication with the remote\n     * HTTP servers via the browser's [XMLHttpRequest](https://developer.mozilla.org/en/xmlhttprequest)\n     * object or via [JSONP](http://en.wikipedia.org/wiki/JSONP).\n     *\n     * For unit testing applications that use `$http` service, see\n     * {@link ngMock.$httpBackend $httpBackend mock}.\n     *\n     * For a higher level of abstraction, please check out the {@link ngResource.$resource\n     * $resource} service.\n     *\n     * The $http API is based on the {@link ng.$q deferred/promise APIs} exposed by\n     * the $q service. While for simple usage patterns this doesn't matter much, for advanced usage\n     * it is important to familiarize yourself with these APIs and the guarantees they provide.\n     *\n     *\n     * ## General usage\n     * The `$http` service is a function which takes a single argument — a configuration object —\n     * that is used to generate an HTTP request and returns  a {@link ng.$q promise}\n     * with two $http specific methods: `success` and `error`.\n     *\n     * ```js\n     *   // Simple GET request example :\n     *   $http.get('/someUrl').\n     *     success(function(data, status, headers, config) {\n     *       // this callback will be called asynchronously\n     *       // when the response is available\n     *     }).\n     *     error(function(data, status, headers, config) {\n     *       // called asynchronously if an error occurs\n     *       // or server returns response with an error status.\n     *     });\n     * ```\n     *\n     * ```js\n     *   // Simple POST request example (passing data) :\n     *   $http.post('/someUrl', {msg:'hello word!'}).\n     *     success(function(data, status, headers, config) {\n     *       // this callback will be called asynchronously\n     *       // when the response is available\n     *     }).\n     *     error(function(data, status, headers, config) {\n     *       // called asynchronously if an error occurs\n     *       // or server returns response with an error status.\n     *     });\n     * ```\n     *\n     *\n     * Since the returned value of calling the $http function is a `promise`, you can also use\n     * the `then` method to register callbacks, and these callbacks will receive a single argument –\n     * an object representing the response. See the API signature and type info below for more\n     * details.\n     *\n     * A response status code between 200 and 299 is considered a success status and\n     * will result in the success callback being called. Note that if the response is a redirect,\n     * XMLHttpRequest will transparently follow it, meaning that the error callback will not be\n     * called for such responses.\n     *\n     * ## Writing Unit Tests that use $http\n     * When unit testing (using {@link ngMock ngMock}), it is necessary to call\n     * {@link ngMock.$httpBackend#flush $httpBackend.flush()} to flush each pending\n     * request using trained responses.\n     *\n     * ```\n     * $httpBackend.expectGET(...);\n     * $http.get(...);\n     * $httpBackend.flush();\n     * ```\n     *\n     * ## Shortcut methods\n     *\n     * Shortcut methods are also available. All shortcut methods require passing in the URL, and\n     * request data must be passed in for POST/PUT requests.\n     *\n     * ```js\n     *   $http.get('/someUrl').success(successCallback);\n     *   $http.post('/someUrl', data).success(successCallback);\n     * ```\n     *\n     * Complete list of shortcut methods:\n     *\n     * - {@link ng.$http#get $http.get}\n     * - {@link ng.$http#head $http.head}\n     * - {@link ng.$http#post $http.post}\n     * - {@link ng.$http#put $http.put}\n     * - {@link ng.$http#delete $http.delete}\n     * - {@link ng.$http#jsonp $http.jsonp}\n     * - {@link ng.$http#patch $http.patch}\n     *\n     *\n     * ## Setting HTTP Headers\n     *\n     * The $http service will automatically add certain HTTP headers to all requests. These defaults\n     * can be fully configured by accessing the `$httpProvider.defaults.headers` configuration\n     * object, which currently contains this default configuration:\n     *\n     * - `$httpProvider.defaults.headers.common` (headers that are common for all requests):\n     *   - `Accept: application/json, text/plain, * / *`\n     * - `$httpProvider.defaults.headers.post`: (header defaults for POST requests)\n     *   - `Content-Type: application/json`\n     * - `$httpProvider.defaults.headers.put` (header defaults for PUT requests)\n     *   - `Content-Type: application/json`\n     *\n     * To add or overwrite these defaults, simply add or remove a property from these configuration\n     * objects. To add headers for an HTTP method other than POST or PUT, simply add a new object\n     * with the lowercased HTTP method name as the key, e.g.\n     * `$httpProvider.defaults.headers.get = { 'My-Header' : 'value' }.\n     *\n     * The defaults can also be set at runtime via the `$http.defaults` object in the same\n     * fashion. For example:\n     *\n     * ```\n     * module.run(function($http) {\n     *   $http.defaults.headers.common.Authorization = 'Basic YmVlcDpib29w'\n     * });\n     * ```\n     *\n     * In addition, you can supply a `headers` property in the config object passed when\n     * calling `$http(config)`, which overrides the defaults without changing them globally.\n     *\n     * To explicitly remove a header automatically added via $httpProvider.defaults.headers on a per request basis,\n     * Use the `headers` property, setting the desired header to `undefined`. For example:\n     *\n     * ```js\n     * var req = {\n     *  method: 'POST',\n     *  url: 'http://example.com',\n     *  headers: {\n     *    'Content-Type': undefined\n     *  },\n     *  data: { test: 'test' },\n     * }\n     *\n     * $http(req).success(function(){...}).error(function(){...});\n     * ```\n     *\n     * ## Transforming Requests and Responses\n     *\n     * Both requests and responses can be transformed using transformation functions: `transformRequest`\n     * and `transformResponse`. These properties can be a single function that returns\n     * the transformed value (`function(data, headersGetter, status)`) or an array of such transformation functions,\n     * which allows you to `push` or `unshift` a new transformation function into the transformation chain.\n     *\n     * ### Default Transformations\n     *\n     * The `$httpProvider` provider and `$http` service expose `defaults.transformRequest` and\n     * `defaults.transformResponse` properties. If a request does not provide its own transformations\n     * then these will be applied.\n     *\n     * You can augment or replace the default transformations by modifying these properties by adding to or\n     * replacing the array.\n     *\n     * Angular provides the following default transformations:\n     *\n     * Request transformations (`$httpProvider.defaults.transformRequest` and `$http.defaults.transformRequest`):\n     *\n     * - If the `data` property of the request configuration object contains an object, serialize it\n     *   into JSON format.\n     *\n     * Response transformations (`$httpProvider.defaults.transformResponse` and `$http.defaults.transformResponse`):\n     *\n     *  - If XSRF prefix is detected, strip it (see Security Considerations section below).\n     *  - If JSON response is detected, deserialize it using a JSON parser.\n     *\n     *\n     * ### Overriding the Default Transformations Per Request\n     *\n     * If you wish override the request/response transformations only for a single request then provide\n     * `transformRequest` and/or `transformResponse` properties on the configuration object passed\n     * into `$http`.\n     *\n     * Note that if you provide these properties on the config object the default transformations will be\n     * overwritten. If you wish to augment the default transformations then you must include them in your\n     * local transformation array.\n     *\n     * The following code demonstrates adding a new response transformation to be run after the default response\n     * transformations have been run.\n     *\n     * ```js\n     * function appendTransform(defaults, transform) {\n     *\n     *   // We can't guarantee that the default transformation is an array\n     *   defaults = angular.isArray(defaults) ? defaults : [defaults];\n     *\n     *   // Append the new transformation to the defaults\n     *   return defaults.concat(transform);\n     * }\n     *\n     * $http({\n     *   url: '...',\n     *   method: 'GET',\n     *   transformResponse: appendTransform($http.defaults.transformResponse, function(value) {\n     *     return doTransform(value);\n     *   })\n     * });\n     * ```\n     *\n     *\n     * ## Caching\n     *\n     * To enable caching, set the request configuration `cache` property to `true` (to use default\n     * cache) or to a custom cache object (built with {@link ng.$cacheFactory `$cacheFactory`}).\n     * When the cache is enabled, `$http` stores the response from the server in the specified\n     * cache. The next time the same request is made, the response is served from the cache without\n     * sending a request to the server.\n     *\n     * Note that even if the response is served from cache, delivery of the data is asynchronous in\n     * the same way that real requests are.\n     *\n     * If there are multiple GET requests for the same URL that should be cached using the same\n     * cache, but the cache is not populated yet, only one request to the server will be made and\n     * the remaining requests will be fulfilled using the response from the first request.\n     *\n     * You can change the default cache to a new object (built with\n     * {@link ng.$cacheFactory `$cacheFactory`}) by updating the\n     * {@link ng.$http#defaults `$http.defaults.cache`} property. All requests who set\n     * their `cache` property to `true` will now use this cache object.\n     *\n     * If you set the default cache to `false` then only requests that specify their own custom\n     * cache object will be cached.\n     *\n     * ## Interceptors\n     *\n     * Before you start creating interceptors, be sure to understand the\n     * {@link ng.$q $q and deferred/promise APIs}.\n     *\n     * For purposes of global error handling, authentication, or any kind of synchronous or\n     * asynchronous pre-processing of request or postprocessing of responses, it is desirable to be\n     * able to intercept requests before they are handed to the server and\n     * responses before they are handed over to the application code that\n     * initiated these requests. The interceptors leverage the {@link ng.$q\n     * promise APIs} to fulfill this need for both synchronous and asynchronous pre-processing.\n     *\n     * The interceptors are service factories that are registered with the `$httpProvider` by\n     * adding them to the `$httpProvider.interceptors` array. The factory is called and\n     * injected with dependencies (if specified) and returns the interceptor.\n     *\n     * There are two kinds of interceptors (and two kinds of rejection interceptors):\n     *\n     *   * `request`: interceptors get called with a http `config` object. The function is free to\n     *     modify the `config` object or create a new one. The function needs to return the `config`\n     *     object directly, or a promise containing the `config` or a new `config` object.\n     *   * `requestError`: interceptor gets called when a previous interceptor threw an error or\n     *     resolved with a rejection.\n     *   * `response`: interceptors get called with http `response` object. The function is free to\n     *     modify the `response` object or create a new one. The function needs to return the `response`\n     *     object directly, or as a promise containing the `response` or a new `response` object.\n     *   * `responseError`: interceptor gets called when a previous interceptor threw an error or\n     *     resolved with a rejection.\n     *\n     *\n     * ```js\n     *   // register the interceptor as a service\n     *   $provide.factory('myHttpInterceptor', function($q, dependency1, dependency2) {\n     *     return {\n     *       // optional method\n     *       'request': function(config) {\n     *         // do something on success\n     *         return config;\n     *       },\n     *\n     *       // optional method\n     *      'requestError': function(rejection) {\n     *         // do something on error\n     *         if (canRecover(rejection)) {\n     *           return responseOrNewPromise\n     *         }\n     *         return $q.reject(rejection);\n     *       },\n     *\n     *\n     *\n     *       // optional method\n     *       'response': function(response) {\n     *         // do something on success\n     *         return response;\n     *       },\n     *\n     *       // optional method\n     *      'responseError': function(rejection) {\n     *         // do something on error\n     *         if (canRecover(rejection)) {\n     *           return responseOrNewPromise\n     *         }\n     *         return $q.reject(rejection);\n     *       }\n     *     };\n     *   });\n     *\n     *   $httpProvider.interceptors.push('myHttpInterceptor');\n     *\n     *\n     *   // alternatively, register the interceptor via an anonymous factory\n     *   $httpProvider.interceptors.push(function($q, dependency1, dependency2) {\n     *     return {\n     *      'request': function(config) {\n     *          // same as above\n     *       },\n     *\n     *       'response': function(response) {\n     *          // same as above\n     *       }\n     *     };\n     *   });\n     * ```\n     *\n     * ## Security Considerations\n     *\n     * When designing web applications, consider security threats from:\n     *\n     * - [JSON vulnerability](http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx)\n     * - [XSRF](http://en.wikipedia.org/wiki/Cross-site_request_forgery)\n     *\n     * Both server and the client must cooperate in order to eliminate these threats. Angular comes\n     * pre-configured with strategies that address these issues, but for this to work backend server\n     * cooperation is required.\n     *\n     * ### JSON Vulnerability Protection\n     *\n     * A [JSON vulnerability](http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx)\n     * allows third party website to turn your JSON resource URL into\n     * [JSONP](http://en.wikipedia.org/wiki/JSONP) request under some conditions. To\n     * counter this your server can prefix all JSON requests with following string `\")]}',\\n\"`.\n     * Angular will automatically strip the prefix before processing it as JSON.\n     *\n     * For example if your server needs to return:\n     * ```js\n     * ['one','two']\n     * ```\n     *\n     * which is vulnerable to attack, your server can return:\n     * ```js\n     * )]}',\n     * ['one','two']\n     * ```\n     *\n     * Angular will strip the prefix, before processing the JSON.\n     *\n     *\n     * ### Cross Site Request Forgery (XSRF) Protection\n     *\n     * [XSRF](http://en.wikipedia.org/wiki/Cross-site_request_forgery) is a technique by which\n     * an unauthorized site can gain your user's private data. Angular provides a mechanism\n     * to counter XSRF. When performing XHR requests, the $http service reads a token from a cookie\n     * (by default, `XSRF-TOKEN`) and sets it as an HTTP header (`X-XSRF-TOKEN`). Since only\n     * JavaScript that runs on your domain could read the cookie, your server can be assured that\n     * the XHR came from JavaScript running on your domain. The header will not be set for\n     * cross-domain requests.\n     *\n     * To take advantage of this, your server needs to set a token in a JavaScript readable session\n     * cookie called `XSRF-TOKEN` on the first HTTP GET request. On subsequent XHR requests the\n     * server can verify that the cookie matches `X-XSRF-TOKEN` HTTP header, and therefore be sure\n     * that only JavaScript running on your domain could have sent the request. The token must be\n     * unique for each user and must be verifiable by the server (to prevent the JavaScript from\n     * making up its own tokens). We recommend that the token is a digest of your site's\n     * authentication cookie with a [salt](https://en.wikipedia.org/wiki/Salt_(cryptography&#41;)\n     * for added security.\n     *\n     * The name of the headers can be specified using the xsrfHeaderName and xsrfCookieName\n     * properties of either $httpProvider.defaults at config-time, $http.defaults at run-time,\n     * or the per-request config object.\n     *\n     *\n     * @param {object} config Object describing the request to be made and how it should be\n     *    processed. The object has following properties:\n     *\n     *    - **method** – `{string}` – HTTP method (e.g. 'GET', 'POST', etc)\n     *    - **url** – `{string}` – Absolute or relative URL of the resource that is being requested.\n     *    - **params** – `{Object.<string|Object>}` – Map of strings or objects which will be turned\n     *      to `?key1=value1&key2=value2` after the url. If the value is not a string, it will be\n     *      JSONified.\n     *    - **data** – `{string|Object}` – Data to be sent as the request message data.\n     *    - **headers** – `{Object}` – Map of strings or functions which return strings representing\n     *      HTTP headers to send to the server. If the return value of a function is null, the\n     *      header will not be sent.\n     *    - **xsrfHeaderName** – `{string}` – Name of HTTP header to populate with the XSRF token.\n     *    - **xsrfCookieName** – `{string}` – Name of cookie containing the XSRF token.\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     *      See {@link ng.$http#overriding-the-default-transformations-per-request\n     *      Overriding the Default Transformations}\n     *    - **transformResponse** –\n     *      `{function(data, headersGetter, status)|Array.<function(data, headersGetter, status)>}` –\n     *      transform function or an array of such functions. The transform function takes the http\n     *      response body, headers and status and returns its transformed (typically deserialized) version.\n     *      See {@link ng.$http#overriding-the-default-transformations-per-request\n     *      Overriding the Default Transformations}\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}\n     *      that should abort the request when resolved.\n     *    - **withCredentials** - `{boolean}` - whether to set the `withCredentials` flag on the\n     *      XHR object. See [requests with credentials](https://developer.mozilla.org/docs/Web/HTTP/Access_control_CORS#Requests_with_credentials)\n     *      for more information.\n     *    - **responseType** - `{string}` - see\n     *      [requestType](https://developer.mozilla.org/en-US/docs/DOM/XMLHttpRequest#responseType).\n     *\n     * @returns {HttpPromise} Returns a {@link ng.$q promise} object with the\n     *   standard `then` method and two http specific methods: `success` and `error`. The `then`\n     *   method takes two arguments a success and an error callback which will be called with a\n     *   response object. The `success` and `error` methods take a single argument - a function that\n     *   will be called when the request succeeds or fails respectively. The arguments passed into\n     *   these functions are destructured representation of the response object passed into the\n     *   `then` method. The response object has these properties:\n     *\n     *   - **data** – `{string|Object}` – The response body transformed with the transform\n     *     functions.\n     *   - **status** – `{number}` – HTTP status code of the response.\n     *   - **headers** – `{function([headerName])}` – Header getter function.\n     *   - **config** – `{Object}` – The configuration object that was used to generate the request.\n     *   - **statusText** – `{string}` – HTTP status text of the response.\n     *\n     * @property {Array.<Object>} pendingRequests Array of config objects for currently pending\n     *   requests. This is primarily meant to be used for debugging purposes.\n     *\n     *\n     * @example\n<example module=\"httpExample\">\n<file name=\"index.html\">\n  <div ng-controller=\"FetchController\">\n    <select ng-model=\"method\">\n      <option>GET</option>\n      <option>JSONP</option>\n    </select>\n    <input type=\"text\" ng-model=\"url\" size=\"80\"/>\n    <button id=\"fetchbtn\" ng-click=\"fetch()\">fetch</button><br>\n    <button id=\"samplegetbtn\" ng-click=\"updateModel('GET', 'http-hello.html')\">Sample GET</button>\n    <button id=\"samplejsonpbtn\"\n      ng-click=\"updateModel('JSONP',\n                    'https://angularjs.org/greet.php?callback=JSON_CALLBACK&name=Super%20Hero')\">\n      Sample JSONP\n    </button>\n    <button id=\"invalidjsonpbtn\"\n      ng-click=\"updateModel('JSONP', 'https://angularjs.org/doesntexist&callback=JSON_CALLBACK')\">\n        Invalid JSONP\n      </button>\n    <pre>http status code: {{status}}</pre>\n    <pre>http response data: {{data}}</pre>\n  </div>\n</file>\n<file name=\"script.js\">\n  angular.module('httpExample', [])\n    .controller('FetchController', ['$scope', '$http', '$templateCache',\n      function($scope, $http, $templateCache) {\n        $scope.method = 'GET';\n        $scope.url = 'http-hello.html';\n\n        $scope.fetch = function() {\n          $scope.code = null;\n          $scope.response = null;\n\n          $http({method: $scope.method, url: $scope.url, cache: $templateCache}).\n            success(function(data, status) {\n              $scope.status = status;\n              $scope.data = data;\n            }).\n            error(function(data, status) {\n              $scope.data = data || \"Request failed\";\n              $scope.status = status;\n          });\n        };\n\n        $scope.updateModel = function(method, url) {\n          $scope.method = method;\n          $scope.url = url;\n        };\n      }]);\n</file>\n<file name=\"http-hello.html\">\n  Hello, $http!\n</file>\n<file name=\"protractor.js\" type=\"protractor\">\n  var status = element(by.binding('status'));\n  var data = element(by.binding('data'));\n  var fetchBtn = element(by.id('fetchbtn'));\n  var sampleGetBtn = element(by.id('samplegetbtn'));\n  var sampleJsonpBtn = element(by.id('samplejsonpbtn'));\n  var invalidJsonpBtn = element(by.id('invalidjsonpbtn'));\n\n  it('should make an xhr GET request', function() {\n    sampleGetBtn.click();\n    fetchBtn.click();\n    expect(status.getText()).toMatch('200');\n    expect(data.getText()).toMatch(/Hello, \\$http!/);\n  });\n\n// Commented out due to flakes. See https://github.com/angular/angular.js/issues/9185\n// it('should make a JSONP request to angularjs.org', function() {\n//   sampleJsonpBtn.click();\n//   fetchBtn.click();\n//   expect(status.getText()).toMatch('200');\n//   expect(data.getText()).toMatch(/Super Hero!/);\n// });\n\n  it('should make JSONP request to invalid URL and invoke the error handler',\n      function() {\n    invalidJsonpBtn.click();\n    fetchBtn.click();\n    expect(status.getText()).toMatch('0');\n    expect(data.getText()).toMatch('Request failed');\n  });\n</file>\n</example>\n     */\n    function $http(requestConfig) {\n\n      if (!angular.isObject(requestConfig)) {\n        throw minErr('$http')('badreq', 'Http request configuration must be an object.  Received: {0}', requestConfig);\n      }\n\n      var config = extend({\n        method: 'get',\n        transformRequest: defaults.transformRequest,\n        transformResponse: defaults.transformResponse\n      }, requestConfig);\n\n      config.headers = mergeHeaders(requestConfig);\n      config.method = uppercase(config.method);\n\n      var serverRequest = function(config) {\n        var headers = config.headers;\n        var reqData = transformData(config.data, headersGetter(headers), undefined, config.transformRequest);\n\n        // strip content-type if data is undefined\n        if (isUndefined(reqData)) {\n          forEach(headers, function(value, header) {\n            if (lowercase(header) === 'content-type') {\n                delete headers[header];\n            }\n          });\n        }\n\n        if (isUndefined(config.withCredentials) && !isUndefined(defaults.withCredentials)) {\n          config.withCredentials = defaults.withCredentials;\n        }\n\n        // send request\n        return sendReq(config, reqData).then(transformResponse, transformResponse);\n      };\n\n      var chain = [serverRequest, undefined];\n      var promise = $q.when(config);\n\n      // apply interceptors\n      forEach(reversedInterceptors, function(interceptor) {\n        if (interceptor.request || interceptor.requestError) {\n          chain.unshift(interceptor.request, interceptor.requestError);\n        }\n        if (interceptor.response || interceptor.responseError) {\n          chain.push(interceptor.response, interceptor.responseError);\n        }\n      });\n\n      while (chain.length) {\n        var thenFn = chain.shift();\n        var rejectFn = chain.shift();\n\n        promise = promise.then(thenFn, rejectFn);\n      }\n\n      promise.success = function(fn) {\n        promise.then(function(response) {\n          fn(response.data, response.status, response.headers, config);\n        });\n        return promise;\n      };\n\n      promise.error = function(fn) {\n        promise.then(null, function(response) {\n          fn(response.data, response.status, response.headers, config);\n        });\n        return promise;\n      };\n\n      return promise;\n\n      function transformResponse(response) {\n        // make a copy since the response must be cacheable\n        var resp = extend({}, response);\n        if (!response.data) {\n          resp.data = response.data;\n        } else {\n          resp.data = transformData(response.data, response.headers, response.status, config.transformResponse);\n        }\n        return (isSuccess(response.status))\n          ? resp\n          : $q.reject(resp);\n      }\n\n      function executeHeaderFns(headers) {\n        var headerContent, processedHeaders = {};\n\n        forEach(headers, function(headerFn, header) {\n          if (isFunction(headerFn)) {\n            headerContent = headerFn();\n            if (headerContent != null) {\n              processedHeaders[header] = headerContent;\n            }\n          } else {\n            processedHeaders[header] = headerFn;\n          }\n        });\n\n        return processedHeaders;\n      }\n\n      function mergeHeaders(config) {\n        var defHeaders = defaults.headers,\n            reqHeaders = extend({}, config.headers),\n            defHeaderName, lowercaseDefHeaderName, reqHeaderName;\n\n        defHeaders = extend({}, defHeaders.common, defHeaders[lowercase(config.method)]);\n\n        // using for-in instead of forEach to avoid unecessary iteration after header has been found\n        defaultHeadersIteration:\n        for (defHeaderName in defHeaders) {\n          lowercaseDefHeaderName = lowercase(defHeaderName);\n\n          for (reqHeaderName in reqHeaders) {\n            if (lowercase(reqHeaderName) === lowercaseDefHeaderName) {\n              continue defaultHeadersIteration;\n            }\n          }\n\n          reqHeaders[defHeaderName] = defHeaders[defHeaderName];\n        }\n\n        // execute if header value is a function for merged headers\n        return executeHeaderFns(reqHeaders);\n      }\n    }\n\n    $http.pendingRequests = [];\n\n    /**\n     * @ngdoc method\n     * @name $http#get\n     *\n     * @description\n     * Shortcut method to perform `GET` request.\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name $http#delete\n     *\n     * @description\n     * Shortcut method to perform `DELETE` request.\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name $http#head\n     *\n     * @description\n     * Shortcut method to perform `HEAD` request.\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name $http#jsonp\n     *\n     * @description\n     * Shortcut method to perform `JSONP` request.\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request.\n     *                     The name of the callback should be the string `JSON_CALLBACK`.\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n    createShortMethods('get', 'delete', 'head', 'jsonp');\n\n    /**\n     * @ngdoc method\n     * @name $http#post\n     *\n     * @description\n     * Shortcut method to perform `POST` request.\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {*} data Request content\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name $http#put\n     *\n     * @description\n     * Shortcut method to perform `PUT` request.\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {*} data Request content\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n     /**\n      * @ngdoc method\n      * @name $http#patch\n      *\n      * @description\n      * Shortcut method to perform `PATCH` request.\n      *\n      * @param {string} url Relative or absolute URL specifying the destination of the request\n      * @param {*} data Request content\n      * @param {Object=} config Optional configuration object\n      * @returns {HttpPromise} Future object\n      */\n    createShortMethodsWithData('post', 'put', 'patch');\n\n        /**\n         * @ngdoc property\n         * @name $http#defaults\n         *\n         * @description\n         * Runtime equivalent of the `$httpProvider.defaults` property. Allows configuration of\n         * default headers, withCredentials as well as request and response transformations.\n         *\n         * See \"Setting HTTP Headers\" and \"Transforming Requests and Responses\" sections above.\n         */\n    $http.defaults = defaults;\n\n\n    return $http;\n\n\n    function createShortMethods(names) {\n      forEach(arguments, function(name) {\n        $http[name] = function(url, config) {\n          return $http(extend(config || {}, {\n            method: name,\n            url: url\n          }));\n        };\n      });\n    }\n\n\n    function createShortMethodsWithData(name) {\n      forEach(arguments, function(name) {\n        $http[name] = function(url, data, config) {\n          return $http(extend(config || {}, {\n            method: name,\n            url: url,\n            data: data\n          }));\n        };\n      });\n    }\n\n\n    /**\n     * Makes the request.\n     *\n     * !!! ACCESSES CLOSURE VARS:\n     * $httpBackend, defaults, $log, $rootScope, defaultCache, $http.pendingRequests\n     */\n    function sendReq(config, reqData) {\n      var deferred = $q.defer(),\n          promise = deferred.promise,\n          cache,\n          cachedResp,\n          reqHeaders = config.headers,\n          url = buildUrl(config.url, config.params);\n\n      $http.pendingRequests.push(config);\n      promise.then(removePendingReq, removePendingReq);\n\n\n      if ((config.cache || defaults.cache) && config.cache !== false &&\n          (config.method === 'GET' || config.method === 'JSONP')) {\n        cache = isObject(config.cache) ? config.cache\n              : isObject(defaults.cache) ? defaults.cache\n              : defaultCache;\n      }\n\n      if (cache) {\n        cachedResp = cache.get(url);\n        if (isDefined(cachedResp)) {\n          if (isPromiseLike(cachedResp)) {\n            // cached request has already been sent, but there is no response yet\n            cachedResp.then(resolvePromiseWithResult, resolvePromiseWithResult);\n          } else {\n            // serving from cache\n            if (isArray(cachedResp)) {\n              resolvePromise(cachedResp[1], cachedResp[0], shallowCopy(cachedResp[2]), cachedResp[3]);\n            } else {\n              resolvePromise(cachedResp, 200, {}, 'OK');\n            }\n          }\n        } else {\n          // put the promise for the non-transformed response into cache as a placeholder\n          cache.put(url, promise);\n        }\n      }\n\n\n      // if we won't have the response in cache, set the xsrf headers and\n      // send the request to the backend\n      if (isUndefined(cachedResp)) {\n        var xsrfValue = urlIsSameOrigin(config.url)\n            ? $browser.cookies()[config.xsrfCookieName || defaults.xsrfCookieName]\n            : undefined;\n        if (xsrfValue) {\n          reqHeaders[(config.xsrfHeaderName || defaults.xsrfHeaderName)] = xsrfValue;\n        }\n\n        $httpBackend(config.method, url, reqData, done, reqHeaders, config.timeout,\n            config.withCredentials, config.responseType);\n      }\n\n      return promise;\n\n\n      /**\n       * Callback registered to $httpBackend():\n       *  - caches the response if desired\n       *  - resolves the raw $http promise\n       *  - calls $apply\n       */\n      function done(status, response, headersString, statusText) {\n        if (cache) {\n          if (isSuccess(status)) {\n            cache.put(url, [status, response, parseHeaders(headersString), statusText]);\n          } else {\n            // remove promise from the cache\n            cache.remove(url);\n          }\n        }\n\n        function resolveHttpPromise() {\n          resolvePromise(response, status, headersString, statusText);\n        }\n\n        if (useApplyAsync) {\n          $rootScope.$applyAsync(resolveHttpPromise);\n        } else {\n          resolveHttpPromise();\n          if (!$rootScope.$$phase) $rootScope.$apply();\n        }\n      }\n\n\n      /**\n       * Resolves the raw $http promise.\n       */\n      function resolvePromise(response, status, headers, statusText) {\n        // normalize internal statuses to 0\n        status = Math.max(status, 0);\n\n        (isSuccess(status) ? deferred.resolve : deferred.reject)({\n          data: response,\n          status: status,\n          headers: headersGetter(headers),\n          config: config,\n          statusText: statusText\n        });\n      }\n\n      function resolvePromiseWithResult(result) {\n        resolvePromise(result.data, result.status, shallowCopy(result.headers()), result.statusText);\n      }\n\n      function removePendingReq() {\n        var idx = $http.pendingRequests.indexOf(config);\n        if (idx !== -1) $http.pendingRequests.splice(idx, 1);\n      }\n    }\n\n\n    function buildUrl(url, params) {\n      if (!params) return url;\n      var parts = [];\n      forEachSorted(params, function(value, key) {\n        if (value === null || isUndefined(value)) return;\n        if (!isArray(value)) value = [value];\n\n        forEach(value, function(v) {\n          if (isObject(v)) {\n            if (isDate(v)) {\n              v = v.toISOString();\n            } else {\n              v = toJson(v);\n            }\n          }\n          parts.push(encodeUriQuery(key) + '=' +\n                     encodeUriQuery(v));\n        });\n      });\n      if (parts.length > 0) {\n        url += ((url.indexOf('?') == -1) ? '?' : '&') + parts.join('&');\n      }\n      return url;\n    }\n  }];\n}\n\nfunction createXhr() {\n    return new window.XMLHttpRequest();\n}\n\n/**\n * @ngdoc service\n * @name $httpBackend\n * @requires $window\n * @requires $document\n *\n * @description\n * HTTP backend used by the {@link ng.$http service} that delegates to\n * XMLHttpRequest object or JSONP and deals with browser incompatibilities.\n *\n * You should never need to use this service directly, instead use the higher-level abstractions:\n * {@link ng.$http $http} or {@link ngResource.$resource $resource}.\n *\n * During testing this implementation is swapped with {@link ngMock.$httpBackend mock\n * $httpBackend} which can be trained with responses.\n */\nfunction $HttpBackendProvider() {\n  this.$get = ['$browser', '$window', '$document', function($browser, $window, $document) {\n    return createHttpBackend($browser, createXhr, $browser.defer, $window.angular.callbacks, $document[0]);\n  }];\n}\n\nfunction createHttpBackend($browser, createXhr, $browserDefer, callbacks, rawDocument) {\n  // TODO(vojta): fix the signature\n  return function(method, url, post, callback, headers, timeout, withCredentials, responseType) {\n    $browser.$$incOutstandingRequestCount();\n    url = url || $browser.url();\n\n    if (lowercase(method) == 'jsonp') {\n      var callbackId = '_' + (callbacks.counter++).toString(36);\n      callbacks[callbackId] = function(data) {\n        callbacks[callbackId].data = data;\n        callbacks[callbackId].called = true;\n      };\n\n      var jsonpDone = jsonpReq(url.replace('JSON_CALLBACK', 'angular.callbacks.' + callbackId),\n          callbackId, function(status, text) {\n        completeRequest(callback, status, callbacks[callbackId].data, \"\", text);\n        callbacks[callbackId] = noop;\n      });\n    } else {\n\n      var xhr = createXhr();\n\n      xhr.open(method, url, true);\n      forEach(headers, function(value, key) {\n        if (isDefined(value)) {\n            xhr.setRequestHeader(key, value);\n        }\n      });\n\n      xhr.onload = function requestLoaded() {\n        var statusText = xhr.statusText || '';\n\n        // responseText is the old-school way of retrieving response (supported by IE8 & 9)\n        // response/responseType properties were introduced in XHR Level2 spec (supported by IE10)\n        var response = ('response' in xhr) ? xhr.response : xhr.responseText;\n\n        // normalize IE9 bug (http://bugs.jquery.com/ticket/1450)\n        var status = xhr.status === 1223 ? 204 : xhr.status;\n\n        // fix status code when it is 0 (0 status is undocumented).\n        // Occurs when accessing file resources or on Android 4.1 stock browser\n        // while retrieving files from application cache.\n        if (status === 0) {\n          status = response ? 200 : urlResolve(url).protocol == 'file' ? 404 : 0;\n        }\n\n        completeRequest(callback,\n            status,\n            response,\n            xhr.getAllResponseHeaders(),\n            statusText);\n      };\n\n      var requestError = function() {\n        // The response is always empty\n        // See https://xhr.spec.whatwg.org/#request-error-steps and https://fetch.spec.whatwg.org/#concept-network-error\n        completeRequest(callback, -1, null, null, '');\n      };\n\n      xhr.onerror = requestError;\n      xhr.onabort = requestError;\n\n      if (withCredentials) {\n        xhr.withCredentials = true;\n      }\n\n      if (responseType) {\n        try {\n          xhr.responseType = responseType;\n        } catch (e) {\n          // WebKit added support for the json responseType value on 09/03/2013\n          // https://bugs.webkit.org/show_bug.cgi?id=73648. Versions of Safari prior to 7 are\n          // known to throw when setting the value \"json\" as the response type. Other older\n          // browsers implementing the responseType\n          //\n          // The json response type can be ignored if not supported, because JSON payloads are\n          // parsed on the client-side regardless.\n          if (responseType !== 'json') {\n            throw e;\n          }\n        }\n      }\n\n      xhr.send(post || null);\n    }\n\n    if (timeout > 0) {\n      var timeoutId = $browserDefer(timeoutRequest, timeout);\n    } else if (isPromiseLike(timeout)) {\n      timeout.then(timeoutRequest);\n    }\n\n\n    function timeoutRequest() {\n      jsonpDone && jsonpDone();\n      xhr && xhr.abort();\n    }\n\n    function completeRequest(callback, status, response, headersString, statusText) {\n      // cancel timeout and subsequent timeout promise resolution\n      if (timeoutId !== undefined) {\n        $browserDefer.cancel(timeoutId);\n      }\n      jsonpDone = xhr = null;\n\n      callback(status, response, headersString, statusText);\n      $browser.$$completeOutstandingRequest(noop);\n    }\n  };\n\n  function jsonpReq(url, callbackId, done) {\n    // we can't use jQuery/jqLite here because jQuery does crazy shit with script elements, e.g.:\n    // - fetches local scripts via XHR and evals them\n    // - adds and immediately removes script elements from the document\n    var script = rawDocument.createElement('script'), callback = null;\n    script.type = \"text/javascript\";\n    script.src = url;\n    script.async = true;\n\n    callback = function(event) {\n      removeEventListenerFn(script, \"load\", callback);\n      removeEventListenerFn(script, \"error\", callback);\n      rawDocument.body.removeChild(script);\n      script = null;\n      var status = -1;\n      var text = \"unknown\";\n\n      if (event) {\n        if (event.type === \"load\" && !callbacks[callbackId].called) {\n          event = { type: \"error\" };\n        }\n        text = event.type;\n        status = event.type === \"error\" ? 404 : 200;\n      }\n\n      if (done) {\n        done(status, text);\n      }\n    };\n\n    addEventListenerFn(script, \"load\", callback);\n    addEventListenerFn(script, \"error\", callback);\n    rawDocument.body.appendChild(script);\n    return callback;\n  }\n}\n\nvar $interpolateMinErr = minErr('$interpolate');\n\n/**\n * @ngdoc provider\n * @name $interpolateProvider\n *\n * @description\n *\n * Used for configuring the interpolation markup. Defaults to `{{` and `}}`.\n *\n * @example\n<example module=\"customInterpolationApp\">\n<file name=\"index.html\">\n<script>\n  var customInterpolationApp = angular.module('customInterpolationApp', []);\n\n  customInterpolationApp.config(function($interpolateProvider) {\n    $interpolateProvider.startSymbol('//');\n    $interpolateProvider.endSymbol('//');\n  });\n\n\n  customInterpolationApp.controller('DemoController', function() {\n      this.label = \"This binding is brought you by // interpolation symbols.\";\n  });\n</script>\n<div ng-app=\"App\" ng-controller=\"DemoController as demo\">\n    //demo.label//\n</div>\n</file>\n<file name=\"protractor.js\" type=\"protractor\">\n  it('should interpolate binding with custom symbols', function() {\n    expect(element(by.binding('demo.label')).getText()).toBe('This binding is brought you by // interpolation symbols.');\n  });\n</file>\n</example>\n */\nfunction $InterpolateProvider() {\n  var startSymbol = '{{';\n  var endSymbol = '}}';\n\n  /**\n   * @ngdoc method\n   * @name $interpolateProvider#startSymbol\n   * @description\n   * Symbol to denote start of expression in the interpolated string. Defaults to `{{`.\n   *\n   * @param {string=} value new value to set the starting symbol to.\n   * @returns {string|self} Returns the symbol when used as getter and self if used as setter.\n   */\n  this.startSymbol = function(value) {\n    if (value) {\n      startSymbol = value;\n      return this;\n    } else {\n      return startSymbol;\n    }\n  };\n\n  /**\n   * @ngdoc method\n   * @name $interpolateProvider#endSymbol\n   * @description\n   * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.\n   *\n   * @param {string=} value new value to set the ending symbol to.\n   * @returns {string|self} Returns the symbol when used as getter and self if used as setter.\n   */\n  this.endSymbol = function(value) {\n    if (value) {\n      endSymbol = value;\n      return this;\n    } else {\n      return endSymbol;\n    }\n  };\n\n\n  this.$get = ['$parse', '$exceptionHandler', '$sce', function($parse, $exceptionHandler, $sce) {\n    var startSymbolLength = startSymbol.length,\n        endSymbolLength = endSymbol.length,\n        escapedStartRegexp = new RegExp(startSymbol.replace(/./g, escape), 'g'),\n        escapedEndRegexp = new RegExp(endSymbol.replace(/./g, escape), 'g');\n\n    function escape(ch) {\n      return '\\\\\\\\\\\\' + ch;\n    }\n\n    /**\n     * @ngdoc service\n     * @name $interpolate\n     * @kind function\n     *\n     * @requires $parse\n     * @requires $sce\n     *\n     * @description\n     *\n     * Compiles a string with markup into an interpolation function. This service is used by the\n     * HTML {@link ng.$compile $compile} service for data binding. See\n     * {@link ng.$interpolateProvider $interpolateProvider} for configuring the\n     * interpolation markup.\n     *\n     *\n     * ```js\n     *   var $interpolate = ...; // injected\n     *   var exp = $interpolate('Hello {{name | uppercase}}!');\n     *   expect(exp({name:'Angular'}).toEqual('Hello ANGULAR!');\n     * ```\n     *\n     * `$interpolate` takes an optional fourth argument, `allOrNothing`. If `allOrNothing` is\n     * `true`, the interpolation function will return `undefined` unless all embedded expressions\n     * evaluate to a value other than `undefined`.\n     *\n     * ```js\n     *   var $interpolate = ...; // injected\n     *   var context = {greeting: 'Hello', name: undefined };\n     *\n     *   // default \"forgiving\" mode\n     *   var exp = $interpolate('{{greeting}} {{name}}!');\n     *   expect(exp(context)).toEqual('Hello !');\n     *\n     *   // \"allOrNothing\" mode\n     *   exp = $interpolate('{{greeting}} {{name}}!', false, null, true);\n     *   expect(exp(context)).toBeUndefined();\n     *   context.name = 'Angular';\n     *   expect(exp(context)).toEqual('Hello Angular!');\n     * ```\n     *\n     * `allOrNothing` is useful for interpolating URLs. `ngSrc` and `ngSrcset` use this behavior.\n     *\n     * ####Escaped Interpolation\n     * $interpolate provides a mechanism for escaping interpolation markers. Start and end markers\n     * can be escaped by preceding each of their characters with a REVERSE SOLIDUS U+005C (backslash).\n     * It will be rendered as a regular start/end marker, and will not be interpreted as an expression\n     * or binding.\n     *\n     * This enables web-servers to prevent script injection attacks and defacing attacks, to some\n     * degree, while also enabling code examples to work without relying on the\n     * {@link ng.directive:ngNonBindable ngNonBindable} directive.\n     *\n     * **For security purposes, it is strongly encouraged that web servers escape user-supplied data,\n     * replacing angle brackets (&lt;, &gt;) with &amp;lt; and &amp;gt; respectively, and replacing all\n     * interpolation start/end markers with their escaped counterparts.**\n     *\n     * Escaped interpolation markers are only replaced with the actual interpolation markers in rendered\n     * output when the $interpolate service processes the text. So, for HTML elements interpolated\n     * by {@link ng.$compile $compile}, or otherwise interpolated with the `mustHaveExpression` parameter\n     * set to `true`, the interpolated text must contain an unescaped interpolation expression. As such,\n     * this is typically useful only when user-data is used in rendering a template from the server, or\n     * when otherwise untrusted data is used by a directive.\n     *\n     * <example>\n     *  <file name=\"index.html\">\n     *    <div ng-init=\"username='A user'\">\n     *      <p ng-init=\"apptitle='Escaping demo'\">{{apptitle}}: \\{\\{ username = \"defaced value\"; \\}\\}\n     *        </p>\n     *      <p><strong>{{username}}</strong> attempts to inject code which will deface the\n     *        application, but fails to accomplish their task, because the server has correctly\n     *        escaped the interpolation start/end markers with REVERSE SOLIDUS U+005C (backslash)\n     *        characters.</p>\n     *      <p>Instead, the result of the attempted script injection is visible, and can be removed\n     *        from the database by an administrator.</p>\n     *    </div>\n     *  </file>\n     * </example>\n     *\n     * @param {string} text The text with markup to interpolate.\n     * @param {boolean=} mustHaveExpression if set to true then the interpolation string must have\n     *    embedded expression in order to return an interpolation function. Strings with no\n     *    embedded expression will return null for the interpolation function.\n     * @param {string=} trustedContext when provided, the returned function passes the interpolated\n     *    result through {@link ng.$sce#getTrusted $sce.getTrusted(interpolatedResult,\n     *    trustedContext)} before returning it.  Refer to the {@link ng.$sce $sce} service that\n     *    provides Strict Contextual Escaping for details.\n     * @param {boolean=} allOrNothing if `true`, then the returned function returns undefined\n     *    unless all embedded expressions evaluate to a value other than `undefined`.\n     * @returns {function(context)} an interpolation function which is used to compute the\n     *    interpolated string. The function has these parameters:\n     *\n     * - `context`: evaluation context for all expressions embedded in the interpolated text\n     */\n    function $interpolate(text, mustHaveExpression, trustedContext, allOrNothing) {\n      allOrNothing = !!allOrNothing;\n      var startIndex,\n          endIndex,\n          index = 0,\n          expressions = [],\n          parseFns = [],\n          textLength = text.length,\n          exp,\n          concat = [],\n          expressionPositions = [];\n\n      while (index < textLength) {\n        if (((startIndex = text.indexOf(startSymbol, index)) != -1) &&\n             ((endIndex = text.indexOf(endSymbol, startIndex + startSymbolLength)) != -1)) {\n          if (index !== startIndex) {\n            concat.push(unescapeText(text.substring(index, startIndex)));\n          }\n          exp = text.substring(startIndex + startSymbolLength, endIndex);\n          expressions.push(exp);\n          parseFns.push($parse(exp, parseStringifyInterceptor));\n          index = endIndex + endSymbolLength;\n          expressionPositions.push(concat.length);\n          concat.push('');\n        } else {\n          // we did not find an interpolation, so we have to add the remainder to the separators array\n          if (index !== textLength) {\n            concat.push(unescapeText(text.substring(index)));\n          }\n          break;\n        }\n      }\n\n      // Concatenating expressions makes it hard to reason about whether some combination of\n      // concatenated values are unsafe to use and could easily lead to XSS.  By requiring that a\n      // single expression be used for iframe[src], object[src], etc., we ensure that the value\n      // that's used is assigned or constructed by some JS code somewhere that is more testable or\n      // make it obvious that you bound the value to some user controlled value.  This helps reduce\n      // the load when auditing for XSS issues.\n      if (trustedContext && concat.length > 1) {\n          throw $interpolateMinErr('noconcat',\n              \"Error while interpolating: {0}\\nStrict Contextual Escaping disallows \" +\n              \"interpolations that concatenate multiple expressions when a trusted value is \" +\n              \"required.  See http://docs.angularjs.org/api/ng.$sce\", text);\n      }\n\n      if (!mustHaveExpression || expressions.length) {\n        var compute = function(values) {\n          for (var i = 0, ii = expressions.length; i < ii; i++) {\n            if (allOrNothing && isUndefined(values[i])) return;\n            concat[expressionPositions[i]] = values[i];\n          }\n          return concat.join('');\n        };\n\n        var getValue = function(value) {\n          return trustedContext ?\n            $sce.getTrusted(trustedContext, value) :\n            $sce.valueOf(value);\n        };\n\n        var stringify = function(value) {\n          if (value == null) { // null || undefined\n            return '';\n          }\n          switch (typeof value) {\n            case 'string':\n              break;\n            case 'number':\n              value = '' + value;\n              break;\n            default:\n              value = toJson(value);\n          }\n\n          return value;\n        };\n\n        return extend(function interpolationFn(context) {\n            var i = 0;\n            var ii = expressions.length;\n            var values = new Array(ii);\n\n            try {\n              for (; i < ii; i++) {\n                values[i] = parseFns[i](context);\n              }\n\n              return compute(values);\n            } catch (err) {\n              var newErr = $interpolateMinErr('interr', \"Can't interpolate: {0}\\n{1}\", text,\n                  err.toString());\n              $exceptionHandler(newErr);\n            }\n\n          }, {\n          // all of these properties are undocumented for now\n          exp: text, //just for compatibility with regular watchers created via $watch\n          expressions: expressions,\n          $$watchDelegate: function(scope, listener, objectEquality) {\n            var lastValue;\n            return scope.$watchGroup(parseFns, function interpolateFnWatcher(values, oldValues) {\n              var currValue = compute(values);\n              if (isFunction(listener)) {\n                listener.call(this, currValue, values !== oldValues ? lastValue : currValue, scope);\n              }\n              lastValue = currValue;\n            }, objectEquality);\n          }\n        });\n      }\n\n      function unescapeText(text) {\n        return text.replace(escapedStartRegexp, startSymbol).\n          replace(escapedEndRegexp, endSymbol);\n      }\n\n      function parseStringifyInterceptor(value) {\n        try {\n          value = getValue(value);\n          return allOrNothing && !isDefined(value) ? value : stringify(value);\n        } catch (err) {\n          var newErr = $interpolateMinErr('interr', \"Can't interpolate: {0}\\n{1}\", text,\n            err.toString());\n          $exceptionHandler(newErr);\n        }\n      }\n    }\n\n\n    /**\n     * @ngdoc method\n     * @name $interpolate#startSymbol\n     * @description\n     * Symbol to denote the start of expression in the interpolated string. Defaults to `{{`.\n     *\n     * Use {@link ng.$interpolateProvider#startSymbol `$interpolateProvider.startSymbol`} to change\n     * the symbol.\n     *\n     * @returns {string} start symbol.\n     */\n    $interpolate.startSymbol = function() {\n      return startSymbol;\n    };\n\n\n    /**\n     * @ngdoc method\n     * @name $interpolate#endSymbol\n     * @description\n     * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.\n     *\n     * Use {@link ng.$interpolateProvider#endSymbol `$interpolateProvider.endSymbol`} to change\n     * the symbol.\n     *\n     * @returns {string} end symbol.\n     */\n    $interpolate.endSymbol = function() {\n      return endSymbol;\n    };\n\n    return $interpolate;\n  }];\n}\n\nfunction $IntervalProvider() {\n  this.$get = ['$rootScope', '$window', '$q', '$$q',\n       function($rootScope,   $window,   $q,   $$q) {\n    var intervals = {};\n\n\n     /**\n      * @ngdoc service\n      * @name $interval\n      *\n      * @description\n      * Angular's wrapper for `window.setInterval`. The `fn` function is executed every `delay`\n      * milliseconds.\n      *\n      * The return value of registering an interval function is a promise. This promise will be\n      * notified upon each tick of the interval, and will be resolved after `count` iterations, or\n      * run indefinitely if `count` is not defined. The value of the notification will be the\n      * number of iterations that have run.\n      * To cancel an interval, call `$interval.cancel(promise)`.\n      *\n      * In tests you can use {@link ngMock.$interval#flush `$interval.flush(millis)`} to\n      * move forward by `millis` milliseconds and trigger any functions scheduled to run in that\n      * time.\n      *\n      * <div class=\"alert alert-warning\">\n      * **Note**: Intervals created by this service must be explicitly destroyed when you are finished\n      * with them.  In particular they are not automatically destroyed when a controller's scope or a\n      * directive's element are destroyed.\n      * You should take this into consideration and make sure to always cancel the interval at the\n      * appropriate moment.  See the example below for more details on how and when to do this.\n      * </div>\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#$apply $apply} block.\n      * @returns {promise} A promise which will be notified on each iteration.\n      *\n      * @example\n      * <example module=\"intervalExample\">\n      * <file name=\"index.html\">\n      *   <script>\n      *     angular.module('intervalExample', [])\n      *       .controller('ExampleController', ['$scope', '$interval',\n      *         function($scope, $interval) {\n      *           $scope.format = 'M/d/yy h:mm:ss a';\n      *           $scope.blood_1 = 100;\n      *           $scope.blood_2 = 120;\n      *\n      *           var stop;\n      *           $scope.fight = function() {\n      *             // Don't start a new fight if we are already fighting\n      *             if ( angular.isDefined(stop) ) return;\n      *\n      *             stop = $interval(function() {\n      *               if ($scope.blood_1 > 0 && $scope.blood_2 > 0) {\n      *                 $scope.blood_1 = $scope.blood_1 - 3;\n      *                 $scope.blood_2 = $scope.blood_2 - 4;\n      *               } else {\n      *                 $scope.stopFight();\n      *               }\n      *             }, 100);\n      *           };\n      *\n      *           $scope.stopFight = function() {\n      *             if (angular.isDefined(stop)) {\n      *               $interval.cancel(stop);\n      *               stop = undefined;\n      *             }\n      *           };\n      *\n      *           $scope.resetFight = function() {\n      *             $scope.blood_1 = 100;\n      *             $scope.blood_2 = 120;\n      *           };\n      *\n      *           $scope.$on('$destroy', function() {\n      *             // Make sure that the interval is destroyed too\n      *             $scope.stopFight();\n      *           });\n      *         }])\n      *       // Register the 'myCurrentTime' directive factory method.\n      *       // We inject $interval and dateFilter service since the factory method is DI.\n      *       .directive('myCurrentTime', ['$interval', 'dateFilter',\n      *         function($interval, dateFilter) {\n      *           // return the directive link function. (compile function not needed)\n      *           return function(scope, element, attrs) {\n      *             var format,  // date format\n      *                 stopTime; // so that we can cancel the time updates\n      *\n      *             // used to update the UI\n      *             function updateTime() {\n      *               element.text(dateFilter(new Date(), format));\n      *             }\n      *\n      *             // watch the expression, and update the UI on change.\n      *             scope.$watch(attrs.myCurrentTime, function(value) {\n      *               format = value;\n      *               updateTime();\n      *             });\n      *\n      *             stopTime = $interval(updateTime, 1000);\n      *\n      *             // listen on DOM destroy (removal) event, and cancel the next UI update\n      *             // to prevent updating time after the DOM element was removed.\n      *             element.on('$destroy', function() {\n      *               $interval.cancel(stopTime);\n      *             });\n      *           }\n      *         }]);\n      *   </script>\n      *\n      *   <div>\n      *     <div ng-controller=\"ExampleController\">\n      *       Date format: <input ng-model=\"format\"> <hr/>\n      *       Current time is: <span my-current-time=\"format\"></span>\n      *       <hr/>\n      *       Blood 1 : <font color='red'>{{blood_1}}</font>\n      *       Blood 2 : <font color='red'>{{blood_2}}</font>\n      *       <button type=\"button\" data-ng-click=\"fight()\">Fight</button>\n      *       <button type=\"button\" data-ng-click=\"stopFight()\">StopFight</button>\n      *       <button type=\"button\" data-ng-click=\"resetFight()\">resetFight</button>\n      *     </div>\n      *   </div>\n      *\n      * </file>\n      * </example>\n      */\n    function interval(fn, delay, count, invokeApply) {\n      var setInterval = $window.setInterval,\n          clearInterval = $window.clearInterval,\n          iteration = 0,\n          skipApply = (isDefined(invokeApply) && !invokeApply),\n          deferred = (skipApply ? $$q : $q).defer(),\n          promise = deferred.promise;\n\n      count = isDefined(count) ? count : 0;\n\n      promise.then(null, null, fn);\n\n      promise.$$intervalId = setInterval(function tick() {\n        deferred.notify(iteration++);\n\n        if (count > 0 && iteration >= count) {\n          deferred.resolve(iteration);\n          clearInterval(promise.$$intervalId);\n          delete intervals[promise.$$intervalId];\n        }\n\n        if (!skipApply) $rootScope.$apply();\n\n      }, delay);\n\n      intervals[promise.$$intervalId] = deferred;\n\n      return promise;\n    }\n\n\n     /**\n      * @ngdoc method\n      * @name $interval#cancel\n      *\n      * @description\n      * Cancels a task associated with the `promise`.\n      *\n      * @param {promise} promise returned by the `$interval` function.\n      * @returns {boolean} Returns `true` if the task was successfully canceled.\n      */\n    interval.cancel = function(promise) {\n      if (promise && promise.$$intervalId in intervals) {\n        intervals[promise.$$intervalId].reject('canceled');\n        $window.clearInterval(promise.$$intervalId);\n        delete intervals[promise.$$intervalId];\n        return true;\n      }\n      return false;\n    };\n\n    return interval;\n  }];\n}\n\n/**\n * @ngdoc service\n * @name $locale\n *\n * @description\n * $locale service provides localization rules for various Angular components. As of right now the\n * only public api is:\n *\n * * `id` – `{string}` – locale id formatted as `languageId-countryId` (e.g. `en-us`)\n */\nfunction $LocaleProvider() {\n  this.$get = function() {\n    return {\n      id: 'en-us',\n\n      NUMBER_FORMATS: {\n        DECIMAL_SEP: '.',\n        GROUP_SEP: ',',\n        PATTERNS: [\n          { // Decimal Pattern\n            minInt: 1,\n            minFrac: 0,\n            maxFrac: 3,\n            posPre: '',\n            posSuf: '',\n            negPre: '-',\n            negSuf: '',\n            gSize: 3,\n            lgSize: 3\n          },{ //Currency Pattern\n            minInt: 1,\n            minFrac: 2,\n            maxFrac: 2,\n            posPre: '\\u00A4',\n            posSuf: '',\n            negPre: '(\\u00A4',\n            negSuf: ')',\n            gSize: 3,\n            lgSize: 3\n          }\n        ],\n        CURRENCY_SYM: '$'\n      },\n\n      DATETIME_FORMATS: {\n        MONTH:\n            'January,February,March,April,May,June,July,August,September,October,November,December'\n            .split(','),\n        SHORTMONTH:  'Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec'.split(','),\n        DAY: 'Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday'.split(','),\n        SHORTDAY: 'Sun,Mon,Tue,Wed,Thu,Fri,Sat'.split(','),\n        AMPMS: ['AM','PM'],\n        medium: 'MMM d, y h:mm:ss a',\n        'short': 'M/d/yy h:mm a',\n        fullDate: 'EEEE, MMMM d, y',\n        longDate: 'MMMM d, y',\n        mediumDate: 'MMM d, y',\n        shortDate: 'M/d/yy',\n        mediumTime: 'h:mm:ss a',\n        shortTime: 'h:mm a'\n      },\n\n      pluralCat: function(num) {\n        if (num === 1) {\n          return 'one';\n        }\n        return 'other';\n      }\n    };\n  };\n}\n\nvar PATH_MATCH = /^([^\\?#]*)(\\?([^#]*))?(#(.*))?$/,\n    DEFAULT_PORTS = {'http': 80, 'https': 443, 'ftp': 21};\nvar $locationMinErr = minErr('$location');\n\n\n/**\n * Encode path using encodeUriSegment, ignoring forward slashes\n *\n * @param {string} path Path to encode\n * @returns {string}\n */\nfunction encodePath(path) {\n  var segments = path.split('/'),\n      i = segments.length;\n\n  while (i--) {\n    segments[i] = encodeUriSegment(segments[i]);\n  }\n\n  return segments.join('/');\n}\n\nfunction parseAbsoluteUrl(absoluteUrl, locationObj) {\n  var parsedUrl = urlResolve(absoluteUrl);\n\n  locationObj.$$protocol = parsedUrl.protocol;\n  locationObj.$$host = parsedUrl.hostname;\n  locationObj.$$port = int(parsedUrl.port) || DEFAULT_PORTS[parsedUrl.protocol] || null;\n}\n\n\nfunction parseAppUrl(relativeUrl, locationObj) {\n  var prefixed = (relativeUrl.charAt(0) !== '/');\n  if (prefixed) {\n    relativeUrl = '/' + relativeUrl;\n  }\n  var match = urlResolve(relativeUrl);\n  locationObj.$$path = decodeURIComponent(prefixed && match.pathname.charAt(0) === '/' ?\n      match.pathname.substring(1) : match.pathname);\n  locationObj.$$search = parseKeyValue(match.search);\n  locationObj.$$hash = decodeURIComponent(match.hash);\n\n  // make sure path starts with '/';\n  if (locationObj.$$path && locationObj.$$path.charAt(0) != '/') {\n    locationObj.$$path = '/' + locationObj.$$path;\n  }\n}\n\n\n/**\n *\n * @param {string} begin\n * @param {string} whole\n * @returns {string} returns text from whole after begin or undefined if it does not begin with\n *                   expected string.\n */\nfunction beginsWith(begin, whole) {\n  if (whole.indexOf(begin) === 0) {\n    return whole.substr(begin.length);\n  }\n}\n\n\nfunction stripHash(url) {\n  var index = url.indexOf('#');\n  return index == -1 ? url : url.substr(0, index);\n}\n\nfunction trimEmptyHash(url) {\n  return url.replace(/(#.+)|#$/, '$1');\n}\n\n\nfunction stripFile(url) {\n  return url.substr(0, stripHash(url).lastIndexOf('/') + 1);\n}\n\n/* return the server only (scheme://host:port) */\nfunction serverBase(url) {\n  return url.substring(0, url.indexOf('/', url.indexOf('//') + 2));\n}\n\n\n/**\n * LocationHtml5Url represents an url\n * This object is exposed as $location service when HTML5 mode is enabled and supported\n *\n * @constructor\n * @param {string} appBase application base URL\n * @param {string} basePrefix url path prefix\n */\nfunction LocationHtml5Url(appBase, basePrefix) {\n  this.$$html5 = true;\n  basePrefix = basePrefix || '';\n  var appBaseNoFile = stripFile(appBase);\n  parseAbsoluteUrl(appBase, this);\n\n\n  /**\n   * Parse given html5 (regular) url string into properties\n   * @param {string} url HTML5 url\n   * @private\n   */\n  this.$$parse = function(url) {\n    var pathUrl = beginsWith(appBaseNoFile, url);\n    if (!isString(pathUrl)) {\n      throw $locationMinErr('ipthprfx', 'Invalid url \"{0}\", missing path prefix \"{1}\".', url,\n          appBaseNoFile);\n    }\n\n    parseAppUrl(pathUrl, this);\n\n    if (!this.$$path) {\n      this.$$path = '/';\n    }\n\n    this.$$compose();\n  };\n\n  /**\n   * Compose url and update `absUrl` property\n   * @private\n   */\n  this.$$compose = function() {\n    var search = toKeyValue(this.$$search),\n        hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';\n\n    this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;\n    this.$$absUrl = appBaseNoFile + this.$$url.substr(1); // first char is always '/'\n  };\n\n  this.$$parseLinkUrl = function(url, relHref) {\n    if (relHref && relHref[0] === '#') {\n      // special case for links to hash fragments:\n      // keep the old url and only replace the hash fragment\n      this.hash(relHref.slice(1));\n      return true;\n    }\n    var appUrl, prevAppUrl;\n    var rewrittenUrl;\n\n    if ((appUrl = beginsWith(appBase, url)) !== undefined) {\n      prevAppUrl = appUrl;\n      if ((appUrl = beginsWith(basePrefix, appUrl)) !== undefined) {\n        rewrittenUrl = appBaseNoFile + (beginsWith('/', appUrl) || appUrl);\n      } else {\n        rewrittenUrl = appBase + prevAppUrl;\n      }\n    } else if ((appUrl = beginsWith(appBaseNoFile, url)) !== undefined) {\n      rewrittenUrl = appBaseNoFile + appUrl;\n    } else if (appBaseNoFile == url + '/') {\n      rewrittenUrl = appBaseNoFile;\n    }\n    if (rewrittenUrl) {\n      this.$$parse(rewrittenUrl);\n    }\n    return !!rewrittenUrl;\n  };\n}\n\n\n/**\n * LocationHashbangUrl represents url\n * This object is exposed as $location service when developer doesn't opt into html5 mode.\n * It also serves as the base class for html5 mode fallback on legacy browsers.\n *\n * @constructor\n * @param {string} appBase application base URL\n * @param {string} hashPrefix hashbang prefix\n */\nfunction LocationHashbangUrl(appBase, hashPrefix) {\n  var appBaseNoFile = stripFile(appBase);\n\n  parseAbsoluteUrl(appBase, this);\n\n\n  /**\n   * Parse given hashbang url into properties\n   * @param {string} url Hashbang url\n   * @private\n   */\n  this.$$parse = function(url) {\n    var withoutBaseUrl = beginsWith(appBase, url) || beginsWith(appBaseNoFile, url);\n    var withoutHashUrl;\n\n    if (withoutBaseUrl.charAt(0) === '#') {\n\n      // The rest of the url starts with a hash so we have\n      // got either a hashbang path or a plain hash fragment\n      withoutHashUrl = beginsWith(hashPrefix, withoutBaseUrl);\n      if (isUndefined(withoutHashUrl)) {\n        // There was no hashbang prefix so we just have a hash fragment\n        withoutHashUrl = withoutBaseUrl;\n      }\n\n    } else {\n      // There was no hashbang path nor hash fragment:\n      // If we are in HTML5 mode we use what is left as the path;\n      // Otherwise we ignore what is left\n      withoutHashUrl = this.$$html5 ? withoutBaseUrl : '';\n    }\n\n    parseAppUrl(withoutHashUrl, this);\n\n    this.$$path = removeWindowsDriveName(this.$$path, withoutHashUrl, appBase);\n\n    this.$$compose();\n\n    /*\n     * In Windows, on an anchor node on documents loaded from\n     * the filesystem, the browser will return a pathname\n     * prefixed with the drive name ('/C:/path') when a\n     * pathname without a drive is set:\n     *  * a.setAttribute('href', '/foo')\n     *   * a.pathname === '/C:/foo' //true\n     *\n     * Inside of Angular, we're always using pathnames that\n     * do not include drive names for routing.\n     */\n    function removeWindowsDriveName(path, url, base) {\n      /*\n      Matches paths for file protocol on windows,\n      such as /C:/foo/bar, and captures only /foo/bar.\n      */\n      var windowsFilePathExp = /^\\/[A-Z]:(\\/.*)/;\n\n      var firstPathSegmentMatch;\n\n      //Get the relative path from the input URL.\n      if (url.indexOf(base) === 0) {\n        url = url.replace(base, '');\n      }\n\n      // The input URL intentionally contains a first path segment that ends with a colon.\n      if (windowsFilePathExp.exec(url)) {\n        return path;\n      }\n\n      firstPathSegmentMatch = windowsFilePathExp.exec(path);\n      return firstPathSegmentMatch ? firstPathSegmentMatch[1] : path;\n    }\n  };\n\n  /**\n   * Compose hashbang url and update `absUrl` property\n   * @private\n   */\n  this.$$compose = function() {\n    var search = toKeyValue(this.$$search),\n        hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';\n\n    this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;\n    this.$$absUrl = appBase + (this.$$url ? hashPrefix + this.$$url : '');\n  };\n\n  this.$$parseLinkUrl = function(url, relHref) {\n    if (stripHash(appBase) == stripHash(url)) {\n      this.$$parse(url);\n      return true;\n    }\n    return false;\n  };\n}\n\n\n/**\n * LocationHashbangUrl represents url\n * This object is exposed as $location service when html5 history api is enabled but the browser\n * does not support it.\n *\n * @constructor\n * @param {string} appBase application base URL\n * @param {string} hashPrefix hashbang prefix\n */\nfunction LocationHashbangInHtml5Url(appBase, hashPrefix) {\n  this.$$html5 = true;\n  LocationHashbangUrl.apply(this, arguments);\n\n  var appBaseNoFile = stripFile(appBase);\n\n  this.$$parseLinkUrl = function(url, relHref) {\n    if (relHref && relHref[0] === '#') {\n      // special case for links to hash fragments:\n      // keep the old url and only replace the hash fragment\n      this.hash(relHref.slice(1));\n      return true;\n    }\n\n    var rewrittenUrl;\n    var appUrl;\n\n    if (appBase == stripHash(url)) {\n      rewrittenUrl = url;\n    } else if ((appUrl = beginsWith(appBaseNoFile, url))) {\n      rewrittenUrl = appBase + hashPrefix + appUrl;\n    } else if (appBaseNoFile === url + '/') {\n      rewrittenUrl = appBaseNoFile;\n    }\n    if (rewrittenUrl) {\n      this.$$parse(rewrittenUrl);\n    }\n    return !!rewrittenUrl;\n  };\n\n  this.$$compose = function() {\n    var search = toKeyValue(this.$$search),\n        hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';\n\n    this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;\n    // include hashPrefix in $$absUrl when $$url is empty so IE8 & 9 do not reload page because of removal of '#'\n    this.$$absUrl = appBase + hashPrefix + this.$$url;\n  };\n\n}\n\n\nvar locationPrototype = {\n\n  /**\n   * Are we in html5 mode?\n   * @private\n   */\n  $$html5: false,\n\n  /**\n   * Has any change been replacing?\n   * @private\n   */\n  $$replace: false,\n\n  /**\n   * @ngdoc method\n   * @name $location#absUrl\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return full url representation with all segments encoded according to rules specified in\n   * [RFC 3986](http://www.ietf.org/rfc/rfc3986.txt).\n   *\n   *\n   * ```js\n   * // given url http://example.com/#/some/path?foo=bar&baz=xoxo\n   * var absUrl = $location.absUrl();\n   * // => \"http://example.com/#/some/path?foo=bar&baz=xoxo\"\n   * ```\n   *\n   * @return {string} full url\n   */\n  absUrl: locationGetter('$$absUrl'),\n\n  /**\n   * @ngdoc method\n   * @name $location#url\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return url (e.g. `/path?a=b#hash`) when called without any parameter.\n   *\n   * Change path, search and hash, when called with parameter and return `$location`.\n   *\n   *\n   * ```js\n   * // given url http://example.com/#/some/path?foo=bar&baz=xoxo\n   * var url = $location.url();\n   * // => \"/some/path?foo=bar&baz=xoxo\"\n   * ```\n   *\n   * @param {string=} url New url without base prefix (e.g. `/path?a=b#hash`)\n   * @return {string} url\n   */\n  url: function(url) {\n    if (isUndefined(url))\n      return this.$$url;\n\n    var match = PATH_MATCH.exec(url);\n    if (match[1] || url === '') this.path(decodeURIComponent(match[1]));\n    if (match[2] || match[1] || url === '') this.search(match[3] || '');\n    this.hash(match[5] || '');\n\n    return this;\n  },\n\n  /**\n   * @ngdoc method\n   * @name $location#protocol\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return protocol of current url.\n   *\n   *\n   * ```js\n   * // given url http://example.com/#/some/path?foo=bar&baz=xoxo\n   * var protocol = $location.protocol();\n   * // => \"http\"\n   * ```\n   *\n   * @return {string} protocol of current url\n   */\n  protocol: locationGetter('$$protocol'),\n\n  /**\n   * @ngdoc method\n   * @name $location#host\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return host of current url.\n   *\n   *\n   * ```js\n   * // given url http://example.com/#/some/path?foo=bar&baz=xoxo\n   * var host = $location.host();\n   * // => \"example.com\"\n   * ```\n   *\n   * @return {string} host of current url.\n   */\n  host: locationGetter('$$host'),\n\n  /**\n   * @ngdoc method\n   * @name $location#port\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return port of current url.\n   *\n   *\n   * ```js\n   * // given url http://example.com/#/some/path?foo=bar&baz=xoxo\n   * var port = $location.port();\n   * // => 80\n   * ```\n   *\n   * @return {Number} port\n   */\n  port: locationGetter('$$port'),\n\n  /**\n   * @ngdoc method\n   * @name $location#path\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return path of current url when called without any parameter.\n   *\n   * Change path when called with parameter and return `$location`.\n   *\n   * Note: Path should always begin with forward slash (/), this method will add the forward slash\n   * if it is missing.\n   *\n   *\n   * ```js\n   * // given url http://example.com/#/some/path?foo=bar&baz=xoxo\n   * var path = $location.path();\n   * // => \"/some/path\"\n   * ```\n   *\n   * @param {(string|number)=} path New path\n   * @return {string} path\n   */\n  path: locationGetterSetter('$$path', function(path) {\n    path = path !== null ? path.toString() : '';\n    return path.charAt(0) == '/' ? path : '/' + path;\n  }),\n\n  /**\n   * @ngdoc method\n   * @name $location#search\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return search part (as object) of current url when called without any parameter.\n   *\n   * Change search part when called with parameter and return `$location`.\n   *\n   *\n   * ```js\n   * // given url http://example.com/#/some/path?foo=bar&baz=xoxo\n   * var searchObject = $location.search();\n   * // => {foo: 'bar', baz: 'xoxo'}\n   *\n   * // set foo to 'yipee'\n   * $location.search('foo', 'yipee');\n   * // $location.search() => {foo: 'yipee', baz: 'xoxo'}\n   * ```\n   *\n   * @param {string|Object.<string>|Object.<Array.<string>>} search New search params - string or\n   * hash object.\n   *\n   * When called with a single argument the method acts as a setter, setting the `search` component\n   * of `$location` to the specified value.\n   *\n   * If the argument is a hash object containing an array of values, these values will be encoded\n   * as duplicate search parameters in the url.\n   *\n   * @param {(string|Number|Array<string>|boolean)=} paramValue If `search` is a string or number, then `paramValue`\n   * will override only a single search property.\n   *\n   * If `paramValue` is an array, it will override the property of the `search` component of\n   * `$location` specified via the first argument.\n   *\n   * If `paramValue` is `null`, the property specified via the first argument will be deleted.\n   *\n   * If `paramValue` is `true`, the property specified via the first argument will be added with no\n   * value nor trailing equal sign.\n   *\n   * @return {Object} If called with no arguments returns the parsed `search` object. If called with\n   * one or more arguments returns `$location` object itself.\n   */\n  search: function(search, paramValue) {\n    switch (arguments.length) {\n      case 0:\n        return this.$$search;\n      case 1:\n        if (isString(search) || isNumber(search)) {\n          search = search.toString();\n          this.$$search = parseKeyValue(search);\n        } else if (isObject(search)) {\n          search = copy(search, {});\n          // remove object undefined or null properties\n          forEach(search, function(value, key) {\n            if (value == null) delete search[key];\n          });\n\n          this.$$search = search;\n        } else {\n          throw $locationMinErr('isrcharg',\n              'The first argument of the `$location#search()` call must be a string or an object.');\n        }\n        break;\n      default:\n        if (isUndefined(paramValue) || paramValue === null) {\n          delete this.$$search[search];\n        } else {\n          this.$$search[search] = paramValue;\n        }\n    }\n\n    this.$$compose();\n    return this;\n  },\n\n  /**\n   * @ngdoc method\n   * @name $location#hash\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return hash fragment when called without any parameter.\n   *\n   * Change hash fragment when called with parameter and return `$location`.\n   *\n   *\n   * ```js\n   * // given url http://example.com/#/some/path?foo=bar&baz=xoxo#hashValue\n   * var hash = $location.hash();\n   * // => \"hashValue\"\n   * ```\n   *\n   * @param {(string|number)=} hash New hash fragment\n   * @return {string} hash\n   */\n  hash: locationGetterSetter('$$hash', function(hash) {\n    return hash !== null ? hash.toString() : '';\n  }),\n\n  /**\n   * @ngdoc method\n   * @name $location#replace\n   *\n   * @description\n   * If called, all changes to $location during current `$digest` will be replacing current history\n   * record, instead of adding new one.\n   */\n  replace: function() {\n    this.$$replace = true;\n    return this;\n  }\n};\n\nforEach([LocationHashbangInHtml5Url, LocationHashbangUrl, LocationHtml5Url], function(Location) {\n  Location.prototype = Object.create(locationPrototype);\n\n  /**\n   * @ngdoc method\n   * @name $location#state\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return the history state object when called without any parameter.\n   *\n   * Change the history state object when called with one parameter and return `$location`.\n   * The state object is later passed to `pushState` or `replaceState`.\n   *\n   * NOTE: This method is supported only in HTML5 mode and only in browsers supporting\n   * the HTML5 History API (i.e. methods `pushState` and `replaceState`). If you need to support\n   * older browsers (like IE9 or Android < 4.0), don't use this method.\n   *\n   * @param {object=} state State object for pushState or replaceState\n   * @return {object} state\n   */\n  Location.prototype.state = function(state) {\n    if (!arguments.length)\n      return this.$$state;\n\n    if (Location !== LocationHtml5Url || !this.$$html5) {\n      throw $locationMinErr('nostate', 'History API state support is available only ' +\n        'in HTML5 mode and only in browsers supporting HTML5 History API');\n    }\n    // The user might modify `stateObject` after invoking `$location.state(stateObject)`\n    // but we're changing the $$state reference to $browser.state() during the $digest\n    // so the modification window is narrow.\n    this.$$state = isUndefined(state) ? null : state;\n\n    return this;\n  };\n});\n\n\nfunction locationGetter(property) {\n  return function() {\n    return this[property];\n  };\n}\n\n\nfunction locationGetterSetter(property, preprocess) {\n  return function(value) {\n    if (isUndefined(value))\n      return this[property];\n\n    this[property] = preprocess(value);\n    this.$$compose();\n\n    return this;\n  };\n}\n\n\n/**\n * @ngdoc service\n * @name $location\n *\n * @requires $rootElement\n *\n * @description\n * The $location service parses the URL in the browser address bar (based on the\n * [window.location](https://developer.mozilla.org/en/window.location)) and makes the URL\n * available to your application. Changes to the URL in the address bar are reflected into\n * $location service and changes to $location are reflected into the browser address bar.\n *\n * **The $location service:**\n *\n * - Exposes the current URL in the browser address bar, so you can\n *   - Watch and observe the URL.\n *   - Change the URL.\n * - Synchronizes the URL with the browser when the user\n *   - Changes the address bar.\n *   - Clicks the back or forward button (or clicks a History link).\n *   - Clicks on a link.\n * - Represents the URL object as a set of methods (protocol, host, port, path, search, hash).\n *\n * For more information see {@link guide/$location Developer Guide: Using $location}\n */\n\n/**\n * @ngdoc provider\n * @name $locationProvider\n * @description\n * Use the `$locationProvider` to configure how the application deep linking paths are stored.\n */\nfunction $LocationProvider() {\n  var hashPrefix = '',\n      html5Mode = {\n        enabled: false,\n        requireBase: true,\n        rewriteLinks: true\n      };\n\n  /**\n   * @ngdoc method\n   * @name $locationProvider#hashPrefix\n   * @description\n   * @param {string=} prefix Prefix for hash part (containing path and search)\n   * @returns {*} current value if used as getter or itself (chaining) if used as setter\n   */\n  this.hashPrefix = function(prefix) {\n    if (isDefined(prefix)) {\n      hashPrefix = prefix;\n      return this;\n    } else {\n      return hashPrefix;\n    }\n  };\n\n  /**\n   * @ngdoc method\n   * @name $locationProvider#html5Mode\n   * @description\n   * @param {(boolean|Object)=} mode If boolean, sets `html5Mode.enabled` to value.\n   *   If object, sets `enabled`, `requireBase` and `rewriteLinks` to respective values. Supported\n   *   properties:\n   *   - **enabled** – `{boolean}` – (default: false) If true, will rely on `history.pushState` to\n   *     change urls where supported. Will fall back to hash-prefixed paths in browsers that do not\n   *     support `pushState`.\n   *   - **requireBase** - `{boolean}` - (default: `true`) When html5Mode is enabled, specifies\n   *     whether or not a <base> tag is required to be present. If `enabled` and `requireBase` are\n   *     true, and a base tag is not present, an error will be thrown when `$location` is injected.\n   *     See the {@link guide/$location $location guide for more information}\n   *   - **rewriteLinks** - `{boolean}` - (default: `true`) When html5Mode is enabled,\n   *     enables/disables url rewriting for relative links.\n   *\n   * @returns {Object} html5Mode object if used as getter or itself (chaining) if used as setter\n   */\n  this.html5Mode = function(mode) {\n    if (isBoolean(mode)) {\n      html5Mode.enabled = mode;\n      return this;\n    } else if (isObject(mode)) {\n\n      if (isBoolean(mode.enabled)) {\n        html5Mode.enabled = mode.enabled;\n      }\n\n      if (isBoolean(mode.requireBase)) {\n        html5Mode.requireBase = mode.requireBase;\n      }\n\n      if (isBoolean(mode.rewriteLinks)) {\n        html5Mode.rewriteLinks = mode.rewriteLinks;\n      }\n\n      return this;\n    } else {\n      return html5Mode;\n    }\n  };\n\n  /**\n   * @ngdoc event\n   * @name $location#$locationChangeStart\n   * @eventType broadcast on root scope\n   * @description\n   * Broadcasted before a URL will change.\n   *\n   * This change can be prevented by calling\n   * `preventDefault` method of the event. See {@link ng.$rootScope.Scope#$on} for more\n   * details about event object. Upon successful change\n   * {@link ng.$location#$locationChangeSuccess $locationChangeSuccess} is fired.\n   *\n   * The `newState` and `oldState` parameters may be defined only in HTML5 mode and when\n   * the browser supports the HTML5 History API.\n   *\n   * @param {Object} angularEvent Synthetic event object.\n   * @param {string} newUrl New URL\n   * @param {string=} oldUrl URL that was before it was changed.\n   * @param {string=} newState New history state object\n   * @param {string=} oldState History state object that was before it was changed.\n   */\n\n  /**\n   * @ngdoc event\n   * @name $location#$locationChangeSuccess\n   * @eventType broadcast on root scope\n   * @description\n   * Broadcasted after a URL was changed.\n   *\n   * The `newState` and `oldState` parameters may be defined only in HTML5 mode and when\n   * the browser supports the HTML5 History API.\n   *\n   * @param {Object} angularEvent Synthetic event object.\n   * @param {string} newUrl New URL\n   * @param {string=} oldUrl URL that was before it was changed.\n   * @param {string=} newState New history state object\n   * @param {string=} oldState History state object that was before it was changed.\n   */\n\n  this.$get = ['$rootScope', '$browser', '$sniffer', '$rootElement', '$window',\n      function($rootScope, $browser, $sniffer, $rootElement, $window) {\n    var $location,\n        LocationMode,\n        baseHref = $browser.baseHref(), // if base[href] is undefined, it defaults to ''\n        initialUrl = $browser.url(),\n        appBase;\n\n    if (html5Mode.enabled) {\n      if (!baseHref && html5Mode.requireBase) {\n        throw $locationMinErr('nobase',\n          \"$location in HTML5 mode requires a <base> tag to be present!\");\n      }\n      appBase = serverBase(initialUrl) + (baseHref || '/');\n      LocationMode = $sniffer.history ? LocationHtml5Url : LocationHashbangInHtml5Url;\n    } else {\n      appBase = stripHash(initialUrl);\n      LocationMode = LocationHashbangUrl;\n    }\n    $location = new LocationMode(appBase, '#' + hashPrefix);\n    $location.$$parseLinkUrl(initialUrl, initialUrl);\n\n    $location.$$state = $browser.state();\n\n    var IGNORE_URI_REGEXP = /^\\s*(javascript|mailto):/i;\n\n    function setBrowserUrlWithFallback(url, replace, state) {\n      var oldUrl = $location.url();\n      var oldState = $location.$$state;\n      try {\n        $browser.url(url, replace, state);\n\n        // Make sure $location.state() returns referentially identical (not just deeply equal)\n        // state object; this makes possible quick checking if the state changed in the digest\n        // loop. Checking deep equality would be too expensive.\n        $location.$$state = $browser.state();\n      } catch (e) {\n        // Restore old values if pushState fails\n        $location.url(oldUrl);\n        $location.$$state = oldState;\n\n        throw e;\n      }\n    }\n\n    $rootElement.on('click', function(event) {\n      // TODO(vojta): rewrite link when opening in new tab/window (in legacy browser)\n      // currently we open nice url link and redirect then\n\n      if (!html5Mode.rewriteLinks || event.ctrlKey || event.metaKey || event.shiftKey || event.which == 2 || event.button == 2) return;\n\n      var elm = jqLite(event.target);\n\n      // traverse the DOM up to find first A tag\n      while (nodeName_(elm[0]) !== 'a') {\n        // ignore rewriting if no A tag (reached root element, or no parent - removed from document)\n        if (elm[0] === $rootElement[0] || !(elm = elm.parent())[0]) return;\n      }\n\n      var absHref = elm.prop('href');\n      // get the actual href attribute - see\n      // http://msdn.microsoft.com/en-us/library/ie/dd347148(v=vs.85).aspx\n      var relHref = elm.attr('href') || elm.attr('xlink:href');\n\n      if (isObject(absHref) && absHref.toString() === '[object SVGAnimatedString]') {\n        // SVGAnimatedString.animVal should be identical to SVGAnimatedString.baseVal, unless during\n        // an animation.\n        absHref = urlResolve(absHref.animVal).href;\n      }\n\n      // Ignore when url is started with javascript: or mailto:\n      if (IGNORE_URI_REGEXP.test(absHref)) return;\n\n      if (absHref && !elm.attr('target') && !event.isDefaultPrevented()) {\n        if ($location.$$parseLinkUrl(absHref, relHref)) {\n          // We do a preventDefault for all urls that are part of the angular application,\n          // in html5mode and also without, so that we are able to abort navigation without\n          // getting double entries in the location history.\n          event.preventDefault();\n          // update location manually\n          if ($location.absUrl() != $browser.url()) {\n            $rootScope.$apply();\n            // hack to work around FF6 bug 684208 when scenario runner clicks on links\n            $window.angular['ff-684208-preventDefault'] = true;\n          }\n        }\n      }\n    });\n\n\n    // rewrite hashbang url <> html5 url\n    if (trimEmptyHash($location.absUrl()) != trimEmptyHash(initialUrl)) {\n      $browser.url($location.absUrl(), true);\n    }\n\n    var initializing = true;\n\n    // update $location when $browser url changes\n    $browser.onUrlChange(function(newUrl, newState) {\n      $rootScope.$evalAsync(function() {\n        var oldUrl = $location.absUrl();\n        var oldState = $location.$$state;\n        var defaultPrevented;\n\n        $location.$$parse(newUrl);\n        $location.$$state = newState;\n\n        defaultPrevented = $rootScope.$broadcast('$locationChangeStart', newUrl, oldUrl,\n            newState, oldState).defaultPrevented;\n\n        // if the location was changed by a `$locationChangeStart` handler then stop\n        // processing this location change\n        if ($location.absUrl() !== newUrl) return;\n\n        if (defaultPrevented) {\n          $location.$$parse(oldUrl);\n          $location.$$state = oldState;\n          setBrowserUrlWithFallback(oldUrl, false, oldState);\n        } else {\n          initializing = false;\n          afterLocationChange(oldUrl, oldState);\n        }\n      });\n      if (!$rootScope.$$phase) $rootScope.$digest();\n    });\n\n    // update browser\n    $rootScope.$watch(function $locationWatch() {\n      var oldUrl = trimEmptyHash($browser.url());\n      var newUrl = trimEmptyHash($location.absUrl());\n      var oldState = $browser.state();\n      var currentReplace = $location.$$replace;\n      var urlOrStateChanged = oldUrl !== newUrl ||\n        ($location.$$html5 && $sniffer.history && oldState !== $location.$$state);\n\n      if (initializing || urlOrStateChanged) {\n        initializing = false;\n\n        $rootScope.$evalAsync(function() {\n          var newUrl = $location.absUrl();\n          var defaultPrevented = $rootScope.$broadcast('$locationChangeStart', newUrl, oldUrl,\n              $location.$$state, oldState).defaultPrevented;\n\n          // if the location was changed by a `$locationChangeStart` handler then stop\n          // processing this location change\n          if ($location.absUrl() !== newUrl) return;\n\n          if (defaultPrevented) {\n            $location.$$parse(oldUrl);\n            $location.$$state = oldState;\n          } else {\n            if (urlOrStateChanged) {\n              setBrowserUrlWithFallback(newUrl, currentReplace,\n                                        oldState === $location.$$state ? null : $location.$$state);\n            }\n            afterLocationChange(oldUrl, oldState);\n          }\n        });\n      }\n\n      $location.$$replace = false;\n\n      // we don't need to return anything because $evalAsync will make the digest loop dirty when\n      // there is a change\n    });\n\n    return $location;\n\n    function afterLocationChange(oldUrl, oldState) {\n      $rootScope.$broadcast('$locationChangeSuccess', $location.absUrl(), oldUrl,\n        $location.$$state, oldState);\n    }\n}];\n}\n\n/**\n * @ngdoc service\n * @name $log\n * @requires $window\n *\n * @description\n * Simple service for logging. Default implementation safely writes the message\n * into the browser's console (if present).\n *\n * The main purpose of this service is to simplify debugging and troubleshooting.\n *\n * The default is to log `debug` messages. You can use\n * {@link ng.$logProvider ng.$logProvider#debugEnabled} to change this.\n *\n * @example\n   <example module=\"logExample\">\n     <file name=\"script.js\">\n       angular.module('logExample', [])\n         .controller('LogController', ['$scope', '$log', function($scope, $log) {\n           $scope.$log = $log;\n           $scope.message = 'Hello World!';\n         }]);\n     </file>\n     <file name=\"index.html\">\n       <div ng-controller=\"LogController\">\n         <p>Reload this page with open console, enter text and hit the log button...</p>\n         Message:\n         <input type=\"text\" ng-model=\"message\"/>\n         <button ng-click=\"$log.log(message)\">log</button>\n         <button ng-click=\"$log.warn(message)\">warn</button>\n         <button ng-click=\"$log.info(message)\">info</button>\n         <button ng-click=\"$log.error(message)\">error</button>\n       </div>\n     </file>\n   </example>\n */\n\n/**\n * @ngdoc provider\n * @name $logProvider\n * @description\n * Use the `$logProvider` to configure how the application logs messages\n */\nfunction $LogProvider() {\n  var debug = true,\n      self = this;\n\n  /**\n   * @ngdoc method\n   * @name $logProvider#debugEnabled\n   * @description\n   * @param {boolean=} flag enable or disable debug level messages\n   * @returns {*} current value if used as getter or itself (chaining) if used as setter\n   */\n  this.debugEnabled = function(flag) {\n    if (isDefined(flag)) {\n      debug = flag;\n    return this;\n    } else {\n      return debug;\n    }\n  };\n\n  this.$get = ['$window', function($window) {\n    return {\n      /**\n       * @ngdoc method\n       * @name $log#log\n       *\n       * @description\n       * Write a log message\n       */\n      log: consoleLog('log'),\n\n      /**\n       * @ngdoc method\n       * @name $log#info\n       *\n       * @description\n       * Write an information message\n       */\n      info: consoleLog('info'),\n\n      /**\n       * @ngdoc method\n       * @name $log#warn\n       *\n       * @description\n       * Write a warning message\n       */\n      warn: consoleLog('warn'),\n\n      /**\n       * @ngdoc method\n       * @name $log#error\n       *\n       * @description\n       * Write an error message\n       */\n      error: consoleLog('error'),\n\n      /**\n       * @ngdoc method\n       * @name $log#debug\n       *\n       * @description\n       * Write a debug message\n       */\n      debug: (function() {\n        var fn = consoleLog('debug');\n\n        return function() {\n          if (debug) {\n            fn.apply(self, arguments);\n          }\n        };\n      }())\n    };\n\n    function formatError(arg) {\n      if (arg instanceof Error) {\n        if (arg.stack) {\n          arg = (arg.message && arg.stack.indexOf(arg.message) === -1)\n              ? 'Error: ' + arg.message + '\\n' + arg.stack\n              : arg.stack;\n        } else if (arg.sourceURL) {\n          arg = arg.message + '\\n' + arg.sourceURL + ':' + arg.line;\n        }\n      }\n      return arg;\n    }\n\n    function consoleLog(type) {\n      var console = $window.console || {},\n          logFn = console[type] || console.log || noop,\n          hasApply = false;\n\n      // Note: reading logFn.apply throws an error in IE11 in IE8 document mode.\n      // The reason behind this is that console.log has type \"object\" in IE8...\n      try {\n        hasApply = !!logFn.apply;\n      } catch (e) {}\n\n      if (hasApply) {\n        return function() {\n          var args = [];\n          forEach(arguments, function(arg) {\n            args.push(formatError(arg));\n          });\n          return logFn.apply(console, args);\n        };\n      }\n\n      // we are IE which either doesn't have window.console => this is noop and we do nothing,\n      // or we are IE where console.log doesn't have apply so we log at least first 2 args\n      return function(arg1, arg2) {\n        logFn(arg1, arg2 == null ? '' : arg2);\n      };\n    }\n  }];\n}\n\nvar $parseMinErr = minErr('$parse');\n\n// Sandboxing Angular Expressions\n// ------------------------------\n// Angular expressions are generally considered safe because these expressions only have direct\n// access to `$scope` and locals. However, one can obtain the ability to execute arbitrary JS code by\n// obtaining a reference to native JS functions such as the Function constructor.\n//\n// As an example, consider the following Angular expression:\n//\n//   {}.toString.constructor('alert(\"evil JS code\")')\n//\n// This sandboxing technique is not perfect and doesn't aim to be. The goal is to prevent exploits\n// against the expression language, but not to prevent exploits that were enabled by exposing\n// sensitive JavaScript or browser APIs on Scope. Exposing such objects on a Scope is never a good\n// practice and therefore we are not even trying to protect against interaction with an object\n// explicitly exposed in this way.\n//\n// In general, it is not possible to access a Window object from an angular expression unless a\n// window or some DOM object that has a reference to window is published onto a Scope.\n// Similarly we prevent invocations of function known to be dangerous, as well as assignments to\n// native objects.\n//\n// See https://docs.angularjs.org/guide/security\n\n\nfunction ensureSafeMemberName(name, fullExpression) {\n  if (name === \"__defineGetter__\" || name === \"__defineSetter__\"\n      || name === \"__lookupGetter__\" || name === \"__lookupSetter__\"\n      || name === \"__proto__\") {\n    throw $parseMinErr('isecfld',\n        'Attempting to access a disallowed field in Angular expressions! '\n        + 'Expression: {0}', fullExpression);\n  }\n  return name;\n}\n\nfunction ensureSafeObject(obj, fullExpression) {\n  // nifty check if obj is Function that is fast and works across iframes and other contexts\n  if (obj) {\n    if (obj.constructor === obj) {\n      throw $parseMinErr('isecfn',\n          'Referencing Function in Angular expressions is disallowed! Expression: {0}',\n          fullExpression);\n    } else if (// isWindow(obj)\n        obj.window === obj) {\n      throw $parseMinErr('isecwindow',\n          'Referencing the Window in Angular expressions is disallowed! Expression: {0}',\n          fullExpression);\n    } else if (// isElement(obj)\n        obj.children && (obj.nodeName || (obj.prop && obj.attr && obj.find))) {\n      throw $parseMinErr('isecdom',\n          'Referencing DOM nodes in Angular expressions is disallowed! Expression: {0}',\n          fullExpression);\n    } else if (// block Object so that we can't get hold of dangerous Object.* methods\n        obj === Object) {\n      throw $parseMinErr('isecobj',\n          'Referencing Object in Angular expressions is disallowed! Expression: {0}',\n          fullExpression);\n    }\n  }\n  return obj;\n}\n\nvar CALL = Function.prototype.call;\nvar APPLY = Function.prototype.apply;\nvar BIND = Function.prototype.bind;\n\nfunction ensureSafeFunction(obj, fullExpression) {\n  if (obj) {\n    if (obj.constructor === obj) {\n      throw $parseMinErr('isecfn',\n        'Referencing Function in Angular expressions is disallowed! Expression: {0}',\n        fullExpression);\n    } else if (obj === CALL || obj === APPLY || obj === BIND) {\n      throw $parseMinErr('isecff',\n        'Referencing call, apply or bind in Angular expressions is disallowed! Expression: {0}',\n        fullExpression);\n    }\n  }\n}\n\n//Keyword constants\nvar CONSTANTS = createMap();\nforEach({\n  'null': function() { return null; },\n  'true': function() { return true; },\n  'false': function() { return false; },\n  'undefined': function() {}\n}, function(constantGetter, name) {\n  constantGetter.constant = constantGetter.literal = constantGetter.sharedGetter = true;\n  CONSTANTS[name] = constantGetter;\n});\n\n//Not quite a constant, but can be lex/parsed the same\nCONSTANTS['this'] = function(self) { return self; };\nCONSTANTS['this'].sharedGetter = true;\n\n\n//Operators - will be wrapped by binaryFn/unaryFn/assignment/filter\nvar OPERATORS = extend(createMap(), {\n    '+':function(self, locals, a, b) {\n      a=a(self, locals); b=b(self, locals);\n      if (isDefined(a)) {\n        if (isDefined(b)) {\n          return a + b;\n        }\n        return a;\n      }\n      return isDefined(b) ? b : undefined;},\n    '-':function(self, locals, a, b) {\n          a=a(self, locals); b=b(self, locals);\n          return (isDefined(a) ? a : 0) - (isDefined(b) ? b : 0);\n        },\n    '*':function(self, locals, a, b) {return a(self, locals) * b(self, locals);},\n    '/':function(self, locals, a, b) {return a(self, locals) / b(self, locals);},\n    '%':function(self, locals, a, b) {return a(self, locals) % b(self, locals);},\n    '===':function(self, locals, a, b) {return a(self, locals) === b(self, locals);},\n    '!==':function(self, locals, a, b) {return a(self, locals) !== b(self, locals);},\n    '==':function(self, locals, a, b) {return a(self, locals) == b(self, locals);},\n    '!=':function(self, locals, a, b) {return a(self, locals) != b(self, locals);},\n    '<':function(self, locals, a, b) {return a(self, locals) < b(self, locals);},\n    '>':function(self, locals, a, b) {return a(self, locals) > b(self, locals);},\n    '<=':function(self, locals, a, b) {return a(self, locals) <= b(self, locals);},\n    '>=':function(self, locals, a, b) {return a(self, locals) >= b(self, locals);},\n    '&&':function(self, locals, a, b) {return a(self, locals) && b(self, locals);},\n    '||':function(self, locals, a, b) {return a(self, locals) || b(self, locals);},\n    '!':function(self, locals, a) {return !a(self, locals);},\n\n    //Tokenized as operators but parsed as assignment/filters\n    '=':true,\n    '|':true\n});\nvar ESCAPE = {\"n\":\"\\n\", \"f\":\"\\f\", \"r\":\"\\r\", \"t\":\"\\t\", \"v\":\"\\v\", \"'\":\"'\", '\"':'\"'};\n\n\n/////////////////////////////////////////\n\n\n/**\n * @constructor\n */\nvar Lexer = function(options) {\n  this.options = options;\n};\n\nLexer.prototype = {\n  constructor: Lexer,\n\n  lex: function(text) {\n    this.text = text;\n    this.index = 0;\n    this.tokens = [];\n\n    while (this.index < this.text.length) {\n      var ch = this.text.charAt(this.index);\n      if (ch === '\"' || ch === \"'\") {\n        this.readString(ch);\n      } else if (this.isNumber(ch) || ch === '.' && this.isNumber(this.peek())) {\n        this.readNumber();\n      } else if (this.isIdent(ch)) {\n        this.readIdent();\n      } else if (this.is(ch, '(){}[].,;:?')) {\n        this.tokens.push({index: this.index, text: ch});\n        this.index++;\n      } else if (this.isWhitespace(ch)) {\n        this.index++;\n      } else {\n        var ch2 = ch + this.peek();\n        var ch3 = ch2 + this.peek(2);\n        var op1 = OPERATORS[ch];\n        var op2 = OPERATORS[ch2];\n        var op3 = OPERATORS[ch3];\n        if (op1 || op2 || op3) {\n          var token = op3 ? ch3 : (op2 ? ch2 : ch);\n          this.tokens.push({index: this.index, text: token, operator: true});\n          this.index += token.length;\n        } else {\n          this.throwError('Unexpected next character ', this.index, this.index + 1);\n        }\n      }\n    }\n    return this.tokens;\n  },\n\n  is: function(ch, chars) {\n    return chars.indexOf(ch) !== -1;\n  },\n\n  peek: function(i) {\n    var num = i || 1;\n    return (this.index + num < this.text.length) ? this.text.charAt(this.index + num) : false;\n  },\n\n  isNumber: function(ch) {\n    return ('0' <= ch && ch <= '9') && typeof ch === \"string\";\n  },\n\n  isWhitespace: function(ch) {\n    // IE treats non-breaking space as \\u00A0\n    return (ch === ' ' || ch === '\\r' || ch === '\\t' ||\n            ch === '\\n' || ch === '\\v' || ch === '\\u00A0');\n  },\n\n  isIdent: function(ch) {\n    return ('a' <= ch && ch <= 'z' ||\n            'A' <= ch && ch <= 'Z' ||\n            '_' === ch || ch === '$');\n  },\n\n  isExpOperator: function(ch) {\n    return (ch === '-' || ch === '+' || this.isNumber(ch));\n  },\n\n  throwError: function(error, start, end) {\n    end = end || this.index;\n    var colStr = (isDefined(start)\n            ? 's ' + start +  '-' + this.index + ' [' + this.text.substring(start, end) + ']'\n            : ' ' + end);\n    throw $parseMinErr('lexerr', 'Lexer Error: {0} at column{1} in expression [{2}].',\n        error, colStr, this.text);\n  },\n\n  readNumber: function() {\n    var number = '';\n    var start = this.index;\n    while (this.index < this.text.length) {\n      var ch = lowercase(this.text.charAt(this.index));\n      if (ch == '.' || this.isNumber(ch)) {\n        number += ch;\n      } else {\n        var peekCh = this.peek();\n        if (ch == 'e' && this.isExpOperator(peekCh)) {\n          number += ch;\n        } else if (this.isExpOperator(ch) &&\n            peekCh && this.isNumber(peekCh) &&\n            number.charAt(number.length - 1) == 'e') {\n          number += ch;\n        } else if (this.isExpOperator(ch) &&\n            (!peekCh || !this.isNumber(peekCh)) &&\n            number.charAt(number.length - 1) == 'e') {\n          this.throwError('Invalid exponent');\n        } else {\n          break;\n        }\n      }\n      this.index++;\n    }\n    this.tokens.push({\n      index: start,\n      text: number,\n      constant: true,\n      value: Number(number)\n    });\n  },\n\n  readIdent: function() {\n    var start = this.index;\n    while (this.index < this.text.length) {\n      var ch = this.text.charAt(this.index);\n      if (!(this.isIdent(ch) || this.isNumber(ch))) {\n        break;\n      }\n      this.index++;\n    }\n    this.tokens.push({\n      index: start,\n      text: this.text.slice(start, this.index),\n      identifier: true\n    });\n  },\n\n  readString: function(quote) {\n    var start = this.index;\n    this.index++;\n    var string = '';\n    var rawString = quote;\n    var escape = false;\n    while (this.index < this.text.length) {\n      var ch = this.text.charAt(this.index);\n      rawString += ch;\n      if (escape) {\n        if (ch === 'u') {\n          var hex = this.text.substring(this.index + 1, this.index + 5);\n          if (!hex.match(/[\\da-f]{4}/i))\n            this.throwError('Invalid unicode escape [\\\\u' + hex + ']');\n          this.index += 4;\n          string += String.fromCharCode(parseInt(hex, 16));\n        } else {\n          var rep = ESCAPE[ch];\n          string = string + (rep || ch);\n        }\n        escape = false;\n      } else if (ch === '\\\\') {\n        escape = true;\n      } else if (ch === quote) {\n        this.index++;\n        this.tokens.push({\n          index: start,\n          text: rawString,\n          constant: true,\n          value: string\n        });\n        return;\n      } else {\n        string += ch;\n      }\n      this.index++;\n    }\n    this.throwError('Unterminated quote', start);\n  }\n};\n\n\nfunction isConstant(exp) {\n  return exp.constant;\n}\n\n/**\n * @constructor\n */\nvar Parser = function(lexer, $filter, options) {\n  this.lexer = lexer;\n  this.$filter = $filter;\n  this.options = options;\n};\n\nParser.ZERO = extend(function() {\n  return 0;\n}, {\n  sharedGetter: true,\n  constant: true\n});\n\nParser.prototype = {\n  constructor: Parser,\n\n  parse: function(text) {\n    this.text = text;\n    this.tokens = this.lexer.lex(text);\n\n    var value = this.statements();\n\n    if (this.tokens.length !== 0) {\n      this.throwError('is an unexpected token', this.tokens[0]);\n    }\n\n    value.literal = !!value.literal;\n    value.constant = !!value.constant;\n\n    return value;\n  },\n\n  primary: function() {\n    var primary;\n    if (this.expect('(')) {\n      primary = this.filterChain();\n      this.consume(')');\n    } else if (this.expect('[')) {\n      primary = this.arrayDeclaration();\n    } else if (this.expect('{')) {\n      primary = this.object();\n    } else if (this.peek().identifier && this.peek().text in CONSTANTS) {\n      primary = CONSTANTS[this.consume().text];\n    } else if (this.peek().identifier) {\n      primary = this.identifier();\n    } else if (this.peek().constant) {\n      primary = this.constant();\n    } else {\n      this.throwError('not a primary expression', this.peek());\n    }\n\n    var next, context;\n    while ((next = this.expect('(', '[', '.'))) {\n      if (next.text === '(') {\n        primary = this.functionCall(primary, context);\n        context = null;\n      } else if (next.text === '[') {\n        context = primary;\n        primary = this.objectIndex(primary);\n      } else if (next.text === '.') {\n        context = primary;\n        primary = this.fieldAccess(primary);\n      } else {\n        this.throwError('IMPOSSIBLE');\n      }\n    }\n    return primary;\n  },\n\n  throwError: function(msg, token) {\n    throw $parseMinErr('syntax',\n        'Syntax Error: Token \\'{0}\\' {1} at column {2} of the expression [{3}] starting at [{4}].',\n          token.text, msg, (token.index + 1), this.text, this.text.substring(token.index));\n  },\n\n  peekToken: function() {\n    if (this.tokens.length === 0)\n      throw $parseMinErr('ueoe', 'Unexpected end of expression: {0}', this.text);\n    return this.tokens[0];\n  },\n\n  peek: function(e1, e2, e3, e4) {\n    return this.peekAhead(0, e1, e2, e3, e4);\n  },\n  peekAhead: function(i, e1, e2, e3, e4) {\n    if (this.tokens.length > i) {\n      var token = this.tokens[i];\n      var t = token.text;\n      if (t === e1 || t === e2 || t === e3 || t === e4 ||\n          (!e1 && !e2 && !e3 && !e4)) {\n        return token;\n      }\n    }\n    return false;\n  },\n\n  expect: function(e1, e2, e3, e4) {\n    var token = this.peek(e1, e2, e3, e4);\n    if (token) {\n      this.tokens.shift();\n      return token;\n    }\n    return false;\n  },\n\n  consume: function(e1) {\n    if (this.tokens.length === 0) {\n      throw $parseMinErr('ueoe', 'Unexpected end of expression: {0}', this.text);\n    }\n\n    var token = this.expect(e1);\n    if (!token) {\n      this.throwError('is unexpected, expecting [' + e1 + ']', this.peek());\n    }\n    return token;\n  },\n\n  unaryFn: function(op, right) {\n    var fn = OPERATORS[op];\n    return extend(function $parseUnaryFn(self, locals) {\n      return fn(self, locals, right);\n    }, {\n      constant:right.constant,\n      inputs: [right]\n    });\n  },\n\n  binaryFn: function(left, op, right, isBranching) {\n    var fn = OPERATORS[op];\n    return extend(function $parseBinaryFn(self, locals) {\n      return fn(self, locals, left, right);\n    }, {\n      constant: left.constant && right.constant,\n      inputs: !isBranching && [left, right]\n    });\n  },\n\n  identifier: function() {\n    var id = this.consume().text;\n\n    //Continue reading each `.identifier` unless it is a method invocation\n    while (this.peek('.') && this.peekAhead(1).identifier && !this.peekAhead(2, '(')) {\n      id += this.consume().text + this.consume().text;\n    }\n\n    return getterFn(id, this.options, this.text);\n  },\n\n  constant: function() {\n    var value = this.consume().value;\n\n    return extend(function $parseConstant() {\n      return value;\n    }, {\n      constant: true,\n      literal: true\n    });\n  },\n\n  statements: function() {\n    var statements = [];\n    while (true) {\n      if (this.tokens.length > 0 && !this.peek('}', ')', ';', ']'))\n        statements.push(this.filterChain());\n      if (!this.expect(';')) {\n        // optimize for the common case where there is only one statement.\n        // TODO(size): maybe we should not support multiple statements?\n        return (statements.length === 1)\n            ? statements[0]\n            : function $parseStatements(self, locals) {\n                var value;\n                for (var i = 0, ii = statements.length; i < ii; i++) {\n                  value = statements[i](self, locals);\n                }\n                return value;\n              };\n      }\n    }\n  },\n\n  filterChain: function() {\n    var left = this.expression();\n    var token;\n    while ((token = this.expect('|'))) {\n      left = this.filter(left);\n    }\n    return left;\n  },\n\n  filter: function(inputFn) {\n    var fn = this.$filter(this.consume().text);\n    var argsFn;\n    var args;\n\n    if (this.peek(':')) {\n      argsFn = [];\n      args = []; // we can safely reuse the array\n      while (this.expect(':')) {\n        argsFn.push(this.expression());\n      }\n    }\n\n    var inputs = [inputFn].concat(argsFn || []);\n\n    return extend(function $parseFilter(self, locals) {\n      var input = inputFn(self, locals);\n      if (args) {\n        args[0] = input;\n\n        var i = argsFn.length;\n        while (i--) {\n          args[i + 1] = argsFn[i](self, locals);\n        }\n\n        return fn.apply(undefined, args);\n      }\n\n      return fn(input);\n    }, {\n      constant: !fn.$stateful && inputs.every(isConstant),\n      inputs: !fn.$stateful && inputs\n    });\n  },\n\n  expression: function() {\n    return this.assignment();\n  },\n\n  assignment: function() {\n    var left = this.ternary();\n    var right;\n    var token;\n    if ((token = this.expect('='))) {\n      if (!left.assign) {\n        this.throwError('implies assignment but [' +\n            this.text.substring(0, token.index) + '] can not be assigned to', token);\n      }\n      right = this.ternary();\n      return extend(function $parseAssignment(scope, locals) {\n        return left.assign(scope, right(scope, locals), locals);\n      }, {\n        inputs: [left, right]\n      });\n    }\n    return left;\n  },\n\n  ternary: function() {\n    var left = this.logicalOR();\n    var middle;\n    var token;\n    if ((token = this.expect('?'))) {\n      middle = this.assignment();\n      if (this.consume(':')) {\n        var right = this.assignment();\n\n        return extend(function $parseTernary(self, locals) {\n          return left(self, locals) ? middle(self, locals) : right(self, locals);\n        }, {\n          constant: left.constant && middle.constant && right.constant\n        });\n      }\n    }\n\n    return left;\n  },\n\n  logicalOR: function() {\n    var left = this.logicalAND();\n    var token;\n    while ((token = this.expect('||'))) {\n      left = this.binaryFn(left, token.text, this.logicalAND(), true);\n    }\n    return left;\n  },\n\n  logicalAND: function() {\n    var left = this.equality();\n    var token;\n    while ((token = this.expect('&&'))) {\n      left = this.binaryFn(left, token.text, this.equality(), true);\n    }\n    return left;\n  },\n\n  equality: function() {\n    var left = this.relational();\n    var token;\n    while ((token = this.expect('==','!=','===','!=='))) {\n      left = this.binaryFn(left, token.text, this.relational());\n    }\n    return left;\n  },\n\n  relational: function() {\n    var left = this.additive();\n    var token;\n    while ((token = this.expect('<', '>', '<=', '>='))) {\n      left = this.binaryFn(left, token.text, this.additive());\n    }\n    return left;\n  },\n\n  additive: function() {\n    var left = this.multiplicative();\n    var token;\n    while ((token = this.expect('+','-'))) {\n      left = this.binaryFn(left, token.text, this.multiplicative());\n    }\n    return left;\n  },\n\n  multiplicative: function() {\n    var left = this.unary();\n    var token;\n    while ((token = this.expect('*','/','%'))) {\n      left = this.binaryFn(left, token.text, this.unary());\n    }\n    return left;\n  },\n\n  unary: function() {\n    var token;\n    if (this.expect('+')) {\n      return this.primary();\n    } else if ((token = this.expect('-'))) {\n      return this.binaryFn(Parser.ZERO, token.text, this.unary());\n    } else if ((token = this.expect('!'))) {\n      return this.unaryFn(token.text, this.unary());\n    } else {\n      return this.primary();\n    }\n  },\n\n  fieldAccess: function(object) {\n    var getter = this.identifier();\n\n    return extend(function $parseFieldAccess(scope, locals, self) {\n      var o = self || object(scope, locals);\n      return (o == null) ? undefined : getter(o);\n    }, {\n      assign: function(scope, value, locals) {\n        var o = object(scope, locals);\n        if (!o) object.assign(scope, o = {}, locals);\n        return getter.assign(o, value);\n      }\n    });\n  },\n\n  objectIndex: function(obj) {\n    var expression = this.text;\n\n    var indexFn = this.expression();\n    this.consume(']');\n\n    return extend(function $parseObjectIndex(self, locals) {\n      var o = obj(self, locals),\n          i = indexFn(self, locals),\n          v;\n\n      ensureSafeMemberName(i, expression);\n      if (!o) return undefined;\n      v = ensureSafeObject(o[i], expression);\n      return v;\n    }, {\n      assign: function(self, value, locals) {\n        var key = ensureSafeMemberName(indexFn(self, locals), expression);\n        // prevent overwriting of Function.constructor which would break ensureSafeObject check\n        var o = ensureSafeObject(obj(self, locals), expression);\n        if (!o) obj.assign(self, o = {}, locals);\n        return o[key] = value;\n      }\n    });\n  },\n\n  functionCall: function(fnGetter, contextGetter) {\n    var argsFn = [];\n    if (this.peekToken().text !== ')') {\n      do {\n        argsFn.push(this.expression());\n      } while (this.expect(','));\n    }\n    this.consume(')');\n\n    var expressionText = this.text;\n    // we can safely reuse the array across invocations\n    var args = argsFn.length ? [] : null;\n\n    return function $parseFunctionCall(scope, locals) {\n      var context = contextGetter ? contextGetter(scope, locals) : isDefined(contextGetter) ? undefined : scope;\n      var fn = fnGetter(scope, locals, context) || noop;\n\n      if (args) {\n        var i = argsFn.length;\n        while (i--) {\n          args[i] = ensureSafeObject(argsFn[i](scope, locals), expressionText);\n        }\n      }\n\n      ensureSafeObject(context, expressionText);\n      ensureSafeFunction(fn, expressionText);\n\n      // IE doesn't have apply for some native functions\n      var v = fn.apply\n            ? fn.apply(context, args)\n            : fn(args[0], args[1], args[2], args[3], args[4]);\n\n      if (args) {\n        // Free-up the memory (arguments of the last function call).\n        args.length = 0;\n      }\n\n      return ensureSafeObject(v, expressionText);\n      };\n  },\n\n  // This is used with json array declaration\n  arrayDeclaration: function() {\n    var elementFns = [];\n    if (this.peekToken().text !== ']') {\n      do {\n        if (this.peek(']')) {\n          // Support trailing commas per ES5.1.\n          break;\n        }\n        elementFns.push(this.expression());\n      } while (this.expect(','));\n    }\n    this.consume(']');\n\n    return extend(function $parseArrayLiteral(self, locals) {\n      var array = [];\n      for (var i = 0, ii = elementFns.length; i < ii; i++) {\n        array.push(elementFns[i](self, locals));\n      }\n      return array;\n    }, {\n      literal: true,\n      constant: elementFns.every(isConstant),\n      inputs: elementFns\n    });\n  },\n\n  object: function() {\n    var keys = [], valueFns = [];\n    if (this.peekToken().text !== '}') {\n      do {\n        if (this.peek('}')) {\n          // Support trailing commas per ES5.1.\n          break;\n        }\n        var token = this.consume();\n        if (token.constant) {\n          keys.push(token.value);\n        } else if (token.identifier) {\n          keys.push(token.text);\n        } else {\n          this.throwError(\"invalid key\", token);\n        }\n        this.consume(':');\n        valueFns.push(this.expression());\n      } while (this.expect(','));\n    }\n    this.consume('}');\n\n    return extend(function $parseObjectLiteral(self, locals) {\n      var object = {};\n      for (var i = 0, ii = valueFns.length; i < ii; i++) {\n        object[keys[i]] = valueFns[i](self, locals);\n      }\n      return object;\n    }, {\n      literal: true,\n      constant: valueFns.every(isConstant),\n      inputs: valueFns\n    });\n  }\n};\n\n\n//////////////////////////////////////////////////\n// Parser helper functions\n//////////////////////////////////////////////////\n\nfunction setter(obj, locals, path, setValue, fullExp) {\n  ensureSafeObject(obj, fullExp);\n  ensureSafeObject(locals, fullExp);\n\n  var element = path.split('.'), key;\n  for (var i = 0; element.length > 1; i++) {\n    key = ensureSafeMemberName(element.shift(), fullExp);\n    var propertyObj = (i === 0 && locals && locals[key]) || obj[key];\n    if (!propertyObj) {\n      propertyObj = {};\n      obj[key] = propertyObj;\n    }\n    obj = ensureSafeObject(propertyObj, fullExp);\n  }\n  key = ensureSafeMemberName(element.shift(), fullExp);\n  ensureSafeObject(obj[key], fullExp);\n  obj[key] = setValue;\n  return setValue;\n}\n\nvar getterFnCacheDefault = createMap();\nvar getterFnCacheExpensive = createMap();\n\nfunction isPossiblyDangerousMemberName(name) {\n  return name == 'constructor';\n}\n\n/**\n * Implementation of the \"Black Hole\" variant from:\n * - http://jsperf.com/angularjs-parse-getter/4\n * - http://jsperf.com/path-evaluation-simplified/7\n */\nfunction cspSafeGetterFn(key0, key1, key2, key3, key4, fullExp, expensiveChecks) {\n  ensureSafeMemberName(key0, fullExp);\n  ensureSafeMemberName(key1, fullExp);\n  ensureSafeMemberName(key2, fullExp);\n  ensureSafeMemberName(key3, fullExp);\n  ensureSafeMemberName(key4, fullExp);\n  var eso = function(o) {\n    return ensureSafeObject(o, fullExp);\n  };\n  var eso0 = (expensiveChecks || isPossiblyDangerousMemberName(key0)) ? eso : identity;\n  var eso1 = (expensiveChecks || isPossiblyDangerousMemberName(key1)) ? eso : identity;\n  var eso2 = (expensiveChecks || isPossiblyDangerousMemberName(key2)) ? eso : identity;\n  var eso3 = (expensiveChecks || isPossiblyDangerousMemberName(key3)) ? eso : identity;\n  var eso4 = (expensiveChecks || isPossiblyDangerousMemberName(key4)) ? eso : identity;\n\n  return function cspSafeGetter(scope, locals) {\n    var pathVal = (locals && locals.hasOwnProperty(key0)) ? locals : scope;\n\n    if (pathVal == null) return pathVal;\n    pathVal = eso0(pathVal[key0]);\n\n    if (!key1) return pathVal;\n    if (pathVal == null) return undefined;\n    pathVal = eso1(pathVal[key1]);\n\n    if (!key2) return pathVal;\n    if (pathVal == null) return undefined;\n    pathVal = eso2(pathVal[key2]);\n\n    if (!key3) return pathVal;\n    if (pathVal == null) return undefined;\n    pathVal = eso3(pathVal[key3]);\n\n    if (!key4) return pathVal;\n    if (pathVal == null) return undefined;\n    pathVal = eso4(pathVal[key4]);\n\n    return pathVal;\n  };\n}\n\nfunction getterFnWithEnsureSafeObject(fn, fullExpression) {\n  return function(s, l) {\n    return fn(s, l, ensureSafeObject, fullExpression);\n  };\n}\n\nfunction getterFn(path, options, fullExp) {\n  var expensiveChecks = options.expensiveChecks;\n  var getterFnCache = (expensiveChecks ? getterFnCacheExpensive : getterFnCacheDefault);\n  var fn = getterFnCache[path];\n  if (fn) return fn;\n\n\n  var pathKeys = path.split('.'),\n      pathKeysLength = pathKeys.length;\n\n  // http://jsperf.com/angularjs-parse-getter/6\n  if (options.csp) {\n    if (pathKeysLength < 6) {\n      fn = cspSafeGetterFn(pathKeys[0], pathKeys[1], pathKeys[2], pathKeys[3], pathKeys[4], fullExp, expensiveChecks);\n    } else {\n      fn = function cspSafeGetter(scope, locals) {\n        var i = 0, val;\n        do {\n          val = cspSafeGetterFn(pathKeys[i++], pathKeys[i++], pathKeys[i++], pathKeys[i++],\n                                pathKeys[i++], fullExp, expensiveChecks)(scope, locals);\n\n          locals = undefined; // clear after first iteration\n          scope = val;\n        } while (i < pathKeysLength);\n        return val;\n      };\n    }\n  } else {\n    var code = '';\n    if (expensiveChecks) {\n      code += 's = eso(s, fe);\\nl = eso(l, fe);\\n';\n    }\n    var needsEnsureSafeObject = expensiveChecks;\n    forEach(pathKeys, function(key, index) {\n      ensureSafeMemberName(key, fullExp);\n      var lookupJs = (index\n                      // we simply dereference 's' on any .dot notation\n                      ? 's'\n                      // but if we are first then we check locals first, and if so read it first\n                      : '((l&&l.hasOwnProperty(\"' + key + '\"))?l:s)') + '.' + key;\n      if (expensiveChecks || isPossiblyDangerousMemberName(key)) {\n        lookupJs = 'eso(' + lookupJs + ', fe)';\n        needsEnsureSafeObject = true;\n      }\n      code += 'if(s == null) return undefined;\\n' +\n              's=' + lookupJs + ';\\n';\n    });\n    code += 'return s;';\n\n    /* jshint -W054 */\n    var evaledFnGetter = new Function('s', 'l', 'eso', 'fe', code); // s=scope, l=locals, eso=ensureSafeObject\n    /* jshint +W054 */\n    evaledFnGetter.toString = valueFn(code);\n    if (needsEnsureSafeObject) {\n      evaledFnGetter = getterFnWithEnsureSafeObject(evaledFnGetter, fullExp);\n    }\n    fn = evaledFnGetter;\n  }\n\n  fn.sharedGetter = true;\n  fn.assign = function(self, value, locals) {\n    return setter(self, locals, path, value, path);\n  };\n  getterFnCache[path] = fn;\n  return fn;\n}\n\nvar objectValueOf = Object.prototype.valueOf;\n\nfunction getValueOf(value) {\n  return isFunction(value.valueOf) ? value.valueOf() : objectValueOf.call(value);\n}\n\n///////////////////////////////////\n\n/**\n * @ngdoc service\n * @name $parse\n * @kind function\n *\n * @description\n *\n * Converts Angular {@link guide/expression expression} into a function.\n *\n * ```js\n *   var getter = $parse('user.name');\n *   var setter = getter.assign;\n *   var context = {user:{name:'angular'}};\n *   var locals = {user:{name:'local'}};\n *\n *   expect(getter(context)).toEqual('angular');\n *   setter(context, 'newValue');\n *   expect(context.user.name).toEqual('newValue');\n *   expect(getter(context, locals)).toEqual('local');\n * ```\n *\n *\n * @param {string} expression String expression to compile.\n * @returns {function(context, locals)} a function which represents the compiled expression:\n *\n *    * `context` – `{object}` – an object against which any expressions embedded in the strings\n *      are evaluated against (typically a scope object).\n *    * `locals` – `{object=}` – local variables context object, useful for overriding values in\n *      `context`.\n *\n *    The returned function also has the following properties:\n *      * `literal` – `{boolean}` – whether the expression's top-level node is a JavaScript\n *        literal.\n *      * `constant` – `{boolean}` – whether the expression is made entirely of JavaScript\n *        constant literals.\n *      * `assign` – `{?function(context, value)}` – if the expression is assignable, this will be\n *        set to a function to change its value on the given context.\n *\n */\n\n\n/**\n * @ngdoc provider\n * @name $parseProvider\n *\n * @description\n * `$parseProvider` can be used for configuring the default behavior of the {@link ng.$parse $parse}\n *  service.\n */\nfunction $ParseProvider() {\n  var cacheDefault = createMap();\n  var cacheExpensive = createMap();\n\n\n\n  this.$get = ['$filter', '$sniffer', function($filter, $sniffer) {\n    var $parseOptions = {\n          csp: $sniffer.csp,\n          expensiveChecks: false\n        },\n        $parseOptionsExpensive = {\n          csp: $sniffer.csp,\n          expensiveChecks: true\n        };\n\n    function wrapSharedExpression(exp) {\n      var wrapped = exp;\n\n      if (exp.sharedGetter) {\n        wrapped = function $parseWrapper(self, locals) {\n          return exp(self, locals);\n        };\n        wrapped.literal = exp.literal;\n        wrapped.constant = exp.constant;\n        wrapped.assign = exp.assign;\n      }\n\n      return wrapped;\n    }\n\n    return function $parse(exp, interceptorFn, expensiveChecks) {\n      var parsedExpression, oneTime, cacheKey;\n\n      switch (typeof exp) {\n        case 'string':\n          cacheKey = exp = exp.trim();\n\n          var cache = (expensiveChecks ? cacheExpensive : cacheDefault);\n          parsedExpression = cache[cacheKey];\n\n          if (!parsedExpression) {\n            if (exp.charAt(0) === ':' && exp.charAt(1) === ':') {\n              oneTime = true;\n              exp = exp.substring(2);\n            }\n\n            var parseOptions = expensiveChecks ? $parseOptionsExpensive : $parseOptions;\n            var lexer = new Lexer(parseOptions);\n            var parser = new Parser(lexer, $filter, parseOptions);\n            parsedExpression = parser.parse(exp);\n\n            if (parsedExpression.constant) {\n              parsedExpression.$$watchDelegate = constantWatchDelegate;\n            } else if (oneTime) {\n              //oneTime is not part of the exp passed to the Parser so we may have to\n              //wrap the parsedExpression before adding a $$watchDelegate\n              parsedExpression = wrapSharedExpression(parsedExpression);\n              parsedExpression.$$watchDelegate = parsedExpression.literal ?\n                oneTimeLiteralWatchDelegate : oneTimeWatchDelegate;\n            } else if (parsedExpression.inputs) {\n              parsedExpression.$$watchDelegate = inputsWatchDelegate;\n            }\n\n            cache[cacheKey] = parsedExpression;\n          }\n          return addInterceptor(parsedExpression, interceptorFn);\n\n        case 'function':\n          return addInterceptor(exp, interceptorFn);\n\n        default:\n          return addInterceptor(noop, interceptorFn);\n      }\n    };\n\n    function collectExpressionInputs(inputs, list) {\n      for (var i = 0, ii = inputs.length; i < ii; i++) {\n        var input = inputs[i];\n        if (!input.constant) {\n          if (input.inputs) {\n            collectExpressionInputs(input.inputs, list);\n          } else if (list.indexOf(input) === -1) { // TODO(perf) can we do better?\n            list.push(input);\n          }\n        }\n      }\n\n      return list;\n    }\n\n    function expressionInputDirtyCheck(newValue, oldValueOfValue) {\n\n      if (newValue == null || oldValueOfValue == null) { // null/undefined\n        return newValue === oldValueOfValue;\n      }\n\n      if (typeof newValue === 'object') {\n\n        // attempt to convert the value to a primitive type\n        // TODO(docs): add a note to docs that by implementing valueOf even objects and arrays can\n        //             be cheaply dirty-checked\n        newValue = getValueOf(newValue);\n\n        if (typeof newValue === 'object') {\n          // objects/arrays are not supported - deep-watching them would be too expensive\n          return false;\n        }\n\n        // fall-through to the primitive equality check\n      }\n\n      //Primitive or NaN\n      return newValue === oldValueOfValue || (newValue !== newValue && oldValueOfValue !== oldValueOfValue);\n    }\n\n    function inputsWatchDelegate(scope, listener, objectEquality, parsedExpression) {\n      var inputExpressions = parsedExpression.$$inputs ||\n                    (parsedExpression.$$inputs = collectExpressionInputs(parsedExpression.inputs, []));\n\n      var lastResult;\n\n      if (inputExpressions.length === 1) {\n        var oldInputValue = expressionInputDirtyCheck; // init to something unique so that equals check fails\n        inputExpressions = inputExpressions[0];\n        return scope.$watch(function expressionInputWatch(scope) {\n          var newInputValue = inputExpressions(scope);\n          if (!expressionInputDirtyCheck(newInputValue, oldInputValue)) {\n            lastResult = parsedExpression(scope);\n            oldInputValue = newInputValue && getValueOf(newInputValue);\n          }\n          return lastResult;\n        }, listener, objectEquality);\n      }\n\n      var oldInputValueOfValues = [];\n      for (var i = 0, ii = inputExpressions.length; i < ii; i++) {\n        oldInputValueOfValues[i] = expressionInputDirtyCheck; // init to something unique so that equals check fails\n      }\n\n      return scope.$watch(function expressionInputsWatch(scope) {\n        var changed = false;\n\n        for (var i = 0, ii = inputExpressions.length; i < ii; i++) {\n          var newInputValue = inputExpressions[i](scope);\n          if (changed || (changed = !expressionInputDirtyCheck(newInputValue, oldInputValueOfValues[i]))) {\n            oldInputValueOfValues[i] = newInputValue && getValueOf(newInputValue);\n          }\n        }\n\n        if (changed) {\n          lastResult = parsedExpression(scope);\n        }\n\n        return lastResult;\n      }, listener, objectEquality);\n    }\n\n    function oneTimeWatchDelegate(scope, listener, objectEquality, parsedExpression) {\n      var unwatch, lastValue;\n      return unwatch = scope.$watch(function oneTimeWatch(scope) {\n        return parsedExpression(scope);\n      }, function oneTimeListener(value, old, scope) {\n        lastValue = value;\n        if (isFunction(listener)) {\n          listener.apply(this, arguments);\n        }\n        if (isDefined(value)) {\n          scope.$$postDigest(function() {\n            if (isDefined(lastValue)) {\n              unwatch();\n            }\n          });\n        }\n      }, objectEquality);\n    }\n\n    function oneTimeLiteralWatchDelegate(scope, listener, objectEquality, parsedExpression) {\n      var unwatch, lastValue;\n      return unwatch = scope.$watch(function oneTimeWatch(scope) {\n        return parsedExpression(scope);\n      }, function oneTimeListener(value, old, scope) {\n        lastValue = value;\n        if (isFunction(listener)) {\n          listener.call(this, value, old, scope);\n        }\n        if (isAllDefined(value)) {\n          scope.$$postDigest(function() {\n            if (isAllDefined(lastValue)) unwatch();\n          });\n        }\n      }, objectEquality);\n\n      function isAllDefined(value) {\n        var allDefined = true;\n        forEach(value, function(val) {\n          if (!isDefined(val)) allDefined = false;\n        });\n        return allDefined;\n      }\n    }\n\n    function constantWatchDelegate(scope, listener, objectEquality, parsedExpression) {\n      var unwatch;\n      return unwatch = scope.$watch(function constantWatch(scope) {\n        return parsedExpression(scope);\n      }, function constantListener(value, old, scope) {\n        if (isFunction(listener)) {\n          listener.apply(this, arguments);\n        }\n        unwatch();\n      }, objectEquality);\n    }\n\n    function addInterceptor(parsedExpression, interceptorFn) {\n      if (!interceptorFn) return parsedExpression;\n      var watchDelegate = parsedExpression.$$watchDelegate;\n\n      var regularWatch =\n          watchDelegate !== oneTimeLiteralWatchDelegate &&\n          watchDelegate !== oneTimeWatchDelegate;\n\n      var fn = regularWatch ? function regularInterceptedExpression(scope, locals) {\n        var value = parsedExpression(scope, locals);\n        return interceptorFn(value, scope, locals);\n      } : function oneTimeInterceptedExpression(scope, locals) {\n        var value = parsedExpression(scope, locals);\n        var result = interceptorFn(value, scope, locals);\n        // we only return the interceptor's result if the\n        // initial value is defined (for bind-once)\n        return isDefined(value) ? result : value;\n      };\n\n      // Propagate $$watchDelegates other then inputsWatchDelegate\n      if (parsedExpression.$$watchDelegate &&\n          parsedExpression.$$watchDelegate !== inputsWatchDelegate) {\n        fn.$$watchDelegate = parsedExpression.$$watchDelegate;\n      } else if (!interceptorFn.$stateful) {\n        // If there is an interceptor, but no watchDelegate then treat the interceptor like\n        // we treat filters - it is assumed to be a pure function unless flagged with $stateful\n        fn.$$watchDelegate = inputsWatchDelegate;\n        fn.inputs = [parsedExpression];\n      }\n\n      return fn;\n    }\n  }];\n}\n\n/**\n * @ngdoc service\n * @name $q\n * @requires $rootScope\n *\n * @description\n * A service that helps you run functions asynchronously, and use their return values (or exceptions)\n * when they are done processing.\n *\n * This is an implementation of promises/deferred objects inspired by\n * [Kris Kowal's Q](https://github.com/kriskowal/q).\n *\n * $q can be used in two fashions --- one which is more similar to Kris Kowal's Q or jQuery's Deferred\n * implementations, and the other which resembles ES6 promises to some degree.\n *\n * # $q constructor\n *\n * The streamlined ES6 style promise is essentially just using $q as a constructor which takes a `resolver`\n * function as the first argument. This is similar to the native Promise implementation from ES6 Harmony,\n * see [MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise).\n *\n * While the constructor-style use is supported, not all of the supporting methods from ES6 Harmony promises are\n * available yet.\n *\n * It can be used like so:\n *\n * ```js\n *   // for the purpose of this example let's assume that variables `$q` and `okToGreet`\n *   // are available in the current lexical scope (they could have been injected or passed in).\n *\n *   function asyncGreet(name) {\n *     // perform some asynchronous operation, resolve or reject the promise when appropriate.\n *     return $q(function(resolve, reject) {\n *       setTimeout(function() {\n *         if (okToGreet(name)) {\n *           resolve('Hello, ' + name + '!');\n *         } else {\n *           reject('Greeting ' + name + ' is not allowed.');\n *         }\n *       }, 1000);\n *     });\n *   }\n *\n *   var promise = asyncGreet('Robin Hood');\n *   promise.then(function(greeting) {\n *     alert('Success: ' + greeting);\n *   }, function(reason) {\n *     alert('Failed: ' + reason);\n *   });\n * ```\n *\n * Note: progress/notify callbacks are not currently supported via the ES6-style interface.\n *\n * However, the more traditional CommonJS-style usage is still available, and documented below.\n *\n * [The CommonJS Promise proposal](http://wiki.commonjs.org/wiki/Promises) describes a promise as an\n * interface for interacting with an object that represents the result of an action that is\n * performed asynchronously, and may or may not be finished at any given point in time.\n *\n * From the perspective of dealing with error handling, deferred and promise APIs are to\n * asynchronous programming what `try`, `catch` and `throw` keywords are to synchronous programming.\n *\n * ```js\n *   // for the purpose of this example let's assume that variables `$q` and `okToGreet`\n *   // are available in the current lexical scope (they could have been injected or passed in).\n *\n *   function asyncGreet(name) {\n *     var deferred = $q.defer();\n *\n *     setTimeout(function() {\n *       deferred.notify('About to greet ' + name + '.');\n *\n *       if (okToGreet(name)) {\n *         deferred.resolve('Hello, ' + name + '!');\n *       } else {\n *         deferred.reject('Greeting ' + name + ' is not allowed.');\n *       }\n *     }, 1000);\n *\n *     return deferred.promise;\n *   }\n *\n *   var promise = asyncGreet('Robin Hood');\n *   promise.then(function(greeting) {\n *     alert('Success: ' + greeting);\n *   }, function(reason) {\n *     alert('Failed: ' + reason);\n *   }, function(update) {\n *     alert('Got notification: ' + update);\n *   });\n * ```\n *\n * At first it might not be obvious why this extra complexity is worth the trouble. The payoff\n * comes in the way of guarantees that promise and deferred APIs make, see\n * https://github.com/kriskowal/uncommonjs/blob/master/promises/specification.md.\n *\n * Additionally the promise api allows for composition that is very hard to do with the\n * traditional callback ([CPS](http://en.wikipedia.org/wiki/Continuation-passing_style)) approach.\n * For more on this please see the [Q documentation](https://github.com/kriskowal/q) especially the\n * section on serial or parallel joining of promises.\n *\n * # The Deferred API\n *\n * A new instance of deferred is constructed by calling `$q.defer()`.\n *\n * The purpose of the deferred object is to expose the associated Promise instance as well as APIs\n * that can be used for signaling the successful or unsuccessful completion, as well as the status\n * of the task.\n *\n * **Methods**\n *\n * - `resolve(value)` – resolves the derived promise with the `value`. If the value is a rejection\n *   constructed via `$q.reject`, the promise will be rejected instead.\n * - `reject(reason)` – rejects the derived promise with the `reason`. This is equivalent to\n *   resolving it with a rejection constructed via `$q.reject`.\n * - `notify(value)` - provides updates on the status of the promise's execution. This may be called\n *   multiple times before the promise is either resolved or rejected.\n *\n * **Properties**\n *\n * - promise – `{Promise}` – promise object associated with this deferred.\n *\n *\n * # The Promise API\n *\n * A new promise instance is created when a deferred instance is created and can be retrieved by\n * calling `deferred.promise`.\n *\n * The purpose of the promise object is to allow for interested parties to get access to the result\n * of the deferred task when it completes.\n *\n * **Methods**\n *\n * - `then(successCallback, errorCallback, notifyCallback)` – regardless of when the promise was or\n *   will be resolved or rejected, `then` calls one of the success or error callbacks asynchronously\n *   as soon as the result is available. The callbacks are called with a single argument: the result\n *   or rejection reason. Additionally, the notify callback may be called zero or more times to\n *   provide a progress indication, before the promise is resolved or rejected.\n *\n *   This method *returns a new promise* which is resolved or rejected via the return value of the\n *   `successCallback`, `errorCallback`. It also notifies via the return value of the\n *   `notifyCallback` method. The promise cannot be resolved or rejected from the notifyCallback\n *   method.\n *\n * - `catch(errorCallback)` – shorthand for `promise.then(null, errorCallback)`\n *\n * - `finally(callback, notifyCallback)` – allows you to observe either the fulfillment or rejection of a promise,\n *   but to do so without modifying the final value. This is useful to release resources or do some\n *   clean-up that needs to be done whether the promise was rejected or resolved. See the [full\n *   specification](https://github.com/kriskowal/q/wiki/API-Reference#promisefinallycallback) for\n *   more information.\n *\n * # Chaining promises\n *\n * Because calling the `then` method of a promise returns a new derived promise, it is easily\n * possible to create a chain of promises:\n *\n * ```js\n *   promiseB = promiseA.then(function(result) {\n *     return result + 1;\n *   });\n *\n *   // promiseB will be resolved immediately after promiseA is resolved and its value\n *   // will be the result of promiseA incremented by 1\n * ```\n *\n * It is possible to create chains of any length and since a promise can be resolved with another\n * promise (which will defer its resolution further), it is possible to pause/defer resolution of\n * the promises at any point in the chain. This makes it possible to implement powerful APIs like\n * $http's response interceptors.\n *\n *\n * # Differences between Kris Kowal's Q and $q\n *\n *  There are two main differences:\n *\n * - $q is integrated with the {@link ng.$rootScope.Scope} Scope model observation\n *   mechanism in angular, which means faster propagation of resolution or rejection into your\n *   models and avoiding unnecessary browser repaints, which would result in flickering UI.\n * - Q has many more features than $q, but that comes at a cost of bytes. $q is tiny, but contains\n *   all the important functionality needed for common async tasks.\n *\n *  # Testing\n *\n *  ```js\n *    it('should simulate promise', inject(function($q, $rootScope) {\n *      var deferred = $q.defer();\n *      var promise = deferred.promise;\n *      var resolvedValue;\n *\n *      promise.then(function(value) { resolvedValue = value; });\n *      expect(resolvedValue).toBeUndefined();\n *\n *      // Simulate resolving of promise\n *      deferred.resolve(123);\n *      // Note that the 'then' function does not get called synchronously.\n *      // This is because we want the promise API to always be async, whether or not\n *      // it got called synchronously or asynchronously.\n *      expect(resolvedValue).toBeUndefined();\n *\n *      // Propagate promise resolution to 'then' functions using $apply().\n *      $rootScope.$apply();\n *      expect(resolvedValue).toEqual(123);\n *    }));\n *  ```\n *\n * @param {function(function, function)} resolver Function which is responsible for resolving or\n *   rejecting the newly created promise. The first parameter is a function which resolves the\n *   promise, the second parameter is a function which rejects the promise.\n *\n * @returns {Promise} The newly created promise.\n */\nfunction $QProvider() {\n\n  this.$get = ['$rootScope', '$exceptionHandler', function($rootScope, $exceptionHandler) {\n    return qFactory(function(callback) {\n      $rootScope.$evalAsync(callback);\n    }, $exceptionHandler);\n  }];\n}\n\nfunction $$QProvider() {\n  this.$get = ['$browser', '$exceptionHandler', function($browser, $exceptionHandler) {\n    return qFactory(function(callback) {\n      $browser.defer(callback);\n    }, $exceptionHandler);\n  }];\n}\n\n/**\n * Constructs a promise manager.\n *\n * @param {function(function)} nextTick Function for executing functions in the next turn.\n * @param {function(...*)} exceptionHandler Function into which unexpected exceptions are passed for\n *     debugging purposes.\n * @returns {object} Promise manager.\n */\nfunction qFactory(nextTick, exceptionHandler) {\n  var $qMinErr = minErr('$q', TypeError);\n  function callOnce(self, resolveFn, rejectFn) {\n    var called = false;\n    function wrap(fn) {\n      return function(value) {\n        if (called) return;\n        called = true;\n        fn.call(self, value);\n      };\n    }\n\n    return [wrap(resolveFn), wrap(rejectFn)];\n  }\n\n  /**\n   * @ngdoc method\n   * @name ng.$q#defer\n   * @kind function\n   *\n   * @description\n   * Creates a `Deferred` object which represents a task which will finish in the future.\n   *\n   * @returns {Deferred} Returns a new instance of deferred.\n   */\n  var defer = function() {\n    return new Deferred();\n  };\n\n  function Promise() {\n    this.$$state = { status: 0 };\n  }\n\n  Promise.prototype = {\n    then: function(onFulfilled, onRejected, progressBack) {\n      var result = new Deferred();\n\n      this.$$state.pending = this.$$state.pending || [];\n      this.$$state.pending.push([result, onFulfilled, onRejected, progressBack]);\n      if (this.$$state.status > 0) scheduleProcessQueue(this.$$state);\n\n      return result.promise;\n    },\n\n    \"catch\": function(callback) {\n      return this.then(null, callback);\n    },\n\n    \"finally\": function(callback, progressBack) {\n      return this.then(function(value) {\n        return handleCallback(value, true, callback);\n      }, function(error) {\n        return handleCallback(error, false, callback);\n      }, progressBack);\n    }\n  };\n\n  //Faster, more basic than angular.bind http://jsperf.com/angular-bind-vs-custom-vs-native\n  function simpleBind(context, fn) {\n    return function(value) {\n      fn.call(context, value);\n    };\n  }\n\n  function processQueue(state) {\n    var fn, promise, pending;\n\n    pending = state.pending;\n    state.processScheduled = false;\n    state.pending = undefined;\n    for (var i = 0, ii = pending.length; i < ii; ++i) {\n      promise = pending[i][0];\n      fn = pending[i][state.status];\n      try {\n        if (isFunction(fn)) {\n          promise.resolve(fn(state.value));\n        } else if (state.status === 1) {\n          promise.resolve(state.value);\n        } else {\n          promise.reject(state.value);\n        }\n      } catch (e) {\n        promise.reject(e);\n        exceptionHandler(e);\n      }\n    }\n  }\n\n  function scheduleProcessQueue(state) {\n    if (state.processScheduled || !state.pending) return;\n    state.processScheduled = true;\n    nextTick(function() { processQueue(state); });\n  }\n\n  function Deferred() {\n    this.promise = new Promise();\n    //Necessary to support unbound execution :/\n    this.resolve = simpleBind(this, this.resolve);\n    this.reject = simpleBind(this, this.reject);\n    this.notify = simpleBind(this, this.notify);\n  }\n\n  Deferred.prototype = {\n    resolve: function(val) {\n      if (this.promise.$$state.status) return;\n      if (val === this.promise) {\n        this.$$reject($qMinErr(\n          'qcycle',\n          \"Expected promise to be resolved with value other than itself '{0}'\",\n          val));\n      } else {\n        this.$$resolve(val);\n      }\n\n    },\n\n    $$resolve: function(val) {\n      var then, fns;\n\n      fns = callOnce(this, this.$$resolve, this.$$reject);\n      try {\n        if ((isObject(val) || isFunction(val))) then = val && val.then;\n        if (isFunction(then)) {\n          this.promise.$$state.status = -1;\n          then.call(val, fns[0], fns[1], this.notify);\n        } else {\n          this.promise.$$state.value = val;\n          this.promise.$$state.status = 1;\n          scheduleProcessQueue(this.promise.$$state);\n        }\n      } catch (e) {\n        fns[1](e);\n        exceptionHandler(e);\n      }\n    },\n\n    reject: function(reason) {\n      if (this.promise.$$state.status) return;\n      this.$$reject(reason);\n    },\n\n    $$reject: function(reason) {\n      this.promise.$$state.value = reason;\n      this.promise.$$state.status = 2;\n      scheduleProcessQueue(this.promise.$$state);\n    },\n\n    notify: function(progress) {\n      var callbacks = this.promise.$$state.pending;\n\n      if ((this.promise.$$state.status <= 0) && callbacks && callbacks.length) {\n        nextTick(function() {\n          var callback, result;\n          for (var i = 0, ii = callbacks.length; i < ii; i++) {\n            result = callbacks[i][0];\n            callback = callbacks[i][3];\n            try {\n              result.notify(isFunction(callback) ? callback(progress) : progress);\n            } catch (e) {\n              exceptionHandler(e);\n            }\n          }\n        });\n      }\n    }\n  };\n\n  /**\n   * @ngdoc method\n   * @name $q#reject\n   * @kind function\n   *\n   * @description\n   * Creates a promise that is resolved as rejected with the specified `reason`. This api should be\n   * used to forward rejection in a chain of promises. If you are dealing with the last promise in\n   * a promise chain, you don't need to worry about it.\n   *\n   * When comparing deferreds/promises to the familiar behavior of try/catch/throw, think of\n   * `reject` as the `throw` keyword in JavaScript. This also means that if you \"catch\" an error via\n   * a promise error callback and you want to forward the error to the promise derived from the\n   * current promise, you have to \"rethrow\" the error by returning a rejection constructed via\n   * `reject`.\n   *\n   * ```js\n   *   promiseB = promiseA.then(function(result) {\n   *     // success: do something and resolve promiseB\n   *     //          with the old or a new result\n   *     return result;\n   *   }, function(reason) {\n   *     // error: handle the error if possible and\n   *     //        resolve promiseB with newPromiseOrValue,\n   *     //        otherwise forward the rejection to promiseB\n   *     if (canHandle(reason)) {\n   *      // handle the error and recover\n   *      return newPromiseOrValue;\n   *     }\n   *     return $q.reject(reason);\n   *   });\n   * ```\n   *\n   * @param {*} reason Constant, message, exception or an object representing the rejection reason.\n   * @returns {Promise} Returns a promise that was already resolved as rejected with the `reason`.\n   */\n  var reject = function(reason) {\n    var result = new Deferred();\n    result.reject(reason);\n    return result.promise;\n  };\n\n  var makePromise = function makePromise(value, resolved) {\n    var result = new Deferred();\n    if (resolved) {\n      result.resolve(value);\n    } else {\n      result.reject(value);\n    }\n    return result.promise;\n  };\n\n  var handleCallback = function handleCallback(value, isResolved, callback) {\n    var callbackOutput = null;\n    try {\n      if (isFunction(callback)) callbackOutput = callback();\n    } catch (e) {\n      return makePromise(e, false);\n    }\n    if (isPromiseLike(callbackOutput)) {\n      return callbackOutput.then(function() {\n        return makePromise(value, isResolved);\n      }, function(error) {\n        return makePromise(error, false);\n      });\n    } else {\n      return makePromise(value, isResolved);\n    }\n  };\n\n  /**\n   * @ngdoc method\n   * @name $q#when\n   * @kind function\n   *\n   * @description\n   * Wraps an object that might be a value or a (3rd party) then-able promise into a $q promise.\n   * This is useful when you are dealing with an object that might or might not be a promise, or if\n   * the promise comes from a source that can't be trusted.\n   *\n   * @param {*} value Value or a promise\n   * @returns {Promise} Returns a promise of the passed value or promise\n   */\n\n\n  var when = function(value, callback, errback, progressBack) {\n    var result = new Deferred();\n    result.resolve(value);\n    return result.promise.then(callback, errback, progressBack);\n  };\n\n  /**\n   * @ngdoc method\n   * @name $q#all\n   * @kind function\n   *\n   * @description\n   * Combines multiple promises into a single promise that is resolved when all of the input\n   * promises are resolved.\n   *\n   * @param {Array.<Promise>|Object.<Promise>} promises An array or hash of promises.\n   * @returns {Promise} Returns a single promise that will be resolved with an array/hash of values,\n   *   each value corresponding to the promise at the same index/key in the `promises` array/hash.\n   *   If any of the promises is resolved with a rejection, this resulting promise will be rejected\n   *   with the same rejection value.\n   */\n\n  function all(promises) {\n    var deferred = new Deferred(),\n        counter = 0,\n        results = isArray(promises) ? [] : {};\n\n    forEach(promises, function(promise, key) {\n      counter++;\n      when(promise).then(function(value) {\n        if (results.hasOwnProperty(key)) return;\n        results[key] = value;\n        if (!(--counter)) deferred.resolve(results);\n      }, function(reason) {\n        if (results.hasOwnProperty(key)) return;\n        deferred.reject(reason);\n      });\n    });\n\n    if (counter === 0) {\n      deferred.resolve(results);\n    }\n\n    return deferred.promise;\n  }\n\n  var $Q = function Q(resolver) {\n    if (!isFunction(resolver)) {\n      throw $qMinErr('norslvr', \"Expected resolverFn, got '{0}'\", resolver);\n    }\n\n    if (!(this instanceof Q)) {\n      // More useful when $Q is the Promise itself.\n      return new Q(resolver);\n    }\n\n    var deferred = new Deferred();\n\n    function resolveFn(value) {\n      deferred.resolve(value);\n    }\n\n    function rejectFn(reason) {\n      deferred.reject(reason);\n    }\n\n    resolver(resolveFn, rejectFn);\n\n    return deferred.promise;\n  };\n\n  $Q.defer = defer;\n  $Q.reject = reject;\n  $Q.when = when;\n  $Q.all = all;\n\n  return $Q;\n}\n\nfunction $$RAFProvider() { //rAF\n  this.$get = ['$window', '$timeout', function($window, $timeout) {\n    var requestAnimationFrame = $window.requestAnimationFrame ||\n                                $window.webkitRequestAnimationFrame;\n\n    var cancelAnimationFrame = $window.cancelAnimationFrame ||\n                               $window.webkitCancelAnimationFrame ||\n                               $window.webkitCancelRequestAnimationFrame;\n\n    var rafSupported = !!requestAnimationFrame;\n    var raf = rafSupported\n      ? function(fn) {\n          var id = requestAnimationFrame(fn);\n          return function() {\n            cancelAnimationFrame(id);\n          };\n        }\n      : function(fn) {\n          var timer = $timeout(fn, 16.66, false); // 1000 / 60 = 16.666\n          return function() {\n            $timeout.cancel(timer);\n          };\n        };\n\n    raf.supported = rafSupported;\n\n    return raf;\n  }];\n}\n\n/**\n * DESIGN NOTES\n *\n * The design decisions behind the scope are heavily favored for speed and memory consumption.\n *\n * The typical use of scope is to watch the expressions, which most of the time return the same\n * value as last time so we optimize the operation.\n *\n * Closures construction is expensive in terms of speed as well as memory:\n *   - No closures, instead use prototypical inheritance for API\n *   - Internal state needs to be stored on scope directly, which means that private state is\n *     exposed as $$____ properties\n *\n * Loop operations are optimized by using while(count--) { ... }\n *   - this means that in order to keep the same order of execution as addition we have to add\n *     items to the array at the beginning (unshift) instead of at the end (push)\n *\n * Child scopes are created and removed often\n *   - Using an array would be slow since inserts in middle are expensive so we use linked list\n *\n * There are few watches then a lot of observers. This is why you don't want the observer to be\n * implemented in the same way as watch. Watch requires return of initialization function which\n * are expensive to construct.\n */\n\n\n/**\n * @ngdoc provider\n * @name $rootScopeProvider\n * @description\n *\n * Provider for the $rootScope service.\n */\n\n/**\n * @ngdoc method\n * @name $rootScopeProvider#digestTtl\n * @description\n *\n * Sets the number of `$digest` iterations the scope should attempt to execute before giving up and\n * assuming that the model is unstable.\n *\n * The current default is 10 iterations.\n *\n * In complex applications it's possible that the dependencies between `$watch`s will result in\n * several digest iterations. However if an application needs more than the default 10 digest\n * iterations for its model to stabilize then you should investigate what is causing the model to\n * continuously change during the digest.\n *\n * Increasing the TTL could have performance implications, so you should not change it without\n * proper justification.\n *\n * @param {number} limit The number of digest iterations.\n */\n\n\n/**\n * @ngdoc service\n * @name $rootScope\n * @description\n *\n * Every application has a single root {@link ng.$rootScope.Scope scope}.\n * All other scopes are descendant scopes of the root scope. Scopes provide separation\n * between the model and the view, via a mechanism for watching the model for changes.\n * They also provide an event emission/broadcast and subscription facility. See the\n * {@link guide/scope developer guide on scopes}.\n */\nfunction $RootScopeProvider() {\n  var TTL = 10;\n  var $rootScopeMinErr = minErr('$rootScope');\n  var lastDirtyWatch = null;\n  var applyAsyncId = null;\n\n  this.digestTtl = function(value) {\n    if (arguments.length) {\n      TTL = value;\n    }\n    return TTL;\n  };\n\n  this.$get = ['$injector', '$exceptionHandler', '$parse', '$browser',\n      function($injector, $exceptionHandler, $parse, $browser) {\n\n    /**\n     * @ngdoc type\n     * @name $rootScope.Scope\n     *\n     * @description\n     * A root scope can be retrieved using the {@link ng.$rootScope $rootScope} key from the\n     * {@link auto.$injector $injector}. Child scopes are created using the\n     * {@link ng.$rootScope.Scope#$new $new()} method. (Most scopes are created automatically when\n     * compiled HTML template is executed.)\n     *\n     * Here is a simple scope snippet to show how you can interact with the scope.\n     * ```html\n     * <file src=\"./test/ng/rootScopeSpec.js\" tag=\"docs1\" />\n     * ```\n     *\n     * # Inheritance\n     * A scope can inherit from a parent scope, as in this example:\n     * ```js\n         var parent = $rootScope;\n         var child = parent.$new();\n\n         parent.salutation = \"Hello\";\n         expect(child.salutation).toEqual('Hello');\n\n         child.salutation = \"Welcome\";\n         expect(child.salutation).toEqual('Welcome');\n         expect(parent.salutation).toEqual('Hello');\n     * ```\n     *\n     * When interacting with `Scope` in tests, additional helper methods are available on the\n     * instances of `Scope` type. See {@link ngMock.$rootScope.Scope ngMock Scope} for additional\n     * details.\n     *\n     *\n     * @param {Object.<string, function()>=} providers Map of service factory which need to be\n     *                                       provided for the current scope. Defaults to {@link ng}.\n     * @param {Object.<string, *>=} instanceCache Provides pre-instantiated services which should\n     *                              append/override services provided by `providers`. This is handy\n     *                              when unit-testing and having the need to override a default\n     *                              service.\n     * @returns {Object} Newly created scope.\n     *\n     */\n    function Scope() {\n      this.$id = nextUid();\n      this.$$phase = this.$parent = this.$$watchers =\n                     this.$$nextSibling = this.$$prevSibling =\n                     this.$$childHead = this.$$childTail = null;\n      this.$root = this;\n      this.$$destroyed = false;\n      this.$$listeners = {};\n      this.$$listenerCount = {};\n      this.$$isolateBindings = null;\n    }\n\n    /**\n     * @ngdoc property\n     * @name $rootScope.Scope#$id\n     *\n     * @description\n     * Unique scope ID (monotonically increasing) useful for debugging.\n     */\n\n     /**\n      * @ngdoc property\n      * @name $rootScope.Scope#$parent\n      *\n      * @description\n      * Reference to the parent scope.\n      */\n\n      /**\n       * @ngdoc property\n       * @name $rootScope.Scope#$root\n       *\n       * @description\n       * Reference to the root scope.\n       */\n\n    Scope.prototype = {\n      constructor: Scope,\n      /**\n       * @ngdoc method\n       * @name $rootScope.Scope#$new\n       * @kind function\n       *\n       * @description\n       * Creates a new child {@link ng.$rootScope.Scope scope}.\n       *\n       * The parent scope will propagate the {@link ng.$rootScope.Scope#$digest $digest()} event.\n       * The scope can be removed from the scope hierarchy using {@link ng.$rootScope.Scope#$destroy $destroy()}.\n       *\n       * {@link ng.$rootScope.Scope#$destroy $destroy()} must be called on a scope when it is\n       * desired for the scope and its child scopes to be permanently detached from the parent and\n       * thus stop participating in model change detection and listener notification by invoking.\n       *\n       * @param {boolean} isolate If true, then the scope does not prototypically inherit from the\n       *         parent scope. The scope is isolated, as it can not see parent scope properties.\n       *         When creating widgets, it is useful for the widget to not accidentally read parent\n       *         state.\n       *\n       * @param {Scope} [parent=this] The {@link ng.$rootScope.Scope `Scope`} that will be the `$parent`\n       *                              of the newly created scope. Defaults to `this` scope if not provided.\n       *                              This is used when creating a transclude scope to correctly place it\n       *                              in the scope hierarchy while maintaining the correct prototypical\n       *                              inheritance.\n       *\n       * @returns {Object} The newly created child scope.\n       *\n       */\n      $new: function(isolate, parent) {\n        var child;\n\n        parent = parent || this;\n\n        if (isolate) {\n          child = new Scope();\n          child.$root = this.$root;\n        } else {\n          // Only create a child scope class if somebody asks for one,\n          // but cache it to allow the VM to optimize lookups.\n          if (!this.$$ChildScope) {\n            this.$$ChildScope = function ChildScope() {\n              this.$$watchers = this.$$nextSibling =\n                  this.$$childHead = this.$$childTail = null;\n              this.$$listeners = {};\n              this.$$listenerCount = {};\n              this.$id = nextUid();\n              this.$$ChildScope = null;\n            };\n            this.$$ChildScope.prototype = this;\n          }\n          child = new this.$$ChildScope();\n        }\n        child.$parent = parent;\n        child.$$prevSibling = parent.$$childTail;\n        if (parent.$$childHead) {\n          parent.$$childTail.$$nextSibling = child;\n          parent.$$childTail = child;\n        } else {\n          parent.$$childHead = parent.$$childTail = child;\n        }\n\n        // When the new scope is not isolated or we inherit from `this`, and\n        // the parent scope is destroyed, the property `$$destroyed` is inherited\n        // prototypically. In all other cases, this property needs to be set\n        // when the parent scope is destroyed.\n        // The listener needs to be added after the parent is set\n        if (isolate || parent != this) child.$on('$destroy', destroyChild);\n\n        return child;\n\n        function destroyChild() {\n          child.$$destroyed = true;\n        }\n      },\n\n      /**\n       * @ngdoc method\n       * @name $rootScope.Scope#$watch\n       * @kind function\n       *\n       * @description\n       * Registers a `listener` callback to be executed whenever the `watchExpression` changes.\n       *\n       * - The `watchExpression` is called on every call to {@link ng.$rootScope.Scope#$digest\n       *   $digest()} and should return the value that will be watched. (Since\n       *   {@link ng.$rootScope.Scope#$digest $digest()} reruns when it detects changes the\n       *   `watchExpression` can execute multiple times per\n       *   {@link ng.$rootScope.Scope#$digest $digest()} and should be idempotent.)\n       * - The `listener` is called only when the value from the current `watchExpression` and the\n       *   previous call to `watchExpression` are not equal (with the exception of the initial run,\n       *   see below). Inequality is determined according to reference inequality,\n       *   [strict comparison](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Comparison_Operators)\n       *    via the `!==` Javascript operator, unless `objectEquality == true`\n       *   (see next point)\n       * - When `objectEquality == true`, inequality of the `watchExpression` is determined\n       *   according to the {@link angular.equals} function. To save the value of the object for\n       *   later comparison, the {@link angular.copy} function is used. This therefore means that\n       *   watching complex objects will have adverse memory and performance implications.\n       * - The watch `listener` may change the model, which may trigger other `listener`s to fire.\n       *   This is achieved by rerunning the watchers until no changes are detected. The rerun\n       *   iteration limit is 10 to prevent an infinite loop deadlock.\n       *\n       *\n       * If you want to be notified whenever {@link ng.$rootScope.Scope#$digest $digest} is called,\n       * you can register a `watchExpression` function with no `listener`. (Since `watchExpression`\n       * can execute multiple times per {@link ng.$rootScope.Scope#$digest $digest} cycle when a\n       * change is detected, be prepared for multiple calls to your listener.)\n       *\n       * After a watcher is registered with the scope, the `listener` fn is called asynchronously\n       * (via {@link ng.$rootScope.Scope#$evalAsync $evalAsync}) to initialize the\n       * watcher. In rare cases, this is undesirable because the listener is called when the result\n       * of `watchExpression` didn't change. To detect this scenario within the `listener` fn, you\n       * can compare the `newVal` and `oldVal`. If these two values are identical (`===`) then the\n       * listener was called due to initialization.\n       *\n       *\n       *\n       * # Example\n       * ```js\n           // let's assume that scope was dependency injected as the $rootScope\n           var scope = $rootScope;\n           scope.name = 'misko';\n           scope.counter = 0;\n\n           expect(scope.counter).toEqual(0);\n           scope.$watch('name', function(newValue, oldValue) {\n             scope.counter = scope.counter + 1;\n           });\n           expect(scope.counter).toEqual(0);\n\n           scope.$digest();\n           // the listener is always called during the first $digest loop after it was registered\n           expect(scope.counter).toEqual(1);\n\n           scope.$digest();\n           // but now it will not be called unless the value changes\n           expect(scope.counter).toEqual(1);\n\n           scope.name = 'adam';\n           scope.$digest();\n           expect(scope.counter).toEqual(2);\n\n\n\n           // Using a function as a watchExpression\n           var food;\n           scope.foodCounter = 0;\n           expect(scope.foodCounter).toEqual(0);\n           scope.$watch(\n             // This function returns the value being watched. It is called for each turn of the $digest loop\n             function() { return food; },\n             // This is the change listener, called when the value returned from the above function changes\n             function(newValue, oldValue) {\n               if ( newValue !== oldValue ) {\n                 // Only increment the counter if the value changed\n                 scope.foodCounter = scope.foodCounter + 1;\n               }\n             }\n           );\n           // No digest has been run so the counter will be zero\n           expect(scope.foodCounter).toEqual(0);\n\n           // Run the digest but since food has not changed count will still be zero\n           scope.$digest();\n           expect(scope.foodCounter).toEqual(0);\n\n           // Update food and run digest.  Now the counter will increment\n           food = 'cheeseburger';\n           scope.$digest();\n           expect(scope.foodCounter).toEqual(1);\n\n       * ```\n       *\n       *\n       *\n       * @param {(function()|string)} watchExpression Expression that is evaluated on each\n       *    {@link ng.$rootScope.Scope#$digest $digest} cycle. A change in the return value triggers\n       *    a call to the `listener`.\n       *\n       *    - `string`: Evaluated as {@link guide/expression expression}\n       *    - `function(scope)`: called with current `scope` as a parameter.\n       * @param {function(newVal, oldVal, scope)} listener Callback called whenever the value\n       *    of `watchExpression` changes.\n       *\n       *    - `newVal` contains the current value of the `watchExpression`\n       *    - `oldVal` contains the previous value of the `watchExpression`\n       *    - `scope` refers to the current scope\n       * @param {boolean=} objectEquality Compare for object equality using {@link angular.equals} instead of\n       *     comparing for reference equality.\n       * @returns {function()} Returns a deregistration function for this listener.\n       */\n      $watch: function(watchExp, listener, objectEquality) {\n        var get = $parse(watchExp);\n\n        if (get.$$watchDelegate) {\n          return get.$$watchDelegate(this, listener, objectEquality, get);\n        }\n        var scope = this,\n            array = scope.$$watchers,\n            watcher = {\n              fn: listener,\n              last: initWatchVal,\n              get: get,\n              exp: watchExp,\n              eq: !!objectEquality\n            };\n\n        lastDirtyWatch = null;\n\n        if (!isFunction(listener)) {\n          watcher.fn = noop;\n        }\n\n        if (!array) {\n          array = scope.$$watchers = [];\n        }\n        // we use unshift since we use a while loop in $digest for speed.\n        // the while loop reads in reverse order.\n        array.unshift(watcher);\n\n        return function deregisterWatch() {\n          arrayRemove(array, watcher);\n          lastDirtyWatch = null;\n        };\n      },\n\n      /**\n       * @ngdoc method\n       * @name $rootScope.Scope#$watchGroup\n       * @kind function\n       *\n       * @description\n       * A variant of {@link ng.$rootScope.Scope#$watch $watch()} where it watches an array of `watchExpressions`.\n       * If any one expression in the collection changes the `listener` is executed.\n       *\n       * - The items in the `watchExpressions` array are observed via standard $watch operation and are examined on every\n       *   call to $digest() to see if any items changes.\n       * - The `listener` is called whenever any expression in the `watchExpressions` array changes.\n       *\n       * @param {Array.<string|Function(scope)>} watchExpressions Array of expressions that will be individually\n       * watched using {@link ng.$rootScope.Scope#$watch $watch()}\n       *\n       * @param {function(newValues, oldValues, scope)} listener Callback called whenever the return value of any\n       *    expression in `watchExpressions` changes\n       *    The `newValues` array contains the current values of the `watchExpressions`, with the indexes matching\n       *    those of `watchExpression`\n       *    and the `oldValues` array contains the previous values of the `watchExpressions`, with the indexes matching\n       *    those of `watchExpression`\n       *    The `scope` refers to the current scope.\n       * @returns {function()} Returns a de-registration function for all listeners.\n       */\n      $watchGroup: function(watchExpressions, listener) {\n        var oldValues = new Array(watchExpressions.length);\n        var newValues = new Array(watchExpressions.length);\n        var deregisterFns = [];\n        var self = this;\n        var changeReactionScheduled = false;\n        var firstRun = true;\n\n        if (!watchExpressions.length) {\n          // No expressions means we call the listener ASAP\n          var shouldCall = true;\n          self.$evalAsync(function() {\n            if (shouldCall) listener(newValues, newValues, self);\n          });\n          return function deregisterWatchGroup() {\n            shouldCall = false;\n          };\n        }\n\n        if (watchExpressions.length === 1) {\n          // Special case size of one\n          return this.$watch(watchExpressions[0], function watchGroupAction(value, oldValue, scope) {\n            newValues[0] = value;\n            oldValues[0] = oldValue;\n            listener(newValues, (value === oldValue) ? newValues : oldValues, scope);\n          });\n        }\n\n        forEach(watchExpressions, function(expr, i) {\n          var unwatchFn = self.$watch(expr, function watchGroupSubAction(value, oldValue) {\n            newValues[i] = value;\n            oldValues[i] = oldValue;\n            if (!changeReactionScheduled) {\n              changeReactionScheduled = true;\n              self.$evalAsync(watchGroupAction);\n            }\n          });\n          deregisterFns.push(unwatchFn);\n        });\n\n        function watchGroupAction() {\n          changeReactionScheduled = false;\n\n          if (firstRun) {\n            firstRun = false;\n            listener(newValues, newValues, self);\n          } else {\n            listener(newValues, oldValues, self);\n          }\n        }\n\n        return function deregisterWatchGroup() {\n          while (deregisterFns.length) {\n            deregisterFns.shift()();\n          }\n        };\n      },\n\n\n      /**\n       * @ngdoc method\n       * @name $rootScope.Scope#$watchCollection\n       * @kind function\n       *\n       * @description\n       * Shallow watches the properties of an object and fires whenever any of the properties change\n       * (for arrays, this implies watching the array items; for object maps, this implies watching\n       * the properties). If a change is detected, the `listener` callback is fired.\n       *\n       * - The `obj` collection is observed via standard $watch operation and is examined on every\n       *   call to $digest() to see if any items have been added, removed, or moved.\n       * - The `listener` is called whenever anything within the `obj` has changed. Examples include\n       *   adding, removing, and moving items belonging to an object or array.\n       *\n       *\n       * # Example\n       * ```js\n          $scope.names = ['igor', 'matias', 'misko', 'james'];\n          $scope.dataCount = 4;\n\n          $scope.$watchCollection('names', function(newNames, oldNames) {\n            $scope.dataCount = newNames.length;\n          });\n\n          expect($scope.dataCount).toEqual(4);\n          $scope.$digest();\n\n          //still at 4 ... no changes\n          expect($scope.dataCount).toEqual(4);\n\n          $scope.names.pop();\n          $scope.$digest();\n\n          //now there's been a change\n          expect($scope.dataCount).toEqual(3);\n       * ```\n       *\n       *\n       * @param {string|function(scope)} obj Evaluated as {@link guide/expression expression}. The\n       *    expression value should evaluate to an object or an array which is observed on each\n       *    {@link ng.$rootScope.Scope#$digest $digest} cycle. Any shallow change within the\n       *    collection will trigger a call to the `listener`.\n       *\n       * @param {function(newCollection, oldCollection, scope)} listener a callback function called\n       *    when a change is detected.\n       *    - The `newCollection` object is the newly modified data obtained from the `obj` expression\n       *    - The `oldCollection` object is a copy of the former collection data.\n       *      Due to performance considerations, the`oldCollection` value is computed only if the\n       *      `listener` function declares two or more arguments.\n       *    - The `scope` argument refers to the current scope.\n       *\n       * @returns {function()} Returns a de-registration function for this listener. When the\n       *    de-registration function is executed, the internal watch operation is terminated.\n       */\n      $watchCollection: function(obj, listener) {\n        $watchCollectionInterceptor.$stateful = true;\n\n        var self = this;\n        // the current value, updated on each dirty-check run\n        var newValue;\n        // a shallow copy of the newValue from the last dirty-check run,\n        // updated to match newValue during dirty-check run\n        var oldValue;\n        // a shallow copy of the newValue from when the last change happened\n        var veryOldValue;\n        // only track veryOldValue if the listener is asking for it\n        var trackVeryOldValue = (listener.length > 1);\n        var changeDetected = 0;\n        var changeDetector = $parse(obj, $watchCollectionInterceptor);\n        var internalArray = [];\n        var internalObject = {};\n        var initRun = true;\n        var oldLength = 0;\n\n        function $watchCollectionInterceptor(_value) {\n          newValue = _value;\n          var newLength, key, bothNaN, newItem, oldItem;\n\n          // If the new value is undefined, then return undefined as the watch may be a one-time watch\n          if (isUndefined(newValue)) return;\n\n          if (!isObject(newValue)) { // if primitive\n            if (oldValue !== newValue) {\n              oldValue = newValue;\n              changeDetected++;\n            }\n          } else if (isArrayLike(newValue)) {\n            if (oldValue !== internalArray) {\n              // we are transitioning from something which was not an array into array.\n              oldValue = internalArray;\n              oldLength = oldValue.length = 0;\n              changeDetected++;\n            }\n\n            newLength = newValue.length;\n\n            if (oldLength !== newLength) {\n              // if lengths do not match we need to trigger change notification\n              changeDetected++;\n              oldValue.length = oldLength = newLength;\n            }\n            // copy the items to oldValue and look for changes.\n            for (var i = 0; i < newLength; i++) {\n              oldItem = oldValue[i];\n              newItem = newValue[i];\n\n              bothNaN = (oldItem !== oldItem) && (newItem !== newItem);\n              if (!bothNaN && (oldItem !== newItem)) {\n                changeDetected++;\n                oldValue[i] = newItem;\n              }\n            }\n          } else {\n            if (oldValue !== internalObject) {\n              // we are transitioning from something which was not an object into object.\n              oldValue = internalObject = {};\n              oldLength = 0;\n              changeDetected++;\n            }\n            // copy the items to oldValue and look for changes.\n            newLength = 0;\n            for (key in newValue) {\n              if (newValue.hasOwnProperty(key)) {\n                newLength++;\n                newItem = newValue[key];\n                oldItem = oldValue[key];\n\n                if (key in oldValue) {\n                  bothNaN = (oldItem !== oldItem) && (newItem !== newItem);\n                  if (!bothNaN && (oldItem !== newItem)) {\n                    changeDetected++;\n                    oldValue[key] = newItem;\n                  }\n                } else {\n                  oldLength++;\n                  oldValue[key] = newItem;\n                  changeDetected++;\n                }\n              }\n            }\n            if (oldLength > newLength) {\n              // we used to have more keys, need to find them and destroy them.\n              changeDetected++;\n              for (key in oldValue) {\n                if (!newValue.hasOwnProperty(key)) {\n                  oldLength--;\n                  delete oldValue[key];\n                }\n              }\n            }\n          }\n          return changeDetected;\n        }\n\n        function $watchCollectionAction() {\n          if (initRun) {\n            initRun = false;\n            listener(newValue, newValue, self);\n          } else {\n            listener(newValue, veryOldValue, self);\n          }\n\n          // make a copy for the next time a collection is changed\n          if (trackVeryOldValue) {\n            if (!isObject(newValue)) {\n              //primitive\n              veryOldValue = newValue;\n            } else if (isArrayLike(newValue)) {\n              veryOldValue = new Array(newValue.length);\n              for (var i = 0; i < newValue.length; i++) {\n                veryOldValue[i] = newValue[i];\n              }\n            } else { // if object\n              veryOldValue = {};\n              for (var key in newValue) {\n                if (hasOwnProperty.call(newValue, key)) {\n                  veryOldValue[key] = newValue[key];\n                }\n              }\n            }\n          }\n        }\n\n        return this.$watch(changeDetector, $watchCollectionAction);\n      },\n\n      /**\n       * @ngdoc method\n       * @name $rootScope.Scope#$digest\n       * @kind function\n       *\n       * @description\n       * Processes all of the {@link ng.$rootScope.Scope#$watch watchers} of the current scope and\n       * its children. Because a {@link ng.$rootScope.Scope#$watch watcher}'s listener can change\n       * the model, the `$digest()` keeps calling the {@link ng.$rootScope.Scope#$watch watchers}\n       * until no more listeners are firing. This means that it is possible to get into an infinite\n       * loop. This function will throw `'Maximum iteration limit exceeded.'` if the number of\n       * iterations exceeds 10.\n       *\n       * Usually, you don't call `$digest()` directly in\n       * {@link ng.directive:ngController controllers} or in\n       * {@link ng.$compileProvider#directive directives}.\n       * Instead, you should call {@link ng.$rootScope.Scope#$apply $apply()} (typically from within\n       * a {@link ng.$compileProvider#directive directive}), which will force a `$digest()`.\n       *\n       * If you want to be notified whenever `$digest()` is called,\n       * you can register a `watchExpression` function with\n       * {@link ng.$rootScope.Scope#$watch $watch()} with no `listener`.\n       *\n       * In unit tests, you may need to call `$digest()` to simulate the scope life cycle.\n       *\n       * # Example\n       * ```js\n           var scope = ...;\n           scope.name = 'misko';\n           scope.counter = 0;\n\n           expect(scope.counter).toEqual(0);\n           scope.$watch('name', function(newValue, oldValue) {\n             scope.counter = scope.counter + 1;\n           });\n           expect(scope.counter).toEqual(0);\n\n           scope.$digest();\n           // the listener is always called during the first $digest loop after it was registered\n           expect(scope.counter).toEqual(1);\n\n           scope.$digest();\n           // but now it will not be called unless the value changes\n           expect(scope.counter).toEqual(1);\n\n           scope.name = 'adam';\n           scope.$digest();\n           expect(scope.counter).toEqual(2);\n       * ```\n       *\n       */\n      $digest: function() {\n        var watch, value, last,\n            watchers,\n            length,\n            dirty, ttl = TTL,\n            next, current, target = this,\n            watchLog = [],\n            logIdx, logMsg, asyncTask;\n\n        beginPhase('$digest');\n        // Check for changes to browser url that happened in sync before the call to $digest\n        $browser.$$checkUrlChange();\n\n        if (this === $rootScope && applyAsyncId !== null) {\n          // If this is the root scope, and $applyAsync has scheduled a deferred $apply(), then\n          // cancel the scheduled $apply and flush the queue of expressions to be evaluated.\n          $browser.defer.cancel(applyAsyncId);\n          flushApplyAsync();\n        }\n\n        lastDirtyWatch = null;\n\n        do { // \"while dirty\" loop\n          dirty = false;\n          current = target;\n\n          while (asyncQueue.length) {\n            try {\n              asyncTask = asyncQueue.shift();\n              asyncTask.scope.$eval(asyncTask.expression, asyncTask.locals);\n            } catch (e) {\n              $exceptionHandler(e);\n            }\n            lastDirtyWatch = null;\n          }\n\n          traverseScopesLoop:\n          do { // \"traverse the scopes\" loop\n            if ((watchers = current.$$watchers)) {\n              // process our watches\n              length = watchers.length;\n              while (length--) {\n                try {\n                  watch = watchers[length];\n                  // Most common watches are on primitives, in which case we can short\n                  // circuit it with === operator, only when === fails do we use .equals\n                  if (watch) {\n                    if ((value = watch.get(current)) !== (last = watch.last) &&\n                        !(watch.eq\n                            ? equals(value, last)\n                            : (typeof value === 'number' && typeof last === 'number'\n                               && isNaN(value) && isNaN(last)))) {\n                      dirty = true;\n                      lastDirtyWatch = watch;\n                      watch.last = watch.eq ? copy(value, null) : value;\n                      watch.fn(value, ((last === initWatchVal) ? value : last), current);\n                      if (ttl < 5) {\n                        logIdx = 4 - ttl;\n                        if (!watchLog[logIdx]) watchLog[logIdx] = [];\n                        watchLog[logIdx].push({\n                          msg: isFunction(watch.exp) ? 'fn: ' + (watch.exp.name || watch.exp.toString()) : watch.exp,\n                          newVal: value,\n                          oldVal: last\n                        });\n                      }\n                    } else if (watch === lastDirtyWatch) {\n                      // If the most recently dirty watcher is now clean, short circuit since the remaining watchers\n                      // have already been tested.\n                      dirty = false;\n                      break traverseScopesLoop;\n                    }\n                  }\n                } catch (e) {\n                  $exceptionHandler(e);\n                }\n              }\n            }\n\n            // Insanity Warning: scope depth-first traversal\n            // yes, this code is a bit crazy, but it works and we have tests to prove it!\n            // this piece should be kept in sync with the traversal in $broadcast\n            if (!(next = (current.$$childHead ||\n                (current !== target && current.$$nextSibling)))) {\n              while (current !== target && !(next = current.$$nextSibling)) {\n                current = current.$parent;\n              }\n            }\n          } while ((current = next));\n\n          // `break traverseScopesLoop;` takes us to here\n\n          if ((dirty || asyncQueue.length) && !(ttl--)) {\n            clearPhase();\n            throw $rootScopeMinErr('infdig',\n                '{0} $digest() iterations reached. Aborting!\\n' +\n                'Watchers fired in the last 5 iterations: {1}',\n                TTL, watchLog);\n          }\n\n        } while (dirty || asyncQueue.length);\n\n        clearPhase();\n\n        while (postDigestQueue.length) {\n          try {\n            postDigestQueue.shift()();\n          } catch (e) {\n            $exceptionHandler(e);\n          }\n        }\n      },\n\n\n      /**\n       * @ngdoc event\n       * @name $rootScope.Scope#$destroy\n       * @eventType broadcast on scope being destroyed\n       *\n       * @description\n       * Broadcasted when a scope and its children are being destroyed.\n       *\n       * Note that, in AngularJS, there is also a `$destroy` jQuery event, which can be used to\n       * clean up DOM bindings before an element is removed from the DOM.\n       */\n\n      /**\n       * @ngdoc method\n       * @name $rootScope.Scope#$destroy\n       * @kind function\n       *\n       * @description\n       * Removes the current scope (and all of its children) from the parent scope. Removal implies\n       * that calls to {@link ng.$rootScope.Scope#$digest $digest()} will no longer\n       * propagate to the current scope and its children. Removal also implies that the current\n       * scope is eligible for garbage collection.\n       *\n       * The `$destroy()` is usually used by directives such as\n       * {@link ng.directive:ngRepeat ngRepeat} for managing the\n       * unrolling of the loop.\n       *\n       * Just before a scope is destroyed, a `$destroy` event is broadcasted on this scope.\n       * Application code can register a `$destroy` event handler that will give it a chance to\n       * perform any necessary cleanup.\n       *\n       * Note that, in AngularJS, there is also a `$destroy` jQuery event, which can be used to\n       * clean up DOM bindings before an element is removed from the DOM.\n       */\n      $destroy: function() {\n        // we can't destroy the root scope or a scope that has been already destroyed\n        if (this.$$destroyed) return;\n        var parent = this.$parent;\n\n        this.$broadcast('$destroy');\n        this.$$destroyed = true;\n        if (this === $rootScope) return;\n\n        for (var eventName in this.$$listenerCount) {\n          decrementListenerCount(this, this.$$listenerCount[eventName], eventName);\n        }\n\n        // sever all the references to parent scopes (after this cleanup, the current scope should\n        // not be retained by any of our references and should be eligible for garbage collection)\n        if (parent.$$childHead == this) parent.$$childHead = this.$$nextSibling;\n        if (parent.$$childTail == this) parent.$$childTail = this.$$prevSibling;\n        if (this.$$prevSibling) this.$$prevSibling.$$nextSibling = this.$$nextSibling;\n        if (this.$$nextSibling) this.$$nextSibling.$$prevSibling = this.$$prevSibling;\n\n        // Disable listeners, watchers and apply/digest methods\n        this.$destroy = this.$digest = this.$apply = this.$evalAsync = this.$applyAsync = noop;\n        this.$on = this.$watch = this.$watchGroup = function() { return noop; };\n        this.$$listeners = {};\n\n        // All of the code below is bogus code that works around V8's memory leak via optimized code\n        // and inline caches.\n        //\n        // see:\n        // - https://code.google.com/p/v8/issues/detail?id=2073#c26\n        // - https://github.com/angular/angular.js/issues/6794#issuecomment-38648909\n        // - https://github.com/angular/angular.js/issues/1313#issuecomment-10378451\n\n        this.$parent = this.$$nextSibling = this.$$prevSibling = this.$$childHead =\n            this.$$childTail = this.$root = this.$$watchers = null;\n      },\n\n      /**\n       * @ngdoc method\n       * @name $rootScope.Scope#$eval\n       * @kind function\n       *\n       * @description\n       * Executes the `expression` on the current scope and returns the result. Any exceptions in\n       * the expression are propagated (uncaught). This is useful when evaluating Angular\n       * expressions.\n       *\n       * # Example\n       * ```js\n           var scope = ng.$rootScope.Scope();\n           scope.a = 1;\n           scope.b = 2;\n\n           expect(scope.$eval('a+b')).toEqual(3);\n           expect(scope.$eval(function(scope){ return scope.a + scope.b; })).toEqual(3);\n       * ```\n       *\n       * @param {(string|function())=} expression An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in  {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with the current `scope` parameter.\n       *\n       * @param {(object)=} locals Local variables object, useful for overriding values in scope.\n       * @returns {*} The result of evaluating the expression.\n       */\n      $eval: function(expr, locals) {\n        return $parse(expr)(this, locals);\n      },\n\n      /**\n       * @ngdoc method\n       * @name $rootScope.Scope#$evalAsync\n       * @kind function\n       *\n       * @description\n       * Executes the expression on the current scope at a later point in time.\n       *\n       * The `$evalAsync` makes no guarantees as to when the `expression` will be executed, only\n       * that:\n       *\n       *   - it will execute after the function that scheduled the evaluation (preferably before DOM\n       *     rendering).\n       *   - at least one {@link ng.$rootScope.Scope#$digest $digest cycle} will be performed after\n       *     `expression` execution.\n       *\n       * Any exceptions from the execution of the expression are forwarded to the\n       * {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * __Note:__ if this function is called outside of a `$digest` cycle, a new `$digest` cycle\n       * will be scheduled. However, it is encouraged to always call code that changes the model\n       * from within an `$apply` call. That includes code evaluated via `$evalAsync`.\n       *\n       * @param {(string|function())=} expression An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with the current `scope` parameter.\n       *\n       * @param {(object)=} locals Local variables object, useful for overriding values in scope.\n       */\n      $evalAsync: function(expr, locals) {\n        // if we are outside of an $digest loop and this is the first time we are scheduling async\n        // task also schedule async auto-flush\n        if (!$rootScope.$$phase && !asyncQueue.length) {\n          $browser.defer(function() {\n            if (asyncQueue.length) {\n              $rootScope.$digest();\n            }\n          });\n        }\n\n        asyncQueue.push({scope: this, expression: expr, locals: locals});\n      },\n\n      $$postDigest: function(fn) {\n        postDigestQueue.push(fn);\n      },\n\n      /**\n       * @ngdoc method\n       * @name $rootScope.Scope#$apply\n       * @kind function\n       *\n       * @description\n       * `$apply()` is used to execute an expression in angular from outside of the angular\n       * framework. (For example from browser DOM events, setTimeout, XHR or third party libraries).\n       * Because we are calling into the angular framework we need to perform proper scope life\n       * cycle of {@link ng.$exceptionHandler exception handling},\n       * {@link ng.$rootScope.Scope#$digest executing watches}.\n       *\n       * ## Life cycle\n       *\n       * # Pseudo-Code of `$apply()`\n       * ```js\n           function $apply(expr) {\n             try {\n               return $eval(expr);\n             } catch (e) {\n               $exceptionHandler(e);\n             } finally {\n               $root.$digest();\n             }\n           }\n       * ```\n       *\n       *\n       * Scope's `$apply()` method transitions through the following stages:\n       *\n       * 1. The {@link guide/expression expression} is executed using the\n       *    {@link ng.$rootScope.Scope#$eval $eval()} method.\n       * 2. Any exceptions from the execution of the expression are forwarded to the\n       *    {@link ng.$exceptionHandler $exceptionHandler} service.\n       * 3. The {@link ng.$rootScope.Scope#$watch watch} listeners are fired immediately after the\n       *    expression was executed using the {@link ng.$rootScope.Scope#$digest $digest()} method.\n       *\n       *\n       * @param {(string|function())=} exp An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with current `scope` parameter.\n       *\n       * @returns {*} The result of evaluating the expression.\n       */\n      $apply: function(expr) {\n        try {\n          beginPhase('$apply');\n          return this.$eval(expr);\n        } catch (e) {\n          $exceptionHandler(e);\n        } finally {\n          clearPhase();\n          try {\n            $rootScope.$digest();\n          } catch (e) {\n            $exceptionHandler(e);\n            throw e;\n          }\n        }\n      },\n\n      /**\n       * @ngdoc method\n       * @name $rootScope.Scope#$applyAsync\n       * @kind function\n       *\n       * @description\n       * Schedule the invocation of $apply to occur at a later time. The actual time difference\n       * varies across browsers, but is typically around ~10 milliseconds.\n       *\n       * This can be used to queue up multiple expressions which need to be evaluated in the same\n       * digest.\n       *\n       * @param {(string|function())=} exp An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with current `scope` parameter.\n       */\n      $applyAsync: function(expr) {\n        var scope = this;\n        expr && applyAsyncQueue.push($applyAsyncExpression);\n        scheduleApplyAsync();\n\n        function $applyAsyncExpression() {\n          scope.$eval(expr);\n        }\n      },\n\n      /**\n       * @ngdoc method\n       * @name $rootScope.Scope#$on\n       * @kind function\n       *\n       * @description\n       * Listens on events of a given type. See {@link ng.$rootScope.Scope#$emit $emit} for\n       * discussion of event life cycle.\n       *\n       * The event listener function format is: `function(event, args...)`. The `event` object\n       * passed into the listener has the following attributes:\n       *\n       *   - `targetScope` - `{Scope}`: the scope on which the event was `$emit`-ed or\n       *     `$broadcast`-ed.\n       *   - `currentScope` - `{Scope}`: the scope that is currently handling the event. Once the\n       *     event propagates through the scope hierarchy, this property is set to null.\n       *   - `name` - `{string}`: name of the event.\n       *   - `stopPropagation` - `{function=}`: calling `stopPropagation` function will cancel\n       *     further event propagation (available only for events that were `$emit`-ed).\n       *   - `preventDefault` - `{function}`: calling `preventDefault` sets `defaultPrevented` flag\n       *     to true.\n       *   - `defaultPrevented` - `{boolean}`: true if `preventDefault` was called.\n       *\n       * @param {string} name Event name to listen on.\n       * @param {function(event, ...args)} listener Function to call when the event is emitted.\n       * @returns {function()} Returns a deregistration function for this listener.\n       */\n      $on: function(name, listener) {\n        var namedListeners = this.$$listeners[name];\n        if (!namedListeners) {\n          this.$$listeners[name] = namedListeners = [];\n        }\n        namedListeners.push(listener);\n\n        var current = this;\n        do {\n          if (!current.$$listenerCount[name]) {\n            current.$$listenerCount[name] = 0;\n          }\n          current.$$listenerCount[name]++;\n        } while ((current = current.$parent));\n\n        var self = this;\n        return function() {\n          var indexOfListener = namedListeners.indexOf(listener);\n          if (indexOfListener !== -1) {\n            namedListeners[indexOfListener] = null;\n            decrementListenerCount(self, 1, name);\n          }\n        };\n      },\n\n\n      /**\n       * @ngdoc method\n       * @name $rootScope.Scope#$emit\n       * @kind function\n       *\n       * @description\n       * Dispatches an event `name` upwards through the scope hierarchy notifying the\n       * registered {@link ng.$rootScope.Scope#$on} listeners.\n       *\n       * The event life cycle starts at the scope on which `$emit` was called. All\n       * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get\n       * notified. Afterwards, the event traverses upwards toward the root scope and calls all\n       * registered listeners along the way. The event will stop propagating if one of the listeners\n       * cancels it.\n       *\n       * Any exception emitted from the {@link ng.$rootScope.Scope#$on listeners} will be passed\n       * onto the {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {string} name Event name to emit.\n       * @param {...*} args Optional one or more arguments which will be passed onto the event listeners.\n       * @return {Object} Event object (see {@link ng.$rootScope.Scope#$on}).\n       */\n      $emit: function(name, args) {\n        var empty = [],\n            namedListeners,\n            scope = this,\n            stopPropagation = false,\n            event = {\n              name: name,\n              targetScope: scope,\n              stopPropagation: function() {stopPropagation = true;},\n              preventDefault: function() {\n                event.defaultPrevented = true;\n              },\n              defaultPrevented: false\n            },\n            listenerArgs = concat([event], arguments, 1),\n            i, length;\n\n        do {\n          namedListeners = scope.$$listeners[name] || empty;\n          event.currentScope = scope;\n          for (i = 0, length = namedListeners.length; i < length; i++) {\n\n            // if listeners were deregistered, defragment the array\n            if (!namedListeners[i]) {\n              namedListeners.splice(i, 1);\n              i--;\n              length--;\n              continue;\n            }\n            try {\n              //allow all listeners attached to the current scope to run\n              namedListeners[i].apply(null, listenerArgs);\n            } catch (e) {\n              $exceptionHandler(e);\n            }\n          }\n          //if any listener on the current scope stops propagation, prevent bubbling\n          if (stopPropagation) {\n            event.currentScope = null;\n            return event;\n          }\n          //traverse upwards\n          scope = scope.$parent;\n        } while (scope);\n\n        event.currentScope = null;\n\n        return event;\n      },\n\n\n      /**\n       * @ngdoc method\n       * @name $rootScope.Scope#$broadcast\n       * @kind function\n       *\n       * @description\n       * Dispatches an event `name` downwards to all child scopes (and their children) notifying the\n       * registered {@link ng.$rootScope.Scope#$on} listeners.\n       *\n       * The event life cycle starts at the scope on which `$broadcast` was called. All\n       * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get\n       * notified. Afterwards, the event propagates to all direct and indirect scopes of the current\n       * scope and calls all registered listeners along the way. The event cannot be canceled.\n       *\n       * Any exception emitted from the {@link ng.$rootScope.Scope#$on listeners} will be passed\n       * onto the {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {string} name Event name to broadcast.\n       * @param {...*} args Optional one or more arguments which will be passed onto the event listeners.\n       * @return {Object} Event object, see {@link ng.$rootScope.Scope#$on}\n       */\n      $broadcast: function(name, args) {\n        var target = this,\n            current = target,\n            next = target,\n            event = {\n              name: name,\n              targetScope: target,\n              preventDefault: function() {\n                event.defaultPrevented = true;\n              },\n              defaultPrevented: false\n            };\n\n        if (!target.$$listenerCount[name]) return event;\n\n        var listenerArgs = concat([event], arguments, 1),\n            listeners, i, length;\n\n        //down while you can, then up and next sibling or up and next sibling until back at root\n        while ((current = next)) {\n          event.currentScope = current;\n          listeners = current.$$listeners[name] || [];\n          for (i = 0, length = listeners.length; i < length; i++) {\n            // if listeners were deregistered, defragment the array\n            if (!listeners[i]) {\n              listeners.splice(i, 1);\n              i--;\n              length--;\n              continue;\n            }\n\n            try {\n              listeners[i].apply(null, listenerArgs);\n            } catch (e) {\n              $exceptionHandler(e);\n            }\n          }\n\n          // Insanity Warning: scope depth-first traversal\n          // yes, this code is a bit crazy, but it works and we have tests to prove it!\n          // this piece should be kept in sync with the traversal in $digest\n          // (though it differs due to having the extra check for $$listenerCount)\n          if (!(next = ((current.$$listenerCount[name] && current.$$childHead) ||\n              (current !== target && current.$$nextSibling)))) {\n            while (current !== target && !(next = current.$$nextSibling)) {\n              current = current.$parent;\n            }\n          }\n        }\n\n        event.currentScope = null;\n        return event;\n      }\n    };\n\n    var $rootScope = new Scope();\n\n    //The internal queues. Expose them on the $rootScope for debugging/testing purposes.\n    var asyncQueue = $rootScope.$$asyncQueue = [];\n    var postDigestQueue = $rootScope.$$postDigestQueue = [];\n    var applyAsyncQueue = $rootScope.$$applyAsyncQueue = [];\n\n    return $rootScope;\n\n\n    function beginPhase(phase) {\n      if ($rootScope.$$phase) {\n        throw $rootScopeMinErr('inprog', '{0} already in progress', $rootScope.$$phase);\n      }\n\n      $rootScope.$$phase = phase;\n    }\n\n    function clearPhase() {\n      $rootScope.$$phase = null;\n    }\n\n\n    function decrementListenerCount(current, count, name) {\n      do {\n        current.$$listenerCount[name] -= count;\n\n        if (current.$$listenerCount[name] === 0) {\n          delete current.$$listenerCount[name];\n        }\n      } while ((current = current.$parent));\n    }\n\n    /**\n     * function used as an initial value for watchers.\n     * because it's unique we can easily tell it apart from other values\n     */\n    function initWatchVal() {}\n\n    function flushApplyAsync() {\n      while (applyAsyncQueue.length) {\n        try {\n          applyAsyncQueue.shift()();\n        } catch (e) {\n          $exceptionHandler(e);\n        }\n      }\n      applyAsyncId = null;\n    }\n\n    function scheduleApplyAsync() {\n      if (applyAsyncId === null) {\n        applyAsyncId = $browser.defer(function() {\n          $rootScope.$apply(flushApplyAsync);\n        });\n      }\n    }\n  }];\n}\n\n/**\n * @description\n * Private service to sanitize uris for links and images. Used by $compile and $sanitize.\n */\nfunction $$SanitizeUriProvider() {\n  var aHrefSanitizationWhitelist = /^\\s*(https?|ftp|mailto|tel|file):/,\n    imgSrcSanitizationWhitelist = /^\\s*((https?|ftp|file|blob):|data:image\\/)/;\n\n  /**\n   * @description\n   * Retrieves or overrides the default regular expression that is used for whitelisting of safe\n   * urls during a[href] sanitization.\n   *\n   * The sanitization is a security measure aimed at prevent XSS attacks via html links.\n   *\n   * Any url about to be assigned to a[href] via data-binding is first normalized and turned into\n   * an absolute url. Afterwards, the url is matched against the `aHrefSanitizationWhitelist`\n   * regular expression. If a match is found, the original url is written into the dom. Otherwise,\n   * the absolute url is prefixed with `'unsafe:'` string and only then is it written into the DOM.\n   *\n   * @param {RegExp=} regexp New regexp to whitelist urls with.\n   * @returns {RegExp|ng.$compileProvider} Current RegExp if called without value or self for\n   *    chaining otherwise.\n   */\n  this.aHrefSanitizationWhitelist = function(regexp) {\n    if (isDefined(regexp)) {\n      aHrefSanitizationWhitelist = regexp;\n      return this;\n    }\n    return aHrefSanitizationWhitelist;\n  };\n\n\n  /**\n   * @description\n   * Retrieves or overrides the default regular expression that is used for whitelisting of safe\n   * urls during img[src] sanitization.\n   *\n   * The sanitization is a security measure aimed at prevent XSS attacks via html links.\n   *\n   * Any url about to be assigned to img[src] via data-binding is first normalized and turned into\n   * an absolute url. Afterwards, the url is matched against the `imgSrcSanitizationWhitelist`\n   * regular expression. If a match is found, the original url is written into the dom. Otherwise,\n   * the absolute url is prefixed with `'unsafe:'` string and only then is it written into the DOM.\n   *\n   * @param {RegExp=} regexp New regexp to whitelist urls with.\n   * @returns {RegExp|ng.$compileProvider} Current RegExp if called without value or self for\n   *    chaining otherwise.\n   */\n  this.imgSrcSanitizationWhitelist = function(regexp) {\n    if (isDefined(regexp)) {\n      imgSrcSanitizationWhitelist = regexp;\n      return this;\n    }\n    return imgSrcSanitizationWhitelist;\n  };\n\n  this.$get = function() {\n    return function sanitizeUri(uri, isImage) {\n      var regex = isImage ? imgSrcSanitizationWhitelist : aHrefSanitizationWhitelist;\n      var normalizedVal;\n      normalizedVal = urlResolve(uri).href;\n      if (normalizedVal !== '' && !normalizedVal.match(regex)) {\n        return 'unsafe:' + normalizedVal;\n      }\n      return uri;\n    };\n  };\n}\n\nvar $sceMinErr = minErr('$sce');\n\nvar SCE_CONTEXTS = {\n  HTML: 'html',\n  CSS: 'css',\n  URL: 'url',\n  // RESOURCE_URL is a subtype of URL used in contexts where a privileged resource is sourced from a\n  // url.  (e.g. ng-include, script src, templateUrl)\n  RESOURCE_URL: 'resourceUrl',\n  JS: 'js'\n};\n\n// Helper functions follow.\n\nfunction adjustMatcher(matcher) {\n  if (matcher === 'self') {\n    return matcher;\n  } else if (isString(matcher)) {\n    // Strings match exactly except for 2 wildcards - '*' and '**'.\n    // '*' matches any character except those from the set ':/.?&'.\n    // '**' matches any character (like .* in a RegExp).\n    // More than 2 *'s raises an error as it's ill defined.\n    if (matcher.indexOf('***') > -1) {\n      throw $sceMinErr('iwcard',\n          'Illegal sequence *** in string matcher.  String: {0}', matcher);\n    }\n    matcher = escapeForRegexp(matcher).\n                  replace('\\\\*\\\\*', '.*').\n                  replace('\\\\*', '[^:/.?&;]*');\n    return new RegExp('^' + matcher + '$');\n  } else if (isRegExp(matcher)) {\n    // The only other type of matcher allowed is a Regexp.\n    // Match entire URL / disallow partial matches.\n    // Flags are reset (i.e. no global, ignoreCase or multiline)\n    return new RegExp('^' + matcher.source + '$');\n  } else {\n    throw $sceMinErr('imatcher',\n        'Matchers may only be \"self\", string patterns or RegExp objects');\n  }\n}\n\n\nfunction adjustMatchers(matchers) {\n  var adjustedMatchers = [];\n  if (isDefined(matchers)) {\n    forEach(matchers, function(matcher) {\n      adjustedMatchers.push(adjustMatcher(matcher));\n    });\n  }\n  return adjustedMatchers;\n}\n\n\n/**\n * @ngdoc service\n * @name $sceDelegate\n * @kind function\n *\n * @description\n *\n * `$sceDelegate` is a service that is used by the `$sce` service to provide {@link ng.$sce Strict\n * Contextual Escaping (SCE)} services to AngularJS.\n *\n * Typically, you would configure or override the {@link ng.$sceDelegate $sceDelegate} instead of\n * the `$sce` service to customize the way Strict Contextual Escaping works in AngularJS.  This is\n * because, while the `$sce` provides numerous shorthand methods, etc., you really only need to\n * override 3 core functions (`trustAs`, `getTrusted` and `valueOf`) to replace the way things\n * work because `$sce` delegates to `$sceDelegate` for these operations.\n *\n * Refer {@link ng.$sceDelegateProvider $sceDelegateProvider} to configure this service.\n *\n * The default instance of `$sceDelegate` should work out of the box with little pain.  While you\n * can override it completely to change the behavior of `$sce`, the common case would\n * involve configuring the {@link ng.$sceDelegateProvider $sceDelegateProvider} instead by setting\n * your own whitelists and blacklists for trusting URLs used for loading AngularJS resources such as\n * templates.  Refer {@link ng.$sceDelegateProvider#resourceUrlWhitelist\n * $sceDelegateProvider.resourceUrlWhitelist} and {@link\n * ng.$sceDelegateProvider#resourceUrlBlacklist $sceDelegateProvider.resourceUrlBlacklist}\n */\n\n/**\n * @ngdoc provider\n * @name $sceDelegateProvider\n * @description\n *\n * The `$sceDelegateProvider` provider allows developers to configure the {@link ng.$sceDelegate\n * $sceDelegate} service.  This allows one to get/set the whitelists and blacklists used to ensure\n * that the URLs used for sourcing Angular templates are safe.  Refer {@link\n * ng.$sceDelegateProvider#resourceUrlWhitelist $sceDelegateProvider.resourceUrlWhitelist} and\n * {@link ng.$sceDelegateProvider#resourceUrlBlacklist $sceDelegateProvider.resourceUrlBlacklist}\n *\n * For the general details about this service in Angular, read the main page for {@link ng.$sce\n * Strict Contextual Escaping (SCE)}.\n *\n * **Example**:  Consider the following case. <a name=\"example\"></a>\n *\n * - your app is hosted at url `http://myapp.example.com/`\n * - but some of your templates are hosted on other domains you control such as\n *   `http://srv01.assets.example.com/`,  `http://srv02.assets.example.com/`, etc.\n * - and you have an open redirect at `http://myapp.example.com/clickThru?...`.\n *\n * Here is what a secure configuration for this scenario might look like:\n *\n * ```\n *  angular.module('myApp', []).config(function($sceDelegateProvider) {\n *    $sceDelegateProvider.resourceUrlWhitelist([\n *      // Allow same origin resource loads.\n *      'self',\n *      // Allow loading from our assets domain.  Notice the difference between * and **.\n *      'http://srv*.assets.example.com/**'\n *    ]);\n *\n *    // The blacklist overrides the whitelist so the open redirect here is blocked.\n *    $sceDelegateProvider.resourceUrlBlacklist([\n *      'http://myapp.example.com/clickThru**'\n *    ]);\n *  });\n * ```\n */\n\nfunction $SceDelegateProvider() {\n  this.SCE_CONTEXTS = SCE_CONTEXTS;\n\n  // Resource URLs can also be trusted by policy.\n  var resourceUrlWhitelist = ['self'],\n      resourceUrlBlacklist = [];\n\n  /**\n   * @ngdoc method\n   * @name $sceDelegateProvider#resourceUrlWhitelist\n   * @kind function\n   *\n   * @param {Array=} whitelist When provided, replaces the resourceUrlWhitelist with the value\n   *     provided.  This must be an array or null.  A snapshot of this array is used so further\n   *     changes to the array are ignored.\n   *\n   *     Follow {@link ng.$sce#resourceUrlPatternItem this link} for a description of the items\n   *     allowed in this array.\n   *\n   *     Note: **an empty whitelist array will block all URLs**!\n   *\n   * @return {Array} the currently set whitelist array.\n   *\n   * The **default value** when no whitelist has been explicitly set is `['self']` allowing only\n   * same origin resource requests.\n   *\n   * @description\n   * Sets/Gets the whitelist of trusted resource URLs.\n   */\n  this.resourceUrlWhitelist = function(value) {\n    if (arguments.length) {\n      resourceUrlWhitelist = adjustMatchers(value);\n    }\n    return resourceUrlWhitelist;\n  };\n\n  /**\n   * @ngdoc method\n   * @name $sceDelegateProvider#resourceUrlBlacklist\n   * @kind function\n   *\n   * @param {Array=} blacklist When provided, replaces the resourceUrlBlacklist with the value\n   *     provided.  This must be an array or null.  A snapshot of this array is used so further\n   *     changes to the array are ignored.\n   *\n   *     Follow {@link ng.$sce#resourceUrlPatternItem this link} for a description of the items\n   *     allowed in this array.\n   *\n   *     The typical usage for the blacklist is to **block\n   *     [open redirects](http://cwe.mitre.org/data/definitions/601.html)** served by your domain as\n   *     these would otherwise be trusted but actually return content from the redirected domain.\n   *\n   *     Finally, **the blacklist overrides the whitelist** and has the final say.\n   *\n   * @return {Array} the currently set blacklist array.\n   *\n   * The **default value** when no whitelist has been explicitly set is the empty array (i.e. there\n   * is no blacklist.)\n   *\n   * @description\n   * Sets/Gets the blacklist of trusted resource URLs.\n   */\n\n  this.resourceUrlBlacklist = function(value) {\n    if (arguments.length) {\n      resourceUrlBlacklist = adjustMatchers(value);\n    }\n    return resourceUrlBlacklist;\n  };\n\n  this.$get = ['$injector', function($injector) {\n\n    var htmlSanitizer = function htmlSanitizer(html) {\n      throw $sceMinErr('unsafe', 'Attempting to use an unsafe value in a safe context.');\n    };\n\n    if ($injector.has('$sanitize')) {\n      htmlSanitizer = $injector.get('$sanitize');\n    }\n\n\n    function matchUrl(matcher, parsedUrl) {\n      if (matcher === 'self') {\n        return urlIsSameOrigin(parsedUrl);\n      } else {\n        // definitely a regex.  See adjustMatchers()\n        return !!matcher.exec(parsedUrl.href);\n      }\n    }\n\n    function isResourceUrlAllowedByPolicy(url) {\n      var parsedUrl = urlResolve(url.toString());\n      var i, n, allowed = false;\n      // Ensure that at least one item from the whitelist allows this url.\n      for (i = 0, n = resourceUrlWhitelist.length; i < n; i++) {\n        if (matchUrl(resourceUrlWhitelist[i], parsedUrl)) {\n          allowed = true;\n          break;\n        }\n      }\n      if (allowed) {\n        // Ensure that no item from the blacklist blocked this url.\n        for (i = 0, n = resourceUrlBlacklist.length; i < n; i++) {\n          if (matchUrl(resourceUrlBlacklist[i], parsedUrl)) {\n            allowed = false;\n            break;\n          }\n        }\n      }\n      return allowed;\n    }\n\n    function generateHolderType(Base) {\n      var holderType = function TrustedValueHolderType(trustedValue) {\n        this.$$unwrapTrustedValue = function() {\n          return trustedValue;\n        };\n      };\n      if (Base) {\n        holderType.prototype = new Base();\n      }\n      holderType.prototype.valueOf = function sceValueOf() {\n        return this.$$unwrapTrustedValue();\n      };\n      holderType.prototype.toString = function sceToString() {\n        return this.$$unwrapTrustedValue().toString();\n      };\n      return holderType;\n    }\n\n    var trustedValueHolderBase = generateHolderType(),\n        byType = {};\n\n    byType[SCE_CONTEXTS.HTML] = generateHolderType(trustedValueHolderBase);\n    byType[SCE_CONTEXTS.CSS] = generateHolderType(trustedValueHolderBase);\n    byType[SCE_CONTEXTS.URL] = generateHolderType(trustedValueHolderBase);\n    byType[SCE_CONTEXTS.JS] = generateHolderType(trustedValueHolderBase);\n    byType[SCE_CONTEXTS.RESOURCE_URL] = generateHolderType(byType[SCE_CONTEXTS.URL]);\n\n    /**\n     * @ngdoc method\n     * @name $sceDelegate#trustAs\n     *\n     * @description\n     * Returns an object that is trusted by angular for use in specified strict\n     * contextual escaping contexts (such as ng-bind-html, ng-include, any src\n     * attribute interpolation, any dom event binding attribute interpolation\n     * such as for onclick,  etc.) that uses the provided value.\n     * See {@link ng.$sce $sce} for enabling strict contextual escaping.\n     *\n     * @param {string} type The kind of context in which this value is safe for use.  e.g. url,\n     *   resourceUrl, html, js and css.\n     * @param {*} value The value that that should be considered trusted/safe.\n     * @returns {*} A value that can be used to stand in for the provided `value` in places\n     * where Angular expects a $sce.trustAs() return value.\n     */\n    function trustAs(type, trustedValue) {\n      var Constructor = (byType.hasOwnProperty(type) ? byType[type] : null);\n      if (!Constructor) {\n        throw $sceMinErr('icontext',\n            'Attempted to trust a value in invalid context. Context: {0}; Value: {1}',\n            type, trustedValue);\n      }\n      if (trustedValue === null || trustedValue === undefined || trustedValue === '') {\n        return trustedValue;\n      }\n      // All the current contexts in SCE_CONTEXTS happen to be strings.  In order to avoid trusting\n      // mutable objects, we ensure here that the value passed in is actually a string.\n      if (typeof trustedValue !== 'string') {\n        throw $sceMinErr('itype',\n            'Attempted to trust a non-string value in a content requiring a string: Context: {0}',\n            type);\n      }\n      return new Constructor(trustedValue);\n    }\n\n    /**\n     * @ngdoc method\n     * @name $sceDelegate#valueOf\n     *\n     * @description\n     * If the passed parameter had been returned by a prior call to {@link ng.$sceDelegate#trustAs\n     * `$sceDelegate.trustAs`}, returns the value that had been passed to {@link\n     * ng.$sceDelegate#trustAs `$sceDelegate.trustAs`}.\n     *\n     * If the passed parameter is not a value that had been returned by {@link\n     * ng.$sceDelegate#trustAs `$sceDelegate.trustAs`}, returns it as-is.\n     *\n     * @param {*} value The result of a prior {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs`}\n     *      call or anything else.\n     * @returns {*} The `value` that was originally provided to {@link ng.$sceDelegate#trustAs\n     *     `$sceDelegate.trustAs`} if `value` is the result of such a call.  Otherwise, returns\n     *     `value` unchanged.\n     */\n    function valueOf(maybeTrusted) {\n      if (maybeTrusted instanceof trustedValueHolderBase) {\n        return maybeTrusted.$$unwrapTrustedValue();\n      } else {\n        return maybeTrusted;\n      }\n    }\n\n    /**\n     * @ngdoc method\n     * @name $sceDelegate#getTrusted\n     *\n     * @description\n     * Takes the result of a {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs`} call and\n     * returns the originally supplied value if the queried context type is a supertype of the\n     * created type.  If this condition isn't satisfied, throws an exception.\n     *\n     * @param {string} type The kind of context in which this value is to be used.\n     * @param {*} maybeTrusted The result of a prior {@link ng.$sceDelegate#trustAs\n     *     `$sceDelegate.trustAs`} call.\n     * @returns {*} The value the was originally provided to {@link ng.$sceDelegate#trustAs\n     *     `$sceDelegate.trustAs`} if valid in this context.  Otherwise, throws an exception.\n     */\n    function getTrusted(type, maybeTrusted) {\n      if (maybeTrusted === null || maybeTrusted === undefined || maybeTrusted === '') {\n        return maybeTrusted;\n      }\n      var constructor = (byType.hasOwnProperty(type) ? byType[type] : null);\n      if (constructor && maybeTrusted instanceof constructor) {\n        return maybeTrusted.$$unwrapTrustedValue();\n      }\n      // If we get here, then we may only take one of two actions.\n      // 1. sanitize the value for the requested type, or\n      // 2. throw an exception.\n      if (type === SCE_CONTEXTS.RESOURCE_URL) {\n        if (isResourceUrlAllowedByPolicy(maybeTrusted)) {\n          return maybeTrusted;\n        } else {\n          throw $sceMinErr('insecurl',\n              'Blocked loading resource from url not allowed by $sceDelegate policy.  URL: {0}',\n              maybeTrusted.toString());\n        }\n      } else if (type === SCE_CONTEXTS.HTML) {\n        return htmlSanitizer(maybeTrusted);\n      }\n      throw $sceMinErr('unsafe', 'Attempting to use an unsafe value in a safe context.');\n    }\n\n    return { trustAs: trustAs,\n             getTrusted: getTrusted,\n             valueOf: valueOf };\n  }];\n}\n\n\n/**\n * @ngdoc provider\n * @name $sceProvider\n * @description\n *\n * The $sceProvider provider allows developers to configure the {@link ng.$sce $sce} service.\n * -   enable/disable Strict Contextual Escaping (SCE) in a module\n * -   override the default implementation with a custom delegate\n *\n * Read more about {@link ng.$sce Strict Contextual Escaping (SCE)}.\n */\n\n/* jshint maxlen: false*/\n\n/**\n * @ngdoc service\n * @name $sce\n * @kind function\n *\n * @description\n *\n * `$sce` is a service that provides Strict Contextual Escaping services to AngularJS.\n *\n * # Strict Contextual Escaping\n *\n * Strict Contextual Escaping (SCE) is a mode in which AngularJS requires bindings in certain\n * contexts to result in a value that is marked as safe to use for that context.  One example of\n * such a context is binding arbitrary html controlled by the user via `ng-bind-html`.  We refer\n * to these contexts as privileged or SCE contexts.\n *\n * As of version 1.2, Angular ships with SCE enabled by default.\n *\n * Note:  When enabled (the default), IE<11 in quirks mode is not supported.  In this mode, IE<11 allow\n * one to execute arbitrary javascript by the use of the expression() syntax.  Refer\n * <http://blogs.msdn.com/b/ie/archive/2008/10/16/ending-expressions.aspx> to learn more about them.\n * You can ensure your document is in standards mode and not quirks mode by adding `<!doctype html>`\n * to the top of your HTML document.\n *\n * SCE assists in writing code in way that (a) is secure by default and (b) makes auditing for\n * security vulnerabilities such as XSS, clickjacking, etc. a lot easier.\n *\n * Here's an example of a binding in a privileged context:\n *\n * ```\n * <input ng-model=\"userHtml\">\n * <div ng-bind-html=\"userHtml\"></div>\n * ```\n *\n * Notice that `ng-bind-html` is bound to `userHtml` controlled by the user.  With SCE\n * disabled, this application allows the user to render arbitrary HTML into the DIV.\n * In a more realistic example, one may be rendering user comments, blog articles, etc. via\n * bindings.  (HTML is just one example of a context where rendering user controlled input creates\n * security vulnerabilities.)\n *\n * For the case of HTML, you might use a library, either on the client side, or on the server side,\n * to sanitize unsafe HTML before binding to the value and rendering it in the document.\n *\n * How would you ensure that every place that used these types of bindings was bound to a value that\n * was sanitized by your library (or returned as safe for rendering by your server?)  How can you\n * ensure that you didn't accidentally delete the line that sanitized the value, or renamed some\n * properties/fields and forgot to update the binding to the sanitized value?\n *\n * To be secure by default, you want to ensure that any such bindings are disallowed unless you can\n * determine that something explicitly says it's safe to use a value for binding in that\n * context.  You can then audit your code (a simple grep would do) to ensure that this is only done\n * for those values that you can easily tell are safe - because they were received from your server,\n * sanitized by your library, etc.  You can organize your codebase to help with this - perhaps\n * allowing only the files in a specific directory to do this.  Ensuring that the internal API\n * exposed by that code doesn't markup arbitrary values as safe then becomes a more manageable task.\n *\n * In the case of AngularJS' SCE service, one uses {@link ng.$sce#trustAs $sce.trustAs}\n * (and shorthand methods such as {@link ng.$sce#trustAsHtml $sce.trustAsHtml}, etc.) to\n * obtain values that will be accepted by SCE / privileged contexts.\n *\n *\n * ## How does it work?\n *\n * In privileged contexts, directives and code will bind to the result of {@link ng.$sce#getTrusted\n * $sce.getTrusted(context, value)} rather than to the value directly.  Directives use {@link\n * ng.$sce#parseAs $sce.parseAs} rather than `$parse` to watch attribute bindings, which performs the\n * {@link ng.$sce#getTrusted $sce.getTrusted} behind the scenes on non-constant literals.\n *\n * As an example, {@link ng.directive:ngBindHtml ngBindHtml} uses {@link\n * ng.$sce#parseAsHtml $sce.parseAsHtml(binding expression)}.  Here's the actual code (slightly\n * simplified):\n *\n * ```\n * var ngBindHtmlDirective = ['$sce', function($sce) {\n *   return function(scope, element, attr) {\n *     scope.$watch($sce.parseAsHtml(attr.ngBindHtml), function(value) {\n *       element.html(value || '');\n *     });\n *   };\n * }];\n * ```\n *\n * ## Impact on loading templates\n *\n * This applies both to the {@link ng.directive:ngInclude `ng-include`} directive as well as\n * `templateUrl`'s specified by {@link guide/directive directives}.\n *\n * By default, Angular only loads templates from the same domain and protocol as the application\n * document.  This is done by calling {@link ng.$sce#getTrustedResourceUrl\n * $sce.getTrustedResourceUrl} on the template URL.  To load templates from other domains and/or\n * protocols, you may either either {@link ng.$sceDelegateProvider#resourceUrlWhitelist whitelist\n * them} or {@link ng.$sce#trustAsResourceUrl wrap it} into a trusted value.\n *\n * *Please note*:\n * The browser's\n * [Same Origin Policy](https://code.google.com/p/browsersec/wiki/Part2#Same-origin_policy_for_XMLHttpRequest)\n * and [Cross-Origin Resource Sharing (CORS)](http://www.w3.org/TR/cors/)\n * policy apply in addition to this and may further restrict whether the template is successfully\n * loaded.  This means that without the right CORS policy, loading templates from a different domain\n * won't work on all browsers.  Also, loading templates from `file://` URL does not work on some\n * browsers.\n *\n * ## This feels like too much overhead\n *\n * It's important to remember that SCE only applies to interpolation expressions.\n *\n * If your expressions are constant literals, they're automatically trusted and you don't need to\n * call `$sce.trustAs` on them (remember to include the `ngSanitize` module) (e.g.\n * `<div ng-bind-html=\"'<b>implicitly trusted</b>'\"></div>`) just works.\n *\n * Additionally, `a[href]` and `img[src]` automatically sanitize their URLs and do not pass them\n * through {@link ng.$sce#getTrusted $sce.getTrusted}.  SCE doesn't play a role here.\n *\n * The included {@link ng.$sceDelegate $sceDelegate} comes with sane defaults to allow you to load\n * templates in `ng-include` from your application's domain without having to even know about SCE.\n * It blocks loading templates from other domains or loading templates over http from an https\n * served document.  You can change these by setting your own custom {@link\n * ng.$sceDelegateProvider#resourceUrlWhitelist whitelists} and {@link\n * ng.$sceDelegateProvider#resourceUrlBlacklist blacklists} for matching such URLs.\n *\n * This significantly reduces the overhead.  It is far easier to pay the small overhead and have an\n * application that's secure and can be audited to verify that with much more ease than bolting\n * security onto an application later.\n *\n * <a name=\"contexts\"></a>\n * ## What trusted context types are supported?\n *\n * | Context             | Notes          |\n * |---------------------|----------------|\n * | `$sce.HTML`         | For HTML that's safe to source into the application.  The {@link ng.directive:ngBindHtml ngBindHtml} directive uses this context for bindings. If an unsafe value is encountered and the {@link ngSanitize $sanitize} module is present this will sanitize the value instead of throwing an error. |\n * | `$sce.CSS`          | For CSS that's safe to source into the application.  Currently unused.  Feel free to use it in your own directives. |\n * | `$sce.URL`          | For URLs that are safe to follow as links.  Currently unused (`<a href=` and `<img src=` sanitize their urls and don't constitute an SCE context. |\n * | `$sce.RESOURCE_URL` | For URLs that are not only safe to follow as links, but whose contents are also safe to include in your application.  Examples include `ng-include`, `src` / `ngSrc` bindings for tags other than `IMG` (e.g. `IFRAME`, `OBJECT`, etc.)  <br><br>Note that `$sce.RESOURCE_URL` makes a stronger statement about the URL than `$sce.URL` does and therefore contexts requiring values trusted for `$sce.RESOURCE_URL` can be used anywhere that values trusted for `$sce.URL` are required. |\n * | `$sce.JS`           | For JavaScript that is safe to execute in your application's context.  Currently unused.  Feel free to use it in your own directives. |\n *\n * ## Format of items in {@link ng.$sceDelegateProvider#resourceUrlWhitelist resourceUrlWhitelist}/{@link ng.$sceDelegateProvider#resourceUrlBlacklist Blacklist} <a name=\"resourceUrlPatternItem\"></a>\n *\n *  Each element in these arrays must be one of the following:\n *\n *  - **'self'**\n *    - The special **string**, `'self'`, can be used to match against all URLs of the **same\n *      domain** as the application document using the **same protocol**.\n *  - **String** (except the special value `'self'`)\n *    - The string is matched against the full *normalized / absolute URL* of the resource\n *      being tested (substring matches are not good enough.)\n *    - There are exactly **two wildcard sequences** - `*` and `**`.  All other characters\n *      match themselves.\n *    - `*`: matches zero or more occurrences of any character other than one of the following 6\n *      characters: '`:`', '`/`', '`.`', '`?`', '`&`' and ';'.  It's a useful wildcard for use\n *      in a whitelist.\n *    - `**`: matches zero or more occurrences of *any* character.  As such, it's not\n *      not appropriate to use in for a scheme, domain, etc. as it would match too much.  (e.g.\n *      http://**.example.com/ would match http://evil.com/?ignore=.example.com/ and that might\n *      not have been the intention.)  Its usage at the very end of the path is ok.  (e.g.\n *      http://foo.example.com/templates/**).\n *  - **RegExp** (*see caveat below*)\n *    - *Caveat*:  While regular expressions are powerful and offer great flexibility,  their syntax\n *      (and all the inevitable escaping) makes them *harder to maintain*.  It's easy to\n *      accidentally introduce a bug when one updates a complex expression (imho, all regexes should\n *      have good test coverage.).  For instance, the use of `.` in the regex is correct only in a\n *      small number of cases.  A `.` character in the regex used when matching the scheme or a\n *      subdomain could be matched against a `:` or literal `.` that was likely not intended.   It\n *      is highly recommended to use the string patterns and only fall back to regular expressions\n *      if they as a last resort.\n *    - The regular expression must be an instance of RegExp (i.e. not a string.)  It is\n *      matched against the **entire** *normalized / absolute URL* of the resource being tested\n *      (even when the RegExp did not have the `^` and `$` codes.)  In addition, any flags\n *      present on the RegExp (such as multiline, global, ignoreCase) are ignored.\n *    - If you are generating your JavaScript from some other templating engine (not\n *      recommended, e.g. in issue [#4006](https://github.com/angular/angular.js/issues/4006)),\n *      remember to escape your regular expression (and be aware that you might need more than\n *      one level of escaping depending on your templating engine and the way you interpolated\n *      the value.)  Do make use of your platform's escaping mechanism as it might be good\n *      enough before coding your own.  e.g. Ruby has\n *      [Regexp.escape(str)](http://www.ruby-doc.org/core-2.0.0/Regexp.html#method-c-escape)\n *      and Python has [re.escape](http://docs.python.org/library/re.html#re.escape).\n *      Javascript lacks a similar built in function for escaping.  Take a look at Google\n *      Closure library's [goog.string.regExpEscape(s)](\n *      http://docs.closure-library.googlecode.com/git/closure_goog_string_string.js.source.html#line962).\n *\n * Refer {@link ng.$sceDelegateProvider $sceDelegateProvider} for an example.\n *\n * ## Show me an example using SCE.\n *\n * <example module=\"mySceApp\" deps=\"angular-sanitize.js\">\n * <file name=\"index.html\">\n *   <div ng-controller=\"AppController as myCtrl\">\n *     <i ng-bind-html=\"myCtrl.explicitlyTrustedHtml\" id=\"explicitlyTrustedHtml\"></i><br><br>\n *     <b>User comments</b><br>\n *     By default, HTML that isn't explicitly trusted (e.g. Alice's comment) is sanitized when\n *     $sanitize is available.  If $sanitize isn't available, this results in an error instead of an\n *     exploit.\n *     <div class=\"well\">\n *       <div ng-repeat=\"userComment in myCtrl.userComments\">\n *         <b>{{userComment.name}}</b>:\n *         <span ng-bind-html=\"userComment.htmlComment\" class=\"htmlComment\"></span>\n *         <br>\n *       </div>\n *     </div>\n *   </div>\n * </file>\n *\n * <file name=\"script.js\">\n *   angular.module('mySceApp', ['ngSanitize'])\n *     .controller('AppController', ['$http', '$templateCache', '$sce',\n *       function($http, $templateCache, $sce) {\n *         var self = this;\n *         $http.get(\"test_data.json\", {cache: $templateCache}).success(function(userComments) {\n *           self.userComments = userComments;\n *         });\n *         self.explicitlyTrustedHtml = $sce.trustAsHtml(\n *             '<span onmouseover=\"this.textContent=&quot;Explicitly trusted HTML bypasses ' +\n *             'sanitization.&quot;\">Hover over this text.</span>');\n *       }]);\n * </file>\n *\n * <file name=\"test_data.json\">\n * [\n *   { \"name\": \"Alice\",\n *     \"htmlComment\":\n *         \"<span onmouseover='this.textContent=\\\"PWN3D!\\\"'>Is <i>anyone</i> reading this?</span>\"\n *   },\n *   { \"name\": \"Bob\",\n *     \"htmlComment\": \"<i>Yes!</i>  Am I the only other one?\"\n *   }\n * ]\n * </file>\n *\n * <file name=\"protractor.js\" type=\"protractor\">\n *   describe('SCE doc demo', function() {\n *     it('should sanitize untrusted values', function() {\n *       expect(element.all(by.css('.htmlComment')).first().getInnerHtml())\n *           .toBe('<span>Is <i>anyone</i> reading this?</span>');\n *     });\n *\n *     it('should NOT sanitize explicitly trusted values', function() {\n *       expect(element(by.id('explicitlyTrustedHtml')).getInnerHtml()).toBe(\n *           '<span onmouseover=\"this.textContent=&quot;Explicitly trusted HTML bypasses ' +\n *           'sanitization.&quot;\">Hover over this text.</span>');\n *     });\n *   });\n * </file>\n * </example>\n *\n *\n *\n * ## Can I disable SCE completely?\n *\n * Yes, you can.  However, this is strongly discouraged.  SCE gives you a lot of security benefits\n * for little coding overhead.  It will be much harder to take an SCE disabled application and\n * either secure it on your own or enable SCE at a later stage.  It might make sense to disable SCE\n * for cases where you have a lot of existing code that was written before SCE was introduced and\n * you're migrating them a module at a time.\n *\n * That said, here's how you can completely disable SCE:\n *\n * ```\n * angular.module('myAppWithSceDisabledmyApp', []).config(function($sceProvider) {\n *   // Completely disable SCE.  For demonstration purposes only!\n *   // Do not use in new projects.\n *   $sceProvider.enabled(false);\n * });\n * ```\n *\n */\n/* jshint maxlen: 100 */\n\nfunction $SceProvider() {\n  var enabled = true;\n\n  /**\n   * @ngdoc method\n   * @name $sceProvider#enabled\n   * @kind function\n   *\n   * @param {boolean=} value If provided, then enables/disables SCE.\n   * @return {boolean} true if SCE is enabled, false otherwise.\n   *\n   * @description\n   * Enables/disables SCE and returns the current value.\n   */\n  this.enabled = function(value) {\n    if (arguments.length) {\n      enabled = !!value;\n    }\n    return enabled;\n  };\n\n\n  /* Design notes on the default implementation for SCE.\n   *\n   * The API contract for the SCE delegate\n   * -------------------------------------\n   * The SCE delegate object must provide the following 3 methods:\n   *\n   * - trustAs(contextEnum, value)\n   *     This method is used to tell the SCE service that the provided value is OK to use in the\n   *     contexts specified by contextEnum.  It must return an object that will be accepted by\n   *     getTrusted() for a compatible contextEnum and return this value.\n   *\n   * - valueOf(value)\n   *     For values that were not produced by trustAs(), return them as is.  For values that were\n   *     produced by trustAs(), return the corresponding input value to trustAs.  Basically, if\n   *     trustAs is wrapping the given values into some type, this operation unwraps it when given\n   *     such a value.\n   *\n   * - getTrusted(contextEnum, value)\n   *     This function should return the a value that is safe to use in the context specified by\n   *     contextEnum or throw and exception otherwise.\n   *\n   * NOTE: This contract deliberately does NOT state that values returned by trustAs() must be\n   * opaque or wrapped in some holder object.  That happens to be an implementation detail.  For\n   * instance, an implementation could maintain a registry of all trusted objects by context.  In\n   * such a case, trustAs() would return the same object that was passed in.  getTrusted() would\n   * return the same object passed in if it was found in the registry under a compatible context or\n   * throw an exception otherwise.  An implementation might only wrap values some of the time based\n   * on some criteria.  getTrusted() might return a value and not throw an exception for special\n   * constants or objects even if not wrapped.  All such implementations fulfill this contract.\n   *\n   *\n   * A note on the inheritance model for SCE contexts\n   * ------------------------------------------------\n   * I've used inheritance and made RESOURCE_URL wrapped types a subtype of URL wrapped types.  This\n   * is purely an implementation details.\n   *\n   * The contract is simply this:\n   *\n   *     getTrusted($sce.RESOURCE_URL, value) succeeding implies that getTrusted($sce.URL, value)\n   *     will also succeed.\n   *\n   * Inheritance happens to capture this in a natural way.  In some future, we\n   * may not use inheritance anymore.  That is OK because no code outside of\n   * sce.js and sceSpecs.js would need to be aware of this detail.\n   */\n\n  this.$get = ['$parse', '$sceDelegate', function(\n                $parse,   $sceDelegate) {\n    // Prereq: Ensure that we're not running in IE<11 quirks mode.  In that mode, IE < 11 allow\n    // the \"expression(javascript expression)\" syntax which is insecure.\n    if (enabled && msie < 8) {\n      throw $sceMinErr('iequirks',\n        'Strict Contextual Escaping does not support Internet Explorer version < 11 in quirks ' +\n        'mode.  You can fix this by adding the text <!doctype html> to the top of your HTML ' +\n        'document.  See http://docs.angularjs.org/api/ng.$sce for more information.');\n    }\n\n    var sce = shallowCopy(SCE_CONTEXTS);\n\n    /**\n     * @ngdoc method\n     * @name $sce#isEnabled\n     * @kind function\n     *\n     * @return {Boolean} true if SCE is enabled, false otherwise.  If you want to set the value, you\n     * have to do it at module config time on {@link ng.$sceProvider $sceProvider}.\n     *\n     * @description\n     * Returns a boolean indicating if SCE is enabled.\n     */\n    sce.isEnabled = function() {\n      return enabled;\n    };\n    sce.trustAs = $sceDelegate.trustAs;\n    sce.getTrusted = $sceDelegate.getTrusted;\n    sce.valueOf = $sceDelegate.valueOf;\n\n    if (!enabled) {\n      sce.trustAs = sce.getTrusted = function(type, value) { return value; };\n      sce.valueOf = identity;\n    }\n\n    /**\n     * @ngdoc method\n     * @name $sce#parseAs\n     *\n     * @description\n     * Converts Angular {@link guide/expression expression} into a function.  This is like {@link\n     * ng.$parse $parse} and is identical when the expression is a literal constant.  Otherwise, it\n     * wraps the expression in a call to {@link ng.$sce#getTrusted $sce.getTrusted(*type*,\n     * *result*)}\n     *\n     * @param {string} type The kind of SCE context in which this result will be used.\n     * @param {string} expression String expression to compile.\n     * @returns {function(context, locals)} a function which represents the compiled expression:\n     *\n     *    * `context` – `{object}` – an object against which any expressions embedded in the strings\n     *      are evaluated against (typically a scope object).\n     *    * `locals` – `{object=}` – local variables context object, useful for overriding values in\n     *      `context`.\n     */\n    sce.parseAs = function sceParseAs(type, expr) {\n      var parsed = $parse(expr);\n      if (parsed.literal && parsed.constant) {\n        return parsed;\n      } else {\n        return $parse(expr, function(value) {\n          return sce.getTrusted(type, value);\n        });\n      }\n    };\n\n    /**\n     * @ngdoc method\n     * @name $sce#trustAs\n     *\n     * @description\n     * Delegates to {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs`}.  As such,\n     * returns an object that is trusted by angular for use in specified strict contextual\n     * escaping contexts (such as ng-bind-html, ng-include, any src attribute\n     * interpolation, any dom event binding attribute interpolation such as for onclick,  etc.)\n     * that uses the provided value.  See * {@link ng.$sce $sce} for enabling strict contextual\n     * escaping.\n     *\n     * @param {string} type The kind of context in which this value is safe for use.  e.g. url,\n     *   resource_url, html, js and css.\n     * @param {*} value The value that that should be considered trusted/safe.\n     * @returns {*} A value that can be used to stand in for the provided `value` in places\n     * where Angular expects a $sce.trustAs() return value.\n     */\n\n    /**\n     * @ngdoc method\n     * @name $sce#trustAsHtml\n     *\n     * @description\n     * Shorthand method.  `$sce.trustAsHtml(value)` →\n     *     {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs($sce.HTML, value)`}\n     *\n     * @param {*} value The value to trustAs.\n     * @returns {*} An object that can be passed to {@link ng.$sce#getTrustedHtml\n     *     $sce.getTrustedHtml(value)} to obtain the original value.  (privileged directives\n     *     only accept expressions that are either literal constants or are the\n     *     return value of {@link ng.$sce#trustAs $sce.trustAs}.)\n     */\n\n    /**\n     * @ngdoc method\n     * @name $sce#trustAsUrl\n     *\n     * @description\n     * Shorthand method.  `$sce.trustAsUrl(value)` →\n     *     {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs($sce.URL, value)`}\n     *\n     * @param {*} value The value to trustAs.\n     * @returns {*} An object that can be passed to {@link ng.$sce#getTrustedUrl\n     *     $sce.getTrustedUrl(value)} to obtain the original value.  (privileged directives\n     *     only accept expressions that are either literal constants or are the\n     *     return value of {@link ng.$sce#trustAs $sce.trustAs}.)\n     */\n\n    /**\n     * @ngdoc method\n     * @name $sce#trustAsResourceUrl\n     *\n     * @description\n     * Shorthand method.  `$sce.trustAsResourceUrl(value)` →\n     *     {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs($sce.RESOURCE_URL, value)`}\n     *\n     * @param {*} value The value to trustAs.\n     * @returns {*} An object that can be passed to {@link ng.$sce#getTrustedResourceUrl\n     *     $sce.getTrustedResourceUrl(value)} to obtain the original value.  (privileged directives\n     *     only accept expressions that are either literal constants or are the return\n     *     value of {@link ng.$sce#trustAs $sce.trustAs}.)\n     */\n\n    /**\n     * @ngdoc method\n     * @name $sce#trustAsJs\n     *\n     * @description\n     * Shorthand method.  `$sce.trustAsJs(value)` →\n     *     {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs($sce.JS, value)`}\n     *\n     * @param {*} value The value to trustAs.\n     * @returns {*} An object that can be passed to {@link ng.$sce#getTrustedJs\n     *     $sce.getTrustedJs(value)} to obtain the original value.  (privileged directives\n     *     only accept expressions that are either literal constants or are the\n     *     return value of {@link ng.$sce#trustAs $sce.trustAs}.)\n     */\n\n    /**\n     * @ngdoc method\n     * @name $sce#getTrusted\n     *\n     * @description\n     * Delegates to {@link ng.$sceDelegate#getTrusted `$sceDelegate.getTrusted`}.  As such,\n     * takes the result of a {@link ng.$sce#trustAs `$sce.trustAs`}() call and returns the\n     * originally supplied value if the queried context type is a supertype of the created type.\n     * If this condition isn't satisfied, throws an exception.\n     *\n     * @param {string} type The kind of context in which this value is to be used.\n     * @param {*} maybeTrusted The result of a prior {@link ng.$sce#trustAs `$sce.trustAs`}\n     *                         call.\n     * @returns {*} The value the was originally provided to\n     *              {@link ng.$sce#trustAs `$sce.trustAs`} if valid in this context.\n     *              Otherwise, throws an exception.\n     */\n\n    /**\n     * @ngdoc method\n     * @name $sce#getTrustedHtml\n     *\n     * @description\n     * Shorthand method.  `$sce.getTrustedHtml(value)` →\n     *     {@link ng.$sceDelegate#getTrusted `$sceDelegate.getTrusted($sce.HTML, value)`}\n     *\n     * @param {*} value The value to pass to `$sce.getTrusted`.\n     * @returns {*} The return value of `$sce.getTrusted($sce.HTML, value)`\n     */\n\n    /**\n     * @ngdoc method\n     * @name $sce#getTrustedCss\n     *\n     * @description\n     * Shorthand method.  `$sce.getTrustedCss(value)` →\n     *     {@link ng.$sceDelegate#getTrusted `$sceDelegate.getTrusted($sce.CSS, value)`}\n     *\n     * @param {*} value The value to pass to `$sce.getTrusted`.\n     * @returns {*} The return value of `$sce.getTrusted($sce.CSS, value)`\n     */\n\n    /**\n     * @ngdoc method\n     * @name $sce#getTrustedUrl\n     *\n     * @description\n     * Shorthand method.  `$sce.getTrustedUrl(value)` →\n     *     {@link ng.$sceDelegate#getTrusted `$sceDelegate.getTrusted($sce.URL, value)`}\n     *\n     * @param {*} value The value to pass to `$sce.getTrusted`.\n     * @returns {*} The return value of `$sce.getTrusted($sce.URL, value)`\n     */\n\n    /**\n     * @ngdoc method\n     * @name $sce#getTrustedResourceUrl\n     *\n     * @description\n     * Shorthand method.  `$sce.getTrustedResourceUrl(value)` →\n     *     {@link ng.$sceDelegate#getTrusted `$sceDelegate.getTrusted($sce.RESOURCE_URL, value)`}\n     *\n     * @param {*} value The value to pass to `$sceDelegate.getTrusted`.\n     * @returns {*} The return value of `$sce.getTrusted($sce.RESOURCE_URL, value)`\n     */\n\n    /**\n     * @ngdoc method\n     * @name $sce#getTrustedJs\n     *\n     * @description\n     * Shorthand method.  `$sce.getTrustedJs(value)` →\n     *     {@link ng.$sceDelegate#getTrusted `$sceDelegate.getTrusted($sce.JS, value)`}\n     *\n     * @param {*} value The value to pass to `$sce.getTrusted`.\n     * @returns {*} The return value of `$sce.getTrusted($sce.JS, value)`\n     */\n\n    /**\n     * @ngdoc method\n     * @name $sce#parseAsHtml\n     *\n     * @description\n     * Shorthand method.  `$sce.parseAsHtml(expression string)` →\n     *     {@link ng.$sce#parseAs `$sce.parseAs($sce.HTML, value)`}\n     *\n     * @param {string} expression String expression to compile.\n     * @returns {function(context, locals)} a function which represents the compiled expression:\n     *\n     *    * `context` – `{object}` – an object against which any expressions embedded in the strings\n     *      are evaluated against (typically a scope object).\n     *    * `locals` – `{object=}` – local variables context object, useful for overriding values in\n     *      `context`.\n     */\n\n    /**\n     * @ngdoc method\n     * @name $sce#parseAsCss\n     *\n     * @description\n     * Shorthand method.  `$sce.parseAsCss(value)` →\n     *     {@link ng.$sce#parseAs `$sce.parseAs($sce.CSS, value)`}\n     *\n     * @param {string} expression String expression to compile.\n     * @returns {function(context, locals)} a function which represents the compiled expression:\n     *\n     *    * `context` – `{object}` – an object against which any expressions embedded in the strings\n     *      are evaluated against (typically a scope object).\n     *    * `locals` – `{object=}` – local variables context object, useful for overriding values in\n     *      `context`.\n     */\n\n    /**\n     * @ngdoc method\n     * @name $sce#parseAsUrl\n     *\n     * @description\n     * Shorthand method.  `$sce.parseAsUrl(value)` →\n     *     {@link ng.$sce#parseAs `$sce.parseAs($sce.URL, value)`}\n     *\n     * @param {string} expression String expression to compile.\n     * @returns {function(context, locals)} a function which represents the compiled expression:\n     *\n     *    * `context` – `{object}` – an object against which any expressions embedded in the strings\n     *      are evaluated against (typically a scope object).\n     *    * `locals` – `{object=}` – local variables context object, useful for overriding values in\n     *      `context`.\n     */\n\n    /**\n     * @ngdoc method\n     * @name $sce#parseAsResourceUrl\n     *\n     * @description\n     * Shorthand method.  `$sce.parseAsResourceUrl(value)` →\n     *     {@link ng.$sce#parseAs `$sce.parseAs($sce.RESOURCE_URL, value)`}\n     *\n     * @param {string} expression String expression to compile.\n     * @returns {function(context, locals)} a function which represents the compiled expression:\n     *\n     *    * `context` – `{object}` – an object against which any expressions embedded in the strings\n     *      are evaluated against (typically a scope object).\n     *    * `locals` – `{object=}` – local variables context object, useful for overriding values in\n     *      `context`.\n     */\n\n    /**\n     * @ngdoc method\n     * @name $sce#parseAsJs\n     *\n     * @description\n     * Shorthand method.  `$sce.parseAsJs(value)` →\n     *     {@link ng.$sce#parseAs `$sce.parseAs($sce.JS, value)`}\n     *\n     * @param {string} expression String expression to compile.\n     * @returns {function(context, locals)} a function which represents the compiled expression:\n     *\n     *    * `context` – `{object}` – an object against which any expressions embedded in the strings\n     *      are evaluated against (typically a scope object).\n     *    * `locals` – `{object=}` – local variables context object, useful for overriding values in\n     *      `context`.\n     */\n\n    // Shorthand delegations.\n    var parse = sce.parseAs,\n        getTrusted = sce.getTrusted,\n        trustAs = sce.trustAs;\n\n    forEach(SCE_CONTEXTS, function(enumValue, name) {\n      var lName = lowercase(name);\n      sce[camelCase(\"parse_as_\" + lName)] = function(expr) {\n        return parse(enumValue, expr);\n      };\n      sce[camelCase(\"get_trusted_\" + lName)] = function(value) {\n        return getTrusted(enumValue, value);\n      };\n      sce[camelCase(\"trust_as_\" + lName)] = function(value) {\n        return trustAs(enumValue, value);\n      };\n    });\n\n    return sce;\n  }];\n}\n\n/**\n * !!! This is an undocumented \"private\" service !!!\n *\n * @name $sniffer\n * @requires $window\n * @requires $document\n *\n * @property {boolean} history Does the browser support html5 history api ?\n * @property {boolean} transitions Does the browser support CSS transition events ?\n * @property {boolean} animations Does the browser support CSS animation events ?\n *\n * @description\n * This is very simple implementation of testing browser's features.\n */\nfunction $SnifferProvider() {\n  this.$get = ['$window', '$document', function($window, $document) {\n    var eventSupport = {},\n        android =\n          int((/android (\\d+)/.exec(lowercase(($window.navigator || {}).userAgent)) || [])[1]),\n        boxee = /Boxee/i.test(($window.navigator || {}).userAgent),\n        document = $document[0] || {},\n        vendorPrefix,\n        vendorRegex = /^(Moz|webkit|ms)(?=[A-Z])/,\n        bodyStyle = document.body && document.body.style,\n        transitions = false,\n        animations = false,\n        match;\n\n    if (bodyStyle) {\n      for (var prop in bodyStyle) {\n        if (match = vendorRegex.exec(prop)) {\n          vendorPrefix = match[0];\n          vendorPrefix = vendorPrefix.substr(0, 1).toUpperCase() + vendorPrefix.substr(1);\n          break;\n        }\n      }\n\n      if (!vendorPrefix) {\n        vendorPrefix = ('WebkitOpacity' in bodyStyle) && 'webkit';\n      }\n\n      transitions = !!(('transition' in bodyStyle) || (vendorPrefix + 'Transition' in bodyStyle));\n      animations  = !!(('animation' in bodyStyle) || (vendorPrefix + 'Animation' in bodyStyle));\n\n      if (android && (!transitions ||  !animations)) {\n        transitions = isString(document.body.style.webkitTransition);\n        animations = isString(document.body.style.webkitAnimation);\n      }\n    }\n\n\n    return {\n      // Android has history.pushState, but it does not update location correctly\n      // so let's not use the history API at all.\n      // http://code.google.com/p/android/issues/detail?id=17471\n      // https://github.com/angular/angular.js/issues/904\n\n      // older webkit browser (533.9) on Boxee box has exactly the same problem as Android has\n      // so let's not use the history API also\n      // We are purposefully using `!(android < 4)` to cover the case when `android` is undefined\n      // jshint -W018\n      history: !!($window.history && $window.history.pushState && !(android < 4) && !boxee),\n      // jshint +W018\n      hasEvent: function(event) {\n        // IE9 implements 'input' event it's so fubared that we rather pretend that it doesn't have\n        // it. In particular the event is not fired when backspace or delete key are pressed or\n        // when cut operation is performed.\n        // IE10+ implements 'input' event but it erroneously fires under various situations,\n        // e.g. when placeholder changes, or a form is focused.\n        if (event === 'input' && msie <= 11) return false;\n\n        if (isUndefined(eventSupport[event])) {\n          var divElm = document.createElement('div');\n          eventSupport[event] = 'on' + event in divElm;\n        }\n\n        return eventSupport[event];\n      },\n      csp: csp(),\n      vendorPrefix: vendorPrefix,\n      transitions: transitions,\n      animations: animations,\n      android: android\n    };\n  }];\n}\n\nvar $compileMinErr = minErr('$compile');\n\n/**\n * @ngdoc service\n * @name $templateRequest\n *\n * @description\n * The `$templateRequest` service downloads the provided template using `$http` and, upon success,\n * stores the contents inside of `$templateCache`. If the HTTP request fails or the response data\n * of the HTTP request is empty, a `$compile` error will be thrown (the exception can be thwarted\n * by setting the 2nd parameter of the function to true).\n *\n * @param {string} tpl The HTTP request template URL\n * @param {boolean=} ignoreRequestError Whether or not to ignore the exception when the request fails or the template is empty\n *\n * @return {Promise} the HTTP Promise for the given.\n *\n * @property {number} totalPendingRequests total amount of pending template requests being downloaded.\n */\nfunction $TemplateRequestProvider() {\n  this.$get = ['$templateCache', '$http', '$q', function($templateCache, $http, $q) {\n    function handleRequestFn(tpl, ignoreRequestError) {\n      handleRequestFn.totalPendingRequests++;\n\n      var transformResponse = $http.defaults && $http.defaults.transformResponse;\n\n      if (isArray(transformResponse)) {\n        transformResponse = transformResponse.filter(function(transformer) {\n          return transformer !== defaultHttpResponseTransform;\n        });\n      } else if (transformResponse === defaultHttpResponseTransform) {\n        transformResponse = null;\n      }\n\n      var httpOptions = {\n        cache: $templateCache,\n        transformResponse: transformResponse\n      };\n\n      return $http.get(tpl, httpOptions)\n        .finally(function() {\n          handleRequestFn.totalPendingRequests--;\n        })\n        .then(function(response) {\n          return response.data;\n        }, handleError);\n\n      function handleError(resp) {\n        if (!ignoreRequestError) {\n          throw $compileMinErr('tpload', 'Failed to load template: {0}', tpl);\n        }\n        return $q.reject(resp);\n      }\n    }\n\n    handleRequestFn.totalPendingRequests = 0;\n\n    return handleRequestFn;\n  }];\n}\n\nfunction $$TestabilityProvider() {\n  this.$get = ['$rootScope', '$browser', '$location',\n       function($rootScope,   $browser,   $location) {\n\n    /**\n     * @name $testability\n     *\n     * @description\n     * The private $$testability service provides a collection of methods for use when debugging\n     * or by automated test and debugging tools.\n     */\n    var testability = {};\n\n    /**\n     * @name $$testability#findBindings\n     *\n     * @description\n     * Returns an array of elements that are bound (via ng-bind or {{}})\n     * to expressions matching the input.\n     *\n     * @param {Element} element The element root to search from.\n     * @param {string} expression The binding expression to match.\n     * @param {boolean} opt_exactMatch If true, only returns exact matches\n     *     for the expression. Filters and whitespace are ignored.\n     */\n    testability.findBindings = function(element, expression, opt_exactMatch) {\n      var bindings = element.getElementsByClassName('ng-binding');\n      var matches = [];\n      forEach(bindings, function(binding) {\n        var dataBinding = angular.element(binding).data('$binding');\n        if (dataBinding) {\n          forEach(dataBinding, function(bindingName) {\n            if (opt_exactMatch) {\n              var matcher = new RegExp('(^|\\\\s)' + escapeForRegexp(expression) + '(\\\\s|\\\\||$)');\n              if (matcher.test(bindingName)) {\n                matches.push(binding);\n              }\n            } else {\n              if (bindingName.indexOf(expression) != -1) {\n                matches.push(binding);\n              }\n            }\n          });\n        }\n      });\n      return matches;\n    };\n\n    /**\n     * @name $$testability#findModels\n     *\n     * @description\n     * Returns an array of elements that are two-way found via ng-model to\n     * expressions matching the input.\n     *\n     * @param {Element} element The element root to search from.\n     * @param {string} expression The model expression to match.\n     * @param {boolean} opt_exactMatch If true, only returns exact matches\n     *     for the expression.\n     */\n    testability.findModels = function(element, expression, opt_exactMatch) {\n      var prefixes = ['ng-', 'data-ng-', 'ng\\\\:'];\n      for (var p = 0; p < prefixes.length; ++p) {\n        var attributeEquals = opt_exactMatch ? '=' : '*=';\n        var selector = '[' + prefixes[p] + 'model' + attributeEquals + '\"' + expression + '\"]';\n        var elements = element.querySelectorAll(selector);\n        if (elements.length) {\n          return elements;\n        }\n      }\n    };\n\n    /**\n     * @name $$testability#getLocation\n     *\n     * @description\n     * Shortcut for getting the location in a browser agnostic way. Returns\n     *     the path, search, and hash. (e.g. /path?a=b#hash)\n     */\n    testability.getLocation = function() {\n      return $location.url();\n    };\n\n    /**\n     * @name $$testability#setLocation\n     *\n     * @description\n     * Shortcut for navigating to a location without doing a full page reload.\n     *\n     * @param {string} url The location url (path, search and hash,\n     *     e.g. /path?a=b#hash) to go to.\n     */\n    testability.setLocation = function(url) {\n      if (url !== $location.url()) {\n        $location.url(url);\n        $rootScope.$digest();\n      }\n    };\n\n    /**\n     * @name $$testability#whenStable\n     *\n     * @description\n     * Calls the callback when $timeout and $http requests are completed.\n     *\n     * @param {function} callback\n     */\n    testability.whenStable = function(callback) {\n      $browser.notifyWhenNoOutstandingRequests(callback);\n    };\n\n    return testability;\n  }];\n}\n\nfunction $TimeoutProvider() {\n  this.$get = ['$rootScope', '$browser', '$q', '$$q', '$exceptionHandler',\n       function($rootScope,   $browser,   $q,   $$q,   $exceptionHandler) {\n    var deferreds = {};\n\n\n     /**\n      * @ngdoc service\n      * @name $timeout\n      *\n      * @description\n      * Angular's wrapper for `window.setTimeout`. The `fn` function is wrapped into a try/catch\n      * block and delegates any exceptions to\n      * {@link ng.$exceptionHandler $exceptionHandler} service.\n      *\n      * The return value of registering a timeout function is a promise, which will be resolved when\n      * the timeout is reached and the timeout function is executed.\n      *\n      * To cancel a timeout request, call `$timeout.cancel(promise)`.\n      *\n      * In tests you can use {@link ngMock.$timeout `$timeout.flush()`} to\n      * synchronously flush the queue of deferred functions.\n      *\n      * @param {function()} fn A function, whose execution should be delayed.\n      * @param {number=} [delay=0] Delay in milliseconds.\n      * @param {boolean=} [invokeApply=true] If set to `false` skips model dirty checking, otherwise\n      *   will invoke `fn` within the {@link ng.$rootScope.Scope#$apply $apply} block.\n      * @returns {Promise} Promise that will be resolved when the timeout is reached. The value this\n      *   promise will be resolved with is the return value of the `fn` function.\n      *\n      */\n    function timeout(fn, delay, invokeApply) {\n      var skipApply = (isDefined(invokeApply) && !invokeApply),\n          deferred = (skipApply ? $$q : $q).defer(),\n          promise = deferred.promise,\n          timeoutId;\n\n      timeoutId = $browser.defer(function() {\n        try {\n          deferred.resolve(fn());\n        } catch (e) {\n          deferred.reject(e);\n          $exceptionHandler(e);\n        }\n        finally {\n          delete deferreds[promise.$$timeoutId];\n        }\n\n        if (!skipApply) $rootScope.$apply();\n      }, delay);\n\n      promise.$$timeoutId = timeoutId;\n      deferreds[timeoutId] = deferred;\n\n      return promise;\n    }\n\n\n     /**\n      * @ngdoc method\n      * @name $timeout#cancel\n      *\n      * @description\n      * Cancels a task associated with the `promise`. As a result of this, the promise will be\n      * resolved with a rejection.\n      *\n      * @param {Promise=} promise Promise returned by the `$timeout` function.\n      * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfully\n      *   canceled.\n      */\n    timeout.cancel = function(promise) {\n      if (promise && promise.$$timeoutId in deferreds) {\n        deferreds[promise.$$timeoutId].reject('canceled');\n        delete deferreds[promise.$$timeoutId];\n        return $browser.defer.cancel(promise.$$timeoutId);\n      }\n      return false;\n    };\n\n    return timeout;\n  }];\n}\n\n// NOTE:  The usage of window and document instead of $window and $document here is\n// deliberate.  This service depends on the specific behavior of anchor nodes created by the\n// browser (resolving and parsing URLs) that is unlikely to be provided by mock objects and\n// cause us to break tests.  In addition, when the browser resolves a URL for XHR, it\n// doesn't know about mocked locations and resolves URLs to the real document - which is\n// exactly the behavior needed here.  There is little value is mocking these out for this\n// service.\nvar urlParsingNode = document.createElement(\"a\");\nvar originUrl = urlResolve(window.location.href);\n\n\n/**\n *\n * Implementation Notes for non-IE browsers\n * ----------------------------------------\n * Assigning a URL to the href property of an anchor DOM node, even one attached to the DOM,\n * results both in the normalizing and parsing of the URL.  Normalizing means that a relative\n * URL will be resolved into an absolute URL in the context of the application document.\n * Parsing means that the anchor node's host, hostname, protocol, port, pathname and related\n * properties are all populated to reflect the normalized URL.  This approach has wide\n * compatibility - Safari 1+, Mozilla 1+, Opera 7+,e etc.  See\n * http://www.aptana.com/reference/html/api/HTMLAnchorElement.html\n *\n * Implementation Notes for IE\n * ---------------------------\n * IE >= 8 and <= 10 normalizes the URL when assigned to the anchor node similar to the other\n * browsers.  However, the parsed components will not be set if the URL assigned did not specify\n * them.  (e.g. if you assign a.href = \"foo\", then a.protocol, a.host, etc. will be empty.)  We\n * work around that by performing the parsing in a 2nd step by taking a previously normalized\n * URL (e.g. by assigning to a.href) and assigning it a.href again.  This correctly populates the\n * properties such as protocol, hostname, port, etc.\n *\n * IE7 does not normalize the URL when assigned to an anchor node.  (Apparently, it does, if one\n * uses the inner HTML approach to assign the URL as part of an HTML snippet -\n * http://stackoverflow.com/a/472729)  However, setting img[src] does normalize the URL.\n * Unfortunately, setting img[src] to something like \"javascript:foo\" on IE throws an exception.\n * Since the primary usage for normalizing URLs is to sanitize such URLs, we can't use that\n * method and IE < 8 is unsupported.\n *\n * References:\n *   http://developer.mozilla.org/en-US/docs/Web/API/HTMLAnchorElement\n *   http://www.aptana.com/reference/html/api/HTMLAnchorElement.html\n *   http://url.spec.whatwg.org/#urlutils\n *   https://github.com/angular/angular.js/pull/2902\n *   http://james.padolsey.com/javascript/parsing-urls-with-the-dom/\n *\n * @kind function\n * @param {string} url The URL to be parsed.\n * @description Normalizes and parses a URL.\n * @returns {object} Returns the normalized URL as a dictionary.\n *\n *   | member name   | Description    |\n *   |---------------|----------------|\n *   | href          | A normalized version of the provided URL if it was not an absolute URL |\n *   | protocol      | The protocol including the trailing colon                              |\n *   | host          | The host and port (if the port is non-default) of the normalizedUrl    |\n *   | search        | The search params, minus the question mark                             |\n *   | hash          | The hash string, minus the hash symbol\n *   | hostname      | The hostname\n *   | port          | The port, without \":\"\n *   | pathname      | The pathname, beginning with \"/\"\n *\n */\nfunction urlResolve(url) {\n  var href = url;\n\n  if (msie) {\n    // Normalize before parse.  Refer Implementation Notes on why this is\n    // done in two steps on IE.\n    urlParsingNode.setAttribute(\"href\", href);\n    href = urlParsingNode.href;\n  }\n\n  urlParsingNode.setAttribute('href', href);\n\n  // urlParsingNode provides the UrlUtils interface - http://url.spec.whatwg.org/#urlutils\n  return {\n    href: urlParsingNode.href,\n    protocol: urlParsingNode.protocol ? urlParsingNode.protocol.replace(/:$/, '') : '',\n    host: urlParsingNode.host,\n    search: urlParsingNode.search ? urlParsingNode.search.replace(/^\\?/, '') : '',\n    hash: urlParsingNode.hash ? urlParsingNode.hash.replace(/^#/, '') : '',\n    hostname: urlParsingNode.hostname,\n    port: urlParsingNode.port,\n    pathname: (urlParsingNode.pathname.charAt(0) === '/')\n      ? urlParsingNode.pathname\n      : '/' + urlParsingNode.pathname\n  };\n}\n\n/**\n * Parse a request URL and determine whether this is a same-origin request as the application document.\n *\n * @param {string|object} requestUrl The url of the request as a string that will be resolved\n * or a parsed URL object.\n * @returns {boolean} Whether the request is for the same origin as the application document.\n */\nfunction urlIsSameOrigin(requestUrl) {\n  var parsed = (isString(requestUrl)) ? urlResolve(requestUrl) : requestUrl;\n  return (parsed.protocol === originUrl.protocol &&\n          parsed.host === originUrl.host);\n}\n\n/**\n * @ngdoc service\n * @name $window\n *\n * @description\n * A reference to the browser's `window` object. While `window`\n * is globally available in JavaScript, it causes testability problems, because\n * it is a global variable. In angular we always refer to it through the\n * `$window` service, so it may be overridden, removed or mocked for testing.\n *\n * Expressions, like the one defined for the `ngClick` directive in the example\n * below, are evaluated with respect to the current scope.  Therefore, there is\n * no risk of inadvertently coding in a dependency on a global value in such an\n * expression.\n *\n * @example\n   <example module=\"windowExample\">\n     <file name=\"index.html\">\n       <script>\n         angular.module('windowExample', [])\n           .controller('ExampleController', ['$scope', '$window', function($scope, $window) {\n             $scope.greeting = 'Hello, World!';\n             $scope.doGreeting = function(greeting) {\n               $window.alert(greeting);\n             };\n           }]);\n       </script>\n       <div ng-controller=\"ExampleController\">\n         <input type=\"text\" ng-model=\"greeting\" />\n         <button ng-click=\"doGreeting(greeting)\">ALERT</button>\n       </div>\n     </file>\n     <file name=\"protractor.js\" type=\"protractor\">\n      it('should display the greeting in the input box', function() {\n       element(by.model('greeting')).sendKeys('Hello, E2E Tests');\n       // If we click the button it will block the test runner\n       // element(':button').click();\n      });\n     </file>\n   </example>\n */\nfunction $WindowProvider() {\n  this.$get = valueFn(window);\n}\n\n/* global currencyFilter: true,\n dateFilter: true,\n filterFilter: true,\n jsonFilter: true,\n limitToFilter: true,\n lowercaseFilter: true,\n numberFilter: true,\n orderByFilter: true,\n uppercaseFilter: true,\n */\n\n/**\n * @ngdoc provider\n * @name $filterProvider\n * @description\n *\n * Filters are just functions which transform input to an output. However filters need to be\n * Dependency Injected. To achieve this a filter definition consists of a factory function which is\n * annotated with dependencies and is responsible for creating a filter function.\n *\n * ```js\n *   // Filter registration\n *   function MyModule($provide, $filterProvider) {\n *     // create a service to demonstrate injection (not always needed)\n *     $provide.value('greet', function(name){\n *       return 'Hello ' + name + '!';\n *     });\n *\n *     // register a filter factory which uses the\n *     // greet service to demonstrate DI.\n *     $filterProvider.register('greet', function(greet){\n *       // return the filter function which uses the greet service\n *       // to generate salutation\n *       return function(text) {\n *         // filters need to be forgiving so check input validity\n *         return text && greet(text) || text;\n *       };\n *     });\n *   }\n * ```\n *\n * The filter function is registered with the `$injector` under the filter name suffix with\n * `Filter`.\n *\n * ```js\n *   it('should be the same instance', inject(\n *     function($filterProvider) {\n *       $filterProvider.register('reverse', function(){\n *         return ...;\n *       });\n *     },\n *     function($filter, reverseFilter) {\n *       expect($filter('reverse')).toBe(reverseFilter);\n *     });\n * ```\n *\n *\n * For more information about how angular filters work, and how to create your own filters, see\n * {@link guide/filter Filters} in the Angular Developer Guide.\n */\n\n/**\n * @ngdoc service\n * @name $filter\n * @kind function\n * @description\n * Filters are used for formatting data displayed to the user.\n *\n * The general syntax in templates is as follows:\n *\n *         {{ expression [| filter_name[:parameter_value] ... ] }}\n *\n * @param {String} name Name of the filter function to retrieve\n * @return {Function} the filter function\n * @example\n   <example name=\"$filter\" module=\"filterExample\">\n     <file name=\"index.html\">\n       <div ng-controller=\"MainCtrl\">\n        <h3>{{ originalText }}</h3>\n        <h3>{{ filteredText }}</h3>\n       </div>\n     </file>\n\n     <file name=\"script.js\">\n      angular.module('filterExample', [])\n      .controller('MainCtrl', function($scope, $filter) {\n        $scope.originalText = 'hello';\n        $scope.filteredText = $filter('uppercase')($scope.originalText);\n      });\n     </file>\n   </example>\n  */\n$FilterProvider.$inject = ['$provide'];\nfunction $FilterProvider($provide) {\n  var suffix = 'Filter';\n\n  /**\n   * @ngdoc method\n   * @name $filterProvider#register\n   * @param {string|Object} name Name of the filter function, or an object map of filters where\n   *    the keys are the filter names and the values are the filter factories.\n   * @returns {Object} Registered filter instance, or if a map of filters was provided then a map\n   *    of the registered filter instances.\n   */\n  function register(name, factory) {\n    if (isObject(name)) {\n      var filters = {};\n      forEach(name, function(filter, key) {\n        filters[key] = register(key, filter);\n      });\n      return filters;\n    } else {\n      return $provide.factory(name + suffix, factory);\n    }\n  }\n  this.register = register;\n\n  this.$get = ['$injector', function($injector) {\n    return function(name) {\n      return $injector.get(name + suffix);\n    };\n  }];\n\n  ////////////////////////////////////////\n\n  /* global\n    currencyFilter: false,\n    dateFilter: false,\n    filterFilter: false,\n    jsonFilter: false,\n    limitToFilter: false,\n    lowercaseFilter: false,\n    numberFilter: false,\n    orderByFilter: false,\n    uppercaseFilter: false,\n  */\n\n  register('currency', currencyFilter);\n  register('date', dateFilter);\n  register('filter', filterFilter);\n  register('json', jsonFilter);\n  register('limitTo', limitToFilter);\n  register('lowercase', lowercaseFilter);\n  register('number', numberFilter);\n  register('orderBy', orderByFilter);\n  register('uppercase', uppercaseFilter);\n}\n\n/**\n * @ngdoc filter\n * @name filter\n * @kind function\n *\n * @description\n * Selects a subset of items from `array` and returns it as a new array.\n *\n * @param {Array} array The source array.\n * @param {string|Object|function()} expression The predicate to be used for selecting items from\n *   `array`.\n *\n *   Can be one of:\n *\n *   - `string`: The string is used for matching against the contents of the `array`. All strings or\n *     objects with string properties in `array` that match this string will be returned. This also\n *     applies to nested object properties.\n *     The predicate can be negated by prefixing the string with `!`.\n *\n *   - `Object`: A pattern object can be used to filter specific properties on objects contained\n *     by `array`. For example `{name:\"M\", phone:\"1\"}` predicate will return an array of items\n *     which have property `name` containing \"M\" and property `phone` containing \"1\". A special\n *     property name `$` can be used (as in `{$:\"text\"}`) to accept a match against any\n *     property of the object or its nested object properties. That's equivalent to the simple\n *     substring match with a `string` as described above. The predicate can be negated by prefixing\n *     the string with `!`.\n *     For example `{name: \"!M\"}` predicate will return an array of items which have property `name`\n *     not containing \"M\".\n *\n *     Note that a named property will match properties on the same level only, while the special\n *     `$` property will match properties on the same level or deeper. E.g. an array item like\n *     `{name: {first: 'John', last: 'Doe'}}` will **not** be matched by `{name: 'John'}`, but\n *     **will** be matched by `{$: 'John'}`.\n *\n *   - `function(value, index)`: A predicate function can be used to write arbitrary filters. The\n *     function is called for each element of `array`. The final result is an array of those\n *     elements that the predicate returned true for.\n *\n * @param {function(actual, expected)|true|undefined} comparator Comparator which is used in\n *     determining if the expected value (from the filter expression) and actual value (from\n *     the object in the array) should be considered a match.\n *\n *   Can be one of:\n *\n *   - `function(actual, expected)`:\n *     The function will be given the object value and the predicate value to compare and\n *     should return true if both values should be considered equal.\n *\n *   - `true`: A shorthand for `function(actual, expected) { return angular.equals(actual, expected)}`.\n *     This is essentially strict comparison of expected and actual.\n *\n *   - `false|undefined`: A short hand for a function which will look for a substring match in case\n *     insensitive way.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n       <div ng-init=\"friends = [{name:'John', phone:'555-1276'},\n                                {name:'Mary', phone:'800-BIG-MARY'},\n                                {name:'Mike', phone:'555-4321'},\n                                {name:'Adam', phone:'555-5678'},\n                                {name:'Julie', phone:'555-8765'},\n                                {name:'Juliette', phone:'555-5678'}]\"></div>\n\n       Search: <input ng-model=\"searchText\">\n       <table id=\"searchTextResults\">\n         <tr><th>Name</th><th>Phone</th></tr>\n         <tr ng-repeat=\"friend in friends | filter:searchText\">\n           <td>{{friend.name}}</td>\n           <td>{{friend.phone}}</td>\n         </tr>\n       </table>\n       <hr>\n       Any: <input ng-model=\"search.$\"> <br>\n       Name only <input ng-model=\"search.name\"><br>\n       Phone only <input ng-model=\"search.phone\"><br>\n       Equality <input type=\"checkbox\" ng-model=\"strict\"><br>\n       <table id=\"searchObjResults\">\n         <tr><th>Name</th><th>Phone</th></tr>\n         <tr ng-repeat=\"friendObj in friends | filter:search:strict\">\n           <td>{{friendObj.name}}</td>\n           <td>{{friendObj.phone}}</td>\n         </tr>\n       </table>\n     </file>\n     <file name=\"protractor.js\" type=\"protractor\">\n       var expectFriendNames = function(expectedNames, key) {\n         element.all(by.repeater(key + ' in friends').column(key + '.name')).then(function(arr) {\n           arr.forEach(function(wd, i) {\n             expect(wd.getText()).toMatch(expectedNames[i]);\n           });\n         });\n       };\n\n       it('should search across all fields when filtering with a string', function() {\n         var searchText = element(by.model('searchText'));\n         searchText.clear();\n         searchText.sendKeys('m');\n         expectFriendNames(['Mary', 'Mike', 'Adam'], 'friend');\n\n         searchText.clear();\n         searchText.sendKeys('76');\n         expectFriendNames(['John', 'Julie'], 'friend');\n       });\n\n       it('should search in specific fields when filtering with a predicate object', function() {\n         var searchAny = element(by.model('search.$'));\n         searchAny.clear();\n         searchAny.sendKeys('i');\n         expectFriendNames(['Mary', 'Mike', 'Julie', 'Juliette'], 'friendObj');\n       });\n       it('should use a equal comparison when comparator is true', function() {\n         var searchName = element(by.model('search.name'));\n         var strict = element(by.model('strict'));\n         searchName.clear();\n         searchName.sendKeys('Julie');\n         strict.click();\n         expectFriendNames(['Julie'], 'friendObj');\n       });\n     </file>\n   </example>\n */\nfunction filterFilter() {\n  return function(array, expression, comparator) {\n    if (!isArray(array)) return array;\n\n    var predicateFn;\n    var matchAgainstAnyProp;\n\n    switch (typeof expression) {\n      case 'function':\n        predicateFn = expression;\n        break;\n      case 'boolean':\n      case 'number':\n      case 'string':\n        matchAgainstAnyProp = true;\n        //jshint -W086\n      case 'object':\n        //jshint +W086\n        predicateFn = createPredicateFn(expression, comparator, matchAgainstAnyProp);\n        break;\n      default:\n        return array;\n    }\n\n    return array.filter(predicateFn);\n  };\n}\n\n// Helper functions for `filterFilter`\nfunction createPredicateFn(expression, comparator, matchAgainstAnyProp) {\n  var shouldMatchPrimitives = isObject(expression) && ('$' in expression);\n  var predicateFn;\n\n  if (comparator === true) {\n    comparator = equals;\n  } else if (!isFunction(comparator)) {\n    comparator = function(actual, expected) {\n      if (isObject(actual) || isObject(expected)) {\n        // Prevent an object to be considered equal to a string like `'[object'`\n        return false;\n      }\n\n      actual = lowercase('' + actual);\n      expected = lowercase('' + expected);\n      return actual.indexOf(expected) !== -1;\n    };\n  }\n\n  predicateFn = function(item) {\n    if (shouldMatchPrimitives && !isObject(item)) {\n      return deepCompare(item, expression.$, comparator, false);\n    }\n    return deepCompare(item, expression, comparator, matchAgainstAnyProp);\n  };\n\n  return predicateFn;\n}\n\nfunction deepCompare(actual, expected, comparator, matchAgainstAnyProp, dontMatchWholeObject) {\n  var actualType = typeof actual;\n  var expectedType = typeof expected;\n\n  if ((expectedType === 'string') && (expected.charAt(0) === '!')) {\n    return !deepCompare(actual, expected.substring(1), comparator, matchAgainstAnyProp);\n  } else if (isArray(actual)) {\n    // In case `actual` is an array, consider it a match\n    // if ANY of it's items matches `expected`\n    return actual.some(function(item) {\n      return deepCompare(item, expected, comparator, matchAgainstAnyProp);\n    });\n  }\n\n  switch (actualType) {\n    case 'object':\n      var key;\n      if (matchAgainstAnyProp) {\n        for (key in actual) {\n          if ((key.charAt(0) !== '$') && deepCompare(actual[key], expected, comparator, true)) {\n            return true;\n          }\n        }\n        return dontMatchWholeObject ? false : deepCompare(actual, expected, comparator, false);\n      } else if (expectedType === 'object') {\n        for (key in expected) {\n          var expectedVal = expected[key];\n          if (isFunction(expectedVal)) {\n            continue;\n          }\n\n          var matchAnyProperty = key === '$';\n          var actualVal = matchAnyProperty ? actual : actual[key];\n          if (!deepCompare(actualVal, expectedVal, comparator, matchAnyProperty, matchAnyProperty)) {\n            return false;\n          }\n        }\n        return true;\n      } else {\n        return comparator(actual, expected);\n      }\n      break;\n    case 'function':\n      return false;\n    default:\n      return comparator(actual, expected);\n  }\n}\n\n/**\n * @ngdoc filter\n * @name currency\n * @kind function\n *\n * @description\n * Formats a number as a currency (ie $1,234.56). When no currency symbol is provided, default\n * symbol for current locale is used.\n *\n * @param {number} amount Input to filter.\n * @param {string=} symbol Currency symbol or identifier to be displayed.\n * @param {number=} fractionSize Number of decimal places to round the amount to, defaults to default max fraction size for current locale\n * @returns {string} Formatted number.\n *\n *\n * @example\n   <example module=\"currencyExample\">\n     <file name=\"index.html\">\n       <script>\n         angular.module('currencyExample', [])\n           .controller('ExampleController', ['$scope', function($scope) {\n             $scope.amount = 1234.56;\n           }]);\n       </script>\n       <div ng-controller=\"ExampleController\">\n         <input type=\"number\" ng-model=\"amount\"> <br>\n         default currency symbol ($): <span id=\"currency-default\">{{amount | currency}}</span><br>\n         custom currency identifier (USD$): <span id=\"currency-custom\">{{amount | currency:\"USD$\"}}</span>\n         no fractions (0): <span id=\"currency-no-fractions\">{{amount | currency:\"USD$\":0}}</span>\n       </div>\n     </file>\n     <file name=\"protractor.js\" type=\"protractor\">\n       it('should init with 1234.56', function() {\n         expect(element(by.id('currency-default')).getText()).toBe('$1,234.56');\n         expect(element(by.id('currency-custom')).getText()).toBe('USD$1,234.56');\n         expect(element(by.id('currency-no-fractions')).getText()).toBe('USD$1,235');\n       });\n       it('should update', function() {\n         if (browser.params.browser == 'safari') {\n           // Safari does not understand the minus key. See\n           // https://github.com/angular/protractor/issues/481\n           return;\n         }\n         element(by.model('amount')).clear();\n         element(by.model('amount')).sendKeys('-1234');\n         expect(element(by.id('currency-default')).getText()).toBe('($1,234.00)');\n         expect(element(by.id('currency-custom')).getText()).toBe('(USD$1,234.00)');\n         expect(element(by.id('currency-no-fractions')).getText()).toBe('(USD$1,234)');\n       });\n     </file>\n   </example>\n */\ncurrencyFilter.$inject = ['$locale'];\nfunction currencyFilter($locale) {\n  var formats = $locale.NUMBER_FORMATS;\n  return function(amount, currencySymbol, fractionSize) {\n    if (isUndefined(currencySymbol)) {\n      currencySymbol = formats.CURRENCY_SYM;\n    }\n\n    if (isUndefined(fractionSize)) {\n      fractionSize = formats.PATTERNS[1].maxFrac;\n    }\n\n    // if null or undefined pass it through\n    return (amount == null)\n        ? amount\n        : formatNumber(amount, formats.PATTERNS[1], formats.GROUP_SEP, formats.DECIMAL_SEP, fractionSize).\n            replace(/\\u00A4/g, currencySymbol);\n  };\n}\n\n/**\n * @ngdoc filter\n * @name number\n * @kind function\n *\n * @description\n * Formats a number as text.\n *\n * If the input is not a number an empty string is returned.\n *\n * @param {number|string} number Number to format.\n * @param {(number|string)=} fractionSize Number of decimal places to round the number to.\n * If this is not provided then the fraction size is computed from the current locale's number\n * formatting pattern. In the case of the default locale, it will be 3.\n * @returns {string} Number rounded to decimalPlaces and places a “,” after each third digit.\n *\n * @example\n   <example module=\"numberFilterExample\">\n     <file name=\"index.html\">\n       <script>\n         angular.module('numberFilterExample', [])\n           .controller('ExampleController', ['$scope', function($scope) {\n             $scope.val = 1234.56789;\n           }]);\n       </script>\n       <div ng-controller=\"ExampleController\">\n         Enter number: <input ng-model='val'><br>\n         Default formatting: <span id='number-default'>{{val | number}}</span><br>\n         No fractions: <span>{{val | number:0}}</span><br>\n         Negative number: <span>{{-val | number:4}}</span>\n       </div>\n     </file>\n     <file name=\"protractor.js\" type=\"protractor\">\n       it('should format numbers', function() {\n         expect(element(by.id('number-default')).getText()).toBe('1,234.568');\n         expect(element(by.binding('val | number:0')).getText()).toBe('1,235');\n         expect(element(by.binding('-val | number:4')).getText()).toBe('-1,234.5679');\n       });\n\n       it('should update', function() {\n         element(by.model('val')).clear();\n         element(by.model('val')).sendKeys('3374.333');\n         expect(element(by.id('number-default')).getText()).toBe('3,374.333');\n         expect(element(by.binding('val | number:0')).getText()).toBe('3,374');\n         expect(element(by.binding('-val | number:4')).getText()).toBe('-3,374.3330');\n      });\n     </file>\n   </example>\n */\n\n\nnumberFilter.$inject = ['$locale'];\nfunction numberFilter($locale) {\n  var formats = $locale.NUMBER_FORMATS;\n  return function(number, fractionSize) {\n\n    // if null or undefined pass it through\n    return (number == null)\n        ? number\n        : formatNumber(number, formats.PATTERNS[0], formats.GROUP_SEP, formats.DECIMAL_SEP,\n                       fractionSize);\n  };\n}\n\nvar DECIMAL_SEP = '.';\nfunction formatNumber(number, pattern, groupSep, decimalSep, fractionSize) {\n  if (!isFinite(number) || isObject(number)) return '';\n\n  var isNegative = number < 0;\n  number = Math.abs(number);\n  var numStr = number + '',\n      formatedText = '',\n      parts = [];\n\n  var hasExponent = false;\n  if (numStr.indexOf('e') !== -1) {\n    var match = numStr.match(/([\\d\\.]+)e(-?)(\\d+)/);\n    if (match && match[2] == '-' && match[3] > fractionSize + 1) {\n      number = 0;\n    } else {\n      formatedText = numStr;\n      hasExponent = true;\n    }\n  }\n\n  if (!hasExponent) {\n    var fractionLen = (numStr.split(DECIMAL_SEP)[1] || '').length;\n\n    // determine fractionSize if it is not specified\n    if (isUndefined(fractionSize)) {\n      fractionSize = Math.min(Math.max(pattern.minFrac, fractionLen), pattern.maxFrac);\n    }\n\n    // safely round numbers in JS without hitting imprecisions of floating-point arithmetics\n    // inspired by:\n    // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/round\n    number = +(Math.round(+(number.toString() + 'e' + fractionSize)).toString() + 'e' + -fractionSize);\n\n    var fraction = ('' + number).split(DECIMAL_SEP);\n    var whole = fraction[0];\n    fraction = fraction[1] || '';\n\n    var i, pos = 0,\n        lgroup = pattern.lgSize,\n        group = pattern.gSize;\n\n    if (whole.length >= (lgroup + group)) {\n      pos = whole.length - lgroup;\n      for (i = 0; i < pos; i++) {\n        if ((pos - i) % group === 0 && i !== 0) {\n          formatedText += groupSep;\n        }\n        formatedText += whole.charAt(i);\n      }\n    }\n\n    for (i = pos; i < whole.length; i++) {\n      if ((whole.length - i) % lgroup === 0 && i !== 0) {\n        formatedText += groupSep;\n      }\n      formatedText += whole.charAt(i);\n    }\n\n    // format fraction part.\n    while (fraction.length < fractionSize) {\n      fraction += '0';\n    }\n\n    if (fractionSize && fractionSize !== \"0\") formatedText += decimalSep + fraction.substr(0, fractionSize);\n  } else {\n    if (fractionSize > 0 && number < 1) {\n      formatedText = number.toFixed(fractionSize);\n      number = parseFloat(formatedText);\n    }\n  }\n\n  if (number === 0) {\n    isNegative = false;\n  }\n\n  parts.push(isNegative ? pattern.negPre : pattern.posPre,\n             formatedText,\n             isNegative ? pattern.negSuf : pattern.posSuf);\n  return parts.join('');\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\nfunction dateGetter(name, size, offset, trim) {\n  offset = offset || 0;\n  return function(date) {\n    var value = date['get' + name]();\n    if (offset > 0 || value > -offset)\n      value += offset;\n    if (value === 0 && offset == -12) value = 12;\n    return padNumber(value, size, trim);\n  };\n}\n\nfunction dateStrGetter(name, shortForm) {\n  return function(date, formats) {\n    var value = date['get' + name]();\n    var get = uppercase(shortForm ? ('SHORT' + name) : name);\n\n    return formats[get][value];\n  };\n}\n\nfunction timeZoneGetter(date) {\n  var zone = -1 * date.getTimezoneOffset();\n  var paddedZone = (zone >= 0) ? \"+\" : \"\";\n\n  paddedZone += padNumber(Math[zone > 0 ? 'floor' : 'ceil'](zone / 60), 2) +\n                padNumber(Math.abs(zone % 60), 2);\n\n  return paddedZone;\n}\n\nfunction getFirstThursdayOfYear(year) {\n    // 0 = index of January\n    var dayOfWeekOnFirst = (new Date(year, 0, 1)).getDay();\n    // 4 = index of Thursday (+1 to account for 1st = 5)\n    // 11 = index of *next* Thursday (+1 account for 1st = 12)\n    return new Date(year, 0, ((dayOfWeekOnFirst <= 4) ? 5 : 12) - dayOfWeekOnFirst);\n}\n\nfunction getThursdayThisWeek(datetime) {\n    return new Date(datetime.getFullYear(), datetime.getMonth(),\n      // 4 = index of Thursday\n      datetime.getDate() + (4 - datetime.getDay()));\n}\n\nfunction weekGetter(size) {\n   return function(date) {\n      var firstThurs = getFirstThursdayOfYear(date.getFullYear()),\n         thisThurs = getThursdayThisWeek(date);\n\n      var diff = +thisThurs - +firstThurs,\n         result = 1 + Math.round(diff / 6.048e8); // 6.048e8 ms per week\n\n      return padNumber(result, size);\n   };\n}\n\nfunction ampmGetter(date, formats) {\n  return date.getHours() < 12 ? formats.AMPMS[0] : formats.AMPMS[1];\n}\n\nvar DATE_FORMATS = {\n  yyyy: dateGetter('FullYear', 4),\n    yy: dateGetter('FullYear', 2, 0, true),\n     y: dateGetter('FullYear', 1),\n  MMMM: dateStrGetter('Month'),\n   MMM: dateStrGetter('Month', true),\n    MM: dateGetter('Month', 2, 1),\n     M: dateGetter('Month', 1, 1),\n    dd: dateGetter('Date', 2),\n     d: dateGetter('Date', 1),\n    HH: dateGetter('Hours', 2),\n     H: dateGetter('Hours', 1),\n    hh: dateGetter('Hours', 2, -12),\n     h: dateGetter('Hours', 1, -12),\n    mm: dateGetter('Minutes', 2),\n     m: dateGetter('Minutes', 1),\n    ss: dateGetter('Seconds', 2),\n     s: dateGetter('Seconds', 1),\n     // while ISO 8601 requires fractions to be prefixed with `.` or `,`\n     // we can be just safely rely on using `sss` since we currently don't support single or two digit fractions\n   sss: dateGetter('Milliseconds', 3),\n  EEEE: dateStrGetter('Day'),\n   EEE: dateStrGetter('Day', true),\n     a: ampmGetter,\n     Z: timeZoneGetter,\n    ww: weekGetter(2),\n     w: weekGetter(1)\n};\n\nvar DATE_FORMATS_SPLIT = /((?:[^yMdHhmsaZEw']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+|H+|h+|m+|s+|a|Z|w+))(.*)/,\n    NUMBER_STRING = /^\\-?\\d+$/;\n\n/**\n * @ngdoc filter\n * @name date\n * @kind function\n *\n * @description\n *   Formats `date` to a string based on the requested `format`.\n *\n *   `format` string can be composed of the following elements:\n *\n *   * `'yyyy'`: 4 digit representation of year (e.g. AD 1 => 0001, AD 2010 => 2010)\n *   * `'yy'`: 2 digit representation of year, padded (00-99). (e.g. AD 2001 => 01, AD 2010 => 10)\n *   * `'y'`: 1 digit representation of year, e.g. (AD 1 => 1, AD 199 => 199)\n *   * `'MMMM'`: Month in year (January-December)\n *   * `'MMM'`: Month in year (Jan-Dec)\n *   * `'MM'`: Month in year, padded (01-12)\n *   * `'M'`: Month in year (1-12)\n *   * `'dd'`: Day in month, padded (01-31)\n *   * `'d'`: Day in month (1-31)\n *   * `'EEEE'`: Day in Week,(Sunday-Saturday)\n *   * `'EEE'`: Day in Week, (Sun-Sat)\n *   * `'HH'`: Hour in day, padded (00-23)\n *   * `'H'`: Hour in day (0-23)\n *   * `'hh'`: Hour in AM/PM, padded (01-12)\n *   * `'h'`: Hour in AM/PM, (1-12)\n *   * `'mm'`: Minute in hour, padded (00-59)\n *   * `'m'`: Minute in hour (0-59)\n *   * `'ss'`: Second in minute, padded (00-59)\n *   * `'s'`: Second in minute (0-59)\n *   * `'sss'`: Millisecond in second, padded (000-999)\n *   * `'a'`: AM/PM marker\n *   * `'Z'`: 4 digit (+sign) representation of the timezone offset (-1200-+1200)\n *   * `'ww'`: Week of year, padded (00-53). Week 01 is the week with the first Thursday of the year\n *   * `'w'`: Week of year (0-53). Week 1 is the week with the first Thursday of the year\n *\n *   `format` string can also be one of the following predefined\n *   {@link guide/i18n localizable formats}:\n *\n *   * `'medium'`: equivalent to `'MMM d, y h:mm:ss a'` for en_US locale\n *     (e.g. Sep 3, 2010 12:05:08 PM)\n *   * `'short'`: equivalent to `'M/d/yy h:mm a'` for en_US  locale (e.g. 9/3/10 12:05 PM)\n *   * `'fullDate'`: equivalent to `'EEEE, MMMM d, y'` for en_US  locale\n *     (e.g. Friday, September 3, 2010)\n *   * `'longDate'`: equivalent to `'MMMM d, y'` for en_US  locale (e.g. September 3, 2010)\n *   * `'mediumDate'`: equivalent to `'MMM d, y'` for en_US  locale (e.g. Sep 3, 2010)\n *   * `'shortDate'`: equivalent to `'M/d/yy'` for en_US locale (e.g. 9/3/10)\n *   * `'mediumTime'`: equivalent to `'h:mm:ss a'` for en_US locale (e.g. 12:05:08 PM)\n *   * `'shortTime'`: equivalent to `'h:mm a'` for en_US locale (e.g. 12:05 PM)\n *\n *   `format` string can contain literal values. These need to be escaped by surrounding with single quotes (e.g.\n *   `\"h 'in the morning'\"`). In order to output a single quote, escape it - i.e., two single quotes in a sequence\n *   (e.g. `\"h 'o''clock'\"`).\n *\n * @param {(Date|number|string)} date Date to format either as Date object, milliseconds (string or\n *    number) or various ISO 8601 datetime string formats (e.g. yyyy-MM-ddTHH:mm:ss.sssZ and its\n *    shorter versions like yyyy-MM-ddTHH:mmZ, yyyy-MM-dd or yyyyMMddTHHmmssZ). If no timezone is\n *    specified in the string input, the time is considered to be in the local timezone.\n * @param {string=} format Formatting rules (see Description). If not specified,\n *    `mediumDate` is used.\n * @param {string=} timezone Timezone to be used for formatting. Right now, only `'UTC'` is supported.\n *    If not specified, the timezone of the browser will be used.\n * @returns {string} Formatted string or the input if input is not recognized as date/millis.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n       <span ng-non-bindable>{{1288323623006 | date:'medium'}}</span>:\n           <span>{{1288323623006 | date:'medium'}}</span><br>\n       <span ng-non-bindable>{{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}</span>:\n          <span>{{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}</span><br>\n       <span ng-non-bindable>{{1288323623006 | date:'MM/dd/yyyy @ h:mma'}}</span>:\n          <span>{{'1288323623006' | date:'MM/dd/yyyy @ h:mma'}}</span><br>\n       <span ng-non-bindable>{{1288323623006 | date:\"MM/dd/yyyy 'at' h:mma\"}}</span>:\n          <span>{{'1288323623006' | date:\"MM/dd/yyyy 'at' h:mma\"}}</span><br>\n     </file>\n     <file name=\"protractor.js\" type=\"protractor\">\n       it('should format date', function() {\n         expect(element(by.binding(\"1288323623006 | date:'medium'\")).getText()).\n            toMatch(/Oct 2\\d, 2010 \\d{1,2}:\\d{2}:\\d{2} (AM|PM)/);\n         expect(element(by.binding(\"1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'\")).getText()).\n            toMatch(/2010\\-10\\-2\\d \\d{2}:\\d{2}:\\d{2} (\\-|\\+)?\\d{4}/);\n         expect(element(by.binding(\"'1288323623006' | date:'MM/dd/yyyy @ h:mma'\")).getText()).\n            toMatch(/10\\/2\\d\\/2010 @ \\d{1,2}:\\d{2}(AM|PM)/);\n         expect(element(by.binding(\"'1288323623006' | date:\\\"MM/dd/yyyy 'at' h:mma\\\"\")).getText()).\n            toMatch(/10\\/2\\d\\/2010 at \\d{1,2}:\\d{2}(AM|PM)/);\n       });\n     </file>\n   </example>\n */\ndateFilter.$inject = ['$locale'];\nfunction dateFilter($locale) {\n\n\n  var R_ISO8601_STR = /^(\\d{4})-?(\\d\\d)-?(\\d\\d)(?:T(\\d\\d)(?::?(\\d\\d)(?::?(\\d\\d)(?:\\.(\\d+))?)?)?(Z|([+-])(\\d\\d):?(\\d\\d))?)?$/;\n                     // 1        2       3         4          5          6          7          8  9     10      11\n  function jsonStringToDate(string) {\n    var match;\n    if (match = string.match(R_ISO8601_STR)) {\n      var date = new Date(0),\n          tzHour = 0,\n          tzMin  = 0,\n          dateSetter = match[8] ? date.setUTCFullYear : date.setFullYear,\n          timeSetter = match[8] ? date.setUTCHours : date.setHours;\n\n      if (match[9]) {\n        tzHour = int(match[9] + match[10]);\n        tzMin = int(match[9] + match[11]);\n      }\n      dateSetter.call(date, int(match[1]), int(match[2]) - 1, int(match[3]));\n      var h = int(match[4] || 0) - tzHour;\n      var m = int(match[5] || 0) - tzMin;\n      var s = int(match[6] || 0);\n      var ms = Math.round(parseFloat('0.' + (match[7] || 0)) * 1000);\n      timeSetter.call(date, h, m, s, ms);\n      return date;\n    }\n    return string;\n  }\n\n\n  return function(date, format, timezone) {\n    var text = '',\n        parts = [],\n        fn, match;\n\n    format = format || 'mediumDate';\n    format = $locale.DATETIME_FORMATS[format] || format;\n    if (isString(date)) {\n      date = NUMBER_STRING.test(date) ? int(date) : jsonStringToDate(date);\n    }\n\n    if (isNumber(date)) {\n      date = new Date(date);\n    }\n\n    if (!isDate(date)) {\n      return date;\n    }\n\n    while (format) {\n      match = DATE_FORMATS_SPLIT.exec(format);\n      if (match) {\n        parts = concat(parts, match, 1);\n        format = parts.pop();\n      } else {\n        parts.push(format);\n        format = null;\n      }\n    }\n\n    if (timezone && timezone === 'UTC') {\n      date = new Date(date.getTime());\n      date.setMinutes(date.getMinutes() + date.getTimezoneOffset());\n    }\n    forEach(parts, function(value) {\n      fn = DATE_FORMATS[value];\n      text += fn ? fn(date, $locale.DATETIME_FORMATS)\n                 : value.replace(/(^'|'$)/g, '').replace(/''/g, \"'\");\n    });\n\n    return text;\n  };\n}\n\n\n/**\n * @ngdoc filter\n * @name json\n * @kind function\n *\n * @description\n *   Allows you to convert a JavaScript object into JSON string.\n *\n *   This filter is mostly useful for debugging. When using the double curly {{value}} notation\n *   the binding is automatically converted to JSON.\n *\n * @param {*} object Any JavaScript object (including arrays and primitive types) to filter.\n * @param {number=} spacing The number of spaces to use per indentation, defaults to 2.\n * @returns {string} JSON string.\n *\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n       <pre id=\"default-spacing\">{{ {'name':'value'} | json }}</pre>\n       <pre id=\"custom-spacing\">{{ {'name':'value'} | json:4 }}</pre>\n     </file>\n     <file name=\"protractor.js\" type=\"protractor\">\n       it('should jsonify filtered objects', function() {\n         expect(element(by.id('default-spacing')).getText()).toMatch(/\\{\\n  \"name\": ?\"value\"\\n}/);\n         expect(element(by.id('custom-spacing')).getText()).toMatch(/\\{\\n    \"name\": ?\"value\"\\n}/);\n       });\n     </file>\n   </example>\n *\n */\nfunction jsonFilter() {\n  return function(object, spacing) {\n    if (isUndefined(spacing)) {\n        spacing = 2;\n    }\n    return toJson(object, spacing);\n  };\n}\n\n\n/**\n * @ngdoc filter\n * @name lowercase\n * @kind function\n * @description\n * Converts string to lowercase.\n * @see angular.lowercase\n */\nvar lowercaseFilter = valueFn(lowercase);\n\n\n/**\n * @ngdoc filter\n * @name uppercase\n * @kind function\n * @description\n * Converts string to uppercase.\n * @see angular.uppercase\n */\nvar uppercaseFilter = valueFn(uppercase);\n\n/**\n * @ngdoc filter\n * @name limitTo\n * @kind function\n *\n * @description\n * Creates a new array or string containing only a specified number of elements. The elements\n * are taken from either the beginning or the end of the source array, string or number, as specified by\n * the value and sign (positive or negative) of `limit`. If a number is used as input, it is\n * converted to a string.\n *\n * @param {Array|string|number} input Source array, string or number to be limited.\n * @param {string|number} limit The length of the returned array or string. If the `limit` number\n *     is positive, `limit` number of items from the beginning of the source array/string are copied.\n *     If the number is negative, `limit` number  of items from the end of the source array/string\n *     are copied. The `limit` will be trimmed if it exceeds `array.length`\n * @returns {Array|string} A new sub-array or substring of length `limit` or less if input array\n *     had less than `limit` elements.\n *\n * @example\n   <example module=\"limitToExample\">\n     <file name=\"index.html\">\n       <script>\n         angular.module('limitToExample', [])\n           .controller('ExampleController', ['$scope', function($scope) {\n             $scope.numbers = [1,2,3,4,5,6,7,8,9];\n             $scope.letters = \"abcdefghi\";\n             $scope.longNumber = 2345432342;\n             $scope.numLimit = 3;\n             $scope.letterLimit = 3;\n             $scope.longNumberLimit = 3;\n           }]);\n       </script>\n       <div ng-controller=\"ExampleController\">\n         Limit {{numbers}} to: <input type=\"number\" step=\"1\" ng-model=\"numLimit\">\n         <p>Output numbers: {{ numbers | limitTo:numLimit }}</p>\n         Limit {{letters}} to: <input type=\"number\" step=\"1\" ng-model=\"letterLimit\">\n         <p>Output letters: {{ letters | limitTo:letterLimit }}</p>\n         Limit {{longNumber}} to: <input type=\"number\" step=\"1\" ng-model=\"longNumberLimit\">\n         <p>Output long number: {{ longNumber | limitTo:longNumberLimit }}</p>\n       </div>\n     </file>\n     <file name=\"protractor.js\" type=\"protractor\">\n       var numLimitInput = element(by.model('numLimit'));\n       var letterLimitInput = element(by.model('letterLimit'));\n       var longNumberLimitInput = element(by.model('longNumberLimit'));\n       var limitedNumbers = element(by.binding('numbers | limitTo:numLimit'));\n       var limitedLetters = element(by.binding('letters | limitTo:letterLimit'));\n       var limitedLongNumber = element(by.binding('longNumber | limitTo:longNumberLimit'));\n\n       it('should limit the number array to first three items', function() {\n         expect(numLimitInput.getAttribute('value')).toBe('3');\n         expect(letterLimitInput.getAttribute('value')).toBe('3');\n         expect(longNumberLimitInput.getAttribute('value')).toBe('3');\n         expect(limitedNumbers.getText()).toEqual('Output numbers: [1,2,3]');\n         expect(limitedLetters.getText()).toEqual('Output letters: abc');\n         expect(limitedLongNumber.getText()).toEqual('Output long number: 234');\n       });\n\n       // There is a bug in safari and protractor that doesn't like the minus key\n       // it('should update the output when -3 is entered', function() {\n       //   numLimitInput.clear();\n       //   numLimitInput.sendKeys('-3');\n       //   letterLimitInput.clear();\n       //   letterLimitInput.sendKeys('-3');\n       //   longNumberLimitInput.clear();\n       //   longNumberLimitInput.sendKeys('-3');\n       //   expect(limitedNumbers.getText()).toEqual('Output numbers: [7,8,9]');\n       //   expect(limitedLetters.getText()).toEqual('Output letters: ghi');\n       //   expect(limitedLongNumber.getText()).toEqual('Output long number: 342');\n       // });\n\n       it('should not exceed the maximum size of input array', function() {\n         numLimitInput.clear();\n         numLimitInput.sendKeys('100');\n         letterLimitInput.clear();\n         letterLimitInput.sendKeys('100');\n         longNumberLimitInput.clear();\n         longNumberLimitInput.sendKeys('100');\n         expect(limitedNumbers.getText()).toEqual('Output numbers: [1,2,3,4,5,6,7,8,9]');\n         expect(limitedLetters.getText()).toEqual('Output letters: abcdefghi');\n         expect(limitedLongNumber.getText()).toEqual('Output long number: 2345432342');\n       });\n     </file>\n   </example>\n*/\nfunction limitToFilter() {\n  return function(input, limit) {\n    if (isNumber(input)) input = input.toString();\n    if (!isArray(input) && !isString(input)) return input;\n\n    if (Math.abs(Number(limit)) === Infinity) {\n      limit = Number(limit);\n    } else {\n      limit = int(limit);\n    }\n\n    //NaN check on limit\n    if (limit) {\n      return limit > 0 ? input.slice(0, limit) : input.slice(limit);\n    } else {\n      return isString(input) ? \"\" : [];\n    }\n  };\n}\n\n/**\n * @ngdoc filter\n * @name orderBy\n * @kind function\n *\n * @description\n * Orders a specified `array` by the `expression` predicate. It is ordered alphabetically\n * for strings and numerically for numbers. Note: if you notice numbers are not being sorted\n * correctly, make sure they are actually being saved as numbers and not strings.\n *\n * @param {Array} array The array to sort.\n * @param {function(*)|string|Array.<(function(*)|string)>=} expression A predicate to be\n *    used by the comparator to determine the order of elements.\n *\n *    Can be one of:\n *\n *    - `function`: Getter function. The result of this function will be sorted using the\n *      `<`, `=`, `>` operator.\n *    - `string`: An Angular expression. The result of this expression is used to compare elements\n *      (for example `name` to sort by a property called `name` or `name.substr(0, 3)` to sort by\n *      3 first characters of a property called `name`). The result of a constant expression\n *      is interpreted as a property name to be used in comparisons (for example `\"special name\"`\n *      to sort object by the value of their `special name` property). An expression can be\n *      optionally prefixed with `+` or `-` to control ascending or descending sort order\n *      (for example, `+name` or `-name`). If no property is provided, (e.g. `'+'`) then the array\n *      element itself is used to compare where sorting.\n *    - `Array`: An array of function or string predicates. The first predicate in the array\n *      is used for sorting, but when two items are equivalent, the next predicate is used.\n *\n *    If the predicate is missing or empty then it defaults to `'+'`.\n *\n * @param {boolean=} reverse Reverse the order of the array.\n * @returns {Array} Sorted copy of the source array.\n *\n * @example\n   <example module=\"orderByExample\">\n     <file name=\"index.html\">\n       <script>\n         angular.module('orderByExample', [])\n           .controller('ExampleController', ['$scope', function($scope) {\n             $scope.friends =\n                 [{name:'John', phone:'555-1212', age:10},\n                  {name:'Mary', phone:'555-9876', age:19},\n                  {name:'Mike', phone:'555-4321', age:21},\n                  {name:'Adam', phone:'555-5678', age:35},\n                  {name:'Julie', phone:'555-8765', age:29}];\n             $scope.predicate = '-age';\n           }]);\n       </script>\n       <div ng-controller=\"ExampleController\">\n         <pre>Sorting predicate = {{predicate}}; reverse = {{reverse}}</pre>\n         <hr/>\n         [ <a href=\"\" ng-click=\"predicate=''\">unsorted</a> ]\n         <table class=\"friend\">\n           <tr>\n             <th><a href=\"\" ng-click=\"predicate = 'name'; reverse=false\">Name</a>\n                 (<a href=\"\" ng-click=\"predicate = '-name'; reverse=false\">^</a>)</th>\n             <th><a href=\"\" ng-click=\"predicate = 'phone'; reverse=!reverse\">Phone Number</a></th>\n             <th><a href=\"\" ng-click=\"predicate = 'age'; reverse=!reverse\">Age</a></th>\n           </tr>\n           <tr ng-repeat=\"friend in friends | orderBy:predicate:reverse\">\n             <td>{{friend.name}}</td>\n             <td>{{friend.phone}}</td>\n             <td>{{friend.age}}</td>\n           </tr>\n         </table>\n       </div>\n     </file>\n   </example>\n *\n * It's also possible to call the orderBy filter manually, by injecting `$filter`, retrieving the\n * filter routine with `$filter('orderBy')`, and calling the returned filter routine with the\n * desired parameters.\n *\n * Example:\n *\n * @example\n  <example module=\"orderByExample\">\n    <file name=\"index.html\">\n      <div ng-controller=\"ExampleController\">\n        <table class=\"friend\">\n          <tr>\n            <th><a href=\"\" ng-click=\"reverse=false;order('name', false)\">Name</a>\n              (<a href=\"\" ng-click=\"order('-name',false)\">^</a>)</th>\n            <th><a href=\"\" ng-click=\"reverse=!reverse;order('phone', reverse)\">Phone Number</a></th>\n            <th><a href=\"\" ng-click=\"reverse=!reverse;order('age',reverse)\">Age</a></th>\n          </tr>\n          <tr ng-repeat=\"friend in friends\">\n            <td>{{friend.name}}</td>\n            <td>{{friend.phone}}</td>\n            <td>{{friend.age}}</td>\n          </tr>\n        </table>\n      </div>\n    </file>\n\n    <file name=\"script.js\">\n      angular.module('orderByExample', [])\n        .controller('ExampleController', ['$scope', '$filter', function($scope, $filter) {\n          var orderBy = $filter('orderBy');\n          $scope.friends = [\n            { name: 'John',    phone: '555-1212',    age: 10 },\n            { name: 'Mary',    phone: '555-9876',    age: 19 },\n            { name: 'Mike',    phone: '555-4321',    age: 21 },\n            { name: 'Adam',    phone: '555-5678',    age: 35 },\n            { name: 'Julie',   phone: '555-8765',    age: 29 }\n          ];\n          $scope.order = function(predicate, reverse) {\n            $scope.friends = orderBy($scope.friends, predicate, reverse);\n          };\n          $scope.order('-age',false);\n        }]);\n    </file>\n</example>\n */\norderByFilter.$inject = ['$parse'];\nfunction orderByFilter($parse) {\n  return function(array, sortPredicate, reverseOrder) {\n    if (!(isArrayLike(array))) return array;\n    sortPredicate = isArray(sortPredicate) ? sortPredicate : [sortPredicate];\n    if (sortPredicate.length === 0) { sortPredicate = ['+']; }\n    sortPredicate = sortPredicate.map(function(predicate) {\n      var descending = false, get = predicate || identity;\n      if (isString(predicate)) {\n        if ((predicate.charAt(0) == '+' || predicate.charAt(0) == '-')) {\n          descending = predicate.charAt(0) == '-';\n          predicate = predicate.substring(1);\n        }\n        if (predicate === '') {\n          // Effectively no predicate was passed so we compare identity\n          return reverseComparator(compare, descending);\n        }\n        get = $parse(predicate);\n        if (get.constant) {\n          var key = get();\n          return reverseComparator(function(a, b) {\n            return compare(a[key], b[key]);\n          }, descending);\n        }\n      }\n      return reverseComparator(function(a, b) {\n        return compare(get(a),get(b));\n      }, descending);\n    });\n    return slice.call(array).sort(reverseComparator(comparator, reverseOrder));\n\n    function comparator(o1, o2) {\n      for (var i = 0; i < sortPredicate.length; i++) {\n        var comp = sortPredicate[i](o1, o2);\n        if (comp !== 0) return comp;\n      }\n      return 0;\n    }\n    function reverseComparator(comp, descending) {\n      return descending\n          ? function(a, b) {return comp(b,a);}\n          : comp;\n    }\n\n    function isPrimitive(value) {\n      switch (typeof value) {\n        case 'number': /* falls through */\n        case 'boolean': /* falls through */\n        case 'string':\n          return true;\n        default:\n          return false;\n      }\n    }\n\n    function objectToString(value) {\n      if (value === null) return 'null';\n      if (typeof value.valueOf === 'function') {\n        value = value.valueOf();\n        if (isPrimitive(value)) return value;\n      }\n      if (typeof value.toString === 'function') {\n        value = value.toString();\n        if (isPrimitive(value)) return value;\n      }\n      return '';\n    }\n\n    function compare(v1, v2) {\n      var t1 = typeof v1;\n      var t2 = typeof v2;\n      if (t1 === t2 && t1 === \"object\") {\n        v1 = objectToString(v1);\n        v2 = objectToString(v2);\n      }\n      if (t1 === t2) {\n        if (t1 === \"string\") {\n           v1 = v1.toLowerCase();\n           v2 = v2.toLowerCase();\n        }\n        if (v1 === v2) return 0;\n        return v1 < v2 ? -1 : 1;\n      } else {\n        return t1 < t2 ? -1 : 1;\n      }\n    }\n  };\n}\n\nfunction ngDirective(directive) {\n  if (isFunction(directive)) {\n    directive = {\n      link: directive\n    };\n  }\n  directive.restrict = directive.restrict || 'AC';\n  return valueFn(directive);\n}\n\n/**\n * @ngdoc directive\n * @name a\n * @restrict E\n *\n * @description\n * Modifies the default behavior of the html A tag so that the default action is prevented when\n * the href attribute is empty.\n *\n * This change permits the easy creation of action links with the `ngClick` directive\n * without changing the location or causing page reloads, e.g.:\n * `<a href=\"\" ng-click=\"list.addItem()\">Add Item</a>`\n */\nvar htmlAnchorDirective = valueFn({\n  restrict: 'E',\n  compile: function(element, attr) {\n    if (!attr.href && !attr.xlinkHref && !attr.name) {\n      return function(scope, element) {\n        // If the linked element is not an anchor tag anymore, do nothing\n        if (element[0].nodeName.toLowerCase() !== 'a') return;\n\n        // SVGAElement does not use the href attribute, but rather the 'xlinkHref' attribute.\n        var href = toString.call(element.prop('href')) === '[object SVGAnimatedString]' ?\n                   'xlink:href' : 'href';\n        element.on('click', function(event) {\n          // if we have no href url, then don't navigate anywhere.\n          if (!element.attr(href)) {\n            event.preventDefault();\n          }\n        });\n      };\n    }\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ngHref\n * @restrict A\n * @priority 99\n *\n * @description\n * Using Angular markup like `{{hash}}` in an href attribute will\n * make the link go to the wrong URL if the user clicks it before\n * Angular has a chance to replace the `{{hash}}` markup with its\n * value. Until Angular replaces the markup the link will be broken\n * and will most likely return a 404 error. The `ngHref` directive\n * solves this problem.\n *\n * The wrong way to write it:\n * ```html\n * <a href=\"http://www.gravatar.com/avatar/{{hash}}\">link1</a>\n * ```\n *\n * The correct way to write it:\n * ```html\n * <a ng-href=\"http://www.gravatar.com/avatar/{{hash}}\">link1</a>\n * ```\n *\n * @element A\n * @param {template} ngHref any string which can contain `{{}}` markup.\n *\n * @example\n * This example shows various combinations of `href`, `ng-href` and `ng-click` attributes\n * in links and their different behaviors:\n    <example>\n      <file name=\"index.html\">\n        <input ng-model=\"value\" /><br />\n        <a id=\"link-1\" href ng-click=\"value = 1\">link 1</a> (link, don't reload)<br />\n        <a id=\"link-2\" href=\"\" ng-click=\"value = 2\">link 2</a> (link, don't reload)<br />\n        <a id=\"link-3\" ng-href=\"/{{'123'}}\">link 3</a> (link, reload!)<br />\n        <a id=\"link-4\" href=\"\" name=\"xx\" ng-click=\"value = 4\">anchor</a> (link, don't reload)<br />\n        <a id=\"link-5\" name=\"xxx\" ng-click=\"value = 5\">anchor</a> (no link)<br />\n        <a id=\"link-6\" ng-href=\"{{value}}\">link</a> (link, change location)\n      </file>\n      <file name=\"protractor.js\" type=\"protractor\">\n        it('should execute ng-click but not reload when href without value', function() {\n          element(by.id('link-1')).click();\n          expect(element(by.model('value')).getAttribute('value')).toEqual('1');\n          expect(element(by.id('link-1')).getAttribute('href')).toBe('');\n        });\n\n        it('should execute ng-click but not reload when href empty string', function() {\n          element(by.id('link-2')).click();\n          expect(element(by.model('value')).getAttribute('value')).toEqual('2');\n          expect(element(by.id('link-2')).getAttribute('href')).toBe('');\n        });\n\n        it('should execute ng-click and change url when ng-href specified', function() {\n          expect(element(by.id('link-3')).getAttribute('href')).toMatch(/\\/123$/);\n\n          element(by.id('link-3')).click();\n\n          // At this point, we navigate away from an Angular page, so we need\n          // to use browser.driver to get the base webdriver.\n\n          browser.wait(function() {\n            return browser.driver.getCurrentUrl().then(function(url) {\n              return url.match(/\\/123$/);\n            });\n          }, 5000, 'page should navigate to /123');\n        });\n\n        xit('should execute ng-click but not reload when href empty string and name specified', function() {\n          element(by.id('link-4')).click();\n          expect(element(by.model('value')).getAttribute('value')).toEqual('4');\n          expect(element(by.id('link-4')).getAttribute('href')).toBe('');\n        });\n\n        it('should execute ng-click but not reload when no href but name specified', function() {\n          element(by.id('link-5')).click();\n          expect(element(by.model('value')).getAttribute('value')).toEqual('5');\n          expect(element(by.id('link-5')).getAttribute('href')).toBe(null);\n        });\n\n        it('should only change url when only ng-href', function() {\n          element(by.model('value')).clear();\n          element(by.model('value')).sendKeys('6');\n          expect(element(by.id('link-6')).getAttribute('href')).toMatch(/\\/6$/);\n\n          element(by.id('link-6')).click();\n\n          // At this point, we navigate away from an Angular page, so we need\n          // to use browser.driver to get the base webdriver.\n          browser.wait(function() {\n            return browser.driver.getCurrentUrl().then(function(url) {\n              return url.match(/\\/6$/);\n            });\n          }, 5000, 'page should navigate to /6');\n        });\n      </file>\n    </example>\n */\n\n/**\n * @ngdoc directive\n * @name ngSrc\n * @restrict A\n * @priority 99\n *\n * @description\n * Using Angular markup like `{{hash}}` in a `src` attribute doesn't\n * work right: The browser will fetch from the URL with the literal\n * text `{{hash}}` until Angular replaces the expression inside\n * `{{hash}}`. The `ngSrc` directive solves this problem.\n *\n * The buggy way to write it:\n * ```html\n * <img src=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * ```\n *\n * The correct way to write it:\n * ```html\n * <img ng-src=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * ```\n *\n * @element IMG\n * @param {template} ngSrc any string which can contain `{{}}` markup.\n */\n\n/**\n * @ngdoc directive\n * @name ngSrcset\n * @restrict A\n * @priority 99\n *\n * @description\n * Using Angular markup like `{{hash}}` in a `srcset` attribute doesn't\n * work right: The browser will fetch from the URL with the literal\n * text `{{hash}}` until Angular replaces the expression inside\n * `{{hash}}`. The `ngSrcset` directive solves this problem.\n *\n * The buggy way to write it:\n * ```html\n * <img srcset=\"http://www.gravatar.com/avatar/{{hash}} 2x\"/>\n * ```\n *\n * The correct way to write it:\n * ```html\n * <img ng-srcset=\"http://www.gravatar.com/avatar/{{hash}} 2x\"/>\n * ```\n *\n * @element IMG\n * @param {template} ngSrcset any string which can contain `{{}}` markup.\n */\n\n/**\n * @ngdoc directive\n * @name ngDisabled\n * @restrict A\n * @priority 100\n *\n * @description\n *\n * We shouldn't do this, because it will make the button enabled on Chrome/Firefox but not on IE8 and older IEs:\n * ```html\n * <div ng-init=\"scope = { isDisabled: false }\">\n *  <button disabled=\"{{scope.isDisabled}}\">Disabled</button>\n * </div>\n * ```\n *\n * The HTML specification does not require browsers to preserve the values of boolean attributes\n * such as disabled. (Their presence means true and their absence means false.)\n * If we put an Angular interpolation expression into such an attribute then the\n * binding information would be lost when the browser removes the attribute.\n * The `ngDisabled` directive solves this problem for the `disabled` attribute.\n * This complementary directive is not removed by the browser and so provides\n * a permanent reliable place to store the binding information.\n *\n * @example\n    <example>\n      <file name=\"index.html\">\n        Click me to toggle: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        <button ng-model=\"button\" ng-disabled=\"checked\">Button</button>\n      </file>\n      <file name=\"protractor.js\" type=\"protractor\">\n        it('should toggle button', function() {\n          expect(element(by.css('button')).getAttribute('disabled')).toBeFalsy();\n          element(by.model('checked')).click();\n          expect(element(by.css('button')).getAttribute('disabled')).toBeTruthy();\n        });\n      </file>\n    </example>\n *\n * @element INPUT\n * @param {expression} ngDisabled If the {@link guide/expression expression} is truthy,\n *     then special attribute \"disabled\" will be set on the element\n */\n\n\n/**\n * @ngdoc directive\n * @name ngChecked\n * @restrict A\n * @priority 100\n *\n * @description\n * The HTML specification does not require browsers to preserve the values of boolean attributes\n * such as checked. (Their presence means true and their absence means false.)\n * If we put an Angular interpolation expression into such an attribute then the\n * binding information would be lost when the browser removes the attribute.\n * The `ngChecked` directive solves this problem for the `checked` attribute.\n * This complementary directive is not removed by the browser and so provides\n * a permanent reliable place to store the binding information.\n * @example\n    <example>\n      <file name=\"index.html\">\n        Check me to check both: <input type=\"checkbox\" ng-model=\"master\"><br/>\n        <input id=\"checkSlave\" type=\"checkbox\" ng-checked=\"master\">\n      </file>\n      <file name=\"protractor.js\" type=\"protractor\">\n        it('should check both checkBoxes', function() {\n          expect(element(by.id('checkSlave')).getAttribute('checked')).toBeFalsy();\n          element(by.model('master')).click();\n          expect(element(by.id('checkSlave')).getAttribute('checked')).toBeTruthy();\n        });\n      </file>\n    </example>\n *\n * @element INPUT\n * @param {expression} ngChecked If the {@link guide/expression expression} is truthy,\n *     then special attribute \"checked\" will be set on the element\n */\n\n\n/**\n * @ngdoc directive\n * @name ngReadonly\n * @restrict A\n * @priority 100\n *\n * @description\n * The HTML specification does not require browsers to preserve the values of boolean attributes\n * such as readonly. (Their presence means true and their absence means false.)\n * If we put an Angular interpolation expression into such an attribute then the\n * binding information would be lost when the browser removes the attribute.\n * The `ngReadonly` directive solves this problem for the `readonly` attribute.\n * This complementary directive is not removed by the browser and so provides\n * a permanent reliable place to store the binding information.\n * @example\n    <example>\n      <file name=\"index.html\">\n        Check me to make text readonly: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        <input type=\"text\" ng-readonly=\"checked\" value=\"I'm Angular\"/>\n      </file>\n      <file name=\"protractor.js\" type=\"protractor\">\n        it('should toggle readonly attr', function() {\n          expect(element(by.css('[type=\"text\"]')).getAttribute('readonly')).toBeFalsy();\n          element(by.model('checked')).click();\n          expect(element(by.css('[type=\"text\"]')).getAttribute('readonly')).toBeTruthy();\n        });\n      </file>\n    </example>\n *\n * @element INPUT\n * @param {expression} ngReadonly If the {@link guide/expression expression} is truthy,\n *     then special attribute \"readonly\" will be set on the element\n */\n\n\n/**\n * @ngdoc directive\n * @name ngSelected\n * @restrict A\n * @priority 100\n *\n * @description\n * The HTML specification does not require browsers to preserve the values of boolean attributes\n * such as selected. (Their presence means true and their absence means false.)\n * If we put an Angular interpolation expression into such an attribute then the\n * binding information would be lost when the browser removes the attribute.\n * The `ngSelected` directive solves this problem for the `selected` attribute.\n * This complementary directive is not removed by the browser and so provides\n * a permanent reliable place to store the binding information.\n *\n * @example\n    <example>\n      <file name=\"index.html\">\n        Check me to select: <input type=\"checkbox\" ng-model=\"selected\"><br/>\n        <select>\n          <option>Hello!</option>\n          <option id=\"greet\" ng-selected=\"selected\">Greetings!</option>\n        </select>\n      </file>\n      <file name=\"protractor.js\" type=\"protractor\">\n        it('should select Greetings!', function() {\n          expect(element(by.id('greet')).getAttribute('selected')).toBeFalsy();\n          element(by.model('selected')).click();\n          expect(element(by.id('greet')).getAttribute('selected')).toBeTruthy();\n        });\n      </file>\n    </example>\n *\n * @element OPTION\n * @param {expression} ngSelected If the {@link guide/expression expression} is truthy,\n *     then special attribute \"selected\" will be set on the element\n */\n\n/**\n * @ngdoc directive\n * @name ngOpen\n * @restrict A\n * @priority 100\n *\n * @description\n * The HTML specification does not require browsers to preserve the values of boolean attributes\n * such as open. (Their presence means true and their absence means false.)\n * If we put an Angular interpolation expression into such an attribute then the\n * binding information would be lost when the browser removes the attribute.\n * The `ngOpen` directive solves this problem for the `open` attribute.\n * This complementary directive is not removed by the browser and so provides\n * a permanent reliable place to store the binding information.\n * @example\n     <example>\n       <file name=\"index.html\">\n         Check me check multiple: <input type=\"checkbox\" ng-model=\"open\"><br/>\n         <details id=\"details\" ng-open=\"open\">\n            <summary>Show/Hide me</summary>\n         </details>\n       </file>\n       <file name=\"protractor.js\" type=\"protractor\">\n         it('should toggle open', function() {\n           expect(element(by.id('details')).getAttribute('open')).toBeFalsy();\n           element(by.model('open')).click();\n           expect(element(by.id('details')).getAttribute('open')).toBeTruthy();\n         });\n       </file>\n     </example>\n *\n * @element DETAILS\n * @param {expression} ngOpen If the {@link guide/expression expression} is truthy,\n *     then special attribute \"open\" will be set on the element\n */\n\nvar ngAttributeAliasDirectives = {};\n\n\n// boolean attrs are evaluated\nforEach(BOOLEAN_ATTR, function(propName, attrName) {\n  // binding to multiple is not supported\n  if (propName == \"multiple\") return;\n\n  var normalized = directiveNormalize('ng-' + attrName);\n  ngAttributeAliasDirectives[normalized] = function() {\n    return {\n      restrict: 'A',\n      priority: 100,\n      link: function(scope, element, attr) {\n        scope.$watch(attr[normalized], function ngBooleanAttrWatchAction(value) {\n          attr.$set(attrName, !!value);\n        });\n      }\n    };\n  };\n});\n\n// aliased input attrs are evaluated\nforEach(ALIASED_ATTR, function(htmlAttr, ngAttr) {\n  ngAttributeAliasDirectives[ngAttr] = function() {\n    return {\n      priority: 100,\n      link: function(scope, element, attr) {\n        //special case ngPattern when a literal regular expression value\n        //is used as the expression (this way we don't have to watch anything).\n        if (ngAttr === \"ngPattern\" && attr.ngPattern.charAt(0) == \"/\") {\n          var match = attr.ngPattern.match(REGEX_STRING_REGEXP);\n          if (match) {\n            attr.$set(\"ngPattern\", new RegExp(match[1], match[2]));\n            return;\n          }\n        }\n\n        scope.$watch(attr[ngAttr], function ngAttrAliasWatchAction(value) {\n          attr.$set(ngAttr, value);\n        });\n      }\n    };\n  };\n});\n\n// ng-src, ng-srcset, ng-href are interpolated\nforEach(['src', 'srcset', 'href'], function(attrName) {\n  var normalized = directiveNormalize('ng-' + attrName);\n  ngAttributeAliasDirectives[normalized] = function() {\n    return {\n      priority: 99, // it needs to run after the attributes are interpolated\n      link: function(scope, element, attr) {\n        var propName = attrName,\n            name = attrName;\n\n        if (attrName === 'href' &&\n            toString.call(element.prop('href')) === '[object SVGAnimatedString]') {\n          name = 'xlinkHref';\n          attr.$attr[name] = 'xlink:href';\n          propName = null;\n        }\n\n        attr.$observe(normalized, function(value) {\n          if (!value) {\n            if (attrName === 'href') {\n              attr.$set(name, null);\n            }\n            return;\n          }\n\n          attr.$set(name, value);\n\n          // on IE, if \"ng:src\" directive declaration is used and \"src\" attribute doesn't exist\n          // then calling element.setAttribute('src', 'foo') doesn't do anything, so we need\n          // to set the property as well to achieve the desired effect.\n          // we use attr[attrName] value since $set can sanitize the url.\n          if (msie && propName) element.prop(propName, attr[name]);\n        });\n      }\n    };\n  };\n});\n\n/* global -nullFormCtrl, -SUBMITTED_CLASS, addSetValidityMethod: true\n */\nvar nullFormCtrl = {\n  $addControl: noop,\n  $$renameControl: nullFormRenameControl,\n  $removeControl: noop,\n  $setValidity: noop,\n  $setDirty: noop,\n  $setPristine: noop,\n  $setSubmitted: noop\n},\nSUBMITTED_CLASS = 'ng-submitted';\n\nfunction nullFormRenameControl(control, name) {\n  control.$name = name;\n}\n\n/**\n * @ngdoc type\n * @name form.FormController\n *\n * @property {boolean} $pristine True if user has not interacted with the form yet.\n * @property {boolean} $dirty True if user has already interacted with the form.\n * @property {boolean} $valid True if all of the containing forms and controls are valid.\n * @property {boolean} $invalid True if at least one containing control or form is invalid.\n * @property {boolean} $submitted True if user has submitted the form even if its invalid.\n *\n * @property {Object} $error Is an object hash, containing references to controls or\n *  forms with failing validators, where:\n *\n *  - keys are validation tokens (error names),\n *  - values are arrays of controls or forms that have a failing validator for given error name.\n *\n *  Built-in validation tokens:\n *\n *  - `email`\n *  - `max`\n *  - `maxlength`\n *  - `min`\n *  - `minlength`\n *  - `number`\n *  - `pattern`\n *  - `required`\n *  - `url`\n *  - `date`\n *  - `datetimelocal`\n *  - `time`\n *  - `week`\n *  - `month`\n *\n * @description\n * `FormController` keeps track of all its controls and nested forms as well as the state of them,\n * such as being valid/invalid or dirty/pristine.\n *\n * Each {@link ng.directive:form form} directive creates an instance\n * of `FormController`.\n *\n */\n//asks for $scope to fool the BC controller module\nFormController.$inject = ['$element', '$attrs', '$scope', '$animate', '$interpolate'];\nfunction FormController(element, attrs, $scope, $animate, $interpolate) {\n  var form = this,\n      controls = [];\n\n  var parentForm = form.$$parentForm = element.parent().controller('form') || nullFormCtrl;\n\n  // init state\n  form.$error = {};\n  form.$$success = {};\n  form.$pending = undefined;\n  form.$name = $interpolate(attrs.name || attrs.ngForm || '')($scope);\n  form.$dirty = false;\n  form.$pristine = true;\n  form.$valid = true;\n  form.$invalid = false;\n  form.$submitted = false;\n\n  parentForm.$addControl(form);\n\n  /**\n   * @ngdoc method\n   * @name form.FormController#$rollbackViewValue\n   *\n   * @description\n   * Rollback all form controls pending updates to the `$modelValue`.\n   *\n   * Updates may be pending by a debounced event or because the input is waiting for a some future\n   * event defined in `ng-model-options`. This method is typically needed by the reset button of\n   * a form that uses `ng-model-options` to pend updates.\n   */\n  form.$rollbackViewValue = function() {\n    forEach(controls, function(control) {\n      control.$rollbackViewValue();\n    });\n  };\n\n  /**\n   * @ngdoc method\n   * @name form.FormController#$commitViewValue\n   *\n   * @description\n   * Commit all form controls pending updates to the `$modelValue`.\n   *\n   * Updates may be pending by a debounced event or because the input is waiting for a some future\n   * event defined in `ng-model-options`. This method is rarely needed as `NgModelController`\n   * usually handles calling this in response to input events.\n   */\n  form.$commitViewValue = function() {\n    forEach(controls, function(control) {\n      control.$commitViewValue();\n    });\n  };\n\n  /**\n   * @ngdoc method\n   * @name form.FormController#$addControl\n   *\n   * @description\n   * Register a control with the form.\n   *\n   * Input elements using ngModelController do this automatically when they are linked.\n   */\n  form.$addControl = function(control) {\n    // Breaking change - before, inputs whose name was \"hasOwnProperty\" were quietly ignored\n    // and not added to the scope.  Now we throw an error.\n    assertNotHasOwnProperty(control.$name, 'input');\n    controls.push(control);\n\n    if (control.$name) {\n      form[control.$name] = control;\n    }\n  };\n\n  // Private API: rename a form control\n  form.$$renameControl = function(control, newName) {\n    var oldName = control.$name;\n\n    if (form[oldName] === control) {\n      delete form[oldName];\n    }\n    form[newName] = control;\n    control.$name = newName;\n  };\n\n  /**\n   * @ngdoc method\n   * @name form.FormController#$removeControl\n   *\n   * @description\n   * Deregister a control from the form.\n   *\n   * Input elements using ngModelController do this automatically when they are destroyed.\n   */\n  form.$removeControl = function(control) {\n    if (control.$name && form[control.$name] === control) {\n      delete form[control.$name];\n    }\n    forEach(form.$pending, function(value, name) {\n      form.$setValidity(name, null, control);\n    });\n    forEach(form.$error, function(value, name) {\n      form.$setValidity(name, null, control);\n    });\n    forEach(form.$$success, function(value, name) {\n      form.$setValidity(name, null, control);\n    });\n\n    arrayRemove(controls, control);\n  };\n\n\n  /**\n   * @ngdoc method\n   * @name form.FormController#$setValidity\n   *\n   * @description\n   * Sets the validity of a form control.\n   *\n   * This method will also propagate to parent forms.\n   */\n  addSetValidityMethod({\n    ctrl: this,\n    $element: element,\n    set: function(object, property, controller) {\n      var list = object[property];\n      if (!list) {\n        object[property] = [controller];\n      } else {\n        var index = list.indexOf(controller);\n        if (index === -1) {\n          list.push(controller);\n        }\n      }\n    },\n    unset: function(object, property, controller) {\n      var list = object[property];\n      if (!list) {\n        return;\n      }\n      arrayRemove(list, controller);\n      if (list.length === 0) {\n        delete object[property];\n      }\n    },\n    parentForm: parentForm,\n    $animate: $animate\n  });\n\n  /**\n   * @ngdoc method\n   * @name form.FormController#$setDirty\n   *\n   * @description\n   * Sets the form to a dirty state.\n   *\n   * This method can be called to add the 'ng-dirty' class and set the form to a dirty\n   * state (ng-dirty class). This method will also propagate to parent forms.\n   */\n  form.$setDirty = function() {\n    $animate.removeClass(element, PRISTINE_CLASS);\n    $animate.addClass(element, DIRTY_CLASS);\n    form.$dirty = true;\n    form.$pristine = false;\n    parentForm.$setDirty();\n  };\n\n  /**\n   * @ngdoc method\n   * @name form.FormController#$setPristine\n   *\n   * @description\n   * Sets the form to its pristine state.\n   *\n   * This method can be called to remove the 'ng-dirty' class and set the form to its pristine\n   * state (ng-pristine class). This method will also propagate to all the controls contained\n   * in this form.\n   *\n   * Setting a form back to a pristine state is often useful when we want to 'reuse' a form after\n   * saving or resetting it.\n   */\n  form.$setPristine = function() {\n    $animate.setClass(element, PRISTINE_CLASS, DIRTY_CLASS + ' ' + SUBMITTED_CLASS);\n    form.$dirty = false;\n    form.$pristine = true;\n    form.$submitted = false;\n    forEach(controls, function(control) {\n      control.$setPristine();\n    });\n  };\n\n  /**\n   * @ngdoc method\n   * @name form.FormController#$setUntouched\n   *\n   * @description\n   * Sets the form to its untouched state.\n   *\n   * This method can be called to remove the 'ng-touched' class and set the form controls to their\n   * untouched state (ng-untouched class).\n   *\n   * Setting a form controls back to their untouched state is often useful when setting the form\n   * back to its pristine state.\n   */\n  form.$setUntouched = function() {\n    forEach(controls, function(control) {\n      control.$setUntouched();\n    });\n  };\n\n  /**\n   * @ngdoc method\n   * @name form.FormController#$setSubmitted\n   *\n   * @description\n   * Sets the form to its submitted state.\n   */\n  form.$setSubmitted = function() {\n    $animate.addClass(element, SUBMITTED_CLASS);\n    form.$submitted = true;\n    parentForm.$setSubmitted();\n  };\n}\n\n/**\n * @ngdoc directive\n * @name ngForm\n * @restrict EAC\n *\n * @description\n * Nestable alias of {@link ng.directive:form `form`} directive. HTML\n * does not allow nesting of form elements. It is useful to nest forms, for example if the validity of a\n * sub-group of controls needs to be determined.\n *\n * Note: the purpose of `ngForm` is to group controls,\n * but not to be a replacement for the `<form>` tag with all of its capabilities\n * (e.g. posting to the server, ...).\n *\n * @param {string=} ngForm|name Name of the form. If specified, the form controller will be published into\n *                       related scope, under this name.\n *\n */\n\n /**\n * @ngdoc directive\n * @name form\n * @restrict E\n *\n * @description\n * Directive that instantiates\n * {@link form.FormController FormController}.\n *\n * If the `name` attribute is specified, the form controller is published onto the current scope under\n * this name.\n *\n * # Alias: {@link ng.directive:ngForm `ngForm`}\n *\n * In Angular forms can be nested. This means that the outer form is valid when all of the child\n * forms are valid as well. However, browsers do not allow nesting of `<form>` elements, so\n * Angular provides the {@link ng.directive:ngForm `ngForm`} directive which behaves identically to\n * `<form>` but can be nested.  This allows you to have nested forms, which is very useful when\n * using Angular validation directives in forms that are dynamically generated using the\n * {@link ng.directive:ngRepeat `ngRepeat`} directive. Since you cannot dynamically generate the `name`\n * attribute of input elements using interpolation, you have to wrap each set of repeated inputs in an\n * `ngForm` directive and nest these in an outer `form` element.\n *\n *\n * # CSS classes\n *  - `ng-valid` is set if the form is valid.\n *  - `ng-invalid` is set if the form is invalid.\n *  - `ng-pristine` is set if the form is pristine.\n *  - `ng-dirty` is set if the form is dirty.\n *  - `ng-submitted` is set if the form was submitted.\n *\n * Keep in mind that ngAnimate can detect each of these classes when added and removed.\n *\n *\n * # Submitting a form and preventing the default action\n *\n * Since the role of forms in client-side Angular applications is different than in classical\n * roundtrip apps, it is desirable for the browser not to translate the form submission into a full\n * page reload that sends the data to the server. Instead some javascript logic should be triggered\n * to handle the form submission in an application-specific way.\n *\n * For this reason, Angular prevents the default action (form submission to the server) unless the\n * `<form>` element has an `action` attribute specified.\n *\n * You can use one of the following two ways to specify what javascript method should be called when\n * a form is submitted:\n *\n * - {@link ng.directive:ngSubmit ngSubmit} directive on the form element\n * - {@link ng.directive:ngClick ngClick} directive on the first\n  *  button or input field of type submit (input[type=submit])\n *\n * To prevent double execution of the handler, use only one of the {@link ng.directive:ngSubmit ngSubmit}\n * or {@link ng.directive:ngClick ngClick} directives.\n * This is because of the following form submission rules in the HTML specification:\n *\n * - If a form has only one input field then hitting enter in this field triggers form submit\n * (`ngSubmit`)\n * - if a form has 2+ input fields and no buttons or input[type=submit] then hitting enter\n * doesn't trigger submit\n * - if a form has one or more input fields and one or more buttons or input[type=submit] then\n * hitting enter in any of the input fields will trigger the click handler on the *first* button or\n * input[type=submit] (`ngClick`) *and* a submit handler on the enclosing form (`ngSubmit`)\n *\n * Any pending `ngModelOptions` changes will take place immediately when an enclosing form is\n * submitted. Note that `ngClick` events will occur before the model is updated. Use `ngSubmit`\n * to have access to the updated model.\n *\n * ## Animation Hooks\n *\n * Animations in ngForm are triggered when any of the associated CSS classes are added and removed.\n * These classes are: `.ng-pristine`, `.ng-dirty`, `.ng-invalid` and `.ng-valid` as well as any\n * other validations that are performed within the form. Animations in ngForm are similar to how\n * they work in ngClass and animations can be hooked into using CSS transitions, keyframes as well\n * as JS animations.\n *\n * The following example shows a simple way to utilize CSS transitions to style a form element\n * that has been rendered as invalid after it has been validated:\n *\n * <pre>\n * //be sure to include ngAnimate as a module to hook into more\n * //advanced animations\n * .my-form {\n *   transition:0.5s linear all;\n *   background: white;\n * }\n * .my-form.ng-invalid {\n *   background: red;\n *   color:white;\n * }\n * </pre>\n *\n * @example\n    <example deps=\"angular-animate.js\" animations=\"true\" fixBase=\"true\" module=\"formExample\">\n      <file name=\"index.html\">\n       <script>\n         angular.module('formExample', [])\n           .controller('FormController', ['$scope', function($scope) {\n             $scope.userType = 'guest';\n           }]);\n       </script>\n       <style>\n        .my-form {\n          -webkit-transition:all linear 0.5s;\n          transition:all linear 0.5s;\n          background: transparent;\n        }\n        .my-form.ng-invalid {\n          background: red;\n        }\n       </style>\n       <form name=\"myForm\" ng-controller=\"FormController\" class=\"my-form\">\n         userType: <input name=\"input\" ng-model=\"userType\" required>\n         <span class=\"error\" ng-show=\"myForm.input.$error.required\">Required!</span><br>\n         <tt>userType = {{userType}}</tt><br>\n         <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br>\n         <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br>\n        </form>\n      </file>\n      <file name=\"protractor.js\" type=\"protractor\">\n        it('should initialize to model', function() {\n          var userType = element(by.binding('userType'));\n          var valid = element(by.binding('myForm.input.$valid'));\n\n          expect(userType.getText()).toContain('guest');\n          expect(valid.getText()).toContain('true');\n        });\n\n        it('should be invalid if empty', function() {\n          var userType = element(by.binding('userType'));\n          var valid = element(by.binding('myForm.input.$valid'));\n          var userInput = element(by.model('userType'));\n\n          userInput.clear();\n          userInput.sendKeys('');\n\n          expect(userType.getText()).toEqual('userType =');\n          expect(valid.getText()).toContain('false');\n        });\n      </file>\n    </example>\n *\n * @param {string=} name Name of the form. If specified, the form controller will be published into\n *                       related scope, under this name.\n */\nvar formDirectiveFactory = function(isNgForm) {\n  return ['$timeout', function($timeout) {\n    var formDirective = {\n      name: 'form',\n      restrict: isNgForm ? 'EAC' : 'E',\n      controller: FormController,\n      compile: function ngFormCompile(formElement) {\n        // Setup initial state of the control\n        formElement.addClass(PRISTINE_CLASS).addClass(VALID_CLASS);\n\n        return {\n          pre: function ngFormPreLink(scope, formElement, attr, controller) {\n            // if `action` attr is not present on the form, prevent the default action (submission)\n            if (!('action' in attr)) {\n              // we can't use jq events because if a form is destroyed during submission the default\n              // action is not prevented. see #1238\n              //\n              // IE 9 is not affected because it doesn't fire a submit event and try to do a full\n              // page reload if the form was destroyed by submission of the form via a click handler\n              // on a button in the form. Looks like an IE9 specific bug.\n              var handleFormSubmission = function(event) {\n                scope.$apply(function() {\n                  controller.$commitViewValue();\n                  controller.$setSubmitted();\n                });\n\n                event.preventDefault();\n              };\n\n              addEventListenerFn(formElement[0], 'submit', handleFormSubmission);\n\n              // unregister the preventDefault listener so that we don't not leak memory but in a\n              // way that will achieve the prevention of the default action.\n              formElement.on('$destroy', function() {\n                $timeout(function() {\n                  removeEventListenerFn(formElement[0], 'submit', handleFormSubmission);\n                }, 0, false);\n              });\n            }\n\n            var parentFormCtrl = controller.$$parentForm,\n                alias = controller.$name;\n\n            if (alias) {\n              setter(scope, null, alias, controller, alias);\n              attr.$observe(attr.name ? 'name' : 'ngForm', function(newValue) {\n                if (alias === newValue) return;\n                setter(scope, null, alias, undefined, alias);\n                alias = newValue;\n                setter(scope, null, alias, controller, alias);\n                parentFormCtrl.$$renameControl(controller, alias);\n              });\n            }\n            formElement.on('$destroy', function() {\n              parentFormCtrl.$removeControl(controller);\n              if (alias) {\n                setter(scope, null, alias, undefined, alias);\n              }\n              extend(controller, nullFormCtrl); //stop propagating child destruction handlers upwards\n            });\n          }\n        };\n      }\n    };\n\n    return formDirective;\n  }];\n};\n\nvar formDirective = formDirectiveFactory();\nvar ngFormDirective = formDirectiveFactory(true);\n\n/* global VALID_CLASS: false,\n  INVALID_CLASS: false,\n  PRISTINE_CLASS: false,\n  DIRTY_CLASS: false,\n  UNTOUCHED_CLASS: false,\n  TOUCHED_CLASS: false,\n  $ngModelMinErr: false,\n*/\n\n// Regex code is obtained from SO: https://stackoverflow.com/questions/3143070/javascript-regex-iso-datetime#answer-3143231\nvar ISO_DATE_REGEXP = /\\d{4}-[01]\\d-[0-3]\\dT[0-2]\\d:[0-5]\\d:[0-5]\\d\\.\\d+([+-][0-2]\\d:[0-5]\\d|Z)/;\nvar URL_REGEXP = /^(ftp|http|https):\\/\\/(\\w+:{0,1}\\w*@)?(\\S+)(:[0-9]+)?(\\/|\\/([\\w#!:.?+=&%@!\\-\\/]))?$/;\nvar EMAIL_REGEXP = /^[a-z0-9!#$%&'*+\\/=?^_`{|}~.-]+@[a-z0-9]([a-z0-9-]*[a-z0-9])?(\\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)*$/i;\nvar NUMBER_REGEXP = /^\\s*(\\-|\\+)?(\\d+|(\\d*(\\.\\d*)))\\s*$/;\nvar DATE_REGEXP = /^(\\d{4})-(\\d{2})-(\\d{2})$/;\nvar DATETIMELOCAL_REGEXP = /^(\\d{4})-(\\d\\d)-(\\d\\d)T(\\d\\d):(\\d\\d)(?::(\\d\\d)(\\.\\d{1,3})?)?$/;\nvar WEEK_REGEXP = /^(\\d{4})-W(\\d\\d)$/;\nvar MONTH_REGEXP = /^(\\d{4})-(\\d\\d)$/;\nvar TIME_REGEXP = /^(\\d\\d):(\\d\\d)(?::(\\d\\d)(\\.\\d{1,3})?)?$/;\n\nvar inputType = {\n\n  /**\n   * @ngdoc input\n   * @name input[text]\n   *\n   * @description\n   * Standard HTML text input with angular data binding, inherited by most of the `input` elements.\n   *\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Adds `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength. Setting the attribute to a negative or non-numeric value, allows view values of\n   *    any length.\n   * @param {string=} pattern Similar to `ngPattern` except that the attribute value is the actual string\n   *    that contains the regular expression body that will be converted to a regular expression\n   *    as in the ngPattern directive.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the ngModel value does not match\n   *    a RegExp found by evaluating the Angular expression given in the attribute value.\n   *    If the expression evaluates to a RegExp object then this is used directly.\n   *    If the expression is a string then it will be converted to a RegExp after wrapping it in `^` and `$`\n   *    characters. For instance, `\"abc\"` will be converted to `new RegExp('^abc$')`.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   * @param {boolean=} [ngTrim=true] If set to false Angular will not automatically trim the input.\n   *    This parameter is ignored for input[type=password] controls, which will never trim the\n   *    input.\n   *\n   * @example\n      <example name=\"text-input-directive\" module=\"textInputExample\">\n        <file name=\"index.html\">\n         <script>\n           angular.module('textInputExample', [])\n             .controller('ExampleController', ['$scope', function($scope) {\n               $scope.example = {\n                 text: 'guest',\n                 word: /^\\s*\\w*\\s*$/\n               };\n             }]);\n         </script>\n         <form name=\"myForm\" ng-controller=\"ExampleController\">\n           Single word: <input type=\"text\" name=\"input\" ng-model=\"example.text\"\n                               ng-pattern=\"example.word\" required ng-trim=\"false\">\n           <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.input.$error.pattern\">\n             Single word only!</span>\n\n           <tt>text = {{example.text}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n          </form>\n        </file>\n        <file name=\"protractor.js\" type=\"protractor\">\n          var text = element(by.binding('example.text'));\n          var valid = element(by.binding('myForm.input.$valid'));\n          var input = element(by.model('example.text'));\n\n          it('should initialize to model', function() {\n            expect(text.getText()).toContain('guest');\n            expect(valid.getText()).toContain('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input.clear();\n            input.sendKeys('');\n\n            expect(text.getText()).toEqual('text =');\n            expect(valid.getText()).toContain('false');\n          });\n\n          it('should be invalid if multi word', function() {\n            input.clear();\n            input.sendKeys('hello world');\n\n            expect(valid.getText()).toContain('false');\n          });\n        </file>\n      </example>\n   */\n  'text': textInputType,\n\n    /**\n     * @ngdoc input\n     * @name input[date]\n     *\n     * @description\n     * Input with date validation and transformation. In browsers that do not yet support\n     * the HTML5 date input, a text element will be used. In that case, text must be entered in a valid ISO-8601\n     * date format (yyyy-MM-dd), for example: `2009-01-06`. Since many\n     * modern browsers do not yet support this input type, it is important to provide cues to users on the\n     * expected input format via a placeholder or label.\n     *\n     * The model must always be a Date object, otherwise Angular will throw an error.\n     * Invalid `Date` objects (dates whose `getTime()` is `NaN`) will be rendered as an empty string.\n     *\n     * The timezone to be used to read/write the `Date` instance in the model can be defined using\n     * {@link ng.directive:ngModelOptions ngModelOptions}. By default, this is the timezone of the browser.\n     *\n     * @param {string} ngModel Assignable angular expression to data-bind to.\n     * @param {string=} name Property name of the form under which the control is published.\n     * @param {string=} min Sets the `min` validation error key if the value entered is less than `min`. This must be a\n     * valid ISO date string (yyyy-MM-dd).\n     * @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`. This must be\n     * a valid ISO date string (yyyy-MM-dd).\n     * @param {string=} required Sets `required` validation error key if the value is not entered.\n     * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n     *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n     *    `required` when you want to data-bind to the `required` attribute.\n     * @param {string=} ngChange Angular expression to be executed when input changes due to user\n     *    interaction with the input element.\n     *\n     * @example\n     <example name=\"date-input-directive\" module=\"dateInputExample\">\n     <file name=\"index.html\">\n       <script>\n          angular.module('dateInputExample', [])\n            .controller('DateController', ['$scope', function($scope) {\n              $scope.example = {\n                value: new Date(2013, 9, 22)\n              };\n            }]);\n       </script>\n       <form name=\"myForm\" ng-controller=\"DateController as dateCtrl\">\n          Pick a date in 2013:\n          <input type=\"date\" id=\"exampleInput\" name=\"input\" ng-model=\"example.value\"\n              placeholder=\"yyyy-MM-dd\" min=\"2013-01-01\" max=\"2013-12-31\" required />\n          <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n              Required!</span>\n          <span class=\"error\" ng-show=\"myForm.input.$error.date\">\n              Not a valid date!</span>\n           <tt>value = {{example.value | date: \"yyyy-MM-dd\"}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n       </form>\n     </file>\n     <file name=\"protractor.js\" type=\"protractor\">\n        var value = element(by.binding('example.value | date: \"yyyy-MM-dd\"'));\n        var valid = element(by.binding('myForm.input.$valid'));\n        var input = element(by.model('example.value'));\n\n        // currently protractor/webdriver does not support\n        // sending keys to all known HTML5 input controls\n        // for various browsers (see https://github.com/angular/protractor/issues/562).\n        function setInput(val) {\n          // set the value of the element and force validation.\n          var scr = \"var ipt = document.getElementById('exampleInput'); \" +\n          \"ipt.value = '\" + val + \"';\" +\n          \"angular.element(ipt).scope().$apply(function(s) { s.myForm[ipt.name].$setViewValue('\" + val + \"'); });\";\n          browser.executeScript(scr);\n        }\n\n        it('should initialize to model', function() {\n          expect(value.getText()).toContain('2013-10-22');\n          expect(valid.getText()).toContain('myForm.input.$valid = true');\n        });\n\n        it('should be invalid if empty', function() {\n          setInput('');\n          expect(value.getText()).toEqual('value =');\n          expect(valid.getText()).toContain('myForm.input.$valid = false');\n        });\n\n        it('should be invalid if over max', function() {\n          setInput('2015-01-01');\n          expect(value.getText()).toContain('');\n          expect(valid.getText()).toContain('myForm.input.$valid = false');\n        });\n     </file>\n     </example>\n     */\n  'date': createDateInputType('date', DATE_REGEXP,\n         createDateParser(DATE_REGEXP, ['yyyy', 'MM', 'dd']),\n         'yyyy-MM-dd'),\n\n   /**\n    * @ngdoc input\n    * @name input[datetime-local]\n    *\n    * @description\n    * Input with datetime validation and transformation. In browsers that do not yet support\n    * the HTML5 date input, a text element will be used. In that case, the text must be entered in a valid ISO-8601\n    * local datetime format (yyyy-MM-ddTHH:mm:ss), for example: `2010-12-28T14:57:00`.\n    *\n    * The model must always be a Date object, otherwise Angular will throw an error.\n    * Invalid `Date` objects (dates whose `getTime()` is `NaN`) will be rendered as an empty string.\n    *\n    * The timezone to be used to read/write the `Date` instance in the model can be defined using\n    * {@link ng.directive:ngModelOptions ngModelOptions}. By default, this is the timezone of the browser.\n    *\n    * @param {string} ngModel Assignable angular expression to data-bind to.\n    * @param {string=} name Property name of the form under which the control is published.\n    * @param {string=} min Sets the `min` validation error key if the value entered is less than `min`. This must be a\n    * valid ISO datetime format (yyyy-MM-ddTHH:mm:ss).\n    * @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`. This must be\n    * a valid ISO datetime format (yyyy-MM-ddTHH:mm:ss).\n    * @param {string=} required Sets `required` validation error key if the value is not entered.\n    * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n    *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n    *    `required` when you want to data-bind to the `required` attribute.\n    * @param {string=} ngChange Angular expression to be executed when input changes due to user\n    *    interaction with the input element.\n    *\n    * @example\n    <example name=\"datetimelocal-input-directive\" module=\"dateExample\">\n    <file name=\"index.html\">\n      <script>\n        angular.module('dateExample', [])\n          .controller('DateController', ['$scope', function($scope) {\n            $scope.example = {\n              value: new Date(2010, 11, 28, 14, 57)\n            };\n          }]);\n      </script>\n      <form name=\"myForm\" ng-controller=\"DateController as dateCtrl\">\n        Pick a date between in 2013:\n        <input type=\"datetime-local\" id=\"exampleInput\" name=\"input\" ng-model=\"example.value\"\n            placeholder=\"yyyy-MM-ddTHH:mm:ss\" min=\"2001-01-01T00:00:00\" max=\"2013-12-31T00:00:00\" required />\n        <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n            Required!</span>\n        <span class=\"error\" ng-show=\"myForm.input.$error.datetimelocal\">\n            Not a valid date!</span>\n        <tt>value = {{example.value | date: \"yyyy-MM-ddTHH:mm:ss\"}}</tt><br/>\n        <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n        <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n        <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n        <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n      </form>\n    </file>\n    <file name=\"protractor.js\" type=\"protractor\">\n      var value = element(by.binding('example.value | date: \"yyyy-MM-ddTHH:mm:ss\"'));\n      var valid = element(by.binding('myForm.input.$valid'));\n      var input = element(by.model('example.value'));\n\n      // currently protractor/webdriver does not support\n      // sending keys to all known HTML5 input controls\n      // for various browsers (https://github.com/angular/protractor/issues/562).\n      function setInput(val) {\n        // set the value of the element and force validation.\n        var scr = \"var ipt = document.getElementById('exampleInput'); \" +\n        \"ipt.value = '\" + val + \"';\" +\n        \"angular.element(ipt).scope().$apply(function(s) { s.myForm[ipt.name].$setViewValue('\" + val + \"'); });\";\n        browser.executeScript(scr);\n      }\n\n      it('should initialize to model', function() {\n        expect(value.getText()).toContain('2010-12-28T14:57:00');\n        expect(valid.getText()).toContain('myForm.input.$valid = true');\n      });\n\n      it('should be invalid if empty', function() {\n        setInput('');\n        expect(value.getText()).toEqual('value =');\n        expect(valid.getText()).toContain('myForm.input.$valid = false');\n      });\n\n      it('should be invalid if over max', function() {\n        setInput('2015-01-01T23:59:00');\n        expect(value.getText()).toContain('');\n        expect(valid.getText()).toContain('myForm.input.$valid = false');\n      });\n    </file>\n    </example>\n    */\n  'datetime-local': createDateInputType('datetimelocal', DATETIMELOCAL_REGEXP,\n      createDateParser(DATETIMELOCAL_REGEXP, ['yyyy', 'MM', 'dd', 'HH', 'mm', 'ss', 'sss']),\n      'yyyy-MM-ddTHH:mm:ss.sss'),\n\n  /**\n   * @ngdoc input\n   * @name input[time]\n   *\n   * @description\n   * Input with time validation and transformation. In browsers that do not yet support\n   * the HTML5 date input, a text element will be used. In that case, the text must be entered in a valid ISO-8601\n   * local time format (HH:mm:ss), for example: `14:57:00`. Model must be a Date object. This binding will always output a\n   * Date object to the model of January 1, 1970, or local date `new Date(1970, 0, 1, HH, mm, ss)`.\n   *\n   * The model must always be a Date object, otherwise Angular will throw an error.\n   * Invalid `Date` objects (dates whose `getTime()` is `NaN`) will be rendered as an empty string.\n   *\n   * The timezone to be used to read/write the `Date` instance in the model can be defined using\n   * {@link ng.directive:ngModelOptions ngModelOptions}. By default, this is the timezone of the browser.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} min Sets the `min` validation error key if the value entered is less than `min`. This must be a\n   * valid ISO time format (HH:mm:ss).\n   * @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`. This must be a\n   * valid ISO time format (HH:mm:ss).\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n   <example name=\"time-input-directive\" module=\"timeExample\">\n   <file name=\"index.html\">\n     <script>\n      angular.module('timeExample', [])\n        .controller('DateController', ['$scope', function($scope) {\n          $scope.example = {\n            value: new Date(1970, 0, 1, 14, 57, 0)\n          };\n        }]);\n     </script>\n     <form name=\"myForm\" ng-controller=\"DateController as dateCtrl\">\n        Pick a between 8am and 5pm:\n        <input type=\"time\" id=\"exampleInput\" name=\"input\" ng-model=\"example.value\"\n            placeholder=\"HH:mm:ss\" min=\"08:00:00\" max=\"17:00:00\" required />\n        <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n            Required!</span>\n        <span class=\"error\" ng-show=\"myForm.input.$error.time\">\n            Not a valid date!</span>\n        <tt>value = {{example.value | date: \"HH:mm:ss\"}}</tt><br/>\n        <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n        <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n        <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n        <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n     </form>\n   </file>\n   <file name=\"protractor.js\" type=\"protractor\">\n      var value = element(by.binding('example.value | date: \"HH:mm:ss\"'));\n      var valid = element(by.binding('myForm.input.$valid'));\n      var input = element(by.model('example.value'));\n\n      // currently protractor/webdriver does not support\n      // sending keys to all known HTML5 input controls\n      // for various browsers (https://github.com/angular/protractor/issues/562).\n      function setInput(val) {\n        // set the value of the element and force validation.\n        var scr = \"var ipt = document.getElementById('exampleInput'); \" +\n        \"ipt.value = '\" + val + \"';\" +\n        \"angular.element(ipt).scope().$apply(function(s) { s.myForm[ipt.name].$setViewValue('\" + val + \"'); });\";\n        browser.executeScript(scr);\n      }\n\n      it('should initialize to model', function() {\n        expect(value.getText()).toContain('14:57:00');\n        expect(valid.getText()).toContain('myForm.input.$valid = true');\n      });\n\n      it('should be invalid if empty', function() {\n        setInput('');\n        expect(value.getText()).toEqual('value =');\n        expect(valid.getText()).toContain('myForm.input.$valid = false');\n      });\n\n      it('should be invalid if over max', function() {\n        setInput('23:59:00');\n        expect(value.getText()).toContain('');\n        expect(valid.getText()).toContain('myForm.input.$valid = false');\n      });\n   </file>\n   </example>\n   */\n  'time': createDateInputType('time', TIME_REGEXP,\n      createDateParser(TIME_REGEXP, ['HH', 'mm', 'ss', 'sss']),\n     'HH:mm:ss.sss'),\n\n   /**\n    * @ngdoc input\n    * @name input[week]\n    *\n    * @description\n    * Input with week-of-the-year validation and transformation to Date. In browsers that do not yet support\n    * the HTML5 week input, a text element will be used. In that case, the text must be entered in a valid ISO-8601\n    * week format (yyyy-W##), for example: `2013-W02`.\n    *\n    * The model must always be a Date object, otherwise Angular will throw an error.\n    * Invalid `Date` objects (dates whose `getTime()` is `NaN`) will be rendered as an empty string.\n    *\n    * The timezone to be used to read/write the `Date` instance in the model can be defined using\n    * {@link ng.directive:ngModelOptions ngModelOptions}. By default, this is the timezone of the browser.\n    *\n    * @param {string} ngModel Assignable angular expression to data-bind to.\n    * @param {string=} name Property name of the form under which the control is published.\n    * @param {string=} min Sets the `min` validation error key if the value entered is less than `min`. This must be a\n    * valid ISO week format (yyyy-W##).\n    * @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`. This must be\n    * a valid ISO week format (yyyy-W##).\n    * @param {string=} required Sets `required` validation error key if the value is not entered.\n    * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n    *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n    *    `required` when you want to data-bind to the `required` attribute.\n    * @param {string=} ngChange Angular expression to be executed when input changes due to user\n    *    interaction with the input element.\n    *\n    * @example\n    <example name=\"week-input-directive\" module=\"weekExample\">\n    <file name=\"index.html\">\n      <script>\n      angular.module('weekExample', [])\n        .controller('DateController', ['$scope', function($scope) {\n          $scope.example = {\n            value: new Date(2013, 0, 3)\n          };\n        }]);\n      </script>\n      <form name=\"myForm\" ng-controller=\"DateController as dateCtrl\">\n        Pick a date between in 2013:\n        <input id=\"exampleInput\" type=\"week\" name=\"input\" ng-model=\"example.value\"\n            placeholder=\"YYYY-W##\" min=\"2012-W32\" max=\"2013-W52\" required />\n        <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n            Required!</span>\n        <span class=\"error\" ng-show=\"myForm.input.$error.week\">\n            Not a valid date!</span>\n        <tt>value = {{example.value | date: \"yyyy-Www\"}}</tt><br/>\n        <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n        <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n        <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n        <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n      </form>\n    </file>\n    <file name=\"protractor.js\" type=\"protractor\">\n      var value = element(by.binding('example.value | date: \"yyyy-Www\"'));\n      var valid = element(by.binding('myForm.input.$valid'));\n      var input = element(by.model('example.value'));\n\n      // currently protractor/webdriver does not support\n      // sending keys to all known HTML5 input controls\n      // for various browsers (https://github.com/angular/protractor/issues/562).\n      function setInput(val) {\n        // set the value of the element and force validation.\n        var scr = \"var ipt = document.getElementById('exampleInput'); \" +\n        \"ipt.value = '\" + val + \"';\" +\n        \"angular.element(ipt).scope().$apply(function(s) { s.myForm[ipt.name].$setViewValue('\" + val + \"'); });\";\n        browser.executeScript(scr);\n      }\n\n      it('should initialize to model', function() {\n        expect(value.getText()).toContain('2013-W01');\n        expect(valid.getText()).toContain('myForm.input.$valid = true');\n      });\n\n      it('should be invalid if empty', function() {\n        setInput('');\n        expect(value.getText()).toEqual('value =');\n        expect(valid.getText()).toContain('myForm.input.$valid = false');\n      });\n\n      it('should be invalid if over max', function() {\n        setInput('2015-W01');\n        expect(value.getText()).toContain('');\n        expect(valid.getText()).toContain('myForm.input.$valid = false');\n      });\n    </file>\n    </example>\n    */\n  'week': createDateInputType('week', WEEK_REGEXP, weekParser, 'yyyy-Www'),\n\n  /**\n   * @ngdoc input\n   * @name input[month]\n   *\n   * @description\n   * Input with month validation and transformation. In browsers that do not yet support\n   * the HTML5 month input, a text element will be used. In that case, the text must be entered in a valid ISO-8601\n   * month format (yyyy-MM), for example: `2009-01`.\n   *\n   * The model must always be a Date object, otherwise Angular will throw an error.\n   * Invalid `Date` objects (dates whose `getTime()` is `NaN`) will be rendered as an empty string.\n   * If the model is not set to the first of the month, the next view to model update will set it\n   * to the first of the month.\n   *\n   * The timezone to be used to read/write the `Date` instance in the model can be defined using\n   * {@link ng.directive:ngModelOptions ngModelOptions}. By default, this is the timezone of the browser.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} min Sets the `min` validation error key if the value entered is less than `min`. This must be\n   * a valid ISO month format (yyyy-MM).\n   * @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`. This must\n   * be a valid ISO month format (yyyy-MM).\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n   <example name=\"month-input-directive\" module=\"monthExample\">\n   <file name=\"index.html\">\n     <script>\n      angular.module('monthExample', [])\n        .controller('DateController', ['$scope', function($scope) {\n          $scope.example = {\n            value: new Date(2013, 9, 1)\n          };\n        }]);\n     </script>\n     <form name=\"myForm\" ng-controller=\"DateController as dateCtrl\">\n       Pick a month in 2013:\n       <input id=\"exampleInput\" type=\"month\" name=\"input\" ng-model=\"example.value\"\n          placeholder=\"yyyy-MM\" min=\"2013-01\" max=\"2013-12\" required />\n       <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n          Required!</span>\n       <span class=\"error\" ng-show=\"myForm.input.$error.month\">\n          Not a valid month!</span>\n       <tt>value = {{example.value | date: \"yyyy-MM\"}}</tt><br/>\n       <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n       <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n       <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n       <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n     </form>\n   </file>\n   <file name=\"protractor.js\" type=\"protractor\">\n      var value = element(by.binding('example.value | date: \"yyyy-MM\"'));\n      var valid = element(by.binding('myForm.input.$valid'));\n      var input = element(by.model('example.value'));\n\n      // currently protractor/webdriver does not support\n      // sending keys to all known HTML5 input controls\n      // for various browsers (https://github.com/angular/protractor/issues/562).\n      function setInput(val) {\n        // set the value of the element and force validation.\n        var scr = \"var ipt = document.getElementById('exampleInput'); \" +\n        \"ipt.value = '\" + val + \"';\" +\n        \"angular.element(ipt).scope().$apply(function(s) { s.myForm[ipt.name].$setViewValue('\" + val + \"'); });\";\n        browser.executeScript(scr);\n      }\n\n      it('should initialize to model', function() {\n        expect(value.getText()).toContain('2013-10');\n        expect(valid.getText()).toContain('myForm.input.$valid = true');\n      });\n\n      it('should be invalid if empty', function() {\n        setInput('');\n        expect(value.getText()).toEqual('value =');\n        expect(valid.getText()).toContain('myForm.input.$valid = false');\n      });\n\n      it('should be invalid if over max', function() {\n        setInput('2015-01');\n        expect(value.getText()).toContain('');\n        expect(valid.getText()).toContain('myForm.input.$valid = false');\n      });\n   </file>\n   </example>\n   */\n  'month': createDateInputType('month', MONTH_REGEXP,\n     createDateParser(MONTH_REGEXP, ['yyyy', 'MM']),\n     'yyyy-MM'),\n\n  /**\n   * @ngdoc input\n   * @name input[number]\n   *\n   * @description\n   * Text input with number validation and transformation. Sets the `number` validation\n   * error if not a valid number.\n   *\n   * The model must always be a number, otherwise Angular will throw an error.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} min Sets the `min` validation error key if the value entered is less than `min`.\n   * @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength. Setting the attribute to a negative or non-numeric value, allows view values of\n   *    any length.\n   * @param {string=} pattern Similar to `ngPattern` except that the attribute value is the actual string\n   *    that contains the regular expression body that will be converted to a regular expression\n   *    as in the ngPattern directive.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the ngModel value does not match\n   *    a RegExp found by evaluating the Angular expression given in the attribute value.\n   *    If the expression evaluates to a RegExp object then this is used directly.\n   *    If the expression is a string then it will be converted to a RegExp after wrapping it in `^` and `$`\n   *    characters. For instance, `\"abc\"` will be converted to `new RegExp('^abc$')`.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <example name=\"number-input-directive\" module=\"numberExample\">\n        <file name=\"index.html\">\n         <script>\n           angular.module('numberExample', [])\n             .controller('ExampleController', ['$scope', function($scope) {\n               $scope.example = {\n                 value: 12\n               };\n             }]);\n         </script>\n         <form name=\"myForm\" ng-controller=\"ExampleController\">\n           Number: <input type=\"number\" name=\"input\" ng-model=\"example.value\"\n                          min=\"0\" max=\"99\" required>\n           <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.input.$error.number\">\n             Not valid number!</span>\n           <tt>value = {{example.value}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n          </form>\n        </file>\n        <file name=\"protractor.js\" type=\"protractor\">\n          var value = element(by.binding('example.value'));\n          var valid = element(by.binding('myForm.input.$valid'));\n          var input = element(by.model('example.value'));\n\n          it('should initialize to model', function() {\n            expect(value.getText()).toContain('12');\n            expect(valid.getText()).toContain('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input.clear();\n            input.sendKeys('');\n            expect(value.getText()).toEqual('value =');\n            expect(valid.getText()).toContain('false');\n          });\n\n          it('should be invalid if over max', function() {\n            input.clear();\n            input.sendKeys('123');\n            expect(value.getText()).toEqual('value =');\n            expect(valid.getText()).toContain('false');\n          });\n        </file>\n      </example>\n   */\n  'number': numberInputType,\n\n\n  /**\n   * @ngdoc input\n   * @name input[url]\n   *\n   * @description\n   * Text input with URL validation. Sets the `url` validation error key if the content is not a\n   * valid URL.\n   *\n   * <div class=\"alert alert-warning\">\n   * **Note:** `input[url]` uses a regex to validate urls that is derived from the regex\n   * used in Chromium. If you need stricter validation, you can use `ng-pattern` or modify\n   * the built-in validators (see the {@link guide/forms Forms guide})\n   * </div>\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength. Setting the attribute to a negative or non-numeric value, allows view values of\n   *    any length.\n   * @param {string=} pattern Similar to `ngPattern` except that the attribute value is the actual string\n   *    that contains the regular expression body that will be converted to a regular expression\n   *    as in the ngPattern directive.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the ngModel value does not match\n   *    a RegExp found by evaluating the Angular expression given in the attribute value.\n   *    If the expression evaluates to a RegExp object then this is used directly.\n   *    If the expression is a string then it will be converted to a RegExp after wrapping it in `^` and `$`\n   *    characters. For instance, `\"abc\"` will be converted to `new RegExp('^abc$')`.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <example name=\"url-input-directive\" module=\"urlExample\">\n        <file name=\"index.html\">\n         <script>\n           angular.module('urlExample', [])\n             .controller('ExampleController', ['$scope', function($scope) {\n               $scope.url = {\n                 text: 'http://google.com'\n               };\n             }]);\n         </script>\n         <form name=\"myForm\" ng-controller=\"ExampleController\">\n           URL: <input type=\"url\" name=\"input\" ng-model=\"url.text\" required>\n           <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.input.$error.url\">\n             Not valid url!</span>\n           <tt>text = {{url.text}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n           <tt>myForm.$error.url = {{!!myForm.$error.url}}</tt><br/>\n          </form>\n        </file>\n        <file name=\"protractor.js\" type=\"protractor\">\n          var text = element(by.binding('url.text'));\n          var valid = element(by.binding('myForm.input.$valid'));\n          var input = element(by.model('url.text'));\n\n          it('should initialize to model', function() {\n            expect(text.getText()).toContain('http://google.com');\n            expect(valid.getText()).toContain('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input.clear();\n            input.sendKeys('');\n\n            expect(text.getText()).toEqual('text =');\n            expect(valid.getText()).toContain('false');\n          });\n\n          it('should be invalid if not url', function() {\n            input.clear();\n            input.sendKeys('box');\n\n            expect(valid.getText()).toContain('false');\n          });\n        </file>\n      </example>\n   */\n  'url': urlInputType,\n\n\n  /**\n   * @ngdoc input\n   * @name input[email]\n   *\n   * @description\n   * Text input with email validation. Sets the `email` validation error key if not a valid email\n   * address.\n   *\n   * <div class=\"alert alert-warning\">\n   * **Note:** `input[email]` uses a regex to validate email addresses that is derived from the regex\n   * used in Chromium. If you need stricter validation (e.g. requiring a top-level domain), you can\n   * use `ng-pattern` or modify the built-in validators (see the {@link guide/forms Forms guide})\n   * </div>\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength. Setting the attribute to a negative or non-numeric value, allows view values of\n   *    any length.\n   * @param {string=} pattern Similar to `ngPattern` except that the attribute value is the actual string\n   *    that contains the regular expression body that will be converted to a regular expression\n   *    as in the ngPattern directive.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the ngModel value does not match\n   *    a RegExp found by evaluating the Angular expression given in the attribute value.\n   *    If the expression evaluates to a RegExp object then this is used directly.\n   *    If the expression is a string then it will be converted to a RegExp after wrapping it in `^` and `$`\n   *    characters. For instance, `\"abc\"` will be converted to `new RegExp('^abc$')`.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <example name=\"email-input-directive\" module=\"emailExample\">\n        <file name=\"index.html\">\n         <script>\n           angular.module('emailExample', [])\n             .controller('ExampleController', ['$scope', function($scope) {\n               $scope.email = {\n                 text: 'me@example.com'\n               };\n             }]);\n         </script>\n           <form name=\"myForm\" ng-controller=\"ExampleController\">\n             Email: <input type=\"email\" name=\"input\" ng-model=\"email.text\" required>\n             <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n               Required!</span>\n             <span class=\"error\" ng-show=\"myForm.input.$error.email\">\n               Not valid email!</span>\n             <tt>text = {{email.text}}</tt><br/>\n             <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n             <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n             <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n             <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n             <tt>myForm.$error.email = {{!!myForm.$error.email}}</tt><br/>\n           </form>\n         </file>\n        <file name=\"protractor.js\" type=\"protractor\">\n          var text = element(by.binding('email.text'));\n          var valid = element(by.binding('myForm.input.$valid'));\n          var input = element(by.model('email.text'));\n\n          it('should initialize to model', function() {\n            expect(text.getText()).toContain('me@example.com');\n            expect(valid.getText()).toContain('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input.clear();\n            input.sendKeys('');\n            expect(text.getText()).toEqual('text =');\n            expect(valid.getText()).toContain('false');\n          });\n\n          it('should be invalid if not email', function() {\n            input.clear();\n            input.sendKeys('xxx');\n\n            expect(valid.getText()).toContain('false');\n          });\n        </file>\n      </example>\n   */\n  'email': emailInputType,\n\n\n  /**\n   * @ngdoc input\n   * @name input[radio]\n   *\n   * @description\n   * HTML radio button.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string} value The value to which the expression should be set when selected.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   * @param {string} ngValue Angular expression which sets the value to which the expression should\n   *    be set when selected.\n   *\n   * @example\n      <example name=\"radio-input-directive\" module=\"radioExample\">\n        <file name=\"index.html\">\n         <script>\n           angular.module('radioExample', [])\n             .controller('ExampleController', ['$scope', function($scope) {\n               $scope.color = {\n                 name: 'blue'\n               };\n               $scope.specialValue = {\n                 \"id\": \"12345\",\n                 \"value\": \"green\"\n               };\n             }]);\n         </script>\n         <form name=\"myForm\" ng-controller=\"ExampleController\">\n           <input type=\"radio\" ng-model=\"color.name\" value=\"red\">  Red <br/>\n           <input type=\"radio\" ng-model=\"color.name\" ng-value=\"specialValue\"> Green <br/>\n           <input type=\"radio\" ng-model=\"color.name\" value=\"blue\"> Blue <br/>\n           <tt>color = {{color.name | json}}</tt><br/>\n          </form>\n          Note that `ng-value=\"specialValue\"` sets radio item's value to be the value of `$scope.specialValue`.\n        </file>\n        <file name=\"protractor.js\" type=\"protractor\">\n          it('should change state', function() {\n            var color = element(by.binding('color.name'));\n\n            expect(color.getText()).toContain('blue');\n\n            element.all(by.model('color.name')).get(0).click();\n\n            expect(color.getText()).toContain('red');\n          });\n        </file>\n      </example>\n   */\n  'radio': radioInputType,\n\n\n  /**\n   * @ngdoc input\n   * @name input[checkbox]\n   *\n   * @description\n   * HTML checkbox.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {expression=} ngTrueValue The value to which the expression should be set when selected.\n   * @param {expression=} ngFalseValue The value to which the expression should be set when not selected.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <example name=\"checkbox-input-directive\" module=\"checkboxExample\">\n        <file name=\"index.html\">\n         <script>\n           angular.module('checkboxExample', [])\n             .controller('ExampleController', ['$scope', function($scope) {\n               $scope.checkboxModel = {\n                value1 : true,\n                value2 : 'YES'\n              };\n             }]);\n         </script>\n         <form name=\"myForm\" ng-controller=\"ExampleController\">\n           Value1: <input type=\"checkbox\" ng-model=\"checkboxModel.value1\"> <br/>\n           Value2: <input type=\"checkbox\" ng-model=\"checkboxModel.value2\"\n                          ng-true-value=\"'YES'\" ng-false-value=\"'NO'\"> <br/>\n           <tt>value1 = {{checkboxModel.value1}}</tt><br/>\n           <tt>value2 = {{checkboxModel.value2}}</tt><br/>\n          </form>\n        </file>\n        <file name=\"protractor.js\" type=\"protractor\">\n          it('should change state', function() {\n            var value1 = element(by.binding('checkboxModel.value1'));\n            var value2 = element(by.binding('checkboxModel.value2'));\n\n            expect(value1.getText()).toContain('true');\n            expect(value2.getText()).toContain('YES');\n\n            element(by.model('checkboxModel.value1')).click();\n            element(by.model('checkboxModel.value2')).click();\n\n            expect(value1.getText()).toContain('false');\n            expect(value2.getText()).toContain('NO');\n          });\n        </file>\n      </example>\n   */\n  'checkbox': checkboxInputType,\n\n  'hidden': noop,\n  'button': noop,\n  'submit': noop,\n  'reset': noop,\n  'file': noop\n};\n\nfunction stringBasedInputType(ctrl) {\n  ctrl.$formatters.push(function(value) {\n    return ctrl.$isEmpty(value) ? value : value.toString();\n  });\n}\n\nfunction textInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  baseInputType(scope, element, attr, ctrl, $sniffer, $browser);\n  stringBasedInputType(ctrl);\n}\n\nfunction baseInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  var type = lowercase(element[0].type);\n\n  // In composition mode, users are still inputing intermediate text buffer,\n  // hold the listener until composition is done.\n  // More about composition events: https://developer.mozilla.org/en-US/docs/Web/API/CompositionEvent\n  if (!$sniffer.android) {\n    var composing = false;\n\n    element.on('compositionstart', function(data) {\n      composing = true;\n    });\n\n    element.on('compositionend', function() {\n      composing = false;\n      listener();\n    });\n  }\n\n  var listener = function(ev) {\n    if (timeout) {\n      $browser.defer.cancel(timeout);\n      timeout = null;\n    }\n    if (composing) return;\n    var value = element.val(),\n        event = ev && ev.type;\n\n    // By default we will trim the value\n    // If the attribute ng-trim exists we will avoid trimming\n    // If input type is 'password', the value is never trimmed\n    if (type !== 'password' && (!attr.ngTrim || attr.ngTrim !== 'false')) {\n      value = trim(value);\n    }\n\n    // If a control is suffering from bad input (due to native validators), browsers discard its\n    // value, so it may be necessary to revalidate (by calling $setViewValue again) even if the\n    // control's value is the same empty value twice in a row.\n    if (ctrl.$viewValue !== value || (value === '' && ctrl.$$hasNativeValidators)) {\n      ctrl.$setViewValue(value, event);\n    }\n  };\n\n  // if the browser does support \"input\" event, we are fine - except on IE9 which doesn't fire the\n  // input event on backspace, delete or cut\n  if ($sniffer.hasEvent('input')) {\n    element.on('input', listener);\n  } else {\n    var timeout;\n\n    var deferListener = function(ev, input, origValue) {\n      if (!timeout) {\n        timeout = $browser.defer(function() {\n          timeout = null;\n          if (!input || input.value !== origValue) {\n            listener(ev);\n          }\n        });\n      }\n    };\n\n    element.on('keydown', function(event) {\n      var key = event.keyCode;\n\n      // ignore\n      //    command            modifiers                   arrows\n      if (key === 91 || (15 < key && key < 19) || (37 <= key && key <= 40)) return;\n\n      deferListener(event, this, this.value);\n    });\n\n    // if user modifies input value using context menu in IE, we need \"paste\" and \"cut\" events to catch it\n    if ($sniffer.hasEvent('paste')) {\n      element.on('paste cut', deferListener);\n    }\n  }\n\n  // if user paste into input using mouse on older browser\n  // or form autocomplete on newer browser, we need \"change\" event to catch it\n  element.on('change', listener);\n\n  ctrl.$render = function() {\n    element.val(ctrl.$isEmpty(ctrl.$viewValue) ? '' : ctrl.$viewValue);\n  };\n}\n\nfunction weekParser(isoWeek, existingDate) {\n  if (isDate(isoWeek)) {\n    return isoWeek;\n  }\n\n  if (isString(isoWeek)) {\n    WEEK_REGEXP.lastIndex = 0;\n    var parts = WEEK_REGEXP.exec(isoWeek);\n    if (parts) {\n      var year = +parts[1],\n          week = +parts[2],\n          hours = 0,\n          minutes = 0,\n          seconds = 0,\n          milliseconds = 0,\n          firstThurs = getFirstThursdayOfYear(year),\n          addDays = (week - 1) * 7;\n\n      if (existingDate) {\n        hours = existingDate.getHours();\n        minutes = existingDate.getMinutes();\n        seconds = existingDate.getSeconds();\n        milliseconds = existingDate.getMilliseconds();\n      }\n\n      return new Date(year, 0, firstThurs.getDate() + addDays, hours, minutes, seconds, milliseconds);\n    }\n  }\n\n  return NaN;\n}\n\nfunction createDateParser(regexp, mapping) {\n  return function(iso, date) {\n    var parts, map;\n\n    if (isDate(iso)) {\n      return iso;\n    }\n\n    if (isString(iso)) {\n      // When a date is JSON'ified to wraps itself inside of an extra\n      // set of double quotes. This makes the date parsing code unable\n      // to match the date string and parse it as a date.\n      if (iso.charAt(0) == '\"' && iso.charAt(iso.length - 1) == '\"') {\n        iso = iso.substring(1, iso.length - 1);\n      }\n      if (ISO_DATE_REGEXP.test(iso)) {\n        return new Date(iso);\n      }\n      regexp.lastIndex = 0;\n      parts = regexp.exec(iso);\n\n      if (parts) {\n        parts.shift();\n        if (date) {\n          map = {\n            yyyy: date.getFullYear(),\n            MM: date.getMonth() + 1,\n            dd: date.getDate(),\n            HH: date.getHours(),\n            mm: date.getMinutes(),\n            ss: date.getSeconds(),\n            sss: date.getMilliseconds() / 1000\n          };\n        } else {\n          map = { yyyy: 1970, MM: 1, dd: 1, HH: 0, mm: 0, ss: 0, sss: 0 };\n        }\n\n        forEach(parts, function(part, index) {\n          if (index < mapping.length) {\n            map[mapping[index]] = +part;\n          }\n        });\n        return new Date(map.yyyy, map.MM - 1, map.dd, map.HH, map.mm, map.ss || 0, map.sss * 1000 || 0);\n      }\n    }\n\n    return NaN;\n  };\n}\n\nfunction createDateInputType(type, regexp, parseDate, format) {\n  return function dynamicDateInputType(scope, element, attr, ctrl, $sniffer, $browser, $filter) {\n    badInputChecker(scope, element, attr, ctrl);\n    baseInputType(scope, element, attr, ctrl, $sniffer, $browser);\n    var timezone = ctrl && ctrl.$options && ctrl.$options.timezone;\n    var previousDate;\n\n    ctrl.$$parserName = type;\n    ctrl.$parsers.push(function(value) {\n      if (ctrl.$isEmpty(value)) return null;\n      if (regexp.test(value)) {\n        // Note: We cannot read ctrl.$modelValue, as there might be a different\n        // parser/formatter in the processing chain so that the model\n        // contains some different data format!\n        var parsedDate = parseDate(value, previousDate);\n        if (timezone === 'UTC') {\n          parsedDate.setMinutes(parsedDate.getMinutes() - parsedDate.getTimezoneOffset());\n        }\n        return parsedDate;\n      }\n      return undefined;\n    });\n\n    ctrl.$formatters.push(function(value) {\n      if (value && !isDate(value)) {\n        throw $ngModelMinErr('datefmt', 'Expected `{0}` to be a date', value);\n      }\n      if (isValidDate(value)) {\n        previousDate = value;\n        if (previousDate && timezone === 'UTC') {\n          var timezoneOffset = 60000 * previousDate.getTimezoneOffset();\n          previousDate = new Date(previousDate.getTime() + timezoneOffset);\n        }\n        return $filter('date')(value, format, timezone);\n      } else {\n        previousDate = null;\n        return '';\n      }\n    });\n\n    if (isDefined(attr.min) || attr.ngMin) {\n      var minVal;\n      ctrl.$validators.min = function(value) {\n        return !isValidDate(value) || isUndefined(minVal) || parseDate(value) >= minVal;\n      };\n      attr.$observe('min', function(val) {\n        minVal = parseObservedDateValue(val);\n        ctrl.$validate();\n      });\n    }\n\n    if (isDefined(attr.max) || attr.ngMax) {\n      var maxVal;\n      ctrl.$validators.max = function(value) {\n        return !isValidDate(value) || isUndefined(maxVal) || parseDate(value) <= maxVal;\n      };\n      attr.$observe('max', function(val) {\n        maxVal = parseObservedDateValue(val);\n        ctrl.$validate();\n      });\n    }\n\n    function isValidDate(value) {\n      // Invalid Date: getTime() returns NaN\n      return value && !(value.getTime && value.getTime() !== value.getTime());\n    }\n\n    function parseObservedDateValue(val) {\n      return isDefined(val) ? (isDate(val) ? val : parseDate(val)) : undefined;\n    }\n  };\n}\n\nfunction badInputChecker(scope, element, attr, ctrl) {\n  var node = element[0];\n  var nativeValidation = ctrl.$$hasNativeValidators = isObject(node.validity);\n  if (nativeValidation) {\n    ctrl.$parsers.push(function(value) {\n      var validity = element.prop(VALIDITY_STATE_PROPERTY) || {};\n      // Detect bug in FF35 for input[email] (https://bugzilla.mozilla.org/show_bug.cgi?id=1064430):\n      // - also sets validity.badInput (should only be validity.typeMismatch).\n      // - see http://www.whatwg.org/specs/web-apps/current-work/multipage/forms.html#e-mail-state-(type=email)\n      // - can ignore this case as we can still read out the erroneous email...\n      return validity.badInput && !validity.typeMismatch ? undefined : value;\n    });\n  }\n}\n\nfunction numberInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  badInputChecker(scope, element, attr, ctrl);\n  baseInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  ctrl.$$parserName = 'number';\n  ctrl.$parsers.push(function(value) {\n    if (ctrl.$isEmpty(value))      return null;\n    if (NUMBER_REGEXP.test(value)) return parseFloat(value);\n    return undefined;\n  });\n\n  ctrl.$formatters.push(function(value) {\n    if (!ctrl.$isEmpty(value)) {\n      if (!isNumber(value)) {\n        throw $ngModelMinErr('numfmt', 'Expected `{0}` to be a number', value);\n      }\n      value = value.toString();\n    }\n    return value;\n  });\n\n  if (attr.min || attr.ngMin) {\n    var minVal;\n    ctrl.$validators.min = function(value) {\n      return ctrl.$isEmpty(value) || isUndefined(minVal) || value >= minVal;\n    };\n\n    attr.$observe('min', function(val) {\n      if (isDefined(val) && !isNumber(val)) {\n        val = parseFloat(val, 10);\n      }\n      minVal = isNumber(val) && !isNaN(val) ? val : undefined;\n      // TODO(matsko): implement validateLater to reduce number of validations\n      ctrl.$validate();\n    });\n  }\n\n  if (attr.max || attr.ngMax) {\n    var maxVal;\n    ctrl.$validators.max = function(value) {\n      return ctrl.$isEmpty(value) || isUndefined(maxVal) || value <= maxVal;\n    };\n\n    attr.$observe('max', function(val) {\n      if (isDefined(val) && !isNumber(val)) {\n        val = parseFloat(val, 10);\n      }\n      maxVal = isNumber(val) && !isNaN(val) ? val : undefined;\n      // TODO(matsko): implement validateLater to reduce number of validations\n      ctrl.$validate();\n    });\n  }\n}\n\nfunction urlInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  // Note: no badInputChecker here by purpose as `url` is only a validation\n  // in browsers, i.e. we can always read out input.value even if it is not valid!\n  baseInputType(scope, element, attr, ctrl, $sniffer, $browser);\n  stringBasedInputType(ctrl);\n\n  ctrl.$$parserName = 'url';\n  ctrl.$validators.url = function(modelValue, viewValue) {\n    var value = modelValue || viewValue;\n    return ctrl.$isEmpty(value) || URL_REGEXP.test(value);\n  };\n}\n\nfunction emailInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  // Note: no badInputChecker here by purpose as `url` is only a validation\n  // in browsers, i.e. we can always read out input.value even if it is not valid!\n  baseInputType(scope, element, attr, ctrl, $sniffer, $browser);\n  stringBasedInputType(ctrl);\n\n  ctrl.$$parserName = 'email';\n  ctrl.$validators.email = function(modelValue, viewValue) {\n    var value = modelValue || viewValue;\n    return ctrl.$isEmpty(value) || EMAIL_REGEXP.test(value);\n  };\n}\n\nfunction radioInputType(scope, element, attr, ctrl) {\n  // make the name unique, if not defined\n  if (isUndefined(attr.name)) {\n    element.attr('name', nextUid());\n  }\n\n  var listener = function(ev) {\n    if (element[0].checked) {\n      ctrl.$setViewValue(attr.value, ev && ev.type);\n    }\n  };\n\n  element.on('click', listener);\n\n  ctrl.$render = function() {\n    var value = attr.value;\n    element[0].checked = (value == ctrl.$viewValue);\n  };\n\n  attr.$observe('value', ctrl.$render);\n}\n\nfunction parseConstantExpr($parse, context, name, expression, fallback) {\n  var parseFn;\n  if (isDefined(expression)) {\n    parseFn = $parse(expression);\n    if (!parseFn.constant) {\n      throw minErr('ngModel')('constexpr', 'Expected constant expression for `{0}`, but saw ' +\n                                   '`{1}`.', name, expression);\n    }\n    return parseFn(context);\n  }\n  return fallback;\n}\n\nfunction checkboxInputType(scope, element, attr, ctrl, $sniffer, $browser, $filter, $parse) {\n  var trueValue = parseConstantExpr($parse, scope, 'ngTrueValue', attr.ngTrueValue, true);\n  var falseValue = parseConstantExpr($parse, scope, 'ngFalseValue', attr.ngFalseValue, false);\n\n  var listener = function(ev) {\n    ctrl.$setViewValue(element[0].checked, ev && ev.type);\n  };\n\n  element.on('click', listener);\n\n  ctrl.$render = function() {\n    element[0].checked = ctrl.$viewValue;\n  };\n\n  // Override the standard `$isEmpty` because the $viewValue of an empty checkbox is always set to `false`\n  // This is because of the parser below, which compares the `$modelValue` with `trueValue` to convert\n  // it to a boolean.\n  ctrl.$isEmpty = function(value) {\n    return value === false;\n  };\n\n  ctrl.$formatters.push(function(value) {\n    return equals(value, trueValue);\n  });\n\n  ctrl.$parsers.push(function(value) {\n    return value ? trueValue : falseValue;\n  });\n}\n\n\n/**\n * @ngdoc directive\n * @name textarea\n * @restrict E\n *\n * @description\n * HTML textarea element control with angular data-binding. The data-binding and validation\n * properties of this element are exactly the same as those of the\n * {@link ng.directive:input input element}.\n *\n * @param {string} ngModel Assignable angular expression to data-bind to.\n * @param {string=} name Property name of the form under which the control is published.\n * @param {string=} required Sets `required` validation error key if the value is not entered.\n * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n *    `required` when you want to data-bind to the `required` attribute.\n * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n *    minlength.\n * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n *    maxlength. Setting the attribute to a negative or non-numeric value, allows view values of any\n *    length.\n * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n *    patterns defined as scope expressions.\n * @param {string=} ngChange Angular expression to be executed when input changes due to user\n *    interaction with the input element.\n * @param {boolean=} [ngTrim=true] If set to false Angular will not automatically trim the input.\n */\n\n\n/**\n * @ngdoc directive\n * @name input\n * @restrict E\n *\n * @description\n * HTML input element control. When used together with {@link ngModel `ngModel`}, it provides data-binding,\n * input state control, and validation.\n * Input control follows HTML5 input types and polyfills the HTML5 validation behavior for older browsers.\n *\n * <div class=\"alert alert-warning\">\n * **Note:** Not every feature offered is available for all input types.\n * Specifically, data binding and event handling via `ng-model` is unsupported for `input[file]`.\n * </div>\n *\n * @param {string} ngModel Assignable angular expression to data-bind to.\n * @param {string=} name Property name of the form under which the control is published.\n * @param {string=} required Sets `required` validation error key if the value is not entered.\n * @param {boolean=} ngRequired Sets `required` attribute if set to true\n * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n *    minlength.\n * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n *    maxlength. Setting the attribute to a negative or non-numeric value, allows view values of any\n *    length.\n * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n *    patterns defined as scope expressions.\n * @param {string=} ngChange Angular expression to be executed when input changes due to user\n *    interaction with the input element.\n * @param {boolean=} [ngTrim=true] If set to false Angular will not automatically trim the input.\n *    This parameter is ignored for input[type=password] controls, which will never trim the\n *    input.\n *\n * @example\n    <example name=\"input-directive\" module=\"inputExample\">\n      <file name=\"index.html\">\n       <script>\n          angular.module('inputExample', [])\n            .controller('ExampleController', ['$scope', function($scope) {\n              $scope.user = {name: 'guest', last: 'visitor'};\n            }]);\n       </script>\n       <div ng-controller=\"ExampleController\">\n         <form name=\"myForm\">\n           User name: <input type=\"text\" name=\"userName\" ng-model=\"user.name\" required>\n           <span class=\"error\" ng-show=\"myForm.userName.$error.required\">\n             Required!</span><br>\n           Last name: <input type=\"text\" name=\"lastName\" ng-model=\"user.last\"\n             ng-minlength=\"3\" ng-maxlength=\"10\">\n           <span class=\"error\" ng-show=\"myForm.lastName.$error.minlength\">\n             Too short!</span>\n           <span class=\"error\" ng-show=\"myForm.lastName.$error.maxlength\">\n             Too long!</span><br>\n         </form>\n         <hr>\n         <tt>user = {{user}}</tt><br/>\n         <tt>myForm.userName.$valid = {{myForm.userName.$valid}}</tt><br>\n         <tt>myForm.userName.$error = {{myForm.userName.$error}}</tt><br>\n         <tt>myForm.lastName.$valid = {{myForm.lastName.$valid}}</tt><br>\n         <tt>myForm.lastName.$error = {{myForm.lastName.$error}}</tt><br>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br>\n         <tt>myForm.$error.minlength = {{!!myForm.$error.minlength}}</tt><br>\n         <tt>myForm.$error.maxlength = {{!!myForm.$error.maxlength}}</tt><br>\n       </div>\n      </file>\n      <file name=\"protractor.js\" type=\"protractor\">\n        var user = element(by.exactBinding('user'));\n        var userNameValid = element(by.binding('myForm.userName.$valid'));\n        var lastNameValid = element(by.binding('myForm.lastName.$valid'));\n        var lastNameError = element(by.binding('myForm.lastName.$error'));\n        var formValid = element(by.binding('myForm.$valid'));\n        var userNameInput = element(by.model('user.name'));\n        var userLastInput = element(by.model('user.last'));\n\n        it('should initialize to model', function() {\n          expect(user.getText()).toContain('{\"name\":\"guest\",\"last\":\"visitor\"}');\n          expect(userNameValid.getText()).toContain('true');\n          expect(formValid.getText()).toContain('true');\n        });\n\n        it('should be invalid if empty when required', function() {\n          userNameInput.clear();\n          userNameInput.sendKeys('');\n\n          expect(user.getText()).toContain('{\"last\":\"visitor\"}');\n          expect(userNameValid.getText()).toContain('false');\n          expect(formValid.getText()).toContain('false');\n        });\n\n        it('should be valid if empty when min length is set', function() {\n          userLastInput.clear();\n          userLastInput.sendKeys('');\n\n          expect(user.getText()).toContain('{\"name\":\"guest\",\"last\":\"\"}');\n          expect(lastNameValid.getText()).toContain('true');\n          expect(formValid.getText()).toContain('true');\n        });\n\n        it('should be invalid if less than required min length', function() {\n          userLastInput.clear();\n          userLastInput.sendKeys('xx');\n\n          expect(user.getText()).toContain('{\"name\":\"guest\"}');\n          expect(lastNameValid.getText()).toContain('false');\n          expect(lastNameError.getText()).toContain('minlength');\n          expect(formValid.getText()).toContain('false');\n        });\n\n        it('should be invalid if longer than max length', function() {\n          userLastInput.clear();\n          userLastInput.sendKeys('some ridiculously long name');\n\n          expect(user.getText()).toContain('{\"name\":\"guest\"}');\n          expect(lastNameValid.getText()).toContain('false');\n          expect(lastNameError.getText()).toContain('maxlength');\n          expect(formValid.getText()).toContain('false');\n        });\n      </file>\n    </example>\n */\nvar inputDirective = ['$browser', '$sniffer', '$filter', '$parse',\n    function($browser, $sniffer, $filter, $parse) {\n  return {\n    restrict: 'E',\n    require: ['?ngModel'],\n    link: {\n      pre: function(scope, element, attr, ctrls) {\n        if (ctrls[0]) {\n          (inputType[lowercase(attr.type)] || inputType.text)(scope, element, attr, ctrls[0], $sniffer,\n                                                              $browser, $filter, $parse);\n        }\n      }\n    }\n  };\n}];\n\n\n\nvar CONSTANT_VALUE_REGEXP = /^(true|false|\\d+)$/;\n/**\n * @ngdoc directive\n * @name ngValue\n *\n * @description\n * Binds the given expression to the value of `<option>` or {@link input[radio] `input[radio]`},\n * so that when the element is selected, the {@link ngModel `ngModel`} of that element is set to\n * the bound value.\n *\n * `ngValue` is useful when dynamically generating lists of radio buttons using\n * {@link ngRepeat `ngRepeat`}, as shown below.\n *\n * Likewise, `ngValue` can be used to generate `<option>` elements for\n * the {@link select `select`} element. In that case however, only strings are supported\n * for the `value `attribute, so the resulting `ngModel` will always be a string.\n * Support for `select` models with non-string values is available via `ngOptions`.\n *\n * @element input\n * @param {string=} ngValue angular expression, whose value will be bound to the `value` attribute\n *   of the `input` element\n *\n * @example\n    <example name=\"ngValue-directive\" module=\"valueExample\">\n      <file name=\"index.html\">\n       <script>\n          angular.module('valueExample', [])\n            .controller('ExampleController', ['$scope', function($scope) {\n              $scope.names = ['pizza', 'unicorns', 'robots'];\n              $scope.my = { favorite: 'unicorns' };\n            }]);\n       </script>\n        <form ng-controller=\"ExampleController\">\n          <h2>Which is your favorite?</h2>\n            <label ng-repeat=\"name in names\" for=\"{{name}}\">\n              {{name}}\n              <input type=\"radio\"\n                     ng-model=\"my.favorite\"\n                     ng-value=\"name\"\n                     id=\"{{name}}\"\n                     name=\"favorite\">\n            </label>\n          <div>You chose {{my.favorite}}</div>\n        </form>\n      </file>\n      <file name=\"protractor.js\" type=\"protractor\">\n        var favorite = element(by.binding('my.favorite'));\n\n        it('should initialize to model', function() {\n          expect(favorite.getText()).toContain('unicorns');\n        });\n        it('should bind the values to the inputs', function() {\n          element.all(by.model('my.favorite')).get(0).click();\n          expect(favorite.getText()).toContain('pizza');\n        });\n      </file>\n    </example>\n */\nvar ngValueDirective = function() {\n  return {\n    restrict: 'A',\n    priority: 100,\n    compile: function(tpl, tplAttr) {\n      if (CONSTANT_VALUE_REGEXP.test(tplAttr.ngValue)) {\n        return function ngValueConstantLink(scope, elm, attr) {\n          attr.$set('value', scope.$eval(attr.ngValue));\n        };\n      } else {\n        return function ngValueLink(scope, elm, attr) {\n          scope.$watch(attr.ngValue, function valueWatchAction(value) {\n            attr.$set('value', value);\n          });\n        };\n      }\n    }\n  };\n};\n\n/**\n * @ngdoc directive\n * @name ngBind\n * @restrict AC\n *\n * @description\n * The `ngBind` attribute tells Angular to replace the text content of the specified HTML element\n * with the value of a given expression, and to update the text content when the value of that\n * expression changes.\n *\n * Typically, you don't use `ngBind` directly, but instead you use the double curly markup like\n * `{{ expression }}` which is similar but less verbose.\n *\n * It is preferable to use `ngBind` instead of `{{ expression }}` if a template is momentarily\n * displayed by the browser in its raw state before Angular compiles it. Since `ngBind` is an\n * element attribute, it makes the bindings invisible to the user while the page is loading.\n *\n * An alternative solution to this problem would be using the\n * {@link ng.directive:ngCloak ngCloak} directive.\n *\n *\n * @element ANY\n * @param {expression} ngBind {@link guide/expression Expression} to evaluate.\n *\n * @example\n * Enter a name in the Live Preview text box; the greeting below the text box changes instantly.\n   <example module=\"bindExample\">\n     <file name=\"index.html\">\n       <script>\n         angular.module('bindExample', [])\n           .controller('ExampleController', ['$scope', function($scope) {\n             $scope.name = 'Whirled';\n           }]);\n       </script>\n       <div ng-controller=\"ExampleController\">\n         Enter name: <input type=\"text\" ng-model=\"name\"><br>\n         Hello <span ng-bind=\"name\"></span>!\n       </div>\n     </file>\n     <file name=\"protractor.js\" type=\"protractor\">\n       it('should check ng-bind', function() {\n         var nameInput = element(by.model('name'));\n\n         expect(element(by.binding('name')).getText()).toBe('Whirled');\n         nameInput.clear();\n         nameInput.sendKeys('world');\n         expect(element(by.binding('name')).getText()).toBe('world');\n       });\n     </file>\n   </example>\n */\nvar ngBindDirective = ['$compile', function($compile) {\n  return {\n    restrict: 'AC',\n    compile: function ngBindCompile(templateElement) {\n      $compile.$$addBindingClass(templateElement);\n      return function ngBindLink(scope, element, attr) {\n        $compile.$$addBindingInfo(element, attr.ngBind);\n        element = element[0];\n        scope.$watch(attr.ngBind, function ngBindWatchAction(value) {\n          element.textContent = value === undefined ? '' : value;\n        });\n      };\n    }\n  };\n}];\n\n\n/**\n * @ngdoc directive\n * @name ngBindTemplate\n *\n * @description\n * The `ngBindTemplate` directive specifies that the element\n * text content should be replaced with the interpolation of the template\n * in the `ngBindTemplate` attribute.\n * Unlike `ngBind`, the `ngBindTemplate` can contain multiple `{{` `}}`\n * expressions. This directive is needed since some HTML elements\n * (such as TITLE and OPTION) cannot contain SPAN elements.\n *\n * @element ANY\n * @param {string} ngBindTemplate template of form\n *   <tt>{{</tt> <tt>expression</tt> <tt>}}</tt> to eval.\n *\n * @example\n * Try it here: enter text in text box and watch the greeting change.\n   <example module=\"bindExample\">\n     <file name=\"index.html\">\n       <script>\n         angular.module('bindExample', [])\n           .controller('ExampleController', ['$scope', function($scope) {\n             $scope.salutation = 'Hello';\n             $scope.name = 'World';\n           }]);\n       </script>\n       <div ng-controller=\"ExampleController\">\n        Salutation: <input type=\"text\" ng-model=\"salutation\"><br>\n        Name: <input type=\"text\" ng-model=\"name\"><br>\n        <pre ng-bind-template=\"{{salutation}} {{name}}!\"></pre>\n       </div>\n     </file>\n     <file name=\"protractor.js\" type=\"protractor\">\n       it('should check ng-bind', function() {\n         var salutationElem = element(by.binding('salutation'));\n         var salutationInput = element(by.model('salutation'));\n         var nameInput = element(by.model('name'));\n\n         expect(salutationElem.getText()).toBe('Hello World!');\n\n         salutationInput.clear();\n         salutationInput.sendKeys('Greetings');\n         nameInput.clear();\n         nameInput.sendKeys('user');\n\n         expect(salutationElem.getText()).toBe('Greetings user!');\n       });\n     </file>\n   </example>\n */\nvar ngBindTemplateDirective = ['$interpolate', '$compile', function($interpolate, $compile) {\n  return {\n    compile: function ngBindTemplateCompile(templateElement) {\n      $compile.$$addBindingClass(templateElement);\n      return function ngBindTemplateLink(scope, element, attr) {\n        var interpolateFn = $interpolate(element.attr(attr.$attr.ngBindTemplate));\n        $compile.$$addBindingInfo(element, interpolateFn.expressions);\n        element = element[0];\n        attr.$observe('ngBindTemplate', function(value) {\n          element.textContent = value === undefined ? '' : value;\n        });\n      };\n    }\n  };\n}];\n\n\n/**\n * @ngdoc directive\n * @name ngBindHtml\n *\n * @description\n * Evaluates the expression and inserts the resulting HTML into the element in a secure way. By default,\n * the resulting HTML content will be sanitized using the {@link ngSanitize.$sanitize $sanitize} service.\n * To utilize this functionality, ensure that `$sanitize` is available, for example, by including {@link\n * ngSanitize} in your module's dependencies (not in core Angular). In order to use {@link ngSanitize}\n * in your module's dependencies, you need to include \"angular-sanitize.js\" in your application.\n *\n * You may also bypass sanitization for values you know are safe. To do so, bind to\n * an explicitly trusted value via {@link ng.$sce#trustAsHtml $sce.trustAsHtml}.  See the example\n * under {@link ng.$sce#show-me-an-example-using-sce- Strict Contextual Escaping (SCE)}.\n *\n * Note: If a `$sanitize` service is unavailable and the bound value isn't explicitly trusted, you\n * will have an exception (instead of an exploit.)\n *\n * @element ANY\n * @param {expression} ngBindHtml {@link guide/expression Expression} to evaluate.\n *\n * @example\n\n   <example module=\"bindHtmlExample\" deps=\"angular-sanitize.js\">\n     <file name=\"index.html\">\n       <div ng-controller=\"ExampleController\">\n        <p ng-bind-html=\"myHTML\"></p>\n       </div>\n     </file>\n\n     <file name=\"script.js\">\n       angular.module('bindHtmlExample', ['ngSanitize'])\n         .controller('ExampleController', ['$scope', function($scope) {\n           $scope.myHTML =\n              'I am an <code>HTML</code>string with ' +\n              '<a href=\"#\">links!</a> and other <em>stuff</em>';\n         }]);\n     </file>\n\n     <file name=\"protractor.js\" type=\"protractor\">\n       it('should check ng-bind-html', function() {\n         expect(element(by.binding('myHTML')).getText()).toBe(\n             'I am an HTMLstring with links! and other stuff');\n       });\n     </file>\n   </example>\n */\nvar ngBindHtmlDirective = ['$sce', '$parse', '$compile', function($sce, $parse, $compile) {\n  return {\n    restrict: 'A',\n    compile: function ngBindHtmlCompile(tElement, tAttrs) {\n      var ngBindHtmlGetter = $parse(tAttrs.ngBindHtml);\n      var ngBindHtmlWatch = $parse(tAttrs.ngBindHtml, function getStringValue(value) {\n        return (value || '').toString();\n      });\n      $compile.$$addBindingClass(tElement);\n\n      return function ngBindHtmlLink(scope, element, attr) {\n        $compile.$$addBindingInfo(element, attr.ngBindHtml);\n\n        scope.$watch(ngBindHtmlWatch, function ngBindHtmlWatchAction() {\n          // we re-evaluate the expr because we want a TrustedValueHolderType\n          // for $sce, not a string\n          element.html($sce.getTrustedHtml(ngBindHtmlGetter(scope)) || '');\n        });\n      };\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ngChange\n *\n * @description\n * Evaluate the given expression when the user changes the input.\n * The expression is evaluated immediately, unlike the JavaScript onchange event\n * which only triggers at the end of a change (usually, when the user leaves the\n * form element or presses the return key).\n *\n * The `ngChange` expression is only evaluated when a change in the input value causes\n * a new value to be committed to the model.\n *\n * It will not be evaluated:\n * * if the value returned from the `$parsers` transformation pipeline has not changed\n * * if the input has continued to be invalid since the model will stay `null`\n * * if the model is changed programmatically and not by a change to the input value\n *\n *\n * Note, this directive requires `ngModel` to be present.\n *\n * @element input\n * @param {expression} ngChange {@link guide/expression Expression} to evaluate upon change\n * in input value.\n *\n * @example\n * <example name=\"ngChange-directive\" module=\"changeExample\">\n *   <file name=\"index.html\">\n *     <script>\n *       angular.module('changeExample', [])\n *         .controller('ExampleController', ['$scope', function($scope) {\n *           $scope.counter = 0;\n *           $scope.change = function() {\n *             $scope.counter++;\n *           };\n *         }]);\n *     </script>\n *     <div ng-controller=\"ExampleController\">\n *       <input type=\"checkbox\" ng-model=\"confirmed\" ng-change=\"change()\" id=\"ng-change-example1\" />\n *       <input type=\"checkbox\" ng-model=\"confirmed\" id=\"ng-change-example2\" />\n *       <label for=\"ng-change-example2\">Confirmed</label><br />\n *       <tt>debug = {{confirmed}}</tt><br/>\n *       <tt>counter = {{counter}}</tt><br/>\n *     </div>\n *   </file>\n *   <file name=\"protractor.js\" type=\"protractor\">\n *     var counter = element(by.binding('counter'));\n *     var debug = element(by.binding('confirmed'));\n *\n *     it('should evaluate the expression if changing from view', function() {\n *       expect(counter.getText()).toContain('0');\n *\n *       element(by.id('ng-change-example1')).click();\n *\n *       expect(counter.getText()).toContain('1');\n *       expect(debug.getText()).toContain('true');\n *     });\n *\n *     it('should not evaluate the expression if changing from model', function() {\n *       element(by.id('ng-change-example2')).click();\n\n *       expect(counter.getText()).toContain('0');\n *       expect(debug.getText()).toContain('true');\n *     });\n *   </file>\n * </example>\n */\nvar ngChangeDirective = valueFn({\n  restrict: 'A',\n  require: 'ngModel',\n  link: function(scope, element, attr, ctrl) {\n    ctrl.$viewChangeListeners.push(function() {\n      scope.$eval(attr.ngChange);\n    });\n  }\n});\n\nfunction classDirective(name, selector) {\n  name = 'ngClass' + name;\n  return ['$animate', function($animate) {\n    return {\n      restrict: 'AC',\n      link: function(scope, element, attr) {\n        var oldVal;\n\n        scope.$watch(attr[name], ngClassWatchAction, true);\n\n        attr.$observe('class', function(value) {\n          ngClassWatchAction(scope.$eval(attr[name]));\n        });\n\n\n        if (name !== 'ngClass') {\n          scope.$watch('$index', function($index, old$index) {\n            // jshint bitwise: false\n            var mod = $index & 1;\n            if (mod !== (old$index & 1)) {\n              var classes = arrayClasses(scope.$eval(attr[name]));\n              mod === selector ?\n                addClasses(classes) :\n                removeClasses(classes);\n            }\n          });\n        }\n\n        function addClasses(classes) {\n          var newClasses = digestClassCounts(classes, 1);\n          attr.$addClass(newClasses);\n        }\n\n        function removeClasses(classes) {\n          var newClasses = digestClassCounts(classes, -1);\n          attr.$removeClass(newClasses);\n        }\n\n        function digestClassCounts(classes, count) {\n          var classCounts = element.data('$classCounts') || {};\n          var classesToUpdate = [];\n          forEach(classes, function(className) {\n            if (count > 0 || classCounts[className]) {\n              classCounts[className] = (classCounts[className] || 0) + count;\n              if (classCounts[className] === +(count > 0)) {\n                classesToUpdate.push(className);\n              }\n            }\n          });\n          element.data('$classCounts', classCounts);\n          return classesToUpdate.join(' ');\n        }\n\n        function updateClasses(oldClasses, newClasses) {\n          var toAdd = arrayDifference(newClasses, oldClasses);\n          var toRemove = arrayDifference(oldClasses, newClasses);\n          toAdd = digestClassCounts(toAdd, 1);\n          toRemove = digestClassCounts(toRemove, -1);\n          if (toAdd && toAdd.length) {\n            $animate.addClass(element, toAdd);\n          }\n          if (toRemove && toRemove.length) {\n            $animate.removeClass(element, toRemove);\n          }\n        }\n\n        function ngClassWatchAction(newVal) {\n          if (selector === true || scope.$index % 2 === selector) {\n            var newClasses = arrayClasses(newVal || []);\n            if (!oldVal) {\n              addClasses(newClasses);\n            } else if (!equals(newVal,oldVal)) {\n              var oldClasses = arrayClasses(oldVal);\n              updateClasses(oldClasses, newClasses);\n            }\n          }\n          oldVal = shallowCopy(newVal);\n        }\n      }\n    };\n\n    function arrayDifference(tokens1, tokens2) {\n      var values = [];\n\n      outer:\n      for (var i = 0; i < tokens1.length; i++) {\n        var token = tokens1[i];\n        for (var j = 0; j < tokens2.length; j++) {\n          if (token == tokens2[j]) continue outer;\n        }\n        values.push(token);\n      }\n      return values;\n    }\n\n    function arrayClasses(classVal) {\n      if (isArray(classVal)) {\n        return classVal;\n      } else if (isString(classVal)) {\n        return classVal.split(' ');\n      } else if (isObject(classVal)) {\n        var classes = [];\n        forEach(classVal, function(v, k) {\n          if (v) {\n            classes = classes.concat(k.split(' '));\n          }\n        });\n        return classes;\n      }\n      return classVal;\n    }\n  }];\n}\n\n/**\n * @ngdoc directive\n * @name ngClass\n * @restrict AC\n *\n * @description\n * The `ngClass` directive allows you to dynamically set CSS classes on an HTML element by databinding\n * an expression that represents all classes to be added.\n *\n * The directive operates in three different ways, depending on which of three types the expression\n * evaluates to:\n *\n * 1. If the expression evaluates to a string, the string should be one or more space-delimited class\n * names.\n *\n * 2. If the expression evaluates to an array, each element of the array should be a string that is\n * one or more space-delimited class names.\n *\n * 3. If the expression evaluates to an object, then for each key-value pair of the\n * object with a truthy value the corresponding key is used as a class name.\n *\n * The directive won't add duplicate classes if a particular class was already set.\n *\n * When the expression changes, the previously added classes are removed and only then the\n * new classes are added.\n *\n * @animations\n * **add** - happens just before the class is applied to the elements\n *\n * **remove** - happens just before the class is removed from the element\n *\n * @element ANY\n * @param {expression} ngClass {@link guide/expression Expression} to eval. The result\n *   of the evaluation can be a string representing space delimited class\n *   names, an array, or a map of class names to boolean values. In the case of a map, the\n *   names of the properties whose values are truthy will be added as css classes to the\n *   element.\n *\n * @example Example that demonstrates basic bindings via ngClass directive.\n   <example>\n     <file name=\"index.html\">\n       <p ng-class=\"{strike: deleted, bold: important, red: error}\">Map Syntax Example</p>\n       <input type=\"checkbox\" ng-model=\"deleted\"> deleted (apply \"strike\" class)<br>\n       <input type=\"checkbox\" ng-model=\"important\"> important (apply \"bold\" class)<br>\n       <input type=\"checkbox\" ng-model=\"error\"> error (apply \"red\" class)\n       <hr>\n       <p ng-class=\"style\">Using String Syntax</p>\n       <input type=\"text\" ng-model=\"style\" placeholder=\"Type: bold strike red\">\n       <hr>\n       <p ng-class=\"[style1, style2, style3]\">Using Array Syntax</p>\n       <input ng-model=\"style1\" placeholder=\"Type: bold, strike or red\"><br>\n       <input ng-model=\"style2\" placeholder=\"Type: bold, strike or red\"><br>\n       <input ng-model=\"style3\" placeholder=\"Type: bold, strike or red\"><br>\n     </file>\n     <file name=\"style.css\">\n       .strike {\n         text-decoration: line-through;\n       }\n       .bold {\n           font-weight: bold;\n       }\n       .red {\n           color: red;\n       }\n     </file>\n     <file name=\"protractor.js\" type=\"protractor\">\n       var ps = element.all(by.css('p'));\n\n       it('should let you toggle the class', function() {\n\n         expect(ps.first().getAttribute('class')).not.toMatch(/bold/);\n         expect(ps.first().getAttribute('class')).not.toMatch(/red/);\n\n         element(by.model('important')).click();\n         expect(ps.first().getAttribute('class')).toMatch(/bold/);\n\n         element(by.model('error')).click();\n         expect(ps.first().getAttribute('class')).toMatch(/red/);\n       });\n\n       it('should let you toggle string example', function() {\n         expect(ps.get(1).getAttribute('class')).toBe('');\n         element(by.model('style')).clear();\n         element(by.model('style')).sendKeys('red');\n         expect(ps.get(1).getAttribute('class')).toBe('red');\n       });\n\n       it('array example should have 3 classes', function() {\n         expect(ps.last().getAttribute('class')).toBe('');\n         element(by.model('style1')).sendKeys('bold');\n         element(by.model('style2')).sendKeys('strike');\n         element(by.model('style3')).sendKeys('red');\n         expect(ps.last().getAttribute('class')).toBe('bold strike red');\n       });\n     </file>\n   </example>\n\n   ## Animations\n\n   The example below demonstrates how to perform animations using ngClass.\n\n   <example module=\"ngAnimate\" deps=\"angular-animate.js\" animations=\"true\">\n     <file name=\"index.html\">\n      <input id=\"setbtn\" type=\"button\" value=\"set\" ng-click=\"myVar='my-class'\">\n      <input id=\"clearbtn\" type=\"button\" value=\"clear\" ng-click=\"myVar=''\">\n      <br>\n      <span class=\"base-class\" ng-class=\"myVar\">Sample Text</span>\n     </file>\n     <file name=\"style.css\">\n       .base-class {\n         -webkit-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;\n         transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;\n       }\n\n       .base-class.my-class {\n         color: red;\n         font-size:3em;\n       }\n     </file>\n     <file name=\"protractor.js\" type=\"protractor\">\n       it('should check ng-class', function() {\n         expect(element(by.css('.base-class')).getAttribute('class')).not.\n           toMatch(/my-class/);\n\n         element(by.id('setbtn')).click();\n\n         expect(element(by.css('.base-class')).getAttribute('class')).\n           toMatch(/my-class/);\n\n         element(by.id('clearbtn')).click();\n\n         expect(element(by.css('.base-class')).getAttribute('class')).not.\n           toMatch(/my-class/);\n       });\n     </file>\n   </example>\n\n\n   ## ngClass and pre-existing CSS3 Transitions/Animations\n   The ngClass directive still supports CSS3 Transitions/Animations even if they do not follow the ngAnimate CSS naming structure.\n   Upon animation ngAnimate will apply supplementary CSS classes to track the start and end of an animation, but this will not hinder\n   any pre-existing CSS transitions already on the element. To get an idea of what happens during a class-based animation, be sure\n   to view the step by step details of {@link ng.$animate#addClass $animate.addClass} and\n   {@link ng.$animate#removeClass $animate.removeClass}.\n */\nvar ngClassDirective = classDirective('', true);\n\n/**\n * @ngdoc directive\n * @name ngClassOdd\n * @restrict AC\n *\n * @description\n * The `ngClassOdd` and `ngClassEven` directives work exactly as\n * {@link ng.directive:ngClass ngClass}, except they work in\n * conjunction with `ngRepeat` and take effect only on odd (even) rows.\n *\n * This directive can be applied only within the scope of an\n * {@link ng.directive:ngRepeat ngRepeat}.\n *\n * @element ANY\n * @param {expression} ngClassOdd {@link guide/expression Expression} to eval. The result\n *   of the evaluation can be a string representing space delimited class names or an array.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <ol ng-init=\"names=['John', 'Mary', 'Cate', 'Suz']\">\n          <li ng-repeat=\"name in names\">\n           <span ng-class-odd=\"'odd'\" ng-class-even=\"'even'\">\n             {{name}}\n           </span>\n          </li>\n        </ol>\n     </file>\n     <file name=\"style.css\">\n       .odd {\n         color: red;\n       }\n       .even {\n         color: blue;\n       }\n     </file>\n     <file name=\"protractor.js\" type=\"protractor\">\n       it('should check ng-class-odd and ng-class-even', function() {\n         expect(element(by.repeater('name in names').row(0).column('name')).getAttribute('class')).\n           toMatch(/odd/);\n         expect(element(by.repeater('name in names').row(1).column('name')).getAttribute('class')).\n           toMatch(/even/);\n       });\n     </file>\n   </example>\n */\nvar ngClassOddDirective = classDirective('Odd', 0);\n\n/**\n * @ngdoc directive\n * @name ngClassEven\n * @restrict AC\n *\n * @description\n * The `ngClassOdd` and `ngClassEven` directives work exactly as\n * {@link ng.directive:ngClass ngClass}, except they work in\n * conjunction with `ngRepeat` and take effect only on odd (even) rows.\n *\n * This directive can be applied only within the scope of an\n * {@link ng.directive:ngRepeat ngRepeat}.\n *\n * @element ANY\n * @param {expression} ngClassEven {@link guide/expression Expression} to eval. The\n *   result of the evaluation can be a string representing space delimited class names or an array.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <ol ng-init=\"names=['John', 'Mary', 'Cate', 'Suz']\">\n          <li ng-repeat=\"name in names\">\n           <span ng-class-odd=\"'odd'\" ng-class-even=\"'even'\">\n             {{name}} &nbsp; &nbsp; &nbsp;\n           </span>\n          </li>\n        </ol>\n     </file>\n     <file name=\"style.css\">\n       .odd {\n         color: red;\n       }\n       .even {\n         color: blue;\n       }\n     </file>\n     <file name=\"protractor.js\" type=\"protractor\">\n       it('should check ng-class-odd and ng-class-even', function() {\n         expect(element(by.repeater('name in names').row(0).column('name')).getAttribute('class')).\n           toMatch(/odd/);\n         expect(element(by.repeater('name in names').row(1).column('name')).getAttribute('class')).\n           toMatch(/even/);\n       });\n     </file>\n   </example>\n */\nvar ngClassEvenDirective = classDirective('Even', 1);\n\n/**\n * @ngdoc directive\n * @name ngCloak\n * @restrict AC\n *\n * @description\n * The `ngCloak` directive is used to prevent the Angular html template from being briefly\n * displayed by the browser in its raw (uncompiled) form while your application is loading. Use this\n * directive to avoid the undesirable flicker effect caused by the html template display.\n *\n * The directive can be applied to the `<body>` element, but the preferred usage is to apply\n * multiple `ngCloak` directives to small portions of the page to permit progressive rendering\n * of the browser view.\n *\n * `ngCloak` works in cooperation with the following css rule embedded within `angular.js` and\n * `angular.min.js`.\n * For CSP mode please add `angular-csp.css` to your html file (see {@link ng.directive:ngCsp ngCsp}).\n *\n * ```css\n * [ng\\:cloak], [ng-cloak], [data-ng-cloak], [x-ng-cloak], .ng-cloak, .x-ng-cloak {\n *   display: none !important;\n * }\n * ```\n *\n * When this css rule is loaded by the browser, all html elements (including their children) that\n * are tagged with the `ngCloak` directive are hidden. When Angular encounters this directive\n * during the compilation of the template it deletes the `ngCloak` element attribute, making\n * the compiled element visible.\n *\n * For the best result, the `angular.js` script must be loaded in the head section of the html\n * document; alternatively, the css rule above must be included in the external stylesheet of the\n * application.\n *\n * Legacy browsers, like IE7, do not provide attribute selector support (added in CSS 2.1) so they\n * cannot match the `[ng\\:cloak]` selector. To work around this limitation, you must add the css\n * class `ng-cloak` in addition to the `ngCloak` directive as shown in the example below.\n *\n * @element ANY\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <div id=\"template1\" ng-cloak>{{ 'hello' }}</div>\n        <div id=\"template2\" ng-cloak class=\"ng-cloak\">{{ 'hello IE7' }}</div>\n     </file>\n     <file name=\"protractor.js\" type=\"protractor\">\n       it('should remove the template directive and css class', function() {\n         expect($('#template1').getAttribute('ng-cloak')).\n           toBeNull();\n         expect($('#template2').getAttribute('ng-cloak')).\n           toBeNull();\n       });\n     </file>\n   </example>\n *\n */\nvar ngCloakDirective = ngDirective({\n  compile: function(element, attr) {\n    attr.$set('ngCloak', undefined);\n    element.removeClass('ng-cloak');\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ngController\n *\n * @description\n * The `ngController` directive attaches a controller class to the view. This is a key aspect of how angular\n * supports the principles behind the Model-View-Controller design pattern.\n *\n * MVC components in angular:\n *\n * * Model — Models are the properties of a scope; scopes are attached to the DOM where scope properties\n *   are accessed through bindings.\n * * View — The template (HTML with data bindings) that is rendered into the View.\n * * Controller — The `ngController` directive specifies a Controller class; the class contains business\n *   logic behind the application to decorate the scope with functions and values\n *\n * Note that you can also attach controllers to the DOM by declaring it in a route definition\n * via the {@link ngRoute.$route $route} service. A common mistake is to declare the controller\n * again using `ng-controller` in the template itself.  This will cause the controller to be attached\n * and executed twice.\n *\n * @element ANY\n * @scope\n * @priority 500\n * @param {expression} ngController Name of a constructor function registered with the current\n * {@link ng.$controllerProvider $controllerProvider} or an {@link guide/expression expression}\n * that on the current scope evaluates to a constructor function.\n *\n * The controller instance can be published into a scope property by specifying\n * `ng-controller=\"as propertyName\"`.\n *\n * If the current `$controllerProvider` is configured to use globals (via\n * {@link ng.$controllerProvider#allowGlobals `$controllerProvider.allowGlobals()` }), this may\n * also be the name of a globally accessible constructor function (not recommended).\n *\n * @example\n * Here is a simple form for editing user contact information. Adding, removing, clearing, and\n * greeting are methods declared on the controller (see source tab). These methods can\n * easily be called from the angular markup. Any changes to the data are automatically reflected\n * in the View without the need for a manual update.\n *\n * Two different declaration styles are included below:\n *\n * * one binds methods and properties directly onto the controller using `this`:\n * `ng-controller=\"SettingsController1 as settings\"`\n * * one injects `$scope` into the controller:\n * `ng-controller=\"SettingsController2\"`\n *\n * The second option is more common in the Angular community, and is generally used in boilerplates\n * and in this guide. However, there are advantages to binding properties directly to the controller\n * and avoiding scope.\n *\n * * Using `controller as` makes it obvious which controller you are accessing in the template when\n * multiple controllers apply to an element.\n * * If you are writing your controllers as classes you have easier access to the properties and\n * methods, which will appear on the scope, from inside the controller code.\n * * Since there is always a `.` in the bindings, you don't have to worry about prototypal\n * inheritance masking primitives.\n *\n * This example demonstrates the `controller as` syntax.\n *\n * <example name=\"ngControllerAs\" module=\"controllerAsExample\">\n *   <file name=\"index.html\">\n *    <div id=\"ctrl-as-exmpl\" ng-controller=\"SettingsController1 as settings\">\n *      Name: <input type=\"text\" ng-model=\"settings.name\"/>\n *      [ <a href=\"\" ng-click=\"settings.greet()\">greet</a> ]<br/>\n *      Contact:\n *      <ul>\n *        <li ng-repeat=\"contact in settings.contacts\">\n *          <select ng-model=\"contact.type\">\n *             <option>phone</option>\n *             <option>email</option>\n *          </select>\n *          <input type=\"text\" ng-model=\"contact.value\"/>\n *          [ <a href=\"\" ng-click=\"settings.clearContact(contact)\">clear</a>\n *          | <a href=\"\" ng-click=\"settings.removeContact(contact)\">X</a> ]\n *        </li>\n *        <li>[ <a href=\"\" ng-click=\"settings.addContact()\">add</a> ]</li>\n *     </ul>\n *    </div>\n *   </file>\n *   <file name=\"app.js\">\n *    angular.module('controllerAsExample', [])\n *      .controller('SettingsController1', SettingsController1);\n *\n *    function SettingsController1() {\n *      this.name = \"John Smith\";\n *      this.contacts = [\n *        {type: 'phone', value: '408 555 1212'},\n *        {type: 'email', value: 'john.smith@example.org'} ];\n *    }\n *\n *    SettingsController1.prototype.greet = function() {\n *      alert(this.name);\n *    };\n *\n *    SettingsController1.prototype.addContact = function() {\n *      this.contacts.push({type: 'email', value: 'yourname@example.org'});\n *    };\n *\n *    SettingsController1.prototype.removeContact = function(contactToRemove) {\n *     var index = this.contacts.indexOf(contactToRemove);\n *      this.contacts.splice(index, 1);\n *    };\n *\n *    SettingsController1.prototype.clearContact = function(contact) {\n *      contact.type = 'phone';\n *      contact.value = '';\n *    };\n *   </file>\n *   <file name=\"protractor.js\" type=\"protractor\">\n *     it('should check controller as', function() {\n *       var container = element(by.id('ctrl-as-exmpl'));\n *         expect(container.element(by.model('settings.name'))\n *           .getAttribute('value')).toBe('John Smith');\n *\n *       var firstRepeat =\n *           container.element(by.repeater('contact in settings.contacts').row(0));\n *       var secondRepeat =\n *           container.element(by.repeater('contact in settings.contacts').row(1));\n *\n *       expect(firstRepeat.element(by.model('contact.value')).getAttribute('value'))\n *           .toBe('408 555 1212');\n *\n *       expect(secondRepeat.element(by.model('contact.value')).getAttribute('value'))\n *           .toBe('john.smith@example.org');\n *\n *       firstRepeat.element(by.linkText('clear')).click();\n *\n *       expect(firstRepeat.element(by.model('contact.value')).getAttribute('value'))\n *           .toBe('');\n *\n *       container.element(by.linkText('add')).click();\n *\n *       expect(container.element(by.repeater('contact in settings.contacts').row(2))\n *           .element(by.model('contact.value'))\n *           .getAttribute('value'))\n *           .toBe('yourname@example.org');\n *     });\n *   </file>\n * </example>\n *\n * This example demonstrates the \"attach to `$scope`\" style of controller.\n *\n * <example name=\"ngController\" module=\"controllerExample\">\n *  <file name=\"index.html\">\n *   <div id=\"ctrl-exmpl\" ng-controller=\"SettingsController2\">\n *     Name: <input type=\"text\" ng-model=\"name\"/>\n *     [ <a href=\"\" ng-click=\"greet()\">greet</a> ]<br/>\n *     Contact:\n *     <ul>\n *       <li ng-repeat=\"contact in contacts\">\n *         <select ng-model=\"contact.type\">\n *            <option>phone</option>\n *            <option>email</option>\n *         </select>\n *         <input type=\"text\" ng-model=\"contact.value\"/>\n *         [ <a href=\"\" ng-click=\"clearContact(contact)\">clear</a>\n *         | <a href=\"\" ng-click=\"removeContact(contact)\">X</a> ]\n *       </li>\n *       <li>[ <a href=\"\" ng-click=\"addContact()\">add</a> ]</li>\n *    </ul>\n *   </div>\n *  </file>\n *  <file name=\"app.js\">\n *   angular.module('controllerExample', [])\n *     .controller('SettingsController2', ['$scope', SettingsController2]);\n *\n *   function SettingsController2($scope) {\n *     $scope.name = \"John Smith\";\n *     $scope.contacts = [\n *       {type:'phone', value:'408 555 1212'},\n *       {type:'email', value:'john.smith@example.org'} ];\n *\n *     $scope.greet = function() {\n *       alert($scope.name);\n *     };\n *\n *     $scope.addContact = function() {\n *       $scope.contacts.push({type:'email', value:'yourname@example.org'});\n *     };\n *\n *     $scope.removeContact = function(contactToRemove) {\n *       var index = $scope.contacts.indexOf(contactToRemove);\n *       $scope.contacts.splice(index, 1);\n *     };\n *\n *     $scope.clearContact = function(contact) {\n *       contact.type = 'phone';\n *       contact.value = '';\n *     };\n *   }\n *  </file>\n *  <file name=\"protractor.js\" type=\"protractor\">\n *    it('should check controller', function() {\n *      var container = element(by.id('ctrl-exmpl'));\n *\n *      expect(container.element(by.model('name'))\n *          .getAttribute('value')).toBe('John Smith');\n *\n *      var firstRepeat =\n *          container.element(by.repeater('contact in contacts').row(0));\n *      var secondRepeat =\n *          container.element(by.repeater('contact in contacts').row(1));\n *\n *      expect(firstRepeat.element(by.model('contact.value')).getAttribute('value'))\n *          .toBe('408 555 1212');\n *      expect(secondRepeat.element(by.model('contact.value')).getAttribute('value'))\n *          .toBe('john.smith@example.org');\n *\n *      firstRepeat.element(by.linkText('clear')).click();\n *\n *      expect(firstRepeat.element(by.model('contact.value')).getAttribute('value'))\n *          .toBe('');\n *\n *      container.element(by.linkText('add')).click();\n *\n *      expect(container.element(by.repeater('contact in contacts').row(2))\n *          .element(by.model('contact.value'))\n *          .getAttribute('value'))\n *          .toBe('yourname@example.org');\n *    });\n *  </file>\n *</example>\n\n */\nvar ngControllerDirective = [function() {\n  return {\n    restrict: 'A',\n    scope: true,\n    controller: '@',\n    priority: 500\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ngCsp\n *\n * @element html\n * @description\n * Enables [CSP (Content Security Policy)](https://developer.mozilla.org/en/Security/CSP) support.\n *\n * This is necessary when developing things like Google Chrome Extensions or Universal Windows Apps.\n *\n * CSP forbids apps to use `eval` or `Function(string)` generated functions (among other things).\n * For Angular to be CSP compatible there are only two things that we need to do differently:\n *\n * - don't use `Function` constructor to generate optimized value getters\n * - don't inject custom stylesheet into the document\n *\n * AngularJS uses `Function(string)` generated functions as a speed optimization. Applying the `ngCsp`\n * directive will cause Angular to use CSP compatibility mode. When this mode is on AngularJS will\n * evaluate all expressions up to 30% slower than in non-CSP mode, but no security violations will\n * be raised.\n *\n * CSP forbids JavaScript to inline stylesheet rules. In non CSP mode Angular automatically\n * includes some CSS rules (e.g. {@link ng.directive:ngCloak ngCloak}).\n * To make those directives work in CSP mode, include the `angular-csp.css` manually.\n *\n * Angular tries to autodetect if CSP is active and automatically turn on the CSP-safe mode. This\n * autodetection however triggers a CSP error to be logged in the console:\n *\n * ```\n * Refused to evaluate a string as JavaScript because 'unsafe-eval' is not an allowed source of\n * script in the following Content Security Policy directive: \"default-src 'self'\". Note that\n * 'script-src' was not explicitly set, so 'default-src' is used as a fallback.\n * ```\n *\n * This error is harmless but annoying. To prevent the error from showing up, put the `ngCsp`\n * directive on the root element of the application or on the `angular.js` script tag, whichever\n * appears first in the html document.\n *\n * *Note: This directive is only available in the `ng-csp` and `data-ng-csp` attribute form.*\n *\n * @example\n * This example shows how to apply the `ngCsp` directive to the `html` tag.\n   ```html\n     <!doctype html>\n     <html ng-app ng-csp>\n     ...\n     ...\n     </html>\n   ```\n  * @example\n      // Note: the suffix `.csp` in the example name triggers\n      // csp mode in our http server!\n      <example name=\"example.csp\" module=\"cspExample\" ng-csp=\"true\">\n        <file name=\"index.html\">\n          <div ng-controller=\"MainController as ctrl\">\n            <div>\n              <button ng-click=\"ctrl.inc()\" id=\"inc\">Increment</button>\n              <span id=\"counter\">\n                {{ctrl.counter}}\n              </span>\n            </div>\n\n            <div>\n              <button ng-click=\"ctrl.evil()\" id=\"evil\">Evil</button>\n              <span id=\"evilError\">\n                {{ctrl.evilError}}\n              </span>\n            </div>\n          </div>\n        </file>\n        <file name=\"script.js\">\n           angular.module('cspExample', [])\n             .controller('MainController', function() {\n                this.counter = 0;\n                this.inc = function() {\n                  this.counter++;\n                };\n                this.evil = function() {\n                  // jshint evil:true\n                  try {\n                    eval('1+2');\n                  } catch (e) {\n                    this.evilError = e.message;\n                  }\n                };\n              });\n        </file>\n        <file name=\"protractor.js\" type=\"protractor\">\n          var util, webdriver;\n\n          var incBtn = element(by.id('inc'));\n          var counter = element(by.id('counter'));\n          var evilBtn = element(by.id('evil'));\n          var evilError = element(by.id('evilError'));\n\n          function getAndClearSevereErrors() {\n            return browser.manage().logs().get('browser').then(function(browserLog) {\n              return browserLog.filter(function(logEntry) {\n                return logEntry.level.value > webdriver.logging.Level.WARNING.value;\n              });\n            });\n          }\n\n          function clearErrors() {\n            getAndClearSevereErrors();\n          }\n\n          function expectNoErrors() {\n            getAndClearSevereErrors().then(function(filteredLog) {\n              expect(filteredLog.length).toEqual(0);\n              if (filteredLog.length) {\n                console.log('browser console errors: ' + util.inspect(filteredLog));\n              }\n            });\n          }\n\n          function expectError(regex) {\n            getAndClearSevereErrors().then(function(filteredLog) {\n              var found = false;\n              filteredLog.forEach(function(log) {\n                if (log.message.match(regex)) {\n                  found = true;\n                }\n              });\n              if (!found) {\n                throw new Error('expected an error that matches ' + regex);\n              }\n            });\n          }\n\n          beforeEach(function() {\n            util = require('util');\n            webdriver = require('protractor/node_modules/selenium-webdriver');\n          });\n\n          // For now, we only test on Chrome,\n          // as Safari does not load the page with Protractor's injected scripts,\n          // and Firefox webdriver always disables content security policy (#6358)\n          if (browser.params.browser !== 'chrome') {\n            return;\n          }\n\n          it('should not report errors when the page is loaded', function() {\n            // clear errors so we are not dependent on previous tests\n            clearErrors();\n            // Need to reload the page as the page is already loaded when\n            // we come here\n            browser.driver.getCurrentUrl().then(function(url) {\n              browser.get(url);\n            });\n            expectNoErrors();\n          });\n\n          it('should evaluate expressions', function() {\n            expect(counter.getText()).toEqual('0');\n            incBtn.click();\n            expect(counter.getText()).toEqual('1');\n            expectNoErrors();\n          });\n\n          it('should throw and report an error when using \"eval\"', function() {\n            evilBtn.click();\n            expect(evilError.getText()).toMatch(/Content Security Policy/);\n            expectError(/Content Security Policy/);\n          });\n        </file>\n      </example>\n  */\n\n// ngCsp is not implemented as a proper directive any more, because we need it be processed while we\n// bootstrap the system (before $parse is instantiated), for this reason we just have\n// the csp.isActive() fn that looks for ng-csp attribute anywhere in the current doc\n\n/**\n * @ngdoc directive\n * @name ngClick\n *\n * @description\n * The ngClick directive allows you to specify custom behavior when\n * an element is clicked.\n *\n * @element ANY\n * @priority 0\n * @param {expression} ngClick {@link guide/expression Expression} to evaluate upon\n * click. ({@link guide/expression#-event- Event object is available as `$event`})\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n      <button ng-click=\"count = count + 1\" ng-init=\"count=0\">\n        Increment\n      </button>\n      <span>\n        count: {{count}}\n      </span>\n     </file>\n     <file name=\"protractor.js\" type=\"protractor\">\n       it('should check ng-click', function() {\n         expect(element(by.binding('count')).getText()).toMatch('0');\n         element(by.css('button')).click();\n         expect(element(by.binding('count')).getText()).toMatch('1');\n       });\n     </file>\n   </example>\n */\n/*\n * A collection of directives that allows creation of custom event handlers that are defined as\n * angular expressions and are compiled and executed within the current scope.\n */\nvar ngEventDirectives = {};\n\n// For events that might fire synchronously during DOM manipulation\n// we need to execute their event handlers asynchronously using $evalAsync,\n// so that they are not executed in an inconsistent state.\nvar forceAsyncEvents = {\n  'blur': true,\n  'focus': true\n};\nforEach(\n  'click dblclick mousedown mouseup mouseover mouseout mousemove mouseenter mouseleave keydown keyup keypress submit focus blur copy cut paste'.split(' '),\n  function(eventName) {\n    var directiveName = directiveNormalize('ng-' + eventName);\n    ngEventDirectives[directiveName] = ['$parse', '$rootScope', function($parse, $rootScope) {\n      return {\n        restrict: 'A',\n        compile: function($element, attr) {\n          // We expose the powerful $event object on the scope that provides access to the Window,\n          // etc. that isn't protected by the fast paths in $parse.  We explicitly request better\n          // checks at the cost of speed since event handler expressions are not executed as\n          // frequently as regular change detection.\n          var fn = $parse(attr[directiveName], /* interceptorFn */ null, /* expensiveChecks */ true);\n          return function ngEventHandler(scope, element) {\n            element.on(eventName, function(event) {\n              var callback = function() {\n                fn(scope, {$event:event});\n              };\n              if (forceAsyncEvents[eventName] && $rootScope.$$phase) {\n                scope.$evalAsync(callback);\n              } else {\n                scope.$apply(callback);\n              }\n            });\n          };\n        }\n      };\n    }];\n  }\n);\n\n/**\n * @ngdoc directive\n * @name ngDblclick\n *\n * @description\n * The `ngDblclick` directive allows you to specify custom behavior on a dblclick event.\n *\n * @element ANY\n * @priority 0\n * @param {expression} ngDblclick {@link guide/expression Expression} to evaluate upon\n * a dblclick. (The Event object is available as `$event`)\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n      <button ng-dblclick=\"count = count + 1\" ng-init=\"count=0\">\n        Increment (on double click)\n      </button>\n      count: {{count}}\n     </file>\n   </example>\n */\n\n\n/**\n * @ngdoc directive\n * @name ngMousedown\n *\n * @description\n * The ngMousedown directive allows you to specify custom behavior on mousedown event.\n *\n * @element ANY\n * @priority 0\n * @param {expression} ngMousedown {@link guide/expression Expression} to evaluate upon\n * mousedown. ({@link guide/expression#-event- Event object is available as `$event`})\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n      <button ng-mousedown=\"count = count + 1\" ng-init=\"count=0\">\n        Increment (on mouse down)\n      </button>\n      count: {{count}}\n     </file>\n   </example>\n */\n\n\n/**\n * @ngdoc directive\n * @name ngMouseup\n *\n * @description\n * Specify custom behavior on mouseup event.\n *\n * @element ANY\n * @priority 0\n * @param {expression} ngMouseup {@link guide/expression Expression} to evaluate upon\n * mouseup. ({@link guide/expression#-event- Event object is available as `$event`})\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n      <button ng-mouseup=\"count = count + 1\" ng-init=\"count=0\">\n        Increment (on mouse up)\n      </button>\n      count: {{count}}\n     </file>\n   </example>\n */\n\n/**\n * @ngdoc directive\n * @name ngMouseover\n *\n * @description\n * Specify custom behavior on mouseover event.\n *\n * @element ANY\n * @priority 0\n * @param {expression} ngMouseover {@link guide/expression Expression} to evaluate upon\n * mouseover. ({@link guide/expression#-event- Event object is available as `$event`})\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n      <button ng-mouseover=\"count = count + 1\" ng-init=\"count=0\">\n        Increment (when mouse is over)\n      </button>\n      count: {{count}}\n     </file>\n   </example>\n */\n\n\n/**\n * @ngdoc directive\n * @name ngMouseenter\n *\n * @description\n * Specify custom behavior on mouseenter event.\n *\n * @element ANY\n * @priority 0\n * @param {expression} ngMouseenter {@link guide/expression Expression} to evaluate upon\n * mouseenter. ({@link guide/expression#-event- Event object is available as `$event`})\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n      <button ng-mouseenter=\"count = count + 1\" ng-init=\"count=0\">\n        Increment (when mouse enters)\n      </button>\n      count: {{count}}\n     </file>\n   </example>\n */\n\n\n/**\n * @ngdoc directive\n * @name ngMouseleave\n *\n * @description\n * Specify custom behavior on mouseleave event.\n *\n * @element ANY\n * @priority 0\n * @param {expression} ngMouseleave {@link guide/expression Expression} to evaluate upon\n * mouseleave. ({@link guide/expression#-event- Event object is available as `$event`})\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n      <button ng-mouseleave=\"count = count + 1\" ng-init=\"count=0\">\n        Increment (when mouse leaves)\n      </button>\n      count: {{count}}\n     </file>\n   </example>\n */\n\n\n/**\n * @ngdoc directive\n * @name ngMousemove\n *\n * @description\n * Specify custom behavior on mousemove event.\n *\n * @element ANY\n * @priority 0\n * @param {expression} ngMousemove {@link guide/expression Expression} to evaluate upon\n * mousemove. ({@link guide/expression#-event- Event object is available as `$event`})\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n      <button ng-mousemove=\"count = count + 1\" ng-init=\"count=0\">\n        Increment (when mouse moves)\n      </button>\n      count: {{count}}\n     </file>\n   </example>\n */\n\n\n/**\n * @ngdoc directive\n * @name ngKeydown\n *\n * @description\n * Specify custom behavior on keydown event.\n *\n * @element ANY\n * @priority 0\n * @param {expression} ngKeydown {@link guide/expression Expression} to evaluate upon\n * keydown. (Event object is available as `$event` and can be interrogated for keyCode, altKey, etc.)\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n      <input ng-keydown=\"count = count + 1\" ng-init=\"count=0\">\n      key down count: {{count}}\n     </file>\n   </example>\n */\n\n\n/**\n * @ngdoc directive\n * @name ngKeyup\n *\n * @description\n * Specify custom behavior on keyup event.\n *\n * @element ANY\n * @priority 0\n * @param {expression} ngKeyup {@link guide/expression Expression} to evaluate upon\n * keyup. (Event object is available as `$event` and can be interrogated for keyCode, altKey, etc.)\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n       <p>Typing in the input box below updates the key count</p>\n       <input ng-keyup=\"count = count + 1\" ng-init=\"count=0\"> key up count: {{count}}\n\n       <p>Typing in the input box below updates the keycode</p>\n       <input ng-keyup=\"event=$event\">\n       <p>event keyCode: {{ event.keyCode }}</p>\n       <p>event altKey: {{ event.altKey }}</p>\n     </file>\n   </example>\n */\n\n\n/**\n * @ngdoc directive\n * @name ngKeypress\n *\n * @description\n * Specify custom behavior on keypress event.\n *\n * @element ANY\n * @param {expression} ngKeypress {@link guide/expression Expression} to evaluate upon\n * keypress. ({@link guide/expression#-event- Event object is available as `$event`}\n * and can be interrogated for keyCode, altKey, etc.)\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n      <input ng-keypress=\"count = count + 1\" ng-init=\"count=0\">\n      key press count: {{count}}\n     </file>\n   </example>\n */\n\n\n/**\n * @ngdoc directive\n * @name ngSubmit\n *\n * @description\n * Enables binding angular expressions to onsubmit events.\n *\n * Additionally it prevents the default action (which for form means sending the request to the\n * server and reloading the current page), but only if the form does not contain `action`,\n * `data-action`, or `x-action` attributes.\n *\n * <div class=\"alert alert-warning\">\n * **Warning:** Be careful not to cause \"double-submission\" by using both the `ngClick` and\n * `ngSubmit` handlers together. See the\n * {@link form#submitting-a-form-and-preventing-the-default-action `form` directive documentation}\n * for a detailed discussion of when `ngSubmit` may be triggered.\n * </div>\n *\n * @element form\n * @priority 0\n * @param {expression} ngSubmit {@link guide/expression Expression} to eval.\n * ({@link guide/expression#-event- Event object is available as `$event`})\n *\n * @example\n   <example module=\"submitExample\">\n     <file name=\"index.html\">\n      <script>\n        angular.module('submitExample', [])\n          .controller('ExampleController', ['$scope', function($scope) {\n            $scope.list = [];\n            $scope.text = 'hello';\n            $scope.submit = function() {\n              if ($scope.text) {\n                $scope.list.push(this.text);\n                $scope.text = '';\n              }\n            };\n          }]);\n      </script>\n      <form ng-submit=\"submit()\" ng-controller=\"ExampleController\">\n        Enter text and hit enter:\n        <input type=\"text\" ng-model=\"text\" name=\"text\" />\n        <input type=\"submit\" id=\"submit\" value=\"Submit\" />\n        <pre>list={{list}}</pre>\n      </form>\n     </file>\n     <file name=\"protractor.js\" type=\"protractor\">\n       it('should check ng-submit', function() {\n         expect(element(by.binding('list')).getText()).toBe('list=[]');\n         element(by.css('#submit')).click();\n         expect(element(by.binding('list')).getText()).toContain('hello');\n         expect(element(by.model('text')).getAttribute('value')).toBe('');\n       });\n       it('should ignore empty strings', function() {\n         expect(element(by.binding('list')).getText()).toBe('list=[]');\n         element(by.css('#submit')).click();\n         element(by.css('#submit')).click();\n         expect(element(by.binding('list')).getText()).toContain('hello');\n        });\n     </file>\n   </example>\n */\n\n/**\n * @ngdoc directive\n * @name ngFocus\n *\n * @description\n * Specify custom behavior on focus event.\n *\n * Note: As the `focus` event is executed synchronously when calling `input.focus()`\n * AngularJS executes the expression using `scope.$evalAsync` if the event is fired\n * during an `$apply` to ensure a consistent state.\n *\n * @element window, input, select, textarea, a\n * @priority 0\n * @param {expression} ngFocus {@link guide/expression Expression} to evaluate upon\n * focus. ({@link guide/expression#-event- Event object is available as `$event`})\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n/**\n * @ngdoc directive\n * @name ngBlur\n *\n * @description\n * Specify custom behavior on blur event.\n *\n * A [blur event](https://developer.mozilla.org/en-US/docs/Web/Events/blur) fires when\n * an element has lost focus.\n *\n * Note: As the `blur` event is executed synchronously also during DOM manipulations\n * (e.g. removing a focussed input),\n * AngularJS executes the expression using `scope.$evalAsync` if the event is fired\n * during an `$apply` to ensure a consistent state.\n *\n * @element window, input, select, textarea, a\n * @priority 0\n * @param {expression} ngBlur {@link guide/expression Expression} to evaluate upon\n * blur. ({@link guide/expression#-event- Event object is available as `$event`})\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n/**\n * @ngdoc directive\n * @name ngCopy\n *\n * @description\n * Specify custom behavior on copy event.\n *\n * @element window, input, select, textarea, a\n * @priority 0\n * @param {expression} ngCopy {@link guide/expression Expression} to evaluate upon\n * copy. ({@link guide/expression#-event- Event object is available as `$event`})\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n      <input ng-copy=\"copied=true\" ng-init=\"copied=false; value='copy me'\" ng-model=\"value\">\n      copied: {{copied}}\n     </file>\n   </example>\n */\n\n/**\n * @ngdoc directive\n * @name ngCut\n *\n * @description\n * Specify custom behavior on cut event.\n *\n * @element window, input, select, textarea, a\n * @priority 0\n * @param {expression} ngCut {@link guide/expression Expression} to evaluate upon\n * cut. ({@link guide/expression#-event- Event object is available as `$event`})\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n      <input ng-cut=\"cut=true\" ng-init=\"cut=false; value='cut me'\" ng-model=\"value\">\n      cut: {{cut}}\n     </file>\n   </example>\n */\n\n/**\n * @ngdoc directive\n * @name ngPaste\n *\n * @description\n * Specify custom behavior on paste event.\n *\n * @element window, input, select, textarea, a\n * @priority 0\n * @param {expression} ngPaste {@link guide/expression Expression} to evaluate upon\n * paste. ({@link guide/expression#-event- Event object is available as `$event`})\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n      <input ng-paste=\"paste=true\" ng-init=\"paste=false\" placeholder='paste here'>\n      pasted: {{paste}}\n     </file>\n   </example>\n */\n\n/**\n * @ngdoc directive\n * @name ngIf\n * @restrict A\n *\n * @description\n * The `ngIf` directive removes or recreates a portion of the DOM tree based on an\n * {expression}. If the expression assigned to `ngIf` evaluates to a false\n * value then the element is removed from the DOM, otherwise a clone of the\n * element is reinserted into the DOM.\n *\n * `ngIf` differs from `ngShow` and `ngHide` in that `ngIf` completely removes and recreates the\n * element in the DOM rather than changing its visibility via the `display` css property.  A common\n * case when this difference is significant is when using css selectors that rely on an element's\n * position within the DOM, such as the `:first-child` or `:last-child` pseudo-classes.\n *\n * Note that when an element is removed using `ngIf` its scope is destroyed and a new scope\n * is created when the element is restored.  The scope created within `ngIf` inherits from\n * its parent scope using\n * [prototypal inheritance](https://github.com/angular/angular.js/wiki/Understanding-Scopes#javascript-prototypal-inheritance).\n * An important implication of this is if `ngModel` is used within `ngIf` to bind to\n * a javascript primitive defined in the parent scope. In this case any modifications made to the\n * variable within the child scope will override (hide) the value in the parent scope.\n *\n * Also, `ngIf` recreates elements using their compiled state. An example of this behavior\n * is if an element's class attribute is directly modified after it's compiled, using something like\n * jQuery's `.addClass()` method, and the element is later removed. When `ngIf` recreates the element\n * the added class will be lost because the original compiled state is used to regenerate the element.\n *\n * Additionally, you can provide animations via the `ngAnimate` module to animate the `enter`\n * and `leave` effects.\n *\n * @animations\n * enter - happens just after the `ngIf` contents change and a new DOM element is created and injected into the `ngIf` container\n * leave - happens just before the `ngIf` contents are removed from the DOM\n *\n * @element ANY\n * @scope\n * @priority 600\n * @param {expression} ngIf If the {@link guide/expression expression} is falsy then\n *     the element is removed from the DOM tree. If it is truthy a copy of the compiled\n *     element is added to the DOM tree.\n *\n * @example\n  <example module=\"ngAnimate\" deps=\"angular-animate.js\" animations=\"true\">\n    <file name=\"index.html\">\n      Click me: <input type=\"checkbox\" ng-model=\"checked\" ng-init=\"checked=true\" /><br/>\n      Show when checked:\n      <span ng-if=\"checked\" class=\"animate-if\">\n        This is removed when the checkbox is unchecked.\n      </span>\n    </file>\n    <file name=\"animations.css\">\n      .animate-if {\n        background:white;\n        border:1px solid black;\n        padding:10px;\n      }\n\n      .animate-if.ng-enter, .animate-if.ng-leave {\n        -webkit-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;\n        transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;\n      }\n\n      .animate-if.ng-enter,\n      .animate-if.ng-leave.ng-leave-active {\n        opacity:0;\n      }\n\n      .animate-if.ng-leave,\n      .animate-if.ng-enter.ng-enter-active {\n        opacity:1;\n      }\n    </file>\n  </example>\n */\nvar ngIfDirective = ['$animate', function($animate) {\n  return {\n    multiElement: true,\n    transclude: 'element',\n    priority: 600,\n    terminal: true,\n    restrict: 'A',\n    $$tlb: true,\n    link: function($scope, $element, $attr, ctrl, $transclude) {\n        var block, childScope, previousElements;\n        $scope.$watch($attr.ngIf, function ngIfWatchAction(value) {\n\n          if (value) {\n            if (!childScope) {\n              $transclude(function(clone, newScope) {\n                childScope = newScope;\n                clone[clone.length++] = document.createComment(' end ngIf: ' + $attr.ngIf + ' ');\n                // Note: We only need the first/last node of the cloned nodes.\n                // However, we need to keep the reference to the jqlite wrapper as it might be changed later\n                // by a directive with templateUrl when its template arrives.\n                block = {\n                  clone: clone\n                };\n                $animate.enter(clone, $element.parent(), $element);\n              });\n            }\n          } else {\n            if (previousElements) {\n              previousElements.remove();\n              previousElements = null;\n            }\n            if (childScope) {\n              childScope.$destroy();\n              childScope = null;\n            }\n            if (block) {\n              previousElements = getBlockNodes(block.clone);\n              $animate.leave(previousElements).then(function() {\n                previousElements = null;\n              });\n              block = null;\n            }\n          }\n        });\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ngInclude\n * @restrict ECA\n *\n * @description\n * Fetches, compiles and includes an external HTML fragment.\n *\n * By default, the template URL is restricted to the same domain and protocol as the\n * application document. This is done by calling {@link $sce#getTrustedResourceUrl\n * $sce.getTrustedResourceUrl} on it. To load templates from other domains or protocols\n * you may either {@link ng.$sceDelegateProvider#resourceUrlWhitelist whitelist them} or\n * {@link $sce#trustAsResourceUrl wrap them} as trusted values. Refer to Angular's {@link\n * ng.$sce Strict Contextual Escaping}.\n *\n * In addition, the browser's\n * [Same Origin Policy](https://code.google.com/p/browsersec/wiki/Part2#Same-origin_policy_for_XMLHttpRequest)\n * and [Cross-Origin Resource Sharing (CORS)](http://www.w3.org/TR/cors/)\n * policy may further restrict whether the template is successfully loaded.\n * For example, `ngInclude` won't work for cross-domain requests on all browsers and for `file://`\n * access on some browsers.\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 *\n * @param {string} ngInclude|src angular expression evaluating to URL. If the source is a string constant,\n *                 make sure you wrap it in **single** quotes, e.g. `src=\"'myPartialTemplate.html'\"`.\n * @param {string=} onload Expression to evaluate when a new partial is loaded.\n *\n * @param {string=} autoscroll Whether `ngInclude` should call {@link ng.$anchorScroll\n *                  $anchorScroll} to scroll the viewport after the content is loaded.\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 expression evaluates to truthy value.\n *\n * @example\n  <example module=\"includeExample\" deps=\"angular-animate.js\" animations=\"true\">\n    <file name=\"index.html\">\n     <div ng-controller=\"ExampleController\">\n       <select ng-model=\"template\" ng-options=\"t.name for t in templates\">\n        <option value=\"\">(blank)</option>\n       </select>\n       url of the template: <code>{{template.url}}</code>\n       <hr/>\n       <div class=\"slide-animate-container\">\n         <div class=\"slide-animate\" ng-include=\"template.url\"></div>\n       </div>\n     </div>\n    </file>\n    <file name=\"script.js\">\n      angular.module('includeExample', ['ngAnimate'])\n        .controller('ExampleController', ['$scope', function($scope) {\n          $scope.templates =\n            [ { name: 'template1.html', url: 'template1.html'},\n              { name: 'template2.html', url: 'template2.html'} ];\n          $scope.template = $scope.templates[0];\n        }]);\n     </file>\n    <file name=\"template1.html\">\n      Content of template1.html\n    </file>\n    <file name=\"template2.html\">\n      Content of template2.html\n    </file>\n    <file name=\"animations.css\">\n      .slide-animate-container {\n        position:relative;\n        background:white;\n        border:1px solid black;\n        height:40px;\n        overflow:hidden;\n      }\n\n      .slide-animate {\n        padding:10px;\n      }\n\n      .slide-animate.ng-enter, .slide-animate.ng-leave {\n        -webkit-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;\n        transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;\n\n        position:absolute;\n        top:0;\n        left:0;\n        right:0;\n        bottom:0;\n        display:block;\n        padding:10px;\n      }\n\n      .slide-animate.ng-enter {\n        top:-50px;\n      }\n      .slide-animate.ng-enter.ng-enter-active {\n        top:0;\n      }\n\n      .slide-animate.ng-leave {\n        top:0;\n      }\n      .slide-animate.ng-leave.ng-leave-active {\n        top:50px;\n      }\n    </file>\n    <file name=\"protractor.js\" type=\"protractor\">\n      var templateSelect = element(by.model('template'));\n      var includeElem = element(by.css('[ng-include]'));\n\n      it('should load template1.html', function() {\n        expect(includeElem.getText()).toMatch(/Content of template1.html/);\n      });\n\n      it('should load template2.html', function() {\n        if (browser.params.browser == 'firefox') {\n          // Firefox can't handle using selects\n          // See https://github.com/angular/protractor/issues/480\n          return;\n        }\n        templateSelect.click();\n        templateSelect.all(by.css('option')).get(2).click();\n        expect(includeElem.getText()).toMatch(/Content of template2.html/);\n      });\n\n      it('should change to blank', function() {\n        if (browser.params.browser == 'firefox') {\n          // Firefox can't handle using selects\n          return;\n        }\n        templateSelect.click();\n        templateSelect.all(by.css('option')).get(0).click();\n        expect(includeElem.isPresent()).toBe(false);\n      });\n    </file>\n  </example>\n */\n\n\n/**\n * @ngdoc event\n * @name ngInclude#$includeContentRequested\n * @eventType emit on the scope ngInclude was declared in\n * @description\n * Emitted every time the ngInclude content is requested.\n *\n * @param {Object} angularEvent Synthetic event object.\n * @param {String} src URL of content to load.\n */\n\n\n/**\n * @ngdoc event\n * @name ngInclude#$includeContentLoaded\n * @eventType emit on the current ngInclude scope\n * @description\n * Emitted every time the ngInclude content is reloaded.\n *\n * @param {Object} angularEvent Synthetic event object.\n * @param {String} src URL of content to load.\n */\n\n\n/**\n * @ngdoc event\n * @name ngInclude#$includeContentError\n * @eventType emit on the scope ngInclude was declared in\n * @description\n * Emitted when a template HTTP request yields an erroneous response (status < 200 || status > 299)\n *\n * @param {Object} angularEvent Synthetic event object.\n * @param {String} src URL of content to load.\n */\nvar ngIncludeDirective = ['$templateRequest', '$anchorScroll', '$animate', '$sce',\n                  function($templateRequest,   $anchorScroll,   $animate,   $sce) {\n  return {\n    restrict: 'ECA',\n    priority: 400,\n    terminal: true,\n    transclude: 'element',\n    controller: angular.noop,\n    compile: function(element, attr) {\n      var srcExp = attr.ngInclude || attr.src,\n          onloadExp = attr.onload || '',\n          autoScrollExp = attr.autoscroll;\n\n      return function(scope, $element, $attr, ctrl, $transclude) {\n        var changeCounter = 0,\n            currentScope,\n            previousElement,\n            currentElement;\n\n        var cleanupLastIncludeContent = function() {\n          if (previousElement) {\n            previousElement.remove();\n            previousElement = null;\n          }\n          if (currentScope) {\n            currentScope.$destroy();\n            currentScope = null;\n          }\n          if (currentElement) {\n            $animate.leave(currentElement).then(function() {\n              previousElement = null;\n            });\n            previousElement = currentElement;\n            currentElement = null;\n          }\n        };\n\n        scope.$watch($sce.parseAsResourceUrl(srcExp), function ngIncludeWatchAction(src) {\n          var afterAnimation = function() {\n            if (isDefined(autoScrollExp) && (!autoScrollExp || scope.$eval(autoScrollExp))) {\n              $anchorScroll();\n            }\n          };\n          var thisChangeId = ++changeCounter;\n\n          if (src) {\n            //set the 2nd param to true to ignore the template request error so that the inner\n            //contents and scope can be cleaned up.\n            $templateRequest(src, true).then(function(response) {\n              if (thisChangeId !== changeCounter) return;\n              var newScope = scope.$new();\n              ctrl.template = response;\n\n              // Note: This will also link all children of ng-include that were contained in the original\n              // html. If that content contains controllers, ... they could pollute/change the scope.\n              // However, using ng-include 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                cleanupLastIncludeContent();\n                $animate.enter(clone, null, $element).then(afterAnimation);\n              });\n\n              currentScope = newScope;\n              currentElement = clone;\n\n              currentScope.$emit('$includeContentLoaded', src);\n              scope.$eval(onloadExp);\n            }, function() {\n              if (thisChangeId === changeCounter) {\n                cleanupLastIncludeContent();\n                scope.$emit('$includeContentError', src);\n              }\n            });\n            scope.$emit('$includeContentRequested', src);\n          } else {\n            cleanupLastIncludeContent();\n            ctrl.template = null;\n          }\n        });\n      };\n    }\n  };\n}];\n\n// This directive is called during the $transclude call of the first `ngInclude` 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 ngInclude\n// is called.\nvar ngIncludeFillContentDirective = ['$compile',\n  function($compile) {\n    return {\n      restrict: 'ECA',\n      priority: -400,\n      require: 'ngInclude',\n      link: function(scope, $element, $attr, ctrl) {\n        if (/SVG/.test($element[0].toString())) {\n          // WebKit: https://bugs.webkit.org/show_bug.cgi?id=135698 --- SVG elements do not\n          // support innerHTML, so detect this here and try to generate the contents\n          // specially.\n          $element.empty();\n          $compile(jqLiteBuildFragment(ctrl.template, document).childNodes)(scope,\n              function namespaceAdaptedClone(clone) {\n            $element.append(clone);\n          }, {futureParentElement: $element});\n          return;\n        }\n\n        $element.html(ctrl.template);\n        $compile($element.contents())(scope);\n      }\n    };\n  }];\n\n/**\n * @ngdoc directive\n * @name ngInit\n * @restrict AC\n *\n * @description\n * The `ngInit` directive allows you to evaluate an expression in the\n * current scope.\n *\n * <div class=\"alert alert-error\">\n * The only appropriate use of `ngInit` is for aliasing special properties of\n * {@link ng.directive:ngRepeat `ngRepeat`}, as seen in the demo below. Besides this case, you\n * should use {@link guide/controller controllers} rather than `ngInit`\n * to initialize values on a scope.\n * </div>\n * <div class=\"alert alert-warning\">\n * **Note**: If you have assignment in `ngInit` along with {@link ng.$filter `$filter`}, make\n * sure you have parenthesis for correct precedence:\n * <pre class=\"prettyprint\">\n * `<div ng-init=\"test1 = (data | orderBy:'name')\"></div>`\n * </pre>\n * </div>\n *\n * @priority 450\n *\n * @element ANY\n * @param {expression} ngInit {@link guide/expression Expression} to eval.\n *\n * @example\n   <example module=\"initExample\">\n     <file name=\"index.html\">\n   <script>\n     angular.module('initExample', [])\n       .controller('ExampleController', ['$scope', function($scope) {\n         $scope.list = [['a', 'b'], ['c', 'd']];\n       }]);\n   </script>\n   <div ng-controller=\"ExampleController\">\n     <div ng-repeat=\"innerList in list\" ng-init=\"outerIndex = $index\">\n       <div ng-repeat=\"value in innerList\" ng-init=\"innerIndex = $index\">\n          <span class=\"example-init\">list[ {{outerIndex}} ][ {{innerIndex}} ] = {{value}};</span>\n       </div>\n     </div>\n   </div>\n     </file>\n     <file name=\"protractor.js\" type=\"protractor\">\n       it('should alias index positions', function() {\n         var elements = element.all(by.css('.example-init'));\n         expect(elements.get(0).getText()).toBe('list[ 0 ][ 0 ] = a;');\n         expect(elements.get(1).getText()).toBe('list[ 0 ][ 1 ] = b;');\n         expect(elements.get(2).getText()).toBe('list[ 1 ][ 0 ] = c;');\n         expect(elements.get(3).getText()).toBe('list[ 1 ][ 1 ] = d;');\n       });\n     </file>\n   </example>\n */\nvar ngInitDirective = ngDirective({\n  priority: 450,\n  compile: function() {\n    return {\n      pre: function(scope, element, attrs) {\n        scope.$eval(attrs.ngInit);\n      }\n    };\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ngList\n *\n * @description\n * Text input that converts between a delimited string and an array of strings. The default\n * delimiter is a comma followed by a space - equivalent to `ng-list=\", \"`. You can specify a custom\n * delimiter as the value of the `ngList` attribute - for example, `ng-list=\" | \"`.\n *\n * The behaviour of the directive is affected by the use of the `ngTrim` attribute.\n * * If `ngTrim` is set to `\"false\"` then whitespace around both the separator and each\n *   list item is respected. This implies that the user of the directive is responsible for\n *   dealing with whitespace but also allows you to use whitespace as a delimiter, such as a\n *   tab or newline character.\n * * Otherwise whitespace around the delimiter is ignored when splitting (although it is respected\n *   when joining the list items back together) and whitespace around each list item is stripped\n *   before it is added to the model.\n *\n * ### Example with Validation\n *\n * <example name=\"ngList-directive\" module=\"listExample\">\n *   <file name=\"app.js\">\n *      angular.module('listExample', [])\n *        .controller('ExampleController', ['$scope', function($scope) {\n *          $scope.names = ['morpheus', 'neo', 'trinity'];\n *        }]);\n *   </file>\n *   <file name=\"index.html\">\n *    <form name=\"myForm\" ng-controller=\"ExampleController\">\n *      List: <input name=\"namesInput\" ng-model=\"names\" ng-list required>\n *      <span class=\"error\" ng-show=\"myForm.namesInput.$error.required\">\n *        Required!</span>\n *      <br>\n *      <tt>names = {{names}}</tt><br/>\n *      <tt>myForm.namesInput.$valid = {{myForm.namesInput.$valid}}</tt><br/>\n *      <tt>myForm.namesInput.$error = {{myForm.namesInput.$error}}</tt><br/>\n *      <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n *      <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n *     </form>\n *   </file>\n *   <file name=\"protractor.js\" type=\"protractor\">\n *     var listInput = element(by.model('names'));\n *     var names = element(by.exactBinding('names'));\n *     var valid = element(by.binding('myForm.namesInput.$valid'));\n *     var error = element(by.css('span.error'));\n *\n *     it('should initialize to model', function() {\n *       expect(names.getText()).toContain('[\"morpheus\",\"neo\",\"trinity\"]');\n *       expect(valid.getText()).toContain('true');\n *       expect(error.getCssValue('display')).toBe('none');\n *     });\n *\n *     it('should be invalid if empty', function() {\n *       listInput.clear();\n *       listInput.sendKeys('');\n *\n *       expect(names.getText()).toContain('');\n *       expect(valid.getText()).toContain('false');\n *       expect(error.getCssValue('display')).not.toBe('none');\n *     });\n *   </file>\n * </example>\n *\n * ### Example - splitting on whitespace\n * <example name=\"ngList-directive-newlines\">\n *   <file name=\"index.html\">\n *    <textarea ng-model=\"list\" ng-list=\"&#10;\" ng-trim=\"false\"></textarea>\n *    <pre>{{ list | json }}</pre>\n *   </file>\n *   <file name=\"protractor.js\" type=\"protractor\">\n *     it(\"should split the text by newlines\", function() {\n *       var listInput = element(by.model('list'));\n *       var output = element(by.binding('list | json'));\n *       listInput.sendKeys('abc\\ndef\\nghi');\n *       expect(output.getText()).toContain('[\\n  \"abc\",\\n  \"def\",\\n  \"ghi\"\\n]');\n *     });\n *   </file>\n * </example>\n *\n * @element input\n * @param {string=} ngList optional delimiter that should be used to split the value.\n */\nvar ngListDirective = function() {\n  return {\n    restrict: 'A',\n    priority: 100,\n    require: 'ngModel',\n    link: function(scope, element, attr, ctrl) {\n      // We want to control whitespace trimming so we use this convoluted approach\n      // to access the ngList attribute, which doesn't pre-trim the attribute\n      var ngList = element.attr(attr.$attr.ngList) || ', ';\n      var trimValues = attr.ngTrim !== 'false';\n      var separator = trimValues ? trim(ngList) : ngList;\n\n      var parse = function(viewValue) {\n        // If the viewValue is invalid (say required but empty) it will be `undefined`\n        if (isUndefined(viewValue)) return;\n\n        var list = [];\n\n        if (viewValue) {\n          forEach(viewValue.split(separator), function(value) {\n            if (value) list.push(trimValues ? trim(value) : value);\n          });\n        }\n\n        return list;\n      };\n\n      ctrl.$parsers.push(parse);\n      ctrl.$formatters.push(function(value) {\n        if (isArray(value)) {\n          return value.join(ngList);\n        }\n\n        return undefined;\n      });\n\n      // Override the standard $isEmpty because an empty array means the input is empty.\n      ctrl.$isEmpty = function(value) {\n        return !value || !value.length;\n      };\n    }\n  };\n};\n\n/* global VALID_CLASS: true,\n  INVALID_CLASS: true,\n  PRISTINE_CLASS: true,\n  DIRTY_CLASS: true,\n  UNTOUCHED_CLASS: true,\n  TOUCHED_CLASS: true,\n*/\n\nvar VALID_CLASS = 'ng-valid',\n    INVALID_CLASS = 'ng-invalid',\n    PRISTINE_CLASS = 'ng-pristine',\n    DIRTY_CLASS = 'ng-dirty',\n    UNTOUCHED_CLASS = 'ng-untouched',\n    TOUCHED_CLASS = 'ng-touched',\n    PENDING_CLASS = 'ng-pending';\n\n\nvar $ngModelMinErr = new minErr('ngModel');\n\n/**\n * @ngdoc type\n * @name ngModel.NgModelController\n *\n * @property {string} $viewValue Actual string value in the view.\n * @property {*} $modelValue The value in the model that the control is bound to.\n * @property {Array.<Function>} $parsers Array of functions to execute, as a pipeline, whenever\n       the control reads value from the DOM. The functions are called in array order, each passing\n       its return value through to the next. The last return value is forwarded to the\n       {@link ngModel.NgModelController#$validators `$validators`} collection.\n\nParsers are used to sanitize / convert the {@link ngModel.NgModelController#$viewValue\n`$viewValue`}.\n\nReturning `undefined` from a parser means a parse error occurred. In that case,\nno {@link ngModel.NgModelController#$validators `$validators`} will run and the `ngModel`\nwill be set to `undefined` unless {@link ngModelOptions `ngModelOptions.allowInvalid`}\nis set to `true`. The parse error is stored in `ngModel.$error.parse`.\n\n *\n * @property {Array.<Function>} $formatters Array of functions to execute, as a pipeline, whenever\n       the model value changes. The functions are called in reverse array order, each passing the value through to the\n       next. The last return value is used as the actual DOM value.\n       Used to format / convert values for display in the control.\n * ```js\n * function formatter(value) {\n *   if (value) {\n *     return value.toUpperCase();\n *   }\n * }\n * ngModel.$formatters.push(formatter);\n * ```\n *\n * @property {Object.<string, function>} $validators A collection of validators that are applied\n *      whenever the model value changes. The key value within the object refers to the name of the\n *      validator while the function refers to the validation operation. The validation operation is\n *      provided with the model value as an argument and must return a true or false value depending\n *      on the response of that validation.\n *\n * ```js\n * ngModel.$validators.validCharacters = function(modelValue, viewValue) {\n *   var value = modelValue || viewValue;\n *   return /[0-9]+/.test(value) &&\n *          /[a-z]+/.test(value) &&\n *          /[A-Z]+/.test(value) &&\n *          /\\W+/.test(value);\n * };\n * ```\n *\n * @property {Object.<string, function>} $asyncValidators A collection of validations that are expected to\n *      perform an asynchronous validation (e.g. a HTTP request). The validation function that is provided\n *      is expected to return a promise when it is run during the model validation process. Once the promise\n *      is delivered then the validation status will be set to true when fulfilled and false when rejected.\n *      When the asynchronous validators are triggered, each of the validators will run in parallel and the model\n *      value will only be updated once all validators have been fulfilled. As long as an asynchronous validator\n *      is unfulfilled, its key will be added to the controllers `$pending` property. Also, all asynchronous validators\n *      will only run once all synchronous validators have passed.\n *\n * Please note that if $http is used then it is important that the server returns a success HTTP response code\n * in order to fulfill the validation and a status level of `4xx` in order to reject the validation.\n *\n * ```js\n * ngModel.$asyncValidators.uniqueUsername = function(modelValue, viewValue) {\n *   var value = modelValue || viewValue;\n *\n *   // Lookup user by username\n *   return $http.get('/api/users/' + value).\n *      then(function resolved() {\n *        //username exists, this means validation fails\n *        return $q.reject('exists');\n *      }, function rejected() {\n *        //username does not exist, therefore this validation passes\n *        return true;\n *      });\n * };\n * ```\n *\n * @property {Array.<Function>} $viewChangeListeners Array of functions to execute whenever the\n *     view value has changed. It is called with no arguments, and its return value is ignored.\n *     This can be used in place of additional $watches against the model value.\n *\n * @property {Object} $error An object hash with all failing validator ids as keys.\n * @property {Object} $pending An object hash with all pending validator ids as keys.\n *\n * @property {boolean} $untouched True if control has not lost focus yet.\n * @property {boolean} $touched True if control has lost focus.\n * @property {boolean} $pristine True if user has not interacted with the control yet.\n * @property {boolean} $dirty True if user has already interacted with the control.\n * @property {boolean} $valid True if there is no error.\n * @property {boolean} $invalid True if at least one error on the control.\n * @property {string} $name The name attribute of the control.\n *\n * @description\n *\n * `NgModelController` provides API for the {@link ngModel `ngModel`} directive.\n * The controller contains services for data-binding, validation, CSS updates, and value formatting\n * and parsing. It purposefully does not contain any logic which deals with DOM rendering or\n * listening to DOM events.\n * Such DOM related logic should be provided by other directives which make use of\n * `NgModelController` for data-binding to control elements.\n * Angular provides this DOM logic for most {@link input `input`} elements.\n * At the end of this page you can find a {@link ngModel.NgModelController#custom-control-example\n * custom control example} that uses `ngModelController` to bind to `contenteditable` elements.\n *\n * @example\n * ### Custom Control Example\n * This example shows how to use `NgModelController` with a custom control to achieve\n * data-binding. Notice how different directives (`contenteditable`, `ng-model`, and `required`)\n * collaborate together to achieve the desired result.\n *\n * Note that `contenteditable` is an HTML5 attribute, which tells the browser to let the element\n * contents be edited in place by the user.  This will not work on older browsers.\n *\n * We are using the {@link ng.service:$sce $sce} service here and include the {@link ngSanitize $sanitize}\n * module to automatically remove \"bad\" content like inline event listener (e.g. `<span onclick=\"...\">`).\n * However, as we are using `$sce` the model can still decide to provide unsafe content if it marks\n * that content using the `$sce` service.\n *\n * <example name=\"NgModelController\" module=\"customControl\" deps=\"angular-sanitize.js\">\n    <file name=\"style.css\">\n      [contenteditable] {\n        border: 1px solid black;\n        background-color: white;\n        min-height: 20px;\n      }\n\n      .ng-invalid {\n        border: 1px solid red;\n      }\n\n    </file>\n    <file name=\"script.js\">\n      angular.module('customControl', ['ngSanitize']).\n        directive('contenteditable', ['$sce', function($sce) {\n          return {\n            restrict: 'A', // only activate on element attribute\n            require: '?ngModel', // get a hold of NgModelController\n            link: function(scope, element, attrs, ngModel) {\n              if (!ngModel) return; // do nothing if no ng-model\n\n              // Specify how UI should be updated\n              ngModel.$render = function() {\n                element.html($sce.getTrustedHtml(ngModel.$viewValue || ''));\n              };\n\n              // Listen for change events to enable binding\n              element.on('blur keyup change', function() {\n                scope.$evalAsync(read);\n              });\n              read(); // initialize\n\n              // Write data to the model\n              function read() {\n                var html = element.html();\n                // When we clear the content editable the browser leaves a <br> behind\n                // If strip-br attribute is provided then we strip this out\n                if ( attrs.stripBr && html == '<br>' ) {\n                  html = '';\n                }\n                ngModel.$setViewValue(html);\n              }\n            }\n          };\n        }]);\n    </file>\n    <file name=\"index.html\">\n      <form name=\"myForm\">\n       <div contenteditable\n            name=\"myWidget\" ng-model=\"userContent\"\n            strip-br=\"true\"\n            required>Change me!</div>\n        <span ng-show=\"myForm.myWidget.$error.required\">Required!</span>\n       <hr>\n       <textarea ng-model=\"userContent\"></textarea>\n      </form>\n    </file>\n    <file name=\"protractor.js\" type=\"protractor\">\n    it('should data-bind and become invalid', function() {\n      if (browser.params.browser == 'safari' || browser.params.browser == 'firefox') {\n        // SafariDriver can't handle contenteditable\n        // and Firefox driver can't clear contenteditables very well\n        return;\n      }\n      var contentEditable = element(by.css('[contenteditable]'));\n      var content = 'Change me!';\n\n      expect(contentEditable.getText()).toEqual(content);\n\n      contentEditable.clear();\n      contentEditable.sendKeys(protractor.Key.BACK_SPACE);\n      expect(contentEditable.getText()).toEqual('');\n      expect(contentEditable.getAttribute('class')).toMatch(/ng-invalid-required/);\n    });\n    </file>\n * </example>\n *\n *\n */\nvar NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$parse', '$animate', '$timeout', '$rootScope', '$q', '$interpolate',\n    function($scope, $exceptionHandler, $attr, $element, $parse, $animate, $timeout, $rootScope, $q, $interpolate) {\n  this.$viewValue = Number.NaN;\n  this.$modelValue = Number.NaN;\n  this.$$rawModelValue = undefined; // stores the parsed modelValue / model set from scope regardless of validity.\n  this.$validators = {};\n  this.$asyncValidators = {};\n  this.$parsers = [];\n  this.$formatters = [];\n  this.$viewChangeListeners = [];\n  this.$untouched = true;\n  this.$touched = false;\n  this.$pristine = true;\n  this.$dirty = false;\n  this.$valid = true;\n  this.$invalid = false;\n  this.$error = {}; // keep invalid keys here\n  this.$$success = {}; // keep valid keys here\n  this.$pending = undefined; // keep pending keys here\n  this.$name = $interpolate($attr.name || '', false)($scope);\n\n\n  var parsedNgModel = $parse($attr.ngModel),\n      parsedNgModelAssign = parsedNgModel.assign,\n      ngModelGet = parsedNgModel,\n      ngModelSet = parsedNgModelAssign,\n      pendingDebounce = null,\n      ctrl = this;\n\n  this.$$setOptions = function(options) {\n    ctrl.$options = options;\n    if (options && options.getterSetter) {\n      var invokeModelGetter = $parse($attr.ngModel + '()'),\n          invokeModelSetter = $parse($attr.ngModel + '($$$p)');\n\n      ngModelGet = function($scope) {\n        var modelValue = parsedNgModel($scope);\n        if (isFunction(modelValue)) {\n          modelValue = invokeModelGetter($scope);\n        }\n        return modelValue;\n      };\n      ngModelSet = function($scope, newValue) {\n        if (isFunction(parsedNgModel($scope))) {\n          invokeModelSetter($scope, {$$$p: ctrl.$modelValue});\n        } else {\n          parsedNgModelAssign($scope, ctrl.$modelValue);\n        }\n      };\n    } else if (!parsedNgModel.assign) {\n      throw $ngModelMinErr('nonassign', \"Expression '{0}' is non-assignable. Element: {1}\",\n          $attr.ngModel, startingTag($element));\n    }\n  };\n\n  /**\n   * @ngdoc method\n   * @name ngModel.NgModelController#$render\n   *\n   * @description\n   * Called when the view needs to be updated. It is expected that the user of the ng-model\n   * directive will implement this method.\n   *\n   * The `$render()` method is invoked in the following situations:\n   *\n   * * `$rollbackViewValue()` is called.  If we are rolling back the view value to the last\n   *   committed value then `$render()` is called to update the input control.\n   * * The value referenced by `ng-model` is changed programmatically and both the `$modelValue` and\n   *   the `$viewValue` are different to last time.\n   *\n   * Since `ng-model` does not do a deep watch, `$render()` is only invoked if the values of\n   * `$modelValue` and `$viewValue` are actually different to their previous value. If `$modelValue`\n   * or `$viewValue` are objects (rather than a string or number) then `$render()` will not be\n   * invoked if you only change a property on the objects.\n   */\n  this.$render = noop;\n\n  /**\n   * @ngdoc method\n   * @name ngModel.NgModelController#$isEmpty\n   *\n   * @description\n   * This is called when we need to determine if the value of an input is empty.\n   *\n   * For instance, the required directive does this to work out if the input has data or not.\n   *\n   * The default `$isEmpty` function checks whether the value is `undefined`, `''`, `null` or `NaN`.\n   *\n   * You can override this for input directives whose concept of being empty is different to the\n   * default. The `checkboxInputType` directive does this because in its case a value of `false`\n   * implies empty.\n   *\n   * @param {*} value The value of the input to check for emptiness.\n   * @returns {boolean} True if `value` is \"empty\".\n   */\n  this.$isEmpty = function(value) {\n    return isUndefined(value) || value === '' || value === null || value !== value;\n  };\n\n  var parentForm = $element.inheritedData('$formController') || nullFormCtrl,\n      currentValidationRunId = 0;\n\n  /**\n   * @ngdoc method\n   * @name ngModel.NgModelController#$setValidity\n   *\n   * @description\n   * Change the validity state, and notify the form.\n   *\n   * This method can be called within $parsers/$formatters or a custom validation implementation.\n   * However, in most cases it should be sufficient to use the `ngModel.$validators` and\n   * `ngModel.$asyncValidators` collections which will call `$setValidity` automatically.\n   *\n   * @param {string} validationErrorKey Name of the validator. The `validationErrorKey` will be assigned\n   *        to either `$error[validationErrorKey]` or `$pending[validationErrorKey]`\n   *        (for unfulfilled `$asyncValidators`), so that it is available for data-binding.\n   *        The `validationErrorKey` should be in camelCase and will get converted into dash-case\n   *        for class name. Example: `myError` will result in `ng-valid-my-error` and `ng-invalid-my-error`\n   *        class and can be bound to as  `{{someForm.someControl.$error.myError}}` .\n   * @param {boolean} isValid Whether the current state is valid (true), invalid (false), pending (undefined),\n   *                          or skipped (null). Pending is used for unfulfilled `$asyncValidators`.\n   *                          Skipped is used by Angular when validators do not run because of parse errors and\n   *                          when `$asyncValidators` do not run because any of the `$validators` failed.\n   */\n  addSetValidityMethod({\n    ctrl: this,\n    $element: $element,\n    set: function(object, property) {\n      object[property] = true;\n    },\n    unset: function(object, property) {\n      delete object[property];\n    },\n    parentForm: parentForm,\n    $animate: $animate\n  });\n\n  /**\n   * @ngdoc method\n   * @name ngModel.NgModelController#$setPristine\n   *\n   * @description\n   * Sets the control to its pristine state.\n   *\n   * This method can be called to remove the `ng-dirty` class and set the control to its pristine\n   * state (`ng-pristine` class). A model is considered to be pristine when the control\n   * has not been changed from when first compiled.\n   */\n  this.$setPristine = function() {\n    ctrl.$dirty = false;\n    ctrl.$pristine = true;\n    $animate.removeClass($element, DIRTY_CLASS);\n    $animate.addClass($element, PRISTINE_CLASS);\n  };\n\n  /**\n   * @ngdoc method\n   * @name ngModel.NgModelController#$setDirty\n   *\n   * @description\n   * Sets the control to its dirty state.\n   *\n   * This method can be called to remove the `ng-pristine` class and set the control to its dirty\n   * state (`ng-dirty` class). A model is considered to be dirty when the control has been changed\n   * from when first compiled.\n   */\n  this.$setDirty = function() {\n    ctrl.$dirty = true;\n    ctrl.$pristine = false;\n    $animate.removeClass($element, PRISTINE_CLASS);\n    $animate.addClass($element, DIRTY_CLASS);\n    parentForm.$setDirty();\n  };\n\n  /**\n   * @ngdoc method\n   * @name ngModel.NgModelController#$setUntouched\n   *\n   * @description\n   * Sets the control to its untouched state.\n   *\n   * This method can be called to remove the `ng-touched` class and set the control to its\n   * untouched state (`ng-untouched` class). Upon compilation, a model is set as untouched\n   * by default, however this function can be used to restore that state if the model has\n   * already been touched by the user.\n   */\n  this.$setUntouched = function() {\n    ctrl.$touched = false;\n    ctrl.$untouched = true;\n    $animate.setClass($element, UNTOUCHED_CLASS, TOUCHED_CLASS);\n  };\n\n  /**\n   * @ngdoc method\n   * @name ngModel.NgModelController#$setTouched\n   *\n   * @description\n   * Sets the control to its touched state.\n   *\n   * This method can be called to remove the `ng-untouched` class and set the control to its\n   * touched state (`ng-touched` class). A model is considered to be touched when the user has\n   * first focused the control element and then shifted focus away from the control (blur event).\n   */\n  this.$setTouched = function() {\n    ctrl.$touched = true;\n    ctrl.$untouched = false;\n    $animate.setClass($element, TOUCHED_CLASS, UNTOUCHED_CLASS);\n  };\n\n  /**\n   * @ngdoc method\n   * @name ngModel.NgModelController#$rollbackViewValue\n   *\n   * @description\n   * Cancel an update and reset the input element's value to prevent an update to the `$modelValue`,\n   * which may be caused by a pending debounced event or because the input is waiting for a some\n   * future event.\n   *\n   * If you have an input that uses `ng-model-options` to set up debounced events or events such\n   * as blur you can have a situation where there is a period when the `$viewValue`\n   * is out of synch with the ngModel's `$modelValue`.\n   *\n   * In this case, you can run into difficulties if you try to update the ngModel's `$modelValue`\n   * programmatically before these debounced/future events have resolved/occurred, because Angular's\n   * dirty checking mechanism is not able to tell whether the model has actually changed or not.\n   *\n   * The `$rollbackViewValue()` method should be called before programmatically changing the model of an\n   * input which may have such events pending. This is important in order to make sure that the\n   * input field will be updated with the new model value and any pending operations are cancelled.\n   *\n   * <example name=\"ng-model-cancel-update\" module=\"cancel-update-example\">\n   *   <file name=\"app.js\">\n   *     angular.module('cancel-update-example', [])\n   *\n   *     .controller('CancelUpdateController', ['$scope', function($scope) {\n   *       $scope.resetWithCancel = function(e) {\n   *         if (e.keyCode == 27) {\n   *           $scope.myForm.myInput1.$rollbackViewValue();\n   *           $scope.myValue = '';\n   *         }\n   *       };\n   *       $scope.resetWithoutCancel = function(e) {\n   *         if (e.keyCode == 27) {\n   *           $scope.myValue = '';\n   *         }\n   *       };\n   *     }]);\n   *   </file>\n   *   <file name=\"index.html\">\n   *     <div ng-controller=\"CancelUpdateController\">\n   *       <p>Try typing something in each input.  See that the model only updates when you\n   *          blur off the input.\n   *        </p>\n   *        <p>Now see what happens if you start typing then press the Escape key</p>\n   *\n   *       <form name=\"myForm\" ng-model-options=\"{ updateOn: 'blur' }\">\n   *         <p>With $rollbackViewValue()</p>\n   *         <input name=\"myInput1\" ng-model=\"myValue\" ng-keydown=\"resetWithCancel($event)\"><br/>\n   *         myValue: \"{{ myValue }}\"\n   *\n   *         <p>Without $rollbackViewValue()</p>\n   *         <input name=\"myInput2\" ng-model=\"myValue\" ng-keydown=\"resetWithoutCancel($event)\"><br/>\n   *         myValue: \"{{ myValue }}\"\n   *       </form>\n   *     </div>\n   *   </file>\n   * </example>\n   */\n  this.$rollbackViewValue = function() {\n    $timeout.cancel(pendingDebounce);\n    ctrl.$viewValue = ctrl.$$lastCommittedViewValue;\n    ctrl.$render();\n  };\n\n  /**\n   * @ngdoc method\n   * @name ngModel.NgModelController#$validate\n   *\n   * @description\n   * Runs each of the registered validators (first synchronous validators and then\n   * asynchronous validators).\n   * If the validity changes to invalid, the model will be set to `undefined`,\n   * unless {@link ngModelOptions `ngModelOptions.allowInvalid`} is `true`.\n   * If the validity changes to valid, it will set the model to the last available valid\n   * modelValue, i.e. either the last parsed value or the last value set from the scope.\n   */\n  this.$validate = function() {\n    // ignore $validate before model is initialized\n    if (isNumber(ctrl.$modelValue) && isNaN(ctrl.$modelValue)) {\n      return;\n    }\n\n    var viewValue = ctrl.$$lastCommittedViewValue;\n    // Note: we use the $$rawModelValue as $modelValue might have been\n    // set to undefined during a view -> model update that found validation\n    // errors. We can't parse the view here, since that could change\n    // the model although neither viewValue nor the model on the scope changed\n    var modelValue = ctrl.$$rawModelValue;\n\n    // Check if the there's a parse error, so we don't unset it accidentially\n    var parserName = ctrl.$$parserName || 'parse';\n    var parserValid = ctrl.$error[parserName] ? false : undefined;\n\n    var prevValid = ctrl.$valid;\n    var prevModelValue = ctrl.$modelValue;\n\n    var allowInvalid = ctrl.$options && ctrl.$options.allowInvalid;\n\n    ctrl.$$runValidators(parserValid, modelValue, viewValue, function(allValid) {\n      // If there was no change in validity, don't update the model\n      // This prevents changing an invalid modelValue to undefined\n      if (!allowInvalid && prevValid !== allValid) {\n        // Note: Don't check ctrl.$valid here, as we could have\n        // external validators (e.g. calculated on the server),\n        // that just call $setValidity and need the model value\n        // to calculate their validity.\n        ctrl.$modelValue = allValid ? modelValue : undefined;\n\n        if (ctrl.$modelValue !== prevModelValue) {\n          ctrl.$$writeModelToScope();\n        }\n      }\n    });\n\n  };\n\n  this.$$runValidators = function(parseValid, modelValue, viewValue, doneCallback) {\n    currentValidationRunId++;\n    var localValidationRunId = currentValidationRunId;\n\n    // check parser error\n    if (!processParseErrors(parseValid)) {\n      validationDone(false);\n      return;\n    }\n    if (!processSyncValidators()) {\n      validationDone(false);\n      return;\n    }\n    processAsyncValidators();\n\n    function processParseErrors(parseValid) {\n      var errorKey = ctrl.$$parserName || 'parse';\n      if (parseValid === undefined) {\n        setValidity(errorKey, null);\n      } else {\n        setValidity(errorKey, parseValid);\n        if (!parseValid) {\n          forEach(ctrl.$validators, function(v, name) {\n            setValidity(name, null);\n          });\n          forEach(ctrl.$asyncValidators, function(v, name) {\n            setValidity(name, null);\n          });\n          return false;\n        }\n      }\n      return true;\n    }\n\n    function processSyncValidators() {\n      var syncValidatorsValid = true;\n      forEach(ctrl.$validators, function(validator, name) {\n        var result = validator(modelValue, viewValue);\n        syncValidatorsValid = syncValidatorsValid && result;\n        setValidity(name, result);\n      });\n      if (!syncValidatorsValid) {\n        forEach(ctrl.$asyncValidators, function(v, name) {\n          setValidity(name, null);\n        });\n        return false;\n      }\n      return true;\n    }\n\n    function processAsyncValidators() {\n      var validatorPromises = [];\n      var allValid = true;\n      forEach(ctrl.$asyncValidators, function(validator, name) {\n        var promise = validator(modelValue, viewValue);\n        if (!isPromiseLike(promise)) {\n          throw $ngModelMinErr(\"$asyncValidators\",\n            \"Expected asynchronous validator to return a promise but got '{0}' instead.\", promise);\n        }\n        setValidity(name, undefined);\n        validatorPromises.push(promise.then(function() {\n          setValidity(name, true);\n        }, function(error) {\n          allValid = false;\n          setValidity(name, false);\n        }));\n      });\n      if (!validatorPromises.length) {\n        validationDone(true);\n      } else {\n        $q.all(validatorPromises).then(function() {\n          validationDone(allValid);\n        }, noop);\n      }\n    }\n\n    function setValidity(name, isValid) {\n      if (localValidationRunId === currentValidationRunId) {\n        ctrl.$setValidity(name, isValid);\n      }\n    }\n\n    function validationDone(allValid) {\n      if (localValidationRunId === currentValidationRunId) {\n\n        doneCallback(allValid);\n      }\n    }\n  };\n\n  /**\n   * @ngdoc method\n   * @name ngModel.NgModelController#$commitViewValue\n   *\n   * @description\n   * Commit a pending update to the `$modelValue`.\n   *\n   * Updates may be pending by a debounced event or because the input is waiting for a some future\n   * event defined in `ng-model-options`. this method is rarely needed as `NgModelController`\n   * usually handles calling this in response to input events.\n   */\n  this.$commitViewValue = function() {\n    var viewValue = ctrl.$viewValue;\n\n    $timeout.cancel(pendingDebounce);\n\n    // If the view value has not changed then we should just exit, except in the case where there is\n    // a native validator on the element. In this case the validation state may have changed even though\n    // the viewValue has stayed empty.\n    if (ctrl.$$lastCommittedViewValue === viewValue && (viewValue !== '' || !ctrl.$$hasNativeValidators)) {\n      return;\n    }\n    ctrl.$$lastCommittedViewValue = viewValue;\n\n    // change to dirty\n    if (ctrl.$pristine) {\n      this.$setDirty();\n    }\n    this.$$parseAndValidate();\n  };\n\n  this.$$parseAndValidate = function() {\n    var viewValue = ctrl.$$lastCommittedViewValue;\n    var modelValue = viewValue;\n    var parserValid = isUndefined(modelValue) ? undefined : true;\n\n    if (parserValid) {\n      for (var i = 0; i < ctrl.$parsers.length; i++) {\n        modelValue = ctrl.$parsers[i](modelValue);\n        if (isUndefined(modelValue)) {\n          parserValid = false;\n          break;\n        }\n      }\n    }\n    if (isNumber(ctrl.$modelValue) && isNaN(ctrl.$modelValue)) {\n      // ctrl.$modelValue has not been touched yet...\n      ctrl.$modelValue = ngModelGet($scope);\n    }\n    var prevModelValue = ctrl.$modelValue;\n    var allowInvalid = ctrl.$options && ctrl.$options.allowInvalid;\n    ctrl.$$rawModelValue = modelValue;\n\n    if (allowInvalid) {\n      ctrl.$modelValue = modelValue;\n      writeToModelIfNeeded();\n    }\n\n    // Pass the $$lastCommittedViewValue here, because the cached viewValue might be out of date.\n    // This can happen if e.g. $setViewValue is called from inside a parser\n    ctrl.$$runValidators(parserValid, modelValue, ctrl.$$lastCommittedViewValue, function(allValid) {\n      if (!allowInvalid) {\n        // Note: Don't check ctrl.$valid here, as we could have\n        // external validators (e.g. calculated on the server),\n        // that just call $setValidity and need the model value\n        // to calculate their validity.\n        ctrl.$modelValue = allValid ? modelValue : undefined;\n        writeToModelIfNeeded();\n      }\n    });\n\n    function writeToModelIfNeeded() {\n      if (ctrl.$modelValue !== prevModelValue) {\n        ctrl.$$writeModelToScope();\n      }\n    }\n  };\n\n  this.$$writeModelToScope = function() {\n    ngModelSet($scope, ctrl.$modelValue);\n    forEach(ctrl.$viewChangeListeners, function(listener) {\n      try {\n        listener();\n      } catch (e) {\n        $exceptionHandler(e);\n      }\n    });\n  };\n\n  /**\n   * @ngdoc method\n   * @name ngModel.NgModelController#$setViewValue\n   *\n   * @description\n   * Update the view value.\n   *\n   * This method should be called when an input directive want to change the view value; typically,\n   * this is done from within a DOM event handler.\n   *\n   * For example {@link ng.directive:input input} calls it when the value of the input changes and\n   * {@link ng.directive:select select} calls it when an option is selected.\n   *\n   * If the new `value` is an object (rather than a string or a number), we should make a copy of the\n   * object before passing it to `$setViewValue`.  This is because `ngModel` does not perform a deep\n   * watch of objects, it only looks for a change of identity. If you only change the property of\n   * the object then ngModel will not realise that the object has changed and will not invoke the\n   * `$parsers` and `$validators` pipelines.\n   *\n   * For this reason, you should not change properties of the copy once it has been passed to\n   * `$setViewValue`. Otherwise you may cause the model value on the scope to change incorrectly.\n   *\n   * When this method is called, the new `value` will be staged for committing through the `$parsers`\n   * and `$validators` pipelines. If there are no special {@link ngModelOptions} specified then the staged\n   * value sent directly for processing, finally to be applied to `$modelValue` and then the\n   * **expression** specified in the `ng-model` attribute.\n   *\n   * Lastly, all the registered change listeners, in the `$viewChangeListeners` list, are called.\n   *\n   * In case the {@link ng.directive:ngModelOptions ngModelOptions} directive is used with `updateOn`\n   * and the `default` trigger is not listed, all those actions will remain pending until one of the\n   * `updateOn` events is triggered on the DOM element.\n   * All these actions will be debounced if the {@link ng.directive:ngModelOptions ngModelOptions}\n   * directive is used with a custom debounce for this particular event.\n   *\n   * Note that calling this function does not trigger a `$digest`.\n   *\n   * @param {string} value Value from the view.\n   * @param {string} trigger Event that triggered the update.\n   */\n  this.$setViewValue = function(value, trigger) {\n    ctrl.$viewValue = value;\n    if (!ctrl.$options || ctrl.$options.updateOnDefault) {\n      ctrl.$$debounceViewValueCommit(trigger);\n    }\n  };\n\n  this.$$debounceViewValueCommit = function(trigger) {\n    var debounceDelay = 0,\n        options = ctrl.$options,\n        debounce;\n\n    if (options && isDefined(options.debounce)) {\n      debounce = options.debounce;\n      if (isNumber(debounce)) {\n        debounceDelay = debounce;\n      } else if (isNumber(debounce[trigger])) {\n        debounceDelay = debounce[trigger];\n      } else if (isNumber(debounce['default'])) {\n        debounceDelay = debounce['default'];\n      }\n    }\n\n    $timeout.cancel(pendingDebounce);\n    if (debounceDelay) {\n      pendingDebounce = $timeout(function() {\n        ctrl.$commitViewValue();\n      }, debounceDelay);\n    } else if ($rootScope.$$phase) {\n      ctrl.$commitViewValue();\n    } else {\n      $scope.$apply(function() {\n        ctrl.$commitViewValue();\n      });\n    }\n  };\n\n  // model -> value\n  // Note: we cannot use a normal scope.$watch as we want to detect the following:\n  // 1. scope value is 'a'\n  // 2. user enters 'b'\n  // 3. ng-change kicks in and reverts scope value to 'a'\n  //    -> scope value did not change since the last digest as\n  //       ng-change executes in apply phase\n  // 4. view should be changed back to 'a'\n  $scope.$watch(function ngModelWatch() {\n    var modelValue = ngModelGet($scope);\n\n    // if scope model value and ngModel value are out of sync\n    // TODO(perf): why not move this to the action fn?\n    if (modelValue !== ctrl.$modelValue) {\n      ctrl.$modelValue = ctrl.$$rawModelValue = modelValue;\n\n      var formatters = ctrl.$formatters,\n          idx = formatters.length;\n\n      var viewValue = modelValue;\n      while (idx--) {\n        viewValue = formatters[idx](viewValue);\n      }\n      if (ctrl.$viewValue !== viewValue) {\n        ctrl.$viewValue = ctrl.$$lastCommittedViewValue = viewValue;\n        ctrl.$render();\n\n        ctrl.$$runValidators(undefined, modelValue, viewValue, noop);\n      }\n    }\n\n    return modelValue;\n  });\n}];\n\n\n/**\n * @ngdoc directive\n * @name ngModel\n *\n * @element input\n * @priority 1\n *\n * @description\n * The `ngModel` directive binds an `input`,`select`, `textarea` (or custom form control) to a\n * property on the scope using {@link ngModel.NgModelController NgModelController},\n * which is created and exposed by this directive.\n *\n * `ngModel` is responsible for:\n *\n * - Binding the view into the model, which other directives such as `input`, `textarea` or `select`\n *   require.\n * - Providing validation behavior (i.e. required, number, email, url).\n * - Keeping the state of the control (valid/invalid, dirty/pristine, touched/untouched, validation errors).\n * - Setting related css classes on the element (`ng-valid`, `ng-invalid`, `ng-dirty`, `ng-pristine`, `ng-touched`, `ng-untouched`) including animations.\n * - Registering the control with its parent {@link ng.directive:form form}.\n *\n * Note: `ngModel` will try to bind to the property given by evaluating the expression on the\n * current scope. If the property doesn't already exist on this scope, it will be created\n * implicitly and added to the scope.\n *\n * For best practices on using `ngModel`, see:\n *\n *  - [Understanding Scopes](https://github.com/angular/angular.js/wiki/Understanding-Scopes)\n *\n * For basic examples, how to use `ngModel`, see:\n *\n *  - {@link ng.directive:input input}\n *    - {@link input[text] text}\n *    - {@link input[checkbox] checkbox}\n *    - {@link input[radio] radio}\n *    - {@link input[number] number}\n *    - {@link input[email] email}\n *    - {@link input[url] url}\n *    - {@link input[date] date}\n *    - {@link input[datetime-local] datetime-local}\n *    - {@link input[time] time}\n *    - {@link input[month] month}\n *    - {@link input[week] week}\n *  - {@link ng.directive:select select}\n *  - {@link ng.directive:textarea textarea}\n *\n * # CSS classes\n * The following CSS classes are added and removed on the associated input/select/textarea element\n * depending on the validity of the model.\n *\n *  - `ng-valid`: the model is valid\n *  - `ng-invalid`: the model is invalid\n *  - `ng-valid-[key]`: for each valid key added by `$setValidity`\n *  - `ng-invalid-[key]`: for each invalid key added by `$setValidity`\n *  - `ng-pristine`: the control hasn't been interacted with yet\n *  - `ng-dirty`: the control has been interacted with\n *  - `ng-touched`: the control has been blurred\n *  - `ng-untouched`: the control hasn't been blurred\n *  - `ng-pending`: any `$asyncValidators` are unfulfilled\n *\n * Keep in mind that ngAnimate can detect each of these classes when added and removed.\n *\n * ## Animation Hooks\n *\n * Animations within models are triggered when any of the associated CSS classes are added and removed\n * on the input element which is attached to the model. These classes are: `.ng-pristine`, `.ng-dirty`,\n * `.ng-invalid` and `.ng-valid` as well as any other validations that are performed on the model itself.\n * The animations that are triggered within ngModel are similar to how they work in ngClass and\n * animations can be hooked into using CSS transitions, keyframes as well as JS animations.\n *\n * The following example shows a simple way to utilize CSS transitions to style an input element\n * that has been rendered as invalid after it has been validated:\n *\n * <pre>\n * //be sure to include ngAnimate as a module to hook into more\n * //advanced animations\n * .my-input {\n *   transition:0.5s linear all;\n *   background: white;\n * }\n * .my-input.ng-invalid {\n *   background: red;\n *   color:white;\n * }\n * </pre>\n *\n * @example\n * <example deps=\"angular-animate.js\" animations=\"true\" fixBase=\"true\" module=\"inputExample\">\n     <file name=\"index.html\">\n       <script>\n        angular.module('inputExample', [])\n          .controller('ExampleController', ['$scope', function($scope) {\n            $scope.val = '1';\n          }]);\n       </script>\n       <style>\n         .my-input {\n           -webkit-transition:all linear 0.5s;\n           transition:all linear 0.5s;\n           background: transparent;\n         }\n         .my-input.ng-invalid {\n           color:white;\n           background: red;\n         }\n       </style>\n       Update input to see transitions when valid/invalid.\n       Integer is a valid value.\n       <form name=\"testForm\" ng-controller=\"ExampleController\">\n         <input ng-model=\"val\" ng-pattern=\"/^\\d+$/\" name=\"anim\" class=\"my-input\" />\n       </form>\n     </file>\n * </example>\n *\n * ## Binding to a getter/setter\n *\n * Sometimes it's helpful to bind `ngModel` to a getter/setter function.  A getter/setter is a\n * function that returns a representation of the model when called with zero arguments, and sets\n * the internal state of a model when called with an argument. It's sometimes useful to use this\n * for models that have an internal representation that's different than what the model exposes\n * to the view.\n *\n * <div class=\"alert alert-success\">\n * **Best Practice:** It's best to keep getters fast because Angular is likely to call them more\n * frequently than other parts of your code.\n * </div>\n *\n * You use this behavior by adding `ng-model-options=\"{ getterSetter: true }\"` to an element that\n * has `ng-model` attached to it. You can also add `ng-model-options=\"{ getterSetter: true }\"` to\n * a `<form>`, which will enable this behavior for all `<input>`s within it. See\n * {@link ng.directive:ngModelOptions `ngModelOptions`} for more.\n *\n * The following example shows how to use `ngModel` with a getter/setter:\n *\n * @example\n * <example name=\"ngModel-getter-setter\" module=\"getterSetterExample\">\n     <file name=\"index.html\">\n       <div ng-controller=\"ExampleController\">\n         <form name=\"userForm\">\n           Name:\n           <input type=\"text\" name=\"userName\"\n                  ng-model=\"user.name\"\n                  ng-model-options=\"{ getterSetter: true }\" />\n         </form>\n         <pre>user.name = <span ng-bind=\"user.name()\"></span></pre>\n       </div>\n     </file>\n     <file name=\"app.js\">\n       angular.module('getterSetterExample', [])\n         .controller('ExampleController', ['$scope', function($scope) {\n           var _name = 'Brian';\n           $scope.user = {\n             name: function(newName) {\n               if (angular.isDefined(newName)) {\n                 _name = newName;\n               }\n               return _name;\n             }\n           };\n         }]);\n     </file>\n * </example>\n */\nvar ngModelDirective = ['$rootScope', function($rootScope) {\n  return {\n    restrict: 'A',\n    require: ['ngModel', '^?form', '^?ngModelOptions'],\n    controller: NgModelController,\n    // Prelink needs to run before any input directive\n    // so that we can set the NgModelOptions in NgModelController\n    // before anyone else uses it.\n    priority: 1,\n    compile: function ngModelCompile(element) {\n      // Setup initial state of the control\n      element.addClass(PRISTINE_CLASS).addClass(UNTOUCHED_CLASS).addClass(VALID_CLASS);\n\n      return {\n        pre: function ngModelPreLink(scope, element, attr, ctrls) {\n          var modelCtrl = ctrls[0],\n              formCtrl = ctrls[1] || nullFormCtrl;\n\n          modelCtrl.$$setOptions(ctrls[2] && ctrls[2].$options);\n\n          // notify others, especially parent forms\n          formCtrl.$addControl(modelCtrl);\n\n          attr.$observe('name', function(newValue) {\n            if (modelCtrl.$name !== newValue) {\n              formCtrl.$$renameControl(modelCtrl, newValue);\n            }\n          });\n\n          scope.$on('$destroy', function() {\n            formCtrl.$removeControl(modelCtrl);\n          });\n        },\n        post: function ngModelPostLink(scope, element, attr, ctrls) {\n          var modelCtrl = ctrls[0];\n          if (modelCtrl.$options && modelCtrl.$options.updateOn) {\n            element.on(modelCtrl.$options.updateOn, function(ev) {\n              modelCtrl.$$debounceViewValueCommit(ev && ev.type);\n            });\n          }\n\n          element.on('blur', function(ev) {\n            if (modelCtrl.$touched) return;\n\n            if ($rootScope.$$phase) {\n              scope.$evalAsync(modelCtrl.$setTouched);\n            } else {\n              scope.$apply(modelCtrl.$setTouched);\n            }\n          });\n        }\n      };\n    }\n  };\n}];\n\nvar DEFAULT_REGEXP = /(\\s+|^)default(\\s+|$)/;\n\n/**\n * @ngdoc directive\n * @name ngModelOptions\n *\n * @description\n * Allows tuning how model updates are done. Using `ngModelOptions` you can specify a custom list of\n * events that will trigger a model update and/or a debouncing delay so that the actual update only\n * takes place when a timer expires; this timer will be reset after another change takes place.\n *\n * Given the nature of `ngModelOptions`, the value displayed inside input fields in the view might\n * be different than the value in the actual model. This means that if you update the model you\n * should also invoke {@link ngModel.NgModelController `$rollbackViewValue`} on the relevant input field in\n * order to make sure it is synchronized with the model and that any debounced action is canceled.\n *\n * The easiest way to reference the control's {@link ngModel.NgModelController `$rollbackViewValue`}\n * method is by making sure the input is placed inside a form that has a `name` attribute. This is\n * important because `form` controllers are published to the related scope under the name in their\n * `name` attribute.\n *\n * Any pending changes will take place immediately when an enclosing form is submitted via the\n * `submit` event. Note that `ngClick` events will occur before the model is updated. Use `ngSubmit`\n * to have access to the updated model.\n *\n * `ngModelOptions` has an effect on the element it's declared on and its descendants.\n *\n * @param {Object} ngModelOptions options to apply to the current model. Valid keys are:\n *   - `updateOn`: string specifying which event should the input be bound to. You can set several\n *     events using an space delimited list. There is a special event called `default` that\n *     matches the default events belonging of the control.\n *   - `debounce`: integer value which contains the debounce model update value in milliseconds. A\n *     value of 0 triggers an immediate update. If an object is supplied instead, you can specify a\n *     custom value for each event. For example:\n *     `ng-model-options=\"{ updateOn: 'default blur', debounce: {'default': 500, 'blur': 0} }\"`\n *   - `allowInvalid`: boolean value which indicates that the model can be set with values that did\n *     not validate correctly instead of the default behavior of setting the model to undefined.\n *   - `getterSetter`: boolean value which determines whether or not to treat functions bound to\n       `ngModel` as getters/setters.\n *   - `timezone`: Defines the timezone to be used to read/write the `Date` instance in the model for\n *     `<input type=\"date\">`, `<input type=\"time\">`, ... . Right now, the only supported value is `'UTC'`,\n *     otherwise the default timezone of the browser will be used.\n *\n * @example\n\n  The following example shows how to override immediate updates. Changes on the inputs within the\n  form will update the model only when the control loses focus (blur event). If `escape` key is\n  pressed while the input field is focused, the value is reset to the value in the current model.\n\n  <example name=\"ngModelOptions-directive-blur\" module=\"optionsExample\">\n    <file name=\"index.html\">\n      <div ng-controller=\"ExampleController\">\n        <form name=\"userForm\">\n          Name:\n          <input type=\"text\" name=\"userName\"\n                 ng-model=\"user.name\"\n                 ng-model-options=\"{ updateOn: 'blur' }\"\n                 ng-keyup=\"cancel($event)\" /><br />\n\n          Other data:\n          <input type=\"text\" ng-model=\"user.data\" /><br />\n        </form>\n        <pre>user.name = <span ng-bind=\"user.name\"></span></pre>\n      </div>\n    </file>\n    <file name=\"app.js\">\n      angular.module('optionsExample', [])\n        .controller('ExampleController', ['$scope', function($scope) {\n          $scope.user = { name: 'say', data: '' };\n\n          $scope.cancel = function(e) {\n            if (e.keyCode == 27) {\n              $scope.userForm.userName.$rollbackViewValue();\n            }\n          };\n        }]);\n    </file>\n    <file name=\"protractor.js\" type=\"protractor\">\n      var model = element(by.binding('user.name'));\n      var input = element(by.model('user.name'));\n      var other = element(by.model('user.data'));\n\n      it('should allow custom events', function() {\n        input.sendKeys(' hello');\n        input.click();\n        expect(model.getText()).toEqual('say');\n        other.click();\n        expect(model.getText()).toEqual('say hello');\n      });\n\n      it('should $rollbackViewValue when model changes', function() {\n        input.sendKeys(' hello');\n        expect(input.getAttribute('value')).toEqual('say hello');\n        input.sendKeys(protractor.Key.ESCAPE);\n        expect(input.getAttribute('value')).toEqual('say');\n        other.click();\n        expect(model.getText()).toEqual('say');\n      });\n    </file>\n  </example>\n\n  This one shows how to debounce model changes. Model will be updated only 1 sec after last change.\n  If the `Clear` button is pressed, any debounced action is canceled and the value becomes empty.\n\n  <example name=\"ngModelOptions-directive-debounce\" module=\"optionsExample\">\n    <file name=\"index.html\">\n      <div ng-controller=\"ExampleController\">\n        <form name=\"userForm\">\n          Name:\n          <input type=\"text\" name=\"userName\"\n                 ng-model=\"user.name\"\n                 ng-model-options=\"{ debounce: 1000 }\" />\n          <button ng-click=\"userForm.userName.$rollbackViewValue(); user.name=''\">Clear</button><br />\n        </form>\n        <pre>user.name = <span ng-bind=\"user.name\"></span></pre>\n      </div>\n    </file>\n    <file name=\"app.js\">\n      angular.module('optionsExample', [])\n        .controller('ExampleController', ['$scope', function($scope) {\n          $scope.user = { name: 'say' };\n        }]);\n    </file>\n  </example>\n\n  This one shows how to bind to getter/setters:\n\n  <example name=\"ngModelOptions-directive-getter-setter\" module=\"getterSetterExample\">\n    <file name=\"index.html\">\n      <div ng-controller=\"ExampleController\">\n        <form name=\"userForm\">\n          Name:\n          <input type=\"text\" name=\"userName\"\n                 ng-model=\"user.name\"\n                 ng-model-options=\"{ getterSetter: true }\" />\n        </form>\n        <pre>user.name = <span ng-bind=\"user.name()\"></span></pre>\n      </div>\n    </file>\n    <file name=\"app.js\">\n      angular.module('getterSetterExample', [])\n        .controller('ExampleController', ['$scope', function($scope) {\n          var _name = 'Brian';\n          $scope.user = {\n            name: function(newName) {\n              return angular.isDefined(newName) ? (_name = newName) : _name;\n            }\n          };\n        }]);\n    </file>\n  </example>\n */\nvar ngModelOptionsDirective = function() {\n  return {\n    restrict: 'A',\n    controller: ['$scope', '$attrs', function($scope, $attrs) {\n      var that = this;\n      this.$options = $scope.$eval($attrs.ngModelOptions);\n      // Allow adding/overriding bound events\n      if (this.$options.updateOn !== undefined) {\n        this.$options.updateOnDefault = false;\n        // extract \"default\" pseudo-event from list of events that can trigger a model update\n        this.$options.updateOn = trim(this.$options.updateOn.replace(DEFAULT_REGEXP, function() {\n          that.$options.updateOnDefault = true;\n          return ' ';\n        }));\n      } else {\n        this.$options.updateOnDefault = true;\n      }\n    }]\n  };\n};\n\n\n\n// helper methods\nfunction addSetValidityMethod(context) {\n  var ctrl = context.ctrl,\n      $element = context.$element,\n      classCache = {},\n      set = context.set,\n      unset = context.unset,\n      parentForm = context.parentForm,\n      $animate = context.$animate;\n\n  classCache[INVALID_CLASS] = !(classCache[VALID_CLASS] = $element.hasClass(VALID_CLASS));\n\n  ctrl.$setValidity = setValidity;\n\n  function setValidity(validationErrorKey, state, controller) {\n    if (state === undefined) {\n      createAndSet('$pending', validationErrorKey, controller);\n    } else {\n      unsetAndCleanup('$pending', validationErrorKey, controller);\n    }\n    if (!isBoolean(state)) {\n      unset(ctrl.$error, validationErrorKey, controller);\n      unset(ctrl.$$success, validationErrorKey, controller);\n    } else {\n      if (state) {\n        unset(ctrl.$error, validationErrorKey, controller);\n        set(ctrl.$$success, validationErrorKey, controller);\n      } else {\n        set(ctrl.$error, validationErrorKey, controller);\n        unset(ctrl.$$success, validationErrorKey, controller);\n      }\n    }\n    if (ctrl.$pending) {\n      cachedToggleClass(PENDING_CLASS, true);\n      ctrl.$valid = ctrl.$invalid = undefined;\n      toggleValidationCss('', null);\n    } else {\n      cachedToggleClass(PENDING_CLASS, false);\n      ctrl.$valid = isObjectEmpty(ctrl.$error);\n      ctrl.$invalid = !ctrl.$valid;\n      toggleValidationCss('', ctrl.$valid);\n    }\n\n    // re-read the state as the set/unset methods could have\n    // combined state in ctrl.$error[validationError] (used for forms),\n    // where setting/unsetting only increments/decrements the value,\n    // and does not replace it.\n    var combinedState;\n    if (ctrl.$pending && ctrl.$pending[validationErrorKey]) {\n      combinedState = undefined;\n    } else if (ctrl.$error[validationErrorKey]) {\n      combinedState = false;\n    } else if (ctrl.$$success[validationErrorKey]) {\n      combinedState = true;\n    } else {\n      combinedState = null;\n    }\n\n    toggleValidationCss(validationErrorKey, combinedState);\n    parentForm.$setValidity(validationErrorKey, combinedState, ctrl);\n  }\n\n  function createAndSet(name, value, controller) {\n    if (!ctrl[name]) {\n      ctrl[name] = {};\n    }\n    set(ctrl[name], value, controller);\n  }\n\n  function unsetAndCleanup(name, value, controller) {\n    if (ctrl[name]) {\n      unset(ctrl[name], value, controller);\n    }\n    if (isObjectEmpty(ctrl[name])) {\n      ctrl[name] = undefined;\n    }\n  }\n\n  function cachedToggleClass(className, switchValue) {\n    if (switchValue && !classCache[className]) {\n      $animate.addClass($element, className);\n      classCache[className] = true;\n    } else if (!switchValue && classCache[className]) {\n      $animate.removeClass($element, className);\n      classCache[className] = false;\n    }\n  }\n\n  function toggleValidationCss(validationErrorKey, isValid) {\n    validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : '';\n\n    cachedToggleClass(VALID_CLASS + validationErrorKey, isValid === true);\n    cachedToggleClass(INVALID_CLASS + validationErrorKey, isValid === false);\n  }\n}\n\nfunction isObjectEmpty(obj) {\n  if (obj) {\n    for (var prop in obj) {\n      return false;\n    }\n  }\n  return true;\n}\n\n/**\n * @ngdoc directive\n * @name ngNonBindable\n * @restrict AC\n * @priority 1000\n *\n * @description\n * The `ngNonBindable` directive tells Angular not to compile or bind the contents of the current\n * DOM element. This is useful if the element contains what appears to be Angular directives and\n * bindings but which should be ignored by Angular. This could be the case if you have a site that\n * displays snippets of code, for instance.\n *\n * @element ANY\n *\n * @example\n * In this example there are two locations where a simple interpolation binding (`{{}}`) is present,\n * but the one wrapped in `ngNonBindable` is left alone.\n *\n * @example\n    <example>\n      <file name=\"index.html\">\n        <div>Normal: {{1 + 2}}</div>\n        <div ng-non-bindable>Ignored: {{1 + 2}}</div>\n      </file>\n      <file name=\"protractor.js\" type=\"protractor\">\n       it('should check ng-non-bindable', function() {\n         expect(element(by.binding('1 + 2')).getText()).toContain('3');\n         expect(element.all(by.css('div')).last().getText()).toMatch(/1 \\+ 2/);\n       });\n      </file>\n    </example>\n */\nvar ngNonBindableDirective = ngDirective({ terminal: true, priority: 1000 });\n\n/**\n * @ngdoc directive\n * @name ngPluralize\n * @restrict EA\n *\n * @description\n * `ngPluralize` is a directive that displays messages according to en-US localization rules.\n * These rules are bundled with angular.js, but can be overridden\n * (see {@link guide/i18n Angular i18n} dev guide). You configure ngPluralize directive\n * by specifying the mappings between\n * [plural categories](http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html)\n * and the strings to be displayed.\n *\n * # Plural categories and explicit number rules\n * There are two\n * [plural categories](http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html)\n * in Angular's default en-US locale: \"one\" and \"other\".\n *\n * While a plural category may match many numbers (for example, in en-US locale, \"other\" can match\n * any number that is not 1), an explicit number rule can only match one number. For example, the\n * explicit number rule for \"3\" matches the number 3. There are examples of plural categories\n * and explicit number rules throughout the rest of this documentation.\n *\n * # Configuring ngPluralize\n * You configure ngPluralize by providing 2 attributes: `count` and `when`.\n * You can also provide an optional attribute, `offset`.\n *\n * The value of the `count` attribute can be either a string or an {@link guide/expression\n * Angular expression}; these are evaluated on the current scope for its bound value.\n *\n * The `when` attribute specifies the mappings between plural categories and the actual\n * string to be displayed. The value of the attribute should be a JSON object.\n *\n * The following example shows how to configure ngPluralize:\n *\n * ```html\n * <ng-pluralize count=\"personCount\"\n                 when=\"{'0': 'Nobody is viewing.',\n *                      'one': '1 person is viewing.',\n *                      'other': '{} people are viewing.'}\">\n * </ng-pluralize>\n *```\n *\n * In the example, `\"0: Nobody is viewing.\"` is an explicit number rule. If you did not\n * specify this rule, 0 would be matched to the \"other\" category and \"0 people are viewing\"\n * would be shown instead of \"Nobody is viewing\". You can specify an explicit number rule for\n * other numbers, for example 12, so that instead of showing \"12 people are viewing\", you can\n * show \"a dozen people are viewing\".\n *\n * You can use a set of closed braces (`{}`) as a placeholder for the number that you want substituted\n * into pluralized strings. In the previous example, Angular will replace `{}` with\n * <span ng-non-bindable>`{{personCount}}`</span>. The closed braces `{}` is a placeholder\n * for <span ng-non-bindable>{{numberExpression}}</span>.\n *\n * # Configuring ngPluralize with offset\n * The `offset` attribute allows further customization of pluralized text, which can result in\n * a better user experience. For example, instead of the message \"4 people are viewing this document\",\n * you might display \"John, Kate and 2 others are viewing this document\".\n * The offset attribute allows you to offset a number by any desired value.\n * Let's take a look at an example:\n *\n * ```html\n * <ng-pluralize count=\"personCount\" offset=2\n *               when=\"{'0': 'Nobody is viewing.',\n *                      '1': '{{person1}} is viewing.',\n *                      '2': '{{person1}} and {{person2}} are viewing.',\n *                      'one': '{{person1}}, {{person2}} and one other person are viewing.',\n *                      'other': '{{person1}}, {{person2}} and {} other people are viewing.'}\">\n * </ng-pluralize>\n * ```\n *\n * Notice that we are still using two plural categories(one, other), but we added\n * three explicit number rules 0, 1 and 2.\n * When one person, perhaps John, views the document, \"John is viewing\" will be shown.\n * When three people view the document, no explicit number rule is found, so\n * an offset of 2 is taken off 3, and Angular uses 1 to decide the plural category.\n * In this case, plural category 'one' is matched and \"John, Mary and one other person are viewing\"\n * is shown.\n *\n * Note that when you specify offsets, you must provide explicit number rules for\n * numbers from 0 up to and including the offset. If you use an offset of 3, for example,\n * you must provide explicit number rules for 0, 1, 2 and 3. You must also provide plural strings for\n * plural categories \"one\" and \"other\".\n *\n * @param {string|expression} count The variable to be bound to.\n * @param {string} when The mapping between plural category to its corresponding strings.\n * @param {number=} offset Offset to deduct from the total number.\n *\n * @example\n    <example module=\"pluralizeExample\">\n      <file name=\"index.html\">\n        <script>\n          angular.module('pluralizeExample', [])\n            .controller('ExampleController', ['$scope', function($scope) {\n              $scope.person1 = 'Igor';\n              $scope.person2 = 'Misko';\n              $scope.personCount = 1;\n            }]);\n        </script>\n        <div ng-controller=\"ExampleController\">\n          Person 1:<input type=\"text\" ng-model=\"person1\" value=\"Igor\" /><br/>\n          Person 2:<input type=\"text\" ng-model=\"person2\" value=\"Misko\" /><br/>\n          Number of People:<input type=\"text\" ng-model=\"personCount\" value=\"1\" /><br/>\n\n          <!--- Example with simple pluralization rules for en locale --->\n          Without Offset:\n          <ng-pluralize count=\"personCount\"\n                        when=\"{'0': 'Nobody is viewing.',\n                               'one': '1 person is viewing.',\n                               'other': '{} people are viewing.'}\">\n          </ng-pluralize><br>\n\n          <!--- Example with offset --->\n          With Offset(2):\n          <ng-pluralize count=\"personCount\" offset=2\n                        when=\"{'0': 'Nobody is viewing.',\n                               '1': '{{person1}} is viewing.',\n                               '2': '{{person1}} and {{person2}} are viewing.',\n                               'one': '{{person1}}, {{person2}} and one other person are viewing.',\n                               'other': '{{person1}}, {{person2}} and {} other people are viewing.'}\">\n          </ng-pluralize>\n        </div>\n      </file>\n      <file name=\"protractor.js\" type=\"protractor\">\n        it('should show correct pluralized string', function() {\n          var withoutOffset = element.all(by.css('ng-pluralize')).get(0);\n          var withOffset = element.all(by.css('ng-pluralize')).get(1);\n          var countInput = element(by.model('personCount'));\n\n          expect(withoutOffset.getText()).toEqual('1 person is viewing.');\n          expect(withOffset.getText()).toEqual('Igor is viewing.');\n\n          countInput.clear();\n          countInput.sendKeys('0');\n\n          expect(withoutOffset.getText()).toEqual('Nobody is viewing.');\n          expect(withOffset.getText()).toEqual('Nobody is viewing.');\n\n          countInput.clear();\n          countInput.sendKeys('2');\n\n          expect(withoutOffset.getText()).toEqual('2 people are viewing.');\n          expect(withOffset.getText()).toEqual('Igor and Misko are viewing.');\n\n          countInput.clear();\n          countInput.sendKeys('3');\n\n          expect(withoutOffset.getText()).toEqual('3 people are viewing.');\n          expect(withOffset.getText()).toEqual('Igor, Misko and one other person are viewing.');\n\n          countInput.clear();\n          countInput.sendKeys('4');\n\n          expect(withoutOffset.getText()).toEqual('4 people are viewing.');\n          expect(withOffset.getText()).toEqual('Igor, Misko and 2 other people are viewing.');\n        });\n        it('should show data-bound names', function() {\n          var withOffset = element.all(by.css('ng-pluralize')).get(1);\n          var personCount = element(by.model('personCount'));\n          var person1 = element(by.model('person1'));\n          var person2 = element(by.model('person2'));\n          personCount.clear();\n          personCount.sendKeys('4');\n          person1.clear();\n          person1.sendKeys('Di');\n          person2.clear();\n          person2.sendKeys('Vojta');\n          expect(withOffset.getText()).toEqual('Di, Vojta and 2 other people are viewing.');\n        });\n      </file>\n    </example>\n */\nvar ngPluralizeDirective = ['$locale', '$interpolate', function($locale, $interpolate) {\n  var BRACE = /{}/g,\n      IS_WHEN = /^when(Minus)?(.+)$/;\n\n  return {\n    restrict: 'EA',\n    link: function(scope, element, attr) {\n      var numberExp = attr.count,\n          whenExp = attr.$attr.when && element.attr(attr.$attr.when), // we have {{}} in attrs\n          offset = attr.offset || 0,\n          whens = scope.$eval(whenExp) || {},\n          whensExpFns = {},\n          startSymbol = $interpolate.startSymbol(),\n          endSymbol = $interpolate.endSymbol(),\n          braceReplacement = startSymbol + numberExp + '-' + offset + endSymbol,\n          watchRemover = angular.noop,\n          lastCount;\n\n      forEach(attr, function(expression, attributeName) {\n        var tmpMatch = IS_WHEN.exec(attributeName);\n        if (tmpMatch) {\n          var whenKey = (tmpMatch[1] ? '-' : '') + lowercase(tmpMatch[2]);\n          whens[whenKey] = element.attr(attr.$attr[attributeName]);\n        }\n      });\n      forEach(whens, function(expression, key) {\n        whensExpFns[key] = $interpolate(expression.replace(BRACE, braceReplacement));\n\n      });\n\n      scope.$watch(numberExp, function ngPluralizeWatchAction(newVal) {\n        var count = parseFloat(newVal);\n        var countIsNaN = isNaN(count);\n\n        if (!countIsNaN && !(count in whens)) {\n          // If an explicit number rule such as 1, 2, 3... is defined, just use it.\n          // Otherwise, check it against pluralization rules in $locale service.\n          count = $locale.pluralCat(count - offset);\n        }\n\n        // If both `count` and `lastCount` are NaN, we don't need to re-register a watch.\n        // In JS `NaN !== NaN`, so we have to exlicitly check.\n        if ((count !== lastCount) && !(countIsNaN && isNaN(lastCount))) {\n          watchRemover();\n          watchRemover = scope.$watch(whensExpFns[count], updateElementText);\n          lastCount = count;\n        }\n      });\n\n      function updateElementText(newText) {\n        element.text(newText || '');\n      }\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ngRepeat\n *\n * @description\n * The `ngRepeat` directive instantiates a template once per item from a collection. Each template\n * instance gets its own scope, where the given loop variable is set to the current collection item,\n * and `$index` is set to the item index or key.\n *\n * Special properties are exposed on the local scope of each template instance, including:\n *\n * | Variable  | Type            | Details                                                                     |\n * |-----------|-----------------|-----------------------------------------------------------------------------|\n * | `$index`  | {@type number}  | iterator offset of the repeated element (0..length-1)                       |\n * | `$first`  | {@type boolean} | true if the repeated element is first in the iterator.                      |\n * | `$middle` | {@type boolean} | true if the repeated element is between the first and last in the iterator. |\n * | `$last`   | {@type boolean} | true if the repeated element is last in the iterator.                       |\n * | `$even`   | {@type boolean} | true if the iterator position `$index` is even (otherwise false).           |\n * | `$odd`    | {@type boolean} | true if the iterator position `$index` is odd (otherwise false).            |\n *\n * Creating aliases for these properties is possible with {@link ng.directive:ngInit `ngInit`}.\n * This may be useful when, for instance, nesting ngRepeats.\n *\n * # Iterating over object properties\n *\n * It is possible to get `ngRepeat` to iterate over the properties of an object using the following\n * syntax:\n *\n * ```js\n * <div ng-repeat=\"(key, value) in myObj\"> ... </div>\n * ```\n *\n * You need to be aware that the JavaScript specification does not define what order\n * it will return the keys for an object. In order to have a guaranteed deterministic order\n * for the keys, Angular versions up to and including 1.3 **sort the keys alphabetically**.\n *\n * If this is not desired, the recommended workaround is to convert your object into an array\n * that is sorted into the order that you prefer before providing it to `ngRepeat`.  You could\n * do this with a filter such as [toArrayFilter](http://ngmodules.org/modules/angular-toArrayFilter)\n * or implement a `$watch` on the object yourself.\n *\n * In version 1.4 we will remove the sorting, since it seems that browsers generally follow the\n * strategy of providing keys in the order in which they were defined, although there are exceptions\n * when keys are deleted and reinstated.\n *\n *\n * # Special repeat start and end points\n * To repeat a series of elements instead of just one parent element, ngRepeat (as well as other ng directives) supports extending\n * the range of the repeater by defining explicit start and end points by using **ng-repeat-start** and **ng-repeat-end** respectively.\n * The **ng-repeat-start** directive works the same as **ng-repeat**, but will repeat all the HTML code (including the tag it's defined on)\n * up to and including the ending HTML tag where **ng-repeat-end** is placed.\n *\n * The example below makes use of this feature:\n * ```html\n *   <header ng-repeat-start=\"item in items\">\n *     Header {{ item }}\n *   </header>\n *   <div class=\"body\">\n *     Body {{ item }}\n *   </div>\n *   <footer ng-repeat-end>\n *     Footer {{ item }}\n *   </footer>\n * ```\n *\n * And with an input of {@type ['A','B']} for the items variable in the example above, the output will evaluate to:\n * ```html\n *   <header>\n *     Header A\n *   </header>\n *   <div class=\"body\">\n *     Body A\n *   </div>\n *   <footer>\n *     Footer A\n *   </footer>\n *   <header>\n *     Header B\n *   </header>\n *   <div class=\"body\">\n *     Body B\n *   </div>\n *   <footer>\n *     Footer B\n *   </footer>\n * ```\n *\n * The custom start and end points for ngRepeat also support all other HTML directive syntax flavors provided in AngularJS (such\n * as **data-ng-repeat-start**, **x-ng-repeat-start** and **ng:repeat-start**).\n *\n * @animations\n * **.enter** - when a new item is added to the list or when an item is revealed after a filter\n *\n * **.leave** - when an item is removed from the list or when an item is filtered out\n *\n * **.move** - when an adjacent item is filtered out causing a reorder or when the item contents are reordered\n *\n * @element ANY\n * @scope\n * @priority 1000\n * @param {repeat_expression} ngRepeat The expression indicating how to enumerate a collection. These\n *   formats are currently supported:\n *\n *   * `variable in expression` – where variable is the user defined loop variable and `expression`\n *     is a scope expression giving the collection to enumerate.\n *\n *     For example: `album in artist.albums`.\n *\n *   * `(key, value) in expression` – where `key` and `value` can be any user defined identifiers,\n *     and `expression` is the scope expression giving the collection to enumerate.\n *\n *     For example: `(name, age) in {'adam':10, 'amalie':12}`.\n *\n *   * `variable in expression track by tracking_expression` – You can also provide an optional tracking function\n *     which can be used to associate the objects in the collection with the DOM elements. If no tracking function\n *     is specified the ng-repeat associates elements by identity in the collection. It is an error to have\n *     more than one tracking function to resolve to the same key. (This would mean that two distinct objects are\n *     mapped to the same DOM element, which is not possible.)  Filters should be applied to the expression,\n *     before specifying a tracking expression.\n *\n *     For example: `item in items` is equivalent to `item in items track by $id(item)`. This implies that the DOM elements\n *     will be associated by item identity in the array.\n *\n *     For example: `item in items track by $id(item)`. A built in `$id()` function can be used to assign a unique\n *     `$$hashKey` property to each item in the array. This property is then used as a key to associated DOM elements\n *     with the corresponding item in the array by identity. Moving the same object in array would move the DOM\n *     element in the same way in the DOM.\n *\n *     For example: `item in items track by item.id` is a typical pattern when the items come from the database. In this\n *     case the object identity does not matter. Two objects are considered equivalent as long as their `id`\n *     property is same.\n *\n *     For example: `item in items | filter:searchText track by item.id` is a pattern that might be used to apply a filter\n *     to items in conjunction with a tracking expression.\n *\n *   * `variable in expression as alias_expression` – You can also provide an optional alias expression which will then store the\n *     intermediate results of the repeater after the filters have been applied. Typically this is used to render a special message\n *     when a filter is active on the repeater, but the filtered result set is empty.\n *\n *     For example: `item in items | filter:x as results` will store the fragment of the repeated items as `results`, but only after\n *     the items have been processed through the filter.\n *\n * @example\n * This example initializes the scope to a list of names and\n * then uses `ngRepeat` to display every person:\n  <example module=\"ngAnimate\" deps=\"angular-animate.js\" animations=\"true\">\n    <file name=\"index.html\">\n      <div ng-init=\"friends = [\n        {name:'John', age:25, gender:'boy'},\n        {name:'Jessie', age:30, gender:'girl'},\n        {name:'Johanna', age:28, gender:'girl'},\n        {name:'Joy', age:15, gender:'girl'},\n        {name:'Mary', age:28, gender:'girl'},\n        {name:'Peter', age:95, gender:'boy'},\n        {name:'Sebastian', age:50, gender:'boy'},\n        {name:'Erika', age:27, gender:'girl'},\n        {name:'Patrick', age:40, gender:'boy'},\n        {name:'Samantha', age:60, gender:'girl'}\n      ]\">\n        I have {{friends.length}} friends. They are:\n        <input type=\"search\" ng-model=\"q\" placeholder=\"filter friends...\" />\n        <ul class=\"example-animate-container\">\n          <li class=\"animate-repeat\" ng-repeat=\"friend in friends | filter:q as results\">\n            [{{$index + 1}}] {{friend.name}} who is {{friend.age}} years old.\n          </li>\n          <li class=\"animate-repeat\" ng-if=\"results.length == 0\">\n            <strong>No results found...</strong>\n          </li>\n        </ul>\n      </div>\n    </file>\n    <file name=\"animations.css\">\n      .example-animate-container {\n        background:white;\n        border:1px solid black;\n        list-style:none;\n        margin:0;\n        padding:0 10px;\n      }\n\n      .animate-repeat {\n        line-height:40px;\n        list-style:none;\n        box-sizing:border-box;\n      }\n\n      .animate-repeat.ng-move,\n      .animate-repeat.ng-enter,\n      .animate-repeat.ng-leave {\n        -webkit-transition:all linear 0.5s;\n        transition:all linear 0.5s;\n      }\n\n      .animate-repeat.ng-leave.ng-leave-active,\n      .animate-repeat.ng-move,\n      .animate-repeat.ng-enter {\n        opacity:0;\n        max-height:0;\n      }\n\n      .animate-repeat.ng-leave,\n      .animate-repeat.ng-move.ng-move-active,\n      .animate-repeat.ng-enter.ng-enter-active {\n        opacity:1;\n        max-height:40px;\n      }\n    </file>\n    <file name=\"protractor.js\" type=\"protractor\">\n      var friends = element.all(by.repeater('friend in friends'));\n\n      it('should render initial data set', function() {\n        expect(friends.count()).toBe(10);\n        expect(friends.get(0).getText()).toEqual('[1] John who is 25 years old.');\n        expect(friends.get(1).getText()).toEqual('[2] Jessie who is 30 years old.');\n        expect(friends.last().getText()).toEqual('[10] Samantha who is 60 years old.');\n        expect(element(by.binding('friends.length')).getText())\n            .toMatch(\"I have 10 friends. They are:\");\n      });\n\n       it('should update repeater when filter predicate changes', function() {\n         expect(friends.count()).toBe(10);\n\n         element(by.model('q')).sendKeys('ma');\n\n         expect(friends.count()).toBe(2);\n         expect(friends.get(0).getText()).toEqual('[1] Mary who is 28 years old.');\n         expect(friends.last().getText()).toEqual('[2] Samantha who is 60 years old.');\n       });\n      </file>\n    </example>\n */\nvar ngRepeatDirective = ['$parse', '$animate', function($parse, $animate) {\n  var NG_REMOVED = '$$NG_REMOVED';\n  var ngRepeatMinErr = minErr('ngRepeat');\n\n  var updateScope = function(scope, index, valueIdentifier, value, keyIdentifier, key, arrayLength) {\n    // TODO(perf): generate setters to shave off ~40ms or 1-1.5%\n    scope[valueIdentifier] = value;\n    if (keyIdentifier) scope[keyIdentifier] = key;\n    scope.$index = index;\n    scope.$first = (index === 0);\n    scope.$last = (index === (arrayLength - 1));\n    scope.$middle = !(scope.$first || scope.$last);\n    // jshint bitwise: false\n    scope.$odd = !(scope.$even = (index&1) === 0);\n    // jshint bitwise: true\n  };\n\n  var getBlockStart = function(block) {\n    return block.clone[0];\n  };\n\n  var getBlockEnd = function(block) {\n    return block.clone[block.clone.length - 1];\n  };\n\n\n  return {\n    restrict: 'A',\n    multiElement: true,\n    transclude: 'element',\n    priority: 1000,\n    terminal: true,\n    $$tlb: true,\n    compile: function ngRepeatCompile($element, $attr) {\n      var expression = $attr.ngRepeat;\n      var ngRepeatEndComment = document.createComment(' end ngRepeat: ' + expression + ' ');\n\n      var match = expression.match(/^\\s*([\\s\\S]+?)\\s+in\\s+([\\s\\S]+?)(?:\\s+as\\s+([\\s\\S]+?))?(?:\\s+track\\s+by\\s+([\\s\\S]+?))?\\s*$/);\n\n      if (!match) {\n        throw ngRepeatMinErr('iexp', \"Expected expression in form of '_item_ in _collection_[ track by _id_]' but got '{0}'.\",\n            expression);\n      }\n\n      var lhs = match[1];\n      var rhs = match[2];\n      var aliasAs = match[3];\n      var trackByExp = match[4];\n\n      match = lhs.match(/^(?:(\\s*[\\$\\w]+)|\\(\\s*([\\$\\w]+)\\s*,\\s*([\\$\\w]+)\\s*\\))$/);\n\n      if (!match) {\n        throw ngRepeatMinErr('iidexp', \"'_item_' in '_item_ in _collection_' should be an identifier or '(_key_, _value_)' expression, but got '{0}'.\",\n            lhs);\n      }\n      var valueIdentifier = match[3] || match[1];\n      var keyIdentifier = match[2];\n\n      if (aliasAs && (!/^[$a-zA-Z_][$a-zA-Z0-9_]*$/.test(aliasAs) ||\n          /^(null|undefined|this|\\$index|\\$first|\\$middle|\\$last|\\$even|\\$odd|\\$parent|\\$root|\\$id)$/.test(aliasAs))) {\n        throw ngRepeatMinErr('badident', \"alias '{0}' is invalid --- must be a valid JS identifier which is not a reserved name.\",\n          aliasAs);\n      }\n\n      var trackByExpGetter, trackByIdExpFn, trackByIdArrayFn, trackByIdObjFn;\n      var hashFnLocals = {$id: hashKey};\n\n      if (trackByExp) {\n        trackByExpGetter = $parse(trackByExp);\n      } else {\n        trackByIdArrayFn = function(key, value) {\n          return hashKey(value);\n        };\n        trackByIdObjFn = function(key) {\n          return key;\n        };\n      }\n\n      return function ngRepeatLink($scope, $element, $attr, ctrl, $transclude) {\n\n        if (trackByExpGetter) {\n          trackByIdExpFn = function(key, value, index) {\n            // assign key, value, and $index to the locals so that they can be used in hash functions\n            if (keyIdentifier) hashFnLocals[keyIdentifier] = key;\n            hashFnLocals[valueIdentifier] = value;\n            hashFnLocals.$index = index;\n            return trackByExpGetter($scope, hashFnLocals);\n          };\n        }\n\n        // Store a list of elements from previous run. This is a hash where key is the item from the\n        // iterator, and the value is objects with following properties.\n        //   - scope: bound scope\n        //   - element: previous element.\n        //   - index: position\n        //\n        // We are using no-proto object so that we don't need to guard against inherited props via\n        // hasOwnProperty.\n        var lastBlockMap = createMap();\n\n        //watch props\n        $scope.$watchCollection(rhs, function ngRepeatAction(collection) {\n          var index, length,\n              previousNode = $element[0],     // node that cloned nodes should be inserted after\n                                              // initialized to the comment node anchor\n              nextNode,\n              // Same as lastBlockMap but it has the current state. It will become the\n              // lastBlockMap on the next iteration.\n              nextBlockMap = createMap(),\n              collectionLength,\n              key, value, // key/value of iteration\n              trackById,\n              trackByIdFn,\n              collectionKeys,\n              block,       // last object information {scope, element, id}\n              nextBlockOrder,\n              elementsToRemove;\n\n          if (aliasAs) {\n            $scope[aliasAs] = collection;\n          }\n\n          if (isArrayLike(collection)) {\n            collectionKeys = collection;\n            trackByIdFn = trackByIdExpFn || trackByIdArrayFn;\n          } else {\n            trackByIdFn = trackByIdExpFn || trackByIdObjFn;\n            // if object, extract keys, sort them and use to determine order of iteration over obj props\n            collectionKeys = [];\n            for (var itemKey in collection) {\n              if (collection.hasOwnProperty(itemKey) && itemKey.charAt(0) != '$') {\n                collectionKeys.push(itemKey);\n              }\n            }\n            collectionKeys.sort();\n          }\n\n          collectionLength = collectionKeys.length;\n          nextBlockOrder = new Array(collectionLength);\n\n          // locate existing items\n          for (index = 0; index < collectionLength; index++) {\n            key = (collection === collectionKeys) ? index : collectionKeys[index];\n            value = collection[key];\n            trackById = trackByIdFn(key, value, index);\n            if (lastBlockMap[trackById]) {\n              // found previously seen block\n              block = lastBlockMap[trackById];\n              delete lastBlockMap[trackById];\n              nextBlockMap[trackById] = block;\n              nextBlockOrder[index] = block;\n            } else if (nextBlockMap[trackById]) {\n              // if collision detected. restore lastBlockMap and throw an error\n              forEach(nextBlockOrder, function(block) {\n                if (block && block.scope) lastBlockMap[block.id] = block;\n              });\n              throw ngRepeatMinErr('dupes',\n                  \"Duplicates in a repeater are not allowed. Use 'track by' expression to specify unique keys. Repeater: {0}, Duplicate key: {1}, Duplicate value: {2}\",\n                  expression, trackById, value);\n            } else {\n              // new never before seen block\n              nextBlockOrder[index] = {id: trackById, scope: undefined, clone: undefined};\n              nextBlockMap[trackById] = true;\n            }\n          }\n\n          // remove leftover items\n          for (var blockKey in lastBlockMap) {\n            block = lastBlockMap[blockKey];\n            elementsToRemove = getBlockNodes(block.clone);\n            $animate.leave(elementsToRemove);\n            if (elementsToRemove[0].parentNode) {\n              // if the element was not removed yet because of pending animation, mark it as deleted\n              // so that we can ignore it later\n              for (index = 0, length = elementsToRemove.length; index < length; index++) {\n                elementsToRemove[index][NG_REMOVED] = true;\n              }\n            }\n            block.scope.$destroy();\n          }\n\n          // we are not using forEach for perf reasons (trying to avoid #call)\n          for (index = 0; index < collectionLength; index++) {\n            key = (collection === collectionKeys) ? index : collectionKeys[index];\n            value = collection[key];\n            block = nextBlockOrder[index];\n\n            if (block.scope) {\n              // if we have already seen this object, then we need to reuse the\n              // associated scope/element\n\n              nextNode = previousNode;\n\n              // skip nodes that are already pending removal via leave animation\n              do {\n                nextNode = nextNode.nextSibling;\n              } while (nextNode && nextNode[NG_REMOVED]);\n\n              if (getBlockStart(block) != nextNode) {\n                // existing item which got moved\n                $animate.move(getBlockNodes(block.clone), null, jqLite(previousNode));\n              }\n              previousNode = getBlockEnd(block);\n              updateScope(block.scope, index, valueIdentifier, value, keyIdentifier, key, collectionLength);\n            } else {\n              // new item which we don't know about\n              $transclude(function ngRepeatTransclude(clone, scope) {\n                block.scope = scope;\n                // http://jsperf.com/clone-vs-createcomment\n                var endNode = ngRepeatEndComment.cloneNode(false);\n                clone[clone.length++] = endNode;\n\n                // TODO(perf): support naked previousNode in `enter` to avoid creation of jqLite wrapper?\n                $animate.enter(clone, null, jqLite(previousNode));\n                previousNode = endNode;\n                // Note: We only need the first/last node of the cloned nodes.\n                // However, we need to keep the reference to the jqlite wrapper as it might be changed later\n                // by a directive with templateUrl when its template arrives.\n                block.clone = clone;\n                nextBlockMap[block.id] = block;\n                updateScope(block.scope, index, valueIdentifier, value, keyIdentifier, key, collectionLength);\n              });\n            }\n          }\n          lastBlockMap = nextBlockMap;\n        });\n      };\n    }\n  };\n}];\n\nvar NG_HIDE_CLASS = 'ng-hide';\nvar NG_HIDE_IN_PROGRESS_CLASS = 'ng-hide-animate';\n/**\n * @ngdoc directive\n * @name ngShow\n *\n * @description\n * The `ngShow` directive shows or hides the given HTML element based on the expression\n * provided to the `ngShow` attribute. The element is shown or hidden by removing or adding\n * the `.ng-hide` CSS class onto the element. The `.ng-hide` CSS class is predefined\n * in AngularJS and sets the display style to none (using an !important flag).\n * For CSP mode please add `angular-csp.css` to your html file (see {@link ng.directive:ngCsp ngCsp}).\n *\n * ```html\n * <!-- when $scope.myValue is truthy (element is visible) -->\n * <div ng-show=\"myValue\"></div>\n *\n * <!-- when $scope.myValue is falsy (element is hidden) -->\n * <div ng-show=\"myValue\" class=\"ng-hide\"></div>\n * ```\n *\n * When the `ngShow` expression evaluates to a falsy value then the `.ng-hide` CSS class is added to the class\n * attribute on the element causing it to become hidden. When truthy, the `.ng-hide` CSS class is removed\n * from the element causing the element not to appear hidden.\n *\n * ## Why is !important used?\n *\n * You may be wondering why !important is used for the `.ng-hide` CSS class. This is because the `.ng-hide` selector\n * can be easily overridden by heavier selectors. For example, something as simple\n * as changing the display style on a HTML list item would make hidden elements appear visible.\n * This also becomes a bigger issue when dealing with CSS frameworks.\n *\n * By using !important, the show and hide behavior will work as expected despite any clash between CSS selector\n * specificity (when !important isn't used with any conflicting styles). If a developer chooses to override the\n * styling to change how to hide an element then it is just a matter of using !important in their own CSS code.\n *\n * ### Overriding `.ng-hide`\n *\n * By default, the `.ng-hide` class will style the element with `display: none!important`. If you wish to change\n * the hide behavior with ngShow/ngHide then this can be achieved by restating the styles for the `.ng-hide`\n * class CSS. Note that the selector that needs to be used is actually `.ng-hide:not(.ng-hide-animate)` to cope\n * with extra animation classes that can be added.\n *\n * ```css\n * .ng-hide:not(.ng-hide-animate) {\n *   /&#42; this is just another form of hiding an element &#42;/\n *   display: block!important;\n *   position: absolute;\n *   top: -9999px;\n *   left: -9999px;\n * }\n * ```\n *\n * By default you don't need to override in CSS anything and the animations will work around the display style.\n *\n * ## A note about animations with `ngShow`\n *\n * Animations in ngShow/ngHide work with the show and hide events that are triggered when the directive expression\n * is true and false. This system works like the animation system present with ngClass except that\n * you must also include the !important flag to override the display property\n * so that you can perform an animation when the element is hidden during the time of the animation.\n *\n * ```css\n * //\n * //a working example can be found at the bottom of this page\n * //\n * .my-element.ng-hide-add, .my-element.ng-hide-remove {\n *   /&#42; this is required as of 1.3x to properly\n *      apply all styling in a show/hide animation &#42;/\n *   transition: 0s linear all;\n * }\n *\n * .my-element.ng-hide-add-active,\n * .my-element.ng-hide-remove-active {\n *   /&#42; the transition is defined in the active class &#42;/\n *   transition: 1s linear all;\n * }\n *\n * .my-element.ng-hide-add { ... }\n * .my-element.ng-hide-add.ng-hide-add-active { ... }\n * .my-element.ng-hide-remove { ... }\n * .my-element.ng-hide-remove.ng-hide-remove-active { ... }\n * ```\n *\n * Keep in mind that, as of AngularJS version 1.3.0-beta.11, there is no need to change the display\n * property to block during animation states--ngAnimate will handle the style toggling automatically for you.\n *\n * @animations\n * addClass: `.ng-hide` - happens after the `ngShow` expression evaluates to a truthy value and the just before contents are set to visible\n * removeClass: `.ng-hide` - happens after the `ngShow` expression evaluates to a non truthy value and just before the contents are set to hidden\n *\n * @element ANY\n * @param {expression} ngShow If the {@link guide/expression expression} is truthy\n *     then the element is shown or hidden respectively.\n *\n * @example\n  <example module=\"ngAnimate\" deps=\"angular-animate.js\" animations=\"true\">\n    <file name=\"index.html\">\n      Click me: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n      <div>\n        Show:\n        <div class=\"check-element animate-show\" ng-show=\"checked\">\n          <span class=\"glyphicon glyphicon-thumbs-up\"></span> I show up when your checkbox is checked.\n        </div>\n      </div>\n      <div>\n        Hide:\n        <div class=\"check-element animate-show\" ng-hide=\"checked\">\n          <span class=\"glyphicon glyphicon-thumbs-down\"></span> I hide when your checkbox is checked.\n        </div>\n      </div>\n    </file>\n    <file name=\"glyphicons.css\">\n      @import url(../../components/bootstrap-3.1.1/css/bootstrap.css);\n    </file>\n    <file name=\"animations.css\">\n      .animate-show {\n        line-height: 20px;\n        opacity: 1;\n        padding: 10px;\n        border: 1px solid black;\n        background: white;\n      }\n\n      .animate-show.ng-hide-add.ng-hide-add-active,\n      .animate-show.ng-hide-remove.ng-hide-remove-active {\n        -webkit-transition: all linear 0.5s;\n        transition: all linear 0.5s;\n      }\n\n      .animate-show.ng-hide {\n        line-height: 0;\n        opacity: 0;\n        padding: 0 10px;\n      }\n\n      .check-element {\n        padding: 10px;\n        border: 1px solid black;\n        background: white;\n      }\n    </file>\n    <file name=\"protractor.js\" type=\"protractor\">\n      var thumbsUp = element(by.css('span.glyphicon-thumbs-up'));\n      var thumbsDown = element(by.css('span.glyphicon-thumbs-down'));\n\n      it('should check ng-show / ng-hide', function() {\n        expect(thumbsUp.isDisplayed()).toBeFalsy();\n        expect(thumbsDown.isDisplayed()).toBeTruthy();\n\n        element(by.model('checked')).click();\n\n        expect(thumbsUp.isDisplayed()).toBeTruthy();\n        expect(thumbsDown.isDisplayed()).toBeFalsy();\n      });\n    </file>\n  </example>\n */\nvar ngShowDirective = ['$animate', function($animate) {\n  return {\n    restrict: 'A',\n    multiElement: true,\n    link: function(scope, element, attr) {\n      scope.$watch(attr.ngShow, function ngShowWatchAction(value) {\n        // we're adding a temporary, animation-specific class for ng-hide since this way\n        // we can control when the element is actually displayed on screen without having\n        // to have a global/greedy CSS selector that breaks when other animations are run.\n        // Read: https://github.com/angular/angular.js/issues/9103#issuecomment-58335845\n        $animate[value ? 'removeClass' : 'addClass'](element, NG_HIDE_CLASS, {\n          tempClasses: NG_HIDE_IN_PROGRESS_CLASS\n        });\n      });\n    }\n  };\n}];\n\n\n/**\n * @ngdoc directive\n * @name ngHide\n *\n * @description\n * The `ngHide` directive shows or hides the given HTML element based on the expression\n * provided to the `ngHide` attribute. The element is shown or hidden by removing or adding\n * the `ng-hide` CSS class onto the element. The `.ng-hide` CSS class is predefined\n * in AngularJS and sets the display style to none (using an !important flag).\n * For CSP mode please add `angular-csp.css` to your html file (see {@link ng.directive:ngCsp ngCsp}).\n *\n * ```html\n * <!-- when $scope.myValue is truthy (element is hidden) -->\n * <div ng-hide=\"myValue\" class=\"ng-hide\"></div>\n *\n * <!-- when $scope.myValue is falsy (element is visible) -->\n * <div ng-hide=\"myValue\"></div>\n * ```\n *\n * When the `ngHide` expression evaluates to a truthy value then the `.ng-hide` CSS class is added to the class\n * attribute on the element causing it to become hidden. When falsy, the `.ng-hide` CSS class is removed\n * from the element causing the element not to appear hidden.\n *\n * ## Why is !important used?\n *\n * You may be wondering why !important is used for the `.ng-hide` CSS class. This is because the `.ng-hide` selector\n * can be easily overridden by heavier selectors. For example, something as simple\n * as changing the display style on a HTML list item would make hidden elements appear visible.\n * This also becomes a bigger issue when dealing with CSS frameworks.\n *\n * By using !important, the show and hide behavior will work as expected despite any clash between CSS selector\n * specificity (when !important isn't used with any conflicting styles). If a developer chooses to override the\n * styling to change how to hide an element then it is just a matter of using !important in their own CSS code.\n *\n * ### Overriding `.ng-hide`\n *\n * By default, the `.ng-hide` class will style the element with `display: none!important`. If you wish to change\n * the hide behavior with ngShow/ngHide then this can be achieved by restating the styles for the `.ng-hide`\n * class in CSS:\n *\n * ```css\n * .ng-hide {\n *   /&#42; this is just another form of hiding an element &#42;/\n *   display: block!important;\n *   position: absolute;\n *   top: -9999px;\n *   left: -9999px;\n * }\n * ```\n *\n * By default you don't need to override in CSS anything and the animations will work around the display style.\n *\n * ## A note about animations with `ngHide`\n *\n * Animations in ngShow/ngHide work with the show and hide events that are triggered when the directive expression\n * is true and false. This system works like the animation system present with ngClass, except that the `.ng-hide`\n * CSS class is added and removed for you instead of your own CSS class.\n *\n * ```css\n * //\n * //a working example can be found at the bottom of this page\n * //\n * .my-element.ng-hide-add, .my-element.ng-hide-remove {\n *   transition: 0.5s linear all;\n * }\n *\n * .my-element.ng-hide-add { ... }\n * .my-element.ng-hide-add.ng-hide-add-active { ... }\n * .my-element.ng-hide-remove { ... }\n * .my-element.ng-hide-remove.ng-hide-remove-active { ... }\n * ```\n *\n * Keep in mind that, as of AngularJS version 1.3.0-beta.11, there is no need to change the display\n * property to block during animation states--ngAnimate will handle the style toggling automatically for you.\n *\n * @animations\n * removeClass: `.ng-hide` - happens after the `ngHide` expression evaluates to a truthy value and just before the contents are set to hidden\n * addClass: `.ng-hide` - happens after the `ngHide` expression evaluates to a non truthy value and just before the contents are set to visible\n *\n * @element ANY\n * @param {expression} ngHide If the {@link guide/expression expression} is truthy then\n *     the element is shown or hidden respectively.\n *\n * @example\n  <example module=\"ngAnimate\" deps=\"angular-animate.js\" animations=\"true\">\n    <file name=\"index.html\">\n      Click me: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n      <div>\n        Show:\n        <div class=\"check-element animate-hide\" ng-show=\"checked\">\n          <span class=\"glyphicon glyphicon-thumbs-up\"></span> I show up when your checkbox is checked.\n        </div>\n      </div>\n      <div>\n        Hide:\n        <div class=\"check-element animate-hide\" ng-hide=\"checked\">\n          <span class=\"glyphicon glyphicon-thumbs-down\"></span> I hide when your checkbox is checked.\n        </div>\n      </div>\n    </file>\n    <file name=\"glyphicons.css\">\n      @import url(../../components/bootstrap-3.1.1/css/bootstrap.css);\n    </file>\n    <file name=\"animations.css\">\n      .animate-hide {\n        -webkit-transition: all linear 0.5s;\n        transition: all linear 0.5s;\n        line-height: 20px;\n        opacity: 1;\n        padding: 10px;\n        border: 1px solid black;\n        background: white;\n      }\n\n      .animate-hide.ng-hide {\n        line-height: 0;\n        opacity: 0;\n        padding: 0 10px;\n      }\n\n      .check-element {\n        padding: 10px;\n        border: 1px solid black;\n        background: white;\n      }\n    </file>\n    <file name=\"protractor.js\" type=\"protractor\">\n      var thumbsUp = element(by.css('span.glyphicon-thumbs-up'));\n      var thumbsDown = element(by.css('span.glyphicon-thumbs-down'));\n\n      it('should check ng-show / ng-hide', function() {\n        expect(thumbsUp.isDisplayed()).toBeFalsy();\n        expect(thumbsDown.isDisplayed()).toBeTruthy();\n\n        element(by.model('checked')).click();\n\n        expect(thumbsUp.isDisplayed()).toBeTruthy();\n        expect(thumbsDown.isDisplayed()).toBeFalsy();\n      });\n    </file>\n  </example>\n */\nvar ngHideDirective = ['$animate', function($animate) {\n  return {\n    restrict: 'A',\n    multiElement: true,\n    link: function(scope, element, attr) {\n      scope.$watch(attr.ngHide, function ngHideWatchAction(value) {\n        // The comment inside of the ngShowDirective explains why we add and\n        // remove a temporary class for the show/hide animation\n        $animate[value ? 'addClass' : 'removeClass'](element,NG_HIDE_CLASS, {\n          tempClasses: NG_HIDE_IN_PROGRESS_CLASS\n        });\n      });\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ngStyle\n * @restrict AC\n *\n * @description\n * The `ngStyle` directive allows you to set CSS style on an HTML element conditionally.\n *\n * @element ANY\n * @param {expression} ngStyle\n *\n * {@link guide/expression Expression} which evals to an\n * object whose keys are CSS style names and values are corresponding values for those CSS\n * keys.\n *\n * Since some CSS style names are not valid keys for an object, they must be quoted.\n * See the 'background-color' style in the example below.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <input type=\"button\" value=\"set color\" ng-click=\"myStyle={color:'red'}\">\n        <input type=\"button\" value=\"set background\" ng-click=\"myStyle={'background-color':'blue'}\">\n        <input type=\"button\" value=\"clear\" ng-click=\"myStyle={}\">\n        <br/>\n        <span ng-style=\"myStyle\">Sample Text</span>\n        <pre>myStyle={{myStyle}}</pre>\n     </file>\n     <file name=\"style.css\">\n       span {\n         color: black;\n       }\n     </file>\n     <file name=\"protractor.js\" type=\"protractor\">\n       var colorSpan = element(by.css('span'));\n\n       it('should check ng-style', function() {\n         expect(colorSpan.getCssValue('color')).toBe('rgba(0, 0, 0, 1)');\n         element(by.css('input[value=\\'set color\\']')).click();\n         expect(colorSpan.getCssValue('color')).toBe('rgba(255, 0, 0, 1)');\n         element(by.css('input[value=clear]')).click();\n         expect(colorSpan.getCssValue('color')).toBe('rgba(0, 0, 0, 1)');\n       });\n     </file>\n   </example>\n */\nvar ngStyleDirective = ngDirective(function(scope, element, attr) {\n  scope.$watchCollection(attr.ngStyle, function ngStyleWatchAction(newStyles, oldStyles) {\n    if (oldStyles && (newStyles !== oldStyles)) {\n      forEach(oldStyles, function(val, style) { element.css(style, '');});\n    }\n    if (newStyles) element.css(newStyles);\n  });\n});\n\n/**\n * @ngdoc directive\n * @name ngSwitch\n * @restrict EA\n *\n * @description\n * The `ngSwitch` directive is used to conditionally swap DOM structure on your template based on a scope expression.\n * Elements within `ngSwitch` but without `ngSwitchWhen` or `ngSwitchDefault` directives will be preserved at the location\n * as specified in the template.\n *\n * The directive itself works similar to ngInclude, however, instead of downloading template code (or loading it\n * from the template cache), `ngSwitch` simply chooses one of the nested elements and makes it visible based on which element\n * matches the value obtained from the evaluated expression. In other words, you define a container element\n * (where you place the directive), place an expression on the **`on=\"...\"` attribute**\n * (or the **`ng-switch=\"...\"` attribute**), define any inner elements inside of the directive and place\n * a when attribute per element. The when attribute is used to inform ngSwitch which element to display when the on\n * expression is evaluated. If a matching expression is not found via a when attribute then an element with the default\n * attribute is displayed.\n *\n * <div class=\"alert alert-info\">\n * Be aware that the attribute values to match against cannot be expressions. They are interpreted\n * as literal string values to match against.\n * For example, **`ng-switch-when=\"someVal\"`** will match against the string `\"someVal\"` not against the\n * value of the expression `$scope.someVal`.\n * </div>\n\n * @animations\n * enter - happens after the ngSwitch contents change and the matched child element is placed inside the container\n * leave - happens just after the ngSwitch contents change and just before the former contents are removed from the DOM\n *\n * @usage\n *\n * ```\n * <ANY ng-switch=\"expression\">\n *   <ANY ng-switch-when=\"matchValue1\">...</ANY>\n *   <ANY ng-switch-when=\"matchValue2\">...</ANY>\n *   <ANY ng-switch-default>...</ANY>\n * </ANY>\n * ```\n *\n *\n * @scope\n * @priority 1200\n * @param {*} ngSwitch|on expression to match against <tt>ng-switch-when</tt>.\n * On child elements add:\n *\n * * `ngSwitchWhen`: the case statement to match against. If match then this\n *   case will be displayed. If the same match appears multiple times, all the\n *   elements will be displayed.\n * * `ngSwitchDefault`: the default case when no other case match. If there\n *   are multiple default cases, all of them will be displayed when no other\n *   case match.\n *\n *\n * @example\n  <example module=\"switchExample\" deps=\"angular-animate.js\" animations=\"true\">\n    <file name=\"index.html\">\n      <div ng-controller=\"ExampleController\">\n        <select ng-model=\"selection\" ng-options=\"item for item in items\">\n        </select>\n        <tt>selection={{selection}}</tt>\n        <hr/>\n        <div class=\"animate-switch-container\"\n          ng-switch on=\"selection\">\n            <div class=\"animate-switch\" ng-switch-when=\"settings\">Settings Div</div>\n            <div class=\"animate-switch\" ng-switch-when=\"home\">Home Span</div>\n            <div class=\"animate-switch\" ng-switch-default>default</div>\n        </div>\n      </div>\n    </file>\n    <file name=\"script.js\">\n      angular.module('switchExample', ['ngAnimate'])\n        .controller('ExampleController', ['$scope', function($scope) {\n          $scope.items = ['settings', 'home', 'other'];\n          $scope.selection = $scope.items[0];\n        }]);\n    </file>\n    <file name=\"animations.css\">\n      .animate-switch-container {\n        position:relative;\n        background:white;\n        border:1px solid black;\n        height:40px;\n        overflow:hidden;\n      }\n\n      .animate-switch {\n        padding:10px;\n      }\n\n      .animate-switch.ng-animate {\n        -webkit-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;\n        transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;\n\n        position:absolute;\n        top:0;\n        left:0;\n        right:0;\n        bottom:0;\n      }\n\n      .animate-switch.ng-leave.ng-leave-active,\n      .animate-switch.ng-enter {\n        top:-50px;\n      }\n      .animate-switch.ng-leave,\n      .animate-switch.ng-enter.ng-enter-active {\n        top:0;\n      }\n    </file>\n    <file name=\"protractor.js\" type=\"protractor\">\n      var switchElem = element(by.css('[ng-switch]'));\n      var select = element(by.model('selection'));\n\n      it('should start in settings', function() {\n        expect(switchElem.getText()).toMatch(/Settings Div/);\n      });\n      it('should change to home', function() {\n        select.all(by.css('option')).get(1).click();\n        expect(switchElem.getText()).toMatch(/Home Span/);\n      });\n      it('should select default', function() {\n        select.all(by.css('option')).get(2).click();\n        expect(switchElem.getText()).toMatch(/default/);\n      });\n    </file>\n  </example>\n */\nvar ngSwitchDirective = ['$animate', function($animate) {\n  return {\n    restrict: 'EA',\n    require: 'ngSwitch',\n\n    // asks for $scope to fool the BC controller module\n    controller: ['$scope', function ngSwitchController() {\n     this.cases = {};\n    }],\n    link: function(scope, element, attr, ngSwitchController) {\n      var watchExpr = attr.ngSwitch || attr.on,\n          selectedTranscludes = [],\n          selectedElements = [],\n          previousLeaveAnimations = [],\n          selectedScopes = [];\n\n      var spliceFactory = function(array, index) {\n          return function() { array.splice(index, 1); };\n      };\n\n      scope.$watch(watchExpr, function ngSwitchWatchAction(value) {\n        var i, ii;\n        for (i = 0, ii = previousLeaveAnimations.length; i < ii; ++i) {\n          $animate.cancel(previousLeaveAnimations[i]);\n        }\n        previousLeaveAnimations.length = 0;\n\n        for (i = 0, ii = selectedScopes.length; i < ii; ++i) {\n          var selected = getBlockNodes(selectedElements[i].clone);\n          selectedScopes[i].$destroy();\n          var promise = previousLeaveAnimations[i] = $animate.leave(selected);\n          promise.then(spliceFactory(previousLeaveAnimations, i));\n        }\n\n        selectedElements.length = 0;\n        selectedScopes.length = 0;\n\n        if ((selectedTranscludes = ngSwitchController.cases['!' + value] || ngSwitchController.cases['?'])) {\n          forEach(selectedTranscludes, function(selectedTransclude) {\n            selectedTransclude.transclude(function(caseElement, selectedScope) {\n              selectedScopes.push(selectedScope);\n              var anchor = selectedTransclude.element;\n              caseElement[caseElement.length++] = document.createComment(' end ngSwitchWhen: ');\n              var block = { clone: caseElement };\n\n              selectedElements.push(block);\n              $animate.enter(caseElement, anchor.parent(), anchor);\n            });\n          });\n        }\n      });\n    }\n  };\n}];\n\nvar ngSwitchWhenDirective = ngDirective({\n  transclude: 'element',\n  priority: 1200,\n  require: '^ngSwitch',\n  multiElement: true,\n  link: function(scope, element, attrs, ctrl, $transclude) {\n    ctrl.cases['!' + attrs.ngSwitchWhen] = (ctrl.cases['!' + attrs.ngSwitchWhen] || []);\n    ctrl.cases['!' + attrs.ngSwitchWhen].push({ transclude: $transclude, element: element });\n  }\n});\n\nvar ngSwitchDefaultDirective = ngDirective({\n  transclude: 'element',\n  priority: 1200,\n  require: '^ngSwitch',\n  multiElement: true,\n  link: function(scope, element, attr, ctrl, $transclude) {\n    ctrl.cases['?'] = (ctrl.cases['?'] || []);\n    ctrl.cases['?'].push({ transclude: $transclude, element: element });\n   }\n});\n\n/**\n * @ngdoc directive\n * @name ngTransclude\n * @restrict EAC\n *\n * @description\n * Directive that marks the insertion point for the transcluded DOM of the nearest parent directive that uses transclusion.\n *\n * Any existing content of the element that this directive is placed on will be removed before the transcluded content is inserted.\n *\n * @element ANY\n *\n * @example\n   <example module=\"transcludeExample\">\n     <file name=\"index.html\">\n       <script>\n         angular.module('transcludeExample', [])\n          .directive('pane', function(){\n             return {\n               restrict: 'E',\n               transclude: true,\n               scope: { title:'@' },\n               template: '<div style=\"border: 1px solid black;\">' +\n                           '<div style=\"background-color: gray\">{{title}}</div>' +\n                           '<ng-transclude></ng-transclude>' +\n                         '</div>'\n             };\n         })\n         .controller('ExampleController', ['$scope', function($scope) {\n           $scope.title = 'Lorem Ipsum';\n           $scope.text = 'Neque porro quisquam est qui dolorem ipsum quia dolor...';\n         }]);\n       </script>\n       <div ng-controller=\"ExampleController\">\n         <input ng-model=\"title\"> <br/>\n         <textarea ng-model=\"text\"></textarea> <br/>\n         <pane title=\"{{title}}\">{{text}}</pane>\n       </div>\n     </file>\n     <file name=\"protractor.js\" type=\"protractor\">\n        it('should have transcluded', function() {\n          var titleElement = element(by.model('title'));\n          titleElement.clear();\n          titleElement.sendKeys('TITLE');\n          var textElement = element(by.model('text'));\n          textElement.clear();\n          textElement.sendKeys('TEXT');\n          expect(element(by.binding('title')).getText()).toEqual('TITLE');\n          expect(element(by.binding('text')).getText()).toEqual('TEXT');\n        });\n     </file>\n   </example>\n *\n */\nvar ngTranscludeDirective = ngDirective({\n  restrict: 'EAC',\n  link: function($scope, $element, $attrs, controller, $transclude) {\n    if (!$transclude) {\n      throw minErr('ngTransclude')('orphan',\n       'Illegal use of ngTransclude directive in the template! ' +\n       'No parent directive that requires a transclusion found. ' +\n       'Element: {0}',\n       startingTag($element));\n    }\n\n    $transclude(function(clone) {\n      $element.empty();\n      $element.append(clone);\n    });\n  }\n});\n\n/**\n * @ngdoc directive\n * @name script\n * @restrict E\n *\n * @description\n * Load the content of a `<script>` element into {@link ng.$templateCache `$templateCache`}, so that the\n * template can be used by {@link ng.directive:ngInclude `ngInclude`},\n * {@link ngRoute.directive:ngView `ngView`}, or {@link guide/directive directives}. The type of the\n * `<script>` element must be specified as `text/ng-template`, and a cache name for the template must be\n * assigned through the element's `id`, which can then be used as a directive's `templateUrl`.\n *\n * @param {string} type Must be set to `'text/ng-template'`.\n * @param {string} id Cache name of the template.\n *\n * @example\n  <example>\n    <file name=\"index.html\">\n      <script type=\"text/ng-template\" id=\"/tpl.html\">\n        Content of the template.\n      </script>\n\n      <a ng-click=\"currentTpl='/tpl.html'\" id=\"tpl-link\">Load inlined template</a>\n      <div id=\"tpl-content\" ng-include src=\"currentTpl\"></div>\n    </file>\n    <file name=\"protractor.js\" type=\"protractor\">\n      it('should load template defined inside script tag', function() {\n        element(by.css('#tpl-link')).click();\n        expect(element(by.css('#tpl-content')).getText()).toMatch(/Content of the template/);\n      });\n    </file>\n  </example>\n */\nvar scriptDirective = ['$templateCache', function($templateCache) {\n  return {\n    restrict: 'E',\n    terminal: true,\n    compile: function(element, attr) {\n      if (attr.type == 'text/ng-template') {\n        var templateUrl = attr.id,\n            text = element[0].text;\n\n        $templateCache.put(templateUrl, text);\n      }\n    }\n  };\n}];\n\nvar ngOptionsMinErr = minErr('ngOptions');\n/**\n * @ngdoc directive\n * @name select\n * @restrict E\n *\n * @description\n * HTML `SELECT` element with angular data-binding.\n *\n * # `ngOptions`\n *\n * The `ngOptions` attribute can be used to dynamically generate a list of `<option>`\n * elements for the `<select>` element using the array or object obtained by evaluating the\n * `ngOptions` comprehension expression.\n *\n * In many cases, `ngRepeat` can be used on `<option>` elements instead of `ngOptions` to achieve a\n * similar result. However, `ngOptions` provides some benefits such as reducing memory and\n * increasing speed by not creating a new scope for each repeated instance, as well as providing\n * more flexibility in how the `<select>`'s model is assigned via the `select` **`as`** part of the\n * comprehension expression. `ngOptions` should be used when the `<select>` model needs to be bound\n *  to a non-string value. This is because an option element can only be bound to string values at\n * present.\n *\n * When an item in the `<select>` menu is selected, the array element or object property\n * represented by the selected option will be bound to the model identified by the `ngModel`\n * directive.\n *\n * Optionally, a single hard-coded `<option>` element, with the value set to an empty string, can\n * be nested into the `<select>` element. This element will then represent the `null` or \"not selected\"\n * option. See example below for demonstration.\n *\n * <div class=\"alert alert-warning\">\n * **Note:** `ngModel` compares by reference, not value. This is important when binding to an\n * array of objects. See an example [in this jsfiddle](http://jsfiddle.net/qWzTb/).\n * </div>\n *\n * ## `select` **`as`**\n *\n * Using `select` **`as`** will bind the result of the `select` expression to the model, but\n * the value of the `<select>` and `<option>` html elements will be either the index (for array data sources)\n * or property name (for object data sources) of the value within the collection. If a **`track by`** expression\n * is used, the result of that expression will be set as the value of the `option` and `select` elements.\n *\n *\n * ### `select` **`as`** and **`track by`**\n *\n * <div class=\"alert alert-warning\">\n * Do not use `select` **`as`** and **`track by`** in the same expression. They are not designed to work together.\n * </div>\n *\n * Consider the following example:\n *\n * ```html\n * <select ng-options=\"item.subItem as item.label for item in values track by item.id\" ng-model=\"selected\">\n * ```\n *\n * ```js\n * $scope.values = [{\n *   id: 1,\n *   label: 'aLabel',\n *   subItem: { name: 'aSubItem' }\n * }, {\n *   id: 2,\n *   label: 'bLabel',\n *   subItem: { name: 'bSubItem' }\n * }];\n *\n * $scope.selected = { name: 'aSubItem' };\n * ```\n *\n * With the purpose of preserving the selection, the **`track by`** expression is always applied to the element\n * of the data source (to `item` in this example). To calculate whether an element is selected, we do the\n * following:\n *\n * 1. Apply **`track by`** to the elements in the array. In the example: `[1, 2]`\n * 2. Apply **`track by`** to the already selected value in `ngModel`.\n *    In the example: this is not possible as **`track by`** refers to `item.id`, but the selected\n *    value from `ngModel` is `{name: 'aSubItem'}`, so the **`track by`** expression is applied to\n *    a wrong object, the selected element can't be found, `<select>` is always reset to the \"not\n *    selected\" option.\n *\n *\n * @param {string} ngModel Assignable angular expression to data-bind to.\n * @param {string=} name Property name of the form under which the control is published.\n * @param {string=} required The control is considered valid only if value is entered.\n * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n *    `required` when you want to data-bind to the `required` attribute.\n * @param {comprehension_expression=} ngOptions in one of the following forms:\n *\n *   * for array data sources:\n *     * `label` **`for`** `value` **`in`** `array`\n *     * `select` **`as`** `label` **`for`** `value` **`in`** `array`\n *     * `label` **`group by`** `group` **`for`** `value` **`in`** `array`\n *     * `label` **`group by`** `group` **`for`** `value` **`in`** `array` **`track by`** `trackexpr`\n *     * `label` **`for`** `value` **`in`** `array` | orderBy:`orderexpr` **`track by`** `trackexpr`\n *        (for including a filter with `track by`)\n *   * for object data sources:\n *     * `label` **`for (`**`key` **`,`** `value`**`) in`** `object`\n *     * `select` **`as`** `label` **`for (`**`key` **`,`** `value`**`) in`** `object`\n *     * `label` **`group by`** `group` **`for (`**`key`**`,`** `value`**`) in`** `object`\n *     * `select` **`as`** `label` **`group by`** `group`\n *         **`for` `(`**`key`**`,`** `value`**`) in`** `object`\n *\n * Where:\n *\n *   * `array` / `object`: an expression which evaluates to an array / object to iterate over.\n *   * `value`: local variable which will refer to each item in the `array` or each property value\n *      of `object` during iteration.\n *   * `key`: local variable which will refer to a property name in `object` during iteration.\n *   * `label`: The result of this expression will be the label for `<option>` element. The\n *     `expression` will most likely refer to the `value` variable (e.g. `value.propertyName`).\n *   * `select`: The result of this expression will be bound to the model of the parent `<select>`\n *      element. If not specified, `select` expression will default to `value`.\n *   * `group`: The result of this expression will be used to group options using the `<optgroup>`\n *      DOM element.\n *   * `trackexpr`: Used when working with an array of objects. The result of this expression will be\n *      used to identify the objects in the array. The `trackexpr` will most likely refer to the\n *     `value` variable (e.g. `value.propertyName`). With this the selection is preserved\n *      even when the options are recreated (e.g. reloaded from the server).\n *\n * @example\n    <example module=\"selectExample\">\n      <file name=\"index.html\">\n        <script>\n        angular.module('selectExample', [])\n          .controller('ExampleController', ['$scope', function($scope) {\n            $scope.colors = [\n              {name:'black', shade:'dark'},\n              {name:'white', shade:'light'},\n              {name:'red', shade:'dark'},\n              {name:'blue', shade:'dark'},\n              {name:'yellow', shade:'light'}\n            ];\n            $scope.myColor = $scope.colors[2]; // red\n          }]);\n        </script>\n        <div ng-controller=\"ExampleController\">\n          <ul>\n            <li ng-repeat=\"color in colors\">\n              Name: <input ng-model=\"color.name\">\n              [<a href ng-click=\"colors.splice($index, 1)\">X</a>]\n            </li>\n            <li>\n              [<a href ng-click=\"colors.push({})\">add</a>]\n            </li>\n          </ul>\n          <hr/>\n          Color (null not allowed):\n          <select ng-model=\"myColor\" ng-options=\"color.name for color in colors\"></select><br>\n\n          Color (null allowed):\n          <span  class=\"nullable\">\n            <select ng-model=\"myColor\" ng-options=\"color.name for color in colors\">\n              <option value=\"\">-- choose color --</option>\n            </select>\n          </span><br/>\n\n          Color grouped by shade:\n          <select ng-model=\"myColor\" ng-options=\"color.name group by color.shade for color in colors\">\n          </select><br/>\n\n\n          Select <a href ng-click=\"myColor = { name:'not in list', shade: 'other' }\">bogus</a>.<br>\n          <hr/>\n          Currently selected: {{ {selected_color:myColor} }}\n          <div style=\"border:solid 1px black; height:20px\"\n               ng-style=\"{'background-color':myColor.name}\">\n          </div>\n        </div>\n      </file>\n      <file name=\"protractor.js\" type=\"protractor\">\n         it('should check ng-options', function() {\n           expect(element(by.binding('{selected_color:myColor}')).getText()).toMatch('red');\n           element.all(by.model('myColor')).first().click();\n           element.all(by.css('select[ng-model=\"myColor\"] option')).first().click();\n           expect(element(by.binding('{selected_color:myColor}')).getText()).toMatch('black');\n           element(by.css('.nullable select[ng-model=\"myColor\"]')).click();\n           element.all(by.css('.nullable select[ng-model=\"myColor\"] option')).first().click();\n           expect(element(by.binding('{selected_color:myColor}')).getText()).toMatch('null');\n         });\n      </file>\n    </example>\n */\n\nvar ngOptionsDirective = valueFn({\n  restrict: 'A',\n  terminal: true\n});\n\n// jshint maxlen: false\nvar selectDirective = ['$compile', '$parse', function($compile,   $parse) {\n                         //000011111111110000000000022222222220000000000000000000003333333333000000000000004444444444444440000000005555555555555550000000666666666666666000000000000000777777777700000000000000000008888888888\n  var NG_OPTIONS_REGEXP = /^\\s*([\\s\\S]+?)(?:\\s+as\\s+([\\s\\S]+?))?(?:\\s+group\\s+by\\s+([\\s\\S]+?))?\\s+for\\s+(?:([\\$\\w][\\$\\w]*)|(?:\\(\\s*([\\$\\w][\\$\\w]*)\\s*,\\s*([\\$\\w][\\$\\w]*)\\s*\\)))\\s+in\\s+([\\s\\S]+?)(?:\\s+track\\s+by\\s+([\\s\\S]+?))?$/,\n      nullModelCtrl = {$setViewValue: noop};\n// jshint maxlen: 100\n\n  return {\n    restrict: 'E',\n    require: ['select', '?ngModel'],\n    controller: ['$element', '$scope', '$attrs', function($element, $scope, $attrs) {\n      var self = this,\n          optionsMap = {},\n          ngModelCtrl = nullModelCtrl,\n          nullOption,\n          unknownOption;\n\n\n      self.databound = $attrs.ngModel;\n\n\n      self.init = function(ngModelCtrl_, nullOption_, unknownOption_) {\n        ngModelCtrl = ngModelCtrl_;\n        nullOption = nullOption_;\n        unknownOption = unknownOption_;\n      };\n\n\n      self.addOption = function(value, element) {\n        assertNotHasOwnProperty(value, '\"option value\"');\n        optionsMap[value] = true;\n\n        if (ngModelCtrl.$viewValue == value) {\n          $element.val(value);\n          if (unknownOption.parent()) unknownOption.remove();\n        }\n        // Workaround for https://code.google.com/p/chromium/issues/detail?id=381459\n        // Adding an <option selected=\"selected\"> element to a <select required=\"required\"> should\n        // automatically select the new element\n        if (element && element[0].hasAttribute('selected')) {\n          element[0].selected = true;\n        }\n      };\n\n\n      self.removeOption = function(value) {\n        if (this.hasOption(value)) {\n          delete optionsMap[value];\n          if (ngModelCtrl.$viewValue === value) {\n            this.renderUnknownOption(value);\n          }\n        }\n      };\n\n\n      self.renderUnknownOption = function(val) {\n        var unknownVal = '? ' + hashKey(val) + ' ?';\n        unknownOption.val(unknownVal);\n        $element.prepend(unknownOption);\n        $element.val(unknownVal);\n        unknownOption.prop('selected', true); // needed for IE\n      };\n\n\n      self.hasOption = function(value) {\n        return optionsMap.hasOwnProperty(value);\n      };\n\n      $scope.$on('$destroy', function() {\n        // disable unknown option so that we don't do work when the whole select is being destroyed\n        self.renderUnknownOption = noop;\n      });\n    }],\n\n    link: function(scope, element, attr, ctrls) {\n      // if ngModel is not defined, we don't need to do anything\n      if (!ctrls[1]) return;\n\n      var selectCtrl = ctrls[0],\n          ngModelCtrl = ctrls[1],\n          multiple = attr.multiple,\n          optionsExp = attr.ngOptions,\n          nullOption = false, // if false, user will not be able to select it (used by ngOptions)\n          emptyOption,\n          renderScheduled = false,\n          // we can't just jqLite('<option>') since jqLite is not smart enough\n          // to create it in <select> and IE barfs otherwise.\n          optionTemplate = jqLite(document.createElement('option')),\n          optGroupTemplate =jqLite(document.createElement('optgroup')),\n          unknownOption = optionTemplate.clone();\n\n      // find \"null\" option\n      for (var i = 0, children = element.children(), ii = children.length; i < ii; i++) {\n        if (children[i].value === '') {\n          emptyOption = nullOption = children.eq(i);\n          break;\n        }\n      }\n\n      selectCtrl.init(ngModelCtrl, nullOption, unknownOption);\n\n      // required validator\n      if (multiple) {\n        ngModelCtrl.$isEmpty = function(value) {\n          return !value || value.length === 0;\n        };\n      }\n\n      if (optionsExp) setupAsOptions(scope, element, ngModelCtrl);\n      else if (multiple) setupAsMultiple(scope, element, ngModelCtrl);\n      else setupAsSingle(scope, element, ngModelCtrl, selectCtrl);\n\n\n      ////////////////////////////\n\n\n\n      function setupAsSingle(scope, selectElement, ngModelCtrl, selectCtrl) {\n        ngModelCtrl.$render = function() {\n          var viewValue = ngModelCtrl.$viewValue;\n\n          if (selectCtrl.hasOption(viewValue)) {\n            if (unknownOption.parent()) unknownOption.remove();\n            selectElement.val(viewValue);\n            if (viewValue === '') emptyOption.prop('selected', true); // to make IE9 happy\n          } else {\n            if (isUndefined(viewValue) && emptyOption) {\n              selectElement.val('');\n            } else {\n              selectCtrl.renderUnknownOption(viewValue);\n            }\n          }\n        };\n\n        selectElement.on('change', function() {\n          scope.$apply(function() {\n            if (unknownOption.parent()) unknownOption.remove();\n            ngModelCtrl.$setViewValue(selectElement.val());\n          });\n        });\n      }\n\n      function setupAsMultiple(scope, selectElement, ctrl) {\n        var lastView;\n        ctrl.$render = function() {\n          var items = new HashMap(ctrl.$viewValue);\n          forEach(selectElement.find('option'), function(option) {\n            option.selected = isDefined(items.get(option.value));\n          });\n        };\n\n        // we have to do it on each watch since ngModel watches reference, but\n        // we need to work of an array, so we need to see if anything was inserted/removed\n        scope.$watch(function selectMultipleWatch() {\n          if (!equals(lastView, ctrl.$viewValue)) {\n            lastView = shallowCopy(ctrl.$viewValue);\n            ctrl.$render();\n          }\n        });\n\n        selectElement.on('change', function() {\n          scope.$apply(function() {\n            var array = [];\n            forEach(selectElement.find('option'), function(option) {\n              if (option.selected) {\n                array.push(option.value);\n              }\n            });\n            ctrl.$setViewValue(array);\n          });\n        });\n      }\n\n      function setupAsOptions(scope, selectElement, ctrl) {\n        var match;\n\n        if (!(match = optionsExp.match(NG_OPTIONS_REGEXP))) {\n          throw ngOptionsMinErr('iexp',\n            \"Expected expression in form of \" +\n            \"'_select_ (as _label_)? for (_key_,)?_value_ in _collection_'\" +\n            \" but got '{0}'. Element: {1}\",\n            optionsExp, startingTag(selectElement));\n        }\n\n        var displayFn = $parse(match[2] || match[1]),\n            valueName = match[4] || match[6],\n            selectAs = / as /.test(match[0]) && match[1],\n            selectAsFn = selectAs ? $parse(selectAs) : null,\n            keyName = match[5],\n            groupByFn = $parse(match[3] || ''),\n            valueFn = $parse(match[2] ? match[1] : valueName),\n            valuesFn = $parse(match[7]),\n            track = match[8],\n            trackFn = track ? $parse(match[8]) : null,\n            trackKeysCache = {},\n            // This is an array of array of existing option groups in DOM.\n            // We try to reuse these if possible\n            // - optionGroupsCache[0] is the options with no option group\n            // - optionGroupsCache[?][0] is the parent: either the SELECT or OPTGROUP element\n            optionGroupsCache = [[{element: selectElement, label:''}]],\n            //re-usable object to represent option's locals\n            locals = {};\n\n        if (nullOption) {\n          // compile the element since there might be bindings in it\n          $compile(nullOption)(scope);\n\n          // remove the class, which is added automatically because we recompile the element and it\n          // becomes the compilation root\n          nullOption.removeClass('ng-scope');\n\n          // we need to remove it before calling selectElement.empty() because otherwise IE will\n          // remove the label from the element. wtf?\n          nullOption.remove();\n        }\n\n        // clear contents, we'll add what's needed based on the model\n        selectElement.empty();\n\n        selectElement.on('change', selectionChanged);\n\n        ctrl.$render = render;\n\n        scope.$watchCollection(valuesFn, scheduleRendering);\n        scope.$watchCollection(getLabels, scheduleRendering);\n\n        if (multiple) {\n          scope.$watchCollection(function() { return ctrl.$modelValue; }, scheduleRendering);\n        }\n\n        // ------------------------------------------------------------------ //\n\n        function callExpression(exprFn, key, value) {\n          locals[valueName] = value;\n          if (keyName) locals[keyName] = key;\n          return exprFn(scope, locals);\n        }\n\n        function selectionChanged() {\n          scope.$apply(function() {\n            var collection = valuesFn(scope) || [];\n            var viewValue;\n            if (multiple) {\n              viewValue = [];\n              forEach(selectElement.val(), function(selectedKey) {\n                  selectedKey = trackFn ? trackKeysCache[selectedKey] : selectedKey;\n                viewValue.push(getViewValue(selectedKey, collection[selectedKey]));\n              });\n            } else {\n              var selectedKey = trackFn ? trackKeysCache[selectElement.val()] : selectElement.val();\n              viewValue = getViewValue(selectedKey, collection[selectedKey]);\n            }\n            ctrl.$setViewValue(viewValue);\n            render();\n          });\n        }\n\n        function getViewValue(key, value) {\n          if (key === '?') {\n            return undefined;\n          } else if (key === '') {\n            return null;\n          } else {\n            var viewValueFn = selectAsFn ? selectAsFn : valueFn;\n            return callExpression(viewValueFn, key, value);\n          }\n        }\n\n        function getLabels() {\n          var values = valuesFn(scope);\n          var toDisplay;\n          if (values && isArray(values)) {\n            toDisplay = new Array(values.length);\n            for (var i = 0, ii = values.length; i < ii; i++) {\n              toDisplay[i] = callExpression(displayFn, i, values[i]);\n            }\n            return toDisplay;\n          } else if (values) {\n            // TODO: Add a test for this case\n            toDisplay = {};\n            for (var prop in values) {\n              if (values.hasOwnProperty(prop)) {\n                toDisplay[prop] = callExpression(displayFn, prop, values[prop]);\n              }\n            }\n          }\n          return toDisplay;\n        }\n\n        function createIsSelectedFn(viewValue) {\n          var selectedSet;\n          if (multiple) {\n            if (trackFn && isArray(viewValue)) {\n\n              selectedSet = new HashMap([]);\n              for (var trackIndex = 0; trackIndex < viewValue.length; trackIndex++) {\n                // tracking by key\n                selectedSet.put(callExpression(trackFn, null, viewValue[trackIndex]), true);\n              }\n            } else {\n              selectedSet = new HashMap(viewValue);\n            }\n          } else if (trackFn) {\n            viewValue = callExpression(trackFn, null, viewValue);\n          }\n\n          return function isSelected(key, value) {\n            var compareValueFn;\n            if (trackFn) {\n              compareValueFn = trackFn;\n            } else if (selectAsFn) {\n              compareValueFn = selectAsFn;\n            } else {\n              compareValueFn = valueFn;\n            }\n\n            if (multiple) {\n              return isDefined(selectedSet.remove(callExpression(compareValueFn, key, value)));\n            } else {\n              return viewValue === callExpression(compareValueFn, key, value);\n            }\n          };\n        }\n\n        function scheduleRendering() {\n          if (!renderScheduled) {\n            scope.$$postDigest(render);\n            renderScheduled = true;\n          }\n        }\n\n        /**\n         * A new labelMap is created with each render.\n         * This function is called for each existing option with added=false,\n         * and each new option with added=true.\n         * - Labels that are passed to this method twice,\n         * (once with added=true and once with added=false) will end up with a value of 0, and\n         * will cause no change to happen to the corresponding option.\n         * - Labels that are passed to this method only once with added=false will end up with a\n         * value of -1 and will eventually be passed to selectCtrl.removeOption()\n         * - Labels that are passed to this method only once with added=true will end up with a\n         * value of 1 and will eventually be passed to selectCtrl.addOption()\n        */\n        function updateLabelMap(labelMap, label, added) {\n          labelMap[label] = labelMap[label] || 0;\n          labelMap[label] += (added ? 1 : -1);\n        }\n\n        function render() {\n          renderScheduled = false;\n\n          // Temporary location for the option groups before we render them\n          var optionGroups = {'':[]},\n              optionGroupNames = [''],\n              optionGroupName,\n              optionGroup,\n              option,\n              existingParent, existingOptions, existingOption,\n              viewValue = ctrl.$viewValue,\n              values = valuesFn(scope) || [],\n              keys = keyName ? sortedKeys(values) : values,\n              key,\n              value,\n              groupLength, length,\n              groupIndex, index,\n              labelMap = {},\n              selected,\n              isSelected = createIsSelectedFn(viewValue),\n              anySelected = false,\n              lastElement,\n              element,\n              label,\n              optionId;\n\n          trackKeysCache = {};\n\n          // We now build up the list of options we need (we merge later)\n          for (index = 0; length = keys.length, index < length; index++) {\n            key = index;\n            if (keyName) {\n              key = keys[index];\n              if (key.charAt(0) === '$') continue;\n            }\n            value = values[key];\n\n            optionGroupName = callExpression(groupByFn, key, value) || '';\n            if (!(optionGroup = optionGroups[optionGroupName])) {\n              optionGroup = optionGroups[optionGroupName] = [];\n              optionGroupNames.push(optionGroupName);\n            }\n\n            selected = isSelected(key, value);\n            anySelected = anySelected || selected;\n\n            label = callExpression(displayFn, key, value); // what will be seen by the user\n\n            // doing displayFn(scope, locals) || '' overwrites zero values\n            label = isDefined(label) ? label : '';\n            optionId = trackFn ? trackFn(scope, locals) : (keyName ? keys[index] : index);\n            if (trackFn) {\n              trackKeysCache[optionId] = key;\n            }\n\n            optionGroup.push({\n              // either the index into array or key from object\n              id: optionId,\n              label: label,\n              selected: selected                   // determine if we should be selected\n            });\n          }\n          if (!multiple) {\n            if (nullOption || viewValue === null) {\n              // insert null option if we have a placeholder, or the model is null\n              optionGroups[''].unshift({id:'', label:'', selected:!anySelected});\n            } else if (!anySelected) {\n              // option could not be found, we have to insert the undefined item\n              optionGroups[''].unshift({id:'?', label:'', selected:true});\n            }\n          }\n\n          // Now we need to update the list of DOM nodes to match the optionGroups we computed above\n          for (groupIndex = 0, groupLength = optionGroupNames.length;\n               groupIndex < groupLength;\n               groupIndex++) {\n            // current option group name or '' if no group\n            optionGroupName = optionGroupNames[groupIndex];\n\n            // list of options for that group. (first item has the parent)\n            optionGroup = optionGroups[optionGroupName];\n\n            if (optionGroupsCache.length <= groupIndex) {\n              // we need to grow the optionGroups\n              existingParent = {\n                element: optGroupTemplate.clone().attr('label', optionGroupName),\n                label: optionGroup.label\n              };\n              existingOptions = [existingParent];\n              optionGroupsCache.push(existingOptions);\n              selectElement.append(existingParent.element);\n            } else {\n              existingOptions = optionGroupsCache[groupIndex];\n              existingParent = existingOptions[0];  // either SELECT (no group) or OPTGROUP element\n\n              // update the OPTGROUP label if not the same.\n              if (existingParent.label != optionGroupName) {\n                existingParent.element.attr('label', existingParent.label = optionGroupName);\n              }\n            }\n\n            lastElement = null;  // start at the beginning\n            for (index = 0, length = optionGroup.length; index < length; index++) {\n              option = optionGroup[index];\n              if ((existingOption = existingOptions[index + 1])) {\n                // reuse elements\n                lastElement = existingOption.element;\n                if (existingOption.label !== option.label) {\n                  updateLabelMap(labelMap, existingOption.label, false);\n                  updateLabelMap(labelMap, option.label, true);\n                  lastElement.text(existingOption.label = option.label);\n                  lastElement.prop('label', existingOption.label);\n                }\n                if (existingOption.id !== option.id) {\n                  lastElement.val(existingOption.id = option.id);\n                }\n                // lastElement.prop('selected') provided by jQuery has side-effects\n                if (lastElement[0].selected !== option.selected) {\n                  lastElement.prop('selected', (existingOption.selected = option.selected));\n                  if (msie) {\n                    // See #7692\n                    // The selected item wouldn't visually update on IE without this.\n                    // Tested on Win7: IE9, IE10 and IE11. Future IEs should be tested as well\n                    lastElement.prop('selected', existingOption.selected);\n                  }\n                }\n              } else {\n                // grow elements\n\n                // if it's a null option\n                if (option.id === '' && nullOption) {\n                  // put back the pre-compiled element\n                  element = nullOption;\n                } else {\n                  // jQuery(v1.4.2) Bug: We should be able to chain the method calls, but\n                  // in this version of jQuery on some browser the .text() returns a string\n                  // rather then the element.\n                  (element = optionTemplate.clone())\n                      .val(option.id)\n                      .prop('selected', option.selected)\n                      .attr('selected', option.selected)\n                      .prop('label', option.label)\n                      .text(option.label);\n                }\n\n                existingOptions.push(existingOption = {\n                    element: element,\n                    label: option.label,\n                    id: option.id,\n                    selected: option.selected\n                });\n                updateLabelMap(labelMap, option.label, true);\n                if (lastElement) {\n                  lastElement.after(element);\n                } else {\n                  existingParent.element.append(element);\n                }\n                lastElement = element;\n              }\n            }\n            // remove any excessive OPTIONs in a group\n            index++; // increment since the existingOptions[0] is parent element not OPTION\n            while (existingOptions.length > index) {\n              option = existingOptions.pop();\n              updateLabelMap(labelMap, option.label, false);\n              option.element.remove();\n            }\n          }\n          // remove any excessive OPTGROUPs from select\n          while (optionGroupsCache.length > groupIndex) {\n            // remove all the labels in the option group\n            optionGroup = optionGroupsCache.pop();\n            for (index = 1; index < optionGroup.length; ++index) {\n              updateLabelMap(labelMap, optionGroup[index].label, false);\n            }\n            optionGroup[0].element.remove();\n          }\n          forEach(labelMap, function(count, label) {\n            if (count > 0) {\n              selectCtrl.addOption(label);\n            } else if (count < 0) {\n              selectCtrl.removeOption(label);\n            }\n          });\n        }\n      }\n    }\n  };\n}];\n\nvar optionDirective = ['$interpolate', function($interpolate) {\n  var nullSelectCtrl = {\n    addOption: noop,\n    removeOption: noop\n  };\n\n  return {\n    restrict: 'E',\n    priority: 100,\n    compile: function(element, attr) {\n      if (isUndefined(attr.value)) {\n        var interpolateFn = $interpolate(element.text(), true);\n        if (!interpolateFn) {\n          attr.$set('value', element.text());\n        }\n      }\n\n      return function(scope, element, attr) {\n        var selectCtrlName = '$selectController',\n            parent = element.parent(),\n            selectCtrl = parent.data(selectCtrlName) ||\n              parent.parent().data(selectCtrlName); // in case we are in optgroup\n\n        if (!selectCtrl || !selectCtrl.databound) {\n          selectCtrl = nullSelectCtrl;\n        }\n\n        if (interpolateFn) {\n          scope.$watch(interpolateFn, function interpolateWatchAction(newVal, oldVal) {\n            attr.$set('value', newVal);\n            if (oldVal !== newVal) {\n              selectCtrl.removeOption(oldVal);\n            }\n            selectCtrl.addOption(newVal, element);\n          });\n        } else {\n          selectCtrl.addOption(attr.value, element);\n        }\n\n        element.on('$destroy', function() {\n          selectCtrl.removeOption(attr.value);\n        });\n      };\n    }\n  };\n}];\n\nvar styleDirective = valueFn({\n  restrict: 'E',\n  terminal: false\n});\n\nvar requiredDirective = function() {\n  return {\n    restrict: 'A',\n    require: '?ngModel',\n    link: function(scope, elm, attr, ctrl) {\n      if (!ctrl) return;\n      attr.required = true; // force truthy in case we are on non input element\n\n      ctrl.$validators.required = function(modelValue, viewValue) {\n        return !attr.required || !ctrl.$isEmpty(viewValue);\n      };\n\n      attr.$observe('required', function() {\n        ctrl.$validate();\n      });\n    }\n  };\n};\n\n\nvar patternDirective = function() {\n  return {\n    restrict: 'A',\n    require: '?ngModel',\n    link: function(scope, elm, attr, ctrl) {\n      if (!ctrl) return;\n\n      var regexp, patternExp = attr.ngPattern || attr.pattern;\n      attr.$observe('pattern', function(regex) {\n        if (isString(regex) && regex.length > 0) {\n          regex = new RegExp('^' + regex + '$');\n        }\n\n        if (regex && !regex.test) {\n          throw minErr('ngPattern')('noregexp',\n            'Expected {0} to be a RegExp but was {1}. Element: {2}', patternExp,\n            regex, startingTag(elm));\n        }\n\n        regexp = regex || undefined;\n        ctrl.$validate();\n      });\n\n      ctrl.$validators.pattern = function(value) {\n        return ctrl.$isEmpty(value) || isUndefined(regexp) || regexp.test(value);\n      };\n    }\n  };\n};\n\n\nvar maxlengthDirective = function() {\n  return {\n    restrict: 'A',\n    require: '?ngModel',\n    link: function(scope, elm, attr, ctrl) {\n      if (!ctrl) return;\n\n      var maxlength = -1;\n      attr.$observe('maxlength', function(value) {\n        var intVal = int(value);\n        maxlength = isNaN(intVal) ? -1 : intVal;\n        ctrl.$validate();\n      });\n      ctrl.$validators.maxlength = function(modelValue, viewValue) {\n        return (maxlength < 0) || ctrl.$isEmpty(viewValue) || (viewValue.length <= maxlength);\n      };\n    }\n  };\n};\n\nvar minlengthDirective = function() {\n  return {\n    restrict: 'A',\n    require: '?ngModel',\n    link: function(scope, elm, attr, ctrl) {\n      if (!ctrl) return;\n\n      var minlength = 0;\n      attr.$observe('minlength', function(value) {\n        minlength = int(value) || 0;\n        ctrl.$validate();\n      });\n      ctrl.$validators.minlength = function(modelValue, viewValue) {\n        return ctrl.$isEmpty(viewValue) || viewValue.length >= minlength;\n      };\n    }\n  };\n};\n\n  if (window.angular.bootstrap) {\n    //AngularJS is already loaded, so we can return here...\n    console.log('WARNING: Tried to load angular more than once.');\n    return;\n  }\n\n  //try to bind to jquery now so that one can write jqLite(document).ready()\n  //but we will rebind on bootstrap again.\n  bindJQuery();\n\n  publishExternalAPI(angular);\n\n  jqLite(document).ready(function() {\n    angularInit(document, bootstrap);\n  });\n\n})(window, document);\n\n!window.angular.$$csp() && window.angular.element(document).find('head').prepend('<style type=\"text/css\">@charset \"UTF-8\";[ng\\\\:cloak],[ng-cloak],[data-ng-cloak],[x-ng-cloak],.ng-cloak,.x-ng-cloak,.ng-hide:not(.ng-hide-animate){display:none !important;}ng\\\\:form{display:block;}</style>');"
  },
  {
    "path": "flowable-ui-web/modeler/libs/autofill-events_1.0.0/autofill-event.js",
    "content": "/**\n * Autofill event polyfill ##version:1.0.0##\n * (c) 2014 Google, Inc.\n * License: MIT\n */\n(function(window) {\n  var $ = window.jQuery || window.angular.element;\n  var rootElement = window.document.documentElement,\n    $rootElement = $(rootElement);\n\n  addGlobalEventListener('change', markValue);\n  addValueChangeByJsListener(markValue);\n\n  $.prototype.checkAndTriggerAutoFillEvent = jqCheckAndTriggerAutoFillEvent;\n\n  // Need to use blur and not change event\n  // as Chrome does not fire change events in all cases an input is changed\n  // (e.g. when starting to type and then finish the input by auto filling a username)\n  addGlobalEventListener('blur', function(target) {\n    // setTimeout needed for Chrome as it fills other\n    // form fields a little later...\n    window.setTimeout(function() {\n      findParentForm(target).find('input').checkAndTriggerAutoFillEvent();\n    }, 20);\n  });\n\n  function DOMContentLoadedListener() {\n      // mark all values that are present when the DOM is ready.\n      // We don't need to trigger a change event here,\n      // as js libs start with those values already being set!\n      forEach(document.getElementsByTagName('input'), markValue);\n\n      // The timeout is needed for Chrome as it auto fills\n      // login forms some time after DOMContentLoaded!\n      window.setTimeout(function() {\n        $rootElement.find('input').checkAndTriggerAutoFillEvent();\n      }, 200);\n  }\n\n  //IE8 compatibility issue\n  if(!window.document.addEventListener){\n    window.document.attachEvent('DOMContentLoaded', DOMContentLoadedListener);    \n  }else{\n    window.document.addEventListener('DOMContentLoaded', DOMContentLoadedListener, false);\n  }\n\n  return;\n\n  // ----------\n\n  function jqCheckAndTriggerAutoFillEvent() {\n    var i, el;\n    for (i=0; i<this.length; i++) {\n      el = this[i];\n      if (!valueMarked(el)) {\n        markValue(el);\n        triggerChangeEvent(el);\n      }\n    }\n  }\n\n  function valueMarked(el) {\n    var val = el.value,\n         $$currentValue = el.$$currentValue;\n    if (!val && !$$currentValue) {\n      return true;\n    }\n    return val === $$currentValue;\n  }\n\n  function markValue(el) {\n    el.$$currentValue = el.value;\n  }\n\n  function addValueChangeByJsListener(listener) {\n    var jq = window.jQuery || window.angular.element,\n        jqProto = jq.prototype;\n    var _val = jqProto.val;\n    jqProto.val = function(newValue) {\n      var res = _val.apply(this, arguments);\n      if (arguments.length > 0) {\n        forEach(this, function(el) {\n          listener(el, newValue);\n        });\n      }\n      return res;\n    }\n  }\n\n  function addGlobalEventListener(eventName, listener) {\n      // Use a capturing event listener so that\n      // we also get the event when it's stopped!\n      // Also, the blur event does not bubble.\n      if(!rootElement.addEventListener){\n          rootElement.attachEvent(eventName, onEvent);      \n      }else{\n          rootElement.addEventListener(eventName, onEvent, true);\n      }\n\n      function onEvent(event) {\n          var target = event.target;\n          listener(target);\n      }\n  }\n\n  function findParentForm(el) {\n    while (el) {\n      if (el.nodeName === 'FORM') {\n        return $(el);\n      }\n      el = el.parentNode;\n    }\n    return $();\n  }\n\n  function forEach(arr, listener) {\n    if (arr.forEach) {\n      return arr.forEach(listener);\n    }\n    var i;\n    for (i=0; i<arr.length; i++) {\n      listener(arr[i]);\n    }\n  }\n\n  function triggerChangeEvent(element) {\n    var doc = window.document;\n    var event = doc.createEvent(\"HTMLEvents\");\n    event.initEvent(\"change\", true, true);\n    element.dispatchEvent(event);\n  }\n\n})(window);\n"
  },
  {
    "path": "flowable-ui-web/modeler/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": "flowable-ui-web/modeler/libs/bootstrap-daterangepicker_1.3.7/daterangepicker.js",
    "content": "/**\n * @version: 1.3.7\n * @author: Dan Grossman http://www.dangrossman.info/\n * @date: 2014-04-29\n * @copyright: Copyright (c) 2012-2014 Dan Grossman. All rights reserved.\n * @license: Licensed under Apache License v2.0. See http://www.apache.org/licenses/LICENSE-2.0\n * @website: http://www.improvely.com/\n */\n!function ($, moment) {\n\n    var DateRangePicker = function (element, options, cb) {\n\n        // by default, the daterangepicker element is placed at the bottom of HTML body\n        this.parentEl = 'body';\n\n        //element that triggered the date range picker\n        this.element = $(element);\n\n        //create the picker HTML object\n        var DRPTemplate = '<div class=\"daterangepicker dropdown-menu\">' +\n            '<div class=\"calendar left\"></div>' +\n            '<div class=\"calendar right\"></div>' +\n            '<div class=\"ranges\">' +\n            '<div class=\"range_inputs\">' +\n            '<div class=\"daterangepicker_start_input\">' +\n            '<label for=\"daterangepicker_start\"></label>' +\n            '<input class=\"input-mini\" type=\"text\" name=\"daterangepicker_start\" value=\"\" disabled=\"disabled\" />' +\n            '</div>' +\n            '<div class=\"daterangepicker_end_input\">' +\n            '<label for=\"daterangepicker_end\"></label>' +\n            '<input class=\"input-mini\" type=\"text\" name=\"daterangepicker_end\" value=\"\" disabled=\"disabled\" />' +\n            '</div>' +\n            '<button class=\"applyBtn\" disabled=\"disabled\"></button>&nbsp;' +\n            '<button class=\"cancelBtn\"></button>' +\n            '</div>' +\n            '</div>' +\n            '</div>';\n\n        //custom options\n        if (typeof options !== 'object' || options === null)\n            options = {};\n\n        this.parentEl = (typeof options === 'object' && options.parentEl && $(options.parentEl).length) ? $(options.parentEl) : $(this.parentEl);\n        this.container = $(DRPTemplate).appendTo(this.parentEl);\n\n        this.setOptions(options, cb);\n\n        //apply CSS classes and labels to buttons\n        var c = this.container;\n        $.each(this.buttonClasses, function (idx, val) {\n            c.find('button').addClass(val);\n        });\n        this.container.find('.daterangepicker_start_input label').html(this.locale.fromLabel);\n        this.container.find('.daterangepicker_end_input label').html(this.locale.toLabel);\n        if (this.applyClass.length)\n            this.container.find('.applyBtn').addClass(this.applyClass);\n        if (this.cancelClass.length)\n            this.container.find('.cancelBtn').addClass(this.cancelClass);\n        this.container.find('.applyBtn').html(this.locale.applyLabel);\n        this.container.find('.cancelBtn').html(this.locale.cancelLabel);\n\n        //event listeners\n\n        this.container.find('.calendar')\n            .on('click.daterangepicker', '.prev', $.proxy(this.clickPrev, this))\n            .on('click.daterangepicker', '.next', $.proxy(this.clickNext, this))\n            .on('click.daterangepicker', 'td.available', $.proxy(this.clickDate, this))\n            .on('mouseenter.daterangepicker', 'td.available', $.proxy(this.enterDate, this))\n            .on('mouseleave.daterangepicker', 'td.available', $.proxy(this.updateFormInputs, this))\n            .on('change.daterangepicker', 'select.yearselect', $.proxy(this.updateMonthYear, this))\n            .on('change.daterangepicker', 'select.monthselect', $.proxy(this.updateMonthYear, this))\n            .on('change.daterangepicker', 'select.hourselect,select.minuteselect,select.ampmselect', $.proxy(this.updateTime, this));\n\n        this.container.find('.ranges')\n            .on('click.daterangepicker', 'button.applyBtn', $.proxy(this.clickApply, this))\n            .on('click.daterangepicker', 'button.cancelBtn', $.proxy(this.clickCancel, this))\n            .on('click.daterangepicker', '.daterangepicker_start_input,.daterangepicker_end_input', $.proxy(this.showCalendars, this))\n            .on('click.daterangepicker', 'li', $.proxy(this.clickRange, this))\n            .on('mouseenter.daterangepicker', 'li', $.proxy(this.enterRange, this))\n            .on('mouseleave.daterangepicker', 'li', $.proxy(this.updateFormInputs, this));\n\n        if (this.element.is('input')) {\n            this.element.on({\n                'click.daterangepicker': $.proxy(this.show, this),\n                'focus.daterangepicker': $.proxy(this.show, this),\n                'keyup.daterangepicker': $.proxy(this.updateFromControl, this)\n            });\n        } else {\n            this.element.on('click.daterangepicker', $.proxy(this.toggle, this));\n        }\n\n    };\n\n    DateRangePicker.prototype = {\n\n        constructor: DateRangePicker,\n\n        setOptions: function(options, callback) {\n\n            this.startDate = moment().startOf('day');\n            this.endDate = moment().endOf('day');\n            this.minDate = false;\n            this.maxDate = false;\n            this.dateLimit = false;\n\n            this.showDropdowns = false;\n            this.showWeekNumbers = false;\n            this.timePicker = false;\n            this.timePickerIncrement = 30;\n            this.timePicker12Hour = true;\n            this.singleDatePicker = false;\n            this.ranges = {};\n\n            this.opens = 'right';\n            if (this.element.hasClass('pull-right'))\n                this.opens = 'left';\n\n            this.buttonClasses = ['btn', 'btn-small'];\n            this.applyClass = 'btn-success';\n            this.cancelClass = 'btn-default';\n\n            this.format = 'MM/DD/YYYY';\n            this.separator = ' - ';\n\n            this.locale = {\n                applyLabel: 'Apply',\n                cancelLabel: 'Cancel',\n                fromLabel: 'From',\n                toLabel: 'To',\n                weekLabel: 'W',\n                customRangeLabel: 'Custom Range',\n                daysOfWeek: moment()._lang._weekdaysMin.slice(),\n                monthNames: moment()._lang._monthsShort.slice(),\n                firstDay: 0\n            };\n\n            this.cb = function () { };\n\n            if (typeof options.format === 'string')\n                this.format = options.format;\n\n            if (typeof options.separator === 'string')\n                this.separator = options.separator;\n\n            if (typeof options.startDate === 'string')\n                this.startDate = moment(options.startDate, this.format);\n\n            if (typeof options.endDate === 'string')\n                this.endDate = moment(options.endDate, this.format);\n\n            if (typeof options.minDate === 'string')\n                this.minDate = moment(options.minDate, this.format);\n\n            if (typeof options.maxDate === 'string')\n                this.maxDate = moment(options.maxDate, this.format);\n\n            if (typeof options.startDate === 'object')\n                this.startDate = moment(options.startDate);\n\n            if (typeof options.endDate === 'object')\n                this.endDate = moment(options.endDate);\n\n            if (typeof options.minDate === 'object')\n                this.minDate = moment(options.minDate);\n\n            if (typeof options.maxDate === 'object')\n                this.maxDate = moment(options.maxDate);\n\n            if (typeof options.applyClass === 'string')\n                this.applyClass = options.applyClass;\n\n            if (typeof options.cancelClass === 'string')\n                this.cancelClass = options.cancelClass;\n\n            if (typeof options.dateLimit === 'object')\n                this.dateLimit = options.dateLimit;\n\n            // update day names order to firstDay\n            if (typeof options.locale === 'object') {\n\n                if (typeof options.locale.daysOfWeek === 'object') {\n                    // Create a copy of daysOfWeek to avoid modification of original\n                    // options object for reusability in multiple daterangepicker instances\n                    this.locale.daysOfWeek = options.locale.daysOfWeek.slice();\n                }\n\n                if (typeof options.locale.monthNames === 'object') {\n                    this.locale.monthNames = options.locale.monthNames.slice();\n                }\n\n                if (typeof options.locale.firstDay === 'number') {\n                    this.locale.firstDay = options.locale.firstDay;\n                    var iterator = options.locale.firstDay;\n                    while (iterator > 0) {\n                        this.locale.daysOfWeek.push(this.locale.daysOfWeek.shift());\n                        iterator--;\n                    }\n                }\n\n                if (typeof options.locale.applyLabel === 'string') {\n                    this.locale.applyLabel = options.locale.applyLabel;\n                }\n\n                if (typeof options.locale.cancelLabel === 'string') {\n                    this.locale.cancelLabel = options.locale.cancelLabel;\n                }\n\n                if (typeof options.locale.fromLabel === 'string') {\n                    this.locale.fromLabel = options.locale.fromLabel;\n                }\n\n                if (typeof options.locale.toLabel === 'string') {\n                    this.locale.toLabel = options.locale.toLabel;\n                }\n\n                if (typeof options.locale.weekLabel === 'string') {\n                    this.locale.weekLabel = options.locale.weekLabel;\n                }\n\n                if (typeof options.locale.customRangeLabel === 'string') {\n                    this.locale.customRangeLabel = options.locale.customRangeLabel;\n                }\n            }\n\n            if (typeof options.opens === 'string')\n                this.opens = options.opens;\n\n            if (typeof options.showWeekNumbers === 'boolean') {\n                this.showWeekNumbers = options.showWeekNumbers;\n            }\n\n            if (typeof options.buttonClasses === 'string') {\n                this.buttonClasses = [options.buttonClasses];\n            }\n\n            if (typeof options.buttonClasses === 'object') {\n                this.buttonClasses = options.buttonClasses;\n            }\n\n            if (typeof options.showDropdowns === 'boolean') {\n                this.showDropdowns = options.showDropdowns;\n            }\n\n            if (typeof options.singleDatePicker === 'boolean') {\n                this.singleDatePicker = options.singleDatePicker;\n            }\n\n            if (typeof options.timePicker === 'boolean') {\n                this.timePicker = options.timePicker;\n            }\n\n            if (typeof options.timePickerIncrement === 'number') {\n                this.timePickerIncrement = options.timePickerIncrement;\n            }\n\n            if (typeof options.timePicker12Hour === 'boolean') {\n                this.timePicker12Hour = options.timePicker12Hour;\n            }\n\n            var start, end, range;\n\n            //if no start/end dates set, check if an input element contains initial values\n            if (typeof options.startDate === 'undefined' && typeof options.endDate === 'undefined') {\n                if ($(this.element).is('input[type=text]')) {\n                    var val = $(this.element).val();\n                    var split = val.split(this.separator);\n                    start = end = null;\n                    if (split.length == 2) {\n                        start = moment(split[0], this.format);\n                        end = moment(split[1], this.format);\n                    } else if (this.singleDatePicker) {\n                        start = moment(val, this.format);\n                        end = moment(val, this.format);\n                    }\n                    if (start !== null && end !== null) {\n                        this.startDate = start;\n                        this.endDate = end;\n                    }\n                }\n            }\n\n            if (typeof options.ranges === 'object') {\n                for (range in options.ranges) {\n\n                    start = moment(options.ranges[range][0]);\n                    end = moment(options.ranges[range][1]);\n\n                    // If we have a min/max date set, bound this range\n                    // to it, but only if it would otherwise fall\n                    // outside of the min/max.\n                    if (this.minDate && start.isBefore(this.minDate))\n                        start = moment(this.minDate);\n\n                    if (this.maxDate && end.isAfter(this.maxDate))\n                        end = moment(this.maxDate);\n\n                    // If the end of the range is before the minimum (if min is set) OR\n                    // the start of the range is after the max (also if set) don't display this\n                    // range option.\n                    if ((this.minDate && end.isBefore(this.minDate)) || (this.maxDate && start.isAfter(this.maxDate))) {\n                        continue;\n                    }\n\n                    this.ranges[range] = [start, end];\n                }\n\n                var list = '<ul>';\n                for (range in this.ranges) {\n                    list += '<li>' + range + '</li>';\n                }\n                list += '<li>' + this.locale.customRangeLabel + '</li>';\n                list += '</ul>';\n                this.container.find('.ranges ul').remove();\n                this.container.find('.ranges').prepend(list);\n            }\n\n            if (typeof callback === 'function') {\n                this.cb = callback;\n            }\n\n            if (!this.timePicker) {\n                this.startDate = this.startDate.startOf('day');\n                this.endDate = this.endDate.endOf('day');\n            }\n\n            if (this.singleDatePicker) {\n                this.opens = 'right';\n                this.container.find('.calendar.right').show();\n                this.container.find('.calendar.left').hide();\n                this.container.find('.ranges').hide();\n                if (!this.container.find('.calendar.right').hasClass('single'))\n                    this.container.find('.calendar.right').addClass('single');\n            } else {\n                this.container.find('.calendar.right').removeClass('single');\n                this.container.find('.ranges').show();\n            }\n\n            this.oldStartDate = this.startDate.clone();\n            this.oldEndDate = this.endDate.clone();\n            this.oldChosenLabel = this.chosenLabel;\n\n            this.leftCalendar = {\n                month: moment([this.startDate.year(), this.startDate.month(), 1, this.startDate.hour(), this.startDate.minute()]),\n                calendar: []\n            };\n\n            this.rightCalendar = {\n                month: moment([this.endDate.year(), this.endDate.month(), 1, this.endDate.hour(), this.endDate.minute()]),\n                calendar: []\n            };\n\n            if (this.opens == 'right') {\n                //swap calendar positions\n                var left = this.container.find('.calendar.left');\n                var right = this.container.find('.calendar.right');\n                left.removeClass('left').addClass('right');\n                right.removeClass('right').addClass('left');\n            }\n\n            if (typeof options.ranges === 'undefined' && !this.singleDatePicker) {\n                this.container.addClass('show-calendar');\n            }\n\n            this.container.addClass('opens' + this.opens);\n\n            this.updateView();\n            this.updateCalendars();\n\n        },\n\n        setStartDate: function(startDate) {\n            if (typeof startDate === 'string')\n                this.startDate = moment(startDate, this.format);\n\n            if (typeof startDate === 'object')\n                this.startDate = moment(startDate);\n\n            if (!this.timePicker)\n                this.startDate = this.startDate.startOf('day');\n\n            this.oldStartDate = this.startDate.clone();\n\n            this.updateView();\n            this.updateCalendars();\n        },\n\n        setEndDate: function(endDate) {\n            if (typeof endDate === 'string')\n                this.endDate = moment(endDate, this.format);\n\n            if (typeof endDate === 'object')\n                this.endDate = moment(endDate);\n\n            if (!this.timePicker)\n                this.endDate = this.endDate.endOf('day');\n\n            this.oldEndDate = this.endDate.clone();\n\n            this.updateView();\n            this.updateCalendars();\n        },\n\n        updateView: function () {\n            this.leftCalendar.month.month(this.startDate.month()).year(this.startDate.year());\n            this.rightCalendar.month.month(this.endDate.month()).year(this.endDate.year());\n            this.updateFormInputs();\n        },\n\n        updateFormInputs: function () {\n            this.container.find('input[name=daterangepicker_start]').val(this.startDate.format(this.format));\n            this.container.find('input[name=daterangepicker_end]').val(this.endDate.format(this.format));\n\n            if (this.startDate.isSame(this.endDate) || this.startDate.isBefore(this.endDate)) {\n                this.container.find('button.applyBtn').removeAttr('disabled');\n            } else {\n                this.container.find('button.applyBtn').attr('disabled', 'disabled');\n            }\n        },\n\n        updateFromControl: function () {\n            if (!this.element.is('input')) return;\n            if (!this.element.val().length) return;\n\n            var dateString = this.element.val().split(this.separator),\n                start = null,\n                end = null;\n\n            if(dateString.length === 2) {\n                start = moment(dateString[0], this.format);\n                end = moment(dateString[1], this.format);\n            }\n\n            if (this.singleDatePicker || start === null || end === null) {\n                start = moment(this.element.val(), this.format);\n                end = start;\n            }\n\n            if (end.isBefore(start)) return;\n\n            this.oldStartDate = this.startDate.clone();\n            this.oldEndDate = this.endDate.clone();\n\n            this.startDate = start;\n            this.endDate = end;\n\n            if (!this.startDate.isSame(this.oldStartDate) || !this.endDate.isSame(this.oldEndDate))\n                this.notify();\n\n            this.updateCalendars();\n        },\n\n        notify: function () {\n            this.updateView();\n            this.cb(this.startDate, this.endDate, this.chosenLabel);\n        },\n\n        move: function () {\n            var parentOffset = { top: 0, left: 0 };\n            if (!this.parentEl.is('body')) {\n                parentOffset = {\n                    top: this.parentEl.offset().top - this.parentEl.scrollTop(),\n                    left: this.parentEl.offset().left - this.parentEl.scrollLeft()\n                };\n            }\n\n            if (this.opens == 'left') {\n                this.container.css({\n                    top: this.element.offset().top + this.element.outerHeight() - parentOffset.top,\n                    right: $(window).width() - this.element.offset().left - this.element.outerWidth() - parentOffset.left,\n                    left: 'auto'\n                });\n                if (this.container.offset().left < 0) {\n                    this.container.css({\n                        right: 'auto',\n                        left: 9\n                    });\n                }\n            } else {\n                this.container.css({\n                    top: this.element.offset().top + this.element.outerHeight() - parentOffset.top,\n                    left: this.element.offset().left - parentOffset.left,\n                    right: 'auto'\n                });\n                if (this.container.offset().left + this.container.outerWidth() > $(window).width()) {\n                    this.container.css({\n                        left: 'auto',\n                        right: 0\n                    });\n                }\n            }\n        },\n\n        toggle: function (e) {\n            if (this.element.hasClass('active')) {\n                this.hide();\n            } else {\n                this.show();\n            }\n        },\n\n        show: function (e) {\n            this.element.addClass('active');\n            this.container.show();\n            this.move();\n\n            // Create a click proxy that is private to this instance of datepicker, for unbinding\n            this._outsideClickProxy = $.proxy(function (e) { this.outsideClick(e); }, this);\n            // Bind global datepicker mousedown for hiding and\n            $(document)\n                .on('mousedown.daterangepicker', this._outsideClickProxy)\n                // also explicitly play nice with Bootstrap dropdowns, which stopPropagation when clicking them\n                .on('click.daterangepicker', '[data-toggle=dropdown]', this._outsideClickProxy)\n                // and also close when focus changes to outside the picker (eg. tabbing between controls)\n                .on('focusin.daterangepicker', this._outsideClickProxy);\n\n            this.element.trigger('show.daterangepicker', this);\n        },\n\n        outsideClick: function (e) {\n            var target = $(e.target);\n            // if the page is clicked anywhere except within the daterangerpicker/button\n            // itself then call this.hide()\n            if (\n                target.closest(this.element).length ||\n                target.closest(this.container).length ||\n                target.closest('.calendar-date').length\n                ) return;\n            this.hide();\n        },\n\n        hide: function (e) {\n            $(document)\n                .off('mousedown.daterangepicker', this._outsideClickProxy)\n                .off('click.daterangepicker', this._outsideClickProxy)\n                .off('focusin.daterangepicker', this._outsideClickProxy);\n\n            this.element.removeClass('active');\n            this.container.hide();\n\n            if (!this.startDate.isSame(this.oldStartDate) || !this.endDate.isSame(this.oldEndDate))\n                this.notify();\n\n            this.oldStartDate = this.startDate.clone();\n            this.oldEndDate = this.endDate.clone();\n\n            this.element.trigger('hide.daterangepicker', this);\n        },\n\n        enterRange: function (e) {\n            // mouse pointer has entered a range label\n            var label = e.target.innerHTML;\n            if (label == this.locale.customRangeLabel) {\n                this.updateView();\n            } else {\n                var dates = this.ranges[label];\n                this.container.find('input[name=daterangepicker_start]').val(dates[0].format(this.format));\n                this.container.find('input[name=daterangepicker_end]').val(dates[1].format(this.format));\n            }\n        },\n\n        showCalendars: function() {\n            this.container.addClass('show-calendar');\n            this.move();\n        },\n\n        hideCalendars: function() {\n            this.container.removeClass('show-calendar');\n        },\n\n        updateInputText: function() {\n            if (this.element.is('input') && !this.singleDatePicker) {\n                this.element.val(this.startDate.format(this.format) + this.separator + this.endDate.format(this.format));\n            } else if (this.element.is('input')) {\n                this.element.val(this.startDate.format(this.format));\n            }\n        },\n\n        clickRange: function (e) {\n            var label = e.target.innerHTML;\n            this.chosenLabel = label;\n            if (label == this.locale.customRangeLabel) {\n                this.showCalendars();\n            } else {\n                var dates = this.ranges[label];\n\n                this.startDate = dates[0];\n                this.endDate = dates[1];\n\n                if (!this.timePicker) {\n                    this.startDate.startOf('day');\n                    this.endDate.endOf('day');\n                }\n\n                this.leftCalendar.month.month(this.startDate.month()).year(this.startDate.year()).hour(this.startDate.hour()).minute(this.startDate.minute());\n                this.rightCalendar.month.month(this.endDate.month()).year(this.endDate.year()).hour(this.endDate.hour()).minute(this.endDate.minute());\n                this.updateCalendars();\n\n                this.updateInputText();\n\n                this.hideCalendars();\n                this.hide();\n                this.element.trigger('apply.daterangepicker', this);\n            }\n        },\n\n        clickPrev: function (e) {\n            var cal = $(e.target).parents('.calendar');\n            if (cal.hasClass('left')) {\n                this.leftCalendar.month.subtract('month', 1);\n            } else {\n                this.rightCalendar.month.subtract('month', 1);\n            }\n            this.updateCalendars();\n        },\n\n        clickNext: function (e) {\n            var cal = $(e.target).parents('.calendar');\n            if (cal.hasClass('left')) {\n                this.leftCalendar.month.add('month', 1);\n            } else {\n                this.rightCalendar.month.add('month', 1);\n            }\n            this.updateCalendars();\n        },\n\n        enterDate: function (e) {\n\n            var title = $(e.target).attr('data-title');\n            var row = title.substr(1, 1);\n            var col = title.substr(3, 1);\n            var cal = $(e.target).parents('.calendar');\n\n            if (cal.hasClass('left')) {\n                this.container.find('input[name=daterangepicker_start]').val(this.leftCalendar.calendar[row][col].format(this.format));\n            } else {\n                this.container.find('input[name=daterangepicker_end]').val(this.rightCalendar.calendar[row][col].format(this.format));\n            }\n\n        },\n\n        clickDate: function (e) {\n            var title = $(e.target).attr('data-title');\n            var row = title.substr(1, 1);\n            var col = title.substr(3, 1);\n            var cal = $(e.target).parents('.calendar');\n\n            var startDate, endDate;\n            if (cal.hasClass('left')) {\n                startDate = this.leftCalendar.calendar[row][col];\n                endDate = this.endDate;\n                if (typeof this.dateLimit === 'object') {\n                    var maxDate = moment(startDate).add(this.dateLimit).startOf('day');\n                    if (endDate.isAfter(maxDate)) {\n                        endDate = maxDate;\n                    }\n                }\n            } else {\n                startDate = this.startDate;\n                endDate = this.rightCalendar.calendar[row][col];\n                if (typeof this.dateLimit === 'object') {\n                    var minDate = moment(endDate).subtract(this.dateLimit).startOf('day');\n                    if (startDate.isBefore(minDate)) {\n                        startDate = minDate;\n                    }\n                }\n            }\n\n            if (this.singleDatePicker && cal.hasClass('left')) {\n                endDate = startDate.clone();\n            } else if (this.singleDatePicker && cal.hasClass('right')) {\n                startDate = endDate.clone();\n            }\n\n            cal.find('td').removeClass('active');\n\n            if (startDate.isSame(endDate) || startDate.isBefore(endDate)) {\n                $(e.target).addClass('active');\n                this.startDate = startDate;\n                this.endDate = endDate;\n                this.chosenLabel = this.locale.customRangeLabel;\n            } else if (startDate.isAfter(endDate)) {\n                $(e.target).addClass('active');\n                var difference = this.endDate.diff(this.startDate);\n                this.startDate = startDate;\n                this.endDate = moment(startDate).add('ms', difference);\n                this.chosenLabel = this.locale.customRangeLabel;\n            }\n\n            this.leftCalendar.month.month(this.startDate.month()).year(this.startDate.year());\n            this.rightCalendar.month.month(this.endDate.month()).year(this.endDate.year());\n            this.updateCalendars();\n\n            if (!this.timePicker)\n                endDate.endOf('day');\n\n            if (this.singleDatePicker)\n                this.clickApply();\n        },\n\n        clickApply: function (e) {\n            this.updateInputText();\n            this.hide();\n            this.element.trigger('apply.daterangepicker', this);\n        },\n\n        clickCancel: function (e) {\n            this.startDate = this.oldStartDate;\n            this.endDate = this.oldEndDate;\n            this.chosenLabel = this.oldChosenLabel;\n            this.updateView();\n            this.updateCalendars();\n            this.hide();\n            this.element.trigger('cancel.daterangepicker', this);\n        },\n\n        updateMonthYear: function (e) {\n            var isLeft = $(e.target).closest('.calendar').hasClass('left'),\n                leftOrRight = isLeft ? 'left' : 'right',\n                cal = this.container.find('.calendar.'+leftOrRight);\n\n            // Month must be Number for new moment versions\n            var month = parseInt(cal.find('.monthselect').val(), 10);\n            var year = cal.find('.yearselect').val();\n\n            this[leftOrRight+'Calendar'].month.month(month).year(year);\n            this.updateCalendars();\n        },\n\n        updateTime: function(e) {\n\n            var cal = $(e.target).closest('.calendar'),\n                isLeft = cal.hasClass('left');\n\n            var hour = parseInt(cal.find('.hourselect').val(), 10);\n            var minute = parseInt(cal.find('.minuteselect').val(), 10);\n\n            if (this.timePicker12Hour) {\n                var ampm = cal.find('.ampmselect').val();\n                if (ampm === 'PM' && hour < 12)\n                    hour += 12;\n                if (ampm === 'AM' && hour === 12)\n                    hour = 0;\n            }\n\n            if (isLeft) {\n                var start = this.startDate.clone();\n                start.hour(hour);\n                start.minute(minute);\n                this.startDate = start;\n                this.leftCalendar.month.hour(hour).minute(minute);\n            } else {\n                var end = this.endDate.clone();\n                end.hour(hour);\n                end.minute(minute);\n                this.endDate = end;\n                this.rightCalendar.month.hour(hour).minute(minute);\n            }\n\n            this.updateCalendars();\n        },\n\n        updateCalendars: function () {\n            this.leftCalendar.calendar = this.buildCalendar(this.leftCalendar.month.month(), this.leftCalendar.month.year(), this.leftCalendar.month.hour(), this.leftCalendar.month.minute(), 'left');\n            this.rightCalendar.calendar = this.buildCalendar(this.rightCalendar.month.month(), this.rightCalendar.month.year(), this.rightCalendar.month.hour(), this.rightCalendar.month.minute(), 'right');\n            this.container.find('.calendar.left').empty().html(this.renderCalendar(this.leftCalendar.calendar, this.startDate, this.minDate, this.maxDate));\n            this.container.find('.calendar.right').empty().html(this.renderCalendar(this.rightCalendar.calendar, this.endDate, this.startDate, this.maxDate));\n\n            this.container.find('.ranges li').removeClass('active');\n            var customRange = true;\n            var i = 0;\n            for (var range in this.ranges) {\n                if (this.timePicker) {\n                    if (this.startDate.isSame(this.ranges[range][0]) && this.endDate.isSame(this.ranges[range][1])) {\n                        customRange = false;\n                        this.chosenLabel = this.container.find('.ranges li:eq(' + i + ')')\n                            .addClass('active').html();\n                    }\n                } else {\n                    //ignore times when comparing dates if time picker is not enabled\n                    if (this.startDate.format('YYYY-MM-DD') == this.ranges[range][0].format('YYYY-MM-DD') && this.endDate.format('YYYY-MM-DD') == this.ranges[range][1].format('YYYY-MM-DD')) {\n                        customRange = false;\n                        this.chosenLabel = this.container.find('.ranges li:eq(' + i + ')')\n                            .addClass('active').html();\n                    }\n                }\n                i++;\n            }\n            if (customRange) {\n                this.chosenLabel = this.container.find('.ranges li:last')\n                    .addClass('active').html();\n            }\n        },\n\n        buildCalendar: function (month, year, hour, minute, side) {\n            var firstDay = moment([year, month, 1]);\n            var lastMonth = moment(firstDay).subtract('month', 1).month();\n            var lastYear = moment(firstDay).subtract('month', 1).year();\n\n            var daysInLastMonth = moment([lastYear, lastMonth]).daysInMonth();\n\n            var dayOfWeek = firstDay.day();\n\n            var i;\n\n            //initialize a 6 rows x 7 columns array for the calendar\n            var calendar = [];\n            for (i = 0; i < 6; i++) {\n                calendar[i] = [];\n            }\n\n            //populate the calendar with date objects\n            var startDay = daysInLastMonth - dayOfWeek + this.locale.firstDay + 1;\n            if (startDay > daysInLastMonth)\n                startDay -= 7;\n\n            if (dayOfWeek == this.locale.firstDay)\n                startDay = daysInLastMonth - 6;\n\n            var curDate = moment([lastYear, lastMonth, startDay, 12, minute]);\n            var col, row;\n            for (i = 0, col = 0, row = 0; i < 42; i++, col++, curDate = moment(curDate).add('hour', 24)) {\n                if (i > 0 && col % 7 === 0) {\n                    col = 0;\n                    row++;\n                }\n                calendar[row][col] = curDate.clone().hour(hour);\n                curDate.hour(12);\n            }\n\n            return calendar;\n        },\n\n        renderDropdowns: function (selected, minDate, maxDate) {\n            var currentMonth = selected.month();\n            var monthHtml = '<select class=\"monthselect\">';\n            var inMinYear = false;\n            var inMaxYear = false;\n\n            for (var m = 0; m < 12; m++) {\n                if ((!inMinYear || m >= minDate.month()) && (!inMaxYear || m <= maxDate.month())) {\n                    monthHtml += \"<option value='\" + m + \"'\" +\n                        (m === currentMonth ? \" selected='selected'\" : \"\") +\n                        \">\" + this.locale.monthNames[m] + \"</option>\";\n                }\n            }\n            monthHtml += \"</select>\";\n\n            var currentYear = selected.year();\n            var maxYear = (maxDate && maxDate.year()) || (currentYear + 5);\n            var minYear = (minDate && minDate.year()) || (currentYear - 50);\n            var yearHtml = '<select class=\"yearselect\">';\n\n            for (var y = minYear; y <= maxYear; y++) {\n                yearHtml += '<option value=\"' + y + '\"' +\n                    (y === currentYear ? ' selected=\"selected\"' : '') +\n                    '>' + y + '</option>';\n            }\n\n            yearHtml += '</select>';\n\n            return monthHtml + yearHtml;\n        },\n\n        renderCalendar: function (calendar, selected, minDate, maxDate) {\n\n            var html = '<div class=\"calendar-date\">';\n            html += '<table class=\"table-condensed\">';\n            html += '<thead>';\n            html += '<tr>';\n\n            // add empty cell for week number\n            if (this.showWeekNumbers)\n                html += '<th></th>';\n\n            if (!minDate || minDate.isBefore(calendar[1][1])) {\n                html += '<th class=\"prev available\"><i class=\"fa fa-arrow-left icon-arrow-left glyphicon glyphicon-arrow-left\"></i></th>';\n            } else {\n                html += '<th></th>';\n            }\n\n            var dateHtml = this.locale.monthNames[calendar[1][1].month()] + calendar[1][1].format(\" YYYY\");\n\n            if (this.showDropdowns) {\n                dateHtml = this.renderDropdowns(calendar[1][1], minDate, maxDate);\n            }\n\n            html += '<th colspan=\"5\" class=\"month\">' + dateHtml + '</th>';\n            if (!maxDate || maxDate.isAfter(calendar[1][1])) {\n                html += '<th class=\"next available\"><i class=\"fa fa-arrow-right icon-arrow-right glyphicon glyphicon-arrow-right\"></i></th>';\n            } else {\n                html += '<th></th>';\n            }\n\n            html += '</tr>';\n            html += '<tr>';\n\n            // add week number label\n            if (this.showWeekNumbers)\n                html += '<th class=\"week\">' + this.locale.weekLabel + '</th>';\n\n            $.each(this.locale.daysOfWeek, function (index, dayOfWeek) {\n                html += '<th>' + dayOfWeek + '</th>';\n            });\n\n            html += '</tr>';\n            html += '</thead>';\n            html += '<tbody>';\n\n            for (var row = 0; row < 6; row++) {\n                html += '<tr>';\n\n                // add week number\n                if (this.showWeekNumbers)\n                    html += '<td class=\"week\">' + calendar[row][0].week() + '</td>';\n\n                for (var col = 0; col < 7; col++) {\n                    var cname = 'available ';\n                    cname += (calendar[row][col].month() == calendar[1][1].month()) ? '' : 'off';\n\n                    if ((minDate && calendar[row][col].isBefore(minDate, 'day')) || (maxDate && calendar[row][col].isAfter(maxDate, 'day'))) {\n                        cname = ' off disabled ';\n                    } else if (calendar[row][col].format('YYYY-MM-DD') == selected.format('YYYY-MM-DD')) {\n                        cname += ' active ';\n                        if (calendar[row][col].format('YYYY-MM-DD') == this.startDate.format('YYYY-MM-DD')) {\n                            cname += ' start-date ';\n                        }\n                        if (calendar[row][col].format('YYYY-MM-DD') == this.endDate.format('YYYY-MM-DD')) {\n                            cname += ' end-date ';\n                        }\n                    } else if (calendar[row][col] >= this.startDate && calendar[row][col] <= this.endDate) {\n                        cname += ' in-range ';\n                        if (calendar[row][col].isSame(this.startDate)) { cname += ' start-date '; }\n                        if (calendar[row][col].isSame(this.endDate)) { cname += ' end-date '; }\n                    }\n\n                    var title = 'r' + row + 'c' + col;\n                    html += '<td class=\"' + cname.replace(/\\s+/g, ' ').replace(/^\\s?(.*?)\\s?$/, '$1') + '\" data-title=\"' + title + '\">' + calendar[row][col].date() + '</td>';\n                }\n                html += '</tr>';\n            }\n\n            html += '</tbody>';\n            html += '</table>';\n            html += '</div>';\n\n            var i;\n            if (this.timePicker) {\n\n                html += '<div class=\"calendar-time\">';\n                html += '<select class=\"hourselect\">';\n                var start = 0;\n                var end = 23;\n                var selected_hour = selected.hour();\n                if (this.timePicker12Hour) {\n                    start = 1;\n                    end = 12;\n                    if (selected_hour >= 12)\n                        selected_hour -= 12;\n                    if (selected_hour === 0)\n                        selected_hour = 12;\n                }\n\n                for (i = start; i <= end; i++) {\n                    if (i == selected_hour) {\n                        html += '<option value=\"' + i + '\" selected=\"selected\">' + i + '</option>';\n                    } else {\n                        html += '<option value=\"' + i + '\">' + i + '</option>';\n                    }\n                }\n\n                html += '</select> : ';\n\n                html += '<select class=\"minuteselect\">';\n\n                for (i = 0; i < 60; i += this.timePickerIncrement) {\n                    var num = i;\n                    if (num < 10)\n                        num = '0' + num;\n                    if (i == selected.minute()) {\n                        html += '<option value=\"' + i + '\" selected=\"selected\">' + num + '</option>';\n                    } else {\n                        html += '<option value=\"' + i + '\">' + num + '</option>';\n                    }\n                }\n\n                html += '</select> ';\n\n                if (this.timePicker12Hour) {\n                    html += '<select class=\"ampmselect\">';\n                    if (selected.hour() >= 12) {\n                        html += '<option value=\"AM\">AM</option><option value=\"PM\" selected=\"selected\">PM</option>';\n                    } else {\n                        html += '<option value=\"AM\" selected=\"selected\">AM</option><option value=\"PM\">PM</option>';\n                    }\n                    html += '</select>';\n                }\n\n                html += '</div>';\n\n            }\n\n            return html;\n\n        },\n\n        remove: function() {\n\n            this.container.remove();\n            this.element.off('.daterangepicker');\n            this.element.removeData('daterangepicker');\n\n        }\n\n    };\n\n    $.fn.daterangepicker = function (options, cb) {\n        this.each(function () {\n            var el = $(this);\n            if (el.data('daterangepicker'))\n                el.data('daterangepicker').remove();\n            el.data('daterangepicker', new DateRangePicker(el, options, cb));\n        });\n        return this;\n    };\n\n}(window.jQuery, window.moment);"
  },
  {
    "path": "flowable-ui-web/modeler/libs/bootstrap-tour_0.9.1/bootstrap-tour.js",
    "content": "/* ===========================================================\n # bootstrap-tour - v0.9.1\n # http://bootstraptour.com\n # ==============================================================\n # Copyright 2012-2013 Ulrich Sossou\n #\n # Licensed under the Apache License, Version 2.0 (the \"License\");\n # you may not use this file except in compliance with the License.\n # You may obtain a copy of the License at\n #\n #     http://www.apache.org/licenses/LICENSE-2.0\n #\n # Unless required by applicable law or agreed to in writing, software\n # distributed under the License is distributed on an \"AS IS\" BASIS,\n # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n # See the License for the specific language governing permissions and\n # limitations under the License.\n */\n(function($, window) {\n    var Tour, document;\n    document = window.document;\n    Tour = (function() {\n        function Tour(options) {\n            this._options = $.extend({\n                name: \"tour\",\n                steps: [],\n                container: \"body\",\n                keyboard: true,\n                storage: window.localStorage,\n                debug: false,\n                backdrop: false,\n                redirect: true,\n                orphan: false,\n                duration: false,\n                basePath: \"\",\n                template: \"<div class='popover'> <div class='arrow'></div> <h3 class='popover-title'></h3> <div class='popover-content'></div> <div class='popover-navigation'> <div class='btn-group'> <button class='btn btn-sm btn-default' data-role='prev'>&laquo; Prev</button> <button class='btn btn-sm btn-default' data-role='next'>Next &raquo;</button> <button class='btn btn-sm btn-default' data-role='pause-resume' data-pause-text='Pause' data-resume-text='Resume'>Pause</button> </div> <button class='btn btn-sm btn-default' data-role='end'>End tour</button> </div> </div>\",\n                afterSetState: function(key, value) {},\n                afterGetState: function(key, value) {},\n                afterRemoveState: function(key) {},\n                onStart: function(tour) {},\n                onEnd: function(tour) {},\n                onShow: function(tour) {},\n                onShown: function(tour) {},\n                onHide: function(tour) {},\n                onHidden: function(tour) {},\n                onNext: function(tour) {},\n                onPrev: function(tour) {},\n                onPause: function(tour, duration) {},\n                onResume: function(tour, duration) {}\n            }, options);\n            this._force = false;\n            this._inited = false;\n            this.backdrop = {\n                overlay: null,\n                $element: null,\n                $background: null,\n                backgroundShown: false,\n                overlayElementShown: false\n            };\n            this;\n        }\n\n        Tour.prototype.addSteps = function(steps) {\n            var step, _i, _len;\n            for (_i = 0, _len = steps.length; _i < _len; _i++) {\n                step = steps[_i];\n                this.addStep(step);\n            }\n            return this;\n        };\n\n        Tour.prototype.addStep = function(step) {\n            this._options.steps.push(step);\n            return this;\n        };\n\n        Tour.prototype.getStep = function(i) {\n            if (this._options.steps[i] != null) {\n                return $.extend({\n                    id: \"step-\" + i,\n                    path: \"\",\n                    placement: \"right\",\n                    title: \"\",\n                    content: \"<p></p>\",\n                    next: i === this._options.steps.length - 1 ? -1 : i + 1,\n                    prev: i - 1,\n                    animation: true,\n                    container: this._options.container,\n                    backdrop: this._options.backdrop,\n                    redirect: this._options.redirect,\n                    orphan: this._options.orphan,\n                    duration: this._options.duration,\n                    template: this._options.template,\n                    onShow: this._options.onShow,\n                    onShown: this._options.onShown,\n                    onHide: this._options.onHide,\n                    onHidden: this._options.onHidden,\n                    onNext: this._options.onNext,\n                    onPrev: this._options.onPrev,\n                    onPause: this._options.onPause,\n                    onResume: this._options.onResume\n                }, this._options.steps[i]);\n            }\n        };\n\n        Tour.prototype.init = function(force) {\n            this._force = force;\n            if (this.ended()) {\n                this._debug(\"Tour ended, init prevented.\");\n                return this;\n            }\n            this.setCurrentStep();\n            this._initMouseNavigation();\n            this._initKeyboardNavigation();\n            this._onResize((function(_this) {\n                return function() {\n                    return _this.showStep(_this._current);\n                };\n            })(this));\n            if (this._current !== null) {\n                this.showStep(this._current);\n            }\n            this._inited = true;\n            return this;\n        };\n\n        Tour.prototype.start = function(force) {\n            var promise;\n            if (force == null) {\n                force = false;\n            }\n            if (!this._inited) {\n                this.init(force);\n            }\n            if (this._current === null) {\n                promise = this._makePromise(this._options.onStart != null ? this._options.onStart(this) : void 0);\n                this._callOnPromiseDone(promise, this.showStep, 0);\n            }\n            return this;\n        };\n\n        Tour.prototype.next = function() {\n            var promise;\n            promise = this.hideStep(this._current);\n            return this._callOnPromiseDone(promise, this._showNextStep);\n        };\n\n        Tour.prototype.prev = function() {\n            var promise;\n            promise = this.hideStep(this._current);\n            return this._callOnPromiseDone(promise, this._showPrevStep);\n        };\n\n        Tour.prototype.goTo = function(i) {\n            var promise;\n            promise = this.hideStep(this._current);\n            return this._callOnPromiseDone(promise, this.showStep, i);\n        };\n\n        Tour.prototype.end = function() {\n            var endHelper, promise;\n            endHelper = (function(_this) {\n                return function(e) {\n                    $(document).off(\"click.tour-\" + _this._options.name);\n                    $(document).off(\"keyup.tour-\" + _this._options.name);\n                    $(window).off(\"resize.tour-\" + _this._options.name);\n                    _this._setState(\"end\", \"yes\");\n                    _this._inited = false;\n                    _this._force = false;\n                    _this._clearTimer();\n                    if (_this._options.onEnd != null) {\n                        return _this._options.onEnd(_this);\n                    }\n                };\n            })(this);\n            promise = this.hideStep(this._current);\n            return this._callOnPromiseDone(promise, endHelper);\n        };\n\n        Tour.prototype.ended = function() {\n            return !this._force && !!this._getState(\"end\");\n        };\n\n        Tour.prototype.restart = function() {\n            this._removeState(\"current_step\");\n            this._removeState(\"end\");\n            this.setCurrentStep(0);\n            return this.start();\n        };\n\n        Tour.prototype.pause = function() {\n            var step;\n            step = this.getStep(this._current);\n            if (!(step && step.duration)) {\n                return this;\n            }\n            this._paused = true;\n            this._duration -= new Date().getTime() - this._start;\n            window.clearTimeout(this._timer);\n            this._debug(\"Paused/Stopped step \" + (this._current + 1) + \" timer (\" + this._duration + \" remaining).\");\n            if (step.onPause != null) {\n                return step.onPause(this, this._duration);\n            }\n        };\n\n        Tour.prototype.resume = function() {\n            var step;\n            step = this.getStep(this._current);\n            if (!(step && step.duration)) {\n                return this;\n            }\n            this._paused = false;\n            this._start = new Date().getTime();\n            this._duration = this._duration || step.duration;\n            this._timer = window.setTimeout((function(_this) {\n                return function() {\n                    if (_this._isLast()) {\n                        return _this.next();\n                    } else {\n                        return _this.end();\n                    }\n                };\n            })(this), this._duration);\n            this._debug(\"Started step \" + (this._current + 1) + \" timer with duration \" + this._duration);\n            if ((step.onResume != null) && this._duration !== step.duration) {\n                return step.onResume(this, this._duration);\n            }\n        };\n\n        Tour.prototype.hideStep = function(i) {\n            var hideStepHelper, promise, step;\n            step = this.getStep(i);\n            if (!step) {\n                return;\n            }\n            this._clearTimer();\n            promise = this._makePromise(step.onHide != null ? step.onHide(this, i) : void 0);\n            hideStepHelper = (function(_this) {\n                return function(e) {\n                    var $element;\n                    $element = $(step.element);\n                    if (!($element.data(\"bs.popover\") || $element.data(\"popover\"))) {\n                        $element = $(\"body\");\n                    }\n                    $element.popover(\"destroy\").removeClass(\"tour-\" + _this._options.name + \"-element tour-\" + _this._options.name + \"-\" + i + \"-element\");\n                    if (step.reflex) {\n                        $element.css(\"cursor\", \"\").off(\"click.tour-\" + _this._options.name);\n                    }\n                    if (step.backdrop) {\n                        _this._hideBackdrop();\n                    }\n                    if (step.onHidden != null) {\n                        return step.onHidden(_this);\n                    }\n                };\n            })(this);\n            this._callOnPromiseDone(promise, hideStepHelper);\n            return promise;\n        };\n\n        Tour.prototype.showStep = function(i) {\n            var promise, showStepHelper, skipToPrevious, step;\n            if (this.ended()) {\n                this._debug(\"Tour ended, showStep prevented.\");\n                return this;\n            }\n            step = this.getStep(i);\n            if (!step) {\n                return;\n            }\n            skipToPrevious = i < this._current;\n            promise = this._makePromise(step.onShow != null ? step.onShow(this, i) : void 0);\n            showStepHelper = (function(_this) {\n                return function(e) {\n                    var current_path, path;\n                    _this.setCurrentStep(i);\n                    path = (function() {\n                        switch ({}.toString.call(step.path)) {\n                            case \"[object Function]\":\n                                return step.path();\n                            case \"[object String]\":\n                                return this._options.basePath + step.path;\n                            default:\n                                return step.path;\n                        }\n                    }).call(_this);\n                    current_path = [document.location.pathname, document.location.hash].join(\"\");\n                    if (_this._isRedirect(path, current_path)) {\n                        _this._redirect(step, path);\n                        return;\n                    }\n                    if (_this._isOrphan(step)) {\n                        if (!step.orphan) {\n                            _this._debug(\"Skip the orphan step \" + (_this._current + 1) + \". Orphan option is false and the element doesn't exist or is hidden.\");\n                            if (skipToPrevious) {\n                                _this._showPrevStep();\n                            } else {\n                                _this._showNextStep();\n                            }\n                            return;\n                        }\n                        _this._debug(\"Show the orphan step \" + (_this._current + 1) + \". Orphans option is true.\");\n                    }\n                    if (step.backdrop) {\n                        _this._showBackdrop(!_this._isOrphan(step) ? step.element : void 0);\n                    }\n                    _this._scrollIntoView(step.element, function() {\n                        if ((step.element != null) && step.backdrop) {\n                            _this._showOverlayElement(step.element);\n                        }\n                        _this._showPopover(step, i);\n                        if (step.onShown != null) {\n                            step.onShown(_this);\n                        }\n                        return _this._debug(\"Step \" + (_this._current + 1) + \" of \" + _this._options.steps.length);\n                    });\n                    if (step.duration) {\n                        return _this.resume();\n                    }\n                };\n            })(this);\n            this._callOnPromiseDone(promise, showStepHelper);\n            return promise;\n        };\n\n        Tour.prototype.getCurrentStep = function() {\n            return this._current;\n        };\n\n        Tour.prototype.setCurrentStep = function(value) {\n            if (value != null) {\n                this._current = value;\n                this._setState(\"current_step\", value);\n            } else {\n                this._current = this._getState(\"current_step\");\n                this._current = this._current === null ? null : parseInt(this._current, 10);\n            }\n            return this;\n        };\n\n        Tour.prototype._setState = function(key, value) {\n            var e, keyName;\n            if (this._options.storage) {\n                keyName = \"\" + this._options.name + \"_\" + key;\n                try {\n                    this._options.storage.setItem(keyName, value);\n                } catch (_error) {\n                    e = _error;\n                    if (e.code === DOMException.QUOTA_EXCEEDED_ERR) {\n                        this.debug(\"LocalStorage quota exceeded. State storage failed.\");\n                    }\n                }\n                return this._options.afterSetState(keyName, value);\n            } else {\n                if (this._state == null) {\n                    this._state = {};\n                }\n                return this._state[key] = value;\n            }\n        };\n\n        Tour.prototype._removeState = function(key) {\n            var keyName;\n            if (this._options.storage) {\n                keyName = \"\" + this._options.name + \"_\" + key;\n                this._options.storage.removeItem(keyName);\n                return this._options.afterRemoveState(keyName);\n            } else {\n                if (this._state != null) {\n                    return delete this._state[key];\n                }\n            }\n        };\n\n        Tour.prototype._getState = function(key) {\n            var keyName, value;\n            if (this._options.storage) {\n                keyName = \"\" + this._options.name + \"_\" + key;\n                value = this._options.storage.getItem(keyName);\n            } else {\n                if (this._state != null) {\n                    value = this._state[key];\n                }\n            }\n            if (value === void 0 || value === \"null\") {\n                value = null;\n            }\n            this._options.afterGetState(key, value);\n            return value;\n        };\n\n        Tour.prototype._showNextStep = function() {\n            var promise, showNextStepHelper, step;\n            step = this.getStep(this._current);\n            showNextStepHelper = (function(_this) {\n                return function(e) {\n                    return _this.showStep(step.next);\n                };\n            })(this);\n            promise = this._makePromise(step.onNext != null ? step.onNext(this) : void 0);\n            return this._callOnPromiseDone(promise, showNextStepHelper);\n        };\n\n        Tour.prototype._showPrevStep = function() {\n            var promise, showPrevStepHelper, step;\n            step = this.getStep(this._current);\n            showPrevStepHelper = (function(_this) {\n                return function(e) {\n                    return _this.showStep(step.prev);\n                };\n            })(this);\n            promise = this._makePromise(step.onPrev != null ? step.onPrev(this) : void 0);\n            return this._callOnPromiseDone(promise, showPrevStepHelper);\n        };\n\n        Tour.prototype._debug = function(text) {\n            if (this._options.debug) {\n                return window.console.log(\"Bootstrap Tour '\" + this._options.name + \"' | \" + text);\n            }\n        };\n\n        Tour.prototype._isRedirect = function(path, currentPath) {\n            return (path != null) && path !== \"\" && ((toString.call(path) === \"[object RegExp]\" && !path.test(currentPath)) || (toString.call(path) === \"[object String]\" && path.replace(/\\?.*$/, \"\").replace(/\\/?$/, \"\") !== currentPath.replace(/\\/?$/, \"\")));\n        };\n\n        Tour.prototype._redirect = function(step, path) {\n            if ($.isFunction(step.redirect)) {\n                return step.redirect.call(this, path);\n            } else if (step.redirect === true) {\n                this._debug(\"Redirect to \" + path);\n                return document.location.href = path;\n            }\n        };\n\n        Tour.prototype._isOrphan = function(step) {\n            return (step.element == null) || !$(step.element).length || $(step.element).is(\":hidden\") && ($(step.element)[0].namespaceURI !== \"http://www.w3.org/2000/svg\");\n        };\n\n        Tour.prototype._isLast = function() {\n            return this._current < this._options.steps.length - 1;\n        };\n\n        Tour.prototype._showPopover = function(step, i) {\n            var $element, $navigation, $template, $tip, isOrphan, options;\n            options = $.extend({}, this._options);\n            $template = $.isFunction(step.template) ? $(step.template(i, step)) : $(step.template);\n            $navigation = $template.find(\".popover-navigation\");\n            isOrphan = this._isOrphan(step);\n            if (isOrphan) {\n                step.element = \"body\";\n                step.placement = \"top\";\n                $template = $template.addClass(\"orphan\");\n            }\n            $element = $(step.element);\n            $template.addClass(\"tour-\" + this._options.name + \" tour-\" + this._options.name + \"-\" + i);\n            $element.addClass(\"tour-\" + this._options.name + \"-element tour-\" + this._options.name + \"-\" + i + \"-element\");\n            if (step.options) {\n                $.extend(options, step.options);\n            }\n            if (step.reflex) {\n                $element.css(\"cursor\", \"pointer\").on(\"click.tour-\" + this._options.name, (function(_this) {\n                    return function() {\n                        if (_this._isLast()) {\n                            return _this.next();\n                        } else {\n                            return _this.end();\n                        }\n                    };\n                })(this));\n            }\n            if (step.prev < 0) {\n                $navigation.find(\"[data-role='prev']\").addClass(\"disabled\");\n            }\n            if (step.next < 0) {\n                $navigation.find(\"[data-role='next']\").addClass(\"disabled\");\n            }\n            if (!step.duration) {\n                $navigation.find(\"[data-role='pause-resume']\").remove();\n            }\n            step.template = $template.clone().wrap(\"<div>\").parent().html();\n            $element.popover({\n                placement: step.placement,\n                trigger: \"manual\",\n                title: step.title,\n                content: step.content,\n                html: true,\n                animation: step.animation,\n                container: step.container,\n                template: step.template,\n                selector: step.element\n            }).popover(\"show\");\n            $tip = $element.data(\"bs.popover\") ? $element.data(\"bs.popover\").tip() : $element.data(\"popover\").tip();\n            $tip.attr(\"id\", step.id);\n            this._reposition($tip, step);\n            if (isOrphan) {\n                return this._center($tip);\n            }\n        };\n\n        Tour.prototype._reposition = function($tip, step) {\n            var offsetBottom, offsetHeight, offsetRight, offsetWidth, originalLeft, originalTop, tipOffset;\n            offsetWidth = $tip[0].offsetWidth;\n            offsetHeight = $tip[0].offsetHeight;\n            tipOffset = $tip.offset();\n            originalLeft = tipOffset.left;\n            originalTop = tipOffset.top;\n            offsetBottom = $(document).outerHeight() - tipOffset.top - $tip.outerHeight();\n            if (offsetBottom < 0) {\n                tipOffset.top = tipOffset.top + offsetBottom;\n            }\n            offsetRight = $(\"html\").outerWidth() - tipOffset.left - $tip.outerWidth();\n            if (offsetRight < 0) {\n                tipOffset.left = tipOffset.left + offsetRight;\n            }\n            if (tipOffset.top < 0) {\n                tipOffset.top = 0;\n            }\n            if (tipOffset.left < 0) {\n                tipOffset.left = 0;\n            }\n            $tip.offset(tipOffset);\n            if (step.placement === \"bottom\" || step.placement === \"top\") {\n                if (originalLeft !== tipOffset.left) {\n                    return this._replaceArrow($tip, (tipOffset.left - originalLeft) * 2, offsetWidth, \"left\");\n                }\n            } else {\n                if (originalTop !== tipOffset.top) {\n                    return this._replaceArrow($tip, (tipOffset.top - originalTop) * 2, offsetHeight, \"top\");\n                }\n            }\n        };\n\n        Tour.prototype._center = function($tip) {\n            return $tip.css(\"top\", $(window).outerHeight() / 2 - $tip.outerHeight() / 2);\n        };\n\n        Tour.prototype._replaceArrow = function($tip, delta, dimension, position) {\n            return $tip.find(\".arrow\").css(position, delta ? 50 * (1 - delta / dimension) + \"%\" : \"\");\n        };\n\n        Tour.prototype._scrollIntoView = function(element, callback) {\n            var $element, $window, counter, offsetTop, scrollTop, windowHeight;\n            $element = $(element);\n            if (!$element.length) {\n                return callback();\n            }\n            $window = $(window);\n            offsetTop = $element.offset().top;\n            windowHeight = $window.height();\n            scrollTop = Math.max(0, offsetTop - (windowHeight / 2));\n            this._debug(\"Scroll into view. ScrollTop: \" + scrollTop + \". Element offset: \" + offsetTop + \". Window height: \" + windowHeight + \".\");\n            counter = 0;\n            return $(\"body,html\").stop(true, true).animate({\n                scrollTop: Math.ceil(scrollTop)\n            }, (function(_this) {\n                return function() {\n                    if (++counter === 2) {\n                        callback();\n                        return _this._debug(\"Scroll into view. Animation end element offset: \" + ($element.offset().top) + \". Window height: \" + ($window.height()) + \".\");\n                    }\n                };\n            })(this));\n        };\n\n        Tour.prototype._onResize = function(callback, timeout) {\n            return $(window).on(\"resize.tour-\" + this._options.name, function() {\n                clearTimeout(timeout);\n                return timeout = setTimeout(callback, 100);\n            });\n        };\n\n        Tour.prototype._initMouseNavigation = function() {\n            var _this;\n            _this = this;\n            return $(document).off(\"click.tour-\" + this._options.name, \".popover.tour-\" + this._options.name + \" *[data-role='prev']:not(.disabled)\").off(\"click.tour-\" + this._options.name, \".popover.tour-\" + this._options.name + \" *[data-role='next']:not(.disabled)\").off(\"click.tour-\" + this._options.name, \".popover.tour-\" + this._options.name + \" *[data-role='end']\").off(\"click.tour-\" + this._options.name, \".popover.tour-\" + this._options.name + \" *[data-role='pause-resume']\").on(\"click.tour-\" + this._options.name, \".popover.tour-\" + this._options.name + \" *[data-role='next']:not(.disabled)\", (function(_this) {\n                return function(e) {\n                    e.preventDefault();\n                    return _this.next();\n                };\n            })(this)).on(\"click.tour-\" + this._options.name, \".popover.tour-\" + this._options.name + \" *[data-role='prev']:not(.disabled)\", (function(_this) {\n                return function(e) {\n                    e.preventDefault();\n                    return _this.prev();\n                };\n            })(this)).on(\"click.tour-\" + this._options.name, \".popover.tour-\" + this._options.name + \" *[data-role='end']\", (function(_this) {\n                return function(e) {\n                    e.preventDefault();\n                    return _this.end();\n                };\n            })(this)).on(\"click.tour-\" + this._options.name, \".popover.tour-\" + this._options.name + \" *[data-role='pause-resume']\", function(e) {\n                var $this;\n                e.preventDefault();\n                $this = $(this);\n                $this.text(_this._paused ? $this.data(\"pause-text\") : $this.data(\"resume-text\"));\n                if (_this._paused) {\n                    return _this.resume();\n                } else {\n                    return _this.pause();\n                }\n            });\n        };\n\n        Tour.prototype._initKeyboardNavigation = function() {\n            if (!this._options.keyboard) {\n                return;\n            }\n            return $(document).on(\"keyup.tour-\" + this._options.name, (function(_this) {\n                return function(e) {\n                    if (!e.which) {\n                        return;\n                    }\n                    switch (e.which) {\n                        case 39:\n                            e.preventDefault();\n                            if (_this._isLast()) {\n                                return _this.next();\n                            } else {\n                                return _this.end();\n                            }\n                            break;\n                        case 37:\n                            e.preventDefault();\n                            if (_this._current > 0) {\n                                return _this.prev();\n                            }\n                            break;\n                        case 27:\n                            e.preventDefault();\n                            return _this.end();\n                    }\n                };\n            })(this));\n        };\n\n        Tour.prototype._makePromise = function(result) {\n            if (result && $.isFunction(result.then)) {\n                return result;\n            } else {\n                return null;\n            }\n        };\n\n        Tour.prototype._callOnPromiseDone = function(promise, cb, arg) {\n            if (promise) {\n                return promise.then((function(_this) {\n                    return function(e) {\n                        return cb.call(_this, arg);\n                    };\n                })(this));\n            } else {\n                return cb.call(this, arg);\n            }\n        };\n\n        Tour.prototype._showBackdrop = function(element) {\n            if (this.backdrop.backgroundShown) {\n                return;\n            }\n            this.backdrop = $(\"<div/>\", {\n                \"class\": \"tour-backdrop\"\n            });\n            this.backdrop.backgroundShown = true;\n            return $(\"body\").append(this.backdrop);\n        };\n\n        Tour.prototype._hideBackdrop = function() {\n            this._hideOverlayElement();\n            return this._hideBackground();\n        };\n\n        Tour.prototype._hideBackground = function() {\n            this.backdrop.remove();\n            this.backdrop.overlay = null;\n            return this.backdrop.backgroundShown = false;\n        };\n\n        Tour.prototype._showOverlayElement = function(element) {\n            var $background, $element, offset;\n            $element = $(element);\n            if (!$element || $element.length === 0 || this.backdrop.overlayElementShown) {\n                return;\n            }\n            this.backdrop.overlayElementShown = true;\n            $background = $(\"<div/>\");\n            offset = $element.offset();\n            offset.top = offset.top;\n            offset.left = offset.left;\n            $background.width($element.innerWidth()).height($element.innerHeight()).addClass(\"tour-step-background\").offset(offset);\n            $element.addClass(\"tour-step-backdrop\");\n            $(\"body\").append($background);\n            this.backdrop.$element = $element;\n            return this.backdrop.$background = $background;\n        };\n\n        Tour.prototype._hideOverlayElement = function() {\n            if (!this.backdrop.overlayElementShown) {\n                return;\n            }\n            this.backdrop.$element.removeClass(\"tour-step-backdrop\");\n            this.backdrop.$background.remove();\n            this.backdrop.$element = null;\n            this.backdrop.$background = null;\n            return this.backdrop.overlayElementShown = false;\n        };\n\n        Tour.prototype._clearTimer = function() {\n            window.clearTimeout(this._timer);\n            this._timer = null;\n            return this._duration = null;\n        };\n\n        return Tour;\n\n    })();\n    return window.Tour = Tour;\n})(jQuery, window);"
  },
  {
    "path": "flowable-ui-web/modeler/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": "flowable-ui-web/modeler/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": "flowable-ui-web/modeler/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": "flowable-ui-web/modeler/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": "flowable-ui-web/modeler/libs/es5-shim-15.3.4.5/.gitignore",
    "content": "node_modules\n.DS_Store\n"
  },
  {
    "path": "flowable-ui-web/modeler/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": "flowable-ui-web/modeler/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": "flowable-ui-web/modeler/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": "flowable-ui-web/modeler/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": "flowable-ui-web/modeler/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": "flowable-ui-web/modeler/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": "flowable-ui-web/modeler/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": "flowable-ui-web/modeler/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": "flowable-ui-web/modeler/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": "flowable-ui-web/modeler/libs/es5-shim-15.3.4.5/tests/helpers/h.js",
    "content": "function implement() {\n    throw 'Not implemented';\n}"
  },
  {
    "path": "flowable-ui-web/modeler/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": "flowable-ui-web/modeler/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": "flowable-ui-web/modeler/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": "flowable-ui-web/modeler/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": "flowable-ui-web/modeler/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": "flowable-ui-web/modeler/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": "flowable-ui-web/modeler/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": "flowable-ui-web/modeler/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": "flowable-ui-web/modeler/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": "flowable-ui-web/modeler/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": "flowable-ui-web/modeler/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": "flowable-ui-web/modeler/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": "flowable-ui-web/modeler/libs/html2canvas_0.4.1/html2canvas.js",
    "content": "/*\n  html2canvas 0.4.1 <http://html2canvas.hertzen.com>\n  Copyright (c) 2013 Niklas von Hertzen\n\n  Released under MIT License\n*/\n\n(function(window, document, undefined){\n\n\"use strict\";\n\nvar _html2canvas = {},\npreviousElement,\ncomputedCSS,\nhtml2canvas;\n\n_html2canvas.Util = {};\n\n_html2canvas.Util.log = function(a) {\n  if (_html2canvas.logging && window.console && window.console.log) {\n    window.console.log(a);\n  }\n};\n\n_html2canvas.Util.trimText = (function(isNative){\n  return function(input) {\n    return isNative ? isNative.apply(input) : ((input || '') + '').replace( /^\\s+|\\s+$/g , '' );\n  };\n})(String.prototype.trim);\n\n_html2canvas.Util.asFloat = function(v) {\n  return parseFloat(v);\n};\n\n(function() {\n  // TODO: support all possible length values\n  var TEXT_SHADOW_PROPERTY = /((rgba|rgb)\\([^\\)]+\\)(\\s-?\\d+px){0,})/g;\n  var TEXT_SHADOW_VALUES = /(-?\\d+px)|(#.+)|(rgb\\(.+\\))|(rgba\\(.+\\))/g;\n  _html2canvas.Util.parseTextShadows = function (value) {\n    if (!value || value === 'none') {\n      return [];\n    }\n\n    // find multiple shadow declarations\n    var shadows = value.match(TEXT_SHADOW_PROPERTY),\n      results = [];\n    for (var i = 0; shadows && (i < shadows.length); i++) {\n      var s = shadows[i].match(TEXT_SHADOW_VALUES);\n      results.push({\n        color: s[0],\n        offsetX: s[1] ? s[1].replace('px', '') : 0,\n        offsetY: s[2] ? s[2].replace('px', '') : 0,\n        blur: s[3] ? s[3].replace('px', '') : 0\n      });\n    }\n    return results;\n  };\n})();\n\n\n_html2canvas.Util.parseBackgroundImage = function (value) {\n    var whitespace = ' \\r\\n\\t',\n        method, definition, prefix, prefix_i, block, results = [],\n        c, mode = 0, numParen = 0, quote, args;\n\n    var appendResult = function(){\n        if(method) {\n            if(definition.substr( 0, 1 ) === '\"') {\n                definition = definition.substr( 1, definition.length - 2 );\n            }\n            if(definition) {\n                args.push(definition);\n            }\n            if(method.substr( 0, 1 ) === '-' &&\n                    (prefix_i = method.indexOf( '-', 1 ) + 1) > 0) {\n                prefix = method.substr( 0, prefix_i);\n                method = method.substr( prefix_i );\n            }\n            results.push({\n                prefix: prefix,\n                method: method.toLowerCase(),\n                value: block,\n                args: args\n            });\n        }\n        args = []; //for some odd reason, setting .length = 0 didn't work in safari\n        method =\n            prefix =\n            definition =\n            block = '';\n    };\n\n    appendResult();\n    for(var i = 0, ii = value.length; i<ii; i++) {\n        c = value[i];\n        if(mode === 0 && whitespace.indexOf( c ) > -1){\n            continue;\n        }\n        switch(c) {\n            case '\"':\n                if(!quote) {\n                    quote = c;\n                }\n                else if(quote === c) {\n                    quote = null;\n                }\n                break;\n\n            case '(':\n                if(quote) { break; }\n                else if(mode === 0) {\n                    mode = 1;\n                    block += c;\n                    continue;\n                } else {\n                    numParen++;\n                }\n                break;\n\n            case ')':\n                if(quote) { break; }\n                else if(mode === 1) {\n                    if(numParen === 0) {\n                        mode = 0;\n                        block += c;\n                        appendResult();\n                        continue;\n                    } else {\n                        numParen--;\n                    }\n                }\n                break;\n\n            case ',':\n                if(quote) { break; }\n                else if(mode === 0) {\n                    appendResult();\n                    continue;\n                }\n                else if (mode === 1) {\n                    if(numParen === 0 && !method.match(/^url$/i)) {\n                        args.push(definition);\n                        definition = '';\n                        block += c;\n                        continue;\n                    }\n                }\n                break;\n        }\n\n        block += c;\n        if(mode === 0) { method += c; }\n        else { definition += c; }\n    }\n    appendResult();\n\n    return results;\n};\n\n_html2canvas.Util.Bounds = function (element) {\n  var clientRect, bounds = {};\n\n  if (element.getBoundingClientRect){\n    clientRect = element.getBoundingClientRect();\n\n    // TODO add scroll position to bounds, so no scrolling of window necessary\n    bounds.top = clientRect.top;\n    bounds.bottom = clientRect.bottom || (clientRect.top + clientRect.height);\n    bounds.left = clientRect.left;\n\n    bounds.width = element.offsetWidth;\n    bounds.height = element.offsetHeight;\n  }\n\n  return bounds;\n};\n\n// TODO ideally, we'd want everything to go through this function instead of Util.Bounds,\n// but would require further work to calculate the correct positions for elements with offsetParents\n_html2canvas.Util.OffsetBounds = function (element) {\n  var parent = element.offsetParent ? _html2canvas.Util.OffsetBounds(element.offsetParent) : {top: 0, left: 0};\n\n  return {\n    top: element.offsetTop + parent.top,\n    bottom: element.offsetTop + element.offsetHeight + parent.top,\n    left: element.offsetLeft + parent.left,\n    width: element.offsetWidth,\n    height: element.offsetHeight\n  };\n};\n\nfunction toPX(element, attribute, value ) {\n    var rsLeft = element.runtimeStyle && element.runtimeStyle[attribute],\n        left,\n        style = element.style;\n\n    // Check if we are not dealing with pixels, (Opera has issues with this)\n    // Ported from jQuery css.js\n    // From the awesome hack by Dean Edwards\n    // http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291\n\n    // If we're not dealing with a regular pixel number\n    // but a number that has a weird ending, we need to convert it to pixels\n\n    if ( !/^-?[0-9]+\\.?[0-9]*(?:px)?$/i.test( value ) && /^-?\\d/.test(value) ) {\n        // Remember the original values\n        left = style.left;\n\n        // Put in the new values to get a computed value out\n        if (rsLeft) {\n            element.runtimeStyle.left = element.currentStyle.left;\n        }\n        style.left = attribute === \"fontSize\" ? \"1em\" : (value || 0);\n        value = style.pixelLeft + \"px\";\n\n        // Revert the changed values\n        style.left = left;\n        if (rsLeft) {\n            element.runtimeStyle.left = rsLeft;\n        }\n    }\n\n    if (!/^(thin|medium|thick)$/i.test(value)) {\n        return Math.round(parseFloat(value)) + \"px\";\n    }\n\n    return value;\n}\n\nfunction asInt(val) {\n    return parseInt(val, 10);\n}\n\nfunction parseBackgroundSizePosition(value, element, attribute, index) {\n    value = (value || '').split(',');\n    value = value[index || 0] || value[0] || 'auto';\n    value = _html2canvas.Util.trimText(value).split(' ');\n\n    if(attribute === 'backgroundSize' && (!value[0] || value[0].match(/cover|contain|auto/))) {\n        //these values will be handled in the parent function\n    } else {\n        value[0] = (value[0].indexOf( \"%\" ) === -1) ? toPX(element, attribute + \"X\", value[0]) : value[0];\n        if(value[1] === undefined) {\n            if(attribute === 'backgroundSize') {\n                value[1] = 'auto';\n                return value;\n            } else {\n                // IE 9 doesn't return double digit always\n                value[1] = value[0];\n            }\n        }\n        value[1] = (value[1].indexOf(\"%\") === -1) ? toPX(element, attribute + \"Y\", value[1]) : value[1];\n    }\n    return value;\n}\n\n_html2canvas.Util.getCSS = function (element, attribute, index) {\n    if (previousElement !== element) {\n      computedCSS = document.defaultView.getComputedStyle(element, null);\n    }\n\n    var value = computedCSS[attribute];\n\n    if (/^background(Size|Position)$/.test(attribute)) {\n        return parseBackgroundSizePosition(value, element, attribute, index);\n    } else if (/border(Top|Bottom)(Left|Right)Radius/.test(attribute)) {\n      var arr = value.split(\" \");\n      if (arr.length <= 1) {\n          arr[1] = arr[0];\n      }\n      return arr.map(asInt);\n    }\n\n  return value;\n};\n\n_html2canvas.Util.resizeBounds = function( current_width, current_height, target_width, target_height, stretch_mode ){\n  var target_ratio = target_width / target_height,\n    current_ratio = current_width / current_height,\n    output_width, output_height;\n\n  if(!stretch_mode || stretch_mode === 'auto') {\n    output_width = target_width;\n    output_height = target_height;\n  } else if(target_ratio < current_ratio ^ stretch_mode === 'contain') {\n    output_height = target_height;\n    output_width = target_height * current_ratio;\n  } else {\n    output_width = target_width;\n    output_height = target_width / current_ratio;\n  }\n\n  return {\n    width: output_width,\n    height: output_height\n  };\n};\n\nfunction backgroundBoundsFactory( prop, el, bounds, image, imageIndex, backgroundSize ) {\n    var bgposition =  _html2canvas.Util.getCSS( el, prop, imageIndex ) ,\n    topPos,\n    left,\n    percentage,\n    val;\n\n    if (bgposition.length === 1){\n      val = bgposition[0];\n\n      bgposition = [];\n\n      bgposition[0] = val;\n      bgposition[1] = val;\n    }\n\n    if (bgposition[0].toString().indexOf(\"%\") !== -1){\n      percentage = (parseFloat(bgposition[0])/100);\n      left = bounds.width * percentage;\n      if(prop !== 'backgroundSize') {\n        left -= (backgroundSize || image).width*percentage;\n      }\n    } else {\n      if(prop === 'backgroundSize') {\n        if(bgposition[0] === 'auto') {\n          left = image.width;\n        } else {\n          if (/contain|cover/.test(bgposition[0])) {\n            var resized = _html2canvas.Util.resizeBounds(image.width, image.height, bounds.width, bounds.height, bgposition[0]);\n            left = resized.width;\n            topPos = resized.height;\n          } else {\n            left = parseInt(bgposition[0], 10);\n          }\n        }\n      } else {\n        left = parseInt( bgposition[0], 10);\n      }\n    }\n\n\n    if(bgposition[1] === 'auto') {\n      topPos = left / image.width * image.height;\n    } else if (bgposition[1].toString().indexOf(\"%\") !== -1){\n      percentage = (parseFloat(bgposition[1])/100);\n      topPos =  bounds.height * percentage;\n      if(prop !== 'backgroundSize') {\n        topPos -= (backgroundSize || image).height * percentage;\n      }\n\n    } else {\n      topPos = parseInt(bgposition[1],10);\n    }\n\n    return [left, topPos];\n}\n\n_html2canvas.Util.BackgroundPosition = function( el, bounds, image, imageIndex, backgroundSize ) {\n    var result = backgroundBoundsFactory( 'backgroundPosition', el, bounds, image, imageIndex, backgroundSize );\n    return { left: result[0], top: result[1] };\n};\n\n_html2canvas.Util.BackgroundSize = function( el, bounds, image, imageIndex ) {\n    var result = backgroundBoundsFactory( 'backgroundSize', el, bounds, image, imageIndex );\n    return { width: result[0], height: result[1] };\n};\n\n_html2canvas.Util.Extend = function (options, defaults) {\n  for (var key in options) {\n    if (options.hasOwnProperty(key)) {\n      defaults[key] = options[key];\n    }\n  }\n  return defaults;\n};\n\n\n/*\n * Derived from jQuery.contents()\n * Copyright 2010, John Resig\n * Dual licensed under the MIT or GPL Version 2 licenses.\n * http://jquery.org/license\n */\n_html2canvas.Util.Children = function( elem ) {\n  var children;\n  try {\n    children = (elem.nodeName && elem.nodeName.toUpperCase() === \"IFRAME\") ? elem.contentDocument || elem.contentWindow.document : (function(array) {\n      var ret = [];\n      if (array !== null) {\n        (function(first, second ) {\n          var i = first.length,\n          j = 0;\n\n          if (typeof second.length === \"number\") {\n            for (var l = second.length; j < l; j++) {\n              first[i++] = second[j];\n            }\n          } else {\n            while (second[j] !== undefined) {\n              first[i++] = second[j++];\n            }\n          }\n\n          first.length = i;\n\n          return first;\n        })(ret, array);\n      }\n      return ret;\n    })(elem.childNodes);\n\n  } catch (ex) {\n    _html2canvas.Util.log(\"html2canvas.Util.Children failed with exception: \" + ex.message);\n    children = [];\n  }\n  return children;\n};\n\n_html2canvas.Util.isTransparent = function(backgroundColor) {\n  return (backgroundColor === \"transparent\" || backgroundColor === \"rgba(0, 0, 0, 0)\");\n};\n_html2canvas.Util.Font = (function () {\n\n  var fontData = {};\n\n  return function(font, fontSize, doc) {\n    if (fontData[font + \"-\" + fontSize] !== undefined) {\n      return fontData[font + \"-\" + fontSize];\n    }\n\n    var container = doc.createElement('div'),\n    img = doc.createElement('img'),\n    span = doc.createElement('span'),\n    sampleText = 'Hidden Text',\n    baseline,\n    middle,\n    metricsObj;\n\n    container.style.visibility = \"hidden\";\n    container.style.fontFamily = font;\n    container.style.fontSize = fontSize;\n    container.style.margin = 0;\n    container.style.padding = 0;\n\n    doc.body.appendChild(container);\n\n    // http://probablyprogramming.com/2009/03/15/the-tiniest-gif-ever (handtinywhite.gif)\n    img.src = \"data:image/gif;base64,R0lGODlhAQABAIABAP///wAAACwAAAAAAQABAAACAkQBADs=\";\n    img.width = 1;\n    img.height = 1;\n\n    img.style.margin = 0;\n    img.style.padding = 0;\n    img.style.verticalAlign = \"baseline\";\n\n    span.style.fontFamily = font;\n    span.style.fontSize = fontSize;\n    span.style.margin = 0;\n    span.style.padding = 0;\n\n    span.appendChild(doc.createTextNode(sampleText));\n    container.appendChild(span);\n    container.appendChild(img);\n    baseline = (img.offsetTop - span.offsetTop) + 1;\n\n    container.removeChild(span);\n    container.appendChild(doc.createTextNode(sampleText));\n\n    container.style.lineHeight = \"normal\";\n    img.style.verticalAlign = \"super\";\n\n    middle = (img.offsetTop-container.offsetTop) + 1;\n    metricsObj = {\n      baseline: baseline,\n      lineWidth: 1,\n      middle: middle\n    };\n\n    fontData[font + \"-\" + fontSize] = metricsObj;\n\n    doc.body.removeChild(container);\n\n    return metricsObj;\n  };\n})();\n\n(function(){\n  var Util = _html2canvas.Util,\n    Generate = {};\n\n  _html2canvas.Generate = Generate;\n\n  var reGradients = [\n  /^(-webkit-linear-gradient)\\(([a-z\\s]+)([\\w\\d\\.\\s,%\\(\\)]+)\\)$/,\n  /^(-o-linear-gradient)\\(([a-z\\s]+)([\\w\\d\\.\\s,%\\(\\)]+)\\)$/,\n  /^(-webkit-gradient)\\((linear|radial),\\s((?:\\d{1,3}%?)\\s(?:\\d{1,3}%?),\\s(?:\\d{1,3}%?)\\s(?:\\d{1,3}%?))([\\w\\d\\.\\s,%\\(\\)\\-]+)\\)$/,\n  /^(-moz-linear-gradient)\\(((?:\\d{1,3}%?)\\s(?:\\d{1,3}%?))([\\w\\d\\.\\s,%\\(\\)]+)\\)$/,\n  /^(-webkit-radial-gradient)\\(((?:\\d{1,3}%?)\\s(?:\\d{1,3}%?)),\\s(\\w+)\\s([a-z\\-]+)([\\w\\d\\.\\s,%\\(\\)]+)\\)$/,\n  /^(-moz-radial-gradient)\\(((?:\\d{1,3}%?)\\s(?:\\d{1,3}%?)),\\s(\\w+)\\s?([a-z\\-]*)([\\w\\d\\.\\s,%\\(\\)]+)\\)$/,\n  /^(-o-radial-gradient)\\(((?:\\d{1,3}%?)\\s(?:\\d{1,3}%?)),\\s(\\w+)\\s([a-z\\-]+)([\\w\\d\\.\\s,%\\(\\)]+)\\)$/\n  ];\n\n  /*\n * TODO: Add IE10 vendor prefix (-ms) support\n * TODO: Add W3C gradient (linear-gradient) support\n * TODO: Add old Webkit -webkit-gradient(radial, ...) support\n * TODO: Maybe some RegExp optimizations are possible ;o)\n */\n  Generate.parseGradient = function(css, bounds) {\n    var gradient, i, len = reGradients.length, m1, stop, m2, m2Len, step, m3, tl,tr,br,bl;\n\n    for(i = 0; i < len; i+=1){\n      m1 = css.match(reGradients[i]);\n      if(m1) {\n        break;\n      }\n    }\n\n    if(m1) {\n      switch(m1[1]) {\n        case '-webkit-linear-gradient':\n        case '-o-linear-gradient':\n\n          gradient = {\n            type: 'linear',\n            x0: null,\n            y0: null,\n            x1: null,\n            y1: null,\n            colorStops: []\n          };\n\n          // get coordinates\n          m2 = m1[2].match(/\\w+/g);\n          if(m2){\n            m2Len = m2.length;\n            for(i = 0; i < m2Len; i+=1){\n              switch(m2[i]) {\n                case 'top':\n                  gradient.y0 = 0;\n                  gradient.y1 = bounds.height;\n                  break;\n\n                case 'right':\n                  gradient.x0 = bounds.width;\n                  gradient.x1 = 0;\n                  break;\n\n                case 'bottom':\n                  gradient.y0 = bounds.height;\n                  gradient.y1 = 0;\n                  break;\n\n                case 'left':\n                  gradient.x0 = 0;\n                  gradient.x1 = bounds.width;\n                  break;\n              }\n            }\n          }\n          if(gradient.x0 === null && gradient.x1 === null){ // center\n            gradient.x0 = gradient.x1 = bounds.width / 2;\n          }\n          if(gradient.y0 === null && gradient.y1 === null){ // center\n            gradient.y0 = gradient.y1 = bounds.height / 2;\n          }\n\n          // get colors and stops\n          m2 = m1[3].match(/((?:rgb|rgba)\\(\\d{1,3},\\s\\d{1,3},\\s\\d{1,3}(?:,\\s[0-9\\.]+)?\\)(?:\\s\\d{1,3}(?:%|px))?)+/g);\n          if(m2){\n            m2Len = m2.length;\n            step = 1 / Math.max(m2Len - 1, 1);\n            for(i = 0; i < m2Len; i+=1){\n              m3 = m2[i].match(/((?:rgb|rgba)\\(\\d{1,3},\\s\\d{1,3},\\s\\d{1,3}(?:,\\s[0-9\\.]+)?\\))\\s*(\\d{1,3})?(%|px)?/);\n              if(m3[2]){\n                stop = parseFloat(m3[2]);\n                if(m3[3] === '%'){\n                  stop /= 100;\n                } else { // px - stupid opera\n                  stop /= bounds.width;\n                }\n              } else {\n                stop = i * step;\n              }\n              gradient.colorStops.push({\n                color: m3[1],\n                stop: stop\n              });\n            }\n          }\n          break;\n\n        case '-webkit-gradient':\n\n          gradient = {\n            type: m1[2] === 'radial' ? 'circle' : m1[2], // TODO: Add radial gradient support for older mozilla definitions\n            x0: 0,\n            y0: 0,\n            x1: 0,\n            y1: 0,\n            colorStops: []\n          };\n\n          // get coordinates\n          m2 = m1[3].match(/(\\d{1,3})%?\\s(\\d{1,3})%?,\\s(\\d{1,3})%?\\s(\\d{1,3})%?/);\n          if(m2){\n            gradient.x0 = (m2[1] * bounds.width) / 100;\n            gradient.y0 = (m2[2] * bounds.height) / 100;\n            gradient.x1 = (m2[3] * bounds.width) / 100;\n            gradient.y1 = (m2[4] * bounds.height) / 100;\n          }\n\n          // get colors and stops\n          m2 = m1[4].match(/((?:from|to|color-stop)\\((?:[0-9\\.]+,\\s)?(?:rgb|rgba)\\(\\d{1,3},\\s\\d{1,3},\\s\\d{1,3}(?:,\\s[0-9\\.]+)?\\)\\))+/g);\n          if(m2){\n            m2Len = m2.length;\n            for(i = 0; i < m2Len; i+=1){\n              m3 = m2[i].match(/(from|to|color-stop)\\(([0-9\\.]+)?(?:,\\s)?((?:rgb|rgba)\\(\\d{1,3},\\s\\d{1,3},\\s\\d{1,3}(?:,\\s[0-9\\.]+)?\\))\\)/);\n              stop = parseFloat(m3[2]);\n              if(m3[1] === 'from') {\n                stop = 0.0;\n              }\n              if(m3[1] === 'to') {\n                stop = 1.0;\n              }\n              gradient.colorStops.push({\n                color: m3[3],\n                stop: stop\n              });\n            }\n          }\n          break;\n\n        case '-moz-linear-gradient':\n\n          gradient = {\n            type: 'linear',\n            x0: 0,\n            y0: 0,\n            x1: 0,\n            y1: 0,\n            colorStops: []\n          };\n\n          // get coordinates\n          m2 = m1[2].match(/(\\d{1,3})%?\\s(\\d{1,3})%?/);\n\n          // m2[1] == 0%   -> left\n          // m2[1] == 50%  -> center\n          // m2[1] == 100% -> right\n\n          // m2[2] == 0%   -> top\n          // m2[2] == 50%  -> center\n          // m2[2] == 100% -> bottom\n\n          if(m2){\n            gradient.x0 = (m2[1] * bounds.width) / 100;\n            gradient.y0 = (m2[2] * bounds.height) / 100;\n            gradient.x1 = bounds.width - gradient.x0;\n            gradient.y1 = bounds.height - gradient.y0;\n          }\n\n          // get colors and stops\n          m2 = m1[3].match(/((?:rgb|rgba)\\(\\d{1,3},\\s\\d{1,3},\\s\\d{1,3}(?:,\\s[0-9\\.]+)?\\)(?:\\s\\d{1,3}%)?)+/g);\n          if(m2){\n            m2Len = m2.length;\n            step = 1 / Math.max(m2Len - 1, 1);\n            for(i = 0; i < m2Len; i+=1){\n              m3 = m2[i].match(/((?:rgb|rgba)\\(\\d{1,3},\\s\\d{1,3},\\s\\d{1,3}(?:,\\s[0-9\\.]+)?\\))\\s*(\\d{1,3})?(%)?/);\n              if(m3[2]){\n                stop = parseFloat(m3[2]);\n                if(m3[3]){ // percentage\n                  stop /= 100;\n                }\n              } else {\n                stop = i * step;\n              }\n              gradient.colorStops.push({\n                color: m3[1],\n                stop: stop\n              });\n            }\n          }\n          break;\n\n        case '-webkit-radial-gradient':\n        case '-moz-radial-gradient':\n        case '-o-radial-gradient':\n\n          gradient = {\n            type: 'circle',\n            x0: 0,\n            y0: 0,\n            x1: bounds.width,\n            y1: bounds.height,\n            cx: 0,\n            cy: 0,\n            rx: 0,\n            ry: 0,\n            colorStops: []\n          };\n\n          // center\n          m2 = m1[2].match(/(\\d{1,3})%?\\s(\\d{1,3})%?/);\n          if(m2){\n            gradient.cx = (m2[1] * bounds.width) / 100;\n            gradient.cy = (m2[2] * bounds.height) / 100;\n          }\n\n          // size\n          m2 = m1[3].match(/\\w+/);\n          m3 = m1[4].match(/[a-z\\-]*/);\n          if(m2 && m3){\n            switch(m3[0]){\n              case 'farthest-corner':\n              case 'cover': // is equivalent to farthest-corner\n              case '': // mozilla removes \"cover\" from definition :(\n                tl = Math.sqrt(Math.pow(gradient.cx, 2) + Math.pow(gradient.cy, 2));\n                tr = Math.sqrt(Math.pow(gradient.cx, 2) + Math.pow(gradient.y1 - gradient.cy, 2));\n                br = Math.sqrt(Math.pow(gradient.x1 - gradient.cx, 2) + Math.pow(gradient.y1 - gradient.cy, 2));\n                bl = Math.sqrt(Math.pow(gradient.x1 - gradient.cx, 2) + Math.pow(gradient.cy, 2));\n                gradient.rx = gradient.ry = Math.max(tl, tr, br, bl);\n                break;\n              case 'closest-corner':\n                tl = Math.sqrt(Math.pow(gradient.cx, 2) + Math.pow(gradient.cy, 2));\n                tr = Math.sqrt(Math.pow(gradient.cx, 2) + Math.pow(gradient.y1 - gradient.cy, 2));\n                br = Math.sqrt(Math.pow(gradient.x1 - gradient.cx, 2) + Math.pow(gradient.y1 - gradient.cy, 2));\n                bl = Math.sqrt(Math.pow(gradient.x1 - gradient.cx, 2) + Math.pow(gradient.cy, 2));\n                gradient.rx = gradient.ry = Math.min(tl, tr, br, bl);\n                break;\n              case 'farthest-side':\n                if(m2[0] === 'circle'){\n                  gradient.rx = gradient.ry = Math.max(\n                    gradient.cx,\n                    gradient.cy,\n                    gradient.x1 - gradient.cx,\n                    gradient.y1 - gradient.cy\n                    );\n                } else { // ellipse\n\n                  gradient.type = m2[0];\n\n                  gradient.rx = Math.max(\n                    gradient.cx,\n                    gradient.x1 - gradient.cx\n                    );\n                  gradient.ry = Math.max(\n                    gradient.cy,\n                    gradient.y1 - gradient.cy\n                    );\n                }\n                break;\n              case 'closest-side':\n              case 'contain': // is equivalent to closest-side\n                if(m2[0] === 'circle'){\n                  gradient.rx = gradient.ry = Math.min(\n                    gradient.cx,\n                    gradient.cy,\n                    gradient.x1 - gradient.cx,\n                    gradient.y1 - gradient.cy\n                    );\n                } else { // ellipse\n\n                  gradient.type = m2[0];\n\n                  gradient.rx = Math.min(\n                    gradient.cx,\n                    gradient.x1 - gradient.cx\n                    );\n                  gradient.ry = Math.min(\n                    gradient.cy,\n                    gradient.y1 - gradient.cy\n                    );\n                }\n                break;\n\n            // TODO: add support for \"30px 40px\" sizes (webkit only)\n            }\n          }\n\n          // color stops\n          m2 = m1[5].match(/((?:rgb|rgba)\\(\\d{1,3},\\s\\d{1,3},\\s\\d{1,3}(?:,\\s[0-9\\.]+)?\\)(?:\\s\\d{1,3}(?:%|px))?)+/g);\n          if(m2){\n            m2Len = m2.length;\n            step = 1 / Math.max(m2Len - 1, 1);\n            for(i = 0; i < m2Len; i+=1){\n              m3 = m2[i].match(/((?:rgb|rgba)\\(\\d{1,3},\\s\\d{1,3},\\s\\d{1,3}(?:,\\s[0-9\\.]+)?\\))\\s*(\\d{1,3})?(%|px)?/);\n              if(m3[2]){\n                stop = parseFloat(m3[2]);\n                if(m3[3] === '%'){\n                  stop /= 100;\n                } else { // px - stupid opera\n                  stop /= bounds.width;\n                }\n              } else {\n                stop = i * step;\n              }\n              gradient.colorStops.push({\n                color: m3[1],\n                stop: stop\n              });\n            }\n          }\n          break;\n      }\n    }\n\n    return gradient;\n  };\n\n  function addScrollStops(grad) {\n    return function(colorStop) {\n      try {\n        grad.addColorStop(colorStop.stop, colorStop.color);\n      }\n      catch(e) {\n        Util.log(['failed to add color stop: ', e, '; tried to add: ', colorStop]);\n      }\n    };\n  }\n\n  Generate.Gradient = function(src, bounds) {\n    if(bounds.width === 0 || bounds.height === 0) {\n      return;\n    }\n\n    var canvas = document.createElement('canvas'),\n    ctx = canvas.getContext('2d'),\n    gradient, grad;\n\n    canvas.width = bounds.width;\n    canvas.height = bounds.height;\n\n    // TODO: add support for multi defined background gradients\n    gradient = _html2canvas.Generate.parseGradient(src, bounds);\n\n    if(gradient) {\n      switch(gradient.type) {\n        case 'linear':\n          grad = ctx.createLinearGradient(gradient.x0, gradient.y0, gradient.x1, gradient.y1);\n          gradient.colorStops.forEach(addScrollStops(grad));\n          ctx.fillStyle = grad;\n          ctx.fillRect(0, 0, bounds.width, bounds.height);\n          break;\n\n        case 'circle':\n          grad = ctx.createRadialGradient(gradient.cx, gradient.cy, 0, gradient.cx, gradient.cy, gradient.rx);\n          gradient.colorStops.forEach(addScrollStops(grad));\n          ctx.fillStyle = grad;\n          ctx.fillRect(0, 0, bounds.width, bounds.height);\n          break;\n\n        case 'ellipse':\n          var canvasRadial = document.createElement('canvas'),\n            ctxRadial = canvasRadial.getContext('2d'),\n            ri = Math.max(gradient.rx, gradient.ry),\n            di = ri * 2;\n\n          canvasRadial.width = canvasRadial.height = di;\n\n          grad = ctxRadial.createRadialGradient(gradient.rx, gradient.ry, 0, gradient.rx, gradient.ry, ri);\n          gradient.colorStops.forEach(addScrollStops(grad));\n\n          ctxRadial.fillStyle = grad;\n          ctxRadial.fillRect(0, 0, di, di);\n\n          ctx.fillStyle = gradient.colorStops[gradient.colorStops.length - 1].color;\n          ctx.fillRect(0, 0, canvas.width, canvas.height);\n          ctx.drawImage(canvasRadial, gradient.cx - gradient.rx, gradient.cy - gradient.ry, 2 * gradient.rx, 2 * gradient.ry);\n          break;\n      }\n    }\n\n    return canvas;\n  };\n\n  Generate.ListAlpha = function(number) {\n    var tmp = \"\",\n    modulus;\n\n    do {\n      modulus = number % 26;\n      tmp = String.fromCharCode((modulus) + 64) + tmp;\n      number = number / 26;\n    }while((number*26) > 26);\n\n    return tmp;\n  };\n\n  Generate.ListRoman = function(number) {\n    var romanArray = [\"M\", \"CM\", \"D\", \"CD\", \"C\", \"XC\", \"L\", \"XL\", \"X\", \"IX\", \"V\", \"IV\", \"I\"],\n    decimal = [1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1],\n    roman = \"\",\n    v,\n    len = romanArray.length;\n\n    if (number <= 0 || number >= 4000) {\n      return number;\n    }\n\n    for (v=0; v < len; v+=1) {\n      while (number >= decimal[v]) {\n        number -= decimal[v];\n        roman += romanArray[v];\n      }\n    }\n\n    return roman;\n  };\n})();\nfunction h2cRenderContext(width, height) {\n  var storage = [];\n  return {\n    storage: storage,\n    width: width,\n    height: height,\n    clip: function() {\n      storage.push({\n        type: \"function\",\n        name: \"clip\",\n        'arguments': arguments\n      });\n    },\n    translate: function() {\n      storage.push({\n        type: \"function\",\n        name: \"translate\",\n        'arguments': arguments\n      });\n    },\n    fill: function() {\n      storage.push({\n        type: \"function\",\n        name: \"fill\",\n        'arguments': arguments\n      });\n    },\n    save: function() {\n      storage.push({\n        type: \"function\",\n        name: \"save\",\n        'arguments': arguments\n      });\n    },\n    restore: function() {\n      storage.push({\n        type: \"function\",\n        name: \"restore\",\n        'arguments': arguments\n      });\n    },\n    fillRect: function () {\n      storage.push({\n        type: \"function\",\n        name: \"fillRect\",\n        'arguments': arguments\n      });\n    },\n    createPattern: function() {\n      storage.push({\n        type: \"function\",\n        name: \"createPattern\",\n        'arguments': arguments\n      });\n    },\n    drawShape: function() {\n\n      var shape = [];\n\n      storage.push({\n        type: \"function\",\n        name: \"drawShape\",\n        'arguments': shape\n      });\n\n      return {\n        moveTo: function() {\n          shape.push({\n            name: \"moveTo\",\n            'arguments': arguments\n          });\n        },\n        lineTo: function() {\n          shape.push({\n            name: \"lineTo\",\n            'arguments': arguments\n          });\n        },\n        arcTo: function() {\n          shape.push({\n            name: \"arcTo\",\n            'arguments': arguments\n          });\n        },\n        bezierCurveTo: function() {\n          shape.push({\n            name: \"bezierCurveTo\",\n            'arguments': arguments\n          });\n        },\n        quadraticCurveTo: function() {\n          shape.push({\n            name: \"quadraticCurveTo\",\n            'arguments': arguments\n          });\n        }\n      };\n\n    },\n    drawImage: function () {\n      storage.push({\n        type: \"function\",\n        name: \"drawImage\",\n        'arguments': arguments\n      });\n    },\n    fillText: function () {\n      storage.push({\n        type: \"function\",\n        name: \"fillText\",\n        'arguments': arguments\n      });\n    },\n    setVariable: function (variable, value) {\n      storage.push({\n        type: \"variable\",\n        name: variable,\n        'arguments': value\n      });\n      return value;\n    }\n  };\n}\n_html2canvas.Parse = function (images, options) {\n  window.scroll(0,0);\n\n  var element = (( options.elements === undefined ) ? document.body : options.elements[0]), // select body by default\n  numDraws = 0,\n  doc = element.ownerDocument,\n  Util = _html2canvas.Util,\n  support = Util.Support(options, doc),\n  ignoreElementsRegExp = new RegExp(\"(\" + options.ignoreElements + \")\"),\n  body = doc.body,\n  getCSS = Util.getCSS,\n  pseudoHide = \"___html2canvas___pseudoelement\",\n  hidePseudoElements = doc.createElement('style');\n\n  hidePseudoElements.innerHTML = '.' + pseudoHide + '-before:before { content: \"\" !important; display: none !important; }' +\n  '.' + pseudoHide + '-after:after { content: \"\" !important; display: none !important; }';\n\n  body.appendChild(hidePseudoElements);\n\n  images = images || {};\n\n  function documentWidth () {\n    return Math.max(\n      Math.max(doc.body.scrollWidth, doc.documentElement.scrollWidth),\n      Math.max(doc.body.offsetWidth, doc.documentElement.offsetWidth),\n      Math.max(doc.body.clientWidth, doc.documentElement.clientWidth)\n      );\n  }\n\n  function documentHeight () {\n    return Math.max(\n      Math.max(doc.body.scrollHeight, doc.documentElement.scrollHeight),\n      Math.max(doc.body.offsetHeight, doc.documentElement.offsetHeight),\n      Math.max(doc.body.clientHeight, doc.documentElement.clientHeight)\n      );\n  }\n\n  function getCSSInt(element, attribute) {\n    var val = parseInt(getCSS(element, attribute), 10);\n    return (isNaN(val)) ? 0 : val; // borders in old IE are throwing 'medium' for demo.html\n  }\n\n  function renderRect (ctx, x, y, w, h, bgcolor) {\n    if (bgcolor !== \"transparent\"){\n      ctx.setVariable(\"fillStyle\", bgcolor);\n      ctx.fillRect(x, y, w, h);\n      numDraws+=1;\n    }\n  }\n\n  function capitalize(m, p1, p2) {\n    if (m.length > 0) {\n      return p1 + p2.toUpperCase();\n    }\n  }\n\n  function textTransform (text, transform) {\n    switch(transform){\n      case \"lowercase\":\n        return text.toLowerCase();\n      case \"capitalize\":\n        return text.replace( /(^|\\s|:|-|\\(|\\))([a-z])/g, capitalize);\n      case \"uppercase\":\n        return text.toUpperCase();\n      default:\n        return text;\n    }\n  }\n\n  function noLetterSpacing(letter_spacing) {\n    return (/^(normal|none|0px)$/.test(letter_spacing));\n  }\n\n  function drawText(currentText, x, y, ctx){\n    if (currentText !== null && Util.trimText(currentText).length > 0) {\n      ctx.fillText(currentText, x, y);\n      numDraws+=1;\n    }\n  }\n\n  function setTextVariables(ctx, el, text_decoration, color) {\n    var align = false,\n    bold = getCSS(el, \"fontWeight\"),\n    family = getCSS(el, \"fontFamily\"),\n    size = getCSS(el, \"fontSize\"),\n    shadows = Util.parseTextShadows(getCSS(el, \"textShadow\"));\n\n    switch(parseInt(bold, 10)){\n      case 401:\n        bold = \"bold\";\n        break;\n      case 400:\n        bold = \"normal\";\n        break;\n    }\n\n    ctx.setVariable(\"fillStyle\", color);\n    ctx.setVariable(\"font\", [getCSS(el, \"fontStyle\"), getCSS(el, \"fontVariant\"), bold, size, family].join(\" \"));\n    ctx.setVariable(\"textAlign\", (align) ? \"right\" : \"left\");\n\n    if (shadows.length) {\n      // TODO: support multiple text shadows\n      // apply the first text shadow\n      ctx.setVariable(\"shadowColor\", shadows[0].color);\n      ctx.setVariable(\"shadowOffsetX\", shadows[0].offsetX);\n      ctx.setVariable(\"shadowOffsetY\", shadows[0].offsetY);\n      ctx.setVariable(\"shadowBlur\", shadows[0].blur);\n    }\n\n    if (text_decoration !== \"none\"){\n      return Util.Font(family, size, doc);\n    }\n  }\n\n  function renderTextDecoration(ctx, text_decoration, bounds, metrics, color) {\n    switch(text_decoration) {\n      case \"underline\":\n        // Draws a line at the baseline of the font\n        // TODO As some browsers display the line as more than 1px if the font-size is big, need to take that into account both in position and size\n        renderRect(ctx, bounds.left, Math.round(bounds.top + metrics.baseline + metrics.lineWidth), bounds.width, 1, color);\n        break;\n      case \"overline\":\n        renderRect(ctx, bounds.left, Math.round(bounds.top), bounds.width, 1, color);\n        break;\n      case \"line-through\":\n        // TODO try and find exact position for line-through\n        renderRect(ctx, bounds.left, Math.ceil(bounds.top + metrics.middle + metrics.lineWidth), bounds.width, 1, color);\n        break;\n    }\n  }\n\n  function getTextBounds(state, text, textDecoration, isLast, transform) {\n    var bounds;\n    if (support.rangeBounds && !transform) {\n      if (textDecoration !== \"none\" || Util.trimText(text).length !== 0) {\n        bounds = textRangeBounds(text, state.node, state.textOffset);\n      }\n      state.textOffset += text.length;\n    } else if (state.node && typeof state.node.nodeValue === \"string\" ){\n      var newTextNode = (isLast) ? state.node.splitText(text.length) : null;\n      bounds = textWrapperBounds(state.node, transform);\n      state.node = newTextNode;\n    }\n    return bounds;\n  }\n\n  function textRangeBounds(text, textNode, textOffset) {\n    var range = doc.createRange();\n    range.setStart(textNode, textOffset);\n    range.setEnd(textNode, textOffset + text.length);\n    return range.getBoundingClientRect();\n  }\n\n  function textWrapperBounds(oldTextNode, transform) {\n    var parent = oldTextNode.parentNode,\n    wrapElement = doc.createElement('wrapper'),\n    backupText = oldTextNode.cloneNode(true);\n\n    wrapElement.appendChild(oldTextNode.cloneNode(true));\n    parent.replaceChild(wrapElement, oldTextNode);\n\n    var bounds = transform ? Util.OffsetBounds(wrapElement) : Util.Bounds(wrapElement);\n    parent.replaceChild(backupText, wrapElement);\n    return bounds;\n  }\n\n  function renderText(el, textNode, stack) {\n    var ctx = stack.ctx,\n    color = getCSS(el, \"color\"),\n    textDecoration = getCSS(el, \"textDecoration\"),\n    textAlign = getCSS(el, \"textAlign\"),\n    metrics,\n    textList,\n    state = {\n      node: textNode,\n      textOffset: 0\n    };\n\n    if (Util.trimText(textNode.nodeValue).length > 0) {\n      textNode.nodeValue = textTransform(textNode.nodeValue, getCSS(el, \"textTransform\"));\n      textAlign = textAlign.replace([\"-webkit-auto\"],[\"auto\"]);\n\n      textList = (!options.letterRendering && /^(left|right|justify|auto)$/.test(textAlign) && noLetterSpacing(getCSS(el, \"letterSpacing\"))) ?\n      textNode.nodeValue.split(/(\\b| )/)\n      : textNode.nodeValue.split(\"\");\n\n      metrics = setTextVariables(ctx, el, textDecoration, color);\n\n      if (options.chinese) {\n        textList.forEach(function(word, index) {\n          if (/.*[\\u4E00-\\u9FA5].*$/.test(word)) {\n            word = word.split(\"\");\n            word.unshift(index, 1);\n            textList.splice.apply(textList, word);\n          }\n        });\n      }\n\n      textList.forEach(function(text, index) {\n        var bounds = getTextBounds(state, text, textDecoration, (index < textList.length - 1), stack.transform.matrix);\n        if (bounds) {\n          drawText(text, bounds.left, bounds.bottom, ctx);\n          renderTextDecoration(ctx, textDecoration, bounds, metrics, color);\n        }\n      });\n    }\n  }\n\n  function listPosition (element, val) {\n    var boundElement = doc.createElement( \"boundelement\" ),\n    originalType,\n    bounds;\n\n    boundElement.style.display = \"inline\";\n\n    originalType = element.style.listStyleType;\n    element.style.listStyleType = \"none\";\n\n    boundElement.appendChild(doc.createTextNode(val));\n\n    element.insertBefore(boundElement, element.firstChild);\n\n    bounds = Util.Bounds(boundElement);\n    element.removeChild(boundElement);\n    element.style.listStyleType = originalType;\n    return bounds;\n  }\n\n  function elementIndex(el) {\n    var i = -1,\n    count = 1,\n    childs = el.parentNode.childNodes;\n\n    if (el.parentNode) {\n      while(childs[++i] !== el) {\n        if (childs[i].nodeType === 1) {\n          count++;\n        }\n      }\n      return count;\n    } else {\n      return -1;\n    }\n  }\n\n  function listItemText(element, type) {\n    var currentIndex = elementIndex(element), text;\n    switch(type){\n      case \"decimal\":\n        text = currentIndex;\n        break;\n      case \"decimal-leading-zero\":\n        text = (currentIndex.toString().length === 1) ? currentIndex = \"0\" + currentIndex.toString() : currentIndex.toString();\n        break;\n      case \"upper-roman\":\n        text = _html2canvas.Generate.ListRoman( currentIndex );\n        break;\n      case \"lower-roman\":\n        text = _html2canvas.Generate.ListRoman( currentIndex ).toLowerCase();\n        break;\n      case \"lower-alpha\":\n        text = _html2canvas.Generate.ListAlpha( currentIndex ).toLowerCase();\n        break;\n      case \"upper-alpha\":\n        text = _html2canvas.Generate.ListAlpha( currentIndex );\n        break;\n    }\n\n    return text + \". \";\n  }\n\n  function renderListItem(element, stack, elBounds) {\n    var x,\n    text,\n    ctx = stack.ctx,\n    type = getCSS(element, \"listStyleType\"),\n    listBounds;\n\n    if (/^(decimal|decimal-leading-zero|upper-alpha|upper-latin|upper-roman|lower-alpha|lower-greek|lower-latin|lower-roman)$/i.test(type)) {\n      text = listItemText(element, type);\n      listBounds = listPosition(element, text);\n      setTextVariables(ctx, element, \"none\", getCSS(element, \"color\"));\n\n      if (getCSS(element, \"listStylePosition\") === \"inside\") {\n        ctx.setVariable(\"textAlign\", \"left\");\n        x = elBounds.left;\n      } else {\n        return;\n      }\n\n      drawText(text, x, listBounds.bottom, ctx);\n    }\n  }\n\n  function loadImage (src){\n    var img = images[src];\n    return (img && img.succeeded === true) ? img.img : false;\n  }\n\n  function clipBounds(src, dst){\n    var x = Math.max(src.left, dst.left),\n    y = Math.max(src.top, dst.top),\n    x2 = Math.min((src.left + src.width), (dst.left + dst.width)),\n    y2 = Math.min((src.top + src.height), (dst.top + dst.height));\n\n    return {\n      left:x,\n      top:y,\n      width:x2-x,\n      height:y2-y\n    };\n  }\n\n  function setZ(element, stack, parentStack){\n    var newContext,\n    isPositioned = stack.cssPosition !== 'static',\n    zIndex = isPositioned ? getCSS(element, 'zIndex') : 'auto',\n    opacity = getCSS(element, 'opacity'),\n    isFloated = getCSS(element, 'cssFloat') !== 'none';\n\n    // https://developer.mozilla.org/en-US/docs/Web/Guide/CSS/Understanding_z_index/The_stacking_context\n    // When a new stacking context should be created:\n    // the root element (HTML),\n    // positioned (absolutely or relatively) with a z-index value other than \"auto\",\n    // elements with an opacity value less than 1. (See the specification for opacity),\n    // on mobile WebKit and Chrome 22+, position: fixed always creates a new stacking context, even when z-index is \"auto\" (See this post)\n\n    stack.zIndex = newContext = h2czContext(zIndex);\n    newContext.isPositioned = isPositioned;\n    newContext.isFloated = isFloated;\n    newContext.opacity = opacity;\n    newContext.ownStacking = (zIndex !== 'auto' || opacity < 1);\n\n    if (parentStack) {\n      parentStack.zIndex.children.push(stack);\n    }\n  }\n\n  function renderImage(ctx, element, image, bounds, borders) {\n\n    var paddingLeft = getCSSInt(element, 'paddingLeft'),\n    paddingTop = getCSSInt(element, 'paddingTop'),\n    paddingRight = getCSSInt(element, 'paddingRight'),\n    paddingBottom = getCSSInt(element, 'paddingBottom');\n\n    drawImage(\n      ctx,\n      image,\n      0, //sx\n      0, //sy\n      image.width, //sw\n      image.height, //sh\n      bounds.left + paddingLeft + borders[3].width, //dx\n      bounds.top + paddingTop + borders[0].width, // dy\n      bounds.width - (borders[1].width + borders[3].width + paddingLeft + paddingRight), //dw\n      bounds.height - (borders[0].width + borders[2].width + paddingTop + paddingBottom) //dh\n      );\n  }\n\n  function getBorderData(element) {\n    return [\"Top\", \"Right\", \"Bottom\", \"Left\"].map(function(side) {\n      return {\n        width: getCSSInt(element, 'border' + side + 'Width'),\n        color: getCSS(element, 'border' + side + 'Color')\n      };\n    });\n  }\n\n  function getBorderRadiusData(element) {\n    return [\"TopLeft\", \"TopRight\", \"BottomRight\", \"BottomLeft\"].map(function(side) {\n      return getCSS(element, 'border' + side + 'Radius');\n    });\n  }\n\n  var getCurvePoints = (function(kappa) {\n\n    return function(x, y, r1, r2) {\n      var ox = (r1) * kappa, // control point offset horizontal\n      oy = (r2) * kappa, // control point offset vertical\n      xm = x + r1, // x-middle\n      ym = y + r2; // y-middle\n      return {\n        topLeft: bezierCurve({\n          x:x,\n          y:ym\n        }, {\n          x:x,\n          y:ym - oy\n        }, {\n          x:xm - ox,\n          y:y\n        }, {\n          x:xm,\n          y:y\n        }),\n        topRight: bezierCurve({\n          x:x,\n          y:y\n        }, {\n          x:x + ox,\n          y:y\n        }, {\n          x:xm,\n          y:ym - oy\n        }, {\n          x:xm,\n          y:ym\n        }),\n        bottomRight: bezierCurve({\n          x:xm,\n          y:y\n        }, {\n          x:xm,\n          y:y + oy\n        }, {\n          x:x + ox,\n          y:ym\n        }, {\n          x:x,\n          y:ym\n        }),\n        bottomLeft: bezierCurve({\n          x:xm,\n          y:ym\n        }, {\n          x:xm - ox,\n          y:ym\n        }, {\n          x:x,\n          y:y + oy\n        }, {\n          x:x,\n          y:y\n        })\n      };\n    };\n  })(4 * ((Math.sqrt(2) - 1) / 3));\n\n  function bezierCurve(start, startControl, endControl, end) {\n\n    var lerp = function (a, b, t) {\n      return {\n        x:a.x + (b.x - a.x) * t,\n        y:a.y + (b.y - a.y) * t\n      };\n    };\n\n    return {\n      start: start,\n      startControl: startControl,\n      endControl: endControl,\n      end: end,\n      subdivide: function(t) {\n        var ab = lerp(start, startControl, t),\n        bc = lerp(startControl, endControl, t),\n        cd = lerp(endControl, end, t),\n        abbc = lerp(ab, bc, t),\n        bccd = lerp(bc, cd, t),\n        dest = lerp(abbc, bccd, t);\n        return [bezierCurve(start, ab, abbc, dest), bezierCurve(dest, bccd, cd, end)];\n      },\n      curveTo: function(borderArgs) {\n        borderArgs.push([\"bezierCurve\", startControl.x, startControl.y, endControl.x, endControl.y, end.x, end.y]);\n      },\n      curveToReversed: function(borderArgs) {\n        borderArgs.push([\"bezierCurve\", endControl.x, endControl.y, startControl.x, startControl.y, start.x, start.y]);\n      }\n    };\n  }\n\n  function parseCorner(borderArgs, radius1, radius2, corner1, corner2, x, y) {\n    if (radius1[0] > 0 || radius1[1] > 0) {\n      borderArgs.push([\"line\", corner1[0].start.x, corner1[0].start.y]);\n      corner1[0].curveTo(borderArgs);\n      corner1[1].curveTo(borderArgs);\n    } else {\n      borderArgs.push([\"line\", x, y]);\n    }\n\n    if (radius2[0] > 0 || radius2[1] > 0) {\n      borderArgs.push([\"line\", corner2[0].start.x, corner2[0].start.y]);\n    }\n  }\n\n  function drawSide(borderData, radius1, radius2, outer1, inner1, outer2, inner2) {\n    var borderArgs = [];\n\n    if (radius1[0] > 0 || radius1[1] > 0) {\n      borderArgs.push([\"line\", outer1[1].start.x, outer1[1].start.y]);\n      outer1[1].curveTo(borderArgs);\n    } else {\n      borderArgs.push([ \"line\", borderData.c1[0], borderData.c1[1]]);\n    }\n\n    if (radius2[0] > 0 || radius2[1] > 0) {\n      borderArgs.push([\"line\", outer2[0].start.x, outer2[0].start.y]);\n      outer2[0].curveTo(borderArgs);\n      borderArgs.push([\"line\", inner2[0].end.x, inner2[0].end.y]);\n      inner2[0].curveToReversed(borderArgs);\n    } else {\n      borderArgs.push([ \"line\", borderData.c2[0], borderData.c2[1]]);\n      borderArgs.push([ \"line\", borderData.c3[0], borderData.c3[1]]);\n    }\n\n    if (radius1[0] > 0 || radius1[1] > 0) {\n      borderArgs.push([\"line\", inner1[1].end.x, inner1[1].end.y]);\n      inner1[1].curveToReversed(borderArgs);\n    } else {\n      borderArgs.push([ \"line\", borderData.c4[0], borderData.c4[1]]);\n    }\n\n    return borderArgs;\n  }\n\n  function calculateCurvePoints(bounds, borderRadius, borders) {\n\n    var x = bounds.left,\n    y = bounds.top,\n    width = bounds.width,\n    height = bounds.height,\n\n    tlh = borderRadius[0][0],\n    tlv = borderRadius[0][1],\n    trh = borderRadius[1][0],\n    trv = borderRadius[1][1],\n    brh = borderRadius[2][0],\n    brv = borderRadius[2][1],\n    blh = borderRadius[3][0],\n    blv = borderRadius[3][1],\n\n    topWidth = width - trh,\n    rightHeight = height - brv,\n    bottomWidth = width - brh,\n    leftHeight = height - blv;\n\n    return {\n      topLeftOuter: getCurvePoints(\n        x,\n        y,\n        tlh,\n        tlv\n        ).topLeft.subdivide(0.5),\n\n      topLeftInner: getCurvePoints(\n        x + borders[3].width,\n        y + borders[0].width,\n        Math.max(0, tlh - borders[3].width),\n        Math.max(0, tlv - borders[0].width)\n        ).topLeft.subdivide(0.5),\n\n      topRightOuter: getCurvePoints(\n        x + topWidth,\n        y,\n        trh,\n        trv\n        ).topRight.subdivide(0.5),\n\n      topRightInner: getCurvePoints(\n        x + Math.min(topWidth, width + borders[3].width),\n        y + borders[0].width,\n        (topWidth > width + borders[3].width) ? 0 :trh - borders[3].width,\n        trv - borders[0].width\n        ).topRight.subdivide(0.5),\n\n      bottomRightOuter: getCurvePoints(\n        x + bottomWidth,\n        y + rightHeight,\n        brh,\n        brv\n        ).bottomRight.subdivide(0.5),\n\n      bottomRightInner: getCurvePoints(\n        x + Math.min(bottomWidth, width + borders[3].width),\n        y + Math.min(rightHeight, height + borders[0].width),\n        Math.max(0, brh - borders[1].width),\n        Math.max(0, brv - borders[2].width)\n        ).bottomRight.subdivide(0.5),\n\n      bottomLeftOuter: getCurvePoints(\n        x,\n        y + leftHeight,\n        blh,\n        blv\n        ).bottomLeft.subdivide(0.5),\n\n      bottomLeftInner: getCurvePoints(\n        x + borders[3].width,\n        y + leftHeight,\n        Math.max(0, blh - borders[3].width),\n        Math.max(0, blv - borders[2].width)\n        ).bottomLeft.subdivide(0.5)\n    };\n  }\n\n  function getBorderClip(element, borderPoints, borders, radius, bounds) {\n    var backgroundClip = getCSS(element, 'backgroundClip'),\n    borderArgs = [];\n\n    switch(backgroundClip) {\n      case \"content-box\":\n      case \"padding-box\":\n        parseCorner(borderArgs, radius[0], radius[1], borderPoints.topLeftInner, borderPoints.topRightInner, bounds.left + borders[3].width, bounds.top + borders[0].width);\n        parseCorner(borderArgs, radius[1], radius[2], borderPoints.topRightInner, borderPoints.bottomRightInner, bounds.left + bounds.width - borders[1].width, bounds.top + borders[0].width);\n        parseCorner(borderArgs, radius[2], radius[3], borderPoints.bottomRightInner, borderPoints.bottomLeftInner, bounds.left + bounds.width - borders[1].width, bounds.top + bounds.height - borders[2].width);\n        parseCorner(borderArgs, radius[3], radius[0], borderPoints.bottomLeftInner, borderPoints.topLeftInner, bounds.left + borders[3].width, bounds.top + bounds.height - borders[2].width);\n        break;\n\n      default:\n        parseCorner(borderArgs, radius[0], radius[1], borderPoints.topLeftOuter, borderPoints.topRightOuter, bounds.left, bounds.top);\n        parseCorner(borderArgs, radius[1], radius[2], borderPoints.topRightOuter, borderPoints.bottomRightOuter, bounds.left + bounds.width, bounds.top);\n        parseCorner(borderArgs, radius[2], radius[3], borderPoints.bottomRightOuter, borderPoints.bottomLeftOuter, bounds.left + bounds.width, bounds.top + bounds.height);\n        parseCorner(borderArgs, radius[3], radius[0], borderPoints.bottomLeftOuter, borderPoints.topLeftOuter, bounds.left, bounds.top + bounds.height);\n        break;\n    }\n\n    return borderArgs;\n  }\n\n  function parseBorders(element, bounds, borders){\n    var x = bounds.left,\n    y = bounds.top,\n    width = bounds.width,\n    height = bounds.height,\n    borderSide,\n    bx,\n    by,\n    bw,\n    bh,\n    borderArgs,\n    // http://www.w3.org/TR/css3-background/#the-border-radius\n    borderRadius = getBorderRadiusData(element),\n    borderPoints = calculateCurvePoints(bounds, borderRadius, borders),\n    borderData = {\n      clip: getBorderClip(element, borderPoints, borders, borderRadius, bounds),\n      borders: []\n    };\n\n    for (borderSide = 0; borderSide < 4; borderSide++) {\n\n      if (borders[borderSide].width > 0) {\n        bx = x;\n        by = y;\n        bw = width;\n        bh = height - (borders[2].width);\n\n        switch(borderSide) {\n          case 0:\n            // top border\n            bh = borders[0].width;\n\n            borderArgs = drawSide({\n              c1: [bx, by],\n              c2: [bx + bw, by],\n              c3: [bx + bw - borders[1].width, by + bh],\n              c4: [bx + borders[3].width, by + bh]\n            }, borderRadius[0], borderRadius[1],\n            borderPoints.topLeftOuter, borderPoints.topLeftInner, borderPoints.topRightOuter, borderPoints.topRightInner);\n            break;\n          case 1:\n            // right border\n            bx = x + width - (borders[1].width);\n            bw = borders[1].width;\n\n            borderArgs = drawSide({\n              c1: [bx + bw, by],\n              c2: [bx + bw, by + bh + borders[2].width],\n              c3: [bx, by + bh],\n              c4: [bx, by + borders[0].width]\n            }, borderRadius[1], borderRadius[2],\n            borderPoints.topRightOuter, borderPoints.topRightInner, borderPoints.bottomRightOuter, borderPoints.bottomRightInner);\n            break;\n          case 2:\n            // bottom border\n            by = (by + height) - (borders[2].width);\n            bh = borders[2].width;\n\n            borderArgs = drawSide({\n              c1: [bx + bw, by + bh],\n              c2: [bx, by + bh],\n              c3: [bx + borders[3].width, by],\n              c4: [bx + bw - borders[3].width, by]\n            }, borderRadius[2], borderRadius[3],\n            borderPoints.bottomRightOuter, borderPoints.bottomRightInner, borderPoints.bottomLeftOuter, borderPoints.bottomLeftInner);\n            break;\n          case 3:\n            // left border\n            bw = borders[3].width;\n\n            borderArgs = drawSide({\n              c1: [bx, by + bh + borders[2].width],\n              c2: [bx, by],\n              c3: [bx + bw, by + borders[0].width],\n              c4: [bx + bw, by + bh]\n            }, borderRadius[3], borderRadius[0],\n            borderPoints.bottomLeftOuter, borderPoints.bottomLeftInner, borderPoints.topLeftOuter, borderPoints.topLeftInner);\n            break;\n        }\n\n        borderData.borders.push({\n          args: borderArgs,\n          color: borders[borderSide].color\n        });\n\n      }\n    }\n\n    return borderData;\n  }\n\n  function createShape(ctx, args) {\n    var shape = ctx.drawShape();\n    args.forEach(function(border, index) {\n      shape[(index === 0) ? \"moveTo\" : border[0] + \"To\" ].apply(null, border.slice(1));\n    });\n    return shape;\n  }\n\n  function renderBorders(ctx, borderArgs, color) {\n    if (color !== \"transparent\") {\n      ctx.setVariable( \"fillStyle\", color);\n      createShape(ctx, borderArgs);\n      ctx.fill();\n      numDraws+=1;\n    }\n  }\n\n  function renderFormValue (el, bounds, stack){\n\n    var valueWrap = doc.createElement('valuewrap'),\n    cssPropertyArray = ['lineHeight','textAlign','fontFamily','color','fontSize','paddingLeft','paddingTop','width','height','border','borderLeftWidth','borderTopWidth'],\n    textValue,\n    textNode;\n\n    cssPropertyArray.forEach(function(property) {\n      try {\n        valueWrap.style[property] = getCSS(el, property);\n      } catch(e) {\n        // Older IE has issues with \"border\"\n        Util.log(\"html2canvas: Parse: Exception caught in renderFormValue: \" + e.message);\n      }\n    });\n\n    valueWrap.style.borderColor = \"black\";\n    valueWrap.style.borderStyle = \"solid\";\n    valueWrap.style.display = \"block\";\n    valueWrap.style.position = \"absolute\";\n\n    if (/^(submit|reset|button|text|password)$/.test(el.type) || el.nodeName === \"SELECT\"){\n      valueWrap.style.lineHeight = getCSS(el, \"height\");\n    }\n\n    valueWrap.style.top = bounds.top + \"px\";\n    valueWrap.style.left = bounds.left + \"px\";\n\n    textValue = (el.nodeName === \"SELECT\") ? (el.options[el.selectedIndex] || 0).text : el.value;\n    if(!textValue) {\n      textValue = el.placeholder;\n    }\n\n    textNode = doc.createTextNode(textValue);\n\n    valueWrap.appendChild(textNode);\n    body.appendChild(valueWrap);\n\n    renderText(el, textNode, stack);\n    body.removeChild(valueWrap);\n  }\n\n  function drawImage (ctx) {\n    ctx.drawImage.apply(ctx, Array.prototype.slice.call(arguments, 1));\n    numDraws+=1;\n  }\n\n  function getPseudoElement(el, which) {\n    var elStyle = window.getComputedStyle(el, which);\n    if(!elStyle || !elStyle.content || elStyle.content === \"none\" || elStyle.content === \"-moz-alt-content\" || elStyle.display === \"none\") {\n      return;\n    }\n    var content = elStyle.content + '',\n    first = content.substr( 0, 1 );\n    //strips quotes\n    if(first === content.substr( content.length - 1 ) && first.match(/'|\"/)) {\n      content = content.substr( 1, content.length - 2 );\n    }\n\n    var isImage = content.substr( 0, 3 ) === 'url',\n    elps = document.createElement( isImage ? 'img' : 'span' );\n\n    elps.className = pseudoHide + \"-before \" + pseudoHide + \"-after\";\n\n    Object.keys(elStyle).filter(indexedProperty).forEach(function(prop) {\n      // Prevent assigning of read only CSS Rules, ex. length, parentRule\n      try {\n        elps.style[prop] = elStyle[prop];\n      } catch (e) {\n        Util.log(['Tried to assign readonly property ', prop, 'Error:', e]);\n      }\n    });\n\n    if(isImage) {\n      elps.src = Util.parseBackgroundImage(content)[0].args[0];\n    } else {\n      elps.innerHTML = content;\n    }\n    return elps;\n  }\n\n  function indexedProperty(property) {\n    return (isNaN(window.parseInt(property, 10)));\n  }\n\n  function injectPseudoElements(el, stack) {\n    var before = getPseudoElement(el, ':before'),\n    after = getPseudoElement(el, ':after');\n    if(!before && !after) {\n      return;\n    }\n\n    if(before) {\n      el.className += \" \" + pseudoHide + \"-before\";\n      el.parentNode.insertBefore(before, el);\n      parseElement(before, stack, true);\n      el.parentNode.removeChild(before);\n      el.className = el.className.replace(pseudoHide + \"-before\", \"\").trim();\n    }\n\n    if (after) {\n      el.className += \" \" + pseudoHide + \"-after\";\n      el.appendChild(after);\n      parseElement(after, stack, true);\n      el.removeChild(after);\n      el.className = el.className.replace(pseudoHide + \"-after\", \"\").trim();\n    }\n\n  }\n\n  function renderBackgroundRepeat(ctx, image, backgroundPosition, bounds) {\n    var offsetX = Math.round(bounds.left + backgroundPosition.left),\n    offsetY = Math.round(bounds.top + backgroundPosition.top);\n\n    ctx.createPattern(image);\n    ctx.translate(offsetX, offsetY);\n    ctx.fill();\n    ctx.translate(-offsetX, -offsetY);\n  }\n\n  function backgroundRepeatShape(ctx, image, backgroundPosition, bounds, left, top, width, height) {\n    var args = [];\n    args.push([\"line\", Math.round(left), Math.round(top)]);\n    args.push([\"line\", Math.round(left + width), Math.round(top)]);\n    args.push([\"line\", Math.round(left + width), Math.round(height + top)]);\n    args.push([\"line\", Math.round(left), Math.round(height + top)]);\n    createShape(ctx, args);\n    ctx.save();\n    ctx.clip();\n    renderBackgroundRepeat(ctx, image, backgroundPosition, bounds);\n    ctx.restore();\n  }\n\n  function renderBackgroundColor(ctx, backgroundBounds, bgcolor) {\n    renderRect(\n      ctx,\n      backgroundBounds.left,\n      backgroundBounds.top,\n      backgroundBounds.width,\n      backgroundBounds.height,\n      bgcolor\n      );\n  }\n\n  function renderBackgroundRepeating(el, bounds, ctx, image, imageIndex) {\n    var backgroundSize = Util.BackgroundSize(el, bounds, image, imageIndex),\n    backgroundPosition = Util.BackgroundPosition(el, bounds, image, imageIndex, backgroundSize),\n    backgroundRepeat = getCSS(el, \"backgroundRepeat\").split(\",\").map(Util.trimText);\n\n    image = resizeImage(image, backgroundSize);\n\n    backgroundRepeat = backgroundRepeat[imageIndex] || backgroundRepeat[0];\n\n    switch (backgroundRepeat) {\n      case \"repeat-x\":\n        backgroundRepeatShape(ctx, image, backgroundPosition, bounds,\n          bounds.left, bounds.top + backgroundPosition.top, 99999, image.height);\n        break;\n\n      case \"repeat-y\":\n        backgroundRepeatShape(ctx, image, backgroundPosition, bounds,\n          bounds.left + backgroundPosition.left, bounds.top, image.width, 99999);\n        break;\n\n      case \"no-repeat\":\n        backgroundRepeatShape(ctx, image, backgroundPosition, bounds,\n          bounds.left + backgroundPosition.left, bounds.top + backgroundPosition.top, image.width, image.height);\n        break;\n\n      default:\n        renderBackgroundRepeat(ctx, image, backgroundPosition, {\n          top: bounds.top,\n          left: bounds.left,\n          width: image.width,\n          height: image.height\n        });\n        break;\n    }\n  }\n\n  function renderBackgroundImage(element, bounds, ctx) {\n    var backgroundImage = getCSS(element, \"backgroundImage\"),\n    backgroundImages = Util.parseBackgroundImage(backgroundImage),\n    image,\n    imageIndex = backgroundImages.length;\n\n    while(imageIndex--) {\n      backgroundImage = backgroundImages[imageIndex];\n\n      if (!backgroundImage.args || backgroundImage.args.length === 0) {\n        continue;\n      }\n\n      var key = backgroundImage.method === 'url' ?\n      backgroundImage.args[0] :\n      backgroundImage.value;\n\n      image = loadImage(key);\n\n      // TODO add support for background-origin\n      if (image) {\n        renderBackgroundRepeating(element, bounds, ctx, image, imageIndex);\n      } else {\n        Util.log(\"html2canvas: Error loading background:\", backgroundImage);\n      }\n    }\n  }\n\n  function resizeImage(image, bounds) {\n    if(image.width === bounds.width && image.height === bounds.height) {\n      return image;\n    }\n\n    var ctx, canvas = doc.createElement('canvas');\n    canvas.width = bounds.width;\n    canvas.height = bounds.height;\n    ctx = canvas.getContext(\"2d\");\n    drawImage(ctx, image, 0, 0, image.width, image.height, 0, 0, bounds.width, bounds.height );\n    return canvas;\n  }\n\n  function setOpacity(ctx, element, parentStack) {\n    return ctx.setVariable(\"globalAlpha\", getCSS(element, \"opacity\") * ((parentStack) ? parentStack.opacity : 1));\n  }\n\n  function removePx(str) {\n    return str.replace(\"px\", \"\");\n  }\n\n  var transformRegExp = /(matrix)\\((.+)\\)/;\n\n  function getTransform(element, parentStack) {\n    var transform = getCSS(element, \"transform\") || getCSS(element, \"-webkit-transform\") || getCSS(element, \"-moz-transform\") || getCSS(element, \"-ms-transform\") || getCSS(element, \"-o-transform\");\n    var transformOrigin = getCSS(element, \"transform-origin\") || getCSS(element, \"-webkit-transform-origin\") || getCSS(element, \"-moz-transform-origin\") || getCSS(element, \"-ms-transform-origin\") || getCSS(element, \"-o-transform-origin\") || \"0px 0px\";\n\n    transformOrigin = transformOrigin.split(\" \").map(removePx).map(Util.asFloat);\n\n    var matrix;\n    if (transform && transform !== \"none\") {\n      var match = transform.match(transformRegExp);\n      if (match) {\n        switch(match[1]) {\n          case \"matrix\":\n            matrix = match[2].split(\",\").map(Util.trimText).map(Util.asFloat);\n            break;\n        }\n      }\n    }\n\n    return {\n      origin: transformOrigin,\n      matrix: matrix\n    };\n  }\n\n  function createStack(element, parentStack, bounds, transform) {\n    var ctx = h2cRenderContext((!parentStack) ? documentWidth() : bounds.width , (!parentStack) ? documentHeight() : bounds.height),\n    stack = {\n      ctx: ctx,\n      opacity: setOpacity(ctx, element, parentStack),\n      cssPosition: getCSS(element, \"position\"),\n      borders: getBorderData(element),\n      transform: transform,\n      clip: (parentStack && parentStack.clip) ? Util.Extend( {}, parentStack.clip ) : null\n    };\n\n    setZ(element, stack, parentStack);\n\n    // TODO correct overflow for absolute content residing under a static position\n    if (options.useOverflow === true && /(hidden|scroll|auto)/.test(getCSS(element, \"overflow\")) === true && /(BODY)/i.test(element.nodeName) === false){\n      stack.clip = (stack.clip) ? clipBounds(stack.clip, bounds) : bounds;\n    }\n\n    return stack;\n  }\n\n  function getBackgroundBounds(borders, bounds, clip) {\n    var backgroundBounds = {\n      left: bounds.left + borders[3].width,\n      top: bounds.top + borders[0].width,\n      width: bounds.width - (borders[1].width + borders[3].width),\n      height: bounds.height - (borders[0].width + borders[2].width)\n    };\n\n    if (clip) {\n      backgroundBounds = clipBounds(backgroundBounds, clip);\n    }\n\n    return backgroundBounds;\n  }\n\n  function getBounds(element, transform) {\n    var bounds = (transform.matrix) ? Util.OffsetBounds(element) : Util.Bounds(element);\n    transform.origin[0] += bounds.left;\n    transform.origin[1] += bounds.top;\n    return bounds;\n  }\n\n  function renderElement(element, parentStack, pseudoElement, ignoreBackground) {\n    var transform = getTransform(element, parentStack),\n    bounds = getBounds(element, transform),\n    image,\n    stack = createStack(element, parentStack, bounds, transform),\n    borders = stack.borders,\n    ctx = stack.ctx,\n    backgroundBounds = getBackgroundBounds(borders, bounds, stack.clip),\n    borderData = parseBorders(element, bounds, borders),\n    backgroundColor = (ignoreElementsRegExp.test(element.nodeName)) ? \"#efefef\" : getCSS(element, \"backgroundColor\");\n\n\n    createShape(ctx, borderData.clip);\n\n    ctx.save();\n    ctx.clip();\n\n    if (backgroundBounds.height > 0 && backgroundBounds.width > 0 && !ignoreBackground) {\n      renderBackgroundColor(ctx, bounds, backgroundColor);\n      renderBackgroundImage(element, backgroundBounds, ctx);\n    } else if (ignoreBackground) {\n      stack.backgroundColor =  backgroundColor;\n    }\n\n    ctx.restore();\n\n    borderData.borders.forEach(function(border) {\n      renderBorders(ctx, border.args, border.color);\n    });\n\n    if (!pseudoElement) {\n      injectPseudoElements(element, stack);\n    }\n\n    switch(element.nodeName){\n      case \"IMG\":\n        if ((image = loadImage(element.getAttribute('src')))) {\n          renderImage(ctx, element, image, bounds, borders);\n        } else {\n          Util.log(\"html2canvas: Error loading <img>:\" + element.getAttribute('src'));\n        }\n        break;\n      case \"INPUT\":\n        // TODO add all relevant type's, i.e. HTML5 new stuff\n        // todo add support for placeholder attribute for browsers which support it\n        if (/^(text|url|email|submit|button|reset)$/.test(element.type) && (element.value || element.placeholder || \"\").length > 0){\n          renderFormValue(element, bounds, stack);\n        }\n        break;\n      case \"TEXTAREA\":\n        if ((element.value || element.placeholder || \"\").length > 0){\n          renderFormValue(element, bounds, stack);\n        }\n        break;\n      case \"SELECT\":\n        if ((element.options||element.placeholder || \"\").length > 0){\n          renderFormValue(element, bounds, stack);\n        }\n        break;\n      case \"LI\":\n        renderListItem(element, stack, backgroundBounds);\n        break;\n      case \"CANVAS\":\n        renderImage(ctx, element, element, bounds, borders);\n        break;\n    }\n\n    return stack;\n  }\n\n  function isElementVisible(element) {\n    return (getCSS(element, 'display') !== \"none\" && getCSS(element, 'visibility') !== \"hidden\" && !element.hasAttribute(\"data-html2canvas-ignore\"));\n  }\n\n  function parseElement (element, stack, pseudoElement) {\n    if (isElementVisible(element)) {\n      stack = renderElement(element, stack, pseudoElement, false) || stack;\n      if (!ignoreElementsRegExp.test(element.nodeName)) {\n        parseChildren(element, stack, pseudoElement);\n      }\n    }\n  }\n\n  function parseChildren(element, stack, pseudoElement) {\n    Util.Children(element).forEach(function(node) {\n      if (node.nodeType === node.ELEMENT_NODE) {\n        parseElement(node, stack, pseudoElement);\n      } else if (node.nodeType === node.TEXT_NODE) {\n        renderText(element, node, stack);\n      }\n    });\n  }\n\n  function init() {\n    var background = getCSS(document.documentElement, \"backgroundColor\"),\n      transparentBackground = (Util.isTransparent(background) && element === document.body),\n      stack = renderElement(element, null, false, transparentBackground);\n    parseChildren(element, stack);\n\n    if (transparentBackground) {\n      background = stack.backgroundColor;\n    }\n\n    body.removeChild(hidePseudoElements);\n    return {\n      backgroundColor: background,\n      stack: stack\n    };\n  }\n\n  return init();\n};\n\nfunction h2czContext(zindex) {\n  return {\n    zindex: zindex,\n    children: []\n  };\n}\n\n_html2canvas.Preload = function( options ) {\n\n  var images = {\n    numLoaded: 0,   // also failed are counted here\n    numFailed: 0,\n    numTotal: 0,\n    cleanupDone: false\n  },\n  pageOrigin,\n  Util = _html2canvas.Util,\n  methods,\n  i,\n  count = 0,\n  element = options.elements[0] || document.body,\n  doc = element.ownerDocument,\n  domImages = element.getElementsByTagName('img'), // Fetch images of the present element only\n  imgLen = domImages.length,\n  link = doc.createElement(\"a\"),\n  supportCORS = (function( img ){\n    return (img.crossOrigin !== undefined);\n  })(new Image()),\n  timeoutTimer;\n\n  link.href = window.location.href;\n  pageOrigin  = link.protocol + link.host;\n\n  function isSameOrigin(url){\n    link.href = url;\n    link.href = link.href; // YES, BELIEVE IT OR NOT, that is required for IE9 - http://jsfiddle.net/niklasvh/2e48b/\n    var origin = link.protocol + link.host;\n    return (origin === pageOrigin);\n  }\n\n  function start(){\n    Util.log(\"html2canvas: start: images: \" + images.numLoaded + \" / \" + images.numTotal + \" (failed: \" + images.numFailed + \")\");\n    if (!images.firstRun && images.numLoaded >= images.numTotal){\n      Util.log(\"Finished loading images: # \" + images.numTotal + \" (failed: \" + images.numFailed + \")\");\n\n      if (typeof options.complete === \"function\"){\n        options.complete(images);\n      }\n\n    }\n  }\n\n  // TODO modify proxy to serve images with CORS enabled, where available\n  function proxyGetImage(url, img, imageObj){\n    var callback_name,\n    scriptUrl = options.proxy,\n    script;\n\n    link.href = url;\n    url = link.href; // work around for pages with base href=\"\" set - WARNING: this may change the url\n\n    callback_name = 'html2canvas_' + (count++);\n    imageObj.callbackname = callback_name;\n\n    if (scriptUrl.indexOf(\"?\") > -1) {\n      scriptUrl += \"&\";\n    } else {\n      scriptUrl += \"?\";\n    }\n    scriptUrl += 'url=' + encodeURIComponent(url) + '&callback=' + callback_name;\n    script = doc.createElement(\"script\");\n\n    window[callback_name] = function(a){\n      if (a.substring(0,6) === \"error:\"){\n        imageObj.succeeded = false;\n        images.numLoaded++;\n        images.numFailed++;\n        start();\n      } else {\n        setImageLoadHandlers(img, imageObj);\n        img.src = a;\n      }\n      window[callback_name] = undefined; // to work with IE<9  // NOTE: that the undefined callback property-name still exists on the window object (for IE<9)\n      try {\n        delete window[callback_name];  // for all browser that support this\n      } catch(ex) {}\n      script.parentNode.removeChild(script);\n      script = null;\n      delete imageObj.script;\n      delete imageObj.callbackname;\n    };\n\n    script.setAttribute(\"type\", \"text/javascript\");\n    script.setAttribute(\"src\", scriptUrl);\n    imageObj.script = script;\n    window.document.body.appendChild(script);\n\n  }\n\n  function loadPseudoElement(element, type) {\n    var style = window.getComputedStyle(element, type),\n    content = style.content;\n    if (content.substr(0, 3) === 'url') {\n      methods.loadImage(_html2canvas.Util.parseBackgroundImage(content)[0].args[0]);\n    }\n    loadBackgroundImages(style.backgroundImage, element);\n  }\n\n  function loadPseudoElementImages(element) {\n    loadPseudoElement(element, \":before\");\n    loadPseudoElement(element, \":after\");\n  }\n\n  function loadGradientImage(backgroundImage, bounds) {\n    var img = _html2canvas.Generate.Gradient(backgroundImage, bounds);\n\n    if (img !== undefined){\n      images[backgroundImage] = {\n        img: img,\n        succeeded: true\n      };\n      images.numTotal++;\n      images.numLoaded++;\n      start();\n    }\n  }\n\n  function invalidBackgrounds(background_image) {\n    return (background_image && background_image.method && background_image.args && background_image.args.length > 0 );\n  }\n\n  function loadBackgroundImages(background_image, el) {\n    var bounds;\n\n    _html2canvas.Util.parseBackgroundImage(background_image).filter(invalidBackgrounds).forEach(function(background_image) {\n      if (background_image.method === 'url') {\n        methods.loadImage(background_image.args[0]);\n      } else if(background_image.method.match(/\\-?gradient$/)) {\n        if(bounds === undefined) {\n          bounds = _html2canvas.Util.Bounds(el);\n        }\n        loadGradientImage(background_image.value, bounds);\n      }\n    });\n  }\n\n  function getImages (el) {\n    var elNodeType = false;\n\n    // Firefox fails with permission denied on pages with iframes\n    try {\n      Util.Children(el).forEach(getImages);\n    }\n    catch( e ) {}\n\n    try {\n      elNodeType = el.nodeType;\n    } catch (ex) {\n      elNodeType = false;\n      Util.log(\"html2canvas: failed to access some element's nodeType - Exception: \" + ex.message);\n    }\n\n    if (elNodeType === 1 || elNodeType === undefined) {\n      loadPseudoElementImages(el);\n      try {\n        loadBackgroundImages(Util.getCSS(el, 'backgroundImage'), el);\n      } catch(e) {\n        Util.log(\"html2canvas: failed to get background-image - Exception: \" + e.message);\n      }\n      loadBackgroundImages(el);\n    }\n  }\n\n  function setImageLoadHandlers(img, imageObj) {\n    img.onload = function() {\n      if ( imageObj.timer !== undefined ) {\n        // CORS succeeded\n        window.clearTimeout( imageObj.timer );\n      }\n\n      images.numLoaded++;\n      imageObj.succeeded = true;\n      img.onerror = img.onload = null;\n      start();\n    };\n    img.onerror = function() {\n      if (img.crossOrigin === \"anonymous\") {\n        // CORS failed\n        window.clearTimeout( imageObj.timer );\n\n        // let's try with proxy instead\n        if ( options.proxy ) {\n          var src = img.src;\n          img = new Image();\n          imageObj.img = img;\n          img.src = src;\n\n          proxyGetImage( img.src, img, imageObj );\n          return;\n        }\n      }\n\n      images.numLoaded++;\n      images.numFailed++;\n      imageObj.succeeded = false;\n      img.onerror = img.onload = null;\n      start();\n    };\n  }\n\n  methods = {\n    loadImage: function( src ) {\n      var img, imageObj;\n      if ( src && images[src] === undefined ) {\n        img = new Image();\n        if ( src.match(/data:image\\/.*;base64,/i) ) {\n          img.src = src.replace(/url\\(['\"]{0,}|['\"]{0,}\\)$/ig, '');\n          imageObj = images[src] = {\n            img: img\n          };\n          images.numTotal++;\n          setImageLoadHandlers(img, imageObj);\n        } else if ( isSameOrigin( src ) || options.allowTaint ===  true ) {\n          imageObj = images[src] = {\n            img: img\n          };\n          images.numTotal++;\n          setImageLoadHandlers(img, imageObj);\n          img.src = src;\n        } else if ( supportCORS && !options.allowTaint && options.useCORS ) {\n          // attempt to load with CORS\n\n          img.crossOrigin = \"anonymous\";\n          imageObj = images[src] = {\n            img: img\n          };\n          images.numTotal++;\n          setImageLoadHandlers(img, imageObj);\n          img.src = src;\n        } else if ( options.proxy ) {\n          imageObj = images[src] = {\n            img: img\n          };\n          images.numTotal++;\n          proxyGetImage( src, img, imageObj );\n        }\n      }\n\n    },\n    cleanupDOM: function(cause) {\n      var img, src;\n      if (!images.cleanupDone) {\n        if (cause && typeof cause === \"string\") {\n          Util.log(\"html2canvas: Cleanup because: \" + cause);\n        } else {\n          Util.log(\"html2canvas: Cleanup after timeout: \" + options.timeout + \" ms.\");\n        }\n\n        for (src in images) {\n          if (images.hasOwnProperty(src)) {\n            img = images[src];\n            if (typeof img === \"object\" && img.callbackname && img.succeeded === undefined) {\n              // cancel proxy image request\n              window[img.callbackname] = undefined; // to work with IE<9  // NOTE: that the undefined callback property-name still exists on the window object (for IE<9)\n              try {\n                delete window[img.callbackname];  // for all browser that support this\n              } catch(ex) {}\n              if (img.script && img.script.parentNode) {\n                img.script.setAttribute(\"src\", \"about:blank\");  // try to cancel running request\n                img.script.parentNode.removeChild(img.script);\n              }\n              images.numLoaded++;\n              images.numFailed++;\n              Util.log(\"html2canvas: Cleaned up failed img: '\" + src + \"' Steps: \" + images.numLoaded + \" / \" + images.numTotal);\n            }\n          }\n        }\n\n        // cancel any pending requests\n        if(window.stop !== undefined) {\n          window.stop();\n        } else if(document.execCommand !== undefined) {\n          document.execCommand(\"Stop\", false);\n        }\n        if (document.close !== undefined) {\n          document.close();\n        }\n        images.cleanupDone = true;\n        if (!(cause && typeof cause === \"string\")) {\n          start();\n        }\n      }\n    },\n\n    renderingDone: function() {\n      if (timeoutTimer) {\n        window.clearTimeout(timeoutTimer);\n      }\n    }\n  };\n\n  if (options.timeout > 0) {\n    timeoutTimer = window.setTimeout(methods.cleanupDOM, options.timeout);\n  }\n\n  Util.log('html2canvas: Preload starts: finding background-images');\n  images.firstRun = true;\n\n  getImages(element);\n\n  Util.log('html2canvas: Preload: Finding images');\n  // load <img> images\n  for (i = 0; i < imgLen; i+=1){\n    methods.loadImage( domImages[i].getAttribute( \"src\" ) );\n  }\n\n  images.firstRun = false;\n  Util.log('html2canvas: Preload: Done.');\n  if (images.numTotal === images.numLoaded) {\n    start();\n  }\n\n  return methods;\n};\n\n_html2canvas.Renderer = function(parseQueue, options){\n\n  // http://www.w3.org/TR/CSS21/zindex.html\n  function createRenderQueue(parseQueue) {\n    var queue = [],\n    rootContext;\n\n    rootContext = (function buildStackingContext(rootNode) {\n      var rootContext = {};\n      function insert(context, node, specialParent) {\n        var zi = (node.zIndex.zindex === 'auto') ? 0 : Number(node.zIndex.zindex),\n        contextForChildren = context, // the stacking context for children\n        isPositioned = node.zIndex.isPositioned,\n        isFloated = node.zIndex.isFloated,\n        stub = {node: node},\n        childrenDest = specialParent; // where children without z-index should be pushed into\n\n        if (node.zIndex.ownStacking) {\n          // '!' comes before numbers in sorted array\n          contextForChildren = stub.context = { '!': [{node:node, children: []}]};\n          childrenDest = undefined;\n        } else if (isPositioned || isFloated) {\n          childrenDest = stub.children = [];\n        }\n\n        if (zi === 0 && specialParent) {\n          specialParent.push(stub);\n        } else {\n          if (!context[zi]) { context[zi] = []; }\n          context[zi].push(stub);\n        }\n\n        node.zIndex.children.forEach(function(childNode) {\n          insert(contextForChildren, childNode, childrenDest);\n        });\n      }\n      insert(rootContext, rootNode);\n      return rootContext;\n    })(parseQueue);\n\n    function sortZ(context) {\n      Object.keys(context).sort().forEach(function(zi) {\n        var nonPositioned = [],\n        floated = [],\n        positioned = [],\n        list = [];\n\n        // positioned after static\n        context[zi].forEach(function(v) {\n          if (v.node.zIndex.isPositioned || v.node.zIndex.opacity < 1) {\n            // http://www.w3.org/TR/css3-color/#transparency\n            // non-positioned element with opactiy < 1 should be stacked as if it were a positioned element with ‘z-index: 0’ and ‘opacity: 1’.\n            positioned.push(v);\n          } else if (v.node.zIndex.isFloated) {\n            floated.push(v);\n          } else {\n            nonPositioned.push(v);\n          }\n        });\n\n        (function walk(arr) {\n          arr.forEach(function(v) {\n            list.push(v);\n            if (v.children) { walk(v.children); }\n          });\n        })(nonPositioned.concat(floated, positioned));\n\n        list.forEach(function(v) {\n          if (v.context) {\n            sortZ(v.context);\n          } else {\n            queue.push(v.node);\n          }\n        });\n      });\n    }\n\n    sortZ(rootContext);\n\n    return queue;\n  }\n\n  function getRenderer(rendererName) {\n    var renderer;\n\n    if (typeof options.renderer === \"string\" && _html2canvas.Renderer[rendererName] !== undefined) {\n      renderer = _html2canvas.Renderer[rendererName](options);\n    } else if (typeof rendererName === \"function\") {\n      renderer = rendererName(options);\n    } else {\n      throw new Error(\"Unknown renderer\");\n    }\n\n    if ( typeof renderer !== \"function\" ) {\n      throw new Error(\"Invalid renderer defined\");\n    }\n    return renderer;\n  }\n\n  return getRenderer(options.renderer)(parseQueue, options, document, createRenderQueue(parseQueue.stack), _html2canvas);\n};\n\n_html2canvas.Util.Support = function (options, doc) {\n\n  function supportSVGRendering() {\n    var img = new Image(),\n    canvas = doc.createElement(\"canvas\"),\n    ctx = (canvas.getContext === undefined) ? false : canvas.getContext(\"2d\");\n    if (ctx === false) {\n      return false;\n    }\n    canvas.width = canvas.height = 10;\n    img.src = [\n    \"data:image/svg+xml,\",\n    \"<svg xmlns='http://www.w3.org/2000/svg' width='10' height='10'>\",\n    \"<foreignObject width='10' height='10'>\",\n    \"<div xmlns='http://www.w3.org/1999/xhtml' style='width:10;height:10;'>\",\n    \"sup\",\n    \"</div>\",\n    \"</foreignObject>\",\n    \"</svg>\"\n    ].join(\"\");\n    try {\n      ctx.drawImage(img, 0, 0);\n      canvas.toDataURL();\n    } catch(e) {\n      return false;\n    }\n    _html2canvas.Util.log('html2canvas: Parse: SVG powered rendering available');\n    return true;\n  }\n\n  // Test whether we can use ranges to measure bounding boxes\n  // Opera doesn't provide valid bounds.height/bottom even though it supports the method.\n\n  function supportRangeBounds() {\n    var r, testElement, rangeBounds, rangeHeight, support = false;\n\n    if (doc.createRange) {\n      r = doc.createRange();\n      if (r.getBoundingClientRect) {\n        testElement = doc.createElement('boundtest');\n        testElement.style.height = \"123px\";\n        testElement.style.display = \"block\";\n        doc.body.appendChild(testElement);\n\n        r.selectNode(testElement);\n        rangeBounds = r.getBoundingClientRect();\n        rangeHeight = rangeBounds.height;\n\n        if (rangeHeight === 123) {\n          support = true;\n        }\n        doc.body.removeChild(testElement);\n      }\n    }\n\n    return support;\n  }\n\n  return {\n    rangeBounds: supportRangeBounds(),\n    svgRendering: options.svgRendering && supportSVGRendering()\n  };\n};\nwindow.html2canvas = function(elements, opts) {\n  elements = (elements.length) ? elements : [elements];\n  var queue,\n  canvas,\n  options = {\n    // general\n    logging: false,\n    elements: elements,\n    background: \"#fff\",\n\n    // preload options\n    proxy: null,\n    timeout: 0,    // no timeout\n    useCORS: false, // try to load images as CORS (where available), before falling back to proxy\n    allowTaint: false, // whether to allow images to taint the canvas, won't need proxy if set to true\n\n    // parse options\n    svgRendering: false, // use svg powered rendering where available (FF11+)\n    ignoreElements: \"IFRAME|OBJECT|PARAM\",\n    useOverflow: true,\n    letterRendering: false,\n    chinese: false,\n\n    // render options\n\n    width: null,\n    height: null,\n    taintTest: true, // do a taint test with all images before applying to canvas\n    renderer: \"Canvas\"\n  };\n\n  options = _html2canvas.Util.Extend(opts, options);\n\n  _html2canvas.logging = options.logging;\n  options.complete = function( images ) {\n\n    if (typeof options.onpreloaded === \"function\") {\n      if ( options.onpreloaded( images ) === false ) {\n        return;\n      }\n    }\n    queue = _html2canvas.Parse( images, options );\n\n    if (typeof options.onparsed === \"function\") {\n      if ( options.onparsed( queue ) === false ) {\n        return;\n      }\n    }\n\n    canvas = _html2canvas.Renderer( queue, options );\n\n    if (typeof options.onrendered === \"function\") {\n      options.onrendered( canvas );\n    }\n\n\n  };\n\n  // for pages without images, we still want this to be async, i.e. return methods before executing\n  window.setTimeout( function(){\n    _html2canvas.Preload( options );\n  }, 0 );\n\n  return {\n    render: function( queue, opts ) {\n      return _html2canvas.Renderer( queue, _html2canvas.Util.Extend(opts, options) );\n    },\n    parse: function( images, opts ) {\n      return _html2canvas.Parse( images, _html2canvas.Util.Extend(opts, options) );\n    },\n    preload: function( opts ) {\n      return _html2canvas.Preload( _html2canvas.Util.Extend(opts, options) );\n    },\n    log: _html2canvas.Util.log\n  };\n};\n\nwindow.html2canvas.log = _html2canvas.Util.log; // for renderers\nwindow.html2canvas.Renderer = {\n  Canvas: undefined // We are assuming this will be used\n};\n_html2canvas.Renderer.Canvas = function(options) {\n  options = options || {};\n\n  var doc = document,\n  safeImages = [],\n  testCanvas = document.createElement(\"canvas\"),\n  testctx = testCanvas.getContext(\"2d\"),\n  Util = _html2canvas.Util,\n  canvas = options.canvas || doc.createElement('canvas');\n\n  function createShape(ctx, args) {\n    ctx.beginPath();\n    args.forEach(function(arg) {\n      ctx[arg.name].apply(ctx, arg['arguments']);\n    });\n    ctx.closePath();\n  }\n\n  function safeImage(item) {\n    if (safeImages.indexOf(item['arguments'][0].src ) === -1) {\n      testctx.drawImage(item['arguments'][0], 0, 0);\n      try {\n        testctx.getImageData(0, 0, 1, 1);\n      } catch(e) {\n        testCanvas = doc.createElement(\"canvas\");\n        testctx = testCanvas.getContext(\"2d\");\n        return false;\n      }\n      safeImages.push(item['arguments'][0].src);\n    }\n    return true;\n  }\n\n  function renderItem(ctx, item) {\n    switch(item.type){\n      case \"variable\":\n        ctx[item.name] = item['arguments'];\n        break;\n      case \"function\":\n        switch(item.name) {\n          case \"createPattern\":\n            if (item['arguments'][0].width > 0 && item['arguments'][0].height > 0) {\n              try {\n                ctx.fillStyle = ctx.createPattern(item['arguments'][0], \"repeat\");\n              }\n              catch(e) {\n                Util.log(\"html2canvas: Renderer: Error creating pattern\", e.message);\n              }\n            }\n            break;\n          case \"drawShape\":\n            createShape(ctx, item['arguments']);\n            break;\n          case \"drawImage\":\n            if (item['arguments'][8] > 0 && item['arguments'][7] > 0) {\n              if (!options.taintTest || (options.taintTest && safeImage(item))) {\n                ctx.drawImage.apply( ctx, item['arguments'] );\n              }\n            }\n            break;\n          default:\n            ctx[item.name].apply(ctx, item['arguments']);\n        }\n        break;\n    }\n  }\n\n  return function(parsedData, options, document, queue, _html2canvas) {\n    var ctx = canvas.getContext(\"2d\"),\n    newCanvas,\n    bounds,\n    fstyle,\n    zStack = parsedData.stack;\n\n    canvas.width = canvas.style.width =  options.width || zStack.ctx.width;\n    canvas.height = canvas.style.height = options.height || zStack.ctx.height;\n\n    fstyle = ctx.fillStyle;\n    ctx.fillStyle = (Util.isTransparent(zStack.backgroundColor) && options.background !== undefined) ? options.background : parsedData.backgroundColor;\n    ctx.fillRect(0, 0, canvas.width, canvas.height);\n    ctx.fillStyle = fstyle;\n\n    queue.forEach(function(storageContext) {\n      // set common settings for canvas\n      ctx.textBaseline = \"bottom\";\n      ctx.save();\n\n      if (storageContext.transform.matrix) {\n        ctx.translate(storageContext.transform.origin[0], storageContext.transform.origin[1]);\n        ctx.transform.apply(ctx, storageContext.transform.matrix);\n        ctx.translate(-storageContext.transform.origin[0], -storageContext.transform.origin[1]);\n      }\n\n      if (storageContext.clip){\n        ctx.beginPath();\n        ctx.rect(storageContext.clip.left, storageContext.clip.top, storageContext.clip.width, storageContext.clip.height);\n        ctx.clip();\n      }\n\n      if (storageContext.ctx.storage) {\n        storageContext.ctx.storage.forEach(function(item) {\n          renderItem(ctx, item);\n        });\n      }\n\n      ctx.restore();\n    });\n\n    Util.log(\"html2canvas: Renderer: Canvas renderer done - returning canvas obj\");\n\n    if (options.elements.length === 1) {\n      if (typeof options.elements[0] === \"object\" && options.elements[0].nodeName !== \"BODY\") {\n        // crop image to the bounds of selected (single) element\n        bounds = _html2canvas.Util.Bounds(options.elements[0]);\n        newCanvas = document.createElement('canvas');\n        newCanvas.width = Math.ceil(bounds.width);\n        newCanvas.height = Math.ceil(bounds.height);\n        ctx = newCanvas.getContext(\"2d\");\n\n        // fix https://github.com/niklasvh/html2canvas/commit/f61ceea01d0240624aaee5b24d02f4e2fe6a69d2\n        //ctx.drawImage(canvas, bounds.left, bounds.top, bounds.width, bounds.height, 0, 0, bounds.width, bounds.height);\n        var imgData = canvas.getContext(\"2d\").getImageData(bounds.left, bounds.top, bounds.width, bounds.height);\n        ctx.putImageData(imgData, 0, 0);\n        canvas = null;\n        return newCanvas;\n      }\n    }\n\n    return canvas;\n  };\n};\n})(window,document);"
  },
  {
    "path": "flowable-ui-web/modeler/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": "flowable-ui-web/modeler/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": "flowable-ui-web/modeler/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": "flowable-ui-web/modeler/libs/ng-file-upload/FileAPI.js",
    "content": "/*! FileAPI 2.0.7 - BSD | git://github.com/mailru/FileAPI.git\n * FileAPI — a set of  javascript tools for working with files. Multiupload, drag'n'drop and chunked file upload. Images: crop, resize and auto orientation by EXIF.\n */\n\n/*\n * JavaScript Canvas to Blob 2.0.5\n * https://github.com/blueimp/JavaScript-Canvas-to-Blob\n *\n * Copyright 2012, Sebastian Tschan\n * https://blueimp.net\n *\n * Licensed under the MIT license:\n * http://www.opensource.org/licenses/MIT\n *\n * Based on stackoverflow user Stoive's code snippet:\n * http://stackoverflow.com/q/4998908\n */\n\n/*jslint nomen: true, regexp: true */\n/*global window, atob, Blob, ArrayBuffer, Uint8Array */\n\n(function (window) {\n    'use strict';\n    var CanvasPrototype = window.HTMLCanvasElement &&\n            window.HTMLCanvasElement.prototype,\n        hasBlobConstructor = window.Blob && (function () {\n            try {\n                return Boolean(new Blob());\n            } catch (e) {\n                return false;\n            }\n        }()),\n        hasArrayBufferViewSupport = hasBlobConstructor && window.Uint8Array &&\n            (function () {\n                try {\n                    return new Blob([new Uint8Array(100)]).size === 100;\n                } catch (e) {\n                    return false;\n                }\n            }()),\n        BlobBuilder = window.BlobBuilder || window.WebKitBlobBuilder ||\n            window.MozBlobBuilder || window.MSBlobBuilder,\n        dataURLtoBlob = (hasBlobConstructor || BlobBuilder) && window.atob &&\n            window.ArrayBuffer && window.Uint8Array && function (dataURI) {\n                var byteString,\n                    arrayBuffer,\n                    intArray,\n                    i,\n                    mimeString,\n                    bb;\n                if (dataURI.split(',')[0].indexOf('base64') >= 0) {\n                    // Convert base64 to raw binary data held in a string:\n                    byteString = atob(dataURI.split(',')[1]);\n                } else {\n                    // Convert base64/URLEncoded data component to raw binary data:\n                    byteString = decodeURIComponent(dataURI.split(',')[1]);\n                }\n                // Write the bytes of the string to an ArrayBuffer:\n                arrayBuffer = new ArrayBuffer(byteString.length);\n                intArray = new Uint8Array(arrayBuffer);\n                for (i = 0; i < byteString.length; i += 1) {\n                    intArray[i] = byteString.charCodeAt(i);\n                }\n                // Separate out the mime component:\n                mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0];\n                // Write the ArrayBuffer (or ArrayBufferView) to a blob:\n                if (hasBlobConstructor) {\n                    return new Blob(\n                        [hasArrayBufferViewSupport ? intArray : arrayBuffer],\n                        {type: mimeString}\n                    );\n                }\n                bb = new BlobBuilder();\n                bb.append(arrayBuffer);\n                return bb.getBlob(mimeString);\n            };\n    if (window.HTMLCanvasElement && !CanvasPrototype.toBlob) {\n        if (CanvasPrototype.mozGetAsFile) {\n            CanvasPrototype.toBlob = function (callback, type, quality) {\n                if (quality && CanvasPrototype.toDataURL && dataURLtoBlob) {\n                    callback(dataURLtoBlob(this.toDataURL(type, quality)));\n                } else {\n                    callback(this.mozGetAsFile('blob', type));\n                }\n            };\n        } else if (CanvasPrototype.toDataURL && dataURLtoBlob) {\n            CanvasPrototype.toBlob = function (callback, type, quality) {\n                callback(dataURLtoBlob(this.toDataURL(type, quality)));\n            };\n        }\n    }\n    window.dataURLtoBlob = dataURLtoBlob;\n})(window);\n\n/*jslint evil: true */\n/*global window, URL, webkitURL, ActiveXObject */\n\n(function (window, undef){\n\t'use strict';\n\n\tvar\n\t\tgid = 1,\n\t\tnoop = function (){},\n\n\t\tdocument = window.document,\n\t\tdoctype = document.doctype || {},\n\t\tuserAgent = window.navigator.userAgent,\n\n\t\t// https://github.com/blueimp/JavaScript-Load-Image/blob/master/load-image.js#L48\n\t\tapiURL = (window.createObjectURL && window) || (window.URL && URL.revokeObjectURL && URL) || (window.webkitURL && webkitURL),\n\n\t\tBlob = window.Blob,\n\t\tFile = window.File,\n\t\tFileReader = window.FileReader,\n\t\tFormData = window.FormData,\n\n\n\t\tXMLHttpRequest = window.XMLHttpRequest,\n\t\tjQuery = window.jQuery,\n\n\t\thtml5 =    !!(File && (FileReader && (window.Uint8Array || FormData || XMLHttpRequest.prototype.sendAsBinary)))\n\t\t\t\t&& !(/safari\\//i.test(userAgent) && !/chrome\\//i.test(userAgent) && /windows/i.test(userAgent)), // BugFix: https://github.com/mailru/FileAPI/issues/25\n\n\t\tcors = html5 && ('withCredentials' in (new XMLHttpRequest)),\n\n\t\tchunked = html5 && !!Blob && !!(Blob.prototype.webkitSlice || Blob.prototype.mozSlice || Blob.prototype.slice),\n\n\t\t// https://github.com/blueimp/JavaScript-Canvas-to-Blob\n\t\tdataURLtoBlob = window.dataURLtoBlob,\n\n\n\t\t_rimg = /img/i,\n\t\t_rcanvas = /canvas/i,\n\t\t_rimgcanvas = /img|canvas/i,\n\t\t_rinput = /input/i,\n\t\t_rdata = /^data:[^,]+,/,\n\n\t\t_toString = {}.toString,\n\n\n\t\tMath = window.Math,\n\n\t\t_SIZE_CONST = function (pow){\n\t\t\tpow = new window.Number(Math.pow(1024, pow));\n\t\t\tpow.from = function (sz){ return Math.round(sz * this); };\n\t\t\treturn\tpow;\n\t\t},\n\n\t\t_elEvents = {}, // element event listeners\n\t\t_infoReader = [], // list of file info processors\n\n\t\t_readerEvents = 'abort progress error load loadend',\n\t\t_xhrPropsExport = 'status statusText readyState response responseXML responseText responseBody'.split(' '),\n\n\t\tcurrentTarget = 'currentTarget', // for minimize\n\t\tpreventDefault = 'preventDefault', // and this too\n\n\t\t_isArray = function (ar) {\n\t\t\treturn\tar && ('length' in ar);\n\t\t},\n\n\t\t/**\n\t\t * Iterate over a object or array\n\t\t */\n\t\t_each = function (obj, fn, ctx){\n\t\t\tif( obj ){\n\t\t\t\tif( _isArray(obj) ){\n\t\t\t\t\tfor( var i = 0, n = obj.length; i < n; i++ ){\n\t\t\t\t\t\tif( i in obj ){\n\t\t\t\t\t\t\tfn.call(ctx, obj[i], i, obj);\n\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\tfor( var key in obj ){\n\t\t\t\t\t\tif( obj.hasOwnProperty(key) ){\n\t\t\t\t\t\t\tfn.call(ctx, obj[key], key, obj);\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/**\n\t\t * Merge the contents of two or more objects together into the first object\n\t\t */\n\t\t_extend = function (dst){\n\t\t\tvar args = arguments, i = 1, _ext = function (val, key){ dst[key] = val; };\n\t\t\tfor( ; i < args.length; i++ ){\n\t\t\t\t_each(args[i], _ext);\n\t\t\t}\n\t\t\treturn  dst;\n\t\t},\n\n\t\t/**\n\t\t * Add event listener\n\t\t */\n\t\t_on = function (el, type, fn){\n\t\t\tif( el ){\n\t\t\t\tvar uid = api.uid(el);\n\n\t\t\t\tif( !_elEvents[uid] ){\n\t\t\t\t\t_elEvents[uid] = {};\n\t\t\t\t}\n\n\t\t\t\tvar isFileReader = (FileReader && el) && (el instanceof FileReader);\n\t\t\t\t_each(type.split(/\\s+/), function (type){\n\t\t\t\t\tif( jQuery && !isFileReader){\n\t\t\t\t\t\tjQuery.event.add(el, type, fn);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif( !_elEvents[uid][type] ){\n\t\t\t\t\t\t\t_elEvents[uid][type] = [];\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t_elEvents[uid][type].push(fn);\n\n\t\t\t\t\t\tif( el.addEventListener ){ el.addEventListener(type, fn, false); }\n\t\t\t\t\t\telse if( el.attachEvent ){ el.attachEvent('on'+type, fn); }\n\t\t\t\t\t\telse { el['on'+type] = fn; }\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t},\n\n\n\t\t/**\n\t\t * Remove event listener\n\t\t */\n\t\t_off = function (el, type, fn){\n\t\t\tif( el ){\n\t\t\t\tvar uid = api.uid(el), events = _elEvents[uid] || {};\n\n\t\t\t\tvar isFileReader = (FileReader && el) && (el instanceof FileReader);\n\t\t\t\t_each(type.split(/\\s+/), function (type){\n\t\t\t\t\tif( jQuery && !isFileReader){\n\t\t\t\t\t\tjQuery.event.remove(el, type, fn);\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\tvar fns = events[type] || [], i = fns.length;\n\n\t\t\t\t\t\twhile( i-- ){\n\t\t\t\t\t\t\tif( fns[i] === fn ){\n\t\t\t\t\t\t\t\tfns.splice(i, 1);\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\n\t\t\t\t\t\tif( el.addEventListener ){ el.removeEventListener(type, fn, false); }\n\t\t\t\t\t\telse if( el.detachEvent ){ el.detachEvent('on'+type, fn); }\n\t\t\t\t\t\telse { el['on'+type] = null; }\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t},\n\n\n\t\t_one = function(el, type, fn){\n\t\t\t_on(el, type, function _(evt){\n\t\t\t\t_off(el, type, _);\n\t\t\t\tfn(evt);\n\t\t\t});\n\t\t},\n\n\n\t\t_fixEvent = function (evt){\n\t\t\tif( !evt.target ){ evt.target = window.event && window.event.srcElement || document; }\n\t\t\tif( evt.target.nodeType === 3 ){ evt.target = evt.target.parentNode; }\n\t\t\treturn  evt;\n\t\t},\n\n\n\t\t_supportInputAttr = function (attr){\n\t\t\tvar input = document.createElement('input');\n\t\t\tinput.setAttribute('type', \"file\");\n\t\t\treturn attr in input;\n\t\t},\n\n\n\t\t/**\n\t\t * FileAPI (core object)\n\t\t */\n\t\tapi = {\n\t\t\tversion: '2.0.7',\n\n\t\t\tcors: false,\n\t\t\thtml5: true,\n\t\t\tmedia: false,\n\t\t\tformData: true,\n\t\t\tmultiPassResize: true,\n\n\t\t\tdebug: false,\n\t\t\tpingUrl: false,\n\t\t\tmultiFlash: false,\n\t\t\tflashAbortTimeout: 0,\n\t\t\twithCredentials: true,\n\n\t\t\tstaticPath: './dist/',\n\n\t\t\tflashUrl: 0, // @default: './FileAPI.flash.swf'\n\t\t\tflashImageUrl: 0, // @default: './FileAPI.flash.image.swf'\n\n\t\t\tpostNameConcat: function (name, idx){\n\t\t\t\treturn\tname + (idx != null ? '['+ idx +']' : '');\n\t\t\t},\n\n\t\t\text2mime: {\n\t\t\t\t  jpg:\t'image/jpeg'\n\t\t\t\t, tif:\t'image/tiff'\n\t\t\t\t, txt:\t'text/plain'\n\t\t\t},\n\n\t\t\t// Fallback for flash\n\t\t\taccept: {\n\t\t\t\t  'image/*': 'art bm bmp dwg dxf cbr cbz fif fpx gif ico iefs jfif jpe jpeg jpg jps jut mcf nap nif pbm pcx pgm pict pm png pnm qif qtif ras rast rf rp svf tga tif tiff xbm xbm xpm xwd'\n\t\t\t\t, 'audio/*': 'm4a flac aac rm mpa wav wma ogg mp3 mp2 m3u mod amf dmf dsm far gdm imf it m15 med okt s3m stm sfx ult uni xm sid ac3 dts cue aif aiff wpl ape mac mpc mpp shn wv nsf spc gym adplug adx dsp adp ymf ast afc hps xs'\n\t\t\t\t, 'video/*': 'm4v 3gp nsv ts ty strm rm rmvb m3u ifo mov qt divx xvid bivx vob nrg img iso pva wmv asf asx ogm m2v avi bin dat dvr-ms mpg mpeg mp4 mkv avc vp3 svq3 nuv viv dv fli flv wpl'\n\t\t\t},\n\n\t\t\tuploadRetry : 0,\n\t\t\tnetworkDownRetryTimeout : 5000, // milliseconds, don't flood when network is down\n\n\t\t\tchunkSize : 0,\n\t\t\tchunkUploadRetry : 0,\n\t\t\tchunkNetworkDownRetryTimeout : 2000, // milliseconds, don't flood when network is down\n\n\t\t\tKB: _SIZE_CONST(1),\n\t\t\tMB: _SIZE_CONST(2),\n\t\t\tGB: _SIZE_CONST(3),\n\t\t\tTB: _SIZE_CONST(4),\n\n\t\t\tEMPTY_PNG: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAC0lEQVQIW2NkAAIAAAoAAggA9GkAAAAASUVORK5CYII=',\n\n\t\t\texpando: 'fileapi' + (new Date).getTime(),\n\n\t\t\tuid: function (obj){\n\t\t\t\treturn\tobj\n\t\t\t\t\t? (obj[api.expando] = obj[api.expando] || api.uid())\n\t\t\t\t\t: (++gid, api.expando + gid)\n\t\t\t\t;\n\t\t\t},\n\n\t\t\tlog: function (){\n\t\t\t\tif( api.debug && window.console && console.log ){\n\t\t\t\t\tif( console.log.apply ){\n\t\t\t\t\t\tconsole.log.apply(console, arguments);\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\tconsole.log([].join.call(arguments, ' '));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\n\t\t\t/**\n\t\t\t * Create new image\n\t\t\t *\n\t\t\t * @param {String} [src]\n\t\t\t * @param {Function} [fn]   1. error -- boolean, 2. img -- Image element\n\t\t\t * @returns {HTMLElement}\n\t\t\t */\n\t\t\tnewImage: function (src, fn){\n\t\t\t\tvar img = document.createElement('img');\n\t\t\t\tif( fn ){\n\t\t\t\t\tapi.event.one(img, 'error load', function (evt){\n\t\t\t\t\t\tfn(evt.type == 'error', img);\n\t\t\t\t\t\timg = null;\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\timg.src = src;\n\t\t\t\treturn\timg;\n\t\t\t},\n\n\t\t\t/**\n\t\t\t * Get XHR\n\t\t\t * @returns {XMLHttpRequest}\n\t\t\t */\n\t\t\tgetXHR: function (){\n\t\t\t\tvar xhr;\n\n\t\t\t\tif( XMLHttpRequest ){\n\t\t\t\t\txhr = new XMLHttpRequest;\n\t\t\t\t}\n\t\t\t\telse if( window.ActiveXObject ){\n\t\t\t\t\ttry {\n\t\t\t\t\t\txhr = new ActiveXObject('MSXML2.XMLHttp.3.0');\n\t\t\t\t\t} catch (e) {\n\t\t\t\t\t\txhr = new ActiveXObject('Microsoft.XMLHTTP');\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn  xhr;\n\t\t\t},\n\n\t\t\tisArray: _isArray,\n\n\t\t\tsupport: {\n\t\t\t\tdnd:     cors && ('ondrop' in document.createElement('div')),\n\t\t\t\tcors:    cors,\n\t\t\t\thtml5:   html5,\n\t\t\t\tchunked: chunked,\n\t\t\t\tdataURI: true,\n\t\t\t\taccept:   _supportInputAttr('accept'),\n\t\t\t\tmultiple: _supportInputAttr('multiple')\n\t\t\t},\n\n\t\t\tevent: {\n\t\t\t\t  on: _on\n\t\t\t\t, off: _off\n\t\t\t\t, one: _one\n\t\t\t\t, fix: _fixEvent\n\t\t\t},\n\n\n\t\t\tthrottle: function(fn, delay) {\n\t\t\t\tvar id, args;\n\n\t\t\t\treturn function _throttle(){\n\t\t\t\t\targs = arguments;\n\n\t\t\t\t\tif( !id ){\n\t\t\t\t\t\tfn.apply(window, args);\n\t\t\t\t\t\tid = setTimeout(function (){\n\t\t\t\t\t\t\tid = 0;\n\t\t\t\t\t\t\tfn.apply(window, args);\n\t\t\t\t\t\t}, delay);\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\t},\n\n\n\t\t\tF: function (){},\n\n\n\t\t\tparseJSON: function (str){\n\t\t\t\tvar json;\n\t\t\t\tif( window.JSON && JSON.parse ){\n\t\t\t\t\tjson = JSON.parse(str);\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tjson = (new Function('return ('+str.replace(/([\\r\\n])/g, '\\\\$1')+');'))();\n\t\t\t\t}\n\t\t\t\treturn json;\n\t\t\t},\n\n\n\t\t\ttrim: function (str){\n\t\t\t\tstr = String(str);\n\t\t\t\treturn\tstr.trim ? str.trim() : str.replace(/^\\s+|\\s+$/g, '');\n\t\t\t},\n\n\t\t\t/**\n\t\t\t * Simple Defer\n\t\t\t * @return\t{Object}\n\t\t\t */\n\t\t\tdefer: function (){\n\t\t\t\tvar\n\t\t\t\t\t  list = []\n\t\t\t\t\t, result\n\t\t\t\t\t, error\n\t\t\t\t\t, defer = {\n\t\t\t\t\t\tresolve: function (err, res){\n\t\t\t\t\t\t\tdefer.resolve = noop;\n\t\t\t\t\t\t\terror\t= err || false;\n\t\t\t\t\t\t\tresult\t= res;\n\n\t\t\t\t\t\t\twhile( res = list.shift() ){\n\t\t\t\t\t\t\t\tres(error, result);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\n\t\t\t\t\t\tthen: function (fn){\n\t\t\t\t\t\t\tif( error !== undef ){\n\t\t\t\t\t\t\t\tfn(error, result);\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tlist.push(fn);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t};\n\n\t\t\t\treturn\tdefer;\n\t\t\t},\n\n\t\t\tqueue: function (fn){\n\t\t\t\tvar\n\t\t\t\t\t  _idx = 0\n\t\t\t\t\t, _length = 0\n\t\t\t\t\t, _fail = false\n\t\t\t\t\t, _end = false\n\t\t\t\t\t, queue = {\n\t\t\t\t\t\tinc: function (){\n\t\t\t\t\t\t\t_length++;\n\t\t\t\t\t\t},\n\n\t\t\t\t\t\tnext: function (){\n\t\t\t\t\t\t\t_idx++;\n\t\t\t\t\t\t\tsetTimeout(queue.check, 0);\n\t\t\t\t\t\t},\n\n\t\t\t\t\t\tcheck: function (){\n\t\t\t\t\t\t\t(_idx >= _length) && !_fail && queue.end();\n\t\t\t\t\t\t},\n\n\t\t\t\t\t\tisFail: function (){\n\t\t\t\t\t\t\treturn _fail;\n\t\t\t\t\t\t},\n\n\t\t\t\t\t\tfail: function (){\n\t\t\t\t\t\t\t!_fail && fn(_fail = true);\n\t\t\t\t\t\t},\n\n\t\t\t\t\t\tend: function (){\n\t\t\t\t\t\t\tif( !_end ){\n\t\t\t\t\t\t\t\t_end = true;\n\t\t\t\t\t\t\t\tfn();\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 queue;\n\t\t\t},\n\n\n\t\t\t/**\n\t\t\t * For each object\n\t\t\t *\n\t\t\t * @param\t{Object|Array}\tobj\n\t\t\t * @param\t{Function}\t\tfn\n\t\t\t * @param\t{*}\t\t\t\t[ctx]\n\t\t\t */\n\t\t\teach: _each,\n\n\n\t\t\t/**\n\t\t\t * Async for\n\t\t\t * @param {Array} array\n\t\t\t * @param {Function} callback\n\t\t\t */\n\t\t\tafor: function (array, callback){\n\t\t\t\tvar i = 0, n = array.length;\n\n\t\t\t\tif( _isArray(array) && n-- ){\n\t\t\t\t\t(function _next(){\n\t\t\t\t\t\tcallback(n != i && _next, array[i], i++);\n\t\t\t\t\t})();\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tcallback(false);\n\t\t\t\t}\n\t\t\t},\n\n\n\t\t\t/**\n\t\t\t * Merge the contents of two or more objects together into the first object\n\t\t\t *\n\t\t\t * @param\t{Object}\tdst\n\t\t\t * @return\t{Object}\n\t\t\t */\n\t\t\textend: _extend,\n\n\n\t\t\t/**\n\t\t\t * Is file?\n\t\t\t * @param  {File}  file\n\t\t\t * @return {Boolean}\n\t\t\t */\n\t\t\tisFile: function (file){\n\t\t\t\treturn _toString.call(file) === '[object File]';\n\t\t\t},\n\n\n\t\t\t/**\n\t\t\t * Is blob?\n\t\t\t * @param   {Blob}  blob\n\t\t\t * @returns {Boolean}\n\t\t\t */\n\t\t\tisBlob: function (blob) {\n\t\t\t\treturn this.isFile(blob) || (_toString.call(blob) === '[object Blob]');\n\t\t\t},\n\n\n\t\t\t/**\n\t\t\t * Is canvas element\n\t\t\t *\n\t\t\t * @param\t{HTMLElement}\tel\n\t\t\t * @return\t{Boolean}\n\t\t\t */\n\t\t\tisCanvas: function (el){\n\t\t\t\treturn\tel && _rcanvas.test(el.nodeName);\n\t\t\t},\n\n\n\t\t\tgetFilesFilter: function (filter){\n\t\t\t\tfilter = typeof filter == 'string' ? filter : (filter.getAttribute && filter.getAttribute('accept') || '');\n\t\t\t\treturn\tfilter ? new RegExp('('+ filter.replace(/\\./g, '\\\\.').replace(/,/g, '|') +')$', 'i') : /./;\n\t\t\t},\n\n\n\n\t\t\t/**\n\t\t\t * Read as DataURL\n\t\t\t *\n\t\t\t * @param {File|Element} file\n\t\t\t * @param {Function} fn\n\t\t\t */\n\t\t\treadAsDataURL: function (file, fn){\n\t\t\t\tif( api.isCanvas(file) ){\n\t\t\t\t\t_emit(file, fn, 'load', api.toDataURL(file));\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\t_readAs(file, fn, 'DataURL');\n\t\t\t\t}\n\t\t\t},\n\n\n\t\t\t/**\n\t\t\t * Read as Binary string\n\t\t\t *\n\t\t\t * @param {File} file\n\t\t\t * @param {Function} fn\n\t\t\t */\n\t\t\treadAsBinaryString: function (file, fn){\n\t\t\t\tif( _hasSupportReadAs('BinaryString') ){\n\t\t\t\t\t_readAs(file, fn, 'BinaryString');\n\t\t\t\t} else {\n\t\t\t\t\t// Hello IE10!\n\t\t\t\t\t_readAs(file, function (evt){\n\t\t\t\t\t\tif( evt.type == 'load' ){\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t// dataURL -> binaryString\n\t\t\t\t\t\t\t\tevt.result = api.toBinaryString(evt.result);\n\t\t\t\t\t\t\t} catch (e){\n\t\t\t\t\t\t\t\tevt.type = 'error';\n\t\t\t\t\t\t\t\tevt.message = e.toString();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tfn(evt);\n\t\t\t\t\t}, 'DataURL');\n\t\t\t\t}\n\t\t\t},\n\n\n\t\t\t/**\n\t\t\t * Read as ArrayBuffer\n\t\t\t *\n\t\t\t * @param {File} file\n\t\t\t * @param {Function} fn\n\t\t\t */\n\t\t\treadAsArrayBuffer: function(file, fn){\n\t\t\t\t_readAs(file, fn, 'ArrayBuffer');\n\t\t\t},\n\n\n\t\t\t/**\n\t\t\t * Read as text\n\t\t\t *\n\t\t\t * @param {File} file\n\t\t\t * @param {String} encoding\n\t\t\t * @param {Function} [fn]\n\t\t\t */\n\t\t\treadAsText: function(file, encoding, fn){\n\t\t\t\tif( !fn ){\n\t\t\t\t\tfn\t= encoding;\n\t\t\t\t\tencoding = 'utf-8';\n\t\t\t\t}\n\n\t\t\t\t_readAs(file, fn, 'Text', encoding);\n\t\t\t},\n\n\n\t\t\t/**\n\t\t\t * Convert image or canvas to DataURL\n\t\t\t *\n\t\t\t * @param   {Element}  el      Image or Canvas element\n\t\t\t * @param   {String}   [type]  mime-type\n\t\t\t * @return  {String}\n\t\t\t */\n\t\t\ttoDataURL: function (el, type){\n\t\t\t\tif( typeof el == 'string' ){\n\t\t\t\t\treturn  el;\n\t\t\t\t}\n\t\t\t\telse if( el.toDataURL ){\n\t\t\t\t\treturn  el.toDataURL(type || 'image/png');\n\t\t\t\t}\n\t\t\t},\n\n\n\t\t\t/**\n\t\t\t * Canvert string, image or canvas to binary string\n\t\t\t *\n\t\t\t * @param   {String|Element} val\n\t\t\t * @return  {String}\n\t\t\t */\n\t\t\ttoBinaryString: function (val){\n\t\t\t\treturn  window.atob(api.toDataURL(val).replace(_rdata, ''));\n\t\t\t},\n\n\n\t\t\t/**\n\t\t\t * Read file or DataURL as ImageElement\n\t\t\t *\n\t\t\t * @param\t{File|String}\tfile\n\t\t\t * @param\t{Function}\t\tfn\n\t\t\t * @param\t{Boolean}\t\t[progress]\n\t\t\t */\n\t\t\treadAsImage: function (file, fn, progress){\n\t\t\t\tif( api.isFile(file) ){\n\t\t\t\t\tif( apiURL ){\n\t\t\t\t\t\t/** @namespace apiURL.createObjectURL */\n\t\t\t\t\t\tvar data = apiURL.createObjectURL(file);\n\t\t\t\t\t\tif( data === undef ){\n\t\t\t\t\t\t\t_emit(file, fn, 'error');\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse {\n\t\t\t\t\t\t\tapi.readAsImage(data, fn, progress);\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\tapi.readAsDataURL(file, function (evt){\n\t\t\t\t\t\t\tif( evt.type == 'load' ){\n\t\t\t\t\t\t\t\tapi.readAsImage(evt.result, fn, progress);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse if( progress || evt.type == 'error' ){\n\t\t\t\t\t\t\t\t_emit(file, fn, evt, null, { loaded: evt.loaded, total: evt.total });\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\telse if( api.isCanvas(file) ){\n\t\t\t\t\t_emit(file, fn, 'load', file);\n\t\t\t\t}\n\t\t\t\telse if( _rimg.test(file.nodeName) ){\n\t\t\t\t\tif( file.complete ){\n\t\t\t\t\t\t_emit(file, fn, 'load', file);\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\tvar events = 'error abort load';\n\t\t\t\t\t\t_one(file, events, function _fn(evt){\n\t\t\t\t\t\t\tif( evt.type == 'load' && apiURL ){\n\t\t\t\t\t\t\t\t/** @namespace apiURL.revokeObjectURL */\n\t\t\t\t\t\t\t\tapiURL.revokeObjectURL(file.src);\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t_off(file, events, _fn);\n\t\t\t\t\t\t\t_emit(file, fn, evt, file);\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse if( file.iframe ){\n\t\t\t\t\t_emit(file, fn, { type: 'error' });\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\t// Created image\n\t\t\t\t\tvar img = api.newImage(file.dataURL || file);\n\t\t\t\t\tapi.readAsImage(img, fn, progress);\n\t\t\t\t}\n\t\t\t},\n\n\n\t\t\t/**\n\t\t\t * Make file by name\n\t\t\t *\n\t\t\t * @param\t{String}\tname\n\t\t\t * @return\t{Array}\n\t\t\t */\n\t\t\tcheckFileObj: function (name){\n\t\t\t\tvar file = {}, accept = api.accept;\n\n\t\t\t\tif( typeof name == 'object' ){\n\t\t\t\t\tfile = name;\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tfile.name = (name + '').split(/\\\\|\\//g).pop();\n\t\t\t\t}\n\n\t\t\t\tif( file.type == null ){\n\t\t\t\t\tfile.type = file.name.split('.').pop();\n\t\t\t\t}\n\n\t\t\t\t_each(accept, function (ext, type){\n\t\t\t\t\text = new RegExp(ext.replace(/\\s/g, '|'), 'i');\n\t\t\t\t\tif( ext.test(file.type) || api.ext2mime[file.type] ){\n\t\t\t\t\t\tfile.type = api.ext2mime[file.type] || (type.split('/')[0] +'/'+ file.type);\n\t\t\t\t\t}\n\t\t\t\t});\n\n\t\t\t\treturn\tfile;\n\t\t\t},\n\n\n\t\t\t/**\n\t\t\t * Get drop files\n\t\t\t *\n\t\t\t * @param\t{Event}\tevt\n\t\t\t * @param\t{Function} callback\n\t\t\t */\n\t\t\tgetDropFiles: function (evt, callback){\n\t\t\t\tvar\n\t\t\t\t\t  files = []\n\t\t\t\t\t, dataTransfer = _getDataTransfer(evt)\n\t\t\t\t\t, entrySupport = _isArray(dataTransfer.items) && dataTransfer.items[0] && _getAsEntry(dataTransfer.items[0])\n\t\t\t\t\t, queue = api.queue(function (){ callback(files); })\n\t\t\t\t;\n\n\t\t\t\t_each((entrySupport ? dataTransfer.items : dataTransfer.files) || [], function (item){\n\t\t\t\t\tqueue.inc();\n\n\t\t\t\t\ttry {\n\t\t\t\t\t\tif( entrySupport ){\n\t\t\t\t\t\t\t_readEntryAsFiles(item, function (err, entryFiles){\n\t\t\t\t\t\t\t\tif( err ){\n\t\t\t\t\t\t\t\t\tapi.log('[err] getDropFiles:', err);\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tfiles.push.apply(files, entryFiles);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tqueue.next();\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\t_isRegularFile(item, function (yes){\n\t\t\t\t\t\t\t\tyes && files.push(item);\n\t\t\t\t\t\t\t\tqueue.next();\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\tcatch( err ){\n\t\t\t\t\t\tqueue.next();\n\t\t\t\t\t\tapi.log('[err] getDropFiles: ', err);\n\t\t\t\t\t}\n\t\t\t\t});\n\n\t\t\t\tqueue.check();\n\t\t\t},\n\n\n\t\t\t/**\n\t\t\t * Get file list\n\t\t\t *\n\t\t\t * @param\t{HTMLInputElement|Event}\tinput\n\t\t\t * @param\t{String|Function}\t[filter]\n\t\t\t * @param\t{Function}\t\t\t[callback]\n\t\t\t * @return\t{Array|Null}\n\t\t\t */\n\t\t\tgetFiles: function (input, filter, callback){\n\t\t\t\tvar files = [];\n\n\t\t\t\tif( callback ){\n\t\t\t\t\tapi.filterFiles(api.getFiles(input), filter, callback);\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\n\t\t\t\tif( input.jquery ){\n\t\t\t\t\t// jQuery object\n\t\t\t\t\tinput.each(function (){\n\t\t\t\t\t\tfiles = files.concat(api.getFiles(this));\n\t\t\t\t\t});\n\t\t\t\t\tinput\t= files;\n\t\t\t\t\tfiles\t= [];\n\t\t\t\t}\n\n\t\t\t\tif( typeof filter == 'string' ){\n\t\t\t\t\tfilter\t= api.getFilesFilter(filter);\n\t\t\t\t}\n\n\t\t\t\tif( input.originalEvent ){\n\t\t\t\t\t// jQuery event\n\t\t\t\t\tinput = _fixEvent(input.originalEvent);\n\t\t\t\t}\n\t\t\t\telse if( input.srcElement ){\n\t\t\t\t\t// IE Event\n\t\t\t\t\tinput = _fixEvent(input);\n\t\t\t\t}\n\n\n\t\t\t\tif( input.dataTransfer ){\n\t\t\t\t\t// Drag'n'Drop\n\t\t\t\t\tinput = input.dataTransfer;\n\t\t\t\t}\n\t\t\t\telse if( input.target ){\n\t\t\t\t\t// Event\n\t\t\t\t\tinput = input.target;\n\t\t\t\t}\n\n\t\t\t\tif( input.files ){\n\t\t\t\t\t// Input[type=\"file\"]\n\t\t\t\t\tfiles = input.files;\n\n\t\t\t\t\tif( !html5 ){\n\t\t\t\t\t\t// Partial support for file api\n\t\t\t\t\t\tfiles[0].blob\t= input;\n\t\t\t\t\t\tfiles[0].iframe\t= true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse if( !html5 && isInputFile(input) ){\n\t\t\t\t\tif( api.trim(input.value) ){\n\t\t\t\t\t\tfiles = [api.checkFileObj(input.value)];\n\t\t\t\t\t\tfiles[0].blob   = input;\n\t\t\t\t\t\tfiles[0].iframe = true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse if( _isArray(input) ){\n\t\t\t\t\tfiles\t= input;\n\t\t\t\t}\n\n\t\t\t\treturn\tapi.filter(files, function (file){ return !filter || filter.test(file.name); });\n\t\t\t},\n\n\n\t\t\t/**\n\t\t\t * Get total file size\n\t\t\t * @param\t{Array}\tfiles\n\t\t\t * @return\t{Number}\n\t\t\t */\n\t\t\tgetTotalSize: function (files){\n\t\t\t\tvar size = 0, i = files && files.length;\n\t\t\t\twhile( i-- ){\n\t\t\t\t\tsize += files[i].size;\n\t\t\t\t}\n\t\t\t\treturn\tsize;\n\t\t\t},\n\n\n\t\t\t/**\n\t\t\t * Get image information\n\t\t\t *\n\t\t\t * @param\t{File}\t\tfile\n\t\t\t * @param\t{Function}\tfn\n\t\t\t */\n\t\t\tgetInfo: function (file, fn){\n\t\t\t\tvar info = {}, readers = _infoReader.concat();\n\n\t\t\t\tif( api.isFile(file) ){\n\t\t\t\t\t(function _next(){\n\t\t\t\t\t\tvar reader = readers.shift();\n\t\t\t\t\t\tif( reader ){\n\t\t\t\t\t\t\tif( reader.test(file.type) ){\n\t\t\t\t\t\t\t\treader(file, function (err, res){\n\t\t\t\t\t\t\t\t\tif( err ){\n\t\t\t\t\t\t\t\t\t\tfn(err);\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\t_extend(info, res);\n\t\t\t\t\t\t\t\t\t\t_next();\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\telse {\n\t\t\t\t\t\t\t\t_next();\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\tfn(false, info);\n\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\tfn('not_support_info', info);\n\t\t\t\t}\n\t\t\t},\n\n\n\t\t\t/**\n\t\t\t * Add information reader\n\t\t\t *\n\t\t\t * @param {RegExp} mime\n\t\t\t * @param {Function} fn\n\t\t\t */\n\t\t\taddInfoReader: function (mime, fn){\n\t\t\t\tfn.test = function (type){ return mime.test(type); };\n\t\t\t\t_infoReader.push(fn);\n\t\t\t},\n\n\n\t\t\t/**\n\t\t\t * Filter of array\n\t\t\t *\n\t\t\t * @param\t{Array}\t\tinput\n\t\t\t * @param\t{Function}\tfn\n\t\t\t * @return\t{Array}\n\t\t\t */\n\t\t\tfilter: function (input, fn){\n\t\t\t\tvar result = [], i = 0, n = input.length, val;\n\n\t\t\t\tfor( ; i < n; i++ ){\n\t\t\t\t\tif( i in input ){\n\t\t\t\t\t\tval = input[i];\n\t\t\t\t\t\tif( fn.call(val, val, i, input) ){\n\t\t\t\t\t\t\tresult.push(val);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn\tresult;\n\t\t\t},\n\n\n\t\t\t/**\n\t\t\t * Filter files\n\t\t\t *\n\t\t\t * @param\t{Array}\t\tfiles\n\t\t\t * @param\t{Function}\teachFn\n\t\t\t * @param\t{Function}\tresultFn\n\t\t\t */\n\t\t\tfilterFiles: function (files, eachFn, resultFn){\n\t\t\t\tif( files.length ){\n\t\t\t\t\t// HTML5 or Flash\n\t\t\t\t\tvar queue = files.concat(), file, result = [], deleted = [];\n\n\t\t\t\t\t(function _next(){\n\t\t\t\t\t\tif( queue.length ){\n\t\t\t\t\t\t\tfile = queue.shift();\n\t\t\t\t\t\t\tapi.getInfo(file, function (err, info){\n\t\t\t\t\t\t\t\t(eachFn(file, err ? false : info) ? result : deleted).push(file);\n\t\t\t\t\t\t\t\t_next();\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\tresultFn(result, deleted);\n\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\tresultFn([], files);\n\t\t\t\t}\n\t\t\t},\n\n\n\t\t\tupload: function (options){\n\t\t\t\toptions = _extend({\n\t\t\t\t\t  jsonp: 'callback'\n\t\t\t\t\t, prepare: api.F\n\t\t\t\t\t, beforeupload: api.F\n\t\t\t\t\t, upload: api.F\n\t\t\t\t\t, fileupload: api.F\n\t\t\t\t\t, fileprogress: api.F\n\t\t\t\t\t, filecomplete: api.F\n\t\t\t\t\t, progress: api.F\n\t\t\t\t\t, complete: api.F\n\t\t\t\t\t, pause: api.F\n\t\t\t\t\t, imageOriginal: true\n\t\t\t\t\t, chunkSize: api.chunkSize\n\t\t\t\t\t, chunkUploadRetry: api.chunkUploadRetry\n\t\t\t\t\t, uploadRetry: api.uploadRetry\n\t\t\t\t}, options);\n\n\n\t\t\t\tif( options.imageAutoOrientation && !options.imageTransform ){\n\t\t\t\t\toptions.imageTransform = { rotate: 'auto' };\n\t\t\t\t}\n\n\n\t\t\t\tvar\n\t\t\t\t\t  proxyXHR = new api.XHR(options)\n\t\t\t\t\t, dataArray = this._getFilesDataArray(options.files)\n\t\t\t\t\t, _this = this\n\t\t\t\t\t, _total = 0\n\t\t\t\t\t, _loaded = 0\n\t\t\t\t\t, _nextFile\n\t\t\t\t\t, _complete = false\n\t\t\t\t;\n\n\n\t\t\t\t// calc total size\n\t\t\t\t_each(dataArray, function (data){\n\t\t\t\t\t_total += data.size;\n\t\t\t\t});\n\n\t\t\t\t// Array of files\n\t\t\t\tproxyXHR.files = [];\n\t\t\t\t_each(dataArray, function (data){\n\t\t\t\t\tproxyXHR.files.push(data.file);\n\t\t\t\t});\n\n\t\t\t\t// Set upload status props\n\t\t\t\tproxyXHR.total\t= _total;\n\t\t\t\tproxyXHR.loaded\t= 0;\n\t\t\t\tproxyXHR.filesLeft = dataArray.length;\n\n\t\t\t\t// emit \"beforeupload\"  event\n\t\t\t\toptions.beforeupload(proxyXHR, options);\n\n\t\t\t\t// Upload by file\n\t\t\t\t_nextFile = function (){\n\t\t\t\t\tvar\n\t\t\t\t\t\t  data = dataArray.shift()\n\t\t\t\t\t\t, _file = data && data.file\n\t\t\t\t\t\t, _fileLoaded = false\n\t\t\t\t\t\t, _fileOptions = _simpleClone(options)\n\t\t\t\t\t;\n\n\t\t\t\t\tproxyXHR.filesLeft = dataArray.length;\n\n\t\t\t\t\tif( _file && _file.name === api.expando ){\n\t\t\t\t\t\t_file = null;\n\t\t\t\t\t\tapi.log('[warn] FileAPI.upload() — called without files');\n\t\t\t\t\t}\n\n\t\t\t\t\tif( ( proxyXHR.statusText != 'abort' || proxyXHR.current ) && data ){\n\t\t\t\t\t\t// Mark active job\n\t\t\t\t\t\t_complete = false;\n\n\t\t\t\t\t\t// Set current upload file\n\t\t\t\t\t\tproxyXHR.currentFile = _file;\n\n\t\t\t\t\t\t// Prepare file options\n\t\t\t\t\t\tif (_file && options.prepare(_file, _fileOptions) === false) {\n\t\t\t\t\t\t\t_nextFile.call(_this);\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t\t_fileOptions.file = _file;\n\n\t\t\t\t\t\t_this._getFormData(_fileOptions, data, function (form){\n\t\t\t\t\t\t\tif( !_loaded ){\n\t\t\t\t\t\t\t\t// emit \"upload\" event\n\t\t\t\t\t\t\t\toptions.upload(proxyXHR, options);\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tvar xhr = new api.XHR(_extend({}, _fileOptions, {\n\n\t\t\t\t\t\t\t\tupload: _file ? function (){\n\t\t\t\t\t\t\t\t\t// emit \"fileupload\" event\n\t\t\t\t\t\t\t\t\toptions.fileupload(_file, xhr, _fileOptions);\n\t\t\t\t\t\t\t\t} : noop,\n\n\t\t\t\t\t\t\t\tprogress: _file ? function (evt){\n\t\t\t\t\t\t\t\t\tif( !_fileLoaded ){\n\t\t\t\t\t\t\t\t\t\t// For ignore the double calls.\n\t\t\t\t\t\t\t\t\t\t_fileLoaded = (evt.loaded === evt.total);\n\n\t\t\t\t\t\t\t\t\t\t// emit \"fileprogress\" event\n\t\t\t\t\t\t\t\t\t\toptions.fileprogress({\n\t\t\t\t\t\t\t\t\t\t\t  type:   'progress'\n\t\t\t\t\t\t\t\t\t\t\t, total:  data.total = evt.total\n\t\t\t\t\t\t\t\t\t\t\t, loaded: data.loaded = evt.loaded\n\t\t\t\t\t\t\t\t\t\t}, _file, xhr, _fileOptions);\n\n\t\t\t\t\t\t\t\t\t\t// emit \"progress\" event\n\t\t\t\t\t\t\t\t\t\toptions.progress({\n\t\t\t\t\t\t\t\t\t\t\t  type:   'progress'\n\t\t\t\t\t\t\t\t\t\t\t, total:  _total\n\t\t\t\t\t\t\t\t\t\t\t, loaded: proxyXHR.loaded = (_loaded + data.size * (evt.loaded/evt.total))|0\n\t\t\t\t\t\t\t\t\t\t}, _file, xhr, _fileOptions);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t} : noop,\n\n\t\t\t\t\t\t\t\tcomplete: function (err){\n\t\t\t\t\t\t\t\t\t_each(_xhrPropsExport, function (name){\n\t\t\t\t\t\t\t\t\t\tproxyXHR[name] = xhr[name];\n\t\t\t\t\t\t\t\t\t});\n\n\t\t\t\t\t\t\t\t\tif( _file ){\n\t\t\t\t\t\t\t\t\t\tdata.total = (data.total || data.size);\n\t\t\t\t\t\t\t\t\t\tdata.loaded\t= data.total;\n\n\t\t\t\t\t\t\t\t\t\tif( !err ) {\n\t\t\t\t\t\t\t\t\t\t\t// emulate 100% \"progress\"\n\t\t\t\t\t\t\t\t\t\t\tthis.progress(data);\n\n\t\t\t\t\t\t\t\t\t\t\t// fixed throttle event\n\t\t\t\t\t\t\t\t\t\t\t_fileLoaded = true;\n\n\t\t\t\t\t\t\t\t\t\t\t// bytes loaded\n\t\t\t\t\t\t\t\t\t\t\t_loaded += data.size; // data.size != data.total, it's desirable fix this\n\t\t\t\t\t\t\t\t\t\t\tproxyXHR.loaded = _loaded;\n\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t// emit \"filecomplete\" event\n\t\t\t\t\t\t\t\t\t\toptions.filecomplete(err, xhr, _file, _fileOptions);\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t// upload next file\n\t\t\t\t\t\t\t\t\tsetTimeout(function () {_nextFile.call(_this);}, 0);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t})); // xhr\n\n\n\t\t\t\t\t\t\t// ...\n\t\t\t\t\t\t\tproxyXHR.abort = function (current){\n\t\t\t\t\t\t\t\tif (!current) { dataArray.length = 0; }\n\t\t\t\t\t\t\t\tthis.current = current;\n\t\t\t\t\t\t\t\txhr.abort();\n\t\t\t\t\t\t\t};\n\n\t\t\t\t\t\t\t// Start upload\n\t\t\t\t\t\t\txhr.send(form);\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\tvar successful = proxyXHR.status == 200 || proxyXHR.status == 201 || proxyXHR.status == 204;\n\t\t\t\t\t\toptions.complete(successful ? false : (proxyXHR.statusText || 'error'), proxyXHR, options);\n\t\t\t\t\t\t// Mark done state\n\t\t\t\t\t\t_complete = true;\n\t\t\t\t\t}\n\t\t\t\t};\n\n\n\t\t\t\t// Next tick\n\t\t\t\tsetTimeout(_nextFile, 0);\n\n\n\t\t\t\t// Append more files to the existing request\n\t\t\t\t// first - add them to the queue head/tail\n\t\t\t\tproxyXHR.append = function (files, first) {\n\t\t\t\t\tfiles = api._getFilesDataArray([].concat(files));\n\n\t\t\t\t\t_each(files, function (data) {\n\t\t\t\t\t\t_total += data.size;\n\t\t\t\t\t\tproxyXHR.files.push(data.file);\n\t\t\t\t\t\tif (first) {\n\t\t\t\t\t\t\tdataArray.unshift(data);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tdataArray.push(data);\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\n\t\t\t\t\tproxyXHR.statusText = \"\";\n\n\t\t\t\t\tif( _complete ){\n\t\t\t\t\t\t_nextFile.call(_this);\n\t\t\t\t\t}\n\t\t\t\t};\n\n\n\t\t\t\t// Removes file from queue by file reference and returns it\n\t\t\t\tproxyXHR.remove = function (file) {\n\t\t\t\t    var i = dataArray.length, _file;\n\t\t\t\t    while( i-- ){\n\t\t\t\t\t\tif( dataArray[i].file == file ){\n\t\t\t\t\t\t\t_file = dataArray.splice(i, 1);\n\t\t\t\t\t\t\t_total -= _file.size;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\treturn\t_file;\n\t\t\t\t};\n\n\t\t\t\treturn proxyXHR;\n\t\t\t},\n\n\n\t\t\t_getFilesDataArray: function (data){\n\t\t\t\tvar files = [], oFiles = {};\n\n\t\t\t\tif( isInputFile(data) ){\n\t\t\t\t\tvar tmp = api.getFiles(data);\n\t\t\t\t\toFiles[data.name || 'file'] = data.getAttribute('multiple') !== null ? tmp : tmp[0];\n\t\t\t\t}\n\t\t\t\telse if( _isArray(data) && isInputFile(data[0]) ){\n\t\t\t\t\t_each(data, function (input){\n\t\t\t\t\t\toFiles[input.name || 'file'] = api.getFiles(input);\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\toFiles = data;\n\t\t\t\t}\n\n\t\t\t\t_each(oFiles, function add(file, name){\n\t\t\t\t\tif( _isArray(file) ){\n\t\t\t\t\t\t_each(file, function (file){\n\t\t\t\t\t\t\tadd(file, name);\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t\telse if( file && (file.name || file.image) ){\n\t\t\t\t\t\tfiles.push({\n\t\t\t\t\t\t\t  name: name\n\t\t\t\t\t\t\t, file: file\n\t\t\t\t\t\t\t, size: file.size\n\t\t\t\t\t\t\t, total: file.size\n\t\t\t\t\t\t\t, loaded: 0\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t});\n\n\t\t\t\tif( !files.length ){\n\t\t\t\t\t// Create fake `file` object\n\t\t\t\t\tfiles.push({ file: { name: api.expando } });\n\t\t\t\t}\n\n\t\t\t\treturn\tfiles;\n\t\t\t},\n\n\n\t\t\t_getFormData: function (options, data, fn){\n\t\t\t\tvar\n\t\t\t\t\t  file = data.file\n\t\t\t\t\t, name = data.name\n\t\t\t\t\t, filename = file.name\n\t\t\t\t\t, filetype = file.type\n\t\t\t\t\t, trans = api.support.transform && options.imageTransform\n\t\t\t\t\t, Form = new api.Form\n\t\t\t\t\t, queue = api.queue(function (){ fn(Form); })\n\t\t\t\t\t, isOrignTrans = trans && _isOriginTransform(trans)\n\t\t\t\t\t, postNameConcat = api.postNameConcat\n\t\t\t\t;\n\n\t\t\t\t// Append data\n\t\t\t\t_each(options.data, function add(val, name){\n\t\t\t\t\tif( typeof val == 'object' ){\n\t\t\t\t\t\t_each(val, function (v, i){\n\t\t\t\t\t\t\tadd(v, postNameConcat(name, 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\tForm.append(name, val);\n\t\t\t\t\t}\n\t\t\t\t});\n\n\t\t\t\t(function _addFile(file/**Object*/){\n\t\t\t\t\tif( file.image ){ // This is a FileAPI.Image\n\t\t\t\t\t\tqueue.inc();\n\n\t\t\t\t\t\tfile.toData(function (err, image){\n\t\t\t\t\t\t\t// @todo: error\n\t\t\t\t\t\t\tfilename = filename || (new Date).getTime()+'.png';\n\n\t\t\t\t\t\t\t_addFile(image);\n\t\t\t\t\t\t\tqueue.next();\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t\telse if( api.Image && trans && (/^image/.test(file.type) || _rimgcanvas.test(file.nodeName)) ){\n\t\t\t\t\t\tqueue.inc();\n\n\t\t\t\t\t\tif( isOrignTrans ){\n\t\t\t\t\t\t\t// Convert to array for transform function\n\t\t\t\t\t\t\ttrans = [trans];\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tapi.Image.transform(file, trans, options.imageAutoOrientation, function (err, images){\n\t\t\t\t\t\t\tif( isOrignTrans && !err ){\n\t\t\t\t\t\t\t\tif( !dataURLtoBlob && !api.flashEngine ){\n\t\t\t\t\t\t\t\t\t// Canvas.toBlob or Flash not supported, use multipart\n\t\t\t\t\t\t\t\t\tForm.multipart = true;\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\tForm.append(name, images[0], filename,  trans[0].type || filetype);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse {\n\t\t\t\t\t\t\t\tvar addOrigin = 0;\n\n\t\t\t\t\t\t\t\tif( !err ){\n\t\t\t\t\t\t\t\t\t_each(images, function (image, idx){\n\t\t\t\t\t\t\t\t\t\tif( !dataURLtoBlob && !api.flashEngine ){\n\t\t\t\t\t\t\t\t\t\t\tForm.multipart = true;\n\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\tif( !trans[idx].postName ){\n\t\t\t\t\t\t\t\t\t\t\taddOrigin = 1;\n\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\tForm.append(trans[idx].postName || postNameConcat(name, idx), image, filename, trans[idx].type || filetype);\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\tif( err || options.imageOriginal ){\n\t\t\t\t\t\t\t\t\tForm.append(postNameConcat(name, (addOrigin ? 'original' : null)), file, filename, filetype);\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\tqueue.next();\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t\telse if( filename !== api.expando ){\n\t\t\t\t\t\tForm.append(name, file, filename);\n\t\t\t\t\t}\n\t\t\t\t})(file);\n\n\t\t\t\tqueue.check();\n\t\t\t},\n\n\n\t\t\treset: function (inp, notRemove){\n\t\t\t\tvar parent, clone;\n\n\t\t\t\tif( jQuery ){\n\t\t\t\t\tclone = jQuery(inp).clone(true).insertBefore(inp).val('')[0];\n\t\t\t\t\tif( !notRemove ){\n\t\t\t\t\t\tjQuery(inp).remove();\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tparent  = inp.parentNode;\n\t\t\t\t\tclone   = parent.insertBefore(inp.cloneNode(true), inp);\n\t\t\t\t\tclone.value = '';\n\n\t\t\t\t\tif( !notRemove ){\n\t\t\t\t\t\tparent.removeChild(inp);\n\t\t\t\t\t}\n\n\t\t\t\t\t_each(_elEvents[api.uid(inp)], function (fns, type){\n\t\t\t\t\t\t_each(fns, function (fn){\n\t\t\t\t\t\t\t_off(inp, type, fn);\n\t\t\t\t\t\t\t_on(clone, type, fn);\n\t\t\t\t\t\t});\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\treturn  clone;\n\t\t\t},\n\n\n\t\t\t/**\n\t\t\t * Load remote file\n\t\t\t *\n\t\t\t * @param   {String}    url\n\t\t\t * @param   {Function}  fn\n\t\t\t * @return  {XMLHttpRequest}\n\t\t\t */\n\t\t\tload: function (url, fn){\n\t\t\t\tvar xhr = api.getXHR();\n\t\t\t\tif( xhr ){\n\t\t\t\t\txhr.open('GET', url, true);\n\n\t\t\t\t\tif( xhr.overrideMimeType ){\n\t\t\t\t        xhr.overrideMimeType('text/plain; charset=x-user-defined');\n\t\t\t\t\t}\n\n\t\t\t\t\t_on(xhr, 'progress', function (/**Event*/evt){\n\t\t\t\t\t\t/** @namespace evt.lengthComputable */\n\t\t\t\t\t\tif( evt.lengthComputable ){\n\t\t\t\t\t\t\tfn({ type: evt.type, loaded: evt.loaded, total: evt.total }, xhr);\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\n\t\t\t\t\txhr.onreadystatechange = function(){\n\t\t\t\t\t\tif( xhr.readyState == 4 ){\n\t\t\t\t\t\t\txhr.onreadystatechange = null;\n\t\t\t\t\t\t\tif( xhr.status == 200 ){\n\t\t\t\t\t\t\t\turl = url.split('/');\n\t\t\t\t\t\t\t\t/** @namespace xhr.responseBody */\n\t\t\t\t\t\t\t\tvar file = {\n\t\t\t\t\t\t\t\t      name: url[url.length-1]\n\t\t\t\t\t\t\t\t\t, size: xhr.getResponseHeader('Content-Length')\n\t\t\t\t\t\t\t\t\t, type: xhr.getResponseHeader('Content-Type')\n\t\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\t\tfile.dataURL = 'data:'+file.type+';base64,' + api.encode64(xhr.responseBody || xhr.responseText);\n\t\t\t\t\t\t\t\tfn({ type: 'load', result: file }, xhr);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse {\n\t\t\t\t\t\t\t\tfn({ type: 'error' }, xhr);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t    }\n\t\t\t\t\t};\n\t\t\t\t    xhr.send(null);\n\t\t\t\t} else {\n\t\t\t\t\tfn({ type: 'error' });\n\t\t\t\t}\n\n\t\t\t\treturn  xhr;\n\t\t\t},\n\n\t\t\tencode64: function (str){\n\t\t\t\tvar b64 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=', outStr = '', i = 0;\n\n\t\t\t\tif( typeof str !== 'string' ){\n\t\t\t\t\tstr\t= String(str);\n\t\t\t\t}\n\n\t\t\t\twhile( i < str.length ){\n\t\t\t\t\t//all three \"& 0xff\" added below are there to fix a known bug\n\t\t\t\t\t//with bytes returned by xhr.responseText\n\t\t\t\t\tvar\n\t\t\t\t\t\t  byte1 = str.charCodeAt(i++) & 0xff\n\t\t\t\t\t\t, byte2 = str.charCodeAt(i++) & 0xff\n\t\t\t\t\t\t, byte3 = str.charCodeAt(i++) & 0xff\n\t\t\t\t\t\t, enc1 = byte1 >> 2\n\t\t\t\t\t\t, enc2 = ((byte1 & 3) << 4) | (byte2 >> 4)\n\t\t\t\t\t\t, enc3, enc4\n\t\t\t\t\t;\n\n\t\t\t\t\tif( isNaN(byte2) ){\n\t\t\t\t\t\tenc3 = enc4 = 64;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tenc3 = ((byte2 & 15) << 2) | (byte3 >> 6);\n\t\t\t\t\t\tenc4 = isNaN(byte3) ? 64 : byte3 & 63;\n\t\t\t\t\t}\n\n\t\t\t\t\toutStr += b64.charAt(enc1) + b64.charAt(enc2) + b64.charAt(enc3) + b64.charAt(enc4);\n\t\t\t\t}\n\n\t\t\t\treturn  outStr;\n\t\t\t}\n\n\t\t} // api\n\t;\n\n\n\tfunction _emit(target, fn, name, res, ext){\n\t\tvar evt = {\n\t\t\t  type:\t\tname.type || name\n\t\t\t, target:\ttarget\n\t\t\t, result:\tres\n\t\t};\n\t\t_extend(evt, ext);\n\t\tfn(evt);\n\t}\n\n\n\tfunction _hasSupportReadAs(as){\n\t\treturn\tFileReader && !!FileReader.prototype['readAs'+as];\n\t}\n\n\n\tfunction _readAs(file, fn, as, encoding){\n\t\tif( api.isBlob(file) && _hasSupportReadAs(as) ){\n\t\t\tvar Reader = new FileReader;\n\n\t\t\t// Add event listener\n\t\t\t_on(Reader, _readerEvents, function _fn(evt){\n\t\t\t\tvar type = evt.type;\n\t\t\t\tif( type == 'progress' ){\n\t\t\t\t\t_emit(file, fn, evt, evt.target.result, { loaded: evt.loaded, total: evt.total });\n\t\t\t\t}\n\t\t\t\telse if( type == 'loadend' ){\n\t\t\t\t\t_off(Reader, _readerEvents, _fn);\n\t\t\t\t\tReader = null;\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\t_emit(file, fn, evt, evt.target.result);\n\t\t\t\t}\n\t\t\t});\n\n\n\t\t\ttry {\n\t\t\t\t// ReadAs ...\n\t\t\t\tif( encoding ){\n\t\t\t\t\tReader['readAs'+as](file, encoding);\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tReader['readAs'+as](file);\n\t\t\t\t}\n\t\t\t}\n\t\t\tcatch (err){\n\t\t\t\t_emit(file, fn, 'error', undef, { error: err.toString() });\n\t\t\t}\n\t\t}\n\t\telse {\n\t\t\t_emit(file, fn, 'error', undef, { error: 'filreader_not_support_'+as });\n\t\t}\n\t}\n\n\n\tfunction _isRegularFile(file, callback){\n\t\t// http://stackoverflow.com/questions/8856628/detecting-folders-directories-in-javascript-filelist-objects\n\t\tif( !file.type && (file.size % 4096) === 0 && (file.size <= 102400) ){\n\t\t\tif( FileReader ){\n\t\t\t\ttry {\n\t\t\t\t\tvar Reader = new FileReader();\n\n\t\t\t\t\t_one(Reader, _readerEvents, function (evt){\n\t\t\t\t\t\tvar isFile = evt.type != 'error';\n\t\t\t\t\t\tcallback(isFile);\n\t\t\t\t\t\tif( isFile ){\n\t\t\t\t\t\t\tReader.abort();\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\n\t\t\t\t\tReader.readAsDataURL(file);\n\t\t\t\t} catch( err ){\n\t\t\t\t\tcallback(false);\n\t\t\t\t}\n\t\t\t}\n\t\t\telse {\n\t\t\t\tcallback(null);\n\t\t\t}\n\t\t}\n\t\telse {\n\t\t\tcallback(true);\n\t\t}\n\t}\n\n\n\tfunction _getAsEntry(item){\n\t\tvar entry;\n\t\tif( item.getAsEntry ){ entry = item.getAsEntry(); }\n\t\telse if( item.webkitGetAsEntry ){ entry = item.webkitGetAsEntry(); }\n\t\treturn\tentry;\n\t}\n\n\n\tfunction _readEntryAsFiles(entry, callback){\n\t\tif( !entry ){\n\t\t\t// error\n\t\t\tcallback('invalid entry');\n\t\t}\n\t\telse if( entry.isFile ){\n\t\t\t// Read as file\n\t\t\tentry.file(function(file){\n\t\t\t\t// success\n\t\t\t\tfile.fullPath = entry.fullPath;\n\t\t\t\tcallback(false, [file]);\n\t\t\t}, function (err){\n\t\t\t\t// error\n\t\t\t\tcallback('FileError.code: '+err.code);\n\t\t\t});\n\t\t}\n\t\telse if( entry.isDirectory ){\n\t\t\tvar reader = entry.createReader(), result = [];\n\n\t\t\treader.readEntries(function(entries){\n\t\t\t\t// success\n\t\t\t\tapi.afor(entries, function (next, entry){\n\t\t\t\t\t_readEntryAsFiles(entry, function (err, files){\n\t\t\t\t\t\tif( err ){\n\t\t\t\t\t\t\tapi.log(err);\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse {\n\t\t\t\t\t\t\tresult = result.concat(files);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif( next ){\n\t\t\t\t\t\t\tnext();\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse {\n\t\t\t\t\t\t\tcallback(false, result);\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t});\n\t\t\t}, function (err){\n\t\t\t\t// error\n\t\t\t\tcallback('directory_reader: ' + err);\n\t\t\t});\n\t\t}\n\t\telse {\n\t\t\t_readEntryAsFiles(_getAsEntry(entry), callback);\n\t\t}\n\t}\n\n\n\tfunction _simpleClone(obj){\n\t\tvar copy = {};\n\t\t_each(obj, function (val, key){\n\t\t\tif( val && (typeof val === 'object') && (val.nodeType === void 0) ){\n\t\t\t\tval = _extend({}, val);\n\t\t\t}\n\t\t\tcopy[key] = val;\n\t\t});\n\t\treturn\tcopy;\n\t}\n\n\n\tfunction isInputFile(el){\n\t\treturn\t_rinput.test(el && el.tagName);\n\t}\n\n\n\tfunction _getDataTransfer(evt){\n\t\treturn\t(evt.originalEvent || evt || '').dataTransfer || {};\n\t}\n\n\n\tfunction _isOriginTransform(trans){\n\t\tvar key;\n\t\tfor( key in trans ){\n\t\t\tif( trans.hasOwnProperty(key) ){\n\t\t\t\tif( !(trans[key] instanceof Object || key === 'overlay' || key === 'filter') ){\n\t\t\t\t\treturn\ttrue;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn\tfalse;\n\t}\n\n\n\t// Add default image info reader\n\tapi.addInfoReader(/^image/, function (file/**File*/, callback/**Function*/){\n\t\tif( !file.__dimensions ){\n\t\t\tvar defer = file.__dimensions = api.defer();\n\n\t\t\tapi.readAsImage(file, function (evt){\n\t\t\t\tvar img = evt.target;\n\t\t\t\tdefer.resolve(evt.type == 'load' ? false : 'error', {\n\t\t\t\t\t  width:  img.width\n\t\t\t\t\t, height: img.height\n\t\t\t\t});\n                img.src = api.EMPTY_PNG;\n\t\t\t\timg = null;\n\t\t\t});\n\t\t}\n\n\t\tfile.__dimensions.then(callback);\n\t});\n\n\n\t/**\n\t * Drag'n'Drop special event\n\t *\n\t * @param\t{HTMLElement}\tel\n\t * @param\t{Function}\t\tonHover\n\t * @param\t{Function}\t\tonDrop\n\t */\n\tapi.event.dnd = function (el, onHover, onDrop){\n\t\tvar _id, _type;\n\n\t\tif( !onDrop ){\n\t\t\tonDrop = onHover;\n\t\t\tonHover = api.F;\n\t\t}\n\n\t\tif( FileReader ){\n\t\t\t// Hover\n\t\t\t_on(el, 'dragenter dragleave dragover', onHover.ff = onHover.ff || function (evt){\n\t\t\t\tvar\n\t\t\t\t\t  types = _getDataTransfer(evt).types\n\t\t\t\t\t, i = types && types.length\n\t\t\t\t\t, debounceTrigger = false\n\t\t\t\t;\n\n\t\t\t\twhile( i-- ){\n\t\t\t\t\tif( ~types[i].indexOf('File') ){\n\t\t\t\t\t\tevt[preventDefault]();\n\n\t\t\t\t\t\tif( _type !== evt.type ){\n\t\t\t\t\t\t\t_type = evt.type; // Store current type of event\n\n\t\t\t\t\t\t\tif( _type != 'dragleave' ){\n\t\t\t\t\t\t\t\tonHover.call(evt[currentTarget], true, evt);\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tdebounceTrigger = true;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tbreak; // exit from \"while\"\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif( debounceTrigger ){\n\t\t\t\t\tclearTimeout(_id);\n\t\t\t\t\t_id = setTimeout(function (){\n\t\t\t\t\t\tonHover.call(evt[currentTarget], _type != 'dragleave', evt);\n\t\t\t\t\t}, 50);\n\t\t\t\t}\n\t\t\t});\n\n\n\t\t\t// Drop\n\t\t\t_on(el, 'drop', onDrop.ff = onDrop.ff || function (evt){\n\t\t\t\tevt[preventDefault]();\n\n\t\t\t\t_type = 0;\n\t\t\t\tonHover.call(evt[currentTarget], false, evt);\n\n\t\t\t\tapi.getDropFiles(evt, function (files){\n\t\t\t\t\tonDrop.call(evt[currentTarget], files, evt);\n\t\t\t\t});\n\t\t\t});\n\t\t}\n\t\telse {\n\t\t\tapi.log(\"Drag'n'Drop -- not supported\");\n\t\t}\n\t};\n\n\n\t/**\n\t * Remove drag'n'drop\n\t * @param\t{HTMLElement}\tel\n\t * @param\t{Function}\t\tonHover\n\t * @param\t{Function}\t\tonDrop\n\t */\n\tapi.event.dnd.off = function (el, onHover, onDrop){\n\t\t_off(el, 'dragenter dragleave dragover', onHover.ff);\n\t\t_off(el, 'drop', onDrop.ff);\n\t};\n\n\n\t// Support jQuery\n\tif( jQuery && !jQuery.fn.dnd ){\n\t\tjQuery.fn.dnd = function (onHover, onDrop){\n\t\t\treturn this.each(function (){\n\t\t\t\tapi.event.dnd(this, onHover, onDrop);\n\t\t\t});\n\t\t};\n\n\t\tjQuery.fn.offdnd = function (onHover, onDrop){\n\t\t\treturn this.each(function (){\n\t\t\t\tapi.event.dnd.off(this, onHover, onDrop);\n\t\t\t});\n\t\t};\n\t}\n\n\t// @export\n\twindow.FileAPI  = _extend(api, window.FileAPI);\n\n\n\t// Debug info\n\tapi.log('FileAPI: ' + api.version);\n\tapi.log('protocol: ' + window.location.protocol);\n\tapi.log('doctype: [' + doctype.name + '] ' + doctype.publicId + ' ' + doctype.systemId);\n\n\n\t// @detect 'x-ua-compatible'\n\t_each(document.getElementsByTagName('meta'), function (meta){\n\t\tif( /x-ua-compatible/i.test(meta.getAttribute('http-equiv')) ){\n\t\t\tapi.log('meta.http-equiv: ' + meta.getAttribute('content'));\n\t\t}\n\t});\n\n\n\t// @configuration\n\tif( !api.flashUrl ){ api.flashUrl = api.staticPath + 'FileAPI.flash.swf'; }\n\tif( !api.flashImageUrl ){ api.flashImageUrl = api.staticPath + 'FileAPI.flash.image.swf'; }\n\tif( !api.flashWebcamUrl ){ api.flashWebcamUrl = api.staticPath + 'FileAPI.flash.camera.swf'; }\n})(window, void 0);\n\n/*global window, FileAPI, document */\n\n(function (api, document, undef) {\n\t'use strict';\n\n\tvar\n\t\tmin = Math.min,\n\t\tround = Math.round,\n\t\tgetCanvas = function () { return document.createElement('canvas'); },\n\t\tsupport = false,\n\t\texifOrientation = {\n\t\t\t  8:\t270\n\t\t\t, 3:\t180\n\t\t\t, 6:\t90\n\t\t\t, 7:\t270\n\t\t\t, 4:\t180\n\t\t\t, 5:\t90\n\t\t}\n\t;\n\n\ttry {\n\t\tsupport = getCanvas().toDataURL('image/png').indexOf('data:image/png') > -1;\n\t}\n\tcatch (e){}\n\n\n\tfunction Image(file){\n\t\tif( file instanceof Image ){\n\t\t\tvar img = new Image(file.file);\n\t\t\tapi.extend(img.matrix, file.matrix);\n\t\t\treturn\timg;\n\t\t}\n\t\telse if( !(this instanceof Image) ){\n\t\t\treturn\tnew Image(file);\n\t\t}\n\n\t\tthis.file   = file;\n\t\tthis.size   = file.size || 100;\n\n\t\tthis.matrix\t= {\n\t\t\tsx: 0,\n\t\t\tsy: 0,\n\t\t\tsw: 0,\n\t\t\tsh: 0,\n\t\t\tdx: 0,\n\t\t\tdy: 0,\n\t\t\tdw: 0,\n\t\t\tdh: 0,\n\t\t\tresize: 0, // min, max OR preview\n\t\t\tdeg: 0,\n\t\t\tquality: 1, // jpeg quality\n\t\t\tfilter: 0\n\t\t};\n\t}\n\n\n\tImage.prototype = {\n\t\timage: true,\n\t\tconstructor: Image,\n\n\t\tset: function (attrs){\n\t\t\tapi.extend(this.matrix, attrs);\n\t\t\treturn\tthis;\n\t\t},\n\n\t\tcrop: function (x, y, w, h){\n\t\t\tif( w === undef ){\n\t\t\t\tw\t= x;\n\t\t\t\th\t= y;\n\t\t\t\tx = y = 0;\n\t\t\t}\n\t\t\treturn\tthis.set({ sx: x, sy: y, sw: w, sh: h || w });\n\t\t},\n\n\t\tresize: function (w, h, strategy){\n\t\t\tif( /min|max/.test(h) ){\n\t\t\t\tstrategy = h;\n\t\t\t\th = w;\n\t\t\t}\n\n\t\t\treturn\tthis.set({ dw: w, dh: h || w, resize: strategy });\n\t\t},\n\n\t\tpreview: function (w, h){\n\t\t\treturn\tthis.resize(w, h || w, 'preview');\n\t\t},\n\n\t\trotate: function (deg){\n\t\t\treturn\tthis.set({ deg: deg });\n\t\t},\n\n\t\tfilter: function (filter){\n\t\t\treturn\tthis.set({ filter: filter });\n\t\t},\n\n\t\toverlay: function (images){\n\t\t\treturn\tthis.set({ overlay: images });\n\t\t},\n\n\t\tclone: function (){\n\t\t\treturn\tnew Image(this);\n\t\t},\n\n\t\t_load: function (image, fn){\n\t\t\tvar self = this;\n\n\t\t\tif( /img|video/i.test(image.nodeName) ){\n\t\t\t\tfn.call(self, null, image);\n\t\t\t}\n\t\t\telse {\n\t\t\t\tapi.readAsImage(image, function (evt){\n\t\t\t\t\tfn.call(self, evt.type != 'load', evt.result);\n\t\t\t\t});\n\t\t\t}\n\t\t},\n\n\t\t_apply: function (image, fn){\n\t\t\tvar\n\t\t\t\t  canvas = getCanvas()\n\t\t\t\t, m = this.getMatrix(image)\n\t\t\t\t, ctx = canvas.getContext('2d')\n\t\t\t\t, width = image.videoWidth || image.width\n\t\t\t\t, height = image.videoHeight || image.height\n\t\t\t\t, deg = m.deg\n\t\t\t\t, dw = m.dw\n\t\t\t\t, dh = m.dh\n\t\t\t\t, w = width\n\t\t\t\t, h = height\n\t\t\t\t, filter = m.filter\n\t\t\t\t, copy // canvas copy\n\t\t\t\t, buffer = image\n\t\t\t\t, overlay = m.overlay\n\t\t\t\t, queue = api.queue(function (){ image.src = api.EMPTY_PNG; fn(false, canvas); })\n\t\t\t\t, renderImageToCanvas = api.renderImageToCanvas\n\t\t\t;\n\n\t\t\t// Normalize angle\n\t\t\tdeg = deg - Math.floor(deg/360)*360;\n\n\t\t\t// For `renderImageToCanvas`\n\t\t\timage._type = this.file.type;\n\n\t\t\twhile(m.multipass && min(w/dw, h/dh) > 2 ){\n\t\t\t\tw = (w/2 + 0.5)|0;\n\t\t\t\th = (h/2 + 0.5)|0;\n\n\t\t\t\tcopy = getCanvas();\n\t\t\t\tcopy.width  = w;\n\t\t\t\tcopy.height = h;\n\n\t\t\t\tif( buffer !== image ){\n\t\t\t\t\trenderImageToCanvas(copy, buffer, 0, 0, buffer.width, buffer.height, 0, 0, w, h);\n\t\t\t\t\tbuffer = copy;\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tbuffer = copy;\n\t\t\t\t\trenderImageToCanvas(buffer, image, m.sx, m.sy, m.sw, m.sh, 0, 0, w, h);\n\t\t\t\t\tm.sx = m.sy = m.sw = m.sh = 0;\n\t\t\t\t}\n\t\t\t}\n\n\n\t\t\tcanvas.width  = (deg % 180) ? dh : dw;\n\t\t\tcanvas.height = (deg % 180) ? dw : dh;\n\n\t\t\tcanvas.type = m.type;\n\t\t\tcanvas.quality = m.quality;\n\n\t\t\tctx.rotate(deg * Math.PI / 180);\n\t\t\trenderImageToCanvas(ctx.canvas, buffer\n\t\t\t\t, m.sx, m.sy\n\t\t\t\t, m.sw || buffer.width\n\t\t\t\t, m.sh || buffer.height\n\t\t\t\t, (deg == 180 || deg == 270 ? -dw : 0)\n\t\t\t\t, (deg == 90 || deg == 180 ? -dh : 0)\n\t\t\t\t, dw, dh\n\t\t\t);\n\t\t\tdw = canvas.width;\n\t\t\tdh = canvas.height;\n\n\t\t\t// Apply overlay\n\t\t\toverlay && api.each([].concat(overlay), function (over){\n\t\t\t\tqueue.inc();\n\t\t\t\t// preload\n\t\t\t\tvar img = new window.Image, fn = function (){\n\t\t\t\t\tvar\n\t\t\t\t\t\t  x = over.x|0\n\t\t\t\t\t\t, y = over.y|0\n\t\t\t\t\t\t, w = over.w || img.width\n\t\t\t\t\t\t, h = over.h || img.height\n\t\t\t\t\t\t, rel = over.rel\n\t\t\t\t\t;\n\n\t\t\t\t\t// center  |  right  |  left\n\t\t\t\t\tx = (rel == 1 || rel == 4 || rel == 7) ? (dw - w + x)/2 : (rel == 2 || rel == 5 || rel == 8 ? dw - (w + x) : x);\n\n\t\t\t\t\t// center  |  bottom  |  top\n\t\t\t\t\ty = (rel == 3 || rel == 4 || rel == 5) ? (dh - h + y)/2 : (rel >= 6 ? dh - (h + y) : y);\n\n\t\t\t\t\tapi.event.off(img, 'error load abort', fn);\n\n\t\t\t\t\ttry {\n\t\t\t\t\t\tctx.globalAlpha = over.opacity || 1;\n\t\t\t\t\t\tctx.drawImage(img, x, y, w, h);\n\t\t\t\t\t}\n\t\t\t\t\tcatch (er){}\n\n\t\t\t\t\tqueue.next();\n\t\t\t\t};\n\n\t\t\t\tapi.event.on(img, 'error load abort', fn);\n\t\t\t\timg.src = over.src;\n\n\t\t\t\tif( img.complete ){\n\t\t\t\t\tfn();\n\t\t\t\t}\n\t\t\t});\n\n\t\t\tif( filter ){\n\t\t\t\tqueue.inc();\n\t\t\t\tImage.applyFilter(canvas, filter, queue.next);\n\t\t\t}\n\n\t\t\tqueue.check();\n\t\t},\n\n\t\tgetMatrix: function (image){\n\t\t\tvar\n\t\t\t\t  m  = api.extend({}, this.matrix)\n\t\t\t\t, sw = m.sw = m.sw || image.videoWidth || image.naturalWidth ||  image.width\n\t\t\t\t, sh = m.sh = m.sh || image.videoHeight || image.naturalHeight || image.height\n\t\t\t\t, dw = m.dw = m.dw || sw\n\t\t\t\t, dh = m.dh = m.dh || sh\n\t\t\t\t, sf = sw/sh, df = dw/dh\n\t\t\t\t, strategy = m.resize\n\t\t\t;\n\n\t\t\tif( strategy == 'preview' ){\n\t\t\t\tif( dw != sw || dh != sh ){\n\t\t\t\t\t// Make preview\n\t\t\t\t\tvar w, h;\n\n\t\t\t\t\tif( df >= sf ){\n\t\t\t\t\t\tw\t= sw;\n\t\t\t\t\t\th\t= w / df;\n\t\t\t\t\t} else {\n\t\t\t\t\t\th\t= sh;\n\t\t\t\t\t\tw\t= h * df;\n\t\t\t\t\t}\n\n\t\t\t\t\tif( w != sw || h != sh ){\n\t\t\t\t\t\tm.sx\t= ~~((sw - w)/2);\n\t\t\t\t\t\tm.sy\t= ~~((sh - h)/2);\n\t\t\t\t\t\tsw\t\t= w;\n\t\t\t\t\t\tsh\t\t= h;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\telse if( strategy ){\n\t\t\t\tif( !(sw > dw || sh > dh) ){\n\t\t\t\t\tdw = sw;\n\t\t\t\t\tdh = sh;\n\t\t\t\t}\n\t\t\t\telse if( strategy == 'min' ){\n\t\t\t\t\tdw = round(sf < df ? min(sw, dw) : dh*sf);\n\t\t\t\t\tdh = round(sf < df ? dw/sf : min(sh, dh));\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tdw = round(sf >= df ? min(sw, dw) : dh*sf);\n\t\t\t\t\tdh = round(sf >= df ? dw/sf : min(sh, dh));\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tm.sw = sw;\n\t\t\tm.sh = sh;\n\t\t\tm.dw = dw;\n\t\t\tm.dh = dh;\n\t\t\tm.multipass = api.multiPassResize;\n\t\t\treturn\tm;\n\t\t},\n\n\t\t_trans: function (fn){\n\t\t\tthis._load(this.file, function (err, image){\n\t\t\t\tif( err ){\n\t\t\t\t\tfn(err);\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tthis._apply(image, fn);\n\t\t\t\t\t} catch (err){\n\t\t\t\t\t\tapi.log('[err] FileAPI.Image.fn._apply:', err);\n\t\t\t\t\t\tfn(err);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t},\n\n\n\t\tget: function (fn){\n\t\t\tif( api.support.transform ){\n\t\t\t\tvar _this = this, matrix = _this.matrix;\n\n\t\t\t\tif( matrix.deg == 'auto' ){\n\t\t\t\t\tapi.getInfo(_this.file, function (err, info){\n\t\t\t\t\t\t// rotate by exif orientation\n\t\t\t\t\t\tmatrix.deg = exifOrientation[info && info.exif && info.exif.Orientation] || 0;\n\t\t\t\t\t\t_this._trans(fn);\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\t_this._trans(fn);\n\t\t\t\t}\n\t\t\t}\n\t\t\telse {\n\t\t\t\tfn('not_support_transform');\n\t\t\t}\n\n\t\t\treturn this;\n\t\t},\n\n\n\t\ttoData: function (fn){\n\t\t\treturn this.get(fn);\n\t\t}\n\n\t};\n\n\n\tImage.exifOrientation = exifOrientation;\n\n\n\tImage.transform = function (file, transform, autoOrientation, fn){\n\t\tfunction _transform(err, img){\n\t\t\t// img -- info object\n\t\t\tvar\n\t\t\t\t  images = {}\n\t\t\t\t, queue = api.queue(function (err){\n\t\t\t\t\tfn(err, images);\n\t\t\t\t})\n\t\t\t;\n\n\t\t\tif( !err ){\n\t\t\t\tapi.each(transform, function (params, name){\n\t\t\t\t\tif( !queue.isFail() ){\n\t\t\t\t\t\tvar ImgTrans = new Image(img.nodeType ? img : file), isFn = typeof params == 'function';\n\n\t\t\t\t\t\tif( isFn ){\n\t\t\t\t\t\t\tparams(img, ImgTrans);\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse if( params.width ){\n\t\t\t\t\t\t\tImgTrans[params.preview ? 'preview' : 'resize'](params.width, params.height, params.strategy);\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse {\n\t\t\t\t\t\t\tif( params.maxWidth && (img.width > params.maxWidth || img.height > params.maxHeight) ){\n\t\t\t\t\t\t\t\tImgTrans.resize(params.maxWidth, params.maxHeight, 'max');\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif( params.crop ){\n\t\t\t\t\t\t\tvar crop = params.crop;\n\t\t\t\t\t\t\tImgTrans.crop(crop.x|0, crop.y|0, crop.w || crop.width, crop.h || crop.height);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif( params.rotate === undef && autoOrientation ){\n\t\t\t\t\t\t\tparams.rotate = 'auto';\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tImgTrans.set({ type: ImgTrans.matrix.type || params.type || file.type || 'image/png' });\n\n\t\t\t\t\t\tif( !isFn ){\n\t\t\t\t\t\t\tImgTrans.set({\n\t\t\t\t\t\t\t\t  deg: params.rotate\n\t\t\t\t\t\t\t\t, overlay: params.overlay\n\t\t\t\t\t\t\t\t, filter: params.filter\n\t\t\t\t\t\t\t\t, quality: params.quality || 1\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tqueue.inc();\n\t\t\t\t\t\tImgTrans.toData(function (err, image){\n\t\t\t\t\t\t\tif( err ){\n\t\t\t\t\t\t\t\tqueue.fail();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse {\n\t\t\t\t\t\t\t\timages[name] = image;\n\t\t\t\t\t\t\t\tqueue.next();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t\telse {\n\t\t\t\tqueue.fail();\n\t\t\t}\n\t\t}\n\n\n\t\t// @todo: Оло-ло, нужно рефакторить это место\n\t\tif( file.width ){\n\t\t\t_transform(false, file);\n\t\t} else {\n\t\t\tapi.getInfo(file, _transform);\n\t\t}\n\t};\n\n\n\t// @const\n\tapi.each(['TOP', 'CENTER', 'BOTTOM'], function (x, i){\n\t\tapi.each(['LEFT', 'CENTER', 'RIGHT'], function (y, j){\n\t\t\tImage[x+'_'+y] = i*3 + j;\n\t\t\tImage[y+'_'+x] = i*3 + j;\n\t\t});\n\t});\n\n\n\t/**\n\t * Trabsform element to canvas\n\t *\n\t * @param    {Image|HTMLVideoElement}   el\n\t * @returns  {Canvas}\n\t */\n\tImage.toCanvas = function(el){\n\t\tvar canvas\t\t= document.createElement('canvas');\n\t\tcanvas.width\t= el.videoWidth || el.width;\n\t\tcanvas.height\t= el.videoHeight || el.height;\n\t\tcanvas.getContext('2d').drawImage(el, 0, 0);\n\t\treturn\tcanvas;\n\t};\n\n\n\t/**\n\t * Create image from DataURL\n\t * @param  {String}  dataURL\n\t * @param  {Object}  size\n\t * @param  {Function}  callback\n\t */\n\tImage.fromDataURL = function (dataURL, size, callback){\n\t\tvar img = api.newImage(dataURL);\n\t\tapi.extend(img, size);\n\t\tcallback(img);\n\t};\n\n\n\t/**\n\t * Apply filter (caman.js)\n\t *\n\t * @param  {Canvas|Image}   canvas\n\t * @param  {String|Function}  filter\n\t * @param  {Function}  doneFn\n\t */\n\tImage.applyFilter = function (canvas, filter, doneFn){\n\t\tif( typeof filter == 'function' ){\n\t\t\tfilter(canvas, doneFn);\n\t\t}\n\t\telse if( window.Caman ){\n\t\t\t// http://camanjs.com/guides/\n\t\t\twindow.Caman(canvas.tagName == 'IMG' ? Image.toCanvas(canvas) : canvas, function (){\n\t\t\t\tif( typeof filter == 'string' ){\n\t\t\t\t\tthis[filter]();\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tapi.each(filter, function (val, method){\n\t\t\t\t\t\tthis[method](val);\n\t\t\t\t\t}, this);\n\t\t\t\t}\n\t\t\t\tthis.render(doneFn);\n\t\t\t});\n\t\t}\n\t};\n\n\n\t/**\n\t * For load-image-ios.js\n\t */\n\tapi.renderImageToCanvas = function (canvas, img, sx, sy, sw, sh, dx, dy, dw, dh){\n\t\ttry {\n\t\t\treturn canvas.getContext('2d').drawImage(img, sx, sy, sw, sh, dx, dy, dw, dh);\n\t\t} catch (ex) {\n\t\t\tapi.log('renderImageToCanvas failed');\n\t\t\tthrow ex;\n\t\t}\n\t};\n\n\n\t// @export\n\tapi.support.canvas = api.support.transform = support;\n\tapi.Image = Image;\n})(FileAPI, document);\n\n/*\n * JavaScript Load Image iOS scaling fixes 1.0.3\n * https://github.com/blueimp/JavaScript-Load-Image\n *\n * Copyright 2013, Sebastian Tschan\n * https://blueimp.net\n *\n * iOS image scaling fixes based on\n * https://github.com/stomita/ios-imagefile-megapixel\n *\n * Licensed under the MIT license:\n * http://www.opensource.org/licenses/MIT\n */\n\n/*jslint nomen: true, bitwise: true */\n/*global FileAPI, window, document */\n\n(function (factory) {\n\t'use strict';\n\tfactory(FileAPI);\n}(function (loadImage) {\n    'use strict';\n\n    // Only apply fixes on the iOS platform:\n    if (!window.navigator || !window.navigator.platform ||\n             !(/iP(hone|od|ad)/).test(window.navigator.platform)) {\n        return;\n    }\n\n    var originalRenderMethod = loadImage.renderImageToCanvas;\n\n    // Detects subsampling in JPEG images:\n    loadImage.detectSubsampling = function (img) {\n        var canvas,\n            context;\n        if (img.width * img.height > 1024 * 1024) { // only consider mexapixel images\n            canvas = document.createElement('canvas');\n            canvas.width = canvas.height = 1;\n            context = canvas.getContext('2d');\n            context.drawImage(img, -img.width + 1, 0);\n            // subsampled image becomes half smaller in rendering size.\n            // check alpha channel value to confirm image is covering edge pixel or not.\n            // if alpha value is 0 image is not covering, hence subsampled.\n            return context.getImageData(0, 0, 1, 1).data[3] === 0;\n        }\n        return false;\n    };\n\n    // Detects vertical squash in JPEG images:\n    loadImage.detectVerticalSquash = function (img, subsampled) {\n        var naturalHeight = img.naturalHeight || img.height,\n            canvas = document.createElement('canvas'),\n            context = canvas.getContext('2d'),\n            data,\n            sy,\n            ey,\n            py,\n            alpha;\n        if (subsampled) {\n            naturalHeight /= 2;\n        }\n        canvas.width = 1;\n        canvas.height = naturalHeight;\n        context.drawImage(img, 0, 0);\n        data = context.getImageData(0, 0, 1, naturalHeight).data;\n        // search image edge pixel position in case it is squashed vertically:\n        sy = 0;\n        ey = naturalHeight;\n        py = naturalHeight;\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        return (py / naturalHeight) || 1;\n    };\n\n    // Renders image to canvas while working around iOS image scaling bugs:\n    // https://github.com/blueimp/JavaScript-Load-Image/issues/13\n    loadImage.renderImageToCanvas = function (\n        canvas,\n        img,\n        sourceX,\n        sourceY,\n        sourceWidth,\n        sourceHeight,\n        destX,\n        destY,\n        destWidth,\n        destHeight\n    ) {\n        if (img._type === 'image/jpeg') {\n            var context = canvas.getContext('2d'),\n                tmpCanvas = document.createElement('canvas'),\n                tileSize = 1024,\n                tmpContext = tmpCanvas.getContext('2d'),\n                subsampled,\n                vertSquashRatio,\n                tileX,\n                tileY;\n            tmpCanvas.width = tileSize;\n            tmpCanvas.height = tileSize;\n            context.save();\n            subsampled = loadImage.detectSubsampling(img);\n            if (subsampled) {\n                sourceX /= 2;\n                sourceY /= 2;\n                sourceWidth /= 2;\n                sourceHeight /= 2;\n            }\n            vertSquashRatio = loadImage.detectVerticalSquash(img, subsampled);\n            if (subsampled || vertSquashRatio !== 1) {\n                sourceY *= vertSquashRatio;\n                destWidth = Math.ceil(tileSize * destWidth / sourceWidth);\n                destHeight = Math.ceil(\n                    tileSize * destHeight / sourceHeight / vertSquashRatio\n                );\n                destY = 0;\n                tileY = 0;\n                while (tileY < sourceHeight) {\n                    destX = 0;\n                    tileX = 0;\n                    while (tileX < sourceWidth) {\n                        tmpContext.clearRect(0, 0, tileSize, tileSize);\n                        tmpContext.drawImage(\n                            img,\n                            sourceX,\n                            sourceY,\n                            sourceWidth,\n                            sourceHeight,\n                            -tileX,\n                            -tileY,\n                            sourceWidth,\n                            sourceHeight\n                        );\n                        context.drawImage(\n                            tmpCanvas,\n                            0,\n                            0,\n                            tileSize,\n                            tileSize,\n                            destX,\n                            destY,\n                            destWidth,\n                            destHeight\n                        );\n                        tileX += tileSize;\n                        destX += destWidth;\n                    }\n                    tileY += tileSize;\n                    destY += destHeight;\n                }\n                context.restore();\n                return canvas;\n            }\n        }\n        return originalRenderMethod(\n            canvas,\n            img,\n            sourceX,\n            sourceY,\n            sourceWidth,\n            sourceHeight,\n            destX,\n            destY,\n            destWidth,\n            destHeight\n        );\n    };\n\n}));\n\n/*global window, FileAPI */\n\n(function (api, window){\n\t\"use strict\";\n\n\tvar\n\t\t  document = window.document\n\t\t, FormData = window.FormData\n\t\t, Form = function (){ this.items = []; }\n\t\t, encodeURIComponent = window.encodeURIComponent\n\t;\n\n\n\tForm.prototype = {\n\n\t\tappend: function (name, blob, file, type){\n\t\t\tthis.items.push({\n\t\t\t\t  name: name\n\t\t\t\t, blob: blob && blob.blob || (blob == void 0 ? '' : blob)\n\t\t\t\t, file: blob && (file || blob.name)\n\t\t\t\t, type:\tblob && (type || blob.type)\n\t\t\t});\n\t\t},\n\n\t\teach: function (fn){\n\t\t\tvar i = 0, n = this.items.length;\n\t\t\tfor( ; i < n; i++ ){\n\t\t\t\tfn.call(this, this.items[i]);\n\t\t\t}\n\t\t},\n\n\t\ttoData: function (fn, options){\n\t\t    // allow chunked transfer if we have only one file to send\n\t\t    // flag is used below and in XHR._send\n\t\t    options._chunked = api.support.chunked && options.chunkSize > 0 && api.filter(this.items, function (item){ return item.file; }).length == 1;\n\n\t\t\tif( !api.support.html5 ){\n\t\t\t\tapi.log('FileAPI.Form.toHtmlData');\n\t\t\t\tthis.toHtmlData(fn);\n\t\t\t}\n\t\t\telse if( !api.formData || this.multipart || !FormData ){\n\t\t\t\tapi.log('FileAPI.Form.toMultipartData');\n\t\t\t\tthis.toMultipartData(fn);\n\t\t\t}\n\t\t\telse if( options._chunked ){\n\t\t\t\tapi.log('FileAPI.Form.toPlainData');\n\t\t\t\tthis.toPlainData(fn);\n\t\t\t}\n\t\t\telse {\n\t\t\t\tapi.log('FileAPI.Form.toFormData');\n\t\t\t\tthis.toFormData(fn);\n\t\t\t}\n\t\t},\n\n\t\t_to: function (data, complete, next, arg){\n\t\t\tvar queue = api.queue(function (){\n\t\t\t\tcomplete(data);\n\t\t\t});\n\n\t\t\tthis.each(function (file){\n\t\t\t\tnext(file, data, queue, arg);\n\t\t\t});\n\n\t\t\tqueue.check();\n\t\t},\n\n\n\t\ttoHtmlData: function (fn){\n\t\t\tthis._to(document.createDocumentFragment(), fn, function (file, data/**DocumentFragment*/){\n\t\t\t\tvar blob = file.blob, hidden;\n\n\t\t\t\tif( file.file ){\n\t\t\t\t\tapi.reset(blob, true);\n\t\t\t\t\t// set new name\n\t\t\t\t\tblob.name = file.name;\n\t\t\t\t\tblob.disabled = false;\n\t\t\t\t\tdata.appendChild(blob);\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\thidden = document.createElement('input');\n\t\t\t\t\thidden.name  = file.name;\n\t\t\t\t\thidden.type  = 'hidden';\n\t\t\t\t\thidden.value = blob;\n\t\t\t\t\tdata.appendChild(hidden);\n\t\t\t\t}\n\t\t\t});\n\t\t},\n\n\t\ttoPlainData: function (fn){\n\t\t\tthis._to({}, fn, function (file, data, queue){\n\t\t\t\tif( file.file ){\n\t\t\t\t\tdata.type = file.file;\n\t\t\t\t}\n\n\t\t\t\tif( file.blob.toBlob ){\n\t\t\t\t    // canvas\n\t\t\t\t\tqueue.inc();\n\t\t\t\t\t_convertFile(file, function (file, blob){\n\t\t\t\t\t\tdata.name = file.name;\n\t\t\t\t\t\tdata.file = blob;\n\t\t\t\t\t\tdata.size = blob.length;\n\t\t\t\t\t\tdata.type = file.type;\n\t\t\t\t\t\tqueue.next();\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\telse if( file.file ){\n\t\t\t\t    // file\n\t\t\t\t\tdata.name = file.blob.name;\n\t\t\t\t\tdata.file = file.blob;\n\t\t\t\t\tdata.size = file.blob.size;\n\t\t\t\t\tdata.type = file.type;\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t    // additional data\n\t\t\t\t    if( !data.params ){\n\t\t\t\t        data.params = [];\n\t\t\t\t    }\n\t\t\t\t    data.params.push(encodeURIComponent(file.name) +\"=\"+ encodeURIComponent(file.blob));\n\t\t\t\t}\n\n\t\t\t\tdata.start = -1;\n\t\t\t\tdata.end = data.file && data.file.FileAPIReadPosition || -1;\n\t\t\t\tdata.retry = 0;\n\t\t\t});\n\t\t},\n\n\t\ttoFormData: function (fn){\n\t\t\tthis._to(new FormData, fn, function (file, data, queue){\n\t\t\t\tif( file.blob && file.blob.toBlob ){\n\t\t\t\t\tqueue.inc();\n\t\t\t\t\t_convertFile(file, function (file, blob){\n\t\t\t\t\t\tdata.append(file.name, blob, file.file);\n\t\t\t\t\t\tqueue.next();\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\telse if( file.file ){\n\t\t\t\t\tdata.append(file.name, file.blob, file.file);\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tdata.append(file.name, file.blob);\n\t\t\t\t}\n\n\t\t\t\tif( file.file ){\n\t\t\t\t\tdata.append('_'+file.name, file.file);\n\t\t\t\t}\n\t\t\t});\n\t\t},\n\n\n\t\ttoMultipartData: function (fn){\n\t\t\tthis._to([], fn, function (file, data, queue, boundary){\n\t\t\t\tqueue.inc();\n\t\t\t\t_convertFile(file, function (file, blob){\n\t\t\t\t\tdata.push(\n\t\t\t\t\t\t  '--_' + boundary + ('\\r\\nContent-Disposition: form-data; name=\"'+ file.name +'\"'+ (file.file ? '; filename=\"'+ encodeURIComponent(file.file) +'\"' : '')\n\t\t\t\t\t\t+ (file.file ? '\\r\\nContent-Type: '+ (file.type || 'application/octet-stream') : '')\n\t\t\t\t\t\t+ '\\r\\n'\n\t\t\t\t\t\t+ '\\r\\n'+ (file.file ? blob : encodeURIComponent(blob))\n\t\t\t\t\t\t+ '\\r\\n')\n\t\t\t\t\t);\n\t\t\t\t\tqueue.next();\n\t\t\t\t}, true);\n\t\t\t}, api.expando);\n\t\t}\n\t};\n\n\n\tfunction _convertFile(file, fn, useBinaryString){\n\t\tvar blob = file.blob, filename = file.file;\n\n\t\tif( filename ){\n\t\t\tif( !blob.toDataURL ){\n\t\t\t\t// The Blob is not an image.\n\t\t\t\tapi.readAsBinaryString(blob, function (evt){\n\t\t\t\t\tif( evt.type == 'load' ){\n\t\t\t\t\t\tfn(file, evt.result);\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tvar\n\t\t\t\t  mime = { 'image/jpeg': '.jpe?g', 'image/png': '.png' }\n\t\t\t\t, type = mime[file.type] ? file.type : 'image/png'\n\t\t\t\t, ext  = mime[type] || '.png'\n\t\t\t\t, quality = blob.quality || 1\n\t\t\t;\n\n\t\t\tif( !filename.match(new RegExp(ext+'$', 'i')) ){\n\t\t\t\t// Does not change the current extension, but add a new one.\n\t\t\t\tfilename += ext.replace('?', '');\n\t\t\t}\n\n\t\t\tfile.file = filename;\n\t\t\tfile.type = type;\n\n\t\t\tif( !useBinaryString && blob.toBlob ){\n\t\t\t\tblob.toBlob(function (blob){\n\t\t\t\t\tfn(file, blob);\n\t\t\t\t}, type, quality);\n\t\t\t}\n\t\t\telse {\n\t\t\t\tfn(file, api.toBinaryString(blob.toDataURL(type, quality)));\n\t\t\t}\n\t\t}\n\t\telse {\n\t\t\tfn(file, blob);\n\t\t}\n\t}\n\n\n\t// @export\n\tapi.Form = Form;\n})(FileAPI, window);\n\n/*global window, FileAPI, Uint8Array */\n\n(function (window, api){\n\t\"use strict\";\n\n\tvar\n\t\t  noop = function (){}\n\t\t, document = window.document\n\n\t\t, XHR = function (options){\n\t\t\tthis.uid = api.uid();\n\t\t\tthis.xhr = {\n\t\t\t\t  abort: noop\n\t\t\t\t, getResponseHeader: noop\n\t\t\t\t, getAllResponseHeaders: noop\n\t\t\t};\n\t\t\tthis.options = options;\n\t\t},\n\n\t\t_xhrResponsePostfix = { '': 1, XML: 1, Text: 1, Body: 1 }\n\t;\n\n\n\tXHR.prototype = {\n\t\tstatus: 0,\n\t\tstatusText: '',\n\t\tconstructor: XHR,\n\n\t\tgetResponseHeader: function (name){\n\t\t\treturn this.xhr.getResponseHeader(name);\n\t\t},\n\n\t\tgetAllResponseHeaders: function (){\n\t\t\treturn this.xhr.getAllResponseHeaders() || {};\n\t\t},\n\n\t\tend: function (status, statusText){\n\t\t\tvar _this = this, options = _this.options;\n\n\t\t\t_this.end\t\t=\n\t\t\t_this.abort\t\t= noop;\n\t\t\t_this.status\t= status;\n\n\t\t\tif( statusText ){\n\t\t\t\t_this.statusText = statusText;\n\t\t\t}\n\n\t\t\tapi.log('xhr.end:', status, statusText);\n\t\t\toptions.complete(status == 200 || status == 201 ? false : _this.statusText || 'unknown', _this);\n\n\t\t\tif( _this.xhr && _this.xhr.node ){\n\t\t\t\tsetTimeout(function (){\n\t\t\t\t\tvar node = _this.xhr.node;\n\t\t\t\t\ttry { node.parentNode.removeChild(node); } catch (e){}\n\t\t\t\t\ttry { delete window[_this.uid]; } catch (e){}\n\t\t\t\t\twindow[_this.uid] = _this.xhr.node = null;\n\t\t\t\t}, 9);\n\t\t\t}\n\t\t},\n\n\t\tabort: function (){\n\t\t\tthis.end(0, 'abort');\n\n\t\t\tif( this.xhr ){\n\t\t\t\tthis.xhr.aborted = true;\n\t\t\t\tthis.xhr.abort();\n\t\t\t}\n\t\t},\n\n\t\tsend: function (FormData){\n\t\t\tvar _this = this, options = this.options;\n\n\t\t\tFormData.toData(function (data){\n\t\t\t\t// Start uploading\n\t\t\t\toptions.upload(options, _this);\n\t\t\t\t_this._send.call(_this, options, data);\n\t\t\t}, options);\n\t\t},\n\n\t\t_send: function (options, data){\n\t\t\tvar _this = this, xhr, uid = _this.uid, onloadFuncName = _this.uid + \"Load\", url = options.url;\n\n\t\t\tapi.log('XHR._send:', data);\n\n\t\t\tif( !options.cache ){\n\t\t\t\t// No cache\n\t\t\t\turl += (~url.indexOf('?') ? '&' : '?') + api.uid();\n\t\t\t}\n\n\t\t\tif( data.nodeName ){\n\t\t\t\tvar jsonp = options.jsonp;\n\n\t\t\t\t// prepare callback in GET\n\t\t\t\turl = url.replace(/([a-z]+)=(\\?)/i, '$1='+uid);\n\n\t\t\t\t// legacy\n\t\t\t\toptions.upload(options, _this);\n\n\t\t\t\tvar\n\t\t\t\t\tonPostMessage = function (evt){\n\t\t\t\t\t\tif( ~url.indexOf(evt.origin) ){\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\tvar result = api.parseJSON(evt.data);\n\t\t\t\t\t\t\t\tif( result.id == uid ){\n\t\t\t\t\t\t\t\t\tcomplete(result.status, result.statusText, result.response);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} catch( err ){\n\t\t\t\t\t\t\t\tcomplete(0, err.message);\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// jsonp-callack\n\t\t\t\t\tcomplete = window[uid] = function (status, statusText, response){\n\t\t\t\t\t\t_this.readyState\t= 4;\n\t\t\t\t\t\t_this.responseText\t= response;\n\t\t\t\t\t\t_this.end(status, statusText);\n\n\t\t\t\t\t\tapi.event.off(window, 'message', onPostMessage);\n\t\t\t\t\t\twindow[uid] = xhr = transport = window[onloadFuncName] = null;\n\t\t\t\t\t}\n\t\t\t\t;\n\n\t\t\t\t_this.xhr.abort = function (){\n\t\t\t\t\ttry {\n\t\t\t\t\t\tif( transport.stop ){ transport.stop(); }\n\t\t\t\t\t\telse if( transport.contentWindow.stop ){ transport.contentWindow.stop(); }\n\t\t\t\t\t\telse { transport.contentWindow.document.execCommand('Stop'); }\n\t\t\t\t\t}\n\t\t\t\t\tcatch (er) {}\n\t\t\t\t\tcomplete(0, \"abort\");\n\t\t\t\t};\n\n\t\t\t\tapi.event.on(window, 'message', onPostMessage);\n\n\t\t\t\twindow[onloadFuncName] = function (){\n\t\t\t\t\ttry {\n\t\t\t\t\t\tvar\n\t\t\t\t\t\t\t  win = transport.contentWindow\n\t\t\t\t\t\t\t, doc = win.document\n\t\t\t\t\t\t\t, result = win.result || api.parseJSON(doc.body.innerHTML)\n\t\t\t\t\t\t;\n\t\t\t\t\t\tcomplete(result.status, result.statusText, result.response);\n\t\t\t\t\t} catch (e){\n\t\t\t\t\t\tapi.log('[transport.onload]', e);\n\t\t\t\t\t}\n\t\t\t\t};\n\n\t\t\t\txhr = document.createElement('div');\n\t\t\t\txhr.innerHTML = '<form target=\"'+ uid +'\" action=\"'+ url +'\" method=\"POST\" enctype=\"multipart/form-data\" style=\"position: absolute; top: -1000px; overflow: hidden; width: 1px; height: 1px;\">'\n\t\t\t\t\t\t\t+ '<iframe name=\"'+ uid +'\" src=\"javascript:false;\" onload=\"' + onloadFuncName + '()\"></iframe>'\n\t\t\t\t\t\t\t+ (jsonp && (options.url.indexOf('=?') < 0) ? '<input value=\"'+ uid +'\" name=\"'+jsonp+'\" type=\"hidden\"/>' : '')\n\t\t\t\t\t\t\t+ '</form>'\n\t\t\t\t;\n\n\t\t\t\t// get form-data & transport\n\t\t\t\tvar\n\t\t\t\t\t  form = xhr.getElementsByTagName('form')[0]\n\t\t\t\t\t, transport = xhr.getElementsByTagName('iframe')[0]\n\t\t\t\t;\n\n\t\t\t\tform.appendChild(data);\n\n\t\t\t\tapi.log(form.parentNode.innerHTML);\n\n\t\t\t\t// append to DOM\n\t\t\t\tdocument.body.appendChild(xhr);\n\n\t\t\t\t// keep a reference to node-transport\n\t\t\t\t_this.xhr.node = xhr;\n\n\t\t\t\t// send\n\t\t\t\t_this.readyState = 2; // loaded\n\t\t\t\tform.submit();\n\t\t\t\tform = null;\n\t\t\t}\n\t\t\telse {\n\t\t\t\t// Clean url\n\t\t\t\turl = url.replace(/([a-z]+)=(\\?)&?/i, '');\n\n\t\t\t\t// html5\n\t\t\t\tif (this.xhr && this.xhr.aborted) {\n\t\t\t\t\tapi.log(\"Error: already aborted\");\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\txhr = _this.xhr = api.getXHR();\n\n\t\t\t\tif (data.params) {\n\t\t\t\t\turl += (url.indexOf('?') < 0 ? \"?\" : \"&\") + data.params.join(\"&\");\n\t\t\t\t}\n\n\t\t\t\txhr.open('POST', url, true);\n\n\t\t\t\tif( api.withCredentials ){\n\t\t\t\t\txhr.withCredentials = \"true\";\n\t\t\t\t}\n\n\t\t\t\tif( !options.headers || !options.headers['X-Requested-With'] ){\n\t\t\t\t\txhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');\n\t\t\t\t}\n\n\t\t\t\tapi.each(options.headers, function (val, key){\n\t\t\t\t\txhr.setRequestHeader(key, val);\n\t\t\t\t});\n\n\n\t\t\t\tif ( options._chunked ) {\n\t\t\t\t\t// chunked upload\n\t\t\t\t\tif( xhr.upload ){\n\t\t\t\t\t\txhr.upload.addEventListener('progress', api.throttle(function (/**Event*/evt){\n\t\t\t\t\t\t\tif (!data.retry) {\n\t\t\t\t\t\t\t\t// show progress only for correct chunk uploads\n\t\t\t\t\t\t\t\toptions.progress({\n\t\t\t\t\t\t\t\t\t  type:\t\t\tevt.type\n\t\t\t\t\t\t\t\t\t, total:\t\tdata.size\n\t\t\t\t\t\t\t\t\t, loaded:\t\tdata.start + evt.loaded\n\t\t\t\t\t\t\t\t\t, totalSize:\tdata.size\n\t\t\t\t\t\t\t\t}, _this, options);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}, 100), false);\n\t\t\t\t\t}\n\n\t\t\t\t\txhr.onreadystatechange = function (){\n\t\t\t\t\t\tvar lkb = parseInt(xhr.getResponseHeader('X-Last-Known-Byte'), 10);\n\n\t\t\t\t\t\t_this.status     = xhr.status;\n\t\t\t\t\t\t_this.statusText = xhr.statusText;\n\t\t\t\t\t\t_this.readyState = xhr.readyState;\n\n\t\t\t\t\t\tif( xhr.readyState == 4 ){\n\t\t\t\t\t\t\tfor( var k in _xhrResponsePostfix ){\n\t\t\t\t\t\t\t\t_this['response'+k]  = xhr['response'+k];\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\txhr.onreadystatechange = null;\n\n\t\t\t\t\t\t\tif (!xhr.status || xhr.status - 201 > 0) {\n\t\t\t\t\t\t\t\tapi.log(\"Error: \" + xhr.status);\n\t\t\t\t\t\t\t\t// some kind of error\n\t\t\t\t\t\t\t\t// 0 - connection fail or timeout, if xhr.aborted is true, then it's not recoverable user action\n\t\t\t\t\t\t\t\t// up - server error\n\t\t\t\t\t\t\t\tif (((!xhr.status && !xhr.aborted) || 500 == xhr.status || 416 == xhr.status) && ++data.retry <= options.chunkUploadRetry) {\n\t\t\t\t\t\t\t\t\t// let's try again the same chunk\n\t\t\t\t\t\t\t\t\t// only applicable for recoverable error codes 500 && 416\n\t\t\t\t\t\t\t\t\tvar delay = xhr.status ? 0 : api.chunkNetworkDownRetryTimeout;\n\n\t\t\t\t\t\t\t\t\t// inform about recoverable problems\n\t\t\t\t\t\t\t\t\toptions.pause(data.file, options);\n\n\t\t\t\t\t\t\t\t\t// smart restart if server reports about the last known byte\n\t\t\t\t\t\t\t\t\tapi.log(\"X-Last-Known-Byte: \" + lkb);\n\t\t\t\t\t\t\t\t\tif (lkb) {\n\t\t\t\t\t\t\t\t\t\tdata.end = lkb;\n\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\tdata.end = data.start - 1;\n\t\t\t\t\t\t\t\t\t\tif (416 == xhr.status) {\n\t\t\t\t\t\t\t\t\t\t\tdata.end = data.end - options.chunkSize;\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\tsetTimeout(function () {\n\t\t\t\t\t\t\t\t\t\t_this._send(options, data);\n\t\t\t\t\t\t\t\t\t}, delay);\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t// no mo retries\n\t\t\t\t\t\t\t\t\t_this.end(xhr.status);\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\t// success\n\t\t\t\t\t\t\t\tdata.retry = 0;\n\n\t\t\t\t\t\t\t\tif (data.end == data.size - 1) {\n\t\t\t\t\t\t\t\t\t// finished\n\t\t\t\t\t\t\t\t\t_this.end(xhr.status);\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t// next chunk\n\n\t\t\t\t\t\t\t\t\t// shift position if server reports about the last known byte\n\t\t\t\t\t\t\t\t\tapi.log(\"X-Last-Known-Byte: \" + lkb);\n\t\t\t\t\t\t\t\t\tif (lkb) {\n\t\t\t\t\t\t\t\t\t\tdata.end = lkb;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tdata.file.FileAPIReadPosition = data.end;\n\n\t\t\t\t\t\t\t\t\tsetTimeout(function () {\n\t\t\t\t\t\t\t\t\t\t_this._send(options, data);\n\t\t\t\t\t\t\t\t\t}, 0);\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\txhr = null;\n\t\t\t\t\t\t}\n\t\t\t\t\t};\n\n\t\t\t\t\tdata.start = data.end + 1;\n\t\t\t\t\tdata.end = Math.max(Math.min(data.start + options.chunkSize, data.size) - 1, data.start);\n\n\t\t\t\t\t// Retrieve a slice of file\n\t\t\t\t\tvar\n\t\t\t\t\t\t  file = data.file\n\t\t\t\t\t\t, slice = (file.slice || file.mozSlice || file.webkitSlice).call(file, data.start, data.end + 1)\n\t\t\t\t\t;\n\n\t\t\t\t\tif( data.size && !slice.size ){\n\t\t\t\t\t\tsetTimeout(function (){\n\t\t\t\t\t\t\t_this.end(-1);\n\t\t\t\t\t\t});\n\t\t\t\t\t} else {\n\t\t\t\t\t\txhr.setRequestHeader(\"Content-Range\", \"bytes \" + data.start + \"-\" + data.end + \"/\" + data.size);\n\t\t\t\t\t\txhr.setRequestHeader(\"Content-Disposition\", 'attachment; filename=' + encodeURIComponent(data.name));\n\t\t\t\t\t\txhr.setRequestHeader(\"Content-Type\", data.type || \"application/octet-stream\");\n\n\t\t\t\t\t\txhr.send(slice);\n\t\t\t\t\t}\n\n\t\t\t\t\tfile = slice = null;\n\t\t\t\t} else {\n\t\t\t\t\t// single piece upload\n\t\t\t\t\tif( xhr.upload ){\n\t\t\t\t\t\t// https://github.com/blueimp/jQuery-File-Upload/wiki/Fixing-Safari-hanging-on-very-high-speed-connections-%281Gbps%29\n\t\t\t\t\t\txhr.upload.addEventListener('progress', api.throttle(function (/**Event*/evt){\n\t\t\t\t\t\t\toptions.progress(evt, _this, options);\n\t\t\t\t\t\t}, 100), false);\n\t\t\t\t\t}\n\n\t\t\t\t\txhr.onreadystatechange = function (){\n\t\t\t\t\t\t_this.status     = xhr.status;\n\t\t\t\t\t\t_this.statusText = xhr.statusText;\n\t\t\t\t\t\t_this.readyState = xhr.readyState;\n\n\t\t\t\t\t\tif( xhr.readyState == 4 ){\n\t\t\t\t\t\t\tfor( var k in _xhrResponsePostfix ){\n\t\t\t\t\t\t\t\t_this['response'+k]  = xhr['response'+k];\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\txhr.onreadystatechange = null;\n\n\t\t\t\t\t\t\tif (!xhr.status || xhr.status > 201) {\n\t\t\t\t\t\t\t\tapi.log(\"Error: \" + xhr.status);\n\t\t\t\t\t\t\t\tif (((!xhr.status && !xhr.aborted) || 500 == xhr.status) && (options.retry || 0) < options.uploadRetry) {\n\t\t\t\t\t\t\t\t\toptions.retry = (options.retry || 0) + 1;\n\t\t\t\t\t\t\t\t\tvar delay = api.networkDownRetryTimeout;\n\n\t\t\t\t\t\t\t\t\t// inform about recoverable problems\n\t\t\t\t\t\t\t\t\toptions.pause(options.file, options);\n\n\t\t\t\t\t\t\t\t\tsetTimeout(function () {\n\t\t\t\t\t\t\t\t\t\t_this._send(options, data);\n\t\t\t\t\t\t\t\t\t}, delay);\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t//success\n\t\t\t\t\t\t\t\t\t_this.end(xhr.status);\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\t//success\n\t\t\t\t\t\t\t\t_this.end(xhr.status);\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\txhr = null;\n\t\t\t\t\t\t}\n\t\t\t\t\t};\n\n\t\t\t\t\tif( api.isArray(data) ){\n\t\t\t\t\t\t// multipart\n\t\t\t\t\t\txhr.setRequestHeader('Content-Type', 'multipart/form-data; boundary=_'+api.expando);\n\t\t\t\t\t\tvar rawData = data.join('') +'--_'+ api.expando +'--';\n\n\t\t\t\t\t\t/** @namespace  xhr.sendAsBinary  https://developer.mozilla.org/ru/XMLHttpRequest#Sending_binary_content */\n\t\t\t\t\t\tif( xhr.sendAsBinary ){\n\t\t\t\t\t\t\txhr.sendAsBinary(rawData);\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse {\n\t\t\t\t\t\t\tvar bytes = Array.prototype.map.call(rawData, function(c){ return c.charCodeAt(0) & 0xff; });\n\t\t\t\t\t\t\txhr.send(new Uint8Array(bytes).buffer);\n\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// FormData\n\t\t\t\t\t\txhr.send(data);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t};\n\n\n\t// @export\n\tapi.XHR = XHR;\n})(window, FileAPI);\n\n/**\n * @class\tFileAPI.Camera\n * @author\tRubaXa\t<trash@rubaxa.org>\n * @support\tChrome 21+, FF 18+, Opera 12+\n */\n\n/*global window, FileAPI, jQuery */\n/** @namespace LocalMediaStream -- https://developer.mozilla.org/en-US/docs/WebRTC/MediaStream_API#LocalMediaStream */\n(function (window, api){\n\t\"use strict\";\n\n\tvar\n\t\tURL = window.URL || window.webkitURL,\n\n\t\tdocument = window.document,\n\t\tnavigator = window.navigator,\n\n\t\tgetMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia,\n\n\t\thtml5 = !!getMedia\n\t;\n\n\n\t// Support \"media\"\n\tapi.support.media = html5;\n\n\n\tvar Camera = function (video){\n\t\tthis.video = video;\n\t};\n\n\n\tCamera.prototype = {\n\t\tisActive: function (){\n\t\t\treturn\t!!this._active;\n\t\t},\n\n\n\t\t/**\n\t\t * Start camera streaming\n\t\t * @param\t{Function}\tcallback\n\t\t */\n\t\tstart: function (callback){\n\t\t\tvar\n\t\t\t\t  _this = this\n\t\t\t\t, video = _this.video\n\t\t\t\t, _successId\n\t\t\t\t, _failId\n\t\t\t\t, _complete = function (err){\n\t\t\t\t\t_this._active = !err;\n\t\t\t\t\tclearTimeout(_failId);\n\t\t\t\t\tclearTimeout(_successId);\n//\t\t\t\t\tapi.event.off(video, 'loadedmetadata', _complete);\n\t\t\t\t\tcallback && callback(err, _this);\n\t\t\t\t}\n\t\t\t;\n\n\t\t\tgetMedia.call(navigator, { video: true }, function (stream/**LocalMediaStream*/){\n\t\t\t\t// Success\n\t\t\t\t_this.stream = stream;\n\n//\t\t\t\tapi.event.on(video, 'loadedmetadata', function (){\n//\t\t\t\t\t_complete(null);\n//\t\t\t\t});\n\n\t\t\t\t// Set camera stream\n\t\t\t\tvideo.src = URL.createObjectURL(stream);\n\n\t\t\t\t// Note: onloadedmetadata doesn't fire in Chrome when using it with getUserMedia.\n\t\t\t\t// See crbug.com/110938.\n\t\t\t\t_successId = setInterval(function (){\n\t\t\t\t\tif( _detectVideoSignal(video) ){\n\t\t\t\t\t\t_complete(null);\n\t\t\t\t\t}\n\t\t\t\t}, 1000);\n\n\t\t\t\t_failId = setTimeout(function (){\n\t\t\t\t\t_complete('timeout');\n\t\t\t\t}, 5000);\n\n\t\t\t\t// Go-go-go!\n\t\t\t\tvideo.play();\n\t\t\t}, _complete/*error*/);\n\t\t},\n\n\n\t\t/**\n\t\t * Stop camera streaming\n\t\t */\n\t\tstop: function (){\n\t\t\ttry {\n\t\t\t\tthis._active = false;\n\t\t\t\tthis.video.pause();\n\t\t\t\tthis.stream.stop();\n\t\t\t} catch( err ){ }\n\t\t},\n\n\n\t\t/**\n\t\t * Create screenshot\n\t\t * @return {FileAPI.Camera.Shot}\n\t\t */\n\t\tshot: function (){\n\t\t\treturn\tnew Shot(this.video);\n\t\t}\n\t};\n\n\n\t/**\n\t * Get camera element from container\n\t *\n\t * @static\n\t * @param\t{HTMLElement}\tel\n\t * @return\t{Camera}\n\t */\n\tCamera.get = function (el){\n\t\treturn\tnew Camera(el.firstChild);\n\t};\n\n\n\t/**\n\t * Publish camera element into container\n\t *\n\t * @static\n\t * @param\t{HTMLElement}\tel\n\t * @param\t{Object}\t\toptions\n\t * @param\t{Function}\t\t[callback]\n\t */\n\tCamera.publish = function (el, options, callback){\n\t\tif( typeof options == 'function' ){\n\t\t\tcallback = options;\n\t\t\toptions = {};\n\t\t}\n\n\t\t// Dimensions of \"camera\"\n\t\toptions = api.extend({}, {\n\t\t\t  width:\t'100%'\n\t\t\t, height:\t'100%'\n\t\t\t, start:\ttrue\n\t\t}, options);\n\n\n\t\tif( el.jquery ){\n\t\t\t// Extract first element, from jQuery collection\n\t\t\tel = el[0];\n\t\t}\n\n\n\t\tvar doneFn = function (err){\n\t\t\tif( err ){\n\t\t\t\tcallback(err);\n\t\t\t}\n\t\t\telse {\n\t\t\t\t// Get camera\n\t\t\t\tvar cam = Camera.get(el);\n\t\t\t\tif( options.start ){\n\t\t\t\t\tcam.start(callback);\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tcallback(null, cam);\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\n\n\t\tel.style.width\t= _px(options.width);\n\t\tel.style.height\t= _px(options.height);\n\n\n\t\tif( api.html5 && html5 ){\n\t\t\t// Create video element\n\t\t\tvar video = document.createElement('video');\n\n\t\t\t// Set dimensions\n\t\t\tvideo.style.width\t= _px(options.width);\n\t\t\tvideo.style.height\t= _px(options.height);\n\n\t\t\t// Clean container\n\t\t\tif( window.jQuery ){\n\t\t\t\tjQuery(el).empty();\n\t\t\t} else {\n\t\t\t\tel.innerHTML = '';\n\t\t\t}\n\n\t\t\t// Add \"camera\" to container\n\t\t\tel.appendChild(video);\n\n\t\t\t// end\n\t\t\tdoneFn();\n\t\t}\n\t\telse {\n\t\t\tCamera.fallback(el, options, doneFn);\n\t\t}\n\t};\n\n\n\tCamera.fallback = function (el, options, callback){\n\t\tcallback('not_support_camera');\n\t};\n\n\n\t/**\n\t * @class\tFileAPI.Camera.Shot\n\t */\n\tvar Shot = function (video){\n\t\tvar canvas\t= video.nodeName ? api.Image.toCanvas(video) : video;\n\t\tvar shot\t= api.Image(canvas);\n\t\tshot.type\t= 'image/png';\n\t\tshot.width\t= canvas.width;\n\t\tshot.height\t= canvas.height;\n\t\tshot.size\t= canvas.width * canvas.height * 4;\n\t\treturn\tshot;\n\t};\n\n\n\t/**\n\t * Add \"px\" postfix, if value is a number\n\t *\n\t * @private\n\t * @param\t{*}  val\n\t * @return\t{String}\n\t */\n\tfunction _px(val){\n\t\treturn\tval >= 0 ? val + 'px' : val;\n\t}\n\n\n\t/**\n\t * @private\n\t * @param\t{HTMLVideoElement} video\n\t * @return\t{Boolean}\n\t */\n\tfunction _detectVideoSignal(video){\n\t\tvar canvas = document.createElement('canvas'), ctx, res = false;\n\t\ttry {\n\t\t\tctx = canvas.getContext('2d');\n\t\t\tctx.drawImage(video, 0, 0, 1, 1);\n\t\t\tres = ctx.getImageData(0, 0, 1, 1).data[4] != 255;\n\t\t}\n\t\tcatch( e ){}\n\t\treturn\tres;\n\t}\n\n\n\t// @export\n\tCamera.Shot\t= Shot;\n\tapi.Camera\t= Camera;\n})(window, FileAPI);\n\n/**\n * FileAPI fallback to Flash\n *\n * @flash-developer  \"Vladimir Demidov\" <v.demidov@corp.mail.ru>\n */\n\n/*global window, ActiveXObject, FileAPI */\n(function (window, jQuery, api) {\n\t\"use strict\";\n\n\tvar\n\t\t  document = window.document\n\t\t, location = window.location\n\t\t, navigator = window.navigator\n\t\t, _each = api.each\n\t;\n\n\n\tapi.support.flash = (function (){\n\t\tvar mime = navigator.mimeTypes, has = false;\n\n\t\tif( navigator.plugins && typeof navigator.plugins['Shockwave Flash'] == 'object' ){\n\t\t\thas\t= navigator.plugins['Shockwave Flash'].description && !(mime && mime['application/x-shockwave-flash'] && !mime['application/x-shockwave-flash'].enabledPlugin);\n\t\t}\n\t\telse {\n\t\t\ttry {\n\t\t\t\thas\t= !!(window.ActiveXObject && new ActiveXObject('ShockwaveFlash.ShockwaveFlash'));\n\t\t\t}\n\t\t\tcatch(er){\n\t\t\t\tapi.log('Flash -- does not supported.');\n\t\t\t}\n\t\t}\n\n\t\tif( has && /^file:/i.test(location) ){\n\t\t\tapi.log('[warn] Flash does not work on `file:` protocol.');\n\t\t}\n\n\t\treturn\thas;\n\t})();\n\n\n\t   api.support.flash\n\t&& (0\n\t\t|| !api.html5 || !api.support.html5\n\t\t|| (api.cors && !api.support.cors)\n\t\t|| (api.media && !api.support.media)\n\t)\n\t&& (function (){\n\t\tvar\n\t\t\t  _attr  = api.uid()\n\t\t\t, _retry = 0\n\t\t\t, _files = {}\n\t\t\t, _rhttp = /^https?:/i\n\n\t\t\t, flash = {\n\t\t\t\t_fn: {},\n\n\n\t\t\t\t/**\n\t\t\t\t * Initialization & preload flash object\n\t\t\t\t */\n\t\t\t\tinit: function (){\n\t\t\t\t\tvar child = document.body && document.body.firstChild;\n\n\t\t\t\t\tif( child ){\n\t\t\t\t\t\tdo {\n\t\t\t\t\t\t\tif( child.nodeType == 1 ){\n\t\t\t\t\t\t\t\tapi.log('FlashAPI.state: awaiting');\n\n\t\t\t\t\t\t\t\tvar dummy = document.createElement('div');\n\n\t\t\t\t\t\t\t\tdummy.id = '_' + _attr;\n\n\t\t\t\t\t\t\t\t_css(dummy, {\n\t\t\t\t\t\t\t\t\t  top: 1\n\t\t\t\t\t\t\t\t\t, right: 1\n\t\t\t\t\t\t\t\t\t, width: 5\n\t\t\t\t\t\t\t\t\t, height: 5\n\t\t\t\t\t\t\t\t\t, position: 'absolute'\n\t\t\t\t\t\t\t\t\t, zIndex: 1e6+'' // set max zIndex\n\t\t\t\t\t\t\t\t});\n\n\t\t\t\t\t\t\t\tchild.parentNode.insertBefore(dummy, child);\n\t\t\t\t\t\t\t\tflash.publish(dummy, _attr);\n\n\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\twhile( child = child.nextSibling );\n\t\t\t\t\t}\n\n\t\t\t\t\tif( _retry < 10 ){\n\t\t\t\t\t\tsetTimeout(flash.init, ++_retry*50);\n\t\t\t\t\t}\n\t\t\t\t},\n\n\n\t\t\t\t/**\n\t\t\t\t * Publish flash-object\n\t\t\t\t *\n\t\t\t\t * @param {HTMLElement} el\n\t\t\t\t * @param {String} id\n\t\t\t\t * @param {Object} [opts]\n\t\t\t\t */\n\t\t\t\tpublish: function (el, id, opts){\n\t\t\t\t\topts = opts || {};\n\t\t\t\t\tel.innerHTML = _makeFlashHTML({\n\t\t\t\t\t\t  id: id\n\t\t\t\t\t\t, src: _getUrl(api.flashUrl, 'r=' + api.version)\n//\t\t\t\t\t\t, src: _getUrl('http://v.demidov.boom.corp.mail.ru/uploaderfileapi/FlashFileAPI.swf?1')\n\t\t\t\t\t\t, wmode: opts.camera ? '' : 'transparent'\n\t\t\t\t\t\t, flashvars: 'callback=' + (opts.onEvent || 'FileAPI.Flash.onEvent')\n\t\t\t\t\t\t\t+ '&flashId='+ id\n\t\t\t\t\t\t\t+ '&storeKey='+ navigator.userAgent.match(/\\d/ig).join('') +'_'+ api.version\n\t\t\t\t\t\t\t+ (flash.isReady || (api.pingUrl ? '&ping='+api.pingUrl : ''))\n\t\t\t\t\t\t\t+ '&timeout='+api.flashAbortTimeout\n\t\t\t\t\t\t\t+ (opts.camera ? '&useCamera=' + _getUrl(api.flashWebcamUrl) : '')\n\t\t\t\t\t\t\t+ '&debug='+(api.debug?\"1\":\"\")\n\t\t\t\t\t}, opts);\n\t\t\t\t},\n\n\n\t\t\t\tready: function (){\n\t\t\t\t\tapi.log('FlashAPI.state: ready');\n\n\t\t\t\t\tflash.ready = api.F;\n\t\t\t\t\tflash.isReady = true;\n\t\t\t\t\tflash.patch();\n\t\t\t\t\tflash.patchCamera && flash.patchCamera();\n\t\t\t\t\tapi.event.on(document, 'mouseover', flash.mouseover);\n\t\t\t\t\tapi.event.on(document, 'click', function (evt){\n\t\t\t\t\t\tif( flash.mouseover(evt) ){\n\t\t\t\t\t\t\tevt.preventDefault\n\t\t\t\t\t\t\t\t? evt.preventDefault()\n\t\t\t\t\t\t\t\t: (evt.returnValue = 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\n\t\t\t\tgetEl: function (){\n\t\t\t\t\treturn\tdocument.getElementById('_'+_attr);\n\t\t\t\t},\n\n\n\t\t\t\tgetWrapper: function (node){\n\t\t\t\t\tdo {\n\t\t\t\t\t\tif( /js-fileapi-wrapper/.test(node.className) ){\n\t\t\t\t\t\t\treturn\tnode;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\twhile( (node = node.parentNode) && (node !== document.body) );\n\t\t\t\t},\n\t\t\t\t\n\t\t\t\tdisableMouseover: false,\n\n\t\t\t\tmouseover: function (evt){\n\t\t\t\t\tif (!flash.disableMouseover) {\n\t\t\t\t\t\tvar target = api.event.fix(evt).target;\n\t\n\t\t\t\t\t\tif( /input/i.test(target.nodeName) && target.type == 'file' && !target.disabled ){\n\t\t\t\t\t\t\tvar\n\t\t\t\t\t\t\t\t  state = target.getAttribute(_attr)\n\t\t\t\t\t\t\t\t, wrapper = flash.getWrapper(target)\n\t\t\t\t\t\t\t;\n\t\n\t\t\t\t\t\t\tif( api.multiFlash ){\n\t\t\t\t\t\t\t\t// check state:\n\t\t\t\t\t\t\t\t//   i — published\n\t\t\t\t\t\t\t\t//   i — initialization\n\t\t\t\t\t\t\t\t//   r — ready\n\t\t\t\t\t\t\t\tif( state == 'i' || state == 'r' ){\n\t\t\t\t\t\t\t\t\t// publish fail\n\t\t\t\t\t\t\t\t\treturn\tfalse;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\telse if( state != 'p' ){\n\t\t\t\t\t\t\t\t\t// set \"init\" state\n\t\t\t\t\t\t\t\t\ttarget.setAttribute(_attr, 'i');\n\t\n\t\t\t\t\t\t\t\t\tvar dummy = document.createElement('div');\n\t\n\t\t\t\t\t\t\t\t\tif( !wrapper ){\n\t\t\t\t\t\t\t\t\t\tapi.log('[err] FlashAPI.mouseover: js-fileapi-wrapper not found');\n\t\t\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t\t\t}\n\t\n\t\t\t\t\t\t\t\t\t_css(dummy, {\n\t\t\t\t\t\t\t\t\t\t  top:    0\n\t\t\t\t\t\t\t\t\t\t, left:   0\n\t\t\t\t\t\t\t\t\t\t, width:  target.offsetWidth\n\t\t\t\t\t\t\t\t\t\t, height: target.offsetHeight\n\t\t\t\t\t\t\t\t\t\t, zIndex: 1e6+'' // set max zIndex\n\t\t\t\t\t\t\t\t\t\t, position: 'absolute'\n\t\t\t\t\t\t\t\t\t});\n\t\n\t\t\t\t\t\t\t\t\twrapper.appendChild(dummy);\n\t\t\t\t\t\t\t\t\tflash.publish(dummy, api.uid());\n\t\n\t\t\t\t\t\t\t\t\t// set \"publish\" state\n\t\t\t\t\t\t\t\t\ttarget.setAttribute(_attr, 'p');\n\t\t\t\t\t\t\t\t}\n\t\n\t\t\t\t\t\t\t\treturn\ttrue;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse if( wrapper ){\n\t\t\t\t\t\t\t\t// Use one flash element\n\t\t\t\t\t\t\t\tvar box = _getDimensions(wrapper);\n\t\t\t\t\t\t\t\t_css(flash.getEl(), box);\n\t\n\t\t\t\t\t\t\t\t// Set current input\n\t\t\t\t\t\t\t\tflash.curInp = target;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse if( !/object|embed/i.test(target.nodeName) ){\n\t\t\t\t\t\t\t_css(flash.getEl(), { top: 1, left: 1, width: 5, height: 5 });\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t},\n\n\t\t\t\tonEvent: function (evt){\n\t\t\t\t\tvar type = evt.type;\n\t\t\t\t\t\n\t\t\t\t\tif( type == 'ready' ){\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t// set \"ready\" state\n\t\t\t\t\t\t\tflash.getInput(evt.flashId).setAttribute(_attr, 'r');\n\t\t\t\t\t\t} catch (e){\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tflash.ready();\n\t\t\t\t\t\tsetTimeout(function (){ flash.mouseenter(evt); }, 50);\n\t\t\t\t\t\treturn\ttrue;\n\t\t\t\t\t}\n\t\t\t\t\telse if( type === 'ping' ){\n\t\t\t\t\t\tapi.log('(flash -> js).ping:', [evt.status, evt.savedStatus], evt.error);\n\t\t\t\t\t}\n\t\t\t\t\telse if( type === 'log' ){\n\t\t\t\t\t\tapi.log('(flash -> js).log:', evt.target);\n\t\t\t\t\t}\n\t\t\t\t\telse if( type in flash ){\n\t\t\t\t\t\tsetTimeout(function (){\n\t\t\t\t\t\t\tapi.log('FlashAPI.event.'+evt.type+':', evt);\n\t\t\t\t\t\t\tflash[type](evt);\n\t\t\t\t\t\t}, 1);\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tmouseDown: function(evt) {\n\t\t\t\t\tflash.disableMouseover = true;\n\t\t\t\t},\n\t\t\t\tcancel: function(evt) {\n\t\t\t\t\tflash.disableMouseover = false;\n\t\t\t\t},\n\t\t\t\tmouseenter: function (evt){\n\t\t\t\t\tvar node = flash.getInput(evt.flashId);\n\n\t\t\t\t\tif( node ){\n\t\t\t\t\t\t// Set multiple mode\n\t\t\t\t\t\tflash.cmd(evt, 'multiple', node.getAttribute('multiple') != null);\n\n\n\t\t\t\t\t\t// Set files filter\n\t\t\t\t\t\tvar accept = [], exts = {};\n\n\t\t\t\t\t\t_each((node.getAttribute('accept') || '').split(/,\\s*/), function (mime){\n\t\t\t\t\t\t\tapi.accept[mime] && _each(api.accept[mime].split(' '), function (ext){\n\t\t\t\t\t\t\t\texts[ext] = 1;\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t});\n\n\t\t\t\t\t\t_each(exts, function (i, ext){\n\t\t\t\t\t\t\taccept.push( ext );\n\t\t\t\t\t\t});\n\n\t\t\t\t\t\tflash.cmd(evt, 'accept', accept.length ? accept.join(',')+','+accept.join(',').toUpperCase() : '*');\n\t\t\t\t\t}\n\t\t\t\t},\n\n\n\t\t\t\tget: function (id){\n\t\t\t\t\treturn\tdocument[id] || window[id] || document.embeds[id];\n\t\t\t\t},\n\n\n\t\t\t\tgetInput: function (id){\n\t\t\t\t\tif( api.multiFlash ){\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tvar node = flash.getWrapper(flash.get(id));\n\t\t\t\t\t\t\tif( node ){\n\t\t\t\t\t\t\t\treturn node.getElementsByTagName('input')[0];\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} catch (e){\n\t\t\t\t\t\t\tapi.log('[err] Can not find \"input\" by flashId:', id, e);\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\treturn\tflash.curInp;\n\t\t\t\t\t}\n\t\t\t\t},\n\n\n\t\t\t\tselect: function (evt){\n\t\t\t\t\ttry {\n\t\t\t\t\t\tvar\n\t\t\t\t\t\t\t  inp = flash.getInput(evt.flashId)\n\t\t\t\t\t\t\t, uid = api.uid(inp)\n\t\t\t\t\t\t\t, files = evt.target.files\n\t\t\t\t\t\t\t, event\n\t\t\t\t\t\t;\n\t\t\t\t\t\t_each(files, function (file){\n\t\t\t\t\t\t\tapi.checkFileObj(file);\n\t\t\t\t\t\t});\n\t\n\t\t\t\t\t\t_files[uid] = files;\n\t\n\t\t\t\t\t\tif( document.createEvent ){\n\t\t\t\t\t\t\tevent = document.createEvent('Event');\n\t\t\t\t\t\t\tevent.files = files;\n\t\t\t\t\t\t\tevent.initEvent('change', true, true);\n\t\t\t\t\t\t\tinp.dispatchEvent(event);\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse if( jQuery ){\n\t\t\t\t\t\t\tjQuery(inp).trigger({ type: 'change', files: files });\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse {\n\t\t\t\t\t\t\tevent = document.createEventObject();\n\t\t\t\t\t\t\tevent.files = files;\n\t\t\t\t\t\t\tinp.fireEvent('onchange', event);\n\t\t\t\t\t\t}\n\t\t\t\t\t} finally {\n\t\t\t\t\t\tflash.disableMouseover = false;\n\t\t\t\t\t}\n\t\t\t\t},\n\n\n\t\t\t\tcmd: function (id, name, data, last){\n\t\t\t\t\ttry {\n\t\t\t\t\t\tapi.log('(js -> flash).'+name+':', data);\n\t\t\t\t\t\treturn flash.get(id.flashId || id).cmd(name, data);\n\t\t\t\t\t} catch (e){\n\t\t\t\t\t\tapi.log('(js -> flash).onError:', e);\n\t\t\t\t\t\tif( !last ){\n\t\t\t\t\t\t\t// try again\n\t\t\t\t\t\t\tsetTimeout(function (){ flash.cmd(id, name, data, true); }, 50);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t},\n\n\n\t\t\t\tpatch: function (){\n\t\t\t\t\tapi.flashEngine = true;\n\n\t\t\t\t\t// FileAPI\n\t\t\t\t\t_inherit(api, {\n\t\t\t\t\t\tgetFiles: function (input, filter, callback){\n\t\t\t\t\t\t\tif( callback ){\n\t\t\t\t\t\t\t\tapi.filterFiles(api.getFiles(input), filter, callback);\n\t\t\t\t\t\t\t\treturn null;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tvar files = api.isArray(input) ? input : _files[api.uid(input.target || input.srcElement || input)];\n\n\n\t\t\t\t\t\t\tif( !files ){\n\t\t\t\t\t\t\t\t// Файлов нету, вызываем родительский метод\n\t\t\t\t\t\t\t\treturn\tthis.parent.apply(this, arguments);\n\t\t\t\t\t\t\t}\n\n\n\t\t\t\t\t\t\tif( filter ){\n\t\t\t\t\t\t\t\tfilter\t= api.getFilesFilter(filter);\n\t\t\t\t\t\t\t\tfiles\t= api.filter(files, function (file){ return filter.test(file.name); });\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\treturn\tfiles;\n\t\t\t\t\t\t},\n\n\n\t\t\t\t\t\tgetInfo: function (file, fn){\n\t\t\t\t\t\t\tif( _isHtmlFile(file) ){\n\t\t\t\t\t\t\t\tthis.parent.apply(this, arguments);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse if( file.isShot ){\n\t\t\t\t\t\t\t\tfn(null, file.info = {\n\t\t\t\t\t\t\t\t\twidth: file.width,\n\t\t\t\t\t\t\t\t\theight: file.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\telse {\n\t\t\t\t\t\t\t\tif( !file.__info ){\n\t\t\t\t\t\t\t\t\tvar defer = file.__info = api.defer();\n\n//\t\t\t\t\t\t\t\t\tflash.cmd(file, 'getFileInfo', {\n//\t\t\t\t\t\t\t\t\t\t  id: file.id\n//\t\t\t\t\t\t\t\t\t\t, callback: _wrap(function _(err, info){\n//\t\t\t\t\t\t\t\t\t\t\t_unwrap(_);\n//\t\t\t\t\t\t\t\t\t\t\tdefer.resolve(err, file.info = info);\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\tdefer.resolve(null, file.info = null);\n\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\tfile.__info.then(fn);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\n\n\t\t\t\t\t// FileAPI.Image\n\t\t\t\t\tapi.support.transform = true;\n\t\t\t\t\tapi.Image && _inherit(api.Image.prototype, {\n\t\t\t\t\t\tget: function (fn, scaleMode){\n\t\t\t\t\t\t\tthis.set({ scaleMode: scaleMode || 'noScale' }); // noScale, exactFit\n\t\t\t\t\t\t\treturn this.parent(fn);\n\t\t\t\t\t\t},\n\n\t\t\t\t\t\t_load: function (file, fn){\n\t\t\t\t\t\t\tapi.log('FlashAPI.Image._load:', file);\n\n\t\t\t\t\t\t\tif( _isHtmlFile(file) ){\n\t\t\t\t\t\t\t\tthis.parent.apply(this, arguments);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse {\n\t\t\t\t\t\t\t\tvar _this = this;\n\t\t\t\t\t\t\t\tapi.getInfo(file, function (err){\n\t\t\t\t\t\t\t\t\tfn.call(_this, err, file);\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_apply: function (file, fn){\n\t\t\t\t\t\t\tapi.log('FlashAPI.Image._apply:', file);\n\n\t\t\t\t\t\t\tif( _isHtmlFile(file) ){\n\t\t\t\t\t\t\t\tthis.parent.apply(this, arguments);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse {\n\t\t\t\t\t\t\t\tvar m = this.getMatrix(file.info), doneFn = fn;\n\n\t\t\t\t\t\t\t\tflash.cmd(file, 'imageTransform', {\n\t\t\t\t\t\t\t\t\t  id: file.id\n\t\t\t\t\t\t\t\t\t, matrix: m\n\t\t\t\t\t\t\t\t\t, callback: _wrap(function _(err, base64){\n\t\t\t\t\t\t\t\t\t\tapi.log('FlashAPI.Image._apply.callback:', err);\n\t\t\t\t\t\t\t\t\t\t_unwrap(_);\n\n\t\t\t\t\t\t\t\t\t\tif( err ){\n\t\t\t\t\t\t\t\t\t\t\tdoneFn(err);\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\telse if( !api.support.html5 && (!api.support.dataURI || base64.length > 3e4) ){\n\t\t\t\t\t\t\t\t\t\t\t_makeFlashImage({\n\t\t\t\t\t\t\t\t\t\t\t\t  width:\t(m.deg % 180) ? m.dh : m.dw\n\t\t\t\t\t\t\t\t\t\t\t\t, height:\t(m.deg % 180) ? m.dw : m.dh\n\t\t\t\t\t\t\t\t\t\t\t\t, scale:\tm.scaleMode\n\t\t\t\t\t\t\t\t\t\t\t}, base64, doneFn);\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\telse {\n\t\t\t\t\t\t\t\t\t\t\tif( m.filter ){\n\t\t\t\t\t\t\t\t\t\t\t\tdoneFn = function (err, img){\n\t\t\t\t\t\t\t\t\t\t\t\t\tif( err ){\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tfn(err);\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\telse {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tapi.Image.applyFilter(img, m.filter, function (){\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tfn(err, this.canvas);\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};\n\t\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t\tapi.newImage('data:'+ file.type +';base64,'+ base64, doneFn);\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\ttoData: function (fn){\n\t\t\t\t\t\t\tvar\n\t\t\t\t\t\t\t\t  file = this.file\n\t\t\t\t\t\t\t\t, info = file.info\n\t\t\t\t\t\t\t\t, matrix = this.getMatrix(info)\n\t\t\t\t\t\t\t;\n\t\t\t\t\t\t\tapi.log('FlashAPI.Image.toData');\n\n\t\t\t\t\t\t\tif( _isHtmlFile(file) ){\n\t\t\t\t\t\t\t\tthis.parent.apply(this, arguments);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse {\n\t\t\t\t\t\t\t\tif( matrix.deg == 'auto' ){\n\t\t\t\t\t\t\t\t\tmatrix.deg = api.Image.exifOrientation[info && info.exif && info.exif.Orientation] || 0;\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\tfn.call(this, !file.info, {\n\t\t\t\t\t\t\t\t\t  id:\t\tfile.id\n\t\t\t\t\t\t\t\t\t, flashId:\tfile.flashId\n\t\t\t\t\t\t\t\t\t, name:\t\tfile.name\n\t\t\t\t\t\t\t\t\t, type:\t\tfile.type\n\t\t\t\t\t\t\t\t\t, matrix:\tmatrix\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\n\n\t\t\t\t\tapi.Image && _inherit(api.Image, {\n\t\t\t\t\t\tfromDataURL: function (dataURL, size, callback){\n\t\t\t\t\t\t\tif( !api.support.dataURI || dataURL.length > 3e4 ){\n\t\t\t\t\t\t\t\t_makeFlashImage(\n\t\t\t\t\t\t\t\t\t  api.extend({ scale: 'exactFit' }, size)\n\t\t\t\t\t\t\t\t\t, dataURL.replace(/^data:[^,]+,/, '')\n\t\t\t\t\t\t\t\t\t, function (err, el){ callback(el); }\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\tthis.parent(dataURL, size, callback);\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// FileAPI.Form\n\t\t\t\t\t_inherit(api.Form.prototype, {\n\t\t\t\t\t\ttoData: function (fn){\n\t\t\t\t\t\t\tvar items = this.items, i = items.length;\n\n\t\t\t\t\t\t\tfor( ; i--; ){\n\t\t\t\t\t\t\t\tif( items[i].file && _isHtmlFile(items[i].blob) ){\n\t\t\t\t\t\t\t\t\treturn this.parent.apply(this, arguments);\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\tapi.log('FlashAPI.Form.toData');\n\t\t\t\t\t\t\tfn(items);\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\n\n\t\t\t\t\t// FileAPI.XHR\n\t\t\t\t\t_inherit(api.XHR.prototype, {\n\t\t\t\t\t\t_send: function (options, formData){\n\t\t\t\t\t\t\tif(\n\t\t\t\t\t\t\t\t   formData.nodeName\n\t\t\t\t\t\t\t\t|| formData.append && api.support.html5\n\t\t\t\t\t\t\t\t|| api.isArray(formData) && (typeof formData[0] === 'string')\n\t\t\t\t\t\t\t){\n\t\t\t\t\t\t\t\t// HTML5, Multipart or IFrame\n\t\t\t\t\t\t\t\treturn\tthis.parent.apply(this, arguments);\n\t\t\t\t\t\t\t}\n\n\n\t\t\t\t\t\t\tvar\n\t\t\t\t\t\t\t\t  data = {}\n\t\t\t\t\t\t\t\t, files = {}\n\t\t\t\t\t\t\t\t, _this = this\n\t\t\t\t\t\t\t\t, flashId\n\t\t\t\t\t\t\t\t, fileId\n\t\t\t\t\t\t\t;\n\n\t\t\t\t\t\t\t_each(formData, function (item){\n\t\t\t\t\t\t\t\tif( item.file ){\n\t\t\t\t\t\t\t\t\tfiles[item.name] = item = _getFileDescr(item.blob);\n\t\t\t\t\t\t\t\t\tfileId  = item.id;\n\t\t\t\t\t\t\t\t\tflashId = item.flashId;\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\tdata[item.name] = item.blob;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t});\n\n\t\t\t\t\t\t\tif( !fileId ){\n\t\t\t\t\t\t\t\tflashId = _attr;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tif( !flashId ){\n\t\t\t\t\t\t\t\tapi.log('[err] FlashAPI._send: flashId -- undefined');\n\t\t\t\t\t\t\t\treturn this.parent.apply(this, arguments);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse {\n\t\t\t\t\t\t\t\tapi.log('FlashAPI.XHR._send: '+ flashId +' -> '+ fileId);\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t_this.xhr = {\n\t\t\t\t\t\t\t\theaders: {},\n\t\t\t\t\t\t\t\tabort: function (){ flash.cmd(flashId, 'abort', { id: fileId }); },\n\t\t\t\t\t\t\t\tgetResponseHeader: function (name){ return this.headers[name]; },\n\t\t\t\t\t\t\t\tgetAllResponseHeaders: function (){ return this.headers; }\n\t\t\t\t\t\t\t};\n\n\t\t\t\t\t\t\tvar queue = api.queue(function (){\n\t\t\t\t\t\t\t\tflash.cmd(flashId, 'upload', {\n\t\t\t\t\t\t\t\t\t  url: _getUrl(options.url.replace(/([a-z]+)=(\\?)&?/i, ''))\n\t\t\t\t\t\t\t\t\t, data: data\n\t\t\t\t\t\t\t\t\t, files: fileId ? files : null\n\t\t\t\t\t\t\t\t\t, headers: options.headers || {}\n\t\t\t\t\t\t\t\t\t, callback: _wrap(function upload(evt){\n\t\t\t\t\t\t\t\t\t\tvar type = evt.type, result = evt.result;\n\n\t\t\t\t\t\t\t\t\t\tapi.log('FlashAPI.upload.'+type);\n\n\t\t\t\t\t\t\t\t\t\tif( type == 'progress' ){\n\t\t\t\t\t\t\t\t\t\t\tevt.loaded = Math.min(evt.loaded, evt.total); // @todo fixme\n\t\t\t\t\t\t\t\t\t\t\tevt.lengthComputable = true;\n\t\t\t\t\t\t\t\t\t\t\toptions.progress(evt);\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\telse if( type == 'complete' ){\n\t\t\t\t\t\t\t\t\t\t\t_unwrap(upload);\n\n\t\t\t\t\t\t\t\t\t\t\tif( typeof result == 'string' ){\n\t\t\t\t\t\t\t\t\t\t\t\t_this.responseText\t= result.replace(/%22/g, \"\\\"\").replace(/%5c/g, \"\\\\\").replace(/%26/g, \"&\").replace(/%25/g, \"%\");\n\t\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t\t_this.end(evt.status || 200);\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\telse if( type == 'abort' || type == 'error' ){\n\t\t\t\t\t\t\t\t\t\t\t_this.end(evt.status || 0, evt.message);\n\t\t\t\t\t\t\t\t\t\t\t_unwrap(upload);\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\n\n\t\t\t\t\t\t\t// #2174: FileReference.load() call while FileReference.upload() or vice versa\n\t\t\t\t\t\t\t_each(files, function (file){\n\t\t\t\t\t\t\t\tqueue.inc();\n\t\t\t\t\t\t\t\tapi.getInfo(file, queue.next);\n\t\t\t\t\t\t\t});\n\n\t\t\t\t\t\t\tqueue.check();\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\n\t\tfunction _makeFlashHTML(opts){\n\t\t\treturn ('<object id=\"#id#\" classid=\"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000\" width=\"'+(opts.width || '100%')+'\" height=\"'+(opts.height || '100%')+'\">'\n\t\t\t\t+ '<param name=\"movie\" value=\"#src#\" />'\n\t\t\t\t+ '<param name=\"flashvars\" value=\"#flashvars#\" />'\n\t\t\t\t+ '<param name=\"swliveconnect\" value=\"true\" />'\n\t\t\t\t+ '<param name=\"allowscriptaccess\" value=\"always\" />'\n\t\t\t\t+ '<param name=\"allownetworking\" value=\"all\" />'\n\t\t\t\t+ '<param name=\"menu\" value=\"false\" />'\n\t\t\t\t+ '<param name=\"wmode\" value=\"#wmode#\" />'\n\t\t\t\t+ '<embed flashvars=\"#flashvars#\" swliveconnect=\"true\" allownetworking=\"all\" allowscriptaccess=\"always\" name=\"#id#\" src=\"#src#\" width=\"'+(opts.width || '100%')+'\" height=\"'+(opts.height || '100%')+'\" menu=\"false\" wmode=\"transparent\" type=\"application/x-shockwave-flash\"></embed>'\n\t\t\t\t+ '</object>').replace(/#(\\w+)#/ig, function (a, name){ return opts[name]; })\n\t\t\t;\n\t\t}\n\n\n\t\tfunction _css(el, css){\n\t\t\tif( el && el.style ){\n\t\t\t\tvar key, val;\n\t\t\t\tfor( key in css ){\n\t\t\t\t\tval = css[key];\n\t\t\t\t\tif( typeof val == 'number' ){\n\t\t\t\t\t\tval += 'px';\n\t\t\t\t\t}\n\t\t\t\t\ttry { el.style[key] = val; } catch (e) {}\n\t\t\t\t}\n\t\t\t\t\n\t\t\t}\n\t\t}\n\n\n\t\tfunction _inherit(obj, methods){\n\t\t\t_each(methods, function (fn, name){\n\t\t\t\tvar prev = obj[name];\n\t\t\t\tobj[name] = function (){\n\t\t\t\t\tthis.parent = prev;\n\t\t\t\t\treturn fn.apply(this, arguments);\n\t\t\t\t};\n\t\t\t});\n\t\t}\n\n\t\tfunction _isHtmlFile(file){\n\t\t\treturn\tfile && !file.flashId;\n\t\t}\n\n\t\tfunction _wrap(fn){\n\t\t\tvar id = fn.wid = api.uid();\n\t\t\tflash._fn[id] = fn;\n\t\t\treturn\t'FileAPI.Flash._fn.'+id;\n\t\t}\n\n\n\t\tfunction _unwrap(fn){\n\t\t\ttry {\n\t\t\t\tflash._fn[fn.wid] = null;\n\t\t\t\tdelete\tflash._fn[fn.wid];\n\t\t\t}\n\t\t\tcatch(e){}\n\t\t}\n\n\n\t\tfunction _getUrl(url, params){\n\t\t\tif( !_rhttp.test(url) ){\n\t\t\t\tif( /^\\.\\//.test(url) || '/' != url.charAt(0) ){\n\t\t\t\t\tvar path = location.pathname;\n\t\t\t\t\tpath = path.substr(0, path.lastIndexOf('/'));\n\t\t\t\t\turl = (path +'/'+ url).replace('/./', '/');\n\t\t\t\t}\n\n\t\t\t\tif( '//' != url.substr(0, 2) ){\n\t\t\t\t\turl = '//' + location.host + url;\n\t\t\t\t}\n\n\t\t\t\tif( !_rhttp.test(url) ){\n\t\t\t\t\turl = location.protocol + url;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif( params ){\n\t\t\t\turl += (/\\?/.test(url) ? '&' : '?') + params;\n\t\t\t}\n\n\t\t\treturn\turl;\n\t\t}\n\n\n\t\tfunction _makeFlashImage(opts, base64, fn){\n\t\t\tvar\n\t\t\t\t  key\n\t\t\t\t, flashId = api.uid()\n\t\t\t\t, el = document.createElement('div')\n\t\t\t\t, attempts = 10\n\t\t\t;\n\n\t\t\tfor( key in opts ){\n\t\t\t\tel.setAttribute(key, opts[key]);\n\t\t\t\tel[key] = opts[key];\n\t\t\t}\n\n\t\t\t_css(el, opts);\n\n\t\t\topts.width\t= '100%';\n\t\t\topts.height\t= '100%';\n\n\t\t\tel.innerHTML = _makeFlashHTML(api.extend({\n\t\t\t\t  id: flashId\n\t\t\t\t, src: _getUrl(api.flashImageUrl, 'r='+ api.uid())\n\t\t\t\t, wmode: 'opaque'\n\t\t\t\t, flashvars: 'scale='+ opts.scale +'&callback='+_wrap(function _(){\n\t\t\t\t\t_unwrap(_);\n\t\t\t\t\tif( --attempts > 0 ){\n\t\t\t\t\t\t_setImage();\n\t\t\t\t\t}\n\t\t\t\t\treturn true;\n\t\t\t\t})\n\t\t\t}, opts));\n\n\t\t\tfunction _setImage(){\n\t\t\t\ttry {\n\t\t\t\t\t// Get flash-object by id\n\t\t\t\t\tvar img = flash.get(flashId);\n\t\t\t\t\timg.setImage(base64);\n\t\t\t\t} catch (e){\n\t\t\t\t\tapi.log('[err] FlashAPI.Preview.setImage -- can not set \"base64\":', e);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfn(false, el);\n\t\t\tel = null;\n\t\t}\n\n\n\t\tfunction _getFileDescr(file){\n\t\t\treturn\t{\n\t\t\t\t  id: file.id\n\t\t\t\t, name: file.name\n\t\t\t\t, matrix: file.matrix\n\t\t\t\t, flashId: file.flashId\n\t\t\t};\n\t\t}\n\n\n\t\tfunction _getDimensions(el){\n\t\t\tvar\n\t\t\t\t  box = el.getBoundingClientRect()\n\t\t\t\t, body = document.body\n\t\t\t\t, docEl = (el && el.ownerDocument).documentElement\n\t\t\t;\n\t\t\t\n\t\t\tfunction getOffset(obj) {\n\t\t\t    var left, top;\n\t\t\t    left = top = 0;\n\t\t\t    if (obj.offsetParent) {\n\t\t\t        do {\n\t\t\t            left += obj.offsetLeft;\n\t\t\t            top  += obj.offsetTop;\n\t\t\t        } while (obj = obj.offsetParent);\n\t\t\t    }\n\t\t\t    return {\n\t\t\t        left : left,\n\t\t\t        top : top\n\t\t\t    };\n\t\t\t};\n\t\t\t\n\t\t\treturn {\n\t\t\t\t  top:\t\tgetOffset(el).top\n\t\t\t\t, left:\t\tgetOffset(el).left\n\t\t\t\t, width:\tel.offsetWidth\n\t\t\t\t, height:\tel.offsetHeight\n\t\t\t};\n\t\t}\n\n\t\t// @export\n\t\tapi.Flash = flash;\n\n\n\t\t// Check dataURI support\n\t\tapi.newImage('data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///ywAAAAAAQABAAACAUwAOw==', function (err, img){\n\t\t\tapi.support.dataURI = !(img.width != 1 || img.height != 1);\n\t\t\tflash.init();\n\t\t});\n\t})();\n})(window, window.jQuery, FileAPI);\n\n/**\n * FileAPI fallback to Flash\n *\n * @flash-developer  \"Vladimir Demidov\" <v.demidov@corp.mail.ru>\n */\n\n/*global window, FileAPI */\n(function (window, jQuery, api) {\n    \"use strict\";\n\n    var _each = api.each,\n        _cameraQueue = [];\n\n\n    if (api.support.flash && (api.media && !api.support.media)) {\n        (function () {\n\n            function _wrap(fn) {\n                var id = fn.wid = api.uid();\n                api.Flash._fn[id] = fn;\n                return 'FileAPI.Flash._fn.' + id;\n            }\n\n\n            function _unwrap(fn) {\n                try {\n                    api.Flash._fn[fn.wid] = null;\n                    delete api.Flash._fn[fn.wid];\n                } catch (e) {\n                }\n            }\n\n            var flash = api.Flash;\n            api.extend(api.Flash, {\n\n                patchCamera: function () {\n                    api.Camera.fallback = function (el, options, callback) {\n                        var camId = api.uid();\n                        api.log('FlashAPI.Camera.publish: ' + camId);\n                        flash.publish(el, camId, api.extend(options, {\n                            camera: true,\n                            onEvent: _wrap(function _(evt) {\n                                if (evt.type === 'camera') {\n                                    _unwrap(_);\n\n                                    if (evt.error) {\n                                        api.log('FlashAPI.Camera.publish.error: ' + evt.error);\n                                        callback(evt.error);\n                                    } else {\n                                        api.log('FlashAPI.Camera.publish.success: ' + camId);\n                                        callback(null);\n                                    }\n                                }\n                            })\n                        }));\n                    };\n                    // Run\n                    _each(_cameraQueue, function (args) {\n                        api.Camera.fallback.apply(api.Camera, args);\n                    });\n                    _cameraQueue = [];\n\n\n                    // FileAPI.Camera:proto\n                    api.extend(api.Camera.prototype, {\n                        _id: function () {\n                            return this.video.id;\n                        },\n\n                        start: function (callback) {\n                            var _this = this;\n                            flash.cmd(this._id(), 'camera.on', {\n                                callback: _wrap(function _(evt) {\n                                    _unwrap(_);\n\n                                    if (evt.error) {\n                                        api.log('FlashAPI.camera.on.error: ' + evt.error);\n                                        callback(evt.error, _this);\n                                    } else {\n                                        api.log('FlashAPI.camera.on.success: ' + _this._id());\n                                        _this._active = true;\n                                        callback(null, _this);\n                                    }\n                                })\n                            });\n                        },\n\n                        stop: function () {\n                            this._active = false;\n                            flash.cmd(this._id(), 'camera.off');\n                        },\n\n                        shot: function () {\n                            api.log('FlashAPI.Camera.shot:', this._id());\n\n                            var shot = api.Flash.cmd(this._id(), 'shot', {});\n                            shot.type = 'image/png';\n                            shot.flashId = this._id();\n                            shot.isShot = true;\n\n                            return new api.Camera.Shot(shot);\n                        }\n                    });\n                }\n            });\n\n            api.Camera.fallback = function () {\n                _cameraQueue.push(arguments);\n            };\n\n        }());\n    }\n}(window, window.jQuery, FileAPI));\nif( typeof define === \"function\" && define.amd ){ define(\"FileAPI\", [], function (){ return FileAPI; }); }"
  },
  {
    "path": "flowable-ui-web/modeler/libs/ng-file-upload/ng-file-upload-all.js",
    "content": "/**!\n * AngularJS file upload/drop directive and service with progress and abort\n * @author  Danial  <danial.farid@gmail.com>\n * @version 4.1.0\n */\n(function () {\n\nvar key, i;\nfunction patchXHR(fnName, newFn) {\n    window.XMLHttpRequest.prototype[fnName] = newFn(window.XMLHttpRequest.prototype[fnName]);\n}\n\nif (window.XMLHttpRequest && !window.XMLHttpRequest.__isFileAPIShim) {\n    patchXHR('setRequestHeader', function (orig) {\n        return function (header, value) {\n            if (header === '__setXHR_') {\n                var val = value(this);\n                // fix for angular < 1.2.0\n                if (val instanceof Function) {\n                    val(this);\n                }\n            } else {\n                orig.apply(this, arguments);\n            }\n        }\n    });\n}\n\nvar ngFileUpload = angular.module('ngFileUpload', []);\n\nngFileUpload.version = '4.1.0';\nngFileUpload.service('Upload', ['$http', '$q', '$timeout', function ($http, $q, $timeout) {\n    function sendHttp(config) {\n        config.method = config.method || 'POST';\n        config.headers = config.headers || {};\n        config.transformRequest = config.transformRequest || function (data, headersGetter) {\n            if (window.ArrayBuffer && data instanceof window.ArrayBuffer) {\n                return data;\n            }\n            return $http.defaults.transformRequest[0](data, headersGetter);\n        };\n        var deferred = $q.defer();\n        var promise = deferred.promise;\n\n        config.headers['__setXHR_'] = function () {\n            return function (xhr) {\n                if (!xhr) return;\n                config.__XHR = xhr;\n                config.xhrFn && config.xhrFn(xhr);\n                xhr.upload.addEventListener('progress', function (e) {\n                    e.config = config;\n                    deferred.notify ? deferred.notify(e) : promise.progress_fn && $timeout(function () {\n                        promise.progress_fn(e)\n                    });\n                }, false);\n                //fix for firefox not firing upload progress end, also IE8-9\n                xhr.upload.addEventListener('load', function (e) {\n                    if (e.lengthComputable) {\n                        e.config = config;\n                        deferred.notify ? deferred.notify(e) : promise.progress_fn && $timeout(function () {\n                            promise.progress_fn(e)\n                        });\n                    }\n                }, false);\n            };\n        };\n\n        $http(config).then(function (r) {\n            deferred.resolve(r)\n        }, function (e) {\n            deferred.reject(e)\n        }, function (n) {\n            deferred.notify(n)\n        });\n\n        promise.success = function (fn) {\n            promise.then(function (response) {\n                fn(response.data, response.status, response.headers, config);\n            });\n            return promise;\n        };\n\n        promise.error = function (fn) {\n            promise.then(null, function (response) {\n                fn(response.data, response.status, response.headers, config);\n            });\n            return promise;\n        };\n\n        promise.progress = function (fn) {\n            promise.progress_fn = fn;\n            promise.then(null, null, function (update) {\n                fn(update);\n            });\n            return promise;\n        };\n        promise.abort = function () {\n            if (config.__XHR) {\n                $timeout(function () {\n                    config.__XHR.abort();\n                });\n            }\n            return promise;\n        };\n        promise.xhr = function (fn) {\n            config.xhrFn = (function (origXhrFn) {\n                return function () {\n                    origXhrFn && origXhrFn.apply(promise, arguments);\n                    fn.apply(promise, arguments);\n                }\n            })(config.xhrFn);\n            return promise;\n        };\n\n        return promise;\n    }\n\n    this.upload = function (config) {\n        config.headers = config.headers || {};\n        config.headers['Content-Type'] = undefined;\n        config.transformRequest = config.transformRequest ?\n            (angular.isArray(config.transformRequest) ?\n                config.transformRequest : [config.transformRequest]) : [];\n        config.transformRequest.push(function (data) {\n            var formData = new FormData();\n            var allFields = {};\n            for (key in config.fields) {\n                if (config.fields.hasOwnProperty(key)) {\n                    allFields[key] = config.fields[key];\n                }\n            }\n            if (data) allFields['data'] = data;\n\n            if (config.formDataAppender) {\n                for (key in allFields) {\n                    if (allFields.hasOwnProperty(key)) {\n                        config.formDataAppender(formData, key, allFields[key]);\n                    }\n                }\n            } else {\n                for (key in allFields) {\n                    if (allFields.hasOwnProperty(key)) {\n                        var val = allFields[key];\n                        if (val !== undefined) {\n                            if (angular.isDate(val)) {\n                                val = val.toISOString();\n                            }\n                            if (angular.isString(val)) {\n                                formData.append(key, val);\n                            } else {\n                                if (config.sendObjectsAsJsonBlob && angular.isObject(val)) {\n                                    formData.append(key, new Blob([val], {type: 'application/json'}));\n                                } else {\n                                    formData.append(key, JSON.stringify(val));\n                                }\n                            }\n\n                        }\n                    }\n                }\n            }\n\n            if (config.file != null) {\n                var fileFormName = config.fileFormDataName || 'file';\n\n                if (angular.isArray(config.file)) {\n                    var isFileFormNameString = angular.isString(fileFormName);\n                    for (var i = 0; i < config.file.length; i++) {\n                        formData.append(isFileFormNameString ? fileFormName : fileFormName[i], config.file[i],\n                            (config.fileName && config.fileName[i]) || config.file[i].name);\n                    }\n                } else {\n                    formData.append(fileFormName, config.file, config.fileName || config.file.name);\n                }\n            }\n            return formData;\n        });\n\n        return sendHttp(config);\n    };\n\n    this.http = function (config) {\n        return sendHttp(config);\n    };\n}]);\n\nngFileUpload.directive('ngfSelect', ['$parse', '$timeout', '$compile',\n    function ($parse, $timeout, $compile) {\n        return {\n            restrict: 'AEC',\n            require: '?ngModel',\n            link: function (scope, elem, attr, ngModel) {\n                linkFileSelect(scope, elem, attr, ngModel, $parse, $timeout, $compile);\n            }\n        }\n    }]);\n\nfunction linkFileSelect(scope, elem, attr, ngModel, $parse, $timeout, $compile) {\n    function isInputTypeFile() {\n        return elem[0].tagName.toLowerCase() === 'input' && elem.attr('type') && elem.attr('type').toLowerCase() === 'file';\n    }\n    var changeFnAttr = attr.ngfChange || (attr.ngfSelect && attr.ngfSelect.indexOf('(') > 0);\n    var isUpdating = false;\n    function changeFn(evt) {\n        if (!isUpdating) {\n            isUpdating = true;\n            try {\n                var fileList = evt.__files_ || (evt.target && evt.target.files);\n                var files = [], rejFiles = [];\n\n                for (var i = 0; i < fileList.length; i++) {\n                    var file = fileList.item(i);\n                    if (validate(scope, $parse, attr, file, evt)) {\n                        files.push(file);\n                    } else {\n                        rejFiles.push(file);\n                    }\n                }\n                updateModel($parse, $timeout, scope, ngModel, attr, changeFnAttr, files, rejFiles, evt);\n                if (files.length == 0) evt.target.value = files;\n//                if (evt.target && evt.target.getAttribute('__ngf_gen__')) {\n//                    angular.element(evt.target).remove();\n//                }\n            } finally {\n                isUpdating = false;\n            }\n        }\n    }\n\n    function bindAttrToFileInput(fileElem) {\n        if (attr.ngfMultiple) fileElem.attr('multiple', $parse(attr.ngfMultiple)(scope));\n        if (!$parse(attr.ngfMultiple)(scope)) fileElem.attr('multiple', undefined);\n        if (attr['accept']) fileElem.attr('accept', attr['accept']);\n        if (attr.ngfCapture) fileElem.attr('capture', $parse(attr.ngfCapture)(scope));\n        if (attr.ngfDisabled) fileElem.attr('disabled', $parse(attr.ngfDisabled)(scope));\n        for (var i = 0; i < elem[0].attributes.length; i++) {\n            var attribute = elem[0].attributes[i];\n            if (attribute.name !== 'type' && attribute.name !== 'class' && attribute.name !== 'id' && attribute.name !== 'style') {\n            \tfileElem.attr(attribute.name, attribute.value);\n            }\n        }\n    }\n\n    function createFileInput(evt) {\n        if (elem.attr('disabled')) {\n            return;\n        }\n        var fileElem = angular.element('<input type=\"file\">');\n        bindAttrToFileInput(fileElem);\n\n        if (isInputTypeFile()) {\n            elem.replaceWith(fileElem);\n            elem = fileElem;\n        } else {\n            fileElem.css('display', 'none').attr('tabindex', '-1').attr('__ngf_gen__', true);\n            if (elem.__ngf_ref_elem__) {elem.__ngf_ref_elem__.remove();}\n            elem.__ngf_ref_elem__ = fileElem;\n            document.body.appendChild(fileElem[0]);\n        }\n\n        return fileElem;\n    }\n\n    function resetModel(evt) {\n        updateModel($parse, $timeout, scope, ngModel, attr, changeFnAttr, [], [], evt, true);\n    }\n\n    function clickHandler(evt) {\n    \tevt.preventDefault();\n        var fileElem = createFileInput(evt);\n        if (fileElem) {\n        \tfileElem.bind('change', changeFn);\n        \tresetModel(evt);\n\n        \tfunction clickAndAssign() {\n            \tfileElem[0].click();\n    \t        if (isInputTypeFile()) {\n    \t            elem.bind('click touchend', clickHandler);\n    \t            evt.preventDefault()\n    \t        }\n        \t}\n        \t\n        \t// fix for android native browser\n        \tif (navigator.userAgent.toLowerCase().match(/android/)) {\n                setTimeout(function() {\n                \tclickAndAssign();\n                }, 0);        \t\t\n        \t} else {\n        \t\tclickAndAssign();\n        \t}\n        }\n    }\n\n    if (window.FileAPI && window.FileAPI.ngfFixIE) {\n        window.FileAPI.ngfFixIE(elem, createFileInput, bindAttrToFileInput, changeFn, resetModel);\n    } else {\n        elem.bind('click touchend', clickHandler);\n    }\n}\n\nngFileUpload.directive('ngfDrop', ['$parse', '$timeout', '$location', function ($parse, $timeout, $location) {\n    return {\n        restrict: 'AEC',\n        require: '?ngModel',\n        link: function (scope, elem, attr, ngModel) {\n            linkDrop(scope, elem, attr, ngModel, $parse, $timeout, $location);\n        }\n    }\n}]);\n\nngFileUpload.directive('ngfNoFileDrop', function () {\n    return function (scope, elem) {\n        if (dropAvailable()) elem.css('display', 'none')\n    }\n});\n\nngFileUpload.directive('ngfDropAvailable', ['$parse', '$timeout', function ($parse, $timeout) {\n    return function (scope, elem, attr) {\n        if (dropAvailable()) {\n            var fn = $parse(attr.ngfDropAvailable);\n            $timeout(function () {\n                fn(scope);\n                if (fn.assign) {\n                    fn.assign(scope, true);                \t\n                }\n            });\n        }\n    }\n}]);\n\nfunction linkDrop(scope, elem, attr, ngModel, $parse, $timeout, $location) {\n    var available = dropAvailable();\n    if (attr.dropAvailable) {\n        $timeout(function () {\n        \tscope[attr.dropAvailable] ? scope[attr.dropAvailable].value = available : scope[attr.dropAvailable] = available;\n        });\n    }\n    if (!available) {\n        if ($parse(attr.ngfHideOnDropNotAvailable)(scope) == true) {\n            elem.css('display', 'none');\n        }\n        return;\n    }\n    var leaveTimeout = null;\n    var stopPropagation = $parse(attr.ngfStopPropagation);\n    var dragOverDelay = 1;\n    var accept = $parse(attr.ngfAccept);\n    var disabled = $parse(attr.ngfDisabled);\n    var actualDragOverClass;\n\n    elem[0].addEventListener('dragover', function (evt) {\n        if (disabled(scope)) return;\n        evt.preventDefault();\n        if (stopPropagation(scope)) evt.stopPropagation();\n        // handling dragover events from the Chrome download bar\n        if (navigator.userAgent.indexOf(\"Chrome\") > -1) {\n            var b = evt.dataTransfer.effectAllowed;\n            evt.dataTransfer.dropEffect = ('move' === b || 'linkMove' === b) ? 'move' : 'copy';\n        }\n        $timeout.cancel(leaveTimeout);\n        if (!scope.actualDragOverClass) {\n            actualDragOverClass = calculateDragOverClass(scope, attr, evt);\n        }\n        elem.addClass(actualDragOverClass);\n    }, false);\n    elem[0].addEventListener('dragenter', function (evt) {\n        if (disabled(scope)) return;\n        evt.preventDefault();\n        if (stopPropagation(scope)) evt.stopPropagation();\n    }, false);\n    elem[0].addEventListener('dragleave', function () {\n        if (disabled(scope)) return;\n        leaveTimeout = $timeout(function () {\n            elem.removeClass(actualDragOverClass);\n            actualDragOverClass = null;\n        }, dragOverDelay || 1);\n    }, false);\n    elem[0].addEventListener('drop', function (evt) {\n        if (disabled(scope)) return;\n        evt.preventDefault();\n        if (stopPropagation(scope)) evt.stopPropagation();\n        elem.removeClass(actualDragOverClass);\n        actualDragOverClass = null;\n        extractFiles(evt, function (files, rejFiles) {\n            updateModel($parse, $timeout, scope, ngModel, attr,\n                attr.ngfChange || (attr.ngfDrop && attr.ngfDrop.indexOf('(') > 0), files, rejFiles, evt)\n        }, $parse(attr.ngfAllowDir)(scope) != false, attr.multiple || $parse(attr.ngfMultiple)(scope));\n    }, false);\n\n    function calculateDragOverClass(scope, attr, evt) {\n        var accepted = true;\n        var items = evt.dataTransfer.items;\n        if (items != null) {\n            for (var i = 0; i < items.length && accepted; i++) {\n                accepted = accepted\n                    && (items[i].kind == 'file' || items[i].kind == '')\n                    && validate(scope, $parse, attr, items[i], evt);\n            }\n        }\n        var clazz = $parse(attr.ngfDragOverClass)(scope, {$event: evt});\n        if (clazz) {\n            if (clazz.delay) dragOverDelay = clazz.delay;\n            if (clazz.accept) clazz = accepted ? clazz.accept : clazz.reject;\n        }\n        return clazz || attr.ngfDragOverClass || 'dragover';\n    }\n\n    function extractFiles(evt, callback, allowDir, multiple) {\n        var files = [], rejFiles = [], items = evt.dataTransfer.items, processing = 0;\n\n        function addFile(file) {\n            if (validate(scope, $parse, attr, file, evt)) {\n                files.push(file);\n            } else {\n                rejFiles.push(file);\n            }\n        }\n\n        if (items && items.length > 0 && $location.protocol() != 'file') {\n            for (var i = 0; i < items.length; i++) {\n                if (items[i].webkitGetAsEntry && items[i].webkitGetAsEntry() && items[i].webkitGetAsEntry().isDirectory) {\n                    var entry = items[i].webkitGetAsEntry();\n                    if (entry.isDirectory && !allowDir) {\n                        continue;\n                    }\n                    if (entry != null) {\n                        traverseFileTree(files, entry);\n                    }\n                } else {\n                    var f = items[i].getAsFile();\n                    if (f != null) addFile(f);\n                }\n                if (!multiple && files.length > 0) break;\n            }\n        } else {\n            var fileList = evt.dataTransfer.files;\n            if (fileList != null) {\n                for (var i = 0; i < fileList.length; i++) {\n                    addFile(fileList.item(i));\n                    if (!multiple && files.length > 0) break;\n                }\n            }\n        }\n        var delays = 0;\n        (function waitForProcess(delay) {\n            $timeout(function () {\n                if (!processing) {\n                    if (!multiple && files.length > 1) {\n                        i = 0;\n                        while (files[i].type == 'directory') i++;\n                        files = [files[i]];\n                    }\n                    callback(files, rejFiles);\n                } else {\n                    if (delays++ * 10 < 20 * 1000) {\n                        waitForProcess(10);\n                    }\n                }\n            }, delay || 0)\n        })();\n\n        function traverseFileTree(files, entry, path) {\n            if (entry != null) {\n                if (entry.isDirectory) {\n                    var filePath = (path || '') + entry.name;\n                    addFile({name: entry.name, type: 'directory', path: filePath});\n                    var dirReader = entry.createReader();\n                    var entries = [];\n                    processing++;\n                    var readEntries = function () {\n                        dirReader.readEntries(function (results) {\n                            try {\n                                if (!results.length) {\n                                    for (var i = 0; i < entries.length; i++) {\n                                        traverseFileTree(files, entries[i], (path ? path : '') + entry.name + '/');\n                                    }\n                                    processing--;\n                                } else {\n                                    entries = entries.concat(Array.prototype.slice.call(results || [], 0));\n                                    readEntries();\n                                }\n                            } catch (e) {\n                                processing--;\n                                console.error(e);\n                            }\n                        }, function () {\n                            processing--;\n                        });\n                    };\n                    readEntries();\n                } else {\n                    processing++;\n                    entry.file(function (file) {\n                        try {\n                            processing--;\n                            file.path = (path ? path : '') + file.name;\n                            addFile(file);\n                        } catch (e) {\n                            processing--;\n                            console.error(e);\n                        }\n                    }, function () {\n                        processing--;\n                    });\n                }\n            }\n        }\n    }\n}\n\nngFileUpload.directive('ngfSrc', ['$parse', '$timeout', function ($parse, $timeout) {\n\treturn {\n\t\trestrict: 'AE',\n\t\tlink: function (scope, elem, attr, file) {\n\t\t\tif (window.FileReader) {\n\t\t\t\tscope.$watch(attr.ngfSrc, function(file) {\n\t\t\t\t\tif (file) {\n\t\t\t\t\t\t$timeout(function() {\n\t\t\t\t\t\t\tvar fileReader = new FileReader();\n\t\t\t\t\t\t\tfileReader.readAsDataURL(file);\n\t\t\t\t\t\t\tfileReader.onload = function(e) {\n\t\t\t\t\t\t\t\t$timeout(function() {\n\t\t\t\t\t\t\t\t\telem.attr('src', e.target.result);\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t});\n\t\t\t\t\t} else {\n\t\t\t\t\t\telem.attr('src', '');\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n}]);\n\nfunction dropAvailable() {\n    var div = document.createElement('div');\n    return ('draggable' in div) && ('ondrop' in div);\n}\n\nfunction updateModel($parse, $timeout, scope, ngModel, attr, fileChange, files, rejFiles, evt, noDelay) {\n    function update() {\n        if (ngModel) {\n            $parse(attr.ngModel).assign(scope, files);\n            $timeout(function () {\n                ngModel && ngModel.$setViewValue(files != null && files.length == 0 ? null : files);\n            });\n        }\n        if (attr.ngModelRejected) {\n            $parse(attr.ngModelRejected).assign(scope, rejFiles);\n        }\n        if (fileChange) {\n            $parse(fileChange)(scope, {\n                $files: files,\n                $rejectedFiles: rejFiles,\n                $event: evt\n            });\n\n        }\n    }\n    if (noDelay) {\n        update();\n    } else {\n        $timeout(function () {\n            update();\n        });\n    }\n}\n\nfunction validate(scope, $parse, attr, file, evt) {\n    var accept = $parse(attr.ngfAccept);\n    var fileSizeMax = $parse(attr.ngfMaxSize)(scope) || 9007199254740991;\n    var fileSizeMin = $parse(attr.ngfMinSize)(scope) || -1;\n    var val = accept(scope, {$file: file, $event: evt}), match = false;\n    if (val != null && angular.isString(val)) {\n        var regexp = new RegExp(globStringToRegex(val), 'gi');\n        match = (file.type != null && file.type.match(regexp)) ||\n        \t\t(file.name != null && file.name.match(regexp));\n    }\n    return (val == null || match) && (file.size == null || (file.size < fileSizeMax && file.size > fileSizeMin));\n}\n\nfunction globStringToRegex(str) {\n    if (str.length > 2 && str[0] === '/' && str[str.length - 1] === '/') {\n        return str.substring(1, str.length - 1);\n    }\n    var split = str.split(','), result = '';\n    if (split.length > 1) {\n        for (var i = 0; i < split.length; i++) {\n            result += '(' + globStringToRegex(split[i]) + ')';\n            if (i < split.length - 1) {\n                result += '|'\n            }\n        }\n    } else {\n        if (str.indexOf('.') == 0) {\n            str = '*' + str;\n        }\n        result = '^' + str.replace(new RegExp('[.\\\\\\\\+*?\\\\[\\\\^\\\\]$(){}=!<>|:\\\\' + '-]', 'g'), '\\\\$&') + '$';\n        result = result.replace(/\\\\\\*/g, '.*').replace(/\\\\\\?/g, '.');\n    }\n    return result;\n}\n\n})();\n\n/**!\n * AngularJS file upload/drop directive and service with progress and abort\n * FileAPI Flash shim for old browsers not supporting FormData \n * @author  Danial  <danial.farid@gmail.com>\n * @version 4.1.0\n */\n\n(function() {\n\nvar hasFlash = function() {\n\ttry {\n\t  var fo = new ActiveXObject('ShockwaveFlash.ShockwaveFlash');\n\t  if (fo) return true;\n\t} catch(e) {\n\t  if (navigator.mimeTypes['application/x-shockwave-flash'] != undefined) return true;\n\t}\n\treturn false;\n}\n\nfunction patchXHR(fnName, newFn) {\n\twindow.XMLHttpRequest.prototype[fnName] = newFn(window.XMLHttpRequest.prototype[fnName]);\n};\n\nif ((window.XMLHttpRequest && !window.FormData) || (window.FileAPI && FileAPI.forceLoad)) {\n\tvar initializeUploadListener = function(xhr) {\n\t\tif (!xhr.__listeners) {\n\t\t\tif (!xhr.upload) xhr.upload = {};\n\t\t\txhr.__listeners = [];\n\t\t\tvar origAddEventListener = xhr.upload.addEventListener;\n\t\t\txhr.upload.addEventListener = function(t, fn, b) {\n\t\t\t\txhr.__listeners[t] = fn;\n\t\t\t\torigAddEventListener && origAddEventListener.apply(this, arguments);\n\t\t\t};\n\t\t}\n\t}\n\t\n\tpatchXHR('open', function(orig) {\n\t\treturn function(m, url, b) {\n\t\t\tinitializeUploadListener(this);\n\t\t\tthis.__url = url;\n\t\t\ttry {\n\t\t\t\torig.apply(this, [m, url, b]);\n\t\t\t} catch (e) {\n\t\t\t\tif (e.message.indexOf('Access is denied') > -1) {\n\t\t\t\t\tthis.__origError = e;\n\t\t\t\t\torig.apply(this, [m, '_fix_for_ie_crossdomain__', b]);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t});\n\n\tpatchXHR('getResponseHeader', function(orig) {\n\t\treturn function(h) {\n\t\t\treturn this.__fileApiXHR && this.__fileApiXHR.getResponseHeader ? this.__fileApiXHR.getResponseHeader(h) : (orig == null ? null : orig.apply(this, [h]));\n\t\t};\n\t});\n\n\tpatchXHR('getAllResponseHeaders', function(orig) {\n\t\treturn function() {\n\t\t\treturn this.__fileApiXHR && this.__fileApiXHR.getAllResponseHeaders ? this.__fileApiXHR.getAllResponseHeaders() : (orig == null ? null : orig.apply(this));\n\t\t}\n\t});\n\n\tpatchXHR('abort', function(orig) {\n\t\treturn function() {\n\t\t\treturn this.__fileApiXHR && this.__fileApiXHR.abort ? this.__fileApiXHR.abort() : (orig == null ? null : orig.apply(this));\n\t\t}\n\t});\n\n\tpatchXHR('setRequestHeader', function(orig) {\n\t\treturn function(header, value) {\n\t\t\tif (header === '__setXHR_') {\n\t\t\t\tinitializeUploadListener(this);\n\t\t\t\tvar val = value(this);\n\t\t\t\t// fix for angular < 1.2.0\n\t\t\t\tif (val instanceof Function) {\n\t\t\t\t\tval(this);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tthis.__requestHeaders = this.__requestHeaders || {};\n\t\t\t\tthis.__requestHeaders[header] = value;\n\t\t\t\torig.apply(this, arguments);\n\t\t\t}\n\t\t}\n\t});\n\t\n\tfunction redefineProp(xhr, prop, fn) {\n\t\ttry {\n\t\t\tObject.defineProperty(xhr, prop, {get: fn});\n\t\t} catch (e) {/*ignore*/}\n\t}\n\n\tpatchXHR('send', function(orig) {\n\t\treturn function() {\n\t\t\tvar xhr = this;\n\t\t\tif (arguments[0] && arguments[0].__isFileAPIShim) {\n\t\t\t\tvar formData = arguments[0];\n\t\t\t\tvar config = {\n\t\t\t\t\turl: xhr.__url,\n\t\t\t\t\tjsonp: false, //removes the callback form param\n\t\t\t\t\tcache: true, //removes the ?fileapiXXX in the url\n\t\t\t\t\tcomplete: function(err, fileApiXHR) {\n\t\t\t\t\t\txhr.__completed = true;\n\t\t\t\t\t\tif (!err && xhr.__listeners['load']) \n\t\t\t\t\t\t\txhr.__listeners['load']({type: 'load', loaded: xhr.__loaded, total: xhr.__total, target: xhr, lengthComputable: true});\n\t\t\t\t\t\tif (!err && xhr.__listeners['loadend']) \n\t\t\t\t\t\t\txhr.__listeners['loadend']({type: 'loadend', loaded: xhr.__loaded, total: xhr.__total, target: xhr, lengthComputable: true});\n\t\t\t\t\t\tif (err === 'abort' && xhr.__listeners['abort']) \n\t\t\t\t\t\t\txhr.__listeners['abort']({type: 'abort', loaded: xhr.__loaded, total: xhr.__total, target: xhr, lengthComputable: true});\n\t\t\t\t\t\tif (fileApiXHR.status !== undefined) redefineProp(xhr, 'status', function() {return (fileApiXHR.status == 0 && err && err !== 'abort') ? 500 : fileApiXHR.status});\n\t\t\t\t\t\tif (fileApiXHR.statusText !== undefined) redefineProp(xhr, 'statusText', function() {return fileApiXHR.statusText});\n\t\t\t\t\t\tredefineProp(xhr, 'readyState', function() {return 4});\n\t\t\t\t\t\tif (fileApiXHR.response !== undefined) redefineProp(xhr, 'response', function() {return fileApiXHR.response});\n\t\t\t\t\t\tvar resp = fileApiXHR.responseText || (err && fileApiXHR.status == 0 && err !== 'abort' ? err : undefined);\n\t\t\t\t\t\tredefineProp(xhr, 'responseText', function() {return resp});\n\t\t\t\t\t\tredefineProp(xhr, 'response', function() {return resp});\n\t\t\t\t\t\tif (err) redefineProp(xhr, 'err', function() {return err});\n\t\t\t\t\t\txhr.__fileApiXHR = fileApiXHR;\n\t\t\t\t\t\tif (xhr.onreadystatechange) xhr.onreadystatechange();\n\t\t\t\t\t\tif (xhr.onload) xhr.onload();\n\t\t\t\t\t},\n\t\t\t\t\tfileprogress: function(e) {\n\t\t\t\t\t\te.target = xhr;\n\t\t\t\t\t\txhr.__listeners['progress'] && xhr.__listeners['progress'](e);\n\t\t\t\t\t\txhr.__total = e.total;\n\t\t\t\t\t\txhr.__loaded = e.loaded;\n\t\t\t\t\t\tif (e.total === e.loaded) {\n\t\t\t\t\t\t\t// fix flash issue that doesn't call complete if there is no response text from the server  \n\t\t\t\t\t\t\tvar _this = this\n\t\t\t\t\t\t\tsetTimeout(function() {\n\t\t\t\t\t\t\t\tif (!xhr.__completed) {\n\t\t\t\t\t\t\t\t\txhr.getAllResponseHeaders = function(){};\n\t\t\t\t\t\t\t\t\t_this.complete(null, {status: 204, statusText: 'No Content'});\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}, FileAPI.noContentTimeout || 10000);\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\theaders: xhr.__requestHeaders\n\t\t\t\t}\n\t\t\t\tconfig.data = {};\n\t\t\t\tconfig.files = {}\n\t\t\t\tfor (var i = 0; i < formData.data.length; i++) {\n\t\t\t\t\tvar item = formData.data[i];\n\t\t\t\t\tif (item.val != null && item.val.name != null && item.val.size != null && item.val.type != null) {\n\t\t\t\t\t\tconfig.files[item.key] = item.val;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tconfig.data[item.key] = item.val;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tsetTimeout(function() {\n\t\t\t\t\tif (!hasFlash()) {\n\t\t\t\t\t\tthrow 'Adode Flash Player need to be installed. To check ahead use \"FileAPI.hasFlash\"';\n\t\t\t\t\t}\n\t\t\t\t\txhr.__fileApiXHR = FileAPI.upload(config);\n\t\t\t\t}, 1);\n\t\t\t} else {\n\t\t\t\tif (this.__origError) {\n\t\t\t\t\tthrow this.__origError;\n\t\t\t\t}\n\t\t\t\torig.apply(xhr, arguments);\n\t\t\t}\n\t\t}\n\t});\n\twindow.XMLHttpRequest.__isFileAPIShim = true;\n\n\tfunction isInputTypeFile(elem) {\n\t\treturn elem[0].tagName.toLowerCase() === 'input' && elem.attr('type') && elem.attr('type').toLowerCase() === 'file';\n\t}\n\t\n\twindow.FormData = FormData = function() {\n\t\treturn {\n\t\t\tappend: function(key, val, name) {\n\t\t\t\tif (val.__isFileAPIBlobShim) {\n\t\t\t\t\tval = val.data[0];\n\t\t\t\t}\n\t\t\t\tthis.data.push({\n\t\t\t\t\tkey: key,\n\t\t\t\t\tval: val,\n\t\t\t\t\tname: name\n\t\t\t\t});\n\t\t\t},\n\t\t\tdata: [],\n\t\t\t__isFileAPIShim: true\n\t\t};\n\t};\n\n\twindow.Blob = Blob = function(b) {\n\t\treturn {\n\t\t\tdata: b,\n\t\t\t__isFileAPIBlobShim: true\n\t\t};\n\t};\n\n\t(function () {\n\t\t//load FileAPI\n\t\tif (!window.FileAPI) {\n\t\t\twindow.FileAPI = {};\n\t\t}\n\t\tif (FileAPI.forceLoad) {\n\t\t\tFileAPI.html5 = false;\n\t\t}\n\t\t\n\t\tif (!FileAPI.upload) {\n\t\t\tvar jsUrl, basePath, script = document.createElement('script'), allScripts = document.getElementsByTagName('script'), i, index, src;\n\t\t\tif (window.FileAPI.jsUrl) {\n\t\t\t\tjsUrl = window.FileAPI.jsUrl;\n\t\t\t} else if (window.FileAPI.jsPath) {\n\t\t\t\tbasePath = window.FileAPI.jsPath;\n\t\t\t} else {\n\t\t\t\tfor (i = 0; i < allScripts.length; i++) {\n\t\t\t\t\tsrc = allScripts[i].src;\n\t\t\t\t\tindex = src.search(/\\/ng\\-file\\-upload[\\-a-zA-z0-9\\.]*\\.js/)\n\t\t\t\t\tif (index > -1) {\n\t\t\t\t\t\tbasePath = src.substring(0, index + 1);\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\tif (FileAPI.staticPath == null) FileAPI.staticPath = basePath;\n\t\t\tscript.setAttribute('src', jsUrl || basePath + 'FileAPI.min.js');\n\t\t\tdocument.getElementsByTagName('head')[0].appendChild(script);\n\t\t\tFileAPI.hasFlash = hasFlash();\n\t\t}\n\t})();\n\t\n\tFileAPI.ngfFixIE = function(elem, createFileElemFn, bindAttr, changeFn, resetModel) {\n\t\tif (!hasFlash()) {\n\t\t\tthrow 'Adode Flash Player need to be installed. To check ahead use \"FileAPI.hasFlash\"';\n\t\t}\n\t\tvar makeFlashInput = function(evt) {\n\t\t\tif (elem.attr('disabled')) {\n\t\t\t\telem.__ngf_elem__.removeClass('js-fileapi-wrapper');\n\t\t\t} else {\n\t\t\t\tvar fileElem = elem.__ngf_elem__;\n\t\t\t\tif (!fileElem) {\n\t\t\t\t\tfileElem = elem.__ngf_elem__ = createFileElemFn();\n\t\t\t\t\tfileElem.addClass('js-fileapi-wrapper');\n\t\t\t\t\tif (!isInputTypeFile(elem)) {\n//\t\t\t\t\t\tif (fileElem.parent().css('position') === '' || fileElem.parent().css('position') === 'static') {\n//\t\t\t\t\t\t\tfileElem.parent().css('position', 'relative');\n//\t\t\t\t\t\t}\n//\t\t\t\t\t\telem.parent()[0].insertBefore(fileElem[0], elem[0]);\n//\t\t\t\t\t\telem.css('overflow', 'hidden');\n\t\t\t\t\t}\n\t\t\t\t\tsetTimeout(function() {\n\t\t\t\t\t\tfileElem.bind('mouseenter', makeFlashInput);\n\t\t\t\t\t}, 10);\n\t\t\t\t\tfileElem.bind('change', function(evt) {\n\t\t\t\t    \tfileApiChangeFn.apply(this, [evt]);\n\t\t\t\t\t\tchangeFn.apply(this, [evt]);\n//\t\t\t\t\t\talert('change' +  evt);\n\t\t\t\t\t});\n\t\t\t\t} else {\n\t\t\t\t\tbindAttr(elem.__ngf_elem__);\n\t\t\t\t}\n\t\t\t\tif (!isInputTypeFile(elem)) {\n\t\t\t\t\tfileElem.css('position', 'absolute')\n\t\t\t\t\t\t\t.css('top', getOffset(elem[0]).top + 'px').css('left', getOffset(elem[0]).left + 'px')\n\t\t\t\t\t\t\t.css('width', elem[0].offsetWidth + 'px').css('height', elem[0].offsetHeight + 'px')\n\t\t\t\t\t\t\t.css('filter', 'alpha(opacity=0)').css('display', elem.css('display'))\n\t\t\t\t\t\t\t.css('overflow', 'hidden').css('z-index', '900000');\n\t\t\t\t}\n\t\t\t}\n\t\t\tfunction getOffset(obj) {\n\t\t\t    var left, top;\n\t\t\t    left = top = 0;\n\t\t\t    if (obj.offsetParent) {\n\t\t\t        do {\n\t\t\t            left += obj.offsetLeft;\n\t\t\t            top  += obj.offsetTop;\n\t\t\t        } while (obj = obj.offsetParent);\n\t\t\t    }\n\t\t\t    return {\n\t\t\t        left : left,\n\t\t\t        top : top\n\t\t\t    };\n\t\t\t};\n\t\t};\n\n\t\telem.bind('mouseenter', makeFlashInput);\n\n\t\tvar fileApiChangeFn = function(evt) {\n\t\t\tvar files = FileAPI.getFiles(evt);\n\t\t\t//just a double check for #233\n\t\t\tfor (var i = 0; i < files.length; i++) {\n\t\t\t\tif (files[i].size === undefined) files[i].size = 0;\n\t\t\t\tif (files[i].name === undefined) files[i].name = 'file';\n\t\t\t\tif (files[i].type === undefined) files[i].type = 'undefined';\n\t\t\t}\n\t\t\tif (!evt.target) {\n\t\t\t\tevt.target = {};\n\t\t\t}\n\t\t\tevt.target.files = files;\n\t\t\t// if evt.target.files is not writable use helper field\n\t\t\tif (evt.target.files != files) {\n\t\t\t\tevt.__files_ = files;\n\t\t\t}\n\t\t\t(evt.__files_ || evt.target.files).item = function(i) {\n\t\t\t\treturn (evt.__files_ || evt.target.files)[i] || null;\n\t\t\t};\n\t\t};\n\t};\n\n\tFileAPI.disableFileInput = function(elem, disable) {\n\t\tif (disable) {\n\t\t\telem.removeClass('js-fileapi-wrapper')\n\t\t} else {\n\t\t\telem.addClass('js-fileapi-wrapper');\n\t\t}\n\t};\n}\n\n\nif (!window.FileReader) {\n\twindow.FileReader = function() {\n\t\tvar _this = this, loadStarted = false;\n\t\tthis.listeners = {};\n\t\tthis.addEventListener = function(type, fn) {\n\t\t\t_this.listeners[type] = _this.listeners[type] || [];\n\t\t\t_this.listeners[type].push(fn);\n\t\t};\n\t\tthis.removeEventListener = function(type, fn) {\n\t\t\t_this.listeners[type] && _this.listeners[type].splice(_this.listeners[type].indexOf(fn), 1);\n\t\t};\n\t\tthis.dispatchEvent = function(evt) {\n\t\t\tvar list = _this.listeners[evt.type];\n\t\t\tif (list) {\n\t\t\t\tfor (var i = 0; i < list.length; i++) {\n\t\t\t\t\tlist[i].call(_this, evt);\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t\tthis.onabort = this.onerror = this.onload = this.onloadstart = this.onloadend = this.onprogress = null;\n\n\t\tvar constructEvent = function(type, evt) {\n\t\t\tvar e = {type: type, target: _this, loaded: evt.loaded, total: evt.total, error: evt.error};\n\t\t\tif (evt.result != null) e.target.result = evt.result;\n\t\t\treturn e;\n\t\t};\n\t\tvar listener = function(evt) {\n\t\t\tif (!loadStarted) {\n\t\t\t\tloadStarted = true;\n\t\t\t\t_this.onloadstart && _this.onloadstart(constructEvent('loadstart', evt));\n\t\t\t}\n\t\t\tif (evt.type === 'load') {\n\t\t\t\t_this.onloadend && _this.onloadend(constructEvent('loadend', evt));\n\t\t\t\tvar e = constructEvent('load', evt);\n\t\t\t\t_this.onload && _this.onload(e);\n\t\t\t\t_this.dispatchEvent(e);\n\t\t\t} else if (evt.type === 'progress') {\n\t\t\t\tvar e = constructEvent('progress', evt);\n\t\t\t\t_this.onprogress && _this.onprogress(e);\n\t\t\t\t_this.dispatchEvent(e);\n\t\t\t} else {\n\t\t\t\tvar e = constructEvent('error', evt);\n\t\t\t\t_this.onerror && _this.onerror(e);\n\t\t\t\t_this.dispatchEvent(e);\n\t\t\t}\n\t\t};\n\t\tthis.readAsArrayBuffer = function(file) {\n\t\t\tFileAPI.readAsBinaryString(file, listener);\n\t\t}\n\t\tthis.readAsBinaryString = function(file) {\n\t\t\tFileAPI.readAsBinaryString(file, listener);\n\t\t}\n\t\tthis.readAsDataURL = function(file) {\n\t\t\tFileAPI.readAsDataURL(file, listener);\n\t\t}\n\t\tthis.readAsText = function(file) {\n\t\t\tFileAPI.readAsText(file, listener);\n\t\t}\n\t}\n}\n})();\n"
  },
  {
    "path": "flowable-ui-web/modeler/libs/ng-file-upload/ng-file-upload-shim.js",
    "content": "/**!\n * AngularJS file upload/drop directive and service with progress and abort\n * FileAPI Flash shim for old browsers not supporting FormData \n * @author  Danial  <danial.farid@gmail.com>\n * @version 4.1.0\n */\n\n(function() {\n\nvar hasFlash = function() {\n\ttry {\n\t  var fo = new ActiveXObject('ShockwaveFlash.ShockwaveFlash');\n\t  if (fo) return true;\n\t} catch(e) {\n\t  if (navigator.mimeTypes['application/x-shockwave-flash'] != undefined) return true;\n\t}\n\treturn false;\n}\n\nfunction patchXHR(fnName, newFn) {\n\twindow.XMLHttpRequest.prototype[fnName] = newFn(window.XMLHttpRequest.prototype[fnName]);\n};\n\nif ((window.XMLHttpRequest && !window.FormData) || (window.FileAPI && FileAPI.forceLoad)) {\n\tvar initializeUploadListener = function(xhr) {\n\t\tif (!xhr.__listeners) {\n\t\t\tif (!xhr.upload) xhr.upload = {};\n\t\t\txhr.__listeners = [];\n\t\t\tvar origAddEventListener = xhr.upload.addEventListener;\n\t\t\txhr.upload.addEventListener = function(t, fn, b) {\n\t\t\t\txhr.__listeners[t] = fn;\n\t\t\t\torigAddEventListener && origAddEventListener.apply(this, arguments);\n\t\t\t};\n\t\t}\n\t}\n\t\n\tpatchXHR('open', function(orig) {\n\t\treturn function(m, url, b) {\n\t\t\tinitializeUploadListener(this);\n\t\t\tthis.__url = url;\n\t\t\ttry {\n\t\t\t\torig.apply(this, [m, url, b]);\n\t\t\t} catch (e) {\n\t\t\t\tif (e.message.indexOf('Access is denied') > -1) {\n\t\t\t\t\tthis.__origError = e;\n\t\t\t\t\torig.apply(this, [m, '_fix_for_ie_crossdomain__', b]);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t});\n\n\tpatchXHR('getResponseHeader', function(orig) {\n\t\treturn function(h) {\n\t\t\treturn this.__fileApiXHR && this.__fileApiXHR.getResponseHeader ? this.__fileApiXHR.getResponseHeader(h) : (orig == null ? null : orig.apply(this, [h]));\n\t\t};\n\t});\n\n\tpatchXHR('getAllResponseHeaders', function(orig) {\n\t\treturn function() {\n\t\t\treturn this.__fileApiXHR && this.__fileApiXHR.getAllResponseHeaders ? this.__fileApiXHR.getAllResponseHeaders() : (orig == null ? null : orig.apply(this));\n\t\t}\n\t});\n\n\tpatchXHR('abort', function(orig) {\n\t\treturn function() {\n\t\t\treturn this.__fileApiXHR && this.__fileApiXHR.abort ? this.__fileApiXHR.abort() : (orig == null ? null : orig.apply(this));\n\t\t}\n\t});\n\n\tpatchXHR('setRequestHeader', function(orig) {\n\t\treturn function(header, value) {\n\t\t\tif (header === '__setXHR_') {\n\t\t\t\tinitializeUploadListener(this);\n\t\t\t\tvar val = value(this);\n\t\t\t\t// fix for angular < 1.2.0\n\t\t\t\tif (val instanceof Function) {\n\t\t\t\t\tval(this);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tthis.__requestHeaders = this.__requestHeaders || {};\n\t\t\t\tthis.__requestHeaders[header] = value;\n\t\t\t\torig.apply(this, arguments);\n\t\t\t}\n\t\t}\n\t});\n\t\n\tfunction redefineProp(xhr, prop, fn) {\n\t\ttry {\n\t\t\tObject.defineProperty(xhr, prop, {get: fn});\n\t\t} catch (e) {/*ignore*/}\n\t}\n\n\tpatchXHR('send', function(orig) {\n\t\treturn function() {\n\t\t\tvar xhr = this;\n\t\t\tif (arguments[0] && arguments[0].__isFileAPIShim) {\n\t\t\t\tvar formData = arguments[0];\n\t\t\t\tvar config = {\n\t\t\t\t\turl: xhr.__url,\n\t\t\t\t\tjsonp: false, //removes the callback form param\n\t\t\t\t\tcache: true, //removes the ?fileapiXXX in the url\n\t\t\t\t\tcomplete: function(err, fileApiXHR) {\n\t\t\t\t\t\txhr.__completed = true;\n\t\t\t\t\t\tif (!err && xhr.__listeners['load']) \n\t\t\t\t\t\t\txhr.__listeners['load']({type: 'load', loaded: xhr.__loaded, total: xhr.__total, target: xhr, lengthComputable: true});\n\t\t\t\t\t\tif (!err && xhr.__listeners['loadend']) \n\t\t\t\t\t\t\txhr.__listeners['loadend']({type: 'loadend', loaded: xhr.__loaded, total: xhr.__total, target: xhr, lengthComputable: true});\n\t\t\t\t\t\tif (err === 'abort' && xhr.__listeners['abort']) \n\t\t\t\t\t\t\txhr.__listeners['abort']({type: 'abort', loaded: xhr.__loaded, total: xhr.__total, target: xhr, lengthComputable: true});\n\t\t\t\t\t\tif (fileApiXHR.status !== undefined) redefineProp(xhr, 'status', function() {return (fileApiXHR.status == 0 && err && err !== 'abort') ? 500 : fileApiXHR.status});\n\t\t\t\t\t\tif (fileApiXHR.statusText !== undefined) redefineProp(xhr, 'statusText', function() {return fileApiXHR.statusText});\n\t\t\t\t\t\tredefineProp(xhr, 'readyState', function() {return 4});\n\t\t\t\t\t\tif (fileApiXHR.response !== undefined) redefineProp(xhr, 'response', function() {return fileApiXHR.response});\n\t\t\t\t\t\tvar resp = fileApiXHR.responseText || (err && fileApiXHR.status == 0 && err !== 'abort' ? err : undefined);\n\t\t\t\t\t\tredefineProp(xhr, 'responseText', function() {return resp});\n\t\t\t\t\t\tredefineProp(xhr, 'response', function() {return resp});\n\t\t\t\t\t\tif (err) redefineProp(xhr, 'err', function() {return err});\n\t\t\t\t\t\txhr.__fileApiXHR = fileApiXHR;\n\t\t\t\t\t\tif (xhr.onreadystatechange) xhr.onreadystatechange();\n\t\t\t\t\t\tif (xhr.onload) xhr.onload();\n\t\t\t\t\t},\n\t\t\t\t\tfileprogress: function(e) {\n\t\t\t\t\t\te.target = xhr;\n\t\t\t\t\t\txhr.__listeners['progress'] && xhr.__listeners['progress'](e);\n\t\t\t\t\t\txhr.__total = e.total;\n\t\t\t\t\t\txhr.__loaded = e.loaded;\n\t\t\t\t\t\tif (e.total === e.loaded) {\n\t\t\t\t\t\t\t// fix flash issue that doesn't call complete if there is no response text from the server  \n\t\t\t\t\t\t\tvar _this = this\n\t\t\t\t\t\t\tsetTimeout(function() {\n\t\t\t\t\t\t\t\tif (!xhr.__completed) {\n\t\t\t\t\t\t\t\t\txhr.getAllResponseHeaders = function(){};\n\t\t\t\t\t\t\t\t\t_this.complete(null, {status: 204, statusText: 'No Content'});\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}, FileAPI.noContentTimeout || 10000);\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\theaders: xhr.__requestHeaders\n\t\t\t\t}\n\t\t\t\tconfig.data = {};\n\t\t\t\tconfig.files = {}\n\t\t\t\tfor (var i = 0; i < formData.data.length; i++) {\n\t\t\t\t\tvar item = formData.data[i];\n\t\t\t\t\tif (item.val != null && item.val.name != null && item.val.size != null && item.val.type != null) {\n\t\t\t\t\t\tconfig.files[item.key] = item.val;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tconfig.data[item.key] = item.val;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tsetTimeout(function() {\n\t\t\t\t\tif (!hasFlash()) {\n\t\t\t\t\t\tthrow 'Adode Flash Player need to be installed. To check ahead use \"FileAPI.hasFlash\"';\n\t\t\t\t\t}\n\t\t\t\t\txhr.__fileApiXHR = FileAPI.upload(config);\n\t\t\t\t}, 1);\n\t\t\t} else {\n\t\t\t\tif (this.__origError) {\n\t\t\t\t\tthrow this.__origError;\n\t\t\t\t}\n\t\t\t\torig.apply(xhr, arguments);\n\t\t\t}\n\t\t}\n\t});\n\twindow.XMLHttpRequest.__isFileAPIShim = true;\n\n\tfunction isInputTypeFile(elem) {\n\t\treturn elem[0].tagName.toLowerCase() === 'input' && elem.attr('type') && elem.attr('type').toLowerCase() === 'file';\n\t}\n\t\n\twindow.FormData = FormData = function() {\n\t\treturn {\n\t\t\tappend: function(key, val, name) {\n\t\t\t\tif (val.__isFileAPIBlobShim) {\n\t\t\t\t\tval = val.data[0];\n\t\t\t\t}\n\t\t\t\tthis.data.push({\n\t\t\t\t\tkey: key,\n\t\t\t\t\tval: val,\n\t\t\t\t\tname: name\n\t\t\t\t});\n\t\t\t},\n\t\t\tdata: [],\n\t\t\t__isFileAPIShim: true\n\t\t};\n\t};\n\n\twindow.Blob = Blob = function(b) {\n\t\treturn {\n\t\t\tdata: b,\n\t\t\t__isFileAPIBlobShim: true\n\t\t};\n\t};\n\n\t(function () {\n\t\t//load FileAPI\n\t\tif (!window.FileAPI) {\n\t\t\twindow.FileAPI = {};\n\t\t}\n\t\tif (FileAPI.forceLoad) {\n\t\t\tFileAPI.html5 = false;\n\t\t}\n\t\t\n\t\tif (!FileAPI.upload) {\n\t\t\tvar jsUrl, basePath, script = document.createElement('script'), allScripts = document.getElementsByTagName('script'), i, index, src;\n\t\t\tif (window.FileAPI.jsUrl) {\n\t\t\t\tjsUrl = window.FileAPI.jsUrl;\n\t\t\t} else if (window.FileAPI.jsPath) {\n\t\t\t\tbasePath = window.FileAPI.jsPath;\n\t\t\t} else {\n\t\t\t\tfor (i = 0; i < allScripts.length; i++) {\n\t\t\t\t\tsrc = allScripts[i].src;\n\t\t\t\t\tindex = src.search(/\\/ng\\-file\\-upload[\\-a-zA-z0-9\\.]*\\.js/)\n\t\t\t\t\tif (index > -1) {\n\t\t\t\t\t\tbasePath = src.substring(0, index + 1);\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\tif (FileAPI.staticPath == null) FileAPI.staticPath = basePath;\n\t\t\tscript.setAttribute('src', jsUrl || basePath + 'FileAPI.min.js');\n\t\t\tdocument.getElementsByTagName('head')[0].appendChild(script);\n\t\t\tFileAPI.hasFlash = hasFlash();\n\t\t}\n\t})();\n\t\n\tFileAPI.ngfFixIE = function(elem, createFileElemFn, bindAttr, changeFn, resetModel) {\n\t\tif (!hasFlash()) {\n\t\t\tthrow 'Adode Flash Player need to be installed. To check ahead use \"FileAPI.hasFlash\"';\n\t\t}\n\t\tvar makeFlashInput = function(evt) {\n\t\t\tif (elem.attr('disabled')) {\n\t\t\t\telem.__ngf_elem__.removeClass('js-fileapi-wrapper');\n\t\t\t} else {\n\t\t\t\tvar fileElem = elem.__ngf_elem__;\n\t\t\t\tif (!fileElem) {\n\t\t\t\t\tfileElem = elem.__ngf_elem__ = createFileElemFn();\n\t\t\t\t\tfileElem.addClass('js-fileapi-wrapper');\n\t\t\t\t\tif (!isInputTypeFile(elem)) {\n//\t\t\t\t\t\tif (fileElem.parent().css('position') === '' || fileElem.parent().css('position') === 'static') {\n//\t\t\t\t\t\t\tfileElem.parent().css('position', 'relative');\n//\t\t\t\t\t\t}\n//\t\t\t\t\t\telem.parent()[0].insertBefore(fileElem[0], elem[0]);\n//\t\t\t\t\t\telem.css('overflow', 'hidden');\n\t\t\t\t\t}\n\t\t\t\t\tsetTimeout(function() {\n\t\t\t\t\t\tfileElem.bind('mouseenter', makeFlashInput);\n\t\t\t\t\t}, 10);\n\t\t\t\t\tfileElem.bind('change', function(evt) {\n\t\t\t\t    \tfileApiChangeFn.apply(this, [evt]);\n\t\t\t\t\t\tchangeFn.apply(this, [evt]);\n//\t\t\t\t\t\talert('change' +  evt);\n\t\t\t\t\t});\n\t\t\t\t} else {\n\t\t\t\t\tbindAttr(elem.__ngf_elem__);\n\t\t\t\t}\n\t\t\t\tif (!isInputTypeFile(elem)) {\n\t\t\t\t\tfileElem.css('position', 'absolute')\n\t\t\t\t\t\t\t.css('top', getOffset(elem[0]).top + 'px').css('left', getOffset(elem[0]).left + 'px')\n\t\t\t\t\t\t\t.css('width', elem[0].offsetWidth + 'px').css('height', elem[0].offsetHeight + 'px')\n\t\t\t\t\t\t\t.css('filter', 'alpha(opacity=0)').css('display', elem.css('display'))\n\t\t\t\t\t\t\t.css('overflow', 'hidden').css('z-index', '900000');\n\t\t\t\t}\n\t\t\t}\n\t\t\tfunction getOffset(obj) {\n\t\t\t    var left, top;\n\t\t\t    left = top = 0;\n\t\t\t    if (obj.offsetParent) {\n\t\t\t        do {\n\t\t\t            left += obj.offsetLeft;\n\t\t\t            top  += obj.offsetTop;\n\t\t\t        } while (obj = obj.offsetParent);\n\t\t\t    }\n\t\t\t    return {\n\t\t\t        left : left,\n\t\t\t        top : top\n\t\t\t    };\n\t\t\t};\n\t\t};\n\n\t\telem.bind('mouseenter', makeFlashInput);\n\n\t\tvar fileApiChangeFn = function(evt) {\n\t\t\tvar files = FileAPI.getFiles(evt);\n\t\t\t//just a double check for #233\n\t\t\tfor (var i = 0; i < files.length; i++) {\n\t\t\t\tif (files[i].size === undefined) files[i].size = 0;\n\t\t\t\tif (files[i].name === undefined) files[i].name = 'file';\n\t\t\t\tif (files[i].type === undefined) files[i].type = 'undefined';\n\t\t\t}\n\t\t\tif (!evt.target) {\n\t\t\t\tevt.target = {};\n\t\t\t}\n\t\t\tevt.target.files = files;\n\t\t\t// if evt.target.files is not writable use helper field\n\t\t\tif (evt.target.files != files) {\n\t\t\t\tevt.__files_ = files;\n\t\t\t}\n\t\t\t(evt.__files_ || evt.target.files).item = function(i) {\n\t\t\t\treturn (evt.__files_ || evt.target.files)[i] || null;\n\t\t\t};\n\t\t};\n\t};\n\n\tFileAPI.disableFileInput = function(elem, disable) {\n\t\tif (disable) {\n\t\t\telem.removeClass('js-fileapi-wrapper')\n\t\t} else {\n\t\t\telem.addClass('js-fileapi-wrapper');\n\t\t}\n\t};\n}\n\n\nif (!window.FileReader) {\n\twindow.FileReader = function() {\n\t\tvar _this = this, loadStarted = false;\n\t\tthis.listeners = {};\n\t\tthis.addEventListener = function(type, fn) {\n\t\t\t_this.listeners[type] = _this.listeners[type] || [];\n\t\t\t_this.listeners[type].push(fn);\n\t\t};\n\t\tthis.removeEventListener = function(type, fn) {\n\t\t\t_this.listeners[type] && _this.listeners[type].splice(_this.listeners[type].indexOf(fn), 1);\n\t\t};\n\t\tthis.dispatchEvent = function(evt) {\n\t\t\tvar list = _this.listeners[evt.type];\n\t\t\tif (list) {\n\t\t\t\tfor (var i = 0; i < list.length; i++) {\n\t\t\t\t\tlist[i].call(_this, evt);\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t\tthis.onabort = this.onerror = this.onload = this.onloadstart = this.onloadend = this.onprogress = null;\n\n\t\tvar constructEvent = function(type, evt) {\n\t\t\tvar e = {type: type, target: _this, loaded: evt.loaded, total: evt.total, error: evt.error};\n\t\t\tif (evt.result != null) e.target.result = evt.result;\n\t\t\treturn e;\n\t\t};\n\t\tvar listener = function(evt) {\n\t\t\tif (!loadStarted) {\n\t\t\t\tloadStarted = true;\n\t\t\t\t_this.onloadstart && _this.onloadstart(constructEvent('loadstart', evt));\n\t\t\t}\n\t\t\tif (evt.type === 'load') {\n\t\t\t\t_this.onloadend && _this.onloadend(constructEvent('loadend', evt));\n\t\t\t\tvar e = constructEvent('load', evt);\n\t\t\t\t_this.onload && _this.onload(e);\n\t\t\t\t_this.dispatchEvent(e);\n\t\t\t} else if (evt.type === 'progress') {\n\t\t\t\tvar e = constructEvent('progress', evt);\n\t\t\t\t_this.onprogress && _this.onprogress(e);\n\t\t\t\t_this.dispatchEvent(e);\n\t\t\t} else {\n\t\t\t\tvar e = constructEvent('error', evt);\n\t\t\t\t_this.onerror && _this.onerror(e);\n\t\t\t\t_this.dispatchEvent(e);\n\t\t\t}\n\t\t};\n\t\tthis.readAsArrayBuffer = function(file) {\n\t\t\tFileAPI.readAsBinaryString(file, listener);\n\t\t}\n\t\tthis.readAsBinaryString = function(file) {\n\t\t\tFileAPI.readAsBinaryString(file, listener);\n\t\t}\n\t\tthis.readAsDataURL = function(file) {\n\t\t\tFileAPI.readAsDataURL(file, listener);\n\t\t}\n\t\tthis.readAsText = function(file) {\n\t\t\tFileAPI.readAsText(file, listener);\n\t\t}\n\t}\n}\n})();\n"
  },
  {
    "path": "flowable-ui-web/modeler/libs/ng-file-upload/ng-file-upload.js",
    "content": "/**!\n * AngularJS file upload/drop directive and service with progress and abort\n * @author  Danial  <danial.farid@gmail.com>\n * @version 4.1.0\n */\n(function () {\n\nvar key, i;\nfunction patchXHR(fnName, newFn) {\n    window.XMLHttpRequest.prototype[fnName] = newFn(window.XMLHttpRequest.prototype[fnName]);\n}\n\nif (window.XMLHttpRequest && !window.XMLHttpRequest.__isFileAPIShim) {\n    patchXHR('setRequestHeader', function (orig) {\n        return function (header, value) {\n            if (header === '__setXHR_') {\n                var val = value(this);\n                // fix for angular < 1.2.0\n                if (val instanceof Function) {\n                    val(this);\n                }\n            } else {\n                orig.apply(this, arguments);\n            }\n        }\n    });\n}\n\nvar ngFileUpload = angular.module('ngFileUpload', []);\n\nngFileUpload.version = '4.1.0';\nngFileUpload.service('Upload', ['$http', '$q', '$timeout', function ($http, $q, $timeout) {\n    function sendHttp(config) {\n        config.method = config.method || 'POST';\n        config.headers = config.headers || {};\n        config.transformRequest = config.transformRequest || function (data, headersGetter) {\n            if (window.ArrayBuffer && data instanceof window.ArrayBuffer) {\n                return data;\n            }\n            return $http.defaults.transformRequest[0](data, headersGetter);\n        };\n        var deferred = $q.defer();\n        var promise = deferred.promise;\n\n        config.headers['__setXHR_'] = function () {\n            return function (xhr) {\n                if (!xhr) return;\n                config.__XHR = xhr;\n                config.xhrFn && config.xhrFn(xhr);\n                xhr.upload.addEventListener('progress', function (e) {\n                    e.config = config;\n                    deferred.notify ? deferred.notify(e) : promise.progress_fn && $timeout(function () {\n                        promise.progress_fn(e)\n                    });\n                }, false);\n                //fix for firefox not firing upload progress end, also IE8-9\n                xhr.upload.addEventListener('load', function (e) {\n                    if (e.lengthComputable) {\n                        e.config = config;\n                        deferred.notify ? deferred.notify(e) : promise.progress_fn && $timeout(function () {\n                            promise.progress_fn(e)\n                        });\n                    }\n                }, false);\n            };\n        };\n\n        $http(config).then(function (r) {\n            deferred.resolve(r)\n        }, function (e) {\n            deferred.reject(e)\n        }, function (n) {\n            deferred.notify(n)\n        });\n\n        promise.success = function (fn) {\n            promise.then(function (response) {\n                fn(response.data, response.status, response.headers, config);\n            });\n            return promise;\n        };\n\n        promise.error = function (fn) {\n            promise.then(null, function (response) {\n                fn(response.data, response.status, response.headers, config);\n            });\n            return promise;\n        };\n\n        promise.progress = function (fn) {\n            promise.progress_fn = fn;\n            promise.then(null, null, function (update) {\n                fn(update);\n            });\n            return promise;\n        };\n        promise.abort = function () {\n            if (config.__XHR) {\n                $timeout(function () {\n                    config.__XHR.abort();\n                });\n            }\n            return promise;\n        };\n        promise.xhr = function (fn) {\n            config.xhrFn = (function (origXhrFn) {\n                return function () {\n                    origXhrFn && origXhrFn.apply(promise, arguments);\n                    fn.apply(promise, arguments);\n                }\n            })(config.xhrFn);\n            return promise;\n        };\n\n        return promise;\n    }\n\n    this.upload = function (config) {\n        config.headers = config.headers || {};\n        config.headers['Content-Type'] = undefined;\n        config.transformRequest = config.transformRequest ?\n            (angular.isArray(config.transformRequest) ?\n                config.transformRequest : [config.transformRequest]) : [];\n        config.transformRequest.push(function (data) {\n            var formData = new FormData();\n            var allFields = {};\n            for (key in config.fields) {\n                if (config.fields.hasOwnProperty(key)) {\n                    allFields[key] = config.fields[key];\n                }\n            }\n            if (data) allFields['data'] = data;\n\n            if (config.formDataAppender) {\n                for (key in allFields) {\n                    if (allFields.hasOwnProperty(key)) {\n                        config.formDataAppender(formData, key, allFields[key]);\n                    }\n                }\n            } else {\n                for (key in allFields) {\n                    if (allFields.hasOwnProperty(key)) {\n                        var val = allFields[key];\n                        if (val !== undefined) {\n                            if (angular.isDate(val)) {\n                                val = val.toISOString();\n                            }\n                            if (angular.isString(val)) {\n                                formData.append(key, val);\n                            } else {\n                                if (config.sendObjectsAsJsonBlob && angular.isObject(val)) {\n                                    formData.append(key, new Blob([val], {type: 'application/json'}));\n                                } else {\n                                    formData.append(key, JSON.stringify(val));\n                                }\n                            }\n\n                        }\n                    }\n                }\n            }\n\n            if (config.file != null) {\n                var fileFormName = config.fileFormDataName || 'file';\n\n                if (angular.isArray(config.file)) {\n                    var isFileFormNameString = angular.isString(fileFormName);\n                    for (var i = 0; i < config.file.length; i++) {\n                        formData.append(isFileFormNameString ? fileFormName : fileFormName[i], config.file[i],\n                            (config.fileName && config.fileName[i]) || config.file[i].name);\n                    }\n                } else {\n                    formData.append(fileFormName, config.file, config.fileName || config.file.name);\n                }\n            }\n            return formData;\n        });\n\n        return sendHttp(config);\n    };\n\n    this.http = function (config) {\n        return sendHttp(config);\n    };\n}]);\n\nngFileUpload.directive('ngfSelect', ['$parse', '$timeout', '$compile',\n    function ($parse, $timeout, $compile) {\n        return {\n            restrict: 'AEC',\n            require: '?ngModel',\n            link: function (scope, elem, attr, ngModel) {\n                linkFileSelect(scope, elem, attr, ngModel, $parse, $timeout, $compile);\n            }\n        }\n    }]);\n\nfunction linkFileSelect(scope, elem, attr, ngModel, $parse, $timeout, $compile) {\n    function isInputTypeFile() {\n        return elem[0].tagName.toLowerCase() === 'input' && elem.attr('type') && elem.attr('type').toLowerCase() === 'file';\n    }\n    var changeFnAttr = attr.ngfChange || (attr.ngfSelect && attr.ngfSelect.indexOf('(') > 0);\n    var isUpdating = false;\n    function changeFn(evt) {\n        if (!isUpdating) {\n            isUpdating = true;\n            try {\n                var fileList = evt.__files_ || (evt.target && evt.target.files);\n                var files = [], rejFiles = [];\n\n                for (var i = 0; i < fileList.length; i++) {\n                    var file = fileList.item(i);\n                    if (validate(scope, $parse, attr, file, evt)) {\n                        files.push(file);\n                    } else {\n                        rejFiles.push(file);\n                    }\n                }\n                updateModel($parse, $timeout, scope, ngModel, attr, changeFnAttr, files, rejFiles, evt);\n                if (files.length == 0) evt.target.value = files;\n//                if (evt.target && evt.target.getAttribute('__ngf_gen__')) {\n//                    angular.element(evt.target).remove();\n//                }\n            } finally {\n                isUpdating = false;\n            }\n        }\n    }\n\n    function bindAttrToFileInput(fileElem) {\n        if (attr.ngfMultiple) fileElem.attr('multiple', $parse(attr.ngfMultiple)(scope));\n        if (!$parse(attr.ngfMultiple)(scope)) fileElem.attr('multiple', undefined);\n        if (attr['accept']) fileElem.attr('accept', attr['accept']);\n        if (attr.ngfCapture) fileElem.attr('capture', $parse(attr.ngfCapture)(scope));\n        if (attr.ngfDisabled) fileElem.attr('disabled', $parse(attr.ngfDisabled)(scope));\n        for (var i = 0; i < elem[0].attributes.length; i++) {\n            var attribute = elem[0].attributes[i];\n            if (attribute.name !== 'type' && attribute.name !== 'class' && attribute.name !== 'id' && attribute.name !== 'style') {\n            \tfileElem.attr(attribute.name, attribute.value);\n            }\n        }\n    }\n\n    function createFileInput(evt) {\n        if (elem.attr('disabled')) {\n            return;\n        }\n        var fileElem = angular.element('<input type=\"file\">');\n        bindAttrToFileInput(fileElem);\n\n        if (isInputTypeFile()) {\n            elem.replaceWith(fileElem);\n            elem = fileElem;\n        } else {\n            fileElem.css('display', 'none').attr('tabindex', '-1').attr('__ngf_gen__', true);\n            if (elem.__ngf_ref_elem__) {elem.__ngf_ref_elem__.remove();}\n            elem.__ngf_ref_elem__ = fileElem;\n            document.body.appendChild(fileElem[0]);\n        }\n\n        return fileElem;\n    }\n\n    function resetModel(evt) {\n        updateModel($parse, $timeout, scope, ngModel, attr, changeFnAttr, [], [], evt, true);\n    }\n\n    function clickHandler(evt) {\n    \tevt.preventDefault();\n        var fileElem = createFileInput(evt);\n        if (fileElem) {\n        \tfileElem.bind('change', changeFn);\n        \tresetModel(evt);\n\n        \tfunction clickAndAssign() {\n            \tfileElem[0].click();\n    \t        if (isInputTypeFile()) {\n    \t            elem.bind('click touchend', clickHandler);\n    \t            evt.preventDefault()\n    \t        }\n        \t}\n        \t\n        \t// fix for android native browser\n        \tif (navigator.userAgent.toLowerCase().match(/android/)) {\n                setTimeout(function() {\n                \tclickAndAssign();\n                }, 0);        \t\t\n        \t} else {\n        \t\tclickAndAssign();\n        \t}\n        }\n    }\n\n    if (window.FileAPI && window.FileAPI.ngfFixIE) {\n        window.FileAPI.ngfFixIE(elem, createFileInput, bindAttrToFileInput, changeFn, resetModel);\n    } else {\n        elem.bind('click touchend', clickHandler);\n    }\n}\n\nngFileUpload.directive('ngfDrop', ['$parse', '$timeout', '$location', function ($parse, $timeout, $location) {\n    return {\n        restrict: 'AEC',\n        require: '?ngModel',\n        link: function (scope, elem, attr, ngModel) {\n            linkDrop(scope, elem, attr, ngModel, $parse, $timeout, $location);\n        }\n    }\n}]);\n\nngFileUpload.directive('ngfNoFileDrop', function () {\n    return function (scope, elem) {\n        if (dropAvailable()) elem.css('display', 'none')\n    }\n});\n\nngFileUpload.directive('ngfDropAvailable', ['$parse', '$timeout', function ($parse, $timeout) {\n    return function (scope, elem, attr) {\n        if (dropAvailable()) {\n            var fn = $parse(attr.ngfDropAvailable);\n            $timeout(function () {\n                fn(scope);\n                if (fn.assign) {\n                    fn.assign(scope, true);                \t\n                }\n            });\n        }\n    }\n}]);\n\nfunction linkDrop(scope, elem, attr, ngModel, $parse, $timeout, $location) {\n    var available = dropAvailable();\n    if (attr.dropAvailable) {\n        $timeout(function () {\n        \tscope[attr.dropAvailable] ? scope[attr.dropAvailable].value = available : scope[attr.dropAvailable] = available;\n        });\n    }\n    if (!available) {\n        if ($parse(attr.ngfHideOnDropNotAvailable)(scope) == true) {\n            elem.css('display', 'none');\n        }\n        return;\n    }\n    var leaveTimeout = null;\n    var stopPropagation = $parse(attr.ngfStopPropagation);\n    var dragOverDelay = 1;\n    var accept = $parse(attr.ngfAccept);\n    var disabled = $parse(attr.ngfDisabled);\n    var actualDragOverClass;\n\n    elem[0].addEventListener('dragover', function (evt) {\n        if (disabled(scope)) return;\n        evt.preventDefault();\n        if (stopPropagation(scope)) evt.stopPropagation();\n        // handling dragover events from the Chrome download bar\n        if (navigator.userAgent.indexOf(\"Chrome\") > -1) {\n            var b = evt.dataTransfer.effectAllowed;\n            evt.dataTransfer.dropEffect = ('move' === b || 'linkMove' === b) ? 'move' : 'copy';\n        }\n        $timeout.cancel(leaveTimeout);\n        if (!scope.actualDragOverClass) {\n            actualDragOverClass = calculateDragOverClass(scope, attr, evt);\n        }\n        elem.addClass(actualDragOverClass);\n    }, false);\n    elem[0].addEventListener('dragenter', function (evt) {\n        if (disabled(scope)) return;\n        evt.preventDefault();\n        if (stopPropagation(scope)) evt.stopPropagation();\n    }, false);\n    elem[0].addEventListener('dragleave', function () {\n        if (disabled(scope)) return;\n        leaveTimeout = $timeout(function () {\n            elem.removeClass(actualDragOverClass);\n            actualDragOverClass = null;\n        }, dragOverDelay || 1);\n    }, false);\n    elem[0].addEventListener('drop', function (evt) {\n        if (disabled(scope)) return;\n        evt.preventDefault();\n        if (stopPropagation(scope)) evt.stopPropagation();\n        elem.removeClass(actualDragOverClass);\n        actualDragOverClass = null;\n        extractFiles(evt, function (files, rejFiles) {\n            updateModel($parse, $timeout, scope, ngModel, attr,\n                attr.ngfChange || (attr.ngfDrop && attr.ngfDrop.indexOf('(') > 0), files, rejFiles, evt)\n        }, $parse(attr.ngfAllowDir)(scope) != false, attr.multiple || $parse(attr.ngfMultiple)(scope));\n    }, false);\n\n    function calculateDragOverClass(scope, attr, evt) {\n        var accepted = true;\n        var items = evt.dataTransfer.items;\n        if (items != null) {\n            for (var i = 0; i < items.length && accepted; i++) {\n                accepted = accepted\n                    && (items[i].kind == 'file' || items[i].kind == '')\n                    && validate(scope, $parse, attr, items[i], evt);\n            }\n        }\n        var clazz = $parse(attr.ngfDragOverClass)(scope, {$event: evt});\n        if (clazz) {\n            if (clazz.delay) dragOverDelay = clazz.delay;\n            if (clazz.accept) clazz = accepted ? clazz.accept : clazz.reject;\n        }\n        return clazz || attr.ngfDragOverClass || 'dragover';\n    }\n\n    function extractFiles(evt, callback, allowDir, multiple) {\n        var files = [], rejFiles = [], items = evt.dataTransfer.items, processing = 0;\n\n        function addFile(file) {\n            if (validate(scope, $parse, attr, file, evt)) {\n                files.push(file);\n            } else {\n                rejFiles.push(file);\n            }\n        }\n\n        if (items && items.length > 0 && $location.protocol() != 'file') {\n            for (var i = 0; i < items.length; i++) {\n                if (items[i].webkitGetAsEntry && items[i].webkitGetAsEntry() && items[i].webkitGetAsEntry().isDirectory) {\n                    var entry = items[i].webkitGetAsEntry();\n                    if (entry.isDirectory && !allowDir) {\n                        continue;\n                    }\n                    if (entry != null) {\n                        traverseFileTree(files, entry);\n                    }\n                } else {\n                    var f = items[i].getAsFile();\n                    if (f != null) addFile(f);\n                }\n                if (!multiple && files.length > 0) break;\n            }\n        } else {\n            var fileList = evt.dataTransfer.files;\n            if (fileList != null) {\n                for (var i = 0; i < fileList.length; i++) {\n                    addFile(fileList.item(i));\n                    if (!multiple && files.length > 0) break;\n                }\n            }\n        }\n        var delays = 0;\n        (function waitForProcess(delay) {\n            $timeout(function () {\n                if (!processing) {\n                    if (!multiple && files.length > 1) {\n                        i = 0;\n                        while (files[i].type == 'directory') i++;\n                        files = [files[i]];\n                    }\n                    callback(files, rejFiles);\n                } else {\n                    if (delays++ * 10 < 20 * 1000) {\n                        waitForProcess(10);\n                    }\n                }\n            }, delay || 0)\n        })();\n\n        function traverseFileTree(files, entry, path) {\n            if (entry != null) {\n                if (entry.isDirectory) {\n                    var filePath = (path || '') + entry.name;\n                    addFile({name: entry.name, type: 'directory', path: filePath});\n                    var dirReader = entry.createReader();\n                    var entries = [];\n                    processing++;\n                    var readEntries = function () {\n                        dirReader.readEntries(function (results) {\n                            try {\n                                if (!results.length) {\n                                    for (var i = 0; i < entries.length; i++) {\n                                        traverseFileTree(files, entries[i], (path ? path : '') + entry.name + '/');\n                                    }\n                                    processing--;\n                                } else {\n                                    entries = entries.concat(Array.prototype.slice.call(results || [], 0));\n                                    readEntries();\n                                }\n                            } catch (e) {\n                                processing--;\n                                console.error(e);\n                            }\n                        }, function () {\n                            processing--;\n                        });\n                    };\n                    readEntries();\n                } else {\n                    processing++;\n                    entry.file(function (file) {\n                        try {\n                            processing--;\n                            file.path = (path ? path : '') + file.name;\n                            addFile(file);\n                        } catch (e) {\n                            processing--;\n                            console.error(e);\n                        }\n                    }, function () {\n                        processing--;\n                    });\n                }\n            }\n        }\n    }\n}\n\nngFileUpload.directive('ngfSrc', ['$parse', '$timeout', function ($parse, $timeout) {\n\treturn {\n\t\trestrict: 'AE',\n\t\tlink: function (scope, elem, attr, file) {\n\t\t\tif (window.FileReader) {\n\t\t\t\tscope.$watch(attr.ngfSrc, function(file) {\n\t\t\t\t\tif (file) {\n\t\t\t\t\t\t$timeout(function() {\n\t\t\t\t\t\t\tvar fileReader = new FileReader();\n\t\t\t\t\t\t\tfileReader.readAsDataURL(file);\n\t\t\t\t\t\t\tfileReader.onload = function(e) {\n\t\t\t\t\t\t\t\t$timeout(function() {\n\t\t\t\t\t\t\t\t\telem.attr('src', e.target.result);\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t});\n\t\t\t\t\t} else {\n\t\t\t\t\t\telem.attr('src', '');\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n}]);\n\nfunction dropAvailable() {\n    var div = document.createElement('div');\n    return ('draggable' in div) && ('ondrop' in div);\n}\n\nfunction updateModel($parse, $timeout, scope, ngModel, attr, fileChange, files, rejFiles, evt, noDelay) {\n    function update() {\n        if (ngModel) {\n            $parse(attr.ngModel).assign(scope, files);\n            $timeout(function () {\n                ngModel && ngModel.$setViewValue(files != null && files.length == 0 ? null : files);\n            });\n        }\n        if (attr.ngModelRejected) {\n            $parse(attr.ngModelRejected).assign(scope, rejFiles);\n        }\n        if (fileChange) {\n            $parse(fileChange)(scope, {\n                $files: files,\n                $rejectedFiles: rejFiles,\n                $event: evt\n            });\n\n        }\n    }\n    if (noDelay) {\n        update();\n    } else {\n        $timeout(function () {\n            update();\n        });\n    }\n}\n\nfunction validate(scope, $parse, attr, file, evt) {\n    var accept = $parse(attr.ngfAccept);\n    var fileSizeMax = $parse(attr.ngfMaxSize)(scope) || 9007199254740991;\n    var fileSizeMin = $parse(attr.ngfMinSize)(scope) || -1;\n    var val = accept(scope, {$file: file, $event: evt}), match = false;\n    if (val != null && angular.isString(val)) {\n        var regexp = new RegExp(globStringToRegex(val), 'gi');\n        match = (file.type != null && file.type.match(regexp)) ||\n        \t\t(file.name != null && file.name.match(regexp));\n    }\n    return (val == null || match) && (file.size == null || (file.size < fileSizeMax && file.size > fileSizeMin));\n}\n\nfunction globStringToRegex(str) {\n    if (str.length > 2 && str[0] === '/' && str[str.length - 1] === '/') {\n        return str.substring(1, str.length - 1);\n    }\n    var split = str.split(','), result = '';\n    if (split.length > 1) {\n        for (var i = 0; i < split.length; i++) {\n            result += '(' + globStringToRegex(split[i]) + ')';\n            if (i < split.length - 1) {\n                result += '|'\n            }\n        }\n    } else {\n        if (str.indexOf('.') == 0) {\n            str = '*' + str;\n        }\n        result = '^' + str.replace(new RegExp('[.\\\\\\\\+*?\\\\[\\\\^\\\\]$(){}=!<>|:\\\\' + '-]', 'g'), '\\\\$&') + '$';\n        result = result.replace(/\\\\\\*/g, '.*').replace(/\\\\\\?/g, '.');\n    }\n    return result;\n}\n\n})();\n"
  },
  {
    "path": "flowable-ui-web/modeler/libs/ng-handsontable_0.13/ngHandsontable.js",
    "content": "/**\n * ng-handsontable 0.13.0\n * \n * Copyright 2012-2015 Marcin Warpechowski\n * Copyright 2015 Handsoncode sp. z o.o. <hello@handsontable.com>\n * Licensed under the MIT license.\n * https://github.com/handsontable/ngHandsontable\n * Date: Wed Oct 26 2016 10:00:05 GMT+0200 (CEST)\n*/\n\nif (document.all && !document.addEventListener) { // IE 8 and lower\n  document.createElement('hot-table');\n  document.createElement('hot-column');\n  document.createElement('hot-autocomplete');\n}\n\nangular.module('ngHandsontable.services', []);\nangular.module('ngHandsontable.directives', []);\nangular.module('ngHandsontable', [\n    'ngHandsontable.services',\n    'ngHandsontable.directives'\n  ]);\n\nHandsontable.hooks.add('afterContextMenuShow', function() {\n  Handsontable.eventManager.isHotTableEnv = false;\n});\n\n(function() {\n  function autoCompleteFactory($parse) {\n    return {\n      parseAutoComplete: function(column, dataSet, propertyOnly) {\n        column.source = function(query, process) {\n          var row = this.instance.getSelected()[0];\n          var source = [];\n          var data = dataSet[row];\n\n          if (!data) {\n            return;\n          }\n          var options = column.optionList;\n\n          if (!options || !options.object) {\n            return;\n          }\n          if (angular.isArray(options.object)) {\n            source = options.object;\n          } else {\n            // Using $parse to evaluate the expression against the row object\n            // allows us to support filters like the ngRepeat directive does.\n            var paramObject = $parse(options.object)(data);\n\n            if (angular.isArray(paramObject)) {\n              if (propertyOnly) {\n                for (var i = 0, length = paramObject.length; i < length; i++) {\n                  var item = paramObject[i][options.property];\n\n                  if (item !== null && item !== undefined) {\n                    source.push(item);\n                  }\n                }\n              } else {\n                source = paramObject;\n              }\n            } else {\n              source = paramObject;\n            }\n          }\n          process(source);\n        };\n      }\n    };\n  }\n  autoCompleteFactory.$inject = ['$parse'];\n\n  angular.module('ngHandsontable.services').factory('autoCompleteFactory', autoCompleteFactory);\n}());\n\n(function() {\n\n  function hotRegisterer() {\n    var instances = {};\n\n    return {\n      getInstance: function(id) {\n        return instances[id];\n      },\n\n      registerInstance: function(id, instance) {\n        instances[id] = instance;\n      },\n\n      removeInstance: function(id) {\n        instances[id] = void 0;\n      }\n    };\n  }\n  hotRegisterer.$inject = [];\n\n  angular.module('ngHandsontable.services').factory('hotRegisterer', hotRegisterer);\n}());\n\n(function() {\n\n  function hyphenate(string) {\n    return string.replace(/[A-Z]/g, function(match) {\n      return ('-' + match.charAt(0).toLowerCase());\n    });\n  }\n\n  function camelCase(string) {\n    return string.replace(/-\\D/g, function(match) {\n      return match.charAt(1).toUpperCase();\n    });\n  }\n\n  function ucFirst(string) {\n    return string.substr(0, 1).toUpperCase() + string.substr(1, string.length - 1);\n  }\n\n  function settingFactory(hotRegisterer) {\n    return {\n      containerClassName: 'handsontable-container',\n\n      /**\n       * Append handsontable container div and initialize handsontable instance inside element.\n       *\n       * @param {qLite} element\n       * @param {Object} htSettings\n       */\n      initializeHandsontable: function(element, htSettings) {\n        var container = document.createElement('div'),\n          hot;\n\n        container.className = this.containerClassName;\n\n        if (htSettings.hotId) {\n          container.id = htSettings.hotId;\n        }\n        element[0].appendChild(container);\n        hot = new Handsontable(container, htSettings);\n\n        if (htSettings.hotId) {\n          hotRegisterer.registerInstance(htSettings.hotId, hot);\n        }\n\n        return hot;\n      },\n\n      /**\n       * Set new settings to handsontable instance.\n       *\n       * @param {Handsontable} instance\n       * @param {Object} settings\n       */\n      updateHandsontableSettings: function(instance, settings) {\n        if (instance) {\n          instance.updateSettings(settings);\n        }\n      },\n\n      /**\n       * Render handsontable instance inside element.\n       *\n       * @param {Handsontable} instance\n       */\n      renderHandsontable: function(instance) {\n        if (instance) {\n          instance.render();\n        }\n      },\n\n      /**\n       * Merge original handsontable settings with setting defined in scope.\n       *\n       * @param {Object} settings\n       * @param {Object} scope\n       * @returns {Object}\n       */\n      mergeSettingsFromScope: function(settings, scope) {\n        var\n          scopeOptions = angular.extend({}, scope),\n          htOptions, i, length;\n\n        settings = settings || {};\n        angular.extend(scopeOptions, scope.settings || {});\n        htOptions = this.getAvailableSettings();\n\n        for (i = 0, length = htOptions.length; i < length; i++) {\n          if (typeof scopeOptions[htOptions[i]] !== 'undefined') {\n            settings[htOptions[i]] = scopeOptions[htOptions[i]];\n          }\n        }\n\n        return settings;\n      },\n\n      /**\n       * Merge original handsontable hooks with hooks defined in scope.\n       *\n       * @param {Object} settings\n       * @param {Object} scope\n       * @returns {Object}\n       */\n      mergeHooksFromScope: function(settings, scope) {\n        var\n          scopeOptions = angular.extend({}, scope),\n          htHooks, i, length, attribute;\n\n        settings = settings || {};\n        angular.extend(scopeOptions, scope.settings || {});\n        htHooks = this.getAvailableHooks();\n\n        for (i = 0, length = htHooks.length; i < length; i++) {\n          attribute = 'on' + ucFirst(htHooks[i]);\n\n          if (typeof scopeOptions[htHooks[i]] === 'function' || typeof scopeOptions[attribute] === 'function') {\n            settings[htHooks[i]] = scopeOptions[htHooks[i]] || scopeOptions[attribute];\n          }\n        }\n\n        return settings;\n      },\n\n      /**\n       * Trim scope definition according to attrs object from directive.\n       *\n       * @param {Object} scopeDefinition\n       * @param {Object} attrs\n       * @returns {Object}\n       */\n      trimScopeDefinitionAccordingToAttrs: function(scopeDefinition, attrs) {\n        for (var i in scopeDefinition) {\n          if (scopeDefinition.hasOwnProperty(i) && attrs[i] === void 0 &&\n              attrs[scopeDefinition[i].substr(1, scopeDefinition[i].length)] === void 0) {\n            delete scopeDefinition[i];\n          }\n        }\n\n        return scopeDefinition;\n      },\n\n      /**\n       * Get isolate scope definition for main handsontable directive.\n       *\n       * @return {Object}\n       */\n      getTableScopeDefinition: function() {\n        var scopeDefinition = {};\n\n        this.applyAvailableSettingsScopeDef(scopeDefinition);\n        this.applyAvailableHooksScopeDef(scopeDefinition);\n\n        scopeDefinition.datarows = '=';\n        scopeDefinition.dataschema = '=';\n        scopeDefinition.observeDomVisibility = '=';\n        //scopeDefinition.settings = '=';\n\n        return scopeDefinition;\n      },\n\n      /**\n       * Get isolate scope definition for column directive.\n       *\n       * @return {Object}\n       */\n      getColumnScopeDefinition: function() {\n        var scopeDefinition = {};\n\n        this.applyAvailableSettingsScopeDef(scopeDefinition);\n        scopeDefinition.data = '@';\n\n        return scopeDefinition;\n      },\n\n      /**\n       * Apply all available handsontable settings into object which represents scope definition.\n       *\n       * @param {Object} [scopeDefinition]\n       * @returns {Object}\n       */\n      applyAvailableSettingsScopeDef: function(scopeDefinition) {\n        var options, i, length;\n\n        options = this.getAvailableSettings();\n\n        for (i = 0, length = options.length; i < length; i++) {\n          scopeDefinition[options[i]] = '=';\n        }\n\n        return scopeDefinition;\n      },\n\n      /**\n       * Apply all available handsontable hooks into object which represents scope definition.\n       *\n       * @param {Object} [scopeDefinition]\n       * @returns {Object}\n       */\n      applyAvailableHooksScopeDef: function(scopeDefinition) {\n        var options, i, length;\n\n        options = this.getAvailableHooks();\n\n        for (i = 0, length = options.length; i < length; i++) {\n          scopeDefinition[options[i]] = '=on' + ucFirst(options[i]);\n        }\n\n        return scopeDefinition;\n      },\n\n      /**\n       * Get all available settings from handsontable, returns settings by default in camelCase mode.\n       *\n       * @param {Boolean} [hyphenateStyle=undefined] If `true` then returns options in hyphenate mode (eq. row-header)\n       * @returns {Array}\n       */\n      getAvailableSettings: function(hyphenateStyle) {\n        var settings = Object.keys(Handsontable.DefaultSettings.prototype);\n\n        if (settings.indexOf('contextMenuCopyPaste') === -1) {\n          settings.push('contextMenuCopyPaste');\n        }\n        if (settings.indexOf('handsontable') === -1) {\n          settings.push('handsontable');\n        }\n        if (settings.indexOf('settings') >= 0) {\n          settings.splice(settings.indexOf('settings'), 1);\n        }\n        if (hyphenateStyle) {\n          settings = settings.map(hyphenate);\n        }\n\n        return settings;\n      },\n\n      /**\n       * Get all available hooks from handsontable, returns hooks by default in camelCase mode.\n       *\n       * @param {Boolean} [hyphenateStyle=undefined] If `true` then returns hooks in hyphenate mode (eq. on-after-init)\n       * @returns {Array}\n       */\n      getAvailableHooks: function(hyphenateStyle) {\n        var settings = Handsontable.hooks.getRegistered();\n\n        if (hyphenateStyle) {\n          settings = settings.map(function(hook) {\n            return 'on-' + hyphenate(hook);\n          });\n        }\n\n        return settings;\n      }\n    };\n  }\n  settingFactory.$inject = ['hotRegisterer'];\n\n  angular.module('ngHandsontable.services').factory('settingFactory', settingFactory);\n}());\n\n(function() {\n  /**\n   * Angular Handsontable directive for autocomplete settings\n   */\n  function hotAutocomplete() {\n    return {\n      restrict: 'EA',\n      scope: true,\n      require: '^hotColumn',\n      link: function(scope, element, attrs, controllerInstance) {\n        var options = attrs.datarows;\n\n        controllerInstance.setColumnOptionList(options);\n      }\n    };\n  }\n  hotAutocomplete.$inject = [];\n\n  angular.module('ngHandsontable.directives').directive('hotAutocomplete', hotAutocomplete);\n}());\n\n(function() {\n  /**\n   * Angular Handsontable directive for single column settings\n   */\n  function hotColumn(settingFactory) {\n    return {\n      restrict: 'EA',\n      require: '^hotTable',\n      scope: {},\n      controller: ['$scope', function($scope) {\n        this.setColumnOptionList = function(options) {\n          if (!$scope.column) {\n            $scope.column = {};\n          }\n          var optionList = {};\n          var match = options.match(/^\\s*([\\s\\S]+?)\\s+in\\s+([\\s\\S]+?)\\s*$/);\n\n          if (match) {\n            optionList.property = match[1];\n            optionList.object = match[2];\n          } else {\n            optionList.object = options.split(',');\n          }\n          $scope.column.optionList = optionList;\n        };\n      }],\n      compile: function(tElement, tAttrs) {\n        var _this = this;\n\n        this.scope = settingFactory.trimScopeDefinitionAccordingToAttrs(settingFactory.getColumnScopeDefinition(), tAttrs);\n        //this.$$isolateBindings = {};\n\n        angular.forEach(Object.keys(this.scope), function(key) {\n          _this.$$isolateBindings[key] = {\n            attrName: key,\n            collection: false,\n            mode: key === 'data' ? '@' : '=',\n            optional: false\n          };\n        });\n\n        return function(scope, element, attrs, controllerInstance) {\n          var column = {};\n\n          // Turn all attributes without value as `true` by default\n          angular.forEach(Object.keys(attrs), function(key) {\n            if (key.charAt(0) !== '$' && attrs[key] === '') {\n              column[key] = true;\n            }\n          });\n          settingFactory.mergeSettingsFromScope(column, scope);\n\n          if (!scope.column) {\n            scope.column = {};\n          }\n          angular.extend(scope.column, column);\n          controllerInstance.setColumnSetting(scope.column);\n\n          scope.$on('$destroy', function() {\n            controllerInstance.removeColumnSetting(scope.column);\n          });\n        };\n      }\n    };\n  }\n  hotColumn.$inject = ['settingFactory'];\n\n  angular.module('ngHandsontable.directives').directive('hotColumn', hotColumn);\n}());\n\n(function() {\n  /**\n   * Main Angular Handsontable directive\n   */\n  function hotTable(settingFactory, autoCompleteFactory, $rootScope, $parse) {\n    return {\n      restrict: 'EA',\n      scope: {},\n      // for ng-repeat\n      priority: -400,\n      controller: ['$scope', function($scope) {\n        this.setColumnSetting = function(column) {\n          if (!$scope.htSettings) {\n            $scope.htSettings = {};\n          }\n          if (!$scope.htSettings.columns) {\n            $scope.htSettings.columns = [];\n          }\n          $scope.htSettings.columns.push(column);\n          settingFactory.updateHandsontableSettings($scope.hotInstance, $scope.htSettings);\n        };\n        this.removeColumnSetting = function(column) {\n          if ($scope.htSettings.columns.indexOf(column) > -1) {\n            $scope.htSettings.columns.splice($scope.htSettings.columns.indexOf(column), 1);\n            settingFactory.updateHandsontableSettings($scope.hotInstance, $scope.htSettings);\n          }\n        };\n      }],\n      compile: function(tElement, tAttrs) {\n        var _this = this,\n          bindingsKeys;\n\n        this.scope = settingFactory.trimScopeDefinitionAccordingToAttrs(settingFactory.getTableScopeDefinition(), tAttrs);\n        bindingsKeys = Object.keys(this.scope);\n\n        angular.forEach(bindingsKeys, function(key) {\n          var mode = _this.scope[key].charAt(0);\n\n          _this.$$isolateBindings[key] = {\n            attrName: _this.scope[key].length > 1 ? _this.scope[key].substr(1, _this.scope[key].length) : key,\n            collection: key === 'datarows',\n            mode: mode,\n            optional: false\n          };\n        });\n\n        return function(scope, element, attrs) {\n          scope.settings = $parse(attrs.settings)(scope.$parent);\n\n          if (!scope.htSettings) {\n            scope.htSettings = {};\n          }\n          // Turn all attributes without value as `true` by default\n          angular.forEach(Object.keys(attrs), function(key) {\n            if (key.charAt(0) !== '$' && attrs[key] === '') {\n              scope.htSettings[key] = true;\n            }\n          });\n\n          settingFactory.mergeSettingsFromScope(scope.htSettings, scope);\n          settingFactory.mergeHooksFromScope(scope.htSettings, scope);\n\n          if (!scope.htSettings.data) {\n            scope.htSettings.data = scope.datarows;\n          }\n          scope.htSettings.dataSchema = scope.dataschema;\n          scope.htSettings.hotId = attrs.hotId;\n          scope.htSettings.observeDOMVisibility = scope.observeDomVisibility;\n\n          if (scope.htSettings.columns) {\n            for (var i = 0, length = scope.htSettings.columns.length; i < length; i++) {\n              var column = scope.htSettings.columns[i];\n\n              if (column.type !== 'autocomplete') {\n                continue;\n              }\n              if (!column.optionList) {\n                continue;\n              }\n              if (typeof column.optionList === 'string') {\n                var optionList = {};\n                var match = column.optionList.match(/^\\s*([\\s\\S]+?)\\s+in\\s+([\\s\\S]+?)\\s*$/);\n\n                if (match) {\n                  optionList.property = match[1];\n                  optionList.object = match[2];\n                } else {\n                  optionList.object = optionList;\n                }\n                column.optionList = optionList;\n              }\n              autoCompleteFactory.parseAutoComplete(column, scope.datarows, true);\n            }\n          }\n          var origAfterChange = scope.htSettings.afterChange;\n\n          scope.htSettings.afterChange = function() {\n            if (origAfterChange) {\n              origAfterChange.apply(this, arguments);\n            }\n            if (!$rootScope.$$phase) {\n              scope.$apply();\n            }\n          };\n          scope.hotInstance = settingFactory.initializeHandsontable(element, scope.htSettings);\n\n          // TODO: Add watch properties descriptor + needs perf test. Watch full equality vs toJson\n          angular.forEach(bindingsKeys, function(key) {\n            scope.$watch(key, function(newValue, oldValue) {\n              if (newValue === void 0) {\n                return;\n              }\n              if (key === 'datarows') {\n                // If reference to data rows is not changed then only re-render table\n                if (scope.hotInstance.getSettings().data === newValue) {\n                  settingFactory.renderHandsontable(scope.hotInstance);\n                } else {\n                  scope.hotInstance.loadData(newValue);\n                  scope.htSettings.data = newValue;\n                }\n              } else if (newValue !== oldValue) {\n                scope.htSettings[key] = newValue;\n                settingFactory.updateHandsontableSettings(scope.hotInstance, scope.htSettings);\n              }\n            }, ['datarows', 'columns', 'rowHeights', 'colWidths', 'rowHeaders', 'colHeaders'].indexOf(key) >= 0);\n          });\n\n          /**\n           * Check for reference equality changes for datarows\n           * TODO: must the remaining bindingsKeys need to be added also if their reference changes\n           */\n          scope.$watch('datarows', function(newValue) {\n            if (newValue === void 0) {\n              return;\n            }\n            if (scope.hotInstance.getSettings().data !== newValue) {\n              scope.hotInstance.loadData(newValue);\n            }\n          });\n\n          /**\n           * Check if data length has been changed\n           */\n          scope.$watchCollection('datarows', function(newValue, oldValue) {\n            if (oldValue && oldValue.length === scope.htSettings.minSpareRows && newValue.length !== scope.htSettings.minSpareRows) {\n              scope.htSettings.data = scope.datarows;\n              settingFactory.updateHandsontableSettings(scope.hotInstance, scope.htSettings);\n            }\n          });\n        };\n      }\n    };\n  }\n  hotTable.$inject = ['settingFactory', 'autoCompleteFactory', '$rootScope', '$parse'];\n\n  angular.module('ngHandsontable.directives').directive('hotTable', hotTable);\n}());\n"
  },
  {
    "path": "flowable-ui-web/modeler/libs/sizzle_1.10.16/.bower.json",
    "content": "{\n  \"name\": \"sizzle\",\n  \"version\": \"1.10.16\",\n  \"main\": \"./dist/sizzle.js\",\n  \"devDependencies\": {\n    \"qunit\": \"~1.12.0\",\n    \"benchmark\": \"~1.0.0\",\n    \"requirejs\": \"~2.1.8\",\n    \"requirejs-domready\": \"~2.0.1\",\n    \"requirejs-text\": \"~2.0.10\"\n  },\n  \"ignore\": [\n    \"**/.*\",\n    \"package.json\",\n    \"bower.json\",\n    \"speed\",\n    \"Makefile\",\n    \"*.md\",\n    \"*.txt\",\n    \"src\",\n    \"Gruntfile.js\"\n  ],\n  \"homepage\": \"https://github.com/jquery/sizzle\",\n  \"_release\": \"1.10.16\",\n  \"_resolution\": {\n    \"type\": \"version\",\n    \"tag\": \"1.10.16\",\n    \"commit\": \"0fd151739d05648118002914c7a638411bbd0dbe\"\n  },\n  \"_source\": \"git://github.com/jquery/sizzle.git\",\n  \"_target\": \"1.10.16\",\n  \"_originalSource\": \"sizzle\"\n}"
  },
  {
    "path": "flowable-ui-web/modeler/libs/sizzle_1.10.16/tasks/commit.js",
    "content": "\"use strict\";\n\nvar exec = require( \"child_process\" ).exec;\n\nmodule.exports = function( grunt ) {\n\tgrunt.registerTask( \"commit\", \"Add and commit changes\", function( message ) {\n\t\t// Always add dist directory\n\t\texec( \"git add dist && git commit -m \" + message, this.async() );\n\t});\n};\n"
  },
  {
    "path": "flowable-ui-web/modeler/libs/sizzle_1.10.16/tasks/compile.js",
    "content": "\"use strict\";\n\nmodule.exports = function( grunt ) {\n\tgrunt.registerMultiTask(\n\t\t\"compile\",\n\t\t\"Compile sizzle.js to the dist directory. Embed date/version.\",\n\t\tfunction() {\n\t\t\tvar data = this.data,\n\t\t\t\tdest = data.dest,\n\t\t\t\tsrc = data.src,\n\t\t\t\tversion = grunt.config( \"pkg.version\" ),\n\t\t\t\tcompiled = grunt.file.read( src );\n\n\t\t\t// Embed version and date\n\t\t\tcompiled = compiled\n\t\t\t\t.replace( /@VERSION/g, version )\n\t\t\t\t.replace( \"@DATE\", function() {\n\t\t\t\t\tvar date = new Date();\n\n\t\t\t\t\t// YYYY-MM-DD\n\t\t\t\t\treturn [\n\t\t\t\t\t\tdate.getFullYear(),\n\t\t\t\t\t\t( \"0\" + ( date.getMonth() + 1 ) ).slice( -2 ),\n\t\t\t\t\t\t( \"0\" + date.getDate() ).slice( -2 )\n\t\t\t\t\t].join( \"-\" );\n\t\t\t\t});\n\n\t\t\t// Write source to file\n\t\t\tgrunt.file.write( dest, compiled );\n\n\t\t\tgrunt.log.ok( \"File written to \" + dest );\n\t\t}\n\t);\n};\n"
  },
  {
    "path": "flowable-ui-web/modeler/libs/sizzle_1.10.16/tasks/dist.js",
    "content": "\"use strict\";\n\nvar fs = require( \"fs\" );\n\nmodule.exports = function( grunt ) {\n\tgrunt.registerTask( \"dist\", \"Process files for distribution\", function() {\n\t\tvar files = grunt.file.expand( { filter: \"isFile\" }, \"dist/*\" );\n\n\t\tfiles.forEach(function( filename ) {\n\t\t\tvar map,\n\t\t\t\ttext = fs.readFileSync( filename, \"utf8\" );\n\n\t\t\t// Modify map/min so that it points to files in the same folder;\n\t\t\t// see https://github.com/mishoo/UglifyJS2/issues/47\n\t\t\tif ( /\\.map$/.test( filename ) ) {\n\t\t\t\ttext = text.replace( /\"dist\\//g, \"\\\"\" );\n\t\t\t\tfs.writeFileSync( filename, text, \"utf-8\" );\n\t\t\t} else if ( /\\.min\\.js$/.test( filename ) ) {\n\t\t\t\t// Wrap sourceMap directive in multiline comments (#13274)\n\t\t\t\ttext = text.replace( /\\n?(\\/\\/@\\s*sourceMappingURL=)(.*)/,\n\t\t\t\t\tfunction( _, directive, path ) {\n\t\t\t\t\t\tmap = \"\\n\" + directive + path.replace( /^dist\\//, \"\" );\n\t\t\t\t\t\treturn \"\";\n\t\t\t\t\t});\n\t\t\t\tif ( map ) {\n\t\t\t\t\ttext = text.replace( /(^\\/\\*[\\w\\W]*?)\\s*\\*\\/|$/,\n\t\t\t\t\t\tfunction( _, comment ) {\n\t\t\t\t\t\t\treturn ( comment || \"\\n/*\" ) + map + \"\\n*/\";\n\t\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tfs.writeFileSync( filename, text, \"utf-8\" );\n\t\t\t}\n\t\t});\n\t});\n};\n"
  },
  {
    "path": "flowable-ui-web/modeler/libs/sizzle_1.10.16/tasks/release.js",
    "content": "\"use strict\";\n\nvar exec = require( \"child_process\" ).exec;\n\nmodule.exports = function( grunt ) {\n\tvar rpreversion = /(\\d\\.\\d+\\.\\d+)-pre/;\n\n\tgrunt.registerTask( \"release\",\n\t\t\"Release a version of sizzle, updates a pre version to released, \" +\n\t\t\"inserts `next` as the new pre version\", function( next ) {\n\t\t\n\t\tif ( !rpreversion.test( next ) ) {\n\t\t\tgrunt.fatal( \"Next version should be a -pre version (x.x.x-pre): \" + next );\n\t\t\treturn;\n\t\t}\n\n\t\tvar done,\n\t\t\tversion = grunt.config( \"pkg.version\" );\n\t\tif ( !rpreversion.test( version ) ) {\n\t\t\tgrunt.fatal( \"Existing version is not a pre version: \" + version );\n\t\t\treturn;\n\t\t}\n\t\tversion = version.replace( rpreversion, \"$1\" );\n\n\t\tdone = this.async();\n\t\texec( \"git diff --quiet HEAD\", function( err ) {\n\t\t\tif ( err ) {\n\t\t\t\tgrunt.fatal( \"The working directory should be clean when releasing. Commit or stash changes.\" );\n\t\t\t\treturn;\n\t\t\t}\n\t\t\t// Build to dist directories along with a map and tag the release\n\t\t\tgrunt.task.run([\n\t\t\t\t// Commit new version\n\t\t\t\t\"version:\" + version,\n\t\t\t\t// Tag new version\n\t\t\t\t\"tag:\" + version,\n\t\t\t\t// Commit next version\n\t\t\t\t\"version:\" + next\n\t\t\t]);\n\t\t\tdone();\n\t\t});\n\t});\n};\n"
  },
  {
    "path": "flowable-ui-web/modeler/libs/sizzle_1.10.16/tasks/tag.js",
    "content": "\"use strict\";\n\nvar exec = require( \"child_process\" ).exec;\n\nmodule.exports = function( grunt ) {\n\tgrunt.registerTask( \"tag\", \"Tag the specified version\", function( version ) {\n\t\texec( \"git tag \" + version, this.async() );\n\t});\n};\n"
  },
  {
    "path": "flowable-ui-web/modeler/libs/sizzle_1.10.16/tasks/version.js",
    "content": "\"use strict\";\n\nvar exec = require( \"child_process\" ).exec;\n\nmodule.exports = function( grunt ) {\n\tgrunt.registerTask( \"version\", \"Commit a new version\", function( version ) {\n\t\tif ( !/\\d\\.\\d+\\.\\d+(?:-pre)?/.test( version ) ) {\n\t\t\tgrunt.fatal( \"Version must follow semver release format: \" + version );\n\t\t\treturn;\n\t\t}\n\n\t\tvar done = this.async(),\n\t\t\tfiles = grunt.config( \"version.files\" ),\n\t\t\trversion = /(\"version\":\\s*\")[^\"]+/;\n\n\t\t// Update version in specified files\n\t\tfiles.forEach(function( filename ) {\n\t\t\tvar text = grunt.file.read( filename );\n\t\t\ttext = text.replace( rversion, \"$1\" + version );\n\t\t\tgrunt.file.write( filename, text );\n\t\t});\n\n\t\t// Add files to git index\n\t\texec( \"git add -A\", function( err ) {\n\t\t\tif ( err ) {\n\t\t\t\tgrunt.fatal( err );\n\t\t\t\treturn;\n\t\t\t}\n\t\t\t// Commit next pre version\n\t\t\tgrunt.config( \"pkg.version\", version );\n\t\t\tgrunt.task.run([ \"build\", \"uglify\", \"dist\", \"commit:'Update version to \" + version + \"'\" ]);\n\t\t\tdone();\n\t\t});\n\t});\n};\n"
  },
  {
    "path": "flowable-ui-web/modeler/libs/sizzle_1.10.16/test/data/empty.js",
    "content": ""
  },
  {
    "path": "flowable-ui-web/modeler/libs/sizzle_1.10.16/test/data/mixed_sort.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />\n\t<script>var QUnit = parent.QUnit</script>\n\t<script src=\"testinit.js\"></script>\n\t<script src=\"../../dist/sizzle.js\"></script>\n</head>\n<body>\n\t<script>\n\t\tvar doc = parent.document,\n\t\t\tunframed = [ doc.getElementById( \"qunit-fixture\" ), doc.body, doc.documentElement ],\n\t\t\tframed = Sizzle( \"*\" );\n\n\t\twindow.parent.iframeCallback(\n\t\t\tSizzle.uniqueSort( unframed.concat( framed ) ),\n\t\t\tframed.concat( unframed.reverse() ),\n\t\t\t\"Mixed array was sorted correctly\"\n\t\t);\n\t</script>\n</body>\n</html>\n"
  },
  {
    "path": "flowable-ui-web/modeler/libs/sizzle_1.10.16/test/data/testinit.js",
    "content": "var fireNative,\n\tjQuery = this.jQuery || \"jQuery\", // For testing .noConflict()\n\t$ = this.$ || \"$\",\n\toriginaljQuery = jQuery,\n\toriginal$ = $;\n\n(function() {\n\t// Config parameter to force basic code paths\n\tQUnit.config.urlConfig.push({\n\t\tid: \"basic\",\n\t\tlabel: \"Bypass optimizations\",\n\t\ttooltip: \"Force use of the most basic code by disabling native querySelectorAll; contains; compareDocumentPosition\"\n\t});\n\tif ( QUnit.urlParams.basic ) {\n\t\tdocument.querySelectorAll = null;\n\t\tdocument.documentElement.contains = null;\n\t\tdocument.documentElement.compareDocumentPosition = null;\n\t\t// Return array of length two to pass assertion\n\t\t// But support should be false as its not native\n\t\tdocument.getElementsByClassName = function() { return [ 0, 1 ]; };\n\t}\n})();\n\n/**\n * Returns an array of elements with the given IDs\n * @example q(\"main\", \"foo\", \"bar\")\n * @result [<div id=\"main\">, <span id=\"foo\">, <input id=\"bar\">]\n */\nfunction q() {\n\tvar r = [],\n\t\ti = 0;\n\n\tfor ( ; i < arguments.length; i++ ) {\n\t\tr.push( document.getElementById( arguments[i] ) );\n\t}\n\treturn r;\n}\n\n/**\n * Asserts that a select matches the given IDs\n * @param {String} a - Assertion name\n * @param {String} b - Sizzle selector\n * @param {String} c - Array of ids to construct what is expected\n * @example t(\"Check for something\", \"//[a]\", [\"foo\", \"baar\"]);\n * @result returns true if \"//[a]\" return two elements with the IDs 'foo' and 'baar'\n */\nfunction t( a, b, c ) {\n\tvar f = Sizzle(b),\n\t\ts = \"\",\n\t\ti = 0;\n\n\tfor ( ; i < f.length; i++ ) {\n\t\ts += ( s && \",\" ) + '\"' + f[ i ].id + '\"';\n\t}\n\n\tdeepEqual(f, q.apply( q, c ), a + \" (\" + b + \")\");\n}\n\n/**\n * Add random number to url to stop caching\n *\n * @example url(\"data/test.html\")\n * @result \"data/test.html?10538358428943\"\n *\n * @example url(\"data/test.php?foo=bar\")\n * @result \"data/test.php?foo=bar&10538358345554\"\n */\nfunction url( value ) {\n\treturn value + (/\\?/.test(value) ? \"&\" : \"?\") + new Date().getTime() + \"\" + parseInt(Math.random()*100000);\n}\n\nvar createWithFriesXML = function() {\n\tvar string = '<?xml version=\"1.0\" encoding=\"UTF-8\"?> \\\n\t<soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\" \\\n\t\txmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" \\\n\t\txmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"> \\\n\t\t<soap:Body> \\\n\t\t\t<jsconf xmlns=\"http://www.example.com/ns1\"> \\\n\t\t\t\t<response xmlns:ab=\"http://www.example.com/ns2\"> \\\n\t\t\t\t\t<meta> \\\n\t\t\t\t\t\t<component id=\"seite1\" class=\"component\"> \\\n\t\t\t\t\t\t\t<properties xmlns:cd=\"http://www.example.com/ns3\"> \\\n\t\t\t\t\t\t\t\t<property name=\"prop1\"> \\\n\t\t\t\t\t\t\t\t\t<thing /> \\\n\t\t\t\t\t\t\t\t\t<value>1</value> \\\n\t\t\t\t\t\t\t\t</property> \\\n\t\t\t\t\t\t\t\t<property name=\"prop2\"> \\\n\t\t\t\t\t\t\t\t\t<thing att=\"something\" /> \\\n\t\t\t\t\t\t\t\t</property> \\\n\t\t\t\t\t\t\t\t<foo_bar>foo</foo_bar> \\\n\t\t\t\t\t\t\t</properties> \\\n\t\t\t\t\t\t</component> \\\n\t\t\t\t\t</meta> \\\n\t\t\t\t</response> \\\n\t\t\t</jsconf> \\\n\t\t</soap:Body> \\\n\t</soap:Envelope>';\n\n\treturn jQuery.parseXML( string );\n};\n\nfireNative = document.createEvent ?\n\tfunction( node, type ) {\n\t\tvar event = document.createEvent(\"HTMLEvents\");\n\t\tevent.initEvent( type, true, true );\n\t\tnode.dispatchEvent( event );\n\t} :\n\tfunction( node, type ) {\n\t\tvar event = document.createEventObject();\n\t\tnode.fireEvent( \"on\" + type, event );\n\t};\n\nfunction testIframeWithCallback( title, fileName, func ) {\n\ttest( title, function() {\n\t\tvar iframe;\n\n\t\tstop();\n\t\twindow.iframeCallback = function() {\n\t\t\tvar self = this,\n\t\t\t\targs = arguments;\n\t\t\tsetTimeout(function() {\n\t\t\t\twindow.iframeCallback = undefined;\n\t\t\t\tiframe.remove();\n\t\t\t\tfunc.apply( self, args );\n\t\t\t\tfunc = function() {};\n\t\t\t\tstart();\n\t\t\t}, 0 );\n\t\t};\n\t\tiframe = jQuery( \"<div/>\" ).css({ position: \"absolute\", width: \"500px\", left: \"-600px\" })\n\t\t\t.append( jQuery( \"<iframe/>\" ).attr( \"src\", url( \"./data/\" + fileName ) ) )\n\t\t\t.appendTo( \"#qunit-fixture\" );\n\t});\n};\nwindow.iframeCallback = undefined;\n\nfunction moduleTeardown() {}\n"
  },
  {
    "path": "flowable-ui-web/modeler/libs/sizzle_1.10.16/test/index.html",
    "content": "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\" dir=\"ltr\" id=\"html\">\n<head>\n\t<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />\n\t<title>Sizzle Test Suite</title>\n\t<link rel=\"Stylesheet\" media=\"screen\" href=\"libs/qunit/qunit.css\" />\n\t<script type=\"text/javascript\" src=\"libs/qunit/qunit.js\"></script>\n\t<script type=\"text/javascript\" src=\"data/testinit.js\"></script>\n\t<script type=\"text/javascript\" src=\"jquery.js\"></script>\n\t<script type=\"text/javascript\" src=\"../dist/sizzle.js\"></script>\n\t<script type=\"text/javascript\" src=\"unit/selector.js\"></script>\n\t<script type=\"text/javascript\" src=\"unit/utilities.js\"></script>\n\t<script type=\"text/javascript\" src=\"unit/extending.js\"></script>\n</head>\n\n<body id=\"body\">\n\t<div id=\"qunit\"></div>\n\n\t<!-- Test HTML -->\n\t<dl id=\"dl\" style=\"position:absolute;top:-32767px;left:-32767px;width:1px\">\n\t<div id=\"qunit-fixture\">\n\t\t<p id=\"firstp\">See <a id=\"simon1\" href=\"http://simon.incutio.com/archive/2003/03/25/#getElementsBySelector\" rel=\"bookmark\">this blog entry</a> for more information.</p>\n\t\t<p id=\"ap\">\n\t\t\tHere are some [links] in a normal paragraph: <a id=\"google\" href=\"http://www.google.com/\" title=\"Google!\">Google</a>,\n\t\t\t<a id=\"groups\" href=\"http://groups.google.com/\" class=\"GROUPS\">Google Groups (Link)</a>.\n\t\t\tThis link has <code id=\"code1\"><a href=\"http://smin\" id=\"anchor1\">class=\"blog\"</a></code>:\n\t\t\t<a href=\"http://diveintomark.org/\" class=\"blog\" hreflang=\"en\" id=\"mark\">diveintomark</a>\n\n\t\t</p>\n\t\t<div id=\"foo\">\n\t\t\t<p id=\"sndp\">Everything inside the red border is inside a div with <code>id=\"foo\"</code>.</p>\n\t\t\t<p lang=\"en\" id=\"en\">This is a normal link: <a id=\"yahoo\" href=\"http://www.yahoo.com/\" class=\"blogTest\">Yahoo</a></p>\n\t\t\t<p id=\"sap\">This link has <code><a href=\"#2\" id=\"anchor2\">class=\"blog\"</a></code>: <a href=\"http://simon.incutio.com/\" class=\"blog link\" id=\"simon\">Simon Willison's Weblog</a></p>\n\n\t\t</div>\n\t\t<div id=\"nothiddendiv\" style=\"height:1px;background:white;\" class=\"nothiddendiv\">\n\t\t\t<div id=\"nothiddendivchild\"></div>\n\t\t</div>\n\t\t<span id=\"name+value\"></span>\n\t\t<p id=\"first\">Try them out:</p>\n\t\t<ul id=\"firstUL\"></ul>\n\t\t<ol id=\"empty\"><!-- comment --></ol>\n\t\t<form id=\"form\" action=\"formaction\">\n\t\t\t<label for=\"action\" id=\"label-for\">Action:</label>\n\t\t\t<input type=\"text\" name=\"action\" value=\"Test\" id=\"text1\" maxlength=\"30\"/>\n\t\t\t<input type=\"text\" name=\"text2\" value=\"Test\" id=\"text2\" disabled=\"disabled\"/>\n\t\t\t<input type=\"radio\" name=\"radio1\" id=\"radio1\" value=\"on\"/>\n\n\t\t\t<input type=\"radio\" name=\"radio2\" id=\"radio2\" checked=\"checked\"/>\n\t\t\t<input type=\"checkbox\" name=\"check\" id=\"check1\" checked=\"checked\"/>\n\t\t\t<input type=\"checkbox\" id=\"check2\" value=\"on\"/>\n\n\t\t\t<input type=\"hidden\" name=\"hidden\" id=\"hidden1\"/>\n\t\t\t<input type=\"text\" style=\"display:none;\" name=\"foo[bar]\" id=\"hidden2\"/>\n\n\t\t\t<input type=\"text\" id=\"name\" name=\"name\" value=\"name\" />\n\t\t\t<input type=\"search\" id=\"search\" name=\"search\" value=\"search\" />\n\n\t\t\t<button id=\"button\" name=\"button\" type=\"button\">Button</button>\n\n\t\t\t<textarea id=\"area1\" maxlength=\"30\">foobar</textarea>\n\n\t\t\t<select name=\"select1\" id=\"select1\">\n\t\t\t\t<option id=\"option1a\" class=\"emptyopt\" value=\"\">Nothing</option>\n\t\t\t\t<option id=\"option1b\" value=\"1\">1</option>\n\t\t\t\t<option id=\"option1c\" value=\"2\">2</option>\n\t\t\t\t<option id=\"option1d\" value=\"3\">3</option>\n\t\t\t</select>\n\t\t\t<select name=\"select2\" id=\"select2\">\n\t\t\t\t<option id=\"option2a\" class=\"emptyopt\" value=\"\">Nothing</option>\n\t\t\t\t<option id=\"option2b\" value=\"1\">1</option>\n\t\t\t\t<option id=\"option2c\" value=\"2\">2</option>\n\t\t\t\t<option id=\"option2d\" selected=\"selected\" value=\"3\">3</option>\n\t\t\t</select>\n\t\t\t<select name=\"select3\" id=\"select3\" multiple=\"multiple\">\n\t\t\t\t<option id=\"option3a\" class=\"emptyopt\" value=\"\">Nothing</option>\n\t\t\t\t<option id=\"option3b\" selected=\"selected\" value=\"1\">1</option>\n\t\t\t\t<option id=\"option3c\" selected=\"selected\" value=\"2\">2</option>\n\t\t\t\t<option id=\"option3d\" value=\"3\">3</option>\n\t\t\t\t<option id=\"option3e\">no value</option>\n\t\t\t</select>\n\t\t\t<select name=\"select4\" id=\"select4\" multiple=\"multiple\">\n\t\t\t\t<optgroup disabled=\"disabled\">\n\t\t\t\t\t<option id=\"option4a\" class=\"emptyopt\" value=\"\">Nothing</option>\n\t\t\t\t\t<option id=\"option4b\" disabled=\"disabled\" selected=\"selected\" value=\"1\">1</option>\n\t\t\t\t\t<option id=\"option4c\" selected=\"selected\" value=\"2\">2</option>\n\t\t\t\t</optgroup>\n\t\t\t\t<option selected=\"selected\" disabled=\"disabled\" id=\"option4d\" value=\"3\">3</option>\n\t\t\t\t<option id=\"option4e\">no value</option>\n\t\t\t</select>\n\t\t\t<select name=\"select5\" id=\"select5\">\n\t\t\t\t<option id=\"option5a\" value=\"3\">1</option>\n\t\t\t\t<option id=\"option5b\" value=\"2\">2</option>\n\t\t\t\t<option id=\"option5c\" value=\"1\">3</option>\n\t\t\t</select>\n\n\t\t\t<object id=\"object1\" codebase=\"stupid\">\n\t\t\t\t<param name=\"p1\" value=\"x1\" />\n\t\t\t\t<param name=\"p2\" value=\"x2\" />\n\t\t\t</object>\n\n\t\t\t<span id=\"台北Táiběi\"></span>\n\t\t\t<span id=\"台北\" lang=\"中文\"></span>\n\t\t\t<span id=\"utf8class1\" class=\"台北Táiběi 台北\"></span>\n\t\t\t<span id=\"utf8class2\" class=\"台北\"></span>\n\t\t\t<span id=\"foo:bar\" class=\"foo:bar\"><span id=\"foo_descendent\"></span></span>\n\t\t\t<span id=\"test.foo[5]bar\" class=\"test.foo[5]bar\"></span>\n\n\t\t\t<foo_bar id=\"foobar\">test element</foo_bar>\n\t\t</form>\n\t\t<b id=\"floatTest\">Float test.</b>\n\t\t<iframe id=\"iframe\" name=\"iframe\"></iframe>\n\t\t<form id=\"lengthtest\">\n\t\t\t<input type=\"text\" id=\"length\" name=\"test\"/>\n\t\t\t<input type=\"text\" id=\"idTest\" name=\"id\"/>\n\t\t</form>\n\t\t<table id=\"table\"></table>\n\n\t\t<form id=\"name-tests\">\n\t\t\t<!-- Inputs with a grouped name attribute. -->\n\t\t\t<input name=\"types[]\" id=\"types_all\" type=\"checkbox\" value=\"all\" />\n\t\t\t<input name=\"types[]\" id=\"types_anime\" type=\"checkbox\" value=\"anime\" />\n\t\t\t<input name=\"types[]\" id=\"types_movie\" type=\"checkbox\" value=\"movie\" />\n\t\t</form>\n\n\t\t<form id=\"testForm\" action=\"#\" method=\"get\">\n\t\t\t<textarea name=\"T3\" rows=\"2\" cols=\"15\">?\nZ</textarea>\n\t\t\t<input type=\"hidden\" name=\"H1\" value=\"x\" />\n\t\t\t<input type=\"hidden\" name=\"H2\" />\n\t\t\t<input name=\"PWD\" type=\"password\" value=\"\" />\n\t\t\t<input name=\"T1\" type=\"text\" />\n\t\t\t<input name=\"T2\" type=\"text\" value=\"YES\" readonly=\"readonly\" />\n\t\t\t<input type=\"checkbox\" name=\"C1\" value=\"1\" />\n\t\t\t<input type=\"checkbox\" name=\"C2\" />\n\t\t\t<input type=\"radio\" name=\"R1\" value=\"1\" />\n\t\t\t<input type=\"radio\" name=\"R1\" value=\"2\" />\n\t\t\t<input type=\"text\" name=\"My Name\" value=\"me\" />\n\t\t\t<input type=\"reset\" name=\"reset\" value=\"NO\" />\n\t\t\t<select name=\"S1\">\n\t\t\t\t<option value=\"abc\">ABC</option>\n\t\t\t\t<option value=\"abc\">ABC</option>\n\t\t\t\t<option value=\"abc\">ABC</option>\n\t\t\t</select>\n\t\t\t<select name=\"S2\" multiple=\"multiple\" size=\"3\">\n\t\t\t\t<option value=\"abc\">ABC</option>\n\t\t\t\t<option value=\"abc\">ABC</option>\n\t\t\t\t<option value=\"abc\">ABC</option>\n\t\t\t</select>\n\t\t\t<select name=\"S3\">\n\t\t\t\t<option selected=\"selected\">YES</option>\n\t\t\t</select>\n\t\t\t<select name=\"S4\">\n\t\t\t\t<option value=\"\" selected=\"selected\">NO</option>\n\t\t\t</select>\n\t\t\t<input type=\"submit\" name=\"sub1\" value=\"NO\" />\n\t\t\t<input type=\"submit\" name=\"sub2\" value=\"NO\" />\n\t\t\t<input type=\"image\" name=\"sub3\" value=\"NO\" />\n\t\t\t<button name=\"sub4\" type=\"submit\" value=\"NO\">NO</button>\n\t\t\t<input name=\"D1\" type=\"text\" value=\"NO\" disabled=\"disabled\" />\n\t\t\t<input type=\"checkbox\" checked=\"checked\" disabled=\"disabled\" name=\"D2\" value=\"NO\" />\n\t\t\t<input type=\"radio\" name=\"D3\" value=\"NO\" checked=\"checked\" disabled=\"disabled\" />\n\t\t\t<select name=\"D4\" disabled=\"disabled\">\n\t\t\t\t<option selected=\"selected\" value=\"NO\">NO</option>\n\t\t\t</select>\n\t\t\t<input id=\"list-test\" type=\"text\" />\n\t\t\t<datalist id=\"datalist\">\n\t\t\t\t<option value=\"option\"></option>\n\t\t\t</datalist>\n\t\t</form>\n\t\t<div id=\"moretests\">\n\t\t\t<form>\n\t\t\t\t<div id=\"checkedtest\" style=\"display:none;\">\n\t\t\t\t\t<input type=\"radio\" name=\"checkedtestradios\" checked=\"checked\"/>\n\t\t\t\t\t<input type=\"radio\" name=\"checkedtestradios\" value=\"on\"/>\n\t\t\t\t\t<input type=\"checkbox\" name=\"checkedtestcheckboxes\" checked=\"checked\"/>\n\t\t\t\t\t<input type=\"checkbox\" name=\"checkedtestcheckboxes\" />\n\t\t\t\t</div>\n\t\t\t</form>\n\t\t\t<div id=\"nonnodes\"><span>hi</span> there <!-- mon ami --></div>\n\t\t\t<div id=\"t2037\">\n\t\t\t\t<div><div class=\"hidden\">hidden</div></div>\n\t\t\t</div>\n\t\t\t<div id=\"t6652\">\n\t\t\t\t<div></div>\n\t\t\t</div>\n\t\t\t<div id=\"t12087\">\n\t\t\t\t<input type=\"hidden\" id=\"el12087\" data-comma=\"0,1\"/>\n\t\t\t</div>\n\t\t\t<div id=\"no-clone-exception\"><object><embed></embed></object></div>\n\t\t\t<div id=\"names-group\">\n\t\t\t\t<span id=\"name-is-example\" name=\"example\"></span>\n\t\t\t\t<span id=\"name-is-div\" name=\"div\"></span>\n\t\t\t</div>\n\t\t\t<script id=\"script-no-src\"></script>\n\t\t\t<script id=\"script-src\" src=\"data/empty.js\"></script>\n\t\t\t<div id=\"id-name-tests\">\n\t\t\t\t<a id=\"tName1ID\" name=\"tName1\"><span></span></a>\n\t\t\t\t<a id=\"tName2ID\" name=\"tName2\"><span></span></a>\n\t\t\t\t<div id=\"tName1\"><span id=\"tName1-span\">C</span></div>\n\t\t\t</div>\n\t\t</div>\n\n\t\t<div id=\"tabindex-tests\">\n\t\t\t<ol id=\"listWithTabIndex\" tabindex=\"5\">\n\t\t\t\t<li id=\"foodWithNegativeTabIndex\" tabindex=\"-1\">Rice</li>\n\t\t\t\t<li id=\"foodNoTabIndex\">Beans</li>\n\t\t\t\t<li>Blinis</li>\n\t\t\t\t<li>Tofu</li>\n\t\t\t</ol>\n\n\t\t\t<div id=\"divWithNoTabIndex\">I'm hungry. I should...</div>\n\t\t\t<span>...</span><a href=\"#\" id=\"linkWithNoTabIndex\">Eat lots of food</a><span>...</span> |\n\t\t\t<span>...</span><a href=\"#\" id=\"linkWithTabIndex\" tabindex=\"2\">Eat a little food</a><span>...</span> |\n\t\t\t<span>...</span><a href=\"#\" id=\"linkWithNegativeTabIndex\" tabindex=\"-1\">Eat no food</a><span>...</span>\n\t\t\t<span>...</span><a id=\"linkWithNoHrefWithNoTabIndex\">Eat a burger</a><span>...</span>\n\t\t\t<span>...</span><a id=\"linkWithNoHrefWithTabIndex\" tabindex=\"1\">Eat some funyuns</a><span>...</span>\n\t\t\t<span>...</span><a id=\"linkWithNoHrefWithNegativeTabIndex\" tabindex=\"-1\">Eat some funyuns</a><span>...</span>\n\t\t</div>\n\n\t\t<div id=\"liveHandlerOrder\">\n\t\t\t<span id=\"liveSpan1\"><a href=\"#\" id=\"liveLink1\"></a></span>\n\t\t\t<span id=\"liveSpan2\"><a href=\"#\" id=\"liveLink2\"></a></span>\n\t\t</div>\n\n\t\t<div id=\"siblingTest\">\n\t\t\t<em id=\"siblingfirst\">1</em>\n\t\t\t<em id=\"siblingnext\">2</em>\n\t\t\t<em id=\"siblingthird\">\n\t\t\t\t<em id=\"siblingchild\">\n\t\t\t\t\t<em id=\"siblinggrandchild\">\n\t\t\t\t\t\t<em id=\"siblinggreatgrandchild\"></em>\n\t\t\t\t\t</em>\n\t\t\t\t</em>\n\t\t\t</em>\n\t\t\t<span id=\"siblingspan\"></span>\n\t\t</div>​\n\t</div>\n\t</dl>\n\t<br id=\"last\"/>\n</body>\n</html>\n"
  },
  {
    "path": "flowable-ui-web/modeler/libs/sizzle_1.10.16/test/jquery.js",
    "content": "/*!\n * jQuery JavaScript Library v1.9.1\n * http://jquery.com/\n *\n * Includes Sizzle.js\n * http://sizzlejs.com/\n *\n * Copyright 2005, 2012 jQuery Foundation, Inc. and other contributors\n * Released under the MIT license\n * http://jquery.org/license\n *\n * Date: 2013-2-4\n */\n(function( window, undefined ) {\n\n// Can't do this because several apps including ASP.NET trace\n// the stack via arguments.caller.callee and Firefox dies if\n// you try to trace through \"use strict\" call chains. (#13335)\n// Support: Firefox 18+\n//\"use strict\";\nvar\n\t// The deferred used on DOM ready\n\treadyList,\n\n\t// A central reference to the root jQuery(document)\n\trootjQuery,\n\n\t// Support: IE<9\n\t// For `typeof node.method` instead of `node.method !== undefined`\n\tcore_strundefined = typeof undefined,\n\n\t// Use the correct document accordingly with window argument (sandbox)\n\tdocument = window.document,\n\tlocation = window.location,\n\n\t// Map over jQuery in case of overwrite\n\t_jQuery = window.jQuery,\n\n\t// Map over the $ in case of overwrite\n\t_$ = window.$,\n\n\t// [[Class]] -> type pairs\n\tclass2type = {},\n\n\t// List of deleted data cache ids, so we can reuse them\n\tcore_deletedIds = [],\n\n\tcore_version = \"1.9.1\",\n\n\t// Save a reference to some core methods\n\tcore_concat = core_deletedIds.concat,\n\tcore_push = core_deletedIds.push,\n\tcore_slice = core_deletedIds.slice,\n\tcore_indexOf = core_deletedIds.indexOf,\n\tcore_toString = class2type.toString,\n\tcore_hasOwn = class2type.hasOwnProperty,\n\tcore_trim = core_version.trim,\n\n\t// Define a local copy of jQuery\n\tjQuery = function( selector, context ) {\n\t\t// The jQuery object is actually just the init constructor 'enhanced'\n\t\treturn new jQuery.fn.init( selector, context, rootjQuery );\n\t},\n\n\t// Used for matching numbers\n\tcore_pnum = /[+-]?(?:\\d*\\.|)\\d+(?:[eE][+-]?\\d+|)/.source,\n\n\t// Used for splitting on whitespace\n\tcore_rnotwhite = /\\S+/g,\n\n\t// Make sure we trim BOM and NBSP (here's looking at you, Safari 5.0 and IE)\n\trtrim = /^[\\s\\uFEFF\\xA0]+|[\\s\\uFEFF\\xA0]+$/g,\n\n\t// A simple way to check for HTML strings\n\t// Prioritize #id over <tag> to avoid XSS via location.hash (#9521)\n\t// Strict HTML recognition (#11290: must start with <)\n\trquickExpr = /^(?:(<[\\w\\W]+>)[^>]*|#([\\w-]*))$/,\n\n\t// Match a standalone tag\n\trsingleTag = /^<(\\w+)\\s*\\/?>(?:<\\/\\1>|)$/,\n\n\t// JSON RegExp\n\trvalidchars = /^[\\],:{}\\s]*$/,\n\trvalidbraces = /(?:^|:|,)(?:\\s*\\[)+/g,\n\trvalidescape = /\\\\(?:[\"\\\\\\/bfnrt]|u[\\da-fA-F]{4})/g,\n\trvalidtokens = /\"[^\"\\\\\\r\\n]*\"|true|false|null|-?(?:\\d+\\.|)\\d+(?:[eE][+-]?\\d+|)/g,\n\n\t// Matches dashed string for camelizing\n\trmsPrefix = /^-ms-/,\n\trdashAlpha = /-([\\da-z])/gi,\n\n\t// Used by jQuery.camelCase as callback to replace()\n\tfcamelCase = function( all, letter ) {\n\t\treturn letter.toUpperCase();\n\t},\n\n\t// The ready event handler\n\tcompleted = function( event ) {\n\n\t\t// readyState === \"complete\" is good enough for us to call the dom ready in oldIE\n\t\tif ( document.addEventListener || event.type === \"load\" || document.readyState === \"complete\" ) {\n\t\t\tdetach();\n\t\t\tjQuery.ready();\n\t\t}\n\t},\n\t// Clean-up method for dom ready events\n\tdetach = function() {\n\t\tif ( document.addEventListener ) {\n\t\t\tdocument.removeEventListener( \"DOMContentLoaded\", completed, false );\n\t\t\twindow.removeEventListener( \"load\", completed, false );\n\n\t\t} else {\n\t\t\tdocument.detachEvent( \"onreadystatechange\", completed );\n\t\t\twindow.detachEvent( \"onload\", completed );\n\t\t}\n\t};\n\njQuery.fn = jQuery.prototype = {\n\t// The current version of jQuery being used\n\tjquery: core_version,\n\n\tconstructor: jQuery,\n\tinit: function( selector, context, rootjQuery ) {\n\t\tvar match, elem;\n\n\t\t// HANDLE: $(\"\"), $(null), $(undefined), $(false)\n\t\tif ( !selector ) {\n\t\t\treturn this;\n\t\t}\n\n\t\t// Handle HTML strings\n\t\tif ( typeof selector === \"string\" ) {\n\t\t\tif ( selector.charAt(0) === \"<\" && selector.charAt( selector.length - 1 ) === \">\" && selector.length >= 3 ) {\n\t\t\t\t// Assume that strings that start and end with <> are HTML and skip the regex check\n\t\t\t\tmatch = [ null, selector, null ];\n\n\t\t\t} else {\n\t\t\t\tmatch = rquickExpr.exec( selector );\n\t\t\t}\n\n\t\t\t// Match html or make sure no context is specified for #id\n\t\t\tif ( match && (match[1] || !context) ) {\n\n\t\t\t\t// HANDLE: $(html) -> $(array)\n\t\t\t\tif ( match[1] ) {\n\t\t\t\t\tcontext = context instanceof jQuery ? context[0] : context;\n\n\t\t\t\t\t// scripts is true for back-compat\n\t\t\t\t\tjQuery.merge( this, jQuery.parseHTML(\n\t\t\t\t\t\tmatch[1],\n\t\t\t\t\t\tcontext && context.nodeType ? context.ownerDocument || context : document,\n\t\t\t\t\t\ttrue\n\t\t\t\t\t) );\n\n\t\t\t\t\t// HANDLE: $(html, props)\n\t\t\t\t\tif ( rsingleTag.test( match[1] ) && jQuery.isPlainObject( context ) ) {\n\t\t\t\t\t\tfor ( match in context ) {\n\t\t\t\t\t\t\t// Properties of context are called as methods if possible\n\t\t\t\t\t\t\tif ( jQuery.isFunction( this[ match ] ) ) {\n\t\t\t\t\t\t\t\tthis[ match ]( context[ match ] );\n\n\t\t\t\t\t\t\t// ...and otherwise set as attributes\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tthis.attr( match, context[ match ] );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\treturn this;\n\n\t\t\t\t// HANDLE: $(#id)\n\t\t\t\t} else {\n\t\t\t\t\telem = document.getElementById( match[2] );\n\n\t\t\t\t\t// Check parentNode to catch when Blackberry 4.6 returns\n\t\t\t\t\t// nodes that are no longer in the document #6963\n\t\t\t\t\tif ( elem && elem.parentNode ) {\n\t\t\t\t\t\t// Handle the case where IE and Opera return items\n\t\t\t\t\t\t// by name instead of ID\n\t\t\t\t\t\tif ( elem.id !== match[2] ) {\n\t\t\t\t\t\t\treturn rootjQuery.find( selector );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Otherwise, we inject the element directly into the jQuery object\n\t\t\t\t\t\tthis.length = 1;\n\t\t\t\t\t\tthis[0] = elem;\n\t\t\t\t\t}\n\n\t\t\t\t\tthis.context = document;\n\t\t\t\t\tthis.selector = selector;\n\t\t\t\t\treturn this;\n\t\t\t\t}\n\n\t\t\t// HANDLE: $(expr, $(...))\n\t\t\t} else if ( !context || context.jquery ) {\n\t\t\t\treturn ( context || rootjQuery ).find( selector );\n\n\t\t\t// HANDLE: $(expr, context)\n\t\t\t// (which is just equivalent to: $(context).find(expr)\n\t\t\t} else {\n\t\t\t\treturn this.constructor( context ).find( selector );\n\t\t\t}\n\n\t\t// HANDLE: $(DOMElement)\n\t\t} else if ( selector.nodeType ) {\n\t\t\tthis.context = this[0] = selector;\n\t\t\tthis.length = 1;\n\t\t\treturn this;\n\n\t\t// HANDLE: $(function)\n\t\t// Shortcut for document ready\n\t\t} else if ( jQuery.isFunction( selector ) ) {\n\t\t\treturn rootjQuery.ready( selector );\n\t\t}\n\n\t\tif ( selector.selector !== undefined ) {\n\t\t\tthis.selector = selector.selector;\n\t\t\tthis.context = selector.context;\n\t\t}\n\n\t\treturn jQuery.makeArray( selector, this );\n\t},\n\n\t// Start with an empty selector\n\tselector: \"\",\n\n\t// The default length of a jQuery object is 0\n\tlength: 0,\n\n\t// The number of elements contained in the matched element set\n\tsize: function() {\n\t\treturn this.length;\n\t},\n\n\ttoArray: function() {\n\t\treturn core_slice.call( this );\n\t},\n\n\t// Get the Nth element in the matched element set OR\n\t// Get the whole matched element set as a clean array\n\tget: function( num ) {\n\t\treturn num == null ?\n\n\t\t\t// Return a 'clean' array\n\t\t\tthis.toArray() :\n\n\t\t\t// Return just the object\n\t\t\t( num < 0 ? this[ this.length + num ] : this[ num ] );\n\t},\n\n\t// Take an array of elements and push it onto the stack\n\t// (returning the new matched element set)\n\tpushStack: function( elems ) {\n\n\t\t// Build a new jQuery matched element set\n\t\tvar ret = jQuery.merge( this.constructor(), elems );\n\n\t\t// Add the old object onto the stack (as a reference)\n\t\tret.prevObject = this;\n\t\tret.context = this.context;\n\n\t\t// Return the newly-formed element set\n\t\treturn ret;\n\t},\n\n\t// Execute a callback for every element in the matched set.\n\t// (You can seed the arguments with an array of args, but this is\n\t// only used internally.)\n\teach: function( callback, args ) {\n\t\treturn jQuery.each( this, callback, args );\n\t},\n\n\tready: function( fn ) {\n\t\t// Add the callback\n\t\tjQuery.ready.promise().done( fn );\n\n\t\treturn this;\n\t},\n\n\tslice: function() {\n\t\treturn this.pushStack( core_slice.apply( this, arguments ) );\n\t},\n\n\tfirst: function() {\n\t\treturn this.eq( 0 );\n\t},\n\n\tlast: function() {\n\t\treturn this.eq( -1 );\n\t},\n\n\teq: function( i ) {\n\t\tvar len = this.length,\n\t\t\tj = +i + ( i < 0 ? len : 0 );\n\t\treturn this.pushStack( j >= 0 && j < len ? [ this[j] ] : [] );\n\t},\n\n\tmap: function( callback ) {\n\t\treturn this.pushStack( jQuery.map(this, function( elem, i ) {\n\t\t\treturn callback.call( elem, i, elem );\n\t\t}));\n\t},\n\n\tend: function() {\n\t\treturn this.prevObject || this.constructor(null);\n\t},\n\n\t// For internal use only.\n\t// Behaves like an Array's method, not like a jQuery method.\n\tpush: core_push,\n\tsort: [].sort,\n\tsplice: [].splice\n};\n\n// Give the init function the jQuery prototype for later instantiation\njQuery.fn.init.prototype = jQuery.fn;\n\njQuery.extend = jQuery.fn.extend = function() {\n\tvar src, copyIsArray, copy, name, options, clone,\n\t\ttarget = arguments[0] || {},\n\t\ti = 1,\n\t\tlength = arguments.length,\n\t\tdeep = false;\n\n\t// Handle a deep copy situation\n\tif ( typeof target === \"boolean\" ) {\n\t\tdeep = target;\n\t\ttarget = arguments[1] || {};\n\t\t// skip the boolean and the target\n\t\ti = 2;\n\t}\n\n\t// Handle case when target is a string or something (possible in deep copy)\n\tif ( typeof target !== \"object\" && !jQuery.isFunction(target) ) {\n\t\ttarget = {};\n\t}\n\n\t// extend jQuery itself if only one argument is passed\n\tif ( length === i ) {\n\t\ttarget = this;\n\t\t--i;\n\t}\n\n\tfor ( ; i < length; i++ ) {\n\t\t// Only deal with non-null/undefined values\n\t\tif ( (options = arguments[ i ]) != null ) {\n\t\t\t// Extend the base object\n\t\t\tfor ( name in options ) {\n\t\t\t\tsrc = target[ name ];\n\t\t\t\tcopy = options[ name ];\n\n\t\t\t\t// Prevent never-ending loop\n\t\t\t\tif ( target === copy ) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\t// Recurse if we're merging plain objects or arrays\n\t\t\t\tif ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {\n\t\t\t\t\tif ( copyIsArray ) {\n\t\t\t\t\t\tcopyIsArray = false;\n\t\t\t\t\t\tclone = src && jQuery.isArray(src) ? src : [];\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\tclone = src && jQuery.isPlainObject(src) ? src : {};\n\t\t\t\t\t}\n\n\t\t\t\t\t// Never move original objects, clone them\n\t\t\t\t\ttarget[ name ] = jQuery.extend( deep, clone, copy );\n\n\t\t\t\t// Don't bring in undefined values\n\t\t\t\t} else if ( copy !== undefined ) {\n\t\t\t\t\ttarget[ name ] = copy;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Return the modified object\n\treturn target;\n};\n\njQuery.extend({\n\tnoConflict: function( deep ) {\n\t\tif ( window.$ === jQuery ) {\n\t\t\twindow.$ = _$;\n\t\t}\n\n\t\tif ( deep && window.jQuery === jQuery ) {\n\t\t\twindow.jQuery = _jQuery;\n\t\t}\n\n\t\treturn jQuery;\n\t},\n\n\t// Is the DOM ready to be used? Set to true once it occurs.\n\tisReady: false,\n\n\t// A counter to track how many items to wait for before\n\t// the ready event fires. See #6781\n\treadyWait: 1,\n\n\t// Hold (or release) the ready event\n\tholdReady: function( hold ) {\n\t\tif ( hold ) {\n\t\t\tjQuery.readyWait++;\n\t\t} else {\n\t\t\tjQuery.ready( true );\n\t\t}\n\t},\n\n\t// Handle when the DOM is ready\n\tready: function( wait ) {\n\n\t\t// Abort if there are pending holds or we're already ready\n\t\tif ( wait === true ? --jQuery.readyWait : jQuery.isReady ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).\n\t\tif ( !document.body ) {\n\t\t\treturn setTimeout( jQuery.ready );\n\t\t}\n\n\t\t// Remember that the DOM is ready\n\t\tjQuery.isReady = true;\n\n\t\t// If a normal DOM Ready event fired, decrement, and wait if need be\n\t\tif ( wait !== true && --jQuery.readyWait > 0 ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// If there are functions bound, to execute\n\t\treadyList.resolveWith( document, [ jQuery ] );\n\n\t\t// Trigger any bound ready events\n\t\tif ( jQuery.fn.trigger ) {\n\t\t\tjQuery( document ).trigger(\"ready\").off(\"ready\");\n\t\t}\n\t},\n\n\t// See test/unit/core.js for details concerning isFunction.\n\t// Since version 1.3, DOM methods and functions like alert\n\t// aren't supported. They return false on IE (#2968).\n\tisFunction: function( obj ) {\n\t\treturn jQuery.type(obj) === \"function\";\n\t},\n\n\tisArray: Array.isArray || function( obj ) {\n\t\treturn jQuery.type(obj) === \"array\";\n\t},\n\n\tisWindow: function( obj ) {\n\t\treturn obj != null && obj == obj.window;\n\t},\n\n\tisNumeric: function( obj ) {\n\t\treturn !isNaN( parseFloat(obj) ) && isFinite( obj );\n\t},\n\n\ttype: function( obj ) {\n\t\tif ( obj == null ) {\n\t\t\treturn String( obj );\n\t\t}\n\t\treturn typeof obj === \"object\" || typeof obj === \"function\" ?\n\t\t\tclass2type[ core_toString.call(obj) ] || \"object\" :\n\t\t\ttypeof obj;\n\t},\n\n\tisPlainObject: function( obj ) {\n\t\t// Must be an Object.\n\t\t// Because of IE, we also have to check the presence of the constructor property.\n\t\t// Make sure that DOM nodes and window objects don't pass through, as well\n\t\tif ( !obj || jQuery.type(obj) !== \"object\" || obj.nodeType || jQuery.isWindow( obj ) ) {\n\t\t\treturn false;\n\t\t}\n\n\t\ttry {\n\t\t\t// Not own constructor property must be Object\n\t\t\tif ( obj.constructor &&\n\t\t\t\t!core_hasOwn.call(obj, \"constructor\") &&\n\t\t\t\t!core_hasOwn.call(obj.constructor.prototype, \"isPrototypeOf\") ) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t} catch ( e ) {\n\t\t\t// IE8,9 Will throw exceptions on certain host objects #9897\n\t\t\treturn false;\n\t\t}\n\n\t\t// Own properties are enumerated firstly, so to speed up,\n\t\t// if last one is own, then all properties are own.\n\n\t\tvar key;\n\t\tfor ( key in obj ) {}\n\n\t\treturn key === undefined || core_hasOwn.call( obj, key );\n\t},\n\n\tisEmptyObject: function( obj ) {\n\t\tvar name;\n\t\tfor ( name in obj ) {\n\t\t\treturn false;\n\t\t}\n\t\treturn true;\n\t},\n\n\terror: function( msg ) {\n\t\tthrow new Error( msg );\n\t},\n\n\t// data: string of html\n\t// context (optional): If specified, the fragment will be created in this context, defaults to document\n\t// keepScripts (optional): If true, will include scripts passed in the html string\n\tparseHTML: function( data, context, keepScripts ) {\n\t\tif ( !data || typeof data !== \"string\" ) {\n\t\t\treturn null;\n\t\t}\n\t\tif ( typeof context === \"boolean\" ) {\n\t\t\tkeepScripts = context;\n\t\t\tcontext = false;\n\t\t}\n\t\tcontext = context || document;\n\n\t\tvar parsed = rsingleTag.exec( data ),\n\t\t\tscripts = !keepScripts && [];\n\n\t\t// Single tag\n\t\tif ( parsed ) {\n\t\t\treturn [ context.createElement( parsed[1] ) ];\n\t\t}\n\n\t\tparsed = jQuery.buildFragment( [ data ], context, scripts );\n\t\tif ( scripts ) {\n\t\t\tjQuery( scripts ).remove();\n\t\t}\n\t\treturn jQuery.merge( [], parsed.childNodes );\n\t},\n\n\tparseJSON: function( data ) {\n\t\t// Attempt to parse using the native JSON parser first\n\t\tif ( window.JSON && window.JSON.parse ) {\n\t\t\treturn window.JSON.parse( data );\n\t\t}\n\n\t\tif ( data === null ) {\n\t\t\treturn data;\n\t\t}\n\n\t\tif ( typeof data === \"string\" ) {\n\n\t\t\t// Make sure leading/trailing whitespace is removed (IE can't handle it)\n\t\t\tdata = jQuery.trim( data );\n\n\t\t\tif ( data ) {\n\t\t\t\t// Make sure the incoming data is actual JSON\n\t\t\t\t// Logic borrowed from http://json.org/json2.js\n\t\t\t\tif ( rvalidchars.test( data.replace( rvalidescape, \"@\" )\n\t\t\t\t\t.replace( rvalidtokens, \"]\" )\n\t\t\t\t\t.replace( rvalidbraces, \"\")) ) {\n\n\t\t\t\t\treturn ( new Function( \"return \" + data ) )();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tjQuery.error( \"Invalid JSON: \" + data );\n\t},\n\n\t// Cross-browser xml parsing\n\tparseXML: function( data ) {\n\t\tvar xml, tmp;\n\t\tif ( !data || typeof data !== \"string\" ) {\n\t\t\treturn null;\n\t\t}\n\t\ttry {\n\t\t\tif ( window.DOMParser ) { // Standard\n\t\t\t\ttmp = new DOMParser();\n\t\t\t\txml = tmp.parseFromString( data , \"text/xml\" );\n\t\t\t} else { // IE\n\t\t\t\txml = new ActiveXObject( \"Microsoft.XMLDOM\" );\n\t\t\t\txml.async = \"false\";\n\t\t\t\txml.loadXML( data );\n\t\t\t}\n\t\t} catch( e ) {\n\t\t\txml = undefined;\n\t\t}\n\t\tif ( !xml || !xml.documentElement || xml.getElementsByTagName( \"parsererror\" ).length ) {\n\t\t\tjQuery.error( \"Invalid XML: \" + data );\n\t\t}\n\t\treturn xml;\n\t},\n\n\tnoop: function() {},\n\n\t// Evaluates a script in a global context\n\t// Workarounds based on findings by Jim Driscoll\n\t// http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context\n\tglobalEval: function( data ) {\n\t\tif ( data && jQuery.trim( data ) ) {\n\t\t\t// We use execScript on Internet Explorer\n\t\t\t// We use an anonymous function so that context is window\n\t\t\t// rather than jQuery in Firefox\n\t\t\t( window.execScript || function( data ) {\n\t\t\t\twindow[ \"eval\" ].call( window, data );\n\t\t\t} )( data );\n\t\t}\n\t},\n\n\t// Convert dashed to camelCase; used by the css and data modules\n\t// Microsoft forgot to hump their vendor prefix (#9572)\n\tcamelCase: function( string ) {\n\t\treturn string.replace( rmsPrefix, \"ms-\" ).replace( rdashAlpha, fcamelCase );\n\t},\n\n\tnodeName: function( elem, name ) {\n\t\treturn elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase();\n\t},\n\n\t// args is for internal usage only\n\teach: function( obj, callback, args ) {\n\t\tvar value,\n\t\t\ti = 0,\n\t\t\tlength = obj.length,\n\t\t\tisArray = isArraylike( obj );\n\n\t\tif ( args ) {\n\t\t\tif ( isArray ) {\n\t\t\t\tfor ( ; i < length; i++ ) {\n\t\t\t\t\tvalue = callback.apply( obj[ i ], args );\n\n\t\t\t\t\tif ( value === false ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tfor ( i in obj ) {\n\t\t\t\t\tvalue = callback.apply( obj[ i ], args );\n\n\t\t\t\t\tif ( value === false ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t// A special, fast, case for the most common use of each\n\t\t} else {\n\t\t\tif ( isArray ) {\n\t\t\t\tfor ( ; i < length; i++ ) {\n\t\t\t\t\tvalue = callback.call( obj[ i ], i, obj[ i ] );\n\n\t\t\t\t\tif ( value === false ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tfor ( i in obj ) {\n\t\t\t\t\tvalue = callback.call( obj[ i ], i, obj[ i ] );\n\n\t\t\t\t\tif ( value === false ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn obj;\n\t},\n\n\t// Use native String.trim function wherever possible\n\ttrim: core_trim && !core_trim.call(\"\\uFEFF\\xA0\") ?\n\t\tfunction( text ) {\n\t\t\treturn text == null ?\n\t\t\t\t\"\" :\n\t\t\t\tcore_trim.call( text );\n\t\t} :\n\n\t\t// Otherwise use our own trimming functionality\n\t\tfunction( text ) {\n\t\t\treturn text == null ?\n\t\t\t\t\"\" :\n\t\t\t\t( text + \"\" ).replace( rtrim, \"\" );\n\t\t},\n\n\t// results is for internal usage only\n\tmakeArray: function( arr, results ) {\n\t\tvar ret = results || [];\n\n\t\tif ( arr != null ) {\n\t\t\tif ( isArraylike( Object(arr) ) ) {\n\t\t\t\tjQuery.merge( ret,\n\t\t\t\t\ttypeof arr === \"string\" ?\n\t\t\t\t\t[ arr ] : arr\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\tcore_push.call( ret, arr );\n\t\t\t}\n\t\t}\n\n\t\treturn ret;\n\t},\n\n\tinArray: function( elem, arr, i ) {\n\t\tvar len;\n\n\t\tif ( arr ) {\n\t\t\tif ( core_indexOf ) {\n\t\t\t\treturn core_indexOf.call( arr, elem, i );\n\t\t\t}\n\n\t\t\tlen = arr.length;\n\t\t\ti = i ? i < 0 ? Math.max( 0, len + i ) : i : 0;\n\n\t\t\tfor ( ; i < len; i++ ) {\n\t\t\t\t// Skip accessing in sparse arrays\n\t\t\t\tif ( i in arr && arr[ i ] === elem ) {\n\t\t\t\t\treturn i;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn -1;\n\t},\n\n\tmerge: function( first, second ) {\n\t\tvar l = second.length,\n\t\t\ti = first.length,\n\t\t\tj = 0;\n\n\t\tif ( typeof l === \"number\" ) {\n\t\t\tfor ( ; j < l; j++ ) {\n\t\t\t\tfirst[ i++ ] = second[ j ];\n\t\t\t}\n\t\t} else {\n\t\t\twhile ( second[j] !== undefined ) {\n\t\t\t\tfirst[ i++ ] = second[ j++ ];\n\t\t\t}\n\t\t}\n\n\t\tfirst.length = i;\n\n\t\treturn first;\n\t},\n\n\tgrep: function( elems, callback, inv ) {\n\t\tvar retVal,\n\t\t\tret = [],\n\t\t\ti = 0,\n\t\t\tlength = elems.length;\n\t\tinv = !!inv;\n\n\t\t// Go through the array, only saving the items\n\t\t// that pass the validator function\n\t\tfor ( ; i < length; i++ ) {\n\t\t\tretVal = !!callback( elems[ i ], i );\n\t\t\tif ( inv !== retVal ) {\n\t\t\t\tret.push( elems[ i ] );\n\t\t\t}\n\t\t}\n\n\t\treturn ret;\n\t},\n\n\t// arg is for internal usage only\n\tmap: function( elems, callback, arg ) {\n\t\tvar value,\n\t\t\ti = 0,\n\t\t\tlength = elems.length,\n\t\t\tisArray = isArraylike( elems ),\n\t\t\tret = [];\n\n\t\t// Go through the array, translating each of the items to their\n\t\tif ( isArray ) {\n\t\t\tfor ( ; i < length; i++ ) {\n\t\t\t\tvalue = callback( elems[ i ], i, arg );\n\n\t\t\t\tif ( value != null ) {\n\t\t\t\t\tret[ ret.length ] = value;\n\t\t\t\t}\n\t\t\t}\n\n\t\t// Go through every key on the object,\n\t\t} else {\n\t\t\tfor ( i in elems ) {\n\t\t\t\tvalue = callback( elems[ i ], i, arg );\n\n\t\t\t\tif ( value != null ) {\n\t\t\t\t\tret[ ret.length ] = value;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Flatten any nested arrays\n\t\treturn core_concat.apply( [], ret );\n\t},\n\n\t// A global GUID counter for objects\n\tguid: 1,\n\n\t// Bind a function to a context, optionally partially applying any\n\t// arguments.\n\tproxy: function( fn, context ) {\n\t\tvar args, proxy, tmp;\n\n\t\tif ( typeof context === \"string\" ) {\n\t\t\ttmp = fn[ context ];\n\t\t\tcontext = fn;\n\t\t\tfn = tmp;\n\t\t}\n\n\t\t// Quick check to determine if target is callable, in the spec\n\t\t// this throws a TypeError, but we will just return undefined.\n\t\tif ( !jQuery.isFunction( fn ) ) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\t// Simulated bind\n\t\targs = core_slice.call( arguments, 2 );\n\t\tproxy = function() {\n\t\t\treturn fn.apply( context || this, args.concat( core_slice.call( arguments ) ) );\n\t\t};\n\n\t\t// Set the guid of unique handler to the same of original handler, so it can be removed\n\t\tproxy.guid = fn.guid = fn.guid || jQuery.guid++;\n\n\t\treturn proxy;\n\t},\n\n\t// Multifunctional method to get and set values of a collection\n\t// The value/s can optionally be executed if it's a function\n\taccess: function( elems, fn, key, value, chainable, emptyGet, raw ) {\n\t\tvar i = 0,\n\t\t\tlength = elems.length,\n\t\t\tbulk = key == null;\n\n\t\t// Sets many values\n\t\tif ( jQuery.type( key ) === \"object\" ) {\n\t\t\tchainable = true;\n\t\t\tfor ( i in key ) {\n\t\t\t\tjQuery.access( elems, fn, i, key[i], true, emptyGet, raw );\n\t\t\t}\n\n\t\t// Sets one value\n\t\t} else if ( value !== undefined ) {\n\t\t\tchainable = true;\n\n\t\t\tif ( !jQuery.isFunction( value ) ) {\n\t\t\t\traw = true;\n\t\t\t}\n\n\t\t\tif ( bulk ) {\n\t\t\t\t// Bulk operations run against the entire set\n\t\t\t\tif ( raw ) {\n\t\t\t\t\tfn.call( elems, value );\n\t\t\t\t\tfn = null;\n\n\t\t\t\t// ...except when executing function values\n\t\t\t\t} else {\n\t\t\t\t\tbulk = fn;\n\t\t\t\t\tfn = function( elem, key, value ) {\n\t\t\t\t\t\treturn bulk.call( jQuery( elem ), value );\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( fn ) {\n\t\t\t\tfor ( ; i < length; i++ ) {\n\t\t\t\t\tfn( elems[i], key, raw ? value : value.call( elems[i], i, fn( elems[i], key ) ) );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn chainable ?\n\t\t\telems :\n\n\t\t\t// Gets\n\t\t\tbulk ?\n\t\t\t\tfn.call( elems ) :\n\t\t\t\tlength ? fn( elems[0], key ) : emptyGet;\n\t},\n\n\tnow: function() {\n\t\treturn ( new Date() ).getTime();\n\t}\n});\n\njQuery.ready.promise = function( obj ) {\n\tif ( !readyList ) {\n\n\t\treadyList = jQuery.Deferred();\n\n\t\t// Catch cases where $(document).ready() is called after the browser event has already occurred.\n\t\t// we once tried to use readyState \"interactive\" here, but it caused issues like the one\n\t\t// discovered by ChrisS here: http://bugs.jquery.com/ticket/12282#comment:15\n\t\tif ( document.readyState === \"complete\" ) {\n\t\t\t// Handle it asynchronously to allow scripts the opportunity to delay ready\n\t\t\tsetTimeout( jQuery.ready );\n\n\t\t// Standards-based browsers support DOMContentLoaded\n\t\t} else if ( document.addEventListener ) {\n\t\t\t// Use the handy event callback\n\t\t\tdocument.addEventListener( \"DOMContentLoaded\", completed, false );\n\n\t\t\t// A fallback to window.onload, that will always work\n\t\t\twindow.addEventListener( \"load\", completed, false );\n\n\t\t// If IE event model is used\n\t\t} else {\n\t\t\t// Ensure firing before onload, maybe late but safe also for iframes\n\t\t\tdocument.attachEvent( \"onreadystatechange\", completed );\n\n\t\t\t// A fallback to window.onload, that will always work\n\t\t\twindow.attachEvent( \"onload\", completed );\n\n\t\t\t// If IE and not a frame\n\t\t\t// continually check to see if the document is ready\n\t\t\tvar top = false;\n\n\t\t\ttry {\n\t\t\t\ttop = window.frameElement == null && document.documentElement;\n\t\t\t} catch(e) {}\n\n\t\t\tif ( top && top.doScroll ) {\n\t\t\t\t(function doScrollCheck() {\n\t\t\t\t\tif ( !jQuery.isReady ) {\n\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t// Use the trick by Diego Perini\n\t\t\t\t\t\t\t// http://javascript.nwbox.com/IEContentLoaded/\n\t\t\t\t\t\t\ttop.doScroll(\"left\");\n\t\t\t\t\t\t} catch(e) {\n\t\t\t\t\t\t\treturn setTimeout( doScrollCheck, 50 );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// detach all dom ready events\n\t\t\t\t\t\tdetach();\n\n\t\t\t\t\t\t// and execute any waiting functions\n\t\t\t\t\t\tjQuery.ready();\n\t\t\t\t\t}\n\t\t\t\t})();\n\t\t\t}\n\t\t}\n\t}\n\treturn readyList.promise( obj );\n};\n\n// Populate the class2type map\njQuery.each(\"Boolean Number String Function Array Date RegExp Object Error\".split(\" \"), function(i, name) {\n\tclass2type[ \"[object \" + name + \"]\" ] = name.toLowerCase();\n});\n\nfunction isArraylike( obj ) {\n\tvar length = obj.length,\n\t\ttype = jQuery.type( obj );\n\n\tif ( jQuery.isWindow( obj ) ) {\n\t\treturn false;\n\t}\n\n\tif ( obj.nodeType === 1 && length ) {\n\t\treturn true;\n\t}\n\n\treturn type === \"array\" || type !== \"function\" &&\n\t\t( length === 0 ||\n\t\ttypeof length === \"number\" && length > 0 && ( length - 1 ) in obj );\n}\n\n// All jQuery objects should point back to these\nrootjQuery = jQuery(document);\n// String to Object options format cache\nvar optionsCache = {};\n\n// Convert String-formatted options into Object-formatted ones and store in cache\nfunction createOptions( options ) {\n\tvar object = optionsCache[ options ] = {};\n\tjQuery.each( options.match( core_rnotwhite ) || [], function( _, flag ) {\n\t\tobject[ flag ] = true;\n\t});\n\treturn object;\n}\n\n/*\n * Create a callback list using the following parameters:\n *\n *\toptions: an optional list of space-separated options that will change how\n *\t\t\tthe callback list behaves or a more traditional option object\n *\n * By default a callback list will act like an event callback list and can be\n * \"fired\" multiple times.\n *\n * Possible options:\n *\n *\tonce:\t\t\twill ensure the callback list can only be fired once (like a Deferred)\n *\n *\tmemory:\t\t\twill keep track of previous values and will call any callback added\n *\t\t\t\t\tafter the list has been fired right away with the latest \"memorized\"\n *\t\t\t\t\tvalues (like a Deferred)\n *\n *\tunique:\t\t\twill ensure a callback can only be added once (no duplicate in the list)\n *\n *\tstopOnFalse:\tinterrupt callings when a callback returns false\n *\n */\njQuery.Callbacks = function( options ) {\n\n\t// Convert options from String-formatted to Object-formatted if needed\n\t// (we check in cache first)\n\toptions = typeof options === \"string\" ?\n\t\t( optionsCache[ options ] || createOptions( options ) ) :\n\t\tjQuery.extend( {}, options );\n\n\tvar // Flag to know if list is currently firing\n\t\tfiring,\n\t\t// Last fire value (for non-forgettable lists)\n\t\tmemory,\n\t\t// Flag to know if list was already fired\n\t\tfired,\n\t\t// End of the loop when firing\n\t\tfiringLength,\n\t\t// Index of currently firing callback (modified by remove if needed)\n\t\tfiringIndex,\n\t\t// First callback to fire (used internally by add and fireWith)\n\t\tfiringStart,\n\t\t// Actual callback list\n\t\tlist = [],\n\t\t// Stack of fire calls for repeatable lists\n\t\tstack = !options.once && [],\n\t\t// Fire callbacks\n\t\tfire = function( data ) {\n\t\t\tmemory = options.memory && data;\n\t\t\tfired = true;\n\t\t\tfiringIndex = firingStart || 0;\n\t\t\tfiringStart = 0;\n\t\t\tfiringLength = list.length;\n\t\t\tfiring = true;\n\t\t\tfor ( ; list && firingIndex < firingLength; firingIndex++ ) {\n\t\t\t\tif ( list[ firingIndex ].apply( data[ 0 ], data[ 1 ] ) === false && options.stopOnFalse ) {\n\t\t\t\t\tmemory = false; // To prevent further calls using add\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tfiring = false;\n\t\t\tif ( list ) {\n\t\t\t\tif ( stack ) {\n\t\t\t\t\tif ( stack.length ) {\n\t\t\t\t\t\tfire( stack.shift() );\n\t\t\t\t\t}\n\t\t\t\t} else if ( memory ) {\n\t\t\t\t\tlist = [];\n\t\t\t\t} else {\n\t\t\t\t\tself.disable();\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t// Actual Callbacks object\n\t\tself = {\n\t\t\t// Add a callback or a collection of callbacks to the list\n\t\t\tadd: function() {\n\t\t\t\tif ( list ) {\n\t\t\t\t\t// First, we save the current length\n\t\t\t\t\tvar start = list.length;\n\t\t\t\t\t(function add( args ) {\n\t\t\t\t\t\tjQuery.each( args, function( _, arg ) {\n\t\t\t\t\t\t\tvar type = jQuery.type( arg );\n\t\t\t\t\t\t\tif ( type === \"function\" ) {\n\t\t\t\t\t\t\t\tif ( !options.unique || !self.has( arg ) ) {\n\t\t\t\t\t\t\t\t\tlist.push( arg );\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} else if ( arg && arg.length && type !== \"string\" ) {\n\t\t\t\t\t\t\t\t// Inspect recursively\n\t\t\t\t\t\t\t\tadd( arg );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t});\n\t\t\t\t\t})( arguments );\n\t\t\t\t\t// Do we need to add the callbacks to the\n\t\t\t\t\t// current firing batch?\n\t\t\t\t\tif ( firing ) {\n\t\t\t\t\t\tfiringLength = list.length;\n\t\t\t\t\t// With memory, if we're not firing then\n\t\t\t\t\t// we should call right away\n\t\t\t\t\t} else if ( memory ) {\n\t\t\t\t\t\tfiringStart = start;\n\t\t\t\t\t\tfire( memory );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Remove a callback from the list\n\t\t\tremove: function() {\n\t\t\t\tif ( list ) {\n\t\t\t\t\tjQuery.each( arguments, function( _, arg ) {\n\t\t\t\t\t\tvar index;\n\t\t\t\t\t\twhile( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) {\n\t\t\t\t\t\t\tlist.splice( index, 1 );\n\t\t\t\t\t\t\t// Handle firing indexes\n\t\t\t\t\t\t\tif ( firing ) {\n\t\t\t\t\t\t\t\tif ( index <= firingLength ) {\n\t\t\t\t\t\t\t\t\tfiringLength--;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif ( index <= firingIndex ) {\n\t\t\t\t\t\t\t\t\tfiringIndex--;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Check if a given callback is in the list.\n\t\t\t// If no argument is given, return whether or not list has callbacks attached.\n\t\t\thas: function( fn ) {\n\t\t\t\treturn fn ? jQuery.inArray( fn, list ) > -1 : !!( list && list.length );\n\t\t\t},\n\t\t\t// Remove all callbacks from the list\n\t\t\tempty: function() {\n\t\t\t\tlist = [];\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Have the list do nothing anymore\n\t\t\tdisable: function() {\n\t\t\t\tlist = stack = memory = undefined;\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Is it disabled?\n\t\t\tdisabled: function() {\n\t\t\t\treturn !list;\n\t\t\t},\n\t\t\t// Lock the list in its current state\n\t\t\tlock: function() {\n\t\t\t\tstack = undefined;\n\t\t\t\tif ( !memory ) {\n\t\t\t\t\tself.disable();\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Is it locked?\n\t\t\tlocked: function() {\n\t\t\t\treturn !stack;\n\t\t\t},\n\t\t\t// Call all callbacks with the given context and arguments\n\t\t\tfireWith: function( context, args ) {\n\t\t\t\targs = args || [];\n\t\t\t\targs = [ context, args.slice ? args.slice() : args ];\n\t\t\t\tif ( list && ( !fired || stack ) ) {\n\t\t\t\t\tif ( firing ) {\n\t\t\t\t\t\tstack.push( args );\n\t\t\t\t\t} else {\n\t\t\t\t\t\tfire( args );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Call all the callbacks with the given arguments\n\t\t\tfire: function() {\n\t\t\t\tself.fireWith( this, arguments );\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// To know if the callbacks have already been called at least once\n\t\t\tfired: function() {\n\t\t\t\treturn !!fired;\n\t\t\t}\n\t\t};\n\n\treturn self;\n};\njQuery.extend({\n\n\tDeferred: function( func ) {\n\t\tvar tuples = [\n\t\t\t\t// action, add listener, listener list, final state\n\t\t\t\t[ \"resolve\", \"done\", jQuery.Callbacks(\"once memory\"), \"resolved\" ],\n\t\t\t\t[ \"reject\", \"fail\", jQuery.Callbacks(\"once memory\"), \"rejected\" ],\n\t\t\t\t[ \"notify\", \"progress\", jQuery.Callbacks(\"memory\") ]\n\t\t\t],\n\t\t\tstate = \"pending\",\n\t\t\tpromise = {\n\t\t\t\tstate: function() {\n\t\t\t\t\treturn state;\n\t\t\t\t},\n\t\t\t\talways: function() {\n\t\t\t\t\tdeferred.done( arguments ).fail( arguments );\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\t\t\t\tthen: function( /* fnDone, fnFail, fnProgress */ ) {\n\t\t\t\t\tvar fns = arguments;\n\t\t\t\t\treturn jQuery.Deferred(function( newDefer ) {\n\t\t\t\t\t\tjQuery.each( tuples, function( i, tuple ) {\n\t\t\t\t\t\t\tvar action = tuple[ 0 ],\n\t\t\t\t\t\t\t\tfn = jQuery.isFunction( fns[ i ] ) && fns[ i ];\n\t\t\t\t\t\t\t// deferred[ done | fail | progress ] for forwarding actions to newDefer\n\t\t\t\t\t\t\tdeferred[ tuple[1] ](function() {\n\t\t\t\t\t\t\t\tvar returned = fn && fn.apply( this, arguments );\n\t\t\t\t\t\t\t\tif ( returned && jQuery.isFunction( returned.promise ) ) {\n\t\t\t\t\t\t\t\t\treturned.promise()\n\t\t\t\t\t\t\t\t\t\t.done( newDefer.resolve )\n\t\t\t\t\t\t\t\t\t\t.fail( newDefer.reject )\n\t\t\t\t\t\t\t\t\t\t.progress( newDefer.notify );\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tnewDefer[ action + \"With\" ]( this === promise ? newDefer.promise() : this, fn ? [ returned ] : arguments );\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t});\n\t\t\t\t\t\tfns = null;\n\t\t\t\t\t}).promise();\n\t\t\t\t},\n\t\t\t\t// Get a promise for this deferred\n\t\t\t\t// If obj is provided, the promise aspect is added to the object\n\t\t\t\tpromise: function( obj ) {\n\t\t\t\t\treturn obj != null ? jQuery.extend( obj, promise ) : promise;\n\t\t\t\t}\n\t\t\t},\n\t\t\tdeferred = {};\n\n\t\t// Keep pipe for back-compat\n\t\tpromise.pipe = promise.then;\n\n\t\t// Add list-specific methods\n\t\tjQuery.each( tuples, function( i, tuple ) {\n\t\t\tvar list = tuple[ 2 ],\n\t\t\t\tstateString = tuple[ 3 ];\n\n\t\t\t// promise[ done | fail | progress ] = list.add\n\t\t\tpromise[ tuple[1] ] = list.add;\n\n\t\t\t// Handle state\n\t\t\tif ( stateString ) {\n\t\t\t\tlist.add(function() {\n\t\t\t\t\t// state = [ resolved | rejected ]\n\t\t\t\t\tstate = stateString;\n\n\t\t\t\t// [ reject_list | resolve_list ].disable; progress_list.lock\n\t\t\t\t}, tuples[ i ^ 1 ][ 2 ].disable, tuples[ 2 ][ 2 ].lock );\n\t\t\t}\n\n\t\t\t// deferred[ resolve | reject | notify ]\n\t\t\tdeferred[ tuple[0] ] = function() {\n\t\t\t\tdeferred[ tuple[0] + \"With\" ]( this === deferred ? promise : this, arguments );\n\t\t\t\treturn this;\n\t\t\t};\n\t\t\tdeferred[ tuple[0] + \"With\" ] = list.fireWith;\n\t\t});\n\n\t\t// Make the deferred a promise\n\t\tpromise.promise( deferred );\n\n\t\t// Call given func if any\n\t\tif ( func ) {\n\t\t\tfunc.call( deferred, deferred );\n\t\t}\n\n\t\t// All done!\n\t\treturn deferred;\n\t},\n\n\t// Deferred helper\n\twhen: function( subordinate /* , ..., subordinateN */ ) {\n\t\tvar i = 0,\n\t\t\tresolveValues = core_slice.call( arguments ),\n\t\t\tlength = resolveValues.length,\n\n\t\t\t// the count of uncompleted subordinates\n\t\t\tremaining = length !== 1 || ( subordinate && jQuery.isFunction( subordinate.promise ) ) ? length : 0,\n\n\t\t\t// the master Deferred. If resolveValues consist of only a single Deferred, just use that.\n\t\t\tdeferred = remaining === 1 ? subordinate : jQuery.Deferred(),\n\n\t\t\t// Update function for both resolve and progress values\n\t\t\tupdateFunc = function( i, contexts, values ) {\n\t\t\t\treturn function( value ) {\n\t\t\t\t\tcontexts[ i ] = this;\n\t\t\t\t\tvalues[ i ] = arguments.length > 1 ? core_slice.call( arguments ) : value;\n\t\t\t\t\tif( values === progressValues ) {\n\t\t\t\t\t\tdeferred.notifyWith( contexts, values );\n\t\t\t\t\t} else if ( !( --remaining ) ) {\n\t\t\t\t\t\tdeferred.resolveWith( contexts, values );\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\t},\n\n\t\t\tprogressValues, progressContexts, resolveContexts;\n\n\t\t// add listeners to Deferred subordinates; treat others as resolved\n\t\tif ( length > 1 ) {\n\t\t\tprogressValues = new Array( length );\n\t\t\tprogressContexts = new Array( length );\n\t\t\tresolveContexts = new Array( length );\n\t\t\tfor ( ; i < length; i++ ) {\n\t\t\t\tif ( resolveValues[ i ] && jQuery.isFunction( resolveValues[ i ].promise ) ) {\n\t\t\t\t\tresolveValues[ i ].promise()\n\t\t\t\t\t\t.done( updateFunc( i, resolveContexts, resolveValues ) )\n\t\t\t\t\t\t.fail( deferred.reject )\n\t\t\t\t\t\t.progress( updateFunc( i, progressContexts, progressValues ) );\n\t\t\t\t} else {\n\t\t\t\t\t--remaining;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// if we're not waiting on anything, resolve the master\n\t\tif ( !remaining ) {\n\t\t\tdeferred.resolveWith( resolveContexts, resolveValues );\n\t\t}\n\n\t\treturn deferred.promise();\n\t}\n});\njQuery.support = (function() {\n\n\tvar support, all, a,\n\t\tinput, select, fragment,\n\t\topt, eventName, isSupported, i,\n\t\tdiv = document.createElement(\"div\");\n\n\t// Setup\n\tdiv.setAttribute( \"className\", \"t\" );\n\tdiv.innerHTML = \"  <link/><table></table><a href='/a'>a</a><input type='checkbox'/>\";\n\n\t// Support tests won't run in some limited or non-browser environments\n\tall = div.getElementsByTagName(\"*\");\n\ta = div.getElementsByTagName(\"a\")[ 0 ];\n\tif ( !all || !a || !all.length ) {\n\t\treturn {};\n\t}\n\n\t// First batch of tests\n\tselect = document.createElement(\"select\");\n\topt = select.appendChild( document.createElement(\"option\") );\n\tinput = div.getElementsByTagName(\"input\")[ 0 ];\n\n\ta.style.cssText = \"top:1px;float:left;opacity:.5\";\n\tsupport = {\n\t\t// Test setAttribute on camelCase class. If it works, we need attrFixes when doing get/setAttribute (ie6/7)\n\t\tgetSetAttribute: div.className !== \"t\",\n\n\t\t// IE strips leading whitespace when .innerHTML is used\n\t\tleadingWhitespace: div.firstChild.nodeType === 3,\n\n\t\t// Make sure that tbody elements aren't automatically inserted\n\t\t// IE will insert them into empty tables\n\t\ttbody: !div.getElementsByTagName(\"tbody\").length,\n\n\t\t// Make sure that link elements get serialized correctly by innerHTML\n\t\t// This requires a wrapper element in IE\n\t\thtmlSerialize: !!div.getElementsByTagName(\"link\").length,\n\n\t\t// Get the style information from getAttribute\n\t\t// (IE uses .cssText instead)\n\t\tstyle: /top/.test( a.getAttribute(\"style\") ),\n\n\t\t// Make sure that URLs aren't manipulated\n\t\t// (IE normalizes it by default)\n\t\threfNormalized: a.getAttribute(\"href\") === \"/a\",\n\n\t\t// Make sure that element opacity exists\n\t\t// (IE uses filter instead)\n\t\t// Use a regex to work around a WebKit issue. See #5145\n\t\topacity: /^0.5/.test( a.style.opacity ),\n\n\t\t// Verify style float existence\n\t\t// (IE uses styleFloat instead of cssFloat)\n\t\tcssFloat: !!a.style.cssFloat,\n\n\t\t// Check the default checkbox/radio value (\"\" on WebKit; \"on\" elsewhere)\n\t\tcheckOn: !!input.value,\n\n\t\t// Make sure that a selected-by-default option has a working selected property.\n\t\t// (WebKit defaults to false instead of true, IE too, if it's in an optgroup)\n\t\toptSelected: opt.selected,\n\n\t\t// Tests for enctype support on a form (#6743)\n\t\tenctype: !!document.createElement(\"form\").enctype,\n\n\t\t// Makes sure cloning an html5 element does not cause problems\n\t\t// Where outerHTML is undefined, this still works\n\t\thtml5Clone: document.createElement(\"nav\").cloneNode( true ).outerHTML !== \"<:nav></:nav>\",\n\n\t\t// jQuery.support.boxModel DEPRECATED in 1.8 since we don't support Quirks Mode\n\t\tboxModel: document.compatMode === \"CSS1Compat\",\n\n\t\t// Will be defined later\n\t\tdeleteExpando: true,\n\t\tnoCloneEvent: true,\n\t\tinlineBlockNeedsLayout: false,\n\t\tshrinkWrapBlocks: false,\n\t\treliableMarginRight: true,\n\t\tboxSizingReliable: true,\n\t\tpixelPosition: false\n\t};\n\n\t// Make sure checked status is properly cloned\n\tinput.checked = true;\n\tsupport.noCloneChecked = input.cloneNode( true ).checked;\n\n\t// Make sure that the options inside disabled selects aren't marked as disabled\n\t// (WebKit marks them as disabled)\n\tselect.disabled = true;\n\tsupport.optDisabled = !opt.disabled;\n\n\t// Support: IE<9\n\ttry {\n\t\tdelete div.test;\n\t} catch( e ) {\n\t\tsupport.deleteExpando = false;\n\t}\n\n\t// Check if we can trust getAttribute(\"value\")\n\tinput = document.createElement(\"input\");\n\tinput.setAttribute( \"value\", \"\" );\n\tsupport.input = input.getAttribute( \"value\" ) === \"\";\n\n\t// Check if an input maintains its value after becoming a radio\n\tinput.value = \"t\";\n\tinput.setAttribute( \"type\", \"radio\" );\n\tsupport.radioValue = input.value === \"t\";\n\n\t// #11217 - WebKit loses check when the name is after the checked attribute\n\tinput.setAttribute( \"checked\", \"t\" );\n\tinput.setAttribute( \"name\", \"t\" );\n\n\tfragment = document.createDocumentFragment();\n\tfragment.appendChild( input );\n\n\t// Check if a disconnected checkbox will retain its checked\n\t// value of true after appended to the DOM (IE6/7)\n\tsupport.appendChecked = input.checked;\n\n\t// WebKit doesn't clone checked state correctly in fragments\n\tsupport.checkClone = fragment.cloneNode( true ).cloneNode( true ).lastChild.checked;\n\n\t// Support: IE<9\n\t// Opera does not clone events (and typeof div.attachEvent === undefined).\n\t// IE9-10 clones events bound via attachEvent, but they don't trigger with .click()\n\tif ( div.attachEvent ) {\n\t\tdiv.attachEvent( \"onclick\", function() {\n\t\t\tsupport.noCloneEvent = false;\n\t\t});\n\n\t\tdiv.cloneNode( true ).click();\n\t}\n\n\t// Support: IE<9 (lack submit/change bubble), Firefox 17+ (lack focusin event)\n\t// Beware of CSP restrictions (https://developer.mozilla.org/en/Security/CSP), test/csp.php\n\tfor ( i in { submit: true, change: true, focusin: true }) {\n\t\tdiv.setAttribute( eventName = \"on\" + i, \"t\" );\n\n\t\tsupport[ i + \"Bubbles\" ] = eventName in window || div.attributes[ eventName ].expando === false;\n\t}\n\n\tdiv.style.backgroundClip = \"content-box\";\n\tdiv.cloneNode( true ).style.backgroundClip = \"\";\n\tsupport.clearCloneStyle = div.style.backgroundClip === \"content-box\";\n\n\t// Run tests that need a body at doc ready\n\tjQuery(function() {\n\t\tvar container, marginDiv, tds,\n\t\t\tdivReset = \"padding:0;margin:0;border:0;display:block;box-sizing:content-box;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;\",\n\t\t\tbody = document.getElementsByTagName(\"body\")[0];\n\n\t\tif ( !body ) {\n\t\t\t// Return for frameset docs that don't have a body\n\t\t\treturn;\n\t\t}\n\n\t\tcontainer = document.createElement(\"div\");\n\t\tcontainer.style.cssText = \"border:0;width:0;height:0;position:absolute;top:0;left:-9999px;margin-top:1px\";\n\n\t\tbody.appendChild( container ).appendChild( div );\n\n\t\t// Support: IE8\n\t\t// Check if table cells still have offsetWidth/Height when they are set\n\t\t// to display:none and there are still other visible table cells in a\n\t\t// table row; if so, offsetWidth/Height are not reliable for use when\n\t\t// determining if an element has been hidden directly using\n\t\t// display:none (it is still safe to use offsets if a parent element is\n\t\t// hidden; don safety goggles and see bug #4512 for more information).\n\t\tdiv.innerHTML = \"<table><tr><td></td><td>t</td></tr></table>\";\n\t\ttds = div.getElementsByTagName(\"td\");\n\t\ttds[ 0 ].style.cssText = \"padding:0;margin:0;border:0;display:none\";\n\t\tisSupported = ( tds[ 0 ].offsetHeight === 0 );\n\n\t\ttds[ 0 ].style.display = \"\";\n\t\ttds[ 1 ].style.display = \"none\";\n\n\t\t// Support: IE8\n\t\t// Check if empty table cells still have offsetWidth/Height\n\t\tsupport.reliableHiddenOffsets = isSupported && ( tds[ 0 ].offsetHeight === 0 );\n\n\t\t// Check box-sizing and margin behavior\n\t\tdiv.innerHTML = \"\";\n\t\tdiv.style.cssText = \"box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%;\";\n\t\tsupport.boxSizing = ( div.offsetWidth === 4 );\n\t\tsupport.doesNotIncludeMarginInBodyOffset = ( body.offsetTop !== 1 );\n\n\t\t// Use window.getComputedStyle because jsdom on node.js will break without it.\n\t\tif ( window.getComputedStyle ) {\n\t\t\tsupport.pixelPosition = ( window.getComputedStyle( div, null ) || {} ).top !== \"1%\";\n\t\t\tsupport.boxSizingReliable = ( window.getComputedStyle( div, null ) || { width: \"4px\" } ).width === \"4px\";\n\n\t\t\t// Check if div with explicit width and no margin-right incorrectly\n\t\t\t// gets computed margin-right based on width of container. (#3333)\n\t\t\t// Fails in WebKit before Feb 2011 nightlies\n\t\t\t// WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right\n\t\t\tmarginDiv = div.appendChild( document.createElement(\"div\") );\n\t\t\tmarginDiv.style.cssText = div.style.cssText = divReset;\n\t\t\tmarginDiv.style.marginRight = marginDiv.style.width = \"0\";\n\t\t\tdiv.style.width = \"1px\";\n\n\t\t\tsupport.reliableMarginRight =\n\t\t\t\t!parseFloat( ( window.getComputedStyle( marginDiv, null ) || {} ).marginRight );\n\t\t}\n\n\t\tif ( typeof div.style.zoom !== core_strundefined ) {\n\t\t\t// Support: IE<8\n\t\t\t// Check if natively block-level elements act like inline-block\n\t\t\t// elements when setting their display to 'inline' and giving\n\t\t\t// them layout\n\t\t\tdiv.innerHTML = \"\";\n\t\t\tdiv.style.cssText = divReset + \"width:1px;padding:1px;display:inline;zoom:1\";\n\t\t\tsupport.inlineBlockNeedsLayout = ( div.offsetWidth === 3 );\n\n\t\t\t// Support: IE6\n\t\t\t// Check if elements with layout shrink-wrap their children\n\t\t\tdiv.style.display = \"block\";\n\t\t\tdiv.innerHTML = \"<div></div>\";\n\t\t\tdiv.firstChild.style.width = \"5px\";\n\t\t\tsupport.shrinkWrapBlocks = ( div.offsetWidth !== 3 );\n\n\t\t\tif ( support.inlineBlockNeedsLayout ) {\n\t\t\t\t// Prevent IE 6 from affecting layout for positioned elements #11048\n\t\t\t\t// Prevent IE from shrinking the body in IE 7 mode #12869\n\t\t\t\t// Support: IE<8\n\t\t\t\tbody.style.zoom = 1;\n\t\t\t}\n\t\t}\n\n\t\tbody.removeChild( container );\n\n\t\t// Null elements to avoid leaks in IE\n\t\tcontainer = div = tds = marginDiv = null;\n\t});\n\n\t// Null elements to avoid leaks in IE\n\tall = select = fragment = opt = a = input = null;\n\n\treturn support;\n})();\n\nvar rbrace = /(?:\\{[\\s\\S]*\\}|\\[[\\s\\S]*\\])$/,\n\trmultiDash = /([A-Z])/g;\n\nfunction internalData( elem, name, data, pvt /* Internal Use Only */ ){\n\tif ( !jQuery.acceptData( elem ) ) {\n\t\treturn;\n\t}\n\n\tvar thisCache, ret,\n\t\tinternalKey = jQuery.expando,\n\t\tgetByName = typeof name === \"string\",\n\n\t\t// We have to handle DOM nodes and JS objects differently because IE6-7\n\t\t// can't GC object references properly across the DOM-JS boundary\n\t\tisNode = elem.nodeType,\n\n\t\t// Only DOM nodes need the global jQuery cache; JS object data is\n\t\t// attached directly to the object so GC can occur automatically\n\t\tcache = isNode ? jQuery.cache : elem,\n\n\t\t// Only defining an ID for JS objects if its cache already exists allows\n\t\t// the code to shortcut on the same path as a DOM node with no cache\n\t\tid = isNode ? elem[ internalKey ] : elem[ internalKey ] && internalKey;\n\n\t// Avoid doing any more work than we need to when trying to get data on an\n\t// object that has no data at all\n\tif ( (!id || !cache[id] || (!pvt && !cache[id].data)) && getByName && data === undefined ) {\n\t\treturn;\n\t}\n\n\tif ( !id ) {\n\t\t// Only DOM nodes need a new unique ID for each element since their data\n\t\t// ends up in the global cache\n\t\tif ( isNode ) {\n\t\t\telem[ internalKey ] = id = core_deletedIds.pop() || jQuery.guid++;\n\t\t} else {\n\t\t\tid = internalKey;\n\t\t}\n\t}\n\n\tif ( !cache[ id ] ) {\n\t\tcache[ id ] = {};\n\n\t\t// Avoids exposing jQuery metadata on plain JS objects when the object\n\t\t// is serialized using JSON.stringify\n\t\tif ( !isNode ) {\n\t\t\tcache[ id ].toJSON = jQuery.noop;\n\t\t}\n\t}\n\n\t// An object can be passed to jQuery.data instead of a key/value pair; this gets\n\t// shallow copied over onto the existing cache\n\tif ( typeof name === \"object\" || typeof name === \"function\" ) {\n\t\tif ( pvt ) {\n\t\t\tcache[ id ] = jQuery.extend( cache[ id ], name );\n\t\t} else {\n\t\t\tcache[ id ].data = jQuery.extend( cache[ id ].data, name );\n\t\t}\n\t}\n\n\tthisCache = cache[ id ];\n\n\t// jQuery data() is stored in a separate object inside the object's internal data\n\t// cache in order to avoid key collisions between internal data and user-defined\n\t// data.\n\tif ( !pvt ) {\n\t\tif ( !thisCache.data ) {\n\t\t\tthisCache.data = {};\n\t\t}\n\n\t\tthisCache = thisCache.data;\n\t}\n\n\tif ( data !== undefined ) {\n\t\tthisCache[ jQuery.camelCase( name ) ] = data;\n\t}\n\n\t// Check for both converted-to-camel and non-converted data property names\n\t// If a data property was specified\n\tif ( getByName ) {\n\n\t\t// First Try to find as-is property data\n\t\tret = thisCache[ name ];\n\n\t\t// Test for null|undefined property data\n\t\tif ( ret == null ) {\n\n\t\t\t// Try to find the camelCased property\n\t\t\tret = thisCache[ jQuery.camelCase( name ) ];\n\t\t}\n\t} else {\n\t\tret = thisCache;\n\t}\n\n\treturn ret;\n}\n\nfunction internalRemoveData( elem, name, pvt ) {\n\tif ( !jQuery.acceptData( elem ) ) {\n\t\treturn;\n\t}\n\n\tvar i, l, thisCache,\n\t\tisNode = elem.nodeType,\n\n\t\t// See jQuery.data for more information\n\t\tcache = isNode ? jQuery.cache : elem,\n\t\tid = isNode ? elem[ jQuery.expando ] : jQuery.expando;\n\n\t// If there is already no cache entry for this object, there is no\n\t// purpose in continuing\n\tif ( !cache[ id ] ) {\n\t\treturn;\n\t}\n\n\tif ( name ) {\n\n\t\tthisCache = pvt ? cache[ id ] : cache[ id ].data;\n\n\t\tif ( thisCache ) {\n\n\t\t\t// Support array or space separated string names for data keys\n\t\t\tif ( !jQuery.isArray( name ) ) {\n\n\t\t\t\t// try the string as a key before any manipulation\n\t\t\t\tif ( name in thisCache ) {\n\t\t\t\t\tname = [ name ];\n\t\t\t\t} else {\n\n\t\t\t\t\t// split the camel cased version by spaces unless a key with the spaces exists\n\t\t\t\t\tname = jQuery.camelCase( name );\n\t\t\t\t\tif ( name in thisCache ) {\n\t\t\t\t\t\tname = [ name ];\n\t\t\t\t\t} else {\n\t\t\t\t\t\tname = name.split(\" \");\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// If \"name\" is an array of keys...\n\t\t\t\t// When data is initially created, via (\"key\", \"val\") signature,\n\t\t\t\t// keys will be converted to camelCase.\n\t\t\t\t// Since there is no way to tell _how_ a key was added, remove\n\t\t\t\t// both plain key and camelCase key. #12786\n\t\t\t\t// This will only penalize the array argument path.\n\t\t\t\tname = name.concat( jQuery.map( name, jQuery.camelCase ) );\n\t\t\t}\n\n\t\t\tfor ( i = 0, l = name.length; i < l; i++ ) {\n\t\t\t\tdelete thisCache[ name[i] ];\n\t\t\t}\n\n\t\t\t// If there is no data left in the cache, we want to continue\n\t\t\t// and let the cache object itself get destroyed\n\t\t\tif ( !( pvt ? isEmptyDataObject : jQuery.isEmptyObject )( thisCache ) ) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t}\n\n\t// See jQuery.data for more information\n\tif ( !pvt ) {\n\t\tdelete cache[ id ].data;\n\n\t\t// Don't destroy the parent cache unless the internal data object\n\t\t// had been the only thing left in it\n\t\tif ( !isEmptyDataObject( cache[ id ] ) ) {\n\t\t\treturn;\n\t\t}\n\t}\n\n\t// Destroy the cache\n\tif ( isNode ) {\n\t\tjQuery.cleanData( [ elem ], true );\n\n\t// Use delete when supported for expandos or `cache` is not a window per isWindow (#10080)\n\t} else if ( jQuery.support.deleteExpando || cache != cache.window ) {\n\t\tdelete cache[ id ];\n\n\t// When all else fails, null\n\t} else {\n\t\tcache[ id ] = null;\n\t}\n}\n\njQuery.extend({\n\tcache: {},\n\n\t// Unique for each copy of jQuery on the page\n\t// Non-digits removed to match rinlinejQuery\n\texpando: \"jQuery\" + ( core_version + Math.random() ).replace( /\\D/g, \"\" ),\n\n\t// The following elements throw uncatchable exceptions if you\n\t// attempt to add expando properties to them.\n\tnoData: {\n\t\t\"embed\": true,\n\t\t// Ban all objects except for Flash (which handle expandos)\n\t\t\"object\": \"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000\",\n\t\t\"applet\": true\n\t},\n\n\thasData: function( elem ) {\n\t\telem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ];\n\t\treturn !!elem && !isEmptyDataObject( elem );\n\t},\n\n\tdata: function( elem, name, data ) {\n\t\treturn internalData( elem, name, data );\n\t},\n\n\tremoveData: function( elem, name ) {\n\t\treturn internalRemoveData( elem, name );\n\t},\n\n\t// For internal use only.\n\t_data: function( elem, name, data ) {\n\t\treturn internalData( elem, name, data, true );\n\t},\n\n\t_removeData: function( elem, name ) {\n\t\treturn internalRemoveData( elem, name, true );\n\t},\n\n\t// A method for determining if a DOM node can handle the data expando\n\tacceptData: function( elem ) {\n\t\t// Do not set data on non-element because it will not be cleared (#8335).\n\t\tif ( elem.nodeType && elem.nodeType !== 1 && elem.nodeType !== 9 ) {\n\t\t\treturn false;\n\t\t}\n\n\t\tvar noData = elem.nodeName && jQuery.noData[ elem.nodeName.toLowerCase() ];\n\n\t\t// nodes accept data unless otherwise specified; rejection can be conditional\n\t\treturn !noData || noData !== true && elem.getAttribute(\"classid\") === noData;\n\t}\n});\n\njQuery.fn.extend({\n\tdata: function( key, value ) {\n\t\tvar attrs, name,\n\t\t\telem = this[0],\n\t\t\ti = 0,\n\t\t\tdata = null;\n\n\t\t// Gets all values\n\t\tif ( key === undefined ) {\n\t\t\tif ( this.length ) {\n\t\t\t\tdata = jQuery.data( elem );\n\n\t\t\t\tif ( elem.nodeType === 1 && !jQuery._data( elem, \"parsedAttrs\" ) ) {\n\t\t\t\t\tattrs = elem.attributes;\n\t\t\t\t\tfor ( ; i < attrs.length; i++ ) {\n\t\t\t\t\t\tname = attrs[i].name;\n\n\t\t\t\t\t\tif ( !name.indexOf( \"data-\" ) ) {\n\t\t\t\t\t\t\tname = jQuery.camelCase( name.slice(5) );\n\n\t\t\t\t\t\t\tdataAttr( elem, name, data[ name ] );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tjQuery._data( elem, \"parsedAttrs\", true );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn data;\n\t\t}\n\n\t\t// Sets multiple values\n\t\tif ( typeof key === \"object\" ) {\n\t\t\treturn this.each(function() {\n\t\t\t\tjQuery.data( this, key );\n\t\t\t});\n\t\t}\n\n\t\treturn jQuery.access( this, function( value ) {\n\n\t\t\tif ( value === undefined ) {\n\t\t\t\t// Try to fetch any internally stored data first\n\t\t\t\treturn elem ? dataAttr( elem, key, jQuery.data( elem, key ) ) : null;\n\t\t\t}\n\n\t\t\tthis.each(function() {\n\t\t\t\tjQuery.data( this, key, value );\n\t\t\t});\n\t\t}, null, value, arguments.length > 1, null, true );\n\t},\n\n\tremoveData: function( key ) {\n\t\treturn this.each(function() {\n\t\t\tjQuery.removeData( this, key );\n\t\t});\n\t}\n});\n\nfunction dataAttr( elem, key, data ) {\n\t// If nothing was found internally, try to fetch any\n\t// data from the HTML5 data-* attribute\n\tif ( data === undefined && elem.nodeType === 1 ) {\n\n\t\tvar name = \"data-\" + key.replace( rmultiDash, \"-$1\" ).toLowerCase();\n\n\t\tdata = elem.getAttribute( name );\n\n\t\tif ( typeof data === \"string\" ) {\n\t\t\ttry {\n\t\t\t\tdata = data === \"true\" ? true :\n\t\t\t\t\tdata === \"false\" ? false :\n\t\t\t\t\tdata === \"null\" ? null :\n\t\t\t\t\t// Only convert to a number if it doesn't change the string\n\t\t\t\t\t+data + \"\" === data ? +data :\n\t\t\t\t\trbrace.test( data ) ? jQuery.parseJSON( data ) :\n\t\t\t\t\t\tdata;\n\t\t\t} catch( e ) {}\n\n\t\t\t// Make sure we set the data so it isn't changed later\n\t\t\tjQuery.data( elem, key, data );\n\n\t\t} else {\n\t\t\tdata = undefined;\n\t\t}\n\t}\n\n\treturn data;\n}\n\n// checks a cache object for emptiness\nfunction isEmptyDataObject( obj ) {\n\tvar name;\n\tfor ( name in obj ) {\n\n\t\t// if the public data object is empty, the private is still empty\n\t\tif ( name === \"data\" && jQuery.isEmptyObject( obj[name] ) ) {\n\t\t\tcontinue;\n\t\t}\n\t\tif ( name !== \"toJSON\" ) {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\treturn true;\n}\njQuery.extend({\n\tqueue: function( elem, type, data ) {\n\t\tvar queue;\n\n\t\tif ( elem ) {\n\t\t\ttype = ( type || \"fx\" ) + \"queue\";\n\t\t\tqueue = jQuery._data( elem, type );\n\n\t\t\t// Speed up dequeue by getting out quickly if this is just a lookup\n\t\t\tif ( data ) {\n\t\t\t\tif ( !queue || jQuery.isArray(data) ) {\n\t\t\t\t\tqueue = jQuery._data( elem, type, jQuery.makeArray(data) );\n\t\t\t\t} else {\n\t\t\t\t\tqueue.push( data );\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn queue || [];\n\t\t}\n\t},\n\n\tdequeue: function( elem, type ) {\n\t\ttype = type || \"fx\";\n\n\t\tvar queue = jQuery.queue( elem, type ),\n\t\t\tstartLength = queue.length,\n\t\t\tfn = queue.shift(),\n\t\t\thooks = jQuery._queueHooks( elem, type ),\n\t\t\tnext = function() {\n\t\t\t\tjQuery.dequeue( elem, type );\n\t\t\t};\n\n\t\t// If the fx queue is dequeued, always remove the progress sentinel\n\t\tif ( fn === \"inprogress\" ) {\n\t\t\tfn = queue.shift();\n\t\t\tstartLength--;\n\t\t}\n\n\t\thooks.cur = fn;\n\t\tif ( fn ) {\n\n\t\t\t// Add a progress sentinel to prevent the fx queue from being\n\t\t\t// automatically dequeued\n\t\t\tif ( type === \"fx\" ) {\n\t\t\t\tqueue.unshift( \"inprogress\" );\n\t\t\t}\n\n\t\t\t// clear up the last queue stop function\n\t\t\tdelete hooks.stop;\n\t\t\tfn.call( elem, next, hooks );\n\t\t}\n\n\t\tif ( !startLength && hooks ) {\n\t\t\thooks.empty.fire();\n\t\t}\n\t},\n\n\t// not intended for public consumption - generates a queueHooks object, or returns the current one\n\t_queueHooks: function( elem, type ) {\n\t\tvar key = type + \"queueHooks\";\n\t\treturn jQuery._data( elem, key ) || jQuery._data( elem, key, {\n\t\t\tempty: jQuery.Callbacks(\"once memory\").add(function() {\n\t\t\t\tjQuery._removeData( elem, type + \"queue\" );\n\t\t\t\tjQuery._removeData( elem, key );\n\t\t\t})\n\t\t});\n\t}\n});\n\njQuery.fn.extend({\n\tqueue: function( type, data ) {\n\t\tvar setter = 2;\n\n\t\tif ( typeof type !== \"string\" ) {\n\t\t\tdata = type;\n\t\t\ttype = \"fx\";\n\t\t\tsetter--;\n\t\t}\n\n\t\tif ( arguments.length < setter ) {\n\t\t\treturn jQuery.queue( this[0], type );\n\t\t}\n\n\t\treturn data === undefined ?\n\t\t\tthis :\n\t\t\tthis.each(function() {\n\t\t\t\tvar queue = jQuery.queue( this, type, data );\n\n\t\t\t\t// ensure a hooks for this queue\n\t\t\t\tjQuery._queueHooks( this, type );\n\n\t\t\t\tif ( type === \"fx\" && queue[0] !== \"inprogress\" ) {\n\t\t\t\t\tjQuery.dequeue( this, type );\n\t\t\t\t}\n\t\t\t});\n\t},\n\tdequeue: function( type ) {\n\t\treturn this.each(function() {\n\t\t\tjQuery.dequeue( this, type );\n\t\t});\n\t},\n\t// Based off of the plugin by Clint Helfers, with permission.\n\t// http://blindsignals.com/index.php/2009/07/jquery-delay/\n\tdelay: function( time, type ) {\n\t\ttime = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time;\n\t\ttype = type || \"fx\";\n\n\t\treturn this.queue( type, function( next, hooks ) {\n\t\t\tvar timeout = setTimeout( next, time );\n\t\t\thooks.stop = function() {\n\t\t\t\tclearTimeout( timeout );\n\t\t\t};\n\t\t});\n\t},\n\tclearQueue: function( type ) {\n\t\treturn this.queue( type || \"fx\", [] );\n\t},\n\t// Get a promise resolved when queues of a certain type\n\t// are emptied (fx is the type by default)\n\tpromise: function( type, obj ) {\n\t\tvar tmp,\n\t\t\tcount = 1,\n\t\t\tdefer = jQuery.Deferred(),\n\t\t\telements = this,\n\t\t\ti = this.length,\n\t\t\tresolve = function() {\n\t\t\t\tif ( !( --count ) ) {\n\t\t\t\t\tdefer.resolveWith( elements, [ elements ] );\n\t\t\t\t}\n\t\t\t};\n\n\t\tif ( typeof type !== \"string\" ) {\n\t\t\tobj = type;\n\t\t\ttype = undefined;\n\t\t}\n\t\ttype = type || \"fx\";\n\n\t\twhile( i-- ) {\n\t\t\ttmp = jQuery._data( elements[ i ], type + \"queueHooks\" );\n\t\t\tif ( tmp && tmp.empty ) {\n\t\t\t\tcount++;\n\t\t\t\ttmp.empty.add( resolve );\n\t\t\t}\n\t\t}\n\t\tresolve();\n\t\treturn defer.promise( obj );\n\t}\n});\nvar nodeHook, boolHook,\n\trclass = /[\\t\\r\\n]/g,\n\trreturn = /\\r/g,\n\trfocusable = /^(?:input|select|textarea|button|object)$/i,\n\trclickable = /^(?:a|area)$/i,\n\trboolean = /^(?:checked|selected|autofocus|autoplay|async|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped)$/i,\n\truseDefault = /^(?:checked|selected)$/i,\n\tgetSetAttribute = jQuery.support.getSetAttribute,\n\tgetSetInput = jQuery.support.input;\n\njQuery.fn.extend({\n\tattr: function( name, value ) {\n\t\treturn jQuery.access( this, jQuery.attr, name, value, arguments.length > 1 );\n\t},\n\n\tremoveAttr: function( name ) {\n\t\treturn this.each(function() {\n\t\t\tjQuery.removeAttr( this, name );\n\t\t});\n\t},\n\n\tprop: function( name, value ) {\n\t\treturn jQuery.access( this, jQuery.prop, name, value, arguments.length > 1 );\n\t},\n\n\tremoveProp: function( name ) {\n\t\tname = jQuery.propFix[ name ] || name;\n\t\treturn this.each(function() {\n\t\t\t// try/catch handles cases where IE balks (such as removing a property on window)\n\t\t\ttry {\n\t\t\t\tthis[ name ] = undefined;\n\t\t\t\tdelete this[ name ];\n\t\t\t} catch( e ) {}\n\t\t});\n\t},\n\n\taddClass: function( value ) {\n\t\tvar classes, elem, cur, clazz, j,\n\t\t\ti = 0,\n\t\t\tlen = this.length,\n\t\t\tproceed = typeof value === \"string\" && value;\n\n\t\tif ( jQuery.isFunction( value ) ) {\n\t\t\treturn this.each(function( j ) {\n\t\t\t\tjQuery( this ).addClass( value.call( this, j, this.className ) );\n\t\t\t});\n\t\t}\n\n\t\tif ( proceed ) {\n\t\t\t// The disjunction here is for better compressibility (see removeClass)\n\t\t\tclasses = ( value || \"\" ).match( core_rnotwhite ) || [];\n\n\t\t\tfor ( ; i < len; i++ ) {\n\t\t\t\telem = this[ i ];\n\t\t\t\tcur = elem.nodeType === 1 && ( elem.className ?\n\t\t\t\t\t( \" \" + elem.className + \" \" ).replace( rclass, \" \" ) :\n\t\t\t\t\t\" \"\n\t\t\t\t);\n\n\t\t\t\tif ( cur ) {\n\t\t\t\t\tj = 0;\n\t\t\t\t\twhile ( (clazz = classes[j++]) ) {\n\t\t\t\t\t\tif ( cur.indexOf( \" \" + clazz + \" \" ) < 0 ) {\n\t\t\t\t\t\t\tcur += clazz + \" \";\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\telem.className = jQuery.trim( cur );\n\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\tremoveClass: function( value ) {\n\t\tvar classes, elem, cur, clazz, j,\n\t\t\ti = 0,\n\t\t\tlen = this.length,\n\t\t\tproceed = arguments.length === 0 || typeof value === \"string\" && value;\n\n\t\tif ( jQuery.isFunction( value ) ) {\n\t\t\treturn this.each(function( j ) {\n\t\t\t\tjQuery( this ).removeClass( value.call( this, j, this.className ) );\n\t\t\t});\n\t\t}\n\t\tif ( proceed ) {\n\t\t\tclasses = ( value || \"\" ).match( core_rnotwhite ) || [];\n\n\t\t\tfor ( ; i < len; i++ ) {\n\t\t\t\telem = this[ i ];\n\t\t\t\t// This expression is here for better compressibility (see addClass)\n\t\t\t\tcur = elem.nodeType === 1 && ( elem.className ?\n\t\t\t\t\t( \" \" + elem.className + \" \" ).replace( rclass, \" \" ) :\n\t\t\t\t\t\"\"\n\t\t\t\t);\n\n\t\t\t\tif ( cur ) {\n\t\t\t\t\tj = 0;\n\t\t\t\t\twhile ( (clazz = classes[j++]) ) {\n\t\t\t\t\t\t// Remove *all* instances\n\t\t\t\t\t\twhile ( cur.indexOf( \" \" + clazz + \" \" ) >= 0 ) {\n\t\t\t\t\t\t\tcur = cur.replace( \" \" + clazz + \" \", \" \" );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\telem.className = value ? jQuery.trim( cur ) : \"\";\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\ttoggleClass: function( value, stateVal ) {\n\t\tvar type = typeof value,\n\t\t\tisBool = typeof stateVal === \"boolean\";\n\n\t\tif ( jQuery.isFunction( value ) ) {\n\t\t\treturn this.each(function( i ) {\n\t\t\t\tjQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal );\n\t\t\t});\n\t\t}\n\n\t\treturn this.each(function() {\n\t\t\tif ( type === \"string\" ) {\n\t\t\t\t// toggle individual class names\n\t\t\t\tvar className,\n\t\t\t\t\ti = 0,\n\t\t\t\t\tself = jQuery( this ),\n\t\t\t\t\tstate = stateVal,\n\t\t\t\t\tclassNames = value.match( core_rnotwhite ) || [];\n\n\t\t\t\twhile ( (className = classNames[ i++ ]) ) {\n\t\t\t\t\t// check each className given, space separated list\n\t\t\t\t\tstate = isBool ? state : !self.hasClass( className );\n\t\t\t\t\tself[ state ? \"addClass\" : \"removeClass\" ]( className );\n\t\t\t\t}\n\n\t\t\t// Toggle whole class name\n\t\t\t} else if ( type === core_strundefined || type === \"boolean\" ) {\n\t\t\t\tif ( this.className ) {\n\t\t\t\t\t// store className if set\n\t\t\t\t\tjQuery._data( this, \"__className__\", this.className );\n\t\t\t\t}\n\n\t\t\t\t// If the element has a class name or if we're passed \"false\",\n\t\t\t\t// then remove the whole classname (if there was one, the above saved it).\n\t\t\t\t// Otherwise bring back whatever was previously saved (if anything),\n\t\t\t\t// falling back to the empty string if nothing was stored.\n\t\t\t\tthis.className = this.className || value === false ? \"\" : jQuery._data( this, \"__className__\" ) || \"\";\n\t\t\t}\n\t\t});\n\t},\n\n\thasClass: function( selector ) {\n\t\tvar className = \" \" + selector + \" \",\n\t\t\ti = 0,\n\t\t\tl = this.length;\n\t\tfor ( ; i < l; i++ ) {\n\t\t\tif ( this[i].nodeType === 1 && (\" \" + this[i].className + \" \").replace(rclass, \" \").indexOf( className ) >= 0 ) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\n\t\treturn false;\n\t},\n\n\tval: function( value ) {\n\t\tvar ret, hooks, isFunction,\n\t\t\telem = this[0];\n\n\t\tif ( !arguments.length ) {\n\t\t\tif ( elem ) {\n\t\t\t\thooks = jQuery.valHooks[ elem.type ] || jQuery.valHooks[ elem.nodeName.toLowerCase() ];\n\n\t\t\t\tif ( hooks && \"get\" in hooks && (ret = hooks.get( elem, \"value\" )) !== undefined ) {\n\t\t\t\t\treturn ret;\n\t\t\t\t}\n\n\t\t\t\tret = elem.value;\n\n\t\t\t\treturn typeof ret === \"string\" ?\n\t\t\t\t\t// handle most common string cases\n\t\t\t\t\tret.replace(rreturn, \"\") :\n\t\t\t\t\t// handle cases where value is null/undef or number\n\t\t\t\t\tret == null ? \"\" : ret;\n\t\t\t}\n\n\t\t\treturn;\n\t\t}\n\n\t\tisFunction = jQuery.isFunction( value );\n\n\t\treturn this.each(function( i ) {\n\t\t\tvar val,\n\t\t\t\tself = jQuery(this);\n\n\t\t\tif ( this.nodeType !== 1 ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif ( isFunction ) {\n\t\t\t\tval = value.call( this, i, self.val() );\n\t\t\t} else {\n\t\t\t\tval = value;\n\t\t\t}\n\n\t\t\t// Treat null/undefined as \"\"; convert numbers to string\n\t\t\tif ( val == null ) {\n\t\t\t\tval = \"\";\n\t\t\t} else if ( typeof val === \"number\" ) {\n\t\t\t\tval += \"\";\n\t\t\t} else if ( jQuery.isArray( val ) ) {\n\t\t\t\tval = jQuery.map(val, function ( value ) {\n\t\t\t\t\treturn value == null ? \"\" : value + \"\";\n\t\t\t\t});\n\t\t\t}\n\n\t\t\thooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ];\n\n\t\t\t// If set returns undefined, fall back to normal setting\n\t\t\tif ( !hooks || !(\"set\" in hooks) || hooks.set( this, val, \"value\" ) === undefined ) {\n\t\t\t\tthis.value = val;\n\t\t\t}\n\t\t});\n\t}\n});\n\njQuery.extend({\n\tvalHooks: {\n\t\toption: {\n\t\t\tget: function( elem ) {\n\t\t\t\t// attributes.value is undefined in Blackberry 4.7 but\n\t\t\t\t// uses .value. See #6932\n\t\t\t\tvar val = elem.attributes.value;\n\t\t\t\treturn !val || val.specified ? elem.value : elem.text;\n\t\t\t}\n\t\t},\n\t\tselect: {\n\t\t\tget: function( elem ) {\n\t\t\t\tvar value, option,\n\t\t\t\t\toptions = elem.options,\n\t\t\t\t\tindex = elem.selectedIndex,\n\t\t\t\t\tone = elem.type === \"select-one\" || index < 0,\n\t\t\t\t\tvalues = one ? null : [],\n\t\t\t\t\tmax = one ? index + 1 : options.length,\n\t\t\t\t\ti = index < 0 ?\n\t\t\t\t\t\tmax :\n\t\t\t\t\t\tone ? index : 0;\n\n\t\t\t\t// Loop through all the selected options\n\t\t\t\tfor ( ; i < max; i++ ) {\n\t\t\t\t\toption = options[ i ];\n\n\t\t\t\t\t// oldIE doesn't update selected after form reset (#2551)\n\t\t\t\t\tif ( ( option.selected || i === index ) &&\n\t\t\t\t\t\t\t// Don't return options that are disabled or in a disabled optgroup\n\t\t\t\t\t\t\t( jQuery.support.optDisabled ? !option.disabled : option.getAttribute(\"disabled\") === null ) &&\n\t\t\t\t\t\t\t( !option.parentNode.disabled || !jQuery.nodeName( option.parentNode, \"optgroup\" ) ) ) {\n\n\t\t\t\t\t\t// Get the specific value for the option\n\t\t\t\t\t\tvalue = jQuery( option ).val();\n\n\t\t\t\t\t\t// We don't need an array for one selects\n\t\t\t\t\t\tif ( one ) {\n\t\t\t\t\t\t\treturn value;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Multi-Selects return an array\n\t\t\t\t\t\tvalues.push( value );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn values;\n\t\t\t},\n\n\t\t\tset: function( elem, value ) {\n\t\t\t\tvar values = jQuery.makeArray( value );\n\n\t\t\t\tjQuery(elem).find(\"option\").each(function() {\n\t\t\t\t\tthis.selected = jQuery.inArray( jQuery(this).val(), values ) >= 0;\n\t\t\t\t});\n\n\t\t\t\tif ( !values.length ) {\n\t\t\t\t\telem.selectedIndex = -1;\n\t\t\t\t}\n\t\t\t\treturn values;\n\t\t\t}\n\t\t}\n\t},\n\n\tattr: function( elem, name, value ) {\n\t\tvar hooks, notxml, ret,\n\t\t\tnType = elem.nodeType;\n\n\t\t// don't get/set attributes on text, comment and attribute nodes\n\t\tif ( !elem || nType === 3 || nType === 8 || nType === 2 ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Fallback to prop when attributes are not supported\n\t\tif ( typeof elem.getAttribute === core_strundefined ) {\n\t\t\treturn jQuery.prop( elem, name, value );\n\t\t}\n\n\t\tnotxml = nType !== 1 || !jQuery.isXMLDoc( elem );\n\n\t\t// All attributes are lowercase\n\t\t// Grab necessary hook if one is defined\n\t\tif ( notxml ) {\n\t\t\tname = name.toLowerCase();\n\t\t\thooks = jQuery.attrHooks[ name ] || ( rboolean.test( name ) ? boolHook : nodeHook );\n\t\t}\n\n\t\tif ( value !== undefined ) {\n\n\t\t\tif ( value === null ) {\n\t\t\t\tjQuery.removeAttr( elem, name );\n\n\t\t\t} else if ( hooks && notxml && \"set\" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) {\n\t\t\t\treturn ret;\n\n\t\t\t} else {\n\t\t\t\telem.setAttribute( name, value + \"\" );\n\t\t\t\treturn value;\n\t\t\t}\n\n\t\t} else if ( hooks && notxml && \"get\" in hooks && (ret = hooks.get( elem, name )) !== null ) {\n\t\t\treturn ret;\n\n\t\t} else {\n\n\t\t\t// In IE9+, Flash objects don't have .getAttribute (#12945)\n\t\t\t// Support: IE9+\n\t\t\tif ( typeof elem.getAttribute !== core_strundefined ) {\n\t\t\t\tret =  elem.getAttribute( name );\n\t\t\t}\n\n\t\t\t// Non-existent attributes return null, we normalize to undefined\n\t\t\treturn ret == null ?\n\t\t\t\tundefined :\n\t\t\t\tret;\n\t\t}\n\t},\n\n\tremoveAttr: function( elem, value ) {\n\t\tvar name, propName,\n\t\t\ti = 0,\n\t\t\tattrNames = value && value.match( core_rnotwhite );\n\n\t\tif ( attrNames && elem.nodeType === 1 ) {\n\t\t\twhile ( (name = attrNames[i++]) ) {\n\t\t\t\tpropName = jQuery.propFix[ name ] || name;\n\n\t\t\t\t// Boolean attributes get special treatment (#10870)\n\t\t\t\tif ( rboolean.test( name ) ) {\n\t\t\t\t\t// Set corresponding property to false for boolean attributes\n\t\t\t\t\t// Also clear defaultChecked/defaultSelected (if appropriate) for IE<8\n\t\t\t\t\tif ( !getSetAttribute && ruseDefault.test( name ) ) {\n\t\t\t\t\t\telem[ jQuery.camelCase( \"default-\" + name ) ] =\n\t\t\t\t\t\t\telem[ propName ] = false;\n\t\t\t\t\t} else {\n\t\t\t\t\t\telem[ propName ] = false;\n\t\t\t\t\t}\n\n\t\t\t\t// See #9699 for explanation of this approach (setting first, then removal)\n\t\t\t\t} else {\n\t\t\t\t\tjQuery.attr( elem, name, \"\" );\n\t\t\t\t}\n\n\t\t\t\telem.removeAttribute( getSetAttribute ? name : propName );\n\t\t\t}\n\t\t}\n\t},\n\n\tattrHooks: {\n\t\ttype: {\n\t\t\tset: function( elem, value ) {\n\t\t\t\tif ( !jQuery.support.radioValue && value === \"radio\" && jQuery.nodeName(elem, \"input\") ) {\n\t\t\t\t\t// Setting the type on a radio button after the value resets the value in IE6-9\n\t\t\t\t\t// Reset value to default in case type is set after value during creation\n\t\t\t\t\tvar val = elem.value;\n\t\t\t\t\telem.setAttribute( \"type\", value );\n\t\t\t\t\tif ( val ) {\n\t\t\t\t\t\telem.value = val;\n\t\t\t\t\t}\n\t\t\t\t\treturn value;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\n\tpropFix: {\n\t\ttabindex: \"tabIndex\",\n\t\treadonly: \"readOnly\",\n\t\t\"for\": \"htmlFor\",\n\t\t\"class\": \"className\",\n\t\tmaxlength: \"maxLength\",\n\t\tcellspacing: \"cellSpacing\",\n\t\tcellpadding: \"cellPadding\",\n\t\trowspan: \"rowSpan\",\n\t\tcolspan: \"colSpan\",\n\t\tusemap: \"useMap\",\n\t\tframeborder: \"frameBorder\",\n\t\tcontenteditable: \"contentEditable\"\n\t},\n\n\tprop: function( elem, name, value ) {\n\t\tvar ret, hooks, notxml,\n\t\t\tnType = elem.nodeType;\n\n\t\t// don't get/set properties on text, comment and attribute nodes\n\t\tif ( !elem || nType === 3 || nType === 8 || nType === 2 ) {\n\t\t\treturn;\n\t\t}\n\n\t\tnotxml = nType !== 1 || !jQuery.isXMLDoc( elem );\n\n\t\tif ( notxml ) {\n\t\t\t// Fix name and attach hooks\n\t\t\tname = jQuery.propFix[ name ] || name;\n\t\t\thooks = jQuery.propHooks[ name ];\n\t\t}\n\n\t\tif ( value !== undefined ) {\n\t\t\tif ( hooks && \"set\" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) {\n\t\t\t\treturn ret;\n\n\t\t\t} else {\n\t\t\t\treturn ( elem[ name ] = value );\n\t\t\t}\n\n\t\t} else {\n\t\t\tif ( hooks && \"get\" in hooks && (ret = hooks.get( elem, name )) !== null ) {\n\t\t\t\treturn ret;\n\n\t\t\t} else {\n\t\t\t\treturn elem[ name ];\n\t\t\t}\n\t\t}\n\t},\n\n\tpropHooks: {\n\t\ttabIndex: {\n\t\t\tget: function( elem ) {\n\t\t\t\t// elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set\n\t\t\t\t// http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/\n\t\t\t\tvar attributeNode = elem.getAttributeNode(\"tabindex\");\n\n\t\t\t\treturn attributeNode && attributeNode.specified ?\n\t\t\t\t\tparseInt( attributeNode.value, 10 ) :\n\t\t\t\t\trfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ?\n\t\t\t\t\t\t0 :\n\t\t\t\t\t\tundefined;\n\t\t\t}\n\t\t}\n\t}\n});\n\n// Hook for boolean attributes\nboolHook = {\n\tget: function( elem, name ) {\n\t\tvar\n\t\t\t// Use .prop to determine if this attribute is understood as boolean\n\t\t\tprop = jQuery.prop( elem, name ),\n\n\t\t\t// Fetch it accordingly\n\t\t\tattr = typeof prop === \"boolean\" && elem.getAttribute( name ),\n\t\t\tdetail = typeof prop === \"boolean\" ?\n\n\t\t\t\tgetSetInput && getSetAttribute ?\n\t\t\t\t\tattr != null :\n\t\t\t\t\t// oldIE fabricates an empty string for missing boolean attributes\n\t\t\t\t\t// and conflates checked/selected into attroperties\n\t\t\t\t\truseDefault.test( name ) ?\n\t\t\t\t\t\telem[ jQuery.camelCase( \"default-\" + name ) ] :\n\t\t\t\t\t\t!!attr :\n\n\t\t\t\t// fetch an attribute node for properties not recognized as boolean\n\t\t\t\telem.getAttributeNode( name );\n\n\t\treturn detail && detail.value !== false ?\n\t\t\tname.toLowerCase() :\n\t\t\tundefined;\n\t},\n\tset: function( elem, value, name ) {\n\t\tif ( value === false ) {\n\t\t\t// Remove boolean attributes when set to false\n\t\t\tjQuery.removeAttr( elem, name );\n\t\t} else if ( getSetInput && getSetAttribute || !ruseDefault.test( name ) ) {\n\t\t\t// IE<8 needs the *property* name\n\t\t\telem.setAttribute( !getSetAttribute && jQuery.propFix[ name ] || name, name );\n\n\t\t// Use defaultChecked and defaultSelected for oldIE\n\t\t} else {\n\t\t\telem[ jQuery.camelCase( \"default-\" + name ) ] = elem[ name ] = true;\n\t\t}\n\n\t\treturn name;\n\t}\n};\n\n// fix oldIE value attroperty\nif ( !getSetInput || !getSetAttribute ) {\n\tjQuery.attrHooks.value = {\n\t\tget: function( elem, name ) {\n\t\t\tvar ret = elem.getAttributeNode( name );\n\t\t\treturn jQuery.nodeName( elem, \"input\" ) ?\n\n\t\t\t\t// Ignore the value *property* by using defaultValue\n\t\t\t\telem.defaultValue :\n\n\t\t\t\tret && ret.specified ? ret.value : undefined;\n\t\t},\n\t\tset: function( elem, value, name ) {\n\t\t\tif ( jQuery.nodeName( elem, \"input\" ) ) {\n\t\t\t\t// Does not return so that setAttribute is also used\n\t\t\t\telem.defaultValue = value;\n\t\t\t} else {\n\t\t\t\t// Use nodeHook if defined (#1954); otherwise setAttribute is fine\n\t\t\t\treturn nodeHook && nodeHook.set( elem, value, name );\n\t\t\t}\n\t\t}\n\t};\n}\n\n// IE6/7 do not support getting/setting some attributes with get/setAttribute\nif ( !getSetAttribute ) {\n\n\t// Use this for any attribute in IE6/7\n\t// This fixes almost every IE6/7 issue\n\tnodeHook = jQuery.valHooks.button = {\n\t\tget: function( elem, name ) {\n\t\t\tvar ret = elem.getAttributeNode( name );\n\t\t\treturn ret && ( name === \"id\" || name === \"name\" || name === \"coords\" ? ret.value !== \"\" : ret.specified ) ?\n\t\t\t\tret.value :\n\t\t\t\tundefined;\n\t\t},\n\t\tset: function( elem, value, name ) {\n\t\t\t// Set the existing or create a new attribute node\n\t\t\tvar ret = elem.getAttributeNode( name );\n\t\t\tif ( !ret ) {\n\t\t\t\telem.setAttributeNode(\n\t\t\t\t\t(ret = elem.ownerDocument.createAttribute( name ))\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tret.value = value += \"\";\n\n\t\t\t// Break association with cloned elements by also using setAttribute (#9646)\n\t\t\treturn name === \"value\" || value === elem.getAttribute( name ) ?\n\t\t\t\tvalue :\n\t\t\t\tundefined;\n\t\t}\n\t};\n\n\t// Set contenteditable to false on removals(#10429)\n\t// Setting to empty string throws an error as an invalid value\n\tjQuery.attrHooks.contenteditable = {\n\t\tget: nodeHook.get,\n\t\tset: function( elem, value, name ) {\n\t\t\tnodeHook.set( elem, value === \"\" ? false : value, name );\n\t\t}\n\t};\n\n\t// Set width and height to auto instead of 0 on empty string( Bug #8150 )\n\t// This is for removals\n\tjQuery.each([ \"width\", \"height\" ], function( i, name ) {\n\t\tjQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], {\n\t\t\tset: function( elem, value ) {\n\t\t\t\tif ( value === \"\" ) {\n\t\t\t\t\telem.setAttribute( name, \"auto\" );\n\t\t\t\t\treturn value;\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t});\n}\n\n\n// Some attributes require a special call on IE\n// http://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx\nif ( !jQuery.support.hrefNormalized ) {\n\tjQuery.each([ \"href\", \"src\", \"width\", \"height\" ], function( i, name ) {\n\t\tjQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], {\n\t\t\tget: function( elem ) {\n\t\t\t\tvar ret = elem.getAttribute( name, 2 );\n\t\t\t\treturn ret == null ? undefined : ret;\n\t\t\t}\n\t\t});\n\t});\n\n\t// href/src property should get the full normalized URL (#10299/#12915)\n\tjQuery.each([ \"href\", \"src\" ], function( i, name ) {\n\t\tjQuery.propHooks[ name ] = {\n\t\t\tget: function( elem ) {\n\t\t\t\treturn elem.getAttribute( name, 4 );\n\t\t\t}\n\t\t};\n\t});\n}\n\nif ( !jQuery.support.style ) {\n\tjQuery.attrHooks.style = {\n\t\tget: function( elem ) {\n\t\t\t// Return undefined in the case of empty string\n\t\t\t// Note: IE uppercases css property names, but if we were to .toLowerCase()\n\t\t\t// .cssText, that would destroy case senstitivity in URL's, like in \"background\"\n\t\t\treturn elem.style.cssText || undefined;\n\t\t},\n\t\tset: function( elem, value ) {\n\t\t\treturn ( elem.style.cssText = value + \"\" );\n\t\t}\n\t};\n}\n\n// Safari mis-reports the default selected property of an option\n// Accessing the parent's selectedIndex property fixes it\nif ( !jQuery.support.optSelected ) {\n\tjQuery.propHooks.selected = jQuery.extend( jQuery.propHooks.selected, {\n\t\tget: function( elem ) {\n\t\t\tvar parent = elem.parentNode;\n\n\t\t\tif ( parent ) {\n\t\t\t\tparent.selectedIndex;\n\n\t\t\t\t// Make sure that it also works with optgroups, see #5701\n\t\t\t\tif ( parent.parentNode ) {\n\t\t\t\t\tparent.parentNode.selectedIndex;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn null;\n\t\t}\n\t});\n}\n\n// IE6/7 call enctype encoding\nif ( !jQuery.support.enctype ) {\n\tjQuery.propFix.enctype = \"encoding\";\n}\n\n// Radios and checkboxes getter/setter\nif ( !jQuery.support.checkOn ) {\n\tjQuery.each([ \"radio\", \"checkbox\" ], function() {\n\t\tjQuery.valHooks[ this ] = {\n\t\t\tget: function( elem ) {\n\t\t\t\t// Handle the case where in Webkit \"\" is returned instead of \"on\" if a value isn't specified\n\t\t\t\treturn elem.getAttribute(\"value\") === null ? \"on\" : elem.value;\n\t\t\t}\n\t\t};\n\t});\n}\njQuery.each([ \"radio\", \"checkbox\" ], function() {\n\tjQuery.valHooks[ this ] = jQuery.extend( jQuery.valHooks[ this ], {\n\t\tset: function( elem, value ) {\n\t\t\tif ( jQuery.isArray( value ) ) {\n\t\t\t\treturn ( elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0 );\n\t\t\t}\n\t\t}\n\t});\n});\nvar rformElems = /^(?:input|select|textarea)$/i,\n\trkeyEvent = /^key/,\n\trmouseEvent = /^(?:mouse|contextmenu)|click/,\n\trfocusMorph = /^(?:focusinfocus|focusoutblur)$/,\n\trtypenamespace = /^([^.]*)(?:\\.(.+)|)$/;\n\nfunction returnTrue() {\n\treturn true;\n}\n\nfunction returnFalse() {\n\treturn false;\n}\n\n/*\n * Helper functions for managing events -- not part of the public interface.\n * Props to Dean Edwards' addEvent library for many of the ideas.\n */\njQuery.event = {\n\n\tglobal: {},\n\n\tadd: function( elem, types, handler, data, selector ) {\n\t\tvar tmp, events, t, handleObjIn,\n\t\t\tspecial, eventHandle, handleObj,\n\t\t\thandlers, type, namespaces, origType,\n\t\t\telemData = jQuery._data( elem );\n\n\t\t// Don't attach events to noData or text/comment nodes (but allow plain objects)\n\t\tif ( !elemData ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Caller can pass in an object of custom data in lieu of the handler\n\t\tif ( handler.handler ) {\n\t\t\thandleObjIn = handler;\n\t\t\thandler = handleObjIn.handler;\n\t\t\tselector = handleObjIn.selector;\n\t\t}\n\n\t\t// Make sure that the handler has a unique ID, used to find/remove it later\n\t\tif ( !handler.guid ) {\n\t\t\thandler.guid = jQuery.guid++;\n\t\t}\n\n\t\t// Init the element's event structure and main handler, if this is the first\n\t\tif ( !(events = elemData.events) ) {\n\t\t\tevents = elemData.events = {};\n\t\t}\n\t\tif ( !(eventHandle = elemData.handle) ) {\n\t\t\teventHandle = elemData.handle = function( e ) {\n\t\t\t\t// Discard the second event of a jQuery.event.trigger() and\n\t\t\t\t// when an event is called after a page has unloaded\n\t\t\t\treturn typeof jQuery !== core_strundefined && (!e || jQuery.event.triggered !== e.type) ?\n\t\t\t\t\tjQuery.event.dispatch.apply( eventHandle.elem, arguments ) :\n\t\t\t\t\tundefined;\n\t\t\t};\n\t\t\t// Add elem as a property of the handle fn to prevent a memory leak with IE non-native events\n\t\t\teventHandle.elem = elem;\n\t\t}\n\n\t\t// Handle multiple events separated by a space\n\t\t// jQuery(...).bind(\"mouseover mouseout\", fn);\n\t\ttypes = ( types || \"\" ).match( core_rnotwhite ) || [\"\"];\n\t\tt = types.length;\n\t\twhile ( t-- ) {\n\t\t\ttmp = rtypenamespace.exec( types[t] ) || [];\n\t\t\ttype = origType = tmp[1];\n\t\t\tnamespaces = ( tmp[2] || \"\" ).split( \".\" ).sort();\n\n\t\t\t// If event changes its type, use the special event handlers for the changed type\n\t\t\tspecial = jQuery.event.special[ type ] || {};\n\n\t\t\t// If selector defined, determine special event api type, otherwise given type\n\t\t\ttype = ( selector ? special.delegateType : special.bindType ) || type;\n\n\t\t\t// Update special based on newly reset type\n\t\t\tspecial = jQuery.event.special[ type ] || {};\n\n\t\t\t// handleObj is passed to all event handlers\n\t\t\thandleObj = jQuery.extend({\n\t\t\t\ttype: type,\n\t\t\t\torigType: origType,\n\t\t\t\tdata: data,\n\t\t\t\thandler: handler,\n\t\t\t\tguid: handler.guid,\n\t\t\t\tselector: selector,\n\t\t\t\tneedsContext: selector && jQuery.expr.match.needsContext.test( selector ),\n\t\t\t\tnamespace: namespaces.join(\".\")\n\t\t\t}, handleObjIn );\n\n\t\t\t// Init the event handler queue if we're the first\n\t\t\tif ( !(handlers = events[ type ]) ) {\n\t\t\t\thandlers = events[ type ] = [];\n\t\t\t\thandlers.delegateCount = 0;\n\n\t\t\t\t// Only use addEventListener/attachEvent if the special events handler returns false\n\t\t\t\tif ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) {\n\t\t\t\t\t// Bind the global event handler to the element\n\t\t\t\t\tif ( elem.addEventListener ) {\n\t\t\t\t\t\telem.addEventListener( type, eventHandle, false );\n\n\t\t\t\t\t} else if ( elem.attachEvent ) {\n\t\t\t\t\t\telem.attachEvent( \"on\" + type, eventHandle );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( special.add ) {\n\t\t\t\tspecial.add.call( elem, handleObj );\n\n\t\t\t\tif ( !handleObj.handler.guid ) {\n\t\t\t\t\thandleObj.handler.guid = handler.guid;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Add to the element's handler list, delegates in front\n\t\t\tif ( selector ) {\n\t\t\t\thandlers.splice( handlers.delegateCount++, 0, handleObj );\n\t\t\t} else {\n\t\t\t\thandlers.push( handleObj );\n\t\t\t}\n\n\t\t\t// Keep track of which events have ever been used, for event optimization\n\t\t\tjQuery.event.global[ type ] = true;\n\t\t}\n\n\t\t// Nullify elem to prevent memory leaks in IE\n\t\telem = null;\n\t},\n\n\t// Detach an event or set of events from an element\n\tremove: function( elem, types, handler, selector, mappedTypes ) {\n\t\tvar j, handleObj, tmp,\n\t\t\torigCount, t, events,\n\t\t\tspecial, handlers, type,\n\t\t\tnamespaces, origType,\n\t\t\telemData = jQuery.hasData( elem ) && jQuery._data( elem );\n\n\t\tif ( !elemData || !(events = elemData.events) ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Once for each type.namespace in types; type may be omitted\n\t\ttypes = ( types || \"\" ).match( core_rnotwhite ) || [\"\"];\n\t\tt = types.length;\n\t\twhile ( t-- ) {\n\t\t\ttmp = rtypenamespace.exec( types[t] ) || [];\n\t\t\ttype = origType = tmp[1];\n\t\t\tnamespaces = ( tmp[2] || \"\" ).split( \".\" ).sort();\n\n\t\t\t// Unbind all events (on this namespace, if provided) for the element\n\t\t\tif ( !type ) {\n\t\t\t\tfor ( type in events ) {\n\t\t\t\t\tjQuery.event.remove( elem, type + types[ t ], handler, selector, true );\n\t\t\t\t}\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tspecial = jQuery.event.special[ type ] || {};\n\t\t\ttype = ( selector ? special.delegateType : special.bindType ) || type;\n\t\t\thandlers = events[ type ] || [];\n\t\t\ttmp = tmp[2] && new RegExp( \"(^|\\\\.)\" + namespaces.join(\"\\\\.(?:.*\\\\.|)\") + \"(\\\\.|$)\" );\n\n\t\t\t// Remove matching events\n\t\t\torigCount = j = handlers.length;\n\t\t\twhile ( j-- ) {\n\t\t\t\thandleObj = handlers[ j ];\n\n\t\t\t\tif ( ( mappedTypes || origType === handleObj.origType ) &&\n\t\t\t\t\t( !handler || handler.guid === handleObj.guid ) &&\n\t\t\t\t\t( !tmp || tmp.test( handleObj.namespace ) ) &&\n\t\t\t\t\t( !selector || selector === handleObj.selector || selector === \"**\" && handleObj.selector ) ) {\n\t\t\t\t\thandlers.splice( j, 1 );\n\n\t\t\t\t\tif ( handleObj.selector ) {\n\t\t\t\t\t\thandlers.delegateCount--;\n\t\t\t\t\t}\n\t\t\t\t\tif ( special.remove ) {\n\t\t\t\t\t\tspecial.remove.call( elem, handleObj );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Remove generic event handler if we removed something and no more handlers exist\n\t\t\t// (avoids potential for endless recursion during removal of special event handlers)\n\t\t\tif ( origCount && !handlers.length ) {\n\t\t\t\tif ( !special.teardown || special.teardown.call( elem, namespaces, elemData.handle ) === false ) {\n\t\t\t\t\tjQuery.removeEvent( elem, type, elemData.handle );\n\t\t\t\t}\n\n\t\t\t\tdelete events[ type ];\n\t\t\t}\n\t\t}\n\n\t\t// Remove the expando if it's no longer used\n\t\tif ( jQuery.isEmptyObject( events ) ) {\n\t\t\tdelete elemData.handle;\n\n\t\t\t// removeData also checks for emptiness and clears the expando if empty\n\t\t\t// so use it instead of delete\n\t\t\tjQuery._removeData( elem, \"events\" );\n\t\t}\n\t},\n\n\ttrigger: function( event, data, elem, onlyHandlers ) {\n\t\tvar handle, ontype, cur,\n\t\t\tbubbleType, special, tmp, i,\n\t\t\teventPath = [ elem || document ],\n\t\t\ttype = core_hasOwn.call( event, \"type\" ) ? event.type : event,\n\t\t\tnamespaces = core_hasOwn.call( event, \"namespace\" ) ? event.namespace.split(\".\") : [];\n\n\t\tcur = tmp = elem = elem || document;\n\n\t\t// Don't do events on text and comment nodes\n\t\tif ( elem.nodeType === 3 || elem.nodeType === 8 ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// focus/blur morphs to focusin/out; ensure we're not firing them right now\n\t\tif ( rfocusMorph.test( type + jQuery.event.triggered ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( type.indexOf(\".\") >= 0 ) {\n\t\t\t// Namespaced trigger; create a regexp to match event type in handle()\n\t\t\tnamespaces = type.split(\".\");\n\t\t\ttype = namespaces.shift();\n\t\t\tnamespaces.sort();\n\t\t}\n\t\tontype = type.indexOf(\":\") < 0 && \"on\" + type;\n\n\t\t// Caller can pass in a jQuery.Event object, Object, or just an event type string\n\t\tevent = event[ jQuery.expando ] ?\n\t\t\tevent :\n\t\t\tnew jQuery.Event( type, typeof event === \"object\" && event );\n\n\t\tevent.isTrigger = true;\n\t\tevent.namespace = namespaces.join(\".\");\n\t\tevent.namespace_re = event.namespace ?\n\t\t\tnew RegExp( \"(^|\\\\.)\" + namespaces.join(\"\\\\.(?:.*\\\\.|)\") + \"(\\\\.|$)\" ) :\n\t\t\tnull;\n\n\t\t// Clean up the event in case it is being reused\n\t\tevent.result = undefined;\n\t\tif ( !event.target ) {\n\t\t\tevent.target = elem;\n\t\t}\n\n\t\t// Clone any incoming data and prepend the event, creating the handler arg list\n\t\tdata = data == null ?\n\t\t\t[ event ] :\n\t\t\tjQuery.makeArray( data, [ event ] );\n\n\t\t// Allow special events to draw outside the lines\n\t\tspecial = jQuery.event.special[ type ] || {};\n\t\tif ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Determine event propagation path in advance, per W3C events spec (#9951)\n\t\t// Bubble up to document, then to window; watch for a global ownerDocument var (#9724)\n\t\tif ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) {\n\n\t\t\tbubbleType = special.delegateType || type;\n\t\t\tif ( !rfocusMorph.test( bubbleType + type ) ) {\n\t\t\t\tcur = cur.parentNode;\n\t\t\t}\n\t\t\tfor ( ; cur; cur = cur.parentNode ) {\n\t\t\t\teventPath.push( cur );\n\t\t\t\ttmp = cur;\n\t\t\t}\n\n\t\t\t// Only add window if we got to document (e.g., not plain obj or detached DOM)\n\t\t\tif ( tmp === (elem.ownerDocument || document) ) {\n\t\t\t\teventPath.push( tmp.defaultView || tmp.parentWindow || window );\n\t\t\t}\n\t\t}\n\n\t\t// Fire handlers on the event path\n\t\ti = 0;\n\t\twhile ( (cur = eventPath[i++]) && !event.isPropagationStopped() ) {\n\n\t\t\tevent.type = i > 1 ?\n\t\t\t\tbubbleType :\n\t\t\t\tspecial.bindType || type;\n\n\t\t\t// jQuery handler\n\t\t\thandle = ( jQuery._data( cur, \"events\" ) || {} )[ event.type ] && jQuery._data( cur, \"handle\" );\n\t\t\tif ( handle ) {\n\t\t\t\thandle.apply( cur, data );\n\t\t\t}\n\n\t\t\t// Native handler\n\t\t\thandle = ontype && cur[ ontype ];\n\t\t\tif ( handle && jQuery.acceptData( cur ) && handle.apply && handle.apply( cur, data ) === false ) {\n\t\t\t\tevent.preventDefault();\n\t\t\t}\n\t\t}\n\t\tevent.type = type;\n\n\t\t// If nobody prevented the default action, do it now\n\t\tif ( !onlyHandlers && !event.isDefaultPrevented() ) {\n\n\t\t\tif ( (!special._default || special._default.apply( elem.ownerDocument, data ) === false) &&\n\t\t\t\t!(type === \"click\" && jQuery.nodeName( elem, \"a\" )) && jQuery.acceptData( elem ) ) {\n\n\t\t\t\t// Call a native DOM method on the target with the same name name as the event.\n\t\t\t\t// Can't use an .isFunction() check here because IE6/7 fails that test.\n\t\t\t\t// Don't do default actions on window, that's where global variables be (#6170)\n\t\t\t\tif ( ontype && elem[ type ] && !jQuery.isWindow( elem ) ) {\n\n\t\t\t\t\t// Don't re-trigger an onFOO event when we call its FOO() method\n\t\t\t\t\ttmp = elem[ ontype ];\n\n\t\t\t\t\tif ( tmp ) {\n\t\t\t\t\t\telem[ ontype ] = null;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Prevent re-triggering of the same event, since we already bubbled it above\n\t\t\t\t\tjQuery.event.triggered = type;\n\t\t\t\t\ttry {\n\t\t\t\t\t\telem[ type ]();\n\t\t\t\t\t} catch ( e ) {\n\t\t\t\t\t\t// IE<9 dies on focus/blur to hidden element (#1486,#12518)\n\t\t\t\t\t\t// only reproducible on winXP IE8 native, not IE9 in IE8 mode\n\t\t\t\t\t}\n\t\t\t\t\tjQuery.event.triggered = undefined;\n\n\t\t\t\t\tif ( tmp ) {\n\t\t\t\t\t\telem[ ontype ] = tmp;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn event.result;\n\t},\n\n\tdispatch: function( event ) {\n\n\t\t// Make a writable jQuery.Event from the native event object\n\t\tevent = jQuery.event.fix( event );\n\n\t\tvar i, ret, handleObj, matched, j,\n\t\t\thandlerQueue = [],\n\t\t\targs = core_slice.call( arguments ),\n\t\t\thandlers = ( jQuery._data( this, \"events\" ) || {} )[ event.type ] || [],\n\t\t\tspecial = jQuery.event.special[ event.type ] || {};\n\n\t\t// Use the fix-ed jQuery.Event rather than the (read-only) native event\n\t\targs[0] = event;\n\t\tevent.delegateTarget = this;\n\n\t\t// Call the preDispatch hook for the mapped type, and let it bail if desired\n\t\tif ( special.preDispatch && special.preDispatch.call( this, event ) === false ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Determine handlers\n\t\thandlerQueue = jQuery.event.handlers.call( this, event, handlers );\n\n\t\t// Run delegates first; they may want to stop propagation beneath us\n\t\ti = 0;\n\t\twhile ( (matched = handlerQueue[ i++ ]) && !event.isPropagationStopped() ) {\n\t\t\tevent.currentTarget = matched.elem;\n\n\t\t\tj = 0;\n\t\t\twhile ( (handleObj = matched.handlers[ j++ ]) && !event.isImmediatePropagationStopped() ) {\n\n\t\t\t\t// Triggered event must either 1) have no namespace, or\n\t\t\t\t// 2) have namespace(s) a subset or equal to those in the bound event (both can have no namespace).\n\t\t\t\tif ( !event.namespace_re || event.namespace_re.test( handleObj.namespace ) ) {\n\n\t\t\t\t\tevent.handleObj = handleObj;\n\t\t\t\t\tevent.data = handleObj.data;\n\n\t\t\t\t\tret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler )\n\t\t\t\t\t\t\t.apply( matched.elem, args );\n\n\t\t\t\t\tif ( ret !== undefined ) {\n\t\t\t\t\t\tif ( (event.result = ret) === false ) {\n\t\t\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\t\t\tevent.stopPropagation();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Call the postDispatch hook for the mapped type\n\t\tif ( special.postDispatch ) {\n\t\t\tspecial.postDispatch.call( this, event );\n\t\t}\n\n\t\treturn event.result;\n\t},\n\n\thandlers: function( event, handlers ) {\n\t\tvar sel, handleObj, matches, i,\n\t\t\thandlerQueue = [],\n\t\t\tdelegateCount = handlers.delegateCount,\n\t\t\tcur = event.target;\n\n\t\t// Find delegate handlers\n\t\t// Black-hole SVG <use> instance trees (#13180)\n\t\t// Avoid non-left-click bubbling in Firefox (#3861)\n\t\tif ( delegateCount && cur.nodeType && (!event.button || event.type !== \"click\") ) {\n\n\t\t\tfor ( ; cur != this; cur = cur.parentNode || this ) {\n\n\t\t\t\t// Don't check non-elements (#13208)\n\t\t\t\t// Don't process clicks on disabled elements (#6911, #8165, #11382, #11764)\n\t\t\t\tif ( cur.nodeType === 1 && (cur.disabled !== true || event.type !== \"click\") ) {\n\t\t\t\t\tmatches = [];\n\t\t\t\t\tfor ( i = 0; i < delegateCount; i++ ) {\n\t\t\t\t\t\thandleObj = handlers[ i ];\n\n\t\t\t\t\t\t// Don't conflict with Object.prototype properties (#13203)\n\t\t\t\t\t\tsel = handleObj.selector + \" \";\n\n\t\t\t\t\t\tif ( matches[ sel ] === undefined ) {\n\t\t\t\t\t\t\tmatches[ sel ] = handleObj.needsContext ?\n\t\t\t\t\t\t\t\tjQuery( sel, this ).index( cur ) >= 0 :\n\t\t\t\t\t\t\t\tjQuery.find( sel, this, null, [ cur ] ).length;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif ( matches[ sel ] ) {\n\t\t\t\t\t\t\tmatches.push( handleObj );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif ( matches.length ) {\n\t\t\t\t\t\thandlerQueue.push({ elem: cur, handlers: matches });\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Add the remaining (directly-bound) handlers\n\t\tif ( delegateCount < handlers.length ) {\n\t\t\thandlerQueue.push({ elem: this, handlers: handlers.slice( delegateCount ) });\n\t\t}\n\n\t\treturn handlerQueue;\n\t},\n\n\tfix: function( event ) {\n\t\tif ( event[ jQuery.expando ] ) {\n\t\t\treturn event;\n\t\t}\n\n\t\t// Create a writable copy of the event object and normalize some properties\n\t\tvar i, prop, copy,\n\t\t\ttype = event.type,\n\t\t\toriginalEvent = event,\n\t\t\tfixHook = this.fixHooks[ type ];\n\n\t\tif ( !fixHook ) {\n\t\t\tthis.fixHooks[ type ] = fixHook =\n\t\t\t\trmouseEvent.test( type ) ? this.mouseHooks :\n\t\t\t\trkeyEvent.test( type ) ? this.keyHooks :\n\t\t\t\t{};\n\t\t}\n\t\tcopy = fixHook.props ? this.props.concat( fixHook.props ) : this.props;\n\n\t\tevent = new jQuery.Event( originalEvent );\n\n\t\ti = copy.length;\n\t\twhile ( i-- ) {\n\t\t\tprop = copy[ i ];\n\t\t\tevent[ prop ] = originalEvent[ prop ];\n\t\t}\n\n\t\t// Support: IE<9\n\t\t// Fix target property (#1925)\n\t\tif ( !event.target ) {\n\t\t\tevent.target = originalEvent.srcElement || document;\n\t\t}\n\n\t\t// Support: Chrome 23+, Safari?\n\t\t// Target should not be a text node (#504, #13143)\n\t\tif ( event.target.nodeType === 3 ) {\n\t\t\tevent.target = event.target.parentNode;\n\t\t}\n\n\t\t// Support: IE<9\n\t\t// For mouse/key events, metaKey==false if it's undefined (#3368, #11328)\n\t\tevent.metaKey = !!event.metaKey;\n\n\t\treturn fixHook.filter ? fixHook.filter( event, originalEvent ) : event;\n\t},\n\n\t// Includes some event props shared by KeyEvent and MouseEvent\n\tprops: \"altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which\".split(\" \"),\n\n\tfixHooks: {},\n\n\tkeyHooks: {\n\t\tprops: \"char charCode key keyCode\".split(\" \"),\n\t\tfilter: function( event, original ) {\n\n\t\t\t// Add which for key events\n\t\t\tif ( event.which == null ) {\n\t\t\t\tevent.which = original.charCode != null ? original.charCode : original.keyCode;\n\t\t\t}\n\n\t\t\treturn event;\n\t\t}\n\t},\n\n\tmouseHooks: {\n\t\tprops: \"button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement\".split(\" \"),\n\t\tfilter: function( event, original ) {\n\t\t\tvar body, eventDoc, doc,\n\t\t\t\tbutton = original.button,\n\t\t\t\tfromElement = original.fromElement;\n\n\t\t\t// Calculate pageX/Y if missing and clientX/Y available\n\t\t\tif ( event.pageX == null && original.clientX != null ) {\n\t\t\t\teventDoc = event.target.ownerDocument || document;\n\t\t\t\tdoc = eventDoc.documentElement;\n\t\t\t\tbody = eventDoc.body;\n\n\t\t\t\tevent.pageX = original.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && body.clientLeft || 0 );\n\t\t\t\tevent.pageY = original.clientY + ( doc && doc.scrollTop  || body && body.scrollTop  || 0 ) - ( doc && doc.clientTop  || body && body.clientTop  || 0 );\n\t\t\t}\n\n\t\t\t// Add relatedTarget, if necessary\n\t\t\tif ( !event.relatedTarget && fromElement ) {\n\t\t\t\tevent.relatedTarget = fromElement === event.target ? original.toElement : fromElement;\n\t\t\t}\n\n\t\t\t// Add which for click: 1 === left; 2 === middle; 3 === right\n\t\t\t// Note: button is not normalized, so don't use it\n\t\t\tif ( !event.which && button !== undefined ) {\n\t\t\t\tevent.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) );\n\t\t\t}\n\n\t\t\treturn event;\n\t\t}\n\t},\n\n\tspecial: {\n\t\tload: {\n\t\t\t// Prevent triggered image.load events from bubbling to window.load\n\t\t\tnoBubble: true\n\t\t},\n\t\tclick: {\n\t\t\t// For checkbox, fire native event so checked state will be right\n\t\t\ttrigger: function() {\n\t\t\t\tif ( jQuery.nodeName( this, \"input\" ) && this.type === \"checkbox\" && this.click ) {\n\t\t\t\t\tthis.click();\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\tfocus: {\n\t\t\t// Fire native event if possible so blur/focus sequence is correct\n\t\t\ttrigger: function() {\n\t\t\t\tif ( this !== document.activeElement && this.focus ) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tthis.focus();\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t} catch ( e ) {\n\t\t\t\t\t\t// Support: IE<9\n\t\t\t\t\t\t// If we error on focus to hidden element (#1486, #12518),\n\t\t\t\t\t\t// let .trigger() run the handlers\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\tdelegateType: \"focusin\"\n\t\t},\n\t\tblur: {\n\t\t\ttrigger: function() {\n\t\t\t\tif ( this === document.activeElement && this.blur ) {\n\t\t\t\t\tthis.blur();\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t},\n\t\t\tdelegateType: \"focusout\"\n\t\t},\n\n\t\tbeforeunload: {\n\t\t\tpostDispatch: function( event ) {\n\n\t\t\t\t// Even when returnValue equals to undefined Firefox will still show alert\n\t\t\t\tif ( event.result !== undefined ) {\n\t\t\t\t\tevent.originalEvent.returnValue = event.result;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\n\tsimulate: function( type, elem, event, bubble ) {\n\t\t// Piggyback on a donor event to simulate a different one.\n\t\t// Fake originalEvent to avoid donor's stopPropagation, but if the\n\t\t// simulated event prevents default then we do the same on the donor.\n\t\tvar e = jQuery.extend(\n\t\t\tnew jQuery.Event(),\n\t\t\tevent,\n\t\t\t{ type: type,\n\t\t\t\tisSimulated: true,\n\t\t\t\toriginalEvent: {}\n\t\t\t}\n\t\t);\n\t\tif ( bubble ) {\n\t\t\tjQuery.event.trigger( e, null, elem );\n\t\t} else {\n\t\t\tjQuery.event.dispatch.call( elem, e );\n\t\t}\n\t\tif ( e.isDefaultPrevented() ) {\n\t\t\tevent.preventDefault();\n\t\t}\n\t}\n};\n\njQuery.removeEvent = document.removeEventListener ?\n\tfunction( elem, type, handle ) {\n\t\tif ( elem.removeEventListener ) {\n\t\t\telem.removeEventListener( type, handle, false );\n\t\t}\n\t} :\n\tfunction( elem, type, handle ) {\n\t\tvar name = \"on\" + type;\n\n\t\tif ( elem.detachEvent ) {\n\n\t\t\t// #8545, #7054, preventing memory leaks for custom events in IE6-8\n\t\t\t// detachEvent needed property on element, by name of that event, to properly expose it to GC\n\t\t\tif ( typeof elem[ name ] === core_strundefined ) {\n\t\t\t\telem[ name ] = null;\n\t\t\t}\n\n\t\t\telem.detachEvent( name, handle );\n\t\t}\n\t};\n\njQuery.Event = function( src, props ) {\n\t// Allow instantiation without the 'new' keyword\n\tif ( !(this instanceof jQuery.Event) ) {\n\t\treturn new jQuery.Event( src, props );\n\t}\n\n\t// Event object\n\tif ( src && src.type ) {\n\t\tthis.originalEvent = src;\n\t\tthis.type = src.type;\n\n\t\t// Events bubbling up the document may have been marked as prevented\n\t\t// by a handler lower down the tree; reflect the correct value.\n\t\tthis.isDefaultPrevented = ( src.defaultPrevented || src.returnValue === false ||\n\t\t\tsrc.getPreventDefault && src.getPreventDefault() ) ? returnTrue : returnFalse;\n\n\t// Event type\n\t} else {\n\t\tthis.type = src;\n\t}\n\n\t// Put explicitly provided properties onto the event object\n\tif ( props ) {\n\t\tjQuery.extend( this, props );\n\t}\n\n\t// Create a timestamp if incoming event doesn't have one\n\tthis.timeStamp = src && src.timeStamp || jQuery.now();\n\n\t// Mark it as fixed\n\tthis[ jQuery.expando ] = true;\n};\n\n// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding\n// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html\njQuery.Event.prototype = {\n\tisDefaultPrevented: returnFalse,\n\tisPropagationStopped: returnFalse,\n\tisImmediatePropagationStopped: returnFalse,\n\n\tpreventDefault: function() {\n\t\tvar e = this.originalEvent;\n\n\t\tthis.isDefaultPrevented = returnTrue;\n\t\tif ( !e ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// If preventDefault exists, run it on the original event\n\t\tif ( e.preventDefault ) {\n\t\t\te.preventDefault();\n\n\t\t// Support: IE\n\t\t// Otherwise set the returnValue property of the original event to false\n\t\t} else {\n\t\t\te.returnValue = false;\n\t\t}\n\t},\n\tstopPropagation: function() {\n\t\tvar e = this.originalEvent;\n\n\t\tthis.isPropagationStopped = returnTrue;\n\t\tif ( !e ) {\n\t\t\treturn;\n\t\t}\n\t\t// If stopPropagation exists, run it on the original event\n\t\tif ( e.stopPropagation ) {\n\t\t\te.stopPropagation();\n\t\t}\n\n\t\t// Support: IE\n\t\t// Set the cancelBubble property of the original event to true\n\t\te.cancelBubble = true;\n\t},\n\tstopImmediatePropagation: function() {\n\t\tthis.isImmediatePropagationStopped = returnTrue;\n\t\tthis.stopPropagation();\n\t}\n};\n\n// Create mouseenter/leave events using mouseover/out and event-time checks\njQuery.each({\n\tmouseenter: \"mouseover\",\n\tmouseleave: \"mouseout\"\n}, function( orig, fix ) {\n\tjQuery.event.special[ orig ] = {\n\t\tdelegateType: fix,\n\t\tbindType: fix,\n\n\t\thandle: function( event ) {\n\t\t\tvar ret,\n\t\t\t\ttarget = this,\n\t\t\t\trelated = event.relatedTarget,\n\t\t\t\thandleObj = event.handleObj;\n\n\t\t\t// For mousenter/leave call the handler if related is outside the target.\n\t\t\t// NB: No relatedTarget if the mouse left/entered the browser window\n\t\t\tif ( !related || (related !== target && !jQuery.contains( target, related )) ) {\n\t\t\t\tevent.type = handleObj.origType;\n\t\t\t\tret = handleObj.handler.apply( this, arguments );\n\t\t\t\tevent.type = fix;\n\t\t\t}\n\t\t\treturn ret;\n\t\t}\n\t};\n});\n\n// IE submit delegation\nif ( !jQuery.support.submitBubbles ) {\n\n\tjQuery.event.special.submit = {\n\t\tsetup: function() {\n\t\t\t// Only need this for delegated form submit events\n\t\t\tif ( jQuery.nodeName( this, \"form\" ) ) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\t// Lazy-add a submit handler when a descendant form may potentially be submitted\n\t\t\tjQuery.event.add( this, \"click._submit keypress._submit\", function( e ) {\n\t\t\t\t// Node name check avoids a VML-related crash in IE (#9807)\n\t\t\t\tvar elem = e.target,\n\t\t\t\t\tform = jQuery.nodeName( elem, \"input\" ) || jQuery.nodeName( elem, \"button\" ) ? elem.form : undefined;\n\t\t\t\tif ( form && !jQuery._data( form, \"submitBubbles\" ) ) {\n\t\t\t\t\tjQuery.event.add( form, \"submit._submit\", function( event ) {\n\t\t\t\t\t\tevent._submit_bubble = true;\n\t\t\t\t\t});\n\t\t\t\t\tjQuery._data( form, \"submitBubbles\", true );\n\t\t\t\t}\n\t\t\t});\n\t\t\t// return undefined since we don't need an event listener\n\t\t},\n\n\t\tpostDispatch: function( event ) {\n\t\t\t// If form was submitted by the user, bubble the event up the tree\n\t\t\tif ( event._submit_bubble ) {\n\t\t\t\tdelete event._submit_bubble;\n\t\t\t\tif ( this.parentNode && !event.isTrigger ) {\n\t\t\t\t\tjQuery.event.simulate( \"submit\", this.parentNode, event, true );\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\tteardown: function() {\n\t\t\t// Only need this for delegated form submit events\n\t\t\tif ( jQuery.nodeName( this, \"form\" ) ) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\t// Remove delegated handlers; cleanData eventually reaps submit handlers attached above\n\t\t\tjQuery.event.remove( this, \"._submit\" );\n\t\t}\n\t};\n}\n\n// IE change delegation and checkbox/radio fix\nif ( !jQuery.support.changeBubbles ) {\n\n\tjQuery.event.special.change = {\n\n\t\tsetup: function() {\n\n\t\t\tif ( rformElems.test( this.nodeName ) ) {\n\t\t\t\t// IE doesn't fire change on a check/radio until blur; trigger it on click\n\t\t\t\t// after a propertychange. Eat the blur-change in special.change.handle.\n\t\t\t\t// This still fires onchange a second time for check/radio after blur.\n\t\t\t\tif ( this.type === \"checkbox\" || this.type === \"radio\" ) {\n\t\t\t\t\tjQuery.event.add( this, \"propertychange._change\", function( event ) {\n\t\t\t\t\t\tif ( event.originalEvent.propertyName === \"checked\" ) {\n\t\t\t\t\t\t\tthis._just_changed = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t\tjQuery.event.add( this, \"click._change\", function( event ) {\n\t\t\t\t\t\tif ( this._just_changed && !event.isTrigger ) {\n\t\t\t\t\t\t\tthis._just_changed = false;\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// Allow triggered, simulated change events (#11500)\n\t\t\t\t\t\tjQuery.event.simulate( \"change\", this, event, true );\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\t// Delegated event; lazy-add a change handler on descendant inputs\n\t\t\tjQuery.event.add( this, \"beforeactivate._change\", function( e ) {\n\t\t\t\tvar elem = e.target;\n\n\t\t\t\tif ( rformElems.test( elem.nodeName ) && !jQuery._data( elem, \"changeBubbles\" ) ) {\n\t\t\t\t\tjQuery.event.add( elem, \"change._change\", function( event ) {\n\t\t\t\t\t\tif ( this.parentNode && !event.isSimulated && !event.isTrigger ) {\n\t\t\t\t\t\t\tjQuery.event.simulate( \"change\", this.parentNode, event, true );\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t\tjQuery._data( elem, \"changeBubbles\", true );\n\t\t\t\t}\n\t\t\t});\n\t\t},\n\n\t\thandle: function( event ) {\n\t\t\tvar elem = event.target;\n\n\t\t\t// Swallow native change events from checkbox/radio, we already triggered them above\n\t\t\tif ( this !== elem || event.isSimulated || event.isTrigger || (elem.type !== \"radio\" && elem.type !== \"checkbox\") ) {\n\t\t\t\treturn event.handleObj.handler.apply( this, arguments );\n\t\t\t}\n\t\t},\n\n\t\tteardown: function() {\n\t\t\tjQuery.event.remove( this, \"._change\" );\n\n\t\t\treturn !rformElems.test( this.nodeName );\n\t\t}\n\t};\n}\n\n// Create \"bubbling\" focus and blur events\nif ( !jQuery.support.focusinBubbles ) {\n\tjQuery.each({ focus: \"focusin\", blur: \"focusout\" }, function( orig, fix ) {\n\n\t\t// Attach a single capturing handler while someone wants focusin/focusout\n\t\tvar attaches = 0,\n\t\t\thandler = function( event ) {\n\t\t\t\tjQuery.event.simulate( fix, event.target, jQuery.event.fix( event ), true );\n\t\t\t};\n\n\t\tjQuery.event.special[ fix ] = {\n\t\t\tsetup: function() {\n\t\t\t\tif ( attaches++ === 0 ) {\n\t\t\t\t\tdocument.addEventListener( orig, handler, true );\n\t\t\t\t}\n\t\t\t},\n\t\t\tteardown: function() {\n\t\t\t\tif ( --attaches === 0 ) {\n\t\t\t\t\tdocument.removeEventListener( orig, handler, true );\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t});\n}\n\njQuery.fn.extend({\n\n\ton: function( types, selector, data, fn, /*INTERNAL*/ one ) {\n\t\tvar type, origFn;\n\n\t\t// Types can be a map of types/handlers\n\t\tif ( typeof types === \"object\" ) {\n\t\t\t// ( types-Object, selector, data )\n\t\t\tif ( typeof selector !== \"string\" ) {\n\t\t\t\t// ( types-Object, data )\n\t\t\t\tdata = data || selector;\n\t\t\t\tselector = undefined;\n\t\t\t}\n\t\t\tfor ( type in types ) {\n\t\t\t\tthis.on( type, selector, data, types[ type ], one );\n\t\t\t}\n\t\t\treturn this;\n\t\t}\n\n\t\tif ( data == null && fn == null ) {\n\t\t\t// ( types, fn )\n\t\t\tfn = selector;\n\t\t\tdata = selector = undefined;\n\t\t} else if ( fn == null ) {\n\t\t\tif ( typeof selector === \"string\" ) {\n\t\t\t\t// ( types, selector, fn )\n\t\t\t\tfn = data;\n\t\t\t\tdata = undefined;\n\t\t\t} else {\n\t\t\t\t// ( types, data, fn )\n\t\t\t\tfn = data;\n\t\t\t\tdata = selector;\n\t\t\t\tselector = undefined;\n\t\t\t}\n\t\t}\n\t\tif ( fn === false ) {\n\t\t\tfn = returnFalse;\n\t\t} else if ( !fn ) {\n\t\t\treturn this;\n\t\t}\n\n\t\tif ( one === 1 ) {\n\t\t\torigFn = fn;\n\t\t\tfn = function( event ) {\n\t\t\t\t// Can use an empty set, since event contains the info\n\t\t\t\tjQuery().off( event );\n\t\t\t\treturn origFn.apply( this, arguments );\n\t\t\t};\n\t\t\t// Use same guid so caller can remove using origFn\n\t\t\tfn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ );\n\t\t}\n\t\treturn this.each( function() {\n\t\t\tjQuery.event.add( this, types, fn, data, selector );\n\t\t});\n\t},\n\tone: function( types, selector, data, fn ) {\n\t\treturn this.on( types, selector, data, fn, 1 );\n\t},\n\toff: function( types, selector, fn ) {\n\t\tvar handleObj, type;\n\t\tif ( types && types.preventDefault && types.handleObj ) {\n\t\t\t// ( event )  dispatched jQuery.Event\n\t\t\thandleObj = types.handleObj;\n\t\t\tjQuery( types.delegateTarget ).off(\n\t\t\t\thandleObj.namespace ? handleObj.origType + \".\" + handleObj.namespace : handleObj.origType,\n\t\t\t\thandleObj.selector,\n\t\t\t\thandleObj.handler\n\t\t\t);\n\t\t\treturn this;\n\t\t}\n\t\tif ( typeof types === \"object\" ) {\n\t\t\t// ( types-object [, selector] )\n\t\t\tfor ( type in types ) {\n\t\t\t\tthis.off( type, selector, types[ type ] );\n\t\t\t}\n\t\t\treturn this;\n\t\t}\n\t\tif ( selector === false || typeof selector === \"function\" ) {\n\t\t\t// ( types [, fn] )\n\t\t\tfn = selector;\n\t\t\tselector = undefined;\n\t\t}\n\t\tif ( fn === false ) {\n\t\t\tfn = returnFalse;\n\t\t}\n\t\treturn this.each(function() {\n\t\t\tjQuery.event.remove( this, types, fn, selector );\n\t\t});\n\t},\n\n\tbind: function( types, data, fn ) {\n\t\treturn this.on( types, null, data, fn );\n\t},\n\tunbind: function( types, fn ) {\n\t\treturn this.off( types, null, fn );\n\t},\n\n\tdelegate: function( selector, types, data, fn ) {\n\t\treturn this.on( types, selector, data, fn );\n\t},\n\tundelegate: function( selector, types, fn ) {\n\t\t// ( namespace ) or ( selector, types [, fn] )\n\t\treturn arguments.length === 1 ? this.off( selector, \"**\" ) : this.off( types, selector || \"**\", fn );\n\t},\n\n\ttrigger: function( type, data ) {\n\t\treturn this.each(function() {\n\t\t\tjQuery.event.trigger( type, data, this );\n\t\t});\n\t},\n\ttriggerHandler: function( type, data ) {\n\t\tvar elem = this[0];\n\t\tif ( elem ) {\n\t\t\treturn jQuery.event.trigger( type, data, elem, true );\n\t\t}\n\t}\n});\n/*!\n * Sizzle CSS Selector Engine\n * Copyright 2012 jQuery Foundation and other contributors\n * Released under the MIT license\n * http://sizzlejs.com/\n */\n(function( window, undefined ) {\n\nvar i,\n\tcachedruns,\n\tExpr,\n\tgetText,\n\tisXML,\n\tcompile,\n\thasDuplicate,\n\toutermostContext,\n\n\t// Local document vars\n\tsetDocument,\n\tdocument,\n\tdocElem,\n\tdocumentIsXML,\n\trbuggyQSA,\n\trbuggyMatches,\n\tmatches,\n\tcontains,\n\tsortOrder,\n\n\t// Instance-specific data\n\texpando = \"sizzle\" + -(new Date()),\n\tpreferredDoc = window.document,\n\tsupport = {},\n\tdirruns = 0,\n\tdone = 0,\n\tclassCache = createCache(),\n\ttokenCache = createCache(),\n\tcompilerCache = createCache(),\n\n\t// General-purpose constants\n\tstrundefined = typeof undefined,\n\tMAX_NEGATIVE = 1 << 31,\n\n\t// Array methods\n\tarr = [],\n\tpop = arr.pop,\n\tpush = arr.push,\n\tslice = arr.slice,\n\t// Use a stripped-down indexOf if we can't use a native one\n\tindexOf = arr.indexOf || function( elem ) {\n\t\tvar i = 0,\n\t\t\tlen = this.length;\n\t\tfor ( ; i < len; i++ ) {\n\t\t\tif ( this[i] === elem ) {\n\t\t\t\treturn i;\n\t\t\t}\n\t\t}\n\t\treturn -1;\n\t},\n\n\n\t// Regular expressions\n\n\t// Whitespace characters http://www.w3.org/TR/css3-selectors/#whitespace\n\twhitespace = \"[\\\\x20\\\\t\\\\r\\\\n\\\\f]\",\n\t// http://www.w3.org/TR/css3-syntax/#characters\n\tcharacterEncoding = \"(?:\\\\\\\\.|[\\\\w-]|[^\\\\x00-\\\\xa0])+\",\n\n\t// Loosely modeled on CSS identifier characters\n\t// An unquoted value should be a CSS identifier http://www.w3.org/TR/css3-selectors/#attribute-selectors\n\t// Proper syntax: http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier\n\tidentifier = characterEncoding.replace( \"w\", \"w#\" ),\n\n\t// Acceptable operators http://www.w3.org/TR/selectors/#attribute-selectors\n\toperators = \"([*^$|!~]?=)\",\n\tattributes = \"\\\\[\" + whitespace + \"*(\" + characterEncoding + \")\" + whitespace +\n\t\t\"*(?:\" + operators + whitespace + \"*(?:(['\\\"])((?:\\\\\\\\.|[^\\\\\\\\])*?)\\\\3|(\" + identifier + \")|)|)\" + whitespace + \"*\\\\]\",\n\n\t// Prefer arguments quoted,\n\t//   then not containing pseudos/brackets,\n\t//   then attribute selectors/non-parenthetical expressions,\n\t//   then anything else\n\t// These preferences are here to reduce the number of selectors\n\t//   needing tokenize in the PSEUDO preFilter\n\tpseudos = \":(\" + characterEncoding + \")(?:\\\\(((['\\\"])((?:\\\\\\\\.|[^\\\\\\\\])*?)\\\\3|((?:\\\\\\\\.|[^\\\\\\\\()[\\\\]]|\" + attributes.replace( 3, 8 ) + \")*)|.*)\\\\)|)\",\n\n\t// Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter\n\trtrim = new RegExp( \"^\" + whitespace + \"+|((?:^|[^\\\\\\\\])(?:\\\\\\\\.)*)\" + whitespace + \"+$\", \"g\" ),\n\n\trcomma = new RegExp( \"^\" + whitespace + \"*,\" + whitespace + \"*\" ),\n\trcombinators = new RegExp( \"^\" + whitespace + \"*([\\\\x20\\\\t\\\\r\\\\n\\\\f>+~])\" + whitespace + \"*\" ),\n\trpseudo = new RegExp( pseudos ),\n\tridentifier = new RegExp( \"^\" + identifier + \"$\" ),\n\n\tmatchExpr = {\n\t\t\"ID\": new RegExp( \"^#(\" + characterEncoding + \")\" ),\n\t\t\"CLASS\": new RegExp( \"^\\\\.(\" + characterEncoding + \")\" ),\n\t\t\"NAME\": new RegExp( \"^\\\\[name=['\\\"]?(\" + characterEncoding + \")['\\\"]?\\\\]\" ),\n\t\t\"TAG\": new RegExp( \"^(\" + characterEncoding.replace( \"w\", \"w*\" ) + \")\" ),\n\t\t\"ATTR\": new RegExp( \"^\" + attributes ),\n\t\t\"PSEUDO\": new RegExp( \"^\" + pseudos ),\n\t\t\"CHILD\": new RegExp( \"^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\\\(\" + whitespace +\n\t\t\t\"*(even|odd|(([+-]|)(\\\\d*)n|)\" + whitespace + \"*(?:([+-]|)\" + whitespace +\n\t\t\t\"*(\\\\d+)|))\" + whitespace + \"*\\\\)|)\", \"i\" ),\n\t\t// For use in libraries implementing .is()\n\t\t// We use this for POS matching in `select`\n\t\t\"needsContext\": new RegExp( \"^\" + whitespace + \"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\\\(\" +\n\t\t\twhitespace + \"*((?:-\\\\d)?\\\\d*)\" + whitespace + \"*\\\\)|)(?=[^-]|$)\", \"i\" )\n\t},\n\n\trsibling = /[\\x20\\t\\r\\n\\f]*[+~]/,\n\n\trnative = /^[^{]+\\{\\s*\\[native code/,\n\n\t// Easily-parseable/retrievable ID or TAG or CLASS selectors\n\trquickExpr = /^(?:#([\\w-]+)|(\\w+)|\\.([\\w-]+))$/,\n\n\trinputs = /^(?:input|select|textarea|button)$/i,\n\trheader = /^h\\d$/i,\n\n\trescape = /'|\\\\/g,\n\trattributeQuotes = /\\=[\\x20\\t\\r\\n\\f]*([^'\"\\]]*)[\\x20\\t\\r\\n\\f]*\\]/g,\n\n\t// CSS escapes http://www.w3.org/TR/CSS21/syndata.html#escaped-characters\n\trunescape = /\\\\([\\da-fA-F]{1,6}[\\x20\\t\\r\\n\\f]?|.)/g,\n\tfunescape = function( _, escaped ) {\n\t\tvar high = \"0x\" + escaped - 0x10000;\n\t\t// NaN means non-codepoint\n\t\treturn high !== high ?\n\t\t\tescaped :\n\t\t\t// BMP codepoint\n\t\t\thigh < 0 ?\n\t\t\t\tString.fromCharCode( high + 0x10000 ) :\n\t\t\t\t// Supplemental Plane codepoint (surrogate pair)\n\t\t\t\tString.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 );\n\t};\n\n// Use a stripped-down slice if we can't use a native one\ntry {\n\tslice.call( preferredDoc.documentElement.childNodes, 0 )[0].nodeType;\n} catch ( e ) {\n\tslice = function( i ) {\n\t\tvar elem,\n\t\t\tresults = [];\n\t\twhile ( (elem = this[i++]) ) {\n\t\t\tresults.push( elem );\n\t\t}\n\t\treturn results;\n\t};\n}\n\n/**\n * For feature detection\n * @param {Function} fn The function to test for native support\n */\nfunction isNative( fn ) {\n\treturn rnative.test( fn + \"\" );\n}\n\n/**\n * Create key-value caches of limited size\n * @returns {Function(string, Object)} Returns the Object data after storing it on itself with\n *\tproperty name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength)\n *\tdeleting the oldest entry\n */\nfunction createCache() {\n\tvar cache,\n\t\tkeys = [];\n\n\treturn (cache = function( key, value ) {\n\t\t// Use (key + \" \") to avoid collision with native prototype properties (see Issue #157)\n\t\tif ( keys.push( key += \" \" ) > Expr.cacheLength ) {\n\t\t\t// Only keep the most recent entries\n\t\t\tdelete cache[ keys.shift() ];\n\t\t}\n\t\treturn (cache[ key ] = value);\n\t});\n}\n\n/**\n * Mark a function for special use by Sizzle\n * @param {Function} fn The function to mark\n */\nfunction markFunction( fn ) {\n\tfn[ expando ] = true;\n\treturn fn;\n}\n\n/**\n * Support testing using an element\n * @param {Function} fn Passed the created div and expects a boolean result\n */\nfunction assert( fn ) {\n\tvar div = document.createElement(\"div\");\n\n\ttry {\n\t\treturn fn( div );\n\t} catch (e) {\n\t\treturn false;\n\t} finally {\n\t\t// release memory in IE\n\t\tdiv = null;\n\t}\n}\n\nfunction Sizzle( selector, context, results, seed ) {\n\tvar match, elem, m, nodeType,\n\t\t// QSA vars\n\t\ti, groups, old, nid, newContext, newSelector;\n\n\tif ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) {\n\t\tsetDocument( context );\n\t}\n\n\tcontext = context || document;\n\tresults = results || [];\n\n\tif ( !selector || typeof selector !== \"string\" ) {\n\t\treturn results;\n\t}\n\n\tif ( (nodeType = context.nodeType) !== 1 && nodeType !== 9 ) {\n\t\treturn [];\n\t}\n\n\tif ( !documentIsXML && !seed ) {\n\n\t\t// Shortcuts\n\t\tif ( (match = rquickExpr.exec( selector )) ) {\n\t\t\t// Speed-up: Sizzle(\"#ID\")\n\t\t\tif ( (m = match[1]) ) {\n\t\t\t\tif ( nodeType === 9 ) {\n\t\t\t\t\telem = context.getElementById( m );\n\t\t\t\t\t// Check parentNode to catch when Blackberry 4.6 returns\n\t\t\t\t\t// nodes that are no longer in the document #6963\n\t\t\t\t\tif ( elem && elem.parentNode ) {\n\t\t\t\t\t\t// Handle the case where IE, Opera, and Webkit return items\n\t\t\t\t\t\t// by name instead of ID\n\t\t\t\t\t\tif ( elem.id === m ) {\n\t\t\t\t\t\t\tresults.push( elem );\n\t\t\t\t\t\t\treturn results;\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\treturn results;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\t// Context is not a document\n\t\t\t\t\tif ( context.ownerDocument && (elem = context.ownerDocument.getElementById( m )) &&\n\t\t\t\t\t\tcontains( context, elem ) && elem.id === m ) {\n\t\t\t\t\t\tresults.push( elem );\n\t\t\t\t\t\treturn results;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t// Speed-up: Sizzle(\"TAG\")\n\t\t\t} else if ( match[2] ) {\n\t\t\t\tpush.apply( results, slice.call(context.getElementsByTagName( selector ), 0) );\n\t\t\t\treturn results;\n\n\t\t\t// Speed-up: Sizzle(\".CLASS\")\n\t\t\t} else if ( (m = match[3]) && support.getByClassName && context.getElementsByClassName ) {\n\t\t\t\tpush.apply( results, slice.call(context.getElementsByClassName( m ), 0) );\n\t\t\t\treturn results;\n\t\t\t}\n\t\t}\n\n\t\t// QSA path\n\t\tif ( support.qsa && !rbuggyQSA.test(selector) ) {\n\t\t\told = true;\n\t\t\tnid = expando;\n\t\t\tnewContext = context;\n\t\t\tnewSelector = nodeType === 9 && selector;\n\n\t\t\t// qSA works strangely on Element-rooted queries\n\t\t\t// We can work around this by specifying an extra ID on the root\n\t\t\t// and working up from there (Thanks to Andrew Dupont for the technique)\n\t\t\t// IE 8 doesn't work on object elements\n\t\t\tif ( nodeType === 1 && context.nodeName.toLowerCase() !== \"object\" ) {\n\t\t\t\tgroups = tokenize( selector );\n\n\t\t\t\tif ( (old = context.getAttribute(\"id\")) ) {\n\t\t\t\t\tnid = old.replace( rescape, \"\\\\$&\" );\n\t\t\t\t} else {\n\t\t\t\t\tcontext.setAttribute( \"id\", nid );\n\t\t\t\t}\n\t\t\t\tnid = \"[id='\" + nid + \"'] \";\n\n\t\t\t\ti = groups.length;\n\t\t\t\twhile ( i-- ) {\n\t\t\t\t\tgroups[i] = nid + toSelector( groups[i] );\n\t\t\t\t}\n\t\t\t\tnewContext = rsibling.test( selector ) && context.parentNode || context;\n\t\t\t\tnewSelector = groups.join(\",\");\n\t\t\t}\n\n\t\t\tif ( newSelector ) {\n\t\t\t\ttry {\n\t\t\t\t\tpush.apply( results, slice.call( newContext.querySelectorAll(\n\t\t\t\t\t\tnewSelector\n\t\t\t\t\t), 0 ) );\n\t\t\t\t\treturn results;\n\t\t\t\t} catch(qsaError) {\n\t\t\t\t} finally {\n\t\t\t\t\tif ( !old ) {\n\t\t\t\t\t\tcontext.removeAttribute(\"id\");\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// All others\n\treturn select( selector.replace( rtrim, \"$1\" ), context, results, seed );\n}\n\n/**\n * Detect xml\n * @param {Element|Object} elem An element or a document\n */\nisXML = Sizzle.isXML = function( elem ) {\n\t// documentElement is verified for cases where it doesn't yet exist\n\t// (such as loading iframes in IE - #4833)\n\tvar documentElement = elem && (elem.ownerDocument || elem).documentElement;\n\treturn documentElement ? documentElement.nodeName !== \"HTML\" : false;\n};\n\n/**\n * Sets document-related variables once based on the current document\n * @param {Element|Object} [doc] An element or document object to use to set the document\n * @returns {Object} Returns the current document\n */\nsetDocument = Sizzle.setDocument = function( node ) {\n\tvar doc = node ? node.ownerDocument || node : preferredDoc;\n\n\t// If no document and documentElement is available, return\n\tif ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) {\n\t\treturn document;\n\t}\n\n\t// Set our document\n\tdocument = doc;\n\tdocElem = doc.documentElement;\n\n\t// Support tests\n\tdocumentIsXML = isXML( doc );\n\n\t// Check if getElementsByTagName(\"*\") returns only elements\n\tsupport.tagNameNoComments = assert(function( div ) {\n\t\tdiv.appendChild( doc.createComment(\"\") );\n\t\treturn !div.getElementsByTagName(\"*\").length;\n\t});\n\n\t// Check if attributes should be retrieved by attribute nodes\n\tsupport.attributes = assert(function( div ) {\n\t\tdiv.innerHTML = \"<select></select>\";\n\t\tvar type = typeof div.lastChild.getAttribute(\"multiple\");\n\t\t// IE8 returns a string for some attributes even when not present\n\t\treturn type !== \"boolean\" && type !== \"string\";\n\t});\n\n\t// Check if getElementsByClassName can be trusted\n\tsupport.getByClassName = assert(function( div ) {\n\t\t// Opera can't find a second classname (in 9.6)\n\t\tdiv.innerHTML = \"<div class='hidden e'></div><div class='hidden'></div>\";\n\t\tif ( !div.getElementsByClassName || !div.getElementsByClassName(\"e\").length ) {\n\t\t\treturn false;\n\t\t}\n\n\t\t// Safari 3.2 caches class attributes and doesn't catch changes\n\t\tdiv.lastChild.className = \"e\";\n\t\treturn div.getElementsByClassName(\"e\").length === 2;\n\t});\n\n\t// Check if getElementById returns elements by name\n\t// Check if getElementsByName privileges form controls or returns elements by ID\n\tsupport.getByName = assert(function( div ) {\n\t\t// Inject content\n\t\tdiv.id = expando + 0;\n\t\tdiv.innerHTML = \"<a name='\" + expando + \"'></a><div name='\" + expando + \"'></div>\";\n\t\tdocElem.insertBefore( div, docElem.firstChild );\n\n\t\t// Test\n\t\tvar pass = doc.getElementsByName &&\n\t\t\t// buggy browsers will return fewer than the correct 2\n\t\t\tdoc.getElementsByName( expando ).length === 2 +\n\t\t\t// buggy browsers will return more than the correct 0\n\t\t\tdoc.getElementsByName( expando + 0 ).length;\n\t\tsupport.getIdNotName = !doc.getElementById( expando );\n\n\t\t// Cleanup\n\t\tdocElem.removeChild( div );\n\n\t\treturn pass;\n\t});\n\n\t// IE6/7 return modified attributes\n\tExpr.attrHandle = assert(function( div ) {\n\t\tdiv.innerHTML = \"<a href='#'></a>\";\n\t\treturn div.firstChild && typeof div.firstChild.getAttribute !== strundefined &&\n\t\t\tdiv.firstChild.getAttribute(\"href\") === \"#\";\n\t}) ?\n\t\t{} :\n\t\t{\n\t\t\t\"href\": function( elem ) {\n\t\t\t\treturn elem.getAttribute( \"href\", 2 );\n\t\t\t},\n\t\t\t\"type\": function( elem ) {\n\t\t\t\treturn elem.getAttribute(\"type\");\n\t\t\t}\n\t\t};\n\n\t// ID find and filter\n\tif ( support.getIdNotName ) {\n\t\tExpr.find[\"ID\"] = function( id, context ) {\n\t\t\tif ( typeof context.getElementById !== strundefined && !documentIsXML ) {\n\t\t\t\tvar m = context.getElementById( id );\n\t\t\t\t// Check parentNode to catch when Blackberry 4.6 returns\n\t\t\t\t// nodes that are no longer in the document #6963\n\t\t\t\treturn m && m.parentNode ? [m] : [];\n\t\t\t}\n\t\t};\n\t\tExpr.filter[\"ID\"] = function( id ) {\n\t\t\tvar attrId = id.replace( runescape, funescape );\n\t\t\treturn function( elem ) {\n\t\t\t\treturn elem.getAttribute(\"id\") === attrId;\n\t\t\t};\n\t\t};\n\t} else {\n\t\tExpr.find[\"ID\"] = function( id, context ) {\n\t\t\tif ( typeof context.getElementById !== strundefined && !documentIsXML ) {\n\t\t\t\tvar m = context.getElementById( id );\n\n\t\t\t\treturn m ?\n\t\t\t\t\tm.id === id || typeof m.getAttributeNode !== strundefined && m.getAttributeNode(\"id\").value === id ?\n\t\t\t\t\t\t[m] :\n\t\t\t\t\t\tundefined :\n\t\t\t\t\t[];\n\t\t\t}\n\t\t};\n\t\tExpr.filter[\"ID\"] =  function( id ) {\n\t\t\tvar attrId = id.replace( runescape, funescape );\n\t\t\treturn function( elem ) {\n\t\t\t\tvar node = typeof elem.getAttributeNode !== strundefined && elem.getAttributeNode(\"id\");\n\t\t\t\treturn node && node.value === attrId;\n\t\t\t};\n\t\t};\n\t}\n\n\t// Tag\n\tExpr.find[\"TAG\"] = support.tagNameNoComments ?\n\t\tfunction( tag, context ) {\n\t\t\tif ( typeof context.getElementsByTagName !== strundefined ) {\n\t\t\t\treturn context.getElementsByTagName( tag );\n\t\t\t}\n\t\t} :\n\t\tfunction( tag, context ) {\n\t\t\tvar elem,\n\t\t\t\ttmp = [],\n\t\t\t\ti = 0,\n\t\t\t\tresults = context.getElementsByTagName( tag );\n\n\t\t\t// Filter out possible comments\n\t\t\tif ( tag === \"*\" ) {\n\t\t\t\twhile ( (elem = results[i++]) ) {\n\t\t\t\t\tif ( elem.nodeType === 1 ) {\n\t\t\t\t\t\ttmp.push( elem );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn tmp;\n\t\t\t}\n\t\t\treturn results;\n\t\t};\n\n\t// Name\n\tExpr.find[\"NAME\"] = support.getByName && function( tag, context ) {\n\t\tif ( typeof context.getElementsByName !== strundefined ) {\n\t\t\treturn context.getElementsByName( name );\n\t\t}\n\t};\n\n\t// Class\n\tExpr.find[\"CLASS\"] = support.getByClassName && function( className, context ) {\n\t\tif ( typeof context.getElementsByClassName !== strundefined && !documentIsXML ) {\n\t\t\treturn context.getElementsByClassName( className );\n\t\t}\n\t};\n\n\t// QSA and matchesSelector support\n\n\t// matchesSelector(:active) reports false when true (IE9/Opera 11.5)\n\trbuggyMatches = [];\n\n\t// qSa(:focus) reports false when true (Chrome 21),\n\t// no need to also add to buggyMatches since matches checks buggyQSA\n\t// A support test would require too much code (would include document ready)\n\trbuggyQSA = [ \":focus\" ];\n\n\tif ( (support.qsa = isNative(doc.querySelectorAll)) ) {\n\t\t// Build QSA regex\n\t\t// Regex strategy adopted from Diego Perini\n\t\tassert(function( div ) {\n\t\t\t// Select is set to empty string on purpose\n\t\t\t// This is to test IE's treatment of not explictly\n\t\t\t// setting a boolean content attribute,\n\t\t\t// since its presence should be enough\n\t\t\t// http://bugs.jquery.com/ticket/12359\n\t\t\tdiv.innerHTML = \"<select><option selected=''></option></select>\";\n\n\t\t\t// IE8 - Some boolean attributes are not treated correctly\n\t\t\tif ( !div.querySelectorAll(\"[selected]\").length ) {\n\t\t\t\trbuggyQSA.push( \"\\\\[\" + whitespace + \"*(?:checked|disabled|ismap|multiple|readonly|selected|value)\" );\n\t\t\t}\n\n\t\t\t// Webkit/Opera - :checked should return selected option elements\n\t\t\t// http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked\n\t\t\t// IE8 throws error here and will not see later tests\n\t\t\tif ( !div.querySelectorAll(\":checked\").length ) {\n\t\t\t\trbuggyQSA.push(\":checked\");\n\t\t\t}\n\t\t});\n\n\t\tassert(function( div ) {\n\n\t\t\t// Opera 10-12/IE8 - ^= $= *= and empty values\n\t\t\t// Should not select anything\n\t\t\tdiv.innerHTML = \"<input type='hidden' i=''/>\";\n\t\t\tif ( div.querySelectorAll(\"[i^='']\").length ) {\n\t\t\t\trbuggyQSA.push( \"[*^$]=\" + whitespace + \"*(?:\\\"\\\"|'')\" );\n\t\t\t}\n\n\t\t\t// FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled)\n\t\t\t// IE8 throws error here and will not see later tests\n\t\t\tif ( !div.querySelectorAll(\":enabled\").length ) {\n\t\t\t\trbuggyQSA.push( \":enabled\", \":disabled\" );\n\t\t\t}\n\n\t\t\t// Opera 10-11 does not throw on post-comma invalid pseudos\n\t\t\tdiv.querySelectorAll(\"*,:x\");\n\t\t\trbuggyQSA.push(\",.*:\");\n\t\t});\n\t}\n\n\tif ( (support.matchesSelector = isNative( (matches = docElem.matchesSelector ||\n\t\tdocElem.mozMatchesSelector ||\n\t\tdocElem.webkitMatchesSelector ||\n\t\tdocElem.oMatchesSelector ||\n\t\tdocElem.msMatchesSelector) )) ) {\n\n\t\tassert(function( div ) {\n\t\t\t// Check to see if it's possible to do matchesSelector\n\t\t\t// on a disconnected node (IE 9)\n\t\t\tsupport.disconnectedMatch = matches.call( div, \"div\" );\n\n\t\t\t// This should fail with an exception\n\t\t\t// Gecko does not error, returns false instead\n\t\t\tmatches.call( div, \"[s!='']:x\" );\n\t\t\trbuggyMatches.push( \"!=\", pseudos );\n\t\t});\n\t}\n\n\trbuggyQSA = new RegExp( rbuggyQSA.join(\"|\") );\n\trbuggyMatches = new RegExp( rbuggyMatches.join(\"|\") );\n\n\t// Element contains another\n\t// Purposefully does not implement inclusive descendent\n\t// As in, an element does not contain itself\n\tcontains = isNative(docElem.contains) || docElem.compareDocumentPosition ?\n\t\tfunction( a, b ) {\n\t\t\tvar adown = a.nodeType === 9 ? a.documentElement : a,\n\t\t\t\tbup = b && b.parentNode;\n\t\t\treturn a === bup || !!( bup && bup.nodeType === 1 && (\n\t\t\t\tadown.contains ?\n\t\t\t\t\tadown.contains( bup ) :\n\t\t\t\t\ta.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16\n\t\t\t));\n\t\t} :\n\t\tfunction( a, b ) {\n\t\t\tif ( b ) {\n\t\t\t\twhile ( (b = b.parentNode) ) {\n\t\t\t\t\tif ( b === a ) {\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn false;\n\t\t};\n\n\t// Document order sorting\n\tsortOrder = docElem.compareDocumentPosition ?\n\tfunction( a, b ) {\n\t\tvar compare;\n\n\t\tif ( a === b ) {\n\t\t\thasDuplicate = true;\n\t\t\treturn 0;\n\t\t}\n\n\t\tif ( (compare = b.compareDocumentPosition && a.compareDocumentPosition && a.compareDocumentPosition( b )) ) {\n\t\t\tif ( compare & 1 || a.parentNode && a.parentNode.nodeType === 11 ) {\n\t\t\t\tif ( a === doc || contains( preferredDoc, a ) ) {\n\t\t\t\t\treturn -1;\n\t\t\t\t}\n\t\t\t\tif ( b === doc || contains( preferredDoc, b ) ) {\n\t\t\t\t\treturn 1;\n\t\t\t\t}\n\t\t\t\treturn 0;\n\t\t\t}\n\t\t\treturn compare & 4 ? -1 : 1;\n\t\t}\n\n\t\treturn a.compareDocumentPosition ? -1 : 1;\n\t} :\n\tfunction( a, b ) {\n\t\tvar cur,\n\t\t\ti = 0,\n\t\t\taup = a.parentNode,\n\t\t\tbup = b.parentNode,\n\t\t\tap = [ a ],\n\t\t\tbp = [ b ];\n\n\t\t// Exit early if the nodes are identical\n\t\tif ( a === b ) {\n\t\t\thasDuplicate = true;\n\t\t\treturn 0;\n\n\t\t// Parentless nodes are either documents or disconnected\n\t\t} else if ( !aup || !bup ) {\n\t\t\treturn a === doc ? -1 :\n\t\t\t\tb === doc ? 1 :\n\t\t\t\taup ? -1 :\n\t\t\t\tbup ? 1 :\n\t\t\t\t0;\n\n\t\t// If the nodes are siblings, we can do a quick check\n\t\t} else if ( aup === bup ) {\n\t\t\treturn siblingCheck( a, b );\n\t\t}\n\n\t\t// Otherwise we need full lists of their ancestors for comparison\n\t\tcur = a;\n\t\twhile ( (cur = cur.parentNode) ) {\n\t\t\tap.unshift( cur );\n\t\t}\n\t\tcur = b;\n\t\twhile ( (cur = cur.parentNode) ) {\n\t\t\tbp.unshift( cur );\n\t\t}\n\n\t\t// Walk down the tree looking for a discrepancy\n\t\twhile ( ap[i] === bp[i] ) {\n\t\t\ti++;\n\t\t}\n\n\t\treturn i ?\n\t\t\t// Do a sibling check if the nodes have a common ancestor\n\t\t\tsiblingCheck( ap[i], bp[i] ) :\n\n\t\t\t// Otherwise nodes in our document sort first\n\t\t\tap[i] === preferredDoc ? -1 :\n\t\t\tbp[i] === preferredDoc ? 1 :\n\t\t\t0;\n\t};\n\n\t// Always assume the presence of duplicates if sort doesn't\n\t// pass them to our comparison function (as in Google Chrome).\n\thasDuplicate = false;\n\t[0, 0].sort( sortOrder );\n\tsupport.detectDuplicates = hasDuplicate;\n\n\treturn document;\n};\n\nSizzle.matches = function( expr, elements ) {\n\treturn Sizzle( expr, null, null, elements );\n};\n\nSizzle.matchesSelector = function( elem, expr ) {\n\t// Set document vars if needed\n\tif ( ( elem.ownerDocument || elem ) !== document ) {\n\t\tsetDocument( elem );\n\t}\n\n\t// Make sure that attribute selectors are quoted\n\texpr = expr.replace( rattributeQuotes, \"='$1']\" );\n\n\t// rbuggyQSA always contains :focus, so no need for an existence check\n\tif ( support.matchesSelector && !documentIsXML && (!rbuggyMatches || !rbuggyMatches.test(expr)) && !rbuggyQSA.test(expr) ) {\n\t\ttry {\n\t\t\tvar ret = matches.call( elem, expr );\n\n\t\t\t// IE 9's matchesSelector returns false on disconnected nodes\n\t\t\tif ( ret || support.disconnectedMatch ||\n\t\t\t\t\t// As well, disconnected nodes are said to be in a document\n\t\t\t\t\t// fragment in IE 9\n\t\t\t\t\telem.document && elem.document.nodeType !== 11 ) {\n\t\t\t\treturn ret;\n\t\t\t}\n\t\t} catch(e) {}\n\t}\n\n\treturn Sizzle( expr, document, null, [elem] ).length > 0;\n};\n\nSizzle.contains = function( context, elem ) {\n\t// Set document vars if needed\n\tif ( ( context.ownerDocument || context ) !== document ) {\n\t\tsetDocument( context );\n\t}\n\treturn contains( context, elem );\n};\n\nSizzle.attr = function( elem, name ) {\n\tvar val;\n\n\t// Set document vars if needed\n\tif ( ( elem.ownerDocument || elem ) !== document ) {\n\t\tsetDocument( elem );\n\t}\n\n\tif ( !documentIsXML ) {\n\t\tname = name.toLowerCase();\n\t}\n\tif ( (val = Expr.attrHandle[ name ]) ) {\n\t\treturn val( elem );\n\t}\n\tif ( documentIsXML || support.attributes ) {\n\t\treturn elem.getAttribute( name );\n\t}\n\treturn ( (val = elem.getAttributeNode( name )) || elem.getAttribute( name ) ) && elem[ name ] === true ?\n\t\tname :\n\t\tval && val.specified ? val.value : null;\n};\n\nSizzle.error = function( msg ) {\n\tthrow new Error( \"Syntax error, unrecognized expression: \" + msg );\n};\n\n// Document sorting and removing duplicates\nSizzle.uniqueSort = function( results ) {\n\tvar elem,\n\t\tduplicates = [],\n\t\ti = 1,\n\t\tj = 0;\n\n\t// Unless we *know* we can detect duplicates, assume their presence\n\thasDuplicate = !support.detectDuplicates;\n\tresults.sort( sortOrder );\n\n\tif ( hasDuplicate ) {\n\t\tfor ( ; (elem = results[i]); i++ ) {\n\t\t\tif ( elem === results[ i - 1 ] ) {\n\t\t\t\tj = duplicates.push( i );\n\t\t\t}\n\t\t}\n\t\twhile ( j-- ) {\n\t\t\tresults.splice( duplicates[ j ], 1 );\n\t\t}\n\t}\n\n\treturn results;\n};\n\nfunction siblingCheck( a, b ) {\n\tvar cur = b && a,\n\t\tdiff = cur && ( ~b.sourceIndex || MAX_NEGATIVE ) - ( ~a.sourceIndex || MAX_NEGATIVE );\n\n\t// Use IE sourceIndex if available on both nodes\n\tif ( diff ) {\n\t\treturn diff;\n\t}\n\n\t// Check if b follows a\n\tif ( cur ) {\n\t\twhile ( (cur = cur.nextSibling) ) {\n\t\t\tif ( cur === b ) {\n\t\t\t\treturn -1;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn a ? 1 : -1;\n}\n\n// Returns a function to use in pseudos for input types\nfunction createInputPseudo( type ) {\n\treturn function( elem ) {\n\t\tvar name = elem.nodeName.toLowerCase();\n\t\treturn name === \"input\" && elem.type === type;\n\t};\n}\n\n// Returns a function to use in pseudos for buttons\nfunction createButtonPseudo( type ) {\n\treturn function( elem ) {\n\t\tvar name = elem.nodeName.toLowerCase();\n\t\treturn (name === \"input\" || name === \"button\") && elem.type === type;\n\t};\n}\n\n// Returns a function to use in pseudos for positionals\nfunction createPositionalPseudo( fn ) {\n\treturn markFunction(function( argument ) {\n\t\targument = +argument;\n\t\treturn markFunction(function( seed, matches ) {\n\t\t\tvar j,\n\t\t\t\tmatchIndexes = fn( [], seed.length, argument ),\n\t\t\t\ti = matchIndexes.length;\n\n\t\t\t// Match elements found at the specified indexes\n\t\t\twhile ( i-- ) {\n\t\t\t\tif ( seed[ (j = matchIndexes[i]) ] ) {\n\t\t\t\t\tseed[j] = !(matches[j] = seed[j]);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t});\n}\n\n/**\n * Utility function for retrieving the text value of an array of DOM nodes\n * @param {Array|Element} elem\n */\ngetText = Sizzle.getText = function( elem ) {\n\tvar node,\n\t\tret = \"\",\n\t\ti = 0,\n\t\tnodeType = elem.nodeType;\n\n\tif ( !nodeType ) {\n\t\t// If no nodeType, this is expected to be an array\n\t\tfor ( ; (node = elem[i]); i++ ) {\n\t\t\t// Do not traverse comment nodes\n\t\t\tret += getText( node );\n\t\t}\n\t} else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) {\n\t\t// Use textContent for elements\n\t\t// innerText usage removed for consistency of new lines (see #11153)\n\t\tif ( typeof elem.textContent === \"string\" ) {\n\t\t\treturn elem.textContent;\n\t\t} else {\n\t\t\t// Traverse its children\n\t\t\tfor ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {\n\t\t\t\tret += getText( elem );\n\t\t\t}\n\t\t}\n\t} else if ( nodeType === 3 || nodeType === 4 ) {\n\t\treturn elem.nodeValue;\n\t}\n\t// Do not include comment or processing instruction nodes\n\n\treturn ret;\n};\n\nExpr = Sizzle.selectors = {\n\n\t// Can be adjusted by the user\n\tcacheLength: 50,\n\n\tcreatePseudo: markFunction,\n\n\tmatch: matchExpr,\n\n\tfind: {},\n\n\trelative: {\n\t\t\">\": { dir: \"parentNode\", first: true },\n\t\t\" \": { dir: \"parentNode\" },\n\t\t\"+\": { dir: \"previousSibling\", first: true },\n\t\t\"~\": { dir: \"previousSibling\" }\n\t},\n\n\tpreFilter: {\n\t\t\"ATTR\": function( match ) {\n\t\t\tmatch[1] = match[1].replace( runescape, funescape );\n\n\t\t\t// Move the given value to match[3] whether quoted or unquoted\n\t\t\tmatch[3] = ( match[4] || match[5] || \"\" ).replace( runescape, funescape );\n\n\t\t\tif ( match[2] === \"~=\" ) {\n\t\t\t\tmatch[3] = \" \" + match[3] + \" \";\n\t\t\t}\n\n\t\t\treturn match.slice( 0, 4 );\n\t\t},\n\n\t\t\"CHILD\": function( match ) {\n\t\t\t/* matches from matchExpr[\"CHILD\"]\n\t\t\t\t1 type (only|nth|...)\n\t\t\t\t2 what (child|of-type)\n\t\t\t\t3 argument (even|odd|\\d*|\\d*n([+-]\\d+)?|...)\n\t\t\t\t4 xn-component of xn+y argument ([+-]?\\d*n|)\n\t\t\t\t5 sign of xn-component\n\t\t\t\t6 x of xn-component\n\t\t\t\t7 sign of y-component\n\t\t\t\t8 y of y-component\n\t\t\t*/\n\t\t\tmatch[1] = match[1].toLowerCase();\n\n\t\t\tif ( match[1].slice( 0, 3 ) === \"nth\" ) {\n\t\t\t\t// nth-* requires argument\n\t\t\t\tif ( !match[3] ) {\n\t\t\t\t\tSizzle.error( match[0] );\n\t\t\t\t}\n\n\t\t\t\t// numeric x and y parameters for Expr.filter.CHILD\n\t\t\t\t// remember that false/true cast respectively to 0/1\n\t\t\t\tmatch[4] = +( match[4] ? match[5] + (match[6] || 1) : 2 * ( match[3] === \"even\" || match[3] === \"odd\" ) );\n\t\t\t\tmatch[5] = +( ( match[7] + match[8] ) || match[3] === \"odd\" );\n\n\t\t\t// other types prohibit arguments\n\t\t\t} else if ( match[3] ) {\n\t\t\t\tSizzle.error( match[0] );\n\t\t\t}\n\n\t\t\treturn match;\n\t\t},\n\n\t\t\"PSEUDO\": function( match ) {\n\t\t\tvar excess,\n\t\t\t\tunquoted = !match[5] && match[2];\n\n\t\t\tif ( matchExpr[\"CHILD\"].test( match[0] ) ) {\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\t// Accept quoted arguments as-is\n\t\t\tif ( match[4] ) {\n\t\t\t\tmatch[2] = match[4];\n\n\t\t\t// Strip excess characters from unquoted arguments\n\t\t\t} else if ( unquoted && rpseudo.test( unquoted ) &&\n\t\t\t\t// Get excess from tokenize (recursively)\n\t\t\t\t(excess = tokenize( unquoted, true )) &&\n\t\t\t\t// advance to the next closing parenthesis\n\t\t\t\t(excess = unquoted.indexOf( \")\", unquoted.length - excess ) - unquoted.length) ) {\n\n\t\t\t\t// excess is a negative index\n\t\t\t\tmatch[0] = match[0].slice( 0, excess );\n\t\t\t\tmatch[2] = unquoted.slice( 0, excess );\n\t\t\t}\n\n\t\t\t// Return only captures needed by the pseudo filter method (type and argument)\n\t\t\treturn match.slice( 0, 3 );\n\t\t}\n\t},\n\n\tfilter: {\n\n\t\t\"TAG\": function( nodeName ) {\n\t\t\tif ( nodeName === \"*\" ) {\n\t\t\t\treturn function() { return true; };\n\t\t\t}\n\n\t\t\tnodeName = nodeName.replace( runescape, funescape ).toLowerCase();\n\t\t\treturn function( elem ) {\n\t\t\t\treturn elem.nodeName && elem.nodeName.toLowerCase() === nodeName;\n\t\t\t};\n\t\t},\n\n\t\t\"CLASS\": function( className ) {\n\t\t\tvar pattern = classCache[ className + \" \" ];\n\n\t\t\treturn pattern ||\n\t\t\t\t(pattern = new RegExp( \"(^|\" + whitespace + \")\" + className + \"(\" + whitespace + \"|$)\" )) &&\n\t\t\t\tclassCache( className, function( elem ) {\n\t\t\t\t\treturn pattern.test( elem.className || (typeof elem.getAttribute !== strundefined && elem.getAttribute(\"class\")) || \"\" );\n\t\t\t\t});\n\t\t},\n\n\t\t\"ATTR\": function( name, operator, check ) {\n\t\t\treturn function( elem ) {\n\t\t\t\tvar result = Sizzle.attr( elem, name );\n\n\t\t\t\tif ( result == null ) {\n\t\t\t\t\treturn operator === \"!=\";\n\t\t\t\t}\n\t\t\t\tif ( !operator ) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\n\t\t\t\tresult += \"\";\n\n\t\t\t\treturn operator === \"=\" ? result === check :\n\t\t\t\t\toperator === \"!=\" ? result !== check :\n\t\t\t\t\toperator === \"^=\" ? check && result.indexOf( check ) === 0 :\n\t\t\t\t\toperator === \"*=\" ? check && result.indexOf( check ) > -1 :\n\t\t\t\t\toperator === \"$=\" ? check && result.slice( -check.length ) === check :\n\t\t\t\t\toperator === \"~=\" ? ( \" \" + result + \" \" ).indexOf( check ) > -1 :\n\t\t\t\t\toperator === \"|=\" ? result === check || result.slice( 0, check.length + 1 ) === check + \"-\" :\n\t\t\t\t\tfalse;\n\t\t\t};\n\t\t},\n\n\t\t\"CHILD\": function( type, what, argument, first, last ) {\n\t\t\tvar simple = type.slice( 0, 3 ) !== \"nth\",\n\t\t\t\tforward = type.slice( -4 ) !== \"last\",\n\t\t\t\tofType = what === \"of-type\";\n\n\t\t\treturn first === 1 && last === 0 ?\n\n\t\t\t\t// Shortcut for :nth-*(n)\n\t\t\t\tfunction( elem ) {\n\t\t\t\t\treturn !!elem.parentNode;\n\t\t\t\t} :\n\n\t\t\t\tfunction( elem, context, xml ) {\n\t\t\t\t\tvar cache, outerCache, node, diff, nodeIndex, start,\n\t\t\t\t\t\tdir = simple !== forward ? \"nextSibling\" : \"previousSibling\",\n\t\t\t\t\t\tparent = elem.parentNode,\n\t\t\t\t\t\tname = ofType && elem.nodeName.toLowerCase(),\n\t\t\t\t\t\tuseCache = !xml && !ofType;\n\n\t\t\t\t\tif ( parent ) {\n\n\t\t\t\t\t\t// :(first|last|only)-(child|of-type)\n\t\t\t\t\t\tif ( simple ) {\n\t\t\t\t\t\t\twhile ( dir ) {\n\t\t\t\t\t\t\t\tnode = elem;\n\t\t\t\t\t\t\t\twhile ( (node = node[ dir ]) ) {\n\t\t\t\t\t\t\t\t\tif ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) {\n\t\t\t\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t// Reverse direction for :only-* (if we haven't yet done so)\n\t\t\t\t\t\t\t\tstart = dir = type === \"only\" && !start && \"nextSibling\";\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tstart = [ forward ? parent.firstChild : parent.lastChild ];\n\n\t\t\t\t\t\t// non-xml :nth-child(...) stores cache data on `parent`\n\t\t\t\t\t\tif ( forward && useCache ) {\n\t\t\t\t\t\t\t// Seek `elem` from a previously-cached index\n\t\t\t\t\t\t\touterCache = parent[ expando ] || (parent[ expando ] = {});\n\t\t\t\t\t\t\tcache = outerCache[ type ] || [];\n\t\t\t\t\t\t\tnodeIndex = cache[0] === dirruns && cache[1];\n\t\t\t\t\t\t\tdiff = cache[0] === dirruns && cache[2];\n\t\t\t\t\t\t\tnode = nodeIndex && parent.childNodes[ nodeIndex ];\n\n\t\t\t\t\t\t\twhile ( (node = ++nodeIndex && node && node[ dir ] ||\n\n\t\t\t\t\t\t\t\t// Fallback to seeking `elem` from the start\n\t\t\t\t\t\t\t\t(diff = nodeIndex = 0) || start.pop()) ) {\n\n\t\t\t\t\t\t\t\t// When found, cache indexes on `parent` and break\n\t\t\t\t\t\t\t\tif ( node.nodeType === 1 && ++diff && node === elem ) {\n\t\t\t\t\t\t\t\t\touterCache[ type ] = [ dirruns, nodeIndex, diff ];\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Use previously-cached element index if available\n\t\t\t\t\t\t} else if ( useCache && (cache = (elem[ expando ] || (elem[ expando ] = {}))[ type ]) && cache[0] === dirruns ) {\n\t\t\t\t\t\t\tdiff = cache[1];\n\n\t\t\t\t\t\t// xml :nth-child(...) or :nth-last-child(...) or :nth(-last)?-of-type(...)\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t// Use the same loop as above to seek `elem` from the start\n\t\t\t\t\t\t\twhile ( (node = ++nodeIndex && node && node[ dir ] ||\n\t\t\t\t\t\t\t\t(diff = nodeIndex = 0) || start.pop()) ) {\n\n\t\t\t\t\t\t\t\tif ( ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) && ++diff ) {\n\t\t\t\t\t\t\t\t\t// Cache the index of each encountered element\n\t\t\t\t\t\t\t\t\tif ( useCache ) {\n\t\t\t\t\t\t\t\t\t\t(node[ expando ] || (node[ expando ] = {}))[ type ] = [ dirruns, diff ];\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\tif ( node === elem ) {\n\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Incorporate the offset, then check against cycle size\n\t\t\t\t\t\tdiff -= last;\n\t\t\t\t\t\treturn diff === first || ( diff % first === 0 && diff / first >= 0 );\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t},\n\n\t\t\"PSEUDO\": function( pseudo, argument ) {\n\t\t\t// pseudo-class names are case-insensitive\n\t\t\t// http://www.w3.org/TR/selectors/#pseudo-classes\n\t\t\t// Prioritize by case sensitivity in case custom pseudos are added with uppercase letters\n\t\t\t// Remember that setFilters inherits from pseudos\n\t\t\tvar args,\n\t\t\t\tfn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] ||\n\t\t\t\t\tSizzle.error( \"unsupported pseudo: \" + pseudo );\n\n\t\t\t// The user may use createPseudo to indicate that\n\t\t\t// arguments are needed to create the filter function\n\t\t\t// just as Sizzle does\n\t\t\tif ( fn[ expando ] ) {\n\t\t\t\treturn fn( argument );\n\t\t\t}\n\n\t\t\t// But maintain support for old signatures\n\t\t\tif ( fn.length > 1 ) {\n\t\t\t\targs = [ pseudo, pseudo, \"\", argument ];\n\t\t\t\treturn Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ?\n\t\t\t\t\tmarkFunction(function( seed, matches ) {\n\t\t\t\t\t\tvar idx,\n\t\t\t\t\t\t\tmatched = fn( seed, argument ),\n\t\t\t\t\t\t\ti = matched.length;\n\t\t\t\t\t\twhile ( i-- ) {\n\t\t\t\t\t\t\tidx = indexOf.call( seed, matched[i] );\n\t\t\t\t\t\t\tseed[ idx ] = !( matches[ idx ] = matched[i] );\n\t\t\t\t\t\t}\n\t\t\t\t\t}) :\n\t\t\t\t\tfunction( elem ) {\n\t\t\t\t\t\treturn fn( elem, 0, args );\n\t\t\t\t\t};\n\t\t\t}\n\n\t\t\treturn fn;\n\t\t}\n\t},\n\n\tpseudos: {\n\t\t// Potentially complex pseudos\n\t\t\"not\": markFunction(function( selector ) {\n\t\t\t// Trim the selector passed to compile\n\t\t\t// to avoid treating leading and trailing\n\t\t\t// spaces as combinators\n\t\t\tvar input = [],\n\t\t\t\tresults = [],\n\t\t\t\tmatcher = compile( selector.replace( rtrim, \"$1\" ) );\n\n\t\t\treturn matcher[ expando ] ?\n\t\t\t\tmarkFunction(function( seed, matches, context, xml ) {\n\t\t\t\t\tvar elem,\n\t\t\t\t\t\tunmatched = matcher( seed, null, xml, [] ),\n\t\t\t\t\t\ti = seed.length;\n\n\t\t\t\t\t// Match elements unmatched by `matcher`\n\t\t\t\t\twhile ( i-- ) {\n\t\t\t\t\t\tif ( (elem = unmatched[i]) ) {\n\t\t\t\t\t\t\tseed[i] = !(matches[i] = elem);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}) :\n\t\t\t\tfunction( elem, context, xml ) {\n\t\t\t\t\tinput[0] = elem;\n\t\t\t\t\tmatcher( input, null, xml, results );\n\t\t\t\t\treturn !results.pop();\n\t\t\t\t};\n\t\t}),\n\n\t\t\"has\": markFunction(function( selector ) {\n\t\t\treturn function( elem ) {\n\t\t\t\treturn Sizzle( selector, elem ).length > 0;\n\t\t\t};\n\t\t}),\n\n\t\t\"contains\": markFunction(function( text ) {\n\t\t\treturn function( elem ) {\n\t\t\t\treturn ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1;\n\t\t\t};\n\t\t}),\n\n\t\t// \"Whether an element is represented by a :lang() selector\n\t\t// is based solely on the element's language value\n\t\t// being equal to the identifier C,\n\t\t// or beginning with the identifier C immediately followed by \"-\".\n\t\t// The matching of C against the element's language value is performed case-insensitively.\n\t\t// The identifier C does not have to be a valid language name.\"\n\t\t// http://www.w3.org/TR/selectors/#lang-pseudo\n\t\t\"lang\": markFunction( function( lang ) {\n\t\t\t// lang value must be a valid identifider\n\t\t\tif ( !ridentifier.test(lang || \"\") ) {\n\t\t\t\tSizzle.error( \"unsupported lang: \" + lang );\n\t\t\t}\n\t\t\tlang = lang.replace( runescape, funescape ).toLowerCase();\n\t\t\treturn function( elem ) {\n\t\t\t\tvar elemLang;\n\t\t\t\tdo {\n\t\t\t\t\tif ( (elemLang = documentIsXML ?\n\t\t\t\t\t\telem.getAttribute(\"xml:lang\") || elem.getAttribute(\"lang\") :\n\t\t\t\t\t\telem.lang) ) {\n\n\t\t\t\t\t\telemLang = elemLang.toLowerCase();\n\t\t\t\t\t\treturn elemLang === lang || elemLang.indexOf( lang + \"-\" ) === 0;\n\t\t\t\t\t}\n\t\t\t\t} while ( (elem = elem.parentNode) && elem.nodeType === 1 );\n\t\t\t\treturn false;\n\t\t\t};\n\t\t}),\n\n\t\t// Miscellaneous\n\t\t\"target\": function( elem ) {\n\t\t\tvar hash = window.location && window.location.hash;\n\t\t\treturn hash && hash.slice( 1 ) === elem.id;\n\t\t},\n\n\t\t\"root\": function( elem ) {\n\t\t\treturn elem === docElem;\n\t\t},\n\n\t\t\"focus\": function( elem ) {\n\t\t\treturn elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex);\n\t\t},\n\n\t\t// Boolean properties\n\t\t\"enabled\": function( elem ) {\n\t\t\treturn elem.disabled === false;\n\t\t},\n\n\t\t\"disabled\": function( elem ) {\n\t\t\treturn elem.disabled === true;\n\t\t},\n\n\t\t\"checked\": function( elem ) {\n\t\t\t// In CSS3, :checked should return both checked and selected elements\n\t\t\t// http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked\n\t\t\tvar nodeName = elem.nodeName.toLowerCase();\n\t\t\treturn (nodeName === \"input\" && !!elem.checked) || (nodeName === \"option\" && !!elem.selected);\n\t\t},\n\n\t\t\"selected\": function( elem ) {\n\t\t\t// Accessing this property makes selected-by-default\n\t\t\t// options in Safari work properly\n\t\t\tif ( elem.parentNode ) {\n\t\t\t\telem.parentNode.selectedIndex;\n\t\t\t}\n\n\t\t\treturn elem.selected === true;\n\t\t},\n\n\t\t// Contents\n\t\t\"empty\": function( elem ) {\n\t\t\t// http://www.w3.org/TR/selectors/#empty-pseudo\n\t\t\t// :empty is only affected by element nodes and content nodes(including text(3), cdata(4)),\n\t\t\t//   not comment, processing instructions, or others\n\t\t\t// Thanks to Diego Perini for the nodeName shortcut\n\t\t\t//   Greater than \"@\" means alpha characters (specifically not starting with \"#\" or \"?\")\n\t\t\tfor ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {\n\t\t\t\tif ( elem.nodeName > \"@\" || elem.nodeType === 3 || elem.nodeType === 4 ) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn true;\n\t\t},\n\n\t\t\"parent\": function( elem ) {\n\t\t\treturn !Expr.pseudos[\"empty\"]( elem );\n\t\t},\n\n\t\t// Element/input types\n\t\t\"header\": function( elem ) {\n\t\t\treturn rheader.test( elem.nodeName );\n\t\t},\n\n\t\t\"input\": function( elem ) {\n\t\t\treturn rinputs.test( elem.nodeName );\n\t\t},\n\n\t\t\"button\": function( elem ) {\n\t\t\tvar name = elem.nodeName.toLowerCase();\n\t\t\treturn name === \"input\" && elem.type === \"button\" || name === \"button\";\n\t\t},\n\n\t\t\"text\": function( elem ) {\n\t\t\tvar attr;\n\t\t\t// IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc)\n\t\t\t// use getAttribute instead to test this case\n\t\t\treturn elem.nodeName.toLowerCase() === \"input\" &&\n\t\t\t\telem.type === \"text\" &&\n\t\t\t\t( (attr = elem.getAttribute(\"type\")) == null || attr.toLowerCase() === elem.type );\n\t\t},\n\n\t\t// Position-in-collection\n\t\t\"first\": createPositionalPseudo(function() {\n\t\t\treturn [ 0 ];\n\t\t}),\n\n\t\t\"last\": createPositionalPseudo(function( matchIndexes, length ) {\n\t\t\treturn [ length - 1 ];\n\t\t}),\n\n\t\t\"eq\": createPositionalPseudo(function( matchIndexes, length, argument ) {\n\t\t\treturn [ argument < 0 ? argument + length : argument ];\n\t\t}),\n\n\t\t\"even\": createPositionalPseudo(function( matchIndexes, length ) {\n\t\t\tvar i = 0;\n\t\t\tfor ( ; i < length; i += 2 ) {\n\t\t\t\tmatchIndexes.push( i );\n\t\t\t}\n\t\t\treturn matchIndexes;\n\t\t}),\n\n\t\t\"odd\": createPositionalPseudo(function( matchIndexes, length ) {\n\t\t\tvar i = 1;\n\t\t\tfor ( ; i < length; i += 2 ) {\n\t\t\t\tmatchIndexes.push( i );\n\t\t\t}\n\t\t\treturn matchIndexes;\n\t\t}),\n\n\t\t\"lt\": createPositionalPseudo(function( matchIndexes, length, argument ) {\n\t\t\tvar i = argument < 0 ? argument + length : argument;\n\t\t\tfor ( ; --i >= 0; ) {\n\t\t\t\tmatchIndexes.push( i );\n\t\t\t}\n\t\t\treturn matchIndexes;\n\t\t}),\n\n\t\t\"gt\": createPositionalPseudo(function( matchIndexes, length, argument ) {\n\t\t\tvar i = argument < 0 ? argument + length : argument;\n\t\t\tfor ( ; ++i < length; ) {\n\t\t\t\tmatchIndexes.push( i );\n\t\t\t}\n\t\t\treturn matchIndexes;\n\t\t})\n\t}\n};\n\n// Add button/input type pseudos\nfor ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) {\n\tExpr.pseudos[ i ] = createInputPseudo( i );\n}\nfor ( i in { submit: true, reset: true } ) {\n\tExpr.pseudos[ i ] = createButtonPseudo( i );\n}\n\nfunction tokenize( selector, parseOnly ) {\n\tvar matched, match, tokens, type,\n\t\tsoFar, groups, preFilters,\n\t\tcached = tokenCache[ selector + \" \" ];\n\n\tif ( cached ) {\n\t\treturn parseOnly ? 0 : cached.slice( 0 );\n\t}\n\n\tsoFar = selector;\n\tgroups = [];\n\tpreFilters = Expr.preFilter;\n\n\twhile ( soFar ) {\n\n\t\t// Comma and first run\n\t\tif ( !matched || (match = rcomma.exec( soFar )) ) {\n\t\t\tif ( match ) {\n\t\t\t\t// Don't consume trailing commas as valid\n\t\t\t\tsoFar = soFar.slice( match[0].length ) || soFar;\n\t\t\t}\n\t\t\tgroups.push( tokens = [] );\n\t\t}\n\n\t\tmatched = false;\n\n\t\t// Combinators\n\t\tif ( (match = rcombinators.exec( soFar )) ) {\n\t\t\tmatched = match.shift();\n\t\t\ttokens.push( {\n\t\t\t\tvalue: matched,\n\t\t\t\t// Cast descendant combinators to space\n\t\t\t\ttype: match[0].replace( rtrim, \" \" )\n\t\t\t} );\n\t\t\tsoFar = soFar.slice( matched.length );\n\t\t}\n\n\t\t// Filters\n\t\tfor ( type in Expr.filter ) {\n\t\t\tif ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] ||\n\t\t\t\t(match = preFilters[ type ]( match ))) ) {\n\t\t\t\tmatched = match.shift();\n\t\t\t\ttokens.push( {\n\t\t\t\t\tvalue: matched,\n\t\t\t\t\ttype: type,\n\t\t\t\t\tmatches: match\n\t\t\t\t} );\n\t\t\t\tsoFar = soFar.slice( matched.length );\n\t\t\t}\n\t\t}\n\n\t\tif ( !matched ) {\n\t\t\tbreak;\n\t\t}\n\t}\n\n\t// Return the length of the invalid excess\n\t// if we're just parsing\n\t// Otherwise, throw an error or return tokens\n\treturn parseOnly ?\n\t\tsoFar.length :\n\t\tsoFar ?\n\t\t\tSizzle.error( selector ) :\n\t\t\t// Cache the tokens\n\t\t\ttokenCache( selector, groups ).slice( 0 );\n}\n\nfunction toSelector( tokens ) {\n\tvar i = 0,\n\t\tlen = tokens.length,\n\t\tselector = \"\";\n\tfor ( ; i < len; i++ ) {\n\t\tselector += tokens[i].value;\n\t}\n\treturn selector;\n}\n\nfunction addCombinator( matcher, combinator, base ) {\n\tvar dir = combinator.dir,\n\t\tcheckNonElements = base && dir === \"parentNode\",\n\t\tdoneName = done++;\n\n\treturn combinator.first ?\n\t\t// Check against closest ancestor/preceding element\n\t\tfunction( elem, context, xml ) {\n\t\t\twhile ( (elem = elem[ dir ]) ) {\n\t\t\t\tif ( elem.nodeType === 1 || checkNonElements ) {\n\t\t\t\t\treturn matcher( elem, context, xml );\n\t\t\t\t}\n\t\t\t}\n\t\t} :\n\n\t\t// Check against all ancestor/preceding elements\n\t\tfunction( elem, context, xml ) {\n\t\t\tvar data, cache, outerCache,\n\t\t\t\tdirkey = dirruns + \" \" + doneName;\n\n\t\t\t// We can't set arbitrary data on XML nodes, so they don't benefit from dir caching\n\t\t\tif ( xml ) {\n\t\t\t\twhile ( (elem = elem[ dir ]) ) {\n\t\t\t\t\tif ( elem.nodeType === 1 || checkNonElements ) {\n\t\t\t\t\t\tif ( matcher( elem, context, xml ) ) {\n\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\twhile ( (elem = elem[ dir ]) ) {\n\t\t\t\t\tif ( elem.nodeType === 1 || checkNonElements ) {\n\t\t\t\t\t\touterCache = elem[ expando ] || (elem[ expando ] = {});\n\t\t\t\t\t\tif ( (cache = outerCache[ dir ]) && cache[0] === dirkey ) {\n\t\t\t\t\t\t\tif ( (data = cache[1]) === true || data === cachedruns ) {\n\t\t\t\t\t\t\t\treturn data === true;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tcache = outerCache[ dir ] = [ dirkey ];\n\t\t\t\t\t\t\tcache[1] = matcher( elem, context, xml ) || cachedruns;\n\t\t\t\t\t\t\tif ( cache[1] === true ) {\n\t\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t};\n}\n\nfunction elementMatcher( matchers ) {\n\treturn matchers.length > 1 ?\n\t\tfunction( elem, context, xml ) {\n\t\t\tvar i = matchers.length;\n\t\t\twhile ( i-- ) {\n\t\t\t\tif ( !matchers[i]( elem, context, xml ) ) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn true;\n\t\t} :\n\t\tmatchers[0];\n}\n\nfunction condense( unmatched, map, filter, context, xml ) {\n\tvar elem,\n\t\tnewUnmatched = [],\n\t\ti = 0,\n\t\tlen = unmatched.length,\n\t\tmapped = map != null;\n\n\tfor ( ; i < len; i++ ) {\n\t\tif ( (elem = unmatched[i]) ) {\n\t\t\tif ( !filter || filter( elem, context, xml ) ) {\n\t\t\t\tnewUnmatched.push( elem );\n\t\t\t\tif ( mapped ) {\n\t\t\t\t\tmap.push( i );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn newUnmatched;\n}\n\nfunction setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) {\n\tif ( postFilter && !postFilter[ expando ] ) {\n\t\tpostFilter = setMatcher( postFilter );\n\t}\n\tif ( postFinder && !postFinder[ expando ] ) {\n\t\tpostFinder = setMatcher( postFinder, postSelector );\n\t}\n\treturn markFunction(function( seed, results, context, xml ) {\n\t\tvar temp, i, elem,\n\t\t\tpreMap = [],\n\t\t\tpostMap = [],\n\t\t\tpreexisting = results.length,\n\n\t\t\t// Get initial elements from seed or context\n\t\t\telems = seed || multipleContexts( selector || \"*\", context.nodeType ? [ context ] : context, [] ),\n\n\t\t\t// Prefilter to get matcher input, preserving a map for seed-results synchronization\n\t\t\tmatcherIn = preFilter && ( seed || !selector ) ?\n\t\t\t\tcondense( elems, preMap, preFilter, context, xml ) :\n\t\t\t\telems,\n\n\t\t\tmatcherOut = matcher ?\n\t\t\t\t// If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results,\n\t\t\t\tpostFinder || ( seed ? preFilter : preexisting || postFilter ) ?\n\n\t\t\t\t\t// ...intermediate processing is necessary\n\t\t\t\t\t[] :\n\n\t\t\t\t\t// ...otherwise use results directly\n\t\t\t\t\tresults :\n\t\t\t\tmatcherIn;\n\n\t\t// Find primary matches\n\t\tif ( matcher ) {\n\t\t\tmatcher( matcherIn, matcherOut, context, xml );\n\t\t}\n\n\t\t// Apply postFilter\n\t\tif ( postFilter ) {\n\t\t\ttemp = condense( matcherOut, postMap );\n\t\t\tpostFilter( temp, [], context, xml );\n\n\t\t\t// Un-match failing elements by moving them back to matcherIn\n\t\t\ti = temp.length;\n\t\t\twhile ( i-- ) {\n\t\t\t\tif ( (elem = temp[i]) ) {\n\t\t\t\t\tmatcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif ( seed ) {\n\t\t\tif ( postFinder || preFilter ) {\n\t\t\t\tif ( postFinder ) {\n\t\t\t\t\t// Get the final matcherOut by condensing this intermediate into postFinder contexts\n\t\t\t\t\ttemp = [];\n\t\t\t\t\ti = matcherOut.length;\n\t\t\t\t\twhile ( i-- ) {\n\t\t\t\t\t\tif ( (elem = matcherOut[i]) ) {\n\t\t\t\t\t\t\t// Restore matcherIn since elem is not yet a final match\n\t\t\t\t\t\t\ttemp.push( (matcherIn[i] = elem) );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tpostFinder( null, (matcherOut = []), temp, xml );\n\t\t\t\t}\n\n\t\t\t\t// Move matched elements from seed to results to keep them synchronized\n\t\t\t\ti = matcherOut.length;\n\t\t\t\twhile ( i-- ) {\n\t\t\t\t\tif ( (elem = matcherOut[i]) &&\n\t\t\t\t\t\t(temp = postFinder ? indexOf.call( seed, elem ) : preMap[i]) > -1 ) {\n\n\t\t\t\t\t\tseed[temp] = !(results[temp] = elem);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t// Add elements to results, through postFinder if defined\n\t\t} else {\n\t\t\tmatcherOut = condense(\n\t\t\t\tmatcherOut === results ?\n\t\t\t\t\tmatcherOut.splice( preexisting, matcherOut.length ) :\n\t\t\t\t\tmatcherOut\n\t\t\t);\n\t\t\tif ( postFinder ) {\n\t\t\t\tpostFinder( null, results, matcherOut, xml );\n\t\t\t} else {\n\t\t\t\tpush.apply( results, matcherOut );\n\t\t\t}\n\t\t}\n\t});\n}\n\nfunction matcherFromTokens( tokens ) {\n\tvar checkContext, matcher, j,\n\t\tlen = tokens.length,\n\t\tleadingRelative = Expr.relative[ tokens[0].type ],\n\t\timplicitRelative = leadingRelative || Expr.relative[\" \"],\n\t\ti = leadingRelative ? 1 : 0,\n\n\t\t// The foundational matcher ensures that elements are reachable from top-level context(s)\n\t\tmatchContext = addCombinator( function( elem ) {\n\t\t\treturn elem === checkContext;\n\t\t}, implicitRelative, true ),\n\t\tmatchAnyContext = addCombinator( function( elem ) {\n\t\t\treturn indexOf.call( checkContext, elem ) > -1;\n\t\t}, implicitRelative, true ),\n\t\tmatchers = [ function( elem, context, xml ) {\n\t\t\treturn ( !leadingRelative && ( xml || context !== outermostContext ) ) || (\n\t\t\t\t(checkContext = context).nodeType ?\n\t\t\t\t\tmatchContext( elem, context, xml ) :\n\t\t\t\t\tmatchAnyContext( elem, context, xml ) );\n\t\t} ];\n\n\tfor ( ; i < len; i++ ) {\n\t\tif ( (matcher = Expr.relative[ tokens[i].type ]) ) {\n\t\t\tmatchers = [ addCombinator(elementMatcher( matchers ), matcher) ];\n\t\t} else {\n\t\t\tmatcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches );\n\n\t\t\t// Return special upon seeing a positional matcher\n\t\t\tif ( matcher[ expando ] ) {\n\t\t\t\t// Find the next relative operator (if any) for proper handling\n\t\t\t\tj = ++i;\n\t\t\t\tfor ( ; j < len; j++ ) {\n\t\t\t\t\tif ( Expr.relative[ tokens[j].type ] ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn setMatcher(\n\t\t\t\t\ti > 1 && elementMatcher( matchers ),\n\t\t\t\t\ti > 1 && toSelector( tokens.slice( 0, i - 1 ) ).replace( rtrim, \"$1\" ),\n\t\t\t\t\tmatcher,\n\t\t\t\t\ti < j && matcherFromTokens( tokens.slice( i, j ) ),\n\t\t\t\t\tj < len && matcherFromTokens( (tokens = tokens.slice( j )) ),\n\t\t\t\t\tj < len && toSelector( tokens )\n\t\t\t\t);\n\t\t\t}\n\t\t\tmatchers.push( matcher );\n\t\t}\n\t}\n\n\treturn elementMatcher( matchers );\n}\n\nfunction matcherFromGroupMatchers( elementMatchers, setMatchers ) {\n\t// A counter to specify which element is currently being matched\n\tvar matcherCachedRuns = 0,\n\t\tbySet = setMatchers.length > 0,\n\t\tbyElement = elementMatchers.length > 0,\n\t\tsuperMatcher = function( seed, context, xml, results, expandContext ) {\n\t\t\tvar elem, j, matcher,\n\t\t\t\tsetMatched = [],\n\t\t\t\tmatchedCount = 0,\n\t\t\t\ti = \"0\",\n\t\t\t\tunmatched = seed && [],\n\t\t\t\toutermost = expandContext != null,\n\t\t\t\tcontextBackup = outermostContext,\n\t\t\t\t// We must always have either seed elements or context\n\t\t\t\telems = seed || byElement && Expr.find[\"TAG\"]( \"*\", expandContext && context.parentNode || context ),\n\t\t\t\t// Use integer dirruns iff this is the outermost matcher\n\t\t\t\tdirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1);\n\n\t\t\tif ( outermost ) {\n\t\t\t\toutermostContext = context !== document && context;\n\t\t\t\tcachedruns = matcherCachedRuns;\n\t\t\t}\n\n\t\t\t// Add elements passing elementMatchers directly to results\n\t\t\t// Keep `i` a string if there are no elements so `matchedCount` will be \"00\" below\n\t\t\tfor ( ; (elem = elems[i]) != null; i++ ) {\n\t\t\t\tif ( byElement && elem ) {\n\t\t\t\t\tj = 0;\n\t\t\t\t\twhile ( (matcher = elementMatchers[j++]) ) {\n\t\t\t\t\t\tif ( matcher( elem, context, xml ) ) {\n\t\t\t\t\t\t\tresults.push( elem );\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif ( outermost ) {\n\t\t\t\t\t\tdirruns = dirrunsUnique;\n\t\t\t\t\t\tcachedruns = ++matcherCachedRuns;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Track unmatched elements for set filters\n\t\t\t\tif ( bySet ) {\n\t\t\t\t\t// They will have gone through all possible matchers\n\t\t\t\t\tif ( (elem = !matcher && elem) ) {\n\t\t\t\t\t\tmatchedCount--;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Lengthen the array for every element, matched or not\n\t\t\t\t\tif ( seed ) {\n\t\t\t\t\t\tunmatched.push( elem );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Apply set filters to unmatched elements\n\t\t\tmatchedCount += i;\n\t\t\tif ( bySet && i !== matchedCount ) {\n\t\t\t\tj = 0;\n\t\t\t\twhile ( (matcher = setMatchers[j++]) ) {\n\t\t\t\t\tmatcher( unmatched, setMatched, context, xml );\n\t\t\t\t}\n\n\t\t\t\tif ( seed ) {\n\t\t\t\t\t// Reintegrate element matches to eliminate the need for sorting\n\t\t\t\t\tif ( matchedCount > 0 ) {\n\t\t\t\t\t\twhile ( i-- ) {\n\t\t\t\t\t\t\tif ( !(unmatched[i] || setMatched[i]) ) {\n\t\t\t\t\t\t\t\tsetMatched[i] = pop.call( results );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Discard index placeholder values to get only actual matches\n\t\t\t\t\tsetMatched = condense( setMatched );\n\t\t\t\t}\n\n\t\t\t\t// Add matches to results\n\t\t\t\tpush.apply( results, setMatched );\n\n\t\t\t\t// Seedless set matches succeeding multiple successful matchers stipulate sorting\n\t\t\t\tif ( outermost && !seed && setMatched.length > 0 &&\n\t\t\t\t\t( matchedCount + setMatchers.length ) > 1 ) {\n\n\t\t\t\t\tSizzle.uniqueSort( results );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Override manipulation of globals by nested matchers\n\t\t\tif ( outermost ) {\n\t\t\t\tdirruns = dirrunsUnique;\n\t\t\t\toutermostContext = contextBackup;\n\t\t\t}\n\n\t\t\treturn unmatched;\n\t\t};\n\n\treturn bySet ?\n\t\tmarkFunction( superMatcher ) :\n\t\tsuperMatcher;\n}\n\ncompile = Sizzle.compile = function( selector, group /* Internal Use Only */ ) {\n\tvar i,\n\t\tsetMatchers = [],\n\t\telementMatchers = [],\n\t\tcached = compilerCache[ selector + \" \" ];\n\n\tif ( !cached ) {\n\t\t// Generate a function of recursive functions that can be used to check each element\n\t\tif ( !group ) {\n\t\t\tgroup = tokenize( selector );\n\t\t}\n\t\ti = group.length;\n\t\twhile ( i-- ) {\n\t\t\tcached = matcherFromTokens( group[i] );\n\t\t\tif ( cached[ expando ] ) {\n\t\t\t\tsetMatchers.push( cached );\n\t\t\t} else {\n\t\t\t\telementMatchers.push( cached );\n\t\t\t}\n\t\t}\n\n\t\t// Cache the compiled function\n\t\tcached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) );\n\t}\n\treturn cached;\n};\n\nfunction multipleContexts( selector, contexts, results ) {\n\tvar i = 0,\n\t\tlen = contexts.length;\n\tfor ( ; i < len; i++ ) {\n\t\tSizzle( selector, contexts[i], results );\n\t}\n\treturn results;\n}\n\nfunction select( selector, context, results, seed ) {\n\tvar i, tokens, token, type, find,\n\t\tmatch = tokenize( selector );\n\n\tif ( !seed ) {\n\t\t// Try to minimize operations if there is only one group\n\t\tif ( match.length === 1 ) {\n\n\t\t\t// Take a shortcut and set the context if the root selector is an ID\n\t\t\ttokens = match[0] = match[0].slice( 0 );\n\t\t\tif ( tokens.length > 2 && (token = tokens[0]).type === \"ID\" &&\n\t\t\t\t\tcontext.nodeType === 9 && !documentIsXML &&\n\t\t\t\t\tExpr.relative[ tokens[1].type ] ) {\n\n\t\t\t\tcontext = Expr.find[\"ID\"]( token.matches[0].replace( runescape, funescape ), context )[0];\n\t\t\t\tif ( !context ) {\n\t\t\t\t\treturn results;\n\t\t\t\t}\n\n\t\t\t\tselector = selector.slice( tokens.shift().value.length );\n\t\t\t}\n\n\t\t\t// Fetch a seed set for right-to-left matching\n\t\t\ti = matchExpr[\"needsContext\"].test( selector ) ? 0 : tokens.length;\n\t\t\twhile ( i-- ) {\n\t\t\t\ttoken = tokens[i];\n\n\t\t\t\t// Abort if we hit a combinator\n\t\t\t\tif ( Expr.relative[ (type = token.type) ] ) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tif ( (find = Expr.find[ type ]) ) {\n\t\t\t\t\t// Search, expanding context for leading sibling combinators\n\t\t\t\t\tif ( (seed = find(\n\t\t\t\t\t\ttoken.matches[0].replace( runescape, funescape ),\n\t\t\t\t\t\trsibling.test( tokens[0].type ) && context.parentNode || context\n\t\t\t\t\t)) ) {\n\n\t\t\t\t\t\t// If seed is empty or no tokens remain, we can return early\n\t\t\t\t\t\ttokens.splice( i, 1 );\n\t\t\t\t\t\tselector = seed.length && toSelector( tokens );\n\t\t\t\t\t\tif ( !selector ) {\n\t\t\t\t\t\t\tpush.apply( results, slice.call( seed, 0 ) );\n\t\t\t\t\t\t\treturn results;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Compile and execute a filtering function\n\t// Provide `match` to avoid retokenization if we modified the selector above\n\tcompile( selector, match )(\n\t\tseed,\n\t\tcontext,\n\t\tdocumentIsXML,\n\t\tresults,\n\t\trsibling.test( selector )\n\t);\n\treturn results;\n}\n\n// Deprecated\nExpr.pseudos[\"nth\"] = Expr.pseudos[\"eq\"];\n\n// Easy API for creating new setFilters\nfunction setFilters() {}\nExpr.filters = setFilters.prototype = Expr.pseudos;\nExpr.setFilters = new setFilters();\n\n// Initialize with the default document\nsetDocument();\n\n// Override sizzle attribute retrieval\nSizzle.attr = jQuery.attr;\njQuery.find = Sizzle;\njQuery.expr = Sizzle.selectors;\njQuery.expr[\":\"] = jQuery.expr.pseudos;\njQuery.unique = Sizzle.uniqueSort;\njQuery.text = Sizzle.getText;\njQuery.isXMLDoc = Sizzle.isXML;\njQuery.contains = Sizzle.contains;\n\n\n})( window );\nvar runtil = /Until$/,\n\trparentsprev = /^(?:parents|prev(?:Until|All))/,\n\tisSimple = /^.[^:#\\[\\.,]*$/,\n\trneedsContext = jQuery.expr.match.needsContext,\n\t// methods guaranteed to produce a unique set when starting from a unique set\n\tguaranteedUnique = {\n\t\tchildren: true,\n\t\tcontents: true,\n\t\tnext: true,\n\t\tprev: true\n\t};\n\njQuery.fn.extend({\n\tfind: function( selector ) {\n\t\tvar i, ret, self,\n\t\t\tlen = this.length;\n\n\t\tif ( typeof selector !== \"string\" ) {\n\t\t\tself = this;\n\t\t\treturn this.pushStack( jQuery( selector ).filter(function() {\n\t\t\t\tfor ( i = 0; i < len; i++ ) {\n\t\t\t\t\tif ( jQuery.contains( self[ i ], this ) ) {\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}) );\n\t\t}\n\n\t\tret = [];\n\t\tfor ( i = 0; i < len; i++ ) {\n\t\t\tjQuery.find( selector, this[ i ], ret );\n\t\t}\n\n\t\t// Needed because $( selector, context ) becomes $( context ).find( selector )\n\t\tret = this.pushStack( len > 1 ? jQuery.unique( ret ) : ret );\n\t\tret.selector = ( this.selector ? this.selector + \" \" : \"\" ) + selector;\n\t\treturn ret;\n\t},\n\n\thas: function( target ) {\n\t\tvar i,\n\t\t\ttargets = jQuery( target, this ),\n\t\t\tlen = targets.length;\n\n\t\treturn this.filter(function() {\n\t\t\tfor ( i = 0; i < len; i++ ) {\n\t\t\t\tif ( jQuery.contains( this, targets[i] ) ) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t},\n\n\tnot: function( selector ) {\n\t\treturn this.pushStack( winnow(this, selector, false) );\n\t},\n\n\tfilter: function( selector ) {\n\t\treturn this.pushStack( winnow(this, selector, true) );\n\t},\n\n\tis: function( selector ) {\n\t\treturn !!selector && (\n\t\t\ttypeof selector === \"string\" ?\n\t\t\t\t// If this is a positional/relative selector, check membership in the returned set\n\t\t\t\t// so $(\"p:first\").is(\"p:last\") won't return true for a doc with two \"p\".\n\t\t\t\trneedsContext.test( selector ) ?\n\t\t\t\t\tjQuery( selector, this.context ).index( this[0] ) >= 0 :\n\t\t\t\t\tjQuery.filter( selector, this ).length > 0 :\n\t\t\t\tthis.filter( selector ).length > 0 );\n\t},\n\n\tclosest: function( selectors, context ) {\n\t\tvar cur,\n\t\t\ti = 0,\n\t\t\tl = this.length,\n\t\t\tret = [],\n\t\t\tpos = rneedsContext.test( selectors ) || typeof selectors !== \"string\" ?\n\t\t\t\tjQuery( selectors, context || this.context ) :\n\t\t\t\t0;\n\n\t\tfor ( ; i < l; i++ ) {\n\t\t\tcur = this[i];\n\n\t\t\twhile ( cur && cur.ownerDocument && cur !== context && cur.nodeType !== 11 ) {\n\t\t\t\tif ( pos ? pos.index(cur) > -1 : jQuery.find.matchesSelector(cur, selectors) ) {\n\t\t\t\t\tret.push( cur );\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcur = cur.parentNode;\n\t\t\t}\n\t\t}\n\n\t\treturn this.pushStack( ret.length > 1 ? jQuery.unique( ret ) : ret );\n\t},\n\n\t// Determine the position of an element within\n\t// the matched set of elements\n\tindex: function( elem ) {\n\n\t\t// No argument, return index in parent\n\t\tif ( !elem ) {\n\t\t\treturn ( this[0] && this[0].parentNode ) ? this.first().prevAll().length : -1;\n\t\t}\n\n\t\t// index in selector\n\t\tif ( typeof elem === \"string\" ) {\n\t\t\treturn jQuery.inArray( this[0], jQuery( elem ) );\n\t\t}\n\n\t\t// Locate the position of the desired element\n\t\treturn jQuery.inArray(\n\t\t\t// If it receives a jQuery object, the first element is used\n\t\t\telem.jquery ? elem[0] : elem, this );\n\t},\n\n\tadd: function( selector, context ) {\n\t\tvar set = typeof selector === \"string\" ?\n\t\t\t\tjQuery( selector, context ) :\n\t\t\t\tjQuery.makeArray( selector && selector.nodeType ? [ selector ] : selector ),\n\t\t\tall = jQuery.merge( this.get(), set );\n\n\t\treturn this.pushStack( jQuery.unique(all) );\n\t},\n\n\taddBack: function( selector ) {\n\t\treturn this.add( selector == null ?\n\t\t\tthis.prevObject : this.prevObject.filter(selector)\n\t\t);\n\t}\n});\n\njQuery.fn.andSelf = jQuery.fn.addBack;\n\nfunction sibling( cur, dir ) {\n\tdo {\n\t\tcur = cur[ dir ];\n\t} while ( cur && cur.nodeType !== 1 );\n\n\treturn cur;\n}\n\njQuery.each({\n\tparent: function( elem ) {\n\t\tvar parent = elem.parentNode;\n\t\treturn parent && parent.nodeType !== 11 ? parent : null;\n\t},\n\tparents: function( elem ) {\n\t\treturn jQuery.dir( elem, \"parentNode\" );\n\t},\n\tparentsUntil: function( elem, i, until ) {\n\t\treturn jQuery.dir( elem, \"parentNode\", until );\n\t},\n\tnext: function( elem ) {\n\t\treturn sibling( elem, \"nextSibling\" );\n\t},\n\tprev: function( elem ) {\n\t\treturn sibling( elem, \"previousSibling\" );\n\t},\n\tnextAll: function( elem ) {\n\t\treturn jQuery.dir( elem, \"nextSibling\" );\n\t},\n\tprevAll: function( elem ) {\n\t\treturn jQuery.dir( elem, \"previousSibling\" );\n\t},\n\tnextUntil: function( elem, i, until ) {\n\t\treturn jQuery.dir( elem, \"nextSibling\", until );\n\t},\n\tprevUntil: function( elem, i, until ) {\n\t\treturn jQuery.dir( elem, \"previousSibling\", until );\n\t},\n\tsiblings: function( elem ) {\n\t\treturn jQuery.sibling( ( elem.parentNode || {} ).firstChild, elem );\n\t},\n\tchildren: function( elem ) {\n\t\treturn jQuery.sibling( elem.firstChild );\n\t},\n\tcontents: function( elem ) {\n\t\treturn jQuery.nodeName( elem, \"iframe\" ) ?\n\t\t\telem.contentDocument || elem.contentWindow.document :\n\t\t\tjQuery.merge( [], elem.childNodes );\n\t}\n}, function( name, fn ) {\n\tjQuery.fn[ name ] = function( until, selector ) {\n\t\tvar ret = jQuery.map( this, fn, until );\n\n\t\tif ( !runtil.test( name ) ) {\n\t\t\tselector = until;\n\t\t}\n\n\t\tif ( selector && typeof selector === \"string\" ) {\n\t\t\tret = jQuery.filter( selector, ret );\n\t\t}\n\n\t\tret = this.length > 1 && !guaranteedUnique[ name ] ? jQuery.unique( ret ) : ret;\n\n\t\tif ( this.length > 1 && rparentsprev.test( name ) ) {\n\t\t\tret = ret.reverse();\n\t\t}\n\n\t\treturn this.pushStack( ret );\n\t};\n});\n\njQuery.extend({\n\tfilter: function( expr, elems, not ) {\n\t\tif ( not ) {\n\t\t\texpr = \":not(\" + expr + \")\";\n\t\t}\n\n\t\treturn elems.length === 1 ?\n\t\t\tjQuery.find.matchesSelector(elems[0], expr) ? [ elems[0] ] : [] :\n\t\t\tjQuery.find.matches(expr, elems);\n\t},\n\n\tdir: function( elem, dir, until ) {\n\t\tvar matched = [],\n\t\t\tcur = elem[ dir ];\n\n\t\twhile ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) {\n\t\t\tif ( cur.nodeType === 1 ) {\n\t\t\t\tmatched.push( cur );\n\t\t\t}\n\t\t\tcur = cur[dir];\n\t\t}\n\t\treturn matched;\n\t},\n\n\tsibling: function( n, elem ) {\n\t\tvar r = [];\n\n\t\tfor ( ; n; n = n.nextSibling ) {\n\t\t\tif ( n.nodeType === 1 && n !== elem ) {\n\t\t\t\tr.push( n );\n\t\t\t}\n\t\t}\n\n\t\treturn r;\n\t}\n});\n\n// Implement the identical functionality for filter and not\nfunction winnow( elements, qualifier, keep ) {\n\n\t// Can't pass null or undefined to indexOf in Firefox 4\n\t// Set to 0 to skip string check\n\tqualifier = qualifier || 0;\n\n\tif ( jQuery.isFunction( qualifier ) ) {\n\t\treturn jQuery.grep(elements, function( elem, i ) {\n\t\t\tvar retVal = !!qualifier.call( elem, i, elem );\n\t\t\treturn retVal === keep;\n\t\t});\n\n\t} else if ( qualifier.nodeType ) {\n\t\treturn jQuery.grep(elements, function( elem ) {\n\t\t\treturn ( elem === qualifier ) === keep;\n\t\t});\n\n\t} else if ( typeof qualifier === \"string\" ) {\n\t\tvar filtered = jQuery.grep(elements, function( elem ) {\n\t\t\treturn elem.nodeType === 1;\n\t\t});\n\n\t\tif ( isSimple.test( qualifier ) ) {\n\t\t\treturn jQuery.filter(qualifier, filtered, !keep);\n\t\t} else {\n\t\t\tqualifier = jQuery.filter( qualifier, filtered );\n\t\t}\n\t}\n\n\treturn jQuery.grep(elements, function( elem ) {\n\t\treturn ( jQuery.inArray( elem, qualifier ) >= 0 ) === keep;\n\t});\n}\nfunction createSafeFragment( document ) {\n\tvar list = nodeNames.split( \"|\" ),\n\t\tsafeFrag = document.createDocumentFragment();\n\n\tif ( safeFrag.createElement ) {\n\t\twhile ( list.length ) {\n\t\t\tsafeFrag.createElement(\n\t\t\t\tlist.pop()\n\t\t\t);\n\t\t}\n\t}\n\treturn safeFrag;\n}\n\nvar nodeNames = \"abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|\" +\n\t\t\"header|hgroup|mark|meter|nav|output|progress|section|summary|time|video\",\n\trinlinejQuery = / jQuery\\d+=\"(?:null|\\d+)\"/g,\n\trnoshimcache = new RegExp(\"<(?:\" + nodeNames + \")[\\\\s/>]\", \"i\"),\n\trleadingWhitespace = /^\\s+/,\n\trxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\\w:]+)[^>]*)\\/>/gi,\n\trtagName = /<([\\w:]+)/,\n\trtbody = /<tbody/i,\n\trhtml = /<|&#?\\w+;/,\n\trnoInnerhtml = /<(?:script|style|link)/i,\n\tmanipulation_rcheckableType = /^(?:checkbox|radio)$/i,\n\t// checked=\"checked\" or checked\n\trchecked = /checked\\s*(?:[^=]|=\\s*.checked.)/i,\n\trscriptType = /^$|\\/(?:java|ecma)script/i,\n\trscriptTypeMasked = /^true\\/(.*)/,\n\trcleanScript = /^\\s*<!(?:\\[CDATA\\[|--)|(?:\\]\\]|--)>\\s*$/g,\n\n\t// We have to close these tags to support XHTML (#13200)\n\twrapMap = {\n\t\toption: [ 1, \"<select multiple='multiple'>\", \"</select>\" ],\n\t\tlegend: [ 1, \"<fieldset>\", \"</fieldset>\" ],\n\t\tarea: [ 1, \"<map>\", \"</map>\" ],\n\t\tparam: [ 1, \"<object>\", \"</object>\" ],\n\t\tthead: [ 1, \"<table>\", \"</table>\" ],\n\t\ttr: [ 2, \"<table><tbody>\", \"</tbody></table>\" ],\n\t\tcol: [ 2, \"<table><tbody></tbody><colgroup>\", \"</colgroup></table>\" ],\n\t\ttd: [ 3, \"<table><tbody><tr>\", \"</tr></tbody></table>\" ],\n\n\t\t// IE6-8 can't serialize link, script, style, or any html5 (NoScope) tags,\n\t\t// unless wrapped in a div with non-breaking characters in front of it.\n\t\t_default: jQuery.support.htmlSerialize ? [ 0, \"\", \"\" ] : [ 1, \"X<div>\", \"</div>\"  ]\n\t},\n\tsafeFragment = createSafeFragment( document ),\n\tfragmentDiv = safeFragment.appendChild( document.createElement(\"div\") );\n\nwrapMap.optgroup = wrapMap.option;\nwrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;\nwrapMap.th = wrapMap.td;\n\njQuery.fn.extend({\n\ttext: function( value ) {\n\t\treturn jQuery.access( this, function( value ) {\n\t\t\treturn value === undefined ?\n\t\t\t\tjQuery.text( this ) :\n\t\t\t\tthis.empty().append( ( this[0] && this[0].ownerDocument || document ).createTextNode( value ) );\n\t\t}, null, value, arguments.length );\n\t},\n\n\twrapAll: function( html ) {\n\t\tif ( jQuery.isFunction( html ) ) {\n\t\t\treturn this.each(function(i) {\n\t\t\t\tjQuery(this).wrapAll( html.call(this, i) );\n\t\t\t});\n\t\t}\n\n\t\tif ( this[0] ) {\n\t\t\t// The elements to wrap the target around\n\t\t\tvar wrap = jQuery( html, this[0].ownerDocument ).eq(0).clone(true);\n\n\t\t\tif ( this[0].parentNode ) {\n\t\t\t\twrap.insertBefore( this[0] );\n\t\t\t}\n\n\t\t\twrap.map(function() {\n\t\t\t\tvar elem = this;\n\n\t\t\t\twhile ( elem.firstChild && elem.firstChild.nodeType === 1 ) {\n\t\t\t\t\telem = elem.firstChild;\n\t\t\t\t}\n\n\t\t\t\treturn elem;\n\t\t\t}).append( this );\n\t\t}\n\n\t\treturn this;\n\t},\n\n\twrapInner: function( html ) {\n\t\tif ( jQuery.isFunction( html ) ) {\n\t\t\treturn this.each(function(i) {\n\t\t\t\tjQuery(this).wrapInner( html.call(this, i) );\n\t\t\t});\n\t\t}\n\n\t\treturn this.each(function() {\n\t\t\tvar self = jQuery( this ),\n\t\t\t\tcontents = self.contents();\n\n\t\t\tif ( contents.length ) {\n\t\t\t\tcontents.wrapAll( html );\n\n\t\t\t} else {\n\t\t\t\tself.append( html );\n\t\t\t}\n\t\t});\n\t},\n\n\twrap: function( html ) {\n\t\tvar isFunction = jQuery.isFunction( html );\n\n\t\treturn this.each(function(i) {\n\t\t\tjQuery( this ).wrapAll( isFunction ? html.call(this, i) : html );\n\t\t});\n\t},\n\n\tunwrap: function() {\n\t\treturn this.parent().each(function() {\n\t\t\tif ( !jQuery.nodeName( this, \"body\" ) ) {\n\t\t\t\tjQuery( this ).replaceWith( this.childNodes );\n\t\t\t}\n\t\t}).end();\n\t},\n\n\tappend: function() {\n\t\treturn this.domManip(arguments, true, function( elem ) {\n\t\t\tif ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {\n\t\t\t\tthis.appendChild( elem );\n\t\t\t}\n\t\t});\n\t},\n\n\tprepend: function() {\n\t\treturn this.domManip(arguments, true, function( elem ) {\n\t\t\tif ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {\n\t\t\t\tthis.insertBefore( elem, this.firstChild );\n\t\t\t}\n\t\t});\n\t},\n\n\tbefore: function() {\n\t\treturn this.domManip( arguments, false, function( elem ) {\n\t\t\tif ( this.parentNode ) {\n\t\t\t\tthis.parentNode.insertBefore( elem, this );\n\t\t\t}\n\t\t});\n\t},\n\n\tafter: function() {\n\t\treturn this.domManip( arguments, false, function( elem ) {\n\t\t\tif ( this.parentNode ) {\n\t\t\t\tthis.parentNode.insertBefore( elem, this.nextSibling );\n\t\t\t}\n\t\t});\n\t},\n\n\t// keepData is for internal use only--do not document\n\tremove: function( selector, keepData ) {\n\t\tvar elem,\n\t\t\ti = 0;\n\n\t\tfor ( ; (elem = this[i]) != null; i++ ) {\n\t\t\tif ( !selector || jQuery.filter( selector, [ elem ] ).length > 0 ) {\n\t\t\t\tif ( !keepData && elem.nodeType === 1 ) {\n\t\t\t\t\tjQuery.cleanData( getAll( elem ) );\n\t\t\t\t}\n\n\t\t\t\tif ( elem.parentNode ) {\n\t\t\t\t\tif ( keepData && jQuery.contains( elem.ownerDocument, elem ) ) {\n\t\t\t\t\t\tsetGlobalEval( getAll( elem, \"script\" ) );\n\t\t\t\t\t}\n\t\t\t\t\telem.parentNode.removeChild( elem );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\tempty: function() {\n\t\tvar elem,\n\t\t\ti = 0;\n\n\t\tfor ( ; (elem = this[i]) != null; i++ ) {\n\t\t\t// Remove element nodes and prevent memory leaks\n\t\t\tif ( elem.nodeType === 1 ) {\n\t\t\t\tjQuery.cleanData( getAll( elem, false ) );\n\t\t\t}\n\n\t\t\t// Remove any remaining nodes\n\t\t\twhile ( elem.firstChild ) {\n\t\t\t\telem.removeChild( elem.firstChild );\n\t\t\t}\n\n\t\t\t// If this is a select, ensure that it displays empty (#12336)\n\t\t\t// Support: IE<9\n\t\t\tif ( elem.options && jQuery.nodeName( elem, \"select\" ) ) {\n\t\t\t\telem.options.length = 0;\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\tclone: function( dataAndEvents, deepDataAndEvents ) {\n\t\tdataAndEvents = dataAndEvents == null ? false : dataAndEvents;\n\t\tdeepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents;\n\n\t\treturn this.map( function () {\n\t\t\treturn jQuery.clone( this, dataAndEvents, deepDataAndEvents );\n\t\t});\n\t},\n\n\thtml: function( value ) {\n\t\treturn jQuery.access( this, function( value ) {\n\t\t\tvar elem = this[0] || {},\n\t\t\t\ti = 0,\n\t\t\t\tl = this.length;\n\n\t\t\tif ( value === undefined ) {\n\t\t\t\treturn elem.nodeType === 1 ?\n\t\t\t\t\telem.innerHTML.replace( rinlinejQuery, \"\" ) :\n\t\t\t\t\tundefined;\n\t\t\t}\n\n\t\t\t// See if we can take a shortcut and just use innerHTML\n\t\t\tif ( typeof value === \"string\" && !rnoInnerhtml.test( value ) &&\n\t\t\t\t( jQuery.support.htmlSerialize || !rnoshimcache.test( value )  ) &&\n\t\t\t\t( jQuery.support.leadingWhitespace || !rleadingWhitespace.test( value ) ) &&\n\t\t\t\t!wrapMap[ ( rtagName.exec( value ) || [\"\", \"\"] )[1].toLowerCase() ] ) {\n\n\t\t\t\tvalue = value.replace( rxhtmlTag, \"<$1></$2>\" );\n\n\t\t\t\ttry {\n\t\t\t\t\tfor (; i < l; i++ ) {\n\t\t\t\t\t\t// Remove element nodes and prevent memory leaks\n\t\t\t\t\t\telem = this[i] || {};\n\t\t\t\t\t\tif ( elem.nodeType === 1 ) {\n\t\t\t\t\t\t\tjQuery.cleanData( getAll( elem, false ) );\n\t\t\t\t\t\t\telem.innerHTML = value;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\telem = 0;\n\n\t\t\t\t// If using innerHTML throws an exception, use the fallback method\n\t\t\t\t} catch(e) {}\n\t\t\t}\n\n\t\t\tif ( elem ) {\n\t\t\t\tthis.empty().append( value );\n\t\t\t}\n\t\t}, null, value, arguments.length );\n\t},\n\n\treplaceWith: function( value ) {\n\t\tvar isFunc = jQuery.isFunction( value );\n\n\t\t// Make sure that the elements are removed from the DOM before they are inserted\n\t\t// this can help fix replacing a parent with child elements\n\t\tif ( !isFunc && typeof value !== \"string\" ) {\n\t\t\tvalue = jQuery( value ).not( this ).detach();\n\t\t}\n\n\t\treturn this.domManip( [ value ], true, function( elem ) {\n\t\t\tvar next = this.nextSibling,\n\t\t\t\tparent = this.parentNode;\n\n\t\t\tif ( parent ) {\n\t\t\t\tjQuery( this ).remove();\n\t\t\t\tparent.insertBefore( elem, next );\n\t\t\t}\n\t\t});\n\t},\n\n\tdetach: function( selector ) {\n\t\treturn this.remove( selector, true );\n\t},\n\n\tdomManip: function( args, table, callback ) {\n\n\t\t// Flatten any nested arrays\n\t\targs = core_concat.apply( [], args );\n\n\t\tvar first, node, hasScripts,\n\t\t\tscripts, doc, fragment,\n\t\t\ti = 0,\n\t\t\tl = this.length,\n\t\t\tset = this,\n\t\t\tiNoClone = l - 1,\n\t\t\tvalue = args[0],\n\t\t\tisFunction = jQuery.isFunction( value );\n\n\t\t// We can't cloneNode fragments that contain checked, in WebKit\n\t\tif ( isFunction || !( l <= 1 || typeof value !== \"string\" || jQuery.support.checkClone || !rchecked.test( value ) ) ) {\n\t\t\treturn this.each(function( index ) {\n\t\t\t\tvar self = set.eq( index );\n\t\t\t\tif ( isFunction ) {\n\t\t\t\t\targs[0] = value.call( this, index, table ? self.html() : undefined );\n\t\t\t\t}\n\t\t\t\tself.domManip( args, table, callback );\n\t\t\t});\n\t\t}\n\n\t\tif ( l ) {\n\t\t\tfragment = jQuery.buildFragment( args, this[ 0 ].ownerDocument, false, this );\n\t\t\tfirst = fragment.firstChild;\n\n\t\t\tif ( fragment.childNodes.length === 1 ) {\n\t\t\t\tfragment = first;\n\t\t\t}\n\n\t\t\tif ( first ) {\n\t\t\t\ttable = table && jQuery.nodeName( first, \"tr\" );\n\t\t\t\tscripts = jQuery.map( getAll( fragment, \"script\" ), disableScript );\n\t\t\t\thasScripts = scripts.length;\n\n\t\t\t\t// Use the original fragment for the last item instead of the first because it can end up\n\t\t\t\t// being emptied incorrectly in certain situations (#8070).\n\t\t\t\tfor ( ; i < l; i++ ) {\n\t\t\t\t\tnode = fragment;\n\n\t\t\t\t\tif ( i !== iNoClone ) {\n\t\t\t\t\t\tnode = jQuery.clone( node, true, true );\n\n\t\t\t\t\t\t// Keep references to cloned scripts for later restoration\n\t\t\t\t\t\tif ( hasScripts ) {\n\t\t\t\t\t\t\tjQuery.merge( scripts, getAll( node, \"script\" ) );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tcallback.call(\n\t\t\t\t\t\ttable && jQuery.nodeName( this[i], \"table\" ) ?\n\t\t\t\t\t\t\tfindOrAppend( this[i], \"tbody\" ) :\n\t\t\t\t\t\t\tthis[i],\n\t\t\t\t\t\tnode,\n\t\t\t\t\t\ti\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\tif ( hasScripts ) {\n\t\t\t\t\tdoc = scripts[ scripts.length - 1 ].ownerDocument;\n\n\t\t\t\t\t// Reenable scripts\n\t\t\t\t\tjQuery.map( scripts, restoreScript );\n\n\t\t\t\t\t// Evaluate executable scripts on first document insertion\n\t\t\t\t\tfor ( i = 0; i < hasScripts; i++ ) {\n\t\t\t\t\t\tnode = scripts[ i ];\n\t\t\t\t\t\tif ( rscriptType.test( node.type || \"\" ) &&\n\t\t\t\t\t\t\t!jQuery._data( node, \"globalEval\" ) && jQuery.contains( doc, node ) ) {\n\n\t\t\t\t\t\t\tif ( node.src ) {\n\t\t\t\t\t\t\t\t// Hope ajax is available...\n\t\t\t\t\t\t\t\tjQuery.ajax({\n\t\t\t\t\t\t\t\t\turl: node.src,\n\t\t\t\t\t\t\t\t\ttype: \"GET\",\n\t\t\t\t\t\t\t\t\tdataType: \"script\",\n\t\t\t\t\t\t\t\t\tasync: false,\n\t\t\t\t\t\t\t\t\tglobal: false,\n\t\t\t\t\t\t\t\t\t\"throws\": true\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tjQuery.globalEval( ( node.text || node.textContent || node.innerHTML || \"\" ).replace( rcleanScript, \"\" ) );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Fix #11809: Avoid leaking memory\n\t\t\t\tfragment = first = null;\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t}\n});\n\nfunction findOrAppend( elem, tag ) {\n\treturn elem.getElementsByTagName( tag )[0] || elem.appendChild( elem.ownerDocument.createElement( tag ) );\n}\n\n// Replace/restore the type attribute of script elements for safe DOM manipulation\nfunction disableScript( elem ) {\n\tvar attr = elem.getAttributeNode(\"type\");\n\telem.type = ( attr && attr.specified ) + \"/\" + elem.type;\n\treturn elem;\n}\nfunction restoreScript( elem ) {\n\tvar match = rscriptTypeMasked.exec( elem.type );\n\tif ( match ) {\n\t\telem.type = match[1];\n\t} else {\n\t\telem.removeAttribute(\"type\");\n\t}\n\treturn elem;\n}\n\n// Mark scripts as having already been evaluated\nfunction setGlobalEval( elems, refElements ) {\n\tvar elem,\n\t\ti = 0;\n\tfor ( ; (elem = elems[i]) != null; i++ ) {\n\t\tjQuery._data( elem, \"globalEval\", !refElements || jQuery._data( refElements[i], \"globalEval\" ) );\n\t}\n}\n\nfunction cloneCopyEvent( src, dest ) {\n\n\tif ( dest.nodeType !== 1 || !jQuery.hasData( src ) ) {\n\t\treturn;\n\t}\n\n\tvar type, i, l,\n\t\toldData = jQuery._data( src ),\n\t\tcurData = jQuery._data( dest, oldData ),\n\t\tevents = oldData.events;\n\n\tif ( events ) {\n\t\tdelete curData.handle;\n\t\tcurData.events = {};\n\n\t\tfor ( type in events ) {\n\t\t\tfor ( i = 0, l = events[ type ].length; i < l; i++ ) {\n\t\t\t\tjQuery.event.add( dest, type, events[ type ][ i ] );\n\t\t\t}\n\t\t}\n\t}\n\n\t// make the cloned public data object a copy from the original\n\tif ( curData.data ) {\n\t\tcurData.data = jQuery.extend( {}, curData.data );\n\t}\n}\n\nfunction fixCloneNodeIssues( src, dest ) {\n\tvar nodeName, e, data;\n\n\t// We do not need to do anything for non-Elements\n\tif ( dest.nodeType !== 1 ) {\n\t\treturn;\n\t}\n\n\tnodeName = dest.nodeName.toLowerCase();\n\n\t// IE6-8 copies events bound via attachEvent when using cloneNode.\n\tif ( !jQuery.support.noCloneEvent && dest[ jQuery.expando ] ) {\n\t\tdata = jQuery._data( dest );\n\n\t\tfor ( e in data.events ) {\n\t\t\tjQuery.removeEvent( dest, e, data.handle );\n\t\t}\n\n\t\t// Event data gets referenced instead of copied if the expando gets copied too\n\t\tdest.removeAttribute( jQuery.expando );\n\t}\n\n\t// IE blanks contents when cloning scripts, and tries to evaluate newly-set text\n\tif ( nodeName === \"script\" && dest.text !== src.text ) {\n\t\tdisableScript( dest ).text = src.text;\n\t\trestoreScript( dest );\n\n\t// IE6-10 improperly clones children of object elements using classid.\n\t// IE10 throws NoModificationAllowedError if parent is null, #12132.\n\t} else if ( nodeName === \"object\" ) {\n\t\tif ( dest.parentNode ) {\n\t\t\tdest.outerHTML = src.outerHTML;\n\t\t}\n\n\t\t// This path appears unavoidable for IE9. When cloning an object\n\t\t// element in IE9, the outerHTML strategy above is not sufficient.\n\t\t// If the src has innerHTML and the destination does not,\n\t\t// copy the src.innerHTML into the dest.innerHTML. #10324\n\t\tif ( jQuery.support.html5Clone && ( src.innerHTML && !jQuery.trim(dest.innerHTML) ) ) {\n\t\t\tdest.innerHTML = src.innerHTML;\n\t\t}\n\n\t} else if ( nodeName === \"input\" && manipulation_rcheckableType.test( src.type ) ) {\n\t\t// IE6-8 fails to persist the checked state of a cloned checkbox\n\t\t// or radio button. Worse, IE6-7 fail to give the cloned element\n\t\t// a checked appearance if the defaultChecked value isn't also set\n\n\t\tdest.defaultChecked = dest.checked = src.checked;\n\n\t\t// IE6-7 get confused and end up setting the value of a cloned\n\t\t// checkbox/radio button to an empty string instead of \"on\"\n\t\tif ( dest.value !== src.value ) {\n\t\t\tdest.value = src.value;\n\t\t}\n\n\t// IE6-8 fails to return the selected option to the default selected\n\t// state when cloning options\n\t} else if ( nodeName === \"option\" ) {\n\t\tdest.defaultSelected = dest.selected = src.defaultSelected;\n\n\t// IE6-8 fails to set the defaultValue to the correct value when\n\t// cloning other types of input fields\n\t} else if ( nodeName === \"input\" || nodeName === \"textarea\" ) {\n\t\tdest.defaultValue = src.defaultValue;\n\t}\n}\n\njQuery.each({\n\tappendTo: \"append\",\n\tprependTo: \"prepend\",\n\tinsertBefore: \"before\",\n\tinsertAfter: \"after\",\n\treplaceAll: \"replaceWith\"\n}, function( name, original ) {\n\tjQuery.fn[ name ] = function( selector ) {\n\t\tvar elems,\n\t\t\ti = 0,\n\t\t\tret = [],\n\t\t\tinsert = jQuery( selector ),\n\t\t\tlast = insert.length - 1;\n\n\t\tfor ( ; i <= last; i++ ) {\n\t\t\telems = i === last ? this : this.clone(true);\n\t\t\tjQuery( insert[i] )[ original ]( elems );\n\n\t\t\t// Modern browsers can apply jQuery collections as arrays, but oldIE needs a .get()\n\t\t\tcore_push.apply( ret, elems.get() );\n\t\t}\n\n\t\treturn this.pushStack( ret );\n\t};\n});\n\nfunction getAll( context, tag ) {\n\tvar elems, elem,\n\t\ti = 0,\n\t\tfound = typeof context.getElementsByTagName !== core_strundefined ? context.getElementsByTagName( tag || \"*\" ) :\n\t\t\ttypeof context.querySelectorAll !== core_strundefined ? context.querySelectorAll( tag || \"*\" ) :\n\t\t\tundefined;\n\n\tif ( !found ) {\n\t\tfor ( found = [], elems = context.childNodes || context; (elem = elems[i]) != null; i++ ) {\n\t\t\tif ( !tag || jQuery.nodeName( elem, tag ) ) {\n\t\t\t\tfound.push( elem );\n\t\t\t} else {\n\t\t\t\tjQuery.merge( found, getAll( elem, tag ) );\n\t\t\t}\n\t\t}\n\t}\n\n\treturn tag === undefined || tag && jQuery.nodeName( context, tag ) ?\n\t\tjQuery.merge( [ context ], found ) :\n\t\tfound;\n}\n\n// Used in buildFragment, fixes the defaultChecked property\nfunction fixDefaultChecked( elem ) {\n\tif ( manipulation_rcheckableType.test( elem.type ) ) {\n\t\telem.defaultChecked = elem.checked;\n\t}\n}\n\njQuery.extend({\n\tclone: function( elem, dataAndEvents, deepDataAndEvents ) {\n\t\tvar destElements, node, clone, i, srcElements,\n\t\t\tinPage = jQuery.contains( elem.ownerDocument, elem );\n\n\t\tif ( jQuery.support.html5Clone || jQuery.isXMLDoc(elem) || !rnoshimcache.test( \"<\" + elem.nodeName + \">\" ) ) {\n\t\t\tclone = elem.cloneNode( true );\n\n\t\t// IE<=8 does not properly clone detached, unknown element nodes\n\t\t} else {\n\t\t\tfragmentDiv.innerHTML = elem.outerHTML;\n\t\t\tfragmentDiv.removeChild( clone = fragmentDiv.firstChild );\n\t\t}\n\n\t\tif ( (!jQuery.support.noCloneEvent || !jQuery.support.noCloneChecked) &&\n\t\t\t\t(elem.nodeType === 1 || elem.nodeType === 11) && !jQuery.isXMLDoc(elem) ) {\n\n\t\t\t// We eschew Sizzle here for performance reasons: http://jsperf.com/getall-vs-sizzle/2\n\t\t\tdestElements = getAll( clone );\n\t\t\tsrcElements = getAll( elem );\n\n\t\t\t// Fix all IE cloning issues\n\t\t\tfor ( i = 0; (node = srcElements[i]) != null; ++i ) {\n\t\t\t\t// Ensure that the destination node is not null; Fixes #9587\n\t\t\t\tif ( destElements[i] ) {\n\t\t\t\t\tfixCloneNodeIssues( node, destElements[i] );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Copy the events from the original to the clone\n\t\tif ( dataAndEvents ) {\n\t\t\tif ( deepDataAndEvents ) {\n\t\t\t\tsrcElements = srcElements || getAll( elem );\n\t\t\t\tdestElements = destElements || getAll( clone );\n\n\t\t\t\tfor ( i = 0; (node = srcElements[i]) != null; i++ ) {\n\t\t\t\t\tcloneCopyEvent( node, destElements[i] );\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tcloneCopyEvent( elem, clone );\n\t\t\t}\n\t\t}\n\n\t\t// Preserve script evaluation history\n\t\tdestElements = getAll( clone, \"script\" );\n\t\tif ( destElements.length > 0 ) {\n\t\t\tsetGlobalEval( destElements, !inPage && getAll( elem, \"script\" ) );\n\t\t}\n\n\t\tdestElements = srcElements = node = null;\n\n\t\t// Return the cloned set\n\t\treturn clone;\n\t},\n\n\tbuildFragment: function( elems, context, scripts, selection ) {\n\t\tvar j, elem, contains,\n\t\t\ttmp, tag, tbody, wrap,\n\t\t\tl = elems.length,\n\n\t\t\t// Ensure a safe fragment\n\t\t\tsafe = createSafeFragment( context ),\n\n\t\t\tnodes = [],\n\t\t\ti = 0;\n\n\t\tfor ( ; i < l; i++ ) {\n\t\t\telem = elems[ i ];\n\n\t\t\tif ( elem || elem === 0 ) {\n\n\t\t\t\t// Add nodes directly\n\t\t\t\tif ( jQuery.type( elem ) === \"object\" ) {\n\t\t\t\t\tjQuery.merge( nodes, elem.nodeType ? [ elem ] : elem );\n\n\t\t\t\t// Convert non-html into a text node\n\t\t\t\t} else if ( !rhtml.test( elem ) ) {\n\t\t\t\t\tnodes.push( context.createTextNode( elem ) );\n\n\t\t\t\t// Convert html into DOM nodes\n\t\t\t\t} else {\n\t\t\t\t\ttmp = tmp || safe.appendChild( context.createElement(\"div\") );\n\n\t\t\t\t\t// Deserialize a standard representation\n\t\t\t\t\ttag = ( rtagName.exec( elem ) || [\"\", \"\"] )[1].toLowerCase();\n\t\t\t\t\twrap = wrapMap[ tag ] || wrapMap._default;\n\n\t\t\t\t\ttmp.innerHTML = wrap[1] + elem.replace( rxhtmlTag, \"<$1></$2>\" ) + wrap[2];\n\n\t\t\t\t\t// Descend through wrappers to the right content\n\t\t\t\t\tj = wrap[0];\n\t\t\t\t\twhile ( j-- ) {\n\t\t\t\t\t\ttmp = tmp.lastChild;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Manually add leading whitespace removed by IE\n\t\t\t\t\tif ( !jQuery.support.leadingWhitespace && rleadingWhitespace.test( elem ) ) {\n\t\t\t\t\t\tnodes.push( context.createTextNode( rleadingWhitespace.exec( elem )[0] ) );\n\t\t\t\t\t}\n\n\t\t\t\t\t// Remove IE's autoinserted <tbody> from table fragments\n\t\t\t\t\tif ( !jQuery.support.tbody ) {\n\n\t\t\t\t\t\t// String was a <table>, *may* have spurious <tbody>\n\t\t\t\t\t\telem = tag === \"table\" && !rtbody.test( elem ) ?\n\t\t\t\t\t\t\ttmp.firstChild :\n\n\t\t\t\t\t\t\t// String was a bare <thead> or <tfoot>\n\t\t\t\t\t\t\twrap[1] === \"<table>\" && !rtbody.test( elem ) ?\n\t\t\t\t\t\t\t\ttmp :\n\t\t\t\t\t\t\t\t0;\n\n\t\t\t\t\t\tj = elem && elem.childNodes.length;\n\t\t\t\t\t\twhile ( j-- ) {\n\t\t\t\t\t\t\tif ( jQuery.nodeName( (tbody = elem.childNodes[j]), \"tbody\" ) && !tbody.childNodes.length ) {\n\t\t\t\t\t\t\t\telem.removeChild( tbody );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tjQuery.merge( nodes, tmp.childNodes );\n\n\t\t\t\t\t// Fix #12392 for WebKit and IE > 9\n\t\t\t\t\ttmp.textContent = \"\";\n\n\t\t\t\t\t// Fix #12392 for oldIE\n\t\t\t\t\twhile ( tmp.firstChild ) {\n\t\t\t\t\t\ttmp.removeChild( tmp.firstChild );\n\t\t\t\t\t}\n\n\t\t\t\t\t// Remember the top-level container for proper cleanup\n\t\t\t\t\ttmp = safe.lastChild;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Fix #11356: Clear elements from fragment\n\t\tif ( tmp ) {\n\t\t\tsafe.removeChild( tmp );\n\t\t}\n\n\t\t// Reset defaultChecked for any radios and checkboxes\n\t\t// about to be appended to the DOM in IE 6/7 (#8060)\n\t\tif ( !jQuery.support.appendChecked ) {\n\t\t\tjQuery.grep( getAll( nodes, \"input\" ), fixDefaultChecked );\n\t\t}\n\n\t\ti = 0;\n\t\twhile ( (elem = nodes[ i++ ]) ) {\n\n\t\t\t// #4087 - If origin and destination elements are the same, and this is\n\t\t\t// that element, do not do anything\n\t\t\tif ( selection && jQuery.inArray( elem, selection ) !== -1 ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tcontains = jQuery.contains( elem.ownerDocument, elem );\n\n\t\t\t// Append to fragment\n\t\t\ttmp = getAll( safe.appendChild( elem ), \"script\" );\n\n\t\t\t// Preserve script evaluation history\n\t\t\tif ( contains ) {\n\t\t\t\tsetGlobalEval( tmp );\n\t\t\t}\n\n\t\t\t// Capture executables\n\t\t\tif ( scripts ) {\n\t\t\t\tj = 0;\n\t\t\t\twhile ( (elem = tmp[ j++ ]) ) {\n\t\t\t\t\tif ( rscriptType.test( elem.type || \"\" ) ) {\n\t\t\t\t\t\tscripts.push( elem );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\ttmp = null;\n\n\t\treturn safe;\n\t},\n\n\tcleanData: function( elems, /* internal */ acceptData ) {\n\t\tvar elem, type, id, data,\n\t\t\ti = 0,\n\t\t\tinternalKey = jQuery.expando,\n\t\t\tcache = jQuery.cache,\n\t\t\tdeleteExpando = jQuery.support.deleteExpando,\n\t\t\tspecial = jQuery.event.special;\n\n\t\tfor ( ; (elem = elems[i]) != null; i++ ) {\n\n\t\t\tif ( acceptData || jQuery.acceptData( elem ) ) {\n\n\t\t\t\tid = elem[ internalKey ];\n\t\t\t\tdata = id && cache[ id ];\n\n\t\t\t\tif ( data ) {\n\t\t\t\t\tif ( data.events ) {\n\t\t\t\t\t\tfor ( type in data.events ) {\n\t\t\t\t\t\t\tif ( special[ type ] ) {\n\t\t\t\t\t\t\t\tjQuery.event.remove( elem, type );\n\n\t\t\t\t\t\t\t// This is a shortcut to avoid jQuery.event.remove's overhead\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tjQuery.removeEvent( elem, type, data.handle );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Remove cache only if it was not already removed by jQuery.event.remove\n\t\t\t\t\tif ( cache[ id ] ) {\n\n\t\t\t\t\t\tdelete cache[ id ];\n\n\t\t\t\t\t\t// IE does not allow us to delete expando properties from nodes,\n\t\t\t\t\t\t// nor does it have a removeAttribute function on Document nodes;\n\t\t\t\t\t\t// we must handle all of these cases\n\t\t\t\t\t\tif ( deleteExpando ) {\n\t\t\t\t\t\t\tdelete elem[ internalKey ];\n\n\t\t\t\t\t\t} else if ( typeof elem.removeAttribute !== core_strundefined ) {\n\t\t\t\t\t\t\telem.removeAttribute( internalKey );\n\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\telem[ internalKey ] = null;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tcore_deletedIds.push( id );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n});\nvar iframe, getStyles, curCSS,\n\tralpha = /alpha\\([^)]*\\)/i,\n\tropacity = /opacity\\s*=\\s*([^)]*)/,\n\trposition = /^(top|right|bottom|left)$/,\n\t// swappable if display is none or starts with table except \"table\", \"table-cell\", or \"table-caption\"\n\t// see here for display values: https://developer.mozilla.org/en-US/docs/CSS/display\n\trdisplayswap = /^(none|table(?!-c[ea]).+)/,\n\trmargin = /^margin/,\n\trnumsplit = new RegExp( \"^(\" + core_pnum + \")(.*)$\", \"i\" ),\n\trnumnonpx = new RegExp( \"^(\" + core_pnum + \")(?!px)[a-z%]+$\", \"i\" ),\n\trrelNum = new RegExp( \"^([+-])=(\" + core_pnum + \")\", \"i\" ),\n\telemdisplay = { BODY: \"block\" },\n\n\tcssShow = { position: \"absolute\", visibility: \"hidden\", display: \"block\" },\n\tcssNormalTransform = {\n\t\tletterSpacing: 0,\n\t\tfontWeight: 400\n\t},\n\n\tcssExpand = [ \"Top\", \"Right\", \"Bottom\", \"Left\" ],\n\tcssPrefixes = [ \"Webkit\", \"O\", \"Moz\", \"ms\" ];\n\n// return a css property mapped to a potentially vendor prefixed property\nfunction vendorPropName( style, name ) {\n\n\t// shortcut for names that are not vendor prefixed\n\tif ( name in style ) {\n\t\treturn name;\n\t}\n\n\t// check for vendor prefixed names\n\tvar capName = name.charAt(0).toUpperCase() + name.slice(1),\n\t\torigName = name,\n\t\ti = cssPrefixes.length;\n\n\twhile ( i-- ) {\n\t\tname = cssPrefixes[ i ] + capName;\n\t\tif ( name in style ) {\n\t\t\treturn name;\n\t\t}\n\t}\n\n\treturn origName;\n}\n\nfunction isHidden( elem, el ) {\n\t// isHidden might be called from jQuery#filter function;\n\t// in that case, element will be second argument\n\telem = el || elem;\n\treturn jQuery.css( elem, \"display\" ) === \"none\" || !jQuery.contains( elem.ownerDocument, elem );\n}\n\nfunction showHide( elements, show ) {\n\tvar display, elem, hidden,\n\t\tvalues = [],\n\t\tindex = 0,\n\t\tlength = elements.length;\n\n\tfor ( ; index < length; index++ ) {\n\t\telem = elements[ index ];\n\t\tif ( !elem.style ) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tvalues[ index ] = jQuery._data( elem, \"olddisplay\" );\n\t\tdisplay = elem.style.display;\n\t\tif ( show ) {\n\t\t\t// Reset the inline display of this element to learn if it is\n\t\t\t// being hidden by cascaded rules or not\n\t\t\tif ( !values[ index ] && display === \"none\" ) {\n\t\t\t\telem.style.display = \"\";\n\t\t\t}\n\n\t\t\t// Set elements which have been overridden with display: none\n\t\t\t// in a stylesheet to whatever the default browser style is\n\t\t\t// for such an element\n\t\t\tif ( elem.style.display === \"\" && isHidden( elem ) ) {\n\t\t\t\tvalues[ index ] = jQuery._data( elem, \"olddisplay\", css_defaultDisplay(elem.nodeName) );\n\t\t\t}\n\t\t} else {\n\n\t\t\tif ( !values[ index ] ) {\n\t\t\t\thidden = isHidden( elem );\n\n\t\t\t\tif ( display && display !== \"none\" || !hidden ) {\n\t\t\t\t\tjQuery._data( elem, \"olddisplay\", hidden ? display : jQuery.css( elem, \"display\" ) );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Set the display of most of the elements in a second loop\n\t// to avoid the constant reflow\n\tfor ( index = 0; index < length; index++ ) {\n\t\telem = elements[ index ];\n\t\tif ( !elem.style ) {\n\t\t\tcontinue;\n\t\t}\n\t\tif ( !show || elem.style.display === \"none\" || elem.style.display === \"\" ) {\n\t\t\telem.style.display = show ? values[ index ] || \"\" : \"none\";\n\t\t}\n\t}\n\n\treturn elements;\n}\n\njQuery.fn.extend({\n\tcss: function( name, value ) {\n\t\treturn jQuery.access( this, function( elem, name, value ) {\n\t\t\tvar len, styles,\n\t\t\t\tmap = {},\n\t\t\t\ti = 0;\n\n\t\t\tif ( jQuery.isArray( name ) ) {\n\t\t\t\tstyles = getStyles( elem );\n\t\t\t\tlen = name.length;\n\n\t\t\t\tfor ( ; i < len; i++ ) {\n\t\t\t\t\tmap[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles );\n\t\t\t\t}\n\n\t\t\t\treturn map;\n\t\t\t}\n\n\t\t\treturn value !== undefined ?\n\t\t\t\tjQuery.style( elem, name, value ) :\n\t\t\t\tjQuery.css( elem, name );\n\t\t}, name, value, arguments.length > 1 );\n\t},\n\tshow: function() {\n\t\treturn showHide( this, true );\n\t},\n\thide: function() {\n\t\treturn showHide( this );\n\t},\n\ttoggle: function( state ) {\n\t\tvar bool = typeof state === \"boolean\";\n\n\t\treturn this.each(function() {\n\t\t\tif ( bool ? state : isHidden( this ) ) {\n\t\t\t\tjQuery( this ).show();\n\t\t\t} else {\n\t\t\t\tjQuery( this ).hide();\n\t\t\t}\n\t\t});\n\t}\n});\n\njQuery.extend({\n\t// Add in style property hooks for overriding the default\n\t// behavior of getting and setting a style property\n\tcssHooks: {\n\t\topacity: {\n\t\t\tget: function( elem, computed ) {\n\t\t\t\tif ( computed ) {\n\t\t\t\t\t// We should always get a number back from opacity\n\t\t\t\t\tvar ret = curCSS( elem, \"opacity\" );\n\t\t\t\t\treturn ret === \"\" ? \"1\" : ret;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\n\t// Exclude the following css properties to add px\n\tcssNumber: {\n\t\t\"columnCount\": true,\n\t\t\"fillOpacity\": true,\n\t\t\"fontWeight\": true,\n\t\t\"lineHeight\": true,\n\t\t\"opacity\": true,\n\t\t\"orphans\": true,\n\t\t\"widows\": true,\n\t\t\"zIndex\": true,\n\t\t\"zoom\": true\n\t},\n\n\t// Add in properties whose names you wish to fix before\n\t// setting or getting the value\n\tcssProps: {\n\t\t// normalize float css property\n\t\t\"float\": jQuery.support.cssFloat ? \"cssFloat\" : \"styleFloat\"\n\t},\n\n\t// Get and set the style property on a DOM Node\n\tstyle: function( elem, name, value, extra ) {\n\t\t// Don't set styles on text and comment nodes\n\t\tif ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Make sure that we're working with the right name\n\t\tvar ret, type, hooks,\n\t\t\torigName = jQuery.camelCase( name ),\n\t\t\tstyle = elem.style;\n\n\t\tname = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( style, origName ) );\n\n\t\t// gets hook for the prefixed version\n\t\t// followed by the unprefixed version\n\t\thooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];\n\n\t\t// Check if we're setting a value\n\t\tif ( value !== undefined ) {\n\t\t\ttype = typeof value;\n\n\t\t\t// convert relative number strings (+= or -=) to relative numbers. #7345\n\t\t\tif ( type === \"string\" && (ret = rrelNum.exec( value )) ) {\n\t\t\t\tvalue = ( ret[1] + 1 ) * ret[2] + parseFloat( jQuery.css( elem, name ) );\n\t\t\t\t// Fixes bug #9237\n\t\t\t\ttype = \"number\";\n\t\t\t}\n\n\t\t\t// Make sure that NaN and null values aren't set. See: #7116\n\t\t\tif ( value == null || type === \"number\" && isNaN( value ) ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// If a number was passed in, add 'px' to the (except for certain CSS properties)\n\t\t\tif ( type === \"number\" && !jQuery.cssNumber[ origName ] ) {\n\t\t\t\tvalue += \"px\";\n\t\t\t}\n\n\t\t\t// Fixes #8908, it can be done more correctly by specifing setters in cssHooks,\n\t\t\t// but it would mean to define eight (for every problematic property) identical functions\n\t\t\tif ( !jQuery.support.clearCloneStyle && value === \"\" && name.indexOf(\"background\") === 0 ) {\n\t\t\t\tstyle[ name ] = \"inherit\";\n\t\t\t}\n\n\t\t\t// If a hook was provided, use that value, otherwise just set the specified value\n\t\t\tif ( !hooks || !(\"set\" in hooks) || (value = hooks.set( elem, value, extra )) !== undefined ) {\n\n\t\t\t\t// Wrapped to prevent IE from throwing errors when 'invalid' values are provided\n\t\t\t\t// Fixes bug #5509\n\t\t\t\ttry {\n\t\t\t\t\tstyle[ name ] = value;\n\t\t\t\t} catch(e) {}\n\t\t\t}\n\n\t\t} else {\n\t\t\t// If a hook was provided get the non-computed value from there\n\t\t\tif ( hooks && \"get\" in hooks && (ret = hooks.get( elem, false, extra )) !== undefined ) {\n\t\t\t\treturn ret;\n\t\t\t}\n\n\t\t\t// Otherwise just get the value from the style object\n\t\t\treturn style[ name ];\n\t\t}\n\t},\n\n\tcss: function( elem, name, extra, styles ) {\n\t\tvar num, val, hooks,\n\t\t\torigName = jQuery.camelCase( name );\n\n\t\t// Make sure that we're working with the right name\n\t\tname = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( elem.style, origName ) );\n\n\t\t// gets hook for the prefixed version\n\t\t// followed by the unprefixed version\n\t\thooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];\n\n\t\t// If a hook was provided get the computed value from there\n\t\tif ( hooks && \"get\" in hooks ) {\n\t\t\tval = hooks.get( elem, true, extra );\n\t\t}\n\n\t\t// Otherwise, if a way to get the computed value exists, use that\n\t\tif ( val === undefined ) {\n\t\t\tval = curCSS( elem, name, styles );\n\t\t}\n\n\t\t//convert \"normal\" to computed value\n\t\tif ( val === \"normal\" && name in cssNormalTransform ) {\n\t\t\tval = cssNormalTransform[ name ];\n\t\t}\n\n\t\t// Return, converting to number if forced or a qualifier was provided and val looks numeric\n\t\tif ( extra === \"\" || extra ) {\n\t\t\tnum = parseFloat( val );\n\t\t\treturn extra === true || jQuery.isNumeric( num ) ? num || 0 : val;\n\t\t}\n\t\treturn val;\n\t},\n\n\t// A method for quickly swapping in/out CSS properties to get correct calculations\n\tswap: function( elem, options, callback, args ) {\n\t\tvar ret, name,\n\t\t\told = {};\n\n\t\t// Remember the old values, and insert the new ones\n\t\tfor ( name in options ) {\n\t\t\told[ name ] = elem.style[ name ];\n\t\t\telem.style[ name ] = options[ name ];\n\t\t}\n\n\t\tret = callback.apply( elem, args || [] );\n\n\t\t// Revert the old values\n\t\tfor ( name in options ) {\n\t\t\telem.style[ name ] = old[ name ];\n\t\t}\n\n\t\treturn ret;\n\t}\n});\n\n// NOTE: we've included the \"window\" in window.getComputedStyle\n// because jsdom on node.js will break without it.\nif ( window.getComputedStyle ) {\n\tgetStyles = function( elem ) {\n\t\treturn window.getComputedStyle( elem, null );\n\t};\n\n\tcurCSS = function( elem, name, _computed ) {\n\t\tvar width, minWidth, maxWidth,\n\t\t\tcomputed = _computed || getStyles( elem ),\n\n\t\t\t// getPropertyValue is only needed for .css('filter') in IE9, see #12537\n\t\t\tret = computed ? computed.getPropertyValue( name ) || computed[ name ] : undefined,\n\t\t\tstyle = elem.style;\n\n\t\tif ( computed ) {\n\n\t\t\tif ( ret === \"\" && !jQuery.contains( elem.ownerDocument, elem ) ) {\n\t\t\t\tret = jQuery.style( elem, name );\n\t\t\t}\n\n\t\t\t// A tribute to the \"awesome hack by Dean Edwards\"\n\t\t\t// Chrome < 17 and Safari 5.0 uses \"computed value\" instead of \"used value\" for margin-right\n\t\t\t// Safari 5.1.7 (at least) returns percentage for a larger set of values, but width seems to be reliably pixels\n\t\t\t// this is against the CSSOM draft spec: http://dev.w3.org/csswg/cssom/#resolved-values\n\t\t\tif ( rnumnonpx.test( ret ) && rmargin.test( name ) ) {\n\n\t\t\t\t// Remember the original values\n\t\t\t\twidth = style.width;\n\t\t\t\tminWidth = style.minWidth;\n\t\t\t\tmaxWidth = style.maxWidth;\n\n\t\t\t\t// Put in the new values to get a computed value out\n\t\t\t\tstyle.minWidth = style.maxWidth = style.width = ret;\n\t\t\t\tret = computed.width;\n\n\t\t\t\t// Revert the changed values\n\t\t\t\tstyle.width = width;\n\t\t\t\tstyle.minWidth = minWidth;\n\t\t\t\tstyle.maxWidth = maxWidth;\n\t\t\t}\n\t\t}\n\n\t\treturn ret;\n\t};\n} else if ( document.documentElement.currentStyle ) {\n\tgetStyles = function( elem ) {\n\t\treturn elem.currentStyle;\n\t};\n\n\tcurCSS = function( elem, name, _computed ) {\n\t\tvar left, rs, rsLeft,\n\t\t\tcomputed = _computed || getStyles( elem ),\n\t\t\tret = computed ? computed[ name ] : undefined,\n\t\t\tstyle = elem.style;\n\n\t\t// Avoid setting ret to empty string here\n\t\t// so we don't default to auto\n\t\tif ( ret == null && style && style[ name ] ) {\n\t\t\tret = style[ name ];\n\t\t}\n\n\t\t// From the awesome hack by Dean Edwards\n\t\t// http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291\n\n\t\t// If we're not dealing with a regular pixel number\n\t\t// but a number that has a weird ending, we need to convert it to pixels\n\t\t// but not position css attributes, as those are proportional to the parent element instead\n\t\t// and we can't measure the parent instead because it might trigger a \"stacking dolls\" problem\n\t\tif ( rnumnonpx.test( ret ) && !rposition.test( name ) ) {\n\n\t\t\t// Remember the original values\n\t\t\tleft = style.left;\n\t\t\trs = elem.runtimeStyle;\n\t\t\trsLeft = rs && rs.left;\n\n\t\t\t// Put in the new values to get a computed value out\n\t\t\tif ( rsLeft ) {\n\t\t\t\trs.left = elem.currentStyle.left;\n\t\t\t}\n\t\t\tstyle.left = name === \"fontSize\" ? \"1em\" : ret;\n\t\t\tret = style.pixelLeft + \"px\";\n\n\t\t\t// Revert the changed values\n\t\t\tstyle.left = left;\n\t\t\tif ( rsLeft ) {\n\t\t\t\trs.left = rsLeft;\n\t\t\t}\n\t\t}\n\n\t\treturn ret === \"\" ? \"auto\" : ret;\n\t};\n}\n\nfunction setPositiveNumber( elem, value, subtract ) {\n\tvar matches = rnumsplit.exec( value );\n\treturn matches ?\n\t\t// Guard against undefined \"subtract\", e.g., when used as in cssHooks\n\t\tMath.max( 0, matches[ 1 ] - ( subtract || 0 ) ) + ( matches[ 2 ] || \"px\" ) :\n\t\tvalue;\n}\n\nfunction augmentWidthOrHeight( elem, name, extra, isBorderBox, styles ) {\n\tvar i = extra === ( isBorderBox ? \"border\" : \"content\" ) ?\n\t\t// If we already have the right measurement, avoid augmentation\n\t\t4 :\n\t\t// Otherwise initialize for horizontal or vertical properties\n\t\tname === \"width\" ? 1 : 0,\n\n\t\tval = 0;\n\n\tfor ( ; i < 4; i += 2 ) {\n\t\t// both box models exclude margin, so add it if we want it\n\t\tif ( extra === \"margin\" ) {\n\t\t\tval += jQuery.css( elem, extra + cssExpand[ i ], true, styles );\n\t\t}\n\n\t\tif ( isBorderBox ) {\n\t\t\t// border-box includes padding, so remove it if we want content\n\t\t\tif ( extra === \"content\" ) {\n\t\t\t\tval -= jQuery.css( elem, \"padding\" + cssExpand[ i ], true, styles );\n\t\t\t}\n\n\t\t\t// at this point, extra isn't border nor margin, so remove border\n\t\t\tif ( extra !== \"margin\" ) {\n\t\t\t\tval -= jQuery.css( elem, \"border\" + cssExpand[ i ] + \"Width\", true, styles );\n\t\t\t}\n\t\t} else {\n\t\t\t// at this point, extra isn't content, so add padding\n\t\t\tval += jQuery.css( elem, \"padding\" + cssExpand[ i ], true, styles );\n\n\t\t\t// at this point, extra isn't content nor padding, so add border\n\t\t\tif ( extra !== \"padding\" ) {\n\t\t\t\tval += jQuery.css( elem, \"border\" + cssExpand[ i ] + \"Width\", true, styles );\n\t\t\t}\n\t\t}\n\t}\n\n\treturn val;\n}\n\nfunction getWidthOrHeight( elem, name, extra ) {\n\n\t// Start with offset property, which is equivalent to the border-box value\n\tvar valueIsBorderBox = true,\n\t\tval = name === \"width\" ? elem.offsetWidth : elem.offsetHeight,\n\t\tstyles = getStyles( elem ),\n\t\tisBorderBox = jQuery.support.boxSizing && jQuery.css( elem, \"boxSizing\", false, styles ) === \"border-box\";\n\n\t// some non-html elements return undefined for offsetWidth, so check for null/undefined\n\t// svg - https://bugzilla.mozilla.org/show_bug.cgi?id=649285\n\t// MathML - https://bugzilla.mozilla.org/show_bug.cgi?id=491668\n\tif ( val <= 0 || val == null ) {\n\t\t// Fall back to computed then uncomputed css if necessary\n\t\tval = curCSS( elem, name, styles );\n\t\tif ( val < 0 || val == null ) {\n\t\t\tval = elem.style[ name ];\n\t\t}\n\n\t\t// Computed unit is not pixels. Stop here and return.\n\t\tif ( rnumnonpx.test(val) ) {\n\t\t\treturn val;\n\t\t}\n\n\t\t// we need the check for style in case a browser which returns unreliable values\n\t\t// for getComputedStyle silently falls back to the reliable elem.style\n\t\tvalueIsBorderBox = isBorderBox && ( jQuery.support.boxSizingReliable || val === elem.style[ name ] );\n\n\t\t// Normalize \"\", auto, and prepare for extra\n\t\tval = parseFloat( val ) || 0;\n\t}\n\n\t// use the active box-sizing model to add/subtract irrelevant styles\n\treturn ( val +\n\t\taugmentWidthOrHeight(\n\t\t\telem,\n\t\t\tname,\n\t\t\textra || ( isBorderBox ? \"border\" : \"content\" ),\n\t\t\tvalueIsBorderBox,\n\t\t\tstyles\n\t\t)\n\t) + \"px\";\n}\n\n// Try to determine the default display value of an element\nfunction css_defaultDisplay( nodeName ) {\n\tvar doc = document,\n\t\tdisplay = elemdisplay[ nodeName ];\n\n\tif ( !display ) {\n\t\tdisplay = actualDisplay( nodeName, doc );\n\n\t\t// If the simple way fails, read from inside an iframe\n\t\tif ( display === \"none\" || !display ) {\n\t\t\t// Use the already-created iframe if possible\n\t\t\tiframe = ( iframe ||\n\t\t\t\tjQuery(\"<iframe frameborder='0' width='0' height='0'/>\")\n\t\t\t\t.css( \"cssText\", \"display:block !important\" )\n\t\t\t).appendTo( doc.documentElement );\n\n\t\t\t// Always write a new HTML skeleton so Webkit and Firefox don't choke on reuse\n\t\t\tdoc = ( iframe[0].contentWindow || iframe[0].contentDocument ).document;\n\t\t\tdoc.write(\"<!doctype html><html><body>\");\n\t\t\tdoc.close();\n\n\t\t\tdisplay = actualDisplay( nodeName, doc );\n\t\t\tiframe.detach();\n\t\t}\n\n\t\t// Store the correct default display\n\t\telemdisplay[ nodeName ] = display;\n\t}\n\n\treturn display;\n}\n\n// Called ONLY from within css_defaultDisplay\nfunction actualDisplay( name, doc ) {\n\tvar elem = jQuery( doc.createElement( name ) ).appendTo( doc.body ),\n\t\tdisplay = jQuery.css( elem[0], \"display\" );\n\telem.remove();\n\treturn display;\n}\n\njQuery.each([ \"height\", \"width\" ], function( i, name ) {\n\tjQuery.cssHooks[ name ] = {\n\t\tget: function( elem, computed, extra ) {\n\t\t\tif ( computed ) {\n\t\t\t\t// certain elements can have dimension info if we invisibly show them\n\t\t\t\t// however, it must have a current display style that would benefit from this\n\t\t\t\treturn elem.offsetWidth === 0 && rdisplayswap.test( jQuery.css( elem, \"display\" ) ) ?\n\t\t\t\t\tjQuery.swap( elem, cssShow, function() {\n\t\t\t\t\t\treturn getWidthOrHeight( elem, name, extra );\n\t\t\t\t\t}) :\n\t\t\t\t\tgetWidthOrHeight( elem, name, extra );\n\t\t\t}\n\t\t},\n\n\t\tset: function( elem, value, extra ) {\n\t\t\tvar styles = extra && getStyles( elem );\n\t\t\treturn setPositiveNumber( elem, value, extra ?\n\t\t\t\taugmentWidthOrHeight(\n\t\t\t\t\telem,\n\t\t\t\t\tname,\n\t\t\t\t\textra,\n\t\t\t\t\tjQuery.support.boxSizing && jQuery.css( elem, \"boxSizing\", false, styles ) === \"border-box\",\n\t\t\t\t\tstyles\n\t\t\t\t) : 0\n\t\t\t);\n\t\t}\n\t};\n});\n\nif ( !jQuery.support.opacity ) {\n\tjQuery.cssHooks.opacity = {\n\t\tget: function( elem, computed ) {\n\t\t\t// IE uses filters for opacity\n\t\t\treturn ropacity.test( (computed && elem.currentStyle ? elem.currentStyle.filter : elem.style.filter) || \"\" ) ?\n\t\t\t\t( 0.01 * parseFloat( RegExp.$1 ) ) + \"\" :\n\t\t\t\tcomputed ? \"1\" : \"\";\n\t\t},\n\n\t\tset: function( elem, value ) {\n\t\t\tvar style = elem.style,\n\t\t\t\tcurrentStyle = elem.currentStyle,\n\t\t\t\topacity = jQuery.isNumeric( value ) ? \"alpha(opacity=\" + value * 100 + \")\" : \"\",\n\t\t\t\tfilter = currentStyle && currentStyle.filter || style.filter || \"\";\n\n\t\t\t// IE has trouble with opacity if it does not have layout\n\t\t\t// Force it by setting the zoom level\n\t\t\tstyle.zoom = 1;\n\n\t\t\t// if setting opacity to 1, and no other filters exist - attempt to remove filter attribute #6652\n\t\t\t// if value === \"\", then remove inline opacity #12685\n\t\t\tif ( ( value >= 1 || value === \"\" ) &&\n\t\t\t\t\tjQuery.trim( filter.replace( ralpha, \"\" ) ) === \"\" &&\n\t\t\t\t\tstyle.removeAttribute ) {\n\n\t\t\t\t// Setting style.filter to null, \"\" & \" \" still leave \"filter:\" in the cssText\n\t\t\t\t// if \"filter:\" is present at all, clearType is disabled, we want to avoid this\n\t\t\t\t// style.removeAttribute is IE Only, but so apparently is this code path...\n\t\t\t\tstyle.removeAttribute( \"filter\" );\n\n\t\t\t\t// if there is no filter style applied in a css rule or unset inline opacity, we are done\n\t\t\t\tif ( value === \"\" || currentStyle && !currentStyle.filter ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// otherwise, set new filter values\n\t\t\tstyle.filter = ralpha.test( filter ) ?\n\t\t\t\tfilter.replace( ralpha, opacity ) :\n\t\t\t\tfilter + \" \" + opacity;\n\t\t}\n\t};\n}\n\n// These hooks cannot be added until DOM ready because the support test\n// for it is not run until after DOM ready\njQuery(function() {\n\tif ( !jQuery.support.reliableMarginRight ) {\n\t\tjQuery.cssHooks.marginRight = {\n\t\t\tget: function( elem, computed ) {\n\t\t\t\tif ( computed ) {\n\t\t\t\t\t// WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right\n\t\t\t\t\t// Work around by temporarily setting element display to inline-block\n\t\t\t\t\treturn jQuery.swap( elem, { \"display\": \"inline-block\" },\n\t\t\t\t\t\tcurCSS, [ elem, \"marginRight\" ] );\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t}\n\n\t// Webkit bug: https://bugs.webkit.org/show_bug.cgi?id=29084\n\t// getComputedStyle returns percent when specified for top/left/bottom/right\n\t// rather than make the css module depend on the offset module, we just check for it here\n\tif ( !jQuery.support.pixelPosition && jQuery.fn.position ) {\n\t\tjQuery.each( [ \"top\", \"left\" ], function( i, prop ) {\n\t\t\tjQuery.cssHooks[ prop ] = {\n\t\t\t\tget: function( elem, computed ) {\n\t\t\t\t\tif ( computed ) {\n\t\t\t\t\t\tcomputed = curCSS( elem, prop );\n\t\t\t\t\t\t// if curCSS returns percentage, fallback to offset\n\t\t\t\t\t\treturn rnumnonpx.test( computed ) ?\n\t\t\t\t\t\t\tjQuery( elem ).position()[ prop ] + \"px\" :\n\t\t\t\t\t\t\tcomputed;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t};\n\t\t});\n\t}\n\n});\n\nif ( jQuery.expr && jQuery.expr.filters ) {\n\tjQuery.expr.filters.hidden = function( elem ) {\n\t\t// Support: Opera <= 12.12\n\t\t// Opera reports offsetWidths and offsetHeights less than zero on some elements\n\t\treturn elem.offsetWidth <= 0 && elem.offsetHeight <= 0 ||\n\t\t\t(!jQuery.support.reliableHiddenOffsets && ((elem.style && elem.style.display) || jQuery.css( elem, \"display\" )) === \"none\");\n\t};\n\n\tjQuery.expr.filters.visible = function( elem ) {\n\t\treturn !jQuery.expr.filters.hidden( elem );\n\t};\n}\n\n// These hooks are used by animate to expand properties\njQuery.each({\n\tmargin: \"\",\n\tpadding: \"\",\n\tborder: \"Width\"\n}, function( prefix, suffix ) {\n\tjQuery.cssHooks[ prefix + suffix ] = {\n\t\texpand: function( value ) {\n\t\t\tvar i = 0,\n\t\t\t\texpanded = {},\n\n\t\t\t\t// assumes a single number if not a string\n\t\t\t\tparts = typeof value === \"string\" ? value.split(\" \") : [ value ];\n\n\t\t\tfor ( ; i < 4; i++ ) {\n\t\t\t\texpanded[ prefix + cssExpand[ i ] + suffix ] =\n\t\t\t\t\tparts[ i ] || parts[ i - 2 ] || parts[ 0 ];\n\t\t\t}\n\n\t\t\treturn expanded;\n\t\t}\n\t};\n\n\tif ( !rmargin.test( prefix ) ) {\n\t\tjQuery.cssHooks[ prefix + suffix ].set = setPositiveNumber;\n\t}\n});\nvar r20 = /%20/g,\n\trbracket = /\\[\\]$/,\n\trCRLF = /\\r?\\n/g,\n\trsubmitterTypes = /^(?:submit|button|image|reset|file)$/i,\n\trsubmittable = /^(?:input|select|textarea|keygen)/i;\n\njQuery.fn.extend({\n\tserialize: function() {\n\t\treturn jQuery.param( this.serializeArray() );\n\t},\n\tserializeArray: function() {\n\t\treturn this.map(function(){\n\t\t\t// Can add propHook for \"elements\" to filter or add form elements\n\t\t\tvar elements = jQuery.prop( this, \"elements\" );\n\t\t\treturn elements ? jQuery.makeArray( elements ) : this;\n\t\t})\n\t\t.filter(function(){\n\t\t\tvar type = this.type;\n\t\t\t// Use .is(\":disabled\") so that fieldset[disabled] works\n\t\t\treturn this.name && !jQuery( this ).is( \":disabled\" ) &&\n\t\t\t\trsubmittable.test( this.nodeName ) && !rsubmitterTypes.test( type ) &&\n\t\t\t\t( this.checked || !manipulation_rcheckableType.test( type ) );\n\t\t})\n\t\t.map(function( i, elem ){\n\t\t\tvar val = jQuery( this ).val();\n\n\t\t\treturn val == null ?\n\t\t\t\tnull :\n\t\t\t\tjQuery.isArray( val ) ?\n\t\t\t\t\tjQuery.map( val, function( val ){\n\t\t\t\t\t\treturn { name: elem.name, value: val.replace( rCRLF, \"\\r\\n\" ) };\n\t\t\t\t\t}) :\n\t\t\t\t\t{ name: elem.name, value: val.replace( rCRLF, \"\\r\\n\" ) };\n\t\t}).get();\n\t}\n});\n\n//Serialize an array of form elements or a set of\n//key/values into a query string\njQuery.param = function( a, traditional ) {\n\tvar prefix,\n\t\ts = [],\n\t\tadd = function( key, value ) {\n\t\t\t// If value is a function, invoke it and return its value\n\t\t\tvalue = jQuery.isFunction( value ) ? value() : ( value == null ? \"\" : value );\n\t\t\ts[ s.length ] = encodeURIComponent( key ) + \"=\" + encodeURIComponent( value );\n\t\t};\n\n\t// Set traditional to true for jQuery <= 1.3.2 behavior.\n\tif ( traditional === undefined ) {\n\t\ttraditional = jQuery.ajaxSettings && jQuery.ajaxSettings.traditional;\n\t}\n\n\t// If an array was passed in, assume that it is an array of form elements.\n\tif ( jQuery.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) {\n\t\t// Serialize the form elements\n\t\tjQuery.each( a, function() {\n\t\t\tadd( this.name, this.value );\n\t\t});\n\n\t} else {\n\t\t// If traditional, encode the \"old\" way (the way 1.3.2 or older\n\t\t// did it), otherwise encode params recursively.\n\t\tfor ( prefix in a ) {\n\t\t\tbuildParams( prefix, a[ prefix ], traditional, add );\n\t\t}\n\t}\n\n\t// Return the resulting serialization\n\treturn s.join( \"&\" ).replace( r20, \"+\" );\n};\n\nfunction buildParams( prefix, obj, traditional, add ) {\n\tvar name;\n\n\tif ( jQuery.isArray( obj ) ) {\n\t\t// Serialize array item.\n\t\tjQuery.each( obj, function( i, v ) {\n\t\t\tif ( traditional || rbracket.test( prefix ) ) {\n\t\t\t\t// Treat each array item as a scalar.\n\t\t\t\tadd( prefix, v );\n\n\t\t\t} else {\n\t\t\t\t// Item is non-scalar (array or object), encode its numeric index.\n\t\t\t\tbuildParams( prefix + \"[\" + ( typeof v === \"object\" ? i : \"\" ) + \"]\", v, traditional, add );\n\t\t\t}\n\t\t});\n\n\t} else if ( !traditional && jQuery.type( obj ) === \"object\" ) {\n\t\t// Serialize object item.\n\t\tfor ( name in obj ) {\n\t\t\tbuildParams( prefix + \"[\" + name + \"]\", obj[ name ], traditional, add );\n\t\t}\n\n\t} else {\n\t\t// Serialize scalar item.\n\t\tadd( prefix, obj );\n\t}\n}\njQuery.each( (\"blur focus focusin focusout load resize scroll unload click dblclick \" +\n\t\"mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave \" +\n\t\"change select submit keydown keypress keyup error contextmenu\").split(\" \"), function( i, name ) {\n\n\t// Handle event binding\n\tjQuery.fn[ name ] = function( data, fn ) {\n\t\treturn arguments.length > 0 ?\n\t\t\tthis.on( name, null, data, fn ) :\n\t\t\tthis.trigger( name );\n\t};\n});\n\njQuery.fn.hover = function( fnOver, fnOut ) {\n\treturn this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );\n};\nvar\n\t// Document location\n\tajaxLocParts,\n\tajaxLocation,\n\tajax_nonce = jQuery.now(),\n\n\tajax_rquery = /\\?/,\n\trhash = /#.*$/,\n\trts = /([?&])_=[^&]*/,\n\trheaders = /^(.*?):[ \\t]*([^\\r\\n]*)\\r?$/mg, // IE leaves an \\r character at EOL\n\t// #7653, #8125, #8152: local protocol detection\n\trlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/,\n\trnoContent = /^(?:GET|HEAD)$/,\n\trprotocol = /^\\/\\//,\n\trurl = /^([\\w.+-]+:)(?:\\/\\/([^\\/?#:]*)(?::(\\d+)|)|)/,\n\n\t// Keep a copy of the old load method\n\t_load = jQuery.fn.load,\n\n\t/* Prefilters\n\t * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example)\n\t * 2) These are called:\n\t *    - BEFORE asking for a transport\n\t *    - AFTER param serialization (s.data is a string if s.processData is true)\n\t * 3) key is the dataType\n\t * 4) the catchall symbol \"*\" can be used\n\t * 5) execution will start with transport dataType and THEN continue down to \"*\" if needed\n\t */\n\tprefilters = {},\n\n\t/* Transports bindings\n\t * 1) key is the dataType\n\t * 2) the catchall symbol \"*\" can be used\n\t * 3) selection will start with transport dataType and THEN go to \"*\" if needed\n\t */\n\ttransports = {},\n\n\t// Avoid comment-prolog char sequence (#10098); must appease lint and evade compression\n\tallTypes = \"*/\".concat(\"*\");\n\n// #8138, IE may throw an exception when accessing\n// a field from window.location if document.domain has been set\ntry {\n\tajaxLocation = location.href;\n} catch( e ) {\n\t// Use the href attribute of an A element\n\t// since IE will modify it given document.location\n\tajaxLocation = document.createElement( \"a\" );\n\tajaxLocation.href = \"\";\n\tajaxLocation = ajaxLocation.href;\n}\n\n// Segment location into parts\najaxLocParts = rurl.exec( ajaxLocation.toLowerCase() ) || [];\n\n// Base \"constructor\" for jQuery.ajaxPrefilter and jQuery.ajaxTransport\nfunction addToPrefiltersOrTransports( structure ) {\n\n\t// dataTypeExpression is optional and defaults to \"*\"\n\treturn function( dataTypeExpression, func ) {\n\n\t\tif ( typeof dataTypeExpression !== \"string\" ) {\n\t\t\tfunc = dataTypeExpression;\n\t\t\tdataTypeExpression = \"*\";\n\t\t}\n\n\t\tvar dataType,\n\t\t\ti = 0,\n\t\t\tdataTypes = dataTypeExpression.toLowerCase().match( core_rnotwhite ) || [];\n\n\t\tif ( jQuery.isFunction( func ) ) {\n\t\t\t// For each dataType in the dataTypeExpression\n\t\t\twhile ( (dataType = dataTypes[i++]) ) {\n\t\t\t\t// Prepend if requested\n\t\t\t\tif ( dataType[0] === \"+\" ) {\n\t\t\t\t\tdataType = dataType.slice( 1 ) || \"*\";\n\t\t\t\t\t(structure[ dataType ] = structure[ dataType ] || []).unshift( func );\n\n\t\t\t\t// Otherwise append\n\t\t\t\t} else {\n\t\t\t\t\t(structure[ dataType ] = structure[ dataType ] || []).push( func );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t};\n}\n\n// Base inspection function for prefilters and transports\nfunction inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR ) {\n\n\tvar inspected = {},\n\t\tseekingTransport = ( structure === transports );\n\n\tfunction inspect( dataType ) {\n\t\tvar selected;\n\t\tinspected[ dataType ] = true;\n\t\tjQuery.each( structure[ dataType ] || [], function( _, prefilterOrFactory ) {\n\t\t\tvar dataTypeOrTransport = prefilterOrFactory( options, originalOptions, jqXHR );\n\t\t\tif( typeof dataTypeOrTransport === \"string\" && !seekingTransport && !inspected[ dataTypeOrTransport ] ) {\n\t\t\t\toptions.dataTypes.unshift( dataTypeOrTransport );\n\t\t\t\tinspect( dataTypeOrTransport );\n\t\t\t\treturn false;\n\t\t\t} else if ( seekingTransport ) {\n\t\t\t\treturn !( selected = dataTypeOrTransport );\n\t\t\t}\n\t\t});\n\t\treturn selected;\n\t}\n\n\treturn inspect( options.dataTypes[ 0 ] ) || !inspected[ \"*\" ] && inspect( \"*\" );\n}\n\n// A special extend for ajax options\n// that takes \"flat\" options (not to be deep extended)\n// Fixes #9887\nfunction ajaxExtend( target, src ) {\n\tvar deep, key,\n\t\tflatOptions = jQuery.ajaxSettings.flatOptions || {};\n\n\tfor ( key in src ) {\n\t\tif ( src[ key ] !== undefined ) {\n\t\t\t( flatOptions[ key ] ? target : ( deep || (deep = {}) ) )[ key ] = src[ key ];\n\t\t}\n\t}\n\tif ( deep ) {\n\t\tjQuery.extend( true, target, deep );\n\t}\n\n\treturn target;\n}\n\njQuery.fn.load = function( url, params, callback ) {\n\tif ( typeof url !== \"string\" && _load ) {\n\t\treturn _load.apply( this, arguments );\n\t}\n\n\tvar selector, response, type,\n\t\tself = this,\n\t\toff = url.indexOf(\" \");\n\n\tif ( off >= 0 ) {\n\t\tselector = url.slice( off, url.length );\n\t\turl = url.slice( 0, off );\n\t}\n\n\t// If it's a function\n\tif ( jQuery.isFunction( params ) ) {\n\n\t\t// We assume that it's the callback\n\t\tcallback = params;\n\t\tparams = undefined;\n\n\t// Otherwise, build a param string\n\t} else if ( params && typeof params === \"object\" ) {\n\t\ttype = \"POST\";\n\t}\n\n\t// If we have elements to modify, make the request\n\tif ( self.length > 0 ) {\n\t\tjQuery.ajax({\n\t\t\turl: url,\n\n\t\t\t// if \"type\" variable is undefined, then \"GET\" method will be used\n\t\t\ttype: type,\n\t\t\tdataType: \"html\",\n\t\t\tdata: params\n\t\t}).done(function( responseText ) {\n\n\t\t\t// Save response for use in complete callback\n\t\t\tresponse = arguments;\n\n\t\t\tself.html( selector ?\n\n\t\t\t\t// If a selector was specified, locate the right elements in a dummy div\n\t\t\t\t// Exclude scripts to avoid IE 'Permission Denied' errors\n\t\t\t\tjQuery(\"<div>\").append( jQuery.parseHTML( responseText ) ).find( selector ) :\n\n\t\t\t\t// Otherwise use the full result\n\t\t\t\tresponseText );\n\n\t\t}).complete( callback && function( jqXHR, status ) {\n\t\t\tself.each( callback, response || [ jqXHR.responseText, status, jqXHR ] );\n\t\t});\n\t}\n\n\treturn this;\n};\n\n// Attach a bunch of functions for handling common AJAX events\njQuery.each( [ \"ajaxStart\", \"ajaxStop\", \"ajaxComplete\", \"ajaxError\", \"ajaxSuccess\", \"ajaxSend\" ], function( i, type ){\n\tjQuery.fn[ type ] = function( fn ){\n\t\treturn this.on( type, fn );\n\t};\n});\n\njQuery.each( [ \"get\", \"post\" ], function( i, method ) {\n\tjQuery[ method ] = function( url, data, callback, type ) {\n\t\t// shift arguments if data argument was omitted\n\t\tif ( jQuery.isFunction( data ) ) {\n\t\t\ttype = type || callback;\n\t\t\tcallback = data;\n\t\t\tdata = undefined;\n\t\t}\n\n\t\treturn jQuery.ajax({\n\t\t\turl: url,\n\t\t\ttype: method,\n\t\t\tdataType: type,\n\t\t\tdata: data,\n\t\t\tsuccess: callback\n\t\t});\n\t};\n});\n\njQuery.extend({\n\n\t// Counter for holding the number of active queries\n\tactive: 0,\n\n\t// Last-Modified header cache for next request\n\tlastModified: {},\n\tetag: {},\n\n\tajaxSettings: {\n\t\turl: ajaxLocation,\n\t\ttype: \"GET\",\n\t\tisLocal: rlocalProtocol.test( ajaxLocParts[ 1 ] ),\n\t\tglobal: true,\n\t\tprocessData: true,\n\t\tasync: true,\n\t\tcontentType: \"application/x-www-form-urlencoded; charset=UTF-8\",\n\t\t/*\n\t\ttimeout: 0,\n\t\tdata: null,\n\t\tdataType: null,\n\t\tusername: null,\n\t\tpassword: null,\n\t\tcache: null,\n\t\tthrows: false,\n\t\ttraditional: false,\n\t\theaders: {},\n\t\t*/\n\n\t\taccepts: {\n\t\t\t\"*\": allTypes,\n\t\t\ttext: \"text/plain\",\n\t\t\thtml: \"text/html\",\n\t\t\txml: \"application/xml, text/xml\",\n\t\t\tjson: \"application/json, text/javascript\"\n\t\t},\n\n\t\tcontents: {\n\t\t\txml: /xml/,\n\t\t\thtml: /html/,\n\t\t\tjson: /json/\n\t\t},\n\n\t\tresponseFields: {\n\t\t\txml: \"responseXML\",\n\t\t\ttext: \"responseText\"\n\t\t},\n\n\t\t// Data converters\n\t\t// Keys separate source (or catchall \"*\") and destination types with a single space\n\t\tconverters: {\n\n\t\t\t// Convert anything to text\n\t\t\t\"* text\": window.String,\n\n\t\t\t// Text to html (true = no transformation)\n\t\t\t\"text html\": true,\n\n\t\t\t// Evaluate text as a json expression\n\t\t\t\"text json\": jQuery.parseJSON,\n\n\t\t\t// Parse text as xml\n\t\t\t\"text xml\": jQuery.parseXML\n\t\t},\n\n\t\t// For options that shouldn't be deep extended:\n\t\t// you can add your own custom options here if\n\t\t// and when you create one that shouldn't be\n\t\t// deep extended (see ajaxExtend)\n\t\tflatOptions: {\n\t\t\turl: true,\n\t\t\tcontext: true\n\t\t}\n\t},\n\n\t// Creates a full fledged settings object into target\n\t// with both ajaxSettings and settings fields.\n\t// If target is omitted, writes into ajaxSettings.\n\tajaxSetup: function( target, settings ) {\n\t\treturn settings ?\n\n\t\t\t// Building a settings object\n\t\t\tajaxExtend( ajaxExtend( target, jQuery.ajaxSettings ), settings ) :\n\n\t\t\t// Extending ajaxSettings\n\t\t\tajaxExtend( jQuery.ajaxSettings, target );\n\t},\n\n\tajaxPrefilter: addToPrefiltersOrTransports( prefilters ),\n\tajaxTransport: addToPrefiltersOrTransports( transports ),\n\n\t// Main method\n\tajax: function( url, options ) {\n\n\t\t// If url is an object, simulate pre-1.5 signature\n\t\tif ( typeof url === \"object\" ) {\n\t\t\toptions = url;\n\t\t\turl = undefined;\n\t\t}\n\n\t\t// Force options to be an object\n\t\toptions = options || {};\n\n\t\tvar // Cross-domain detection vars\n\t\t\tparts,\n\t\t\t// Loop variable\n\t\t\ti,\n\t\t\t// URL without anti-cache param\n\t\t\tcacheURL,\n\t\t\t// Response headers as string\n\t\t\tresponseHeadersString,\n\t\t\t// timeout handle\n\t\t\ttimeoutTimer,\n\n\t\t\t// To know if global events are to be dispatched\n\t\t\tfireGlobals,\n\n\t\t\ttransport,\n\t\t\t// Response headers\n\t\t\tresponseHeaders,\n\t\t\t// Create the final options object\n\t\t\ts = jQuery.ajaxSetup( {}, options ),\n\t\t\t// Callbacks context\n\t\t\tcallbackContext = s.context || s,\n\t\t\t// Context for global events is callbackContext if it is a DOM node or jQuery collection\n\t\t\tglobalEventContext = s.context && ( callbackContext.nodeType || callbackContext.jquery ) ?\n\t\t\t\tjQuery( callbackContext ) :\n\t\t\t\tjQuery.event,\n\t\t\t// Deferreds\n\t\t\tdeferred = jQuery.Deferred(),\n\t\t\tcompleteDeferred = jQuery.Callbacks(\"once memory\"),\n\t\t\t// Status-dependent callbacks\n\t\t\tstatusCode = s.statusCode || {},\n\t\t\t// Headers (they are sent all at once)\n\t\t\trequestHeaders = {},\n\t\t\trequestHeadersNames = {},\n\t\t\t// The jqXHR state\n\t\t\tstate = 0,\n\t\t\t// Default abort message\n\t\t\tstrAbort = \"canceled\",\n\t\t\t// Fake xhr\n\t\t\tjqXHR = {\n\t\t\t\treadyState: 0,\n\n\t\t\t\t// Builds headers hashtable if needed\n\t\t\t\tgetResponseHeader: function( key ) {\n\t\t\t\t\tvar match;\n\t\t\t\t\tif ( state === 2 ) {\n\t\t\t\t\t\tif ( !responseHeaders ) {\n\t\t\t\t\t\t\tresponseHeaders = {};\n\t\t\t\t\t\t\twhile ( (match = rheaders.exec( responseHeadersString )) ) {\n\t\t\t\t\t\t\t\tresponseHeaders[ match[1].toLowerCase() ] = match[ 2 ];\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tmatch = responseHeaders[ key.toLowerCase() ];\n\t\t\t\t\t}\n\t\t\t\t\treturn match == null ? null : match;\n\t\t\t\t},\n\n\t\t\t\t// Raw string\n\t\t\t\tgetAllResponseHeaders: function() {\n\t\t\t\t\treturn state === 2 ? responseHeadersString : null;\n\t\t\t\t},\n\n\t\t\t\t// Caches the header\n\t\t\t\tsetRequestHeader: function( name, value ) {\n\t\t\t\t\tvar lname = name.toLowerCase();\n\t\t\t\t\tif ( !state ) {\n\t\t\t\t\t\tname = requestHeadersNames[ lname ] = requestHeadersNames[ lname ] || name;\n\t\t\t\t\t\trequestHeaders[ name ] = value;\n\t\t\t\t\t}\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\n\t\t\t\t// Overrides response content-type header\n\t\t\t\toverrideMimeType: function( type ) {\n\t\t\t\t\tif ( !state ) {\n\t\t\t\t\t\ts.mimeType = type;\n\t\t\t\t\t}\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\n\t\t\t\t// Status-dependent callbacks\n\t\t\t\tstatusCode: function( map ) {\n\t\t\t\t\tvar code;\n\t\t\t\t\tif ( map ) {\n\t\t\t\t\t\tif ( state < 2 ) {\n\t\t\t\t\t\t\tfor ( code in map ) {\n\t\t\t\t\t\t\t\t// Lazy-add the new callback in a way that preserves old ones\n\t\t\t\t\t\t\t\tstatusCode[ code ] = [ statusCode[ code ], map[ code ] ];\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t// Execute the appropriate callbacks\n\t\t\t\t\t\t\tjqXHR.always( map[ jqXHR.status ] );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\n\t\t\t\t// Cancel the request\n\t\t\t\tabort: function( statusText ) {\n\t\t\t\t\tvar finalText = statusText || strAbort;\n\t\t\t\t\tif ( transport ) {\n\t\t\t\t\t\ttransport.abort( finalText );\n\t\t\t\t\t}\n\t\t\t\t\tdone( 0, finalText );\n\t\t\t\t\treturn this;\n\t\t\t\t}\n\t\t\t};\n\n\t\t// Attach deferreds\n\t\tdeferred.promise( jqXHR ).complete = completeDeferred.add;\n\t\tjqXHR.success = jqXHR.done;\n\t\tjqXHR.error = jqXHR.fail;\n\n\t\t// Remove hash character (#7531: and string promotion)\n\t\t// Add protocol if not provided (#5866: IE7 issue with protocol-less urls)\n\t\t// Handle falsy url in the settings object (#10093: consistency with old signature)\n\t\t// We also use the url parameter if available\n\t\ts.url = ( ( url || s.url || ajaxLocation ) + \"\" ).replace( rhash, \"\" ).replace( rprotocol, ajaxLocParts[ 1 ] + \"//\" );\n\n\t\t// Alias method option to type as per ticket #12004\n\t\ts.type = options.method || options.type || s.method || s.type;\n\n\t\t// Extract dataTypes list\n\t\ts.dataTypes = jQuery.trim( s.dataType || \"*\" ).toLowerCase().match( core_rnotwhite ) || [\"\"];\n\n\t\t// A cross-domain request is in order when we have a protocol:host:port mismatch\n\t\tif ( s.crossDomain == null ) {\n\t\t\tparts = rurl.exec( s.url.toLowerCase() );\n\t\t\ts.crossDomain = !!( parts &&\n\t\t\t\t( parts[ 1 ] !== ajaxLocParts[ 1 ] || parts[ 2 ] !== ajaxLocParts[ 2 ] ||\n\t\t\t\t\t( parts[ 3 ] || ( parts[ 1 ] === \"http:\" ? 80 : 443 ) ) !=\n\t\t\t\t\t\t( ajaxLocParts[ 3 ] || ( ajaxLocParts[ 1 ] === \"http:\" ? 80 : 443 ) ) )\n\t\t\t);\n\t\t}\n\n\t\t// Convert data if not already a string\n\t\tif ( s.data && s.processData && typeof s.data !== \"string\" ) {\n\t\t\ts.data = jQuery.param( s.data, s.traditional );\n\t\t}\n\n\t\t// Apply prefilters\n\t\tinspectPrefiltersOrTransports( prefilters, s, options, jqXHR );\n\n\t\t// If request was aborted inside a prefilter, stop there\n\t\tif ( state === 2 ) {\n\t\t\treturn jqXHR;\n\t\t}\n\n\t\t// We can fire global events as of now if asked to\n\t\tfireGlobals = s.global;\n\n\t\t// Watch for a new set of requests\n\t\tif ( fireGlobals && jQuery.active++ === 0 ) {\n\t\t\tjQuery.event.trigger(\"ajaxStart\");\n\t\t}\n\n\t\t// Uppercase the type\n\t\ts.type = s.type.toUpperCase();\n\n\t\t// Determine if request has content\n\t\ts.hasContent = !rnoContent.test( s.type );\n\n\t\t// Save the URL in case we're toying with the If-Modified-Since\n\t\t// and/or If-None-Match header later on\n\t\tcacheURL = s.url;\n\n\t\t// More options handling for requests with no content\n\t\tif ( !s.hasContent ) {\n\n\t\t\t// If data is available, append data to url\n\t\t\tif ( s.data ) {\n\t\t\t\tcacheURL = ( s.url += ( ajax_rquery.test( cacheURL ) ? \"&\" : \"?\" ) + s.data );\n\t\t\t\t// #9682: remove data so that it's not used in an eventual retry\n\t\t\t\tdelete s.data;\n\t\t\t}\n\n\t\t\t// Add anti-cache in url if needed\n\t\t\tif ( s.cache === false ) {\n\t\t\t\ts.url = rts.test( cacheURL ) ?\n\n\t\t\t\t\t// If there is already a '_' parameter, set its value\n\t\t\t\t\tcacheURL.replace( rts, \"$1_=\" + ajax_nonce++ ) :\n\n\t\t\t\t\t// Otherwise add one to the end\n\t\t\t\t\tcacheURL + ( ajax_rquery.test( cacheURL ) ? \"&\" : \"?\" ) + \"_=\" + ajax_nonce++;\n\t\t\t}\n\t\t}\n\n\t\t// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.\n\t\tif ( s.ifModified ) {\n\t\t\tif ( jQuery.lastModified[ cacheURL ] ) {\n\t\t\t\tjqXHR.setRequestHeader( \"If-Modified-Since\", jQuery.lastModified[ cacheURL ] );\n\t\t\t}\n\t\t\tif ( jQuery.etag[ cacheURL ] ) {\n\t\t\t\tjqXHR.setRequestHeader( \"If-None-Match\", jQuery.etag[ cacheURL ] );\n\t\t\t}\n\t\t}\n\n\t\t// Set the correct header, if data is being sent\n\t\tif ( s.data && s.hasContent && s.contentType !== false || options.contentType ) {\n\t\t\tjqXHR.setRequestHeader( \"Content-Type\", s.contentType );\n\t\t}\n\n\t\t// Set the Accepts header for the server, depending on the dataType\n\t\tjqXHR.setRequestHeader(\n\t\t\t\"Accept\",\n\t\t\ts.dataTypes[ 0 ] && s.accepts[ s.dataTypes[0] ] ?\n\t\t\t\ts.accepts[ s.dataTypes[0] ] + ( s.dataTypes[ 0 ] !== \"*\" ? \", \" + allTypes + \"; q=0.01\" : \"\" ) :\n\t\t\t\ts.accepts[ \"*\" ]\n\t\t);\n\n\t\t// Check for headers option\n\t\tfor ( i in s.headers ) {\n\t\t\tjqXHR.setRequestHeader( i, s.headers[ i ] );\n\t\t}\n\n\t\t// Allow custom headers/mimetypes and early abort\n\t\tif ( s.beforeSend && ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || state === 2 ) ) {\n\t\t\t// Abort if not done already and return\n\t\t\treturn jqXHR.abort();\n\t\t}\n\n\t\t// aborting is no longer a cancellation\n\t\tstrAbort = \"abort\";\n\n\t\t// Install callbacks on deferreds\n\t\tfor ( i in { success: 1, error: 1, complete: 1 } ) {\n\t\t\tjqXHR[ i ]( s[ i ] );\n\t\t}\n\n\t\t// Get transport\n\t\ttransport = inspectPrefiltersOrTransports( transports, s, options, jqXHR );\n\n\t\t// If no transport, we auto-abort\n\t\tif ( !transport ) {\n\t\t\tdone( -1, \"No Transport\" );\n\t\t} else {\n\t\t\tjqXHR.readyState = 1;\n\n\t\t\t// Send global event\n\t\t\tif ( fireGlobals ) {\n\t\t\t\tglobalEventContext.trigger( \"ajaxSend\", [ jqXHR, s ] );\n\t\t\t}\n\t\t\t// Timeout\n\t\t\tif ( s.async && s.timeout > 0 ) {\n\t\t\t\ttimeoutTimer = setTimeout(function() {\n\t\t\t\t\tjqXHR.abort(\"timeout\");\n\t\t\t\t}, s.timeout );\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tstate = 1;\n\t\t\t\ttransport.send( requestHeaders, done );\n\t\t\t} catch ( e ) {\n\t\t\t\t// Propagate exception as error if not done\n\t\t\t\tif ( state < 2 ) {\n\t\t\t\t\tdone( -1, e );\n\t\t\t\t// Simply rethrow otherwise\n\t\t\t\t} else {\n\t\t\t\t\tthrow e;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Callback for when everything is done\n\t\tfunction done( status, nativeStatusText, responses, headers ) {\n\t\t\tvar isSuccess, success, error, response, modified,\n\t\t\t\tstatusText = nativeStatusText;\n\n\t\t\t// Called once\n\t\t\tif ( state === 2 ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// State is \"done\" now\n\t\t\tstate = 2;\n\n\t\t\t// Clear timeout if it exists\n\t\t\tif ( timeoutTimer ) {\n\t\t\t\tclearTimeout( timeoutTimer );\n\t\t\t}\n\n\t\t\t// Dereference transport for early garbage collection\n\t\t\t// (no matter how long the jqXHR object will be used)\n\t\t\ttransport = undefined;\n\n\t\t\t// Cache response headers\n\t\t\tresponseHeadersString = headers || \"\";\n\n\t\t\t// Set readyState\n\t\t\tjqXHR.readyState = status > 0 ? 4 : 0;\n\n\t\t\t// Get response data\n\t\t\tif ( responses ) {\n\t\t\t\tresponse = ajaxHandleResponses( s, jqXHR, responses );\n\t\t\t}\n\n\t\t\t// If successful, handle type chaining\n\t\t\tif ( status >= 200 && status < 300 || status === 304 ) {\n\n\t\t\t\t// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.\n\t\t\t\tif ( s.ifModified ) {\n\t\t\t\t\tmodified = jqXHR.getResponseHeader(\"Last-Modified\");\n\t\t\t\t\tif ( modified ) {\n\t\t\t\t\t\tjQuery.lastModified[ cacheURL ] = modified;\n\t\t\t\t\t}\n\t\t\t\t\tmodified = jqXHR.getResponseHeader(\"etag\");\n\t\t\t\t\tif ( modified ) {\n\t\t\t\t\t\tjQuery.etag[ cacheURL ] = modified;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// if no content\n\t\t\t\tif ( status === 204 ) {\n\t\t\t\t\tisSuccess = true;\n\t\t\t\t\tstatusText = \"nocontent\";\n\n\t\t\t\t// if not modified\n\t\t\t\t} else if ( status === 304 ) {\n\t\t\t\t\tisSuccess = true;\n\t\t\t\t\tstatusText = \"notmodified\";\n\n\t\t\t\t// If we have data, let's convert it\n\t\t\t\t} else {\n\t\t\t\t\tisSuccess = ajaxConvert( s, response );\n\t\t\t\t\tstatusText = isSuccess.state;\n\t\t\t\t\tsuccess = isSuccess.data;\n\t\t\t\t\terror = isSuccess.error;\n\t\t\t\t\tisSuccess = !error;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// We extract error from statusText\n\t\t\t\t// then normalize statusText and status for non-aborts\n\t\t\t\terror = statusText;\n\t\t\t\tif ( status || !statusText ) {\n\t\t\t\t\tstatusText = \"error\";\n\t\t\t\t\tif ( status < 0 ) {\n\t\t\t\t\t\tstatus = 0;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Set data for the fake xhr object\n\t\t\tjqXHR.status = status;\n\t\t\tjqXHR.statusText = ( nativeStatusText || statusText ) + \"\";\n\n\t\t\t// Success/Error\n\t\t\tif ( isSuccess ) {\n\t\t\t\tdeferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] );\n\t\t\t} else {\n\t\t\t\tdeferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] );\n\t\t\t}\n\n\t\t\t// Status-dependent callbacks\n\t\t\tjqXHR.statusCode( statusCode );\n\t\t\tstatusCode = undefined;\n\n\t\t\tif ( fireGlobals ) {\n\t\t\t\tglobalEventContext.trigger( isSuccess ? \"ajaxSuccess\" : \"ajaxError\",\n\t\t\t\t\t[ jqXHR, s, isSuccess ? success : error ] );\n\t\t\t}\n\n\t\t\t// Complete\n\t\t\tcompleteDeferred.fireWith( callbackContext, [ jqXHR, statusText ] );\n\n\t\t\tif ( fireGlobals ) {\n\t\t\t\tglobalEventContext.trigger( \"ajaxComplete\", [ jqXHR, s ] );\n\t\t\t\t// Handle the global AJAX counter\n\t\t\t\tif ( !( --jQuery.active ) ) {\n\t\t\t\t\tjQuery.event.trigger(\"ajaxStop\");\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn jqXHR;\n\t},\n\n\tgetScript: function( url, callback ) {\n\t\treturn jQuery.get( url, undefined, callback, \"script\" );\n\t},\n\n\tgetJSON: function( url, data, callback ) {\n\t\treturn jQuery.get( url, data, callback, \"json\" );\n\t}\n});\n\n/* Handles responses to an ajax request:\n * - sets all responseXXX fields accordingly\n * - finds the right dataType (mediates between content-type and expected dataType)\n * - returns the corresponding response\n */\nfunction ajaxHandleResponses( s, jqXHR, responses ) {\n\tvar firstDataType, ct, finalDataType, type,\n\t\tcontents = s.contents,\n\t\tdataTypes = s.dataTypes,\n\t\tresponseFields = s.responseFields;\n\n\t// Fill responseXXX fields\n\tfor ( type in responseFields ) {\n\t\tif ( type in responses ) {\n\t\t\tjqXHR[ responseFields[type] ] = responses[ type ];\n\t\t}\n\t}\n\n\t// Remove auto dataType and get content-type in the process\n\twhile( dataTypes[ 0 ] === \"*\" ) {\n\t\tdataTypes.shift();\n\t\tif ( ct === undefined ) {\n\t\t\tct = s.mimeType || jqXHR.getResponseHeader(\"Content-Type\");\n\t\t}\n\t}\n\n\t// Check if we're dealing with a known content-type\n\tif ( ct ) {\n\t\tfor ( type in contents ) {\n\t\t\tif ( contents[ type ] && contents[ type ].test( ct ) ) {\n\t\t\t\tdataTypes.unshift( type );\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\t// Check to see if we have a response for the expected dataType\n\tif ( dataTypes[ 0 ] in responses ) {\n\t\tfinalDataType = dataTypes[ 0 ];\n\t} else {\n\t\t// Try convertible dataTypes\n\t\tfor ( type in responses ) {\n\t\t\tif ( !dataTypes[ 0 ] || s.converters[ type + \" \" + dataTypes[0] ] ) {\n\t\t\t\tfinalDataType = type;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif ( !firstDataType ) {\n\t\t\t\tfirstDataType = type;\n\t\t\t}\n\t\t}\n\t\t// Or just use first one\n\t\tfinalDataType = finalDataType || firstDataType;\n\t}\n\n\t// If we found a dataType\n\t// We add the dataType to the list if needed\n\t// and return the corresponding response\n\tif ( finalDataType ) {\n\t\tif ( finalDataType !== dataTypes[ 0 ] ) {\n\t\t\tdataTypes.unshift( finalDataType );\n\t\t}\n\t\treturn responses[ finalDataType ];\n\t}\n}\n\n// Chain conversions given the request and the original response\nfunction ajaxConvert( s, response ) {\n\tvar conv2, current, conv, tmp,\n\t\tconverters = {},\n\t\ti = 0,\n\t\t// Work with a copy of dataTypes in case we need to modify it for conversion\n\t\tdataTypes = s.dataTypes.slice(),\n\t\tprev = dataTypes[ 0 ];\n\n\t// Apply the dataFilter if provided\n\tif ( s.dataFilter ) {\n\t\tresponse = s.dataFilter( response, s.dataType );\n\t}\n\n\t// Create converters map with lowercased keys\n\tif ( dataTypes[ 1 ] ) {\n\t\tfor ( conv in s.converters ) {\n\t\t\tconverters[ conv.toLowerCase() ] = s.converters[ conv ];\n\t\t}\n\t}\n\n\t// Convert to each sequential dataType, tolerating list modification\n\tfor ( ; (current = dataTypes[++i]); ) {\n\n\t\t// There's only work to do if current dataType is non-auto\n\t\tif ( current !== \"*\" ) {\n\n\t\t\t// Convert response if prev dataType is non-auto and differs from current\n\t\t\tif ( prev !== \"*\" && prev !== current ) {\n\n\t\t\t\t// Seek a direct converter\n\t\t\t\tconv = converters[ prev + \" \" + current ] || converters[ \"* \" + current ];\n\n\t\t\t\t// If none found, seek a pair\n\t\t\t\tif ( !conv ) {\n\t\t\t\t\tfor ( conv2 in converters ) {\n\n\t\t\t\t\t\t// If conv2 outputs current\n\t\t\t\t\t\ttmp = conv2.split(\" \");\n\t\t\t\t\t\tif ( tmp[ 1 ] === current ) {\n\n\t\t\t\t\t\t\t// If prev can be converted to accepted input\n\t\t\t\t\t\t\tconv = converters[ prev + \" \" + tmp[ 0 ] ] ||\n\t\t\t\t\t\t\t\tconverters[ \"* \" + tmp[ 0 ] ];\n\t\t\t\t\t\t\tif ( conv ) {\n\t\t\t\t\t\t\t\t// Condense equivalence converters\n\t\t\t\t\t\t\t\tif ( conv === true ) {\n\t\t\t\t\t\t\t\t\tconv = converters[ conv2 ];\n\n\t\t\t\t\t\t\t\t// Otherwise, insert the intermediate dataType\n\t\t\t\t\t\t\t\t} else if ( converters[ conv2 ] !== true ) {\n\t\t\t\t\t\t\t\t\tcurrent = tmp[ 0 ];\n\t\t\t\t\t\t\t\t\tdataTypes.splice( i--, 0, current );\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Apply converter (if not an equivalence)\n\t\t\t\tif ( conv !== true ) {\n\n\t\t\t\t\t// Unless errors are allowed to bubble, catch and return them\n\t\t\t\t\tif ( conv && s[\"throws\"] ) {\n\t\t\t\t\t\tresponse = conv( response );\n\t\t\t\t\t} else {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tresponse = conv( response );\n\t\t\t\t\t\t} catch ( e ) {\n\t\t\t\t\t\t\treturn { state: \"parsererror\", error: conv ? e : \"No conversion from \" + prev + \" to \" + current };\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Update prev for next iteration\n\t\t\tprev = current;\n\t\t}\n\t}\n\n\treturn { state: \"success\", data: response };\n}\n// Install script dataType\njQuery.ajaxSetup({\n\taccepts: {\n\t\tscript: \"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript\"\n\t},\n\tcontents: {\n\t\tscript: /(?:java|ecma)script/\n\t},\n\tconverters: {\n\t\t\"text script\": function( text ) {\n\t\t\tjQuery.globalEval( text );\n\t\t\treturn text;\n\t\t}\n\t}\n});\n\n// Handle cache's special case and global\njQuery.ajaxPrefilter( \"script\", function( s ) {\n\tif ( s.cache === undefined ) {\n\t\ts.cache = false;\n\t}\n\tif ( s.crossDomain ) {\n\t\ts.type = \"GET\";\n\t\ts.global = false;\n\t}\n});\n\n// Bind script tag hack transport\njQuery.ajaxTransport( \"script\", function(s) {\n\n\t// This transport only deals with cross domain requests\n\tif ( s.crossDomain ) {\n\n\t\tvar script,\n\t\t\thead = document.head || jQuery(\"head\")[0] || document.documentElement;\n\n\t\treturn {\n\n\t\t\tsend: function( _, callback ) {\n\n\t\t\t\tscript = document.createElement(\"script\");\n\n\t\t\t\tscript.async = true;\n\n\t\t\t\tif ( s.scriptCharset ) {\n\t\t\t\t\tscript.charset = s.scriptCharset;\n\t\t\t\t}\n\n\t\t\t\tscript.src = s.url;\n\n\t\t\t\t// Attach handlers for all browsers\n\t\t\t\tscript.onload = script.onreadystatechange = function( _, isAbort ) {\n\n\t\t\t\t\tif ( isAbort || !script.readyState || /loaded|complete/.test( script.readyState ) ) {\n\n\t\t\t\t\t\t// Handle memory leak in IE\n\t\t\t\t\t\tscript.onload = script.onreadystatechange = null;\n\n\t\t\t\t\t\t// Remove the script\n\t\t\t\t\t\tif ( script.parentNode ) {\n\t\t\t\t\t\t\tscript.parentNode.removeChild( script );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Dereference the script\n\t\t\t\t\t\tscript = null;\n\n\t\t\t\t\t\t// Callback if not abort\n\t\t\t\t\t\tif ( !isAbort ) {\n\t\t\t\t\t\t\tcallback( 200, \"success\" );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t};\n\n\t\t\t\t// Circumvent IE6 bugs with base elements (#2709 and #4378) by prepending\n\t\t\t\t// Use native DOM manipulation to avoid our domManip AJAX trickery\n\t\t\t\thead.insertBefore( script, head.firstChild );\n\t\t\t},\n\n\t\t\tabort: function() {\n\t\t\t\tif ( script ) {\n\t\t\t\t\tscript.onload( undefined, true );\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t}\n});\nvar oldCallbacks = [],\n\trjsonp = /(=)\\?(?=&|$)|\\?\\?/;\n\n// Default jsonp settings\njQuery.ajaxSetup({\n\tjsonp: \"callback\",\n\tjsonpCallback: function() {\n\t\tvar callback = oldCallbacks.pop() || ( jQuery.expando + \"_\" + ( ajax_nonce++ ) );\n\t\tthis[ callback ] = true;\n\t\treturn callback;\n\t}\n});\n\n// Detect, normalize options and install callbacks for jsonp requests\njQuery.ajaxPrefilter( \"json jsonp\", function( s, originalSettings, jqXHR ) {\n\n\tvar callbackName, overwritten, responseContainer,\n\t\tjsonProp = s.jsonp !== false && ( rjsonp.test( s.url ) ?\n\t\t\t\"url\" :\n\t\t\ttypeof s.data === \"string\" && !( s.contentType || \"\" ).indexOf(\"application/x-www-form-urlencoded\") && rjsonp.test( s.data ) && \"data\"\n\t\t);\n\n\t// Handle iff the expected data type is \"jsonp\" or we have a parameter to set\n\tif ( jsonProp || s.dataTypes[ 0 ] === \"jsonp\" ) {\n\n\t\t// Get callback name, remembering preexisting value associated with it\n\t\tcallbackName = s.jsonpCallback = jQuery.isFunction( s.jsonpCallback ) ?\n\t\t\ts.jsonpCallback() :\n\t\t\ts.jsonpCallback;\n\n\t\t// Insert callback into url or form data\n\t\tif ( jsonProp ) {\n\t\t\ts[ jsonProp ] = s[ jsonProp ].replace( rjsonp, \"$1\" + callbackName );\n\t\t} else if ( s.jsonp !== false ) {\n\t\t\ts.url += ( ajax_rquery.test( s.url ) ? \"&\" : \"?\" ) + s.jsonp + \"=\" + callbackName;\n\t\t}\n\n\t\t// Use data converter to retrieve json after script execution\n\t\ts.converters[\"script json\"] = function() {\n\t\t\tif ( !responseContainer ) {\n\t\t\t\tjQuery.error( callbackName + \" was not called\" );\n\t\t\t}\n\t\t\treturn responseContainer[ 0 ];\n\t\t};\n\n\t\t// force json dataType\n\t\ts.dataTypes[ 0 ] = \"json\";\n\n\t\t// Install callback\n\t\toverwritten = window[ callbackName ];\n\t\twindow[ callbackName ] = function() {\n\t\t\tresponseContainer = arguments;\n\t\t};\n\n\t\t// Clean-up function (fires after converters)\n\t\tjqXHR.always(function() {\n\t\t\t// Restore preexisting value\n\t\t\twindow[ callbackName ] = overwritten;\n\n\t\t\t// Save back as free\n\t\t\tif ( s[ callbackName ] ) {\n\t\t\t\t// make sure that re-using the options doesn't screw things around\n\t\t\t\ts.jsonpCallback = originalSettings.jsonpCallback;\n\n\t\t\t\t// save the callback name for future use\n\t\t\t\toldCallbacks.push( callbackName );\n\t\t\t}\n\n\t\t\t// Call if it was a function and we have a response\n\t\t\tif ( responseContainer && jQuery.isFunction( overwritten ) ) {\n\t\t\t\toverwritten( responseContainer[ 0 ] );\n\t\t\t}\n\n\t\t\tresponseContainer = overwritten = undefined;\n\t\t});\n\n\t\t// Delegate to script\n\t\treturn \"script\";\n\t}\n});\nvar xhrCallbacks, xhrSupported,\n\txhrId = 0,\n\t// #5280: Internet Explorer will keep connections alive if we don't abort on unload\n\txhrOnUnloadAbort = window.ActiveXObject && function() {\n\t\t// Abort all pending requests\n\t\tvar key;\n\t\tfor ( key in xhrCallbacks ) {\n\t\t\txhrCallbacks[ key ]( undefined, true );\n\t\t}\n\t};\n\n// Functions to create xhrs\nfunction createStandardXHR() {\n\ttry {\n\t\treturn new window.XMLHttpRequest();\n\t} catch( e ) {}\n}\n\nfunction createActiveXHR() {\n\ttry {\n\t\treturn new window.ActiveXObject(\"Microsoft.XMLHTTP\");\n\t} catch( e ) {}\n}\n\n// Create the request object\n// (This is still attached to ajaxSettings for backward compatibility)\njQuery.ajaxSettings.xhr = window.ActiveXObject ?\n\t/* Microsoft failed to properly\n\t * implement the XMLHttpRequest in IE7 (can't request local files),\n\t * so we use the ActiveXObject when it is available\n\t * Additionally XMLHttpRequest can be disabled in IE7/IE8 so\n\t * we need a fallback.\n\t */\n\tfunction() {\n\t\treturn !this.isLocal && createStandardXHR() || createActiveXHR();\n\t} :\n\t// For all other browsers, use the standard XMLHttpRequest object\n\tcreateStandardXHR;\n\n// Determine support properties\nxhrSupported = jQuery.ajaxSettings.xhr();\njQuery.support.cors = !!xhrSupported && ( \"withCredentials\" in xhrSupported );\nxhrSupported = jQuery.support.ajax = !!xhrSupported;\n\n// Create transport if the browser can provide an xhr\nif ( xhrSupported ) {\n\n\tjQuery.ajaxTransport(function( s ) {\n\t\t// Cross domain only allowed if supported through XMLHttpRequest\n\t\tif ( !s.crossDomain || jQuery.support.cors ) {\n\n\t\t\tvar callback;\n\n\t\t\treturn {\n\t\t\t\tsend: function( headers, complete ) {\n\n\t\t\t\t\t// Get a new xhr\n\t\t\t\t\tvar handle, i,\n\t\t\t\t\t\txhr = s.xhr();\n\n\t\t\t\t\t// Open the socket\n\t\t\t\t\t// Passing null username, generates a login popup on Opera (#2865)\n\t\t\t\t\tif ( s.username ) {\n\t\t\t\t\t\txhr.open( s.type, s.url, s.async, s.username, s.password );\n\t\t\t\t\t} else {\n\t\t\t\t\t\txhr.open( s.type, s.url, s.async );\n\t\t\t\t\t}\n\n\t\t\t\t\t// Apply custom fields if provided\n\t\t\t\t\tif ( s.xhrFields ) {\n\t\t\t\t\t\tfor ( i in s.xhrFields ) {\n\t\t\t\t\t\t\txhr[ i ] = s.xhrFields[ i ];\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Override mime type if needed\n\t\t\t\t\tif ( s.mimeType && xhr.overrideMimeType ) {\n\t\t\t\t\t\txhr.overrideMimeType( s.mimeType );\n\t\t\t\t\t}\n\n\t\t\t\t\t// X-Requested-With header\n\t\t\t\t\t// For cross-domain requests, seeing as conditions for a preflight are\n\t\t\t\t\t// akin to a jigsaw puzzle, we simply never set it to be sure.\n\t\t\t\t\t// (it can always be set on a per-request basis or even using ajaxSetup)\n\t\t\t\t\t// For same-domain requests, won't change header if already provided.\n\t\t\t\t\tif ( !s.crossDomain && !headers[\"X-Requested-With\"] ) {\n\t\t\t\t\t\theaders[\"X-Requested-With\"] = \"XMLHttpRequest\";\n\t\t\t\t\t}\n\n\t\t\t\t\t// Need an extra try/catch for cross domain requests in Firefox 3\n\t\t\t\t\ttry {\n\t\t\t\t\t\tfor ( i in headers ) {\n\t\t\t\t\t\t\txhr.setRequestHeader( i, headers[ i ] );\n\t\t\t\t\t\t}\n\t\t\t\t\t} catch( err ) {}\n\n\t\t\t\t\t// Do send the request\n\t\t\t\t\t// This may raise an exception which is actually\n\t\t\t\t\t// handled in jQuery.ajax (so no try/catch here)\n\t\t\t\t\txhr.send( ( s.hasContent && s.data ) || null );\n\n\t\t\t\t\t// Listener\n\t\t\t\t\tcallback = function( _, isAbort ) {\n\t\t\t\t\t\tvar status, responseHeaders, statusText, responses;\n\n\t\t\t\t\t\t// Firefox throws exceptions when accessing properties\n\t\t\t\t\t\t// of an xhr when a network error occurred\n\t\t\t\t\t\t// http://helpful.knobs-dials.com/index.php/Component_returned_failure_code:_0x80040111_(NS_ERROR_NOT_AVAILABLE)\n\t\t\t\t\t\ttry {\n\n\t\t\t\t\t\t\t// Was never called and is aborted or complete\n\t\t\t\t\t\t\tif ( callback && ( isAbort || xhr.readyState === 4 ) ) {\n\n\t\t\t\t\t\t\t\t// Only called once\n\t\t\t\t\t\t\t\tcallback = undefined;\n\n\t\t\t\t\t\t\t\t// Do not keep as active anymore\n\t\t\t\t\t\t\t\tif ( handle ) {\n\t\t\t\t\t\t\t\t\txhr.onreadystatechange = jQuery.noop;\n\t\t\t\t\t\t\t\t\tif ( xhrOnUnloadAbort ) {\n\t\t\t\t\t\t\t\t\t\tdelete xhrCallbacks[ handle ];\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t// If it's an abort\n\t\t\t\t\t\t\t\tif ( isAbort ) {\n\t\t\t\t\t\t\t\t\t// Abort it manually if needed\n\t\t\t\t\t\t\t\t\tif ( xhr.readyState !== 4 ) {\n\t\t\t\t\t\t\t\t\t\txhr.abort();\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tresponses = {};\n\t\t\t\t\t\t\t\t\tstatus = xhr.status;\n\t\t\t\t\t\t\t\t\tresponseHeaders = xhr.getAllResponseHeaders();\n\n\t\t\t\t\t\t\t\t\t// When requesting binary data, IE6-9 will throw an exception\n\t\t\t\t\t\t\t\t\t// on any attempt to access responseText (#11426)\n\t\t\t\t\t\t\t\t\tif ( typeof xhr.responseText === \"string\" ) {\n\t\t\t\t\t\t\t\t\t\tresponses.text = xhr.responseText;\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t// Firefox throws an exception when accessing\n\t\t\t\t\t\t\t\t\t// statusText for faulty cross-domain requests\n\t\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\t\tstatusText = xhr.statusText;\n\t\t\t\t\t\t\t\t\t} catch( e ) {\n\t\t\t\t\t\t\t\t\t\t// We normalize with Webkit giving an empty statusText\n\t\t\t\t\t\t\t\t\t\tstatusText = \"\";\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t// Filter status for non standard behaviors\n\n\t\t\t\t\t\t\t\t\t// If the request is local and we have data: assume a success\n\t\t\t\t\t\t\t\t\t// (success with no data won't get notified, that's the best we\n\t\t\t\t\t\t\t\t\t// can do given current implementations)\n\t\t\t\t\t\t\t\t\tif ( !status && s.isLocal && !s.crossDomain ) {\n\t\t\t\t\t\t\t\t\t\tstatus = responses.text ? 200 : 404;\n\t\t\t\t\t\t\t\t\t// IE - #1450: sometimes returns 1223 when it should be 204\n\t\t\t\t\t\t\t\t\t} else if ( status === 1223 ) {\n\t\t\t\t\t\t\t\t\t\tstatus = 204;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} catch( firefoxAccessException ) {\n\t\t\t\t\t\t\tif ( !isAbort ) {\n\t\t\t\t\t\t\t\tcomplete( -1, firefoxAccessException );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Call complete if needed\n\t\t\t\t\t\tif ( responses ) {\n\t\t\t\t\t\t\tcomplete( status, statusText, responses, responseHeaders );\n\t\t\t\t\t\t}\n\t\t\t\t\t};\n\n\t\t\t\t\tif ( !s.async ) {\n\t\t\t\t\t\t// if we're in sync mode we fire the callback\n\t\t\t\t\t\tcallback();\n\t\t\t\t\t} else if ( xhr.readyState === 4 ) {\n\t\t\t\t\t\t// (IE6 & IE7) if it's in cache and has been\n\t\t\t\t\t\t// retrieved directly we need to fire the callback\n\t\t\t\t\t\tsetTimeout( callback );\n\t\t\t\t\t} else {\n\t\t\t\t\t\thandle = ++xhrId;\n\t\t\t\t\t\tif ( xhrOnUnloadAbort ) {\n\t\t\t\t\t\t\t// Create the active xhrs callbacks list if needed\n\t\t\t\t\t\t\t// and attach the unload handler\n\t\t\t\t\t\t\tif ( !xhrCallbacks ) {\n\t\t\t\t\t\t\t\txhrCallbacks = {};\n\t\t\t\t\t\t\t\tjQuery( window ).unload( xhrOnUnloadAbort );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t// Add to list of active xhrs callbacks\n\t\t\t\t\t\t\txhrCallbacks[ handle ] = callback;\n\t\t\t\t\t\t}\n\t\t\t\t\t\txhr.onreadystatechange = callback;\n\t\t\t\t\t}\n\t\t\t\t},\n\n\t\t\t\tabort: function() {\n\t\t\t\t\tif ( callback ) {\n\t\t\t\t\t\tcallback( undefined, true );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t};\n\t\t}\n\t});\n}\nvar fxNow, timerId,\n\trfxtypes = /^(?:toggle|show|hide)$/,\n\trfxnum = new RegExp( \"^(?:([+-])=|)(\" + core_pnum + \")([a-z%]*)$\", \"i\" ),\n\trrun = /queueHooks$/,\n\tanimationPrefilters = [ defaultPrefilter ],\n\ttweeners = {\n\t\t\"*\": [function( prop, value ) {\n\t\t\tvar end, unit,\n\t\t\t\ttween = this.createTween( prop, value ),\n\t\t\t\tparts = rfxnum.exec( value ),\n\t\t\t\ttarget = tween.cur(),\n\t\t\t\tstart = +target || 0,\n\t\t\t\tscale = 1,\n\t\t\t\tmaxIterations = 20;\n\n\t\t\tif ( parts ) {\n\t\t\t\tend = +parts[2];\n\t\t\t\tunit = parts[3] || ( jQuery.cssNumber[ prop ] ? \"\" : \"px\" );\n\n\t\t\t\t// We need to compute starting value\n\t\t\t\tif ( unit !== \"px\" && start ) {\n\t\t\t\t\t// Iteratively approximate from a nonzero starting point\n\t\t\t\t\t// Prefer the current property, because this process will be trivial if it uses the same units\n\t\t\t\t\t// Fallback to end or a simple constant\n\t\t\t\t\tstart = jQuery.css( tween.elem, prop, true ) || end || 1;\n\n\t\t\t\t\tdo {\n\t\t\t\t\t\t// If previous iteration zeroed out, double until we get *something*\n\t\t\t\t\t\t// Use a string for doubling factor so we don't accidentally see scale as unchanged below\n\t\t\t\t\t\tscale = scale || \".5\";\n\n\t\t\t\t\t\t// Adjust and apply\n\t\t\t\t\t\tstart = start / scale;\n\t\t\t\t\t\tjQuery.style( tween.elem, prop, start + unit );\n\n\t\t\t\t\t// Update scale, tolerating zero or NaN from tween.cur()\n\t\t\t\t\t// And breaking the loop if scale is unchanged or perfect, or if we've just had enough\n\t\t\t\t\t} while ( scale !== (scale = tween.cur() / target) && scale !== 1 && --maxIterations );\n\t\t\t\t}\n\n\t\t\t\ttween.unit = unit;\n\t\t\t\ttween.start = start;\n\t\t\t\t// If a +=/-= token was provided, we're doing a relative animation\n\t\t\t\ttween.end = parts[1] ? start + ( parts[1] + 1 ) * end : end;\n\t\t\t}\n\t\t\treturn tween;\n\t\t}]\n\t};\n\n// Animations created synchronously will run synchronously\nfunction createFxNow() {\n\tsetTimeout(function() {\n\t\tfxNow = undefined;\n\t});\n\treturn ( fxNow = jQuery.now() );\n}\n\nfunction createTweens( animation, props ) {\n\tjQuery.each( props, function( prop, value ) {\n\t\tvar collection = ( tweeners[ prop ] || [] ).concat( tweeners[ \"*\" ] ),\n\t\t\tindex = 0,\n\t\t\tlength = collection.length;\n\t\tfor ( ; index < length; index++ ) {\n\t\t\tif ( collection[ index ].call( animation, prop, value ) ) {\n\n\t\t\t\t// we're done with this property\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t});\n}\n\nfunction Animation( elem, properties, options ) {\n\tvar result,\n\t\tstopped,\n\t\tindex = 0,\n\t\tlength = animationPrefilters.length,\n\t\tdeferred = jQuery.Deferred().always( function() {\n\t\t\t// don't match elem in the :animated selector\n\t\t\tdelete tick.elem;\n\t\t}),\n\t\ttick = function() {\n\t\t\tif ( stopped ) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tvar currentTime = fxNow || createFxNow(),\n\t\t\t\tremaining = Math.max( 0, animation.startTime + animation.duration - currentTime ),\n\t\t\t\t// archaic crash bug won't allow us to use 1 - ( 0.5 || 0 ) (#12497)\n\t\t\t\ttemp = remaining / animation.duration || 0,\n\t\t\t\tpercent = 1 - temp,\n\t\t\t\tindex = 0,\n\t\t\t\tlength = animation.tweens.length;\n\n\t\t\tfor ( ; index < length ; index++ ) {\n\t\t\t\tanimation.tweens[ index ].run( percent );\n\t\t\t}\n\n\t\t\tdeferred.notifyWith( elem, [ animation, percent, remaining ]);\n\n\t\t\tif ( percent < 1 && length ) {\n\t\t\t\treturn remaining;\n\t\t\t} else {\n\t\t\t\tdeferred.resolveWith( elem, [ animation ] );\n\t\t\t\treturn false;\n\t\t\t}\n\t\t},\n\t\tanimation = deferred.promise({\n\t\t\telem: elem,\n\t\t\tprops: jQuery.extend( {}, properties ),\n\t\t\topts: jQuery.extend( true, { specialEasing: {} }, options ),\n\t\t\toriginalProperties: properties,\n\t\t\toriginalOptions: options,\n\t\t\tstartTime: fxNow || createFxNow(),\n\t\t\tduration: options.duration,\n\t\t\ttweens: [],\n\t\t\tcreateTween: function( prop, end ) {\n\t\t\t\tvar tween = jQuery.Tween( elem, animation.opts, prop, end,\n\t\t\t\t\t\tanimation.opts.specialEasing[ prop ] || animation.opts.easing );\n\t\t\t\tanimation.tweens.push( tween );\n\t\t\t\treturn tween;\n\t\t\t},\n\t\t\tstop: function( gotoEnd ) {\n\t\t\t\tvar index = 0,\n\t\t\t\t\t// if we are going to the end, we want to run all the tweens\n\t\t\t\t\t// otherwise we skip this part\n\t\t\t\t\tlength = gotoEnd ? animation.tweens.length : 0;\n\t\t\t\tif ( stopped ) {\n\t\t\t\t\treturn this;\n\t\t\t\t}\n\t\t\t\tstopped = true;\n\t\t\t\tfor ( ; index < length ; index++ ) {\n\t\t\t\t\tanimation.tweens[ index ].run( 1 );\n\t\t\t\t}\n\n\t\t\t\t// resolve when we played the last frame\n\t\t\t\t// otherwise, reject\n\t\t\t\tif ( gotoEnd ) {\n\t\t\t\t\tdeferred.resolveWith( elem, [ animation, gotoEnd ] );\n\t\t\t\t} else {\n\t\t\t\t\tdeferred.rejectWith( elem, [ animation, gotoEnd ] );\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t}\n\t\t}),\n\t\tprops = animation.props;\n\n\tpropFilter( props, animation.opts.specialEasing );\n\n\tfor ( ; index < length ; index++ ) {\n\t\tresult = animationPrefilters[ index ].call( animation, elem, props, animation.opts );\n\t\tif ( result ) {\n\t\t\treturn result;\n\t\t}\n\t}\n\n\tcreateTweens( animation, props );\n\n\tif ( jQuery.isFunction( animation.opts.start ) ) {\n\t\tanimation.opts.start.call( elem, animation );\n\t}\n\n\tjQuery.fx.timer(\n\t\tjQuery.extend( tick, {\n\t\t\telem: elem,\n\t\t\tanim: animation,\n\t\t\tqueue: animation.opts.queue\n\t\t})\n\t);\n\n\t// attach callbacks from options\n\treturn animation.progress( animation.opts.progress )\n\t\t.done( animation.opts.done, animation.opts.complete )\n\t\t.fail( animation.opts.fail )\n\t\t.always( animation.opts.always );\n}\n\nfunction propFilter( props, specialEasing ) {\n\tvar value, name, index, easing, hooks;\n\n\t// camelCase, specialEasing and expand cssHook pass\n\tfor ( index in props ) {\n\t\tname = jQuery.camelCase( index );\n\t\teasing = specialEasing[ name ];\n\t\tvalue = props[ index ];\n\t\tif ( jQuery.isArray( value ) ) {\n\t\t\teasing = value[ 1 ];\n\t\t\tvalue = props[ index ] = value[ 0 ];\n\t\t}\n\n\t\tif ( index !== name ) {\n\t\t\tprops[ name ] = value;\n\t\t\tdelete props[ index ];\n\t\t}\n\n\t\thooks = jQuery.cssHooks[ name ];\n\t\tif ( hooks && \"expand\" in hooks ) {\n\t\t\tvalue = hooks.expand( value );\n\t\t\tdelete props[ name ];\n\n\t\t\t// not quite $.extend, this wont overwrite keys already present.\n\t\t\t// also - reusing 'index' from above because we have the correct \"name\"\n\t\t\tfor ( index in value ) {\n\t\t\t\tif ( !( index in props ) ) {\n\t\t\t\t\tprops[ index ] = value[ index ];\n\t\t\t\t\tspecialEasing[ index ] = easing;\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tspecialEasing[ name ] = easing;\n\t\t}\n\t}\n}\n\njQuery.Animation = jQuery.extend( Animation, {\n\n\ttweener: function( props, callback ) {\n\t\tif ( jQuery.isFunction( props ) ) {\n\t\t\tcallback = props;\n\t\t\tprops = [ \"*\" ];\n\t\t} else {\n\t\t\tprops = props.split(\" \");\n\t\t}\n\n\t\tvar prop,\n\t\t\tindex = 0,\n\t\t\tlength = props.length;\n\n\t\tfor ( ; index < length ; index++ ) {\n\t\t\tprop = props[ index ];\n\t\t\ttweeners[ prop ] = tweeners[ prop ] || [];\n\t\t\ttweeners[ prop ].unshift( callback );\n\t\t}\n\t},\n\n\tprefilter: function( callback, prepend ) {\n\t\tif ( prepend ) {\n\t\t\tanimationPrefilters.unshift( callback );\n\t\t} else {\n\t\t\tanimationPrefilters.push( callback );\n\t\t}\n\t}\n});\n\nfunction defaultPrefilter( elem, props, opts ) {\n\t/*jshint validthis:true */\n\tvar prop, index, length,\n\t\tvalue, dataShow, toggle,\n\t\ttween, hooks, oldfire,\n\t\tanim = this,\n\t\tstyle = elem.style,\n\t\torig = {},\n\t\thandled = [],\n\t\thidden = elem.nodeType && isHidden( elem );\n\n\t// handle queue: false promises\n\tif ( !opts.queue ) {\n\t\thooks = jQuery._queueHooks( elem, \"fx\" );\n\t\tif ( hooks.unqueued == null ) {\n\t\t\thooks.unqueued = 0;\n\t\t\toldfire = hooks.empty.fire;\n\t\t\thooks.empty.fire = function() {\n\t\t\t\tif ( !hooks.unqueued ) {\n\t\t\t\t\toldfire();\n\t\t\t\t}\n\t\t\t};\n\t\t}\n\t\thooks.unqueued++;\n\n\t\tanim.always(function() {\n\t\t\t// doing this makes sure that the complete handler will be called\n\t\t\t// before this completes\n\t\t\tanim.always(function() {\n\t\t\t\thooks.unqueued--;\n\t\t\t\tif ( !jQuery.queue( elem, \"fx\" ).length ) {\n\t\t\t\t\thooks.empty.fire();\n\t\t\t\t}\n\t\t\t});\n\t\t});\n\t}\n\n\t// height/width overflow pass\n\tif ( elem.nodeType === 1 && ( \"height\" in props || \"width\" in props ) ) {\n\t\t// Make sure that nothing sneaks out\n\t\t// Record all 3 overflow attributes because IE does not\n\t\t// change the overflow attribute when overflowX and\n\t\t// overflowY are set to the same value\n\t\topts.overflow = [ style.overflow, style.overflowX, style.overflowY ];\n\n\t\t// Set display property to inline-block for height/width\n\t\t// animations on inline elements that are having width/height animated\n\t\tif ( jQuery.css( elem, \"display\" ) === \"inline\" &&\n\t\t\t\tjQuery.css( elem, \"float\" ) === \"none\" ) {\n\n\t\t\t// inline-level elements accept inline-block;\n\t\t\t// block-level elements need to be inline with layout\n\t\t\tif ( !jQuery.support.inlineBlockNeedsLayout || css_defaultDisplay( elem.nodeName ) === \"inline\" ) {\n\t\t\t\tstyle.display = \"inline-block\";\n\n\t\t\t} else {\n\t\t\t\tstyle.zoom = 1;\n\t\t\t}\n\t\t}\n\t}\n\n\tif ( opts.overflow ) {\n\t\tstyle.overflow = \"hidden\";\n\t\tif ( !jQuery.support.shrinkWrapBlocks ) {\n\t\t\tanim.always(function() {\n\t\t\t\tstyle.overflow = opts.overflow[ 0 ];\n\t\t\t\tstyle.overflowX = opts.overflow[ 1 ];\n\t\t\t\tstyle.overflowY = opts.overflow[ 2 ];\n\t\t\t});\n\t\t}\n\t}\n\n\n\t// show/hide pass\n\tfor ( index in props ) {\n\t\tvalue = props[ index ];\n\t\tif ( rfxtypes.exec( value ) ) {\n\t\t\tdelete props[ index ];\n\t\t\ttoggle = toggle || value === \"toggle\";\n\t\t\tif ( value === ( hidden ? \"hide\" : \"show\" ) ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\thandled.push( index );\n\t\t}\n\t}\n\n\tlength = handled.length;\n\tif ( length ) {\n\t\tdataShow = jQuery._data( elem, \"fxshow\" ) || jQuery._data( elem, \"fxshow\", {} );\n\t\tif ( \"hidden\" in dataShow ) {\n\t\t\thidden = dataShow.hidden;\n\t\t}\n\n\t\t// store state if its toggle - enables .stop().toggle() to \"reverse\"\n\t\tif ( toggle ) {\n\t\t\tdataShow.hidden = !hidden;\n\t\t}\n\t\tif ( hidden ) {\n\t\t\tjQuery( elem ).show();\n\t\t} else {\n\t\t\tanim.done(function() {\n\t\t\t\tjQuery( elem ).hide();\n\t\t\t});\n\t\t}\n\t\tanim.done(function() {\n\t\t\tvar prop;\n\t\t\tjQuery._removeData( elem, \"fxshow\" );\n\t\t\tfor ( prop in orig ) {\n\t\t\t\tjQuery.style( elem, prop, orig[ prop ] );\n\t\t\t}\n\t\t});\n\t\tfor ( index = 0 ; index < length ; index++ ) {\n\t\t\tprop = handled[ index ];\n\t\t\ttween = anim.createTween( prop, hidden ? dataShow[ prop ] : 0 );\n\t\t\torig[ prop ] = dataShow[ prop ] || jQuery.style( elem, prop );\n\n\t\t\tif ( !( prop in dataShow ) ) {\n\t\t\t\tdataShow[ prop ] = tween.start;\n\t\t\t\tif ( hidden ) {\n\t\t\t\t\ttween.end = tween.start;\n\t\t\t\t\ttween.start = prop === \"width\" || prop === \"height\" ? 1 : 0;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunction Tween( elem, options, prop, end, easing ) {\n\treturn new Tween.prototype.init( elem, options, prop, end, easing );\n}\njQuery.Tween = Tween;\n\nTween.prototype = {\n\tconstructor: Tween,\n\tinit: function( elem, options, prop, end, easing, unit ) {\n\t\tthis.elem = elem;\n\t\tthis.prop = prop;\n\t\tthis.easing = easing || \"swing\";\n\t\tthis.options = options;\n\t\tthis.start = this.now = this.cur();\n\t\tthis.end = end;\n\t\tthis.unit = unit || ( jQuery.cssNumber[ prop ] ? \"\" : \"px\" );\n\t},\n\tcur: function() {\n\t\tvar hooks = Tween.propHooks[ this.prop ];\n\n\t\treturn hooks && hooks.get ?\n\t\t\thooks.get( this ) :\n\t\t\tTween.propHooks._default.get( this );\n\t},\n\trun: function( percent ) {\n\t\tvar eased,\n\t\t\thooks = Tween.propHooks[ this.prop ];\n\n\t\tif ( this.options.duration ) {\n\t\t\tthis.pos = eased = jQuery.easing[ this.easing ](\n\t\t\t\tpercent, this.options.duration * percent, 0, 1, this.options.duration\n\t\t\t);\n\t\t} else {\n\t\t\tthis.pos = eased = percent;\n\t\t}\n\t\tthis.now = ( this.end - this.start ) * eased + this.start;\n\n\t\tif ( this.options.step ) {\n\t\t\tthis.options.step.call( this.elem, this.now, this );\n\t\t}\n\n\t\tif ( hooks && hooks.set ) {\n\t\t\thooks.set( this );\n\t\t} else {\n\t\t\tTween.propHooks._default.set( this );\n\t\t}\n\t\treturn this;\n\t}\n};\n\nTween.prototype.init.prototype = Tween.prototype;\n\nTween.propHooks = {\n\t_default: {\n\t\tget: function( tween ) {\n\t\t\tvar result;\n\n\t\t\tif ( tween.elem[ tween.prop ] != null &&\n\t\t\t\t(!tween.elem.style || tween.elem.style[ tween.prop ] == null) ) {\n\t\t\t\treturn tween.elem[ tween.prop ];\n\t\t\t}\n\n\t\t\t// passing an empty string as a 3rd parameter to .css will automatically\n\t\t\t// attempt a parseFloat and fallback to a string if the parse fails\n\t\t\t// so, simple values such as \"10px\" are parsed to Float.\n\t\t\t// complex values such as \"rotate(1rad)\" are returned as is.\n\t\t\tresult = jQuery.css( tween.elem, tween.prop, \"\" );\n\t\t\t// Empty strings, null, undefined and \"auto\" are converted to 0.\n\t\t\treturn !result || result === \"auto\" ? 0 : result;\n\t\t},\n\t\tset: function( tween ) {\n\t\t\t// use step hook for back compat - use cssHook if its there - use .style if its\n\t\t\t// available and use plain properties where available\n\t\t\tif ( jQuery.fx.step[ tween.prop ] ) {\n\t\t\t\tjQuery.fx.step[ tween.prop ]( tween );\n\t\t\t} else if ( tween.elem.style && ( tween.elem.style[ jQuery.cssProps[ tween.prop ] ] != null || jQuery.cssHooks[ tween.prop ] ) ) {\n\t\t\t\tjQuery.style( tween.elem, tween.prop, tween.now + tween.unit );\n\t\t\t} else {\n\t\t\t\ttween.elem[ tween.prop ] = tween.now;\n\t\t\t}\n\t\t}\n\t}\n};\n\n// Remove in 2.0 - this supports IE8's panic based approach\n// to setting things on disconnected nodes\n\nTween.propHooks.scrollTop = Tween.propHooks.scrollLeft = {\n\tset: function( tween ) {\n\t\tif ( tween.elem.nodeType && tween.elem.parentNode ) {\n\t\t\ttween.elem[ tween.prop ] = tween.now;\n\t\t}\n\t}\n};\n\njQuery.each([ \"toggle\", \"show\", \"hide\" ], function( i, name ) {\n\tvar cssFn = jQuery.fn[ name ];\n\tjQuery.fn[ name ] = function( speed, easing, callback ) {\n\t\treturn speed == null || typeof speed === \"boolean\" ?\n\t\t\tcssFn.apply( this, arguments ) :\n\t\t\tthis.animate( genFx( name, true ), speed, easing, callback );\n\t};\n});\n\njQuery.fn.extend({\n\tfadeTo: function( speed, to, easing, callback ) {\n\n\t\t// show any hidden elements after setting opacity to 0\n\t\treturn this.filter( isHidden ).css( \"opacity\", 0 ).show()\n\n\t\t\t// animate to the value specified\n\t\t\t.end().animate({ opacity: to }, speed, easing, callback );\n\t},\n\tanimate: function( prop, speed, easing, callback ) {\n\t\tvar empty = jQuery.isEmptyObject( prop ),\n\t\t\toptall = jQuery.speed( speed, easing, callback ),\n\t\t\tdoAnimation = function() {\n\t\t\t\t// Operate on a copy of prop so per-property easing won't be lost\n\t\t\t\tvar anim = Animation( this, jQuery.extend( {}, prop ), optall );\n\t\t\t\tdoAnimation.finish = function() {\n\t\t\t\t\tanim.stop( true );\n\t\t\t\t};\n\t\t\t\t// Empty animations, or finishing resolves immediately\n\t\t\t\tif ( empty || jQuery._data( this, \"finish\" ) ) {\n\t\t\t\t\tanim.stop( true );\n\t\t\t\t}\n\t\t\t};\n\t\t\tdoAnimation.finish = doAnimation;\n\n\t\treturn empty || optall.queue === false ?\n\t\t\tthis.each( doAnimation ) :\n\t\t\tthis.queue( optall.queue, doAnimation );\n\t},\n\tstop: function( type, clearQueue, gotoEnd ) {\n\t\tvar stopQueue = function( hooks ) {\n\t\t\tvar stop = hooks.stop;\n\t\t\tdelete hooks.stop;\n\t\t\tstop( gotoEnd );\n\t\t};\n\n\t\tif ( typeof type !== \"string\" ) {\n\t\t\tgotoEnd = clearQueue;\n\t\t\tclearQueue = type;\n\t\t\ttype = undefined;\n\t\t}\n\t\tif ( clearQueue && type !== false ) {\n\t\t\tthis.queue( type || \"fx\", [] );\n\t\t}\n\n\t\treturn this.each(function() {\n\t\t\tvar dequeue = true,\n\t\t\t\tindex = type != null && type + \"queueHooks\",\n\t\t\t\ttimers = jQuery.timers,\n\t\t\t\tdata = jQuery._data( this );\n\n\t\t\tif ( index ) {\n\t\t\t\tif ( data[ index ] && data[ index ].stop ) {\n\t\t\t\t\tstopQueue( data[ index ] );\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tfor ( index in data ) {\n\t\t\t\t\tif ( data[ index ] && data[ index ].stop && rrun.test( index ) ) {\n\t\t\t\t\t\tstopQueue( data[ index ] );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfor ( index = timers.length; index--; ) {\n\t\t\t\tif ( timers[ index ].elem === this && (type == null || timers[ index ].queue === type) ) {\n\t\t\t\t\ttimers[ index ].anim.stop( gotoEnd );\n\t\t\t\t\tdequeue = false;\n\t\t\t\t\ttimers.splice( index, 1 );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// start the next in the queue if the last step wasn't forced\n\t\t\t// timers currently will call their complete callbacks, which will dequeue\n\t\t\t// but only if they were gotoEnd\n\t\t\tif ( dequeue || !gotoEnd ) {\n\t\t\t\tjQuery.dequeue( this, type );\n\t\t\t}\n\t\t});\n\t},\n\tfinish: function( type ) {\n\t\tif ( type !== false ) {\n\t\t\ttype = type || \"fx\";\n\t\t}\n\t\treturn this.each(function() {\n\t\t\tvar index,\n\t\t\t\tdata = jQuery._data( this ),\n\t\t\t\tqueue = data[ type + \"queue\" ],\n\t\t\t\thooks = data[ type + \"queueHooks\" ],\n\t\t\t\ttimers = jQuery.timers,\n\t\t\t\tlength = queue ? queue.length : 0;\n\n\t\t\t// enable finishing flag on private data\n\t\t\tdata.finish = true;\n\n\t\t\t// empty the queue first\n\t\t\tjQuery.queue( this, type, [] );\n\n\t\t\tif ( hooks && hooks.cur && hooks.cur.finish ) {\n\t\t\t\thooks.cur.finish.call( this );\n\t\t\t}\n\n\t\t\t// look for any active animations, and finish them\n\t\t\tfor ( index = timers.length; index--; ) {\n\t\t\t\tif ( timers[ index ].elem === this && timers[ index ].queue === type ) {\n\t\t\t\t\ttimers[ index ].anim.stop( true );\n\t\t\t\t\ttimers.splice( index, 1 );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// look for any animations in the old queue and finish them\n\t\t\tfor ( index = 0; index < length; index++ ) {\n\t\t\t\tif ( queue[ index ] && queue[ index ].finish ) {\n\t\t\t\t\tqueue[ index ].finish.call( this );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// turn off finishing flag\n\t\t\tdelete data.finish;\n\t\t});\n\t}\n});\n\n// Generate parameters to create a standard animation\nfunction genFx( type, includeWidth ) {\n\tvar which,\n\t\tattrs = { height: type },\n\t\ti = 0;\n\n\t// if we include width, step value is 1 to do all cssExpand values,\n\t// if we don't include width, step value is 2 to skip over Left and Right\n\tincludeWidth = includeWidth? 1 : 0;\n\tfor( ; i < 4 ; i += 2 - includeWidth ) {\n\t\twhich = cssExpand[ i ];\n\t\tattrs[ \"margin\" + which ] = attrs[ \"padding\" + which ] = type;\n\t}\n\n\tif ( includeWidth ) {\n\t\tattrs.opacity = attrs.width = type;\n\t}\n\n\treturn attrs;\n}\n\n// Generate shortcuts for custom animations\njQuery.each({\n\tslideDown: genFx(\"show\"),\n\tslideUp: genFx(\"hide\"),\n\tslideToggle: genFx(\"toggle\"),\n\tfadeIn: { opacity: \"show\" },\n\tfadeOut: { opacity: \"hide\" },\n\tfadeToggle: { opacity: \"toggle\" }\n}, function( name, props ) {\n\tjQuery.fn[ name ] = function( speed, easing, callback ) {\n\t\treturn this.animate( props, speed, easing, callback );\n\t};\n});\n\njQuery.speed = function( speed, easing, fn ) {\n\tvar opt = speed && typeof speed === \"object\" ? jQuery.extend( {}, speed ) : {\n\t\tcomplete: fn || !fn && easing ||\n\t\t\tjQuery.isFunction( speed ) && speed,\n\t\tduration: speed,\n\t\teasing: fn && easing || easing && !jQuery.isFunction( easing ) && easing\n\t};\n\n\topt.duration = jQuery.fx.off ? 0 : typeof opt.duration === \"number\" ? opt.duration :\n\t\topt.duration in jQuery.fx.speeds ? jQuery.fx.speeds[ opt.duration ] : jQuery.fx.speeds._default;\n\n\t// normalize opt.queue - true/undefined/null -> \"fx\"\n\tif ( opt.queue == null || opt.queue === true ) {\n\t\topt.queue = \"fx\";\n\t}\n\n\t// Queueing\n\topt.old = opt.complete;\n\n\topt.complete = function() {\n\t\tif ( jQuery.isFunction( opt.old ) ) {\n\t\t\topt.old.call( this );\n\t\t}\n\n\t\tif ( opt.queue ) {\n\t\t\tjQuery.dequeue( this, opt.queue );\n\t\t}\n\t};\n\n\treturn opt;\n};\n\njQuery.easing = {\n\tlinear: function( p ) {\n\t\treturn p;\n\t},\n\tswing: function( p ) {\n\t\treturn 0.5 - Math.cos( p*Math.PI ) / 2;\n\t}\n};\n\njQuery.timers = [];\njQuery.fx = Tween.prototype.init;\njQuery.fx.tick = function() {\n\tvar timer,\n\t\ttimers = jQuery.timers,\n\t\ti = 0;\n\n\tfxNow = jQuery.now();\n\n\tfor ( ; i < timers.length; i++ ) {\n\t\ttimer = timers[ i ];\n\t\t// Checks the timer has not already been removed\n\t\tif ( !timer() && timers[ i ] === timer ) {\n\t\t\ttimers.splice( i--, 1 );\n\t\t}\n\t}\n\n\tif ( !timers.length ) {\n\t\tjQuery.fx.stop();\n\t}\n\tfxNow = undefined;\n};\n\njQuery.fx.timer = function( timer ) {\n\tif ( timer() && jQuery.timers.push( timer ) ) {\n\t\tjQuery.fx.start();\n\t}\n};\n\njQuery.fx.interval = 13;\n\njQuery.fx.start = function() {\n\tif ( !timerId ) {\n\t\ttimerId = setInterval( jQuery.fx.tick, jQuery.fx.interval );\n\t}\n};\n\njQuery.fx.stop = function() {\n\tclearInterval( timerId );\n\ttimerId = null;\n};\n\njQuery.fx.speeds = {\n\tslow: 600,\n\tfast: 200,\n\t// Default speed\n\t_default: 400\n};\n\n// Back Compat <1.8 extension point\njQuery.fx.step = {};\n\nif ( jQuery.expr && jQuery.expr.filters ) {\n\tjQuery.expr.filters.animated = function( elem ) {\n\t\treturn jQuery.grep(jQuery.timers, function( fn ) {\n\t\t\treturn elem === fn.elem;\n\t\t}).length;\n\t};\n}\njQuery.fn.offset = function( options ) {\n\tif ( arguments.length ) {\n\t\treturn options === undefined ?\n\t\t\tthis :\n\t\t\tthis.each(function( i ) {\n\t\t\t\tjQuery.offset.setOffset( this, options, i );\n\t\t\t});\n\t}\n\n\tvar docElem, win,\n\t\tbox = { top: 0, left: 0 },\n\t\telem = this[ 0 ],\n\t\tdoc = elem && elem.ownerDocument;\n\n\tif ( !doc ) {\n\t\treturn;\n\t}\n\n\tdocElem = doc.documentElement;\n\n\t// Make sure it's not a disconnected DOM node\n\tif ( !jQuery.contains( docElem, elem ) ) {\n\t\treturn box;\n\t}\n\n\t// If we don't have gBCR, just use 0,0 rather than error\n\t// BlackBerry 5, iOS 3 (original iPhone)\n\tif ( typeof elem.getBoundingClientRect !== core_strundefined ) {\n\t\tbox = elem.getBoundingClientRect();\n\t}\n\twin = getWindow( doc );\n\treturn {\n\t\ttop: box.top  + ( win.pageYOffset || docElem.scrollTop )  - ( docElem.clientTop  || 0 ),\n\t\tleft: box.left + ( win.pageXOffset || docElem.scrollLeft ) - ( docElem.clientLeft || 0 )\n\t};\n};\n\njQuery.offset = {\n\n\tsetOffset: function( elem, options, i ) {\n\t\tvar position = jQuery.css( elem, \"position\" );\n\n\t\t// set position first, in-case top/left are set even on static elem\n\t\tif ( position === \"static\" ) {\n\t\t\telem.style.position = \"relative\";\n\t\t}\n\n\t\tvar curElem = jQuery( elem ),\n\t\t\tcurOffset = curElem.offset(),\n\t\t\tcurCSSTop = jQuery.css( elem, \"top\" ),\n\t\t\tcurCSSLeft = jQuery.css( elem, \"left\" ),\n\t\t\tcalculatePosition = ( position === \"absolute\" || position === \"fixed\" ) && jQuery.inArray(\"auto\", [curCSSTop, curCSSLeft]) > -1,\n\t\t\tprops = {}, curPosition = {}, curTop, curLeft;\n\n\t\t// need to be able to calculate position if either top or left is auto and position is either absolute or fixed\n\t\tif ( calculatePosition ) {\n\t\t\tcurPosition = curElem.position();\n\t\t\tcurTop = curPosition.top;\n\t\t\tcurLeft = curPosition.left;\n\t\t} else {\n\t\t\tcurTop = parseFloat( curCSSTop ) || 0;\n\t\t\tcurLeft = parseFloat( curCSSLeft ) || 0;\n\t\t}\n\n\t\tif ( jQuery.isFunction( options ) ) {\n\t\t\toptions = options.call( elem, i, curOffset );\n\t\t}\n\n\t\tif ( options.top != null ) {\n\t\t\tprops.top = ( options.top - curOffset.top ) + curTop;\n\t\t}\n\t\tif ( options.left != null ) {\n\t\t\tprops.left = ( options.left - curOffset.left ) + curLeft;\n\t\t}\n\n\t\tif ( \"using\" in options ) {\n\t\t\toptions.using.call( elem, props );\n\t\t} else {\n\t\t\tcurElem.css( props );\n\t\t}\n\t}\n};\n\n\njQuery.fn.extend({\n\n\tposition: function() {\n\t\tif ( !this[ 0 ] ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar offsetParent, offset,\n\t\t\tparentOffset = { top: 0, left: 0 },\n\t\t\telem = this[ 0 ];\n\n\t\t// fixed elements are offset from window (parentOffset = {top:0, left: 0}, because it is it's only offset parent\n\t\tif ( jQuery.css( elem, \"position\" ) === \"fixed\" ) {\n\t\t\t// we assume that getBoundingClientRect is available when computed position is fixed\n\t\t\toffset = elem.getBoundingClientRect();\n\t\t} else {\n\t\t\t// Get *real* offsetParent\n\t\t\toffsetParent = this.offsetParent();\n\n\t\t\t// Get correct offsets\n\t\t\toffset = this.offset();\n\t\t\tif ( !jQuery.nodeName( offsetParent[ 0 ], \"html\" ) ) {\n\t\t\t\tparentOffset = offsetParent.offset();\n\t\t\t}\n\n\t\t\t// Add offsetParent borders\n\t\t\tparentOffset.top  += jQuery.css( offsetParent[ 0 ], \"borderTopWidth\", true );\n\t\t\tparentOffset.left += jQuery.css( offsetParent[ 0 ], \"borderLeftWidth\", true );\n\t\t}\n\n\t\t// Subtract parent offsets and element margins\n\t\t// note: when an element has margin: auto the offsetLeft and marginLeft\n\t\t// are the same in Safari causing offset.left to incorrectly be 0\n\t\treturn {\n\t\t\ttop:  offset.top  - parentOffset.top - jQuery.css( elem, \"marginTop\", true ),\n\t\t\tleft: offset.left - parentOffset.left - jQuery.css( elem, \"marginLeft\", true)\n\t\t};\n\t},\n\n\toffsetParent: function() {\n\t\treturn this.map(function() {\n\t\t\tvar offsetParent = this.offsetParent || document.documentElement;\n\t\t\twhile ( offsetParent && ( !jQuery.nodeName( offsetParent, \"html\" ) && jQuery.css( offsetParent, \"position\") === \"static\" ) ) {\n\t\t\t\toffsetParent = offsetParent.offsetParent;\n\t\t\t}\n\t\t\treturn offsetParent || document.documentElement;\n\t\t});\n\t}\n});\n\n\n// Create scrollLeft and scrollTop methods\njQuery.each( {scrollLeft: \"pageXOffset\", scrollTop: \"pageYOffset\"}, function( method, prop ) {\n\tvar top = /Y/.test( prop );\n\n\tjQuery.fn[ method ] = function( val ) {\n\t\treturn jQuery.access( this, function( elem, method, val ) {\n\t\t\tvar win = getWindow( elem );\n\n\t\t\tif ( val === undefined ) {\n\t\t\t\treturn win ? (prop in win) ? win[ prop ] :\n\t\t\t\t\twin.document.documentElement[ method ] :\n\t\t\t\t\telem[ method ];\n\t\t\t}\n\n\t\t\tif ( win ) {\n\t\t\t\twin.scrollTo(\n\t\t\t\t\t!top ? val : jQuery( win ).scrollLeft(),\n\t\t\t\t\ttop ? val : jQuery( win ).scrollTop()\n\t\t\t\t);\n\n\t\t\t} else {\n\t\t\t\telem[ method ] = val;\n\t\t\t}\n\t\t}, method, val, arguments.length, null );\n\t};\n});\n\nfunction getWindow( elem ) {\n\treturn jQuery.isWindow( elem ) ?\n\t\telem :\n\t\telem.nodeType === 9 ?\n\t\t\telem.defaultView || elem.parentWindow :\n\t\t\tfalse;\n}\n// Create innerHeight, innerWidth, height, width, outerHeight and outerWidth methods\njQuery.each( { Height: \"height\", Width: \"width\" }, function( name, type ) {\n\tjQuery.each( { padding: \"inner\" + name, content: type, \"\": \"outer\" + name }, function( defaultExtra, funcName ) {\n\t\t// margin is only for outerHeight, outerWidth\n\t\tjQuery.fn[ funcName ] = function( margin, value ) {\n\t\t\tvar chainable = arguments.length && ( defaultExtra || typeof margin !== \"boolean\" ),\n\t\t\t\textra = defaultExtra || ( margin === true || value === true ? \"margin\" : \"border\" );\n\n\t\t\treturn jQuery.access( this, function( elem, type, value ) {\n\t\t\t\tvar doc;\n\n\t\t\t\tif ( jQuery.isWindow( elem ) ) {\n\t\t\t\t\t// As of 5/8/2012 this will yield incorrect results for Mobile Safari, but there\n\t\t\t\t\t// isn't a whole lot we can do. See pull request at this URL for discussion:\n\t\t\t\t\t// https://github.com/jquery/jquery/pull/764\n\t\t\t\t\treturn elem.document.documentElement[ \"client\" + name ];\n\t\t\t\t}\n\n\t\t\t\t// Get document width or height\n\t\t\t\tif ( elem.nodeType === 9 ) {\n\t\t\t\t\tdoc = elem.documentElement;\n\n\t\t\t\t\t// Either scroll[Width/Height] or offset[Width/Height] or client[Width/Height], whichever is greatest\n\t\t\t\t\t// unfortunately, this causes bug #3838 in IE6/8 only, but there is currently no good, small way to fix it.\n\t\t\t\t\treturn Math.max(\n\t\t\t\t\t\telem.body[ \"scroll\" + name ], doc[ \"scroll\" + name ],\n\t\t\t\t\t\telem.body[ \"offset\" + name ], doc[ \"offset\" + name ],\n\t\t\t\t\t\tdoc[ \"client\" + name ]\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\treturn value === undefined ?\n\t\t\t\t\t// Get width or height on the element, requesting but not forcing parseFloat\n\t\t\t\t\tjQuery.css( elem, type, extra ) :\n\n\t\t\t\t\t// Set width or height on the element\n\t\t\t\t\tjQuery.style( elem, type, value, extra );\n\t\t\t}, type, chainable ? margin : undefined, chainable, null );\n\t\t};\n\t});\n});\n// Limit scope pollution from any deprecated API\n// (function() {\n\n// })();\n// Expose jQuery to the global object\nwindow.jQuery = window.$ = jQuery;\n\n// Expose jQuery as an AMD module, but only for AMD loaders that\n// understand the issues with loading multiple versions of jQuery\n// in a page that all might call define(). The loader will indicate\n// they have special allowances for multiple jQuery versions by\n// specifying define.amd.jQuery = true. Register as a named module,\n// since jQuery can be concatenated with other files that may use define,\n// but not use a proper concatenation script that understands anonymous\n// AMD modules. A named AMD is safest and most robust way to register.\n// Lowercase jquery is used because AMD module names are derived from\n// file names, and jQuery is normally delivered in a lowercase file name.\n// Do this after creating the global so that if an AMD module wants to call\n// noConflict to hide this version of jQuery, it will work.\nif ( typeof define === \"function\" && define.amd && define.amd.jQuery ) {\n\tdefine( \"jquery\", [], function () { return jQuery; } );\n}\n\n})( window );"
  },
  {
    "path": "flowable-ui-web/modeler/libs/sizzle_1.10.16/test/libs/qunit/qunit.css",
    "content": "/**\n * QUnit v1.12.0 - A JavaScript Unit Testing Framework\n *\n * http://qunitjs.com\n *\n * Copyright 2012 jQuery Foundation and other contributors\n * Released under the MIT license.\n * http://jquery.org/license\n */\n\n/** Font Family and Sizes */\n\n#qunit-tests, #qunit-header, #qunit-banner, #qunit-testrunner-toolbar, #qunit-userAgent, #qunit-testresult {\n\tfont-family: \"Helvetica Neue Light\", \"HelveticaNeue-Light\", \"Helvetica Neue\", Calibri, Helvetica, Arial, sans-serif;\n}\n\n#qunit-testrunner-toolbar, #qunit-userAgent, #qunit-testresult, #qunit-tests li { font-size: small; }\n#qunit-tests { font-size: smaller; }\n\n\n/** Resets */\n\n#qunit-tests, #qunit-header, #qunit-banner, #qunit-userAgent, #qunit-testresult, #qunit-modulefilter {\n\tmargin: 0;\n\tpadding: 0;\n}\n\n\n/** Header */\n\n#qunit-header {\n\tpadding: 0.5em 0 0.5em 1em;\n\n\tcolor: #8699a4;\n\tbackground-color: #0d3349;\n\n\tfont-size: 1.5em;\n\tline-height: 1em;\n\tfont-weight: normal;\n\n\tborder-radius: 5px 5px 0 0;\n\t-moz-border-radius: 5px 5px 0 0;\n\t-webkit-border-top-right-radius: 5px;\n\t-webkit-border-top-left-radius: 5px;\n}\n\n#qunit-header a {\n\ttext-decoration: none;\n\tcolor: #c2ccd1;\n}\n\n#qunit-header a:hover,\n#qunit-header a:focus {\n\tcolor: #fff;\n}\n\n#qunit-testrunner-toolbar label {\n\tdisplay: inline-block;\n\tpadding: 0 .5em 0 .1em;\n}\n\n#qunit-banner {\n\theight: 5px;\n}\n\n#qunit-testrunner-toolbar {\n\tpadding: 0.5em 0 0.5em 2em;\n\tcolor: #5E740B;\n\tbackground-color: #eee;\n\toverflow: hidden;\n}\n\n#qunit-userAgent {\n\tpadding: 0.5em 0 0.5em 2.5em;\n\tbackground-color: #2b81af;\n\tcolor: #fff;\n\ttext-shadow: rgba(0, 0, 0, 0.5) 2px 2px 1px;\n}\n\n#qunit-modulefilter-container {\n\tfloat: right;\n}\n\n/** Tests: Pass/Fail */\n\n#qunit-tests {\n\tlist-style-position: inside;\n}\n\n#qunit-tests li {\n\tpadding: 0.4em 0.5em 0.4em 2.5em;\n\tborder-bottom: 1px solid #fff;\n\tlist-style-position: inside;\n}\n\n#qunit-tests.hidepass li.pass, #qunit-tests.hidepass li.running  {\n\tdisplay: none;\n}\n\n#qunit-tests li strong {\n\tcursor: pointer;\n}\n\n#qunit-tests li a {\n\tpadding: 0.5em;\n\tcolor: #c2ccd1;\n\ttext-decoration: none;\n}\n#qunit-tests li a:hover,\n#qunit-tests li a:focus {\n\tcolor: #000;\n}\n\n#qunit-tests li .runtime {\n\tfloat: right;\n\tfont-size: smaller;\n}\n\n.qunit-assert-list {\n\tmargin-top: 0.5em;\n\tpadding: 0.5em;\n\n\tbackground-color: #fff;\n\n\tborder-radius: 5px;\n\t-moz-border-radius: 5px;\n\t-webkit-border-radius: 5px;\n}\n\n.qunit-collapsed {\n\tdisplay: none;\n}\n\n#qunit-tests table {\n\tborder-collapse: collapse;\n\tmargin-top: .2em;\n}\n\n#qunit-tests th {\n\ttext-align: right;\n\tvertical-align: top;\n\tpadding: 0 .5em 0 0;\n}\n\n#qunit-tests td {\n\tvertical-align: top;\n}\n\n#qunit-tests pre {\n\tmargin: 0;\n\twhite-space: pre-wrap;\n\tword-wrap: break-word;\n}\n\n#qunit-tests del {\n\tbackground-color: #e0f2be;\n\tcolor: #374e0c;\n\ttext-decoration: none;\n}\n\n#qunit-tests ins {\n\tbackground-color: #ffcaca;\n\tcolor: #500;\n\ttext-decoration: none;\n}\n\n/*** Test Counts */\n\n#qunit-tests b.counts                       { color: black; }\n#qunit-tests b.passed                       { color: #5E740B; }\n#qunit-tests b.failed                       { color: #710909; }\n\n#qunit-tests li li {\n\tpadding: 5px;\n\tbackground-color: #fff;\n\tborder-bottom: none;\n\tlist-style-position: inside;\n}\n\n/*** Passing Styles */\n\n#qunit-tests li li.pass {\n\tcolor: #3c510c;\n\tbackground-color: #fff;\n\tborder-left: 10px solid #C6E746;\n}\n\n#qunit-tests .pass                          { color: #528CE0; background-color: #D2E0E6; }\n#qunit-tests .pass .test-name               { color: #366097; }\n\n#qunit-tests .pass .test-actual,\n#qunit-tests .pass .test-expected           { color: #999999; }\n\n#qunit-banner.qunit-pass                    { background-color: #C6E746; }\n\n/*** Failing Styles */\n\n#qunit-tests li li.fail {\n\tcolor: #710909;\n\tbackground-color: #fff;\n\tborder-left: 10px solid #EE5757;\n\twhite-space: pre;\n}\n\n#qunit-tests > li:last-child {\n\tborder-radius: 0 0 5px 5px;\n\t-moz-border-radius: 0 0 5px 5px;\n\t-webkit-border-bottom-right-radius: 5px;\n\t-webkit-border-bottom-left-radius: 5px;\n}\n\n#qunit-tests .fail                          { color: #000000; background-color: #EE5757; }\n#qunit-tests .fail .test-name,\n#qunit-tests .fail .module-name             { color: #000000; }\n\n#qunit-tests .fail .test-actual             { color: #EE5757; }\n#qunit-tests .fail .test-expected           { color: green;   }\n\n#qunit-banner.qunit-fail                    { background-color: #EE5757; }\n\n\n/** Result */\n\n#qunit-testresult {\n\tpadding: 0.5em 0.5em 0.5em 2.5em;\n\n\tcolor: #2b81af;\n\tbackground-color: #D2E0E6;\n\n\tborder-bottom: 1px solid white;\n}\n#qunit-testresult .module-name {\n\tfont-weight: bold;\n}\n\n/** Fixture */\n\n#qunit-fixture {\n\tposition: absolute;\n\ttop: -10000px;\n\tleft: -10000px;\n\twidth: 1000px;\n\theight: 1000px;\n}\n"
  },
  {
    "path": "flowable-ui-web/modeler/libs/sizzle_1.10.16/test/libs/qunit/qunit.js",
    "content": "/**\n * QUnit v1.12.0 - A JavaScript Unit Testing Framework\n *\n * http://qunitjs.com\n *\n * Copyright 2013 jQuery Foundation and other contributors\n * Released under the MIT license.\n * https://jquery.org/license/\n */\n\n(function( window ) {\n\nvar QUnit,\n\tassert,\n\tconfig,\n\tonErrorFnPrev,\n\ttestId = 0,\n\tfileName = (sourceFromStacktrace( 0 ) || \"\" ).replace(/(:\\d+)+\\)?/, \"\").replace(/.+\\//, \"\"),\n\ttoString = Object.prototype.toString,\n\thasOwn = Object.prototype.hasOwnProperty,\n\t// Keep a local reference to Date (GH-283)\n\tDate = window.Date,\n\tsetTimeout = window.setTimeout,\n\tdefined = {\n\t\tsetTimeout: typeof window.setTimeout !== \"undefined\",\n\t\tsessionStorage: (function() {\n\t\t\tvar x = \"qunit-test-string\";\n\t\t\ttry {\n\t\t\t\tsessionStorage.setItem( x, x );\n\t\t\t\tsessionStorage.removeItem( x );\n\t\t\t\treturn true;\n\t\t\t} catch( e ) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}())\n\t},\n\t/**\n\t * Provides a normalized error string, correcting an issue\n\t * with IE 7 (and prior) where Error.prototype.toString is\n\t * not properly implemented\n\t *\n\t * Based on http://es5.github.com/#x15.11.4.4\n\t *\n\t * @param {String|Error} error\n\t * @return {String} error message\n\t */\n\terrorString = function( error ) {\n\t\tvar name, message,\n\t\t\terrorString = error.toString();\n\t\tif ( errorString.substring( 0, 7 ) === \"[object\" ) {\n\t\t\tname = error.name ? error.name.toString() : \"Error\";\n\t\t\tmessage = error.message ? error.message.toString() : \"\";\n\t\t\tif ( name && message ) {\n\t\t\t\treturn name + \": \" + message;\n\t\t\t} else if ( name ) {\n\t\t\t\treturn name;\n\t\t\t} else if ( message ) {\n\t\t\t\treturn message;\n\t\t\t} else {\n\t\t\t\treturn \"Error\";\n\t\t\t}\n\t\t} else {\n\t\t\treturn errorString;\n\t\t}\n\t},\n\t/**\n\t * Makes a clone of an object using only Array or Object as base,\n\t * and copies over the own enumerable properties.\n\t *\n\t * @param {Object} obj\n\t * @return {Object} New object with only the own properties (recursively).\n\t */\n\tobjectValues = function( obj ) {\n\t\t// Grunt 0.3.x uses an older version of jshint that still has jshint/jshint#392.\n\t\t/*jshint newcap: false */\n\t\tvar key, val,\n\t\t\tvals = QUnit.is( \"array\", obj ) ? [] : {};\n\t\tfor ( key in obj ) {\n\t\t\tif ( hasOwn.call( obj, key ) ) {\n\t\t\t\tval = obj[key];\n\t\t\t\tvals[key] = val === Object(val) ? objectValues(val) : val;\n\t\t\t}\n\t\t}\n\t\treturn vals;\n\t};\n\nfunction Test( settings ) {\n\textend( this, settings );\n\tthis.assertions = [];\n\tthis.testNumber = ++Test.count;\n}\n\nTest.count = 0;\n\nTest.prototype = {\n\tinit: function() {\n\t\tvar a, b, li,\n\t\t\ttests = id( \"qunit-tests\" );\n\n\t\tif ( tests ) {\n\t\t\tb = document.createElement( \"strong\" );\n\t\t\tb.innerHTML = this.nameHtml;\n\n\t\t\t// `a` initialized at top of scope\n\t\t\ta = document.createElement( \"a\" );\n\t\t\ta.innerHTML = \"Rerun\";\n\t\t\ta.href = QUnit.url({ testNumber: this.testNumber });\n\n\t\t\tli = document.createElement( \"li\" );\n\t\t\tli.appendChild( b );\n\t\t\tli.appendChild( a );\n\t\t\tli.className = \"running\";\n\t\t\tli.id = this.id = \"qunit-test-output\" + testId++;\n\n\t\t\ttests.appendChild( li );\n\t\t}\n\t},\n\tsetup: function() {\n\t\tif (\n\t\t\t// Emit moduleStart when we're switching from one module to another\n\t\t\tthis.module !== config.previousModule ||\n\t\t\t\t// They could be equal (both undefined) but if the previousModule property doesn't\n\t\t\t\t// yet exist it means this is the first test in a suite that isn't wrapped in a\n\t\t\t\t// module, in which case we'll just emit a moduleStart event for 'undefined'.\n\t\t\t\t// Without this, reporters can get testStart before moduleStart  which is a problem.\n\t\t\t\t!hasOwn.call( config, \"previousModule\" )\n\t\t) {\n\t\t\tif ( hasOwn.call( config, \"previousModule\" ) ) {\n\t\t\t\trunLoggingCallbacks( \"moduleDone\", QUnit, {\n\t\t\t\t\tname: config.previousModule,\n\t\t\t\t\tfailed: config.moduleStats.bad,\n\t\t\t\t\tpassed: config.moduleStats.all - config.moduleStats.bad,\n\t\t\t\t\ttotal: config.moduleStats.all\n\t\t\t\t});\n\t\t\t}\n\t\t\tconfig.previousModule = this.module;\n\t\t\tconfig.moduleStats = { all: 0, bad: 0 };\n\t\t\trunLoggingCallbacks( \"moduleStart\", QUnit, {\n\t\t\t\tname: this.module\n\t\t\t});\n\t\t}\n\n\t\tconfig.current = this;\n\n\t\tthis.testEnvironment = extend({\n\t\t\tsetup: function() {},\n\t\t\tteardown: function() {}\n\t\t}, this.moduleTestEnvironment );\n\n\t\tthis.started = +new Date();\n\t\trunLoggingCallbacks( \"testStart\", QUnit, {\n\t\t\tname: this.testName,\n\t\t\tmodule: this.module\n\t\t});\n\n\t\t/*jshint camelcase:false */\n\n\n\t\t/**\n\t\t * Expose the current test environment.\n\t\t *\n\t\t * @deprecated since 1.12.0: Use QUnit.config.current.testEnvironment instead.\n\t\t */\n\t\tQUnit.current_testEnvironment = this.testEnvironment;\n\n\t\t/*jshint camelcase:true */\n\n\t\tif ( !config.pollution ) {\n\t\t\tsaveGlobal();\n\t\t}\n\t\tif ( config.notrycatch ) {\n\t\t\tthis.testEnvironment.setup.call( this.testEnvironment, QUnit.assert );\n\t\t\treturn;\n\t\t}\n\t\ttry {\n\t\t\tthis.testEnvironment.setup.call( this.testEnvironment, QUnit.assert );\n\t\t} catch( e ) {\n\t\t\tQUnit.pushFailure( \"Setup failed on \" + this.testName + \": \" + ( e.message || e ), extractStacktrace( e, 1 ) );\n\t\t}\n\t},\n\trun: function() {\n\t\tconfig.current = this;\n\n\t\tvar running = id( \"qunit-testresult\" );\n\n\t\tif ( running ) {\n\t\t\trunning.innerHTML = \"Running: <br/>\" + this.nameHtml;\n\t\t}\n\n\t\tif ( this.async ) {\n\t\t\tQUnit.stop();\n\t\t}\n\n\t\tthis.callbackStarted = +new Date();\n\n\t\tif ( config.notrycatch ) {\n\t\t\tthis.callback.call( this.testEnvironment, QUnit.assert );\n\t\t\tthis.callbackRuntime = +new Date() - this.callbackStarted;\n\t\t\treturn;\n\t\t}\n\n\t\ttry {\n\t\t\tthis.callback.call( this.testEnvironment, QUnit.assert );\n\t\t\tthis.callbackRuntime = +new Date() - this.callbackStarted;\n\t\t} catch( e ) {\n\t\t\tthis.callbackRuntime = +new Date() - this.callbackStarted;\n\n\t\t\tQUnit.pushFailure( \"Died on test #\" + (this.assertions.length + 1) + \" \" + this.stack + \": \" + ( e.message || e ), extractStacktrace( e, 0 ) );\n\t\t\t// else next test will carry the responsibility\n\t\t\tsaveGlobal();\n\n\t\t\t// Restart the tests if they're blocking\n\t\t\tif ( config.blocking ) {\n\t\t\t\tQUnit.start();\n\t\t\t}\n\t\t}\n\t},\n\tteardown: function() {\n\t\tconfig.current = this;\n\t\tif ( config.notrycatch ) {\n\t\t\tif ( typeof this.callbackRuntime === \"undefined\" ) {\n\t\t\t\tthis.callbackRuntime = +new Date() - this.callbackStarted;\n\t\t\t}\n\t\t\tthis.testEnvironment.teardown.call( this.testEnvironment, QUnit.assert );\n\t\t\treturn;\n\t\t} else {\n\t\t\ttry {\n\t\t\t\tthis.testEnvironment.teardown.call( this.testEnvironment, QUnit.assert );\n\t\t\t} catch( e ) {\n\t\t\t\tQUnit.pushFailure( \"Teardown failed on \" + this.testName + \": \" + ( e.message || e ), extractStacktrace( e, 1 ) );\n\t\t\t}\n\t\t}\n\t\tcheckPollution();\n\t},\n\tfinish: function() {\n\t\tconfig.current = this;\n\t\tif ( config.requireExpects && this.expected === null ) {\n\t\t\tQUnit.pushFailure( \"Expected number of assertions to be defined, but expect() was not called.\", this.stack );\n\t\t} else if ( this.expected !== null && this.expected !== this.assertions.length ) {\n\t\t\tQUnit.pushFailure( \"Expected \" + this.expected + \" assertions, but \" + this.assertions.length + \" were run\", this.stack );\n\t\t} else if ( this.expected === null && !this.assertions.length ) {\n\t\t\tQUnit.pushFailure( \"Expected at least one assertion, but none were run - call expect(0) to accept zero assertions.\", this.stack );\n\t\t}\n\n\t\tvar i, assertion, a, b, time, li, ol,\n\t\t\ttest = this,\n\t\t\tgood = 0,\n\t\t\tbad = 0,\n\t\t\ttests = id( \"qunit-tests\" );\n\n\t\tthis.runtime = +new Date() - this.started;\n\t\tconfig.stats.all += this.assertions.length;\n\t\tconfig.moduleStats.all += this.assertions.length;\n\n\t\tif ( tests ) {\n\t\t\tol = document.createElement( \"ol\" );\n\t\t\tol.className = \"qunit-assert-list\";\n\n\t\t\tfor ( i = 0; i < this.assertions.length; i++ ) {\n\t\t\t\tassertion = this.assertions[i];\n\n\t\t\t\tli = document.createElement( \"li\" );\n\t\t\t\tli.className = assertion.result ? \"pass\" : \"fail\";\n\t\t\t\tli.innerHTML = assertion.message || ( assertion.result ? \"okay\" : \"failed\" );\n\t\t\t\tol.appendChild( li );\n\n\t\t\t\tif ( assertion.result ) {\n\t\t\t\t\tgood++;\n\t\t\t\t} else {\n\t\t\t\t\tbad++;\n\t\t\t\t\tconfig.stats.bad++;\n\t\t\t\t\tconfig.moduleStats.bad++;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// store result when possible\n\t\t\tif ( QUnit.config.reorder && defined.sessionStorage ) {\n\t\t\t\tif ( bad ) {\n\t\t\t\t\tsessionStorage.setItem( \"qunit-test-\" + this.module + \"-\" + this.testName, bad );\n\t\t\t\t} else {\n\t\t\t\t\tsessionStorage.removeItem( \"qunit-test-\" + this.module + \"-\" + this.testName );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( bad === 0 ) {\n\t\t\t\taddClass( ol, \"qunit-collapsed\" );\n\t\t\t}\n\n\t\t\t// `b` initialized at top of scope\n\t\t\tb = document.createElement( \"strong\" );\n\t\t\tb.innerHTML = this.nameHtml + \" <b class='counts'>(<b class='failed'>\" + bad + \"</b>, <b class='passed'>\" + good + \"</b>, \" + this.assertions.length + \")</b>\";\n\n\t\t\taddEvent(b, \"click\", function() {\n\t\t\t\tvar next = b.parentNode.lastChild,\n\t\t\t\t\tcollapsed = hasClass( next, \"qunit-collapsed\" );\n\t\t\t\t( collapsed ? removeClass : addClass )( next, \"qunit-collapsed\" );\n\t\t\t});\n\n\t\t\taddEvent(b, \"dblclick\", function( e ) {\n\t\t\t\tvar target = e && e.target ? e.target : window.event.srcElement;\n\t\t\t\tif ( target.nodeName.toLowerCase() === \"span\" || target.nodeName.toLowerCase() === \"b\" ) {\n\t\t\t\t\ttarget = target.parentNode;\n\t\t\t\t}\n\t\t\t\tif ( window.location && target.nodeName.toLowerCase() === \"strong\" ) {\n\t\t\t\t\twindow.location = QUnit.url({ testNumber: test.testNumber });\n\t\t\t\t}\n\t\t\t});\n\n\t\t\t// `time` initialized at top of scope\n\t\t\ttime = document.createElement( \"span\" );\n\t\t\ttime.className = \"runtime\";\n\t\t\ttime.innerHTML = this.runtime + \" ms\";\n\n\t\t\t// `li` initialized at top of scope\n\t\t\tli = id( this.id );\n\t\t\tli.className = bad ? \"fail\" : \"pass\";\n\t\t\tli.removeChild( li.firstChild );\n\t\t\ta = li.firstChild;\n\t\t\tli.appendChild( b );\n\t\t\tli.appendChild( a );\n\t\t\tli.appendChild( time );\n\t\t\tli.appendChild( ol );\n\n\t\t} else {\n\t\t\tfor ( i = 0; i < this.assertions.length; i++ ) {\n\t\t\t\tif ( !this.assertions[i].result ) {\n\t\t\t\t\tbad++;\n\t\t\t\t\tconfig.stats.bad++;\n\t\t\t\t\tconfig.moduleStats.bad++;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\trunLoggingCallbacks( \"testDone\", QUnit, {\n\t\t\tname: this.testName,\n\t\t\tmodule: this.module,\n\t\t\tfailed: bad,\n\t\t\tpassed: this.assertions.length - bad,\n\t\t\ttotal: this.assertions.length,\n\t\t\tduration: this.runtime\n\t\t});\n\n\t\tQUnit.reset();\n\n\t\tconfig.current = undefined;\n\t},\n\n\tqueue: function() {\n\t\tvar bad,\n\t\t\ttest = this;\n\n\t\tsynchronize(function() {\n\t\t\ttest.init();\n\t\t});\n\t\tfunction run() {\n\t\t\t// each of these can by async\n\t\t\tsynchronize(function() {\n\t\t\t\ttest.setup();\n\t\t\t});\n\t\t\tsynchronize(function() {\n\t\t\t\ttest.run();\n\t\t\t});\n\t\t\tsynchronize(function() {\n\t\t\t\ttest.teardown();\n\t\t\t});\n\t\t\tsynchronize(function() {\n\t\t\t\ttest.finish();\n\t\t\t});\n\t\t}\n\n\t\t// `bad` initialized at top of scope\n\t\t// defer when previous test run passed, if storage is available\n\t\tbad = QUnit.config.reorder && defined.sessionStorage &&\n\t\t\t\t\t\t+sessionStorage.getItem( \"qunit-test-\" + this.module + \"-\" + this.testName );\n\n\t\tif ( bad ) {\n\t\t\trun();\n\t\t} else {\n\t\t\tsynchronize( run, true );\n\t\t}\n\t}\n};\n\n// Root QUnit object.\n// `QUnit` initialized at top of scope\nQUnit = {\n\n\t// call on start of module test to prepend name to all tests\n\tmodule: function( name, testEnvironment ) {\n\t\tconfig.currentModule = name;\n\t\tconfig.currentModuleTestEnvironment = testEnvironment;\n\t\tconfig.modules[name] = true;\n\t},\n\n\tasyncTest: function( testName, expected, callback ) {\n\t\tif ( arguments.length === 2 ) {\n\t\t\tcallback = expected;\n\t\t\texpected = null;\n\t\t}\n\n\t\tQUnit.test( testName, expected, callback, true );\n\t},\n\n\ttest: function( testName, expected, callback, async ) {\n\t\tvar test,\n\t\t\tnameHtml = \"<span class='test-name'>\" + escapeText( testName ) + \"</span>\";\n\n\t\tif ( arguments.length === 2 ) {\n\t\t\tcallback = expected;\n\t\t\texpected = null;\n\t\t}\n\n\t\tif ( config.currentModule ) {\n\t\t\tnameHtml = \"<span class='module-name'>\" + escapeText( config.currentModule ) + \"</span>: \" + nameHtml;\n\t\t}\n\n\t\ttest = new Test({\n\t\t\tnameHtml: nameHtml,\n\t\t\ttestName: testName,\n\t\t\texpected: expected,\n\t\t\tasync: async,\n\t\t\tcallback: callback,\n\t\t\tmodule: config.currentModule,\n\t\t\tmoduleTestEnvironment: config.currentModuleTestEnvironment,\n\t\t\tstack: sourceFromStacktrace( 2 )\n\t\t});\n\n\t\tif ( !validTest( test ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\ttest.queue();\n\t},\n\n\t// Specify the number of expected assertions to guarantee that failed test (no assertions are run at all) don't slip through.\n\texpect: function( asserts ) {\n\t\tif (arguments.length === 1) {\n\t\t\tconfig.current.expected = asserts;\n\t\t} else {\n\t\t\treturn config.current.expected;\n\t\t}\n\t},\n\n\tstart: function( count ) {\n\t\t// QUnit hasn't been initialized yet.\n\t\t// Note: RequireJS (et al) may delay onLoad\n\t\tif ( config.semaphore === undefined ) {\n\t\t\tQUnit.begin(function() {\n\t\t\t\t// This is triggered at the top of QUnit.load, push start() to the event loop, to allow QUnit.load to finish first\n\t\t\t\tsetTimeout(function() {\n\t\t\t\t\tQUnit.start( count );\n\t\t\t\t});\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\n\t\tconfig.semaphore -= count || 1;\n\t\t// don't start until equal number of stop-calls\n\t\tif ( config.semaphore > 0 ) {\n\t\t\treturn;\n\t\t}\n\t\t// ignore if start is called more often then stop\n\t\tif ( config.semaphore < 0 ) {\n\t\t\tconfig.semaphore = 0;\n\t\t\tQUnit.pushFailure( \"Called start() while already started (QUnit.config.semaphore was 0 already)\", null, sourceFromStacktrace(2) );\n\t\t\treturn;\n\t\t}\n\t\t// A slight delay, to avoid any current callbacks\n\t\tif ( defined.setTimeout ) {\n\t\t\tsetTimeout(function() {\n\t\t\t\tif ( config.semaphore > 0 ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tif ( config.timeout ) {\n\t\t\t\t\tclearTimeout( config.timeout );\n\t\t\t\t}\n\n\t\t\t\tconfig.blocking = false;\n\t\t\t\tprocess( true );\n\t\t\t}, 13);\n\t\t} else {\n\t\t\tconfig.blocking = false;\n\t\t\tprocess( true );\n\t\t}\n\t},\n\n\tstop: function( count ) {\n\t\tconfig.semaphore += count || 1;\n\t\tconfig.blocking = true;\n\n\t\tif ( config.testTimeout && defined.setTimeout ) {\n\t\t\tclearTimeout( config.timeout );\n\t\t\tconfig.timeout = setTimeout(function() {\n\t\t\t\tQUnit.ok( false, \"Test timed out\" );\n\t\t\t\tconfig.semaphore = 1;\n\t\t\t\tQUnit.start();\n\t\t\t}, config.testTimeout );\n\t\t}\n\t}\n};\n\n// `assert` initialized at top of scope\n// Assert helpers\n// All of these must either call QUnit.push() or manually do:\n// - runLoggingCallbacks( \"log\", .. );\n// - config.current.assertions.push({ .. });\n// We attach it to the QUnit object *after* we expose the public API,\n// otherwise `assert` will become a global variable in browsers (#341).\nassert = {\n\t/**\n\t * Asserts rough true-ish result.\n\t * @name ok\n\t * @function\n\t * @example ok( \"asdfasdf\".length > 5, \"There must be at least 5 chars\" );\n\t */\n\tok: function( result, msg ) {\n\t\tif ( !config.current ) {\n\t\t\tthrow new Error( \"ok() assertion outside test context, was \" + sourceFromStacktrace(2) );\n\t\t}\n\t\tresult = !!result;\n\t\tmsg = msg || (result ? \"okay\" : \"failed\" );\n\n\t\tvar source,\n\t\t\tdetails = {\n\t\t\t\tmodule: config.current.module,\n\t\t\t\tname: config.current.testName,\n\t\t\t\tresult: result,\n\t\t\t\tmessage: msg\n\t\t\t};\n\n\t\tmsg = \"<span class='test-message'>\" + escapeText( msg ) + \"</span>\";\n\n\t\tif ( !result ) {\n\t\t\tsource = sourceFromStacktrace( 2 );\n\t\t\tif ( source ) {\n\t\t\t\tdetails.source = source;\n\t\t\t\tmsg += \"<table><tr class='test-source'><th>Source: </th><td><pre>\" + escapeText( source ) + \"</pre></td></tr></table>\";\n\t\t\t}\n\t\t}\n\t\trunLoggingCallbacks( \"log\", QUnit, details );\n\t\tconfig.current.assertions.push({\n\t\t\tresult: result,\n\t\t\tmessage: msg\n\t\t});\n\t},\n\n\t/**\n\t * Assert that the first two arguments are equal, with an optional message.\n\t * Prints out both actual and expected values.\n\t * @name equal\n\t * @function\n\t * @example equal( format( \"Received {0} bytes.\", 2), \"Received 2 bytes.\", \"format() replaces {0} with next argument\" );\n\t */\n\tequal: function( actual, expected, message ) {\n\t\t/*jshint eqeqeq:false */\n\t\tQUnit.push( expected == actual, actual, expected, message );\n\t},\n\n\t/**\n\t * @name notEqual\n\t * @function\n\t */\n\tnotEqual: function( actual, expected, message ) {\n\t\t/*jshint eqeqeq:false */\n\t\tQUnit.push( expected != actual, actual, expected, message );\n\t},\n\n\t/**\n\t * @name propEqual\n\t * @function\n\t */\n\tpropEqual: function( actual, expected, message ) {\n\t\tactual = objectValues(actual);\n\t\texpected = objectValues(expected);\n\t\tQUnit.push( QUnit.equiv(actual, expected), actual, expected, message );\n\t},\n\n\t/**\n\t * @name notPropEqual\n\t * @function\n\t */\n\tnotPropEqual: function( actual, expected, message ) {\n\t\tactual = objectValues(actual);\n\t\texpected = objectValues(expected);\n\t\tQUnit.push( !QUnit.equiv(actual, expected), actual, expected, message );\n\t},\n\n\t/**\n\t * @name deepEqual\n\t * @function\n\t */\n\tdeepEqual: function( actual, expected, message ) {\n\t\tQUnit.push( QUnit.equiv(actual, expected), actual, expected, message );\n\t},\n\n\t/**\n\t * @name notDeepEqual\n\t * @function\n\t */\n\tnotDeepEqual: function( actual, expected, message ) {\n\t\tQUnit.push( !QUnit.equiv(actual, expected), actual, expected, message );\n\t},\n\n\t/**\n\t * @name strictEqual\n\t * @function\n\t */\n\tstrictEqual: function( actual, expected, message ) {\n\t\tQUnit.push( expected === actual, actual, expected, message );\n\t},\n\n\t/**\n\t * @name notStrictEqual\n\t * @function\n\t */\n\tnotStrictEqual: function( actual, expected, message ) {\n\t\tQUnit.push( expected !== actual, actual, expected, message );\n\t},\n\n\t\"throws\": function( block, expected, message ) {\n\t\tvar actual,\n\t\t\texpectedOutput = expected,\n\t\t\tok = false;\n\n\t\t// 'expected' is optional\n\t\tif ( typeof expected === \"string\" ) {\n\t\t\tmessage = expected;\n\t\t\texpected = null;\n\t\t}\n\n\t\tconfig.current.ignoreGlobalErrors = true;\n\t\ttry {\n\t\t\tblock.call( config.current.testEnvironment );\n\t\t} catch (e) {\n\t\t\tactual = e;\n\t\t}\n\t\tconfig.current.ignoreGlobalErrors = false;\n\n\t\tif ( actual ) {\n\t\t\t// we don't want to validate thrown error\n\t\t\tif ( !expected ) {\n\t\t\t\tok = true;\n\t\t\t\texpectedOutput = null;\n\t\t\t// expected is a regexp\n\t\t\t} else if ( QUnit.objectType( expected ) === \"regexp\" ) {\n\t\t\t\tok = expected.test( errorString( actual ) );\n\t\t\t// expected is a constructor\n\t\t\t} else if ( actual instanceof expected ) {\n\t\t\t\tok = true;\n\t\t\t// expected is a validation function which returns true is validation passed\n\t\t\t} else if ( expected.call( {}, actual ) === true ) {\n\t\t\t\texpectedOutput = null;\n\t\t\t\tok = true;\n\t\t\t}\n\n\t\t\tQUnit.push( ok, actual, expectedOutput, message );\n\t\t} else {\n\t\t\tQUnit.pushFailure( message, null, \"No exception was thrown.\" );\n\t\t}\n\t}\n};\n\n/**\n * @deprecated since 1.8.0\n * Kept assertion helpers in root for backwards compatibility.\n */\nextend( QUnit, assert );\n\n/**\n * @deprecated since 1.9.0\n * Kept root \"raises()\" for backwards compatibility.\n * (Note that we don't introduce assert.raises).\n */\nQUnit.raises = assert[ \"throws\" ];\n\n/**\n * @deprecated since 1.0.0, replaced with error pushes since 1.3.0\n * Kept to avoid TypeErrors for undefined methods.\n */\nQUnit.equals = function() {\n\tQUnit.push( false, false, false, \"QUnit.equals has been deprecated since 2009 (e88049a0), use QUnit.equal instead\" );\n};\nQUnit.same = function() {\n\tQUnit.push( false, false, false, \"QUnit.same has been deprecated since 2009 (e88049a0), use QUnit.deepEqual instead\" );\n};\n\n// We want access to the constructor's prototype\n(function() {\n\tfunction F() {}\n\tF.prototype = QUnit;\n\tQUnit = new F();\n\t// Make F QUnit's constructor so that we can add to the prototype later\n\tQUnit.constructor = F;\n}());\n\n/**\n * Config object: Maintain internal state\n * Later exposed as QUnit.config\n * `config` initialized at top of scope\n */\nconfig = {\n\t// The queue of tests to run\n\tqueue: [],\n\n\t// block until document ready\n\tblocking: true,\n\n\t// when enabled, show only failing tests\n\t// gets persisted through sessionStorage and can be changed in UI via checkbox\n\thidepassed: false,\n\n\t// by default, run previously failed tests first\n\t// very useful in combination with \"Hide passed tests\" checked\n\treorder: true,\n\n\t// by default, modify document.title when suite is done\n\taltertitle: true,\n\n\t// when enabled, all tests must call expect()\n\trequireExpects: false,\n\n\t// add checkboxes that are persisted in the query-string\n\t// when enabled, the id is set to `true` as a `QUnit.config` property\n\turlConfig: [\n\t\t{\n\t\t\tid: \"noglobals\",\n\t\t\tlabel: \"Check for Globals\",\n\t\t\ttooltip: \"Enabling this will test if any test introduces new properties on the `window` object. Stored as query-strings.\"\n\t\t},\n\t\t{\n\t\t\tid: \"notrycatch\",\n\t\t\tlabel: \"No try-catch\",\n\t\t\ttooltip: \"Enabling this will run tests outside of a try-catch block. Makes debugging exceptions in IE reasonable. Stored as query-strings.\"\n\t\t}\n\t],\n\n\t// Set of all modules.\n\tmodules: {},\n\n\t// logging callback queues\n\tbegin: [],\n\tdone: [],\n\tlog: [],\n\ttestStart: [],\n\ttestDone: [],\n\tmoduleStart: [],\n\tmoduleDone: []\n};\n\n// Export global variables, unless an 'exports' object exists,\n// in that case we assume we're in CommonJS (dealt with on the bottom of the script)\nif ( typeof exports === \"undefined\" ) {\n\textend( window, QUnit.constructor.prototype );\n\n\t// Expose QUnit object\n\twindow.QUnit = QUnit;\n}\n\n// Initialize more QUnit.config and QUnit.urlParams\n(function() {\n\tvar i,\n\t\tlocation = window.location || { search: \"\", protocol: \"file:\" },\n\t\tparams = location.search.slice( 1 ).split( \"&\" ),\n\t\tlength = params.length,\n\t\turlParams = {},\n\t\tcurrent;\n\n\tif ( params[ 0 ] ) {\n\t\tfor ( i = 0; i < length; i++ ) {\n\t\t\tcurrent = params[ i ].split( \"=\" );\n\t\t\tcurrent[ 0 ] = decodeURIComponent( current[ 0 ] );\n\t\t\t// allow just a key to turn on a flag, e.g., test.html?noglobals\n\t\t\tcurrent[ 1 ] = current[ 1 ] ? decodeURIComponent( current[ 1 ] ) : true;\n\t\t\turlParams[ current[ 0 ] ] = current[ 1 ];\n\t\t}\n\t}\n\n\tQUnit.urlParams = urlParams;\n\n\t// String search anywhere in moduleName+testName\n\tconfig.filter = urlParams.filter;\n\n\t// Exact match of the module name\n\tconfig.module = urlParams.module;\n\n\tconfig.testNumber = parseInt( urlParams.testNumber, 10 ) || null;\n\n\t// Figure out if we're running the tests from a server or not\n\tQUnit.isLocal = location.protocol === \"file:\";\n}());\n\n// Extend QUnit object,\n// these after set here because they should not be exposed as global functions\nextend( QUnit, {\n\tassert: assert,\n\n\tconfig: config,\n\n\t// Initialize the configuration options\n\tinit: function() {\n\t\textend( config, {\n\t\t\tstats: { all: 0, bad: 0 },\n\t\t\tmoduleStats: { all: 0, bad: 0 },\n\t\t\tstarted: +new Date(),\n\t\t\tupdateRate: 1000,\n\t\t\tblocking: false,\n\t\t\tautostart: true,\n\t\t\tautorun: false,\n\t\t\tfilter: \"\",\n\t\t\tqueue: [],\n\t\t\tsemaphore: 1\n\t\t});\n\n\t\tvar tests, banner, result,\n\t\t\tqunit = id( \"qunit\" );\n\n\t\tif ( qunit ) {\n\t\t\tqunit.innerHTML =\n\t\t\t\t\"<h1 id='qunit-header'>\" + escapeText( document.title ) + \"</h1>\" +\n\t\t\t\t\"<h2 id='qunit-banner'></h2>\" +\n\t\t\t\t\"<div id='qunit-testrunner-toolbar'></div>\" +\n\t\t\t\t\"<h2 id='qunit-userAgent'></h2>\" +\n\t\t\t\t\"<ol id='qunit-tests'></ol>\";\n\t\t}\n\n\t\ttests = id( \"qunit-tests\" );\n\t\tbanner = id( \"qunit-banner\" );\n\t\tresult = id( \"qunit-testresult\" );\n\n\t\tif ( tests ) {\n\t\t\ttests.innerHTML = \"\";\n\t\t}\n\n\t\tif ( banner ) {\n\t\t\tbanner.className = \"\";\n\t\t}\n\n\t\tif ( result ) {\n\t\t\tresult.parentNode.removeChild( result );\n\t\t}\n\n\t\tif ( tests ) {\n\t\t\tresult = document.createElement( \"p\" );\n\t\t\tresult.id = \"qunit-testresult\";\n\t\t\tresult.className = \"result\";\n\t\t\ttests.parentNode.insertBefore( result, tests );\n\t\t\tresult.innerHTML = \"Running...<br/>&nbsp;\";\n\t\t}\n\t},\n\n\t// Resets the test setup. Useful for tests that modify the DOM.\n\t/*\n\tDEPRECATED: Use multiple tests instead of resetting inside a test.\n\tUse testStart or testDone for custom cleanup.\n\tThis method will throw an error in 2.0, and will be removed in 2.1\n\t*/\n\treset: function() {\n\t\tvar fixture = id( \"qunit-fixture\" );\n\t\tif ( fixture ) {\n\t\t\tfixture.innerHTML = config.fixture;\n\t\t}\n\t},\n\n\t// Trigger an event on an element.\n\t// @example triggerEvent( document.body, \"click\" );\n\ttriggerEvent: function( elem, type, event ) {\n\t\tif ( document.createEvent ) {\n\t\t\tevent = document.createEvent( \"MouseEvents\" );\n\t\t\tevent.initMouseEvent(type, true, true, elem.ownerDocument.defaultView,\n\t\t\t\t0, 0, 0, 0, 0, false, false, false, false, 0, null);\n\n\t\t\telem.dispatchEvent( event );\n\t\t} else if ( elem.fireEvent ) {\n\t\t\telem.fireEvent( \"on\" + type );\n\t\t}\n\t},\n\n\t// Safe object type checking\n\tis: function( type, obj ) {\n\t\treturn QUnit.objectType( obj ) === type;\n\t},\n\n\tobjectType: function( obj ) {\n\t\tif ( typeof obj === \"undefined\" ) {\n\t\t\t\treturn \"undefined\";\n\t\t// consider: typeof null === object\n\t\t}\n\t\tif ( obj === null ) {\n\t\t\t\treturn \"null\";\n\t\t}\n\n\t\tvar match = toString.call( obj ).match(/^\\[object\\s(.*)\\]$/),\n\t\t\ttype = match && match[1] || \"\";\n\n\t\tswitch ( type ) {\n\t\t\tcase \"Number\":\n\t\t\t\tif ( isNaN(obj) ) {\n\t\t\t\t\treturn \"nan\";\n\t\t\t\t}\n\t\t\t\treturn \"number\";\n\t\t\tcase \"String\":\n\t\t\tcase \"Boolean\":\n\t\t\tcase \"Array\":\n\t\t\tcase \"Date\":\n\t\t\tcase \"RegExp\":\n\t\t\tcase \"Function\":\n\t\t\t\treturn type.toLowerCase();\n\t\t}\n\t\tif ( typeof obj === \"object\" ) {\n\t\t\treturn \"object\";\n\t\t}\n\t\treturn undefined;\n\t},\n\n\tpush: function( result, actual, expected, message ) {\n\t\tif ( !config.current ) {\n\t\t\tthrow new Error( \"assertion outside test context, was \" + sourceFromStacktrace() );\n\t\t}\n\n\t\tvar output, source,\n\t\t\tdetails = {\n\t\t\t\tmodule: config.current.module,\n\t\t\t\tname: config.current.testName,\n\t\t\t\tresult: result,\n\t\t\t\tmessage: message,\n\t\t\t\tactual: actual,\n\t\t\t\texpected: expected\n\t\t\t};\n\n\t\tmessage = escapeText( message ) || ( result ? \"okay\" : \"failed\" );\n\t\tmessage = \"<span class='test-message'>\" + message + \"</span>\";\n\t\toutput = message;\n\n\t\tif ( !result ) {\n\t\t\texpected = escapeText( QUnit.jsDump.parse(expected) );\n\t\t\tactual = escapeText( QUnit.jsDump.parse(actual) );\n\t\t\toutput += \"<table><tr class='test-expected'><th>Expected: </th><td><pre>\" + expected + \"</pre></td></tr>\";\n\n\t\t\tif ( actual !== expected ) {\n\t\t\t\toutput += \"<tr class='test-actual'><th>Result: </th><td><pre>\" + actual + \"</pre></td></tr>\";\n\t\t\t\toutput += \"<tr class='test-diff'><th>Diff: </th><td><pre>\" + QUnit.diff( expected, actual ) + \"</pre></td></tr>\";\n\t\t\t}\n\n\t\t\tsource = sourceFromStacktrace();\n\n\t\t\tif ( source ) {\n\t\t\t\tdetails.source = source;\n\t\t\t\toutput += \"<tr class='test-source'><th>Source: </th><td><pre>\" + escapeText( source ) + \"</pre></td></tr>\";\n\t\t\t}\n\n\t\t\toutput += \"</table>\";\n\t\t}\n\n\t\trunLoggingCallbacks( \"log\", QUnit, details );\n\n\t\tconfig.current.assertions.push({\n\t\t\tresult: !!result,\n\t\t\tmessage: output\n\t\t});\n\t},\n\n\tpushFailure: function( message, source, actual ) {\n\t\tif ( !config.current ) {\n\t\t\tthrow new Error( \"pushFailure() assertion outside test context, was \" + sourceFromStacktrace(2) );\n\t\t}\n\n\t\tvar output,\n\t\t\tdetails = {\n\t\t\t\tmodule: config.current.module,\n\t\t\t\tname: config.current.testName,\n\t\t\t\tresult: false,\n\t\t\t\tmessage: message\n\t\t\t};\n\n\t\tmessage = escapeText( message ) || \"error\";\n\t\tmessage = \"<span class='test-message'>\" + message + \"</span>\";\n\t\toutput = message;\n\n\t\toutput += \"<table>\";\n\n\t\tif ( actual ) {\n\t\t\toutput += \"<tr class='test-actual'><th>Result: </th><td><pre>\" + escapeText( actual ) + \"</pre></td></tr>\";\n\t\t}\n\n\t\tif ( source ) {\n\t\t\tdetails.source = source;\n\t\t\toutput += \"<tr class='test-source'><th>Source: </th><td><pre>\" + escapeText( source ) + \"</pre></td></tr>\";\n\t\t}\n\n\t\toutput += \"</table>\";\n\n\t\trunLoggingCallbacks( \"log\", QUnit, details );\n\n\t\tconfig.current.assertions.push({\n\t\t\tresult: false,\n\t\t\tmessage: output\n\t\t});\n\t},\n\n\turl: function( params ) {\n\t\tparams = extend( extend( {}, QUnit.urlParams ), params );\n\t\tvar key,\n\t\t\tquerystring = \"?\";\n\n\t\tfor ( key in params ) {\n\t\t\tif ( hasOwn.call( params, key ) ) {\n\t\t\t\tquerystring += encodeURIComponent( key ) + \"=\" +\n\t\t\t\t\tencodeURIComponent( params[ key ] ) + \"&\";\n\t\t\t}\n\t\t}\n\t\treturn window.location.protocol + \"//\" + window.location.host +\n\t\t\twindow.location.pathname + querystring.slice( 0, -1 );\n\t},\n\n\textend: extend,\n\tid: id,\n\taddEvent: addEvent,\n\taddClass: addClass,\n\thasClass: hasClass,\n\tremoveClass: removeClass\n\t// load, equiv, jsDump, diff: Attached later\n});\n\n/**\n * @deprecated: Created for backwards compatibility with test runner that set the hook function\n * into QUnit.{hook}, instead of invoking it and passing the hook function.\n * QUnit.constructor is set to the empty F() above so that we can add to it's prototype here.\n * Doing this allows us to tell if the following methods have been overwritten on the actual\n * QUnit object.\n */\nextend( QUnit.constructor.prototype, {\n\n\t// Logging callbacks; all receive a single argument with the listed properties\n\t// run test/logs.html for any related changes\n\tbegin: registerLoggingCallback( \"begin\" ),\n\n\t// done: { failed, passed, total, runtime }\n\tdone: registerLoggingCallback( \"done\" ),\n\n\t// log: { result, actual, expected, message }\n\tlog: registerLoggingCallback( \"log\" ),\n\n\t// testStart: { name }\n\ttestStart: registerLoggingCallback( \"testStart\" ),\n\n\t// testDone: { name, failed, passed, total, duration }\n\ttestDone: registerLoggingCallback( \"testDone\" ),\n\n\t// moduleStart: { name }\n\tmoduleStart: registerLoggingCallback( \"moduleStart\" ),\n\n\t// moduleDone: { name, failed, passed, total }\n\tmoduleDone: registerLoggingCallback( \"moduleDone\" )\n});\n\nif ( typeof document === \"undefined\" || document.readyState === \"complete\" ) {\n\tconfig.autorun = true;\n}\n\nQUnit.load = function() {\n\trunLoggingCallbacks( \"begin\", QUnit, {} );\n\n\t// Initialize the config, saving the execution queue\n\tvar banner, filter, i, label, len, main, ol, toolbar, userAgent, val,\n\t\turlConfigCheckboxesContainer, urlConfigCheckboxes, moduleFilter,\n\t\tnumModules = 0,\n\t\tmoduleNames = [],\n\t\tmoduleFilterHtml = \"\",\n\t\turlConfigHtml = \"\",\n\t\toldconfig = extend( {}, config );\n\n\tQUnit.init();\n\textend(config, oldconfig);\n\n\tconfig.blocking = false;\n\n\tlen = config.urlConfig.length;\n\n\tfor ( i = 0; i < len; i++ ) {\n\t\tval = config.urlConfig[i];\n\t\tif ( typeof val === \"string\" ) {\n\t\t\tval = {\n\t\t\t\tid: val,\n\t\t\t\tlabel: val,\n\t\t\t\ttooltip: \"[no tooltip available]\"\n\t\t\t};\n\t\t}\n\t\tconfig[ val.id ] = QUnit.urlParams[ val.id ];\n\t\turlConfigHtml += \"<input id='qunit-urlconfig-\" + escapeText( val.id ) +\n\t\t\t\"' name='\" + escapeText( val.id ) +\n\t\t\t\"' type='checkbox'\" + ( config[ val.id ] ? \" checked='checked'\" : \"\" ) +\n\t\t\t\" title='\" + escapeText( val.tooltip ) +\n\t\t\t\"'><label for='qunit-urlconfig-\" + escapeText( val.id ) +\n\t\t\t\"' title='\" + escapeText( val.tooltip ) + \"'>\" + val.label + \"</label>\";\n\t}\n\tfor ( i in config.modules ) {\n\t\tif ( config.modules.hasOwnProperty( i ) ) {\n\t\t\tmoduleNames.push(i);\n\t\t}\n\t}\n\tnumModules = moduleNames.length;\n\tmoduleNames.sort( function( a, b ) {\n\t\treturn a.localeCompare( b );\n\t});\n\tmoduleFilterHtml += \"<label for='qunit-modulefilter'>Module: </label><select id='qunit-modulefilter' name='modulefilter'><option value='' \" +\n\t\t( config.module === undefined  ? \"selected='selected'\" : \"\" ) +\n\t\t\">< All Modules ></option>\";\n\n\n\tfor ( i = 0; i < numModules; i++) {\n\t\t\tmoduleFilterHtml += \"<option value='\" + escapeText( encodeURIComponent(moduleNames[i]) ) + \"' \" +\n\t\t\t\t( config.module === moduleNames[i] ? \"selected='selected'\" : \"\" ) +\n\t\t\t\t\">\" + escapeText(moduleNames[i]) + \"</option>\";\n\t}\n\tmoduleFilterHtml += \"</select>\";\n\n\t// `userAgent` initialized at top of scope\n\tuserAgent = id( \"qunit-userAgent\" );\n\tif ( userAgent ) {\n\t\tuserAgent.innerHTML = navigator.userAgent;\n\t}\n\n\t// `banner` initialized at top of scope\n\tbanner = id( \"qunit-header\" );\n\tif ( banner ) {\n\t\tbanner.innerHTML = \"<a href='\" + QUnit.url({ filter: undefined, module: undefined, testNumber: undefined }) + \"'>\" + banner.innerHTML + \"</a> \";\n\t}\n\n\t// `toolbar` initialized at top of scope\n\ttoolbar = id( \"qunit-testrunner-toolbar\" );\n\tif ( toolbar ) {\n\t\t// `filter` initialized at top of scope\n\t\tfilter = document.createElement( \"input\" );\n\t\tfilter.type = \"checkbox\";\n\t\tfilter.id = \"qunit-filter-pass\";\n\n\t\taddEvent( filter, \"click\", function() {\n\t\t\tvar tmp,\n\t\t\t\tol = document.getElementById( \"qunit-tests\" );\n\n\t\t\tif ( filter.checked ) {\n\t\t\t\tol.className = ol.className + \" hidepass\";\n\t\t\t} else {\n\t\t\t\ttmp = \" \" + ol.className.replace( /[\\n\\t\\r]/g, \" \" ) + \" \";\n\t\t\t\tol.className = tmp.replace( / hidepass /, \" \" );\n\t\t\t}\n\t\t\tif ( defined.sessionStorage ) {\n\t\t\t\tif (filter.checked) {\n\t\t\t\t\tsessionStorage.setItem( \"qunit-filter-passed-tests\", \"true\" );\n\t\t\t\t} else {\n\t\t\t\t\tsessionStorage.removeItem( \"qunit-filter-passed-tests\" );\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\tif ( config.hidepassed || defined.sessionStorage && sessionStorage.getItem( \"qunit-filter-passed-tests\" ) ) {\n\t\t\tfilter.checked = true;\n\t\t\t// `ol` initialized at top of scope\n\t\t\tol = document.getElementById( \"qunit-tests\" );\n\t\t\tol.className = ol.className + \" hidepass\";\n\t\t}\n\t\ttoolbar.appendChild( filter );\n\n\t\t// `label` initialized at top of scope\n\t\tlabel = document.createElement( \"label\" );\n\t\tlabel.setAttribute( \"for\", \"qunit-filter-pass\" );\n\t\tlabel.setAttribute( \"title\", \"Only show tests and assertions that fail. Stored in sessionStorage.\" );\n\t\tlabel.innerHTML = \"Hide passed tests\";\n\t\ttoolbar.appendChild( label );\n\n\t\turlConfigCheckboxesContainer = document.createElement(\"span\");\n\t\turlConfigCheckboxesContainer.innerHTML = urlConfigHtml;\n\t\turlConfigCheckboxes = urlConfigCheckboxesContainer.getElementsByTagName(\"input\");\n\t\t// For oldIE support:\n\t\t// * Add handlers to the individual elements instead of the container\n\t\t// * Use \"click\" instead of \"change\"\n\t\t// * Fallback from event.target to event.srcElement\n\t\taddEvents( urlConfigCheckboxes, \"click\", function( event ) {\n\t\t\tvar params = {},\n\t\t\t\ttarget = event.target || event.srcElement;\n\t\t\tparams[ target.name ] = target.checked ? true : undefined;\n\t\t\twindow.location = QUnit.url( params );\n\t\t});\n\t\ttoolbar.appendChild( urlConfigCheckboxesContainer );\n\n\t\tif (numModules > 1) {\n\t\t\tmoduleFilter = document.createElement( \"span\" );\n\t\t\tmoduleFilter.setAttribute( \"id\", \"qunit-modulefilter-container\" );\n\t\t\tmoduleFilter.innerHTML = moduleFilterHtml;\n\t\t\taddEvent( moduleFilter.lastChild, \"change\", function() {\n\t\t\t\tvar selectBox = moduleFilter.getElementsByTagName(\"select\")[0],\n\t\t\t\t\tselectedModule = decodeURIComponent(selectBox.options[selectBox.selectedIndex].value);\n\n\t\t\t\twindow.location = QUnit.url({\n\t\t\t\t\tmodule: ( selectedModule === \"\" ) ? undefined : selectedModule,\n\t\t\t\t\t// Remove any existing filters\n\t\t\t\t\tfilter: undefined,\n\t\t\t\t\ttestNumber: undefined\n\t\t\t\t});\n\t\t\t});\n\t\t\ttoolbar.appendChild(moduleFilter);\n\t\t}\n\t}\n\n\t// `main` initialized at top of scope\n\tmain = id( \"qunit-fixture\" );\n\tif ( main ) {\n\t\tconfig.fixture = main.innerHTML;\n\t}\n\n\tif ( config.autostart ) {\n\t\tQUnit.start();\n\t}\n};\n\naddEvent( window, \"load\", QUnit.load );\n\n// `onErrorFnPrev` initialized at top of scope\n// Preserve other handlers\nonErrorFnPrev = window.onerror;\n\n// Cover uncaught exceptions\n// Returning true will suppress the default browser handler,\n// returning false will let it run.\nwindow.onerror = function ( error, filePath, linerNr ) {\n\tvar ret = false;\n\tif ( onErrorFnPrev ) {\n\t\tret = onErrorFnPrev( error, filePath, linerNr );\n\t}\n\n\t// Treat return value as window.onerror itself does,\n\t// Only do our handling if not suppressed.\n\tif ( ret !== true ) {\n\t\tif ( QUnit.config.current ) {\n\t\t\tif ( QUnit.config.current.ignoreGlobalErrors ) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\tQUnit.pushFailure( error, filePath + \":\" + linerNr );\n\t\t} else {\n\t\t\tQUnit.test( \"global failure\", extend( function() {\n\t\t\t\tQUnit.pushFailure( error, filePath + \":\" + linerNr );\n\t\t\t}, { validTest: validTest } ) );\n\t\t}\n\t\treturn false;\n\t}\n\n\treturn ret;\n};\n\nfunction done() {\n\tconfig.autorun = true;\n\n\t// Log the last module results\n\tif ( config.currentModule ) {\n\t\trunLoggingCallbacks( \"moduleDone\", QUnit, {\n\t\t\tname: config.currentModule,\n\t\t\tfailed: config.moduleStats.bad,\n\t\t\tpassed: config.moduleStats.all - config.moduleStats.bad,\n\t\t\ttotal: config.moduleStats.all\n\t\t});\n\t}\n\tdelete config.previousModule;\n\n\tvar i, key,\n\t\tbanner = id( \"qunit-banner\" ),\n\t\ttests = id( \"qunit-tests\" ),\n\t\truntime = +new Date() - config.started,\n\t\tpassed = config.stats.all - config.stats.bad,\n\t\thtml = [\n\t\t\t\"Tests completed in \",\n\t\t\truntime,\n\t\t\t\" milliseconds.<br/>\",\n\t\t\t\"<span class='passed'>\",\n\t\t\tpassed,\n\t\t\t\"</span> assertions of <span class='total'>\",\n\t\t\tconfig.stats.all,\n\t\t\t\"</span> passed, <span class='failed'>\",\n\t\t\tconfig.stats.bad,\n\t\t\t\"</span> failed.\"\n\t\t].join( \"\" );\n\n\tif ( banner ) {\n\t\tbanner.className = ( config.stats.bad ? \"qunit-fail\" : \"qunit-pass\" );\n\t}\n\n\tif ( tests ) {\n\t\tid( \"qunit-testresult\" ).innerHTML = html;\n\t}\n\n\tif ( config.altertitle && typeof document !== \"undefined\" && document.title ) {\n\t\t// show ✖ for good, ✔ for bad suite result in title\n\t\t// use escape sequences in case file gets loaded with non-utf-8-charset\n\t\tdocument.title = [\n\t\t\t( config.stats.bad ? \"\\u2716\" : \"\\u2714\" ),\n\t\t\tdocument.title.replace( /^[\\u2714\\u2716] /i, \"\" )\n\t\t].join( \" \" );\n\t}\n\n\t// clear own sessionStorage items if all tests passed\n\tif ( config.reorder && defined.sessionStorage && config.stats.bad === 0 ) {\n\t\t// `key` & `i` initialized at top of scope\n\t\tfor ( i = 0; i < sessionStorage.length; i++ ) {\n\t\t\tkey = sessionStorage.key( i++ );\n\t\t\tif ( key.indexOf( \"qunit-test-\" ) === 0 ) {\n\t\t\t\tsessionStorage.removeItem( key );\n\t\t\t}\n\t\t}\n\t}\n\n\t// scroll back to top to show results\n\tif ( window.scrollTo ) {\n\t\twindow.scrollTo(0, 0);\n\t}\n\n\trunLoggingCallbacks( \"done\", QUnit, {\n\t\tfailed: config.stats.bad,\n\t\tpassed: passed,\n\t\ttotal: config.stats.all,\n\t\truntime: runtime\n\t});\n}\n\n/** @return Boolean: true if this test should be ran */\nfunction validTest( test ) {\n\tvar include,\n\t\tfilter = config.filter && config.filter.toLowerCase(),\n\t\tmodule = config.module && config.module.toLowerCase(),\n\t\tfullName = (test.module + \": \" + test.testName).toLowerCase();\n\n\t// Internally-generated tests are always valid\n\tif ( test.callback && test.callback.validTest === validTest ) {\n\t\tdelete test.callback.validTest;\n\t\treturn true;\n\t}\n\n\tif ( config.testNumber ) {\n\t\treturn test.testNumber === config.testNumber;\n\t}\n\n\tif ( module && ( !test.module || test.module.toLowerCase() !== module ) ) {\n\t\treturn false;\n\t}\n\n\tif ( !filter ) {\n\t\treturn true;\n\t}\n\n\tinclude = filter.charAt( 0 ) !== \"!\";\n\tif ( !include ) {\n\t\tfilter = filter.slice( 1 );\n\t}\n\n\t// If the filter matches, we need to honour include\n\tif ( fullName.indexOf( filter ) !== -1 ) {\n\t\treturn include;\n\t}\n\n\t// Otherwise, do the opposite\n\treturn !include;\n}\n\n// so far supports only Firefox, Chrome and Opera (buggy), Safari (for real exceptions)\n// Later Safari and IE10 are supposed to support error.stack as well\n// See also https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error/Stack\nfunction extractStacktrace( e, offset ) {\n\toffset = offset === undefined ? 3 : offset;\n\n\tvar stack, include, i;\n\n\tif ( e.stacktrace ) {\n\t\t// Opera\n\t\treturn e.stacktrace.split( \"\\n\" )[ offset + 3 ];\n\t} else if ( e.stack ) {\n\t\t// Firefox, Chrome\n\t\tstack = e.stack.split( \"\\n\" );\n\t\tif (/^error$/i.test( stack[0] ) ) {\n\t\t\tstack.shift();\n\t\t}\n\t\tif ( fileName ) {\n\t\t\tinclude = [];\n\t\t\tfor ( i = offset; i < stack.length; i++ ) {\n\t\t\t\tif ( stack[ i ].indexOf( fileName ) !== -1 ) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tinclude.push( stack[ i ] );\n\t\t\t}\n\t\t\tif ( include.length ) {\n\t\t\t\treturn include.join( \"\\n\" );\n\t\t\t}\n\t\t}\n\t\treturn stack[ offset ];\n\t} else if ( e.sourceURL ) {\n\t\t// Safari, PhantomJS\n\t\t// hopefully one day Safari provides actual stacktraces\n\t\t// exclude useless self-reference for generated Error objects\n\t\tif ( /qunit.js$/.test( e.sourceURL ) ) {\n\t\t\treturn;\n\t\t}\n\t\t// for actual exceptions, this is useful\n\t\treturn e.sourceURL + \":\" + e.line;\n\t}\n}\nfunction sourceFromStacktrace( offset ) {\n\ttry {\n\t\tthrow new Error();\n\t} catch ( e ) {\n\t\treturn extractStacktrace( e, offset );\n\t}\n}\n\n/**\n * Escape text for attribute or text content.\n */\nfunction escapeText( s ) {\n\tif ( !s ) {\n\t\treturn \"\";\n\t}\n\ts = s + \"\";\n\t// Both single quotes and double quotes (for attributes)\n\treturn s.replace( /['\"<>&]/g, function( s ) {\n\t\tswitch( s ) {\n\t\t\tcase \"'\":\n\t\t\t\treturn \"&#039;\";\n\t\t\tcase \"\\\"\":\n\t\t\t\treturn \"&quot;\";\n\t\t\tcase \"<\":\n\t\t\t\treturn \"&lt;\";\n\t\t\tcase \">\":\n\t\t\t\treturn \"&gt;\";\n\t\t\tcase \"&\":\n\t\t\t\treturn \"&amp;\";\n\t\t}\n\t});\n}\n\nfunction synchronize( callback, last ) {\n\tconfig.queue.push( callback );\n\n\tif ( config.autorun && !config.blocking ) {\n\t\tprocess( last );\n\t}\n}\n\nfunction process( last ) {\n\tfunction next() {\n\t\tprocess( last );\n\t}\n\tvar start = new Date().getTime();\n\tconfig.depth = config.depth ? config.depth + 1 : 1;\n\n\twhile ( config.queue.length && !config.blocking ) {\n\t\tif ( !defined.setTimeout || config.updateRate <= 0 || ( ( new Date().getTime() - start ) < config.updateRate ) ) {\n\t\t\tconfig.queue.shift()();\n\t\t} else {\n\t\t\tsetTimeout( next, 13 );\n\t\t\tbreak;\n\t\t}\n\t}\n\tconfig.depth--;\n\tif ( last && !config.blocking && !config.queue.length && config.depth === 0 ) {\n\t\tdone();\n\t}\n}\n\nfunction saveGlobal() {\n\tconfig.pollution = [];\n\n\tif ( config.noglobals ) {\n\t\tfor ( var key in window ) {\n\t\t\tif ( hasOwn.call( window, key ) ) {\n\t\t\t\t// in Opera sometimes DOM element ids show up here, ignore them\n\t\t\t\tif ( /^qunit-test-output/.test( key ) ) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tconfig.pollution.push( key );\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunction checkPollution() {\n\tvar newGlobals,\n\t\tdeletedGlobals,\n\t\told = config.pollution;\n\n\tsaveGlobal();\n\n\tnewGlobals = diff( config.pollution, old );\n\tif ( newGlobals.length > 0 ) {\n\t\tQUnit.pushFailure( \"Introduced global variable(s): \" + newGlobals.join(\", \") );\n\t}\n\n\tdeletedGlobals = diff( old, config.pollution );\n\tif ( deletedGlobals.length > 0 ) {\n\t\tQUnit.pushFailure( \"Deleted global variable(s): \" + deletedGlobals.join(\", \") );\n\t}\n}\n\n// returns a new Array with the elements that are in a but not in b\nfunction diff( a, b ) {\n\tvar i, j,\n\t\tresult = a.slice();\n\n\tfor ( i = 0; i < result.length; i++ ) {\n\t\tfor ( j = 0; j < b.length; j++ ) {\n\t\t\tif ( result[i] === b[j] ) {\n\t\t\t\tresult.splice( i, 1 );\n\t\t\t\ti--;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\treturn result;\n}\n\nfunction extend( a, b ) {\n\tfor ( var prop in b ) {\n\t\tif ( hasOwn.call( b, prop ) ) {\n\t\t\t// Avoid \"Member not found\" error in IE8 caused by messing with window.constructor\n\t\t\tif ( !( prop === \"constructor\" && a === window ) ) {\n\t\t\t\tif ( b[ prop ] === undefined ) {\n\t\t\t\t\tdelete a[ prop ];\n\t\t\t\t} else {\n\t\t\t\t\ta[ prop ] = b[ prop ];\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn a;\n}\n\n/**\n * @param {HTMLElement} elem\n * @param {string} type\n * @param {Function} fn\n */\nfunction addEvent( elem, type, fn ) {\n\t// Standards-based browsers\n\tif ( elem.addEventListener ) {\n\t\telem.addEventListener( type, fn, false );\n\t// IE\n\t} else {\n\t\telem.attachEvent( \"on\" + type, fn );\n\t}\n}\n\n/**\n * @param {Array|NodeList} elems\n * @param {string} type\n * @param {Function} fn\n */\nfunction addEvents( elems, type, fn ) {\n\tvar i = elems.length;\n\twhile ( i-- ) {\n\t\taddEvent( elems[i], type, fn );\n\t}\n}\n\nfunction hasClass( elem, name ) {\n\treturn (\" \" + elem.className + \" \").indexOf(\" \" + name + \" \") > -1;\n}\n\nfunction addClass( elem, name ) {\n\tif ( !hasClass( elem, name ) ) {\n\t\telem.className += (elem.className ? \" \" : \"\") + name;\n\t}\n}\n\nfunction removeClass( elem, name ) {\n\tvar set = \" \" + elem.className + \" \";\n\t// Class name may appear multiple times\n\twhile ( set.indexOf(\" \" + name + \" \") > -1 ) {\n\t\tset = set.replace(\" \" + name + \" \" , \" \");\n\t}\n\t// If possible, trim it for prettiness, but not necessarily\n\telem.className = typeof set.trim === \"function\" ? set.trim() : set.replace(/^\\s+|\\s+$/g, \"\");\n}\n\nfunction id( name ) {\n\treturn !!( typeof document !== \"undefined\" && document && document.getElementById ) &&\n\t\tdocument.getElementById( name );\n}\n\nfunction registerLoggingCallback( key ) {\n\treturn function( callback ) {\n\t\tconfig[key].push( callback );\n\t};\n}\n\n// Supports deprecated method of completely overwriting logging callbacks\nfunction runLoggingCallbacks( key, scope, args ) {\n\tvar i, callbacks;\n\tif ( QUnit.hasOwnProperty( key ) ) {\n\t\tQUnit[ key ].call(scope, args );\n\t} else {\n\t\tcallbacks = config[ key ];\n\t\tfor ( i = 0; i < callbacks.length; i++ ) {\n\t\t\tcallbacks[ i ].call( scope, args );\n\t\t}\n\t}\n}\n\n// Test for equality any JavaScript type.\n// Author: Philippe Rathé <prathe@gmail.com>\nQUnit.equiv = (function() {\n\n\t// Call the o related callback with the given arguments.\n\tfunction bindCallbacks( o, callbacks, args ) {\n\t\tvar prop = QUnit.objectType( o );\n\t\tif ( prop ) {\n\t\t\tif ( QUnit.objectType( callbacks[ prop ] ) === \"function\" ) {\n\t\t\t\treturn callbacks[ prop ].apply( callbacks, args );\n\t\t\t} else {\n\t\t\t\treturn callbacks[ prop ]; // or undefined\n\t\t\t}\n\t\t}\n\t}\n\n\t// the real equiv function\n\tvar innerEquiv,\n\t\t// stack to decide between skip/abort functions\n\t\tcallers = [],\n\t\t// stack to avoiding loops from circular referencing\n\t\tparents = [],\n\t\tparentsB = [],\n\n\t\tgetProto = Object.getPrototypeOf || function ( obj ) {\n\t\t\t/*jshint camelcase:false */\n\t\t\treturn obj.__proto__;\n\t\t},\n\t\tcallbacks = (function () {\n\n\t\t\t// for string, boolean, number and null\n\t\t\tfunction useStrictEquality( b, a ) {\n\t\t\t\t/*jshint eqeqeq:false */\n\t\t\t\tif ( b instanceof a.constructor || a instanceof b.constructor ) {\n\t\t\t\t\t// to catch short annotation VS 'new' annotation of a\n\t\t\t\t\t// declaration\n\t\t\t\t\t// e.g. var i = 1;\n\t\t\t\t\t// var j = new Number(1);\n\t\t\t\t\treturn a == b;\n\t\t\t\t} else {\n\t\t\t\t\treturn a === b;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\t\"string\": useStrictEquality,\n\t\t\t\t\"boolean\": useStrictEquality,\n\t\t\t\t\"number\": useStrictEquality,\n\t\t\t\t\"null\": useStrictEquality,\n\t\t\t\t\"undefined\": useStrictEquality,\n\n\t\t\t\t\"nan\": function( b ) {\n\t\t\t\t\treturn isNaN( b );\n\t\t\t\t},\n\n\t\t\t\t\"date\": function( b, a ) {\n\t\t\t\t\treturn QUnit.objectType( b ) === \"date\" && a.valueOf() === b.valueOf();\n\t\t\t\t},\n\n\t\t\t\t\"regexp\": function( b, a ) {\n\t\t\t\t\treturn QUnit.objectType( b ) === \"regexp\" &&\n\t\t\t\t\t\t// the regex itself\n\t\t\t\t\t\ta.source === b.source &&\n\t\t\t\t\t\t// and its modifiers\n\t\t\t\t\t\ta.global === b.global &&\n\t\t\t\t\t\t// (gmi) ...\n\t\t\t\t\t\ta.ignoreCase === b.ignoreCase &&\n\t\t\t\t\t\ta.multiline === b.multiline &&\n\t\t\t\t\t\ta.sticky === b.sticky;\n\t\t\t\t},\n\n\t\t\t\t// - skip when the property is a method of an instance (OOP)\n\t\t\t\t// - abort otherwise,\n\t\t\t\t// initial === would have catch identical references anyway\n\t\t\t\t\"function\": function() {\n\t\t\t\t\tvar caller = callers[callers.length - 1];\n\t\t\t\t\treturn caller !== Object && typeof caller !== \"undefined\";\n\t\t\t\t},\n\n\t\t\t\t\"array\": function( b, a ) {\n\t\t\t\t\tvar i, j, len, loop, aCircular, bCircular;\n\n\t\t\t\t\t// b could be an object literal here\n\t\t\t\t\tif ( QUnit.objectType( b ) !== \"array\" ) {\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\n\t\t\t\t\tlen = a.length;\n\t\t\t\t\tif ( len !== b.length ) {\n\t\t\t\t\t\t// safe and faster\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\n\t\t\t\t\t// track reference to avoid circular references\n\t\t\t\t\tparents.push( a );\n\t\t\t\t\tparentsB.push( b );\n\t\t\t\t\tfor ( i = 0; i < len; i++ ) {\n\t\t\t\t\t\tloop = false;\n\t\t\t\t\t\tfor ( j = 0; j < parents.length; j++ ) {\n\t\t\t\t\t\t\taCircular = parents[j] === a[i];\n\t\t\t\t\t\t\tbCircular = parentsB[j] === b[i];\n\t\t\t\t\t\t\tif ( aCircular || bCircular ) {\n\t\t\t\t\t\t\t\tif ( a[i] === b[i] || aCircular && bCircular ) {\n\t\t\t\t\t\t\t\t\tloop = true;\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tparents.pop();\n\t\t\t\t\t\t\t\t\tparentsB.pop();\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}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif ( !loop && !innerEquiv(a[i], b[i]) ) {\n\t\t\t\t\t\t\tparents.pop();\n\t\t\t\t\t\t\tparentsB.pop();\n\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tparents.pop();\n\t\t\t\t\tparentsB.pop();\n\t\t\t\t\treturn true;\n\t\t\t\t},\n\n\t\t\t\t\"object\": function( b, a ) {\n\t\t\t\t\t/*jshint forin:false */\n\t\t\t\t\tvar i, j, loop, aCircular, bCircular,\n\t\t\t\t\t\t// Default to true\n\t\t\t\t\t\teq = true,\n\t\t\t\t\t\taProperties = [],\n\t\t\t\t\t\tbProperties = [];\n\n\t\t\t\t\t// comparing constructors is more strict than using\n\t\t\t\t\t// instanceof\n\t\t\t\t\tif ( a.constructor !== b.constructor ) {\n\t\t\t\t\t\t// Allow objects with no prototype to be equivalent to\n\t\t\t\t\t\t// objects with Object as their constructor.\n\t\t\t\t\t\tif ( !(( getProto(a) === null && getProto(b) === Object.prototype ) ||\n\t\t\t\t\t\t\t( getProto(b) === null && getProto(a) === Object.prototype ) ) ) {\n\t\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// stack constructor before traversing properties\n\t\t\t\t\tcallers.push( a.constructor );\n\n\t\t\t\t\t// track reference to avoid circular references\n\t\t\t\t\tparents.push( a );\n\t\t\t\t\tparentsB.push( b );\n\n\t\t\t\t\t// be strict: don't ensure hasOwnProperty and go deep\n\t\t\t\t\tfor ( i in a ) {\n\t\t\t\t\t\tloop = false;\n\t\t\t\t\t\tfor ( j = 0; j < parents.length; j++ ) {\n\t\t\t\t\t\t\taCircular = parents[j] === a[i];\n\t\t\t\t\t\t\tbCircular = parentsB[j] === b[i];\n\t\t\t\t\t\t\tif ( aCircular || bCircular ) {\n\t\t\t\t\t\t\t\tif ( a[i] === b[i] || aCircular && bCircular ) {\n\t\t\t\t\t\t\t\t\tloop = true;\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\teq = false;\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\taProperties.push(i);\n\t\t\t\t\t\tif ( !loop && !innerEquiv(a[i], b[i]) ) {\n\t\t\t\t\t\t\teq = false;\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\tparents.pop();\n\t\t\t\t\tparentsB.pop();\n\t\t\t\t\tcallers.pop(); // unstack, we are done\n\n\t\t\t\t\tfor ( i in b ) {\n\t\t\t\t\t\tbProperties.push( i ); // collect b's properties\n\t\t\t\t\t}\n\n\t\t\t\t\t// Ensures identical properties name\n\t\t\t\t\treturn eq && innerEquiv( aProperties.sort(), bProperties.sort() );\n\t\t\t\t}\n\t\t\t};\n\t\t}());\n\n\tinnerEquiv = function() { // can take multiple arguments\n\t\tvar args = [].slice.apply( arguments );\n\t\tif ( args.length < 2 ) {\n\t\t\treturn true; // end transition\n\t\t}\n\n\t\treturn (function( a, b ) {\n\t\t\tif ( a === b ) {\n\t\t\t\treturn true; // catch the most you can\n\t\t\t} else if ( a === null || b === null || typeof a === \"undefined\" ||\n\t\t\t\t\ttypeof b === \"undefined\" ||\n\t\t\t\t\tQUnit.objectType(a) !== QUnit.objectType(b) ) {\n\t\t\t\treturn false; // don't lose time with error prone cases\n\t\t\t} else {\n\t\t\t\treturn bindCallbacks(a, callbacks, [ b, a ]);\n\t\t\t}\n\n\t\t\t// apply transition with (1..n) arguments\n\t\t}( args[0], args[1] ) && innerEquiv.apply( this, args.splice(1, args.length - 1 )) );\n\t};\n\n\treturn innerEquiv;\n}());\n\n/**\n * jsDump Copyright (c) 2008 Ariel Flesler - aflesler(at)gmail(dot)com |\n * http://flesler.blogspot.com Licensed under BSD\n * (http://www.opensource.org/licenses/bsd-license.php) Date: 5/15/2008\n *\n * @projectDescription Advanced and extensible data dumping for Javascript.\n * @version 1.0.0\n * @author Ariel Flesler\n * @link {http://flesler.blogspot.com/2008/05/jsdump-pretty-dump-of-any-javascript.html}\n */\nQUnit.jsDump = (function() {\n\tfunction quote( str ) {\n\t\treturn \"\\\"\" + str.toString().replace( /\"/g, \"\\\\\\\"\" ) + \"\\\"\";\n\t}\n\tfunction literal( o ) {\n\t\treturn o + \"\";\n\t}\n\tfunction join( pre, arr, post ) {\n\t\tvar s = jsDump.separator(),\n\t\t\tbase = jsDump.indent(),\n\t\t\tinner = jsDump.indent(1);\n\t\tif ( arr.join ) {\n\t\t\tarr = arr.join( \",\" + s + inner );\n\t\t}\n\t\tif ( !arr ) {\n\t\t\treturn pre + post;\n\t\t}\n\t\treturn [ pre, inner + arr, base + post ].join(s);\n\t}\n\tfunction array( arr, stack ) {\n\t\tvar i = arr.length, ret = new Array(i);\n\t\tthis.up();\n\t\twhile ( i-- ) {\n\t\t\tret[i] = this.parse( arr[i] , undefined , stack);\n\t\t}\n\t\tthis.down();\n\t\treturn join( \"[\", ret, \"]\" );\n\t}\n\n\tvar reName = /^function (\\w+)/,\n\t\tjsDump = {\n\t\t\t// type is used mostly internally, you can fix a (custom)type in advance\n\t\t\tparse: function( obj, type, stack ) {\n\t\t\t\tstack = stack || [ ];\n\t\t\t\tvar inStack, res,\n\t\t\t\t\tparser = this.parsers[ type || this.typeOf(obj) ];\n\n\t\t\t\ttype = typeof parser;\n\t\t\t\tinStack = inArray( obj, stack );\n\n\t\t\t\tif ( inStack !== -1 ) {\n\t\t\t\t\treturn \"recursion(\" + (inStack - stack.length) + \")\";\n\t\t\t\t}\n\t\t\t\tif ( type === \"function\" )  {\n\t\t\t\t\tstack.push( obj );\n\t\t\t\t\tres = parser.call( this, obj, stack );\n\t\t\t\t\tstack.pop();\n\t\t\t\t\treturn res;\n\t\t\t\t}\n\t\t\t\treturn ( type === \"string\" ) ? parser : this.parsers.error;\n\t\t\t},\n\t\t\ttypeOf: function( obj ) {\n\t\t\t\tvar type;\n\t\t\t\tif ( obj === null ) {\n\t\t\t\t\ttype = \"null\";\n\t\t\t\t} else if ( typeof obj === \"undefined\" ) {\n\t\t\t\t\ttype = \"undefined\";\n\t\t\t\t} else if ( QUnit.is( \"regexp\", obj) ) {\n\t\t\t\t\ttype = \"regexp\";\n\t\t\t\t} else if ( QUnit.is( \"date\", obj) ) {\n\t\t\t\t\ttype = \"date\";\n\t\t\t\t} else if ( QUnit.is( \"function\", obj) ) {\n\t\t\t\t\ttype = \"function\";\n\t\t\t\t} else if ( typeof obj.setInterval !== undefined && typeof obj.document !== \"undefined\" && typeof obj.nodeType === \"undefined\" ) {\n\t\t\t\t\ttype = \"window\";\n\t\t\t\t} else if ( obj.nodeType === 9 ) {\n\t\t\t\t\ttype = \"document\";\n\t\t\t\t} else if ( obj.nodeType ) {\n\t\t\t\t\ttype = \"node\";\n\t\t\t\t} else if (\n\t\t\t\t\t// native arrays\n\t\t\t\t\ttoString.call( obj ) === \"[object Array]\" ||\n\t\t\t\t\t// NodeList objects\n\t\t\t\t\t( typeof obj.length === \"number\" && typeof obj.item !== \"undefined\" && ( obj.length ? obj.item(0) === obj[0] : ( obj.item( 0 ) === null && typeof obj[0] === \"undefined\" ) ) )\n\t\t\t\t) {\n\t\t\t\t\ttype = \"array\";\n\t\t\t\t} else if ( obj.constructor === Error.prototype.constructor ) {\n\t\t\t\t\ttype = \"error\";\n\t\t\t\t} else {\n\t\t\t\t\ttype = typeof obj;\n\t\t\t\t}\n\t\t\t\treturn type;\n\t\t\t},\n\t\t\tseparator: function() {\n\t\t\t\treturn this.multiline ?\tthis.HTML ? \"<br />\" : \"\\n\" : this.HTML ? \"&nbsp;\" : \" \";\n\t\t\t},\n\t\t\t// extra can be a number, shortcut for increasing-calling-decreasing\n\t\t\tindent: function( extra ) {\n\t\t\t\tif ( !this.multiline ) {\n\t\t\t\t\treturn \"\";\n\t\t\t\t}\n\t\t\t\tvar chr = this.indentChar;\n\t\t\t\tif ( this.HTML ) {\n\t\t\t\t\tchr = chr.replace( /\\t/g, \"   \" ).replace( / /g, \"&nbsp;\" );\n\t\t\t\t}\n\t\t\t\treturn new Array( this.depth + ( extra || 0 ) ).join(chr);\n\t\t\t},\n\t\t\tup: function( a ) {\n\t\t\t\tthis.depth += a || 1;\n\t\t\t},\n\t\t\tdown: function( a ) {\n\t\t\t\tthis.depth -= a || 1;\n\t\t\t},\n\t\t\tsetParser: function( name, parser ) {\n\t\t\t\tthis.parsers[name] = parser;\n\t\t\t},\n\t\t\t// The next 3 are exposed so you can use them\n\t\t\tquote: quote,\n\t\t\tliteral: literal,\n\t\t\tjoin: join,\n\t\t\t//\n\t\t\tdepth: 1,\n\t\t\t// This is the list of parsers, to modify them, use jsDump.setParser\n\t\t\tparsers: {\n\t\t\t\twindow: \"[Window]\",\n\t\t\t\tdocument: \"[Document]\",\n\t\t\t\terror: function(error) {\n\t\t\t\t\treturn \"Error(\\\"\" + error.message + \"\\\")\";\n\t\t\t\t},\n\t\t\t\tunknown: \"[Unknown]\",\n\t\t\t\t\"null\": \"null\",\n\t\t\t\t\"undefined\": \"undefined\",\n\t\t\t\t\"function\": function( fn ) {\n\t\t\t\t\tvar ret = \"function\",\n\t\t\t\t\t\t// functions never have name in IE\n\t\t\t\t\t\tname = \"name\" in fn ? fn.name : (reName.exec(fn) || [])[1];\n\n\t\t\t\t\tif ( name ) {\n\t\t\t\t\t\tret += \" \" + name;\n\t\t\t\t\t}\n\t\t\t\t\tret += \"( \";\n\n\t\t\t\t\tret = [ ret, QUnit.jsDump.parse( fn, \"functionArgs\" ), \"){\" ].join( \"\" );\n\t\t\t\t\treturn join( ret, QUnit.jsDump.parse(fn,\"functionCode\" ), \"}\" );\n\t\t\t\t},\n\t\t\t\tarray: array,\n\t\t\t\tnodelist: array,\n\t\t\t\t\"arguments\": array,\n\t\t\t\tobject: function( map, stack ) {\n\t\t\t\t\t/*jshint forin:false */\n\t\t\t\t\tvar ret = [ ], keys, key, val, i;\n\t\t\t\t\tQUnit.jsDump.up();\n\t\t\t\t\tkeys = [];\n\t\t\t\t\tfor ( key in map ) {\n\t\t\t\t\t\tkeys.push( key );\n\t\t\t\t\t}\n\t\t\t\t\tkeys.sort();\n\t\t\t\t\tfor ( i = 0; i < keys.length; i++ ) {\n\t\t\t\t\t\tkey = keys[ i ];\n\t\t\t\t\t\tval = map[ key ];\n\t\t\t\t\t\tret.push( QUnit.jsDump.parse( key, \"key\" ) + \": \" + QUnit.jsDump.parse( val, undefined, stack ) );\n\t\t\t\t\t}\n\t\t\t\t\tQUnit.jsDump.down();\n\t\t\t\t\treturn join( \"{\", ret, \"}\" );\n\t\t\t\t},\n\t\t\t\tnode: function( node ) {\n\t\t\t\t\tvar len, i, val,\n\t\t\t\t\t\topen = QUnit.jsDump.HTML ? \"&lt;\" : \"<\",\n\t\t\t\t\t\tclose = QUnit.jsDump.HTML ? \"&gt;\" : \">\",\n\t\t\t\t\t\ttag = node.nodeName.toLowerCase(),\n\t\t\t\t\t\tret = open + tag,\n\t\t\t\t\t\tattrs = node.attributes;\n\n\t\t\t\t\tif ( attrs ) {\n\t\t\t\t\t\tfor ( i = 0, len = attrs.length; i < len; i++ ) {\n\t\t\t\t\t\t\tval = attrs[i].nodeValue;\n\t\t\t\t\t\t\t// IE6 includes all attributes in .attributes, even ones not explicitly set.\n\t\t\t\t\t\t\t// Those have values like undefined, null, 0, false, \"\" or \"inherit\".\n\t\t\t\t\t\t\tif ( val && val !== \"inherit\" ) {\n\t\t\t\t\t\t\t\tret += \" \" + attrs[i].nodeName + \"=\" + QUnit.jsDump.parse( val, \"attribute\" );\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\tret += close;\n\n\t\t\t\t\t// Show content of TextNode or CDATASection\n\t\t\t\t\tif ( node.nodeType === 3 || node.nodeType === 4 ) {\n\t\t\t\t\t\tret += node.nodeValue;\n\t\t\t\t\t}\n\n\t\t\t\t\treturn ret + open + \"/\" + tag + close;\n\t\t\t\t},\n\t\t\t\t// function calls it internally, it's the arguments part of the function\n\t\t\t\tfunctionArgs: function( fn ) {\n\t\t\t\t\tvar args,\n\t\t\t\t\t\tl = fn.length;\n\n\t\t\t\t\tif ( !l ) {\n\t\t\t\t\t\treturn \"\";\n\t\t\t\t\t}\n\n\t\t\t\t\targs = new Array(l);\n\t\t\t\t\twhile ( l-- ) {\n\t\t\t\t\t\t// 97 is 'a'\n\t\t\t\t\t\targs[l] = String.fromCharCode(97+l);\n\t\t\t\t\t}\n\t\t\t\t\treturn \" \" + args.join( \", \" ) + \" \";\n\t\t\t\t},\n\t\t\t\t// object calls it internally, the key part of an item in a map\n\t\t\t\tkey: quote,\n\t\t\t\t// function calls it internally, it's the content of the function\n\t\t\t\tfunctionCode: \"[code]\",\n\t\t\t\t// node calls it internally, it's an html attribute value\n\t\t\t\tattribute: quote,\n\t\t\t\tstring: quote,\n\t\t\t\tdate: quote,\n\t\t\t\tregexp: literal,\n\t\t\t\tnumber: literal,\n\t\t\t\t\"boolean\": literal\n\t\t\t},\n\t\t\t// if true, entities are escaped ( <, >, \\t, space and \\n )\n\t\t\tHTML: false,\n\t\t\t// indentation unit\n\t\t\tindentChar: \"  \",\n\t\t\t// if true, items in a collection, are separated by a \\n, else just a space.\n\t\t\tmultiline: true\n\t\t};\n\n\treturn jsDump;\n}());\n\n// from jquery.js\nfunction inArray( elem, array ) {\n\tif ( array.indexOf ) {\n\t\treturn array.indexOf( elem );\n\t}\n\n\tfor ( var i = 0, length = array.length; i < length; i++ ) {\n\t\tif ( array[ i ] === elem ) {\n\t\t\treturn i;\n\t\t}\n\t}\n\n\treturn -1;\n}\n\n/*\n * Javascript Diff Algorithm\n *  By John Resig (http://ejohn.org/)\n *  Modified by Chu Alan \"sprite\"\n *\n * Released under the MIT license.\n *\n * More Info:\n *  http://ejohn.org/projects/javascript-diff-algorithm/\n *\n * Usage: QUnit.diff(expected, actual)\n *\n * QUnit.diff( \"the quick brown fox jumped over\", \"the quick fox jumps over\" ) == \"the  quick <del>brown </del> fox <del>jumped </del><ins>jumps </ins> over\"\n */\nQUnit.diff = (function() {\n\t/*jshint eqeqeq:false, eqnull:true */\n\tfunction diff( o, n ) {\n\t\tvar i,\n\t\t\tns = {},\n\t\t\tos = {};\n\n\t\tfor ( i = 0; i < n.length; i++ ) {\n\t\t\tif ( !hasOwn.call( ns, n[i] ) ) {\n\t\t\t\tns[ n[i] ] = {\n\t\t\t\t\trows: [],\n\t\t\t\t\to: null\n\t\t\t\t};\n\t\t\t}\n\t\t\tns[ n[i] ].rows.push( i );\n\t\t}\n\n\t\tfor ( i = 0; i < o.length; i++ ) {\n\t\t\tif ( !hasOwn.call( os, o[i] ) ) {\n\t\t\t\tos[ o[i] ] = {\n\t\t\t\t\trows: [],\n\t\t\t\t\tn: null\n\t\t\t\t};\n\t\t\t}\n\t\t\tos[ o[i] ].rows.push( i );\n\t\t}\n\n\t\tfor ( i in ns ) {\n\t\t\tif ( hasOwn.call( ns, i ) ) {\n\t\t\t\tif ( ns[i].rows.length === 1 && hasOwn.call( os, i ) && os[i].rows.length === 1 ) {\n\t\t\t\t\tn[ ns[i].rows[0] ] = {\n\t\t\t\t\t\ttext: n[ ns[i].rows[0] ],\n\t\t\t\t\t\trow: os[i].rows[0]\n\t\t\t\t\t};\n\t\t\t\t\to[ os[i].rows[0] ] = {\n\t\t\t\t\t\ttext: o[ os[i].rows[0] ],\n\t\t\t\t\t\trow: ns[i].rows[0]\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 < n.length - 1; i++ ) {\n\t\t\tif ( n[i].text != null && n[ i + 1 ].text == null && n[i].row + 1 < o.length && o[ n[i].row + 1 ].text == null &&\n\t\t\t\t\t\tn[ i + 1 ] == o[ n[i].row + 1 ] ) {\n\n\t\t\t\tn[ i + 1 ] = {\n\t\t\t\t\ttext: n[ i + 1 ],\n\t\t\t\t\trow: n[i].row + 1\n\t\t\t\t};\n\t\t\t\to[ n[i].row + 1 ] = {\n\t\t\t\t\ttext: o[ n[i].row + 1 ],\n\t\t\t\t\trow: i + 1\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\n\t\tfor ( i = n.length - 1; i > 0; i-- ) {\n\t\t\tif ( n[i].text != null && n[ i - 1 ].text == null && n[i].row > 0 && o[ n[i].row - 1 ].text == null &&\n\t\t\t\t\t\tn[ i - 1 ] == o[ n[i].row - 1 ]) {\n\n\t\t\t\tn[ i - 1 ] = {\n\t\t\t\t\ttext: n[ i - 1 ],\n\t\t\t\t\trow: n[i].row - 1\n\t\t\t\t};\n\t\t\t\to[ n[i].row - 1 ] = {\n\t\t\t\t\ttext: o[ n[i].row - 1 ],\n\t\t\t\t\trow: i - 1\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\n\t\treturn {\n\t\t\to: o,\n\t\t\tn: n\n\t\t};\n\t}\n\n\treturn function( o, n ) {\n\t\to = o.replace( /\\s+$/, \"\" );\n\t\tn = n.replace( /\\s+$/, \"\" );\n\n\t\tvar i, pre,\n\t\t\tstr = \"\",\n\t\t\tout = diff( o === \"\" ? [] : o.split(/\\s+/), n === \"\" ? [] : n.split(/\\s+/) ),\n\t\t\toSpace = o.match(/\\s+/g),\n\t\t\tnSpace = n.match(/\\s+/g);\n\n\t\tif ( oSpace == null ) {\n\t\t\toSpace = [ \" \" ];\n\t\t}\n\t\telse {\n\t\t\toSpace.push( \" \" );\n\t\t}\n\n\t\tif ( nSpace == null ) {\n\t\t\tnSpace = [ \" \" ];\n\t\t}\n\t\telse {\n\t\t\tnSpace.push( \" \" );\n\t\t}\n\n\t\tif ( out.n.length === 0 ) {\n\t\t\tfor ( i = 0; i < out.o.length; i++ ) {\n\t\t\t\tstr += \"<del>\" + out.o[i] + oSpace[i] + \"</del>\";\n\t\t\t}\n\t\t}\n\t\telse {\n\t\t\tif ( out.n[0].text == null ) {\n\t\t\t\tfor ( n = 0; n < out.o.length && out.o[n].text == null; n++ ) {\n\t\t\t\t\tstr += \"<del>\" + out.o[n] + oSpace[n] + \"</del>\";\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfor ( i = 0; i < out.n.length; i++ ) {\n\t\t\t\tif (out.n[i].text == null) {\n\t\t\t\t\tstr += \"<ins>\" + out.n[i] + nSpace[i] + \"</ins>\";\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\t// `pre` initialized at top of scope\n\t\t\t\t\tpre = \"\";\n\n\t\t\t\t\tfor ( n = out.n[i].row + 1; n < out.o.length && out.o[n].text == null; n++ ) {\n\t\t\t\t\t\tpre += \"<del>\" + out.o[n] + oSpace[n] + \"</del>\";\n\t\t\t\t\t}\n\t\t\t\t\tstr += \" \" + out.n[i].text + nSpace[i] + pre;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn str;\n\t};\n}());\n\n// for CommonJS environments, export everything\nif ( typeof exports !== \"undefined\" ) {\n\textend( exports, QUnit.constructor.prototype );\n}\n\n// get at whatever the global object is, like window in browsers\n}( (function() {return this;}.call()) ));\n"
  },
  {
    "path": "flowable-ui-web/modeler/libs/sizzle_1.10.16/test/unit/extending.js",
    "content": "module(\"extending\", { teardown: moduleTeardown });\n\ntest(\"custom pseudos\", function() {\n\texpect( 6 );\n\n\tSizzle.selectors.filters.foundation = Sizzle.selectors.filters.root;\n\tdeepEqual( Sizzle(\":foundation\"), [ document.documentElement ], \"Copy element filter with new name\" );\n\tdelete Sizzle.selectors.filters.foundation;\n\n\tSizzle.selectors.setFilters.primary = Sizzle.selectors.setFilters.first;\n\tt( \"Copy set filter with new name\", \"div:primary\", [\"qunit\"] );\n\tdelete Sizzle.selectors.setFilters.primary;\n\n\tSizzle.selectors.filters.aristotlean = Sizzle.selectors.createPseudo(function() {\n\t\treturn function( elem ) {\n\t\t\treturn !!elem.id;\n\t\t};\n\t});\n\tt( \"Custom element filter\", \"#foo :aristotlean\", [ \"sndp\", \"en\", \"yahoo\", \"sap\", \"anchor2\", \"simon\" ] );\n\tdelete Sizzle.selectors.filters.aristotlean;\n\n\tSizzle.selectors.filters.endswith = Sizzle.selectors.createPseudo(function( text ) {\n\t\treturn function( elem ) {\n\t\t\treturn Sizzle.getText( elem ).slice( -text.length ) === text;\n\t\t};\n\t});\n\tt( \"Custom element filter with argument\", \"a:endswith(ogle)\", [\"google\"] );\n\tdelete Sizzle.selectors.filters.endswith;\n\n\tSizzle.selectors.setFilters.second = Sizzle.selectors.createPseudo(function() {\n\t\treturn Sizzle.selectors.createPseudo(function( seed, matches ) {\n\t\t\tif ( seed[1] ) {\n\t\t\t\tmatches[1] = seed[1];\n\t\t\t\tseed[1] = false;\n\t\t\t}\n\t\t});\n\t});\n\tt( \"Custom set filter\", \"#qunit-fixture p:second\", [\"ap\"] );\n\tdelete Sizzle.selectors.filters.second;\n\n\tSizzle.selectors.setFilters.slice = Sizzle.selectors.createPseudo(function( argument ) {\n\t\tvar bounds = argument.split(\":\");\n\t\treturn Sizzle.selectors.createPseudo(function( seed, matches ) {\n\t\t\tvar i = bounds[1];\n\n\t\t\t// Match elements found at the specified indexes\n\t\t\twhile ( --i >= bounds[0] ) {\n\t\t\t\tif ( seed[i] ) {\n\t\t\t\t\tmatches[i] = seed[i];\n\t\t\t\t\tseed[i] = false;\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t});\n\tt( \"Custom set filter with argument\", \"#qunit-fixture p:slice(1:3)\", [ \"ap\", \"sndp\" ] );\n\tdelete Sizzle.selectors.filters.slice;\n});\n\ntest(\"backwards-compatible custom pseudos\", function() {\n\texpect( 3 );\n\n\tSizzle.selectors.filters.icontains = function( elem, i, match ) {\n\t\treturn Sizzle.getText( elem ).toLowerCase().indexOf( (match[3] || \"\").toLowerCase() ) > -1;\n\t};\n\tt( \"Custom element filter with argument\", \"a:icontains(THIS BLOG ENTRY)\", [\"simon1\"] );\n\tdelete Sizzle.selectors.filters.icontains;\n\n\tSizzle.selectors.setFilters.podium = function( elements, argument ) {\n\t\tvar count = argument == null || argument === \"\" ? 3 : +argument;\n\t\treturn elements.slice( 0, count );\n\t};\n\t// Using TAG as the first token here forces this setMatcher into a fail state\n\t// Where the descendent combinator was lost\n\tt( \"Custom setFilter\", \"form#form :PODIUM\", [\"label-for\", \"text1\", \"text2\"] );\n\tt( \"Custom setFilter with argument\", \"#form input:Podium(1)\", [\"text1\"] );\n\tdelete Sizzle.selectors.setFilters.podium;\n});\n\ntest(\"custom attribute getters\", function() {\n\texpect( 2 );\n\n\tvar original = Sizzle.selectors.attrHandle.hreflang,\n\t\tselector = \"a:contains('mark')[hreflang='http://diveintomark.org/en']\";\n\n\tSizzle.selectors.attrHandle.hreflang = function( elem, name ) {\n\t\tvar href = elem.getAttribute(\"href\"),\n\t\t\tlang = elem.getAttribute( name );\n\t\treturn lang && ( href + lang );\n\t};\n\n\tdeepEqual( Sizzle(selector, createWithFriesXML()), [], \"Custom attrHandle (preferred document)\" );\n\tt( \"Custom attrHandle (preferred document)\", selector, [\"mark\"] );\n\n\tSizzle.selectors.attrHandle.hreflang = original;\n});\n"
  },
  {
    "path": "flowable-ui-web/modeler/libs/sizzle_1.10.16/test/unit/selector.js",
    "content": "module(\"selector\", { teardown: moduleTeardown });\n\n// #### NOTE: ####\n// jQuery should not be used in this module\n// except for DOM manipulation\n// If jQuery is mandatory for the selection, move the test to jquery/test/unit/selector.js\n// Use t() or Sizzle()\n// ###############\n\n/*\n\t======== QUnit Reference ========\n\thttp://docs.jquery.com/QUnit\n\n\tTest methods:\n\t\texpect(numAssertions)\n\t\tstop()\n\t\tstart()\n\t\t\tnote: QUnit's eventual addition of an argument to stop/start is ignored in this test suite\n\t\t\tso that start and stop can be passed as callbacks without worrying about\n\t\t\t\ttheir parameters\n\tTest assertions:\n\t\tok(value, [message])\n\t\tequal(actual, expected, [message])\n\t\tnotEqual(actual, expected, [message])\n\t\tdeepEqual(actual, expected, [message])\n\t\tnotDeepEqual(actual, expected, [message])\n\t\tstrictEqual(actual, expected, [message])\n\t\tnotStrictEqual(actual, expected, [message])\n\t\traises(block, [expected], [message])\n\n\t======== testinit.js reference ========\n\tSee data/testinit.js\n\n\tq(...);\n\t\tReturns an array of elements with the given IDs\n\t\t@example q(\"main\", \"foo\", \"bar\") => [<div id=\"main\">, <span id=\"foo\">, <input id=\"bar\">]\n\n\tt( testName, selector, [ \"array\", \"of\", \"ids\" ] );\n\t\tAsserts that a select matches the given IDs\n\t\t@example t(\"Check for something\", \"//[a]\", [\"foo\", \"baar\"]);\n\n\turl( \"some/url.php\" );\n\t\tAdd random number to url to stop caching\n\t\t@example url(\"data/test.html\") => \"data/test.html?10538358428943\"\n\t\t@example url(\"data/test.php?foo=bar\") => \"data/test.php?foo=bar&10538358345554\"\n*/\n\ntest(\"element\", function() {\n\texpect( 39 );\n\n\tvar form, all, good, i, obj1, lengthtest,\n\t\tsiblingTest, siblingNext, iframe, iframeDoc, html;\n\n\tequal( Sizzle(\"\").length, 0, \"Empty selector returns an empty array\" );\n\tdeepEqual( Sizzle(\"div\", document.createTextNode(\"\")), [], \"Text element as context fails silently\" );\n\tform = document.getElementById(\"form\");\n\tok( !Sizzle.matchesSelector( form, \"\" ), \"Empty string passed to matchesSelector does not match\" );\n\tequal( Sizzle(\" \").length, 0, \"Empty selector returns an empty array\" );\n\tequal( Sizzle(\"\\t\").length, 0, \"Empty selector returns an empty array\" );\n\n\tok( Sizzle(\"*\").length >= 30, \"Select all\" );\n\tall = Sizzle(\"*\");\n\tgood = true;\n\tfor ( i = 0; i < all.length; i++ ) {\n\t\tif ( all[i].nodeType === 8 ) {\n\t\t\tgood = false;\n\t\t}\n\t}\n\tok( good, \"Select all elements, no comment nodes\" );\n\tt( \"Element Selector\", \"html\", [\"html\"] );\n\tt( \"Element Selector\", \"body\", [\"body\"] );\n\tt( \"Element Selector\", \"#qunit-fixture p\", [\"firstp\",\"ap\",\"sndp\",\"en\",\"sap\",\"first\"] );\n\n\tt( \"Leading space\", \" #qunit-fixture p\", [\"firstp\",\"ap\",\"sndp\",\"en\",\"sap\",\"first\"] );\n\tt( \"Leading tab\", \"\\t#qunit-fixture p\", [\"firstp\",\"ap\",\"sndp\",\"en\",\"sap\",\"first\"] );\n\tt( \"Leading carriage return\", \"\\r#qunit-fixture p\", [\"firstp\",\"ap\",\"sndp\",\"en\",\"sap\",\"first\"] );\n\tt( \"Leading line feed\", \"\\n#qunit-fixture p\", [\"firstp\",\"ap\",\"sndp\",\"en\",\"sap\",\"first\"] );\n\tt( \"Leading form feed\", \"\\f#qunit-fixture p\", [\"firstp\",\"ap\",\"sndp\",\"en\",\"sap\",\"first\"] );\n\tt( \"Trailing space\", \"#qunit-fixture p \", [\"firstp\",\"ap\",\"sndp\",\"en\",\"sap\",\"first\"] );\n\tt( \"Trailing tab\", \"#qunit-fixture p\\t\", [\"firstp\",\"ap\",\"sndp\",\"en\",\"sap\",\"first\"] );\n\tt( \"Trailing carriage return\", \"#qunit-fixture p\\r\", [\"firstp\",\"ap\",\"sndp\",\"en\",\"sap\",\"first\"] );\n\tt( \"Trailing line feed\", \"#qunit-fixture p\\n\", [\"firstp\",\"ap\",\"sndp\",\"en\",\"sap\",\"first\"] );\n\tt( \"Trailing form feed\", \"#qunit-fixture p\\f\", [\"firstp\",\"ap\",\"sndp\",\"en\",\"sap\",\"first\"] );\n\n\tt( \"Parent Element\", \"dl ol\", [\"empty\", \"listWithTabIndex\"] );\n\tt( \"Parent Element (non-space descendant combinator)\", \"dl\\tol\", [\"empty\", \"listWithTabIndex\"] );\n\tobj1 = document.getElementById(\"object1\");\n\tequal( Sizzle(\"param\", obj1).length, 2, \"Object/param as context\" );\n\n\tdeepEqual( Sizzle(\"select\", form), q(\"select1\",\"select2\",\"select3\",\"select4\",\"select5\"), \"Finding selects with a context.\" );\n\n\t// Check for unique-ness and sort order\n\tdeepEqual( Sizzle(\"p, div p\"), Sizzle(\"p\"), \"Check for duplicates: p, div p\" );\n\n\tt( \"Checking sort order\", \"h2, h1\", [\"qunit-header\", \"qunit-banner\", \"qunit-userAgent\"] );\n\tt( \"Checking sort order\", \"h2:first, h1:first\", [\"qunit-header\", \"qunit-banner\"] );\n\tt( \"Checking sort order\", \"#qunit-fixture p, #qunit-fixture p a\", [\"firstp\", \"simon1\", \"ap\", \"google\", \"groups\", \"anchor1\", \"mark\", \"sndp\", \"en\", \"yahoo\", \"sap\", \"anchor2\", \"simon\", \"first\"] );\n\n\t// Test Conflict ID\n\tlengthtest = document.getElementById(\"lengthtest\");\n\tdeepEqual( Sizzle(\"#idTest\", lengthtest), q(\"idTest\"), \"Finding element with id of ID.\" );\n\tdeepEqual( Sizzle(\"[name='id']\", lengthtest), q(\"idTest\"), \"Finding element with id of ID.\" );\n\tdeepEqual( Sizzle(\"input[id='idTest']\", lengthtest), q(\"idTest\"), \"Finding elements with id of ID.\" );\n\n\tsiblingTest = document.getElementById(\"siblingTest\");\n\tdeepEqual( Sizzle(\"div em\", siblingTest), [], \"Element-rooted QSA does not select based on document context\" );\n\tdeepEqual( Sizzle(\"div em, div em, div em:not(div em)\", siblingTest), [], \"Element-rooted QSA does not select based on document context\" );\n\tdeepEqual( Sizzle(\"div em, em\\\\,\", siblingTest), [], \"Escaped commas do not get treated with an id in element-rooted QSA\" );\n\n\tsiblingNext = document.getElementById(\"siblingnext\");\n\tdocument.createDocumentFragment().appendChild( siblingTest );\n\tdeepEqual( Sizzle( \"em + :not(:has(*)):not(:empty), foo\", siblingTest ), [ siblingNext ],\n\t\t\"Non-qSA path correctly sets detached context for sibling selectors (jQuery #14351)\" );\n\n\tiframe = document.getElementById(\"iframe\"),\n\t\tiframeDoc = iframe.contentDocument || iframe.contentWindow.document;\n\tiframeDoc.open();\n\tiframeDoc.write(\"<body><p id='foo'>bar</p></body>\");\n\tiframeDoc.close();\n\tdeepEqual(\n\t\tSizzle( \"p:contains(bar)\", iframeDoc ),\n\t\t[ iframeDoc.getElementById(\"foo\") ],\n\t\t\"Other document as context\"\n\t);\n\n\thtml = \"\";\n\tfor ( i = 0; i < 100; i++ ) {\n\t\thtml = \"<div>\" + html + \"</div>\";\n\t}\n\thtml = jQuery( html ).appendTo( document.body );\n\tok( !!Sizzle(\"body div div div\").length, \"No stack or performance problems with large amounts of descendents\" );\n\tok( !!Sizzle(\"body>div div div\").length, \"No stack or performance problems with large amounts of descendents\" );\n\thtml.remove();\n\n\t// Real use case would be using .watch in browsers with window.watch (see Issue #157)\n\tq(\"qunit-fixture\")[0].appendChild( document.createElement(\"toString\") ).id = \"toString\";\n\tt( \"Element name matches Object.prototype property\", \"toString#toString\", [\"toString\"] );\n});\n\ntest(\"XML Document Selectors\", function() {\n\tvar xml = createWithFriesXML();\n\texpect( 11 );\n\n\tequal( Sizzle(\"foo_bar\", xml).length, 1, \"Element Selector with underscore\" );\n\tequal( Sizzle(\".component\", xml).length, 1, \"Class selector\" );\n\tequal( Sizzle(\"[class*=component]\", xml).length, 1, \"Attribute selector for class\" );\n\tequal( Sizzle(\"property[name=prop2]\", xml).length, 1, \"Attribute selector with name\" );\n\tequal( Sizzle(\"[name=prop2]\", xml).length, 1, \"Attribute selector with name\" );\n\tequal( Sizzle(\"#seite1\", xml).length, 1, \"Attribute selector with ID\" );\n\tequal( Sizzle(\"component#seite1\", xml).length, 1, \"Attribute selector with ID\" );\n\tequal( Sizzle.matches( \"#seite1\", Sizzle(\"component\", xml) ).length, 1, \"Attribute selector filter with ID\" );\n\tequal( Sizzle(\"meta property thing\", xml).length, 2, \"Descendent selector and dir caching\" );\n\tok( Sizzle.matchesSelector( xml.lastChild, \"soap\\\\:Envelope\" ), \"Check for namespaced element\" );\n\n\txml = jQuery.parseXML(\"<?xml version='1.0' encoding='UTF-8'?><root><elem id='1'/></root>\");\n\tequal( Sizzle( \"elem:not(:has(*))\", xml ).length, 1,\n\t\t\"Non-qSA path correctly handles numeric ids (jQuery #14142)\" );\n});\n\ntest(\"broken\", function() {\n\texpect( 26 );\n\n\tvar attrbad,\n\t\tbroken = function( name, selector ) {\n\t\t\traises(function() {\n\t\t\t\t// Setting context to null here somehow avoids QUnit's window.error handling\n\t\t\t\t// making the e & e.message correct\n\t\t\t\t// For whatever reason, without this,\n\t\t\t\t// Sizzle.error will be called but no error will be seen in oldIE\n\t\t\t\tSizzle.call( null, selector );\n\t\t\t}, function( e ) {\n\t\t\t\treturn e.message.indexOf(\"Syntax error\") >= 0;\n\t\t\t}, name + \": \" + selector );\n\t\t};\n\n\tbroken( \"Broken Selector\", \"[\" );\n\tbroken( \"Broken Selector\", \"(\" );\n\tbroken( \"Broken Selector\", \"{\" );\n\tbroken( \"Broken Selector\", \"<\" );\n\tbroken( \"Broken Selector\", \"()\" );\n\tbroken( \"Broken Selector\", \"<>\" );\n\tbroken( \"Broken Selector\", \"{}\" );\n\tbroken( \"Broken Selector\", \",\" );\n\tbroken( \"Broken Selector\", \",a\" );\n\tbroken( \"Broken Selector\", \"a,\" );\n\t// Hangs on IE 9 if regular expression is inefficient\n\tbroken( \"Broken Selector\", \"[id=012345678901234567890123456789\");\n\tbroken( \"Doesn't exist\", \":visble\" );\n\tbroken( \"Nth-child\", \":nth-child\" );\n\t// Sigh again. IE 9 thinks this is also a real selector\n\t// not super critical that we fix this case\n\t//broken( \"Nth-child\", \":nth-child(-)\" );\n\t// Sigh. WebKit thinks this is a real selector in qSA\n\t// They've already fixed this and it'll be coming into\n\t// current browsers soon. Currently, Safari 5.0 still has this problem\n\t// broken( \"Nth-child\", \":nth-child(asdf)\", [] );\n\tbroken( \"Nth-child\", \":nth-child(2n+-0)\" );\n\tbroken( \"Nth-child\", \":nth-child(2+0)\" );\n\tbroken( \"Nth-child\", \":nth-child(- 1n)\" );\n\tbroken( \"Nth-child\", \":nth-child(-1 n)\" );\n\tbroken( \"First-child\", \":first-child(n)\" );\n\tbroken( \"Last-child\", \":last-child(n)\" );\n\tbroken( \"Only-child\", \":only-child(n)\" );\n\tbroken( \"Nth-last-last-child\", \":nth-last-last-child(1)\" );\n\tbroken( \"First-last-child\", \":first-last-child\" );\n\tbroken( \"Last-last-child\", \":last-last-child\" );\n\tbroken( \"Only-last-child\", \":only-last-child\" );\n\n\t// Make sure attribute value quoting works correctly. See: #6093\n\tattrbad = jQuery(\"<input type='hidden' value='2' name='foo.baz' id='attrbad1'/><input type='hidden' value='2' name='foo[baz]' id='attrbad2'/>\").appendTo(\"#qunit-fixture\");\n\n\tbroken( \"Attribute not escaped\", \"input[name=foo.baz]\", [] );\n\t// Shouldn't be matching those inner brackets\n\tbroken( \"Attribute not escaped\", \"input[name=foo[baz]]\", [] );\n});\n\ntest(\"id\", function() {\n\texpect( 34 );\n\n\tvar fiddle, a;\n\n\tt( \"ID Selector\", \"#body\", [\"body\"] );\n\tt( \"ID Selector w/ Element\", \"body#body\", [\"body\"] );\n\tt( \"ID Selector w/ Element\", \"ul#first\", [] );\n\tt( \"ID selector with existing ID descendant\", \"#firstp #simon1\", [\"simon1\"] );\n\tt( \"ID selector with non-existant descendant\", \"#firstp #foobar\", [] );\n\tt( \"ID selector using UTF8\", \"#台北Táiběi\", [\"台北Táiběi\"] );\n\tt( \"Multiple ID selectors using UTF8\", \"#台北Táiběi, #台北\", [\"台北Táiběi\",\"台北\"] );\n\tt( \"Descendant ID selector using UTF8\", \"div #台北\", [\"台北\"] );\n\tt( \"Child ID selector using UTF8\", \"form > #台北\", [\"台北\"] );\n\n\tt( \"Escaped ID\", \"#foo\\\\:bar\", [\"foo:bar\"] );\n\tt( \"Escaped ID with descendent\", \"#foo\\\\:bar span:not(:input)\", [\"foo_descendent\"] );\n\tt( \"Escaped ID\", \"#test\\\\.foo\\\\[5\\\\]bar\", [\"test.foo[5]bar\"] );\n\tt( \"Descendant escaped ID\", \"div #foo\\\\:bar\", [\"foo:bar\"] );\n\tt( \"Descendant escaped ID\", \"div #test\\\\.foo\\\\[5\\\\]bar\", [\"test.foo[5]bar\"] );\n\tt( \"Child escaped ID\", \"form > #foo\\\\:bar\", [\"foo:bar\"] );\n\tt( \"Child escaped ID\", \"form > #test\\\\.foo\\\\[5\\\\]bar\", [\"test.foo[5]bar\"] );\n\n\tfiddle = jQuery(\"<div id='fiddle\\\\Foo'><span id='fiddleSpan'></span></div>\").appendTo(\"#qunit-fixture\");\n\tdeepEqual( Sizzle( \"> span\", Sizzle(\"#fiddle\\\\\\\\Foo\")[0] ), q([ \"fiddleSpan\" ]), \"Escaped ID as context\" );\n\tfiddle.remove();\n\n\tt( \"ID Selector, child ID present\", \"#form > #radio1\", [\"radio1\"] ); // bug #267\n\tt( \"ID Selector, not an ancestor ID\", \"#form #first\", [] );\n\tt( \"ID Selector, not a child ID\", \"#form > #option1a\", [] );\n\n\tt( \"All Children of ID\", \"#foo > *\", [\"sndp\", \"en\", \"sap\"] );\n\tt( \"All Children of ID with no children\", \"#firstUL > *\", [] );\n\n\tequal( Sizzle(\"#tName1\")[0].id, \"tName1\", \"ID selector with same value for a name attribute\" );\n\tt( \"ID selector non-existing but name attribute on an A tag\",         \"#tName2\",      [] );\n\tt( \"Leading ID selector non-existing but name attribute on an A tag\", \"#tName2 span\", [] );\n\tt( \"Leading ID selector existing, retrieving the child\",              \"#tName1 span\", [\"tName1-span\"] );\n\tequal( Sizzle(\"div > div #tName1\")[0].id, Sizzle(\"#tName1-span\")[0].parentNode.id, \"Ending with ID\" );\n\n\ta = jQuery(\"<a id='backslash\\\\foo'></a>\").appendTo(\"#qunit-fixture\");\n\tt( \"ID Selector contains backslash\", \"#backslash\\\\\\\\foo\", [\"backslash\\\\foo\"] );\n\n\tt( \"ID Selector on Form with an input that has a name of 'id'\", \"#lengthtest\", [\"lengthtest\"] );\n\n\tt( \"ID selector with non-existant ancestor\", \"#asdfasdf #foobar\", [] ); // bug #986\n\n\tdeepEqual( Sizzle(\"div#form\", document.body), [], \"ID selector within the context of another element\" );\n\n\tt( \"Underscore ID\", \"#types_all\", [\"types_all\"] );\n\tt( \"Dash ID\", \"#qunit-fixture\", [\"qunit-fixture\"] );\n\n\tt( \"ID with weird characters in it\", \"#name\\\\+value\", [\"name+value\"] );\n});\n\ntest(\"class\", function() {\n\texpect( 26 );\n\n\tt( \"Class Selector\", \".blog\", [\"mark\",\"simon\"] );\n\tt( \"Class Selector\", \".GROUPS\", [\"groups\"] );\n\tt( \"Class Selector\", \".blog.link\", [\"simon\"] );\n\tt( \"Class Selector w/ Element\", \"a.blog\", [\"mark\",\"simon\"] );\n\tt( \"Parent Class Selector\", \"p .blog\", [\"mark\",\"simon\"] );\n\n\tt( \"Class selector using UTF8\", \".台北Táiběi\", [\"utf8class1\"] );\n\t//t( \"Class selector using UTF8\", \".台北\", [\"utf8class1\",\"utf8class2\"] );\n\tt( \"Class selector using UTF8\", \".台北Táiběi.台北\", [\"utf8class1\"] );\n\tt( \"Class selector using UTF8\", \".台北Táiběi, .台北\", [\"utf8class1\",\"utf8class2\"] );\n\tt( \"Descendant class selector using UTF8\", \"div .台北Táiběi\", [\"utf8class1\"] );\n\tt( \"Child class selector using UTF8\", \"form > .台北Táiběi\", [\"utf8class1\"] );\n\n\tt( \"Escaped Class\", \".foo\\\\:bar\", [\"foo:bar\"] );\n\tt( \"Escaped Class\", \".test\\\\.foo\\\\[5\\\\]bar\", [\"test.foo[5]bar\"] );\n\tt( \"Descendant escaped Class\", \"div .foo\\\\:bar\", [\"foo:bar\"] );\n\tt( \"Descendant escaped Class\", \"div .test\\\\.foo\\\\[5\\\\]bar\", [\"test.foo[5]bar\"] );\n\tt( \"Child escaped Class\", \"form > .foo\\\\:bar\", [\"foo:bar\"] );\n\tt( \"Child escaped Class\", \"form > .test\\\\.foo\\\\[5\\\\]bar\", [\"test.foo[5]bar\"] );\n\n\tvar div = document.createElement(\"div\");\n\tdiv.innerHTML = \"<div class='test e'></div><div class='test'></div>\";\n\tdeepEqual( Sizzle(\".e\", div), [ div.firstChild ], \"Finding a second class.\" );\n\n\tdiv.lastChild.className = \"e\";\n\n\tdeepEqual( Sizzle(\".e\", div), [ div.firstChild, div.lastChild ], \"Finding a modified class.\" );\n\n\tok( !Sizzle.matchesSelector( div, \".null\"), \".null does not match an element with no class\" );\n\tok( !Sizzle.matchesSelector( div.firstChild, \".null div\"), \".null does not match an element with no class\" );\n\tdiv.className = \"null\";\n\tok( Sizzle.matchesSelector( div, \".null\"), \".null matches element with class 'null'\" );\n\tok( Sizzle.matchesSelector( div.firstChild, \".null div\"), \"caching system respects DOM changes\" );\n\tok( !Sizzle.matchesSelector( document, \".foo\" ), \"testing class on document doesn't error\" );\n\tok( !Sizzle.matchesSelector( window, \".foo\" ), \"testing class on window doesn't error\" );\n\n\tdiv.lastChild.className += \" hasOwnProperty toString\";\n\tdeepEqual( Sizzle(\".e.hasOwnProperty.toString\", div), [ div.lastChild ], \"Classes match Object.prototype properties\" );\n\n\tdiv = jQuery(\"<div><svg width='200' height='250' version='1.1' xmlns='http://www.w3.org/2000/svg'><rect x='10' y='10' width='30' height='30' class='foo'></rect></svg></div>\")[0];\n\tequal( Sizzle(\".foo\", div).length, 1, \"Class selector against SVG\" );\n});\n\ntest(\"name\", function() {\n\texpect( 14 );\n\n\tvar form;\n\n\tt( \"Name selector\", \"input[name=action]\", [\"text1\"] );\n\tt( \"Name selector with single quotes\", \"input[name='action']\", [\"text1\"] );\n\tt( \"Name selector with double quotes\", \"input[name=\\\"action\\\"]\", [\"text1\"] );\n\n\tt( \"Name selector non-input\", \"[name=example]\", [\"name-is-example\"] );\n\tt( \"Name selector non-input\", \"[name=div]\", [\"name-is-div\"] );\n\tt( \"Name selector non-input\", \"*[name=iframe]\", [\"iframe\"] );\n\n\tt( \"Name selector for grouped input\", \"input[name='types[]']\", [\"types_all\", \"types_anime\", \"types_movie\"] );\n\n\tform = document.getElementById(\"form\");\n\tdeepEqual( Sizzle(\"input[name=action]\", form), q(\"text1\"), \"Name selector within the context of another element\" );\n\tdeepEqual( Sizzle(\"input[name='foo[bar]']\", form), q(\"hidden2\"), \"Name selector for grouped form element within the context of another element\" );\n\n\tform = jQuery(\"<form><input name='id'/></form>\").appendTo(\"body\");\n\tequal( Sizzle(\"input\", form[0]).length, 1, \"Make sure that rooted queries on forms (with possible expandos) work.\" );\n\n\tform.remove();\n\n\tt( \"Find elements that have similar IDs\", \"[name=tName1]\", [\"tName1ID\"] );\n\tt( \"Find elements that have similar IDs\", \"[name=tName2]\", [\"tName2ID\"] );\n\tt( \"Find elements that have similar IDs\", \"#tName2ID\", [\"tName2ID\"] );\n\n\tt( \"Case-sensitivity\", \"[name=tname1]\", [] );\n});\n\ntest(\"multiple\", function() {\n\texpect(6);\n\n\tt( \"Comma Support\", \"h2, #qunit-fixture p\", [\"qunit-banner\",\"qunit-userAgent\",\"firstp\",\"ap\",\"sndp\",\"en\",\"sap\",\"first\"] );\n\tt( \"Comma Support\", \"h2 , #qunit-fixture p\", [\"qunit-banner\",\"qunit-userAgent\",\"firstp\",\"ap\",\"sndp\",\"en\",\"sap\",\"first\"] );\n\tt( \"Comma Support\", \"h2 , #qunit-fixture p\", [\"qunit-banner\",\"qunit-userAgent\",\"firstp\",\"ap\",\"sndp\",\"en\",\"sap\",\"first\"] );\n\tt( \"Comma Support\", \"h2,#qunit-fixture p\", [\"qunit-banner\",\"qunit-userAgent\",\"firstp\",\"ap\",\"sndp\",\"en\",\"sap\",\"first\"] );\n\tt( \"Comma Support\", \"h2,#qunit-fixture p \", [\"qunit-banner\",\"qunit-userAgent\",\"firstp\",\"ap\",\"sndp\",\"en\",\"sap\",\"first\"] );\n\tt( \"Comma Support\", \"h2\\t,\\r#qunit-fixture p\\n\", [\"qunit-banner\",\"qunit-userAgent\",\"firstp\",\"ap\",\"sndp\",\"en\",\"sap\",\"first\"] );\n});\n\ntest(\"child and adjacent\", function() {\n\texpect( 42 );\n\n\tvar siblingFirst, en, nothiddendiv;\n\n\tt( \"Child\", \"p > a\", [\"simon1\",\"google\",\"groups\",\"mark\",\"yahoo\",\"simon\"] );\n\tt( \"Child\", \"p> a\", [\"simon1\",\"google\",\"groups\",\"mark\",\"yahoo\",\"simon\"] );\n\tt( \"Child\", \"p >a\", [\"simon1\",\"google\",\"groups\",\"mark\",\"yahoo\",\"simon\"] );\n\tt( \"Child\", \"p>a\", [\"simon1\",\"google\",\"groups\",\"mark\",\"yahoo\",\"simon\"] );\n\tt( \"Child w/ Class\", \"p > a.blog\", [\"mark\",\"simon\"] );\n\tt( \"All Children\", \"code > *\", [\"anchor1\",\"anchor2\"] );\n\tt( \"All Grandchildren\", \"p > * > *\", [\"anchor1\",\"anchor2\"] );\n\tt( \"Adjacent\", \"#qunit-fixture a + a\", [\"groups\", \"tName2ID\"] );\n\tt( \"Adjacent\", \"#qunit-fixture a +a\", [\"groups\", \"tName2ID\"] );\n\tt( \"Adjacent\", \"#qunit-fixture a+ a\", [\"groups\", \"tName2ID\"] );\n\tt( \"Adjacent\", \"#qunit-fixture a+a\", [\"groups\", \"tName2ID\"] );\n\tt( \"Adjacent\", \"p + p\", [\"ap\",\"en\",\"sap\"] );\n\tt( \"Adjacent\", \"p#firstp + p\", [\"ap\"] );\n\tt( \"Adjacent\", \"p[lang=en] + p\", [\"sap\"] );\n\tt( \"Adjacent\", \"a.GROUPS + code + a\", [\"mark\"] );\n\tt( \"Comma, Child, and Adjacent\", \"#qunit-fixture a + a, code > a\", [\"groups\",\"anchor1\",\"anchor2\",\"tName2ID\"] );\n\tt( \"Element Preceded By\", \"#qunit-fixture p ~ div\", [\"foo\", \"nothiddendiv\", \"moretests\",\"tabindex-tests\", \"liveHandlerOrder\", \"siblingTest\"] );\n\tt( \"Element Preceded By\", \"#first ~ div\", [\"moretests\",\"tabindex-tests\", \"liveHandlerOrder\", \"siblingTest\"] );\n\tt( \"Element Preceded By\", \"#groups ~ a\", [\"mark\"] );\n\tt( \"Element Preceded By\", \"#length ~ input\", [\"idTest\"] );\n\tt( \"Element Preceded By\", \"#siblingfirst ~ em\", [\"siblingnext\", \"siblingthird\"] );\n\tt( \"Element Preceded By (multiple)\", \"#siblingTest em ~ em ~ em ~ span\", [\"siblingspan\"] );\n\tt( \"Element Preceded By, Containing\", \"#liveHandlerOrder ~ div em:contains('1')\", [\"siblingfirst\"] );\n\n\tsiblingFirst = document.getElementById(\"siblingfirst\");\n\n\tdeepEqual( Sizzle(\"~ em\", siblingFirst), q(\"siblingnext\", \"siblingthird\"), \"Element Preceded By with a context.\" );\n\tdeepEqual( Sizzle(\"+ em\", siblingFirst), q(\"siblingnext\"), \"Element Directly Preceded By with a context.\" );\n\tdeepEqual( Sizzle(\"~ em:first\", siblingFirst), q(\"siblingnext\"), \"Element Preceded By positional with a context.\" );\n\n\ten = document.getElementById(\"en\");\n\tdeepEqual( Sizzle(\"+ p, a\", en), q(\"yahoo\", \"sap\"), \"Compound selector with context, beginning with sibling test.\" );\n\tdeepEqual( Sizzle(\"a, + p\", en), q(\"yahoo\", \"sap\"), \"Compound selector with context, containing sibling test.\" );\n\n\tt( \"Multiple combinators selects all levels\", \"#siblingTest em *\", [\"siblingchild\", \"siblinggrandchild\", \"siblinggreatgrandchild\"] );\n\tt( \"Multiple combinators selects all levels\", \"#siblingTest > em *\", [\"siblingchild\", \"siblinggrandchild\", \"siblinggreatgrandchild\"] );\n\tt( \"Multiple sibling combinators doesn't miss general siblings\", \"#siblingTest > em:first-child + em ~ span\", [\"siblingspan\"] );\n\tt( \"Combinators are not skipped when mixing general and specific\", \"#siblingTest > em:contains('x') + em ~ span\", [] );\n\n\tequal( Sizzle(\"#listWithTabIndex\").length, 1, \"Parent div for next test is found via ID (#8310)\" );\n\tequal( Sizzle(\"#listWithTabIndex li:eq(2) ~ li\").length, 1, \"Find by general sibling combinator (#8310)\" );\n\tequal( Sizzle(\"#__sizzle__\").length, 0, \"Make sure the temporary id assigned by sizzle is cleared out (#8310)\" );\n\tequal( Sizzle(\"#listWithTabIndex\").length, 1, \"Parent div for previous test is still found via ID (#8310)\" );\n\n\tt( \"Verify deep class selector\", \"div.blah > p > a\", [] );\n\n\tt( \"No element deep selector\", \"div.foo > span > a\", [] );\n\n\tnothiddendiv = document.getElementById(\"nothiddendiv\");\n\tdeepEqual( Sizzle(\"> :first\", nothiddendiv), q(\"nothiddendivchild\"), \"Verify child context positional selector\" );\n\tdeepEqual( Sizzle(\"> :eq(0)\", nothiddendiv), q(\"nothiddendivchild\"), \"Verify child context positional selector\" );\n\tdeepEqual( Sizzle(\"> *:first\", nothiddendiv), q(\"nothiddendivchild\"), \"Verify child context positional selector\" );\n\n\tt( \"Non-existant ancestors\", \".fototab > .thumbnails > a\", [] );\n});\n\ntest(\"attributes\", function() {\n\texpect( 76 );\n\n\tvar opt, input, attrbad, div;\n\n\tt( \"Attribute Exists\", \"#qunit-fixture a[title]\", [\"google\"] );\n\tt( \"Attribute Exists (case-insensitive)\", \"#qunit-fixture a[TITLE]\", [\"google\"] );\n\tt( \"Attribute Exists\", \"#qunit-fixture *[title]\", [\"google\"] );\n\tt( \"Attribute Exists\", \"#qunit-fixture [title]\", [\"google\"] );\n\tt( \"Attribute Exists\", \"#qunit-fixture a[ title ]\", [\"google\"] );\n\n\tt( \"Boolean attribute exists\", \"#select2 option[selected]\", [\"option2d\"]);\n\tt( \"Boolean attribute equals\", \"#select2 option[selected='selected']\", [\"option2d\"]);\n\n\tt( \"Attribute Equals\", \"#qunit-fixture a[rel='bookmark']\", [\"simon1\"] );\n\tt( \"Attribute Equals\", \"#qunit-fixture a[rel='bookmark']\", [\"simon1\"] );\n\tt( \"Attribute Equals\", \"#qunit-fixture a[rel=bookmark]\", [\"simon1\"] );\n\tt( \"Attribute Equals\", \"#qunit-fixture a[href='http://www.google.com/']\", [\"google\"] );\n\tt( \"Attribute Equals\", \"#qunit-fixture a[ rel = 'bookmark' ]\", [\"simon1\"] );\n\tt( \"Attribute Equals Number\", \"#qunit-fixture option[value=1]\", [\"option1b\",\"option2b\",\"option3b\",\"option4b\",\"option5c\"] );\n\tt( \"Attribute Equals Number\", \"#qunit-fixture li[tabIndex=-1]\", [\"foodWithNegativeTabIndex\"] );\n\n\tdocument.getElementById(\"anchor2\").href = \"#2\";\n\tt( \"href Attribute\", \"p a[href^=#]\", [\"anchor2\"] );\n\tt( \"href Attribute\", \"p a[href*=#]\", [\"simon1\", \"anchor2\"] );\n\n\tt( \"for Attribute\", \"form label[for]\", [\"label-for\"] );\n\tt( \"for Attribute in form\", \"#form [for=action]\", [\"label-for\"] );\n\n\tt( \"Attribute containing []\", \"input[name^='foo[']\", [\"hidden2\"] );\n\tt( \"Attribute containing []\", \"input[name^='foo[bar]']\", [\"hidden2\"] );\n\tt( \"Attribute containing []\", \"input[name*='[bar]']\", [\"hidden2\"] );\n\tt( \"Attribute containing []\", \"input[name$='bar]']\", [\"hidden2\"] );\n\tt( \"Attribute containing []\", \"input[name$='[bar]']\", [\"hidden2\"] );\n\tt( \"Attribute containing []\", \"input[name$='foo[bar]']\", [\"hidden2\"] );\n\tt( \"Attribute containing []\", \"input[name*='foo[bar]']\", [\"hidden2\"] );\n\n\tdeepEqual( Sizzle( \"input[data-comma='0,1']\" ), [ document.getElementById(\"el12087\") ], \"Without context, single-quoted attribute containing ','\" );\n\tdeepEqual( Sizzle( \"input[data-comma=\\\"0,1\\\"]\" ), [ document.getElementById(\"el12087\") ], \"Without context, double-quoted attribute containing ','\" );\n\tdeepEqual( Sizzle( \"input[data-comma='0,1']\", document.getElementById(\"t12087\") ), [ document.getElementById(\"el12087\") ], \"With context, single-quoted attribute containing ','\" );\n\tdeepEqual( Sizzle( \"input[data-comma=\\\"0,1\\\"]\", document.getElementById(\"t12087\") ), [ document.getElementById(\"el12087\") ], \"With context, double-quoted attribute containing ','\" );\n\n\tt( \"Multiple Attribute Equals\", \"#form input[type='radio'], #form input[type='hidden']\", [\"radio1\", \"radio2\", \"hidden1\"] );\n\tt( \"Multiple Attribute Equals\", \"#form input[type='radio'], #form input[type=\\\"hidden\\\"]\", [\"radio1\", \"radio2\", \"hidden1\"] );\n\tt( \"Multiple Attribute Equals\", \"#form input[type='radio'], #form input[type=hidden]\", [\"radio1\", \"radio2\", \"hidden1\"] );\n\n\tt( \"Attribute selector using UTF8\", \"span[lang=中文]\", [\"台北\"] );\n\n\tt( \"Attribute Begins With\", \"a[href ^= 'http://www']\", [\"google\",\"yahoo\"] );\n\tt( \"Attribute Ends With\", \"a[href $= 'org/']\", [\"mark\"] );\n\tt( \"Attribute Contains\", \"a[href *= 'google']\", [\"google\",\"groups\"] );\n\tt( \"Attribute Is Not Equal\", \"#ap a[hreflang!='en']\", [\"google\",\"groups\",\"anchor1\"] );\n\n\topt = document.getElementById(\"option1a\");\n\topt.setAttribute( \"test\", \"\" );\n\n\tok( Sizzle.matchesSelector( opt, \"[id*=option1][type!=checkbox]\" ), \"Attribute Is Not Equal Matches\" );\n\tok( Sizzle.matchesSelector( opt, \"[id*=option1]\" ), \"Attribute With No Quotes Contains Matches\" );\n\tok( Sizzle.matchesSelector( opt, \"[test=]\" ), \"Attribute With No Quotes No Content Matches\" );\n\tok( !Sizzle.matchesSelector( opt, \"[test^='']\" ), \"Attribute with empty string value does not match startsWith selector (^=)\" );\n\tok( Sizzle.matchesSelector( opt, \"[id=option1a]\" ), \"Attribute With No Quotes Equals Matches\" );\n\tok( Sizzle.matchesSelector( document.getElementById(\"simon1\"), \"a[href*=#]\" ), \"Attribute With No Quotes Href Contains Matches\" );\n\n\tt( \"Empty values\", \"#select1 option[value='']\", [\"option1a\"] );\n\tt( \"Empty values\", \"#select1 option[value!='']\", [\"option1b\",\"option1c\",\"option1d\"] );\n\n\tt( \"Select options via :selected\", \"#select1 option:selected\", [\"option1a\"] );\n\tt( \"Select options via :selected\", \"#select2 option:selected\", [\"option2d\"] );\n\tt( \"Select options via :selected\", \"#select3 option:selected\", [\"option3b\", \"option3c\"] );\n\tt( \"Select options via :selected\", \"select[name='select2'] option:selected\", [\"option2d\"] );\n\n\tt( \"Grouped Form Elements\", \"input[name='foo[bar]']\", [\"hidden2\"] );\n\n\tinput = document.getElementById(\"text1\");\n\tinput.title = \"Don't click me\";\n\n\tok( Sizzle.matchesSelector( input, \"input[title=\\\"Don't click me\\\"]\" ), \"Quote within attribute value does not mess up tokenizer\" );\n\n\t// Uncomment if the boolHook is removed\n\t// var check2 = document.getElementById(\"check2\");\n\t// check2.checked = true;\n\t// ok( !Sizzle.matches(\"[checked]\", [ check2 ] ), \"Dynamic boolean attributes match when they should with Sizzle.matches (#11115)\" );\n\n\t// jQuery #12303\n\tinput.setAttribute( \"data-pos\", \":first\" );\n\tok( Sizzle.matchesSelector( input, \"input[data-pos=\\\\:first]\"), \"POS within attribute value is treated as an attribute value\" );\n\tok( Sizzle.matchesSelector( input, \"input[data-pos=':first']\"), \"POS within attribute value is treated as an attribute value\" );\n\tok( Sizzle.matchesSelector( input, \":input[data-pos=':first']\"), \"POS within attribute value after pseudo is treated as an attribute value\" );\n\tinput.removeAttribute(\"data-pos\");\n\n\t// Make sure attribute value quoting works correctly. See jQuery #6093; #6428; #13894\n\t// Use seeded results to bypass querySelectorAll optimizations\n\tattrbad = jQuery(\n\t\t\"<input type='hidden' id='attrbad_space' name='foo bar'/>\" +\n\t\t\"<input type='hidden' id='attrbad_dot' value='2' name='foo.baz'/>\" +\n\t\t\"<input type='hidden' id='attrbad_brackets' value='2' name='foo[baz]'/>\" +\n\t\t\"<input type='hidden' id='attrbad_injection' data-attr='foo_baz&#39;]'/>\" +\n\t\t\"<input type='hidden' id='attrbad_quote' data-attr='&#39;'/>\" +\n\t\t\"<input type='hidden' id='attrbad_backslash' data-attr='&#92;'/>\" +\n\t\t\"<input type='hidden' id='attrbad_backslash_quote' data-attr='&#92;&#39;'/>\" +\n\t\t\"<input type='hidden' id='attrbad_backslash_backslash' data-attr='&#92;&#92;'/>\" +\n\t\t\"<input type='hidden' id='attrbad_unicode' data-attr='&#x4e00;'/>\"\n\t).appendTo(\"#qunit-fixture\").get();\n\n\tt( \"Underscores don't need escaping\", \"input[id=types_all]\", [\"types_all\"] );\n\n\tdeepEqual( Sizzle( \"input[name=foo\\\\ bar]\", null, null, attrbad ), q(\"attrbad_space\"),\n\t\t\"Escaped space\" );\n\tdeepEqual( Sizzle( \"input[name=foo\\\\.baz]\", null, null, attrbad ), q(\"attrbad_dot\"),\n\t\t\"Escaped dot\" );\n\tdeepEqual( Sizzle( \"input[name=foo\\\\[baz\\\\]]\", null, null, attrbad ), q(\"attrbad_brackets\"),\n\t\t\"Escaped brackets\" );\n\tdeepEqual( Sizzle( \"input[data-attr='foo_baz\\\\']']\", null, null, attrbad ), q(\"attrbad_injection\"),\n\t\t\"Escaped quote + right bracket\" );\n\n\tdeepEqual( Sizzle( \"input[data-attr='\\\\'']\", null, null, attrbad ), q(\"attrbad_quote\"),\n\t\t\"Quoted quote\" );\n\tdeepEqual( Sizzle( \"input[data-attr='\\\\\\\\']\", null, null, attrbad ), q(\"attrbad_backslash\"),\n\t\t\"Quoted backslash\" );\n\tdeepEqual( Sizzle( \"input[data-attr='\\\\\\\\\\\\'']\", null, null, attrbad ), q(\"attrbad_backslash_quote\"),\n\t\t\"Quoted backslash quote\" );\n\tdeepEqual( Sizzle( \"input[data-attr='\\\\\\\\\\\\\\\\']\", null, null, attrbad ), q(\"attrbad_backslash_backslash\"),\n\t\t\"Quoted backslash backslash\" );\n\n\tdeepEqual( Sizzle( \"input[data-attr='\\\\5C\\\\\\\\']\", null, null, attrbad ), q(\"attrbad_backslash_backslash\"),\n\t\t\"Quoted backslash backslash (numeric escape)\" );\n\tdeepEqual( Sizzle( \"input[data-attr='\\\\5C \\\\\\\\']\", null, null, attrbad ), q(\"attrbad_backslash_backslash\"),\n\t\t\"Quoted backslash backslash (numeric escape with trailing space)\" );\n\tdeepEqual( Sizzle( \"input[data-attr='\\\\5C\\t\\\\\\\\']\", null, null, attrbad ), q(\"attrbad_backslash_backslash\"),\n\t\t\"Quoted backslash backslash (numeric escape with trailing tab)\" );\n\tdeepEqual( Sizzle( \"input[data-attr='\\\\04e00']\", null, null, attrbad ), q(\"attrbad_unicode\"),\n\t\t\"Long numeric escape (BMP)\" );\n\tdocument.getElementById(\"attrbad_unicode\").setAttribute( \"data-attr\", \"\\uD834\\uDF06A\" );\n\t// It was too much code to fix Safari 5.x Supplemental Plane crashes (see ba5f09fa404379a87370ec905ffa47f8ac40aaa3)\n\t// deepEqual( Sizzle( \"input[data-attr='\\\\01D306A']\", null, null, attrbad ), q(\"attrbad_unicode\"),\n\t// \t\"Long numeric escape (non-BMP)\" );\n\n\tt( \"input[type=text]\", \"#form input[type=text]\", [\"text1\", \"text2\", \"hidden2\", \"name\"] );\n\tt( \"input[type=search]\", \"#form input[type=search]\", [\"search\"] );\n\tt( \"script[src] (jQuery #13777)\", \"#moretests script[src]\", [\"script-src\"] );\n\n\t// #3279\n\tdiv = document.createElement(\"div\");\n\tdiv.innerHTML = \"<div id='foo' xml:test='something'></div>\";\n\n\tdeepEqual( Sizzle( \"[xml\\\\:test]\", div ), [ div.firstChild ], \"Finding by attribute with escaped characters.\" );\n\n\tdiv = document.getElementById(\"foo\");\n\tt( \"Object.prototype property \\\"constructor\\\" (negative)\", \"[constructor]\", [] );\n\tt( \"Gecko Object.prototype property \\\"watch\\\" (negative)\", \"[watch]\", [] );\n\tdiv.setAttribute( \"constructor\", \"foo\" );\n\tdiv.setAttribute( \"watch\", \"bar\" );\n\tt( \"Object.prototype property \\\"constructor\\\"\", \"[constructor='foo']\", [\"foo\"] );\n\tt( \"Gecko Object.prototype property \\\"watch\\\"\", \"[watch='bar']\", [\"foo\"] );\n\n\tt( \"Value attribute is retrieved correctly\", \"input[value=Test]\", [\"text1\", \"text2\"] );\n});\n\ntest(\"pseudo - (parent|empty)\", function() {\n\texpect( 3 );\n\tt( \"Empty\", \"ul:empty\", [\"firstUL\"] );\n\tt( \"Empty with comment node\", \"ol:empty\", [\"empty\"] );\n\tt( \"Is A Parent\", \"#qunit-fixture p:parent\", [\"firstp\",\"ap\",\"sndp\",\"en\",\"sap\",\"first\"] );\n});\n\ntest(\"pseudo - (first|last|only)-(child|of-type)\", function() {\n\texpect( 12 );\n\n\tt( \"First Child\", \"p:first-child\", [\"firstp\",\"sndp\"] );\n\tt( \"First Child (leading id)\", \"#qunit-fixture p:first-child\", [\"firstp\",\"sndp\"] );\n\tt( \"First Child (leading class)\", \".nothiddendiv div:first-child\", [\"nothiddendivchild\"] );\n\tt( \"First Child (case-insensitive)\", \"#qunit-fixture p:FIRST-CHILD\", [\"firstp\",\"sndp\"] );\n\n\tt( \"Last Child\", \"p:last-child\", [\"sap\"] );\n\tt( \"Last Child (leading id)\", \"#qunit-fixture a:last-child\", [\"simon1\",\"anchor1\",\"mark\",\"yahoo\",\"anchor2\",\"simon\",\"liveLink1\",\"liveLink2\"] );\n\n\tt( \"Only Child\", \"#qunit-fixture a:only-child\", [\"simon1\",\"anchor1\",\"yahoo\",\"anchor2\",\"liveLink1\",\"liveLink2\"] );\n\n\tt( \"First-of-type\", \"#qunit-fixture > p:first-of-type\", [\"firstp\"] );\n\tt( \"Last-of-type\", \"#qunit-fixture > p:last-of-type\", [\"first\"] );\n\tt( \"Only-of-type\", \"#qunit-fixture > :only-of-type\", [\"name+value\", \"firstUL\", \"empty\", \"floatTest\", \"iframe\", \"table\"] );\n\n\t// Verify that the child position isn't being cached improperly\n\tvar secondChildren = jQuery(\"p:nth-child(2)\").before(\"<div></div>\");\n\n\tt( \"No longer second child\", \"p:nth-child(2)\", [] );\n\tsecondChildren.prev().remove();\n\tt( \"Restored second child\", \"p:nth-child(2)\", [\"ap\",\"en\"] );\n});\n\ntest(\"pseudo - nth-child\", function() {\n\texpect( 30 );\n\n\tt( \"Nth-child\", \"p:nth-child(1)\", [\"firstp\",\"sndp\"] );\n\tt( \"Nth-child (with whitespace)\", \"p:nth-child( 1 )\", [\"firstp\",\"sndp\"] );\n\tt( \"Nth-child (case-insensitive)\", \"#form select:first option:NTH-child(3)\", [\"option1c\"] );\n\tt( \"Not nth-child\", \"#qunit-fixture p:not(:nth-child(1))\", [\"ap\",\"en\",\"sap\",\"first\"] );\n\n\tt( \"Nth-child(2)\", \"#qunit-fixture form#form > *:nth-child(2)\", [\"text1\"] );\n\tt( \"Nth-child(2)\", \"#qunit-fixture form#form > :nth-child(2)\", [\"text1\"] );\n\n\tt( \"Nth-child(-1)\", \"#form select:first option:nth-child(-1)\", [] );\n\tt( \"Nth-child(3)\", \"#form select:first option:nth-child(3)\", [\"option1c\"] );\n\tt( \"Nth-child(0n+3)\", \"#form select:first option:nth-child(0n+3)\", [\"option1c\"] );\n\tt( \"Nth-child(1n+0)\", \"#form select:first option:nth-child(1n+0)\", [\"option1a\", \"option1b\", \"option1c\", \"option1d\"] );\n\tt( \"Nth-child(1n)\", \"#form select:first option:nth-child(1n)\", [\"option1a\", \"option1b\", \"option1c\", \"option1d\"] );\n\tt( \"Nth-child(n)\", \"#form select:first option:nth-child(n)\", [\"option1a\", \"option1b\", \"option1c\", \"option1d\"] );\n\tt( \"Nth-child(even)\", \"#form select:first option:nth-child(even)\", [\"option1b\", \"option1d\"] );\n\tt( \"Nth-child(odd)\", \"#form select:first option:nth-child(odd)\", [\"option1a\", \"option1c\"] );\n\tt( \"Nth-child(2n)\", \"#form select:first option:nth-child(2n)\", [\"option1b\", \"option1d\"] );\n\tt( \"Nth-child(2n+1)\", \"#form select:first option:nth-child(2n+1)\", [\"option1a\", \"option1c\"] );\n\tt( \"Nth-child(2n + 1)\", \"#form select:first option:nth-child(2n + 1)\", [\"option1a\", \"option1c\"] );\n\tt( \"Nth-child(+2n + 1)\", \"#form select:first option:nth-child(+2n + 1)\", [\"option1a\", \"option1c\"] );\n\tt( \"Nth-child(3n)\", \"#form select:first option:nth-child(3n)\", [\"option1c\"] );\n\tt( \"Nth-child(3n+1)\", \"#form select:first option:nth-child(3n+1)\", [\"option1a\", \"option1d\"] );\n\tt( \"Nth-child(3n+2)\", \"#form select:first option:nth-child(3n+2)\", [\"option1b\"] );\n\tt( \"Nth-child(3n+3)\", \"#form select:first option:nth-child(3n+3)\", [\"option1c\"] );\n\tt( \"Nth-child(3n-1)\", \"#form select:first option:nth-child(3n-1)\", [\"option1b\"] );\n\tt( \"Nth-child(3n-2)\", \"#form select:first option:nth-child(3n-2)\", [\"option1a\", \"option1d\"] );\n\tt( \"Nth-child(3n-3)\", \"#form select:first option:nth-child(3n-3)\", [\"option1c\"] );\n\tt( \"Nth-child(3n+0)\", \"#form select:first option:nth-child(3n+0)\", [\"option1c\"] );\n\tt( \"Nth-child(-1n+3)\", \"#form select:first option:nth-child(-1n+3)\", [\"option1a\", \"option1b\", \"option1c\"] );\n\tt( \"Nth-child(-n+3)\", \"#form select:first option:nth-child(-n+3)\", [\"option1a\", \"option1b\", \"option1c\"] );\n\tt( \"Nth-child(-1n + 3)\", \"#form select:first option:nth-child(-1n + 3)\", [\"option1a\", \"option1b\", \"option1c\"] );\n\n\tdeepEqual( Sizzle( \":nth-child(n)\", null, null, [ document.createElement(\"a\") ].concat( q(\"ap\") ) ), q(\"ap\"), \"Seeded nth-child\" );\n});\n\ntest(\"pseudo - nth-last-child\", function() {\n\texpect( 30 );\n\n\tt( \"Nth-last-child\", \"form:nth-last-child(5)\", [\"testForm\"] );\n\tt( \"Nth-last-child (with whitespace)\", \"form:nth-last-child( 5 )\", [\"testForm\"] );\n\tt( \"Nth-last-child (case-insensitive)\", \"#form select:first option:NTH-last-child(3)\", [\"option1b\"] );\n\tt( \"Not nth-last-child\", \"#qunit-fixture p:not(:nth-last-child(1))\", [\"firstp\", \"ap\", \"sndp\", \"en\", \"first\"] );\n\n\tt( \"Nth-last-child(-1)\", \"#form select:first option:nth-last-child(-1)\", [] );\n\tt( \"Nth-last-child(3)\", \"#form select:first :nth-last-child(3)\", [\"option1b\"] );\n\tt( \"Nth-last-child(3)\", \"#form select:first *:nth-last-child(3)\", [\"option1b\"] );\n\tt( \"Nth-last-child(3)\", \"#form select:first option:nth-last-child(3)\", [\"option1b\"] );\n\tt( \"Nth-last-child(0n+3)\", \"#form select:first option:nth-last-child(0n+3)\", [\"option1b\"] );\n\tt( \"Nth-last-child(1n+0)\", \"#form select:first option:nth-last-child(1n+0)\", [\"option1a\", \"option1b\", \"option1c\", \"option1d\"] );\n\tt( \"Nth-last-child(1n)\", \"#form select:first option:nth-last-child(1n)\", [\"option1a\", \"option1b\", \"option1c\", \"option1d\"] );\n\tt( \"Nth-last-child(n)\", \"#form select:first option:nth-last-child(n)\", [\"option1a\", \"option1b\", \"option1c\", \"option1d\"] );\n\tt( \"Nth-last-child(even)\", \"#form select:first option:nth-last-child(even)\", [\"option1a\", \"option1c\"] );\n\tt( \"Nth-last-child(odd)\", \"#form select:first option:nth-last-child(odd)\", [\"option1b\", \"option1d\"] );\n\tt( \"Nth-last-child(2n)\", \"#form select:first option:nth-last-child(2n)\", [\"option1a\", \"option1c\"] );\n\tt( \"Nth-last-child(2n+1)\", \"#form select:first option:nth-last-child(2n+1)\", [\"option1b\", \"option1d\"] );\n\tt( \"Nth-last-child(2n + 1)\", \"#form select:first option:nth-last-child(2n + 1)\", [\"option1b\", \"option1d\"] );\n\tt( \"Nth-last-child(+2n + 1)\", \"#form select:first option:nth-last-child(+2n + 1)\", [\"option1b\", \"option1d\"] );\n\tt( \"Nth-last-child(3n)\", \"#form select:first option:nth-last-child(3n)\", [\"option1b\"] );\n\tt( \"Nth-last-child(3n+1)\", \"#form select:first option:nth-last-child(3n+1)\", [\"option1a\", \"option1d\"] );\n\tt( \"Nth-last-child(3n+2)\", \"#form select:first option:nth-last-child(3n+2)\", [\"option1c\"] );\n\tt( \"Nth-last-child(3n+3)\", \"#form select:first option:nth-last-child(3n+3)\", [\"option1b\"] );\n\tt( \"Nth-last-child(3n-1)\", \"#form select:first option:nth-last-child(3n-1)\", [\"option1c\"] );\n\tt( \"Nth-last-child(3n-2)\", \"#form select:first option:nth-last-child(3n-2)\", [\"option1a\", \"option1d\"] );\n\tt( \"Nth-last-child(3n-3)\", \"#form select:first option:nth-last-child(3n-3)\", [\"option1b\"] );\n\tt( \"Nth-last-child(3n+0)\", \"#form select:first option:nth-last-child(3n+0)\", [\"option1b\"] );\n\tt( \"Nth-last-child(-1n+3)\", \"#form select:first option:nth-last-child(-1n+3)\", [\"option1b\", \"option1c\", \"option1d\"] );\n\tt( \"Nth-last-child(-n+3)\", \"#form select:first option:nth-last-child(-n+3)\", [\"option1b\", \"option1c\", \"option1d\"] );\n\tt( \"Nth-last-child(-1n + 3)\", \"#form select:first option:nth-last-child(-1n + 3)\", [\"option1b\", \"option1c\", \"option1d\"] );\n\n\tdeepEqual( Sizzle( \":nth-last-child(n)\", null, null, [ document.createElement(\"a\") ].concat( q(\"ap\") ) ), q(\"ap\"), \"Seeded nth-last-child\" );\n});\n\ntest(\"pseudo - nth-of-type\", function() {\n\texpect( 9 );\n\tt( \"Nth-of-type(-1)\", \":nth-of-type(-1)\", [] );\n\tt( \"Nth-of-type(3)\", \"#ap :nth-of-type(3)\", [\"mark\"] );\n\tt( \"Nth-of-type(n)\", \"#ap :nth-of-type(n)\", [\"google\", \"groups\", \"code1\", \"anchor1\", \"mark\"] );\n\tt( \"Nth-of-type(0n+3)\", \"#ap :nth-of-type(0n+3)\", [\"mark\"] );\n\tt( \"Nth-of-type(2n)\", \"#ap :nth-of-type(2n)\", [\"groups\"] );\n\tt( \"Nth-of-type(even)\", \"#ap :nth-of-type(even)\", [\"groups\"] );\n\tt( \"Nth-of-type(2n+1)\", \"#ap :nth-of-type(2n+1)\", [\"google\", \"code1\", \"anchor1\", \"mark\"] );\n\tt( \"Nth-of-type(odd)\", \"#ap :nth-of-type(odd)\", [\"google\", \"code1\", \"anchor1\", \"mark\"] );\n\tt( \"Nth-of-type(-n+2)\", \"#qunit-fixture > :nth-of-type(-n+2)\", [\"firstp\", \"ap\", \"foo\", \"nothiddendiv\", \"name+value\", \"firstUL\", \"empty\", \"form\", \"floatTest\", \"iframe\", \"lengthtest\", \"table\"] );\n});\n\ntest(\"pseudo - nth-last-of-type\", function() {\n\texpect( 9 );\n\tt( \"Nth-last-of-type(-1)\", \":nth-last-of-type(-1)\", [] );\n\tt( \"Nth-last-of-type(3)\", \"#ap :nth-last-of-type(3)\", [\"google\"] );\n\tt( \"Nth-last-of-type(n)\", \"#ap :nth-last-of-type(n)\", [\"google\", \"groups\", \"code1\", \"anchor1\", \"mark\"] );\n\tt( \"Nth-last-of-type(0n+3)\", \"#ap :nth-last-of-type(0n+3)\", [\"google\"] );\n\tt( \"Nth-last-of-type(2n)\", \"#ap :nth-last-of-type(2n)\", [\"groups\"] );\n\tt( \"Nth-last-of-type(even)\", \"#ap :nth-last-of-type(even)\", [\"groups\"] );\n\tt( \"Nth-last-of-type(2n+1)\", \"#ap :nth-last-of-type(2n+1)\", [\"google\", \"code1\", \"anchor1\", \"mark\"] );\n\tt( \"Nth-last-of-type(odd)\", \"#ap :nth-last-of-type(odd)\", [\"google\", \"code1\", \"anchor1\", \"mark\"] );\n\tt( \"Nth-last-of-type(-n+2)\", \"#qunit-fixture > :nth-last-of-type(-n+2)\", [\"ap\", \"name+value\", \"first\", \"firstUL\", \"empty\", \"floatTest\", \"iframe\", \"table\", \"name-tests\", \"testForm\", \"liveHandlerOrder\", \"siblingTest\"] );\n});\n\ntest(\"pseudo - has\", function() {\n\texpect( 3 );\n\n\tt( \"Basic test\", \"p:has(a)\", [\"firstp\",\"ap\",\"en\",\"sap\"] );\n\tt( \"Basic test (irrelevant whitespace)\", \"p:has( a )\", [\"firstp\",\"ap\",\"en\",\"sap\"] );\n\tt( \"Nested with overlapping candidates\", \"#qunit-fixture div:has(div:has(div:not([id])))\", [ \"moretests\", \"t2037\" ] );\n});\n\ntest(\"pseudo - misc\", function() {\n\texpect( 39 );\n\n\tvar select, tmp, input;\n\n\tt( \"Headers\", \":header\", [\"qunit-header\", \"qunit-banner\", \"qunit-userAgent\"] );\n\tt( \"Headers(case-insensitive)\", \":Header\", [\"qunit-header\", \"qunit-banner\", \"qunit-userAgent\"] );\n\tt( \"Multiple matches with the same context (cache check)\", \"#form select:has(option:first-child:contains('o'))\", [\"select1\", \"select2\", \"select3\", \"select4\"] );\n\n\tok( Sizzle(\"#qunit-fixture :not(:has(:has(*)))\").length, \"All not grandparents\" );\n\n\tselect = document.getElementById(\"select1\");\n\tok( Sizzle.matchesSelector( select, \":has(option)\" ), \"Has Option Matches\" );\n\n\tok( Sizzle(\"a:contains('')\").length, \"Empty string contains\" );\n\tt( \"Text Contains\", \"a:contains(Google)\", [\"google\",\"groups\"] );\n\tt( \"Text Contains\", \"a:contains(Google Groups)\", [\"groups\"] );\n\n\tt( \"Text Contains\", \"a:contains('Google Groups (Link)')\", [\"groups\"] );\n\tt( \"Text Contains\", \"a:contains(\\\"(Link)\\\")\", [\"groups\"] );\n\tt( \"Text Contains\", \"a:contains(Google Groups (Link))\", [\"groups\"] );\n\tt( \"Text Contains\", \"a:contains((Link))\", [\"groups\"] );\n\n\n\ttmp = document.createElement(\"div\");\n\ttmp.id = \"tmp_input\";\n\tdocument.body.appendChild( tmp );\n\n\tjQuery.each( [ \"button\", \"submit\", \"reset\" ], function( i, type ) {\n\t\tvar els = jQuery(\n\t\t\t\"<input id='input_%' type='%'/><button id='button_%' type='%'>test</button>\"\n\t\t\t.replace( /%/g, type )\n\t\t).appendTo( tmp );\n\n\t\tt( \"Input Buttons :\" + type, \"#tmp_input :\" + type, [ \"input_\" + type, \"button_\" + type ] );\n\n\t\tok( Sizzle.matchesSelector( els[0], \":\" + type ), \"Input Matches :\" + type );\n\t\tok( Sizzle.matchesSelector( els[1], \":\" + type ), \"Button Matches :\" + type );\n\t});\n\n\tdocument.body.removeChild( tmp );\n\n\t// Recreate tmp\n\ttmp = document.createElement(\"div\");\n\ttmp.id = \"tmp_input\";\n\ttmp.innerHTML = \"<span>Hello I am focusable.</span>\";\n\t// Setting tabIndex should make the element focusable\n\t// http://dev.w3.org/html5/spec/single-page.html#focus-management\n\tdocument.body.appendChild( tmp );\n\ttmp.tabIndex = 0;\n\ttmp.focus();\n\tif ( document.activeElement !== tmp || (document.hasFocus && !document.hasFocus()) ||\n\t\t(document.querySelectorAll && !document.querySelectorAll(\"div:focus\").length) ) {\n\t\tok( true, \"The div was not focused. Skip checking the :focus match.\" );\n\t\tok( true, \"The div was not focused. Skip checking the :focus match.\" );\n\t} else {\n\t\tt( \"tabIndex element focused\", \":focus\", [ \"tmp_input\" ] );\n\t\tok( Sizzle.matchesSelector( tmp, \":focus\" ), \":focus matches tabIndex div\" );\n\t}\n\n\t// Blur tmp\n\ttmp.blur();\n\tdocument.body.focus();\n\tok( !Sizzle.matchesSelector( tmp, \":focus\" ), \":focus doesn't match tabIndex div\" );\n\tdocument.body.removeChild( tmp );\n\n\t// Input focus/active\n\tinput = document.createElement(\"input\");\n\tinput.type = \"text\";\n\tinput.id = \"focus-input\";\n\n\tdocument.body.appendChild( input );\n\tinput.focus();\n\n\t// Inputs can't be focused unless the document has focus\n\tif ( document.activeElement !== input || (document.hasFocus && !document.hasFocus()) ||\n\t\t(document.querySelectorAll && !document.querySelectorAll(\"input:focus\").length) ) {\n\t\tok( true, \"The input was not focused. Skip checking the :focus match.\" );\n\t\tok( true, \"The input was not focused. Skip checking the :focus match.\" );\n\t} else {\n\t\tt( \"Element focused\", \"input:focus\", [ \"focus-input\" ] );\n\t\tok( Sizzle.matchesSelector( input, \":focus\" ), \":focus matches\" );\n\t}\n\n\tinput.blur();\n\n\t// When IE is out of focus, blur does not work. Force it here.\n\tif ( document.activeElement === input ) {\n\t\tdocument.body.focus();\n\t}\n\n\tok( !Sizzle.matchesSelector( input, \":focus\" ), \":focus doesn't match\" );\n\tdocument.body.removeChild( input );\n\n\n\n\tdeepEqual(\n\t\tSizzle( \"[id='select1'] *:not(:last-child), [id='select2'] *:not(:last-child)\", q(\"qunit-fixture\")[0] ),\n\t\tq( \"option1a\", \"option1b\", \"option1c\", \"option2a\", \"option2b\", \"option2c\" ),\n\t\t\"caching system tolerates recursive selection\"\n\t);\n\n\t// Tokenization edge cases\n\tt( \"Sequential pseudos\", \"#qunit-fixture p:has(:contains(mark)):has(code)\", [\"ap\"] );\n\tt( \"Sequential pseudos\", \"#qunit-fixture p:has(:contains(mark)):has(code):contains(This link)\", [\"ap\"] );\n\n\tt( \"Pseudo argument containing ')'\", \"p:has(>a.GROUPS[src!=')'])\", [\"ap\"] );\n\tt( \"Pseudo argument containing ')'\", \"p:has(>a.GROUPS[src!=')'])\", [\"ap\"] );\n\tt( \"Pseudo followed by token containing ')'\", \"p:contains(id=\\\"foo\\\")[id!=\\\\)]\", [\"sndp\"] );\n\tt( \"Pseudo followed by token containing ')'\", \"p:contains(id=\\\"foo\\\")[id!=')']\", [\"sndp\"] );\n\n\tt( \"Multi-pseudo\", \"#ap:has(*), #ap:has(*)\", [\"ap\"] );\n\tt( \"Multi-positional\", \"#ap:gt(0), #ap:lt(1)\", [\"ap\"] );\n\tt( \"Multi-pseudo with leading nonexistent id\", \"#nonexistent:has(*), #ap:has(*)\", [\"ap\"] );\n\tt( \"Multi-positional with leading nonexistent id\", \"#nonexistent:gt(0), #ap:lt(1)\", [\"ap\"] );\n\n\tt( \"Tokenization stressor\", \"a[class*=blog]:not(:has(*, :contains(!)), :contains(!)), br:contains(]), p:contains(]), :not(:empty):not(:parent)\", [\"ap\", \"mark\",\"yahoo\",\"simon\"] );\n});\n\n\ntest(\"pseudo - :not\", function() {\n\texpect( 43 );\n\n\tt( \"Not\", \"a.blog:not(.link)\", [\"mark\"] );\n\tt( \":not() with :first\", \"#foo p:not(:first) .link\", [\"simon\"] );\n\n\tt( \"Not - multiple\", \"#form option:not(:contains(Nothing),#option1b,:selected)\", [\"option1c\", \"option1d\", \"option2b\", \"option2c\", \"option3d\", \"option3e\", \"option4e\", \"option5b\", \"option5c\"] );\n\tt( \"Not - recursive\", \"#form option:not(:not(:selected))[id^='option3']\", [ \"option3b\", \"option3c\"] );\n\n\tt( \":not() failing interior\", \"#qunit-fixture p:not(.foo)\", [\"firstp\",\"ap\",\"sndp\",\"en\",\"sap\",\"first\"] );\n\tt( \":not() failing interior\", \"#qunit-fixture p:not(div.foo)\", [\"firstp\",\"ap\",\"sndp\",\"en\",\"sap\",\"first\"] );\n\tt( \":not() failing interior\", \"#qunit-fixture p:not(p.foo)\", [\"firstp\",\"ap\",\"sndp\",\"en\",\"sap\",\"first\"] );\n\tt( \":not() failing interior\", \"#qunit-fixture p:not(#blargh)\", [\"firstp\",\"ap\",\"sndp\",\"en\",\"sap\",\"first\"] );\n\tt( \":not() failing interior\", \"#qunit-fixture p:not(div#blargh)\", [\"firstp\",\"ap\",\"sndp\",\"en\",\"sap\",\"first\"] );\n\tt( \":not() failing interior\", \"#qunit-fixture p:not(p#blargh)\", [\"firstp\",\"ap\",\"sndp\",\"en\",\"sap\",\"first\"] );\n\n\tt( \":not Multiple\", \"#qunit-fixture p:not(a)\", [\"firstp\",\"ap\",\"sndp\",\"en\",\"sap\",\"first\"] );\n\tt( \":not Multiple\", \"#qunit-fixture p:not( a )\", [\"firstp\",\"ap\",\"sndp\",\"en\",\"sap\",\"first\"] );\n\tt( \":not Multiple\", \"#qunit-fixture p:not( p )\", [] );\n\tt( \":not Multiple\", \"#qunit-fixture p:not(a, b)\", [\"firstp\",\"ap\",\"sndp\",\"en\",\"sap\",\"first\"] );\n\tt( \":not Multiple\", \"#qunit-fixture p:not(a, b, div)\", [\"firstp\",\"ap\",\"sndp\",\"en\",\"sap\",\"first\"] );\n\tt( \":not Multiple\", \"p:not(p)\", [] );\n\tt( \":not Multiple\", \"p:not(a,p)\", [] );\n\tt( \":not Multiple\", \"p:not(p,a)\", [] );\n\tt( \":not Multiple\", \"p:not(a,p,b)\", [] );\n\tt( \":not Multiple\", \":input:not(:image,:input,:submit)\", [] );\n\tt( \":not Multiple\", \"#qunit-fixture p:not(:has(a), :nth-child(1))\", [\"first\"] );\n\n\tt( \"No element not selector\", \".container div:not(.excluded) div\", [] );\n\n\tt( \":not() Existing attribute\", \"#form select:not([multiple])\", [\"select1\", \"select2\", \"select5\"]);\n\tt( \":not() Equals attribute\", \"#form select:not([name=select1])\", [\"select2\", \"select3\", \"select4\",\"select5\"]);\n\tt( \":not() Equals quoted attribute\", \"#form select:not([name='select1'])\", [\"select2\", \"select3\", \"select4\", \"select5\"]);\n\n\tt( \":not() Multiple Class\", \"#foo a:not(.blog)\", [\"yahoo\", \"anchor2\"] );\n\tt( \":not() Multiple Class\", \"#foo a:not(.link)\", [\"yahoo\", \"anchor2\"] );\n\tt( \":not() Multiple Class\", \"#foo a:not(.blog.link)\", [\"yahoo\", \"anchor2\"] );\n\n\tt( \":not chaining (compound)\", \"#qunit-fixture div[id]:not(:has(div, span)):not(:has(*))\", [\"nothiddendivchild\", \"divWithNoTabIndex\"] );\n\tt( \":not chaining (with attribute)\", \"#qunit-fixture form[id]:not([action$='formaction']):not(:button)\", [\"lengthtest\", \"name-tests\", \"testForm\"] );\n\tt( \":not chaining (colon in attribute)\", \"#qunit-fixture form[id]:not([action='form:action']):not(:button)\", [\"form\", \"lengthtest\", \"name-tests\", \"testForm\"] );\n\tt( \":not chaining (colon in attribute and nested chaining)\", \"#qunit-fixture form[id]:not([action='form:action']:button):not(:input)\", [\"form\", \"lengthtest\", \"name-tests\", \"testForm\"] );\n\tt( \":not chaining\", \"#form select:not(.select1):contains(Nothing) > option:not(option)\", [] );\n\n\tt( \"positional :not()\", \"#foo p:not(:last)\", [\"sndp\", \"en\"] );\n\tt( \"positional :not() prefix\", \"#foo p:not(:last) a\", [\"yahoo\"] );\n\tt( \"compound positional :not()\", \"#foo p:not(:first, :last)\", [\"en\"] );\n\tt( \"compound positional :not()\", \"#foo p:not(:first, :even)\", [\"en\"] );\n\tt( \"compound positional :not()\", \"#foo p:not(:first, :odd)\", [\"sap\"] );\n\tt( \"reordered compound positional :not()\", \"#foo p:not(:odd, :first)\", [\"sap\"] );\n\n\tt( \"positional :not() with pre-filter\", \"#foo p:not([id]:first)\", [\"en\", \"sap\"] );\n\tt( \"positional :not() with post-filter\", \"#foo p:not(:first[id])\", [\"en\", \"sap\"] );\n\tt( \"positional :not() with pre-filter\", \"#foo p:not([lang]:first)\", [\"sndp\", \"sap\"] );\n\tt( \"positional :not() with post-filter\", \"#foo p:not(:first[lang])\", [\"sndp\", \"en\", \"sap\"] );\n});\n\ntest(\"pseudo - position\", function() {\n\texpect( 33 );\n\n\tt( \"First element\", \"div:first\", [\"qunit\"] );\n\tt( \"First element(case-insensitive)\", \"div:fiRst\", [\"qunit\"] );\n\tt( \"nth Element\", \"#qunit-fixture p:nth(1)\", [\"ap\"] );\n\tt( \"First Element\", \"#qunit-fixture p:first\", [\"firstp\"] );\n\tt( \"Last Element\", \"p:last\", [\"first\"] );\n\tt( \"Even Elements\", \"#qunit-fixture p:even\", [\"firstp\",\"sndp\",\"sap\"] );\n\tt( \"Odd Elements\", \"#qunit-fixture p:odd\", [\"ap\",\"en\",\"first\"] );\n\tt( \"Position Equals\", \"#qunit-fixture p:eq(1)\", [\"ap\"] );\n\tt( \"Position Equals (negative)\", \"#qunit-fixture p:eq(-1)\", [\"first\"] );\n\tt( \"Position Greater Than\", \"#qunit-fixture p:gt(0)\", [\"ap\",\"sndp\",\"en\",\"sap\",\"first\"] );\n\tt( \"Position Less Than\", \"#qunit-fixture p:lt(3)\", [\"firstp\",\"ap\",\"sndp\"] );\n\n\tt( \"Check position filtering\", \"div#nothiddendiv:eq(0)\", [\"nothiddendiv\"] );\n\tt( \"Check position filtering\", \"div#nothiddendiv:last\", [\"nothiddendiv\"] );\n\tt( \"Check position filtering\", \"div#nothiddendiv:not(:gt(0))\", [\"nothiddendiv\"] );\n\tt( \"Check position filtering\", \"#foo > :not(:first)\", [\"en\", \"sap\"] );\n\tt( \"Check position filtering\", \"#qunit-fixture select > :not(:gt(2))\", [\"option1a\", \"option1b\", \"option1c\"] );\n\tt( \"Check position filtering\", \"#qunit-fixture select:lt(2) :not(:first)\", [\"option1b\", \"option1c\", \"option1d\", \"option2a\", \"option2b\", \"option2c\", \"option2d\"] );\n\tt( \"Check position filtering\", \"div.nothiddendiv:eq(0)\", [\"nothiddendiv\"] );\n\tt( \"Check position filtering\", \"div.nothiddendiv:last\", [\"nothiddendiv\"] );\n\tt( \"Check position filtering\", \"div.nothiddendiv:not(:lt(0))\", [\"nothiddendiv\"] );\n\n\tt( \"Check element position\", \"#qunit-fixture div div:eq(0)\", [\"nothiddendivchild\"] );\n\tt( \"Check element position\", \"#select1 option:eq(3)\", [\"option1d\"] );\n\tt( \"Check element position\", \"#qunit-fixture div div:eq(10)\", [\"names-group\"] );\n\tt( \"Check element position\", \"#qunit-fixture div div:first\", [\"nothiddendivchild\"] );\n\tt( \"Check element position\", \"#qunit-fixture div > div:first\", [\"nothiddendivchild\"] );\n\tt( \"Check element position\", \"#dl div:first div:first\", [\"foo\"] );\n\tt( \"Check element position\", \"#dl div:first > div:first\", [\"foo\"] );\n\tt( \"Check element position\", \"div#nothiddendiv:first > div:first\", [\"nothiddendivchild\"] );\n\tt( \"Chained pseudo after a pos pseudo\", \"#listWithTabIndex li:eq(0):contains(Rice)\", [\"foodWithNegativeTabIndex\"] );\n\n\tt( \"Check sort order with POS and comma\", \"#qunit-fixture em>em>em>em:first-child,div>em:first\", [\"siblingfirst\", \"siblinggreatgrandchild\"] );\n\n\tt( \"Isolated position\", \":last\", [\"last\"] );\n\n\tdeepEqual( Sizzle( \"*:lt(2) + *\", null, [], Sizzle(\"#qunit-fixture > p\") ), q(\"ap\"), \"Seeded pos with trailing relative\" );\n\n\t// jQuery #12526\n\tvar context = jQuery(\"#qunit-fixture\").append(\"<div id='jquery12526'></div>\")[0];\n\tdeepEqual( Sizzle( \":last\", context ), q(\"jquery12526\"), \"Post-manipulation positional\" );\n});\n\ntest(\"pseudo - form\", function() {\n\texpect( 10 );\n\n\tvar extraTexts = jQuery(\"<input id=\\\"impliedText\\\"/><input id=\\\"capitalText\\\" type=\\\"TEXT\\\">\").appendTo(\"#form\");\n\n\tt( \"Form element :input\", \"#form :input\", [\"text1\", \"text2\", \"radio1\", \"radio2\", \"check1\", \"check2\", \"hidden1\", \"hidden2\", \"name\", \"search\", \"button\", \"area1\", \"select1\", \"select2\", \"select3\", \"select4\", \"select5\", \"impliedText\", \"capitalText\"] );\n\tt( \"Form element :radio\", \"#form :radio\", [\"radio1\", \"radio2\"] );\n\tt( \"Form element :checkbox\", \"#form :checkbox\", [\"check1\", \"check2\"] );\n\tt( \"Form element :text\", \"#form :text\", [\"text1\", \"text2\", \"hidden2\", \"name\", \"impliedText\", \"capitalText\"] );\n\tt( \"Form element :radio:checked\", \"#form :radio:checked\", [\"radio2\"] );\n\tt( \"Form element :checkbox:checked\", \"#form :checkbox:checked\", [\"check1\"] );\n\tt( \"Form element :radio:checked, :checkbox:checked\", \"#form :radio:checked, #form :checkbox:checked\", [\"radio2\", \"check1\"] );\n\n\tt( \"Selected Option Element\", \"#form option:selected\", [\"option1a\",\"option2d\",\"option3b\",\"option3c\",\"option4b\",\"option4c\",\"option4d\",\"option5a\"] );\n\tt( \"Selected Option Element are also :checked\", \"#form option:checked\", [\"option1a\",\"option2d\",\"option3b\",\"option3c\",\"option4b\",\"option4c\",\"option4d\",\"option5a\"] );\n\tt( \"Hidden inputs should be treated as enabled. See QSA test.\", \"#hidden1:enabled\", [\"hidden1\"] );\n\n\textraTexts.remove();\n});\n\ntest(\"pseudo - :target and :root\", function() {\n\texpect( 2 );\n\n\t// Target\n\tvar oldHash,\n\t$link = jQuery(\"<a/>\").attr({\n\t\thref: \"#\",\n\t\tid: \"new-link\"\n\t}).appendTo(\"#qunit-fixture\");\n\n\toldHash = window.location.hash;\n\twindow.location.hash = \"new-link\";\n\n\tt( \":target\", \":target\", [\"new-link\"] );\n\n\t$link.remove();\n\twindow.location.hash = oldHash;\n\n\t// Root\n\tequal( Sizzle(\":root\")[0], document.documentElement, \":root selector\" );\n});\n\ntest(\"pseudo - :lang\", function() {\n\texpect( 105 );\n\n\tvar docElem = document.documentElement,\n\t\tdocXmlLang = docElem.getAttribute(\"xml:lang\"),\n\t\tdocLang = docElem.lang,\n\t\tfoo = document.getElementById(\"foo\"),\n\t\tanchor = document.getElementById(\"anchor2\"),\n\t\txml = createWithFriesXML(),\n\t\ttestLang = function( text, elem, container, lang, extra ) {\n\t\t\tvar message,\n\t\t\t\tfull = lang + \"-\" + extra;\n\n\t\t\tmessage = \"lang=\" + lang + \" \" + text;\n\t\t\tcontainer.setAttribute( container.ownerDocument.documentElement.nodeName === \"HTML\" ? \"lang\" : \"xml:lang\", lang );\n\t\t\tassertMatch( message, elem, \":lang(\" + lang + \")\" );\n\t\t\tassertMatch( message, elem, \":lang(\" + mixCase(lang) + \")\" );\n\t\t\tassertNoMatch( message, elem, \":lang(\" + full + \")\" );\n\t\t\tassertNoMatch( message, elem, \":lang(\" + mixCase(full) + \")\" );\n\t\t\tassertNoMatch( message, elem, \":lang(\" + lang + \"-)\" );\n\t\t\tassertNoMatch( message, elem, \":lang(\" + full + \"-)\" );\n\t\t\tassertNoMatch( message, elem, \":lang(\" + lang + \"glish)\" );\n\t\t\tassertNoMatch( message, elem, \":lang(\" + full + \"glish)\" );\n\n\t\t\tmessage = \"lang=\" + full + \" \" + text;\n\t\t\tcontainer.setAttribute( container.ownerDocument.documentElement.nodeName === \"HTML\" ? \"lang\" : \"xml:lang\", full );\n\t\t\tassertMatch( message, elem, \":lang(\" + lang + \")\" );\n\t\t\tassertMatch( message, elem, \":lang(\" + mixCase(lang) + \")\" );\n\t\t\tassertMatch( message, elem, \":lang(\" + full + \")\" );\n\t\t\tassertMatch( message, elem, \":lang(\" + mixCase(full) + \")\" );\n\t\t\tassertNoMatch( message, elem, \":lang(\" + lang + \"-)\" );\n\t\t\tassertNoMatch( message, elem, \":lang(\" + full + \"-)\" );\n\t\t\tassertNoMatch( message, elem, \":lang(\" + lang + \"glish)\" );\n\t\t\tassertNoMatch( message, elem, \":lang(\" + full + \"glish)\" );\n\t\t},\n\t\tmixCase = function( str ) {\n\t\t\tvar ret = str.split(\"\"),\n\t\t\t\ti = ret.length;\n\t\t\twhile ( i-- ) {\n\t\t\t\tif ( i & 1 ) {\n\t\t\t\t\tret[i] = ret[i].toUpperCase();\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn ret.join(\"\");\n\t\t},\n\t\tassertMatch = function( text, elem, selector ) {\n\t\t\tok( Sizzle.matchesSelector( elem, selector ), text + \" match \" + selector );\n\t\t},\n\t\tassertNoMatch = function( text, elem, selector ) {\n\t\t\tok( !Sizzle.matchesSelector( elem, selector ), text + \" fail \" + selector );\n\t\t};\n\n\t// Prefixing and inheritance\n\tok( Sizzle.matchesSelector( docElem, \":lang(\" + docElem.lang + \")\" ), \"starting :lang\" );\n\ttestLang( \"document\", anchor, docElem, \"en\", \"us\" );\n\ttestLang( \"grandparent\", anchor, anchor.parentNode.parentNode, \"yue\", \"hk\" );\n\tok( !Sizzle.matchesSelector( anchor, \":lang(en), :lang(en-us)\" ),\n\t\t\":lang does not look above an ancestor with specified lang\" );\n\ttestLang( \"self\", anchor, anchor, \"es\", \"419\" );\n\tok( !Sizzle.matchesSelector( anchor, \":lang(en), :lang(en-us), :lang(yue), :lang(yue-hk)\" ),\n\t\t\":lang does not look above self with specified lang\" );\n\n\t// Searching by language tag\n\tanchor.parentNode.parentNode.lang = \"arab\";\n\tanchor.parentNode.lang = anchor.parentNode.id = \"ara-sa\";\n\tanchor.lang = \"ara\";\n\tdeepEqual( Sizzle( \":lang(ara)\", foo ), [ anchor.parentNode, anchor ], \"Find by :lang\" );\n\n\t// Selector validity\n\tanchor.parentNode.lang = \"ara\";\n\tanchor.lang = \"ara\\\\b\";\n\tdeepEqual( Sizzle( \":lang(ara\\\\b)\", foo ), [], \":lang respects backslashes\" );\n\tdeepEqual( Sizzle( \":lang(ara\\\\\\\\b)\", foo ), [ anchor ], \":lang respects escaped backslashes\" );\n\traises(function() {\n\t\tSizzle.call( null, \"dl:lang(c++)\" );\n\t}, function( e ) {\n\t\treturn e.message.indexOf(\"Syntax error\") >= 0;\n\t}, \":lang value must be a valid identifier\" );\n\n\t// XML\n\tfoo = jQuery( \"response\", xml )[0];\n\tanchor = jQuery( \"#seite1\", xml )[0];\n\ttestLang( \"XML document\", anchor, xml.documentElement, \"en\", \"us\" );\n\ttestLang( \"XML grandparent\", anchor, foo, \"yue\", \"hk\" );\n\tok( !Sizzle.matchesSelector( anchor, \":lang(en), :lang(en-us)\" ),\n\t\t\"XML :lang does not look above an ancestor with specified lang\" );\n\ttestLang( \"XML self\", anchor, anchor, \"es\", \"419\" );\n\tok( !Sizzle.matchesSelector( anchor, \":lang(en), :lang(en-us), :lang(yue), :lang(yue-hk)\" ),\n\t\t\"XML :lang does not look above self with specified lang\" );\n\n\t// Cleanup\n\tif ( docXmlLang == null ) {\n\t\tdocElem.removeAttribute(\"xml:lang\");\n\t} else {\n\t\tdocElem.setAttribute( \"xml:lang\", docXmlLang );\n\t}\n\tdocElem.lang = docLang;\n});\n\ntest(\"caching\", function() {\n\texpect( 2 );\n\tSizzle( \":not(code)\", document.getElementById(\"ap\") );\n\tdeepEqual( Sizzle( \":not(code)\", document.getElementById(\"foo\") ), q(\"sndp\", \"en\", \"yahoo\", \"sap\", \"anchor2\", \"simon\"), \"Reusing selector with new context\" );\n\n\tt( \"Deep ancestry caching in post-positional element matcher (jQuery #14657)\",\n\t\t\"#qunit-fixture a:lt(3):parent\",\n\t\t[ \"simon1\", \"google\", \"groups\" ] );\n});\n\nasyncTest( \"Iframe dispatch should not affect Sizzle, see jQuery #13936\", 1, function() {\n\tvar loaded = false,\n\t\tthrown = false,\n\t\tiframe = document.getElementById(\"iframe\"),\n\t\tiframeDoc = iframe.contentDocument || iframe.contentWindow.document;\n\n\tjQuery( iframe ).on( \"load\", function() {\n\t\tvar form;\n\n\t\ttry {\n\t\t\tiframeDoc = this.contentDocument || this.contentWindow.document;\n\t\t\tform = Sizzle( \"#navigate\", iframeDoc )[ 0 ];\n\t\t} catch ( e ) {\n\t\t\tthrown = e;\n\t\t}\n\n\t\tif ( loaded ) {\n\t\t\tstrictEqual( thrown, false, \"No error thrown from post-reload Sizzle call\" );\n\t\t\tstart();\n\t\t} else {\n\t\t\tloaded = true;\n\t\t\tform.submit();\n\t\t}\n\t});\n\n\tiframeDoc.open();\n\tiframeDoc.write(\"<body><form id='navigate'></form></body>\");\n\tiframeDoc.close();\n});\n\ntest(\"matchesSelector\", function() {\n\texpect( 6 );\n\n\tvar el = document.getElementById(\"simon1\"),\n\t\tdisconnected = document.createElement(\"div\");\n\n\tok( Sizzle.matchesSelector( el, \"[rel='bookmark']\" ), \"quoted attribute\" );\n\tok( Sizzle.matchesSelector( el, \"[rel=bookmark]\" ), \"unquoted attribute\" );\n\tok( Sizzle.matchesSelector( el, \"[\\nrel = bookmark\\t]\" ), \"unquoted attribute with non-semantic whitespace\" );\n\n\tok( Sizzle.matchesSelector( disconnected, \"div\" ), \"disconnected element\" );\n\n\tok( Sizzle.matchesSelector( el, \"* > *\" ), \"child combinator (matching)\" );\n\tok( !Sizzle.matchesSelector( disconnected, \"* > *\" ), \"child combinator (not matching)\" );\n});\n"
  },
  {
    "path": "flowable-ui-web/modeler/libs/sizzle_1.10.16/test/unit/utilities.js",
    "content": "module(\"utilities\", { teardown: moduleTeardown });\n\nfunction testAttr( doc ) {\n\texpect( 9 );\n\n\tvar el;\n\tif ( doc ) {\n\t\t// XML\n\t\tel = doc.createElement( \"input\" );\n\t\tel.setAttribute( \"type\", \"checkbox\" );\n\t} else {\n\t\t// Set checked on creation by creating with a fragment\n\t\t// See http://jsfiddle.net/8sVgA/1/show/light in oldIE\n\t\tel = jQuery( \"<input type='checkbox' checked='checked' />\" )[0];\n\t}\n\n\t// Set it again for good measure\n\tel.setAttribute( \"checked\", \"checked\" );\n\tel.setAttribute( \"id\", \"id\" );\n\tel.setAttribute( \"value\", \"on\" );\n\n\tstrictEqual( Sizzle.attr( el, \"nonexistent\" ), null, \"nonexistent\" );\n\tstrictEqual( Sizzle.attr( el, \"id\" ), \"id\", \"existent\" );\n\tstrictEqual( Sizzle.attr( el, \"value\" ), \"on\", \"value\" );\n\tstrictEqual( Sizzle.attr( el, \"checked\" ), \"checked\", \"boolean\" );\n\tstrictEqual( Sizzle.attr( el, \"href\" ), null, \"interpolation risk\" );\n\tstrictEqual( Sizzle.attr( el, \"constructor\" ), null,\n\t\t\"Object.prototype property \\\"constructor\\\" (negative)\" );\n\tstrictEqual( Sizzle.attr( el, \"watch\" ), null,\n\t\t\"Gecko Object.prototype property \\\"watch\\\" (negative)\" );\n\tel.setAttribute( \"constructor\", \"foo\" );\n\tel.setAttribute( \"watch\", \"bar\" );\n\tstrictEqual( Sizzle.attr( el, \"constructor\" ), \"foo\",\n\t\t\"Object.prototype property \\\"constructor\\\"\" );\n\tstrictEqual( Sizzle.attr( el, \"watch\" ), \"bar\",\n\t\t\"Gecko Object.prototype property \\\"watch\\\"\" );\n}\n\ntest(\"Sizzle.attr (HTML)\", function() {\n\ttestAttr();\n});\n\ntest(\"Sizzle.attr (XML)\", function() {\n\ttestAttr( jQuery.parseXML(\"<root/>\") );\n});\n\ntest(\"Sizzle.contains\", function() {\n\texpect( 16 );\n\n\tvar container = document.getElementById(\"nonnodes\"),\n\t\telement = container.firstChild,\n\t\ttext = element.nextSibling,\n\t\tnonContained = container.nextSibling,\n\t\tdetached = document.createElement(\"a\");\n\tok( element && element.nodeType === 1, \"preliminary: found element\" );\n\tok( text && text.nodeType === 3, \"preliminary: found text\" );\n\tok( nonContained, \"preliminary: found non-descendant\" );\n\tok( Sizzle.contains(container, element), \"child\" );\n\tok( Sizzle.contains(container.parentNode, element), \"grandchild\" );\n\tok( Sizzle.contains(container, text), \"text child\" );\n\tok( Sizzle.contains(container.parentNode, text), \"text grandchild\" );\n\tok( !Sizzle.contains(container, container), \"self\" );\n\tok( !Sizzle.contains(element, container), \"parent\" );\n\tok( !Sizzle.contains(container, nonContained), \"non-descendant\" );\n\tok( !Sizzle.contains(container, document), \"document\" );\n\tok( !Sizzle.contains(container, document.documentElement), \"documentElement (negative)\" );\n\tok( !Sizzle.contains(container, null), \"Passing null does not throw an error\" );\n\tok( Sizzle.contains(document, document.documentElement), \"documentElement (positive)\" );\n\tok( Sizzle.contains(document, element), \"document container (positive)\" );\n\tok( !Sizzle.contains(document, detached), \"document container (negative)\" );\n});\n\nif ( jQuery(\"<svg xmlns='http://www.w3.org/2000/svg' version='1.1' height='1' width='1'><g/></svg>\")[0].firstChild ) {\n\ttest(\"Sizzle.contains in SVG (jQuery #10832)\", function() {\n\t\texpect( 4 );\n\n\t\tvar svg = jQuery(\n\t\t\t\"<svg xmlns='http://www.w3.org/2000/svg' version='1.1' height='1' width='1'>\" +\n\t\t\t\t\"<g><circle cx='1' cy='1' r='1' /></g>\" +\n\t\t\t\"</svg>\"\n\t\t).appendTo(\"#qunit-fixture\")[0];\n\n\t\tok( Sizzle.contains( svg, svg.firstChild ), \"root child\" );\n\t\tok( Sizzle.contains( svg.firstChild, svg.firstChild.firstChild ), \"element child\" );\n\t\tok( Sizzle.contains( svg, svg.firstChild.firstChild ), \"root granchild\" );\n\t\tok( !Sizzle.contains( svg.firstChild.firstChild, svg.firstChild ), \"parent (negative)\" );\n\t});\n}\n\ntest(\"Sizzle.uniqueSort\", function() {\n\texpect( 14 );\n\n\tfunction Arrayish( arr ) {\n\t\tvar i = this.length = arr.length;\n\t\twhile ( i-- ) {\n\t\t\tthis[ i ] = arr[ i ];\n\t\t}\n\t}\n\tArrayish.prototype = {\n\t\tslice: [].slice,\n\t\tsort: [].sort,\n\t\tsplice: [].splice\n\t};\n\n\tvar i, tests,\n\t\tdetached = [],\n\t\tbody = document.body,\n\t\tfixture = document.getElementById(\"qunit-fixture\"),\n\t\tdetached1 = document.createElement(\"p\"),\n\t\tdetached2 = document.createElement(\"ul\"),\n\t\tdetachedChild = detached1.appendChild( document.createElement(\"a\") ),\n\t\tdetachedGrandchild = detachedChild.appendChild( document.createElement(\"b\") );\n\n\tfor ( i = 0; i < 12; i++ ) {\n\t\tdetached.push( document.createElement(\"li\") );\n\t\tdetached[i].id = \"detached\" + i;\n\t\tdetached2.appendChild( document.createElement(\"li\") ).id = \"detachedChild\" + i;\n\t}\n\n\ttests = {\n\t\t\"Empty\": {\n\t\t\tinput: [],\n\t\t\texpected: []\n\t\t},\n\t\t\"Single-element\": {\n\t\t\tinput: [ fixture ],\n\t\t\texpected: [ fixture ]\n\t\t},\n\t\t\"No duplicates\": {\n\t\t\tinput: [ fixture, body ],\n\t\t\texpected: [ body, fixture ]\n\t\t},\n\t\t\"Duplicates\": {\n\t\t\tinput: [ body, fixture, fixture, body ],\n\t\t\texpected: [ body, fixture ]\n\t\t},\n\t\t\"Detached\": {\n\t\t\tinput: detached.slice( 0 ),\n\t\t\texpected: detached.slice( 0 )\n\t\t},\n\t\t\"Detached children\": {\n\t\t\tinput: [\n\t\t\t\tdetached2.childNodes[0],\n\t\t\t\tdetached2.childNodes[1],\n\t\t\t\tdetached2.childNodes[2],\n\t\t\t\tdetached2.childNodes[3]\n\t\t\t],\n\t\t\texpected: [\n\t\t\t\tdetached2.childNodes[0],\n\t\t\t\tdetached2.childNodes[1],\n\t\t\t\tdetached2.childNodes[2],\n\t\t\t\tdetached2.childNodes[3]\n\t\t\t]\n\t\t},\n\t\t\"Attached/detached mixture\": {\n\t\t\tinput: [ detached1, fixture, detached2, document, detachedChild, body, detachedGrandchild ],\n\t\t\texpected: [ document, body, fixture ],\n\t\t\tlength: 3\n\t\t}\n\t};\n\n\tjQuery.each( tests, function( label, test ) {\n\t\tvar length = test.length || test.input.length;\n\t\tdeepEqual( Sizzle.uniqueSort( test.input ).slice( 0, length ), test.expected, label + \" (array)\" );\n\t\tdeepEqual( Sizzle.uniqueSort( new Arrayish(test.input) ).slice( 0, length ), test.expected, label + \" (quasi-array)\" );\n\t});\n});\n\ntestIframeWithCallback( \"Sizzle.uniqueSort works cross-window (jQuery #14381)\", \"mixed_sort.html\", deepEqual );\n"
  },
  {
    "path": "flowable-ui-web/modeler/libs/ui-grid_3.0.0/ui-grid.css",
    "content": "/*!\n * ui-grid - v3.2.9 - 2016-09-21\n * Copyright (c) 2016 ; License: MIT \n */\n#ui-grid-twbs #ui-grid-twbs .form-horizontal .form-group:before,\n#ui-grid-twbs #ui-grid-twbs .form-horizontal .form-group:after,\n#ui-grid-twbs #ui-grid-twbs .btn-toolbar:before,\n#ui-grid-twbs #ui-grid-twbs .btn-toolbar:after,\n#ui-grid-twbs #ui-grid-twbs .btn-group-vertical > .btn-group:before,\n#ui-grid-twbs #ui-grid-twbs .btn-group-vertical > .btn-group:after {\n  content: \" \";\n  display: table;\n}\n#ui-grid-twbs #ui-grid-twbs .form-horizontal .form-group:after,\n#ui-grid-twbs #ui-grid-twbs .btn-toolbar:after,\n#ui-grid-twbs #ui-grid-twbs .btn-group-vertical > .btn-group:after {\n  clear: both;\n}\n.ui-grid {\n  border: 1px solid #d4d4d4;\n  box-sizing: content-box;\n  -webkit-border-radius: 0px;\n  -moz-border-radius: 0px;\n  border-radius: 0px;\n  -webkit-transform: translateZ(0);\n  -moz-transform: translateZ(0);\n  -o-transform: translateZ(0);\n  -ms-transform: translateZ(0);\n  transform: translateZ(0);\n}\n.ui-grid-vertical-bar {\n  position: absolute;\n  right: 0;\n  width: 0;\n}\n.ui-grid-header-cell:not(:last-child) .ui-grid-vertical-bar,\n.ui-grid-cell:not(:last-child) .ui-grid-vertical-bar {\n  width: 1px;\n}\n.ui-grid-scrollbar-placeholder {\n  background-color: transparent;\n}\n.ui-grid-header-cell:not(:last-child) .ui-grid-vertical-bar {\n  background-color: #d4d4d4;\n}\n.ui-grid-cell:not(:last-child) .ui-grid-vertical-bar {\n  background-color: #d4d4d4;\n}\n.ui-grid-header-cell:last-child .ui-grid-vertical-bar {\n  right: -1px;\n  width: 1px;\n  background-color: #d4d4d4;\n}\n.ui-grid-clearfix:before,\n.ui-grid-clearfix:after {\n  content: \"\";\n  display: table;\n}\n.ui-grid-clearfix:after {\n  clear: both;\n}\n.ui-grid-invisible {\n  visibility: hidden;\n}\n.ui-grid-contents-wrapper {\n  position: relative;\n  height: 100%;\n  width: 100%;\n}\n.ui-grid-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.ui-grid-top-panel-background {\n  background: #f3f3f3;\n  background: -webkit-gradient(linear, left bottom, left top, color-stop(0, #eeeeee), color-stop(1, #ffffff));\n  background: -ms-linear-gradient(bottom, #eeeeee, #ffffff);\n  background: -moz-linear-gradient(center bottom, #eeeeee 0%, #ffffff 100%);\n  background: -o-linear-gradient(#ffffff, #eeeeee);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#eeeeee', GradientType=0);\n}\n.ui-grid-header {\n  border-bottom: 1px solid #d4d4d4;\n  box-sizing: border-box;\n}\n.ui-grid-top-panel {\n  position: relative;\n  overflow: hidden;\n  font-weight: bold;\n  background: #f3f3f3;\n  background: -webkit-gradient(linear, left bottom, left top, color-stop(0, #eeeeee), color-stop(1, #ffffff));\n  background: -ms-linear-gradient(bottom, #eeeeee, #ffffff);\n  background: -moz-linear-gradient(center bottom, #eeeeee 0%, #ffffff 100%);\n  background: -o-linear-gradient(#ffffff, #eeeeee);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#eeeeee', GradientType=0);\n  -webkit-border-top-right-radius: -1px;\n  -webkit-border-bottom-right-radius: 0;\n  -webkit-border-bottom-left-radius: 0;\n  -webkit-border-top-left-radius: -1px;\n  -moz-border-radius-topright: -1px;\n  -moz-border-radius-bottomright: 0;\n  -moz-border-radius-bottomleft: 0;\n  -moz-border-radius-topleft: -1px;\n  border-top-right-radius: -1px;\n  border-bottom-right-radius: 0;\n  border-bottom-left-radius: 0;\n  border-top-left-radius: -1px;\n  -moz-background-clip: padding-box;\n  -webkit-background-clip: padding-box;\n  background-clip: padding-box;\n}\n.ui-grid-header-viewport {\n  overflow: hidden;\n}\n.ui-grid-header-canvas:before,\n.ui-grid-header-canvas:after {\n  content: \"\";\n  display: table;\n  line-height: 0;\n}\n.ui-grid-header-canvas:after {\n  clear: both;\n}\n.ui-grid-header-cell-wrapper {\n  position: relative;\n  display: table;\n  box-sizing: border-box;\n  height: 100%;\n}\n.ui-grid-header-cell-row {\n  display: table-row;\n  position: relative;\n}\n.ui-grid-header-cell {\n  position: relative;\n  box-sizing: border-box;\n  background-color: inherit;\n  border-right: 1px solid;\n  border-color: #d4d4d4;\n  display: table-cell;\n  -webkit-user-select: none;\n  -moz-user-select: none;\n  -ms-user-select: none;\n  user-select: none;\n  width: 0;\n}\n.ui-grid-header-cell:last-child {\n  border-right: 0;\n}\n.ui-grid-header-cell .sortable {\n  cursor: pointer;\n}\n.ui-grid-header-cell .ui-grid-sort-priority-number {\n  margin-left: -8px;\n}\n.ui-grid-header .ui-grid-vertical-bar {\n  top: 0;\n  bottom: 0;\n}\n.ui-grid-column-menu-button {\n  position: absolute;\n  right: 1px;\n  top: 0;\n}\n.ui-grid-column-menu-button .ui-grid-icon-angle-down {\n  vertical-align: sub;\n}\n.ui-grid-column-menu-button-last-col {\n  margin-right: 25px;\n}\n.ui-grid-column-menu {\n  position: absolute;\n}\n/* Slide up/down animations */\n.ui-grid-column-menu .ui-grid-menu .ui-grid-menu-mid.ng-hide-add,\n.ui-grid-column-menu .ui-grid-menu .ui-grid-menu-mid.ng-hide-remove {\n  -webkit-transition: all 0.05s linear;\n  -moz-transition: all 0.05s linear;\n  -o-transition: all 0.05s linear;\n  transition: all 0.05s linear;\n  display: block !important;\n}\n.ui-grid-column-menu .ui-grid-menu .ui-grid-menu-mid.ng-hide-add.ng-hide-add-active,\n.ui-grid-column-menu .ui-grid-menu .ui-grid-menu-mid.ng-hide-remove {\n  -webkit-transform: translateY(-100%);\n  -moz-transform: translateY(-100%);\n  -o-transform: translateY(-100%);\n  -ms-transform: translateY(-100%);\n  transform: translateY(-100%);\n}\n.ui-grid-column-menu .ui-grid-menu .ui-grid-menu-mid.ng-hide-add,\n.ui-grid-column-menu .ui-grid-menu .ui-grid-menu-mid.ng-hide-remove.ng-hide-remove-active {\n  -webkit-transform: translateY(0);\n  -moz-transform: translateY(0);\n  -o-transform: translateY(0);\n  -ms-transform: translateY(0);\n  transform: translateY(0);\n}\n/* Slide up/down animations */\n.ui-grid-menu-button .ui-grid-menu .ui-grid-menu-mid.ng-hide-add,\n.ui-grid-menu-button .ui-grid-menu .ui-grid-menu-mid.ng-hide-remove {\n  -webkit-transition: all 0.05s linear;\n  -moz-transition: all 0.05s linear;\n  -o-transition: all 0.05s linear;\n  transition: all 0.05s linear;\n  display: block !important;\n}\n.ui-grid-menu-button .ui-grid-menu .ui-grid-menu-mid.ng-hide-add.ng-hide-add-active,\n.ui-grid-menu-button .ui-grid-menu .ui-grid-menu-mid.ng-hide-remove {\n  -webkit-transform: translateY(-100%);\n  -moz-transform: translateY(-100%);\n  -o-transform: translateY(-100%);\n  -ms-transform: translateY(-100%);\n  transform: translateY(-100%);\n}\n.ui-grid-menu-button .ui-grid-menu .ui-grid-menu-mid.ng-hide-add,\n.ui-grid-menu-button .ui-grid-menu .ui-grid-menu-mid.ng-hide-remove.ng-hide-remove-active {\n  -webkit-transform: translateY(0);\n  -moz-transform: translateY(0);\n  -o-transform: translateY(0);\n  -ms-transform: translateY(0);\n  transform: translateY(0);\n}\n.ui-grid-filter-container {\n  padding: 4px 10px;\n  position: relative;\n}\n.ui-grid-filter-container .ui-grid-filter-button {\n  position: absolute;\n  top: 0;\n  bottom: 0;\n  right: 0;\n}\n.ui-grid-filter-container .ui-grid-filter-button [class^=\"ui-grid-icon\"] {\n  position: absolute;\n  top: 50%;\n  line-height: 32px;\n  margin-top: -16px;\n  right: 10px;\n  opacity: 0.66;\n}\n.ui-grid-filter-container .ui-grid-filter-button [class^=\"ui-grid-icon\"]:hover {\n  opacity: 1;\n}\n.ui-grid-filter-container .ui-grid-filter-button-select {\n  position: absolute;\n  top: 0;\n  bottom: 0;\n  right: 0;\n}\n.ui-grid-filter-container .ui-grid-filter-button-select [class^=\"ui-grid-icon\"] {\n  position: absolute;\n  top: 50%;\n  line-height: 32px;\n  margin-top: -16px;\n  right: 0px;\n  opacity: 0.66;\n}\n.ui-grid-filter-container .ui-grid-filter-button-select [class^=\"ui-grid-icon\"]:hover {\n  opacity: 1;\n}\ninput[type=\"text\"].ui-grid-filter-input {\n  padding: 0;\n  margin: 0;\n  border: 0;\n  width: 100%;\n  border: 1px solid #d4d4d4;\n  -webkit-border-top-right-radius: 0px;\n  -webkit-border-bottom-right-radius: 0;\n  -webkit-border-bottom-left-radius: 0;\n  -webkit-border-top-left-radius: 0;\n  -moz-border-radius-topright: 0px;\n  -moz-border-radius-bottomright: 0;\n  -moz-border-radius-bottomleft: 0;\n  -moz-border-radius-topleft: 0;\n  border-top-right-radius: 0px;\n  border-bottom-right-radius: 0;\n  border-bottom-left-radius: 0;\n  border-top-left-radius: 0;\n  -moz-background-clip: padding-box;\n  -webkit-background-clip: padding-box;\n  background-clip: padding-box;\n}\ninput[type=\"text\"].ui-grid-filter-input:hover {\n  border: 1px solid #d4d4d4;\n}\nselect.ui-grid-filter-select {\n  padding: 0;\n  margin: 0;\n  border: 0;\n  width: 90%;\n  border: 1px solid #d4d4d4;\n  -webkit-border-top-right-radius: 0px;\n  -webkit-border-bottom-right-radius: 0;\n  -webkit-border-bottom-left-radius: 0;\n  -webkit-border-top-left-radius: 0;\n  -moz-border-radius-topright: 0px;\n  -moz-border-radius-bottomright: 0;\n  -moz-border-radius-bottomleft: 0;\n  -moz-border-radius-topleft: 0;\n  border-top-right-radius: 0px;\n  border-bottom-right-radius: 0;\n  border-bottom-left-radius: 0;\n  border-top-left-radius: 0;\n  -moz-background-clip: padding-box;\n  -webkit-background-clip: padding-box;\n  background-clip: padding-box;\n}\nselect.ui-grid-filter-select:hover {\n  border: 1px solid #d4d4d4;\n}\n.ui-grid-filter-cancel-button-hidden select.ui-grid-filter-select {\n  width: 100%;\n}\n.ui-grid-render-container {\n  position: inherit;\n  -webkit-border-top-right-radius: 0;\n  -webkit-border-bottom-right-radius: 0px;\n  -webkit-border-bottom-left-radius: 0px;\n  -webkit-border-top-left-radius: 0;\n  -moz-border-radius-topright: 0;\n  -moz-border-radius-bottomright: 0px;\n  -moz-border-radius-bottomleft: 0px;\n  -moz-border-radius-topleft: 0;\n  border-top-right-radius: 0;\n  border-bottom-right-radius: 0px;\n  border-bottom-left-radius: 0px;\n  border-top-left-radius: 0;\n  -moz-background-clip: padding-box;\n  -webkit-background-clip: padding-box;\n  background-clip: padding-box;\n}\n.ui-grid-render-container:focus {\n  outline: none;\n}\n.ui-grid-viewport {\n  min-height: 20px;\n  position: relative;\n  overflow-y: scroll;\n  -webkit-overflow-scrolling: touch;\n}\n.ui-grid-viewport:focus {\n  outline: none !important;\n}\n.ui-grid-canvas {\n  position: relative;\n  padding-top: 1px;\n}\n.ui-grid-row:nth-child(odd) .ui-grid-cell {\n  background-color: #fdfdfd;\n}\n.ui-grid-row:nth-child(even) .ui-grid-cell {\n  background-color: #f3f3f3;\n}\n.ui-grid-row:last-child .ui-grid-cell {\n  border-bottom-color: #d4d4d4;\n  border-bottom-style: solid;\n}\n.ui-grid-no-row-overlay {\n  position: absolute;\n  top: 0;\n  bottom: 0;\n  left: 0;\n  right: 0;\n  margin: 10%;\n  background: #f3f3f3;\n  background: -webkit-gradient(linear, left bottom, left top, color-stop(0, #eeeeee), color-stop(1, #ffffff));\n  background: -ms-linear-gradient(bottom, #eeeeee, #ffffff);\n  background: -moz-linear-gradient(center bottom, #eeeeee 0%, #ffffff 100%);\n  background: -o-linear-gradient(#ffffff, #eeeeee);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#eeeeee', GradientType=0);\n  -webkit-border-top-right-radius: 0px;\n  -webkit-border-bottom-right-radius: 0;\n  -webkit-border-bottom-left-radius: 0;\n  -webkit-border-top-left-radius: 0;\n  -moz-border-radius-topright: 0px;\n  -moz-border-radius-bottomright: 0;\n  -moz-border-radius-bottomleft: 0;\n  -moz-border-radius-topleft: 0;\n  border-top-right-radius: 0px;\n  border-bottom-right-radius: 0;\n  border-bottom-left-radius: 0;\n  border-top-left-radius: 0;\n  -moz-background-clip: padding-box;\n  -webkit-background-clip: padding-box;\n  background-clip: padding-box;\n  border: 1px solid #d4d4d4;\n  font-size: 2em;\n  text-align: center;\n}\n.ui-grid-no-row-overlay > * {\n  position: absolute;\n  display: table;\n  margin: auto 0;\n  width: 100%;\n  top: 0;\n  bottom: 0;\n  left: 0;\n  right: 0;\n  opacity: 0.66;\n}\n.ui-grid-cell {\n  overflow: hidden;\n  float: left;\n  background-color: inherit;\n  border-right: 1px solid;\n  border-color: #d4d4d4;\n  box-sizing: border-box;\n}\n.ui-grid-cell:last-child {\n  border-right: 0;\n}\n.ui-grid-cell-contents {\n  padding: 5px;\n  -moz-box-sizing: border-box;\n  -webkit-box-sizing: border-box;\n  box-sizing: border-box;\n  white-space: nowrap;\n  -ms-text-overflow: ellipsis;\n  -o-text-overflow: ellipsis;\n  text-overflow: ellipsis;\n  overflow: hidden;\n  height: 100%;\n}\n.ui-grid-cell-contents-hidden {\n  visibility: hidden;\n  width: 0;\n  height: 0;\n  display: none;\n}\n.ui-grid-row .ui-grid-cell.ui-grid-row-header-cell {\n  background-color: #f0f0ee;\n  border-bottom: solid 1px #d4d4d4;\n}\n.ui-grid-footer-panel-background {\n  background: #f3f3f3;\n  background: -webkit-gradient(linear, left bottom, left top, color-stop(0, #eeeeee), color-stop(1, #ffffff));\n  background: -ms-linear-gradient(bottom, #eeeeee, #ffffff);\n  background: -moz-linear-gradient(center bottom, #eeeeee 0%, #ffffff 100%);\n  background: -o-linear-gradient(#ffffff, #eeeeee);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#eeeeee', GradientType=0);\n}\n.ui-grid-footer-panel {\n  position: relative;\n  border-bottom: 1px solid #d4d4d4;\n  border-top: 1px solid #d4d4d4;\n  overflow: hidden;\n  font-weight: bold;\n  background: #f3f3f3;\n  background: -webkit-gradient(linear, left bottom, left top, color-stop(0, #eeeeee), color-stop(1, #ffffff));\n  background: -ms-linear-gradient(bottom, #eeeeee, #ffffff);\n  background: -moz-linear-gradient(center bottom, #eeeeee 0%, #ffffff 100%);\n  background: -o-linear-gradient(#ffffff, #eeeeee);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#eeeeee', GradientType=0);\n  -webkit-border-top-right-radius: -1px;\n  -webkit-border-bottom-right-radius: 0;\n  -webkit-border-bottom-left-radius: 0;\n  -webkit-border-top-left-radius: -1px;\n  -moz-border-radius-topright: -1px;\n  -moz-border-radius-bottomright: 0;\n  -moz-border-radius-bottomleft: 0;\n  -moz-border-radius-topleft: -1px;\n  border-top-right-radius: -1px;\n  border-bottom-right-radius: 0;\n  border-bottom-left-radius: 0;\n  border-top-left-radius: -1px;\n  -moz-background-clip: padding-box;\n  -webkit-background-clip: padding-box;\n  background-clip: padding-box;\n}\n.ui-grid-grid-footer {\n  float: left;\n  width: 100%;\n}\n.ui-grid-footer-viewport {\n  overflow: hidden;\n}\n.ui-grid-footer-canvas {\n  position: relative;\n}\n.ui-grid-footer-canvas:before,\n.ui-grid-footer-canvas:after {\n  content: \"\";\n  display: table;\n  line-height: 0;\n}\n.ui-grid-footer-canvas:after {\n  clear: both;\n}\n.ui-grid-footer-cell-wrapper {\n  position: relative;\n  display: table;\n  box-sizing: border-box;\n  height: 100%;\n}\n.ui-grid-footer-cell-row {\n  display: table-row;\n}\n.ui-grid-footer-cell {\n  overflow: hidden;\n  background-color: inherit;\n  border-right: 1px solid;\n  border-color: #d4d4d4;\n  box-sizing: border-box;\n  display: table-cell;\n}\n.ui-grid-footer-cell:last-child {\n  border-right: 0;\n}\ninput[type=\"text\"].ui-grid-filter-input {\n  padding: 0;\n  margin: 0;\n  border: 0;\n  width: 100%;\n  border: 1px solid #d4d4d4;\n  -webkit-border-top-right-radius: 0px;\n  -webkit-border-bottom-right-radius: 0;\n  -webkit-border-bottom-left-radius: 0;\n  -webkit-border-top-left-radius: 0;\n  -moz-border-radius-topright: 0px;\n  -moz-border-radius-bottomright: 0;\n  -moz-border-radius-bottomleft: 0;\n  -moz-border-radius-topleft: 0;\n  border-top-right-radius: 0px;\n  border-bottom-right-radius: 0;\n  border-bottom-left-radius: 0;\n  border-top-left-radius: 0;\n  -moz-background-clip: padding-box;\n  -webkit-background-clip: padding-box;\n  background-clip: padding-box;\n}\ninput[type=\"text\"].ui-grid-filter-input:hover {\n  border: 1px solid #d4d4d4;\n}\n.ui-grid-menu-button {\n  z-index: 2;\n  position: absolute;\n  right: 0;\n  top: 0;\n  background: #f3f3f3;\n  border: 1px solid #d4d4d4;\n  cursor: pointer;\n  height: 31px;\n  font-weight: normal;\n}\n.ui-grid-menu-button .ui-grid-icon-container {\n  margin-top: 3px;\n}\n.ui-grid-menu-button .ui-grid-menu {\n  right: 0;\n}\n.ui-grid-menu-button .ui-grid-menu .ui-grid-menu-mid {\n  overflow: scroll;\n  border: 1px solid #d4d4d4;\n}\n.ui-grid-menu {\n  z-index: 2;\n  position: absolute;\n  padding: 0 10px 20px 10px;\n  cursor: pointer;\n  box-sizing: border-box;\n}\n.ui-grid-menu .ui-grid-menu-inner {\n  background: #f3f3f3;\n  border: 1px solid #d4d4d4;\n  position: relative;\n  white-space: nowrap;\n  -webkit-border-radius: 0px;\n  -moz-border-radius: 0px;\n  border-radius: 0px;\n  -webkit-box-shadow: 0 10px 20px rgba(0, 0, 0, 0.2), inset 0 12px 12px -14px rgba(0, 0, 0, 0.2);\n  -moz-box-shadow: 0 10px 20px rgba(0, 0, 0, 0.2), inset 0 12px 12px -14px rgba(0, 0, 0, 0.2);\n  box-shadow: 0 10px 20px rgba(0, 0, 0, 0.2), inset 0 12px 12px -14px rgba(0, 0, 0, 0.2);\n}\n.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button {\n  position: absolute;\n  right: 0px;\n  top: 0px;\n  display: inline-block;\n  margin-bottom: 0;\n  font-weight: normal;\n  text-align: center;\n  vertical-align: middle;\n  touch-action: manipulation;\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.42857143;\n  border-radius: 4px;\n  -webkit-user-select: none;\n  -moz-user-select: none;\n  -ms-user-select: none;\n  user-select: none;\n  padding: 1px 1px;\n  font-size: 10px;\n  line-height: 1;\n  border-radius: 2px;\n  color: transparent;\n  background-color: transparent;\n  border-color: transparent;\n}\n.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button:focus,\n.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button:active:focus,\n.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button.active:focus,\n.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button.focus,\n.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button:active.focus,\n.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button.active.focus {\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button:hover,\n.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button:focus,\n.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button.focus {\n  color: #333333;\n  text-decoration: none;\n}\n.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button:active,\n.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button.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.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button.disabled,\n.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button[disabled],\nfieldset[disabled] .ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button {\n  cursor: not-allowed;\n  opacity: 0.65;\n  filter: alpha(opacity=65);\n  -webkit-box-shadow: none;\n  box-shadow: none;\n}\na.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button.disabled,\nfieldset[disabled] a.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button {\n  pointer-events: none;\n}\n.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button:focus,\n.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button.focus {\n  color: transparent;\n  background-color: rgba(0, 0, 0, 0);\n  border-color: rgba(0, 0, 0, 0);\n}\n.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button:hover {\n  color: transparent;\n  background-color: rgba(0, 0, 0, 0);\n  border-color: rgba(0, 0, 0, 0);\n}\n.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button:active,\n.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button.active,\n.open > .dropdown-toggle.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button {\n  color: transparent;\n  background-color: rgba(0, 0, 0, 0);\n  border-color: rgba(0, 0, 0, 0);\n}\n.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button:active:hover,\n.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button.active:hover,\n.open > .dropdown-toggle.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button:hover,\n.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button:active:focus,\n.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button.active:focus,\n.open > .dropdown-toggle.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button:focus,\n.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button:active.focus,\n.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button.active.focus,\n.open > .dropdown-toggle.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button.focus {\n  color: transparent;\n  background-color: rgba(0, 0, 0, 0);\n  border-color: rgba(0, 0, 0, 0);\n}\n.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button:active,\n.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button.active,\n.open > .dropdown-toggle.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button {\n  background-image: none;\n}\n.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button.disabled:hover,\n.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button[disabled]:hover,\nfieldset[disabled] .ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button:hover,\n.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button.disabled:focus,\n.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button[disabled]:focus,\nfieldset[disabled] .ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button:focus,\n.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button.disabled.focus,\n.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button[disabled].focus,\nfieldset[disabled] .ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button.focus {\n  background-color: transparent;\n  border-color: transparent;\n}\n.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button .badge {\n  color: transparent;\n  background-color: transparent;\n}\n.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button > i {\n  opacity: 0.75;\n  color: black;\n}\n.ui-grid-menu .ui-grid-menu-inner ul {\n  margin: 0;\n  padding: 0;\n  list-style-type: none;\n}\n.ui-grid-menu .ui-grid-menu-inner ul li {\n  padding: 0px;\n}\n.ui-grid-menu .ui-grid-menu-inner ul li button {\n  min-width: 100%;\n  padding: 8px;\n  text-align: left;\n  background: transparent;\n  border: none;\n}\n.ui-grid-menu .ui-grid-menu-inner ul li button:hover,\n.ui-grid-menu .ui-grid-menu-inner ul li button:focus {\n  -webkit-box-shadow: inset 0 0 14px rgba(0, 0, 0, 0.2);\n  -moz-box-shadow: inset 0 0 14px rgba(0, 0, 0, 0.2);\n  box-shadow: inset 0 0 14px rgba(0, 0, 0, 0.2);\n}\n.ui-grid-menu .ui-grid-menu-inner ul li button.ui-grid-menu-item-active {\n  -webkit-box-shadow: inset 0 0 14px rgba(0, 0, 0, 0.2);\n  -moz-box-shadow: inset 0 0 14px rgba(0, 0, 0, 0.2);\n  box-shadow: inset 0 0 14px rgba(0, 0, 0, 0.2);\n  background-color: #cecece;\n}\n.ui-grid-menu .ui-grid-menu-inner ul li:not(:last-child) > button {\n  border-bottom: 1px solid #d4d4d4;\n}\n.ui-grid-sortarrow {\n  right: 5px;\n  position: absolute;\n  width: 20px;\n  top: 0;\n  bottom: 0;\n  background-position: center;\n}\n.ui-grid-sortarrow.down {\n  -webkit-transform: rotate(180deg);\n  -moz-transform: rotate(180deg);\n  -o-transform: rotate(180deg);\n  -ms-transform: rotate(180deg);\n  transform: rotate(180deg);\n}\n@font-face {\n  font-family: 'ui-grid';\n  src: url('ui-grid.eot');\n  src: url('ui-grid.eot#iefix') format('embedded-opentype'), url('ui-grid.woff') format('woff'), url('ui-grid.ttf') format('truetype'), url('ui-grid.svg?#ui-grid') format('svg');\n  font-weight: normal;\n  font-style: normal;\n}\n/* Chrome hack: SVG is rendered more smooth in Windozze. 100% magic, uncomment if you need it. */\n/* Note, that will break hinting! In other OS-es font will be not as sharp as it could be */\n/*\n@media screen and (-webkit-min-device-pixel-ratio:0) {\n  @font-face {\n    font-family: 'ui-grid';\n    src: url('@{font-path}ui-grid.svg?12312827#ui-grid') format('svg');\n  }\n}\n*/\n[class^=\"ui-grid-icon\"]:before,\n[class*=\" ui-grid-icon\"]:before {\n  font-family: \"ui-grid\";\n  font-style: normal;\n  font-weight: normal;\n  speak: none;\n  display: inline-block;\n  text-decoration: inherit;\n  width: 1em;\n  margin-right: .2em;\n  text-align: center;\n  /* opacity: .8; */\n  /* For safety - reset parent styles, that can break glyph codes*/\n  font-variant: normal;\n  text-transform: none;\n  /* fix buttons height, for twitter bootstrap */\n  line-height: 1em;\n  /* Animation center compensation - margins should be symmetric */\n  /* remove if not needed */\n  margin-left: .2em;\n  /* you can be more comfortable with increased icons size */\n  /* font-size: 120%; */\n  /* Uncomment for 3D effect */\n  /* text-shadow: 1px 1px 1px rgba(127, 127, 127, 0.3); */\n}\n.ui-grid-icon-blank::before {\n  width: 1em;\n  content: ' ';\n}\n/*\n* RTL Styles\n*/\n.ui-grid[dir=rtl] .ui-grid-header-cell,\n.ui-grid[dir=rtl] .ui-grid-footer-cell,\n.ui-grid[dir=rtl] .ui-grid-cell {\n  float: right !important;\n}\n.ui-grid[dir=rtl] .ui-grid-column-menu-button {\n  position: absolute;\n  left: 1px;\n  top: 0;\n  right: inherit;\n}\n.ui-grid[dir=rtl] .ui-grid-cell:first-child,\n.ui-grid[dir=rtl] .ui-grid-header-cell:first-child,\n.ui-grid[dir=rtl] .ui-grid-footer-cell:first-child {\n  border-right: 0;\n}\n.ui-grid[dir=rtl] .ui-grid-cell:last-child,\n.ui-grid[dir=rtl] .ui-grid-header-cell:last-child {\n  border-right: 1px solid #d4d4d4;\n  border-left: 0;\n}\n.ui-grid[dir=rtl] .ui-grid-header-cell:first-child .ui-grid-vertical-bar,\n.ui-grid[dir=rtl] .ui-grid-footer-cell:first-child .ui-grid-vertical-bar,\n.ui-grid[dir=rtl] .ui-grid-cell:first-child .ui-grid-vertical-bar {\n  width: 0;\n}\n.ui-grid[dir=rtl] .ui-grid-menu-button {\n  z-index: 2;\n  position: absolute;\n  left: 0;\n  right: auto;\n  background: #f3f3f3;\n  border: 1px solid #d4d4d4;\n  cursor: pointer;\n  min-height: 27px;\n  font-weight: normal;\n}\n.ui-grid[dir=rtl] .ui-grid-menu-button .ui-grid-menu {\n  left: 0;\n  right: auto;\n}\n.ui-grid[dir=rtl] .ui-grid-filter-container .ui-grid-filter-button {\n  right: initial;\n  left: 0;\n}\n.ui-grid[dir=rtl] .ui-grid-filter-container .ui-grid-filter-button [class^=\"ui-grid-icon\"] {\n  right: initial;\n  left: 10px;\n}\n/*\n   Animation example, for spinners\n*/\n.ui-grid-animate-spin {\n  -moz-animation: ui-grid-spin 2s infinite linear;\n  -o-animation: ui-grid-spin 2s infinite linear;\n  -webkit-animation: ui-grid-spin 2s infinite linear;\n  animation: ui-grid-spin 2s infinite linear;\n  display: inline-block;\n}\n@-moz-keyframes ui-grid-spin {\n  0% {\n    -moz-transform: rotate(0deg);\n    -o-transform: rotate(0deg);\n    -webkit-transform: rotate(0deg);\n    transform: rotate(0deg);\n  }\n  100% {\n    -moz-transform: rotate(359deg);\n    -o-transform: rotate(359deg);\n    -webkit-transform: rotate(359deg);\n    transform: rotate(359deg);\n  }\n}\n@-webkit-keyframes ui-grid-spin {\n  0% {\n    -moz-transform: rotate(0deg);\n    -o-transform: rotate(0deg);\n    -webkit-transform: rotate(0deg);\n    transform: rotate(0deg);\n  }\n  100% {\n    -moz-transform: rotate(359deg);\n    -o-transform: rotate(359deg);\n    -webkit-transform: rotate(359deg);\n    transform: rotate(359deg);\n  }\n}\n@-o-keyframes ui-grid-spin {\n  0% {\n    -moz-transform: rotate(0deg);\n    -o-transform: rotate(0deg);\n    -webkit-transform: rotate(0deg);\n    transform: rotate(0deg);\n  }\n  100% {\n    -moz-transform: rotate(359deg);\n    -o-transform: rotate(359deg);\n    -webkit-transform: rotate(359deg);\n    transform: rotate(359deg);\n  }\n}\n@-ms-keyframes ui-grid-spin {\n  0% {\n    -moz-transform: rotate(0deg);\n    -o-transform: rotate(0deg);\n    -webkit-transform: rotate(0deg);\n    transform: rotate(0deg);\n  }\n  100% {\n    -moz-transform: rotate(359deg);\n    -o-transform: rotate(359deg);\n    -webkit-transform: rotate(359deg);\n    transform: rotate(359deg);\n  }\n}\n@keyframes ui-grid-spin {\n  0% {\n    -moz-transform: rotate(0deg);\n    -o-transform: rotate(0deg);\n    -webkit-transform: rotate(0deg);\n    transform: rotate(0deg);\n  }\n  100% {\n    -moz-transform: rotate(359deg);\n    -o-transform: rotate(359deg);\n    -webkit-transform: rotate(359deg);\n    transform: rotate(359deg);\n  }\n}\n/*---------------------------------------------------\n    LESS Elements 0.9\n  ---------------------------------------------------\n    A set of useful LESS mixins\n    More info at: http://lesselements.com\n  ---------------------------------------------------*/\n/* This file contains variable declarations (do not remove this line) */\n/*-- VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/\n/**\n* @section Grid styles\n*/\n/**\n* @section Header styles\n*/\n/** @description Colors for header gradient */\n/**\n* @section Grid body styles\n*/\n/** @description Colors used for row alternation */\n/**\n* @section Sort arrow colors\n*/\n/**\n* @section Scrollbar styles\n*/\n/**\n* @section font library path\n*/\n/*-- END VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/\n\n/* This file contains variable declarations (do not remove this line) */\n/*-- VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/\n/**\n* @section Grid styles\n*/\n/**\n* @section Header styles\n*/\n/** @description Colors for header gradient */\n/**\n* @section Grid body styles\n*/\n/** @description Colors used for row alternation */\n/**\n* @section Sort arrow colors\n*/\n/**\n* @section Scrollbar styles\n*/\n/**\n* @section font library path\n*/\n/*-- END VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/\n#ui-grid-twbs #ui-grid-twbs .form-horizontal .form-group:before,\n#ui-grid-twbs #ui-grid-twbs .form-horizontal .form-group:after,\n#ui-grid-twbs #ui-grid-twbs .btn-toolbar:before,\n#ui-grid-twbs #ui-grid-twbs .btn-toolbar:after,\n#ui-grid-twbs #ui-grid-twbs .btn-group-vertical > .btn-group:before,\n#ui-grid-twbs #ui-grid-twbs .btn-group-vertical > .btn-group:after {\n  content: \" \";\n  display: table;\n}\n#ui-grid-twbs #ui-grid-twbs .form-horizontal .form-group:after,\n#ui-grid-twbs #ui-grid-twbs .btn-toolbar:after,\n#ui-grid-twbs #ui-grid-twbs .btn-group-vertical > .btn-group:after {\n  clear: both;\n}\n.ui-grid-cell-focus {\n  outline: 0;\n  background-color: #b3c4c7;\n}\n.ui-grid-focuser {\n  position: absolute;\n  left: 0px;\n  top: 0px;\n  z-index: -1;\n  width: 100%;\n  height: 100%;\n}\n.ui-grid-focuser: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.ui-grid-offscreen {\n  display: block;\n  position: absolute;\n  left: -10000px;\n  top: -10000px;\n  clip: rect(0px, 0px, 0px, 0px);\n}\n\n/* This file contains variable declarations (do not remove this line) */\n/*-- VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/\n/**\n* @section Grid styles\n*/\n/**\n* @section Header styles\n*/\n/** @description Colors for header gradient */\n/**\n* @section Grid body styles\n*/\n/** @description Colors used for row alternation */\n/**\n* @section Sort arrow colors\n*/\n/**\n* @section Scrollbar styles\n*/\n/**\n* @section font library path\n*/\n/*-- END VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/\ndiv.ui-grid-cell input {\n  border-radius: inherit;\n  padding: 0;\n  width: 100%;\n  color: inherit;\n  height: auto;\n  font: inherit;\n  outline: none;\n}\ndiv.ui-grid-cell input:focus {\n  color: inherit;\n  outline: none;\n}\ndiv.ui-grid-cell input[type=\"checkbox\"] {\n  margin: 9px 0 0 6px;\n  width: auto;\n}\ndiv.ui-grid-cell input.ng-invalid {\n  border: 1px solid #fc8f8f;\n}\ndiv.ui-grid-cell input.ng-valid {\n  border: 1px solid #d4d4d4;\n}\n\n/* This file contains variable declarations (do not remove this line) */\n/*-- VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/\n/**\n* @section Grid styles\n*/\n/**\n* @section Header styles\n*/\n/** @description Colors for header gradient */\n/**\n* @section Grid body styles\n*/\n/** @description Colors used for row alternation */\n/**\n* @section Sort arrow colors\n*/\n/**\n* @section Scrollbar styles\n*/\n/**\n* @section font library path\n*/\n/*-- END VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/\n.expandableRow .ui-grid-row:nth-child(odd) .ui-grid-cell {\n  background-color: #fdfdfd;\n}\n.expandableRow .ui-grid-row:nth-child(even) .ui-grid-cell {\n  background-color: #f3f3f3;\n}\n.ui-grid-cell.ui-grid-disable-selection.ui-grid-row-header-cell {\n  pointer-events: none;\n}\n.ui-grid-expandable-buttons-cell i {\n  pointer-events: all;\n}\n.scrollFiller {\n  float: left;\n  border: 1px solid #d4d4d4;\n}\n\n/* This file contains variable declarations (do not remove this line) */\n/*-- VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/\n/**\n* @section Grid styles\n*/\n/**\n* @section Header styles\n*/\n/** @description Colors for header gradient */\n/**\n* @section Grid body styles\n*/\n/** @description Colors used for row alternation */\n/**\n* @section Sort arrow colors\n*/\n/**\n* @section Scrollbar styles\n*/\n/**\n* @section font library path\n*/\n/*-- END VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/\n\n/* This file contains variable declarations (do not remove this line) */\n/*-- VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/\n/**\n* @section Grid styles\n*/\n/**\n* @section Header styles\n*/\n/** @description Colors for header gradient */\n/**\n* @section Grid body styles\n*/\n/** @description Colors used for row alternation */\n/**\n* @section Sort arrow colors\n*/\n/**\n* @section Scrollbar styles\n*/\n/**\n* @section font library path\n*/\n/*-- END VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/\n.ui-grid-tree-header-row {\n  font-weight: bold !important;\n}\n\n/* This file contains variable declarations (do not remove this line) */\n/*-- VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/\n/**\n* @section Grid styles\n*/\n/**\n* @section Header styles\n*/\n/** @description Colors for header gradient */\n/**\n* @section Grid body styles\n*/\n/** @description Colors used for row alternation */\n/**\n* @section Sort arrow colors\n*/\n/**\n* @section Scrollbar styles\n*/\n/**\n* @section font library path\n*/\n/*-- END VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/\n\n/* This file contains variable declarations (do not remove this line) */\n/*-- VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/\n/**\n* @section Grid styles\n*/\n/**\n* @section Header styles\n*/\n/** @description Colors for header gradient */\n/**\n* @section Grid body styles\n*/\n/** @description Colors used for row alternation */\n/**\n* @section Sort arrow colors\n*/\n/**\n* @section Scrollbar styles\n*/\n/**\n* @section font library path\n*/\n/*-- END VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/\n.movingColumn {\n  position: absolute;\n  top: 0;\n  border: 1px solid #d4d4d4;\n  box-shadow: inset 0 0 14px rgba(0, 0, 0, 0.2);\n}\n.movingColumn .ui-grid-icon-angle-down {\n  display: none;\n}\n\n/* This file contains variable declarations (do not remove this line) */\n/*-- VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/\n/**\n* @section Grid styles\n*/\n/**\n* @section Header styles\n*/\n/** @description Colors for header gradient */\n/**\n* @section Grid body styles\n*/\n/** @description Colors used for row alternation */\n/**\n* @section Sort arrow colors\n*/\n/**\n* @section Scrollbar styles\n*/\n/**\n* @section font library path\n*/\n/*-- END VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/\n/*---------------------------------------------------\n    LESS Elements 0.9\n  ---------------------------------------------------\n    A set of useful LESS mixins\n    More info at: http://lesselements.com\n  ---------------------------------------------------*/\n#ui-grid-twbs #ui-grid-twbs .form-horizontal .form-group:before,\n#ui-grid-twbs #ui-grid-twbs .form-horizontal .form-group:after,\n#ui-grid-twbs #ui-grid-twbs .btn-toolbar:before,\n#ui-grid-twbs #ui-grid-twbs .btn-toolbar:after,\n#ui-grid-twbs #ui-grid-twbs .btn-group-vertical > .btn-group:before,\n#ui-grid-twbs #ui-grid-twbs .btn-group-vertical > .btn-group:after {\n  content: \" \";\n  display: table;\n}\n#ui-grid-twbs #ui-grid-twbs .form-horizontal .form-group:after,\n#ui-grid-twbs #ui-grid-twbs .btn-toolbar:after,\n#ui-grid-twbs #ui-grid-twbs .btn-group-vertical > .btn-group:after {\n  clear: both;\n}\n.ui-grid-pager-panel {\n  position: absolute;\n  left: 0;\n  bottom: 0;\n  width: 100%;\n  padding-top: 3px;\n  padding-bottom: 3px;\n  box-sizing: content-box;\n}\n.ui-grid-pager-container {\n  float: left;\n}\n.ui-grid-pager-control {\n  margin-right: 10px;\n  margin-left: 10px;\n  min-width: 135px;\n  float: left;\n}\n.ui-grid-pager-control button {\n  height: 25px;\n  min-width: 26px;\n  display: inline-block;\n  margin-bottom: 0;\n  font-weight: normal;\n  text-align: center;\n  vertical-align: middle;\n  touch-action: manipulation;\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.42857143;\n  border-radius: 4px;\n  -webkit-user-select: none;\n  -moz-user-select: none;\n  -ms-user-select: none;\n  user-select: none;\n  color: #eeeeee;\n  background-color: #f3f3f3;\n  border-color: #cccccc;\n}\n.ui-grid-pager-control button:focus,\n.ui-grid-pager-control button:active:focus,\n.ui-grid-pager-control button.active:focus,\n.ui-grid-pager-control button.focus,\n.ui-grid-pager-control button:active.focus,\n.ui-grid-pager-control button.active.focus {\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n.ui-grid-pager-control button:hover,\n.ui-grid-pager-control button:focus,\n.ui-grid-pager-control button.focus {\n  color: #333333;\n  text-decoration: none;\n}\n.ui-grid-pager-control button:active,\n.ui-grid-pager-control button.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.ui-grid-pager-control button.disabled,\n.ui-grid-pager-control button[disabled],\nfieldset[disabled] .ui-grid-pager-control button {\n  cursor: not-allowed;\n  opacity: 0.65;\n  filter: alpha(opacity=65);\n  -webkit-box-shadow: none;\n  box-shadow: none;\n}\na.ui-grid-pager-control button.disabled,\nfieldset[disabled] a.ui-grid-pager-control button {\n  pointer-events: none;\n}\n.ui-grid-pager-control button:focus,\n.ui-grid-pager-control button.focus {\n  color: #eeeeee;\n  background-color: #dadada;\n  border-color: #8c8c8c;\n}\n.ui-grid-pager-control button:hover {\n  color: #eeeeee;\n  background-color: #dadada;\n  border-color: #adadad;\n}\n.ui-grid-pager-control button:active,\n.ui-grid-pager-control button.active,\n.open > .dropdown-toggle.ui-grid-pager-control button {\n  color: #eeeeee;\n  background-color: #dadada;\n  border-color: #adadad;\n}\n.ui-grid-pager-control button:active:hover,\n.ui-grid-pager-control button.active:hover,\n.open > .dropdown-toggle.ui-grid-pager-control button:hover,\n.ui-grid-pager-control button:active:focus,\n.ui-grid-pager-control button.active:focus,\n.open > .dropdown-toggle.ui-grid-pager-control button:focus,\n.ui-grid-pager-control button:active.focus,\n.ui-grid-pager-control button.active.focus,\n.open > .dropdown-toggle.ui-grid-pager-control button.focus {\n  color: #eeeeee;\n  background-color: #c8c8c8;\n  border-color: #8c8c8c;\n}\n.ui-grid-pager-control button:active,\n.ui-grid-pager-control button.active,\n.open > .dropdown-toggle.ui-grid-pager-control button {\n  background-image: none;\n}\n.ui-grid-pager-control button.disabled:hover,\n.ui-grid-pager-control button[disabled]:hover,\nfieldset[disabled] .ui-grid-pager-control button:hover,\n.ui-grid-pager-control button.disabled:focus,\n.ui-grid-pager-control button[disabled]:focus,\nfieldset[disabled] .ui-grid-pager-control button:focus,\n.ui-grid-pager-control button.disabled.focus,\n.ui-grid-pager-control button[disabled].focus,\nfieldset[disabled] .ui-grid-pager-control button.focus {\n  background-color: #f3f3f3;\n  border-color: #cccccc;\n}\n.ui-grid-pager-control button .badge {\n  color: #f3f3f3;\n  background-color: #eeeeee;\n}\n.ui-grid-pager-control input {\n  display: block;\n  width: 100%;\n  height: 34px;\n  padding: 6px 12px;\n  font-size: 14px;\n  line-height: 1.42857143;\n  color: #555555;\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  -o-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  height: 30px;\n  padding: 5px 10px;\n  font-size: 12px;\n  line-height: 1.5;\n  border-radius: 3px;\n  display: inline;\n  height: 26px;\n  width: 50px;\n  vertical-align: top;\n}\n.ui-grid-pager-control input: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.ui-grid-pager-control input::-moz-placeholder {\n  color: #999999;\n  opacity: 1;\n}\n.ui-grid-pager-control input:-ms-input-placeholder {\n  color: #999999;\n}\n.ui-grid-pager-control input::-webkit-input-placeholder {\n  color: #999999;\n}\n.ui-grid-pager-control input::-ms-expand {\n  border: 0;\n  background-color: transparent;\n}\n.ui-grid-pager-control input[disabled],\n.ui-grid-pager-control input[readonly],\nfieldset[disabled] .ui-grid-pager-control input {\n  background-color: #eeeeee;\n  opacity: 1;\n}\n.ui-grid-pager-control input[disabled],\nfieldset[disabled] .ui-grid-pager-control input {\n  cursor: not-allowed;\n}\ntextarea.ui-grid-pager-control input {\n  height: auto;\n}\nselect.ui-grid-pager-control input {\n  height: 30px;\n  line-height: 30px;\n}\ntextarea.ui-grid-pager-control input,\nselect[multiple].ui-grid-pager-control input {\n  height: auto;\n}\n.ui-grid-pager-control .ui-grid-pager-max-pages-number {\n  vertical-align: bottom;\n}\n.ui-grid-pager-control .ui-grid-pager-max-pages-number > * {\n  vertical-align: middle;\n}\n.ui-grid-pager-control .first-bar {\n  width: 10px;\n  border-left: 2px solid #4d4d4d;\n  margin-top: -6px;\n  height: 12px;\n  margin-left: -3px;\n}\n.ui-grid-pager-control .first-bar-rtl {\n  width: 10px;\n  border-left: 2px solid #4d4d4d;\n  margin-top: -6px;\n  height: 12px;\n  margin-right: -7px;\n}\n.ui-grid-pager-control .first-triangle {\n  width: 0;\n  height: 0;\n  border-style: solid;\n  border-width: 5px 8.7px 5px 0;\n  border-color: transparent #4d4d4d transparent transparent;\n  margin-left: 2px;\n}\n.ui-grid-pager-control .next-triangle {\n  margin-left: 1px;\n}\n.ui-grid-pager-control .prev-triangle {\n  margin-left: 0;\n}\n.ui-grid-pager-control .last-triangle {\n  width: 0;\n  height: 0;\n  border-style: solid;\n  border-width: 5px 0 5px 8.7px;\n  border-color: transparent transparent transparent #4d4d4d;\n  margin-left: -1px;\n}\n.ui-grid-pager-control .last-bar {\n  width: 10px;\n  border-left: 2px solid #4d4d4d;\n  margin-top: -6px;\n  height: 12px;\n  margin-left: 1px;\n}\n.ui-grid-pager-control .last-bar-rtl {\n  width: 10px;\n  border-left: 2px solid #4d4d4d;\n  margin-top: -6px;\n  height: 12px;\n  margin-right: -11px;\n}\n.ui-grid-pager-row-count-picker {\n  float: left;\n}\n.ui-grid-pager-row-count-picker select {\n  display: block;\n  width: 100%;\n  height: 34px;\n  padding: 6px 12px;\n  font-size: 14px;\n  line-height: 1.42857143;\n  color: #555555;\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  -o-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  height: 30px;\n  padding: 5px 10px;\n  font-size: 12px;\n  line-height: 1.5;\n  border-radius: 3px;\n  height: 26px;\n  width: 67px;\n  display: inline;\n}\n.ui-grid-pager-row-count-picker select: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.ui-grid-pager-row-count-picker select::-moz-placeholder {\n  color: #999999;\n  opacity: 1;\n}\n.ui-grid-pager-row-count-picker select:-ms-input-placeholder {\n  color: #999999;\n}\n.ui-grid-pager-row-count-picker select::-webkit-input-placeholder {\n  color: #999999;\n}\n.ui-grid-pager-row-count-picker select::-ms-expand {\n  border: 0;\n  background-color: transparent;\n}\n.ui-grid-pager-row-count-picker select[disabled],\n.ui-grid-pager-row-count-picker select[readonly],\nfieldset[disabled] .ui-grid-pager-row-count-picker select {\n  background-color: #eeeeee;\n  opacity: 1;\n}\n.ui-grid-pager-row-count-picker select[disabled],\nfieldset[disabled] .ui-grid-pager-row-count-picker select {\n  cursor: not-allowed;\n}\ntextarea.ui-grid-pager-row-count-picker select {\n  height: auto;\n}\nselect.ui-grid-pager-row-count-picker select {\n  height: 30px;\n  line-height: 30px;\n}\ntextarea.ui-grid-pager-row-count-picker select,\nselect[multiple].ui-grid-pager-row-count-picker select {\n  height: auto;\n}\n.ui-grid-pager-row-count-picker .ui-grid-pager-row-count-label {\n  margin-top: 3px;\n}\n.ui-grid-pager-count-container {\n  float: right;\n  margin-top: 4px;\n  min-width: 50px;\n}\n.ui-grid-pager-count-container .ui-grid-pager-count {\n  margin-right: 10px;\n  margin-left: 10px;\n  float: right;\n}\n\n/* This file contains variable declarations (do not remove this line) */\n/*-- VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/\n/**\n* @section Grid styles\n*/\n/**\n* @section Header styles\n*/\n/** @description Colors for header gradient */\n/**\n* @section Grid body styles\n*/\n/** @description Colors used for row alternation */\n/**\n* @section Sort arrow colors\n*/\n/**\n* @section Scrollbar styles\n*/\n/**\n* @section font library path\n*/\n/*-- END VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/\n.ui-grid-pinned-container {\n  position: absolute;\n  display: inline;\n  top: 0;\n}\n.ui-grid-pinned-container.ui-grid-pinned-container-left {\n  float: left;\n  left: 0;\n}\n.ui-grid-pinned-container.ui-grid-pinned-container-right {\n  float: right;\n  right: 0;\n}\n.ui-grid-pinned-container.ui-grid-pinned-container-left .ui-grid-header-cell:last-child {\n  box-sizing: border-box;\n  border-right: 1px solid;\n  border-width: 1px;\n  border-right-color: #aeaeae;\n}\n.ui-grid-pinned-container.ui-grid-pinned-container-left .ui-grid-cell:last-child {\n  box-sizing: border-box;\n  border-right: 1px solid;\n  border-width: 1px;\n  border-right-color: #aeaeae;\n}\n.ui-grid-pinned-container.ui-grid-pinned-container-left .ui-grid-header-cell:not(:last-child) .ui-grid-vertical-bar,\n.ui-grid-pinned-container .ui-grid-cell:not(:last-child) .ui-grid-vertical-bar {\n  width: 1px;\n}\n.ui-grid-pinned-container.ui-grid-pinned-container-left .ui-grid-header-cell:not(:last-child) .ui-grid-vertical-bar {\n  background-color: #d4d4d4;\n}\n.ui-grid-pinned-container.ui-grid-pinned-container-left .ui-grid-cell:not(:last-child) .ui-grid-vertical-bar {\n  background-color: #aeaeae;\n}\n.ui-grid-pinned-container.ui-grid-pinned-container-left .ui-grid-header-cell:last-child .ui-grid-vertical-bar {\n  right: -1px;\n  width: 1px;\n  background-color: #aeaeae;\n}\n.ui-grid-pinned-container.ui-grid-pinned-container-right .ui-grid-header-cell:first-child {\n  box-sizing: border-box;\n  border-left: 1px solid;\n  border-width: 1px;\n  border-left-color: #aeaeae;\n}\n.ui-grid-pinned-container.ui-grid-pinned-container-right .ui-grid-cell:first-child {\n  box-sizing: border-box;\n  border-left: 1px solid;\n  border-width: 1px;\n  border-left-color: #aeaeae;\n}\n.ui-grid-pinned-container.ui-grid-pinned-container-right .ui-grid-header-cell:not(:first-child) .ui-grid-vertical-bar,\n.ui-grid-pinned-container .ui-grid-cell:not(:first-child) .ui-grid-vertical-bar {\n  width: 1px;\n}\n.ui-grid-pinned-container.ui-grid-pinned-container-right .ui-grid-header-cell:not(:first-child) .ui-grid-vertical-bar {\n  background-color: #d4d4d4;\n}\n.ui-grid-pinned-container.ui-grid-pinned-container-right .ui-grid-cell:not(:last-child) .ui-grid-vertical-bar {\n  background-color: #aeaeae;\n}\n.ui-grid-pinned-container.ui-grid-pinned-container-first .ui-grid-header-cell:first-child .ui-grid-vertical-bar {\n  left: -1px;\n  width: 1px;\n  background-color: #aeaeae;\n}\n\n/* This file contains variable declarations (do not remove this line) */\n/*-- VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/\n/**\n* @section Grid styles\n*/\n/**\n* @section Header styles\n*/\n/** @description Colors for header gradient */\n/**\n* @section Grid body styles\n*/\n/** @description Colors used for row alternation */\n/**\n* @section Sort arrow colors\n*/\n/**\n* @section Scrollbar styles\n*/\n/**\n* @section font library path\n*/\n/*-- END VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/\n.ui-grid-column-resizer {\n  top: 0;\n  bottom: 0;\n  width: 5px;\n  position: absolute;\n  cursor: col-resize;\n}\n.ui-grid-column-resizer.left {\n  left: 0;\n}\n.ui-grid-column-resizer.right {\n  right: 0;\n}\n.ui-grid-header-cell:last-child .ui-grid-column-resizer.right {\n  border-right: 1px solid #d4d4d4;\n}\n.ui-grid[dir=rtl] .ui-grid-header-cell:last-child .ui-grid-column-resizer.right {\n  border-right: 0;\n}\n.ui-grid[dir=rtl] .ui-grid-header-cell:last-child .ui-grid-column-resizer.left {\n  border-left: 1px solid #d4d4d4;\n}\n.ui-grid.column-resizing {\n  cursor: col-resize;\n}\n.ui-grid.column-resizing .ui-grid-resize-overlay {\n  position: absolute;\n  top: 0;\n  height: 100%;\n  width: 1px;\n  background-color: #aeaeae;\n}\n\n/* This file contains variable declarations (do not remove this line) */\n/*-- VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/\n/**\n* @section Grid styles\n*/\n/**\n* @section Header styles\n*/\n/** @description Colors for header gradient */\n/**\n* @section Grid body styles\n*/\n/** @description Colors used for row alternation */\n/**\n* @section Sort arrow colors\n*/\n/**\n* @section Scrollbar styles\n*/\n/**\n* @section font library path\n*/\n/*-- END VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/\n.ui-grid-row-saving .ui-grid-cell {\n  color: #848484 !important;\n}\n.ui-grid-row-dirty .ui-grid-cell {\n  color: #610b38;\n}\n.ui-grid-row-error .ui-grid-cell {\n  color: #ff0000 !important;\n}\n\n/* This file contains variable declarations (do not remove this line) */\n/*-- VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/\n/**\n* @section Grid styles\n*/\n/**\n* @section Header styles\n*/\n/** @description Colors for header gradient */\n/**\n* @section Grid body styles\n*/\n/** @description Colors used for row alternation */\n/**\n* @section Sort arrow colors\n*/\n/**\n* @section Scrollbar styles\n*/\n/**\n* @section font library path\n*/\n/*-- END VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/\n.ui-grid-row.ui-grid-row-selected > [ui-grid-row] > .ui-grid-cell {\n  background-color: #c9dde1;\n}\n.ui-grid-disable-selection {\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  cursor: default;\n}\n.ui-grid-selection-row-header-buttons {\n  cursor: pointer;\n  opacity: 0.1;\n}\n.ui-grid-selection-row-header-buttons.ui-grid-row-selected {\n  opacity: 1;\n}\n.ui-grid-selection-row-header-buttons.ui-grid-all-selected {\n  opacity: 1;\n}\n\n/* This file contains variable declarations (do not remove this line) */\n/*-- VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/\n/**\n* @section Grid styles\n*/\n/**\n* @section Header styles\n*/\n/** @description Colors for header gradient */\n/**\n* @section Grid body styles\n*/\n/** @description Colors used for row alternation */\n/**\n* @section Sort arrow colors\n*/\n/**\n* @section Scrollbar styles\n*/\n/**\n* @section font library path\n*/\n/*-- END VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/\n.ui-grid-tree-row-header-buttons.ui-grid-tree-header {\n  cursor: pointer;\n  opacity: 1;\n}\n\n/* This file contains variable declarations (do not remove this line) */\n/*-- VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/\n/**\n* @section Grid styles\n*/\n/**\n* @section Header styles\n*/\n/** @description Colors for header gradient */\n/**\n* @section Grid body styles\n*/\n/** @description Colors used for row alternation */\n/**\n* @section Sort arrow colors\n*/\n/**\n* @section Scrollbar styles\n*/\n/**\n* @section font library path\n*/\n/*-- END VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/\n.ui-grid-tree-header-row {\n  font-weight: bold !important;\n}\n.ui-grid-tree-header-row .ui-grid-cell.ui-grid-disable-selection.ui-grid-row-header-cell {\n  pointer-events: all;\n}\n\n/* This file contains variable declarations (do not remove this line) */\n/*-- VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/\n/**\n* @section Grid styles\n*/\n/**\n* @section Header styles\n*/\n/** @description Colors for header gradient */\n/**\n* @section Grid body styles\n*/\n/** @description Colors used for row alternation */\n/**\n* @section Sort arrow colors\n*/\n/**\n* @section Scrollbar styles\n*/\n/**\n* @section font library path\n*/\n/*-- END VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/\ndiv.ui-grid-cell-contents.invalid {\n  border: 1px solid #fc8f8f;\n}\n\n.ui-grid-icon-plus-squared:before {\n  content: '\\c350';\n}\n/* '썐' */\n.ui-grid-icon-minus-squared:before {\n  content: '\\c351';\n}\n/* '썑' */\n.ui-grid-icon-search:before {\n  content: '\\c352';\n}\n/* '썒' */\n.ui-grid-icon-cancel:before {\n  content: '\\c353';\n}\n/* '썓' */\n.ui-grid-icon-info-circled:before {\n  content: '\\c354';\n}\n/* '썔' */\n.ui-grid-icon-lock:before {\n  content: '\\c355';\n}\n/* '썕' */\n.ui-grid-icon-lock-open:before {\n  content: '\\c356';\n}\n/* '썖' */\n.ui-grid-icon-pencil:before {\n  content: '\\c357';\n}\n/* '썗' */\n.ui-grid-icon-down-dir:before {\n  content: '\\c358';\n}\n/* '썘' */\n.ui-grid-icon-up-dir:before {\n  content: '\\c359';\n}\n/* '썙' */\n.ui-grid-icon-left-dir:before {\n  content: '\\c35a';\n}\n/* '썚' */\n.ui-grid-icon-right-dir:before {\n  content: '\\c35b';\n}\n/* '썛' */\n.ui-grid-icon-left-open:before {\n  content: '\\c35c';\n}\n/* '썜' */\n.ui-grid-icon-right-open:before {\n  content: '\\c35d';\n}\n/* '썝' */\n.ui-grid-icon-angle-down:before {\n  content: '\\c35e';\n}\n/* '썞' */\n.ui-grid-icon-filter:before {\n  content: '\\c35f';\n}\n/* '썟' */\n.ui-grid-icon-sort-alt-up:before {\n  content: '\\c360';\n}\n/* '썠' */\n.ui-grid-icon-sort-alt-down:before {\n  content: '\\c361';\n}\n/* '썡' */\n.ui-grid-icon-ok:before {\n  content: '\\c362';\n}\n/* '썢' */\n.ui-grid-icon-menu:before {\n  content: '\\c363';\n}\n/* '썣' */\n.ui-grid-icon-indent-left:before {\n  content: '\\e800';\n}\n/* '' */\n.ui-grid-icon-indent-right:before {\n  content: '\\e801';\n}\n/* '' */\n.ui-grid-icon-spin5:before {\n  content: '\\ea61';\n}\n/* '' */\n"
  },
  {
    "path": "flowable-ui-web/modeler/libs/ui-grid_3.0.0/ui-grid.js",
    "content": "/*!\n * ui-grid - v3.2.9 - 2016-09-21\n * Copyright (c) 2016 ; License: MIT \n */\n\n(function () {\n  'use strict';\n  angular.module('ui.grid.i18n', []);\n  angular.module('ui.grid', ['ui.grid.i18n']);\n})();\n(function () {\n  'use strict';\n\n  /**\n   * @ngdoc object\n   * @name ui.grid.service:uiGridConstants\n   * @description Constants for use across many grid features\n   *\n   */\n\n\n  angular.module('ui.grid').constant('uiGridConstants', {\n    LOG_DEBUG_MESSAGES: true,\n    LOG_WARN_MESSAGES: true,\n    LOG_ERROR_MESSAGES: true,\n    CUSTOM_FILTERS: /CUSTOM_FILTERS/g,\n    COL_FIELD: /COL_FIELD/g,\n    MODEL_COL_FIELD: /MODEL_COL_FIELD/g,\n    TOOLTIP: /title=\\\"TOOLTIP\\\"/g,\n    DISPLAY_CELL_TEMPLATE: /DISPLAY_CELL_TEMPLATE/g,\n    TEMPLATE_REGEXP: /<.+>/,\n    FUNC_REGEXP: /(\\([^)]*\\))?$/,\n    DOT_REGEXP: /\\./g,\n    APOS_REGEXP: /'/g,\n    BRACKET_REGEXP: /^(.*)((?:\\s*\\[\\s*\\d+\\s*\\]\\s*)|(?:\\s*\\[\\s*\"(?:[^\"\\\\]|\\\\.)*\"\\s*\\]\\s*)|(?:\\s*\\[\\s*'(?:[^'\\\\]|\\\\.)*'\\s*\\]\\s*))(.*)$/,\n    COL_CLASS_PREFIX: 'ui-grid-col',\n    ENTITY_BINDING: '$$this',\n    events: {\n      GRID_SCROLL: 'uiGridScroll',\n      COLUMN_MENU_SHOWN: 'uiGridColMenuShown',\n      ITEM_DRAGGING: 'uiGridItemDragStart', // For any item being dragged\n      COLUMN_HEADER_CLICK: 'uiGridColumnHeaderClick'\n    },\n    // copied from http://www.lsauer.com/2011/08/javascript-keymap-keycodes-in-json.html\n    keymap: {\n      TAB: 9,\n      STRG: 17,\n      CAPSLOCK: 20,\n      CTRL: 17,\n      CTRLRIGHT: 18,\n      CTRLR: 18,\n      SHIFT: 16,\n      RETURN: 13,\n      ENTER: 13,\n      BACKSPACE: 8,\n      BCKSP: 8,\n      ALT: 18,\n      ALTR: 17,\n      ALTRIGHT: 17,\n      SPACE: 32,\n      WIN: 91,\n      MAC: 91,\n      FN: null,\n      PG_UP: 33,\n      PG_DOWN: 34,\n      UP: 38,\n      DOWN: 40,\n      LEFT: 37,\n      RIGHT: 39,\n      ESC: 27,\n      DEL: 46,\n      F1: 112,\n      F2: 113,\n      F3: 114,\n      F4: 115,\n      F5: 116,\n      F6: 117,\n      F7: 118,\n      F8: 119,\n      F9: 120,\n      F10: 121,\n      F11: 122,\n      F12: 123\n    },\n     /**\n     * @ngdoc object\n     * @name ASC\n     * @propertyOf ui.grid.service:uiGridConstants\n     * @description Used in {@link ui.grid.class:GridOptions.columnDef#properties_sort columnDef.sort} and\n     * {@link ui.grid.class:GridOptions.columnDef#properties_sortDirectionCycle columnDef.sortDirectionCycle}\n     * to configure the sorting direction of the column\n     */\n    ASC: 'asc',\n     /**\n     * @ngdoc object\n     * @name DESC\n     * @propertyOf ui.grid.service:uiGridConstants\n     * @description Used in {@link ui.grid.class:GridOptions.columnDef#properties_sort columnDef.sort} and\n     * {@link ui.grid.class:GridOptions.columnDef#properties_sortDirectionCycle columnDef.sortDirectionCycle}\n     * to configure the sorting direction of the column\n     */\n    DESC: 'desc',\n\n\n     /**\n     * @ngdoc object\n     * @name filter\n     * @propertyOf ui.grid.service:uiGridConstants\n     * @description Used in {@link ui.grid.class:GridOptions.columnDef#properties_filter columnDef.filter}\n     * to configure filtering on the column\n     *\n     * `SELECT` and `INPUT` are used with the `type` property of the filter, the rest are used to specify\n     * one of the built-in conditions.\n     *\n     * Available `condition` options are:\n     * - `uiGridConstants.filter.STARTS_WITH`\n     * - `uiGridConstants.filter.ENDS_WITH`\n     * - `uiGridConstants.filter.CONTAINS`\n     * - `uiGridConstants.filter.GREATER_THAN`\n     * - `uiGridConstants.filter.GREATER_THAN_OR_EQUAL`\n     * - `uiGridConstants.filter.LESS_THAN`\n     * - `uiGridConstants.filter.LESS_THAN_OR_EQUAL`\n     * - `uiGridConstants.filter.NOT_EQUAL`\n     * - `uiGridConstants.filter.STARTS_WITH`\n     *\n     *\n     * Available `type` options are:\n     * - `uiGridConstants.filter.SELECT` - use a dropdown box for the cell header filter field\n     * - `uiGridConstants.filter.INPUT` - use a text box for the cell header filter field\n     */\n    filter: {\n      STARTS_WITH: 2,\n      ENDS_WITH: 4,\n      EXACT: 8,\n      CONTAINS: 16,\n      GREATER_THAN: 32,\n      GREATER_THAN_OR_EQUAL: 64,\n      LESS_THAN: 128,\n      LESS_THAN_OR_EQUAL: 256,\n      NOT_EQUAL: 512,\n      SELECT: 'select',\n      INPUT: 'input'\n    },\n\n    /**\n     * @ngdoc object\n     * @name aggregationTypes\n     * @propertyOf ui.grid.service:uiGridConstants\n     * @description Used in {@link ui.grid.class:GridOptions.columnDef#properties_aggregationType columnDef.aggregationType}\n     * to specify the type of built-in aggregation the column should use.\n     *\n     * Available options are:\n     * - `uiGridConstants.aggregationTypes.sum` - add the values in this column to produce the aggregated value\n     * - `uiGridConstants.aggregationTypes.count` - count the number of rows to produce the aggregated value\n     * - `uiGridConstants.aggregationTypes.avg` - average the values in this column to produce the aggregated value\n     * - `uiGridConstants.aggregationTypes.min` - use the minimum value in this column as the aggregated value\n     * - `uiGridConstants.aggregationTypes.max` - use the maximum value in this column as the aggregated value\n     */\n    aggregationTypes: {\n      sum: 2,\n      count: 4,\n      avg: 8,\n      min: 16,\n      max: 32\n    },\n\n    // TODO(c0bra): Create full list of these somehow. NOTE: do any allow a space before or after them?\n    CURRENCY_SYMBOLS: ['ƒ', '$', '£', '$', '¤', '¥', '៛', '₩', '₱', '฿', '₫'],\n\n    /**\n     * @ngdoc object\n     * @name scrollDirection\n     * @propertyOf ui.grid.service:uiGridConstants\n     * @description Set on {@link ui.grid.class:Grid#properties_scrollDirection Grid.scrollDirection},\n     * to indicate the direction the grid is currently scrolling in\n     *\n     * Available options are:\n     * - `uiGridConstants.scrollDirection.UP` - set when the grid is scrolling up\n     * - `uiGridConstants.scrollDirection.DOWN` - set when the grid is scrolling down\n     * - `uiGridConstants.scrollDirection.LEFT` - set when the grid is scrolling left\n     * - `uiGridConstants.scrollDirection.RIGHT` - set when the grid is scrolling right\n     * - `uiGridConstants.scrollDirection.NONE` - set when the grid is not scrolling, this is the default\n     */\n    scrollDirection: {\n      UP: 'up',\n      DOWN: 'down',\n      LEFT: 'left',\n      RIGHT: 'right',\n      NONE: 'none'\n\n    },\n\n    /**\n     * @ngdoc object\n     * @name dataChange\n     * @propertyOf ui.grid.service:uiGridConstants\n     * @description Used with {@link ui.grid.core.api:PublicApi#methods_notifyDataChange PublicApi.notifyDataChange},\n     * {@link ui.grid.class:Grid#methods_callDataChangeCallbacks Grid.callDataChangeCallbacks},\n     * and {@link ui.grid.class:Grid#methods_registerDataChangeCallback Grid.registerDataChangeCallback}\n     * to specify the type of the event(s).\n     *\n     * Available options are:\n     * - `uiGridConstants.dataChange.ALL` - listeners fired on any of these events, fires listeners on all events.\n     * - `uiGridConstants.dataChange.EDIT` - fired when the data in a cell is edited\n     * - `uiGridConstants.dataChange.ROW` - fired when a row is added or removed\n     * - `uiGridConstants.dataChange.COLUMN` - fired when the column definitions are modified\n     * - `uiGridConstants.dataChange.OPTIONS` - fired when the grid options are modified\n     */\n    dataChange: {\n      ALL: 'all',\n      EDIT: 'edit',\n      ROW: 'row',\n      COLUMN: 'column',\n      OPTIONS: 'options'\n    },\n\n    /**\n     * @ngdoc object\n     * @name scrollbars\n     * @propertyOf ui.grid.service:uiGridConstants\n     * @description Used with {@link ui.grid.class:GridOptions#properties_enableHorizontalScrollbar GridOptions.enableHorizontalScrollbar}\n     * and {@link ui.grid.class:GridOptions#properties_enableVerticalScrollbar GridOptions.enableVerticalScrollbar}\n     * to specify the scrollbar policy for that direction.\n     *\n     * Available options are:\n     * - `uiGridConstants.scrollbars.NEVER` - never show scrollbars in this direction\n     * - `uiGridConstants.scrollbars.ALWAYS` - always show scrollbars in this direction\n     */\n\n    scrollbars: {\n      NEVER: 0,\n      ALWAYS: 1\n      //WHEN_NEEDED: 2\n    }\n  });\n\n})();\n\nangular.module('ui.grid').directive('uiGridCell', ['$compile', '$parse', 'gridUtil', 'uiGridConstants', function ($compile, $parse, gridUtil, uiGridConstants) {\n  var uiGridCell = {\n    priority: 0,\n    scope: false,\n    require: '?^uiGrid',\n    compile: function() {\n      return {\n        pre: function($scope, $elm, $attrs, uiGridCtrl) {\n          function compileTemplate() {\n            var compiledElementFn = $scope.col.compiledElementFn;\n\n            compiledElementFn($scope, function(clonedElement, scope) {\n              $elm.append(clonedElement);\n            });\n          }\n\n          // If the grid controller is present, use it to get the compiled cell template function\n          if (uiGridCtrl && $scope.col.compiledElementFn) {\n             compileTemplate();\n          }\n          // No controller, compile the element manually (for unit tests)\n          else {\n            if ( uiGridCtrl && !$scope.col.compiledElementFn ){\n              // gridUtil.logError('Render has been called before precompile.  Please log a ui-grid issue');  \n\n              $scope.col.getCompiledElementFn()\n                .then(function (compiledElementFn) {\n                  compiledElementFn($scope, function(clonedElement, scope) {\n                    $elm.append(clonedElement);\n                  });\n                });\n            }\n            else {\n              var html = $scope.col.cellTemplate\n                .replace(uiGridConstants.MODEL_COL_FIELD, 'row.entity.' + gridUtil.preEval($scope.col.field))\n                .replace(uiGridConstants.COL_FIELD, 'grid.getCellValue(row, col)');\n\n              var cellElement = $compile(html)($scope);\n              $elm.append(cellElement);\n            }\n          }\n        },\n        post: function($scope, $elm, $attrs, uiGridCtrl) {\n          var initColClass = $scope.col.getColClass(false);\n          $elm.addClass(initColClass);\n\n          var classAdded;\n          var updateClass = function( grid ){\n            var contents = $elm;\n            if ( classAdded ){\n              contents.removeClass( classAdded );\n              classAdded = null;\n            }\n\n            if (angular.isFunction($scope.col.cellClass)) {\n              classAdded = $scope.col.cellClass($scope.grid, $scope.row, $scope.col, $scope.rowRenderIndex, $scope.colRenderIndex);\n            }\n            else {\n              classAdded = $scope.col.cellClass;\n            }\n            contents.addClass(classAdded);\n          };\n\n          if ($scope.col.cellClass) {\n            updateClass();\n          }\n          \n          // Register a data change watch that would get triggered whenever someone edits a cell or modifies column defs\n          var dataChangeDereg = $scope.grid.registerDataChangeCallback( updateClass, [uiGridConstants.dataChange.COLUMN, uiGridConstants.dataChange.EDIT]);\n          \n          // watch the col and row to see if they change - which would indicate that we've scrolled or sorted or otherwise\n          // changed the row/col that this cell relates to, and we need to re-evaluate cell classes and maybe other things\n          var cellChangeFunction = function( n, o ){\n            if ( n !== o ) {\n              if ( classAdded || $scope.col.cellClass ){\n                updateClass();\n              }\n\n              // See if the column's internal class has changed\n              var newColClass = $scope.col.getColClass(false);\n              if (newColClass !== initColClass) {\n                $elm.removeClass(initColClass);\n                $elm.addClass(newColClass);\n                initColClass = newColClass;\n              }\n            }\n          };\n\n          // TODO(c0bra): Turn this into a deep array watch\n/*        shouldn't be needed any more given track by col.name\n          var colWatchDereg = $scope.$watch( 'col', cellChangeFunction );\n*/\n          var rowWatchDereg = $scope.$watch( 'row', cellChangeFunction );\n          \n          \n          var deregisterFunction = function() {\n            dataChangeDereg();\n//            colWatchDereg();\n            rowWatchDereg(); \n          };\n          \n          $scope.$on( '$destroy', deregisterFunction );\n          $elm.on( '$destroy', deregisterFunction );\n        }\n      };\n    }\n  };\n\n  return uiGridCell;\n}]);\n\n\n(function(){\n\nangular.module('ui.grid')\n.service('uiGridColumnMenuService', [ 'i18nService', 'uiGridConstants', 'gridUtil',\nfunction ( i18nService, uiGridConstants, gridUtil ) {\n/**\n *  @ngdoc service\n *  @name ui.grid.service:uiGridColumnMenuService\n *\n *  @description Services for working with column menus, factored out\n *  to make the code easier to understand\n */\n\n  var service = {\n    /**\n     * @ngdoc method\n     * @methodOf ui.grid.service:uiGridColumnMenuService\n     * @name initialize\n     * @description  Sets defaults, puts a reference to the $scope on\n     * the uiGridController\n     * @param {$scope} $scope the $scope from the uiGridColumnMenu\n     * @param {controller} uiGridCtrl the uiGridController for the grid\n     * we're on\n     *\n     */\n    initialize: function( $scope, uiGridCtrl ){\n      $scope.grid = uiGridCtrl.grid;\n\n      // Store a reference to this link/controller in the main uiGrid controller\n      // to allow showMenu later\n      uiGridCtrl.columnMenuScope = $scope;\n\n      // Save whether we're shown or not so the columns can check\n      $scope.menuShown = false;\n    },\n\n\n    /**\n     * @ngdoc method\n     * @methodOf ui.grid.service:uiGridColumnMenuService\n     * @name setColMenuItemWatch\n     * @description  Setup a watch on $scope.col.menuItems, and update\n     * menuItems based on this.  $scope.col needs to be set by the column\n     * before calling the menu.\n     * @param {$scope} $scope the $scope from the uiGridColumnMenu\n     * @param {controller} uiGridCtrl the uiGridController for the grid\n     * we're on\n     *\n     */\n    setColMenuItemWatch: function ( $scope ){\n      var deregFunction = $scope.$watch('col.menuItems', function (n) {\n        if (typeof(n) !== 'undefined' && n && angular.isArray(n)) {\n          n.forEach(function (item) {\n            if (typeof(item.context) === 'undefined' || !item.context) {\n              item.context = {};\n            }\n            item.context.col = $scope.col;\n          });\n\n          $scope.menuItems = $scope.defaultMenuItems.concat(n);\n        }\n        else {\n          $scope.menuItems = $scope.defaultMenuItems;\n        }\n      });\n\n      $scope.$on( '$destroy', deregFunction );\n    },\n\n\n    /**\n     * @ngdoc boolean\n     * @name enableSorting\n     * @propertyOf ui.grid.class:GridOptions.columnDef\n     * @description (optional) True by default. When enabled, this setting adds sort\n     * widgets to the column header, allowing sorting of the data in the individual column.\n     */\n    /**\n     * @ngdoc method\n     * @methodOf ui.grid.service:uiGridColumnMenuService\n     * @name sortable\n     * @description  determines whether this column is sortable\n     * @param {$scope} $scope the $scope from the uiGridColumnMenu\n     *\n     */\n    sortable: function( $scope ) {\n      if ( $scope.grid.options.enableSorting && typeof($scope.col) !== 'undefined' && $scope.col && $scope.col.enableSorting) {\n        return true;\n      }\n      else {\n        return false;\n      }\n    },\n\n    /**\n     * @ngdoc method\n     * @methodOf ui.grid.service:uiGridColumnMenuService\n     * @name isActiveSort\n     * @description  determines whether the requested sort direction is current active, to\n     * allow highlighting in the menu\n     * @param {$scope} $scope the $scope from the uiGridColumnMenu\n     * @param {string} direction the direction that we'd have selected for us to be active\n     *\n     */\n    isActiveSort: function( $scope, direction ){\n      return (typeof($scope.col) !== 'undefined' && typeof($scope.col.sort) !== 'undefined' &&\n              typeof($scope.col.sort.direction) !== 'undefined' && $scope.col.sort.direction === direction);\n\n    },\n\n    /**\n     * @ngdoc method\n     * @methodOf ui.grid.service:uiGridColumnMenuService\n     * @name suppressRemoveSort\n     * @description  determines whether we should suppress the removeSort option\n     * @param {$scope} $scope the $scope from the uiGridColumnMenu\n     *\n     */\n    suppressRemoveSort: function( $scope ) {\n      if ($scope.col && $scope.col.suppressRemoveSort) {\n        return true;\n      }\n      else {\n        return false;\n      }\n    },\n\n\n    /**\n     * @ngdoc boolean\n     * @name enableHiding\n     * @propertyOf ui.grid.class:GridOptions.columnDef\n     * @description (optional) True by default. When set to false, this setting prevents a user from hiding the column\n     * using the column menu or the grid menu.\n     */\n    /**\n     * @ngdoc method\n     * @methodOf ui.grid.service:uiGridColumnMenuService\n     * @name hideable\n     * @description  determines whether a column can be hidden, by checking the enableHiding columnDef option\n     * @param {$scope} $scope the $scope from the uiGridColumnMenu\n     *\n     */\n    hideable: function( $scope ) {\n      if (typeof($scope.col) !== 'undefined' && $scope.col && $scope.col.colDef && $scope.col.colDef.enableHiding === false ) {\n        return false;\n      }\n      else {\n        return true;\n      }\n    },\n\n\n    /**\n     * @ngdoc method\n     * @methodOf ui.grid.service:uiGridColumnMenuService\n     * @name getDefaultMenuItems\n     * @description  returns the default menu items for a column menu\n     * @param {$scope} $scope the $scope from the uiGridColumnMenu\n     *\n     */\n    getDefaultMenuItems: function( $scope ){\n      return [\n        {\n          title: i18nService.getSafeText('sort.ascending'),\n          icon: 'ui-grid-icon-sort-alt-up',\n          action: function($event) {\n            $event.stopPropagation();\n            $scope.sortColumn($event, uiGridConstants.ASC);\n          },\n          shown: function () {\n            return service.sortable( $scope );\n          },\n          active: function() {\n            return service.isActiveSort( $scope, uiGridConstants.ASC);\n          }\n        },\n        {\n          title: i18nService.getSafeText('sort.descending'),\n          icon: 'ui-grid-icon-sort-alt-down',\n          action: function($event) {\n            $event.stopPropagation();\n            $scope.sortColumn($event, uiGridConstants.DESC);\n          },\n          shown: function() {\n            return service.sortable( $scope );\n          },\n          active: function() {\n            return service.isActiveSort( $scope, uiGridConstants.DESC);\n          }\n        },\n        {\n          title: i18nService.getSafeText('sort.remove'),\n          icon: 'ui-grid-icon-cancel',\n          action: function ($event) {\n            $event.stopPropagation();\n            $scope.unsortColumn();\n          },\n          shown: function() {\n            return service.sortable( $scope ) &&\n                   typeof($scope.col) !== 'undefined' && (typeof($scope.col.sort) !== 'undefined' &&\n                   typeof($scope.col.sort.direction) !== 'undefined') && $scope.col.sort.direction !== null &&\n                  !service.suppressRemoveSort( $scope );\n          }\n        },\n        {\n          title: i18nService.getSafeText('column.hide'),\n          icon: 'ui-grid-icon-cancel',\n          shown: function() {\n            return service.hideable( $scope );\n          },\n          action: function ($event) {\n            $event.stopPropagation();\n            $scope.hideColumn();\n          }\n        }\n      ];\n    },\n\n\n    /**\n     * @ngdoc method\n     * @methodOf ui.grid.service:uiGridColumnMenuService\n     * @name getColumnElementPosition\n     * @description  gets the position information needed to place the column\n     * menu below the column header\n     * @param {$scope} $scope the $scope from the uiGridColumnMenu\n     * @param {GridCol} column the column we want to position below\n     * @param {element} $columnElement the column element we want to position below\n     * @returns {hash} containing left, top, offset, height, width\n     *\n     */\n    getColumnElementPosition: function( $scope, column, $columnElement ){\n      var positionData = {};\n      positionData.left = $columnElement[0].offsetLeft;\n      positionData.top = $columnElement[0].offsetTop;\n      positionData.parentLeft = $columnElement[0].offsetParent.offsetLeft;\n\n      // Get the grid scrollLeft\n      positionData.offset = 0;\n      if (column.grid.options.offsetLeft) {\n        positionData.offset = column.grid.options.offsetLeft;\n      }\n\n      positionData.height = gridUtil.elementHeight($columnElement, true);\n      positionData.width = gridUtil.elementWidth($columnElement, true);\n\n      return positionData;\n    },\n\n\n    /**\n     * @ngdoc method\n     * @methodOf ui.grid.service:uiGridColumnMenuService\n     * @name repositionMenu\n     * @description  Reposition the menu below the new column.  If the menu has no child nodes\n     * (i.e. it's not currently visible) then we guess it's width at 100, we'll be called again\n     * later to fix it\n     * @param {$scope} $scope the $scope from the uiGridColumnMenu\n     * @param {GridCol} column the column we want to position below\n     * @param {hash} positionData a hash containing left, top, offset, height, width\n     * @param {element} $elm the column menu element that we want to reposition\n     * @param {element} $columnElement the column element that we want to reposition underneath\n     *\n     */\n    repositionMenu: function( $scope, column, positionData, $elm, $columnElement ) {\n      var menu = $elm[0].querySelectorAll('.ui-grid-menu');\n\n      // It's possible that the render container of the column we're attaching to is\n      // offset from the grid (i.e. pinned containers), we need to get the difference in the offsetLeft\n      // between the render container and the grid\n      var renderContainerElm = gridUtil.closestElm($columnElement, '.ui-grid-render-container');\n      var renderContainerOffset = renderContainerElm.getBoundingClientRect().left - $scope.grid.element[0].getBoundingClientRect().left;\n\n      var containerScrollLeft = renderContainerElm.querySelectorAll('.ui-grid-viewport')[0].scrollLeft;\n\n      // default value the last width for _this_ column, otherwise last width for _any_ column, otherwise default to 170\n      var myWidth = column.lastMenuWidth ? column.lastMenuWidth : ( $scope.lastMenuWidth ? $scope.lastMenuWidth : 170);\n      var paddingRight = column.lastMenuPaddingRight ? column.lastMenuPaddingRight : ( $scope.lastMenuPaddingRight ? $scope.lastMenuPaddingRight : 10);\n\n      if ( menu.length !== 0 ){\n        var mid = menu[0].querySelectorAll('.ui-grid-menu-mid');\n        if ( mid.length !== 0 && !angular.element(mid).hasClass('ng-hide') ) {\n          myWidth = gridUtil.elementWidth(menu, true);\n          $scope.lastMenuWidth = myWidth;\n          column.lastMenuWidth = myWidth;\n\n          // TODO(c0bra): use padding-left/padding-right based on document direction (ltr/rtl), place menu on proper side\n          // Get the column menu right padding\n          paddingRight = parseInt(gridUtil.getStyles(angular.element(menu)[0])['paddingRight'], 10);\n          $scope.lastMenuPaddingRight = paddingRight;\n          column.lastMenuPaddingRight = paddingRight;\n        }\n      }\n\n      var left = positionData.left + renderContainerOffset - containerScrollLeft + positionData.parentLeft + positionData.width - myWidth + paddingRight;\n      if (left < positionData.offset){\n        left = positionData.offset;\n      }\n\n      $elm.css('left', left + 'px');\n      $elm.css('top', (positionData.top + positionData.height) + 'px');\n    }\n\n  };\n\n  return service;\n}])\n\n\n.directive('uiGridColumnMenu', ['$timeout', 'gridUtil', 'uiGridConstants', 'uiGridColumnMenuService', '$document',\nfunction ($timeout, gridUtil, uiGridConstants, uiGridColumnMenuService, $document) {\n/**\n * @ngdoc directive\n * @name ui.grid.directive:uiGridColumnMenu\n * @description  Provides the column menu framework, leverages uiGridMenu underneath\n *\n */\n\n  var uiGridColumnMenu = {\n    priority: 0,\n    scope: true,\n    require: '^uiGrid',\n    templateUrl: 'ui-grid/uiGridColumnMenu',\n    replace: true,\n    link: function ($scope, $elm, $attrs, uiGridCtrl) {\n      uiGridColumnMenuService.initialize( $scope, uiGridCtrl );\n\n      $scope.defaultMenuItems = uiGridColumnMenuService.getDefaultMenuItems( $scope );\n\n      // Set the menu items for use with the column menu. The user can later add additional items via the watch\n      $scope.menuItems = $scope.defaultMenuItems;\n      uiGridColumnMenuService.setColMenuItemWatch( $scope );\n\n\n      /**\n       * @ngdoc method\n       * @methodOf ui.grid.directive:uiGridColumnMenu\n       * @name showMenu\n       * @description Shows the column menu.  If the menu is already displayed it\n       * calls the menu to ask it to hide (it will animate), then it repositions the menu\n       * to the right place whilst hidden (it will make an assumption on menu width),\n       * then it asks the menu to show (it will animate), then it repositions the menu again\n       * once we can calculate it's size.\n       * @param {GridCol} column the column we want to position below\n       * @param {element} $columnElement the column element we want to position below\n       */\n      $scope.showMenu = function(column, $columnElement, event) {\n        // Swap to this column\n        $scope.col = column;\n\n        // Get the position information for the column element\n        var colElementPosition = uiGridColumnMenuService.getColumnElementPosition( $scope, column, $columnElement );\n\n        if ($scope.menuShown) {\n          // we want to hide, then reposition, then show, but we want to wait for animations\n          // we set a variable, and then rely on the menu-hidden event to call the reposition and show\n          $scope.colElement = $columnElement;\n          $scope.colElementPosition = colElementPosition;\n          $scope.hideThenShow = true;\n\n          $scope.$broadcast('hide-menu', { originalEvent: event });\n        } else {\n          $scope.menuShown = true;\n          uiGridColumnMenuService.repositionMenu( $scope, column, colElementPosition, $elm, $columnElement );\n\n          $scope.colElement = $columnElement;\n          $scope.colElementPosition = colElementPosition;\n          $scope.$broadcast('show-menu', { originalEvent: event });\n\n        }\n      };\n\n\n      /**\n       * @ngdoc method\n       * @methodOf ui.grid.directive:uiGridColumnMenu\n       * @name hideMenu\n       * @description Hides the column menu.\n       * @param {boolean} broadcastTrigger true if we were triggered by a broadcast\n       * from the menu itself - in which case don't broadcast again as we'll get\n       * an infinite loop\n       */\n      $scope.hideMenu = function( broadcastTrigger ) {\n        $scope.menuShown = false;\n        if ( !broadcastTrigger ){\n          $scope.$broadcast('hide-menu');\n        }\n      };\n\n\n      $scope.$on('menu-hidden', function() {\n        if ( $scope.hideThenShow ){\n          delete $scope.hideThenShow;\n\n          uiGridColumnMenuService.repositionMenu( $scope, $scope.col, $scope.colElementPosition, $elm, $scope.colElement );\n          $scope.$broadcast('show-menu');\n\n          $scope.menuShown = true;\n        } else {\n          $scope.hideMenu( true );\n\n          if ($scope.col) {\n            //Focus on the menu button\n            gridUtil.focus.bySelector($document, '.ui-grid-header-cell.' + $scope.col.getColClass()+ ' .ui-grid-column-menu-button', $scope.col.grid, false);\n          }\n        }\n      });\n\n      $scope.$on('menu-shown', function() {\n        $timeout( function() {\n          uiGridColumnMenuService.repositionMenu( $scope, $scope.col, $scope.colElementPosition, $elm, $scope.colElement );\n          //Focus on the first item\n          gridUtil.focus.bySelector($document, '.ui-grid-menu-items .ui-grid-menu-item', true);\n          delete $scope.colElementPosition;\n          delete $scope.columnElement;\n        }, 200);\n      });\n\n\n      /* Column methods */\n      $scope.sortColumn = function (event, dir) {\n        event.stopPropagation();\n\n        $scope.grid.sortColumn($scope.col, dir, true)\n          .then(function () {\n            $scope.grid.refresh();\n            $scope.hideMenu();\n          });\n      };\n\n      $scope.unsortColumn = function () {\n        $scope.col.unsort();\n\n        $scope.grid.refresh();\n        $scope.hideMenu();\n      };\n\n      //Since we are hiding this column the default hide action will fail so we need to focus somewhere else.\n      var setFocusOnHideColumn = function(){\n        $timeout(function(){\n          // Get the UID of the first\n          var focusToGridMenu = function(){\n            return gridUtil.focus.byId('grid-menu', $scope.grid);\n          };\n\n          var thisIndex;\n          $scope.grid.columns.some(function(element, index){\n            if (angular.equals(element, $scope.col)) {\n              thisIndex = index;\n              return true;\n            }\n          });\n\n          var previousVisibleCol;\n          // Try and find the next lower or nearest column to focus on\n          $scope.grid.columns.some(function(element, index){\n            if (!element.visible){\n              return false;\n            } // This columns index is below the current column index\n            else if ( index < thisIndex){\n              previousVisibleCol = element;\n            } // This elements index is above this column index and we haven't found one that is lower\n            else if ( index > thisIndex && !previousVisibleCol) {\n              // This is the next best thing\n              previousVisibleCol = element;\n              // We've found one so use it.\n              return true;\n            } // We've reached an element with an index above this column and the previousVisibleCol variable has been set\n            else if (index > thisIndex && previousVisibleCol) {\n              // We are done.\n              return true;\n            }\n          });\n          // If found then focus on it\n          if (previousVisibleCol){\n            var colClass = previousVisibleCol.getColClass();\n            gridUtil.focus.bySelector($document, '.ui-grid-header-cell.' + colClass+ ' .ui-grid-header-cell-primary-focus', true).then(angular.noop, function(reason){\n              if (reason !== 'canceled'){ // If this is canceled then don't perform the action\n                //The fallback action is to focus on the grid menu\n                return focusToGridMenu();\n              }\n            });\n          } else {\n            // Fallback action to focus on the grid menu\n            focusToGridMenu();\n          }\n        });\n      };\n\n      $scope.hideColumn = function () {\n        $scope.col.colDef.visible = false;\n        $scope.col.visible = false;\n\n        $scope.grid.queueGridRefresh();\n        $scope.hideMenu();\n        $scope.grid.api.core.notifyDataChange( uiGridConstants.dataChange.COLUMN );\n        $scope.grid.api.core.raise.columnVisibilityChanged( $scope.col );\n\n        // We are hiding so the default action of focusing on the button that opened this menu will fail.\n        setFocusOnHideColumn();\n      };\n    },\n\n\n\n    controller: ['$scope', function ($scope) {\n      var self = this;\n\n      $scope.$watch('menuItems', function (n) {\n        self.menuItems = n;\n      });\n    }]\n  };\n\n  return uiGridColumnMenu;\n\n}]);\n\n})();\n\n(function(){\n  'use strict';\n\n  angular.module('ui.grid').directive('uiGridFilter', ['$compile', '$templateCache', 'i18nService', 'gridUtil', function ($compile, $templateCache, i18nService, gridUtil) {\n\n    return {\n      compile: function() {\n        return {\n          pre: function ($scope, $elm, $attrs, controllers) {\n            $scope.col.updateFilters = function( filterable ){\n              $elm.children().remove();\n              if ( filterable ){\n                var template = $scope.col.filterHeaderTemplate;\n\n                $elm.append($compile(template)($scope));\n              }\n            };\n\n            $scope.$on( '$destroy', function() {\n              delete $scope.col.updateFilters;\n            });\n          },\n          post: function ($scope, $elm, $attrs, controllers){\n            $scope.aria = i18nService.getSafeText('headerCell.aria');\n            $scope.removeFilter = function(colFilter, index){\n              colFilter.term = null;\n              //Set the focus to the filter input after the action disables the button\n              gridUtil.focus.bySelector($elm, '.ui-grid-filter-input-' + index);\n            };\n          }\n        };\n      }\n    };\n  }]);\n})();\n\n(function () {\n  'use strict';\n\n  angular.module('ui.grid').directive('uiGridFooterCell', ['$timeout', 'gridUtil', 'uiGridConstants', '$compile',\n  function ($timeout, gridUtil, uiGridConstants, $compile) {\n    var uiGridFooterCell = {\n      priority: 0,\n      scope: {\n        col: '=',\n        row: '=',\n        renderIndex: '='\n      },\n      replace: true,\n      require: '^uiGrid',\n      compile: function compile(tElement, tAttrs, transclude) {\n        return {\n          pre: function ($scope, $elm, $attrs, uiGridCtrl) {\n            var cellFooter = $compile($scope.col.footerCellTemplate)($scope);\n            $elm.append(cellFooter);\n          },\n          post: function ($scope, $elm, $attrs, uiGridCtrl) {\n            //$elm.addClass($scope.col.getColClass(false));\n            $scope.grid = uiGridCtrl.grid;\n\n            var initColClass = $scope.col.getColClass(false);\n            $elm.addClass(initColClass);\n\n            // apply any footerCellClass\n            var classAdded;\n            var updateClass = function( grid ){\n              var contents = $elm;\n              if ( classAdded ){\n                contents.removeClass( classAdded );\n                classAdded = null;\n              }\n  \n              if (angular.isFunction($scope.col.footerCellClass)) {\n                classAdded = $scope.col.footerCellClass($scope.grid, $scope.row, $scope.col, $scope.rowRenderIndex, $scope.colRenderIndex);\n              }\n              else {\n                classAdded = $scope.col.footerCellClass;\n              }\n              contents.addClass(classAdded);\n            };\n  \n            if ($scope.col.footerCellClass) {\n              updateClass();\n            }\n\n            $scope.col.updateAggregationValue();\n\n            // Watch for column changes so we can alter the col cell class properly\n/* shouldn't be needed any more, given track by col.name\n            $scope.$watch('col', function (n, o) {\n              if (n !== o) {\n                // See if the column's internal class has changed\n                var newColClass = $scope.col.getColClass(false);\n                if (newColClass !== initColClass) {\n                  $elm.removeClass(initColClass);\n                  $elm.addClass(newColClass);\n                  initColClass = newColClass;\n                }\n              }\n            });\n*/\n\n\n            // Register a data change watch that would get triggered whenever someone edits a cell or modifies column defs\n            var dataChangeDereg = $scope.grid.registerDataChangeCallback( updateClass, [uiGridConstants.dataChange.COLUMN]);\n            // listen for visible rows change and update aggregation values\n            $scope.grid.api.core.on.rowsRendered( $scope, $scope.col.updateAggregationValue );\n            $scope.grid.api.core.on.rowsRendered( $scope, updateClass );\n            $scope.$on( '$destroy', dataChangeDereg );\n          }\n        };\n      }\n    };\n\n    return uiGridFooterCell;\n  }]);\n\n})();\n\n(function () {\n  'use strict';\n\n  angular.module('ui.grid').directive('uiGridFooter', ['$templateCache', '$compile', 'uiGridConstants', 'gridUtil', '$timeout', function ($templateCache, $compile, uiGridConstants, gridUtil, $timeout) {\n\n    return {\n      restrict: 'EA',\n      replace: true,\n      // priority: 1000,\n      require: ['^uiGrid', '^uiGridRenderContainer'],\n      scope: true,\n      compile: function ($elm, $attrs) {\n        return {\n          pre: function ($scope, $elm, $attrs, controllers) {\n            var uiGridCtrl = controllers[0];\n            var containerCtrl = controllers[1];\n\n            $scope.grid = uiGridCtrl.grid;\n            $scope.colContainer = containerCtrl.colContainer;\n\n            containerCtrl.footer = $elm;\n\n            var footerTemplate = $scope.grid.options.footerTemplate;\n            gridUtil.getTemplate(footerTemplate)\n              .then(function (contents) {\n                var template = angular.element(contents);\n\n                var newElm = $compile(template)($scope);\n                $elm.append(newElm);\n\n                if (containerCtrl) {\n                  // Inject a reference to the footer viewport (if it exists) into the grid controller for use in the horizontal scroll handler below\n                  var footerViewport = $elm[0].getElementsByClassName('ui-grid-footer-viewport')[0];\n\n                  if (footerViewport) {\n                    containerCtrl.footerViewport = footerViewport;\n                  }\n                }\n              });\n          },\n\n          post: function ($scope, $elm, $attrs, controllers) {\n            var uiGridCtrl = controllers[0];\n            var containerCtrl = controllers[1];\n\n            // gridUtil.logDebug('ui-grid-footer link');\n\n            var grid = uiGridCtrl.grid;\n\n            // Don't animate footer cells\n            gridUtil.disableAnimations($elm);\n\n            containerCtrl.footer = $elm;\n\n            var footerViewport = $elm[0].getElementsByClassName('ui-grid-footer-viewport')[0];\n            if (footerViewport) {\n              containerCtrl.footerViewport = footerViewport;\n            }\n          }\n        };\n      }\n    };\n  }]);\n\n})();\n(function () {\n  'use strict';\n\n  angular.module('ui.grid').directive('uiGridGridFooter', ['$templateCache', '$compile', 'uiGridConstants', 'gridUtil', '$timeout', function ($templateCache, $compile, uiGridConstants, gridUtil, $timeout) {\n\n    return {\n      restrict: 'EA',\n      replace: true,\n      // priority: 1000,\n      require: '^uiGrid',\n      scope: true,\n      compile: function ($elm, $attrs) {\n        return {\n          pre: function ($scope, $elm, $attrs, uiGridCtrl) {\n\n            $scope.grid = uiGridCtrl.grid;\n\n\n\n            var footerTemplate = $scope.grid.options.gridFooterTemplate;\n            gridUtil.getTemplate(footerTemplate)\n              .then(function (contents) {\n                var template = angular.element(contents);\n\n                var newElm = $compile(template)($scope);\n                $elm.append(newElm);\n              });\n          },\n\n          post: function ($scope, $elm, $attrs, controllers) {\n\n          }\n        };\n      }\n    };\n  }]);\n\n})();\n(function(){\n  'use strict';\n\n  angular.module('ui.grid').directive('uiGridGroupPanel', [\"$compile\", \"uiGridConstants\", \"gridUtil\", function($compile, uiGridConstants, gridUtil) {\n    var defaultTemplate = 'ui-grid/ui-grid-group-panel';\n\n    return {\n      restrict: 'EA',\n      replace: true,\n      require: '?^uiGrid',\n      scope: false,\n      compile: function($elm, $attrs) {\n        return {\n          pre: function ($scope, $elm, $attrs, uiGridCtrl) {\n            var groupPanelTemplate = $scope.grid.options.groupPanelTemplate  || defaultTemplate;\n\n             gridUtil.getTemplate(groupPanelTemplate)\n              .then(function (contents) {\n                var template = angular.element(contents);\n                \n                var newElm = $compile(template)($scope);\n                $elm.append(newElm);\n              });\n          },\n\n          post: function ($scope, $elm, $attrs, uiGridCtrl) {\n            $elm.bind('$destroy', function() {\n              // scrollUnbinder();\n            });\n          }\n        };\n      }\n    };\n  }]);\n\n})();\n(function(){\n  'use strict';\n\n  angular.module('ui.grid').directive('uiGridHeaderCell', ['$compile', '$timeout', '$window', '$document', 'gridUtil', 'uiGridConstants', 'ScrollEvent', 'i18nService',\n  function ($compile, $timeout, $window, $document, gridUtil, uiGridConstants, ScrollEvent, i18nService) {\n    // Do stuff after mouse has been down this many ms on the header cell\n    var mousedownTimeout = 500;\n    var changeModeTimeout = 500;    // length of time between a touch event and a mouse event being recognised again, and vice versa\n\n    var uiGridHeaderCell = {\n      priority: 0,\n      scope: {\n        col: '=',\n        row: '=',\n        renderIndex: '='\n      },\n      require: ['^uiGrid', '^uiGridRenderContainer'],\n      replace: true,\n      compile: function() {\n        return {\n          pre: function ($scope, $elm, $attrs) {\n            var cellHeader = $compile($scope.col.headerCellTemplate)($scope);\n            $elm.append(cellHeader);\n          },\n\n          post: function ($scope, $elm, $attrs, controllers) {\n            var uiGridCtrl = controllers[0];\n            var renderContainerCtrl = controllers[1];\n\n            $scope.i18n = {\n              headerCell: i18nService.getSafeText('headerCell'),\n              sort: i18nService.getSafeText('sort')\n            };\n            $scope.isSortPriorityVisible = function() {\n              //show sort priority if column is sorted and there is at least one other sorted column\n              return angular.isNumber($scope.col.sort.priority) && $scope.grid.columns.some(function(element, index){\n                  return angular.isNumber(element.sort.priority) && element !== $scope.col;\n                });\n            };\n            $scope.getSortDirectionAriaLabel = function(){\n              var col = $scope.col;\n              //Trying to recreate this sort of thing but it was getting messy having it in the template.\n              //Sort direction {{col.sort.direction == asc ? 'ascending' : ( col.sort.direction == desc ? 'descending':'none')}}. {{col.sort.priority ? {{columnPriorityText}} {{col.sort.priority}} : ''}\n              var sortDirectionText = col.sort.direction === uiGridConstants.ASC ? $scope.i18n.sort.ascending : ( col.sort.direction === uiGridConstants.DESC ? $scope.i18n.sort.descending : $scope.i18n.sort.none);\n              var label = sortDirectionText;\n\n              if ($scope.isSortPriorityVisible()) {\n                label = label + '. ' + $scope.i18n.headerCell.priority + ' ' + col.sort.priority;\n              }\n              return label;\n            };\n\n            $scope.grid = uiGridCtrl.grid;\n\n            $scope.renderContainer = uiGridCtrl.grid.renderContainers[renderContainerCtrl.containerId];\n\n            var initColClass = $scope.col.getColClass(false);\n            $elm.addClass(initColClass);\n\n            // Hide the menu by default\n            $scope.menuShown = false;\n\n            // Put asc and desc sort directions in scope\n            $scope.asc = uiGridConstants.ASC;\n            $scope.desc = uiGridConstants.DESC;\n\n            // Store a reference to menu element\n            var $colMenu = angular.element( $elm[0].querySelectorAll('.ui-grid-header-cell-menu') );\n\n            var $contentsElm = angular.element( $elm[0].querySelectorAll('.ui-grid-cell-contents') );\n\n\n            // apply any headerCellClass\n            var classAdded;\n            var previousMouseX;\n\n            // filter watchers\n            var filterDeregisters = [];\n\n\n            /*\n             * Our basic approach here for event handlers is that we listen for a down event (mousedown or touchstart).\n             * Once we have a down event, we need to work out whether we have a click, a drag, or a\n             * hold.  A click would sort the grid (if sortable).  A drag would be used by moveable, so\n             * we ignore it.  A hold would open the menu.\n             *\n             * So, on down event, we put in place handlers for move and up events, and a timer.  If the\n             * timer expires before we see a move or up, then we have a long press and hence a column menu open.\n             * If the up happens before the timer, then we have a click, and we sort if the column is sortable.\n             * If a move happens before the timer, then we are doing column move, so we do nothing, the moveable feature\n             * will handle it.\n             *\n             * To deal with touch enabled devices that also have mice, we only create our handlers when\n             * we get the down event, and we create the corresponding handlers - if we're touchstart then\n             * we get touchmove and touchend, if we're mousedown then we get mousemove and mouseup.\n             *\n             * We also suppress the click action whilst this is happening - otherwise after the mouseup there\n             * will be a click event and that can cause the column menu to close\n             *\n             */\n\n            $scope.downFn = function( event ){\n              event.stopPropagation();\n\n              if (typeof(event.originalEvent) !== 'undefined' && event.originalEvent !== undefined) {\n                event = event.originalEvent;\n              }\n\n              // Don't show the menu if it's not the left button\n              if (event.button && event.button !== 0) {\n                return;\n              }\n              previousMouseX = event.pageX;\n\n              $scope.mousedownStartTime = (new Date()).getTime();\n              $scope.mousedownTimeout = $timeout(function() { }, mousedownTimeout);\n\n              $scope.mousedownTimeout.then(function () {\n                if ( $scope.colMenu ) {\n                  uiGridCtrl.columnMenuScope.showMenu($scope.col, $elm, event);\n                }\n              });\n\n              uiGridCtrl.fireEvent(uiGridConstants.events.COLUMN_HEADER_CLICK, {event: event, columnName: $scope.col.colDef.name});\n\n              $scope.offAllEvents();\n              if ( event.type === 'touchstart'){\n                $document.on('touchend', $scope.upFn);\n                $document.on('touchmove', $scope.moveFn);\n              } else if ( event.type === 'mousedown' ){\n                $document.on('mouseup', $scope.upFn);\n                $document.on('mousemove', $scope.moveFn);\n              }\n            };\n\n            $scope.upFn = function( event ){\n              event.stopPropagation();\n              $timeout.cancel($scope.mousedownTimeout);\n              $scope.offAllEvents();\n              $scope.onDownEvents(event.type);\n\n              var mousedownEndTime = (new Date()).getTime();\n              var mousedownTime = mousedownEndTime - $scope.mousedownStartTime;\n\n              if (mousedownTime > mousedownTimeout) {\n                // long click, handled above with mousedown\n              }\n              else {\n                // short click\n                if ( $scope.sortable ){\n                  $scope.handleClick(event);\n                }\n              }\n            };\n\n            $scope.moveFn = function( event ){\n              // Chrome is known to fire some bogus move events.\n              var changeValue = event.pageX - previousMouseX;\n              if ( changeValue === 0 ){ return; }\n\n              // we're a move, so do nothing and leave for column move (if enabled) to take over\n              $timeout.cancel($scope.mousedownTimeout);\n              $scope.offAllEvents();\n              $scope.onDownEvents(event.type);\n            };\n\n            $scope.clickFn = function ( event ){\n              event.stopPropagation();\n              $contentsElm.off('click', $scope.clickFn);\n            };\n\n\n            $scope.offAllEvents = function(){\n              $contentsElm.off('touchstart', $scope.downFn);\n              $contentsElm.off('mousedown', $scope.downFn);\n\n              $document.off('touchend', $scope.upFn);\n              $document.off('mouseup', $scope.upFn);\n\n              $document.off('touchmove', $scope.moveFn);\n              $document.off('mousemove', $scope.moveFn);\n\n              $contentsElm.off('click', $scope.clickFn);\n            };\n\n            $scope.onDownEvents = function( type ){\n              // If there is a previous event, then wait a while before\n              // activating the other mode - i.e. if the last event was a touch event then\n              // don't enable mouse events for a wee while (500ms or so)\n              // Avoids problems with devices that emulate mouse events when you have touch events\n\n              switch (type){\n                case 'touchmove':\n                case 'touchend':\n                  $contentsElm.on('click', $scope.clickFn);\n                  $contentsElm.on('touchstart', $scope.downFn);\n                  $timeout(function(){\n                    $contentsElm.on('mousedown', $scope.downFn);\n                  }, changeModeTimeout);\n                  break;\n                case 'mousemove':\n                case 'mouseup':\n                  $contentsElm.on('click', $scope.clickFn);\n                  $contentsElm.on('mousedown', $scope.downFn);\n                  $timeout(function(){\n                    $contentsElm.on('touchstart', $scope.downFn);\n                  }, changeModeTimeout);\n                  break;\n                default:\n                  $contentsElm.on('click', $scope.clickFn);\n                  $contentsElm.on('touchstart', $scope.downFn);\n                  $contentsElm.on('mousedown', $scope.downFn);\n              }\n            };\n\n\n            var updateHeaderOptions = function( grid ){\n              var contents = $elm;\n              if ( classAdded ){\n                contents.removeClass( classAdded );\n                classAdded = null;\n              }\n\n              if (angular.isFunction($scope.col.headerCellClass)) {\n                classAdded = $scope.col.headerCellClass($scope.grid, $scope.row, $scope.col, $scope.rowRenderIndex, $scope.colRenderIndex);\n              }\n              else {\n                classAdded = $scope.col.headerCellClass;\n              }\n              contents.addClass(classAdded);\n\n              $timeout(function (){\n                var rightMostContainer = $scope.grid.renderContainers['right'] ? $scope.grid.renderContainers['right'] : $scope.grid.renderContainers['body'];\n                $scope.isLastCol = ( $scope.col === rightMostContainer.visibleColumnCache[ rightMostContainer.visibleColumnCache.length - 1 ] );\n              });\n\n              // Figure out whether this column is sortable or not\n              if (uiGridCtrl.grid.options.enableSorting && $scope.col.enableSorting) {\n                $scope.sortable = true;\n              }\n              else {\n                $scope.sortable = false;\n              }\n\n              // Figure out whether this column is filterable or not\n              var oldFilterable = $scope.filterable;\n              if (uiGridCtrl.grid.options.enableFiltering && $scope.col.enableFiltering) {\n                $scope.filterable = true;\n              }\n              else {\n                $scope.filterable = false;\n              }\n\n              if ( oldFilterable !== $scope.filterable){\n                if ( typeof($scope.col.updateFilters) !== 'undefined' ){\n                  $scope.col.updateFilters($scope.filterable);\n                }\n\n                // if column is filterable add a filter watcher\n                if ($scope.filterable) {\n                  $scope.col.filters.forEach( function(filter, i) {\n                    filterDeregisters.push($scope.$watch('col.filters[' + i + '].term', function(n, o) {\n                      if (n !== o) {\n                        uiGridCtrl.grid.api.core.raise.filterChanged();\n                        uiGridCtrl.grid.api.core.notifyDataChange( uiGridConstants.dataChange.COLUMN );\n                        uiGridCtrl.grid.queueGridRefresh();\n                      }\n                    }));\n                  });\n                  $scope.$on('$destroy', function() {\n                    filterDeregisters.forEach( function(filterDeregister) {\n                      filterDeregister();\n                    });\n                  });\n                } else {\n                  filterDeregisters.forEach( function(filterDeregister) {\n                    filterDeregister();\n                  });\n                }\n\n              }\n\n              // figure out whether we support column menus\n              if ($scope.col.grid.options && $scope.col.grid.options.enableColumnMenus !== false &&\n                      $scope.col.colDef && $scope.col.colDef.enableColumnMenu !== false){\n                $scope.colMenu = true;\n              } else {\n                $scope.colMenu = false;\n              }\n\n              /**\n              * @ngdoc property\n              * @name enableColumnMenu\n              * @propertyOf ui.grid.class:GridOptions.columnDef\n              * @description if column menus are enabled, controls the column menus for this specific\n              * column (i.e. if gridOptions.enableColumnMenus, then you can control column menus\n              * using this option. If gridOptions.enableColumnMenus === false then you get no column\n              * menus irrespective of the value of this option ).  Defaults to true.\n              *\n              */\n              /**\n              * @ngdoc property\n              * @name enableColumnMenus\n              * @propertyOf ui.grid.class:GridOptions.columnDef\n              * @description Override for column menus everywhere - if set to false then you get no\n              * column menus.  Defaults to true.\n              *\n              */\n\n              $scope.offAllEvents();\n\n              if ($scope.sortable || $scope.colMenu) {\n                $scope.onDownEvents();\n\n                $scope.$on('$destroy', function () {\n                  $scope.offAllEvents();\n                });\n              }\n            };\n\n/*\n            $scope.$watch('col', function (n, o) {\n              if (n !== o) {\n                // See if the column's internal class has changed\n                var newColClass = $scope.col.getColClass(false);\n                if (newColClass !== initColClass) {\n                  $elm.removeClass(initColClass);\n                  $elm.addClass(newColClass);\n                  initColClass = newColClass;\n                }\n              }\n            });\n*/\n            updateHeaderOptions();\n\n            // Register a data change watch that would get triggered whenever someone edits a cell or modifies column defs\n            var dataChangeDereg = $scope.grid.registerDataChangeCallback( updateHeaderOptions, [uiGridConstants.dataChange.COLUMN]);\n\n            $scope.$on( '$destroy', dataChangeDereg );\n\n            $scope.handleClick = function(event) {\n              // If the shift key is being held down, add this column to the sort\n              var add = false;\n              if (event.shiftKey) {\n                add = true;\n              }\n\n              // Sort this column then rebuild the grid's rows\n              uiGridCtrl.grid.sortColumn($scope.col, add)\n                .then(function () {\n                  if (uiGridCtrl.columnMenuScope) { uiGridCtrl.columnMenuScope.hideMenu(); }\n                  uiGridCtrl.grid.refresh();\n                });\n            };\n\n\n            $scope.toggleMenu = function(event) {\n              event.stopPropagation();\n\n              // If the menu is already showing...\n              if (uiGridCtrl.columnMenuScope.menuShown) {\n                // ... and we're the column the menu is on...\n                if (uiGridCtrl.columnMenuScope.col === $scope.col) {\n                  // ... hide it\n                  uiGridCtrl.columnMenuScope.hideMenu();\n                }\n                // ... and we're NOT the column the menu is on\n                else {\n                  // ... move the menu to our column\n                  uiGridCtrl.columnMenuScope.showMenu($scope.col, $elm);\n                }\n              }\n              // If the menu is NOT showing\n              else {\n                // ... show it on our column\n                uiGridCtrl.columnMenuScope.showMenu($scope.col, $elm);\n              }\n            };\n          }\n        };\n      }\n    };\n\n    return uiGridHeaderCell;\n  }]);\n\n})();\n\n(function(){\n  'use strict';\n\n  angular.module('ui.grid').directive('uiGridHeader', ['$templateCache', '$compile', 'uiGridConstants', 'gridUtil', '$timeout', 'ScrollEvent',\n    function($templateCache, $compile, uiGridConstants, gridUtil, $timeout, ScrollEvent) {\n    var defaultTemplate = 'ui-grid/ui-grid-header';\n    var emptyTemplate = 'ui-grid/ui-grid-no-header';\n\n    return {\n      restrict: 'EA',\n      // templateUrl: 'ui-grid/ui-grid-header',\n      replace: true,\n      // priority: 1000,\n      require: ['^uiGrid', '^uiGridRenderContainer'],\n      scope: true,\n      compile: function($elm, $attrs) {\n        return {\n          pre: function ($scope, $elm, $attrs, controllers) {\n            var uiGridCtrl = controllers[0];\n            var containerCtrl = controllers[1];\n\n            $scope.grid = uiGridCtrl.grid;\n            $scope.colContainer = containerCtrl.colContainer;\n\n            updateHeaderReferences();\n            \n            var headerTemplate;\n            if (!$scope.grid.options.showHeader) {\n              headerTemplate = emptyTemplate;\n            }\n            else {\n              headerTemplate = ($scope.grid.options.headerTemplate) ? $scope.grid.options.headerTemplate : defaultTemplate;            \n            }\n\n            gridUtil.getTemplate(headerTemplate)\n              .then(function (contents) {\n                var template = angular.element(contents);\n                \n                var newElm = $compile(template)($scope);\n                $elm.replaceWith(newElm);\n\n                // And update $elm to be the new element\n                $elm = newElm;\n\n                updateHeaderReferences();\n\n                if (containerCtrl) {\n                  // Inject a reference to the header viewport (if it exists) into the grid controller for use in the horizontal scroll handler below\n                  var headerViewport = $elm[0].getElementsByClassName('ui-grid-header-viewport')[0];\n\n\n                  if (headerViewport) {\n                    containerCtrl.headerViewport = headerViewport;\n                    angular.element(headerViewport).on('scroll', scrollHandler);\n                    $scope.$on('$destroy', function () {\n                      angular.element(headerViewport).off('scroll', scrollHandler);\n                    });\n                  }\n                }\n\n                $scope.grid.queueRefresh();\n              });\n\n            function updateHeaderReferences() {\n              containerCtrl.header = containerCtrl.colContainer.header = $elm;\n\n              var headerCanvases = $elm[0].getElementsByClassName('ui-grid-header-canvas');\n\n              if (headerCanvases.length > 0) {\n                containerCtrl.headerCanvas = containerCtrl.colContainer.headerCanvas = headerCanvases[0];\n              }\n              else {\n                containerCtrl.headerCanvas = null;\n              }\n            }\n\n            function scrollHandler(evt) {\n              if (uiGridCtrl.grid.isScrollingHorizontally) {\n                return;\n              }\n              var newScrollLeft = gridUtil.normalizeScrollLeft(containerCtrl.headerViewport, uiGridCtrl.grid);\n              var horizScrollPercentage = containerCtrl.colContainer.scrollHorizontal(newScrollLeft);\n\n              var scrollEvent = new ScrollEvent(uiGridCtrl.grid, null, containerCtrl.colContainer, ScrollEvent.Sources.ViewPortScroll);\n              scrollEvent.newScrollLeft = newScrollLeft;\n              if ( horizScrollPercentage > -1 ){\n                scrollEvent.x = { percentage: horizScrollPercentage };\n              }\n\n              uiGridCtrl.grid.scrollContainers(null, scrollEvent);\n            }\n          },\n\n          post: function ($scope, $elm, $attrs, controllers) {\n            var uiGridCtrl = controllers[0];\n            var containerCtrl = controllers[1];\n\n            // gridUtil.logDebug('ui-grid-header link');\n\n            var grid = uiGridCtrl.grid;\n\n            // Don't animate header cells\n            gridUtil.disableAnimations($elm);\n\n            function updateColumnWidths() {\n              // this styleBuilder always runs after the renderContainer, so we can rely on the column widths\n              // already being populated correctly\n\n              var columnCache = containerCtrl.colContainer.visibleColumnCache;\n              \n              // Build the CSS\n              // uiGridCtrl.grid.columns.forEach(function (column) {\n              var ret = '';\n              var canvasWidth = 0;\n              columnCache.forEach(function (column) {\n                ret = ret + column.getColClassDefinition();\n                canvasWidth += column.drawnWidth;\n              });\n\n              containerCtrl.colContainer.canvasWidth = canvasWidth;\n              \n              // Return the styles back to buildStyles which pops them into the `customStyles` scope variable\n              return ret;\n            }\n            \n            containerCtrl.header = $elm;\n            \n            var headerViewport = $elm[0].getElementsByClassName('ui-grid-header-viewport')[0];\n            if (headerViewport) {\n              containerCtrl.headerViewport = headerViewport;\n            }\n\n            //todo: remove this if by injecting gridCtrl into unit tests\n            if (uiGridCtrl) {\n              uiGridCtrl.grid.registerStyleComputation({\n                priority: 15,\n                func: updateColumnWidths\n              });\n            }\n          }\n        };\n      }\n    };\n  }]);\n\n})();\n\n(function(){\n\nangular.module('ui.grid')\n.service('uiGridGridMenuService', [ 'gridUtil', 'i18nService', 'uiGridConstants', function( gridUtil, i18nService, uiGridConstants ) {\n  /**\n   *  @ngdoc service\n   *  @name ui.grid.gridMenuService\n   *\n   *  @description Methods for working with the grid menu\n   */\n\n  var service = {\n    /**\n     * @ngdoc method\n     * @methodOf ui.grid.gridMenuService\n     * @name initialize\n     * @description Sets up the gridMenu. Most importantly, sets our\n     * scope onto the grid object as grid.gridMenuScope, allowing us\n     * to operate when passed only the grid.  Second most importantly,\n     * we register the 'addToGridMenu' and 'removeFromGridMenu' methods\n     * on the core api.\n     * @param {$scope} $scope the scope of this gridMenu\n     * @param {Grid} grid the grid to which this gridMenu is associated\n     */\n    initialize: function( $scope, grid ){\n      grid.gridMenuScope = $scope;\n      $scope.grid = grid;\n      $scope.registeredMenuItems = [];\n\n      // not certain this is needed, but would be bad to create a memory leak\n      $scope.$on('$destroy', function() {\n        if ( $scope.grid && $scope.grid.gridMenuScope ){\n          $scope.grid.gridMenuScope = null;\n        }\n        if ( $scope.grid ){\n          $scope.grid = null;\n        }\n        if ( $scope.registeredMenuItems ){\n          $scope.registeredMenuItems = null;\n        }\n      });\n\n      $scope.registeredMenuItems = [];\n\n      /**\n       * @ngdoc function\n       * @name addToGridMenu\n       * @methodOf ui.grid.core.api:PublicApi\n       * @description add items to the grid menu.  Used by features\n       * to add their menu items if they are enabled, can also be used by\n       * end users to add menu items.  This method has the advantage of allowing\n       * remove again, which can simplify management of which items are included\n       * in the menu when.  (Noting that in most cases the shown and active functions\n       * provide a better way to handle visibility of menu items)\n       * @param {Grid} grid the grid on which we are acting\n       * @param {array} items menu items in the format as described in the tutorial, with\n       * the added note that if you want to use remove you must also specify an `id` field,\n       * which is provided when you want to remove an item.  The id should be unique.\n       *\n       */\n      grid.api.registerMethod( 'core', 'addToGridMenu', service.addToGridMenu );\n\n      /**\n       * @ngdoc function\n       * @name removeFromGridMenu\n       * @methodOf ui.grid.core.api:PublicApi\n       * @description Remove an item from the grid menu based on a provided id. Assumes\n       * that the id is unique, removes only the last instance of that id. Does nothing if\n       * the specified id is not found\n       * @param {Grid} grid the grid on which we are acting\n       * @param {string} id the id we'd like to remove from the menu\n       *\n       */\n      grid.api.registerMethod( 'core', 'removeFromGridMenu', service.removeFromGridMenu );\n    },\n\n\n    /**\n     * @ngdoc function\n     * @name addToGridMenu\n     * @propertyOf ui.grid.gridMenuService\n     * @description add items to the grid menu.  Used by features\n     * to add their menu items if they are enabled, can also be used by\n     * end users to add menu items.  This method has the advantage of allowing\n     * remove again, which can simplify management of which items are included\n     * in the menu when.  (Noting that in most cases the shown and active functions\n     * provide a better way to handle visibility of menu items)\n     * @param {Grid} grid the grid on which we are acting\n     * @param {array} items menu items in the format as described in the tutorial, with\n     * the added note that if you want to use remove you must also specify an `id` field,\n     * which is provided when you want to remove an item.  The id should be unique.\n     *\n     */\n    addToGridMenu: function( grid, menuItems ) {\n      if ( !angular.isArray( menuItems ) ) {\n        gridUtil.logError( 'addToGridMenu: menuItems must be an array, and is not, not adding any items');\n      } else {\n        if ( grid.gridMenuScope ){\n          grid.gridMenuScope.registeredMenuItems = grid.gridMenuScope.registeredMenuItems ? grid.gridMenuScope.registeredMenuItems : [];\n          grid.gridMenuScope.registeredMenuItems = grid.gridMenuScope.registeredMenuItems.concat( menuItems );\n        } else {\n          gridUtil.logError( 'Asked to addToGridMenu, but gridMenuScope not present.  Timing issue?  Please log issue with ui-grid');\n        }\n      }\n    },\n\n\n    /**\n     * @ngdoc function\n     * @name removeFromGridMenu\n     * @methodOf ui.grid.gridMenuService\n     * @description Remove an item from the grid menu based on a provided id.  Assumes\n     * that the id is unique, removes only the last instance of that id.  Does nothing if\n     * the specified id is not found.  If there is no gridMenuScope or registeredMenuItems\n     * then do nothing silently - the desired result is those menu items not be present and they\n     * aren't.\n     * @param {Grid} grid the grid on which we are acting\n     * @param {string} id the id we'd like to remove from the menu\n     *\n     */\n    removeFromGridMenu: function( grid, id ){\n      var foundIndex = -1;\n\n      if ( grid && grid.gridMenuScope ){\n        grid.gridMenuScope.registeredMenuItems.forEach( function( value, index ) {\n          if ( value.id === id ){\n            if (foundIndex > -1) {\n              gridUtil.logError( 'removeFromGridMenu: found multiple items with the same id, removing only the last' );\n            } else {\n\n              foundIndex = index;\n            }\n          }\n        });\n      }\n\n      if ( foundIndex > -1 ){\n        grid.gridMenuScope.registeredMenuItems.splice( foundIndex, 1 );\n      }\n    },\n\n\n    /**\n     * @ngdoc array\n     * @name gridMenuCustomItems\n     * @propertyOf ui.grid.class:GridOptions\n     * @description (optional) An array of menu items that should be added to\n     * the gridMenu.  Follow the format documented in the tutorial for column\n     * menu customisation.  The context provided to the action function will\n     * include context.grid.  An alternative if working with dynamic menus is to use the\n     * provided api - core.addToGridMenu and core.removeFromGridMenu, which handles\n     * some of the management of items for you.\n     *\n     */\n    /**\n     * @ngdoc boolean\n     * @name gridMenuShowHideColumns\n     * @propertyOf ui.grid.class:GridOptions\n     * @description true by default, whether the grid menu should allow hide/show\n     * of columns\n     *\n     */\n    /**\n     * @ngdoc method\n     * @methodOf ui.grid.gridMenuService\n     * @name getMenuItems\n     * @description Decides the menu items to show in the menu.  This is a\n     * combination of:\n     *\n     * - the default menu items that are always included,\n     * - any menu items that have been provided through the addMenuItem api. These\n     *   are typically added by features within the grid\n     * - any menu items included in grid.options.gridMenuCustomItems.  These can be\n     *   changed dynamically, as they're always recalculated whenever we show the\n     *   menu\n     * @param {$scope} $scope the scope of this gridMenu, from which we can find all\n     * the information that we need\n     * @returns {array} an array of menu items that can be shown\n     */\n    getMenuItems: function( $scope ) {\n      var menuItems = [\n        // this is where we add any menu items we want to always include\n      ];\n\n      if ( $scope.grid.options.gridMenuCustomItems ){\n        if ( !angular.isArray( $scope.grid.options.gridMenuCustomItems ) ){\n          gridUtil.logError( 'gridOptions.gridMenuCustomItems must be an array, and is not');\n        } else {\n          menuItems = menuItems.concat( $scope.grid.options.gridMenuCustomItems );\n        }\n      }\n\n      var clearFilters = [{\n        title: i18nService.getSafeText('gridMenu.clearAllFilters'),\n        action: function ($event) {\n          $scope.grid.clearAllFilters(undefined, true, undefined);\n        },\n        shown: function() {\n          return $scope.grid.options.enableFiltering;\n        },\n        order: 100\n      }];\n      menuItems = menuItems.concat( clearFilters );\n\n      menuItems = menuItems.concat( $scope.registeredMenuItems );\n\n      if ( $scope.grid.options.gridMenuShowHideColumns !== false ){\n        menuItems = menuItems.concat( service.showHideColumns( $scope ) );\n      }\n\n      menuItems.sort(function(a, b){\n        return a.order - b.order;\n      });\n\n      return menuItems;\n    },\n\n\n    /**\n     * @ngdoc array\n     * @name gridMenuTitleFilter\n     * @propertyOf ui.grid.class:GridOptions\n     * @description (optional) A function that takes a title string\n     * (usually the col.displayName), and converts it into a display value.  The function\n     * must return either a string or a promise.\n     *\n     * Used for internationalization of the grid menu column names - for angular-translate\n     * you can pass $translate as the function, for i18nService you can pass getSafeText as the\n     * function\n     * @example\n     * <pre>\n     *   gridOptions = {\n     *     gridMenuTitleFilter: $translate\n     *   }\n     * </pre>\n     */\n    /**\n     * @ngdoc method\n     * @methodOf ui.grid.gridMenuService\n     * @name showHideColumns\n     * @description Adds two menu items for each of the columns in columnDefs.  One\n     * menu item for hide, one menu item for show.  Each is visible when appropriate\n     * (show when column is not visible, hide when column is visible).  Each toggles\n     * the visible property on the columnDef using toggleColumnVisibility\n     * @param {$scope} $scope of a gridMenu, which contains a reference to the grid\n     */\n    showHideColumns: function( $scope ){\n      var showHideColumns = [];\n      if ( !$scope.grid.options.columnDefs || $scope.grid.options.columnDefs.length === 0 || $scope.grid.columns.length === 0 ) {\n        return showHideColumns;\n      }\n\n      // add header for columns\n      showHideColumns.push({\n        title: i18nService.getSafeText('gridMenu.columns'),\n        order: 300\n      });\n\n      $scope.grid.options.gridMenuTitleFilter = $scope.grid.options.gridMenuTitleFilter ? $scope.grid.options.gridMenuTitleFilter : function( title ) { return title; };\n\n      $scope.grid.options.columnDefs.forEach( function( colDef, index ){\n        if ( colDef.enableHiding !== false ){\n          // add hide menu item - shows an OK icon as we only show when column is already visible\n          var menuItem = {\n            icon: 'ui-grid-icon-ok',\n            action: function($event) {\n              $event.stopPropagation();\n              service.toggleColumnVisibility( this.context.gridCol );\n            },\n            shown: function() {\n              return this.context.gridCol.colDef.visible === true || this.context.gridCol.colDef.visible === undefined;\n            },\n            context: { gridCol: $scope.grid.getColumn(colDef.name || colDef.field) },\n            leaveOpen: true,\n            order: 301 + index * 2\n          };\n          service.setMenuItemTitle( menuItem, colDef, $scope.grid );\n          showHideColumns.push( menuItem );\n\n          // add show menu item - shows no icon as we only show when column is invisible\n          menuItem = {\n            icon: 'ui-grid-icon-cancel',\n            action: function($event) {\n              $event.stopPropagation();\n              service.toggleColumnVisibility( this.context.gridCol );\n            },\n            shown: function() {\n              return !(this.context.gridCol.colDef.visible === true || this.context.gridCol.colDef.visible === undefined);\n            },\n            context: { gridCol: $scope.grid.getColumn(colDef.name || colDef.field) },\n            leaveOpen: true,\n            order: 301 + index * 2 + 1\n          };\n          service.setMenuItemTitle( menuItem, colDef, $scope.grid );\n          showHideColumns.push( menuItem );\n        }\n      });\n      return showHideColumns;\n    },\n\n\n    /**\n     * @ngdoc method\n     * @methodOf ui.grid.gridMenuService\n     * @name setMenuItemTitle\n     * @description Handles the response from gridMenuTitleFilter, adding it directly to the menu\n     * item if it returns a string, otherwise waiting for the promise to resolve or reject then\n     * putting the result into the title\n     * @param {object} menuItem the menuItem we want to put the title on\n     * @param {object} colDef the colDef from which we can get displayName, name or field\n     * @param {Grid} grid the grid, from which we can get the options.gridMenuTitleFilter\n     *\n     */\n    setMenuItemTitle: function( menuItem, colDef, grid ){\n      var title = grid.options.gridMenuTitleFilter( colDef.displayName || gridUtil.readableColumnName(colDef.name) || colDef.field );\n\n      if ( typeof(title) === 'string' ){\n        menuItem.title = title;\n      } else if ( title.then ){\n        // must be a promise\n        menuItem.title = \"\";\n        title.then( function( successValue ) {\n          menuItem.title = successValue;\n        }, function( errorValue ) {\n          menuItem.title = errorValue;\n        });\n      } else {\n        gridUtil.logError('Expected gridMenuTitleFilter to return a string or a promise, it has returned neither, bad config');\n        menuItem.title = 'badconfig';\n      }\n    },\n\n    /**\n     * @ngdoc method\n     * @methodOf ui.grid.gridMenuService\n     * @name toggleColumnVisibility\n     * @description Toggles the visibility of an individual column.  Expects to be\n     * provided a context that has on it a gridColumn, which is the column that\n     * we'll operate upon.  We change the visibility, and refresh the grid as appropriate\n     * @param {GridCol} gridCol the column that we want to toggle\n     *\n     */\n    toggleColumnVisibility: function( gridCol ) {\n      gridCol.colDef.visible = !( gridCol.colDef.visible === true || gridCol.colDef.visible === undefined );\n\n      gridCol.grid.refresh();\n      gridCol.grid.api.core.notifyDataChange( uiGridConstants.dataChange.COLUMN );\n      gridCol.grid.api.core.raise.columnVisibilityChanged( gridCol );\n    }\n  };\n\n  return service;\n}])\n\n\n\n.directive('uiGridMenuButton', ['gridUtil', 'uiGridConstants', 'uiGridGridMenuService', 'i18nService',\nfunction (gridUtil, uiGridConstants, uiGridGridMenuService, i18nService) {\n\n  return {\n    priority: 0,\n    scope: true,\n    require: ['^uiGrid'],\n    templateUrl: 'ui-grid/ui-grid-menu-button',\n    replace: true,\n\n    link: function ($scope, $elm, $attrs, controllers) {\n      var uiGridCtrl = controllers[0];\n\n      // For the aria label\n      $scope.i18n = {\n        aria: i18nService.getSafeText('gridMenu.aria')\n      };\n\n      uiGridGridMenuService.initialize($scope, uiGridCtrl.grid);\n\n      $scope.shown = false;\n\n      $scope.toggleMenu = function () {\n        if ( $scope.shown ){\n          $scope.$broadcast('hide-menu');\n          $scope.shown = false;\n        } else {\n          $scope.menuItems = uiGridGridMenuService.getMenuItems( $scope );\n          $scope.$broadcast('show-menu');\n          $scope.shown = true;\n        }\n      };\n\n      $scope.$on('menu-hidden', function() {\n        $scope.shown = false;\n        gridUtil.focus.bySelector($elm, '.ui-grid-icon-container');\n      });\n    }\n  };\n\n}]);\n\n})();\n\n(function(){\n\n/**\n * @ngdoc directive\n * @name ui.grid.directive:uiGridMenu\n * @element style\n * @restrict A\n *\n * @description\n * Allows us to interpolate expressions in `<style>` elements. Angular doesn't do this by default as it can/will/might? break in IE8.\n *\n * @example\n <doc:example module=\"app\">\n <doc:source>\n <script>\n var app = angular.module('app', ['ui.grid']);\n\n app.controller('MainCtrl', ['$scope', function ($scope) {\n\n }]);\n </script>\n\n <div ng-controller=\"MainCtrl\">\n   <div ui-grid-menu shown=\"true\"  ></div>\n </div>\n </doc:source>\n <doc:scenario>\n </doc:scenario>\n </doc:example>\n */\nangular.module('ui.grid')\n\n.directive('uiGridMenu', ['$compile', '$timeout', '$window', '$document', 'gridUtil', 'uiGridConstants', 'i18nService',\nfunction ($compile, $timeout, $window, $document, gridUtil, uiGridConstants, i18nService) {\n  var uiGridMenu = {\n    priority: 0,\n    scope: {\n      // shown: '&',\n      menuItems: '=',\n      autoHide: '=?'\n    },\n    require: '?^uiGrid',\n    templateUrl: 'ui-grid/uiGridMenu',\n    replace: false,\n    link: function ($scope, $elm, $attrs, uiGridCtrl) {\n\n      $scope.dynamicStyles = '';\n\n      var setupHeightStyle = function(gridHeight) {\n        //menu appears under header row, so substract that height from it's total\n        // additional 20px for general padding\n        var gridMenuMaxHeight = gridHeight - uiGridCtrl.grid.headerHeight - 20;\n        $scope.dynamicStyles = [\n          '.grid' + uiGridCtrl.grid.id + ' .ui-grid-menu-mid {',\n          'max-height: ' + gridMenuMaxHeight + 'px;',\n          '}'\n        ].join(' ');\n      };\n\n      if (uiGridCtrl) {\n        setupHeightStyle(uiGridCtrl.grid.gridHeight);\n        uiGridCtrl.grid.api.core.on.gridDimensionChanged($scope, function(oldGridHeight, oldGridWidth, newGridHeight, newGridWidth) {\n          setupHeightStyle(newGridHeight);\n\t\t});\n      }\n\n      $scope.i18n = {\n        close: i18nService.getSafeText('columnMenu.close')\n      };\n\n    // *** Show/Hide functions ******\n      $scope.showMenu = function(event, args) {\n        if ( !$scope.shown ){\n\n          /*\n           * In order to animate cleanly we remove the ng-if, wait a digest cycle, then\n           * animate the removal of the ng-hide.  We can't successfully (so far as I can tell)\n           * animate removal of the ng-if, as the menu items aren't there yet.  And we don't want\n           * to rely on ng-show only, as that leaves elements in the DOM that are needlessly evaluated\n           * on scroll events.\n           *\n           * Note when testing animation that animations don't run on the tutorials.  When debugging it looks\n           * like they do, but angular has a default $animate provider that is just a stub, and that's what's\n           * being called.  ALso don't be fooled by the fact that your browser has actually loaded the\n           * angular-translate.js, it's not using it.  You need to test animations in an external application.\n           */\n          $scope.shown = true;\n\n          $timeout( function() {\n            $scope.shownMid = true;\n            $scope.$emit('menu-shown');\n          });\n        } else if ( !$scope.shownMid ) {\n          // we're probably doing a hide then show, so we don't need to wait for ng-if\n          $scope.shownMid = true;\n          $scope.$emit('menu-shown');\n        }\n\n        var docEventType = 'click';\n        if (args && args.originalEvent && args.originalEvent.type && args.originalEvent.type === 'touchstart') {\n          docEventType = args.originalEvent.type;\n        }\n\n        // Turn off an existing document click handler\n        angular.element(document).off('click touchstart', applyHideMenu);\n        $elm.off('keyup', checkKeyUp);\n        $elm.off('keydown', checkKeyDown);\n\n        // Turn on the document click handler, but in a timeout so it doesn't apply to THIS click if there is one\n        $timeout(function() {\n          angular.element(document).on(docEventType, applyHideMenu);\n          $elm.on('keyup', checkKeyUp);\n          $elm.on('keydown', checkKeyDown);\n\n        });\n        //automatically set the focus to the first button element in the now open menu.\n        gridUtil.focus.bySelector($elm, 'button[type=button]', true);\n      };\n\n\n      $scope.hideMenu = function(event) {\n        if ( $scope.shown ){\n          /*\n           * In order to animate cleanly we animate the addition of ng-hide, then use a $timeout to\n           * set the ng-if (shown = false) after the animation runs.  In theory we can cascade off the\n           * callback on the addClass method, but it is very unreliable with unit tests for no discernable reason.\n           *\n           * The user may have clicked on the menu again whilst\n           * we're waiting, so we check that the mid isn't shown before applying the ng-if.\n           */\n          $scope.shownMid = false;\n          $timeout( function() {\n            if ( !$scope.shownMid ){\n              $scope.shown = false;\n              $scope.$emit('menu-hidden');\n            }\n          }, 200);\n        }\n\n        angular.element(document).off('click touchstart', applyHideMenu);\n        $elm.off('keyup', checkKeyUp);\n        $elm.off('keydown', checkKeyDown);\n      };\n\n      $scope.$on('hide-menu', function (event, args) {\n        $scope.hideMenu(event, args);\n      });\n\n      $scope.$on('show-menu', function (event, args) {\n        $scope.showMenu(event, args);\n      });\n\n\n    // *** Auto hide when click elsewhere ******\n      var applyHideMenu = function(){\n        if ($scope.shown) {\n          $scope.$apply(function () {\n            $scope.hideMenu();\n          });\n        }\n      };\n\n      // close menu on ESC and keep tab cyclical\n      var checkKeyUp = function(event) {\n        if (event.keyCode === 27) {\n          $scope.hideMenu();\n        }\n      };\n\n      var checkKeyDown = function(event) {\n        var setFocus = function(elm) {\n          elm.focus();\n          event.preventDefault();\n          return false;\n        };\n        if (event.keyCode === 9) {\n          var firstMenuItem, lastMenuItem;\n          var menuItemButtons = $elm[0].querySelectorAll('button:not(.ng-hide)');\n          if (menuItemButtons.length > 0) {\n            firstMenuItem = menuItemButtons[0];\n            lastMenuItem = menuItemButtons[menuItemButtons.length - 1];\n            if (event.target === lastMenuItem && !event.shiftKey) {\n              setFocus(firstMenuItem);\n            } else if (event.target === firstMenuItem && event.shiftKey) {\n              setFocus(lastMenuItem);\n            }\n          }\n        }\n      };\n\n      if (typeof($scope.autoHide) === 'undefined' || $scope.autoHide === undefined) {\n        $scope.autoHide = true;\n      }\n\n      if ($scope.autoHide) {\n        angular.element($window).on('resize', applyHideMenu);\n      }\n\n      $scope.$on('$destroy', function () {\n        angular.element(document).off('click touchstart', applyHideMenu);\n      });\n\n\n      $scope.$on('$destroy', function() {\n        angular.element($window).off('resize', applyHideMenu);\n      });\n\n      if (uiGridCtrl) {\n       $scope.$on('$destroy', uiGridCtrl.grid.api.core.on.scrollBegin($scope, applyHideMenu ));\n      }\n\n      $scope.$on('$destroy', $scope.$on(uiGridConstants.events.ITEM_DRAGGING, applyHideMenu ));\n    }\n  };\n\n  return uiGridMenu;\n}])\n\n.directive('uiGridMenuItem', ['gridUtil', '$compile', 'i18nService', function (gridUtil, $compile, i18nService) {\n  var uiGridMenuItem = {\n    priority: 0,\n    scope: {\n      name: '=',\n      active: '=',\n      action: '=',\n      icon: '=',\n      shown: '=',\n      context: '=',\n      templateUrl: '=',\n      leaveOpen: '=',\n      screenReaderOnly: '='\n    },\n    require: ['?^uiGrid'],\n    templateUrl: 'ui-grid/uiGridMenuItem',\n    replace: false,\n    compile: function() {\n      return {\n        pre: function ($scope, $elm) {\n          if ($scope.templateUrl) {\n            gridUtil.getTemplate($scope.templateUrl)\n                .then(function (contents) {\n                  var template = angular.element(contents);\n\n                  var newElm = $compile(template)($scope);\n                  $elm.replaceWith(newElm);\n                });\n          }\n        },\n        post: function ($scope, $elm, $attrs, controllers) {\n          var uiGridCtrl = controllers[0];\n\n          // TODO(c0bra): validate that shown and active are functions if they're defined. An exception is already thrown above this though\n          // if (typeof($scope.shown) !== 'undefined' && $scope.shown && typeof($scope.shown) !== 'function') {\n          //   throw new TypeError(\"$scope.shown is defined but not a function\");\n          // }\n          if (typeof($scope.shown) === 'undefined' || $scope.shown === null) {\n            $scope.shown = function() { return true; };\n          }\n\n          $scope.itemShown = function () {\n            var context = {};\n            if ($scope.context) {\n              context.context = $scope.context;\n            }\n\n            if (typeof(uiGridCtrl) !== 'undefined' && uiGridCtrl) {\n              context.grid = uiGridCtrl.grid;\n            }\n\n            return $scope.shown.call(context);\n          };\n\n          $scope.itemAction = function($event,title) {\n            $event.stopPropagation();\n\n            if (typeof($scope.action) === 'function') {\n              var context = {};\n\n              if ($scope.context) {\n                context.context = $scope.context;\n              }\n\n              // Add the grid to the function call context if the uiGrid controller is present\n              if (typeof(uiGridCtrl) !== 'undefined' && uiGridCtrl) {\n                context.grid = uiGridCtrl.grid;\n              }\n\n              $scope.action.call(context, $event, title);\n\n              if ( !$scope.leaveOpen ){\n                $scope.$emit('hide-menu');\n              } else {\n                /*\n                 * XXX: Fix after column refactor\n                 * Ideally the focus would remain on the item.\n                 * However, since there are two menu items that have their 'show' property toggled instead. This is a quick fix.\n                 */\n                gridUtil.focus.bySelector(angular.element(gridUtil.closestElm($elm, \".ui-grid-menu-items\")), 'button[type=button]', true);\n              }\n            }\n          };\n\n          $scope.i18n = i18nService.get();\n        }\n      };\n    }\n  };\n\n  return uiGridMenuItem;\n}]);\n\n})();\n\n(function(){\n  'use strict';\n  /**\n   * @ngdoc overview\n   * @name ui.grid.directive:uiGridOneBind\n   * @summary A group of directives that provide a one time bind to a dom element.\n   * @description A group of directives that provide a one time bind to a dom element.\n   * As one time bindings are not supported in Angular 1.2.* this directive provdes this capability.\n   * This is done to reduce the number of watchers on the dom.\n   * <br/>\n   * <h2>Short Example ({@link ui.grid.directive:uiGridOneBindSrc ui-grid-one-bind-src})</h2>\n   * <pre>\n        <div ng-init=\"imageName = 'myImageDir.jpg'\">\n          <img ui-grid-one-bind-src=\"imageName\"></img>\n        </div>\n     </pre>\n   * Will become:\n   * <pre>\n       <div ng-init=\"imageName = 'myImageDir.jpg'\">\n         <img ui-grid-one-bind-src=\"imageName\" src=\"myImageDir.jpg\"></img>\n       </div>\n     </pre>\n     </br>\n     <h2>Short Example ({@link ui.grid.directive:uiGridOneBindText ui-grid-one-bind-text})</h2>\n   * <pre>\n        <div ng-init=\"text='Add this text'\" ui-grid-one-bind-text=\"text\"></div>\n     </pre>\n   * Will become:\n   * <pre>\n   <div ng-init=\"text='Add this text'\" ui-grid-one-bind-text=\"text\">Add this text</div>\n     </pre>\n     </br>\n   * <b>Note:</b> This behavior is slightly different for the {@link ui.grid.directive:uiGridOneBindIdGrid uiGridOneBindIdGrid}\n   * and {@link ui.grid.directive:uiGridOneBindAriaLabelledbyGrid uiGridOneBindAriaLabelledbyGrid} directives.\n   *\n   */\n  //https://github.com/joshkurz/Black-Belt-AngularJS-Directives/blob/master/directives/Optimization/oneBind.js\n  var oneBinders = angular.module('ui.grid');\n  angular.forEach([\n      /**\n       * @ngdoc directive\n       * @name ui.grid.directive:uiGridOneBindSrc\n       * @memberof ui.grid.directive:uiGridOneBind\n       * @element img\n       * @restrict A\n       * @param {String} uiGridOneBindSrc The angular string you want to bind. Does not support interpolation. Don't use <code>{{scopeElt}}</code> instead use <code>scopeElt</code>.\n       * @description One time binding for the src dom tag.\n       *\n       */\n      {tag: 'Src', method: 'attr'},\n      /**\n       * @ngdoc directive\n       * @name ui.grid.directive:uiGridOneBindText\n       * @element div\n       * @restrict A\n       * @param {String} uiGridOneBindText The angular string you want to bind. Does not support interpolation. Don't use <code>{{scopeElt}}</code> instead use <code>scopeElt</code>.\n       * @description One time binding for the text dom tag.\n       */\n      {tag: 'Text', method: 'text'},\n      /**\n       * @ngdoc directive\n       * @name ui.grid.directive:uiGridOneBindHref\n       * @element div\n       * @restrict A\n       * @param {String} uiGridOneBindHref The angular string you want to bind. Does not support interpolation. Don't use <code>{{scopeElt}}</code> instead use <code>scopeElt</code>.\n       * @description One time binding for the href dom tag. For more information see {@link ui.grid.directive:uiGridOneBind}.\n       */\n      {tag: 'Href', method: 'attr'},\n      /**\n       * @ngdoc directive\n       * @name ui.grid.directive:uiGridOneBindClass\n       * @element div\n       * @restrict A\n       * @param {String} uiGridOneBindClass The angular string you want to bind. Does not support interpolation. Don't use <code>{{scopeElt}}</code> instead use <code>scopeElt</code>.\n       * @param {Object} uiGridOneBindClass The object that you want to bind. At least one of the values in the object must be something other than null or undefined for the watcher to be removed.\n       *                                    this is to prevent the watcher from being removed before the scope is initialized.\n       * @param {Array} uiGridOneBindClass An array of classes to bind to this element.\n       * @description One time binding for the class dom tag. For more information see {@link ui.grid.directive:uiGridOneBind}.\n       */\n      {tag: 'Class', method: 'addClass'},\n      /**\n       * @ngdoc directive\n       * @name ui.grid.directive:uiGridOneBindHtml\n       * @element div\n       * @restrict A\n       * @param {String} uiGridOneBindHtml The angular string you want to bind. Does not support interpolation. Don't use <code>{{scopeElt}}</code> instead use <code>scopeElt</code>.\n       * @description One time binding for the html method on a dom element. For more information see {@link ui.grid.directive:uiGridOneBind}.\n       */\n      {tag: 'Html', method: 'html'},\n      /**\n       * @ngdoc directive\n       * @name ui.grid.directive:uiGridOneBindAlt\n       * @element div\n       * @restrict A\n       * @param {String} uiGridOneBindAlt The angular string you want to bind. Does not support interpolation. Don't use <code>{{scopeElt}}</code> instead use <code>scopeElt</code>.\n       * @description One time binding for the alt dom tag. For more information see {@link ui.grid.directive:uiGridOneBind}.\n       */\n      {tag: 'Alt', method: 'attr'},\n      /**\n       * @ngdoc directive\n       * @name ui.grid.directive:uiGridOneBindStyle\n       * @element div\n       * @restrict A\n       * @param {String} uiGridOneBindStyle The angular string you want to bind. Does not support interpolation. Don't use <code>{{scopeElt}}</code> instead use <code>scopeElt</code>.\n       * @description One time binding for the style dom tag. For more information see {@link ui.grid.directive:uiGridOneBind}.\n       */\n      {tag: 'Style', method: 'css'},\n      /**\n       * @ngdoc directive\n       * @name ui.grid.directive:uiGridOneBindValue\n       * @element div\n       * @restrict A\n       * @param {String} uiGridOneBindValue The angular string you want to bind. Does not support interpolation. Don't use <code>{{scopeElt}}</code> instead use <code>scopeElt</code>.\n       * @description One time binding for the value dom tag. For more information see {@link ui.grid.directive:uiGridOneBind}.\n       */\n      {tag: 'Value', method: 'attr'},\n      /**\n       * @ngdoc directive\n       * @name ui.grid.directive:uiGridOneBindId\n       * @element div\n       * @restrict A\n       * @param {String} uiGridOneBindId The angular string you want to bind. Does not support interpolation. Don't use <code>{{scopeElt}}</code> instead use <code>scopeElt</code>.\n       * @description One time binding for the value dom tag. For more information see {@link ui.grid.directive:uiGridOneBind}.\n       */\n      {tag: 'Id', method: 'attr'},\n      /**\n       * @ngdoc directive\n       * @name ui.grid.directive:uiGridOneBindIdGrid\n       * @element div\n       * @restrict A\n       * @param {String} uiGridOneBindIdGrid The angular string you want to bind. Does not support interpolation. Don't use <code>{{scopeElt}}</code> instead use <code>scopeElt</code>.\n       * @description One time binding for the id dom tag.\n       * <h1>Important Note!</h1>\n       * If the id tag passed as a parameter does <b>not</b> contain the grid id as a substring\n       * then the directive will search the scope and the parent controller (if it is a uiGridController) for the grid.id value.\n       * If this value is found then it is appended to the begining of the id tag. If the grid is not found then the directive throws an error.\n       * This is done in order to ensure uniqueness of id tags across the grid.\n       * This is to prevent two grids in the same document having duplicate id tags.\n       */\n      {tag: 'Id', directiveName:'IdGrid', method: 'attr', appendGridId: true},\n      /**\n       * @ngdoc directive\n       * @name ui.grid.directive:uiGridOneBindTitle\n       * @element div\n       * @restrict A\n       * @param {String} uiGridOneBindTitle The angular string you want to bind. Does not support interpolation. Don't use <code>{{scopeElt}}</code> instead use <code>scopeElt</code>.\n       * @description One time binding for the title dom tag. For more information see {@link ui.grid.directive:uiGridOneBind}.\n       */\n      {tag: 'Title', method: 'attr'},\n      /**\n       * @ngdoc directive\n       * @name ui.grid.directive:uiGridOneBindAriaLabel\n       * @element div\n       * @restrict A\n       * @param {String} uiGridOneBindAriaLabel The angular string you want to bind. Does not support interpolation. Don't use <code>{{scopeElt}}</code> instead use <code>scopeElt</code>.\n       * @description One time binding for the aria-label dom tag. For more information see {@link ui.grid.directive:uiGridOneBind}.\n       *<br/>\n       * <pre>\n            <div ng-init=\"text='Add this text'\" ui-grid-one-bind-aria-label=\"text\"></div>\n         </pre>\n       * Will become:\n       * <pre>\n            <div ng-init=\"text='Add this text'\" ui-grid-one-bind-aria-label=\"text\" aria-label=\"Add this text\"></div>\n         </pre>\n       */\n      {tag: 'Label', method: 'attr', aria:true},\n      /**\n       * @ngdoc directive\n       * @name ui.grid.directive:uiGridOneBindAriaLabelledby\n       * @element div\n       * @restrict A\n       * @param {String} uiGridOneBindAriaLabelledby The angular string you want to bind. Does not support interpolation. Don't use <code>{{scopeElt}}</code> instead use <code>scopeElt</code>.\n       * @description One time binding for the aria-labelledby dom tag. For more information see {@link ui.grid.directive:uiGridOneBind}.\n       *<br/>\n       * <pre>\n            <div ng-init=\"anId = 'gridID32'\" ui-grid-one-bind-aria-labelledby=\"anId\"></div>\n         </pre>\n       * Will become:\n       * <pre>\n            <div ng-init=\"anId = 'gridID32'\" ui-grid-one-bind-aria-labelledby=\"anId\" aria-labelledby=\"gridID32\"></div>\n         </pre>\n       */\n      {tag: 'Labelledby', method: 'attr', aria:true},\n      /**\n       * @ngdoc directive\n       * @name ui.grid.directive:uiGridOneBindAriaLabelledbyGrid\n       * @element div\n       * @restrict A\n       * @param {String} uiGridOneBindAriaLabelledbyGrid The angular string you want to bind. Does not support interpolation. Don't use <code>{{scopeElt}}</code> instead use <code>scopeElt</code>.\n       * @description One time binding for the aria-labelledby dom tag. For more information see {@link ui.grid.directive:uiGridOneBind}.\n       * Works somewhat like {@link ui.grid.directive:uiGridOneBindIdGrid} however this one supports a list of ids (seperated by a space) and will dynamically add the\n       * grid id to each one.\n       *<br/>\n       * <pre>\n            <div ng-init=\"anId = 'gridID32'\" ui-grid-one-bind-aria-labelledby-grid=\"anId\"></div>\n         </pre>\n       * Will become ([grid.id] will be replaced by the actual grid id):\n       * <pre>\n            <div ng-init=\"anId = 'gridID32'\" ui-grid-one-bind-aria-labelledby-grid=\"anId\" aria-labelledby-Grid=\"[grid.id]-gridID32\"></div>\n         </pre>\n       */\n      {tag: 'Labelledby', directiveName:'LabelledbyGrid', appendGridId:true, method: 'attr', aria:true},\n      /**\n       * @ngdoc directive\n       * @name ui.grid.directive:uiGridOneBindAriaDescribedby\n       * @element ANY\n       * @restrict A\n       * @param {String} uiGridOneBindAriaDescribedby The angular string you want to bind. Does not support interpolation. Don't use <code>{{scopeElt}}</code> instead use <code>scopeElt</code>.\n       * @description One time binding for the aria-describedby dom tag. For more information see {@link ui.grid.directive:uiGridOneBind}.\n       *<br/>\n       * <pre>\n            <div ng-init=\"anId = 'gridID32'\" ui-grid-one-bind-aria-describedby=\"anId\"></div>\n         </pre>\n       * Will become:\n       * <pre>\n            <div ng-init=\"anId = 'gridID32'\" ui-grid-one-bind-aria-describedby=\"anId\" aria-describedby=\"gridID32\"></div>\n         </pre>\n       */\n      {tag: 'Describedby', method: 'attr', aria:true},\n      /**\n       * @ngdoc directive\n       * @name ui.grid.directive:uiGridOneBindAriaDescribedbyGrid\n       * @element ANY\n       * @restrict A\n       * @param {String} uiGridOneBindAriaDescribedbyGrid The angular string you want to bind. Does not support interpolation. Don't use <code>{{scopeElt}}</code> instead use <code>scopeElt</code>.\n       * @description One time binding for the aria-labelledby dom tag. For more information see {@link ui.grid.directive:uiGridOneBind}.\n       * Works somewhat like {@link ui.grid.directive:uiGridOneBindIdGrid} however this one supports a list of ids (seperated by a space) and will dynamically add the\n       * grid id to each one.\n       *<br/>\n       * <pre>\n            <div ng-init=\"anId = 'gridID32'\" ui-grid-one-bind-aria-describedby-grid=\"anId\"></div>\n         </pre>\n       * Will become ([grid.id] will be replaced by the actual grid id):\n       * <pre>\n            <div ng-init=\"anId = 'gridID32'\" ui-grid-one-bind-aria-describedby-grid=\"anId\" aria-describedby=\"[grid.id]-gridID32\"></div>\n         </pre>\n       */\n      {tag: 'Describedby', directiveName:'DescribedbyGrid', appendGridId:true, method: 'attr', aria:true}],\n    function(v){\n\n      var baseDirectiveName = 'uiGridOneBind';\n      //If it is an aria tag then append the aria label seperately\n      //This is done because the aria tags are formatted aria-* and the directive name can't have a '-' character in it.\n      //If the diretiveName has to be overridden then it does so here. This is because the tag being modified and the directive sometimes don't match up.\n      var directiveName = (v.aria ? baseDirectiveName + 'Aria' : baseDirectiveName) + (v.directiveName ? v.directiveName : v.tag);\n      oneBinders.directive(directiveName, ['gridUtil', function(gridUtil){\n        return {\n          restrict: 'A',\n          require: ['?uiGrid','?^uiGrid'],\n          link: function(scope, iElement, iAttrs, controllers){\n            /* Appends the grid id to the beginnig of the value. */\n            var appendGridId = function(val){\n              var grid; //Get an instance of the grid if its available\n              //If its available in the scope then we don't need to try to find it elsewhere\n              if (scope.grid) {\n                grid = scope.grid;\n              }\n              //Another possible location to try to find the grid\n              else if (scope.col && scope.col.grid){\n                grid = scope.col.grid;\n              }\n              //Last ditch effort: Search through the provided controllers.\n              else if (!controllers.some( //Go through the controllers till one has the element we need\n                function(controller){\n                  if (controller && controller.grid) {\n                    grid = controller.grid;\n                    return true; //We've found the grid\n                  }\n              })){\n                //We tried our best to find it for you\n                gridUtil.logError(\"[\"+directiveName+\"] A valid grid could not be found to bind id. Are you using this directive \" +\n                                 \"within the correct scope? Trying to generate id: [gridID]-\" + val);\n                throw new Error(\"No valid grid could be found\");\n              }\n\n              if (grid){\n                var idRegex = new RegExp(grid.id.toString());\n                //If the grid id hasn't been appended already in the template declaration\n                if (!idRegex.test(val)){\n                  val = grid.id.toString() + '-' + val;\n                }\n              }\n              return val;\n            };\n\n            // The watch returns a function to remove itself.\n            var rmWatcher = scope.$watch(iAttrs[directiveName], function(newV){\n              if (newV){\n                //If we are trying to add an id element then we also apply the grid id if it isn't already there\n                if (v.appendGridId) {\n                  var newIdString = null;\n                  //Append the id to all of the new ids.\n                  angular.forEach( newV.split(' '), function(s){\n                    newIdString = (newIdString ? (newIdString + ' ') : '') +  appendGridId(s);\n                  });\n                  newV = newIdString;\n                }\n\n                // Append this newValue to the dom element.\n                switch (v.method) {\n                  case 'attr': //The attr method takes two paraams the tag and the value\n                    if (v.aria) {\n                      //If it is an aria element then append the aria prefix\n                      iElement[v.method]('aria-' + v.tag.toLowerCase(),newV);\n                    } else {\n                      iElement[v.method](v.tag.toLowerCase(),newV);\n                    }\n                    break;\n                  case 'addClass':\n                    //Pulled from https://github.com/Pasvaz/bindonce/blob/master/bindonce.js\n                    if (angular.isObject(newV) && !angular.isArray(newV)) {\n                      var results = [];\n                      var nonNullFound = false; //We don't want to remove the binding unless the key is actually defined\n                      angular.forEach(newV, function (value, index) {\n                        if (value !== null && typeof(value) !== \"undefined\"){\n                          nonNullFound = true; //A non null value for a key was found so the object must have been initialized\n                          if (value) {results.push(index);}\n                        }\n                      });\n                      //A non null value for a key wasn't found so assume that the scope values haven't been fully initialized\n                      if (!nonNullFound){\n                        return; // If not initialized then the watcher should not be removed yet.\n                      }\n                      newV = results;\n                    }\n\n                    if (newV) {\n                      iElement.addClass(angular.isArray(newV) ? newV.join(' ') : newV);\n                    } else {\n                      return;\n                    }\n                    break;\n                  default:\n                    iElement[v.method](newV);\n                    break;\n                }\n\n                //Removes the watcher on itself after the bind\n                rmWatcher();\n              }\n            // True ensures that equality is determined using angular.equals instead of ===\n            }, true); //End rm watchers\n          } //End compile function\n        }; //End directive return\n      } // End directive function\n    ]); //End directive\n  }); // End angular foreach\n})();\n\n(function () {\n  'use strict';\n\n  var module = angular.module('ui.grid');\n\n  module.directive('uiGridRenderContainer', ['$timeout', '$document', 'uiGridConstants', 'gridUtil', 'ScrollEvent',\n    function($timeout, $document, uiGridConstants, gridUtil, ScrollEvent) {\n    return {\n      replace: true,\n      transclude: true,\n      templateUrl: 'ui-grid/uiGridRenderContainer',\n      require: ['^uiGrid', 'uiGridRenderContainer'],\n      scope: {\n        containerId: '=',\n        rowContainerName: '=',\n        colContainerName: '=',\n        bindScrollHorizontal: '=',\n        bindScrollVertical: '=',\n        enableVerticalScrollbar: '=',\n        enableHorizontalScrollbar: '='\n      },\n      controller: 'uiGridRenderContainer as RenderContainer',\n      compile: function () {\n        return {\n          pre: function prelink($scope, $elm, $attrs, controllers) {\n\n            var uiGridCtrl = controllers[0];\n            var containerCtrl = controllers[1];\n            var grid = $scope.grid = uiGridCtrl.grid;\n\n            // Verify that the render container for this element exists\n            if (!$scope.rowContainerName) {\n              throw \"No row render container name specified\";\n            }\n            if (!$scope.colContainerName) {\n              throw \"No column render container name specified\";\n            }\n\n            if (!grid.renderContainers[$scope.rowContainerName]) {\n              throw \"Row render container '\" + $scope.rowContainerName + \"' is not registered.\";\n            }\n            if (!grid.renderContainers[$scope.colContainerName]) {\n              throw \"Column render container '\" + $scope.colContainerName + \"' is not registered.\";\n            }\n\n            var rowContainer = $scope.rowContainer = grid.renderContainers[$scope.rowContainerName];\n            var colContainer = $scope.colContainer = grid.renderContainers[$scope.colContainerName];\n\n            containerCtrl.containerId = $scope.containerId;\n            containerCtrl.rowContainer = rowContainer;\n            containerCtrl.colContainer = colContainer;\n          },\n          post: function postlink($scope, $elm, $attrs, controllers) {\n\n            var uiGridCtrl = controllers[0];\n            var containerCtrl = controllers[1];\n\n            var grid = uiGridCtrl.grid;\n            var rowContainer = containerCtrl.rowContainer;\n            var colContainer = containerCtrl.colContainer;\n            var scrollTop = null;\n            var scrollLeft = null;\n\n\n            var renderContainer = grid.renderContainers[$scope.containerId];\n\n            // Put the container name on this element as a class\n            $elm.addClass('ui-grid-render-container-' + $scope.containerId);\n\n            // Scroll the render container viewport when the mousewheel is used\n            gridUtil.on.mousewheel($elm, function (event) {\n              var scrollEvent = new ScrollEvent(grid, rowContainer, colContainer, ScrollEvent.Sources.RenderContainerMouseWheel);\n              if (event.deltaY !== 0) {\n                var scrollYAmount = event.deltaY * -1 * event.deltaFactor;\n\n                scrollTop = containerCtrl.viewport[0].scrollTop;\n\n                // Get the scroll percentage\n                scrollEvent.verticalScrollLength = rowContainer.getVerticalScrollLength();\n                var scrollYPercentage = (scrollTop + scrollYAmount) / scrollEvent.verticalScrollLength;\n\n                // If we should be scrolled 100%, make sure the scrollTop matches the maximum scroll length\n                //   Viewports that have \"overflow: hidden\" don't let the mousewheel scroll all the way to the bottom without this check\n                if (scrollYPercentage >= 1 && scrollTop < scrollEvent.verticalScrollLength) {\n                  containerCtrl.viewport[0].scrollTop = scrollEvent.verticalScrollLength;\n                }\n\n                // Keep scrollPercentage within the range 0-1.\n                if (scrollYPercentage < 0) { scrollYPercentage = 0; }\n                else if (scrollYPercentage > 1) { scrollYPercentage = 1; }\n\n                scrollEvent.y = { percentage: scrollYPercentage, pixels: scrollYAmount };\n              }\n              if (event.deltaX !== 0) {\n                var scrollXAmount = event.deltaX * event.deltaFactor;\n\n                // Get the scroll percentage\n                scrollLeft = gridUtil.normalizeScrollLeft(containerCtrl.viewport, grid);\n                scrollEvent.horizontalScrollLength = (colContainer.getCanvasWidth() - colContainer.getViewportWidth());\n                var scrollXPercentage = (scrollLeft + scrollXAmount) / scrollEvent.horizontalScrollLength;\n\n                // Keep scrollPercentage within the range 0-1.\n                if (scrollXPercentage < 0) { scrollXPercentage = 0; }\n                else if (scrollXPercentage > 1) { scrollXPercentage = 1; }\n\n                scrollEvent.x = { percentage: scrollXPercentage, pixels: scrollXAmount };\n              }\n\n              // Let the parent container scroll if the grid is already at the top/bottom\n              if ((event.deltaY !== 0 && (scrollEvent.atTop(scrollTop) || scrollEvent.atBottom(scrollTop))) ||\n                  (event.deltaX !== 0 && (scrollEvent.atLeft(scrollLeft) || scrollEvent.atRight(scrollLeft)))) {\n                //parent controller scrolls\n              }\n              else {\n                event.preventDefault();\n                event.stopPropagation();\n                scrollEvent.fireThrottledScrollingEvent('', scrollEvent);\n              }\n\n            });\n\n            $elm.bind('$destroy', function() {\n              $elm.unbind('keydown');\n\n              ['touchstart', 'touchmove', 'touchend','keydown', 'wheel', 'mousewheel', 'DomMouseScroll', 'MozMousePixelScroll'].forEach(function (eventName) {\n                $elm.unbind(eventName);\n              });\n            });\n\n            // TODO(c0bra): Handle resizing the inner canvas based on the number of elements\n            function update() {\n              var ret = '';\n\n              var canvasWidth = colContainer.canvasWidth;\n              var viewportWidth = colContainer.getViewportWidth();\n\n              var canvasHeight = rowContainer.getCanvasHeight();\n\n              //add additional height for scrollbar on left and right container\n              //if ($scope.containerId !== 'body') {\n              //  canvasHeight -= grid.scrollbarHeight;\n              //}\n\n              var viewportHeight = rowContainer.getViewportHeight();\n              //shorten the height to make room for a scrollbar placeholder\n              if (colContainer.needsHScrollbarPlaceholder()) {\n                viewportHeight -= grid.scrollbarHeight;\n              }\n\n              var headerViewportWidth,\n                  footerViewportWidth;\n              headerViewportWidth = footerViewportWidth = colContainer.getHeaderViewportWidth();\n\n              // Set canvas dimensions\n              ret += '\\n .grid' + uiGridCtrl.grid.id + ' .ui-grid-render-container-' + $scope.containerId + ' .ui-grid-canvas { width: ' + canvasWidth + 'px; height: ' + canvasHeight + 'px; }';\n\n              ret += '\\n .grid' + uiGridCtrl.grid.id + ' .ui-grid-render-container-' + $scope.containerId + ' .ui-grid-header-canvas { width: ' + (canvasWidth + grid.scrollbarWidth) + 'px; }';\n\n              if (renderContainer.explicitHeaderCanvasHeight) {\n                ret += '\\n .grid' + uiGridCtrl.grid.id + ' .ui-grid-render-container-' + $scope.containerId + ' .ui-grid-header-canvas { height: ' + renderContainer.explicitHeaderCanvasHeight + 'px; }';\n              }\n              else {\n                ret += '\\n .grid' + uiGridCtrl.grid.id + ' .ui-grid-render-container-' + $scope.containerId + ' .ui-grid-header-canvas { height: inherit; }';\n              }\n\n              ret += '\\n .grid' + uiGridCtrl.grid.id + ' .ui-grid-render-container-' + $scope.containerId + ' .ui-grid-viewport { width: ' + viewportWidth + 'px; height: ' + viewportHeight + 'px; }';\n              ret += '\\n .grid' + uiGridCtrl.grid.id + ' .ui-grid-render-container-' + $scope.containerId + ' .ui-grid-header-viewport { width: ' + headerViewportWidth + 'px; }';\n\n              ret += '\\n .grid' + uiGridCtrl.grid.id + ' .ui-grid-render-container-' + $scope.containerId + ' .ui-grid-footer-canvas { width: ' + (canvasWidth + grid.scrollbarWidth) + 'px; }';\n              ret += '\\n .grid' + uiGridCtrl.grid.id + ' .ui-grid-render-container-' + $scope.containerId + ' .ui-grid-footer-viewport { width: ' + footerViewportWidth + 'px; }';\n\n              return ret;\n            }\n\n            uiGridCtrl.grid.registerStyleComputation({\n              priority: 6,\n              func: update\n            });\n          }\n        };\n      }\n    };\n\n  }]);\n\n  module.controller('uiGridRenderContainer', ['$scope', 'gridUtil', function ($scope, gridUtil) {\n\n  }]);\n\n})();\n\n(function(){\n  'use strict';\n\n  angular.module('ui.grid').directive('uiGridRow', ['gridUtil', function(gridUtil) {\n    return {\n      replace: true,\n      // priority: 2001,\n      // templateUrl: 'ui-grid/ui-grid-row',\n      require: ['^uiGrid', '^uiGridRenderContainer'],\n      scope: {\n         row: '=uiGridRow',\n         //rowRenderIndex is added to scope to give the true visual index of the row to any directives that need it\n         rowRenderIndex: '='\n      },\n      compile: function() {\n        return {\n          pre: function($scope, $elm, $attrs, controllers) {\n            var uiGridCtrl = controllers[0];\n            var containerCtrl = controllers[1];\n\n            var grid = uiGridCtrl.grid;\n\n            $scope.grid = uiGridCtrl.grid;\n            $scope.colContainer = containerCtrl.colContainer;\n\n            // Function for attaching the template to this scope\n            var clonedElement, cloneScope;\n            function compileTemplate() {\n              $scope.row.getRowTemplateFn.then(function (compiledElementFn) {\n                // var compiledElementFn = $scope.row.compiledElementFn;\n\n                // Create a new scope for the contents of this row, so we can destroy it later if need be\n                var newScope = $scope.$new();\n\n                compiledElementFn(newScope, function (newElm, scope) {\n                  // If we already have a cloned element, we need to remove it and destroy its scope\n                  if (clonedElement) {\n                    clonedElement.remove();\n                    cloneScope.$destroy();\n                  }\n\n                  // Empty the row and append the new element\n                  $elm.empty().append(newElm);\n\n                  // Save the new cloned element and scope\n                  clonedElement = newElm;\n                  cloneScope = newScope;\n                });\n              });\n            }\n\n            // Initially attach the compiled template to this scope\n            compileTemplate();\n\n            // If the row's compiled element function changes, we need to replace this element's contents with the new compiled template\n            $scope.$watch('row.getRowTemplateFn', function (newFunc, oldFunc) {\n              if (newFunc !== oldFunc) {\n                compileTemplate();\n              }\n            });\n          },\n          post: function($scope, $elm, $attrs, controllers) {\n\n          }\n        };\n      }\n    };\n  }]);\n\n})();\n(function(){\n// 'use strict';\n\n  /**\n   * @ngdoc directive\n   * @name ui.grid.directive:uiGridStyle\n   * @element style\n   * @restrict A\n   *\n   * @description\n   * Allows us to interpolate expressions in `<style>` elements. Angular doesn't do this by default as it can/will/might? break in IE8.\n   *\n   * @example\n   <doc:example module=\"app\">\n   <doc:source>\n   <script>\n   var app = angular.module('app', ['ui.grid']);\n\n   app.controller('MainCtrl', ['$scope', function ($scope) {\n          $scope.myStyle = '.blah { border: 1px solid }';\n        }]);\n   </script>\n\n   <div ng-controller=\"MainCtrl\">\n   <style ui-grid-style>{{ myStyle }}</style>\n   <span class=\"blah\">I am in a box.</span>\n   </div>\n   </doc:source>\n   <doc:scenario>\n      it('should apply the right class to the element', function () {\n        element(by.css('.blah')).getCssValue('border-top-width')\n          .then(function(c) {\n            expect(c).toContain('1px');\n          });\n      });\n   </doc:scenario>\n   </doc:example>\n   */\n\n\n  angular.module('ui.grid').directive('uiGridStyle', ['gridUtil', '$interpolate', function(gridUtil, $interpolate) {\n    return {\n      // restrict: 'A',\n      // priority: 1000,\n      // require: '?^uiGrid',\n      link: function($scope, $elm, $attrs, uiGridCtrl) {\n        // gridUtil.logDebug('ui-grid-style link');\n        // if (uiGridCtrl === undefined) {\n        //    gridUtil.logWarn('[ui-grid-style link] uiGridCtrl is undefined!');\n        // }\n\n        var interpolateFn = $interpolate($elm.text(), true);\n\n        if (interpolateFn) {\n          $scope.$watch(interpolateFn, function(value) {\n            $elm.text(value);\n          });\n        }\n\n          // uiGridCtrl.recalcRowStyles = function() {\n          //   var offset = (scope.options.offsetTop || 0) - (scope.options.excessRows * scope.options.rowHeight);\n          //   var rowHeight = scope.options.rowHeight;\n\n          //   var ret = '';\n          //   var rowStyleCount = uiGridCtrl.minRowsToRender() + (scope.options.excessRows * 2);\n          //   for (var i = 1; i <= rowStyleCount; i++) {\n          //     ret = ret + ' .grid' + scope.gridId + ' .ui-grid-row:nth-child(' + i + ') { top: ' + offset + 'px; }';\n          //     offset = offset + rowHeight;\n          //   }\n\n          //   scope.rowStyles = ret;\n          // };\n\n          // uiGridCtrl.styleComputions.push(uiGridCtrl.recalcRowStyles);\n\n      }\n    };\n  }]);\n\n})();\n\n(function(){\n  'use strict';\n\n  angular.module('ui.grid').directive('uiGridViewport', ['gridUtil','ScrollEvent','uiGridConstants', '$log',\n    function(gridUtil, ScrollEvent, uiGridConstants, $log) {\n      return {\n        replace: true,\n        scope: {},\n        controllerAs: 'Viewport',\n        templateUrl: 'ui-grid/uiGridViewport',\n        require: ['^uiGrid', '^uiGridRenderContainer'],\n        link: function($scope, $elm, $attrs, controllers) {\n          // gridUtil.logDebug('viewport post-link');\n\n          var uiGridCtrl = controllers[0];\n          var containerCtrl = controllers[1];\n\n          $scope.containerCtrl = containerCtrl;\n\n          var rowContainer = containerCtrl.rowContainer;\n          var colContainer = containerCtrl.colContainer;\n\n          var grid = uiGridCtrl.grid;\n\n          $scope.grid = uiGridCtrl.grid;\n\n          // Put the containers in scope so we can get rows and columns from them\n          $scope.rowContainer = containerCtrl.rowContainer;\n          $scope.colContainer = containerCtrl.colContainer;\n\n          // Register this viewport with its container\n          containerCtrl.viewport = $elm;\n\n\n          $elm.on('scroll', scrollHandler);\n\n          var ignoreScroll = false;\n\n          function scrollHandler(evt) {\n            //Leaving in this commented code in case it can someday be used\n            //It does improve performance, but because the horizontal scroll is normalized,\n            //  using this code will lead to the column header getting slightly out of line with columns\n            //\n            //if (ignoreScroll && (grid.isScrollingHorizontally || grid.isScrollingHorizontally)) {\n            //  //don't ask for scrollTop if we just set it\n            //  ignoreScroll = false;\n            //  return;\n            //}\n            //ignoreScroll = true;\n\n            var newScrollTop = $elm[0].scrollTop;\n            var newScrollLeft = gridUtil.normalizeScrollLeft($elm, grid);\n\n            var vertScrollPercentage = rowContainer.scrollVertical(newScrollTop);\n            var horizScrollPercentage = colContainer.scrollHorizontal(newScrollLeft);\n\n            var scrollEvent = new ScrollEvent(grid, rowContainer, colContainer, ScrollEvent.Sources.ViewPortScroll);\n            scrollEvent.newScrollLeft = newScrollLeft;\n            scrollEvent.newScrollTop = newScrollTop;\n            if ( horizScrollPercentage > -1 ){\n              scrollEvent.x = { percentage: horizScrollPercentage };\n            }\n\n            if ( vertScrollPercentage > -1 ){\n              scrollEvent.y = { percentage: vertScrollPercentage };\n            }\n\n            grid.scrollContainers($scope.$parent.containerId, scrollEvent);\n          }\n\n          if ($scope.$parent.bindScrollVertical) {\n            grid.addVerticalScrollSync($scope.$parent.containerId, syncVerticalScroll);\n          }\n\n          if ($scope.$parent.bindScrollHorizontal) {\n            grid.addHorizontalScrollSync($scope.$parent.containerId, syncHorizontalScroll);\n            grid.addHorizontalScrollSync($scope.$parent.containerId + 'header', syncHorizontalHeader);\n            grid.addHorizontalScrollSync($scope.$parent.containerId + 'footer', syncHorizontalFooter);\n          }\n\n          function syncVerticalScroll(scrollEvent){\n            containerCtrl.prevScrollArgs = scrollEvent;\n            var newScrollTop = scrollEvent.getNewScrollTop(rowContainer,containerCtrl.viewport);\n            $elm[0].scrollTop = newScrollTop;\n\n          }\n\n          function syncHorizontalScroll(scrollEvent){\n            containerCtrl.prevScrollArgs = scrollEvent;\n            var newScrollLeft = scrollEvent.getNewScrollLeft(colContainer, containerCtrl.viewport);\n            $elm[0].scrollLeft =  gridUtil.denormalizeScrollLeft(containerCtrl.viewport,newScrollLeft, grid);\n          }\n\n          function syncHorizontalHeader(scrollEvent){\n            var newScrollLeft = scrollEvent.getNewScrollLeft(colContainer, containerCtrl.viewport);\n            if (containerCtrl.headerViewport) {\n              containerCtrl.headerViewport.scrollLeft = gridUtil.denormalizeScrollLeft(containerCtrl.viewport,newScrollLeft, grid);\n            }\n          }\n\n          function syncHorizontalFooter(scrollEvent){\n            var newScrollLeft = scrollEvent.getNewScrollLeft(colContainer, containerCtrl.viewport);\n            if (containerCtrl.footerViewport) {\n              containerCtrl.footerViewport.scrollLeft =  gridUtil.denormalizeScrollLeft(containerCtrl.viewport,newScrollLeft, grid);\n            }\n          }\n\n\n        },\n        controller: ['$scope', function ($scope) {\n          this.rowStyle = function (index) {\n            var rowContainer = $scope.rowContainer;\n            var colContainer = $scope.colContainer;\n\n            var styles = {};\n\n            if (index === 0 && rowContainer.currentTopRow !== 0) {\n              // The row offset-top is just the height of the rows above the current top-most row, which are no longer rendered\n              var hiddenRowWidth = (rowContainer.currentTopRow) * rowContainer.grid.options.rowHeight;\n\n              // return { 'margin-top': hiddenRowWidth + 'px' };\n              styles['margin-top'] = hiddenRowWidth + 'px';\n            }\n\n            if (colContainer.currentFirstColumn !== 0) {\n              if (colContainer.grid.isRTL()) {\n                styles['margin-right'] = colContainer.columnOffset + 'px';\n              }\n              else {\n                styles['margin-left'] = colContainer.columnOffset + 'px';\n              }\n            }\n\n            return styles;\n          };\n        }]\n      };\n    }\n  ]);\n\n})();\n\n(function() {\n\nangular.module('ui.grid')\n.directive('uiGridVisible', function uiGridVisibleAction() {\n  return function ($scope, $elm, $attr) {\n    $scope.$watch($attr.uiGridVisible, function (visible) {\n        // $elm.css('visibility', visible ? 'visible' : 'hidden');\n        $elm[visible ? 'removeClass' : 'addClass']('ui-grid-invisible');\n    });\n  };\n});\n\n})();\n(function () {\n  'use strict';\n\n  angular.module('ui.grid').controller('uiGridController', ['$scope', '$element', '$attrs', 'gridUtil', '$q', 'uiGridConstants',\n                    '$templateCache', 'gridClassFactory', '$timeout', '$parse', '$compile',\n    function ($scope, $elm, $attrs, gridUtil, $q, uiGridConstants,\n              $templateCache, gridClassFactory, $timeout, $parse, $compile) {\n      // gridUtil.logDebug('ui-grid controller');\n\n      var self = this;\n\n      self.grid = gridClassFactory.createGrid($scope.uiGrid);\n\n      //assign $scope.$parent if appScope not already assigned\n      self.grid.appScope = self.grid.appScope || $scope.$parent;\n\n      $elm.addClass('grid' + self.grid.id);\n      self.grid.rtl = gridUtil.getStyles($elm[0])['direction'] === 'rtl';\n\n\n      // angular.extend(self.grid.options, );\n\n      //all properties of grid are available on scope\n      $scope.grid = self.grid;\n\n      if ($attrs.uiGridColumns) {\n        $attrs.$observe('uiGridColumns', function(value) {\n          self.grid.options.columnDefs = value;\n          self.grid.buildColumns()\n            .then(function(){\n              self.grid.preCompileCellTemplates();\n\n              self.grid.refreshCanvas(true);\n            });\n        });\n      }\n\n\n      // if fastWatch is set we watch only the length and the reference, not every individual object\n      var deregFunctions = [];\n      if (self.grid.options.fastWatch) {\n        self.uiGrid = $scope.uiGrid;\n        if (angular.isString($scope.uiGrid.data)) {\n          deregFunctions.push( $scope.$parent.$watch($scope.uiGrid.data, dataWatchFunction) );\n          deregFunctions.push( $scope.$parent.$watch(function() {\n            if ( self.grid.appScope[$scope.uiGrid.data] ){\n              return self.grid.appScope[$scope.uiGrid.data].length;\n            } else {\n              return undefined;\n            }\n          }, dataWatchFunction) );\n        } else {\n          deregFunctions.push( $scope.$parent.$watch(function() { return $scope.uiGrid.data; }, dataWatchFunction) );\n          deregFunctions.push( $scope.$parent.$watch(function() { return $scope.uiGrid.data.length; }, function(){ dataWatchFunction($scope.uiGrid.data); }) );\n        }\n        deregFunctions.push( $scope.$parent.$watch(function() { return $scope.uiGrid.columnDefs; }, columnDefsWatchFunction) );\n        deregFunctions.push( $scope.$parent.$watch(function() { return $scope.uiGrid.columnDefs.length; }, function(){ columnDefsWatchFunction($scope.uiGrid.columnDefs); }) );\n      } else {\n        if (angular.isString($scope.uiGrid.data)) {\n          deregFunctions.push( $scope.$parent.$watchCollection($scope.uiGrid.data, dataWatchFunction) );\n        } else {\n          deregFunctions.push( $scope.$parent.$watchCollection(function() { return $scope.uiGrid.data; }, dataWatchFunction) );\n        }\n        deregFunctions.push( $scope.$parent.$watchCollection(function() { return $scope.uiGrid.columnDefs; }, columnDefsWatchFunction) );\n      }\n\n\n      function columnDefsWatchFunction(n, o) {\n        if (n && n !== o) {\n          self.grid.options.columnDefs = $scope.uiGrid.columnDefs;\n          self.grid.buildColumns({ orderByColumnDefs: true })\n            .then(function(){\n\n              self.grid.preCompileCellTemplates();\n\n              self.grid.callDataChangeCallbacks(uiGridConstants.dataChange.COLUMN);\n            });\n        }\n      }\n\n      var mostRecentData;\n\n      function dataWatchFunction(newData) {\n        // gridUtil.logDebug('dataWatch fired');\n        var promises = [];\n\n        if ( self.grid.options.fastWatch ){\n          if (angular.isString($scope.uiGrid.data)) {\n            newData = self.grid.appScope[$scope.uiGrid.data];\n          } else {\n            newData = $scope.uiGrid.data;\n          }\n        }\n\n        mostRecentData = newData;\n\n        if (newData) {\n          // columns length is greater than the number of row header columns, which don't count because they're created automatically\n          var hasColumns = self.grid.columns.length > (self.grid.rowHeaderColumns ? self.grid.rowHeaderColumns.length : 0);\n\n          if (\n            // If we have no columns\n            !hasColumns &&\n            // ... and we don't have a ui-grid-columns attribute, which would define columns for us\n            !$attrs.uiGridColumns &&\n            // ... and we have no pre-defined columns\n            self.grid.options.columnDefs.length === 0 &&\n            // ... but we DO have data\n            newData.length > 0\n          ) {\n            // ... then build the column definitions from the data that we have\n            self.grid.buildColumnDefsFromData(newData);\n          }\n\n          // If we haven't built columns before and either have some columns defined or some data defined\n          if (!hasColumns && (self.grid.options.columnDefs.length > 0 || newData.length > 0)) {\n            // Build the column set, then pre-compile the column cell templates\n            promises.push(self.grid.buildColumns()\n              .then(function() {\n                self.grid.preCompileCellTemplates();\n              }));\n          }\n\n          $q.all(promises).then(function() {\n            // use most recent data, rather than the potentially outdated data passed into watcher handler\n            self.grid.modifyRows(mostRecentData)\n              .then(function () {\n                // if (self.viewport) {\n                  self.grid.redrawInPlace(true);\n                // }\n\n                $scope.$evalAsync(function() {\n                  self.grid.refreshCanvas(true);\n                  self.grid.callDataChangeCallbacks(uiGridConstants.dataChange.ROW);\n                });\n              });\n          });\n        }\n      }\n\n      var styleWatchDereg = $scope.$watch(function () { return self.grid.styleComputations; }, function() {\n        self.grid.refreshCanvas(true);\n      });\n\n      $scope.$on('$destroy', function() {\n        deregFunctions.forEach( function( deregFn ){ deregFn(); });\n        styleWatchDereg();\n      });\n\n      self.fireEvent = function(eventName, args) {\n        // Add the grid to the event arguments if it's not there\n        if (typeof(args) === 'undefined' || args === undefined) {\n          args = {};\n        }\n\n        if (typeof(args.grid) === 'undefined' || args.grid === undefined) {\n          args.grid = self.grid;\n        }\n\n        $scope.$broadcast(eventName, args);\n      };\n\n      self.innerCompile = function innerCompile(elm) {\n        $compile(elm)($scope);\n      };\n\n    }]);\n\n/**\n *  @ngdoc directive\n *  @name ui.grid.directive:uiGrid\n *  @element div\n *  @restrict EA\n *  @param {Object} uiGrid Options for the grid to use\n *\n *  @description Create a very basic grid.\n *\n *  @example\n    <example module=\"app\">\n      <file name=\"app.js\">\n        var app = angular.module('app', ['ui.grid']);\n\n        app.controller('MainCtrl', ['$scope', function ($scope) {\n          $scope.data = [\n            { name: 'Bob', title: 'CEO' },\n            { name: 'Frank', title: 'Lowly Developer' }\n          ];\n        }]);\n      </file>\n      <file name=\"index.html\">\n        <div ng-controller=\"MainCtrl\">\n          <div ui-grid=\"{ data: data }\"></div>\n        </div>\n      </file>\n    </example>\n */\nangular.module('ui.grid').directive('uiGrid', uiGridDirective);\n\nuiGridDirective.$inject = ['$compile', '$templateCache', '$timeout', '$window', 'gridUtil', 'uiGridConstants'];\nfunction uiGridDirective($compile, $templateCache, $timeout, $window, gridUtil, uiGridConstants) {\n  return {\n    templateUrl: 'ui-grid/ui-grid',\n    scope: {\n      uiGrid: '='\n    },\n    replace: true,\n    transclude: true,\n    controller: 'uiGridController',\n    compile: function () {\n      return {\n        post: function ($scope, $elm, $attrs, uiGridCtrl) {\n          var grid = uiGridCtrl.grid;\n          // Initialize scrollbars (TODO: move to controller??)\n          uiGridCtrl.scrollbars = [];\n          grid.element = $elm;\n\n\n          // See if the grid has a rendered width, if not, wait a bit and try again\n          var sizeCheckInterval = 100; // ms\n          var maxSizeChecks = 20; // 2 seconds total\n          var sizeChecks = 0;\n\n          // Setup (event listeners) the grid\n          setup();\n\n          // And initialize it\n          init();\n\n          // Mark rendering complete so API events can happen\n          grid.renderingComplete();\n\n          // If the grid doesn't have size currently, wait for a bit to see if it gets size\n          checkSize();\n\n          /*-- Methods --*/\n\n          function checkSize() {\n            // If the grid has no width and we haven't checked more than <maxSizeChecks> times, check again in <sizeCheckInterval> milliseconds\n            if ($elm[0].offsetWidth <= 0 && sizeChecks < maxSizeChecks) {\n              setTimeout(checkSize, sizeCheckInterval);\n              sizeChecks++;\n            }\n            else {\n              $timeout(init);\n            }\n          }\n\n          // Setup event listeners and watchers\n          function setup() {\n            // Bind to window resize events\n            angular.element($window).on('resize', gridResize);\n\n            // Unbind from window resize events when the grid is destroyed\n            $elm.on('$destroy', function () {\n              angular.element($window).off('resize', gridResize);\n            });\n\n            // If we add a left container after render, we need to watch and react\n            $scope.$watch(function () { return grid.hasLeftContainer();}, function (newValue, oldValue) {\n              if (newValue === oldValue) {\n                return;\n              }\n              grid.refreshCanvas(true);\n            });\n\n            // If we add a right container after render, we need to watch and react\n            $scope.$watch(function () { return grid.hasRightContainer();}, function (newValue, oldValue) {\n              if (newValue === oldValue) {\n                return;\n              }\n              grid.refreshCanvas(true);\n            });\n          }\n\n          // Initialize the directive\n          function init() {\n            grid.gridWidth = $scope.gridWidth = gridUtil.elementWidth($elm);\n\n            // Default canvasWidth to the grid width, in case we don't get any column definitions to calculate it from\n            grid.canvasWidth = uiGridCtrl.grid.gridWidth;\n\n            grid.gridHeight = $scope.gridHeight = gridUtil.elementHeight($elm);\n\n            // If the grid isn't tall enough to fit a single row, it's kind of useless. Resize it to fit a minimum number of rows\n            if (grid.gridHeight <= grid.options.rowHeight && grid.options.enableMinHeightCheck) {\n              autoAdjustHeight();\n            }\n\n            // Run initial canvas refresh\n            grid.refreshCanvas(true);\n          }\n\n          // Set the grid's height ourselves in the case that its height would be unusably small\n          function autoAdjustHeight() {\n            // Figure out the new height\n            var contentHeight = grid.options.minRowsToShow * grid.options.rowHeight;\n            var headerHeight = grid.options.showHeader ? grid.options.headerRowHeight : 0;\n            var footerHeight = grid.calcFooterHeight();\n\n            var scrollbarHeight = 0;\n            if (grid.options.enableHorizontalScrollbar === uiGridConstants.scrollbars.ALWAYS) {\n              scrollbarHeight = gridUtil.getScrollbarWidth();\n            }\n\n            var maxNumberOfFilters = 0;\n            // Calculates the maximum number of filters in the columns\n            angular.forEach(grid.options.columnDefs, function(col) {\n              if (col.hasOwnProperty('filter')) {\n                if (maxNumberOfFilters < 1) {\n                    maxNumberOfFilters = 1;\n                }\n              }\n              else if (col.hasOwnProperty('filters')) {\n                if (maxNumberOfFilters < col.filters.length) {\n                    maxNumberOfFilters = col.filters.length;\n                }\n              }\n            });\n\n            if (grid.options.enableFiltering  && !maxNumberOfFilters) {\n              var allColumnsHaveFilteringTurnedOff = grid.options.columnDefs.length && grid.options.columnDefs.every(function(col) {\n                return col.enableFiltering === false;\n              });\n\n              if (!allColumnsHaveFilteringTurnedOff) {\n                maxNumberOfFilters = 1;\n              }\n            }\n\n            var filterHeight = maxNumberOfFilters * headerHeight;\n\n            var newHeight = headerHeight + contentHeight + footerHeight + scrollbarHeight + filterHeight;\n\n            $elm.css('height', newHeight + 'px');\n\n            grid.gridHeight = $scope.gridHeight = gridUtil.elementHeight($elm);\n          }\n\n          // Resize the grid on window resize events\n          function gridResize($event) {\n            grid.gridWidth = $scope.gridWidth = gridUtil.elementWidth($elm);\n            grid.gridHeight = $scope.gridHeight = gridUtil.elementHeight($elm);\n\n            grid.refreshCanvas(true);\n          }\n        }\n      };\n    }\n  };\n}\n\n})();\n\n(function(){\n  'use strict';\n\n  // TODO: rename this file to ui-grid-pinned-container.js\n\n  angular.module('ui.grid').directive('uiGridPinnedContainer', ['gridUtil', function (gridUtil) {\n    return {\n      restrict: 'EA',\n      replace: true,\n      template: '<div class=\"ui-grid-pinned-container\"><div ui-grid-render-container container-id=\"side\" row-container-name=\"\\'body\\'\" col-container-name=\"side\" bind-scroll-vertical=\"true\" class=\"{{ side }} ui-grid-render-container-{{ side }}\"></div></div>',\n      scope: {\n        side: '=uiGridPinnedContainer'\n      },\n      require: '^uiGrid',\n      compile: function compile() {\n        return {\n          post: function ($scope, $elm, $attrs, uiGridCtrl) {\n            // gridUtil.logDebug('ui-grid-pinned-container ' + $scope.side + ' link');\n\n            var grid = uiGridCtrl.grid;\n\n            var myWidth = 0;\n\n            $elm.addClass('ui-grid-pinned-container-' + $scope.side);\n\n            // Monkey-patch the viewport width function\n            if ($scope.side === 'left' || $scope.side === 'right') {\n              grid.renderContainers[$scope.side].getViewportWidth = monkeyPatchedGetViewportWidth;\n            }\n\n            function monkeyPatchedGetViewportWidth() {\n              /*jshint validthis: true */\n              var self = this;\n\n              var viewportWidth = 0;\n              self.visibleColumnCache.forEach(function (column) {\n                viewportWidth += column.drawnWidth;\n              });\n\n              var adjustment = self.getViewportAdjustment();\n\n              viewportWidth = viewportWidth + adjustment.width;\n\n              return viewportWidth;\n            }\n\n            function updateContainerWidth() {\n              if ($scope.side === 'left' || $scope.side === 'right') {\n                var cols = grid.renderContainers[$scope.side].visibleColumnCache;\n                var width = 0;\n                for (var i = 0; i < cols.length; i++) {\n                  var col = cols[i];\n                  width += col.drawnWidth || col.width || 0;\n                }\n\n                return width;\n              }\n            }\n\n            function updateContainerDimensions() {\n              var ret = '';\n\n              // Column containers\n              if ($scope.side === 'left' || $scope.side === 'right') {\n                myWidth = updateContainerWidth();\n\n                // gridUtil.logDebug('myWidth', myWidth);\n\n                // TODO(c0bra): Subtract sum of col widths from grid viewport width and update it\n                $elm.attr('style', null);\n\n             //   var myHeight = grid.renderContainers.body.getViewportHeight(); // + grid.horizontalScrollbarHeight;\n\n                ret += '.grid' + grid.id + ' .ui-grid-pinned-container-' + $scope.side + ', .grid' + grid.id + ' .ui-grid-pinned-container-' + $scope.side + ' .ui-grid-render-container-' + $scope.side + ' .ui-grid-viewport { width: ' + myWidth + 'px; } ';\n              }\n\n              return ret;\n            }\n\n            grid.renderContainers.body.registerViewportAdjuster(function (adjustment) {\n              myWidth = updateContainerWidth();\n\n              // Subtract our own width\n              adjustment.width -= myWidth;\n              adjustment.side = $scope.side;\n\n              return adjustment;\n            });\n\n            // Register style computation to adjust for columns in `side`'s render container\n            grid.registerStyleComputation({\n              priority: 15,\n              func: updateContainerDimensions\n            });\n          }\n        };\n      }\n    };\n  }]);\n})();\n\n(function(){\n\nangular.module('ui.grid')\n.factory('Grid', ['$q', '$compile', '$parse', 'gridUtil', 'uiGridConstants', 'GridOptions', 'GridColumn', 'GridRow', 'GridApi', 'rowSorter', 'rowSearcher', 'GridRenderContainer', '$timeout','ScrollEvent',\n    function($q, $compile, $parse, gridUtil, uiGridConstants, GridOptions, GridColumn, GridRow, GridApi, rowSorter, rowSearcher, GridRenderContainer, $timeout, ScrollEvent) {\n\n  /**\n   * @ngdoc object\n   * @name ui.grid.core.api:PublicApi\n   * @description Public Api for the core grid features\n   *\n   */\n\n  /**\n   * @ngdoc function\n   * @name ui.grid.class:Grid\n   * @description Grid is the main viewModel.  Any properties or methods needed to maintain state are defined in\n   * this prototype.  One instance of Grid is created per Grid directive instance.\n   * @param {object} options Object map of options to pass into the grid. An 'id' property is expected.\n   */\n  var Grid = function Grid(options) {\n    var self = this;\n    // Get the id out of the options, then remove it\n    if (options !== undefined && typeof(options.id) !== 'undefined' && options.id) {\n      if (!/^[_a-zA-Z0-9-]+$/.test(options.id)) {\n        throw new Error(\"Grid id '\" + options.id + '\" is invalid. It must follow CSS selector syntax rules.');\n      }\n    }\n    else {\n      throw new Error('No ID provided. An ID must be given when creating a grid.');\n    }\n\n    self.id = options.id;\n    delete options.id;\n\n    // Get default options\n    self.options = GridOptions.initialize( options );\n\n    /**\n     * @ngdoc object\n     * @name appScope\n     * @propertyOf ui.grid.class:Grid\n     * @description reference to the application scope (the parent scope of the ui-grid element).  Assigned in ui-grid controller\n     * <br/>\n     * use gridOptions.appScopeProvider to override the default assignment of $scope.$parent with any reference\n     */\n    self.appScope = self.options.appScopeProvider;\n\n    self.headerHeight = self.options.headerRowHeight;\n\n\n    /**\n     * @ngdoc object\n     * @name footerHeight\n     * @propertyOf ui.grid.class:Grid\n     * @description returns the total footer height gridFooter + columnFooter\n     */\n    self.footerHeight = self.calcFooterHeight();\n\n\n    /**\n     * @ngdoc object\n     * @name columnFooterHeight\n     * @propertyOf ui.grid.class:Grid\n     * @description returns the total column footer height\n     */\n    self.columnFooterHeight = self.calcColumnFooterHeight();\n\n    self.rtl = false;\n    self.gridHeight = 0;\n    self.gridWidth = 0;\n    self.columnBuilders = [];\n    self.rowBuilders = [];\n    self.rowsProcessors = [];\n    self.columnsProcessors = [];\n    self.styleComputations = [];\n    self.viewportAdjusters = [];\n    self.rowHeaderColumns = [];\n    self.dataChangeCallbacks = {};\n    self.verticalScrollSyncCallBackFns = {};\n    self.horizontalScrollSyncCallBackFns = {};\n\n    // self.visibleRowCache = [];\n\n    // Set of 'render' containers for self grid, which can render sets of rows\n    self.renderContainers = {};\n\n    // Create a\n    self.renderContainers.body = new GridRenderContainer('body', self);\n\n    self.cellValueGetterCache = {};\n\n    // Cached function to use with custom row templates\n    self.getRowTemplateFn = null;\n\n\n    //representation of the rows on the grid.\n    //these are wrapped references to the actual data rows (options.data)\n    self.rows = [];\n\n    //represents the columns on the grid\n    self.columns = [];\n\n    /**\n     * @ngdoc boolean\n     * @name isScrollingVertically\n     * @propertyOf ui.grid.class:Grid\n     * @description set to true when Grid is scrolling vertically. Set to false via debounced method\n     */\n    self.isScrollingVertically = false;\n\n    /**\n     * @ngdoc boolean\n     * @name isScrollingHorizontally\n     * @propertyOf ui.grid.class:Grid\n     * @description set to true when Grid is scrolling horizontally. Set to false via debounced method\n     */\n    self.isScrollingHorizontally = false;\n\n    /**\n     * @ngdoc property\n     * @name scrollDirection\n     * @propertyOf ui.grid.class:Grid\n     * @description set one of the {@link ui.grid.service:uiGridConstants#properties_scrollDirection uiGridConstants.scrollDirection}\n     *  values (UP, DOWN, LEFT, RIGHT, NONE), which tells us which direction we are scrolling.\n     * Set to NONE via debounced method\n     */\n    self.scrollDirection = uiGridConstants.scrollDirection.NONE;\n\n    //if true, grid will not respond to any scroll events\n    self.disableScrolling = false;\n\n\n    function vertical (scrollEvent) {\n      self.isScrollingVertically = false;\n      self.api.core.raise.scrollEnd(scrollEvent);\n      self.scrollDirection = uiGridConstants.scrollDirection.NONE;\n    }\n\n    var debouncedVertical = gridUtil.debounce(vertical, self.options.scrollDebounce);\n    var debouncedVerticalMinDelay = gridUtil.debounce(vertical, 0);\n\n    function horizontal (scrollEvent) {\n      self.isScrollingHorizontally = false;\n      self.api.core.raise.scrollEnd(scrollEvent);\n      self.scrollDirection = uiGridConstants.scrollDirection.NONE;\n    }\n\n    var debouncedHorizontal = gridUtil.debounce(horizontal, self.options.scrollDebounce);\n    var debouncedHorizontalMinDelay = gridUtil.debounce(horizontal, 0);\n\n\n    /**\n     * @ngdoc function\n     * @name flagScrollingVertically\n     * @methodOf ui.grid.class:Grid\n     * @description sets isScrollingVertically to true and sets it to false in a debounced function\n     */\n    self.flagScrollingVertically = function(scrollEvent) {\n      if (!self.isScrollingVertically && !self.isScrollingHorizontally) {\n        self.api.core.raise.scrollBegin(scrollEvent);\n      }\n      self.isScrollingVertically = true;\n      if (self.options.scrollDebounce === 0 || !scrollEvent.withDelay) {\n        debouncedVerticalMinDelay(scrollEvent);\n      }\n      else {\n        debouncedVertical(scrollEvent);\n      }\n    };\n\n    /**\n     * @ngdoc function\n     * @name flagScrollingHorizontally\n     * @methodOf ui.grid.class:Grid\n     * @description sets isScrollingHorizontally to true and sets it to false in a debounced function\n     */\n    self.flagScrollingHorizontally = function(scrollEvent) {\n      if (!self.isScrollingVertically && !self.isScrollingHorizontally) {\n        self.api.core.raise.scrollBegin(scrollEvent);\n      }\n      self.isScrollingHorizontally = true;\n      if (self.options.scrollDebounce === 0 || !scrollEvent.withDelay) {\n        debouncedHorizontalMinDelay(scrollEvent);\n      }\n      else {\n        debouncedHorizontal(scrollEvent);\n      }\n    };\n\n    self.scrollbarHeight = 0;\n    self.scrollbarWidth = 0;\n    if (self.options.enableHorizontalScrollbar === uiGridConstants.scrollbars.ALWAYS) {\n      self.scrollbarHeight = gridUtil.getScrollbarWidth();\n    }\n\n    if (self.options.enableVerticalScrollbar === uiGridConstants.scrollbars.ALWAYS) {\n      self.scrollbarWidth = gridUtil.getScrollbarWidth();\n    }\n\n\n\n    self.api = new GridApi(self);\n\n    /**\n     * @ngdoc function\n     * @name refresh\n     * @methodOf ui.grid.core.api:PublicApi\n     * @description Refresh the rendered grid on screen.\n     * The refresh method re-runs both the columnProcessors and the\n     * rowProcessors, as well as calling refreshCanvas to update all\n     * the grid sizing.  In general you should prefer to use queueGridRefresh\n     * instead, which is basically a debounced version of refresh.\n     *\n     * If you only want to resize the grid, not regenerate all the rows\n     * and columns, you should consider directly calling refreshCanvas instead.\n     *\n     * @param {boolean} [rowsAltered] Optional flag for refreshing when the number of rows has changed\n     */\n    self.api.registerMethod( 'core', 'refresh', this.refresh );\n\n    /**\n     * @ngdoc function\n     * @name queueGridRefresh\n     * @methodOf ui.grid.core.api:PublicApi\n     * @description Request a refresh of the rendered grid on screen, if multiple\n     * calls to queueGridRefresh are made within a digest cycle only one will execute.\n     * The refresh method re-runs both the columnProcessors and the\n     * rowProcessors, as well as calling refreshCanvas to update all\n     * the grid sizing.  In general you should prefer to use queueGridRefresh\n     * instead, which is basically a debounced version of refresh.\n     *\n     */\n    self.api.registerMethod( 'core', 'queueGridRefresh', this.queueGridRefresh );\n\n    /**\n     * @ngdoc function\n     * @name refreshRows\n     * @methodOf ui.grid.core.api:PublicApi\n     * @description Runs only the rowProcessors, columns remain as they were.\n     * It then calls redrawInPlace and refreshCanvas, which adjust the grid sizing.\n     * @returns {promise} promise that is resolved when render completes?\n     *\n     */\n    self.api.registerMethod( 'core', 'refreshRows', this.refreshRows );\n\n    /**\n     * @ngdoc function\n     * @name queueRefresh\n     * @methodOf ui.grid.core.api:PublicApi\n     * @description Requests execution of refreshCanvas, if multiple requests are made\n     * during a digest cycle only one will run.  RefreshCanvas updates the grid sizing.\n     * @returns {promise} promise that is resolved when render completes?\n     *\n     */\n    self.api.registerMethod( 'core', 'queueRefresh', this.queueRefresh );\n\n    /**\n     * @ngdoc function\n     * @name handleWindowResize\n     * @methodOf ui.grid.core.api:PublicApi\n     * @description Trigger a grid resize, normally this would be picked\n     * up by a watch on window size, but in some circumstances it is necessary\n     * to call this manually\n     * @returns {promise} promise that is resolved when render completes?\n     *\n     */\n    self.api.registerMethod( 'core', 'handleWindowResize', this.handleWindowResize );\n\n\n    /**\n     * @ngdoc function\n     * @name addRowHeaderColumn\n     * @methodOf ui.grid.core.api:PublicApi\n     * @description adds a row header column to the grid\n     * @param {object} column def\n     * @param {number} order Determines order of header column on grid.  Lower order means header\n     * is positioned to the left of higher order headers\n     *\n     */\n    self.api.registerMethod( 'core', 'addRowHeaderColumn', this.addRowHeaderColumn );\n\n    /**\n     * @ngdoc function\n     * @name scrollToIfNecessary\n     * @methodOf ui.grid.core.api:PublicApi\n     * @description Scrolls the grid to make a certain row and column combo visible,\n     *   in the case that it is not completely visible on the screen already.\n     * @param {GridRow} gridRow row to make visible\n     * @param {GridCol} gridCol column to make visible\n     * @returns {promise} a promise that is resolved when scrolling is complete\n     *\n     */\n    self.api.registerMethod( 'core', 'scrollToIfNecessary', function(gridRow, gridCol) { return self.scrollToIfNecessary(gridRow, gridCol);} );\n\n    /**\n     * @ngdoc function\n     * @name scrollTo\n     * @methodOf ui.grid.core.api:PublicApi\n     * @description Scroll the grid such that the specified\n     * row and column is in view\n     * @param {object} rowEntity gridOptions.data[] array instance to make visible\n     * @param {object} colDef to make visible\n     * @returns {promise} a promise that is resolved after any scrolling is finished\n     */\n    self.api.registerMethod( 'core', 'scrollTo', function (rowEntity, colDef) { return self.scrollTo(rowEntity, colDef);}  );\n\n    /**\n     * @ngdoc function\n     * @name registerRowsProcessor\n     * @methodOf ui.grid.core.api:PublicApi\n     * @description\n     * Register a \"rows processor\" function. When the rows are updated,\n     * the grid calls each registered \"rows processor\", which has a chance\n     * to alter the set of rows (sorting, etc) as long as the count is not\n     * modified.\n     *\n     * @param {function(renderedRowsToProcess, columns )} processorFunction rows processor function, which\n     * is run in the context of the grid (i.e. this for the function will be the grid), and must\n     * return the updated rows list, which is passed to the next processor in the chain\n     * @param {number} priority the priority of this processor.  In general we try to do them in 100s to leave room\n     * for other people to inject rows processors at intermediate priorities.  Lower priority rowsProcessors run earlier.\n     *\n     * At present allRowsVisible is running at 50, sort manipulations running at 60-65, filter is running at 100,\n     * sort is at 200, grouping and treeview at 400-410, selectable rows at 500, pagination at 900 (pagination will generally want to be last)\n     */\n    self.api.registerMethod( 'core', 'registerRowsProcessor', this.registerRowsProcessor  );\n\n    /**\n     * @ngdoc function\n     * @name registerColumnsProcessor\n     * @methodOf ui.grid.core.api:PublicApi\n     * @description\n     * Register a \"columns processor\" function. When the columns are updated,\n     * the grid calls each registered \"columns processor\", which has a chance\n     * to alter the set of columns as long as the count is not\n     * modified.\n     *\n     * @param {function(renderedColumnsToProcess, rows )} processorFunction columns processor function, which\n     * is run in the context of the grid (i.e. this for the function will be the grid), and must\n     * return the updated columns list, which is passed to the next processor in the chain\n     * @param {number} priority the priority of this processor.  In general we try to do them in 100s to leave room\n     * for other people to inject columns processors at intermediate priorities.  Lower priority columnsProcessors run earlier.\n     *\n     * At present allRowsVisible is running at 50, filter is running at 100, sort is at 200, grouping at 400, selectable rows at 500, pagination at 900 (pagination will generally want to be last)\n     */\n    self.api.registerMethod( 'core', 'registerColumnsProcessor', this.registerColumnsProcessor  );\n\n\n\n    /**\n     * @ngdoc function\n     * @name sortHandleNulls\n     * @methodOf ui.grid.core.api:PublicApi\n     * @description A null handling method that can be used when building custom sort\n     * functions\n     * @example\n     * <pre>\n     *   mySortFn = function(a, b) {\n     *   var nulls = $scope.gridApi.core.sortHandleNulls(a, b);\n     *   if ( nulls !== null ){\n     *     return nulls;\n     *   } else {\n     *     // your code for sorting here\n     *   };\n     * </pre>\n     * @param {object} a sort value a\n     * @param {object} b sort value b\n     * @returns {number} null if there were no nulls/undefineds, otherwise returns\n     * a sort value that should be passed back from the sort function\n     *\n     */\n    self.api.registerMethod( 'core', 'sortHandleNulls', rowSorter.handleNulls );\n\n\n    /**\n     * @ngdoc function\n     * @name sortChanged\n     * @methodOf  ui.grid.core.api:PublicApi\n     * @description The sort criteria on one or more columns has\n     * changed.  Provides as parameters the grid and the output of\n     * getColumnSorting, which is an array of gridColumns\n     * that have sorting on them, sorted in priority order.\n     *\n     * @param {$scope} scope The scope of the controller. This is used to deregister this event when the scope is destroyed.\n     * @param {Function} callBack Will be called when the event is emited. The function passes back the grid and an array of\n     * columns with sorts on them, in priority order.\n     *\n     * @example\n     * <pre>\n     *      gridApi.core.on.sortChanged( $scope, function(grid, sortColumns){\n     *        // do something\n     *      });\n     * </pre>\n     */\n    self.api.registerEvent( 'core', 'sortChanged' );\n\n      /**\n     * @ngdoc function\n     * @name columnVisibilityChanged\n     * @methodOf  ui.grid.core.api:PublicApi\n     * @description The visibility of a column has changed,\n     * the column itself is passed out as a parameter of the event.\n     *\n     * @param {$scope} scope The scope of the controller. This is used to deregister this event when the scope is destroyed.\n     * @param {Function} callBack Will be called when the event is emited. The function passes back the GridCol that has changed.\n     *\n     * @example\n     * <pre>\n     *      gridApi.core.on.columnVisibilityChanged( $scope, function (column) {\n     *        // do something\n     *      } );\n     * </pre>\n     */\n    self.api.registerEvent( 'core', 'columnVisibilityChanged' );\n\n    /**\n     * @ngdoc method\n     * @name notifyDataChange\n     * @methodOf ui.grid.core.api:PublicApi\n     * @description Notify the grid that a data or config change has occurred,\n     * where that change isn't something the grid was otherwise noticing.  This\n     * might be particularly relevant where you've changed values within the data\n     * and you'd like cell classes to be re-evaluated, or changed config within\n     * the columnDef and you'd like headerCellClasses to be re-evaluated.\n     * @param {string} type one of the\n     * {@link ui.grid.service:uiGridConstants#properties_dataChange uiGridConstants.dataChange}\n     * values (ALL, ROW, EDIT, COLUMN), which tells us which refreshes to fire.\n     *\n     */\n    self.api.registerMethod( 'core', 'notifyDataChange', this.notifyDataChange );\n\n    /**\n     * @ngdoc method\n     * @name clearAllFilters\n     * @methodOf ui.grid.core.api:PublicApi\n     * @description Clears all filters and optionally refreshes the visible rows.\n     * @param {object} refreshRows Defaults to true.\n     * @param {object} clearConditions Defaults to false.\n     * @param {object} clearFlags Defaults to false.\n     * @returns {promise} If `refreshRows` is true, returns a promise of the rows refreshing.\n     */\n    self.api.registerMethod('core', 'clearAllFilters', this.clearAllFilters);\n\n    self.registerDataChangeCallback( self.columnRefreshCallback, [uiGridConstants.dataChange.COLUMN]);\n    self.registerDataChangeCallback( self.processRowsCallback, [uiGridConstants.dataChange.EDIT]);\n    self.registerDataChangeCallback( self.updateFooterHeightCallback, [uiGridConstants.dataChange.OPTIONS]);\n\n    self.registerStyleComputation({\n      priority: 10,\n      func: self.getFooterStyles\n    });\n  };\n\n   Grid.prototype.calcFooterHeight = function () {\n     if (!this.hasFooter()) {\n       return 0;\n     }\n\n     var height = 0;\n     if (this.options.showGridFooter) {\n       height += this.options.gridFooterHeight;\n     }\n\n     height += this.calcColumnFooterHeight();\n\n     return height;\n   };\n\n   Grid.prototype.calcColumnFooterHeight = function () {\n     var height = 0;\n\n     if (this.options.showColumnFooter) {\n       height += this.options.columnFooterHeight;\n     }\n\n     return height;\n   };\n\n   Grid.prototype.getFooterStyles = function () {\n     var style = '.grid' + this.id + ' .ui-grid-footer-aggregates-row { height: ' + this.options.columnFooterHeight + 'px; }';\n     style += ' .grid' + this.id + ' .ui-grid-footer-info { height: ' + this.options.gridFooterHeight + 'px; }';\n     return style;\n   };\n\n  Grid.prototype.hasFooter = function () {\n   return this.options.showGridFooter || this.options.showColumnFooter;\n  };\n\n  /**\n   * @ngdoc function\n   * @name isRTL\n   * @methodOf ui.grid.class:Grid\n   * @description Returns true if grid is RightToLeft\n   */\n  Grid.prototype.isRTL = function () {\n    return this.rtl;\n  };\n\n\n  /**\n   * @ngdoc function\n   * @name registerColumnBuilder\n   * @methodOf ui.grid.class:Grid\n   * @description When the build creates columns from column definitions, the columnbuilders will be called to add\n   * additional properties to the column.\n   * @param {function(colDef, col, gridOptions)} columnBuilder function to be called\n   */\n  Grid.prototype.registerColumnBuilder = function registerColumnBuilder(columnBuilder) {\n    this.columnBuilders.push(columnBuilder);\n  };\n\n  /**\n   * @ngdoc function\n   * @name buildColumnDefsFromData\n   * @methodOf ui.grid.class:Grid\n   * @description Populates columnDefs from the provided data\n   * @param {function(colDef, col, gridOptions)} rowBuilder function to be called\n   */\n  Grid.prototype.buildColumnDefsFromData = function (dataRows){\n    this.options.columnDefs =  gridUtil.getColumnsFromData(dataRows, this.options.excludeProperties);\n  };\n\n  /**\n   * @ngdoc function\n   * @name registerRowBuilder\n   * @methodOf ui.grid.class:Grid\n   * @description When the build creates rows from gridOptions.data, the rowBuilders will be called to add\n   * additional properties to the row.\n   * @param {function(row, gridOptions)} rowBuilder function to be called\n   */\n  Grid.prototype.registerRowBuilder = function registerRowBuilder(rowBuilder) {\n    this.rowBuilders.push(rowBuilder);\n  };\n\n\n  /**\n   * @ngdoc function\n   * @name registerDataChangeCallback\n   * @methodOf ui.grid.class:Grid\n   * @description When a data change occurs, the data change callbacks of the specified type\n   * will be called.  The rules are:\n   *\n   * - when the data watch fires, that is considered a ROW change (the data watch only notices\n   *   added or removed rows)\n   * - when the api is called to inform us of a change, the declared type of that change is used\n   * - when a cell edit completes, the EDIT callbacks are triggered\n   * - when the columnDef watch fires, the COLUMN callbacks are triggered\n   * - when the options watch fires, the OPTIONS callbacks are triggered\n   *\n   * For a given event:\n   * - ALL calls ROW, EDIT, COLUMN, OPTIONS and ALL callbacks\n   * - ROW calls ROW and ALL callbacks\n   * - EDIT calls EDIT and ALL callbacks\n   * - COLUMN calls COLUMN and ALL callbacks\n   * - OPTIONS calls OPTIONS and ALL callbacks\n   *\n   * @param {function(grid)} callback function to be called\n   * @param {array} types the types of data change you want to be informed of.  Values from\n   * the {@link ui.grid.service:uiGridConstants#properties_dataChange uiGridConstants.dataChange}\n   *  values ( ALL, EDIT, ROW, COLUMN, OPTIONS ).  Optional and defaults to ALL\n   * @returns {function} deregister function - a function that can be called to deregister this callback\n   */\n  Grid.prototype.registerDataChangeCallback = function registerDataChangeCallback(callback, types, _this) {\n    var uid = gridUtil.nextUid();\n    if ( !types ){\n      types = [uiGridConstants.dataChange.ALL];\n    }\n    if ( !Array.isArray(types)){\n      gridUtil.logError(\"Expected types to be an array or null in registerDataChangeCallback, value passed was: \" + types );\n    }\n    this.dataChangeCallbacks[uid] = { callback: callback, types: types, _this:_this };\n\n    var self = this;\n    var deregisterFunction = function() {\n      delete self.dataChangeCallbacks[uid];\n    };\n    return deregisterFunction;\n  };\n\n  /**\n   * @ngdoc function\n   * @name callDataChangeCallbacks\n   * @methodOf ui.grid.class:Grid\n   * @description Calls the callbacks based on the type of data change that\n   * has occurred. Always calls the ALL callbacks, calls the ROW, EDIT, COLUMN and OPTIONS callbacks if the\n   * event type is matching, or if the type is ALL.\n   * @param {string} type the type of event that occurred - one of the\n   * {@link ui.grid.service:uiGridConstants#properties_dataChange uiGridConstants.dataChange}\n   *  values (ALL, ROW, EDIT, COLUMN, OPTIONS)\n   */\n  Grid.prototype.callDataChangeCallbacks = function callDataChangeCallbacks(type, options) {\n    angular.forEach( this.dataChangeCallbacks, function( callback, uid ){\n      if ( callback.types.indexOf( uiGridConstants.dataChange.ALL ) !== -1 ||\n           callback.types.indexOf( type ) !== -1 ||\n           type === uiGridConstants.dataChange.ALL ) {\n        if (callback._this) {\n           callback.callback.apply(callback._this,this);\n        }\n        else {\n          callback.callback( this );\n        }\n      }\n    }, this);\n  };\n\n  /**\n   * @ngdoc function\n   * @name notifyDataChange\n   * @methodOf ui.grid.class:Grid\n   * @description Notifies us that a data change has occurred, used in the public\n   * api for users to tell us when they've changed data or some other event that\n   * our watches cannot pick up\n   * @param {string} type the type of event that occurred - one of the\n   * uiGridConstants.dataChange values (ALL, ROW, EDIT, COLUMN)\n   */\n  Grid.prototype.notifyDataChange = function notifyDataChange(type) {\n    var constants = uiGridConstants.dataChange;\n    if ( type === constants.ALL ||\n         type === constants.COLUMN ||\n         type === constants.EDIT ||\n         type === constants.ROW ||\n         type === constants.OPTIONS ){\n      this.callDataChangeCallbacks( type );\n    } else {\n      gridUtil.logError(\"Notified of a data change, but the type was not recognised, so no action taken, type was: \" + type);\n    }\n  };\n\n\n  /**\n   * @ngdoc function\n   * @name columnRefreshCallback\n   * @methodOf ui.grid.class:Grid\n   * @description refreshes the grid when a column refresh\n   * is notified, which triggers handling of the visible flag.\n   * This is called on uiGridConstants.dataChange.COLUMN, and is\n   * registered as a dataChangeCallback in grid.js\n   * @param {string} name column name\n   */\n  Grid.prototype.columnRefreshCallback = function columnRefreshCallback( grid ){\n    grid.buildColumns();\n    grid.queueGridRefresh();\n  };\n\n\n  /**\n   * @ngdoc function\n   * @name processRowsCallback\n   * @methodOf ui.grid.class:Grid\n   * @description calls the row processors, specifically\n   * intended to reset the sorting when an edit is called,\n   * registered as a dataChangeCallback on uiGridConstants.dataChange.EDIT\n   * @param {string} name column name\n   */\n  Grid.prototype.processRowsCallback = function processRowsCallback( grid ){\n    grid.queueGridRefresh();\n  };\n\n\n  /**\n   * @ngdoc function\n   * @name updateFooterHeightCallback\n   * @methodOf ui.grid.class:Grid\n   * @description recalculates the footer height,\n   * registered as a dataChangeCallback on uiGridConstants.dataChange.OPTIONS\n   * @param {string} name column name\n   */\n  Grid.prototype.updateFooterHeightCallback = function updateFooterHeightCallback( grid ){\n    grid.footerHeight = grid.calcFooterHeight();\n    grid.columnFooterHeight = grid.calcColumnFooterHeight();\n  };\n\n\n  /**\n   * @ngdoc function\n   * @name getColumn\n   * @methodOf ui.grid.class:Grid\n   * @description returns a grid column for the column name\n   * @param {string} name column name\n   */\n  Grid.prototype.getColumn = function getColumn(name) {\n    var columns = this.columns.filter(function (column) {\n      return column.colDef.name === name;\n    });\n    return columns.length > 0 ? columns[0] : null;\n  };\n\n  /**\n   * @ngdoc function\n   * @name getColDef\n   * @methodOf ui.grid.class:Grid\n   * @description returns a grid colDef for the column name\n   * @param {string} name column.field\n   */\n  Grid.prototype.getColDef = function getColDef(name) {\n    var colDefs = this.options.columnDefs.filter(function (colDef) {\n      return colDef.name === name;\n    });\n    return colDefs.length > 0 ? colDefs[0] : null;\n  };\n\n  /**\n   * @ngdoc function\n   * @name assignTypes\n   * @methodOf ui.grid.class:Grid\n   * @description uses the first row of data to assign colDef.type for any types not defined.\n   */\n  /**\n   * @ngdoc property\n   * @name type\n   * @propertyOf ui.grid.class:GridOptions.columnDef\n   * @description the type of the column, used in sorting.  If not provided then the\n   * grid will guess the type.  Add this only if the grid guessing is not to your\n   * satisfaction.  One of:\n   * - 'string'\n   * - 'boolean'\n   * - 'number'\n   * - 'date'\n   * - 'object'\n   * - 'numberStr'\n   * Note that if you choose date, your dates should be in a javascript date type\n   *\n   */\n  Grid.prototype.assignTypes = function(){\n    var self = this;\n    self.options.columnDefs.forEach(function (colDef, index) {\n\n      //Assign colDef type if not specified\n      if (!colDef.type) {\n        var col = new GridColumn(colDef, index, self);\n        var firstRow = self.rows.length > 0 ? self.rows[0] : null;\n        if (firstRow) {\n          colDef.type = gridUtil.guessType(self.getCellValue(firstRow, col));\n        }\n        else {\n          colDef.type = 'string';\n        }\n      }\n    });\n  };\n\n\n  /**\n   * @ngdoc function\n   * @name isRowHeaderColumn\n   * @methodOf ui.grid.class:Grid\n   * @description returns true if the column is a row Header\n   * @param {object} column column\n   */\n  Grid.prototype.isRowHeaderColumn = function isRowHeaderColumn(column) {\n    return this.rowHeaderColumns.indexOf(column) !== -1;\n  };\n\n  /**\n  * @ngdoc function\n  * @name addRowHeaderColumn\n  * @methodOf ui.grid.class:Grid\n  * @description adds a row header column to the grid\n  * @param {object} column def\n  */\n  Grid.prototype.addRowHeaderColumn = function addRowHeaderColumn(colDef, order) {\n    var self = this;\n\n    //default order\n    if (order === undefined) {\n      order = 0;\n    }\n\n    var rowHeaderCol = new GridColumn(colDef, gridUtil.nextUid(), self);\n    rowHeaderCol.isRowHeader = true;\n    if (self.isRTL()) {\n      self.createRightContainer();\n      rowHeaderCol.renderContainer = 'right';\n    }\n    else {\n      self.createLeftContainer();\n      rowHeaderCol.renderContainer = 'left';\n    }\n\n    // relies on the default column builder being first in array, as it is instantiated\n    // as part of grid creation\n    self.columnBuilders[0](colDef,rowHeaderCol,self.options)\n      .then(function(){\n        rowHeaderCol.enableFiltering = false;\n        rowHeaderCol.enableSorting = false;\n        rowHeaderCol.enableHiding = false;\n        rowHeaderCol.headerPriority = order;\n        self.rowHeaderColumns.push(rowHeaderCol);\n        self.rowHeaderColumns = self.rowHeaderColumns.sort(function (a, b) {\n          return a.headerPriority - b.headerPriority;\n        });\n\n        self.buildColumns()\n          .then( function() {\n            self.preCompileCellTemplates();\n            self.queueGridRefresh();\n          });\n      });\n  };\n\n  /**\n   * @ngdoc function\n   * @name getOnlyDataColumns\n   * @methodOf ui.grid.class:Grid\n   * @description returns all columns except for rowHeader columns\n   */\n  Grid.prototype.getOnlyDataColumns = function getOnlyDataColumns() {\n    var self = this;\n    var cols = [];\n    self.columns.forEach(function (col) {\n      if (self.rowHeaderColumns.indexOf(col) === -1) {\n        cols.push(col);\n      }\n    });\n    return cols;\n  };\n\n  /**\n   * @ngdoc function\n   * @name buildColumns\n   * @methodOf ui.grid.class:Grid\n   * @description creates GridColumn objects from the columnDefinition.  Calls each registered\n   * columnBuilder to further process the column\n   * @param {object} options  An object contains options to use when building columns\n   *\n   * * **orderByColumnDefs**: defaults to **false**. When true, `buildColumns` will reorder existing columns according to the order within the column definitions.\n   *\n   * @returns {Promise} a promise to load any needed column resources\n   */\n  Grid.prototype.buildColumns = function buildColumns(opts) {\n    var options = {\n      orderByColumnDefs: false\n    };\n\n    angular.extend(options, opts);\n\n    // gridUtil.logDebug('buildColumns');\n    var self = this;\n    var builderPromises = [];\n    var headerOffset = self.rowHeaderColumns.length;\n    var i;\n\n    // Remove any columns for which a columnDef cannot be found\n    // Deliberately don't use forEach, as it doesn't like splice being called in the middle\n    // Also don't cache columns.length, as it will change during this operation\n    for (i = 0; i < self.columns.length; i++){\n      if (!self.getColDef(self.columns[i].name)) {\n        self.columns.splice(i, 1);\n        i--;\n      }\n    }\n\n    //add row header columns to the grid columns array _after_ columns without columnDefs have been removed\n    //rowHeaderColumns is ordered by priority so insert in reverse\n    for (var j = self.rowHeaderColumns.length - 1; j >= 0; j--) {\n      self.columns.unshift(self.rowHeaderColumns[j]);\n    }\n\n\n\n    // look at each column def, and update column properties to match.  If the column def\n    // doesn't have a column, then splice in a new gridCol\n    self.options.columnDefs.forEach(function (colDef, index) {\n      self.preprocessColDef(colDef);\n      var col = self.getColumn(colDef.name);\n\n      if (!col) {\n        col = new GridColumn(colDef, gridUtil.nextUid(), self);\n        self.columns.splice(index + headerOffset, 0, col);\n      }\n      else {\n        // tell updateColumnDef that the column was pre-existing\n        col.updateColumnDef(colDef, false);\n      }\n\n      self.columnBuilders.forEach(function (builder) {\n        builderPromises.push(builder.call(self, colDef, col, self.options));\n      });\n    });\n\n    /*** Reorder columns if necessary ***/\n    if (!!options.orderByColumnDefs) {\n      // Create a shallow copy of the columns as a cache\n      var columnCache = self.columns.slice(0);\n\n      // We need to allow for the \"row headers\" when mapping from the column defs array to the columns array\n      //   If we have a row header in columns[0] and don't account for it   we'll overwrite it with the column in columnDefs[0]\n\n      // Go through all the column defs, use the shorter of columns length and colDefs.length because if a user has given two columns the same name then\n      // columns will be shorter than columnDefs.  In this situation we'll avoid an error, but the user will still get an unexpected result\n      var len = Math.min(self.options.columnDefs.length, self.columns.length);\n      for (i = 0; i < len; i++) {\n        // If the column at this index has a different name than the column at the same index in the column defs...\n        if (self.columns[i + headerOffset].name !== self.options.columnDefs[i].name) {\n          // Replace the one in the cache with the appropriate column\n          columnCache[i + headerOffset] = self.getColumn(self.options.columnDefs[i].name);\n        }\n        else {\n          // Otherwise just copy over the one from the initial columns\n          columnCache[i + headerOffset] = self.columns[i + headerOffset];\n        }\n      }\n\n      // Empty out the columns array, non-destructively\n      self.columns.length = 0;\n\n      // And splice in the updated, ordered columns from the cache\n      Array.prototype.splice.apply(self.columns, [0, 0].concat(columnCache));\n    }\n\n    return $q.all(builderPromises).then(function(){\n      if (self.rows.length > 0){\n        self.assignTypes();\n      }\n    });\n  };\n\n  Grid.prototype.preCompileCellTemplate = function(col) {\n    var self = this;\n    var html = col.cellTemplate.replace(uiGridConstants.MODEL_COL_FIELD, self.getQualifiedColField(col));\n    html = html.replace(uiGridConstants.COL_FIELD, 'grid.getCellValue(row, col)');\n\n    var compiledElementFn = $compile(html);\n    col.compiledElementFn = compiledElementFn;\n\n    if (col.compiledElementFnDefer) {\n      col.compiledElementFnDefer.resolve(col.compiledElementFn);\n    }\n  };\n\n/**\n * @ngdoc function\n * @name preCompileCellTemplates\n * @methodOf ui.grid.class:Grid\n * @description precompiles all cell templates\n */\n  Grid.prototype.preCompileCellTemplates = function() {\n    var self = this;\n    self.columns.forEach(function (col) {\n      if ( col.cellTemplate ){\n        self.preCompileCellTemplate( col );\n      } else if ( col.cellTemplatePromise ){\n        col.cellTemplatePromise.then( function() {\n          self.preCompileCellTemplate( col );\n        });\n      }\n    });\n  };\n\n  /**\n   * @ngdoc function\n   * @name getGridQualifiedColField\n   * @methodOf ui.grid.class:Grid\n   * @description Returns the $parse-able accessor for a column within its $scope\n   * @param {GridColumn} col col object\n   */\n  Grid.prototype.getQualifiedColField = function (col) {\n    var base = 'row.entity';\n    if ( col.field === uiGridConstants.ENTITY_BINDING ) {\n      return base;\n    }\n    return gridUtil.preEval(base + '.' + col.field);\n  };\n\n  /**\n   * @ngdoc function\n   * @name createLeftContainer\n   * @methodOf ui.grid.class:Grid\n   * @description creates the left render container if it doesn't already exist\n   */\n  Grid.prototype.createLeftContainer = function() {\n    if (!this.hasLeftContainer()) {\n      this.renderContainers.left = new GridRenderContainer('left', this, { disableColumnOffset: true });\n    }\n  };\n\n  /**\n   * @ngdoc function\n   * @name createRightContainer\n   * @methodOf ui.grid.class:Grid\n   * @description creates the right render container if it doesn't already exist\n   */\n  Grid.prototype.createRightContainer = function() {\n    if (!this.hasRightContainer()) {\n      this.renderContainers.right = new GridRenderContainer('right', this, { disableColumnOffset: true });\n    }\n  };\n\n  /**\n   * @ngdoc function\n   * @name hasLeftContainer\n   * @methodOf ui.grid.class:Grid\n   * @description returns true if leftContainer exists\n   */\n  Grid.prototype.hasLeftContainer = function() {\n    return this.renderContainers.left !== undefined;\n  };\n\n  /**\n   * @ngdoc function\n   * @name hasRightContainer\n   * @methodOf ui.grid.class:Grid\n   * @description returns true if rightContainer exists\n   */\n  Grid.prototype.hasRightContainer = function() {\n    return this.renderContainers.right !== undefined;\n  };\n\n\n      /**\n   * undocumented function\n   * @name preprocessColDef\n   * @methodOf ui.grid.class:Grid\n   * @description defaults the name property from field to maintain backwards compatibility with 2.x\n   * validates that name or field is present\n   */\n  Grid.prototype.preprocessColDef = function preprocessColDef(colDef) {\n    var self = this;\n\n    if (!colDef.field && !colDef.name) {\n      throw new Error('colDef.name or colDef.field property is required');\n    }\n\n    //maintain backwards compatibility with 2.x\n    //field was required in 2.x.  now name is required\n    if (colDef.name === undefined && colDef.field !== undefined) {\n      // See if the column name already exists:\n      var newName = colDef.field,\n        counter = 2;\n      while (self.getColumn(newName)) {\n        newName = colDef.field + counter.toString();\n        counter++;\n      }\n      colDef.name = newName;\n    }\n  };\n\n  // Return a list of items that exist in the `n` array but not the `o` array. Uses optional property accessors passed as third & fourth parameters\n  Grid.prototype.newInN = function newInN(o, n, oAccessor, nAccessor) {\n    var self = this;\n\n    var t = [];\n    for (var i = 0; i < n.length; i++) {\n      var nV = nAccessor ? n[i][nAccessor] : n[i];\n\n      var found = false;\n      for (var j = 0; j < o.length; j++) {\n        var oV = oAccessor ? o[j][oAccessor] : o[j];\n        if (self.options.rowEquality(nV, oV)) {\n          found = true;\n          break;\n        }\n      }\n      if (!found) {\n        t.push(nV);\n      }\n    }\n\n    return t;\n  };\n\n  /**\n   * @ngdoc function\n   * @name getRow\n   * @methodOf ui.grid.class:Grid\n   * @description returns the GridRow that contains the rowEntity\n   * @param {object} rowEntity the gridOptions.data array element instance\n   * @param {array} rows [optional] the rows to look in - if not provided then\n   * looks in grid.rows\n   */\n  Grid.prototype.getRow = function getRow(rowEntity, lookInRows) {\n    var self = this;\n\n    lookInRows = typeof(lookInRows) === 'undefined' ? self.rows : lookInRows;\n\n    var rows = lookInRows.filter(function (row) {\n      return self.options.rowEquality(row.entity, rowEntity);\n    });\n    return rows.length > 0 ? rows[0] : null;\n  };\n\n\n  /**\n   * @ngdoc function\n   * @name modifyRows\n   * @methodOf ui.grid.class:Grid\n   * @description creates or removes GridRow objects from the newRawData array.  Calls each registered\n   * rowBuilder to further process the row\n   * @param {array} newRawData Modified set of data\n   *\n   * This method aims to achieve three things:\n   * 1. the resulting rows array is in the same order as the newRawData, we'll call\n   * rowsProcessors immediately after to sort the data anyway\n   * 2. if we have row hashing available, we try to use the rowHash to find the row\n   * 3. no memory leaks - rows that are no longer in newRawData need to be garbage collected\n   *\n   * The basic logic flow makes use of the newRawData, oldRows and oldHash, and creates\n   * the newRows and newHash\n   *\n   * ```\n   * newRawData.forEach newEntity\n   *   if (hashing enabled)\n   *     check oldHash for newEntity\n   *   else\n   *     look for old row directly in oldRows\n   *   if !oldRowFound     // must be a new row\n   *     create newRow\n   *   append to the newRows and add to newHash\n   *   run the processors\n   * ```\n   *\n   * Rows are identified using the hashKey if configured.  If not configured, then rows\n   * are identified using the gridOptions.rowEquality function\n   *\n   * This method is useful when trying to select rows immediately after loading data without\n   * using a $timeout/$interval, e.g.:\n   *\n   *   $scope.gridOptions.data =  someData;\n   *   $scope.gridApi.grid.modifyRows($scope.gridOptions.data);\n   *   $scope.gridApi.selection.selectRow($scope.gridOptions.data[0]);\n   *\n   * OR to persist row selection after data update (e.g. rows selected, new data loaded, want\n   * originally selected rows to be re-selected))\n   */\n  Grid.prototype.modifyRows = function modifyRows(newRawData) {\n    var self = this;\n    var oldRows = self.rows.slice(0);\n    var oldRowHash = self.rowHashMap || self.createRowHashMap();\n    self.rowHashMap = self.createRowHashMap();\n    self.rows.length = 0;\n\n    newRawData.forEach( function( newEntity, i ) {\n      var newRow;\n      if ( self.options.enableRowHashing ){\n        // if hashing is enabled, then this row will be in the hash if we already know about it\n        newRow = oldRowHash.get( newEntity );\n      } else {\n        // otherwise, manually search the oldRows to see if we can find this row\n        newRow = self.getRow(newEntity, oldRows);\n      }\n\n      // if we didn't find the row, it must be new, so create it\n      if ( !newRow ){\n        newRow = self.processRowBuilders(new GridRow(newEntity, i, self));\n      }\n\n      self.rows.push( newRow );\n      self.rowHashMap.put( newEntity, newRow );\n    });\n\n    self.assignTypes();\n\n    var p1 = $q.when(self.processRowsProcessors(self.rows))\n      .then(function (renderableRows) {\n        return self.setVisibleRows(renderableRows);\n      });\n\n    var p2 = $q.when(self.processColumnsProcessors(self.columns))\n      .then(function (renderableColumns) {\n        return self.setVisibleColumns(renderableColumns);\n      });\n\n    return $q.all([p1, p2]);\n  };\n\n\n  /**\n   * Private Undocumented Method\n   * @name addRows\n   * @methodOf ui.grid.class:Grid\n   * @description adds the newRawData array of rows to the grid and calls all registered\n   * rowBuilders. this keyword will reference the grid\n   */\n  Grid.prototype.addRows = function addRows(newRawData) {\n    var self = this;\n\n    var existingRowCount = self.rows.length;\n    for (var i = 0; i < newRawData.length; i++) {\n      var newRow = self.processRowBuilders(new GridRow(newRawData[i], i + existingRowCount, self));\n\n      if (self.options.enableRowHashing) {\n        var found = self.rowHashMap.get(newRow.entity);\n        if (found) {\n          found.row = newRow;\n        }\n      }\n\n      self.rows.push(newRow);\n    }\n  };\n\n  /**\n   * @ngdoc function\n   * @name processRowBuilders\n   * @methodOf ui.grid.class:Grid\n   * @description processes all RowBuilders for the gridRow\n   * @param {GridRow} gridRow reference to gridRow\n   * @returns {GridRow} the gridRow with all additional behavior added\n   */\n  Grid.prototype.processRowBuilders = function processRowBuilders(gridRow) {\n    var self = this;\n\n    self.rowBuilders.forEach(function (builder) {\n      builder.call(self, gridRow, self.options);\n    });\n\n    return gridRow;\n  };\n\n  /**\n   * @ngdoc function\n   * @name registerStyleComputation\n   * @methodOf ui.grid.class:Grid\n   * @description registered a styleComputation function\n   *\n   * If the function returns a value it will be appended into the grid's `<style>` block\n   * @param {function($scope)} styleComputation function\n   */\n  Grid.prototype.registerStyleComputation = function registerStyleComputation(styleComputationInfo) {\n    this.styleComputations.push(styleComputationInfo);\n  };\n\n\n  // NOTE (c0bra): We already have rowBuilders. I think these do exactly the same thing...\n  // Grid.prototype.registerRowFilter = function(filter) {\n  //   // TODO(c0bra): validate filter?\n\n  //   this.rowFilters.push(filter);\n  // };\n\n  // Grid.prototype.removeRowFilter = function(filter) {\n  //   var idx = this.rowFilters.indexOf(filter);\n\n  //   if (typeof(idx) !== 'undefined' && idx !== undefined) {\n  //     this.rowFilters.slice(idx, 1);\n  //   }\n  // };\n\n  // Grid.prototype.processRowFilters = function(rows) {\n  //   var self = this;\n  //   self.rowFilters.forEach(function (filter) {\n  //     filter.call(self, rows);\n  //   });\n  // };\n\n\n  /**\n   * @ngdoc function\n   * @name registerRowsProcessor\n   * @methodOf ui.grid.class:Grid\n   * @description\n   *\n   * Register a \"rows processor\" function. When the rows are updated,\n   * the grid calls each registered \"rows processor\", which has a chance\n   * to alter the set of rows (sorting, etc) as long as the count is not\n   * modified.\n   *\n   * @param {function(renderedRowsToProcess, columns )} processorFunction rows processor function, which\n   * is run in the context of the grid (i.e. this for the function will be the grid), and must\n   * return the updated rows list, which is passed to the next processor in the chain\n   * @param {number} priority the priority of this processor.  In general we try to do them in 100s to leave room\n   * for other people to inject rows processors at intermediate priorities.  Lower priority rowsProcessors run earlier.\n   *\n   * At present all rows visible is running at 50, filter is running at 100, sort is at 200, grouping at 400, selectable rows at 500, pagination at 900 (pagination will generally want to be last)\n   *\n   */\n  Grid.prototype.registerRowsProcessor = function registerRowsProcessor(processor, priority) {\n    if (!angular.isFunction(processor)) {\n      throw 'Attempt to register non-function rows processor: ' + processor;\n    }\n\n    this.rowsProcessors.push({processor: processor, priority: priority});\n    this.rowsProcessors.sort(function sortByPriority( a, b ){\n      return a.priority - b.priority;\n    });\n  };\n\n  /**\n   * @ngdoc function\n   * @name removeRowsProcessor\n   * @methodOf ui.grid.class:Grid\n   * @param {function(renderableRows)} rows processor function\n   * @description Remove a registered rows processor\n   */\n  Grid.prototype.removeRowsProcessor = function removeRowsProcessor(processor) {\n    var idx = -1;\n    this.rowsProcessors.forEach(function(rowsProcessor, index){\n      if ( rowsProcessor.processor === processor ){\n        idx = index;\n      }\n    });\n\n    if ( idx !== -1 ) {\n      this.rowsProcessors.splice(idx, 1);\n    }\n  };\n\n  /**\n   * Private Undocumented Method\n   * @name processRowsProcessors\n   * @methodOf ui.grid.class:Grid\n   * @param {Array[GridRow]} The array of \"renderable\" rows\n   * @param {Array[GridColumn]} The array of columns\n   * @description Run all the registered rows processors on the array of renderable rows\n   */\n  Grid.prototype.processRowsProcessors = function processRowsProcessors(renderableRows) {\n    var self = this;\n\n    // Create a shallow copy of the rows so that we can safely sort them without altering the original grid.rows sort order\n    var myRenderableRows = renderableRows.slice(0);\n\n    // Return myRenderableRows with no processing if we have no rows processors\n    if (self.rowsProcessors.length === 0) {\n      return $q.when(myRenderableRows);\n    }\n\n    // Counter for iterating through rows processors\n    var i = 0;\n\n    // Promise for when we're done with all the processors\n    var finished = $q.defer();\n\n    // This function will call the processor in self.rowsProcessors at index 'i', and then\n    //   when done will call the next processor in the list, using the output from the processor\n    //   at i as the argument for 'renderedRowsToProcess' on the next iteration.\n    //\n    //   If we're at the end of the list of processors, we resolve our 'finished' callback with\n    //   the result.\n    function startProcessor(i, renderedRowsToProcess) {\n      // Get the processor at 'i'\n      var processor = self.rowsProcessors[i].processor;\n\n      // Call the processor, passing in the rows to process and the current columns\n      //   (note: it's wrapped in $q.when() in case the processor does not return a promise)\n      return $q.when( processor.call(self, renderedRowsToProcess, self.columns) )\n        .then(function handleProcessedRows(processedRows) {\n          // Check for errors\n          if (!processedRows) {\n            throw \"Processor at index \" + i + \" did not return a set of renderable rows\";\n          }\n\n          if (!angular.isArray(processedRows)) {\n            throw \"Processor at index \" + i + \" did not return an array\";\n          }\n\n          // Processor is done, increment the counter\n          i++;\n\n          // If we're not done with the processors, call the next one\n          if (i <= self.rowsProcessors.length - 1) {\n            return startProcessor(i, processedRows);\n          }\n          // We're done! Resolve the 'finished' promise\n          else {\n            finished.resolve(processedRows);\n          }\n        });\n    }\n\n    // Start on the first processor\n    startProcessor(0, myRenderableRows);\n\n    return finished.promise;\n  };\n\n  Grid.prototype.setVisibleRows = function setVisibleRows(rows) {\n    var self = this;\n\n    // Reset all the render container row caches\n    for (var i in self.renderContainers) {\n      var container = self.renderContainers[i];\n\n      container.canvasHeightShouldUpdate = true;\n\n      if ( typeof(container.visibleRowCache) === 'undefined' ){\n        container.visibleRowCache = [];\n      } else {\n        container.visibleRowCache.length = 0;\n      }\n    }\n\n    // rows.forEach(function (row) {\n    for (var ri = 0; ri < rows.length; ri++) {\n      var row = rows[ri];\n\n      var targetContainer = (typeof(row.renderContainer) !== 'undefined' && row.renderContainer) ? row.renderContainer : 'body';\n\n      // If the row is visible\n      if (row.visible) {\n        self.renderContainers[targetContainer].visibleRowCache.push(row);\n      }\n    }\n    self.api.core.raise.rowsVisibleChanged(this.api);\n    self.api.core.raise.rowsRendered(this.api);\n  };\n\n  /**\n   * @ngdoc function\n   * @name registerColumnsProcessor\n   * @methodOf ui.grid.class:Grid\n   * @param {function(renderedColumnsToProcess, rows)} columnProcessor column processor function, which\n   * is run in the context of the grid (i.e. this for the function will be the grid), and\n   * which must return an updated renderedColumnsToProcess which can be passed to the next processor\n   * in the chain\n   * @param {number} priority the priority of this processor.  In general we try to do them in 100s to leave room\n   * for other people to inject columns processors at intermediate priorities.  Lower priority columnsProcessors run earlier.\n   *\n   * At present all rows visible is running at 50, filter is running at 100, sort is at 200, grouping at 400, selectable rows at 500, pagination at 900 (pagination will generally want to be last)\n   * @description\n\n     Register a \"columns processor\" function. When the columns are updated,\n     the grid calls each registered \"columns processor\", which has a chance\n     to alter the set of columns, as long as the count is not modified.\n   */\n  Grid.prototype.registerColumnsProcessor = function registerColumnsProcessor(processor, priority) {\n    if (!angular.isFunction(processor)) {\n      throw 'Attempt to register non-function rows processor: ' + processor;\n    }\n\n    this.columnsProcessors.push({processor: processor, priority: priority});\n    this.columnsProcessors.sort(function sortByPriority( a, b ){\n      return a.priority - b.priority;\n    });\n  };\n\n  Grid.prototype.removeColumnsProcessor = function removeColumnsProcessor(processor) {\n    var idx = this.columnsProcessors.indexOf(processor);\n\n    if (typeof(idx) !== 'undefined' && idx !== undefined) {\n      this.columnsProcessors.splice(idx, 1);\n    }\n  };\n\n  Grid.prototype.processColumnsProcessors = function processColumnsProcessors(renderableColumns) {\n    var self = this;\n\n    // Create a shallow copy of the rows so that we can safely sort them without altering the original grid.rows sort order\n    var myRenderableColumns = renderableColumns.slice(0);\n\n    // Return myRenderableRows with no processing if we have no rows processors\n    if (self.columnsProcessors.length === 0) {\n      return $q.when(myRenderableColumns);\n    }\n\n    // Counter for iterating through rows processors\n    var i = 0;\n\n    // Promise for when we're done with all the processors\n    var finished = $q.defer();\n\n    // This function will call the processor in self.rowsProcessors at index 'i', and then\n    //   when done will call the next processor in the list, using the output from the processor\n    //   at i as the argument for 'renderedRowsToProcess' on the next iteration.\n    //\n    //   If we're at the end of the list of processors, we resolve our 'finished' callback with\n    //   the result.\n    function startProcessor(i, renderedColumnsToProcess) {\n      // Get the processor at 'i'\n      var processor = self.columnsProcessors[i].processor;\n\n      // Call the processor, passing in the rows to process and the current columns\n      //   (note: it's wrapped in $q.when() in case the processor does not return a promise)\n      return $q.when( processor.call(self, renderedColumnsToProcess, self.rows) )\n        .then(function handleProcessedRows(processedColumns) {\n          // Check for errors\n          if (!processedColumns) {\n            throw \"Processor at index \" + i + \" did not return a set of renderable rows\";\n          }\n\n          if (!angular.isArray(processedColumns)) {\n            throw \"Processor at index \" + i + \" did not return an array\";\n          }\n\n          // Processor is done, increment the counter\n          i++;\n\n          // If we're not done with the processors, call the next one\n          if (i <= self.columnsProcessors.length - 1) {\n            return startProcessor(i, myRenderableColumns);\n          }\n          // We're done! Resolve the 'finished' promise\n          else {\n            finished.resolve(myRenderableColumns);\n          }\n        });\n    }\n\n    // Start on the first processor\n    startProcessor(0, myRenderableColumns);\n\n    return finished.promise;\n  };\n\n  Grid.prototype.setVisibleColumns = function setVisibleColumns(columns) {\n    // gridUtil.logDebug('setVisibleColumns');\n\n    var self = this;\n\n    // Reset all the render container row caches\n    for (var i in self.renderContainers) {\n      var container = self.renderContainers[i];\n\n      container.visibleColumnCache.length = 0;\n    }\n\n    for (var ci = 0; ci < columns.length; ci++) {\n      var column = columns[ci];\n\n      // If the column is visible\n      if (column.visible) {\n        // If the column has a container specified\n        if (typeof(column.renderContainer) !== 'undefined' && column.renderContainer) {\n          self.renderContainers[column.renderContainer].visibleColumnCache.push(column);\n        }\n        // If not, put it into the body container\n        else {\n          self.renderContainers.body.visibleColumnCache.push(column);\n        }\n      }\n    }\n  };\n\n  /**\n   * @ngdoc function\n   * @name handleWindowResize\n   * @methodOf ui.grid.class:Grid\n   * @description Triggered when the browser window resizes; automatically resizes the grid\n   * @returns {Promise} A resolved promise once the window resize has completed.\n   */\n  Grid.prototype.handleWindowResize = function handleWindowResize($event) {\n    var self = this;\n\n    self.gridWidth = gridUtil.elementWidth(self.element);\n    self.gridHeight = gridUtil.elementHeight(self.element);\n\n    return self.queueRefresh();\n  };\n\n  /**\n   * @ngdoc function\n   * @name queueRefresh\n   * @methodOf ui.grid.class:Grid\n   * @description queues a grid refreshCanvas, a way of debouncing all the refreshes we might otherwise issue\n   */\n  Grid.prototype.queueRefresh = function queueRefresh() {\n    var self = this;\n\n    if (self.refreshCanceller) {\n      $timeout.cancel(self.refreshCanceller);\n    }\n\n    self.refreshCanceller = $timeout(function () {\n      self.refreshCanvas(true);\n    });\n\n    self.refreshCanceller.then(function () {\n      self.refreshCanceller = null;\n    });\n\n    return self.refreshCanceller;\n  };\n\n\n  /**\n   * @ngdoc function\n   * @name queueGridRefresh\n   * @methodOf ui.grid.class:Grid\n   * @description queues a grid refresh, a way of debouncing all the refreshes we might otherwise issue\n   */\n  Grid.prototype.queueGridRefresh = function queueGridRefresh() {\n    var self = this;\n\n    if (self.gridRefreshCanceller) {\n      $timeout.cancel(self.gridRefreshCanceller);\n    }\n\n    self.gridRefreshCanceller = $timeout(function () {\n      self.refresh(true);\n    });\n\n    self.gridRefreshCanceller.then(function () {\n      self.gridRefreshCanceller = null;\n    });\n\n    return self.gridRefreshCanceller;\n  };\n\n\n  /**\n   * @ngdoc function\n   * @name updateCanvasHeight\n   * @methodOf ui.grid.class:Grid\n   * @description flags all render containers to update their canvas height\n   */\n  Grid.prototype.updateCanvasHeight = function updateCanvasHeight() {\n    var self = this;\n\n    for (var containerId in self.renderContainers) {\n      if (self.renderContainers.hasOwnProperty(containerId)) {\n        var container = self.renderContainers[containerId];\n        container.canvasHeightShouldUpdate = true;\n      }\n    }\n  };\n\n  /**\n   * @ngdoc function\n   * @name buildStyles\n   * @methodOf ui.grid.class:Grid\n   * @description calls each styleComputation function\n   */\n  // TODO: this used to take $scope, but couldn't see that it was used\n  Grid.prototype.buildStyles = function buildStyles() {\n    // gridUtil.logDebug('buildStyles');\n\n    var self = this;\n\n    self.customStyles = '';\n\n    self.styleComputations\n      .sort(function(a, b) {\n        if (a.priority === null) { return 1; }\n        if (b.priority === null) { return -1; }\n        if (a.priority === null && b.priority === null) { return 0; }\n        return a.priority - b.priority;\n      })\n      .forEach(function (compInfo) {\n        // this used to provide $scope as a second parameter, but I couldn't find any\n        // style builders that used it, so removed it as part of moving to grid from controller\n        var ret = compInfo.func.call(self);\n\n        if (angular.isString(ret)) {\n          self.customStyles += '\\n' + ret;\n        }\n      });\n  };\n\n\n  Grid.prototype.minColumnsToRender = function minColumnsToRender() {\n    var self = this;\n    var viewport = this.getViewportWidth();\n\n    var min = 0;\n    var totalWidth = 0;\n    self.columns.forEach(function(col, i) {\n      if (totalWidth < viewport) {\n        totalWidth += col.drawnWidth;\n        min++;\n      }\n      else {\n        var currWidth = 0;\n        for (var j = i; j >= i - min; j--) {\n          currWidth += self.columns[j].drawnWidth;\n        }\n        if (currWidth < viewport) {\n          min++;\n        }\n      }\n    });\n\n    return min;\n  };\n\n  Grid.prototype.getBodyHeight = function getBodyHeight() {\n    // Start with the viewportHeight\n    var bodyHeight = this.getViewportHeight();\n\n    // Add the horizontal scrollbar height if there is one\n    //if (typeof(this.horizontalScrollbarHeight) !== 'undefined' && this.horizontalScrollbarHeight !== undefined && this.horizontalScrollbarHeight > 0) {\n    //  bodyHeight = bodyHeight + this.horizontalScrollbarHeight;\n    //}\n\n    return bodyHeight;\n  };\n\n  // NOTE: viewport drawable height is the height of the grid minus the header row height (including any border)\n  // TODO(c0bra): account for footer height\n  Grid.prototype.getViewportHeight = function getViewportHeight() {\n    var self = this;\n\n    var viewPortHeight = this.gridHeight - this.headerHeight - this.footerHeight;\n\n    // Account for native horizontal scrollbar, if present\n    //if (typeof(this.horizontalScrollbarHeight) !== 'undefined' && this.horizontalScrollbarHeight !== undefined && this.horizontalScrollbarHeight > 0) {\n    //  viewPortHeight = viewPortHeight - this.horizontalScrollbarHeight;\n    //}\n\n    var adjustment = self.getViewportAdjustment();\n\n    viewPortHeight = viewPortHeight + adjustment.height;\n\n    //gridUtil.logDebug('viewPortHeight', viewPortHeight);\n\n    return viewPortHeight;\n  };\n\n  Grid.prototype.getViewportWidth = function getViewportWidth() {\n    var self = this;\n\n    var viewPortWidth = this.gridWidth;\n\n    //if (typeof(this.verticalScrollbarWidth) !== 'undefined' && this.verticalScrollbarWidth !== undefined && this.verticalScrollbarWidth > 0) {\n    //  viewPortWidth = viewPortWidth - this.verticalScrollbarWidth;\n    //}\n\n    var adjustment = self.getViewportAdjustment();\n\n    viewPortWidth = viewPortWidth + adjustment.width;\n\n    //gridUtil.logDebug('getviewPortWidth', viewPortWidth);\n\n    return viewPortWidth;\n  };\n\n  Grid.prototype.getHeaderViewportWidth = function getHeaderViewportWidth() {\n    var viewPortWidth = this.getViewportWidth();\n\n    //if (typeof(this.verticalScrollbarWidth) !== 'undefined' && this.verticalScrollbarWidth !== undefined && this.verticalScrollbarWidth > 0) {\n    //  viewPortWidth = viewPortWidth + this.verticalScrollbarWidth;\n    //}\n\n    return viewPortWidth;\n  };\n\n  Grid.prototype.addVerticalScrollSync = function (containerId, callBackFn) {\n    this.verticalScrollSyncCallBackFns[containerId] = callBackFn;\n  };\n\n  Grid.prototype.addHorizontalScrollSync = function (containerId, callBackFn) {\n    this.horizontalScrollSyncCallBackFns[containerId] = callBackFn;\n  };\n\n/**\n * Scroll needed containers by calling their ScrollSyncs\n * @param sourceContainerId the containerId that has already set it's top/left.\n *         can be empty string which means all containers need to set top/left\n * @param scrollEvent\n */\n  Grid.prototype.scrollContainers = function (sourceContainerId, scrollEvent) {\n\n    if (scrollEvent.y) {\n      //default for no container Id (ex. mousewheel means that all containers must set scrollTop/Left)\n      var verts = ['body','left', 'right'];\n\n      this.flagScrollingVertically(scrollEvent);\n\n      if (sourceContainerId === 'body') {\n        verts = ['left', 'right'];\n      }\n      else if (sourceContainerId === 'left') {\n        verts = ['body', 'right'];\n      }\n      else if (sourceContainerId === 'right') {\n        verts = ['body', 'left'];\n      }\n\n      for (var i = 0; i < verts.length; i++) {\n        var id = verts[i];\n        if (this.verticalScrollSyncCallBackFns[id]) {\n          this.verticalScrollSyncCallBackFns[id](scrollEvent);\n        }\n      }\n\n    }\n\n    if (scrollEvent.x) {\n      //default for no container Id (ex. mousewheel means that all containers must set scrollTop/Left)\n      var horizs = ['body','bodyheader', 'bodyfooter'];\n\n      this.flagScrollingHorizontally(scrollEvent);\n      if (sourceContainerId === 'body') {\n        horizs = ['bodyheader', 'bodyfooter'];\n      }\n\n      for (var j = 0; j < horizs.length; j++) {\n        var idh = horizs[j];\n        if (this.horizontalScrollSyncCallBackFns[idh]) {\n          this.horizontalScrollSyncCallBackFns[idh](scrollEvent);\n        }\n      }\n\n    }\n\n  };\n\n  Grid.prototype.registerViewportAdjuster = function registerViewportAdjuster(func) {\n    this.viewportAdjusters.push(func);\n  };\n\n  Grid.prototype.removeViewportAdjuster = function registerViewportAdjuster(func) {\n    var idx = this.viewportAdjusters.indexOf(func);\n\n    if (typeof(idx) !== 'undefined' && idx !== undefined) {\n      this.viewportAdjusters.splice(idx, 1);\n    }\n  };\n\n  Grid.prototype.getViewportAdjustment = function getViewportAdjustment() {\n    var self = this;\n\n    var adjustment = { height: 0, width: 0 };\n\n    self.viewportAdjusters.forEach(function (func) {\n      adjustment = func.call(this, adjustment);\n    });\n\n    return adjustment;\n  };\n\n  Grid.prototype.getVisibleRowCount = function getVisibleRowCount() {\n    // var count = 0;\n\n    // this.rows.forEach(function (row) {\n    //   if (row.visible) {\n    //     count++;\n    //   }\n    // });\n\n    // return this.visibleRowCache.length;\n    return this.renderContainers.body.visibleRowCache.length;\n  };\n\n   Grid.prototype.getVisibleRows = function getVisibleRows() {\n    return this.renderContainers.body.visibleRowCache;\n   };\n\n  Grid.prototype.getVisibleColumnCount = function getVisibleColumnCount() {\n    // var count = 0;\n\n    // this.rows.forEach(function (row) {\n    //   if (row.visible) {\n    //     count++;\n    //   }\n    // });\n\n    // return this.visibleRowCache.length;\n    return this.renderContainers.body.visibleColumnCache.length;\n  };\n\n\n  Grid.prototype.searchRows = function searchRows(renderableRows) {\n    return rowSearcher.search(this, renderableRows, this.columns);\n  };\n\n  Grid.prototype.sortByColumn = function sortByColumn(renderableRows) {\n    return rowSorter.sort(this, renderableRows, this.columns);\n  };\n\n  /**\n   * @ngdoc function\n   * @name getCellValue\n   * @methodOf ui.grid.class:Grid\n   * @description Gets the value of a cell for a particular row and column\n   * @param {GridRow} row Row to access\n   * @param {GridColumn} col Column to access\n   */\n  Grid.prototype.getCellValue = function getCellValue(row, col){\n    if ( typeof(row.entity[ '$$' + col.uid ]) !== 'undefined' ) {\n      return row.entity[ '$$' + col.uid].rendered;\n    } else if (this.options.flatEntityAccess && typeof(col.field) !== 'undefined' ){\n      return row.entity[col.field];\n    } else {\n      if (!col.cellValueGetterCache) {\n        col.cellValueGetterCache = $parse(row.getEntityQualifiedColField(col));\n      }\n\n      return col.cellValueGetterCache(row);\n    }\n  };\n\n  /**\n   * @ngdoc function\n   * @name getCellDisplayValue\n   * @methodOf ui.grid.class:Grid\n   * @description Gets the displayed value of a cell after applying any the `cellFilter`\n   * @param {GridRow} row Row to access\n   * @param {GridColumn} col Column to access\n   */\n  Grid.prototype.getCellDisplayValue = function getCellDisplayValue(row, col) {\n    if ( !col.cellDisplayGetterCache ) {\n      var custom_filter = col.cellFilter ? \" | \" + col.cellFilter : \"\";\n\n      if (typeof(row.entity['$$' + col.uid]) !== 'undefined') {\n        col.cellDisplayGetterCache = $parse(row.entity['$$' + col.uid].rendered + custom_filter);\n      } else if (this.options.flatEntityAccess && typeof(col.field) !== 'undefined') {\n        col.cellDisplayGetterCache = $parse(row.entity[col.field] + custom_filter);\n      } else {\n        col.cellDisplayGetterCache = $parse(row.getEntityQualifiedColField(col) + custom_filter);\n      }\n    }\n\n    return col.cellDisplayGetterCache(row);\n  };\n\n\n  Grid.prototype.getNextColumnSortPriority = function getNextColumnSortPriority() {\n    var self = this,\n        p = 0;\n\n    self.columns.forEach(function (col) {\n      if (col.sort && col.sort.priority !== undefined && col.sort.priority >= p) {\n        p = col.sort.priority + 1;\n      }\n    });\n\n    return p;\n  };\n\n  /**\n   * @ngdoc function\n   * @name resetColumnSorting\n   * @methodOf ui.grid.class:Grid\n   * @description Return the columns that the grid is currently being sorted by\n   * @param {GridColumn} [excludedColumn] Optional GridColumn to exclude from having its sorting reset\n   */\n  Grid.prototype.resetColumnSorting = function resetColumnSorting(excludeCol) {\n    var self = this;\n\n    self.columns.forEach(function (col) {\n      if (col !== excludeCol && !col.suppressRemoveSort) {\n        col.sort = {};\n      }\n    });\n  };\n\n  /**\n   * @ngdoc function\n   * @name getColumnSorting\n   * @methodOf ui.grid.class:Grid\n   * @description Return the columns that the grid is currently being sorted by\n   * @returns {Array[GridColumn]} An array of GridColumn objects\n   */\n  Grid.prototype.getColumnSorting = function getColumnSorting() {\n    var self = this;\n\n    var sortedCols = [], myCols;\n\n    // Iterate through all the columns, sorted by priority\n    // Make local copy of column list, because sorting is in-place and we do not want to\n    // change the original sequence of columns\n    myCols = self.columns.slice(0);\n    myCols.sort(rowSorter.prioritySort).forEach(function (col) {\n      if (col.sort && typeof(col.sort.direction) !== 'undefined' && col.sort.direction && (col.sort.direction === uiGridConstants.ASC || col.sort.direction === uiGridConstants.DESC)) {\n        sortedCols.push(col);\n      }\n    });\n\n    return sortedCols;\n  };\n\n  /**\n   * @ngdoc function\n   * @name sortColumn\n   * @methodOf ui.grid.class:Grid\n   * @description Set the sorting on a given column, optionally resetting any existing sorting on the Grid.\n   * Emits the sortChanged event whenever the sort criteria are changed.\n   * @param {GridColumn} column Column to set the sorting on\n   * @param {uiGridConstants.ASC|uiGridConstants.DESC} [direction] Direction to sort by, either descending or ascending.\n   *   If not provided, the column will iterate through the sort directions\n   *   specified in the {@link ui.grid.class:GridOptions.columnDef#sortDirectionCycle sortDirectionCycle} attribute.\n   * @param {boolean} [add] Add this column to the sorting. If not provided or set to `false`, the Grid will reset any existing sorting and sort\n   *   by this column only\n   * @returns {Promise} A resolved promise that supplies the column.\n   */\n\n  Grid.prototype.sortColumn = function sortColumn(column, directionOrAdd, add) {\n    var self = this,\n        direction = null;\n\n    if (typeof(column) === 'undefined' || !column) {\n      throw new Error('No column parameter provided');\n    }\n\n    // Second argument can either be a direction or whether to add this column to the existing sort.\n    //   If it's a boolean, it's an add, otherwise, it's a direction\n    if (typeof(directionOrAdd) === 'boolean') {\n      add = directionOrAdd;\n    }\n    else {\n      direction = directionOrAdd;\n    }\n\n    if (!add) {\n      self.resetColumnSorting(column);\n      column.sort.priority = undefined;\n      // Get the actual priority since there may be columns which have suppressRemoveSort set\n      column.sort.priority = self.getNextColumnSortPriority();\n    }\n    else if (column.sort.priority === undefined){\n      column.sort.priority = self.getNextColumnSortPriority();\n    }\n\n    if (!direction) {\n      // Find the current position in the cycle (or -1).\n      var i = column.sortDirectionCycle.indexOf(column.sort.direction ? column.sort.direction : null);\n      // Proceed to the next position in the cycle (or start at the beginning).\n      i = (i+1) % column.sortDirectionCycle.length;\n      // If suppressRemoveSort is set, and the next position in the cycle would\n      // remove the sort, skip it.\n      if (column.colDef && column.suppressRemoveSort && !column.sortDirectionCycle[i]) {\n        i = (i+1) % column.sortDirectionCycle.length;\n      }\n\n      if (column.sortDirectionCycle[i]) {\n        column.sort.direction = column.sortDirectionCycle[i];\n      } else {\n        removeSortOfColumn(column, self);\n      }\n    }\n    else {\n      column.sort.direction = direction;\n    }\n\n    self.api.core.raise.sortChanged( self, self.getColumnSorting() );\n\n    return $q.when(column);\n  };\n\n  var removeSortOfColumn = function removeSortOfColumn(column, grid) {\n    //Decrease priority for every col where priority is higher than the removed sort's priority.\n    grid.columns.forEach(function (col) {\n      if (col.sort && col.sort.priority !== undefined && col.sort.priority > column.sort.priority) {\n        col.sort.priority -= 1;\n      }\n    });\n\n    //Remove sort\n    column.sort = {};\n  };\n\n  /**\n   * communicate to outside world that we are done with initial rendering\n   */\n  Grid.prototype.renderingComplete = function(){\n    if (angular.isFunction(this.options.onRegisterApi)) {\n      this.options.onRegisterApi(this.api);\n    }\n    this.api.core.raise.renderingComplete( this.api );\n  };\n\n  Grid.prototype.createRowHashMap = function createRowHashMap() {\n    var self = this;\n\n    var hashMap = new RowHashMap();\n    hashMap.grid = self;\n\n    return hashMap;\n  };\n\n\n  /**\n   * @ngdoc function\n   * @name refresh\n   * @methodOf ui.grid.class:Grid\n   * @description Refresh the rendered grid on screen.\n   * @param {boolean} [rowsAltered] Optional flag for refreshing when the number of rows has changed.\n   */\n  Grid.prototype.refresh = function refresh(rowsAltered) {\n    var self = this;\n\n    var p1 = self.processRowsProcessors(self.rows).then(function (renderableRows) {\n      self.setVisibleRows(renderableRows);\n    });\n\n    var p2 = self.processColumnsProcessors(self.columns).then(function (renderableColumns) {\n      self.setVisibleColumns(renderableColumns);\n    });\n\n    return $q.all([p1, p2]).then(function () {\n      self.redrawInPlace(rowsAltered);\n\n      self.refreshCanvas(true);\n    });\n  };\n\n  /**\n   * @ngdoc function\n   * @name refreshRows\n   * @methodOf ui.grid.class:Grid\n   * @description Refresh the rendered rows on screen?  Note: not functional at present\n   * @returns {promise} promise that is resolved when render completes?\n   *\n   */\n  Grid.prototype.refreshRows = function refreshRows() {\n    var self = this;\n\n    return self.processRowsProcessors(self.rows)\n      .then(function (renderableRows) {\n        self.setVisibleRows(renderableRows);\n\n        self.redrawInPlace();\n\n        self.refreshCanvas( true );\n      });\n  };\n\n  /**\n   * @ngdoc function\n   * @name refreshCanvas\n   * @methodOf ui.grid.class:Grid\n   * @description Builds all styles and recalculates much of the grid sizing\n   * @param {object} buildStyles optional parameter.  Use TBD\n   * @returns {promise} promise that is resolved when the canvas\n   * has been refreshed\n   *\n   */\n  Grid.prototype.refreshCanvas = function(buildStyles) {\n    var self = this;\n\n    if (buildStyles) {\n      self.buildStyles();\n    }\n\n    var p = $q.defer();\n\n    // Get all the header heights\n    var containerHeadersToRecalc = [];\n    for (var containerId in self.renderContainers) {\n      if (self.renderContainers.hasOwnProperty(containerId)) {\n        var container = self.renderContainers[containerId];\n\n        // Skip containers that have no canvasWidth set yet\n        if (container.canvasWidth === null || isNaN(container.canvasWidth)) {\n          continue;\n        }\n\n        if (container.header || container.headerCanvas) {\n          container.explicitHeaderHeight = container.explicitHeaderHeight || null;\n          container.explicitHeaderCanvasHeight = container.explicitHeaderCanvasHeight || null;\n\n          containerHeadersToRecalc.push(container);\n        }\n      }\n    }\n\n    /*\n     *\n     * Here we loop through the headers, measuring each element as well as any header \"canvas\" it has within it.\n     *\n     * If any header is less than the largest header height, it will be resized to that so that we don't have headers\n     * with different heights, which looks like a rendering problem\n     *\n     * We'll do the same thing with the header canvases, and give the header CELLS an explicit height if their canvas\n     * is smaller than the largest canvas height. That was header cells without extra controls like filtering don't\n     * appear shorter than other cells.\n     *\n     */\n    if (containerHeadersToRecalc.length > 0) {\n      // Build the styles without the explicit header heights\n      if (buildStyles) {\n        self.buildStyles();\n      }\n\n      // Putting in a timeout as it's not calculating after the grid element is rendered and filled out\n      $timeout(function() {\n        // var oldHeaderHeight = self.grid.headerHeight;\n        // self.grid.headerHeight = gridUtil.outerElementHeight(self.header);\n\n        var rebuildStyles = false;\n\n        // Get all the header heights\n        var maxHeaderHeight = 0;\n        var maxHeaderCanvasHeight = 0;\n        var i, container;\n        var getHeight = function(oldVal, newVal){\n          if ( oldVal !== newVal){\n            rebuildStyles = true;\n          }\n          return newVal;\n        };\n        for (i = 0; i < containerHeadersToRecalc.length; i++) {\n          container = containerHeadersToRecalc[i];\n\n          // Skip containers that have no canvasWidth set yet\n          if (container.canvasWidth === null || isNaN(container.canvasWidth)) {\n            continue;\n          }\n\n          if (container.header) {\n            var headerHeight = container.headerHeight = getHeight(container.headerHeight, parseInt(gridUtil.outerElementHeight(container.header), 10));\n\n            // Get the \"inner\" header height, that is the height minus the top and bottom borders, if present. We'll use it to make sure all the headers have a consistent height\n            var topBorder = gridUtil.getBorderSize(container.header, 'top');\n            var bottomBorder = gridUtil.getBorderSize(container.header, 'bottom');\n            var innerHeaderHeight = parseInt(headerHeight - topBorder - bottomBorder, 10);\n\n            innerHeaderHeight  = innerHeaderHeight < 0 ? 0 : innerHeaderHeight;\n\n            container.innerHeaderHeight = innerHeaderHeight;\n\n            // If the header doesn't have an explicit height set, save the largest header height for use later\n            //   Explicit header heights are based off of the max we are calculating here. We never want to base the max on something we're setting explicitly\n            if (!container.explicitHeaderHeight && innerHeaderHeight > maxHeaderHeight) {\n              maxHeaderHeight = innerHeaderHeight;\n            }\n          }\n\n          if (container.headerCanvas) {\n            var headerCanvasHeight = container.headerCanvasHeight = getHeight(container.headerCanvasHeight, parseInt(gridUtil.outerElementHeight(container.headerCanvas), 10));\n\n\n            // If the header doesn't have an explicit canvas height, save the largest header canvas height for use later\n            //   Explicit header heights are based off of the max we are calculating here. We never want to base the max on something we're setting explicitly\n            if (!container.explicitHeaderCanvasHeight && headerCanvasHeight > maxHeaderCanvasHeight) {\n              maxHeaderCanvasHeight = headerCanvasHeight;\n            }\n          }\n        }\n\n        // Go through all the headers\n        for (i = 0; i < containerHeadersToRecalc.length; i++) {\n          container = containerHeadersToRecalc[i];\n\n          /* If:\n              1. We have a max header height\n              2. This container has a header height defined\n              3. And either this container has an explicit header height set, OR its header height is less than the max\n\n              then:\n\n              Give this container's header an explicit height so it will line up with the tallest header\n          */\n          if (\n            maxHeaderHeight > 0 && typeof(container.headerHeight) !== 'undefined' && container.headerHeight !== null &&\n            (container.explicitHeaderHeight || container.headerHeight < maxHeaderHeight)\n          ) {\n            container.explicitHeaderHeight = getHeight(container.explicitHeaderHeight, maxHeaderHeight);\n          }\n\n          // Do the same as above except for the header canvas\n          if (\n            maxHeaderCanvasHeight > 0 && typeof(container.headerCanvasHeight) !== 'undefined' && container.headerCanvasHeight !== null &&\n            (container.explicitHeaderCanvasHeight || container.headerCanvasHeight < maxHeaderCanvasHeight)\n          ) {\n            container.explicitHeaderCanvasHeight = getHeight(container.explicitHeaderCanvasHeight, maxHeaderCanvasHeight);\n          }\n        }\n\n        // Rebuild styles if the header height has changed\n        //   The header height is used in body/viewport calculations and those are then used in other styles so we need it to be available\n        if (buildStyles && rebuildStyles) {\n          self.buildStyles();\n        }\n\n        p.resolve();\n      });\n    }\n    else {\n      // Timeout still needs to be here to trigger digest after styles have been rebuilt\n      $timeout(function() {\n        p.resolve();\n      });\n    }\n\n    return p.promise;\n  };\n\n\n  /**\n   * @ngdoc function\n   * @name redrawCanvas\n   * @methodOf ui.grid.class:Grid\n   * @description Redraw the rows and columns based on our current scroll position\n   * @param {boolean} [rowsAdded] Optional to indicate rows are added and the scroll percentage must be recalculated\n   *\n   */\n  Grid.prototype.redrawInPlace = function redrawInPlace(rowsAdded) {\n    // gridUtil.logDebug('redrawInPlace');\n\n    var self = this;\n\n    for (var i in self.renderContainers) {\n      var container = self.renderContainers[i];\n\n      // gridUtil.logDebug('redrawing container', i);\n\n      if (rowsAdded) {\n        container.adjustRows(container.prevScrollTop, null);\n        container.adjustColumns(container.prevScrollLeft, null);\n      }\n      else {\n        container.adjustRows(null, container.prevScrolltopPercentage);\n        container.adjustColumns(null, container.prevScrollleftPercentage);\n      }\n    }\n  };\n\n    /**\n     * @ngdoc function\n     * @name hasLeftContainerColumns\n     * @methodOf ui.grid.class:Grid\n     * @description returns true if leftContainer has columns\n     */\n    Grid.prototype.hasLeftContainerColumns = function () {\n      return this.hasLeftContainer() && this.renderContainers.left.renderedColumns.length > 0;\n    };\n\n    /**\n     * @ngdoc function\n     * @name hasRightContainerColumns\n     * @methodOf ui.grid.class:Grid\n     * @description returns true if rightContainer has columns\n     */\n    Grid.prototype.hasRightContainerColumns = function () {\n      return this.hasRightContainer() && this.renderContainers.right.renderedColumns.length > 0;\n    };\n\n    /**\n     * @ngdoc method\n     * @methodOf  ui.grid.class:Grid\n     * @name scrollToIfNecessary\n     * @description Scrolls the grid to make a certain row and column combo visible,\n     *   in the case that it is not completely visible on the screen already.\n     * @param {GridRow} gridRow row to make visible\n     * @param {GridCol} gridCol column to make visible\n     * @returns {promise} a promise that is resolved when scrolling is complete\n     */\n    Grid.prototype.scrollToIfNecessary = function (gridRow, gridCol) {\n      var self = this;\n\n      var scrollEvent = new ScrollEvent(self, 'uiGrid.scrollToIfNecessary');\n\n      // Alias the visible row and column caches\n      var visRowCache = self.renderContainers.body.visibleRowCache;\n      var visColCache = self.renderContainers.body.visibleColumnCache;\n\n      /*-- Get the top, left, right, and bottom \"scrolled\" edges of the grid --*/\n\n      // The top boundary is the current Y scroll position PLUS the header height, because the header can obscure rows when the grid is scrolled downwards\n      var topBound = self.renderContainers.body.prevScrollTop + self.headerHeight;\n\n      // Don't the let top boundary be less than 0\n      topBound = (topBound < 0) ? 0 : topBound;\n\n      // The left boundary is the current X scroll position\n      var leftBound = self.renderContainers.body.prevScrollLeft;\n\n      // The bottom boundary is the current Y scroll position, plus the height of the grid, but minus the header height.\n      //   Basically this is the viewport height added on to the scroll position\n      var bottomBound = self.renderContainers.body.prevScrollTop + self.gridHeight - self.renderContainers.body.headerHeight - self.footerHeight -  self.scrollbarWidth;\n\n      // If there's a horizontal scrollbar, remove its height from the bottom boundary, otherwise we'll be letting it obscure rows\n      //if (self.horizontalScrollbarHeight) {\n      //  bottomBound = bottomBound - self.horizontalScrollbarHeight;\n      //}\n\n      // The right position is the current X scroll position minus the grid width\n      var rightBound = self.renderContainers.body.prevScrollLeft + Math.ceil(self.renderContainers.body.getViewportWidth());\n\n      // If there's a vertical scrollbar, subtract it from the right boundary or we'll allow it to obscure cells\n      //if (self.verticalScrollbarWidth) {\n      //  rightBound = rightBound - self.verticalScrollbarWidth;\n      //}\n\n      // We were given a row to scroll to\n      if (gridRow !== null) {\n        // This is the index of the row we want to scroll to, within the list of rows that can be visible\n        var seekRowIndex = visRowCache.indexOf(gridRow);\n\n        // Total vertical scroll length of the grid\n        var scrollLength = (self.renderContainers.body.getCanvasHeight() - self.renderContainers.body.getViewportHeight());\n\n        // Add the height of the native horizontal scrollbar to the scroll length, if it's there. Otherwise it will mask over the final row\n        //if (self.horizontalScrollbarHeight && self.horizontalScrollbarHeight > 0) {\n        //  scrollLength = scrollLength + self.horizontalScrollbarHeight;\n        //}\n\n        // This is the minimum amount of pixels we need to scroll vertical in order to see this row.\n        var pixelsToSeeRow = (seekRowIndex * self.options.rowHeight + self.headerHeight);\n\n        // Don't let the pixels required to see the row be less than zero\n        pixelsToSeeRow = (pixelsToSeeRow < 0) ? 0 : pixelsToSeeRow;\n\n        var scrollPixels, percentage;\n\n        // If the scroll position we need to see the row is LESS than the top boundary, i.e. obscured above the top of the self...\n        if (pixelsToSeeRow < topBound) {\n          // Get the different between the top boundary and the required scroll position and subtract it from the current scroll position\\\n          //   to get the full position we need\n          scrollPixels = self.renderContainers.body.prevScrollTop - (topBound - pixelsToSeeRow);\n\n          // Turn the scroll position into a percentage and make it an argument for a scroll event\n          percentage = scrollPixels / scrollLength;\n          scrollEvent.y = { percentage: percentage  };\n        }\n        // Otherwise if the scroll position we need to see the row is MORE than the bottom boundary, i.e. obscured below the bottom of the self...\n        else if (pixelsToSeeRow > bottomBound) {\n          // Get the different between the bottom boundary and the required scroll position and add it to the current scroll position\n          //   to get the full position we need\n          scrollPixels = pixelsToSeeRow - bottomBound + self.renderContainers.body.prevScrollTop;\n\n          // Turn the scroll position into a percentage and make it an argument for a scroll event\n          percentage = scrollPixels / scrollLength;\n          scrollEvent.y = { percentage: percentage  };\n        }\n      }\n\n      // We were given a column to scroll to\n      if (gridCol !== null) {\n        // This is the index of the column we want to scroll to, within the list of columns that can be visible\n        var seekColumnIndex = visColCache.indexOf(gridCol);\n\n        // Total horizontal scroll length of the grid\n        var horizScrollLength = (self.renderContainers.body.getCanvasWidth() - self.renderContainers.body.getViewportWidth());\n\n        // This is the minimum amount of pixels we need to scroll horizontal in order to see this column\n        var columnLeftEdge = 0;\n        for (var i = 0; i < seekColumnIndex; i++) {\n          var col = visColCache[i];\n          columnLeftEdge += col.drawnWidth;\n        }\n        columnLeftEdge = (columnLeftEdge < 0) ? 0 : columnLeftEdge;\n\n        var columnRightEdge = columnLeftEdge + gridCol.drawnWidth;\n\n        // Don't let the pixels required to see the column be less than zero\n        columnRightEdge = (columnRightEdge < 0) ? 0 : columnRightEdge;\n\n        var horizScrollPixels, horizPercentage;\n\n        // If the scroll position we need to see the column is LESS than the left boundary, i.e. obscured before the left of the self...\n        if (columnLeftEdge < leftBound) {\n          // Get the different between the left boundary and the required scroll position and subtract it from the current scroll position\\\n          //   to get the full position we need\n          horizScrollPixels = self.renderContainers.body.prevScrollLeft - (leftBound - columnLeftEdge);\n\n          // Turn the scroll position into a percentage and make it an argument for a scroll event\n          horizPercentage = horizScrollPixels / horizScrollLength;\n          horizPercentage = (horizPercentage > 1) ? 1 : horizPercentage;\n          scrollEvent.x = { percentage: horizPercentage  };\n        }\n        // Otherwise if the scroll position we need to see the column is MORE than the right boundary, i.e. obscured after the right of the self...\n        else if (columnRightEdge > rightBound) {\n          // Get the different between the right boundary and the required scroll position and add it to the current scroll position\n          //   to get the full position we need\n          horizScrollPixels = columnRightEdge - rightBound + self.renderContainers.body.prevScrollLeft;\n\n          // Turn the scroll position into a percentage and make it an argument for a scroll event\n          horizPercentage = horizScrollPixels / horizScrollLength;\n          horizPercentage = (horizPercentage > 1) ? 1 : horizPercentage;\n          scrollEvent.x = { percentage: horizPercentage  };\n        }\n      }\n\n      var deferred = $q.defer();\n\n      // If we need to scroll on either the x or y axes, fire a scroll event\n      if (scrollEvent.y || scrollEvent.x) {\n        scrollEvent.withDelay = false;\n        self.scrollContainers('',scrollEvent);\n        var dereg = self.api.core.on.scrollEnd(null,function() {\n          deferred.resolve(scrollEvent);\n          dereg();\n        });\n      }\n      else {\n        deferred.resolve();\n      }\n\n      return deferred.promise;\n    };\n\n    /**\n     * @ngdoc method\n     * @methodOf ui.grid.class:Grid\n     * @name scrollTo\n     * @description Scroll the grid such that the specified\n     * row and column is in view\n     * @param {object} rowEntity gridOptions.data[] array instance to make visible\n     * @param {object} colDef to make visible\n     * @returns {promise} a promise that is resolved after any scrolling is finished\n     */\n    Grid.prototype.scrollTo = function (rowEntity, colDef) {\n      var gridRow = null, gridCol = null;\n\n      if (rowEntity !== null && typeof(rowEntity) !== 'undefined' ) {\n        gridRow = this.getRow(rowEntity);\n      }\n\n      if (colDef !== null && typeof(colDef) !== 'undefined' ) {\n        gridCol = this.getColumn(colDef.name ? colDef.name : colDef.field);\n      }\n      return this.scrollToIfNecessary(gridRow, gridCol);\n    };\n\n  /**\n   * @ngdoc function\n   * @name clearAllFilters\n   * @methodOf ui.grid.class:Grid\n   * @description Clears all filters and optionally refreshes the visible rows.\n   * @param {object} refreshRows Defaults to true.\n   * @param {object} clearConditions Defaults to false.\n   * @param {object} clearFlags Defaults to false.\n   * @returns {promise} If `refreshRows` is true, returns a promise of the rows refreshing.\n   */\n  Grid.prototype.clearAllFilters = function clearAllFilters(refreshRows, clearConditions, clearFlags) {\n    // Default `refreshRows` to true because it will be the most commonly desired behaviour.\n    if (refreshRows === undefined) {\n      refreshRows = true;\n    }\n    if (clearConditions === undefined) {\n      clearConditions = false;\n    }\n    if (clearFlags === undefined) {\n      clearFlags = false;\n    }\n\n    this.columns.forEach(function(column) {\n      column.filters.forEach(function(filter) {\n        filter.term = undefined;\n\n        if (clearConditions) {\n          filter.condition = undefined;\n        }\n\n        if (clearFlags) {\n          filter.flags = undefined;\n        }\n      });\n    });\n\n    if (refreshRows) {\n      return this.refreshRows();\n    }\n  };\n\n\n      // Blatantly stolen from Angular as it isn't exposed (yet? 2.0?)\n  function RowHashMap() {}\n\n  RowHashMap.prototype = {\n    /**\n     * Store key value pair\n     * @param key key to store can be any type\n     * @param value value to store can be any type\n     */\n    put: function(key, value) {\n      this[this.grid.options.rowIdentity(key)] = value;\n    },\n\n    /**\n     * @param key\n     * @returns {Object} the value for the key\n     */\n    get: function(key) {\n      return this[this.grid.options.rowIdentity(key)];\n    },\n\n    /**\n     * Remove the key/value pair\n     * @param key\n     */\n    remove: function(key) {\n      var value = this[key = this.grid.options.rowIdentity(key)];\n      delete this[key];\n      return value;\n    }\n  };\n\n\n\n  return Grid;\n\n}]);\n\n})();\n\n(function () {\n\n  angular.module('ui.grid')\n    .factory('GridApi', ['$q', '$rootScope', 'gridUtil', 'uiGridConstants', 'GridRow', 'uiGridGridMenuService',\n      function ($q, $rootScope, gridUtil, uiGridConstants, GridRow, uiGridGridMenuService) {\n        /**\n         * @ngdoc function\n         * @name ui.grid.class:GridApi\n         * @description GridApi provides the ability to register public methods events inside the grid and allow\n         * for other components to use the api via featureName.raise.methodName and featureName.on.eventName(function(args){}.\n         * <br/>\n         * To listen to events, you must add a callback to gridOptions.onRegisterApi\n         * <pre>\n         *   $scope.gridOptions.onRegisterApi = function(gridApi){\n         *      gridApi.cellNav.on.navigate($scope,function(newRowCol, oldRowCol){\n         *          $log.log('navigation event');\n         *      });\n         *   };\n         * </pre>\n         * @param {object} grid grid that owns api\n         */\n        var GridApi = function GridApi(grid) {\n          this.grid = grid;\n          this.listeners = [];\n\n          /**\n           * @ngdoc function\n           * @name renderingComplete\n           * @methodOf  ui.grid.core.api:PublicApi\n           * @description Rendering is complete, called at the same\n           * time as `onRegisterApi`, but provides a way to obtain\n           * that same event within features without stopping end\n           * users from getting at the onRegisterApi method.\n           *\n           * Included in gridApi so that it's always there - otherwise\n           * there is still a timing problem with when a feature can\n           * call this.\n           *\n           * @param {GridApi} gridApi the grid api, as normally\n           * returned in the onRegisterApi method\n           *\n           * @example\n           * <pre>\n           *      gridApi.core.on.renderingComplete( grid );\n           * </pre>\n           */\n          this.registerEvent( 'core', 'renderingComplete' );\n\n          /**\n           * @ngdoc event\n           * @name filterChanged\n           * @eventOf  ui.grid.core.api:PublicApi\n           * @description  is raised after the filter is changed.  The nature\n           * of the watch expression doesn't allow notification of what changed,\n           * so the receiver of this event will need to re-extract the filter\n           * conditions from the columns.\n           *\n           */\n          this.registerEvent( 'core', 'filterChanged' );\n\n          /**\n           * @ngdoc function\n           * @name setRowInvisible\n           * @methodOf  ui.grid.core.api:PublicApi\n           * @description Sets an override on the row to make it always invisible,\n           * which will override any filtering or other visibility calculations.\n           * If the row is currently visible then sets it to invisible and calls\n           * both grid refresh and emits the rowsVisibleChanged event\n           * @param {object} rowEntity gridOptions.data[] array instance\n           */\n          this.registerMethod( 'core', 'setRowInvisible', GridRow.prototype.setRowInvisible );\n\n          /**\n           * @ngdoc function\n           * @name clearRowInvisible\n           * @methodOf  ui.grid.core.api:PublicApi\n           * @description Clears any override on visibility for the row so that it returns to\n           * using normal filtering and other visibility calculations.\n           * If the row is currently invisible then sets it to visible and calls\n           * both grid refresh and emits the rowsVisibleChanged event\n           * TODO: if a filter is active then we can't just set it to visible?\n           * @param {object} rowEntity gridOptions.data[] array instance\n           */\n          this.registerMethod( 'core', 'clearRowInvisible', GridRow.prototype.clearRowInvisible );\n\n          /**\n           * @ngdoc function\n           * @name getVisibleRows\n           * @methodOf  ui.grid.core.api:PublicApi\n           * @description Returns all visible rows\n           * @param {Grid} grid the grid you want to get visible rows from\n           * @returns {array} an array of gridRow\n           */\n          this.registerMethod( 'core', 'getVisibleRows', this.grid.getVisibleRows );\n\n          /**\n           * @ngdoc event\n           * @name rowsVisibleChanged\n           * @eventOf  ui.grid.core.api:PublicApi\n           * @description  is raised after the rows that are visible\n           * change.  The filtering is zero-based, so it isn't possible\n           * to say which rows changed (unlike in the selection feature).\n           * We can plausibly know which row was changed when setRowInvisible\n           * is called, but in that situation the user already knows which row\n           * they changed.  When a filter runs we don't know what changed,\n           * and that is the one that would have been useful.\n           *\n           */\n          this.registerEvent( 'core', 'rowsVisibleChanged' );\n\n          /**\n           * @ngdoc event\n           * @name rowsRendered\n           * @eventOf  ui.grid.core.api:PublicApi\n           * @description  is raised after the cache of visible rows is changed.\n           */\n          this.registerEvent( 'core', 'rowsRendered' );\n\n\n          /**\n           * @ngdoc event\n           * @name scrollBegin\n           * @eventOf  ui.grid.core.api:PublicApi\n           * @description  is raised when scroll begins.  Is throttled, so won't be raised too frequently\n           */\n          this.registerEvent( 'core', 'scrollBegin' );\n\n          /**\n           * @ngdoc event\n           * @name scrollEnd\n           * @eventOf  ui.grid.core.api:PublicApi\n           * @description  is raised when scroll has finished.  Is throttled, so won't be raised too frequently\n           */\n          this.registerEvent( 'core', 'scrollEnd' );\n\n          /**\n           * @ngdoc event\n           * @name canvasHeightChanged\n           * @eventOf  ui.grid.core.api:PublicApi\n           * @description  is raised when the canvas height has changed\n           * <br/>\n           * arguments: oldHeight, newHeight\n           */\n          this.registerEvent( 'core', 'canvasHeightChanged');\n\n          /**\n           * @ngdoc event\n           * @name gridDimensionChanged\n           * @eventOf  ui.grid.core.api:PublicApi\n           * @description  is raised when the grid dimensions have changed (when autoResize is on)\n           * <br/>\n           * arguments: oldGridHeight, oldGridWidth, newGridHeight, newGridWidth\n           */\n          this.registerEvent( 'core', 'gridDimensionChanged');\n        };\n\n        /**\n         * @ngdoc function\n         * @name ui.grid.class:suppressEvents\n         * @methodOf ui.grid.class:GridApi\n         * @description Used to execute a function while disabling the specified event listeners.\n         * Disables the listenerFunctions, executes the callbackFn, and then enables\n         * the listenerFunctions again\n         * @param {object} listenerFuncs listenerFunc or array of listenerFuncs to suppress. These must be the same\n         * functions that were used in the .on.eventName method\n         * @param {object} callBackFn function to execute\n         * @example\n         * <pre>\n         *    var navigate = function (newRowCol, oldRowCol){\n         *       //do something on navigate\n         *    }\n         *\n         *    gridApi.cellNav.on.navigate(scope,navigate);\n         *\n         *\n         *    //call the scrollTo event and suppress our navigate listener\n         *    //scrollTo will still raise the event for other listeners\n         *    gridApi.suppressEvents(navigate, function(){\n         *       gridApi.cellNav.scrollTo(aRow, aCol);\n         *    });\n         *\n         * </pre>\n         */\n        GridApi.prototype.suppressEvents = function (listenerFuncs, callBackFn) {\n          var self = this;\n          var listeners = angular.isArray(listenerFuncs) ? listenerFuncs : [listenerFuncs];\n\n          //find all registered listeners\n          var foundListeners = self.listeners.filter(function(listener) {\n            return listeners.some(function(l) {\n              return listener.handler === l;\n            });\n          });\n\n          //deregister all the listeners\n          foundListeners.forEach(function(l){\n            l.dereg();\n          });\n\n          callBackFn();\n\n          //reregister all the listeners\n          foundListeners.forEach(function(l){\n              l.dereg = registerEventWithAngular(l.eventId, l.handler, self.grid, l._this);\n          });\n\n        };\n\n        /**\n         * @ngdoc function\n         * @name registerEvent\n         * @methodOf ui.grid.class:GridApi\n         * @description Registers a new event for the given feature.  The event will get a\n         * .raise and .on prepended to it\n         * <br>\n         * .raise.eventName() - takes no arguments\n         * <br/>\n         * <br/>\n         * .on.eventName(scope, callBackFn, _this)\n         * <br/>\n         * scope - a scope reference to add a deregister call to the scopes .$on('destroy').  Scope is optional and can be a null value,\n         * but in this case you must deregister it yourself via the returned deregister function\n         * <br/>\n         * callBackFn - The function to call\n         * <br/>\n         * _this - optional this context variable for callbackFn. If omitted, grid.api will be used for the context\n         * <br/>\n         * .on.eventName returns a dereg funtion that will remove the listener.  It's not necessary to use it as the listener\n         * will be removed when the scope is destroyed.\n         * @param {string} featureName name of the feature that raises the event\n         * @param {string} eventName  name of the event\n         */\n        GridApi.prototype.registerEvent = function (featureName, eventName) {\n          var self = this;\n          if (!self[featureName]) {\n            self[featureName] = {};\n          }\n\n          var feature = self[featureName];\n          if (!feature.on) {\n            feature.on = {};\n            feature.raise = {};\n          }\n\n          var eventId = self.grid.id + featureName + eventName;\n\n          // gridUtil.logDebug('Creating raise event method ' + featureName + '.raise.' + eventName);\n          feature.raise[eventName] = function () {\n            $rootScope.$emit.apply($rootScope, [eventId].concat(Array.prototype.slice.call(arguments)));\n          };\n\n          // gridUtil.logDebug('Creating on event method ' + featureName + '.on.' + eventName);\n          feature.on[eventName] = function (scope, handler, _this) {\n            if ( scope !== null && typeof(scope.$on) === 'undefined' ){\n              gridUtil.logError('asked to listen on ' + featureName + '.on.' + eventName + ' but scope wasn\\'t passed in the input parameters.  It is legitimate to pass null, but you\\'ve passed something else, so you probably forgot to provide scope rather than did it deliberately, not registering');\n              return;\n            }\n            var deregAngularOn = registerEventWithAngular(eventId, handler, self.grid, _this);\n\n            //track our listener so we can turn off and on\n            var listener = {handler: handler, dereg: deregAngularOn, eventId: eventId, scope: scope, _this:_this};\n            self.listeners.push(listener);\n\n            var removeListener = function(){\n              listener.dereg();\n              var index = self.listeners.indexOf(listener);\n              self.listeners.splice(index,1);\n            };\n\n            //destroy tracking when scope is destroyed\n            if (scope) {\n              scope.$on('$destroy', function() {\n                removeListener();\n              });\n            }\n\n\n            return removeListener;\n          };\n        };\n\n        function registerEventWithAngular(eventId, handler, grid, _this) {\n          return $rootScope.$on(eventId, function (event) {\n            var args = Array.prototype.slice.call(arguments);\n            args.splice(0, 1); //remove evt argument\n            handler.apply(_this ? _this : grid.api, args);\n          });\n        }\n\n        /**\n         * @ngdoc function\n         * @name registerEventsFromObject\n         * @methodOf ui.grid.class:GridApi\n         * @description Registers features and events from a simple objectMap.\n         * eventObjectMap must be in this format (multiple features allowed)\n         * <pre>\n         * {featureName:\n         *        {\n         *          eventNameOne:function(args){},\n         *          eventNameTwo:function(args){}\n         *        }\n         *  }\n         * </pre>\n         * @param {object} eventObjectMap map of feature/event names\n         */\n        GridApi.prototype.registerEventsFromObject = function (eventObjectMap) {\n          var self = this;\n          var features = [];\n          angular.forEach(eventObjectMap, function (featProp, featPropName) {\n            var feature = {name: featPropName, events: []};\n            angular.forEach(featProp, function (prop, propName) {\n              feature.events.push(propName);\n            });\n            features.push(feature);\n          });\n\n          features.forEach(function (feature) {\n            feature.events.forEach(function (event) {\n              self.registerEvent(feature.name, event);\n            });\n          });\n\n        };\n\n        /**\n         * @ngdoc function\n         * @name registerMethod\n         * @methodOf ui.grid.class:GridApi\n         * @description Registers a new event for the given feature\n         * @param {string} featureName name of the feature\n         * @param {string} methodName  name of the method\n         * @param {object} callBackFn function to execute\n         * @param {object} _this binds callBackFn 'this' to _this.  Defaults to gridApi.grid\n         */\n        GridApi.prototype.registerMethod = function (featureName, methodName, callBackFn, _this) {\n          if (!this[featureName]) {\n            this[featureName] = {};\n          }\n\n          var feature = this[featureName];\n\n          feature[methodName] = gridUtil.createBoundedWrapper(_this || this.grid, callBackFn);\n        };\n\n        /**\n         * @ngdoc function\n         * @name registerMethodsFromObject\n         * @methodOf ui.grid.class:GridApi\n         * @description Registers features and methods from a simple objectMap.\n         * eventObjectMap must be in this format (multiple features allowed)\n         * <br>\n         * {featureName:\n         *        {\n         *          methodNameOne:function(args){},\n         *          methodNameTwo:function(args){}\n         *        }\n         * @param {object} eventObjectMap map of feature/event names\n         * @param {object} _this binds this to _this for all functions.  Defaults to gridApi.grid\n         */\n        GridApi.prototype.registerMethodsFromObject = function (methodMap, _this) {\n          var self = this;\n          var features = [];\n          angular.forEach(methodMap, function (featProp, featPropName) {\n            var feature = {name: featPropName, methods: []};\n            angular.forEach(featProp, function (prop, propName) {\n              feature.methods.push({name: propName, fn: prop});\n            });\n            features.push(feature);\n          });\n\n          features.forEach(function (feature) {\n            feature.methods.forEach(function (method) {\n              self.registerMethod(feature.name, method.name, method.fn, _this);\n            });\n          });\n\n        };\n\n        return GridApi;\n\n      }]);\n\n})();\n\n(function(){\n\nangular.module('ui.grid')\n.factory('GridColumn', ['gridUtil', 'uiGridConstants', 'i18nService', function(gridUtil, uiGridConstants, i18nService) {\n\n  /**\n   * ******************************************************************************************\n   * PaulL1: Ugly hack here in documentation.  These properties are clearly properties of GridColumn,\n   * and need to be noted as such for those extending and building ui-grid itself.\n   * However, from an end-developer perspective, they interact with all these through columnDefs,\n   * and they really need to be documented there.  I feel like they're relatively static, and\n   * I can't find an elegant way for ngDoc to reference to both....so I've duplicated each\n   * comment block.  Ugh.\n   *\n   */\n\n  /**\n   * @ngdoc property\n   * @name name\n   * @propertyOf ui.grid.class:GridColumn\n   * @description (mandatory) each column should have a name, although for backward\n   * compatibility with 2.x name can be omitted if field is present\n   *\n   */\n\n  /**\n   * @ngdoc property\n   * @name name\n   * @propertyOf ui.grid.class:GridOptions.columnDef\n   * @description (mandatory) each column should have a name, although for backward\n   * compatibility with 2.x name can be omitted if field is present\n   *\n   */\n\n  /**\n   * @ngdoc property\n   * @name displayName\n   * @propertyOf ui.grid.class:GridColumn\n   * @description Column name that will be shown in the header.  If displayName is not\n   * provided then one is generated using the name.\n   *\n   */\n\n  /**\n   * @ngdoc property\n   * @name displayName\n   * @propertyOf ui.grid.class:GridOptions.columnDef\n   * @description Column name that will be shown in the header.  If displayName is not\n   * provided then one is generated using the name.\n   *\n   */\n\n  /**\n   * @ngdoc property\n   * @name field\n   * @propertyOf ui.grid.class:GridColumn\n   * @description field must be provided if you wish to bind to a\n   * property in the data source.  Should be an angular expression that evaluates against grid.options.data\n   * array element.  Can be a complex expression: <code>employee.address.city</code>, or can be a function: <code>employee.getFullAddress()</code>.\n   * See the angular docs on binding expressions.\n   *\n   */\n\n  /**\n   * @ngdoc property\n   * @name field\n   * @propertyOf ui.grid.class:GridOptions.columnDef\n   * @description field must be provided if you wish to bind to a\n   * property in the data source.  Should be an angular expression that evaluates against grid.options.data\n   * array element.  Can be a complex expression: <code>employee.address.city</code>, or can be a function: <code>employee.getFullAddress()</code>.    * See the angular docs on binding expressions.    *\n   */\n\n  /**\n   * @ngdoc property\n   * @name filter\n   * @propertyOf ui.grid.class:GridColumn\n   * @description Filter on this column.\n   *\n   * Available built-in conditions and types are listed under {@link jui.grid.service:uiGridConstants#properties_filter uiGridOptions.filter}\n   * @example\n   * <pre>{ term: 'text', condition: uiGridConstants.filter.STARTS_WITH, placeholder: 'type to filter...', ariaLabel: 'Filter for text', flags: { caseSensitive: false }, type: uiGridConstants.filter.SELECT, [ { value: 1, label: 'male' }, { value: 2, label: 'female' } ] }</pre>\n   *\n   */\n\n  /**\n   * @ngdoc object\n   * @name ui.grid.class:GridColumn\n   * @description Represents the viewModel for each column.  Any state or methods needed for a Grid Column\n   * are defined on this prototype\n   * @param {ColumnDef} colDef the column def to associate with this column\n   * @param {number} uid the unique and immutable uid we'd like to allocate to this column\n   * @param {Grid} grid the grid we'd like to create this column in\n   */\n  function GridColumn(colDef, uid, grid) {\n    var self = this;\n\n    self.grid = grid;\n    self.uid = uid;\n\n    self.updateColumnDef(colDef, true);\n\n    self.aggregationValue = undefined;\n\n    // The footer cell registers to listen for the rowsRendered event, and calls this.  Needed to be\n    // in something with a scope so that the dereg would get called\n    self.updateAggregationValue = function() {\n\n     // gridUtil.logDebug('getAggregationValue for Column ' + self.colDef.name);\n\n      /**\n       * @ngdoc property\n       * @name aggregationType\n       * @propertyOf ui.grid.class:GridOptions.columnDef\n       * @description The aggregation that you'd like to show in the columnFooter for this\n       * column.  Valid values are in\n       * {@link ui.grid.service:uiGridConstants#properties_aggregationTypes uiGridConstants.aggregationTypes},\n       * and currently include `uiGridConstants.aggregationTypes.count`,\n       * `uiGridConstants.aggregationTypes.sum`, `uiGridConstants.aggregationTypes.avg`, `uiGridConstants.aggregationTypes.min`,\n       * `uiGridConstants.aggregationTypes.max`.\n       *\n       * You can also provide a function as the aggregation type, in this case your function needs to accept the full\n       * set of visible rows, and return a value that should be shown\n       */\n      if (!self.aggregationType) {\n        self.aggregationValue = undefined;\n        return;\n      }\n\n      var result = 0;\n      var visibleRows = self.grid.getVisibleRows();\n\n      var cellValues = function(){\n        var values = [];\n        visibleRows.forEach(function (row) {\n          var cellValue = self.grid.getCellValue(row, self);\n          var cellNumber = Number(cellValue);\n          if (!isNaN(cellNumber)) {\n            values.push(cellNumber);\n          }\n        });\n        return values;\n      };\n\n      if (angular.isFunction(self.aggregationType)) {\n        self.aggregationValue = self.aggregationType(visibleRows, self);\n      }\n      else if (self.aggregationType === uiGridConstants.aggregationTypes.count) {\n        self.aggregationValue = self.grid.getVisibleRowCount();\n      }\n      else if (self.aggregationType === uiGridConstants.aggregationTypes.sum) {\n        cellValues().forEach(function (value) {\n          result += value;\n        });\n        self.aggregationValue = result;\n      }\n      else if (self.aggregationType === uiGridConstants.aggregationTypes.avg) {\n        cellValues().forEach(function (value) {\n          result += value;\n        });\n        result = result / cellValues().length;\n        self.aggregationValue = result;\n      }\n      else if (self.aggregationType === uiGridConstants.aggregationTypes.min) {\n        self.aggregationValue = Math.min.apply(null, cellValues());\n      }\n      else if (self.aggregationType === uiGridConstants.aggregationTypes.max) {\n        self.aggregationValue = Math.max.apply(null, cellValues());\n      }\n      else {\n        self.aggregationValue = '\\u00A0';\n      }\n    };\n\n//     var throttledUpdateAggregationValue = gridUtil.throttle(updateAggregationValue, self.grid.options.aggregationCalcThrottle, { trailing: true, context: self.name });\n\n    /**\n     * @ngdoc function\n     * @name getAggregationValue\n     * @methodOf ui.grid.class:GridColumn\n     * @description gets the aggregation value based on the aggregation type for this column.\n     * Debounced using scrollDebounce option setting\n     */\n    this.getAggregationValue =  function() {\n//      if (!self.grid.isScrollingVertically && !self.grid.isScrollingHorizontally) {\n//        throttledUpdateAggregationValue();\n//      }\n\n      return self.aggregationValue;\n    };\n  }\n\n  /**\n   * @ngdoc function\n   * @name hideColumn\n   * @methodOf ui.grid.class:GridColumn\n   * @description Hides the column by setting colDef.visible = false\n   */\n  GridColumn.prototype.hideColumn = function() {\n    this.colDef.visible = false;\n  };\n  \n\n  /**\n   * @ngdoc method\n   * @methodOf ui.grid.class:GridColumn\n   * @name setPropertyOrDefault\n   * @description Sets a property on the column using the passed in columnDef, and\n   * setting the defaultValue if the value cannot be found on the colDef\n   * @param {ColumnDef} colDef the column def to look in for the property value\n   * @param {string} propName the property name we'd like to set\n   * @param {object} defaultValue the value to use if the colDef doesn't provide the setting\n   */\n  GridColumn.prototype.setPropertyOrDefault = function (colDef, propName, defaultValue) {\n    var self = this;\n\n    // Use the column definition filter if we were passed it\n    if (typeof(colDef[propName]) !== 'undefined' && colDef[propName]) {\n      self[propName] = colDef[propName];\n    }\n    // Otherwise use our own if it's set\n    else if (typeof(self[propName]) !== 'undefined') {\n      self[propName] = self[propName];\n    }\n    // Default to empty object for the filter\n    else {\n      self[propName] = defaultValue ? defaultValue : {};\n    }\n  };\n\n\n\n  /**\n   * @ngdoc property\n   * @name width\n   * @propertyOf ui.grid.class:GridOptions.columnDef\n   * @description sets the column width.  Can be either\n   * a number or a percentage, or an * for auto.\n   * @example\n   * <pre>  $scope.gridOptions.columnDefs = [ { field: 'field1', width: 100},\n   *                                          { field: 'field2', width: '20%'},\n   *                                          { field: 'field3', width: '*' }]; </pre>\n   *\n   */\n\n  /**\n   * @ngdoc property\n   * @name minWidth\n   * @propertyOf ui.grid.class:GridOptions.columnDef\n   * @description sets the minimum column width.  Should be a number.\n   * @example\n   * <pre>  $scope.gridOptions.columnDefs = [ { field: 'field1', minWidth: 100}]; </pre>\n   *\n   */\n\n  /**\n   * @ngdoc property\n   * @name maxWidth\n   * @propertyOf ui.grid.class:GridOptions.columnDef\n   * @description sets the maximum column width.  Should be a number.\n   * @example\n   * <pre>  $scope.gridOptions.columnDefs = [ { field: 'field1', maxWidth: 100}]; </pre>\n   *\n   */\n\n  /**\n   * @ngdoc property\n   * @name visible\n   * @propertyOf ui.grid.class:GridOptions.columnDef\n   * @description sets whether or not the column is visible\n   * </br>Default is true\n   * @example\n   * <pre>  $scope.gridOptions.columnDefs = [\n   *     { field: 'field1', visible: true},\n   *     { field: 'field2', visible: false }\n   *   ]; </pre>\n   *\n   */\n\n /**\n  * @ngdoc property\n  * @name sort\n  * @propertyOf ui.grid.class:GridOptions.columnDef\n  * @description An object of sort information, attributes are:\n  *\n  * - direction: values are {@link ui.grid.service:uiGridConstants#properties_ASC uiGridConstants.ASC}\n  *  or {@link ui.grid.service:uiGridConstants#properties_DESC uiGridConstants.DESC}\n  * - ignoreSort: if set to true this sort is ignored (used by tree to manipulate the sort functionality)\n  * - priority: says what order to sort the columns in (lower priority gets sorted first).\n  * @example\n  * <pre>\n  *   $scope.gridOptions.columnDefs = [{\n  *     field: 'field1',\n  *     sort: {\n  *       direction: uiGridConstants.ASC,\n  *       ignoreSort: true,\n  *       priority: 0\n  *      }\n  *   }];\n  * </pre>\n  */\n\n\n  /**\n   * @ngdoc property\n   * @name sortingAlgorithm\n   * @propertyOf ui.grid.class:GridOptions.columnDef\n   * @description Algorithm to use for sorting this column. Takes 'a' and 'b' parameters\n   * like any normal sorting function with additional 'rowA', 'rowB', and 'direction' parameters\n   * that are the row objects and the current direction of the sort respectively.\n   *\n   */\n\n  /**\n   * @ngdoc array\n   * @name filters\n   * @propertyOf ui.grid.class:GridOptions.columnDef\n   * @description Specify multiple filter fields.\n   * @example\n   * <pre>$scope.gridOptions.columnDefs = [\n   *   {\n   *     field: 'field1', filters: [\n   *       {\n   *         term: 'aa',\n   *         condition: uiGridConstants.filter.STARTS_WITH,\n   *         placeholder: 'starts with...',\n   *         ariaLabel: 'Filter for field1',\n   *         flags: { caseSensitive: false },\n   *         type: uiGridConstants.filter.SELECT,\n   *         selectOptions: [ { value: 1, label: 'male' }, { value: 2, label: 'female' } ]\n   *       },\n   *       {\n   *         condition: uiGridConstants.filter.ENDS_WITH,\n   *         placeholder: 'ends with...'\n   *       }\n   *     ]\n   *   }\n   * ]; </pre>\n   *\n   *\n   */\n\n  /**\n   * @ngdoc array\n   * @name filters\n   * @propertyOf ui.grid.class:GridColumn\n   * @description Filters for this column. Includes 'term' property bound to filter input elements.\n   * @example\n   * <pre>[\n   *   {\n   *     term: 'foo', // ngModel for <input>\n   *     condition: uiGridConstants.filter.STARTS_WITH,\n   *     placeholder: 'starts with...',\n   *     ariaLabel: 'Filter for foo',\n   *     flags: { caseSensitive: false },\n   *     type: uiGridConstants.filter.SELECT,\n   *     selectOptions: [ { value: 1, label: 'male' }, { value: 2, label: 'female' } ]\n   *   },\n   *   {\n   *     term: 'baz',\n   *     condition: uiGridConstants.filter.ENDS_WITH,\n   *     placeholder: 'ends with...'\n   *   }\n   * ] </pre>\n   *\n   *\n   */\n\n  /**\n   * @ngdoc array\n   * @name menuItems\n   * @propertyOf ui.grid.class:GridOptions.columnDef\n   * @description used to add menu items to a column.  Refer to the tutorial on this\n   * functionality.  A number of settings are supported:\n   *\n   * - title: controls the title that is displayed in the menu\n   * - icon: the icon shown alongside that title\n   * - action: the method to call when the menu is clicked\n   * - shown: a function to evaluate to determine whether or not to show the item\n   * - active: a function to evaluate to determine whether or not the item is currently selected\n   * - context: context to pass to the action function, available in this.context in your handler\n   * - leaveOpen: if set to true, the menu should stay open after the action, defaults to false\n   * @example\n   * <pre>  $scope.gridOptions.columnDefs = [\n   *   { field: 'field1', menuItems: [\n   *     {\n   *       title: 'Outer Scope Alert',\n   *       icon: 'ui-grid-icon-info-circled',\n   *       action: function($event) {\n   *         this.context.blargh(); // $scope.blargh() would work too, this is just an example\n   *       },\n   *       shown: function() { return true; },\n   *       active: function() { return true; },\n   *       context: $scope\n   *     },\n   *     {\n   *       title: 'Grid ID',\n   *       action: function() {\n   *         alert('Grid ID: ' + this.grid.id);\n   *       }\n   *     }\n   *   ] }]; </pre>\n   *\n   */\n\n  /**\n   * @ngdoc method\n   * @methodOf ui.grid.class:GridColumn\n   * @name updateColumnDef\n   * @description Moves settings from the columnDef down onto the column,\n   * and sets properties as appropriate\n   * @param {ColumnDef} colDef the column def to look in for the property value\n   * @param {boolean} isNew whether the column is being newly created, if not\n   * we're updating an existing column, and some items such as the sort shouldn't\n   * be copied down\n   */\n  GridColumn.prototype.updateColumnDef = function(colDef, isNew) {\n    var self = this;\n\n    self.colDef = colDef;\n\n    if (colDef.name === undefined) {\n      throw new Error('colDef.name is required for column at index ' + self.grid.options.columnDefs.indexOf(colDef));\n    }\n\n    self.displayName = (colDef.displayName === undefined) ? gridUtil.readableColumnName(colDef.name) : colDef.displayName;\n\n    if (!angular.isNumber(self.width) || !self.hasCustomWidth || colDef.allowCustomWidthOverride) {\n      var colDefWidth = colDef.width;\n      var parseErrorMsg = \"Cannot parse column width '\" + colDefWidth + \"' for column named '\" + colDef.name + \"'\";\n      self.hasCustomWidth = false;\n\n      if (!angular.isString(colDefWidth) && !angular.isNumber(colDefWidth)) {\n        self.width = '*';\n      } else if (angular.isString(colDefWidth)) {\n        // See if it ends with a percent\n        if (gridUtil.endsWith(colDefWidth, '%')) {\n          // If so we should be able to parse the non-percent-sign part to a number\n          var percentStr = colDefWidth.replace(/%/g, '');\n          var percent = parseInt(percentStr, 10);\n          if (isNaN(percent)) {\n            throw new Error(parseErrorMsg);\n          }\n          self.width = colDefWidth;\n        }\n        // And see if it's a number string\n        else if (colDefWidth.match(/^(\\d+)$/)) {\n          self.width = parseInt(colDefWidth.match(/^(\\d+)$/)[1], 10);\n        }\n        // Otherwise it should be a string of asterisks\n        else if (colDefWidth.match(/^\\*+$/)) {\n          self.width = colDefWidth;\n        }\n        // No idea, throw an Error\n        else {\n          throw new Error(parseErrorMsg);\n        }\n      }\n      // Is a number, use it as the width\n      else {\n        self.width = colDefWidth;\n      }\n    }\n\n    ['minWidth', 'maxWidth'].forEach(function (name) {\n      var minOrMaxWidth = colDef[name];\n      var parseErrorMsg = \"Cannot parse column \" + name + \" '\" + minOrMaxWidth + \"' for column named '\" + colDef.name + \"'\";\n\n      if (!angular.isString(minOrMaxWidth) && !angular.isNumber(minOrMaxWidth)) {\n        //Sets default minWidth and maxWidth values\n        self[name] = ((name === 'minWidth') ? 30 : 9000);\n      } else if (angular.isString(minOrMaxWidth)) {\n        if (minOrMaxWidth.match(/^(\\d+)$/)) {\n          self[name] = parseInt(minOrMaxWidth.match(/^(\\d+)$/)[1], 10);\n        } else {\n          throw new Error(parseErrorMsg);\n        }\n      } else {\n        self[name] = minOrMaxWidth;\n      }\n    });\n\n    //use field if it is defined; name if it is not\n    self.field = (colDef.field === undefined) ? colDef.name : colDef.field;\n\n    if ( typeof( self.field ) !== 'string' ){\n      gridUtil.logError( 'Field is not a string, this is likely to break the code, Field is: ' + self.field );\n    }\n\n    self.name = colDef.name;\n\n    // Use colDef.displayName as long as it's not undefined, otherwise default to the field name\n    self.displayName = (colDef.displayName === undefined) ? gridUtil.readableColumnName(colDef.name) : colDef.displayName;\n\n    //self.originalIndex = index;\n\n    self.aggregationType = angular.isDefined(colDef.aggregationType) ? colDef.aggregationType : null;\n    self.footerCellTemplate = angular.isDefined(colDef.footerCellTemplate) ? colDef.footerCellTemplate : null;\n\n    /**\n     * @ngdoc property\n     * @name cellTooltip\n     * @propertyOf ui.grid.class:GridOptions.columnDef\n     * @description Whether or not to show a tooltip when a user hovers over the cell.\n     * If set to false, no tooltip.  If true, the cell value is shown in the tooltip (useful\n     * if you have long values in your cells), if a function then that function is called\n     * passing in the row and the col `cellTooltip( row, col )`, and the return value is shown in the tooltip,\n     * if it is a static string then displays that static string.\n     *\n     * Defaults to false\n     *\n     */\n    if ( typeof(colDef.cellTooltip) === 'undefined' || colDef.cellTooltip === false ) {\n      self.cellTooltip = false;\n    } else if ( colDef.cellTooltip === true ){\n      self.cellTooltip = function(row, col) {\n        return self.grid.getCellValue( row, col );\n      };\n    } else if (typeof(colDef.cellTooltip) === 'function' ){\n      self.cellTooltip = colDef.cellTooltip;\n    } else {\n      self.cellTooltip = function ( row, col ){\n        return col.colDef.cellTooltip;\n      };\n    }\n\n    /**\n     * @ngdoc property\n     * @name headerTooltip\n     * @propertyOf ui.grid.class:GridOptions.columnDef\n     * @description Whether or not to show a tooltip when a user hovers over the header cell.\n     * If set to false, no tooltip.  If true, the displayName is shown in the tooltip (useful\n     * if you have long values in your headers), if a function then that function is called\n     * passing in the row and the col `headerTooltip( col )`, and the return value is shown in the tooltip,\n     * if a static string then shows that static string.\n     *\n     * Defaults to false\n     *\n     */\n    if ( typeof(colDef.headerTooltip) === 'undefined' || colDef.headerTooltip === false ) {\n      self.headerTooltip = false;\n    } else if ( colDef.headerTooltip === true ){\n      self.headerTooltip = function(col) {\n        return col.displayName;\n      };\n    } else if (typeof(colDef.headerTooltip) === 'function' ){\n      self.headerTooltip = colDef.headerTooltip;\n    } else {\n      self.headerTooltip = function ( col ) {\n        return col.colDef.headerTooltip;\n      };\n    }\n\n\n    /**\n     * @ngdoc property\n     * @name footerCellClass\n     * @propertyOf ui.grid.class:GridOptions.columnDef\n     * @description footerCellClass can be a string specifying the class to append to a cell\n     * or it can be a function(grid, row, col, rowRenderIndex, colRenderIndex) that returns a class name\n     *\n     */\n    self.footerCellClass = colDef.footerCellClass;\n\n    /**\n     * @ngdoc property\n     * @name cellClass\n     * @propertyOf ui.grid.class:GridOptions.columnDef\n     * @description cellClass can be a string specifying the class to append to a cell\n     * or it can be a function(grid, row, col, rowRenderIndex, colRenderIndex) that returns a class name\n     *\n     */\n    self.cellClass = colDef.cellClass;\n\n    /**\n     * @ngdoc property\n     * @name headerCellClass\n     * @propertyOf ui.grid.class:GridOptions.columnDef\n     * @description headerCellClass can be a string specifying the class to append to a cell\n     * or it can be a function(grid, row, col, rowRenderIndex, colRenderIndex) that returns a class name\n     *\n     */\n    self.headerCellClass = colDef.headerCellClass;\n\n    /**\n     * @ngdoc property\n     * @name cellFilter\n     * @propertyOf ui.grid.class:GridOptions.columnDef\n     * @description cellFilter is a filter to apply to the content of each cell\n     * @example\n     * <pre>\n     *   gridOptions.columnDefs[0].cellFilter = 'date'\n     *\n     */\n    self.cellFilter = colDef.cellFilter ? colDef.cellFilter : \"\";\n\n    /**\n     * @ngdoc boolean\n     * @name sortCellFiltered\n     * @propertyOf ui.grid.class:GridOptions.columnDef\n     * @description (optional) False by default. When `true` uiGrid will apply the cellFilter before\n     * sorting the data. Note that when using this option uiGrid will assume that the displayed value is\n     * a string, and use the {@link ui.grid.class:RowSorter#sortAlpha sortAlpha} `sortFn`. It is possible\n     * to return a non-string value from an angularjs filter, in which case you should define a {@link ui.grid.class:GridOptions.columnDef#sortingAlgorithm sortingAlgorithm}\n     * for the column which hanldes the returned type. You may specify one of the `sortingAlgorithms`\n     * found in the {@link ui.grid.RowSorter rowSorter} service.\n     */\n    self.sortCellFiltered = colDef.sortCellFiltered ? true : false;\n\n    /**\n     * @ngdoc boolean\n     * @name filterCellFiltered\n     * @propertyOf ui.grid.class:GridOptions.columnDef\n     * @description (optional) False by default. When `true` uiGrid will apply the cellFilter before\n     * applying \"search\" `filters`.\n     */\n    self.filterCellFiltered = colDef.filterCellFiltered ? true : false;\n\n    /**\n     * @ngdoc property\n     * @name headerCellFilter\n     * @propertyOf ui.grid.class:GridOptions.columnDef\n     * @description headerCellFilter is a filter to apply to the content of the column header\n     * @example\n     * <pre>\n     *   gridOptions.columnDefs[0].headerCellFilter = 'translate'\n     *\n     */\n    self.headerCellFilter = colDef.headerCellFilter ? colDef.headerCellFilter : \"\";\n\n    /**\n     * @ngdoc property\n     * @name footerCellFilter\n     * @propertyOf ui.grid.class:GridOptions.columnDef\n     * @description footerCellFilter is a filter to apply to the content of the column footer\n     * @example\n     * <pre>\n     *   gridOptions.columnDefs[0].footerCellFilter = 'date'\n     *\n     */\n    self.footerCellFilter = colDef.footerCellFilter ? colDef.footerCellFilter : \"\";\n\n    self.visible = gridUtil.isNullOrUndefined(colDef.visible) || colDef.visible;\n\n    self.headerClass = colDef.headerClass;\n    //self.cursor = self.sortable ? 'pointer' : 'default';\n\n    // Turn on sorting by default\n    self.enableSorting = typeof(colDef.enableSorting) !== 'undefined' ? colDef.enableSorting : true;\n    self.sortingAlgorithm = colDef.sortingAlgorithm;\n\n    /**\n     * @ngdoc property\n     * @name sortDirectionCycle\n     * @propertyOf ui.grid.class:GridOptions.columnDef\n     * @description (optional) An array of {@link ui.grid.service:uiGridConstants#properties_ASC sort directions},\n     * specifying the order that they should cycle through as the user repeatedly clicks on the column heading.\n     * The default is `[null, uiGridConstants.ASC, uiGridConstants.DESC]`. Null\n     * refers to the unsorted state. This does not affect the initial sort\n     * direction; use the {@link ui.grid.class:GridOptions.columnDef#sort sort}\n     * property for that. If\n     * {@link ui.grid.class:GridOptions.columnDef#suppressRemoveSort suppressRemoveSort}\n     * is also set, the unsorted state will be skipped even if it is listed here.\n     * Each direction may not appear in the list more than once (e.g. `[ASC,\n     * DESC, DESC]` is not allowed), and the list may not be empty.\n     */\n    self.sortDirectionCycle = typeof(colDef.sortDirectionCycle) !== 'undefined' ?\n      colDef.sortDirectionCycle :\n      [null, uiGridConstants.ASC, uiGridConstants.DESC];\n\n    /**\n     * @ngdoc boolean\n     * @name suppressRemoveSort\n     * @propertyOf ui.grid.class:GridOptions.columnDef\n     * @description (optional) False by default. When enabled, this setting hides the removeSort option\n     * in the menu, and prevents users from manually removing the sort\n     */\n    if ( typeof(self.suppressRemoveSort) === 'undefined'){\n      self.suppressRemoveSort = typeof(colDef.suppressRemoveSort) !== 'undefined' ? colDef.suppressRemoveSort : false;\n    }\n\n    /**\n     * @ngdoc property\n     * @name enableFiltering\n     * @propertyOf ui.grid.class:GridOptions.columnDef\n     * @description turn off filtering for an individual column, where\n     * you've turned on filtering for the overall grid\n     * @example\n     * <pre>\n     *   gridOptions.columnDefs[0].enableFiltering = false;\n     *\n     */\n    // Turn on filtering by default (it's disabled by default at the Grid level)\n    self.enableFiltering = typeof(colDef.enableFiltering) !== 'undefined' ? colDef.enableFiltering : true;\n\n    // self.menuItems = colDef.menuItems;\n    self.setPropertyOrDefault(colDef, 'menuItems', []);\n\n    // Use the column definition sort if we were passed it, but only if this is a newly added column\n    if ( isNew ){\n      self.setPropertyOrDefault(colDef, 'sort');\n    }\n\n    // Set up default filters array for when one is not provided.\n    //   In other words, this (in column def):\n    //\n    //       filter: { term: 'something', flags: {}, condition: [CONDITION] }\n    //\n    //   is just shorthand for this:\n    //\n    //       filters: [{ term: 'something', flags: {}, condition: [CONDITION] }]\n    //\n    var defaultFilters = [];\n    if (colDef.filter) {\n      defaultFilters.push(colDef.filter);\n    }\n    else if ( colDef.filters ){\n      defaultFilters = colDef.filters;\n    } else {\n      // Add an empty filter definition object, which will\n      // translate to a guessed condition and no pre-populated\n      // value for the filter <input>.\n      defaultFilters.push({});\n    }\n\n    /**\n     * @ngdoc property\n     * @name filter\n     * @propertyOf ui.grid.class:GridOptions.columnDef\n     * @description Specify a single filter field on this column.\n     *\n     * A filter consists of a condition, a term, and a placeholder:\n     *\n     * - condition defines how rows are chosen as matching the filter term. This can be set to\n     * one of the constants in {@link ui.grid.service:uiGridConstants#properties_filter uiGridConstants.filter},\n     * or you can supply a custom filter function\n     * that gets passed the following arguments: [searchTerm, cellValue, row, column].\n     * - term: If set, the filter field will be pre-populated\n     * with this value.\n     * - placeholder: String that will be set to the `<input>.placeholder` attribute.\n     * - ariaLabel: String that will be set to the `<input>.ariaLabel` attribute. This is what is read as a label to screen reader users.\n     * - noTerm: set this to true if you have defined a custom function in condition, and\n     * your custom function doesn't require a term (so it can run even when the term is null)\n     * - rawTerm: set this to true if you have defined a custom function in condition, and\n     * your custom function requires access to the raw unmodified search term that was entered\n     * - flags: only flag currently available is `caseSensitive`, set to false if you don't want\n     * case sensitive matching\n     * - type: defaults to {@link ui.grid.service:uiGridConstants#properties_filter uiGridConstants.filter.INPUT},\n     * which gives a text box.  If set to {@link ui.grid.service:uiGridConstants#properties_filter uiGridConstants.filter.SELECT}\n     * then a select box will be shown with options selectOptions\n     * - selectOptions: options in the format `[ { value: 1, label: 'male' }]`.  No i18n filter is provided, you need\n     * to perform the i18n on the values before you provide them\n     * - disableCancelFilterButton: defaults to false. If set to true then the 'x' button that cancels/clears the filter\n     * will not be shown.\n     * @example\n     * <pre>$scope.gridOptions.columnDefs = [\n     *   {\n     *     field: 'field1',\n     *     filter: {\n     *       term: 'xx',\n     *       condition: uiGridConstants.filter.STARTS_WITH,\n     *       placeholder: 'starts with...',\n     *       ariaLabel: 'Starts with filter for field1',\n     *       flags: { caseSensitive: false },\n     *       type: uiGridConstants.filter.SELECT,\n     *       selectOptions: [ { value: 1, label: 'male' }, { value: 2, label: 'female' } ],\n     *       disableCancelFilterButton: true\n     *     }\n     *   }\n     * ]; </pre>\n     *\n     */\n\n    /*\n\n\n    /*\n\n      self.filters = [\n        {\n          term: 'search term'\n          condition: uiGridConstants.filter.CONTAINS,\n          placeholder: 'my placeholder',\n          ariaLabel: 'Starts with filter for field1',\n          flags: {\n            caseSensitive: true\n          }\n        }\n      ]\n\n    */\n\n    // Only set filter if this is a newly added column, if we're updating an existing\n    // column then we don't want to put the default filter back if the user may have already\n    // removed it.\n    // However, we do want to keep the settings if they change, just not the term\n    if ( isNew ) {\n      self.setPropertyOrDefault(colDef, 'filter');\n      self.setPropertyOrDefault(colDef, 'filters', defaultFilters);\n    } else if ( self.filters.length === defaultFilters.length ) {\n      self.filters.forEach( function( filter, index ){\n        if (typeof(defaultFilters[index].placeholder) !== 'undefined') {\n          filter.placeholder = defaultFilters[index].placeholder;\n        }\n        if (typeof(defaultFilters[index].ariaLabel) !== 'undefined') {\n          filter.ariaLabel = defaultFilters[index].ariaLabel;\n        }\n        if (typeof(defaultFilters[index].flags) !== 'undefined') {\n          filter.flags = defaultFilters[index].flags;\n        }\n        if (typeof(defaultFilters[index].type) !== 'undefined') {\n          filter.type = defaultFilters[index].type;\n        }\n        if (typeof(defaultFilters[index].selectOptions) !== 'undefined') {\n          filter.selectOptions = defaultFilters[index].selectOptions;\n        }\n      });\n    }\n  };\n\n  /**\n   * @ngdoc function\n   * @name unsort\n   * @methodOf ui.grid.class:GridColumn\n   * @description Removes column from the grid sorting\n   */\n  GridColumn.prototype.unsort = function () {\n    this.sort = {};\n    this.grid.api.core.raise.sortChanged( this.grid, this.grid.getColumnSorting() );\n  };\n\n\n  /**\n   * @ngdoc function\n   * @name getColClass\n   * @methodOf ui.grid.class:GridColumn\n   * @description Returns the class name for the column\n   * @param {bool} prefixDot  if true, will return .className instead of className\n   */\n  GridColumn.prototype.getColClass = function (prefixDot) {\n    var cls = uiGridConstants.COL_CLASS_PREFIX + this.uid;\n\n    return prefixDot ? '.' + cls : cls;\n  };\n\n    /**\n     * @ngdoc function\n     * @name isPinnedLeft\n     * @methodOf ui.grid.class:GridColumn\n     * @description Returns true if column is in the left render container\n     */\n    GridColumn.prototype.isPinnedLeft = function () {\n      return this.renderContainer === 'left';\n    };\n\n    /**\n     * @ngdoc function\n     * @name isPinnedRight\n     * @methodOf ui.grid.class:GridColumn\n     * @description Returns true if column is in the right render container\n     */\n    GridColumn.prototype.isPinnedRight = function () {\n      return this.renderContainer === 'right';\n    };\n\n\n    /**\n   * @ngdoc function\n   * @name getColClassDefinition\n   * @methodOf ui.grid.class:GridColumn\n   * @description Returns the class definition for th column\n   */\n  GridColumn.prototype.getColClassDefinition = function () {\n    return ' .grid' + this.grid.id + ' ' + this.getColClass(true) + ' { min-width: ' + this.drawnWidth + 'px; max-width: ' + this.drawnWidth + 'px; }';\n  };\n\n  /**\n   * @ngdoc function\n   * @name getRenderContainer\n   * @methodOf ui.grid.class:GridColumn\n   * @description Returns the render container object that this column belongs to.\n   *\n   * Columns will be default be in the `body` render container if they aren't allocated to one specifically.\n   */\n  GridColumn.prototype.getRenderContainer = function getRenderContainer() {\n    var self = this;\n\n    var containerId = self.renderContainer;\n\n    if (containerId === null || containerId === '' || containerId === undefined) {\n      containerId = 'body';\n    }\n\n    return self.grid.renderContainers[containerId];\n  };\n\n  /**\n   * @ngdoc function\n   * @name showColumn\n   * @methodOf ui.grid.class:GridColumn\n   * @description Makes the column visible by setting colDef.visible = true\n   */\n  GridColumn.prototype.showColumn = function() {\n      this.colDef.visible = true;\n  };\n\n\n  /**\n   * @ngdoc property\n   * @name aggregationHideLabel\n   * @propertyOf ui.grid.class:GridOptions.columnDef\n   * @description defaults to false, if set to true hides the label text\n   * in the aggregation footer, so only the value is displayed.\n   *\n   */\n  /**\n   * @ngdoc function\n   * @name getAggregationText\n   * @methodOf ui.grid.class:GridColumn\n   * @description Gets the aggregation label from colDef.aggregationLabel if\n   * specified or by using i18n, including deciding whether or not to display\n   * based on colDef.aggregationHideLabel.\n   *\n   * @param {string} label the i18n lookup value to use for the column label\n   *\n   */\n  GridColumn.prototype.getAggregationText = function () {\n    var self = this;\n    if ( self.colDef.aggregationHideLabel ){\n      return '';\n    }\n    else if ( self.colDef.aggregationLabel ) {\n      return self.colDef.aggregationLabel;\n    }\n    else {\n      switch ( self.colDef.aggregationType ){\n        case uiGridConstants.aggregationTypes.count:\n          return i18nService.getSafeText('aggregation.count');\n        case uiGridConstants.aggregationTypes.sum:\n          return i18nService.getSafeText('aggregation.sum');\n        case uiGridConstants.aggregationTypes.avg:\n          return i18nService.getSafeText('aggregation.avg');\n        case uiGridConstants.aggregationTypes.min:\n          return i18nService.getSafeText('aggregation.min');\n        case uiGridConstants.aggregationTypes.max:\n          return i18nService.getSafeText('aggregation.max');\n        default:\n          return '';\n      }\n    }\n  };\n\n  GridColumn.prototype.getCellTemplate = function () {\n    var self = this;\n\n    return self.cellTemplatePromise;\n  };\n\n  GridColumn.prototype.getCompiledElementFn = function () {\n    var self = this;\n\n    return self.compiledElementFnDefer.promise;\n  };\n\n  return GridColumn;\n}]);\n\n})();\n\n  (function(){\n\nangular.module('ui.grid')\n.factory('GridOptions', ['gridUtil','uiGridConstants', function(gridUtil,uiGridConstants) {\n\n  /**\n   * @ngdoc function\n   * @name ui.grid.class:GridOptions\n   * @description Default GridOptions class.  GridOptions are defined by the application developer and overlaid\n   * over this object.  Setting gridOptions within your controller is the most common method for an application\n   * developer to configure the behaviour of their ui-grid\n   *\n   * @example To define your gridOptions within your controller:\n   * <pre>$scope.gridOptions = {\n   *   data: $scope.myData,\n   *   columnDefs: [\n   *     { name: 'field1', displayName: 'pretty display name' },\n   *     { name: 'field2', visible: false }\n   *  ]\n   * };</pre>\n   *\n   * You can then use this within your html template, when you define your grid:\n   * <pre>&lt;div ui-grid=\"gridOptions\"&gt;&lt;/div&gt;</pre>\n   *\n   * To provide default options for all of the grids within your application, use an angular\n   * decorator to modify the GridOptions factory.\n   * <pre>\n   * app.config(function($provide){\n   *   $provide.decorator('GridOptions',function($delegate){\n   *     var gridOptions;\n   *     gridOptions = angular.copy($delegate);\n   *     gridOptions.initialize = function(options) {\n   *       var initOptions;\n   *       initOptions = $delegate.initialize(options);\n   *       initOptions.enableColumnMenus = false;\n   *       return initOptions;\n   *     };\n   *     return gridOptions;\n   *   });\n   * });\n   * </pre>\n   */\n  return {\n    initialize: function( baseOptions ){\n      /**\n       * @ngdoc function\n       * @name onRegisterApi\n       * @propertyOf ui.grid.class:GridOptions\n       * @description A callback that returns the gridApi once the grid is instantiated, which is\n       * then used to interact with the grid programatically.\n       *\n       * Note that the gridApi.core.renderingComplete event is identical to this\n       * callback, but has the advantage that it can be called from multiple places\n       * if needed\n       *\n       * @example\n       * <pre>\n       *   $scope.gridOptions.onRegisterApi = function ( gridApi ) {\n       *     $scope.gridApi = gridApi;\n       *     $scope.gridApi.selection.selectAllRows( $scope.gridApi.grid );\n       *   };\n       * </pre>\n       *\n       */\n      baseOptions.onRegisterApi = baseOptions.onRegisterApi || angular.noop();\n\n      /**\n       * @ngdoc object\n       * @name data\n       * @propertyOf ui.grid.class:GridOptions\n       * @description (mandatory) Array of data to be rendered into the grid, providing the data source or data binding for\n       * the grid.\n       *\n       * Most commonly the data is an array of objects, where each object has a number of attributes.\n       * Each attribute automatically becomes a column in your grid.  This array could, for example, be sourced from\n       * an angularJS $resource query request.  The array can also contain complex objects, refer the binding tutorial\n       * for examples of that.\n       *\n       * The most flexible usage is to set your data on $scope:\n       *\n       * `$scope.data = data;`\n       *\n       * And then direct the grid to resolve whatever is in $scope.data:\n       *\n       * `$scope.gridOptions.data = 'data';`\n       *\n       * This is the most flexible approach as it allows you to replace $scope.data whenever you feel like it without\n       * getting pointer issues.\n       *\n       * Alternatively you can directly set the data array:\n       *\n       * `$scope.gridOptions.data = [ ];`\n       * or\n       *\n       * `$http.get('/data/100.json')\n       * .success(function(data) {\n       *   $scope.myData = data;\n       *   $scope.gridOptions.data = $scope.myData;\n       *  });`\n       *\n       * Where you do this, you need to take care in updating the data - you can't just update `$scope.myData` to some other\n       * array, you need to update $scope.gridOptions.data to point to that new array as well.\n       *\n       */\n      baseOptions.data = baseOptions.data || [];\n\n      /**\n       * @ngdoc array\n       * @name columnDefs\n       * @propertyOf  ui.grid.class:GridOptions\n       * @description Array of columnDef objects.  Only required property is name.\n       * The individual options available in columnDefs are documented in the\n       * {@link ui.grid.class:GridOptions.columnDef columnDef} section\n       * </br>_field property can be used in place of name for backwards compatibility with 2.x_\n       *  @example\n       *\n       * <pre>var columnDefs = [{name:'field1'}, {name:'field2'}];</pre>\n       *\n       */\n      baseOptions.columnDefs = baseOptions.columnDefs || [];\n\n      /**\n       * @ngdoc object\n       * @name ui.grid.class:GridOptions.columnDef\n       * @description Definition / configuration of an individual column, which would typically be\n       * one of many column definitions within the gridOptions.columnDefs array\n       * @example\n       * <pre>{name:'field1', field: 'field1', filter: { term: 'xxx' }}</pre>\n       *\n       */\n\n\n      /**\n       * @ngdoc array\n       * @name excludeProperties\n       * @propertyOf  ui.grid.class:GridOptions\n       * @description Array of property names in data to ignore when auto-generating column names.  Provides the\n       * inverse of columnDefs - columnDefs is a list of columns to include, excludeProperties is a list of columns\n       * to exclude.\n       *\n       * If columnDefs is defined, this will be ignored.\n       *\n       * Defaults to ['$$hashKey']\n       */\n\n      baseOptions.excludeProperties = baseOptions.excludeProperties || ['$$hashKey'];\n\n      /**\n       * @ngdoc boolean\n       * @name enableRowHashing\n       * @propertyOf ui.grid.class:GridOptions\n       * @description True by default. When enabled, this setting allows uiGrid to add\n       * `$$hashKey`-type properties (similar to Angular) to elements in the `data` array. This allows\n       * the grid to maintain state while vastly speeding up the process of altering `data` by adding/moving/removing rows.\n       *\n       * Note that this DOES add properties to your data that you may not want, but they are stripped out when using `angular.toJson()`. IF\n       * you do not want this at all you can disable this setting but you will take a performance hit if you are using large numbers of rows\n       * and are altering the data set often.\n       */\n      baseOptions.enableRowHashing = baseOptions.enableRowHashing !== false;\n\n      /**\n       * @ngdoc function\n       * @name rowIdentity\n       * @methodOf ui.grid.class:GridOptions\n       * @description This function is used to get and, if necessary, set the value uniquely identifying this row (i.e. if an identity is not present it will set one).\n       *\n       * By default it returns the `$$hashKey` property if it exists. If it doesn't it uses gridUtil.nextUid() to generate one\n       */\n      baseOptions.rowIdentity = baseOptions.rowIdentity || function rowIdentity(row) {\n        return gridUtil.hashKey(row);\n      };\n\n      /**\n       * @ngdoc function\n       * @name getRowIdentity\n       * @methodOf ui.grid.class:GridOptions\n       * @description This function returns the identity value uniquely identifying this row, if one is not present it does not set it.\n       *\n       * By default it returns the `$$hashKey` property but can be overridden to use any property or set of properties you want.\n       */\n      baseOptions.getRowIdentity = baseOptions.getRowIdentity || function getRowIdentity(row) {\n        return row.$$hashKey;\n      };\n\n      /**\n       * @ngdoc property\n       * @name flatEntityAccess\n       * @propertyOf ui.grid.class:GridOptions\n       * @description Set to true if your columns are all related directly to fields in a flat object structure - i.e.\n       * each of your columns associate directly with a property on each of the entities in your data array.\n       *\n       * In that situation we can avoid all the logic associated with complex binding to functions or to properties of sub-objects,\n       * which can provide a significant speed improvement with large data sets when filtering or sorting.\n       *\n       * By default false\n       */\n      baseOptions.flatEntityAccess = baseOptions.flatEntityAccess === true;\n\n      /**\n       * @ngdoc property\n       * @name showHeader\n       * @propertyOf ui.grid.class:GridOptions\n       * @description True by default. When set to false, this setting will replace the\n       * standard header template with '<div></div>', resulting in no header being shown.\n       */\n      baseOptions.showHeader = typeof(baseOptions.showHeader) !== \"undefined\" ? baseOptions.showHeader : true;\n\n      /* (NOTE): Don't show this in the docs. We only use it internally\n       * @ngdoc property\n       * @name headerRowHeight\n       * @propertyOf ui.grid.class:GridOptions\n       * @description The height of the header in pixels, defaults to 30\n       *\n       */\n      if (!baseOptions.showHeader) {\n        baseOptions.headerRowHeight = 0;\n      }\n      else {\n        baseOptions.headerRowHeight = typeof(baseOptions.headerRowHeight) !== \"undefined\" ? baseOptions.headerRowHeight : 30;\n      }\n\n      /**\n       * @ngdoc property\n       * @name rowHeight\n       * @propertyOf ui.grid.class:GridOptions\n       * @description The height of the row in pixels, defaults to 30\n       *\n       */\n      baseOptions.rowHeight = baseOptions.rowHeight || 30;\n\n      /**\n       * @ngdoc integer\n       * @name minRowsToShow\n       * @propertyOf ui.grid.class:GridOptions\n       * @description Minimum number of rows to show when the grid doesn't have a defined height. Defaults to \"10\".\n       */\n      baseOptions.minRowsToShow = typeof(baseOptions.minRowsToShow) !== \"undefined\" ? baseOptions.minRowsToShow : 10;\n\n      /**\n       * @ngdoc property\n       * @name showGridFooter\n       * @propertyOf ui.grid.class:GridOptions\n       * @description Whether or not to show the footer, defaults to false\n       * The footer display Total Rows and Visible Rows (filtered rows)\n       */\n      baseOptions.showGridFooter = baseOptions.showGridFooter === true;\n\n      /**\n       * @ngdoc property\n       * @name showColumnFooter\n       * @propertyOf ui.grid.class:GridOptions\n       * @description Whether or not to show the column footer, defaults to false\n       * The column footer displays column aggregates\n       */\n      baseOptions.showColumnFooter = baseOptions.showColumnFooter === true;\n\n      /**\n       * @ngdoc property\n       * @name columnFooterHeight\n       * @propertyOf ui.grid.class:GridOptions\n       * @description The height of the footer rows (column footer and grid footer) in pixels\n       *\n       */\n      baseOptions.columnFooterHeight = typeof(baseOptions.columnFooterHeight) !== \"undefined\" ? baseOptions.columnFooterHeight : 30;\n      baseOptions.gridFooterHeight = typeof(baseOptions.gridFooterHeight) !== \"undefined\" ? baseOptions.gridFooterHeight : 30;\n\n      baseOptions.columnWidth = typeof(baseOptions.columnWidth) !== \"undefined\" ? baseOptions.columnWidth : 50;\n\n      /**\n       * @ngdoc property\n       * @name maxVisibleColumnCount\n       * @propertyOf ui.grid.class:GridOptions\n       * @description Defaults to 200\n       *\n       */\n      baseOptions.maxVisibleColumnCount = typeof(baseOptions.maxVisibleColumnCount) !== \"undefined\" ? baseOptions.maxVisibleColumnCount : 200;\n\n      /**\n       * @ngdoc property\n       * @name virtualizationThreshold\n       * @propertyOf ui.grid.class:GridOptions\n       * @description Turn virtualization on when number of data elements goes over this number, defaults to 20\n       */\n      baseOptions.virtualizationThreshold = typeof(baseOptions.virtualizationThreshold) !== \"undefined\" ? baseOptions.virtualizationThreshold : 20;\n\n      /**\n       * @ngdoc property\n       * @name columnVirtualizationThreshold\n       * @propertyOf ui.grid.class:GridOptions\n       * @description Turn virtualization on when number of columns goes over this number, defaults to 10\n       */\n      baseOptions.columnVirtualizationThreshold = typeof(baseOptions.columnVirtualizationThreshold) !== \"undefined\" ? baseOptions.columnVirtualizationThreshold : 10;\n\n      /**\n       * @ngdoc property\n       * @name excessRows\n       * @propertyOf ui.grid.class:GridOptions\n       * @description Extra rows to to render outside of the viewport, which helps with smoothness of scrolling.\n       * Defaults to 4\n       */\n      baseOptions.excessRows = typeof(baseOptions.excessRows) !== \"undefined\" ? baseOptions.excessRows : 4;\n      /**\n       * @ngdoc property\n       * @name scrollThreshold\n       * @propertyOf ui.grid.class:GridOptions\n       * @description Defaults to 4\n       */\n      baseOptions.scrollThreshold = typeof(baseOptions.scrollThreshold) !== \"undefined\" ? baseOptions.scrollThreshold : 4;\n\n      /**\n       * @ngdoc property\n       * @name excessColumns\n       * @propertyOf ui.grid.class:GridOptions\n       * @description Extra columns to to render outside of the viewport, which helps with smoothness of scrolling.\n       * Defaults to 4\n       */\n      baseOptions.excessColumns = typeof(baseOptions.excessColumns) !== \"undefined\" ? baseOptions.excessColumns : 4;\n      /**\n       * @ngdoc property\n       * @name horizontalScrollThreshold\n       * @propertyOf ui.grid.class:GridOptions\n       * @description Defaults to 4\n       */\n      baseOptions.horizontalScrollThreshold = typeof(baseOptions.horizontalScrollThreshold) !== \"undefined\" ? baseOptions.horizontalScrollThreshold : 2;\n\n\n      /**\n       * @ngdoc property\n       * @name aggregationCalcThrottle\n       * @propertyOf ui.grid.class:GridOptions\n       * @description Default time in milliseconds to throttle aggregation calcuations, defaults to 500ms\n       */\n      baseOptions.aggregationCalcThrottle = typeof(baseOptions.aggregationCalcThrottle) !== \"undefined\" ? baseOptions.aggregationCalcThrottle : 500;\n\n      /**\n       * @ngdoc property\n       * @name wheelScrollThrottle\n       * @propertyOf ui.grid.class:GridOptions\n       * @description Default time in milliseconds to throttle scroll events to, defaults to 70ms\n       */\n      baseOptions.wheelScrollThrottle = typeof(baseOptions.wheelScrollThrottle) !== \"undefined\" ? baseOptions.wheelScrollThrottle : 70;\n\n\n      /**\n       * @ngdoc property\n       * @name scrollDebounce\n       * @propertyOf ui.grid.class:GridOptions\n       * @description Default time in milliseconds to debounce scroll events, defaults to 300ms\n       */\n      baseOptions.scrollDebounce = typeof(baseOptions.scrollDebounce) !== \"undefined\" ? baseOptions.scrollDebounce : 300;\n\n      /**\n       * @ngdoc boolean\n       * @name enableSorting\n       * @propertyOf ui.grid.class:GridOptions\n       * @description True by default. When enabled, this setting adds sort\n       * widgets to the column headers, allowing sorting of the data for the entire grid.\n       * Sorting can then be disabled on individual columns using the columnDefs.\n       */\n      baseOptions.enableSorting = baseOptions.enableSorting !== false;\n\n      /**\n       * @ngdoc boolean\n       * @name enableFiltering\n       * @propertyOf ui.grid.class:GridOptions\n       * @description False by default. When enabled, this setting adds filter\n       * boxes to each column header, allowing filtering within the column for the entire grid.\n       * Filtering can then be disabled on individual columns using the columnDefs.\n       */\n      baseOptions.enableFiltering = baseOptions.enableFiltering === true;\n\n      /**\n       * @ngdoc boolean\n       * @name enableColumnMenus\n       * @propertyOf ui.grid.class:GridOptions\n       * @description True by default. When enabled, this setting displays a column\n       * menu within each column.\n       */\n      baseOptions.enableColumnMenus = baseOptions.enableColumnMenus !== false;\n\n      /**\n       * @ngdoc boolean\n       * @name enableVerticalScrollbar\n       * @propertyOf ui.grid.class:GridOptions\n       * @description {@link ui.grid.service:uiGridConstants#properties_scrollbars uiGridConstants.scrollbars.ALWAYS} by default.\n       * This settings controls the vertical scrollbar for the grid.\n       * Supported values: uiGridConstants.scrollbars.ALWAYS, uiGridConstants.scrollbars.NEVER\n       */\n      baseOptions.enableVerticalScrollbar = typeof(baseOptions.enableVerticalScrollbar) !== \"undefined\" ? baseOptions.enableVerticalScrollbar : uiGridConstants.scrollbars.ALWAYS;\n\n      /**\n       * @ngdoc boolean\n       * @name enableHorizontalScrollbar\n       * @propertyOf ui.grid.class:GridOptions\n       * @description {@link ui.grid.service:uiGridConstants#properties_scrollbars uiGridConstants.scrollbars.ALWAYS} by default.\n       * This settings controls the horizontal scrollbar for the grid.\n       * Supported values: uiGridConstants.scrollbars.ALWAYS, uiGridConstants.scrollbars.NEVER\n       */\n      baseOptions.enableHorizontalScrollbar = typeof(baseOptions.enableHorizontalScrollbar) !== \"undefined\" ? baseOptions.enableHorizontalScrollbar : uiGridConstants.scrollbars.ALWAYS;\n\n      /**\n       * @ngdoc boolean\n       * @name enableMinHeightCheck\n       * @propertyOf ui.grid.class:GridOptions\n       * @description True by default. When enabled, a newly initialized grid will check to see if it is tall enough to display\n       * at least one row of data.  If the grid is not tall enough, it will resize the DOM element to display minRowsToShow number\n       * of rows.\n       */\n       baseOptions.enableMinHeightCheck = baseOptions.enableMinHeightCheck !== false;\n\n      /**\n       * @ngdoc boolean\n       * @name minimumColumnSize\n       * @propertyOf ui.grid.class:GridOptions\n       * @description Columns can't be smaller than this, defaults to 10 pixels\n       */\n      baseOptions.minimumColumnSize = typeof(baseOptions.minimumColumnSize) !== \"undefined\" ? baseOptions.minimumColumnSize : 10;\n\n      /**\n       * @ngdoc function\n       * @name rowEquality\n       * @methodOf ui.grid.class:GridOptions\n       * @description By default, rows are compared using object equality.  This option can be overridden\n       * to compare on any data item property or function\n       * @param {object} entityA First Data Item to compare\n       * @param {object} entityB Second Data Item to compare\n       */\n      baseOptions.rowEquality = baseOptions.rowEquality || function(entityA, entityB) {\n        return entityA === entityB;\n      };\n\n      /**\n       * @ngdoc string\n       * @name headerTemplate\n       * @propertyOf ui.grid.class:GridOptions\n       * @description Null by default. When provided, this setting uses a custom header\n       * template, rather than the default template. Can be set to either the name of a template file:\n       * <pre>  $scope.gridOptions.headerTemplate = 'header_template.html';</pre>\n       * inline html\n       * <pre>  $scope.gridOptions.headerTemplate = '<div class=\"ui-grid-top-panel\" style=\"text-align: center\">I am a Custom Grid Header</div>'</pre>\n       * or the id of a precompiled template (TBD how to use this).\n       * </br>Refer to the custom header tutorial for more information.\n       * If you want no header at all, you can set to an empty div:\n       * <pre>  $scope.gridOptions.headerTemplate = '<div></div>';</pre>\n       *\n       * If you want to only have a static header, then you can set to static content.  If\n       * you want to tailor the existing column headers, then you should look at the\n       * current 'ui-grid-header.html' template in github as your starting point.\n       *\n       */\n      baseOptions.headerTemplate = baseOptions.headerTemplate || null;\n\n      /**\n       * @ngdoc string\n       * @name footerTemplate\n       * @propertyOf ui.grid.class:GridOptions\n       * @description (optional) ui-grid/ui-grid-footer by default.  This footer shows the per-column\n       * aggregation totals.\n       * When provided, this setting uses a custom footer template. Can be set to either the name of a template file 'footer_template.html', inline html\n       * <pre>'<div class=\"ui-grid-bottom-panel\" style=\"text-align: center\">I am a Custom Grid Footer</div>'</pre>, or the id\n       * of a precompiled template (TBD how to use this).  Refer to the custom footer tutorial for more information.\n       */\n      baseOptions.footerTemplate = baseOptions.footerTemplate || 'ui-grid/ui-grid-footer';\n\n      /**\n       * @ngdoc string\n       * @name gridFooterTemplate\n       * @propertyOf ui.grid.class:GridOptions\n       * @description (optional) ui-grid/ui-grid-grid-footer by default. This template by default shows the\n       * total items at the bottom of the grid, and the selected items if selection is enabled.\n       */\n      baseOptions.gridFooterTemplate = baseOptions.gridFooterTemplate || 'ui-grid/ui-grid-grid-footer';\n\n      /**\n       * @ngdoc string\n       * @name rowTemplate\n       * @propertyOf ui.grid.class:GridOptions\n       * @description 'ui-grid/ui-grid-row' by default. When provided, this setting uses a\n       * custom row template.  Can be set to either the name of a template file:\n       * <pre> $scope.gridOptions.rowTemplate = 'row_template.html';</pre>\n       * inline html\n       * <pre>  $scope.gridOptions.rowTemplate = '<div style=\"background-color: aquamarine\" ng-click=\"grid.appScope.fnOne(row)\" ng-repeat=\"col in colContainer.renderedColumns track by col.colDef.name\" class=\"ui-grid-cell\" ui-grid-cell></div>';</pre>\n       * or the id of a precompiled template (TBD how to use this) can be provided.\n       * </br>Refer to the custom row template tutorial for more information.\n       */\n      baseOptions.rowTemplate = baseOptions.rowTemplate || 'ui-grid/ui-grid-row';\n\n      /**\n       * @ngdoc object\n       * @name appScopeProvider\n       * @propertyOf ui.grid.class:GridOptions\n       * @description by default, the parent scope of the ui-grid element will be assigned to grid.appScope\n       * this property allows you to assign any reference you want to grid.appScope\n       */\n      baseOptions.appScopeProvider = baseOptions.appScopeProvider || null;\n\n      return baseOptions;\n    }\n  };\n\n\n}]);\n\n})();\n\n(function(){\n\nangular.module('ui.grid')\n\n  /**\n   * @ngdoc function\n   * @name ui.grid.class:GridRenderContainer\n   * @description The grid has render containers, allowing the ability to have pinned columns.  If the grid\n   * is right-to-left then there may be a right render container, if left-to-right then there may\n   * be a left render container.  There is always a body render container.\n   * @param {string} name The name of the render container ('body', 'left', or 'right')\n   * @param {Grid} grid the grid the render container is in\n   * @param {object} options the render container options\n   */\n.factory('GridRenderContainer', ['gridUtil', 'uiGridConstants', function(gridUtil, uiGridConstants) {\n  function GridRenderContainer(name, grid, options) {\n    var self = this;\n\n    // if (gridUtil.type(grid) !== 'Grid') {\n    //   throw new Error('Grid argument is not a Grid object');\n    // }\n\n    self.name = name;\n\n    self.grid = grid;\n\n    // self.rowCache = [];\n    // self.columnCache = [];\n\n    self.visibleRowCache = [];\n    self.visibleColumnCache = [];\n\n    self.renderedRows = [];\n    self.renderedColumns = [];\n\n    self.prevScrollTop = 0;\n    self.prevScrolltopPercentage = 0;\n    self.prevRowScrollIndex = 0;\n\n    self.prevScrollLeft = 0;\n    self.prevScrollleftPercentage = 0;\n    self.prevColumnScrollIndex = 0;\n\n    self.columnStyles = \"\";\n\n    self.viewportAdjusters = [];\n\n    /**\n     *  @ngdoc boolean\n     *  @name hasHScrollbar\n     *  @propertyOf  ui.grid.class:GridRenderContainer\n     *  @description flag to signal that container has a horizontal scrollbar\n     */\n    self.hasHScrollbar = false;\n\n    /**\n     *  @ngdoc boolean\n     *  @name hasVScrollbar\n     *  @propertyOf  ui.grid.class:GridRenderContainer\n     *  @description flag to signal that container has a vertical scrollbar\n     */\n    self.hasVScrollbar = false;\n\n    /**\n     *  @ngdoc boolean\n     *  @name canvasHeightShouldUpdate\n     *  @propertyOf  ui.grid.class:GridRenderContainer\n     *  @description flag to signal that container should recalculate the canvas size\n     */\n    self.canvasHeightShouldUpdate = true;\n\n    /**\n     *  @ngdoc boolean\n     *  @name canvasHeight\n     *  @propertyOf  ui.grid.class:GridRenderContainer\n     *  @description last calculated canvas height value\n     */\n    self.$$canvasHeight = 0;\n\n    if (options && angular.isObject(options)) {\n      angular.extend(self, options);\n    }\n\n    grid.registerStyleComputation({\n      priority: 5,\n      func: function () {\n        self.updateColumnWidths();\n        return self.columnStyles;\n      }\n    });\n  }\n\n\n  GridRenderContainer.prototype.reset = function reset() {\n    // this.rowCache.length = 0;\n    // this.columnCache.length = 0;\n\n    this.visibleColumnCache.length = 0;\n    this.visibleRowCache.length = 0;\n\n    this.renderedRows.length = 0;\n    this.renderedColumns.length = 0;\n  };\n\n  // TODO(c0bra): calculate size?? Should this be in a stackable directive?\n\n\n  GridRenderContainer.prototype.containsColumn = function (col) {\n     return this.visibleColumnCache.indexOf(col) !== -1;\n  };\n\n  GridRenderContainer.prototype.minRowsToRender = function minRowsToRender() {\n    var self = this;\n    var minRows = 0;\n    var rowAddedHeight = 0;\n    var viewPortHeight = self.getViewportHeight();\n    for (var i = self.visibleRowCache.length - 1; rowAddedHeight < viewPortHeight && i >= 0; i--) {\n      rowAddedHeight += self.visibleRowCache[i].height;\n      minRows++;\n    }\n    return minRows;\n  };\n\n  GridRenderContainer.prototype.minColumnsToRender = function minColumnsToRender() {\n    var self = this;\n    var viewportWidth = this.getViewportWidth();\n\n    var min = 0;\n    var totalWidth = 0;\n    // self.columns.forEach(function(col, i) {\n    for (var i = 0; i < self.visibleColumnCache.length; i++) {\n      var col = self.visibleColumnCache[i];\n\n      if (totalWidth < viewportWidth) {\n        totalWidth += col.drawnWidth ? col.drawnWidth : 0;\n        min++;\n      }\n      else {\n        var currWidth = 0;\n        for (var j = i; j >= i - min; j--) {\n          currWidth += self.visibleColumnCache[j].drawnWidth ? self.visibleColumnCache[j].drawnWidth : 0;\n        }\n        if (currWidth < viewportWidth) {\n          min++;\n        }\n      }\n    }\n\n    return min;\n  };\n\n  GridRenderContainer.prototype.getVisibleRowCount = function getVisibleRowCount() {\n    return this.visibleRowCache.length;\n  };\n\n  /**\n   * @ngdoc function\n   * @name registerViewportAdjuster\n   * @methodOf ui.grid.class:GridRenderContainer\n   * @description Registers an adjuster to the render container's available width or height.  Adjusters are used\n   * to tell the render container that there is something else consuming space, and to adjust it's size\n   * appropriately.\n   * @param {function} func the adjuster function we want to register\n   */\n\n  GridRenderContainer.prototype.registerViewportAdjuster = function registerViewportAdjuster(func) {\n    this.viewportAdjusters.push(func);\n  };\n\n  /**\n   * @ngdoc function\n   * @name removeViewportAdjuster\n   * @methodOf ui.grid.class:GridRenderContainer\n   * @description Removes an adjuster, should be used when your element is destroyed\n   * @param {function} func the adjuster function we want to remove\n   */\n  GridRenderContainer.prototype.removeViewportAdjuster = function removeViewportAdjuster(func) {\n    var idx = this.viewportAdjusters.indexOf(func);\n\n    if (idx > -1) {\n      this.viewportAdjusters.splice(idx, 1);\n    }\n  };\n\n  /**\n   * @ngdoc function\n   * @name getViewportAdjustment\n   * @methodOf ui.grid.class:GridRenderContainer\n   * @description Gets the adjustment based on the viewportAdjusters.\n   * @returns {object} a hash of { height: x, width: y }.  Usually the values will be negative\n   */\n  GridRenderContainer.prototype.getViewportAdjustment = function getViewportAdjustment() {\n    var self = this;\n\n    var adjustment = { height: 0, width: 0 };\n\n    self.viewportAdjusters.forEach(function (func) {\n      adjustment = func.call(this, adjustment);\n    });\n\n    return adjustment;\n  };\n\n  GridRenderContainer.prototype.getMargin = function getMargin(side) {\n    var self = this;\n\n    var amount = 0;\n\n    self.viewportAdjusters.forEach(function (func) {\n      var adjustment = func.call(this, { height: 0, width: 0 });\n\n      if (adjustment.side && adjustment.side === side) {\n        amount += adjustment.width * -1;\n      }\n    });\n\n    return amount;\n  };\n\n  GridRenderContainer.prototype.getViewportHeight = function getViewportHeight() {\n    var self = this;\n\n    var headerHeight = (self.headerHeight) ? self.headerHeight : self.grid.headerHeight;\n\n    var viewPortHeight = self.grid.gridHeight - headerHeight - self.grid.footerHeight;\n\n\n    var adjustment = self.getViewportAdjustment();\n\n    viewPortHeight = viewPortHeight + adjustment.height;\n\n    return viewPortHeight;\n  };\n\n  GridRenderContainer.prototype.getViewportWidth = function getViewportWidth() {\n    var self = this;\n\n    var viewportWidth = self.grid.gridWidth;\n\n    //if (typeof(self.grid.verticalScrollbarWidth) !== 'undefined' && self.grid.verticalScrollbarWidth !== undefined && self.grid.verticalScrollbarWidth > 0) {\n    //  viewPortWidth = viewPortWidth - self.grid.verticalScrollbarWidth;\n    //}\n\n    // var viewportWidth = 0;\\\n    // self.visibleColumnCache.forEach(function (column) {\n    //   viewportWidth += column.drawnWidth;\n    // });\n\n    var adjustment = self.getViewportAdjustment();\n\n    viewportWidth = viewportWidth + adjustment.width;\n\n    return viewportWidth;\n  };\n\n  GridRenderContainer.prototype.getHeaderViewportWidth = function getHeaderViewportWidth() {\n    var self = this;\n\n    var viewportWidth = this.getViewportWidth();\n\n    //if (typeof(self.grid.verticalScrollbarWidth) !== 'undefined' && self.grid.verticalScrollbarWidth !== undefined && self.grid.verticalScrollbarWidth > 0) {\n    //  viewPortWidth = viewPortWidth + self.grid.verticalScrollbarWidth;\n    //}\n\n    // var adjustment = self.getViewportAdjustment();\n    // viewPortWidth = viewPortWidth + adjustment.width;\n\n    return viewportWidth;\n  };\n\n\n  /**\n   * @ngdoc function\n   * @name getCanvasHeight\n   * @methodOf ui.grid.class:GridRenderContainer\n   * @description Returns the total canvas height.   Only recalculates if canvasHeightShouldUpdate = false\n   * @returns {number} total height of all the visible rows in the container\n   */\n  GridRenderContainer.prototype.getCanvasHeight = function getCanvasHeight() {\n    var self = this;\n\n    if (!self.canvasHeightShouldUpdate) {\n      return self.$$canvasHeight;\n    }\n\n    var oldCanvasHeight = self.$$canvasHeight;\n\n    self.$$canvasHeight =  0;\n\n    self.visibleRowCache.forEach(function(row){\n      self.$$canvasHeight += row.height;\n    });\n\n\n    self.canvasHeightShouldUpdate = false;\n\n    self.grid.api.core.raise.canvasHeightChanged(oldCanvasHeight, self.$$canvasHeight);\n\n    return self.$$canvasHeight;\n  };\n\n  GridRenderContainer.prototype.getVerticalScrollLength = function getVerticalScrollLength() {\n    return this.getCanvasHeight() - this.getViewportHeight() + this.grid.scrollbarHeight;\n  };\n\n  GridRenderContainer.prototype.getHorizontalScrollLength = function getHorizontalScrollLength() {\n    return this.getCanvasWidth() - this.getViewportWidth() + this.grid.scrollbarWidth;\n  };\n\n  GridRenderContainer.prototype.getCanvasWidth = function getCanvasWidth() {\n    var self = this;\n\n    var ret = self.canvasWidth;\n\n    return ret;\n  };\n\n  GridRenderContainer.prototype.setRenderedRows = function setRenderedRows(newRows) {\n    this.renderedRows.length = newRows.length;\n    for (var i = 0; i < newRows.length; i++) {\n      this.renderedRows[i] = newRows[i];\n    }\n  };\n\n  GridRenderContainer.prototype.setRenderedColumns = function setRenderedColumns(newColumns) {\n    var self = this;\n\n    // OLD:\n    this.renderedColumns.length = newColumns.length;\n    for (var i = 0; i < newColumns.length; i++) {\n      this.renderedColumns[i] = newColumns[i];\n    }\n\n    this.updateColumnOffset();\n  };\n\n  GridRenderContainer.prototype.updateColumnOffset = function updateColumnOffset() {\n    // Calculate the width of the columns on the left side that are no longer rendered.\n    //  That will be the offset for the columns as we scroll horizontally.\n    var hiddenColumnsWidth = 0;\n    for (var i = 0; i < this.currentFirstColumn; i++) {\n      hiddenColumnsWidth += this.visibleColumnCache[i].drawnWidth;\n    }\n\n    this.columnOffset = hiddenColumnsWidth;\n  };\n\n  GridRenderContainer.prototype.scrollVertical = function (newScrollTop) {\n    var vertScrollPercentage = -1;\n\n    if (newScrollTop !== this.prevScrollTop) {\n      var yDiff = newScrollTop - this.prevScrollTop;\n\n      if (yDiff > 0 ) { this.grid.scrollDirection = uiGridConstants.scrollDirection.DOWN; }\n      if (yDiff < 0 ) { this.grid.scrollDirection = uiGridConstants.scrollDirection.UP; }\n\n      var vertScrollLength = this.getVerticalScrollLength();\n\n      vertScrollPercentage = newScrollTop / vertScrollLength;\n\n      // console.log('vert', vertScrollPercentage, newScrollTop, vertScrollLength);\n\n      if (vertScrollPercentage > 1) { vertScrollPercentage = 1; }\n      if (vertScrollPercentage < 0) { vertScrollPercentage = 0; }\n\n      this.adjustScrollVertical(newScrollTop, vertScrollPercentage);\n      return vertScrollPercentage;\n    }\n  };\n\n  GridRenderContainer.prototype.scrollHorizontal = function(newScrollLeft){\n    var horizScrollPercentage = -1;\n\n    // Handle RTL here\n\n    if (newScrollLeft !== this.prevScrollLeft) {\n      var xDiff = newScrollLeft - this.prevScrollLeft;\n\n      if (xDiff > 0) { this.grid.scrollDirection = uiGridConstants.scrollDirection.RIGHT; }\n      if (xDiff < 0) { this.grid.scrollDirection = uiGridConstants.scrollDirection.LEFT; }\n\n      var horizScrollLength = this.getHorizontalScrollLength();\n      if (horizScrollLength !== 0) {\n        horizScrollPercentage = newScrollLeft / horizScrollLength;\n      }\n      else {\n        horizScrollPercentage = 0;\n      }\n\n      this.adjustScrollHorizontal(newScrollLeft, horizScrollPercentage);\n      return horizScrollPercentage;\n    }\n  };\n\n  GridRenderContainer.prototype.adjustScrollVertical = function adjustScrollVertical(scrollTop, scrollPercentage, force) {\n    if (this.prevScrollTop === scrollTop && !force) {\n      return;\n    }\n\n    if (typeof(scrollTop) === 'undefined' || scrollTop === undefined || scrollTop === null) {\n      scrollTop = (this.getCanvasHeight() - this.getViewportHeight()) * scrollPercentage;\n    }\n\n    this.adjustRows(scrollTop, scrollPercentage, false);\n\n    this.prevScrollTop = scrollTop;\n    this.prevScrolltopPercentage = scrollPercentage;\n\n    this.grid.queueRefresh();\n  };\n\n  GridRenderContainer.prototype.adjustScrollHorizontal = function adjustScrollHorizontal(scrollLeft, scrollPercentage, force) {\n    if (this.prevScrollLeft === scrollLeft && !force) {\n      return;\n    }\n\n    if (typeof(scrollLeft) === 'undefined' || scrollLeft === undefined || scrollLeft === null) {\n      scrollLeft = (this.getCanvasWidth() - this.getViewportWidth()) * scrollPercentage;\n    }\n\n    this.adjustColumns(scrollLeft, scrollPercentage);\n\n    this.prevScrollLeft = scrollLeft;\n    this.prevScrollleftPercentage = scrollPercentage;\n\n    this.grid.queueRefresh();\n  };\n\n  GridRenderContainer.prototype.adjustRows = function adjustRows(scrollTop, scrollPercentage, postDataLoaded) {\n    var self = this;\n\n    var minRows = self.minRowsToRender();\n\n    var rowCache = self.visibleRowCache;\n\n    var maxRowIndex = rowCache.length - minRows;\n\n    // console.log('scroll%1', scrollPercentage);\n\n    // Calculate the scroll percentage according to the scrollTop location, if no percentage was provided\n    if ((typeof(scrollPercentage) === 'undefined' || scrollPercentage === null) && scrollTop) {\n      scrollPercentage = scrollTop / self.getVerticalScrollLength();\n    }\n\n    var rowIndex = Math.ceil(Math.min(maxRowIndex, maxRowIndex * scrollPercentage));\n\n    // console.log('maxRowIndex / scroll%', maxRowIndex, scrollPercentage, rowIndex);\n\n    // Define a max row index that we can't scroll past\n    if (rowIndex > maxRowIndex) {\n      rowIndex = maxRowIndex;\n    }\n\n    var newRange = [];\n    if (rowCache.length > self.grid.options.virtualizationThreshold) {\n      if (!(typeof(scrollTop) === 'undefined' || scrollTop === null)) {\n        // Have we hit the threshold going down?\n        if ( !self.grid.suppressParentScrollDown && self.prevScrollTop < scrollTop && rowIndex < self.prevRowScrollIndex + self.grid.options.scrollThreshold && rowIndex < maxRowIndex) {\n          return;\n        }\n        //Have we hit the threshold going up?\n        if ( !self.grid.suppressParentScrollUp && self.prevScrollTop > scrollTop && rowIndex > self.prevRowScrollIndex - self.grid.options.scrollThreshold && rowIndex < maxRowIndex) {\n          return;\n        }\n      }\n      var rangeStart = {};\n      var rangeEnd = {};\n\n      rangeStart = Math.max(0, rowIndex - self.grid.options.excessRows);\n      rangeEnd = Math.min(rowCache.length, rowIndex + minRows + self.grid.options.excessRows);\n\n      newRange = [rangeStart, rangeEnd];\n    }\n    else {\n      var maxLen = self.visibleRowCache.length;\n      newRange = [0, Math.max(maxLen, minRows + self.grid.options.excessRows)];\n    }\n\n    self.updateViewableRowRange(newRange);\n\n    self.prevRowScrollIndex = rowIndex;\n  };\n\n  GridRenderContainer.prototype.adjustColumns = function adjustColumns(scrollLeft, scrollPercentage) {\n    var self = this;\n\n    var minCols = self.minColumnsToRender();\n\n    var columnCache = self.visibleColumnCache;\n    var maxColumnIndex = columnCache.length - minCols;\n\n    // Calculate the scroll percentage according to the scrollLeft location, if no percentage was provided\n    if ((typeof(scrollPercentage) === 'undefined' || scrollPercentage === null) && scrollLeft) {\n      scrollPercentage = scrollLeft / self.getHorizontalScrollLength();\n    }\n\n    var colIndex = Math.ceil(Math.min(maxColumnIndex, maxColumnIndex * scrollPercentage));\n\n    // Define a max row index that we can't scroll past\n    if (colIndex > maxColumnIndex) {\n      colIndex = maxColumnIndex;\n    }\n\n    var newRange = [];\n    if (columnCache.length > self.grid.options.columnVirtualizationThreshold && self.getCanvasWidth() > self.getViewportWidth()) {\n      /* Commented the following lines because otherwise the moved column wasn't visible immediately on the new position\n       * in the case of many columns with horizontal scroll, one had to scroll left or right and then return in order to see it\n      // Have we hit the threshold going down?\n      if (self.prevScrollLeft < scrollLeft && colIndex < self.prevColumnScrollIndex + self.grid.options.horizontalScrollThreshold && colIndex < maxColumnIndex) {\n        return;\n      }\n      //Have we hit the threshold going up?\n      if (self.prevScrollLeft > scrollLeft && colIndex > self.prevColumnScrollIndex - self.grid.options.horizontalScrollThreshold && colIndex < maxColumnIndex) {\n        return;\n      }*/\n\n      var rangeStart = Math.max(0, colIndex - self.grid.options.excessColumns);\n      var rangeEnd = Math.min(columnCache.length, colIndex + minCols + self.grid.options.excessColumns);\n\n      newRange = [rangeStart, rangeEnd];\n    }\n    else {\n      var maxLen = self.visibleColumnCache.length;\n\n      newRange = [0, Math.max(maxLen, minCols + self.grid.options.excessColumns)];\n    }\n\n    self.updateViewableColumnRange(newRange);\n\n    self.prevColumnScrollIndex = colIndex;\n  };\n\n  // Method for updating the visible rows\n  GridRenderContainer.prototype.updateViewableRowRange = function updateViewableRowRange(renderedRange) {\n    // Slice out the range of rows from the data\n    // var rowArr = uiGridCtrl.grid.rows.slice(renderedRange[0], renderedRange[1]);\n    var rowArr = this.visibleRowCache.slice(renderedRange[0], renderedRange[1]);\n\n    // Define the top-most rendered row\n    this.currentTopRow = renderedRange[0];\n\n    this.setRenderedRows(rowArr);\n  };\n\n  // Method for updating the visible columns\n  GridRenderContainer.prototype.updateViewableColumnRange = function updateViewableColumnRange(renderedRange) {\n    // Slice out the range of rows from the data\n    // var columnArr = uiGridCtrl.grid.columns.slice(renderedRange[0], renderedRange[1]);\n    var columnArr = this.visibleColumnCache.slice(renderedRange[0], renderedRange[1]);\n\n    // Define the left-most rendered columns\n    this.currentFirstColumn = renderedRange[0];\n\n    this.setRenderedColumns(columnArr);\n  };\n\n  GridRenderContainer.prototype.headerCellWrapperStyle = function () {\n    var self = this;\n\n    if (self.currentFirstColumn !== 0) {\n      var offset = self.columnOffset;\n\n      if (self.grid.isRTL()) {\n        return { 'margin-right': offset + 'px' };\n      }\n      else {\n        return { 'margin-left': offset + 'px' };\n      }\n    }\n\n    return null;\n  };\n\n    /**\n     *  @ngdoc boolean\n     *  @name updateColumnWidths\n     *  @propertyOf  ui.grid.class:GridRenderContainer\n     *  @description Determine the appropriate column width of each column across all render containers.\n     *\n     *  Column width is easy when each column has a specified width.  When columns are variable width (i.e.\n     *  have an * or % of the viewport) then we try to calculate so that things fit in.  The problem is that\n     *  we have multiple render containers, and we don't want one render container to just take the whole viewport\n     *  when it doesn't need to - we want things to balance out across the render containers.\n     *\n     *  To do this, we use this method to calculate all the renderContainers, recognising that in a given render\n     *  cycle it'll get called once per render container, so it needs to return the same values each time.\n     *\n     *  The constraints on this method are therefore:\n     *  - must return the same value when called multiple times, to do this it needs to rely on properties of the\n     *    columns, but not properties that change when this is called (so it shouldn't rely on drawnWidth)\n     *\n     *  The general logic of this method is:\n     *  - calculate our total available width\n     *  - look at all the columns across all render containers, and work out which have widths and which have\n     *    constraints such as % or * or something else\n     *  - for those with *, count the total number of * we see and add it onto a running total, add this column to an * array\n     *  - for those with a %, allocate the % as a percentage of the viewport, having consideration of min and max\n     *  - for those with manual width (in pixels) we set the drawnWidth to the specified width\n     *  - we end up with an asterisks array still to process\n     *  - we look at our remaining width.  If it's greater than zero, we divide it up among the asterisk columns, then process\n     *    them for min and max width constraints\n     *  - if it's zero or less, we set the asterisk columns to their minimum widths\n     *  - we use parseInt quite a bit, as we try to make all our column widths integers\n     */\n  GridRenderContainer.prototype.updateColumnWidths = function () {\n    var self = this;\n\n    var asterisksArray = [],\n        asteriskNum = 0,\n        usedWidthSum = 0,\n        ret = '';\n\n    // Get the width of the viewport\n    var availableWidth = self.grid.getViewportWidth() - self.grid.scrollbarWidth;\n\n    // get all the columns across all render containers, we have to calculate them all or one render container\n    // could consume the whole viewport\n    var columnCache = [];\n    angular.forEach(self.grid.renderContainers, function( container, name){\n      columnCache = columnCache.concat(container.visibleColumnCache);\n    });\n\n    // look at each column, process any manual values or %, put the * into an array to look at later\n    columnCache.forEach(function(column, i) {\n      var width = 0;\n      // Skip hidden columns\n      if (!column.visible) { return; }\n\n      if (angular.isNumber(column.width)) {\n        // pixel width, set to this value\n        width = parseInt(column.width, 10);\n        usedWidthSum = usedWidthSum + width;\n        column.drawnWidth = width;\n\n      } else if (gridUtil.endsWith(column.width, \"%\")) {\n        // percentage width, set to percentage of the viewport\n        width = parseInt(parseInt(column.width.replace(/%/g, ''), 10) / 100 * availableWidth);\n\n        if ( width > column.maxWidth ){\n          width = column.maxWidth;\n        }\n\n        if ( width < column.minWidth ){\n          width = column.minWidth;\n        }\n\n        usedWidthSum = usedWidthSum + width;\n        column.drawnWidth = width;\n      } else if (angular.isString(column.width) && column.width.indexOf('*') !== -1) {\n        // is an asterisk column, the gridColumn already checked the string consists only of '****'\n        asteriskNum = asteriskNum + column.width.length;\n        asterisksArray.push(column);\n      }\n    });\n\n    // Get the remaining width (available width subtracted by the used widths sum)\n    var remainingWidth = availableWidth - usedWidthSum;\n\n    var i, column, colWidth;\n\n    if (asterisksArray.length > 0) {\n      // the width that each asterisk value would be assigned (this can be negative)\n      var asteriskVal = remainingWidth / asteriskNum;\n\n      asterisksArray.forEach(function( column ){\n        var width = parseInt(column.width.length * asteriskVal, 10);\n\n        if ( width > column.maxWidth ){\n          width = column.maxWidth;\n        }\n\n        if ( width < column.minWidth ){\n          width = column.minWidth;\n        }\n\n        usedWidthSum = usedWidthSum + width;\n        column.drawnWidth = width;\n      });\n    }\n\n    // If the grid width didn't divide evenly into the column widths and we have pixels left over, or our\n    // calculated widths would have the grid narrower than the available space,\n    // dole the remainder out one by one to make everything fit\n    var processColumnUpwards = function(column){\n      if ( column.drawnWidth < column.maxWidth && leftoverWidth > 0) {\n        column.drawnWidth++;\n        usedWidthSum++;\n        leftoverWidth--;\n        columnsToChange = true;\n      }\n    };\n\n    var leftoverWidth = availableWidth - usedWidthSum;\n    var columnsToChange = true;\n\n    while (leftoverWidth > 0 && columnsToChange) {\n      columnsToChange = false;\n      asterisksArray.forEach(processColumnUpwards);\n    }\n\n    // We can end up with too much width even though some columns aren't at their max width, in this situation\n    // we can trim the columns a little\n    var processColumnDownwards = function(column){\n      if ( column.drawnWidth > column.minWidth && excessWidth > 0) {\n        column.drawnWidth--;\n        usedWidthSum--;\n        excessWidth--;\n        columnsToChange = true;\n      }\n    };\n\n    var excessWidth =  usedWidthSum - availableWidth;\n    columnsToChange = true;\n\n    while (excessWidth > 0 && columnsToChange) {\n      columnsToChange = false;\n      asterisksArray.forEach(processColumnDownwards);\n    }\n\n\n    // all that was across all the renderContainers, now we need to work out what that calculation decided for\n    // our renderContainer\n    var canvasWidth = 0;\n    self.visibleColumnCache.forEach(function(column){\n      if ( column.visible ){\n        canvasWidth = canvasWidth + column.drawnWidth;\n      }\n    });\n\n    // Build the CSS\n    columnCache.forEach(function (column) {\n      ret = ret + column.getColClassDefinition();\n    });\n\n    self.canvasWidth = canvasWidth;\n\n    // Return the styles back to buildStyles which pops them into the `customStyles` scope variable\n    // return ret;\n\n    // Set this render container's column styles so they can be used in style computation\n    this.columnStyles = ret;\n  };\n\n  GridRenderContainer.prototype.needsHScrollbarPlaceholder = function () {\n    return this.grid.options.enableHorizontalScrollbar && !this.hasHScrollbar && !this.grid.disableScrolling;\n  };\n\n  GridRenderContainer.prototype.getViewportStyle = function () {\n    var self = this;\n    var styles = {};\n\n    self.hasHScrollbar = false;\n    self.hasVScrollbar = false;\n\n    if (self.grid.disableScrolling) {\n      styles['overflow-x'] = 'hidden';\n      styles['overflow-y'] = 'hidden';\n      return styles;\n    }\n\n    if (self.name === 'body') {\n      self.hasHScrollbar = self.grid.options.enableHorizontalScrollbar !== uiGridConstants.scrollbars.NEVER;\n      if (!self.grid.isRTL()) {\n        if (!self.grid.hasRightContainerColumns()) {\n          self.hasVScrollbar = self.grid.options.enableVerticalScrollbar !== uiGridConstants.scrollbars.NEVER;\n        }\n      }\n      else {\n        if (!self.grid.hasLeftContainerColumns()) {\n          self.hasVScrollbar = self.grid.options.enableVerticalScrollbar !== uiGridConstants.scrollbars.NEVER;\n        }\n      }\n    }\n    else if (self.name === 'left') {\n      self.hasVScrollbar = self.grid.isRTL() ? self.grid.options.enableVerticalScrollbar !== uiGridConstants.scrollbars.NEVER : false;\n    }\n    else {\n      self.hasVScrollbar = !self.grid.isRTL() ? self.grid.options.enableVerticalScrollbar !== uiGridConstants.scrollbars.NEVER : false;\n    }\n\n    styles['overflow-x'] = self.hasHScrollbar ? 'scroll' : 'hidden';\n    styles['overflow-y'] = self.hasVScrollbar ? 'scroll' : 'hidden';\n\n\n    return styles;\n\n\n  };\n\n  return GridRenderContainer;\n}]);\n\n})();\n\n(function(){\n\nangular.module('ui.grid')\n.factory('GridRow', ['gridUtil', 'uiGridConstants', function(gridUtil, uiGridConstants) {\n\n   /**\n   * @ngdoc function\n   * @name ui.grid.class:GridRow\n   * @description GridRow is the viewModel for one logical row on the grid.  A grid Row is not necessarily a one-to-one\n   * relation to gridOptions.data.\n   * @param {object} entity the array item from GridOptions.data\n   * @param {number} index the current position of the row in the array\n   * @param {Grid} reference to the parent grid\n   */\n  function GridRow(entity, index, grid) {\n\n     /**\n      *  @ngdoc object\n      *  @name grid\n      *  @propertyOf  ui.grid.class:GridRow\n      *  @description A reference back to the grid\n      */\n     this.grid = grid;\n\n     /**\n      *  @ngdoc object\n      *  @name entity\n      *  @propertyOf  ui.grid.class:GridRow\n      *  @description A reference to an item in gridOptions.data[]\n      */\n    this.entity = entity;\n\n     /**\n      *  @ngdoc object\n      *  @name uid\n      *  @propertyOf  ui.grid.class:GridRow\n      *  @description  UniqueId of row\n      */\n     this.uid = gridUtil.nextUid();\n\n     /**\n      *  @ngdoc object\n      *  @name visible\n      *  @propertyOf  ui.grid.class:GridRow\n      *  @description If true, the row will be rendered\n      */\n    // Default to true\n    this.visible = true;\n\n\n    this.$$height = grid.options.rowHeight;\n\n  }\n\n    /**\n     *  @ngdoc object\n     *  @name height\n     *  @propertyOf  ui.grid.class:GridRow\n     *  @description height of each individual row. changing the height will flag all\n     *  row renderContainers to recalculate their canvas height\n     */\n    Object.defineProperty(GridRow.prototype, 'height', {\n      get: function() {\n        return this.$$height;\n      },\n      set: function(height) {\n        if (height !== this.$$height) {\n          this.grid.updateCanvasHeight();\n          this.$$height = height;\n        }\n      }\n    });\n\n  /**\n   * @ngdoc function\n   * @name getQualifiedColField\n   * @methodOf ui.grid.class:GridRow\n   * @description returns the qualified field name as it exists on scope\n   * ie: row.entity.fieldA\n   * @param {GridCol} col column instance\n   * @returns {string} resulting name that can be evaluated on scope\n   */\n    GridRow.prototype.getQualifiedColField = function(col) {\n      return 'row.' + this.getEntityQualifiedColField(col);\n    };\n\n    /**\n     * @ngdoc function\n     * @name getEntityQualifiedColField\n     * @methodOf ui.grid.class:GridRow\n     * @description returns the qualified field name minus the row path\n     * ie: entity.fieldA\n     * @param {GridCol} col column instance\n     * @returns {string} resulting name that can be evaluated against a row\n     */\n  GridRow.prototype.getEntityQualifiedColField = function(col) {\n    var base = 'entity';\n    if ( col.field === uiGridConstants.ENTITY_BINDING ) {\n      return base;\n    }\n    return gridUtil.preEval(base + '.' + col.field);\n  };\n  \n  \n  /**\n   * @ngdoc function\n   * @name setRowInvisible\n   * @methodOf  ui.grid.class:GridRow\n   * @description Sets an override on the row that forces it to always\n   * be invisible. Emits the rowsVisibleChanged event if it changed the row visibility.\n   * \n   * This method can be called from the api, passing in the gridRow we want\n   * altered.  It should really work by calling gridRow.setRowInvisible, but that's\n   * not the way I coded it, and too late to change now.  Changed to just call\n   * the internal function row.setThisRowInvisible().\n   * \n   * @param {GridRow} row the row we want to set to invisible\n   * \n   */\n  GridRow.prototype.setRowInvisible = function ( row ) {\n    if (row && row.setThisRowInvisible){\n      row.setThisRowInvisible( 'user' );\n    }\n  };\n  \n  \n  /**\n   * @ngdoc function\n   * @name clearRowInvisible\n   * @methodOf  ui.grid.class:GridRow\n   * @description Clears an override on the row that forces it to always\n   * be invisible. Emits the rowsVisibleChanged event if it changed the row visibility.\n   * \n   * This method can be called from the api, passing in the gridRow we want\n   * altered.  It should really work by calling gridRow.clearRowInvisible, but that's\n   * not the way I coded it, and too late to change now.  Changed to just call\n   * the internal function row.clearThisRowInvisible().\n   * \n   * @param {GridRow} row the row we want to clear the invisible flag\n   * \n   */\n  GridRow.prototype.clearRowInvisible = function ( row ) {\n    if (row && row.clearThisRowInvisible){\n      row.clearThisRowInvisible( 'user' );\n    }\n  };\n  \n  \n  /**\n   * @ngdoc function\n   * @name setThisRowInvisible\n   * @methodOf  ui.grid.class:GridRow\n   * @description Sets an override on the row that forces it to always\n   * be invisible. Emits the rowsVisibleChanged event if it changed the row visibility\n   *\n   * @param {string} reason the reason (usually the module) for the row to be invisible.\n   * E.g. grouping, user, filter\n   * @param {boolean} fromRowsProcessor whether we were called from a rowsProcessor, passed through to evaluateRowVisibility\n   */\n  GridRow.prototype.setThisRowInvisible = function ( reason, fromRowsProcessor ) {\n    if ( !this.invisibleReason ){\n      this.invisibleReason = {};\n    }\n    this.invisibleReason[reason] = true;\n    this.evaluateRowVisibility( fromRowsProcessor);\n  };\n\n\n  /**\n   * @ngdoc function\n   * @name clearRowInvisible\n   * @methodOf ui.grid.class:GridRow\n   * @description Clears any override on the row visibility, returning it \n   * to normal visibility calculations.  Emits the rowsVisibleChanged\n   * event\n   * \n   * @param {string} reason the reason (usually the module) for the row to be invisible.\n   * E.g. grouping, user, filter\n   * @param {boolean} fromRowsProcessor whether we were called from a rowsProcessor, passed through to evaluateRowVisibility\n   */\n  GridRow.prototype.clearThisRowInvisible = function ( reason, fromRowsProcessor ) {\n    if (typeof(this.invisibleReason) !== 'undefined' ) {\n      delete this.invisibleReason[reason];\n    }\n    this.evaluateRowVisibility( fromRowsProcessor );\n  };\n\n\n  /**\n   * @ngdoc function\n   * @name evaluateRowVisibility\n   * @methodOf ui.grid.class:GridRow\n   * @description Determines whether the row should be visible based on invisibleReason, \n   * and if it changes the row visibility, then emits the rowsVisibleChanged event.\n   * \n   * Queues a grid refresh, but doesn't call it directly to avoid hitting lots of grid refreshes.\n   * @param {boolean} fromRowProcessor if true, then it won't raise events or queue the refresh, the\n   * row processor does that already\n   */\n  GridRow.prototype.evaluateRowVisibility = function ( fromRowProcessor ) {\n    var newVisibility = true;\n    if ( typeof(this.invisibleReason) !== 'undefined' ){\n      angular.forEach(this.invisibleReason, function( value, key ){\n        if ( value ){\n          newVisibility = false;\n        }\n      });\n    }\n    \n    if ( typeof(this.visible) === 'undefined' || this.visible !== newVisibility ){\n      this.visible = newVisibility;\n      if ( !fromRowProcessor ){\n        this.grid.queueGridRefresh();\n        this.grid.api.core.raise.rowsVisibleChanged(this);\n      }\n    }\n  };\n  \n\n  return GridRow;\n}]);\n\n})();\n\n(function(){\n  'use strict';\n  /**\n   * @ngdoc object\n   * @name ui.grid.class:GridRowColumn\n   * @param {GridRow} row The row for this pair\n   * @param {GridColumn} column The column for this pair\n   * @description A row and column pair that represents the intersection of these two entities.\n   * Must be instantiated as a constructor using the `new` keyword.\n   */\n  angular.module('ui.grid')\n  .factory('GridRowColumn', ['$parse', '$filter',\n    function GridRowColumnFactory($parse, $filter){\n      var GridRowColumn = function GridRowColumn(row, col) {\n        if ( !(this instanceof GridRowColumn)){\n          throw \"Using GridRowColumn as a function insead of as a constructor. Must be called with `new` keyword\";\n        }\n\n        /**\n         * @ngdoc object\n         * @name row\n         * @propertyOf ui.grid.class:GridRowColumn\n         * @description {@link ui.grid.class:GridRow }\n         */\n        this.row = row;\n        /**\n         * @ngdoc object\n         * @name col\n         * @propertyOf ui.grid.class:GridRowColumn\n         * @description {@link ui.grid.class:GridColumn }\n         */\n        this.col = col;\n      };\n\n      /**\n       * @ngdoc function\n       * @name getIntersectionValueRaw\n       * @methodOf ui.grid.class:GridRowColumn\n       * @description Gets the intersection of where the row and column meet.\n       * @returns {String|Number|Object} The value from the grid data that this GridRowColumn points too.\n       *          If the column has a cellFilter this will NOT return the filtered value.\n       */\n      GridRowColumn.prototype.getIntersectionValueRaw = function(){\n        var getter = $parse(this.row.getEntityQualifiedColField(this.col));\n        var context = this.row;\n        return getter(context);\n      };\n      return GridRowColumn;\n    }\n  ]);\n})();\n\n(function () {\n  angular.module('ui.grid')\n    .factory('ScrollEvent', ['gridUtil', function (gridUtil) {\n\n      /**\n       * @ngdoc function\n       * @name ui.grid.class:ScrollEvent\n       * @description Model for all scrollEvents\n       * @param {Grid} grid that owns the scroll event\n       * @param {GridRenderContainer} sourceRowContainer that owns the scroll event. Can be null\n       * @param {GridRenderContainer} sourceColContainer that owns the scroll event. Can be null\n       * @param {string} source the source of the event - from uiGridConstants.scrollEventSources or a string value of directive/service/factory.functionName\n       */\n      function ScrollEvent(grid, sourceRowContainer, sourceColContainer, source) {\n        var self = this;\n        if (!grid) {\n          throw new Error(\"grid argument is required\");\n        }\n\n        /**\n         *  @ngdoc object\n         *  @name grid\n         *  @propertyOf  ui.grid.class:ScrollEvent\n         *  @description A reference back to the grid\n         */\n         self.grid = grid;\n\n\n\n        /**\n         *  @ngdoc object\n         *  @name source\n         *  @propertyOf  ui.grid.class:ScrollEvent\n         *  @description the source of the scroll event. limited to values from uiGridConstants.scrollEventSources\n         */\n        self.source = source;\n\n\n        /**\n         *  @ngdoc object\n         *  @name noDelay\n         *  @propertyOf  ui.grid.class:ScrollEvent\n         *  @description most scroll events from the mouse or trackpad require delay to operate properly\n         *  set to false to eliminate delay.  Useful for scroll events that the grid causes, such as scrolling to make a row visible.\n         */\n        self.withDelay = true;\n\n        self.sourceRowContainer = sourceRowContainer;\n        self.sourceColContainer = sourceColContainer;\n\n        self.newScrollLeft = null;\n        self.newScrollTop = null;\n        self.x = null;\n        self.y = null;\n\n        self.verticalScrollLength = -9999999;\n        self.horizontalScrollLength = -999999;\n\n\n        /**\n         *  @ngdoc function\n         *  @name fireThrottledScrollingEvent\n         *  @methodOf  ui.grid.class:ScrollEvent\n         *  @description fires a throttled event using grid.api.core.raise.scrollEvent\n         */\n        self.fireThrottledScrollingEvent = gridUtil.throttle(function(sourceContainerId) {\n          self.grid.scrollContainers(sourceContainerId, self);\n        }, self.grid.options.wheelScrollThrottle, {trailing: true});\n\n      }\n\n\n      /**\n       *  @ngdoc function\n       *  @name getNewScrollLeft\n       *  @methodOf  ui.grid.class:ScrollEvent\n       *  @description returns newScrollLeft property if available; calculates a new value if it isn't\n       */\n      ScrollEvent.prototype.getNewScrollLeft = function(colContainer, viewport){\n        var self = this;\n\n        if (!self.newScrollLeft){\n          var scrollWidth = (colContainer.getCanvasWidth() - colContainer.getViewportWidth());\n\n          var oldScrollLeft = gridUtil.normalizeScrollLeft(viewport, self.grid);\n\n          var scrollXPercentage;\n          if (typeof(self.x.percentage) !== 'undefined' && self.x.percentage !== undefined) {\n            scrollXPercentage = self.x.percentage;\n          }\n          else if (typeof(self.x.pixels) !== 'undefined' && self.x.pixels !== undefined) {\n            scrollXPercentage = self.x.percentage = (oldScrollLeft + self.x.pixels) / scrollWidth;\n          }\n          else {\n            throw new Error(\"No percentage or pixel value provided for scroll event X axis\");\n          }\n\n          return Math.max(0, scrollXPercentage * scrollWidth);\n        }\n\n        return self.newScrollLeft;\n      };\n\n\n      /**\n       *  @ngdoc function\n       *  @name getNewScrollTop\n       *  @methodOf  ui.grid.class:ScrollEvent\n       *  @description returns newScrollTop property if available; calculates a new value if it isn't\n       */\n      ScrollEvent.prototype.getNewScrollTop = function(rowContainer, viewport){\n        var self = this;\n\n\n        if (!self.newScrollTop){\n          var scrollLength = rowContainer.getVerticalScrollLength();\n\n          var oldScrollTop = viewport[0].scrollTop;\n\n          var scrollYPercentage;\n          if (typeof(self.y.percentage) !== 'undefined' && self.y.percentage !== undefined) {\n            scrollYPercentage = self.y.percentage;\n          }\n          else if (typeof(self.y.pixels) !== 'undefined' && self.y.pixels !== undefined) {\n            scrollYPercentage = self.y.percentage = (oldScrollTop + self.y.pixels) / scrollLength;\n          }\n          else {\n            throw new Error(\"No percentage or pixel value provided for scroll event Y axis\");\n          }\n\n          return Math.max(0, scrollYPercentage * scrollLength);\n        }\n\n        return self.newScrollTop;\n      };\n\n      ScrollEvent.prototype.atTop = function(scrollTop) {\n        return (this.y && (this.y.percentage === 0 || this.verticalScrollLength < 0) && scrollTop === 0);\n      };\n\n      ScrollEvent.prototype.atBottom = function(scrollTop) {\n        return (this.y && (this.y.percentage === 1 || this.verticalScrollLength === 0) && scrollTop > 0);\n      };\n\n      ScrollEvent.prototype.atLeft = function(scrollLeft) {\n        return (this.x && (this.x.percentage === 0 || this.horizontalScrollLength < 0) && scrollLeft === 0);\n      };\n\n      ScrollEvent.prototype.atRight = function(scrollLeft) {\n        return (this.x && (this.x.percentage === 1 || this.horizontalScrollLength ===0) && scrollLeft > 0);\n      };\n\n\n      ScrollEvent.Sources = {\n        ViewPortScroll: 'ViewPortScroll',\n        RenderContainerMouseWheel: 'RenderContainerMouseWheel',\n        RenderContainerTouchMove: 'RenderContainerTouchMove',\n        Other: 99\n      };\n\n      return ScrollEvent;\n    }]);\n\n\n\n})();\n\n(function () {\n  'use strict';\n  /**\n   *  @ngdoc object\n   *  @name ui.grid.service:gridClassFactory\n   *\n   *  @description factory to return dom specific instances of a grid\n   *\n   */\n  angular.module('ui.grid').service('gridClassFactory', ['gridUtil', '$q', '$compile', '$templateCache', 'uiGridConstants', 'Grid', 'GridColumn', 'GridRow',\n    function (gridUtil, $q, $compile, $templateCache, uiGridConstants, Grid, GridColumn, GridRow) {\n\n      var service = {\n        /**\n         * @ngdoc method\n         * @name createGrid\n         * @methodOf ui.grid.service:gridClassFactory\n         * @description Creates a new grid instance. Each instance will have a unique id\n         * @param {object} options An object map of options to pass into the created grid instance.\n         * @returns {Grid} grid\n         */\n        createGrid : function(options) {\n          options = (typeof(options) !== 'undefined') ? options : {};\n          options.id = gridUtil.newId();\n          var grid = new Grid(options);\n\n          // NOTE/TODO: rowTemplate should always be defined...\n          if (grid.options.rowTemplate) {\n            var rowTemplateFnPromise = $q.defer();\n            grid.getRowTemplateFn = rowTemplateFnPromise.promise;\n            \n            gridUtil.getTemplate(grid.options.rowTemplate)\n              .then(\n                function (template) {\n                  var rowTemplateFn = $compile(template);\n                  rowTemplateFnPromise.resolve(rowTemplateFn);\n                },\n                function (res) {\n                  // Todo handle response error here?\n                  throw new Error(\"Couldn't fetch/use row template '\" + grid.options.rowTemplate + \"'\");\n                });\n          }\n\n          grid.registerColumnBuilder(service.defaultColumnBuilder);\n\n          // Row builder for custom row templates\n          grid.registerRowBuilder(service.rowTemplateAssigner);\n\n          // Reset all rows to visible initially\n          grid.registerRowsProcessor(function allRowsVisible(rows) {\n            rows.forEach(function (row) {\n              row.evaluateRowVisibility( true );\n            }, 50);\n\n            return rows;\n          });\n\n          grid.registerColumnsProcessor(function applyColumnVisibility(columns) {\n            columns.forEach(function (column) {\n              column.visible = angular.isDefined(column.colDef.visible) ? column.colDef.visible : true;\n            });\n\n            return columns;\n          }, 50);\n\n          grid.registerRowsProcessor(grid.searchRows, 100);\n\n          // Register the default row processor, it sorts rows by selected columns\n          if (grid.options.externalSort && angular.isFunction(grid.options.externalSort)) {\n            grid.registerRowsProcessor(grid.options.externalSort, 200);\n          }\n          else {\n            grid.registerRowsProcessor(grid.sortByColumn, 200);\n          }\n\n          return grid;\n        },\n\n        /**\n         * @ngdoc function\n         * @name defaultColumnBuilder\n         * @methodOf ui.grid.service:gridClassFactory\n         * @description Processes designTime column definitions and applies them to col for the\n         *              core grid features\n         * @param {object} colDef reference to column definition\n         * @param {GridColumn} col reference to gridCol\n         * @param {object} gridOptions reference to grid options\n         */\n        defaultColumnBuilder: function (colDef, col, gridOptions) {\n\n          var templateGetPromises = [];\n\n          // Abstracts the standard template processing we do for every template type.\n          var processTemplate = function( templateType, providedType, defaultTemplate, filterType, tooltipType ) {\n            if ( !colDef[templateType] ){\n              col[providedType] = defaultTemplate;\n            } else {\n              col[providedType] = colDef[templateType];\n            }\n \n             templateGetPromises.push(gridUtil.getTemplate(col[providedType])\n                .then(\n                function (template) {\n                  if ( angular.isFunction(template) ) { template = template(); }\n                  var tooltipCall = ( tooltipType === 'cellTooltip' ) ? 'col.cellTooltip(row,col)' : 'col.headerTooltip(col)';\n                  if ( tooltipType && col[tooltipType] === false ){\n                    template = template.replace(uiGridConstants.TOOLTIP, '');\n                  } else if ( tooltipType && col[tooltipType] ){\n                    template = template.replace(uiGridConstants.TOOLTIP, 'title=\"{{' + tooltipCall + ' CUSTOM_FILTERS }}\"');\n                  }\n\n                  if ( filterType ){\n                    col[templateType] = template.replace(uiGridConstants.CUSTOM_FILTERS, function() {\n                      return col[filterType] ? \"|\" + col[filterType] : \"\";\n                    });\n                  } else {\n                    col[templateType] = template;\n                  }\n                },\n                function (res) {\n                  throw new Error(\"Couldn't fetch/use colDef.\" + templateType + \" '\" + colDef[templateType] + \"'\");\n                })\n            );\n\n          };\n\n\n          /**\n           * @ngdoc property\n           * @name cellTemplate\n           * @propertyOf ui.grid.class:GridOptions.columnDef\n           * @description a custom template for each cell in this column.  The default\n           * is ui-grid/uiGridCell.  If you are using the cellNav feature, this template\n           * must contain a div that can receive focus.\n           *\n           */\n          processTemplate( 'cellTemplate', 'providedCellTemplate', 'ui-grid/uiGridCell', 'cellFilter', 'cellTooltip' );\n          col.cellTemplatePromise = templateGetPromises[0];\n\n          /**\n           * @ngdoc property\n           * @name headerCellTemplate\n           * @propertyOf ui.grid.class:GridOptions.columnDef\n           * @description a custom template for the header for this column.  The default\n           * is ui-grid/uiGridHeaderCell\n           *\n           */\n          processTemplate( 'headerCellTemplate', 'providedHeaderCellTemplate', 'ui-grid/uiGridHeaderCell', 'headerCellFilter', 'headerTooltip' );\n\n          /**\n           * @ngdoc property\n           * @name footerCellTemplate\n           * @propertyOf ui.grid.class:GridOptions.columnDef\n           * @description a custom template for the footer for this column.  The default\n           * is ui-grid/uiGridFooterCell\n           *\n           */\n          processTemplate( 'footerCellTemplate', 'providedFooterCellTemplate', 'ui-grid/uiGridFooterCell', 'footerCellFilter' );\n\n          /**\n           * @ngdoc property\n           * @name filterHeaderTemplate\n           * @propertyOf ui.grid.class:GridOptions.columnDef\n           * @description a custom template for the filter input.  The default is ui-grid/ui-grid-filter\n           *\n           */\n          processTemplate( 'filterHeaderTemplate', 'providedFilterHeaderTemplate', 'ui-grid/ui-grid-filter' );\n\n          // Create a promise for the compiled element function\n          col.compiledElementFnDefer = $q.defer();\n\n          return $q.all(templateGetPromises);\n        },\n        \n\n        rowTemplateAssigner: function rowTemplateAssigner(row) {\n          var grid = this;\n\n          // Row has no template assigned to it\n          if (!row.rowTemplate) {\n            // Use the default row template from the grid\n            row.rowTemplate = grid.options.rowTemplate;\n\n            // Use the grid's function for fetching the compiled row template function\n            row.getRowTemplateFn = grid.getRowTemplateFn;\n          }\n          // Row has its own template assigned\n          else {\n            // Create a promise for the compiled row template function\n            var perRowTemplateFnPromise = $q.defer();\n            row.getRowTemplateFn = perRowTemplateFnPromise.promise;\n\n            // Get the row template\n            gridUtil.getTemplate(row.rowTemplate)\n              .then(function (template) {\n                // Compile the template\n                var rowTemplateFn = $compile(template);\n                \n                // Resolve the compiled template function promise\n                perRowTemplateFnPromise.resolve(rowTemplateFn);\n              },\n              function (res) {\n                // Todo handle response error here?\n                throw new Error(\"Couldn't fetch/use row template '\" + row.rowTemplate + \"'\");\n              });\n          }\n\n          return row.getRowTemplateFn;\n        }\n      };\n\n      //class definitions (moved to separate factories)\n\n      return service;\n    }]);\n\n})();\n\n(function() {\n\nvar module = angular.module('ui.grid');\n\nfunction escapeRegExp(str) {\n  return str.replace(/[\\-\\[\\]\\/\\{\\}\\(\\)\\*\\+\\?\\.\\\\\\^\\$\\|]/g, \"\\\\$&\");\n}\n\n\n/**\n *  @ngdoc service\n *  @name ui.grid.service:rowSearcher\n *\n *  @description Service for searching/filtering rows based on column value conditions.\n */\nmodule.service('rowSearcher', ['gridUtil', 'uiGridConstants', function (gridUtil, uiGridConstants) {\n  var defaultCondition = uiGridConstants.filter.CONTAINS;\n\n  var rowSearcher = {};\n\n  /**\n   * @ngdoc function\n   * @name getTerm\n   * @methodOf ui.grid.service:rowSearcher\n   * @description Get the term from a filter\n   * Trims leading and trailing whitespace\n   * @param {object} filter object to use\n   * @returns {object} Parsed term\n   */\n  rowSearcher.getTerm = function getTerm(filter) {\n    if (typeof(filter.term) === 'undefined') { return filter.term; }\n    \n    var term = filter.term;\n\n    // Strip leading and trailing whitespace if the term is a string\n    if (typeof(term) === 'string') {\n      term = term.trim();\n    }\n\n    return term;\n  };\n\n  /**\n   * @ngdoc function\n   * @name stripTerm\n   * @methodOf ui.grid.service:rowSearcher\n   * @description Remove leading and trailing asterisk (*) from the filter's term\n   * @param {object} filter object to use\n   * @returns {uiGridConstants.filter<int>} Value representing the condition constant value\n   */\n  rowSearcher.stripTerm = function stripTerm(filter) {\n    var term = rowSearcher.getTerm(filter);\n\n    if (typeof(term) === 'string') {\n      return escapeRegExp(term.replace(/(^\\*|\\*$)/g, ''));\n    }\n    else {\n      return term;\n    }\n  };\n  \n\n  /**\n   * @ngdoc function\n   * @name guessCondition\n   * @methodOf ui.grid.service:rowSearcher\n   * @description Guess the condition for a filter based on its term\n   * <br>\n   * Defaults to STARTS_WITH. Uses CONTAINS for strings beginning and ending with *s (*bob*).\n   * Uses STARTS_WITH for strings ending with * (bo*). Uses ENDS_WITH for strings starting with * (*ob).\n   * @param {object} filter object to use\n   * @returns {uiGridConstants.filter<int>} Value representing the condition constant value\n   */\n  rowSearcher.guessCondition = function guessCondition(filter) {\n    if (typeof(filter.term) === 'undefined' || !filter.term) {\n      return defaultCondition;\n    }\n\n    var term = rowSearcher.getTerm(filter);\n    \n    if (/\\*/.test(term)) {\n      var regexpFlags = '';\n      if (!filter.flags || !filter.flags.caseSensitive) {\n        regexpFlags += 'i';\n      }\n\n      var reText = term.replace(/(\\\\)?\\*/g, function ($0, $1) { return $1 ? $0 : '[\\\\s\\\\S]*?'; });\n      return new RegExp('^' + reText + '$', regexpFlags);\n    }\n    // Otherwise default to default condition\n    else {\n      return defaultCondition;\n    }\n  };\n  \n  \n  /**\n   * @ngdoc function\n   * @name setupFilters\n   * @methodOf ui.grid.service:rowSearcher\n   * @description For a given columns filters (either col.filters, or [col.filter] can be passed in),\n   * do all the parsing and pre-processing and store that data into a new filters object.  The object\n   * has the condition, the flags, the stripped term, and a parsed reg exp if there was one.\n   * \n   * We could use a forEach in here, since it's much less performance sensitive, but since we're using \n   * for loops everywhere else in this module...\n   * \n   * @param {array} filters the filters from the column (col.filters or [col.filter])\n   * @returns {array} An array of parsed/preprocessed filters\n   */\n  rowSearcher.setupFilters = function setupFilters( filters ){\n    var newFilters = [];\n    \n    var filtersLength = filters.length;\n    for ( var i = 0; i < filtersLength; i++ ){\n      var filter = filters[i];\n      \n      if ( filter.noTerm || !gridUtil.isNullOrUndefined(filter.term) ){\n        var newFilter = {};\n        \n        var regexpFlags = '';\n        if (!filter.flags || !filter.flags.caseSensitive) {\n          regexpFlags += 'i';\n        }\n    \n        if ( !gridUtil.isNullOrUndefined(filter.term) ){\n          // it is possible to have noTerm.\n          if ( filter.rawTerm ){\n            newFilter.term = filter.term;\n          } else {\n            newFilter.term = rowSearcher.stripTerm(filter);\n          }\n        }\n        newFilter.noTerm = filter.noTerm;\n        \n        if ( filter.condition ){\n          newFilter.condition = filter.condition;\n        } else {\n          newFilter.condition = rowSearcher.guessCondition(filter);\n        }\n\n        newFilter.flags = angular.extend( { caseSensitive: false, date: false }, filter.flags );\n\n        if (newFilter.condition === uiGridConstants.filter.STARTS_WITH) {\n          newFilter.startswithRE = new RegExp('^' + newFilter.term, regexpFlags);\n        }\n        \n         if (newFilter.condition === uiGridConstants.filter.ENDS_WITH) {\n          newFilter.endswithRE = new RegExp(newFilter.term + '$', regexpFlags);\n        }\n\n        if (newFilter.condition === uiGridConstants.filter.CONTAINS) {\n          newFilter.containsRE = new RegExp(newFilter.term, regexpFlags);\n        }\n\n        if (newFilter.condition === uiGridConstants.filter.EXACT) {\n          newFilter.exactRE = new RegExp('^' + newFilter.term + '$', regexpFlags);\n        }\n        \n        newFilters.push(newFilter);\n      }\n    }\n    return newFilters;\n  };\n  \n\n  /**\n   * @ngdoc function\n   * @name runColumnFilter\n   * @methodOf ui.grid.service:rowSearcher\n   * @description Runs a single pre-parsed filter against a cell, returning true\n   * if the cell matches that one filter.\n   * \n   * @param {Grid} grid the grid we're working against\n   * @param {GridRow} row the row we're matching against\n   * @param {GridCol} column the column that we're working against\n   * @param {object} filter the specific, preparsed, filter that we want to test\n   * @returns {boolean} true if we match (row stays visible)\n   */\n  rowSearcher.runColumnFilter = function runColumnFilter(grid, row, column, filter) {\n    // Cache typeof condition\n    var conditionType = typeof(filter.condition);\n\n    // Term to search for.\n    var term = filter.term;\n\n    // Get the column value for this row\n    var value;\n    if ( column.filterCellFiltered ){\n      value = grid.getCellDisplayValue(row, column);\n    } else {\n      value = grid.getCellValue(row, column);\n    }\n\n\n    // If the filter's condition is a RegExp, then use it\n    if (filter.condition instanceof RegExp) {\n      return filter.condition.test(value);\n    }\n\n    // If the filter's condition is a function, run it\n    if (conditionType === 'function') {\n      return filter.condition(term, value, row, column);\n    }\n\n    if (filter.startswithRE) {\n      return filter.startswithRE.test(value);\n    }\n\n    if (filter.endswithRE) {\n      return filter.endswithRE.test(value);\n    }\n\n    if (filter.containsRE) {\n      return filter.containsRE.test(value);\n    }\n\n    if (filter.exactRE) {\n      return filter.exactRE.test(value);\n    }\n\n    if (filter.condition === uiGridConstants.filter.NOT_EQUAL) {\n      var regex = new RegExp('^' + term + '$');\n      return !regex.exec(value);\n    }\n\n    if (typeof(value) === 'number' && typeof(term) === 'string' ){\n      // if the term has a decimal in it, it comes through as '9\\.4', we need to take out the \\\n      // the same for negative numbers\n      // TODO: I suspect the right answer is to look at escapeRegExp at the top of this code file, maybe it's not needed?\n      var tempFloat = parseFloat(term.replace(/\\\\\\./,'.').replace(/\\\\\\-/,'-'));\n      if (!isNaN(tempFloat)) {\n        term = tempFloat;\n      }\n    }\n\n    if (filter.flags.date === true) {\n      value = new Date(value);\n      // If the term has a dash in it, it comes through as '\\-' -- we need to take out the '\\'.\n      term = new Date(term.replace(/\\\\/g, ''));\n    }\n\n    if (filter.condition === uiGridConstants.filter.GREATER_THAN) {\n      return (value > term);\n    }\n\n    if (filter.condition === uiGridConstants.filter.GREATER_THAN_OR_EQUAL) {\n      return (value >= term);\n    }\n\n    if (filter.condition === uiGridConstants.filter.LESS_THAN) {\n      return (value < term);\n    }\n\n    if (filter.condition === uiGridConstants.filter.LESS_THAN_OR_EQUAL) {\n      return (value <= term);\n    }\n\n    return true;\n  };\n\n\n  /**\n   * @ngdoc boolean\n   * @name useExternalFiltering\n   * @propertyOf ui.grid.class:GridOptions\n   * @description False by default. When enabled, this setting suppresses the internal filtering.\n   * All UI logic will still operate, allowing filter conditions to be set and modified.\n   * \n   * The external filter logic can listen for the `filterChange` event, which fires whenever\n   * a filter has been adjusted.\n   */\n  /**\n   * @ngdoc function\n   * @name searchColumn\n   * @methodOf ui.grid.service:rowSearcher\n   * @description Process provided filters on provided column against a given row. If the row meets \n   * the conditions on all the filters, return true.\n   * @param {Grid} grid Grid to search in\n   * @param {GridRow} row Row to search on\n   * @param {GridCol} column Column with the filters to use\n   * @param {array} filters array of pre-parsed/preprocessed filters to apply\n   * @returns {boolean} Whether the column matches or not.\n   */\n  rowSearcher.searchColumn = function searchColumn(grid, row, column, filters) {\n    if (grid.options.useExternalFiltering) {\n      return true;\n    }\n\n    var filtersLength = filters.length;\n    for (var i = 0; i < filtersLength; i++) {\n      var filter = filters[i];\n\n      if ( !gridUtil.isNullOrUndefined(filter.term) && filter.term !== '' || filter.noTerm ){ \n        var ret = rowSearcher.runColumnFilter(grid, row, column, filter);\n        if (!ret) {\n          return false;\n        }\n      }\n    }\n\n    return true;\n  };\n\n\n  /**\n   * @ngdoc function\n   * @name search\n   * @methodOf ui.grid.service:rowSearcher\n   * @description Run a search across the given rows and columns, marking any rows that don't \n   * match the stored col.filters or col.filter as invisible.\n   * @param {Grid} grid Grid instance to search inside\n   * @param {Array[GridRow]} rows GridRows to filter\n   * @param {Array[GridColumn]} columns GridColumns with filters to process\n   */\n  rowSearcher.search = function search(grid, rows, columns) {\n    /*\n     * Added performance optimisations into this code base, as this logic creates deeply nested\n     * loops and is therefore very performance sensitive.  In particular, avoiding forEach as\n     * this impacts some browser optimisers (particularly Chrome), using iterators instead\n     */\n\n    // Don't do anything if we weren't passed any rows\n    if (!rows) {\n      return;\n    }\n\n    // don't filter if filtering currently disabled\n    if (!grid.options.enableFiltering){\n      return rows;\n    }\n\n    // Build list of filters to apply\n    var filterData = [];\n\n    var colsLength = columns.length;\n\n    var hasTerm = function( filters ) {\n      var hasTerm = false;\n\n      filters.forEach( function (filter) {\n        if ( !gridUtil.isNullOrUndefined(filter.term) && filter.term !== '' || filter.noTerm ){\n          hasTerm = true;\n        }\n      });\n\n      return hasTerm;\n    };\n\n    for (var i = 0; i < colsLength; i++) {\n      var col = columns[i];\n\n      if (typeof(col.filters) !== 'undefined' && hasTerm(col.filters) ) {\n        filterData.push( { col: col, filters: rowSearcher.setupFilters(col.filters) } );\n      }\n    }\n\n    if (filterData.length > 0) {\n      // define functions outside the loop, performance optimisation\n      var foreachRow = function(grid, row, col, filters){\n        if ( row.visible && !rowSearcher.searchColumn(grid, row, col, filters) ) {\n          row.visible = false;\n        }\n      };\n\n      var foreachFilterCol = function(grid, filterData){\n        var rowsLength = rows.length;\n        for ( var i = 0; i < rowsLength; i++){\n          foreachRow(grid, rows[i], filterData.col, filterData.filters);  \n        }\n      };\n\n      // nested loop itself - foreachFilterCol, which in turn calls foreachRow\n      var filterDataLength = filterData.length;\n      for ( var j = 0; j < filterDataLength; j++){\n        foreachFilterCol( grid, filterData[j] );  \n      }\n\n      if (grid.api.core.raise.rowsVisibleChanged) {\n        grid.api.core.raise.rowsVisibleChanged();\n      }\n\n      // drop any invisible rows\n      // keeping these, as needed with filtering for trees - we have to come back and make parent nodes visible if child nodes are selected in the filter\n      // rows = rows.filter(function(row){ return row.visible; });\n\n    }\n\n    return rows;\n  };\n\n  return rowSearcher;\n}]);\n\n})();\n\n(function() {\n\nvar module = angular.module('ui.grid');\n\n/**\n * @ngdoc object\n * @name ui.grid.class:rowSorter\n * @description rowSorter provides the default sorting mechanisms,\n * including guessing column types and applying appropriate sort\n * algorithms\n *\n */\n\nmodule.service('rowSorter', ['$parse', 'uiGridConstants', function ($parse, uiGridConstants) {\n  var currencyRegexStr =\n    '(' +\n    uiGridConstants.CURRENCY_SYMBOLS\n      .map(function (a) { return '\\\\' + a; }) // Escape all the currency symbols ($ at least will jack up this regex)\n      .join('|') + // Join all the symbols together with |s\n    ')?';\n\n  // /^[-+]?[£$¤¥]?[\\d,.]+%?$/\n  var numberStrRegex = new RegExp('^[-+]?' + currencyRegexStr + '[\\\\d,.]+' + currencyRegexStr + '%?$');\n\n  var rowSorter = {\n    // Cache of sorting functions. Once we create them, we don't want to keep re-doing it\n    //   this takes a piece of data from the cell and tries to determine its type and what sorting\n    //   function to use for it\n    colSortFnCache: {}\n  };\n\n\n  /**\n   * @ngdoc method\n   * @methodOf ui.grid.class:rowSorter\n   * @name guessSortFn\n   * @description Assigns a sort function to use based on the itemType in the column\n   * @param {string} itemType one of 'number', 'boolean', 'string', 'date', 'object'.  And\n   * error will be thrown for any other type.\n   * @returns {function} a sort function that will sort that type\n   */\n  rowSorter.guessSortFn = function guessSortFn(itemType) {\n    switch (itemType) {\n      case \"number\":\n        return rowSorter.sortNumber;\n      case \"numberStr\":\n        return rowSorter.sortNumberStr;\n      case \"boolean\":\n        return rowSorter.sortBool;\n      case \"string\":\n        return rowSorter.sortAlpha;\n      case \"date\":\n        return rowSorter.sortDate;\n      case \"object\":\n        return rowSorter.basicSort;\n      default:\n        throw new Error('No sorting function found for type:' + itemType);\n    }\n  };\n\n\n  /**\n   * @ngdoc method\n   * @methodOf ui.grid.class:rowSorter\n   * @name handleNulls\n   * @description Sorts nulls and undefined to the bottom (top when\n   * descending).  Called by each of the internal sorters before\n   * attempting to sort.  Note that this method is available on the core api\n   * via gridApi.core.sortHandleNulls\n   * @param {object} a sort value a\n   * @param {object} b sort value b\n   * @returns {number} null if there were no nulls/undefineds, otherwise returns\n   * a sort value that should be passed back from the sort function\n   */\n  rowSorter.handleNulls = function handleNulls(a, b) {\n    // We want to allow zero values and false values to be evaluated in the sort function\n    if ((!a && a !== 0 && a !== false) || (!b && b !== 0 && b !== false)) {\n      // We want to force nulls and such to the bottom when we sort... which effectively is \"greater than\"\n      if ((!a && a !== 0 && a !== false) && (!b && b !== 0 && b !== false)) {\n        return 0;\n      }\n      else if (!a && a !== 0 && a !== false) {\n        return 1;\n      }\n      else if (!b && b !== 0 && b !== false) {\n        return -1;\n      }\n    }\n    return null;\n  };\n\n\n  /**\n   * @ngdoc method\n   * @methodOf ui.grid.class:rowSorter\n   * @name basicSort\n   * @description Sorts any values that provide the < method, including strings\n   * or numbers.  Handles nulls and undefined through calling handleNulls\n   * @param {object} a sort value a\n   * @param {object} b sort value b\n   * @returns {number} normal sort function, returns -ve, 0, +ve\n   */\n  rowSorter.basicSort = function basicSort(a, b) {\n    var nulls = rowSorter.handleNulls(a, b);\n    if ( nulls !== null ){\n      return nulls;\n    } else {\n      if (a === b) {\n        return 0;\n      }\n      if (a < b) {\n        return -1;\n      }\n      return 1;\n    }\n  };\n\n\n  /**\n   * @ngdoc method\n   * @methodOf ui.grid.class:rowSorter\n   * @name sortNumber\n   * @description Sorts numerical values.  Handles nulls and undefined through calling handleNulls\n   * @param {object} a sort value a\n   * @param {object} b sort value b\n   * @returns {number} normal sort function, returns -ve, 0, +ve\n   */\n  rowSorter.sortNumber = function sortNumber(a, b) {\n    var nulls = rowSorter.handleNulls(a, b);\n    if ( nulls !== null ){\n      return nulls;\n    } else {\n      return a - b;\n    }\n  };\n\n\n  /**\n   * @ngdoc method\n   * @methodOf ui.grid.class:rowSorter\n   * @name sortNumberStr\n   * @description Sorts numerical values that are stored in a string (i.e. parses them to numbers first).\n   * Handles nulls and undefined through calling handleNulls\n   * @param {object} a sort value a\n   * @param {object} b sort value b\n   * @returns {number} normal sort function, returns -ve, 0, +ve\n   */\n  rowSorter.sortNumberStr = function sortNumberStr(a, b) {\n    var nulls = rowSorter.handleNulls(a, b);\n    if ( nulls !== null ){\n      return nulls;\n    } else {\n      var numA, // The parsed number form of 'a'\n          numB, // The parsed number form of 'b'\n          badA = false,\n          badB = false;\n\n      // Try to parse 'a' to a float\n      numA = parseFloat(a.replace(/[^0-9.-]/g, ''));\n\n      // If 'a' couldn't be parsed to float, flag it as bad\n      if (isNaN(numA)) {\n          badA = true;\n      }\n\n      // Try to parse 'b' to a float\n      numB = parseFloat(b.replace(/[^0-9.-]/g, ''));\n\n      // If 'b' couldn't be parsed to float, flag it as bad\n      if (isNaN(numB)) {\n          badB = true;\n      }\n\n      // We want bad ones to get pushed to the bottom... which effectively is \"greater than\"\n      if (badA && badB) {\n          return 0;\n      }\n\n      if (badA) {\n          return 1;\n      }\n\n      if (badB) {\n          return -1;\n      }\n\n      return numA - numB;\n    }\n  };\n\n\n  /**\n   * @ngdoc method\n   * @methodOf ui.grid.class:rowSorter\n   * @name sortAlpha\n   * @description Sorts string values. Handles nulls and undefined through calling handleNulls\n   * @param {object} a sort value a\n   * @param {object} b sort value b\n   * @returns {number} normal sort function, returns -ve, 0, +ve\n   */\n  rowSorter.sortAlpha = function sortAlpha(a, b) {\n    var nulls = rowSorter.handleNulls(a, b);\n    if ( nulls !== null ){\n      return nulls;\n    } else {\n      var strA = a.toString().toLowerCase(),\n          strB = b.toString().toLowerCase();\n\n      return strA === strB ? 0 : strA.localeCompare(strB);\n    }\n  };\n\n\n  /**\n   * @ngdoc method\n   * @methodOf ui.grid.class:rowSorter\n   * @name sortDate\n   * @description Sorts date values. Handles nulls and undefined through calling handleNulls.\n   * Handles date strings by converting to Date object if not already an instance of Date\n   * @param {object} a sort value a\n   * @param {object} b sort value b\n   * @returns {number} normal sort function, returns -ve, 0, +ve\n   */\n  rowSorter.sortDate = function sortDate(a, b) {\n    var nulls = rowSorter.handleNulls(a, b);\n    if ( nulls !== null ){\n      return nulls;\n    } else {\n      if (!(a instanceof Date)) {\n        a = new Date(a);\n      }\n      if (!(b instanceof Date)){\n        b = new Date(b);\n      }\n      var timeA = a.getTime(),\n          timeB = b.getTime();\n\n      return timeA === timeB ? 0 : (timeA < timeB ? -1 : 1);\n    }\n  };\n\n\n  /**\n   * @ngdoc method\n   * @methodOf ui.grid.class:rowSorter\n   * @name sortBool\n   * @description Sorts boolean values, true is considered larger than false.\n   * Handles nulls and undefined through calling handleNulls\n   * @param {object} a sort value a\n   * @param {object} b sort value b\n   * @returns {number} normal sort function, returns -ve, 0, +ve\n   */\n  rowSorter.sortBool = function sortBool(a, b) {\n    var nulls = rowSorter.handleNulls(a, b);\n    if ( nulls !== null ){\n      return nulls;\n    } else {\n      if (a && b) {\n        return 0;\n      }\n\n      if (!a && !b) {\n        return 0;\n      }\n      else {\n        return a ? 1 : -1;\n      }\n    }\n  };\n\n\n  /**\n   * @ngdoc method\n   * @methodOf ui.grid.class:rowSorter\n   * @name getSortFn\n   * @description Get the sort function for the column.  Looks first in\n   * rowSorter.colSortFnCache using the column name, failing that it\n   * looks at col.sortingAlgorithm (and puts it in the cache), failing that\n   * it guesses the sort algorithm based on the data type.\n   *\n   * The cache currently seems a bit pointless, as none of the work we do is\n   * processor intensive enough to need caching.  Presumably in future we might\n   * inspect the row data itself to guess the sort function, and in that case\n   * it would make sense to have a cache, the infrastructure is in place to allow\n   * that.\n   *\n   * @param {Grid} grid the grid to consider\n   * @param {GridCol} col the column to find a function for\n   * @param {array} rows an array of grid rows.  Currently unused, but presumably in future\n   * we might inspect the rows themselves to decide what sort of data might be there\n   * @returns {function} the sort function chosen for the column\n   */\n  rowSorter.getSortFn = function getSortFn(grid, col, rows) {\n    var sortFn, item;\n\n    // See if we already figured out what to use to sort the column and have it in the cache\n    if (rowSorter.colSortFnCache[col.colDef.name]) {\n      sortFn = rowSorter.colSortFnCache[col.colDef.name];\n    }\n    // If the column has its OWN sorting algorithm, use that\n    else if (col.sortingAlgorithm !== undefined) {\n      sortFn = col.sortingAlgorithm;\n      rowSorter.colSortFnCache[col.colDef.name] = col.sortingAlgorithm;\n    }\n    // Always default to sortAlpha when sorting after a cellFilter\n    else if ( col.sortCellFiltered && col.cellFilter ){\n      sortFn = rowSorter.sortAlpha;\n      rowSorter.colSortFnCache[col.colDef.name] = sortFn;\n    }\n    // Try and guess what sort function to use\n    else {\n      // Guess the sort function\n      sortFn = rowSorter.guessSortFn(col.colDef.type);\n\n      // If we found a sort function, cache it\n      if (sortFn) {\n        rowSorter.colSortFnCache[col.colDef.name] = sortFn;\n      }\n      else {\n        // We assign the alpha sort because anything that is null/undefined will never get passed to\n        // the actual sorting function. It will get caught in our null check and returned to be sorted\n        // down to the bottom\n        sortFn = rowSorter.sortAlpha;\n      }\n    }\n\n    return sortFn;\n  };\n\n\n\n  /**\n   * @ngdoc method\n   * @methodOf ui.grid.class:rowSorter\n   * @name prioritySort\n   * @description Used where multiple columns are present in the sort criteria,\n   * we determine which column should take precedence in the sort by sorting\n   * the columns based on their sort.priority\n   *\n   * @param {gridColumn} a column a\n   * @param {gridColumn} b column b\n   * @returns {number} normal sort function, returns -ve, 0, +ve\n   */\n  rowSorter.prioritySort = function (a, b) {\n    // Both columns have a sort priority\n    if (a.sort.priority !== undefined && b.sort.priority !== undefined) {\n      // A is higher priority\n      if (a.sort.priority < b.sort.priority) {\n        return -1;\n      }\n      // Equal\n      else if (a.sort.priority === b.sort.priority) {\n        return 0;\n      }\n      // B is higher\n      else {\n        return 1;\n      }\n    }\n    // Only A has a priority\n    else if (a.sort.priority || a.sort.priority === undefined) {\n      return -1;\n    }\n    // Only B has a priority\n    else if (b.sort.priority || b.sort.priority === undefined) {\n      return 1;\n    }\n    // Neither has a priority\n    else {\n      return 0;\n    }\n  };\n\n\n  /**\n   * @ngdoc object\n   * @name useExternalSorting\n   * @propertyOf ui.grid.class:GridOptions\n   * @description Prevents the internal sorting from executing.  Events will\n   * still be fired when the sort changes, and the sort information on\n   * the columns will be updated, allowing an external sorter (for example,\n   * server sorting) to be implemented.  Defaults to false.\n   *\n   */\n  /**\n   * @ngdoc method\n   * @methodOf ui.grid.class:rowSorter\n   * @name sort\n   * @description sorts the grid\n   * @param {Object} grid the grid itself\n   * @param {array} rows the rows to be sorted\n   * @param {array} columns the columns in which to look\n   * for sort criteria\n   * @returns {array} sorted rows\n   */\n  rowSorter.sort = function rowSorterSort(grid, rows, columns) {\n    // first make sure we are even supposed to do work\n    if (!rows) {\n      return;\n    }\n\n    if (grid.options.useExternalSorting){\n      return rows;\n    }\n\n    // Build the list of columns to sort by\n    var sortCols = [];\n    columns.forEach(function (col) {\n      if (col.sort && !col.sort.ignoreSort && col.sort.direction && (col.sort.direction === uiGridConstants.ASC || col.sort.direction === uiGridConstants.DESC)) {\n        sortCols.push(col);\n      }\n    });\n\n    // Sort the \"sort columns\" by their sort priority\n    sortCols = sortCols.sort(rowSorter.prioritySort);\n\n    // Now rows to sort by, maintain original order\n    if (sortCols.length === 0) {\n      return rows;\n    }\n\n    // Re-usable variables\n    var col, direction;\n\n    // put a custom index field on each row, used to make a stable sort out of unstable sorts (e.g. Chrome)\n    var setIndex = function( row, idx ){\n      row.entity.$$uiGridIndex = idx;\n    };\n    rows.forEach(setIndex);\n\n    // IE9-11 HACK.... the 'rows' variable would be empty where we call rowSorter.getSortFn(...) below. We have to use a separate reference\n    // var d = data.slice(0);\n    var r = rows.slice(0);\n\n    // Now actually sort the data\n    var rowSortFn = function (rowA, rowB) {\n      var tem = 0,\n          idx = 0,\n          sortFn;\n\n      while (tem === 0 && idx < sortCols.length) {\n        // grab the metadata for the rest of the logic\n        col = sortCols[idx];\n        direction = sortCols[idx].sort.direction;\n\n        sortFn = rowSorter.getSortFn(grid, col, r);\n\n        var propA, propB;\n\n        if ( col.sortCellFiltered ){\n          propA = grid.getCellDisplayValue(rowA, col);\n          propB = grid.getCellDisplayValue(rowB, col);\n        } else {\n          propA = grid.getCellValue(rowA, col);\n          propB = grid.getCellValue(rowB, col);\n        }\n\n        tem = sortFn(propA, propB, rowA, rowB, direction);\n\n        idx++;\n      }\n\n      // Chrome doesn't implement a stable sort function.  If our sort returns 0\n      // (i.e. the items are equal), and we're at the last sort column in the list,\n      // then return the previous order using our custom\n      // index variable\n      if (tem === 0 ) {\n        return rowA.entity.$$uiGridIndex - rowB.entity.$$uiGridIndex;\n      }\n\n      // Made it this far, we don't have to worry about null & undefined\n      if (direction === uiGridConstants.ASC) {\n        return tem;\n      } else {\n        return 0 - tem;\n      }\n    };\n\n    var newRows = rows.sort(rowSortFn);\n\n    // remove the custom index field on each row, used to make a stable sort out of unstable sorts (e.g. Chrome)\n    var clearIndex = function( row, idx ){\n       delete row.entity.$$uiGridIndex;\n    };\n    rows.forEach(clearIndex);\n\n    return newRows;\n  };\n\n  return rowSorter;\n}]);\n\n})();\n\n(function() {\n\nvar module = angular.module('ui.grid');\n\nvar bindPolyfill;\nif (typeof Function.prototype.bind !== \"function\") {\n  bindPolyfill = function() {\n    var slice = Array.prototype.slice;\n    return function(context) {\n      var fn = this,\n        args = slice.call(arguments, 1);\n      if (args.length) {\n        return function() {\n          return arguments.length ? fn.apply(context, args.concat(slice.call(arguments))) : fn.apply(context, args);\n        };\n      }\n      return function() {\n        return arguments.length ? fn.apply(context, arguments) : fn.call(context);\n      };\n    };\n  };\n}\n\nfunction  getStyles (elem) {\n  var e = elem;\n  if (typeof(e.length) !== 'undefined' && e.length) {\n    e = elem[0];\n  }\n\n  return e.ownerDocument.defaultView.getComputedStyle(e, null);\n}\n\nvar rnumnonpx = new RegExp( \"^(\" + (/[+-]?(?:\\d*\\.|)\\d+(?:[eE][+-]?\\d+|)/).source + \")(?!px)[a-z%]+$\", \"i\" ),\n    // swappable if display is none or starts with table except \"table\", \"table-cell\", or \"table-caption\"\n    // see here for display values: https://developer.mozilla.org/en-US/docs/CSS/display\n    rdisplayswap = /^(block|none|table(?!-c[ea]).+)/,\n    cssShow = { position: \"absolute\", visibility: \"hidden\", display: \"block\" };\n\nfunction augmentWidthOrHeight( elem, name, extra, isBorderBox, styles ) {\n  var i = extra === ( isBorderBox ? 'border' : 'content' ) ?\n          // If we already have the right measurement, avoid augmentation\n          4 :\n          // Otherwise initialize for horizontal or vertical properties\n          name === 'width' ? 1 : 0,\n\n          val = 0;\n\n  var sides = ['Top', 'Right', 'Bottom', 'Left'];\n\n  for ( ; i < 4; i += 2 ) {\n    var side = sides[i];\n    // dump('side', side);\n\n    // both box models exclude margin, so add it if we want it\n    if ( extra === 'margin' ) {\n      var marg = parseFloat(styles[extra + side]);\n      if (!isNaN(marg)) {\n        val += marg;\n      }\n    }\n    // dump('val1', val);\n\n    if ( isBorderBox ) {\n      // border-box includes padding, so remove it if we want content\n      if ( extra === 'content' ) {\n        var padd = parseFloat(styles['padding' + side]);\n        if (!isNaN(padd)) {\n          val -= padd;\n          // dump('val2', val);\n        }\n      }\n\n      // at this point, extra isn't border nor margin, so remove border\n      if ( extra !== 'margin' ) {\n        var bordermarg = parseFloat(styles['border' + side + 'Width']);\n        if (!isNaN(bordermarg)) {\n          val -= bordermarg;\n          // dump('val3', val);\n        }\n      }\n    }\n    else {\n      // at this point, extra isn't content, so add padding\n      var nocontentPad = parseFloat(styles['padding' + side]);\n      if (!isNaN(nocontentPad)) {\n        val += nocontentPad;\n        // dump('val4', val);\n      }\n\n      // at this point, extra isn't content nor padding, so add border\n      if ( extra !== 'padding') {\n        var nocontentnopad = parseFloat(styles['border' + side + 'Width']);\n        if (!isNaN(nocontentnopad)) {\n          val += nocontentnopad;\n          // dump('val5', val);\n        }\n      }\n    }\n  }\n\n  // dump('augVal', val);\n\n  return val;\n}\n\nfunction getWidthOrHeight( elem, name, extra ) {\n  // Start with offset property, which is equivalent to the border-box value\n  var valueIsBorderBox = true,\n          val, // = name === 'width' ? elem.offsetWidth : elem.offsetHeight,\n          styles = getStyles(elem),\n          isBorderBox = styles['boxSizing'] === 'border-box';\n\n  // some non-html elements return undefined for offsetWidth, so check for null/undefined\n  // svg - https://bugzilla.mozilla.org/show_bug.cgi?id=649285\n  // MathML - https://bugzilla.mozilla.org/show_bug.cgi?id=491668\n  if ( val <= 0 || val == null ) {\n    // Fall back to computed then uncomputed css if necessary\n    val = styles[name];\n    if ( val < 0 || val == null ) {\n      val = elem.style[ name ];\n    }\n\n    // Computed unit is not pixels. Stop here and return.\n    if ( rnumnonpx.test(val) ) {\n      return val;\n    }\n\n    // we need the check for style in case a browser which returns unreliable values\n    // for getComputedStyle silently falls back to the reliable elem.style\n    valueIsBorderBox = isBorderBox &&\n            ( true || val === elem.style[ name ] ); // use 'true' instead of 'support.boxSizingReliable()'\n\n    // Normalize \"\", auto, and prepare for extra\n    val = parseFloat( val ) || 0;\n  }\n\n  // use the active box-sizing model to add/subtract irrelevant styles\n  var ret = ( val +\n    augmentWidthOrHeight(\n      elem,\n      name,\n      extra || ( isBorderBox ? \"border\" : \"content\" ),\n      valueIsBorderBox,\n      styles\n    )\n  );\n\n  // dump('ret', ret, val);\n  return ret;\n}\n\nfunction getLineHeight(elm) {\n  elm = angular.element(elm)[0];\n  var parent = elm.parentElement;\n\n  if (!parent) {\n    parent = document.getElementsByTagName('body')[0];\n  }\n\n  return parseInt( getStyles(parent).fontSize ) || parseInt( getStyles(elm).fontSize ) || 16;\n}\n\nvar uid = ['0', '0', '0', '0'];\nvar uidPrefix = 'uiGrid-';\n\n/**\n *  @ngdoc service\n *  @name ui.grid.service:GridUtil\n *\n *  @description Grid utility functions\n */\nmodule.service('gridUtil', ['$log', '$window', '$document', '$http', '$templateCache', '$timeout', '$interval', '$injector', '$q', '$interpolate', 'uiGridConstants',\n  function ($log, $window, $document, $http, $templateCache, $timeout, $interval, $injector, $q, $interpolate, uiGridConstants) {\n  var s = {\n\n    augmentWidthOrHeight: augmentWidthOrHeight,\n\n    getStyles: getStyles,\n\n    /**\n     * @ngdoc method\n     * @name createBoundedWrapper\n     * @methodOf ui.grid.service:GridUtil\n     *\n     * @param {object} Object to bind 'this' to\n     * @param {method} Method to bind\n     * @returns {Function} The wrapper that performs the binding\n     *\n     * @description\n     * Binds given method to given object.\n     *\n     * By means of a wrapper, ensures that ``method`` is always bound to\n     * ``object`` regardless of its calling environment.\n     * Iow, inside ``method``, ``this`` always points to ``object``.\n     *\n     * See http://alistapart.com/article/getoutbindingsituations\n     *\n     */\n    createBoundedWrapper: function(object, method) {\n        return function() {\n            return method.apply(object, arguments);\n        };\n    },\n\n\n    /**\n     * @ngdoc method\n     * @name readableColumnName\n     * @methodOf ui.grid.service:GridUtil\n     *\n     * @param {string} columnName Column name as a string\n     * @returns {string} Column name appropriately capitalized and split apart\n     *\n       @example\n       <example module=\"app\">\n        <file name=\"app.js\">\n          var app = angular.module('app', ['ui.grid']);\n\n          app.controller('MainCtrl', ['$scope', 'gridUtil', function ($scope, gridUtil) {\n            $scope.name = 'firstName';\n            $scope.columnName = function(name) {\n              return gridUtil.readableColumnName(name);\n            };\n          }]);\n        </file>\n        <file name=\"index.html\">\n          <div ng-controller=\"MainCtrl\">\n            <strong>Column name:</strong> <input ng-model=\"name\" />\n            <br>\n            <strong>Output:</strong> <span ng-bind=\"columnName(name)\"></span>\n          </div>\n        </file>\n      </example>\n     */\n    readableColumnName: function (columnName) {\n      // Convert underscores to spaces\n      if (typeof(columnName) === 'undefined' || columnName === undefined || columnName === null) { return columnName; }\n\n      if (typeof(columnName) !== 'string') {\n        columnName = String(columnName);\n      }\n\n      return columnName.replace(/_+/g, ' ')\n        // Replace a completely all-capsed word with a first-letter-capitalized version\n        .replace(/^[A-Z]+$/, function (match) {\n          return angular.lowercase(angular.uppercase(match.charAt(0)) + match.slice(1));\n        })\n        // Capitalize the first letter of words\n        .replace(/([\\w\\u00C0-\\u017F]+)/g, function (match) {\n          return angular.uppercase(match.charAt(0)) + match.slice(1);\n        })\n        // Put a space in between words that have partial capilizations (i.e. 'firstName' becomes 'First Name')\n        // .replace(/([A-Z]|[A-Z]\\w+)([A-Z])/g, \"$1 $2\");\n        // .replace(/(\\w+?|\\w)([A-Z])/g, \"$1 $2\");\n        .replace(/(\\w+?(?=[A-Z]))/g, '$1 ');\n    },\n\n    /**\n     * @ngdoc method\n     * @name getColumnsFromData\n     * @methodOf ui.grid.service:GridUtil\n     * @description Return a list of column names, given a data set\n     *\n     * @param {string} data Data array for grid\n     * @returns {Object} Column definitions with field accessor and column name\n     *\n     * @example\n       <pre>\n         var data = [\n           { firstName: 'Bob', lastName: 'Jones' },\n           { firstName: 'Frank', lastName: 'Smith' }\n         ];\n\n         var columnDefs = GridUtil.getColumnsFromData(data, excludeProperties);\n\n         columnDefs == [\n          {\n            field: 'firstName',\n            name: 'First Name'\n          },\n          {\n            field: 'lastName',\n            name: 'Last Name'\n          }\n         ];\n       </pre>\n     */\n    getColumnsFromData: function (data, excludeProperties) {\n      var columnDefs = [];\n\n      if (!data || typeof(data[0]) === 'undefined' || data[0] === undefined) { return []; }\n      if (angular.isUndefined(excludeProperties)) { excludeProperties = []; }\n\n      var item = data[0];\n\n      angular.forEach(item,function (prop, propName) {\n        if ( excludeProperties.indexOf(propName) === -1){\n          columnDefs.push({\n            name: propName\n          });\n        }\n      });\n\n      return columnDefs;\n    },\n\n    /**\n     * @ngdoc method\n     * @name newId\n     * @methodOf ui.grid.service:GridUtil\n     * @description Return a unique ID string\n     *\n     * @returns {string} Unique string\n     *\n     * @example\n       <pre>\n        var id = GridUtil.newId();\n\n        # 1387305700482;\n       </pre>\n     */\n    newId: (function() {\n      var seedId = new Date().getTime();\n      return function() {\n          return seedId += 1;\n      };\n    })(),\n\n\n    /**\n     * @ngdoc method\n     * @name getTemplate\n     * @methodOf ui.grid.service:GridUtil\n     * @description Get's template from cache / element / url\n     *\n     * @param {string|element|promise} Either a string representing the template id, a string representing the template url,\n     *   an jQuery/Angualr element, or a promise that returns the template contents to use.\n     * @returns {object} a promise resolving to template contents\n     *\n     * @example\n     <pre>\n     GridUtil.getTemplate(url).then(function (contents) {\n          alert(contents);\n        })\n     </pre>\n     */\n    getTemplate: function (template) {\n      // Try to fetch the template out of the templateCache\n      if ($templateCache.get(template)) {\n        return s.postProcessTemplate($templateCache.get(template));\n      }\n\n      // See if the template is itself a promise\n      if (angular.isFunction(template.then)) {\n        return template.then(s.postProcessTemplate);\n      }\n\n      // If the template is an element, return the element\n      try {\n        if (angular.element(template).length > 0) {\n          return $q.when(template).then(s.postProcessTemplate);\n        }\n      }\n      catch (err){\n        //do nothing; not valid html\n      }\n\n      s.logDebug('fetching url', template);\n\n      // Default to trying to fetch the template as a url with $http\n      return $http({ method: 'GET', url: template})\n        .then(\n          function (result) {\n            var templateHtml = result.data.trim();\n            //put in templateCache for next call\n            $templateCache.put(template, templateHtml);\n            return templateHtml;\n          },\n          function (err) {\n            throw new Error(\"Could not get template \" + template + \": \" + err);\n          }\n        )\n        .then(s.postProcessTemplate);\n    },\n\n    //\n    postProcessTemplate: function (template) {\n      var startSym = $interpolate.startSymbol(),\n          endSym = $interpolate.endSymbol();\n\n      // If either of the interpolation symbols have been changed, we need to alter this template\n      if (startSym !== '{{' || endSym !== '}}') {\n        template = template.replace(/\\{\\{/g, startSym);\n        template = template.replace(/\\}\\}/g, endSym);\n      }\n\n      return $q.when(template);\n    },\n\n    /**\n     * @ngdoc method\n     * @name guessType\n     * @methodOf ui.grid.service:GridUtil\n     * @description guesses the type of an argument\n     *\n     * @param {string/number/bool/object} item variable to examine\n     * @returns {string} one of the following\n     * - 'string'\n     * - 'boolean'\n     * - 'number'\n     * - 'date'\n     * - 'object'\n     */\n    guessType : function (item) {\n      var itemType = typeof(item);\n\n      // Check for numbers and booleans\n      switch (itemType) {\n        case \"number\":\n        case \"boolean\":\n        case \"string\":\n          return itemType;\n        default:\n          if (angular.isDate(item)) {\n            return \"date\";\n          }\n          return \"object\";\n      }\n    },\n\n\n  /**\n    * @ngdoc method\n    * @name elementWidth\n    * @methodOf ui.grid.service:GridUtil\n    *\n    * @param {element} element DOM element\n    * @param {string} [extra] Optional modifier for calculation. Use 'margin' to account for margins on element\n    *\n    * @returns {number} Element width in pixels, accounting for any borders, etc.\n    */\n    elementWidth: function (elem) {\n\n    },\n\n    /**\n    * @ngdoc method\n    * @name elementHeight\n    * @methodOf ui.grid.service:GridUtil\n    *\n    * @param {element} element DOM element\n    * @param {string} [extra] Optional modifier for calculation. Use 'margin' to account for margins on element\n    *\n    * @returns {number} Element height in pixels, accounting for any borders, etc.\n    */\n    elementHeight: function (elem) {\n\n    },\n\n    // Thanks to http://stackoverflow.com/a/13382873/888165\n    getScrollbarWidth: function() {\n        var outer = document.createElement(\"div\");\n        outer.style.visibility = \"hidden\";\n        outer.style.width = \"100px\";\n        outer.style.msOverflowStyle = \"scrollbar\"; // needed for WinJS apps\n\n        document.body.appendChild(outer);\n\n        var widthNoScroll = outer.offsetWidth;\n        // force scrollbars\n        outer.style.overflow = \"scroll\";\n\n        // add innerdiv\n        var inner = document.createElement(\"div\");\n        inner.style.width = \"100%\";\n        outer.appendChild(inner);\n\n        var widthWithScroll = inner.offsetWidth;\n\n        // remove divs\n        outer.parentNode.removeChild(outer);\n\n        return widthNoScroll - widthWithScroll;\n    },\n\n    swap: function( elem, options, callback, args ) {\n      var ret, name,\n              old = {};\n\n      // Remember the old values, and insert the new ones\n      for ( name in options ) {\n        old[ name ] = elem.style[ name ];\n        elem.style[ name ] = options[ name ];\n      }\n\n      ret = callback.apply( elem, args || [] );\n\n      // Revert the old values\n      for ( name in options ) {\n        elem.style[ name ] = old[ name ];\n      }\n\n      return ret;\n    },\n\n    fakeElement: function( elem, options, callback, args ) {\n      var ret, name,\n          newElement = angular.element(elem).clone()[0];\n\n      for ( name in options ) {\n        newElement.style[ name ] = options[ name ];\n      }\n\n      angular.element(document.body).append(newElement);\n\n      ret = callback.call( newElement, newElement );\n\n      angular.element(newElement).remove();\n\n      return ret;\n    },\n\n    /**\n    * @ngdoc method\n    * @name normalizeWheelEvent\n    * @methodOf ui.grid.service:GridUtil\n    *\n    * @param {event} event A mouse wheel event\n    *\n    * @returns {event} A normalized event\n    *\n    * @description\n    * Given an event from this list:\n    *\n    * `wheel, mousewheel, DomMouseScroll, MozMousePixelScroll`\n    *\n    * \"normalize\" it\n    * so that it stays consistent no matter what browser it comes from (i.e. scale it correctly and make sure the direction is right.)\n    */\n    normalizeWheelEvent: function (event) {\n      // var toFix = ['wheel', 'mousewheel', 'DOMMouseScroll', 'MozMousePixelScroll'];\n      // var toBind = 'onwheel' in document || document.documentMode >= 9 ? ['wheel'] : ['mousewheel', 'DomMouseScroll', 'MozMousePixelScroll'];\n      var lowestDelta, lowestDeltaXY;\n\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          absDeltaXY = 0,\n          fn;\n\n      // event = $.event.fix(orgEvent);\n      // event.type = 'mousewheel';\n\n      // NOTE: jQuery masks the event and stores it in the event as originalEvent\n      if (orgEvent.originalEvent) {\n        orgEvent = orgEvent.originalEvent;\n      }\n\n      // Old school scrollwheel delta\n      if ( orgEvent.wheelDelta ) { delta = orgEvent.wheelDelta; }\n      if ( orgEvent.detail )     { delta = orgEvent.detail * -1; }\n\n      // At a minimum, setup the deltaY to be delta\n      deltaY = delta;\n\n      // Firefox < 17 related to DOMMouseScroll event\n      if ( orgEvent.axis !== undefined && orgEvent.axis === orgEvent.HORIZONTAL_AXIS ) {\n          deltaY = 0;\n          deltaX = delta * -1;\n      }\n\n      // New school wheel delta (wheel event)\n      if ( orgEvent.deltaY ) {\n          deltaY = orgEvent.deltaY * -1;\n          delta  = deltaY;\n      }\n      if ( orgEvent.deltaX ) {\n          deltaX = orgEvent.deltaX;\n          delta  = deltaX * -1;\n      }\n\n      // Webkit\n      if ( orgEvent.wheelDeltaY !== undefined ) { deltaY = orgEvent.wheelDeltaY; }\n      if ( orgEvent.wheelDeltaX !== undefined ) { deltaX = orgEvent.wheelDeltaX; }\n\n      // Look for lowest delta to normalize the delta values\n      absDelta = Math.abs(delta);\n      if ( !lowestDelta || absDelta < lowestDelta ) { lowestDelta = absDelta; }\n      absDeltaXY = Math.max(Math.abs(deltaY), Math.abs(deltaX));\n      if ( !lowestDeltaXY || absDeltaXY < lowestDeltaXY ) { lowestDeltaXY = absDeltaXY; }\n\n      // Get a whole value for the deltas\n      fn     = delta > 0 ? 'floor' : 'ceil';\n      delta  = Math[fn](delta  / lowestDelta);\n      deltaX = Math[fn](deltaX / lowestDeltaXY);\n      deltaY = Math[fn](deltaY / lowestDeltaXY);\n\n      return {\n        delta: delta,\n        deltaX: deltaX,\n        deltaY: deltaY\n      };\n    },\n\n    // Stolen from Modernizr\n    // TODO: make this, and everythign that flows from it, robust\n    //http://www.stucox.com/blog/you-cant-detect-a-touchscreen/\n    isTouchEnabled: function() {\n      var bool;\n\n      if (('ontouchstart' in $window) || $window.DocumentTouch && $document instanceof DocumentTouch) {\n        bool = true;\n      }\n\n      return bool;\n    },\n\n    isNullOrUndefined: function(obj) {\n      if (obj === undefined || obj === null) {\n        return true;\n      }\n      return false;\n    },\n\n    endsWith: function(str, suffix) {\n      if (!str || !suffix || typeof str !== \"string\") {\n        return false;\n      }\n      return str.indexOf(suffix, str.length - suffix.length) !== -1;\n    },\n\n    arrayContainsObjectWithProperty: function(array, propertyName, propertyValue) {\n        var found = false;\n        angular.forEach(array, function (object) {\n            if (object[propertyName] === propertyValue) {\n                found = true;\n            }\n        });\n        return found;\n    },\n\n    //// Shim requestAnimationFrame\n    //requestAnimationFrame: $window.requestAnimationFrame && $window.requestAnimationFrame.bind($window) ||\n    //                       $window.webkitRequestAnimationFrame && $window.webkitRequestAnimationFrame.bind($window) ||\n    //                       function(fn) {\n    //                         return $timeout(fn, 10, false);\n    //                       },\n\n    numericAndNullSort: function (a, b) {\n      if (a === null) { return 1; }\n      if (b === null) { return -1; }\n      if (a === null && b === null) { return 0; }\n      return a - b;\n    },\n\n    // Disable ngAnimate animations on an element\n    disableAnimations: function (element) {\n      var $animate;\n      try {\n        $animate = $injector.get('$animate');\n        // See: http://brianhann.com/angular-1-4-breaking-changes-to-be-aware-of/#animate\n        if (angular.version.major > 1 || (angular.version.major === 1 && angular.version.minor >= 4)) {\n          $animate.enabled(element, false);\n        } else {\n          $animate.enabled(false, element);\n        }\n      }\n      catch (e) {}\n    },\n\n    enableAnimations: function (element) {\n      var $animate;\n      try {\n        $animate = $injector.get('$animate');\n        // See: http://brianhann.com/angular-1-4-breaking-changes-to-be-aware-of/#animate\n        if (angular.version.major > 1 || (angular.version.major === 1 && angular.version.minor >= 4)) {\n          $animate.enabled(element, true);\n        } else {\n          $animate.enabled(true, element);\n        }\n        return $animate;\n      }\n      catch (e) {}\n    },\n\n    // Blatantly stolen from Angular as it isn't exposed (yet. 2.0 maybe?)\n    nextUid: function nextUid() {\n      var index = uid.length;\n      var digit;\n\n      while (index) {\n        index--;\n        digit = uid[index].charCodeAt(0);\n        if (digit === 57 /*'9'*/) {\n          uid[index] = 'A';\n          return uidPrefix + uid.join('');\n        }\n        if (digit === 90  /*'Z'*/) {\n          uid[index] = '0';\n        } else {\n          uid[index] = String.fromCharCode(digit + 1);\n          return uidPrefix + uid.join('');\n        }\n      }\n      uid.unshift('0');\n\n      return uidPrefix + uid.join('');\n    },\n\n    // Blatantly stolen from Angular as it isn't exposed (yet. 2.0 maybe?)\n    hashKey: function hashKey(obj) {\n      var objType = typeof obj,\n          key;\n\n      if (objType === 'object' && obj !== null) {\n        if (typeof (key = obj.$$hashKey) === 'function') {\n          // must invoke on object to keep the right this\n          key = obj.$$hashKey();\n        }\n        else if (typeof(obj.$$hashKey) !== 'undefined' && obj.$$hashKey) {\n          key = obj.$$hashKey;\n        }\n        else if (key === undefined) {\n          key = obj.$$hashKey = s.nextUid();\n        }\n      }\n      else {\n        key = obj;\n      }\n\n      return objType + ':' + key;\n    },\n\n    resetUids: function () {\n      uid = ['0', '0', '0'];\n    },\n\n    /**\n     * @ngdoc method\n     * @methodOf ui.grid.service:GridUtil\n     * @name logError\n     * @description wraps the $log method, allowing us to choose different\n     * treatment within ui-grid if we so desired.  At present we only log\n     * error messages if uiGridConstants.LOG_ERROR_MESSAGES is set to true\n     * @param {string} logMessage message to be logged to the console\n     *\n     */\n    logError: function( logMessage ){\n      if ( uiGridConstants.LOG_ERROR_MESSAGES ){\n        $log.error( logMessage );\n      }\n    },\n\n    /**\n     * @ngdoc method\n     * @methodOf ui.grid.service:GridUtil\n     * @name logWarn\n     * @description wraps the $log method, allowing us to choose different\n     * treatment within ui-grid if we so desired.  At present we only log\n     * warning messages if uiGridConstants.LOG_WARN_MESSAGES is set to true\n     * @param {string} logMessage message to be logged to the console\n     *\n     */\n    logWarn: function( logMessage ){\n      if ( uiGridConstants.LOG_WARN_MESSAGES ){\n        $log.warn( logMessage );\n      }\n    },\n\n    /**\n     * @ngdoc method\n     * @methodOf ui.grid.service:GridUtil\n     * @name logDebug\n     * @description wraps the $log method, allowing us to choose different\n     * treatment within ui-grid if we so desired.  At present we only log\n     * debug messages if uiGridConstants.LOG_DEBUG_MESSAGES is set to true\n     *\n     */\n    logDebug: function() {\n      if ( uiGridConstants.LOG_DEBUG_MESSAGES ){\n        $log.debug.apply($log, arguments);\n      }\n    }\n\n  };\n\n  /**\n   * @ngdoc object\n   * @name focus\n   * @propertyOf ui.grid.service:GridUtil\n   * @description Provies a set of methods to set the document focus inside the grid.\n   * See {@link ui.grid.service:GridUtil.focus} for more information.\n   */\n\n  /**\n   * @ngdoc object\n   * @name ui.grid.service:GridUtil.focus\n   * @description Provies a set of methods to set the document focus inside the grid.\n   * Timeouts are utilized to ensure that the focus is invoked after any other event has been triggered.\n   * e.g. click events that need to run before the focus or\n   * inputs elements that are in a disabled state but are enabled when those events\n   * are triggered.\n   */\n  s.focus = {\n    queue: [],\n    //http://stackoverflow.com/questions/25596399/set-element-focus-in-angular-way\n    /**\n     * @ngdoc method\n     * @methodOf ui.grid.service:GridUtil.focus\n     * @name byId\n     * @description Sets the focus of the document to the given id value.\n     * If provided with the grid object it will automatically append the grid id.\n     * This is done to encourage unique dom id's as it allows for multiple grids on a\n     * page.\n     * @param {String} id the id of the dom element to set the focus on\n     * @param {Object=} Grid the grid object for this grid instance. See: {@link ui.grid.class:Grid}\n     * @param {Number} Grid.id the unique id for this grid. Already set on an initialized grid object.\n     * @returns {Promise} The `$timeout` promise that will be resolved once focus is set. If another focus is requested before this request is evaluated.\n     * then the promise will fail with the `'canceled'` reason.\n     */\n    byId: function (id, Grid) {\n      this._purgeQueue();\n      var promise = $timeout(function() {\n        var elementID = (Grid && Grid.id ? Grid.id + '-' : '') + id;\n        var element = $window.document.getElementById(elementID);\n        if (element) {\n          element.focus();\n        } else {\n          s.logWarn('[focus.byId] Element id ' + elementID + ' was not found.');\n        }\n      });\n      this.queue.push(promise);\n      return promise;\n    },\n\n    /**\n     * @ngdoc method\n     * @methodOf ui.grid.service:GridUtil.focus\n     * @name byElement\n     * @description Sets the focus of the document to the given dom element.\n     * @param {(element|angular.element)} element the DOM element to set the focus on\n     * @returns {Promise} The `$timeout` promise that will be resolved once focus is set. If another focus is requested before this request is evaluated.\n     * then the promise will fail with the `'canceled'` reason.\n     */\n    byElement: function(element){\n      if (!angular.isElement(element)){\n        s.logWarn(\"Trying to focus on an element that isn\\'t an element.\");\n        return $q.reject('not-element');\n      }\n      element = angular.element(element);\n      this._purgeQueue();\n      var promise = $timeout(function(){\n        if (element){\n          element[0].focus();\n        }\n      });\n      this.queue.push(promise);\n      return promise;\n    },\n    /**\n     * @ngdoc method\n     * @methodOf ui.grid.service:GridUtil.focus\n     * @name bySelector\n     * @description Sets the focus of the document to the given dom element.\n     * @param {(element|angular.element)} parentElement the parent/ancestor of the dom element that you are selecting using the query selector\n     * @param {String} querySelector finds the dom element using the {@link http://www.w3schools.com/jsref/met_document_queryselector.asp querySelector}\n     * @param {boolean} [aSync=false] If true then the selector will be querried inside of a timeout. Otherwise the selector will be querried imidately\n     * then the focus will be called.\n     * @returns {Promise} The `$timeout` promise that will be resolved once focus is set. If another focus is requested before this request is evaluated.\n     * then the promise will fail with the `'canceled'` reason.\n     */\n    bySelector: function(parentElement, querySelector, aSync){\n      var self = this;\n      if (!angular.isElement(parentElement)){\n        throw new Error(\"The parent element is not an element.\");\n      }\n      // Ensure that this is an angular element.\n      // It is fine if this is already an angular element.\n      parentElement = angular.element(parentElement);\n      var focusBySelector = function(){\n        var element = parentElement[0].querySelector(querySelector);\n        return self.byElement(element);\n      };\n      this._purgeQueue();\n      if (aSync){ //Do this asynchronysly\n        var promise = $timeout(focusBySelector);\n        this.queue.push($timeout(focusBySelector));\n        return promise;\n      } else {\n        return focusBySelector();\n      }\n    },\n    _purgeQueue: function(){\n      this.queue.forEach(function(element){\n        $timeout.cancel(element);\n      });\n      this.queue = [];\n    }\n  };\n\n\n  ['width', 'height'].forEach(function (name) {\n    var capsName = angular.uppercase(name.charAt(0)) + name.substr(1);\n    s['element' + capsName] = function (elem, extra) {\n      var e = elem;\n      if (e && typeof(e.length) !== 'undefined' && e.length) {\n        e = elem[0];\n      }\n\n      if (e) {\n        var styles = getStyles(e);\n        return e.offsetWidth === 0 && rdisplayswap.test(styles.display) ?\n                  s.swap(e, cssShow, function() {\n                    return getWidthOrHeight(e, name, extra );\n                  }) :\n                  getWidthOrHeight( e, name, extra );\n      }\n      else {\n        return null;\n      }\n    };\n\n    s['outerElement' + capsName] = function (elem, margin) {\n      return elem ? s['element' + capsName].call(this, elem, margin ? 'margin' : 'border') : null;\n    };\n  });\n\n  // http://stackoverflow.com/a/24107550/888165\n  s.closestElm = function closestElm(el, selector) {\n    if (typeof(el.length) !== 'undefined' && el.length) {\n      el = el[0];\n    }\n\n    var matchesFn;\n\n    // find vendor prefix\n    ['matches','webkitMatchesSelector','mozMatchesSelector','msMatchesSelector','oMatchesSelector'].some(function(fn) {\n        if (typeof document.body[fn] === 'function') {\n            matchesFn = fn;\n            return true;\n        }\n        return false;\n    });\n\n    // traverse parents\n    var parent;\n    while (el !== null) {\n      parent = el.parentElement;\n      if (parent !== null && parent[matchesFn](selector)) {\n          return parent;\n      }\n      el = parent;\n    }\n\n    return null;\n  };\n\n  s.type = function (obj) {\n    var text = Function.prototype.toString.call(obj.constructor);\n    return text.match(/function (.*?)\\(/)[1];\n  };\n\n  s.getBorderSize = function getBorderSize(elem, borderType) {\n    if (typeof(elem.length) !== 'undefined' && elem.length) {\n      elem = elem[0];\n    }\n\n    var styles = getStyles(elem);\n\n    // If a specific border is supplied, like 'top', read the 'borderTop' style property\n    if (borderType) {\n      borderType = 'border' + borderType.charAt(0).toUpperCase() + borderType.slice(1);\n    }\n    else {\n      borderType = 'border';\n    }\n\n    borderType += 'Width';\n\n    var val = parseInt(styles[borderType], 10);\n\n    if (isNaN(val)) {\n      return 0;\n    }\n    else {\n      return val;\n    }\n  };\n\n  // http://stackoverflow.com/a/22948274/888165\n  // TODO: Opera? Mobile?\n  s.detectBrowser = function detectBrowser() {\n    var userAgent = $window.navigator.userAgent;\n\n    var browsers = {chrome: /chrome/i, safari: /safari/i, firefox: /firefox/i, ie: /internet explorer|trident\\//i};\n\n    for (var key in browsers) {\n      if (browsers[key].test(userAgent)) {\n        return key;\n      }\n    }\n\n    return 'unknown';\n  };\n\n  // Borrowed from https://github.com/othree/jquery.rtl-scroll-type\n  // Determine the scroll \"type\" this browser is using for RTL\n  s.rtlScrollType = function rtlScrollType() {\n    if (rtlScrollType.type) {\n      return rtlScrollType.type;\n    }\n\n    var definer = angular.element('<div dir=\"rtl\" style=\"font-size: 14px; width: 1px; height: 1px; position: absolute; top: -1000px; overflow: scroll\">A</div>')[0],\n        type = 'reverse';\n\n    document.body.appendChild(definer);\n\n    if (definer.scrollLeft > 0) {\n      type = 'default';\n    }\n    else {\n      definer.scrollLeft = 1;\n      if (definer.scrollLeft === 0) {\n        type = 'negative';\n      }\n    }\n\n    angular.element(definer).remove();\n    rtlScrollType.type = type;\n\n    return type;\n  };\n\n    /**\n     * @ngdoc method\n     * @name normalizeScrollLeft\n     * @methodOf ui.grid.service:GridUtil\n     *\n     * @param {element} element The element to get the `scrollLeft` from.\n     * @param {grid} grid -  grid used to normalize (uses the rtl property)\n     *\n     * @returns {number} A normalized scrollLeft value for the current browser.\n     *\n     * @description\n     * Browsers currently handle RTL in different ways, resulting in inconsistent scrollLeft values. This method normalizes them\n     */\n  s.normalizeScrollLeft = function normalizeScrollLeft(element, grid) {\n    if (typeof(element.length) !== 'undefined' && element.length) {\n      element = element[0];\n    }\n\n    var scrollLeft = element.scrollLeft;\n\n    if (grid.isRTL()) {\n      switch (s.rtlScrollType()) {\n        case 'default':\n          return element.scrollWidth - scrollLeft - element.clientWidth;\n        case 'negative':\n          return Math.abs(scrollLeft);\n        case 'reverse':\n          return scrollLeft;\n      }\n    }\n\n    return scrollLeft;\n  };\n\n  /**\n  * @ngdoc method\n  * @name denormalizeScrollLeft\n  * @methodOf ui.grid.service:GridUtil\n  *\n  * @param {element} element The element to normalize the `scrollLeft` value for\n  * @param {number} scrollLeft The `scrollLeft` value to denormalize.\n  * @param {grid} grid The grid that owns the scroll event.\n  *\n  * @returns {number} A normalized scrollLeft value for the current browser.\n  *\n  * @description\n  * Browsers currently handle RTL in different ways, resulting in inconsistent scrollLeft values. This method denormalizes a value for the current browser.\n  */\n  s.denormalizeScrollLeft = function denormalizeScrollLeft(element, scrollLeft, grid) {\n    if (typeof(element.length) !== 'undefined' && element.length) {\n      element = element[0];\n    }\n\n    if (grid.isRTL()) {\n      switch (s.rtlScrollType()) {\n        case 'default':\n          // Get the max scroll for the element\n          var maxScrollLeft = element.scrollWidth - element.clientWidth;\n\n          // Subtract the current scroll amount from the max scroll\n          return maxScrollLeft - scrollLeft;\n        case 'negative':\n          return scrollLeft * -1;\n        case 'reverse':\n          return scrollLeft;\n      }\n    }\n\n    return scrollLeft;\n  };\n\n    /**\n     * @ngdoc method\n     * @name preEval\n     * @methodOf ui.grid.service:GridUtil\n     *\n     * @param {string} path Path to evaluate\n     *\n     * @returns {string} A path that is normalized.\n     *\n     * @description\n     * Takes a field path and converts it to bracket notation to allow for special characters in path\n     * @example\n     * <pre>\n     * gridUtil.preEval('property') == 'property'\n     * gridUtil.preEval('nested.deep.prop-erty') = \"nested['deep']['prop-erty']\"\n     * </pre>\n     */\n  s.preEval = function (path) {\n    var m = uiGridConstants.BRACKET_REGEXP.exec(path);\n    if (m) {\n      return (m[1] ? s.preEval(m[1]) : m[1]) + m[2] + (m[3] ? s.preEval(m[3]) : m[3]);\n    } else {\n      path = path.replace(uiGridConstants.APOS_REGEXP, '\\\\\\'');\n      var parts = path.split(uiGridConstants.DOT_REGEXP);\n      var preparsed = [parts.shift()];    // first item must be var notation, thus skip\n      angular.forEach(parts, function (part) {\n        preparsed.push(part.replace(uiGridConstants.FUNC_REGEXP, '\\']$1'));\n      });\n      return preparsed.join('[\\'');\n    }\n  };\n\n  /**\n   * @ngdoc method\n   * @name debounce\n   * @methodOf ui.grid.service:GridUtil\n   *\n   * @param {function} func function to debounce\n   * @param {number} wait milliseconds to delay\n   * @param {boolean} immediate execute before delay\n   *\n   * @returns {function} A function that can be executed as debounced function\n   *\n   * @description\n   * Copied from https://github.com/shahata/angular-debounce\n   * Takes a function, decorates it to execute only 1 time after multiple calls, and returns the decorated function\n   * @example\n   * <pre>\n   * var debouncedFunc =  gridUtil.debounce(function(){alert('debounced');}, 500);\n   * debouncedFunc();\n   * debouncedFunc();\n   * debouncedFunc();\n   * </pre>\n   */\n  s.debounce =  function (func, wait, immediate) {\n    var timeout, args, context, result;\n    function debounce() {\n      /* jshint validthis:true */\n      context = this;\n      args = arguments;\n      var later = function () {\n        timeout = null;\n        if (!immediate) {\n          result = func.apply(context, args);\n        }\n      };\n      var callNow = immediate && !timeout;\n      if (timeout) {\n        $timeout.cancel(timeout);\n      }\n      timeout = $timeout(later, wait, false);\n      if (callNow) {\n        result = func.apply(context, args);\n      }\n      return result;\n    }\n    debounce.cancel = function () {\n      $timeout.cancel(timeout);\n      timeout = null;\n    };\n    return debounce;\n  };\n\n  /**\n   * @ngdoc method\n   * @name throttle\n   * @methodOf ui.grid.service:GridUtil\n   *\n   * @param {function} func function to throttle\n   * @param {number} wait milliseconds to delay after first trigger\n   * @param {Object} params to use in throttle.\n   *\n   * @returns {function} A function that can be executed as throttled function\n   *\n   * @description\n   * Adapted from debounce function (above)\n   * Potential keys for Params Object are:\n   *    trailing (bool) - whether to trigger after throttle time ends if called multiple times\n   * Updated to use $interval rather than $timeout, as protractor (e2e tests) is able to work with $interval,\n   * but not with $timeout\n   *\n   * Note that when using throttle, you need to use throttle to create a new function upfront, then use the function\n   * return from that call each time you need to call throttle.  If you call throttle itself repeatedly, the lastCall\n   * variable will get overwritten and the throttling won't work\n   *\n   * @example\n   * <pre>\n   * var throttledFunc =  gridUtil.throttle(function(){console.log('throttled');}, 500, {trailing: true});\n   * throttledFunc(); //=> logs throttled\n   * throttledFunc(); //=> queues attempt to log throttled for ~500ms (since trailing param is truthy)\n   * throttledFunc(); //=> updates arguments to keep most-recent request, but does not do anything else.\n   * </pre>\n   */\n  s.throttle = function(func, wait, options){\n    options = options || {};\n    var lastCall = 0, queued = null, context, args;\n\n    function runFunc(endDate){\n      lastCall = +new Date();\n      func.apply(context, args);\n      $interval(function(){queued = null; }, 0, 1, false);\n    }\n\n    return function(){\n      /* jshint validthis:true */\n      context = this;\n      args = arguments;\n      if (queued === null){\n        var sinceLast = +new Date() - lastCall;\n        if (sinceLast > wait){\n          runFunc();\n        }\n        else if (options.trailing){\n          queued = $interval(runFunc, wait - sinceLast, 1, false);\n        }\n      }\n    };\n  };\n\n  s.on = {};\n  s.off = {};\n  s._events = {};\n\n  s.addOff = function (eventName) {\n    s.off[eventName] = function (elm, fn) {\n      var idx = s._events[eventName].indexOf(fn);\n      if (idx > 0) {\n        s._events[eventName].removeAt(idx);\n      }\n    };\n  };\n\n  var mouseWheeltoBind = ( 'onwheel' in document || document.documentMode >= 9 ) ? ['wheel'] : ['mousewheel', 'DomMouseScroll', 'MozMousePixelScroll'],\n      nullLowestDeltaTimeout,\n      lowestDelta;\n\n  s.on.mousewheel = function (elm, fn) {\n    if (!elm || !fn) { return; }\n\n    var $elm = angular.element(elm);\n\n    // Store the line height and page height for this particular element\n    $elm.data('mousewheel-line-height', getLineHeight($elm));\n    $elm.data('mousewheel-page-height', s.elementHeight($elm));\n    if (!$elm.data('mousewheel-callbacks')) { $elm.data('mousewheel-callbacks', {}); }\n\n    var cbs = $elm.data('mousewheel-callbacks');\n    cbs[fn] = (Function.prototype.bind || bindPolyfill).call(mousewheelHandler, $elm[0], fn);\n\n    // Bind all the mousew heel events\n    for ( var i = mouseWheeltoBind.length; i; ) {\n      $elm.on(mouseWheeltoBind[--i], cbs[fn]);\n    }\n  };\n  s.off.mousewheel = function (elm, fn) {\n    var $elm = angular.element(elm);\n\n    var cbs = $elm.data('mousewheel-callbacks');\n    var handler = cbs[fn];\n\n    if (handler) {\n      for ( var i = mouseWheeltoBind.length; i; ) {\n        $elm.off(mouseWheeltoBind[--i], handler);\n      }\n    }\n\n    delete cbs[fn];\n\n    if (Object.keys(cbs).length === 0) {\n      $elm.removeData('mousewheel-line-height');\n      $elm.removeData('mousewheel-page-height');\n      $elm.removeData('mousewheel-callbacks');\n    }\n  };\n\n  function mousewheelHandler(fn, event) {\n    var $elm = angular.element(this);\n\n    var delta      = 0,\n        deltaX     = 0,\n        deltaY     = 0,\n        absDelta   = 0,\n        offsetX    = 0,\n        offsetY    = 0;\n\n    // jQuery masks events\n    if (event.originalEvent) { event = event.originalEvent; }\n\n    if ( 'detail'      in event ) { deltaY = event.detail * -1;      }\n    if ( 'wheelDelta'  in event ) { deltaY = event.wheelDelta;       }\n    if ( 'wheelDeltaY' in event ) { deltaY = event.wheelDeltaY;      }\n    if ( 'wheelDeltaX' in event ) { deltaX = event.wheelDeltaX * -1; }\n\n    // Firefox < 17 horizontal scrolling related to DOMMouseScroll event\n    if ( 'axis' in event && event.axis === event.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 event ) {\n      deltaY = event.deltaY * -1;\n      delta  = deltaY;\n    }\n    if ( 'deltaX' in event ) {\n      deltaX = event.deltaX;\n      if ( deltaY === 0 ) { delta  = deltaX * -1; }\n    }\n\n    // No change actually happened, no reason to go any further\n    if ( deltaY === 0 && deltaX === 0 ) { return; }\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 ( event.deltaMode === 1 ) {\n        var lineHeight = $elm.data('mousewheel-line-height');\n        delta  *= lineHeight;\n        deltaY *= lineHeight;\n        deltaX *= lineHeight;\n    }\n    else if ( event.deltaMode === 2 ) {\n        var pageHeight = $elm.data('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(event, absDelta) ) {\n        lowestDelta /= 40;\n      }\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 ($elm[0].getBoundingClientRect ) {\n    //   var boundingRect = $(elm)[0].getBoundingClientRect();\n    //   offsetX = event.clientX - boundingRect.left;\n    //   offsetY = event.clientY - boundingRect.top;\n    // }\n\n    // event.deltaX = deltaX;\n    // event.deltaY = deltaY;\n    // event.deltaFactor = lowestDelta;\n\n    var newEvent = {\n      originalEvent: event,\n      deltaX: deltaX,\n      deltaY: deltaY,\n      deltaFactor: lowestDelta,\n      preventDefault: function () { event.preventDefault(); },\n      stopPropagation: function () { event.stopPropagation(); }\n    };\n\n    // Clearout lowestDelta after sometime to better\n    // handle multiple device types that give\n    // a different lowestDelta\n    // Ex: trackpad = 3 and mouse wheel = 120\n    if (nullLowestDeltaTimeout) { clearTimeout(nullLowestDeltaTimeout); }\n    nullLowestDeltaTimeout = setTimeout(nullLowestDelta, 200);\n\n    fn.call($elm[0], newEvent);\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 orgEvent.type === 'mousewheel' && absDelta % 120 === 0;\n  }\n\n  return s;\n}]);\n\n// Add 'px' to the end of a number string if it doesn't have it already\nmodule.filter('px', function() {\n  return function(str) {\n    if (str.match(/^[\\d\\.]+$/)) {\n      return str + 'px';\n    }\n    else {\n      return str;\n    }\n  };\n});\n\n})();\n\n(function () {\n  angular.module('ui.grid').config(['$provide', function($provide) {\n    $provide.decorator('i18nService', ['$delegate', function($delegate) {\n      var lang = {\n              aggregate: {\n                  label: 'položky'\n              },\n              groupPanel: {\n                  description: 'Přesuňte záhlaví zde pro vytvoření skupiny dle sloupce.'\n              },\n              search: {\n                  placeholder: 'Hledat...',\n                  showingItems: 'Zobrazuji položky:',\n                  selectedItems: 'Vybrané položky:',\n                  totalItems: 'Celkem položek:',\n                  size: 'Velikost strany:',\n                  first: 'První strana',\n                  next: 'Další strana',\n                  previous: 'Předchozí strana',\n                  last: 'Poslední strana'\n              },\n              menu: {\n                  text: 'Vyberte sloupec:'\n              },\n              sort: {\n                  ascending: 'Seřadit od A-Z',\n                  descending: 'Seřadit od Z-A',\n                  remove: 'Odebrat seřazení'\n              },\n              column: {\n                  hide: 'Schovat sloupec'\n              },\n              aggregation: {\n                  count: 'celkem řádků: ',\n                  sum: 'celkem: ',\n                  avg: 'avg: ',\n                  min: 'min.: ',\n                  max: 'max.: '\n              },\n              pinning: {\n                  pinLeft: 'Zamknout vlevo',\n                  pinRight: 'Zamknout vpravo',\n                  unpin: 'Odemknout'\n              },\n              gridMenu: {\n                  columns: 'Sloupce:',\n                  importerTitle: 'Importovat soubor',\n                  exporterAllAsCsv: 'Exportovat všechna data do csv',\n                  exporterVisibleAsCsv: 'Exportovat viditelná data do csv',\n                  exporterSelectedAsCsv: 'Exportovat vybraná data do csv',\n                  exporterAllAsPdf: 'Exportovat všechna data do pdf',\n                  exporterVisibleAsPdf: 'Exportovat viditelná data do pdf',\n                  exporterSelectedAsPdf: 'Exportovat vybraná data do pdf',\n                  clearAllFilters: 'Odstranit všechny filtry'\n              },\n              importer: {\n                  noHeaders: 'Názvy sloupců se nepodařilo získat, obsahuje soubor záhlaví?',\n                  noObjects: 'Data se nepodařilo zpracovat, obsahuje soubor řádky mimo záhlaví?',\n                  invalidCsv: 'Soubor nelze zpracovat, jedná se o CSV?',\n                  invalidJson: 'Soubor nelze zpracovat, je to JSON?',\n                  jsonNotArray: 'Soubor musí obsahovat json. Ukončuji..'\n              },\n              pagination: {\n                  sizes: 'položek na stránku',\n                  totalItems: 'položek'\n              },\n              grouping: {\n                  group: 'Seskupit',\n                  ungroup: 'Odebrat seskupení',\n                  aggregate_count: 'Agregace: Count',\n                  aggregate_sum: 'Agregace: Sum',\n                  aggregate_max: 'Agregace: Max',\n                  aggregate_min: 'Agregace: Min',\n                  aggregate_avg: 'Agregace: Avg',\n                  aggregate_remove: 'Agregace: Odebrat'\n              }\n          };\n\n          // support varianty of different czech keys.\n          $delegate.add('cs', lang);\n          $delegate.add('cz', lang);\n          $delegate.add('cs-cz', lang);\n          $delegate.add('cs-CZ', lang);\n      return $delegate;\n    }]);\n  }]);\n})();\n\n(function(){\n  angular.module('ui.grid').config(['$provide', function($provide) {\n    $provide.decorator('i18nService', ['$delegate', function($delegate) {\n      $delegate.add('da', {\n        aggregate:{\n          label: 'artikler'\n        },\n        groupPanel:{\n          description: 'Grupér rækker udfra en kolonne ved at trække dens overskift hertil.'\n        },\n        search:{\n          placeholder: 'Søg...',\n          showingItems: 'Viste rækker:',\n          selectedItems: 'Valgte rækker:',\n          totalItems: 'Rækker totalt:',\n          size: 'Side størrelse:',\n          first: 'Første side',\n          next: 'Næste side',\n          previous: 'Forrige side',\n          last: 'Sidste side'\n        },\n        menu:{\n          text: 'Vælg kolonner:'\n        },\n        sort: {\n          ascending: 'Sorter stigende',\n          descending: 'Sorter faldende',\n          none: 'Sorter ingen',\n          remove: 'Fjern sortering'\n        },\n        column: {\n          hide: 'Skjul kolonne'\n        },\n        aggregation: {\n          count: 'antal rækker: ',\n          sum: 'sum: ',\n          avg: 'gns: ',\n          min: 'min: ',\n          max: 'max: '\n        },\n        gridMenu: {\n          columns: 'Kolonner:',\n          importerTitle: 'Importer fil',\n          exporterAllAsCsv: 'Eksporter alle data som csv',\n          exporterVisibleAsCsv: 'Eksporter synlige data som csv',\n          exporterSelectedAsCsv: 'Eksporter markerede data som csv',\n          exporterAllAsPdf: 'Eksporter alle data som pdf',\n          exporterVisibleAsPdf: 'Eksporter synlige data som pdf',\n          exporterSelectedAsPdf: 'Eksporter markerede data som pdf',\n          clearAllFilters: 'Clear all filters'\n        },\n        importer: {\n          noHeaders: 'Column names were unable to be derived, does the file have a header?',\n          noObjects: 'Objects were not able to be derived, was there data in the file other than headers?',\n          invalidCsv: 'File was unable to be processed, is it valid CSV?',\n          invalidJson: 'File was unable to be processed, is it valid Json?',\n          jsonNotArray: 'Imported json file must contain an array, aborting.'\n        },\n        pagination: {\n          aria: {\n            pageToFirst: 'Gå til første',\n            pageBack: 'Gå tilbage',\n            pageSelected: 'Valgte side',\n            pageForward: 'Gå frem',\n            pageToLast: 'Gå til sidste'\n          },\n          sizes: 'genstande per side',\n          totalItems: 'genstande',\n          through: 'gennem',\n          of: 'af'\n        }\n      });\n      return $delegate;\n    }]);\n  }]);\n})();\n\n(function () {\n  angular.module('ui.grid').config(['$provide', function ($provide) {\n    $provide.decorator('i18nService', ['$delegate', function ($delegate) {\n      $delegate.add('de', {\n        headerCell: {\n          aria: {\n            defaultFilterLabel: 'Filter für Spalte',\n            removeFilter: 'Filter löschen',\n            columnMenuButtonLabel: 'Spaltenmenü'\n          },\n          priority: 'Priorität:',\n          filterLabel: \"Filter für Spalte: \"\n        },\n        aggregate: {\n          label: 'Eintrag'\n        },\n        groupPanel: {\n          description: 'Ziehen Sie eine Spaltenüberschrift hierhin, um nach dieser Spalte zu gruppieren.'\n        },\n        search: {\n          placeholder: 'Suche...',\n          showingItems: 'Zeige Einträge:',\n          selectedItems: 'Ausgewählte Einträge:',\n          totalItems: 'Einträge gesamt:',\n          size: 'Einträge pro Seite:',\n          first: 'Erste Seite',\n          next: 'Nächste Seite',\n          previous: 'Vorherige Seite',\n          last: 'Letzte Seite'\n        },\n        menu: {\n          text: 'Spalten auswählen:'\n        },\n        sort: {\n          ascending: 'aufsteigend sortieren',\n          descending: 'absteigend sortieren',\n          none: 'keine Sortierung',\n          remove: 'Sortierung zurücksetzen'\n        },\n        column: {\n          hide: 'Spalte ausblenden'\n        },\n        aggregation: {\n          count: 'Zeilen insgesamt: ',\n          sum: 'gesamt: ',\n          avg: 'Durchschnitt: ',\n          min: 'min: ',\n          max: 'max: '\n        },\n        pinning: {\n            pinLeft: 'Links anheften',\n            pinRight: 'Rechts anheften',\n            unpin: 'Lösen'\n        },\n        columnMenu: {\n          close: 'Schließen'\n        },\n        gridMenu: {\n          aria: {\n            buttonLabel: 'Tabellenmenü'\n          },\n          columns: 'Spalten:',\n          importerTitle: 'Datei importieren',\n          exporterAllAsCsv: 'Alle Daten als CSV exportieren',\n          exporterVisibleAsCsv: 'sichtbare Daten als CSV exportieren',\n          exporterSelectedAsCsv: 'markierte Daten als CSV exportieren',\n          exporterAllAsPdf: 'Alle Daten als PDF exportieren',\n          exporterVisibleAsPdf: 'sichtbare Daten als PDF exportieren',\n          exporterSelectedAsPdf: 'markierte Daten als PDF exportieren',\n          clearAllFilters: 'Alle Filter zurücksetzen'\n        },\n        importer: {\n          noHeaders: 'Es konnten keine Spaltennamen ermittelt werden. Sind in der Datei Spaltendefinitionen enthalten?',\n          noObjects: 'Es konnten keine Zeileninformationen gelesen werden, Sind in der Datei außer den Spaltendefinitionen auch Daten enthalten?',\n          invalidCsv: 'Die Datei konnte nicht eingelesen werden, ist es eine gültige CSV-Datei?',\n          invalidJson: 'Die Datei konnte nicht eingelesen werden. Enthält sie gültiges JSON?',\n          jsonNotArray: 'Die importierte JSON-Datei muß ein Array enthalten. Breche Import ab.'\n        },\n        pagination: {\n          aria: {\n            pageToFirst: 'Zum Anfang',\n            pageBack: 'Seite zurück',\n            pageSelected: 'Ausgwählte Seite',\n            pageForward: 'Seite vor',\n            pageToLast: 'Zum Ende'\n          },\n          sizes: 'Einträge pro Seite',\n          totalItems: 'Einträge',\n          through: 'bis',\n          of: 'von'\n        },\n        grouping: {\n            group: 'Gruppieren',\n            ungroup: 'Gruppierung aufheben',\n            aggregate_count: 'Agg: Anzahl',\n            aggregate_sum: 'Agg: Summe',\n            aggregate_max: 'Agg: Maximum',\n            aggregate_min: 'Agg: Minimum',\n            aggregate_avg: 'Agg: Mittelwert',\n            aggregate_remove: 'Aggregation entfernen'\n        }\n      });\n      return $delegate;\n    }]);\n  }]);\n})();\n\n(function () {\n  angular.module('ui.grid').config(['$provide', function($provide) {\n    $provide.decorator('i18nService', ['$delegate', function($delegate) {\n      $delegate.add('en', {\n        headerCell: {\n          aria: {\n            defaultFilterLabel: 'Filter for column',\n            removeFilter: 'Remove Filter',\n            columnMenuButtonLabel: 'Column Menu'\n          },\n          priority: 'Priority:',\n          filterLabel: \"Filter for column: \"\n        },\n        aggregate: {\n          label: 'items'\n        },\n        groupPanel: {\n          description: 'Drag a column header here and drop it to group by that column.'\n        },\n        search: {\n          placeholder: 'Search...',\n          showingItems: 'Showing Items:',\n          selectedItems: 'Selected Items:',\n          totalItems: 'Total Items:',\n          size: 'Page Size:',\n          first: 'First Page',\n          next: 'Next Page',\n          previous: 'Previous Page',\n          last: 'Last Page'\n        },\n        menu: {\n          text: 'Choose Columns:'\n        },\n        sort: {\n          ascending: 'Sort Ascending',\n          descending: 'Sort Descending',\n          none: 'Sort None',\n          remove: 'Remove Sort'\n        },\n        column: {\n          hide: 'Hide Column'\n        },\n        aggregation: {\n          count: 'total rows: ',\n          sum: 'total: ',\n          avg: 'avg: ',\n          min: 'min: ',\n          max: 'max: '\n        },\n        pinning: {\n          pinLeft: 'Pin Left',\n          pinRight: 'Pin Right',\n          unpin: 'Unpin'\n        },\n        columnMenu: {\n          close: 'Close'\n        },\n        gridMenu: {\n          aria: {\n            buttonLabel: 'Grid Menu'\n          },\n          columns: 'Columns:',\n          importerTitle: 'Import file',\n          exporterAllAsCsv: 'Export all data as csv',\n          exporterVisibleAsCsv: 'Export visible data as csv',\n          exporterSelectedAsCsv: 'Export selected data as csv',\n          exporterAllAsPdf: 'Export all data as pdf',\n          exporterVisibleAsPdf: 'Export visible data as pdf',\n          exporterSelectedAsPdf: 'Export selected data as pdf',\n          clearAllFilters: 'Clear all filters'\n        },\n        importer: {\n          noHeaders: 'Column names were unable to be derived, does the file have a header?',\n          noObjects: 'Objects were not able to be derived, was there data in the file other than headers?',\n          invalidCsv: 'File was unable to be processed, is it valid CSV?',\n          invalidJson: 'File was unable to be processed, is it valid Json?',\n          jsonNotArray: 'Imported json file must contain an array, aborting.'\n        },\n        pagination: {\n          aria: {\n            pageToFirst: 'Page to first',\n            pageBack: 'Page back',\n            pageSelected: 'Selected page',\n            pageForward: 'Page forward',\n            pageToLast: 'Page to last'\n          },\n          sizes: 'items per page',\n          totalItems: 'items',\n          through: 'through',\n          of: 'of'\n        },\n        grouping: {\n          group: 'Group',\n          ungroup: 'Ungroup',\n          aggregate_count: 'Agg: Count',\n          aggregate_sum: 'Agg: Sum',\n          aggregate_max: 'Agg: Max',\n          aggregate_min: 'Agg: Min',\n          aggregate_avg: 'Agg: Avg',\n          aggregate_remove: 'Agg: Remove'\n        },\n        validate: {\n          error: 'Error:',\n          minLength: 'Value should be at least THRESHOLD characters long.',\n          maxLength: 'Value should be at most THRESHOLD characters long.',\n          required: 'A value is needed.'\n        }\n      });\n      return $delegate;\n    }]);\n  }]);\n})();\n\n(function () {\n  angular.module('ui.grid').config(['$provide', function($provide) {\n    $provide.decorator('i18nService', ['$delegate', function($delegate) {\n      $delegate.add('es', {\n        aggregate: {\n          label: 'Artículos'\n        },\n        groupPanel: {\n          description: 'Arrastre un encabezado de columna aquí y suéltelo para agrupar por esa columna.'\n        },\n        search: {\n          placeholder: 'Buscar...',\n          showingItems: 'Artículos Mostrados:',\n          selectedItems: 'Artículos Seleccionados:',\n          totalItems: 'Artículos Totales:',\n          size: 'Tamaño de Página:',\n          first: 'Primera Página',\n          next: 'Página Siguiente',\n          previous: 'Página Anterior',\n          last: 'Última Página'\n        },\n        menu: {\n          text: 'Elegir columnas:'\n        },\n        sort: {\n          ascending: 'Orden Ascendente',\n          descending: 'Orden Descendente',\n          remove: 'Sin Ordenar'\n        },\n        column: {\n          hide: 'Ocultar la columna'\n        },\n        aggregation: {\n          count: 'filas totales: ',\n          sum: 'total: ',\n          avg: 'media: ',\n          min: 'min: ',\n          max: 'max: '\n        },\n        pinning: {\n          pinLeft: 'Fijar a la Izquierda',\n          pinRight: 'Fijar a la Derecha',\n          unpin: 'Quitar Fijación'\n        },\n        gridMenu: {\n          columns: 'Columnas:',\n          importerTitle: 'Importar archivo',\n          exporterAllAsCsv: 'Exportar todo como csv',\n          exporterVisibleAsCsv: 'Exportar vista como csv',\n          exporterSelectedAsCsv: 'Exportar selección como csv',\n          exporterAllAsPdf: 'Exportar todo como pdf',\n          exporterVisibleAsPdf: 'Exportar vista como pdf',\n          exporterSelectedAsPdf: 'Exportar selección como pdf',\n          clearAllFilters: 'Limpiar todos los filtros'\n        },\n        importer: {\n          noHeaders: 'No fue posible derivar los nombres de las columnas, ¿tiene encabezados el archivo?',\n          noObjects: 'No fue posible obtener registros, ¿contiene datos el archivo, aparte de los encabezados?',\n          invalidCsv: 'No fue posible procesar el archivo, ¿es un CSV válido?',\n          invalidJson: 'No fue posible procesar el archivo, ¿es un Json válido?',\n          jsonNotArray: 'El archivo json importado debe contener un array, abortando.'\n        },\n        pagination: {\n          sizes: 'registros por página',\n          totalItems: 'registros',\n          of: 'de'\n        },\n        grouping: {\n          group: 'Agrupar',\n          ungroup: 'Desagrupar',\n          aggregate_count: 'Agr: Cont',\n          aggregate_sum: 'Agr: Sum',\n          aggregate_max: 'Agr: Máx',\n          aggregate_min: 'Agr: Min',\n          aggregate_avg: 'Agr: Prom',\n          aggregate_remove: 'Agr: Quitar'\n        }\n      });\n      return $delegate;\n    }]);\n}]);\n})();\n\n/**\n * Translated by: R. Salarmehr\n *                M. Hosseynzade\n *                Using Vajje.com online dictionary.\n */\n(function () {\n  angular.module('ui.grid').config(['$provide', function ($provide) {\n    $provide.decorator('i18nService', ['$delegate', function ($delegate) {\n      $delegate.add('fa', {\n        aggregate: {\n          label: 'قلم'\n        },\n        groupPanel: {\n          description: 'عنوان یک ستون را بگیر و به گروهی از آن ستون رها کن.'\n        },\n        search: {\n          placeholder: 'جستجو...',\n          showingItems: 'نمایش اقلام:',\n          selectedItems: 'قلم\\u200cهای انتخاب شده:',\n          totalItems: 'مجموع اقلام:',\n          size: 'اندازه\\u200cی صفحه:',\n          first: 'اولین صفحه',\n          next: 'صفحه\\u200cی\\u200cبعدی',\n          previous: 'صفحه\\u200cی\\u200c قبلی',\n          last: 'آخرین صفحه'\n        },\n        menu: {\n          text: 'ستون\\u200cهای انتخابی:'\n        },\n        sort: {\n          ascending: 'ترتیب صعودی',\n          descending: 'ترتیب نزولی',\n          remove: 'حذف مرتب کردن'\n        },\n        column: {\n          hide: 'پنهان\\u200cکردن ستون'\n        },\n        aggregation: {\n          count: 'تعداد: ',\n          sum: 'مجموع: ',\n          avg: 'میانگین: ',\n          min: 'کمترین: ',\n          max: 'بیشترین: '\n        },\n        pinning: {\n          pinLeft: 'پین کردن سمت چپ',\n          pinRight: 'پین کردن سمت راست',\n          unpin: 'حذف پین'\n        },\n        gridMenu: {\n          columns: 'ستون\\u200cها:',\n          importerTitle: 'وارد کردن فایل',\n          exporterAllAsCsv: 'خروجی تمام داده\\u200cها در فایل csv',\n          exporterVisibleAsCsv: 'خروجی داده\\u200cهای قابل مشاهده در فایل csv',\n          exporterSelectedAsCsv: 'خروجی داده\\u200cهای انتخاب\\u200cشده در فایل csv',\n          exporterAllAsPdf: 'خروجی تمام داده\\u200cها در فایل pdf',\n          exporterVisibleAsPdf: 'خروجی داده\\u200cهای قابل مشاهده در فایل pdf',\n          exporterSelectedAsPdf: 'خروجی داده\\u200cهای انتخاب\\u200cشده در فایل pdf',\n          clearAllFilters: 'پاک کردن تمام فیلتر'\n        },\n        importer: {\n          noHeaders: 'نام ستون قابل استخراج نیست. آیا فایل عنوان دارد؟',\n          noObjects: 'اشیا قابل استخراج نیستند. آیا به جز عنوان\\u200cها در فایل داده وجود دارد؟',\n          invalidCsv: 'فایل قابل پردازش نیست. آیا فرمت  csv  معتبر است؟',\n          invalidJson: 'فایل قابل پردازش نیست. آیا فرمت json   معتبر است؟',\n          jsonNotArray: 'فایل json وارد شده باید حاوی آرایه باشد. عملیات ساقط شد.'\n        },\n        pagination: {\n          sizes: 'اقلام در هر صفحه',\n          totalItems: 'اقلام',\n          of: 'از'\n        },\n        grouping: {\n          group: 'گروه\\u200cبندی',\n          ungroup: 'حذف گروه\\u200cبندی',\n          aggregate_count: 'Agg: تعداد',\n          aggregate_sum: 'Agg: جمع',\n          aggregate_max: 'Agg: بیشینه',\n          aggregate_min: 'Agg: کمینه',\n          aggregate_avg: 'Agg: میانگین',\n          aggregate_remove: 'Agg: حذف'\n        }\n      });\n      return $delegate;\n    }]);\n  }]);\n})();\n\n(function () {\n  angular.module('ui.grid').config(['$provide', function($provide) {\n    $provide.decorator('i18nService', ['$delegate', function($delegate) {\n      $delegate.add('fi', {\n        aggregate: {\n          label: 'rivit'\n        },\n        groupPanel: {\n          description: 'Raahaa ja pudota otsikko tähän ryhmittääksesi sarakkeen mukaan.'\n        },\n        search: {\n          placeholder: 'Hae...',\n          showingItems: 'Näytetään rivejä:',\n          selectedItems: 'Valitut rivit:',\n          totalItems: 'Rivejä yht.:',\n          size: 'Näytä:',\n          first: 'Ensimmäinen sivu',\n          next: 'Seuraava sivu',\n          previous: 'Edellinen sivu',\n          last: 'Viimeinen sivu'\n        },\n        menu: {\n          text: 'Valitse sarakkeet:'\n        },\n        sort: {\n          ascending: 'Järjestä nouseva',\n          descending: 'Järjestä laskeva',\n          remove: 'Poista järjestys'\n        },\n        column: {\n          hide: 'Piilota sarake'\n        },\n        aggregation: {\n          count: 'Rivejä yht.: ',\n          sum: 'Summa: ',\n          avg: 'K.a.: ',\n          min: 'Min: ',\n          max: 'Max: '\n        },\n        pinning: {\n         pinLeft: 'Lukitse vasemmalle',\n          pinRight: 'Lukitse oikealle',\n          unpin: 'Poista lukitus'\n        },\n        gridMenu: {\n          columns: 'Sarakkeet:',\n          importerTitle: 'Tuo tiedosto',\n          exporterAllAsCsv: 'Vie tiedot csv-muodossa',\n          exporterVisibleAsCsv: 'Vie näkyvä tieto csv-muodossa',\n          exporterSelectedAsCsv: 'Vie valittu tieto csv-muodossa',\n          exporterAllAsPdf: 'Vie tiedot pdf-muodossa',\n          exporterVisibleAsPdf: 'Vie näkyvä tieto pdf-muodossa',\n          exporterSelectedAsPdf: 'Vie valittu tieto pdf-muodossa',\n          clearAllFilters: 'Puhdista kaikki suodattimet'\n        },\n        importer: {\n          noHeaders: 'Sarakkeen nimiä ei voitu päätellä, onko tiedostossa otsikkoriviä?',\n          noObjects: 'Tietoja ei voitu lukea, onko tiedostossa muuta kuin otsikkot?',\n          invalidCsv: 'Tiedostoa ei voitu käsitellä, oliko se CSV-muodossa?',\n          invalidJson: 'Tiedostoa ei voitu käsitellä, oliko se JSON-muodossa?',\n          jsonNotArray: 'Tiedosto ei sisältänyt taulukkoa, lopetetaan.'\n        }\n      });\n      return $delegate;\n    }]);\n  }]);\n})();\n\n(function () {\n  angular.module('ui.grid').config(['$provide', function($provide) {\n    $provide.decorator('i18nService', ['$delegate', function($delegate) {\n      $delegate.add('fr', {\n        headerCell: {\n          aria: {\n            defaultFilterLabel: 'Filtre de la colonne',\n            removeFilter: 'Supprimer le filtre',\n            columnMenuButtonLabel: 'Menu de la colonne'\n          },\n          priority: 'Priorité:',\n          filterLabel: \"Filtre de la colonne: \"\n        },\n        aggregate: {\n          label: 'éléments'\n        },\n        groupPanel: {\n          description: 'Faites glisser une en-tête de colonne ici pour créer un groupe de colonnes.'\n        },\n        search: {\n          placeholder: 'Recherche...',\n          showingItems: 'Affichage des éléments :',\n          selectedItems: 'Éléments sélectionnés :',\n          totalItems: 'Nombre total d\\'éléments:',\n          size: 'Taille de page:',\n          first: 'Première page',\n          next: 'Page Suivante',\n          previous: 'Page précédente',\n          last: 'Dernière page'\n        },\n        menu: {\n          text: 'Choisir des colonnes :'\n        },\n        sort: {\n          ascending: 'Trier par ordre croissant',\n          descending: 'Trier par ordre décroissant',\n          none: 'Aucun tri',\n          remove: 'Enlever le tri'\n        },\n        column: {\n          hide: 'Cacher la colonne'\n        },\n        aggregation: {\n          count: 'lignes totales: ',\n          sum: 'total: ',\n          avg: 'moy: ',\n          min: 'min: ',\n          max: 'max: '\n        },\n        pinning: {\n          pinLeft: 'Épingler à gauche',\n          pinRight: 'Épingler à droite',\n          unpin: 'Détacher'\n        },\n        columnMenu: {\n          close: 'Fermer'\n        },\n        gridMenu: {\n          aria: {\n            buttonLabel: 'Menu du tableau'\n          },\n          columns: 'Colonnes:',\n          importerTitle: 'Importer un fichier',\n          exporterAllAsCsv: 'Exporter toutes les données en CSV',\n          exporterVisibleAsCsv: 'Exporter les données visibles en CSV',\n          exporterSelectedAsCsv: 'Exporter les données sélectionnées en CSV',\n          exporterAllAsPdf: 'Exporter toutes les données en PDF',\n          exporterVisibleAsPdf: 'Exporter les données visibles en PDF',\n          exporterSelectedAsPdf: 'Exporter les données sélectionnées en PDF',\n          clearAllFilters: 'Nettoyez tous les filtres'\n        },\n        importer: {\n          noHeaders: 'Impossible de déterminer le nom des colonnes, le fichier possède-t-il une en-tête ?',\n          noObjects: 'Aucun objet trouvé, le fichier possède-t-il des données autres que l\\'en-tête ?',\n          invalidCsv: 'Le fichier n\\'a pas pu être traité, le CSV est-il valide ?',\n          invalidJson: 'Le fichier n\\'a pas pu être traité, le JSON est-il valide ?',\n          jsonNotArray: 'Le fichier JSON importé doit contenir un tableau, abandon.'\n        },\n        pagination: {\n          aria: {\n            pageToFirst: 'Aller à la première page',\n            pageBack: 'Page précédente',\n            pageSelected: 'Page sélectionnée',\n            pageForward: 'Page suivante',\n            pageToLast: 'Aller à la dernière page'\n          },\n          sizes: 'éléments par page',\n          totalItems: 'éléments',\n          through: 'à',\n          of: 'sur'\n        },\n        grouping: {\n          group: 'Grouper',\n          ungroup: 'Dégrouper',\n          aggregate_count: 'Agg: Compter',\n          aggregate_sum: 'Agg: Somme',\n          aggregate_max: 'Agg: Max',\n          aggregate_min: 'Agg: Min',\n          aggregate_avg: 'Agg: Moy',\n          aggregate_remove: 'Agg: Retirer'\n        },\n        validate: {\n          error: 'Erreur:',\n          minLength: 'La valeur doit être supérieure ou égale à THRESHOLD caractères.',\n          maxLength: 'La valeur doit être inférieure ou égale à THRESHOLD caractères.',\n          required: 'Une valeur est nécéssaire.'\n        }\n      });\n      return $delegate;\n    }]);\n  }]);\n})();\n\n(function () {\n  angular.module('ui.grid').config(['$provide', function ($provide) {\n    $provide.decorator('i18nService', ['$delegate', function ($delegate) {\n      $delegate.add('he', {\n        aggregate: {\n          label: 'items'\n        },\n        groupPanel: {\n          description: 'גרור עמודה לכאן ושחרר בכדי לקבץ עמודה זו.'\n        },\n        search: {\n          placeholder: 'חפש...',\n          showingItems: 'מציג:',\n          selectedItems: 'סה\"כ נבחרו:',\n          totalItems: 'סה\"כ רשומות:',\n          size: 'תוצאות בדף:',\n          first: 'דף ראשון',\n          next: 'דף הבא',\n          previous: 'דף קודם',\n          last: 'דף אחרון'\n        },\n        menu: {\n          text: 'בחר עמודות:'\n        },\n        sort: {\n          ascending: 'סדר עולה',\n          descending: 'סדר יורד',\n          remove: 'בטל'\n        },\n        column: {\n          hide: 'טור הסתר'\n        },\n        aggregation: {\n          count: 'total rows: ',\n          sum: 'total: ',\n          avg: 'avg: ',\n          min: 'min: ',\n          max: 'max: '\n        },\n        gridMenu: {\n          columns: 'Columns:',\n          importerTitle: 'Import file',\n          exporterAllAsCsv: 'Export all data as csv',\n          exporterVisibleAsCsv: 'Export visible data as csv',\n          exporterSelectedAsCsv: 'Export selected data as csv',\n          exporterAllAsPdf: 'Export all data as pdf',\n          exporterVisibleAsPdf: 'Export visible data as pdf',\n          exporterSelectedAsPdf: 'Export selected data as pdf',\n          clearAllFilters: 'Clean all filters'\n        },\n        importer: {\n          noHeaders: 'Column names were unable to be derived, does the file have a header?',\n          noObjects: 'Objects were not able to be derived, was there data in the file other than headers?',\n          invalidCsv: 'File was unable to be processed, is it valid CSV?',\n          invalidJson: 'File was unable to be processed, is it valid Json?',\n          jsonNotArray: 'Imported json file must contain an array, aborting.'\n        }\n      });\n      return $delegate;\n    }]);\n  }]);\n})();\n\n(function () {\n  angular.module('ui.grid').config(['$provide', function($provide) {\n    $provide.decorator('i18nService', ['$delegate', function($delegate) {\n      $delegate.add('hy', {\n        aggregate: {\n          label: 'տվյալներ'\n        },\n        groupPanel: {\n          description: 'Ըստ սյան խմբավորելու համար քաշեք և գցեք վերնագիրն այստեղ։'\n        },\n        search: {\n          placeholder: 'Փնտրում...',\n          showingItems: 'Ցուցադրված տվյալներ՝',\n          selectedItems: 'Ընտրված:',\n          totalItems: 'Ընդամենը՝',\n          size: 'Տողերի քանակը էջում՝',\n          first: 'Առաջին էջ',\n          next: 'Հաջորդ էջ',\n          previous: 'Նախորդ էջ',\n          last: 'Վերջին էջ'\n        },\n        menu: {\n          text: 'Ընտրել սյուները:'\n        },\n        sort: {\n          ascending: 'Աճման կարգով',\n          descending: 'Նվազման կարգով',\n          remove: 'Հանել '\n        },\n        column: {\n          hide: 'Թաքցնել սյունը'\n        },\n        aggregation: {\n          count: 'ընդամենը տող՝ ',\n          sum: 'ընդամենը՝ ',\n          avg: 'միջին՝ ',\n          min: 'մին՝ ',\n          max: 'մաքս՝ '\n        },\n        pinning: {\n          pinLeft: 'Կպցնել ձախ կողմում',\n          pinRight: 'Կպցնել աջ կողմում',\n          unpin: 'Արձակել'\n        },\n        gridMenu: {\n          columns: 'Սյուներ:',\n          importerTitle: 'Ներմուծել ֆայլ',\n          exporterAllAsCsv: 'Արտահանել ամբողջը CSV',\n          exporterVisibleAsCsv: 'Արտահանել երևացող տվյալները CSV',\n          exporterSelectedAsCsv: 'Արտահանել ընտրված տվյալները CSV',\n          exporterAllAsPdf: 'Արտահանել PDF',\n          exporterVisibleAsPdf: 'Արտահանել երևացող տվյալները PDF',\n          exporterSelectedAsPdf: 'Արտահանել ընտրված տվյալները PDF',\n          clearAllFilters: 'Մաքրել բոլոր ֆիլտրերը'\n        },\n        importer: {\n          noHeaders: 'Հնարավոր չեղավ որոշել սյան վերնագրերը։ Արդյո՞ք ֆայլը ունի վերնագրեր։',\n          noObjects: 'Հնարավոր չեղավ կարդալ տվյալները։ Արդյո՞ք ֆայլում կան տվյալներ։',\n          invalidCsv: 'Հնարավոր չեղավ մշակել ֆայլը։ Արդյո՞ք այն վավեր CSV է։',\n          invalidJson: 'Հնարավոր չեղավ մշակել ֆայլը։ Արդյո՞ք այն վավեր Json է։',\n          jsonNotArray: 'Ներմուծված json ֆայլը պետք է պարունակի զանգված, կասեցվում է։'\n        }\n      });\n      return $delegate;\n    }]);\n  }]);\n})();\n\n(function () {\n  angular.module('ui.grid').config(['$provide', function($provide) {\n    $provide.decorator('i18nService', ['$delegate', function($delegate) {\n      $delegate.add('it', {\n        aggregate: {\n          label: 'elementi'\n        },\n        groupPanel: {\n          description: 'Trascina un\\'intestazione all\\'interno del gruppo della colonna.'\n        },\n        search: {\n          placeholder: 'Ricerca...',\n          showingItems: 'Mostra:',\n          selectedItems: 'Selezionati:',\n          totalItems: 'Totali:',\n          size: 'Tot Pagine:',\n          first: 'Prima',\n          next: 'Prossima',\n          previous: 'Precedente',\n          last: 'Ultima'\n        },\n        menu: {\n          text: 'Scegli le colonne:'\n        },\n        sort: {\n          ascending: 'Asc.',\n          descending: 'Desc.',\n          remove: 'Annulla ordinamento'\n        },\n        column: {\n          hide: 'Nascondi'\n        },\n        aggregation: {\n          count: 'righe totali: ',\n          sum: 'tot: ',\n          avg: 'media: ',\n          min: 'minimo: ',\n          max: 'massimo: '\n        },\n        pinning: {\n         pinLeft: 'Blocca a sx',\n          pinRight: 'Blocca a dx',\n          unpin: 'Blocca in alto'\n        },\n        gridMenu: {\n          columns: 'Colonne:',\n          importerTitle: 'Importa',\n          exporterAllAsCsv: 'Esporta tutti i dati in CSV',\n          exporterVisibleAsCsv: 'Esporta i dati visibili in CSV',\n          exporterSelectedAsCsv: 'Esporta i dati selezionati in CSV',\n          exporterAllAsPdf: 'Esporta tutti i dati in PDF',\n          exporterVisibleAsPdf: 'Esporta i dati visibili in PDF',\n          exporterSelectedAsPdf: 'Esporta i dati selezionati in PDF',\n          clearAllFilters: 'Pulire tutti i filtri'\n        },\n        importer: {\n          noHeaders: 'Impossibile reperire i nomi delle colonne, sicuro che siano indicati all\\'interno del file?',\n          noObjects: 'Impossibile reperire gli oggetti, sicuro che siano indicati all\\'interno del file?',\n          invalidCsv: 'Impossibile elaborare il file, sicuro che sia un CSV?',\n          invalidJson: 'Impossibile elaborare il file, sicuro che sia un JSON valido?',\n          jsonNotArray: 'Errore! Il file JSON da importare deve contenere un array.'\n        },\n        pagination: {\n          aria: {\n            pageToFirst: 'Prima',\n            pageBack: 'Indietro',\n            pageSelected: 'Pagina selezionata',\n            pageForward: 'Avanti',\n            pageToLast: 'Ultima'\n          },\n          sizes: 'elementi per pagina',\n          totalItems: 'elementi',\n          through: 'a',\n          of: 'di'\n        },\n        grouping: {\n          group: 'Raggruppa',\n          ungroup: 'Separa',\n          aggregate_count: 'Agg: N. Elem.',\n          aggregate_sum: 'Agg: Somma',\n          aggregate_max: 'Agg: Massimo',\n          aggregate_min: 'Agg: Minimo',\n          aggregate_avg: 'Agg: Media',\n          aggregate_remove: 'Agg: Rimuovi'\n        },\n        validate: {\n          error: 'Errore:',\n          minLength: 'Lunghezza minima pari a THRESHOLD caratteri.',\n          maxLength: 'Lunghezza massima pari a THRESHOLD caratteri.',\n          required: 'Necessario inserire un valore.'\n        }\n      });\n      return $delegate;\n    }]);\n  }]);\n})();\n\n(function() {\n  angular.module('ui.grid').config(['$provide', function($provide) {\n    $provide.decorator('i18nService', ['$delegate', function($delegate) {\n      $delegate.add('ja', {\n        aggregate: {\n          label: '項目'\n        },\n        groupPanel: {\n          description: 'ここに列ヘッダをドラッグアンドドロップして、その列でグループ化します。'\n        },\n        search: {\n          placeholder: '検索...',\n          showingItems: '表示中の項目:',\n          selectedItems: '選択した項目:',\n          totalItems: '項目の総数:',\n          size: 'ページサイズ:',\n          first: '最初のページ',\n          next: '次のページ',\n          previous: '前のページ',\n          last: '前のページ'\n        },\n        menu: {\n          text: '列の選択:'\n        },\n        sort: {\n          ascending: '昇順に並べ替え',\n          descending: '降順に並べ替え',\n          remove: '並べ替えの解除'\n        },\n        column: {\n          hide: '列の非表示'\n        },\n        aggregation: {\n          count: '合計行数: ',\n          sum: '合計: ',\n          avg: '平均: ',\n          min: '最小: ',\n          max: '最大: '\n        },\n        pinning: {\n          pinLeft: '左に固定',\n          pinRight: '右に固定',\n          unpin: '固定解除'\n        },\n        gridMenu: {\n          columns: '列:',\n          importerTitle: 'ファイルのインポート',\n          exporterAllAsCsv: 'すべてのデータをCSV形式でエクスポート',\n          exporterVisibleAsCsv: '表示中のデータをCSV形式でエクスポート',\n          exporterSelectedAsCsv: '選択したデータをCSV形式でエクスポート',\n          exporterAllAsPdf: 'すべてのデータをPDF形式でエクスポート',\n          exporterVisibleAsPdf: '表示中のデータをPDF形式でエクスポート',\n          exporterSelectedAsPdf: '選択したデータをPDF形式でエクスポート',\n          clearAllFilters: 'すべてのフィルタを清掃してください'\n        },\n        importer: {\n          noHeaders: '列名を取得できません。ファイルにヘッダが含まれていることを確認してください。',\n          noObjects: 'オブジェクトを取得できません。ファイルにヘッダ以外のデータが含まれていることを確認してください。',\n          invalidCsv: 'ファイルを処理できません。ファイルが有効なCSV形式であることを確認してください。',\n          invalidJson: 'ファイルを処理できません。ファイルが有効なJSON形式であることを確認してください。',\n          jsonNotArray: 'インポートしたJSONファイルには配列が含まれている必要があります。処理を中止します。'\n        },\n        pagination: {\n          aria: {\n            pageToFirst: '最初のページ',\n            pageBack: '前のページ',\n            pageSelected: '現在のページ',\n            pageForward: '次のページ',\n            pageToLast: '最後のページ'\n          },\n          sizes: '項目/ページ',\n          totalItems: '項目',\n          through: 'から',\n          of: '項目/全'\n        }\n      });\n      return $delegate;\n    }]);\n  }]);\n})();\n\n(function () {\n  angular.module('ui.grid').config(['$provide', function($provide) {\n    $provide.decorator('i18nService', ['$delegate', function($delegate) {\n      $delegate.add('ko', {\n        aggregate: {\n          label: '아이템'\n        },\n        groupPanel: {\n          description: '컬럼으로 그룹핑하기 위해서는 컬럼 헤더를 끌어 떨어뜨려 주세요.'\n        },\n        search: {\n          placeholder: '검색...',\n          showingItems: '항목 보여주기:',\n          selectedItems: '선택 항목:',\n          totalItems: '전체 항목:',\n          size: '페이지 크기:',\n          first: '첫번째 페이지',\n          next: '다음 페이지',\n          previous: '이전 페이지',\n          last: '마지막 페이지'\n        },\n        menu: {\n          text: '컬럼을 선택하세요:'\n        },\n        sort: {\n          ascending: '오름차순 정렬',\n          descending: '내림차순 정렬',\n          remove: '소팅 제거'\n        },\n        column: {\n          hide: '컬럼 제거'\n        },\n        aggregation: {\n          count: '전체 갯수: ',\n          sum: '전체: ',\n          avg: '평균: ',\n          min: '최소: ',\n          max: '최대: '\n        },\n        pinning: {\n         pinLeft: '왼쪽 핀',\n          pinRight: '오른쪽 핀',\n          unpin: '핀 제거'\n        },\n        gridMenu: {\n          columns: '컬럼:',\n          importerTitle: '파일 가져오기',\n          exporterAllAsCsv: 'csv로 모든 데이터 내보내기',\n          exporterVisibleAsCsv: 'csv로 보이는 데이터 내보내기',\n          exporterSelectedAsCsv: 'csv로 선택된 데이터 내보내기',\n          exporterAllAsPdf: 'pdf로 모든 데이터 내보내기',\n          exporterVisibleAsPdf: 'pdf로 보이는 데이터 내보내기',\n          exporterSelectedAsPdf: 'pdf로 선택 데이터 내보내기',\n          clearAllFilters: '모든 필터를 청소'\n        },\n        importer: {\n          noHeaders: '컬럼명이 지정되어 있지 않습니다. 파일에 헤더가 명시되어 있는지 확인해 주세요.',\n          noObjects: '데이터가 지정되어 있지 않습니다. 데이터가 파일에 있는지 확인해 주세요.',\n          invalidCsv: '파일을 처리할 수 없습니다. 올바른 csv인지 확인해 주세요.',\n          invalidJson: '파일을 처리할 수 없습니다. 올바른 json인지 확인해 주세요.',\n          jsonNotArray: 'json 파일은 배열을 포함해야 합니다.'\n        },\n        pagination: {\n          sizes: '페이지당 항목',\n          totalItems: '전체 항목'\n        }\n      });\n      return $delegate;\n    }]);\n  }]);\n})();\n\n(function () {\n  angular.module('ui.grid').config(['$provide', function($provide) {\n    $provide.decorator('i18nService', ['$delegate', function($delegate) {\n      $delegate.add('nl', {\n        aggregate: {\n          label: 'items'\n        },\n        groupPanel: {\n          description: 'Sleep hier een kolomnaam heen om op te groeperen.'\n        },\n        search: {\n          placeholder: 'Zoeken...',\n          showingItems: 'Getoonde items:',\n          selectedItems: 'Geselecteerde items:',\n          totalItems: 'Totaal aantal items:',\n          size: 'Items per pagina:',\n          first: 'Eerste pagina',\n          next: 'Volgende pagina',\n          previous: 'Vorige pagina',\n          last: 'Laatste pagina'\n        },\n        menu: {\n          text: 'Kies kolommen:'\n        },\n        sort: {\n          ascending: 'Sorteer oplopend',\n          descending: 'Sorteer aflopend',\n          remove: 'Verwijder sortering'\n        },\n        column: {\n          hide: 'Verberg kolom'\n        },\n        aggregation: {\n          count: 'Aantal rijen: ',\n          sum: 'Som: ',\n          avg: 'Gemiddelde: ',\n          min: 'Min: ',\n          max: 'Max: '\n        },\n        pinning: {\n          pinLeft: 'Zet links vast',\n          pinRight: 'Zet rechts vast',\n          unpin: 'Maak los'\n        },\n        gridMenu: {\n          columns: 'Kolommen:',\n          importerTitle: 'Importeer bestand',\n          exporterAllAsCsv: 'Exporteer alle data als csv',\n          exporterVisibleAsCsv: 'Exporteer zichtbare data als csv',\n          exporterSelectedAsCsv: 'Exporteer geselecteerde data als csv',\n          exporterAllAsPdf: 'Exporteer alle data als pdf',\n          exporterVisibleAsPdf: 'Exporteer zichtbare data als pdf',\n          exporterSelectedAsPdf: 'Exporteer geselecteerde data als pdf',\n          clearAllFilters: 'Reinig alle filters'\n        },\n        importer: {\n          noHeaders: 'Kolomnamen kunnen niet worden afgeleid. Heeft het bestand een header?',\n          noObjects: 'Objecten kunnen niet worden afgeleid. Bevat het bestand data naast de headers?',\n          invalidCsv: 'Het bestand kan niet verwerkt worden. Is het een valide csv bestand?',\n          invalidJson: 'Het bestand kan niet verwerkt worden. Is het valide json?',\n          jsonNotArray: 'Het json bestand moet een array bevatten. De actie wordt geannuleerd.'\n        },\n        pagination: {\n            sizes: 'items per pagina',\n            totalItems: 'items',\n            of: 'van de'\n        },\n        grouping: {\n            group: 'Groepeer',\n            ungroup: 'Groepering opheffen',\n            aggregate_count: 'Agg: Aantal',\n            aggregate_sum: 'Agg: Som',\n            aggregate_max: 'Agg: Max',\n            aggregate_min: 'Agg: Min',\n            aggregate_avg: 'Agg: Gem',\n            aggregate_remove: 'Agg: Verwijder'\n        }\n      });\n      return $delegate;\n    }]);\n  }]);\n})();\n\n(function () {\n  angular.module('ui.grid').config(['$provide', function($provide) {\n    $provide.decorator('i18nService', ['$delegate', function($delegate) {\n      $delegate.add('no', {\n        headerCell: {\n          aria: {\n            defaultFilterLabel: 'Filter for column',\n            removeFilter: 'Remove Filter',\n            columnMenuButtonLabel: 'Column Menu'\n          },\n          priority: 'Priority:',\n          filterLabel: \"Filter for column: \"\n        },\n        aggregate: {\n          label: 'items'\n        },\n        groupPanel: {\n          description: 'Drag a column header here and drop it to group by that column.'\n        },\n        search: {\n          placeholder: 'Search...',\n          showingItems: 'Showing Items:',\n          selectedItems: 'Selected Items:',\n          totalItems: 'Total Items:',\n          size: 'Page Size:',\n          first: 'First Page',\n          next: 'Next Page',\n          previous: 'Previous Page',\n          last: 'Last Page'\n        },\n        menu: {\n          text: 'Choose Columns:'\n        },\n        sort: {\n          ascending: 'Sort Ascending',\n          descending: 'Sort Descending',\n          none: 'Sort None',\n          remove: 'Remove Sort'\n        },\n        column: {\n          hide: 'Hide Column'\n        },\n        aggregation: {\n          count: 'total rows: ',\n          sum: 'total: ',\n          avg: 'avg: ',\n          min: 'min: ',\n          max: 'max: '\n        },\n        pinning: {\n          pinLeft: 'Pin Left',\n          pinRight: 'Pin Right',\n          unpin: 'Unpin'\n        },\n        columnMenu: {\n          close: 'Close'\n        },\n        gridMenu: {\n          aria: {\n            buttonLabel: 'Grid Menu'\n          },\n          columns: 'Kolonner:',\n          importerTitle: 'Importer fil',\n          exporterAllAsCsv: 'Eksporter alle data som csv',\n          exporterVisibleAsCsv: 'Eksporter synlige data som csv',\n          exporterSelectedAsCsv: 'Eksporter utvalgte data som csv',\n          exporterAllAsPdf: 'Eksporter alle data som pdf',\n          exporterVisibleAsPdf: 'Eksporter synlige data som pdf',\n          exporterSelectedAsPdf: 'Eksporter utvalgte data som pdf',\n          clearAllFilters: 'Clear all filters'\n        },\n        importer: {\n          noHeaders: 'Column names were unable to be derived, does the file have a header?',\n          noObjects: 'Objects were not able to be derived, was there data in the file other than headers?',\n          invalidCsv: 'File was unable to be processed, is it valid CSV?',\n          invalidJson: 'File was unable to be processed, is it valid Json?',\n          jsonNotArray: 'Imported json file must contain an array, aborting.'\n        },\n        pagination: {\n          aria: {\n            pageToFirst: 'Page to first',\n            pageBack: 'Page back',\n            pageSelected: 'Selected page',\n            pageForward: 'Page forward',\n            pageToLast: 'Page to last'\n          },\n          sizes: 'items per page',\n          totalItems: 'items',\n          through: 'through',\n          of: 'of'\n        },\n        grouping: {\n          group: 'Group',\n          ungroup: 'Ungroup',\n          aggregate_count: 'Agg: Count',\n          aggregate_sum: 'Agg: Sum',\n          aggregate_max: 'Agg: Max',\n          aggregate_min: 'Agg: Min',\n          aggregate_avg: 'Agg: Avg',\n          aggregate_remove: 'Agg: Remove'\n        }\n      });\n      return $delegate;\n    }]);\n  }]);\n})();\n\n(function () {\n  angular.module('ui.grid').config(['$provide', function($provide) {\n    $provide.decorator('i18nService', ['$delegate', function($delegate) {\n      $delegate.add('pl', {\n        headerCell: {\n          aria: {\n            defaultFilterLabel: 'Filter dla kolumny',\n            removeFilter: 'Usuń filter',\n            columnMenuButtonLabel: 'Menu kolumny'\n          },\n          priority: 'Prioritet:',\n          filterLabel: \"Filtr dla kolumny: \"\n        },\n        aggregate: {\n          label: 'pozycji'\n        },\n        groupPanel: {\n          description: 'Przeciągnij nagłówek kolumny tutaj, aby pogrupować według niej.'\n        },\n        search: {\n          placeholder: 'Szukaj...',\n          showingItems: 'Widoczne pozycje:',\n          selectedItems: 'Zaznaczone pozycje:',\n          totalItems: 'Wszystkich pozycji:',\n          size: 'Rozmiar strony:',\n          first: 'Pierwsza strona',\n          next: 'Następna strona',\n          previous: 'Poprzednia strona',\n          last: 'Ostatnia strona'\n        },\n        menu: {\n          text: 'Wybierz kolumny:'\n        },\n        sort: {\n          ascending: 'Sortuj rosnąco',\n          descending: 'Sortuj malejąco',\n          none: 'Brak sortowania',\n          remove: 'Wyłącz sortowanie'\n        },\n        column: {\n          hide: 'Ukryj kolumne'\n        },\n        aggregation: {\n          count: 'Razem pozycji: ',\n            sum: 'Razem: ',\n            avg: 'Średnia: ',\n            min: 'Min: ',\n            max: 'Max: '\n        },\n        pinning: {\n          pinLeft: 'Przypnij do lewej',\n          pinRight: 'Przypnij do prawej',\n          unpin: 'Odepnij'\n        },\n        columnMenu: {\n          close: 'Zamknij'\n        },\n        gridMenu: {\n          aria: {\n            buttonLabel: 'Menu Grida'\n          },\n          columns: 'Kolumny:',\n          importerTitle: 'Importuj plik',\n          exporterAllAsCsv: 'Eksportuj wszystkie dane do csv',\n          exporterVisibleAsCsv: 'Eksportuj widoczne dane do csv',\n          exporterSelectedAsCsv: 'Eksportuj zaznaczone dane do csv',\n          exporterAllAsPdf: 'Eksportuj wszystkie dane do pdf',\n          exporterVisibleAsPdf: 'Eksportuj widoczne dane do pdf',\n          exporterSelectedAsPdf: 'Eksportuj zaznaczone dane do pdf',\n          clearAllFilters: 'Wyczyść filtry'\n        },\n        importer: {\n          noHeaders: 'Nie udało się wczytać nazw kolumn. Czy plik posiada nagłówek?',\n          noObjects: 'Nie udalo się wczytać pozycji. Czy plik zawiera dane??',\n          invalidCsv: 'Nie udało się przetworzyć pliku, jest to prawidlowy plik CSV??',\n          invalidJson: 'Nie udało się przetworzyć pliku, jest to prawidlowy plik Json?',\n          jsonNotArray: 'Importowany plik json musi zawierać tablicę, importowanie przerwane.'\n        },\n        pagination: {\n          aria: {\n            pageToFirst: 'Pierwsza strona',\n            pageBack: 'Poprzednia strona',\n            pageSelected: 'Wybrana strona',\n            pageForward: 'Następna strona',\n            pageToLast: 'Ostatnia strona'\n          },\n          sizes: 'pozycji na stronę',\n          totalItems: 'pozycji',\n          through: 'do',\n          of: 'z'\n        },\n        grouping: {\n          group: 'Grupuj',\n          ungroup: 'Rozgrupuj',\n          aggregate_count: 'Zbiorczo: Razem',\n          aggregate_sum: 'Zbiorczo: Suma',\n          aggregate_max: 'Zbiorczo: Max',\n          aggregate_min: 'Zbiorczo: Min',\n          aggregate_avg: 'Zbiorczo: Średnia',\n          aggregate_remove: 'Zbiorczo: Usuń'\n        }\n      });\n      return $delegate;\n    }]);\n  }]);\n})();\n\n(function () {\n  angular.module('ui.grid').config(['$provide', function($provide) {\n    $provide.decorator('i18nService', ['$delegate', function($delegate) {\n      $delegate.add('pt-br', {\n        headerCell: {\n          aria: {\n            defaultFilterLabel: 'Filtro por coluna',\n            removeFilter: 'Remover filtro',\n            columnMenuButtonLabel: 'Menu coluna'\n          },\n          priority: 'Prioridade:',\n          filterLabel: \"Filtro por coluna: \"\n        },\n        aggregate: {\n          label: 'itens'\n        },\n        groupPanel: {\n          description: 'Arraste e solte uma coluna aqui para agrupar por essa coluna'\n        },\n        search: {\n          placeholder: 'Procurar...',\n          showingItems: 'Mostrando os Itens:',\n          selectedItems: 'Items Selecionados:',\n          totalItems: 'Total de Itens:',\n          size: 'Tamanho da Página:',\n          first: 'Primeira Página',\n          next: 'Próxima Página',\n          previous: 'Página Anterior',\n          last: 'Última Página'\n        },\n        menu: {\n          text: 'Selecione as colunas:'\n        },\n        sort: {\n          ascending: 'Ordenar Ascendente',\n          descending: 'Ordenar Descendente',\n          none: 'Nenhuma Ordem',\n          remove: 'Remover Ordenação'\n        },\n        column: {\n          hide: 'Esconder coluna'\n        },\n        aggregation: {\n          count: 'total de linhas: ',\n          sum: 'total: ',\n          avg: 'med: ',\n          min: 'min: ',\n          max: 'max: '\n        },\n        pinning: {\n          pinLeft: 'Fixar Esquerda',\n          pinRight: 'Fixar Direita',\n          unpin: 'Desprender'\n        },\n        columnMenu: {\n          close: 'Fechar'\n        },\n        gridMenu: {\n          aria: {\n            buttonLabel: 'Menu Grid'\n          },\n          columns: 'Colunas:',\n          importerTitle: 'Importar arquivo',\n          exporterAllAsCsv: 'Exportar todos os dados como csv',\n          exporterVisibleAsCsv: 'Exportar dados visíveis como csv',\n          exporterSelectedAsCsv: 'Exportar dados selecionados como csv',\n          exporterAllAsPdf: 'Exportar todos os dados como pdf',\n          exporterVisibleAsPdf: 'Exportar dados visíveis como pdf',\n          exporterSelectedAsPdf: 'Exportar dados selecionados como pdf',\n          clearAllFilters: 'Limpar todos os filtros'\n        },\n        importer: {\n          noHeaders: 'Nomes de colunas não puderam ser derivados. O arquivo tem um cabeçalho?',\n          noObjects: 'Objetos não puderam ser derivados. Havia dados no arquivo, além dos cabeçalhos?',\n          invalidCsv: 'Arquivo não pode ser processado. É um CSV válido?',\n          invalidJson: 'Arquivo não pode ser processado. É um Json válido?',\n          jsonNotArray: 'Arquivo json importado tem que conter um array. Abortando.'\n        },\n        pagination: {\n          aria: {\n            pageToFirst: 'Primeira página',\n            pageBack: 'Página anterior',\n            pageSelected: 'Página Selecionada',\n            pageForward: 'Proxima',\n            pageToLast: 'Anterior'\n          },\n          sizes: 'itens por página',\n          totalItems: 'itens',\n          through: 'através dos',\n          of: 'de'\n        },\n        grouping: {\n          group: 'Agrupar',\n          ungroup: 'Desagrupar',\n          aggregate_count: 'Agr: Contar',\n          aggregate_sum: 'Agr: Soma',\n          aggregate_max: 'Agr: Max',\n          aggregate_min: 'Agr: Min',\n          aggregate_avg: 'Agr: Med',\n          aggregate_remove: 'Agr: Remover'\n        }\n      });\n      return $delegate;\n    }]);\n}]);\n})();\n\n(function () {\n  angular.module('ui.grid').config(['$provide', function($provide) {\n    $provide.decorator('i18nService', ['$delegate', function($delegate) {\n      $delegate.add('pt', {\n        headerCell: {\n          aria: {\n            defaultFilterLabel: 'Filtro por coluna',\n            removeFilter: 'Remover filtro',\n            columnMenuButtonLabel: 'Menu coluna'\n          },\n          priority: 'Prioridade:',\n          filterLabel: \"Filtro por coluna: \"\n        },\n        aggregate: {\n          label: 'itens'\n        },\n        groupPanel: {\n          description: 'Arraste e solte uma coluna aqui para agrupar por essa coluna'\n        },\n        search: {\n          placeholder: 'Procurar...',\n          showingItems: 'Mostrando os Itens:',\n          selectedItems: 'Itens Selecionados:',\n          totalItems: 'Total de Itens:',\n          size: 'Tamanho da Página:',\n          first: 'Primeira Página',\n          next: 'Próxima Página',\n          previous: 'Página Anterior',\n          last: 'Última Página'\n        },\n        menu: {\n          text: 'Selecione as colunas:'\n        },\n        sort: {\n          ascending: 'Ordenar Ascendente',\n          descending: 'Ordenar Descendente',\n          none: 'Nenhuma Ordem',\n          remove: 'Remover Ordenação'\n        },\n        column: {\n          hide: 'Esconder coluna'\n        },\n        aggregation: {\n          count: 'total de linhas: ',\n          sum: 'total: ',\n          avg: 'med: ',\n          min: 'min: ',\n          max: 'max: '\n        },\n        pinning: {\n          pinLeft: 'Fixar Esquerda',\n          pinRight: 'Fixar Direita',\n          unpin: 'Desprender'\n        },\n        columnMenu: {\n          close: 'Fechar'\n        },\n        gridMenu: {\n          aria: {\n            buttonLabel: 'Menu Grid'\n          },\n          columns: 'Colunas:',\n          importerTitle: 'Importar ficheiro',\n          exporterAllAsCsv: 'Exportar todos os dados como csv',\n          exporterVisibleAsCsv: 'Exportar dados visíveis como csv',\n          exporterSelectedAsCsv: 'Exportar dados selecionados como csv',\n          exporterAllAsPdf: 'Exportar todos os dados como pdf',\n          exporterVisibleAsPdf: 'Exportar dados visíveis como pdf',\n          exporterSelectedAsPdf: 'Exportar dados selecionados como pdf',\n          clearAllFilters: 'Limpar todos os filtros'\n        },\n        importer: {\n          noHeaders: 'Nomes de colunas não puderam ser derivados. O ficheiro tem um cabeçalho?',\n          noObjects: 'Objetos não puderam ser derivados. Havia dados no ficheiro, além dos cabeçalhos?',\n          invalidCsv: 'Ficheiro não pode ser processado. É um CSV válido?',\n          invalidJson: 'Ficheiro não pode ser processado. É um Json válido?',\n          jsonNotArray: 'Ficheiro json importado tem que conter um array. Interrompendo.'\n        },\n        pagination: {\n          aria: {\n            pageToFirst: 'Primeira página',\n            pageBack: 'Página anterior',\n            pageSelected: 'Página Selecionada',\n            pageForward: 'Próxima',\n            pageToLast: 'Anterior'\n          },\n          sizes: 'itens por página',\n          totalItems: 'itens',\n          through: 'através dos',\n          of: 'de'\n        },\n        grouping: {\n          group: 'Agrupar',\n          ungroup: 'Desagrupar',\n          aggregate_count: 'Agr: Contar',\n          aggregate_sum: 'Agr: Soma',\n          aggregate_max: 'Agr: Max',\n          aggregate_min: 'Agr: Min',\n          aggregate_avg: 'Agr: Med',\n          aggregate_remove: 'Agr: Remover'\n        }\n      });\n      return $delegate;\n    }]);\n}]);\n})();\n\n(function () {\n  angular.module('ui.grid').config(['$provide', function($provide) {\n    $provide.decorator('i18nService', ['$delegate', function($delegate) {\n      $delegate.add('ro', {\n        headerCell: {\n          aria: {\n            defaultFilterLabel: 'Filtru pentru coloana',\n            removeFilter: 'Sterge filtru',\n            columnMenuButtonLabel: 'Column Menu'\n          },\n          priority: 'Prioritate:',\n          filterLabel: \"Filtru pentru coloana:\"\n        },\n        aggregate: {\n          label: 'Elemente'\n        },\n        groupPanel: {\n          description: 'Trage un cap de coloana aici pentru a grupa elementele dupa coloana respectiva'\n        },\n        search: {\n          placeholder: 'Cauta...',\n          showingItems: 'Arata elementele:',\n          selectedItems: 'Elementele selectate:',\n          totalItems: 'Total elemente:',\n          size: 'Marime pagina:',\n          first: 'Prima pagina',\n          next: 'Pagina urmatoare',\n          previous: 'Pagina anterioara',\n          last: 'Ultima pagina'\n        },\n        menu: {\n          text: 'Alege coloane:'\n        },\n        sort: {\n          ascending: 'Ordoneaza crescator',\n          descending: 'Ordoneaza descrescator',\n          none: 'Fara ordonare',\n          remove: 'Sterge ordonarea'\n        },\n        column: {\n          hide: 'Ascunde coloana'\n        },\n        aggregation: {\n          count: 'total linii: ',\n          sum: 'total: ',\n          avg: 'medie: ',\n          min: 'min: ',\n          max: 'max: '\n        },\n        pinning: {\n          pinLeft: 'Pin la stanga',\n          pinRight: 'Pin la dreapta',\n          unpin: 'Sterge pinul'\n        },\n        columnMenu: {\n          close: 'Inchide'\n        },\n        gridMenu: {\n          aria: {\n            buttonLabel: 'Grid Menu'\n          },\n          columns: 'Coloane:',\n          importerTitle: 'Incarca fisier',\n          exporterAllAsCsv: 'Exporta toate datele ca csv',\n          exporterVisibleAsCsv: 'Exporta datele vizibile ca csv',\n          exporterSelectedAsCsv: 'Exporta datele selectate ca csv',\n          exporterAllAsPdf: 'Exporta toate datele ca pdf',\n          exporterVisibleAsPdf: 'Exporta datele vizibile ca pdf',\n          exporterSelectedAsPdf: 'Exporta datele selectate ca csv pdf',\n          clearAllFilters: 'Sterge toate filtrele'\n        },\n        importer: {\n          noHeaders: 'Numele coloanelor nu a putut fi incarcat, acest fisier are un header?',\n          noObjects: 'Datele nu au putut fi incarcate, exista date in fisier in afara numelor de coloane?',\n          invalidCsv: 'Fisierul nu a putut fi procesat, ati incarcat un CSV valid ?',\n          invalidJson: 'Fisierul nu a putut fi procesat, ati incarcat un Json valid?',\n          jsonNotArray: 'Json-ul incarcat trebuie sa contina un array, inchidere.'\n        },\n        pagination: {\n          aria: {\n            pageToFirst: 'Prima pagina',\n            pageBack: 'O pagina inapoi',\n            pageSelected: 'Pagina selectata',\n            pageForward: 'O pagina inainte',\n            pageToLast: 'Ultima pagina'\n          },\n          sizes: 'Elemente per pagina',\n          totalItems: 'elemente',\n          through: 'prin',\n          of: 'of'\n        },\n        grouping: {\n          group: 'Grupeaza',\n          ungroup: 'Opreste gruparea',\n          aggregate_count: 'Agg: Count',\n          aggregate_sum: 'Agg: Sum',\n          aggregate_max: 'Agg: Max',\n          aggregate_min: 'Agg: Min',\n          aggregate_avg: 'Agg: Avg',\n          aggregate_remove: 'Agg: Remove'\n        }\n      });\n      return $delegate;\n    }]);\n  }]);\n})();\n\n(function () {\n  angular.module('ui.grid').config(['$provide', function($provide) {\n    $provide.decorator('i18nService', ['$delegate', function($delegate) {\n      $delegate.add('ru', {\n        headerCell: {\n          aria: {\n            defaultFilterLabel: 'Фильтр столбца',\n            removeFilter: 'Удалить фильтр',\n            columnMenuButtonLabel: 'Меню столбца'\n          },\n          priority: 'Приоритет:',\n          filterLabel: \"Фильтр столбца: \"\n        },\n        aggregate: {\n          label: 'элементы'\n        },\n        groupPanel: {\n          description: 'Для группировки по столбцу перетащите сюда его название.'\n        },\n        search: {\n          placeholder: 'Поиск...',\n          showingItems: 'Показать элементы:',\n          selectedItems: 'Выбранные элементы:',\n          totalItems: 'Всего элементов:',\n          size: 'Размер страницы:',\n          first: 'Первая страница',\n          next: 'Следующая страница',\n          previous: 'Предыдущая страница',\n          last: 'Последняя страница'\n        },\n        menu: {\n          text: 'Выбрать столбцы:'\n        },\n        sort: {\n          ascending: 'По возрастанию',\n          descending: 'По убыванию',\n          none: 'Без сортировки',\n          remove: 'Убрать сортировку'\n        },\n        column: {\n          hide: 'Спрятать столбец'\n        },\n        aggregation: {\n          count: 'всего строк: ',\n          sum: 'итого: ',\n          avg: 'среднее: ',\n          min: 'мин: ',\n          max: 'макс: '\n        },\n\t\t\t\tpinning: {\n\t\t\t\t\tpinLeft: 'Закрепить слева',\n\t\t\t\t\tpinRight: 'Закрепить справа',\n\t\t\t\t\tunpin: 'Открепить'\n\t\t\t\t},\n        columnMenu: {\n          close: 'Закрыть'\n        },\n        gridMenu: {\n          aria: {\n            buttonLabel: 'Меню'\n          },\n          columns: 'Столбцы:',\n          importerTitle: 'Импортировать файл',\n          exporterAllAsCsv: 'Экспортировать всё в CSV',\n          exporterVisibleAsCsv: 'Экспортировать видимые данные в CSV',\n          exporterSelectedAsCsv: 'Экспортировать выбранные данные в CSV',\n          exporterAllAsPdf: 'Экспортировать всё в PDF',\n          exporterVisibleAsPdf: 'Экспортировать видимые данные в PDF',\n          exporterSelectedAsPdf: 'Экспортировать выбранные данные в PDF',\n          clearAllFilters: 'Очистите все фильтры'\n        },\n        importer: {\n          noHeaders: 'Не удалось получить названия столбцов, есть ли в файле заголовок?',\n          noObjects: 'Не удалось получить данные, есть ли в файле строки кроме заголовка?',\n          invalidCsv: 'Не удалось обработать файл, это правильный CSV-файл?',\n          invalidJson: 'Не удалось обработать файл, это правильный JSON?',\n          jsonNotArray: 'Импортируемый JSON-файл должен содержать массив, операция отменена.'\n        },\n        pagination: {\n          aria: {\n            pageToFirst: 'Первая страница',\n            pageBack: 'Предыдущая страница',\n            pageSelected: 'Выбранная страница',\n            pageForward: 'Следующая страница',\n            pageToLast: 'Последняя страница'\n          },\n          sizes: 'строк на страницу',\n          totalItems: 'строк',\n          through: 'по',\n          of: 'из'\n        },\n        grouping: {\n          group: 'Группировать',\n          ungroup: 'Разгруппировать',\n          aggregate_count: 'Группировать: Count',\n          aggregate_sum: 'Для группы: Сумма',\n          aggregate_max: 'Для группы: Максимум',\n          aggregate_min: 'Для группы: Минимум',\n          aggregate_avg: 'Для группы: Среднее',\n          aggregate_remove: 'Для группы: Пусто'\n        }\n      });\n      return $delegate;\n    }]);\n  }]);\n})();\n\n(function () {\n  angular.module('ui.grid').config(['$provide', function($provide) {\n    $provide.decorator('i18nService', ['$delegate', function($delegate) {\n      $delegate.add('sk', {\n        aggregate: {\n          label: 'items'\n        },\n        groupPanel: {\n          description: 'Pretiahni sem názov stĺpca pre zoskupenie podľa toho stĺpca.'\n        },\n        search: {\n          placeholder: 'Hľadaj...',\n          showingItems: 'Zobrazujem položky:',\n          selectedItems: 'Vybraté položky:',\n          totalItems: 'Počet položiek:',\n          size: 'Počet:',\n          first: 'Prvá strana',\n          next: 'Ďalšia strana',\n          previous: 'Predchádzajúca strana',\n          last: 'Posledná strana'\n        },\n        menu: {\n          text: 'Vyberte stĺpce:'\n        },\n        sort: {\n          ascending: 'Zotriediť vzostupne',\n          descending: 'Zotriediť zostupne',\n          remove: 'Vymazať triedenie'\n        },\n        aggregation: {\n          count: 'total rows: ',\n          sum: 'total: ',\n          avg: 'avg: ',\n          min: 'min: ',\n          max: 'max: '\n        },\n        gridMenu: {\n          columns: 'Columns:',\n          importerTitle: 'Import file',\n          exporterAllAsCsv: 'Export all data as csv',\n          exporterVisibleAsCsv: 'Export visible data as csv',\n          exporterSelectedAsCsv: 'Export selected data as csv',\n          exporterAllAsPdf: 'Export all data as pdf',\n          exporterVisibleAsPdf: 'Export visible data as pdf',\n          exporterSelectedAsPdf: 'Export selected data as pdf',\n          clearAllFilters: 'Clear all filters'\n        },\n        importer: {\n          noHeaders: 'Column names were unable to be derived, does the file have a header?',\n          noObjects: 'Objects were not able to be derived, was there data in the file other than headers?',\n          invalidCsv: 'File was unable to be processed, is it valid CSV?',\n          invalidJson: 'File was unable to be processed, is it valid Json?',\n          jsonNotArray: 'Imported json file must contain an array, aborting.'\n        }\n      });\n      return $delegate;\n    }]);\n  }]);\n})();\n\n(function () {\n  angular.module('ui.grid').config(['$provide', function($provide) {\n    $provide.decorator('i18nService', ['$delegate', function($delegate) {\n      $delegate.add('sv', {\n        aggregate: {\n          label: 'Artiklar'\n        },\n        groupPanel: {\n          description: 'Dra en kolumnrubrik hit och släpp den för att gruppera efter den kolumnen.'\n        },\n        search: {\n          placeholder: 'Sök...',\n          showingItems: 'Visar artiklar:',\n          selectedItems: 'Valda artiklar:',\n          totalItems: 'Antal artiklar:',\n          size: 'Sidstorlek:',\n          first: 'Första sidan',\n          next: 'Nästa sida',\n          previous: 'Föregående sida',\n          last: 'Sista sidan'\n        },\n        menu: {\n          text: 'Välj kolumner:'\n        },\n        sort: {\n          ascending: 'Sortera stigande',\n          descending: 'Sortera fallande',\n          remove: 'Inaktivera sortering'\n        },\n        column: {\n          hide: 'Göm kolumn'\n        },\n        aggregation: {\n          count: 'Antal rader: ',\n          sum: 'Summa: ',\n          avg: 'Genomsnitt: ',\n          min: 'Min: ',\n          max: 'Max: '\n        },\n        pinning: {\n          pinLeft: 'Fäst vänster',\n          pinRight: 'Fäst höger',\n          unpin: 'Lösgör'\n        },\n        gridMenu: {\n          columns: 'Kolumner:',\n          importerTitle: 'Importera fil',\n          exporterAllAsCsv: 'Exportera all data som CSV',\n          exporterVisibleAsCsv: 'Exportera synlig data som CSV',\n          exporterSelectedAsCsv: 'Exportera markerad data som CSV',\n          exporterAllAsPdf: 'Exportera all data som PDF',\n          exporterVisibleAsPdf: 'Exportera synlig data som PDF',\n          exporterSelectedAsPdf: 'Exportera markerad data som PDF',\n          clearAllFilters: 'Rengör alla filter'\n        },\n        importer: {\n          noHeaders: 'Kolumnnamn kunde inte härledas. Har filen ett sidhuvud?',\n          noObjects: 'Objekt kunde inte härledas. Har filen data undantaget sidhuvud?',\n          invalidCsv: 'Filen kunde inte behandlas, är den en giltig CSV?',\n          invalidJson: 'Filen kunde inte behandlas, är den en giltig JSON?',\n          jsonNotArray: 'Importerad JSON-fil måste innehålla ett fält. Import avbruten.'\n        },\n        pagination: {\n          sizes: 'Artiklar per sida',\n          totalItems: 'Artiklar'\n        }\n      });\n      return $delegate;\n    }]);\n  }]);\n})();\n\n(function () {\n  angular.module('ui.grid').config(['$provide', function($provide) {\n    $provide.decorator('i18nService', ['$delegate', function($delegate) {\n      $delegate.add('ta', {\n        aggregate: {\n          label: 'உருப்படிகள்'\n        },\n        groupPanel: {\n          description: 'ஒரு பத்தியை குழுவாக அமைக்க அப்பத்தியின் தலைப்பை இங்கே  இழுத்து வரவும் '\n        },\n        search: {\n          placeholder: 'தேடல் ...',\n          showingItems: 'உருப்படிகளை காண்பித்தல்:',\n          selectedItems: 'தேர்ந்தெடுக்கப்பட்ட  உருப்படிகள்:',\n          totalItems: 'மொத்த உருப்படிகள்:',\n          size: 'பக்க அளவு: ',\n          first: 'முதல் பக்கம்',\n          next: 'அடுத்த பக்கம்',\n          previous: 'முந்தைய பக்கம் ',\n          last: 'இறுதி பக்கம்'\n        },\n        menu: {\n          text: 'பத்திகளை தேர்ந்தெடு:'\n        },\n        sort: {\n          ascending: 'மேலிருந்து கீழாக',\n          descending: 'கீழிருந்து மேலாக',\n          remove: 'வரிசையை நீக்கு'\n        },\n        column: {\n          hide: 'பத்தியை மறைத்து வை '\n        },\n        aggregation: {\n          count: 'மொத்த வரிகள்:',\n          sum: 'மொத்தம்: ',\n          avg: 'சராசரி: ',\n          min: 'குறைந்தபட்ச: ',\n          max: 'அதிகபட்ச: '\n        },\n        pinning: {\n         pinLeft: 'இடதுபுறமாக தைக்க ',\n          pinRight: 'வலதுபுறமாக தைக்க',\n          unpin: 'பிரி'\n        },\n        gridMenu: {\n          columns: 'பத்திகள்:',\n          importerTitle: 'கோப்பு : படித்தல்',\n          exporterAllAsCsv: 'எல்லா தரவுகளையும் கோப்பாக்கு: csv',\n          exporterVisibleAsCsv: 'இருக்கும் தரவுகளை கோப்பாக்கு: csv',\n          exporterSelectedAsCsv: 'தேர்ந்தெடுத்த தரவுகளை கோப்பாக்கு: csv',\n          exporterAllAsPdf: 'எல்லா தரவுகளையும் கோப்பாக்கு: pdf',\n          exporterVisibleAsPdf: 'இருக்கும் தரவுகளை கோப்பாக்கு: pdf',\n          exporterSelectedAsPdf: 'தேர்ந்தெடுத்த தரவுகளை கோப்பாக்கு: pdf',\n          clearAllFilters: 'Clear all filters'\n        },\n        importer: {\n          noHeaders: 'பத்தியின் தலைப்புகளை பெற இயலவில்லை, கோப்பிற்கு தலைப்பு உள்ளதா?',\n          noObjects: 'இலக்குகளை உருவாக்க முடியவில்லை, கோப்பில் தலைப்புகளை தவிர தரவு ஏதேனும் உள்ளதா? ',\n          invalidCsv:\t'சரிவர நடைமுறை படுத்த இயலவில்லை, கோப்பு சரிதானா? - csv',\n          invalidJson: 'சரிவர நடைமுறை படுத்த இயலவில்லை, கோப்பு சரிதானா? - json',\n          jsonNotArray: 'படித்த கோப்பில் வரிசைகள் உள்ளது, நடைமுறை ரத்து செய் : json'\n        },\n        pagination: {\n          sizes\t\t: 'உருப்படிகள் / பக்கம்',\n          totalItems\t: 'உருப்படிகள் '\n        },\n        grouping: {\n          group\t: 'குழு',\n          ungroup : 'பிரி',\n          aggregate_count\t: 'மதிப்பீட்டு : எண்ணு',\n          aggregate_sum : 'மதிப்பீட்டு : கூட்டல்',\n          aggregate_max\t: 'மதிப்பீட்டு : அதிகபட்சம்',\n          aggregate_min\t: 'மதிப்பீட்டு : குறைந்தபட்சம்',\n          aggregate_avg\t: 'மதிப்பீட்டு : சராசரி',\n          aggregate_remove : 'மதிப்பீட்டு : நீக்கு'\n        }\n      });\n      return $delegate;\n    }]);\n  }]);\n})();\n\n(function () {\n  angular.module('ui.grid').config(['$provide', function($provide) {\n    $provide.decorator('i18nService', ['$delegate', function($delegate) {\n      $delegate.add('tr', {\n        headerCell: {\n          aria: {\n            defaultFilterLabel: 'Sütun için filtre',\n            removeFilter: 'Filtreyi Kaldır',\n            columnMenuButtonLabel: 'Sütun Menüsü'\n          },\n          priority: 'Öncelik:',\n          filterLabel: \"Sütun için filtre: \"\n        },\n        aggregate: {\n          label: 'kayıtlar'\n        },\n        groupPanel: {\n          description: 'Sütuna göre gruplamak için sütun başlığını buraya sürükleyin ve bırakın.'\n        },\n        search: {\n          placeholder: 'Arama...',\n          showingItems: 'Gösterilen Kayıt:',\n          selectedItems: 'Seçili Kayıt:',\n          totalItems: 'Toplam Kayıt:',\n          size: 'Sayfa Boyutu:',\n          first: 'İlk Sayfa',\n          next: 'Sonraki Sayfa',\n          previous: 'Önceki Sayfa',\n          last: 'Son Sayfa'\n        },\n        menu: {\n          text: 'Sütunları Seç:'\n        },\n        sort: {\n          ascending: 'Artan Sırada Sırala',\n          descending: 'Azalan Sırada Sırala',\n          none: 'Sıralama Yapma',\n          remove: 'Sıralamayı Kaldır'\n        },\n        column: {\n          hide: 'Sütunu Gizle'\n        },\n        aggregation: {\n          count: 'toplam satır: ',\n          sum: 'toplam: ',\n          avg: 'ort: ',\n          min: 'min: ',\n          max: 'maks: '\n        },\n        pinning: {\n          pinLeft: 'Sola Sabitle',\n          pinRight: 'Sağa Sabitle',\n          unpin: 'Sabitlemeyi Kaldır'\n        },\n        columnMenu: {\n          close: 'Kapat'\n        },\n        gridMenu: {\n          aria: {\n            buttonLabel: 'Tablo Menü'\n          },\n          columns: 'Sütunlar:',\n          importerTitle: 'Dosya içeri aktar',\n          exporterAllAsCsv: 'Bütün veriyi CSV olarak dışarı aktar',\n          exporterVisibleAsCsv: 'Görünen veriyi CSV olarak dışarı aktar',\n          exporterSelectedAsCsv: 'Seçili veriyi CSV olarak dışarı aktar',\n          exporterAllAsPdf: 'Bütün veriyi PDF olarak dışarı aktar',\n          exporterVisibleAsPdf: 'Görünen veriyi PDF olarak dışarı aktar',\n          exporterSelectedAsPdf: 'Seçili veriyi PDF olarak dışarı aktar',\n          clearAllFilters: 'Bütün filtreleri kaldır'\n        },\n        importer: {\n          noHeaders: 'Sütun isimleri üretilemiyor, dosyanın bir başlığı var mı?',\n          noObjects: 'Nesneler üretilemiyor, dosyada başlıktan başka bir veri var mı?',\n          invalidCsv: 'Dosya işlenemedi, geçerli bir CSV dosyası mı?',\n          invalidJson: 'Dosya işlenemedi, geçerli bir Json dosyası mı?',\n          jsonNotArray: 'Alınan Json dosyasında bir dizi bulunmalıdır, işlem iptal ediliyor.'\n        },\n        pagination: {\n          aria: {\n            pageToFirst: 'İlk sayfaya',\n            pageBack: 'Geri git',\n            pageSelected: 'Seçili sayfa',\n            pageForward: 'İleri git',\n            pageToLast: 'Sona git'\n          },\n          sizes: 'Sayfadaki nesne sayısı',\n          totalItems: 'kayıtlar',\n          through: '', //note(fsw) : turkish dont have this preposition \n          of: '' //note(fsw) : turkish dont have this preposition\n        },\n        grouping: {\n          group: 'Grupla',\n          ungroup: 'Gruplama',\n          aggregate_count: 'Yekun: Sayı',\n          aggregate_sum: 'Yekun: Toplam',\n          aggregate_max: 'Yekun: Maks',\n          aggregate_min: 'Yekun: Min',\n          aggregate_avg: 'Yekun: Ort',\n          aggregate_remove: 'Yekun: Sil'\n        }\n      });\n      return $delegate;\n    }]);\n  }]);\n})();\n(function () {\n  angular.module('ui.grid').config(['$provide', function($provide) {\n    $provide.decorator('i18nService', ['$delegate', function($delegate) {\n      $delegate.add('ua', {\n        headerCell: {\n          aria: {\n            defaultFilterLabel: 'Фільтр стовпчика',\n            removeFilter: 'Видалити фільтр',\n            columnMenuButtonLabel: 'Меню ствпчика'\n          },\n          priority: 'Пріоритет:',\n          filterLabel: \"Фільтр стовпчика: \"\n        },\n        aggregate: {\n          label: 'елементи'\n        },\n        groupPanel: {\n          description: 'Для групування за стовпчиком перетягніть сюди його назву.'\n        },\n        search: {\n          placeholder: 'Пошук...',\n          showingItems: 'Показати елементи:',\n          selectedItems: 'Обрані елементи:',\n          totalItems: 'Усього елементів:',\n          size: 'Розмір сторінки:',\n          first: 'Перша сторінка',\n          next: 'Наступна сторінка',\n          previous: 'Попередня сторінка',\n          last: 'Остання сторінка'\n        },\n        menu: {\n          text: 'Обрати ствпчики:'\n        },\n        sort: {\n          ascending: 'За зростанням',\n          descending: 'За спаданням',\n          none: 'Без сортування',\n          remove: 'Прибрати сортування'\n        },\n        column: {\n          hide: 'Приховати стовпчик'\n        },\n        aggregation: {\n          count: 'усього рядків: ',\n          sum: 'ітого: ',\n          avg: 'середнє: ',\n          min: 'мін: ',\n          max: 'макс: '\n        },\n\t\t\t\tpinning: {\n\t\t\t\t\tpinLeft: 'Закріпити ліворуч',\n\t\t\t\t\tpinRight: 'Закріпити праворуч',\n\t\t\t\t\tunpin: 'Відкріпити'\n\t\t\t\t},\n        columnMenu: {\n          close: 'Закрити'\n        },\n        gridMenu: {\n          aria: {\n            buttonLabel: 'Меню'\n          },\n          columns: 'Стовпчики:',\n          importerTitle: 'Імпортувати файл',\n          exporterAllAsCsv: 'Експортувати все в CSV',\n          exporterVisibleAsCsv: 'Експортувати видимі дані в CSV',\n          exporterSelectedAsCsv: 'Експортувати обрані дані в CSV',\n          exporterAllAsPdf: 'Експортувати все в PDF',\n          exporterVisibleAsPdf: 'Експортувати видимі дані в PDF',\n          exporterSelectedAsPdf: 'Експортувати обрані дані в PDF',\n          clearAllFilters: 'Очистити всі фільтри'\n        },\n        importer: {\n          noHeaders: 'Не вдалося отримати назви стовпчиків, чи є в файлі заголовок?',\n          noObjects: 'Не вдалося отримати дані, чи є в файлі рядки окрім заголовка?',\n          invalidCsv: 'Не вдалося обробити файл, чи це коректний CSV-файл?',\n          invalidJson: 'Не вдалося обробити файл, чи це коректний JSON?',\n          jsonNotArray: 'JSON-файл що імпортується повинен містити масив, операцію скасовано.'\n        },\n        pagination: {\n          aria: {\n            pageToFirst: 'Перша сторінка',\n            pageBack: 'Попередня сторінка',\n            pageSelected: 'Обрана сторінка',\n            pageForward: 'Наступна сторінка',\n            pageToLast: 'Остання сторінка'\n          },\n          sizes: 'рядків на сторінку',\n          totalItems: 'рядків',\n          through: 'по',\n          of: 'з'\n        },\n        grouping: {\n          group: 'Групувати',\n          ungroup: 'Розгрупувати',\n          aggregate_count: 'Групувати: Кількість',\n          aggregate_sum: 'Для групи: Сума',\n          aggregate_max: 'Для групи: Максимум',\n          aggregate_min: 'Для групи: Мінімум',\n          aggregate_avg: 'Для групи: Серднє',\n          aggregate_remove: 'Для групи: Пусто'\n        }\n      });\n      return $delegate;\n    }]);\n  }]);\n})();\n\n/**\n * @ngdoc overview\n * @name ui.grid.i18n\n * @description\n *\n *  # ui.grid.i18n\n * This module provides i18n functions to ui.grid and any application that wants to use it\n\n *\n * <div doc-module-components=\"ui.grid.i18n\"></div>\n */\n\n(function () {\n  var DIRECTIVE_ALIASES = ['uiT', 'uiTranslate'];\n  var FILTER_ALIASES = ['t', 'uiTranslate'];\n\n  var module = angular.module('ui.grid.i18n');\n\n\n  /**\n   *  @ngdoc object\n   *  @name ui.grid.i18n.constant:i18nConstants\n   *\n   *  @description constants available in i18n module\n   */\n  module.constant('i18nConstants', {\n    MISSING: '[MISSING]',\n    UPDATE_EVENT: '$uiI18n',\n\n    LOCALE_DIRECTIVE_ALIAS: 'uiI18n',\n    // default to english\n    DEFAULT_LANG: 'en'\n  });\n\n//    module.config(['$provide', function($provide) {\n//        $provide.decorator('i18nService', ['$delegate', function($delegate) {}])}]);\n\n  /**\n   *  @ngdoc service\n   *  @name ui.grid.i18n.service:i18nService\n   *\n   *  @description Services for i18n\n   */\n  module.service('i18nService', ['$log', 'i18nConstants', '$rootScope',\n    function ($log, i18nConstants, $rootScope) {\n\n      var langCache = {\n        _langs: {},\n        current: null,\n        get: function (lang) {\n          return this._langs[lang.toLowerCase()];\n        },\n        add: function (lang, strings) {\n          var lower = lang.toLowerCase();\n          if (!this._langs[lower]) {\n            this._langs[lower] = {};\n          }\n          angular.extend(this._langs[lower], strings);\n        },\n        getAllLangs: function () {\n          var langs = [];\n          if (!this._langs) {\n            return langs;\n          }\n\n          for (var key in this._langs) {\n            langs.push(key);\n          }\n\n          return langs;\n        },\n        setCurrent: function (lang) {\n          this.current = lang.toLowerCase();\n        },\n        getCurrentLang: function () {\n          return this.current;\n        }\n      };\n\n      var service = {\n\n        /**\n         * @ngdoc service\n         * @name add\n         * @methodOf ui.grid.i18n.service:i18nService\n         * @description  Adds the languages and strings to the cache. Decorate this service to\n         * add more translation strings\n         * @param {string} lang language to add\n         * @param {object} stringMaps of strings to add grouped by property names\n         * @example\n         * <pre>\n         *      i18nService.add('en', {\n         *         aggregate: {\n         *                 label1: 'items',\n         *                 label2: 'some more items'\n         *                 }\n         *         },\n         *         groupPanel: {\n         *              description: 'Drag a column header here and drop it to group by that column.'\n         *           }\n         *      }\n         * </pre>\n         */\n        add: function (langs, stringMaps) {\n          if (typeof(langs) === 'object') {\n            angular.forEach(langs, function (lang) {\n              if (lang) {\n                langCache.add(lang, stringMaps);\n              }\n            });\n          } else {\n            langCache.add(langs, stringMaps);\n          }\n        },\n\n        /**\n         * @ngdoc service\n         * @name getAllLangs\n         * @methodOf ui.grid.i18n.service:i18nService\n         * @description  return all currently loaded languages\n         * @returns {array} string\n         */\n        getAllLangs: function () {\n          return langCache.getAllLangs();\n        },\n\n        /**\n         * @ngdoc service\n         * @name get\n         * @methodOf ui.grid.i18n.service:i18nService\n         * @description  return all currently loaded languages\n         * @param {string} lang to return.  If not specified, returns current language\n         * @returns {object} the translation string maps for the language\n         */\n        get: function (lang) {\n          var language = lang ? lang : service.getCurrentLang();\n          return langCache.get(language);\n        },\n\n        /**\n         * @ngdoc service\n         * @name getSafeText\n         * @methodOf ui.grid.i18n.service:i18nService\n         * @description  returns the text specified in the path or a Missing text if text is not found\n         * @param {string} path property path to use for retrieving text from string map\n         * @param {string} lang to return.  If not specified, returns current language\n         * @returns {object} the translation for the path\n         * @example\n         * <pre>\n         * i18nService.getSafeText('sort.ascending')\n         * </pre>\n         */\n        getSafeText: function (path, lang) {\n          var language = lang ? lang : service.getCurrentLang();\n          var trans = langCache.get(language);\n\n          if (!trans) {\n            return i18nConstants.MISSING;\n          }\n\n          var paths = path.split('.');\n          var current = trans;\n\n          for (var i = 0; i < paths.length; ++i) {\n            if (current[paths[i]] === undefined || current[paths[i]] === null) {\n              return i18nConstants.MISSING;\n            } else {\n              current = current[paths[i]];\n            }\n          }\n\n          return current;\n\n        },\n\n        /**\n         * @ngdoc service\n         * @name setCurrentLang\n         * @methodOf ui.grid.i18n.service:i18nService\n         * @description sets the current language to use in the application\n         * $broadcasts the Update_Event on the $rootScope\n         * @param {string} lang to set\n         * @example\n         * <pre>\n         * i18nService.setCurrentLang('fr');\n         * </pre>\n         */\n\n        setCurrentLang: function (lang) {\n          if (lang) {\n            langCache.setCurrent(lang);\n            $rootScope.$broadcast(i18nConstants.UPDATE_EVENT);\n          }\n        },\n\n        /**\n         * @ngdoc service\n         * @name getCurrentLang\n         * @methodOf ui.grid.i18n.service:i18nService\n         * @description returns the current language used in the application\n         */\n        getCurrentLang: function () {\n          var lang = langCache.getCurrentLang();\n          if (!lang) {\n            lang = i18nConstants.DEFAULT_LANG;\n            langCache.setCurrent(lang);\n          }\n          return lang;\n        }\n\n      };\n\n      return service;\n\n    }]);\n\n  var localeDirective = function (i18nService, i18nConstants) {\n    return {\n      compile: function () {\n        return {\n          pre: function ($scope, $elm, $attrs) {\n            var alias = i18nConstants.LOCALE_DIRECTIVE_ALIAS;\n            // check for watchable property\n            var lang = $scope.$eval($attrs[alias]);\n            if (lang) {\n              $scope.$watch($attrs[alias], function () {\n                i18nService.setCurrentLang(lang);\n              });\n            } else if ($attrs.$$observers) {\n              $attrs.$observe(alias, function () {\n                i18nService.setCurrentLang($attrs[alias] || i18nConstants.DEFAULT_LANG);\n              });\n            }\n          }\n        };\n      }\n    };\n  };\n\n  module.directive('uiI18n', ['i18nService', 'i18nConstants', localeDirective]);\n\n  // directive syntax\n  var uitDirective = function ($parse, i18nService, i18nConstants) {\n    return {\n      restrict: 'EA',\n      compile: function () {\n        return {\n          pre: function ($scope, $elm, $attrs) {\n            var alias1 = DIRECTIVE_ALIASES[0],\n              alias2 = DIRECTIVE_ALIASES[1];\n            var token = $attrs[alias1] || $attrs[alias2] || $elm.html();\n            var missing = i18nConstants.MISSING + token;\n            var observer;\n            if ($attrs.$$observers) {\n              var prop = $attrs[alias1] ? alias1 : alias2;\n              observer = $attrs.$observe(prop, function (result) {\n                if (result) {\n                  $elm.html($parse(result)(i18nService.getCurrentLang()) || missing);\n                }\n              });\n            }\n            var getter = $parse(token);\n            var listener = $scope.$on(i18nConstants.UPDATE_EVENT, function (evt) {\n              if (observer) {\n                observer($attrs[alias1] || $attrs[alias2]);\n              } else {\n                // set text based on i18n current language\n                $elm.html(getter(i18nService.get()) || missing);\n              }\n            });\n            $scope.$on('$destroy', listener);\n\n            $elm.html(getter(i18nService.get()) || missing);\n          }\n        };\n      }\n    };\n  };\n\n  angular.forEach( DIRECTIVE_ALIASES, function ( alias ) {\n    module.directive( alias, ['$parse', 'i18nService', 'i18nConstants', uitDirective] );\n  } );\n\n  // optional filter syntax\n  var uitFilter = function ($parse, i18nService, i18nConstants) {\n    return function (data) {\n      var getter = $parse(data);\n      // set text based on i18n current language\n      return getter(i18nService.get()) || i18nConstants.MISSING + data;\n    };\n  };\n\n  angular.forEach( FILTER_ALIASES, function ( alias ) {\n    module.filter( alias, ['$parse', 'i18nService', 'i18nConstants', uitFilter] );\n  } );\n\n\n})();\n(function() {\n  angular.module('ui.grid').config(['$provide', function($provide) {\n    $provide.decorator('i18nService', ['$delegate', function($delegate) {\n      $delegate.add('zh-cn', {\n        headerCell: {\n          aria: {\n            defaultFilterLabel: '列过滤器',\n            removeFilter: '移除过滤器',\n            columnMenuButtonLabel: '列菜单'\n          },\n          priority: '优先级:',\n          filterLabel: \"列过滤器: \"\n        },\n        aggregate: {\n          label: '行'\n        },\n        groupPanel: {\n          description: '拖曳表头到此处进行分组'\n        },\n        search: {\n          placeholder: '查找',\n          showingItems: '已显示行数：',\n          selectedItems: '已选择行数：',\n          totalItems: '总行数：',\n          size: '每页显示行数：',\n          first: '首页',\n          next: '下一页',\n          previous: '上一页',\n          last: '末页'\n        },\n        menu: {\n          text: '选择列：'\n        },\n        sort: {\n          ascending: '升序',\n          descending: '降序',\n          none: '无序',\n          remove: '取消排序'\n        },\n        column: {\n          hide: '隐藏列'\n        },\n        aggregation: {\n          count: '计数：',\n          sum: '求和：',\n          avg: '均值：',\n          min: '最小值：',\n          max: '最大值：'\n        },\n        pinning: {\n          pinLeft: '左侧固定',\n          pinRight: '右侧固定',\n          unpin: '取消固定'\n        },\n        columnMenu: {\n          close: '关闭'\n        },\n        gridMenu: {\n          aria: {\n            buttonLabel: '表格菜单'\n          },\n          columns: '列：',\n          importerTitle: '导入文件',\n          exporterAllAsCsv: '导出全部数据到CSV',\n          exporterVisibleAsCsv: '导出可见数据到CSV',\n          exporterSelectedAsCsv: '导出已选数据到CSV',\n          exporterAllAsPdf: '导出全部数据到PDF',\n          exporterVisibleAsPdf: '导出可见数据到PDF',\n          exporterSelectedAsPdf: '导出已选数据到PDF',\n          clearAllFilters: '清除所有过滤器'\n        },\n        importer: {\n          noHeaders: '无法获取列名，确定文件包含表头？',\n          noObjects: '无法获取数据，确定文件包含数据？',\n          invalidCsv: '无法处理文件，确定是合法的CSV文件？',\n          invalidJson: '无法处理文件，确定是合法的JSON文件？',\n          jsonNotArray: '导入的文件不是JSON数组！'\n        },\n        pagination: {\n          aria: {\n            pageToFirst: '第一页',\n            pageBack: '上一页',\n            pageSelected: '当前页',\n            pageForward: '下一页',\n            pageToLast: '最后一页'\n          },\n          sizes: '行每页',\n          totalItems: '行',\n          through: '至',\n          of: '共'\n        },\n        grouping: {\n          group: '分组',\n          ungroup: '取消分组',\n          aggregate_count: '合计: 计数',\n          aggregate_sum: '合计: 求和',\n          aggregate_max: '合计: 最大',\n          aggregate_min: '合计: 最小',\n          aggregate_avg: '合计: 平均',\n          aggregate_remove: '合计: 移除'\n        }\n      });\n      return $delegate;\n    }]);\n  }]);\n})();\n\n(function() {\n  angular.module('ui.grid').config(['$provide', function($provide) {\n    $provide.decorator('i18nService', ['$delegate', function($delegate) {\n      $delegate.add('zh-tw', {\n        aggregate: {\n          label: '行'\n        },\n        groupPanel: {\n          description: '拖曳表頭到此處進行分組'\n        },\n        search: {\n          placeholder: '查找',\n          showingItems: '已顯示行數：',\n          selectedItems: '已選擇行數：',\n          totalItems: '總行數：',\n          size: '每頁顯示行數：',\n          first: '首頁',\n          next: '下壹頁',\n          previous: '上壹頁',\n          last: '末頁'\n        },\n        menu: {\n          text: '選擇列：'\n        },\n        sort: {\n          ascending: '升序',\n          descending: '降序',\n          remove: '取消排序'\n        },\n        column: {\n          hide: '隱藏列'\n        },\n        aggregation: {\n          count: '計數：',\n          sum: '求和：',\n          avg: '均值：',\n          min: '最小值：',\n          max: '最大值：'\n        },\n        pinning: {\n          pinLeft: '左側固定',\n          pinRight: '右側固定',\n          unpin: '取消固定'\n        },\n        gridMenu: {\n          columns: '列：',\n          importerTitle: '導入文件',\n          exporterAllAsCsv: '導出全部數據到CSV',\n          exporterVisibleAsCsv: '導出可見數據到CSV',\n          exporterSelectedAsCsv: '導出已選數據到CSV',\n          exporterAllAsPdf: '導出全部數據到PDF',\n          exporterVisibleAsPdf: '導出可見數據到PDF',\n          exporterSelectedAsPdf: '導出已選數據到PDF',\n          clearAllFilters: '清除所有过滤器'\n        },\n        importer: {\n          noHeaders: '無法獲取列名，確定文件包含表頭？',\n          noObjects: '無法獲取數據，確定文件包含數據？',\n          invalidCsv: '無法處理文件，確定是合法的CSV文件？',\n          invalidJson: '無法處理文件，確定是合法的JSON文件？',\n          jsonNotArray: '導入的文件不是JSON數組！'\n        },\n        pagination: {\n          sizes: '行每頁',\n          totalItems: '行'\n        }\n      });\n      return $delegate;\n    }]);\n  }]);\n})();\n\n(function() {\n  'use strict';\n  /**\n   *  @ngdoc overview\n   *  @name ui.grid.autoResize\n   *\n   *  @description\n   *\n   *  #ui.grid.autoResize\n   *\n   *  <div class=\"alert alert-warning\" role=\"alert\"><strong>Beta</strong> This feature is ready for testing, but it either hasn't seen a lot of use or has some known bugs.</div>\n   *\n   *  This module provides auto-resizing functionality to UI-Grid.\n   */\n  var module = angular.module('ui.grid.autoResize', ['ui.grid']);\n\n\n  module.directive('uiGridAutoResize', ['$timeout', 'gridUtil', function ($timeout, gridUtil) {\n    return {\n      require: 'uiGrid',\n      scope: false,\n      link: function ($scope, $elm, $attrs, uiGridCtrl) {\n        var prevGridWidth, prevGridHeight;\n\n        function getDimensions() {\n          prevGridHeight = gridUtil.elementHeight($elm);\n          prevGridWidth = gridUtil.elementWidth($elm);\n        }\n\n        // Initialize the dimensions\n        getDimensions();\n\n        var resizeTimeoutId;\n        function startTimeout() {\n          clearTimeout(resizeTimeoutId);\n\n          resizeTimeoutId = setTimeout(function () {\n            var newGridHeight = gridUtil.elementHeight($elm);\n            var newGridWidth = gridUtil.elementWidth($elm);\n\n            if (newGridHeight !== prevGridHeight || newGridWidth !== prevGridWidth) {\n              uiGridCtrl.grid.gridHeight = newGridHeight;\n              uiGridCtrl.grid.gridWidth = newGridWidth;\n              uiGridCtrl.grid.api.core.raise.gridDimensionChanged(prevGridHeight, prevGridWidth, newGridHeight, newGridWidth);\n\n              $scope.$apply(function () {\n                uiGridCtrl.grid.refresh()\n                  .then(function () {\n                    getDimensions();\n\n                    startTimeout();\n                  });\n              });\n            }\n            else {\n              startTimeout();\n            }\n          }, 250);\n        }\n\n        startTimeout();\n\n        $scope.$on('$destroy', function() {\n          clearTimeout(resizeTimeoutId);\n        });\n      }\n    };\n  }]);\n})();\n\n(function () {\n  'use strict';\n\n  /**\n   *  @ngdoc overview\n   *  @name ui.grid.cellNav\n   *\n   *  @description\n\n      #ui.grid.cellNav\n\n      <div class=\"alert alert-success\" role=\"alert\"><strong>Stable</strong> This feature is stable. There should no longer be breaking api changes without a deprecation warning.</div>\n\n      This module provides auto-resizing functionality to UI-Grid.\n   */\n  var module = angular.module('ui.grid.cellNav', ['ui.grid']);\n\n  /**\n   *  @ngdoc object\n   *  @name ui.grid.cellNav.constant:uiGridCellNavConstants\n   *\n   *  @description constants available in cellNav\n   */\n  module.constant('uiGridCellNavConstants', {\n    FEATURE_NAME: 'gridCellNav',\n    CELL_NAV_EVENT: 'cellNav',\n    direction: {LEFT: 0, RIGHT: 1, UP: 2, DOWN: 3, PG_UP: 4, PG_DOWN: 5},\n    EVENT_TYPE: {\n      KEYDOWN: 0,\n      CLICK: 1,\n      CLEAR: 2\n    }\n  });\n\n\n  module.factory('uiGridCellNavFactory', ['gridUtil', 'uiGridConstants', 'uiGridCellNavConstants', 'GridRowColumn', '$q',\n    function (gridUtil, uiGridConstants, uiGridCellNavConstants, GridRowColumn, $q) {\n      /**\n       *  @ngdoc object\n       *  @name ui.grid.cellNav.object:CellNav\n       *  @description returns a CellNav prototype function\n       *  @param {object} rowContainer container for rows\n       *  @param {object} colContainer parent column container\n       *  @param {object} leftColContainer column container to the left of parent\n       *  @param {object} rightColContainer column container to the right of parent\n       */\n      var UiGridCellNav = function UiGridCellNav(rowContainer, colContainer, leftColContainer, rightColContainer) {\n        this.rows = rowContainer.visibleRowCache;\n        this.columns = colContainer.visibleColumnCache;\n        this.leftColumns = leftColContainer ? leftColContainer.visibleColumnCache : [];\n        this.rightColumns = rightColContainer ? rightColContainer.visibleColumnCache : [];\n        this.bodyContainer = rowContainer;\n      };\n\n      /** returns focusable columns of all containers */\n      UiGridCellNav.prototype.getFocusableCols = function () {\n        var allColumns = this.leftColumns.concat(this.columns, this.rightColumns);\n\n        return allColumns.filter(function (col) {\n          return col.colDef.allowCellFocus;\n        });\n      };\n\n      /**\n       *  @ngdoc object\n       *  @name ui.grid.cellNav.api:GridRow\n       *\n       *  @description GridRow settings for cellNav feature, these are available to be\n       *  set only internally (for example, by other features)\n       */\n\n      /**\n       *  @ngdoc object\n       *  @name allowCellFocus\n       *  @propertyOf  ui.grid.cellNav.api:GridRow\n       *  @description Enable focus on a cell within this row.  If set to false then no cells\n       *  in this row can be focused - group header rows as an example would set this to false.\n       *  <br/>Defaults to true\n       */\n      /** returns focusable rows */\n      UiGridCellNav.prototype.getFocusableRows = function () {\n        return this.rows.filter(function(row) {\n          return row.allowCellFocus !== false;\n        });\n      };\n\n      UiGridCellNav.prototype.getNextRowCol = function (direction, curRow, curCol) {\n        switch (direction) {\n          case uiGridCellNavConstants.direction.LEFT:\n            return this.getRowColLeft(curRow, curCol);\n          case uiGridCellNavConstants.direction.RIGHT:\n            return this.getRowColRight(curRow, curCol);\n          case uiGridCellNavConstants.direction.UP:\n            return this.getRowColUp(curRow, curCol);\n          case uiGridCellNavConstants.direction.DOWN:\n            return this.getRowColDown(curRow, curCol);\n          case uiGridCellNavConstants.direction.PG_UP:\n            return this.getRowColPageUp(curRow, curCol);\n          case uiGridCellNavConstants.direction.PG_DOWN:\n            return this.getRowColPageDown(curRow, curCol);\n        }\n\n      };\n\n      UiGridCellNav.prototype.initializeSelection = function () {\n        var focusableCols = this.getFocusableCols();\n        var focusableRows = this.getFocusableRows();\n        if (focusableCols.length === 0 || focusableRows.length === 0) {\n          return null;\n        }\n\n        var curRowIndex = 0;\n        var curColIndex = 0;\n        return new GridRowColumn(focusableRows[0], focusableCols[0]); //return same row\n      };\n\n      UiGridCellNav.prototype.getRowColLeft = function (curRow, curCol) {\n        var focusableCols = this.getFocusableCols();\n        var focusableRows = this.getFocusableRows();\n        var curColIndex = focusableCols.indexOf(curCol);\n        var curRowIndex = focusableRows.indexOf(curRow);\n\n        //could not find column in focusable Columns so set it to 1\n        if (curColIndex === -1) {\n          curColIndex = 1;\n        }\n\n        var nextColIndex = curColIndex === 0 ? focusableCols.length - 1 : curColIndex - 1;\n\n        //get column to left\n        if (nextColIndex > curColIndex) {\n          // On the first row\n          // if (curRowIndex === 0 && curColIndex === 0) {\n          //   return null;\n          // }\n          if (curRowIndex === 0) {\n            return new GridRowColumn(curRow, focusableCols[nextColIndex]); //return same row\n          }\n          else {\n            //up one row and far right column\n            return new GridRowColumn(focusableRows[curRowIndex - 1], focusableCols[nextColIndex]);\n          }\n        }\n        else {\n          return new GridRowColumn(curRow, focusableCols[nextColIndex]);\n        }\n      };\n\n\n\n      UiGridCellNav.prototype.getRowColRight = function (curRow, curCol) {\n        var focusableCols = this.getFocusableCols();\n        var focusableRows = this.getFocusableRows();\n        var curColIndex = focusableCols.indexOf(curCol);\n        var curRowIndex = focusableRows.indexOf(curRow);\n\n        //could not find column in focusable Columns so set it to 0\n        if (curColIndex === -1) {\n          curColIndex = 0;\n        }\n        var nextColIndex = curColIndex === focusableCols.length - 1 ? 0 : curColIndex + 1;\n\n        if (nextColIndex < curColIndex) {\n          if (curRowIndex === focusableRows.length - 1) {\n            return new GridRowColumn(curRow, focusableCols[nextColIndex]); //return same row\n          }\n          else {\n            //down one row and far left column\n            return new GridRowColumn(focusableRows[curRowIndex + 1], focusableCols[nextColIndex]);\n          }\n        }\n        else {\n          return new GridRowColumn(curRow, focusableCols[nextColIndex]);\n        }\n      };\n\n      UiGridCellNav.prototype.getRowColDown = function (curRow, curCol) {\n        var focusableCols = this.getFocusableCols();\n        var focusableRows = this.getFocusableRows();\n        var curColIndex = focusableCols.indexOf(curCol);\n        var curRowIndex = focusableRows.indexOf(curRow);\n\n        //could not find column in focusable Columns so set it to 0\n        if (curColIndex === -1) {\n          curColIndex = 0;\n        }\n\n        if (curRowIndex === focusableRows.length - 1) {\n          return new GridRowColumn(curRow, focusableCols[curColIndex]); //return same row\n        }\n        else {\n          //down one row\n          return new GridRowColumn(focusableRows[curRowIndex + 1], focusableCols[curColIndex]);\n        }\n      };\n\n      UiGridCellNav.prototype.getRowColPageDown = function (curRow, curCol) {\n        var focusableCols = this.getFocusableCols();\n        var focusableRows = this.getFocusableRows();\n        var curColIndex = focusableCols.indexOf(curCol);\n        var curRowIndex = focusableRows.indexOf(curRow);\n\n        //could not find column in focusable Columns so set it to 0\n        if (curColIndex === -1) {\n          curColIndex = 0;\n        }\n\n        var pageSize = this.bodyContainer.minRowsToRender();\n        if (curRowIndex >= focusableRows.length - pageSize) {\n          return new GridRowColumn(focusableRows[focusableRows.length - 1], focusableCols[curColIndex]); //return last row\n        }\n        else {\n          //down one page\n          return new GridRowColumn(focusableRows[curRowIndex + pageSize], focusableCols[curColIndex]);\n        }\n      };\n\n      UiGridCellNav.prototype.getRowColUp = function (curRow, curCol) {\n        var focusableCols = this.getFocusableCols();\n        var focusableRows = this.getFocusableRows();\n        var curColIndex = focusableCols.indexOf(curCol);\n        var curRowIndex = focusableRows.indexOf(curRow);\n\n        //could not find column in focusable Columns so set it to 0\n        if (curColIndex === -1) {\n          curColIndex = 0;\n        }\n\n        if (curRowIndex === 0) {\n          return new GridRowColumn(curRow, focusableCols[curColIndex]); //return same row\n        }\n        else {\n          //up one row\n          return new GridRowColumn(focusableRows[curRowIndex - 1], focusableCols[curColIndex]);\n        }\n      };\n\n      UiGridCellNav.prototype.getRowColPageUp = function (curRow, curCol) {\n        var focusableCols = this.getFocusableCols();\n        var focusableRows = this.getFocusableRows();\n        var curColIndex = focusableCols.indexOf(curCol);\n        var curRowIndex = focusableRows.indexOf(curRow);\n\n        //could not find column in focusable Columns so set it to 0\n        if (curColIndex === -1) {\n          curColIndex = 0;\n        }\n\n        var pageSize = this.bodyContainer.minRowsToRender();\n        if (curRowIndex - pageSize < 0) {\n          return new GridRowColumn(focusableRows[0], focusableCols[curColIndex]); //return first row\n        }\n        else {\n          //up one page\n          return new GridRowColumn(focusableRows[curRowIndex - pageSize], focusableCols[curColIndex]);\n        }\n      };\n      return UiGridCellNav;\n    }]);\n\n  /**\n   *  @ngdoc service\n   *  @name ui.grid.cellNav.service:uiGridCellNavService\n   *\n   *  @description Services for cell navigation features. If you don't like the key maps we use,\n   *  or the direction cells navigation, override with a service decorator (see angular docs)\n   */\n  module.service('uiGridCellNavService', ['gridUtil', 'uiGridConstants', 'uiGridCellNavConstants', '$q', 'uiGridCellNavFactory', 'GridRowColumn', 'ScrollEvent',\n    function (gridUtil, uiGridConstants, uiGridCellNavConstants, $q, UiGridCellNav, GridRowColumn, ScrollEvent) {\n\n      var service = {\n\n        initializeGrid: function (grid) {\n          grid.registerColumnBuilder(service.cellNavColumnBuilder);\n\n\n          /**\n           *  @ngdoc object\n           *  @name ui.grid.cellNav:Grid.cellNav\n           * @description cellNav properties added to grid class\n           */\n          grid.cellNav = {};\n          grid.cellNav.lastRowCol = null;\n          grid.cellNav.focusedCells = [];\n\n          service.defaultGridOptions(grid.options);\n\n          /**\n           *  @ngdoc object\n           *  @name ui.grid.cellNav.api:PublicApi\n           *\n           *  @description Public Api for cellNav feature\n           */\n          var publicApi = {\n            events: {\n              cellNav: {\n                /**\n                 * @ngdoc event\n                 * @name navigate\n                 * @eventOf  ui.grid.cellNav.api:PublicApi\n                 * @description raised when the active cell is changed\n                 * <pre>\n                 *      gridApi.cellNav.on.navigate(scope,function(newRowcol, oldRowCol){})\n                 * </pre>\n                 * @param {object} newRowCol new position\n                 * @param {object} oldRowCol old position\n                 */\n                navigate: function (newRowCol, oldRowCol) {},\n                /**\n                 * @ngdoc event\n                 * @name viewPortKeyDown\n                 * @eventOf  ui.grid.cellNav.api:PublicApi\n                 * @description  is raised when the viewPort receives a keyDown event. Cells never get focus in uiGrid\n                 * due to the difficulties of setting focus on a cell that is not visible in the viewport.  Use this\n                 * event whenever you need a keydown event on a cell\n                 * <br/>\n                 * @param {object} event keydown event\n                 * @param {object} rowCol current rowCol position\n                 */\n                viewPortKeyDown: function (event, rowCol) {},\n\n                /**\n                 * @ngdoc event\n                 * @name viewPortKeyPress\n                 * @eventOf  ui.grid.cellNav.api:PublicApi\n                 * @description  is raised when the viewPort receives a keyPress event. Cells never get focus in uiGrid\n                 * due to the difficulties of setting focus on a cell that is not visible in the viewport.  Use this\n                 * event whenever you need a keypress event on a cell\n                 * <br/>\n                 * @param {object} event keypress event\n                 * @param {object} rowCol current rowCol position\n                 */\n                viewPortKeyPress: function (event, rowCol) {}\n              }\n            },\n            methods: {\n              cellNav: {\n                /**\n                 * @ngdoc function\n                 * @name scrollToFocus\n                 * @methodOf  ui.grid.cellNav.api:PublicApi\n                 * @description brings the specified row and column into view, and sets focus\n                 * to that cell\n                 * @param {object} rowEntity gridOptions.data[] array instance to make visible and set focus\n                 * @param {object} colDef to make visible and set focus\n                 * @returns {promise} a promise that is resolved after any scrolling is finished\n                 */\n                scrollToFocus: function (rowEntity, colDef) {\n                  return service.scrollToFocus(grid, rowEntity, colDef);\n                },\n\n                /**\n                 * @ngdoc function\n                 * @name getFocusedCell\n                 * @methodOf  ui.grid.cellNav.api:PublicApi\n                 * @description returns the current (or last if Grid does not have focus) focused row and column\n                 * <br> value is null if no selection has occurred\n                 */\n                getFocusedCell: function () {\n                  return grid.cellNav.lastRowCol;\n                },\n\n                /**\n                 * @ngdoc function\n                 * @name getCurrentSelection\n                 * @methodOf  ui.grid.cellNav.api:PublicApi\n                 * @description returns an array containing the current selection\n                 * <br> array is empty if no selection has occurred\n                 */\n                getCurrentSelection: function () {\n                  return grid.cellNav.focusedCells;\n                },\n\n                /**\n                 * @ngdoc function\n                 * @name rowColSelectIndex\n                 * @methodOf  ui.grid.cellNav.api:PublicApi\n                 * @description returns the index in the order in which the GridRowColumn was selected, returns -1 if the GridRowColumn\n                 * isn't selected\n                 * @param {object} rowCol the rowCol to evaluate\n                 */\n                rowColSelectIndex: function (rowCol) {\n                  //return gridUtil.arrayContainsObjectWithProperty(grid.cellNav.focusedCells, 'col.uid', rowCol.col.uid) &&\n                  var index = -1;\n                  for (var i = 0; i < grid.cellNav.focusedCells.length; i++) {\n                    if (grid.cellNav.focusedCells[i].col.uid === rowCol.col.uid &&\n                      grid.cellNav.focusedCells[i].row.uid === rowCol.row.uid) {\n                      index = i;\n                      break;\n                    }\n                  }\n                  return index;\n                }\n              }\n            }\n          };\n\n          grid.api.registerEventsFromObject(publicApi.events);\n\n          grid.api.registerMethodsFromObject(publicApi.methods);\n\n        },\n\n        defaultGridOptions: function (gridOptions) {\n          /**\n           *  @ngdoc object\n           *  @name ui.grid.cellNav.api:GridOptions\n           *\n           *  @description GridOptions for cellNav feature, these are available to be\n           *  set using the ui-grid {@link ui.grid.class:GridOptions gridOptions}\n           */\n\n          /**\n           *  @ngdoc object\n           *  @name modifierKeysToMultiSelectCells\n           *  @propertyOf  ui.grid.cellNav.api:GridOptions\n           *  @description Enable multiple cell selection only when using the ctrlKey or shiftKey.\n           *  <br/>Defaults to false\n           */\n          gridOptions.modifierKeysToMultiSelectCells = gridOptions.modifierKeysToMultiSelectCells === true;\n\n        },\n\n        /**\n         * @ngdoc service\n         * @name decorateRenderContainers\n         * @methodOf ui.grid.cellNav.service:uiGridCellNavService\n         * @description  decorates grid renderContainers with cellNav functions\n         */\n        decorateRenderContainers: function (grid) {\n\n          var rightContainer = grid.hasRightContainer() ? grid.renderContainers.right : null;\n          var leftContainer = grid.hasLeftContainer() ? grid.renderContainers.left : null;\n\n          if (leftContainer !== null) {\n            grid.renderContainers.left.cellNav = new UiGridCellNav(grid.renderContainers.body, leftContainer, rightContainer, grid.renderContainers.body);\n          }\n          if (rightContainer !== null) {\n            grid.renderContainers.right.cellNav = new UiGridCellNav(grid.renderContainers.body, rightContainer, grid.renderContainers.body, leftContainer);\n          }\n\n          grid.renderContainers.body.cellNav = new UiGridCellNav(grid.renderContainers.body, grid.renderContainers.body, leftContainer, rightContainer);\n        },\n\n        /**\n         * @ngdoc service\n         * @name getDirection\n         * @methodOf ui.grid.cellNav.service:uiGridCellNavService\n         * @description  determines which direction to for a given keyDown event\n         * @returns {uiGridCellNavConstants.direction} direction\n         */\n        getDirection: function (evt) {\n          if (evt.keyCode === uiGridConstants.keymap.LEFT ||\n            (evt.keyCode === uiGridConstants.keymap.TAB && evt.shiftKey)) {\n            return uiGridCellNavConstants.direction.LEFT;\n          }\n          if (evt.keyCode === uiGridConstants.keymap.RIGHT ||\n            evt.keyCode === uiGridConstants.keymap.TAB) {\n            return uiGridCellNavConstants.direction.RIGHT;\n          }\n\n          if (evt.keyCode === uiGridConstants.keymap.UP ||\n            (evt.keyCode === uiGridConstants.keymap.ENTER && evt.shiftKey) ) {\n            return uiGridCellNavConstants.direction.UP;\n          }\n\n          if (evt.keyCode === uiGridConstants.keymap.PG_UP){\n            return uiGridCellNavConstants.direction.PG_UP;\n          }\n\n          if (evt.keyCode === uiGridConstants.keymap.DOWN ||\n            evt.keyCode === uiGridConstants.keymap.ENTER && !(evt.ctrlKey || evt.altKey)) {\n            return uiGridCellNavConstants.direction.DOWN;\n          }\n\n          if (evt.keyCode === uiGridConstants.keymap.PG_DOWN){\n            return uiGridCellNavConstants.direction.PG_DOWN;\n          }\n\n          return null;\n        },\n\n        /**\n         * @ngdoc service\n         * @name cellNavColumnBuilder\n         * @methodOf ui.grid.cellNav.service:uiGridCellNavService\n         * @description columnBuilder function that adds cell navigation properties to grid column\n         * @returns {promise} promise that will load any needed templates when resolved\n         */\n        cellNavColumnBuilder: function (colDef, col, gridOptions) {\n          var promises = [];\n\n          /**\n           *  @ngdoc object\n           *  @name ui.grid.cellNav.api:ColumnDef\n           *\n           *  @description Column Definitions for cellNav feature, these are available to be\n           *  set using the ui-grid {@link ui.grid.class:GridOptions.columnDef gridOptions.columnDefs}\n           */\n\n          /**\n           *  @ngdoc object\n           *  @name allowCellFocus\n           *  @propertyOf  ui.grid.cellNav.api:ColumnDef\n           *  @description Enable focus on a cell within this column.\n           *  <br/>Defaults to true\n           */\n          colDef.allowCellFocus = colDef.allowCellFocus === undefined ? true : colDef.allowCellFocus;\n\n          return $q.all(promises);\n        },\n\n        /**\n         * @ngdoc method\n         * @methodOf ui.grid.cellNav.service:uiGridCellNavService\n         * @name scrollToFocus\n         * @description Scroll the grid such that the specified\n         * row and column is in view, and set focus to the cell in that row and column\n         * @param {Grid} grid the grid you'd like to act upon, usually available\n         * from gridApi.grid\n         * @param {object} rowEntity gridOptions.data[] array instance to make visible and set focus to\n         * @param {object} colDef to make visible and set focus to\n         * @returns {promise} a promise that is resolved after any scrolling is finished\n         */\n        scrollToFocus: function (grid, rowEntity, colDef) {\n          var gridRow = null, gridCol = null;\n\n          if (typeof(rowEntity) !== 'undefined' && rowEntity !== null) {\n            gridRow = grid.getRow(rowEntity);\n          }\n\n          if (typeof(colDef) !== 'undefined' && colDef !== null) {\n            gridCol = grid.getColumn(colDef.name ? colDef.name : colDef.field);\n          }\n          return grid.api.core.scrollToIfNecessary(gridRow, gridCol).then(function () {\n            var rowCol = { row: gridRow, col: gridCol };\n\n            // Broadcast the navigation\n            if (gridRow !== null && gridCol !== null) {\n              grid.cellNav.broadcastCellNav(rowCol);\n            }\n          });\n\n\n\n        },\n\n\n        /**\n         * @ngdoc method\n         * @methodOf ui.grid.cellNav.service:uiGridCellNavService\n         * @name getLeftWidth\n         * @description Get the current drawn width of the columns in the\n         * grid up to the numbered column, and add an apportionment for the\n         * column that we're on.  So if we are on column 0, we want to scroll\n         * 0% (i.e. exclude this column from calc).  If we're on the last column\n         * we want to scroll to 100% (i.e. include this column in the calc). So\n         * we include (thisColIndex / totalNumberCols) % of this column width\n         * @param {Grid} grid the grid you'd like to act upon, usually available\n         * from gridApi.grid\n         * @param {gridCol} upToCol the column to total up to and including\n         */\n        getLeftWidth: function (grid, upToCol) {\n          var width = 0;\n\n          if (!upToCol) {\n            return width;\n          }\n\n          var lastIndex = grid.renderContainers.body.visibleColumnCache.indexOf( upToCol );\n\n          // total column widths up-to but not including the passed in column\n          grid.renderContainers.body.visibleColumnCache.forEach( function( col, index ) {\n            if ( index < lastIndex ){\n              width += col.drawnWidth;\n            }\n          });\n\n          // pro-rata the final column based on % of total columns.\n          var percentage = lastIndex === 0 ? 0 : (lastIndex + 1) / grid.renderContainers.body.visibleColumnCache.length;\n          width += upToCol.drawnWidth * percentage;\n\n          return width;\n        }\n      };\n\n      return service;\n    }]);\n\n  /**\n   *  @ngdoc directive\n   *  @name ui.grid.cellNav.directive:uiCellNav\n   *  @element div\n   *  @restrict EA\n   *\n   *  @description Adds cell navigation features to the grid columns\n   *\n   *  @example\n   <example module=\"app\">\n   <file name=\"app.js\">\n   var app = angular.module('app', ['ui.grid', 'ui.grid.cellNav']);\n\n   app.controller('MainCtrl', ['$scope', function ($scope) {\n      $scope.data = [\n        { name: 'Bob', title: 'CEO' },\n            { name: 'Frank', title: 'Lowly Developer' }\n      ];\n\n      $scope.columnDefs = [\n        {name: 'name'},\n        {name: 'title'}\n      ];\n    }]);\n   </file>\n   <file name=\"index.html\">\n   <div ng-controller=\"MainCtrl\">\n   <div ui-grid=\"{ data: data, columnDefs: columnDefs }\" ui-grid-cellnav></div>\n   </div>\n   </file>\n   </example>\n   */\n  module.directive('uiGridCellnav', ['gridUtil', 'uiGridCellNavService', 'uiGridCellNavConstants', 'uiGridConstants', 'GridRowColumn', '$timeout', '$compile',\n    function (gridUtil, uiGridCellNavService, uiGridCellNavConstants, uiGridConstants, GridRowColumn, $timeout, $compile) {\n      return {\n        replace: true,\n        priority: -150,\n        require: '^uiGrid',\n        scope: false,\n        controller: function () {},\n        compile: function () {\n          return {\n            pre: function ($scope, $elm, $attrs, uiGridCtrl) {\n              var _scope = $scope;\n\n              var grid = uiGridCtrl.grid;\n              uiGridCellNavService.initializeGrid(grid);\n\n              uiGridCtrl.cellNav = {};\n\n              //Ensure that the object has all of the methods we expect it to\n              uiGridCtrl.cellNav.makeRowCol = function (obj) {\n                if (!(obj instanceof GridRowColumn)) {\n                  obj = new GridRowColumn(obj.row, obj.col);\n                }\n                return obj;\n              };\n\n              uiGridCtrl.cellNav.getActiveCell = function () {\n                var elms = $elm[0].getElementsByClassName('ui-grid-cell-focus');\n                if (elms.length > 0){\n                  return elms[0];\n                }\n\n                return undefined;\n              };\n\n              uiGridCtrl.cellNav.broadcastCellNav = grid.cellNav.broadcastCellNav = function (newRowCol, modifierDown, originEvt) {\n                modifierDown = !(modifierDown === undefined || !modifierDown);\n\n                newRowCol = uiGridCtrl.cellNav.makeRowCol(newRowCol);\n\n                uiGridCtrl.cellNav.broadcastFocus(newRowCol, modifierDown, originEvt);\n                _scope.$broadcast(uiGridCellNavConstants.CELL_NAV_EVENT, newRowCol, modifierDown, originEvt);\n              };\n\n              uiGridCtrl.cellNav.clearFocus = grid.cellNav.clearFocus = function () {\n                grid.cellNav.focusedCells = [];\n                _scope.$broadcast(uiGridCellNavConstants.CELL_NAV_EVENT);\n              };\n\n              uiGridCtrl.cellNav.broadcastFocus = function (rowCol, modifierDown, originEvt) {\n                modifierDown = !(modifierDown === undefined || !modifierDown);\n\n                rowCol = uiGridCtrl.cellNav.makeRowCol(rowCol);\n\n                var row = rowCol.row,\n                  col = rowCol.col;\n\n                var rowColSelectIndex = uiGridCtrl.grid.api.cellNav.rowColSelectIndex(rowCol);\n\n                if (grid.cellNav.lastRowCol === null || rowColSelectIndex === -1) {\n                  var newRowCol = new GridRowColumn(row, col);\n\n                  if (grid.cellNav.lastRowCol === null || grid.cellNav.lastRowCol.row !== newRowCol.row || grid.cellNav.lastRowCol.col !== newRowCol.col){\n                    grid.api.cellNav.raise.navigate(newRowCol, grid.cellNav.lastRowCol);\n                    grid.cellNav.lastRowCol = newRowCol;  \n                  }\n                  if (uiGridCtrl.grid.options.modifierKeysToMultiSelectCells && modifierDown) {\n                    grid.cellNav.focusedCells.push(rowCol);\n                  } else {\n                    grid.cellNav.focusedCells = [rowCol];\n                  }\n                } else if (grid.options.modifierKeysToMultiSelectCells && modifierDown &&\n                  rowColSelectIndex >= 0) {\n\n                  grid.cellNav.focusedCells.splice(rowColSelectIndex, 1);\n                }\n              };\n\n              uiGridCtrl.cellNav.handleKeyDown = function (evt) {\n                var direction = uiGridCellNavService.getDirection(evt);\n                if (direction === null) {\n                  return null;\n                }\n\n                var containerId = 'body';\n                if (evt.uiGridTargetRenderContainerId) {\n                  containerId = evt.uiGridTargetRenderContainerId;\n                }\n\n                // Get the last-focused row+col combo\n                var lastRowCol = uiGridCtrl.grid.api.cellNav.getFocusedCell();\n                if (lastRowCol) {\n                  // Figure out which new row+combo we're navigating to\n                  var rowCol = uiGridCtrl.grid.renderContainers[containerId].cellNav.getNextRowCol(direction, lastRowCol.row, lastRowCol.col);\n                  var focusableCols = uiGridCtrl.grid.renderContainers[containerId].cellNav.getFocusableCols();\n                  var rowColSelectIndex = uiGridCtrl.grid.api.cellNav.rowColSelectIndex(rowCol);\n                  // Shift+tab on top-left cell should exit cellnav on render container\n                  if (\n                    // Navigating left\n                    direction === uiGridCellNavConstants.direction.LEFT &&\n                    // New col is last col (i.e. wrap around)\n                    rowCol.col === focusableCols[focusableCols.length - 1] &&\n                    // Staying on same row, which means we're at first row\n                    rowCol.row === lastRowCol.row &&\n                    evt.keyCode === uiGridConstants.keymap.TAB &&\n                    evt.shiftKey\n                  ) {\n                    grid.cellNav.focusedCells.splice(rowColSelectIndex, 1);\n                    uiGridCtrl.cellNav.clearFocus();\n                    return true;\n                  }\n                  // Tab on bottom-right cell should exit cellnav on render container\n                  else if (\n                    direction === uiGridCellNavConstants.direction.RIGHT &&\n                    // New col is first col (i.e. wrap around)\n                    rowCol.col === focusableCols[0] &&\n                    // Staying on same row, which means we're at first row\n                    rowCol.row === lastRowCol.row &&\n                    evt.keyCode === uiGridConstants.keymap.TAB &&\n                    !evt.shiftKey\n                  ) {\n                    grid.cellNav.focusedCells.splice(rowColSelectIndex, 1);\n                    uiGridCtrl.cellNav.clearFocus();\n                    return true;\n                  }\n\n                  // Scroll to the new cell, if it's not completely visible within the render container's viewport\n                  grid.scrollToIfNecessary(rowCol.row, rowCol.col).then(function () {\n                    uiGridCtrl.cellNav.broadcastCellNav(rowCol);\n                  });\n\n\n                  evt.stopPropagation();\n                  evt.preventDefault();\n\n                  return false;\n                }\n              };\n            },\n            post: function ($scope, $elm, $attrs, uiGridCtrl) {\n              var _scope = $scope;\n              var grid = uiGridCtrl.grid;\n\n              function addAriaLiveRegion(){\n                // Thanks to google docs for the inspiration behind how to do this\n                // XXX: Why is this entire mess nessasary?\n                // Because browsers take a lot of coercing to get them to read out live regions\n                //http://www.paciellogroup.com/blog/2012/06/html5-accessibility-chops-aria-rolealert-browser-support/\n                var ariaNotifierDomElt = '<div ' +\n                                           'id=\"' + grid.id +'-aria-speakable\" ' +\n                                           'class=\"ui-grid-a11y-ariascreenreader-speakable ui-grid-offscreen\" ' +\n                                           'aria-live=\"assertive\" ' +\n                                           'role=\"region\" ' +\n                                           'aria-atomic=\"true\" ' +\n                                           'aria-hidden=\"false\" ' +\n                                           'aria-relevant=\"additions\" ' +\n                                           '>' +\n                                           '&nbsp;' +\n                                         '</div>';\n\n                var ariaNotifier = $compile(ariaNotifierDomElt)($scope);\n                $elm.prepend(ariaNotifier);\n                $scope.$on(uiGridCellNavConstants.CELL_NAV_EVENT, function (evt, rowCol, modifierDown, originEvt) {\n                  /*\n                   * If the cell nav event was because of a focus event then we don't want to\n                   * change the notifier text.\n                   * Reasoning: Voice Over fires a focus events when moving arround the grid.\n                   * If the screen reader is handing the grid nav properly then we don't need to\n                   * use the alert to notify the user of the movement.\n                   * In all other cases we do want a notification event.\n                   */\n                  if (originEvt && originEvt.type === 'focus'){return;}\n\n                  function setNotifyText(text){\n                    if (text === ariaNotifier.text()){return;}\n                    ariaNotifier[0].style.clip = 'rect(0px,0px,0px,0px)';\n                    /*\n                     * This is how google docs handles clearing the div. Seems to work better than setting the text of the div to ''\n                     */\n                    ariaNotifier[0].innerHTML = \"\";\n                    ariaNotifier[0].style.visibility = 'hidden';\n                    ariaNotifier[0].style.visibility = 'visible';\n                    if (text !== ''){\n                      ariaNotifier[0].style.clip = 'auto';\n                      /*\n                       * The space after the text is something that google docs does.\n                       */\n                      ariaNotifier[0].appendChild(document.createTextNode(text + \" \"));\n                      ariaNotifier[0].style.visibility = 'hidden';\n                      ariaNotifier[0].style.visibility = 'visible';\n                    }\n                  }\n\n                  var values = [];\n                  var currentSelection = grid.api.cellNav.getCurrentSelection();\n                  for (var i = 0; i < currentSelection.length; i++) {\n                    values.push(grid.getCellDisplayValue(currentSelection[i].row, currentSelection[i].col));\n                  }\n                  var cellText = values.toString();\n                  setNotifyText(cellText);\n\n                });\n              }\n              addAriaLiveRegion();\n            }\n          };\n        }\n      };\n    }]);\n\n  module.directive('uiGridRenderContainer', ['$timeout', '$document', 'gridUtil', 'uiGridConstants', 'uiGridCellNavService', '$compile','uiGridCellNavConstants',\n    function ($timeout, $document, gridUtil, uiGridConstants, uiGridCellNavService, $compile, uiGridCellNavConstants) {\n      return {\n        replace: true,\n        priority: -99999, //this needs to run very last\n        require: ['^uiGrid', 'uiGridRenderContainer', '?^uiGridCellnav'],\n        scope: false,\n        compile: function () {\n          return {\n            post: function ($scope, $elm, $attrs, controllers) {\n              var uiGridCtrl = controllers[0],\n                 renderContainerCtrl = controllers[1],\n                 uiGridCellnavCtrl = controllers[2];\n\n              // Skip attaching cell-nav specific logic if the directive is not attached above us\n              if (!uiGridCtrl.grid.api.cellNav) { return; }\n\n              var containerId = renderContainerCtrl.containerId;\n\n              var grid = uiGridCtrl.grid;\n\n              //run each time a render container is created\n              uiGridCellNavService.decorateRenderContainers(grid);\n\n              // focusser only created for body\n              if (containerId !== 'body') {\n                return;\n              }\n\n\n\n              if (uiGridCtrl.grid.options.modifierKeysToMultiSelectCells){\n                $elm.attr('aria-multiselectable', true);\n              } else {\n                $elm.attr('aria-multiselectable', false);\n              }\n\n              //add an element with no dimensions that can be used to set focus and capture keystrokes\n              var focuser = $compile('<div class=\"ui-grid-focuser\" role=\"region\" aria-live=\"assertive\" aria-atomic=\"false\" tabindex=\"0\" aria-controls=\"' + grid.id +'-aria-speakable '+ grid.id + '-grid-container' +'\" aria-owns=\"' + grid.id + '-grid-container' + '\"></div>')($scope);\n              $elm.append(focuser);\n\n              focuser.on('focus', function (evt) {\n                evt.uiGridTargetRenderContainerId = containerId;\n                var rowCol = uiGridCtrl.grid.api.cellNav.getFocusedCell();\n                if (rowCol === null) {\n                  rowCol = uiGridCtrl.grid.renderContainers[containerId].cellNav.getNextRowCol(uiGridCellNavConstants.direction.DOWN, null, null);\n                  if (rowCol.row && rowCol.col) {\n                    uiGridCtrl.cellNav.broadcastCellNav(rowCol);\n                  }\n                }\n              });\n\n              uiGridCellnavCtrl.setAriaActivedescendant = function(id){\n                $elm.attr('aria-activedescendant', id);\n              };\n\n              uiGridCellnavCtrl.removeAriaActivedescendant = function(id){\n                if ($elm.attr('aria-activedescendant') === id){\n                  $elm.attr('aria-activedescendant', '');\n                }\n              };\n\n\n              uiGridCtrl.focus = function () {\n                gridUtil.focus.byElement(focuser[0]);\n                //allow for first time grid focus\n              };\n\n              var viewPortKeyDownWasRaisedForRowCol = null;\n              // Bind to keydown events in the render container\n              focuser.on('keydown', function (evt) {\n                evt.uiGridTargetRenderContainerId = containerId;\n                var rowCol = uiGridCtrl.grid.api.cellNav.getFocusedCell();\n                var result = uiGridCtrl.cellNav.handleKeyDown(evt);\n                if (result === null) {\n                  uiGridCtrl.grid.api.cellNav.raise.viewPortKeyDown(evt, rowCol);\n                  viewPortKeyDownWasRaisedForRowCol = rowCol;\n                }\n              });\n              //Bind to keypress events in the render container\n              //keypress events are needed by edit function so the key press\n              //that initiated an edit is not lost\n              //must fire the event in a timeout so the editor can\n              //initialize and subscribe to the event on another event loop\n              focuser.on('keypress', function (evt) {\n                if (viewPortKeyDownWasRaisedForRowCol) {\n                  $timeout(function () {\n                    uiGridCtrl.grid.api.cellNav.raise.viewPortKeyPress(evt, viewPortKeyDownWasRaisedForRowCol);\n                  },4);\n\n                  viewPortKeyDownWasRaisedForRowCol = null;\n                }\n              });\n\n              $scope.$on('$destroy', function(){\n                //Remove all event handlers associated with this focuser.\n                focuser.off();\n              });\n\n            }\n          };\n        }\n      };\n    }]);\n\n  module.directive('uiGridViewport', ['$timeout', '$document', 'gridUtil', 'uiGridConstants', 'uiGridCellNavService', 'uiGridCellNavConstants','$log','$compile',\n    function ($timeout, $document, gridUtil, uiGridConstants, uiGridCellNavService, uiGridCellNavConstants, $log, $compile) {\n      return {\n        replace: true,\n        priority: -99999, //this needs to run very last\n        require: ['^uiGrid', '^uiGridRenderContainer', '?^uiGridCellnav'],\n        scope: false,\n        compile: function () {\n          return {\n            pre: function ($scope, $elm, $attrs, uiGridCtrl) {\n            },\n            post: function ($scope, $elm, $attrs, controllers) {\n              var uiGridCtrl = controllers[0],\n                renderContainerCtrl = controllers[1];\n\n              // Skip attaching cell-nav specific logic if the directive is not attached above us\n              if (!uiGridCtrl.grid.api.cellNav) { return; }\n\n              var containerId = renderContainerCtrl.containerId;\n              //no need to process for other containers\n              if (containerId !== 'body') {\n                return;\n              }\n\n              var grid = uiGridCtrl.grid;\n\n              grid.api.core.on.scrollBegin($scope, function (args) {\n\n                // Skip if there's no currently-focused cell\n                var lastRowCol = uiGridCtrl.grid.api.cellNav.getFocusedCell();\n                if (lastRowCol === null) {\n                  return;\n                }\n\n                //if not in my container, move on\n                //todo: worry about horiz scroll\n                if (!renderContainerCtrl.colContainer.containsColumn(lastRowCol.col)) {\n                  return;\n                }\n\n                uiGridCtrl.cellNav.clearFocus();\n\n              });\n\n              grid.api.core.on.scrollEnd($scope, function (args) {\n                // Skip if there's no currently-focused cell\n                var lastRowCol = uiGridCtrl.grid.api.cellNav.getFocusedCell();\n                if (lastRowCol === null) {\n                  return;\n                }\n\n                //if not in my container, move on\n                //todo: worry about horiz scroll\n                if (!renderContainerCtrl.colContainer.containsColumn(lastRowCol.col)) {\n                  return;\n                }\n\n                uiGridCtrl.cellNav.broadcastCellNav(lastRowCol);\n\n              });\n\n              grid.api.cellNav.on.navigate($scope, function () {\n                //focus again because it can be lost\n                 uiGridCtrl.focus();\n              });\n\n            }\n          };\n        }\n      };\n    }]);\n\n  /**\n   *  @ngdoc directive\n   *  @name ui.grid.cellNav.directive:uiGridCell\n   *  @element div\n   *  @restrict A\n   *  @description Stacks on top of ui.grid.uiGridCell to provide cell navigation\n   */\n  module.directive('uiGridCell', ['$timeout', '$document', 'uiGridCellNavService', 'gridUtil', 'uiGridCellNavConstants', 'uiGridConstants', 'GridRowColumn',\n    function ($timeout, $document, uiGridCellNavService, gridUtil, uiGridCellNavConstants, uiGridConstants, GridRowColumn) {\n      return {\n        priority: -150, // run after default uiGridCell directive and ui.grid.edit uiGridCell\n        restrict: 'A',\n        require: ['^uiGrid', '?^uiGridCellnav'],\n        scope: false,\n        link: function ($scope, $elm, $attrs, controllers) {\n          var uiGridCtrl = controllers[0],\n              uiGridCellnavCtrl = controllers[1];\n          // Skip attaching cell-nav specific logic if the directive is not attached above us\n          if (!uiGridCtrl.grid.api.cellNav) { return; }\n\n          if (!$scope.col.colDef.allowCellFocus) {\n            return;\n          }\n\n          //Convinience local variables\n          var grid = uiGridCtrl.grid;\n          $scope.focused = false;\n\n          // Make this cell focusable but only with javascript/a mouse click\n          $elm.attr('tabindex', -1);\n\n          // When a cell is clicked, broadcast a cellNav event saying that this row+col combo is now focused\n          $elm.find('div').on('click', function (evt) {\n            uiGridCtrl.cellNav.broadcastCellNav(new GridRowColumn($scope.row, $scope.col), evt.ctrlKey || evt.metaKey, evt);\n\n            evt.stopPropagation();\n            $scope.$apply();\n          });\n\n\n          /*\n           * XXX Hack for screen readers.\n           * This allows the grid to focus using only the screen reader cursor.\n           * Since the focus event doesn't include key press information we can't use it\n           * as our primary source of the event.\n           */\n          $elm.on('mousedown', preventMouseDown);\n\n          //turn on and off for edit events\n          if (uiGridCtrl.grid.api.edit) {\n            uiGridCtrl.grid.api.edit.on.beginCellEdit($scope, function () {\n              $elm.off('mousedown', preventMouseDown);\n            });\n\n            uiGridCtrl.grid.api.edit.on.afterCellEdit($scope, function () {\n              $elm.on('mousedown', preventMouseDown);\n            });\n\n            uiGridCtrl.grid.api.edit.on.cancelCellEdit($scope, function () {\n              $elm.on('mousedown', preventMouseDown);\n            });\n          }\n\n          function preventMouseDown(evt) {\n            //Prevents the foucus event from firing if the click event is already going to fire.\n            //If both events fire it will cause bouncing behavior.\n            evt.preventDefault();\n          }\n\n          //You can only focus on elements with a tabindex value\n          $elm.on('focus', function (evt) {\n            uiGridCtrl.cellNav.broadcastCellNav(new GridRowColumn($scope.row, $scope.col), false, evt);\n            evt.stopPropagation();\n            $scope.$apply();\n          });\n\n          // This event is fired for all cells.  If the cell matches, then focus is set\n          $scope.$on(uiGridCellNavConstants.CELL_NAV_EVENT, function (evt, rowCol, modifierDown) {\n            var isFocused = grid.cellNav.focusedCells.some(function(focusedRowCol, index){\n              return (focusedRowCol.row === $scope.row && focusedRowCol.col === $scope.col);\n            });\n            if (isFocused){\n              setFocused();\n            } else {\n              clearFocus();\n            }\n          });\n\n          function setFocused() {\n            if (!$scope.focused){\n              var div = $elm.find('div');\n              div.addClass('ui-grid-cell-focus');\n              $elm.attr('aria-selected', true);\n              uiGridCellnavCtrl.setAriaActivedescendant($elm.attr('id'));\n              $scope.focused = true;\n            }\n          }\n\n          function clearFocus() {\n            if ($scope.focused){\n              var div = $elm.find('div');\n              div.removeClass('ui-grid-cell-focus');\n              $elm.attr('aria-selected', false);\n              uiGridCellnavCtrl.removeAriaActivedescendant($elm.attr('id'));\n              $scope.focused = false;\n            }\n          }\n\n          $scope.$on('$destroy', function () {\n            //.off withouth paramaters removes all handlers\n            $elm.find('div').off();\n            $elm.off();\n          });\n        }\n      };\n    }]);\n\n})();\n\n(function () {\n  'use strict';\n\n  /**\n   * @ngdoc overview\n   * @name ui.grid.edit\n   * @description\n   *\n   * # ui.grid.edit\n   *\n   * <div class=\"alert alert-success\" role=\"alert\"><strong>Stable</strong> This feature is stable. There should no longer be breaking api changes without a deprecation warning.</div>\n   *\n   * This module provides cell editing capability to ui.grid. The goal was to emulate keying data in a spreadsheet via\n   * a keyboard.\n   * <br/>\n   * <br/>\n   * To really get the full spreadsheet-like data entry, the ui.grid.cellNav module should be used. This will allow the\n   * user to key data and then tab, arrow, or enter to the cells beside or below.\n   *\n   * <div doc-module-components=\"ui.grid.edit\"></div>\n   */\n\n  var module = angular.module('ui.grid.edit', ['ui.grid']);\n\n  /**\n   *  @ngdoc object\n   *  @name ui.grid.edit.constant:uiGridEditConstants\n   *\n   *  @description constants available in edit module\n   */\n  module.constant('uiGridEditConstants', {\n    EDITABLE_CELL_TEMPLATE: /EDITABLE_CELL_TEMPLATE/g,\n    //must be lowercase because template bulder converts to lower\n    EDITABLE_CELL_DIRECTIVE: /editable_cell_directive/g,\n    events: {\n      BEGIN_CELL_EDIT: 'uiGridEventBeginCellEdit',\n      END_CELL_EDIT: 'uiGridEventEndCellEdit',\n      CANCEL_CELL_EDIT: 'uiGridEventCancelCellEdit'\n    }\n  });\n\n  /**\n   *  @ngdoc service\n   *  @name ui.grid.edit.service:uiGridEditService\n   *\n   *  @description Services for editing features\n   */\n  module.service('uiGridEditService', ['$q', 'uiGridConstants', 'gridUtil',\n    function ($q, uiGridConstants, gridUtil) {\n\n      var service = {\n\n        initializeGrid: function (grid) {\n\n          service.defaultGridOptions(grid.options);\n\n          grid.registerColumnBuilder(service.editColumnBuilder);\n          grid.edit = {};\n\n          /**\n           *  @ngdoc object\n           *  @name ui.grid.edit.api:PublicApi\n           *\n           *  @description Public Api for edit feature\n           */\n          var publicApi = {\n            events: {\n              edit: {\n                /**\n                 * @ngdoc event\n                 * @name afterCellEdit\n                 * @eventOf  ui.grid.edit.api:PublicApi\n                 * @description raised when cell editing is complete\n                 * <pre>\n                 *      gridApi.edit.on.afterCellEdit(scope,function(rowEntity, colDef){})\n                 * </pre>\n                 * @param {object} rowEntity the options.data element that was edited\n                 * @param {object} colDef the column that was edited\n                 * @param {object} newValue new value\n                 * @param {object} oldValue old value\n                 */\n                afterCellEdit: function (rowEntity, colDef, newValue, oldValue) {\n                },\n                /**\n                 * @ngdoc event\n                 * @name beginCellEdit\n                 * @eventOf  ui.grid.edit.api:PublicApi\n                 * @description raised when cell editing starts on a cell\n                 * <pre>\n                 *      gridApi.edit.on.beginCellEdit(scope,function(rowEntity, colDef){})\n                 * </pre>\n                 * @param {object} rowEntity the options.data element that was edited\n                 * @param {object} colDef the column that was edited\n                 * @param {object} triggerEvent the event that triggered the edit.  Useful to prevent losing keystrokes on some\n                 *                 complex editors\n                 */\n                beginCellEdit: function (rowEntity, colDef, triggerEvent) {\n                },\n                /**\n                 * @ngdoc event\n                 * @name cancelCellEdit\n                 * @eventOf  ui.grid.edit.api:PublicApi\n                 * @description raised when cell editing is cancelled on a cell\n                 * <pre>\n                 *      gridApi.edit.on.cancelCellEdit(scope,function(rowEntity, colDef){})\n                 * </pre>\n                 * @param {object} rowEntity the options.data element that was edited\n                 * @param {object} colDef the column that was edited\n                 */\n                cancelCellEdit: function (rowEntity, colDef) {\n                }\n              }\n            },\n            methods: {\n              edit: { }\n            }\n          };\n\n          grid.api.registerEventsFromObject(publicApi.events);\n          //grid.api.registerMethodsFromObject(publicApi.methods);\n\n        },\n\n        defaultGridOptions: function (gridOptions) {\n\n          /**\n           *  @ngdoc object\n           *  @name ui.grid.edit.api:GridOptions\n           *\n           *  @description Options for configuring the edit feature, these are available to be\n           *  set using the ui-grid {@link ui.grid.class:GridOptions gridOptions}\n           */\n\n          /**\n           *  @ngdoc object\n           *  @name enableCellEdit\n           *  @propertyOf  ui.grid.edit.api:GridOptions\n           *  @description If defined, sets the default value for the editable flag on each individual colDefs\n           *  if their individual enableCellEdit configuration is not defined. Defaults to undefined.\n           */\n\n          /**\n           *  @ngdoc object\n           *  @name cellEditableCondition\n           *  @propertyOf  ui.grid.edit.api:GridOptions\n           *  @description If specified, either a value or function to be used by all columns before editing.\n           *  If falsy, then editing of cell is not allowed.\n           *  @example\n           *  <pre>\n           *  function($scope){\n           *    //use $scope.row.entity and $scope.col.colDef to determine if editing is allowed\n           *    return true;\n           *  }\n           *  </pre>\n           */\n          gridOptions.cellEditableCondition = gridOptions.cellEditableCondition === undefined ? true : gridOptions.cellEditableCondition;\n\n          /**\n           *  @ngdoc object\n           *  @name editableCellTemplate\n           *  @propertyOf  ui.grid.edit.api:GridOptions\n           *  @description If specified, cellTemplate to use as the editor for all columns.\n           *  <br/> defaults to 'ui-grid/cellTextEditor'\n           */\n\n          /**\n           *  @ngdoc object\n           *  @name enableCellEditOnFocus\n           *  @propertyOf  ui.grid.edit.api:GridOptions\n           *  @description If true, then editor is invoked as soon as cell receives focus. Default false.\n           *  <br/>_requires cellNav feature and the edit feature to be enabled_\n           */\n            //enableCellEditOnFocus can only be used if cellnav module is used\n          gridOptions.enableCellEditOnFocus = gridOptions.enableCellEditOnFocus === undefined ? false : gridOptions.enableCellEditOnFocus;\n        },\n\n        /**\n         * @ngdoc service\n         * @name editColumnBuilder\n         * @methodOf ui.grid.edit.service:uiGridEditService\n         * @description columnBuilder function that adds edit properties to grid column\n         * @returns {promise} promise that will load any needed templates when resolved\n         */\n        editColumnBuilder: function (colDef, col, gridOptions) {\n\n          var promises = [];\n\n          /**\n           *  @ngdoc object\n           *  @name ui.grid.edit.api:ColumnDef\n           *\n           *  @description Column Definition for edit feature, these are available to be\n           *  set using the ui-grid {@link ui.grid.class:GridOptions.columnDef gridOptions.columnDefs}\n           */\n\n          /**\n           *  @ngdoc object\n           *  @name enableCellEdit\n           *  @propertyOf  ui.grid.edit.api:ColumnDef\n           *  @description enable editing on column\n           */\n          colDef.enableCellEdit = colDef.enableCellEdit === undefined ? (gridOptions.enableCellEdit === undefined ?\n            (colDef.type !== 'object') : gridOptions.enableCellEdit) : colDef.enableCellEdit;\n\n          /**\n           *  @ngdoc object\n           *  @name cellEditableCondition\n           *  @propertyOf  ui.grid.edit.api:ColumnDef\n           *  @description If specified, either a value or function evaluated before editing cell.  If falsy, then editing of cell is not allowed.\n           *  @example\n           *  <pre>\n           *  function($scope){\n           *    //use $scope.row.entity and $scope.col.colDef to determine if editing is allowed\n           *    return true;\n           *  }\n           *  </pre>\n           */\n          colDef.cellEditableCondition = colDef.cellEditableCondition === undefined ? gridOptions.cellEditableCondition :  colDef.cellEditableCondition;\n\n          /**\n           *  @ngdoc object\n           *  @name editableCellTemplate\n           *  @propertyOf  ui.grid.edit.api:ColumnDef\n           *  @description cell template to be used when editing this column. Can be Url or text template\n           *  <br/>Defaults to gridOptions.editableCellTemplate\n           */\n          if (colDef.enableCellEdit) {\n            colDef.editableCellTemplate = colDef.editableCellTemplate || gridOptions.editableCellTemplate || 'ui-grid/cellEditor';\n\n            promises.push(gridUtil.getTemplate(colDef.editableCellTemplate)\n              .then(\n              function (template) {\n                col.editableCellTemplate = template;\n              },\n              function (res) {\n                // Todo handle response error here?\n                throw new Error(\"Couldn't fetch/use colDef.editableCellTemplate '\" + colDef.editableCellTemplate + \"'\");\n              }));\n          }\n\n          /**\n           *  @ngdoc object\n           *  @name enableCellEditOnFocus\n           *  @propertyOf  ui.grid.edit.api:ColumnDef\n           *  @requires ui.grid.cellNav\n           *  @description If true, then editor is invoked as soon as cell receives focus. Default false.\n           *  <br>_requires both the cellNav feature and the edit feature to be enabled_\n           */\n            //enableCellEditOnFocus can only be used if cellnav module is used\n          colDef.enableCellEditOnFocus = colDef.enableCellEditOnFocus === undefined ? gridOptions.enableCellEditOnFocus : colDef.enableCellEditOnFocus;\n\n\n          /**\n           *  @ngdoc string\n           *  @name editModelField\n           *  @propertyOf  ui.grid.edit.api:ColumnDef\n           *  @description a bindable string value that is used when binding to edit controls instead of colDef.field\n           *  <br/> example: You have a complex property on and object like state:{abbrev:'MS',name:'Mississippi'}.  The\n           *  grid should display state.name in the cell and sort/filter based on the state.name property but the editor\n           *  requires the full state object.\n           *  <br/>colDef.field = 'state.name'\n           *  <br/>colDef.editModelField = 'state'\n           */\n          //colDef.editModelField\n\n          return $q.all(promises);\n        },\n\n        /**\n         * @ngdoc service\n         * @name isStartEditKey\n         * @methodOf ui.grid.edit.service:uiGridEditService\n         * @description  Determines if a keypress should start editing.  Decorate this service to override with your\n         * own key events.  See service decorator in angular docs.\n         * @param {Event} evt keydown event\n         * @returns {boolean} true if an edit should start\n         */\n        isStartEditKey: function (evt) {\n          if (evt.metaKey ||\n              evt.keyCode === uiGridConstants.keymap.ESC ||\n              evt.keyCode === uiGridConstants.keymap.SHIFT ||\n              evt.keyCode === uiGridConstants.keymap.CTRL ||\n              evt.keyCode === uiGridConstants.keymap.ALT ||\n              evt.keyCode === uiGridConstants.keymap.WIN ||\n              evt.keyCode === uiGridConstants.keymap.CAPSLOCK ||\n\n             evt.keyCode === uiGridConstants.keymap.LEFT ||\n            (evt.keyCode === uiGridConstants.keymap.TAB && evt.shiftKey) ||\n\n            evt.keyCode === uiGridConstants.keymap.RIGHT ||\n            evt.keyCode === uiGridConstants.keymap.TAB ||\n\n            evt.keyCode === uiGridConstants.keymap.UP ||\n            (evt.keyCode === uiGridConstants.keymap.ENTER && evt.shiftKey) ||\n\n            evt.keyCode === uiGridConstants.keymap.DOWN ||\n            evt.keyCode === uiGridConstants.keymap.ENTER) {\n            return false;\n\n          }\n          return true;\n        }\n\n\n      };\n\n      return service;\n\n    }]);\n\n  /**\n   *  @ngdoc directive\n   *  @name ui.grid.edit.directive:uiGridEdit\n   *  @element div\n   *  @restrict A\n   *\n   *  @description Adds editing features to the ui-grid directive.\n   *\n   *  @example\n   <example module=\"app\">\n   <file name=\"app.js\">\n   var app = angular.module('app', ['ui.grid', 'ui.grid.edit']);\n\n   app.controller('MainCtrl', ['$scope', function ($scope) {\n      $scope.data = [\n        { name: 'Bob', title: 'CEO' },\n            { name: 'Frank', title: 'Lowly Developer' }\n      ];\n\n      $scope.columnDefs = [\n        {name: 'name', enableCellEdit: true},\n        {name: 'title', enableCellEdit: true}\n      ];\n    }]);\n   </file>\n   <file name=\"index.html\">\n   <div ng-controller=\"MainCtrl\">\n   <div ui-grid=\"{ data: data, columnDefs: columnDefs }\" ui-grid-edit></div>\n   </div>\n   </file>\n   </example>\n   */\n  module.directive('uiGridEdit', ['gridUtil', 'uiGridEditService', function (gridUtil, uiGridEditService) {\n    return {\n      replace: true,\n      priority: 0,\n      require: '^uiGrid',\n      scope: false,\n      compile: function () {\n        return {\n          pre: function ($scope, $elm, $attrs, uiGridCtrl) {\n            uiGridEditService.initializeGrid(uiGridCtrl.grid);\n          },\n          post: function ($scope, $elm, $attrs, uiGridCtrl) {\n          }\n        };\n      }\n    };\n  }]);\n\n  /**\n   *  @ngdoc directive\n   *  @name ui.grid.edit.directive:uiGridRenderContainer\n   *  @element div\n   *  @restrict A\n   *\n   *  @description Adds keydown listeners to renderContainer element so we can capture when to begin edits\n   *\n   */\n  module.directive('uiGridViewport', [ 'uiGridEditConstants',\n    function ( uiGridEditConstants) {\n      return {\n        replace: true,\n        priority: -99998, //run before cellNav\n        require: ['^uiGrid', '^uiGridRenderContainer'],\n        scope: false,\n        compile: function () {\n          return {\n            post: function ($scope, $elm, $attrs, controllers) {\n              var uiGridCtrl = controllers[0];\n\n              // Skip attaching if edit and cellNav is not enabled\n              if (!uiGridCtrl.grid.api.edit || !uiGridCtrl.grid.api.cellNav) { return; }\n\n              var containerId =  controllers[1].containerId;\n              //no need to process for other containers\n              if (containerId !== 'body') {\n                return;\n              }\n\n              //refocus on the grid\n              $scope.$on(uiGridEditConstants.events.CANCEL_CELL_EDIT, function () {\n                uiGridCtrl.focus();\n              });\n              $scope.$on(uiGridEditConstants.events.END_CELL_EDIT, function () {\n                uiGridCtrl.focus();\n              });\n\n            }\n          };\n        }\n      };\n    }]);\n\n  /**\n   *  @ngdoc directive\n   *  @name ui.grid.edit.directive:uiGridCell\n   *  @element div\n   *  @restrict A\n   *\n   *  @description Stacks on top of ui.grid.uiGridCell to provide in-line editing capabilities to the cell\n   *  Editing Actions.\n   *\n   *  Binds edit start events to the uiGridCell element.  When the events fire, the gridCell element is appended\n   *  with the columnDef.editableCellTemplate element ('cellEditor.html' by default).\n   *\n   *  The editableCellTemplate should respond to uiGridEditConstants.events.BEGIN\\_CELL\\_EDIT angular event\n   *  and do the initial steps needed to edit the cell (setfocus on input element, etc).\n   *\n   *  When the editableCellTemplate recognizes that the editing is ended (blur event, Enter key, etc.)\n   *  it should emit the uiGridEditConstants.events.END\\_CELL\\_EDIT event.\n   *\n   *  If editableCellTemplate recognizes that the editing has been cancelled (esc key)\n   *  it should emit the uiGridEditConstants.events.CANCEL\\_CELL\\_EDIT event.  The original value\n   *  will be set back on the model by the uiGridCell directive.\n   *\n   *  Events that invoke editing:\n   *    - dblclick\n   *    - F2 keydown (when using cell selection)\n   *\n   *  Events that end editing:\n   *    - Dependent on the specific editableCellTemplate\n   *    - Standards should be blur and enter keydown\n   *\n   *  Events that cancel editing:\n   *    - Dependent on the specific editableCellTemplate\n   *    - Standards should be Esc keydown\n   *\n   *  Grid Events that end editing:\n   *    - uiGridConstants.events.GRID_SCROLL\n   *\n   */\n\n  /**\n   *  @ngdoc object\n   *  @name ui.grid.edit.api:GridRow\n   *\n   *  @description GridRow options for edit feature, these are available to be\n   *  set internally only, by other features\n   */\n\n  /**\n   *  @ngdoc object\n   *  @name enableCellEdit\n   *  @propertyOf  ui.grid.edit.api:GridRow\n   *  @description enable editing on row, grouping for example might disable editing on group header rows\n   */\n\n  module.directive('uiGridCell',\n    ['$compile', '$injector', '$timeout', 'uiGridConstants', 'uiGridEditConstants', 'gridUtil', '$parse', 'uiGridEditService', '$rootScope', '$q',\n      function ($compile, $injector, $timeout, uiGridConstants, uiGridEditConstants, gridUtil, $parse, uiGridEditService, $rootScope, $q) {\n        var touchstartTimeout = 500;\n        if ($injector.has('uiGridCellNavService')) {\n          var uiGridCellNavService = $injector.get('uiGridCellNavService');\n        }\n\n        return {\n          priority: -100, // run after default uiGridCell directive\n          restrict: 'A',\n          scope: false,\n          require: '?^uiGrid',\n          link: function ($scope, $elm, $attrs, uiGridCtrl) {\n            var html;\n            var origCellValue;\n            var inEdit = false;\n            var cellModel;\n            var cancelTouchstartTimeout;\n\n            var editCellScope;\n\n            if (!$scope.col.colDef.enableCellEdit) {\n              return;\n            }\n\n            var cellNavNavigateDereg = function() {};\n            var viewPortKeyDownDereg = function() {};\n\n\n            var setEditable = function() {\n              if ($scope.col.colDef.enableCellEdit && $scope.row.enableCellEdit !== false) {\n                if (!$scope.beginEditEventsWired) { //prevent multiple attachments\n                  registerBeginEditEvents();\n                }\n              } else {\n                if ($scope.beginEditEventsWired) {\n                  cancelBeginEditEvents();\n                }\n              }\n            };\n\n            setEditable();\n\n            var rowWatchDereg = $scope.$watch('row', function (n, o) {\n              if (n !== o) {\n                setEditable();\n              }\n            });\n\n\n            $scope.$on( '$destroy', rowWatchDereg );\n\n            function registerBeginEditEvents() {\n              $elm.on('dblclick', beginEdit);\n\n              // Add touchstart handling. If the users starts a touch and it doesn't end after X milliseconds, then start the edit\n              $elm.on('touchstart', touchStart);\n\n              if (uiGridCtrl && uiGridCtrl.grid.api.cellNav) {\n\n                viewPortKeyDownDereg = uiGridCtrl.grid.api.cellNav.on.viewPortKeyDown($scope, function (evt, rowCol) {\n                  if (rowCol === null) {\n                    return;\n                  }\n\n                  if (rowCol.row === $scope.row && rowCol.col === $scope.col && !$scope.col.colDef.enableCellEditOnFocus) {\n                    //important to do this before scrollToIfNecessary\n                    beginEditKeyDown(evt);\n                  }\n                });\n\n                cellNavNavigateDereg = uiGridCtrl.grid.api.cellNav.on.navigate($scope, function (newRowCol, oldRowCol) {\n                  if ($scope.col.colDef.enableCellEditOnFocus) {\n                    // Don't begin edit if the cell hasn't changed\n                    if ((!oldRowCol || newRowCol.row !== oldRowCol.row || newRowCol.col !== oldRowCol.col) &&\n                      newRowCol.row === $scope.row && newRowCol.col === $scope.col) {\n                      $timeout(function () {\n                        beginEdit();\n                      });\n                    }\n                  }\n                });\n              }\n\n              $scope.beginEditEventsWired = true;\n\n            }\n\n            function touchStart(event) {\n              // jQuery masks events\n              if (typeof(event.originalEvent) !== 'undefined' && event.originalEvent !== undefined) {\n                event = event.originalEvent;\n              }\n\n              // Bind touchend handler\n              $elm.on('touchend', touchEnd);\n\n              // Start a timeout\n              cancelTouchstartTimeout = $timeout(function() { }, touchstartTimeout);\n\n              // Timeout's done! Start the edit\n              cancelTouchstartTimeout.then(function () {\n                // Use setTimeout to start the edit because beginEdit expects to be outside of $digest\n                setTimeout(beginEdit, 0);\n\n                // Undbind the touchend handler, we don't need it anymore\n                $elm.off('touchend', touchEnd);\n              });\n            }\n\n            // Cancel any touchstart timeout\n            function touchEnd(event) {\n              $timeout.cancel(cancelTouchstartTimeout);\n              $elm.off('touchend', touchEnd);\n            }\n\n            function cancelBeginEditEvents() {\n              $elm.off('dblclick', beginEdit);\n              $elm.off('keydown', beginEditKeyDown);\n              $elm.off('touchstart', touchStart);\n              cellNavNavigateDereg();\n              viewPortKeyDownDereg();\n              $scope.beginEditEventsWired = false;\n            }\n\n            function beginEditKeyDown(evt) {\n              if (uiGridEditService.isStartEditKey(evt)) {\n                beginEdit(evt);\n              }\n            }\n\n            function shouldEdit(col, row) {\n              return !row.isSaving &&\n                ( angular.isFunction(col.colDef.cellEditableCondition) ?\n                    col.colDef.cellEditableCondition($scope) :\n                    col.colDef.cellEditableCondition );\n            }\n\n\n            function beginEdit(triggerEvent) {\n              //we need to scroll the cell into focus before invoking the editor\n              $scope.grid.api.core.scrollToIfNecessary($scope.row, $scope.col)\n                .then(function () {\n                  beginEditAfterScroll(triggerEvent);\n                });\n            }\n\n            /**\n             *  @ngdoc property\n             *  @name editDropdownOptionsArray\n             *  @propertyOf ui.grid.edit.api:ColumnDef\n             *  @description an array of values in the format\n             *  [ {id: xxx, value: xxx} ], which is populated\n             *  into the edit dropdown\n             *\n             */\n            /**\n             *  @ngdoc property\n             *  @name editDropdownIdLabel\n             *  @propertyOf ui.grid.edit.api:ColumnDef\n             *  @description the label for the \"id\" field\n             *  in the editDropdownOptionsArray.  Defaults\n             *  to 'id'\n             *  @example\n             *  <pre>\n             *    $scope.gridOptions = {\n             *      columnDefs: [\n             *        {name: 'status', editableCellTemplate: 'ui-grid/dropdownEditor',\n             *          editDropdownOptionsArray: [{code: 1, status: 'active'}, {code: 2, status: 'inactive'}],\n             *          editDropdownIdLabel: 'code', editDropdownValueLabel: 'status' }\n             *      ],\n             *  </pre>\n             *\n             */\n            /**\n             *  @ngdoc property\n             *  @name editDropdownRowEntityOptionsArrayPath\n             *  @propertyOf ui.grid.edit.api:ColumnDef\n             *  @description a path to a property on row.entity containing an\n             *  array of values in the format\n             *  [ {id: xxx, value: xxx} ], which will be used to populate\n             *  the edit dropdown.  This can be used when the dropdown values are dependent on\n             *  the backing row entity.\n             *  If this property is set then editDropdownOptionsArray will be ignored.\n             *  @example\n             *  <pre>\n             *    $scope.gridOptions = {\n             *      columnDefs: [\n             *        {name: 'status', editableCellTemplate: 'ui-grid/dropdownEditor',\n             *          editDropdownRowEntityOptionsArrayPath: 'foo.bars[0].baz',\n             *          editDropdownIdLabel: 'code', editDropdownValueLabel: 'status' }\n             *      ],\n             *  </pre>\n             *\n             */\n            /**\n             *  @ngdoc service\n             *  @name editDropdownOptionsFunction\n             *  @methodOf ui.grid.edit.api:ColumnDef\n             *  @description a function returning an array of values in the format\n             *  [ {id: xxx, value: xxx} ], which will be used to populate\n             *  the edit dropdown.  This can be used when the dropdown values are dependent on\n             *  the backing row entity with some kind of algorithm.\n             *  If this property is set then both editDropdownOptionsArray and\n             *  editDropdownRowEntityOptionsArrayPath will be ignored.\n             *  @param {object} rowEntity the options.data element that the returned array refers to\n             *  @param {object} colDef the column that implements this dropdown\n             *  @returns {object} an array of values in the format\n             *  [ {id: xxx, value: xxx} ] used to populate the edit dropdown\n             *  @example\n             *  <pre>\n             *    $scope.gridOptions = {\n             *      columnDefs: [\n             *        {name: 'status', editableCellTemplate: 'ui-grid/dropdownEditor',\n             *          editDropdownOptionsFunction: function(rowEntity, colDef) {\n             *            if (rowEntity.foo === 'bar') {\n             *              return [{id: 'bar1', value: 'BAR 1'},\n             *                      {id: 'bar2', value: 'BAR 2'},\n             *                      {id: 'bar3', value: 'BAR 3'}];\n             *            } else {\n             *              return [{id: 'foo1', value: 'FOO 1'},\n             *                      {id: 'foo2', value: 'FOO 2'}];\n             *            }\n             *          },\n             *          editDropdownIdLabel: 'code', editDropdownValueLabel: 'status' }\n             *      ],\n             *  </pre>\n             *\n             */\n            /**\n             *  @ngdoc property\n             *  @name editDropdownValueLabel\n             *  @propertyOf ui.grid.edit.api:ColumnDef\n             *  @description the label for the \"value\" field\n             *  in the editDropdownOptionsArray.  Defaults\n             *  to 'value'\n             *  @example\n             *  <pre>\n             *    $scope.gridOptions = {\n             *      columnDefs: [\n             *        {name: 'status', editableCellTemplate: 'ui-grid/dropdownEditor',\n             *          editDropdownOptionsArray: [{code: 1, status: 'active'}, {code: 2, status: 'inactive'}],\n             *          editDropdownIdLabel: 'code', editDropdownValueLabel: 'status' }\n             *      ],\n             *  </pre>\n             *\n             */\n            /**\n             *  @ngdoc property\n             *  @name editDropdownFilter\n             *  @propertyOf ui.grid.edit.api:ColumnDef\n             *  @description A filter that you would like to apply to the values in the options list\n             *  of the dropdown.  For example if you were using angular-translate you might set this\n             *  to `'translate'`\n             *  @example\n             *  <pre>\n             *    $scope.gridOptions = {\n             *      columnDefs: [\n             *        {name: 'status', editableCellTemplate: 'ui-grid/dropdownEditor',\n             *          editDropdownOptionsArray: [{code: 1, status: 'active'}, {code: 2, status: 'inactive'}],\n             *          editDropdownIdLabel: 'code', editDropdownValueLabel: 'status', editDropdownFilter: 'translate' }\n             *      ],\n             *  </pre>\n             *\n             */\n            function beginEditAfterScroll(triggerEvent) {\n              // If we are already editing, then just skip this so we don't try editing twice...\n              if (inEdit) {\n                return;\n              }\n\n              if (!shouldEdit($scope.col, $scope.row)) {\n                return;\n              }\n\n              var modelField = $scope.row.getQualifiedColField($scope.col);\n              if ($scope.col.colDef.editModelField) {\n                modelField = gridUtil.preEval('row.entity.' + $scope.col.colDef.editModelField);\n              }\n\n              cellModel = $parse(modelField);\n\n              //get original value from the cell\n              origCellValue = cellModel($scope);\n\n              html = $scope.col.editableCellTemplate;\n              html = html.replace(uiGridConstants.MODEL_COL_FIELD, modelField);\n              html = html.replace(uiGridConstants.COL_FIELD, 'grid.getCellValue(row, col)');\n\n              var optionFilter = $scope.col.colDef.editDropdownFilter ? '|' + $scope.col.colDef.editDropdownFilter : '';\n              html = html.replace(uiGridConstants.CUSTOM_FILTERS, optionFilter);\n\n              var inputType = 'text';\n              switch ($scope.col.colDef.type){\n                case 'boolean':\n                  inputType = 'checkbox';\n                  break;\n                case 'number':\n                  inputType = 'number';\n                  break;\n                case 'date':\n                  inputType = 'date';\n                  break;\n              }\n              html = html.replace('INPUT_TYPE', inputType);\n\n              // In order to fill dropdown options we use:\n              // - A function/promise or\n              // - An array inside of row entity if no function exists or\n              // - A single array for the whole column if none of the previous exists.\n              var editDropdownOptionsFunction = $scope.col.colDef.editDropdownOptionsFunction;\n              if (editDropdownOptionsFunction) {\n                $q.when(editDropdownOptionsFunction($scope.row.entity, $scope.col.colDef))\n                        .then(function(result) {\n                  $scope.editDropdownOptionsArray = result;\n                });\n              } else {\n                var editDropdownRowEntityOptionsArrayPath = $scope.col.colDef.editDropdownRowEntityOptionsArrayPath;\n                if (editDropdownRowEntityOptionsArrayPath) {\n                  $scope.editDropdownOptionsArray =  resolveObjectFromPath($scope.row.entity, editDropdownRowEntityOptionsArrayPath);\n                }\n                else {\n                  $scope.editDropdownOptionsArray = $scope.col.colDef.editDropdownOptionsArray;\n                }\n              }\n              $scope.editDropdownIdLabel = $scope.col.colDef.editDropdownIdLabel ? $scope.col.colDef.editDropdownIdLabel : 'id';\n              $scope.editDropdownValueLabel = $scope.col.colDef.editDropdownValueLabel ? $scope.col.colDef.editDropdownValueLabel : 'value';\n\n              var cellElement;\n              var createEditor = function(){\n                inEdit = true;\n                cancelBeginEditEvents();\n                var cellElement = angular.element(html);\n                $elm.append(cellElement);\n                editCellScope = $scope.$new();\n                $compile(cellElement)(editCellScope);\n                var gridCellContentsEl = angular.element($elm.children()[0]);\n                gridCellContentsEl.addClass('ui-grid-cell-contents-hidden');\n              };\n              if (!$rootScope.$$phase) {\n                $scope.$apply(createEditor);\n              } else {\n                createEditor();\n              }\n\n              //stop editing when grid is scrolled\n              var deregOnGridScroll = $scope.col.grid.api.core.on.scrollBegin($scope, function () {\n                if ($scope.grid.disableScrolling) {\n                  return;\n                }\n                endEdit();\n                $scope.grid.api.edit.raise.afterCellEdit($scope.row.entity, $scope.col.colDef, cellModel($scope), origCellValue);\n                deregOnGridScroll();\n                deregOnEndCellEdit();\n                deregOnCancelCellEdit();\n              });\n\n              //end editing\n              var deregOnEndCellEdit = $scope.$on(uiGridEditConstants.events.END_CELL_EDIT, function () {\n                endEdit();\n                $scope.grid.api.edit.raise.afterCellEdit($scope.row.entity, $scope.col.colDef, cellModel($scope), origCellValue);\n                deregOnEndCellEdit();\n                deregOnGridScroll();\n                deregOnCancelCellEdit();\n              });\n\n              //cancel editing\n              var deregOnCancelCellEdit = $scope.$on(uiGridEditConstants.events.CANCEL_CELL_EDIT, function () {\n                cancelEdit();\n                deregOnCancelCellEdit();\n                deregOnGridScroll();\n                deregOnEndCellEdit();\n              });\n\n              $scope.$broadcast(uiGridEditConstants.events.BEGIN_CELL_EDIT, triggerEvent);\n              $timeout(function () {\n                //execute in a timeout to give any complex editor templates a cycle to completely render\n                $scope.grid.api.edit.raise.beginCellEdit($scope.row.entity, $scope.col.colDef, triggerEvent);\n              });\n            }\n\n            function endEdit() {\n              $scope.grid.disableScrolling = false;\n              if (!inEdit) {\n                return;\n              }\n\n              //sometimes the events can't keep up with the keyboard and grid focus is lost, so always focus\n              //back to grid here. The focus call needs to be before the $destroy and removal of the control,\n              //otherwise ng-model-options of UpdateOn: 'blur' will not work.\n              if (uiGridCtrl && uiGridCtrl.grid.api.cellNav) {\n                uiGridCtrl.focus();\n              }\n\n              var gridCellContentsEl = angular.element($elm.children()[0]);\n              //remove edit element\n              editCellScope.$destroy();\n              var children = $elm.children();\n              for (var i = 1; i < children.length; i++) {\n                angular.element(children[i]).remove();\n              }\n              gridCellContentsEl.removeClass('ui-grid-cell-contents-hidden');\n              inEdit = false;\n              registerBeginEditEvents();\n              $scope.grid.api.core.notifyDataChange( uiGridConstants.dataChange.EDIT );\n            }\n\n            function cancelEdit() {\n              $scope.grid.disableScrolling = false;\n              if (!inEdit) {\n                return;\n              }\n              cellModel.assign($scope, origCellValue);\n              $scope.$apply();\n\n              $scope.grid.api.edit.raise.cancelCellEdit($scope.row.entity, $scope.col.colDef);\n              endEdit();\n            }\n\n            // resolves a string path against the given object\n            // shamelessly borrowed from\n            // http://stackoverflow.com/questions/6491463/accessing-nested-javascript-objects-with-string-key\n            function resolveObjectFromPath(object, path) {\n              path = path.replace(/\\[(\\w+)\\]/g, '.$1'); // convert indexes to properties\n              path = path.replace(/^\\./, '');           // strip a leading dot\n              var a = path.split('.');\n              while (a.length) {\n                  var n = a.shift();\n                  if (n in object) {\n                      object = object[n];\n                  } else {\n                      return;\n                  }\n              }\n              return object;\n            }\n\n          }\n        };\n      }]);\n\n  /**\n   *  @ngdoc directive\n   *  @name ui.grid.edit.directive:uiGridEditor\n   *  @element div\n   *  @restrict A\n   *\n   *  @description input editor directive for editable fields.\n   *  Provides EndEdit and CancelEdit events\n   *\n   *  Events that end editing:\n   *     blur and enter keydown\n   *\n   *  Events that cancel editing:\n   *    - Esc keydown\n   *\n   */\n  module.directive('uiGridEditor',\n    ['gridUtil', 'uiGridConstants', 'uiGridEditConstants','$timeout', 'uiGridEditService',\n      function (gridUtil, uiGridConstants, uiGridEditConstants, $timeout, uiGridEditService) {\n        return {\n          scope: true,\n          require: ['?^uiGrid', '?^uiGridRenderContainer', 'ngModel'],\n          compile: function () {\n            return {\n              pre: function ($scope, $elm, $attrs) {\n\n              },\n              post: function ($scope, $elm, $attrs, controllers) {\n                var uiGridCtrl, renderContainerCtrl, ngModel;\n                if (controllers[0]) { uiGridCtrl = controllers[0]; }\n                if (controllers[1]) { renderContainerCtrl = controllers[1]; }\n                if (controllers[2]) { ngModel = controllers[2]; }\n\n                //set focus at start of edit\n                $scope.$on(uiGridEditConstants.events.BEGIN_CELL_EDIT, function (evt,triggerEvent) {\n                  $timeout(function () {\n                    $elm[0].focus();\n                    //only select text if it is not being replaced below in the cellNav viewPortKeyPress\n                    if ($elm[0].select && ($scope.col.colDef.enableCellEditOnFocus || !(uiGridCtrl && uiGridCtrl.grid.api.cellNav))) {\n                      $elm[0].select();\n                    }\n                    else {\n                      //some browsers (Chrome) stupidly, imo, support the w3 standard that number, email, ...\n                      //fields should not allow setSelectionRange.  We ignore the error for those browsers\n                      //https://www.w3.org/Bugs/Public/show_bug.cgi?id=24796\n                      try {\n                        $elm[0].setSelectionRange($elm[0].value.length, $elm[0].value.length);\n                      }\n                      catch (ex) {\n                        //ignore\n                      }\n                    }\n                  });\n\n                  //set the keystroke that started the edit event\n                  //we must do this because the BeginEdit is done in a different event loop than the intitial\n                  //keydown event\n                  //fire this event for the keypress that is received\n                  if (uiGridCtrl && uiGridCtrl.grid.api.cellNav) {\n                    var viewPortKeyDownUnregister = uiGridCtrl.grid.api.cellNav.on.viewPortKeyPress($scope, function (evt, rowCol) {\n                      if (uiGridEditService.isStartEditKey(evt)) {\n                        ngModel.$setViewValue(String.fromCharCode( typeof evt.which === 'number' ? evt.which : evt.keyCode), evt);\n                        ngModel.$render();\n                      }\n                      viewPortKeyDownUnregister();\n                    });\n                  }\n\n                  $elm.on('blur', function (evt) {\n                    $scope.stopEdit(evt);\n                  });\n                });\n\n\n                $scope.deepEdit = false;\n\n                $scope.stopEdit = function (evt) {\n                  if ($scope.inputForm && !$scope.inputForm.$valid) {\n                    evt.stopPropagation();\n                    $scope.$emit(uiGridEditConstants.events.CANCEL_CELL_EDIT);\n                  }\n                  else {\n                    $scope.$emit(uiGridEditConstants.events.END_CELL_EDIT);\n                  }\n                  $scope.deepEdit = false;\n                };\n\n\n                $elm.on('click', function (evt) {\n                  if ($elm[0].type !== 'checkbox') {\n                    $scope.deepEdit = true;\n                    $timeout(function () {\n                      $scope.grid.disableScrolling = true;\n                    });\n                  }\n                });\n\n                $elm.on('keydown', function (evt) {\n                  switch (evt.keyCode) {\n                    case uiGridConstants.keymap.ESC:\n                      evt.stopPropagation();\n                      $scope.$emit(uiGridEditConstants.events.CANCEL_CELL_EDIT);\n                      break;\n                  }\n\n                  if ($scope.deepEdit &&\n                    (evt.keyCode === uiGridConstants.keymap.LEFT ||\n                     evt.keyCode === uiGridConstants.keymap.RIGHT ||\n                     evt.keyCode === uiGridConstants.keymap.UP ||\n                     evt.keyCode === uiGridConstants.keymap.DOWN)) {\n                    evt.stopPropagation();\n                  }\n                  // Pass the keydown event off to the cellNav service, if it exists\n                  else if (uiGridCtrl && uiGridCtrl.grid.api.cellNav) {\n                    evt.uiGridTargetRenderContainerId = renderContainerCtrl.containerId;\n                    if (uiGridCtrl.cellNav.handleKeyDown(evt) !== null) {\n                      $scope.stopEdit(evt);\n                    }\n                  }\n                  else {\n                    //handle enter and tab for editing not using cellNav\n                    switch (evt.keyCode) {\n                      case uiGridConstants.keymap.ENTER: // Enter (Leave Field)\n                      case uiGridConstants.keymap.TAB:\n                        evt.stopPropagation();\n                        evt.preventDefault();\n                        $scope.stopEdit(evt);\n                        break;\n                    }\n                  }\n\n                  return true;\n                });\n              }\n            };\n          }\n        };\n      }]);\n\n  /**\n   *  @ngdoc directive\n   *  @name ui.grid.edit.directive:input\n   *  @element input\n   *  @restrict E\n   *\n   *  @description directive to provide binding between input[date] value and ng-model for angular 1.2\n   *  It is similar to input[date] directive of angular 1.3\n   *\n   *  Supported date format for input is 'yyyy-MM-dd'\n   *  The directive will set the $valid property of input element and the enclosing form to false if\n   *  model is invalid date or value of input is entered wrong.\n   *\n   */\n    module.directive('uiGridEditor', ['$filter', function ($filter) {\n      function parseDateString(dateString) {\n        if (typeof(dateString) === 'undefined' || dateString === '') {\n          return null;\n        }\n        var parts = dateString.split('-');\n        if (parts.length !== 3) {\n          return null;\n        }\n        var year = parseInt(parts[0], 10);\n        var month = parseInt(parts[1], 10);\n        var day = parseInt(parts[2], 10);\n\n        if (month < 1 || year < 1 || day < 1) {\n          return null;\n        }\n        return new Date(year, (month - 1), day);\n      }\n      return {\n        priority: -100, // run after default uiGridEditor directive\n        require: '?ngModel',\n        link: function (scope, element, attrs, ngModel) {\n\n          if (angular.version.minor === 2 && attrs.type && attrs.type === 'date' && ngModel) {\n\n            ngModel.$formatters.push(function (modelValue) {\n              ngModel.$setValidity(null,(!modelValue || !isNaN(modelValue.getTime())));\n              return $filter('date')(modelValue, 'yyyy-MM-dd');\n            });\n\n            ngModel.$parsers.push(function (viewValue) {\n              if (viewValue && viewValue.length > 0) {\n                var dateValue = parseDateString(viewValue);\n                ngModel.$setValidity(null, (dateValue && !isNaN(dateValue.getTime())));\n                return dateValue;\n              }\n              else {\n                ngModel.$setValidity(null, true);\n                return null;\n              }\n            });\n          }\n        }\n      };\n    }]);\n\n\n  /**\n   *  @ngdoc directive\n   *  @name ui.grid.edit.directive:uiGridEditDropdown\n   *  @element div\n   *  @restrict A\n   *\n   *  @description dropdown editor for editable fields.\n   *  Provides EndEdit and CancelEdit events\n   *\n   *  Events that end editing:\n   *     blur and enter keydown, and any left/right nav\n   *\n   *  Events that cancel editing:\n   *    - Esc keydown\n   *\n   */\n  module.directive('uiGridEditDropdown',\n    ['uiGridConstants', 'uiGridEditConstants',\n      function (uiGridConstants, uiGridEditConstants) {\n        return {\n          require: ['?^uiGrid', '?^uiGridRenderContainer'],\n          scope: true,\n          compile: function () {\n            return {\n              pre: function ($scope, $elm, $attrs) {\n\n              },\n              post: function ($scope, $elm, $attrs, controllers) {\n                var uiGridCtrl = controllers[0];\n                var renderContainerCtrl = controllers[1];\n\n                //set focus at start of edit\n                $scope.$on(uiGridEditConstants.events.BEGIN_CELL_EDIT, function () {\n                  $elm[0].focus();\n                  $elm[0].style.width = ($elm[0].parentElement.offsetWidth - 1) + 'px';\n                  $elm.on('blur', function (evt) {\n                    $scope.stopEdit(evt);\n                  });\n                });\n\n\n                $scope.stopEdit = function (evt) {\n                  // no need to validate a dropdown - invalid values shouldn't be\n                  // available in the list\n                  $scope.$emit(uiGridEditConstants.events.END_CELL_EDIT);\n                };\n\n                $elm.on('keydown', function (evt) {\n                  switch (evt.keyCode) {\n                    case uiGridConstants.keymap.ESC:\n                      evt.stopPropagation();\n                      $scope.$emit(uiGridEditConstants.events.CANCEL_CELL_EDIT);\n                      break;\n                  }\n                  if (uiGridCtrl && uiGridCtrl.grid.api.cellNav) {\n                    evt.uiGridTargetRenderContainerId = renderContainerCtrl.containerId;\n                    if (uiGridCtrl.cellNav.handleKeyDown(evt) !== null) {\n                      $scope.stopEdit(evt);\n                    }\n                  }\n                  else {\n                    //handle enter and tab for editing not using cellNav\n                    switch (evt.keyCode) {\n                      case uiGridConstants.keymap.ENTER: // Enter (Leave Field)\n                      case uiGridConstants.keymap.TAB:\n                        evt.stopPropagation();\n                        evt.preventDefault();\n                        $scope.stopEdit(evt);\n                        break;\n                    }\n                  }\n                  return true;\n                });\n              }\n            };\n          }\n        };\n      }]);\n\n  /**\n   *  @ngdoc directive\n   *  @name ui.grid.edit.directive:uiGridEditFileChooser\n   *  @element div\n   *  @restrict A\n   *\n   *  @description input editor directive for editable fields.\n   *  Provides EndEdit and CancelEdit events\n   *\n   *  Events that end editing:\n   *     blur and enter keydown\n   *\n   *  Events that cancel editing:\n   *    - Esc keydown\n   *\n   */\n  module.directive('uiGridEditFileChooser',\n    ['gridUtil', 'uiGridConstants', 'uiGridEditConstants','$timeout',\n      function (gridUtil, uiGridConstants, uiGridEditConstants, $timeout) {\n        return {\n          scope: true,\n          require: ['?^uiGrid', '?^uiGridRenderContainer'],\n          compile: function () {\n            return {\n              pre: function ($scope, $elm, $attrs) {\n\n              },\n              post: function ($scope, $elm, $attrs, controllers) {\n                var uiGridCtrl, renderContainerCtrl;\n                if (controllers[0]) { uiGridCtrl = controllers[0]; }\n                if (controllers[1]) { renderContainerCtrl = controllers[1]; }\n                var grid = uiGridCtrl.grid;\n\n                var handleFileSelect = function( event ){\n                  var target = event.srcElement || event.target;\n\n                  if (target && target.files && target.files.length > 0) {\n                    /**\n                     *  @ngdoc property\n                     *  @name editFileChooserCallback\n                     *  @propertyOf  ui.grid.edit.api:ColumnDef\n                     *  @description A function that should be called when any files have been chosen\n                     *  by the user.  You should use this to process the files appropriately for your\n                     *  application.\n                     *\n                     *  It passes the gridCol, the gridRow (from which you can get gridRow.entity),\n                     *  and the files.  The files are in the format as returned from the file chooser,\n                     *  an array of files, with each having useful information such as:\n                     *  - `files[0].lastModifiedDate`\n                     *  - `files[0].name`\n                     *  - `files[0].size`  (appears to be in bytes)\n                     *  - `files[0].type`  (MIME type by the looks)\n                     *\n                     *  Typically you would do something with these files - most commonly you would\n                     *  use the filename or read the file itself in.  The example function does both.\n                     *\n                     *  @example\n                     *  <pre>\n                     *  editFileChooserCallBack: function(gridRow, gridCol, files ){\n                     *    // ignore all but the first file, it can only choose one anyway\n                     *    // set the filename into this column\n                     *    gridRow.entity.filename = file[0].name;\n                     *\n                     *    // read the file and set it into a hidden column, which we may do stuff with later\n                     *    var setFile = function(fileContent){\n                     *      gridRow.entity.file = fileContent.currentTarget.result;\n                     *    };\n                     *    var reader = new FileReader();\n                     *    reader.onload = setFile;\n                     *    reader.readAsText( files[0] );\n                     *  }\n                     *  </pre>\n                     */\n                    if ( typeof($scope.col.colDef.editFileChooserCallback) === 'function' ) {\n                      $scope.col.colDef.editFileChooserCallback($scope.row, $scope.col, target.files);\n                    } else {\n                      gridUtil.logError('You need to set colDef.editFileChooserCallback to use the file chooser');\n                    }\n\n                    target.form.reset();\n                    $scope.$emit(uiGridEditConstants.events.END_CELL_EDIT);\n                  } else {\n                    $scope.$emit(uiGridEditConstants.events.CANCEL_CELL_EDIT);\n                  }\n                };\n\n                $elm[0].addEventListener('change', handleFileSelect, false);  // TODO: why the false on the end?  Google\n\n                $scope.$on(uiGridEditConstants.events.BEGIN_CELL_EDIT, function () {\n                  $elm[0].focus();\n                  $elm[0].select();\n\n                  $elm.on('blur', function (evt) {\n                    $scope.$emit(uiGridEditConstants.events.END_CELL_EDIT);\n                  });\n                });\n              }\n            };\n          }\n        };\n      }]);\n\n\n})();\n\n(function () {\n  'use strict';\n\n  /**\n   * @ngdoc overview\n   * @name ui.grid.expandable\n   * @description\n   *\n   * # ui.grid.expandable\n   *\n   * <div class=\"alert alert-warning\" role=\"alert\"><strong>Alpha</strong> This feature is in development. There will almost certainly be breaking api changes, or there are major outstanding bugs.</div>\n   *\n   * This module provides the ability to create subgrids with the ability to expand a row\n   * to show the subgrid.\n   *\n   * <div doc-module-components=\"ui.grid.expandable\"></div>\n   */\n  var module = angular.module('ui.grid.expandable', ['ui.grid']);\n\n  /**\n   *  @ngdoc service\n   *  @name ui.grid.expandable.service:uiGridExpandableService\n   *\n   *  @description Services for the expandable grid\n   */\n  module.service('uiGridExpandableService', ['gridUtil', '$compile', function (gridUtil, $compile) {\n    var service = {\n      initializeGrid: function (grid) {\n\n        grid.expandable = {};\n        grid.expandable.expandedAll = false;\n\n        /**\n         *  @ngdoc object\n         *  @name enableExpandable\n         *  @propertyOf  ui.grid.expandable.api:GridOptions\n         *  @description Whether or not to use expandable feature, allows you to turn off expandable on specific grids\n         *  within your application, or in specific modes on _this_ grid. Defaults to true.\n         *  @example\n         *  <pre>\n         *    $scope.gridOptions = {\n         *      enableExpandable: false\n         *    }\n         *  </pre>\n         */\n        grid.options.enableExpandable = grid.options.enableExpandable !== false;\n\n        /**\n         *  @ngdoc object\n         *  @name expandableRowHeight\n         *  @propertyOf  ui.grid.expandable.api:GridOptions\n         *  @description Height in pixels of the expanded subgrid.  Defaults to\n         *  150\n         *  @example\n         *  <pre>\n         *    $scope.gridOptions = {\n         *      expandableRowHeight: 150\n         *    }\n         *  </pre>\n         */\n        grid.options.expandableRowHeight = grid.options.expandableRowHeight || 150;\n\n        /**\n         *  @ngdoc object\n         *  @name\n         *  @propertyOf  ui.grid.expandable.api:GridOptions\n         *  @description Width in pixels of the expandable column. Defaults to 40\n         *  @example\n         *  <pre>\n         *    $scope.gridOptions = {\n         *      expandableRowHeaderWidth: 40\n         *    }\n         *  </pre>\n         */\n        grid.options.expandableRowHeaderWidth = grid.options.expandableRowHeaderWidth || 40;\n\n        /**\n         *  @ngdoc object\n         *  @name expandableRowTemplate\n         *  @propertyOf  ui.grid.expandable.api:GridOptions\n         *  @description Mandatory. The template for your expanded row\n         *  @example\n         *  <pre>\n         *    $scope.gridOptions = {\n         *      expandableRowTemplate: 'expandableRowTemplate.html'\n         *    }\n         *  </pre>\n         */\n        if ( grid.options.enableExpandable && !grid.options.expandableRowTemplate ){\n          gridUtil.logError( 'You have not set the expandableRowTemplate, disabling expandable module' );\n          grid.options.enableExpandable = false;\n        }\n\n        /**\n         *  @ngdoc object\n         *  @name ui.grid.expandable.api:PublicApi\n         *\n         *  @description Public Api for expandable feature\n         */\n        /**\n         *  @ngdoc object\n         *  @name ui.grid.expandable.api:GridRow\n         *\n         *  @description Additional properties added to GridRow when using the expandable module\n         */\n        /**\n         *  @ngdoc object\n         *  @name ui.grid.expandable.api:GridOptions\n         *\n         *  @description Options for configuring the expandable feature, these are available to be\n         *  set using the ui-grid {@link ui.grid.class:GridOptions gridOptions}\n         */\n        var publicApi = {\n          events: {\n            expandable: {\n              /**\n               * @ngdoc event\n               * @name rowExpandedStateChanged\n               * @eventOf  ui.grid.expandable.api:PublicApi\n               * @description raised when cell editing is complete\n               * <pre>\n               *      gridApi.expandable.on.rowExpandedStateChanged(scope,function(row){})\n               * </pre>\n               * @param {GridRow} row the row that was expanded\n               */\n              rowExpandedBeforeStateChanged: function(scope,row){\n              },\n              rowExpandedStateChanged: function (scope, row) {\n              }\n            }\n          },\n\n          methods: {\n            expandable: {\n              /**\n               * @ngdoc method\n               * @name toggleRowExpansion\n               * @methodOf  ui.grid.expandable.api:PublicApi\n               * @description Toggle a specific row\n               * <pre>\n               *      gridApi.expandable.toggleRowExpansion(rowEntity);\n               * </pre>\n               * @param {object} rowEntity the data entity for the row you want to expand\n               */\n              toggleRowExpansion: function (rowEntity) {\n                var row = grid.getRow(rowEntity);\n                if (row !== null) {\n                  service.toggleRowExpansion(grid, row);\n                }\n              },\n\n              /**\n               * @ngdoc method\n               * @name expandAllRows\n               * @methodOf  ui.grid.expandable.api:PublicApi\n               * @description Expand all subgrids.\n               * <pre>\n               *      gridApi.expandable.expandAllRows();\n               * </pre>\n               */\n              expandAllRows: function() {\n                service.expandAllRows(grid);\n              },\n\n              /**\n               * @ngdoc method\n               * @name collapseAllRows\n               * @methodOf  ui.grid.expandable.api:PublicApi\n               * @description Collapse all subgrids.\n               * <pre>\n               *      gridApi.expandable.collapseAllRows();\n               * </pre>\n               */\n              collapseAllRows: function() {\n                service.collapseAllRows(grid);\n              },\n\n              /**\n               * @ngdoc method\n               * @name toggleAllRows\n               * @methodOf  ui.grid.expandable.api:PublicApi\n               * @description Toggle all subgrids.\n               * <pre>\n               *      gridApi.expandable.toggleAllRows();\n               * </pre>\n               */\n              toggleAllRows: function() {\n                service.toggleAllRows(grid);\n              },\n              /**\n               * @ngdoc function\n               * @name expandRow\n               * @methodOf  ui.grid.expandable.api:PublicApi\n               * @description Expand the data row\n               * @param {object} rowEntity gridOptions.data[] array instance\n               */\n              expandRow: function (rowEntity) {\n                var row = grid.getRow(rowEntity);\n                if (row !== null && !row.isExpanded) {\n                  service.toggleRowExpansion(grid, row);\n                }\n              },\n              /**\n               * @ngdoc function\n               * @name collapseRow\n               * @methodOf  ui.grid.expandable.api:PublicApi\n               * @description Collapse the data row\n               * @param {object} rowEntity gridOptions.data[] array instance\n               */\n              collapseRow: function (rowEntity) {\n                var row = grid.getRow(rowEntity);\n                if (row !== null && row.isExpanded) {\n                  service.toggleRowExpansion(grid, row);\n                }\n              },\n              /**\n               * @ngdoc function\n               * @name getExpandedRows\n               * @methodOf  ui.grid.expandable.api:PublicApi\n               * @description returns all expandedRow's entity references\n               */\n              getExpandedRows: function () {\n                return service.getExpandedRows(grid).map(function (gridRow) {\n                  return gridRow.entity;\n                });\n              }\n            }\n          }\n        };\n        grid.api.registerEventsFromObject(publicApi.events);\n        grid.api.registerMethodsFromObject(publicApi.methods);\n      },\n\n      toggleRowExpansion: function (grid, row) {\n        // trigger the \"before change\" event. Can change row height dynamically this way.\n        grid.api.expandable.raise.rowExpandedBeforeStateChanged(row);\n        /**\n         *  @ngdoc object\n         *  @name isExpanded\n         *  @propertyOf  ui.grid.expandable.api:GridRow\n         *  @description Whether or not the row is currently expanded.\n         *  @example\n         *  <pre>\n         *    $scope.api.expandable.on.rowExpandedStateChanged($scope, function (row) {\n         *      if (row.isExpanded) {\n         *        //...\n         *      }\n         *    });\n         *  </pre>\n         */\n        row.isExpanded = !row.isExpanded;\n        if (angular.isUndefined(row.expandedRowHeight)){\n          row.expandedRowHeight = grid.options.expandableRowHeight;\n        }\n\n        if (row.isExpanded) {\n          row.height = row.grid.options.rowHeight + row.expandedRowHeight;\n        }\n        else {\n          row.height = row.grid.options.rowHeight;\n          grid.expandable.expandedAll = false;\n        }\n        grid.api.expandable.raise.rowExpandedStateChanged(row);\n      },\n\n      expandAllRows: function(grid, $scope) {\n        grid.renderContainers.body.visibleRowCache.forEach( function(row) {\n          if (!row.isExpanded) {\n            service.toggleRowExpansion(grid, row);\n          }\n        });\n        grid.expandable.expandedAll = true;\n        grid.queueGridRefresh();\n      },\n\n      collapseAllRows: function(grid) {\n        grid.renderContainers.body.visibleRowCache.forEach( function(row) {\n          if (row.isExpanded) {\n            service.toggleRowExpansion(grid, row);\n          }\n        });\n        grid.expandable.expandedAll = false;\n        grid.queueGridRefresh();\n      },\n\n      toggleAllRows: function(grid) {\n        if (grid.expandable.expandedAll) {\n          service.collapseAllRows(grid);\n        }\n        else {\n          service.expandAllRows(grid);\n        }\n      },\n\n      getExpandedRows: function (grid) {\n        return grid.rows.filter(function (row) {\n          return row.isExpanded;\n        });\n      }\n    };\n    return service;\n  }]);\n\n  /**\n   *  @ngdoc object\n   *  @name enableExpandableRowHeader\n   *  @propertyOf  ui.grid.expandable.api:GridOptions\n   *  @description Show a rowHeader to provide the expandable buttons.  If set to false then implies\n   *  you're going to use a custom method for expanding and collapsing the subgrids. Defaults to true.\n   *  @example\n   *  <pre>\n   *    $scope.gridOptions = {\n   *      enableExpandableRowHeader: false\n   *    }\n   *  </pre>\n   */\n  module.directive('uiGridExpandable', ['uiGridExpandableService', '$templateCache',\n    function (uiGridExpandableService, $templateCache) {\n      return {\n        replace: true,\n        priority: 0,\n        require: '^uiGrid',\n        scope: false,\n        compile: function () {\n          return {\n            pre: function ($scope, $elm, $attrs, uiGridCtrl) {\n              uiGridExpandableService.initializeGrid(uiGridCtrl.grid);\n\n              if (!uiGridCtrl.grid.options.enableExpandable) {\n                return;\n              }\n\n              if (uiGridCtrl.grid.options.enableExpandableRowHeader !== false ) {\n                var expandableRowHeaderColDef = {\n                  name: 'expandableButtons',\n                  displayName: '',\n                  exporterSuppressExport: true,\n                  enableColumnResizing: false,\n                  enableColumnMenu: false,\n                  width: uiGridCtrl.grid.options.expandableRowHeaderWidth || 40\n                };\n                expandableRowHeaderColDef.cellTemplate = $templateCache.get('ui-grid/expandableRowHeader');\n                expandableRowHeaderColDef.headerCellTemplate = $templateCache.get('ui-grid/expandableTopRowHeader');\n                uiGridCtrl.grid.addRowHeaderColumn(expandableRowHeaderColDef, -90);\n              }\n\n            },\n            post: function ($scope, $elm, $attrs, uiGridCtrl) {\n            }\n          };\n        }\n      };\n    }]);\n\n  /**\n   *  @ngdoc directive\n   *  @name ui.grid.expandable.directive:uiGrid\n   *  @description stacks on the uiGrid directive to register child grid with parent row when child is created\n   */\n  module.directive('uiGrid', ['uiGridExpandableService', '$templateCache',\n    function (uiGridExpandableService, $templateCache) {\n      return {\n        replace: true,\n        priority: 599,\n        require: '^uiGrid',\n        scope: false,\n        compile: function () {\n          return {\n            pre: function ($scope, $elm, $attrs, uiGridCtrl) {\n\n              uiGridCtrl.grid.api.core.on.renderingComplete($scope, function() {\n                //if a parent grid row is on the scope, then add the parentRow property to this childGrid\n                if ($scope.row && $scope.row.grid && $scope.row.grid.options && $scope.row.grid.options.enableExpandable) {\n\n                  /**\n                   *  @ngdoc directive\n                   *  @name ui.grid.expandable.class:Grid\n                   *  @description Additional Grid properties added by expandable module\n                   */\n\n                  /**\n                   *  @ngdoc object\n                   *  @name parentRow\n                   *  @propertyOf ui.grid.expandable.class:Grid\n                   *  @description reference to the expanded parent row that owns this grid\n                   */\n                  uiGridCtrl.grid.parentRow = $scope.row;\n\n                  //todo: adjust height on parent row when child grid height changes. we need some sort of gridHeightChanged event\n                 // uiGridCtrl.grid.core.on.canvasHeightChanged($scope, function(oldHeight, newHeight) {\n                 //   uiGridCtrl.grid.parentRow = newHeight;\n                 // });\n                }\n\n              });\n            },\n            post: function ($scope, $elm, $attrs, uiGridCtrl) {\n\n            }\n          };\n        }\n      };\n    }]);\n\n  /**\n   *  @ngdoc directive\n   *  @name ui.grid.expandable.directive:uiGridExpandableRow\n   *  @description directive to render the expandable row template\n   */\n  module.directive('uiGridExpandableRow',\n  ['uiGridExpandableService', '$timeout', '$compile', 'uiGridConstants','gridUtil','$interval', '$log',\n    function (uiGridExpandableService, $timeout, $compile, uiGridConstants, gridUtil, $interval, $log) {\n\n      return {\n        replace: false,\n        priority: 0,\n        scope: false,\n\n        compile: function () {\n          return {\n            pre: function ($scope, $elm, $attrs, uiGridCtrl) {\n              gridUtil.getTemplate($scope.grid.options.expandableRowTemplate).then(\n                function (template) {\n                  if ($scope.grid.options.expandableRowScope) {\n                    /**\n                     *  @ngdoc object\n                     *  @name expandableRowScope\n                     *  @propertyOf  ui.grid.expandable.api:GridOptions\n                     *  @description  Variables of object expandableScope will be available in the scope of the expanded subgrid\n                     *  @example\n                     *  <pre>\n                     *    $scope.gridOptions = {\n                     *      expandableRowScope: expandableScope\n                     *    }\n                     *  </pre>\n                     */\n                    var expandableRowScope = $scope.grid.options.expandableRowScope;\n                    for (var property in expandableRowScope) {\n                      if (expandableRowScope.hasOwnProperty(property)) {\n                        $scope[property] = expandableRowScope[property];\n                      }\n                    }\n                  }\n                  var expandedRowElement = angular.element(template);\n                  $elm.append(expandedRowElement);\n                  expandedRowElement = $compile(expandedRowElement)($scope);\n                  $scope.row.expandedRendered = true;\n              });\n            },\n\n            post: function ($scope, $elm, $attrs, uiGridCtrl) {\n              $scope.$on('$destroy', function() {\n                $scope.row.expandedRendered = false;\n              });\n            }\n          };\n        }\n      };\n    }]);\n\n  /**\n   *  @ngdoc directive\n   *  @name ui.grid.expandable.directive:uiGridRow\n   *  @description stacks on the uiGridRow directive to add support for expandable rows\n   */\n  module.directive('uiGridRow',\n    ['$compile', 'gridUtil', '$templateCache',\n      function ($compile, gridUtil, $templateCache) {\n        return {\n          priority: -200,\n          scope: false,\n          compile: function ($elm, $attrs) {\n            return {\n              pre: function ($scope, $elm, $attrs, controllers) {\n\n                if (!$scope.grid.options.enableExpandable) {\n                  return;\n                }\n\n                $scope.expandableRow = {};\n\n                $scope.expandableRow.shouldRenderExpand = function () {\n                  var ret = $scope.colContainer.name === 'body' &&  $scope.grid.options.enableExpandable !== false && $scope.row.isExpanded && (!$scope.grid.isScrollingVertically || $scope.row.expandedRendered);\n                  return ret;\n                };\n\n                $scope.expandableRow.shouldRenderFiller = function () {\n                  var ret = $scope.row.isExpanded && ( $scope.colContainer.name !== 'body' || ($scope.grid.isScrollingVertically && !$scope.row.expandedRendered));\n                  return ret;\n                };\n\n /*\n  * Commented out @PaulL1.  This has no purpose that I can see, and causes #2964.  If this code needs to be reinstated for some\n  * reason it needs to use drawnWidth, not width, and needs to check column visibility.  It should really use render container\n  * visible column cache also instead of checking column.renderContainer.\n                  function updateRowContainerWidth() {\n                      var grid = $scope.grid;\n                      var colWidth = 0;\n                      grid.columns.forEach( function (column) {\n                          if (column.renderContainer === 'left') {\n                            colWidth += column.width;\n                          }\n                      });\n                      colWidth = Math.floor(colWidth);\n                      return '.grid' + grid.id + ' .ui-grid-pinned-container-' + $scope.colContainer.name + ', .grid' + grid.id +\n                          ' .ui-grid-pinned-container-' + $scope.colContainer.name + ' .ui-grid-render-container-' + $scope.colContainer.name +\n                          ' .ui-grid-viewport .ui-grid-canvas .ui-grid-row { width: ' + colWidth + 'px; }';\n                  }\n\n                  if ($scope.colContainer.name === 'left') {\n                      $scope.grid.registerStyleComputation({\n                          priority: 15,\n                          func: updateRowContainerWidth\n                      });\n                  }*/\n\n              },\n              post: function ($scope, $elm, $attrs, controllers) {\n              }\n            };\n          }\n        };\n      }]);\n\n  /**\n   *  @ngdoc directive\n   *  @name ui.grid.expandable.directive:uiGridViewport\n   *  @description stacks on the uiGridViewport directive to append the expandable row html elements to the\n   *  default gridRow template\n   */\n  module.directive('uiGridViewport',\n    ['$compile', 'gridUtil', '$templateCache',\n      function ($compile, gridUtil, $templateCache) {\n        return {\n          priority: -200,\n          scope: false,\n          compile: function ($elm, $attrs) {\n\n             //todo: this adds ng-if watchers to each row even if the grid is not using expandable directive\n             //      or options.enableExpandable == false\n             //      The alternative is to compile the template and append to each row in a uiGridRow directive\n\n            var rowRepeatDiv = angular.element($elm.children().children()[0]);\n            var expandedRowFillerElement = $templateCache.get('ui-grid/expandableScrollFiller');\n            var expandedRowElement = $templateCache.get('ui-grid/expandableRow');\n            rowRepeatDiv.append(expandedRowElement);\n            rowRepeatDiv.append(expandedRowFillerElement);\n            return {\n              pre: function ($scope, $elm, $attrs, controllers) {\n              },\n              post: function ($scope, $elm, $attrs, controllers) {\n              }\n            };\n          }\n        };\n      }]);\n\n})();\n\n/* global console */\n\n(function () {\n  'use strict';\n\n  /**\n   * @ngdoc overview\n   * @name ui.grid.exporter\n   * @description\n   *\n   * # ui.grid.exporter\n   *\n   * <div class=\"alert alert-success\" role=\"alert\"><strong>Stable</strong> This feature is stable. There should no longer be breaking api changes without a deprecation warning.</div>\n   *\n   * This module provides the ability to export data from the grid.\n   *\n   * Data can be exported in a range of formats, and all data, visible\n   * data, or selected rows can be exported, with all columns or visible\n   * columns.\n   *\n   * No UI is provided, the caller should provide their own UI/buttons\n   * as appropriate, or enable the gridMenu\n   *\n   * <br/>\n   * <br/>\n   *\n   * <div doc-module-components=\"ui.grid.exporter\"></div>\n   */\n\n  var module = angular.module('ui.grid.exporter', ['ui.grid']);\n\n  /**\n   *  @ngdoc object\n   *  @name ui.grid.exporter.constant:uiGridExporterConstants\n   *\n   *  @description constants available in exporter module\n   */\n  /**\n   * @ngdoc property\n   * @propertyOf ui.grid.exporter.constant:uiGridExporterConstants\n   * @name ALL\n   * @description export all data, including data not visible.  Can\n   * be set for either rowTypes or colTypes\n   */\n  /**\n   * @ngdoc property\n   * @propertyOf ui.grid.exporter.constant:uiGridExporterConstants\n   * @name VISIBLE\n   * @description export only visible data, including data not visible.  Can\n   * be set for either rowTypes or colTypes\n   */\n  /**\n   * @ngdoc property\n   * @propertyOf ui.grid.exporter.constant:uiGridExporterConstants\n   * @name SELECTED\n   * @description export all data, including data not visible.  Can\n   * be set only for rowTypes, selection of only some columns is\n   * not supported\n   */\n  module.constant('uiGridExporterConstants', {\n    featureName: 'exporter',\n    ALL: 'all',\n    VISIBLE: 'visible',\n    SELECTED: 'selected',\n    CSV_CONTENT: 'CSV_CONTENT',\n    BUTTON_LABEL: 'BUTTON_LABEL',\n    FILE_NAME: 'FILE_NAME'\n  });\n\n  /**\n   *  @ngdoc service\n   *  @name ui.grid.exporter.service:uiGridExporterService\n   *\n   *  @description Services for exporter feature\n   */\n  module.service('uiGridExporterService', ['$q', 'uiGridExporterConstants', 'gridUtil', '$compile', '$interval', 'i18nService',\n    function ($q, uiGridExporterConstants, gridUtil, $compile, $interval, i18nService) {\n\n      var service = {\n\n        delay: 100,\n\n        initializeGrid: function (grid) {\n\n          //add feature namespace and any properties to grid for needed state\n          grid.exporter = {};\n          this.defaultGridOptions(grid.options);\n\n          /**\n           *  @ngdoc object\n           *  @name ui.grid.exporter.api:PublicApi\n           *\n           *  @description Public Api for exporter feature\n           */\n          var publicApi = {\n            events: {\n              exporter: {\n              }\n            },\n            methods: {\n              exporter: {\n                /**\n                 * @ngdoc function\n                 * @name csvExport\n                 * @methodOf  ui.grid.exporter.api:PublicApi\n                 * @description Exports rows from the grid in csv format,\n                 * the data exported is selected based on the provided options\n                 * @param {string} rowTypes which rows to export, valid values are\n                 * uiGridExporterConstants.ALL, uiGridExporterConstants.VISIBLE,\n                 * uiGridExporterConstants.SELECTED\n                 * @param {string} colTypes which columns to export, valid values are\n                 * uiGridExporterConstants.ALL, uiGridExporterConstants.VISIBLE\n                 */\n                csvExport: function (rowTypes, colTypes) {\n                  service.csvExport(grid, rowTypes, colTypes);\n                },\n                /**\n                 * @ngdoc function\n                 * @name pdfExport\n                 * @methodOf  ui.grid.exporter.api:PublicApi\n                 * @description Exports rows from the grid in pdf format,\n                 * the data exported is selected based on the provided options\n                 * Note that this function has a dependency on pdfMake, all\n                 * going well this has been installed for you.\n                 * The resulting pdf opens in a new browser window.\n                 * @param {string} rowTypes which rows to export, valid values are\n                 * uiGridExporterConstants.ALL, uiGridExporterConstants.VISIBLE,\n                 * uiGridExporterConstants.SELECTED\n                 * @param {string} colTypes which columns to export, valid values are\n                 * uiGridExporterConstants.ALL, uiGridExporterConstants.VISIBLE\n                 */\n                pdfExport: function (rowTypes, colTypes) {\n                  service.pdfExport(grid, rowTypes, colTypes);\n                }\n              }\n            }\n          };\n\n          grid.api.registerEventsFromObject(publicApi.events);\n\n          grid.api.registerMethodsFromObject(publicApi.methods);\n\n          if (grid.api.core.addToGridMenu){\n            service.addToMenu( grid );\n          } else {\n            // order of registration is not guaranteed, register in a little while\n            $interval( function() {\n              if (grid.api.core.addToGridMenu){\n                service.addToMenu( grid );\n              }\n            }, this.delay, 1);\n          }\n\n        },\n\n        defaultGridOptions: function (gridOptions) {\n          //default option to true unless it was explicitly set to false\n          /**\n           * @ngdoc object\n           * @name ui.grid.exporter.api:GridOptions\n           *\n           * @description GridOptions for exporter feature, these are available to be\n           * set using the ui-grid {@link ui.grid.class:GridOptions gridOptions}\n           */\n          /**\n           * @ngdoc object\n           * @name ui.grid.exporter.api:ColumnDef\n           * @description ColumnDef settings for exporter\n           */\n          /**\n           * @ngdoc object\n           * @name exporterSuppressMenu\n           * @propertyOf  ui.grid.exporter.api:GridOptions\n           * @description Don't show the export menu button, implying the user\n           * will roll their own UI for calling the exporter\n           * <br/>Defaults to false\n           */\n          gridOptions.exporterSuppressMenu = gridOptions.exporterSuppressMenu === true;\n          /**\n           * @ngdoc object\n           * @name exporterMenuLabel\n           * @propertyOf  ui.grid.exporter.api:GridOptions\n           * @description The text to show on the exporter menu button\n           * link\n           * <br/>Defaults to 'Export'\n           */\n          gridOptions.exporterMenuLabel = gridOptions.exporterMenuLabel ? gridOptions.exporterMenuLabel : 'Export';\n          /**\n           * @ngdoc object\n           * @name exporterSuppressColumns\n           * @propertyOf  ui.grid.exporter.api:GridOptions\n           * @description Columns that should not be exported.  The selectionRowHeader is already automatically\n           * suppressed, but if you had a button column or some other \"system\" column that shouldn't be shown in the\n           * output then add it in this list.  You should provide an array of column names.\n           * <br/>Defaults to: []\n           * <pre>\n           *   gridOptions.exporterSuppressColumns = [ 'buttons' ];\n           * </pre>\n           */\n          gridOptions.exporterSuppressColumns = gridOptions.exporterSuppressColumns ? gridOptions.exporterSuppressColumns : [];\n          /**\n           * @ngdoc object\n           * @name exporterCsvColumnSeparator\n           * @propertyOf  ui.grid.exporter.api:GridOptions\n           * @description The character to use as column separator\n           * link\n           * <br/>Defaults to ','\n           */\n          gridOptions.exporterCsvColumnSeparator = gridOptions.exporterCsvColumnSeparator ? gridOptions.exporterCsvColumnSeparator : ',';\n          /**\n           * @ngdoc object\n           * @name exporterCsvFilename\n           * @propertyOf  ui.grid.exporter.api:GridOptions\n           * @description The default filename to use when saving the downloaded csv.\n           * This will only work in some browsers.\n           * <br/>Defaults to 'download.csv'\n           */\n          gridOptions.exporterCsvFilename = gridOptions.exporterCsvFilename ? gridOptions.exporterCsvFilename : 'download.csv';\n          /**\n           * @ngdoc object\n           * @name exporterPdfFilename\n           * @propertyOf  ui.grid.exporter.api:GridOptions\n           * @description The default filename to use when saving the downloaded pdf, only used in IE (other browsers open pdfs in a new window)\n           * <br/>Defaults to 'download.pdf'\n           */\n          gridOptions.exporterPdfFilename = gridOptions.exporterPdfFilename ? gridOptions.exporterPdfFilename : 'download.pdf';\n          /**\n           * @ngdoc object\n           * @name exporterOlderExcelCompatibility\n           * @propertyOf  ui.grid.exporter.api:GridOptions\n           * @description Some versions of excel don't like the utf-16 BOM on the front, and it comes\n           * through as ï»¿ in the first column header.  Setting this option to false will suppress this, at the\n           * expense of proper utf-16 handling in applications that do recognise the BOM\n           * <br/>Defaults to false\n           */\n          gridOptions.exporterOlderExcelCompatibility = gridOptions.exporterOlderExcelCompatibility === true;\n          /**\n           * @ngdoc object\n           * @name exporterPdfDefaultStyle\n           * @propertyOf  ui.grid.exporter.api:GridOptions\n           * @description The default style in pdfMake format\n           * <br/>Defaults to:\n           * <pre>\n           *   {\n           *     fontSize: 11\n           *   }\n           * </pre>\n           */\n          gridOptions.exporterPdfDefaultStyle = gridOptions.exporterPdfDefaultStyle ? gridOptions.exporterPdfDefaultStyle : { fontSize: 11 };\n          /**\n           * @ngdoc object\n           * @name exporterPdfTableStyle\n           * @propertyOf  ui.grid.exporter.api:GridOptions\n           * @description The table style in pdfMake format\n           * <br/>Defaults to:\n           * <pre>\n           *   {\n           *     margin: [0, 5, 0, 15]\n           *   }\n           * </pre>\n           */\n          gridOptions.exporterPdfTableStyle = gridOptions.exporterPdfTableStyle ? gridOptions.exporterPdfTableStyle : { margin: [0, 5, 0, 15] };\n          /**\n           * @ngdoc object\n           * @name exporterPdfTableHeaderStyle\n           * @propertyOf  ui.grid.exporter.api:GridOptions\n           * @description The tableHeader style in pdfMake format\n           * <br/>Defaults to:\n           * <pre>\n           *   {\n           *     bold: true,\n           *     fontSize: 12,\n           *     color: 'black'\n           *   }\n           * </pre>\n           */\n          gridOptions.exporterPdfTableHeaderStyle = gridOptions.exporterPdfTableHeaderStyle ? gridOptions.exporterPdfTableHeaderStyle : { bold: true, fontSize: 12, color: 'black' };\n          /**\n           * @ngdoc object\n           * @name exporterPdfHeader\n           * @propertyOf  ui.grid.exporter.api:GridOptions\n           * @description The header section for pdf exports.  Can be\n           * simple text:\n           * <pre>\n           *   gridOptions.exporterPdfHeader = 'My Header';\n           * </pre>\n           * Can be a more complex object in pdfMake format:\n           * <pre>\n           *   gridOptions.exporterPdfHeader = {\n           *     columns: [\n           *       'Left part',\n           *       { text: 'Right part', alignment: 'right' }\n           *     ]\n           *   };\n           * </pre>\n           * Or can be a function, allowing page numbers and the like\n           * <pre>\n           *   gridOptions.exporterPdfHeader: function(currentPage, pageCount) { return currentPage.toString() + ' of ' + pageCount; };\n           * </pre>\n           */\n          gridOptions.exporterPdfHeader = gridOptions.exporterPdfHeader ? gridOptions.exporterPdfHeader : null;\n          /**\n           * @ngdoc object\n           * @name exporterPdfFooter\n           * @propertyOf  ui.grid.exporter.api:GridOptions\n           * @description The header section for pdf exports.  Can be\n           * simple text:\n           * <pre>\n           *   gridOptions.exporterPdfFooter = 'My Footer';\n           * </pre>\n           * Can be a more complex object in pdfMake format:\n           * <pre>\n           *   gridOptions.exporterPdfFooter = {\n           *     columns: [\n           *       'Left part',\n           *       { text: 'Right part', alignment: 'right' }\n           *     ]\n           *   };\n           * </pre>\n           * Or can be a function, allowing page numbers and the like\n           * <pre>\n           *   gridOptions.exporterPdfFooter: function(currentPage, pageCount) { return currentPage.toString() + ' of ' + pageCount; };\n           * </pre>\n           */\n          gridOptions.exporterPdfFooter = gridOptions.exporterPdfFooter ? gridOptions.exporterPdfFooter : null;\n          /**\n           * @ngdoc object\n           * @name exporterPdfOrientation\n           * @propertyOf  ui.grid.exporter.api:GridOptions\n           * @description The orientation, should be a valid pdfMake value,\n           * 'landscape' or 'portrait'\n           * <br/>Defaults to landscape\n           */\n          gridOptions.exporterPdfOrientation = gridOptions.exporterPdfOrientation ? gridOptions.exporterPdfOrientation : 'landscape';\n          /**\n           * @ngdoc object\n           * @name exporterPdfPageSize\n           * @propertyOf  ui.grid.exporter.api:GridOptions\n           * @description The orientation, should be a valid pdfMake\n           * paper size, usually 'A4' or 'LETTER'\n           * {@link https://github.com/bpampuch/pdfmake/blob/master/src/standardPageSizes.js pdfMake page sizes}\n           * <br/>Defaults to A4\n           */\n          gridOptions.exporterPdfPageSize = gridOptions.exporterPdfPageSize ? gridOptions.exporterPdfPageSize : 'A4';\n          /**\n           * @ngdoc object\n           * @name exporterPdfMaxGridWidth\n           * @propertyOf  ui.grid.exporter.api:GridOptions\n           * @description The maxium grid width - the current grid width\n           * will be scaled to match this, with any fixed width columns\n           * being adjusted accordingly.\n           * <br/>Defaults to 720 (for A4 landscape), use 670 for LETTER\n           */\n          gridOptions.exporterPdfMaxGridWidth = gridOptions.exporterPdfMaxGridWidth ? gridOptions.exporterPdfMaxGridWidth : 720;\n          /**\n           * @ngdoc object\n           * @name exporterPdfTableLayout\n           * @propertyOf  ui.grid.exporter.api:GridOptions\n           * @description A tableLayout in pdfMake format,\n           * controls gridlines and the like.  We use the default\n           * layout usually.\n           * <br/>Defaults to null, which means no layout\n           */\n\n          /**\n           * @ngdoc object\n           * @name exporterMenuAllData\n           * @porpertyOf  ui.grid.exporter.api:GridOptions\n           * @description Add export all data as cvs/pdf menu items to the ui-grid grid menu, if it's present.  Defaults to true.\n           */\n          gridOptions.exporterMenuAllData = gridOptions.exporterMenuAllData !== undefined ? gridOptions.exporterMenuAllData : true;\n\n          /**\n           * @ngdoc object\n           * @name exporterMenuVisibleData\n           * @porpertyOf  ui.grid.exporter.api:GridOptions\n           * @description Add export visible data as cvs/pdf menu items to the ui-grid grid menu, if it's present.  Defaults to true.\n           */\n          gridOptions.exporterMenuVisibleData = gridOptions.exporterMenuVisibleData !== undefined ? gridOptions.exporterMenuVisibleData : true;\n\n          /**\n           * @ngdoc object\n           * @name exporterMenuSelectedData\n           * @porpertyOf  ui.grid.exporter.api:GridOptions\n           * @description Add export selected data as cvs/pdf menu items to the ui-grid grid menu, if it's present.  Defaults to true.\n           */\n          gridOptions.exporterMenuSelectedData = gridOptions.exporterMenuSelectedData !== undefined ? gridOptions.exporterMenuSelectedData : true;\n\n          /**\n           * @ngdoc object\n           * @name exporterMenuCsv\n           * @propertyOf  ui.grid.exporter.api:GridOptions\n           * @description Add csv export menu items to the ui-grid grid menu, if it's present.  Defaults to true.\n           */\n          gridOptions.exporterMenuCsv = gridOptions.exporterMenuCsv !== undefined ? gridOptions.exporterMenuCsv : true;\n\n          /**\n           * @ngdoc object\n           * @name exporterMenuPdf\n           * @propertyOf  ui.grid.exporter.api:GridOptions\n           * @description Add pdf export menu items to the ui-grid grid menu, if it's present.  Defaults to true.\n           */\n          gridOptions.exporterMenuPdf = gridOptions.exporterMenuPdf !== undefined ? gridOptions.exporterMenuPdf : true;\n\n          /**\n           * @ngdoc object\n           * @name exporterPdfCustomFormatter\n           * @propertyOf  ui.grid.exporter.api:GridOptions\n           * @description A custom callback routine that changes the pdf document, adding any\n           * custom styling or content that is supported by pdfMake.  Takes in the complete docDefinition, and\n           * must return an updated docDefinition ready for pdfMake.\n           * @example\n           * In this example we add a style to the style array, so that we can use it in our\n           * footer definition.\n           * <pre>\n           *   gridOptions.exporterPdfCustomFormatter = function ( docDefinition ) {\n           *     docDefinition.styles.footerStyle = { bold: true, fontSize: 10 };\n           *     return docDefinition;\n           *   }\n           *\n           *   gridOptions.exporterPdfFooter = { text: 'My footer', style: 'footerStyle' }\n           * </pre>\n           */\n          gridOptions.exporterPdfCustomFormatter = ( gridOptions.exporterPdfCustomFormatter && typeof( gridOptions.exporterPdfCustomFormatter ) === 'function' ) ? gridOptions.exporterPdfCustomFormatter : function ( docDef ) { return docDef; };\n\n          /**\n           * @ngdoc object\n           * @name exporterHeaderFilterUseName\n           * @propertyOf  ui.grid.exporter.api:GridOptions\n           * @description Defaults to false, which leads to `displayName` being passed into the headerFilter.\n           * If set to true, then will pass `name` instead.\n           *\n           *\n           * @example\n           * <pre>\n           *   gridOptions.exporterHeaderFilterUseName = true;\n           * </pre>\n           */\n          gridOptions.exporterHeaderFilterUseName = gridOptions.exporterHeaderFilterUseName === true;\n\n          /**\n           * @ngdoc object\n           * @name exporterHeaderFilter\n           * @propertyOf  ui.grid.exporter.api:GridOptions\n           * @description A function to apply to the header displayNames before exporting.  Useful for internationalisation,\n           * for example if you were using angular-translate you'd set this to `$translate.instant`.  Note that this\n           * call must be synchronous, it cannot be a call that returns a promise.\n           *\n           * Behaviour can be changed to pass in `name` instead of `displayName` through use of `exporterHeaderFilterUseName: true`.\n           *\n           * @example\n           * <pre>\n           *   gridOptions.exporterHeaderFilter = function( displayName ){ return 'col: ' + name; };\n           * </pre>\n           * OR\n           * <pre>\n           *   gridOptions.exporterHeaderFilter = $translate.instant;\n           * </pre>\n           */\n\n          /**\n           * @ngdoc function\n           * @name exporterFieldCallback\n           * @propertyOf  ui.grid.exporter.api:GridOptions\n           * @description A function to call for each field before exporting it.  Allows\n           * massaging of raw data into a display format, for example if you have applied\n           * filters to convert codes into decodes, or you require\n           * a specific date format in the exported content.\n           *\n           * The method is called once for each field exported, and provides the grid, the\n           * gridCol and the GridRow for you to use as context in massaging the data.\n           *\n           * @param {Grid} grid provides the grid in case you have need of it\n           * @param {GridRow} row the row from which the data comes\n           * @param {GridCol} col the column from which the data comes\n           * @param {object} value the value for your massaging\n           * @returns {object} you must return the massaged value ready for exporting\n           *\n           * @example\n           * <pre>\n           *   gridOptions.exporterFieldCallback = function ( grid, row, col, value ){\n           *     if ( col.name === 'status' ){\n           *       value = decodeStatus( value );\n           *     }\n           *     return value;\n           *   }\n           * </pre>\n           */\n          gridOptions.exporterFieldCallback = gridOptions.exporterFieldCallback ? gridOptions.exporterFieldCallback : function( grid, row, col, value ) { return value; };\n\n          /**\n           * @ngdoc function\n           * @name exporterAllDataFn\n           * @propertyOf  ui.grid.exporter.api:GridOptions\n           * @description This promise is needed when exporting all rows,\n           * and the data need to be provided by server side. Default is null.\n           * @returns {Promise} a promise to load all data from server\n           *\n           * @example\n           * <pre>\n           *   gridOptions.exporterAllDataFn = function () {\n           *     return $http.get('/data/100.json')\n           *   }\n           * </pre>\n           */\n          gridOptions.exporterAllDataFn = gridOptions.exporterAllDataFn ? gridOptions.exporterAllDataFn : null;\n\n          /**\n           * @ngdoc function\n           * @name exporterAllDataPromise\n           * @propertyOf  ui.grid.exporter.api:GridOptions\n           * @description DEPRECATED - exporterAllDataFn used to be\n           * called this, but it wasn't a promise, it was a function that returned\n           * a promise.  Deprecated, but supported for backward compatibility, use\n           * exporterAllDataFn instead.\n           * @returns {Promise} a promise to load all data from server\n           *\n           * @example\n           * <pre>\n           *   gridOptions.exporterAllDataFn = function () {\n           *     return $http.get('/data/100.json')\n           *   }\n           * </pre>\n           */\n          if ( gridOptions.exporterAllDataFn == null && gridOptions.exporterAllDataPromise ) {\n            gridOptions.exporterAllDataFn = gridOptions.exporterAllDataPromise;\n          }\n        },\n\n\n        /**\n         * @ngdoc function\n         * @name addToMenu\n         * @methodOf  ui.grid.exporter.service:uiGridExporterService\n         * @description Adds export items to the grid menu,\n         * allowing the user to select export options\n         * @param {Grid} grid the grid from which data should be exported\n         */\n        addToMenu: function ( grid ) {\n          grid.api.core.addToGridMenu( grid, [\n            {\n              title: i18nService.getSafeText('gridMenu.exporterAllAsCsv'),\n              action: function ($event) {\n                this.grid.api.exporter.csvExport( uiGridExporterConstants.ALL, uiGridExporterConstants.ALL );\n              },\n              shown: function() {\n                return this.grid.options.exporterMenuCsv && this.grid.options.exporterMenuAllData;\n              },\n              order: 200\n            },\n            {\n              title: i18nService.getSafeText('gridMenu.exporterVisibleAsCsv'),\n              action: function ($event) {\n                this.grid.api.exporter.csvExport( uiGridExporterConstants.VISIBLE, uiGridExporterConstants.VISIBLE );\n              },\n              shown: function() {\n                return this.grid.options.exporterMenuCsv && this.grid.options.exporterMenuVisibleData;\n              },\n              order: 201\n            },\n            {\n              title: i18nService.getSafeText('gridMenu.exporterSelectedAsCsv'),\n              action: function ($event) {\n                this.grid.api.exporter.csvExport( uiGridExporterConstants.SELECTED, uiGridExporterConstants.VISIBLE );\n              },\n              shown: function() {\n                return this.grid.options.exporterMenuCsv && this.grid.options.exporterMenuSelectedData &&\n                       ( this.grid.api.selection && this.grid.api.selection.getSelectedRows().length > 0 );\n              },\n              order: 202\n            },\n            {\n              title: i18nService.getSafeText('gridMenu.exporterAllAsPdf'),\n              action: function ($event) {\n                this.grid.api.exporter.pdfExport( uiGridExporterConstants.ALL, uiGridExporterConstants.ALL );\n              },\n              shown: function() {\n                return this.grid.options.exporterMenuPdf && this.grid.options.exporterMenuAllData;\n              },\n              order: 203\n            },\n            {\n              title: i18nService.getSafeText('gridMenu.exporterVisibleAsPdf'),\n              action: function ($event) {\n                this.grid.api.exporter.pdfExport( uiGridExporterConstants.VISIBLE, uiGridExporterConstants.VISIBLE );\n              },\n              shown: function() {\n                return this.grid.options.exporterMenuPdf && this.grid.options.exporterMenuVisibleData;\n              },\n              order: 204\n            },\n            {\n              title: i18nService.getSafeText('gridMenu.exporterSelectedAsPdf'),\n              action: function ($event) {\n                this.grid.api.exporter.pdfExport( uiGridExporterConstants.SELECTED, uiGridExporterConstants.VISIBLE );\n              },\n              shown: function() {\n                return this.grid.options.exporterMenuPdf && this.grid.options.exporterMenuSelectedData &&\n                       ( this.grid.api.selection && this.grid.api.selection.getSelectedRows().length > 0 );\n              },\n              order: 205\n            }\n          ]);\n        },\n\n\n        /**\n         * @ngdoc function\n         * @name csvExport\n         * @methodOf  ui.grid.exporter.service:uiGridExporterService\n         * @description Exports rows from the grid in csv format,\n         * the data exported is selected based on the provided options\n         * @param {Grid} grid the grid from which data should be exported\n         * @param {string} rowTypes which rows to export, valid values are\n         * uiGridExporterConstants.ALL, uiGridExporterConstants.VISIBLE,\n         * uiGridExporterConstants.SELECTED\n         * @param {string} colTypes which columns to export, valid values are\n         * uiGridExporterConstants.ALL, uiGridExporterConstants.VISIBLE,\n         * uiGridExporterConstants.SELECTED\n         */\n        csvExport: function (grid, rowTypes, colTypes) {\n          var self = this;\n          this.loadAllDataIfNeeded(grid, rowTypes, colTypes).then(function() {\n            var exportColumnHeaders = grid.options.showHeader ? self.getColumnHeaders(grid, colTypes) : [];\n            var exportData = self.getData(grid, rowTypes, colTypes);\n            var csvContent = self.formatAsCsv(exportColumnHeaders, exportData, grid.options.exporterCsvColumnSeparator);\n\n            self.downloadFile (grid.options.exporterCsvFilename, csvContent, grid.options.exporterCsvColumnSeparator, grid.options.exporterOlderExcelCompatibility);\n          });\n        },\n\n        /**\n         * @ngdoc function\n         * @name loadAllDataIfNeeded\n         * @methodOf  ui.grid.exporter.service:uiGridExporterService\n         * @description When using server side pagination, use exporterAllDataFn to\n         * load all data before continuing processing.\n         * When using client side pagination, return a resolved promise so processing\n         * continues immediately\n         * @param {Grid} grid the grid from which data should be exported\n         * @param {string} rowTypes which rows to export, valid values are\n         * uiGridExporterConstants.ALL, uiGridExporterConstants.VISIBLE,\n         * uiGridExporterConstants.SELECTED\n         * @param {string} colTypes which columns to export, valid values are\n         * uiGridExporterConstants.ALL, uiGridExporterConstants.VISIBLE,\n         * uiGridExporterConstants.SELECTED\n         */\n        loadAllDataIfNeeded: function (grid, rowTypes, colTypes) {\n          if ( rowTypes === uiGridExporterConstants.ALL && grid.rows.length !== grid.options.totalItems && grid.options.exporterAllDataFn) {\n            return grid.options.exporterAllDataFn()\n              .then(function() {\n                grid.modifyRows(grid.options.data);\n              });\n          } else {\n            var deferred = $q.defer();\n            deferred.resolve();\n            return deferred.promise;\n          }\n        },\n\n        /**\n         * @ngdoc property\n         * @propertyOf ui.grid.exporter.api:ColumnDef\n         * @name exporterSuppressExport\n         * @description Suppresses export for this column.  Used by selection and expandable.\n         */\n\n        /**\n         * @ngdoc function\n         * @name getColumnHeaders\n         * @methodOf  ui.grid.exporter.service:uiGridExporterService\n         * @description Gets the column headers from the grid to use\n         * as a title row for the exported file, all headers have\n         * headerCellFilters applied as appropriate.\n         *\n         * Column headers are an array of objects, each object has\n         * name, displayName, width and align attributes.  Only name is\n         * used for csv, all attributes are used for pdf.\n         *\n         * @param {Grid} grid the grid from which data should be exported\n         * @param {string} colTypes which columns to export, valid values are\n         * uiGridExporterConstants.ALL, uiGridExporterConstants.VISIBLE,\n         * uiGridExporterConstants.SELECTED\n         */\n        getColumnHeaders: function (grid, colTypes) {\n          var headers = [];\n          var columns;\n\n          if ( colTypes === uiGridExporterConstants.ALL ){\n            columns = grid.columns;\n          } else {\n            var leftColumns = grid.renderContainers.left ? grid.renderContainers.left.visibleColumnCache.filter( function( column ){ return column.visible; } ) : [];\n            var bodyColumns = grid.renderContainers.body ? grid.renderContainers.body.visibleColumnCache.filter( function( column ){ return column.visible; } ) : [];\n            var rightColumns = grid.renderContainers.right ? grid.renderContainers.right.visibleColumnCache.filter( function( column ){ return column.visible; } ) : [];\n\n            columns = leftColumns.concat(bodyColumns,rightColumns);\n          }\n\n          columns.forEach( function( gridCol, index ) {\n            if ( gridCol.colDef.exporterSuppressExport !== true &&\n                 grid.options.exporterSuppressColumns.indexOf( gridCol.name ) === -1 ){\n              headers.push({\n                name: gridCol.field,\n                displayName: grid.options.exporterHeaderFilter ? ( grid.options.exporterHeaderFilterUseName ? grid.options.exporterHeaderFilter(gridCol.name) : grid.options.exporterHeaderFilter(gridCol.displayName) ) : gridCol.displayName,\n                width: gridCol.drawnWidth ? gridCol.drawnWidth : gridCol.width,\n                align: gridCol.colDef.type === 'number' ? 'right' : 'left'\n              });\n            }\n          });\n\n          return headers;\n        },\n\n\n        /**\n         * @ngdoc property\n         * @propertyOf ui.grid.exporter.api:ColumnDef\n         * @name exporterPdfAlign\n         * @description the alignment you'd like for this specific column when\n         * exported into a pdf.  Can be 'left', 'right', 'center' or any other\n         * valid pdfMake alignment option.\n         */\n\n\n        /**\n         * @ngdoc object\n         * @name ui.grid.exporter.api:GridRow\n         * @description GridRow settings for exporter\n         */\n        /**\n         * @ngdoc object\n         * @name exporterEnableExporting\n         * @propertyOf  ui.grid.exporter.api:GridRow\n         * @description If set to false, then don't export this row, notwithstanding visible or\n         * other settings\n         * <br/>Defaults to true\n         */\n\n        /**\n         * @ngdoc function\n         * @name getData\n         * @methodOf  ui.grid.exporter.service:uiGridExporterService\n         * @description Gets data from the grid based on the provided options,\n         * all cells have cellFilters applied as appropriate.  Any rows marked\n         * `exporterEnableExporting: false` will not be exported\n         * @param {Grid} grid the grid from which data should be exported\n         * @param {string} rowTypes which rows to export, valid values are\n         * uiGridExporterConstants.ALL, uiGridExporterConstants.VISIBLE,\n         * uiGridExporterConstants.SELECTED\n         * @param {string} colTypes which columns to export, valid values are\n         * uiGridExporterConstants.ALL, uiGridExporterConstants.VISIBLE,\n         * uiGridExporterConstants.SELECTED\n         * @param {boolean} applyCellFilters whether or not to get the display value or the raw value of the data\n         */\n        getData: function (grid, rowTypes, colTypes, applyCellFilters) {\n          var data = [];\n          var rows;\n          var columns;\n\n          switch ( rowTypes ) {\n            case uiGridExporterConstants.ALL:\n              rows = grid.rows;\n              break;\n            case uiGridExporterConstants.VISIBLE:\n              rows = grid.getVisibleRows();\n              break;\n            case uiGridExporterConstants.SELECTED:\n              if ( grid.api.selection ){\n                rows = grid.api.selection.getSelectedGridRows();\n              } else {\n                gridUtil.logError('selection feature must be enabled to allow selected rows to be exported');\n              }\n              break;\n          }\n\n          if ( colTypes === uiGridExporterConstants.ALL ){\n            columns = grid.columns;\n          } else {\n            var leftColumns = grid.renderContainers.left ? grid.renderContainers.left.visibleColumnCache.filter( function( column ){ return column.visible; } ) : [];\n            var bodyColumns = grid.renderContainers.body ? grid.renderContainers.body.visibleColumnCache.filter( function( column ){ return column.visible; } ) : [];\n            var rightColumns = grid.renderContainers.right ? grid.renderContainers.right.visibleColumnCache.filter( function( column ){ return column.visible; } ) : [];\n\n            columns = leftColumns.concat(bodyColumns,rightColumns);\n          }\n\n          rows.forEach( function( row, index ) {\n\n            if (row.exporterEnableExporting !== false) {\n              var extractedRow = [];\n\n\n              columns.forEach( function( gridCol, index ) {\n              if ( (gridCol.visible || colTypes === uiGridExporterConstants.ALL ) &&\n                   gridCol.colDef.exporterSuppressExport !== true &&\n                   grid.options.exporterSuppressColumns.indexOf( gridCol.name ) === -1 ){\n                  var cellValue = applyCellFilters ? grid.getCellDisplayValue( row, gridCol ) : grid.getCellValue( row, gridCol );\n                  var extractedField = { value: grid.options.exporterFieldCallback( grid, row, gridCol, cellValue ) };\n                  if ( gridCol.colDef.exporterPdfAlign ) {\n                    extractedField.alignment = gridCol.colDef.exporterPdfAlign;\n                  }\n                  extractedRow.push(extractedField);\n                }\n              });\n\n              data.push(extractedRow);\n            }\n          });\n\n          return data;\n        },\n\n\n        /**\n         * @ngdoc function\n         * @name formatAsCsv\n         * @methodOf  ui.grid.exporter.service:uiGridExporterService\n         * @description Formats the column headers and data as a CSV,\n         * and sends that data to the user\n         * @param {array} exportColumnHeaders an array of column headers,\n         * where each header is an object with name, width and maybe alignment\n         * @param {array} exportData an array of rows, where each row is\n         * an array of column data\n         * @param {string} separator a string that represents the separator to be used in the csv file\n         * @returns {string} csv the formatted csv as a string\n         */\n        formatAsCsv: function (exportColumnHeaders, exportData, separator) {\n          var self = this;\n\n          var bareHeaders = exportColumnHeaders.map(function(header){return { value: header.displayName };});\n\n          var csv = bareHeaders.length > 0 ? (self.formatRowAsCsv(this, separator)(bareHeaders) + '\\n') : '';\n\n          csv += exportData.map(this.formatRowAsCsv(this, separator)).join('\\n');\n\n          return csv;\n        },\n\n        /**\n         * @ngdoc function\n         * @name formatRowAsCsv\n         * @methodOf  ui.grid.exporter.service:uiGridExporterService\n         * @description Renders a single field as a csv field, including\n         * quotes around the value\n         * @param {exporterService} exporter pass in exporter\n         * @param {array} row the row to be turned into a csv string\n         * @returns {string} a csv-ified version of the row\n         */\n        formatRowAsCsv: function (exporter, separator) {\n          return function (row) {\n            return row.map(exporter.formatFieldAsCsv).join(separator);\n          };\n        },\n\n        /**\n         * @ngdoc function\n         * @name formatFieldAsCsv\n         * @methodOf  ui.grid.exporter.service:uiGridExporterService\n         * @description Renders a single field as a csv field, including\n         * quotes around the value\n         * @param {field} field the field to be turned into a csv string,\n         * may be of any type\n         * @returns {string} a csv-ified version of the field\n         */\n        formatFieldAsCsv: function (field) {\n          if (field.value == null) { // we want to catch anything null-ish, hence just == not ===\n            return '';\n          }\n          if (typeof(field.value) === 'number') {\n            return field.value;\n          }\n          if (typeof(field.value) === 'boolean') {\n            return (field.value ? 'TRUE' : 'FALSE') ;\n          }\n          if (typeof(field.value) === 'string') {\n            return '\"' + field.value.replace(/\"/g,'\"\"') + '\"';\n          }\n\n          return JSON.stringify(field.value);\n        },\n\n\n        /**\n         * @ngdoc function\n         * @name isIE\n         * @methodOf  ui.grid.exporter.service:uiGridExporterService\n         * @description Checks whether current browser is IE and returns it's version if it is\n        */\n        isIE: function () {\n          var match = navigator.userAgent.search(/(?:Edge|MSIE|Trident\\/.*; rv:)/);\n          var isIE = false;\n\n          if (match !== -1) {\n            isIE = true;\n          }\n\n          return isIE;\n        },\n\n\n        /**\n         * @ngdoc function\n         * @name downloadFile\n         * @methodOf  ui.grid.exporter.service:uiGridExporterService\n         * @description Triggers download of a csv file.  Logic provided\n         * by @cssensei (from his colleagues at https://github.com/ifeelgoods) in issue #2391\n         * @param {string} fileName the filename we'd like our file to be\n         * given\n         * @param {string} csvContent the csv content that we'd like to\n         * download as a file\n         * @param {boolean} exporterOlderExcelCompatibility whether or not we put a utf-16 BOM on the from (\\uFEFF)\n         */\n        downloadFile: function (fileName, csvContent, columnSeparator, exporterOlderExcelCompatibility) {\n          var D = document;\n          var a = D.createElement('a');\n          var strMimeType = 'application/octet-stream;charset=utf-8';\n          var rawFile;\n          var ieVersion = this.isIE();\n\n          // IE10+\n          if (navigator.msSaveBlob) {\n            return navigator.msSaveOrOpenBlob(\n              new Blob(\n                [exporterOlderExcelCompatibility ? \"\\uFEFF\" : '', csvContent],\n                { type: strMimeType } ),\n              fileName\n            );\n          }\n\n          if (ieVersion) {\n            var frame = D.createElement('iframe');\n            document.body.appendChild(frame);\n\n            frame.contentWindow.document.open('text/html', 'replace');\n            frame.contentWindow.document.write('sep=' + columnSeparator + '\\r\\n' + csvContent);\n            frame.contentWindow.document.close();\n            frame.contentWindow.focus();\n            frame.contentWindow.document.execCommand('SaveAs', true, fileName);\n\n            document.body.removeChild(frame);\n            return true;\n          }\n\n          //html5 A[download]\n          if ('download' in a) {\n            var blob = new Blob(\n              [exporterOlderExcelCompatibility ? \"\\uFEFF\" : '', csvContent],\n              { type: strMimeType }\n            );\n            rawFile = URL.createObjectURL(blob);\n            a.setAttribute('download', fileName);\n          } else {\n            rawFile = 'data:' + strMimeType + ',' + encodeURIComponent(csvContent);\n            a.setAttribute('target', '_blank');\n          }\n\n          a.href = rawFile;\n          a.setAttribute('style', 'display:none;');\n          D.body.appendChild(a);\n          setTimeout(function() {\n            if (a.click) {\n              a.click();\n              // Workaround for Safari 5\n            } else if (document.createEvent) {\n              var eventObj = document.createEvent('MouseEvents');\n              eventObj.initEvent('click', true, true);\n              a.dispatchEvent(eventObj);\n            }\n            D.body.removeChild(a);\n\n          }, this.delay);\n        },\n\n        /**\n         * @ngdoc function\n         * @name pdfExport\n         * @methodOf  ui.grid.exporter.service:uiGridExporterService\n         * @description Exports rows from the grid in pdf format,\n         * the data exported is selected based on the provided options.\n         * Note that this function has a dependency on pdfMake, which must\n         * be installed.  The resulting pdf opens in a new\n         * browser window.\n         * @param {Grid} grid the grid from which data should be exported\n         * @param {string} rowTypes which rows to export, valid values are\n         * uiGridExporterConstants.ALL, uiGridExporterConstants.VISIBLE,\n         * uiGridExporterConstants.SELECTED\n         * @param {string} colTypes which columns to export, valid values are\n         * uiGridExporterConstants.ALL, uiGridExporterConstants.VISIBLE,\n         * uiGridExporterConstants.SELECTED\n         */\n        pdfExport: function (grid, rowTypes, colTypes) {\n          var self = this;\n          this.loadAllDataIfNeeded(grid, rowTypes, colTypes).then(function () {\n            var exportColumnHeaders = self.getColumnHeaders(grid, colTypes);\n            var exportData = self.getData(grid, rowTypes, colTypes);\n            var docDefinition = self.prepareAsPdf(grid, exportColumnHeaders, exportData);\n\n            if (self.isIE() || navigator.appVersion.indexOf(\"Edge\") !== -1) {\n              self.downloadPDF(grid.options.exporterPdfFilename, docDefinition);\n            } else {\n              pdfMake.createPdf(docDefinition).open();\n            }\n          });\n        },\n\n\n        /**\n         * @ngdoc function\n         * @name downloadPdf\n         * @methodOf  ui.grid.exporter.service:uiGridExporterService\n         * @description Generates and retrieves the pdf as a blob, then downloads\n         * it as a file.  Only used in IE, in all other browsers we use the native\n         * pdfMake.open function to just open the PDF\n         * @param {string} fileName the filename to give to the pdf, can be set\n         * through exporterPdfFilename\n         * @param {object} docDefinition a pdf docDefinition that we can generate\n         * and get a blob from\n         */\n        downloadPDF: function (fileName, docDefinition) {\n          var D = document;\n          var a = D.createElement('a');\n          var strMimeType = 'application/octet-stream;charset=utf-8';\n          var rawFile;\n          var ieVersion;\n\n          ieVersion = this.isIE(); // This is now a boolean value\n          var doc = pdfMake.createPdf(docDefinition);\n          var blob;\n\n          doc.getBuffer( function (buffer) {\n            blob = new Blob([buffer]);\n\n            // IE10+\n            if (navigator.msSaveBlob) {\n              return navigator.msSaveBlob(\n                blob, fileName\n              );\n            }\n\n            // Previously:  && ieVersion < 10\n            // ieVersion now returns a boolean for the\n            // sake of sanity. We just check `msSaveBlob` first.\n            if (ieVersion) {\n              var frame = D.createElement('iframe');\n              document.body.appendChild(frame);\n\n              frame.contentWindow.document.open(\"text/html\", \"replace\");\n              frame.contentWindow.document.write(blob);\n              frame.contentWindow.document.close();\n              frame.contentWindow.focus();\n              frame.contentWindow.document.execCommand('SaveAs', true, fileName);\n\n              document.body.removeChild(frame);\n              return true;\n            }\n          });\n        },\n\n\n        /**\n         * @ngdoc function\n         * @name renderAsPdf\n         * @methodOf  ui.grid.exporter.service:uiGridExporterService\n         * @description Renders the data into a pdf, and opens that pdf.\n         *\n         * @param {Grid} grid the grid from which data should be exported\n         * @param {array} exportColumnHeaders an array of column headers,\n         * where each header is an object with name, width and maybe alignment\n         * @param {array} exportData an array of rows, where each row is\n         * an array of column data\n         * @returns {object} a pdfMake format document definition, ready\n         * for generation\n         */\n        prepareAsPdf: function(grid, exportColumnHeaders, exportData) {\n          var headerWidths = this.calculatePdfHeaderWidths( grid, exportColumnHeaders );\n\n          var headerColumns = exportColumnHeaders.map( function( header ) {\n            return { text: header.displayName, style: 'tableHeader' };\n          });\n\n          var stringData = exportData.map(this.formatRowAsPdf(this));\n\n          var allData = [headerColumns].concat(stringData);\n\n          var docDefinition = {\n            pageOrientation: grid.options.exporterPdfOrientation,\n            pageSize: grid.options.exporterPdfPageSize,\n            content: [{\n              style: 'tableStyle',\n              table: {\n                headerRows: 1,\n                widths: headerWidths,\n                body: allData\n              }\n            }],\n            styles: {\n              tableStyle: grid.options.exporterPdfTableStyle,\n              tableHeader: grid.options.exporterPdfTableHeaderStyle\n            },\n            defaultStyle: grid.options.exporterPdfDefaultStyle\n          };\n\n          if ( grid.options.exporterPdfLayout ){\n            docDefinition.layout = grid.options.exporterPdfLayout;\n          }\n\n          if ( grid.options.exporterPdfHeader ){\n            docDefinition.header = grid.options.exporterPdfHeader;\n          }\n\n          if ( grid.options.exporterPdfFooter ){\n            docDefinition.footer = grid.options.exporterPdfFooter;\n          }\n\n          if ( grid.options.exporterPdfCustomFormatter ){\n            docDefinition = grid.options.exporterPdfCustomFormatter( docDefinition );\n          }\n          return docDefinition;\n\n        },\n\n\n        /**\n         * @ngdoc function\n         * @name calculatePdfHeaderWidths\n         * @methodOf  ui.grid.exporter.service:uiGridExporterService\n         * @description Determines the column widths base on the\n         * widths we got from the grid.  If the column is drawn\n         * then we have a drawnWidth.  If the column is not visible\n         * then we have '*', 'x%' or a width.  When columns are\n         * not visible they don't contribute to the overall gridWidth,\n         * so we need to adjust to allow for extra columns\n         *\n         * Our basic heuristic is to take the current gridWidth, plus\n         * numeric columns and call this the base gridwidth.\n         *\n         * To that we add 100 for any '*' column, and x% of the base gridWidth\n         * for any column that is a %\n         *\n         * @param {Grid} grid the grid from which data should be exported\n         * @param {array} exportHeaders array of header information\n         * @returns {object} an array of header widths\n         */\n        calculatePdfHeaderWidths: function ( grid, exportHeaders ) {\n          var baseGridWidth = 0;\n          exportHeaders.forEach( function(value){\n            if (typeof(value.width) === 'number'){\n              baseGridWidth += value.width;\n            }\n          });\n\n          var extraColumns = 0;\n          exportHeaders.forEach( function(value){\n            if (value.width === '*'){\n              extraColumns += 100;\n            }\n            if (typeof(value.width) === 'string' && value.width.match(/(\\d)*%/)) {\n              var percent = parseInt(value.width.match(/(\\d)*%/)[0]);\n\n              value.width = baseGridWidth * percent / 100;\n              extraColumns += value.width;\n            }\n          });\n\n          var gridWidth = baseGridWidth + extraColumns;\n\n          return exportHeaders.map(function( header ) {\n            return header.width === '*' ? header.width : header.width * grid.options.exporterPdfMaxGridWidth / gridWidth;\n          });\n\n        },\n\n        /**\n         * @ngdoc function\n         * @name formatRowAsPdf\n         * @methodOf  ui.grid.exporter.service:uiGridExporterService\n         * @description Renders a row in a format consumable by PDF,\n         * mainly meaning casting everything to a string\n         * @param {exporterService} exporter pass in exporter\n         * @param {array} row the row to be turned into a csv string\n         * @returns {string} a csv-ified version of the row\n         */\n        formatRowAsPdf: function ( exporter ) {\n          return function( row ) {\n            return row.map(exporter.formatFieldAsPdfString);\n          };\n        },\n\n\n        /**\n         * @ngdoc function\n         * @name formatFieldAsCsv\n         * @methodOf  ui.grid.exporter.service:uiGridExporterService\n         * @description Renders a single field as a pdf-able field, which\n         * is different from a csv field only in that strings don't have quotes\n         * around them\n         * @param {field} field the field to be turned into a pdf string,\n         * may be of any type\n         * @returns {string} a string-ified version of the field\n         */\n        formatFieldAsPdfString: function (field) {\n          var returnVal;\n          if (field.value == null) { // we want to catch anything null-ish, hence just == not ===\n            returnVal = '';\n          } else if (typeof(field.value) === 'number') {\n            returnVal = field.value.toString();\n          } else if (typeof(field.value) === 'boolean') {\n            returnVal = (field.value ? 'TRUE' : 'FALSE') ;\n          } else if (typeof(field.value) === 'string') {\n            returnVal = field.value.replace(/\"/g,'\"\"');\n          } else {\n            returnVal = JSON.stringify(field.value).replace(/^\"/,'').replace(/\"$/,'');\n          }\n\n          if (field.alignment && typeof(field.alignment) === 'string' ){\n            returnVal = { text: returnVal, alignment: field.alignment };\n          }\n\n          return returnVal;\n        }\n      };\n\n      return service;\n\n    }\n  ]);\n\n  /**\n   *  @ngdoc directive\n   *  @name ui.grid.exporter.directive:uiGridExporter\n   *  @element div\n   *  @restrict A\n   *\n   *  @description Adds exporter features to grid\n   *\n   *  @example\n   <example module=\"app\">\n   <file name=\"app.js\">\n   var app = angular.module('app', ['ui.grid', 'ui.grid.exporter']);\n\n   app.controller('MainCtrl', ['$scope', function ($scope) {\n      $scope.data = [\n        { name: 'Bob', title: 'CEO' },\n            { name: 'Frank', title: 'Lowly Developer' }\n      ];\n\n      $scope.gridOptions = {\n        enableGridMenu: true,\n        exporterMenuCsv: false,\n        columnDefs: [\n          {name: 'name', enableCellEdit: true},\n          {name: 'title', enableCellEdit: true}\n        ],\n        data: $scope.data\n      };\n    }]);\n   </file>\n   <file name=\"index.html\">\n   <div ng-controller=\"MainCtrl\">\n   <div ui-grid=\"gridOptions\" ui-grid-exporter></div>\n   </div>\n   </file>\n   </example>\n   */\n  module.directive('uiGridExporter', ['uiGridExporterConstants', 'uiGridExporterService', 'gridUtil', '$compile',\n    function (uiGridExporterConstants, uiGridExporterService, gridUtil, $compile) {\n      return {\n        replace: true,\n        priority: 0,\n        require: '^uiGrid',\n        scope: false,\n        link: function ($scope, $elm, $attrs, uiGridCtrl) {\n          uiGridExporterService.initializeGrid(uiGridCtrl.grid);\n          uiGridCtrl.grid.exporter.$scope = $scope;\n        }\n      };\n    }\n  ]);\n})();\n\n(function () {\n  'use strict';\n\n  /**\n   * @ngdoc overview\n   * @name ui.grid.grouping\n   * @description\n   *\n   * # ui.grid.grouping\n   *\n   * <div class=\"alert alert-warning\" role=\"alert\"><strong>Beta</strong> This feature is ready for testing, but it either hasn't seen a lot of use or has some known bugs.</div>\n   *\n   * This module provides grouping of rows based on the data in them, similar\n   * in concept to excel grouping.  You can group multiple columns, resulting in\n   * nested grouping.\n   *\n   * In concept this feature is similar to sorting + grid footer/aggregation, it\n   * sorts the data based on the grouped columns, then creates group rows that\n   * reflect a break in the data.  Each of those group rows can have aggregations for\n   * the data within that group.\n   *\n   * This feature leverages treeBase to provide the tree functionality itself,\n   * the key thing this feature does therefore is to set treeLevels on the rows\n   * and insert the group headers.\n   *\n   * Design information:\n   * -------------------\n   *\n   * Each column will get new menu items - group by, and aggregate by.  Group by\n   * will cause this column to be sorted (if not already), and will move this column\n   * to the front of the sorted columns (i.e. grouped columns take precedence over\n   * sorted columns).  It will respect the sort order already set if there is one,\n   * and it will allow the sorting logic to change that sort order, it just forces\n   * the column to the front of the sorting.  You can group by multiple columns, the\n   * logic will add this column to the sorting after any already grouped columns.\n   *\n   * Once a grouping is defined, grouping logic is added to the rowsProcessors.  This\n   * will process the rows, identifying a break in the data value, and inserting a grouping row.\n   * Grouping rows have specific attributes on them:\n   *\n   *  - internalRow = true: tells us that this isn't a real row, so we can ignore it\n   *    from any processing that it looking at core data rows.  This is used by the core\n   *    logic (or will be one day), as it's not grouping specific\n   *  - groupHeader = true: tells us this is a groupHeader.  This is used by the grouping logic\n   *    to know if this is a groupHeader row or not\n   *\n   * Since the logic is baked into the rowsProcessors, it should get triggered whenever\n   * row order or filtering or anything like that is changed.  In order to avoid the row instantiation\n   * time, and to preserve state across invocations, we hold a cache of the rows that we created\n   * last time, and we use them again this time if we can.\n   *\n   * By default rows are collapsed, which means all data rows have their visible property\n   * set to false, and only level 0 group rows are set to visible.\n   *\n   * <br/>\n   * <br/>\n   *\n   * <div doc-module-components=\"ui.grid.grouping\"></div>\n   */\n\n  var module = angular.module('ui.grid.grouping', ['ui.grid', 'ui.grid.treeBase']);\n\n  /**\n   *  @ngdoc object\n   *  @name ui.grid.grouping.constant:uiGridGroupingConstants\n   *\n   *  @description constants available in grouping module, this includes\n   *  all the constants declared in the treeBase module (these are manually copied\n   *  as there isn't an easy way to include constants in another constants file, and\n   *  we don't want to make users include treeBase)\n   *\n   */\n  module.constant('uiGridGroupingConstants', {\n    featureName: \"grouping\",\n    rowHeaderColName: 'treeBaseRowHeaderCol',\n    EXPANDED: 'expanded',\n    COLLAPSED: 'collapsed',\n    aggregation: {\n      COUNT: 'count',\n      SUM: 'sum',\n      MAX: 'max',\n      MIN: 'min',\n      AVG: 'avg'\n    }\n  });\n\n  /**\n   *  @ngdoc service\n   *  @name ui.grid.grouping.service:uiGridGroupingService\n   *\n   *  @description Services for grouping features\n   */\n  module.service('uiGridGroupingService', ['$q', 'uiGridGroupingConstants', 'gridUtil', 'rowSorter', 'GridRow', 'gridClassFactory', 'i18nService', 'uiGridConstants', 'uiGridTreeBaseService',\n  function ($q, uiGridGroupingConstants, gridUtil, rowSorter, GridRow, gridClassFactory, i18nService, uiGridConstants, uiGridTreeBaseService) {\n\n    var service = {\n\n      initializeGrid: function (grid, $scope) {\n        uiGridTreeBaseService.initializeGrid( grid, $scope );\n\n        //add feature namespace and any properties to grid for needed\n        /**\n         *  @ngdoc object\n         *  @name ui.grid.grouping.grid:grouping\n         *\n         *  @description Grid properties and functions added for grouping\n         */\n        grid.grouping = {};\n\n        /**\n         *  @ngdoc property\n         *  @propertyOf ui.grid.grouping.grid:grouping\n         *  @name groupHeaderCache\n         *\n         *  @description Cache that holds the group header rows we created last time, we'll\n         *  reuse these next time, not least because they hold our expanded states.\n         *\n         *  We need to take care with these that they don't become a memory leak, we\n         *  create a new cache each time using the values from the old cache.  This works\n         *  so long as we're creating group rows for invisible rows as well.\n         *\n         *  The cache is a nested hash, indexed on the value we grouped by.  So if we\n         *  grouped by gender then age, we'd maybe have something like:\n         *  ```\n         *    {\n         *      male: {\n         *        row: <pointer to the old row>,\n         *        children: {\n         *          22: { row: <pointer to the old row> },\n         *          31: { row: <pointer to the old row> }\n         *      },\n         *      female: {\n         *        row: <pointer to the old row>,\n         *        children: {\n         *          28: { row: <pointer to the old row> },\n         *          55: { row: <pointer to the old row> }\n         *      }\n         *    }\n         *  ```\n         *\n         *  We create new rows for any missing rows, this means that they come in as collapsed.\n         *\n         */\n        grid.grouping.groupHeaderCache = {};\n\n        service.defaultGridOptions(grid.options);\n\n        grid.registerRowsProcessor(service.groupRows, 400);\n\n        grid.registerColumnBuilder( service.groupingColumnBuilder);\n\n        grid.registerColumnsProcessor(service.groupingColumnProcessor, 400);\n\n        /**\n         *  @ngdoc object\n         *  @name ui.grid.grouping.api:PublicApi\n         *\n         *  @description Public Api for grouping feature\n         */\n        var publicApi = {\n          events: {\n            grouping: {\n              /**\n               * @ngdoc event\n               * @eventOf ui.grid.grouping.api:PublicApi\n               * @name aggregationChanged\n               * @description raised whenever aggregation is changed, added or removed from a column\n               *\n               * <pre>\n               *      gridApi.grouping.on.aggregationChanged(scope,function(col){})\n               * </pre>\n               * @param {gridCol} col the column which on which aggregation changed. The aggregation\n               * type is available as `col.treeAggregation.type`\n               */\n              aggregationChanged: {},\n              /**\n               * @ngdoc event\n               * @eventOf ui.grid.grouping.api:PublicApi\n               * @name groupingChanged\n               * @description raised whenever the grouped columns changes\n               *\n               * <pre>\n               *      gridApi.grouping.on.groupingChanged(scope,function(col){})\n               * </pre>\n               * @param {gridCol} col the column which on which grouping changed. The new grouping is\n               * available as `col.grouping`\n               */\n              groupingChanged: {}\n            }\n          },\n          methods: {\n            grouping: {\n              /**\n               * @ngdoc function\n               * @name getGrouping\n               * @methodOf  ui.grid.grouping.api:PublicApi\n               * @description Get the grouping configuration for this grid,\n               * used by the saveState feature.  Adds expandedState to the information\n               * provided by the internal getGrouping, and removes any aggregations that have a source\n               * of grouping (i.e. will be automatically reapplied when we regroup the column)\n               * Returned grouping is an object\n               *   `{ grouping: groupArray, treeAggregations: aggregateArray, expandedState: hash }`\n               * where grouping contains an array of objects:\n               *   `{ field: column.field, colName: column.name, groupPriority: column.grouping.groupPriority }`\n               * and aggregations contains an array of objects:\n               *   `{ field: column.field, colName: column.name, aggregation: column.grouping.aggregation }`\n               * and expandedState is a hash of the currently expanded nodes\n               *\n               * The groupArray will be sorted by groupPriority.\n               *\n               * @param {boolean} getExpanded whether or not to return the expanded state\n               * @returns {object} grouping configuration\n               */\n              getGrouping: function ( getExpanded ) {\n                var grouping = service.getGrouping(grid);\n\n                grouping.grouping.forEach( function( group ) {\n                  group.colName = group.col.name;\n                  delete group.col;\n                });\n\n                grouping.aggregations.forEach( function( aggregation ) {\n                  aggregation.colName = aggregation.col.name;\n                  delete aggregation.col;\n                });\n\n                grouping.aggregations = grouping.aggregations.filter( function( aggregation ){\n                  return !aggregation.aggregation.source || aggregation.aggregation.source !== 'grouping';\n                });\n\n                if ( getExpanded ){\n                  grouping.rowExpandedStates = service.getRowExpandedStates( grid.grouping.groupingHeaderCache );\n                }\n\n                return grouping;\n              },\n\n              /**\n               * @ngdoc function\n               * @name setGrouping\n               * @methodOf  ui.grid.grouping.api:PublicApi\n               * @description Set the grouping configuration for this grid,\n               * used by the saveState feature, but can also be used by any\n               * user to specify a combined grouping and aggregation configuration\n               * @param {object} config the config you want to apply, in the format\n               * provided out by getGrouping\n               */\n              setGrouping: function ( config ) {\n                service.setGrouping(grid, config);\n              },\n\n              /**\n               * @ngdoc function\n               * @name groupColumn\n               * @methodOf  ui.grid.grouping.api:PublicApi\n               * @description Adds this column to the existing grouping, at the end of the priority order.\n               * If the column doesn't have a sort, adds one, by default ASC\n               *\n               * This column will move to the left of any non-group columns, the\n               * move is handled in a columnProcessor, so gets called as part of refresh\n               *\n               * @param {string} columnName the name of the column we want to group\n               */\n              groupColumn: function( columnName ) {\n                var column = grid.getColumn(columnName);\n                service.groupColumn(grid, column);\n              },\n\n              /**\n               * @ngdoc function\n               * @name ungroupColumn\n               * @methodOf  ui.grid.grouping.api:PublicApi\n               * @description Removes the groupPriority from this column.  If the\n               * column was previously aggregated the aggregation will come back.\n               * The sort will remain.\n               *\n               * This column will move to the right of any other group columns, the\n               * move is handled in a columnProcessor, so gets called as part of refresh\n               *\n               * @param {string} columnName the name of the column we want to ungroup\n               */\n              ungroupColumn: function( columnName ) {\n                var column = grid.getColumn(columnName);\n                service.ungroupColumn(grid, column);\n              },\n\n              /**\n               * @ngdoc function\n               * @name clearGrouping\n               * @methodOf  ui.grid.grouping.api:PublicApi\n               * @description Clear any grouped columns and any aggregations.  Doesn't remove sorting,\n               * as we don't know whether that sorting was added by grouping or was there beforehand\n               *\n               */\n              clearGrouping: function() {\n                service.clearGrouping(grid);\n              },\n\n              /**\n               * @ngdoc function\n               * @name aggregateColumn\n               * @methodOf  ui.grid.grouping.api:PublicApi\n               * @description Sets the aggregation type on a column, if the\n               * column is currently grouped then it removes the grouping first.\n               * If the aggregationDef is null then will result in the aggregation\n               * being removed\n               *\n               * @param {string} columnName the column we want to aggregate\n               * @param {string} or {function} aggregationDef one of the recognised types\n               * from uiGridGroupingConstants or a custom aggregation function.\n               * @param {string} aggregationLabel (optional) The label to use for this aggregation.\n               */\n              aggregateColumn: function( columnName, aggregationDef, aggregationLabel){\n                var column = grid.getColumn(columnName);\n                service.aggregateColumn( grid, column, aggregationDef, aggregationLabel);\n              }\n\n            }\n          }\n        };\n\n        grid.api.registerEventsFromObject(publicApi.events);\n\n        grid.api.registerMethodsFromObject(publicApi.methods);\n\n        grid.api.core.on.sortChanged( $scope, service.tidyPriorities);\n\n      },\n\n      defaultGridOptions: function (gridOptions) {\n        //default option to true unless it was explicitly set to false\n        /**\n         *  @ngdoc object\n         *  @name ui.grid.grouping.api:GridOptions\n         *\n         *  @description GridOptions for grouping feature, these are available to be\n         *  set using the ui-grid {@link ui.grid.class:GridOptions gridOptions}\n         */\n\n        /**\n         *  @ngdoc object\n         *  @name enableGrouping\n         *  @propertyOf  ui.grid.grouping.api:GridOptions\n         *  @description Enable row grouping for entire grid.\n         *  <br/>Defaults to true\n         */\n        gridOptions.enableGrouping = gridOptions.enableGrouping !== false;\n\n        /**\n         *  @ngdoc object\n         *  @name groupingShowCounts\n         *  @propertyOf  ui.grid.grouping.api:GridOptions\n         *  @description shows counts on the groupHeader rows. Not that if you are using a cellFilter or a\n         *  sortingAlgorithm which relies on a specific format or data type, showing counts may cause that\n         *  to break, since the group header rows will always be a string with groupingShowCounts enabled.\n         *  <br/>Defaults to true except on columns of type 'date'\n         */\n        gridOptions.groupingShowCounts = gridOptions.groupingShowCounts !== false;\n\n        /**\n         *  @ngdoc object\n         *  @name groupingNullLabel\n         *  @propertyOf  ui.grid.grouping.api:GridOptions\n         *  @description The string to use for the grouping header row label on rows which contain a null or undefined value in the grouped column.\n         *  <br/>Defaults to \"Null\"\n         */\n        gridOptions.groupingNullLabel = typeof(gridOptions.groupingNullLabel) === 'undefined' ? 'Null' : gridOptions.groupingNullLabel;\n\n        /**\n         *  @ngdoc object\n         *  @name enableGroupHeaderSelection\n         *  @propertyOf  ui.grid.grouping.api:GridOptions\n         *  @description Allows group header rows to be selected.\n         *  <br/>Defaults to false\n         */\n        gridOptions.enableGroupHeaderSelection = gridOptions.enableGroupHeaderSelection === true;\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name groupingColumnBuilder\n       * @methodOf  ui.grid.grouping.service:uiGridGroupingService\n       * @description Sets the grouping defaults based on the columnDefs\n       *\n       * @param {object} colDef columnDef we're basing on\n       * @param {GridCol} col the column we're to update\n       * @param {object} gridOptions the options we should use\n       * @returns {promise} promise for the builder - actually we do it all inline so it's immediately resolved\n       */\n      groupingColumnBuilder: function (colDef, col, gridOptions) {\n        /**\n         *  @ngdoc object\n         *  @name ui.grid.grouping.api:ColumnDef\n         *\n         *  @description ColumnDef for grouping feature, these are available to be\n         *  set using the ui-grid {@link ui.grid.class:GridOptions.columnDef gridOptions.columnDefs}\n         */\n\n        /**\n         *  @ngdoc object\n         *  @name enableGrouping\n         *  @propertyOf  ui.grid.grouping.api:ColumnDef\n         *  @description Enable grouping on this column\n         *  <br/>Defaults to true.\n         */\n        if (colDef.enableGrouping === false){\n          return;\n        }\n\n        /**\n         *  @ngdoc object\n         *  @name grouping\n         *  @propertyOf  ui.grid.grouping.api:ColumnDef\n         *  @description Set the grouping for a column.  Format is:\n         *  ```\n         *    {\n         *      groupPriority: <number, starts at 0, if less than 0 or undefined then we're aggregating in this column>\n         *    }\n         *  ```\n         *\n         *  **Note that aggregation used to be included in grouping, but is now separately set on the column via treeAggregation\n         *  setting in treeBase**\n         *\n         *  We group in the priority order given, this will also put these columns to the high order of the sort irrespective\n         *  of the sort priority given them.  If there is no sort defined then we sort ascending, if there is a sort defined then\n         *  we use that sort.\n         *\n         *  If the groupPriority is undefined or less than 0, then we expect to be aggregating, and we look at the\n         *  aggregation types to determine what sort of aggregation we can do.  Values are in the constants file, but\n         *  include SUM, COUNT, MAX, MIN\n         *\n         *  groupPriorities should generally be sequential, if they're not then the next time getGrouping is called\n         *  we'll renumber them to be sequential.\n         *  <br/>Defaults to undefined.\n         */\n\n        if ( typeof(col.grouping) === 'undefined' && typeof(colDef.grouping) !== 'undefined') {\n          col.grouping = angular.copy(colDef.grouping);\n          if ( typeof(col.grouping.groupPriority) !== 'undefined' && col.grouping.groupPriority > -1 ){\n            col.treeAggregationFn = uiGridTreeBaseService.nativeAggregations()[uiGridGroupingConstants.aggregation.COUNT].aggregationFn;\n            col.treeAggregationFinalizerFn = service.groupedFinalizerFn;\n          }\n        } else if (typeof(col.grouping) === 'undefined'){\n          col.grouping = {};\n        }\n\n        if (typeof(col.grouping) !== 'undefined' && typeof(col.grouping.groupPriority) !== 'undefined' && col.grouping.groupPriority >= 0){\n          col.suppressRemoveSort = true;\n        }\n\n        var groupColumn = {\n          name: 'ui.grid.grouping.group',\n          title: i18nService.get().grouping.group,\n          icon: 'ui-grid-icon-indent-right',\n          shown: function () {\n            return typeof(this.context.col.grouping) === 'undefined' ||\n                   typeof(this.context.col.grouping.groupPriority) === 'undefined' ||\n                   this.context.col.grouping.groupPriority < 0;\n          },\n          action: function () {\n            service.groupColumn( this.context.col.grid, this.context.col );\n          }\n        };\n\n        var ungroupColumn = {\n          name: 'ui.grid.grouping.ungroup',\n          title: i18nService.get().grouping.ungroup,\n          icon: 'ui-grid-icon-indent-left',\n          shown: function () {\n            return typeof(this.context.col.grouping) !== 'undefined' &&\n                   typeof(this.context.col.grouping.groupPriority) !== 'undefined' &&\n                   this.context.col.grouping.groupPriority >= 0;\n          },\n          action: function () {\n            service.ungroupColumn( this.context.col.grid, this.context.col );\n          }\n        };\n\n        var aggregateRemove = {\n          name: 'ui.grid.grouping.aggregateRemove',\n          title: i18nService.get().grouping.aggregate_remove,\n          shown: function () {\n            return typeof(this.context.col.treeAggregationFn) !== 'undefined';\n          },\n          action: function () {\n            service.aggregateColumn( this.context.col.grid, this.context.col, null);\n          }\n        };\n\n        // generic adder for the aggregation menus, which follow a pattern\n        var addAggregationMenu = function(type, title){\n          title = title || i18nService.get().grouping['aggregate_' + type] || type;\n          var menuItem = {\n            name: 'ui.grid.grouping.aggregate' + type,\n            title: title,\n            shown: function () {\n              return typeof(this.context.col.treeAggregation) === 'undefined' ||\n                     typeof(this.context.col.treeAggregation.type) === 'undefined' ||\n                     this.context.col.treeAggregation.type !== type;\n            },\n            action: function () {\n              service.aggregateColumn( this.context.col.grid, this.context.col, type);\n            }\n          };\n\n          if (!gridUtil.arrayContainsObjectWithProperty(col.menuItems, 'name', 'ui.grid.grouping.aggregate' + type)) {\n            col.menuItems.push(menuItem);\n          }\n        };\n\n        /**\n         *  @ngdoc object\n         *  @name groupingShowGroupingMenu\n         *  @propertyOf  ui.grid.grouping.api:ColumnDef\n         *  @description Show the grouping (group and ungroup items) menu on this column\n         *  <br/>Defaults to true.\n         */\n        if ( col.colDef.groupingShowGroupingMenu !== false ){\n          if (!gridUtil.arrayContainsObjectWithProperty(col.menuItems, 'name', 'ui.grid.grouping.group')) {\n            col.menuItems.push(groupColumn);\n          }\n\n          if (!gridUtil.arrayContainsObjectWithProperty(col.menuItems, 'name', 'ui.grid.grouping.ungroup')) {\n            col.menuItems.push(ungroupColumn);\n          }\n        }\n\n\n        /**\n         *  @ngdoc object\n         *  @name groupingShowAggregationMenu\n         *  @propertyOf  ui.grid.grouping.api:ColumnDef\n         *  @description Show the aggregation menu on this column\n         *  <br/>Defaults to true.\n         */\n        if ( col.colDef.groupingShowAggregationMenu !== false ){\n          angular.forEach(uiGridTreeBaseService.nativeAggregations(), function(aggregationDef, name){\n            addAggregationMenu(name);\n          });\n          angular.forEach(gridOptions.treeCustomAggregations, function(aggregationDef, name){\n            addAggregationMenu(name, aggregationDef.menuTitle);\n          });\n\n          if (!gridUtil.arrayContainsObjectWithProperty(col.menuItems, 'name', 'ui.grid.grouping.aggregateRemove')) {\n            col.menuItems.push(aggregateRemove);\n          }\n        }\n      },\n\n\n\n\n      /**\n       * @ngdoc function\n       * @name groupingColumnProcessor\n       * @methodOf  ui.grid.grouping.service:uiGridGroupingService\n       * @description Moves the columns around based on which are grouped\n       *\n       * @param {array} columns the columns to consider rendering\n       * @param {array} rows the grid rows, which we don't use but are passed to us\n       * @returns {array} updated columns array\n       */\n      groupingColumnProcessor: function( columns, rows ) {\n        var grid = this;\n\n        columns = service.moveGroupColumns(this, columns, rows);\n        return columns;\n      },\n\n      /**\n       * @ngdoc function\n       * @name groupedFinalizerFn\n       * @methodOf  ui.grid.grouping.service:uiGridGroupingService\n       * @description Used on group columns to display the rendered value and optionally\n       * display the count of rows.\n       *\n       * @param {aggregation} the aggregation entity for a grouped column\n       */\n      groupedFinalizerFn: function( aggregation ){\n        var col = this;\n\n        if ( typeof(aggregation.groupVal) !== 'undefined') {\n          aggregation.rendered = aggregation.groupVal;\n          if ( col.grid.options.groupingShowCounts && col.colDef.type !== 'date' ){\n            aggregation.rendered += (' (' + aggregation.value + ')');\n          }\n        } else {\n          aggregation.rendered = null;\n        }\n      },\n\n      /**\n       * @ngdoc function\n       * @name moveGroupColumns\n       * @methodOf  ui.grid.grouping.service:uiGridGroupingService\n       * @description Moves the column order so that the grouped columns are lined up\n       * to the left (well, unless you're RTL, then it's the right).  By doing this in\n       * the columnsProcessor, we make it transient - when the column is ungrouped it'll\n       * go back to where it was.\n       *\n       * Does nothing if the option `moveGroupColumns` is set to false.\n       *\n       * @param {Grid} grid grid object\n       * @param {array} columns the columns that we should process/move\n       * @param {array} rows the grid rows\n       * @returns {array} updated columns\n       */\n      moveGroupColumns: function( grid, columns, rows ){\n        if ( grid.options.moveGroupColumns === false){\n          return columns;\n        }\n\n        columns.forEach( function(column, index){\n          // position used to make stable sort in moveGroupColumns\n          column.groupingPosition = index;\n        });\n\n        columns.sort(function(a, b){\n          var a_group, b_group;\n          if (a.isRowHeader){\n            a_group = a.headerPriority;\n          }\n          else if ( typeof(a.grouping) === 'undefined' || typeof(a.grouping.groupPriority) === 'undefined' || a.grouping.groupPriority < 0){\n            a_group = null;\n          } else {\n            a_group = a.grouping.groupPriority;\n          }\n\n          if (b.isRowHeader){\n            b_group = b.headerPriority;\n          }\n          else if ( typeof(b.grouping) === 'undefined' || typeof(b.grouping.groupPriority) === 'undefined' || b.grouping.groupPriority < 0){\n            b_group = null;\n          } else {\n            b_group = b.grouping.groupPriority;\n          }\n\n          // groups get sorted to the top\n          if ( a_group !== null && b_group === null) { return -1; }\n          if ( b_group !== null && a_group === null) { return 1; }\n          if ( a_group !== null && b_group !== null) {return a_group - b_group; }\n\n          return a.groupingPosition - b.groupingPosition;\n        });\n\n        columns.forEach( function(column, index) {\n          delete column.groupingPosition;\n        });\n\n        return columns;\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name groupColumn\n       * @methodOf  ui.grid.grouping.service:uiGridGroupingService\n       * @description Adds this column to the existing grouping, at the end of the priority order.\n       * If the column doesn't have a sort, adds one, by default ASC\n       *\n       * This column will move to the left of any non-group columns, the\n       * move is handled in a columnProcessor, so gets called as part of refresh\n       *\n       * @param {Grid} grid grid object\n       * @param {GridCol} column the column we want to group\n       */\n      groupColumn: function( grid, column){\n        if ( typeof(column.grouping) === 'undefined' ){\n          column.grouping = {};\n        }\n\n        // set the group priority to the next number in the hierarchy\n        var existingGrouping = service.getGrouping( grid );\n        column.grouping.groupPriority = existingGrouping.grouping.length;\n\n        // add sort if not present\n        if ( !column.sort ){\n          column.sort = { direction: uiGridConstants.ASC };\n        } else if ( typeof(column.sort.direction) === 'undefined' || column.sort.direction === null ){\n          column.sort.direction = uiGridConstants.ASC;\n        }\n\n        column.treeAggregation = { type: uiGridGroupingConstants.aggregation.COUNT, source: 'grouping' };\n        column.treeAggregationFn = uiGridTreeBaseService.nativeAggregations()[uiGridGroupingConstants.aggregation.COUNT].aggregationFn;\n        column.treeAggregationFinalizerFn = service.groupedFinalizerFn;\n\n        grid.api.grouping.raise.groupingChanged(column);\n        // This indirectly calls service.tidyPriorities( grid );\n        grid.api.core.raise.sortChanged(grid, grid.getColumnSorting());\n\n        grid.queueGridRefresh();\n      },\n\n\n       /**\n       * @ngdoc function\n       * @name ungroupColumn\n       * @methodOf  ui.grid.grouping.service:uiGridGroupingService\n       * @description Removes the groupPriority from this column.  If the\n       * column was previously aggregated the aggregation will come back.\n       * The sort will remain.\n       *\n       * This column will move to the right of any other group columns, the\n       * move is handled in a columnProcessor, so gets called as part of refresh\n       *\n       * @param {Grid} grid grid object\n       * @param {GridCol} column the column we want to ungroup\n       */\n      ungroupColumn: function( grid, column){\n        if ( typeof(column.grouping) === 'undefined' ){\n          return;\n        }\n\n        delete column.grouping.groupPriority;\n        delete column.treeAggregation;\n        delete column.customTreeAggregationFinalizer;\n\n        service.tidyPriorities( grid );\n\n        grid.api.grouping.raise.groupingChanged(column);\n\n        grid.queueGridRefresh();\n      },\n\n      /**\n       * @ngdoc function\n       * @name aggregateColumn\n       * @methodOf  ui.grid.grouping.service:uiGridGroupingService\n       * @description Sets the aggregation type on a column, if the\n       * column is currently grouped then it removes the grouping first.\n       *\n       * @param {Grid} grid grid object\n       * @param {GridCol} column the column we want to aggregate\n       * @param {string} one of the recognised types from uiGridGroupingConstants or one of the custom aggregations from gridOptions\n       */\n      aggregateColumn: function( grid, column, aggregationType){\n\n        if (typeof(column.grouping) !== 'undefined' && typeof(column.grouping.groupPriority) !== 'undefined' && column.grouping.groupPriority >= 0){\n          service.ungroupColumn( grid, column );\n        }\n\n        var aggregationDef = {};\n        if ( typeof(grid.options.treeCustomAggregations[aggregationType]) !== 'undefined' ){\n          aggregationDef = grid.options.treeCustomAggregations[aggregationType];\n        } else if ( typeof(uiGridTreeBaseService.nativeAggregations()[aggregationType]) !== 'undefined' ){\n          aggregationDef = uiGridTreeBaseService.nativeAggregations()[aggregationType];\n        }\n\n        column.treeAggregation = { type: aggregationType, label:  i18nService.get().aggregation[aggregationDef.label] || aggregationDef.label };\n        column.treeAggregationFn = aggregationDef.aggregationFn;\n        column.treeAggregationFinalizerFn = aggregationDef.finalizerFn;\n\n        grid.api.grouping.raise.aggregationChanged(column);\n\n        grid.queueGridRefresh();\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name setGrouping\n       * @methodOf  ui.grid.grouping.service:uiGridGroupingService\n       * @description Set the grouping based on a config object, used by the save state feature\n       * (more specifically, by the restore function in that feature )\n       *\n       * @param {Grid} grid grid object\n       * @param {object} config the config we want to set, same format as that returned by getGrouping\n       */\n      setGrouping: function ( grid, config ){\n        if ( typeof(config) === 'undefined' ){\n          return;\n        }\n\n        // first remove any existing grouping\n        service.clearGrouping(grid);\n\n        if ( config.grouping && config.grouping.length && config.grouping.length > 0 ){\n          config.grouping.forEach( function( group ) {\n            var col = grid.getColumn(group.colName);\n\n            if ( col ) {\n              service.groupColumn( grid, col );\n            }\n          });\n        }\n\n        if ( config.aggregations && config.aggregations.length ){\n          config.aggregations.forEach( function( aggregation ) {\n            var col = grid.getColumn(aggregation.colName);\n\n            if ( col ) {\n              service.aggregateColumn( grid, col, aggregation.aggregation.type );\n            }\n          });\n        }\n\n        if ( config.rowExpandedStates ){\n          service.applyRowExpandedStates( grid.grouping.groupingHeaderCache, config.rowExpandedStates );\n        }\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name clearGrouping\n       * @methodOf  ui.grid.grouping.service:uiGridGroupingService\n       * @description Clear any grouped columns and any aggregations.  Doesn't remove sorting,\n       * as we don't know whether that sorting was added by grouping or was there beforehand\n       *\n       * @param {Grid} grid grid object\n       */\n      clearGrouping: function( grid ) {\n        var currentGrouping = service.getGrouping(grid);\n\n        if ( currentGrouping.grouping.length > 0 ){\n          currentGrouping.grouping.forEach( function( group ) {\n            if (!group.col){\n              // should have a group.colName if there's no col\n              group.col = grid.getColumn(group.colName);\n            }\n            service.ungroupColumn(grid, group.col);\n          });\n        }\n\n        if ( currentGrouping.aggregations.length > 0 ){\n          currentGrouping.aggregations.forEach( function( aggregation ){\n            if (!aggregation.col){\n              // should have a group.colName if there's no col\n              aggregation.col = grid.getColumn(aggregation.colName);\n            }\n            service.aggregateColumn(grid, aggregation.col, null);\n          });\n        }\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name tidyPriorities\n       * @methodOf  ui.grid.grouping.service:uiGridGroupingService\n       * @description Renumbers groupPriority and sortPriority such that\n       * groupPriority is contiguous, and sortPriority either matches\n       * groupPriority (for group columns), and otherwise is contiguous and\n       * higher than groupPriority.\n       *\n       * @param {Grid} grid grid object\n       */\n      tidyPriorities: function( grid ){\n        // if we're called from sortChanged, grid is in this, not passed as param, the param can be a column or undefined\n        if ( ( typeof(grid) === 'undefined' || typeof(grid.grid) !== 'undefined' ) && typeof(this.grid) !== 'undefined' ) {\n          grid = this.grid;\n        }\n\n        var groupArray = [];\n        var sortArray = [];\n\n        grid.columns.forEach( function(column, index){\n          if ( typeof(column.grouping) !== 'undefined' && typeof(column.grouping.groupPriority) !== 'undefined' && column.grouping.groupPriority >= 0){\n            groupArray.push(column);\n          } else if ( typeof(column.sort) !== 'undefined' && typeof(column.sort.priority) !== 'undefined' && column.sort.priority >= 0){\n            sortArray.push(column);\n          }\n        });\n\n        groupArray.sort(function(a, b){ return a.grouping.groupPriority - b.grouping.groupPriority; });\n        groupArray.forEach( function(column, index){\n          column.grouping.groupPriority = index;\n          column.suppressRemoveSort = true;\n          if ( typeof(column.sort) === 'undefined'){\n            column.sort = {};\n          }\n          column.sort.priority = index;\n        });\n\n        var i = groupArray.length;\n        sortArray.sort(function(a, b){ return a.sort.priority - b.sort.priority; });\n        sortArray.forEach( function(column, index){\n          column.sort.priority = i;\n          column.suppressRemoveSort = column.colDef.suppressRemoveSort;\n          i++;\n        });\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name groupRows\n       * @methodOf  ui.grid.grouping.service:uiGridGroupingService\n       * @description The rowProcessor that creates the groupHeaders (i.e. does\n       * the actual grouping).\n       *\n       * Assumes it is always called after the sorting processor, guaranteed by the priority setting\n       *\n       * Processes all the rows in order, inserting a groupHeader row whenever there is a change\n       * in value of a grouped row, based on the sortAlgorithm used for the column.  The group header row\n       * is looked up in the groupHeaderCache, and used from there if there is one. The entity is reset\n       * to {} if one is found.\n       *\n       * As it processes it maintains a `processingState` array. This records, for each level of grouping we're\n       * working with, the following information:\n       * ```\n       *   {\n       *     fieldName: name,\n       *     col: col,\n       *     initialised: boolean,\n       *     currentValue: value,\n       *     currentRow: gridRow,\n       *   }\n       * ```\n       * We look for changes in the currentValue at any of the levels.  Where we find a change we:\n       *\n       * - create a new groupHeader row in the array\n       *\n       * @param {array} renderableRows the rows we want to process, usually the output from the previous rowProcessor\n       * @returns {array} the updated rows, including our new group rows\n       */\n      groupRows: function( renderableRows ) {\n        if (renderableRows.length === 0){\n          return renderableRows;\n        }\n\n        var grid = this;\n        grid.grouping.oldGroupingHeaderCache = grid.grouping.groupingHeaderCache || {};\n        grid.grouping.groupingHeaderCache = {};\n\n        var processingState = service.initialiseProcessingState( grid );\n\n        // processes each of the fields we are grouping by, checks if the value has changed and inserts a groupHeader\n        // Broken out as shouldn't create functions in a loop.\n        var updateProcessingState = function( groupFieldState, stateIndex ) {\n          var fieldValue = grid.getCellValue(row, groupFieldState.col);\n\n          // look for change of value - and insert a header\n          if ( !groupFieldState.initialised || rowSorter.getSortFn(grid, groupFieldState.col, renderableRows)(fieldValue, groupFieldState.currentValue) !== 0 ){\n            service.insertGroupHeader( grid, renderableRows, i, processingState, stateIndex );\n            i++;\n          }\n        };\n\n        // use a for loop because it's tolerant of the array length changing whilst we go - we can\n        // manipulate the iterator when we insert groupHeader rows\n        for (var i = 0; i < renderableRows.length; i++ ){\n          var row = renderableRows[i];\n\n          if ( row.visible ){\n            processingState.forEach( updateProcessingState );\n          }\n        }\n\n        delete grid.grouping.oldGroupingHeaderCache;\n        return renderableRows;\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name initialiseProcessingState\n       * @methodOf  ui.grid.grouping.service:uiGridGroupingService\n       * @description Creates the processing state array that is used\n       * for groupRows.\n       *\n       * @param {Grid} grid grid object\n       * @returns {array} an array in the format described in the groupRows method,\n       * initialised with blank values\n       */\n      initialiseProcessingState: function( grid ){\n        var processingState = [];\n        var columnSettings = service.getGrouping( grid );\n\n        columnSettings.grouping.forEach( function( groupItem, index){\n          processingState.push({\n            fieldName: groupItem.field,\n            col: groupItem.col,\n            initialised: false,\n            currentValue: null,\n            currentRow: null\n          });\n        });\n\n        return processingState;\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name getGrouping\n       * @methodOf  ui.grid.grouping.service:uiGridGroupingService\n       * @description Get the grouping settings from the columns.  As a side effect\n       * this always renumbers the grouping starting at 0\n       * @param {Grid} grid grid object\n       * @returns {array} an array of the group fields, in order of priority\n       */\n      getGrouping: function( grid ){\n        var groupArray = [];\n        var aggregateArray = [];\n\n        // get all the grouping\n        grid.columns.forEach( function(column, columnIndex){\n          if ( column.grouping ){\n            if ( typeof(column.grouping.groupPriority) !== 'undefined' && column.grouping.groupPriority >= 0){\n              groupArray.push({ field: column.field, col: column, groupPriority: column.grouping.groupPriority, grouping: column.grouping });\n            }\n          }\n          if ( column.treeAggregation && column.treeAggregation.type ){\n            aggregateArray.push({ field: column.field, col: column, aggregation: column.treeAggregation });\n          }\n        });\n\n        // sort grouping into priority order\n        groupArray.sort( function(a, b){\n          return a.groupPriority - b.groupPriority;\n        });\n\n        // renumber the priority in case it was somewhat messed up, then remove the grouping reference\n        groupArray.forEach( function( group, index) {\n          group.grouping.groupPriority = index;\n          group.groupPriority = index;\n          delete group.grouping;\n        });\n\n        return { grouping: groupArray, aggregations: aggregateArray };\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name insertGroupHeader\n       * @methodOf  ui.grid.grouping.service:uiGridGroupingService\n       * @description Create a group header row, and link it to the various configuration\n       * items that we use.\n       *\n       * Look for the row in the oldGroupingHeaderCache, write the row into the new groupingHeaderCache.\n       *\n       * @param {Grid} grid grid object\n       * @param {array} renderableRows the rows that we are processing\n       * @param {number} rowIndex the row we were up to processing\n       * @param {array} processingState the current processing state\n       * @param {number} stateIndex the processing state item that we were on when we triggered a new group header -\n       * i.e. the column that we want to create a header for\n       */\n      insertGroupHeader: function( grid, renderableRows, rowIndex, processingState, stateIndex ) {\n        // set the value that caused the end of a group into the header row and the processing state\n        var fieldName = processingState[stateIndex].fieldName;\n        var col = processingState[stateIndex].col;\n\n        var newValue = grid.getCellValue(renderableRows[rowIndex], col);\n        var newDisplayValue = newValue;\n        if ( typeof(newValue) === 'undefined' || newValue === null ) {\n          newDisplayValue = grid.options.groupingNullLabel;\n        }\n\n        var getKeyAsValueForCacheMap = function(key) {\n          if (angular.isObject(key)) {\n              return JSON.stringify(key);\n          } else {\n              return key;\n          }\n        };\n\n        var cacheItem = grid.grouping.oldGroupingHeaderCache;\n        for ( var i = 0; i < stateIndex; i++ ){\n          if ( cacheItem && cacheItem[getKeyAsValueForCacheMap(processingState[i].currentValue)] ){\n            cacheItem = cacheItem[getKeyAsValueForCacheMap(processingState[i].currentValue)].children;\n          }\n        }\n\n        var headerRow;\n        if ( cacheItem && cacheItem[getKeyAsValueForCacheMap(newValue)]){\n          headerRow = cacheItem[getKeyAsValueForCacheMap(newValue)].row;\n          headerRow.entity = {};\n        } else {\n          headerRow = new GridRow( {}, null, grid );\n          gridClassFactory.rowTemplateAssigner.call(grid, headerRow);\n        }\n\n        headerRow.entity['$$' + processingState[stateIndex].col.uid] = { groupVal: newDisplayValue };\n        headerRow.treeLevel = stateIndex;\n        headerRow.groupHeader = true;\n        headerRow.internalRow = true;\n        headerRow.enableCellEdit = false;\n        headerRow.enableSelection = grid.options.enableGroupHeaderSelection;\n        processingState[stateIndex].initialised = true;\n        processingState[stateIndex].currentValue = newValue;\n        processingState[stateIndex].currentRow = headerRow;\n\n        // set all processing states below this one to not be initialised - change of this state\n        // means all those need to start again\n        service.finaliseProcessingState( processingState, stateIndex + 1);\n\n        // insert our new header row\n        renderableRows.splice(rowIndex, 0, headerRow);\n\n        // add our new header row to the cache\n        cacheItem = grid.grouping.groupingHeaderCache;\n        for ( i = 0; i < stateIndex; i++ ){\n          cacheItem = cacheItem[getKeyAsValueForCacheMap(processingState[i].currentValue)].children;\n        }\n        cacheItem[getKeyAsValueForCacheMap(newValue)] = { row: headerRow, children: {} };\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name finaliseProcessingState\n       * @methodOf  ui.grid.grouping.service:uiGridGroupingService\n       * @description Set all processing states lower than the one that had a break in value to\n       * no longer be initialised.  Render the counts into the entity ready for display.\n       *\n       * @param {Grid} grid grid object\n       * @param {array} processingState the current processing state\n       * @param {number} stateIndex the processing state item that we were on when we triggered a new group header, all\n       * processing states after this need to be finalised\n       */\n      finaliseProcessingState: function( processingState, stateIndex ){\n        for ( var i = stateIndex; i < processingState.length; i++){\n          processingState[i].initialised = false;\n          processingState[i].currentRow = null;\n          processingState[i].currentValue = null;\n        }\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name getRowExpandedStates\n       * @methodOf  ui.grid.grouping.service:uiGridGroupingService\n       * @description Extract the groupHeaderCache hash, pulling out only the states.\n       *\n       * The example below shows a grid that is grouped by gender then age\n       *\n       * <pre>\n       *   {\n       *     male: {\n       *       state: 'expanded',\n       *       children: {\n       *         22: { state: 'expanded' },\n       *         30: { state: 'collapsed' }\n       *       }\n       *     },\n       *     female: {\n       *       state: 'expanded',\n       *       children: {\n       *         28: { state: 'expanded' },\n       *         55: { state: 'collapsed' }\n       *       }\n       *     }\n       *   }\n       * </pre>\n       *\n       * @param {Grid} grid grid object\n       * @returns {hash} the expanded states as a hash\n       */\n      getRowExpandedStates: function(treeChildren){\n        if ( typeof(treeChildren) === 'undefined' ){\n          return {};\n        }\n\n        var newChildren = {};\n\n        angular.forEach( treeChildren, function( value, key ){\n          newChildren[key] = { state: value.row.treeNode.state };\n          if ( value.children ){\n            newChildren[key].children = service.getRowExpandedStates( value.children );\n          } else {\n            newChildren[key].children = {};\n          }\n        });\n\n        return newChildren;\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name applyRowExpandedStates\n       * @methodOf  ui.grid.grouping.service:uiGridGroupingService\n       * @description Take a hash in the format as created by getRowExpandedStates,\n       * and apply it to the grid.grouping.groupHeaderCache.\n       *\n       * Takes a treeSubset, and applies to a treeSubset - so can be called\n       * recursively.\n       *\n       * @param {object} currentNode can be grid.grouping.groupHeaderCache, or any of\n       * the children of that hash\n       * @returns {hash} expandedStates can be the full expanded states, or children\n       * of that expanded states (which hopefully matches the subset of the groupHeaderCache)\n       */\n      applyRowExpandedStates: function( currentNode, expandedStates ){\n        if ( typeof(expandedStates) === 'undefined' ){\n          return;\n        }\n\n        angular.forEach(expandedStates, function( value, key ) {\n          if ( currentNode[key] ){\n            currentNode[key].row.treeNode.state = value.state;\n\n            if (value.children && currentNode[key].children){\n              service.applyRowExpandedStates( currentNode[key].children, value.children );\n            }\n          }\n        });\n      }\n\n\n    };\n\n    return service;\n\n  }]);\n\n\n  /**\n   *  @ngdoc directive\n   *  @name ui.grid.grouping.directive:uiGridGrouping\n   *  @element div\n   *  @restrict A\n   *\n   *  @description Adds grouping features to grid\n   *\n   *  @example\n   <example module=\"app\">\n   <file name=\"app.js\">\n   var app = angular.module('app', ['ui.grid', 'ui.grid.grouping']);\n\n   app.controller('MainCtrl', ['$scope', function ($scope) {\n      $scope.data = [\n        { name: 'Bob', title: 'CEO' },\n            { name: 'Frank', title: 'Lowly Developer' }\n      ];\n\n      $scope.columnDefs = [\n        {name: 'name', enableCellEdit: true},\n        {name: 'title', enableCellEdit: true}\n      ];\n\n      $scope.gridOptions = { columnDefs: $scope.columnDefs, data: $scope.data };\n    }]);\n   </file>\n   <file name=\"index.html\">\n   <div ng-controller=\"MainCtrl\">\n   <div ui-grid=\"gridOptions\" ui-grid-grouping></div>\n   </div>\n   </file>\n   </example>\n   */\n  module.directive('uiGridGrouping', ['uiGridGroupingConstants', 'uiGridGroupingService', '$templateCache',\n  function (uiGridGroupingConstants, uiGridGroupingService, $templateCache) {\n    return {\n      replace: true,\n      priority: 0,\n      require: '^uiGrid',\n      scope: false,\n      compile: function () {\n        return {\n          pre: function ($scope, $elm, $attrs, uiGridCtrl) {\n            if (uiGridCtrl.grid.options.enableGrouping !== false){\n              uiGridGroupingService.initializeGrid(uiGridCtrl.grid, $scope);\n            }\n          },\n          post: function ($scope, $elm, $attrs, uiGridCtrl) {\n          }\n        };\n      }\n    };\n  }]);\n\n})();\n\n(function () {\n  'use strict';\n\n  /**\n   * @ngdoc overview\n   * @name ui.grid.importer\n   * @description\n   *\n   * # ui.grid.importer\n   *\n   * <div class=\"alert alert-success\" role=\"alert\"><strong>Stable</strong> This feature is stable. There should no longer be breaking api changes without a deprecation warning.</div>\n   *\n   * This module provides the ability to import data into the grid. It\n   * uses the column defs to work out which data belongs in which column,\n   * and creates entities from a configured class (typically a $resource).\n   *\n   * If the rowEdit feature is enabled, it also calls save on those newly\n   * created objects, and then displays any errors in the imported data.\n   *\n   * Currently the importer imports only CSV and json files, although provision has been\n   * made to process other file formats, and these can be added over time.\n   *\n   * For json files, the properties within each object in the json must match the column names\n   * (to put it another way, the importer doesn't process the json, it just copies the objects\n   * within the json into a new instance of the specified object type)\n   *\n   * For CSV import, the default column identification relies on each column in the\n   * header row matching a column.name or column.displayName. Optionally, a column identification\n   * callback can be used.  This allows matching using other attributes, which is particularly\n   * useful if your application has internationalised column headings (i.e. the headings that\n   * the user sees don't match the column names).\n   *\n   * The importer makes use of the grid menu as the UI for requesting an\n   * import.\n   *\n   * <div ui-grid-importer></div>\n   */\n\n  var module = angular.module('ui.grid.importer', ['ui.grid']);\n\n  /**\n   *  @ngdoc object\n   *  @name ui.grid.importer.constant:uiGridImporterConstants\n   *\n   *  @description constants available in importer module\n   */\n\n  module.constant('uiGridImporterConstants', {\n    featureName: 'importer'\n  });\n\n  /**\n   *  @ngdoc service\n   *  @name ui.grid.importer.service:uiGridImporterService\n   *\n   *  @description Services for importer feature\n   */\n  module.service('uiGridImporterService', ['$q', 'uiGridConstants', 'uiGridImporterConstants', 'gridUtil', '$compile', '$interval', 'i18nService', '$window',\n    function ($q, uiGridConstants, uiGridImporterConstants, gridUtil, $compile, $interval, i18nService, $window) {\n\n      var service = {\n\n        initializeGrid: function ($scope, grid) {\n\n          //add feature namespace and any properties to grid for needed state\n          grid.importer = {\n            $scope: $scope\n          };\n\n          this.defaultGridOptions(grid.options);\n\n          /**\n           *  @ngdoc object\n           *  @name ui.grid.importer.api:PublicApi\n           *\n           *  @description Public Api for importer feature\n           */\n          var publicApi = {\n            events: {\n              importer: {\n              }\n            },\n            methods: {\n              importer: {\n                /**\n                 * @ngdoc function\n                 * @name importFile\n                 * @methodOf  ui.grid.importer.api:PublicApi\n                 * @description Imports a file into the grid using the file object\n                 * provided.  Bypasses the grid menu\n                 * @param {File} fileObject the file we want to import, as a javascript\n                 * File object\n                 */\n                importFile: function ( fileObject ) {\n                  service.importThisFile( grid, fileObject );\n                }\n              }\n            }\n          };\n\n          grid.api.registerEventsFromObject(publicApi.events);\n\n          grid.api.registerMethodsFromObject(publicApi.methods);\n\n          if ( grid.options.enableImporter && grid.options.importerShowMenu ){\n            if ( grid.api.core.addToGridMenu ){\n              service.addToMenu( grid );\n            } else {\n              // order of registration is not guaranteed, register in a little while\n              $interval( function() {\n                if (grid.api.core.addToGridMenu){\n                  service.addToMenu( grid );\n                }\n              }, 100, 1);\n            }\n          }\n        },\n\n\n        defaultGridOptions: function (gridOptions) {\n          //default option to true unless it was explicitly set to false\n          /**\n           * @ngdoc object\n           * @name ui.grid.importer.api:GridOptions\n           *\n           * @description GridOptions for importer feature, these are available to be\n           * set using the ui-grid {@link ui.grid.class:GridOptions gridOptions}\n           */\n\n          /**\n           * @ngdoc property\n           * @propertyOf ui.grid.importer.api:GridOptions\n           * @name enableImporter\n           * @description Whether or not importer is enabled.  Automatically set\n           * to false if the user's browser does not support the required fileApi.\n           * Otherwise defaults to true.\n           *\n           */\n          if (gridOptions.enableImporter  || gridOptions.enableImporter === undefined) {\n            if ( !($window.hasOwnProperty('File') && $window.hasOwnProperty('FileReader') && $window.hasOwnProperty('FileList') && $window.hasOwnProperty('Blob')) ) {\n              gridUtil.logError('The File APIs are not fully supported in this browser, grid importer cannot be used.');\n              gridOptions.enableImporter = false;\n            } else {\n              gridOptions.enableImporter = true;\n            }\n          } else {\n            gridOptions.enableImporter = false;\n          }\n\n          /**\n           * @ngdoc method\n           * @name importerProcessHeaders\n           * @methodOf ui.grid.importer.api:GridOptions\n           * @description A callback function that will process headers using custom\n           * logic.  Set this callback function if the headers that your user will provide in their\n           * import file don't necessarily match the grid header or field names.  This might commonly\n           * occur where your application is internationalised, and therefore the field names\n           * that the user recognises are in a different language than the field names that\n           * ui-grid knows about.\n           *\n           * Defaults to the internal `processHeaders` method, which seeks to match using both\n           * displayName and column.name.  Any non-matching columns are discarded.\n           *\n           * Your callback routine should respond by processing the header array, and returning an array\n           * of matching column names.  A null value in any given position means \"don't import this column\"\n           *\n           * <pre>\n           *      gridOptions.importerProcessHeaders: function( headerArray ) {\n           *        var myHeaderColumns = [];\n           *        var thisCol;\n           *        headerArray.forEach( function( value, index ) {\n           *          thisCol = mySpecialLookupFunction( value );\n           *          myHeaderColumns.push( thisCol.name );\n           *        });\n           *\n           *        return myHeaderCols;\n           *      })\n           * </pre>\n           * @param {Grid} grid the grid we're importing into\n           * @param {array} headerArray an array of the text from the first row of the csv file,\n           * which you need to match to column.names\n           * @returns {array} array of matching column names, in the same order as the headerArray\n           *\n           */\n          gridOptions.importerProcessHeaders = gridOptions.importerProcessHeaders || service.processHeaders;\n\n          /**\n           * @ngdoc method\n           * @name importerHeaderFilter\n           * @methodOf ui.grid.importer.api:GridOptions\n           * @description A callback function that will filter (usually translate) a single\n           * header.  Used when you want to match the passed in column names to the column\n           * displayName after the header filter.\n           *\n           * Your callback routine needs to return the filtered header value.\n           * <pre>\n           *      gridOptions.importerHeaderFilter: function( displayName ) {\n           *        return $translate.instant( displayName );\n           *      })\n           * </pre>\n           *\n           * or:\n           * <pre>\n           *      gridOptions.importerHeaderFilter: $translate.instant\n           * </pre>\n           * @param {string} displayName the displayName that we'd like to translate\n           * @returns {string} the translated name\n           *\n           */\n          gridOptions.importerHeaderFilter = gridOptions.importerHeaderFilter || function( displayName ) { return displayName; };\n\n          /**\n           * @ngdoc method\n           * @name importerErrorCallback\n           * @methodOf ui.grid.importer.api:GridOptions\n           * @description A callback function that provides custom error handling, rather\n           * than the standard grid behaviour of an alert box and a console message.  You\n           * might use this to internationalise the console log messages, or to write to a\n           * custom logging routine that returned errors to the server.\n           *\n           * <pre>\n           *      gridOptions.importerErrorCallback: function( grid, errorKey, consoleMessage, context ) {\n           *        myUserDisplayRoutine( errorKey );\n           *        myLoggingRoutine( consoleMessage, context );\n           *      })\n           * </pre>\n           * @param {Grid} grid the grid we're importing into, may be useful if you're positioning messages\n           * in some way\n           * @param {string} errorKey one of the i18n keys the importer can return - importer.noHeaders,\n           * importer.noObjects, importer.invalidCsv, importer.invalidJson, importer.jsonNotArray\n           * @param {string} consoleMessage the English console message that importer would have written\n           * @param {object} context the context data that importer would have appended to that console message,\n           * often the file content itself or the element that is in error\n           *\n           */\n          if ( !gridOptions.importerErrorCallback ||  typeof(gridOptions.importerErrorCallback) !== 'function' ){\n            delete gridOptions.importerErrorCallback;\n          }\n\n          /**\n           * @ngdoc method\n           * @name importerDataAddCallback\n           * @methodOf ui.grid.importer.api:GridOptions\n           * @description A mandatory callback function that adds data to the source data array.  The grid\n           * generally doesn't add rows to the source data array, it is tidier to handle this through a user\n           * callback.\n           *\n           * <pre>\n           *      gridOptions.importerDataAddCallback: function( grid, newObjects ) {\n           *        $scope.myData = $scope.myData.concat( newObjects );\n           *      })\n           * </pre>\n           * @param {Grid} grid the grid we're importing into, may be useful in some way\n           * @param {array} newObjects an array of new objects that you should add to your data\n           *\n           */\n          if ( gridOptions.enableImporter === true && !gridOptions.importerDataAddCallback ) {\n            gridUtil.logError(\"You have not set an importerDataAddCallback, importer is disabled\");\n            gridOptions.enableImporter = false;\n          }\n\n          /**\n           * @ngdoc object\n           * @name importerNewObject\n           * @propertyOf  ui.grid.importer.api:GridOptions\n           * @description An object on which we call `new` to create each new row before inserting it into\n           * the data array.  Typically this would be a $resource entity, which means that if you're using\n           * the rowEdit feature, you can directly call save on this entity when the save event is triggered.\n           *\n           * Defaults to a vanilla javascript object\n           *\n           * @example\n           * <pre>\n           *   gridOptions.importerNewObject = MyRes;\n           * </pre>\n           *\n           */\n\n          /**\n           * @ngdoc property\n           * @propertyOf ui.grid.importer.api:GridOptions\n           * @name importerShowMenu\n           * @description Whether or not to show an item in the grid menu.  Defaults to true.\n           *\n           */\n          gridOptions.importerShowMenu = gridOptions.importerShowMenu !== false;\n\n          /**\n           * @ngdoc method\n           * @methodOf ui.grid.importer.api:GridOptions\n           * @name importerObjectCallback\n           * @description A callback that massages the data for each object.  For example,\n           * you might have data stored as a code value, but display the decode.  This callback\n           * can be used to change the decoded value back into a code.  Defaults to doing nothing.\n           * @param {Grid} grid in case you need it\n           * @param {object} newObject the new object as importer has created it, modify it\n           * then return the modified version\n           * @returns {object} the modified object\n           * @example\n           * <pre>\n           *   gridOptions.importerObjectCallback = function ( grid, newObject ) {\n           *     switch newObject.status {\n           *       case 'Active':\n           *         newObject.status = 1;\n           *         break;\n           *       case 'Inactive':\n           *         newObject.status = 2;\n           *         break;\n           *     }\n           *     return newObject;\n           *   };\n           * </pre>\n           */\n          gridOptions.importerObjectCallback = gridOptions.importerObjectCallback || function( grid, newObject ) { return newObject; };\n        },\n\n\n        /**\n         * @ngdoc function\n         * @name addToMenu\n         * @methodOf  ui.grid.importer.service:uiGridImporterService\n         * @description Adds import menu item to the grid menu,\n         * allowing the user to request import of a file\n         * @param {Grid} grid the grid into which data should be imported\n         */\n        addToMenu: function ( grid ) {\n          grid.api.core.addToGridMenu( grid, [\n            {\n              title: i18nService.getSafeText('gridMenu.importerTitle'),\n              order: 150\n            },\n            {\n              templateUrl: 'ui-grid/importerMenuItemContainer',\n              action: function ($event) {\n                this.grid.api.importer.importAFile( grid );\n              },\n              order: 151\n            }\n          ]);\n        },\n\n\n        /**\n         * @ngdoc function\n         * @name importThisFile\n         * @methodOf ui.grid.importer.service:uiGridImporterService\n         * @description Imports the provided file into the grid using the file object\n         * provided.  Bypasses the grid menu\n         * @param {Grid} grid the grid we're importing into\n         * @param {File} fileObject the file we want to import, as returned from the File\n         * javascript object\n         */\n        importThisFile: function ( grid, fileObject ) {\n          if (!fileObject){\n            gridUtil.logError( 'No file object provided to importThisFile, should be impossible, aborting');\n            return;\n          }\n\n          var reader = new FileReader();\n\n          switch ( fileObject.type ){\n            case 'application/json':\n              reader.onload = service.importJsonClosure( grid );\n              break;\n            default:\n              reader.onload = service.importCsvClosure( grid );\n              break;\n          }\n\n          reader.readAsText( fileObject );\n        },\n\n\n        /**\n         * @ngdoc function\n         * @name importJson\n         * @methodOf ui.grid.importer.service:uiGridImporterService\n         * @description Creates a function that imports a json file into the grid.\n         * The json data is imported into new objects of type `gridOptions.importerNewObject`,\n         * and if the rowEdit feature is enabled the rows are marked as dirty\n         * @param {Grid} grid the grid we want to import into\n         * @param {FileObject} importFile the file that we want to import, as\n         * a FileObject\n         */\n        importJsonClosure: function( grid ) {\n          return function( importFile ){\n            var newObjects = [];\n            var newObject;\n\n            var importArray = service.parseJson( grid, importFile );\n            if (importArray === null){\n              return;\n            }\n            importArray.forEach(  function( value, index ) {\n              newObject = service.newObject( grid );\n              angular.extend( newObject, value );\n              newObject = grid.options.importerObjectCallback( grid, newObject );\n              newObjects.push( newObject );\n            });\n\n            service.addObjects( grid, newObjects );\n\n          };\n        },\n\n\n        /**\n         * @ngdoc function\n         * @name parseJson\n         * @methodOf ui.grid.importer.service:uiGridImporterService\n         * @description Parses a json file, returns the parsed data.\n         * Displays an error if file doesn't parse\n         * @param {Grid} grid the grid that we want to import into\n         * @param {FileObject} importFile the file that we want to import, as\n         * a FileObject\n         * @returns {array} array of objects from the imported json\n         */\n        parseJson: function( grid, importFile ){\n          var loadedObjects;\n          try {\n            loadedObjects = JSON.parse( importFile.target.result );\n          } catch (e) {\n            service.alertError( grid, 'importer.invalidJson', 'File could not be processed, is it valid json? Content was: ', importFile.target.result );\n            return;\n          }\n\n          if ( !Array.isArray( loadedObjects ) ){\n            service.alertError( grid, 'importer.jsonNotarray', 'Import failed, file is not an array, file was: ', importFile.target.result );\n            return [];\n          } else {\n            return loadedObjects;\n          }\n        },\n\n\n\n        /**\n         * @ngdoc function\n         * @name importCsvClosure\n         * @methodOf ui.grid.importer.service:uiGridImporterService\n         * @description Creates a function that imports a csv file into the grid\n         * (allowing it to be used in the reader.onload event)\n         * @param {Grid} grid the grid that we want to import into\n         * @param {FileObject} importFile the file that we want to import, as\n         * a file object\n         */\n        importCsvClosure: function( grid ) {\n          return function( importFile ){\n            var importArray = service.parseCsv( importFile );\n            if ( !importArray || importArray.length < 1 ){\n              service.alertError( grid, 'importer.invalidCsv', 'File could not be processed, is it valid csv? Content was: ', importFile.target.result );\n              return;\n            }\n\n            var newObjects = service.createCsvObjects( grid, importArray );\n            if ( !newObjects || newObjects.length === 0 ){\n              service.alertError( grid, 'importer.noObjects', 'Objects were not able to be derived, content was: ', importFile.target.result );\n              return;\n            }\n\n            service.addObjects( grid, newObjects );\n          };\n        },\n\n\n        /**\n         * @ngdoc function\n         * @name parseCsv\n         * @methodOf ui.grid.importer.service:uiGridImporterService\n         * @description Parses a csv file into an array of arrays, with the first\n         * array being the headers, and the remaining arrays being the data.\n         * The logic for this comes from https://github.com/thetalecrafter/excel.js/blob/master/src/csv.js,\n         * which is noted as being under the MIT license.  The code is modified to pass the jscs yoda condition\n         * checker\n         * @param {FileObject} importFile the file that we want to import, as a\n         * file object\n         */\n        parseCsv: function( importFile ) {\n          var csv = importFile.target.result;\n\n          // use the CSV-JS library to parse\n          return CSV.parse(csv);\n        },\n\n\n        /**\n         * @ngdoc function\n         * @name createCsvObjects\n         * @methodOf ui.grid.importer.service:uiGridImporterService\n         * @description Converts an array of arrays (representing the csv file)\n         * into a set of objects.  Uses the provided `gridOptions.importerNewObject`\n         * to create the objects, and maps the header row into the individual columns\n         * using either `gridOptions.importerProcessHeaders`, or by using a native method\n         * of matching to either the displayName, column name or column field of\n         * the columns in the column defs.  The resulting objects will have attributes\n         * that are named based on the column.field or column.name, in that order.\n         * @param {Grid} grid the grid that we want to import into\n         * @param {Array} importArray the data that we want to import, as an array\n         */\n        createCsvObjects: function( grid, importArray ){\n          // pull off header row and turn into headers\n          var headerMapping = grid.options.importerProcessHeaders( grid, importArray.shift() );\n          if ( !headerMapping || headerMapping.length === 0 ){\n            service.alertError( grid, 'importer.noHeaders', 'Column names could not be derived, content was: ', importArray );\n            return [];\n          }\n\n          var newObjects = [];\n          var newObject;\n          importArray.forEach( function( row, index ) {\n            newObject = service.newObject( grid );\n            if ( row !== null ){\n              row.forEach( function( field, index ){\n                if ( headerMapping[index] !== null ){\n                  newObject[ headerMapping[index] ] = field;\n                }\n              });\n            }\n            newObject = grid.options.importerObjectCallback( grid, newObject );\n            newObjects.push( newObject );\n          });\n\n          return newObjects;\n        },\n\n\n        /**\n         * @ngdoc function\n         * @name processHeaders\n         * @methodOf ui.grid.importer.service:uiGridImporterService\n         * @description Determines the columns that the header row from\n         * a csv (or other) file represents.\n         * @param {Grid} grid the grid we're importing into\n         * @param {array} headerRow the header row that we wish to match against\n         * the column definitions\n         * @returns {array} an array of the attribute names that should be used\n         * for that column, based on matching the headers or creating the headers\n         *\n         */\n        processHeaders: function( grid, headerRow ) {\n          var headers = [];\n          if ( !grid.options.columnDefs || grid.options.columnDefs.length === 0 ){\n            // we are going to create new columnDefs for all these columns, so just remove\n            // spaces from the names to create fields\n            headerRow.forEach( function( value, index ) {\n              headers.push( value.replace( /[^0-9a-zA-Z\\-_]/g, '_' ) );\n            });\n            return headers;\n          } else {\n            var lookupHash = service.flattenColumnDefs( grid, grid.options.columnDefs );\n            headerRow.forEach(  function( value, index ) {\n              if ( lookupHash[value] ) {\n                headers.push( lookupHash[value] );\n              } else if ( lookupHash[ value.toLowerCase() ] ) {\n                headers.push( lookupHash[ value.toLowerCase() ] );\n              } else {\n                headers.push( null );\n              }\n            });\n            return headers;\n          }\n        },\n\n\n        /**\n         * @name flattenColumnDefs\n         * @methodOf ui.grid.importer.service:uiGridImporterService\n         * @description Runs through the column defs and creates a hash of\n         * the displayName, name and field, and of each of those values forced to lower case,\n         * with each pointing to the field or name\n         * (whichever is present).  Used to lookup column headers and decide what\n         * attribute name to give to the resulting field.\n         * @param {Grid} grid the grid we're importing into\n         * @param {array} columnDefs the columnDefs that we should flatten\n         * @returns {hash} the flattened version of the column def information, allowing\n         * us to look up a value by `flattenedHash[ headerValue ]`\n         */\n        flattenColumnDefs: function( grid, columnDefs ){\n          var flattenedHash = {};\n          columnDefs.forEach(  function( columnDef, index) {\n            if ( columnDef.name ){\n              flattenedHash[ columnDef.name ] = columnDef.field || columnDef.name;\n              flattenedHash[ columnDef.name.toLowerCase() ] = columnDef.field || columnDef.name;\n            }\n\n            if ( columnDef.field ){\n              flattenedHash[ columnDef.field ] = columnDef.field || columnDef.name;\n              flattenedHash[ columnDef.field.toLowerCase() ] = columnDef.field || columnDef.name;\n            }\n\n            if ( columnDef.displayName ){\n              flattenedHash[ columnDef.displayName ] = columnDef.field || columnDef.name;\n              flattenedHash[ columnDef.displayName.toLowerCase() ] = columnDef.field || columnDef.name;\n            }\n\n            if ( columnDef.displayName && grid.options.importerHeaderFilter ){\n              flattenedHash[ grid.options.importerHeaderFilter(columnDef.displayName) ] = columnDef.field || columnDef.name;\n              flattenedHash[ grid.options.importerHeaderFilter(columnDef.displayName).toLowerCase() ] = columnDef.field || columnDef.name;\n            }\n          });\n\n          return flattenedHash;\n        },\n\n\n        /**\n         * @ngdoc function\n         * @name addObjects\n         * @methodOf ui.grid.importer.service:uiGridImporterService\n         * @description Inserts our new objects into the grid data, and\n         * sets the rows to dirty if the rowEdit feature is being used\n         *\n         * Does this by registering a watch on dataChanges, which essentially\n         * is waiting on the result of the grid data watch, and downstream processing.\n         *\n         * When the callback is called, it deregisters itself - we don't want to run\n         * again next time data is added.\n         *\n         * If we never get called, we deregister on destroy.\n         *\n         * @param {Grid} grid the grid we're importing into\n         * @param {array} newObjects the objects we want to insert into the grid data\n         * @returns {object} the new object\n         */\n        addObjects: function( grid, newObjects, $scope ){\n          if ( grid.api.rowEdit ){\n            var dataChangeDereg = grid.registerDataChangeCallback( function() {\n              grid.api.rowEdit.setRowsDirty( newObjects );\n              dataChangeDereg();\n            }, [uiGridConstants.dataChange.ROW] );\n\n            grid.importer.$scope.$on( '$destroy', dataChangeDereg );\n          }\n\n          grid.importer.$scope.$apply( grid.options.importerDataAddCallback( grid, newObjects ) );\n\n        },\n\n\n        /**\n         * @ngdoc function\n         * @name newObject\n         * @methodOf ui.grid.importer.service:uiGridImporterService\n         * @description Makes a new object based on `gridOptions.importerNewObject`,\n         * or based on an empty object if not present\n         * @param {Grid} grid the grid we're importing into\n         * @returns {object} the new object\n         */\n        newObject: function( grid ){\n          if ( typeof(grid.options) !== \"undefined\" && typeof(grid.options.importerNewObject) !== \"undefined\" ){\n            return new grid.options.importerNewObject();\n          } else {\n            return {};\n          }\n        },\n\n\n        /**\n         * @ngdoc function\n         * @name alertError\n         * @methodOf ui.grid.importer.service:uiGridImporterService\n         * @description Provides an internationalised user alert for the failure,\n         * and logs a console message including diagnostic content.\n         * Optionally, if the the `gridOptions.importerErrorCallback` routine\n         * is defined, then calls that instead, allowing user specified error routines\n         * @param {Grid} grid the grid we're importing into\n         * @param {array} headerRow the header row that we wish to match against\n         * the column definitions\n         */\n        alertError: function( grid, alertI18nToken, consoleMessage, context ){\n          if ( grid.options.importerErrorCallback ){\n            grid.options.importerErrorCallback( grid, alertI18nToken, consoleMessage, context );\n          } else {\n            $window.alert(i18nService.getSafeText( alertI18nToken ));\n            gridUtil.logError(consoleMessage + context );\n          }\n        }\n      };\n\n      return service;\n\n    }\n  ]);\n\n  /**\n   *  @ngdoc directive\n   *  @name ui.grid.importer.directive:uiGridImporter\n   *  @element div\n   *  @restrict A\n   *\n   *  @description Adds importer features to grid\n   *\n   */\n  module.directive('uiGridImporter', ['uiGridImporterConstants', 'uiGridImporterService', 'gridUtil', '$compile',\n    function (uiGridImporterConstants, uiGridImporterService, gridUtil, $compile) {\n      return {\n        replace: true,\n        priority: 0,\n        require: '^uiGrid',\n        scope: false,\n        link: function ($scope, $elm, $attrs, uiGridCtrl) {\n          uiGridImporterService.initializeGrid($scope, uiGridCtrl.grid);\n        }\n      };\n    }\n  ]);\n\n  /**\n   *  @ngdoc directive\n   *  @name ui.grid.importer.directive:uiGridImporterMenuItem\n   *  @element div\n   *  @restrict A\n   *\n   *  @description Handles the processing from the importer menu item - once a file is\n   *  selected\n   *\n   */\n  module.directive('uiGridImporterMenuItem', ['uiGridImporterConstants', 'uiGridImporterService', 'gridUtil', '$compile',\n    function (uiGridImporterConstants, uiGridImporterService, gridUtil, $compile) {\n      return {\n        replace: true,\n        priority: 0,\n        require: '^uiGrid',\n        scope: false,\n        templateUrl: 'ui-grid/importerMenuItem',\n        link: function ($scope, $elm, $attrs, uiGridCtrl) {\n          var handleFileSelect = function( event ){\n            var target = event.srcElement || event.target;\n\n            if (target && target.files && target.files.length === 1) {\n              var fileObject = target.files[0];\n              uiGridImporterService.importThisFile( grid, fileObject );\n              target.form.reset();\n            }\n          };\n\n          var fileChooser = $elm[0].querySelectorAll('.ui-grid-importer-file-chooser');\n          var grid = uiGridCtrl.grid;\n\n          if ( fileChooser.length !== 1 ){\n            gridUtil.logError('Found > 1 or < 1 file choosers within the menu item, error, cannot continue');\n          } else {\n            fileChooser[0].addEventListener('change', handleFileSelect, false);  // TODO: why the false on the end?  Google\n          }\n        }\n      };\n    }\n  ]);\n})();\n\n(function() {\n  'use strict';\n  /**\n   *  @ngdoc overview\n   *  @name ui.grid.infiniteScroll\n   *\n   *  @description\n   *\n   * #ui.grid.infiniteScroll\n   *\n   * <div class=\"alert alert-warning\" role=\"alert\"><strong>Beta</strong> This feature is ready for testing, but it either hasn't seen a lot of use or has some known bugs.</div>\n   *\n   * This module provides infinite scroll functionality to ui-grid\n   *\n   */\n  var module = angular.module('ui.grid.infiniteScroll', ['ui.grid']);\n  /**\n   *  @ngdoc service\n   *  @name ui.grid.infiniteScroll.service:uiGridInfiniteScrollService\n   *\n   *  @description Service for infinite scroll features\n   */\n  module.service('uiGridInfiniteScrollService', ['gridUtil', '$compile', '$timeout', 'uiGridConstants', 'ScrollEvent', '$q', function (gridUtil, $compile, $timeout, uiGridConstants, ScrollEvent, $q) {\n\n    var service = {\n\n      /**\n       * @ngdoc function\n       * @name initializeGrid\n       * @methodOf ui.grid.infiniteScroll.service:uiGridInfiniteScrollService\n       * @description This method register events and methods into grid public API\n       */\n\n      initializeGrid: function(grid, $scope) {\n        service.defaultGridOptions(grid.options);\n\n        if (!grid.options.enableInfiniteScroll){\n          return;\n        }\n\n        grid.infiniteScroll = { dataLoading: false };\n        service.setScrollDirections( grid, grid.options.infiniteScrollUp, grid.options.infiniteScrollDown );\n          grid.api.core.on.scrollEnd($scope, service.handleScroll);\n\n        /**\n         *  @ngdoc object\n         *  @name ui.grid.infiniteScroll.api:PublicAPI\n         *\n         *  @description Public API for infinite scroll feature\n         */\n        var publicApi = {\n          events: {\n            infiniteScroll: {\n\n              /**\n               * @ngdoc event\n               * @name needLoadMoreData\n               * @eventOf ui.grid.infiniteScroll.api:PublicAPI\n               * @description This event fires when scroll reaches bottom percentage of grid\n               * and needs to load data\n               */\n\n              needLoadMoreData: function ($scope, fn) {\n              },\n\n              /**\n               * @ngdoc event\n               * @name needLoadMoreDataTop\n               * @eventOf ui.grid.infiniteScroll.api:PublicAPI\n               * @description This event fires when scroll reaches top percentage of grid\n               * and needs to load data\n               */\n\n              needLoadMoreDataTop: function ($scope, fn) {\n              }\n            }\n          },\n          methods: {\n            infiniteScroll: {\n\n              /**\n               * @ngdoc function\n               * @name dataLoaded\n               * @methodOf ui.grid.infiniteScroll.api:PublicAPI\n               * @description Call this function when you have loaded the additional data\n               * requested.  You should set scrollUp and scrollDown to indicate\n               * whether there are still more pages in each direction.\n               *\n               * If you call dataLoaded without first calling `saveScrollPercentage` then we will\n               * scroll the user to the start of the newly loaded data, which usually gives a smooth scroll\n               * experience, but can give a jumpy experience with large `infiniteScrollRowsFromEnd` values, and\n               * on variable speed internet connections.  Using `saveScrollPercentage` as demonstrated in the tutorial\n               * should give a smoother scrolling experience for users.\n               *\n               * See infinite_scroll tutorial for example of usage\n               * @param {boolean} scrollUp if set to false flags that there are no more pages upwards, so don't fire\n               * any more infinite scroll events upward\n               * @param {boolean} scrollDown if set to false flags that there are no more pages downwards, so don't\n               * fire any more infinite scroll events downward\n               * @returns {promise} a promise that is resolved when the grid scrolling is fully adjusted.  If you're\n               * planning to remove pages, you should wait on this promise first, or you'll break the scroll positioning\n               */\n              dataLoaded: function( scrollUp, scrollDown ) {\n                service.setScrollDirections(grid, scrollUp, scrollDown);\n\n                var promise = service.adjustScroll(grid).then(function() {\n                  grid.infiniteScroll.dataLoading = false;\n                });\n\n                return promise;\n              },\n\n              /**\n               * @ngdoc function\n               * @name resetScroll\n               * @methodOf ui.grid.infiniteScroll.api:PublicAPI\n               * @description Call this function when you have taken some action that makes the current\n               * scroll position invalid.  For example, if you're using external sorting and you've resorted\n               * then you might reset the scroll, or if you've otherwise substantially changed the data, perhaps\n               * you've reused an existing grid for a new data set\n               *\n               * You must tell us whether there is data upwards or downwards after the reset\n               *\n               * @param {boolean} scrollUp flag that there are pages upwards, fire\n               * infinite scroll events upward\n               * @param {boolean} scrollDown flag that there are pages downwards, so\n               * fire infinite scroll events downward\n               * @returns {promise} promise that is resolved when the scroll reset is complete\n               */\n              resetScroll: function( scrollUp, scrollDown ) {\n                service.setScrollDirections( grid, scrollUp, scrollDown);\n\n                return service.adjustInfiniteScrollPosition(grid, 0);\n              },\n\n\n              /**\n               * @ngdoc function\n               * @name saveScrollPercentage\n               * @methodOf ui.grid.infiniteScroll.api:PublicAPI\n               * @description Saves the scroll percentage and number of visible rows before you adjust the data,\n               * used if you're subsequently going to call `dataRemovedTop` or `dataRemovedBottom`\n               */\n              saveScrollPercentage: function() {\n                grid.infiniteScroll.prevScrollTop = grid.renderContainers.body.prevScrollTop;\n                grid.infiniteScroll.previousVisibleRows = grid.getVisibleRowCount();\n              },\n\n\n              /**\n               * @ngdoc function\n               * @name dataRemovedTop\n               * @methodOf ui.grid.infiniteScroll.api:PublicAPI\n               * @description Adjusts the scroll position after you've removed data at the top\n               * @param {boolean} scrollUp flag that there are pages upwards, fire\n               * infinite scroll events upward\n               * @param {boolean} scrollDown flag that there are pages downwards, so\n               * fire infinite scroll events downward\n               */\n              dataRemovedTop: function( scrollUp, scrollDown ) {\n                service.dataRemovedTop( grid, scrollUp, scrollDown );\n              },\n\n              /**\n               * @ngdoc function\n               * @name dataRemovedBottom\n               * @methodOf ui.grid.infiniteScroll.api:PublicAPI\n               * @description Adjusts the scroll position after you've removed data at the bottom\n               * @param {boolean} scrollUp flag that there are pages upwards, fire\n               * infinite scroll events upward\n               * @param {boolean} scrollDown flag that there are pages downwards, so\n               * fire infinite scroll events downward\n               */\n              dataRemovedBottom: function( scrollUp, scrollDown ) {\n                service.dataRemovedBottom( grid, scrollUp, scrollDown );\n              },\n\n              /**\n               * @ngdoc function\n               * @name setScrollDirections\n               * @methodOf ui.grid.infiniteScroll.service:uiGridInfiniteScrollService\n               * @description Sets the scrollUp and scrollDown flags, handling nulls and undefined,\n               * and also sets the grid.suppressParentScroll\n               * @param {boolean} scrollUp whether there are pages available up - defaults to false\n               * @param {boolean} scrollDown whether there are pages available down - defaults to true\n               */\n              setScrollDirections:  function ( scrollUp, scrollDown ) {\n                service.setScrollDirections( grid, scrollUp, scrollDown );\n              }\n\n            }\n          }\n        };\n        grid.api.registerEventsFromObject(publicApi.events);\n        grid.api.registerMethodsFromObject(publicApi.methods);\n      },\n\n\n      defaultGridOptions: function (gridOptions) {\n        //default option to true unless it was explicitly set to false\n        /**\n         *  @ngdoc object\n         *  @name ui.grid.infiniteScroll.api:GridOptions\n         *\n         *  @description GridOptions for infinite scroll feature, these are available to be\n         *  set using the ui-grid {@link ui.grid.class:GridOptions gridOptions}\n         */\n\n        /**\n         *  @ngdoc object\n         *  @name enableInfiniteScroll\n         *  @propertyOf  ui.grid.infiniteScroll.api:GridOptions\n         *  @description Enable infinite scrolling for this grid\n         *  <br/>Defaults to true\n         */\n        gridOptions.enableInfiniteScroll = gridOptions.enableInfiniteScroll !== false;\n\n        /**\n         * @ngdoc property\n         * @name infiniteScrollRowsFromEnd\n         * @propertyOf ui.grid.class:GridOptions\n         * @description This setting controls how close to the end of the dataset a user gets before\n         * more data is requested by the infinite scroll, whether scrolling up or down.  This allows you to\n         * 'prefetch' rows before the user actually runs out of scrolling.\n         *\n         * Note that if you set this value too high it may give jumpy scrolling behaviour, if you're getting\n         * this behaviour you could use the `saveScrollPercentageMethod` right before loading your data, and we'll\n         * preserve that scroll position\n         *\n         * <br> Defaults to 20\n         */\n        gridOptions.infiniteScrollRowsFromEnd = gridOptions.infiniteScrollRowsFromEnd || 20;\n\n        /**\n         * @ngdoc property\n         * @name infiniteScrollUp\n         * @propertyOf ui.grid.class:GridOptions\n         * @description Whether you allow infinite scroll up, implying that the first page of data\n         * you have displayed is in the middle of your data set.  If set to true then we trigger the\n         * needMoreDataTop event when the user hits the top of the scrollbar.\n         * <br> Defaults to false\n         */\n        gridOptions.infiniteScrollUp = gridOptions.infiniteScrollUp === true;\n\n        /**\n         * @ngdoc property\n         * @name infiniteScrollDown\n         * @propertyOf ui.grid.class:GridOptions\n         * @description Whether you allow infinite scroll down, implying that the first page of data\n         * you have displayed is in the middle of your data set.  If set to true then we trigger the\n         * needMoreData event when the user hits the bottom of the scrollbar.\n         * <br> Defaults to true\n         */\n        gridOptions.infiniteScrollDown = gridOptions.infiniteScrollDown !== false;\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name setScrollDirections\n       * @methodOf ui.grid.infiniteScroll.service:uiGridInfiniteScrollService\n       * @description Sets the scrollUp and scrollDown flags, handling nulls and undefined,\n       * and also sets the grid.suppressParentScroll\n       * @param {grid} grid the grid we're operating on\n       * @param {boolean} scrollUp whether there are pages available up - defaults to false\n       * @param {boolean} scrollDown whether there are pages available down - defaults to true\n       */\n      setScrollDirections:  function ( grid, scrollUp, scrollDown ) {\n        grid.infiniteScroll.scrollUp = ( scrollUp === true );\n        grid.suppressParentScrollUp = ( scrollUp === true );\n\n        grid.infiniteScroll.scrollDown = ( scrollDown !== false);\n        grid.suppressParentScrollDown = ( scrollDown !== false);\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name handleScroll\n       * @methodOf ui.grid.infiniteScroll.service:uiGridInfiniteScrollService\n       * @description Called whenever the grid scrolls, determines whether the scroll should\n       * trigger an infinite scroll request for more data\n       * @param {object} args the args from the event\n       */\n      handleScroll:  function (args) {\n        // don't request data if already waiting for data, or if source is coming from ui.grid.adjustInfiniteScrollPosition() function\n        if ( args.grid.infiniteScroll && args.grid.infiniteScroll.dataLoading || args.source === 'ui.grid.adjustInfiniteScrollPosition' ){\n          return;\n        }\n\n        if (args.y) {\n\n          // If the user is scrolling very quickly all the way to the top/bottom, the scroll handler can get confused\n          // about the direction. First we check if they've gone all the way, and data always is loaded in this case.\n          if (args.y.percentage === 0) {\n            args.grid.scrollDirection = uiGridConstants.scrollDirection.UP;\n            service.loadData(args.grid);\n          } else if (args.y.percentage === 1) {\n            args.grid.scrollDirection = uiGridConstants.scrollDirection.DOWN;\n            service.loadData(args.grid);\n          } else { // Scroll position is somewhere in between top/bottom, so determine whether it's far enough to load more data.\n            var percentage;\n            var targetPercentage = args.grid.options.infiniteScrollRowsFromEnd / args.grid.renderContainers.body.visibleRowCache.length;\n            if (args.grid.scrollDirection === uiGridConstants.scrollDirection.UP ) {\n              percentage = args.y.percentage;\n              if (percentage <= targetPercentage){\n                service.loadData(args.grid);\n              }\n            } else if (args.grid.scrollDirection === uiGridConstants.scrollDirection.DOWN) {\n              percentage = 1 - args.y.percentage;\n              if (percentage <= targetPercentage){\n                service.loadData(args.grid);\n              }\n            }\n          }\n        }\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name loadData\n       * @methodOf ui.grid.infiniteScroll.service:uiGridInfiniteScrollService\n       * @description This function fires 'needLoadMoreData' or 'needLoadMoreDataTop' event based on scrollDirection\n       * and whether there are more pages upwards or downwards.  It also stores the number of rows that we had previously,\n       * and clears out any saved scroll position so that we know whether or not the user calls `saveScrollPercentage`\n       * @param {Grid} grid the grid we're working on\n       */\n      loadData: function (grid) {\n        // save number of currently visible rows to calculate new scroll position later - we know that we want\n        // to be at approximately the row we're currently at\n        grid.infiniteScroll.previousVisibleRows = grid.renderContainers.body.visibleRowCache.length;\n        grid.infiniteScroll.direction = grid.scrollDirection;\n        delete grid.infiniteScroll.prevScrollTop;\n\n        if (grid.scrollDirection === uiGridConstants.scrollDirection.UP && grid.infiniteScroll.scrollUp ) {\n          grid.infiniteScroll.dataLoading = true;\n          grid.api.infiniteScroll.raise.needLoadMoreDataTop();\n        } else if (grid.scrollDirection === uiGridConstants.scrollDirection.DOWN && grid.infiniteScroll.scrollDown ) {\n          grid.infiniteScroll.dataLoading = true;\n          grid.api.infiniteScroll.raise.needLoadMoreData();\n        }\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name adjustScroll\n       * @methodOf ui.grid.infiniteScroll.service:uiGridInfiniteScrollService\n       * @description Once we are informed that data has been loaded, adjust the scroll position to account for that\n       * addition and to make things look clean.\n       *\n       * If we're scrolling up we scroll to the first row of the old data set -\n       * so we're assuming that you would have gotten to the top of the grid (from the 20% need more data trigger) by\n       * the time the data comes back.  If we're scrolling down we scoll to the last row of the old data set - so we're\n       * assuming that you would have gotten to the bottom of the grid (from the 80% need more data trigger) by the time\n       * the data comes back.\n       *\n       * Neither of these are good assumptions, but making this a smoother experience really requires\n       * that trigger to not be a percentage, and to be much closer to the end of the data (say, 5 rows off the end).  Even then\n       * it'd be better still to actually run into the end.  But if the data takes a while to come back, they may have scrolled\n       * somewhere else in the mean-time, in which case they'll get a jump back to the new data.  Anyway, this will do for\n       * now, until someone wants to do better.\n       * @param {Grid} grid the grid we're working on\n       * @returns {promise} a promise that is resolved when scrolling has finished\n       */\n      adjustScroll: function(grid){\n        var promise = $q.defer();\n        $timeout(function () {\n          var newPercentage, viewportHeight, rowHeight, newVisibleRows, oldTop, newTop;\n\n          viewportHeight = grid.getViewportHeight() + grid.headerHeight - grid.renderContainers.body.headerHeight - grid.scrollbarHeight;\n          rowHeight = grid.options.rowHeight;\n\n          if ( grid.infiniteScroll.direction === undefined ){\n            // called from initialize, tweak our scroll up a little\n            service.adjustInfiniteScrollPosition(grid, 0);\n          }\n\n          newVisibleRows = grid.getVisibleRowCount();\n\n          // in case not enough data is loaded to enable scroller - load more data\n          var canvasHeight = rowHeight * newVisibleRows;\n          if (grid.infiniteScroll.scrollDown && (viewportHeight > canvasHeight)) {\n            grid.api.infiniteScroll.raise.needLoadMoreData();\n          }\n\n          if ( grid.infiniteScroll.direction === uiGridConstants.scrollDirection.UP ){\n            oldTop = grid.infiniteScroll.prevScrollTop || 0;\n            newTop = oldTop + (newVisibleRows - grid.infiniteScroll.previousVisibleRows)*rowHeight;\n            service.adjustInfiniteScrollPosition(grid, newTop);\n            $timeout( function() {\n              promise.resolve();\n            });\n          }\n\n          if ( grid.infiniteScroll.direction === uiGridConstants.scrollDirection.DOWN ){\n            newTop = grid.infiniteScroll.prevScrollTop || (grid.infiniteScroll.previousVisibleRows*rowHeight - viewportHeight);\n            service.adjustInfiniteScrollPosition(grid, newTop);\n            $timeout( function() {\n              promise.resolve();\n            });\n          }\n        }, 0);\n\n        return promise.promise;\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name adjustInfiniteScrollPosition\n       * @methodOf ui.grid.infiniteScroll.service:uiGridInfiniteScrollService\n       * @description This function fires 'needLoadMoreData' or 'needLoadMoreDataTop' event based on scrollDirection\n       * @param {Grid} grid the grid we're working on\n       * @param {number} scrollTop the position through the grid that we want to scroll to\n       * @returns {promise} a promise that is resolved when the scrolling finishes\n       */\n      adjustInfiniteScrollPosition: function (grid, scrollTop) {\n        var scrollEvent = new ScrollEvent(grid, null, null, 'ui.grid.adjustInfiniteScrollPosition'),\n          visibleRows = grid.getVisibleRowCount(),\n          viewportHeight = grid.getViewportHeight() + grid.headerHeight - grid.renderContainers.body.headerHeight - grid.scrollbarHeight,\n          rowHeight = grid.options.rowHeight,\n          scrollHeight = visibleRows*rowHeight-viewportHeight;\n\n        //for infinite scroll, if there are pages upwards then never allow it to be at the zero position so the up button can be active\n        if (scrollTop === 0 && grid.infiniteScroll.scrollUp) {\n          // using pixels results in a relative scroll, hence we have to use percentage\n          scrollEvent.y = {percentage: 1/scrollHeight};\n        }\n        else {\n          scrollEvent.y = {percentage: scrollTop/scrollHeight};\n        }\n        grid.scrollContainers('', scrollEvent);\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name dataRemovedTop\n       * @methodOf ui.grid.infiniteScroll.api:PublicAPI\n       * @description Adjusts the scroll position after you've removed data at the top. You should\n       * have called `saveScrollPercentage` before you remove the data, and if you're doing this in\n       * response to a `needMoreData` you should wait until the promise from `loadData` has resolved\n       * before you start removing data\n       * @param {Grid} grid the grid we're working on\n       * @param {boolean} scrollUp flag that there are pages upwards, fire\n       * infinite scroll events upward\n       * @param {boolean} scrollDown flag that there are pages downwards, so\n       * fire infinite scroll events downward\n       * @returns {promise} a promise that is resolved when the scrolling finishes\n       */\n      dataRemovedTop: function( grid, scrollUp, scrollDown ) {\n        var newVisibleRows, oldTop, newTop, rowHeight;\n        service.setScrollDirections( grid, scrollUp, scrollDown );\n\n        newVisibleRows = grid.renderContainers.body.visibleRowCache.length;\n        oldTop = grid.infiniteScroll.prevScrollTop;\n        rowHeight = grid.options.rowHeight;\n\n        // since we removed from the top, our new scroll row will be the old scroll row less the number\n        // of rows removed\n        newTop = oldTop - ( grid.infiniteScroll.previousVisibleRows - newVisibleRows )*rowHeight;\n\n        return service.adjustInfiniteScrollPosition( grid, newTop );\n      },\n\n      /**\n       * @ngdoc function\n       * @name dataRemovedBottom\n       * @methodOf ui.grid.infiniteScroll.api:PublicAPI\n       * @description Adjusts the scroll position after you've removed data at the bottom.  You should\n       * have called `saveScrollPercentage` before you remove the data, and if you're doing this in\n       * response to a `needMoreData` you should wait until the promise from `loadData` has resolved\n       * before you start removing data\n       * @param {Grid} grid the grid we're working on\n       * @param {boolean} scrollUp flag that there are pages upwards, fire\n       * infinite scroll events upward\n       * @param {boolean} scrollDown flag that there are pages downwards, so\n       * fire infinite scroll events downward\n       */\n      dataRemovedBottom: function( grid, scrollUp, scrollDown ) {\n        var newTop;\n        service.setScrollDirections( grid, scrollUp, scrollDown );\n\n        newTop = grid.infiniteScroll.prevScrollTop;\n\n        return service.adjustInfiniteScrollPosition( grid, newTop );\n      }\n    };\n    return service;\n  }]);\n  /**\n   *  @ngdoc directive\n   *  @name ui.grid.infiniteScroll.directive:uiGridInfiniteScroll\n   *  @element div\n   *  @restrict A\n   *\n   *  @description Adds infinite scroll features to grid\n   *\n   *  @example\n   <example module=\"app\">\n   <file name=\"app.js\">\n   var app = angular.module('app', ['ui.grid', 'ui.grid.infiniteScroll']);\n\n   app.controller('MainCtrl', ['$scope', function ($scope) {\n      $scope.data = [\n        { name: 'Alex', car: 'Toyota' },\n            { name: 'Sam', car: 'Lexus' }\n      ];\n\n      $scope.columnDefs = [\n        {name: 'name'},\n        {name: 'car'}\n      ];\n    }]);\n   </file>\n   <file name=\"index.html\">\n   <div ng-controller=\"MainCtrl\">\n   <div ui-grid=\"{ data: data, columnDefs: columnDefs }\" ui-grid-infinite-scroll=\"20\"></div>\n   </div>\n   </file>\n   </example>\n   */\n\n  module.directive('uiGridInfiniteScroll', ['uiGridInfiniteScrollService',\n    function (uiGridInfiniteScrollService) {\n      return {\n        priority: -200,\n        scope: false,\n        require: '^uiGrid',\n        compile: function($scope, $elm, $attr){\n          return {\n            pre: function($scope, $elm, $attr, uiGridCtrl) {\n              uiGridInfiniteScrollService.initializeGrid(uiGridCtrl.grid, $scope);\n            },\n            post: function($scope, $elm, $attr) {\n            }\n          };\n        }\n      };\n    }]);\n\n})();\n\n(function () {\n  'use strict';\n\n  /**\n   * @ngdoc overview\n   * @name ui.grid.moveColumns\n   * @description\n   *\n   * # ui.grid.moveColumns\n   *\n   * <div class=\"alert alert-warning\" role=\"alert\"><strong>Alpha</strong> This feature is in development. There will almost certainly be breaking api changes, or there are major outstanding bugs.</div>\n   *\n   * This module provides column moving capability to ui.grid. It enables to change the position of columns.\n   * <div doc-module-components=\"ui.grid.moveColumns\"></div>\n   */\n  var module = angular.module('ui.grid.moveColumns', ['ui.grid']);\n\n  /**\n   *  @ngdoc service\n   *  @name ui.grid.moveColumns.service:uiGridMoveColumnService\n   *  @description Service for column moving feature.\n   */\n  module.service('uiGridMoveColumnService', ['$q', '$timeout', '$log', 'ScrollEvent', 'uiGridConstants', 'gridUtil', function ($q, $timeout, $log, ScrollEvent, uiGridConstants, gridUtil) {\n\n    var service = {\n      initializeGrid: function (grid) {\n        var self = this;\n        this.registerPublicApi(grid);\n        this.defaultGridOptions(grid.options);\n        grid.moveColumns = {orderCache: []}; // Used to cache the order before columns are rebuilt\n        grid.registerColumnBuilder(self.movableColumnBuilder);\n        grid.registerDataChangeCallback(self.verifyColumnOrder, [uiGridConstants.dataChange.COLUMN]);\n      },\n      registerPublicApi: function (grid) {\n        var self = this;\n        /**\n         *  @ngdoc object\n         *  @name ui.grid.moveColumns.api:PublicApi\n         *  @description Public Api for column moving feature.\n         */\n        var publicApi = {\n          events: {\n            /**\n             * @ngdoc event\n             * @name columnPositionChanged\n             * @eventOf  ui.grid.moveColumns.api:PublicApi\n             * @description raised when column is moved\n             * <pre>\n             *      gridApi.colMovable.on.columnPositionChanged(scope,function(colDef, originalPosition, newPosition){})\n             * </pre>\n             * @param {object} colDef the column that was moved\n             * @param {integer} originalPosition of the column\n             * @param {integer} finalPosition of the column\n             */\n            colMovable: {\n              columnPositionChanged: function (colDef, originalPosition, newPosition) {\n              }\n            }\n          },\n          methods: {\n            /**\n             * @ngdoc method\n             * @name moveColumn\n             * @methodOf  ui.grid.moveColumns.api:PublicApi\n             * @description Method can be used to change column position.\n             * <pre>\n             *      gridApi.colMovable.moveColumn(oldPosition, newPosition)\n             * </pre>\n             * @param {integer} originalPosition of the column\n             * @param {integer} finalPosition of the column\n             */\n            colMovable: {\n              moveColumn: function (originalPosition, finalPosition) {\n                var columns = grid.columns;\n                if (!angular.isNumber(originalPosition) || !angular.isNumber(finalPosition)) {\n                  gridUtil.logError('MoveColumn: Please provide valid values for originalPosition and finalPosition');\n                  return;\n                }\n                var nonMovableColumns = 0;\n                for (var i = 0; i < columns.length; i++) {\n                  if ((angular.isDefined(columns[i].colDef.visible) && columns[i].colDef.visible === false) || columns[i].isRowHeader === true) {\n                    nonMovableColumns++;\n                  }\n                }\n                if (originalPosition >= (columns.length - nonMovableColumns) || finalPosition >= (columns.length - nonMovableColumns)) {\n                  gridUtil.logError('MoveColumn: Invalid values for originalPosition, finalPosition');\n                  return;\n                }\n                var findPositionForRenderIndex = function (index) {\n                  var position = index;\n                  for (var i = 0; i <= position; i++) {\n                    if (angular.isDefined(columns[i]) && ((angular.isDefined(columns[i].colDef.visible) && columns[i].colDef.visible === false) || columns[i].isRowHeader === true)) {\n                      position++;\n                    }\n                  }\n                  return position;\n                };\n                self.redrawColumnAtPosition(grid, findPositionForRenderIndex(originalPosition), findPositionForRenderIndex(finalPosition));\n              }\n            }\n          }\n        };\n        grid.api.registerEventsFromObject(publicApi.events);\n        grid.api.registerMethodsFromObject(publicApi.methods);\n      },\n      defaultGridOptions: function (gridOptions) {\n        /**\n         *  @ngdoc object\n         *  @name ui.grid.moveColumns.api:GridOptions\n         *\n         *  @description Options for configuring the move column feature, these are available to be\n         *  set using the ui-grid {@link ui.grid.class:GridOptions gridOptions}\n         */\n        /**\n         *  @ngdoc object\n         *  @name enableColumnMoving\n         *  @propertyOf  ui.grid.moveColumns.api:GridOptions\n         *  @description If defined, sets the default value for the colMovable flag on each individual colDefs\n         *  if their individual enableColumnMoving configuration is not defined. Defaults to true.\n         */\n        gridOptions.enableColumnMoving = gridOptions.enableColumnMoving !== false;\n      },\n      movableColumnBuilder: function (colDef, col, gridOptions) {\n        var promises = [];\n        /**\n         *  @ngdoc object\n         *  @name ui.grid.moveColumns.api:ColumnDef\n         *\n         *  @description Column Definition for move column feature, these are available to be\n         *  set using the ui-grid {@link ui.grid.class:GridOptions.columnDef gridOptions.columnDefs}\n         */\n        /**\n         *  @ngdoc object\n         *  @name enableColumnMoving\n         *  @propertyOf  ui.grid.moveColumns.api:ColumnDef\n         *  @description Enable column moving for the column.\n         */\n        colDef.enableColumnMoving = colDef.enableColumnMoving === undefined ? gridOptions.enableColumnMoving\n          : colDef.enableColumnMoving;\n        return $q.all(promises);\n      },\n      /**\n       * @ngdoc method\n       * @name updateColumnCache\n       * @methodOf  ui.grid.moveColumns\n       * @description Cache the current order of columns, so we can restore them after new columnDefs are defined\n       */\n      updateColumnCache: function(grid){\n        grid.moveColumns.orderCache = grid.getOnlyDataColumns();\n      },\n      /**\n       * @ngdoc method\n       * @name verifyColumnOrder\n       * @methodOf  ui.grid.moveColumns\n       * @description dataChangeCallback which uses the cached column order to restore the column order\n       * when it is reset by altering the columnDefs array.\n       */\n      verifyColumnOrder: function(grid){\n        var headerRowOffset = grid.rowHeaderColumns.length;\n        var newIndex;\n\n        angular.forEach(grid.moveColumns.orderCache, function(cacheCol, cacheIndex){\n          newIndex = grid.columns.indexOf(cacheCol);\n          if ( newIndex !== -1 && newIndex - headerRowOffset !== cacheIndex ){\n            var column = grid.columns.splice(newIndex, 1)[0];\n            grid.columns.splice(cacheIndex + headerRowOffset, 0, column);\n          }\n        });\n      },\n      redrawColumnAtPosition: function (grid, originalPosition, newPosition) {\n        var columns = grid.columns;\n\n        if (originalPosition === newPosition) {\n          return;\n        }\n\n        //check columns in between move-range to make sure they are visible columns\n        var pos = (originalPosition < newPosition) ? originalPosition + 1 : originalPosition - 1;\n        var i0 = Math.min(pos, newPosition);\n        for (i0; i0 <= Math.max(pos, newPosition); i0++) {\n          if (columns[i0].visible) {\n            break;\n          }\n        }\n        if (i0 > Math.max(pos, newPosition)) {\n          //no visible column found, column did not visibly move\n          return;\n        }\n\n        var originalColumn = columns[originalPosition];\n        if (originalColumn.colDef.enableColumnMoving) {\n          if (originalPosition > newPosition) {\n            for (var i1 = originalPosition; i1 > newPosition; i1--) {\n              columns[i1] = columns[i1 - 1];\n            }\n          }\n          else if (newPosition > originalPosition) {\n            for (var i2 = originalPosition; i2 < newPosition; i2++) {\n              columns[i2] = columns[i2 + 1];\n            }\n          }\n          columns[newPosition] = originalColumn;\n          service.updateColumnCache(grid);\n          grid.queueGridRefresh();\n          $timeout(function () {\n            grid.api.core.notifyDataChange( uiGridConstants.dataChange.COLUMN );\n            grid.api.colMovable.raise.columnPositionChanged(originalColumn.colDef, originalPosition, newPosition);\n          });\n        }\n      }\n    };\n    return service;\n  }]);\n\n  /**\n   *  @ngdoc directive\n   *  @name ui.grid.moveColumns.directive:uiGridMoveColumns\n   *  @element div\n   *  @restrict A\n   *  @description Adds column moving features to the ui-grid directive.\n   *  @example\n   <example module=\"app\">\n   <file name=\"app.js\">\n   var app = angular.module('app', ['ui.grid', 'ui.grid.moveColumns']);\n   app.controller('MainCtrl', ['$scope', function ($scope) {\n        $scope.data = [\n          { name: 'Bob', title: 'CEO', age: 45 },\n          { name: 'Frank', title: 'Lowly Developer', age: 25 },\n          { name: 'Jenny', title: 'Highly Developer', age: 35 }\n        ];\n        $scope.columnDefs = [\n          {name: 'name'},\n          {name: 'title'},\n          {name: 'age'}\n        ];\n      }]);\n   </file>\n   <file name=\"main.css\">\n   .grid {\n      width: 100%;\n      height: 150px;\n    }\n   </file>\n   <file name=\"index.html\">\n   <div ng-controller=\"MainCtrl\">\n   <div class=\"grid\" ui-grid=\"{ data: data, columnDefs: columnDefs }\" ui-grid-move-columns></div>\n   </div>\n   </file>\n   </example>\n   */\n  module.directive('uiGridMoveColumns', ['uiGridMoveColumnService', function (uiGridMoveColumnService) {\n    return {\n      replace: true,\n      priority: 0,\n      require: '^uiGrid',\n      scope: false,\n      compile: function () {\n        return {\n          pre: function ($scope, $elm, $attrs, uiGridCtrl) {\n            uiGridMoveColumnService.initializeGrid(uiGridCtrl.grid);\n          },\n          post: function ($scope, $elm, $attrs, uiGridCtrl) {\n          }\n        };\n      }\n    };\n  }]);\n\n  /**\n   *  @ngdoc directive\n   *  @name ui.grid.moveColumns.directive:uiGridHeaderCell\n   *  @element div\n   *  @restrict A\n   *\n   *  @description Stacks on top of ui.grid.uiGridHeaderCell to provide capability to be able to move it to reposition column.\n   *\n   *  On receiving mouseDown event headerCell is cloned, now as the mouse moves the cloned header cell also moved in the grid.\n   *  In case the moving cloned header cell reaches the left or right extreme of grid, grid scrolling is triggered (if horizontal scroll exists).\n   *  On mouseUp event column is repositioned at position where mouse is released and cloned header cell is removed.\n   *\n   *  Events that invoke cloning of header cell:\n   *    - mousedown\n   *\n   *  Events that invoke movement of cloned header cell:\n   *    - mousemove\n   *\n   *  Events that invoke repositioning of column:\n   *    - mouseup\n   */\n  module.directive('uiGridHeaderCell', ['$q', 'gridUtil', 'uiGridMoveColumnService', '$document', '$log', 'uiGridConstants', 'ScrollEvent',\n    function ($q, gridUtil, uiGridMoveColumnService, $document, $log, uiGridConstants, ScrollEvent) {\n      return {\n        priority: -10,\n        require: '^uiGrid',\n        compile: function () {\n          return {\n            post: function ($scope, $elm, $attrs, uiGridCtrl) {\n\n              if ($scope.col.colDef.enableColumnMoving) {\n\n                /*\n                 * Our general approach to column move is that we listen to a touchstart or mousedown\n                 * event over the column header.  When we hear one, then we wait for a move of the same type\n                 * - if we are a touchstart then we listen for a touchmove, if we are a mousedown we listen for\n                 * a mousemove (i.e. a drag) before we decide that there's a move underway.  If there's never a move,\n                 * and we instead get a mouseup or a touchend, then we just drop out again and do nothing.\n                 *\n                 */\n                var $contentsElm = angular.element( $elm[0].querySelectorAll('.ui-grid-cell-contents') );\n\n                var gridLeft;\n                var previousMouseX;\n                var totalMouseMovement;\n                var rightMoveLimit;\n                var elmCloned = false;\n                var movingElm;\n                var reducedWidth;\n                var moveOccurred = false;\n\n                var downFn = function( event ){\n                  //Setting some variables required for calculations.\n                  gridLeft = $scope.grid.element[0].getBoundingClientRect().left;\n                  if ( $scope.grid.hasLeftContainer() ){\n                    gridLeft += $scope.grid.renderContainers.left.header[0].getBoundingClientRect().width;\n                  }\n\n                  previousMouseX = event.pageX || (event.originalEvent ? event.originalEvent.pageX : 0);\n                  totalMouseMovement = 0;\n                  rightMoveLimit = gridLeft + $scope.grid.getViewportWidth();\n\n                  if ( event.type === 'mousedown' ){\n                    $document.on('mousemove', moveFn);\n                    $document.on('mouseup', upFn);\n                  } else if ( event.type === 'touchstart' ){\n                    $document.on('touchmove', moveFn);\n                    $document.on('touchend', upFn);\n                  }\n                };\n\n                var moveFn = function( event ) {\n                  var pageX = event.pageX || (event.originalEvent ? event.originalEvent.pageX : 0);\n                  var changeValue = pageX - previousMouseX;\n                  if ( changeValue === 0 ){ return; }\n                  //Disable text selection in Chrome during column move\n                  document.onselectstart = function() { return false; };\n\n                  moveOccurred = true;\n\n                  if (!elmCloned) {\n                    cloneElement();\n                  }\n                  else if (elmCloned) {\n                    moveElement(changeValue);\n                    previousMouseX = pageX;\n                  }\n                };\n\n                var upFn = function( event ){\n                  //Re-enable text selection after column move\n                  document.onselectstart = null;\n\n                  //Remove the cloned element on mouse up.\n                  if (movingElm) {\n                    movingElm.remove();\n                    elmCloned = false;\n                  }\n\n                  offAllEvents();\n                  onDownEvents();\n\n                  if (!moveOccurred){\n                    return;\n                  }\n\n                  var columns = $scope.grid.columns;\n                  var columnIndex = 0;\n                  for (var i = 0; i < columns.length; i++) {\n                    if (columns[i].colDef.name !== $scope.col.colDef.name) {\n                      columnIndex++;\n                    }\n                    else {\n                      break;\n                    }\n                  }\n\n                  var targetIndex;\n\n                  //Case where column should be moved to a position on its left\n                  if (totalMouseMovement < 0) {\n                    var totalColumnsLeftWidth = 0;\n                    var il;\n                    if ( $scope.grid.isRTL() ){\n                      for (il = columnIndex + 1; il < columns.length; il++) {\n                        if (angular.isUndefined(columns[il].colDef.visible) || columns[il].colDef.visible === true) {\n                          totalColumnsLeftWidth += columns[il].drawnWidth || columns[il].width || columns[il].colDef.width;\n                          if (totalColumnsLeftWidth > Math.abs(totalMouseMovement)) {\n                            uiGridMoveColumnService.redrawColumnAtPosition\n                            ($scope.grid, columnIndex, il - 1);\n                            break;\n                          }\n                        }\n                      }\n                    }\n                    else {\n                      for (il = columnIndex - 1; il >= 0; il--) {\n                        if (angular.isUndefined(columns[il].colDef.visible) || columns[il].colDef.visible === true) {\n                          totalColumnsLeftWidth += columns[il].drawnWidth || columns[il].width || columns[il].colDef.width;\n                          if (totalColumnsLeftWidth > Math.abs(totalMouseMovement)) {\n                            uiGridMoveColumnService.redrawColumnAtPosition\n                            ($scope.grid, columnIndex, il + 1);\n                            break;\n                          }\n                        }\n                      }\n                    }\n\n                    //Case where column should be moved to beginning (or end in RTL) of the grid.\n                    if (totalColumnsLeftWidth < Math.abs(totalMouseMovement)) {\n                      targetIndex = 0;\n                      if ( $scope.grid.isRTL() ){\n                        targetIndex = columns.length - 1;\n                      }\n                      uiGridMoveColumnService.redrawColumnAtPosition\n                      ($scope.grid, columnIndex, targetIndex);\n                    }\n                  }\n\n                  //Case where column should be moved to a position on its right\n                  else if (totalMouseMovement > 0) {\n                    var totalColumnsRightWidth = 0;\n                    var ir;\n                    if ( $scope.grid.isRTL() ){\n                      for (ir = columnIndex - 1; ir > 0; ir--) {\n                        if (angular.isUndefined(columns[ir].colDef.visible) || columns[ir].colDef.visible === true) {\n                          totalColumnsRightWidth += columns[ir].drawnWidth || columns[ir].width || columns[ir].colDef.width;\n                          if (totalColumnsRightWidth > totalMouseMovement) {\n                            uiGridMoveColumnService.redrawColumnAtPosition\n                            ($scope.grid, columnIndex, ir);\n                            break;\n                          }\n                        }\n                      }\n                    }\n                    else {\n                      for (ir = columnIndex + 1; ir < columns.length; ir++) {\n                        if (angular.isUndefined(columns[ir].colDef.visible) || columns[ir].colDef.visible === true) {\n                          totalColumnsRightWidth += columns[ir].drawnWidth || columns[ir].width || columns[ir].colDef.width;\n                          if (totalColumnsRightWidth > totalMouseMovement) {\n                            uiGridMoveColumnService.redrawColumnAtPosition\n                            ($scope.grid, columnIndex, ir - 1);\n                            break;\n                          }\n                        }\n                      }\n                    }\n\n\n                    //Case where column should be moved to end (or beginning in RTL) of the grid.\n                    if (totalColumnsRightWidth < totalMouseMovement) {\n                      targetIndex = columns.length - 1;\n                      if ( $scope.grid.isRTL() ){\n                        targetIndex = 0;\n                      }\n                      uiGridMoveColumnService.redrawColumnAtPosition\n                      ($scope.grid, columnIndex, targetIndex);\n                    }\n                  }\n\n\n\n                };\n\n                var onDownEvents = function(){\n                  $contentsElm.on('touchstart', downFn);\n                  $contentsElm.on('mousedown', downFn);\n                };\n\n                var offAllEvents = function() {\n                  $contentsElm.off('touchstart', downFn);\n                  $contentsElm.off('mousedown', downFn);\n\n                  $document.off('mousemove', moveFn);\n                  $document.off('touchmove', moveFn);\n\n                  $document.off('mouseup', upFn);\n                  $document.off('touchend', upFn);\n                };\n\n                onDownEvents();\n\n\n                var cloneElement = function () {\n                  elmCloned = true;\n\n                  //Cloning header cell and appending to current header cell.\n                  movingElm = $elm.clone();\n                  $elm.parent().append(movingElm);\n\n                  //Left of cloned element should be aligned to original header cell.\n                  movingElm.addClass('movingColumn');\n                  var movingElementStyles = {};\n                  movingElementStyles.left = $elm[0].offsetLeft + 'px';\n                  var gridRight = $scope.grid.element[0].getBoundingClientRect().right;\n                  var elmRight = $elm[0].getBoundingClientRect().right;\n                  if (elmRight > gridRight) {\n                    reducedWidth = $scope.col.drawnWidth + (gridRight - elmRight);\n                    movingElementStyles.width = reducedWidth + 'px';\n                  }\n                  movingElm.css(movingElementStyles);\n                };\n\n                var moveElement = function (changeValue) {\n                  //Calculate total column width\n                  var columns = $scope.grid.columns;\n                  var totalColumnWidth = 0;\n                  for (var i = 0; i < columns.length; i++) {\n                    if (angular.isUndefined(columns[i].colDef.visible) || columns[i].colDef.visible === true) {\n                      totalColumnWidth += columns[i].drawnWidth || columns[i].width || columns[i].colDef.width;\n                    }\n                  }\n\n                  //Calculate new position of left of column\n                  var currentElmLeft = movingElm[0].getBoundingClientRect().left - 1;\n                  var currentElmRight = movingElm[0].getBoundingClientRect().right;\n                  var newElementLeft;\n\n                  newElementLeft = currentElmLeft - gridLeft + changeValue;\n                  newElementLeft = newElementLeft < rightMoveLimit ? newElementLeft : rightMoveLimit;\n\n                  //Update css of moving column to adjust to new left value or fire scroll in case column has reached edge of grid\n                  if ((currentElmLeft >= gridLeft || changeValue > 0) && (currentElmRight <= rightMoveLimit || changeValue < 0)) {\n                    movingElm.css({visibility: 'visible', 'left': (movingElm[0].offsetLeft +\n                    (newElementLeft < rightMoveLimit ? changeValue : (rightMoveLimit - currentElmLeft))) + 'px'});\n                  }\n                  else if (totalColumnWidth > Math.ceil(uiGridCtrl.grid.gridWidth)) {\n                    changeValue *= 8;\n                    var scrollEvent = new ScrollEvent($scope.col.grid, null, null, 'uiGridHeaderCell.moveElement');\n                    scrollEvent.x = {pixels: changeValue};\n                    scrollEvent.grid.scrollContainers('',scrollEvent);\n                  }\n\n                  //Calculate total width of columns on the left of the moving column and the mouse movement\n                  var totalColumnsLeftWidth = 0;\n                  for (var il = 0; il < columns.length; il++) {\n                    if (angular.isUndefined(columns[il].colDef.visible) || columns[il].colDef.visible === true) {\n                      if (columns[il].colDef.name !== $scope.col.colDef.name) {\n                        totalColumnsLeftWidth += columns[il].drawnWidth || columns[il].width || columns[il].colDef.width;\n                      }\n                      else {\n                        break;\n                      }\n                    }\n                  }\n                  if ($scope.newScrollLeft === undefined) {\n                    totalMouseMovement += changeValue;\n                  }\n                  else {\n                    totalMouseMovement = $scope.newScrollLeft + newElementLeft - totalColumnsLeftWidth;\n                  }\n\n                  //Increase width of moving column, in case the rightmost column was moved and its width was\n                  //decreased because of overflow\n                  if (reducedWidth < $scope.col.drawnWidth) {\n                    reducedWidth += Math.abs(changeValue);\n                    movingElm.css({'width': reducedWidth + 'px'});\n                  }\n                };\n              }\n            }\n          };\n        }\n      };\n    }]);\n})();\n\n(function() {\n  'use strict';\n\n  /**\n   * @ngdoc overview\n   * @name ui.grid.pagination\n   *\n   * @description\n   *\n   * # ui.grid.pagination\n   *\n   * <div class=\"alert alert-warning\" role=\"alert\"><strong>Alpha</strong> This feature is in development. There will almost certainly be breaking api changes, or there are major outstanding bugs.</div>\n   *\n   * This module provides pagination support to ui-grid\n   */\n  var module = angular.module('ui.grid.pagination', ['ng', 'ui.grid']);\n\n  /**\n   * @ngdoc service\n   * @name ui.grid.pagination.service:uiGridPaginationService\n   *\n   * @description Service for the pagination feature\n   */\n  module.service('uiGridPaginationService', ['gridUtil',\n    function (gridUtil) {\n      var service = {\n        /**\n         * @ngdoc method\n         * @name initializeGrid\n         * @methodOf ui.grid.pagination.service:uiGridPaginationService\n         * @description Attaches the service to a certain grid\n         * @param {Grid} grid The grid we want to work with\n         */\n        initializeGrid: function (grid) {\n          service.defaultGridOptions(grid.options);\n\n          /**\n          * @ngdoc object\n          * @name ui.grid.pagination.api:PublicAPI\n          *\n          * @description Public API for the pagination feature\n          */\n          var publicApi = {\n            events: {\n              pagination: {\n              /**\n               * @ngdoc event\n               * @name paginationChanged\n               * @eventOf ui.grid.pagination.api:PublicAPI\n               * @description This event fires when the pageSize or currentPage changes\n               * @param {int} currentPage requested page number\n               * @param {int} pageSize requested page size\n               */\n                paginationChanged: function (currentPage, pageSize) { }\n              }\n            },\n            methods: {\n              pagination: {\n                /**\n                 * @ngdoc method\n                 * @name getPage\n                 * @methodOf ui.grid.pagination.api:PublicAPI\n                 * @description Returns the number of the current page\n                 */\n                getPage: function () {\n                  return grid.options.enablePagination ? grid.options.paginationCurrentPage : null;\n                },\n                /**\n                 * @ngdoc method\n                 * @name getTotalPages\n                 * @methodOf ui.grid.pagination.api:PublicAPI\n                 * @description Returns the total number of pages\n                 */\n                getTotalPages: function () {\n                  if (!grid.options.enablePagination) {\n                    return null;\n                  }\n\n                  return (grid.options.totalItems === 0) ? 1 : Math.ceil(grid.options.totalItems / grid.options.paginationPageSize);\n                },\n                /**\n                 * @ngdoc method\n                 * @name nextPage\n                 * @methodOf ui.grid.pagination.api:PublicAPI\n                 * @description Moves to the next page, if possible\n                 */\n                nextPage: function () {\n                  if (!grid.options.enablePagination) {\n                    return;\n                  }\n\n                  if (grid.options.totalItems > 0) {\n                    grid.options.paginationCurrentPage = Math.min(\n                      grid.options.paginationCurrentPage + 1,\n                      publicApi.methods.pagination.getTotalPages()\n                    );\n                  } else {\n                    grid.options.paginationCurrentPage++;\n                  }\n                },\n                /**\n                 * @ngdoc method\n                 * @name previousPage\n                 * @methodOf ui.grid.pagination.api:PublicAPI\n                 * @description Moves to the previous page, if we're not on the first page\n                 */\n                previousPage: function () {\n                  if (!grid.options.enablePagination) {\n                    return;\n                  }\n\n                  grid.options.paginationCurrentPage = Math.max(grid.options.paginationCurrentPage - 1, 1);\n                },\n                /**\n                 * @ngdoc method\n                 * @name seek\n                 * @methodOf ui.grid.pagination.api:PublicAPI\n                 * @description Moves to the requested page\n                 * @param {int} page The number of the page that should be displayed\n                 */\n                seek: function (page) {\n                  if (!grid.options.enablePagination) {\n                    return;\n                  }\n                  if (!angular.isNumber(page) || page < 1) {\n                    throw 'Invalid page number: ' + page;\n                  }\n\n                  grid.options.paginationCurrentPage = Math.min(page, publicApi.methods.pagination.getTotalPages());\n                }\n              }\n            }\n          };\n\n          grid.api.registerEventsFromObject(publicApi.events);\n          grid.api.registerMethodsFromObject(publicApi.methods);\n\n          var processPagination = function( renderableRows ){\n            if (grid.options.useExternalPagination || !grid.options.enablePagination) {\n              return renderableRows;\n            }\n            //client side pagination\n            var pageSize = parseInt(grid.options.paginationPageSize, 10);\n            var currentPage = parseInt(grid.options.paginationCurrentPage, 10);\n\n            var visibleRows = renderableRows.filter(function (row) { return row.visible; });\n            grid.options.totalItems = visibleRows.length;\n\n            var firstRow = (currentPage - 1) * pageSize;\n            if (firstRow > visibleRows.length) {\n              currentPage = grid.options.paginationCurrentPage = 1;\n              firstRow = (currentPage - 1) * pageSize;\n            }\n            return visibleRows.slice(firstRow, firstRow + pageSize);\n          };\n\n          grid.registerRowsProcessor(processPagination, 900 );\n\n        },\n        defaultGridOptions: function (gridOptions) {\n          /**\n           * @ngdoc object\n           * @name ui.grid.pagination.api:GridOptions\n           *\n           * @description GridOptions for the pagination feature, these are available to be\n           * set using the ui-grid {@link ui.grid.class:GridOptions gridOptions}\n           */\n\n          /**\n           * @ngdoc property\n           * @name enablePagination\n           * @propertyOf ui.grid.pagination.api:GridOptions\n           * @description Enables pagination.  Defaults to true.\n           */\n          gridOptions.enablePagination = gridOptions.enablePagination !== false;\n          /**\n           * @ngdoc property\n           * @name enablePaginationControls\n           * @propertyOf ui.grid.pagination.api:GridOptions\n           * @description Enables the paginator at the bottom of the grid. Turn this off if you want to implement your\n           *              own controls outside the grid.\n           */\n          gridOptions.enablePaginationControls = gridOptions.enablePaginationControls !== false;\n          /**\n           * @ngdoc property\n           * @name useExternalPagination\n           * @propertyOf ui.grid.pagination.api:GridOptions\n           * @description Disables client side pagination. When true, handle the paginationChanged event and set data\n           *              and totalItems.  Defaults to `false`\n           */\n          gridOptions.useExternalPagination = gridOptions.useExternalPagination === true;\n          /**\n           * @ngdoc property\n           * @name totalItems\n           * @propertyOf ui.grid.pagination.api:GridOptions\n           * @description Total number of items, set automatically when using client side pagination, but needs set by user\n           *              for server side pagination\n           */\n          if (gridUtil.isNullOrUndefined(gridOptions.totalItems)) {\n            gridOptions.totalItems = 0;\n          }\n          /**\n           * @ngdoc property\n           * @name paginationPageSizes\n           * @propertyOf ui.grid.pagination.api:GridOptions\n           * @description Array of page sizes, defaults to `[250, 500, 1000]`\n           */\n          if (gridUtil.isNullOrUndefined(gridOptions.paginationPageSizes)) {\n            gridOptions.paginationPageSizes = [250, 500, 1000];\n          }\n          /**\n           * @ngdoc property\n           * @name paginationPageSize\n           * @propertyOf ui.grid.pagination.api:GridOptions\n           * @description Page size, defaults to the first item in paginationPageSizes, or 0 if paginationPageSizes is empty\n           */\n          if (gridUtil.isNullOrUndefined(gridOptions.paginationPageSize)) {\n            if (gridOptions.paginationPageSizes.length > 0) {\n              gridOptions.paginationPageSize = gridOptions.paginationPageSizes[0];\n            } else {\n              gridOptions.paginationPageSize = 0;\n            }\n          }\n          /**\n           * @ngdoc property\n           * @name paginationCurrentPage\n           * @propertyOf ui.grid.pagination.api:GridOptions\n           * @description Current page number, defaults to 1\n           */\n          if (gridUtil.isNullOrUndefined(gridOptions.paginationCurrentPage)) {\n            gridOptions.paginationCurrentPage = 1;\n          }\n\n          /**\n           * @ngdoc property\n           * @name paginationTemplate\n           * @propertyOf ui.grid.pagination.api:GridOptions\n           * @description A custom template for the pager, defaults to `ui-grid/pagination`\n           */\n          if (gridUtil.isNullOrUndefined(gridOptions.paginationTemplate)) {\n            gridOptions.paginationTemplate = 'ui-grid/pagination';\n          }\n        },\n        /**\n         * @ngdoc method\n         * @methodOf ui.grid.pagination.service:uiGridPaginationService\n         * @name uiGridPaginationService\n         * @description  Raises paginationChanged and calls refresh for client side pagination\n         * @param {Grid} grid the grid for which the pagination changed\n         * @param {int} currentPage requested page number\n         * @param {int} pageSize requested page size\n         */\n        onPaginationChanged: function (grid, currentPage, pageSize) {\n            grid.api.pagination.raise.paginationChanged(currentPage, pageSize);\n            if (!grid.options.useExternalPagination) {\n              grid.queueGridRefresh(); //client side pagination\n            }\n        }\n      };\n\n      return service;\n    }\n  ]);\n  /**\n   *  @ngdoc directive\n   *  @name ui.grid.pagination.directive:uiGridPagination\n   *  @element div\n   *  @restrict A\n   *\n   *  @description Adds pagination features to grid\n   *  @example\n   <example module=\"app\">\n   <file name=\"app.js\">\n   var app = angular.module('app', ['ui.grid', 'ui.grid.pagination']);\n\n   app.controller('MainCtrl', ['$scope', function ($scope) {\n      $scope.data = [\n        { name: 'Alex', car: 'Toyota' },\n        { name: 'Sam', car: 'Lexus' },\n        { name: 'Joe', car: 'Dodge' },\n        { name: 'Bob', car: 'Buick' },\n        { name: 'Cindy', car: 'Ford' },\n        { name: 'Brian', car: 'Audi' },\n        { name: 'Malcom', car: 'Mercedes Benz' },\n        { name: 'Dave', car: 'Ford' },\n        { name: 'Stacey', car: 'Audi' },\n        { name: 'Amy', car: 'Acura' },\n        { name: 'Scott', car: 'Toyota' },\n        { name: 'Ryan', car: 'BMW' },\n      ];\n\n      $scope.gridOptions = {\n        data: 'data',\n        paginationPageSizes: [5, 10, 25],\n        paginationPageSize: 5,\n        columnDefs: [\n          {name: 'name'},\n          {name: 'car'}\n        ]\n       }\n    }]);\n   </file>\n   <file name=\"index.html\">\n   <div ng-controller=\"MainCtrl\">\n   <div ui-grid=\"gridOptions\" ui-grid-pagination></div>\n   </div>\n   </file>\n   </example>\n   */\n  module.directive('uiGridPagination', ['gridUtil', 'uiGridPaginationService',\n    function (gridUtil, uiGridPaginationService) {\n      return {\n        priority: -200,\n        scope: false,\n        require: 'uiGrid',\n        link: {\n          pre: function ($scope, $elm, $attr, uiGridCtrl) {\n            uiGridPaginationService.initializeGrid(uiGridCtrl.grid);\n\n            gridUtil.getTemplate(uiGridCtrl.grid.options.paginationTemplate)\n              .then(function (contents) {\n                var template = angular.element(contents);\n                $elm.append(template);\n                uiGridCtrl.innerCompile(template);\n              });\n          }\n        }\n      };\n    }\n  ]);\n\n  /**\n   *  @ngdoc directive\n   *  @name ui.grid.pagination.directive:uiGridPager\n   *  @element div\n   *\n   *  @description Panel for handling pagination\n   */\n  module.directive('uiGridPager', ['uiGridPaginationService', 'uiGridConstants', 'gridUtil', 'i18nService',\n    function (uiGridPaginationService, uiGridConstants, gridUtil, i18nService) {\n      return {\n        priority: -200,\n        scope: true,\n        require: '^uiGrid',\n        link: function ($scope, $elm, $attr, uiGridCtrl) {\n          var defaultFocusElementSelector = '.ui-grid-pager-control-input';\n          $scope.aria = i18nService.getSafeText('pagination.aria'); //Returns an object with all of the aria labels\n\n          $scope.paginationApi = uiGridCtrl.grid.api.pagination;\n          $scope.sizesLabel = i18nService.getSafeText('pagination.sizes');\n          $scope.totalItemsLabel = i18nService.getSafeText('pagination.totalItems');\n          $scope.paginationOf = i18nService.getSafeText('pagination.of');\n          $scope.paginationThrough = i18nService.getSafeText('pagination.through');\n\n          var options = uiGridCtrl.grid.options;\n\n          uiGridCtrl.grid.renderContainers.body.registerViewportAdjuster(function (adjustment) {\n            adjustment.height = adjustment.height - gridUtil.elementHeight($elm, \"padding\");\n            return adjustment;\n          });\n\n          var dataChangeDereg = uiGridCtrl.grid.registerDataChangeCallback(function (grid) {\n            if (!grid.options.useExternalPagination) {\n              grid.options.totalItems = grid.rows.length;\n            }\n          }, [uiGridConstants.dataChange.ROW]);\n\n          $scope.$on('$destroy', dataChangeDereg);\n\n          var setShowing = function () {\n            $scope.showingLow = ((options.paginationCurrentPage - 1) * options.paginationPageSize) + 1;\n            $scope.showingHigh = Math.min(options.paginationCurrentPage * options.paginationPageSize, options.totalItems);\n          };\n\n          var deregT = $scope.$watch('grid.options.totalItems + grid.options.paginationPageSize', setShowing);\n\n          var deregP = $scope.$watch('grid.options.paginationCurrentPage + grid.options.paginationPageSize', function (newValues, oldValues) {\n              if (newValues === oldValues || oldValues === undefined) {\n                return;\n              }\n\n              if (!angular.isNumber(options.paginationCurrentPage) || options.paginationCurrentPage < 1) {\n                options.paginationCurrentPage = 1;\n                return;\n              }\n\n              if (options.totalItems > 0 && options.paginationCurrentPage > $scope.paginationApi.getTotalPages()) {\n                options.paginationCurrentPage = $scope.paginationApi.getTotalPages();\n                return;\n              }\n\n              setShowing();\n              uiGridPaginationService.onPaginationChanged($scope.grid, options.paginationCurrentPage, options.paginationPageSize);\n            }\n          );\n\n          $scope.$on('$destroy', function() {\n            deregT();\n            deregP();\n          });\n\n          $scope.cantPageForward = function () {\n            if (options.totalItems > 0) {\n              return options.paginationCurrentPage >= $scope.paginationApi.getTotalPages();\n            } else {\n              return options.data.length < 1;\n            }\n          };\n\n          $scope.cantPageToLast = function () {\n            if (options.totalItems > 0) {\n              return $scope.cantPageForward();\n            } else {\n              return true;\n            }\n          };\n\n          $scope.cantPageBackward = function () {\n            return options.paginationCurrentPage <= 1;\n          };\n\n          var focusToInputIf = function(condition){\n            if (condition){\n              gridUtil.focus.bySelector($elm, defaultFocusElementSelector);\n            }\n          };\n\n          //Takes care of setting focus to the middle element when focus is lost\n          $scope.pageFirstPageClick = function () {\n            $scope.paginationApi.seek(1);\n            focusToInputIf($scope.cantPageBackward());\n          };\n\n          $scope.pagePreviousPageClick = function () {\n            $scope.paginationApi.previousPage();\n            focusToInputIf($scope.cantPageBackward());\n          };\n\n          $scope.pageNextPageClick = function () {\n            $scope.paginationApi.nextPage();\n            focusToInputIf($scope.cantPageForward());\n          };\n\n          $scope.pageLastPageClick = function () {\n            $scope.paginationApi.seek($scope.paginationApi.getTotalPages());\n            focusToInputIf($scope.cantPageToLast());\n          };\n\n        }\n      };\n    }\n  ]);\n})();\n\n(function () {\n  'use strict';\n\n  /**\n   * @ngdoc overview\n   * @name ui.grid.pinning\n   * @description\n   *\n   * # ui.grid.pinning\n   *\n   * <div class=\"alert alert-success\" role=\"alert\"><strong>Stable</strong> This feature is stable. There should no longer be breaking api changes without a deprecation warning.</div>\n   *\n   * This module provides column pinning to the end user via menu options in the column header\n   *\n   * <div doc-module-components=\"ui.grid.pinning\"></div>\n   */\n\n  var module = angular.module('ui.grid.pinning', ['ui.grid']);\n\n  module.constant('uiGridPinningConstants', {\n    container: {\n      LEFT: 'left',\n      RIGHT: 'right',\n      NONE: ''\n    }\n  });\n\n  module.service('uiGridPinningService', ['gridUtil', 'GridRenderContainer', 'i18nService', 'uiGridPinningConstants', function (gridUtil, GridRenderContainer, i18nService, uiGridPinningConstants) {\n    var service = {\n\n      initializeGrid: function (grid) {\n        service.defaultGridOptions(grid.options);\n\n        // Register a column builder to add new menu items for pinning left and right\n        grid.registerColumnBuilder(service.pinningColumnBuilder);\n\n        /**\n         *  @ngdoc object\n         *  @name ui.grid.pinning.api:PublicApi\n         *\n         *  @description Public Api for pinning feature\n         */\n        var publicApi = {\n          events: {\n            pinning: {\n              /**\n               * @ngdoc event\n               * @name columnPin\n               * @eventOf ui.grid.pinning.api:PublicApi\n               * @description raised when column pin state has changed\n               * <pre>\n               *   gridApi.pinning.on.columnPinned(scope, function(colDef){})\n               * </pre>\n               * @param {object} colDef the column that was changed\n               * @param {string} container the render container the column is in ('left', 'right', '')\n               */\n              columnPinned: function(colDef, container) {\n              }\n            }\n          },\n          methods: {\n            pinning: {\n              /**\n               * @ngdoc function\n               * @name pinColumn\n               * @methodOf ui.grid.pinning.api:PublicApi\n               * @description pin column left, right, or none\n               * <pre>\n               *   gridApi.pinning.pinColumn(col, uiGridPinningConstants.container.LEFT)\n               * </pre>\n               * @param {gridColumn} col the column being pinned\n               * @param {string} container one of the recognised types\n               * from uiGridPinningConstants\n               */\n              pinColumn: function(col, container) {\n                service.pinColumn(grid, col, container);\n              }\n            }\n          }\n        };\n\n        grid.api.registerEventsFromObject(publicApi.events);\n        grid.api.registerMethodsFromObject(publicApi.methods);\n      },\n\n      defaultGridOptions: function (gridOptions) {\n        //default option to true unless it was explicitly set to false\n        /**\n         *  @ngdoc object\n         *  @name ui.grid.pinning.api:GridOptions\n         *\n         *  @description GridOptions for pinning feature, these are available to be\n           *  set using the ui-grid {@link ui.grid.class:GridOptions gridOptions}\n         */\n\n        /**\n         *  @ngdoc object\n         *  @name enablePinning\n         *  @propertyOf  ui.grid.pinning.api:GridOptions\n         *  @description Enable pinning for the entire grid.\n         *  <br/>Defaults to true\n         */\n        gridOptions.enablePinning = gridOptions.enablePinning !== false;\n\n      },\n\n      pinningColumnBuilder: function (colDef, col, gridOptions) {\n        //default to true unless gridOptions or colDef is explicitly false\n\n        /**\n         *  @ngdoc object\n         *  @name ui.grid.pinning.api:ColumnDef\n         *\n         *  @description ColumnDef for pinning feature, these are available to be\n         *  set using the ui-grid {@link ui.grid.class:GridOptions.columnDef gridOptions.columnDefs}\n         */\n\n        /**\n         *  @ngdoc object\n         *  @name enablePinning\n         *  @propertyOf  ui.grid.pinning.api:ColumnDef\n         *  @description Enable pinning for the individual column.\n         *  <br/>Defaults to true\n         */\n        colDef.enablePinning = colDef.enablePinning === undefined ? gridOptions.enablePinning : colDef.enablePinning;\n\n\n        /**\n         *  @ngdoc object\n         *  @name pinnedLeft\n         *  @propertyOf  ui.grid.pinning.api:ColumnDef\n         *  @description Column is pinned left when grid is rendered\n         *  <br/>Defaults to false\n         */\n\n        /**\n         *  @ngdoc object\n         *  @name pinnedRight\n         *  @propertyOf  ui.grid.pinning.api:ColumnDef\n         *  @description Column is pinned right when grid is rendered\n         *  <br/>Defaults to false\n         */\n        if (colDef.pinnedLeft) {\n          col.renderContainer = 'left';\n          col.grid.createLeftContainer();\n        }\n        else if (colDef.pinnedRight) {\n          col.renderContainer = 'right';\n          col.grid.createRightContainer();\n        }\n\n        if (!colDef.enablePinning) {\n          return;\n        }\n\n        var pinColumnLeftAction = {\n          name: 'ui.grid.pinning.pinLeft',\n          title: i18nService.get().pinning.pinLeft,\n          icon: 'ui-grid-icon-left-open',\n          shown: function () {\n            return typeof(this.context.col.renderContainer) === 'undefined' || !this.context.col.renderContainer || this.context.col.renderContainer !== 'left';\n          },\n          action: function () {\n            service.pinColumn(this.context.col.grid, this.context.col, uiGridPinningConstants.container.LEFT);\n          }\n        };\n\n        var pinColumnRightAction = {\n          name: 'ui.grid.pinning.pinRight',\n          title: i18nService.get().pinning.pinRight,\n          icon: 'ui-grid-icon-right-open',\n          shown: function () {\n            return typeof(this.context.col.renderContainer) === 'undefined' || !this.context.col.renderContainer || this.context.col.renderContainer !== 'right';\n          },\n          action: function () {\n            service.pinColumn(this.context.col.grid, this.context.col, uiGridPinningConstants.container.RIGHT);\n          }\n        };\n\n        var removePinAction = {\n          name: 'ui.grid.pinning.unpin',\n          title: i18nService.get().pinning.unpin,\n          icon: 'ui-grid-icon-cancel',\n          shown: function () {\n            return typeof(this.context.col.renderContainer) !== 'undefined' && this.context.col.renderContainer !== null && this.context.col.renderContainer !== 'body';\n          },\n          action: function () {\n            service.pinColumn(this.context.col.grid, this.context.col, uiGridPinningConstants.container.NONE);\n          }\n        };\n\n        if (!gridUtil.arrayContainsObjectWithProperty(col.menuItems, 'name', 'ui.grid.pinning.pinLeft')) {\n          col.menuItems.push(pinColumnLeftAction);\n        }\n        if (!gridUtil.arrayContainsObjectWithProperty(col.menuItems, 'name', 'ui.grid.pinning.pinRight')) {\n          col.menuItems.push(pinColumnRightAction);\n        }\n        if (!gridUtil.arrayContainsObjectWithProperty(col.menuItems, 'name', 'ui.grid.pinning.unpin')) {\n          col.menuItems.push(removePinAction);\n        }\n      },\n\n      pinColumn: function(grid, col, container) {\n        if (container === uiGridPinningConstants.container.NONE) {\n          col.renderContainer = null;\n          col.colDef.pinnedLeft = col.colDef.pinnedRight = false;\n        }\n        else {\n          col.renderContainer = container;\n          if (container === uiGridPinningConstants.container.LEFT) {\n            grid.createLeftContainer();\n          }\n          else if (container === uiGridPinningConstants.container.RIGHT) {\n            grid.createRightContainer();\n          }\n        }\n\n        grid.refresh()\n        .then(function() {\n          grid.api.pinning.raise.columnPinned( col.colDef, container );\n        });\n      }\n    };\n\n    return service;\n  }]);\n\n  module.directive('uiGridPinning', ['gridUtil', 'uiGridPinningService',\n    function (gridUtil, uiGridPinningService) {\n      return {\n        require: 'uiGrid',\n        scope: false,\n        compile: function () {\n          return {\n            pre: function ($scope, $elm, $attrs, uiGridCtrl) {\n              uiGridPinningService.initializeGrid(uiGridCtrl.grid);\n            },\n            post: function ($scope, $elm, $attrs, uiGridCtrl) {\n            }\n          };\n        }\n      };\n    }]);\n\n\n})();\n\n(function(){\n  'use strict';\n\n  /**\n   * @ngdoc overview\n   * @name ui.grid.resizeColumns\n   * @description\n   *\n   * # ui.grid.resizeColumns\n   *\n   * <div class=\"alert alert-success\" role=\"alert\"><strong>Stable</strong> This feature is stable. There should no longer be breaking api changes without a deprecation warning.</div>\n   *\n   * This module allows columns to be resized.\n   */\n  var module = angular.module('ui.grid.resizeColumns', ['ui.grid']);\n\n  module.service('uiGridResizeColumnsService', ['gridUtil', '$q', '$timeout',\n    function (gridUtil, $q, $timeout) {\n\n      var service = {\n        defaultGridOptions: function(gridOptions){\n          //default option to true unless it was explicitly set to false\n          /**\n           *  @ngdoc object\n           *  @name ui.grid.resizeColumns.api:GridOptions\n           *\n           *  @description GridOptions for resizeColumns feature, these are available to be\n           *  set using the ui-grid {@link ui.grid.class:GridOptions gridOptions}\n           */\n\n          /**\n           *  @ngdoc object\n           *  @name enableColumnResizing\n           *  @propertyOf  ui.grid.resizeColumns.api:GridOptions\n           *  @description Enable column resizing on the entire grid\n           *  <br/>Defaults to true\n           */\n          gridOptions.enableColumnResizing = gridOptions.enableColumnResizing !== false;\n\n          //legacy support\n          //use old name if it is explicitly false\n          if (gridOptions.enableColumnResize === false){\n            gridOptions.enableColumnResizing = false;\n          }\n        },\n\n        colResizerColumnBuilder: function (colDef, col, gridOptions) {\n\n          var promises = [];\n          /**\n           *  @ngdoc object\n           *  @name ui.grid.resizeColumns.api:ColumnDef\n           *\n           *  @description ColumnDef for resizeColumns feature, these are available to be\n           *  set using the ui-grid {@link ui.grid.class:GridOptions.columnDef gridOptions.columnDefs}\n           */\n\n          /**\n           *  @ngdoc object\n           *  @name enableColumnResizing\n           *  @propertyOf  ui.grid.resizeColumns.api:ColumnDef\n           *  @description Enable column resizing on an individual column\n           *  <br/>Defaults to GridOptions.enableColumnResizing\n           */\n          //default to true unless gridOptions or colDef is explicitly false\n          colDef.enableColumnResizing = colDef.enableColumnResizing === undefined ? gridOptions.enableColumnResizing : colDef.enableColumnResizing;\n\n\n          //legacy support of old option name\n          if (colDef.enableColumnResize === false){\n            colDef.enableColumnResizing = false;\n          }\n\n          return $q.all(promises);\n        },\n\n        registerPublicApi: function (grid) {\n            /**\n             *  @ngdoc object\n             *  @name ui.grid.resizeColumns.api:PublicApi\n             *  @description Public Api for column resize feature.\n             */\n            var publicApi = {\n              events: {\n                /**\n                 * @ngdoc event\n                 * @name columnSizeChanged\n                 * @eventOf  ui.grid.resizeColumns.api:PublicApi\n                 * @description raised when column is resized\n                 * <pre>\n                 *      gridApi.colResizable.on.columnSizeChanged(scope,function(colDef, deltaChange){})\n                 * </pre>\n                 * @param {object} colDef the column that was resized\n                 * @param {integer} delta of the column size change\n                 */\n                colResizable: {\n                  columnSizeChanged: function (colDef, deltaChange) {\n                  }\n                }\n              }\n            };\n            grid.api.registerEventsFromObject(publicApi.events);\n        },\n\n        fireColumnSizeChanged: function (grid, colDef, deltaChange) {\n          $timeout(function () {\n            if ( grid.api.colResizable ){\n              grid.api.colResizable.raise.columnSizeChanged(colDef, deltaChange);\n            } else {\n              gridUtil.logError(\"The resizeable api is not registered, this may indicate that you've included the module but not added the 'ui-grid-resize-columns' directive to your grid definition.  Cannot raise any events.\");\n            }\n          });\n        },\n\n        // get either this column, or the column next to this column, to resize,\n        // returns the column we're going to resize\n        findTargetCol: function(col, position, rtlMultiplier){\n          var renderContainer = col.getRenderContainer();\n\n          if (position === 'left') {\n            // Get the column to the left of this one\n            var colIndex = renderContainer.visibleColumnCache.indexOf(col);\n            return renderContainer.visibleColumnCache[colIndex - 1 * rtlMultiplier];\n          } else {\n            return col;\n          }\n        }\n\n      };\n\n      return service;\n\n    }]);\n\n\n  /**\n   * @ngdoc directive\n   * @name ui.grid.resizeColumns.directive:uiGridResizeColumns\n   * @element div\n   * @restrict A\n   * @description\n   * Enables resizing for all columns on the grid. If, for some reason, you want to use the ui-grid-resize-columns directive, but not allow column resizing, you can explicitly set the\n   * option to false. This prevents resizing for the entire grid, regardless of individual columnDef options.\n   *\n   * @example\n   <doc:example module=\"app\">\n   <doc:source>\n   <script>\n   var app = angular.module('app', ['ui.grid', 'ui.grid.resizeColumns']);\n\n   app.controller('MainCtrl', ['$scope', function ($scope) {\n          $scope.gridOpts = {\n            data: [\n              { \"name\": \"Ethel Price\", \"gender\": \"female\", \"company\": \"Enersol\" },\n              { \"name\": \"Claudine Neal\", \"gender\": \"female\", \"company\": \"Sealoud\" },\n              { \"name\": \"Beryl Rice\", \"gender\": \"female\", \"company\": \"Velity\" },\n              { \"name\": \"Wilder Gonzales\", \"gender\": \"male\", \"company\": \"Geekko\" }\n            ]\n          };\n        }]);\n   </script>\n\n   <div ng-controller=\"MainCtrl\">\n   <div class=\"testGrid\" ui-grid=\"gridOpts\" ui-grid-resize-columns ></div>\n   </div>\n   </doc:source>\n   <doc:scenario>\n\n   </doc:scenario>\n   </doc:example>\n   */\n  module.directive('uiGridResizeColumns', ['gridUtil', 'uiGridResizeColumnsService', function (gridUtil, uiGridResizeColumnsService) {\n    return {\n      replace: true,\n      priority: 0,\n      require: '^uiGrid',\n      scope: false,\n      compile: function () {\n        return {\n          pre: function ($scope, $elm, $attrs, uiGridCtrl) {\n            uiGridResizeColumnsService.defaultGridOptions(uiGridCtrl.grid.options);\n            uiGridCtrl.grid.registerColumnBuilder( uiGridResizeColumnsService.colResizerColumnBuilder);\n            uiGridResizeColumnsService.registerPublicApi(uiGridCtrl.grid);\n          },\n          post: function ($scope, $elm, $attrs, uiGridCtrl) {\n          }\n        };\n      }\n    };\n  }]);\n\n  // Extend the uiGridHeaderCell directive\n  module.directive('uiGridHeaderCell', ['gridUtil', '$templateCache', '$compile', '$q', 'uiGridResizeColumnsService', 'uiGridConstants', '$timeout', function (gridUtil, $templateCache, $compile, $q, uiGridResizeColumnsService, uiGridConstants, $timeout) {\n    return {\n      // Run after the original uiGridHeaderCell\n      priority: -10,\n      require: '^uiGrid',\n      // scope: false,\n      compile: function() {\n        return {\n          post: function ($scope, $elm, $attrs, uiGridCtrl) {\n            var grid = uiGridCtrl.grid;\n\n            if (grid.options.enableColumnResizing) {\n              var columnResizerElm = $templateCache.get('ui-grid/columnResizer');\n\n              var rtlMultiplier = 1;\n              //when in RTL mode reverse the direction using the rtlMultiplier and change the position to left\n              if (grid.isRTL()) {\n                $scope.position = 'left';\n                rtlMultiplier = -1;\n              }\n\n              var displayResizers = function(){\n\n                // remove any existing resizers.\n                var resizers = $elm[0].getElementsByClassName('ui-grid-column-resizer');\n                for ( var i = 0; i < resizers.length; i++ ){\n                  angular.element(resizers[i]).remove();\n                }\n\n                // get the target column for the left resizer\n                var otherCol = uiGridResizeColumnsService.findTargetCol($scope.col, 'left', rtlMultiplier);\n                var renderContainer = $scope.col.getRenderContainer();\n\n                // Don't append the left resizer if this is the first column or the column to the left of this one has resizing disabled\n                if (otherCol && renderContainer.visibleColumnCache.indexOf($scope.col) !== 0 && otherCol.colDef.enableColumnResizing !== false) {\n                  var resizerLeft = angular.element(columnResizerElm).clone();\n                  resizerLeft.attr('position', 'left');\n\n                  $elm.prepend(resizerLeft);\n                  $compile(resizerLeft)($scope);\n                }\n\n                // Don't append the right resizer if this column has resizing disabled\n                if ($scope.col.colDef.enableColumnResizing !== false) {\n                  var resizerRight = angular.element(columnResizerElm).clone();\n                  resizerRight.attr('position', 'right');\n\n                  $elm.append(resizerRight);\n                  $compile(resizerRight)($scope);\n                }\n              };\n\n              displayResizers();\n\n              var waitDisplay = function(){\n                $timeout(displayResizers);\n              };\n\n              var dataChangeDereg = grid.registerDataChangeCallback( waitDisplay, [uiGridConstants.dataChange.COLUMN] );\n\n              $scope.$on( '$destroy', dataChangeDereg );\n            }\n          }\n        };\n      }\n    };\n  }]);\n\n\n\n  /**\n   * @ngdoc directive\n   * @name ui.grid.resizeColumns.directive:uiGridColumnResizer\n   * @element div\n   * @restrict A\n   *\n   * @description\n   * Draggable handle that controls column resizing.\n   *\n   * @example\n   <doc:example module=\"app\">\n     <doc:source>\n       <script>\n        var app = angular.module('app', ['ui.grid', 'ui.grid.resizeColumns']);\n\n        app.controller('MainCtrl', ['$scope', function ($scope) {\n          $scope.gridOpts = {\n            enableColumnResizing: true,\n            data: [\n              { \"name\": \"Ethel Price\", \"gender\": \"female\", \"company\": \"Enersol\" },\n              { \"name\": \"Claudine Neal\", \"gender\": \"female\", \"company\": \"Sealoud\" },\n              { \"name\": \"Beryl Rice\", \"gender\": \"female\", \"company\": \"Velity\" },\n              { \"name\": \"Wilder Gonzales\", \"gender\": \"male\", \"company\": \"Geekko\" }\n            ]\n          };\n        }]);\n       </script>\n\n       <div ng-controller=\"MainCtrl\">\n        <div class=\"testGrid\" ui-grid=\"gridOpts\"></div>\n       </div>\n     </doc:source>\n     <doc:scenario>\n      // TODO: e2e specs?\n\n      // TODO: post-resize a horizontal scroll event should be fired\n     </doc:scenario>\n   </doc:example>\n   */\n  module.directive('uiGridColumnResizer', ['$document', 'gridUtil', 'uiGridConstants', 'uiGridResizeColumnsService', function ($document, gridUtil, uiGridConstants, uiGridResizeColumnsService) {\n    var resizeOverlay = angular.element('<div class=\"ui-grid-resize-overlay\"></div>');\n\n    var resizer = {\n      priority: 0,\n      scope: {\n        col: '=',\n        position: '@',\n        renderIndex: '='\n      },\n      require: '?^uiGrid',\n      link: function ($scope, $elm, $attrs, uiGridCtrl) {\n        var startX = 0,\n            x = 0,\n            gridLeft = 0,\n            rtlMultiplier = 1;\n\n        //when in RTL mode reverse the direction using the rtlMultiplier and change the position to left\n        if (uiGridCtrl.grid.isRTL()) {\n          $scope.position = 'left';\n          rtlMultiplier = -1;\n        }\n\n        if ($scope.position === 'left') {\n          $elm.addClass('left');\n        }\n        else if ($scope.position === 'right') {\n          $elm.addClass('right');\n        }\n\n        // Refresh the grid canvas\n        //   takes an argument representing the diff along the X-axis that the resize had\n        function refreshCanvas(xDiff) {\n          // Then refresh the grid canvas, rebuilding the styles so that the scrollbar updates its size\n          uiGridCtrl.grid.refreshCanvas(true).then( function() {\n            uiGridCtrl.grid.queueGridRefresh();\n          });\n        }\n\n        // Check that the requested width isn't wider than the maxWidth, or narrower than the minWidth\n        // Returns the new recommended with, after constraints applied\n        function constrainWidth(col, width){\n          var newWidth = width;\n\n          // If the new width would be less than the column's allowably minimum width, don't allow it\n          if (col.minWidth && newWidth < col.minWidth) {\n            newWidth = col.minWidth;\n          }\n          else if (col.maxWidth && newWidth > col.maxWidth) {\n            newWidth = col.maxWidth;\n          }\n\n          return newWidth;\n        }\n\n\n        /*\n         * Our approach to event handling aims to deal with both touch devices and mouse devices\n         * We register down handlers on both touch and mouse.  When a touchstart or mousedown event\n         * occurs, we register the corresponding touchmove/touchend, or mousemove/mouseend events.\n         *\n         * This way we can listen for both without worrying about the fact many touch devices also emulate\n         * mouse events - basically whichever one we hear first is what we'll go with.\n         */\n        function moveFunction(event, args) {\n          if (event.originalEvent) { event = event.originalEvent; }\n          event.preventDefault();\n\n          x = (event.targetTouches ? event.targetTouches[0] : event).clientX - gridLeft;\n\n          if (x < 0) { x = 0; }\n          else if (x > uiGridCtrl.grid.gridWidth) { x = uiGridCtrl.grid.gridWidth; }\n\n          var col = uiGridResizeColumnsService.findTargetCol($scope.col, $scope.position, rtlMultiplier);\n\n          // Don't resize if it's disabled on this column\n          if (col.colDef.enableColumnResizing === false) {\n            return;\n          }\n\n          if (!uiGridCtrl.grid.element.hasClass('column-resizing')) {\n            uiGridCtrl.grid.element.addClass('column-resizing');\n          }\n\n          // Get the diff along the X axis\n          var xDiff = x - startX;\n\n          // Get the width that this mouse would give the column\n          var newWidth = parseInt(col.drawnWidth + xDiff * rtlMultiplier, 10);\n\n          // check we're not outside the allowable bounds for this column\n          x = x + ( constrainWidth(col, newWidth) - newWidth ) * rtlMultiplier;\n\n          resizeOverlay.css({ left: x + 'px' });\n\n          uiGridCtrl.fireEvent(uiGridConstants.events.ITEM_DRAGGING);\n        }\n\n\n        function upFunction(event, args) {\n          if (event.originalEvent) { event = event.originalEvent; }\n          event.preventDefault();\n\n          uiGridCtrl.grid.element.removeClass('column-resizing');\n\n          resizeOverlay.remove();\n\n          // Resize the column\n          x = (event.changedTouches ? event.changedTouches[0] : event).clientX - gridLeft;\n          var xDiff = x - startX;\n\n          if (xDiff === 0) {\n            // no movement, so just reset event handlers, including turning back on both\n            // down events - we turned one off when this event started\n            offAllEvents();\n            onDownEvents();\n            return;\n          }\n\n          var col = uiGridResizeColumnsService.findTargetCol($scope.col, $scope.position, rtlMultiplier);\n\n          // Don't resize if it's disabled on this column\n          if (col.colDef.enableColumnResizing === false) {\n            return;\n          }\n\n          // Get the new width\n          var newWidth = parseInt(col.drawnWidth + xDiff * rtlMultiplier, 10);\n\n          // check we're not outside the allowable bounds for this column\n          col.width = constrainWidth(col, newWidth);\n          col.hasCustomWidth = true;\n\n          refreshCanvas(xDiff);\n\n          uiGridResizeColumnsService.fireColumnSizeChanged(uiGridCtrl.grid, col.colDef, xDiff);\n\n          // stop listening of up and move events - wait for next down\n          // reset the down events - we will have turned one off when this event started\n          offAllEvents();\n          onDownEvents();\n        }\n\n\n        var downFunction = function(event, args) {\n          if (event.originalEvent) { event = event.originalEvent; }\n          event.stopPropagation();\n\n          // Get the left offset of the grid\n          // gridLeft = uiGridCtrl.grid.element[0].offsetLeft;\n          gridLeft = uiGridCtrl.grid.element[0].getBoundingClientRect().left;\n\n          // Get the starting X position, which is the X coordinate of the click minus the grid's offset\n          startX = (event.targetTouches ? event.targetTouches[0] : event).clientX - gridLeft;\n\n          // Append the resizer overlay\n          uiGridCtrl.grid.element.append(resizeOverlay);\n\n          // Place the resizer overlay at the start position\n          resizeOverlay.css({ left: startX });\n\n          // Add handlers for move and up events - if we were mousedown then we listen for mousemove and mouseup, if\n          // we were touchdown then we listen for touchmove and touchup.  Also remove the handler for the equivalent\n          // down event - so if we're touchdown, then remove the mousedown handler until this event is over, if we're\n          // mousedown then remove the touchdown handler until this event is over, this avoids processing duplicate events\n          if ( event.type === 'touchstart' ){\n            $document.on('touchend', upFunction);\n            $document.on('touchmove', moveFunction);\n            $elm.off('mousedown', downFunction);\n          } else {\n            $document.on('mouseup', upFunction);\n            $document.on('mousemove', moveFunction);\n            $elm.off('touchstart', downFunction);\n          }\n        };\n\n        var onDownEvents = function() {\n          $elm.on('mousedown', downFunction);\n          $elm.on('touchstart', downFunction);\n        };\n\n        var offAllEvents = function() {\n          $document.off('mouseup', upFunction);\n          $document.off('touchend', upFunction);\n          $document.off('mousemove', moveFunction);\n          $document.off('touchmove', moveFunction);\n          $elm.off('mousedown', downFunction);\n          $elm.off('touchstart', downFunction);\n        };\n\n        onDownEvents();\n\n\n        // On doubleclick, resize to fit all rendered cells\n        var dblClickFn = function(event, args){\n          event.stopPropagation();\n\n          var col = uiGridResizeColumnsService.findTargetCol($scope.col, $scope.position, rtlMultiplier);\n\n          // Don't resize if it's disabled on this column\n          if (col.colDef.enableColumnResizing === false) {\n            return;\n          }\n\n          // Go through the rendered rows and find out the max size for the data in this column\n          var maxWidth = 0;\n          var xDiff = 0;\n\n          // Get the parent render container element\n          var renderContainerElm = gridUtil.closestElm($elm, '.ui-grid-render-container');\n\n          // Get the cell contents so we measure correctly. For the header cell we have to account for the sort icon and the menu buttons, if present\n          var cells = renderContainerElm.querySelectorAll('.' + uiGridConstants.COL_CLASS_PREFIX + col.uid + ' .ui-grid-cell-contents');\n          Array.prototype.forEach.call(cells, function (cell) {\n              // Get the cell width\n              // gridUtil.logDebug('width', gridUtil.elementWidth(cell));\n\n              // Account for the menu button if it exists\n              var menuButton;\n              if (angular.element(cell).parent().hasClass('ui-grid-header-cell')) {\n                menuButton = angular.element(cell).parent()[0].querySelectorAll('.ui-grid-column-menu-button');\n              }\n\n              gridUtil.fakeElement(cell, {}, function(newElm) {\n                // Make the element float since it's a div and can expand to fill its container\n                var e = angular.element(newElm);\n                e.attr('style', 'float: left');\n\n                var width = gridUtil.elementWidth(e);\n\n                if (menuButton) {\n                  var menuButtonWidth = gridUtil.elementWidth(menuButton);\n                  width = width + menuButtonWidth;\n                }\n\n                if (width > maxWidth) {\n                  maxWidth = width;\n                  xDiff = maxWidth - width;\n                }\n              });\n            });\n\n          // check we're not outside the allowable bounds for this column\n          col.width = constrainWidth(col, maxWidth);\n          col.hasCustomWidth = true;\n\n          refreshCanvas(xDiff);\n\n          uiGridResizeColumnsService.fireColumnSizeChanged(uiGridCtrl.grid, col.colDef, xDiff);        };\n        $elm.on('dblclick', dblClickFn);\n\n        $elm.on('$destroy', function() {\n          $elm.off('dblclick', dblClickFn);\n          offAllEvents();\n        });\n      }\n    };\n\n    return resizer;\n  }]);\n\n})();\n\n(function () {\n  'use strict';\n\n  /**\n   * @ngdoc overview\n   * @name ui.grid.rowEdit\n   * @description\n   *\n   * # ui.grid.rowEdit\n   *\n   * <div class=\"alert alert-success\" role=\"alert\"><strong>Stable</strong> This feature is stable. There should no longer be breaking api changes without a deprecation warning.</div>\n   *\n   * This module extends the edit feature to provide tracking and saving of rows\n   * of data.  The tutorial provides more information on how this feature is best\n   * used {@link tutorial/205_row_editable here}.\n   * <br/>\n   * This feature depends on usage of the ui-grid-edit feature, and also benefits\n   * from use of ui-grid-cellNav to provide the full spreadsheet-like editing\n   * experience\n   *\n   */\n\n  var module = angular.module('ui.grid.rowEdit', ['ui.grid', 'ui.grid.edit', 'ui.grid.cellNav']);\n\n  /**\n   *  @ngdoc object\n   *  @name ui.grid.rowEdit.constant:uiGridRowEditConstants\n   *\n   *  @description constants available in row edit module\n   */\n  module.constant('uiGridRowEditConstants', {\n  });\n\n  /**\n   *  @ngdoc service\n   *  @name ui.grid.rowEdit.service:uiGridRowEditService\n   *\n   *  @description Services for row editing features\n   */\n  module.service('uiGridRowEditService', ['$interval', '$q', 'uiGridConstants', 'uiGridRowEditConstants', 'gridUtil',\n    function ($interval, $q, uiGridConstants, uiGridRowEditConstants, gridUtil) {\n\n      var service = {\n\n        initializeGrid: function (scope, grid) {\n          /**\n           *  @ngdoc object\n           *  @name ui.grid.rowEdit.api:PublicApi\n           *\n           *  @description Public Api for rowEdit feature\n           */\n\n          grid.rowEdit = {};\n\n          var publicApi = {\n            events: {\n              rowEdit: {\n                /**\n                 * @ngdoc event\n                 * @eventOf ui.grid.rowEdit.api:PublicApi\n                 * @name saveRow\n                 * @description raised when a row is ready for saving.  Once your\n                 * row has saved you may need to use angular.extend to update the\n                 * data entity with any changed data from your save (for example,\n                 * lock version information if you're using optimistic locking,\n                 * or last update time/user information).\n                 *\n                 * Your method should call setSavePromise somewhere in the body before\n                 * returning control.  The feature will then wait, with the gridRow greyed out\n                 * whilst this promise is being resolved.\n                 *\n                 * <pre>\n                 *      gridApi.rowEdit.on.saveRow(scope,function(rowEntity){})\n                 * </pre>\n                 * and somewhere within the event handler:\n                 * <pre>\n                 *      gridApi.rowEdit.setSavePromise( rowEntity, savePromise)\n                 * </pre>\n                 * @param {object} rowEntity the options.data element that was edited\n                 * @returns {promise} Your saveRow method should return a promise, the\n                 * promise should either be resolved (implying successful save), or\n                 * rejected (implying an error).\n                 */\n                saveRow: function (rowEntity) {\n                }\n              }\n            },\n            methods: {\n              rowEdit: {\n                /**\n                 * @ngdoc method\n                 * @methodOf ui.grid.rowEdit.api:PublicApi\n                 * @name setSavePromise\n                 * @description Sets the promise associated with the row save, mandatory that\n                 * the saveRow event handler calls this method somewhere before returning.\n                 * <pre>\n                 *      gridApi.rowEdit.setSavePromise(rowEntity, savePromise)\n                 * </pre>\n                 * @param {object} rowEntity a data row from the grid for which a save has\n                 * been initiated\n                 * @param {promise} savePromise the promise that will be resolved when the\n                 * save is successful, or rejected if the save fails\n                 *\n                 */\n                setSavePromise: function ( rowEntity, savePromise) {\n                  service.setSavePromise(grid, rowEntity, savePromise);\n                },\n                /**\n                 * @ngdoc method\n                 * @methodOf ui.grid.rowEdit.api:PublicApi\n                 * @name getDirtyRows\n                 * @description Returns all currently dirty rows\n                 * <pre>\n                 *      gridApi.rowEdit.getDirtyRows(grid)\n                 * </pre>\n                 * @returns {array} An array of gridRows that are currently dirty\n                 *\n                 */\n                getDirtyRows: function () {\n                  return grid.rowEdit.dirtyRows ? grid.rowEdit.dirtyRows : [];\n                },\n                /**\n                 * @ngdoc method\n                 * @methodOf ui.grid.rowEdit.api:PublicApi\n                 * @name getErrorRows\n                 * @description Returns all currently errored rows\n                 * <pre>\n                 *      gridApi.rowEdit.getErrorRows(grid)\n                 * </pre>\n                 * @returns {array} An array of gridRows that are currently in error\n                 *\n                 */\n                getErrorRows: function () {\n                  return grid.rowEdit.errorRows ? grid.rowEdit.errorRows : [];\n                },\n                /**\n                 * @ngdoc method\n                 * @methodOf ui.grid.rowEdit.api:PublicApi\n                 * @name flushDirtyRows\n                 * @description Triggers a save event for all currently dirty rows, could\n                 * be used where user presses a save button or navigates away from the page\n                 * <pre>\n                 *      gridApi.rowEdit.flushDirtyRows(grid)\n                 * </pre>\n                 * @returns {promise} a promise that represents the aggregate of all\n                 * of the individual save promises - i.e. it will be resolved when all\n                 * the individual save promises have been resolved.\n                 *\n                 */\n                flushDirtyRows: function () {\n                  return service.flushDirtyRows(grid);\n                },\n\n                /**\n                 * @ngdoc method\n                 * @methodOf ui.grid.rowEdit.api:PublicApi\n                 * @name setRowsDirty\n                 * @description Sets each of the rows passed in dataRows\n                 * to be dirty.  note that if you have only just inserted the\n                 * rows into your data you will need to wait for a $digest cycle\n                 * before the gridRows are present - so often you would wrap this\n                 * call in a $interval or $timeout\n                 * <pre>\n                 *      $interval( function() {\n                 *        gridApi.rowEdit.setRowsDirty(myDataRows);\n                 *      }, 0, 1);\n                 * </pre>\n                 * @param {array} dataRows the data entities for which the gridRows\n                 * should be set dirty.\n                 *\n                 */\n                setRowsDirty: function ( dataRows) {\n                  service.setRowsDirty(grid, dataRows);\n                },\n\n                /**\n                 * @ngdoc method\n                 * @methodOf ui.grid.rowEdit.api:PublicApi\n                 * @name setRowsClean\n                 * @description Sets each of the rows passed in dataRows\n                 * to be clean, removing them from the dirty cache and the error cache,\n                 * and clearing the error flag and the dirty flag\n                 * <pre>\n                 *      var gridRows = $scope.gridApi.rowEdit.getDirtyRows();\n                 *      var dataRows = gridRows.map( function( gridRow ) { return gridRow.entity; });\n                 *      $scope.gridApi.rowEdit.setRowsClean( dataRows );\n                 * </pre>\n                 * @param {array} dataRows the data entities for which the gridRows\n                 * should be set clean.\n                 *\n                 */\n                setRowsClean: function ( dataRows) {\n                  service.setRowsClean(grid, dataRows);\n                }\n              }\n            }\n          };\n\n          grid.api.registerEventsFromObject(publicApi.events);\n          grid.api.registerMethodsFromObject(publicApi.methods);\n\n          grid.api.core.on.renderingComplete( scope, function ( gridApi ) {\n            grid.api.edit.on.afterCellEdit( scope, service.endEditCell );\n            grid.api.edit.on.beginCellEdit( scope, service.beginEditCell );\n            grid.api.edit.on.cancelCellEdit( scope, service.cancelEditCell );\n\n            if ( grid.api.cellNav ) {\n              grid.api.cellNav.on.navigate( scope, service.navigate );\n            }\n          });\n\n        },\n\n        defaultGridOptions: function (gridOptions) {\n\n          /**\n           *  @ngdoc object\n           *  @name ui.grid.rowEdit.api:GridOptions\n           *\n           *  @description Options for configuring the rowEdit feature, these are available to be\n           *  set using the ui-grid {@link ui.grid.class:GridOptions gridOptions}\n           */\n\n        },\n\n\n        /**\n         * @ngdoc method\n         * @methodOf ui.grid.rowEdit.service:uiGridRowEditService\n         * @name saveRow\n         * @description  Returns a function that saves the specified row from the grid,\n         * and returns a promise\n         * @param {object} grid the grid for which dirty rows should be flushed\n         * @param {GridRow} gridRow the row that should be saved\n         * @returns {function} the saveRow function returns a function.  That function\n         * in turn, when called, returns a promise relating to the save callback\n         */\n        saveRow: function ( grid, gridRow ) {\n          var self = this;\n\n          return function() {\n            gridRow.isSaving = true;\n\n            if ( gridRow.rowEditSavePromise ){\n              // don't save the row again if it's already saving - that causes stale object exceptions\n              return gridRow.rowEditSavePromise;\n            }\n\n            var promise = grid.api.rowEdit.raise.saveRow( gridRow.entity );\n\n            if ( gridRow.rowEditSavePromise ){\n              gridRow.rowEditSavePromise.then( self.processSuccessPromise( grid, gridRow ), self.processErrorPromise( grid, gridRow ));\n            } else {\n              gridUtil.logError( 'A promise was not returned when saveRow event was raised, either nobody is listening to event, or event handler did not return a promise' );\n            }\n            return promise;\n          };\n        },\n\n\n        /**\n         * @ngdoc method\n         * @methodOf  ui.grid.rowEdit.service:uiGridRowEditService\n         * @name setSavePromise\n         * @description Sets the promise associated with the row save, mandatory that\n         * the saveRow event handler calls this method somewhere before returning.\n         * <pre>\n         *      gridApi.rowEdit.setSavePromise(grid, rowEntity)\n         * </pre>\n         * @param {object} grid the grid for which dirty rows should be returned\n         * @param {object} rowEntity a data row from the grid for which a save has\n         * been initiated\n         * @param {promise} savePromise the promise that will be resolved when the\n         * save is successful, or rejected if the save fails\n         *\n         */\n        setSavePromise: function (grid, rowEntity, savePromise) {\n          var gridRow = grid.getRow( rowEntity );\n          gridRow.rowEditSavePromise = savePromise;\n        },\n\n\n        /**\n         * @ngdoc method\n         * @methodOf ui.grid.rowEdit.service:uiGridRowEditService\n         * @name processSuccessPromise\n         * @description  Returns a function that processes the successful\n         * resolution of a save promise\n         * @param {object} grid the grid for which the promise should be processed\n         * @param {GridRow} gridRow the row that has been saved\n         * @returns {function} the success handling function\n         */\n        processSuccessPromise: function ( grid, gridRow ) {\n          var self = this;\n\n          return function() {\n            delete gridRow.isSaving;\n            delete gridRow.isDirty;\n            delete gridRow.isError;\n            delete gridRow.rowEditSaveTimer;\n            delete gridRow.rowEditSavePromise;\n            self.removeRow( grid.rowEdit.errorRows, gridRow );\n            self.removeRow( grid.rowEdit.dirtyRows, gridRow );\n          };\n        },\n\n\n        /**\n         * @ngdoc method\n         * @methodOf ui.grid.rowEdit.service:uiGridRowEditService\n         * @name processErrorPromise\n         * @description  Returns a function that processes the failed\n         * resolution of a save promise\n         * @param {object} grid the grid for which the promise should be processed\n         * @param {GridRow} gridRow the row that is now in error\n         * @returns {function} the error handling function\n         */\n        processErrorPromise: function ( grid, gridRow ) {\n          return function() {\n            delete gridRow.isSaving;\n            delete gridRow.rowEditSaveTimer;\n            delete gridRow.rowEditSavePromise;\n\n            gridRow.isError = true;\n\n            if (!grid.rowEdit.errorRows){\n              grid.rowEdit.errorRows = [];\n            }\n            if (!service.isRowPresent( grid.rowEdit.errorRows, gridRow ) ){\n              grid.rowEdit.errorRows.push( gridRow );\n            }\n          };\n        },\n\n\n        /**\n         * @ngdoc method\n         * @methodOf ui.grid.rowEdit.service:uiGridRowEditService\n         * @name removeRow\n         * @description  Removes a row from a cache of rows - either\n         * grid.rowEdit.errorRows or grid.rowEdit.dirtyRows.  If the row\n         * is not present silently does nothing.\n         * @param {array} rowArray the array from which to remove the row\n         * @param {GridRow} gridRow the row that should be removed\n         */\n        removeRow: function( rowArray, removeGridRow ){\n          if (typeof(rowArray) === 'undefined' || rowArray === null){\n            return;\n          }\n\n          rowArray.forEach( function( gridRow, index ){\n            if ( gridRow.uid === removeGridRow.uid ){\n              rowArray.splice( index, 1);\n            }\n          });\n        },\n\n\n        /**\n         * @ngdoc method\n         * @methodOf ui.grid.rowEdit.service:uiGridRowEditService\n         * @name isRowPresent\n         * @description  Checks whether a row is already present\n         * in the given array\n         * @param {array} rowArray the array in which to look for the row\n         * @param {GridRow} gridRow the row that should be looked for\n         */\n        isRowPresent: function( rowArray, removeGridRow ){\n          var present = false;\n          rowArray.forEach( function( gridRow, index ){\n            if ( gridRow.uid === removeGridRow.uid ){\n              present = true;\n            }\n          });\n          return present;\n        },\n\n\n        /**\n         * @ngdoc method\n         * @methodOf ui.grid.rowEdit.service:uiGridRowEditService\n         * @name flushDirtyRows\n         * @description Triggers a save event for all currently dirty rows, could\n         * be used where user presses a save button or navigates away from the page\n         * <pre>\n         *      gridApi.rowEdit.flushDirtyRows(grid)\n         * </pre>\n         * @param {object} grid the grid for which dirty rows should be flushed\n         * @returns {promise} a promise that represents the aggregate of all\n         * of the individual save promises - i.e. it will be resolved when all\n         * the individual save promises have been resolved.\n         *\n         */\n        flushDirtyRows: function(grid){\n          var promises = [];\n          grid.api.rowEdit.getDirtyRows().forEach( function( gridRow ){\n            service.saveRow( grid, gridRow )();\n            promises.push( gridRow.rowEditSavePromise );\n          });\n\n          return $q.all( promises );\n        },\n\n\n        /**\n         * @ngdoc method\n         * @methodOf ui.grid.rowEdit.service:uiGridRowEditService\n         * @name endEditCell\n         * @description Receives an afterCellEdit event from the edit function,\n         * and sets flags as appropriate.  Only the rowEntity parameter\n         * is processed, although other params are available.  Grid\n         * is automatically provided by the gridApi.\n         * @param {object} rowEntity the data entity for which the cell\n         * was edited\n         */\n        endEditCell: function( rowEntity, colDef, newValue, previousValue ){\n          var grid = this.grid;\n          var gridRow = grid.getRow( rowEntity );\n          if ( !gridRow ){ gridUtil.logError( 'Unable to find rowEntity in grid data, dirty flag cannot be set' ); return; }\n\n          if ( newValue !== previousValue || gridRow.isDirty ){\n            if ( !grid.rowEdit.dirtyRows ){\n              grid.rowEdit.dirtyRows = [];\n            }\n\n            if ( !gridRow.isDirty ){\n              gridRow.isDirty = true;\n              grid.rowEdit.dirtyRows.push( gridRow );\n            }\n\n            delete gridRow.isError;\n\n            service.considerSetTimer( grid, gridRow );\n          }\n        },\n\n\n        /**\n         * @ngdoc method\n         * @methodOf ui.grid.rowEdit.service:uiGridRowEditService\n         * @name beginEditCell\n         * @description Receives a beginCellEdit event from the edit function,\n         * and cancels any rowEditSaveTimers if present, as the user is still editing\n         * this row.  Only the rowEntity parameter\n         * is processed, although other params are available.  Grid\n         * is automatically provided by the gridApi.\n         * @param {object} rowEntity the data entity for which the cell\n         * editing has commenced\n         */\n        beginEditCell: function( rowEntity, colDef ){\n          var grid = this.grid;\n          var gridRow = grid.getRow( rowEntity );\n          if ( !gridRow ){ gridUtil.logError( 'Unable to find rowEntity in grid data, timer cannot be cancelled' ); return; }\n\n          service.cancelTimer( grid, gridRow );\n        },\n\n\n        /**\n         * @ngdoc method\n         * @methodOf ui.grid.rowEdit.service:uiGridRowEditService\n         * @name cancelEditCell\n         * @description Receives a cancelCellEdit event from the edit function,\n         * and if the row was already dirty, restarts the save timer.  If the row\n         * was not already dirty, then it's not dirty now either and does nothing.\n         *\n         * Only the rowEntity parameter\n         * is processed, although other params are available.  Grid\n         * is automatically provided by the gridApi.\n         *\n         * @param {object} rowEntity the data entity for which the cell\n         * editing was cancelled\n         */\n        cancelEditCell: function( rowEntity, colDef ){\n          var grid = this.grid;\n          var gridRow = grid.getRow( rowEntity );\n          if ( !gridRow ){ gridUtil.logError( 'Unable to find rowEntity in grid data, timer cannot be set' ); return; }\n\n          service.considerSetTimer( grid, gridRow );\n        },\n\n\n        /**\n         * @ngdoc method\n         * @methodOf ui.grid.rowEdit.service:uiGridRowEditService\n         * @name navigate\n         * @description cellNav tells us that the selected cell has changed.  If\n         * the new row had a timer running, then stop it similar to in a beginCellEdit\n         * call.  If the old row is dirty and not the same as the new row, then\n         * start a timer on it.\n         * @param {object} newRowCol the row and column that were selected\n         * @param {object} oldRowCol the row and column that was left\n         *\n         */\n        navigate: function( newRowCol, oldRowCol ){\n          var grid = this.grid;\n          if ( newRowCol.row.rowEditSaveTimer ){\n            service.cancelTimer( grid, newRowCol.row );\n          }\n\n          if ( oldRowCol && oldRowCol.row && oldRowCol.row !== newRowCol.row ){\n            service.considerSetTimer( grid, oldRowCol.row );\n          }\n        },\n\n\n        /**\n         * @ngdoc property\n         * @propertyOf ui.grid.rowEdit.api:GridOptions\n         * @name rowEditWaitInterval\n         * @description How long the grid should wait for another change on this row\n         * before triggering a save (in milliseconds).  If set to -1, then saves are\n         * never triggered by timer (implying that the user will call flushDirtyRows()\n         * manually)\n         *\n         * @example\n         * Setting the wait interval to 4 seconds\n         * <pre>\n         *   $scope.gridOptions = { rowEditWaitInterval: 4000 }\n         * </pre>\n         *\n         */\n        /**\n         * @ngdoc method\n         * @methodOf ui.grid.rowEdit.service:uiGridRowEditService\n         * @name considerSetTimer\n         * @description Consider setting a timer on this row (if it is dirty).  if there is a timer running\n         * on the row and the row isn't currently saving, cancel it, using cancelTimer, then if the row is\n         * dirty and not currently saving then set a new timer\n         * @param {object} grid the grid for which we are processing\n         * @param {GridRow} gridRow the row for which the timer should be adjusted\n         *\n         */\n        considerSetTimer: function( grid, gridRow ){\n          service.cancelTimer( grid, gridRow );\n\n          if ( gridRow.isDirty && !gridRow.isSaving ){\n            if ( grid.options.rowEditWaitInterval !== -1 ){\n              var waitTime = grid.options.rowEditWaitInterval ? grid.options.rowEditWaitInterval : 2000;\n              gridRow.rowEditSaveTimer = $interval( service.saveRow( grid, gridRow ), waitTime, 1);\n            }\n          }\n        },\n\n\n        /**\n         * @ngdoc method\n         * @methodOf ui.grid.rowEdit.service:uiGridRowEditService\n         * @name cancelTimer\n         * @description cancel the $interval for any timer running on this row\n         * then delete the timer itself\n         * @param {object} grid the grid for which we are processing\n         * @param {GridRow} gridRow the row for which the timer should be adjusted\n         *\n         */\n        cancelTimer: function( grid, gridRow ){\n          if ( gridRow.rowEditSaveTimer && !gridRow.isSaving ){\n            $interval.cancel(gridRow.rowEditSaveTimer);\n            delete gridRow.rowEditSaveTimer;\n          }\n        },\n\n\n        /**\n         * @ngdoc method\n         * @methodOf ui.grid.rowEdit.service:uiGridRowEditService\n         * @name setRowsDirty\n         * @description Sets each of the rows passed in dataRows\n         * to be dirty.  note that if you have only just inserted the\n         * rows into your data you will need to wait for a $digest cycle\n         * before the gridRows are present - so often you would wrap this\n         * call in a $interval or $timeout\n         * <pre>\n         *      $interval( function() {\n         *        gridApi.rowEdit.setRowsDirty( myDataRows);\n         *      }, 0, 1);\n         * </pre>\n         * @param {object} grid the grid for which rows should be set dirty\n         * @param {array} dataRows the data entities for which the gridRows\n         * should be set dirty.\n         *\n         */\n        setRowsDirty: function( grid, myDataRows ) {\n          var gridRow;\n          myDataRows.forEach( function( value, index ){\n            gridRow = grid.getRow( value );\n            if ( gridRow ){\n              if ( !grid.rowEdit.dirtyRows ){\n                grid.rowEdit.dirtyRows = [];\n              }\n\n              if ( !gridRow.isDirty ){\n                gridRow.isDirty = true;\n                grid.rowEdit.dirtyRows.push( gridRow );\n              }\n\n              delete gridRow.isError;\n\n              service.considerSetTimer( grid, gridRow );\n            } else {\n              gridUtil.logError( \"requested row not found in rowEdit.setRowsDirty, row was: \" + value );\n            }\n          });\n        },\n\n\n        /**\n         * @ngdoc method\n         * @methodOf ui.grid.rowEdit.service:uiGridRowEditService\n         * @name setRowsClean\n         * @description Sets each of the rows passed in dataRows\n         * to be clean, clearing the dirty flag and the error flag, and removing\n         * the rows from the dirty and error caches.\n         * @param {object} grid the grid for which rows should be set clean\n         * @param {array} dataRows the data entities for which the gridRows\n         * should be set clean.\n         *\n         */\n        setRowsClean: function( grid, myDataRows ) {\n          var gridRow;\n\n          myDataRows.forEach( function( value, index ){\n            gridRow = grid.getRow( value );\n            if ( gridRow ){\n              delete gridRow.isDirty;\n              service.removeRow( grid.rowEdit.dirtyRows, gridRow );\n              service.cancelTimer( grid, gridRow );\n\n              delete gridRow.isError;\n              service.removeRow( grid.rowEdit.errorRows, gridRow );\n            } else {\n              gridUtil.logError( \"requested row not found in rowEdit.setRowsClean, row was: \" + value );\n            }\n          });\n        }\n\n      };\n\n      return service;\n\n    }]);\n\n  /**\n   *  @ngdoc directive\n   *  @name ui.grid.rowEdit.directive:uiGridEdit\n   *  @element div\n   *  @restrict A\n   *\n   *  @description Adds row editing features to the ui-grid-edit directive.\n   *\n   */\n  module.directive('uiGridRowEdit', ['gridUtil', 'uiGridRowEditService', 'uiGridEditConstants',\n  function (gridUtil, uiGridRowEditService, uiGridEditConstants) {\n    return {\n      replace: true,\n      priority: 0,\n      require: '^uiGrid',\n      scope: false,\n      compile: function () {\n        return {\n          pre: function ($scope, $elm, $attrs, uiGridCtrl) {\n            uiGridRowEditService.initializeGrid($scope, uiGridCtrl.grid);\n          },\n          post: function ($scope, $elm, $attrs, uiGridCtrl) {\n          }\n        };\n      }\n    };\n  }]);\n\n\n  /**\n   *  @ngdoc directive\n   *  @name ui.grid.rowEdit.directive:uiGridViewport\n   *  @element div\n   *\n   *  @description Stacks on top of ui.grid.uiGridViewport to alter the attributes used\n   *  for the grid row to allow coloring of saving and error rows\n   */\n  module.directive('uiGridViewport',\n    ['$compile', 'uiGridConstants', 'gridUtil', '$parse',\n      function ($compile, uiGridConstants, gridUtil, $parse) {\n        return {\n          priority: -200, // run after default  directive\n          scope: false,\n          compile: function ($elm, $attrs) {\n            var rowRepeatDiv = angular.element($elm.children().children()[0]);\n\n            var existingNgClass = rowRepeatDiv.attr(\"ng-class\");\n            var newNgClass = '';\n            if ( existingNgClass ) {\n              newNgClass = existingNgClass.slice(0, -1) + \", 'ui-grid-row-dirty': row.isDirty, 'ui-grid-row-saving': row.isSaving, 'ui-grid-row-error': row.isError}\";\n            } else {\n              newNgClass = \"{'ui-grid-row-dirty': row.isDirty, 'ui-grid-row-saving': row.isSaving, 'ui-grid-row-error': row.isError}\";\n            }\n            rowRepeatDiv.attr(\"ng-class\", newNgClass);\n\n            return {\n              pre: function ($scope, $elm, $attrs, controllers) {\n\n              },\n              post: function ($scope, $elm, $attrs, controllers) {\n              }\n            };\n          }\n        };\n      }]);\n\n})();\n\n(function () {\n  'use strict';\n\n  /**\n   * @ngdoc overview\n   * @name ui.grid.saveState\n   * @description\n   *\n   * # ui.grid.saveState\n   *\n   * <div class=\"alert alert-success\" role=\"alert\"><strong>Stable</strong> This feature is stable. There should no longer be breaking api changes without a deprecation warning.</div>\n   *\n   * This module provides the ability to save the grid state, and restore\n   * it when the user returns to the page.\n   *\n   * No UI is provided, the caller should provide their own UI/buttons\n   * as appropriate. Usually the navigate events would be used to save\n   * the grid state and restore it.\n   *\n   * <br/>\n   * <br/>\n   *\n   * <div doc-module-components=\"ui.grid.save-state\"></div>\n   */\n\n  var module = angular.module('ui.grid.saveState', ['ui.grid', 'ui.grid.selection', 'ui.grid.cellNav', 'ui.grid.grouping', 'ui.grid.pinning', 'ui.grid.treeView']);\n\n  /**\n   *  @ngdoc object\n   *  @name ui.grid.saveState.constant:uiGridSaveStateConstants\n   *\n   *  @description constants available in save state module\n   */\n\n  module.constant('uiGridSaveStateConstants', {\n    featureName: 'saveState'\n  });\n\n  /**\n   *  @ngdoc service\n   *  @name ui.grid.saveState.service:uiGridSaveStateService\n   *\n   *  @description Services for saveState feature\n   */\n  module.service('uiGridSaveStateService', ['$q', 'uiGridSaveStateConstants', 'gridUtil', '$compile', '$interval', 'uiGridConstants',\n    function ($q, uiGridSaveStateConstants, gridUtil, $compile, $interval, uiGridConstants ) {\n\n      var service = {\n\n        initializeGrid: function (grid) {\n\n          //add feature namespace and any properties to grid for needed state\n          grid.saveState = {};\n          this.defaultGridOptions(grid.options);\n\n          /**\n           *  @ngdoc object\n           *  @name ui.grid.saveState.api:PublicApi\n           *\n           *  @description Public Api for saveState feature\n           */\n          var publicApi = {\n            events: {\n              saveState: {\n              }\n            },\n            methods: {\n              saveState: {\n                /**\n                 * @ngdoc function\n                 * @name save\n                 * @methodOf  ui.grid.saveState.api:PublicApi\n                 * @description Packages the current state of the grid into\n                 * an object, and provides it to the user for saving\n                 * @returns {object} the state as a javascript object that can be saved\n                 */\n                save: function () {\n                  return service.save(grid);\n                },\n                /**\n                 * @ngdoc function\n                 * @name restore\n                 * @methodOf  ui.grid.saveState.api:PublicApi\n                 * @description Restores the provided state into the grid\n                 * @param {scope} $scope a scope that we can broadcast on\n                 * @param {object} state the state that should be restored into the grid\n                 */\n                restore: function ( $scope, state) {\n                  service.restore(grid, $scope, state);\n                }\n              }\n            }\n          };\n\n          grid.api.registerEventsFromObject(publicApi.events);\n\n          grid.api.registerMethodsFromObject(publicApi.methods);\n\n        },\n\n        defaultGridOptions: function (gridOptions) {\n          //default option to true unless it was explicitly set to false\n          /**\n           * @ngdoc object\n           * @name ui.grid.saveState.api:GridOptions\n           *\n           * @description GridOptions for saveState feature, these are available to be\n           * set using the ui-grid {@link ui.grid.class:GridOptions gridOptions}\n           */\n          /**\n           * @ngdoc object\n           * @name saveWidths\n           * @propertyOf  ui.grid.saveState.api:GridOptions\n           * @description Save the current column widths.  Note that unless\n           * you've provided the user with some way to resize their columns (say\n           * the resize columns feature), then this makes little sense.\n           * <br/>Defaults to true\n           */\n          gridOptions.saveWidths = gridOptions.saveWidths !== false;\n          /**\n           * @ngdoc object\n           * @name saveOrder\n           * @propertyOf  ui.grid.saveState.api:GridOptions\n           * @description Restore the current column order.  Note that unless\n           * you've provided the user with some way to reorder their columns (for\n           * example the move columns feature), this makes little sense.\n           * <br/>Defaults to true\n           */\n          gridOptions.saveOrder = gridOptions.saveOrder !== false;\n          /**\n           * @ngdoc object\n           * @name saveScroll\n           * @propertyOf  ui.grid.saveState.api:GridOptions\n           * @description Save the current scroll position.  Note that this\n           * is saved as the percentage of the grid scrolled - so if your\n           * user returns to a grid with a significantly different number of\n           * rows (perhaps some data has been deleted) then the scroll won't\n           * actually show the same rows as before.  If you want to scroll to\n           * a specific row then you should instead use the saveFocus option, which\n           * is the default.\n           *\n           * Note that this element will only be saved if the cellNav feature is\n           * enabled\n           * <br/>Defaults to false\n           */\n          gridOptions.saveScroll = gridOptions.saveScroll === true;\n          /**\n           * @ngdoc object\n           * @name saveFocus\n           * @propertyOf  ui.grid.saveState.api:GridOptions\n           * @description Save the current focused cell.  On returning\n           * to this focused cell we'll also scroll.  This option is\n           * preferred to the saveScroll option, so is set to true by\n           * default.  If saveScroll is set to true then this option will\n           * be disabled.\n           *\n           * By default this option saves the current row number and column\n           * number, and returns to that row and column.  However, if you define\n           * a saveRowIdentity function, then it will return you to the currently\n           * selected column within that row (in a business sense - so if some\n           * rows have been deleted, it will still find the same data, presuming it\n           * still exists in the list.  If it isn't in the list then it will instead\n           * return to the same row number - i.e. scroll percentage)\n           *\n           * Note that this option will do nothing if the cellNav\n           * feature is not enabled.\n           *\n           * <br/>Defaults to true (unless saveScroll is true)\n           */\n          gridOptions.saveFocus = gridOptions.saveScroll !== true && gridOptions.saveFocus !== false;\n          /**\n           * @ngdoc object\n           * @name saveRowIdentity\n           * @propertyOf  ui.grid.saveState.api:GridOptions\n           * @description A function that can be called, passing in a rowEntity,\n           * and that will return a unique id for that row.  This might simply\n           * return the `id` field from that row (if you have one), or it might\n           * concatenate some fields within the row to make a unique value.\n           *\n           * This value will be used to find the same row again and set the focus\n           * to it, if it exists when we return.\n           *\n           * <br/>Defaults to undefined\n           */\n          /**\n           * @ngdoc object\n           * @name saveVisible\n           * @propertyOf  ui.grid.saveState.api:GridOptions\n           * @description Save whether or not columns are visible.\n           *\n           * <br/>Defaults to true\n           */\n          gridOptions.saveVisible = gridOptions.saveVisible !== false;\n          /**\n           * @ngdoc object\n           * @name saveSort\n           * @propertyOf  ui.grid.saveState.api:GridOptions\n           * @description Save the current sort state for each column\n           *\n           * <br/>Defaults to true\n           */\n          gridOptions.saveSort = gridOptions.saveSort !== false;\n          /**\n           * @ngdoc object\n           * @name saveFilter\n           * @propertyOf  ui.grid.saveState.api:GridOptions\n           * @description Save the current filter state for each column\n           *\n           * <br/>Defaults to true\n           */\n          gridOptions.saveFilter = gridOptions.saveFilter !== false;\n          /**\n           * @ngdoc object\n           * @name saveSelection\n           * @propertyOf  ui.grid.saveState.api:GridOptions\n           * @description Save the currently selected rows.  If the `saveRowIdentity` callback\n           * is defined, then it will save the id of the row and select that.  If not, then\n           * it will attempt to select the rows by row number, which will give the wrong results\n           * if the data set has changed in the mean-time.\n           *\n           * Note that this option only does anything\n           * if the selection feature is enabled.\n           *\n           * <br/>Defaults to true\n           */\n          gridOptions.saveSelection = gridOptions.saveSelection !== false;\n          /**\n           * @ngdoc object\n           * @name saveGrouping\n           * @propertyOf  ui.grid.saveState.api:GridOptions\n           * @description Save the grouping configuration.  If set to true and the\n           * grouping feature is not enabled then does nothing.\n           *\n           * <br/>Defaults to true\n           */\n          gridOptions.saveGrouping = gridOptions.saveGrouping !== false;\n          /**\n           * @ngdoc object\n           * @name saveGroupingExpandedStates\n           * @propertyOf  ui.grid.saveState.api:GridOptions\n           * @description Save the grouping row expanded states.  If set to true and the\n           * grouping feature is not enabled then does nothing.\n           *\n           * This can be quite a bit of data, in many cases you wouldn't want to save this\n           * information.\n           *\n           * <br/>Defaults to false\n           */\n          gridOptions.saveGroupingExpandedStates = gridOptions.saveGroupingExpandedStates === true;\n          /**\n           * @ngdoc object\n           * @name savePinning\n           * @propertyOf ui.grid.saveState.api:GridOptions\n           * @description Save pinning state for columns.\n           *\n           * <br/>Defaults to true\n           */\n          gridOptions.savePinning = gridOptions.savePinning !== false;\n          /**\n           * @ngdoc object\n           * @name saveTreeView\n           * @propertyOf  ui.grid.saveState.api:GridOptions\n           * @description Save the treeView configuration.  If set to true and the\n           * treeView feature is not enabled then does nothing.\n           *\n           * <br/>Defaults to true\n           */\n          gridOptions.saveTreeView = gridOptions.saveTreeView !== false;\n        },\n\n\n\n        /**\n         * @ngdoc function\n         * @name save\n         * @methodOf  ui.grid.saveState.service:uiGridSaveStateService\n         * @description Saves the current grid state into an object, and\n         * passes that object back to the caller\n         * @param {Grid} grid the grid whose state we'd like to save\n         * @returns {object} the state ready to be saved\n         */\n        save: function (grid) {\n          var savedState = {};\n\n          savedState.columns = service.saveColumns( grid );\n          savedState.scrollFocus = service.saveScrollFocus( grid );\n          savedState.selection = service.saveSelection( grid );\n          savedState.grouping = service.saveGrouping( grid );\n          savedState.treeView = service.saveTreeView( grid );\n          savedState.pagination = service.savePagination( grid );\n\n          return savedState;\n        },\n\n\n        /**\n         * @ngdoc function\n         * @name restore\n         * @methodOf  ui.grid.saveState.service:uiGridSaveStateService\n         * @description Applies the provided state to the grid\n         *\n         * @param {Grid} grid the grid whose state we'd like to restore\n         * @param {scope} $scope a scope that we can broadcast on\n         * @param {object} state the state we'd like to restore\n         */\n        restore: function( grid, $scope, state ){\n          if ( state.columns ) {\n            service.restoreColumns( grid, state.columns );\n          }\n\n          if ( state.scrollFocus ){\n            service.restoreScrollFocus( grid, $scope, state.scrollFocus );\n          }\n\n          if ( state.selection ){\n            service.restoreSelection( grid, state.selection );\n          }\n\n          if ( state.grouping ){\n            service.restoreGrouping( grid, state.grouping );\n          }\n\n          if ( state.treeView ){\n            service.restoreTreeView( grid, state.treeView );\n          }\n\n          if ( state.pagination ){\n            service.restorePagination( grid, state.pagination );\n          }\n\n          grid.refresh();\n        },\n\n\n        /**\n         * @ngdoc function\n         * @name saveColumns\n         * @methodOf  ui.grid.saveState.service:uiGridSaveStateService\n         * @description Saves the column setup, including sort, filters, ordering,\n         * pinning and column widths.\n         *\n         * Works through the current columns, storing them in order.  Stores the\n         * column name, then the visible flag, width, sort and filters for each column.\n         *\n         * @param {Grid} grid the grid whose state we'd like to save\n         * @returns {array} the columns state ready to be saved\n         */\n        saveColumns: function( grid ) {\n          var columns = [];\n          grid.getOnlyDataColumns().forEach( function( column ) {\n            var savedColumn = {};\n            savedColumn.name = column.name;\n\n            if ( grid.options.saveVisible ){\n              savedColumn.visible = column.visible;\n            }\n\n            if ( grid.options.saveWidths ){\n              savedColumn.width = column.width;\n            }\n\n            // these two must be copied, not just pointed too - otherwise our saved state is pointing to the same object as current state\n            if ( grid.options.saveSort ){\n              savedColumn.sort = angular.copy( column.sort );\n            }\n\n            if ( grid.options.saveFilter ){\n              savedColumn.filters = [];\n              column.filters.forEach( function( filter ){\n                var copiedFilter = {};\n                angular.forEach( filter, function( value, key) {\n                  if ( key !== 'condition' && key !== '$$hashKey' && key !== 'placeholder'){\n                    copiedFilter[key] = value;\n                  }\n                });\n                savedColumn.filters.push(copiedFilter);\n              });\n            }\n\n            if ( !!grid.api.pinning && grid.options.savePinning ){\n              savedColumn.pinned = column.renderContainer ? column.renderContainer : '';\n            }\n\n            columns.push( savedColumn );\n          });\n\n          return columns;\n        },\n\n\n        /**\n         * @ngdoc function\n         * @name saveScrollFocus\n         * @methodOf  ui.grid.saveState.service:uiGridSaveStateService\n         * @description Saves the currently scroll or focus.\n         *\n         * If cellNav isn't present then does nothing - we can't return\n         * to the scroll position without cellNav anyway.\n         *\n         * If the cellNav module is present, and saveFocus is true, then\n         * it saves the currently focused cell.  If rowIdentity is present\n         * then saves using rowIdentity, otherwise saves visibleRowNum.\n         *\n         * If the cellNav module is not present, and saveScroll is true, then\n         * it approximates the current scroll row and column, and saves that.\n         *\n         * @param {Grid} grid the grid whose state we'd like to save\n         * @returns {object} the selection state ready to be saved\n         */\n        saveScrollFocus: function( grid ){\n          if ( !grid.api.cellNav ){\n            return {};\n          }\n\n          var scrollFocus = {};\n          if ( grid.options.saveFocus ){\n            scrollFocus.focus = true;\n            var rowCol = grid.api.cellNav.getFocusedCell();\n            if ( rowCol !== null ) {\n              if ( rowCol.col !== null ){\n                scrollFocus.colName = rowCol.col.colDef.name;\n              }\n              if ( rowCol.row !== null ){\n                scrollFocus.rowVal = service.getRowVal( grid, rowCol.row );\n              }\n            }\n          }\n\n          if ( grid.options.saveScroll || grid.options.saveFocus && !scrollFocus.colName && !scrollFocus.rowVal ) {\n            scrollFocus.focus = false;\n            if ( grid.renderContainers.body.prevRowScrollIndex ){\n              scrollFocus.rowVal = service.getRowVal( grid, grid.renderContainers.body.visibleRowCache[ grid.renderContainers.body.prevRowScrollIndex ]);\n            }\n\n            if ( grid.renderContainers.body.prevColScrollIndex ){\n              scrollFocus.colName = grid.renderContainers.body.visibleColumnCache[ grid.renderContainers.body.prevColScrollIndex ].name;\n            }\n          }\n\n          return scrollFocus;\n        },\n\n\n        /**\n         * @ngdoc function\n         * @name saveSelection\n         * @methodOf  ui.grid.saveState.service:uiGridSaveStateService\n         * @description Saves the currently selected rows, if the selection feature is enabled\n         * @param {Grid} grid the grid whose state we'd like to save\n         * @returns {array} the selection state ready to be saved\n         */\n        saveSelection: function( grid ){\n          if ( !grid.api.selection || !grid.options.saveSelection ){\n            return [];\n          }\n\n          var selection = grid.api.selection.getSelectedGridRows().map( function( gridRow ) {\n            return service.getRowVal( grid, gridRow );\n          });\n\n          return selection;\n        },\n\n\n        /**\n         * @ngdoc function\n         * @name saveGrouping\n         * @methodOf  ui.grid.saveState.service:uiGridSaveStateService\n         * @description Saves the grouping state, if the grouping feature is enabled\n         * @param {Grid} grid the grid whose state we'd like to save\n         * @returns {object} the grouping state ready to be saved\n         */\n        saveGrouping: function( grid ){\n          if ( !grid.api.grouping || !grid.options.saveGrouping ){\n            return {};\n          }\n\n          return grid.api.grouping.getGrouping( grid.options.saveGroupingExpandedStates );\n        },\n\n\n        /**\n         * @ngdoc function\n         * @name savePagination\n         * @methodOf  ui.grid.saveState.service:uiGridSaveStateService\n         * @description Saves the pagination state, if the pagination feature is enabled\n         * @param {Grid} grid the grid whose state we'd like to save\n         * @returns {object} the pagination state ready to be saved\n         */\n        savePagination: function( grid ) {\n          if ( !grid.api.pagination || !grid.options.paginationPageSize ){\n            return {};\n          }\n\n          return {\n            paginationCurrentPage: grid.options.paginationCurrentPage,\n            paginationPageSize: grid.options.paginationPageSize\n          };\n        },\n\n\n        /**\n         * @ngdoc function\n         * @name saveTreeView\n         * @methodOf  ui.grid.saveState.service:uiGridSaveStateService\n         * @description Saves the tree view state, if the tree feature is enabled\n         * @param {Grid} grid the grid whose state we'd like to save\n         * @returns {object} the tree view state ready to be saved\n         */\n        saveTreeView: function( grid ){\n          if ( !grid.api.treeView || !grid.options.saveTreeView ){\n            return {};\n          }\n\n          return grid.api.treeView.getTreeView();\n        },\n\n\n        /**\n         * @ngdoc function\n         * @name getRowVal\n         * @methodOf  ui.grid.saveState.service:uiGridSaveStateService\n         * @description Helper function that gets either the rowNum or\n         * the saveRowIdentity, given a gridRow\n         * @param {Grid} grid the grid the row is in\n         * @param {GridRow} gridRow the row we want the rowNum for\n         * @returns {object} an object containing { identity: true/false, row: rowNumber/rowIdentity }\n         *\n         */\n        getRowVal: function( grid, gridRow ){\n          if ( !gridRow ) {\n            return null;\n          }\n\n          var rowVal = {};\n          if ( grid.options.saveRowIdentity ){\n            rowVal.identity = true;\n            rowVal.row = grid.options.saveRowIdentity( gridRow.entity );\n          } else {\n            rowVal.identity = false;\n            rowVal.row = grid.renderContainers.body.visibleRowCache.indexOf( gridRow );\n          }\n          return rowVal;\n        },\n\n\n        /**\n         * @ngdoc function\n         * @name restoreColumns\n         * @methodOf  ui.grid.saveState.service:uiGridSaveStateService\n         * @description Restores the columns, including order, visible, width,\n         * pinning, sort and filters.\n         *\n         * @param {Grid} grid the grid whose state we'd like to restore\n         * @param {object} columnsState the list of columns we had before, with their state\n         */\n        restoreColumns: function( grid, columnsState ){\n          var isSortChanged = false;\n\n          columnsState.forEach( function( columnState, index ) {\n            var currentCol = grid.getColumn( columnState.name );\n\n            if ( currentCol && !grid.isRowHeaderColumn(currentCol) ){\n              if ( grid.options.saveVisible &&\n                   ( currentCol.visible !== columnState.visible ||\n                     currentCol.colDef.visible !== columnState.visible ) ){\n                currentCol.visible = columnState.visible;\n                currentCol.colDef.visible = columnState.visible;\n                grid.api.core.raise.columnVisibilityChanged(currentCol);\n              }\n\n              if ( grid.options.saveWidths && currentCol.width !== columnState.width){\n                currentCol.width = columnState.width;\n                currentCol.hasCustomWidth = true;\n              }\n\n              if ( grid.options.saveSort &&\n                   !angular.equals(currentCol.sort, columnState.sort) &&\n                   !( currentCol.sort === undefined && angular.isEmpty(columnState.sort) ) ){\n                currentCol.sort = angular.copy( columnState.sort );\n                isSortChanged = true;\n              }\n\n              if ( grid.options.saveFilter &&\n                   !angular.equals(currentCol.filters, columnState.filters ) ){\n                columnState.filters.forEach( function( filter, index ){\n                  angular.extend( currentCol.filters[index], filter );\n                  if ( typeof(filter.term) === 'undefined' || filter.term === null ){\n                    delete currentCol.filters[index].term;\n                  }\n                });\n                grid.api.core.raise.filterChanged();\n              }\n\n              if ( !!grid.api.pinning && grid.options.savePinning && currentCol.renderContainer !== columnState.pinned ){\n                grid.api.pinning.pinColumn(currentCol, columnState.pinned);\n              }\n\n              var currentIndex = grid.getOnlyDataColumns().indexOf( currentCol );\n              if (currentIndex !== -1) {\n                if (grid.options.saveOrder && currentIndex !== index) {\n                  var column = grid.columns.splice(currentIndex + grid.rowHeaderColumns.length, 1)[0];\n                  grid.columns.splice(index + grid.rowHeaderColumns.length, 0, column);\n                }\n              }\n            }\n          });\n\n          if ( isSortChanged ) {\n            grid.api.core.raise.sortChanged( grid, grid.getColumnSorting() );\n          }\n        },\n\n\n        /**\n         * @ngdoc function\n         * @name restoreScrollFocus\n         * @methodOf  ui.grid.saveState.service:uiGridSaveStateService\n         * @description Scrolls to the position that was saved.  If focus is true, then\n         * sets focus to the specified row/col.  If focus is false, then scrolls to the\n         * specified row/col.\n         *\n         * @param {Grid} grid the grid whose state we'd like to restore\n         * @param {scope} $scope a scope that we can broadcast on\n         * @param {object} scrollFocusState the scroll/focus state ready to be restored\n         */\n        restoreScrollFocus: function( grid, $scope, scrollFocusState ){\n          if ( !grid.api.cellNav ){\n            return;\n          }\n\n          var colDef, row;\n          if ( scrollFocusState.colName ){\n            var colDefs = grid.options.columnDefs.filter( function( colDef ) { return colDef.name === scrollFocusState.colName; });\n            if ( colDefs.length > 0 ){\n              colDef = colDefs[0];\n            }\n          }\n\n          if ( scrollFocusState.rowVal && scrollFocusState.rowVal.row ){\n            if ( scrollFocusState.rowVal.identity ){\n              row = service.findRowByIdentity( grid, scrollFocusState.rowVal );\n            } else {\n              row = grid.renderContainers.body.visibleRowCache[ scrollFocusState.rowVal.row ];\n            }\n          }\n\n          var entity = row && row.entity ? row.entity : null ;\n\n          if ( colDef || entity ) {\n            if (scrollFocusState.focus ){\n              grid.api.cellNav.scrollToFocus( entity, colDef );\n            } else {\n              grid.scrollTo( entity, colDef );\n            }\n          }\n        },\n\n\n        /**\n         * @ngdoc function\n         * @name restoreSelection\n         * @methodOf  ui.grid.saveState.service:uiGridSaveStateService\n         * @description Selects the rows that are provided in the selection\n         * state.  If you are using `saveRowIdentity` and more than one row matches the identity\n         * function then only the first is selected.\n         * @param {Grid} grid the grid whose state we'd like to restore\n         * @param {object} selectionState the selection state ready to be restored\n         */\n        restoreSelection: function( grid, selectionState ){\n          if ( !grid.api.selection ){\n            return;\n          }\n\n          grid.api.selection.clearSelectedRows();\n\n          selectionState.forEach(  function( rowVal ) {\n            if ( rowVal.identity ){\n              var foundRow = service.findRowByIdentity( grid, rowVal );\n\n              if ( foundRow ){\n                grid.api.selection.selectRow( foundRow.entity );\n              }\n\n            } else {\n              grid.api.selection.selectRowByVisibleIndex( rowVal.row );\n            }\n          });\n        },\n\n\n        /**\n         * @ngdoc function\n         * @name restoreGrouping\n         * @methodOf  ui.grid.saveState.service:uiGridSaveStateService\n         * @description Restores the grouping configuration, if the grouping feature\n         * is enabled.\n         * @param {Grid} grid the grid whose state we'd like to restore\n         * @param {object} groupingState the grouping state ready to be restored\n         */\n        restoreGrouping: function( grid, groupingState ){\n          if ( !grid.api.grouping || typeof(groupingState) === 'undefined' || groupingState === null || angular.equals(groupingState, {}) ){\n            return;\n          }\n\n          grid.api.grouping.setGrouping( groupingState );\n        },\n\n        /**\n         * @ngdoc function\n         * @name restoreTreeView\n         * @methodOf  ui.grid.saveState.service:uiGridSaveStateService\n         * @description Restores the tree view configuration, if the tree view feature\n         * is enabled.\n         * @param {Grid} grid the grid whose state we'd like to restore\n         * @param {object} treeViewState the tree view state ready to be restored\n         */\n        restoreTreeView: function( grid, treeViewState ){\n          if ( !grid.api.treeView || typeof(treeViewState) === 'undefined' || treeViewState === null || angular.equals(treeViewState, {}) ){\n            return;\n          }\n\n          grid.api.treeView.setTreeView( treeViewState );\n        },\n\n        /**\n         * @ngdoc function\n         * @name restorePagination\n         * @methodOf  ui.grid.saveState.service:uiGridSaveStateService\n         * @description Restores the pagination information, if pagination is enabled.\n         * @param {Grid} grid the grid whose state we'd like to restore\n         * @param {object} pagination the pagination object to be restored\n         * @param {number} pagination.paginationCurrentPage the page number to restore\n         * @param {number} pagination.paginationPageSize the number of items displayed per page\n         */\n        restorePagination: function( grid, pagination ){\n          if ( !grid.api.pagination || !grid.options.paginationPageSize ){\n            return;\n          }\n\n          grid.options.paginationCurrentPage = pagination.paginationCurrentPage;\n          grid.options.paginationPageSize = pagination.paginationPageSize;\n        },\n\n        /**\n         * @ngdoc function\n         * @name findRowByIdentity\n         * @methodOf  ui.grid.saveState.service:uiGridSaveStateService\n         * @description Finds a row given it's identity value, returns the first found row\n         * if any are found, otherwise returns null if no rows are found.\n         * @param {Grid} grid the grid whose state we'd like to restore\n         * @param {object} rowVal the row we'd like to find\n         * @returns {gridRow} the found row, or null if none found\n         */\n        findRowByIdentity: function( grid, rowVal ){\n          if ( !grid.options.saveRowIdentity ){\n            return null;\n          }\n\n          var filteredRows = grid.rows.filter( function( gridRow ) {\n            if ( grid.options.saveRowIdentity( gridRow.entity ) === rowVal.row ){\n              return true;\n            } else {\n              return false;\n            }\n          });\n\n          if ( filteredRows.length > 0 ){\n            return filteredRows[0];\n          } else {\n            return null;\n          }\n        }\n      };\n\n      return service;\n\n    }\n  ]);\n\n  /**\n   *  @ngdoc directive\n   *  @name ui.grid.saveState.directive:uiGridSaveState\n   *  @element div\n   *  @restrict A\n   *\n   *  @description Adds saveState features to grid\n   *\n   *  @example\n   <example module=\"app\">\n   <file name=\"app.js\">\n   var app = angular.module('app', ['ui.grid', 'ui.grid.saveState']);\n\n   app.controller('MainCtrl', ['$scope', function ($scope) {\n      $scope.data = [\n        { name: 'Bob', title: 'CEO' },\n        { name: 'Frank', title: 'Lowly Developer' }\n      ];\n\n      $scope.gridOptions = {\n        columnDefs: [\n          {name: 'name'},\n          {name: 'title', enableCellEdit: true}\n        ],\n        data: $scope.data\n      };\n    }]);\n   </file>\n   <file name=\"index.html\">\n   <div ng-controller=\"MainCtrl\">\n   <div ui-grid=\"gridOptions\" ui-grid-save-state></div>\n   </div>\n   </file>\n   </example>\n   */\n  module.directive('uiGridSaveState', ['uiGridSaveStateConstants', 'uiGridSaveStateService', 'gridUtil', '$compile',\n    function (uiGridSaveStateConstants, uiGridSaveStateService, gridUtil, $compile) {\n      return {\n        replace: true,\n        priority: 0,\n        require: '^uiGrid',\n        scope: false,\n        link: function ($scope, $elm, $attrs, uiGridCtrl) {\n          uiGridSaveStateService.initializeGrid(uiGridCtrl.grid);\n        }\n      };\n    }\n  ]);\n})();\n\n(function () {\n  'use strict';\n\n  /**\n   * @ngdoc overview\n   * @name ui.grid.selection\n   * @description\n   *\n   * # ui.grid.selection\n   * This module provides row selection\n   *\n   * <div class=\"alert alert-success\" role=\"alert\"><strong>Stable</strong> This feature is stable. There should no longer be breaking api changes without a deprecation warning.</div>\n   *\n   * <div doc-module-components=\"ui.grid.selection\"></div>\n   */\n\n  var module = angular.module('ui.grid.selection', ['ui.grid']);\n\n  /**\n   *  @ngdoc object\n   *  @name ui.grid.selection.constant:uiGridSelectionConstants\n   *\n   *  @description constants available in selection module\n   */\n  module.constant('uiGridSelectionConstants', {\n    featureName: \"selection\",\n    selectionRowHeaderColName: 'selectionRowHeaderCol'\n  });\n\n  //add methods to GridRow\n  angular.module('ui.grid').config(['$provide', function($provide) {\n    $provide.decorator('GridRow', ['$delegate', function($delegate) {\n\n      /**\n       *  @ngdoc object\n       *  @name ui.grid.selection.api:GridRow\n       *\n       *  @description GridRow prototype functions added for selection\n       */\n\n      /**\n       *  @ngdoc object\n       *  @name enableSelection\n       *  @propertyOf  ui.grid.selection.api:GridRow\n       *  @description Enable row selection for this row, only settable by internal code.\n       *\n       *  The grouping feature, for example, might set group header rows to not be selectable.\n       *  <br/>Defaults to true\n       */\n\n      /**\n       *  @ngdoc object\n       *  @name isSelected\n       *  @propertyOf  ui.grid.selection.api:GridRow\n       *  @description Selected state of row.  Should be readonly. Make any changes to selected state using setSelected().\n       *  <br/>Defaults to false\n       */\n\n\n        /**\n         * @ngdoc function\n         * @name setSelected\n         * @methodOf ui.grid.selection.api:GridRow\n         * @description Sets the isSelected property and updates the selectedCount\n         * Changes to isSelected state should only be made via this function\n         * @param {bool} selected value to set\n         */\n        $delegate.prototype.setSelected = function(selected) {\n          if (selected !== this.isSelected) {\n            this.isSelected = selected;\n            this.grid.selection.selectedCount += selected ? 1 : -1;\n          }\n        };\n\n      return $delegate;\n    }]);\n  }]);\n\n  /**\n   *  @ngdoc service\n   *  @name ui.grid.selection.service:uiGridSelectionService\n   *\n   *  @description Services for selection features\n   */\n  module.service('uiGridSelectionService', ['$q', '$templateCache', 'uiGridSelectionConstants', 'gridUtil',\n    function ($q, $templateCache, uiGridSelectionConstants, gridUtil) {\n\n      var service = {\n\n        initializeGrid: function (grid) {\n\n          //add feature namespace and any properties to grid for needed\n          /**\n           *  @ngdoc object\n           *  @name ui.grid.selection.grid:selection\n           *\n           *  @description Grid properties and functions added for selection\n           */\n          grid.selection = {};\n          grid.selection.lastSelectedRow = null;\n          grid.selection.selectAll = false;\n\n\n          /**\n           *  @ngdoc object\n           *  @name selectedCount\n           *  @propertyOf  ui.grid.selection.grid:selection\n           *  @description Current count of selected rows\n           *  @example\n           *  var count = grid.selection.selectedCount\n           */\n          grid.selection.selectedCount = 0;\n\n          service.defaultGridOptions(grid.options);\n\n          /**\n           *  @ngdoc object\n           *  @name ui.grid.selection.api:PublicApi\n           *\n           *  @description Public Api for selection feature\n           */\n          var publicApi = {\n            events: {\n              selection: {\n                /**\n                 * @ngdoc event\n                 * @name rowSelectionChanged\n                 * @eventOf  ui.grid.selection.api:PublicApi\n                 * @description  is raised after the row.isSelected state is changed\n                 * @param {GridRow} row the row that was selected/deselected\n                 * @param {Event} event object if raised from an event\n                 */\n                rowSelectionChanged: function (scope, row, evt) {\n                },\n                /**\n                 * @ngdoc event\n                 * @name rowSelectionChangedBatch\n                 * @eventOf  ui.grid.selection.api:PublicApi\n                 * @description  is raised after the row.isSelected state is changed\n                 * in bulk, if the `enableSelectionBatchEvent` option is set to true\n                 * (which it is by default).  This allows more efficient processing\n                 * of bulk events.\n                 * @param {array} rows the rows that were selected/deselected\n                 * @param {Event} event object if raised from an event\n                 */\n                rowSelectionChangedBatch: function (scope, rows, evt) {\n                }\n              }\n            },\n            methods: {\n              selection: {\n                /**\n                 * @ngdoc function\n                 * @name toggleRowSelection\n                 * @methodOf  ui.grid.selection.api:PublicApi\n                 * @description Toggles data row as selected or unselected\n                 * @param {object} rowEntity gridOptions.data[] array instance\n                 * @param {Event} event object if raised from an event\n                 */\n                toggleRowSelection: function (rowEntity, evt) {\n                  var row = grid.getRow(rowEntity);\n                  if (row !== null) {\n                    service.toggleRowSelection(grid, row, evt, grid.options.multiSelect, grid.options.noUnselect);\n                  }\n                },\n                /**\n                 * @ngdoc function\n                 * @name selectRow\n                 * @methodOf  ui.grid.selection.api:PublicApi\n                 * @description Select the data row\n                 * @param {object} rowEntity gridOptions.data[] array instance\n                 * @param {Event} event object if raised from an event\n                 */\n                selectRow: function (rowEntity, evt) {\n                  var row = grid.getRow(rowEntity);\n                  if (row !== null && !row.isSelected) {\n                    service.toggleRowSelection(grid, row, evt, grid.options.multiSelect, grid.options.noUnselect);\n                  }\n                },\n                /**\n                 * @ngdoc function\n                 * @name selectRowByVisibleIndex\n                 * @methodOf  ui.grid.selection.api:PublicApi\n                 * @description Select the specified row by visible index (i.e. if you\n                 * specify row 0 you'll get the first visible row selected).  In this context\n                 * visible means of those rows that are theoretically visible (i.e. not filtered),\n                 * rather than rows currently rendered on the screen.\n                 * @param {number} index index within the rowsVisible array\n                 * @param {Event} event object if raised from an event\n                 */\n                selectRowByVisibleIndex: function ( rowNum, evt ) {\n                  var row = grid.renderContainers.body.visibleRowCache[rowNum];\n                  if (row !== null && typeof(row) !== 'undefined' && !row.isSelected) {\n                    service.toggleRowSelection(grid, row, evt, grid.options.multiSelect, grid.options.noUnselect);\n                  }\n                },\n                /**\n                 * @ngdoc function\n                 * @name unSelectRow\n                 * @methodOf  ui.grid.selection.api:PublicApi\n                 * @description UnSelect the data row\n                 * @param {object} rowEntity gridOptions.data[] array instance\n                 * @param {Event} event object if raised from an event\n                 */\n                unSelectRow: function (rowEntity, evt) {\n                  var row = grid.getRow(rowEntity);\n                  if (row !== null && row.isSelected) {\n                    service.toggleRowSelection(grid, row, evt, grid.options.multiSelect, grid.options.noUnselect);\n                  }\n                },\n                /**\n                 * @ngdoc function\n                 * @name selectAllRows\n                 * @methodOf  ui.grid.selection.api:PublicApi\n                 * @description Selects all rows.  Does nothing if multiSelect = false\n                 * @param {Event} event object if raised from an event\n                 */\n                selectAllRows: function (evt) {\n                  if (grid.options.multiSelect === false) {\n                    return;\n                  }\n\n                  var changedRows = [];\n                  grid.rows.forEach(function (row) {\n                    if ( !row.isSelected && row.enableSelection !== false ){\n                      row.setSelected(true);\n                      service.decideRaiseSelectionEvent( grid, row, changedRows, evt );\n                    }\n                  });\n                  service.decideRaiseSelectionBatchEvent( grid, changedRows, evt );\n                  grid.selection.selectAll = true;\n                },\n                /**\n                 * @ngdoc function\n                 * @name selectAllVisibleRows\n                 * @methodOf  ui.grid.selection.api:PublicApi\n                 * @description Selects all visible rows.  Does nothing if multiSelect = false\n                 * @param {Event} event object if raised from an event\n                 */\n                selectAllVisibleRows: function (evt) {\n                  if (grid.options.multiSelect === false) {\n                    return;\n                  }\n\n                  var changedRows = [];\n                  grid.rows.forEach(function (row) {\n                    if (row.visible) {\n                      if (!row.isSelected && row.enableSelection !== false){\n                        row.setSelected(true);\n                        service.decideRaiseSelectionEvent( grid, row, changedRows, evt );\n                      }\n                    } else {\n                      if (row.isSelected){\n                        row.setSelected(false);\n                        service.decideRaiseSelectionEvent( grid, row, changedRows, evt );\n                      }\n                    }\n                  });\n                  service.decideRaiseSelectionBatchEvent( grid, changedRows, evt );\n                  grid.selection.selectAll = true;\n                },\n                /**\n                 * @ngdoc function\n                 * @name clearSelectedRows\n                 * @methodOf  ui.grid.selection.api:PublicApi\n                 * @description Unselects all rows\n                 * @param {Event} event object if raised from an event\n                 */\n                clearSelectedRows: function (evt) {\n                  service.clearSelectedRows(grid, evt);\n                },\n                /**\n                 * @ngdoc function\n                 * @name getSelectedRows\n                 * @methodOf  ui.grid.selection.api:PublicApi\n                 * @description returns all selectedRow's entity references\n                 */\n                getSelectedRows: function () {\n                  return service.getSelectedRows(grid).map(function (gridRow) {\n                    return gridRow.entity;\n                  });\n                },\n                /**\n                 * @ngdoc function\n                 * @name getSelectedGridRows\n                 * @methodOf  ui.grid.selection.api:PublicApi\n                 * @description returns all selectedRow's as gridRows\n                 */\n                getSelectedGridRows: function () {\n                  return service.getSelectedRows(grid);\n                },\n                /**\n                 * @ngdoc function\n                 * @name getSelectedCount\n                 * @methodOf  ui.grid.selection.api:PublicApi\n                 * @description returns the number of rows selected\n                 */\n                getSelectedCount: function () {\n                  return grid.selection.selectedCount;\n                },\n                /**\n                 * @ngdoc function\n                 * @name setMultiSelect\n                 * @methodOf  ui.grid.selection.api:PublicApi\n                 * @description Sets the current gridOption.multiSelect to true or false\n                 * @param {bool} multiSelect true to allow multiple rows\n                 */\n                setMultiSelect: function (multiSelect) {\n                  grid.options.multiSelect = multiSelect;\n                },\n                /**\n                 * @ngdoc function\n                 * @name setModifierKeysToMultiSelect\n                 * @methodOf  ui.grid.selection.api:PublicApi\n                 * @description Sets the current gridOption.modifierKeysToMultiSelect to true or false\n                 * @param {bool} modifierKeysToMultiSelect true to only allow multiple rows when using ctrlKey or shiftKey is used\n                 */\n                setModifierKeysToMultiSelect: function (modifierKeysToMultiSelect) {\n                  grid.options.modifierKeysToMultiSelect = modifierKeysToMultiSelect;\n                },\n                /**\n                 * @ngdoc function\n                 * @name getSelectAllState\n                 * @methodOf  ui.grid.selection.api:PublicApi\n                 * @description Returns whether or not the selectAll checkbox is currently ticked.  The\n                 * grid doesn't automatically select rows when you add extra data - so when you add data\n                 * you need to explicitly check whether the selectAll is set, and then call setVisible rows\n                 * if it is\n                 */\n                getSelectAllState: function () {\n                  return grid.selection.selectAll;\n                }\n\n              }\n            }\n          };\n\n          grid.api.registerEventsFromObject(publicApi.events);\n\n          grid.api.registerMethodsFromObject(publicApi.methods);\n\n        },\n\n        defaultGridOptions: function (gridOptions) {\n          //default option to true unless it was explicitly set to false\n          /**\n           *  @ngdoc object\n           *  @name ui.grid.selection.api:GridOptions\n           *\n           *  @description GridOptions for selection feature, these are available to be\n           *  set using the ui-grid {@link ui.grid.class:GridOptions gridOptions}\n           */\n\n          /**\n           *  @ngdoc object\n           *  @name enableRowSelection\n           *  @propertyOf  ui.grid.selection.api:GridOptions\n           *  @description Enable row selection for entire grid.\n           *  <br/>Defaults to true\n           */\n          gridOptions.enableRowSelection = gridOptions.enableRowSelection !== false;\n          /**\n           *  @ngdoc object\n           *  @name multiSelect\n           *  @propertyOf  ui.grid.selection.api:GridOptions\n           *  @description Enable multiple row selection for entire grid\n           *  <br/>Defaults to true\n           */\n          gridOptions.multiSelect = gridOptions.multiSelect !== false;\n          /**\n           *  @ngdoc object\n           *  @name noUnselect\n           *  @propertyOf  ui.grid.selection.api:GridOptions\n           *  @description Prevent a row from being unselected.  Works in conjunction\n           *  with `multiselect = false` and `gridApi.selection.selectRow()` to allow\n           *  you to create a single selection only grid - a row is always selected, you\n           *  can only select different rows, you can't unselect the row.\n           *  <br/>Defaults to false\n           */\n          gridOptions.noUnselect = gridOptions.noUnselect === true;\n          /**\n           *  @ngdoc object\n           *  @name modifierKeysToMultiSelect\n           *  @propertyOf  ui.grid.selection.api:GridOptions\n           *  @description Enable multiple row selection only when using the ctrlKey or shiftKey. Requires multiSelect to be true.\n           *  <br/>Defaults to false\n           */\n          gridOptions.modifierKeysToMultiSelect = gridOptions.modifierKeysToMultiSelect === true;\n          /**\n           *  @ngdoc object\n           *  @name enableRowHeaderSelection\n           *  @propertyOf  ui.grid.selection.api:GridOptions\n           *  @description Enable a row header to be used for selection\n           *  <br/>Defaults to true\n           */\n          gridOptions.enableRowHeaderSelection = gridOptions.enableRowHeaderSelection !== false;\n          /**\n           *  @ngdoc object\n           *  @name enableFullRowSelection\n           *  @propertyOf  ui.grid.selection.api:GridOptions\n           *  @description Enable selection by clicking anywhere on the row.  Defaults to\n           *  false if `enableRowHeaderSelection` is true, otherwise defaults to false.\n           */\n          if ( typeof(gridOptions.enableFullRowSelection) === 'undefined' ){\n            gridOptions.enableFullRowSelection = !gridOptions.enableRowHeaderSelection;\n          }\n          /**\n           *  @ngdoc object\n           *  @name enableSelectAll\n           *  @propertyOf  ui.grid.selection.api:GridOptions\n           *  @description Enable the select all checkbox at the top of the selectionRowHeader\n           *  <br/>Defaults to true\n           */\n          gridOptions.enableSelectAll = gridOptions.enableSelectAll !== false;\n          /**\n           *  @ngdoc object\n           *  @name enableSelectionBatchEvent\n           *  @propertyOf  ui.grid.selection.api:GridOptions\n           *  @description If selected rows are changed in bulk, either via the API or\n           *  via the selectAll checkbox, then a separate event is fired.  Setting this\n           *  option to false will cause the rowSelectionChanged event to be called multiple times\n           *  instead\n           *  <br/>Defaults to true\n           */\n          gridOptions.enableSelectionBatchEvent = gridOptions.enableSelectionBatchEvent !== false;\n          /**\n           *  @ngdoc object\n           *  @name selectionRowHeaderWidth\n           *  @propertyOf  ui.grid.selection.api:GridOptions\n           *  @description can be used to set a custom width for the row header selection column\n           *  <br/>Defaults to 30px\n           */\n          gridOptions.selectionRowHeaderWidth = angular.isDefined(gridOptions.selectionRowHeaderWidth) ? gridOptions.selectionRowHeaderWidth : 30;\n\n          /**\n           *  @ngdoc object\n           *  @name enableFooterTotalSelected\n           *  @propertyOf  ui.grid.selection.api:GridOptions\n           *  @description Shows the total number of selected items in footer if true.\n           *  <br/>Defaults to true.\n           *  <br/>GridOptions.showGridFooter must also be set to true.\n           */\n          gridOptions.enableFooterTotalSelected = gridOptions.enableFooterTotalSelected !== false;\n\n          /**\n           *  @ngdoc object\n           *  @name isRowSelectable\n           *  @propertyOf  ui.grid.selection.api:GridOptions\n           *  @description Makes it possible to specify a method that evaluates for each row and sets its \"enableSelection\" property.\n           */\n\n          gridOptions.isRowSelectable = angular.isDefined(gridOptions.isRowSelectable) ? gridOptions.isRowSelectable : angular.noop;\n        },\n\n        /**\n         * @ngdoc function\n         * @name toggleRowSelection\n         * @methodOf  ui.grid.selection.service:uiGridSelectionService\n         * @description Toggles row as selected or unselected\n         * @param {Grid} grid grid object\n         * @param {GridRow} row row to select or deselect\n         * @param {Event} event object if resulting from event\n         * @param {bool} multiSelect if false, only one row at time can be selected\n         * @param {bool} noUnselect if true then rows cannot be unselected\n         */\n        toggleRowSelection: function (grid, row, evt, multiSelect, noUnselect) {\n          var selected = row.isSelected;\n\n          if ( row.enableSelection === false && !selected ){\n            return;\n          }\n\n          var selectedRows;\n          if (!multiSelect && !selected) {\n            service.clearSelectedRows(grid, evt);\n          } else if (!multiSelect && selected) {\n            selectedRows = service.getSelectedRows(grid);\n            if (selectedRows.length > 1) {\n              selected = false; // Enable reselect of the row\n              service.clearSelectedRows(grid, evt);\n            }\n          }\n\n          if (selected && noUnselect){\n            // don't deselect the row\n          } else {\n            row.setSelected(!selected);\n            if (row.isSelected === true) {\n              grid.selection.lastSelectedRow = row;\n            }\n\n            selectedRows = service.getSelectedRows(grid);\n            grid.selection.selectAll = grid.rows.length === selectedRows.length;\n\n            grid.api.selection.raise.rowSelectionChanged(row, evt);\n          }\n        },\n        /**\n         * @ngdoc function\n         * @name shiftSelect\n         * @methodOf  ui.grid.selection.service:uiGridSelectionService\n         * @description selects a group of rows from the last selected row using the shift key\n         * @param {Grid} grid grid object\n         * @param {GridRow} clicked row\n         * @param {Event} event object if raised from an event\n         * @param {bool} multiSelect if false, does nothing this is for multiSelect only\n         */\n        shiftSelect: function (grid, row, evt, multiSelect) {\n          if (!multiSelect) {\n            return;\n          }\n          var selectedRows = service.getSelectedRows(grid);\n          var fromRow = selectedRows.length > 0 ? grid.renderContainers.body.visibleRowCache.indexOf(grid.selection.lastSelectedRow) : 0;\n          var toRow = grid.renderContainers.body.visibleRowCache.indexOf(row);\n          //reverse select direction\n          if (fromRow > toRow) {\n            var tmp = fromRow;\n            fromRow = toRow;\n            toRow = tmp;\n          }\n\n          var changedRows = [];\n          for (var i = fromRow; i <= toRow; i++) {\n            var rowToSelect = grid.renderContainers.body.visibleRowCache[i];\n            if (rowToSelect) {\n              if ( !rowToSelect.isSelected && rowToSelect.enableSelection !== false ){\n                rowToSelect.setSelected(true);\n                grid.selection.lastSelectedRow = rowToSelect;\n                service.decideRaiseSelectionEvent( grid, rowToSelect, changedRows, evt );\n              }\n            }\n          }\n          service.decideRaiseSelectionBatchEvent( grid, changedRows, evt );\n        },\n        /**\n         * @ngdoc function\n         * @name getSelectedRows\n         * @methodOf  ui.grid.selection.service:uiGridSelectionService\n         * @description Returns all the selected rows\n         * @param {Grid} grid grid object\n         */\n        getSelectedRows: function (grid) {\n          return grid.rows.filter(function (row) {\n            return row.isSelected;\n          });\n        },\n\n        /**\n         * @ngdoc function\n         * @name clearSelectedRows\n         * @methodOf  ui.grid.selection.service:uiGridSelectionService\n         * @description Clears all selected rows\n         * @param {Grid} grid grid object\n         * @param {Event} event object if raised from an event\n         */\n        clearSelectedRows: function (grid, evt) {\n          var changedRows = [];\n          service.getSelectedRows(grid).forEach(function (row) {\n            if ( row.isSelected ){\n              row.setSelected(false);\n              service.decideRaiseSelectionEvent( grid, row, changedRows, evt );\n            }\n          });\n          service.decideRaiseSelectionBatchEvent( grid, changedRows, evt );\n          grid.selection.selectAll = false;\n          grid.selection.selectedCount = 0;\n        },\n\n        /**\n         * @ngdoc function\n         * @name decideRaiseSelectionEvent\n         * @methodOf  ui.grid.selection.service:uiGridSelectionService\n         * @description Decides whether to raise a single event or a batch event\n         * @param {Grid} grid grid object\n         * @param {GridRow} row row that has changed\n         * @param {array} changedRows an array to which we can append the changed\n         * @param {Event} event object if raised from an event\n         * row if we're doing batch events\n         */\n        decideRaiseSelectionEvent: function( grid, row, changedRows, evt ){\n          if ( !grid.options.enableSelectionBatchEvent ){\n            grid.api.selection.raise.rowSelectionChanged(row, evt);\n          } else {\n            changedRows.push(row);\n          }\n        },\n\n        /**\n         * @ngdoc function\n         * @name raiseSelectionEvent\n         * @methodOf  ui.grid.selection.service:uiGridSelectionService\n         * @description Decides whether we need to raise a batch event, and\n         * raises it if we do.\n         * @param {Grid} grid grid object\n         * @param {array} changedRows an array of changed rows, only populated\n         * @param {Event} event object if raised from an event\n         * if we're doing batch events\n         */\n        decideRaiseSelectionBatchEvent: function( grid, changedRows, evt ){\n          if ( changedRows.length > 0 ){\n            grid.api.selection.raise.rowSelectionChangedBatch(changedRows, evt);\n          }\n        }\n      };\n\n      return service;\n\n    }]);\n\n  /**\n   *  @ngdoc directive\n   *  @name ui.grid.selection.directive:uiGridSelection\n   *  @element div\n   *  @restrict A\n   *\n   *  @description Adds selection features to grid\n   *\n   *  @example\n   <example module=\"app\">\n   <file name=\"app.js\">\n   var app = angular.module('app', ['ui.grid', 'ui.grid.selection']);\n\n   app.controller('MainCtrl', ['$scope', function ($scope) {\n      $scope.data = [\n        { name: 'Bob', title: 'CEO' },\n            { name: 'Frank', title: 'Lowly Developer' }\n      ];\n\n      $scope.columnDefs = [\n        {name: 'name', enableCellEdit: true},\n        {name: 'title', enableCellEdit: true}\n      ];\n    }]);\n   </file>\n   <file name=\"index.html\">\n   <div ng-controller=\"MainCtrl\">\n   <div ui-grid=\"{ data: data, columnDefs: columnDefs }\" ui-grid-selection></div>\n   </div>\n   </file>\n   </example>\n   */\n  module.directive('uiGridSelection', ['uiGridSelectionConstants', 'uiGridSelectionService', '$templateCache', 'uiGridConstants',\n    function (uiGridSelectionConstants, uiGridSelectionService, $templateCache, uiGridConstants) {\n      return {\n        replace: true,\n        priority: 0,\n        require: '^uiGrid',\n        scope: false,\n        compile: function () {\n          return {\n            pre: function ($scope, $elm, $attrs, uiGridCtrl) {\n              uiGridSelectionService.initializeGrid(uiGridCtrl.grid);\n              if (uiGridCtrl.grid.options.enableRowHeaderSelection) {\n                var selectionRowHeaderDef = {\n                  name: uiGridSelectionConstants.selectionRowHeaderColName,\n                  displayName: '',\n                  width:  uiGridCtrl.grid.options.selectionRowHeaderWidth,\n                  minWidth: 10,\n                  cellTemplate: 'ui-grid/selectionRowHeader',\n                  headerCellTemplate: 'ui-grid/selectionHeaderCell',\n                  enableColumnResizing: false,\n                  enableColumnMenu: false,\n                  exporterSuppressExport: true,\n                  allowCellFocus: true\n                };\n\n                uiGridCtrl.grid.addRowHeaderColumn(selectionRowHeaderDef, 0);\n              }\n\n              var processorSet = false;\n\n              var processSelectableRows = function( rows ){\n                rows.forEach(function(row){\n                  row.enableSelection = uiGridCtrl.grid.options.isRowSelectable(row);\n                });\n                return rows;\n              };\n\n              var updateOptions = function(){\n                if (uiGridCtrl.grid.options.isRowSelectable !== angular.noop && processorSet !== true) {\n                  uiGridCtrl.grid.registerRowsProcessor(processSelectableRows, 500);\n                  processorSet = true;\n                }\n              };\n\n              updateOptions();\n\n              var dataChangeDereg = uiGridCtrl.grid.registerDataChangeCallback( updateOptions, [uiGridConstants.dataChange.OPTIONS] );\n\n              $scope.$on( '$destroy', dataChangeDereg);\n            },\n            post: function ($scope, $elm, $attrs, uiGridCtrl) {\n\n            }\n          };\n        }\n      };\n    }]);\n\n  module.directive('uiGridSelectionRowHeaderButtons', ['$templateCache', 'uiGridSelectionService', 'gridUtil',\n    function ($templateCache, uiGridSelectionService, gridUtil) {\n      return {\n        replace: true,\n        restrict: 'E',\n        template: $templateCache.get('ui-grid/selectionRowHeaderButtons'),\n        scope: true,\n        require: '^uiGrid',\n        link: function($scope, $elm, $attrs, uiGridCtrl) {\n          var self = uiGridCtrl.grid;\n          $scope.selectButtonClick = selectButtonClick;\n\n          // On IE, prevent mousedowns on the select button from starting a selection.\n          //   If this is not done and you shift+click on another row, the browser will select a big chunk of text\n          if (gridUtil.detectBrowser() === 'ie') {\n            $elm.on('mousedown', selectButtonMouseDown);\n          }\n\n\n          function selectButtonClick(row, evt) {\n            evt.stopPropagation();\n\n            if (evt.shiftKey) {\n              uiGridSelectionService.shiftSelect(self, row, evt, self.options.multiSelect);\n            }\n            else if (evt.ctrlKey || evt.metaKey) {\n              uiGridSelectionService.toggleRowSelection(self, row, evt, self.options.multiSelect, self.options.noUnselect);\n            }\n            else {\n              uiGridSelectionService.toggleRowSelection(self, row, evt, (self.options.multiSelect && !self.options.modifierKeysToMultiSelect), self.options.noUnselect);\n            }\n          }\n\n          function selectButtonMouseDown(evt) {\n            if (evt.ctrlKey || evt.shiftKey) {\n              evt.target.onselectstart = function () { return false; };\n              window.setTimeout(function () { evt.target.onselectstart = null; }, 0);\n            }\n          }\n        }\n      };\n    }]);\n\n  module.directive('uiGridSelectionSelectAllButtons', ['$templateCache', 'uiGridSelectionService',\n    function ($templateCache, uiGridSelectionService) {\n      return {\n        replace: true,\n        restrict: 'E',\n        template: $templateCache.get('ui-grid/selectionSelectAllButtons'),\n        scope: false,\n        link: function($scope, $elm, $attrs, uiGridCtrl) {\n          var self = $scope.col.grid;\n\n          $scope.headerButtonClick = function(row, evt) {\n            if ( self.selection.selectAll ){\n              uiGridSelectionService.clearSelectedRows(self, evt);\n              if ( self.options.noUnselect ){\n                self.api.selection.selectRowByVisibleIndex(0, evt);\n              }\n              self.selection.selectAll = false;\n            } else {\n              if ( self.options.multiSelect ){\n                self.api.selection.selectAllVisibleRows(evt);\n                self.selection.selectAll = true;\n              }\n            }\n          };\n        }\n      };\n    }]);\n\n  /**\n   *  @ngdoc directive\n   *  @name ui.grid.selection.directive:uiGridViewport\n   *  @element div\n   *\n   *  @description Stacks on top of ui.grid.uiGridViewport to alter the attributes used\n   *  for the grid row\n   */\n  module.directive('uiGridViewport',\n    ['$compile', 'uiGridConstants', 'uiGridSelectionConstants', 'gridUtil', '$parse', 'uiGridSelectionService',\n      function ($compile, uiGridConstants, uiGridSelectionConstants, gridUtil, $parse, uiGridSelectionService) {\n        return {\n          priority: -200, // run after default  directive\n          scope: false,\n          compile: function ($elm, $attrs) {\n            var rowRepeatDiv = angular.element($elm.children().children()[0]);\n\n            var existingNgClass = rowRepeatDiv.attr(\"ng-class\");\n            var newNgClass = '';\n            if ( existingNgClass ) {\n              newNgClass = existingNgClass.slice(0, -1) + \",'ui-grid-row-selected': row.isSelected}\";\n            } else {\n              newNgClass = \"{'ui-grid-row-selected': row.isSelected}\";\n            }\n            rowRepeatDiv.attr(\"ng-class\", newNgClass);\n\n            return {\n              pre: function ($scope, $elm, $attrs, controllers) {\n\n              },\n              post: function ($scope, $elm, $attrs, controllers) {\n              }\n            };\n          }\n        };\n      }]);\n\n  /**\n   *  @ngdoc directive\n   *  @name ui.grid.selection.directive:uiGridCell\n   *  @element div\n   *  @restrict A\n   *\n   *  @description Stacks on top of ui.grid.uiGridCell to provide selection feature\n   */\n  module.directive('uiGridCell',\n    ['$compile', 'uiGridConstants', 'uiGridSelectionConstants', 'gridUtil', '$parse', 'uiGridSelectionService', '$timeout',\n      function ($compile, uiGridConstants, uiGridSelectionConstants, gridUtil, $parse, uiGridSelectionService, $timeout) {\n        return {\n          priority: -200, // run after default uiGridCell directive\n          restrict: 'A',\n          require: '?^uiGrid',\n          scope: false,\n          link: function ($scope, $elm, $attrs, uiGridCtrl) {\n\n            var touchStartTime = 0;\n            var touchTimeout = 300;\n\n            // Bind to keydown events in the render container\n            if (uiGridCtrl.grid.api.cellNav) {\n\n              uiGridCtrl.grid.api.cellNav.on.viewPortKeyDown($scope, function (evt, rowCol) {\n                if (rowCol === null ||\n                  rowCol.row !== $scope.row ||\n                  rowCol.col !== $scope.col) {\n                  return;\n                }\n\n                if (evt.keyCode === 32 && $scope.col.colDef.name === \"selectionRowHeaderCol\") {\n                  uiGridSelectionService.toggleRowSelection($scope.grid, $scope.row, evt, ($scope.grid.options.multiSelect && !$scope.grid.options.modifierKeysToMultiSelect), $scope.grid.options.noUnselect);\n                  $scope.$apply();\n                }\n\n              //  uiGridCellNavService.scrollToIfNecessary(uiGridCtrl.grid, rowCol.row, rowCol.col);\n              });\n            }\n\n            //$elm.bind('keydown', function (evt) {\n            //  if (evt.keyCode === 32 && $scope.col.colDef.name === \"selectionRowHeaderCol\") {\n            //    uiGridSelectionService.toggleRowSelection($scope.grid, $scope.row, evt, ($scope.grid.options.multiSelect && !$scope.grid.options.modifierKeysToMultiSelect), $scope.grid.options.noUnselect);\n            //    $scope.$apply();\n            //  }\n            //});\n\n            var selectCells = function(evt){\n              // if we get a click, then stop listening for touchend\n              $elm.off('touchend', touchEnd);\n\n              if (evt.shiftKey) {\n                uiGridSelectionService.shiftSelect($scope.grid, $scope.row, evt, $scope.grid.options.multiSelect);\n              }\n              else if (evt.ctrlKey || evt.metaKey) {\n                uiGridSelectionService.toggleRowSelection($scope.grid, $scope.row, evt, $scope.grid.options.multiSelect, $scope.grid.options.noUnselect);\n              }\n              else {\n                uiGridSelectionService.toggleRowSelection($scope.grid, $scope.row, evt, ($scope.grid.options.multiSelect && !$scope.grid.options.modifierKeysToMultiSelect), $scope.grid.options.noUnselect);\n              }\n              $scope.$apply();\n\n              // don't re-enable the touchend handler for a little while - some devices generate both, and it will\n              // take a little while to move your hand from the mouse to the screen if you have both modes of input\n              $timeout(function() {\n                $elm.on('touchend', touchEnd);\n              }, touchTimeout);\n            };\n\n            var touchStart = function(evt){\n              touchStartTime = (new Date()).getTime();\n\n              // if we get a touch event, then stop listening for click\n              $elm.off('click', selectCells);\n            };\n\n            var touchEnd = function(evt) {\n              var touchEndTime = (new Date()).getTime();\n              var touchTime = touchEndTime - touchStartTime;\n\n              if (touchTime < touchTimeout ) {\n                // short touch\n                selectCells(evt);\n              }\n\n              // don't re-enable the click handler for a little while - some devices generate both, and it will\n              // take a little while to move your hand from the screen to the mouse if you have both modes of input\n              $timeout(function() {\n                $elm.on('click', selectCells);\n              }, touchTimeout);\n            };\n\n            function registerRowSelectionEvents() {\n              if ($scope.grid.options.enableRowSelection && $scope.grid.options.enableFullRowSelection) {\n                $elm.addClass('ui-grid-disable-selection');\n                $elm.on('touchstart', touchStart);\n                $elm.on('touchend', touchEnd);\n                $elm.on('click', selectCells);\n\n                $scope.registered = true;\n              }\n            }\n\n            function deregisterRowSelectionEvents() {\n              if ($scope.registered){\n                $elm.removeClass('ui-grid-disable-selection');\n\n                $elm.off('touchstart', touchStart);\n                $elm.off('touchend', touchEnd);\n                $elm.off('click', selectCells);\n\n                $scope.registered = false;\n              }\n            }\n\n            registerRowSelectionEvents();\n            // register a dataChange callback so that we can change the selection configuration dynamically\n            // if the user changes the options\n            var dataChangeDereg = $scope.grid.registerDataChangeCallback( function() {\n              if ( $scope.grid.options.enableRowSelection && $scope.grid.options.enableFullRowSelection &&\n                !$scope.registered ){\n                registerRowSelectionEvents();\n              } else if ( ( !$scope.grid.options.enableRowSelection || !$scope.grid.options.enableFullRowSelection ) &&\n                $scope.registered ){\n                deregisterRowSelectionEvents();\n              }\n            }, [uiGridConstants.dataChange.OPTIONS] );\n\n            $elm.on( '$destroy', dataChangeDereg);\n          }\n        };\n      }]);\n\n  module.directive('uiGridGridFooter', ['$compile', 'uiGridConstants', 'gridUtil', function ($compile, uiGridConstants, gridUtil) {\n    return {\n      restrict: 'EA',\n      replace: true,\n      priority: -1000,\n      require: '^uiGrid',\n      scope: true,\n      compile: function ($elm, $attrs) {\n        return {\n          pre: function ($scope, $elm, $attrs, uiGridCtrl) {\n\n            if (!uiGridCtrl.grid.options.showGridFooter) {\n              return;\n            }\n\n\n            gridUtil.getTemplate('ui-grid/gridFooterSelectedItems')\n              .then(function (contents) {\n                var template = angular.element(contents);\n\n                var newElm = $compile(template)($scope);\n\n                angular.element($elm[0].getElementsByClassName('ui-grid-grid-footer')[0]).append(newElm);\n              });\n          },\n\n          post: function ($scope, $elm, $attrs, controllers) {\n\n          }\n        };\n      }\n    };\n  }]);\n\n})();\n\n(function () {\n  'use strict';\n\n  /**\n   * @ngdoc overview\n   * @name ui.grid.treeBase\n   * @description\n   *\n   * # ui.grid.treeBase\n   *\n   * <div class=\"alert alert-warning\" role=\"alert\"><strong>Beta</strong> This feature is ready for testing, but it either hasn't seen a lot of use or has some known bugs.</div>\n   *\n   * This module provides base tree handling functions that are shared by other features, notably grouping\n   * and treeView.  It provides a tree view of the data, with nodes in that\n   * tree and leaves.\n   *\n   * Design information:\n   * -------------------\n   *\n   * The raw data that is provided must come with a $$treeLevel on any non-leaf node.  Grouping will create\n   * these on all the group header rows, treeView will expect these to be set in the raw data by the user.\n   * TreeBase will run a rowsProcessor that:\n   *  - builds `treeBase.tree` out of the provided rows\n   *  - permits a recursive sort of the tree\n   *  - maintains the expand/collapse state of each node\n   *  - provides the expand/collapse all button and the expand/collapse buttons\n   *  - maintains the count of children for each node\n   *\n   * Each row is updated with a link to the tree node that represents it.  Refer {@link ui.grid.treeBase.grid:treeBase.tree tree documentation}\n   * for information.\n   *\n   *  TreeBase adds information to the rows\n   *  - treeLevel: if present and > -1 tells us the level (level 0 is the top level)\n   *  - treeNode: pointer to the node in the grid.treeBase.tree that refers\n   *    to this row, allowing us to manipulate the state\n   *\n   * Since the logic is baked into the rowsProcessors, it should get triggered whenever\n   * row order or filtering or anything like that is changed.  We recall the expanded state\n   * across invocations of the rowsProcessors by the reference to the treeNode on the individual\n   * rows.  We rebuild the tree itself quite frequently, when we do this we use the saved treeNodes to\n   * get the state, but we overwrite the other data in that treeNode.\n   *\n   * By default rows are collapsed, which means all data rows have their visible property\n   * set to false, and only level 0 group rows are set to visible.\n   *\n   * We rely on the rowsProcessors to do the actual expanding and collapsing, so we set the flags we want into\n   * grid.treeBase.tree, then call refresh.  This is because we can't easily change the visible\n   * row cache without calling the processors, and once we've built the logic into the rowProcessors we may as\n   * well use it all the time.\n   *\n   * Tree base provides sorting (on non-grouped columns).\n   *\n   * Sorting works in two passes.  The standard sorting is performed for any columns that are important to building\n   * the tree (for example, any grouped columns).  Then after the tree is built, a recursive tree sort is performed\n   * for the remaining sort columns (including the original sort) - these columns are sorted within each tree level\n   * (so all the level 1 nodes are sorted, then all the level 2 nodes within each level 1 node etc).\n   *\n   * To achieve this we make use of the `ignoreSort` property on the sort configuration.  The parent feature (treeView or grouping)\n   * must provide a rowsProcessor that runs with very low priority (typically in the 60-65 range), and that sets\n   * the `ignoreSort`on any sort that it wants to run on the tree.  TreeBase will clear the ignoreSort on all sorts - so it\n   * will turn on any sorts that haven't run.  It will then call a recursive sort on the tree.\n   *\n   * Tree base provides treeAggregation.  It checks the treeAggregation configuration on each column, and aggregates based on\n   * the logic provided as it builds the tree. Footer aggregation from the uiGrid core should not be used with treeBase aggregation,\n   * since it operates on all visible rows, as opposed to to leaf nodes only. Setting `showColumnFooter: true` will show the\n   * treeAggregations in the column footer.  Aggregation information will be collected in the format:\n   *\n   * ```\n   *   {\n   *     type: 'count',\n   *     value: 4,\n   *     label: 'count: ',\n   *     rendered: 'count: 4'\n   *   }\n   * ```\n   *\n   * A callback is provided to format the value once it is finalised (aka a valueFilter).\n   *\n   * <br/>\n   * <br/>\n   *\n   * <div doc-module-components=\"ui.grid.treeBase\"></div>\n   */\n\n  var module = angular.module('ui.grid.treeBase', ['ui.grid']);\n\n  /**\n   *  @ngdoc object\n   *  @name ui.grid.treeBase.constant:uiGridTreeBaseConstants\n   *\n   *  @description constants available in treeBase module.\n   *\n   *  These constants are manually copied into grouping and treeView,\n   *  as I haven't found a way to simply include them, and it's not worth\n   *  investing time in for something that changes very infrequently.\n   *\n   */\n  module.constant('uiGridTreeBaseConstants', {\n    featureName: \"treeBase\",\n    rowHeaderColName: 'treeBaseRowHeaderCol',\n    EXPANDED: 'expanded',\n    COLLAPSED: 'collapsed',\n    aggregation: {\n      COUNT: 'count',\n      SUM: 'sum',\n      MAX: 'max',\n      MIN: 'min',\n      AVG: 'avg'\n    }\n  });\n\n  /**\n   *  @ngdoc service\n   *  @name ui.grid.treeBase.service:uiGridTreeBaseService\n   *\n   *  @description Services for treeBase feature\n   */\n  /**\n   *  @ngdoc object\n   *  @name ui.grid.treeBase.api:ColumnDef\n   *\n   *  @description ColumnDef for tree feature, these are available to be\n   *  set using the ui-grid {@link ui.grid.class:GridOptions.columnDef gridOptions.columnDefs}\n   */\n\n  module.service('uiGridTreeBaseService', ['$q', 'uiGridTreeBaseConstants', 'gridUtil', 'GridRow', 'gridClassFactory', 'i18nService', 'uiGridConstants', 'rowSorter',\n  function ($q, uiGridTreeBaseConstants, gridUtil, GridRow, gridClassFactory, i18nService, uiGridConstants, rowSorter) {\n\n    var service = {\n\n      initializeGrid: function (grid, $scope) {\n\n        //add feature namespace and any properties to grid for needed\n        /**\n         *  @ngdoc object\n         *  @name ui.grid.treeBase.grid:treeBase\n         *\n         *  @description Grid properties and functions added for treeBase\n         */\n        grid.treeBase = {};\n\n        /**\n         *  @ngdoc property\n         *  @propertyOf ui.grid.treeBase.grid:treeBase\n         *  @name numberLevels\n         *\n         *  @description Total number of tree levels currently used, calculated by the rowsProcessor by\n         *  retaining the highest tree level it sees\n         */\n        grid.treeBase.numberLevels = 0;\n\n        /**\n         *  @ngdoc property\n         *  @propertyOf ui.grid.treeBase.grid:treeBase\n         *  @name expandAll\n         *\n         *  @description Whether or not the expandAll box is selected\n         */\n        grid.treeBase.expandAll = false;\n\n        /**\n         *  @ngdoc property\n         *  @propertyOf ui.grid.treeBase.grid:treeBase\n         *  @name tree\n         *\n         *  @description Tree represented as a nested array that holds the state of each node, along with a\n         *  pointer to the row.  The array order is material - we will display the children in the order\n         *  they are stored in the array\n         *\n         *  Each node stores:\n         *\n         *    - the state of this node\n         *    - an array of children of this node\n         *    - a pointer to the parent of this node (reverse pointer, allowing us to walk up the tree)\n         *    - the number of children of this node\n         *    - aggregation information calculated from the nodes\n         *\n         *  ```\n         *    [{\n         *      state: 'expanded',\n         *      row: <reference to row>,\n         *      parentRow: null,\n         *      aggregations: [{\n         *        type: 'count',\n         *        col: <gridCol>,\n         *        value: 2,\n         *        label: 'count: ',\n         *        rendered: 'count: 2'\n         *      }],\n         *      children: [\n         *        {\n         *          state: 'expanded',\n         *          row: <reference to row>,\n         *          parentRow: <reference to row>,\n         *          aggregations: [{\n         *            type: 'count',\n         *            col: '<gridCol>,\n         *            value: 4,\n         *            label: 'count: ',\n         *            rendered: 'count: 4'\n         *          }],\n         *          children: [\n         *            { state: 'expanded', row: <reference to row>, parentRow: <reference to row> },\n         *            { state: 'collapsed', row: <reference to row>, parentRow: <reference to row> },\n         *            { state: 'expanded', row: <reference to row>, parentRow: <reference to row> },\n         *            { state: 'collapsed', row: <reference to row>, parentRow: <reference to row> }\n         *          ]\n         *        },\n         *        {\n         *          state: 'collapsed',\n         *          row: <reference to row>,\n         *          parentRow: <reference to row>,\n         *          aggregations: [{\n         *            type: 'count',\n         *            col: <gridCol>,\n         *            value: 3,\n         *            label: 'count: ',\n         *            rendered: 'count: 3'\n         *          }],\n         *          children: [\n         *            { state: 'expanded', row: <reference to row>, parentRow: <reference to row> },\n         *            { state: 'collapsed', row: <reference to row>, parentRow: <reference to row> },\n         *            { state: 'expanded', row: <reference to row>, parentRow: <reference to row> }\n         *          ]\n         *        }\n         *      ]\n         *    }, {<another level 0 node maybe>} ]\n         *  ```\n         *  Missing state values are false - meaning they aren't expanded.\n         *\n         *  This is used because the rowProcessors run every time the grid is refreshed, so\n         *  we'd lose the expanded state every time the grid was refreshed.  This instead gives\n         *  us a reliable lookup that persists across rowProcessors.\n         *\n         *  This tree is rebuilt every time we run the rowsProcessors.  Since each row holds a pointer\n         *  to it's tree node we can persist expand/collapse state across calls to rowsProcessor, we discard\n         *  all transient information on the tree (children, childCount) and recalculate it\n         *\n         */\n        grid.treeBase.tree = [];\n\n        service.defaultGridOptions(grid.options);\n\n        grid.registerRowsProcessor(service.treeRows, 410);\n\n        grid.registerColumnBuilder( service.treeBaseColumnBuilder );\n\n        service.createRowHeader( grid );\n\n        /**\n         *  @ngdoc object\n         *  @name ui.grid.treeBase.api:PublicApi\n         *\n         *  @description Public Api for treeBase feature\n         */\n        var publicApi = {\n          events: {\n            treeBase: {\n              /**\n               * @ngdoc event\n               * @eventOf ui.grid.treeBase.api:PublicApi\n               * @name rowExpanded\n               * @description raised whenever a row is expanded.  If you are dynamically\n               * rendering your tree you can listen to this event, and then retrieve\n               * the children of this row and load them into the grid data.\n               *\n               * When the data is loaded the grid will automatically refresh to show these new rows\n               *\n               * <pre>\n               *      gridApi.treeBase.on.rowExpanded(scope,function(row){})\n               * </pre>\n               * @param {gridRow} row the row that was expanded.  You can also\n               * retrieve the grid from this row with row.grid\n               */\n              rowExpanded: {},\n\n              /**\n               * @ngdoc event\n               * @eventOf ui.grid.treeBase.api:PublicApi\n               * @name rowCollapsed\n               * @description raised whenever a row is collapsed.  Doesn't really have\n               * a purpose at the moment, included for symmetry\n               *\n               * <pre>\n               *      gridApi.treeBase.on.rowCollapsed(scope,function(row){})\n               * </pre>\n               * @param {gridRow} row the row that was collapsed.  You can also\n               * retrieve the grid from this row with row.grid\n               */\n              rowCollapsed: {}\n            }\n          },\n\n          methods: {\n            treeBase: {\n              /**\n               * @ngdoc function\n               * @name expandAllRows\n               * @methodOf  ui.grid.treeBase.api:PublicApi\n               * @description Expands all tree rows\n               */\n              expandAllRows: function () {\n                service.expandAllRows(grid);\n              },\n\n              /**\n               * @ngdoc function\n               * @name collapseAllRows\n               * @methodOf  ui.grid.treeBase.api:PublicApi\n               * @description collapse all tree rows\n               */\n              collapseAllRows: function () {\n                service.collapseAllRows(grid);\n              },\n\n              /**\n               * @ngdoc function\n               * @name toggleRowTreeState\n               * @methodOf  ui.grid.treeBase.api:PublicApi\n               * @description  call expand if the row is collapsed, collapse if it is expanded\n               * @param {gridRow} row the row you wish to toggle\n               */\n              toggleRowTreeState: function (row) {\n                service.toggleRowTreeState(grid, row);\n              },\n\n              /**\n               * @ngdoc function\n               * @name expandRow\n               * @methodOf  ui.grid.treeBase.api:PublicApi\n               * @description expand the immediate children of the specified row\n               * @param {gridRow} row the row you wish to expand\n               */\n              expandRow: function (row) {\n                service.expandRow(grid, row);\n              },\n\n              /**\n               * @ngdoc function\n               * @name expandRowChildren\n               * @methodOf  ui.grid.treeBase.api:PublicApi\n               * @description expand all children of the specified row\n               * @param {gridRow} row the row you wish to expand\n               */\n              expandRowChildren: function (row) {\n                service.expandRowChildren(grid, row);\n              },\n\n              /**\n               * @ngdoc function\n               * @name collapseRow\n               * @methodOf  ui.grid.treeBase.api:PublicApi\n               * @description collapse  the specified row.  When\n               * you expand the row again, all grandchildren will retain their state\n               * @param {gridRow} row the row you wish to collapse\n               */\n              collapseRow: function ( row ) {\n                service.collapseRow(grid, row);\n              },\n\n              /**\n               * @ngdoc function\n               * @name collapseRowChildren\n               * @methodOf  ui.grid.treeBase.api:PublicApi\n               * @description collapse all children of the specified row.  When\n               * you expand the row again, all grandchildren will be collapsed\n               * @param {gridRow} row the row you wish to collapse children for\n               */\n              collapseRowChildren: function ( row ) {\n                service.collapseRowChildren(grid, row);\n              },\n\n              /**\n               * @ngdoc function\n               * @name getTreeState\n               * @methodOf  ui.grid.treeBase.api:PublicApi\n               * @description Get the tree state for this grid,\n               * used by the saveState feature\n               * Returned treeState as an object\n               *   `{ expandedState: { uid: 'expanded', uid: 'collapsed' } }`\n               * where expandedState is a hash of row uid and the current expanded state\n               *\n               * @returns {object} tree state\n               *\n               * TODO - this needs work - we need an identifier that persists across instantiations,\n               * not uid.  This really means we need a row identity defined, but that won't work for\n               * grouping.  Perhaps this needs to be moved up to treeView and grouping, rather than\n               * being in base.\n               */\n              getTreeExpandedState: function () {\n                return { expandedState: service.getTreeState(grid) };\n              },\n\n              /**\n               * @ngdoc function\n               * @name setTreeState\n               * @methodOf  ui.grid.treeBase.api:PublicApi\n               * @description Set the expanded states of the tree\n               * @param {object} config the config you want to apply, in the format\n               * provided by getTreeState\n               */\n              setTreeState: function ( config ) {\n                service.setTreeState( grid, config );\n              },\n\n              /**\n               * @ngdoc function\n               * @name getRowChildren\n               * @methodOf  ui.grid.treeBase.api:PublicApi\n               * @description Get the children of the specified row\n               * @param {GridRow} row the row you want the children of\n               * @returns {Array} array of children of this row, the children\n               * are all gridRows\n               */\n              getRowChildren: function ( row ){\n                return row.treeNode.children.map( function( childNode ){\n                  return childNode.row;\n                });\n              }\n            }\n          }\n        };\n\n        grid.api.registerEventsFromObject(publicApi.events);\n\n        grid.api.registerMethodsFromObject(publicApi.methods);\n      },\n\n\n      defaultGridOptions: function (gridOptions) {\n        //default option to true unless it was explicitly set to false\n        /**\n         *  @ngdoc object\n         *  @name ui.grid.treeBase.api:GridOptions\n         *\n         *  @description GridOptions for treeBase feature, these are available to be\n         *  set using the ui-grid {@link ui.grid.class:GridOptions gridOptions}\n         */\n\n        /**\n         *  @ngdoc object\n         *  @name treeRowHeaderBaseWidth\n         *  @propertyOf  ui.grid.treeBase.api:GridOptions\n         *  @description Base width of the tree header, provides for a single level of tree.  This\n         *  is incremented by `treeIndent` for each extra level\n         *  <br/>Defaults to 30\n         */\n        gridOptions.treeRowHeaderBaseWidth = gridOptions.treeRowHeaderBaseWidth || 30;\n\n        /**\n         *  @ngdoc object\n         *  @name treeIndent\n         *  @propertyOf  ui.grid.treeBase.api:GridOptions\n         *  @description Number of pixels of indent for the icon at each tree level, wider indents are visually more pleasing,\n         *  but will make the tree row header wider\n         *  <br/>Defaults to 10\n         */\n        gridOptions.treeIndent = gridOptions.treeIndent || 10;\n\n        /**\n         *  @ngdoc object\n         *  @name showTreeRowHeader\n         *  @propertyOf  ui.grid.treeBase.api:GridOptions\n         *  @description If set to false, don't create the row header.  You'll need to programmatically control the expand\n         *  states\n         *  <br/>Defaults to true\n         */\n        gridOptions.showTreeRowHeader = gridOptions.showTreeRowHeader !== false;\n\n        /**\n         *  @ngdoc object\n         *  @name showTreeExpandNoChildren\n         *  @propertyOf  ui.grid.treeBase.api:GridOptions\n         *  @description If set to true, show the expand/collapse button even if there are no\n         *  children of a node.  You'd use this if you're planning to dynamically load the children\n         *\n         *  <br/>Defaults to true, grouping overrides to false\n         */\n        gridOptions.showTreeExpandNoChildren = gridOptions.showTreeExpandNoChildren !== false;\n\n        /**\n         *  @ngdoc object\n         *  @name treeRowHeaderAlwaysVisible\n         *  @propertyOf  ui.grid.treeBase.api:GridOptions\n         *  @description If set to true, row header even if there are no tree nodes\n         *\n         *  <br/>Defaults to true\n         */\n        gridOptions.treeRowHeaderAlwaysVisible = gridOptions.treeRowHeaderAlwaysVisible !== false;\n\n        /**\n         *  @ngdoc object\n         *  @name treeCustomAggregations\n         *  @propertyOf  ui.grid.treeBase.api:GridOptions\n         *  @description Define custom aggregation functions. The properties of this object will be\n         *  aggregation types available for use on columnDef with {@link ui.grid.treeBase.api:ColumnDef treeAggregationType} or through the column menu.\n         *  If a function defined here uses the same name as one of the native aggregations, this one will take precedence.\n         *  The object format is:\n         *\n         *  <pre>\n         *    {\n         *      aggregationName: {\n         *        label: (optional) string,\n         *        aggregationFn: function( aggregation, fieldValue, numValue, row ){...},\n         *        finalizerFn: (optional) function( aggregation ){...}\n       *        },\n         *      mean: {\n         *        label: 'mean',\n         *        aggregationFn: function( aggregation, fieldValue, numValue ){\n       *            aggregation.count = (aggregation.count || 1) + 1;\n         *          aggregation.sum = (aggregation.sum || 0) + numValue;\n         *        },\n         *        finalizerFn: function( aggregation ){\n         *          aggregation.value = aggregation.sum / aggregation.count\n         *        }\n         *      }\n         *    }\n         *  </pre>\n         *\n         *  <br/>The `finalizerFn` may be used to manipulate the value before rendering, or to\n         *  apply a custom rendered value. If `aggregation.rendered` is left undefined, the value will be\n         *  rendered. Note that the native aggregation functions use an `finalizerFn` to concatenate\n         *  the label and the value.\n         *\n         *  <br/>Defaults to {}\n         */\n        gridOptions.treeCustomAggregations = gridOptions.treeCustomAggregations || {};\n\n        /**\n         *  @ngdoc object\n         *  @name enableExpandAll\n         *  @propertyOf  ui.grid.treeBase.api:GridOptions\n         *  @description Enable the expand all button at the top of the row header\n         *\n         *  <br/>Defaults to true\n         */\n        gridOptions.enableExpandAll = gridOptions.enableExpandAll !== false;\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name treeBaseColumnBuilder\n       * @methodOf  ui.grid.treeBase.service:uiGridTreeBaseService\n       * @description Sets the tree defaults based on the columnDefs\n       *\n       * @param {object} colDef columnDef we're basing on\n       * @param {GridCol} col the column we're to update\n       * @param {object} gridOptions the options we should use\n       * @returns {promise} promise for the builder - actually we do it all inline so it's immediately resolved\n       */\n      treeBaseColumnBuilder: function (colDef, col, gridOptions) {\n\n\n        /**\n         *  @ngdoc object\n         *  @name customTreeAggregationFn\n         *  @propertyOf  ui.grid.treeBase.api:ColumnDef\n         *  @description A custom function that aggregates rows into some form of\n         *  total.  Aggregations run row-by-row, the function needs to be capable of\n         *  creating a running total.\n         *\n         *  The function will be provided the aggregation item (in which you can store running\n         *  totals), the row value that is to be aggregated, and that same row value converted to\n         *  a number (most aggregations work on numbers)\n         *  @example\n         *  <pre>\n         *    customTreeAggregationFn = function ( aggregation, fieldValue, numValue, row ){\n         *      // calculates the average of the squares of the values\n         *      if ( typeof(aggregation.count) === 'undefined' ){\n         *        aggregation.count = 0;\n         *      }\n         *      aggregation.count++;\n         *\n         *      if ( !isNaN(numValue) ){\n         *        if ( typeof(aggregation.total) === 'undefined' ){\n         *          aggregation.total = 0;\n         *        }\n         *        aggregation.total = aggregation.total + numValue * numValue;\n         *      }\n         *\n         *      aggregation.value = aggregation.total / aggregation.count;\n         *    }\n         *  </pre>\n         *  <br/>Defaults to undefined. May be overwritten by treeAggregationType, the two options should not be used together.\n         */\n        if ( typeof(colDef.customTreeAggregationFn) !== 'undefined' ){\n          col.treeAggregationFn = colDef.customTreeAggregationFn;\n        }\n\n        /**\n         *  @ngdoc object\n         *  @name treeAggregationType\n         *  @propertyOf  ui.grid.treeBase.api:ColumnDef\n         *  @description Use one of the native or grid-level aggregation methods for calculating aggregations on this column.\n         *  Native method are in the constants file and include: SUM, COUNT, MIN, MAX, AVG. This may also be the property the\n         *  name of an aggregation function defined with {@link ui.grid.treeBase.api:GridOptions treeCustomAggregations}.\n         *\n         *  <pre>\n         *      treeAggregationType = uiGridTreeBaseConstants.aggregation.SUM,\n         *    }\n         *  </pre>\n         *\n         *  If you are using aggregations you should either:\n         *\n         *   - also use grouping, in which case the aggregations are displayed in the group header, OR\n         *   - use treeView, in which case you can set `treeAggregationUpdateEntity: true` in the colDef, and\n         *     treeBase will store the aggregation information in the entity, or you can set `treeAggregationUpdateEntity: false`\n         *     in the colDef, and you need to manual retrieve the calculated aggregations from the row.treeNode.aggregations\n         *\n         *  <br/>Takes precendence over a treeAggregationFn, the two options should not be used together.\n         *  <br/>Defaults to undefined.\n         */\n        if ( typeof(colDef.treeAggregationType) !== 'undefined' ){\n          col.treeAggregation = { type: colDef.treeAggregationType };\n          if ( typeof(gridOptions.treeCustomAggregations[colDef.treeAggregationType]) !== 'undefined' ){\n            col.treeAggregationFn = gridOptions.treeCustomAggregations[colDef.treeAggregationType].aggregationFn;\n            col.treeAggregationFinalizerFn = gridOptions.treeCustomAggregations[colDef.treeAggregationType].finalizerFn;\n            col.treeAggregation.label = gridOptions.treeCustomAggregations[colDef.treeAggregationType].label;\n          } else if ( typeof(service.nativeAggregations()[colDef.treeAggregationType]) !== 'undefined' ){\n            col.treeAggregationFn = service.nativeAggregations()[colDef.treeAggregationType].aggregationFn;\n            col.treeAggregation.label = service.nativeAggregations()[colDef.treeAggregationType].label;\n          }\n        }\n\n         /**\n         *  @ngdoc object\n         *  @name treeAggregationLabel\n         *  @propertyOf  ui.grid.treeBase.api:ColumnDef\n         *  @description A custom label to use for this aggregation. If provided we don't use native i18n.\n         */\n        if ( typeof(colDef.treeAggregationLabel) !== 'undefined' ){\n          if (typeof(col.treeAggregation) === 'undefined' ){\n            col.treeAggregation = {};\n          }\n          col.treeAggregation.label = colDef.treeAggregationLabel;\n        }\n\n        /**\n         *  @ngdoc object\n         *  @name treeAggregationUpdateEntity\n         *  @propertyOf  ui.grid.treeBase.api:ColumnDef\n         *  @description Store calculated aggregations into the entity, allowing them\n         *  to be displayed in the grid using a standard cellTemplate.  This defaults to true,\n         *  if you are using grouping then you shouldn't set it to false, as then the aggregations won't\n         *  display.\n         *\n         *  If you are using treeView in most cases you'll want to set this to true.  This will result in\n         *  getCellValue returning the aggregation rather than whatever was stored in the cell attribute on\n         *  the entity.  If you want to render the underlying entity value (and do something else with the aggregation)\n         *  then you could use a custom cellTemplate to display `row.entity.myAttribute`, rather than using getCellValue.\n         *\n         *  <br/>Defaults to true\n         *\n         *  @example\n         *  <pre>\n         *    gridOptions.columns = [{\n         *      name: 'myCol',\n         *      treeAggregation: { type: uiGridTreeBaseConstants.aggregation.SUM },\n         *      treeAggregationUpdateEntity: true\n         *      cellTemplate: '<div>{{row.entity.myCol + \" \" + row.treeNode.aggregations[0].rendered}}</div>'\n         *    }];\n         * </pre>\n         */\n        col.treeAggregationUpdateEntity = colDef.treeAggregationUpdateEntity !== false;\n\n        /**\n         *  @ngdoc object\n         *  @name customTreeAggregationFinalizerFn\n         *  @propertyOf  ui.grid.treeBase.api:ColumnDef\n         *  @description A custom function that populates aggregation.rendered, this is called when\n         *  a particular aggregation has been fully calculated, and we want to render the value.\n         *\n         *  With the native aggregation options we just concatenate `aggregation.label` and\n         *  `aggregation.value`, but if you wanted to apply a filter or otherwise manipulate the label\n         *  or the value, you can do so with this function. This function will be called after the\n         *  the default `finalizerFn`.\n         *\n         *  @example\n         *  <pre>\n         *    customTreeAggregationFinalizerFn = function ( aggregation ){\n         *      aggregation.rendered = aggregation.label + aggregation.value / 100 + '%';\n         *    }\n         *  </pre>\n         *  <br/>Defaults to undefined.\n         */\n        if ( typeof(col.customTreeAggregationFinalizerFn) === 'undefined' ){\n          col.customTreeAggregationFinalizerFn = colDef.customTreeAggregationFinalizerFn;\n        }\n\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name createRowHeader\n       * @methodOf  ui.grid.treeBase.service:uiGridTreeBaseService\n       * @description Create the rowHeader.  If treeRowHeaderAlwaysVisible then\n       * set it to visible, otherwise set it to invisible\n       *\n       * @param {Grid} grid grid object\n       */\n      createRowHeader: function( grid ){\n        var rowHeaderColumnDef = {\n          name: uiGridTreeBaseConstants.rowHeaderColName,\n          displayName: '',\n          width:  grid.options.treeRowHeaderBaseWidth,\n          minWidth: 10,\n          cellTemplate: 'ui-grid/treeBaseRowHeader',\n          headerCellTemplate: 'ui-grid/treeBaseHeaderCell',\n          enableColumnResizing: false,\n          enableColumnMenu: false,\n          exporterSuppressExport: true,\n          allowCellFocus: true\n        };\n\n        rowHeaderColumnDef.visible = grid.options.treeRowHeaderAlwaysVisible;\n        grid.addRowHeaderColumn( rowHeaderColumnDef, -100 );\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name expandAllRows\n       * @methodOf  ui.grid.treeBase.service:uiGridTreeBaseService\n       * @description Expands all nodes in the tree\n       *\n       * @param {Grid} grid grid object\n       */\n      expandAllRows: function (grid) {\n        grid.treeBase.tree.forEach( function( node ) {\n          service.setAllNodes( grid, node, uiGridTreeBaseConstants.EXPANDED);\n        });\n        grid.treeBase.expandAll = true;\n        grid.queueGridRefresh();\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name collapseAllRows\n       * @methodOf  ui.grid.treeBase.service:uiGridTreeBaseService\n       * @description Collapses all nodes in the tree\n       *\n       * @param {Grid} grid grid object\n       */\n      collapseAllRows: function (grid) {\n        grid.treeBase.tree.forEach( function( node ) {\n          service.setAllNodes( grid, node, uiGridTreeBaseConstants.COLLAPSED);\n        });\n        grid.treeBase.expandAll = false;\n        grid.queueGridRefresh();\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name setAllNodes\n       * @methodOf  ui.grid.treeBase.service:uiGridTreeBaseService\n       * @description Works through a subset of grid.treeBase.rowExpandedStates, setting\n       * all child nodes (and their descendents) of the provided node to the given state.\n       *\n       * Calls itself recursively on all nodes so as to achieve this.\n       *\n       * @param {Grid} grid the grid we're operating on (so we can raise events)\n       * @param {object} treeNode a node in the tree that we want to update\n       * @param {string} targetState the state we want to set it to\n       */\n      setAllNodes: function (grid, treeNode, targetState) {\n        if ( typeof(treeNode.state) !== 'undefined' && treeNode.state !== targetState ){\n          treeNode.state = targetState;\n\n          if ( targetState === uiGridTreeBaseConstants.EXPANDED ){\n            grid.api.treeBase.raise.rowExpanded(treeNode.row);\n          } else {\n            grid.api.treeBase.raise.rowCollapsed(treeNode.row);\n          }\n        }\n\n        // set all child nodes\n        if ( treeNode.children ){\n          treeNode.children.forEach(function( childNode ){\n            service.setAllNodes(grid, childNode, targetState);\n          });\n        }\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name toggleRowTreeState\n       * @methodOf  ui.grid.treeBase.service:uiGridTreeBaseService\n       * @description Toggles the expand or collapse state of this grouped row, if\n       * it's a parent row\n       *\n       * @param {Grid} grid grid object\n       * @param {GridRow} row the row we want to toggle\n       */\n      toggleRowTreeState: function ( grid, row ){\n        if ( typeof(row.treeLevel) === 'undefined' || row.treeLevel === null || row.treeLevel < 0 ){\n          return;\n        }\n\n        if (row.treeNode.state === uiGridTreeBaseConstants.EXPANDED){\n          service.collapseRow(grid, row);\n        } else {\n          service.expandRow(grid, row);\n        }\n\n        grid.queueGridRefresh();\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name expandRow\n       * @methodOf  ui.grid.treeBase.service:uiGridTreeBaseService\n       * @description Expands this specific row, showing only immediate children.\n       *\n       * @param {Grid} grid grid object\n       * @param {GridRow} row the row we want to expand\n       */\n      expandRow: function ( grid, row ){\n        if ( typeof(row.treeLevel) === 'undefined' || row.treeLevel === null || row.treeLevel < 0 ){\n          return;\n        }\n\n        if ( row.treeNode.state !== uiGridTreeBaseConstants.EXPANDED ){\n          row.treeNode.state = uiGridTreeBaseConstants.EXPANDED;\n          grid.api.treeBase.raise.rowExpanded(row);\n          grid.treeBase.expandAll = service.allExpanded(grid.treeBase.tree);\n          grid.queueGridRefresh();\n        }\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name expandRowChildren\n       * @methodOf  ui.grid.treeBase.service:uiGridTreeBaseService\n       * @description Expands this specific row, showing all children.\n       *\n       * @param {Grid} grid grid object\n       * @param {GridRow} row the row we want to expand\n       */\n      expandRowChildren: function ( grid, row ){\n        if ( typeof(row.treeLevel) === 'undefined' || row.treeLevel === null || row.treeLevel < 0 ){\n          return;\n        }\n\n        service.setAllNodes(grid, row.treeNode, uiGridTreeBaseConstants.EXPANDED);\n        grid.treeBase.expandAll = service.allExpanded(grid.treeBase.tree);\n        grid.queueGridRefresh();\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name collapseRow\n       * @methodOf  ui.grid.treeBase.service:uiGridTreeBaseService\n       * @description Collapses this specific row\n       *\n       * @param {Grid} grid grid object\n       * @param {GridRow} row the row we want to collapse\n       */\n      collapseRow: function( grid, row ){\n        if ( typeof(row.treeLevel) === 'undefined' || row.treeLevel === null || row.treeLevel < 0 ){\n          return;\n        }\n\n        if ( row.treeNode.state !== uiGridTreeBaseConstants.COLLAPSED ){\n          row.treeNode.state = uiGridTreeBaseConstants.COLLAPSED;\n          grid.treeBase.expandAll = false;\n          grid.api.treeBase.raise.rowCollapsed(row);\n          grid.queueGridRefresh();\n        }\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name collapseRowChildren\n       * @methodOf  ui.grid.treeBase.service:uiGridTreeBaseService\n       * @description Collapses this specific row and all children\n       *\n       * @param {Grid} grid grid object\n       * @param {GridRow} row the row we want to collapse\n       */\n      collapseRowChildren: function( grid, row ){\n        if ( typeof(row.treeLevel) === 'undefined' || row.treeLevel === null || row.treeLevel < 0 ){\n          return;\n        }\n\n        service.setAllNodes(grid, row.treeNode, uiGridTreeBaseConstants.COLLAPSED);\n        grid.treeBase.expandAll = false;\n        grid.queueGridRefresh();\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name allExpanded\n       * @methodOf  ui.grid.treeBase.service:uiGridTreeBaseService\n       * @description Returns true if all rows are expanded, false\n       * if they're not.  Walks the tree to determine this.  Used\n       * to set the expandAll state.\n       *\n       * If the node has no children, then return true (it's immaterial\n       * whether it is expanded).  If the node has children, then return\n       * false if this node is collapsed, or if any child node is not all expanded\n       *\n       * @param {object} tree the grid to check\n       * @returns {boolean} whether or not the tree is all expanded\n       */\n      allExpanded: function( tree ){\n        var allExpanded = true;\n        tree.forEach( function( node ){\n          if ( !service.allExpandedInternal( node ) ){\n            allExpanded = false;\n          }\n        });\n        return allExpanded;\n      },\n\n      allExpandedInternal: function( treeNode ){\n        if ( treeNode.children && treeNode.children.length > 0 ){\n          if ( treeNode.state === uiGridTreeBaseConstants.COLLAPSED ){\n            return false;\n          }\n          var allExpanded = true;\n          treeNode.children.forEach( function( node ){\n            if ( !service.allExpandedInternal( node ) ){\n              allExpanded = false;\n            }\n          });\n          return allExpanded;\n        } else {\n          return true;\n        }\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name treeRows\n       * @methodOf  ui.grid.treeBase.service:uiGridTreeBaseService\n       * @description The rowProcessor that adds the nodes to the tree, and sets the visible\n       * state of each row based on it's parent state\n       *\n       * Assumes it is always called after the sorting processor, and the grouping processor if there is one.\n       * Performs any tree sorts itself after having built the tree\n       *\n       * Processes all the rows in order, setting the group level based on the $$treeLevel in the associated\n       * entity, and setting the visible state based on the parent's state.\n       *\n       * Calculates the deepest level of tree whilst it goes, and updates that so that the header column can be correctly\n       * sized.\n       *\n       * Aggregates if necessary along the way.\n       *\n       * @param {array} renderableRows the rows we want to process, usually the output from the previous rowProcessor\n       * @returns {array} the updated rows\n       */\n      treeRows: function( renderableRows ) {\n        if (renderableRows.length === 0){\n          return renderableRows;\n        }\n\n        var grid = this;\n        var currentLevel = 0;\n        var currentState = uiGridTreeBaseConstants.EXPANDED;\n        var parents = [];\n\n        grid.treeBase.tree = service.createTree( grid, renderableRows );\n        service.updateRowHeaderWidth( grid );\n\n        service.sortTree( grid );\n        service.fixFilter( grid );\n\n        return service.renderTree( grid.treeBase.tree );\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name createOrUpdateRowHeaderWidth\n       * @methodOf  ui.grid.treeBase.service:uiGridTreeBaseService\n       * @description Calculates the rowHeader width.\n       *\n       * If rowHeader is always present, updates the width.\n       *\n       * If rowHeader is only sometimes present (`treeRowHeaderAlwaysVisible: false`), determines whether there\n       * should be one, then creates or removes it as appropriate, with the created rowHeader having the\n       * right width.\n       *\n       * If there's never a rowHeader then never creates one: `showTreeRowHeader: false`\n       *\n       * @param {Grid} grid the grid we want to set the row header on\n       */\n      updateRowHeaderWidth: function( grid ){\n        var rowHeader = grid.getColumn(uiGridTreeBaseConstants.rowHeaderColName);\n\n        var newWidth = grid.options.treeRowHeaderBaseWidth + grid.options.treeIndent * Math.max(grid.treeBase.numberLevels - 1, 0);\n        if ( rowHeader && newWidth !== rowHeader.width ){\n          rowHeader.width = newWidth;\n          grid.queueRefresh();\n        }\n\n        var newVisibility = true;\n        if ( grid.options.showTreeRowHeader === false ){\n          newVisibility = false;\n        }\n        if ( grid.options.treeRowHeaderAlwaysVisible === false && grid.treeBase.numberLevels <= 0 ){\n          newVisibility = false;\n        }\n        if ( rowHeader.visible !== newVisibility ) {\n          rowHeader.visible = newVisibility;\n          rowHeader.colDef.visible = newVisibility;\n          grid.queueGridRefresh();\n        }\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name renderTree\n       * @methodOf  ui.grid.treeBase.service:uiGridTreeBaseService\n       * @description Creates an array of rows based on the tree, exporting only\n       * the visible nodes and leaves\n       *\n       * @param {array} nodeList the list of nodes - can be grid.treeBase.tree, or can be node.children when\n       * we're calling recursively\n       * @returns {array} renderable rows\n       */\n      renderTree: function( nodeList ){\n        var renderableRows = [];\n\n        nodeList.forEach( function ( node ){\n          if ( node.row.visible ){\n            renderableRows.push( node.row );\n          }\n          if ( node.state === uiGridTreeBaseConstants.EXPANDED && node.children && node.children.length > 0 ){\n            renderableRows = renderableRows.concat( service.renderTree( node.children ) );\n          }\n        });\n        return renderableRows;\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name createTree\n       * @methodOf  ui.grid.treeBase.service:uiGridTreeBaseService\n       * @description Creates a tree from the renderableRows\n       *\n       * @param {Grid} grid the grid\n       * @param {array} renderableRows the rows we want to create a tree from\n       * @returns {object} the tree we've build\n       */\n      createTree: function( grid, renderableRows ) {\n        var currentLevel = -1;\n        var parents = [];\n        var currentState;\n        grid.treeBase.tree = [];\n        grid.treeBase.numberLevels = 0;\n        var aggregations = service.getAggregations( grid );\n\n        var createNode = function( row ){\n          if ( typeof(row.entity.$$treeLevel) !== 'undefined' && row.treeLevel !== row.entity.$$treeLevel ){\n            row.treeLevel = row.entity.$$treeLevel;\n          }\n\n          if ( row.treeLevel <= currentLevel ){\n            // pop any levels that aren't parents of this level, formatting the aggregation at the same time\n            while ( row.treeLevel <= currentLevel ){\n              var lastParent = parents.pop();\n              service.finaliseAggregations( lastParent );\n              currentLevel--;\n            }\n\n            // reset our current state based on the new parent, set to expanded if this is a level 0 node\n            if ( parents.length > 0 ){\n              currentState = service.setCurrentState(parents);\n            } else {\n              currentState = uiGridTreeBaseConstants.EXPANDED;\n            }\n          }\n\n          // aggregate if this is a leaf node\n          if ( ( typeof(row.treeLevel) === 'undefined' || row.treeLevel === null || row.treeLevel < 0 ) && row.visible  ){\n            service.aggregate( grid, row, parents );\n          }\n\n          // add this node to the tree\n          service.addOrUseNode(grid, row, parents, aggregations);\n\n          if ( typeof(row.treeLevel) !== 'undefined' && row.treeLevel !== null && row.treeLevel >= 0 ){\n            parents.push(row);\n            currentLevel++;\n            currentState = service.setCurrentState(parents);\n          }\n\n          // update the tree number of levels, so we can set header width if we need to\n          if ( grid.treeBase.numberLevels < row.treeLevel + 1){\n            grid.treeBase.numberLevels = row.treeLevel + 1;\n          }\n        };\n\n        renderableRows.forEach( createNode );\n\n        // finalise remaining aggregations\n        while ( parents.length > 0 ){\n          var lastParent = parents.pop();\n          service.finaliseAggregations( lastParent );\n        }\n\n        return grid.treeBase.tree;\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name addOrUseNode\n       * @methodOf  ui.grid.treeBase.service:uiGridTreeBaseService\n       * @description Creates a tree node for this row.  If this row already has a treeNode\n       * recorded against it, preserves the state, but otherwise overwrites the data.\n       *\n       * @param {grid} grid the grid we're operating on\n       * @param {gridRow} row the row we want to set\n       * @param {array} parents an array of the parents this row should have\n       * @param {array} aggregationBase empty aggregation information\n       * @returns {undefined} updates the parents array, updates the row to have a treeNode, and updates the\n       * grid.treeBase.tree\n       */\n      addOrUseNode: function( grid, row, parents, aggregationBase ){\n        var newAggregations = [];\n        aggregationBase.forEach( function(aggregation){\n          newAggregations.push(service.buildAggregationObject(aggregation.col));\n        });\n\n        var newNode = { state: uiGridTreeBaseConstants.COLLAPSED, row: row, parentRow: null, aggregations: newAggregations, children: [] };\n        if ( row.treeNode ){\n          newNode.state = row.treeNode.state;\n        }\n        if ( parents.length > 0 ){\n          newNode.parentRow = parents[parents.length - 1];\n        }\n        row.treeNode = newNode;\n\n        if ( parents.length === 0 ){\n          grid.treeBase.tree.push( newNode );\n        } else {\n          parents[parents.length - 1].treeNode.children.push( newNode );\n        }\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name setCurrentState\n       * @methodOf  ui.grid.treeBase.service:uiGridTreeBaseService\n       * @description Looks at the parents array to determine our current state.\n       * If any node in the hierarchy is collapsed, then return collapsed, otherwise return\n       * expanded.\n       *\n       * @param {array} parents an array of the parents this row should have\n       * @returns {string} the state we should be setting to any nodes we see\n       */\n      setCurrentState: function( parents ){\n        var currentState = uiGridTreeBaseConstants.EXPANDED;\n        parents.forEach( function(parent){\n          if ( parent.treeNode.state === uiGridTreeBaseConstants.COLLAPSED ){\n            currentState = uiGridTreeBaseConstants.COLLAPSED;\n          }\n        });\n        return currentState;\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name sortTree\n       * @methodOf  ui.grid.treeBase.service:uiGridTreeBaseService\n       * @description Performs a recursive sort on the tree nodes, sorting the\n       * children of each node and putting them back into the children array.\n       *\n       * Before doing this it turns back on all the sortIgnore - things that were previously\n       * ignored we process now.  Since we're sorting within the nodes, presumably anything\n       * that was already sorted is how we derived the nodes, we can keep those sorts too.\n       *\n       * We only sort tree nodes that are expanded - no point in wasting effort sorting collapsed\n       * nodes\n       *\n       * @param {Grid} grid the grid to get the aggregation information from\n       * @returns {array} the aggregation information\n       */\n      sortTree: function( grid ){\n        grid.columns.forEach( function( column ) {\n          if ( column.sort && column.sort.ignoreSort ){\n            delete column.sort.ignoreSort;\n          }\n        });\n\n        grid.treeBase.tree = service.sortInternal( grid, grid.treeBase.tree );\n      },\n\n      sortInternal: function( grid, treeList ){\n        var rows = treeList.map( function( node ){\n          return node.row;\n        });\n\n        rows = rowSorter.sort( grid, rows, grid.columns );\n\n        var treeNodes = rows.map( function( row ){\n          return row.treeNode;\n        });\n\n        treeNodes.forEach( function( node ){\n          if ( node.state === uiGridTreeBaseConstants.EXPANDED && node.children && node.children.length > 0 ){\n            node.children = service.sortInternal( grid, node.children );\n          }\n        });\n\n        return treeNodes;\n      },\n\n      /**\n       * @ngdoc function\n       * @name fixFilter\n       * @methodOf  ui.grid.treeBase.service:uiGridTreeBaseService\n       * @description After filtering has run, we need to go back through the tree\n       * and make sure the parent rows are always visible if any of the child rows\n       * are visible (filtering may make a child visible, but the parent may not\n       * match the filter criteria)\n       *\n       * This has a risk of being computationally expensive, we do it by walking\n       * the tree and remembering whether there are any invisible nodes on the\n       * way down.\n       *\n       * @param {Grid} grid the grid to fix filters on\n       */\n      fixFilter: function( grid ){\n        var parentsVisible;\n\n        grid.treeBase.tree.forEach( function( node ){\n          if ( node.children && node.children.length > 0 ){\n            parentsVisible = node.row.visible;\n            service.fixFilterInternal( node.children, parentsVisible );\n          }\n        });\n      },\n\n      fixFilterInternal: function( nodes, parentsVisible) {\n        nodes.forEach( function( node ){\n          if ( node.row.visible && !parentsVisible ){\n            service.setParentsVisible( node );\n            parentsVisible = true;\n          }\n\n          if ( node.children && node.children.length > 0 ){\n            if ( service.fixFilterInternal( node.children, ( parentsVisible && node.row.visible ) ) ) {\n              parentsVisible = true;\n            }\n          }\n        });\n\n        return parentsVisible;\n      },\n\n      setParentsVisible: function( node ){\n        while ( node.parentRow ){\n          node.parentRow.visible = true;\n          node = node.parentRow.treeNode;\n        }\n      },\n\n      /**\n       * @ngdoc function\n       * @name buildAggregationObject\n       * @methodOf  ui.grid.treeBase.service:uiGridTreeBaseService\n       * @description Build the object which is stored on the column for holding meta-data about the aggregation.\n       * This method should only be called with columns which have an aggregation.\n       *\n       * @param {Column} the column which this object relates to\n       * @returns {object} {col: Column object, label: string, type: string (optional)}\n       */\n      buildAggregationObject: function( column ){\n        var newAggregation = { col: column };\n\n        if ( column.treeAggregation && column.treeAggregation.type ){\n          newAggregation.type = column.treeAggregation.type;\n        }\n\n        if ( column.treeAggregation && column.treeAggregation.label ){\n          newAggregation.label = column.treeAggregation.label;\n        }\n\n        return newAggregation;\n      },\n\n      /**\n       * @ngdoc function\n       * @name getAggregations\n       * @methodOf  ui.grid.treeBase.service:uiGridTreeBaseService\n       * @description Looks through the grid columns to find those with aggregations,\n       * and collates the aggregation information into an array, returns that array\n       *\n       * @param {Grid} grid the grid to get the aggregation information from\n       * @returns {array} the aggregation information\n       */\n      getAggregations: function( grid ){\n        var aggregateArray = [];\n\n        grid.columns.forEach( function(column){\n          if ( typeof(column.treeAggregationFn) !== 'undefined' ){\n            aggregateArray.push( service.buildAggregationObject(column) );\n\n            if ( grid.options.showColumnFooter && typeof(column.colDef.aggregationType) === 'undefined' && column.treeAggregation ){\n              // Add aggregation object for footer\n              column.treeFooterAggregation = service.buildAggregationObject(column);\n              column.aggregationType = service.treeFooterAggregationType;\n            }\n          }\n        });\n        return aggregateArray;\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name aggregate\n       * @methodOf  ui.grid.treeBase.service:uiGridTreeBaseService\n       * @description Accumulate the data from this row onto the aggregations for each parent\n       *\n       * Iterate over the parents, then iterate over the aggregations for each of those parents,\n       * and perform the aggregation for each individual aggregation\n       *\n       * @param {Grid} grid grid object\n       * @param {GridRow} row the row we want to set grouping visibility on\n       * @param {array} parents the parents that we would want to aggregate onto\n       */\n      aggregate: function( grid, row, parents ){\n        if ( parents.length === 0 && row.treeNode && row.treeNode.aggregations ){\n          row.treeNode.aggregations.forEach(function(aggregation){\n            // Calculate aggregations for footer even if there are no grouped rows\n            if ( typeof(aggregation.col.treeFooterAggregation) !== 'undefined' ) {\n              var fieldValue = grid.getCellValue(row, aggregation.col);\n              var numValue = Number(fieldValue);\n              aggregation.col.treeAggregationFn(aggregation.col.treeFooterAggregation, fieldValue, numValue, row);\n            }\n          });\n        }\n\n        parents.forEach( function( parent, index ){\n          if ( parent.treeNode.aggregations ){\n            parent.treeNode.aggregations.forEach( function( aggregation ){\n              var fieldValue = grid.getCellValue(row, aggregation.col);\n              var numValue = Number(fieldValue);\n              aggregation.col.treeAggregationFn(aggregation, fieldValue, numValue, row);\n\n              if ( index === 0 && typeof(aggregation.col.treeFooterAggregation) !== 'undefined' ){\n                aggregation.col.treeAggregationFn(aggregation.col.treeFooterAggregation, fieldValue, numValue, row);\n              }\n            });\n          }\n        });\n      },\n\n\n      // Aggregation routines - no doco needed as self evident\n      nativeAggregations: function() {\n        var nativeAggregations = {\n          count: {\n            label: i18nService.get().aggregation.count,\n            menuTitle: i18nService.get().grouping.aggregate_count,\n            aggregationFn: function (aggregation, fieldValue, numValue) {\n              if (typeof(aggregation.value) === 'undefined') {\n                aggregation.value = 1;\n              } else {\n                aggregation.value++;\n              }\n            }\n          },\n\n          sum: {\n            label: i18nService.get().aggregation.sum,\n            menuTitle: i18nService.get().grouping.aggregate_sum,\n            aggregationFn: function( aggregation, fieldValue, numValue ) {\n              if (!isNaN(numValue)) {\n                if (typeof(aggregation.value) === 'undefined') {\n                  aggregation.value = numValue;\n                } else {\n                  aggregation.value += numValue;\n                }\n              }\n            }\n          },\n\n          min: {\n            label: i18nService.get().aggregation.min,\n            menuTitle: i18nService.get().grouping.aggregate_min,\n            aggregationFn: function( aggregation, fieldValue, numValue ) {\n              if (typeof(aggregation.value) === 'undefined') {\n                aggregation.value = fieldValue;\n              } else {\n                if (typeof(fieldValue) !== 'undefined' && fieldValue !== null && (fieldValue < aggregation.value || aggregation.value === null)) {\n                  aggregation.value = fieldValue;\n                }\n              }\n            }\n          },\n\n          max: {\n            label: i18nService.get().aggregation.max,\n            menuTitle: i18nService.get().grouping.aggregate_max,\n            aggregationFn: function( aggregation, fieldValue, numValue ){\n              if ( typeof(aggregation.value) === 'undefined' ){\n                aggregation.value = fieldValue;\n              } else {\n                if ( typeof(fieldValue) !== 'undefined' && fieldValue !== null && (fieldValue > aggregation.value || aggregation.value === null)){\n                  aggregation.value = fieldValue;\n                }\n              }\n            }\n          },\n\n          avg: {\n            label: i18nService.get().aggregation.avg,\n            menuTitle: i18nService.get().grouping.aggregate_avg,\n            aggregationFn: function( aggregation, fieldValue, numValue ){\n              if ( typeof(aggregation.count) === 'undefined' ){\n                aggregation.count = 1;\n              } else {\n                aggregation.count++;\n              }\n\n              if ( isNaN(numValue) ){\n                return;\n              }\n\n              if ( typeof(aggregation.value) === 'undefined' || typeof(aggregation.sum) === 'undefined' ){\n                aggregation.value = numValue;\n                aggregation.sum = numValue;\n              } else {\n                aggregation.sum += numValue;\n                aggregation.value = aggregation.sum / aggregation.count;\n              }\n            }\n          }\n        };\n        return nativeAggregations;\n      },\n\n      /**\n       * @ngdoc function\n       * @name finaliseAggregation\n       * @methodOf  ui.grid.treeBase.service:uiGridTreeBaseService\n       * @description Helper function used to finalize aggregation nodes and footer cells\n       *\n       * @param {gridRow} row the parent we're finalising\n       * @param {aggregation} the aggregation object manipulated by the aggregationFn\n       */\n      finaliseAggregation: function(row, aggregation){\n        if ( aggregation.col.treeAggregationUpdateEntity && typeof(row) !== 'undefined' && typeof(row.entity[ '$$' + aggregation.col.uid ]) !== 'undefined' ){\n          angular.extend( aggregation, row.entity[ '$$' + aggregation.col.uid ]);\n        }\n\n        if ( typeof(aggregation.col.treeAggregationFinalizerFn) === 'function' ){\n          aggregation.col.treeAggregationFinalizerFn( aggregation );\n        }\n        if ( typeof(aggregation.col.customTreeAggregationFinalizerFn) === 'function' ){\n          aggregation.col.customTreeAggregationFinalizerFn( aggregation );\n        }\n        if ( typeof(aggregation.rendered) === 'undefined' ){\n          aggregation.rendered = aggregation.label ? aggregation.label + aggregation.value : aggregation.value;\n        }\n      },\n\n      /**\n       * @ngdoc function\n       * @name finaliseAggregations\n       * @methodOf  ui.grid.treeBase.service:uiGridTreeBaseService\n       * @description Format the data from the aggregation into the rendered text\n       * e.g. if we had label: 'sum: ' and value: 25, we'd create 'sum: 25'.\n       *\n       * As part of this we call any formatting callback routines we've been provided.\n       *\n       * We write our aggregation out to the row.entity if treeAggregationUpdateEntity is\n       * set on the column - we don't overwrite any information that's already there, we append\n       * to it so that grouping can have set the groupVal beforehand without us overwriting it.\n       *\n       * We need to copy the data from the row.entity first before we finalise the aggregation,\n       * we need that information for the finaliserFn\n       *\n       * @param {gridRow} row the parent we're finalising\n       */\n      finaliseAggregations: function( row ){\n        if ( row == null || typeof(row.treeNode.aggregations) === 'undefined' ){\n          return;\n        }\n\n        row.treeNode.aggregations.forEach( function( aggregation ) {\n          service.finaliseAggregation(row, aggregation);\n\n          if ( aggregation.col.treeAggregationUpdateEntity ){\n            var aggregationCopy = {};\n            angular.forEach( aggregation, function( value, key ){\n              if ( aggregation.hasOwnProperty(key) && key !== 'col' ){\n                aggregationCopy[key] = value;\n              }\n            });\n\n            row.entity[ '$$' + aggregation.col.uid ] = aggregationCopy;\n          }\n        });\n      },\n\n      /**\n       * @ngdoc function\n       * @name treeFooterAggregationType\n       * @methodOf  ui.grid.treeBase.service:uiGridTreeBaseService\n       * @description Uses the tree aggregation functions and finalizers to set the\n       * column footer aggregations.\n       *\n       * @param {rows} visible rows. not used, but accepted to match signature of GridColumn.aggregationType\n       * @param {gridColumn} the column we are finalizing\n       */\n      treeFooterAggregationType: function( rows, column ) {\n        service.finaliseAggregation(undefined, column.treeFooterAggregation);\n        if ( typeof(column.treeFooterAggregation.value) === 'undefined' || column.treeFooterAggregation.rendered === null ){\n          // The was apparently no aggregation performed (perhaps this is a grouped column\n          return '';\n        }\n        return column.treeFooterAggregation.rendered;\n      }\n    };\n\n    return service;\n\n  }]);\n\n\n  /**\n   *  @ngdoc directive\n   *  @name ui.grid.treeBase.directive:uiGridTreeRowHeaderButtons\n   *  @element div\n   *\n   *  @description Provides the expand/collapse button on rows\n   */\n  module.directive('uiGridTreeBaseRowHeaderButtons', ['$templateCache', 'uiGridTreeBaseService',\n  function ($templateCache, uiGridTreeBaseService) {\n    return {\n      replace: true,\n      restrict: 'E',\n      template: $templateCache.get('ui-grid/treeBaseRowHeaderButtons'),\n      scope: true,\n      require: '^uiGrid',\n      link: function($scope, $elm, $attrs, uiGridCtrl) {\n        var self = uiGridCtrl.grid;\n        $scope.treeButtonClick = function(row, evt) {\n          uiGridTreeBaseService.toggleRowTreeState(self, row, evt);\n        };\n      }\n    };\n  }]);\n\n\n  /**\n   *  @ngdoc directive\n   *  @name ui.grid.treeBase.directive:uiGridTreeBaseExpandAllButtons\n   *  @element div\n   *\n   *  @description Provides the expand/collapse all button\n   */\n  module.directive('uiGridTreeBaseExpandAllButtons', ['$templateCache', 'uiGridTreeBaseService',\n  function ($templateCache, uiGridTreeBaseService) {\n    return {\n      replace: true,\n      restrict: 'E',\n      template: $templateCache.get('ui-grid/treeBaseExpandAllButtons'),\n      scope: false,\n      link: function($scope, $elm, $attrs, uiGridCtrl) {\n        var self = $scope.col.grid;\n\n        $scope.headerButtonClick = function(row, evt) {\n          if ( self.treeBase.expandAll ){\n            uiGridTreeBaseService.collapseAllRows(self, evt);\n          } else {\n            uiGridTreeBaseService.expandAllRows(self, evt);\n          }\n        };\n      }\n    };\n  }]);\n\n\n  /**\n   *  @ngdoc directive\n   *  @name ui.grid.treeBase.directive:uiGridViewport\n   *  @element div\n   *\n   *  @description Stacks on top of ui.grid.uiGridViewport to set formatting on a tree header row\n   */\n  module.directive('uiGridViewport',\n  ['$compile', 'uiGridConstants', 'gridUtil', '$parse',\n    function ($compile, uiGridConstants, gridUtil, $parse) {\n      return {\n        priority: -200, // run after default  directive\n        scope: false,\n        compile: function ($elm, $attrs) {\n          var rowRepeatDiv = angular.element($elm.children().children()[0]);\n\n          var existingNgClass = rowRepeatDiv.attr(\"ng-class\");\n          var newNgClass = '';\n          if ( existingNgClass ) {\n            newNgClass = existingNgClass.slice(0, -1) + \",'ui-grid-tree-header-row': row.treeLevel > -1}\";\n          } else {\n            newNgClass = \"{'ui-grid-tree-header-row': row.treeLevel > -1}\";\n          }\n          rowRepeatDiv.attr(\"ng-class\", newNgClass);\n\n          return {\n            pre: function ($scope, $elm, $attrs, controllers) {\n\n            },\n            post: function ($scope, $elm, $attrs, controllers) {\n            }\n          };\n        }\n      };\n    }]);\n})();\n\n(function () {\n  'use strict';\n\n  /**\n   * @ngdoc overview\n   * @name ui.grid.treeView\n   * @description\n   *\n   * # ui.grid.treeView\n   *\n   * <div class=\"alert alert-warning\" role=\"alert\"><strong>Beta</strong> This feature is ready for testing, but it either hasn't seen a lot of use or has some known bugs.</div>\n   *\n   * This module provides a tree view of the data that it is provided, with nodes in that\n   * tree and leaves.  Unlike grouping, the tree is an inherent property of the data and must\n   * be provided with your data array.\n   *\n   * Design information:\n   * -------------------\n   *\n   * TreeView uses treeBase for the underlying functionality, and is a very thin wrapper around\n   * that logic.  Most of the design information has now moved to treebase.\n   * <br/>\n   * <br/>\n   *\n   * <div doc-module-components=\"ui.grid.treeView\"></div>\n   */\n\n  var module = angular.module('ui.grid.treeView', ['ui.grid', 'ui.grid.treeBase']);\n\n  /**\n   *  @ngdoc object\n   *  @name ui.grid.treeView.constant:uiGridTreeViewConstants\n   *\n   *  @description constants available in treeView module, this includes\n   *  all the constants declared in the treeBase module (these are manually copied\n   *  as there isn't an easy way to include constants in another constants file, and\n   *  we don't want to make users include treeBase)\n   *\n   */\n  module.constant('uiGridTreeViewConstants', {\n    featureName: \"treeView\",\n    rowHeaderColName: 'treeBaseRowHeaderCol',\n    EXPANDED: 'expanded',\n    COLLAPSED: 'collapsed',\n    aggregation: {\n      COUNT: 'count',\n      SUM: 'sum',\n      MAX: 'max',\n      MIN: 'min',\n      AVG: 'avg'\n    }\n  });\n\n  /**\n   *  @ngdoc service\n   *  @name ui.grid.treeView.service:uiGridTreeViewService\n   *\n   *  @description Services for treeView features\n   */\n  module.service('uiGridTreeViewService', ['$q', 'uiGridTreeViewConstants', 'uiGridTreeBaseConstants', 'uiGridTreeBaseService', 'gridUtil', 'GridRow', 'gridClassFactory', 'i18nService', 'uiGridConstants',\n  function ($q, uiGridTreeViewConstants, uiGridTreeBaseConstants, uiGridTreeBaseService, gridUtil, GridRow, gridClassFactory, i18nService, uiGridConstants) {\n\n    var service = {\n\n      initializeGrid: function (grid, $scope) {\n        uiGridTreeBaseService.initializeGrid( grid, $scope );\n\n        /**\n         *  @ngdoc object\n         *  @name ui.grid.treeView.grid:treeView\n         *\n         *  @description Grid properties and functions added for treeView\n         */\n        grid.treeView = {};\n\n        grid.registerRowsProcessor(service.adjustSorting, 60);\n\n        /**\n         *  @ngdoc object\n         *  @name ui.grid.treeView.api:PublicApi\n         *\n         *  @description Public Api for treeView feature\n         */\n        var publicApi = {\n          events: {\n            treeView: {\n            }\n          },\n          methods: {\n            treeView: {\n            }\n          }\n        };\n\n        grid.api.registerEventsFromObject(publicApi.events);\n\n        grid.api.registerMethodsFromObject(publicApi.methods);\n\n      },\n\n      defaultGridOptions: function (gridOptions) {\n        //default option to true unless it was explicitly set to false\n        /**\n         *  @ngdoc object\n         *  @name ui.grid.treeView.api:GridOptions\n         *\n         *  @description GridOptions for treeView feature, these are available to be\n         *  set using the ui-grid {@link ui.grid.class:GridOptions gridOptions}\n         *\n         *  Many tree options are set on treeBase, make sure to look at that feature in\n         *  conjunction with these options.\n         */\n\n        /**\n         *  @ngdoc object\n         *  @name enableTreeView\n         *  @propertyOf  ui.grid.treeView.api:GridOptions\n         *  @description Enable row tree view for entire grid.\n         *  <br/>Defaults to true\n         */\n        gridOptions.enableTreeView = gridOptions.enableTreeView !== false;\n\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name adjustSorting\n       * @methodOf  ui.grid.treeBase.service:uiGridTreeBaseService\n       * @description Trees cannot be sorted the same as flat lists of rows -\n       * trees are sorted recursively within each level - so the children of each\n       * node are sorted, but not the full set of rows.\n       *\n       * To achieve this, we suppress the normal sorting by setting ignoreSort on\n       * each of the sort columns.  When the treeBase rowsProcessor runs it will then\n       * unignore these, and will perform a recursive sort against the tree that it builds.\n       *\n       * @param {array} renderableRows the rows that we need to pass on through\n       * @returns {array} renderableRows that we passed on through\n       */\n      adjustSorting: function( renderableRows ) {\n        var grid = this;\n\n        grid.columns.forEach( function( column ){\n          if ( column.sort ){\n            column.sort.ignoreSort = true;\n          }\n        });\n\n        return renderableRows;\n      }\n\n    };\n\n    return service;\n\n  }]);\n\n  /**\n   *  @ngdoc directive\n   *  @name ui.grid.treeView.directive:uiGridTreeView\n   *  @element div\n   *  @restrict A\n   *\n   *  @description Adds treeView features to grid\n   *\n   *  @example\n   <example module=\"app\">\n   <file name=\"app.js\">\n   var app = angular.module('app', ['ui.grid', 'ui.grid.treeView']);\n\n   app.controller('MainCtrl', ['$scope', function ($scope) {\n      $scope.data = [\n        { name: 'Bob', title: 'CEO' },\n            { name: 'Frank', title: 'Lowly Developer' }\n      ];\n\n      $scope.columnDefs = [\n        {name: 'name', enableCellEdit: true},\n        {name: 'title', enableCellEdit: true}\n      ];\n\n      $scope.gridOptions = { columnDefs: $scope.columnDefs, data: $scope.data };\n    }]);\n   </file>\n   <file name=\"index.html\">\n   <div ng-controller=\"MainCtrl\">\n   <div ui-grid=\"gridOptions\" ui-grid-tree-view></div>\n   </div>\n   </file>\n   </example>\n   */\n  module.directive('uiGridTreeView', ['uiGridTreeViewConstants', 'uiGridTreeViewService', '$templateCache',\n  function (uiGridTreeViewConstants, uiGridTreeViewService, $templateCache) {\n    return {\n      replace: true,\n      priority: 0,\n      require: '^uiGrid',\n      scope: false,\n      compile: function () {\n        return {\n          pre: function ($scope, $elm, $attrs, uiGridCtrl) {\n            if (uiGridCtrl.grid.options.enableTreeView !== false){\n              uiGridTreeViewService.initializeGrid(uiGridCtrl.grid, $scope);\n            }\n          },\n          post: function ($scope, $elm, $attrs, uiGridCtrl) {\n\n          }\n        };\n      }\n    };\n  }]);\n})();\n\n(function () {\n  'use strict';\n  \n  /**\n   * @ngdoc overview\n   * @name ui.grid.validate\n   * @description\n   *\n   * # ui.grid.validate\n   *\n   * <div class=\"alert alert-warning\" role=\"alert\"><strong>Alpha</strong> This feature is in development. There will almost certainly be breaking api changes, or there are major outstanding bugs.</div>\n   *\n   * This module provides the ability to validate cells upon change.\n   *\n   * Design information:\n   * -------------------\n   *\n   * Validation is not based on angularjs validation, since it would work only when editing the field.\n   * \n   * Instead it adds custom properties to any field considered as invalid.\n   *\n   * <br/>\n   * <br/>\n   *\n   * <div doc-module-components=\"ui.grid.expandable\"></div>\n   */\n\n  var module = angular.module('ui.grid.validate', ['ui.grid']);\n  \n  \n  /**\n   *  @ngdoc service\n   *  @name ui.grid.validate.service:uiGridValidateService\n   *\n   *  @description Services for validation features\n   */\n  module.service('uiGridValidateService', ['$sce', '$q', '$http', 'i18nService', 'uiGridConstants', function ($sce, $q, $http, i18nService, uiGridConstants) {\n\n    var service = {\n      \n      /**\n       *  @ngdoc object\n       *  @name validatorFactories\n       *  @propertyOf ui.grid.validate.service:uiGridValidateService\n       *  @description object containing all the factories used to validate data.<br/>\n       *  These factories will be in the form <br/>\n       *  ```\n       *  {\n       *    validatorFactory: function(argument) {\n       *                        return function(newValue, oldValue, rowEntity, colDef) {\n       *                          return true || false || promise\n       *                        }\n       *                      },\n       *    messageFunction: function(argument) {\n       *                       return string\n       *                     }\n       *  }\n       *  ```\n       *\n       * Promises should return true or false as result according to the result of validation.\n       */\n      validatorFactories: {},\n\n      \n      /**\n       * @ngdoc service\n       * @name setExternalFactoryFunction\n       * @methodOf ui.grid.validate.service:uiGridValidateService\n       * @description Adds a way to retrieve validators from an external service\n       * <p>Validators from this external service have a higher priority than default\n       * ones\n       * @param {function} externalFactoryFunction a function that accepts name and argument to pass to a\n       * validator factory and that returns an object with the same properties as \n       * you can see in {@link ui.grid.validate.service:uiGridValidateService#properties_validatorFactories validatorFactories}\n       */\n      setExternalFactoryFunction: function(externalFactoryFunction) {\n        service.externalFactoryFunction = externalFactoryFunction;\n      },\n      \n      /**\n       * @ngdoc service\n       * @name clearExternalFactory\n       * @methodOf ui.grid.validate.service:uiGridValidateService\n       * @description Removes any link to external factory from this service\n       */\n      clearExternalFactory: function() {\n        delete service.externalFactoryFunction;\n      },\n\n      /**\n       * @ngdoc service\n       * @name getValidatorFromExternalFactory\n       * @methodOf ui.grid.validate.service:uiGridValidateService\n       * @description Retrieves a validator by executing a validatorFactory\n       * stored in an external service.\n       * @param {string} name the name of the validator to retrieve\n       * @param {object} argument an argument to pass to the validator factory\n       */\n      getValidatorFromExternalFactory: function(name, argument) {\n        return service.externalFactoryFunction(name, argument).validatorFactory(argument);\n      },\n      \n      /**\n       * @ngdoc service\n       * @name getMessageFromExternalFactory\n       * @methodOf ui.grid.validate.service:uiGridValidateService\n       * @description Retrieves a message stored in an external service.\n       * @param {string} name the name of the validator\n       * @param {object} argument an argument to pass to the message function\n       */\n      getMessageFromExternalFactory: function(name, argument) {\n        return service.externalFactoryFunction(name, argument).messageFunction(argument);\n      },\n      \n      /**\n       * @ngdoc service\n       * @name setValidator\n       * @methodOf ui.grid.validate.service:uiGridValidateService\n       * @description  Adds a new validator to the service\n       * @param {string} name the name of the validator, must be unique\n       * @param {function} validatorFactory a factory that return a validatorFunction\n       * @param {function} messageFunction a function that return the error message\n       */\n      setValidator: function(name, validatorFactory, messageFunction) {\n        service.validatorFactories[name] = {\n          validatorFactory: validatorFactory,\n          messageFunction: messageFunction\n        };\n      },\n\n      /**\n       * @ngdoc service\n       * @name getValidator\n       * @methodOf ui.grid.validate.service:uiGridValidateService\n       * @description Returns a validator registered to the service\n       * or retrieved from the external factory\n       * @param {string} name the name of the validator to retrieve\n       * @param {object} argument an argument to pass to the validator factory\n       * @returns {object} the validator function\n       */\n      getValidator: function(name, argument) {\n        if (service.externalFactoryFunction) {\n          var validator = service.getValidatorFromExternalFactory(name, argument);\n          if (validator) {\n            return validator;\n          }\n        }\n        if (!service.validatorFactories[name]) {\n          throw (\"Invalid validator name: \" + name);\n        }\n        return service.validatorFactories[name].validatorFactory(argument);\n      },\n\n      /**\n       * @ngdoc service\n       * @name getMessage\n       * @methodOf ui.grid.validate.service:uiGridValidateService\n       * @description Returns the error message related to the validator \n       * @param {string} name the name of the validator\n       * @param {object} argument an argument to pass to the message function\n       * @returns {string} the error message related to the validator\n       */\n      getMessage: function(name, argument) {\n        if (service.externalFactoryFunction) {\n          var message = service.getMessageFromExternalFactory(name, argument);\n          if (message) {\n            return message;\n          }\n        }\n        return service.validatorFactories[name].messageFunction(argument);\n      },\n\n      /**\n       * @ngdoc service\n       * @name isInvalid\n       * @methodOf ui.grid.validate.service:uiGridValidateService\n       * @description Returns true if the cell (identified by rowEntity, colDef) is invalid \n       * @param {object} rowEntity the row entity of the cell\n       * @param {object} colDef the colDef of the cell\n       * @returns {boolean} true if the cell is invalid\n       */\n      isInvalid: function (rowEntity, colDef) {\n        return rowEntity['$$invalid'+colDef.name];\n      },\n\n      /**\n       * @ngdoc service\n       * @name setInvalid\n       * @methodOf ui.grid.validate.service:uiGridValidateService\n       * @description Makes the cell invalid by adding the proper field to the entity\n       * @param {object} rowEntity the row entity of the cell\n       * @param {object} colDef the colDef of the cell\n       */\n      setInvalid: function (rowEntity, colDef) {\n        rowEntity['$$invalid'+colDef.name] = true;\n      },\n    \n      /**\n       * @ngdoc service\n       * @name setValid\n       * @methodOf ui.grid.validate.service:uiGridValidateService\n       * @description Makes the cell valid by removing the proper error field from the entity\n       * @param {object} rowEntity the row entity of the cell\n       * @param {object} colDef the colDef of the cell\n       */\n      setValid: function (rowEntity, colDef) {\n        delete rowEntity['$$invalid'+colDef.name];\n      },\n\n      /**\n       * @ngdoc service\n       * @name setError\n       * @methodOf ui.grid.validate.service:uiGridValidateService\n       * @description Adds the proper error to the entity errors field\n       * @param {object} rowEntity the row entity of the cell\n       * @param {object} colDef the colDef of the cell\n       * @param {string} validatorName the name of the validator that is failing\n       */\n      setError: function(rowEntity, colDef, validatorName) {\n        if (!rowEntity['$$errors'+colDef.name]) {\n          rowEntity['$$errors'+colDef.name] = {};\n        }\n        rowEntity['$$errors'+colDef.name][validatorName] = true;\n      },\n\n      /**\n       * @ngdoc service\n       * @name clearError\n       * @methodOf ui.grid.validate.service:uiGridValidateService\n       * @description Removes the proper error from the entity errors field\n       * @param {object} rowEntity the row entity of the cell\n       * @param {object} colDef the colDef of the cell\n       * @param {string} validatorName the name of the validator that is failing\n       */\n      clearError: function(rowEntity, colDef, validatorName) {\n        if (!rowEntity['$$errors'+colDef.name]) {\n          return;\n        }\n        if (validatorName in rowEntity['$$errors'+colDef.name]) {\n            delete rowEntity['$$errors'+colDef.name][validatorName];\n        }\n      },\n      \n      /**\n       * @ngdoc function\n       * @name getErrorMessages\n       * @methodOf ui.grid.validate.service:uiGridValidateService\n       * @description returns an array of i18n-ed error messages.\n       * @param {object} rowEntity gridOptions.data[] array instance whose errors we are looking for\n       * @param {object} colDef the column whose errors we are looking for\n       * @returns {array} An array of strings containing all the error messages for the cell\n       */\n      getErrorMessages: function(rowEntity, colDef) {\n        var errors = [];\n\n        if (!rowEntity['$$errors'+colDef.name] || Object.keys(rowEntity['$$errors'+colDef.name]).length === 0) {\n          return errors;\n        }\n\n        Object.keys(rowEntity['$$errors'+colDef.name]).sort().forEach(function(validatorName) {\n          errors.push(service.getMessage(validatorName, colDef.validators[validatorName]));\n        });\n        \n        return errors;\n      },\n      \n      /**\n       * @ngdoc function\n       * @name getFormattedErrors\n       * @methodOf  ui.grid.validate.service:uiGridValidateService\n       * @description returns the error i18n-ed and formatted in html to be shown inside the page.\n       * @param {object} rowEntity gridOptions.data[] array instance whose errors we are looking for\n       * @param {object} colDef the column whose errors we are looking for\n       * @returns {object} An object that can be used in a template (like a cellTemplate) to display the\n       * message inside the page (i.e. inside a div)\n       */\n      getFormattedErrors: function(rowEntity, colDef) {\n\n        var msgString = \"\";\n\n        var errors = service.getErrorMessages(rowEntity, colDef);\n        \n        if (!errors.length) {\n          return;\n        }\n        \n        errors.forEach(function(errorMsg) {\n          msgString += errorMsg + \"<br/>\";\n        });\n\n        return $sce.trustAsHtml('<p><b>' + i18nService.getSafeText('validate.error') + '</b></p>' + msgString );\n      },\n\n      /**\n       * @ngdoc function\n       * @name getTitleFormattedErrors\n       * @methodOf ui.grid.validate.service:uiGridValidateService\n       * @description returns the error i18n-ed and formatted in javaScript to be shown inside an html \n       * title attribute.\n       * @param {object} rowEntity gridOptions.data[] array instance whose errors we are looking for\n       * @param {object} colDef the column whose errors we are looking for\n       * @returns {object} An object that can be used in a template (like a cellTemplate) to display the\n       * message inside an html title attribute\n       */\n      getTitleFormattedErrors: function(rowEntity, colDef) {\n\n        var newLine = \"\\n\";\n\n        var msgString = \"\";\n        \n        var errors = service.getErrorMessages(rowEntity, colDef);\n        \n        if (!errors.length) {\n          return;\n        }\n        \n        errors.forEach(function(errorMsg) {\n          msgString += errorMsg + newLine;\n        });\n\n        return $sce.trustAsHtml(i18nService.getSafeText('validate.error') + newLine + msgString);\n      },\n\n      /**\n       * @ngdoc function\n       * @name getTitleFormattedErrors\n       * @methodOf ui.grid.validate.service:uiGridValidateService\n       * @description Executes all validators on a cell (identified by row entity and column definition) and sets or clears errors\n       * @param {object} rowEntity the row entity of the cell we want to run the validators on\n       * @param {object} colDef the column definition of the cell we want to run the validators on\n       * @param {object} newValue the value the user just entered\n       * @param {object} oldValue the value the field had before\n       */\n      runValidators: function(rowEntity, colDef, newValue, oldValue, grid) {\n        \n        if (newValue === oldValue) {\n          // If the value has not changed we perform no validation\n          return;\n        }\n        \n        if (typeof(colDef.name) === 'undefined' || !colDef.name) {\n          throw new Error('colDef.name is required to perform validation');\n        }\n        \n        service.setValid(rowEntity, colDef);\n        \n        var validateClosureFactory = function(rowEntity, colDef, validatorName) {\n          return function(value) {\n            if (!value) {\n              service.setInvalid(rowEntity, colDef);\n              service.setError(rowEntity, colDef, validatorName);\n              if (grid) {\n                grid.api.validate.raise.validationFailed(rowEntity, colDef, newValue, oldValue);\n              }\n            }\n          };\n        };\n\n        var promises = [];\n\n        for (var validatorName in colDef.validators) {\n          service.clearError(rowEntity, colDef, validatorName);\n          var msg;\n          var validatorFunction = service.getValidator(validatorName, colDef.validators[validatorName]);\n          // We pass the arguments as oldValue, newValue so they are in the same order \n          // as ng-model validators (modelValue, viewValue)\n          var promise = $q\n                        .when(validatorFunction(oldValue, newValue, rowEntity, colDef))\n                        .then(validateClosureFactory(rowEntity, colDef, validatorName));\n          promises.push(promise);\n        }\n        \n        return $q.all(promises);\n      },\n\n      /**\n       * @ngdoc function\n       * @name createDefaultValidators\n       * @methodOf ui.grid.validate.service:uiGridValidateService\n       * @description adds the basic validators to the list of service validators\n       */\n      createDefaultValidators: function() {\n        service.setValidator('minLength',\n                             function (argument) {\n                               return function (oldValue, newValue, rowEntity, colDef) {\n                                 if (newValue === undefined || newValue === null || newValue === '') {\n                                   return true;\n                                 }\n                                 return newValue.length >= argument;\n                               };\n                             },\n                               function(argument) {\n                                 return i18nService.getSafeText('validate.minLength').replace('THRESHOLD', argument);\n                               });\n        \n        service.setValidator('maxLength',\n                             function (argument) {\n                               return function (oldValue, newValue, rowEntity, colDef) {\n                                 if (newValue === undefined || newValue === null || newValue === '') {\n                                   return true;\n                                 }\n                                 return newValue.length <= argument;\n                               };\n                             },\n                             function(threshold) {\n                               return i18nService.getSafeText('validate.maxLength').replace('THRESHOLD', threshold);\n                             });\n        \n        service.setValidator('required',\n                             function (argument) {\n                               return function (oldValue, newValue, rowEntity, colDef) {\n                                 if (argument) {\n                                   return !(newValue === undefined || newValue === null || newValue === '');\n                                 }\n                                 return true;\n                               };\n                             },\n                             function(argument) {\n                               return i18nService.getSafeText('validate.required');\n                             });\n      },\n\n      initializeGrid: function (scope, grid) {\n        grid.validate = {\n        \n          isInvalid: service.isInvalid,\n\n          getFormattedErrors: service.getFormattedErrors,\n         \n          getTitleFormattedErrors: service.getTitleFormattedErrors,\n\n          runValidators: service.runValidators\n        };\n        \n        /**\n         *  @ngdoc object\n         *  @name ui.grid.validate.api:PublicApi\n         *\n         *  @description Public Api for validation feature\n         */\n        var publicApi = {\n          events: {\n            validate: {\n              /**\n               * @ngdoc event\n               * @name validationFailed\n               * @eventOf  ui.grid.validate.api:PublicApi\n               * @description raised when one or more failure happened during validation \n               * <pre>\n               *      gridApi.validate.on.validationFailed(scope, function(rowEntity, colDef, newValue, oldValue){...})\n               * </pre>\n               * @param {object} rowEntity the options.data element whose validation failed\n               * @param {object} colDef the column whose validation failed\n               * @param {object} newValue new value\n               * @param {object} oldValue old value\n               */\n              validationFailed: function (rowEntity, colDef, newValue, oldValue) {\n              }\n            }\n          },\n          methods: {\n            validate: {\n              /**\n               * @ngdoc function\n               * @name isInvalid\n               * @methodOf  ui.grid.validate.api:PublicApi\n               * @description checks if a cell (identified by rowEntity, colDef) is invalid\n               * @param {object} rowEntity gridOptions.data[] array instance we want to check\n               * @param {object} colDef the column whose errors we want to check\n               * @returns {boolean} true if the cell value is not valid\n               */\n              isInvalid: function(rowEntity, colDef) {\n                return grid.validate.isInvalid(rowEntity, colDef);\n              },\n              /**\n               * @ngdoc function\n               * @name getErrorMessages\n               * @methodOf  ui.grid.validate.api:PublicApi\n               * @description returns an array of i18n-ed error messages.\n               * @param {object} rowEntity gridOptions.data[] array instance whose errors we are looking for\n               * @param {object} colDef the column whose errors we are looking for\n               * @returns {array} An array of strings containing all the error messages for the cell\n               */\n              getErrorMessages: function (rowEntity, colDef) {\n                return grid.validate.getErrorMessages(rowEntity, colDef);\n              },\n              /**\n               * @ngdoc function\n               * @name getFormattedErrors\n               * @methodOf  ui.grid.validate.api:PublicApi\n               * @description returns the error i18n-ed and formatted in html to be shown inside the page.\n               * @param {object} rowEntity gridOptions.data[] array instance whose errors we are looking for\n               * @param {object} colDef the column whose errors we are looking for\n               * @returns {object} An object that can be used in a template (like a cellTemplate) to display the\n               * message inside the page (i.e. inside a div)\n               */\n              getFormattedErrors: function (rowEntity, colDef) {\n                return grid.validate.getFormattedErrors(rowEntity, colDef);\n              },\n              /**\n               * @ngdoc function\n               * @name getTitleFormattedErrors\n               * @methodOf  ui.grid.validate.api:PublicApi\n               * @description returns the error i18n-ed and formatted in javaScript to be shown inside an html \n               * title attribute.\n               * @param {object} rowEntity gridOptions.data[] array instance whose errors we are looking for\n               * @param {object} colDef the column whose errors we are looking for\n               * @returns {object} An object that can be used in a template (like a cellTemplate) to display the\n               * message inside an html title attribute\n               */\n              getTitleFormattedErrors: function (rowEntity, colDef) {\n                return grid.validate.getTitleFormattedErrors(rowEntity, colDef);\n              }\n            } \n          }\n        };\n        \n        grid.api.registerEventsFromObject(publicApi.events);\n        grid.api.registerMethodsFromObject(publicApi.methods);\n\n        if (grid.edit) {\n          grid.api.edit.on.afterCellEdit(scope, function(rowEntity, colDef, newValue, oldValue) {\n            grid.validate.runValidators(rowEntity, colDef, newValue, oldValue, grid);\n          });\n        }\n\n        service.createDefaultValidators();\n      }\n      \n    };\n  \n    return service;\n  }]);\n  \n  \n  /**\n   *  @ngdoc directive\n   *  @name ui.grid.validate.directive:uiGridValidate\n   *  @element div\n   *  @restrict A\n   *  @description Adds validating features to the ui-grid directive.\n   *  @example\n   <example module=\"app\">\n   <file name=\"app.js\">\n   var app = angular.module('app', ['ui.grid', 'ui.grid.edit', 'ui.grid.validate']);\n\n   app.controller('MainCtrl', ['$scope', function ($scope) {\n      $scope.data = [\n        { name: 'Bob', title: 'CEO' },\n            { name: 'Frank', title: 'Lowly Developer' }\n      ];\n\n      $scope.columnDefs = [\n        {name: 'name', enableCellEdit: true, validators: {minLength: 3, maxLength: 9}, cellTemplate: 'ui-grid/cellTitleValidator'},\n        {name: 'title', enableCellEdit: true, validators: {required: true}, cellTemplate: 'ui-grid/cellTitleValidator'}\n      ];\n    }]);\n   </file>\n   <file name=\"index.html\">\n   <div ng-controller=\"MainCtrl\">\n   <div ui-grid=\"{ data: data, columnDefs: columnDefs }\" ui-grid-edit ui-grid-validate></div>\n   </div>\n   </file>\n   </example>\n   */\n\n  module.directive('uiGridValidate', ['gridUtil', 'uiGridValidateService', function (gridUtil, uiGridValidateService) {\n    return {\n      priority: 0,\n      replace: true,\n      require: '^uiGrid',\n      scope: false,\n      compile: function () {\n        return {\n          pre: function ($scope, $elm, $attrs, uiGridCtrl) {\n            uiGridValidateService.initializeGrid($scope, uiGridCtrl.grid);\n          },\n          post: function ($scope, $elm, $attrs, uiGridCtrl) {\n          }\n        };\n      }\n    };\n  }]);\n})();\n\nangular.module('ui.grid').run(['$templateCache', function($templateCache) {\n  'use strict';\n\n  $templateCache.put('ui-grid/ui-grid-filter',\n    \"<div class=\\\"ui-grid-filter-container\\\" ng-repeat=\\\"colFilter in col.filters\\\" ng-class=\\\"{'ui-grid-filter-cancel-button-hidden' : colFilter.disableCancelFilterButton === true }\\\"><div ng-if=\\\"colFilter.type !== 'select'\\\"><input type=\\\"text\\\" class=\\\"ui-grid-filter-input ui-grid-filter-input-{{$index}}\\\" ng-model=\\\"colFilter.term\\\" ng-attr-placeholder=\\\"{{colFilter.placeholder || ''}}\\\" aria-label=\\\"{{colFilter.ariaLabel || aria.defaultFilterLabel}}\\\"><div role=\\\"button\\\" class=\\\"ui-grid-filter-button\\\" ng-click=\\\"removeFilter(colFilter, $index)\\\" ng-if=\\\"!colFilter.disableCancelFilterButton\\\" ng-disabled=\\\"colFilter.term === undefined || colFilter.term === null || colFilter.term === ''\\\" ng-show=\\\"colFilter.term !== undefined && colFilter.term !== null && colFilter.term !== ''\\\"><i class=\\\"ui-grid-icon-cancel\\\" ui-grid-one-bind-aria-label=\\\"aria.removeFilter\\\">&nbsp;</i></div></div><div ng-if=\\\"colFilter.type === 'select'\\\"><select class=\\\"ui-grid-filter-select ui-grid-filter-input-{{$index}}\\\" ng-model=\\\"colFilter.term\\\" ng-attr-placeholder=\\\"{{colFilter.placeholder || aria.defaultFilterLabel}}\\\" aria-label=\\\"{{colFilter.ariaLabel || ''}}\\\" ng-options=\\\"option.value as option.label for option in colFilter.selectOptions\\\"><option value=\\\"\\\"></option></select><div role=\\\"button\\\" class=\\\"ui-grid-filter-button-select\\\" ng-click=\\\"removeFilter(colFilter, $index)\\\" ng-if=\\\"!colFilter.disableCancelFilterButton\\\" ng-disabled=\\\"colFilter.term === undefined || colFilter.term === null || colFilter.term === ''\\\" ng-show=\\\"colFilter.term !== undefined && colFilter.term != null\\\"><i class=\\\"ui-grid-icon-cancel\\\" ui-grid-one-bind-aria-label=\\\"aria.removeFilter\\\">&nbsp;</i></div></div></div>\"\n  );\n\n\n  $templateCache.put('ui-grid/ui-grid-footer',\n    \"<div class=\\\"ui-grid-footer-panel ui-grid-footer-aggregates-row\\\"><!-- tfooter --><div class=\\\"ui-grid-footer ui-grid-footer-viewport\\\"><div class=\\\"ui-grid-footer-canvas\\\"><div class=\\\"ui-grid-footer-cell-wrapper\\\" ng-style=\\\"colContainer.headerCellWrapperStyle()\\\"><div role=\\\"row\\\" class=\\\"ui-grid-footer-cell-row\\\"><div ui-grid-footer-cell role=\\\"gridcell\\\" ng-repeat=\\\"col in colContainer.renderedColumns track by col.uid\\\" col=\\\"col\\\" render-index=\\\"$index\\\" class=\\\"ui-grid-footer-cell ui-grid-clearfix\\\"></div></div></div></div></div></div>\"\n  );\n\n\n  $templateCache.put('ui-grid/ui-grid-grid-footer',\n    \"<div class=\\\"ui-grid-footer-info ui-grid-grid-footer\\\"><span>{{'search.totalItems' | t}} {{grid.rows.length}}</span> <span ng-if=\\\"grid.renderContainers.body.visibleRowCache.length !== grid.rows.length\\\" class=\\\"ngLabel\\\">({{\\\"search.showingItems\\\" | t}} {{grid.renderContainers.body.visibleRowCache.length}})</span></div>\"\n  );\n\n\n  $templateCache.put('ui-grid/ui-grid-group-panel',\n    \"<div class=\\\"ui-grid-group-panel\\\"><div ui-t=\\\"groupPanel.description\\\" class=\\\"description\\\" ng-show=\\\"groupings.length == 0\\\"></div><ul ng-show=\\\"groupings.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>\"\n  );\n\n\n  $templateCache.put('ui-grid/ui-grid-header',\n    \"<div role=\\\"rowgroup\\\" class=\\\"ui-grid-header\\\"><!-- theader --><div class=\\\"ui-grid-top-panel\\\"><div class=\\\"ui-grid-header-viewport\\\"><div class=\\\"ui-grid-header-canvas\\\"><div class=\\\"ui-grid-header-cell-wrapper\\\" ng-style=\\\"colContainer.headerCellWrapperStyle()\\\"><div role=\\\"row\\\" class=\\\"ui-grid-header-cell-row\\\"><div class=\\\"ui-grid-header-cell ui-grid-clearfix\\\" ng-repeat=\\\"col in colContainer.renderedColumns track by col.uid\\\" ui-grid-header-cell col=\\\"col\\\" render-index=\\\"$index\\\"></div></div></div></div></div></div></div>\"\n  );\n\n\n  $templateCache.put('ui-grid/ui-grid-menu-button',\n    \"<div class=\\\"ui-grid-menu-button\\\"><div role=\\\"button\\\" ui-grid-one-bind-id-grid=\\\"'grid-menu'\\\" class=\\\"ui-grid-icon-container\\\" ng-click=\\\"toggleMenu()\\\" aria-haspopup=\\\"true\\\"><i class=\\\"ui-grid-icon-menu\\\" ui-grid-one-bind-aria-label=\\\"i18n.aria.buttonLabel\\\">&nbsp;</i></div><div ui-grid-menu menu-items=\\\"menuItems\\\"></div></div>\"\n  );\n\n\n  $templateCache.put('ui-grid/ui-grid-no-header',\n    \"<div class=\\\"ui-grid-top-panel\\\"></div>\"\n  );\n\n\n  $templateCache.put('ui-grid/ui-grid-row',\n    \"<div ng-repeat=\\\"(colRenderIndex, col) in colContainer.renderedColumns track by col.uid\\\" ui-grid-one-bind-id-grid=\\\"rowRenderIndex + '-' + col.uid + '-cell'\\\" class=\\\"ui-grid-cell\\\" ng-class=\\\"{ 'ui-grid-row-header-cell': col.isRowHeader }\\\" role=\\\"{{col.isRowHeader ? 'rowheader' : 'gridcell'}}\\\" ui-grid-cell></div>\"\n  );\n\n\n  $templateCache.put('ui-grid/ui-grid',\n    \"<div ui-i18n=\\\"en\\\" class=\\\"ui-grid\\\"><!-- TODO (c0bra): add \\\"scoped\\\" attr here, eventually? --><style ui-grid-style>.grid{{ grid.id }} {\\n\" +\n    \"      /* Styles for the grid */\\n\" +\n    \"    }\\n\" +\n    \"\\n\" +\n    \"    .grid{{ grid.id }} .ui-grid-row, .grid{{ grid.id }} .ui-grid-cell, .grid{{ grid.id }} .ui-grid-cell .ui-grid-vertical-bar {\\n\" +\n    \"      height: {{ grid.options.rowHeight }}px;\\n\" +\n    \"    }\\n\" +\n    \"\\n\" +\n    \"    .grid{{ grid.id }} .ui-grid-row:last-child .ui-grid-cell {\\n\" +\n    \"      border-bottom-width: {{ ((grid.getTotalRowHeight() < grid.getViewportHeight()) && '1') || '0' }}px;\\n\" +\n    \"    }\\n\" +\n    \"\\n\" +\n    \"    {{ grid.verticalScrollbarStyles }}\\n\" +\n    \"    {{ grid.horizontalScrollbarStyles }}\\n\" +\n    \"\\n\" +\n    \"    /*\\n\" +\n    \"    .ui-grid[dir=rtl] .ui-grid-viewport {\\n\" +\n    \"      padding-left: {{ grid.verticalScrollbarWidth }}px;\\n\" +\n    \"    }\\n\" +\n    \"    */\\n\" +\n    \"\\n\" +\n    \"    {{ grid.customStyles }}</style><div class=\\\"ui-grid-contents-wrapper\\\"><div ui-grid-menu-button ng-if=\\\"grid.options.enableGridMenu\\\"></div><div ng-if=\\\"grid.hasLeftContainer()\\\" style=\\\"width: 0\\\" ui-grid-pinned-container=\\\"'left'\\\"></div><div ui-grid-render-container container-id=\\\"'body'\\\" col-container-name=\\\"'body'\\\" row-container-name=\\\"'body'\\\" bind-scroll-horizontal=\\\"true\\\" bind-scroll-vertical=\\\"true\\\" enable-horizontal-scrollbar=\\\"grid.options.enableHorizontalScrollbar\\\" enable-vertical-scrollbar=\\\"grid.options.enableVerticalScrollbar\\\"></div><div ng-if=\\\"grid.hasRightContainer()\\\" style=\\\"width: 0\\\" ui-grid-pinned-container=\\\"'right'\\\"></div><div ui-grid-grid-footer ng-if=\\\"grid.options.showGridFooter\\\"></div><div ui-grid-column-menu ng-if=\\\"grid.options.enableColumnMenus\\\"></div><div ng-transclude></div></div></div>\"\n  );\n\n\n  $templateCache.put('ui-grid/uiGridCell',\n    \"<div class=\\\"ui-grid-cell-contents\\\" title=\\\"TOOLTIP\\\">{{COL_FIELD CUSTOM_FILTERS}}</div>\"\n  );\n\n\n  $templateCache.put('ui-grid/uiGridColumnMenu',\n    \"<div class=\\\"ui-grid-column-menu\\\"><div ui-grid-menu menu-items=\\\"menuItems\\\"><!-- <div class=\\\"ui-grid-column-menu\\\">\\n\" +\n    \"    <div class=\\\"inner\\\" ng-show=\\\"menuShown\\\">\\n\" +\n    \"      <ul>\\n\" +\n    \"        <div ng-show=\\\"grid.options.enableSorting\\\">\\n\" +\n    \"          <li ng-click=\\\"sortColumn($event, asc)\\\" ng-class=\\\"{ 'selected' : col.sort.direction == asc }\\\"><i class=\\\"ui-grid-icon-sort-alt-up\\\"></i> Sort Ascending</li>\\n\" +\n    \"          <li ng-click=\\\"sortColumn($event, desc)\\\" ng-class=\\\"{ 'selected' : col.sort.direction == desc }\\\"><i class=\\\"ui-grid-icon-sort-alt-down\\\"></i> Sort Descending</li>\\n\" +\n    \"          <li ng-show=\\\"col.sort.direction\\\" ng-click=\\\"unsortColumn()\\\"><i class=\\\"ui-grid-icon-cancel\\\"></i> Remove Sort</li>\\n\" +\n    \"        </div>\\n\" +\n    \"      </ul>\\n\" +\n    \"    </div>\\n\" +\n    \"  </div> --></div></div>\"\n  );\n\n\n  $templateCache.put('ui-grid/uiGridFooterCell',\n    \"<div class=\\\"ui-grid-cell-contents\\\" col-index=\\\"renderIndex\\\"><div>{{ col.getAggregationText() + ( col.getAggregationValue() CUSTOM_FILTERS ) }}</div></div>\"\n  );\n\n\n  $templateCache.put('ui-grid/uiGridHeaderCell',\n    \"<div role=\\\"columnheader\\\" ng-class=\\\"{ 'sortable': sortable }\\\" ui-grid-one-bind-aria-labelledby-grid=\\\"col.uid + '-header-text ' + col.uid + '-sortdir-text'\\\" aria-sort=\\\"{{col.sort.direction == asc ? 'ascending' : ( col.sort.direction == desc ? 'descending' : (!col.sort.direction ? 'none' : 'other'))}}\\\"><div role=\\\"button\\\" tabindex=\\\"0\\\" class=\\\"ui-grid-cell-contents ui-grid-header-cell-primary-focus\\\" col-index=\\\"renderIndex\\\" title=\\\"TOOLTIP\\\"><span class=\\\"ui-grid-header-cell-label\\\" ui-grid-one-bind-id-grid=\\\"col.uid + '-header-text'\\\">{{ col.displayName CUSTOM_FILTERS }}</span> <span ui-grid-one-bind-id-grid=\\\"col.uid + '-sortdir-text'\\\" ui-grid-visible=\\\"col.sort.direction\\\" aria-label=\\\"{{getSortDirectionAriaLabel()}}\\\"><i ng-class=\\\"{ 'ui-grid-icon-up-dir': col.sort.direction == asc, 'ui-grid-icon-down-dir': col.sort.direction == desc, 'ui-grid-icon-blank': !col.sort.direction }\\\" title=\\\"{{isSortPriorityVisible() ? i18n.headerCell.priority + ' ' + ( col.sort.priority + 1 )  : null}}\\\" aria-hidden=\\\"true\\\"></i> <sub ui-grid-visible=\\\"isSortPriorityVisible()\\\" class=\\\"ui-grid-sort-priority-number\\\">{{col.sort.priority + 1}}</sub></span></div><div role=\\\"button\\\" tabindex=\\\"0\\\" ui-grid-one-bind-id-grid=\\\"col.uid + '-menu-button'\\\" class=\\\"ui-grid-column-menu-button\\\" ng-if=\\\"grid.options.enableColumnMenus && !col.isRowHeader  && col.colDef.enableColumnMenu !== false\\\" ng-click=\\\"toggleMenu($event)\\\" ng-class=\\\"{'ui-grid-column-menu-button-last-col': isLastCol}\\\" ui-grid-one-bind-aria-label=\\\"i18n.headerCell.aria.columnMenuButtonLabel\\\" aria-haspopup=\\\"true\\\"><i class=\\\"ui-grid-icon-angle-down\\\" aria-hidden=\\\"true\\\">&nbsp;</i></div><div ui-grid-filter></div></div>\"\n  );\n\n\n  $templateCache.put('ui-grid/uiGridMenu',\n    \"<div class=\\\"ui-grid-menu\\\" ng-if=\\\"shown\\\"><style ui-grid-style>{{dynamicStyles}}</style><div class=\\\"ui-grid-menu-mid\\\" ng-show=\\\"shownMid\\\"><div class=\\\"ui-grid-menu-inner\\\"><ul role=\\\"menu\\\" class=\\\"ui-grid-menu-items\\\"><li ng-repeat=\\\"item in menuItems\\\" role=\\\"menuitem\\\" ui-grid-menu-item ui-grid-one-bind-id=\\\"'menuitem-'+$index\\\" action=\\\"item.action\\\" name=\\\"item.title\\\" active=\\\"item.active\\\" icon=\\\"item.icon\\\" shown=\\\"item.shown\\\" context=\\\"item.context\\\" template-url=\\\"item.templateUrl\\\" leave-open=\\\"item.leaveOpen\\\" screen-reader-only=\\\"item.screenReaderOnly\\\"></li></ul></div></div></div>\"\n  );\n\n\n  $templateCache.put('ui-grid/uiGridMenuItem',\n    \"<button type=\\\"button\\\" class=\\\"ui-grid-menu-item\\\" ng-click=\\\"itemAction($event, title)\\\" ng-show=\\\"itemShown()\\\" ng-class=\\\"{ 'ui-grid-menu-item-active': active(), 'ui-grid-sr-only': (!focus && screenReaderOnly) }\\\" aria-pressed=\\\"{{active()}}\\\" tabindex=\\\"0\\\" ng-focus=\\\"focus=true\\\" ng-blur=\\\"focus=false\\\"><i ng-class=\\\"icon\\\" aria-hidden=\\\"true\\\">&nbsp;</i> {{ name }}</button>\"\n  );\n\n\n  $templateCache.put('ui-grid/uiGridRenderContainer',\n    \"<div role=\\\"grid\\\" ui-grid-one-bind-id-grid=\\\"'grid-container'\\\" class=\\\"ui-grid-render-container\\\" ng-style=\\\"{ 'margin-left': colContainer.getMargin('left') + 'px', 'margin-right': colContainer.getMargin('right') + 'px' }\\\"><!-- All of these dom elements are replaced in place --><div ui-grid-header></div><div ui-grid-viewport></div><div ng-if=\\\"colContainer.needsHScrollbarPlaceholder()\\\" class=\\\"ui-grid-scrollbar-placeholder\\\" ng-style=\\\"{height:colContainer.grid.scrollbarHeight + 'px'}\\\"></div><ui-grid-footer ng-if=\\\"grid.options.showColumnFooter\\\"></ui-grid-footer></div>\"\n  );\n\n\n  $templateCache.put('ui-grid/uiGridViewport',\n    \"<div role=\\\"rowgroup\\\" class=\\\"ui-grid-viewport\\\" ng-style=\\\"colContainer.getViewportStyle()\\\"><!-- tbody --><div class=\\\"ui-grid-canvas\\\"><div ng-repeat=\\\"(rowRenderIndex, row) in rowContainer.renderedRows track by $index\\\" class=\\\"ui-grid-row\\\" ng-style=\\\"Viewport.rowStyle(rowRenderIndex)\\\"><div role=\\\"row\\\" ui-grid-row=\\\"row\\\" row-render-index=\\\"rowRenderIndex\\\"></div></div></div></div>\"\n  );\n\n\n  $templateCache.put('ui-grid/cellEditor',\n    \"<div><form name=\\\"inputForm\\\"><input type=\\\"INPUT_TYPE\\\" ng-class=\\\"'colt' + col.uid\\\" ui-grid-editor ng-model=\\\"MODEL_COL_FIELD\\\"></form></div>\"\n  );\n\n\n  $templateCache.put('ui-grid/dropdownEditor',\n    \"<div><form name=\\\"inputForm\\\"><select ng-class=\\\"'colt' + col.uid\\\" ui-grid-edit-dropdown ng-model=\\\"MODEL_COL_FIELD\\\" ng-options=\\\"field[editDropdownIdLabel] as field[editDropdownValueLabel] CUSTOM_FILTERS for field in editDropdownOptionsArray\\\"></select></form></div>\"\n  );\n\n\n  $templateCache.put('ui-grid/fileChooserEditor',\n    \"<div><form name=\\\"inputForm\\\"><input ng-class=\\\"'colt' + col.uid\\\" ui-grid-edit-file-chooser type=\\\"file\\\" id=\\\"files\\\" name=\\\"files[]\\\" ng-model=\\\"MODEL_COL_FIELD\\\"></form></div>\"\n  );\n\n\n  $templateCache.put('ui-grid/expandableRow',\n    \"<div ui-grid-expandable-row ng-if=\\\"expandableRow.shouldRenderExpand()\\\" class=\\\"expandableRow\\\" style=\\\"float:left; margin-top: 1px; margin-bottom: 1px\\\" ng-style=\\\"{width: (grid.renderContainers.body.getCanvasWidth()) + 'px', height: row.expandedRowHeight + 'px'}\\\"></div>\"\n  );\n\n\n  $templateCache.put('ui-grid/expandableRowHeader',\n    \"<div class=\\\"ui-grid-row-header-cell ui-grid-expandable-buttons-cell\\\"><div class=\\\"ui-grid-cell-contents\\\"><i ng-if=\\\"!row.groupHeader==true\\\" ng-class=\\\"{ 'ui-grid-icon-plus-squared' : !row.isExpanded, 'ui-grid-icon-minus-squared' : row.isExpanded }\\\" ng-click=\\\"grid.api.expandable.toggleRowExpansion(row.entity)\\\"></i></div></div>\"\n  );\n\n\n  $templateCache.put('ui-grid/expandableScrollFiller',\n    \"<div ng-if=\\\"expandableRow.shouldRenderFiller()\\\" ng-class=\\\"{scrollFiller:true, scrollFillerClass:(colContainer.name === 'body')}\\\" ng-style=\\\"{ width: (grid.getViewportWidth()) + 'px', height: row.expandedRowHeight + 2 + 'px', 'margin-left': grid.options.rowHeader.rowHeaderWidth + 'px' }\\\"><i class=\\\"ui-grid-icon-spin5 ui-grid-animate-spin\\\" ng-style=\\\"{'margin-top': ( row.expandedRowHeight/2 - 5) + 'px', 'margin-left' : ((grid.getViewportWidth() - grid.options.rowHeader.rowHeaderWidth)/2 - 5) + 'px'}\\\"></i></div>\"\n  );\n\n\n  $templateCache.put('ui-grid/expandableTopRowHeader',\n    \"<div class=\\\"ui-grid-row-header-cell ui-grid-expandable-buttons-cell\\\"><div class=\\\"ui-grid-cell-contents\\\"><i ng-class=\\\"{ 'ui-grid-icon-plus-squared' : !grid.expandable.expandedAll, 'ui-grid-icon-minus-squared' : grid.expandable.expandedAll }\\\" ng-click=\\\"grid.api.expandable.toggleAllRows()\\\"></i></div></div>\"\n  );\n\n\n  $templateCache.put('ui-grid/csvLink',\n    \"<span class=\\\"ui-grid-exporter-csv-link-span\\\"><a href=\\\"data:text/csv;charset=UTF-8,CSV_CONTENT\\\" download=\\\"FILE_NAME\\\">LINK_LABEL</a></span>\"\n  );\n\n\n  $templateCache.put('ui-grid/importerMenuItem',\n    \"<li class=\\\"ui-grid-menu-item\\\"><form><input class=\\\"ui-grid-importer-file-chooser\\\" type=\\\"file\\\" id=\\\"files\\\" name=\\\"files[]\\\"></form></li>\"\n  );\n\n\n  $templateCache.put('ui-grid/importerMenuItemContainer',\n    \"<div ui-grid-importer-menu-item></div>\"\n  );\n\n\n  $templateCache.put('ui-grid/pagination',\n    \"<div role=\\\"contentinfo\\\" class=\\\"ui-grid-pager-panel\\\" ui-grid-pager ng-show=\\\"grid.options.enablePaginationControls\\\"><div role=\\\"navigation\\\" class=\\\"ui-grid-pager-container\\\"><div role=\\\"menubar\\\" class=\\\"ui-grid-pager-control\\\"><button type=\\\"button\\\" role=\\\"menuitem\\\" class=\\\"ui-grid-pager-first\\\" ui-grid-one-bind-title=\\\"aria.pageToFirst\\\" ui-grid-one-bind-aria-label=\\\"aria.pageToFirst\\\" ng-click=\\\"pageFirstPageClick()\\\" ng-disabled=\\\"cantPageBackward()\\\"><div ng-class=\\\"grid.isRTL() ? 'last-triangle' : 'first-triangle'\\\"><div ng-class=\\\"grid.isRTL() ? 'last-bar-rtl' : 'first-bar'\\\"></div></div></button> <button type=\\\"button\\\" role=\\\"menuitem\\\" class=\\\"ui-grid-pager-previous\\\" ui-grid-one-bind-title=\\\"aria.pageBack\\\" ui-grid-one-bind-aria-label=\\\"aria.pageBack\\\" ng-click=\\\"pagePreviousPageClick()\\\" ng-disabled=\\\"cantPageBackward()\\\"><div ng-class=\\\"grid.isRTL() ? 'last-triangle prev-triangle' : 'first-triangle prev-triangle'\\\"></div></button> <input type=\\\"number\\\" ui-grid-one-bind-title=\\\"aria.pageSelected\\\" ui-grid-one-bind-aria-label=\\\"aria.pageSelected\\\" class=\\\"ui-grid-pager-control-input\\\" ng-model=\\\"grid.options.paginationCurrentPage\\\" min=\\\"1\\\" max=\\\"{{ paginationApi.getTotalPages() }}\\\" required> <span class=\\\"ui-grid-pager-max-pages-number\\\" ng-show=\\\"paginationApi.getTotalPages() > 0\\\"><abbr ui-grid-one-bind-title=\\\"paginationOf\\\">/</abbr> {{ paginationApi.getTotalPages() }}</span> <button type=\\\"button\\\" role=\\\"menuitem\\\" class=\\\"ui-grid-pager-next\\\" ui-grid-one-bind-title=\\\"aria.pageForward\\\" ui-grid-one-bind-aria-label=\\\"aria.pageForward\\\" ng-click=\\\"pageNextPageClick()\\\" ng-disabled=\\\"cantPageForward()\\\"><div ng-class=\\\"grid.isRTL() ? 'first-triangle next-triangle' : 'last-triangle next-triangle'\\\"></div></button> <button type=\\\"button\\\" role=\\\"menuitem\\\" class=\\\"ui-grid-pager-last\\\" ui-grid-one-bind-title=\\\"aria.pageToLast\\\" ui-grid-one-bind-aria-label=\\\"aria.pageToLast\\\" ng-click=\\\"pageLastPageClick()\\\" ng-disabled=\\\"cantPageToLast()\\\"><div ng-class=\\\"grid.isRTL() ? 'first-triangle' : 'last-triangle'\\\"><div ng-class=\\\"grid.isRTL() ? 'first-bar-rtl' : 'last-bar'\\\"></div></div></button></div><div class=\\\"ui-grid-pager-row-count-picker\\\" ng-if=\\\"grid.options.paginationPageSizes.length > 1\\\"><select ui-grid-one-bind-aria-labelledby-grid=\\\"'items-per-page-label'\\\" ng-model=\\\"grid.options.paginationPageSize\\\" ng-options=\\\"o as o for o in grid.options.paginationPageSizes\\\"></select><span ui-grid-one-bind-id-grid=\\\"'items-per-page-label'\\\" class=\\\"ui-grid-pager-row-count-label\\\">&nbsp;{{sizesLabel}}</span></div><span ng-if=\\\"grid.options.paginationPageSizes.length <= 1\\\" class=\\\"ui-grid-pager-row-count-label\\\">{{grid.options.paginationPageSize}}&nbsp;{{sizesLabel}}</span></div><div class=\\\"ui-grid-pager-count-container\\\"><div class=\\\"ui-grid-pager-count\\\"><span ng-show=\\\"grid.options.totalItems > 0\\\">{{showingLow}} <abbr ui-grid-one-bind-title=\\\"paginationThrough\\\">-</abbr> {{showingHigh}} {{paginationOf}} {{grid.options.totalItems}} {{totalItemsLabel}}</span></div></div></div>\"\n  );\n\n\n  $templateCache.put('ui-grid/columnResizer',\n    \"<div ui-grid-column-resizer ng-if=\\\"grid.options.enableColumnResizing\\\" class=\\\"ui-grid-column-resizer\\\" col=\\\"col\\\" position=\\\"right\\\" render-index=\\\"renderIndex\\\" unselectable=\\\"on\\\"></div>\"\n  );\n\n\n  $templateCache.put('ui-grid/gridFooterSelectedItems',\n    \"<span ng-if=\\\"grid.selection.selectedCount !== 0 && grid.options.enableFooterTotalSelected\\\">({{\\\"search.selectedItems\\\" | t}} {{grid.selection.selectedCount}})</span>\"\n  );\n\n\n  $templateCache.put('ui-grid/selectionHeaderCell',\n    \"<div><!-- <div class=\\\"ui-grid-vertical-bar\\\">&nbsp;</div> --><div class=\\\"ui-grid-cell-contents\\\" col-index=\\\"renderIndex\\\"><ui-grid-selection-select-all-buttons ng-if=\\\"grid.options.enableSelectAll\\\"></ui-grid-selection-select-all-buttons></div></div>\"\n  );\n\n\n  $templateCache.put('ui-grid/selectionRowHeader',\n    \"<div class=\\\"ui-grid-disable-selection\\\"><div class=\\\"ui-grid-cell-contents\\\"><ui-grid-selection-row-header-buttons></ui-grid-selection-row-header-buttons></div></div>\"\n  );\n\n\n  $templateCache.put('ui-grid/selectionRowHeaderButtons',\n    \"<div class=\\\"ui-grid-selection-row-header-buttons ui-grid-icon-ok\\\" ng-class=\\\"{'ui-grid-row-selected': row.isSelected}\\\" ng-click=\\\"selectButtonClick(row, $event)\\\">&nbsp;</div>\"\n  );\n\n\n  $templateCache.put('ui-grid/selectionSelectAllButtons',\n    \"<div class=\\\"ui-grid-selection-row-header-buttons ui-grid-icon-ok\\\" ng-class=\\\"{'ui-grid-all-selected': grid.selection.selectAll}\\\" ng-click=\\\"headerButtonClick($event)\\\"></div>\"\n  );\n\n\n  $templateCache.put('ui-grid/treeBaseExpandAllButtons',\n    \"<div class=\\\"ui-grid-tree-base-row-header-buttons\\\" ng-class=\\\"{'ui-grid-icon-minus-squared': grid.treeBase.numberLevels > 0 && grid.treeBase.expandAll, 'ui-grid-icon-plus-squared': grid.treeBase.numberLevels > 0 && !grid.treeBase.expandAll}\\\" ng-click=\\\"headerButtonClick($event)\\\"></div>\"\n  );\n\n\n  $templateCache.put('ui-grid/treeBaseHeaderCell',\n    \"<div><div class=\\\"ui-grid-cell-contents\\\" col-index=\\\"renderIndex\\\"><ui-grid-tree-base-expand-all-buttons ng-if=\\\"grid.options.enableExpandAll\\\"></ui-grid-tree-base-expand-all-buttons></div></div>\"\n  );\n\n\n  $templateCache.put('ui-grid/treeBaseRowHeader',\n    \"<div class=\\\"ui-grid-cell-contents\\\"><ui-grid-tree-base-row-header-buttons></ui-grid-tree-base-row-header-buttons></div>\"\n  );\n\n\n  $templateCache.put('ui-grid/treeBaseRowHeaderButtons',\n    \"<div class=\\\"ui-grid-tree-base-row-header-buttons\\\" ng-class=\\\"{'ui-grid-tree-base-header': row.treeLevel > -1 }\\\" ng-click=\\\"treeButtonClick(row, $event)\\\"><i ng-class=\\\"{'ui-grid-icon-minus-squared': ( ( grid.options.showTreeExpandNoChildren && row.treeLevel > -1 ) || ( row.treeNode.children && row.treeNode.children.length > 0 ) ) && row.treeNode.state === 'expanded', 'ui-grid-icon-plus-squared': ( ( grid.options.showTreeExpandNoChildren && row.treeLevel > -1 ) || ( row.treeNode.children && row.treeNode.children.length > 0 ) ) && row.treeNode.state === 'collapsed'}\\\" ng-style=\\\"{'padding-left': grid.options.treeIndent * row.treeLevel + 'px'}\\\"></i> &nbsp;</div>\"\n  );\n\n\n  $templateCache.put('ui-grid/cellTitleValidator',\n    \"<div class=\\\"ui-grid-cell-contents\\\" ng-class=\\\"{invalid:grid.validate.isInvalid(row.entity,col.colDef)}\\\" title=\\\"{{grid.validate.getTitleFormattedErrors(row.entity,col.colDef)}}\\\">{{COL_FIELD CUSTOM_FILTERS}}</div>\"\n  );\n\n\n  $templateCache.put('ui-grid/cellTooltipValidator',\n    \"<div class=\\\"ui-grid-cell-contents\\\" ng-class=\\\"{invalid:grid.validate.isInvalid(row.entity,col.colDef)}\\\" tooltip-html-unsafe=\\\"{{grid.validate.getFormattedErrors(row.entity,col.colDef)}}\\\" tooltip-enable=\\\"grid.validate.isInvalid(row.entity,col.colDef)\\\" tooltip-append-to-body=\\\"true\\\" tooltip-placement=\\\"top\\\" title=\\\"TOOLTIP\\\">{{COL_FIELD CUSTOM_FILTERS}}</div>\"\n  );\n\n}]);\n"
  },
  {
    "path": "flowable-ui-web/modeler/manifest.json",
    "content": "{\n\t\"name\": \"\",\n\t\"icons\": [\n\t\t{\n\t\t\t\"src\": \"images\\/android-chrome-192x192.png?v=Om5N75Y123\",\n\t\t\t\"sizes\": \"192x192\",\n\t\t\t\"type\": \"image\\/png\"\n\t\t},\n\t\t{\n\t\t\t\"src\": \"images\\/android-chrome-384x384.png?v=Om5N75Y123\",\n\t\t\t\"sizes\": \"384x384\",\n\t\t\t\"type\": \"image\\/png\"\n\t\t}\n\t],\n\t\"theme_color\": \"#ffffff\",\n\t\"display\": \"standalone\"\n}\n"
  },
  {
    "path": "flowable-ui-web/modeler/scripts/app-cfg.js",
    "content": "/* Copyright 2005-2015 Alfresco Software, Ltd.\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'use strict';\n\nvar FLOWABLE = FLOWABLE || {};\n\nvar pathname = window.location.pathname.replace(/^(\\/[^\\/]*)(\\/.*)?$/, '$1').replace(/\\/$/, '');\n\nFLOWABLE.CONFIG = {\n\t'onPremise' : true,\n\t'contextRoot' : \"/flowable_modeler\",\n\t'webContextRoot' : pathname,\n\t'datesLocalization' : false\n};\n"
  },
  {
    "path": "flowable-ui-web/modeler/scripts/app.js",
    "content": "/* 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'use strict';\n\nvar flowableModeler = angular.module('flowableModeler', [\n  'ngCookies',\n  'ngResource',\n  'ngSanitize',\n  'ngRoute',\n  'ngDragDrop',\n  'mgcrea.ngStrap',\n  'mgcrea.ngStrap.helpers.dimensions', // Needed for tooltips\n  'ui.grid',\n  'ui.grid.edit',\n  'ui.grid.selection',\n  'ui.grid.autoResize',\n  'ui.grid.moveColumns',\n  'ui.grid.cellNav',\n  'ngAnimate',\n  'pascalprecht.translate',\n  'ngFileUpload',\n  'angularSpectrumColorpicker',\n  'duScroll',\n  'dndLists',\n  'ngHandsontable'\n]);\n\nvar flowableModule = flowableModeler;\nvar flowableApp = flowableModeler;\n\nflowableModeler\n  // Initialize routes\n  .config(['$provide', '$routeProvider', '$selectProvider', '$translateProvider', function ($provide, $routeProvider, $selectProvider, $translateProvider) {\n\n    var appResourceRoot = FLOWABLE.CONFIG.webContextRoot + (FLOWABLE.CONFIG.webContextRoot ? '/' : '');\n    $provide.value('appResourceRoot', appResourceRoot);\n\n\n    // Override caret for bs-select directive\n  \tangular.extend($selectProvider.defaults, {\n      caretHtml: '&nbsp;<i class=\"icon icon-caret-down\"></i>'\n  \t});\n\n    $routeProvider\n        .when('/processes', {\n            templateUrl: appResourceRoot + 'views/processes.html',\n            controller: 'ProcessesCtrl'\n        })\n        .when('/processes/:modelId', {\n            templateUrl: appResourceRoot + 'views/process.html',\n            controller: 'ProcessCtrl'\n        })\n        .when('/processes/:modelId/history/:modelHistoryId', {\n            templateUrl: appResourceRoot + 'views/process.html',\n            controller: 'ProcessCtrl'\n        })\n        .when('/casemodels', {\n            templateUrl: appResourceRoot + 'views/casemodels.html',\n            controller: 'CaseModelsCtrl'\n        })\n        .when('/casemodels/:modelId', {\n            templateUrl: appResourceRoot + 'views/casemodel.html',\n            controller: 'CaseModelCtrl'\n        })\n        .when('/forms', {\n            templateUrl: appResourceRoot + 'views/forms.html',\n            controller: 'FormsCtrl'\n        })\n        .when('/forms/:modelId', {\n            templateUrl: appResourceRoot + 'views/form.html',\n            controller: 'FormCtrl'\n        })\n        .when('/forms/:modelId/history/:modelHistoryId', {\n            templateUrl: appResourceRoot + 'views/form.html',\n            controller: 'FormCtrl'\n        })\n        .when('/decision-tables', {\n            templateUrl: appResourceRoot + 'views/decision-tables.html',\n            controller: 'DecisionTablesController'\n        })\n        .when('/decision-tables/:modelId', {\n            templateUrl: appResourceRoot + 'views/decision-table.html',\n            controller: 'DecisionTableDetailsCtrl'\n        })\n        .when('/decision-tables/:modelId/history/:modelHistoryId', {\n            templateUrl: appResourceRoot + 'views/decision-table.html',\n            controller: 'DecisionTableDetailsCtrl'\n        })\n        .when('/apps', {\n            templateUrl: appResourceRoot + 'views/app-definitions.html',\n            controller: 'AppDefinitionsCtrl'\n        })\n        .when('/apps/:modelId', {\n            templateUrl: appResourceRoot + 'views/app-definition.html',\n            controller: 'AppDefinitionCtrl'\n        })\n        .when('/apps/:modelId/history/:modelHistoryId', {\n            templateUrl: 'views/app-definition.html',\n            controller: 'AppDefinitionCtrl'\n        })\n        .when('/editor/:modelId', {\n            templateUrl: appResourceRoot + 'editor-app/editor.html',\n            controller: 'EditorController'\n        })\n        .when('/form-editor/:modelId', {\n            templateUrl: appResourceRoot + 'views/form-builder.html',\n            controller: 'FormBuilderController'\n        })\n        .when('/case-editor/:modelId', {\n            templateUrl: appResourceRoot + 'editor-app/editor.html',\n            controller: 'EditorController'\n        })\n        .when('/decision-table-editor/:modelId', {\n            templateUrl: appResourceRoot + 'views/decision-table-editor.html',\n            controller: 'DecisionTableEditorController'\n        })\n        .when('/app-editor/:modelId', {\n            templateUrl: appResourceRoot + 'views/app-definition-builder.html',\n            controller: 'AppDefinitionBuilderController'\n        });\n\n        if (FLOWABLE.CONFIG.appDefaultRoute) {\n            $routeProvider.when('/', {\n                redirectTo: FLOWABLE.CONFIG.appDefaultRoute\n            });\n\n        } else {\n            $routeProvider.when('/', {\n                redirectTo: '/processes'\n            })\n        }\n\n        // Initialize angular-translate\n        $translateProvider.useStaticFilesLoader({\n          prefix: './i18n/',\n          suffix: '.json'\n        })\n        /*\n        This can be used to map multiple browser language keys to a\n        angular translate language key.\n        */\n        // .registerAvailableLanguageKeys(['en'], {\n        //     'en-*': 'en'\n        // })\n        .useSanitizeValueStrategy('escapeParameters')\n        .uniformLanguageTag('bcp47')\n        .determinePreferredLanguage();\n\n  }])\n  .run(['$rootScope', '$timeout', '$modal', '$translate', '$location', '$http', '$window', 'appResourceRoot',\n        function($rootScope, $timeout, $modal, $translate, $location, $http, $window, appResourceRoot) {\n\n            // set angular translate fallback language\n            $translate.fallbackLanguage(['en']);\n\n            // setting Moment-JS (global) locale\n            if (FLOWABLE.CONFIG.datesLocalization) {\n                moment.locale($translate.proposedLanguage());\n            }\n\n            $rootScope.restRootUrl = function() {\n                return FLOWABLE.CONFIG.contextRoot;\n            };\n\n          \t$rootScope.appResourceRoot = appResourceRoot;\n\n            $rootScope.window = {};\n            var updateWindowSize = function() {\n                $rootScope.window.width = $window.innerWidth;\n                $rootScope.window.height  = $window.innerHeight;\n            };\n\n            // Window resize hook\n            angular.element($window).bind('resize', function() {\n                $rootScope.safeApply(updateWindowSize());\n            });\n\n            $rootScope.$watch('window.forceRefresh', function(newValue) {\n                if(newValue) {\n                    $timeout(function() {\n                        updateWindowSize();\n                        $rootScope.window.forceRefresh = false;\n                    });\n                }\n            });\n\n            updateWindowSize();\n\n            // Main navigation\n            $rootScope.mainNavigation = [\n                {\n                    'id': 'processes',\n                    'title': 'GENERAL.NAVIGATION.PROCESSES',\n                    'path': '/processes'\n                },\n                {\n                    'id': 'casemodels',\n                    'title': 'GENERAL.NAVIGATION.CASEMODELS',\n                    'path': '/casemodels'\n                },\n                {\n                    'id': 'forms',\n                    'title': 'GENERAL.NAVIGATION.FORMS',\n                    'path': '/forms'\n                },\n                {\n                    'id': 'decision-tables',\n                    'title': 'GENERAL.NAVIGATION.DECISION-TABLES',\n                    'path': '/decision-tables'\n                },\n                {\n                    'id': 'apps',\n                    'title': 'GENERAL.NAVIGATION.APPS',\n                    'path': '/apps'\n                }\n            ];\n\n            $rootScope.config = FLOWABLE.CONFIG;\n\n            $rootScope.mainPage = $rootScope.mainNavigation[0];\n\n            // Add url helpers to root scope:\n            $rootScope.getModelThumbnailUrl = FLOWABLE.APP_URL.getModelThumbnailUrl;\n            $rootScope.getImageUrl = FLOWABLE.APP_URL.getImageUrl;\n\n            /*\n             * History of process and form pages accessed by the editor.\n             * This is needed because you can navigate to sub processes and forms\n             */\n            $rootScope.editorHistory = [];\n\n            /*\n             * Set the current main page, using the page object. If the page is already active,\n             * this is a no-op.\n             */\n            $rootScope.setMainPage = function(mainPage) {\n                $rootScope.mainPage = mainPage;\n                $location.path($rootScope.mainPage.path);\n            };\n\n            /*\n             * Set the current main page, using the page ID. If the page is already active,\n             * this is a no-op.\n             */\n            $rootScope.setMainPageById = function(mainPageId) {\n                for (var i=0; i<$rootScope.mainNavigation.length; i++) {\n                    if (mainPageId == $rootScope.mainNavigation[i].id) {\n                        $rootScope.mainPage = $rootScope.mainNavigation[i];\n                        break;\n                    }\n                }\n            };\n\n            /**\n             * A 'safer' apply that avoids concurrent updates (which $apply allows).\n             */\n            $rootScope.safeApply = function(fn) {\n                var phase = this.$root.$$phase;\n                if(phase == '$apply' || phase == '$digest') {\n                    if(fn && (typeof(fn) === 'function')) {\n                        fn();\n                    }\n                } else {\n                    this.$apply(fn);\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            $http.get(FLOWABLE.APP_URL.getAccountUrl())\n\t        \t.success(function (data, status, headers, config) {\n\t              \t$rootScope.account = data;\n\t               \t$rootScope.invalidCredentials = false;\n\t \t\t\t\t$rootScope.authenticated = true;\n\t          \t});\n\n\t        $rootScope.logout = function () {\n                $rootScope.authenticated = false;\n                $rootScope.authenticationError = false;\n                $http.get(FLOWABLE.APP_URL.getLogoutUrl())\n                    .success(function (data, status, headers, config) {\n                        $rootScope.login = null;\n                        $rootScope.authenticated = false;\n                        $window.location.href = '/';\n                        $window.location.reload();\n                    });\n            };\n        }\n  ])\n  .run(['$rootScope', '$location', '$translate', '$window', '$modal',\n        function($rootScope, $location, $translate, $window , $modal) {\n\n            var fixedUrlPart = '/editor/';\n\n            $rootScope.backToLanding = function() {\n                var baseUrl = $location.absUrl();\n                var index = baseUrl.indexOf(fixedUrlPart);\n                if (index >= 0) {\n                    baseUrl = baseUrl.substring(0, index);\n                    baseUrl += '/';\n                }\n                $window.location.href = baseUrl;\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": "flowable-ui-web/modeler/scripts/common/controllers/about.js",
    "content": "/* 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'use strict';\n\nflowableApp.controller('AboutFlowablePopupCtrl', ['$rootScope', '$scope', '$http', '$translate', '$interval', '$dateFormatter', function($rootScope, $scope, $http, $translate, $interval, $dateFormatter) {\n    $scope.popup = {\n        loading: true,\n        activitiVersion: {},\n        licenseHolder: ''\n    };\n\n    $http({method: 'GET', url: FLOWABLE.APP_URL.getAboutInfoUrl()}).\n        success(function(response, status, headers, config) {\n            $scope.popup.licenseHolder = response.holder;\n            $scope.popup.activitiVersion = response.versionInfo.edition + ' v' + response.versionInfo.majorVersion + '.' + response.versionInfo.minorVersion + '.' + response.versionInfo.revisionVersion;\n            $scope.popup.activitiVersionType = response.versionInfo.type;\n            $scope.popup.loading = false;\n        }).\n        error(function(response, status, headers, config) {\n            $scope.popup.loading = false;\n        });\n\n\n    $scope.cancel = function() {\n        $scope.close();\n    };\n\n\n    $scope.close = function() {\n        $scope.$hide();\n    }\n\n}]);\n"
  },
  {
    "path": "flowable-ui-web/modeler/scripts/common/directives.js",
    "content": "/* 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 */\nflowableModule\n  .directive('restrictInput', [\"$parse\", function ($parse) {\n    return {\n      restrict: 'A',\n      require: 'ngModel',\n      priority: 1002,\n\n      link: function postLink(scope, elm, attrs, ctrl) {\n\n        var acceptedFormat = attrs[\"restrictInput\"];\n        if (acceptedFormat == undefined || acceptedFormat == null || acceptedFormat == \"\") {\n           acceptedFormat = attrs[\"dateFormat\"];\n        }\n\n        scope.field.acceptedFormat=acceptedFormat;\n\n        function calculateAcceptedFormats(format) {\n          var format1 = format.toUpperCase(); //d-m-yyyy\n          var format2 = format1.replace(/-D-/,\"-DD-\").replace(/^D-/,\"DD-\").replace(/-D$/,\"-DD\"); //dd-m-yyyy\n          var format3 = format1.replace(/-M-/,\"-MM-\").replace(/^M-/,\"MM-\").replace(/-M$/,\"-MM\");  //d-mm-yyyy\n          var format4 = format2.replace(/-M-/,\"-MM-\").replace(/^M-/,\"MM-\").replace(/-M$/,\"-MM\");  //dd-mm-yyyy\n          return [format1,format2,format3,format4];\n        }\n\n        var acceptedFormats = calculateAcceptedFormats(acceptedFormat);\n        var skipValidation = false;\n\n        if (acceptedFormat == undefined || acceptedFormat == null || acceptedFormat == \"\") {\n          skipValidation = true;\n        }\n        var oldRenderer = ctrl.$render;\n\n        ctrl.$render = function () {\n          elm.val(ctrl.$viewValue);\n          if (ctrl.$dateValue && !isNaN(ctrl.$dateValue.getTime())) {\n            if (oldRenderer) {\n              oldRenderer();\n            }\n          }\n        };\n\n        function isValidText(viewValue, format) {\n          if (viewValue === undefined || viewValue == null || viewValue ==='') return true;\n          if (viewValue.length > format.length) return false;\n\n           for (var i = 0; i < Math.min(format.length, viewValue.length); i++) {\n             var charType = format[i];\n             if (charType.toUpperCase().match(/D|M|Y/)) {\n               if (viewValue[i].match(/\\d/) == null) return false;\n             }else {\n               if (viewValue[i] != charType) return false;\n             }\n           }\n           return true;\n         }\n\n        ctrl.$parsers.unshift(function (viewValue) {\n\n          if (skipValidation) return viewValue; //just skip this parser\n\n          var isValid = false;\n          for(var i =0 ; i < acceptedFormats.length && !isValid; i++){\n            isValid |= isValidText(viewValue,acceptedFormats[i]);\n          }\n\n          if (!isValid) {\n            //should restore to the latest known well formated date.\n            ctrl.$dateValue = null;\n          } else {\n            ctrl.$lastValidText = viewValue;\n\n              //by default the date picker in angular strap does not reset the dateValue if the viewValue is null or empty.\n              if (viewValue === undefined || viewValue == null || viewValue === '') {\n                  ctrl.$dateValue = null;\n              }\n\n            return viewValue;\n          }\n\n          ctrl.$setViewValue(ctrl.$lastValidText);\n          ctrl.$render();\n          return ctrl.$lastValidText;\n        });\n\n      }\n    }\n  }\n  ]);\n\n\nflowableModule\n    .directive('autoHeight', ['$rootScope', '$timeout', function($rootScope, $timeout) {\n        return {\n            restrict: 'AC',\n            scope: {\n              'toWatch': '=autoHeight'\n            },\n            compile: function (element, attr) {\n                return function ($scope, $element, $attrs) {\n                    var offset = 0;\n                    if($attrs['offset']) {\n                        offset = parseInt($attrs['offset']);\n                        if(isNaN(offset) || offset == undefined) {\n                            offset = 0;\n                        }\n                    }\n\n                    var update = function($element) {\n                        // Get hold of parent and iterate all the children to get available height\n\n                        $timeout(function() {\n                            var total = $element.parent().outerHeight() - offset;\n                            var found = false;\n                            $element.parent().children().each(function() {\n                                if(!found) {\n                                    if($element[0] == this) {\n                                        found = true;\n                                    } else {\n                                        // Substract preceding child's height\n                                        total -= angular.element(this).outerHeight();\n                                    }\n                                }\n                            });\n\n                            if(found) {\n                                $element.height(total);\n                            }\n                        }, 0);\n                    };\n\n                    if($scope.unregisterWatcher) {\n                        $scope.unregisterWatcher();\n                    }\n                    $scope.unregisterWatcher = $rootScope.$watch('window.height', function(windowHeight) {\n                        update($element);\n                    });\n\n                    if($scope.unregisterForceWatcher) {\n                        $scope.unregisterForceWatcher();\n                    }\n                    $scope.unregisterForceWatcher = $rootScope.$watch('window.forceRefresh', function(forceValue) {\n                        update($element);\n                    });\n\n\n                    $scope.$on('$destroy', function() {\n                        // Cleanup watcher for window-height\n                        if($scope.unregisterWatcher) {\n                            $scope.unregisterWatcher();\n                        }\n                        if($scope.unregisterForceWatcher) {\n                            $scope.unregisterForceWatcher();\n                        }\n                    });\n                }\n            }\n        };\n    }]);\n\n/**\n * Directive that ensures the child-element with class .active is visible and scrolls if needed. Watches the value\n * of the directive and will re-apply if this value is changes.\n */\nflowableModule\n    .directive('scrollToActive', ['$timeout', function($timeout) {\n        return {\n            restrict: 'AC',\n            scope: {\n                toWatch: \"=scrollToActiveModel\"\n            },\n            compile: function (element, attr) {\n                return function ($scope, $element, $attrs) {\n                    $scope.$watch('toWatch', function() {\n                        $timeout(function() {\n                            var useParent = $attrs['useParent'];\n                            var offsetTop = $attrs['offsetTop'];\n                            if(offsetTop) {\n                                offsetTop = parseInt(offsetTop);\n                                if(isNaN(offsetTop)) {\n                                    offsetTop = 0;\n                                }\n                            }\n                            if (!offsetTop) {\n                                offsetTop = 0;\n                            }\n\n                            var selectedArr = $element.children('.active');\n                            if(selectedArr && selectedArr.length > 0) {\n                                var selected = angular.element(selectedArr[0]);\n\n                                if(useParent) {\n                                    $element = angular.element($element.parent());\n                                }\n                                var selectedTop = selected.position().top - $element.position().top + $element.scrollTop();\n                                var selectedBottom = selectedTop + selected.outerHeight();\n                                var elementBottom = $element.scrollTop() + $element.innerHeight();\n                                var elementTop = elementBottom - $element.innerHeight();\n\n                                if(selectedTop <= elementTop) {\n                                    // scroll up\n                                    $element.scrollTop(selectedTop - selected.outerHeight() - offsetTop);\n                                } else if(selectedBottom > elementBottom) {\n                                    // scroll down\n                                    $element.scrollTop(elementTop + selected.outerHeight() - offsetTop);\n                                }\n                            }\n                        }, 0);\n                    });\n                }\n            }\n        };\n    }]);\n\n/**\n * Directive that ensures the popup is scrolled into view, using the first parent as scroll-pane that has\n * a class 'scroll-container' set on it. Is applied when the popup is shown.\n */\nflowableModule\n    .directive('autoScroll', ['$timeout', function($timeout) {\n        return {\n            restrict: 'AC',\n            compile: function (element, attr) {\n                return function ($scope, $element, $attrs) {\n                    $scope.$on('tooltip.show', function() {\n                        $timeout(function() {\n                            // Find appropriate parent\n                            var parent = $element[0];\n                            while(parent) {\n                                if(parent.className && parent.className.indexOf('scroll-container') >= 0) {\n                                    break;\n                                }\n                                parent = parent.parentNode;\n                            }\n\n                            if(parent) {\n                                parent = angular.element(parent);\n                                var selectedTop = $element.offset().top  - parent.offset().top + $element.scrollTop();\n                                var selectedBottom = selectedTop + $element.outerHeight();\n\n                                if(selectedBottom + 30 >= parent.outerHeight()) {\n                                    parent.scrollTop(selectedTop);\n                                }\n                            }\n                        }, 50);\n                    });\n                }\n            }\n        };\n    }]);\n\nflowableModule\n    .directive('userName', function() {\n        var directive = {};\n        directive.template = '{{user.firstName && user.firstName || \"\"}} {{user.lastName && user.lastName || \"\"}} {{ (user.email && !user.firstName && !user.lastName) && user.email || \"\"}}';\n        directive.scope = {\n            user: \"=userName\"\n        };\n        return directive;\n    });\n\n\n/**\n * Executes the method that is set on the directive attribute value when ANY OTHER element is clicked, which is not the element the\n * directive is on, or any of it's children.\n *\n */\nflowableModule\n    .directive('clickAnywhere', [\"$document\", \"$parse\", function ($document, $parse) {\n\n        var linkFunction = function ($scope, $element, $attributes) {\n\n            var scopeExpression = $attributes.clickAnywhere;\n            var invoker = $parse(scopeExpression);\n\n            var ignoreId = $attributes.ignore;\n            var ignoreClass = $attributes.ignoreClass;\n            var ignorePopupEvents = $attributes.ignorePopupEvents == 'true';\n\n            var handler = function (event) {\n                // Check source of event\n                var parent = event.target;\n                while(parent) {\n                    if(parent == $element[0] ||\n                        (ignoreId && parent.id == ignoreId) ||\n                        (ignoreClass && parent.className && parent.className.indexOf(ignoreClass) >= 0)) {\n\n                        event.stopPropagation();\n                        event.preventDefault();\n                        return;\n                    }\n                    parent = parent.parentNode;\n                }\n\n                $scope.$apply(\n                    function () {\n                        invoker($scope, {$event: event});\n                    }\n                );\n            };\n\n            $document.on(\"click\", handler);\n\n            $scope.$on('$destroy', function () {\n                $document.off(\"click\", handler);\n            });\n\n            // Special handling for tooltips which don't destroy the scope\n            var hideReg = $scope.$on('tooltip.hide', function () {\n                if(!ignorePopupEvents) {\n                    $document.off(\"click\", handler);\n                    hideReg();\n                }\n            });\n\n        };\n\n        // Return the linking function.\n        return( linkFunction );\n    }\n    ]);\n\n\n\n\nflowableModule\n    .directive('autoFocus', ['$timeout', '$parse', function($timeout, $parse) {\n        return {\n            restrict: 'AC',\n            compile: function($element, attr) {\n                var selectText;\n\n                if(attr[\"selectText\"]) {\n                    selectText = $parse(attr[\"selectText\"]);\n                }\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                                if(selectText && selectText(_scope.$parent)) {\n                                    input[0].setSelectionRange(0,input[0].value.length);\n                                }\n                            }\n                        } else {\n                            // Focus element where the directive is put on\n                            _element[0].focus();\n                            if(selectText && selectText(_scope.$parent)) {\n                                _element[0].setSelectionRange(0,_element[0].value.length);\n                            }\n                        }\n                    }, 100);\n                }\n            }\n        };\n    }]);\n\nflowableModule\n    .directive('focusWhen', ['$timeout', function ($timeout) {\n        return {\n            link: function (scope, element, attrs) {\n                scope.$watch(attrs.ngFocus, function (val) {\n                    if (angular.isDefined(val) && val) {\n                        $timeout(function () {\n                            element[0].focus();\n                        });\n                    }\n                }, true);\n\n                element.bind('blur', function () {\n                    if (angular.isDefined(attrs.ngFocusLost)) {\n                        scope.safeApply(attrs.ngFocusLost);\n                    }\n                });\n            }\n        };\n    }]);\n\n\nflowableModule\n    .directive('loading', [function() {\n        var directive = {};\n        directive.restrict = 'A';\n        directive.template = '<div class=\"loading\" ng-show=\"loading\"><div class=\"l1\"></div><div class=\"l2\"></div><div class=\"l3\"></div></div>';\n        directive.scope = {\n            loading : \"=loading\",\n            loadingText: \"=loadingText\"\n        };\n        return directive;\n    }]);\n\n// Workaround for https://github.com/twbs/bootstrap/issues/8379 :\n// prototype.js interferes with regular dropdown behavior\nflowableModule\n    .directive('activitiFixDropdownBug', function() {\n        return {\n            restrict: 'AEC',\n            link: function(scope, element, attrs) {\n                element.on('hidden.bs.dropdown\t', function () {\n                    element.show(); // evil prototype.js has added display:none to it ...\n                })\n            }\n        };\n    });\n\n/**\n * Directive for rendering user link.\n */\nflowableModule\n  .directive('userLink', function() {\n    var directive = {};\n    directive.template = '{{user.firstName && user.firstName || \"\"}} {{user.lastName && user.lastName || \"\"}} {{ (user.email && !user.firstName && !user.lastName) && user.email || \"\"}}';\n    directive.scope = {\n        user: \"=userLink\"\n    };\n\n    directive.compile = function(element, attributes) {\n        element.addClass('people-link');\n    };\n\n    return directive;\n});\n\n/**\n * Directive for rendering a form field.\n */\nflowableModule\n    .directive('formField', function () {\n        var directive = {};\n\n        directive.template = ' {{field.name || \"\"}} - {{field.id}}';\n        directive.scope = {\n            field: \"=formField\"\n        };\n\n        directive.compile = function (element, attributes) {\n            element.addClass('form-field');\n        };\n        return directive;\n    });\n/**\n * Directive to capture mouse up, down, enter and escape on input fields (eg. list navigation)\n */\nflowableModule\n    .directive('customKeys', [\"$parse\", function ($parse) {\n        var directive = {};\n        directive.compile = function($element, attr) {\n            var up, down, enter, escape;\n\n            if(attr[\"upPressed\"]) {\n                up = $parse(attr[\"upPressed\"]);\n            }\n            if(attr[\"downPressed\"]) {\n                down = $parse(attr[\"downPressed\"]);\n            }\n            if(attr[\"enterPressed\"]) {\n                enter = $parse(attr[\"enterPressed\"]);\n            }\n\n            if(attr[\"escapePressed\"]) {\n                escape = $parse(attr[\"escapePressed\"]);\n            }\n\n            return function(scope, element, attr) {\n                element.on('keyup', function(e) {\n                    if(e.keyCode === 38) {\n                        scope.$apply(function() {\n                            if(up) {\n                                up(scope, {$event:e});\n                            }\n                        });\n                    } else if(e.keyCode === 40) {\n                        scope.$apply(function() {\n                            if(down) {\n                                down(scope, {$event:e});\n                            }\n                        });\n                    } else if(e.keyCode === 13) {\n                        scope.$apply(function() {\n                            if(enter) {\n                                enter(scope, {$event:e});\n                            }\n                        });\n                    } else if(e.keyCode === 27) {\n                    scope.$apply(function() {\n                        if(escape) {\n                            escape(scope, {$event:e});\n                        }\n                    });\n                }\n                });\n\n                element.on('keydown', element, function (e) {\n                    if (e.keyCode === 38 || e.keyCode === 40 || e.keyCode === 13 || e.keyCode === 27)\n                        e.preventDefault();\n                });\n            };\n    };\n    return directive;\n}]);\n\n// Delayed setting of model value in scope, based on input value unchanged after a number of millis\n// See below: ngDebounce is preferred (as it hooks into ngModel, meaning that ng-change will keep working - but not with delayedModel)\nflowableModule\n    .directive('delayedModel', ['$timeout', function($timeout) {\n    return {\n        scope: {\n            targetModel: '=delayedModel'\n        },\n        link: function(scope, element, attrs) {\n\n            element.val(scope.targetModel);\n\n            // Also watch model for any changes not triggered by timer\n            scope.$watch('targetModel', function(newVal, oldVal) {\n                if(scheduled) {\n                    $timeout.cancel(scheduled);\n                }\n                if (newVal !== oldVal) {\n                    element.val(scope.targetModel);\n                }\n            });\n\n            var scheduled;\n            element.on('keyup paste search', function() {\n                if(element.val() !== scope.targetModel) {\n                    if(scheduled) {\n                        $timeout.cancel(scheduled);\n                    }\n                    scheduled = $timeout(function() {\n                        scope.targetModel = element[0].value;\n                        element.val(scope.targetModel);\n                        scope.$apply();\n                    }, attrs.delay || 200);\n                }\n            });\n        }\n    };\n}]);\n\n\n// From https://gist.github.com/benbrandt22/bb44184a2eddcd4b0b8a\nflowableModule.directive('ngDebounce', ['$timeout', function($timeout) {\n    return {\n        restrict: 'A',\n        require: 'ngModel',\n        priority: 99,\n        link: function(scope, elm, attr, ngModelCtrl) {\n            if (attr.type === 'radio' || attr.type === 'checkbox') return;\n\n            elm.unbind('input');\n\n            var debounce;\n            elm.bind('input', function() {\n                $timeout.cancel(debounce);\n                debounce = $timeout( function() {\n                    scope.$apply(function() {\n                        ngModelCtrl.$setViewValue(elm.val());\n                    });\n                }, attr.ngDebounce || 1000);\n            });\n            elm.bind('blur', function() {\n                scope.$apply(function() {\n                    ngModelCtrl.$setViewValue(elm.val());\n                });\n            });\n        }\n\n    }\n}]);\n\nflowableModule.\n    directive('selectPeoplePopover', ['$rootScope', '$http', '$popover', 'appResourceRoot', 'UserService', '$parse', function($rootScope, $http, $popover, appResourceRoot, UserService, $parse) {\n        var directive = {};\n        directive.restrict = 'A';\n\n        directive.scope = {\n            excludeTaskId: '=excludeTaskId',\n            excludeProcessId: '=excludeProcessId',\n            excludeUserId: '=excludeUserId',\n            excludeUserIds: '=excludeUserIds',\n            tenantId: '=tenantId',\n            type: '=type',\n            restrictWithGroup: '=restrictWithGroup',\n            selectPeopleFormFields: '=selectPeopleFormFields',\n            ignoreContainer: '=ignoreContainer'\n        };\n\n        directive.link = function($scope, $element, attrs) {\n            // Set defaults\n            var placement = \"bottom\";\n\n            $element.addClass(\"toggle-people-select\");\n\n            if(attrs.placement) {\n                placement = attrs.placement;\n            }\n\n            var closeOnSelect = true;\n            if(attrs.closeOnSelect !== undefined) {\n                closeOnSelect = attrs.closeOnSelect;\n            }\n\n            if ($scope.ignoreContainer) {\n                $scope.popover = $popover($element, {template: appResourceRoot + '../views/common/popover/select-people-popover.html?'  +\n                    Date.now(), placement: placement});\n\n            } else {\n                $scope.popover = $popover($element, {template: appResourceRoot + '../views/common/popover/select-people-popover.html?'  +\n                    Date.now(), placement: placement, container: 'body'});\n            }\n\n            // Parse callbacks\n            var selectedCallback, cancelledCallback, emailSelectedCallback;\n            if (attrs['onPeopleSelected']) {\n                selectedCallback = $parse(attrs['onPeopleSelected']);\n            }\n            if (attrs['onCancel']) {\n                cancelledCallback = $parse(attrs['onCancel']);\n            }\n            if (attrs['onEmailSelected']) {\n                emailSelectedCallback = $parse(attrs['onEmailSelected']);\n            }\n\n            // Parse type\n            // Can be 'workflow' or 'idm'. In 'workflow', the users are retrieved for filling task assignments etc. This is the default if this param is omitted. 'idm' is more strict.\n            var backendType = 'workflow';\n            if ($scope.type !== null && $scope.type !== undefined) {\n                backendType = $scope.type;\n            }\n\n            var popoverScope = $scope.popover.$scope;\n            popoverScope.title = attrs['popoverTitle'];\n\n            popoverScope.popupModel = {\n                emailMode: false,\n                showRecentResults: false, // Disabled recent for the moment. Put this on true to set it back\n                userResults: [],\n                userField: {},\n                userFieldFilter: ['people']\n            };\n            \n            if ($scope.selectPeopleFormFields) {\n                popoverScope.popupModel.formFields = $scope.selectPeopleFormFields;\n            }\n\n            if (attrs['emailModeDisabled']) {\n                var emailModeDisabledValue = attrs['emailModeDisabled'];\n                if (emailModeDisabledValue === 'true') {\n                    popoverScope.popupModel.emailDisabled = true;\n                }\n            }\n\n            popoverScope.popupModel.emailMode = false;\n\n\n            popoverScope.setSearchType = function() {\n                popoverScope.popupModel.userSourceType = 'search';\n            };\n            \n            popoverScope.setFormFieldType = function() {\n                popoverScope.popupModel.userSourceType = 'field';\n            };\n            \n            popoverScope.$watch('popupModel.userField', function() {\n                if (popoverScope.popupModel.userField && popoverScope.popupModel.userField.id) {\n                    if (selectedCallback) {\n                        // Run callback in parent scope of directive\n                        var simpleUserField = {\n                                id: popoverScope.popupModel.userField.id, \n                                name: popoverScope.popupModel.userField.name,\n                                type: popoverScope.popupModel.userField.type\n                        }\n       \n                        selectedCallback($scope.$parent, {'userField': simpleUserField});\n                        popoverScope.popupModel.userField = {};\n                    }\n                    \n                    if (closeOnSelect || closeOnSelect === 'true') {\n                        popoverScope.$hide();\n                    }\n                }           \n            });\n\n            popoverScope.$watch('popupModel.filter', function() {\n                if (popoverScope.popupModel.filter && popoverScope.popupModel.filter.length > 0) {\n\n                    var userGetPromise;\n                    if (backendType === 'idm') {\n                        userGetPromise = UserService.getFilteredUsersStrict(popoverScope.popupModel.filter, $scope.tenantId, $scope.restrictWithGroup);\n                    } else {\n                        // Default: go to workflow users backend\n                        userGetPromise = UserService.getFilteredUsers(popoverScope.popupModel.filter, $scope.excludeTaskId,\n                                $scope.excludeProcessId, $scope.tenantId, $scope.restrictWithGroup);\n                    }\n\n                    userGetPromise.then(function(result) {\n                        popoverScope.popupModel.showRecentResults =  false;\n\n                        var users = [];\n                        var excludeUserIdSet = $scope.excludeUserId !== null && $scope.excludeUserId !== undefined;\n                        var excludeUserIdsSet = $scope.excludeUserIds !== null && $scope.excludeUserIds !== undefined;\n                        if (excludeUserIdSet === true || excludeUserIdsSet === true) {\n                            for (var userIndex=0; userIndex < result.data.length; userIndex++) {\n\n                                var userExcluded = false;\n                                if (excludeUserIdSet === true && result.data[userIndex].id === $scope.excludeUserId) {\n                                    userExcluded = true;\n                                }\n                                if (excludeUserIdsSet === true && $scope.excludeUserIds.indexOf(result.data[userIndex].id) >= 0) {\n                                    userExcluded = true;\n                                }\n\n                                if (!userExcluded) {\n                                    users.push(result.data[userIndex]);\n                                }\n\n                            }\n                        } else {\n                            users = result.data;\n                        }\n                        popoverScope.popupModel.userResults = users;\n                        popoverScope.resetSelection();\n                    });\n                } else {\n                    popoverScope.resetSelection();\n                    popoverScope.popupModel.userResults = [];\n                }\n            });\n\n            popoverScope.resetSelection = function() {\n                popoverScope.popupModel.selectedUser = undefined;\n                popoverScope.popupModel.selectedIndex = -1;\n            };\n\n            popoverScope.nextUser = function() {\n                var users = popoverScope.popupModel.userResults;\n                if(users && users.length > 0 && popoverScope.popupModel.selectedIndex < users.length -1) {\n                    popoverScope.popupModel.selectedIndex+=1;\n                    popoverScope.popupModel.selectedUser = users[popoverScope.popupModel.selectedIndex];\n                }\n            };\n\n            popoverScope.previousUser = function() {\n                var users = popoverScope.popupModel.userResults;\n                if(users && users.length > 0 && popoverScope.popupModel.selectedIndex > 0) {\n                    popoverScope.popupModel.selectedIndex-=1;\n                    popoverScope.popupModel.selectedUser = users[popoverScope.popupModel.selectedIndex];\n                }\n            };\n\n            popoverScope.confirmUser = function(user) {\n                if (!user) {\n                    // Selection is done with keyboard, use selection index\n                    var users = popoverScope.popupModel.userResults;\n                    if (popoverScope.popupModel.selectedIndex >= 0 && popoverScope.popupModel.selectedIndex <users.length) {\n                        user = users[popoverScope.popupModel.selectedIndex];\n                    }\n                }\n\n                if (user) {\n                    if (selectedCallback) {\n                        // Run callback in parent scope of directive\n                        selectedCallback($scope.$parent, {'user': user});\n                    }\n\n                    if (closeOnSelect === 'true') {\n                        popoverScope.$hide();\n                    } else {\n                        var users = popoverScope.popupModel.userResults;\n                        users.splice(jQuery.inArray(user, users),1);\n                        popoverScope.popupModel.selectedIndex=0;\n                        popoverScope.popupModel.selectedUser = users[popoverScope.popupModel.selectedIndex];\n                    }\n                }\n            };\n\n            popoverScope.selectPersonByEmail = function(validEmail) { // Not so nice we have to pass the valid email agrument, but couldnt make it work properly\n                if (validEmail) {\n                    if (emailSelectedCallback) {\n                        emailSelectedCallback($scope.$parent, {email: popoverScope.popupModel.email});\n                        popoverScope.$hide();\n                    }\n                }\n            };\n\n            popoverScope.$on('tooltip.hide', function() {\n                // Invalidate recent results\n                if(popoverScope.popupModel.showRecentResults && popoverScope.popupModel.added) {\n                    popoverScope.popupModel.recentUsers = [];\n                }\n                popoverScope.popupModel.userResults = [];\n                popoverScope.popupModel.filter = '';\n                popoverScope.popupModel.emailMode = false;\n\n                if(popoverScope.popupModel.added) {\n                    popoverScope.popupModel.added = false;\n                } else {\n                    if(cancelledCallback) {\n                        // Run callback in parent scope of directive\n                        cancelledCallback($scope.$parent);\n                    }\n                }\n            });\n\n        };\n        return directive;\n    }]);\n\nflowableModule.\ndirective('selectFunctionalGroupPopover', ['$rootScope', '$http', '$popover','appResourceRoot', 'FunctionalGroupService', '$parse',\n    function($rootScope, $http, $popover, appResourceRoot, FunctionalGroupService, $parse) {\n\n    var directive = {};\n    directive.restrict = 'A';\n\n    directive.scope = {\n        type: '=type',\n        ignoreContainer: '=ignoreContainer',\n        restrictWithGroup: '=restrictWithGroup',\n        excludeGroupIds: '=excludeGroupIds'\n    };\n\n    directive.link = function($scope, $element, attrs) {\n        // Set defaults\n        var placement = \"bottom\";\n\n        $element.addClass(\"toggle-functional-group-select\");\n\n        if (attrs.placement) {\n            placement = attrs.placement;\n        }\n\n        var closeOnSelect = true;\n        if (attrs.closeOnSelect !== undefined) {\n            closeOnSelect = attrs.closeOnSelect;\n        }\n\n        if ($scope.ignoreContainer) {\n            $scope.popover = $popover($element, {template: appResourceRoot + '../views/common/popover/select-functional-group-popover.html?' +\n                Date.now(), placement: placement});\n\n        } else {\n            $scope.popover = $popover($element, {template: appResourceRoot + '../views/common/popover/select-functional-group-popover.html?' +\n                Date.now(), placement: placement, container: 'body'});\n        }\n\n        // Parse callbacks\n        var selectedCallback, cancelledCallback;\n        if (attrs['onGroupSelected']) {\n            selectedCallback = $parse(attrs['onGroupSelected']);\n        }\n        if (attrs['onCancel']) {\n            cancelledCallback = $parse(attrs['onCancel']);\n        }\n\n        var popoverScope = $scope.popover.$scope;\n        popoverScope.title = attrs['popoverTitle'];\n\n        popoverScope.popupModel = {\n            groupResults: []\n        };\n\n        popoverScope.$watch('popupModel.filter', function() {\n            if (popoverScope.popupModel.filter && popoverScope.popupModel.filter.length > 0) {\n\n                var tenantId;\n                if ($rootScope.common !== null && $rootScope.common !== undefined && $rootScope.common.selectedTenantId !== null && $rootScope.common.selectedTenantId !== undefined) {\n                    tenantId = $rootScope.common.selectedTenantId > 0 ? $rootScope.common.selectedTenantId : undefined;\n                }\n\n               FunctionalGroupService.getFilteredGroups(popoverScope.popupModel.filter, $scope.restrictWithGroup, tenantId).then(function(result) {\n                    var groups = [];\n                    if ($scope.excludeGroupId != null && $scope.excludeGroupId) {\n                        for (var groupIndex=0; groupIndex < result.data.length; groupIndex++) {\n                            if (result.data[groupIndex].id !== $scope.excludeGroupId) {\n                                groups.push(result.data[groupIndex]);\n                            }\n                        }\n                    } else if ($scope.excludeGroupIds != null && $scope.excludeGroupIds !== undefined) {\n                        for (var groupIndex=0; groupIndex < result.data.length; groupIndex++) {\n                            if ($scope.excludeGroupIds.indexOf(result.data[groupIndex].id) < 0) {\n                                groups.push(result.data[groupIndex]);\n                            }\n                        }\n                    } else {\n                        groups = result.data;\n                    }\n                    popoverScope.popupModel.groupResults = groups;\n                    popoverScope.resetSelection();\n                });\n            } else {\n                popoverScope.resetSelection();\n                popoverScope.popupModel.groupResults = [];\n            }\n        });\n\n        popoverScope.resetSelection = function() {\n            popoverScope.popupModel.selectedGroup = undefined;\n            popoverScope.popupModel.selectedIndex = -1;\n        };\n\n        popoverScope.nextGroup = function() {\n            var groups = popoverScope.popupModel.groupResults;\n            if (groups && groups.length > 0 && popoverScope.popupModel.selectedIndex < groups.length -1) {\n                popoverScope.popupModel.selectedIndex+=1;\n                popoverScope.popupModel.groupUser = groups[popoverScope.popupModel.selectedIndex];\n            }\n        };\n\n        popoverScope.previousGroup = function() {\n            var groups = popoverScope.popupModel.groupResults;\n            if (groups && groups.length > 0 && popoverScope.popupModel.selectedIndex > 0) {\n                popoverScope.popupModel.selectedIndex-=1;\n                popoverScope.popupModel.selectedGroup = groups[popoverScope.popupModel.selectedIndex];\n            }\n        };\n\n        popoverScope.confirmGroup = function(group) {\n            if (!group) {\n                // Selection is done with keyboard, use selection index\n                var groups = popoverScope.popupModel.groupResults;\n                if (popoverScope.popupModel.selectedIndex >= 0 && popoverScope.popupModel.selectedIndex < groups.length) {\n                    group = groups[popoverScope.popupModel.selectedIndex];\n                }\n            }\n\n            if (group) {\n                if(selectedCallback) {\n                    // Run callback in parent scope of directive\n                    selectedCallback($scope.$parent, {'group': group});\n                }\n\n                if (closeOnSelect === 'true') {\n                    popoverScope.$hide();\n                } else {\n                    var groups = popoverScope.popupModel.groupResults;\n                    groups.splice(jQuery.inArray(group, groups), 1);\n                    popoverScope.popupModel.selectedIndex = 0;\n                    popoverScope.popupModel.selectedGroup = groups[popoverScope.popupModel.selectedIndex];\n                }\n            }\n        };\n\n        popoverScope.$on('tooltip.hide', function() {\n            popoverScope.popupModel.groupResults = [];\n            popoverScope.popupModel.filter = '';\n\n            if (popoverScope.popupModel.added) {\n                popoverScope.popupModel.added = false;\n            } else {\n                if (cancelledCallback) {\n                    // Run callback in parent scope of directive\n                    cancelledCallback($scope.$parent);\n                }\n            }\n        });\n\n    };\n    return directive;\n}]);\n\nflowableModule.directive('tabControl', ['$compile', '$http', '$templateCache', function($compile, $http, $templateCache) {\n\n        var updateTemplate = function($scope, element, attributes) {\n            if(!$scope.activeTemplate || $scope.activeTemplate != $scope.activeTab.id) {\n                // Check if current loaded template is still the right one\n                var contentDiv = $(element.children()[1]);\n\n                var childScope = angular.element(element.children()[1]).scope();\n                if($scope.activeTemplate && childScope != $scope) {\n                    // Child-scope created by the included element, should be destroyed\n                    childScope.$destroy();\n                }\n\n                if($scope.activeTab && $scope.activeTab.templateUrl) {\n                    // Load the HTML-fragment or get from cache\n                    var loader = $http.get($scope.activeTab.templateUrl, {cache: $templateCache});\n                    var promise = loader.success(function(html) {\n                        contentDiv.html(html);\n                    }).then(function (response) {\n                        $scope.activeTemplate = $scope.activeTab.id;\n                        contentDiv.replaceWith($compile(contentDiv.html())($scope));\n                    });\n                } else {\n                    // No templates are being used, no need to use the contentDiv for this tab, clear it\n                    contentDiv.empty();\n                }\n            }\n        };\n\n        var directive = {};\n        directive.restrict = 'A';\n        directive.replace = true;\n        directive.transclude = true;\n        directive.template = '<div><div class=\"clearfix\"><ul class=\"tabs clearfix\">' +\n            '<li ng-repeat=\"tab in tabs\" ng-class=\"{\\'active\\': tab.id == activeTab.id}\"><a ng-click=\"tabClicked(tab)\">{{tab.title && (tab.title | translate) || (tab.name | translate)}}</a></li>' +\n            '</ul></div>' +\n            '<div></div>' +\n            '</div>';\n\n        directive.scope = {\n            possibleTabs : \"=tabControl\",\n            model: \"=model\",\n            activeTabReference: \"=activeTab\"\n        };\n\n\n        directive.controller = ['$scope', '$element', function($scope, $element) {\n\n            $scope.refreshTabs = function() {\n                var tabs = [];\n                for(var i=0; i < $scope.possibleTabs.length; i++) {\n                    var tab = $scope.possibleTabs[i];\n                    if(!tab.hide) {\n                        tabs.push(tab);\n                    }\n                }\n                $scope.tabs = tabs;\n            };\n\n            $scope.$watch('possibleTabs', function() {\n                $scope.refreshTabs();\n            }, true);\n\n            $scope.$watch('activeTabReference', function(newValue, oldValue) {\n                if(!$scope.activeTab || $scope.activeTab.id != newValue) {\n                    // Active tab ID changed from outside of the directive controller, need to switch to the\n                    // right tab within this scope\n                    var newTab = $scope.findTab(newValue);\n                    if(newTab) {\n                        $scope.tabClicked(newTab);\n                    }\n                }\n            });\n\n            $scope.findTab = function(tabId) {\n                if($scope.possibleTabs) {\n                    for(var i=0; i< $scope.possibleTabs.length; i++) {\n                        if($scope.possibleTabs[i].id == tabId) {\n                            return $scope.possibleTabs[i];\n                        }\n                    }\n                }\n                return undefined;\n            };\n\n            $scope.tabClicked = function(tab) {\n                if (tab.hide) {\n                    tab.hide = false;\n                    $scope.refreshTabs();\n                }\n                $scope.activeTab = tab;\n                if (tab) {\n                    $scope.activeTabReference = tab.id;\n                } else {\n                    $scope.activeTabReference = undefined;\n                }\n                updateTemplate($scope, $element);\n            };\n\n            $scope.refreshTabs();\n\n            if($scope.tabs && $scope.tabs.length > 0) {\n                if($scope.activeTabReference) {\n                    $scope.activeTab = $scope.findTab($scope.activeTabReference);\n                }\n\n                if(!$scope.activeTab) {\n                    // Revert to the first tab, if no tab is forced to be shown first\n                    $scope.activeTab = $scope.tabs[0];\n                }\n                $scope.tabClicked($scope.activeTab);\n            }\n        }];\n\n        directive.link = updateTemplate;\n\n        return directive;\n    }]);\n\n/**\n * Directive that calls the function present in the toggle-dragover attribute with a single parameter (over) when\n * dragging over the element has started (over = true) or ended (over = false)\n */\nflowableModule\n    .directive('toggleDragover', [\"$document\", \"$parse\", function ($document, $parse) {\n        var linkFunction = function ($scope, $element, $attributes) {\n\n\n            var toggleFunction = $attributes.toggleDragover;\n            var callback = $parse(toggleFunction);\n\n            var el = $element[0];\n\n            el.addEventListener('dragenter',function(e) {\n                    $scope.$apply(function() {\n                        callback($scope, {'over': true});\n                    });\n                    return false;\n                },\n                false\n            );\n\n            el.addEventListener('dragleave', function(e) {\n                    $scope.$apply(function() {\n                        callback($scope, {'over': false});\n                    });\n                    return false;\n                },\n                false\n            );\n        };\n\n        return( linkFunction );\n    }]);\n\nflowableModule.directive('editInPlace', function () {\n    return {\n        restrict: 'E',\n        scope: {\n            value: '='\n        },\n        template: '<span ng-click=\"edit()\" ng-bind=\"value\"></span><span class=\"glyphicon glyphicon-pencil edit-in-place-icon\"></span><input ng-model=\"value\" class=\"inline-edit-value form-control\" ng-blur=\"stopEdit()\" custom-keys enter-pressed=\"stopEdit()\">',\n        link: function ($scope, element, attrs) {\n\n            var iconElement = angular.element(element.children()[1]);\n            var inputElement = angular.element(element.children()[2]);\n\n            // This directive should have a set class so we can style it.\n            element.addClass('edit-in-place');\n\n            // Initially, we're not editing.\n            $scope.editing = false;\n\n            // ng-click handler to activate edit-in-place\n            $scope.edit = function () {\n                $scope.editing = true;\n\n                // We control display through a class on the directive itself. See the CSS.\n                element.addClass('active');\n\n                // And we must focus the element.\n                // `angular.element()` provides a chainable array, like jQuery so to access a native DOM function,\n                // we have to reference the first element in the array.\n                inputElement[0].focus();\n            };\n\n            $scope.stopEdit = function() {\n                $scope.editing = false;\n                element.removeClass('active');\n            };\n\n//            // When we leave the input, we're done editing.\n//            inputElement.prop('onblur', function () {\n//                console.log('ONBLUR');\n//                $scope.editing = false;\n//                element.removeClass('active');\n//            });\n        }\n    };\n});\n\n\n/* UTILITY METHODS */\n\n/**\n * This creates a modal window that auto closes on route change.\n * By default, this is NOT the case, and leads to some funny behaviour.\n *\n * Use this method vs the default $modal({myJson}) approach\n */\nvar _internalCreateModal = function(modalConfig, $modal, $scope) {\n\n    if ($scope !== null && $scope !== undefined) {\n        $scope.modal = $modal(modalConfig);\n\n        $scope.$on('$routeChangeStart', function () {\n            if ($scope.modal) {\n                $scope.modal.hide();\n            }\n        });\n\n        return $scope.modal;\n    } else {\n        return $modal(modalConfig);\n    }\n\n};\n\nflowableModule.\n    directive('numberInputCheck', function() {\n\n        return {\n            require: 'ngModel',\n            link: function(scope, element, attrs, modelCtrl) {\n\n                modelCtrl.$parsers.push(function (inputValue) {\n\n                    var transformedInput;\n                    if (inputValue && inputValue.indexOf('-') == 0) {\n                        transformedInput = inputValue.substr(1).replace(/([^0-9])/g, '');\n                        transformedInput = '-' + transformedInput;\n                    } else {\n                        transformedInput = inputValue.replace(/([^0-9])/g, '');\n                    }\n\n                    if (transformedInput != inputValue) {\n                        modelCtrl.$setViewValue(transformedInput);\n                        modelCtrl.$render();\n                    }\n\n                    return transformedInput;\n                });\n            }\n        };\n    });\n\nflowableModule.\ndirective('decimalNumberInputCheck', function() {\n\n    return {\n        require: 'ngModel',\n        link: function(scope, element, attrs, modelCtrl) {\n\n            modelCtrl.$parsers.push(function (inputValue) {\n\n            \tvar transformedInput = inputValue;\n                var negativeSign = '';                \n\n                if (transformedInput && transformedInput.indexOf('-') == 0) {\n                    negativeSign = '-';\n                    transformedInput = inputValue.substr(1);\n                }\n\n                if(transformedInput && transformedInput.indexOf('.') == 0 ){\n                    transformedInput = \"0\" + transformedInput;\n                }\n\n                if(transformedInput && transformedInput.indexOf('.') > -1){       \n                    var dotIndex = transformedInput.indexOf('.');             \n                    var left = transformedInput.substr(0, dotIndex);\n                    var right = transformedInput.substr(dotIndex+1);\n                    \n                    left = left.replace(/([^0-9])/g, '');\n                    right = right.replace(/([^0-9])/g, '');\n                    transformedInput = negativeSign + left + '.' + right;\n                }\n                else{\n                    transformedInput = negativeSign + transformedInput.replace(/([^0-9])/g, '');\n                }\n\n\n                if (transformedInput != inputValue) {\n                    modelCtrl.$setViewValue(transformedInput);\n                    modelCtrl.$render();\n                }\n\n                return transformedInput;\n            });\n        }\n    };\n});\n"
  },
  {
    "path": "flowable-ui-web/modeler/scripts/common/providers-config.js",
    "content": "/* 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 * Configure the HTTP provider such that no caching happens when fetching\n * a resource using $http.\n */\n\nflowableModule.factory('NotPermittedInterceptor', [ '$q', '$window', function($q, $window) {\n    return {\n        responseError: function ( response ) {\n\n            if (response.status === 403) {\n                $window.location.href = FLOWABLE.CONFIG.contextRoot;\n                $window.location.reload();\n                return $q.reject(response);\n            }\n            else{\n                return $q.reject(response);\n            }\n        }\n    }\n}]);\n\nflowableModule.config(['$httpProvider', function($httpProvider) {\n\n    if (!$httpProvider.defaults.headers.get) {\n        $httpProvider.defaults.headers.get = {};\n    }\n\n    $httpProvider.defaults.headers.get['Cache-Control'] = 'no-cache, no-store, must-revalidate';\n    $httpProvider.defaults.headers.get['Pragma'] = 'no-cache';\n    $httpProvider.defaults.headers.get['Expires'] = '0';\n\n    $httpProvider.interceptors.push('NotPermittedInterceptor');\n\n}]);"
  },
  {
    "path": "flowable-ui-web/modeler/scripts/common/services/recursion-helper.js",
    "content": "/* 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'use strict';\n\n// Recursion Helper service, makes it possible to use nested directives of the same type\nflowableModule.factory('RecursionHelper', ['$compile', function($compile){\n    return {\n        /**\n         * Manually compiles the element, fixing the recursion loop.\n         * @param element\n         * @param [link] A post-link function, or an object with function(s) registered via pre and post properties.\n         * @returns An object containing the linking functions.\n         */\n        compile: function(element, link){\n            // Normalize the link parameter\n            if(angular.isFunction(link)){\n                link = { post: link };\n            }\n\n            // Break the recursion loop by removing the contents\n            var contents = element.contents().remove();\n            var compiledContents;\n            return {\n                pre: (link && link.pre) ? link.pre : null,\n                /**\n                 * Compiles and re-adds the contents\n                 */\n                post: function(scope, element){\n                    // Compile the contents\n                    if(!compiledContents){\n                        compiledContents = $compile(contents);\n                    }\n                    // Re-add the compiled contents to the element\n                    compiledContents(scope, function(clone){\n                        element.append(clone);\n                    });\n\n                    // Call the post-linking function, if any\n                    if(link && link.post){\n                        link.post.apply(null, arguments);\n                    }\n                }\n            };\n        }\n    };\n}]);"
  },
  {
    "path": "flowable-ui-web/modeler/scripts/common/services/resource-service.js",
    "content": "/* 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'use strict';\n\n// User service\nflowableModule.service('ResourceService', ['$http', '$q', 'appResourceRoot',\n    function ($http, $q, appResourceRoot) {\n\n        var loadedResources = {};\n\n        function loadStylesheet(relativeUrl, cache)\n        {\n            var url = appResourceRoot + relativeUrl;\n            if (!cache || !loadedResources[url])\n            {\n                if (cache) {\n                    loadedResources[url] = true;\n                }\n                if (document.createStyleSheet)\n                {\n                    try\n                    {\n                        document.createStyleSheet();\n                    } catch (e) { }\n                }\n                else {\n                    var link = document.createElement(\"link\");\n                    link.rel = \"stylesheet\";\n                    link.type = \"text/css\";\n                    link.media = \"all\";\n                    link.href = url;\n                    document.getElementsByTagName(\"head\")[0].appendChild(link);\n                }\n            }\n        }\n\n        function loadScript(relativeUrl, callback, cache)\n        {\n            var url = appResourceRoot + relativeUrl;\n            if (cache && loadedResources[url] && callback)\n            {\n                callback();\n            }\n            else\n            {\n                if (cache) {\n                    loadedResources[url] = true;\n                }\n\n                // Insert the node so it gets loaded\n                var script = document.createElement(\"script\");\n                script.type=\"text/javascript\";\n                script.src = url;\n\n                if (callback) {\n                    var done = false;\n\n                    // Attach handlers for all browsers\n                    script.onload = script.onreadystatechange = function()\n                    {\n                        if (!done && (!this.readyState || this.readyState == \"loaded\" || this.readyState == \"complete\"))\n                        {\n                            done = true;\n                            callback();\n                        }\n                    };\n                }\n                var el = document.getElementsByTagName(\"head\")[0];\n                el.appendChild(script);\n            }\n        }\n\n        function loadScripts(relativeUrls, callback, cache)\n        {\n            function loadNext()\n            {\n                var relativeUrl = relativeUrls.shift();\n                if (relativeUrl)\n                {\n                    loadScript.call(this, relativeUrl, loadNext.bind(this), cache);\n                }\n                else\n                {\n                    if (callback)\n                    {\n                        callback();\n                    }\n                }\n            }\n            loadNext.call(this);\n        }\n\n        function loadFromHtml(url, callback, cache)\n        {\n            $http.get(url).success(function(responseText)\n            {\n                var xmlDoc;\n                if (window.DOMParser)\n                {\n                    var parser = new DOMParser();\n                    xmlDoc = parser.parseFromString(responseText, \"text/xml\");\n                }\n                else // Internet Explorer\n                {\n                    xmlDoc = new ActiveXObject(\"Microsoft.XMLDOM\");\n                    xmlDoc.async = false;\n                    xmlDoc.loadXML(responseText);\n                }\n                var resources = xmlDoc.getElementsByTagName(\"link\");\n                var resourceUrl;\n                var resourceUrls = [];\n                for (var i = 0, il = resources.length; i < il; i++)\n                {\n                    resourceUrl = resources[i].getAttribute(\"href\");\n                    if (resourceUrl)\n                    {\n                        loadStylesheet(resourceUrl, cache);\n                    }\n                }\n                resources = xmlDoc.getElementsByTagName(\"script\");\n                for (i = 0, il = resources.length; i < il; i++)\n                {\n                    resourceUrl = resources[i].getAttribute(\"src\");\n                    if (resourceUrl)\n                    {\n                        resourceUrls.push(resourceUrl);\n                    }\n                }\n                loadScripts(resourceUrls, callback, cache);\n            });\n        }\n\n        this.loadFromHtml = loadFromHtml;\n        this.loadScript = loadScript;\n        this.loadStylesheet = loadStylesheet;\n    }]);\n"
  },
  {
    "path": "flowable-ui-web/modeler/scripts/configuration/app-definition-toolbar-default-actions.js",
    "content": "/* 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'use strict';\n\nvar APP_DEFINITION_TOOLBAR = {\n    ACTIONS: {\n\n        saveModel: function (services) {\n\n            _internalCreateModal({\n                backdrop: true,\n                keyboard: true,\n                template: 'views/popup/app-definition-save-model.html?version=' + Date.now(),\n                scope: services.$scope\n            }, services.$modal, services.$scope);\n        },\n\n        help: function (services) {\n\n        },\n\n        feedback: function (services) {\n\n        },\n\n        closeEditor:  function (services) {\n        \tservices.$location.path('/apps');\n        }\n    }\n};\n\n/** Custom controller for the save dialog */\nangular.module('flowableModeler').controller('SaveAppDefinitionCtrl',\n    [ '$rootScope', '$scope', '$http', '$route', '$location', '$translate',\n    function ($rootScope, $scope, $http, $route, $location, $translate) {\n\n    var description = '';\n    if ($rootScope.currentAppDefinition.description) {\n    \tdescription = $rootScope.currentAppDefinition.description;\n    }\n\n    var saveDialog = {\n        name: $rootScope.currentAppDefinition.name,\n        key: $rootScope.currentAppDefinition.key,\n        description: description,\n        publish: false\n    };\n\n    $scope.saveDialog = saveDialog;\n\n    $scope.status = {\n        loading: false\n    };\n\n    $scope.cancel = function () {\n    \t$scope.$hide();\n    };\n\n    $scope.saveAndClose = function (force) {\n    \t$scope.save(function() {\n    \t\t$location.path('/apps');\n    \t}, force);\n    };\n\n    $scope.save = function (saveCallback, force) {\n\n        if (!$scope.saveDialog.name || $scope.saveDialog.name.length == 0 ||\n        \t!$scope.saveDialog.key || $scope.saveDialog.key.length == 0) {\n\n            return;\n        }\n\n        // Indicator spinner image\n        $scope.status.loading = true;\n\n        var data = {\n            appDefinition: $rootScope.currentAppDefinition,\n            publish: $scope.saveDialog.publish\n        };\n\n        data.appDefinition.name = $scope.saveDialog.name;\n        if ($scope.saveDialog.description && $scope.saveDialog.description.length > 0) {\n        \tdata.appDefinition.description = $scope.saveDialog.description;\n        }\n\n        if (force !== undefined && force !== null && force === true) {\n            data.force = true;\n        }\n\n        delete $scope.conflict;\n        $http({method: 'PUT', url: FLOWABLE.APP_URL.getAppDefinitionUrl($rootScope.currentAppDefinition.id), data: data}).\n            success(function(response, status, headers, config) {\n                // Regular error\n                if (response.error) {\n                    $scope.status.loading = false;\n                    $scope.saveDialog.errorMessage = response.errorDescription;\n                } else {\n                    $scope.$hide();\n                    $rootScope.addAlert($translate.instant('APP.POPUP.SAVE-APP-SAVE-SUCCESS', 'info'));\n                    if (saveCallback) {\n                        saveCallback();\n                    }\n                }\n\n            }).\n            error(function(data, status, headers, config) {\n                $scope.status.loading = false;\n                $scope.saveDialog.errorMessage = data.message;\n            });\n    };\n\n    $scope.isOkButtonDisabled = function() {\n        if ($scope.status.loading) {\n            return false;\n        } else if ($scope.error && $scope.error.hasCustomStencilItem) {\n            return false;\n        }\n        return true;\n    };\n\n    $scope.okClicked = function() {\n        if ($scope.error) {\n            if ($scope.error.conflictResolveAction === 'discardChanges') {\n                $scope.close();\n                $route.reload();\n            } else if ($scope.error.conflictResolveAction === 'overwrite'\n                || $scope.error.conflictResolveAction === 'newVersion') {\n                $scope.save();\n            } else if($scope.error.conflictResolveAction === 'saveAs') {\n                $scope.save(function() {\n                    $rootScope.ignoreChanges = true;  // Otherwise will get pop up that changes are not saved.\n                    $location.path('/apps');\n                });\n            }\n        }\n    };\n\n}]);\n"
  },
  {
    "path": "flowable-ui-web/modeler/scripts/configuration/app-definition-toolbar.js",
    "content": "/* 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'use strict';\n\nvar APP_DEFINITION_TOOLBAR_CONFIG = {\n    \"items\" : [\n        {\n            \"type\" : \"button\",\n            \"title\" : \"APP_DEFINITION_TOOLBAR.ACTION.SAVE\",\n            \"cssClass\" : \"editor-icon editor-icon-save\",\n            \"action\" : \"APP_DEFINITION_TOOLBAR.ACTIONS.saveModel\"\n        }\n    ],\n    \n    \"secondaryItems\" : [\n\t\t{\n\t\t    \"type\" : \"button\",\n\t\t    \"title\" : \"Close\",\n\t\t    \"cssClass\" : \"glyphicon glyphicon-remove\",\n\t\t    \"action\" : \"APP_DEFINITION_TOOLBAR.ACTIONS.closeEditor\"\n\t\t}\n    ]\n};"
  },
  {
    "path": "flowable-ui-web/modeler/scripts/configuration/decision-table-toolbar-default-actions.js",
    "content": "/* Copyright 2005-2015 Alfresco Software, Ltd.\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'use strict';\n\nvar DECISION_TABLE_TOOLBAR = {\n    ACTIONS: {\n\n        saveModel: function (services) {\n\n            _internalCreateModal({\n                backdrop: true,\n                keyboard: true,\n                template: 'views/popup/decision-table-save-model.html?version=' + Date.now(),\n                scope: services.$scope\n            }, services.$modal, services.$scope);\n        },\n\n        help: function (services) {\n\n        },\n\n        feedback: function (services) {\n\n        },\n\n        closeEditor:  function (services) {\n\n            var callback = function() {\n                services.$rootScope.decisiontableChanges = false;\n                \n                if (services.$rootScope.editorHistory.length > 0) {\n                \tvar navigationObject = services.$rootScope.editorHistory.pop();\n                \tvar additionalParameters = '';\n                \tif (navigationObject.subProcessId && navigationObject.subProcessId.length > 0) {\n                \t\tadditionalParameters = '?subProcessId=' + navigationObject.subProcessId;\n                \t}\n        \t\t\tservices.$location.url('/editor/' + navigationObject.id + additionalParameters);\n        \t\t} else {\n        \t\t\tservices.$location.path('/decision-tables');\n        \t\t}\n            };\n\n            if (services.$rootScope.decisiontableChanges == true) {\n\n                services.$scope.$emit(\"decisionTableChangesEvent\");\n\n                var unbindMustSave = services.$scope.$on(\"mustSaveEvent\", function(){\n                    //save the decision table data\n                    var description = '';\n                    if (services.$rootScope.currentDecisionTable.description) {\n                        description = services.$rootScope.currentDecisionTable.description;\n                    }\n\n                    var data = {\n                        newVersion: false\n                    };\n                    \n                    unbindEvents();\n                    services.DecisionTableBuilderService.saveDecisionTable(data, services.$rootScope.currentDecisionTable.name, \n                    \tnull, description, callback);\n                });\n\n                var unbindDiscardDataEvent = services.$scope.$on(\"discardDataEvent\", function() {\n                    unbindEvents();\n                    callback();\n                });\n\n                var unbindContinueEditingEvent = services.$scope.$on(\"continueEditingEvent\", function () {\n                    unbindEvents();\n                });\n\n            } else {\n                callback();\n            }\n\n            var unbindEvents = function () {\n                unbindContinueEditingEvent();\n                unbindMustSave();\n                unbindDiscardDataEvent();\n            };\n\n        }\n    }\n};\n\n/** Custom controller for the save dialog */\nangular.module('flowableModeler')\n    .controller('SaveDecisionTableCtrl', [ '$rootScope', '$scope', '$http', '$route', '$location', '$translate', 'DecisionTableService', 'hotRegisterer',\n        function ($rootScope, $scope, $http, $route, $location, $translate, DecisionTableService, hotRegisterer) {\n\n            var description = '';\n            if ($rootScope.currentDecisionTableModel.description) {\n                description = $rootScope.currentDecisionTableModel.description;\n            }\n\n            $scope.saveDialog = {\n                name: $rootScope.currentDecisionTableModel.name,\n                key: $rootScope.currentDecisionTableModel.key,\n                description: description,\n                newVersion: false,\n                comment: ''\n            };\n\n            $scope.keyFieldPattern = /^[a-zA-Z_]\\w*$/;\n\n            $scope.status = {\n                loading: false\n            };\n\n            $scope.cancel = function () {\n                $scope.$hide();\n            };\n\n            $scope.saveAndClose = function () {\n                $scope.save(function() {\n                    if ($rootScope.editorHistory.length > 0) {\n\t\t    \t        var navigationObject = $rootScope.editorHistory.pop();\n\t\t    \t        var additionalParameters = '';\n\t                \tif (navigationObject.subProcessId && navigationObject.subProcessId.length > 0) {\n\t                \t\tadditionalParameters = '?subProcessId=' + navigationObject.subProcessId;\n\t                \t}\n\t\t    \t        $location.url('/editor/' + navigationObject.id + additionalParameters);\n\t\t \n\t\t            } else {\n\t\t            \t$location.path('/decision-tables');\n\t\t            }\n                });\n            };\n\n            $scope.save = function (additionalSaveCallback) {\n\n                if (!$scope.saveDialog.name || $scope.saveDialog.name.length == 0 || !$scope.saveDialog.key || $scope.saveDialog.key.length == 0) {\n                    return;\n                }\n\n                // Indicator spinner image\n                $scope.status = {\n                    loading: true\n                };\n\n                var data = {\n                    reusable: $scope.saveDialog.reusable,\n                    newVersion: $scope.saveDialog.newVersion,\n                    comment: $scope.saveDialog.comment\n                };\n\n                $rootScope.currentDecisionTableRules = $scope.model.rulesData;\n\n                var saveCallback = function() {\n                    $scope.$hide();\n                    \n                    $rootScope.currentDecisionTableModel.name = $scope.saveDialog.name;\n                    $rootScope.currentDecisionTableModel.key = $scope.saveDialog.key;\n                    $rootScope.currentDecisionTableModel.description = $scope.saveDialog.description;\n                    \n                    $rootScope.addAlertPromise($translate('DECISION-TABLE-EDITOR.ALERT.SAVE-CONFIRM', {name: $scope.saveDialog.name}), 'info');\n                    \n                    if (additionalSaveCallback) {\n                        additionalSaveCallback();\n                    }\n                    \n                    $rootScope.decisionTableChanges = false;\n                };\n\n                var errorCallback = function(errorMessage) {\n                \t$scope.status.loading = false;\n                    $scope.saveDialog.errorMessage = errorMessage.message;\n                };\n\n                // deselect cells before thumbnail generations\n                var hotDecisionTableEditorInstance = hotRegisterer.getInstance('decision-table-editor');\n                if (hotDecisionTableEditorInstance) {\n                    hotDecisionTableEditorInstance.deselectCell();\n                }\n\n                DecisionTableService.saveDecisionTable(data, $scope.saveDialog.name, $scope.saveDialog.key, \n                \t$scope.saveDialog.description, saveCallback, errorCallback);\n            };\n\n            $scope.isOkButtonDisabled = function() {\n                if ($scope.status.loading) {\n                    return false;\n                } else if ($scope.error && $scope.error.conflictResolveAction) {\n                    if ($scope.error.conflictResolveAction === 'saveAs') {\n                        return !$scope.error.saveAs || $scope.error.saveAs.length == 0;\n                    } else {\n                        return false;\n                    }\n                }\n                return true;\n            };\n\n            $scope.okClicked = function() {\n                if ($scope.error) {\n                    if ($scope.error.conflictResolveAction === 'discardChanges') {\n                        $scope.close();\n                        $route.reload();\n                    } else if ($scope.error.conflictResolveAction === 'overwrite'\n                        || $scope.error.conflictResolveAction === 'newVersion') {\n                        $scope.save();\n                    } else if($scope.error.conflictResolveAction === 'saveAs') {\n                        $scope.save(function() {\n                            $rootScope.ignoreChanges = true;  // Otherwise will get pop up that changes are not saved.\n                            $location.path('/decision-tables');\n                        });\n                    }\n                }\n            };\n\n        }]);\n"
  },
  {
    "path": "flowable-ui-web/modeler/scripts/configuration/decision-table-toolbar.js",
    "content": "/* Copyright 2005-2015 Alfresco Software, Ltd.\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'use strict';\n\nvar DECISION_TABLE_TOOLBAR_CONFIG = {\n    \"items\" : [\n        {\n            \"type\" : \"button\",\n            \"title\" : \"TOOLBAR.ACTION.SAVE\",\n            \"cssClass\" : \"editor-icon editor-icon-save\",\n            \"action\" : \"DECISION_TABLE_TOOLBAR.ACTIONS.saveModel\",\n            \"disableOnReadonly\": true\n        }\n    ],\n    \n    \"secondaryItems\" : [\n\t\t{\n\t\t    \"type\" : \"button\",\n\t\t    \"title\" : \"TOOLBAR.ACTION.CLOSE\",\n\t\t    \"cssClass\" : \"glyphicon glyphicon-remove\",\n\t\t    \"action\" : \"DECISION_TABLE_TOOLBAR.ACTIONS.closeEditor\"\n\t\t}\n    ]\n};"
  },
  {
    "path": "flowable-ui-web/modeler/scripts/configuration/form-builder-toolbar-default-actions.js",
    "content": "/* 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'use strict';\n\nvar FORM_TOOLBAR = {\n    ACTIONS: {\n\n        saveModel: function (services) {\n\n            _internalCreateModal({\n                backdrop: true,\n                keyboard: true,\n                template: 'views/popup/form-save-model.html?version=' + Date.now(),\n                scope: services.$scope\n            }, services.$modal, services.$scope);\n        },\n\n        help: function (services) {\n\n        },\n\n        closeEditor:  function (services) {\n            if (services.$rootScope.editorHistory.length > 0) {\n        \t\tvar callback = function() {\n                    services.$rootScope.formChanges = false;\n\n        \t\t    var navigationObject = services.$rootScope.editorHistory.pop();\n        \t\t    var additionalParameters = '';\n                \tif (navigationObject.subProcessId && navigationObject.subProcessId.length > 0) {\n                \t\tadditionalParameters = '?subProcessId=' + navigationObject.subProcessId;\n                \t}\n        \t\t    services.$location.url('/editor/' + navigationObject.id + additionalParameters);\n        \t\t};\n\n        \t\tif (services.$rootScope.formChanges == true) {\n\n        \t\t    services.$scope.$emit(\"formChangesEvent\");\n\n        \t\t    var unbindMustSave = services.$scope.$on(\"mustSaveEvent\", function(){\n        \t\t        //save the form data\n        \t\t        var description = '';\n        \t\t        if (services.$rootScope.currentForm.description) {\n        \t\t            description = services.$rootScope.currentForm.description;\n        \t\t        }\n\n        \t\t        var data = {\n        \t\t            newVersion: false\n        \t\t        };\n        \t\t        unbindEvents();\n        \t\t        services.FormBuilderService.saveForm(data, services.$rootScope.currentForm.name, description, callback);\n        \t\t    });\n\n        \t\t    var unbindDiscardDataEvent = services.$scope.$on(\"discardDataEvent\", function() {\n        \t\t        unbindEvents();\n        \t\t        callback();\n        \t\t    });\n\n        \t\t    var unbindContinueEditingEvent = services.$scope.$on(\"continueEditingEvent\", function () {\n        \t\t        unbindEvents();\n        \t\t    });\n\n        \t\t} else {\n        \t\t    callback();\n        \t\t}\n\n            } else {\n            \tservices.$location.path('/forms');\n            }\n\n            var unbindEvents = function () {\n                unbindContinueEditingEvent();\n                unbindMustSave();\n                unbindDiscardDataEvent();\n            };\n\n        }\n    }\n};\n\n/** Custom controller for the save dialog */\nangular.module('flowableModeler')\n    .controller('SaveFormCtrl', [ '$rootScope', '$scope', '$http', '$route', '$location', '$translate', 'FormBuilderService',\n                         function ($rootScope, $scope, $http, $route, $location, $translate, FormBuilderService) {\n\n\tvar formKey = '';\n    if ($rootScope.currentForm.key) {\n    \tformKey = $rootScope.currentForm.key;\n    }\n\t\n    var description = '';\n    if ($rootScope.currentForm.description) {\n    \tdescription = $rootScope.currentForm.description;\n    }\n\n    var saveDialog = { name: $rootScope.currentForm.name,\n    \t\tformKey: formKey,\n            description: description,\n            reusable: false,\n            newVersion: false,\n            comment: ''};\n\n    $scope.saveDialog = saveDialog;\n\n    $scope.status = {\n        loading: false\n    };\n\n    $scope.cancel = function () {\n    \t$scope.$hide();\n    };\n\n    $scope.saveAndClose = function () {\n    \t$scope.save(function() {\n    \t    if ($rootScope.editorHistory.length > 0) {\n    \t        var navigationObject = $rootScope.editorHistory.pop();\n    \t        var additionalParameters = '';\n            \tif (navigationObject.subProcessId && navigationObject.subProcessId.length > 0) {\n            \t\tadditionalParameters = '?subProcessId=' + navigationObject.subProcessId;\n            \t}\n    \t        $location.url('/editor/' + navigationObject.id + additionalParameters);\n \n            } else {\n            \t$location.path('/forms');\n            }\n    \t});\n    };\n\n    $scope.save = function (additionalSaveCallback) {\n\n        if (!$scope.saveDialog.name || $scope.saveDialog.name.length == 0 ||\n        \t!$scope.saveDialog.formKey || $scope.saveDialog.formKey.length == 0) {\n        \t\n            return;\n        }\n\n        // Indicator spinner image\n        $scope.status = {\n        \tloading: true\n        };\n\n        var data = {\n        \treusable: $scope.saveDialog.reusable,\n        \tnewVersion: $scope.saveDialog.newVersion,\n        \tcomment: $scope.saveDialog.comment\n        };\n\n        var saveCallback = function() {\n            $scope.$hide();\n            // TODO: i18n\n            $rootScope.addAlert(\"Saved form '\" + $scope.saveDialog.name, 'info');\n            if (additionalSaveCallback) {\n                additionalSaveCallback();\n            }\n\n            $rootScope.formChanges = false;\n        };\n\n        var errorCallback = function(errorMessage) {\n        \t$scope.status.loading = false;\n            $scope.saveDialog.errorMessage = errorMessage.message;\n        };\n\n        FormBuilderService.saveForm(data, $scope.saveDialog.name, $scope.saveDialog.formKey, \n        \t$scope.saveDialog.description, saveCallback, errorCallback);\n    };\n\n    $scope.isOkButtonDisabled = function() {\n        if ($scope.status.loading) {\n            return false;\n        } else if ($scope.error && $scope.error.conflictResolveAction) {\n            if ($scope.error.conflictResolveAction === 'saveAs') {\n                return !$scope.error.saveAs || $scope.error.saveAs.length == 0;\n            } else {\n                return false;\n            }\n        }\n        return true;\n    };\n\n    $scope.okClicked = function() {\n        if ($scope.error) {\n            if ($scope.error.conflictResolveAction === 'discardChanges') {\n                $scope.close();\n                $route.reload();\n            } else if ($scope.error.conflictResolveAction === 'overwrite'\n                || $scope.error.conflictResolveAction === 'newVersion') {\n                $scope.save();\n            } else if($scope.error.conflictResolveAction === 'saveAs') {\n                $scope.save(function() {\n                    $rootScope.ignoreChanges = true;  // Otherwise will get pop up that changes are not saved.\n                    if ($rootScope.editorHistory.length > 0) {\n                        var navigationObject = $rootScope.editorHistory.pop();\n                        var additionalParameters = '';\n\t\t            \tif (navigationObject.subProcessId && navigationObject.subProcessId.length > 0) {\n\t\t            \t\tadditionalParameters = '?subProcessId=' + navigationObject.subProcessId;\n\t\t            \t}\n                        $location.url('/editor/' + navigationObject.id + additionalParameters);\n                        \n                    } else {\n                    \t$location.path('/forms');\n                    }\n                });\n            }\n        }\n    };\n\n}]);\n"
  },
  {
    "path": "flowable-ui-web/modeler/scripts/configuration/form-builder-toolbar.js",
    "content": "/* 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'use strict';\n\nvar FORM_TOOLBAR_CONFIG = {\n    \"items\" : [\n        {\n            \"type\" : \"button\",\n            \"title\" : \"FORM_TOOLBAR.ACTION.SAVE\",\n            \"cssClass\" : \"editor-icon editor-icon-save\",\n            \"action\" : \"FORM_TOOLBAR.ACTIONS.saveModel\"\n        }\n    ],\n    \n    \"secondaryItems\" : [\n\t\t{\n\t\t    \"type\" : \"button\",\n\t\t    \"title\" : \"Close\",\n\t\t    \"cssClass\" : \"glyphicon glyphicon-remove\",\n\t\t    \"action\" : \"FORM_TOOLBAR.ACTIONS.closeEditor\"\n\t\t}\n    ]\n};"
  },
  {
    "path": "flowable-ui-web/modeler/scripts/configuration/url-config.js",
    "content": "/* 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 */\nvar FLOWABLE = FLOWABLE || {};\n\n/*\n * Contains methods to retrieve the (mostly) base urls of the different end points.\n * Two of the methods #getImageUrl and #getModelThumbnailUrl are exposed in the $rootScope for usage in the HTML views.\n */\nFLOWABLE.APP_URL = {\n\n    /* ACCOUNT URLS */\n\n    getAccountUrl: function () {\n        return FLOWABLE.CONFIG.contextRoot + '/app/rest/account';\n    },\n\n    getLogoutUrl: function () {\n        return FLOWABLE.CONFIG.contextRoot + '/app/logout';\n    },\n\n    /* MODEL URLS */\n\n    getModelsUrl: function (query) {\n        return FLOWABLE.CONFIG.contextRoot + '/app/rest/models' + (query || \"\");\n    },\n\n    getModelUrl: function (modelId) {\n        return FLOWABLE.CONFIG.contextRoot + '/app/rest/models/' + modelId;\n    },\n\n    getModelModelJsonUrl: function (modelId) {\n        return FLOWABLE.CONFIG.contextRoot + '/app/rest/models/' + modelId + '/model-json';\n    },\n\n    getModelBpmn20ExportUrl: function (modelId) {\n        return FLOWABLE.CONFIG.contextRoot + '/app/rest/models/' + modelId + '/bpmn20?version=' + Date.now();\n    },\n\n    getCloneModelsUrl: function (modelId) {\n        return FLOWABLE.CONFIG.contextRoot + '/app/rest/models/' + modelId + '/clone';\n    },\n\n    getModelHistoriesUrl: function (modelId) {\n        return FLOWABLE.CONFIG.contextRoot + '/app/rest/models/' + modelId + '/history';\n    },\n\n    getModelHistoryUrl: function (modelId, modelHistoryId) {\n        return FLOWABLE.CONFIG.contextRoot + '/app/rest/models/' + modelId + '/history/' + modelHistoryId;\n    },\n\n    getModelHistoryModelJsonUrl: function (modelId, modelHistoryId) {\n        return FLOWABLE.CONFIG.contextRoot + '/app/rest/models/' + modelId + '/history/' + modelHistoryId + '/model-json';\n    },\n\n    getModelHistoryBpmn20ExportUrl: function (modelId, modelHistoryId) {\n        return FLOWABLE.CONFIG.contextRoot + '/app/rest/models/' + modelId + '/history/' + modelHistoryId + '/bpmn20?version=' + Date.now();\n    },\n\n    getCmmnModelDownloadUrl: function (modelId, modelHistoryId) {\n        return FLOWABLE.CONFIG.contextRoot + '/app/rest/models/' + modelId + (modelHistoryId ? '/history/' + modelHistoryId : '') + '/cmmn?version=' + Date.now();\n    },\n\n    getModelParentRelationsUrl: function (modelId) {\n        return FLOWABLE.CONFIG.contextRoot + '/app/rest/models/' + modelId + '/parent-relations';\n    },\n\n    /* APP DEFINITION URLS  */\n\n    getAppDefinitionImportUrl: function (renewIdmIds) {\n        return FLOWABLE.CONFIG.contextRoot + '/app/rest/app-definitions/import?renewIdmEntries=' + renewIdmIds;\n    },\n\n    getAppDefinitionTextImportUrl: function (renewIdmIds) {\n        return FLOWABLE.CONFIG.contextRoot + '/app/rest/app-definitions/text/import?renewIdmEntries=' + renewIdmIds;\n    },\n\n    getAppDefinitionUrl: function (modelId) {\n        return FLOWABLE.CONFIG.contextRoot + '/app/rest/app-definitions/' + modelId;\n    },\n\n    getAppDefinitionModelImportUrl: function (modelId, renewIdmIds) {\n        return FLOWABLE.CONFIG.contextRoot + '/app/rest/app-definitions/' + modelId + '/import?renewIdmEntries=' + renewIdmIds;\n    },\n\n    getAppDefinitionModelTextImportUrl: function (modelId, renewIdmIds) {\n        return FLOWABLE.CONFIG.contextRoot + '/app/rest/app-definitions/' + modelId + '/text/import?renewIdmEntries=' + renewIdmIds;\n    },\n\n    getAppDefinitionPublishUrl: function (modelId) {\n        return FLOWABLE.CONFIG.contextRoot + '/app/rest/app-definitions/' + modelId + '/publish';\n    },\n\n    getAppDefinitionExportUrl: function (modelId) {\n        return FLOWABLE.CONFIG.contextRoot + '/app/rest/app-definitions/' + modelId + '/export?version=' + Date.now();\n    },\n\n    getAppDefinitionBarExportUrl: function (modelId) {\n        return FLOWABLE.CONFIG.contextRoot + '/app/rest/app-definitions/' + modelId + '/export-bar?version=' + Date.now();\n    },\n\n    getAppDefinitionHistoryUrl: function (modelId, historyModelId) {\n        return FLOWABLE.CONFIG.contextRoot + '/app/rest/app-definitions/' + modelId + '/history/' + historyModelId;\n    },\n\n    getModelsForAppDefinitionUrl: function () {\n        return FLOWABLE.CONFIG.contextRoot + '/app/rest/models-for-app-definition';\n    },\n\n    getCmmnModelsForAppDefinitionUrl: function () {\n        return FLOWABLE.CONFIG.contextRoot + '/app/rest/cmmn-models-for-app-definition';\n    },\n\n    /* PROCESS INSTANCE URLS */\n\n    getProcessInstanceModelJsonUrl: function (modelId) {\n        return FLOWABLE.CONFIG.contextRoot + '/app/rest/process-instances/' + modelId + '/model-json';\n    },\n\n    getProcessInstanceModelJsonHistoryUrl: function (historyModelId) {\n        return FLOWABLE.CONFIG.contextRoot + '/app/rest/process-instances/history/' + historyModelId + '/model-json';\n    },\n\n    /* PROCESS DEFINITION URLS */\n\n    getProcessDefinitionModelJsonUrl: function (processDefinitionId) {\n        return FLOWABLE.CONFIG.contextRoot + '/app/rest/process-definitions/' + processDefinitionId + '/model-json';\n    },\n\n    /* PROCESS MODEL URLS */\n\n    getImportProcessModelUrl: function () {\n        return FLOWABLE.CONFIG.contextRoot + '/app/rest/import-process-model';\n    },\n\n    getImportProcessModelTextUrl: function () {\n        return FLOWABLE.CONFIG.contextRoot + '/app/rest/import-process-model/text';\n    },\n\n    /* DECISION TABLE URLS */\n\n    getDecisionTableModelsUrl: function () {\n        return FLOWABLE.CONFIG.contextRoot + '/app/rest/decision-table-models';\n    },\n\n    getDecisionTableImportUrl: function () {\n        return FLOWABLE.CONFIG.contextRoot + '/app/rest/decision-table-models/import-decision-table';\n    },\n\n    getDecisionTableTextImportUrl: function () {\n        return FLOWABLE.CONFIG.contextRoot + '/app/rest/decision-table-models/import-decision-table-text';\n    },\n\n    getDecisionTableModelUrl: function (modelId) {\n        return FLOWABLE.CONFIG.contextRoot + '/app/rest/decision-table-models/' + modelId;\n    },\n\n    getDecisionTableModelValuesUrl: function (query) {\n        return FLOWABLE.CONFIG.contextRoot + '/app/rest/decision-table-models/values?' + query;\n    },\n\n    getDecisionTableModelsHistoryUrl: function (modelHistoryId) {\n        return FLOWABLE.CONFIG.contextRoot + '/app/rest/decision-table-models/history/' + modelHistoryId;\n    },\n\n    getDecisionTableModelHistoryUrl: function (modelId, modelHistoryId) {\n        return FLOWABLE.CONFIG.contextRoot + '/app/rest/decision-table-models/' + modelId + '/history/' + modelHistoryId;\n    },\n\n    /* FORM MODEL URLS */\n\n    getFormModelsUrl: function () {\n        return FLOWABLE.CONFIG.contextRoot + '/app/rest/form-models';\n    },\n\n    getFormModelValuesUrl: function (query) {\n        return FLOWABLE.CONFIG.contextRoot + '/app/rest/form-models/values?' + query;\n    },\n\n    getFormModelUrl: function (modelId) {\n        return FLOWABLE.CONFIG.contextRoot + '/app/rest/form-models/' + modelId;\n    },\n\n    getFormModelHistoryUrl: function (modelId, modelHistoryId) {\n        return FLOWABLE.CONFIG.contextRoot + '/app/rest/form-models/' + modelId + '/history/' + modelHistoryId;\n    },\n\n    /* CASE MODEL URLS */\n\n    getCaseModelsUrl: function (query) {\n        return FLOWABLE.CONFIG.contextRoot + '/app/rest/case-models' + (query || \"\");\n    },\n\n    getCaseModelImportUrl: function () {\n        return FLOWABLE.CONFIG.contextRoot + '/app/rest/import-case-model';\n    },\n\n    getCaseModelTextImportUrl: function () {\n        return FLOWABLE.CONFIG.contextRoot + '/app/rest/import-case-model/text';\n    },\n\n    getCaseInstancesHistoryModelJsonUrl: function (modelHistoryId) {\n        return FLOWABLE.CONFIG.contextRoot + '/app/rest/case-instances/history/' + modelHistoryId + '/model-json';\n    },\n\n    getCaseInstancesModelJsonUrl: function (modelId) {\n        return FLOWABLE.CONFIG.contextRoot + '/app/rest/case-instances/' + modelId + '/model-json';\n    },\n\n    getCaseDefinitionModelJsonUrl: function (caseDefinitionId) {\n        return FLOWABLE.CONFIG.contextRoot + '/app/rest/case-definitions/' + caseDefinitionId + '/model-json';\n    },\n\n    /* IMAGE URLS (exposed in rootscope in app.js */\n\n    getImageUrl: function (imageId) {\n        return FLOWABLE.CONFIG.contextRoot + '/app/rest/image/' + imageId;\n    },\n\n    getModelThumbnailUrl: function (modelId, version) {\n        return FLOWABLE.CONFIG.contextRoot + '/app/rest/models/' + modelId + '/thumbnail' + (version ? \"?version=\" + version : \"\");\n    },\n\n    /* OTHER URLS */\n\n    getEditorUsersUrl: function () {\n        return FLOWABLE.CONFIG.contextRoot + '/app/rest/editor-users';\n    },\n\n    getEditorGroupsUrl: function () {\n        return FLOWABLE.CONFIG.contextRoot + '/app/rest/editor-groups';\n    },\n\n    getAboutInfoUrl: function () {\n        return FLOWABLE.CONFIG.contextRoot + '/app/rest/about-info';\n    }\n\n};\n"
  },
  {
    "path": "flowable-ui-web/modeler/scripts/controllers/app-definition-builder.js",
    "content": "/* 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 */\nangular.module('flowableModeler')\n  .controller('AppDefinitionBuilderController', ['$rootScope', '$scope', '$translate', '$http', '$location', '$routeParams', '$modal', '$popover', '$timeout', \n                              function ($rootScope, $scope, $translate, $http, $location, $routeParams, $modal, $popover, $timeout) {\n\n    // Main page (needed for visual indicator of current page)\n    $rootScope.setMainPageById('apps');\n    \n    // Initialize model\n    $scope.model = {\n        // Store the main model id, this points to the current version of a model,\n        // even when we're showing history\n        latestModelId: $routeParams.modelId\n    };\n    \n    $scope.appBuilder = {\n        activeTab: 'bpmn'\n    };\n    \n    $scope.tabs = [\n        {\n            id: 'bpmn',\n            title: 'BPMN models'\n        },\n        {\n            id: 'cmmn',\n            title: 'CMMN models'\n        }\n    ];\n    \n    $scope.loadApp = function() {\n    \t$http({method: 'GET', url: FLOWABLE.APP_URL.getAppDefinitionUrl($routeParams.modelId)}).\n        \tsuccess(function(data, status, headers, config) {\n        \t    $rootScope.currentAppDefinition = data;\n        \t    if (!$rootScope.currentAppDefinition.definition.theme) {\n        \t        $rootScope.currentAppDefinition.definition.theme = 'theme-1';\n        \t    }\n                if (!$rootScope.currentAppDefinition.definition.icon) {\n                    $rootScope.currentAppDefinition.definition.icon = 'glyphicon-asterisk';\n                }\n\n        \t}).error(function(data, status, headers, config) {\n        \t\tconsole.log(\"Error loading model\");\n        \t});\n    };\n\n    // Cleanup app definition on rootscope when scope is destroyed\n    $scope.$on('$destroy', function() {\n        $rootScope.currentAppDefinition = undefined;\n    });\n    \n    $scope.editIncludedModels = function() {\n        _internalCreateModal({\n            template: 'views/popup/app-definition-models-included.html?version=' + Date.now(),\n            scope: $scope\n        }, $modal, $scope);\n    };\n\n    $scope.availableIcons = [\n        'glyphicon-asterisk', 'glyphicon-plus',\n        'glyphicon-euro', 'glyphicon-cloud', 'glyphicon-envelope',\n        'glyphicon-pencil', 'glyphicon-glass', 'glyphicon-music',\n        'glyphicon-search', 'glyphicon-heart', 'glyphicon-star',\n        'glyphicon-star-empty', 'glyphicon-user', 'glyphicon-film',\n        'glyphicon-th-large', 'glyphicon-th', 'glyphicon-th-list',\n        'glyphicon-ok', 'glyphicon-remove', 'glyphicon-zoom-in',\n        'glyphicon-zoom-out', 'glyphicon-off', 'glyphicon-signal',\n        'glyphicon-cog', 'glyphicon-trash', 'glyphicon-home',\n        'glyphicon-file', 'glyphicon-time', 'glyphicon-road',\n        'glyphicon-download-alt', 'glyphicon-download',\n        'glyphicon-upload', 'glyphicon-inbox', 'glyphicon-play-circle',\n        'glyphicon-repeat', 'glyphicon-refresh', 'glyphicon-list-alt',\n        'glyphicon-lock', 'glyphicon-flag', 'glyphicon-headphones',\n        'glyphicon-volume-up', 'glyphicon-tag', 'glyphicon-tags',\n        'glyphicon-book', 'glyphicon-bookmark', 'glyphicon-print',\n        'glyphicon-camera', 'glyphicon-list', 'glyphicon-facetime-video',\n        'glyphicon-picture', 'glyphicon-map-marker', 'glyphicon-adjust',\n        'glyphicon-tint', 'glyphicon-edit', 'glyphicon-share',\n        'glyphicon-check', 'glyphicon-move', 'glyphicon-play',\n        'glyphicon-eject', 'glyphicon-plus-sign', 'glyphicon-minus-sign',\n        'glyphicon-remove-sign', 'glyphicon-ok-sign',\n        'glyphicon-question-sign', 'glyphicon-info-sign',\n        'glyphicon-screenshot', 'glyphicon-remove-circle',\n        'glyphicon-ok-circle', 'glyphicon-ban-circle',\n        'glyphicon-share-alt', 'glyphicon-exclamation-sign',\n        'glyphicon-gift', 'glyphicon-leaf', 'glyphicon-fire',\n        'glyphicon-eye-open', 'glyphicon-eye-close',\n        'glyphicon-warning-sign', 'glyphicon-plane',\n        'glyphicon-calendar', 'glyphicon-random', 'glyphicon-comment',\n        'glyphicon-magnet', 'glyphicon-retweet',\n        'glyphicon-shopping-cart', 'glyphicon-folder-close',\n        'glyphicon-folder-open', 'glyphicon-hdd', 'glyphicon-bullhorn',\n        'glyphicon-bell', 'glyphicon-certificate', 'glyphicon-thumbs-up',\n        'glyphicon-thumbs-down', 'glyphicon-hand-left',\n        'glyphicon-globe', 'glyphicon-wrench', 'glyphicon-tasks',\n        'glyphicon-filter', 'glyphicon-briefcase', 'glyphicon-dashboard',\n        'glyphicon-paperclip', 'glyphicon-heart-empty', 'glyphicon-link',\n        'glyphicon-phone', 'glyphicon-pushpin', 'glyphicon-usd',\n        'glyphicon-gbp', 'glyphicon-sort', 'glyphicon-flash',\n        'glyphicon-record', 'glyphicon-save', 'glyphicon-open',\n        'glyphicon-saved', 'glyphicon-send', 'glyphicon-floppy-disk',\n        'glyphicon-credit-card', 'glyphicon-cutlery',\n        'glyphicon-earphone', 'glyphicon-phone-alt', 'glyphicon-tower',\n        'glyphicon-stats', 'glyphicon-cloud-download',\n        'glyphicon-cloud-upload', 'glyphicon-tree-conifer',\n        'glyphicon-tree-deciduous' \n    ];\n    \n    // TODO: add themes and perhaps have colors inside JS instead of different css-classes for each theme\n    $scope.availableThemes = [\n        'theme-1', 'theme-2', 'theme-3',\n        'theme-4', 'theme-5', 'theme-6',\n        'theme-7', 'theme-8', 'theme-9',\n        'theme-10'\n    ];\n    \n    $scope.changeIcon = function($event) {\n      if (!$scope.changeIconState) {\n        var state = {};\n        $scope.changeIconState = state;\n        \n        // Create popover\n        state.popover = $popover(angular.element($event.currentTarget), {\n          template: 'views/popover/select-app-icon.html',\n          placement: 'bottom-left',\n          show: true,\n          scope: $scope\n        });\n        \n        var destroy = function() {\n          state.popover.destroy();\n          delete $scope.changeIconState;\n        };\n        \n        // When popup is hidden or scope is destroyed, hide popup\n        state.popover.$scope.$on('tooltip.hide', destroy);\n        $scope.$on('$destroy', destroy);\n      }\n    };\n    \n    $scope.selectIcon = function(icon) {\n        $rootScope.currentAppDefinition.definition.icon = icon;\n    };\n    \n    $scope.changeTheme = function($event) {\n      if(!$scope.changeThemeState) {\n        var state = {};\n        $scope.changeThemeState = state;\n        \n        // Create popover\n        state.popover = $popover(angular.element($event.currentTarget), {\n          template: 'views/popover/select-app-theme.html',\n          placement: 'bottom-left',\n          show: true,\n          scope: $scope\n        });\n        \n        var destroy = function() {\n          state.popover.destroy();\n          delete $scope.changeThemeState;\n        };\n        \n        // When popup is hidden or scope is destroyed, hide popup\n        state.popover.$scope.$on('tooltip.hide', destroy);\n        $scope.$on('$destroy', destroy);\n      }\n    };\n    \n    $scope.selectTheme = function(theme) {\n        $rootScope.currentAppDefinition.definition.theme = theme;\n    };\n    \n    $scope.loadApp();\n}]);\n\nangular.module('flowableModeler')\n.controller('ModelsIncludedPopupCtrl', ['$rootScope', '$scope', '$translate', '$http', '$timeout', '$location', function ($rootScope, $scope, $translate, $http, $timeout, $location) {\n\n    $scope.popup = {\n        loading: false,\n        selectedModels: [],\n        selectedCmmnModels: [],\n        activeTab: 'bpmn'\n    };\n    \n    if ($rootScope.currentAppDefinition.definition.models) {\n        for (var i = 0; i < $rootScope.currentAppDefinition.definition.models.length; i++) {\n            $scope.popup.selectedModels.push($rootScope.currentAppDefinition.definition.models[i].id);\n        }\n    }\n    \n    if ($rootScope.currentAppDefinition.definition.cmmnModels) {\n        for (var i = 0; i < $rootScope.currentAppDefinition.definition.cmmnModels.length; i++) {\n            $scope.popup.selectedCmmnModels.push($rootScope.currentAppDefinition.definition.cmmnModels[i].id);\n        }\n    }\n    \n    $scope.tabs = [\n        {\n            id: 'bpmn',\n            title: 'BPMN models'\n        },\n        {\n            id: 'cmmn',\n            title: 'CMMN models'\n        }\n    ];\n    \n    $scope.loadModels = function() {\n        $scope.popup.loading = true;\n        \n        $http({method: 'GET', url: FLOWABLE.APP_URL.getModelsForAppDefinitionUrl()}).\n          success(function(data, status, headers, config) {\n              $scope.popup.models = data;\n              $scope.popup.loading = false;\n          }).\n          error(function(data, status, headers, config) {\n             $scope.popup.loading = false;\n          });\n          \n        $http({method: 'GET', url: FLOWABLE.APP_URL.getCmmnModelsForAppDefinitionUrl()}).\n          success(function(data, status, headers, config) {\n              $scope.popup.cmmnModels = data;\n              $scope.popup.loading = false;\n          }).\n          error(function(data, status, headers, config) {\n             $scope.popup.loading = false;\n          });\n    };\n    \n    $scope.selectModel = function(model) {\n        var index = $scope.popup.selectedModels.indexOf(model.id);\n        if (index >= 0) {\n            $scope.popup.selectedModels.splice(index, 1);\n        } else {\n            $scope.popup.selectedModels.push(model.id);\n        }\n        \n        var modelArray = [];\n        for (var i = 0; i < $scope.popup.models.data.length; i++) {\n            if ($scope.popup.selectedModels.indexOf($scope.popup.models.data[i].id) >= 0) {\n                var selectedModel = $scope.popup.models.data[i];\n                var summaryModel = {\n                    id: selectedModel.id,\n                    name: selectedModel.name,\n                    version: selectedModel.version,\n                    modelType: selectedModel.modelType,\n                    description: selectedModel.description,\n                    stencilSetId: selectedModel.stencilSet,\n                    createdByFullName: selectedModel.createdByFullName,\n                    createdBy: selectedModel.createdBy,\n                    lastUpdatedByFullName: selectedModel.lastUpdatedByFullName,\n                    lastUpdatedBy: selectedModel.lastUpdatedBy,\n                    lastUpdated: selectedModel.lastUpdated\n                };\n                modelArray.push(summaryModel);\n            }\n        }\n        $rootScope.currentAppDefinition.definition.models = modelArray;\n    };\n    \n    $scope.selectCmmnModel = function(model) {\n        var index = $scope.popup.selectedCmmnModels.indexOf(model.id);\n        if (index >= 0) {\n            $scope.popup.selectedCmmnModels.splice(index, 1);\n        } else {\n            $scope.popup.selectedCmmnModels.push(model.id);\n        }\n        \n        var modelArray = [];\n        for (var i = 0; i < $scope.popup.cmmnModels.data.length; i++) {\n            if ($scope.popup.selectedCmmnModels.indexOf($scope.popup.cmmnModels.data[i].id) >= 0) {\n                var selectedModel = $scope.popup.cmmnModels.data[i];\n                var summaryModel = {\n                    id: selectedModel.id,\n                    name: selectedModel.name,\n                    version: selectedModel.version,\n                    modelType: selectedModel.modelType,\n                    description: selectedModel.description,\n                    stencilSetId: selectedModel.stencilSet,\n                    createdByFullName: selectedModel.createdByFullName,\n                    createdBy: selectedModel.createdBy,\n                    lastUpdatedByFullName: selectedModel.lastUpdatedByFullName,\n                    lastUpdatedBy: selectedModel.lastUpdatedBy,\n                    lastUpdated: selectedModel.lastUpdated\n                };\n                modelArray.push(summaryModel);\n            }\n        }\n        $rootScope.currentAppDefinition.definition.cmmnModels = modelArray;\n    };\n    \n    $scope.isModelSelected = function(model) {\n        if ($scope.popup.selectedModels.indexOf(model.id) >= 0) {\n            return true;\n        } else {\n            return false;\n        }\n    };\n    \n    $scope.isCmmnModelSelected = function(model) {\n        if ($scope.popup.selectedCmmnModels.indexOf(model.id) >= 0) {\n            return true;\n        } else {\n            return false;\n        }\n    };\n    \n    $scope.close = function() {\n        $scope.$hide();\n    };\n    \n    $scope.loadModels();\n}]);\n"
  },
  {
    "path": "flowable-ui-web/modeler/scripts/controllers/app-definition-toolbar-controller.js",
    "content": "/* 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 */\nangular.module('flowableModeler')\n    .controller('AppDefinitionToolbarController', ['$scope', '$http', '$modal', '$q', '$rootScope', '$translate', '$location', function ($scope, $http, $modal, $q, $rootScope, $translate, $location) {\n\n    \tvar toolbarItems = APP_DEFINITION_TOOLBAR_CONFIG.items;\n        $scope.items = [];\n        \n        for (var i = 0; i < toolbarItems.length; i++)\n        {\n        \t$scope.items.push(toolbarItems[i]);\n        }\n        \n        $scope.secondaryItems = APP_DEFINITION_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        \n        // Click handler for secondary toolbar buttons\n        $scope.toolbarSecondaryButtonClicked = function(buttonIndex) {\n            var buttonClicked = $scope.secondaryItems[buttonIndex];\n            var services = { '$scope' : $scope, '$rootScope' : $rootScope, '$http' : $http, '$modal' : $modal, '$q' : $q, '$translate' : $translate, '$location': $location};\n            executeFunctionByName(buttonClicked.action, window, services);\n        };\n}]);"
  },
  {
    "path": "flowable-ui-web/modeler/scripts/controllers/app-definition.js",
    "content": "/* 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 */\nangular.module('flowableModeler')\n  .controller('AppDefinitionCtrl', ['$rootScope', '$scope', '$translate', '$http', '$location', '$routeParams', '$modal', '$popover', '$timeout',\n                              function ($rootScope, $scope, $translate, $http, $location, $routeParams, $modal, $popover, $timeout) {\n\n    // Main page (needed for visual indicator of current page)\n    $rootScope.setMainPageById('apps');\n\n    // Initialize model\n    $scope.model = {\n        // Store the main model id, this points to the current version of a model,\n        // even when we're showing history\n        latestModelId: $routeParams.modelId,\n        activeTab: 'bpmn'\n    };\n    \n    $scope.tabs = [\n        {\n            id: 'bpmn',\n            title: 'BPMN models'\n        },\n        {\n            id: 'cmmn',\n            title: 'CMMN models'\n        }\n    ];\n\n    $scope.loadApp = function() {\n    \tvar url;\n    \tvar definitionUrl;\n\n    \tif ($routeParams.modelHistoryId) {\n    \t\turl = FLOWABLE.APP_URL.getModelHistoryUrl($routeParams.modelId, $routeParams.modelHistoryId);\n    \t\tdefinitionUrl = FLOWABLE.APP_URL.getAppDefinitionHistoryUrl($routeParams.modelId, $routeParams.modelHistoryId);\n    \t} else {\n    \t\turl = FLOWABLE.APP_URL.getModelUrl($routeParams.modelId);\n    \t\tdefinitionUrl = FLOWABLE.APP_URL.getAppDefinitionUrl($routeParams.modelId);\n\n    \t\t$scope.model.appExportUrl = FLOWABLE.APP_URL.getAppDefinitionExportUrl($routeParams.modelId);\n\n    \t\t$scope.model.appBarExportUrl = FLOWABLE.APP_URL.getAppDefinitionBarExportUrl($routeParams.modelId);\n    \t}\n\n    \t$http({method: 'GET', url: url}).\n        \tsuccess(function(data, status, headers, config) {\n        \t\t$scope.model.app = data;\n        \t\t$scope.loadVersions();\n\n        \t}).error(function(data, status, headers, config) {\n        \t\t$scope.returnToList();\n        \t});\n\n    \t$http({method: 'GET', url: definitionUrl}).\n            success(function(data, status, headers, config) {\n                $scope.model.appDefinition = data;\n            });\n    };\n\n    $scope.useAsNewVersion = function() {\n        _internalCreateModal({\n    \t\ttemplate: 'views/popup/model-use-as-new-version.html',\n    \t\tscope: $scope\n    \t}, $modal, $scope);\n    };\n\n    $scope.loadVersions = function() {\n\n      var params = {\n        includeLatestVersion: !$scope.model.app.latestVersion\n      };\n\n      $http({method: 'GET', url: FLOWABLE.APP_URL.getModelHistoriesUrl($scope.model.latestModelId), params: params}).\n\t      success(function(data, status, headers, config) {\n\t        if ($scope.model.app.latestVersion) {\n\t          if (!data.data) {\n\t            data.data = [];\n\t          }\n\t          data.data.unshift($scope.model.app);\n\t        }\n\n\t        $scope.model.versions = data;\n\t      });\n    };\n\n    $scope.showVersion = function(version) {\n      if (version) {\n        if (version.latestVersion) {\n            $location.path(\"/apps/\" +  $scope.model.latestModelId);\n        } else {\n          // Show latest version, no history-suffix needed in URL\n          $location.path(\"/apps/\" +  $scope.model.latestModelId + \"/history/\" + version.id);\n        }\n      }\n    };\n\n    $scope.returnToList = function() {\n        $location.path(\"/apps/\");\n    };\n\n    $scope.openEditor = function() {\n        $location.path(\"/app-editor/\" + $scope.model.latestModelId);\n    };\n\n    $scope.editApp = function() {\n        _internalCreateModal({\n    \t\ttemplate: 'views/popup/model-edit.html',\n\t        scope: $scope\n    \t}, $modal, $scope);\n    };\n\n    $scope.duplicateApp = function () {\n      var modalInstance = _internalCreateModal({\n          template: 'views/popup/app-definition-duplicate.html?version=' + Date.now()\n      }, $modal, $scope);\n\n      modalInstance.$scope.originalModel = $scope.model;\n    };\n\n\n    $scope.deleteApp = function() {\n        // User is owner of the app definition and the app definition is deployed\n        /*_internalCreateModal({\n            template: 'views/popup/app-definition-delete.html?version=' + Date.now(),\n            scope: $scope\n        }, $modal, $scope);*/\n\n      \t_internalCreateModal({\n            template: 'views/popup/model-delete.html?version=' + Date.now(),\n            scope: $scope\n        }, $modal, $scope);\n    };\n\n    $scope.publish = function() {\n        _internalCreateModal({\n            template: 'views/popup/app-definition-publish.html?version=' + Date.now(),\n            scope: $scope\n        }, $modal, $scope);\n    };\n\n    $scope.shareApp = function() {\n        _internalCreateModal({\n    \t\ttemplate: 'views/popup/model-share.html?version=' + Date.now(),\n    \t\tscope: $scope\n    \t}, $modal, $scope);\n    };\n\n    $scope.importAppDefinition = function () {\n        _internalCreateModal({\n            template: 'views/popup/app-definition-import.html?version=' + Date.now(),\n            scope: $scope\n        }, $modal, $scope);\n    };\n\n      $scope.toggleHistory = function($event) {\n        if(!$scope.historyState) {\n          var state = {};\n          $scope.historyState = state;\n\n          // Create popover\n          state.popover = $popover(angular.element($event.target), {\n            template: 'views/popover/history.html',\n            placement: 'bottom-right',\n            show: true,\n            scope: $scope,\n            container: 'body'\n          });\n\n          var destroy = function() {\n            state.popover.destroy();\n            delete $scope.historyState;\n          };\n\n          // When popup is hidden or scope is destroyed, hide popup\n          state.popover.$scope.$on('tooltip.hide', destroy);\n          $scope.$on('$destroy', destroy);\n        }\n      };\n\n    $scope.loadApp();\n}]);\n\nangular.module('flowableModeler')\n.controller('PublishAppDefinitionPopupCtrl', ['$rootScope', '$scope', '$http', '$route', '$translate', function ($rootScope, $scope, $http, $route, $translate) {\n\n    $scope.popup = {\n        loading: false,\n        comment: ''\n    };\n\n    $scope.ok = function (force) {\n        $scope.popup.loading = true;\n        var data = {\n            comment: $scope.popup.comment\n        };\n\n        if (force !== undefined && force !== null && force === true) {\n            data.force = true;\n        }\n\n        delete $scope.popup.error;\n\n        $http({method: 'POST', url: FLOWABLE.APP_URL.getAppDefinitionPublishUrl($scope.model.app.id), data: data}).\n            success(function(data, status, headers, config) {\n                $scope.$hide();\n\n                if (data.error) {\n                    $scope.popup.loading = false;\n                    $scope.addAlert(data.errorDescription, 'error');\n                } else {\n                    $scope.popup.loading = false;\n                    $route.reload();\n                    $scope.addAlertPromise($translate('APP.ALERT.PUBLISH-CONFIRM'), 'info');\n                }\n            }).\n            error(function(data, status, headers, config) {\n                $scope.popup.loading = false;\n                $scope.$hide();\n                $scope.addAlertPromise($translate('APP.ALERT.PUBLISH-ERROR'), 'error');\n            });\n    };\n\n    $scope.cancel = function () {\n        if (!$scope.popup.loading) {\n            $scope.$hide();\n        }\n    };\n}]);\n\nangular.module('flowableModeler')\n.controller('DeleteAppDefinitionPopupCtrl', ['$rootScope', '$scope', '$http', '$translate', function ($rootScope, $scope, $http, $translate) {\n\n    $scope.popup = {\n        loading: false,\n        cascade: 'false'\n    };\n\n    $scope.ok = function () {\n        $scope.popup.loading = true;\n        var params = {\n            // Explicit string-check because radio-values cannot be js-booleans\n            cascade : $scope.popup.cascade === 'true',\n            deleteRuntimeApp: true\n        };\n\n        $http({method: 'DELETE', url: FLOWABLE.APP_URL.getModelUrl($scope.model.app.id), params: params}).\n            success(function(data, status, headers, config) {\n                $scope.$hide();\n                $scope.popup.loading = false;\n                $scope.addAlertPromise($translate('APP.ALERT.DELETE-CONFIRM'), 'info');\n                $scope.returnToList();\n            }).\n            error(function(data, status, headers, config) {\n                $scope.$hide();\n                $scope.popup.loading = false;\n            });\n    };\n\n    $scope.cancel = function () {\n        if (!$scope.popup.loading) {\n            $scope.$hide();\n        }\n    };\n}]);\n\nangular.module('flowableModeler')\n.controller('ImportNewVersionAppDefinitionCtrl', ['$rootScope', '$scope', '$http', 'Upload', '$route', function ($rootScope, $scope, $http, Upload, $route) {\n\n  $scope.popup = {\n       loading: false,\n       renewIdmIds: false\n  };\n\n  $scope.onFileSelect = function($files, isIE) {\n\n      $scope.popup.loading = true;\n\n      for (var i = 0; i < $files.length; i++) {\n          var file = $files[i];\n\n          var url;\n          if (isIE) {\n              url = FLOWABLE.APP_URL.getAppDefinitionModelTextImportUrl($scope.model.app.id, $scope.popup.renewIdmIds);\n          } else {\n              url = FLOWABLE.APP_URL.getAppDefinitionModelImportUrl($scope.model.app.id, $scope.popup.renewIdmIds);\n          }\n\n          Upload.upload({\n              url: url,\n              method: 'POST',\n              file: file\n          }).progress(function(evt) {\n              $scope.popup.uploadProgress = parseInt(100.0 * evt.loaded / evt.total);\n\n          }).success(function(data, status, headers, config) {\n              $scope.popup.loading = false;\n\n              $route.reload();\n              $scope.$hide();\n\n          }).error(function(data, status, headers, config) {\n\n              if (data && data.message) {\n                  $scope.popup.errorMessage = data.message;\n              }\n\n              $scope.popup.error = true;\n              $scope.popup.loading = false;\n          });\n      }\n  };\n\n  $scope.cancel = function () {\n      if (!$scope.popup.loading) {\n          $scope.$hide();\n      }\n  };\n}]);\n"
  },
  {
    "path": "flowable-ui-web/modeler/scripts/controllers/app-definitions.js",
    "content": "/* 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'use strict';\n\nangular.module('flowableModeler')\n  .controller('AppDefinitionsCtrl', ['$rootScope', '$scope', '$translate', '$http', '$timeout','$location', '$modal', function ($rootScope, $scope, $translate, $http, $timeout, $location, $modal) {\n\n      // Main page (needed for visual indicator of current page)\n      $rootScope.setMainPageById('apps');\n\n\t  $scope.model = {\n        filters: [\n            {id: 'apps', labelKey: 'APPS'}\n\t\t],\n\n\t\tsorts: [\n\t        {id: 'modifiedDesc', labelKey: 'MODIFIED-DESC'},\n\t        {id: 'modifiedAsc', labelKey: 'MODIFIED-ASC'},\n\t        {id: 'nameAsc', labelKey: 'NAME-ASC'},\n\t        {id: 'nameDesc', labelKey: 'NAME-DESC'}\n\t\t]\n\t  };\n\n\t  if ($rootScope.appFilter) {\n\t\t  $scope.model.activeFilter = $rootScope.appFilter.filter;\n\t\t  $scope.model.activeSort = $rootScope.appFilter.sort;\n\t\t  $scope.model.filterText = $rootScope.appFilter.filterText;\n\n\t  } else {\n\t\t  // By default, show first filter and use first sort\n\t      $scope.model.activeFilter = $scope.model.filters[0];\n\t      $scope.model.activeSort = $scope.model.sorts[0];\n\t      $rootScope.appFilter = {\n\t    \t\t  filter: $scope.model.activeFilter,\n\t    \t\t  sort: $scope.model.activeSort,\n\t    \t\t  filterText: ''\n\t      };\n\t  }\n\n\t  $scope.activateFilter = function(filter) {\n\t\t  $scope.model.activeFilter = filter;\n\t\t  $rootScope.appFilter.filter = filter;\n\t\t  $scope.loadApps();\n\t  };\n\n\t  $scope.activateSort = function(sort) {\n\t\t  $scope.model.activeSort = sort;\n\t\t  $rootScope.appFilter.sort = sort;\n\t\t  $scope.loadApps();\n\t  };\n\n\t  $scope.loadApps = function() {\n\t\t  $scope.model.loading = true;\n\n\t\t  var params = {\n\t\t      filter: $scope.model.activeFilter.id,\n\t\t      sort: $scope.model.activeSort.id,\n\t\t      modelType: 3\n\t\t  };\n\n\t\t  if ($scope.model.filterText && $scope.model.filterText != '') {\n\t\t    params.filterText = $scope.model.filterText;\n\t\t  }\n\n\t\t  $http({method: 'GET', url: FLOWABLE.APP_URL.getModelsUrl(), params: params}).\n\t\t  \tsuccess(function(data, status, headers, config) {\n\t    \t\t$scope.model.apps = data;\n\t    \t\t$scope.model.loading = false;\n\t        }).\n\t        error(function(data, status, headers, config) {\n\t           $scope.model.loading = false;\n\t        });\n\t  };\n\n\t  var timeoutFilter = function() {\n\t    $scope.model.isFilterDelayed = true;\n\t    $timeout(function() {\n\t        $scope.model.isFilterDelayed = false;\n\t        if($scope.model.isFilterUpdated) {\n\t          $scope.model.isFilterUpdated = false;\n\t          timeoutFilter();\n\t        } else {\n\t          $scope.model.filterText = $scope.model.pendingFilterText;\n\t          $rootScope.appFilter.filterText = $scope.model.filterText;\n\t          $scope.loadApps();\n\t        }\n\t    }, 500);\n\t  };\n\n\t  $scope.filterDelayed = function() {\n\t    if($scope.model.isFilterDelayed) {\n\t      $scope.model.isFilterUpdated = true;\n\t    } else {\n\t      timeoutFilter();\n\t    }\n\t  };\n\n\t  $scope.createApp = function() {\n\n          _internalCreateModal({\n\t\t\t  template: 'views/popup/app-definition-create.html?version=' + Date.now(),\n\t\t\t  scope: $scope\n\t\t  }, $modal, $scope);\n\t  };\n\n\t  $scope.showAppDetails = function(app) {\n\t    if (app) {\n\t      $location.path(\"/apps/\" + app.id);\n\t    }\n\t  };\n\n\t  $scope.editAppDetails = function(app) {\n        if (app) {\n          $location.path(\"/app-editor/\" + app.id);\n        }\n      };\n\n      $scope.importAppDefinition = function () {\n          _internalCreateModal({\n              template: 'views/popup/app-definitions-import.html?version=' + Date.now()\n          }, $modal, $scope);\n      };\n\n\t  // Finally, load initial forms\n\t  $scope.loadApps();\n  }]);\n\n\nangular.module('flowableModeler')\n    .controller('CreateNewAppCtrl', ['$rootScope', '$scope', '$http', '$location', '$translate', function ($rootScope, $scope, $http, $location, $translate) {\n\n        $scope.model = {\n            loading: false,\n            app: {\n                name: '',\n                key: '',\n                description: '',\n                modelType: 3\n            }\n        };\n\n        $scope.ok = function () {\n\n            if (!$scope.model.app.name || $scope.model.app.name.length == 0 ||\n            \t!$scope.model.app.key || $scope.model.app.key.length == 0) {\n            \t\n                return;\n            }\n\n            $scope.model.loading = true;\n\n            $http({method: 'POST', url: FLOWABLE.APP_URL.getModelsUrl(), data: $scope.model.app}).\n                success(function (data, status, headers, config) {\n                    $scope.$hide();\n\n                    $scope.model.loading = false;\n                    $location.path(\"/app-editor/\" + data.id);\n\n                }).\n                error(function (response, status, headers, config) {\n                    $scope.model.loading = false;\n\t\t\t\t\t\n\t\t\t\t\tif (response && response.message && response.message.length > 0) {\n\t\t\t\t\t\t$scope.model.errorMessage = response.message;\n\t\t\t\t\t}\n                });\n        };\n\n        $scope.cancel = function () {\n            if (!$scope.model.loading) {\n                $scope.$hide();\n            }\n        };\n    }]);\n\nangular.module('flowableModeler')\n    .controller('DuplicateAppCtrl', ['$rootScope', '$scope', '$http', '$location', '$translate', function ($rootScope, $scope, $http, $location, $translate) {\n\n        $scope.model = {\n            loading: false,\n            app: {\n                id: '',\n                name: '',\n                key: '',\n                description: '',\n                modelType: 3\n            }\n        };\n\n        if ($scope.originalModel) {\n            //clone the model\n            $scope.model.app.name = $scope.originalModel.app.name;\n            $scope.model.app.key = $scope.originalModel.app.key;\n            $scope.model.app.description = $scope.originalModel.app.description;\n            $scope.model.app.modelType = $scope.originalModel.app.modelType;\n            $scope.model.app.id = $scope.originalModel.app.id;\n        }\n\n        $scope.ok = function () {\n\n            if (!$scope.model.app.name || $scope.model.app.name.length == 0) {\n                return;\n            }\n\n            $scope.model.loading = true;\n\n            $http({method: 'POST', url: FLOWABLE.APP_URL.getCloneModelsUrl($scope.model.app.id), data: $scope.model.app}).\n                success(function (data, status, headers, config) {\n                    $scope.$hide();\n\n                    $scope.model.loading = false;\n                    $location.path(\"/app-editor/\" + data.id);\n\n                }).\n                error(function (response, status, headers, config) {\n                    $scope.model.loading = false;\n                    $scope.model.errorMessage = response.message;\n                });\n        };\n\n        $scope.cancel = function () {\n            if (!$scope.model.loading) {\n                $scope.$hide();\n            }\n        };\n    }]);\n\nangular.module('flowableModeler')\n.controller('ImportAppDefinitionCtrl', ['$rootScope', '$scope', '$http', 'Upload', '$location', function ($rootScope, $scope, $http, Upload, $location) {\n\n  $scope.model = {\n       loading: false,\n       renewIdmIds: false\n  };\n\n  $scope.onFileSelect = function($files, isIE) {\n\n      $scope.model.loading = true;\n\n      for (var i = 0; i < $files.length; i++) {\n          var file = $files[i];\n\n          var url;\n          if (isIE) {\n             url = FLOWABLE.APP_URL.getAppDefinitionTextImportUrl($scope.model.renewIdmIds);\n          } else {\n              url = FLOWABLE.APP_URL.getAppDefinitionImportUrl($scope.model.renewIdmIds);\n          }\n          Upload.upload({\n              url: url,\n              method: 'POST',\n              file: file\n          }).progress(function(evt) {\n              $scope.model.uploadProgress = parseInt(100.0 * evt.loaded / evt.total);\n\n          }).success(function(data, status, headers, config) {\n              $scope.model.loading = false;\n\n              $location.path(\"/apps/\" + data.id);\n              $scope.$hide();\n\n          }).error(function(data, status, headers, config) {\n\n              if (data && data.message) {\n                  $scope.model.errorMessage = data.message;\n              }\n\n              $scope.model.error = true;\n              $scope.model.loading = false;\n          });\n      }\n  };\n\n  $scope.cancel = function () {\n      if(!$scope.model.loading) {\n          $scope.$hide();\n      }\n  };\n}]);\n"
  },
  {
    "path": "flowable-ui-web/modeler/scripts/controllers/casemodel.js",
    "content": "/* 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 */\nangular.module('flowableModeler')\n  .controller('CaseModelCtrl', ['$rootScope', '$scope', '$translate', '$http', '$location', '$routeParams','$modal', '$popover', '$timeout', 'appResourceRoot', 'ResourceService',\n                              function ($rootScope, $scope, $translate, $http, $location, $routeParams, $modal, $popover, $timeout, appResourceRoot, ResourceService) {\n\n    // Main page (needed for visual indicator of current page)\n    $rootScope.setMainPageById('casemodels');\n\n    // Initialize model\n    $scope.model = {\n        // Store the main model id, this points to the current version of a model,\n        // even when we're showing history\n        latestModelId: $routeParams.modelId\n    };\n    \n    $scope.loadCaseModel = function() {\n      var url;\n      if ($routeParams.modelHistoryId) {\n        url = FLOWABLE.APP_URL.getModelHistoryUrl($routeParams.modelId, $routeParams.modelHistoryId);\n      } else {\n        url = FLOWABLE.APP_URL.getModelUrl($routeParams.modelId);\n      }\n      \n      $http({method: 'GET', url: url}).\n        success(function(data, status, headers, config) {\n          $scope.model.caseModel = data;\n          \n          $scope.loadVersions();\n\n          $scope.model.cmmnDownloadUrl = FLOWABLE.APP_URL.getCmmnModelDownloadUrl($routeParams.modelId, $routeParams.modelHistoryId);\n\n\n    \t  $rootScope.$on('$routeChangeStart', function(event, next, current) {\n    \t\t  jQuery('.qtip').qtip('destroy', true);\n    \t  });\n    \t  \n          $timeout(function() {\n            jQuery(\"#cmmnModel\").attr('data-model-id', $routeParams.modelId);\n            jQuery(\"#cmmnModel\").attr('data-model-type', 'design');\n            \n            // in case we want to show a historic model, include additional attribute on the div\n            if(!$scope.model.caseModel.latestVersion) {\n              jQuery(\"#cmmnModel\").attr('data-history-id', $routeParams.modelHistoryId);\n            }\n\n            var viewerUrl = appResourceRoot + \"display-cmmn/displaymodel.html?version=\" + Date.now();\n\n            // If Flowable has been deployed inside an AMD environment Raphael will fail to register\n            // itself globally until displaymodel.js (which depends ona global Raphael variable) is running,\n            // therefore remove AMD's define method until we have loaded in Raphael and displaymodel.js\n            // and assume/hope its not used during.\n            var amdDefine = window.define;\n            window.define = undefined;\n            ResourceService.loadFromHtml(viewerUrl, function(){\n                // Restore AMD's define method again\n                window.define = amdDefine;\n            });\n          });\n\n        }).error(function(data, status, headers, config) {\n          $scope.returnToList();\n        });\n    };\n    \n    $scope.useAsNewVersion = function() {\n        _internalCreateModal({\n    \t\ttemplate: 'views/popup/model-use-as-new-version.html',\n    \t\tscope: $scope\n    \t}, $modal, $scope);\n    };\n    \n    $scope.loadVersions = function() {\n      \n      var params = {\n        includeLatestVersion: !$scope.model.caseModel.latestVersion  \n      };\n      \n      $http({method: 'GET', url: FLOWABLE.APP_URL.getModelHistoriesUrl($scope.model.latestModelId), params: params}).\n      success(function(data, status, headers, config) {\n        if ($scope.model.caseModel.latestVersion) {\n          if (!data.data) {\n            data.data = [];\n          }\n          data.data.unshift($scope.model.caseModel);\n        }\n        \n        $scope.model.versions = data;\n      });\n    };\n    \n    $scope.showVersion = function(version) {\n      if(version) {\n        if(version.latestVersion) {\n            $location.path(\"/casemodels/\" +  $scope.model.latestModelId);\n        } else{\n          // Show latest version, no history-suffix needed in URL\n          $location.path(\"/casemodels/\" +  $scope.model.latestModelId + \"/history/\" + version.id);\n        }\n      }\n    };\n    \n    $scope.returnToList = function() {\n        $location.path(\"/casemodels/\");\n    };\n    \n    $scope.editCaseModel = function() {\n        _internalCreateModal({\n    \t\ttemplate: 'views/popup/model-edit.html',\n\t        scope: $scope\n    \t}, $modal, $scope);\n    };\n\n    $scope.duplicateCaseModel = function() {\n      var modalInstance = _internalCreateModal({\n        template: 'views/popup/casemodel-duplicate.html?version=' + Date.now()\n      }, $modal, $scope);\n\n      modalInstance.$scope.originalModel = $scope.model;\n    };\n\n    $scope.deleteCaseModel = function() {\n        _internalCreateModal({\n    \t\ttemplate: 'views/popup/model-delete.html',\n    \t\tscope: $scope\n    \t}, $modal, $scope);\n    };\n    \n    $scope.openEditor = function() {\n      if ($scope.model.caseModel) {\n        $location.path(\"/editor/\" + $scope.model.caseModel.id);\n      }\n    };\n      \n    $scope.toggleHistory = function($event) {\n        if(!$scope.historyState) {\n          var state = {};\n          $scope.historyState = state;\n          \n          // Create popover\n          state.popover = $popover(angular.element($event.target), {\n            template: 'views/popover/history.html',\n            placement: 'bottom-right',\n            show: true,\n            scope: $scope,\n            container: 'body'\n          });\n          \n          var destroy = function() {\n            state.popover.destroy();\n            delete $scope.historyState;\n          }\n          \n          // When popup is hidden or scope is destroyed, hide popup\n          state.popover.$scope.$on('tooltip.hide', destroy);\n          $scope.$on('$destroy', destroy);\n        }\n    };\n    \n    $scope.loadCaseModel();\n}]);\n"
  },
  {
    "path": "flowable-ui-web/modeler/scripts/controllers/casemodels.js",
    "content": "/* 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'use strict';\n\nangular.module('flowableModeler')\n  .controller('CaseModelsCtrl', ['$rootScope', '$scope', '$translate', '$http', '$timeout','$location', '$modal', function ($rootScope, $scope, $translate, $http, $timeout, $location, $modal) {\n\n      // Main page (needed for visual indicator of current page)\n      $rootScope.setMainPageById('casemodels');\n      $rootScope.formItems = undefined;\n\n      // get latest thumbnails\n      $scope.imageVersion = Date.now();\n\n\t  $scope.model = {\n        filters: [\n            {id: 'cases', labelKey: 'CASES'}\n\t\t],\n\n\t\tsorts: [\n\t\t        {id: 'modifiedDesc', labelKey: 'MODIFIED-DESC'},\n\t\t        {id: 'modifiedAsc', labelKey: 'MODIFIED-ASC'},\n\t\t        {id: 'nameAsc', labelKey: 'NAME-ASC'},\n\t\t        {id: 'nameDesc', labelKey: 'NAME-DESC'}\n\t\t]\n\t  };\n\t  \n\t  // By default, show first filter and use first sort\n      $scope.model.activeFilter = $scope.model.filters[0];\n      $scope.model.activeSort = $scope.model.sorts[0];\n\n\t  $scope.activateFilter = function(filter) {\n\t\t  $scope.model.activeFilter = filter;\n\t\t  $rootScope.modelFilter.filter = filter;\n\t\t  $scope.loadCaseModels();\n\t  };\n\n\t  $scope.activateSort = function(sort) {\n\t\t  $scope.model.activeSort = sort;\n\t\t  $rootScope.modelFilter.sort = sort;\n\t\t  $scope.loadCaseModels();\n\t  };\n\n\t  $scope.loadCaseModels = function() {\n\t\t  $scope.model.loading = true;\n\n\t\t  var params = {\n\t\t      filter: $scope.model.activeFilter.id,\n\t\t      sort: $scope.model.activeSort.id,\n\t\t      modelType: 5\n\t\t  };\n\n\t\t  if ($scope.model.filterText && $scope.model.filterText != '') {\n\t\t    params.filterText = $scope.model.filterText;\n\t\t  }\n\n\t\t  $http({method: 'GET', url: FLOWABLE.APP_URL.getModelsUrl(), params: params}).\n\t\t  \tsuccess(function(data, status, headers, config) {\n\t    \t\t$scope.model.caseModels = data;\n\t    \t\t$scope.model.loading = false;\n\t        }).\n\t        error(function(data, status, headers, config) {\n\t           console.log('Something went wrong: ' + data);\n\t           $scope.model.loading = false;\n\t        });\n\t  };\n\n\t  var timeoutFilter = function() {\n\t      $scope.model.isFilterDelayed = true;\n\t      $timeout(function() {\n\t          $scope.model.isFilterDelayed = false;\n\t          if ($scope.model.isFilterUpdated) {\n\t              $scope.model.isFilterUpdated = false;\n\t              timeoutFilter();\n\t          } else {\n\t              $scope.model.filterText = $scope.model.pendingFilterText;\n\t              $rootScope.modelFilter.filterText = $scope.model.filterText;\n\t              $scope.loadCaseModels();\n\t          }\n\t      }, 500);\n\t  };\n\n\t  $scope.filterDelayed = function() {\n\t      if ($scope.model.isFilterDelayed) {\n\t          $scope.model.isFilterUpdated = true;\n\t      } else {\n\t          timeoutFilter();\n\t      }\n\t  };\n\n\t  $scope.createCaseModel = function(mode) {\n\t    var modalInstance = _internalCreateModal({\n\t        template: 'views/popup/casemodel-create.html?version=' + Date.now()\n\t    }, $modal, $scope);\n\t  };\n\n\t  $scope.importCaseModel = function () {\n          _internalCreateModal({\n              template: 'views/popup/casemodel-import.html?version=' + Date.now()\n          }, $modal, $scope);\n\t  };\n\n\t  $scope.showCaseModelDetails = function(caseModel) {\n\t      if (caseModel) {\n\t          $rootScope.editorHistory = [];\n\t          $location.path(\"/casemodels/\" + caseModel.id);\n\t      }\n\t  };\n\n\t  $scope.editCaseModelDetails = function(caseModel) {\n\t\t  if (caseModel) {\n\t\t      $rootScope.editorHistory = [];\n              $location.path(\"/editor/\" + caseModel.id);\n\t\t  }\n\t  };\n\n\t  // Finally, load initial cases\n\t  $scope.loadCaseModels();\n  }]);\n\nangular.module('flowableModeler')\n.controller('CreateNewCaseModelModelCtrl', ['$rootScope', '$scope', '$modal', '$http', '$location',\n                                          function ($rootScope, $scope, $modal, $http, $location) {\n\n    $scope.model = {\n       loading: false,\n       caseModel: {\n            name: '',\n            key: '',\n            description: '',\n           \tmodelType: 5\n       }\n    };\n\n    if ($scope.initialModelType !== undefined) {\n        $scope.model.caseModel.modelType = $scope.initialModelType;\n    }\n\n    $scope.ok = function () {\n\n        if (!$scope.model.caseModel.name || $scope.model.caseModel.name.length == 0 ||\n        \t!$scope.model.caseModel.key || $scope.model.caseModel.key.length == 0) {\n        \t\n            return;\n        }\n\n        $scope.model.loading = true;\n\n        $http({method: 'POST', url: FLOWABLE.APP_URL.getModelsUrl(), data: $scope.model.caseModel}).\n            success(function(data) {\n                $scope.$hide();\n\n                $scope.model.loading = false;\n                $rootScope.editorHistory = [];\n                $location.path(\"/case-editor/\" + data.id);\n            }).\n            error(function(data, status, headers, config) {\n                $scope.model.loading = false;\n                $scope.model.errorMessage = data.message;\n            });\n    };\n\n    $scope.cancel = function () {\n        if(!$scope.model.loading) {\n            $scope.$hide();\n        }\n    };\n}]);\n\nangular.module('flowableModeler')\n.controller('DuplicateCaseModelCtrl', ['$rootScope', '$scope', '$modal', '$http', '$location',\n                                          function ($rootScope, $scope, $modal, $http, $location) {\n\n    $scope.model = {\n       loading: false,\n       caseModel: {\n            name: '',\n            key: '',\n            description: ''\n       }\n    };\n\n    if ($scope.originalModel) {\n        //clone the model\n        $scope.model.caseModel.name = $scope.originalModel.caseModel.name;\n        $scope.model.caseModel.key = $scope.originalModel.caseModel.key;\n        $scope.model.caseModel.description = $scope.originalModel.caseModel.description;\n        $scope.model.caseModel.id = $scope.originalModel.caseModel.id;\n        $scope.model.caseModel.modelType = $scope.originalModel.caseModel.modelType;\n    }\n\n    $scope.ok = function () {\n\n        if (!$scope.model.caseModel.name || $scope.model.caseModel.name.length == 0 || \n        \t!$scope.model.caseModel.key || $scope.model.caseModel.key.length == 0) {\n        \t\n            return;\n        }\n\n        $scope.model.loading = true;\n\n        $http({method: 'POST', url: FLOWABLE.APP_URL.getCloneModelsUrl($scope.model.caseModel.id), data: $scope.model.caseModel}).\n            success(function(data) {\n                $scope.$hide();\n\n                $scope.model.loading = false;\n                $rootScope.editorHistory = [];\n                $location.path(\"/editor/\" + data.id);\n            }).\n            error(function(data, status, headers, config) {\n                $scope.model.loading = false;\n                $scope.model.errorMessage = data.message;\n            });\n    };\n\n    $scope.cancel = function () {\n        if(!$scope.model.loading) {\n            $scope.$hide();\n        }\n    };\n}]);\n\nangular.module('flowableModeler')\n.controller('ImportCaseModelCtrl', ['$rootScope', '$scope', '$http', 'Upload', '$location', function ($rootScope, $scope, $http, Upload, $location) {\n\n  $scope.model = {\n       loading: false\n  };\n\n  $scope.onFileSelect = function($files, isIE) {\n\n      $scope.model.loading = true;\n\n      for (var i = 0; i < $files.length; i++) {\n          var file = $files[i];\n\n          var url;\n          if (isIE) {\n              url = FLOWABLE.APP_URL.getCaseModelTextImportUrl();\n          } else {\n              url = FLOWABLE.APP_URL.getCaseModelImportUrl();\n          }\n\n          Upload.upload({\n              url: url,\n              method: 'POST',\n              file: file\n          }).progress(function(evt) {\n              $scope.model.uploadProgress = parseInt(100.0 * evt.loaded / evt.total);\n\n          }).success(function(data) {\n              $scope.model.loading = false;\n\n              $location.path(\"/editor/\" + data.id);\n              $scope.$hide();\n\n          }).error(function(data) {\n\n              if (data && data.message) {\n                  $scope.model.errorMessage = data.message;\n              }\n\n              $scope.model.error = true;\n              $scope.model.loading = false;\n          });\n      }\n  };\n\n  $scope.cancel = function () {\n\t  if(!$scope.model.loading) {\n\t\t  $scope.$hide();\n\t  }\n  };\n}]);\n"
  },
  {
    "path": "flowable-ui-web/modeler/scripts/controllers/decision-table-editor.js",
    "content": "/* Copyright 2005-2015 Alfresco Software, Ltd.\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'use strict';\n\nvar extScope;\n\nangular.module('flowableModeler')\n    .controller('DecisionTableEditorController', ['$rootScope', '$scope', '$q', '$translate', '$http', '$timeout', '$location', '$modal', '$route', '$routeParams', 'DecisionTableService',\n        'UtilityService', 'uiGridConstants', 'appResourceRoot', 'hotRegisterer',\n        function ($rootScope, $scope, $q, $translate, $http, $timeout, $location, $modal, $route, $routeParams, DecisionTableService,\n                  UtilityService, uiGridConstants, appResourceRoot, hotRegisterer) {\n\n            extScope = $scope;\n\n            $rootScope.decisionTableChanges = false;\n\n            var hotDecisionTableEditorInstance;\n            var hitPolicies = ['FIRST', 'ANY', 'UNIQUE', 'PRIORITY', 'RULE ORDER', 'OUTPUT ORDER', 'COLLECT'];\n            var stringOperators = ['==', '!=', 'IS IN', 'IS NOT IN'];\n            var numberOperators = ['==', '!=', '<', '>', '>=', '<=', 'IS IN', 'IS NOT IN'];\n            var booleanOperators = ['==', '!='];\n            var dateOperators = ['==', '!=', '<', '>', '>=', '<=', 'IS IN', 'IS NOT IN'];\n            var collectionOperators = ['ANY OF', 'NONE OF', 'ALL OF', 'NOT ALL OF', '==', '!='];\n            var allOperators = ['==', '!=', '<', '>', '>=', '<=', 'ANY OF', 'NONE OF', 'ALL OF', 'NOT ALL OF', 'IS IN', 'IS NOT IN'];\n            var collectOperators = {\n                'SUM': '+',\n                'MIN': '<',\n                'MAX': '>',\n                'COUNT': '#'\n            };\n\n            var columnIdCounter = 0;\n            var hitPolicyHeaderElement;\n            var dateFormat = 'YYYY-MM-DD';\n\n            // Export name to grid's scope\n            $scope.appResourceRoot = appResourceRoot;\n\n            // Model init\n            $scope.status = {loading: true};\n            $scope.model = {\n                rulesData: [],\n                columnDefs: [],\n                columnVariableIdMap: {},\n                startOutputExpression: 0,\n                selectedRow: undefined,\n                availableInputVariableTypes: ['string', 'number', 'boolean', 'date', 'collection'],\n                availableOutputVariableTypes: ['string', 'number', 'boolean', 'date']\n            };\n\n            // Hot Model init\n            $scope.model.hotSettings = {\n                contextMenu: {\n                    items: {\n                        \"insert_row_above\": {\n                            name: 'Insert rule above',\n                            callback: function (key, options) {\n                                if (hotDecisionTableEditorInstance.getSelected()) {\n                                    $scope.addRule(hotDecisionTableEditorInstance.getSelected()[0]);\n                                }\n                            }\n                        },\n                        \"insert_row_below\": {\n                            name: 'Add rule below',\n                            callback: function (key, options) {\n                                if (hotDecisionTableEditorInstance.getSelected()) {\n                                    $scope.addRule(hotDecisionTableEditorInstance.getSelected()[0] + 1);\n                                }\n                            }\n                        },\n                        \"clear_row\": {\n                            name: 'Clear rule',\n                            callback: function (key, options) {\n                                if (hotDecisionTableEditorInstance.getSelected()) {\n                                    $scope.clearRule(hotDecisionTableEditorInstance.getSelected()[0]);\n                                }\n                            }\n                        },\n                        \"remove_row\": {\n                            name: 'Remove this rule',\n                            disabled: function () {\n                                // if only 1 rule disable\n                                if (hotDecisionTableEditorInstance.getSelected()) {\n                                    return $scope.model.rulesData.length < 2;\n                                } else {\n                                    return false;\n                                }\n                            }\n                        },\n                        \"hsep1\": \"---------\",\n                        \"move_rule_up\": {\n                            name: 'Move rule up',\n                            disabled: function () {\n                                if (hotDecisionTableEditorInstance.getSelected()) {\n                                    return hotDecisionTableEditorInstance.getSelected()[0] === 0;\n                                }\n                            },\n                            callback: function (key, options) {\n                                $scope.moveRuleUpwards();\n                            }\n                        },\n                        \"move_rule_down\": {\n                            name: 'Move rule down',\n                            disabled: function () {\n                                if (hotDecisionTableEditorInstance.getSelected()) {\n                                    return hotDecisionTableEditorInstance.getSelected()[0] + 1 === $scope.model.rulesData.length;\n                                }\n                            },\n                            callback: function (key, options) {\n                                $scope.moveRuleDownwards();\n                            }\n                        },\n                        \"hsep2\": \"---------\",\n                        \"add_input\": {\n                            name: 'Add input',\n                            callback: function (key, options) {\n                                if (hotDecisionTableEditorInstance.getSelected()) {\n                                    $scope.openInputExpressionEditor(hotDecisionTableEditorInstance.getSelected()[1], true);\n                                }\n                            }\n                        },\n                        \"add_output\": {\n                            name: 'Add output',\n                            callback: function (key, options) {\n                                if (hotDecisionTableEditorInstance.getSelected()) {\n                                    if (hotDecisionTableEditorInstance.getSelected()[1] < $scope.model.startOutputExpression) {\n                                        $scope.openOutputExpressionEditor($scope.currentDecisionTable.outputExpressions.length, true);\n                                    } else {\n                                        $scope.openOutputExpressionEditor((hotDecisionTableEditorInstance.getSelected()[1] - $scope.model.startOutputExpression), true);\n                                    }\n                                }\n                            }\n                        },\n                        \"hsep3\": \"---------\",\n                        \"undo\": {\n                            name: 'Undo'\n                        },\n                        \"redo\": {\n                            name: 'Redo'\n                        }\n                    }\n                },\n                manualColumnResize: false,\n                stretchH: 'all',\n                outsideClickDeselects: false,\n                viewportColumnRenderingOffset: $scope.model.columnDefs.length + 10\n            };\n\n\n            $scope.hitPolicies = [];\n            hitPolicies.forEach(function (id) {\n                $scope.hitPolicies.push({\n                    id: id,\n                    label: 'DECISION-TABLE.HIT-POLICIES.' + id\n                });\n            });\n\n            $scope.collectOperators = [];\n            Object.keys(collectOperators).forEach(function (key) {\n                $scope.collectOperators.push({\n                    id: key,\n                    label: 'DECISION-TABLE.COLLECT-OPERATORS.' + key\n                });\n            });\n\n            $scope.addRule = function (rowNumber) {\n                if (rowNumber !== undefined) {\n                    $scope.model.rulesData.splice(rowNumber, 0, createDefaultRow());\n                } else {\n                    $scope.model.rulesData.push(createDefaultRow());\n                }\n                if (hotDecisionTableEditorInstance) {\n                    hotDecisionTableEditorInstance.render();\n                }\n            };\n\n            $scope.removeRule = function () {\n                $scope.model.rulesData.splice($scope.model.selectedRow, 1);\n            };\n\n            $scope.clearRule = function (rowNumber) {\n                if (rowNumber === undefined) {\n                    return;\n                }\n                $scope.model.rulesData[rowNumber] = createDefaultRow();\n                if (hotDecisionTableEditorInstance) {\n                    hotDecisionTableEditorInstance.render();\n                }\n            };\n\n            $scope.moveRuleUpwards = function () {\n                $scope.model.rulesData.splice($scope.model.selectedRow - 1, 0, $scope.model.rulesData.splice($scope.model.selectedRow, 1)[0]);\n                if (hotDecisionTableEditorInstance) {\n                    hotDecisionTableEditorInstance.render();\n                }\n            };\n\n            $scope.moveRuleDownwards = function () {\n                $scope.model.rulesData.splice($scope.model.selectedRow + 1, 0, $scope.model.rulesData.splice($scope.model.selectedRow, 1)[0]);\n                if (hotDecisionTableEditorInstance) {\n                    hotDecisionTableEditorInstance.render();\n                }\n            };\n\n            $scope.doAfterGetColHeader = function (col, TH) {\n                if ($scope.model.columnDefs[col] && $scope.model.columnDefs[col].expressionType === 'input-operator') {\n                    TH.className += \"input-operator-header\";\n                } else if ($scope.model.columnDefs[col] && $scope.model.columnDefs[col].expressionType === 'input-expression') {\n                    TH.className += \"input-expression-header\";\n                    if ($scope.model.startOutputExpression - 1 === col) {\n                        TH.className += \" last\";\n                    }\n                } else if ($scope.model.columnDefs[col] && $scope.model.columnDefs[col].expressionType === 'output') {\n                    TH.className += \"output-header\";\n                    if ($scope.model.startOutputExpression === col) {\n                        TH.className += \" first\";\n                    }\n                }\n            };\n\n            $scope.doAfterModifyColWidth = function (width, col) {\n                if ($scope.model.columnDefs[col] && $scope.model.columnDefs[col].width) {\n                    var settingsWidth = $scope.model.columnDefs[col].width;\n                    if (settingsWidth > width) {\n                        return settingsWidth;\n                    }\n                }\n                return width;\n            };\n\n            $scope.doAfterOnCellMouseDown = function (event, coords, TD) {\n                // clicked hit policy indicator\n                if (coords.row === 0 && coords.col === 0 && TD.className === '') {\n                    $scope.openHitPolicyEditor();\n                } else {\n                    if (coords && coords.row !== undefined) {\n                        $timeout(function () {\n                            $scope.model.selectedRow = coords.row;\n                        });\n                    }\n                }\n            };\n\n            $scope.doAfterScroll = function () {\n                if (hotDecisionTableEditorInstance) {\n                    hotDecisionTableEditorInstance.render();\n                }\n            };\n\n            $scope.doAfterRender = function (isForced) {\n\n                if (hitPolicyHeaderElement) {\n                    var element = document.querySelector(\"thead > tr > th:first-of-type\");\n                    if (element) {\n                        var firstChild = element.firstChild;\n                        element.className = 'hit-policy-container';\n                        element.replaceChild(hitPolicyHeaderElement[0], firstChild);\n                    }\n                }\n\n                if (hotDecisionTableEditorInstance === undefined) {\n                    $timeout(function () {\n                        hotDecisionTableEditorInstance = hotRegisterer.getInstance('decision-table-editor');\n                        hotDecisionTableEditorInstance.validateCells();\n                    });\n                } else {\n                    hotDecisionTableEditorInstance.validateCells();\n                }\n            };\n\n            $scope.dumpData = function () {\n                console.log($scope.currentDecisionTable);\n                console.log($scope.model.rulesData);\n                console.log($scope.model.columnDefs);\n            };\n\n            $scope.doAfterValidate = function (isValid, value, row, prop, source) {\n                if (isCorrespondingCollectionOperator(row, prop)) {\n                    return true;\n                } else if (isCustomExpression(value) || isDashValue(value)) {\n                    disableCorrespondingOperatorCell(row, prop);\n                    return true;\n                } else {\n                    enableCorrespondingOperatorCell(row, prop);\n                }\n            };\n\n            // dummy validator for text fields in order to trigger the post validation hook\n            var textValidator = function(value, callback) {\n                callback(true);\n            };\n\n            var isCustomExpression = function (val) {\n                return !!(val != null\n                    && (String(val).startsWith('${') || String(val).startsWith('#{')));\n            };\n\n            var isDashValue = function (val) {\n                return !!(val != null && \"-\" === val);\n            };\n\n            var isCorrespondingCollectionOperator = function (row, prop) {\n                var operatorCol = getCorrespondingOperatorCell(row, prop);\n                var operatorCellMeta = hotDecisionTableEditorInstance.getCellMeta(row, operatorCol);\n\n                var isCollectionOperator = false;\n                if (isOperatorCell(operatorCellMeta)) {\n                    var operatorValue = hotDecisionTableEditorInstance.getDataAtCell(row, operatorCol);\n                    if (operatorValue === \"IN\" || operatorValue === \"NOT IN\" || operatorValue === \"ANY\" || operatorValue === \"NOT ANY\") {\n                        isCollectionOperator = true;\n                    }\n                }\n                return isCollectionOperator;\n            };\n\n            var disableCorrespondingOperatorCell = function (row, prop) {\n                var operatorCol = getCorrespondingOperatorCell(row, prop);\n                var operatorCellMeta = hotDecisionTableEditorInstance.getCellMeta(row, operatorCol);\n\n                if (!isOperatorCell(operatorCellMeta)) {\n                    return;\n                }\n\n                if (operatorCellMeta.className != null && operatorCellMeta.className.indexOf('custom-expression-operator') !== -1) {\n                    return;\n                }\n\n                var currentEditor = hotDecisionTableEditorInstance.getCellEditor(row, operatorCol);\n\n                hotDecisionTableEditorInstance.setCellMeta(row, operatorCol, 'className', operatorCellMeta.className + ' custom-expression-operator');\n                hotDecisionTableEditorInstance.setCellMeta(row, operatorCol, 'originalEditor', currentEditor);\n                hotDecisionTableEditorInstance.setCellMeta(row, operatorCol, 'editor', false);\n                hotDecisionTableEditorInstance.setDataAtCell(row, operatorCol, null);\n            };\n\n            var enableCorrespondingOperatorCell = function (row, prop) {\n                var operatorCol = getCorrespondingOperatorCell(row, prop);\n                var operatorCellMeta = hotDecisionTableEditorInstance.getCellMeta(row, operatorCol);\n\n                if (!isOperatorCell(operatorCellMeta)) {\n                    return;\n                }\n\n                if (operatorCellMeta == null || operatorCellMeta.className == null || operatorCellMeta.className.indexOf('custom-expression-operator') == -1) {\n                    return;\n                }\n\n                operatorCellMeta.className = operatorCellMeta.className.replace('custom-expression-operator', '');\n                hotDecisionTableEditorInstance.setCellMeta(row, operatorCol, 'className', operatorCellMeta.className);\n                hotDecisionTableEditorInstance.setCellMeta(row, operatorCol, 'editor', operatorCellMeta.originalEditor);\n                hotDecisionTableEditorInstance.setDataAtCell(row, operatorCol, '==');\n            };\n\n            var getCorrespondingOperatorCell = function (row, prop) {\n                var currentCol = hotDecisionTableEditorInstance.propToCol(prop);\n                if (currentCol < 1) {\n                    return;\n                }\n                var operatorCol = currentCol - 1;\n                return operatorCol;\n            };\n\n            var isOperatorCell = function (cellMeta) {\n                return !(cellMeta == null || cellMeta.prop == null || typeof cellMeta.prop !== 'string'|| cellMeta.prop.endsWith(\"_operator\") === false);\n            };\n\n            var createNewInputExpression = function (inputExpression) {\n                var newInputExpression;\n                if (inputExpression) {\n                    newInputExpression = {\n                        id: _generateColumnId(),\n                        label: inputExpression.label,\n                        variableId: inputExpression.variableId,\n                        type: inputExpression.type,\n                        newVariable: inputExpression.newVariable,\n                        entries: inputExpression.entries\n                    };\n\n                } else {\n                    newInputExpression = {\n                        id: _generateColumnId(),\n                        label: null,\n                        variableId: null,\n                        type: null,\n                        newVariable: null,\n                        entries: null\n                    };\n                }\n                return newInputExpression;\n            };\n\n            var createNewOutputExpression = function (outputExpression) {\n                var newOutputExpression;\n                if (outputExpression) {\n                    newOutputExpression = {\n                        id: _generateColumnId(),\n                        label: outputExpression.label,\n                        variableId: outputExpression.variableId,\n                        type: outputExpression.type,\n                        newVariable: outputExpression.newVariable,\n                        entries: outputExpression.entries\n                    };\n\n                } else {\n                    newOutputExpression = {\n                        id: _generateColumnId(),\n                        label: null,\n                        variableId: null,\n                        type: null,\n                        newVariable: null,\n                        entries: null\n                    };\n                }\n                return newOutputExpression;\n            };\n\n            $scope.addNewInputExpression = function (inputExpression, insertPos) {\n                var newInputExpression = createNewInputExpression(inputExpression);\n\n                // insert expression at position or just add\n                if (insertPos !== undefined && insertPos !== -1) {\n                    $scope.currentDecisionTable.inputExpressions.splice(insertPos, 0, newInputExpression);\n                } else {\n                    $scope.currentDecisionTable.inputExpressions.push(newInputExpression);\n                }\n\n                // update data model with initial values\n                $scope.model.rulesData.forEach(function (rowData) {\n                    rowData[newInputExpression.id + '_expression'] = '-';\n                });\n\n                // update column definitions off the source model\n                $scope.evaluateDecisionHeaders($scope.currentDecisionTable);\n            };\n\n            $scope.addNewOutputExpression = function (outputExpression, insertPos) {\n                var newOutputExpression = createNewOutputExpression(outputExpression);\n\n                // insert expression at position or just add\n                if (insertPos !== undefined && insertPos !== -1) {\n                    $scope.currentDecisionTable.outputExpressions.splice(insertPos, 0, newOutputExpression);\n                } else {\n                    $scope.currentDecisionTable.outputExpressions.push(newOutputExpression);\n                }\n\n                // update column definitions off the source model\n                $scope.evaluateDecisionHeaders($scope.currentDecisionTable);\n            };\n\n            $scope.removeInputExpression = function (expressionPos) {\n                var removedElements = $scope.currentDecisionTable.inputExpressions.splice(expressionPos, 1);\n                removePropertyFromGrid(removedElements[0].id, 'input');\n                $scope.evaluateDecisionHeaders($scope.currentDecisionTable);\n            };\n\n            var removePropertyFromGrid = function (key, type) {\n                if ($scope.model.rulesData) {\n                    $scope.model.rulesData.forEach(function (rowData) {\n                        if (type === 'input') {\n                            delete rowData[key + '_operator'];\n                            delete rowData[key + '_expression'];\n                        } else if (type === 'output') {\n                            delete rowData[key];\n                        }\n                    });\n                }\n            };\n\n            $scope.removeOutputExpression = function (expressionPos) {\n                var removedElements = $scope.currentDecisionTable.outputExpressions.splice(expressionPos, 1);\n                removePropertyFromGrid(removedElements[0].id, 'output');\n                $scope.evaluateDecisionHeaders($scope.currentDecisionTable);\n            };\n\n            $scope.openInputExpressionEditor = function (expressionPos, newExpression) {\n                var editTemplate = 'views/popup/decision-table-edit-input-expression.html';\n\n                $scope.model.newExpression = !!newExpression;\n\n                if (!$scope.model.newExpression) {\n                    $scope.model.selectedExpression = $scope.currentDecisionTable.inputExpressions[expressionPos];\n                } else {\n                    if (expressionPos >= $scope.model.startOutputExpression) {\n                        $scope.model.selectedColumn = $scope.model.startOutputExpression - 1;\n                    } else {\n                        $scope.model.selectedColumn = Math.floor(expressionPos / 2);\n                    }\n                }\n\n                _internalCreateModal({\n                    template: editTemplate,\n                    scope: $scope\n                }, $modal, $scope);\n            };\n\n            $scope.openOutputExpressionEditor = function (expressionPos, newExpression) {\n                var editTemplate = 'views/popup/decision-table-edit-output-expression.html';\n\n                $scope.model.newExpression = !!newExpression;\n                $scope.model.hitPolicy = $scope.currentDecisionTable.hitIndicator;\n                $scope.model.selectedColumn = expressionPos;\n\n\n                if (!$scope.model.newExpression) {\n                    $scope.model.selectedExpression = $scope.currentDecisionTable.outputExpressions[expressionPos];\n                }\n\n                _internalCreateModal({\n                    template: editTemplate,\n                    scope: $scope\n                }, $modal, $scope);\n            };\n\n            $scope.openHitPolicyEditor = function () {\n                var editTemplate = 'views/popup/decision-table-edit-hit-policy.html';\n\n                $scope.model.hitPolicy = $scope.currentDecisionTable.hitIndicator;\n                $scope.model.collectOperator = $scope.currentDecisionTable.collectOperator;\n\n                _internalCreateModal({\n                    template: editTemplate,\n                    scope: $scope\n                }, $modal, $scope);\n            };\n\n            var _loadDecisionTableDefinition = function (modelId) {\n                DecisionTableService.fetchDecisionTableDetails(modelId).then(function (decisionTable) {\n\n                    $rootScope.currentDecisionTable = decisionTable.decisionTableDefinition;\n                    $rootScope.currentDecisionTable.id = decisionTable.id;\n                    $rootScope.currentDecisionTable.key = decisionTable.decisionTableDefinition.key;\n                    $rootScope.currentDecisionTable.name = decisionTable.name;\n                    $rootScope.currentDecisionTable.description = decisionTable.description;\n\n                    $scope.model.lastUpdatedBy = decisionTable.lastUpdatedBy;\n                    $scope.model.createdBy = decisionTable.createdBy;\n\n                    // decision table model to used in save dialog\n                    $rootScope.currentDecisionTableModel = {\n                        id: decisionTable.id,\n                        name: decisionTable.name,\n                        key: decisionTable.key,\n                        description: decisionTable.description\n                    };\n\n                    if (!$rootScope.currentDecisionTable.hitIndicator) {\n                        $rootScope.currentDecisionTable.hitIndicator = hitPolicies[0];\n                    }\n\n                    var hitPolicyHeaderString = '<div class=\"hit-policy-header\"><a onclick=\"triggerHitPolicyEditor()\">' + $rootScope.currentDecisionTable.hitIndicator.substring(0, 1);\n                    if ($rootScope.currentDecisionTable.collectOperator) {\n                        hitPolicyHeaderString += collectOperators[$rootScope.currentDecisionTable.collectOperator];\n                    }\n                    hitPolicyHeaderString += '</a></div>';\n                    hitPolicyHeaderElement = angular.element(hitPolicyHeaderString);\n\n                    evaluateDecisionTableGrid($rootScope.currentDecisionTable);\n\n                    $timeout(function () {\n                        // Flip switch in timeout to start watching all decision-related models\n                        // after next digest cycle, to prevent first false-positive\n                        $scope.status.loading = false;\n                        $rootScope.decisionTableChanges = false;\n                    });\n\n                });\n            };\n\n            var composeInputOperatorColumnDefinition = function (inputExpression) {\n                var expressionPosition = $scope.currentDecisionTable.inputExpressions.indexOf(inputExpression);\n\n                var columnDefinition = {\n                    data: inputExpression.id + '_operator',\n                    expressionType: 'input-operator',\n                    expression: inputExpression,\n                    width: '70',\n                    className: 'input-operator-cell',\n                    type: 'dropdown',\n                    source: getOperatorsForColumnType(inputExpression.type)\n                };\n\n                if ($scope.currentDecisionTable.inputExpressions.length !== 1) {\n                    columnDefinition.title = '<div class=\"header-remove-expression\">' +\n                        '<a onclick=\"triggerRemoveExpression(\\'input\\',' + expressionPosition + ',true)\"><span class=\"glyphicon glyphicon-minus-sign\"></span></a>' +\n                        '</div>';\n                }\n\n                return columnDefinition;\n            };\n\n            var getOperatorsForColumnType = function (type) {\n                switch (type) {\n                    case 'number':\n                        return numberOperators;\n                    case 'date':\n                        return dateOperators;\n                    case 'boolean':\n                        return booleanOperators;\n                    case 'string':\n                        return stringOperators;\n                    case 'collection':\n                        return collectionOperators;\n                    default:\n                        return allOperators;\n                }\n            };\n\n            var composeInputExpressionColumnDefinition = function (inputExpression) {\n                var expressionPosition = $scope.currentDecisionTable.inputExpressions.indexOf(inputExpression);\n\n                var type;\n                switch (inputExpression.type) {\n                    case 'date':\n                        type = 'date';\n                        break;\n                    case 'number':\n                        type = 'numeric';\n                        break;\n                    case 'boolean':\n                        type = 'dropdown';\n                        break;\n                    default:\n                        type = 'text';\n                }\n\n                var columnDefinition = {\n                    data: inputExpression.id + '_expression',\n                    type: type,\n                    title: '<div class=\"input-header\">' +\n                    '<a onclick=\"triggerExpressionEditor(\\'input\\',' + expressionPosition + ',false)\"><span class=\"header-label\">' + (inputExpression.label ? inputExpression.label : \"New Input\") + '</span></a>' +\n                    '<br><span class=\"header-variable\">' + (inputExpression.variableId ? inputExpression.variableId : \"none\") + '</span>' +\n                    '<br/><span class=\"header-variable-type\">' + (inputExpression.type ? inputExpression.type : \"\") + '</brspan>' +\n                    '</div>' +\n                    '<div class=\"header-add-new-expression\">' +\n                    '<a onclick=\"triggerExpressionEditor(\\'input\\',' + expressionPosition + ',true)\"><span class=\"glyphicon glyphicon-plus-sign\"></span></a>' +\n                    '</div>',\n                    expressionType: 'input-expression',\n                    expression: inputExpression,\n                    className: 'htCenter',\n                    width: '200'\n                };\n\n                if (inputExpression.entries && inputExpression.entries.length > 0) {\n                    var entriesOptionValues = inputExpression.entries.slice(0, inputExpression.entries.length);\n                    entriesOptionValues.push('-');\n\n                    columnDefinition.type = 'dropdown';\n                    columnDefinition.strict = true;\n                    columnDefinition.source = entriesOptionValues;\n\n                    columnDefinition.title = '<div class=\"input-header\">' +\n                        '<a onclick=\"triggerExpressionEditor(\\'input\\',' + expressionPosition + ',false)\"><span class=\"header-label\">' + (inputExpression.label ? inputExpression.label : \"New Input\") + '</span></a>' +\n                        '<br><span class=\"header-variable\">' + (inputExpression.variableId ? inputExpression.variableId : \"none\") + '</span>' +\n                        '<br/><span class=\"header-variable-type\">' + (inputExpression.type ? inputExpression.type : \"\") + '</span>' +\n                        '<br><span class=\"header-entries\">[' + inputExpression.entries.join() + ']</span>' +\n                        '</div>' +\n                        '<div class=\"header-add-new-expression\">' +\n                        '<a onclick=\"triggerExpressionEditor(\\'input\\',' + expressionPosition + ',true)\"><span class=\"glyphicon glyphicon-plus-sign\"></span></a>' +\n                        '</div>';\n                } else if (type === 'text') {\n                    columnDefinition.validator = textValidator;\n                }\n\n                if (type === 'date') {\n                    columnDefinition.dateFormat = dateFormat;\n                    columnDefinition.validator = function (value, callback) {\n                        if (value === '-') {\n                            callback(true);\n                        } else {\n                            Handsontable.DateValidator.call(this, value, callback);\n                        }\n                    }\n\n                } else if (type === 'dropdown') {\n                    columnDefinition.source = ['true', 'false', '-'];\n                }\n\n                if (type !== 'text') {\n                    columnDefinition.allowEmpty = false;\n                }\n\n                return columnDefinition;\n            };\n\n            var composeOutputColumnDefinition = function (outputExpression) {\n                var expressionPosition = $scope.currentDecisionTable.outputExpressions.indexOf(outputExpression);\n\n                var type;\n                switch (outputExpression.type) {\n                    case 'date':\n                        type = 'date';\n                        break;\n                    case 'number':\n                        type = 'numeric';\n                        break;\n                    case 'boolean':\n                        type = 'dropdown';\n                        break;\n                    default:\n                        type = 'text';\n                }\n\n                var title = '';\n                var columnDefinition = {\n                    data: outputExpression.id,\n                    type: type,\n                    expressionType: 'output',\n                    expression: outputExpression,\n                    className: 'htCenter',\n                    width: '270'\n                };\n\n                if ($scope.currentDecisionTable.outputExpressions.length !== 1) {\n                    title = '<div class=\"header-remove-expression\">' +\n                        '<a onclick=\"triggerRemoveExpression(\\'output\\',' + expressionPosition + ',true)\"><span class=\"glyphicon glyphicon-minus-sign\"></span></a>' +\n                        '</div>';\n                }\n\n                if (outputExpression.entries && outputExpression.entries.length > 0) {\n                    var entriesOptionValues = outputExpression.entries.slice(0, outputExpression.entries.length);\n                    columnDefinition.type = 'dropdown';\n                    columnDefinition.source = entriesOptionValues;\n                    columnDefinition.strict = true;\n\n                    title += '<div class=\"output-header\">' +\n                        '<a onclick=\"triggerExpressionEditor(\\'output\\',' + expressionPosition + ',false)\"><span class=\"header-label\">' + (outputExpression.label ? outputExpression.label : \"New Output\") + '</span></a>' +\n                        '<br><span class=\"header-variable\">' + (outputExpression.variableId ? outputExpression.variableId : \"none\") + '</span>' +\n                        '<br/><span class=\"header-variable-type\">' + (outputExpression.type ? outputExpression.type : \"\") + '</span>' +\n                        '<br><span class=\"header-entries\">[' + outputExpression.entries.join() + ']</span>' +\n                        '</div>' +\n                        '<div class=\"header-add-new-expression\">' +\n                        '<a onclick=\"triggerExpressionEditor(\\'output\\',' + expressionPosition + ',true)\"><span class=\"glyphicon glyphicon-plus-sign\"></span></a>' +\n                        '</div>';\n\n                } else {\n                    title += '<div class=\"output-header\">' +\n                        '<a onclick=\"triggerExpressionEditor(\\'output\\',' + expressionPosition + ',false)\"><span class=\"header-label\">' + (outputExpression.label ? outputExpression.label : \"New Output\") + '</span></a>' +\n                        '<br><span class=\"header-variable\">' + (outputExpression.variableId ? outputExpression.variableId : \"none\") + '</span>' +\n                        '<br/><span class=\"header-variable-type\">' + (outputExpression.type ? outputExpression.type : \"\") + '</span>' +\n                        '</div>' +\n                        '<div class=\"header-add-new-expression\">' +\n                        '<a onclick=\"triggerExpressionEditor(\\'output\\',' + expressionPosition + ',true)\"><span class=\"glyphicon glyphicon-plus-sign\"></span></a>' +\n                        '</div>';\n                }\n\n                if (type === 'date') {\n                    columnDefinition.dateFormat = dateFormat;\n                } else if (type === 'dropdown') {\n                    columnDefinition.source = ['true', 'false', '-'];\n                }\n\n                columnDefinition.title = title;\n\n                return columnDefinition;\n            };\n\n            $scope.evaluateDecisionHeaders = function (decisionTable) {\n\n                var element = document.querySelector(\"thead > tr > th:first-of-type > div > a\");\n                if (element) {\n                    if (decisionTable.collectOperator) {\n                        element.innerHTML = decisionTable.hitIndicator.substring(0, 1) + collectOperators[decisionTable.collectOperator];\n                    } else {\n                        element.innerHTML = decisionTable.hitIndicator.substring(0, 1);\n                    }\n                }\n\n                var columnDefinitions = [];\n                var inputExpressionCounter = 0;\n                if (decisionTable.inputExpressions && decisionTable.inputExpressions.length > 0) {\n                    decisionTable.inputExpressions.forEach(function (inputExpression) {\n                        var inputOperatorColumnDefinition = composeInputOperatorColumnDefinition(inputExpression);\n                        columnDefinitions.push(inputOperatorColumnDefinition);\n                        setGridValues(inputOperatorColumnDefinition.data, inputOperatorColumnDefinition.expressionType);\n\n                        var inputExpressionColumnDefinition = composeInputExpressionColumnDefinition(inputExpression);\n                        columnDefinitions.push(inputExpressionColumnDefinition);\n                        setGridValues(inputExpressionColumnDefinition.data, inputExpressionColumnDefinition.expressionType);\n\n                        inputExpressionCounter += 2;\n                    });\n\n                } else { // create default input expression\n                    decisionTable.inputExpressions = [];\n                    var inputExpression = createNewInputExpression();\n                    decisionTable.inputExpressions.push(inputExpression);\n                    columnDefinitions.push(composeInputOperatorColumnDefinition(inputExpression));\n                    columnDefinitions.push(composeInputExpressionColumnDefinition(inputExpression));\n                    inputExpressionCounter += 2;\n                }\n\n                columnDefinitions[inputExpressionCounter - 1].className += ' last';\n                $scope.model.startOutputExpression = inputExpressionCounter;\n\n                if (decisionTable.outputExpressions && decisionTable.outputExpressions.length > 0) {\n                    decisionTable.outputExpressions.forEach(function (outputExpression) {\n                        columnDefinitions.push(composeOutputColumnDefinition(outputExpression));\n                    });\n\n                } else { // create default output expression\n                    decisionTable.outputExpressions = [];\n                    var outputExpression = createNewOutputExpression();\n                    decisionTable.outputExpressions.push(outputExpression);\n                    columnDefinitions.push(composeOutputColumnDefinition(outputExpression));\n                }\n\n                columnDefinitions[inputExpressionCounter].className += ' first';\n\n                // timeout needed for trigger hot update when removing column defs\n                $scope.model.columnDefs = columnDefinitions;\n                $timeout(function () {\n                    if (hotDecisionTableEditorInstance) {\n                        hotDecisionTableEditorInstance.render();\n                    }\n                });\n            };\n\n            var setGridValues = function (key, type) {\n                if ($scope.model.rulesData) {\n                    $scope.model.rulesData.forEach(function (rowData) {\n                        if (type === 'input-operator') {\n                            if (!(key in rowData) || rowData[key] === '') {\n                                rowData[key] = '==';\n                            }\n                        }\n                    });\n                }\n            };\n\n            var createDefaultRow = function () {\n                var defaultRow = {};\n                $scope.model.columnDefs.forEach(function (columnDefinition) {\n                    if (columnDefinition.expressionType === 'input-operator') {\n                        defaultRow[columnDefinition.data] = '==';\n                    }\n                    else if (columnDefinition.expressionType === 'input-expression') {\n                        defaultRow[columnDefinition.data] = '-';\n                    }\n                    else if (columnDefinition.expressionType === 'output') {\n                        defaultRow[columnDefinition.data] = '';\n                    }\n                });\n\n                return defaultRow;\n            };\n\n            var evaluateDecisionGrid = function (decisionTable) {\n                var tmpRuleGrid = [];\n\n                // rows\n                if (decisionTable.rules && decisionTable.rules.length > 0) {\n                    decisionTable.rules.forEach(function (rule) {\n\n                        // rule data\n                        var tmpRowValues = {};\n                        for (var i = 0; i < Object.keys(rule).length; i++) {\n                            var id = Object.keys(rule)[i];\n\n                            $scope.model.columnDefs.forEach(function (columnDef) {\n                                // set counter to max value\n                                var expressionId = 0;\n                                try {\n                                    expressionId = parseInt(columnDef.expression.id);\n                                } catch (e) {\n                                }\n                                if (expressionId > columnIdCounter) {\n                                    columnIdCounter = expressionId;\n                                }\n                            });\n\n                            // collection operators backwards compatibility\n                            // var cellValue = regressionTransformation(id, rule[id]);\n\n                            tmpRowValues[id] = rule[id];\n                        }\n\n                        tmpRuleGrid.push(tmpRowValues);\n                    });\n                } else {\n                    // initialize default values\n                    tmpRuleGrid.push(createDefaultRow());\n                }\n                // $rootScope.currentDecisionTableRules = tmpRuleGrid;\n                $scope.model.rulesData = tmpRuleGrid;\n            };\n\n            var evaluateDecisionTableGrid = function (decisionTable) {\n                $scope.evaluateDecisionHeaders(decisionTable);\n                evaluateDecisionGrid(decisionTable);\n            };\n\n\n            // fetch table from service and populate model\n            _loadDecisionTableDefinition($routeParams.modelId);\n\n            var _generateColumnId = function () {\n                columnIdCounter++;\n                return \"\" + columnIdCounter;\n            };\n\n        }]);\n\nangular.module('flowableModeler')\n    .controller('DecisionTableInputConditionEditorCtlr', ['$rootScope', '$scope', 'hotRegisterer', '$timeout', function ($rootScope, $scope, hotRegisterer, $timeout) {\n\n        var getEntriesValues = function (entriesArrayOfArrays) {\n            var newEntriesArray = [];\n            // remove last value\n            entriesArrayOfArrays.pop();\n\n            entriesArrayOfArrays.forEach(function (entriesArray) {\n                newEntriesArray.push(entriesArray[0]);\n            });\n\n            return newEntriesArray;\n        };\n\n        var createEntriesValues = function (entriesArray) {\n            var localCopy = entriesArray.slice(0);\n            var entriesArrayOfArrays = [];\n            while (localCopy.length) {\n                entriesArrayOfArrays.push(localCopy.splice(0, 1));\n            }\n\n            return entriesArrayOfArrays;\n        };\n\n        var deleteRowRenderer = function (instance, td, row) {\n            td.innerHTML = '';\n            td.className = 'remove_container';\n\n            if ((row + 1) != $scope.popup.selectedExpressionInputValues.length) {\n                var div = document.createElement('div');\n                div.onclick = function () {\n                    return instance.alter(\"remove_row\", row);\n                };\n                div.className = 'btn';\n                div.appendChild(document.createTextNode('x'));\n                td.appendChild(div);\n            }\n            return td;\n        };\n\n        // condition input options\n        if ($scope.model.newExpression === false) {\n            $scope.popup = {\n                selectedExpressionLabel: $scope.model.selectedExpression.label ? $scope.model.selectedExpression.label : '',\n                selectedExpressionVariableId: $scope.model.selectedExpression.variableId,\n                selectedExpressionVariableType: $scope.model.selectedExpression.type ? $scope.model.selectedExpression.type : $scope.model.availableInputVariableTypes[0],\n                selectedExpressionInputValues: $scope.model.selectedExpression.entries && $scope.model.selectedExpression.entries.length > 0 ? createEntriesValues($scope.model.selectedExpression.entries) : [['']],\n                columnDefs: [\n                    {\n                        width: '300'\n                    },\n                    {\n                        width: '40',\n                        readOnly: true,\n                        renderer: deleteRowRenderer\n                    }\n                ],\n                hotSettings: {\n                    stretchH: 'none'\n                }\n            };\n        } else {\n            $scope.popup = {\n                selectedExpressionLabel: '',\n                selectedExpressionVariableId: '',\n                selectedExpressionVariableType: $scope.model.availableInputVariableTypes[0],\n                selectedExpressionInputValues: [['']],\n                columnDefs: [\n                    {\n                        width: '300'\n\n                    },\n                    {\n                        renderer: deleteRowRenderer,\n                        readOnly: true,\n                        width: '40'\n                    }\n                ],\n                hotSettings: {\n                    stretchH: 'none'\n                }\n            };\n        }\n\n        $scope.save = function () {\n            if ($scope.model.newExpression) {\n                var newInputExpression = {\n                    variableId: $scope.popup.selectedExpressionVariableId,\n                    type: $scope.popup.selectedExpressionVariableType,\n                    label: $scope.popup.selectedExpressionLabel,\n                    entries: $scope.popup.selectedExpressionVariableType !== 'collection' ? getEntriesValues($scope.popup.selectedExpressionInputValues) : []\n                };\n\n                $scope.addNewInputExpression(newInputExpression, $scope.model.selectedColumn + 1);\n\n            } else {\n                $scope.model.selectedExpression.variableId = $scope.popup.selectedExpressionVariableId;\n                $scope.model.selectedExpression.type = $scope.popup.selectedExpressionVariableType;\n                $scope.model.selectedExpression.label = $scope.popup.selectedExpressionLabel;\n                $scope.model.selectedExpression.entries = $scope.popup.selectedExpressionVariableType !== 'collection' ? getEntriesValues($scope.popup.selectedExpressionInputValues) : [];\n                $scope.evaluateDecisionHeaders($scope.currentDecisionTable);\n            }\n\n            $scope.close();\n        };\n\n        $scope.setExpressionVariableType = function (variableType) {\n            $scope.popup.selectedExpressionVariable = null;\n            $scope.popup.selectedExpressionVariableType = variableType;\n        };\n\n        $scope.setNewVariable = function (value) {\n            $scope.popup.selectedExpressionNewVariable = value;\n            if (value) {\n                $scope.setExpressionVariableType('variable');\n            }\n        };\n\n        $scope.close = function () {\n            $scope.$hide();\n        };\n\n        // Cancel button handler\n        $scope.cancel = function () {\n            $scope.close();\n        };\n    }]);\n\nangular.module('flowableModeler')\n    .controller('DecisionTableConclusionEditorCtrl', ['$rootScope', '$scope', '$q', '$translate', 'hotRegisterer', function ($rootScope, $scope, $q, $translate, hotRegisterer) {\n\n        var hotInstance;\n        var getEntriesValues = function (entriesArrayOfArrays) {\n            var newEntriesArray = [];\n            // remove last value\n            entriesArrayOfArrays.pop();\n\n            entriesArrayOfArrays.forEach(function (entriesArray) {\n                newEntriesArray.push(entriesArray[0]);\n            });\n\n            return newEntriesArray;\n        };\n\n        var createEntriesValues = function (entriesArray) {\n            var localCopy = entriesArray.slice(0);\n            var entriesArrayOfArrays = [];\n            while (localCopy.length) {\n                entriesArrayOfArrays.push(localCopy.splice(0, 1));\n            }\n\n            return entriesArrayOfArrays;\n        };\n\n        var deleteRowRenderer = function (instance, td, row) {\n            td.innerHTML = '';\n            td.className = 'remove_container';\n\n            if ((row + 1) != $scope.popup.selectedExpressionOutputValues.length) {\n                var div = document.createElement('div');\n                div.onclick = function () {\n                    return instance.alter(\"remove_row\", row);\n                };\n                div.className = 'btn';\n                div.appendChild(document.createTextNode('x'));\n                td.appendChild(div);\n            }\n            return td;\n        };\n\n        $scope.doAfterRender = function () {\n            hotInstance = hotRegisterer.getInstance('decision-table-allowed-values');\n        };\n\n        if ($scope.model.newExpression === false) {\n            $scope.popup = {\n                selectedExpressionLabel: $scope.model.selectedExpression.label ? $scope.model.selectedExpression.label : '',\n                selectedExpressionNewVariableId: $scope.model.selectedExpression.variableId,\n                selectedExpressionNewVariableType: $scope.model.selectedExpression.type ? $scope.model.selectedExpression.type : $scope.model.availableOutputVariableTypes[0],\n                selectedExpressionOutputValues: $scope.model.selectedExpression.entries && $scope.model.selectedExpression.entries.length > 0 ? createEntriesValues($scope.model.selectedExpression.entries) : [['']],\n                currentHitPolicy: $scope.model.hitPolicy,\n                columnDefs: [\n                    {\n                        width: '250'\n                    },\n                    {\n                        width: '40',\n                        readOnly: true,\n                        renderer: deleteRowRenderer\n                    }\n                ],\n                hotSettings: {\n                    currentColClassName: 'currentCol',\n                    stretchH: 'none'\n                }\n            };\n        } else {\n            $scope.popup = {\n                selectedExpressionLabel: '',\n                selectedExpressionNewVariableId: '',\n                selectedExpressionNewVariableType: $scope.model.availableOutputVariableTypes[0],\n                selectedExpressionOutputValues: [['']],\n                currentHitPolicy: $scope.model.hitPolicy,\n                columnDefs: [\n                    {\n                        width: '250'\n                    },\n                    {\n                        width: '40',\n                        readOnly: true,\n                        renderer: deleteRowRenderer\n                    }\n                ],\n                hotSettings: {\n                    stretchH: 'none'\n                }\n            };\n        }\n\n        // Cancel button handler\n        $scope.cancel = function () {\n            $scope.close();\n        };\n\n        // Saving the edited input\n        $scope.save = function () {\n            if ($scope.model.newExpression) {\n                var newOutputExpression = {\n                    variableId: $scope.popup.selectedExpressionNewVariableId,\n                    type: $scope.popup.selectedExpressionNewVariableType,\n                    label: $scope.popup.selectedExpressionLabel,\n                    entries: getEntriesValues(hotInstance.getData())\n                };\n                $scope.addNewOutputExpression(newOutputExpression, $scope.model.selectedColumn + 1);\n\n            } else {\n                $scope.model.selectedExpression.variableId = $scope.popup.selectedExpressionNewVariableId;\n                $scope.model.selectedExpression.type = $scope.popup.selectedExpressionNewVariableType;\n                $scope.model.selectedExpression.label = $scope.popup.selectedExpressionLabel;\n                $scope.model.selectedExpression.entries = getEntriesValues(hotInstance.getData());\n                $scope.evaluateDecisionHeaders($scope.currentDecisionTable);\n            }\n\n            $scope.close();\n        };\n\n        $scope.close = function () {\n\n            $scope.$hide();\n        };\n\n        $scope.dumpData = function () {\n            console.log(hotInstance.getData());\n        }\n\n    }]);\n\nangular.module('flowableModeler')\n    .controller('DecisionTableHitPolicyEditorCtrl', ['$rootScope', '$scope', '$q', '$translate', function ($rootScope, $scope, $q, $translate) {\n\n        $scope.popup = {\n            currentHitPolicy: $scope.model.hitPolicy,\n            currentCollectOperator: $scope.model.collectOperator,\n            availableHitPolicies: $scope.hitPolicies,\n            availableCollectOperators: $scope.collectOperators\n        };\n\n        // Cancel button handler\n        $scope.cancel = function () {\n            $scope.close();\n        };\n\n        // Saving the edited input\n        $scope.save = function () {\n            $scope.currentDecisionTable.hitIndicator = $scope.popup.currentHitPolicy;\n            if ($scope.popup.currentHitPolicy === 'COLLECT') {\n                $scope.currentDecisionTable.collectOperator = $scope.popup.currentCollectOperator;\n            } else {\n                $scope.currentDecisionTable.collectOperator = undefined;\n            }\n\n            $scope.evaluateDecisionHeaders($scope.currentDecisionTable);\n\n            $scope.close();\n        };\n\n        $scope.close = function () {\n            $scope.$hide();\n        };\n\n    }]);\n"
  },
  {
    "path": "flowable-ui-web/modeler/scripts/controllers/decision-table-toolbar-controller.js",
    "content": "/* Copyright 2005-2015 Alfresco Software, Ltd.\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 */\nangular.module('flowableModeler')\n    .controller('DecisionTableToolbarController', ['$scope', '$http', '$modal', '$q', '$rootScope', '$translate', '$location', 'DecisionTableService',\n        function ($scope, $http, $modal, $q, $rootScope, $translate, $location, DecisionTableService) {\n\n    \tvar toolbarItems = DECISION_TABLE_TOOLBAR_CONFIG.items;\n        $scope.items = [];\n        \n        for (var i = 0; i < toolbarItems.length; i++)\n        {\n        \t$scope.items.push(toolbarItems[i]);\n        }\n        \n        $scope.secondaryItems = DECISION_TABLE_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, 'DecisionTableService': DecisionTableService};\n            executeFunctionByName(buttonClicked.action, window, services);\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, '$rootScope' : $rootScope, '$http' : $http, '$modal' : $modal, '$q' : $q, '$translate' : $translate, '$location': $location, 'DecisionTableService': DecisionTableService };\n            executeFunctionByName(buttonClicked.action, window, services);\n        };\n}]);"
  },
  {
    "path": "flowable-ui-web/modeler/scripts/controllers/decision-table.js",
    "content": "/* Copyright 2005-2015 Alfresco Software, Ltd.\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\nvar extScope;\n\nangular.module('flowableModeler')\n    .controller('DecisionTableDetailsCtrl', ['$rootScope', '$scope', '$translate', '$http', '$location', '$routeParams','$modal', '$timeout', '$popover', 'DecisionTableService', 'hotRegisterer',\n        function ($rootScope, $scope, $translate, $http, $location, $routeParams, $modal, $timeout, $popover, DecisionTableService, hotRegisterer) {\n\n            extScope = $scope;\n\n            $scope.decisionTableMode = 'read';\n\n            // Initialize model\n            $scope.model = {\n                // Store the main model id, this points to the current version of a model,\n                // even when we're showing history\n                latestModelId: $routeParams.modelId,\n                columnDefs: [],\n                columnVariableIdMap: {},\n                readOnly: true,\n                availableVariableTypes: ['string', 'number', 'boolean', 'date', 'collection']\n            };\n\n            // Hot Model init\n            $scope.model.hotSettings = {\n                stretchH: 'all',\n                outsideClickDeselects: false,\n                manualColumnResize: false,\n                readOnly: true,\n                disableVisualSelection: true\n            };\n\n            var hotReadOnlyDecisionTableEditorInstance;\n            var hitPolicies = ['FIRST', 'ANY', 'UNIQUE', 'PRIORITY', 'RULE ORDER', 'OUTPUT ORDER', 'COLLECT'];\n            var operators = ['==', '!=', '<', '>', '>=', '<=', 'ANY OF', 'NONE OF', 'ALL OF', 'NOT ALL OF', 'IS IN', 'IS NOT IN'];\n            var columnIdCounter = 0;\n            var dateFormat = 'YYYY-MM-DD';\n\n            var variableUndefined = $translate.instant('DECISION-TABLE-EDITOR.EMPTY-MESSAGES.NO-VARIABLE-SELECTED');\n            // helper for looking up variable id by col id\n            $scope.getVariableNameByColumnId = function (colId) {\n\n                if (!colId) {\n                    return;\n                }\n\n                if ($scope.model.columnVariableIdMap[colId]) {\n                    return $scope.model.columnVariableIdMap[colId];\n                } else {\n                    return variableUndefined;\n                }\n            };\n\n            $scope.loadDecisionTable = function() {\n                var url, decisionTableUrl;\n                if ($routeParams.modelHistoryId) {\n                    url = FLOWABLE.APP_URL.getModelHistoryUrl($routeParams.modelId, $routeParams.modelHistoryId);\n                    decisionTableUrl = FLOWABLE.APP_URL.getDecisionTableModelsHistoryUrl($routeParams.modelHistoryId);\n                } else {\n                    url = FLOWABLE.APP_URL.getModelUrl($routeParams.modelId);\n                    decisionTableUrl = FLOWABLE.APP_URL.getDecisionTableModelUrl($routeParams.modelId);\n                }\n\n                $http({method: 'GET', url: url}).\n                    success(function(data, status, headers, config) {\n                        $scope.model.decisionTable = data;\n                        $scope.model.decisionTableDownloadUrl = decisionTableUrl + '/export?version=' + Date.now();\n                        $scope.loadVersions();\n\n                    }).error(function(data, status, headers, config) {\n                        $scope.returnToList();\n                    });\n            };\n\n            $scope.useAsNewVersion = function() {\n                _internalCreateModal({\n                    template: 'views/popup/model-use-as-new-version.html',\n                    scope: $scope\n                }, $modal, $scope);\n            };\n\n            $scope.toggleFavorite = function() {\n                $scope.model.favoritePending = true;\n\n                var data = {\n                    favorite: !$scope.model.decisionTable.favorite\n                };\n\n                $http({method: 'PUT', url: FLOWABLE.APP_URL.getModelUrl($scope.model.latestModelId), data: data}).\n                    success(function(data, status, headers, config) {\n                        $scope.model.favoritePending = false;\n                        if ($scope.model.decisionTable.favorite) {\n                            $scope.addAlertPromise($translate('DECISION-TABLE.ALERT.UN-FAVORITE-CONFIRM'), 'info');\n                        } else {\n                            $scope.addAlertPromise($translate('DECISION-TABLE.ALERT.FAVORITE-CONFIRM'), 'info');\n                        }\n                        $scope.model.decisionTable.favorite = !$scope.model.decisionTable.favorite;\n                    }).error(function(data, status, headers, config) {\n                        $scope.model.favoritePending = false;\n                    });\n            };\n\n\n            $scope.loadVersions = function() {\n\n                var params = {\n                    includeLatestVersion: !$scope.model.decisionTable.latestVersion\n                };\n\n                $http({method: 'GET', url: FLOWABLE.APP_URL.getModelHistoriesUrl($scope.model.latestModelId), params: params}).\n                    success(function(data, status, headers, config) {\n                        if ($scope.model.decisionTable.latestVersion) {\n                            if (!data.data) {\n                                data.data = [];\n                            }\n                            data.data.unshift($scope.model.decisionTable);\n                        }\n\n                        $scope.model.versions = data;\n                    });\n            };\n\n            $scope.showVersion = function(version) {\n                if (version) {\n                    if (version.latestVersion) {\n                        $location.path(\"/decision-tables/\" +  $scope.model.latestModelId);\n                    } else {\n                        // Show latest version, no history-suffix needed in URL\n                        $location.path(\"/decision-tables/\" +  $scope.model.latestModelId + \"/history/\" + version.id);\n                    }\n                }\n            };\n\n            $scope.returnToList = function() {\n                $location.path(\"/decision-tables/\");\n            };\n\n            $scope.editDecisionTable = function() {\n                _internalCreateModal({\n                    template: 'views/popup/model-edit.html',\n                    scope: $scope\n                }, $modal, $scope);\n            };\n\n            $scope.duplicateDecisionTable = function() {\n\n                var modalInstance = _internalCreateModal({\n                    template: 'views/popup/decision-table-duplicate.html?version=' + Date.now()\n                }, $modal, $scope);\n\n                modalInstance.$scope.originalModel = $scope.model;\n\n                modalInstance.$scope.duplicateDecisionTableCallback = function(result) {\n                    $rootScope.editorHistory = [];\n                    $location.url(\"/decision-table-editor/\" + encodeURIComponent(result.id));\n                };\n            };\n\n            $scope.deleteDecisionTable = function() {\n                _internalCreateModal({\n                    template: 'views/popup/model-delete.html',\n                    scope: $scope\n                }, $modal, $scope);\n            };\n\n            $scope.shareDecisionTable = function() {\n                _internalCreateModal({\n                    template: 'views/popup/model-share.html',\n                    scope: $scope\n                }, $modal, $scope);\n            };\n\n            $scope.openEditor = function() {\n                if ($scope.model.decisionTable) {\n                    $location.path(\"/decision-table-editor/\" + $scope.model.decisionTable.id);\n                }\n            };\n\n            $scope.toggleHistory = function($event) {\n                if (!$scope.historyState) {\n                    var state = {};\n                    $scope.historyState = state;\n\n                    // Create popover\n                    state.popover = $popover(angular.element($event.target), {\n                        template: 'views/popover/history.html',\n                        placement: 'bottom-right',\n                        show: true,\n                        scope: $scope,\n                        container: 'body'\n                    });\n\n                    var destroy = function() {\n                        state.popover.destroy();\n                        delete $scope.historyState;\n                    };\n\n                    // When popup is hidden or scope is destroyed, hide popup\n                    state.popover.$scope.$on('tooltip.hide', destroy);\n                    $scope.$on('$destroy', destroy);\n                }\n            };\n\n            $scope.doAfterGetColHeader = function (col, TH) {\n                if ($scope.model.columnDefs[col] && $scope.model.columnDefs[col].expressionType === 'input-operator') {\n                    TH.className += \"input-operator-header\";\n                } else if ($scope.model.columnDefs[col] && $scope.model.columnDefs[col].expressionType === 'input-expression') {\n                    TH.className += \"input-expression-header\";\n                    if ($scope.model.startOutputExpression - 1 === col) {\n                        TH.className += \" last\";\n                    }\n                } else if ($scope.model.columnDefs[col] && $scope.model.columnDefs[col].expressionType === 'output') {\n                    TH.className += \"output-header\";\n                    if ($scope.model.startOutputExpression === col) {\n                        TH.className += \" first\";\n                    }\n                }\n            };\n\n            $scope.doAfterModifyColWidth = function (width, col) {\n                if ($scope.model.columnDefs[col] && $scope.model.columnDefs[col].width) {\n                    var settingsWidth = $scope.model.columnDefs[col].width;\n                    if (settingsWidth > width) {\n                        return settingsWidth;\n                    }\n                }\n                return width;\n            };\n\n            $scope.doAfterRender = function () {\n                var element = document.querySelector(\"thead > tr > th:first-of-type\");\n                if (element) {\n                    var firstChild = element.firstChild;\n                    var newElement = angular.element('<div class=\"hit-policy-header\"><a onclick=\"triggerHitPolicyEditor()\">' + $scope.currentDecisionTable.hitIndicator.substring(0, 1) + '</a></div>');\n                    element.className = 'hit-policy-container';\n                    element.replaceChild(newElement[0], firstChild);\n                }\n\n                $timeout(function () {\n                    hotReadOnlyDecisionTableEditorInstance = hotRegisterer.getInstance('read-only-decision-table-editor');\n                    if (hotReadOnlyDecisionTableEditorInstance) {\n                        hotReadOnlyDecisionTableEditorInstance.validateCells();\n                    }\n                });\n            };\n\n            $scope.doAfterValidate = function (isValid, value, row, prop, source) {\n                if (isCorrespondingCollectionOperator(row, prop)) {\n                    return true;\n                } else if (isCustomExpression(value) || isDashValue(value)) {\n                    disableCorrespondingOperatorCell(row, prop);\n                    return true;\n                } else {\n                    enableCorrespondingOperatorCell(row, prop);\n                }\n            };\n\n            var isCustomExpression = function (val) {\n                return !!(val != null\n                    && (String(val).startsWith('${') || String(val).startsWith('#{')));\n            };\n\n            var isDashValue = function (val) {\n                return !!(val != null && \"-\" === val);\n            };\n\n            var isCorrespondingCollectionOperator = function (row, prop) {\n                var operatorCol = getCorrespondingOperatorCell(row, prop);\n                var operatorCellMeta = hotReadOnlyDecisionTableEditorInstance.getCellMeta(row, operatorCol);\n\n                var isCollectionOperator = false;\n                if (isOperatorCell(operatorCellMeta)) {\n                    var operatorValue = hotReadOnlyDecisionTableEditorInstance.getDataAtCell(row, operatorCol);\n                    if (operatorValue === \"IN\" || operatorValue === \"NOT IN\" || operatorValue === \"ANY\" || operatorValue === \"NOT ANY\") {\n                        isCollectionOperator = true;\n                    }\n                }\n                return isCollectionOperator;\n            };\n\n            var disableCorrespondingOperatorCell = function (row, prop) {\n                var operatorCol = getCorrespondingOperatorCell(row, prop);\n                var operatorCellMeta = hotReadOnlyDecisionTableEditorInstance.getCellMeta(row, operatorCol);\n\n                if (!isOperatorCell(operatorCellMeta)) {\n                    return;\n                }\n\n                if (operatorCellMeta.className != null && operatorCellMeta.className.indexOf('custom-expression-operator') !== -1) {\n                    return;\n                }\n\n                var currentEditor = hotReadOnlyDecisionTableEditorInstance.getCellEditor(row, operatorCol);\n\n                hotReadOnlyDecisionTableEditorInstance.setCellMeta(row, operatorCol, 'className', operatorCellMeta.className + ' custom-expression-operator');\n                hotReadOnlyDecisionTableEditorInstance.setCellMeta(row, operatorCol, 'originalEditor', currentEditor);\n                hotReadOnlyDecisionTableEditorInstance.setCellMeta(row, operatorCol, 'editor', false);\n                hotReadOnlyDecisionTableEditorInstance.setDataAtCell(row, operatorCol, null);\n            };\n\n            var enableCorrespondingOperatorCell = function (row, prop) {\n                var operatorCol = getCorrespondingOperatorCell(row, prop);\n                var operatorCellMeta = hotReadOnlyDecisionTableEditorInstance.getCellMeta(row, operatorCol);\n\n                if (!isOperatorCell(operatorCellMeta)) {\n                    return;\n                }\n\n                if (operatorCellMeta == null || operatorCellMeta.className == null || operatorCellMeta.className.indexOf('custom-expression-operator') == -1) {\n                    return;\n                }\n\n                operatorCellMeta.className = operatorCellMeta.className.replace('custom-expression-operator', '');\n                hotReadOnlyDecisionTableEditorInstance.setCellMeta(row, operatorCol, 'className', operatorCellMeta.className);\n                hotReadOnlyDecisionTableEditorInstance.setCellMeta(row, operatorCol, 'editor', operatorCellMeta.originalEditor);\n                hotReadOnlyDecisionTableEditorInstance.setDataAtCell(row, operatorCol, '==');\n            };\n\n            var getCorrespondingOperatorCell = function (row, prop) {\n                var currentCol = hotReadOnlyDecisionTableEditorInstance.propToCol(prop);\n                if (currentCol < 1) {\n                    return;\n                }\n                var operatorCol = currentCol - 1;\n                return operatorCol;\n            };\n\n            var isOperatorCell = function (cellMeta) {\n                return !(cellMeta == null || cellMeta.prop == null || typeof cellMeta.prop !== 'string'|| cellMeta.prop.endsWith(\"_operator\") === false);\n            };\n\n            var createNewInputExpression = function (inputExpression) {\n                var newInputExpression;\n                if (inputExpression) {\n                    newInputExpression = {\n                        id: _generateColumnId(),\n                        label: inputExpression.label,\n                        variableId: inputExpression.variableId,\n                        type: inputExpression.type,\n                        newVariable: inputExpression.newVariable,\n                        entries: inputExpression.entries\n                    };\n                } else {\n                    newInputExpression = {\n                        id: _generateColumnId(),\n                        label: null,\n                        variableId: null,\n                        type: null,\n                        newVariable: null,\n                        entries: null\n                    };\n                }\n                return newInputExpression;\n            };\n\n            $scope.openHitPolicyEditor = function () {\n                var editTemplate = 'views/popup/decision-table-edit-hit-policy.html';\n\n                $scope.model.hitPolicy = $scope.currentDecisionTable.hitIndicator;\n\n                _internalCreateModal({\n                    template: editTemplate,\n                    scope: $scope\n                }, $modal, $scope);\n            };\n\n            $scope.openInputExpressionEditor = function (expressionPos, newExpression) {\n                var editTemplate = 'views/popup/decision-table-edit-input-expression.html';\n\n                $scope.model.newExpression = !!newExpression;\n\n                if (!$scope.model.newExpression) {\n                    $scope.model.selectedExpression = $scope.currentDecisionTable.inputExpressions[expressionPos];\n                } else {\n                    if (expressionPos >= $scope.model.startOutputExpression) {\n                        $scope.model.selectedColumn = $scope.model.startOutputExpression - 1;\n                    } else {\n                        $scope.model.selectedColumn = Math.floor(expressionPos / 2);\n                    }\n                }\n\n                _internalCreateModal({\n                    template: editTemplate,\n                    scope: $scope\n                }, $modal, $scope);\n            };\n\n            $scope.openOutputExpressionEditor = function (expressionPos, newExpression) {\n                var editTemplate = 'views/popup/decision-table-edit-output-expression.html';\n\n                $scope.model.newExpression = !!newExpression;\n                $scope.model.hitPolicy = $scope.currentDecisionTable.hitIndicator;\n                $scope.model.selectedColumn = expressionPos;\n\n\n                if (!$scope.model.newExpression) {\n                    $scope.model.selectedExpression = $scope.currentDecisionTable.outputExpressions[expressionPos];\n                }\n\n                _internalCreateModal({\n                    template: editTemplate,\n                    scope: $scope\n                }, $modal, $scope);\n            };\n\n            var createNewOutputExpression = function (outputExpression) {\n                var newOutputExpression;\n                if (outputExpression) {\n                    newOutputExpression = {\n                        id: _generateColumnId(),\n                        label: outputExpression.label,\n                        variableId: outputExpression.variableId,\n                        type: outputExpression.variableType,\n                        newVariable: outputExpression.newVariable,\n                        entries: outputExpression.entries\n                    };\n                } else {\n                    newOutputExpression = {\n                        id: _generateColumnId(),\n                        label: null,\n                        variableId: null,\n                        type: null,\n                        newVariable: null,\n                        entries: null\n                    };\n                }\n                return newOutputExpression;\n            };\n\n            var _loadDecisionTableDefinition = function (modelId, historyId) {\n                DecisionTableService.fetchDecisionTableDetails(modelId, historyId).then(function (decisionTable) {\n\n                    $rootScope.currentDecisionTable = decisionTable.decisionTableDefinition;\n                    $rootScope.currentDecisionTable.id = decisionTable.id;\n                    $rootScope.currentDecisionTable.key = decisionTable.decisionTableDefinition.key;\n                    $rootScope.currentDecisionTable.name = decisionTable.name;\n                    $rootScope.currentDecisionTable.description = decisionTable.description;\n\n                    // decision table model to used in save dialog\n                    $rootScope.currentDecisionTableModel = {\n                        id: decisionTable.id,\n                        name: decisionTable.name,\n                        key: decisionTable.decisionTableDefinition.key,\n                        description: decisionTable.description\n                    };\n\n                    if (!$rootScope.currentDecisionTable.hitIndicator) {\n                        $rootScope.currentDecisionTable.hitIndicator = hitPolicies[0];\n                    }\n\n                    evaluateDecisionTableGrid($rootScope.currentDecisionTable);\n\n                });\n            };\n\n            var evaluateDecisionTableGrid = function (decisionTable) {\n                $scope.evaluateDecisionHeaders(decisionTable);\n                evaluateDecisionGrid(decisionTable);\n            };\n\n            var setGridValues = function (key, type) {\n                if ($scope.model.rulesData) {\n                    $scope.model.rulesData.forEach(function (rowData) {\n                        if (type === 'input-operator') {\n                            if (!(key in rowData) || rowData[key] === '') {\n                                rowData[key] = '==';\n                            }\n                        }\n                        // else if (type === 'input-expression') {\n                        //     if (!(key in rowData) || rowData[key] === '') {\n                        //         rowData[key] = '-';\n                        //     }\n                        // }\n                    });\n                }\n            };\n\n            var evaluateDecisionGrid = function (decisionTable) {\n                var tmpRuleGrid = [];\n\n                // rows\n                if (decisionTable.rules && decisionTable.rules.length > 0) {\n                    decisionTable.rules.forEach(function (rule) {\n\n                        // rule data\n                        var tmpRowValues = {};\n                        for (var i = 0; i < Object.keys(rule).length; i++) {\n                            var id = Object.keys(rule)[i];\n\n                            $scope.model.columnDefs.forEach(function (columnDef) {\n                                // set counter to max value\n                                var expressionId = 0;\n                                try {\n                                    expressionId = parseInt(columnDef.expression.id);\n                                } catch (e) {\n                                }\n                                if (expressionId > columnIdCounter) {\n                                    columnIdCounter = expressionId;\n                                }\n                            });\n\n                            tmpRowValues[id] = rule[id];\n                        }\n\n                        tmpRuleGrid.push(tmpRowValues);\n                    });\n                } else {\n                    // initialize default values\n                    tmpRuleGrid.push(createDefaultRow());\n                }\n                // $rootScope.currentDecisionTableRules = tmpRuleGrid;\n                $scope.model.rulesData = tmpRuleGrid;\n            };\n\n            var createDefaultRow = function () {\n                var defaultRow = {};\n                $scope.model.columnDefs.forEach(function (columnDefinition) {\n                    if (columnDefinition.expressionType === 'input-operator') {\n                        defaultRow[columnDefinition.data] = '==';\n                    }\n                    // else if (columnDefinition.expressionType === 'input-expression') {\n                    //     defaultRow[columnDefinition.data] = '-';\n                    // }\n                    else if (columnDefinition.expressionType === 'output') {\n                        defaultRow[columnDefinition.data] = '';\n                    }\n                });\n\n                return defaultRow;\n            };\n\n            var composeInputOperatorColumnDefinition = function (inputExpression) {\n                var expressionPosition = $scope.currentDecisionTable.inputExpressions.indexOf(inputExpression);\n\n                var columnDefinition = {\n                    data: inputExpression.id + '_operator',\n                    expressionType: 'input-operator',\n                    expression: inputExpression,\n                    width: '70',\n                    className: 'input-operator-cell',\n                    type: 'dropdown',\n                    source: operators\n                };\n\n                return columnDefinition;\n            };\n\n            var composeInputExpressionColumnDefinition = function (inputExpression) {\n                var expressionPosition = $scope.currentDecisionTable.inputExpressions.indexOf(inputExpression);\n\n                var type;\n                switch (inputExpression.type) {\n                    case 'date':\n                        type = 'date';\n                        break;\n                    case 'number':\n                        type = 'numeric';\n                        break;\n                    case 'boolean':\n                        type = 'dropdown';\n                        break;\n                    default:\n                        type = 'text';\n                }\n\n                var columnDefinition = {\n                    data: inputExpression.id + '_expression',\n                    type: type,\n                    title: '<div class=\"input-header\">' +\n                    '<a onclick=\"triggerExpressionEditor(\\'input\\',' + expressionPosition + ',false)\"><span class=\"header-label\">' + (inputExpression.label ? inputExpression.label : \"New Input\") + '</span></a>' +\n                    '<br><span class=\"header-variable\">' + (inputExpression.variableId ? inputExpression.variableId : \"none\") + '</span>' +\n                    '<br/><span class=\"header-variable-type\">' + (inputExpression.type ? inputExpression.type : \"\") + '</brspan>' +\n                    '</div>',\n                    expressionType: 'input-expression',\n                    expression: inputExpression,\n                    className: 'htCenter',\n                    width: '200'\n                };\n\n                if (inputExpression.entries && inputExpression.entries.length > 0) {\n                    var entriesOptionValues = inputExpression.entries.slice(0, inputExpression.entries.length);\n                    entriesOptionValues.push('-', '', ' ');\n\n                    columnDefinition.type = 'dropdown';\n                    columnDefinition.strict = true;\n                    columnDefinition.source = entriesOptionValues;\n\n                    columnDefinition.title = '<div class=\"input-header\">' +\n                        '<a onclick=\"triggerExpressionEditor(\\'input\\',' + expressionPosition + ',false)\"><span class=\"header-label\">' + (inputExpression.label ? inputExpression.label : \"New Input\") + '</span></a>' +\n                        '<br><span class=\"header-variable\">' + (inputExpression.variableId ? inputExpression.variableId : \"none\") + '</span>' +\n                        '<br/><span class=\"header-variable-type\">' + (inputExpression.type ? inputExpression.type : \"\") + '</span>' +\n                        '<br><span class=\"header-entries\">[' + inputExpression.entries.join() + ']</span>' +\n                        '</div>';\n                }\n\n                if (type === 'date') {\n                    columnDefinition.dateFormat = dateFormat;\n                } else if (type === 'dropdown') {\n                    columnDefinition.source = ['true', 'false', '-'];\n                }\n\n                return columnDefinition;\n            };\n\n            var composeOutputColumnDefinition = function (outputExpression) {\n                var expressionPosition = $scope.currentDecisionTable.outputExpressions.indexOf(outputExpression);\n\n                var type;\n                switch (outputExpression.type) {\n                    case 'date':\n                        type = 'date';\n                        break;\n                    case 'number':\n                        type = 'numeric';\n                        break;\n                    case 'boolean':\n                        type = 'dropdown';\n                        break;\n                    default:\n                        type = 'text';\n                }\n\n                var title = '';\n                var columnDefinition = {\n                    data: outputExpression.id,\n                    type: type,\n                    expressionType: 'output',\n                    expression: outputExpression,\n                    className: 'htCenter',\n                    width: '270'\n                };\n\n                if (outputExpression.entries && outputExpression.entries.length > 0) {\n                    var entriesOptionValues = outputExpression.entries.slice(0, outputExpression.entries.length);\n                    columnDefinition.type = 'dropdown';\n                    columnDefinition.source = entriesOptionValues;\n                    columnDefinition.strict = true;\n\n                    title += '<div class=\"output-header\">' +\n                        '<a onclick=\"triggerExpressionEditor(\\'output\\',' + expressionPosition + ',false)\"><span class=\"header-label\">' + (outputExpression.label ? outputExpression.label : \"New Output\") + '</span></a>' +\n                        '<br><span class=\"header-variable\">' + (outputExpression.variableId ? outputExpression.variableId : \"none\") + '</span>' +\n                        '<br/><span class=\"header-variable-type\">' + (outputExpression.type ? outputExpression.type : \"\") + '</span>' +\n                        '<br><span class=\"header-entries\">[' + outputExpression.entries.join() + ']</span>' +\n                        '</div>';\n                } else {\n                    title += '<div class=\"output-header\">' +\n                        '<a onclick=\"triggerExpressionEditor(\\'output\\',' + expressionPosition + ',false)\"><span class=\"header-label\">' + (outputExpression.label ? outputExpression.label : \"New Output\") + '</span></a>' +\n                        '<br><span class=\"header-variable\">' + (outputExpression.variableId ? outputExpression.variableId : \"none\") + '</span>' +\n                        '<br/><span class=\"header-variable-type\">' + (outputExpression.type ? outputExpression.type : \"\") + '</span>' +\n                        '</div>'\n                }\n\n                if (type === 'date') {\n                    columnDefinition.dateFormat = dateFormat;\n                } else if (type === 'dropdown') {\n                    columnDefinition.source = ['true', 'false', '-'];\n                }\n\n                columnDefinition.title = title;\n\n                return columnDefinition;\n            };\n\n            $scope.evaluateDecisionHeaders = function (decisionTable) {\n                var columnDefinitions = [];\n                var inputExpressionCounter = 0;\n                if (decisionTable.inputExpressions && decisionTable.inputExpressions.length > 0) {\n                    decisionTable.inputExpressions.forEach(function (inputExpression) {\n                        var inputOperatorColumnDefinition = composeInputOperatorColumnDefinition(inputExpression);\n                        columnDefinitions.push(inputOperatorColumnDefinition);\n                        setGridValues(inputOperatorColumnDefinition.data, inputOperatorColumnDefinition.expressionType);\n\n                        var inputExpressionColumnDefinition = composeInputExpressionColumnDefinition(inputExpression);\n                        columnDefinitions.push(inputExpressionColumnDefinition);\n                        setGridValues(inputExpressionColumnDefinition.data, inputExpressionColumnDefinition.expressionType);\n\n                        inputExpressionCounter += 2;\n                    });\n                } else { // create default input expression\n                    decisionTable.inputExpressions = [];\n                    var inputExpression = createNewInputExpression();\n                    decisionTable.inputExpressions.push(inputExpression);\n                    columnDefinitions.push(composeInputOperatorColumnDefinition(inputExpression));\n                    columnDefinitions.push(composeInputExpressionColumnDefinition(inputExpression));\n                    inputExpressionCounter += 2;\n                }\n\n                columnDefinitions[inputExpressionCounter - 1].className += ' last';\n                $scope.model.startOutputExpression = inputExpressionCounter;\n\n                if (decisionTable.outputExpressions && decisionTable.outputExpressions.length > 0) {\n                    decisionTable.outputExpressions.forEach(function (outputExpression) {\n                        columnDefinitions.push(composeOutputColumnDefinition(outputExpression));\n                    });\n                } else { // create default output expression\n                    decisionTable.outputExpressions = [];\n                    var outputExpression = createNewOutputExpression();\n                    decisionTable.outputExpressions.push(outputExpression);\n                    columnDefinitions.push(composeOutputColumnDefinition(outputExpression));\n                }\n\n                columnDefinitions[inputExpressionCounter].className += ' first';\n\n                // timeout needed for trigger hot update when removing column defs\n                $scope.model.columnDefs = columnDefinitions;\n                $timeout(function () {\n                    if (hotReadOnlyDecisionTableEditorInstance) {\n                        hotReadOnlyDecisionTableEditorInstance.render();\n                    }\n                });\n            };\n\n            // fetch table from service and populate model\n            _loadDecisionTableDefinition($routeParams.modelId, $routeParams.modelHistoryId);\n\n            var _generateColumnId = function () {\n                columnIdCounter++;\n                return \"\" + columnIdCounter;\n            };\n\n            // Load model needed for favorites\n            $scope.loadDecisionTable();\n\n        }]);\n"
  },
  {
    "path": "flowable-ui-web/modeler/scripts/controllers/decision-tables.js",
    "content": "/* Copyright 2005-2015 Alfresco Software, Ltd.\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'use strict';\n\nangular.module('flowableModeler')\n  .controller('DecisionTablesController', ['$rootScope', '$scope', '$translate', '$http', '$timeout','$location', '$modal', function ($rootScope, $scope, $translate, $http, $timeout, $location, $modal) {\n\n\t  $rootScope.setMainPageById('decision-tables');\n\t  $rootScope.decisionTableItems = undefined;\n\n      // get latest thumbnails\n      $scope.imageVersion = Date.now();\n\n\t  $scope.model = {\n        filters: [\n            {id: 'decisionTables', labelKey: 'DECISION-TABLES'}\n\t\t],\n\n\t\tsorts: [\n\t\t        {id: 'modifiedDesc', labelKey: 'MODIFIED-DESC'},\n\t\t        {id: 'modifiedAsc', labelKey: 'MODIFIED-ASC'},\n\t\t        {id: 'nameAsc', labelKey: 'NAME-ASC'},\n\t\t        {id: 'nameDesc', labelKey: 'NAME-DESC'}\n\t\t]\n\t  };\n\n\t  if ($rootScope.decisionTableFilter) {\n\t\t  $scope.model.activeFilter = $rootScope.decisionTableFilter.filter;\n\t\t  $scope.model.activeSort = $rootScope.decisionTableFilter.sort;\n\t\t  $scope.model.filterText = $rootScope.decisionTableFilter.filterText;\n\t\t  $scope.model.pendingFilterText = $scope.model.filterText; // The search textfield uses this\n\n\t  } else {\n\t\t  // By default, show first filter and use first sort\n\t      $scope.model.activeFilter = $scope.model.filters[0];\n\t      $scope.model.activeSort = $scope.model.sorts[0];\n\t      $rootScope.decisionTableFilter = {\n\t        filter: $scope.model.activeFilter,\n\t        sort: $scope.model.activeSort,\n\t        filterText: ''\n\t      };\n\t  }\n\n\t  $scope.activateFilter = function(filter) {\n\t\t  $scope.model.activeFilter = filter;\n\t\t  $rootScope.decisionTableFilter.filter = filter;\n\t\t  $scope.loadDecisionTables();\n\t  };\n\n\t  $scope.activateSort = function(sort) {\n\t\t  $scope.model.activeSort = sort;\n\t\t  $rootScope.decisionTableFilter.sort = sort;\n\t\t  $scope.loadDecisionTables();\n\t  };\n\n\t  $scope.importDecisionTable = function () {\n          _internalCreateModal({\n              template: 'views/popup/decision-table-import.html?version=' + Date.now()\n          }, $modal, $scope);\n      };\n\n\t  $scope.loadDecisionTables = function() {\n\t\t  $scope.model.loading = true;\n\n\t\t  var params = {\n\t\t      filter: $scope.model.activeFilter.id,\n\t\t      sort: $scope.model.activeSort.id,\n\t\t      modelType: 4\n\t\t  };\n\n\t\t  if ($scope.model.filterText && $scope.model.filterText != '') {\n\t\t    params.filterText = $scope.model.filterText;\n\t\t  }\n\n\t\t  $http({method: 'GET', url: FLOWABLE.APP_URL.getModelsUrl(), params: params}).\n\t\t  \tsuccess(function(data, status, headers, config) {\n\t    \t\t$scope.model.decisionTables = data;\n\t    \t\t$scope.model.loading = false;\n\t        }).\n\t        error(function(data, status, headers, config) {\n\t           $scope.model.loading = false;\n\t        });\n\t  };\n\n\t  var timeoutFilter = function() {\n\t    $scope.model.isFilterDelayed = true;\n\t    $timeout(function() {\n\t        $scope.model.isFilterDelayed = false;\n\t        if($scope.model.isFilterUpdated) {\n\t          $scope.model.isFilterUpdated = false;\n\t          timeoutFilter();\n\t        } else {\n\t          $scope.model.filterText = $scope.model.pendingFilterText;\n\t          $rootScope.decisionTableFilter.filterText = $scope.model.filterText;\n\t          $scope.loadDecisionTables();\n\t        }\n\t    }, 500);\n\t  };\n\n\t  $scope.filterDelayed = function() {\n\t    if($scope.model.isFilterDelayed) {\n\t      $scope.model.isFilterUpdated = true;\n\t    } else {\n\t      timeoutFilter();\n\t    }\n\t  };\n\n\t  $scope.createDecisionTable = function() {\n\t\t  $rootScope.currentKickstartModel = undefined;\n\t      $rootScope.currentDecisionTableModel = undefined;\n\t\t  $scope.createDecisionTableCallback = function(result) {\n\t\t      $rootScope.editorHistory = [];\n\t\t      $location.url(\"/decision-table-editor/\" + encodeURIComponent(result.id));\n\t\t  };\n\n          _internalCreateModal({\n\t\t\t  template: 'views/popup/decision-table-create.html?version=' + Date.now(),\n\t\t\t  scope: $scope\n\t\t  }, $modal, $scope);\n\t  };\n\n\t  $scope.showDecisionTableDetails = function(decisionTable) {\n\t      if (decisionTable) {\n\t      \t  $rootScope.editorHistory = [];\n\t\t\t  $rootScope.currentKickstartModel = undefined;\n\t          $location.url(\"/decision-tables/\" + encodeURIComponent(decisionTable.id));\n\t      }\n\t  };\n\n\t  $scope.editDecisionTableDetails = function(decisionTable) {\n\t\t  if (decisionTable) {\n\t\t  \t  $rootScope.editorHistory = [];\n\t\t\t  $location.url(\"/decision-table-editor/\" + encodeURIComponent(decisionTable.id));\n\t\t  }\n\t  };\n\n\t  // Finally, load initial decisionTables\n\t  $scope.loadDecisionTables();\n  }]);\n\n\nangular.module('flowableModeler')\n.controller('CreateNewDecisionTableCtrl', ['$rootScope', '$scope', '$http', function ($rootScope, $scope, $http) {\n\n    $scope.model = {\n       loading: false,\n       decisionTable: {\n            name: '',\n            key: '',\n            description: '',\n            modelType: 4\n       }\n    };\n\n    $scope.ok = function () {\n\n        if (!$scope.model.decisionTable.name || $scope.model.decisionTable.name.length == 0 ||\n        \t!$scope.model.decisionTable.key || $scope.model.decisionTable.key.length == 0) {\n        \t\n            return;\n        }\n\n        $scope.model.loading = true;\n\n        $http({method: 'POST', url: FLOWABLE.APP_URL.getModelsUrl(), data: $scope.model.decisionTable}).\n            success(function(data, status, headers, config) {\n                $scope.$hide();\n                $scope.model.loading = false;\n\n                if ($scope.createDecisionTableCallback) {\n                \t$scope.createDecisionTableCallback(data);\n                \t$scope.createDecisionTableCallback = undefined;\n                }\n\n            }).\n            error(function(data, status, headers, config) {\n                $scope.model.loading = false;\n                $scope.model.errorMessage = data.message;\n            });\n    };\n\n    $scope.cancel = function () {\n        if(!$scope.model.loading) {\n            $scope.$hide();\n        }\n    };\n}]);\n\nangular.module('flowableModeler')\n\t.controller('DuplicateDecisionTableCtrl', ['$rootScope', '$scope', '$http',\n\t\tfunction ($rootScope, $scope, $http) {\n\n\t\t\t$scope.model = {\n\t\t\t\tloading: false,\n                decisionTable: {\n\t\t\t\t\tid: '',\n\t\t\t\t\tname: '',\n\t\t\t\t\tdescription: '',\n                    modelType: null\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tif ($scope.originalModel) {\n\t\t\t\t//clone the model\n\t\t\t\t$scope.model.decisionTable.name = $scope.originalModel.decisionTable.name;\n\t\t\t\t$scope.model.decisionTable.key = $scope.originalModel.decisionTable.key;\n\t\t\t\t$scope.model.decisionTable.description = $scope.originalModel.decisionTable.description;\n\t\t\t\t$scope.model.decisionTable.modelType = $scope.originalModel.decisionTable.modelType;\n\t\t\t\t$scope.model.decisionTable.id = $scope.originalModel.decisionTable.id;\n\t\t\t}\n\n\t\t\t$scope.ok = function () {\n\n\t\t\t\tif (!$scope.model.decisionTable.name || $scope.model.decisionTable.name.length == 0) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\t$scope.model.loading = true;\n\n\t\t\t\t$http({method: 'POST', url: FLOWABLE.APP_URL.getCloneModelsUrl($scope.model.decisionTable.id), data: $scope.model.decisionTable}).\n\t\t\t\t\tsuccess(function(data, status, headers, config) {\n\t\t\t\t\t\t$scope.$hide();\n\t\t\t\t\t\t$scope.model.loading = false;\n\n\t\t\t\t\t\tif ($scope.duplicateDecisionTableCallback) {\n\t\t\t\t\t\t\t$scope.duplicateDecisionTableCallback(data);\n\t\t\t\t\t\t\t$scope.duplicateDecisionTableCallback = undefined;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t}).\n\t\t\t\t\terror(function(data, status, headers, config) {\n\t\t\t\t\t\t$scope.model.loading = false;\n\t\t\t\t\t\t$scope.model.errorMessage = data.message;\n\t\t\t\t\t});\n\t\t\t};\n\n\t\t\t$scope.cancel = function () {\n\t\t\t\tif(!$scope.model.loading) {\n\t\t\t\t\t$scope.$hide();\n\t\t\t\t}\n\t\t\t};\n\t\t}]);\n\nangular.module('flowableModeler')\n.controller('ImportDecisionTableModelCtrl', ['$rootScope', '$scope', '$http', 'Upload', '$location', function ($rootScope, $scope, $http, Upload, $location) {\n\n  $scope.model = {\n       loading: false\n  };\n\n  $scope.onFileSelect = function($files, isIE) {\n\n      for (var i = 0; i < $files.length; i++) {\n          var file = $files[i];\n\n          var url;\n          if (isIE) {\n              url = FLOWABLE.APP_URL.getDecisionTableTextImportUrl();\n          } else {\n              url = FLOWABLE.APP_URL.getDecisionTableImportUrl();\n          }\n\n          Upload.upload({\n              url: url,\n              method: 'POST',\n              file: file\n          }).progress(function(evt) {\n              $scope.model.loading = true;\n              $scope.model.uploadProgress = parseInt(100.0 * evt.loaded / evt.total);\n\n          }).success(function(data, status, headers, config) {\n              $scope.model.loading = false;\n\n              $location.path(\"/decision-table-editor/\" + data.id);\n              $scope.$hide();\n\n          }).error(function(data, status, headers, config) {\n\n              if (data && data.message) {\n                  $scope.model.errorMessage = data.message;\n              }\n\n              $scope.model.error = true;\n              $scope.model.loading = false;\n          });\n      }\n  };\n\n  $scope.cancel = function () {\n      if(!$scope.model.loading) {\n          $scope.$hide();\n      }\n  };\n}]);\n"
  },
  {
    "path": "flowable-ui-web/modeler/scripts/controllers/form-builder.js",
    "content": "/* 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'use strict';\n\nangular.module('flowableModeler')\n    .controller('FormBuilderController', ['$rootScope', '$scope', '$translate', '$http', '$timeout', '$location', '$modal', '$routeParams', '$popover', 'FormBuilderService',\n        function ($rootScope, $scope, $translate, $http, $timeout, $location, $modal, $routeParams, $popover, FormBuilderService) {\n\n            // Main page (needed for visual indicator of current page)\n            $rootScope.setMainPageById('forms');\n\n            // Needs to be on root scope to be available in the toolbar controller\n            $rootScope.formBuilder = {activeTab: 'design'};\n\n            $scope.model = {\n                useOutcomes: false\n            };\n\n            $rootScope.currentReadonlyFields = {fields: {}};\n\n            $scope.$watch('model.useOutcomes', function (value) {\n                if (value) {\n                    if (!$rootScope.currentOutcomes || $rootScope.currentOutcomes.length === 0) {\n                        $rootScope.currentOutcomes = [{name: ''}];\n                    }\n                } else {\n                    $rootScope.currentOutcomes = [];\n                }\n            });\n\n            // tabs for tab-control. NOT using templates for the tabs, we control the view\n            // ourselves, based on the active tab binding\n            $scope.tabs = [\n                {\n                    id: 'design',\n                    title: 'FORM-BUILDER.TITLE.DESIGN'\n                },\n                {\n                    id: 'outcome',\n                    title: 'FORM-BUILDER.TITLE.OUTCOME'\n                }\n            ];\n\n            $scope.form = {\n            \tname: '', \n            \tkey: '',\n            \tdescription: '', \n            \tversion: 1\n           \t};\n\n            $scope.formElements = [];\n            $rootScope.currentOutcomes = [];\n\n            $rootScope.formChanges = false;\n\n            var guidSequence = 0;\n\n            function setFieldDragDropAttributes (field, prefix) {\n                if (!field._guid) {\n                    field._guid = prefix + guidSequence++;\n                }\n\n                if (!field._width) {\n                    field._width = 1;\n                }\n            }\n\n            var lastDropArrayTarget = null;\n\n            $scope.onFieldMoved = function (field, fieldArraySource) {\n            \t\n            };\n\n\n            $scope.onFieldDrop = function (paletteElementOrField, dropArrayTarget, event, index) {\n\n\t\t\t\t// Is it an existing object?\n                if (paletteElementOrField.hasOwnProperty('_guid')) {\n\n                    lastDropArrayTarget = dropArrayTarget;\n\n                    if (dropArrayTarget) {\n                        var i = -1;\n                        dropArrayTarget.forEach(function (f, index) {\n                            if (paletteElementOrField._guid == f._guid) {\n                                i = index;\n                            }\n                        });\n                        if (i != -1) {\n                            dropArrayTarget.splice(i, 1);\n                        }\n                    }\n\n                    if (navigator.appVersion.indexOf(\"MSIE 9\") != -1) {\n                        // update _guid which is what ngRepeat is tracking by to force dom updates\n                        paletteElementOrField._guid += '_';\n                    }\n                    return paletteElementOrField;\n                }\n\n                lastDropArrayTarget = null;\n\n                var fieldId = paletteElementOrField.type;\n                var fieldType;\n                \n                if (fieldId === 'radio-buttons' || fieldId === 'dropdown') {\n                    fieldType = 'OptionFormField';\n                    \n                } else if (fieldId === 'expression') {\n                    fieldType = 'ExpressionFormField';\n                }\n\n                var field = {\n                    type: fieldId,\n                    fieldType: fieldType,\n                    name: 'Label',\n                    required: false,\n                    readOnly: false\n                };\n                setFieldDragDropAttributes(field, 'newField');\n\n                if (fieldId === 'radio-buttons') {\n                    field.options = [{ \n                    \tname: $translate.instant('FORM-BUILDER.COMPONENT.RADIO-BUTTON-DEFAULT')\n                    }];\n                }\n\n                if (fieldId === 'dropdown') {\n                    field.options = [\n                        {name: $translate.instant('FORM-BUILDER.COMPONENT.DROPDOWN-DEFAULT-EMPTY-SELECTION')}\n                    ];\n                    field.value = field.options[0];\n                    field.hasEmptyValue = true;\n                }\n                \n                return field;\n            };\n\n\n            if ($routeParams.modelId) {\n\n                var url;\n                if ($routeParams.modelHistoryId) {\n                    url = FLOWABLE.APP_URL.getFormModelHistoryUrl($routeParams.modelId, $routeParams.modelHistoryId);\n                } else {\n                    url = FLOWABLE.APP_URL.getFormModelUrl($routeParams.modelId);\n                }\n\n                $http({method: 'GET', url: url}).\n                    success(function (response, status, headers, config) {\n                        if (response.formDefinition.fields) {\n\n                            for (var i = 0; i < response.formDefinition.fields.length; i++) {\n                                var field = response.formDefinition.fields[i];\n                                if (!field.params) {\n                                    field.params = {};\n                                }\n                                setFieldDragDropAttributes(field, 'savedField');\n                            }\n\n                            $scope.formElements = response.formDefinition.fields;\n                        } else {\n                            $scope.formElements = [];\n                        }\n                        if (response.formDefinition.outcomes) {\n                            $rootScope.currentOutcomes = response.formDefinition.outcomes;\n                            if ($rootScope.currentOutcomes.length > 0) {\n                                $scope.model.useOutcomes = true;\n                            }\n                        } else {\n                            $rootScope.currentOutcomes = [];\n                        }\n                        $rootScope.currentForm = response;\n                        delete $rootScope.currentForm.formDefinition;\n\n                        $rootScope.formItems = $scope.formElements;\n\n                        $rootScope.formChanges = false;\n                        $timeout(function () {\n                            // Flip switch in timeout to start watching all form-related models\n                            // after next digest cycle, to prevent first false-positive\n                            $scope.formLoaded = true;\n                        }, 200);\n                        \n                    }).\n                    error(function (response, status, headers, config) {\n                        $scope.model.loading = false;\n                    });\n            } else {\n                $scope.formLoaded = true;\n            }\n\n            $scope.palletteElements = [\n                {'type': 'text', 'title': $translate.instant('FORM-BUILDER.PALLETTE.TEXT'), 'icon': 'images/form-builder/textfield-icon.png', 'width': 1},\n                {'type': 'password', 'title': $translate.instant('FORM-BUILDER.PALLETTE.PASSWORD'), 'icon': 'images/form-builder/password-icon.png', 'width': 1},\n                {'type': 'multi-line-text', 'title': $translate.instant('FORM-BUILDER.PALLETTE.MULTILINE-TEXT'), 'icon': 'images/form-builder/multi-line-textfield-icon.png', 'width': 1},\n                {'type': 'integer', 'title': $translate.instant('FORM-BUILDER.PALLETTE.NUMBER'), 'icon': 'images/form-builder/numberfield-icon.png', 'width': 1},\n                {'type': 'decimal', 'title': $translate.instant('FORM-BUILDER.PALLETTE.DECIMAL'), 'icon': 'images/form-builder/decimalfield-icon.png', 'width': 1},\n                {'type': 'boolean', 'title': $translate.instant('FORM-BUILDER.PALLETTE.CHECKBOX'), 'icon': 'images/form-builder/booleanfield-icon.png', 'width': 1},\n                {'type': 'date', 'title': $translate.instant('FORM-BUILDER.PALLETTE.DATE'), 'icon': 'images/form-builder/datefield-icon.png', 'width': 1},\n                {'type': 'dropdown', 'title': $translate.instant('FORM-BUILDER.PALLETTE.DROPDOWN'), 'icon': 'images/form-builder/dropdownfield-icon.png', 'width': 1},\n                {'type': 'radio-buttons', 'title': $translate.instant('FORM-BUILDER.PALLETTE.RADIO'), 'icon': 'images/form-builder/choicefield-icon.png', 'width': 1},\n                {'type': 'people', 'title': $translate.instant('FORM-BUILDER.PALLETTE.PEOPLE'), 'icon': 'images/form-builder/peoplefield-icon.png', 'width': 1},\n                {'type': 'functional-group', 'title': $translate.instant('FORM-BUILDER.PALLETTE.GROUP-OF-PEOPLE'), 'icon': 'images/form-builder/peoplefield-icon.png', 'width': 1},\n                {'type': 'upload', 'title': $translate.instant('FORM-BUILDER.PALLETTE.UPLOAD'), 'icon': 'images/form-builder/uploadfield-icon.png', 'width': 1},\n                {'type': 'expression', 'title': $translate.instant('FORM-BUILDER.PALLETTE.EXPRESSION'), 'icon': 'images/form-builder/readonly-icon.png', 'width': 1},\n                {'type': 'hyperlink', 'title': $translate.instant('FORM-BUILDER.PALLETTE.HYPERLINK'), 'icon': 'images/form-builder/hyperlink-icon.png', 'width':1},\n\t\t\t\t{'type': 'spacer', 'title': $translate.instant('FORM-BUILDER.PALLETTE.SPACER'), 'icon': 'images/form-builder/spacer-icon.png', 'width':1},\n\t\t\t\t{'type': 'horizontal-line', 'title': $translate.instant('FORM-BUILDER.PALLETTE.HORIZONTAL-LINE'), 'icon': 'images/form-builder/horizontal-line-icon.png', 'width':1},\n\t\t\t\t{'type': 'headline', 'title': $translate.instant('FORM-BUILDER.PALLETTE.HEADLINE'), 'icon': 'images/form-builder/headline-icon.png', 'width':1},\n\t\t\t\t{'type': 'headline-with-line', 'title': $translate.instant('FORM-BUILDER.PALLETTE.HEADLINE-WITH-LINE'), 'icon': 'images/form-builder/headline-with-line-icon.png', 'width':1}\n            ];\n\n            $scope.$watch('formItems', function () {\n                if ($scope.formLoaded) {\n                    $rootScope.formChanges = true;\n                }\n            }, true);\n\n            $scope.$watch('currentOutcomes', function () {\n                if ($scope.formLoaded) {\n                    $rootScope.formChanges = true;\n                }\n            }, true);\n\n            $scope.addOutcome = function () {\n                $rootScope.currentOutcomes[$rootScope.currentOutcomes.length] = {name: ''};\n            };\n\n            $scope.removeOutcome = function (index) {\n                $rootScope.currentOutcomes.splice(index, 1);\n            };\n\n            $scope.$on('$locationChangeStart', function (event, next, current) {\n                if (!$rootScope.ignoreChanges && $rootScope.formChanges) {\n                    // Always prevent location from changing. We'll use a popup to determine the action we want to take\n                    event.preventDefault();\n\n                    var discardCallback = function () {\n                        $rootScope.ignoreChanges = true;\n                        $location.url(next.substring(next.indexOf('/#') + 2));\n                    };\n\n                    var continueEditingCallback = function () {\n                        // Don't change the location and make sure \"main navigation\" is still correct\n                        $rootScope.ignoreChanges = false;\n                        $rootScope.setMainPageById('forms');\n                    };\n\n                    $scope.yesNoCancel = false;\n                    showDiscardPopup($scope, null, discardCallback, continueEditingCallback);\n\n                } else {\n                    // Clear marker\n                    $rootScope.ignoreChanges = false;\n                }\n\n            });\n\n            $scope.$on(\"formChangesEvent\", function () {\n                var discardCallback = function () {\n                    $scope.$broadcast(\"discardDataEvent\");\n                };\n\n                var saveDataCallback = function () {\n                    $scope.$broadcast(\"mustSaveEvent\");\n                };\n\n                var continueEditingCallback = function () {\n                    $scope.$broadcast(\"continueEditingEvent\");\n                };\n\n                $scope.yesNoCancel = true;\n                showDiscardPopup($scope, saveDataCallback, discardCallback, continueEditingCallback);\n            });\n\n            function showDiscardPopup($scope, saveCallback, discardCallback, cancelCallback) {\n                if (!$scope.unsavedChangesModalInstance) {\n\n                    $scope.handleResponseFunction = function (discard) {\n                        $scope.unsavedChangesModalInstance = undefined;\n                        if (discard == true) {\n                            if (discardCallback) {\n                                discardCallback();\n                            }\n\n                        } else if (discard == false) {\n                            if (saveCallback) {\n                                saveCallback();\n                            }\n                        } else {\n                            if (cancelCallback) {\n                                cancelCallback();\n                            }\n                        }\n                    };\n\n                    _internalCreateModal({\n                        template: 'editor-app/popups/unsaved-changes.html',\n                        scope: $scope\n                    }, $modal, $scope);\n                }\n            };\n\n            // get current step and sequential steps for form field resolving\n            if ($rootScope.editorHistory && $rootScope.editorHistory.length > 0) {\n                $scope.stepId = $rootScope.editorHistory[0].stepId;\n                $scope.allSteps = $rootScope.editorHistory[0].allSteps;\n            }\n\n        }]);\n"
  },
  {
    "path": "flowable-ui-web/modeler/scripts/controllers/form-readonly-view.js",
    "content": "/* 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'use strict';\n\nangular.module('flowableModeler')\n  .controller('FormReadonlyViewController', ['$rootScope', '$scope', '$translate', '$http', '$timeout', '$location', '$modal', '$routeParams', '$popover',\n    function ($rootScope, $scope, $translate, $http, $timeout, $location, $modal, $routeParams, $popover) {\n\n      // Main page (needed for visual indicator of current page)\n      $rootScope.setMainPageById('forms');\n      \n      var guidSequence = 0;\n      \n      function setFieldDragDropAttributes (field, prefix) {\n          if (!field._guid) {\n              field._guid = prefix + guidSequence++;\n          }\n          \n          if (!field._width) {\n              field._width = 1;\n          }\n      }\n\n      if ($routeParams.modelId) {\n\n          var url;\n          if ($routeParams.modelHistoryId) {\n              url = FLOWABLE.APP_URL.getFormModelHistoryUrl($routeParams.modelId,$routeParams.modelHistoryId);\n          } else {\n              url = FLOWABLE.APP_URL.getFormModelUrl($routeParams.modelId);\n          }\n\n          $http({method: 'GET', url: url}).\n              success(function (response, status, headers, config) {\n                  if (response.formDefinition.fields) {\n                      for (var i = 0; i < response.formDefinition.fields.length; i++) {\n                          var field = response.formDefinition.fields[i];\n                          if (!field.params) {\n                              field.params = {};\n                          }\n                          setFieldDragDropAttributes(field, 'savedField');\n                      }\n\n                      $scope.formElements = response.formDefinition.fields;\n                  } else {\n                      $scope.formElements = [];\n                  }\n            \n                  $scope.formItems = $scope.formElements;\n                  \n                  $timeout(function () {\n                      // Flip switch in timeout to start watching all form-related models\n                      // after next digest cycle, to prevent first false-positive\n                      $scope.formLoaded = true;\n                  }, 200);\n              }).\n              error(function (response, status, headers, config) {\n                  $scope.model.loading = false;\n              });\n          \n      } else {\n          $scope.formLoaded = true;\n      }\n\n}]);\n"
  },
  {
    "path": "flowable-ui-web/modeler/scripts/controllers/form-toolbar-controller.js",
    "content": "/* 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 */\nangular.module('flowableModeler')\n    .controller('FormToolbarController', ['$scope', '$http', '$modal', '$q', '$rootScope', '$translate', '$location', 'FormBuilderService', function ($scope, $http, $modal, $q, $rootScope, $translate, $location, FormBuilderService) {\n\n    \tvar toolbarItems = FORM_TOOLBAR_CONFIG.items;\n        $scope.items = [];\n        \n        for (var i = 0; i < toolbarItems.length; i++)\n        {\n        \t$scope.items.push(toolbarItems[i]);\n        }\n        \n        $scope.secondaryItems = FORM_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, 'FormBuilderService': FormBuilderService};\n            executeFunctionByName(buttonClicked.action, window, services);\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, '$rootScope' : $rootScope, '$http' : $http, '$modal' : $modal, '$q' : $q, '$translate' : $translate, '$location': $location, 'FormBuilderService': FormBuilderService};\n            executeFunctionByName(buttonClicked.action, window, services);\n        };\n}]);"
  },
  {
    "path": "flowable-ui-web/modeler/scripts/controllers/form.js",
    "content": "/* 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 */\nangular.module('flowableModeler')\n  .controller('FormCtrl', ['$rootScope', '$scope', '$translate', '$http', '$location', '$routeParams','$modal', '$timeout', '$popover',\n                              function ($rootScope, $scope, $translate, $http, $location, $routeParams, $modal, $timeout, $popover) {\n\n    // Main page (needed for visual indicator of current page)\n    $rootScope.setMainPageById('forms');\n\n    $scope.formMode = 'read';\n\n    // Initialize model\n    $scope.model = {\n        // Store the main model id, this points to the current version of a model,\n        // even when we're showing history\n        latestModelId: $routeParams.modelId\n    };\n\n    $scope.loadForm = function() {\n      var url;\n      if ($routeParams.modelHistoryId) {\n        url = FLOWABLE.APP_URL.getModelHistoryUrl($routeParams.modelId, $routeParams.modelHistoryId);\n      } else {\n        url = FLOWABLE.APP_URL.getModelUrl($routeParams.modelId);\n      }\n\n      $http({method: 'GET', url: url}).\n        success(function(data, status, headers, config) {\n          $scope.model.form = data;\n          $scope.loadVersions();\n\n        }).error(function(data, status, headers, config) {\n          $scope.returnToList();\n        });\n    };\n\n    $scope.useAsNewVersion = function() {\n        _internalCreateModal({\n    \t\ttemplate: 'views/popup/model-use-as-new-version.html',\n    \t\tscope: $scope\n    \t}, $modal, $scope);\n    };\n\n    $scope.loadVersions = function() {\n\n      var params = {\n        includeLatestVersion: !$scope.model.form.latestVersion\n      };\n\n      $http({method: 'GET', url: FLOWABLE.APP_URL.getModelHistoriesUrl($scope.model.latestModelId), params: params}).\n\t      success(function(data, status, headers, config) {\n\t        if ($scope.model.form.latestVersion) {\n\t          if (!data.data) {\n\t            data.data = [];\n\t          }\n\t          data.data.unshift($scope.model.form);\n\t        }\n\n\t        $scope.model.versions = data;\n\t      });\n    };\n\n    $scope.showVersion = function(version) {\n      if (version) {\n        if (version.latestVersion) {\n            $location.path(\"/forms/\" +  $scope.model.latestModelId);\n        } else {\n          // Show latest version, no history-suffix needed in URL\n          $location.path(\"/forms/\" +  $scope.model.latestModelId + \"/history/\" + version.id);\n        }\n      }\n    };\n\n    $scope.returnToList = function() {\n        $location.path(\"/forms/\");\n    };\n\n    $scope.editForm = function() {\n        _internalCreateModal({\n    \t\ttemplate: 'views/popup/model-edit.html',\n\t        scope: $scope\n    \t}, $modal, $scope);\n    };\n\n    $scope.duplicateForm = function() {\n\n      var modalInstance = _internalCreateModal({\n        template: 'views/popup/form-duplicate.html?version=' + Date.now()\n      }, $modal, $scope);\n\n      modalInstance.$scope.originalModel = $scope.model;\n\n      modalInstance.$scope.duplicateFormCallback = function(result) {\n        $rootScope.editorHistory = [];\n        $location.path(\"/form-editor/\" + result.id);\n      };\n    };\n\n    $scope.deleteForm = function() {\n        _internalCreateModal({\n    \t\ttemplate: 'views/popup/model-delete.html',\n    \t\tscope: $scope\n    \t}, $modal, $scope);\n    };\n\n    $scope.openEditor = function() {\n      if ($scope.model.form) {\n    \t  $location.path(\"/form-editor/\" + $scope.model.form.id);\n      }\n    };\n\n    $scope.toggleHistory = function($event) {\n      if (!$scope.historyState) {\n        var state = {};\n        $scope.historyState = state;\n\n        // Create popover\n        state.popover = $popover(angular.element($event.target), {\n          template: 'views/popover/history.html',\n          placement: 'bottom-right',\n          show: true,\n          scope: $scope,\n          container: 'body'\n        });\n\n        var destroy = function() {\n          state.popover.destroy();\n          delete $scope.historyState;\n        };\n\n        // When popup is hidden or scope is destroyed, hide popup\n        state.popover.$scope.$on('tooltip.hide', destroy);\n        $scope.$on('$destroy', destroy);\n      }\n    };\n\n    $scope.loadForm();\n\n}]);\n"
  },
  {
    "path": "flowable-ui-web/modeler/scripts/controllers/forms.js",
    "content": "/* 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'use strict';\n\nangular.module('flowableModeler')\n  .controller('FormsCtrl', ['$rootScope', '$scope', '$translate', '$http', '$timeout','$location', '$modal', function ($rootScope, $scope, $translate, $http, $timeout, $location, $modal) {\n\n      // Main page (needed for visual indicator of current page)\n      $rootScope.setMainPageById('forms');\n      $rootScope.formItems = undefined;\n\n      // get latest thumbnails\n      $scope.imageVersion = Date.now();\n\n\t  $scope.model = {\n        filters: [\n            {id: 'forms', labelKey: 'FORMS'}\n\t\t],\n\n\t\tsorts: [\n\t\t        {id: 'modifiedDesc', labelKey: 'MODIFIED-DESC'},\n\t\t        {id: 'modifiedAsc', labelKey: 'MODIFIED-ASC'},\n\t\t        {id: 'nameAsc', labelKey: 'NAME-ASC'},\n\t\t        {id: 'nameDesc', labelKey: 'NAME-DESC'}\n\t\t]\n\t  };\n\n\t  if ($rootScope.formFilter) {\n\t\t  $scope.model.activeFilter = $rootScope.formFilter.filter;\n\t\t  $scope.model.activeSort = $rootScope.formFilter.sort;\n\t\t  $scope.model.filterText = $rootScope.formFilter.filterText;\n\n\t  } else {\n\t\t  // By default, show first filter and use first sort\n\t      $scope.model.activeFilter = $scope.model.filters[0];\n\t      $scope.model.activeSort = $scope.model.sorts[0];\n\t      $rootScope.formFilter = {\n\t        filter: $scope.model.activeFilter,\n\t        sort: $scope.model.activeSort,\n\t        filterText: ''\n\t      };\n\t  }\n\n\t  $scope.activateFilter = function(filter) {\n\t\t  $scope.model.activeFilter = filter;\n\t\t  $rootScope.formFilter.filter = filter;\n\t\t  $scope.loadForms();\n\t  };\n\n\t  $scope.activateSort = function(sort) {\n\t\t  $scope.model.activeSort = sort;\n\t\t  $rootScope.formFilter.sort = sort;\n\t\t  $scope.loadForms();\n\t  };\n\n\t  $scope.loadForms = function() {\n\t\t  $scope.model.loading = true;\n\n\t\t  var params = {\n\t\t      filter: $scope.model.activeFilter.id,\n\t\t      sort: $scope.model.activeSort.id,\n\t\t      modelType: 2\n\t\t  };\n\n\t\t  if ($scope.model.filterText && $scope.model.filterText != '') {\n\t\t    params.filterText = $scope.model.filterText;\n\t\t  }\n\n\t\t  $http({method: 'GET', url: FLOWABLE.APP_URL.getModelsUrl(), params: params}).\n\t\t  \tsuccess(function(data, status, headers, config) {\n\t    \t\t$scope.model.forms = data;\n\t    \t\t$scope.model.loading = false;\n\t        }).\n\t        error(function(data, status, headers, config) {\n\t           $scope.model.loading = false;\n\t        });\n\t  };\n\n\t  var timeoutFilter = function() {\n\t    $scope.model.isFilterDelayed = true;\n\t    $timeout(function() {\n\t        $scope.model.isFilterDelayed = false;\n\t        if($scope.model.isFilterUpdated) {\n\t          $scope.model.isFilterUpdated = false;\n\t          timeoutFilter();\n\t        } else {\n\t          $scope.model.filterText = $scope.model.pendingFilterText;\n\t          $rootScope.formFilter.filterText = $scope.model.filterText;\n\t          $scope.loadForms();\n\t        }\n\t    }, 500);\n\t  };\n\n\t  $scope.filterDelayed = function() {\n\t    if($scope.model.isFilterDelayed) {\n\t      $scope.model.isFilterUpdated = true;\n\t    } else {\n\t      timeoutFilter();\n\t    }\n\t  };\n\n\t  $scope.createForm = function() {\n\t      $rootScope.currentKickstartModel = undefined;\n\t\t  $scope.createFormCallback = function(result) {\n\t\t      $rootScope.editorHistory = [];\n\t\t\t  $location.path(\"/form-editor/\" + result.id);\n\t\t  };\n          _internalCreateModal({\n\t\t\t  template: 'views/popup/form-create.html?version=' + Date.now(),\n\t\t\t  scope: $scope\n\t\t  }, $modal, $scope);\n\t  };\n\n\t  $scope.showFormDetails = function(form) {\n\t      if (form) {\n\t          $rootScope.editorHistory = [];\n\t          $location.path(\"/forms/\" + form.id);\n\t      }\n\t  };\n\n\t  $scope.editFormDetails = function(form) {\n\t\t  if (form) {\n\t\t      $rootScope.editorHistory = [];\n\t\t\t  $location.path(\"/form-editor/\" + form.id);\n\t\t  }\n\t  };\n\n\t  // Finally, load initial forms\n\t  $scope.loadForms();\n  }]);\n\n\nangular.module('flowableModeler')\n.controller('CreateNewFormCtrl', ['$rootScope', '$scope', '$http',\n    function ($rootScope, $scope, $http) {\n\n    $scope.model = {\n       loading: false,\n       form: {\n            name: '',\n            key: '',\n            description: '',\n            modelType: 2\n       }\n    };\n\n    $scope.ok = function () {\n\n        if (!$scope.model.form.name || $scope.model.form.name.length == 0 ||\n        \t!$scope.model.form.key || $scope.model.form.key.length == 0) {\n        \t\n            return;\n        }\n\n        $scope.model.loading = true;\n\n        $http({method: 'POST', url: FLOWABLE.APP_URL.getModelsUrl(), data: $scope.model.form}).\n            success(function(data, status, headers, config) {\n                $scope.$hide();\n                $scope.model.loading = false;\n\n                if ($scope.createFormCallback) {\n                \t$scope.createFormCallback(data);\n                \t$scope.createFormCallback = undefined;\n                }\n\n            }).\n            error(function(data, status, headers, config) {\n                $scope.model.loading = false;\n                $scope.model.errorMessage = data.message;\n            });\n    };\n\n    $scope.cancel = function () {\n        if(!$scope.model.loading) {\n            $scope.$hide();\n        }\n    };\n}]);\n\nangular.module('flowableModeler')\n\t.controller('DuplicateFormCtrl', ['$rootScope', '$scope', '$http',\n\t\tfunction ($rootScope, $scope, $http) {\n\n\t\t\t$scope.model = {\n\t\t\t\tloading: false,\n\t\t\t\tform: {\n\t\t\t\t\tid: '',\n\t\t\t\t\tname: '',\n\t\t\t\t\tkey: '',\n\t\t\t\t\tdescription: '',\n\t\t\t\t\tmodelType: 2\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tif ($scope.originalModel) {\n\t\t\t\t//clone the model\n\t\t\t\t$scope.model.form.name = $scope.originalModel.form.name;\n\t\t\t\t$scope.model.form.key = $scope.originalModel.form.key;\n\t\t\t\t$scope.model.form.description = $scope.originalModel.form.description;\n\t\t\t\t$scope.model.form.modelType = $scope.originalModel.form.modelType;\n\t\t\t\t$scope.model.form.id = $scope.originalModel.form.id;\n\t\t\t}\n\n\t\t\t$scope.ok = function () {\n\n\t\t\t\tif (!$scope.model.form.name || $scope.model.form.name.length == 0 ||\n\t\t\t\t\t!$scope.model.form.key || $scope.model.form.key.length == 0) {\n\t\t\t\t\t\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\t$scope.model.loading = true;\n\n\t\t\t\t$http({method: 'POST', url: FLOWABLE.APP_URL.getCloneModelsUrl($scope.model.form.id), data: $scope.model.form}).\n\t\t\t\t\tsuccess(function(data, status, headers, config) {\n\t\t\t\t\t\t$scope.$hide();\n\t\t\t\t\t\t$scope.model.loading = false;\n\n\t\t\t\t\t\tif ($scope.duplicateFormCallback) {\n\t\t\t\t\t\t\t$scope.duplicateFormCallback(data);\n\t\t\t\t\t\t\t$scope.duplicateFormCallback = undefined;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t}).\n\t\t\t\t\terror(function(data, status, headers, config) {\n\t\t\t\t\t\t$scope.model.loading = false;\n\t\t\t\t\t\t $scope.model.errorMessage = data.message;\n\t\t\t\t\t});\n\t\t\t};\n\n\t\t\t$scope.cancel = function () {\n\t\t\t\tif(!$scope.model.loading) {\n\t\t\t\t\t$scope.$hide();\n\t\t\t\t}\n\t\t\t};\n\t\t}]);\n"
  },
  {
    "path": "flowable-ui-web/modeler/scripts/controllers/model-common-actions.js",
    "content": "/* 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'use strict';\n\nangular.module('flowableModeler')\n.controller('EditModelPopupCtrl', ['$rootScope', '$scope', '$http', '$translate', '$location',\n    function ($rootScope, $scope, $http, $translate, $location) {\n\n        var model;\n        var popupType;\n        if ($scope.model.process) {\n            model = $scope.model.process;\n            popupType = 'PROCESS';\n        } else if ($scope.model.caseModel) {\n            model = $scope.model.caseModel;\n            popupType = 'CASE';\n        } else if ($scope.model.form) {\n            model = $scope.model.form;\n            popupType = 'FORM';\n        } else if ($scope.model.decisionTable) {\n            model = $scope.model.decisionTable;\n            popupType = 'DECISION-TABLE';\n        } else {\n            model = $scope.model.app;\n            popupType = 'APP';\n        }\n\n    \t$scope.popup = {\n    \t\tloading: false,\n    \t\tpopupType: popupType,\n        \tmodelName: model.name,\n        \tmodelKey: model.key,\n        \tmodelDescription: model.description,\n    \t\tid: model.id\n    \t};\n\n    \t$scope.ok = function () {\n\n    \t\tif (!$scope.popup.modelName || $scope.popup.modelName.length == 0 ||\n    \t\t\t!$scope.popup.modelKey || $scope.popup.modelKey.length == 0) {\n    \t\t\t\n    \t\t\treturn;\n    \t\t}\n\n        \t$scope.model.name = $scope.popup.modelName;\n        \t$scope.model.key = $scope.popup.modelKey;\n        \t$scope.model.description = $scope.popup.modelDescription;\n\n    \t\t$scope.popup.loading = true;\n    \t\tvar updateData = {\n    \t\t\tname: $scope.model.name, \n    \t\t\tkey: $scope.model.key, description: \n    \t\t\t$scope.model.description\n    \t\t};\n\n    \t\t$http({method: 'PUT', url: FLOWABLE.APP_URL.getModelUrl($scope.popup.id), data: updateData}).\n    \t\t\tsuccess(function(data, status, headers, config) {\n    \t\t\t\tif ($scope.model.process) {\n    \t\t\t\t\t$scope.model.process = data;\n    \t\t\t\t} else if ($scope.model.caseModel) {\n                        $scope.model.caseModel = data;\n    \t\t\t\t} else if ($scope.model.form) {\n    \t\t\t\t\t$scope.model.form = data;\n    \t\t\t\t} else if ($scope.model.decisionTable) {\n    \t\t\t\t\t$scope.model.decisionTable = data;\n    \t\t\t\t} else {\n    \t\t\t\t\t$scope.model.app = data;\n    \t\t\t\t}\n\n    \t\t\t\t$scope.addAlertPromise($translate('PROCESS.ALERT.EDIT-CONFIRM'), 'info');\n    \t\t\t\t$scope.$hide();\n    \t\t\t\t$scope.popup.loading = false;\n\n    \t\t\t\tif (popupType === 'FORM') {\n                        $location.path(\"/forms/\" +  $scope.popup.id);\n                    } else if (popupType === 'APP') {\n                        $location.path(\"/apps/\" +  $scope.popup.id);\n                    } else if (popupType === 'DECISION-TABLE') {\n                        $location.path(\"/decision-tables/\" +  $scope.popup.id);\n                    } else if (popupType === 'CASE') {\n                        $location.path(\"/casemodels/\" +  $scope.popup.id);\n                    } else {\n                        $location.path(\"/processes/\" +  $scope.popup.id);\n                    }\n\n    \t\t\t}).\n    \t\t\terror(function(data, status, headers, config) {\n    \t\t\t\t$scope.popup.loading = false;\n    \t\t\t\t$scope.popup.errorMessage = data.message;\n    \t\t\t});\n    \t};\n\n    \t$scope.cancel = function () {\n    \t\tif (!$scope.popup.loading) {\n    \t\t\t$scope.$hide();\n    \t\t}\n    \t};\n}]);\n\nangular.module('flowableModeler')\n    .controller('DeleteModelPopupCtrl', ['$rootScope', '$scope', '$http', '$translate', function ($rootScope, $scope, $http, $translate) {\n\n        var model;\n        var popupType;\n        if ($scope.model.process) {\n            model = $scope.model.process;\n            popupType = 'PROCESS';\n        } else if ($scope.model.caseModel) {\n            model = $scope.model.caseModel;\n            popupType = 'CASE';\n        } else if ($scope.model.form) {\n            model = $scope.model.form;\n            popupType = 'FORM';\n        } else if ($scope.model.decisionTable) {\n            model = $scope.model.decisionTable;\n            popupType = 'DECISION-TABLE';\n        } else {\n            model = $scope.model.app;\n            popupType = 'APP';\n        }\n\n        $scope.popup = {\n            loading: true,\n            loadingRelations: true,\n            cascade: 'false',\n            popupType: popupType,\n            model: model\n        };\n\n        // Loading relations when opening\n        $http({method: 'GET', url: FLOWABLE.APP_URL.getModelParentRelationsUrl($scope.popup.model.id)}).\n            success(function (data, status, headers, config) {\n                $scope.popup.loading = false;\n                $scope.popup.loadingRelations = false;\n                $scope.popup.relations = data;\n            }).\n            error(function (data, status, headers, config) {\n                $scope.$hide();\n                $scope.popup.loading = false;\n            });\n\n        $scope.ok = function () {\n            $scope.popup.loading = true;\n            var params = {\n                // Explicit string-check because radio-values cannot be js-booleans\n                cascade: $scope.popup.cascade === 'true'\n            };\n\n            $http({method: 'DELETE', url: FLOWABLE.APP_URL.getModelUrl($scope.popup.model.id), params: params}).\n                success(function (data, status, headers, config) {\n                    $scope.$hide();\n                    $scope.popup.loading = false;\n                    $scope.addAlertPromise($translate(popupType + '.ALERT.DELETE-CONFIRM'), 'info');\n                    $scope.returnToList();\n                }).\n                error(function (data, status, headers, config) {\n                    $scope.$hide();\n                    $scope.popup.loading = false;\n                });\n        };\n\n        $scope.cancel = function () {\n            if (!$scope.popup.loading) {\n                $scope.$hide();\n            }\n        };\n    }]);\n\nangular.module('flowableModeler')\n.controller('UseAsNewVersionPopupCtrl', ['$rootScope', '$scope', '$http', '$translate', '$location', function ($rootScope, $scope, $http, $translate, $location) {\n\n\tvar model;\n\tvar popupType;\n\tif ($scope.model.process) {\n\t\tmodel = $scope.model.process;\n\t\tpopupType = 'PROCESS';\n\t} else if ($scope.model.caseModel) {\n        model = $scope.model.caseModel;\n        popupType = 'CASE';\n\t} else if ($scope.model.form) {\n        model = $scope.model.form;\n        popupType = 'FORM';\n    } else if ($scope.model.decisionTable) {\n        model = $scope.model.decisionTable;\n        popupType = 'DECISION-TABLE';\n    } else {\n        model = $scope.model.app;\n        popupType = 'APP';\n    }\n\n\t$scope.popup = {\n\t\tloading: false,\n\t\tmodel: model,\n\t\tpopupType: popupType,\n\t\tlatestModelId: $scope.model.latestModelId,\n\t\tcomment: ''\n\t};\n\n\t$scope.ok = function () {\n\t\t$scope.popup.loading = true;\n\n\t\tvar actionData = {\n\t\t\taction: 'useAsNewVersion',\n\t\t\tcomment: $scope.popup.comment\n\t\t};\n\n\t\t$http({method: 'POST', url: FLOWABLE.APP_URL.getModelHistoryUrl($scope.popup.latestModelId, $scope.popup.model.id), data: actionData}).\n\t\t\tsuccess(function(data, status, headers, config) {\n\n                var backToOverview = function() {\n                    if (popupType === 'FORM') {\n                        $location.path(\"/forms/\" +  $scope.popup.latestModelId);\n                    } else if (popupType === 'APP') {\n                        $location.path(\"/apps/\" +  $scope.popup.latestModelId);\n                    } else if (popupType === 'DECISION-TABLE') {\n                        $location.path(\"/decision-tables/\" +  $scope.popup.latestModelId);\n                    } else if (popupType === 'CASE') {\n                        $location.path(\"/casemodels/\" +  $scope.popup.latestModelId);\n                    } else {\n                        $location.path(\"/processes/\" +  $scope.popup.latestModelId);\n                    }\n                };\n\n\n                if (data && data.unresolvedModels && data.unresolvedModels.length > 0) {\n\n                    // There were unresolved models\n\n                    $scope.popup.loading = false;\n                    $scope.popup.foundUnresolvedModels = true;\n                    $scope.popup.unresolvedModels = data.unresolvedModels;\n\n                    $scope.close = function() {\n                        $scope.$hide();\n                        backToOverview();\n                    };\n\n\n                } else {\n\n                    // All models working resolved perfectly\n\n                    $scope.popup.loading = false;\n                    $scope.$hide();\n\n                    $scope.addAlertPromise($translate(popupType + '.ALERT.NEW-VERSION-CONFIRM'), 'info');\n                    backToOverview();\n\n                }\n\n\t\t\t}).\n\t\t\terror(function(data, status, headers, config) {\n\t\t\t\t$scope.$hide();\n\t\t\t\t$scope.popup.loading = false;\n\t\t\t});\n\t};\n\n\t$scope.cancel = function () {\n\t\tif (!$scope.popup.loading) {\n\t\t\t$scope.$hide();\n\t\t}\n\t};\n}]);\n"
  },
  {
    "path": "flowable-ui-web/modeler/scripts/controllers/process.js",
    "content": "/* 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 */\nangular.module('flowableModeler')\n  .controller('ProcessCtrl', ['$rootScope', '$scope', '$translate', '$http', '$location', '$routeParams','$modal', '$popover', '$timeout', 'appResourceRoot', 'ResourceService',\n                              function ($rootScope, $scope, $translate, $http, $location, $routeParams, $modal, $popover, $timeout, appResourceRoot, ResourceService) {\n\n    // Main page (needed for visual indicator of current page)\n    $rootScope.setMainPageById('processes');\n\n    // Initialize model\n    $scope.model = {\n        // Store the main model id, this points to the current version of a model,\n        // even when we're showing history\n        latestModelId: $routeParams.modelId\n    };\n    \n    $scope.loadProcess = function() {\n      var url;\n      if ($routeParams.modelHistoryId) {\n        url = FLOWABLE.APP_URL.getModelUrl($routeParams.modelId) + '/history/' + $routeParams.modelHistoryId;\n      } else {\n        url = FLOWABLE.APP_URL.getModelUrl($routeParams.modelId);\n      }\n      \n      $http({method: 'GET', url: url}).\n        success(function(data, status, headers, config) {\n          $scope.model.process = data;\n          \n          $scope.loadVersions();\n\n          $scope.model.bpmn20DownloadUrl = $routeParams.modelHistoryId == undefined ?\n              FLOWABLE.APP_URL.getModelBpmn20ExportUrl($routeParams.modelId) :\n              FLOWABLE.APP_URL.getModelHistoryBpmn20ExportUrl($routeParams.modelId, $routeParams.modelHistoryId);\n\n\n        \t  $rootScope.$on('$routeChangeStart', function(event, next, current) {\n        \t\t  jQuery('.qtip').qtip('destroy', true);\n        \t  });\n        \t  \n\t          $timeout(function() {\n\t            jQuery(\"#bpmnModel\").attr('data-model-id', $routeParams.modelId);\n\t            jQuery(\"#bpmnModel\").attr('data-model-type', 'design');\n\t            \n\t            // in case we want to show a historic model, include additional attribute on the div\n\t            if(!$scope.model.process.latestVersion) {\n\t              jQuery(\"#bpmnModel\").attr('data-history-id', $routeParams.modelHistoryId);\n\t            }\n\n                var viewerUrl = appResourceRoot + \"display/displaymodel.html?version=\" + Date.now();\n\n                // If Flowable has been deployed inside an AMD environment Raphael will fail to register\n                // itself globally until displaymodel.js (which depends ona global Raphale variable) is running,\n                // therefore remove AMD's define method until we have loaded in Raphael and displaymodel.js\n                // and assume/hope its not used during.\n                var amdDefine = window.define;\n                window.define = undefined;\n                ResourceService.loadFromHtml(viewerUrl, function(){\n                    // Restore AMD's define method again\n                    window.define = amdDefine;\n                });\n              });\n\n        }).error(function(data, status, headers, config) {\n          $scope.returnToList();\n        });\n    };\n    \n    $scope.useAsNewVersion = function() {\n        _internalCreateModal({\n    \t\ttemplate: 'views/popup/model-use-as-new-version.html',\n    \t\tscope: $scope\n    \t}, $modal, $scope);\n    };\n    \n    $scope.loadVersions = function() {\n      \n      var params = {\n        includeLatestVersion: !$scope.model.process.latestVersion  \n      };\n      \n      $http({method: 'GET', url: FLOWABLE.APP_URL.getModelHistoriesUrl($scope.model.latestModelId), params: params}).\n      success(function(data, status, headers, config) {\n        if ($scope.model.process.latestVersion) {\n          if (!data.data) {\n            data.data = [];\n          }\n          data.data.unshift($scope.model.process);\n        }\n        \n        $scope.model.versions = data;\n      });\n    };\n    \n    $scope.showVersion = function(version) {\n      if(version) {\n        if(version.latestVersion) {\n            $location.path(\"/processes/\" +  $scope.model.latestModelId);\n        } else{\n          // Show latest version, no history-suffix needed in URL\n          $location.path(\"/processes/\" +  $scope.model.latestModelId + \"/history/\" + version.id);\n        }\n      }\n    };\n    \n    $scope.returnToList = function() {\n        $location.path(\"/processes/\");\n    };\n    \n    $scope.editProcess = function() {\n        _internalCreateModal({\n    \t\ttemplate: 'views/popup/model-edit.html',\n\t        scope: $scope\n    \t}, $modal, $scope);\n    };\n\n    $scope.duplicateProcess = function() {\n      var modalInstance = _internalCreateModal({\n        template: 'views/popup/process-duplicate.html?version=' + Date.now()\n      }, $modal, $scope);\n\n      modalInstance.$scope.originalModel = $scope.model;\n    };\n\n    $scope.deleteProcess = function() {\n        _internalCreateModal({\n    \t\ttemplate: 'views/popup/model-delete.html',\n    \t\tscope: $scope\n    \t}, $modal, $scope);\n    };\n    \n    $scope.openEditor = function() {\n      if ($scope.model.process) {\n        $location.path(\"/editor/\" + $scope.model.process.id);\n      }\n    };\n      \n    $scope.toggleHistory = function($event) {\n        if(!$scope.historyState) {\n          var state = {};\n          $scope.historyState = state;\n          \n          // Create popover\n          state.popover = $popover(angular.element($event.target), {\n            template: 'views/popover/history.html',\n            placement: 'bottom-right',\n            show: true,\n            scope: $scope,\n            container: 'body'\n          });\n          \n          var destroy = function() {\n            state.popover.destroy();\n            delete $scope.historyState;\n          }\n          \n          // When popup is hidden or scope is destroyed, hide popup\n          state.popover.$scope.$on('tooltip.hide', destroy);\n          $scope.$on('$destroy', destroy);\n        }\n    };\n    \n    $scope.loadProcess();\n}]);\n"
  },
  {
    "path": "flowable-ui-web/modeler/scripts/controllers/processes.js",
    "content": "/* 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'use strict';\n\nangular.module('flowableModeler')\n  .controller('ProcessesCtrl', ['$rootScope', '$scope', '$translate', '$http', '$timeout','$location', '$modal', function ($rootScope, $scope, $translate, $http, $timeout, $location, $modal) {\n\n      // Main page (needed for visual indicator of current page)\n      $rootScope.setMainPageById('processes');\n      $rootScope.formItems = undefined;\n\n      // get latest thumbnails\n      $scope.imageVersion = Date.now();\n\n\t  $scope.model = {\n        filters: [\n            {id: 'processes', labelKey: 'PROCESSES'}\n\t\t],\n\n\t\tsorts: [\n\t\t        {id: 'modifiedDesc', labelKey: 'MODIFIED-DESC'},\n\t\t        {id: 'modifiedAsc', labelKey: 'MODIFIED-ASC'},\n\t\t        {id: 'nameAsc', labelKey: 'NAME-ASC'},\n\t\t        {id: 'nameDesc', labelKey: 'NAME-DESC'}\n\t\t]\n\t  };\n\n\t  if ($rootScope.modelFilter) {\n\t\t  $scope.model.activeFilter = $rootScope.modelFilter.filter;\n\t\t  $scope.model.activeSort = $rootScope.modelFilter.sort;\n\t\t  $scope.model.filterText = $rootScope.modelFilter.filterText;\n\n\t  } else {\n\t\t  // By default, show first filter and use first sort\n\t      $scope.model.activeFilter = $scope.model.filters[0];\n\t      $scope.model.activeSort = $scope.model.sorts[0];\n\t      $rootScope.modelFilter = {\n\t        filter: $scope.model.activeFilter,\n\t        sort: $scope.model.activeSort,\n\t        filterText: ''\n\t      };\n\t  }\n\n\t  $scope.activateFilter = function(filter) {\n\t\t  $scope.model.activeFilter = filter;\n\t\t  $rootScope.modelFilter.filter = filter;\n\t\t  $scope.loadProcesses();\n\t  };\n\n\t  $scope.activateSort = function(sort) {\n\t\t  $scope.model.activeSort = sort;\n\t\t  $rootScope.modelFilter.sort = sort;\n\t\t  $scope.loadProcesses();\n\t  };\n\n\t  $scope.loadProcesses = function() {\n\t\t  $scope.model.loading = true;\n\n\t\t  var params = {\n\t\t      filter: $scope.model.activeFilter.id,\n\t\t      sort: $scope.model.activeSort.id,\n\t\t      modelType: 0\n\t\t  };\n\n\t\t  if ($scope.model.filterText && $scope.model.filterText != '') {\n\t\t    params.filterText = $scope.model.filterText;\n\t\t  }\n\n\t\t  $http({method: 'GET', url: FLOWABLE.APP_URL.getModelsUrl(), params: params}).\n\t\t  \tsuccess(function(data, status, headers, config) {\n\t    \t\t$scope.model.processes = data;\n\t    \t\t$scope.model.loading = false;\n\t        }).\n\t        error(function(data, status, headers, config) {\n\t           console.log('Something went wrong: ' + data);\n\t           $scope.model.loading = false;\n\t        });\n\t  };\n\n\t  var timeoutFilter = function() {\n\t      $scope.model.isFilterDelayed = true;\n\t      $timeout(function() {\n\t          $scope.model.isFilterDelayed = false;\n\t          if ($scope.model.isFilterUpdated) {\n\t              $scope.model.isFilterUpdated = false;\n\t              timeoutFilter();\n\t          } else {\n\t              $scope.model.filterText = $scope.model.pendingFilterText;\n\t              $rootScope.modelFilter.filterText = $scope.model.filterText;\n\t              $scope.loadProcesses();\n\t          }\n\t      }, 500);\n\t  };\n\n\t  $scope.filterDelayed = function() {\n\t      if ($scope.model.isFilterDelayed) {\n\t          $scope.model.isFilterUpdated = true;\n\t      } else {\n\t          timeoutFilter();\n\t      }\n\t  };\n\n\t  $scope.createProcess = function(mode) {\n\t    var modalInstance = _internalCreateModal({\n\t        template: 'views/popup/process-create.html?version=' + Date.now()\n\t    }, $modal, $scope);\n\t  };\n\n\t  $scope.importProcess = function () {\n          _internalCreateModal({\n              template: 'views/popup/process-import.html?version=' + Date.now()\n          }, $modal, $scope);\n\t  };\n\n\t  $scope.showProcessDetails = function(process) {\n\t      if (process) {\n\t          $rootScope.editorHistory = [];\n\t          $location.path(\"/processes/\" + process.id);\n\t      }\n\t  };\n\n\t  $scope.editProcessDetails = function(process) {\n\t\t  if (process) {\n\t\t      $rootScope.editorHistory = [];\n              $location.path(\"/editor/\" + process.id);\n\t\t  }\n\t  };\n\n\t  // Finally, load initial processes\n\t  $scope.loadProcesses();\n  }]);\n\nangular.module('flowableModeler')\n.controller('CreateNewProcessModelCtrl', ['$rootScope', '$scope', '$modal', '$http', '$location',\n                                          function ($rootScope, $scope, $modal, $http, $location) {\n\n    $scope.model = {\n       loading: false,\n       process: {\n            name: '',\n            key: '',\n            description: '',\n           \tmodelType: 0\n       }\n    };\n\n    if ($scope.initialModelType !== undefined) {\n        $scope.model.process.modelType = $scope.initialModelType;\n    }\n\n    $scope.ok = function () {\n\n        if (!$scope.model.process.name || $scope.model.process.name.length == 0 ||\n        \t!$scope.model.process.key || $scope.model.process.key.length == 0) {\n        \t\n            return;\n        }\n\n        $scope.model.loading = true;\n\n        $http({method: 'POST', url: FLOWABLE.APP_URL.getModelsUrl(), data: $scope.model.process}).\n            success(function(data) {\n                $scope.$hide();\n\n                $scope.model.loading = false;\n                $rootScope.editorHistory = [];\n                $location.path(\"/editor/\" + data.id);\n            }).\n            error(function(data, status, headers, config) {\n                $scope.model.loading = false;\n                $scope.model.errorMessage = data.message;\n            });\n    };\n\n    $scope.cancel = function () {\n        if(!$scope.model.loading) {\n            $scope.$hide();\n        }\n    };\n}]);\n\nangular.module('flowableModeler')\n.controller('DuplicateProcessModelCtrl', ['$rootScope', '$scope', '$modal', '$http', '$location',\n                                          function ($rootScope, $scope, $modal, $http, $location) {\n\n    $scope.model = {\n       loading: false,\n       process: {\n            name: '',\n            key: '',\n            description: ''\n       }\n    };\n\n    if ($scope.originalModel) {\n        //clone the model\n        $scope.model.process.name = $scope.originalModel.process.name;\n        $scope.model.process.key = $scope.originalModel.process.key;\n        $scope.model.process.description = $scope.originalModel.process.description;\n        $scope.model.process.id = $scope.originalModel.process.id;\n        $scope.model.process.modelType = $scope.originalModel.process.modelType;\n    }\n\n    $scope.ok = function () {\n\n        if (!$scope.model.process.name || $scope.model.process.name.length == 0 || \n        \t!$scope.model.process.key || $scope.model.process.key.length == 0) {\n        \t\n            return;\n        }\n\n        $scope.model.loading = true;\n\n        $http({method: 'POST', url: FLOWABLE.APP_URL.getCloneModelsUrl($scope.model.process.id), data: $scope.model.process}).\n            success(function(data) {\n                $scope.$hide();\n\n                $scope.model.loading = false;\n                $rootScope.editorHistory = [];\n                $location.path(\"/editor/\" + data.id);\n            }).\n            error(function(data, status, headers, config) {\n                $scope.model.loading = false;\n                $scope.model.errorMessage = data.message;\n            });\n    };\n\n    $scope.cancel = function () {\n        if(!$scope.model.loading) {\n            $scope.$hide();\n        }\n    };\n}]);\n\nangular.module('flowableModeler')\n.controller('ImportProcessModelCtrl', ['$rootScope', '$scope', '$http', 'Upload', '$location', function ($rootScope, $scope, $http, Upload, $location) {\n\n  $scope.model = {\n       loading: false\n  };\n\n  $scope.onFileSelect = function($files, isIE) {\n\n      $scope.model.loading = true;\n\n      for (var i = 0; i < $files.length; i++) {\n          var file = $files[i];\n\n          var url;\n          if (isIE) {\n              url = FLOWABLE.APP_URL.getImportProcessModelTextUrl();\n          } else {\n              url = FLOWABLE.APP_URL.getImportProcessModelUrl();\n          }\n\n          Upload.upload({\n              url: url,\n              method: 'POST',\n              file: file\n          }).progress(function(evt) {\n              $scope.model.uploadProgress = parseInt(100.0 * evt.loaded / evt.total);\n\n          }).success(function(data) {\n              $scope.model.loading = false;\n\n              $location.path(\"/editor/\" + data.id);\n              $scope.$hide();\n\n          }).error(function(data) {\n\n              if (data && data.message) {\n                  $scope.model.errorMessage = data.message;\n              }\n\n              $scope.model.error = true;\n              $scope.model.loading = false;\n          });\n      }\n  };\n\n  $scope.cancel = function () {\n\t  if(!$scope.model.loading) {\n\t\t  $scope.$hide();\n\t  }\n  };\n}]);\n"
  },
  {
    "path": "flowable-ui-web/modeler/scripts/editor-directives.js",
    "content": "/* 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 */\nangular.module('flowableModeler')\n    .directive('loading', ['$translate', function ($translate) {\n        return {\n            restrict: 'E',\n            template: '<div class=\\'loading pull-right\\' ng-show=\\'status.loading\\'><div class=\\'l1\\'></div><div class=\\'l2\\'></div><div class=\\'l2\\'></div></div>'\n        };\n    }]);\n\nangular.module('flowableModeler')\n    .directive('loadingLeftPull', ['$translate', function ($translate) {\n        return {\n            restrict: 'E',\n            template: '<div class=\\'loading pull-left\\' ng-show=\\'status.loading\\'><div class=\\'l1\\'></div><div class=\\'l2\\'></div><div class=\\'l2\\'></div></div>'\n        };\n    }]);\n\n/**\n * This is a template for the icon of a stencil item.\n */\nangular.module('flowableModeler')\n    .directive('stencilItemIcon', [function () {\n        return {\n            scope: {\n                item: '=stencilItem'\n            },\n            restrict: 'E',\n            template: '<img class=\"stencil-item-list-icon\" ng-if=\\\"item.customIconId != null && item.customIconId != undefined\\\" ng-src=\\\"' + getImageUrl(item.customIconId) + '\\\" width=\\\"16px\\\" height=\\\"16px\\\"/>' +\n            '<img class=\"stencil-item-list-icon\" ng-if=\\\"(item.customIconId == null || item.customIconId == undefined) && item.icon != null && item.icon != undefined\\\" ng-src=\\\"editor-app/stencilsets/bpmn2.0/icons/{{item.icon}}\\\" width=\\\"16px\\\" height=\\\"16px\\\"/>'\n        };\n    }]);\n\n// Workaround for https://github.com/twbs/bootstrap/issues/8379 :\n// prototype.js interferes with regular dropdown behavior\nangular.module('flowableModeler')\n    .directive('activitiFixDropdownBug', function () {\n        return {\n            restrict: 'AEC',\n            link: function (scope, element, attrs) {\n                if (!element.hasClass('btn-group')) {\n                    // Fix applied to button, use parent instead\n                    element = element.parent();\n                }\n                element.on('hidden.bs.dropdown\t', function () {\n                    element.show(); // evil prototype.js has added display:none to it ...\n                })\n            }\n        };\n    });\n\n\n//form builder element renderer\nangular.module('flowableModeler').directive('formBuilderElement', ['$rootScope', '$timeout', '$modal', '$http', '$templateCache', '$translate', 'RecursionHelper', 'FormBuilderService',\n    function ($rootScope, $timeout, $modal, $http, $templateCache, $translate, RecursionHelper, FormBuilderService) {\n    return {\n        restrict: 'AE',\n        templateUrl: 'views/templates/form-builder-element-template.html',\n        transclude: false,\n        scope: {\n            formElement: '=formElement',\n            editState: '=editState',\n            formMode: '=formMode',\n            drop: \"&\",\n            moved: \"&\"\n        },\n        compile: function(element) {\n            return RecursionHelper.compile(element, this.link);\n        },\n        link: function ($scope, $element, attributes) {\n\n            $scope.formTabs = [\n                {\n                    \"id\": \"general\",\n                    \"name\": $translate.instant('FORM-BUILDER.TABS.GENERAL')\n                },\n                {\n                    \"id\": \"options\",\n                    \"name\": $translate.instant('FORM-BUILDER.TABS.OPTIONS'),\n                    \"show\": ['dropdown', 'radio-buttons']\n                },\n                {\n                    \"id\": \"upload\",\n                    \"name\": $translate.instant('FORM-BUILDER.TABS.UPLOAD-OPTIONS'),\n                    \"show\": ['upload']\n                },\n                {\n                    \"id\": \"advanced\",\n                    \"name\": $translate.instant('FORM-BUILDER.TABS.ADVANCED-OPTIONS'),\n                    \"show\": ['text', 'password', 'multi-line-text', 'integer', 'decimal','hyperlink']\n                }\n            ];\n\n            $scope.activeTab = $scope.formTabs[0];\n\n            $scope.tabClicked = function (tab) {\n                $scope.activeTab = tab;\n            };\n\n            var templateUrl = 'views/popover/formfield-edit-popover.html';\n\n\n            $scope.removeFormElement = function (formElement) {\n                if ($rootScope.formItems.indexOf(formElement) >= 0) {\n                    $rootScope.formItems.splice($rootScope.formItems.indexOf(formElement), 1);\n                }\n            };\n\n            $scope.pristine = true;\n            $scope.newOption = {\n                name: ''\n            };\n\n            $scope.insertFormField = {\n                position: 0\n            };\n\n            $scope.openFieldPopover = function () {\n\n                // Storing original values. In case the changes would trigger a layout change\n                var originalFormElementType = $scope.formElement.type;\n                var originalDisplayFieldType = undefined;\n                if (originalFormElementType === 'readonly') {\n                    if ($scope.formElement.params\n                        && $scope.formElement.params.field\n                        && $scope.formElement.params.field.type) {\n                        originalDisplayFieldType = $scope.formElement.params.field.type;\n                    }\n                }\n\n                // Create popover\n                $scope.fieldEditPopup = _internalCreateModal({\n                    template: 'views/popover/formfield-edit-popover.html?version=' + Date.now(),\n                    scope: $scope,\n                    backdrop: 'static',\n                    keyboard: false\n                }, $modal, $scope);\n\n                // Check for layout changes\n                var deregisterHideListener = $scope.$on('modal.hide', function() {\n                    if ($scope.formElement.type === 'readonly') {\n\n                        if ($scope.formElement.params && $scope.formElement.params.field && $scope.formElement.params.field.type\n                            && $scope.formElement.params.field.type !== originalFormElementType) {\n\n                            $scope.$emit('readonly-field-referenced-field-changed', {\n                                formElement: $scope.formElement,\n                                originalDisplayFieldType: originalDisplayFieldType\n                            });\n\n                        }\n                    }\n\n                    deregisterHideListener();\n                });\n\n            };\n\n            $scope.formElementNameChanged = function (field) {\n                if (!field.overrideId) {\n                    var fieldId;\n                    if (field.name && field.name.length > 0) {\n                        fieldId = field.name.toLowerCase();\n                        fieldId = fieldId.replace(new RegExp(' ', 'g'), '');\n                        fieldId = fieldId.replace(/[&\\/\\\\#,+~%.'\":*?!<>{}()$@;]/g, '');\n                    } else {\n                        var index = 1;\n                        if (field.layout) {\n                            index = 1 + (2 * field.layout.row) + field.layout.column;\n                        }\n                        fieldId = 'field' + index;\n                    }\n                    field.id = fieldId;\n                }\n            };\n\n            $scope.confirmNewOption = function ($event) {\n                if ($scope.newOption.name) {\n                    var options = $scope.formElement.options;\n                    options.push($scope.newOption);\n\n                    $scope.newOption = {name: ''};\n\n                    // if first additional option; first option is defaulted\n                    if (options.length == 2) {\n                        $scope.formElement.value = $scope.formElement.options[0].name;\n                    }\n\n                    if ($event) {\n                        // Focus the input field again, to make adding more options possible immediatly\n                        $($event.target).focus();\n                    }\n                }\n            };\n\n            $scope.optionKeyDown = function ($event) {\n                if ($event.keyCode == 13) {\n                    $scope.confirmNewOption($event);\n                }\n            };\n\n            $scope.removeOption = function (index) {\n                $scope.formElement.options.splice(index, 1);\n\n\n                // if only 1 option left; reset default\n                if ($scope.formElement.options == 1) {\n                    $scope.formElement.value = '';\n                } else {\n\n                    // if removed element is the default option; first option is defaulted\n                    var isPresent = false;\n                    for (var i = 0; i < $scope.formElement.options.length; i++) {\n                        if ($scope.formElement.options[i].name == $scope.formElement.value) {\n                            isPresent = true;\n                        }\n                    }\n                    if (!isPresent) {\n                        $scope.formElement.value = $scope.formElement.options[0].name;\n                    }\n                }\n            };\n\n            $scope.optionsExpressionChanged = function ($event) {\n            \tif(event.target.checked) {\n            \t\t$scope.formElement.options = [];\n                    $scope.formElement.value = '';\n                    $scope.formElement.optionsExpression = '${}';\n            \t} else {\n            \t\t$scope.formElement.optionsExpression = null;\n                    if ($scope.formElement.type === 'radio-buttons') {\n                    \t$scope.formElement.options = [{ \n                        \tname: $translate.instant('FORM-BUILDER.COMPONENT.RADIO-BUTTON-DEFAULT')\n                        }];\n                    } else if($scope.formElement.type === 'dropdown') {\n                    \t$scope.formElement.options = [\n                            {name: $translate.instant('FORM-BUILDER.COMPONENT.DROPDOWN-DEFAULT-EMPTY-SELECTION')}\n                        ];\n\t                    $scope.formElement.value = field.options[0];\n\t                    $scope.formElement.hasEmptyValue = true;\n            \t    }\n            \t}\n            };\n\n            $scope.doneEditing = function () {\n\n                if ($scope.fieldEditPopup) {\n                    $scope.fieldEditPopup.$scope.$hide();\n                }\n            };\n\n            // Readonly field\n            $scope.$watch('formElement.params.field', function (newValue, oldValue) {\n                if (!$scope.pristine || (oldValue !== undefined && oldValue.id != newValue.id)) {\n                    if (newValue && newValue.name) {\n                        // Update the element's name\n                        $scope.formElement.name = newValue.name;\n                    }\n                } else {\n                    $scope.pristine = false;\n                }\n\n            });\n        }\n    };\n}]);\n\n\nangular.module('flowableModeler').directive('storeCursorPosition', ['$rootScope', '$timeout', '$popover', '$http', '$templateCache', function ($rootScope, $timeout, $popover, $http, $templateCache) {\n    return {\n        restrict: 'A',\n        scope: {\n            storeCursorPosition: '=storeCursorPosition'\n        },\n        link: function ($scope, $element, attributes) {\n            $element.on('click change keypress', function () {\n                if ($scope.storeCursorPosition !== undefined) {\n                    $scope.storeCursorPosition = $element[0].selectionStart;\n                }\n            });\n        }\n    };\n}]);\n\nangular.module('flowableModeler').\n    directive('editorInputCheck', function () {\n\n        return {\n            require: 'ngModel',\n            link: function (scope, element, attrs, modelCtrl) {\n\n                modelCtrl.$parsers.push(function (inputValue) {\n\n                    var transformedInput = inputValue.replace(/[&\\/\\\\#,+~%.'\":*?<>{}()$@;]/g, '');\n\n                    if (transformedInput != inputValue) {\n                        modelCtrl.$setViewValue(transformedInput);\n                        modelCtrl.$render();\n                    }\n\n                    return transformedInput;\n                });\n            }\n        };\n    });\n\nangular.module('flowableModeler').\n    directive('hotAutoDestroy',[\"hotRegisterer\",function(hotRegisterer) {\n    return {\n        restrict: 'A',\n        link: function (scope, element, attr){\n            element.on(\"$destroy\", function() {\n                try{\n                    var hotInstance = hotRegisterer.getInstance(attr.hotId);\n                    hotInstance.destroy();\n                }\n                catch(er){\n                    console.log(er);\n                }\n            });\n        }\n    };\n}]);\n"
  },
  {
    "path": "flowable-ui-web/modeler/scripts/resource-loader.js",
    "content": "/* Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n(function(resources){\n\n    if (resources) {\n\n        // Pause angular bootstrap so we have time to register and override angular services/directives etc\n        window.name = 'NG_DEFER_BOOTSTRAP!';\n\n        function load(res, node, callback, scope) {\n            var resource;\n            if (res.tag === 'script') {\n                resource = document.createElement('script');\n                resource.type = res.type || 'text/javascript';\n                resource.src = res.src;\n\n                if (callback) {\n                    var done = false;\n\n                    // Attach handlers for all browsers\n                    resource.onload = resource.onreadystatechange = function()\n                    {\n                        if (!done && (!this.readyState || this.readyState == \"loaded\" || this.readyState == \"complete\"))\n                        {\n                            done = true;\n                            callback.call(scope ? scope : this, res);\n                        }\n                    };\n                }\n            }\n            else if (res.tag === 'link') {\n                resource = document.createElement('link');\n                resource.rel = res.rel || 'stylesheet';\n                resource.href = res.href;\n            }\n\n            if (node.nextSibling) {\n                node.parentNode.insertBefore(resource, node.nextSibling);\n            }\n            else {\n                node.parentNode.appendChild(resource);\n            }\n\n            if (res.tag === 'link' && callback) {\n                callback.call(scope ? scope : this, res);\n            }\n        }\n\n        function getResourceLoaderElement() {\n            var scripts = document.getElementsByTagName('script');\n            for (var i = 0, il = scripts.length; i < il; i++) {\n                if (scripts[i].src.indexOf('scripts/resource-loader.js') != -1) {\n                    return scripts[i];\n                }\n            }\n            return null;\n        }\n\n        var res = resources['*'];\n        var resourceLoaderElement = getResourceLoaderElement();\n        var appName = resourceLoaderElement.getAttribute('app');\n        if (resources.hasOwnProperty(appName)) {\n            res = resources[appName];\n        }\n\n        var loadedResources = 0;\n        for (var i = 0, il = res.length; i < il; i++) {\n            load(res[i], resourceLoaderElement, function(){\n                loadedResources++;\n                if (loadedResources == res.length) {\n                    // Let angular resume bootstrap\n                    var interval = window.setInterval(function(){\n                        if (angular && typeof angular.resumeBootstrap == 'function') {\n                            angular.resumeBootstrap();\n                            window.clearInterval(interval);\n                        }\n                    }, 20);\n\n                }\n            });\n        }\n    }\n\n})(FLOWABLE.CONFIG.resources);"
  },
  {
    "path": "flowable-ui-web/modeler/scripts/services/decision-table-service.js",
    "content": "/* Copyright 2005-2015 Alfresco Software, Ltd.\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'use strict';\n\n// Decision Table service\nangular.module('flowableModeler').service('DecisionTableService', [ '$rootScope', '$http', '$q', '$timeout', '$translate',\n    function ($rootScope, $http, $q, $timeout, $translate) {\n\n        var httpAsPromise = function(options) {\n            var deferred = $q.defer();\n            $http(options).\n                success(function (response, status, headers, config) {\n                    deferred.resolve(response);\n                })\n                .error(function (response, status, headers, config) {\n                    console.log('Something went wrong during http call:' + response);\n                    deferred.reject(response);\n                });\n            return deferred.promise;\n        };\n\n        this.filterDecisionTables = function(filter) {\n            return httpAsPromise(\n                {\n                    method: 'GET',\n                    url: FLOWABLE.APP_URL.getDecisionTableModelsUrl(),\n                    params: {filter: filter}\n                }\n            );\n        };\n\n        /**\n         * Fetches the details of a decision table.\n         */\n        this.fetchDecisionTableDetails = function(modelId, historyModelId) {\n            var url = historyModelId ?\n                FLOWABLE.APP_URL.getDecisionTableModelHistoryUrl(encodeURIComponent(modelId), encodeURIComponent(historyModelId)) :\n                FLOWABLE.APP_URL.getDecisionTableModelUrl(encodeURIComponent(modelId));\n            return httpAsPromise({ method: 'GET', url: url });\n        };\n\n        function cleanUpModel (decisionTableDefinition) {\n            delete decisionTableDefinition.isEmbeddedTable;\n            var expressions = (decisionTableDefinition.inputExpressions || []).concat(decisionTableDefinition.outputExpressions || []);\n            if (decisionTableDefinition.rules && decisionTableDefinition.rules.length > 0) {\n                decisionTableDefinition.rules.forEach(function (rule) {\n                    var headerExpressionIds = [];\n                    expressions.forEach(function(def){\n                        headerExpressionIds.push(def.id);\n                    });\n\n                    // Make sure that the rule has all header ids defined as attribtues\n                    headerExpressionIds.forEach(function(id){\n                        if (!rule.hasOwnProperty(id)) {\n                            rule[id] = \"\";\n                        }\n                    });\n\n                    // Make sure that the rule does not have an attribute that is not a header id\n                    delete rule.$$hashKey;\n                    for (var id in rule) {\n                        if (headerExpressionIds.indexOf(id) === -1) {\n                            delete rule[id];\n                            delete rule.validationErrorMessages;\n                        }\n                    }\n\n                });\n            }\n        }\n\n        this.saveDecisionTable = function (data, name, key, description, saveCallback, errorCallback) {\n\n            data.decisionTableRepresentation = {\n            \tname: name,\n            \tkey: key\n            };\n\n            if (description && description.length > 0) {\n                data.decisionTableRepresentation.description = description;\n            }\n\n            var decisionTableDefinition = angular.copy($rootScope.currentDecisionTable);\n\n            data.decisionTableRepresentation.decisionTableDefinition = decisionTableDefinition;\n            decisionTableDefinition.modelVersion = '2';\n            decisionTableDefinition.key = key;\n            decisionTableDefinition.rules = angular.copy($rootScope.currentDecisionTableRules);\n\n\t\t\thtml2canvas(jQuery('#decision-table-editor'), {\n                onrendered: function (canvas) {\n                    var scale = canvas.width / 300.0;\n\n                    var extra_canvas = document.createElement('canvas');\n                    extra_canvas.setAttribute('width', 300);\n                    extra_canvas.setAttribute('height', canvas.height / scale);\n\n                    var ctx = extra_canvas.getContext('2d');\n                    ctx.drawImage(canvas, 0, 0, canvas.width, canvas.height, 0, 0, 300, canvas.height / scale);\n\n                    data.decisionTableImageBase64 = extra_canvas.toDataURL('image/png');\n\n                    $http({\n\t                    method: 'PUT',\n\t                    url: FLOWABLE.APP_URL.getDecisionTableModelUrl($rootScope.currentDecisionTable.id),\n\t                    data: data}).\n\t                \n\t                \tsuccess(function (response, status, headers, config) {\n\n                            if (saveCallback) {\n                                saveCallback();\n                            }\n                        }).\n                        error(function (response, status, headers, config) {\n                            if (errorCallback) {\n                                errorCallback(response);\n                            }\n                        });\n                }\n            });\n        };\n\n        this.getDecisionTables = function (decisionTableIds, callback) {\n\n            if (decisionTableIds.length > 0) {\n\n                var decisionTableIdParams = '';\n                for (var i = 0; i < decisionTableIds.length; i++) {\n                    if (decisionTableIdParams.length > 0) {\n                        decisionTableIdParams += '&';\n                    }\n                    decisionTableIdParams += 'decisionTableId=' + decisionTableIds[i];\n                }\n                if (decisionTableIdParams.length > 0) {\n                    decisionTableIdParams += '&';\n                }\n                decisionTableIdParams += 'version=' + Date.now();\n\n                $http({method: 'GET', url: FLOWABLE.APP_URL.getDecisionTableModelValuesUrl(decisionTableIdParams)}).\n                    success(function (data) {\n                        if (callback) {\n                            callback(data);\n                        }\n                    }).\n\n                    error(function (data) {\n                        console.log('Something went wrong when fetching decision table(s):' + JSON.stringify(data));\n                    });\n                    \n            } else {\n                if (callback) {\n                    callback();\n                }\n            }\n        };\n\n    }]);\n"
  },
  {
    "path": "flowable-ui-web/modeler/scripts/services/form-services.js",
    "content": "/* 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'use strict';\n\n// Form service\nangular.module('flowableModeler').service('FormBuilderService', ['$http', '$q', '$rootScope', '$translate',\n    function ($http, $q, $rootScope, $translate) {\n\n        // Removes all properties starting with '_', used before json serialization\n        function removePrivateFields(fields) {\n            fields.forEach(function(field, i){\n                for (var attr in field) {\n                    if (attr.indexOf('_') === 0) {\n                        delete field[attr];\n                    }\n                }\n                if (field.fields) {\n                    for (var fieldsName in field.fields) {\n                        removePrivateFields(field.fields[fieldsName]);\n                    }\n                }\n            });\n            return fields;\n        }\n\n        /**\n         * Remove the given step from the given container.\n         */\n        this.saveForm = function (data, name, formKey, description, saveCallback, errorCallback) {\n\n            var fieldIndex = 0;\n            data.formRepresentation = $rootScope.currentForm;\n            data.formRepresentation.name = name;\n            data.formRepresentation.key = formKey;\n\n            if (description && description.length > 0) {\n                data.formRepresentation.description = description;\n            }\n            for (var i = 0; i < $rootScope.formItems.length; i++) {\n                var field = $rootScope.formItems[i];\n                this._cleanFormField(field, fieldIndex++);\n            }\n\n            var currentActiveTab = $rootScope.formBuilder.activeTab;\n            if (currentActiveTab != 'design') {\n                $rootScope.formBuilder.activeTab = 'design';\n            }\n\n            data.formRepresentation.formDefinition = {\n            \tname: name,\n            \tkey: formKey,\n            \tfields: removePrivateFields(angular.copy($rootScope.formItems)), \n            \toutcomes: $rootScope.currentOutcomes\n            };\n\n            html2canvas(jQuery('#canvasSection'), {\n                onrendered: function (canvas) {\n                    var scale = canvas.width / 300.0;\n                    var extra_canvas = document.createElement(\"canvas\");\n                    extra_canvas.setAttribute('width', 300);\n                    extra_canvas.setAttribute('height', canvas.height / scale);\n                    var ctx = extra_canvas.getContext('2d');\n                    ctx.drawImage(canvas, 0, 0, canvas.width, canvas.height, 0, 0, 300, canvas.height / scale);\n                    data.formImageBase64 = extra_canvas.toDataURL(\"image/png\");\n\n                    $http({method: 'PUT', url: FLOWABLE.APP_URL.getFormModelUrl($rootScope.currentForm.id), data: data}).\n                        success(function (response, status, headers, config) {\n\n                            if (saveCallback) {\n                                saveCallback();\n                            }\n                        }).\n                        error(function (response, status, headers, config) {\n                            if (errorCallback) {\n                                errorCallback(response);\n                            }\n                        });\n\n                    if (currentActiveTab != 'design') {\n                        $rootScope.formBuilder.activeTab = currentActiveTab;\n                    }\n                }\n            });\n        };\n        \n        this._cleanFormField = function(field, fieldIndex) {\n            if (!field.overrideId) {\n                var fieldId;\n                if (field.name && field.name.length > 0) {\n                    fieldId = field.name.toLowerCase();\n                    fieldId = fieldId.replace(new RegExp(' ', 'g'), '');\n                    fieldId = fieldId.replace(/[&\\/\\\\#,+~%.'\":*?!<>{}()$@;]/g, '');\n                } else {\n                    fieldId = 'field' + fieldIndex;\n                }\n                field.id = fieldId;\n            }\n        };\n\n        /**\n         * Updates the form cache for a specific step\n         * @param {String} stepId\n         * @param {Object} formDefinition\n         */\n        this.updateFormsCache = function (stepId, formDefinition) {\n            if (stepId) {\n                if (formDefinition && formDefinition.id) {\n                    _updateFormCache(stepId, formDefinition.id);\n                } else {\n                    _updateFormCache(stepId);\n                }\n            }\n        };\n\n        /**\n         * Fetches forms from cache up to the given step (and not after)\n         * @param {Array} steps all steps in sequential order\n         * @param {String} stepId the current step\n         * @return {Array} flattened list of all forms up to given step\n         */\n        this.getFormsForStep = function (steps, stepId) {\n            var forms = [];\n\n            if (stepId !== '__startform') {\n                // check start for start form\n                forms.push(_getFormForStep('__startform'));\n\n                if (stepId && steps && steps.length > 0) {\n                    for (var i = 0; i < steps.length; i++) {\n                        if (steps[i].id != stepId) {\n                            forms.push(_getFormForStep(steps[i].id));\n                        } else {\n                            break;\n                        }\n                    }\n                }\n            }\n\n            // only unique forms\n            var uniqueIds = [];\n            var uniqueForms = [];\n\n            forms.forEach(function (item) {\n                if (item && item.id) {\n                    if (uniqueIds.indexOf(item.id) < 0) {\n                        uniqueIds.push(item.id);\n                        uniqueForms.push(item);\n                    }\n                }\n            });\n\n            uniqueForms.sort(function(a,b){\n                return a.name.toLowerCase() > b.name.toLowerCase() ? 1 : -1;\n            });\n\n            return uniqueForms;\n        };\n\n        /**\n         * Fetches form outcomes from cache for specific form\n         * @param {String} formId\n         * @return {Array} flattened list of all form outcomes\n         */\n        this.getFormOutcomesForForm = function (formId) {\n            var outcomes = [];\n            if (formId) {\n                outcomes = _getFormOutcomesForForm(formId);\n            }\n\n            outcomes.sort(function(a,b){\n                return a.name.toLowerCase() > b.name.toLowerCase() ? 1 : -1;\n            });\n\n            return outcomes;\n        };\n\n        /**\n         * Fetches form fields from cache for specific form\n         * @param {String} formId\n         * @return {Array} flattened list of all form form fields\n         */\n        this.getFormFieldsForForm = function (formId) {\n            var formFields = [];\n            if (formId) {\n                formFields = _getFormFieldsForForm(formId);\n            }\n            return formFields;\n        };\n\n        var _updateFormCache = function (stepId, formId) {\n            if (stepId && formId) {\n                $http({method: 'GET', url: FLOWABLE.APP_URL.getFormModelUrl(formId)}).\n                    success(function(response) {\n                        if (response) {\n                            var outcomes;\n                            var formFields;\n                            if (response.formDefinition) {\n                                if (response.formDefinition.fields) {\n                                    formFields = response.formDefinition.fields;\n                                }\n\n                                if (response.formDefinition.outcomes) {\n                                    outcomes = response.formDefinition.outcomes;\n                                }\n                            }\n                            var filteredFormFields = _filterFormFields(formFields);\n                            var formFieldInfo = {id: response.id, name: response.name, description: response.description, outcomes: outcomes, fields: filteredFormFields};\n                            _addFormFieldsForStepToCache(stepId, formFieldInfo);\n                        }\n                    });\n            }\n            if (stepId && !formId) {\n                _deleteFormFieldsForStepFromCache(stepId);\n            }\n        };\n\n        var _getFormDefinitions = function (formIds, callback) {\n\n            if (formIds.length > 0) {\n\n                var formIdParams = '';\n                for (var i = 0; i < formIds.length; i++) {\n                    if (formIdParams.length > 0) {\n                        formIdParams += '&';\n                    }\n                    formIdParams += 'formId=' + formIds[i];\n                }\n                if (formIdParams.length > 0) {\n                    formIdParams += '&';\n                }\n                formIdParams += 'version=' + Date.now();\n\n                $http({method: 'GET', url: FLOWABLE.APP_URL.getFormModelValuesUrl(formIdParams)}).\n                    success(function (data) {\n                        if (callback) {\n                            callback(data);\n                        }\n                    }).\n\n                    error(function (data) {\n                        console.log('Something went wrong when fetching form values:' + JSON.stringify(data));\n                    });\n            }\n        };\n    }\n]);\n"
  },
  {
    "path": "flowable-ui-web/modeler/scripts/services/identity-services.js",
    "content": "/* 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'use strict';\n\nangular.module('flowableModeler').service('UserService', ['$http', '$q',\n    function ($http, $q) {\n\n        var httpAsPromise = function(options) {\n            var deferred = $q.defer();\n            $http(options).\n                success(function (response, status, headers, config) {\n                    deferred.resolve(response);\n                })\n                .error(function (response, status, headers, config) {\n                    deferred.reject(response);\n                });\n            return deferred.promise;\n        };\n\n        /*\n         * Filter users based on a filter text.\n         */\n        this.getFilteredUsers = function (filterText, taskId, processInstanceId) {\n            var params = {filter: filterText};\n            if(taskId) {\n                params.excludeTaskId = taskId;\n            }\n            if (processInstanceId) {\n                params.exclusdeProcessId = processInstanceId;\n            }\n\n            return httpAsPromise({\n                method: 'GET',\n                url: FLOWABLE.APP_URL.getEditorUsersUrl(),\n                params: params\n            });\n        };\n\n    }]);\n\nangular.module('flowableModeler').service('GroupService', ['$http', '$q',\n    function ($http, $q) {\n\n        var httpAsPromise = function(options) {\n            var deferred = $q.defer();\n            $http(options).\n                success(function (response, status, headers, config) {\n                    deferred.resolve(response);\n                })\n                .error(function (response, status, headers, config) {\n                    deferred.reject(response);\n                });\n            return deferred.promise;\n        };\n\n        /*\n         * Filter functional groups based on a filter text.\n         */\n        this.getFilteredGroups = function (filterText) {\n            var params;\n            if(filterText) {\n                params = {filter: filterText};\n            }\n\n            return httpAsPromise({\n                method: 'GET',\n                url: FLOWABLE.APP_URL.getEditorGroupsUrl(),\n                params: params\n            });\n        };\n    }]);\n"
  },
  {
    "path": "flowable-ui-web/modeler/scripts/services/util-services.js",
    "content": "/* 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 * Service with small utility methods\n */\nangular.module('flowableModeler').service('UtilityService', [ '$window', '$document', '$timeout', function ($window, $document, $timeout) {\n\n    this.scrollToElement = function(elementId) {\n        $timeout(function() {\n            var someElement = angular.element(document.getElementById(elementId))[0];\n            if (someElement) {\n                if (someElement.getBoundingClientRect().top > $window.innerHeight) {\n                    $document.scrollToElement(someElement, 0, 1000);\n                }\n            }\n        });\n    };\n\n}]);"
  },
  {
    "path": "flowable-ui-web/modeler/styles/common/style-retina.css",
    "content": "/* Retina tweaks */\n@media \tonly screen and (-webkit-min-device-pixel-ratio: 1.5),\nonly screen and (   min--moz-device-pixel-ratio: 1.5),\nonly screen and (     -o-min-device-pixel-ratio: 3/2),\nonly screen and (        min-device-pixel-ratio: 1.5),\nonly screen and (min-resolution: 192dpi) {\n\n    .navbar-header .navbar-brand {\n        background-size: 148px 25px;\n    }\n\n    .account .google-drive {\n        background: transparent url('../../images/google-drive-2x.png') 50% 50% no-repeat;\n        background-size: 34px 34px;\n    }\n\n    .account .alfresco {\n        background: transparent url('../../images/alfresco-2x.png') 50% 50% no-repeat;\n        background-size: 34px 34px;\n    }\n\n    .account .alfresco-cloud {\n        background: transparent url('../../images/alfresco-cloud-2x.png') 50% 50% no-repeat;\n        background-size: 34px 34px;\n    }\n}"
  },
  {
    "path": "flowable-ui-web/modeler/styles/common/style.css",
    "content": "/**\n Colors:\n\n  - Header: #1f3245\n  - Subheader: #e8edf1\n  - Subheader border: #a4acb9\n  - Highlight buttons/text: #2980b9\n  - Text color: #1a1a1a\n  - Filter color: #373e48\n  - Dark highlight: #606b7d\n*/\n\n@font-face {\n    font-family: 'cherokeeregular';\n    src: url('../../fonts/cherokee-webfont.eot');\n    src: url('../../fonts/cherokee-webfont.eot?#iefix') format('embedded-opentype'),\n    url('../../fonts/cherokee-webfont.woff') format('woff'),\n    url('../../fonts/cherokee-webfont.ttf') format('truetype'),\n    url('../../fonts/cherokee-webfont.svg#cherokeeregular') format('svg');\n    font-weight: normal;\n    font-style: normal;\n}\n\n@font-face {\n    font-family: 'Titillium Web';\n    font-style: normal;\n    font-weight: normal;\n    url('../../fonts/TitilliumWeb-Regular.ttf') format('truetype');\n}\n\n@font-face {\n    font-family: 'Titillium Web';\n    font-style: normal;\n    font-weight: bold;\n    url('../../fonts/TitilliumWeb-Bold.ttf') format('truetype');\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,\nbody pre {\n    font-family: 'Titillium Web', sans-serif;\n}\n\nbody pre {\n    border: none;\n    padding: 0;\n    background: transparent;\n}\n\nhr {\n\tborder-top: 1px solid #606b7d; \n}\n\n.form-wrapper textarea {\n    width: 100%;\n    max-width: 100%;\n    min-width: 100%;\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:hover {\n    font-weight: bolder;\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: #2980b9;\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.btn[disabled]:hover, .btn[disabled].active, .btn[disabled]:focus {\n    background-color: #3990c9;\n    border-color: #ffffff;\n    color: #ffffff;\n}\n\n.btn[disabled]:active, .btn[disabled].active {\n    outline: 0;\n    background-image: none;\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\n.btn.disabled, .btn[disabled], .btn[disabled]:active, .btn[disabled]:hover {\n    background-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: #2980b9;\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: #2980b9;\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: 350px;\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: #1f3245;\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    width: 180px;\n}\n\n\n.navbar-nav {\n    height: 40px;\n    margin-left: 50px;\n}\n\n.navbar-inverse .navbar-nav > li > a {\n\tcolor: #a8bac1;\n}\n\n.navbar-inverse .navbar-nav > .active > a {\n\tbackground-color: #1f3245;\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    content: \" \";\n    height: 0;\n    width: 0;\n    position: absolute;\n    pointer-events: none;\n    border: 6px solid rgba(0, 0, 0, 0);\n    border-top-color: #1f3245;\n    margin-left: -6px;\n}\n\n.navbar-nav > li.active:hover:after {\n    border-top-color: #000000;\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: #2980b9;\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: 'Titillium Web', 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: #2980b9;\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    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: 1;\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    background-color: #ffffff;\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: #2980b9;\n}\n\n.main-list .list-subheader {\n    margin-top: 40px;\n    position: relative;\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: #2980b9;\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: #2980b9;\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: #2980b9;\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: #2980b9;\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\nh3+div > .dropzone {\n    margin-top: 5px;\n}\n\n.dropzone {\n    position: relative;\n    margin: 0px;\n    padding: 10px 10px;\n    text-align: center;\n}\n\n.dropzone .error, .error-message {\n    background-color: #e9af9f;\n    border: 1px solid #e4593d;\n    background-color: rgba(228, 89, 61, .7);\n    padding: 5px;\n    margin-bottom: 5px;\n    font-size: 14px;\n    color:white;\n}\n\n.dropzone.selection {\n    text-align: left;\n    padding-left: 5px;\n}\n\n.dropzone .select-file {\n    line-height: 40px;\n}\n\n.dropzone.dragover {\n    border: 1px dotted #2980b9;\n}\n\n.dropzone .message {\n    color: #999999;\n    line-height: 22px;\n    visibility: hidden;\n    position: absolute;\n    top: 20px;\n    left: 10px;\n    right: 10px;\n    text-align: center;\n}\n\n.dropzone.dragover .message {\n    color: #2980b9;\n    font-size: 20px;\n    visibility: inherit;\n}\n\n\n.dropzone.uploading .message {\n    visibility: hidden;\n}\n\n.dropzone input[type=file] {\n    width: 100%;\n    display: none;\n    visibility: hidden;\n}\n\n.dropzone.dragover input, .dropzone.dragover .account, .dropzone.dragover .select-file {\n    visibility: hidden;\n}\n\n.dropzone .account {\n    float: left;\n    text-align: center;\n    width: 50px;\n\n    padding: 0px 0px 0px 3px;\n    border-left: 1px solid #eeeeee;\n}\n\n.dropzone .no-upload .account {\n    border-left: none;\n    border-right: 1px solid #eeeeee;\n}\n.dropzone .account:first-child {\n    padding-left: 0;\n}\n\n.dropzone .account > div {\n    height: 40px;\n    cursor: pointer;\n}\n\n.dropzone.uploading .account > div {\n    cursor: not-allowed;\n}\n\n.account .google-drive {\n    background: transparent url('../../images/google-drive.png') 50% 50% no-repeat;\n}\n\n.account .alfresco {\n    background: transparent url('../../images/alfresco.png') 50% 50% no-repeat;\n}\n\n.account .alfresco-cloud {\n    background: transparent url('../../images/alfresco-cloud.png') 50% 50% no-repeat;\n}\n\n.dropzone .loading {\n    position: absolute;\n    left: 50%;\n    margin-left: -15px;\n    line-height: 30px;\n    top: 0px;\n}\n\n.dropzoneIE9.selectionIE9 {\n    text-align: left;\n    padding-left: 5px;\n}\n.dropzoneIE9 {\n    position: relative;\n    margin: 0px;\n    padding: 10px 10px;\n    text-align: center;\n}\n.selectionIE9 {\n    position: relative;\n    margin: 0;\n    padding: 6px 8px;\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    font-size: 14px;\n    cursor: pointer;\n}\n\n.selectionIE9 .actions {\n    float: right;\n}\n\n.dropzoneIE9 .account:first-child {\n    padding-left: 0;\n}\n\n.dropzoneIE9 .account {\n    float: left;\n    text-align: center;\n    width: 50px;\n    padding: 0px 0px 0px 3px;\n    border-left: 1px solid #eeeeee;\n}\n\n.dropzoneIE9 .account > div {\n    height: 40px;\n    cursor: pointer;\n}\n\n.dropzoneIE9 .select-file {\n    line-height: 40px;\n}\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}\n\n\n.read-only-select {\n    overflow: auto;\n}\n.read-only-select .selection {\n    overflow: hidden;\n    width:100%;\n    text-align: left;\n}\n\n/** people select */\n\n.people-select {\n    overflow: auto;\n    max-width: 300px;\n}\n\n.popover .people-select {\n    font-size: 13px;\n}\n\n.popover .people-select .simple-list {\n    height: 180px;\n    overflow: auto;\n    border-bottom: 1px solid #eeeeee;\n}\n\n.people-select-link {\n    color: #428bca;\n    cursor: pointer;\n}\n\n/** date select */\n\n.form-field {\n    overflow: auto;\n    max-width: 100%;\n}\n\n.popover .form-field {\n    font-size: 13px;\n}\n\n.popover .form-field .simple-list {\n    height: 180px;\n    overflow: auto;\n    border-bottom: 1px solid #eeeeee;\n}\n\n.form-field-link {\n    color: #428bca;\n    cursor: pointer;\n}\n\n.dropdown-menu.datepicker .calendar-grid .btn {\n    background-color: #ffffff;\n    color: #1a1a1a;\n    border: none;\n\n    -webkit-border-radius: 0;\n    -moz-border-radius: 0;\n    border-radius: 0;\n}\n\n.dropdown-menu.datepicker th {\n    background-color: #e8edf1;\n}\n.dropdown-menu.datepicker th .btn {\n    background-color: #e8edf1;\n    color: #1a1a1a;\n    border-color: #e8edf1;\n}\n\n.dropdown-menu.datepicker th .btn:hover, .dropdown-menu.datepicker th .btn:focus {\n    color: #2980b9;\n}\n\n.dropdown-menu.datepicker .calendar-grid .btn:hover, .dropdown-menu.datepicker .calendar-grid .btn:focus {\n    background-color: #f8f8f9;\n    border: none;\n    color: #1a1a1a;\n}\n\n.dropdown-menu.datepicker .calendar-grid .btn-today, .dropdown-menu.datepicker .calendar-grid .btn-today:focus, .dropdown-menu.datepicker .calendar-grid .btn-today:hover {\n    background-color: #b8dde7;\n}\n\n.dropdown-menu.datepicker .calendar-grid .btn-primary, .dropdown-menu.datepicker .calendar-grid .btn-primary:hover, .dropdown-menu.datepicker .calendar-grid .btn-primary:focus {\n    background-color: #2980b9;\n    color: #ffffff;\n}\n\n.dropdown-menu.datepicker .custom-buttons .btn {\n    border-color: #ffffff;\n}\n\n.comments > li {\n    padding: 8px 6px;\n}\n\n.comments > li > .title {\n\n    color: #888888;\n    font-size: 13px;\n    margin: 0 0 3px 0;\n}\n\n.comments > li > .message {\n    text-align: left;\n    color: #3a3a3a;\n    padding-left: 3px;\n    word-wrap: break-word;\n}\n\n.comments > li > .message:before, .comments > li > .message:after {\n    font-style: italic;\n}\n\n.comments > li > .message:before {\n    content: open-quote;\n    padding-right: 2px;\n}\n\n.comments > li > .message:after {\n    content: close-quote;\n    padding-left: 2px;\n}\n\n\n.form-wrapper {\n    margin: 10px 0 20px 0;\n}\n\n.form-wrapper .well-sm {\n    padding: 6px 9px;\n}\n\n.checklist.simple-list .user-picture {\n    margin-top: 2px;\n    width: 32px;\n    height: 32px;\n    background-size: 32px 32px;\n    line-height: 32px;\n    font-size: 15px;\n}\n\n.checklist.simple-list > li {\n    cursor: pointer;\n}\n\n.diagram-popup-wrapper {\n    min-width: 1000px;\n    max-width: 1400px;\n    min-height: 300px;\n    z-index: 1005;\n}\n\n.model-preview-wrapper {\n    width: 100%;\n    height:100%;\n    padding: 10px;\n    overflow: auto;\n}\n\n.upload-image-form {\n    margin: 0 20% 0 20%;\n    text-align: center;\n}\n\n.upload-image-dropbox {\n    background: #F8F8F8;\n    border: 5px dashed #DDD;\n    color: #8e8e8e;\n    text-align: center;\n    padding: 35px 0 35px 0;\n    margin: 20px 0 20px 0;\n}\n\n.upload-image-dropbox.dragover {\n    border: 5px dashed #55ae4d;\n    color: #55ae4d;\n}\n\n\n.google-drive-browse .simple-list, .alfresco-cloud-browse .simple-list {\n    position: relative;\n    max-height: 350px;\n    min-height: 350px;\n    height: 350px;\n    overflow: auto;\n}\n\n.alfresco-cloud-browse .col-xs-6 {\n    padding: 0 0 0 10px;\n}\n\n.alfresco-cloud-browse .col-xs-6:first-child {\n    padding-left: 0;\n}\n\n.crumbs {\n    margin: 5px 0px;\n    color: #666666;\n}\n\n.crumb {\n    color: #666666;\n    cursor: pointer;\n}\n\n.crumb i {\n    font-size: 80%;\n}\n\n.crumb:hover {\n    color: #2980b9;\n    text-decoration: underline;\n}\n.crumb:hover i {\n    color: #666666;\n}\n\n/** Apps */\n.apps-wrapper {\n    padding-top: 55px;\n    width: 1200px;\n    margin: 0 auto;\n}\n\n.app-wrapper {\n    float: left;\n    width: 300px;\n}\n\n.app {\n    margin: 10px 10px;\n    height: 200px;\n    border-left: 8px solid transparent;\n    overflow: hidden;\n    position: relative;\n    cursor: pointer;\n}\n\n.app .backdrop, .app .logo {\n    position: absolute;\n    text-shadow: none;\n\n    -webkit-transition: all 1s ease;\n    -moz-transition: all 1s ease;\n    -o-transition: all 1s ease;\n    transition: all 1s ease;\n\n    z-index: 4;\n}\n\n.app .backdrop {\n    font-size: 300px;\n    right: 50px;\n    top: -100px;\n}\n\n.app .logo {\n    font-size: 150px;\n    right: 20px;\n    top: 20px;\n}\n\n.app:hover .backdrop {\n    top: -55px;\n}\n\n.app:hover .logo {\n    right: -10px\n}\n\n.app h3 {\n    margin: 15px 10px 0px 10px;\n    position: relative;\n}\n\n.app-content {\n    color: #ffffff;\n    position: relative;\n    z-index: 5;\n}\n\n\n.app-content p {\n    display: none;\n    margin: 10px 0px 10px 10px;\n    padding: 10px 10px 0 0;\n    border-top: 1px solid #ffffff;\n    border-color: rgba(255,255,255, .1);\n}\n\n.app:hover .app-content p {\n    display: inherit;\n}\n\n.app .actions {\n    position: absolute;\n    top: 0px;\n    right: 0;\n    width: 40px;\n    height: 49px;\n    background-color: transparent;\n    line-height: 50px;\n    text-align: center;\n    z-index: 6;\n    visibility: hidden;\n    font-size: 16px;\n    color: #ffffff;\n    border-right: 2px solid transparent;\n    border-top: 2px solid transparent;\n}\n\n.app .selection-marker {\n    position: absolute;\n    top: 0px;\n    right: 5px;\n    width: 50px;\n    height: 48px;\n    font-size: 45px;\n    color: #ffffff;\n    z-index: 6;\n}\n\n.app:hover .actions {\n    visibility: visible;\n}\n.app .actions:hover {\n    background-color: #ffffff;\n    background-color: rgba(255,255,255, .7);\n    text-shadow: none;\n}\n\n.app .actions+.dropdown-menu {\n    background-color: #ffffff;\n    background-color: rgba(255,255,255, .8);\n    text-shadow: none;\n}\n.app-indicator {\n    position: relative;\n    padding-left: 20px;\n    color: #ffffff;\n}\n\n.app-indicator > span {\n    margin-right: 10px;\n    margin-left: 25px;\n    font-size: 16px;\n    padding-right: 15px;\n    white-space: nowrap;\n    text-overflow: ellipsis;\n}\n\n.app-indicator > .btn-group {\n    border-left: 1px solid #999999;\n}\n\n.app-indicator > i {\n    position: absolute;\n    left: 5px;\n    top:6px;\n    font-size: 28px;\n    color: #ffffff;\n    color: rgba(255, 255, 255, .5);\n}\n\n.popover.app-links-popover {\n    margin-top: 0;\n    padding: 5px;\n    width: 446px;\n    max-width: 446px;\n    overflow: auto;\n    max-height: calc(100vh - 40px);\n}\n.app-link-wrapper {\n    float: left;\n    display: inline-block;\n    min-height: 80px;\n    width: 90px;\n    margin: 5px;\n    text-align: center;\n    padding: 5px;\n    padding-top: 10px;\n    -webkit-transition: background-color 0.5s ease-out;\n    -moz-transition: background-color 0.5s ease-out;\n    -o-transition: background-color 0.5s ease-out;\n    transition: background-color 0.5s ease-out;\n    cursor: pointer;\n}\n.app-link-wrapper:hover,\n.app-link-wrapper:active {\n    background-color: #eee;\n}\n.app-link-name  {\n    word-wrap: break-word;\n    color: black;\n    opacity: 0.9;\n    margin-top: 5px;\n}\n.app-link-icon {\n    border-radius: 50%;\n    height: 50px;\n    width: 50px;\n    display: inline-block;\n}\n.app-link-icon > i {\n    color: white;\n    opacity: 0.5;\n    border-radius: 50%;\n    margin-bottom: 5px;\n    padding: 10px;\n    font-size: 30px;\n}\n.app-link-icon > span {\n    color: black;\n}\n\n.app-link-icon.theme-1,\n.app.theme-1 {\n    background-color: #269abc;\n}\n.app.theme-1 {\n    border-color: #269abc;\n    text-shadow: 1px 1px #168aac;\n}\n\n.app-indicator.theme-1 {\n    background: #269abc;\n    background: -moz-linear-gradient(left,  rgba(38,154,188,0) 0%, rgba(38,154,188,0.02) 1%, rgba(38,154,188,1) 30%, rgba(38,154,188,1) 100%); /* FF3.6+ */\n    background: -webkit-linear-gradient(left,  rgba(38,154,188,0) 0%,rgba(38,154,188,0.02) 1%,rgba(38,154,188,1) 30%,rgba(38,154,188,1) 100%); /* Chrome10+,Safari5.1+ */\n    background: -ms-linear-gradient(left,  rgba(38,154,188,0) 0%,rgba(38,154,188,0.02) 1%,rgba(38,154,188,1) 30%,rgba(38,154,188,1) 100%); /* IE10+ */\n    background: linear-gradient(to right,  rgba(38,154,188,0) 0%,rgba(38,154,188,0.02) 1%,rgba(38,154,188,1) 30%,rgba(38,154,188,1) 100%); /* W3C */\n    filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#00269abc', endColorstr='#269abc',GradientType=1 ); /* IE6-9 */\n}\n\n.app-indicator.theme-1 > .btn-group {\n    border-color: #168aac;\n}\n\n.app-indicator.theme-1 > .btn-group .btn-default:hover, .app-indicator.theme-1 > .btn-group .btn-default:focus {\n    background-color: #168aac;\n}\n\n.app.theme-1  .actions+.dropdown-menu li:hover a {\n    background-color: #168aac;\n}\n\n.app.theme-1 .backdrop i {\n    color: #2a9ec0;\n}\n\n.app.theme-1 .logo i {\n    color: #168aac;\n}\n\n.active > .app.preview.theme-1, .app.theme-1:hover {\n    border-color: #168aac;\n}\n\n.app.theme-1 .actions:hover {\n    border-color: #269abc;\n    color: #269abc;\n}\n\n.app-link-icon.theme-2,\n.app.theme-2 {\n    background-color: #7da9b0;\n}\n.app.theme-2 {\n    border-color: #7da9b0;\n    text-shadow: 1px 1px #6d99a0;\n}\n\n.app-indicator.theme-2 {\n    background: #7da9b0;\n    background: -moz-linear-gradient(left,  rgba(125,169,176,0) 0%, rgba(125,169,176,0.02) 1%, rgba(125,169,176,1) 30%, rgba(125,169,176,1) 100%); /* FF3.6+ */\n    background: -webkit-linear-gradient(left,  rgba(125,169,176,0) 0%,rgba(125,169,176,0.02) 1%,rgba(125,169,176,1) 30%,rgba(125,169,176,1) 100%); /* Chrome10+,Safari5.1+ */\n    background: -ms-linear-gradient(left,  rgba(125,169,176,0) 0%,rgba(125,169,176,0.02) 1%,rgba(125,169,176,1) 30%,rgba(125,169,176,1) 100%); /* IE10+ */\n    background: linear-gradient(to right,  rgba(125,169,176,0) 0%,rgba(125,169,176,0.02) 1%,rgba(125,169,176,1) 30%,rgba(125,169,176,1) 100%); /* W3C */\n    filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#00269abc', endColorstr='#269abc',GradientType=1 ); /* IE6-9 */\n}\n\n.app-indicator.theme-2 > .btn-group {\n    border-color: #6d99a0;\n}\n\n.app-indicator.theme-2 > .btn-group .btn-default:hover, .app-indicator.theme-2 > .btn-group .btn-default:focus {\n    background-color: #6d99a0;\n}\n\n.app.theme-2 .actions+.dropdown-menu li:hover a {\n    background-color: #6d99a0;\n}\n\n.app.theme-2 .backdrop i {\n    color: #81adb4;\n}\n\n.app.theme-2 .logo i {\n    color: #6d99a0;\n}\n\n.active > .app.preview.theme-2, .app.theme-2:hover {\n    border-color: #6d99a0;\n}\n\n.app.theme-2 .actions:hover {\n    border-color: #7da9b0;\n    color: #7da9b0;\n}\n\n.app-link-icon.theme-3,\n.app.theme-3 {\n    background-color: #7689ab;\n}\n.app.theme-3 {\n    border-color: #7689ab;\n    text-shadow: 1px 1px #66799b;\n}\n\n.app-indicator.theme-3 {\n    background: #7689ab;\n    background: -moz-linear-gradient(left,  rgba(118,137,171,0) 0%, rgba(118,137,171,0.02) 1%, rgba(118,137,171,1) 30%, rgba(118,137,171,1) 100%); /* FF3.6+ */\n    background: -webkit-linear-gradient(left,  rgba(118,137,171,0) 0%,rgba(118,137,171,0.02) 1%,rgba(118,137,171,1) 30%,rgba(118,137,171,1) 100%); /* Chrome10+,Safari5.1+ */\n    background: -ms-linear-gradient(left,  rgba(118,137,171,0) 0%,rgba(118,137,171,0.02) 1%,rgba(118,137,171,1) 30%,rgba(118,137,171,1) 100%); /* IE10+ */\n    background: linear-gradient(to right,  rgba(118,137,171,0) 0%,rgba(118,137,171,0.02) 1%,rgba(118,137,171,1) 30%,rgba(118,137,171,1) 100%); /* W3C */\n    filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#00269abc', endColorstr='#269abc',GradientType=1 ); /* IE6-9 */\n}\n\n.app-indicator.theme-3 > .btn-group {\n    border-color: #66799b;\n}\n\n.app-indicator.theme-3 > .btn-group .btn-default:hover, .app-indicator.theme-3 > .btn-group .btn-default:focus {\n    background-color: #66799b;\n}\n\n.app.theme-3 .actions+.dropdown-menu li:hover a {\n    background-color: #66799b;\n}\n\n.app.theme-3 .backdrop i {\n    color: #7a8daf;\n}\n\n.app.theme-3 .logo i {\n    color: #66799b;\n}\n\n.active > .app.preview.theme-3, .app.theme-3:hover {\n    border-color: #66799b;\n}\n\n.app.theme-3 .actions:hover {\n    border-color: #7689ab;\n    color: #7689ab;\n}\n\n.app-link-icon.theme-4,\n.app.theme-4 {\n    background-color: #c74e3e;\n}\n.app.theme-4 {\n    border-color: #c74e3e;\n    text-shadow: 1px 1px #b73e2e;\n}\n\n.app-indicator.theme-4 {\n    background: #c74e3e;\n    background: -moz-linear-gradient(left,  rgba(199,78,62,0) 0%, rgba(199,78,62,0.02) 1%, rgba(199,78,62,1) 30%, rgba(199,78,62,1) 100%); /* FF3.6+ */\n    background: -webkit-linear-gradient(left,  rgba(199,78,62,0) 0%,rgba(199,78,62,0.02) 1%,rgba(199,78,62,1) 30%,rgba(199,78,62,1) 100%); /* Chrome10+,Safari5.1+ */\n    background: -ms-linear-gradient(left,  rgba(199,78,62,0) 0%,rgba(199,78,62,0.02) 1%,rgba(199,78,62,1) 30%,rgba(199,78,62,1) 100%); /* IE10+ */\n    background: linear-gradient(to right,  rgba(199,78,62,0) 0%,rgba(199,78,62,0.02) 1%,rgba(199,78,62,1) 30%,rgba(199,78,62,1) 100%); /* W3C */\n    filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#00269abc', endColorstr='#269abc',GradientType=1 ); /* IE6-9 */\n}\n\n.app-indicator.theme-4 > .btn-group {\n    border-color: #b73e2e;\n}\n\n.app-indicator.theme-4 > .btn-group .btn-default:hover, .app-indicator.theme-4 > .btn-group .btn-default:focus {\n    background-color: #b73e2e;\n}\n\n.app.theme-4 .actions+.dropdown-menu li:hover a {\n    background-color: #b73e2e;\n}\n\n\n.app.theme-4 .backdrop i {\n    color: #cb5245;\n}\n\n.app.theme-4 .logo i {\n    color: #b73e2e;\n}\n\n.active > .app.preview.theme-4, .app.theme-4:hover {\n    border-color: #b73e2e;\n}\n\n.app.theme-4 .actions:hover {\n    border-color: #c74e3e;\n    color: #c74e3e;\n}\n\n.app-link-icon.theme-5,\n.app.theme-5 {\n    background-color: #fab96c;\n}\n.app.theme-5 {\n    border-color: #fab96c;\n    text-shadow: 1px 1px #eaa95c;\n}\n\n.app-indicator.theme-5 {\n    background: #fab96c;\n    background: -moz-linear-gradient(left,  rgba(250,185,108,0) 0%, rgba(250,185,108,0.02) 1%, rgba(250,185,108,1) 30%, rgba(250,185,108,1) 100%); /* FF3.6+ */\n    background: -webkit-linear-gradient(left,  rgba(250,185,108,0) 0%,rgba(250,185,108,0.02) 1%,rgba(250,185,108,1) 30%,rgba(250,185,108,1) 100%); /* Chrome10+,Safari5.1+ */\n    background: -ms-linear-gradient(left,  rgba(250,185,108,0) 0%,rgba(250,185,108,0.02) 1%,rgba(250,185,108,1) 30%,rgba(250,185,108,1) 100%); /* IE10+ */\n    background: linear-gradient(to right,  rgba(250,185,108,0) 0%,rgba(250,185,108,0.02) 1%,rgba(250,185,108,1) 30%,rgba(250,185,108,1) 100%); /* W3C */\n    filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#00269abc', endColorstr='#269abc',GradientType=1 ); /* IE6-9 */\n}\n\n.app-indicator.theme-5 > .btn-group {\n    border-color: #eaa95c;\n}\n\n.app-indicator.theme-5 > .btn-group .btn-default:hover, .app-indicator.theme-5 > .btn-group .btn-default:focus {\n    background-color: #eaa95c;\n}\n\n.app.theme-5 .actions+.dropdown-menu li:hover a {\n    background-color: #eaa95c;\n}\n\n.app.theme-5 .backdrop i {\n    color: #febd70;\n}\n\n.app.theme-5 .logo i {\n    color: #eaa95c;\n}\n\n.active > .app.preview.theme-5, .app.theme-5:hover {\n    border-color: #eaa95c;\n}\n\n.app.theme-5 .actions:hover {\n    border-color: #fab96c;\n    color: #fab96c;\n}\n\n.app-link-icon.theme-6,\n.app.theme-6 {\n    background-color: #759d4c;\n}\n.app.theme-6 {\n    border-color: #759d4c;\n    text-shadow: 1px 1px #658d3c;\n}\n\n.app-indicator.theme-6 {\n    background: #759d4c;\n    background: -moz-linear-gradient(left,  rgba(117,157,76,0) 0%, rgba(117,157,76,0.02) 1%, rgba(117,157,76,1) 30%, rgba(117,157,76,1) 100%); /* FF3.6+ */\n    background: -webkit-linear-gradient(left,  rgba(117,157,76,0) 0%,rgba(117,157,76,0.02) 1%,rgba(117,157,76,1) 30%,rgba(117,157,76,1) 100%); /* Chrome10+,Safari5.1+ */\n    background: -ms-linear-gradient(left,  rgba(117,157,76,0) 0%,rgba(117,157,76,0.02) 1%,rgba(117,157,76,1) 30%,rgba(117,157,76,1) 100%); /* IE10+ */\n    background: linear-gradient(to right,  rgba(117,157,76,0) 0%,rgba(117,157,76,0.02) 1%,rgba(117,157,76,1) 30%,rgba(117,157,76,1) 100%); /* W3C */\n    filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#00269abc', endColorstr='#269abc',GradientType=1 ); /* IE6-9 */\n}\n\n.app-indicator.theme-6 > .btn-group {\n    border-color: #658d3c;\n}\n\n.app-indicator.theme-6 > .btn-group .btn-default:hover, .app-indicator.theme-6 > .btn-group .btn-default:focus {\n    background-color: #658d3c;\n}\n\n.app.theme-6 .actions+.dropdown-menu li:hover a {\n    background-color: #658d3c;\n}\n\n.app.theme-6 .backdrop i {\n    color: #79a150;\n}\n\n.app.theme-6 .logo i {\n    color: #658d3c;\n}\n\n.active > .app.preview.theme-6, .app.theme-6:hover {\n    border-color: #658d3c;\n}\n\n.app.theme-6 .actions:hover {\n    border-color: #759d4c;\n    color: #759d4c;\n}\n\n.app-link-icon.theme-7,\n.app.theme-7 {\n    background-color: #b1b489;\n}\n.app.theme-7 {\n    border-color: #b1b489;\n    text-shadow: 1px 1px #a1a479;\n}\n\n.app-indicator.theme-7 {\n    background: #b1b489;\n    background: -moz-linear-gradient(left,  rgba(177,180,137,0) 0%, rgba(177,180,137,0.02) 1%, rgba(177,180,137,1) 30%, rgba(177,180,137,1) 100%); /* FF3.6+ */\n    background: -webkit-linear-gradient(left,  rgba(177,180,137,0) 0%,rgba(177,180,137,0.02) 1%,rgba(177,180,137,1) 30%,rgba(177,180,137,1) 100%); /* Chrome10+,Safari5.1+ */\n    background: -ms-linear-gradient(left,  rgba(177,180,137,0) 0%,rgba(177,180,137,0.02) 1%,rgba(177,180,137,1) 30%,rgba(177,180,137,1) 100%); /* IE10+ */\n    background: linear-gradient(to right,  rgba(177,180,137,0) 0%,rgba(177,180,137,0.02) 1%,rgba(177,180,137,1) 30%,rgba(177,180,137,1) 100%); /* W3C */\n    filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#00269abc', endColorstr='#269abc',GradientType=1 ); /* IE6-9 */\n}\n\n.app-indicator.theme-7 > .btn-group {\n    border-color: #a1a479;\n}\n\n.app-indicator.theme-7 > .btn-group .btn-default:hover, .app-indicator.theme-7 > .btn-group .btn-default:focus {\n    background-color: #a1a479;\n}\n\n.app.theme-7 .actions+.dropdown-menu li:hover a {\n    background-color: #a1a479;\n}\n\n.app.theme-7 .backdrop i {\n    color: #b5b98d;\n}\n\n.app.theme-7 .logo i {\n    color: #a1a479;\n}\n\n.active > .app.preview.theme-7, .app.theme-7:hover {\n    border-color: #a1a479;\n}\n\n.app.theme-7 .actions:hover {\n    border-color: #b1b489;\n    color: #b1b489;\n}\n\n.app-link-icon.theme-8,\n.app.theme-8 {\n    background-color: #a17299;\n}\n.app.theme-8 {\n    border-color: #a17299;\n    text-shadow: 1px 1px #916289;\n}\n\n.app-indicator.theme-8 {\n    background: #a17299;\n    background: -moz-linear-gradient(left,  rgba(161,114,153,0) 0%, rgba(161,114,153,0.02) 1%, rgba(161,114,153,1) 30%, rgba(161,114,153,1) 100%); /* FF3.6+ */\n    background: -webkit-linear-gradient(left,  rgba(161,114,153,0) 0%,rgba(161,114,153,0.02) 1%,rgba(161,114,153,1) 30%,rgba(161,114,153,1) 100%); /* Chrome10+,Safari5.1+ */\n    background: -ms-linear-gradient(left,  rgba(161,114,153,0) 0%,rgba(161,114,153,0.02) 1%,rgba(161,114,153,1) 30%,rgba(161,114,153,1) 100%); /* IE10+ */\n    background: linear-gradient(to right,  rgba(161,114,153,0) 0%,rgba(161,114,153,0.02) 1%,rgba(161,114,153,1) 30%,rgba(161,114,153,1) 100%); /* W3C */\n    filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#00269abc', endColorstr='#269abc',GradientType=1 ); /* IE6-9 */\n}\n\n.app-indicator.theme-8 > .btn-group {\n    border-color: #916289;\n}\n\n.app-indicator.theme-8 > .btn-group .btn-default:hover, .app-indicator.theme-8 > .btn-group .btn-default:focus {\n    background-color: #916289;\n}\n\n.app.theme-8 .actions+.dropdown-menu li:hover a {\n    background-color: #916289;\n}\n\n.app.theme-8 .backdrop i {\n    color: #a5769d;\n}\n\n.app.theme-8 .logo i {\n    color: #916289;\n}\n\n.active > .app.preview.theme-8, .app.theme-8:hover {\n    border-color: #916289;\n}\n\n.app.theme-8 .actions:hover {\n    border-color: #a17299;\n    color: #a17299;\n}\n\n.app-link-icon.theme-9,\n.app.theme-9 {\n    background-color: #696c67;\n}\n.app.theme-9 {\n    border-color: #696c67;\n    text-shadow: 1px 1px #595c57;\n}\n\n.app-indicator.theme-9 {\n    background: #696c67;\n    background: -moz-linear-gradient(left,  rgba(105,108,103,0) 0%, rgba(105,108,103,0.02) 1%, rgba(105,108,103,1) 30%, rgba(105,108,103,1) 100%); /* FF3.6+ */\n    background: -webkit-linear-gradient(left,  rgba(105,108,103,0) 0%,rgba(105,108,103,0.02) 1%,rgba(105,108,103,1) 30%,rgba(105,108,103,1) 100%); /* Chrome10+,Safari5.1+ */\n    background: -ms-linear-gradient(left,  rgba(105,108,103,0) 0%,rgba(105,108,103,0.02) 1%,rgba(105,108,103,1) 30%,rgba(105,108,103,1) 100%); /* IE10+ */\n    background: linear-gradient(to right,  rgba(105,108,103,0) 0%,rgba(105,108,103,0.02) 1%,rgba(105,108,103,1) 30%,rgba(105,108,103,1) 100%); /* W3C */\n    filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#00269abc', endColorstr='#269abc',GradientType=1 ); /* IE6-9 */\n}\n\n.app-indicator.theme-9 > .btn-group {\n    border-color: #595c57;\n}\n\n.app-indicator.theme-9 > .btn-group .btn-default:hover, .app-indicator.theme-9 > .btn-group .btn-default:focus {\n    background-color: #595c57;\n}\n\n.app.theme-9 .actions+.dropdown-menu li:hover a {\n    background-color: #595c57;\n}\n\n.app.theme-9 .backdrop i {\n    color: #6d706b;\n}\n\n.app.theme-9 .logo i {\n    color: #595c57;\n}\n\n.active > .app.preview.theme-9, .app.theme-9:hover {\n    border-color: #595c57;\n}\n\n.app.theme-9 .actions:hover {\n    border-color: #696c67;\n    color: #696c67;\n}\n\n.app-link-icon.theme-10,\n.app.theme-10 {\n    background-color: #cabb33;\n}\n.app.theme-10 {\n    border-color: #cabb33;\n    text-shadow: 1px 1px #baab23;\n}\n\n.app-indicator.theme-10 {\n    background: #cabb33;\n    background: -moz-linear-gradient(left,  rgba(202,187,51,0) 0%, rgba(202,187,51,0.02) 1%, rgba(202,187,51,1) 30%, rgba(202,187,51,1) 100%); /* FF3.6+ */\n    background: -webkit-linear-gradient(left,  rgba(202,187,51,0) 0%,rgba(202,187,51,0.02) 1%,rgba(202,187,51,1) 30%,rgba(202,187,51,1) 100%); /* Chrome10+,Safari5.1+ */\n    background: -ms-linear-gradient(left,  rgba(202,187,51,0) 0%,rgba(202,187,51,0.02) 1%,rgba(202,187,51,1) 30%,rgba(202,187,51,1) 100%); /* IE10+ */\n    background: linear-gradient(to right,  rgba(202,187,51,0) 0%,rgba(202,187,51,0.02) 1%,rgba(202,187,51,1) 30%,rgba(202,187,51,1) 100%); /* W3C */\n    filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#00269abc', endColorstr='#269abc',GradientType=1 ); /* IE6-9 */\n}\n\n.app-indicator.theme-10 > .btn-group {\n    border-color: #baab23;\n}\n\n.app-indicator.theme-10 > .btn-group .btn-default:hover, .app-indicator.theme-10 > .btn-group .btn-default:focus {\n    background-color: #baab23;\n}\n\n.app.theme-10 .actions+.dropdown-menu li:hover a {\n    background-color: #baab23;\n}\n\n.app.theme-10 .backdrop i {\n    color: #cebf37;\n}\n\n.app.theme-10 .logo i {\n    color: #baab23;\n}\n\n.active > .app.preview.theme-10, .app.theme-10:hover {\n    border-color: #baab23;\n}\n\n.app.theme-10 .actions:hover {\n    border-color: #cabb33;\n    color: #cabb33;\n}\n\n.create-app {\n    margin: 10px;\n    height: 200px;\n    padding: 5px;\n    background-color: #f8f8f7;\n}\n\n.create-app h3 {\n    font-size: 24px;\n    color: #666666;\n    line-height: 180px;\n    text-align: center;\n\n    -webkit-transition: font-size .2s ease;\n    -moz-transition: font-size .2s ease;\n    -o-transition: font-size .2s ease;\n    transition: font-size .2s ease;\n}\n\n.app.create-app:hover {\n    border-color: #eeeeee;\n}\n\n.app.create-app:hover h3{\n    font-size: 110px;\n}\n\n.app.create-app .fixed {\n    position: absolute;\n    top: 40px;\n    left: 0;\n    right: 0;\n    color: #666666;\n    visibility: hidden;\n    text-align: center;\n    font-size: 24px;\n}\n\n.app.create-app:hover .fixed {\n    visibility: visible;\n}\n\n.app.create-app .backdrop  {\n    color: #eeeeee;\n    top: -100px;\n}\n\n.app.create-app:hover .backdrop  {\n    top: -85px;\n}\n\n/** Landing logo (shared between apps) */\n\n.landing-logo {\n    line-height: 40px;\n    height: 40px;\n    width: 180px;\n    float: left;\n    cursor: default;\n}\n\n.landing-logo img {\n    max-height: 35px;\n    margin-top: -3px;\n    margin-left: 10px;\n}\n\n/** Password strength indicator */\n\n\nul#strength {\n    display:inline;\n    list-style:none;\n    margin:0;\n    margin-left:15px;\n    padding:0;\n    vertical-align:2px;\n}\n\nul#strength li {\n    background-color:#DDD;\n    border-radius:2px;\n    display:inline-block;\n    height:5px;\n    margin-right:1px;\n    width:20px;\n}\n\nul#strength li.pwd-very-weak {\n    background-color: #a02c2c;\n}\n\nul#strength li.pwd-weak {\n    background-color: #d45500;\n}\n\nul#strength li.pwd-good {\n    background-color: #ffcc00;\n}\n\nul#strength li.pwd-strong {\n    background-color: #aad400;\n}\n\nul#strength li.pwd-very-strong {\n    background-color: #71c837;\n}\n\nul#strength span {\n    font-weight: bold;\n    padding-left: 5px;\n}\n\nul#strength span.pwd-very-weak {\n    color: #a02c2c;\n}\n\nul#strength span.pwd-weak {\n    color: #d45500;\n}\n\nul#strength span.pwd-good {\n    color: #ffcc00;\n}\n\nul#strength span.pwd-strong {\n    color: #aad400;\n}\n\nul#strength span.pwd-very-strong {\n    color: #71c837;\n}\n\n\nul#strength > li:last-child {\n    margin:0;\n}\n\n.modal-body.content-preview-wrapper {\n    background-color: #404040;\n    padding: 0;\n}\n.modal-body.content-preview-wrapper .nothing-to-see {\n    background-color: #ffffff;\n    padding: 20px 0 0 0;\n    height: 480px;\n    text-align: center;\n    font-size: 15px;\n    color: #666666;\n}\n\n/**\n * Some modal windows need to have a scrollbar inside the modal window.\n * Use the following classes to do so.\n */\n\n.modal-body-with-overflow {\n    max-height: 500px;\n    overflow: auto;\n}\n\n.preview-image {\n    max-width: 100%;\n    max-height: 100%;\n    display: block;\n    margin-left: auto;\n    margin-right: auto;\n}\n\n@media (min-width: 1400px) {\n    .apps-wrapper {\n        width: 1400px;\n    }\n\n    .app-wrapper {\n        float: left;\n        width: 350px;\n    }\n}\n\n@media (max-width: 1200px) {\n    .apps-wrapper {\n        width: 900px;\n    }\n}\n\n\n/** Task details **/\n.summary-header {\n    margin-top: 10px;\n}\n.summary-header > div{\n    float: left;\n    margin-right: 15px;\n    border-left: 1px solid #cccccc;\n    padding-left: 15px;\n    min-height: 32px;\n}\n\n.summary-header.pack > div {\n    min-height: 32px;\n}\n\n.summary-header.pack  .title.title-lg {\n}\n\n.summary-header > div:first-child {\n    border-left: none;\n    padding-left: 0;\n}\n\n.summary-header .btn.btn-xs {\n    background-color: transparent;\n    border: 1px solid #bbbbbb;\n    color: #666666;\n    margin-top: 3px;\n}\n\n.summary-header .btn.btn-xs:hover, .summary-header .btn.btn-xs:active, .summary-header .btn.btn-xs:focus{\n    border: 1px solid #bbbbbb;\n    color: #666666;\n}\n\n.user-picture {\n    text-align: center;\n    font-size: 15px;\n    height: 32px;\n    width: 32px;\n    line-height: 32px;\n    padding: 0;\n    margin: 0 2px 0 0;\n    overflow: hidden;\n    color: #ffffff;\n    background: #2980b9 no-repeat center center;\n    background-size: 32px 32px;\n    cursor: pointer;\n    border: 1px solid transparent;\n}\n\n.summary-header .user-picture {\n    float: left;\n}\n\n.user-picture.no-picture {\n    border-color: #2980b9;\n}\n\n.user-picture span {\n    visibility: hidden;\n}\n\n.user-picture.more {\n    background-color: #6fc2d7;\n    color: #f6f6f6;\n}\n\n.user-picture.add {\n    background-color: #6fc2d7;\n    color: #f6f6f6;\n    font-size: 20px;\n    margin-left: 5px;\n}\n\n.user-picture:hover span, .user-picture.no-picture span, .user-picture.more span, .user-picture.add span {\n    visibility: visible;\n}\n\n.user-picture.no-picture:hover {\n    border-color: #32a3c0;\n}\n\n.summary-header .title {\n    margin-bottom: 2px;\n    font-size: 12px;\n    color: #666666;\n    cursor: pointer;\n}\n\n.summary-header .title.title-lg {\n    margin-top: 5px;\n    font-size: 14px;\n}\n\n.summary-header .title.title-lg > span {\n    font-size: 15px;\n}\n\n.summary-header .title > span {\n    font-size: 13px;\n    color: #555555;\n}\n\n.related-content {\n    float: left;\n    text-align: center;\n    height: 32px;\n    width: 32px;\n    line-height: 32px;\n    padding: 0;\n    margin: 0;\n    overflow: hidden;\n    cursor: pointer;\n}\n\n.related-content i.icon {\n    line-height: 32px;\n    font-size: 26px;\n}\n\n.related-content.more {\n    font-size: 15px;\n    color: #999999;\n    text-align: left;\n    padding: 0 5px;\n    width: auto;\n}\n\n.summary-header .title+.related-content {\n    margin-left: -4px;\n}\n\n\n.tabs {\n    list-style: none inside;\n    padding:0;\n    margin: 0;\n    border-bottom: 1px solid #bbbbbb;\n}\n\n.tabs > li {\n    display: block;\n    float: left;\n    margin-bottom: -1px;\n    border: 1px solid transparent;\n    border-bottom-color: #bbbbbb;\n}\n\n.tabs > li a {\n    display: block;\n    padding: 8px 40px;\n    text-decoration: none;\n    color: #888a85;\n    font-size: 16px;\n}\n.tabs > li a .badge {\n    min-width: 10px;\n    font-size: 12px;\n    margin-left: 4px;\n    padding: 2px 4px;\n    background-color: #5f8dd3;\n}\n\n.tabs > li a:hover {\n    text-decoration: none;\n    color: #5f8dd3;\n}\n\n.tabs > li.active {\n    border-color: #bbbbbb;\n    border-bottom-color: #ffffff;\n\n    -moz-border-radius-topleft: 5px;\n    -webkit-border-top-left-radius: 5px;\n    border-top-left-radius: 5px;\n    -moz-border-radius-topright: 5px;\n    -webkit-border-top-right-radius: 5px;\n    border-top-right-radius: 5px;\n\n}\n\n.tabs > li.active a {\n    color: #000000;\n    cursor: default;\n}\n\n.main-content .tabs {\n    padding: 0 0 0 10px;\n    margin-bottom: 5px;\n    margin-top: 8px;\n}\n\n.people-list.simple-list li {\n    line-height: 24px;\n    padding: 4px;\n}\n\n.people-list li .actions {\n    margin-top: 4px;\n}\n.simple-list .user-picture {\n    float: left;\n    font-size: 12px;\n    width: 24px;\n    height: 24px;\n    line-height: 24px;\n    background-size: 24px 24px;\n    margin-right: 6px;\n    border: none;\n}\n\n.content-group {\n    border-bottom: 1px dotted #eeeeee;\n    margin: 5px 0;\n}\n\n.content-group:last-child {\n    border: none;\n}\n\n/* Help */\n\n.help-container {\n    display: table;\n    height: 100%;\n    padding: 0 30px;\n    margin: 0px auto;\n}\n\n.help-container.fixed {\n    padding-top: 40px;\n}\n\n.help-container > div {\n    display: table-cell;\n    vertical-align: middle;\n    position: relative;\n}\n\n.help-text {\n    margin-top: 10px;\n    color: #636363;\n    background: #eee;\n    padding: 20px;\n    -webkit-border-radius: 10px;\n    -moz-border-radius: 10px;\n    border-radius: 10px;\n    max-width: 450px;\n    font-size: 14px;\n    position: relative;\n}\n\n.help-text.wide {\n    max-width: 550px;\n}\n\n.help-text .description {\n    margin-bottom: 25px;\n}\n\n.help-text .description:last-child {\n    margin-bottom: 0px;\n}\n\n.help-entry {\n    margin: 5px 0 5px 10px;\n    cursor: pointer;\n    padding: 5px;\n}\n\n.help-entry:hover, .help-entry.active {\n    background-color: #f6f6f7;\n}\n\n.help-entry.active {\n    padding: 10px;\n}\n\n.help-entry:hover > span {\n    color: #2980b9;\n}\n\n.help-entry.active:hover > span {\n    color: #636363;\n}\n\n.help-entry .pull-right > .btn {\n    border: none;\n}\n\n.help-entry .note, .action-note {\n    font-size: 12px;\n    color: #999999;\n    padding-left: 38px;\n}\n\n.help-entry:hover .note {\n    color: #999999;\n    text-decoration: none;\n}\n\n.action-note:hover {\n    text-decoration: underline;\n    cursor: pointer;\n}\n\n.help-entry > .glyphicon {\n    margin-right: 5px;\n}\n\n.help-entry > .icon {\n    margin-right: 5px;\n    font-size: 110%;\n}\n\n.help-text > a {\n    color: #636363;\n}\n\n.help-entry:hover > .glyphicon {\n    text-decoration: none;\n}\n\n.no-custom-apps .help-container {\n    float: left;\n    padding-left: 50px;\n}\n\n.content-list.simple-list li {\n    width: 50%;\n    float: left;\n    padding: 5px 10px;\n    margin-bottom: 10px;\n\n    white-space: nowrap;\n    overflow: hidden;\n    text-overflow: ellipsis;\n}\n\n.content-list.simple-list li .subtle {\n    white-space: nowrap;\n    overflow: hidden;\n    text-overflow: ellipsis;\n}\n\n.content-list.simple-list li:hover {\n    background-color: #ffffff;\n}\n\n.content-list.simple-list li .actions {\n    background-color: #ffffff;\n    border: 1px solid #eeeeee;\n    padding: 5px 4px 0 4px;\n    display: inline-block;\n    right: 0px;\n}\n\n.content-list.simple-list .subtle {\n    font-size: 12px;\n}\n.content-list.simple-list .nothing-to-see {\n    border: 1px solid #999999;\n    box-shadow: 1px 1px 2px #dddddd;\n    background-color: #ffffff;\n    width: 130px;\n    height: 155px;\n    padding: 50px 0 0 0;\n    text-align: center;\n}\n\n.content-list.simple-list .nothing-to-see .loading {\n    display: inline-block;\n    position: relative;\n    margin: 3px;\n    left: 0;\n}\n\n.frame {\n    white-space: nowrap;\n    text-align: left;\n    margin-bottom: 5px;\n    width: 100%;\n}\n\n.helper {\n    display: inline-block;\n}\n\n.frame img {\n    max-height: 155px;\n    padding: 5px;\n\n    border: 1px solid #999999;\n    box-shadow: 1px 1px 2px #dddddd;\n    background-color: #ffffff;\n}\n\n.content-list.simple-list li .frame .thumb-wrapper {\n    padding: 10px;\n    background-color: transparent;\n    display: inline-block;\n}\n.content-list.simple-list li:hover .frame .thumb-wrapper {\n    background-color: #eeeeee;\n}\n\n.form-wrapper .col-md-12 .content-list.simple-list li {\n    width: 25%;\n}\n\n.dynamicTableContainer {\n    /*min-height: 165px;*/\n}\n\n.dynamicTable {\n  border: 1px solid rgb(212,212,212) !important;\n  border-radius: 4px;\n  border-spacing: 2px;\n  display: block;\n  width: 100%;\n  height: 180px;\n  border-collapse: collapse;\n  margin-bottom: 5px;\n}\n\n.dynamicTable td, .dynamicTable tr {\n  border: 1px solid rgb(212,212,212) !important;\n  padding: 6px;\n}\n\n.dynamicTableContainer .control-buttons {\n  margin-bottom: 10px;\n}\n\n.edit-in-place-icon {\n    font-size: 20px;\n    color: darkgrey;\n    display: none;\n    margin-left: 5px;\n}\n.edit-in-place span {\n    cursor: pointer;\n}\n.edit-in-place:hover span {\n    display: inline-block;\n}\n.edit-in-place input {\n    display: none;\n}\n.edit-in-place.active span {\n    display: none;\n}\n.edit-in-place.active input {\n    display: inline-block;\n}\n\n.has-error .dynamicTable {\n  border: 1px solid #a94442 !important;\n}\n\n.noHeight {\n  height:auto;\n}\n\n"
  },
  {
    "path": "flowable-ui-web/modeler/styles/style-editor.css",
    "content": "/**\n Colors:\n\n  - Header: #333333\n  - Subheader: #e8edf1\n  - Subheader border: #a4acb9\n  - Highlight buttons/text: #2980b9\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: #2980b9;\n\tpadding-left: 5px;\n\tborder-left: 4px solid #2980b9;\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: #2980b9;\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;\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;\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\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    padding: 0px 20px 0px 20px;\n    background-color: #f9f9f9;\n}\n.content-canvas-wrapper li.form-field-wrapper {\n    list-style: none;\n}\n\n.content-canvas-wrapper ul li {\n    padding-bottom: 0.5rem;\n}\n.content-canvas-wrapper li.dndPlaceholder {\n    list-style: none;\n    background-color: #EFEFEF;\n    display: block;\n    width: 100%;\n    min-height: 70px;\n    z-index: 2;\n    margin-bottom: 0.5rem;\n}\n\n.content-canvas-wrapper .container-control li.dndPlaceholder {\n    min-height: calc(70px - 1.5rem);\n}\n\n.content-canvas-wrapper > ul > li.dndPlaceholder {\n    width: calc(100% - 10px);\n\n}\n\n.content-canvas-wrapper ul[dnd-list],\n.content-canvas-wrapper ul[dnd-list] > li {\n\tposition: relative;\n}\n\n.content-canvas-wrapper .form-group {\n    margin-bottom: 0; /* reset bootstrap margin */\n}\n\n.content-canvas-wrapper .container-control {\n    width: 100%;\n    table-layout: fixed;\n    /* border-spacing: 5px 0; */\n    border-collapse: separate;\n}\n\n.content-canvas-wrapper .container-control .input-group {\n    border-spacing: 0; /* restore bootstrap layout */\n}\n.content-canvas-wrapper .container-control-cell {\n    width: 50%;\n    vertical-align: top;\n    /* padding: 1rem; */\n}\n\n.content-canvas-wrapper .container-control tr > td {\n    /* padding-left: 0; */\n    min-height: 100%;\n    position: relative;\n}\n\n.content-canvas-wrapper .container-control-cell:nth-child(1) {\n    border-right: none;\n}\n\n.content-canvas-wrapper .container-control tr > td > ul {\n    min-height: 70px;\n    list-style: none;\n    padding: 0.5rem;\n}\n\n/*\n    make sure that there is something filling the entire cell to stop drag events form being fired to the main\n    droppable list and therefore start flickering\n*/\n\n.content-canvas-wrapper .container-control tr > td > ul::before {\n    content: \"\";\n    position: absolute;\n    width: 100%;\n    height: 100%;\n    background-color: #F9F9F8;\n    z-index: 0;\n    margin-left: -0.5rem;\n    margin-top: -0.5rem;\n}\n\n.content-canvas-wrapper .container-control tr > td > ul.dndDragover::before {\n    background-color: #EFEFEF;\n}\n\n.content-canvas-wrapper .dndDraggingSource\n{\n    display: none;\n}\n\n.content-canvas {\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 0;\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.content-canvas .canvas-element {\n\tmargin: 8px;\n\tpadding: 8px;\n\tposition:relative;\n\tz-index:0;\n\tborder: 1px dashed #ddd;\n\t/* padding-left: 0; */\n\tmin-height: 100%;\n}\n\n/* History */\ntable.history {\n\tmargin: 0;\n\tpadding: 0;\n}\n\n.subheader table.history {\n\tmin-width: 250px;\n}\n\ntable.history td {\n\tvertical-align: middle;\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\n}\n\ntable.history .version {\n\tfont-size: 30px;\n\tdisplay: inline-block;\n\tcolor: #2980b9;\n\tpadding: 5px 10px;\n\tvertical-align:middle;\n\tcolor: #2980b9;\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;\n}\n\n.comment {\n\tmargin: 10px 0px 20px 0px;\n\tfont-size: 12px;\n}\n\n.comment .date {\n\tcolor: #999999;\n\tfont-size: 12px;\n}\n\n.comment .author {\n\tcolor: #2980b9;\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;\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/** Steps builder */\n.steps-wrapper {\n    position: relative;\n    padding: 15px;\n    top: 0;\n    left: 0;\n    bottom: 1px;\n    right: 0;\n    height: auto;\n    background-color: transparent;\n}\n\n.steps-wrapper .popover.step-center {\n\tleft: 50% !important;\n\tmargin-left: -200px;\n    min-width: 400px;\n    margin-bottom: 20px;\n}\n\n.step {\n    background-color: #ffffff;\n    padding: 0px 0px 10px 0px;\n    border: 2px solid #1a1a1a;\n    -webkit-box-shadow: 0px 2px 2px 0px #999999;\n    -moz-box-shadow: 0px 2px 2px 0px #999999;\n    box-shadow: 0px 2px 2px 0px #999999;\n    font-size: 13px;\n    z-index: 2;\n}\n\n.has-line {\n\tbackground: transparent url('../images/line.png') repeat-y center top;\n}\n\n.step .form-group {\n    margin-bottom: 10px;\n}\n\n.steps-wrapper > div > .step {\n    margin: 0 auto 0 auto;\n    width: 600px;\n}\n\n.step-group {\n    border: 2px dotted #1a1a1a;\n    padding: 5px 0 5px 0;\n    background-color: #ffffff;\n    margin: 0 auto 0 auto;\n    -webkit-transition: width 0.2s ease-in-out;\n    -moz-transition: width 0.2s ease-in-out;\n    -o-transition: width 0.2s ease-in-out;\n    transition: width 0.2s ease-in-out;\n}\n\n.step-group.active {\n    position: relative;\n    width: 100%;\n}\n\n.step-group > .col-xs-6 {\n    background-color: transparent;\n}\n\n.step-container {\n\n}\n\n.step h4, .step-group h4 {\n    cursor: pointer;\n    margin: 10px 0 5px 10px;\n}\n\n.step h4 .icon, .step-group h4 .icon, .line-marker h4 .icon {\n    font-size: 70%;\n}\n\n.step > .actions, .step-group > .actions {\n    display: none;\n    clear: both;\n    float: right;\n    margin-top: 5px;\n}\n\n.step:hover > .actions, .step-group:hover > .actions {\n    display: inherit;\n}\n\n.step > .subtitle, .step-group > .subtitle {\n    margin-left: 25px;\n    line-height: 20px;\n    white-space: nowrap;\n    overflow: hidden;\n    text-overflow: ellipsis;\n}\n\n.step-type {\n    float: left;\n    margin-right: 5px;\n    font-size: 18px;\n    line-height: 20px;\n    color: #666666;\n}\n\n.step-placeholder-readonly {\n    top: 0;\n    margin: 6px auto;\n    -moz-border-radius: 10px;\n    -webkit-border-radius: 10px;\n    border-radius: 10px;\n    width: 20px;\n    height: 20px;\n    background-color: #ffffff;\n    border: 3px solid #999999;\n    color: #999999;\n    font-size: 16px;\n    line-height: 14px;\n    overflow: hidden;\n    text-align: center;\n\n    -webkit-transition: background-color 0.2s ease-in-out;\n    -moz-transition: background-color 0.2s ease-in-out;\n    -o-transition: background-color 0.2s ease-in-out;\n    transition: background-color 0.2s ease-in-out;\n}\n\n.step-placeholder {\n    top: 0;\n    margin: 6px auto;\n    -moz-border-radius: 10px;\n    -webkit-border-radius: 10px;\n    border-radius: 10px;\n    width: 20px;\n    height: 20px;\n    background-color: #ffffff;\n    border: 3px solid #999999;\n    color: #999999;\n    font-size: 16px;\n    line-height: 14px;\n    overflow: hidden;\n    text-align: center;\n    cursor: pointer;\n\n    -webkit-transition: background-color 0.2s ease-in-out;\n    -moz-transition: background-color 0.2s ease-in-out;\n    -o-transition: background-color 0.2s ease-in-out;\n    transition: background-color 0.2s ease-in-out;\n\n    z-index: 2;\n}\n\n.step-placeholder:before {\n    content: '+';\n}\n\n.step-placeholder:hover {\n    background-color: #ffffff;\n    margin: 1px auto;\n    width: 30px;\n    height: 30px;\n    line-height: 24px;\n    border-color: #5f8dd3;\n    color: #5f8dd3;\n    font-size: 20px;\n}\n\n\n.detail-wrapper {\n\tpadding: 0 10px;\n}\n\n.moving .step-placeholder {\n    background-color: #b7d897;\n    border-color: #72a83f;\n    color: #b7d897;\n}\n.moving .step-placeholder.no-move {\n    background-color: #ffffff;\n    border-color: #eeeeee;\n    color: #eeeeee;\n}\n\n.no-move.no-click {\n    pointer-events: none;\n    cursor: default;\n}\n\n.validation-error {\n    border-color: #ff0000;\n}\n\n.step .details, .step-group > .details {\n    border-top: 1px solid #bbbbbb;\n    margin: 10px 5px 10px 5px;\n    padding: 0 5px 0 5px;\n}\n\n.step .details .detail-group, .step-group > .details .detail-group{\n     margin: 10px 0 5px 0;\n     padding-top: 10px;\n     border-top: 1px dotted #f2f2f2;\n}\n\n.step .details .detail-group:first-child, .step-group > .details .detail-group:first-child {\n    margin-top: 0px;\n    border-top: none;\n}\n\n.step-group .detail-group.first, .step .detail-group.first {\n    border-top: none;\n    margin-top: 5px;\n}\n\n.detail-group .btn-group.pull-right, .line-marker .btn-group.pull-right {\n    margin: 0 0 5px 5px;\n}\n\n.detail-group .form-group .detail, .section .form-group .detail {\n    margin-top: 5px;\n    font-size: 13px;\n}\n\n.detail-group .form-group .detail .empty {\n    color: #666666;\n}\n\n.line-marker {\n    margin: 0 auto 0 auto;\n    cursor: pointer;\n    max-width: 300px;\n    padding: 5px 20px;\n    background-color: #ffffff;\n    -moz-border-radius: 16px;\n    -webkit-border-radius: 16px;\n    border-radius: 16px;\n    border: 3px solid #aaaaaa;\n    z-index: 2;\n\n    -webkit-transition: max-width .3s ease;\n    transition: max-width .3s ease;\n}\n\n.line-marker-only {\n    margin: 0 auto 0 auto;\n    max-width: 300px;\n    padding: 5px 20px;\n    background-color: #ffffff;\n    -moz-border-radius: 16px;\n    -webkit-border-radius: 16px;\n    border-radius: 16px;\n    border: 3px solid #aaaaaa;\n    z-index: 2;\n\n    -webkit-transition: max-width .3s ease;\n    transition: max-width .3s ease;\n}\n\n.line-marker-only .section {\n    min-height: 20px;\n    margin: 10px 0 5px 0;\n}\n\n.line-marker-only h4 {\n    text-align: center;\n    margin: 0;\n    font-size: 18px;\n    white-space: nowrap;\n    overflow: hidden;\n    text-overflow: ellipsis;\n}\n\n.line-marker-only h4 > span {\n    font-size: 14px;\n    color: #5f8dd3;\n    line-height: 18px;\n    padding-left: 5px;\n}\n\n.line-marker.expanded {\n    max-width: 600px;\n    width: 600px;\n    padding: 10px 5px;\n}\n\n.line-marker.expanded h4 {\n    margin-bottom: 10px;\n}\n\n.line-marker h4 > i {\n    visibility: hidden;\n}\n\n.line-marker h4:hover > i, .line-marker.expanded h4 > i {\n    visibility: visible;\n}\n\n.line-marker .section {\n    min-height: 20px;\n    margin: 10px 0 5px 0;\n}\n\n.step.moving, .step-group.moving {\n    border-color: #72a83f;\n    border-style: solid;\n}\n\n.step-group .line-marker {\n    max-width: 90%;\n}\n\n.line-marker h4 {\n    text-align: center;\n    margin: 0;\n    font-size: 18px;\n    white-space: nowrap;\n    overflow: hidden;\n    text-overflow: ellipsis;\n}\n\n.line-marker h4 > span {\n    font-size: 14px;\n    color: #5f8dd3;\n    line-height: 18px;\n    padding-left: 5px;\n}\n\n.step .details label, .line-marker .section label {\n    font-weight: normal;\n    padding-right: 10px;\n    padding-top: 5px;\n}\n\n.step-group  .tabs, .step .tabs {\n    margin-top: 15px;\n}\n\n.step-types > li > .icon {\n    padding-right: 5px;\n    color: #666666;\n}\n\n.step-types > li > .glyphicon-inline {\n    padding-right: 5px;\n    color: #666666;\n}\n\n.step-types li {\n    cursor: pointer;\n    font-size: 14px;\n    text-align: left;\n}\n\n.steps-wrapper h5 {\n    margin-top: 5px;\n    margin-left: 0px;\n    font-size: 16px;\n}\n\n/* Form builder */\n.palette-entry {\n    cursor: pointer;\n    padding: 5px 5px 5px 10px;\n}\n\n.palette-entry:hover {\n    background-color: #f2f2f2;\n}\n\n.palette-entry span {\n    padding-left: 10px;\n}\n\n.form-palette {\n    position: relative;\n    height: calc(100% - 60px);\n}\n\n.form-palette .col-sm-2 ul {\n    position: relative;\n    margin-bottom: 0;\n}\n\n.form-palette .col-sm-2 ul::before {\n    position: absolute;\n    top: 0;\n    right: -15px;\n    content: \"\";\n    height: 100%;\n    border-right: 1pt solid #c7cacd;\n}\n\n.form-canvas .empty {\n    border: 2px dashed #eeeeee;\n    padding: 15px;\n    color: #444444;\n}\n\n.form-canvas .popover {\n    width: 100%;\n}\n\n.form-canvas .checkbox.inline {\n    float: right;\n    width: 50%;\n    margin-top: 10px;\n}\n\n.form-canvas .checkbox.inline:last-child {\n    float: none;\n}\n\n\n\n.palette {\n    padding-bottom: 10px;\n}\n\n.palette:first-child {\n    margin-top: 150px;\n}\n\n.form-canvas td {\n    width: 50%;\n}\n\n.form-field {\n    position: relative;\n    overflow: visible;\n}\n\n.container-control .form-field {\n    /*padding: 10px;*/\n}\n\n.form-field > .actions {\n    position: absolute;\n    top: 0;\n    right: 5px;\n    display: none;\n    clear: both;\n\n    border: 1px solid #f2f2f2;\n    padding: 5px 5px 0px 5px;\n    background-color: #f2f2f2;\n    background-color: rgba(242, 242, 242, .8);\n    z-index: 3;\n}\n\n.form-field:hover > .actions {\n    display: inherit;\n}\n\n.editing .form-field:hover > .actions {\n    display: none;\n}\n\n\n.editing .form-field {\n    color: #aaaaaa;\n}\n.editing .form-field input {\n    border-color: #f2f2f2;\n    color: #aaaaaa;\n}\n\n.editing .form-field.editing {\n    border-color: #dddddd;\n    border-bottom-color: transparent;\n    color: #333333;\n}\n\n.editing .form-field.editing input {\n    color: #333333;\n    border-color: #cccccc;\n}\n\n.form-canvas-wrapper .inline-edit {\n    position: relative;\n    max-height: 0px;\n    border: 1px solid #cdcdcd;\n    border-top: none;\n    padding: 20px 15px;\n    overflow: hidden;\n    background-color: #fdfdfd;\n    margin: 0px -10px;\n\n    -webkit-transition: max-height .4s;\n    -moz-transition: max-height .4s;\n    -o-transition: max-height .4s;\n    transition: max-height .4s;\n\n    overflow: auto;\n}\n\n.inline-edit .col-xs-3, .inline-edit .col-xs-4, .inline-edit .col-xs-5, .inline-edit .col-xs-9 {\n    margin-bottom: 10px;\n}\n\n.inline-edit .section {\n    border-top: 1px dotted #eeeeee;\n    padding-top: 10px;\n}\n\n.inline-edit .section:first-child {\n    border-top: none;\n    padding-top: 0px;\n}\n\n.inline-edit .btn-group.pull-right {\n    margin: 0 15px 15px 0;\n}\n\n.arrow_box {\n    position: relative;\n    background: #ffffff;\n    border-top: 1px solid #cdcdcd;\n}\n.arrow_box:after, .arrow_box:before {\n    bottom: 100%;\n    left: 25%;\n    border: solid transparent;\n    content: \" \";\n    height: 0;\n    width: 0;\n    position: absolute;\n    pointer-events: none;\n}\n\n.arrow_box:after {\n    border-color: rgba(255, 255, 255, 0);\n    border-bottom-color: #ffffff;\n    border-width: 16px;\n    margin-left: -16px;\n}\n\n.second-column .form-field-edit .arrow_box:before, .second-column .form-field-edit .arrow_box:after {\n    left: 75%;\n}\n\n.arrow_box:before {\n    border-color: rgba(238, 238, 238, 0);\n    border-bottom-color: #cdcdcd;\n    border-width: 17px;\n    margin-left: -17px;\n}\n.form-canvas-wrapper .expand .inline-edit {\n    max-height: 500px;\n}\n.form-field-edit {\n    position: relative;\n    background-color: #ffffff;\n    margin: 0 -15px;\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/* Model preview */\n\n.model-preview-wrapper {\n\toverflow: auto;\n\twidth: auto;\n\theight: 100%;\n\tpadding: 5px;\n}\n\n.model-preview-wrapper>div {\n\tmargin-left:auto;\n\tmargin-right:auto;\n}\n\n/* Sharing */\n.sharing-info {\n\tmin-height: 250px;\n\tfont-size: 13px;\n}\n\n.sharing-info p, .sharing-info span {\n\tfont-size: 14px;\n}\n\n.sharing-info .no-results {\n\tfont-size: 15px;\n\tpadding-top: 100px;\n\ttext-align: center;\n}\n\n.sharing-info .sharing-list {\n\tmargin-top: 15px;\n\tline-height: 40px;\n}\n\n.sharing-info .sharing-list table {\n    margin-bottom: 0;\n    overflow: auto;\n}\n\n.sharing-list .sharing-entry {\n\tborder-bottom: 1px solid #a4acb9;\n}\n\n.sharing-list .sharing-entry .glyphicon {\n\tmargin-right: 10px;\n    cursor: pointer;\n}\n\n.sharing-list .sharing-entry .active-permission {\n     color: #2980b9;\n    font-weight: bold;\n}\n\n.sharing-list .sharing-entry .not-active-permission {\n    color: darkgrey;\n}\n\n.sharing-list-table-wrapper {\n    overflow: auto;\n    height: 300px;\n}\n\n\n/** Simple content box **/\n.simple-content-wrapper {\n\tmargin-top: 40px;\n}\n\n.simple-content-wrapper p {\n\tfont-size: 15px;\n}\n\n.simple-content-wrapper .loading-text {\n\tfont-size: 15px;\n\tline-height: 30px;\n}\n\n.simple-content-wrapper .alert {\n\tfont-size: 15px;\n\tmargin: 20px 0px;\n}\n\n.simple-content-wrapper .seperator {\n\twidth: 100%;\n\tcontent: ' ';\n\tmargin-top: 25px;\n\tmargin-bottom: 5px;\n\ttext-transform: uppercase;\n\tcolor: #cfcfcf;\n\tfont-size: 12px;\n}\n\n.simple-content-wrapper .seperator:first-child {\n\tmargin-top: 0px;\n}\n.simple-content-wrapper .seperator i.glyphicon {\n\tpadding-right: 5px;\n}\n\n.simple-content-wrapper p.subtle {\n\tfont-size: 13px;\n\tcolor: #afafaf;\n\tmargin:0;\n\ttext-align: right;\n}\n\n.simple-content-wrapper .btn-group.pull-right {\n\tmargin-left: 10px;\n}\n\n.simple-content-wrapper p.subtle a {\n\tfont-size: 13px;\n\tcolor: #afafaf;\n}\n\n.simple-content-wrapper p.subtle a:hover {\n\tcolor: #2980b9;\n}\n\n\n\n.simple-content-wrapper .form-group {\n\tmargin-bottom: 10px;\n}\n\n/** Re-captcha **/\n\n.recaptcha-image-wrapper {\n\tmargin: 5px 20px 0px 0px;\n\tfloat: left;\n\tborder-right: 1px solid rgb(204, 204, 204);\n\tpadding-right: 20px;\n\tmin-height: 100px;\n}\n#recaptcha_image img{\n\tmargin: 20px 5px;\n\tfloat: left;\n}\n\n\n.recaptcha-actions {\n\tmargin: 20px 5px 20px 5px;\n}\n\n.recaptcha-actions a {\n\tfont-size: 13px;\n}\n.recaptcha-actions i.glyphicon {\n\tpadding-right:5px;\n}\n\n.recaptcha-actions .subtle , .subtle > a{\n\tfont-size: 11px;\n\tcolor: rgb(204, 204, 204);\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;\n}\n/* Import process definition */\n\n.import-process-form {\n    margin: 0 20% 0 20%;\n    text-align: center;\n}\n\n.import-process-dropbox {\n    background: #F8F8F8;\n    border: 5px dashed #DDD;\n    color: #8e8e8e;\n    text-align: center;\n    padding: 35px 0 35px 0;\n    margin: 20px 0 20px 0;\n}\n\n.import-process-dropbox.dragover {\n    border: 5px dashed #55ae4d;\n    color: #55ae4d;\n}\n\n/* Bootstrap-Tour tweaks */\n\n.popover.tour {\n    min-width: 200px;\n    padding: 0 0 10px 0;\n}\n\n.popover-content {\n    font-size: 14px;\n}\n\n.row-no-gutter .col-xs-3.tour-activitiEditorTour-element {\n    z-index: 1101;\n}\n\n.row-no-gutter .col-xs-9.tour-activitiEditorTour-element {\n    z-index: 1101;\n}\n\n.popover .grid {\n\tmax-height: 350px;\n\toverflow: auto;\n\twidth: 550px;\n\tmargin: -5px -10px -5px -10px;\n\tpadding: 0 5px;\n}\n\n.popover .grid .item {\n\tfloat: left;\n\twidth: 14%;\n\tmargin: 0;\n\tpadding: 0;\n\tfont-size: 30px;\n\ttext-align: center;\n\tpadding: 1% 0;\n\tcursor: pointer;\n\tcolor: #555555;\n}\n\n.popover .grid.wide .item {\n\twidth: 20%;\n}\n\n\n.popover .grid .item.active {\n\tbackground-color: #f3f6f8;\n\tcolor: #2980b9;\n}\n\n.popover .grid .item:hover {\n\tbackground-color: #f3f6f8;\n}\n\n/*\n * Stencils\n */\n\n.stencil-title {\n    margin-top:10px;\n}\n\n.stencil-info-filter-dropdown {\n    margin-top: 10px;\n}\n\n.stencil-info-filter-dropdown button {\n    color: black;\n    background-color: white;\n    border-color: #e8edf1;\n}\n\n.stencil-info-filter-dropdown button:hover {\n    background-color: #2980b9;\n}\n\n.stencil-filter-selected {\n    color: #55ae4d;\n}\n\n.stencil-info {\n    margin-top:15px;\n    font-size: 16px;\n}\n.stencil-info-actions {\n    margin-top: 10px;\n    font-size: 14px;\n    padding-left: 10px;\n    border-left: 1px solid #e8edf1;\n}\n\n.stencil-info-actions i {\n    padding-right: 6px;\n}\n\n.stencil-info h2, .stencil-info-box h2, .stencil-info-container h2 {\n    margin-top:0;\n}\n\n.stencil-info-box {\n    border: 1px solid #e8edf1;\n    padding: 10px;\n}\n\n.stencil-info-items-box {\n    border-right: 1px solid #e8edf1;\n}\n\n.stencil-info-properties-box {\n    border-right: 1px solid #e8edf1;\n}\n\n.stencil-info-property-description {\n    font-size: 12px;\n}\n\n.stencil-info-item {\n    list-style: none;\n    list-style-position: outside;\n    margin: 0px 0px 5px 15px;\n    background-color: #ffffff;\n    font-family: Arial, Regular;\n    color: #323437;\n    cursor: pointer;\n}\n\n.stencil-info-item i {\n    font-size: 12px;\n    cursor: pointer;\n}\n\n.stencil-info-group {\n    margin-left: 5px;\n    padding-top: 5px;\n    padding-bottom: 5px;\n    cursor: pointer;\n}\n\n.stencil-info-group-selected, .stencil-info-groupItem-selected {\n    color: #2980b9;\n}\n\n.stencil-info-groupitem {\n    padding: 5px 5px 5px 25px;\n}\n\n.stencil-info-group:hover, .stencil-info-groupitem:hover, .restoreable-stencil-item:hover {\n    color: #2980b9;\n}\n\n.stencil-item-list-icon {\n    vertical-align: top;\n    margin: 2px 2px 0 0;\n}\n\n.stencil-info-item-icon {\n    float: right;\n    margin: 0 10px 0 10px;\n}\n\n.stencil-info-edit-properties {\n    margin-left: 10px;\n}\n\n.restoreable-stencil-item {\n    font-size: 16px;\n    cursor: pointer;\n}\n\n.selected-restoreable-stencil-item {\n    color: #55ae4d;\n}\n\n.reverteable-stencil-row {\n    cursor: pointer;\n}\n\n/* App definitions */\n\n.apps-wrapper {\n    padding-top: 55px;\n    width: 1200px;\n    margin: 0 auto;\n}\n\n.app-wrapper {\n    float: left;\n    width: 300px;\n}\n\n.app {\n    margin: 10px 10px;\n    height: 200px;\n    border-left: 8px solid transparent;\n    overflow: hidden;\n    position: relative;\n    cursor: pointer;\n}\n\n.app.app-swatch {\n    margin: 0 5px;\n    padding:0 20px;\n    height: 50px;\n    content: ' ';\n}\n\n.app.thumb {\n\theight: 75px;\n}\n.app .backdrop, .app .logo {\n    position: absolute;\n    text-shadow: none;\n\n    -webkit-transition: all 1s ease;\n    -moz-transition: all 1s ease;\n    -o-transition: all 1s ease;\n    transition: all 1s ease;\n\n    z-index: 4;\n}\n\n.app .backdrop {\n    font-size: 300px;\n    right: 50px;\n    top: -100px;\n}\n\n.app.thumb .backdrop {\n\tfont-size: 100px;\n    right: 20px;\n    top: -20px;\n}\n\n.app .logo {\n    font-size: 150px;\n    right: 20px;\n    top: 20px;\n}\n\n.app.thumb .logo {\n\tfont-size: 50px;\n    right: 5px;\n    top: 10px;\n}\n\n.app:hover .backdrop {\n    top: -55px;\n}\n\n.app.thumb:hover .backdrop {\n    top: 0px;\n}\n\n\n.app:hover .logo {\n    right: -10px\n}\n\n.app.thumb:hover .logo {\n    right: 0px\n}\n\n.app h3 {\n    margin: 15px 10px 0px 10px;\n    position: relative;\n}\n\n.app-content {\n    color: #ffffff;\n    position: relative;\n    z-index: 5;\n}\n\n.app-content p {\n    display: none;\n    margin: 10px 0px 10px 10px;\n    padding: 10px 10px 0 0;\n    border-top: 1px solid #ffffff;\n    border-color: rgba(255,255,255, .1);\n}\n\n\n.preview-wrapper {\n    padding: 0px;\n    border: 2px dotted #eeeeee;\n}\n\n.preview-wrapper > h3 {\n    font-size: 13px;\n    margin: 10px 10px 0px 10px;\n    color: #999999;\n    text-transform: uppercase;\n    text-align: center;\n\n}\n\n.app .app-actions {\n    padding: 5px;\n    height: 45px;\n    z-index: 10;\n    position: relative;\n}\n\n.app .app-actions .btn-group {\n    visibility: hidden;\n}\n\n.app:hover .app-actions .btn-group, .app.active .app-actions .btn-group {\n    visibility: inherit;\n    z-index: 10;\n}\n\n.btn-group.span {\n    width: 100%;\n}\n.btn-group.span .selection {\n    width: 100%;\n    text-align: left;\n}\n.field-type {\n    color: #888888;\n    font-size: 12px;\n}\n\n.form-field-edit .subtitle {\n    font-size: 14px;\n    padding-top: 6px;\n}\n\n.form-field-edit .dropdown-menu {\n    //position: relative;\n}\n\n.app-publish-error {\n    padding: 10px;\n    font-size:14px;\n}\n\n/** Stencil overview */\n\n.stencil-preview {\n    position: absolute;\n    left: 50%;\n    top: -30px;\n    margin-left: -100px;\n    font-size: 200px;\n    color: #9cc5d0;\n}\n\n.stencil-wrapper {\n  height: 100%;\n  position: fixed;\n  z-index: auto;\n  overflow: hidden;\n}\n\n.stencil-panel {\n  height: 100%;\n  overflow-y: auto;\n}\n\n.dynamicTable {\n  border: 1px solid rgb(212,212,212);\n  border-spacing: 2px;\n  dislay: block;\n  width: 100%;\n  height: 125px;\n  border: 1px;\n  border-collapse: collapse;\n}\n\n.dynamicTable td, .dynamicTable tr {\n  border: 1px solid rgb(212,212,212);\n  padding: 6px;\n}\n\n.modal-dialog.modal-maxheight {\n    max-height: 724px;\n    overflow-y: auto;\n}\n\n.dynamicTable-cellError {\n\tbackground-color: rgb(235, 204, 204) !important;\n\n}\n\n.rest-response.fail {\n\tborder-width: medium;\n\tborder-color: rgba(255, 0, 0, 0.45);\n}\n\n.rest-response.success {\n\tborder-width: medium;\n\tborder-color: rgba(7, 131, 7, 0.37);\n}\n\n.form-canvas input[disabled] {\n\tcursor:default;\n\tbackground-color:#fff;\n}\n\n/**\n *\n * Tooltips css selectively chosen from the bootstrap-additions.min.css from angular strap\n *\n * angular-strap\n * @version v2.0.5 - 2014-08-07\n * @link http://mgcrea.github.io/angular-strap\n * @author Olivier Louvignes (olivier@mg-crea.com)\n * @license MIT License, http://www.opensource.org/licenses/MIT\n */\n.tooltip.tooltip-info.top .tooltip-arrow,.tooltip.tooltip-info.top-left .tooltip-arrow,.tooltip.tooltip-info.top-right .tooltip-arrow{border-top-color:#d9edf7}.tooltip.tooltip-info.right .tooltip-arrow{border-right-color:#d9edf7}.tooltip.tooltip-info.bottom .tooltip-arrow,.tooltip.tooltip-info.bottom-left .tooltip-arrow,.tooltip.tooltip-info.bottom-right .tooltip-arrow{border-bottom-color:#d9edf7}.tooltip.tooltip-info.left .tooltip-arrow{border-left-color:#d9edf7}.tooltip.tooltip-info .tooltip-inner{background-color:#d9edf7;border-color:#bce8f1;color:#31708f}.tooltip.tooltip-info .tooltip-inner hr{border-top-color:#a6e1ec}.tooltip.tooltip-info .tooltip-inner .alert-link{color:#245269}.tooltip.tooltip-success.top .tooltip-arrow,.tooltip.tooltip-success.top-left .tooltip-arrow,.tooltip.tooltip-success.top-right .tooltip-arrow{border-top-color:#dff0d8}.tooltip.tooltip-success.right .tooltip-arrow{border-right-color:#dff0d8}.tooltip.tooltip-success.bottom .tooltip-arrow,.tooltip.tooltip-success.bottom-left .tooltip-arrow,.tooltip.tooltip-success.bottom-right .tooltip-arrow{border-bottom-color:#dff0d8}.tooltip.tooltip-success.left .tooltip-arrow{border-left-color:#dff0d8}.tooltip.tooltip-success .tooltip-inner{background-color:#dff0d8;border-color:#d6e9c6;color:#3c763d}.tooltip.tooltip-success .tooltip-inner hr{border-top-color:#c9e2b3}.tooltip.tooltip-success .tooltip-inner .alert-link{color:#2b542c}.tooltip.tooltip-danger.top .tooltip-arrow,.tooltip.tooltip-danger.top-left .tooltip-arrow,.tooltip.tooltip-danger.top-right .tooltip-arrow{border-top-color:#f2dede}.tooltip.tooltip-danger.right .tooltip-arrow{border-right-color:#f2dede}.tooltip.tooltip-danger.bottom .tooltip-arrow,.tooltip.tooltip-danger.bottom-left .tooltip-arrow,.tooltip.tooltip-danger.bottom-right .tooltip-arrow{border-bottom-color:#f2dede}.tooltip.tooltip-danger.left .tooltip-arrow{border-left-color:#f2dede}.tooltip.tooltip-danger .tooltip-inner{background-color:#f2dede;border-color:#ebccd1;color:#a94442}.tooltip.tooltip-danger .tooltip-inner hr{border-top-color:#e4b9c0}.tooltip.tooltip-danger .tooltip-inner .alert-link{color:#843534}.tooltip.top-left{margin-top:-3px;padding:5px 0}.tooltip.top-left .tooltip-arrow{bottom:0;margin-left:-5px;border-width:5px 5px 0;border-top-color:#000;left:10%}.tooltip.top-right{margin-top:-3px;padding:5px 0}.tooltip.top-right .tooltip-arrow{bottom:0;margin-left:-5px;border-width:5px 5px 0;border-top-color:#000;left:90%}.tooltip.bottom-left{margin-top:3px;padding:5px 0}.tooltip.bottom-left .tooltip-arrow{top:0;margin-left:-5px;border-width:0 5px 5px;border-bottom-color:#000;left:10%}.tooltip.bottom-right{margin-top:3px;padding:5px 0}.tooltip.bottom-right .tooltip-arrow{top:0;margin-left:-5px;border-width:0 5px 5px;border-bottom-color:#000;left:90%}\n"
  },
  {
    "path": "flowable-ui-web/modeler/views/app-definition-builder.html",
    "content": "\n<div class=\"subheader editor-toolbar\" id=\"editor-header\">\n    <div class=\"fixed-container\">\n        <div class=\"btn-group\">\n            <div class=\"btn-toolbar pull-left\" ng-controller=\"AppDefinitionToolbarController\" ng-cloak>\n                <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                    <i ng-switch-when=\"button\" ng-class=\"item.cssClass\" class=\"toolbar-button\" data-toggle=\"tooltip\" title=\"{{item.title | translate}}\"></i>\n                    <div ng-switch-when=\"separator\" ng-class=\"item.cssClass\"></div>\n                </button>\n              </div>\n            </div>\n            <div class=\"btn-group pull-right\" ng-show=\"!secondaryItems.length\">\n                <div class=\"btn-toolbar pull-right\" ng-controller=\"AppDefinitionToolbarController\">\n                <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                    <i ng-switch-when=\"button\" ng-class=\"item.cssClass\" class=\"toolbar-button\" data-toggle=\"tooltip\" title=\"{{item.title | translate}}\"></i>\n                    <div ng-switch-when=\"separator\" ng-class=\"item.cssClass\"></div>\n                </button>\n            </div>\n        </div>\n    </div>\n</div>\n<div class=\"container-fluid content\" ng-if=\"currentAppDefinition\" auto-height offset=\"40\">\n    <h2>{{'APP.DETAILS.TITLE' | translate:currentAppDefinition}}</h2>\n    <div class=\"content-canvas-wrapper\">\n        <div class=\"content-canvas\">\n            <div class=\"row\">\n                <div class=\"col-xs-4\">\n                    <div class=\"preview-wrapper active\">\n                        <h3>{{'APP.TITLE.PREVIEW' | translate}}</h3>\n                        <div class=\"app preview {{currentAppDefinition.definition.theme}}\">\n                            <div class=\"app-content\">\n                                <h3>{{currentAppDefinition.name}}</h3>\n                                <p>{{currentAppDefinition.description}}</p>\n                            </div>\n                            <div class=\"backdrop\">\n                                <i ng-show=\"!currentAppDefinition.definition.icon\" class=\"icon icon-choice\"></i>\n                                <i ng-show=\"currentAppDefinition.definition.icon\" class=\"glyphicon {{currentAppDefinition.definition.icon}}\"></i>\n                            </div>\n                            <div class=\"logo\">\n                                <i ng-show=\"!currentAppDefinition.definition.icon\" class=\"icon icon-choice\"></i>\n                                <i ng-show=\"currentAppDefinition.definition.icon\" class=\"glyphicon {{currentAppDefinition.definition.icon}}\"></i>\n                            </div>\n                        </div>\n                    </div>\n                </div>\n\n                <div class=\"col-xs-8\">\n                    <div class=\"form-group\">\n                        <label>{{'APP.ICON' | translate}}</label>\n                        <div id=\"toggle-icon-select\" class=\"selection\" ng-click=\"changeIcon($event)\">\n                            <i class=\"glyphicon {{currentAppDefinition.definition.icon}}\"></i> {{'APP.ACTION.SELECT-ICON' | translate}} <i class=\"icon icon-caret-down\"></i>\n                        </div>\n                    </div>\n                </div>\n                <div class=\"col-xs-8\">\n                    <div class=\"form-group\">\n                        <label>{{'APP.THEME' | translate}}</label>\n                        <div id=\"toggle-theme-select\" class=\"selection\" ng-click=\"changeTheme($event)\">\n                            <span class=\"app app-swatch {{currentAppDefinition.definition.theme}}\"></span> {{'APP.ACTION.SELECT-THEME' | translate}} <i class=\"icon icon-caret-down\"></i>\n                        </div>\n                    </div>\n                </div>\n                <div class=\"col-xs-8\">\n\t\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t\t<label for=\"groupAccessApp\">{{'APP.GROUPS-ACCESS' | translate}}</label>\n\t\t\t\t\t\t<input ng-disabled=\"model.loading\" type=\"text\" class=\"form-control\"\n\t\t\t\t\t\t\tid=\"groupAccessApp\" ng-model=\"currentAppDefinition.definition.groupsAccess\"\n\t\t\t\t\t\t\tcustom-keys enter-pressed=\"changeGroups($event)\" />\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"col-xs-8\">\n\t\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t\t<label for=\"userAccessApp\">{{'APP.USERS-ACCESS' | translate}}</label>\n\t\t\t\t\t\t<input ng-disabled=\"model.loading\" type=\"text\" class=\"form-control\"\n\t\t\t\t\t\t\tid=\"userAccessApp\" ng-model=\"currentAppDefinition.definition.usersAccess\"\n\t\t\t\t\t\t\tcustom-keys enter-pressed=\"changeUsers($event)\" />\n\t\t\t\t\t</div>\n\t\t\t\t</div>                 \n            </div>\n\n            <div class=\"row\">\n                <div class=\"col-xs-12\">\n                    <h3>{{'APP.DETAILS.MODELS-TITLE' | translate}}\n\n                    </h3>\n                    <div class=\"btn-group\">\n                        <button id=\"toggle-included-models\" class=\"btn btn-default\" ng-click=\"editIncludedModels($event)\" class=\"stencil-info-edit-properties\">\n                            {{'APP.ACTION.EDIT-MODELS' | translate}}\n                        </button>\n                    </div>\n                    <div class=\"no-results\" ng-show=\"!currentAppDefinition.definition.models.length && !currentAppDefinition.definition.cmmnModels.length\">\n                        {{'APP.DETAILS.NO-MODELS-SELECTED' | translate}}\n                    </div>\n                </div>\n            </div>\n            \n            <br/>\n            \n            <div class=\"row\">\n                <div class=\"tabs-wrapper\">\n\n                <div tab-control=\"tabs\" active-tab=\"appBuilder.activeTab\">\n                </div>\n                \n                <div class=\"col-xs-12 item-wrapper\" ng-show=\"appBuilder.activeTab == 'bpmn'\">\n                    <div class=\"item fadein\" ng-repeat=\"model in currentAppDefinition.definition.models\">\n                        <div class=\"item-box\" ng-style=\"{'background-image': 'url(\\'' + getModelThumbnailUrl(model.id) + '\\')'}\">\n                            <div class=\"actions\">\n                                <span class=\"badge\">v{{model.version}}</span>\n                            </div>\n                            <div class=\"details\">\n                                <h3 class=\"truncate\" title=\"{{model.name}}\">\n                                    {{model.name}}\n                                </h3>\n                                <p>{{model.description}}</p>\n                            </div>\n                        </div>\n                    </div>\n                </div>\n                \n                <div class=\"col-xs-12 item-wrapper\" ng-show=\"appBuilder.activeTab == 'cmmn'\">\n                    <div class=\"item fadein\" ng-repeat=\"model in currentAppDefinition.definition.cmmnModels\">\n                        <div class=\"item-box\" ng-style=\"{'background-image': 'url(\\'' + getModelThumbnailUrl(model.id) + '\\')'}\">\n                            <div class=\"actions\">\n                                <span class=\"badge\">v{{model.version}}</span>\n                            </div>\n                            <div class=\"details\">\n                                <h3 class=\"truncate\" title=\"{{model.name}}\">\n                                    {{model.name}}\n                                </h3>\n                                <p>{{model.description}}</p>\n                            </div>\n                        </div>\n                    </div>\n                </div>\n            </div>\n        </div>\n    </div>\n</div>\n"
  },
  {
    "path": "flowable-ui-web/modeler/views/app-definition.html",
    "content": "\n<div class=\"subheader\" ng-if=\"model.app\">\n\t<div class=\"fixed-container\">\n\t\t<div class=\"btn-group pull-right\">\n\t\t\t<button type=\"button\" class=\"btn btn-default\" ng-click=\"useAsNewVersion()\" ng-if=\"!model.app.latestVersion\">\n\t\t\t\t{{'APP.ACTION.USE-AS-NEW-VERSION' | translate}}\n\t\t\t</button>\n\t\t\t<a href=\"{{model.appExportUrl}}\" class=\"btn btn-default\" title=\"{{'APP.ACTION.EXPORT-ZIP' | translate}}\" ng-if=\"model.app.latestVersion\">\n                <i class=\"glyphicon glyphicon-save\"></i>\n            </a>\n            <a href=\"{{model.appBarExportUrl}}\" class=\"btn btn-default\" title=\"{{'APP.ACTION.EXPORT-BAR' | translate}}\" ng-if=\"model.app.latestVersion\">\n                <i class=\"glyphicon glyphicon-export\"></i>\n            </a>\n            <button type=\"button\" class=\"btn btn-default\" ng-click=\"importAppDefinition()\" ng-if=\"model.app.latestVersion\" translate>APPS-LIST.ACTION.IMPORT</button>\n\t\t\t<button type=\"button\" class=\"btn btn-default\" ng-click=\"publish()\" ng-if=\"model.app.latestVersion\">\n                {{'APP.ACTION.PUBLISH' | translate}}\n            </button>\n\t\t    <button type=\"button\" class=\"btn btn-default\" ng-click=\"openEditor()\" ng-if=\"model.app.latestVersion\">\n                <i class=\"glyphicon glyphicon-edit icon-and-label\"></i> {{'APP.ACTION.OPEN-IN-EDITOR' | translate}}\n            </button>\n\t\t</div>\n\t\t<div class=\"btn-group pull-right\">\n\t\t\t<button type=\"button\" class=\"btn btn-default\" ng-click=\"editApp()\" ng-disabled=\"!model.app.latestVersion\"\n\t\t\t\ttitle=\"{{'APP.ACTION.EDIT' | translate}}\">\n\t\t\t\t<i class=\"glyphicon glyphicon-pencil\"></i>\n\t\t\t</button>\n            <button type=\"button\" class=\"btn btn-default\" ng-click=\"duplicateApp()\" ng-disabled=\"!model.app.latestVersion\"\n\t\t\t\ttitle=\"{{'APP.ACTION.DUPLICATE' | translate}}\">\n                <i class=\"editor-icon editor-icon-copy\"></i>\n\t\t\t</button>\n\t\t\t<button type=\"button\" class=\"btn btn-default\" ng-click=\"deleteApp()\" title=\"{{'APP.ACTION.DELETE' | translate}}\"\n\t\t\t\tng-disabled=\"!model.app.latestVersion\">\n\t\t\t\t<i class=\"glyphicon glyphicon-trash\"></i>\n\t\t\t</button>\n\t\t</div>\t\t\n\t\t<div class=\"pull-right\">\n\t\t\t<a ng-click=\"returnToList()\" class=\"action\">&larr; {{'GENERAL.ACTION.RETURN-TO-LIST' | translate}}</a>\n\t\t</div>\n\t\t<h2><span class=\"version\">v{{model.app.version}}</span>{{model.app.name}}</h2>\n\t\t<div class=\"clearfix\">\n\t\t\t<div class=\"col-xs-4 details\">\n\t\t\t\t<span><i class=\"glyphicon glyphicon-user\"></i>{{'APP.DETAILS.CREATED-BY' | translate:model.app}}</span> \n\t\t\t\t<span><i class=\"glyphicon glyphicon-pencil\"></i>{{'APP.DETAILS.LAST-UPDATED-BY' | translate:model.app}}</span>\n\t\t\t</div>\n\t\t\t<div class=\"col-xs-8 details clearfix\">\n                <div class=\"related btn-group\">\n                    <button id=\"toggle-history\" type=\"button\" class=\"btn btn-subtle\" ng-click=\"toggleHistory($event)\"\n                        title=\"{{'APP.ACTION.EDIT' | translate}}\">\n                        {{'APP.DETAILS.HISTORY-TITLE' | translate}} <span class=\"counter\" ng-show=\"model.versions.data.length\">{{model.versions.data.length}}</span>\n                    </button>\n                </div>\n                <p ng-if=\"model.app.description\">\n                    {{model.app.description}}\n                </p>\n                <p ng-if=\"!model.app.description && model.app.latestVersion\" class=\"hint\">\n                    <a ng-click=\"editApp()\" class=\"subtle-select\">\n                        {{'APP.DETAILS.NO-DESCRIPTION' | translate}} <i class=\"glyphicon glyphicon-pencil\"></i>\n                    </a>\n                </p>\n            </div>\n\t\t</div>\n\t</div>\n</div>\n<div class=\"container-fluid content\" ng-if=\"model.app\" auto-height offset=\"40\">\n    <h2>{{'APP.DETAILS.TITLE' | translate:model.app}}</h2>\n    <div class=\"content-canvas-wrapper\">\n        <div class=\"content-canvas\">\n            <div class=\"row\" ng-if=\"model.appDefinition.definition.models && (model.appDefinition.definition.models.length > 0 || model.appDefinition.definition.cmmnModels.length > 0)\">\n                <div class=\"col-xs-4\">\n                    <div class=\"preview-wrapper active\">\n                        <h3>{{'APP.TITLE.PREVIEW' | translate}}</h3>\n                        <div class=\"app preview {{model.appDefinition.definition.theme}}\">\n                            <div class=\"app-content\">\n                                <h3>{{model.app.name}}</h3>\n                                <p>{{model.app.description}}</p>\n                            </div>\n                            <div class=\"backdrop\">\n                                <i ng-show=\"!model.appDefinition.definition.icon\" class=\"icon icon-choice\"></i>\n                                <i ng-show=\"model.appDefinition.definition.icon\" class=\"glyphicon {{model.appDefinition.definition.icon}}\"></i>\n                            </div>\n                            <div class=\"logo\">\n                                <i ng-show=\"!model.appDefinition.definition.icon\" class=\"icon icon-choice\"></i>\n                                <i ng-show=\"model.appDefinition.definition.icon\" class=\"glyphicon {{model.appDefinition.definition.icon}}\"></i>\n                            </div>\n                        </div>\n                    </div>\n                </div>\n            </div>\n\n            <div class=\"row\">\n                <div class=\"col-xs-12\">\n                    <h3>{{'APP.DETAILS.MODELS-TITLE' | translate}}\n\n                    </h3>\n                    <div class=\"no-results\" ng-show=\"!model.appDefinition.definition.models.length && !model.appDefinition.definition.cmmnModels.length\">\n                        {{'APP.DETAILS.NO-MODELS-SELECTED' | translate}}\n                    </div>\n                </div>\n            </div>\n            \n            <br/>\n            \n            <div class=\"row\">\n                \n                <div class=\"tabs-wrapper\">\n\n                <div tab-control=\"tabs\" active-tab=\"model.activeTab\">\n                </div>\n                \n                <div class=\"col-xs-12 item-wrapper\" ng-show=\"model.activeTab == 'bpmn'\">\n                    <div class=\"item fadein\" ng-repeat=\"model in model.appDefinition.definition.models\">\n                        <div class=\"item-box\" ng-style=\"{'background-image': 'url(\\'' + getModelThumbnailUrl(model.id) + '\\')'}\">\n                            <div class=\"actions\">\n                                <span class=\"badge\">v{{model.version}}</span>\n                            </div>\n                            <div class=\"details\">\n                                <h3 class=\"truncate\" title=\"{{model.name}}\">\n                                    {{model.name}}\n                                </h3>\n                                <p>{{model.description}}</p>\n                            </div>\n                        </div>\n                    </div>\n                </div>\n                \n                <div class=\"col-xs-12 item-wrapper\" ng-show=\"model.activeTab == 'cmmn'\">\n                    <div class=\"item fadein\" ng-repeat=\"model in model.appDefinition.definition.cmmnModels\">\n                        <div class=\"item-box\" ng-style=\"{'background-image': 'url(\\'' + getModelThumbnailUrl(model.id) + '\\')'}\">\n                            <div class=\"actions\">\n                                <span class=\"badge\">v{{model.version}}</span>\n                            </div>\n                            <div class=\"details\">\n                                <h3 class=\"truncate\" title=\"{{model.name}}\">\n                                    {{model.name}}\n                                </h3>\n                                <p>{{model.description}}</p>\n                            </div>\n                        </div>\n                    </div>\n                </div>\n            </div>\n        </div>\n    </div>\n</div>\n"
  },
  {
    "path": "flowable-ui-web/modeler/views/app-definitions.html",
    "content": "\n<div class=\"subheader\" id=\"list-header\">\n\t<div class=\"fixed-container\">\n\t    <div class=\"btn-group pull-right\">\n\t        <button type=\"button\" class=\"btn btn-default\" ng-click=\"createApp()\" translate>APPS-LIST.ACTION.CREATE</button>\n\t        <button type=\"button\" class=\"btn btn-default\" ng-click=\"importAppDefinition()\" translate>APPS-LIST.ACTION.IMPORT</button>\n\t    </div>\n\t    <h2>{{'APPS-LIST.TITLE' | translate}}</h2>\n\t</div>\n</div>\n<div class=\"container-fluid content\" auto-height offset=\"40\">\n        <div class=\"col-xs-2 filter-wrapper\">\n            <div class=\"input-group\">\n                <span class=\"input-group-addon\"> <i\n                    class=\"glyphicon glyphicon-search\"></i>\n                </span> <input type=\"text\" ng-model=\"model.pendingFilterText\" class=\"form-control\" ng-change=\"filterDelayed()\"\n                    placeholder=\"{{'APPS-LIST.SEARCH-PLACEHOLDER' | translate}}\">\n            </div>\n            <ul class=\"filter-list\">\n                <li ng-repeat=\"filter in model.filters\" ng-class=\"{'current' : filter.id == model.activeFilter.id}\">\n                    <a ng-click=\"activateFilter(filter)\">{{'APPS-LIST.FILTER.' + filter.labelKey | translate}}</a>\n                </li>\n            </ul>\n        </div>\n        \n        <div class=\"col-xs-10 item-wrapper\" id=\"list-items\">\n            <div class=\"dropdown-subtle pull-right\" ng-show=\"model.apps.size != 0\">\n                <div class=\"btn-group btn-group-sm\" activiti-fix-dropdown-bug>\n                    <button type=\"button\" class=\"btn btn-default dropdown-toggle\"\n                        data-toggle=\"dropdown\">{{'FORMS-LIST.SORT.' + model.activeSort.labelKey | translate}} <i class=\"caret\"></i></button>\n                    <ul class=\"dropdown-menu pull-right\">\n                        <li ng-repeat=\"sort in model.sorts\">\n                            <a ng-click=\"activateSort(sort)\">{{'APPS-LIST.SORT.' + sort.labelKey | translate}}</a>\n                        </li>\n                    </ul>\n                </div>\n            </div>\n            <div class=\"message clearfix\">\n                <div class=\"loading pull-left\" ng-show=\"model.loading\">\n                    <div class=\"l1\"></div><div class=\"l2\"></div><div class=\"l2\"></div>\n                </div>\n                <div ng-if=\"!model.loading\">\n                    <span ng-if=\"model.apps.size > 1\">{{'APPS-LIST.FILTER.' + model.activeFilter.labelKey + '-COUNT' | translate:model.apps}}</span>\n                    <span ng-if=\"model.apps.size == 1\">{{'APPS-LIST.FILTER.' + model.activeFilter.labelKey + '-ONE' | translate}}</span>\n                    <span ng-if=\"model.apps.size == 0 && (!model.filterText || model.filterText == '') &&  model.activeFilter.id != 'myApps'\">{{'APPS-LIST.FILTER.' + model.activeFilter.labelKey + '-EMPTY' | translate}}</span>\n                    <span ng-if=\"model.apps.size > 0 && model.filterText !='' && model.filterText !== undefined\">{{'APPS-LIST.FILTER.FILTER-TEXT' | translate:model}}</span>\n                    <span ng-if=\"model.apps.size == 0 && model.filterText !='' && model.filterText !== undefined\">{{'APPS-LIST.FILTER.FILTER-TEXT-EMPTY' | translate:model}}</span>\n\n                </div>\n            </div>\n\n            <div class=\"help-container fixed\" ng-if=\"model.apps.size == 0 && !model.loading && model.activeFilter.id == 'myApps' &&  (!model.filterText || model.filterText == '')\">\n                <div>\n                    <div class=\"help-text wide\">\n                        <div class=\"description\">\n                            {{'APPS-LIST.FILTER.NO-APPS' | translate}}\n                        </div>\n                        <div class=\"help-entry\" ng-click=\"createApp()\">\n                            <span class=\"glyphicon glyphicon-plus-sign\"></span>\n                            <span translate=\"APPS-LIST.FILTER.NO-APPS-CALL-TO-ACTION\"></span>\n                            <br>\n                            <span class=\"note\" translate=\"APPS-LIST.FILTER.NO-APPS-NOTE\"></span>\n                        </div>\n                    </div>\n                </div>\n            </div>\n\n            <div class=\"item fadein\" ng-repeat=\"app in model.apps.data\">\n                <div class=\"app {{app.appDefinition.theme ? app.appDefinition.theme : 'theme-1'}}\">\n                    <div class=\"app-actions\">\n                        <span class=\"badge\">v{{app.version}}</span>\n                        <div class=\"btn-group pull-right\">\n                            <button type=\"button\" ng-click=\"showAppDetails(app); $event.stopPropagation();\" class=\"btn btn-default\" title=\"{{'APP.ACTION.DETAILS' | translate}}\">\n                                <i class=\"glyphicon glyphicon-search\"></i>\n                            </button>\n                            <button type=\"button\" ng-click=\"editAppDetails(app); $event.stopPropagation();\" class=\"btn btn-default\" title=\"{{'APP.ACTION.OPEN-IN-EDITOR' | translate}}\">\n                                <i class=\"glyphicon glyphicon-edit\"></i>\n                            </button>\n                        </div>\n                    </div>\n                    <a ng-click=\"showAppDetails(app)\">\n                        <div class=\"app-content\">\n                            <h3>{{app.name}}</h3>\n                \n                            <p>{{app.description}}</p>\n                        </div>\n                        <div class=\"backdrop\">\n                            <i ng-show=\"!app.appDefinition.icon\" class=\"icon icon-choice\"></i>\n                            <i ng-show=\"app.appDefinition.icon\" class=\"glyphicon {{app.appDefinition.icon}}\"></i>\n                        </div>\n                        <div class=\"logo\">\n                            <i ng-show=\"!app.appDefinition.icon\" class=\"icon icon-choice\"></i>\n                            <i ng-show=\"app.appDefinition.icon\" class=\"glyphicon {{app.appDefinition.icon}}\"></i>\n                        </div>\n                    </a>\n                </div>\n            </div>\n            \n            <div class=\"show-more\" ng-if=\"model.apps.data.length < model.apps.total\">\n                <a>{{'APPS-LIST.ACTION.SHOW-MORE' | translate}}</a>\n            </div>\n        </div>\n</div>"
  },
  {
    "path": "flowable-ui-web/modeler/views/casemodel.html",
    "content": "\n<div class=\"subheader\" ng-if=\"model.caseModel\">\n\t<div class=\"fixed-container\">\n\t\t<div class=\"btn-group pull-right\">\n\t\t\t<button type=\"button\" class=\"btn btn-default\" ng-click=\"openEditor()\" ng-if=\"model.caseModel.latestVersion\">\n\t\t\t\t<i class=\"glyphicon glyphicon-edit icon-and-label\"></i> {{'CASE.ACTION.OPEN-IN-EDITOR' | translate}}\n\t\t\t</button>\n\t\t\t<button type=\"button\" class=\"btn btn-default\" ng-click=\"useAsNewVersion()\" ng-if=\"!model.caseModel.latestVersion\">\n\t\t\t\t{{'CASE.ACTION.USE-AS-NEW-VERSION' | translate}}\n\t\t\t</button>\n\t\t</div>\n\t\t<div class=\"btn-group pull-right\">\n\t        <a href=\"{{model.cmmnDownloadUrl}}\" class=\"btn btn-default\" title=\"{{'CASE.ACTION.EXPORT_CMMN' | translate}}\">\n\t            <i class=\"glyphicon glyphicon-save\"></i>\n\t        </a>\n\t\t</div>\n\t\t<div class=\"btn-group pull-right\">\n\t\t\t<button type=\"button\" class=\"btn btn-default\" ng-click=\"editCaseModel()\" ng-disabled=\"!model.caseModel.latestVersion\"\n\t\t\t\ttitle=\"{{'CASE.ACTION.EDIT' | translate}}\">\n\t\t\t\t<i class=\"glyphicon glyphicon-pencil\"></i>\n\t\t\t</button>\n            <button type=\"button\" class=\"btn btn-default\" ng-click=\"duplicateCaseModel()\" ng-disabled=\"!model.caseModel.latestVersion\"\n                    title=\"{{'CASE.ACTION.DUPLICATE' | translate}}\">\n                <i class=\"editor-icon editor-icon-copy\"></i>\n            </button>\n\t\t\t<button type=\"button\" class=\"btn btn-default\" ng-click=\"deleteCaseModel()\" title=\"{{'CASE.ACTION.DELETE' | translate}}\"\n\t\t\t\tng-disabled=\"!model.caseModel.latestVersion\">\n\t\t\t\t<i class=\"glyphicon glyphicon-trash\"></i>\n\t\t\t</button>\n\t\t</div>\t\t\n\t\t<div class=\"pull-right\">\n\t\t\t<a ng-click=\"returnToList()\" class=\"action\">&larr; {{'GENERAL.ACTION.RETURN-TO-LIST' | translate}}</a>\n\t\t</div>\n\t\t<h2><span class=\"version\">v{{model.caseModel.version}}</span>{{model.caseModel.name}}</h2>\n\t\t<div class=\"clearfix\">\n\t\t\t<div class=\"col-xs-4 details\">\n\t\t\t\t<span><i class=\"glyphicon glyphicon-user\"></i>{{'CASE.DETAILS.CREATED-BY' | translate:model.caseModel}}</span> \n\t\t\t\t<span><i class=\"glyphicon glyphicon-pencil\"></i>{{'CASE.DETAILS.LAST-UPDATED-BY' | translate:model.caseModel}}</span>\n\t\t\t</div>\n\t\t\t<div class=\"col-xs-8 details clearfix\">\n                <div class=\"related btn-group\">\n                    <button id=\"toggle-history\" type=\"button\" class=\"btn btn-subtle\" ng-click=\"toggleHistory($event)\"\n                        title=\"{{'CASE.ACTION.EDIT' | translate}}\">\n                        {{'CASE.DETAILS.HISTORY-TITLE' | translate}} <span class=\"counter\" ng-show=\"model.versions.data.length\">{{model.versions.data.length}}</span>\n                    </button>\n                </div>\n                <a ng-show=\"model.stencil\" ng-click=\"goToStencil()\" class=\"pull-right action\">{{model.stencil.name}}</a>\n                <p ng-if=\"model.caseModel.description\">\n                    {{model.caseModel.description}}\n                </p>\n                <p ng-if=\"!model.caseModel.description && model.caseModel.latestVersion\" class=\"hint\">\n                    <a ng-click=\"editCaseModel()\" class=\"subtle-select\">\n                        {{'CASE.DETAILS.NO-DESCRIPTION' | translate}} <i class=\"glyphicon glyphicon-pencil\"></i>\n                    </a>\n                </p>\n            </div>\n\t\t</div>\n\t</div>\n</div>\n<div class=\"content center-pane\" ng-if=\"model.caseModel\" auto-height offset=\"40\" >\n        \n\t<div class=\"model-preview-wrapper\" ng-if=\"model.caseModel.modelType && model.caseModel.modelType != 1\">\n\t   <div id=\"cmmnModel\"></div>\n\t</div>\n</div>\n"
  },
  {
    "path": "flowable-ui-web/modeler/views/casemodels.html",
    "content": "\n<div class=\"subheader\">\n\t<div class=\"fixed-container\">\n\t\t<div class=\"btn-group pull-right\">\n\t\t\t<button type=\"button\" class=\"btn btn-default\" ng-click=\"createCaseModel()\" translate>CASE-LIST.ACTION.CREATE</button>\n\t\t\t<button type=\"button\" class=\"btn btn-default\" ng-click=\"importCaseModel()\" translate>CASE-LIST.ACTION.IMPORT</button>\n\t\t</div>\n\t\t<h2>{{'CASE-LIST.TITLE' | translate}}</h2>\n\t</div>\n</div>\n<div class=\"container-fluid content\" auto-height offset=\"40\">\n\t\t<div class=\"col-xs-2 filter-wrapper\">\n\t\t\t<div class=\"input-group\">\n\t\t\t\t<span class=\"input-group-addon\"> <i\n\t\t\t\t\tclass=\"glyphicon glyphicon-search\"></i>\n\t\t\t\t</span> <input type=\"text\" ng-model=\"model.pendingFilterText\" class=\"form-control\" ng-change=\"filterDelayed()\"\n\t\t\t\t\tplaceholder=\"{{'CASE-LIST.SEARCH-PLACEHOLDER' | translate}}\">\n\t\t\t</div>\n\t\t\t<ul class=\"filter-list\">\n\t\t\t\t<li ng-repeat=\"filter in model.filters\" ng-class=\"{'current' : filter.id == model.activeFilter.id}\">\n\t\t\t\t\t<a ng-click=\"activateFilter(filter)\">{{'CASE-LIST.FILTER.' + filter.labelKey | translate}}</a>\n\t\t\t\t</li>\n\t\t\t</ul>\n\t\t</div>\n\n\t\t<div class=\"col-xs-10 item-wrapper\" id=\"list-items\">\n\t\t\t<div class=\"dropdown-subtle pull-right\">\n\t\t\t\t<div class=\"btn-group btn-group-sm\" activiti-fix-dropdown-bug>\n\t\t\t\t\t<button type=\"button\" class=\"btn btn-default dropdown-toggle\"\n\t\t\t\t\t\tdata-toggle=\"dropdown\">{{'CASE-LIST.SORT.' + model.activeSort.labelKey | translate}} <i class=\"caret\"></i></button>\n\t\t\t\t\t<ul class=\"dropdown-menu pull-right\">\n\t\t\t\t\t\t<li ng-repeat=\"sort in model.sorts\">\n\t\t\t\t\t\t\t<a ng-click=\"activateSort(sort)\">{{'CASE-LIST.SORT.' + sort.labelKey | translate}}</a>\n\t\t\t\t\t\t</li>\n\t\t\t\t\t</ul>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t<div class=\"message clearfix\">\n\t\t\t\t<div class=\"loading pull-left\" ng-show=\"model.loading\">\n\t\t\t\t\t<div class=\"l1\"></div><div class=\"l2\"></div><div class=\"l2\"></div>\n\t\t\t\t</div>\n\t\t\t\t<div ng-if=\"!model.loading\">\n\t\t\t\t\t<span ng-if=\"model.caseModels.size > 1\">{{'CASE-LIST.FILTER.' + model.activeFilter.labelKey + '-COUNT' | translate:model.caseModels}}</span>\n\t\t\t\t\t<span ng-if=\"model.caseModels.size == 1\">{{'CASE-LIST.FILTER.' + model.activeFilter.labelKey + '-ONE' | translate}}</span>\n\t\t\t\t\t<span ng-if=\"model.caseModels.size > 0 && model.filterText !='' && model.filterText !== undefined\">{{'CASE-LIST.FILTER.FILTER-TEXT' | translate:model}}</span>\n\t\t\t\t\t<span ng-if=\"model.caseModels.size == 0 && model.filterText !='' && model.filterText !== undefined\">{{'CASE-LIST.FILTER.FILTER-TEXT-EMPTY' | translate:model}}</span>\n\t\t\t\t</div>\n\t\t\t</div>\n\n            <div class=\"help-container fixed\" ng-if=\"model.caseModels.size == 0 && (!model.filterText || model.filterText == '')\">\n                <div>\n                    <div class=\"help-text wide\">\n                        <div class=\"description\">\n                            {{'CASE-LIST.FILTER.CASES-EMPTY' | translate}}\n                        </div>\n                        <div class=\"help-entry\" ng-click=\"createCaseModel()\">\n                            <span class=\"glyphicon glyphicon-plus-sign\"></span>\n                            <span translate=\"CASE-LIST.FILTER.CASES-CMMN-HINT\"></span>\n                            <br>\n                        </div>\n\t\t\t\t\t\t<div class=\"help-entry\" ng-click=\"importCaseModel()\">\n                            <span class=\"glyphicon glyphicon-plus-sign\"></span>\n                            <span translate=\"CASE-LIST.FILTER.CASES-CMMN-IMPORT-HINT\"></span>\n                            <br>\n                        </div>\n                    </div>\n                </div>\n            </div>\n\t\t\t<div class=\"item fadein\" ng-repeat=\"caseModel in model.caseModels.data track by $index\">\n\t\t\t\t<div class=\"item-box\" ng-style=\"{'background-image': 'url(\\'' + getModelThumbnailUrl(caseModel.id, imageVersion) + '\\')'}\" ng-click=\"showCaseModelDetails(caseModel);\">\n\t\t\t\t\t<div class=\"actions\">\n\t\t\t\t\t\t<span class=\"badge\">v{{caseModel.version}}</span>\n\t\t\t\t\t\t<div class=\"btn-group pull-right\">\n\t\t\t\t\t\t\t<button id=\"detailsButton\" type=\"button\" ng-click=\"showCaseModelDetails(caseModel); $event.stopPropagation();\" class=\"btn btn-default\" title=\"{{'CASE.ACTION.DETAILS' | translate}}\">\n\t\t\t\t\t\t\t\t<i class=\"glyphicon glyphicon-search\"></i>\n\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t<button id=\"editButton\" type=\"button\" ng-click=\"editCaseModelDetails(caseModel); $event.stopPropagation();\" class=\"btn btn-default\" title=\"{{'CASE.ACTION.OPEN-IN-EDITOR' | translate}}\">\n\t\t\t\t\t\t\t\t<i class=\"glyphicon glyphicon-edit\"></i>\n\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t\t<div class=\"details\">\n\t\t\t\t\t\t<h3 class=\"truncate\" title=\"{{caseModel.name}}\">\n\t\t\t\t\t\t\t{{caseModel.name}}\n\t\t\t\t\t\t</h3>\n\t\t\t\t\t\t<div class=\"basic-details truncate\">\n\t\t\t\t\t\t\t<span><i class=\"glyphicon glyphicon-user\"></i> {{caseModel.createdBy}}</span> <span title=\"{{caseModel.lastUpdated | dateformat:'LLLL'}}\"><i class=\"glyphicon glyphicon-pencil\"></i> {{caseModel.lastUpdated | dateformat}}</span>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<p>{{caseModel.description}}</p>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t</div>\n\n\t\t\t<div class=\"show-more\" ng-if=\"model.caseModels.data.length < model.caseModels.total\">\n\t\t\t\t<a>{{'CASE-LIST.ACTION.SHOW-MORE' | translate}}</a>\n\t\t\t</div>\n\t\t</div>\n</div>\n"
  },
  {
    "path": "flowable-ui-web/modeler/views/decision-table-editor.html",
    "content": "<div class=\"subheader editor-toolbar\" id=\"editor-header\">\n    <div class=\"fixed-container\">\n        <div class=\"btn-group\">\n            <div class=\"btn-toolbar pull-left\" ng-controller=\"DecisionTableToolbarController\" ng-cloak>\n                <button id=\"{{item.id}}\"dec\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 || (readOnly && item.disableOnReadonly)\"\n                        ng-click=\"toolbarButtonClicked($index)\">\n                    <i ng-switch-when=\"button\" ng-class=\"item.cssClass\" class=\"toolbar-button\" data-toggle=\"tooltip\"\n                       title=\"{{item.title | translate}}\"></i>\n                    <div ng-switch-when=\"separator\" ng-class=\"item.cssClass\"></div>\n                </button>\n            </div>\n        </div>\n        <div class=\"btn-group pull-right\" ng-show=\"!secondaryItems.length\">\n            <div class=\"btn-toolbar pull-right\" ng-controller=\"DecisionTableToolbarController\">\n                <button title=\"{{item.title | translate}}\" ng-repeat=\"item in secondaryItems\" ng-switch on=\"item.type\"\n                        class=\"btn btn-inverse\" ng-class=\"{'separator': item.type == 'separator'}\"\n                        ng-disabled=\"item.type == 'separator' || (readOnly && item.disableOnReadonly)\"\n                        ng-click=\"toolbarSecondaryButtonClicked($index)\" id=\"{{item.id}}\">\n                    <i ng-switch-when=\"button\" ng-class=\"item.cssClass\" class=\"toolbar-button\" data-toggle=\"tooltip\"\n                       title=\"{{item.title | translate}}\"></i>\n                    <div ng-switch-when=\"separator\" ng-class=\"item.cssClass\"></div>\n                </button>\n            </div>\n        </div>\n    </div>\n</div>\n\n<div class=\"container-fluid content decision-table\" auto-height offset=\"40\">\n\n    <br/>\n\n    <div class=\"row\">\n        <div class=\"col-xs-12 text-right\">\n            <div class=\"dropdown\">\n                <button class=\"btn btn-default dropdown-toggle\" type=\"button\" id=\"actionsMenu\" data-toggle=\"dropdown\" aria-haspopup=\"true\" aria-expanded=\"true\">\n                    {{\"DECISION-TABLE-EDITOR.BUTTON-ACTIONS-LABEL\" | translate}}\n                    <span class=\"caret\"></span>\n                </button>\n                <ul class=\"dropdown-menu dropdown-menu-right\" aria-labelledby=\"actionsMenu\">\n                    <li><a href ng-click=\"addRule()\">{{\"DECISION-TABLE-EDITOR.BUTTON-ADD-RULE-LABEL\" | translate}}</a></li>\n                    <li ng-if=\"model.selectedRow !== undefined && model.rulesData.length >= 2 && model.selectedRow >= 1\"><a href ng-click=\"moveRuleUpwards()\">{{\"DECISION-TABLE-EDITOR.BUTTON-MOVE-RULE-UPWARDS-LABEL\" | translate}}</a></li>\n                    <li ng-if=\"model.selectedRow !== undefined && model.selectedRow !== model.rulesData.length - 1\"><a href ng-click=\"moveRuleDownwards()\">{{\"DECISION-TABLE-EDITOR.BUTTON-MOVE-RULE-DOWNWARDS-LABEL\" | translate}}</a></li>\n                    <li class=\"danger\" ng-if=\"model.selectedRow !== undefined &&  model.rulesData.length > 1\"><a href ng-click=\"removeRule()\">{{\"DECISION-TABLE-EDITOR.BUTTON-REMOVE-RULE-LABEL\" | translate}}</a></li>\n                </ul>\n            </div>\n        </div>\n    </div>\n\n    <div class=\"decision-table-grid-wrapper\" id=\"decisionTableGrid\">\n        <div class=\"decision-name-container\">\n            <div class=\"decision-name\">\n                {{currentDecisionTable.name}}\n            </div>\n        </div>\n        <hot-table hot-auto-destroy\n                hot-id=\"decision-table-editor\"\n                settings=\"model.hotSettings\"\n                columns=\"model.columnDefs\"\n                row-headers=\"true\"\n                datarows=\"model.rulesData\"\n                auto-row-size=\"'true'\"\n                on-after-get-col-header=doAfterGetColHeader\n                on-modify-col-width=doAfterModifyColWidth\n                on-after-render=doAfterRender\n                on-after-on-cell-mouse-down=doAfterOnCellMouseDown\n                on-after-scroll-horizontally=doAfterScroll\n                on-after-scroll-vertically=doAfterScroll\n                current-row-class-name=\"'currentRow'\"\n                on-after-validate=doAfterValidate\n                height=\"500\">\n        </hot-table>\n    </div>\n</div>\n\n<script>\n    function triggerExpressionEditor(expressionType, expressionPos, newExpression) {\n        if (expressionType === 'input') {\n            extScope.openInputExpressionEditor(expressionPos, newExpression);\n        } else {\n            extScope.openOutputExpressionEditor(expressionPos, newExpression);\n        }\n    }\n\n    function triggerRemoveExpression(expressionType, expressionPos) {\n        if (expressionType === 'input') {\n            extScope.removeInputExpression(expressionPos);\n        } else {\n            extScope.removeOutputExpression(expressionPos);\n        }\n    }\n\n    function triggerHitPolicyEditor() {\n        extScope.openHitPolicyEditor();\n    }\n</script>\n"
  },
  {
    "path": "flowable-ui-web/modeler/views/decision-table.html",
    "content": "<div class=\"subheader\" ng-if=\"model.decisionTable\">\n    <div class=\"fixed-container\">\n        <div class=\"btn-group pull-right\" ng-if=\"!(currentKickstartModel)\">\n            <button type=\"button\" class=\"btn btn-default\" ng-click=\"openEditor()\"\n                    ng-if=\"model.decisionTable.latestVersion\">\n                <i class=\"glyphicon glyphicon-edit icon-and-label\"></i> {{'DECISION-TABLE.ACTION.OPEN-IN-EDITOR' |\n                translate}}\n            </button>\n            <button type=\"button\" class=\"btn btn-default\" ng-click=\"useAsNewVersion()\"\n                    ng-if=\"!model.decisionTable.latestVersion\">\n                {{'DECISION-TABLE.ACTION.USE-AS-NEW-VERSION' | translate}}\n            </button>\n        </div>\n\n        <div class=\"btn-group pull-right\" ng-if=\"!(currentKickstartModel)\">\n            <a href=\"{{model.decisionTableDownloadUrl}}\" class=\"btn btn-default\"\n               title=\"{{'DECISION-TABLE.ACTION.EXPORT' | translate}}\">\n                <i class=\"glyphicon glyphicon-save\"></i>\n            </a>\n        </div>\n\n        <div class=\"btn-group pull-right\" ng-if=\"!(currentKickstartModel)\">\n            <button type=\"button\" class=\"btn btn-default\" ng-click=\"editDecisionTable()\"\n                    ng-disabled=\"!model.decisionTable.latestVersion\"\n                    title=\"{{'DECISION-TABLE.ACTION.EDIT' | translate}}\">\n                <i class=\"glyphicon glyphicon-pencil\"></i>\n            </button>\n            <button type=\"button\" class=\"btn btn-default\" ng-click=\"duplicateDecisionTable()\"\n                    ng-disabled=\"!model.decisionTable.latestVersion\"\n                    title=\"{{'DECISION-TABLE.ACTION.DUPLICATE' | translate}}\">\n                <i class=\"editor-icon editor-icon-copy\"></i>\n            </button>\n            <button type=\"button\" class=\"btn btn-default\" ng-click=\"deleteDecisionTable()\"\n                    title=\"{{'DECISION-TABLE.ACTION.DELETE' | translate}}\"\n                    ng-disabled=\"!model.decisionTable.latestVersion\">\n                <i class=\"glyphicon glyphicon-trash\"></i>\n            </button>\n        </div>\n        <div class=\"pull-right\" ng-if=\"!(currentKickstartModel)\">\n            <a ng-click=\"returnToList()\" class=\"action\">&larr; {{'GENERAL.ACTION.RETURN-TO-LIST' | translate}}</a>\n        </div>\n\n        <h2><span class=\"version\">v{{model.decisionTable.version}}</span>{{model.decisionTable.name}}</h2>\n        <div class=\"clearfix\">\n            <div class=\"col-xs-4 details\">\n                <span><i class=\"glyphicon glyphicon-user\"></i><span translate=\"DECISION-TABLE.DETAILS.CREATED-BY\"\n                                                                    translate-values=\"model.decisionTable\"></span></span>\n                <span><i class=\"glyphicon glyphicon-pencil\"></i><span translate=\"DECISION-TABLE.DETAILS.LAST-UPDATED-BY\"\n                                                                      translate-values=\"model.decisionTable\"></span></span>\n            </div>\n            <div class=\"col-xs-8 details clearfix\">\n                <div class=\"related btn-group\">\n                    <button id=\"toggle-history\" ng-if=\"!(currentKickstartModel)\" type=\"button\" class=\"btn btn-subtle\"\n                            ng-click=\"toggleHistory($event)\"\n                            title=\"{{'DECISION-TABLE.ACTION.EDIT' | translate}}\">\n                        {{'DECISION-TABLE.DETAILS.HISTORY-TITLE' | translate}} <span class=\"counter\"\n                                                                                     ng-show=\"model.versions.data.length\">{{model.versions.data.length}}</span>\n                    </button>\n                </div>\n                <p ng-if=\"model.decisionTable.description\">\n                    {{model.decisionTable.description}}\n                </p>\n            </div>\n        </div>\n    </div>\n</div>\n<div class=\"container-fluid content decision-table read-only\" ng-if=\"model.decisionTable\" auto-height offset=\"40\">\n\n    <div class=\"decision-table-grid-wrapper\" id=\"decisionTableGrid\">\n        <div class=\"decision-name-container\">\n            <div class=\"decision-name\">\n                {{currentDecisionTable.name}}\n            </div>\n        </div>\n        <hot-table class=\"decision-table-editor\" hot-auto-destroy\n                   hot-id=\"read-only-decision-table-editor\"\n                   settings=\"model.hotSettings\"\n                   columns=\"model.columnDefs\"\n                   row-headers=\"true\"\n                   datarows=\"model.rulesData\"\n                   auto-row-size=\"'true'\"\n                   on-after-render=doAfterRender\n                   on-after-get-col-header=doAfterGetColHeader\n                   on-modify-col-width=doAfterModifyColWidth\n                   on-after-validate=doAfterValidate\n                   height=\"500\">\n        </hot-table>\n    </div>\n</div>\n\n<script>\n    function triggerExpressionEditor(expressionType, expressionPos, newExpression) {\n        if (expressionType === 'input') {\n            extScope.openInputExpressionEditor(expressionPos, newExpression);\n        } else {\n            extScope.openOutputExpressionEditor(expressionPos, newExpression);\n        }\n    }\n\n    function triggerHitPolicyEditor() {\n        extScope.openHitPolicyEditor();\n    }\n</script>"
  },
  {
    "path": "flowable-ui-web/modeler/views/decision-tables.html",
    "content": "<div class=\"subheader\" id=\"list-header\">\n\t<div class=\"fixed-container\">\n\t    <div class=\"btn-group pull-right\">\n\t        <button type=\"button\" class=\"btn btn-default\" ng-click=\"createDecisionTable()\" ng-disabled=\"readOnly\" translate>DECISION-TABLES-LIST.ACTION.CREATE</button>\n\t        <button type=\"button\" class=\"btn btn-default\" ng-click=\"importDecisionTable()\" ng-disabled=\"readOnly\" translate>DECISION-TABLES-LIST.ACTION.IMPORT</button>\n\t    </div>\n\t    <h2>{{'DECISION-TABLES-LIST.TITLE' | translate}}</h2>\n\t</div>\n</div>\n<div class=\"container-fluid content\" id=\"list-container\" auto-height offset=\"40\">\n        <div class=\"col-xs-2 filter-wrapper\">\n            <div class=\"input-group\">\n                <span class=\"input-group-addon\"> <i\n                    class=\"glyphicon glyphicon-search\"></i>\n                </span> <input type=\"text\" ng-model=\"model.pendingFilterText\" class=\"form-control\" ng-change=\"filterDelayed()\"\n                    placeholder=\"{{'DECISION-TABLES-LIST.SEARCH-PLACEHOLDER' | translate}}\">\n            </div>\n            <ul class=\"filter-list\">\n                <li ng-repeat=\"filter in model.filters\" ng-class=\"{'current' : filter.id == model.activeFilter.id}\">\n                    <a ng-click=\"activateFilter(filter)\">{{'DECISION-TABLES-LIST.FILTER.' + filter.labelKey | translate}}</a>\n                </li>\n            </ul>\n        </div>\n        \n        <div class=\"col-xs-10 item-wrapper\" id=\"list-items\">\n            <div class=\"dropdown-subtle pull-right\">\n                <div class=\"btn-group btn-group-sm\" activiti-fix-dropdown-bug>\n                    <button type=\"button\" class=\"btn btn-default dropdown-toggle\"\n                        data-toggle=\"dropdown\">{{'DECISION-TABLES-LIST.SORT.' + model.activeSort.labelKey | translate}} <i class=\"caret\"></i></button>\n                    <ul class=\"dropdown-menu pull-right\">\n                        <li ng-repeat=\"sort in model.sorts\">\n                            <a ng-click=\"activateSort(sort)\">{{'DECISION-TABLES-LIST.SORT.' + sort.labelKey | translate}}</a>\n                        </li>\n                    </ul>\n                </div>\n            </div>\n            <div class=\"message clearfix\">\n                <div class=\"loading pull-left\" ng-show=\"model.loading\">\n                    <div class=\"l1\"></div><div class=\"l2\"></div><div class=\"l2\"></div>\n                </div>\n                <div ng-if=\"!model.loading\">\n                    <span ng-if=\"model.decisionTables.size > 1\">{{'DECISION-TABLES-LIST.FILTER.' + model.activeFilter.labelKey + '-COUNT' | translate:model.decisionTables}}</span>\n                    <span ng-if=\"model.decisionTables.size == 1\">{{'DECISION-TABLES-LIST.FILTER.' + model.activeFilter.labelKey + '-ONE' | translate}}</span>\n                    <span ng-if=\"model.decisionTables.size == 0 && (!model.filterText || model.filterText == '')\">{{'DECISION-TABLES-LIST.FILTER.' + model.activeFilter.labelKey + '-EMPTY' | translate}}</span>\n                    <span ng-if=\"model.decisionTables.size > 0 && model.filterText !='' && model.filterText !== undefined\">{{'DECISION-TABLES-LIST.FILTER.FILTER-TEXT' | translate:model}}</span>\n                    <span ng-if=\"model.decisionTables.size == 0 && model.filterText !='' && model.filterText !== undefined\">{{'DECISION-TABLES-LIST.FILTER.FILTER-TEXT-EMPTY' | translate:model}}</span>\n                </div>\n            </div>\n            \n            <div class=\"create-inline\" ng-if=\"model.decisionTables.size == 0 && (!model.filterText || model.filterText == '')\">\n                <span>{{'DECISION-TABLES-LIST.FILTER.' + model.activeFilter.labelKey + '-EMPTY' | translate}}</span>\n                <span><button type=\"button\" class=\"btn btn-default\" ng-click=\"createDecisionTable()\" ng-disabled=\"readOnly\">\n                    <i class=\"glyphicon glyphicon-plus-sign\"></i>{{'DECISION-TABLES-LIST.ACTION.CREATE-INLINE' | translate}}\n                </button></span>\n            </div>\n            \n            <div class=\"item fadein\" ng-repeat=\"decisionTable in model.decisionTables.data track by $index\">\n                <div class=\"item-box\" ng-style=\"{'background-image': 'url(\\'' + getModelThumbnailUrl(decisionTable.id, imageVersion) + '\\')'}\" ng-click=\"showDecisionTableDetails(decisionTable);\">\n                    <div class=\"actions\">\n                        <span class=\"badge\">v{{decisionTable.version}}</span>\n                        <div class=\"btn-group pull-right\">\n                            <button type=\"button\" ng-click=\"showDecisionTableDetails(decisionTable); $event.stopPropagation();\" class=\"btn btn-default\" title=\"{{'DECISION-TABLE.ACTION.DETAILS' | translate}}\">\n                                <i class=\"glyphicon glyphicon-search\"></i>\n                            </button>\n                            <button type=\"button\" ng-click=\"editDecisionTableDetails(decisionTable); $event.stopPropagation();\" class=\"btn btn-default\" title=\"{{'DECISION-TABLE.ACTION.OPEN-IN-EDITOR' | translate}}\">\n                                <i class=\"glyphicon glyphicon-edit\"></i>\n                            </button>\n                        </div>\n                    </div>\n                    <div class=\"details\">\n                        <h3 class=\"truncate\" title=\"{{decisionTable.name}}\">\n                            {{decisionTable.name}}\n                        </h3>\n                        <div class=\"basic-details truncate\">\n                            <span><i class=\"glyphicon glyphicon-user\"></i> {{decisionTable.createdBy}}</span> <span title=\"{{decisionTable.lastUpdated | dateformat:'LLLL'}}\"><i class=\"glyphicon glyphicon-pencil\"></i> {{decisionTable.lastUpdated | dateformat}}</span>\n                        </div>\n                        <p>{{decisionTable.description}}</p>\n                    </div>\n                </div>\n            </div>\n            \n            <div class=\"show-more\" ng-if=\"model.decisionTables.data.length < model.decisionTables.total\">\n                <a>{{'DECISION-TABLES-LIST.ACTION.SHOW-MORE' | translate}}</a>\n            </div>\n        </div>\n</div>\n"
  },
  {
    "path": "flowable-ui-web/modeler/views/form-builder.html",
    "content": "<div class=\"subheader editor-toolbar\" id=\"editor-header\">\n    <div class=\"fixed-container\">\n        <div class=\"btn-group\">\n            <div class=\"btn-toolbar pull-left\" ng-controller=\"FormToolbarController\" ng-cloak>\n                <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                        \n                    <i ng-switch-when=\"button\" ng-class=\"item.cssClass\" class=\"toolbar-button\" data-toggle=\"tooltip\"\n                       title=\"{{item.title | translate}}\"></i>\n\n                    <div ng-switch-when=\"separator\" ng-class=\"item.cssClass\"></div>\n                </button>\n            </div>\n        </div>\n        <div class=\"btn-group pull-right\" ng-show=\"!secondaryItems.length\">\n            <div class=\"btn-toolbar pull-right\" ng-controller=\"FormToolbarController\">\n                <button title=\"{{item.title | translate}}\" ng-repeat=\"item in secondaryItems track by $index\"\n                        ng-switch on=\"item.type\" class=\"btn btn-inverse\"\n                        ng-class=\"{'separator': item.type == 'separator'}\"\n                        ng-disabled=\"item.type == 'separator'\" ng-click=\"toolbarSecondaryButtonClicked($index)\"\n                        id=\"{{item.id}}\">\n                    <i ng-switch-when=\"button\" ng-class=\"item.cssClass\" class=\"toolbar-button\" data-toggle=\"tooltip\"\n                       title=\"{{item.title | translate}}\"></i>\n\n                    <div ng-switch-when=\"separator\" ng-class=\"item.cssClass\"></div>\n                </button>\n            </div>\n        </div>\n    </div>\n</div>\n<div class=\"inset fixed-container form-palette\" ng-mousedown=\"cancelEditing($event)\">\n    <div class=\"col-sm-2\" auto-height style=\"overflow: auto;\">\n        <ul style=\"font-family: Arial, Regular;font-size: 17px;color: #323437;list-style: none;padding:0;\">\n            <li class=\"stencil-item\" ng-repeat=\"palletteElement in palletteElements\"\n                class=\"palette-entry\"\n                ng-model=\"draggedElement\"\n                id=\"{{palletteElement.type}}\"\n                title=\"{{palletteElement.title}}\"\n                dnd-draggable=\"palletteElement\"\n                dnd-type=\"'width-1'\">\n                <img width=\"32\" height=\"32\" ng-src=\"{{palletteElement.icon}}\"/>\n                {{palletteElement.title}}\n            </li>\n        </ul>\n    </div>\n    <div class=\"col-sm-10\" style=\"height:100%; overflow: auto;\">\n        <div class=\"center-pane\">\n            <div class=\"content\">\n                <div class=\"header clearfix\">\n                    <h2>{{currentForm.name}}</h2>\n\n                    <div class=\"pull-left badge-wrapper\">\n                        <span class=\"badge\">{{'FORM-BUILDER.VERSION' | translate:currentForm}}</span>\n                        <span>&nbsp;&nbsp;{{'FORM-BUILDER.LAST-UPDATED' | translate:currentForm}}</span>\n                    </div>\n                </div>\n                <div class=\"tabs-wrapper\">\n\n                    <div tab-control=\"tabs\" active-tab=\"formBuilder.activeTab\">\n                    </div>\n                    <div id=\"canvasSection\" class=\"content-canvas-wrapper\"\n                         ng-show=\"formBuilder.activeTab == 'design'\"\n                         ng-class=\"{'editing': editState.editing}\">\n\n                        <ul style=\"min-height:400px; width: 100%\"\n                            class=\"form-canvas content-canvas\"\n                            dnd-list=\"formItems\"\n                            dnd-allowed-types=\"['width-1']\"\n                            dnd-drop=\"onFieldDrop(item, formItems, event, index)\"\n                            dnd-after-drop=\"afterDropField(item,formItems,event)\">\n                            <li ng-repeat=\"field in formItems track by field._guid\" class=\"form-field-wrapper\"\n                                dnd-draggable=\"field\"\n                                dnd-effect-allowed=\"move\"\n                                dnd-type=\"'width-1'\"\n                                dnd-moved=\"onFieldMoved(field, formItems)\">\n                                <div draggable=\"true\" id=\"{{field._guid}}\" form-builder-element form-element=\"field\" edit-state=\"editState\"\n                                     drop=\"onFieldDrop(item, list, event, index)\" moved=\"onFieldMoved(item, list)\" class=\"canvas-element\">\n                                </div>\n                            </li>\n                        </ul>\n                    </div>\n\n                    <div ng-show=\"formBuilder.activeTab == 'outcome'\" class=\"detail-wrapper\">\n                        <div class=\"well\">\n                            <p>{{'FORM-BUILDER.OUTCOMES.DESCRIPTION' | translate}}</p>\n\n                            <div class=\"radio\">\n                                <label>\n                                    <input type=\"radio\" name=\"outcome\" ng-value=\"false\" ng-model=\"model.useOutcomes\">\n                                    {{'FORM-BUILDER.OUTCOMES.NO-OUTCOMES-OPTION' | translate}}\n                                </label>\n                            </div>\n                            <div class=\"radio\">\n                                <label>\n                                    <input type=\"radio\" name=\"outcome\" ng-value=\"true\" ng-model=\"model.useOutcomes\">\n                                    {{'FORM-BUILDER.OUTCOMES.OUTCOMES-OPTION' | translate}}\n                                </label>\n                            </div>\n                        </div>\n                        <div ng-if=\"model.useOutcomes\">\n                            <h4>{{'FORM-BUILDER.OUTCOMES.POSSIBLE-OUTCOMES' | translate}}</h4>\n\n                            <div class=\"clearfix\" ng-repeat=\"outcome in currentOutcomes track by $index\"\n                                 style=\"margin-bottom:5px\">\n                                <div class=\"col-xs-8\">\n                                    <input type=\"text\" class=\"form-control\"\n                                           placeholder=\"{{'FORM-BUILDER.OUTCOMES.NEW-OUTCOME-PLACEHOLDER' | translate}}\"\n                                           ng-model=\"outcome.name\">\n                                </div>\n                                <div class=\"col-xs-2\">\n                                    <button style=\"width:110px\" ng-show=\"$index > 0\" class=\"btn btn-default\"\n                                            ng-click=\"removeOutcome($index)\">{{'FORM-BUILDER.OUTCOMES.REMOVE' | translate}}\n                                    </button>\n                                </div>\n                                <div class=\"col-xs-2\">\n                                    <button style=\"width:110px\" ng-show=\"($index + 1) === currentOutcomes.length\"\n                                            class=\"btn btn-default\" ng-click=\"addOutcome()\">\n                                        {{'FORM-BUILDER.OUTCOMES.ADD' | translate}}\n                                    </button>\n                                </div>\n                            </div>\n                        </div>\n                    </div>\n                </div>\n            </div>\n        </div>\n    </div>\n</div>\n\n"
  },
  {
    "path": "flowable-ui-web/modeler/views/form.html",
    "content": "\n<div class=\"subheader\" ng-if=\"model.form\">\n\t<div class=\"fixed-container\">\n\t\t<div class=\"btn-group pull-right\">\n\t\t\t<button type=\"button\" class=\"btn btn-default\" ng-click=\"openEditor()\" ng-if=\"model.form.latestVersion\">\n\t\t\t\t<i class=\"glyphicon glyphicon-edit icon-and-label\"></i> {{'FORM.ACTION.OPEN-IN-EDITOR' | translate}}\n\t\t\t</button>\n\t\t\t<button type=\"button\" class=\"btn btn-default\" ng-click=\"useAsNewVersion()\" ng-if=\"!model.form.latestVersion\">\n\t\t\t\t{{'FORM.ACTION.USE-AS-NEW-VERSION' | translate}}\n\t\t\t</button>\n\t\t</div>\n\t\t<div class=\"btn-group pull-right\">\n\t\t\t<button type=\"button\" class=\"btn btn-default\" ng-click=\"editForm()\" ng-disabled=\"!model.form.latestVersion\"\n\t\t\t\ttitle=\"{{'FORM.ACTION.EDIT' | translate}}\">\n\t\t\t\t<i class=\"glyphicon glyphicon-pencil\"></i>\n\t\t\t</button>\n\t\t\t<button type=\"button\" class=\"btn btn-default\" ng-click=\"duplicateForm()\" ng-disabled=\"!model.form.latestVersion\"\n\t\t\t\t\ttitle=\"{{'FORM.ACTION.DUPLICATE' | translate}}\">\n\t\t\t\t<i class=\"editor-icon editor-icon-copy\"></i>\n\t\t\t</button>\n\t\t\t<button type=\"button\" class=\"btn btn-default\" ng-click=\"deleteForm()\" title=\"{{'FORM.ACTION.DELETE' | translate}}\"\n\t\t\t\tng-disabled=\"!model.form.latestVersion\">\n\t\t\t\t<i class=\"glyphicon glyphicon-trash\"></i>\n\t\t\t</button>\n\t\t</div>\t\t\n\t\t<div class=\"pull-right\">\n\t\t\t<a ng-click=\"returnToList()\" class=\"action\">&larr; {{'GENERAL.ACTION.RETURN-TO-LIST' | translate}}</a>\n\t\t</div>\n\t\t<h2><span class=\"version\">v{{model.form.version}}</span>{{model.form.name}}</h2>\n\t\t<div class=\"clearfix\">\n\t\t\t<div class=\"col-xs-4 details\">\n\t\t\t\t<span><i class=\"glyphicon glyphicon-user\"></i>{{'FORM.DETAILS.CREATED-BY' | translate:model.form}}</span> \n\t\t\t\t<span><i class=\"glyphicon glyphicon-pencil\"></i>{{'FORM.DETAILS.LAST-UPDATED-BY' | translate:model.form}}</span>\t\t\t\n\t\t\t</div>\n\t\t\t<div class=\"col-xs-8 details clearfix\">\n\t\t\t    <div class=\"related btn-group\">\n\t\t\t\t\t<button id=\"toggle-history\" type=\"button\" class=\"btn btn-subtle\" ng-click=\"toggleHistory($event)\"\n\t\t\t\t\t\ttitle=\"{{'FORM.ACTION.EDIT' | translate}}\">\n\t\t\t\t\t\t{{'FORM.DETAILS.HISTORY-TITLE' | translate}} <span class=\"counter\" ng-show=\"model.versions.data.length\">{{model.versions.data.length}}</span>\n\t\t\t\t\t</button>\n\t\t\t\t</div>\n\t\t\t\t<p ng-if=\"model.form.description\">\n\t\t\t\t\t{{model.form.description}}\n\t\t\t\t</p>\n\t\t\t</div>\n\t\t</div>\n\t</div>\n</div>\n<div class=\"container-fluid content\" ng-if=\"model.form\" auto-height offset=\"40\">\n\t<div class=\"center-pane\" style=\"overflow-x:hidden\">\n\t\t\n        <div class=\"content roweditor-canvas container-fluid\" ng-controller=\"FormReadonlyViewController\">\n            <div id=\"canvasSection\" class=\"content-canvas-wrapper\" ng-class=\"{'editing': editState.editing}\">\n\n                <ul style=\"min-height:400px; width: 100%\" class=\"form-canvas content-canvas\">\n                     \n                    <li ng-repeat=\"field in formItems track by field._guid\" class=\"form-field-wrapper\">\n                        <div form-builder-element form-element=\"field\" edit-state=\"editState\" form-mode=\"formMode\"></div>\n                    </li>\n                </ul>\n            </div>\n        </div>\n    </div>\n</div>\n"
  },
  {
    "path": "flowable-ui-web/modeler/views/forms.html",
    "content": "\n<div class=\"subheader\" id=\"list-header\">\n\t<div class=\"fixed-container\">\n\t    <div class=\"btn-group pull-right\">\n\t        <button type=\"button\" class=\"btn btn-default\" ng-click=\"createForm()\" translate>FORMS-LIST.ACTION.CREATE</button>\n\t    </div>\n\t    <h2>{{'FORMS-LIST.TITLE' | translate}}</h2>\n\t</div>\n</div>\n<div class=\"container-fluid content\" id=\"list-container\" auto-height offset=\"40\">\n        <div class=\"col-xs-2 filter-wrapper\">\n            <div class=\"input-group\">\n                <span class=\"input-group-addon\"> <i\n                    class=\"glyphicon glyphicon-search\"></i>\n                </span> <input type=\"text\" ng-model=\"model.pendingFilterText\" class=\"form-control\" ng-change=\"filterDelayed()\"\n                    placeholder=\"{{'FORMS-LIST.SEARCH-PLACEHOLDER' | translate}}\">\n            </div>\n            <ul class=\"filter-list\">\n                <li ng-repeat=\"filter in model.filters\" ng-class=\"{'current' : filter.id == model.activeFilter.id}\">\n                    <a ng-click=\"activateFilter(filter)\">{{'FORMS-LIST.FILTER.' + filter.labelKey | translate}}</a>\n                </li>\n            </ul>\n        </div>\n        \n        <div class=\"col-xs-10 item-wrapper\" id=\"list-items\">\n            <div class=\"dropdown-subtle pull-right\">\n                <div class=\"btn-group btn-group-sm\" activiti-fix-dropdown-bug>\n                    <button type=\"button\" class=\"btn btn-default dropdown-toggle\"\n                        data-toggle=\"dropdown\">{{'FORMS-LIST.SORT.' + model.activeSort.labelKey | translate}} <i class=\"caret\"></i></button>\n                    <ul class=\"dropdown-menu pull-right\">\n                        <li ng-repeat=\"sort in model.sorts\">\n                            <a ng-click=\"activateSort(sort)\">{{'FORMS-LIST.SORT.' + sort.labelKey | translate}}</a>\n                        </li>\n                    </ul>\n                </div>\n            </div>\n            <div class=\"message clearfix\">\n                <div class=\"loading pull-left\" ng-show=\"model.loading\">\n                    <div class=\"l1\"></div><div class=\"l2\"></div><div class=\"l2\"></div>\n                </div>\n                <div ng-if=\"!model.loading\">\n                    <span ng-if=\"model.forms.size > 1\">{{'FORMS-LIST.FILTER.' + model.activeFilter.labelKey + '-COUNT' | translate:model.forms}}</span>\n                    <span ng-if=\"model.forms.size == 1\">{{'FORMS-LIST.FILTER.' + model.activeFilter.labelKey + '-ONE' | translate}}</span>\n                    <span ng-if=\"model.forms.size == 0 && (!model.filterText || model.filterText == '')\">{{'FORMS-LIST.FILTER.' + model.activeFilter.labelKey + '-EMPTY' | translate}}</span>\n                    <span ng-if=\"model.forms.size > 0 && model.filterText !='' && model.filterText !== undefined\">{{'FORMS-LIST.FILTER.FILTER-TEXT' | translate:model}}</span>\n                    <span ng-if=\"model.forms.size == 0 && model.filterText !='' && model.filterText !== undefined\">{{'FORMS-LIST.FILTER.FILTER-TEXT-EMPTY' | translate:model}}</span>\n                </div>\n            </div>\n            \n            <div class=\"create-inline\" ng-if=\"model.forms.size == 0 && (!model.filterText || model.filterText == '')\">\n                <span>{{'FORMS-LIST.FILTER.' + model.activeFilter.labelKey + '-EMPTY' | translate}}</span>\n                <span><button type=\"button\" class=\"btn btn-default\" ng-click=\"createForm()\">\n                    <i class=\"glyphicon glyphicon-plus-sign\"></i>{{'FORMS-LIST.ACTION.CREATE-INLINE' | translate}}\n                </button></span>\n            </div>\n            \n            <div class=\"item fadein\" ng-repeat=\"form in model.forms.data track by $index\">\n                <div class=\"item-box\" ng-style=\"{'background-image': 'url(\\'' + getModelThumbnailUrl(form.id, imageVersion) + '\\')'}\" ng-click=\"showFormDetails(form);\">\n                    <div class=\"actions\">\n                        <span class=\"badge\">v{{form.version}}</span>\n                        <div class=\"btn-group pull-right\">\n                            <button type=\"button\" ng-click=\"showFormDetails(form); $event.stopPropagation();\" class=\"btn btn-default\" title=\"{{'FORM.ACTION.DETAILS' | translate}}\">\n                                <i class=\"glyphicon glyphicon-search\"></i>\n                            </button>\n                            <button type=\"button\" ng-click=\"editFormDetails(form); $event.stopPropagation();\" class=\"btn btn-default\" title=\"{{'FORM.ACTION.OPEN-IN-EDITOR' | translate}}\">\n                                <i class=\"glyphicon glyphicon-edit\"></i>\n                            </button>\n                        </div>\n                    </div>\n                    <div class=\"details\">\n                        <h3 class=\"truncate\" title=\"{{form.name}}\">\n                            {{form.name}}\n                        </h3>\n                        <div class=\"basic-details truncate\">\n                            <span><i class=\"glyphicon glyphicon-user\"></i> {{form.createdBy}}</span> <span title=\"{{form.lastUpdated | dateformat:'LLLL'}}\"><i class=\"glyphicon glyphicon-pencil\"></i> {{form.lastUpdated | dateformat}}</span>\n                        </div>\n                        <p>{{form.description}}</p>\n                    </div>\n                </div>\n            </div>\n            \n            <div class=\"show-more\" ng-if=\"model.forms.data.length < model.forms.total\">\n                <a>{{'FORMS-LIST.ACTION.SHOW-MORE' | translate}}</a>\n            </div>\n        </div>\n</div>\n"
  },
  {
    "path": "flowable-ui-web/modeler/views/popover/formfield-edit-popover.html",
    "content": "<div class=\"modal\">\n    <div class=\"modal-dialog modal-wide\">\n        <div class=\"modal-content\">\n            <div class=\"modal-header\">\n                <h2 ng-if=\"formElement.type != 'expression'\">{{'FORM-BUILDER.POPUP.EDIT-TITLE' | translate: formElement}}</h2>\n                <h2 ng-if=\"formElement.type == 'expression'\">{{'FORM-BUILDER.POPUP.EXPRESSION-TITLE' | translate}}</h2>\n            </div>\n            <div class=\"modal-body\">\n                <div class=\"center-pane\">\n                    <div class=\"content\">\n                        <div class=\"clearfix\">\n                            <ul class=\"tabs clearfix\">\n                                <li ng-repeat=\"tab in formTabs\" ng-class=\"{'active': tab.id == activeTab.id}\"\n                                    ng-if=\"!tab.show || tab.show.indexOf(formElement.type) >= 0\">\n                                    <a ng-click=\"tabClicked(tab)\">{{tab.title && (tab.title | translate) || tab.name}}</a>\n                                </li>\n                            </ul>\n                        </div>\n                    </div>\n                </div>\n\n                <div class=\"form-group\" ng-if=\"activeTab.id == 'general' && formElement.type != 'expression'\">\n                    <label translate=\"FORM-BUILDER.COMPONENT.LABEL\"></label>\n                    <input type=\"text\" class=\"form-control\" ng-model=\"formElement.name\"\n                           ng-change=\"formElementNameChanged(formElement)\" auto-focus>\n                </div>\n\n                <div class=\"clearfix\" ng-if=\"activeTab.id == 'general' && formElement.type != 'expression'\">\n                    <div class=\"form-group\">\n                        <div class=\"checkbox\">\n                            <label>\n                                <input type=\"checkbox\" ng-model=\"formElement.overrideId\">\n                                {{'FORM-BUILDER.COMPONENT.OVERRIDEID' | translate}}\n                            </label>\n                        </div>\n                    </div>\n\n                    <div class=\"form-group\">\n                        <label translate=\"FORM-BUILDER.COMPONENT.ID\"></label>\n                        <input type=\"text\" class=\"form-control\" ng-model=\"formElement.id\" ng-disabled=\"!formElement.overrideId\" editor-input-check>\n                    </div>\n\n                    <div ng-show=\"formElement.type !== 'expression' && formElement.type !== 'hyperlink' && formElement.type !== 'spacer' && formElement.type !== 'horizontal-line' && formElement.type !== 'headline' && formElement.type !== 'headline-with-line'\">\n                        <div class=\"row\">\n                           <div class=\"form-group col-md-2\">\n                               <div class=\"checkbox\">\n                                   <label>\n                                       <input type=\"checkbox\" ng-model=\"formElement.required\">\n                                       {{'FORM-BUILDER.COMPONENT.REQUIRED' | translate}}\n                                   </label>\n                               </div>\n                            </div>\n                            <div class=\"form-group col-md-10\">\n                               <div class=\"checkbox\">\n                                   <label>\n                                       <input type=\"checkbox\" ng-model=\"formElement.readOnly\">\n                                       {{'FORM-BUILDER.COMPONENT.READONLY' | translate}}\n                                   </label>\n                               </div>                               \n                           </div>\n                        </div>\n                    </div>\n\n                    <div ng-show=\"formElement.type === 'functional-group' || formElement.type === 'people' || formElement.type === 'dropdown' || formElement.type === 'date' || formElement.type === 'text' || formElement.type === 'password' || formElement.type === 'multi-line-text' || formElement.type === 'integer' || formElement.type === 'decimal'\">\n                        <label translate=\"FORM-BUILDER.COMPONENT.PLACEHOLDER\"></label>\n                        <input type=\"text\" class=\"form-control\" ng-model=\"formElement.placeholder\">\n                    </div>\n                </div>\n\n                <div ng-if=\"(activeTab.id == 'options') && (formElement.type === 'radio-buttons' || formElement.type === 'dropdown')\">\n\n                    <div class=\"form-group\">\n                        <label translate=\"FORM-BUILDER.COMPONENT.OPTIONS\"></label>\n\n                        <div>\n                            <div ng-repeat=\"option in formElement.options\" style=\"margin-bottom: 5px\" class=\"input-group\">\n                                <div class=\"input-group-addon\">\n                                    <input type=\"radio\" ng-disabled=\"optionsExpressionEnabled\" ng-model=\"formElement.value\" ng-value=\"option.name\">\n                                </div>\n\n                                <input id=\"firstDropdownOption\" type=\"text\" class=\"form-control\" ng-disabled=\"optionsExpressionEnabled\" ng-if=\"$index == 0\" ng-model=\"option.name\" style=\"background-color: #E6E6E6;\">\n                                <input type=\"text\" class=\"form-control\" ng-disabled=\"optionsExpressionEnabled\" ng-if=\"$index > 0\" ng-model=\"option.name\">\n\n                                <a class=\"input-group-addon\" ng-if=\"$index == 0\"\n                                   data-placement=\"left\" data-type=\"info\" data-animation=\"am-fade-and-scale\" bs-tooltip=\"'FORM-BUILDER.COMPONENT.DROPDOWN-EMPTY-VALUE-HELP'|translate\">\n                                    <i class=\"glyphicon glyphicon-question-sign\"></i>\n                                </a>\n\n                                <a class=\"input-group-addon\" ng-disabled=\"optionsExpressionEnabled\" ng-click=\"removeOption($index)\" ng-if=\"$index > 1\"><i class=\"icon icon-remove\"></i></a>\n                            </div>\n\n                            <div>\n                                <input type=\"text\" class=\"form-control\" placeholder=\"{{'FORM-BUILDER.COMPONENT.ADD-OPTION' | translate}}\" ng-model=\"newOption.name\"\n                                       ng-disabled=\"optionsExpressionEnabled\" ng-blur=\"confirmNewOption($event)\" ng-keydown=\"optionKeyDown($event)\">\n                            </div>\n                        </div>\n                    </div>\n\n                    <div class=\"form-group\">\n                        <div class=\"checkbox\">\n                            <label>\n                                <input type=\"checkbox\" ng-init=\"optionsExpressionEnabled = formElement.optionsExpression != null && formElement.optionsExpression != ''\" ng-model=\"optionsExpressionEnabled\" ng-change=\"optionsExpressionChanged($event)\">\n                                {{'FORM-BUILDER.COMPONENT.OPTIONS-EXPRESSION-ENABLED' | translate}}\n                            </label>\n                        </div>\n                    </div>\n                    \n                    <div class=\"form-group\">\n                        <label translate=\"FORM-BUILDER.COMPONENT.OPTIONS-EXPRESSION\"></label>\n                        <textarea rows=\"3\" ng-disabled=\"!optionsExpressionEnabled\" ng-model=\"formElement.optionsExpression\" class=\"form-control\" id=\"readonly-text-value\"></textarea>\n                        <div class=\"subtle\" translate=\"FORM-BUILDER.MESSAGE.OPTIONS-EXPRESSION-HELP\" style=\"padding: 5px 0 5px 1px;\"></div>\n                    </div>\n                    \n                </div>\n\n                <div ng-if=\"activeTab.id == 'upload' && formElement.type === 'upload'\">\n                    <div class=\"form-group\">\n                        <div class=\"checkbox\">\n                            <label>\n                                <input type=\"checkbox\" ng-model=\"formElement.params.multiple\">\n                                {{'FORM-BUILDER.COMPONENT.UPLOAD-ALLOW-MULTIPLE' | translate}}\n                            </label>\n                        </div>\n                    </div>\n                </div>\n                <div ng-if=\"activeTab.id == 'advanced' && (formElement.type === 'password')\">\n\t\t     <div class=\"form-group\">\n\t\t\t  <label translate=\"FORM-BUILDER.COMPONENT.MIN-LENGTH\"></label> <input\n\t\t\t\t type=\"text\" number-input-check maxlength=\"5\" class=\"form-control\"\n\t\t\t\t ng-model=\"formElement.params.minLength\">\n\t\t     </div>\n\t\t     <div class=\"form-group\">\n\t\t\t  <label translate=\"FORM-BUILDER.COMPONENT.MAX-LENGTH\"></label> <input\n\t\t\t         type=\"text\" number-input-check maxlength=\"5\" class=\"form-control\"\n\t\t\t         ng-model=\"formElement.params.maxLength\">\n              </div>\n                        <div class=\"row\">\n                           <div class=\"form-group col-md-12\">\n                               <div class=\"checkbox\">\n                                   <label>\n                                       <input type=\"checkbox\" ng-model=\"formElement.params.passwordunmask\">\n                                       {{'FORM-BUILDER.COMPONENT.PASSWORD-UNMASK-OPTION' | translate}}?\n                                   </label>\n                               </div>\n                            </div>\n                        </div>\n              </div>\n                <div ng-if=\"activeTab.id == 'advanced' && (formElement.type === 'text' || formElement.type === 'multi-line-text' || formElement.type === 'decimal' || formElement.type === 'integer')\">\n\t\t     <div class=\"form-group\">\n\t\t\t  <label translate=\"FORM-BUILDER.COMPONENT.MIN-LENGTH\"></label> <input\n\t\t\t\t type=\"text\" number-input-check maxlength=\"5\" class=\"form-control\"\n\t\t\t\t ng-model=\"formElement.params.minLength\">\n\t\t     </div>\n\t\t     <div class=\"form-group\">\n\t\t\t  <label translate=\"FORM-BUILDER.COMPONENT.MAX-LENGTH\"></label> <input\n\t\t\t         type=\"text\" number-input-check maxlength=\"5\" class=\"form-control\"\n\t\t\t         ng-model=\"formElement.params.maxLength\">\n                     </div>\n\t\t     <div class=\"form-group\">\n\t\t\t  <label translate=\"FORM-BUILDER.COMPONENT.REGEX-PATTERN\"></label>\n\t\t\t\t<div class=\"input-group\">\n\t\t\t            <span class=\"input-group-addon\">/^</span> <input type=\"text\" class=\"form-control\" ng-model=\"formElement.params.regexPattern\">\n\t\t\t\t    <span class=\"input-group-addon\">$/</span>\n\t\t\t\t</div>\n\t\t    </div>\n                    <div class=\"row\">\n\t\t\t<div class=\"col-md-4\">\n\t\t\t    <div class=\"form-group\">\n\t\t\t        <label translate=\"FORM-BUILDER.COMPONENT.MASK.TITLE\"></label>\n\t\t\t        <input type=\"text\" class=\"form-control\" ng-model=\"formElement.params.mask\">\n\t\t\t    </div>\n\t\t\t</div>\n\t\t\t<div class=\"col-md-4\">\n\t\t\t    <div class=\"form-group\">\n\t\t\t        <label translate>FORM-BUILDER.COMPONENT.MASK.EXAMPLES.TITLE</label>\n\t\t\t\t<ul>\n\t\t\t   \t    <li><span translate>FORM-BUILDER.COMPONENT.MASK.EXAMPLES.NUMBER</span>: <b>9</b></li>\n\t\t\t\t    <li><span translate>FORM-BUILDER.COMPONENT.MASK.EXAMPLES.LETTER</span>: <b>A</b></li>\n\t\t\t\t    <li><span translate>FORM-BUILDER.COMPONENT.MASK.EXAMPLES.NUMBERORLETTER</span>: <b>*</b></li>\n\t\t\t\t    <li><span translate>FORM-BUILDER.COMPONENT.MASK.EXAMPLES.OPTIONAL</span>: <b>?</b></li>\n\t\t\t\t    <li><span translate>FORM-BUILDER.COMPONENT.MASK.EXAMPLES.PHONE</span>: <b>(99) 9999-9999</b></li>\n\t\t\t\t</ul>\n\t\t\t   </div>\n\t\t\t</div>\n\t\t    </div>\n\t\t</div>\n                \n\t\t<div ng-if=\"activeTab.id == 'advanced' && formElement.type === 'hyperlink'\">\n\t\t    <div class=\"form-group\">\n\t\t\t<label translate=\"FORM-BUILDER.COMPONENT.HYPERLINK-URL\"></label> <input\n\t\t\ttype=\"text\" class=\"form-control\" ng-model=\"formElement.params.hyperlinkUrl\">\n\t\t    </div>\n\t\t</div>\t    \n\t\t    \n                <div ng-if=\"activeTab.id == 'general' && formElement.type === 'expression'\">\n                    <div class=\"form-group\">\n                        <label translate=\"FORM-BUILDER.COMPONENT.EXPRESSION\"></label>\n                        <textarea rows=\"3\" ng-model=\"formElement.expression\" class=\"form-control\" id=\"readonly-text-value\"></textarea>\n                        <div class=\"subtle\" translate=\"FORM-BUILDER.MESSAGE.EXPRESSION-HELP\" style=\"padding: 5px 0 5px 1px;\"></div>\n                    </div>\n                    <div class=\"form-group\">\n                    \t<label translate=\"FORM-BUILDER.COMPONENT.SIZE\"></label>\n                    \t<select class=\"form-control\" ng-model=\"formElement.params.size\">\n                        \t<option>1</option>\n                        \t<option>2</option>\n                        \t<option>3</option>\n                        \t<option>4</option>\n                        \t<option>5</option>\n                        </select>\n                    </div>\n                </div>\n            </div>\n            <div class=\"modal-footer\">\n                <div class=\"pull-right\">\n                    <button type=\"button\" class=\"btn btn-sm btn-default\" ng-click=\"doneEditing()\">\n                        {{'GENERAL.ACTION.CLOSE' | translate}}\n                    </button>\n                </div>\n            </div>\n        </div>\n    </div>\n</div>\n"
  },
  {
    "path": "flowable-ui-web/modeler/views/popover/history.html",
    "content": "<div class=\"popover\" click-anywhere=\"$hide()\" ignore=\"toggle-history\">\n    <div class=\"arrow\"></div>\n    <div class=\"popover-header\">\n        <span class=\"title\">{{title && (title | translate) || ('GENERAL.TITLE.HISTORY' | translate)}}</span>\n\n        <div class=\"actions\">\n            <a ng-click=\"$hide()\" ng-show=\"!newTask.loading\">\n                {{'GENERAL.ACTION.CLOSE' | translate}}</a>\n        </div>\n    </div>\n\n    <div class=\"popover-wrapper\">\n    \t<table class=\"history\" >\n   \t\t\t<tr ng-class=\"{'current' : version.version == model.form.version}\" ng-repeat=\"version in model.versions.data | orderBy:'-lastUpdated'\" ng-click=\"showVersion(version); $event.stopPropagation();\">\n   \t\t\t\t<td><a class=\"version\">{{version.version}}</a></td>\n   \t\t\t\t<td><a class=\"detail\"title=\"{{version.lastUpdated | dateformat:'LLLL'}}\">{{version.createdBy}} - {{version.lastUpdated | dateformat}}</a>\n   \t\t\t</td></tr>\n   \t\t</table>\n    </div>\n</div>"
  },
  {
    "path": "flowable-ui-web/modeler/views/popover/select-app-icon.html",
    "content": "<div class=\"popover medium\" click-anywhere=\"$hide()\" ignore=\"toggle-icon-select\">\n    <div class=\"arrow\"></div>\n    <div class=\"popover-header\">\n        <span class=\"title\">{{'APP.TITLE.SELECT-ICON' | translate}}</span>\n\n        <div class=\"actions\">\n            <a ng-click=\"$hide()\">\n                {{'GENERAL.ACTION.CLOSE' | translate}}</a>\n        </div>\n    </div>\n\t<div class=\"popover-wrapper\">\n    \t<div class=\"grid\">\n    \t\t<div class=\"item\" ng-repeat=\"icon in availableIcons\" ng-class=\"{'active': icon == currentAppDefinition.definition.icon}\" ng-click=\"selectIcon(icon); $hide();\">\n    \t\t\t<i class=\"glyphicon {{icon}}\"></i>\n    \t\t</div>\n    \t</div>\n\t</div>\n</div>"
  },
  {
    "path": "flowable-ui-web/modeler/views/popover/select-app-theme.html",
    "content": "<div class=\"popover medium\" click-anywhere=\"$hide()\" ignore=\"toggle-theme-select\">\n    <div class=\"arrow\"></div>\n    <div class=\"popover-header\">\n        <span class=\"title\">{{'APP.TITLE.SELECT-THEME' | translate}}</span>\n\n        <div class=\"actions\">\n            <a ng-click=\"$hide()\">\n                {{'GENERAL.ACTION.CLOSE' | translate}}</a>\n        </div>\n    </div>\n\t<div class=\"popover-wrapper\">\n    \t<div class=\"grid wide\">\n    \t\t<div class=\"item\" ng-repeat=\"theme in availableThemes\" ng-class=\"{'active': theme == currentAppDefinition.definition.theme}\" ng-click=\"selectTheme(theme); $hide();\">\n    \t\t\t<div class=\"app preview thumb {{theme}}\">\n    \t\t\t\t<div class=\"backdrop\">\n    \t\t\t\t\t<i class=\"glyphicon glyphicon-briefcase\"></i>\n    \t\t\t\t</div>\n    \t\t\t\t<div class=\"logo\">\n    \t\t\t\t\t<i class=\"glyphicon glyphicon-briefcase\"></i>\n    \t\t\t\t</div>\n    \t\t\t</div>\n    \t\t</div>\n    \t</div>\n\t</div>\n</div>"
  },
  {
    "path": "flowable-ui-web/modeler/views/popover/select-group-popover.html",
    "content": "<div class=\"popover\" click-anywhere=\"$hide()\" ignore-class=\"group-selection\" auto-scroll>\n    <div class=\"arrow\"></div>\n    <div class=\"popover-header\">\n        <span class=\"title\">{{title && title || 'GENERAL.TITLE.SELECT-GROUP' | translate}}</span>\n\n        <div class=\"actions\">\n            <a ng-click=\"$hide()\">\n                {{'GENERAL.ACTION.CLOSE' | translate}}</a>\n        </div>\n   \t</div>\n    <div class=\"popover-wrapper\">\n        <div class=\"form-group\" ng-if=\"popupModel.formFields\">\n            <div class=\"col-xs-4\">\n                <label>{{'GENERAL.MESSAGE.GROUP-SOURCE-TYPE' | translate}}</label>\n            </div>\n            <div class=\"col-xs-8\">\n                <div class=\"btn-group btn-group-justified\">\n                  <div class=\"btn-group\">\n                    <button type=\"button\" class=\"btn btn-default\" ng-click=\"setSearchType()\" ng-model=\"popupModel.groupSourceType\" ng-class=\"{'active' : (!popupModel.groupSourceType || popupModel.groupSourceType == 'search')}\">{{'GENERAL.MESSAGE.GROUP-SOURCE-SEARCH-OPTION' | translate}}</button>\n                  </div>\n                  <div class=\"btn-group\">\n                    <button type=\"button\" class=\"btn btn-default\" ng-click=\"setFormFieldType()\" ng-model=\"popupModel.groupSourceType\" ng-class=\"{'active' : popupModel.groupSourceType == 'field'}\">{{'GENERAL.MESSAGE.GROUP-SOURCE-FIELD-OPTION' | translate}}</button>\n                  </div>\n                </div>\n            </div>\n        </div>\n        \n        <div ng-if=\"popupModel.formFields\" class=\"col-xs-12\" style=\"margin-bottom:10px\" />\n\n        <div ng-show=\"(!popupModel.groupSourceType || popupModel.groupSourceType == 'search')\">\n            <div class=\"subtitle\" translate=\"GENERAL.TITLE.FILTER\">\n            </div>\n            <div class=\"form-group\">\n                <input class=\"form-control\" type=\"text\" id=\"people-select-input\" placeholder=\"Search group\" auto-focus custom-keys\n                       up-pressed=\"previousGroup()\" down-pressed=\"nextGroup()\" enter-pressed=\"confirmGroup()\" delayed-model=\"popupModel.filter\" delay=\"200\"/>\n                <div class=\"inline-help\" translate=\"GENERAL.MESSAGE.SELECT-GROUP-HELP\"></div>\n            </div>\n            <div class=\"subtitle\">\n                <span translate=\"GENERAL.TITLE.MATCHING-GROUPS\"></span>\n            </div>\n            <div class=\"people-select\">\n                <ul class=\"simple-list\">\n                    <li ng-click=\"confirmGroup(group);\" ng-repeat=\"group in popupModel.groupResults\" ng-class=\"{'active': group.id === popupModel.selectedGroup.id}\">\n                        {{group.name}}\n                    </li>\n                </ul>\n                <div class=\"nothing-to-see\" translate=\"GENERAL.MESSAGE.GROUP-NO-MATCHING-RESULTS\" ng-show=\"popupModel.groupResults.length == 0\"></div>\n            </div>\n        </div>\n        \n        <div ng-show=\"popupModel.groupSourceType == 'field'\" class=\"form-group clearfix\">\n            <div class=\"col-xs-4\">\n                <label>{{'PROCESS-BUILDER.PUBLISH-STEP.SOURCE.FORM-FIELD' | translate}}:</label>\n            </div>\n            <div class=\"col-xs-8\">\n                <div id=\"userFormField\" variables-select include-type=\"false\" expand-relative=\"true\" field-type-filter=\"popupModel.groupFieldFilter\"\n                       select-title=\"'FORM-BUILDER.MESSAGE.READONLY-TEXT-INSERT-FIELD'\" fields=\"popupModel.formFields\" selected-field=\"popupModel.groupField\" ignore-selection=\"true\"></div>\n            </div>\n        </div>\n    </div>\n</div>"
  },
  {
    "path": "flowable-ui-web/modeler/views/popup/app-definition-create.html",
    "content": "<div class=\"modal\" ng-controller=\"CreateNewAppCtrl\">\n\t<div class=\"modal-dialog\">\n\t\t<div class=\"modal-content\">\n\t\t\t<div class=\"modal-header\"><h2>{{'APP.POPUP.CREATE-TITLE' | translate}}</h2></div>\n\t\t\t<div class=\"modal-body\">\n                <div ng-if=\"model.errorMessage && model.errorMessage.length > 0\" class=\"alert error\" style=\"font-size: 14px; margin-top:20px\">\n                  <div class=\"popup-error\" style=\"font-size: 14px\">\n                    <span class=\"glyphicon glyphicon-remove-circle\"></span>\n                    <span>{{model.errorMessage}}</span>\n                  </div>\n                </div>\n\t\t\t\t<p>{{'APP.POPUP.CREATE-DESCRIPTION' | translate}}</p>\n\t\t\t\t<div class=\"form-group\">\n\t\t\t\t    <label for=\"newAppName\">{{'APP.NAME' | translate}}</label>\n\t\t\t\t    <input ng-disabled=\"model.loading\" type=\"text\" class=\"form-control\"\n\t\t\t               id=\"newAppName\" ng-model=\"model.app.name\"\n                           custom-keys enter-pressed=\"ok()\" auto-focus>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"form-group\">\n\t\t\t\t    <label for=\"newAppKey\">{{'APP.KEY' | translate}}</label>\n\t\t\t\t    <input ng-disabled=\"model.loading\" type=\"text\" class=\"form-control\"\n\t\t\t               id=\"newAppKey\" ng-model=\"model.app.key\">\n\t\t\t\t</div>\n\t\t\t\t<div class=\"form-group\">\n\t\t\t\t    <label for=\"newAppDescription\">{{'APP.DESCRIPTION' | translate}}</label>\n\t\t\t\t\t<textarea ng-disabled=\"model.loading\" class=\"form-control\" id=\"newAppDescription\" rows=\"5\" ng-model=\"model.app.description\"></textarea>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t\n\t\t\t<div class=\"modal-footer\">\n\t\t\t\t<div class=\"pull-right\">\n\t\t\t\t\t<button type=\"button\" class=\"btn btn-sm btn-default\" ng-click=\"cancel()\" ng-disabled=\"model.loading\">\n\t\t\t\t\t\t{{'GENERAL.ACTION.CANCEL' | translate}}\n\t\t\t\t\t</button>\n\t\t\t\t\t<button type=\"button\" class=\"btn btn-sm btn-default\" ng-click=\"ok()\"ng-disabled=\"model.loading || !model.app.name || model.app.name.length == 0 || !model.app.key || model.app.key.length == 0\">\n\t\t\t\t\t\t{{'APP.ACTION.CREATE-CONFIRM' | translate}}\n\t\t\t\t\t</button>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"loading pull-right\" ng-show=\"model.loading\">\n\t\t\t\t\t<div class=\"l1\"></div><div class=\"l2\"></div><div class=\"l2\"></div>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</div>\n\t</div>\n</div>"
  },
  {
    "path": "flowable-ui-web/modeler/views/popup/app-definition-delete.html",
    "content": "\n<div class=\"modal\" ng-controller=\"DeleteAppDefinitionPopupCtrl\">\n\t<div class=\"modal-dialog\">\n\t\t<div class=\"modal-content\">\n\t\t\t<div class=\"modal-header\">\n\t\t\t\t<h2>{{'APP.POPUP.DELETE-TITLE' | translate}}</h2>\n\t\t\t</div>\n\t\t\t<div class=\"modal-body\">\n\t\t\t\t<p>{{'APP.POPUP.DELETE-DESCRIPTION-WITH-RUNTIME' | translate:model.app}}</p>\n\n\t\t\t\t<div class=\"form-group\" ng-if=\"model.app.version != 1 && model.app.createdBy == account.id\">\n\t\t\t\t\t<div class=\"radio\" ng-click=\"popup.cascade = 'false'\">\n\t\t\t\t        <input ng-model=\"popup.cascade\" value=\"false\" type=\"radio\" name=\"cascadeDelete\">\n\t\t\t\t        <strong style=\"cursor:pointer\">{{'APP.POPUP.DELETE-CASCADE-FALSE' | translate:model.app}}</strong>\n\t\t\t\t\t</div>\n\t\t\t\t\t<div class=\"radio\" ng-click=\"popup.cascade = 'true'\">\n\t\t\t\t\t\t<input ng-model=\"popup.cascade\" value=\"true\" type=\"radio\" name=\"cascadeDelete\">\n\t\t\t\t        <strong style=\"cursor:pointer\">{{'APP.POPUP.DELETE-CASCADE-TRUE' | translate}}</strong>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t\t\n\t\t\t</div>\n\t\t\t<div class=\"modal-footer\">\n\t\t\t\t<div class=\"pull-right\">\n\t\t\t\t\t<button type=\"button\" class=\"btn btn-sm btn-default\" ng-click=\"cancel()\" ng-disabled=\"popup.loading\">\n\t\t\t\t\t\t{{'GENERAL.ACTION.CANCEL' | translate}}\n\t\t\t\t\t</button>\n\t\t\t\t\t<button type=\"button\" class=\"btn btn-sm btn-danger\" ng-click=\"ok()\" ng-disabled=\"popup.loading || !model.app.name\">\n\t\t\t\t\t\t<span>{{'APP.ACTION.DELETE-CONFIRM' | translate}}</span>\n\t\t\t\t\t</button>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"loading pull-right\" ng-show=\"popup.loading\">\n\t\t\t\t\t<div class=\"l1\"></div><div class=\"l2\"></div><div class=\"l2\"></div>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</div>\n\t</div>\n</div>"
  },
  {
    "path": "flowable-ui-web/modeler/views/popup/app-definition-duplicate.html",
    "content": "<div class=\"modal\" ng-controller=\"DuplicateAppCtrl\">\n\t<div class=\"modal-dialog\">\n\t\t<div class=\"modal-content\">\n\t\t\t<div class=\"modal-header\"><h2>{{'APP.POPUP.DUPLICATE-TITLE' | translate}}</h2></div>\n\t\t\t<div class=\"modal-body\">\n                 <div ng-if=\"model.errorMessage && model.errorMessage.length > 0\" class=\"alert error\" style=\"font-size: 14px; margin-top:20px\">\n                  <div class=\"popup-error\" style=\"font-size: 14px\">\n                    <span class=\"glyphicon glyphicon-remove-circle\"></span>\n                    <span>{{model.errorMessage}}</span>\n                  </div>\n                </div>\n\t\t\t\t<p>{{originalModel?'APP.POPUP.DUPLICATE-DESCRIPTION':'APP.POPUP.CREATE-DESCRIPTION' | translate}}</p>\n\t\t\t\t<div class=\"form-group\">\n\t\t\t\t    <label for=\"newAppName\">{{'APP.NAME' | translate}}</label>\n\t\t\t\t    <input ng-disabled=\"model.loading\" type=\"text\" class=\"form-control\"\n\t\t\t               id=\"newAppName\" ng-model=\"model.app.name\"\n                           custom-keys enter-pressed=\"ok()\" auto-focus>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"form-group\">\n\t\t\t\t    <label for=\"newAppKey\">{{'APP.KEY' | translate}}</label>\n\t\t\t\t    <input ng-disabled=\"model.loading\" type=\"text\" class=\"form-control\"\n\t\t\t               id=\"newAppKey\" ng-model=\"model.app.key\">\n\t\t\t\t</div>\n\t\t\t\t<div class=\"form-group\">\n\t\t\t\t    <label for=\"newAppDescription\">{{'APP.DESCRIPTION' | translate}}</label>\n\t\t\t\t\t<textarea ng-disabled=\"model.loading\" class=\"form-control\" id=\"newAppDescription\" rows=\"5\" ng-model=\"model.app.description\"></textarea>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t\n\t\t\t<div class=\"modal-footer\">\n\t\t\t\t<div class=\"pull-right\">\n\t\t\t\t\t<button type=\"button\" class=\"btn btn-sm btn-default\" ng-click=\"cancel()\" ng-disabled=\"model.loading\">\n\t\t\t\t\t\t{{'GENERAL.ACTION.CANCEL' | translate}}\n\t\t\t\t\t</button>\n\t\t\t\t\t<button type=\"button\" class=\"btn btn-sm btn-default\" ng-click=\"ok()\"ng-disabled=\"model.loading || !model.app.name || !model.app.key\">\n\t\t\t\t\t\t{{originalModel?'APP.ACTION.DUPLICATE-CONFIRM':'APP.ACTION.CREATE-CONFIRM' | translate}}\n\t\t\t\t\t</button>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"loading pull-right\" ng-show=\"model.loading\">\n\t\t\t\t\t<div class=\"l1\"></div><div class=\"l2\"></div><div class=\"l2\"></div>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</div>\n\t</div>\n</div>"
  },
  {
    "path": "flowable-ui-web/modeler/views/popup/app-definition-import.html",
    "content": "\n<div class=\"modal\" ng-controller=\"ImportNewVersionAppDefinitionCtrl\">\n    <div class=\"modal-dialog\">\n        <div class=\"modal-content\">\n            <div class=\"modal-header-wrapper\">\n            \t<div class=\"modal-header\">\n            \t\t<div class=\"pull-right\">\n                        <a class=\"action\" ng-click=\"cancel()\">&times; {{'GENERAL.ACTION.CANCEL' | translate}}</a>\n                    </div>\n            \t\t<h2>{{'APP.POPUP.IMPORT-TITLE' | translate}}</h2>\n            \t</div>\n            </div>\n            <div class=\"modal-body\">\n\n                <div class=\"checkbox\" ng-show=\"!error && !error.isConflict\">\n                    <label>\n                        <input type=\"checkbox\" ng-disabled=\"popup.loading\" ng-model=\"popup.renewIdmIds\">\n                            {{'APP.POPUP.IMPORT.RENEWIDM-IDS' | translate}}\n                    </label>\n                </div>\n\n                <p>\n                    <i class=\"glyphicon glyphicon-info-sign\"></i>\n                    {{'APP.POPUP.IMPORT-DESCRIPTION' | translate}}\n                </p>\n                <!--[if IE 9]>\n                <div class=\"import-process-form\">\n\n                    <input type=\"file\" ngf-select=\"\" ngf-change=\"onFileSelect($files,true)\" style=\"font-size: smaller; padding-top:6px;\" >\n                    <div class=\"import-process-dropbox\"\n                         ngf-drop=\"onFileSelect($files)\"\n                         ngf-drag-over-class=\"dragover\"\n                         ng-show=\"dropSupported\">\n                        {{'APP.POPUP.IMPORT.DROPZONE' | translate}}\n                    </div>\n                    <div ngf-drop-available=\"dropSupported=true\"\n                         ng-show=\"!dropSupported\">{{'APP.POPUP.IMPORT.NO-DROP' | translate}}</div>\n                    <div class=\"graph-wrapper\" ng-show=\"popup.loading\" style=\"margin: 10px 0 10px 0\">\n                        <div class=\"graph-bar\" ng-style=\"{width: popup.uploadProgress + '%'}\"></div>\n                    </div>\n                    <button class=\"btn btn-danger btn-sm\"\n                            ng-click=\"upload.abort()\"\n                            ng-disabled=\"!popup.loading\"\n                            style=\"margin-bottom: 20px\">\n                        {{'APP.POPUP.IMPORT.CANCEL-UPLOAD' | translate}}\n                    </button>\n\n                </div>\n                <![endif]-->\n                <!--[if gt IE 9]> <!-- -->\n                <div class=\"import-process-form\">\n\n                    <input type=\"file\" ngf-select=\"\" ngf-change=\"onFileSelect($files)\" style=\"font-size: smaller; padding-top:6px;\" >\n                    <div class=\"import-process-dropbox\"\n                         ngf-drop ngf-change=\"onFileSelect($files)\"\n                         ngf-drag-over-class=\"dragover\"\n                         ng-show=\"dropSupported\">\n                        {{'APP.POPUP.IMPORT.DROPZONE' | translate}}\n                    </div>\n                    <div ngf-file-drop-available=\"dropSupported=true\"\n                         ng-show=\"!dropSupported\">{{'APP.POPUP.IMPORT.NO-DROP' | translate}}</div>\n                    <div class=\"graph-wrapper\" ng-show=\"popup.loading\" style=\"margin: 10px 0 10px 0\">\n                        <div class=\"graph-bar\" ng-style=\"{width: popup.uploadProgress + '%'}\"></div>\n                    </div>\n                    <button class=\"btn btn-danger btn-sm\"\n                            ng-click=\"upload.abort()\"\n                            ng-disabled=\"!popup.loading\"\n                            style=\"margin-bottom: 20px\">\n                        {{'APP.POPUP.IMPORT.CANCEL-UPLOAD' | translate}}\n                    </button>\n\n                </div>\n                <!-- <![endif]-->\n            </div>\n\n            <div class=\"modal-footer-wrapper\">\n                <div class=\"modal-footer\">\n                    <loading></loading>\n                    <div class=\"pull-right modeler-processes-error\" ng-if=\"popup.error\">\n                        <span>{{'APP.POPUP.IMPORT.ERROR' | translate}} <span ng-if=\"popup.errorMessage\"> : </span>{{popup.errorMessage}}</span>\n                    </div>\n                </div>\n            </div>\n        </div>\n    </div>\n</div>\n"
  },
  {
    "path": "flowable-ui-web/modeler/views/popup/app-definition-models-included.html",
    "content": "<div class=\"modal\" ng-controller=\"ModelsIncludedPopupCtrl\">\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>\n                    {{'APP.POPUP.INCLUDE-MODELS-TITLE' | translate}}\n                </h2>\n            </div>\n\n\n            <div class=\"modal-body modal-body-with-overflow\">\n                <div class=\"tabs-wrapper\">\n\n                <div tab-control=\"tabs\" active-tab=\"popup.activeTab\">\n                </div>\n                \n                <div class=\"item-wrapper clearfix\" ng-show=\"popup.activeTab == 'bpmn'\">\n                    <div class=\"item fadein\" ng-repeat=\"model in popup.models.data\">\n                        <div class=\"item-box\" ng-style=\"{'background-image': 'url(\\'' + getModelThumbnailUrl(model.id) + '\\')'}\" ng-click=\"selectModel(model); $event.stopPropagation();\">\n                            <span class=\"badge\">v{{model.version}}</span>\n                            <div class=\"btn-group pull-right\">\n                                <button type=\"button\" ng-show=\"isModelSelected(model)\" class=\"btn btn-default\" title=\"{{'PROCESS.ACTION.DETAILS' | translate}}\">\n                                    <i class=\"glyphicon glyphicon-plus-sign\"></i>\n                                </button>\n                            </div>\n                            <div class=\"details\">\n                                <h3 class=\"truncate\" title=\"{{model.name}}\">\n                                    {{model.name}}\n                                </h3>\n                                <div class=\"basic-details truncate\">\n                                    <span><i class=\"glyphicon glyphicon-user\"></i> {{model.createdBy}}</span> <span title=\"{{model.lastUpdated | dateformat:'LLLL'}}\"><i class=\"glyphicon glyphicon-pencil\"></i> {{model.lastUpdated | dateformat}}</span>\n                                </div>\n                                <p>{{model.description}}</p>\n                            </div>\n                        </div>\n                    </div>\n                </div>\n                \n                <div class=\"item-wrapper clearfix\" ng-show=\"popup.activeTab == 'cmmn'\">\n                    <div class=\"item fadein\" ng-repeat=\"cmmnModel in popup.cmmnModels.data\">\n                        <div class=\"item-box\" ng-style=\"{'background-image': 'url(\\'' + getModelThumbnailUrl(cmmnModel.id) + '\\')'}\" ng-click=\"selectCmmnModel(cmmnModel); $event.stopPropagation();\">\n                            <span class=\"badge\">v{{cmmnModel.version}}</span>\n                            <div class=\"btn-group pull-right\">\n                                <button type=\"button\" ng-show=\"isCmmnModelSelected(cmmnModel)\" class=\"btn btn-default\" title=\"{{'PROCESS.ACTION.DETAILS' | translate}}\">\n                                    <i class=\"glyphicon glyphicon-plus-sign\"></i>\n                                </button>\n                            </div>\n                            <div class=\"details\">\n                                <h3 class=\"truncate\" title=\"{{cmmnModel.name}}\">\n                                    {{cmmnModel.name}}\n                                </h3>\n                                <div class=\"basic-details truncate\">\n                                    <span><i class=\"glyphicon glyphicon-user\"></i> {{cmmnModel.createdBy}}</span> <span title=\"{{cmmnModel.lastUpdated | dateformat:'LLLL'}}\"><i class=\"glyphicon glyphicon-pencil\"></i> {{cmmnModel.lastUpdated | dateformat}}</span>\n                                </div>\n                                <p>{{cmmnModel.description}}</p>\n                            </div>\n                        </div>\n                    </div>\n                </div>\n            </div>\n            <div class=\"modal-footer\">\n                <div class=\"pull-right\">\n                    <button type=\"button\" class=\"btn btn-default\" ng-click=\"close()\" ng-disabled=\"popup.loading\">\n                        {{'GENERAL.ACTION.CLOSE' | translate}}\n                    </button>\n                </div>\n            </div>\n        </div>\n    </div>\n</div>\n"
  },
  {
    "path": "flowable-ui-web/modeler/views/popup/app-definition-publish.html",
    "content": "\n<div class=\"modal\" ng-controller=\"PublishAppDefinitionPopupCtrl\">\n\t<div class=\"modal-dialog\">\n\t\t<div class=\"modal-content\">\n\t\t\t<div class=\"modal-header\">\n\t\t\t\t<h2>{{'APP.POPUP.PUBLISH-TITLE' | translate}}</h2>\n\t\t\t</div>\n\t\t\t<div class=\"modal-body\">\n\n                <div ng-show=\"popup.error == undefined || popup.error == null\">\n\t\t\t\t    <p>{{'APP.POPUP.PUBLISH-DESCRIPTION' | translate:model.app}}</p>\n                </div>\n\n                <div ng-if=\"popup.error && popup.error.type && popup.error.type == 'conflictingProcDefKey'\"\n                     class=\"alert-danger app-publish-error\" role=\"alert\">\n                    <span class=\"glyphicon glyphicon-exclamation-sign\" aria-hidden=\"true\" style=\"margin-right: 2px\"></span>\n                    <span>{{'APP.POPUP.PUBLISH-ERROR-PROCDEF-KEY-CONFLICT' | translate:popup.error.data}}</span>\n                </div>\n\n                <div ng-if=\"popup.error && popup.error.type && popup.error.type == 'duplicateProcDefKeys'\"\n                     class=\"alert-danger app-publish-error\" role=\"alert\">\n                    <span class=\"glyphicon glyphicon-exclamation-sign\" aria-hidden=\"true\" style=\"margin-right: 2px\"></span>\n                    <span>{{'APP.POPUP.PUBLISH-ERROR-PROCDEF-DUPLICATE-KEYS' | translate}}</span>\n                    <ul>\n                        <li ng-repeat=\"entry in popup.error.data.duplicateProcessDefinitionIds\">\n                            <span ng-repeat=\"(id, name) in entry\">{{id}} ({{name}})</span>\n                        </li>\n                    </ul>\n                </div>\n\n                <div ng-if=\"popup.error && popup.error.type && popup.error.type == 'processModelAlreadyUsed'\"\n                     class=\"alert-warning app-publish-error\" role=\"alert\">\n                    <span class=\"glyphicon glyphicon-exclamation-sign\" aria-hidden=\"true\" style=\"margin-right: 2px\"></span>\n                    <span>{{'APP.POPUP.PUBLISH-ERROR-PROCESS-ALREADY-USED' | translate}}</span>\n                    <ul>\n                        <li ng-repeat=\"processName in popup.error.data.conflictingProcessModelNames track by $index\">\n                            {{processName}} ({{'APP.POPUP.PUBLISH-ERROR-PROCESS-ALREADY-USED-APP' | translate}} \"{{popup.error.data.conflictingAppNames[$index]}}\")\n                        </li>\n                    </ul>\n                </div>\n\n\t\t\t</div>\n\t\t\t<div class=\"modal-footer\">\n\t\t\t\t<div class=\"pull-right\" ng-if=\"popup.error == undefined || popup.error == null || (popup.error && popup.error.type != 'processModelAlreadyUsed')\">\n\t\t\t\t\t<button type=\"button\" class=\"btn btn-sm btn-default\" ng-click=\"cancel()\" ng-disabled=\"popup.loading\">\n\t\t\t\t\t\t{{'GENERAL.ACTION.CANCEL' | translate}}\n\t\t\t\t\t</button>\n\t\t\t\t\t<button type=\"button\" class=\"btn btn-sm btn-danger\" ng-click=\"ok()\" ng-disabled=\"popup.loading  || (popup.error != null && popup.error != undefined)\">\n\t\t\t\t\t\t<span>{{'APP.ACTION.PUBLISH-CONFIRM' | translate}}</span>\n\t\t\t\t\t</button>\n\t\t\t\t</div>\n                <div class=\"pull-right\" ng-if=\"popup.error.type == 'processModelAlreadyUsed'\">\n                    <button type=\"button\" class=\"btn btn-sm btn-default\" ng-click=\"cancel()\" ng-disabled=\"popup.loading\">\n                        {{'GENERAL.ACTION.CANCEL' | translate}}\n                    </button>\n                    <button type=\"button\" class=\"btn btn-sm btn-success\" style=\"background-color: #5cb85c;border-color: #4cae4c;\" ng-click=\"ok(true)\" ng-disabled=\"popup.loading\">\n                        <span>{{'GENERAL.ACTION.CONFIRM' | translate}}</span>\n                    </button>\n                </div>\n                <div class=\"loading pull-right\" ng-show=\"popup.loading\">\n                    <div class=\"l1\"></div><div class=\"l2\"></div><div class=\"l2\"></div>\n                </div>\n\t\t\t</div>\n\t\t</div>\n\t</div>\n</div>"
  },
  {
    "path": "flowable-ui-web/modeler/views/popup/app-definition-save-model.html",
    "content": "\n<div class=\"modal\" ng-controller=\"SaveAppDefinitionCtrl\">\n\t<div class=\"modal-dialog\">\n\t\t<div class=\"modal-content\">\n\t\t\t<div class=\"modal-header\"><h2>{{'APP.POPUP.SAVE-APP-TITLE' | translate}}</h2></div>\n\t\t\t<div class=\"modal-body\">\n\t\t\t\t<p>{{'APP.POPUP.CREATE-DESCRIPTION' | translate}}</p>\n\t\t\t\t<div ng-if=\"saveDialog.errorMessage && saveDialog.errorMessage.length > 0\" class=\"alert error\" style=\"font-size: 14px; margin-top:20px\">\n                  <div class=\"popup-error\" style=\"font-size: 14px\">\n                    <span class=\"glyphicon glyphicon-remove-circle\"></span>\n                    <span>{{saveDialog.errorMessage}}</span>\n                  </div>\n                </div>\n\t\t\t\t<div class=\"form-group\">\n\t\t\t\t    <label for=\"appName\">{{'APP.NAME' | translate}}</label>\n\t\t\t\t    <input ng-disabled=\"model.loading\" type=\"text\" class=\"form-control\"\n\t\t\t               id=\"appName\" ng-model=\"saveDialog.name\" ui-keypress=\"{13:'ok()'}\" auto-focus>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"form-group\">\n\t\t\t\t    <label for=\"appKey\">{{'APP.KEY' | translate}}</label>\n\t\t\t\t    <input ng-disabled=\"model.loading\" type=\"text\" class=\"form-control\"\n\t\t\t               id=\"appKey\" ng-model=\"saveDialog.key\">\n\t\t\t\t</div>\n\t\t\t\t<div class=\"form-group\">\n\t\t\t\t    <label for=\"appDescription\">{{'APP.DESCRIPTION' | translate}}</label>\n\t\t\t\t\t<textarea ng-disabled=\"model.loading\" class=\"form-control\" id=\"appDescription\" rows=\"5\" ng-model=\"saveDialog.description\"></textarea>\n\t\t\t\t</div>\n                <div class=\"checkbox\" ng-if=\"currentAppDefinition.definition &&\n\t\t\t\t    ((currentAppDefinition.definition.models && currentAppDefinition.definition.models.length > 0)\n\t\t\t\t            || (currentAppDefinition.definition.cmmnModels && currentAppDefinition.definition.cmmnModels.length > 0)) \">\n\n                <label>\n                        <input type=\"checkbox\" ng-model=\"saveDialog.publish\">\n                            {{'APP.POPUP.PUBLISH-FIELD' | translate}}\n                    </label>\n                </div>\n                \n                <div ng-if=\"error && (error.hasCustomStencilItem || error.hasValidationErrors) && !status.loading\" class=\"alert error\" style=\"font-size: 14px; margin-top:20px\">\n                    <div class=\"popup-error\" style=\"font-size: 14px\">\n                        <span class=\"glyphicon glyphicon-remove-circle\"></span>\n                        <span ng-if=\"error.hasCustomStencilItem\">{{'APP.POPUP.HAS-CUSTOM-STENCILITEM' | translate:error}}</span>\n                        <span ng-if=\"error.hasValidationErrors\">{{'APP.POPUP.HAS-VALIDATIONERROR' | translate:error}}</span>\n                    </div>\n                </div>\n\n                <div ng-if=\"conflict && conflict.type && conflict.type == 'conflictingProcDefKey'\"\n                     class=\"alert-danger app-publish-error\" role=\"alert\">\n                    <span class=\"glyphicon glyphicon-exclamation-sign\" aria-hidden=\"true\" style=\"margin-right: 2px\"></span>\n                    <span>{{'APP.POPUP.PUBLISH-ERROR-PROCDEF-KEY-CONFLICT' | translate:conflict.data}}</span>\n                </div>\n\n                <div ng-if=\"conflict && conflict.type && conflict.type == 'duplicateProcDefKeys'\"\n                     class=\"alert-danger app-publish-error\" role=\"alert\">\n                    <span class=\"glyphicon glyphicon-exclamation-sign\" aria-hidden=\"true\" style=\"margin-right: 2px\"></span>\n                    <span>{{'APP.POPUP.PUBLISH-ERROR-PROCDEF-DUPLICATE-KEYS' | translate}}</span>\n                    <ul>\n                        <li ng-repeat=\"entry in conflict.data.duplicateProcessDefinitionIds\">\n                            <span ng-repeat=\"(id, name) in entry\">{{id}} ({{name}})</span>\n                        </li>\n                    </ul>\n                </div>\n\n                <div ng-if=\"conflict && conflict.type && conflict.type == 'processModelAlreadyUsed'\"\n                     class=\"alert-warning app-publish-error\" role=\"alert\">\n                    <span class=\"glyphicon glyphicon-exclamation-sign\" aria-hidden=\"true\" style=\"margin-right: 2px\"></span>\n                    <span>{{'APP.POPUP.PUBLISH-ERROR-PROCESS-ALREADY-USED' | translate}}</span>\n                    <ul>\n                        <li ng-repeat=\"processName in conflict.data.conflictingProcessModelNames track by $index\">\n                            {{processName}} ({{'APP.POPUP.PUBLISH-ERROR-PROCESS-ALREADY-USED-APP' | translate}} \"{{conflict.data.conflictingAppNames[$index]}}\")\n                        </li>\n                    </ul>\n                </div>\n\n\t\t\t</div>\n\t\t\t\n\t\t\t<div class=\"modal-footer\">\n\n\t\t\t\t<div class=\"pull-right\" ng-if=\"conflict == null || conflict == undefined || conflict.type != 'processModelAlreadyUsed'\">\n\t\t\t\t\t<button class=\"btn btn-sm btn-default\" ng-click=\"cancel()\" ng-disabled=\"model.loading\" translate>GENERAL.ACTION.CANCEL</button>\n\t\t\t\t\t<button class=\"btn btn-primary\" ng-click=\"saveAndClose()\" ng-disabled=\"status.loading || saveDialog.name.length == 0 || saveDialog.key.length == 0\" ng-show=\"!error && !error.hasCustomStencilItem && !error.hasValidationErrors\" translate>ACTION.SAVE-AND-CLOSE</button>\n\t\t\t\t\t<button class=\"btn btn-primary\" ng-click=\"save()\" ng-disabled=\"status.loading || saveDialog.name.length == 0 || saveDialog.key.length == 0\" ng-show=\"!error && !error.hasCustomStencilItem && !error.hasValidationErrors\" translate>ACTION.SAVE</button>\n\t\t\t\t</div>\n\n                <div class=\"pull-right\" ng-if=\"conflict && conflict.type == 'processModelAlreadyUsed'\">\n                    <button type=\"button\" class=\"btn btn-sm btn-default\" ng-click=\"cancel()\" ng-disabled=\"popup.loading\">\n                        {{'GENERAL.ACTION.CANCEL' | translate}}\n                    </button>\n                    <button type=\"button\" class=\"btn btn-sm btn-success\" style=\"background-color: #5cb85c;border-color: #4cae4c;\" ng-click=\"saveAndClose(true)\" ng-disabled=\"popup.loading\">\n                        <span>{{'GENERAL.ACTION.CONFIRM-AND-CLOSE' | translate}}</span>\n                    </button>\n                    <button type=\"button\" class=\"btn btn-sm btn-success\" style=\"background-color: #5cb85c;border-color: #4cae4c;\" ng-click=\"save(true)\" ng-disabled=\"popup.loading\">\n                        <span>{{'GENERAL.ACTION.CONFIRM' | translate}}</span>\n                    </button>\n                </div>\n\n\t\t\t\t<div class=\"loading pull-right\" ng-show=\"model.loading\">\n\t\t\t\t\t<div class=\"l1\"></div><div class=\"l2\"></div><div class=\"l2\"></div>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</div>\n\t</div>\n</div>"
  },
  {
    "path": "flowable-ui-web/modeler/views/popup/app-definitions-import.html",
    "content": "\n<div class=\"modal\" ng-controller=\"ImportAppDefinitionCtrl\">\n    <div class=\"modal-dialog\">\n        <div class=\"modal-content\">\n            <div class=\"modal-header-wrapper\">\n            \t<div class=\"modal-header\">\n            \t\t<div class=\"pull-right\">\n                        <a class=\"action\" ng-click=\"cancel()\">&times; {{'GENERAL.ACTION.CANCEL' | translate}}</a>\n                    </div>\n            \t\t<h2>{{'APP.POPUP.IMPORT-TITLE' | translate}}</h2>\n            \t</div>\n            </div>\n            <div class=\"modal-body\">\n\n                <div class=\"checkbox\" ng-show=\"!error && !error.isConflict\">\n                    <label>\n                        <input type=\"checkbox\" ng-disabled=\"status.loading\" ng-model=\"model.renewIdmIds\">\n                            {{'APP.POPUP.IMPORT.RENEWIDM-IDS' | translate}}\n                    </label>\n                </div>\n\n                <p>\n                    <i class=\"glyphicon glyphicon-info-sign\"></i>\n                    {{'APP.POPUP.IMPORT-DESCRIPTION' | translate}}\n                </p>\n\n                <!--[if IE 9]>\n                <div class=\"import-process-form\">\n\n                    <input type=\"file\" ngf-select=\"\" ngf-change=\"onFileSelect($files,true)\" style=\"font-size: smaller; padding-top:6px;\" >\n                    <div class=\"import-process-dropbox\"\n                         ngf-drop=\"onFileSelect($files)\"\n                         ngf-drag-over-class=\"dragover\"\n                         ng-show=\"dropSupported\">\n                        {{'APP.POPUP.IMPORT.DROPZONE' | translate}}\n                    </div>\n                    <div ngf-drop-available=\"dropSupported=true\"\n                         ng-show=\"!dropSupported\">{{'APP.POPUP.IMPORT.NO-DROP' | translate}}</div>\n                    <div class=\"graph-wrapper\" ng-show=\"status.loading\" style=\"margin: 10px 0 10px 0\">\n                        <div class=\"graph-bar\" ng-style=\"{width: model.uploadProgress + '%'}\"></div>\n                    </div>\n                    <button class=\"btn btn-danger btn-sm\"\n                            ng-click=\"upload.abort()\"\n                            ng-disabled=\"!status.loading\"\n                            style=\"margin-bottom: 20px\">\n                        {{'APP.POPUP.IMPORT.CANCEL-UPLOAD' | translate}}\n                    </button>\n\n                </div>\n\n                <![endif]-->\n                <!--[if gt IE 9]> <!-- -->\n                <div class=\"import-process-form\">\n\n                    <input type=\"file\" ngf-select=\"\" ngf-change=\"onFileSelect($files)\" style=\"font-size: smaller; padding-top:6px;\" >\n                    <div class=\"import-process-dropbox\"\n                         ngf-drop ngf-change=\"onFileSelect($files)\"\n                         ngf-drag-over-class=\"dragover\"\n                         ng-show=\"dropSupported\">\n                        {{'APP.POPUP.IMPORT.DROPZONE' | translate}}\n                    </div>\n                    <div ngf-drop-available=\"dropSupported=true\"\n                         ng-show=\"!dropSupported\">{{'APP.POPUP.IMPORT.NO-DROP' | translate}}</div>\n                    <div class=\"graph-wrapper\" ng-show=\"status.loading\" style=\"margin: 10px 0 10px 0\">\n                        <div class=\"graph-bar\" ng-style=\"{width: model.uploadProgress + '%'}\"></div>\n                    </div>\n                    <button class=\"btn btn-danger btn-sm\"\n                            ng-click=\"upload.abort()\"\n                            ng-disabled=\"!status.loading\"\n                            style=\"margin-bottom: 20px\">\n                        {{'APP.POPUP.IMPORT.CANCEL-UPLOAD' | translate}}\n                    </button>\n\n                </div>\n\n                <!-- <![endif]-->\n\n            </div>\n\n            <div class=\"modal-footer-wrapper\">\n                <div class=\"modal-footer\">\n                    <loading></loading>\n                    <div class=\"pull-right modeler-processes-error\" ng-if=\"model.error\">\n                        <span>{{'APP.POPUP.IMPORT.ERROR' | translate}} <span ng-if=\"model.errorMessage\"> : </span>{{model.errorMessage}}</span>\n                    </div>\n                </div>\n            </div>\n        </div>\n    </div>\n</div>\n"
  },
  {
    "path": "flowable-ui-web/modeler/views/popup/casemodel-create.html",
    "content": "\n<div class=\"modal\" ng-controller=\"CreateNewCaseModelModelCtrl\">\n\t<div class=\"modal-dialog\">\n\t\t<div class=\"modal-content\">\n\t\t\t<div class=\"modal-header\"><h2>{{'CASE.POPUP.CREATE-TITLE' | translate}}</h2></div>\n\t\t\t<div class=\"modal-body\">\n\t\t\t\t<p>{{'PROCESS.POPUP.CREATE-DESCRIPTION' | translate}}</p>\n\t\t\t\t<div ng-if=\"model.errorMessage && model.errorMessage.length > 0\" class=\"alert error\" style=\"font-size: 14px; margin-top:20px\">\n                  <div class=\"popup-error\" style=\"font-size: 14px\">\n                    <span class=\"glyphicon glyphicon-remove-circle\"></span>\n                    <span>{{model.errorMessage}}</span>\n                  </div>\n                </div>\n\t\t\t\t<div class=\"form-group\">\n\t\t\t\t    <label for=\"newCaseModelName\">{{'CASE.NAME' | translate}}</label>\n\t\t\t\t    <input ng-disabled=\"model.loading\" type=\"text\" class=\"form-control\"\n\t\t\t               id=\"newCaseModelName\" ng-model=\"model.caseModel.name\" auto-focus editor-input-check>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"form-group\">\n\t\t\t\t    <label for=\"newCaseModelKey\">{{'CASE.KEY' | translate}}</label>\n\t\t\t\t    <input ng-disabled=\"model.loading\" type=\"text\" class=\"form-control\"\n\t\t\t               id=\"newCaseModelKey\" ng-model=\"model.caseModel.key\" editor-input-check>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"form-group\">\n\t\t\t\t    <label for=\"newCaseModelDescription\">{{'CASE.DESCRIPTION' | translate}}</label>\n\t\t\t\t\t<textarea ng-disabled=\"model.loading\" class=\"form-control\" id=\"newCaseModelDescription\" rows=\"5\" ng-model=\"model.caseModel.description\"></textarea>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t\n\t\t\t<div class=\"modal-footer\">\n\t\t\t\t<div class=\"pull-right\">\n\t\t\t\t\t<button type=\"button\" class=\"btn btn-sm btn-default\" ng-click=\"cancel()\" ng-disabled=\"model.loading\">\n\t\t\t\t\t\t{{'GENERAL.ACTION.CANCEL' | translate}}\n\t\t\t\t\t</button>\n\t\t\t\t\t<button type=\"button\" class=\"btn btn-sm btn-default\" ng-click=\"ok()\" ng-disabled=\"model.loading || !model.caseModel.name || model.caseModel.name.length == 0 || !model.caseModel.key || model.caseModel.key.length == 0\">\n\t\t\t\t\t\t{{'PROCESS.ACTION.CREATE-CONFIRM' | translate}}\n\t\t\t\t\t</button>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"loading pull-right\" ng-show=\"model.loading\">\n\t\t\t\t\t<div class=\"l1\"></div><div class=\"l2\"></div><div class=\"l2\"></div>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</div>\n\t</div>\n</div>"
  },
  {
    "path": "flowable-ui-web/modeler/views/popup/casemodel-duplicate.html",
    "content": "<div class=\"modal\" ng-controller=\"DuplicateCaseModelCtrl\">\n\t<div class=\"modal-dialog\">\n\t\t<div class=\"modal-content\">\n\t\t\t<div class=\"modal-header\"><h2>{{'CASE.POPUP.DUPLICATE-TITLE' | translate}}</h2></div>\n\t\t\t<div class=\"modal-body\">\n\t\t\t\t<p>{{'CASE.POPUP.DUPLICATE-DESCRIPTION' | translate}}</p>\n\t\t\t\t<div ng-if=\"model.errorMessage && model.errorMessage.length > 0\" class=\"alert error\" style=\"font-size: 14px; margin-top:20px\">\n                  <div class=\"popup-error\" style=\"font-size: 14px\">\n                    <span class=\"glyphicon glyphicon-remove-circle\"></span>\n                    <span>{{model.errorMessage}}</span>\n                  </div>\n                </div>\n\t\t\t\t<div class=\"form-group\">\n\t\t\t\t    <label for=\"newCaseName\">{{'CASE.NAME' | translate}}</label>\n\t\t\t\t    <input ng-disabled=\"model.loading\" type=\"text\" class=\"form-control\"\n\t\t\t               id=\"newCaseName\" ng-model=\"model.caseModel.name\" ui-keypress=\"{13:'ok()'}\" auto-focus editor-input-check>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"form-group\">\n                    <label for=\"newCaseModelKey\">{{'CASE.KEY' | translate}}</label>\n                    <input ng-disabled=\"model.loading\" type=\"text\" class=\"form-control\"\n                           id=\"newCaseModelKey\" ng-model=\"model.caseModel.key\" editor-input-check>\n                </div>\n\t\t\t\t<div class=\"form-group\">\n\t\t\t\t    <label for=\"newCaseDescription\">{{'CASE.DESCRIPTION' | translate}}</label>\n\t\t\t\t\t<textarea ng-disabled=\"model.loading\" class=\"form-control\" id=\"newCaseDescription\" rows=\"5\" ng-model=\"model.caseModel.description\"></textarea>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t\n\t\t\t<div class=\"modal-footer\">\n\t\t\t\t<div class=\"pull-right\">\n\t\t\t\t\t<button type=\"button\" class=\"btn btn-sm btn-default\" ng-click=\"cancel()\" ng-disabled=\"model.loading\">\n\t\t\t\t\t\t{{'GENERAL.ACTION.CANCEL' | translate}}\n\t\t\t\t\t</button>\n\t\t\t\t\t<button type=\"button\" class=\"btn btn-sm btn-default\" ng-click=\"ok()\"ng-disabled=\"model.loading || !model.caseModel.name\">\n\t\t\t\t\t\t{{'CASE.ACTION.DUPLICATE-CONFIRM' | translate}}\n\t\t\t\t\t</button>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"loading pull-right\" ng-show=\"model.loading\">\n\t\t\t\t\t<div class=\"l1\"></div><div class=\"l2\"></div><div class=\"l2\"></div>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</div>\n\t</div>\n</div>"
  },
  {
    "path": "flowable-ui-web/modeler/views/popup/casemodel-import.html",
    "content": "\n<div class=\"modal\" ng-controller=\"ImportCaseModelCtrl\">\n    <div class=\"modal-dialog\">\n        <div class=\"modal-content\">\n            <div class=\"modal-header-wrapper\">\n            \t<div class=\"modal-header\">\n            \t\t<div class=\"pull-right\">\n                        <a class=\"action\" ng-click=\"cancel()\">&times; {{'GENERAL.ACTION.CANCEL' | translate}}</a>\n                    </div>\n            \t\t<h2>{{'CASE.POPUP.IMPORT-TITLE' | translate}}</h2>\n            \t</div>\n            </div>\n            <div class=\"modal-body\">\n\n                <p>\n                    <i class=\"glyphicon glyphicon-info-sign\"></i>\n                    {{'CASE.POPUP.IMPORT-DESCRIPTION' | translate}}\n                </p>\n                <!--[if IE 9]>\n\n                <div class=\"import-case-form\">\n\n                    <input type=\"file\" ngf-select=\"\" ngf-change=\"onFileSelect($files, true)\" style=\"font-size: smaller; padding-top:6px;\" >\n                    <div class=\"import-process-dropbox\"\n                         ngf-drop=\"onFileSelect($files)\"\n                         ngf-drag-over-class=\"dragover\"\n                         ng-show=\"dropSupported\">\n                        {{'CASE.POPUP.IMPORT.DROPZONE' | translate}}\n                    </div>\n                    <div ngf-drop-available=\"dropSupported=true\"\n                         ng-show=\"!dropSupported\">{{'CASE.POPUP.IMPORT.NO-DROP' | translate}}</div>\n                    <div class=\"graph-wrapper\" ng-show=\"status.loading\" style=\"margin: 10px 0 10px 0\">\n                        <div class=\"graph-bar\" ng-style=\"{width: model.uploadProgress + '%'}\"></div>\n                    </div>\n                    <button class=\"btn btn-danger btn-sm\"\n                            ng-click=\"upload.abort()\"\n                            ng-disabled=\"!status.loading\"\n                            style=\"margin-bottom: 20px\">\n                        {{'CASE.POPUP.IMPORT.CANCEL-UPLOAD' | translate}}\n                    </button>\n\n                </div>\n                <![endif]-->\n                <!--[if gt IE 9]> <!-- -->\n                <div class=\"import-case-form\">\n\n                    <input type=\"file\" ngf-select=\"\" ngf-change=\"onFileSelect($files)\" style=\"font-size: smaller; padding-top:6px;\" >\n                    <div class=\"import-process-dropbox\"\n                         ngf-drop ngf-change=\"onFileSelect($files)\"\n                         ngf-drag-over-class=\"dragover\"\n                         ng-show=\"dropSupported\">\n                        {{'CASE.POPUP.IMPORT.DROPZONE' | translate}}\n                    </div>\n                    <div ngf-drop-available=\"dropSupported=true\"\n                         ng-show=\"!dropSupported\">{{'CASE.POPUP.IMPORT.NO-DROP' | translate}}</div>\n                    <div class=\"graph-wrapper\" ng-show=\"status.loading\" style=\"margin: 10px 0 10px 0\">\n                        <div class=\"graph-bar\" ng-style=\"{width: model.uploadProgress + '%'}\"></div>\n                    </div>\n                    <button class=\"btn btn-danger btn-sm\"\n                            ng-click=\"upload.abort()\"\n                            ng-disabled=\"!status.loading\"\n                            style=\"margin-bottom: 20px\">\n                        {{'CASE.POPUP.IMPORT.CANCEL-UPLOAD' | translate}}\n                    </button>\n                </div>\n\n                <!-- <![endif]-->\n            </div>\n\n            <div class=\"modal-footer-wrapper\">\n                <div class=\"modal-footer\">\n                    <loading></loading>\n                    <div class=\"pull-right modeler-processes-error\" ng-if=\"model.error\">\n                        <span>{{'CASE.POPUP.IMPORT.ERROR' | translate}} <span ng-if=\"model.errorMessage\"> : </span>{{model.errorMessage}}</span>\n                    </div>\n                </div>\n            </div>\n        </div>\n    </div>\n</div>\n"
  },
  {
    "path": "flowable-ui-web/modeler/views/popup/decision-table-create.html",
    "content": "\n<div class=\"modal\" ng-controller=\"CreateNewDecisionTableCtrl\">\n\t<div class=\"modal-dialog\">\n\t\t<div class=\"modal-content\">\n\t\t\t<div class=\"modal-header\"><h2>{{'DECISION-TABLE.POPUP.CREATE-TITLE' | translate}}</h2></div>\n\t\t\t<div class=\"modal-body\">\n\t\t\t\t<p>{{'DECISION-TABLE.POPUP.CREATE-DESCRIPTION' | translate}}</p>\n\t\t\t\t<div ng-if=\"model.errorMessage && model.errorMessage.length > 0\" class=\"alert error\" style=\"font-size: 14px; margin-top:20px\">\n                  <div class=\"popup-error\" style=\"font-size: 14px\">\n                    <span class=\"glyphicon glyphicon-remove-circle\"></span>\n                    <span>{{model.errorMessage}}</span>\n                  </div>\n                </div>\n\t\t\t\t<div class=\"form-group\">\n\t\t\t\t    <label for=\"newDecisionTableName\">{{'DECISION-TABLE.NAME' | translate}}</label>\n\t\t\t\t    <input ng-disabled=\"model.loading\" type=\"text\" class=\"form-control\" maxlength=\"400\"\n\t\t\t               id=\"newDecisionTableName\" ng-model=\"model.decisionTable.name\" custom-keys enter-pressed=\"ok()\" auto-focus editor-input-check>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"form-group\">\n\t\t\t\t    <label for=\"newDecisionTableKey\">{{'DECISION-TABLE.KEY' | translate}}</label>\n\t\t\t\t    <input ng-disabled=\"model.loading\" type=\"text\" class=\"form-control\" maxlength=\"255\"\n\t\t\t               id=\"newDecisionTableKey\" ng-model=\"model.decisionTable.key\" editor-input-check>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"form-group\">\n\t\t\t\t    <label for=\"newDecisionTableDescription\">{{'DECISION-TABLE.DESCRIPTION' | translate}}</label>\n\t\t\t\t\t<textarea ng-disabled=\"model.loading\" class=\"form-control\" id=\"newDecisionTableDescription\" rows=\"5\" ng-model=\"model.decisionTable.description\"></textarea>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t\n\t\t\t<div class=\"modal-footer\">\n\t\t\t\t<div class=\"pull-right\">\n\t\t\t\t\t<button type=\"button\" class=\"btn btn-sm btn-default\" ng-click=\"cancel()\" ng-disabled=\"model.loading\">\n\t\t\t\t\t\t{{'GENERAL.ACTION.CANCEL' | translate}}\n\t\t\t\t\t</button>\n\t\t\t\t\t<button type=\"button\" class=\"btn btn-sm btn-default\" ng-click=\"ok()\" ng-disabled=\"model.loading || !model.decisionTable.name || model.decisionTable.name.length == 0 || !model.decisionTable.key || model.decisionTable.key.length == 0\">\n\t\t\t\t\t\t{{'DECISION-TABLE.ACTION.CREATE-CONFIRM' | translate}}\n\t\t\t\t\t</button>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"loading pull-right\" ng-show=\"model.loading\">\n\t\t\t\t\t<div class=\"l1\"></div><div class=\"l2\"></div><div class=\"l2\"></div>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</div>\n\t</div>\n</div>"
  },
  {
    "path": "flowable-ui-web/modeler/views/popup/decision-table-duplicate.html",
    "content": "\n<div class=\"modal\" ng-controller=\"DuplicateDecisionTableCtrl\">\n\t<div class=\"modal-dialog\">\n\t\t<div class=\"modal-content\">\n\t\t\t<div class=\"modal-header\"><h2>{{'DECISION-TABLE.POPUP.DUPLICATE-TITLE' | translate}}</h2></div>\n\t\t\t<div class=\"modal-body\">\n\t\t\t\t<p>{{'DECISION-TABLE.POPUP.DUPLICATE-DESCRIPTION' | translate}}</p>\n\t\t\t\t<div ng-if=\"model.errorMessage && model.errorMessage.length > 0\" class=\"alert error\" style=\"font-size: 14px; margin-top:20px\">\n                  <div class=\"popup-error\" style=\"font-size: 14px\">\n                    <span class=\"glyphicon glyphicon-remove-circle\"></span>\n                    <span>{{model.errorMessage}}</span>\n                  </div>\n                </div>\n\t\t\t\t<div class=\"form-group\">\n\t\t\t\t    <label for=\"newDecisionTableName\">{{'DECISION-TABLE.NAME' | translate}}</label>\n\t\t\t\t    <input ng-disabled=\"model.loading\" type=\"text\" class=\"form-control\" maxlength=\"400\"\n\t\t\t               id=\"newDecisionTableName\" ng-model=\"model.decisionTable.name\" custom-keys enter-pressed=\"ok()\" auto-focus editor-input-check>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"form-group\">\n\t\t\t\t    <label for=\"newDecisionTableKey\">{{'DECISION-TABLE.KEY' | translate}}</label>\n\t\t\t\t    <input ng-disabled=\"model.loading\" type=\"text\" class=\"form-control\" maxlength=\"255\"\n\t\t\t               id=\"newDecisionTableKey\" ng-model=\"model.decisionTable.key\" editor-input-check>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"form-group\">\n\t\t\t\t    <label for=\"newDecisionTableDescription\">{{'DECISION-TABLE.DESCRIPTION' | translate}}</label>\n\t\t\t\t\t<textarea ng-disabled=\"model.loading\" class=\"form-control\" id=\"newDecisionTableDescription\" rows=\"5\" ng-model=\"model.decisionTable.description\"></textarea>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t\n\t\t\t<div class=\"modal-footer\">\n\t\t\t\t<div class=\"pull-right\">\n\t\t\t\t\t<button type=\"button\" class=\"btn btn-sm btn-default\" ng-click=\"cancel()\" ng-disabled=\"model.loading\">\n\t\t\t\t\t\t{{'GENERAL.ACTION.CANCEL' | translate}}\n\t\t\t\t\t</button>\n\t\t\t\t\t<button type=\"button\" class=\"btn btn-sm btn-default\" ng-click=\"ok()\" ng-disabled=\"model.loading || !model.decisionTable.name || model.decisionTable.name.length == 0 || !model.decisionTable.key || model.decisionTable.key.length == 0\">\n\t\t\t\t\t\t{{'DECISION-TABLE.ACTION.CREATE-CONFIRM' | translate}}\n\t\t\t\t\t</button>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"loading pull-right\" ng-show=\"model.loading\">\n\t\t\t\t\t<div class=\"l1\"></div><div class=\"l2\"></div><div class=\"l2\"></div>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</div>\n\t</div>\n</div>"
  },
  {
    "path": "flowable-ui-web/modeler/views/popup/decision-table-edit-hit-policy.html",
    "content": "<div class=\"modal\" ng-controller=\"DecisionTableHitPolicyEditorCtrl\">\n    <div class=\"modal-dialog\">\n        <div class=\"modal-content\">\n            <form name=\"inputExpressionForm\">\n                <div class=\"modal-header\"><h2>Select Decision Table Hit Policy</h2>\n                </div>\n                <div class=\"modal-body\">\n\n                    <!--Column name start-->\n                    <div class=\"clearfix form-group\">\n                        <div class=\"col-xs-4\">\n                            <label>Hit Policy</label>\n                        </div>\n                        <div ng-if=\"!model.readOnly\"  class=\"col-xs-8\">\n                            <select class=\"form-control\" name=\"hitPolicy\" id=\"hitPolicy\" ng-model=\"popup.currentHitPolicy\">\n                                <option ng-selected=\"{{option.id == popup.currentHitPolicy}}\"\n                                        ng-repeat=\"option in popup.availableHitPolicies\" value=\"{{option.id}}\">\n                                    {{option.label | translate}}\n                                </option>\n                            </select>\n                        </div>\n                        <div ng-if=\"model.readOnly\"  class=\"col-xs-8\">\n                            <div>{{popup.currentHitPolicy}}</div>\n                        </div>\n                        <div class=\"col-xs-12\"><br/></div>\n                        <div ng-if=\"popup.currentHitPolicy === 'COLLECT'\" class=\"col-xs-4\">\n                            <label>Collect operator</label>\n                        </div>\n                        <div ng-if=\"popup.currentHitPolicy === 'COLLECT' && !model.readOnly\"  class=\"col-xs-8\">\n                            <select class=\"form-control\" name=\"collectOperator\" id=\"collectOperator\" ng-model=\"popup.currentCollectOperator\">\n                                <option value=\"\" selected=\"selected\">None</option>\n                                <option ng-selected=\"{{option.id == popup.currentCollectOperator}}\"\n                                        ng-repeat=\"option in popup.availableCollectOperators\" value=\"{{option.id}}\">\n                                    {{option.label | translate}}\n                                </option>\n                            </select>\n                        </div>\n                        <div ng-if=\"popup.currentHitPolicy === 'COLLECT' && model.readOnly\"  class=\"col-xs-8\">\n                            <div>{{popup.currentCollectOperator}}</div>\n                        </div>\n                    </div>\n                </div>\n\n                <div class=\"modal-footer\">\n                    <div class=\"pull-right\">\n                        <button type=\"button\" class=\"btn btn-sm btn-default\" ng-click=\"cancel()\">\n                            {{'GENERAL.ACTION.CANCEL' | translate}}\n                        </button>\n                        <button ng-if=\"!model.readOnly\" type=\"button\" class=\"btn btn-sm btn-default\" ng-click=\"save()\"\n                                ng-disabled=\"!inputExpressionForm.$valid || readOnly\">\n                            {{'GENERAL.ACTION.SAVE' | translate}}\n                        </button>\n                    </div>\n                    <div class=\"loading pull-right\" ng-show=\"model.loading\">\n                        <div class=\"l1\"></div>\n                        <div class=\"l2\"></div>\n                        <div class=\"l2\"></div>\n                    </div>\n                </div>\n            </form>\n        </div>\n    </div>\n</div>\n"
  },
  {
    "path": "flowable-ui-web/modeler/views/popup/decision-table-edit-input-expression.html",
    "content": "<div class=\"modal\" ng-controller=\"DecisionTableInputConditionEditorCtlr\">\n    <div class=\"modal-dialog\">\n        <div class=\"modal-content\">\n            <form name=\"inputExpressionForm\">\n                <div class=\"modal-header\"><h2>{{'DECISION-TABLE-EDITOR.POPUP.EXPRESSION-EDITOR.INPUT-TITLE' |\n                    translate}}</h2>\n                    <p>{{'DECISION-TABLE-EDITOR.POPUP.EXPRESSION-EDITOR.INPUT-DESCRIPTION' | translate}}</p>\n                </div>\n                <div class=\"modal-body\">\n\n                    <div class=\"clearfix form-group\"\n                         ng-class=\"{'has-error': inputExpressionForm.expressionLabel.$invalid}\">\n                        <div class=\"col-xs-4\">\n                            <label>{{'DECISION-TABLE-EDITOR.POPUP.EXPRESSION-EDITOR.EXPRESSION-LABEL' |\n                                translate}}</label>\n                        </div>\n                        <div class=\"col-xs-8\">\n                            <input class=\"form-control\" name=\"expressionLabel\"\n                                   placeholder=\"{{'DECISION-TABLE-EDITOR.POPUP.EXPRESSION-EDITOR.EXPRESSION-PLACEHOLDER' | translate}}\"\n                                   type=\"text\" ng-model=\"popup.selectedExpressionLabel\" ng-disabled=\"model.readOnly\"/>\n                        </div>\n                    </div>\n\n                    <div>\n                        <div>\n                            <div class=\"clearfix form-group\"\n                                 ng-class=\"{'has-error': inputExpressionForm.variableId.$invalid}\">\n                                <div class=\"col-xs-4\">\n                                    <label>{{'DECISION-TABLE-EDITOR.POPUP.EXPRESSION-EDITOR.EXPRESSION-VARIABLE-NAME' |\n                                        translate}}</label><span class=\"marker\">*</span>\n                                </div>\n                                <div class=\"col-xs-8\">\n                                    <input class=\"form-control\"\n                                           placeholder=\"{{'DECISION-TABLE-EDITOR.POPUP.EXPRESSION-EDITOR.EXPRESSION-VARIABLE-NAME-PLACEHOLDER' | translate}}\"\n                                           type=\"text\" ng-required=\"true\" name=\"variableId\"\n                                           ng-model=\"popup.selectedExpressionVariableId\" ng-disabled=\"model.readOnly\"/>\n                                </div>\n                            </div>\n                        </div>\n                    </div>\n\n                    <div class=\"clearfix form-group\"\n                         ng-class=\"{'has-error': inputExpressionForm.variableType.$invalid}\">\n                        <div class=\"col-xs-4\">\n                            <label>{{'DECISION-TABLE-EDITOR.POPUP.EXPRESSION-EDITOR.EXPRESSION-VARIABLE-TYPE' |\n                                translate}}</label><span class=\"marker\">*</span>\n                        </div>\n                        <div class=\"col-xs-8\">\n                            <select class=\"form-control\" ng-options=\"type for type in model.availableInputVariableTypes\"\n                                    ng-model=\"popup.selectedExpressionVariableType\" name=\"variableType\"\n                                    ng-required=\"true\" ng-disabled=\"model.readOnly\"/>\n                        </div>\n                    </div>\n\n                    <div ng-if=\"popup.selectedExpressionVariableType != 'collection'\">\n                        <div class=\"clearfix form-group\">\n                            <div class=\"col-xs-4\">\n                                <label>{{'DECISION-TABLE-EDITOR.POPUP.EXPRESSION-EDITOR.ALLOWED-VALUES' |\n                                    translate}}</label>\n                            </div>\n                            <div ng-if=\"!model.readOnly\" class=\"col-xs-8\">\n                                <hot-table hot-auto-destroy\n                                        hot-id=\"decision-table-allowed-values\"\n                                        settings=\"popup.hotSettings\"\n                                        datarows=\"popup.selectedExpressionInputValues\"\n                                        columns=\"popup.columnDefs\"\n                                        row-heights=\"30\"\n                                        class-name=\"'htMiddle'\"\n                                        min-spare-rows=\"1\"\n                                        read-only=\"model.readOnly\">\n                                </hot-table>\n                            </div>\n                            <div ng-if=\"model.readOnly\" class=\"col-xs-8\">\n                                <div ng-repeat=\"allowedValue in popup.selectedExpressionInputValues\"><span style=\"font-size: 14px\">{{allowedValue[0]}}</span><br></div>\n                            </div>\n                        </div>\n                    </div>\n\n                </div>\n\n                <div class=\"modal-footer\">\n                    <div class=\"pull-right\">\n                        <button type=\"button\" class=\"btn btn-sm btn-default\" ng-click=\"cancel()\">\n                            {{'GENERAL.ACTION.CANCEL' | translate}}\n                        </button>\n                        <button ng-if=\"!model.readOnly\" type=\"button\" class=\"btn btn-sm btn-default\" ng-click=\"save()\"\n                                ng-disabled=\"!inputExpressionForm.$valid\">\n                            {{'GENERAL.ACTION.SAVE' | translate}}\n                        </button>\n                    </div>\n                    <div class=\"loading pull-right\" ng-show=\"model.loading\">\n                        <div class=\"l1\"></div>\n                        <div class=\"l2\"></div>\n                        <div class=\"l2\"></div>\n                    </div>\n                </div>\n            </form>\n        </div>\n    </div>\n</div>\n"
  },
  {
    "path": "flowable-ui-web/modeler/views/popup/decision-table-edit-output-expression.html",
    "content": "<div class=\"modal\" ng-controller=\"DecisionTableConclusionEditorCtrl\">\n    <div class=\"modal-dialog\">\n        <div class=\"modal-content\">\n            <form name=\"outputExpressionForm\">\n                <div class=\"modal-header\"><h2>{{'DECISION-TABLE-EDITOR.POPUP.EXPRESSION-EDITOR.OUTPUT-TITLE' |\n                    translate}}</h2>\n                    <p>{{'DECISION-TABLE-EDITOR.POPUP.EXPRESSION-EDITOR.OUTPUT-DESCRIPTION' | translate}}</p>\n                </div>\n                <div class=\"modal-body\">\n                    <div class=\"clearfix form-group\"\n                         ng-class=\"{'has-error': outputExpressionForm.expressionLabel.$invalid}\">\n                        <div class=\"col-xs-4\">\n                            <label>{{'DECISION-TABLE-EDITOR.POPUP.EXPRESSION-EDITOR.EXPRESSION-LABEL' |\n                                translate}}</label>\n                        </div>\n                        <div class=\"col-xs-8\">\n                            <input class=\"form-control\" name=\"expressionLabel\"\n                                   placeholder=\"{{'DECISION-TABLE-EDITOR.POPUP.EXPRESSION-EDITOR.EXPRESSION-PLACEHOLDER' | translate}}\"\n                                   type=\"text\" ng-model=\"popup.selectedExpressionLabel\" ng-disabled=\"model.readOnly\"/>\n                        </div>\n                    </div>\n\n                    <div class=\"clearfix form-group\"\n                         ng-class=\"{'has-error': outputExpressionForm.variableId.$invalid}\">\n                        <div class=\"col-xs-4\">\n                            <label>{{'DECISION-TABLE-EDITOR.POPUP.EXPRESSION-EDITOR.OUTPUT-NEW-VARIABLE-ID' |\n                                translate}}</label><span class=\"marker\">*</span>\n                        </div>\n                        <div class=\"col-xs-8\">\n                            <input class=\"form-control\" name=\"variableId\" placeholder=\"Enter variable id\" type=\"text\"\n                                   ng-model=\"popup.selectedExpressionNewVariableId\" ng-required=\"true\" variable-identifier ng-disabled=\"model.readOnly\"/>\n                        </div>\n                    </div>\n\n                    <div class=\"clearfix form-group\"\n                         ng-class=\"{'has-error': outputExpressionForm.newVariable.$invalid}\">\n                        <div class=\"col-xs-4\">\n                            <label>{{'DECISION-TABLE-EDITOR.POPUP.EXPRESSION-EDITOR.OUTPUT-NEW-VARIABLE-TYPE' |\n                                translate}}</label>\n                        </div>\n                        <div class=\"col-xs-8\">\n                            <select class=\"form-control\" ng-options=\"type for type in model.availableOutputVariableTypes\"\n                                    ng-model=\"popup.selectedExpressionNewVariableType\" name=\"newVariable\"\n                                    ng-required=\"true\" ng-disabled=\"model.readOnly\"/>\n                        </div>\n                    </div>\n\n                    <div>\n                        <div class=\"clearfix form-group\">\n                            <div class=\"col-xs-4\">\n                                <label>{{'DECISION-TABLE-EDITOR.POPUP.EXPRESSION-EDITOR.OUTPUT-VALUES' |\n                                    translate}}\n                                    <span ng-if=\"popup.currentHitPolicy === 'PRIORITY' || popup.currentHitPolicy === 'OUTPUT ORDER'\">{{'DECISION-TABLE-EDITOR.POPUP.EXPRESSION-EDITOR.OUTPUT-VALUES-NOT-OPTIONAL' |\n                                    translate}}</span>\n                                    <span ng-if=\"popup.currentHitPolicy !== 'PRIORITY' && popup.currentHitPolicy !== 'OUTPUT ORDER'\">{{'DECISION-TABLE-EDITOR.POPUP.EXPRESSION-EDITOR.OUTPUT-VALUES-OPTIONAL' |\n                                    translate}}</span>\n                                </label>\n                            </div>\n                            <div ng-if=\"!model.readOnly\" class=\"col-xs-8\">\n                                <hot-table hot-auto-destroy\n                                        hot-id=\"decision-table-allowed-values\"\n                                        settings=\"popup.hotSettings\"\n                                        datarows=\"popup.selectedExpressionOutputValues\"\n                                        columns=\"popup.columnDefs\"\n                                        row-headers=\"true\"\n                                        manual-row-move=\"true\"\n                                        row-heights=\"30\"\n                                        class-name=\"'htMiddle'\"\n                                        on-after-render=doAfterRender\n                                        min-spare-rows=\"1\"\n                                        read-only=\"model.readOnly\">\n                                </hot-table>\n                            </div>\n                            <div ng-if=\"model.readOnly\" class=\"col-xs-8\">\n                                <div ng-repeat=\"allowedValue in popup.selectedExpressionOutputValues\"><span style=\"font-size: 14px\">{{allowedValue[0]}}</span><br></div>\n                            </div>\n                        </div>\n                    </div>\n                </div>\n\n                <div class=\"modal-footer\">\n                    <div class=\"pull-right\">\n                        <button type=\"button\" class=\"btn btn-sm btn-default\" ng-click=\"cancel()\">\n                            {{'GENERAL.ACTION.CANCEL' | translate}}\n                        </button>\n                        <button ng-if=\"!model.readOnly\" type=\"button\" class=\"btn btn-sm btn-default\" ng-click=\"save()\"\n                                ng-disabled=\"!outputExpressionForm.$valid\">\n                            {{'GENERAL.ACTION.SAVE' | translate}}\n                        </button>\n                    </div>\n                    <div class=\"loading pull-right\" ng-show=\"model.loading\">\n                        <div class=\"l1\"></div>\n                        <div class=\"l2\"></div>\n                        <div class=\"l2\"></div>\n                    </div>\n                </div>\n            </form>\n        </div>\n    </div>\n</div>"
  },
  {
    "path": "flowable-ui-web/modeler/views/popup/decision-table-import.html",
    "content": "\n<div class=\"modal\" ng-controller=\"ImportDecisionTableModelCtrl\">\n    <div class=\"modal-dialog\">\n        <div class=\"modal-content\">\n            <div class=\"modal-header-wrapper\">\n            \t<div class=\"modal-header\">\n            \t\t<div class=\"pull-right\">\n                        <a class=\"action\" ng-click=\"cancel()\">&times; {{'GENERAL.ACTION.CANCEL' | translate}}</a>\n                    </div>\n            \t\t<h2>{{'DECISION-TABLE.POPUP.IMPORT-TITLE' | translate}}</h2>\n            \t</div>\n            </div>\n            <div class=\"modal-body\">\n\n                <p>\n                    <i class=\"glyphicon glyphicon-info-sign\"></i>\n                    {{'DECISION-TABLE.POPUP.IMPORT-DESCRIPTION' | translate}}\n                </p>\n                <!--[if IE 9]>\n\n                <div class=\"import-process-form\">\n\n                    <input type=\"file\" ngf-select=\"\" ngf-change=\"onFileSelect($files, true)\" style=\"font-size: smaller; padding-top:6px;\" >\n                    <div class=\"import-process-dropbox\"\n                         ngf-drop=\"onFileSelect($files)\"\n                         ngf-drag-over-class=\"dragover\"\n                         ng-show=\"dropSupported\">\n                        {{'DECISION-TABLE.POPUP.IMPORT.DROPZONE' | translate}}\n                    </div>\n                    <div ngf-drop-available=\"dropSupported=true\"\n                         ng-show=\"!dropSupported\">{{'DECISION-TABLE.POPUP.IMPORT.NO-DROP' | translate}}</div>\n                    <div class=\"graph-wrapper\" ng-show=\"status.loading\" style=\"margin: 10px 0 10px 0\">\n                        <div class=\"graph-bar\" ng-style=\"{width: model.uploadProgress + '%'}\"></div>\n                    </div>\n                    <button class=\"btn btn-danger btn-sm\"\n                            ng-click=\"upload.abort()\"\n                            ng-disabled=\"!status.loading\"\n                            style=\"margin-bottom: 20px\">\n                        {{'DECISION-TABLE.POPUP.IMPORT.CANCEL-UPLOAD' | translate}}\n                    </button>\n\n                </div>\n                <![endif]-->\n                <!--[if gt IE 9]> <!-- -->\n                <div class=\"import-process-form\">\n\n                    <input type=\"file\" ngf-select=\"\" ngf-change=\"onFileSelect($files)\" style=\"font-size: smaller; padding-top:6px;\" >\n                    <div class=\"import-process-dropbox\"\n                         ngf-drop ngf-change=\"onFileSelect($files)\"\n                         ngf-drag-over-class=\"dragover\"\n                         ng-show=\"dropSupported\">\n                        {{'DECISION-TABLE.POPUP.IMPORT.DROPZONE' | translate}}\n                    </div>\n                    <div ngf-drop-available=\"dropSupported=true\"\n                         ng-show=\"!dropSupported\">{{'DECISION-TABLE.POPUP.IMPORT.NO-DROP' | translate}}</div>\n                    <div class=\"graph-wrapper\" ng-show=\"status.loading\" style=\"margin: 10px 0 10px 0\">\n                        <div class=\"graph-bar\" ng-style=\"{width: model.uploadProgress + '%'}\"></div>\n                    </div>\n                    <button class=\"btn btn-danger btn-sm\"\n                            ng-click=\"upload.abort()\"\n                            ng-disabled=\"!status.loading\"\n                            style=\"margin-bottom: 20px\">\n                        {{'DECISION-TABLE.POPUP.IMPORT.CANCEL-UPLOAD' | translate}}\n                    </button>\n                </div>\n\n                <!-- <![endif]-->\n            </div>\n\n            <div class=\"modal-footer-wrapper\">\n                <div class=\"modal-footer\">\n                    <loading></loading>\n                    <div class=\"pull-right modeler-processes-error\" ng-if=\"model.error\">\n                        <span>{{'DECISION-TABLE.POPUP.IMPORT.ERROR' | translate}} <span ng-if=\"model.errorMessage\"> : </span>{{model.errorMessage}}</span>\n                    </div>\n                </div>\n            </div>\n        </div>\n    </div>\n</div>\n"
  },
  {
    "path": "flowable-ui-web/modeler/views/popup/decision-table-save-model.html",
    "content": "<div class=\"modal\" ng-controller=\"SaveDecisionTableCtrl\">\n    <div class=\"modal-dialog\">\n        <div class=\"modal-content\">\n            <form name=\"decisionTableForm\">\n                <div class=\"modal-header\"><h2>{{'DECISION-TABLE.POPUP.SAVE-DECISION-TABLE-TITLE' | translate}}</h2></div>\n                <div class=\"modal-body\">\n                    <p>{{'DECISION-TABLE.POPUP.SAVE-DESCRIPTION' | translate}}</p>\n                    <div ng-if=\"saveDialog.errorMessage && saveDialog.errorMessage.length > 0\" class=\"alert error\" style=\"font-size: 14px; margin-top:20px\">\n\t                  <div class=\"popup-error\" style=\"font-size: 14px\">\n\t                    <span class=\"glyphicon glyphicon-remove-circle\"></span>\n\t                    <span>{{saveDialog.errorMessage}}</span>\n\t                  </div>\n\t                </div>\n                    <div class=\"form-group\"  ng-class=\"{'has-error': decisionTableForm.name.$invalid}\">\n                        <label for=\"decisiontableName\">{{'DECISION-TABLE.NAME' | translate}}</label>\n                        <input ng-disabled=\"model.loading\" type=\"text\" class=\"form-control\" name=\"name\" ng-required=\"true\"\n                               id=\"decisiontableName\" ng-model=\"saveDialog.name\" maxlength=\"400\" auto-focus editor-input-check>\n                    </div>\n                    <div class=\"form-group\" ng-class=\"{'has-error': decisionTableForm.key.$invalid}\">\n                        <label for=\"decisiontableKey\">{{'DECISION-TABLE.KEY' | translate}}</label>\n                        <input ng-disabled=\"model.loading\" type=\"text\" class=\"form-control\" name=\"key\" maxlength=\"255\" ng-required=\"true\"\n                               id=\"decisiontableKey\" data-ng-trim=\"false\" spaceless-value ng-model=\"saveDialog.key\"\n                               editor-input-check ng-pattern=\"keyFieldPattern\" >\n                    </div>\n                    <div class=\"form-group\">\n                        <label for=\"decisiontableDescription\">{{'DECISION-TABLE.DESCRIPTION' | translate}}</label>\n                        <textarea ng-disabled=\"model.loading\" class=\"form-control\" id=\"decisiontableDescription\" rows=\"5\" ng-model=\"saveDialog.description\"></textarea>\n                    </div>\n                    <div class=\"checkbox\" ng-show=\"!error && !error.isConflict\">\n                        <label>\n                            <input type=\"checkbox\" ng-disabled=\"status.loading\" ng-model=\"saveDialog.newVersion\">\n                            {{'MODEL.SAVE.NEWVERSION' | translate}}\n                        </label>\n                    </div>\n                    <div class=\"form-group\" ng-if=\"saveDialog.newVersion\">\n                        <label for=\"commentTextArea\">{{'MODEL.SAVE.COMMENT' | translate}}</label>\n                        <textarea id=\"commentTextArea\" class=\"form-control\" ng-model=\"saveDialog.comment\" ng-disabled=\"status.loading\"></textarea>\n                    </div>\n                    <div ng-if=\"saveDialog.validationErrors\" class=\"alert error\" style=\"font-size: 14px; margin-top:20px\">\n                        <div class=\"popup-error\" style=\"font-size: 14px\">\n                            <span class=\"glyphicon glyphicon-remove-circle\"></span>\n                            <span translate=\"MODEL.VALIDATIONERRORS\" translate-values=\"error\"></span>\n                        </div>\n                    </div>\n                </div>\n\n                <div class=\"modal-footer\">\n                    <div class=\"pull-right\">\n                        <button class=\"btn btn-sm btn-default\" ng-click=\"cancel()\" ng-disabled=\"model.loading\" translate>GENERAL.ACTION.CANCEL</button>\n                        <button class=\"btn btn-primary\" ng-click=\"saveAndClose()\" ng-disabled=\"status.loading || !decisionTableForm.$valid || readOnly\" ng-show=\"!error && !error.isConflict\" translate>ACTION.SAVE-AND-CLOSE</button>\n                        <button class=\"btn btn-primary\" ng-click=\"save()\" ng-disabled=\"status.loading || !decisionTableForm.$valid || readOnly\" ng-show=\"!error && !error.isConflict\" translate>ACTION.SAVE</button>\n                    </div>\n                    <div class=\"loading pull-right\" ng-show=\"model.loading\">\n                        <div class=\"l1\"></div><div class=\"l2\"></div><div class=\"l2\"></div>\n                    </div>\n                </div>\n            </form>\n        </div>\n    </div>\n</div>"
  },
  {
    "path": "flowable-ui-web/modeler/views/popup/form-create.html",
    "content": "\n<div class=\"modal\" ng-controller=\"CreateNewFormCtrl\">\n\t<div class=\"modal-dialog\">\n\t\t<div class=\"modal-content\">\n\t\t\t<div class=\"modal-header\"><h2>{{'FORM.POPUP.CREATE-TITLE' | translate}}</h2></div>\n\t\t\t<div class=\"modal-body\">\n\t\t\t\t<p>{{'FORM.POPUP.CREATE-DESCRIPTION' | translate}}</p>\n\t\t\t\t<div ng-if=\"model.errorMessage && model.errorMessage.length > 0\" class=\"alert error\" style=\"font-size: 14px; margin-top:20px\">\n                  <div class=\"popup-error\" style=\"font-size: 14px\">\n                    <span class=\"glyphicon glyphicon-remove-circle\"></span>\n                    <span>{{model.errorMessage}}</span>\n                  </div>\n                </div>\n\t\t\t\t<div class=\"form-group\">\n\t\t\t\t    <label for=\"newFormName\">{{'FORM.NAME' | translate}}</label>\n\t\t\t\t    <input ng-disabled=\"model.loading\" type=\"text\" class=\"form-control\"\n\t\t\t               id=\"newFormName\" ng-model=\"model.form.name\" custom-keys enter-pressed=\"ok()\" auto-focus editor-input-check>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"form-group\">\n\t\t\t\t    <label for=\"newFormKey\">{{'FORM.KEY' | translate}}</label>\n\t\t\t\t    <input ng-disabled=\"model.loading\" type=\"text\" class=\"form-control\"\n\t\t\t               id=\"newFormKey\" ng-model=\"model.form.key\" editor-input-check>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"form-group\">\n\t\t\t\t    <label for=\"newFormDescription\">{{'FORM.DESCRIPTION' | translate}}</label>\n\t\t\t\t\t<textarea ng-disabled=\"model.loading\" class=\"form-control\" id=\"newFormDescription\" rows=\"5\" ng-model=\"model.form.description\"></textarea>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t\n\t\t\t<div class=\"modal-footer\">\n\t\t\t\t<div class=\"pull-right\">\n\t\t\t\t\t<button type=\"button\" class=\"btn btn-sm btn-default\" ng-click=\"cancel()\" ng-disabled=\"model.loading\">\n\t\t\t\t\t\t{{'GENERAL.ACTION.CANCEL' | translate}}\n\t\t\t\t\t</button>\n\t\t\t\t\t<button type=\"button\" class=\"btn btn-sm btn-default\" ng-click=\"ok()\"ng-disabled=\"model.loading || !model.form.name || model.form.name.length == 0 || !model.form.key || model.form.key.length == 0\">\n\t\t\t\t\t\t{{'FORM.ACTION.CREATE-CONFIRM' | translate}}\n\t\t\t\t\t</button>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"loading pull-right\" ng-show=\"model.loading\">\n\t\t\t\t\t<div class=\"l1\"></div><div class=\"l2\"></div><div class=\"l2\"></div>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</div>\n\t</div>\n</div>"
  },
  {
    "path": "flowable-ui-web/modeler/views/popup/form-duplicate.html",
    "content": "<div class=\"modal\" ng-controller=\"DuplicateFormCtrl\">\n\t<div class=\"modal-dialog\">\n\t\t<div class=\"modal-content\">\n\t\t\t<div class=\"modal-header\"><h2>{{'FORM.POPUP.DUPLICATE-TITLE' | translate}}</h2></div>\n\t\t\t<div class=\"modal-body\">\n\t\t\t\t<p>{{'FORM.POPUP.DUPLICATE-DESCRIPTION' | translate}}</p>\n\t\t\t\t<div ng-if=\"model.errorMessage && model.errorMessage.length > 0\" class=\"alert error\" style=\"font-size: 14px; margin-top:20px\">\n                  <div class=\"popup-error\" style=\"font-size: 14px\">\n                    <span class=\"glyphicon glyphicon-remove-circle\"></span>\n                    <span>{{model.errorMessage}}</span>\n                  </div>\n                </div>\n\t\t\t\t<div class=\"form-group\">\n\t\t\t\t    <label for=\"newFormName\">{{'FORM.NAME' | translate}}</label>\n\t\t\t\t    <input ng-disabled=\"model.loading\" type=\"text\" class=\"form-control\"\n\t\t\t               id=\"newFormName\" ng-model=\"model.form.name\" custom-keys enter-pressed=\"ok()\" auto-focus editor-input-check>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"form-group\">\n                    <label for=\"newFormKey\">{{'FORM.KEY' | translate}}</label>\n                    <input ng-disabled=\"model.loading\" type=\"text\" class=\"form-control\"\n                           id=\"newFormKey\" ng-model=\"model.form.key\" editor-input-check>\n                </div>\n\t\t\t\t<div class=\"form-group\">\n\t\t\t\t    <label for=\"newFormDescription\">{{'FORM.DESCRIPTION' | translate}}</label>\n\t\t\t\t\t<textarea ng-disabled=\"model.loading\" class=\"form-control\" id=\"newFormDescription\" rows=\"5\" ng-model=\"model.form.description\"></textarea>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t\n\t\t\t<div class=\"modal-footer\">\n\t\t\t\t<div class=\"pull-right\">\n\t\t\t\t\t<button type=\"button\" class=\"btn btn-sm btn-default\" ng-click=\"cancel()\" ng-disabled=\"model.loading\">\n\t\t\t\t\t\t{{'GENERAL.ACTION.CANCEL' | translate}}\n\t\t\t\t\t</button>\n\t\t\t\t\t<button type=\"button\" class=\"btn btn-sm btn-default\" ng-click=\"ok()\"ng-disabled=\"model.loading || !model.form.name\">\n\t\t\t\t\t\t{{'FORM.ACTION.DUPLICATE-CONFIRM' | translate}}\n\t\t\t\t\t</button>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"loading pull-right\" ng-show=\"model.loading\">\n\t\t\t\t\t<div class=\"l1\"></div><div class=\"l2\"></div><div class=\"l2\"></div>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</div>\n\t</div>\n</div>"
  },
  {
    "path": "flowable-ui-web/modeler/views/popup/form-save-model.html",
    "content": "\n<div class=\"modal\" ng-controller=\"SaveFormCtrl\">\n\t<div class=\"modal-dialog\">\n\t\t<div class=\"modal-content\">\n\t\t\t<div class=\"modal-header\"><h2>{{'FORM.POPUP.SAVE-FORM-TITLE' | translate}}</h2></div>\n\t\t\t<div class=\"modal-body\">\n\t\t\t\t<p>{{'FORM.POPUP.CREATE-DESCRIPTION' | translate}}</p>\n\t\t\t\t<div ng-if=\"saveDialog.errorMessage && saveDialog.errorMessage.length > 0\" class=\"alert error\" style=\"font-size: 14px; margin-top:20px\">\n                  <div class=\"popup-error\" style=\"font-size: 14px\">\n                    <span class=\"glyphicon glyphicon-remove-circle\"></span>\n                    <span>{{saveDialog.errorMessage}}</span>\n                  </div>\n                </div>\n\t\t\t\t<div class=\"form-group\">\n\t\t\t\t    <label for=\"formName\">{{'FORM.NAME' | translate}}</label>\n\t\t\t\t    <input ng-disabled=\"model.loading\" type=\"text\" class=\"form-control\"\n\t\t\t               id=\"formName\" ng-model=\"saveDialog.name\" ui-keypress=\"{13:'ok()'}\" auto-focus editor-input-check>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"form-group\">\n\t\t\t\t    <label for=\"formKey\">{{'FORM.KEY' | translate}}</label>\n\t\t\t\t    <input ng-disabled=\"model.loading\" type=\"text\" class=\"form-control\"\n\t\t\t               id=\"formKey\" ng-model=\"saveDialog.formKey\" editor-input-check>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"form-group\">\n\t\t\t\t    <label for=\"formDescription\">{{'FORM.DESCRIPTION' | translate}}</label>\n\t\t\t\t\t<textarea ng-disabled=\"model.loading\" class=\"form-control\" id=\"formDescription\" rows=\"5\" ng-model=\"saveDialog.description\"></textarea>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"checkbox\" ng-show=\"!error && !error.isConflict\">\n                    <label>\n                        <input type=\"checkbox\" ng-disabled=\"status.loading\" ng-model=\"saveDialog.newVersion\">\n                            {{'MODEL.SAVE.NEWVERSION' | translate}}\n                    </label>\n                </div>\n                <div class=\"form-group\" ng-if=\"saveDialog.newVersion\">\n                    <label for=\"commentTextArea\">{{'MODEL.SAVE.COMMENT' | translate}}</label>\n                    <textarea id=\"commentTextArea\" class=\"form-control\" ng-model=\"saveDialog.comment\" ng-disabled=\"status.loading\"></textarea>\n                </div>\n\t\t\t</div>\n\n\t\t\t<div class=\"modal-footer\">\n\t\t\t\t<div class=\"pull-right\">\n\t\t\t\t\t<button class=\"btn btn-sm btn-default\" ng-click=\"cancel()\" ng-disabled=\"model.loading\" translate>GENERAL.ACTION.CANCEL</button>\n\t\t\t\t\t<button class=\"btn btn-primary\" ng-click=\"saveAndClose()\" ng-disabled=\"status.loading || saveDialog.name.length == 0 || saveDialog.key.length == 0\" ng-show=\"!error && !error.isConflict\" translate>ACTION.SAVE-AND-CLOSE</button>\n\t\t\t\t\t<button class=\"btn btn-primary\" ng-click=\"save()\" ng-disabled=\"status.loading || saveDialog.name.length == 0 || saveDialog.key.length == 0\" ng-show=\"!error && !error.isConflict\" translate>ACTION.SAVE</button>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"loading pull-right\" ng-show=\"model.loading\">\n\t\t\t\t\t<div class=\"l1\"></div><div class=\"l2\"></div><div class=\"l2\"></div>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</div>\n\t</div>\n</div>\n"
  },
  {
    "path": "flowable-ui-web/modeler/views/popup/model-delete.html",
    "content": "\n<div class=\"modal\" ng-controller=\"DeleteModelPopupCtrl\">\n\t<div class=\"modal-dialog\">\n\t\t<div class=\"modal-content\">\n\t\t\t<div class=\"modal-header\">\n\t\t\t\t<h2>{{popup.popupType + '.POPUP.DELETE-TITLE' | translate}}</h2>\n\t\t\t</div>\n\t\t\t<div class=\"modal-body\">\n\n                <div ng-show=\"popup.loadingRelations\">\n                    <span class=\"text-info\">{{'PROCESS.POPUP.DELETE-LOADING-RELATIONS' | translate}}</span>\n                </div>\n\n                <div ng-show=\"popup.relations && popup.relations.length > 0\">\n                    <p ng-if=\"popup.relations.length > 1\">{{'PROCESS.POPUP.DELETE-RELATIONS-DESCRIPTION' | translate}}</p>\n                    <p ng-if=\"popup.relations.length == 1\">{{'PROCESS.POPUP.DELETE-RELATIONS-DESCRIPTION-SINGLE' | translate}}</p>\n                    <ul>\n                        <li ng-repeat=\"relation in popup.relations\" style=\"font-size: 15px\">\n                          <span ng-if=\"relation.type == 0 || relation.type == 1\">{{'PROCESS.POPUP.DELETE-PROCESS-RELATION' | translate}}</span>\n                          <span ng-if=\"relation.type == 2\">{{'PROCESS.POPUP.DELETE-FORM-RELATION' | translate}}</span>\n                          <span ng-if=\"relation.type == 3\">{{'PROCESS.POPUP.DELETE-APP-RELATION' | translate}}</span>\n                          <span><i>'{{relation.name}}'</i></span>\n                        </li>\n                    </ul>\n                </div>\n\n                <div ng-show=\"!popup.loadingRelations && (!popup.relations || popup.relations.length == 0)\">\n                    <p>{{popup.popupType + '.POPUP.DELETE-DESCRIPTION' | translate:popup.model}}</p>\n\n                    <div class=\"form-group\" ng-if=\"popup.model.version != 1 && popup.model.createdBy == account.id\">\n                        <div class=\"radio\" ng-click=\"popup.cascade = 'false'\">\n                            <input ng-model=\"popup.cascade\" value=\"false\" type=\"radio\" name=\"cascadeDelete\">\n                            <strong style=\"cursor:pointer\">{{popup.popupType + '.POPUP.DELETE-CASCADE-FALSE' | translate:popup.model}}</strong>\n                        </div>\n                        <div class=\"radio\" ng-click=\"popup.cascade = 'true'\">\n                            <input ng-model=\"popup.cascade\" value=\"true\" type=\"radio\" name=\"cascadeDelete\">\n                            <strong style=\"cursor:pointer\">{{popup.popupType + '.POPUP.DELETE-CASCADE-TRUE' | translate}}</strong>\n                        </div>\n                    </div>\n                </div>\n\t\t\t\t\n\t\t\t</div>\n\t\t\t<div class=\"modal-footer\">\n\t\t\t\t<div class=\"pull-right\">\n\t\t\t\t\t<button type=\"button\" class=\"btn btn-sm btn-default\" ng-click=\"cancel()\" ng-disabled=\"popup.loading\">\n\t\t\t\t\t\t{{'GENERAL.ACTION.CANCEL' | translate}}\n\t\t\t\t\t</button>\n\t\t\t\t\t<button type=\"button\" class=\"btn btn-sm btn-danger\" ng-click=\"ok()\" ng-disabled=\"popup.loading || !popup.model.name || (popup.relations && popup.relations.length > 0)\">\n\t\t\t\t\t\t<span>{{popup.popupType + '.ACTION.DELETE-CONFIRM' | translate}}</span>\n\t\t\t\t\t</button>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"loading pull-right\" ng-show=\"popup.loading\">\n\t\t\t\t\t<div class=\"l1\"></div><div class=\"l2\"></div><div class=\"l2\"></div>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</div>\n\t</div>\n</div>"
  },
  {
    "path": "flowable-ui-web/modeler/views/popup/model-edit.html",
    "content": "<div class=\"modal\" ng-controller=\"EditModelPopupCtrl\">\n    <div class=\"modal-dialog\">\n        <div class=\"modal-content\">\n            <div class=\"modal-header\">\n            \t<h2>{{'PROCESS.POPUP.EDIT-TITLE' | translate}}</h2>\n            </div>\n            <div class=\"modal-body\">\n            \t<p>{{'PROCESS.POPUP.EDIT-DESCRIPTION' | translate}}</p>\n            \t<div ng-if=\"popup.errorMessage && popup.errorMessage.length > 0\" class=\"alert error\" style=\"font-size: 14px; margin-top:20px\">\n                  <div class=\"popup-error\" style=\"font-size: 14px\">\n                    <span class=\"glyphicon glyphicon-remove-circle\"></span>\n                    <span>{{popup.errorMessage}}</span>\n                  </div>\n                </div>\n            \t<div class=\"form-group\">\n            \t    <label for=\"editProcessName\">{{'PROCESS.NAME' | translate}}</label>\n            \t    <input ng-disabled=\"popup.loading\" type=\"text\" class=\"form-control\"\n                           id=\"editProcessName\" ng-model=\"popup.modelName\" autofocus editor-input-check>\n            \t</div>\n            \t<div class=\"form-group\">\n            \t    <label for=\"editProcessKey\">{{'PROCESS.KEY' | translate}}</label>\n            \t    <input ng-disabled=\"popup.loading\" type=\"text\" class=\"form-control\"\n                           id=\"editProcessKey\" ng-model=\"popup.modelKey\" editor-input-check>\n            \t</div>\n            \t<div class=\"form-group\">\n            \t    <label for=\"editPocessDescription\">{{'PROCESS.DESCRIPTION' | translate}}</label>\n            \t\t<textarea ng-disabled=\"popup.loading\" class=\"form-control\" id=\"editProcessDescription\" rows=\"5\" ng-model=\"popup.modelDescription\"></textarea>\n            \t</div>\n            </div>\n\n            <div class=\"modal-footer\">\n            \t<div class=\"pull-right\">\n            \t\t<button type=\"button\" class=\"btn btn-sm btn-default\" ng-click=\"cancel()\" ng-disabled=\"popup.loading\" auto-focus>\n            \t\t\t{{'GENERAL.ACTION.CANCEL' | translate}}\n            \t\t</button>\n            \t\t<button type=\"button\" class=\"btn btn-sm btn-default\" ng-click=\"ok()\" ng-disabled=\"popup.loading || !popup.modelName || popup.modelName.length == 0 || !popup.modelKey || popup.modelKey.length == 0\">\n            \t\t\t{{'PROCESS.ACTION.EDIT-CONFIRM' | translate}}\n            \t\t</button>\n            \t</div>\n            \t<div class=\"loading pull-right\" ng-show=\"popup.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>\n"
  },
  {
    "path": "flowable-ui-web/modeler/views/popup/model-use-as-new-version.html",
    "content": "\n<div class=\"modal\" ng-controller=\"UseAsNewVersionPopupCtrl\">\n    <div class=\"modal-dialog\">\n        <div class=\"modal-content\">\n            <div class=\"modal-header\">\n            \t<h2>{{popup.popupType + '.POPUP.USE-AS-NEW-TITLE' | translate}}</h2>\n            </div>\n            <div class=\"modal-body\" ng-if=\"!popup.foundUnresolvedModels\">\n            \t<p>{{popup.popupType + '.POPUP.USE-AS-NEW-DESCRIPTION' | translate:popup.model}}</p>\n            \t<div class=\"form-group\">\n            \t    <label for=\"newVersionComment\">{{'PROCESS.VERSION-COMMENT' | translate}}</label>\n            \t\t<textarea ng-disabled=\"popup.loading\" class=\"form-control\" id=\"newVersionComment\" rows=\"5\" ng-model=\"popup.comment\"></textarea>\n            \t</div>\n            </div>\n            <div class=\"modal-body\" ng-if=\"popup.foundUnresolvedModels\">\n                <p>{{'PROCESS.POPUP.USE-AS-NEW-UNRESOLVED-MODELS-ERROR'| translate}}</p>\n                <ul style=\"font-size: 15px;\">\n                    <li ng-repeat=\"unresolvedModel in popup.unresolvedModels\">\n                        {{'PROCESS.POPUP.USE-AS-NEW-UNRESOLVED-MODEL' | translate:unresolvedModel}}\n                    </li>\n                </ul>\n            </div>\n            <div class=\"modal-footer\" ng-if=\"!popup.foundUnresolvedModels\">\n            \t<div class=\"pull-right\">\n            \t\t<button type=\"button\" class=\"btn btn-sm btn-default\" ng-click=\"cancel()\" ng-disabled=\"popup.loading\">\n            \t\t\t{{'GENERAL.ACTION.CANCEL' | translate}}\n            \t\t</button>\n            \t\t<button type=\"button\" class=\"btn btn-sm btn-default\" ng-click=\"ok()\" ng-disabled=\"popup.loading || !popup.model.name\">\n            \t\t\t{{popup.popupType + '.ACTION.USE-AS-NEW-VERSION' | translate}}\n            \t\t</button>\n            \t</div>\n            \t<div class=\"loading pull-right\" ng-show=\"popup.loading\">\n            \t\t<div class=\"l1\"></div><div class=\"l2\"></div><div class=\"l2\"></div>\n            \t</div>\n            </div>\n            <div class=\"modal-footer\" ng-if=\"popup.foundUnresolvedModels\">\n                <div class=\"pull-right\">\n                    <button type=\"button\" class=\"btn btn-sm btn-default\" ng-disabled=\"popup.loading\" ng-click=\"close()\">\n                        {{'GENERAL.ACTION.CLOSE' | translate}}\n                    </button>\n                </div>\n            </div>\n        </div>\n    </div>\n</div>"
  },
  {
    "path": "flowable-ui-web/modeler/views/popup/process-create.html",
    "content": "\n<div class=\"modal\" ng-controller=\"CreateNewProcessModelCtrl\">\n\t<div class=\"modal-dialog\">\n\t\t<div class=\"modal-content\">\n\t\t\t<div class=\"modal-header\"><h2>{{'PROCESS.POPUP.CREATE-TITLE' | translate}}</h2></div>\n\t\t\t<div class=\"modal-body\">\n\t\t\t\t<p>{{'PROCESS.POPUP.CREATE-DESCRIPTION' | translate}}</p>\n\t\t\t\t<div ng-if=\"model.errorMessage && model.errorMessage.length > 0\" class=\"alert error\" style=\"font-size: 14px; margin-top:20px\">\n                  <div class=\"popup-error\" style=\"font-size: 14px\">\n                    <span class=\"glyphicon glyphicon-remove-circle\"></span>\n                    <span>{{model.errorMessage}}</span>\n                  </div>\n                </div>\n\t\t\t\t<div class=\"form-group\">\n\t\t\t\t    <label for=\"newProcessName\">{{'PROCESS.NAME' | translate}}</label>\n\t\t\t\t    <input ng-disabled=\"model.loading\" type=\"text\" class=\"form-control\"\n\t\t\t               id=\"newProcessName\" ng-model=\"model.process.name\" auto-focus editor-input-check>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"form-group\">\n\t\t\t\t    <label for=\"newProcessKey\">{{'PROCESS.KEY' | translate}}</label>\n\t\t\t\t    <input ng-disabled=\"model.loading\" type=\"text\" class=\"form-control\"\n\t\t\t               id=\"newProcessKey\" ng-model=\"model.process.key\" editor-input-check>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"form-group\">\n\t\t\t\t    <label for=\"newProcessDescription\">{{'PROCESS.DESCRIPTION' | translate}}</label>\n\t\t\t\t\t<textarea ng-disabled=\"model.loading\" class=\"form-control\" id=\"newProcessDescription\" rows=\"5\" ng-model=\"model.process.description\"></textarea>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t\n\t\t\t<div class=\"modal-footer\">\n\t\t\t\t<div class=\"pull-right\">\n\t\t\t\t\t<button type=\"button\" class=\"btn btn-sm btn-default\" ng-click=\"cancel()\" ng-disabled=\"model.loading\">\n\t\t\t\t\t\t{{'GENERAL.ACTION.CANCEL' | translate}}\n\t\t\t\t\t</button>\n\t\t\t\t\t<button type=\"button\" class=\"btn btn-sm btn-default\" ng-click=\"ok()\" ng-disabled=\"model.loading || !model.process.name || model.process.name.length == 0 || !model.process.key || model.process.key.length == 0\">\n\t\t\t\t\t\t{{'PROCESS.ACTION.CREATE-CONFIRM' | translate}}\n\t\t\t\t\t</button>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"loading pull-right\" ng-show=\"model.loading\">\n\t\t\t\t\t<div class=\"l1\"></div><div class=\"l2\"></div><div class=\"l2\"></div>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</div>\n\t</div>\n</div>"
  },
  {
    "path": "flowable-ui-web/modeler/views/popup/process-duplicate.html",
    "content": "\n<div class=\"modal\" ng-controller=\"DuplicateProcessModelCtrl\">\n\t<div class=\"modal-dialog\">\n\t\t<div class=\"modal-content\">\n\t\t\t<div class=\"modal-header\"><h2>{{'PROCESS.POPUP.DUPLICATE-TITLE' | translate}}</h2></div>\n\t\t\t<div class=\"modal-body\">\n\t\t\t\t<p>{{'PROCESS.POPUP.DUPLICATE-DESCRIPTION' | translate}}</p>\n\t\t\t\t<div ng-if=\"model.errorMessage && model.errorMessage.length > 0\" class=\"alert error\" style=\"font-size: 14px; margin-top:20px\">\n                  <div class=\"popup-error\" style=\"font-size: 14px\">\n                    <span class=\"glyphicon glyphicon-remove-circle\"></span>\n                    <span>{{model.errorMessage}}</span>\n                  </div>\n                </div>\n\t\t\t\t<div class=\"form-group\">\n\t\t\t\t    <label for=\"newProcessName\">{{'PROCESS.NAME' | translate}}</label>\n\t\t\t\t    <input ng-disabled=\"model.loading\" type=\"text\" class=\"form-control\"\n\t\t\t               id=\"newProcessName\" ng-model=\"model.process.name\" ui-keypress=\"{13:'ok()'}\" auto-focus editor-input-check>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"form-group\">\n                    <label for=\"newProcessKey\">{{'PROCESS.KEY' | translate}}</label>\n                    <input ng-disabled=\"model.loading\" type=\"text\" class=\"form-control\"\n                           id=\"newProcessKey\" ng-model=\"model.process.key\" editor-input-check>\n                </div>\n\t\t\t\t<div class=\"form-group\">\n\t\t\t\t    <label for=\"newProcessDescription\">{{'PROCESS.DESCRIPTION' | translate}}</label>\n\t\t\t\t\t<textarea ng-disabled=\"model.loading\" class=\"form-control\" id=\"newProcessDescription\" rows=\"5\" ng-model=\"model.process.description\"></textarea>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t\n\t\t\t<div class=\"modal-footer\">\n\t\t\t\t<div class=\"pull-right\">\n\t\t\t\t\t<button type=\"button\" class=\"btn btn-sm btn-default\" ng-click=\"cancel()\" ng-disabled=\"model.loading\">\n\t\t\t\t\t\t{{'GENERAL.ACTION.CANCEL' | translate}}\n\t\t\t\t\t</button>\n\t\t\t\t\t<button type=\"button\" class=\"btn btn-sm btn-default\" ng-click=\"ok()\"ng-disabled=\"model.loading || !model.process.name\">\n\t\t\t\t\t\t{{'PROCESS.ACTION.DUPLICATE-CONFIRM' | translate}}\n\t\t\t\t\t</button>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"loading pull-right\" ng-show=\"model.loading\">\n\t\t\t\t\t<div class=\"l1\"></div><div class=\"l2\"></div><div class=\"l2\"></div>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</div>\n\t</div>\n</div>"
  },
  {
    "path": "flowable-ui-web/modeler/views/popup/process-import.html",
    "content": "\n<div class=\"modal\" ng-controller=\"ImportProcessModelCtrl\">\n    <div class=\"modal-dialog\">\n        <div class=\"modal-content\">\n            <div class=\"modal-header-wrapper\">\n            \t<div class=\"modal-header\">\n            \t\t<div class=\"pull-right\">\n                        <a class=\"action\" ng-click=\"cancel()\">&times; {{'GENERAL.ACTION.CANCEL' | translate}}</a>\n                    </div>\n            \t\t<h2>{{'PROCESS.POPUP.IMPORT-TITLE' | translate}}</h2>\n            \t</div>\n            </div>\n            <div class=\"modal-body\">\n\n                <p>\n                    <i class=\"glyphicon glyphicon-info-sign\"></i>\n                    {{'PROCESS.POPUP.IMPORT-DESCRIPTION' | translate}}\n                </p>\n                <!--[if IE 9]>\n\n                <div class=\"import-process-form\">\n\n                    <input type=\"file\" ngf-select=\"\" ngf-change=\"onFileSelect($files, true)\" style=\"font-size: smaller; padding-top:6px;\" >\n                    <div class=\"import-process-dropbox\"\n                         ngf-drop=\"onFileSelect($files)\"\n                         ngf-drag-over-class=\"dragover\"\n                         ng-show=\"dropSupported\">\n                        {{'PROCESS.POPUP.IMPORT.DROPZONE' | translate}}\n                    </div>\n                    <div ngf-drop-available=\"dropSupported=true\"\n                         ng-show=\"!dropSupported\">{{'PROCESS.POPUP.IMPORT.NO-DROP' | translate}}</div>\n                    <div class=\"graph-wrapper\" ng-show=\"status.loading\" style=\"margin: 10px 0 10px 0\">\n                        <div class=\"graph-bar\" ng-style=\"{width: model.uploadProgress + '%'}\"></div>\n                    </div>\n                    <button class=\"btn btn-danger btn-sm\"\n                            ng-click=\"upload.abort()\"\n                            ng-disabled=\"!status.loading\"\n                            style=\"margin-bottom: 20px\">\n                        {{'PROCESS.POPUP.IMPORT.CANCEL-UPLOAD' | translate}}\n                    </button>\n\n                </div>\n                <![endif]-->\n                <!--[if gt IE 9]> <!-- -->\n                <div class=\"import-process-form\">\n\n                    <input type=\"file\" ngf-select=\"\" ngf-change=\"onFileSelect($files)\" style=\"font-size: smaller; padding-top:6px;\" >\n                    <div class=\"import-process-dropbox\"\n                         ngf-drop ngf-change=\"onFileSelect($files)\"\n                         ngf-drag-over-class=\"dragover\"\n                         ng-show=\"dropSupported\">\n                        {{'PROCESS.POPUP.IMPORT.DROPZONE' | translate}}\n                    </div>\n                    <div ngf-drop-available=\"dropSupported=true\"\n                         ng-show=\"!dropSupported\">{{'PROCESS.POPUP.IMPORT.NO-DROP' | translate}}</div>\n                    <div class=\"graph-wrapper\" ng-show=\"status.loading\" style=\"margin: 10px 0 10px 0\">\n                        <div class=\"graph-bar\" ng-style=\"{width: model.uploadProgress + '%'}\"></div>\n                    </div>\n                    <button class=\"btn btn-danger btn-sm\"\n                            ng-click=\"upload.abort()\"\n                            ng-disabled=\"!status.loading\"\n                            style=\"margin-bottom: 20px\">\n                        {{'PROCESS.POPUP.IMPORT.CANCEL-UPLOAD' | translate}}\n                    </button>\n                </div>\n\n                <!-- <![endif]-->\n            </div>\n\n            <div class=\"modal-footer-wrapper\">\n                <div class=\"modal-footer\">\n                    <loading></loading>\n                    <div class=\"pull-right modeler-processes-error\" ng-if=\"model.error\">\n                        <span>{{'PROCESS.POPUP.IMPORT.ERROR' | translate}} <span ng-if=\"model.errorMessage\"> : </span>{{model.errorMessage}}</span>\n                    </div>\n                </div>\n            </div>\n        </div>\n    </div>\n</div>\n"
  },
  {
    "path": "flowable-ui-web/modeler/views/popup/subprocess-create.html",
    "content": "\n<div class=\"modal\" ng-controller=\"CreateNewSubProcessCtrl\">\n\t<div class=\"modal-dialog\">\n\t\t<div class=\"modal-content\">\n\t\t\t<div class=\"modal-header\"><h2>{{'SUBPROCESS.POPUP.CREATE-TITLE' | translate}}</h2></div>\n\t\t\t<div class=\"modal-body\">\n\t\t\t\t<p>{{'SUBPROCESS.POPUP.CREATE-DESCRIPTION' | translate}}</p>\n\t\t\t\t<div class=\"form-group\">\n\t\t\t\t    <label for=\"newSubProcessName\">{{'SUBPROCESS.NAME' | translate}}</label>\n\t\t\t\t    <input ng-disabled=\"model.loading\" type=\"text\" class=\"form-control\"\n\t\t\t               id=\"newSubProcessName\" ng-model=\"model.subProcess.name\" ui-keypress=\"{13:'ok()'}\" auto-focus editor-input-check>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"form-group\">\n\t\t\t\t    <label for=\"newFormDescription\">{{'SUBPROCESS.DESCRIPTION' | translate}}</label>\n\t\t\t\t\t<textarea ng-disabled=\"model.loading\" class=\"form-control\" id=\"newFormDescription\" rows=\"5\" ng-model=\"model.subProcess.description\"></textarea>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t\n\t\t\t<div class=\"modal-footer\">\n\t\t\t\t<div class=\"pull-right\">\n\t\t\t\t\t<button type=\"button\" class=\"btn btn-sm btn-default\" ng-click=\"cancel()\" ng-disabled=\"model.loading\">\n\t\t\t\t\t\t{{'GENERAL.ACTION.CANCEL' | translate}}\n\t\t\t\t\t</button>\n\t\t\t\t\t<button type=\"button\" class=\"btn btn-sm btn-default\" ng-click=\"ok()\"ng-disabled=\"model.loading || !model.subProcess.name\">\n\t\t\t\t\t\t{{'SUBPROCESS.ACTION.CREATE-CONFIRM' | translate}}\n\t\t\t\t\t</button>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"loading pull-right\" ng-show=\"model.loading\">\n\t\t\t\t\t<div class=\"l1\"></div><div class=\"l2\"></div><div class=\"l2\"></div>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</div>\n\t</div>\n</div>"
  },
  {
    "path": "flowable-ui-web/modeler/views/process.html",
    "content": "\n<div class=\"subheader\" ng-if=\"model.process\">\n\t<div class=\"fixed-container\">\n\t\t<div class=\"btn-group pull-right\">\n\t\t\t<button type=\"button\" class=\"btn btn-default\" ng-click=\"openEditor()\" ng-if=\"model.process.latestVersion\">\n\t\t\t\t<i class=\"glyphicon glyphicon-edit icon-and-label\"></i> {{'PROCESS.ACTION.OPEN-IN-EDITOR' | translate}}\n\t\t\t</button>\n\t\t\t<button type=\"button\" class=\"btn btn-default\" ng-click=\"useAsNewVersion()\" ng-if=\"!model.process.latestVersion\">\n\t\t\t\t{{'PROCESS.ACTION.USE-AS-NEW-VERSION' | translate}}\n\t\t\t</button>\n\t\t</div>\n\t\t<div class=\"btn-group pull-right\">\n\t        <a href=\"{{model.bpmn20DownloadUrl}}\" class=\"btn btn-default\" title=\"{{'PROCESS.ACTION.EXPORT_BPMN20' | translate}}\">\n\t            <i class=\"glyphicon glyphicon-save\"></i>\n\t        </a>\n\t\t</div>\n\t\t<div class=\"btn-group pull-right\">\n\t\t\t<button type=\"button\" class=\"btn btn-default\" ng-click=\"editProcess()\" ng-disabled=\"!model.process.latestVersion\"\n\t\t\t\ttitle=\"{{'PROCESS.ACTION.EDIT' | translate}}\">\n\t\t\t\t<i class=\"glyphicon glyphicon-pencil\"></i>\n\t\t\t</button>\n            <button type=\"button\" class=\"btn btn-default\" ng-click=\"duplicateProcess()\" ng-disabled=\"!model.process.latestVersion\"\n                    title=\"{{'PROCESS.ACTION.DUPLICATE' | translate}}\">\n                <i class=\"editor-icon editor-icon-copy\"></i>\n            </button>\n\t\t\t<button type=\"button\" class=\"btn btn-default\" ng-click=\"deleteProcess()\" title=\"{{'PROCESS.ACTION.DELETE' | translate}}\"\n\t\t\t\tng-disabled=\"!model.process.latestVersion\">\n\t\t\t\t<i class=\"glyphicon glyphicon-trash\"></i>\n\t\t\t</button>\n\t\t</div>\t\t\n\t\t<div class=\"pull-right\">\n\t\t\t<a ng-click=\"returnToList()\" class=\"action\">&larr; {{'GENERAL.ACTION.RETURN-TO-LIST' | translate}}</a>\n\t\t</div>\n\t\t<h2><span class=\"version\">v{{model.process.version}}</span>{{model.process.name}}</h2>\n\t\t<div class=\"clearfix\">\n\t\t\t<div class=\"col-xs-4 details\">\n\t\t\t\t<span><i class=\"glyphicon glyphicon-user\"></i>{{'PROCESS.DETAILS.CREATED-BY' | translate:model.process}}</span> \n\t\t\t\t<span><i class=\"glyphicon glyphicon-pencil\"></i>{{'PROCESS.DETAILS.LAST-UPDATED-BY' | translate:model.process}}</span>\n\t\t\t</div>\n\t\t\t<div class=\"col-xs-8 details clearfix\">\n                <div class=\"related btn-group\">\n                    <button id=\"toggle-history\" type=\"button\" class=\"btn btn-subtle\" ng-click=\"toggleHistory($event)\"\n                        title=\"{{'PROCESS.ACTION.EDIT' | translate}}\">\n                        {{'PROCESS.DETAILS.HISTORY-TITLE' | translate}} <span class=\"counter\" ng-show=\"model.versions.data.length\">{{model.versions.data.length}}</span>\n                    </button>\n                </div>\n                <a ng-show=\"model.stencil\" ng-click=\"goToStencil()\" class=\"pull-right action\">{{model.stencil.name}}</a>\n                <p ng-if=\"model.process.description\">\n                    {{model.process.description}}\n                </p>\n                <p ng-if=\"!model.process.description && model.process.latestVersion\" class=\"hint\">\n                    <a ng-click=\"editProcess()\" class=\"subtle-select\">\n                        {{'PROCESS.DETAILS.NO-DESCRIPTION' | translate}} <i class=\"glyphicon glyphicon-pencil\"></i>\n                    </a>\n                </p>\n            </div>\n\t\t</div>\n\t</div>\n</div>\n<div class=\"content center-pane\" ng-if=\"model.process\" auto-height offset=\"40\" >\n        \n    \t<div class=\"model-preview-wrapper\" ng-if=\"!model.process.modelType && model.process.modelType != 1\">\n    \t   <div id=\"bpmnModel\"></div>\n    \t</div>\n</div>\n"
  },
  {
    "path": "flowable-ui-web/modeler/views/processes.html",
    "content": "\n<div class=\"subheader\">\n\t<div class=\"fixed-container\">\n\t\t<div class=\"btn-group pull-right\">\n\t\t\t<button type=\"button\" class=\"btn btn-default\" ng-click=\"createProcess()\" translate>PROCESS-LIST.ACTION.CREATE</button>\n\t\t\t<button type=\"button\" class=\"btn btn-default\" ng-click=\"importProcess()\" translate>PROCESS-LIST.ACTION.IMPORT</button>\n\t\t</div>\n\t\t<h2>{{'PROCESS-LIST.TITLE' | translate}}</h2>\n\t</div>\n</div>\n<div class=\"container-fluid content\" auto-height offset=\"40\">\n\t\t<div class=\"col-xs-2 filter-wrapper\">\n\t\t\t<div class=\"input-group\">\n\t\t\t\t<span class=\"input-group-addon\"> <i\n\t\t\t\t\tclass=\"glyphicon glyphicon-search\"></i>\n\t\t\t\t</span> <input type=\"text\" ng-model=\"model.pendingFilterText\" class=\"form-control\" ng-change=\"filterDelayed()\"\n\t\t\t\t\tplaceholder=\"{{'PROCESS-LIST.SEARCH-PLACEHOLDER' | translate}}\">\n\t\t\t</div>\n\t\t\t<ul class=\"filter-list\">\n\t\t\t\t<li ng-repeat=\"filter in model.filters\" ng-class=\"{'current' : filter.id == model.activeFilter.id}\">\n\t\t\t\t\t<a ng-click=\"activateFilter(filter)\">{{'PROCESS-LIST.FILTER.' + filter.labelKey | translate}}</a>\n\t\t\t\t</li>\n\t\t\t</ul>\n\t\t</div>\n\n\t\t<div class=\"col-xs-10 item-wrapper\" id=\"list-items\">\n\t\t\t<div class=\"dropdown-subtle pull-right\">\n\t\t\t\t<div class=\"btn-group btn-group-sm\" activiti-fix-dropdown-bug>\n\t\t\t\t\t<button type=\"button\" class=\"btn btn-default dropdown-toggle\"\n\t\t\t\t\t\tdata-toggle=\"dropdown\">{{'PROCESS-LIST.SORT.' + model.activeSort.labelKey | translate}} <i class=\"caret\"></i></button>\n\t\t\t\t\t<ul class=\"dropdown-menu pull-right\">\n\t\t\t\t\t\t<li ng-repeat=\"sort in model.sorts\">\n\t\t\t\t\t\t\t<a ng-click=\"activateSort(sort)\">{{'PROCESS-LIST.SORT.' + sort.labelKey | translate}}</a>\n\t\t\t\t\t\t</li>\n\t\t\t\t\t</ul>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t<div class=\"message clearfix\">\n\t\t\t\t<div class=\"loading pull-left\" ng-show=\"model.loading\">\n\t\t\t\t\t<div class=\"l1\"></div><div class=\"l2\"></div><div class=\"l2\"></div>\n\t\t\t\t</div>\n\t\t\t\t<div ng-if=\"!model.loading\">\n\t\t\t\t\t<span ng-if=\"model.processes.size > 1\">{{'PROCESS-LIST.FILTER.' + model.activeFilter.labelKey + '-COUNT' | translate:model.processes}}</span>\n\t\t\t\t\t<span ng-if=\"model.processes.size == 1\">{{'PROCESS-LIST.FILTER.' + model.activeFilter.labelKey + '-ONE' | translate}}</span>\n\t\t\t\t\t<span ng-if=\"model.processes.size > 0 && model.filterText !='' && model.filterText !== undefined\">{{'PROCESS-LIST.FILTER.FILTER-TEXT' | translate:model}}</span>\n\t\t\t\t\t<span ng-if=\"model.processes.size == 0 && model.filterText !='' && model.filterText !== undefined\">{{'PROCESS-LIST.FILTER.FILTER-TEXT-EMPTY' | translate:model}}</span>\n\t\t\t\t</div>\n\t\t\t</div>\n\n            <div class=\"help-container fixed\" ng-if=\"model.processes.size == 0 && (!model.filterText || model.filterText == '')\">\n                <div>\n                    <div class=\"help-text wide\">\n                        <div class=\"description\">\n                            {{'PROCESS-LIST.FILTER.PROCESSES-EMPTY' | translate}}\n                        </div>\n                        <div class=\"help-entry\" ng-click=\"createProcess()\">\n                            <span class=\"glyphicon glyphicon-plus-sign\"></span>\n                            <span translate=\"PROCESS-LIST.FILTER.PROCESSES-BPMN-HINT\"></span>\n                            <br>\n                        </div>\n\t\t\t\t\t\t<div class=\"help-entry\" ng-click=\"importProcess()\">\n                            <span class=\"glyphicon glyphicon-plus-sign\"></span>\n                            <span translate=\"PROCESS-LIST.FILTER.PROCESSES-BPMN-IMPORT-HINT\"></span>\n                            <br>\n                        </div>\n                    </div>\n                </div>\n            </div>\n\t\t\t<div class=\"item fadein\" ng-repeat=\"process in model.processes.data track by $index\">\n\t\t\t\t<div class=\"item-box\" ng-style=\"{'background-image': 'url(\\'' + getModelThumbnailUrl(process.id, imageVersion) + '\\')'}\" ng-click=\"showProcessDetails(process);\">\n\t\t\t\t\t<div class=\"actions\">\n\t\t\t\t\t\t<span class=\"badge\">v{{process.version}}</span>\n\t\t\t\t\t\t<div class=\"btn-group pull-right\">\n\t\t\t\t\t\t\t<button id=\"detailsButton\" type=\"button\" ng-click=\"showProcessDetails(process); $event.stopPropagation();\" class=\"btn btn-default\" title=\"{{'PROCESS.ACTION.DETAILS' | translate}}\">\n\t\t\t\t\t\t\t\t<i class=\"glyphicon glyphicon-search\"></i>\n\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t<button id=\"editButton\" type=\"button\" ng-click=\"editProcessDetails(process); $event.stopPropagation();\" class=\"btn btn-default\" title=\"{{'PROCESS.ACTION.OPEN-IN-EDITOR' | translate}}\">\n\t\t\t\t\t\t\t\t<i class=\"glyphicon glyphicon-edit\"></i>\n\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t\t<div class=\"details\">\n\t\t\t\t\t\t<h3 class=\"truncate\" title=\"{{process.name}}\">\n\t\t\t\t\t\t\t{{process.name}}\n\t\t\t\t\t\t</h3>\n\t\t\t\t\t\t<div class=\"basic-details truncate\">\n\t\t\t\t\t\t\t<span><i class=\"glyphicon glyphicon-user\"></i> {{process.createdBy}}</span> <span title=\"{{process.lastUpdated | dateformat:'LLLL'}}\"><i class=\"glyphicon glyphicon-pencil\"></i> {{process.lastUpdated | dateformat}}</span>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<p>{{process.description}}</p>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t</div>\n\n\t\t\t<div class=\"show-more\" ng-if=\"model.processes.data.length < model.processes.total\">\n\t\t\t\t<a>{{'PROCESSES-LIST.ACTION.SHOW-MORE' | translate}}</a>\n\t\t\t</div>\n\t\t</div>\n</div>\n"
  },
  {
    "path": "flowable-ui-web/modeler/views/templates/decision-table-header-template.html",
    "content": "<div role=\"rowgroup\"\n     class=\"ui-grid-header\"> <!-- theader -->\n    <div class=\"ui-grid-top-panel\">\n        <div class=\"ui-grid-header-viewport\">\n            <div class=\"ui-grid-header-canvas\">\n                <div class=\"ui-grid-header-cell-wrapper\" ng-style=\"colContainer.headerCellWrapperStyle()\">\n                    <div role=\"row\" class=\"ui-grid-header-cell-row\"><pre></pre>\n                        <div class=\"ui-grid-header-cell ui-grid-clearfix\"\n                             ng-repeat=\"col in colContainer.renderedColumns track by col.uid\"\n                             ui-grid-header-cell\n                             col=\"col\"\n                             render-index=\"$index\">\n                        </div>\n                    </div>\n                </div>\n            </div>\n        </div>\n    </div>\n</div>"
  },
  {
    "path": "flowable-ui-web/modeler/views/templates/decision-table-headercell-template.html",
    "content": "<div role=\"columnheader\" ng-class=\"{ 'sortable': sortable }\" ui-grid-one-bind-aria-labelledby-grid=\"col.uid + '-header-text ' + col.uid + '-sortdir-text'\" aria-sort=\"{{col.sort.direction == asc ? 'ascending' : ( col.sort.direction == desc ? 'descending' : (!col.sort.direction ? 'none' : 'other'))}}\"><div role=\"button\" tabindex=\"0\" class=\"ui-grid-cell-contents ui-grid-header-cell-primary-focus\" col-index=\"renderIndex\" title=\"TOOLTIP\"><span ui-grid-one-bind-id-grid=\"col.uid + '-header-text'\">{{ col.displayName CUSTOM_FILTERS }}</span> <span ui-grid-one-bind-id-grid=\"col.uid + '-sortdir-text'\" ui-grid-visible=\"col.sort.direction\" aria-label=\"{{getSortDirectionAriaLabel()}}\"><i ng-class=\"{ 'ui-grid-icon-up-dir': col.sort.direction == asc, 'ui-grid-icon-down-dir': col.sort.direction == desc, 'ui-grid-icon-blank': !col.sort.direction }\" title=\"{{col.sort.priority ? i18n.headerCell.priority + ' ' + col.sort.priority : null}}\" aria-hidden=\"true\">&nbsp;</i></span></div><div role=\"button\" tabindex=\"0\" ui-grid-one-bind-id-grid=\"col.uid + '-menu-button'\" class=\"ui-grid-column-menu-button\" ng-if=\"grid.options.enableColumnMenus && !col.isRowHeader  && col.colDef.enableColumnMenu !== false\" ng-click=\"toggleMenu($event)\" ng-class=\"{'ui-grid-column-menu-button-last-col': isLastCol}\" ui-grid-one-bind-aria-label=\"i18n.headerCell.aria.columnMenuButtonLabel\" aria-haspopup=\"true\"><i class=\"ui-grid-icon-angle-down\" aria-hidden=\"true\">&nbsp;</i></div><div ui-grid-filter></div></div>\n"
  },
  {
    "path": "flowable-ui-web/modeler/views/templates/form-builder-element-template.html",
    "content": "<div class=\"form-field\" ng-switch=\"formElement.type\" ng-class=\"{'editing': editState.field == formElement}\">\n\n  <div class=\"actions\" ng-show=\"(!formMode || formMode != 'read')\">\n    <button class=\"btn btn-clean\" ng-click=\"openFieldPopover()\"><i class=\"glyphicon glyphicon-pencil\"></i></button>\n    <button class=\"btn btn-clean\" ng-click=\"removeFormElement(formElement)\"><i class=\"icon icon-remove\"></i></button>\n  </div>\n\n  <div ng-switch-when=\"text\" class=\"form-group\">\n      <label class=\"control-label form-field-label\">{{formElement.name}}</label><span class=\"marker\" ng-if=\"formElement.required\">*</span>\n      <input type=\"text\" class=\"form-control\" style=\"cursor:default;background-color:#fff;\" value=\"Text\" disabled>\n  </div>\n  \n    <div ng-switch-when=\"password\" class=\"form-group\">\n      <label class=\"control-label form-field-label\">{{formElement.name}}</label><span class=\"marker\" ng-if=\"formElement.required\">*</span>\n      <input type=\"text\" class=\"form-control\" style=\"cursor:default;background-color:#fff;\" value=\"Password\" disabled>\n  \t</div>\n\n  <div ng-switch-when=\"multi-line-text\" class=\"form-group\">\n      <label class=\"control-label form-field-label\">{{formElement.name}}</label><span class=\"marker\" ng-if=\"formElement.required\">*</span>\n      <textarea rows=\"4\" class=\"form-control\" style=\"cursor:default;background-color:#fff;\" value=\"Text\" disabled></textarea>\n  </div>\n\n  <div ng-switch-when=\"date\" class=\"form-group\">\n      <label class=\"control-label form-field-label\"><i class=\"glyphicon glyphicon-calendar\"></i> {{formElement.name}} <span class=\"marker\" ng-if=\"formElement.required\">*</span></label>\n      <input type=\"text\" class=\"form-control\" name=\"date\" disabled>\n  </div>\n\n  <div ng-switch-when=\"boolean\" class=\"checkbox\" style=\"padding-left:0;\">\n      <label class=\"control-label form-field-label\"></label>\n      <div style=\"padding-left: 20px;\">\n          <input type=\"checkbox\" class=\"checkbox-inline\" disabled>{{formElement.name}} <span class=\"marker\" ng-if=\"formElement.required\">*</span>\n      </div>\n  </div>\n\n  <div ng-switch-when=\"radio-buttons\" class=\"form-group\">\n      <label class=\"control-label form-field-label\">{{formElement.name}} <span class=\"marker\" ng-if=\"formElement.required\">*</span></label>\n      <div ng-show=\"formElement.options && formElement.options.length > 0\" class=\"radio\" ng-repeat=\"option in formElement.options\">\n          <label>\n              <input type=\"radio\" name=\"optionsRadios\" id=\"optionsRadios{{$index}}\" value=\"option{{$index}}\" ng-checked=\"formElement.value == option.name\" disabled>{{option.name}}</input>\n          </label>\n      </div>\n      <div ng-show=\"!formElement.options && formElement.options.length === 0 && !formElement.optionsExpression\" class=\"radio\">\n          <label>\n              <input type=\"radio\" name=\"optionsRadios\" id=\"optionsRadios1\" value=\"option1\" disabled>\n              Option 1\n          </label>\n      </div>\n      <div ng-show=\"formElement.optionsExpression\" ng-style=\"{'font-size': '1em'}\">\n          <label>\n              <input type=\"radio\" name=\"optionsRadios\" id=\"optionsRadios1\" value=\"none\" disabled>\n                {{formElement.optionsExpression}}\n              </input>\n          </label>\n      </div>\n      <div class=\"clearfix\"></div>\n  </div>\n\n  <div ng-switch-when=\"integer\" class=\"form-group\">\n      <label class=\"control-label form-field-label\">{{formElement.name}} <span class=\"marker\" ng-if=\"formElement.required\">*</span></label>\n      <input type=\"number\" class=\"form-control\" style=\"cursor:default;background-color:#fff;\" value=\"123\" disabled>\n  </div>\n  \n  <div ng-switch-when=\"decimal\" class=\"form-group\">\n      <label class=\"control-label form-field-label\">{{formElement.name}} <span class=\"marker\" ng-if=\"formElement.required\">*</span></label>\n      <input type=\"number\" class=\"form-control\" style=\"cursor:default;background-color:#fff;\" value=\"123.12\" disabled>\n  </div>\n  \n  <div ng-switch-when=\"dropdown\" class=\"form-group\">\n    <label class=\"control-label form-field-label\">{{formElement.name}} <span class=\"marker\" ng-if=\"formElement.required\">*</span></label>\n    <select class=\"form-control\" style=\"cursor:default;\" disabled>\n          <option>Select...</option>\n    </select>\n  </div>\n\n  <div ng-switch-when=\"people\" class=\"form-group\">\n    <label class=\"control-label form-field-label\">{{formElement.name}} <span class=\"marker\" ng-if=\"formElement.required\">*</span></label>\n    <div class=\"input-group\">\n      <span class=\"input-group-addon\"><i class=\"icon icon-user-add\"></i></span>\n      <input type=\"text\" class=\"form-control\" style=\"cursor:default;background-color:#fff;\" placeholder=\"{{'FORM-BUILDER.LABEL.PERSON' | translate}}\" value=\"{{formElement.placeholder}}\" disabled>\n    </div>\n  </div>\n\n  <div ng-switch-when=\"functional-group\" class=\"form-group\">\n    <label class=\"control-label form-field-label\">{{formElement.name}} <span class=\"marker\" ng-if=\"formElement.required\">*</span></label>\n    <div class=\"input-group\">\n      <span class=\"input-group-addon\"></span>\n      <input type=\"text\" class=\"form-control\" style=\"cursor:default;background-color:#fff;\" placeholder=\"{{'FORM-BUILDER.LABEL.FUNCTIONAL-GROUP' | translate}}\" value=\"{{formElement.placeholder}}\" >\n    </div>\n  </div>\n\n  <div ng-switch-when=\"upload\" class=\"form-group\">\n    <label class=\"control-label form-field-label\">{{formElement.name}} <span class=\"marker\" ng-if=\"formElement.required\">*</span></label>\n    <div class=\"input-group clearfix\">\n      <span class=\"input-group-addon\"><i class=\"icon icon-folder\"></i></span>\n      <input type=\"text\" class=\"form-control\" style=\"cursor:default;background-color:#fff;\" value=\"Upload or import content...\" disabled>\n    </div>\n  </div>\n\n  <div ng-switch-when=\"hyperlink\" class=\"form-group\">\n    <label class=\"control-label form-field-label\">{{formElement.name}}<span class=\"marker\" ng-if=\"formElement.required\">*</span></label>\n    <div class=\"message\" ng-show=\"formElement.params.hyperlinkUrl\">{{formElement.params.hyperlinkUrl}}</div>\n  </div>\n  \n  <div ng-switch-when=\"spacer\" class=\"form-group\">\n\t<br />\n  </div>\n  \n  <div ng-switch-when=\"horizontal-line\" class=\"form-group\">\n\t<hr>\n  </div>\n\n  <div ng-switch-when=\"headline\" class=\"form-group\">\n\t<h4><strong>{{formElement.name}}</strong></h4>\n  </div>\n\n  <div ng-switch-when=\"headline-with-line\" class=\"form-group\">\n\t<h4><strong>{{formElement.name}}</strong></h4>\n\t<hr>\n  </div>\n\n  <div ng-switch-when=\"expression\" class=\"form-group\">\n    <div class=\"message\" ng-style=\"{'font-size': formElement.params.size + 'em'}\">\n      <div ng-show=\"formElement.expression && formElement.expression.length > 0\">\n        {{formElement.expression}}\n      </div>\n      <div ng-show=\"!formElement.expression || formElement.expression.length == 0\">\n      \t{{'FORM-BUILDER.MESSAGE.EMPTY-EXPRESSION' | translate}}\n      </div>\n    </div>\n    <div class=\"clearfix\"></div>\n  </div>\n</div>\n"
  },
  {
    "path": "flowable-ui-web/nginx/nginx.conf",
    "content": "\n#user  nobody;\nworker_processes  1;\n\n#error_log  logs/error.log;\n#error_log  logs/error.log  notice;\n#error_log  logs/error.log  info;\n\n#pid        logs/nginx.pid;\n\n\nevents {\n    worker_connections  1024;\n}\n\n\nhttp {\n    include       mime.types;\n    default_type  application/octet-stream;\n\n    #log_format  main  '$remote_addr - $remote_user [$time_local] \"$request\" '\n    #                  '$status $body_bytes_sent \"$http_referer\" '\n    #                  '\"$http_user_agent\" \"$http_x_forwarded_for\"';\n\n    access_log  /usr/local/etc/nginx/logs/access.log;\n\n    sendfile        on;\n    #tcp_nopush     on;\n\n    #keepalive_timeout  0;\n    keepalive_timeout  65;\n\n    gzip  on;\n\n    server {\n        listen 8081;\n        server_name flowable_ui;\n        location / {\n            root /Users/admin/study/workflow/flowable/code/flowable-ui-web;\n            index index.html index.htm;\n        }\n\n        location /flowable_idm {\n            proxy_pass http://localhost:8080/flowable;\n            proxy_cookie_path  /flowable  /flowable_idm;\n        }\n\n        location /flowable_task {\n            proxy_pass http://localhost:8080/flowable;\n            proxy_cookie_path  /flowable  /flowable_task;\n        }\n\n        location /flowable_admin {\n            proxy_pass http://localhost:8080/flowable;\n            proxy_cookie_path  /flowable  /flowable_admin;\n        }\n\n        location /flowable_modeler {\n            proxy_pass http://localhost:8080/flowable;\n            proxy_cookie_path  /flowable  /flowable_modeler;\n        }\n\n    }\n\n    # another virtual host using mix of IP-, name-, and port-based configuration\n    #\n    #server {\n    #    listen       8000;\n    #    listen       somename:8080;\n    #    server_name  somename  alias  another.alias;\n\n    #    location / {\n    #        root   html;\n    #        index  index.html index.htm;\n    #    }\n    #}\n\n\n    # HTTPS server\n    #\n    #server {\n    #    listen       443 ssl;\n    #    server_name  localhost;\n\n    #    ssl_certificate      cert.pem;\n    #    ssl_certificate_key  cert.key;\n\n    #    ssl_session_cache    shared:SSL:1m;\n    #    ssl_session_timeout  5m;\n\n    #    ssl_ciphers  HIGH:!aNULL:!MD5;\n    #    ssl_prefer_server_ciphers  on;\n\n    #    location / {\n    #        root   html;\n    #        index  index.html index.htm;\n    #    }\n    #}\n    include servers/*;\n}\n"
  },
  {
    "path": "flowable-ui-web/task/browserconfig.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<browserconfig>\n  <msapplication>\n    <tile>\n      <square150x150logo src=\"images/mstile-150x150.png?v=Om5N75Y123\"/>\n      <TileColor>#da532c</TileColor>\n    </tile>\n  </msapplication>\n</browserconfig>\n"
  },
  {
    "path": "flowable-ui-web/task/display/Gruntfile.js",
    "content": "/* 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'use strict';\n\nmodule.exports = function (grunt) {\n\n    require('load-grunt-tasks')(grunt);\n    require('time-grunt')(grunt);\n\n    grunt.initConfig({\n        yeoman: {\n            app: require('./package.json').appPath || 'app',\n            dist: 'dist'\n        },\n        clean: {\n            dist: {\n                files: [\n                    {\n                        dot: true,\n                        src: [\n                            '.tmp',\n                            '<%= yeoman.dist %>/*',\n                            '!<%= yeoman.dist %>/.git*'\n                        ]\n                    }\n                ]\n            },\n            server: '.tmp'\n        },\n        useminPrepare: {\n            html: 'displaymodel.html',\n            options: {\n                dest: '<%= yeoman.dist %>/'\n            }\n        },\n        usemin: {\n            html: ['<%= yeoman.dist %>/{,*/}*.html'],\n            css: ['<%= yeoman.dist %>/display/styles/{,*/}*.css'],\n            options: {\n                dirs: ['<%= yeoman.dist %>']\n            }\n        },\n        // Put files not handled in other tasks here\n        copy: {\n          dist: {\n            files: [{\n              expand: true,\n              dot: true,\n              cwd: '.',\n              dest: '<%= yeoman.dist %>',\n              src: [\n                'fonts/*'\n              ]\n            }, {\n              expand: true,\n              cwd: '.tmp/images',\n              dest: '<%= yeoman.dist %>/images',\n              src: [\n                'generated/*'\n              ]\n            }]\n          },\n          styles: {\n            expand: true,\n            cwd: 'styles',\n            dest: '.tmp/styles/',\n            src: '{,*/}*.css'\n          },\n          index: {\n            expand: true,\n            cwd: './',\n            src: ['*.html', 'views/**/**.html'],\n            dest: '<%= yeoman.dist %>'\n          },\n          copyCss : {\n            files: [\n          {expand: true, cwd:'.tmp/concat/display/styles/', src:'*.css', dest:'<%= yeoman.dist %>/display/styles/', filter: 'isFile'}\n            ]\n          },\n          copyJs : {\n            files: [\n          {expand: true, cwd:'.tmp/concat/display/scripts', src:'*.js', dest:'<%= yeoman.dist %>/display/scripts/', filter: 'isFile'}\n            ]\n          },\n        },  \n        ngAnnotate: {\n            dist: {\n                files: [\n                    {\n                        expand: true,\n                        cwd: '.tmp/concat/display/scripts',\n                        src: '*.js',\n                        dest: '.tmp/concat/display/scripts'\n                    }\n                ]\n            }\n        },\n        uglify: {\n            dist: {\n                options: {\n                    mangle: true\n                },\n                files: {\n                    '<%= yeoman.dist %>/display/scripts/displaymodel-logic.js': [\n                        '<%= yeoman.dist %>/display/scripts/displaymodel-logic.js'\n                    ]\n                }\n            }\n        },\n        rev: {\n            dist: {\n                files: {\n                    src: [\n                        '<%= yeoman.dist %>/display/{,*/}*.js',\n                        '<%= yeoman.dist %>/display/{,*/}*.css',\n                        '<%= yeoman.dist %>/{,*/}*.{png,jpg,jpeg,gif,webp,svg}'\n                    ]\n                }\n            }\n        }\n    });\n\n    grunt.registerTask('buildApp', [\n        'clean:dist',\n        'useminPrepare',\n        'copy:styles',\n        'concat',\n        'copy:dist',\n        'ngAnnotate',\n        'copy:copyCss',\n        'copy:copyJs',\n        'copy:index',\n        'uglify',\n        'rev',\n        'usemin'\n    ]);\n\n\n    grunt.registerTask('default', [\n        'buildApp'\n    ]);\n\n};\n"
  },
  {
    "path": "flowable-ui-web/task/display/Polyline.js",
    "content": "/* Copyright 2005-2015 Alfresco Software, Ltd.\n * \n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n * \n *      http://www.apache.org/licenses/LICENSE-2.0\n * \n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Class to generate polyline\n *\n * @author Dmitry Farafonov\n */\n \nvar ANCHOR_TYPE= {\n\tmain: \"main\",\n\tmiddle: \"middle\",\n\tfirst: \"first\",\n\tlast: \"last\"\n};\n\nfunction Anchor(uuid, type, x, y) {\n\tthis.uuid = uuid; \n\tthis.x = x;\n\tthis.y = y;\n\tthis.type = (type == ANCHOR_TYPE.middle) ? ANCHOR_TYPE.middle : ANCHOR_TYPE.main;\n};\nAnchor.prototype = {\n\tuuid: null,\n\tx: 0,\n\ty: 0,\n\ttype: ANCHOR_TYPE.main,\n\tisFirst: false,\n\tisLast: false,\n\tndex: 0,\n\ttypeIndex: 0\n};\n\nfunction Polyline(uuid, points, strokeWidth, paper) {\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.paper = paper;\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: 1,\n\tshowDetails: false,\n\tpaper: null,\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{\n\t\t\tvar line1 = this.getLine(i-1);\n\t\t\tthis.pushAnchor(ANCHOR_TYPE.main,  line1.x2, line1.y2);\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    if (this.points.length > i && this.points[i]) {\n\t        return {x1: this.points[i].x, y1: this.points[i].y, x2: this.points[i+1].x, y2: this.points[i+1].y};\n\t    } else {\n\t        return undefined;\n\t    }\n\t},\n\tgetLine: function(i){\n\t\tvar line = this._getLine(i);\n\t\tif (line != undefined) {\n\t\t    line.angle = this.getLineAngle(i);\n\t\t}\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\treturn Math.sqrt(Math.pow(this.getLineLengthX(i), 2) + Math.pow(this.getLineLengthY(i), 2));\n\t},\n\t\n\tgetAnchors: function(){\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\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\t\t\t// 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\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} 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}\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{\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{\n\t\tthis.element.transform(transformation);\n\t},\n\tattr: function(attrs)\n\t{\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\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};"
  },
  {
    "path": "flowable-ui-web/task/display/bpmn-draw.js",
    "content": "/* Copyright 2005-2015 Alfresco Software, Ltd.\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 */\nfunction _bpmnGetColor(element, defaultColor)\n{\n    var strokeColor;\n    if (selectedElement && selectedElement === element.id) {\n        strokeColor = 'red';\n    } else if(element.current) {\n        strokeColor = CURRENT_COLOR;\n    } else if(element.completed) {\n        strokeColor = COMPLETED_COLOR;\n    } else {\n        strokeColor = defaultColor;\n    }\n    return strokeColor;\n}\n\nfunction _drawPool(pool)\n{\n\tvar rect = paper.rect(pool.x, pool.y, pool.width, pool.height);\n\n\trect.attr({\"stroke-width\": 1,\n\t\t\"stroke\": \"#000000\",\n\t\t\"fill\": \"white\"\n \t});\n\n\tif (pool.name)\n\t{\n\t\tvar poolName = paper.text(pool.x + 14, pool.y + (pool.height / 2), pool.name).attr({\n\t        \"text-anchor\" : \"middle\",\n\t        \"font-family\" : \"Arial\",\n\t        \"font-size\" : \"12\",\n\t        \"fill\" : \"#000000\"\n\t  \t});\n\n\t\tpoolName.transform(\"r270\");\n\t}\n\n\tif (pool.lanes)\n\t{\n\t\tfor (var i = 0; i < pool.lanes.length; i++)\n\t\t{\n\t\t\tvar lane = pool.lanes[i];\n\t\t\t_drawLane(lane);\n\t\t}\n\t}\n}\n\nfunction _drawLane(lane)\n{\n\tvar rect = paper.rect(lane.x, lane.y, lane.width, lane.height);\n\n\trect.attr({\"stroke-width\": 1,\n\t\t\"stroke\": \"#000000\",\n\t\t\"fill\": \"white\"\n \t});\n\n\tif (lane.name)\n\t{\n\t\tvar laneName = paper.text(lane.x + 10, lane.y + (lane.height / 2), lane.name).attr({\n\t        \"text-anchor\" : \"middle\",\n\t        \"font-family\" : \"Arial\",\n\t        \"font-size\" : \"12\",\n\t        \"fill\" : \"#000000\"\n\t  \t});\n\n\t\tlaneName.transform(\"r270\");\n\t}\n}\n\nfunction _drawSubProcess(element)\n{\n\tvar rect = paper.rect(element.x, element.y, element.width, element.height, 4);\n\n\tvar strokeColor = _bpmnGetColor(element, MAIN_STROKE_COLOR);\n\n\trect.attr({\"stroke-width\": 1,\n\t\t\"stroke\": strokeColor,\n\t\t\"fill\": \"white\"\n \t});\n \t\n \tif (element.collapsed) {\n        if (element.name) {\n            this._drawMultilineText(element.name, element.x, element.y, element.width, element.height, \"middle\", \"middle\", 11,\n            _bpmnGetColor(element, TEXT_COLOR));\n        }\n        \n        var topRect = paper.rect(element.x, element.y, element.width, element.height, 4);\n        topRect.attr({\n            \"opacity\": 0,\n            \"stroke\" : \"none\",\n            \"fill\" : \"white\"\n        });\n\n        topRect.click(function() {\n            _expandCollapsedElement(element);\n        });\n    }\n}\n\nfunction _drawTransaction(element)\n{\n\tvar rect = paper.rect(element.x, element.y, element.width, element.height, 4);\n\n\tvar strokeColor = _bpmnGetColor(element, MAIN_STROKE_COLOR);\n\n\trect.attr({\"stroke-width\": 1,\n\t\t\"stroke\": strokeColor,\n\t\t\"fill\": \"white\"\n \t});\n\n\tvar borderRect = paper.rect(element.x + 2, element.y + 2, element.width - 4, element.height -4, 4);\n\n\tborderRect.attr({\"stroke-width\": 1,\n\t\t\"stroke\": \"black\",\n\t\t\"fill\": \"none\"\n \t});\n}\n\nfunction _drawEventSubProcess(element)\n{\n\tvar rect = paper.rect(element.x, element.y, element.width, element.height, 4);\n\tvar strokeColor = _bpmnGetColor(element, MAIN_STROKE_COLOR);\n\n\trect.attr({\"stroke-width\": 1,\n\t\t\"stroke\": strokeColor,\n\t\t\"stroke-dasharray\": \".\",\n\t\t\"fill\": \"white\"\n \t});\n}\n\nfunction _drawStartEvent(element)\n{\n\tvar startEvent = _drawEvent(element, NORMAL_STROKE, 15);\n\tstartEvent.click(function() {\n\t\t_zoom(true);\n\t});\n\t_addHoverLogic(element, \"circle\", MAIN_STROKE_COLOR);\n}\n\nfunction _drawEndEvent(element)\n{\n\tvar endEvent = _drawEvent(element, ENDEVENT_STROKE, 14);\n\tendEvent.click(function() {\n\t\t_zoom(false);\n\t});\n\t_addHoverLogic(element, \"circle\", MAIN_STROKE_COLOR);\n}\n\nfunction _drawEvent(element, strokeWidth, radius)\n{\n\tvar x = element.x + (element.width / 2);\n\tvar y = element.y + (element.height / 2);\n\n\tvar circle = paper.circle(x, y, radius);\n\n\tvar strokeColor = _bpmnGetColor(element, MAIN_STROKE_COLOR);\n\n    // Fill\n    var eventFillColor = _determineCustomFillColor(element, \"#ffffff\");\n\n    // Opacity\n    var eventOpacity = 1.0;\n    if (customActivityBackgroundOpacity) {\n        eventOpacity = customActivityBackgroundOpacity;\n    }\n\n\tcircle.attr({\"stroke-width\": strokeWidth,\n\t\t\"stroke\": strokeColor,\n\t\t\"fill\": eventFillColor,\n        \"fill-opacity\": eventOpacity\n \t});\n\n\tcircle.id = element.id;\n\n\t_drawEventIcon(paper, element);\n\n\treturn circle;\n}\n\nfunction _drawServiceTask(element)\n{\n\t_drawTask(element);\n\tif (element.taskType === \"mail\")\n\t{\n\t\t_drawSendTaskIcon(paper, element.x + 4, element.y + 4);\n\t}\n\telse if (element.taskType === \"camel\")\n\t{\n\t\t_drawCamelTaskIcon(paper, element.x + 4, element.y + 4);\n\t}\n\telse if (element.taskType === \"mule\")\n\t{\n\t\t_drawMuleTaskIcon(paper, element.x + 4, element.y + 4);\n\t}\n    else if (element.taskType === \"alfresco_publish\")\n    {\n        _drawAlfrescoPublishTaskIcon(paper, element.x + 4, element.y + 4);\n    }\n    else if (element.taskType === \"http\")\n    {\n        _drawHttpTaskIcon(paper, element.x + 4, element.y + 4);\n    }\n\telse if (element.taskType === \"shell\")\n    {\n        _drawShellTaskIcon(paper, element.x + 4, element.y + 4);\n    }\n\telse if (element.stencilIconId)\n\t{\n\t\tpaper.image(\"../service/stencilitem/\" + element.stencilIconId + \"/icon\", element.x + 4, element.y + 4, 16, 16);\n\t}\n\telse\n\t{\n\t\t_drawServiceTaskIcon(paper, element.x + 4, element.y + 4);\n\t}\n\t_addHoverLogic(element, \"rect\", ACTIVITY_STROKE_COLOR);\n}\n\nfunction _drawHttpServiceTask(element)\n{\n    _drawTask(element);\n    _drawHttpTaskIcon(paper, element.x + 4, element.y + 4);\n    _addHoverLogic(element, \"rect\", ACTIVITY_STROKE_COLOR);\n}\n\nfunction _drawCallActivity(element)\n{\n    var width = element.width - (CALL_ACTIVITY_STROKE / 2);\n    var height = element.height - (CALL_ACTIVITY_STROKE / 2);\n\n    var rect = paper.rect(element.x, element.y, width, height, 4);\n\n    var strokeColor = _bpmnGetColor(element, ACTIVITY_STROKE_COLOR);\n\n    // Fill\n    var callActivityFillColor = _determineCustomFillColor(element, ACTIVITY_FILL_COLOR);\n\n    // Opacity\n    var callActivityOpacity = 1.0;\n    if (customActivityBackgroundOpacity) {\n        callActivityOpacity = customActivityBackgroundOpacity;\n    }\n\n    rect.attr({\"stroke-width\": CALL_ACTIVITY_STROKE,\n        \"stroke\": strokeColor,\n        \"fill\": callActivityFillColor,\n        \"fill-opacity\": callActivityOpacity\n    });\n\n    rect.id = element.id;\n\n    if (element.name) {\n        this._drawMultilineText(element.name, element.x, element.y, element.width, element.height, \"middle\", \"middle\", 11);\n    }\n    _addHoverLogic(element, \"rect\", ACTIVITY_STROKE_COLOR);\n}\n\nfunction _drawScriptTask(element)\n{\n\t_drawTask(element);\n\t_drawScriptTaskIcon(paper, element.x + 4, element.y + 4);\n\t_addHoverLogic(element, \"rect\", ACTIVITY_STROKE_COLOR);\n}\n\nfunction _drawUserTask(element)\n{\n\t_drawTask(element);\n\t_drawUserTaskIcon(paper, element.x + 4, element.y + 4);\n\t_addHoverLogic(element, \"rect\", ACTIVITY_STROKE_COLOR);\n}\n\nfunction _drawBusinessRuleTask(element)\n{\n\t_drawTask(element);\n\t_drawBusinessRuleTaskIcon(paper, element.x + 4, element.y + 4);\n\t_addHoverLogic(element, \"rect\", ACTIVITY_STROKE_COLOR);\n}\n\nfunction _drawManualTask(element)\n{\n\t_drawTask(element);\n\t_drawManualTaskIcon(paper, element.x + 4, element.y + 4);\n\t_addHoverLogic(element, \"rect\", ACTIVITY_STROKE_COLOR);\n}\n\nfunction _drawSendTask(element)\n{\n    _drawTask(element);\n    _drawSendTaskIcon(paper, element.x + 4, element.y + 4);\n    _addHoverLogic(element, \"rect\", ACTIVITY_STROKE_COLOR);\n}\n\nfunction _drawReceiveTask(element)\n{\n\t_drawTask(element);\n\t_drawReceiveTaskIcon(paper, element.x, element.y);\n\t_addHoverLogic(element, \"rect\", ACTIVITY_STROKE_COLOR);\n}\n\nfunction _drawTask(element)\n{\n    var rectAttrs = {};\n\n    // Stroke\n    var strokeColor = _bpmnGetColor(element, ACTIVITY_STROKE_COLOR);\n    rectAttrs['stroke'] = strokeColor;\n\n    var strokeWidth;\n    if (strokeColor === ACTIVITY_STROKE_COLOR) {\n        strokeWidth = TASK_STROKE;\n    } else {\n        strokeWidth = TASK_HIGHLIGHT_STROKE;\n    }\n\n\tvar width = element.width - (strokeWidth / 2);\n\tvar height = element.height - (strokeWidth / 2);\n\n\tvar rect = paper.rect(element.x, element.y, width, height, 4);\n    rectAttrs['stroke-width'] = strokeWidth;\n\n    // Fill\n\tvar fillColor = _determineCustomFillColor(element, ACTIVITY_FILL_COLOR);\n    rectAttrs['fill'] = fillColor;\n\n    // Opacity\n    if (customActivityBackgroundOpacity) {\n        rectAttrs['fill-opacity'] = customActivityBackgroundOpacity;\n    }\n\n\trect.attr(rectAttrs);\n\trect.id = element.id;\n\n\tif (element.name) {\n\t\tthis._drawMultilineText(element.name, element.x, element.y, element.width, element.height, \"middle\", \"middle\", 11);\n\t}\n}\n\nfunction _drawExclusiveGateway(element)\n{\n\t_drawGateway(element);\n\tvar quarterWidth = element.width / 4;\n\tvar quarterHeight = element.height / 4;\n\n\tvar iks = paper.path(\n\t\t\"M\" + (element.x + quarterWidth + 3) + \" \" + (element.y + quarterHeight + 3) +\n\t\t\"L\" + (element.x + 3 * quarterWidth - 3) + \" \" + (element.y + 3 * quarterHeight - 3) +\n\t\t\"M\" + (element.x + quarterWidth + 3) + \" \" + (element.y + 3 * quarterHeight - 3) +\n\t\t\"L\" + (element.x + 3 * quarterWidth - 3) + \" \" + (element.y + quarterHeight + 3)\n\t);\n\n\tvar strokeColor = _bpmnGetColor(element, MAIN_STROKE_COLOR);\n\n    // Fill\n    var gatewayFillColor = _determineCustomFillColor(element, ACTIVITY_FILL_COLOR);\n\n    // Opacity\n    var gatewayOpacity = 1.0;\n    if (customActivityBackgroundOpacity) {\n        gatewayOpacity = customActivityBackgroundOpacity;\n    }\n\n\n    iks.attr({\"stroke-width\": 3, \"stroke\": strokeColor, \"fill\": gatewayFillColor, \"fill-opacity\": gatewayOpacity});\n\n\t_addHoverLogic(element, \"rhombus\", MAIN_STROKE_COLOR);\n}\n\nfunction _drawParallelGateway(element)\n{\n\t_drawGateway(element);\n\n\tvar strokeColor = _bpmnGetColor(element, MAIN_STROKE_COLOR);\n\n\tvar path1 = paper.path(\"M 6.75,16 L 25.75,16 M 16,6.75 L 16,25.75\");\n\n    // Fill\n    var gatewayFillColor = _determineCustomFillColor(element, ACTIVITY_FILL_COLOR);\n\n    // Opacity\n    var gatewayOpacity = 1.0;\n    if (customActivityBackgroundOpacity) {\n        gatewayOpacity = customActivityBackgroundOpacity;\n    }\n\n\tpath1.attr({\n\t\t\"stroke-width\": 3,\n\t\t\"stroke\": strokeColor,\n\t\t\"fill\": gatewayFillColor,\n        \"fill-opacity\": gatewayOpacity\n\t});\n\n\tpath1.transform(\"T\" + (element.x + 4) + \",\" + (element.y + 4));\n\n\t_addHoverLogic(element, \"rhombus\", MAIN_STROKE_COLOR);\n}\n\nfunction _drawInclusiveGateway(element)\n{\n\t_drawGateway(element);\n\n\tvar strokeColor = _bpmnGetColor(element, MAIN_STROKE_COLOR);\n\n\tvar circle1 = paper.circle(element.x + (element.width / 2), element.y + (element.height / 2), 9.75);\n\n    // Fill\n    var gatewayFillColor = _determineCustomFillColor(element, ACTIVITY_FILL_COLOR);\n\n    // Opacity\n    var gatewayOpacity = 1.0;\n    if (customActivityBackgroundOpacity) {\n        gatewayOpacity = customActivityBackgroundOpacity;\n    }\n\n\tcircle1.attr({\n\t\t\"stroke-width\": 2.5,\n\t\t\"stroke\": strokeColor,\n\t\t\"fill\": gatewayFillColor,\n        \"fill-opacity\": gatewayOpacity\n\t});\n\n\t_addHoverLogic(element, \"rhombus\", MAIN_STROKE_COLOR);\n}\n\nfunction _drawEventGateway(element)\n{\n\t_drawGateway(element);\n\n\tvar strokeColor = _bpmnGetColor(element, MAIN_STROKE_COLOR);\n\n\tvar circle1 = paper.circle(element.x + (element.width / 2), element.y + (element.height / 2), 10.4);\n\n    // Fill\n    var gatewayFillColor = _determineCustomFillColor(element, ACTIVITY_FILL_COLOR);\n\n    // Opacity\n    var gatewayOpacity = 1.0;\n    if (customActivityBackgroundOpacity) {\n        gatewayOpacity = customActivityBackgroundOpacity;\n    }\n\n\tcircle1.attr({\n\t\t\"stroke-width\": 0.5,\n\t\t\"stroke\": strokeColor,\n\t\t\"fill\": gatewayFillColor,\n        \"fill-opacity\": gatewayOpacity\n    });\n\n\tvar circle2 = paper.circle(element.x + (element.width / 2), element.y + (element.height / 2), 11.7);\n\tcircle2.attr({\n\t\t\"stroke-width\": 0.5,\n\t\t\"stroke\": strokeColor,\n        \"fill\": gatewayFillColor,\n        \"fill-opacity\": gatewayOpacity\n\t});\n\n\tvar path1 = paper.path(\"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\tpath1.attr({\n\t\t\"stroke-width\": 1.39999998,\n\t\t\"stroke\": strokeColor,\n        \"fill\": gatewayFillColor,\n        \"fill-opacity\": gatewayOpacity,\n\t\t\"stroke-linejoin\": \"bevel\"\n\t});\n\n\tpath1.transform(\"T\" + (element.x + 4) + \",\" + (element.y + 4));\n\n\t_addHoverLogic(element, \"rhombus\", MAIN_STROKE_COLOR);\n}\n\nfunction _drawGateway(element)\n{\n    var strokeColor = _bpmnGetColor(element, MAIN_STROKE_COLOR);\n\n\tvar rhombus = paper.path(\"M\" + element.x + \" \" + (element.y + (element.height / 2)) +\n\t\t\"L\" + (element.x + (element.width / 2)) + \" \" + (element.y + element.height) +\n\t\t\"L\" + (element.x + element.width) + \" \" + (element.y + (element.height / 2)) +\n\t\t\"L\" + (element.x + (element.width / 2)) + \" \" + element.y + \"z\"\n\t);\n\n    // Fill\n    var gatewayFillColor = _determineCustomFillColor(element, ACTIVITY_FILL_COLOR);\n\n    // Opacity\n    var gatewayOpacity = 1.0;\n    if (customActivityBackgroundOpacity) {\n        gatewayOpacity = customActivityBackgroundOpacity;\n    }\n\n\trhombus.attr(\"stroke-width\", 2);\n\trhombus.attr(\"stroke\", strokeColor);\n\trhombus.attr(\"fill\", gatewayFillColor);\n    rhombus.attr(\"fill-opacity\", gatewayOpacity);\n\n\trhombus.id = element.id;\n\n\treturn rhombus;\n}\n\nfunction _drawBoundaryEvent(element)\n{\n\tvar x = element.x + (element.width / 2);\n\tvar y = element.y + (element.height / 2);\n\n\tvar circle = paper.circle(x, y, 15);\n\n\tvar strokeColor = _bpmnGetColor(element, MAIN_STROKE_COLOR);\n\n\tcircle.attr({\"stroke-width\": 1,\n\t\t\"stroke\": strokeColor,\n\t\t\"fill\": \"white\"\n \t});\n\n\tvar innerCircle = paper.circle(x, y, 12);\n\n\tinnerCircle.attr({\"stroke-width\": 1,\n\t\t\"stroke\": strokeColor,\n\t\t\"fill\": \"none\"\n \t});\n\n\t_drawEventIcon(paper, element);\n\t_addHoverLogic(element, \"circle\", MAIN_STROKE_COLOR);\n\n\tcircle.id = element.id;\n\tinnerCircle.id = element.id + \"_inner\";\n}\n\nfunction _drawStringDataObject(element) {\n}\n\nfunction _drawIntermediateCatchEvent(element)\n{\n\tvar x = element.x + (element.width / 2);\n\tvar y = element.y + (element.height / 2);\n\n\tvar circle = paper.circle(x, y, 15);\n\n\tvar strokeColor = _bpmnGetColor(element, MAIN_STROKE_COLOR);\n\n\tcircle.attr({\"stroke-width\": 1,\n\t\t\"stroke\": strokeColor,\n\t\t\"fill\": \"white\"\n \t});\n\n\tvar innerCircle = paper.circle(x, y, 12);\n\n\tinnerCircle.attr({\"stroke-width\": 1,\n\t\t\"stroke\": strokeColor,\n\t\t\"fill\": \"none\"\n \t});\n\n\t_drawEventIcon(paper, element);\n\t_addHoverLogic(element, \"circle\", MAIN_STROKE_COLOR);\n\n\tcircle.id = element.id;\n\tinnerCircle.id = element.id + \"_inner\";\n}\n\nfunction _drawThrowEvent(element)\n{\n\tvar x = element.x + (element.width / 2);\n\tvar y = element.y + (element.height / 2);\n\n\tvar circle = paper.circle(x, y, 15);\n\n\tvar strokeColor = _bpmnGetColor(element, MAIN_STROKE_COLOR);\n\n\tcircle.attr({\"stroke-width\": 1,\n\t\t\"stroke\": strokeColor,\n\t\t\"fill\": \"white\"\n \t});\n\n\tvar innerCircle = paper.circle(x, y, 12);\n\n\tinnerCircle.attr({\"stroke-width\": 1,\n\t\t\"stroke\": strokeColor,\n\t\t\"fill\": \"none\"\n \t});\n\n\t_drawEventIcon(paper, element);\n\t_addHoverLogic(element, \"circle\", MAIN_STROKE_COLOR);\n\n\tcircle.id = element.id;\n\tinnerCircle.id = element.id + \"_inner\";\n}\n\nfunction _drawMultilineText(text, x, y, boxWidth, boxHeight, horizontalAnchor, verticalAnchor, fontSize)\n{\n\tif (!text || text == \"\")\n\t{\n\t\treturn;\n\t}\n\n\tvar textBoxX, textBoxY;\n    var width = boxWidth - (2 * TEXT_PADDING);\n\n    if (horizontalAnchor === \"middle\")\n    {\n    \ttextBoxX = x + (boxWidth / 2);\n    }\n    else if (horizontalAnchor === \"start\")\n    {\n    \ttextBoxX = x;\n    }\n\n    textBoxY = y + (boxHeight / 2);\n\n \tvar t = paper.text(textBoxX + TEXT_PADDING, textBoxY + TEXT_PADDING).attr({\n        \"text-anchor\" : horizontalAnchor,\n        \"font-family\" : \"Arial\",\n        \"font-size\" : fontSize,\n        \"fill\" : \"#373e48\"\n  \t});\n\n    var abc = \"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ\";\n    t.attr({\n        \"text\" : abc\n    });\n    var letterWidth = t.getBBox().width / abc.length;\n\n    t.attr({\n        \"text\" : text\n    });\n    var removedLineBreaks = text.split(\"\\n\");\n    var x = 0, s = [];\n    for (var r = 0; r < removedLineBreaks.length; r++)\n    {\n  \t    var words = removedLineBreaks[r].split(\" \");\n  \t    for ( var i = 0; i < words.length; i++) {\n\n  \t        var l = words[i].length;\n  \t        if (x + (l * letterWidth) > width) {\n  \t            s.push(\"\\n\");\n  \t            x = 0;\n  \t        }\n  \t        x += l * letterWidth;\n  \t        s.push(words[i] + \" \");\n  \t    }\n\t  \ts.push(\"\\n\");\n        x = 0;\n    }\n    t.attr({\n    \t\"text\" : s.join(\"\")\n    });\n\n    if (verticalAnchor && verticalAnchor === \"top\")\n    {\n    \tt.attr({\"y\": y + (t.getBBox().height / 2)});\n    }\n}\n\nfunction _drawTextAnnotation(element)\n{\n\tvar path1 = paper.path(\"M20,1 L1,1 L1,50 L20,50\");\n\tpath1.attr({\n\t\t\"stroke\": \"#585858\",\n\t\t\"fill\": \"none\"\n \t});\n\n\tvar annotation = paper.set();\n\tannotation.push(path1);\n\n\tannotation.transform(\"T\" + element.x + \",\" + element.y);\n\n\tif (element.text) {\n\t\tthis._drawMultilineText(element.text, element.x + 2, element.y, element.width, element.height, \"start\", \"middle\", 11);\n\t}\n}\n\nfunction _drawFlow(flow){\n\n\tvar polyline = new Polyline(flow.id, flow.waypoints, SEQUENCEFLOW_STROKE, paper);\n\n\tvar strokeColor = _bpmnGetColor(flow, MAIN_STROKE_COLOR);\n\n\tpolyline.element = paper.path(polyline.path);\n\tpolyline.element.attr({\"stroke-width\":SEQUENCEFLOW_STROKE});\n\tpolyline.element.attr({\"stroke\":strokeColor});\n\n\tpolyline.element.id = flow.id;\n\n\tvar lastLineIndex = polyline.getLinesCount() - 1;\n\tvar line = polyline.getLine(lastLineIndex);\n\n\tif (line == undefined) return;\n\n\tif (flow.type == \"connection\" && flow.conditions)\n\t{\n\t\tvar middleX = (line.x1 + line.x2) / 2;\n\t\tvar middleY = (line.y1 + line.y2) / 2;\n\t\tvar image = paper.image(\"../editor/images/condition-flow.png\", middleX - 8, middleY - 8, 16, 16);\n\t}\n\n\tvar polylineInvisible = new Polyline(flow.id, flow.waypoints, SEQUENCEFLOW_STROKE, paper);\n\n\tpolylineInvisible.element = paper.path(polyline.path);\n\tpolylineInvisible.element.attr({\n\t\t\t\"opacity\": 0,\n\t\t\t\"stroke-width\": 8,\n            \"stroke\" : \"#000000\"\n\t});\n\n    if (flow.name) {\n        var firstLine = polyline.getLine(0);\n\n        var angle;\n        if (firstLine.x1 !== firstLine.x2) {\n            angle = Math.atan((firstLine.y2 - firstLine.y1) / (firstLine.x2 - firstLine.x1));\n        } else if (firstLine.y1 < firstLine.y2) {\n            angle = Math.PI / 2;\n        } else {\n            angle = -Math.PI / 2;\n        }\n        var flowName = paper.text(firstLine.x1, firstLine.y1, flow.name).attr({\n            \"text-anchor\": \"middle\",\n            \"font-family\" : \"Arial\",\n            \"font-size\" : \"12\",\n            \"fill\" : \"#000000\"\n        });\n\n        var offsetX = (flowName.getBBox().width / 2 + 5);\n        var offsetY = -(flowName.getBBox().height / 2 + 5);\n\n        if (firstLine.x1 > firstLine.x2) {\n            offsetX = -offsetX;\n        }\n        var rotatedOffsetX = offsetX * Math.cos(angle) - offsetY * Math.sin(angle);\n        var rotatedOffsetY = offsetX * Math.sin(angle) + offsetY * Math.cos(angle);\n\n        flowName.attr({\n            x: firstLine.x1 + rotatedOffsetX,\n            y: firstLine.y1 + rotatedOffsetY\n        });\n\n        flowName.transform(\"r\" + ((angle) * 180) / Math.PI);\n    }\n\n\t_showTip(jQuery(polylineInvisible.element.node), flow);\n\n\tpolylineInvisible.element.mouseover(function() {\n\t\tpaper.getById(polyline.element.id).attr({\"stroke\":\"blue\"});\n\t});\n\n\tpolylineInvisible.element.mouseout(function() {\n\t\tpaper.getById(polyline.element.id).attr({\"stroke\":\"#585858\"});\n\t});\n\n\t_drawArrowHead(line);\n}\n\nfunction _drawAssociation(flow){\n\n\tvar polyline = new Polyline(flow.id, flow.waypoints, ASSOCIATION_STROKE, paper);\n\n\tpolyline.element = paper.path(polyline.path);\n\tpolyline.element.attr({\"stroke-width\": ASSOCIATION_STROKE});\n\tpolyline.element.attr({\"stroke-dasharray\": \". \"});\n\tpolyline.element.attr({\"stroke\":\"#585858\"});\n\n\tpolyline.element.id = flow.id;\n\n\tvar polylineInvisible = new Polyline(flow.id, flow.waypoints, ASSOCIATION_STROKE, paper);\n\n\tpolylineInvisible.element = paper.path(polyline.path);\n\tpolylineInvisible.element.attr({\n\t\t\t\"opacity\": 0,\n\t\t\t\"stroke-width\": 8,\n            \"stroke\" : \"#000000\"\n\t});\n\n\t_showTip(jQuery(polylineInvisible.element.node), flow);\n\n\tpolylineInvisible.element.mouseover(function() {\n\t\tpaper.getById(polyline.element.id).attr({\"stroke\":\"blue\"});\n\t});\n\n\tpolylineInvisible.element.mouseout(function() {\n\t\tpaper.getById(polyline.element.id).attr({\"stroke\":\"#585858\"});\n\t});\n}\n\nfunction _drawArrowHead(line, connectionType)\n{\n\tvar doubleArrowWidth = 2 * ARROW_WIDTH;\n\n\tvar arrowHead = paper.path(\"M0 0L-\" + (ARROW_WIDTH / 2 + .5) + \" -\" + doubleArrowWidth + \"L\" + (ARROW_WIDTH/2 + .5) + \" -\" + doubleArrowWidth + \"z\");\n\n\t// anti smoothing\n\tif (this.strokeWidth%2 == 1)\n\t\tline.x2 += .5, line.y2 += .5;\n\n\tarrowHead.transform(\"t\" + line.x2 + \",\" + line.y2 + \"\");\n\tarrowHead.transform(\"...r\" + Raphael.deg(line.angle - Math.PI / 2) + \" \" + 0 + \" \" + 0);\n\n\tarrowHead.attr(\"fill\", \"#585858\");\n\n\tarrowHead.attr(\"stroke-width\", SEQUENCEFLOW_STROKE);\n\tarrowHead.attr(\"stroke\", \"#585858\");\n\n\treturn arrowHead;\n}\n\nfunction _determineCustomFillColor(element, defaultColor) {\n\n    var color;\n\n    // By name\n    if (customActivityColors && customActivityColors[element.name]) {\n        color = customActivityColors[element.name];\n    }\n\n    if (color !== null && color !== undefined) {\n        return color;\n    }\n\n    // By id\n    if (customActivityColors && customActivityColors[element.id]) {\n        color = customActivityColors[element.id];\n    }\n\n    if (color !== null && color !== undefined) {\n        return color;\n    }\n\n    return defaultColor;\n}\n"
  },
  {
    "path": "flowable-ui-web/task/display/bpmn-icons.js",
    "content": "/* Copyright 2005-2015 Alfresco Software, Ltd.\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 */\nfunction _drawUserTaskIcon(paper, startX, startY)\n{\n\tvar path1 = paper.path(\"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\tpath1.attr({\n\t\t\"opacity\": 1,\n\t\t\"stroke\": \"none\",\n\t\t\"fill\": \"#000000\"\n \t});\n\n\tvar userTaskIcon = paper.set();\n\tuserTaskIcon.push(path1);\n\n\tuserTaskIcon.transform(\"T\" + startX + \",\" + startY);\n}\n\nfunction _drawServiceTaskIcon(paper, startX, startY)\n{\n\tvar path1 = paper.path(\"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\tpath1.attr({\n\t\t\"opacity\": 1,\n\t\t\"stroke\": \"none\",\n\t\t\"fill\": \"#000000\"\n \t});\n\n\tvar serviceTaskIcon = paper.set();\n\tserviceTaskIcon.push(path1);\n\n\tserviceTaskIcon.transform(\"T\" + startX + \",\" + startY);\n}\n\nfunction _drawScriptTaskIcon(paper, startX, startY)\n{\n\tvar path1 = paper.path(\"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\tpath1.attr({\n\t\t\"opacity\": 1,\n\t\t\"stroke\": \"none\",\n\t\t\"fill\": \"#000000\"\n \t});\n\n\tvar scriptTaskIcon = paper.set();\n\tscriptTaskIcon.push(path1);\n\n\tscriptTaskIcon.transform(\"T\" + startX + \",\" + startY);\n}\n\nfunction _drawBusinessRuleTaskIcon(paper, startX, startY)\n{\n\tvar path1 = paper.path(\"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\tpath1.attr({\n\t\t\"stroke\": \"none\",\n\t\t\"fill\": \"#000000\"\n \t});\n\n\tvar businessRuleTaskIcon = paper.set();\n\tbusinessRuleTaskIcon.push(path1);\n\n\tbusinessRuleTaskIcon.transform(\"T\" + startX + \",\" + startY);\n}\n\nfunction _drawSendTaskIcon(paper, startX, startY)\n{\n\tvar path1 = paper.path(\"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\tpath1.attr({\n\t\t\"stroke\": \"none\",\n\t\t\"fill\": \"#000000\"\n \t});\n\n\tvar sendTaskIcon = paper.set();\n\tsendTaskIcon.push(path1);\n\n\tsendTaskIcon.transform(\"T\" + startX + \",\" + startY);\n}\n\nfunction _drawManualTaskIcon(paper, startX, startY)\n{\n\tvar path1 = paper.path(\"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\tpath1.attr({\n\t\t\"opacity\": 1,\n\t\t\"stroke\": \"none\",\n\t\t\"fill\": \"#000000\"\n \t});\n\n\tvar manualTaskIcon = paper.set();\n\tmanualTaskIcon.push(path1);\n\n\tmanualTaskIcon.transform(\"T\" + startX + \",\" + startY);\n}\n\nfunction _drawReceiveTaskIcon(paper, startX, startY)\n{\n\tvar path = paper.path(\"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\tpath.attr({\n\t\t\"opacity\": 1,\n\t\t\"stroke\": \"none\",\n\t\t\"fill\": \"#000000\"\n \t});\n\n\tstartX += 4;\n\tstartY += 2;\n\n\tpath.transform(\"T\" + startX + \",\" + startY);\n\n}\n\nfunction _drawCamelTaskIcon(paper, startX, startY)\n{\n\tvar path = paper.path(\"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\tpath.attr({\n\t\t\"opacity\": 1,\n\t\t\"stroke\": \"none\",\n\t\t\"fill\": \"#000000\"\n \t});\n\n\tstartX += 4;\n\tstartY += 2;\n\n\tpath.transform(\"T\" + startX + \",\" + startY);\n\n}\n\nfunction _drawMuleTaskIcon(paper, startX, startY)\n{\n\tvar path = paper.path(\"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\tpath.attr({\n\t\t\"opacity\": 1,\n\t\t\"stroke\": \"none\",\n\t\t\"fill\": \"#000000\"\n \t});\n\n\tstartX += 4;\n\tstartY += 2;\n\n\tpath.transform(\"T\" + startX + \",\" + startY);\n\n}\n\nfunction _drawAlfrescoPublishTaskIcon(paper, startX, startY)\n{\n\n    startX += 2;\n    startY += 2;\n\n    var path = paper.path(\"M4.11870968,2.12890323 L6.12954839,0.117935484 L3.10993548,0.118064516 L3.10270968,0.118064516 C1.42941935,0.118064516 0.0729032258,1.47458065 0.0729032258,3.14774194 C0.0729032258,4.82116129 1.42929032,6.17754839 3.10258065,6.17754839 C3.22967742,6.17754839 3.35470968,6.16877419 3.47767742,6.15354839 C2.8163871,4.85083871 3.02954839,3.21793548 4.11870968,2.12890323M6.57032258,3.144 L6.57032258,0.300258065 L4.43522581,2.4356129 L4.43006452,2.44064516 C3.24683871,3.62387097 3.24683871,5.54219355 4.43006452,6.72541935 C5.61329032,7.90864516 7.5316129,7.90864516 8.71483871,6.72541935 C8.80464516,6.6356129 8.88529032,6.54025806 8.96154839,6.44270968 C7.57341935,5.98864516 6.57045161,4.68387097 6.57032258,3.144\");\n    path.attr({\"fill\": \"#87C040\"});\n\n    var startX1 = startX + 1.419355;\n    var startY1 = startY + 8.387097;\n    path.transform(\"T\" + startX1 + \",\" + startY1);\n\n    path = paper.path(\"M10.4411613,10.5153548 L8.43032258,8.50451613 L8.43032258,11.5313548 C8.43032258,13.2047742 9.78683871,14.5611613 11.460129,14.5611613 C13.1334194,14.5611613 14.4899355,13.2047742 14.4899355,11.5314839 C14.4899355,11.4043871 14.4811613,11.2793548 14.4659355,11.1563871 C13.1632258,11.8178065 11.5303226,11.6045161 10.4411613,10.5153548M15.0376774,5.91935484 C14.947871,5.82954839 14.8526452,5.74890323 14.7550968,5.67264516 C14.3010323,7.06064516 12.996129,8.06374194 11.4563871,8.06374194 L8.61277419,8.06374194 L10.7529032,10.204 C11.936129,11.3872258 13.8545806,11.3872258 15.0376774,10.204 C16.2209032,9.02077419 16.2209032,7.10245161 15.0376774,5.91935484\");\n    path.attr({\"fill\": \"#87C040\"});\n    path.transform(\"T\" + startX + \",\" + startY);\n\n    path = paper.path(\"M5.9083871,1.5636129 C5.78129032,1.5636129 5.65625806,1.57225806 5.53329032,1.58748387 C6.19458065,2.89032258 5.98141935,4.52309677 4.89225806,5.61225806 L2.88154839,7.62309677 L5.9083871,7.62309677 C7.58154839,7.62309677 8.93806452,6.26658065 8.93806452,4.59329032 C8.93819355,2.92 7.58167742,1.5636129 5.9083871,1.5636129\");\n    path.attr({\"fill\": \"#ED9A2D\"});\n    var startX2 = startX + 5.548387;\n    path.transform(\"T\" + startX2 + \",\" + startY);\n    path = paper.path(\"M4.58090323,1.0156129 C3.39767742,-0.167483871 1.47935484,-0.167483871 0.296129032,1.01574194 C0.206451613,1.10554839 0.125806452,1.20077419 0.0495483871,1.29845161 C1.43754839,1.75251613 2.44064516,3.05729032 2.44064516,4.59703226 L2.44064516,7.44077419 L4.57574194,5.30554839 L4.58090323,5.30051613 C5.76412903,4.11729032 5.76412903,2.19896774 4.58090323,1.0156129\");\n    path.attr({\"fill\": \"#5698C6\"});\n    path.transform(\"T\" + startX2 + \",\" + startY);\n\n    path = paper.path(\"M5.54051613,5.61432258 L5.62670968,5.70425806 L7.54632258,7.62387097 L7.5483871,7.62387097 L7.5483871,4.604 L7.5483871,4.59677419 C7.5483871,2.92348387 6.19187097,1.56696774 4.51858065,1.56696774 C2.84529032,1.56696774 1.48877419,2.92335484 1.48890323,4.59664516 C1.48890323,4.72348387 1.49754839,4.84812903 1.51264516,4.97083871 C2.81625806,4.30993548 4.45122581,4.52503226 5.54051613,5.61432258M1.23251613,10.4292903 C1.25625806,10.3588387 1.28180645,10.2894194 1.30980645,10.2210323 C1.31329032,10.2123871 1.3163871,10.2036129 1.32,10.1952258 C1.35070968,10.1216774 1.38451613,10.0500645 1.42,9.97935484 C1.42774194,9.96374194 1.43574194,9.9483871 1.44387097,9.93277419 C1.4803871,9.86258065 1.51883871,9.79354839 1.55987097,9.72632258 C1.56425806,9.71909677 1.56903226,9.71225806 1.57341935,9.70529032 C1.6123871,9.64245161 1.65354839,9.58141935 1.6963871,9.52141935 C1.70516129,9.50903226 1.71380645,9.49651613 1.72283871,9.48425806 C1.76890323,9.42154839 1.81690323,9.36064516 1.86683871,9.30129032 C1.87703226,9.28916129 1.88735484,9.27741935 1.89780645,9.26567742 C1.94658065,9.20916129 1.99690323,9.15406452 2.04916129,9.10090323 C2.05380645,9.09625806 2.05806452,9.09135484 2.06270968,9.08670968 C2.11832258,9.03083871 2.17625806,8.97741935 2.23548387,8.92554839 C2.2483871,8.91419355 2.26129032,8.90296774 2.27432258,8.89187097 C2.33393548,8.84103226 2.39496774,8.79212903 2.45780645,8.74529032 C2.46606452,8.73922581 2.47470968,8.73354839 2.48296774,8.7276129 C2.54167742,8.68490323 2.60180645,8.64412903 2.66322581,8.60503226 C2.67535484,8.59729032 2.68735484,8.58929032 2.6996129,8.58167742 C2.76593548,8.54064516 2.83380645,8.50206452 2.90296774,8.46541935 C2.91754839,8.45780645 2.93225806,8.45045161 2.94696774,8.44296774 C3.016,8.40774194 3.08593548,8.37406452 3.15741935,8.34348387 C3.16090323,8.34206452 3.16425806,8.3403871 3.16774194,8.33883871 C3.24167742,8.30748387 3.31729032,8.27948387 3.39380645,8.25316129 C3.41032258,8.24748387 3.42670968,8.24180645 3.44335484,8.2363871 C3.51909677,8.21174194 3.59587097,8.18903226 3.67380645,8.16929032 C3.68567742,8.16645161 3.69793548,8.16387097 3.70980645,8.16116129 C3.78206452,8.14374194 3.85509677,8.12877419 3.92890323,8.116 C3.94270968,8.11367742 3.9563871,8.11083871 3.97019355,8.10877419 C4.05032258,8.09587097 4.13148387,8.08619355 4.21329032,8.07896774 C4.23096774,8.07741935 4.24877419,8.07625806 4.26645161,8.07483871 C4.35109677,8.06877419 4.43612903,8.06451613 4.52232258,8.06451613 L7.36606452,8.0643871 L5.22580645,5.92412903 C4.04258065,4.74103226 2.12412903,4.74090323 0.941032258,5.92412903 C-0.242193548,7.10735484 -0.242193548,9.02567742 0.941032258,10.2089032 C1.03070968,10.2985806 1.12464516,10.3814194 1.22206452,10.4575484 C1.22529032,10.448 1.22929032,10.4388387 1.23251613,10.4292903\");\n    path.attr({\"fill\": \"#5698C6\"});\n    path.transform(\"T\" + startX + \",\" + startY);\n\n    path = paper.path(\"M5.23290323,5.92412903 L6.92748387,7.61870968 L4.64980645,7.61870968 L4.52064516,7.62141935 C3.13354839,7.62141935 1.96425806,6.68929032 1.60477419,5.41729032 C2.75870968,4.77019355 4.24619355,4.93754839 5.22787097,5.91909677 L5.23290323,5.92412903M7.54722581,4.59612903 L7.54722581,6.99264516 L5.93664516,5.38206452 L5.84348387,5.29264516 C4.86258065,4.31187097 4.69483871,2.82580645 5.34012903,1.67225806 C6.61367742,2.03070968 7.54722581,3.20090323 7.54722581,4.58890323 L7.54722581,4.59612903M10.1385806,5.29819355 L8.444,6.99290323 L8.444,4.71522581 L8.44129032,4.58606452 C8.44129032,3.19896774 9.37341935,2.02954839 10.6454194,1.67019355 C11.2925161,2.82412903 11.1251613,4.3116129 10.1436129,5.29316129 L10.1385806,5.29819355\");\n    path.attr({\"fill\": \"#446BA5\"});\n    path.transform(\"T\" + startX + \",\" + startY);\n\n    path = paper.path(\"M11.4548387,7.61677419 L9.05832258,7.61677419 L10.6689032,6.00619355 L10.7583226,5.91303226 C11.7390968,4.93212903 13.2251613,4.7643871 14.3787097,5.40967742 C14.0202581,6.68322581 12.8500645,7.61677419 11.4620645,7.61677419 L11.4548387,7.61677419\");\n    path.attr({\"fill\": \"#FFF101\"});\n    path.transform(\"T\" + startX + \",\" + startY);\n\n    path = paper.path(\"M10.7470968,10.192 L9.05251613,8.49741935 L11.3301935,8.49741935 L11.4593548,8.49470968 C12.8464516,8.49483871 14.0157419,9.42696774 14.3752258,10.6989677 C13.2211613,11.3459355 11.7338065,11.1787097 10.752129,10.1970323 L10.7470968,10.192M8.43729032,11.5174194 L8.43729032,9.12090323 L10.047871,10.7314839 L10.1411613,10.8209032 C11.1219355,11.8018065 11.2896774,13.2876129 10.6443871,14.4412903 C9.37083871,14.0828387 8.43729032,12.9127742 8.43729032,11.5245161 L8.43729032,11.5174194M5.86193548,10.8296774 L7.55651613,9.13496774 L7.55651613,11.4126452 L7.55922581,11.5418065 C7.55922581,12.9289032 6.62709677,14.0983226 5.35509677,14.4578065 C4.708,13.3036129 4.87535484,11.8162581 5.85690323,10.8347097 L5.86193548,10.8296774M4.53251613,8.50993548 L6.92903226,8.50993548 L5.31845161,10.1205161 L5.22903226,10.2136774 C4.24812903,11.1945806 2.76219355,11.3623226 1.60851613,10.7170323 C1.96709677,9.44335484 3.13716129,8.50993548 4.52529032,8.50993548 L4.53251613,8.50993548\");\n    path.attr({\"fill\": \"#45AB47\"});\n    path.transform(\"T\" + startX + \",\" + startY);\n}\n\nfunction _drawHttpTaskIcon(paper, startX, startY)\n{\n    var path = paper.path(\"m 16.704699,5.9229055 q 0.358098,0 0.608767,0.2506681 0.250669,0.250668 0.250669,0.6087677 0,0.3580997 -0.250669,0.6087677 -0.250669,0.2506679 -0.608767,0.2506679 -0.358098,0 -0.608767,-0.2506679 -0.250669,-0.250668 -0.250669,-0.6087677 0,-0.3580997 0.250669,-0.6087677 0.250669,-0.2506681 0.608767,-0.2506681 z m 2.578308,-2.0053502 q -2.229162,0 -3.854034,0.6759125 -1.624871,0.6759067 -3.227361,2.2694472 -0.716197,0.725146 -1.575633,1.7457293 L 7.2329969,8.7876913 Q 7.0897576,8.8055849 7.000233,8.9309334 L 4.9948821,12.368677 q -0.035811,0.06267 -0.035811,0.143242 0,0.107426 0.080572,0.205905 l 0.5729577,0.572957 q 0.125334,0.116384 0.2864786,0.07162 l 2.4708789,-0.760963 2.5156417,2.515645 -0.76096,2.470876 q -0.009,0.02687 -0.009,0.08057 0,0.125338 0.08058,0.205905 l 0.572957,0.572958 q 0.170096,0.152194 0.349146,0.04476 l 3.437744,-2.005351 q 0.125335,-0.08953 0.143239,-0.232763 l 0.17905,-3.392986 q 1.02058,-0.859435 1.745729,-1.575629 1.67411,-1.6830612 2.309735,-3.2049805 0.635625,-1.5219191 0.635625,-3.8585111 0,-0.1253369 -0.08505,-0.2148575 -0.08505,-0.089526 -0.201431,-0.089526 z\");\n    path.attr({\n        \"opacity\": 1,\n        \"stroke\": \"none\",\n        \"fill\": \"#000000\"\n    });\n\n    startX += -2;\n    startY += -2;\n\n    path.transform(\"T\" + startX + \",\" + startY);\n\n}\n\nfunction _drawShellTaskIcon(paper, startX, startY) {\n    var path = paper.path(\"m 1,2 0,14 16,0 0,-14 z m 1.4,3 12.7,0 0,10 -12.7,0 z\");\n    path.attr({\n        \"opacity\": 1,\n        \"stroke\": \"none\",\n        \"fill\": \"#000000\"\n    });\n    var text = paper.text(3, 9, \">_\").attr({\n        \"font-size\": \"5px\",\n        \"fill\": \"#000000\"\n    });\n\n    startY += -2;\n    text.transform(\"T\" + startX + \",\" + startY);\n    startX += -2;\n    path.transform(\"T\" + startX + \",\" + startY);\n}\n\nfunction _drawBusinessRuleTaskIcon(paper, startX, startY) {\n    var path1 = paper.path(\"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    path1.attr({\n        \"stroke\": \"none\",\n        \"fill\": \"#000000\"\n    });\n\n    var businessRuleTaskIcon = paper.set();\n    businessRuleTaskIcon.push(path1);\n\n    businessRuleTaskIcon.transform(\"T\" + startX + \",\" + startY);\n}\n\nfunction _drawEventIcon(paper, element)\n{\n\tif (element.eventDefinition && element.eventDefinition.type)\n\t{\n\t\tif (\"timer\" === element.eventDefinition.type)\n\t\t{\n\t\t\t_drawTimerIcon(paper, element);\n\t\t}\n\t\telse if (\"error\" === element.eventDefinition.type)\n\t\t{\n\t\t\t_drawErrorIcon(paper, element);\n\t\t}\n\t\telse if (\"signal\" === element.eventDefinition.type)\n\t\t{\n\t\t\t_drawSignalIcon(paper, element);\n\t\t}\n\t\telse if (\"message\" === element.eventDefinition.type)\n\t\t{\n\t\t\t_drawMessageIcon(paper, element);\n\t\t}\n\t}\n}\n\nfunction _drawTimerIcon(paper, element)\n{\n\tvar x = element.x + (element.width / 2);\n\tvar y = element.y + (element.height / 2);\n\n\tvar circle = paper.circle(x, y, 10);\n\n\tcircle.attr({\"stroke-width\": 1,\n\t\t\"stroke\": \"black\",\n\t\t\"fill\": \"none\"\n \t});\n\n\tvar path = paper.path(\"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\tpath.attr({\n\t\t\"stroke\": \"none\",\n\t\t\"fill\": \"#585858\"\n \t});\n\tpath.transform(\"T\" + (element.x + 5) + \",\" + (element.y + 5));\n\treturn path;\n}\n\nfunction _drawErrorIcon(paper, element)\n{\n\tvar path = paper.path(\"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\n\tvar fill = \"none\";\n\tvar x = element.x - 1;\n\tvar y = element.y - 1;\n\tif (element.type === \"EndEvent\")\n\t{\n\t\tfill = \"black\";\n\t\tx -= 1;\n\t\ty -= 1;\n\t}\n\n\tpath.attr({\n\t\t\"stroke\": \"black\",\n\t\t\"stroke-width\": 1,\n\t\t\"fill\": fill\n \t});\n\n\tpath.transform(\"T\" + x + \",\" + y);\n\treturn path;\n}\n\nfunction _drawSignalIcon(paper, element)\n{\n\tvar fill = \"none\";\n\tif (element.type === \"ThrowEvent\")\n\t{\n\t\tfill = \"black\";\n\t}\n\n\tvar path = paper.path(\"M 8.7124971,21.247342 L 23.333334,21.247342 L 16.022915,8.5759512 L 8.7124971,21.247342 z\");\n\tpath.attr({\n\t\t\"stroke\": \"black\",\n\t\t\"stroke-width\": 1,\n\t\t\"fill\": fill\n \t});\n\tpath.transform(\"T\" + (element.x - 1) + \",\" + (element.y - 1));\n\treturn path;\n}\n\nfunction _drawMessageIcon(paper, element)\n{\n\tvar path = paper.path(\"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\tpath.attr({\n\t\t\"stroke\": \"none\",\n\t\t\"stroke-width\": 1,\n\t\t\"fill\": \"#585858\"\n \t});\n\tpath.transform(\"T\" + (element.x + 6) + \",\" + (element.y + 6));\n\treturn path;\n}\n"
  },
  {
    "path": "flowable-ui-web/task/display/displaymodel.css",
    "content": "div[class*='ui-tooltip-kisbpm-'] {\n    background-color: #ffffff;\n    border-color: #c5c5c5;\n    color: #4a4a4a;\n    font-family: Verdana;\n    font-size: 12px;\n}\n\ndiv[class*='ui-tooltip-kisbpm-'] .qtip-content {\n  color: #4a4a4a;\n  background-color: #ffffff;\n  font-family: Verdana;\n  font-size: 12px;\n}\n\n.ui-tooltip-kisbpm-bpmn .qtip-titlebar {\n  color: #FFFFFF;\n  font-size: 12px;\n  background: #2B414F;\n}\n\n.ui-tooltip-kisbpm-bpmn .qtip-tip {\n  background-color: #2B414F;\n}\n"
  },
  {
    "path": "flowable-ui-web/task/display/displaymodel.html",
    "content": "<html>\n    <head>\n\n        <!-- build:css display/styles/displaymodel-style.css -->\n        <link type=\"text/css\" rel=\"stylesheet\" href=\"jquery.qtip.min.css\" />\n        <link type=\"text/css\" rel=\"stylesheet\" href=\"displaymodel.css\" />\n        <!-- endbuild -->\n\n        <!-- Configuration -->\n       <!--\n         todo\n         Remove this? shouldn't this be on the page already,\n         and wouldn't it override settings form app-cfg-on-premise & others\n         -->\n       <!--\n        <script type=\"text/javascript\" src=\"../scripts/app-cfg.js?v=1\"></script>\n       -->\n        <!-- build:js display/scripts/displaymodel-logic.js -->\n        <script type=\"text/javascript\" src=\"p.min.js\"></script>\n        <script type=\"text/javascript\" src=\"n.js\"></script>\n        <script type=\"text/javascript\" src=\"js\"></script>\n        <script type=\"text/javascript\" src=\".js\"></script>\n        <script type=\"text/javascript\" src=\"s\"></script>\n        <script type=\"text/javascript\" src=\"el.js\"></script>\n        <!-- endbuild -->\n\n    </head>\n</html>\n"
  },
  {
    "path": "flowable-ui-web/task/display/displaymodel.js",
    "content": "/* 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 */\nvar NORMAL_STROKE = 2;\nvar SEQUENCEFLOW_STROKE = 2;\nvar ASSOCIATION_STROKE = 2;\nvar TASK_STROKE = 2;\nvar TASK_HIGHLIGHT_STROKE = 4;\nvar CALL_ACTIVITY_STROKE = 4;\nvar ENDEVENT_STROKE = 4;\n\nvar COMPLETED_COLOR = \"#2632aa\";\nvar TEXT_COLOR = \"#373e48\";\nvar CURRENT_COLOR = \"#017501\";\nvar HOVER_COLOR = \"#666666\";\nvar ACTIVITY_STROKE_COLOR = \"#000000\";\nvar ACTIVITY_FILL_COLOR = \"#ffffff\";\nvar MAIN_STROKE_COLOR = \"#585858\";\n\nvar TEXT_PADDING = 3;\nvar ARROW_WIDTH = 4;\nvar MARKER_WIDTH = 12;\n\nvar TASK_FONT = {font: \"11px Arial\", opacity: 1, fill: Raphael.rgb(0, 0, 0)};\n\n// icons\nvar ICON_SIZE = 16;\nvar ICON_PADDING = 4;\n\nvar INITIAL_CANVAS_WIDTH;\nvar INITIAL_CANVAS_HEIGHT;\n\nvar paper;\nvar viewBox;\nvar viewBoxWidth;\nvar viewBoxHeight;\n\nvar canvasWidth;\nvar canvasHeight;\n\nvar modelDiv = jQuery('#bpmnModel');\nvar modelId = modelDiv.attr('data-model-id');\nvar historyModelId = modelDiv.attr('data-history-id');\nvar processDefinitionId = modelDiv.attr('data-process-definition-id');\nvar modelType = modelDiv.attr('data-model-type');\nvar isDebuggerEnabled = angular.element(document.querySelector('#bpmnModel')).scope().model.isDebuggerEnabled;\n\n// Support for custom background colors for activities\nvar customActivityColors = modelDiv.attr('data-activity-color-mapping');\nif (customActivityColors !== null && customActivityColors !== undefined && customActivityColors.length > 0) {\n    // Stored on the attribute as a string\n    customActivityColors = JSON.parse(customActivityColors);\n}\n\nvar customActivityToolTips = modelDiv.attr('data-activity-tooltips');\nif (customActivityToolTips !== null && customActivityToolTips !== undefined && customActivityToolTips.length > 0) {\n    // Stored on the attribute as a string\n    customActivityToolTips = JSON.parse(customActivityToolTips);\n}\n\n// Support for custom opacity for activity backgrounds\nvar customActivityBackgroundOpacity = modelDiv.attr('data-activity-opacity');\n\nvar elementsAdded = new Array();\nvar elementsRemoved = new Array();\nvar selectedElement = undefined;\n\nvar collapsedItemNavigation = new Array();\nvar bpmnData;\n\nfunction _showTip(htmlNode, element)\n{\n\n    // Custom tooltip\n    var documentation = undefined;\n    if (customActivityToolTips) {\n        if (customActivityToolTips[element.name]) {\n            documentation = customActivityToolTips[element.name];\n        } else if (customActivityToolTips[element.id]) {\n            documentation = customActivityToolTips[element.id];\n        } else {\n            documentation = ''; // Show nothing if custom tool tips are enabled\n        }\n    }\n\n    // Default tooltip, no custom tool tip set\n    if (documentation === undefined) {\n        var documentation = \"\";\n        if (element.name && element.name.length > 0) {\n            documentation += \"<b>Name</b>: <i>\" + element.name + \"</i><br/><br/>\";\n        }\n\n        if (element.properties) {\n            for (var i = 0; i < element.properties.length; i++) {\n                var propName = element.properties[i].name;\n                if (element.properties[i].type && element.properties[i].type === 'list') {\n                    documentation += '<b>' + propName + '</b>:<br/>';\n                    for (var j = 0; j < element.properties[i].value.length; j++) {\n                        documentation += '<i>' + element.properties[i].value[j] + '</i><br/>';\n                    }\n                }\n                else {\n                    documentation += '<b>' + propName + '</b>: <i>' + element.properties[i].value + '</i><br/>';\n                }\n            }\n        }\n    }\n\n    var text = element.type + \" \";\n    if (element.name && element.name.length > 0)\n    {\n        text += element.name;\n    }\n    else\n    {\n        text += element.id;\n    }\n\n    htmlNode.qtip({\n        content: {\n            text: documentation,\n            title: {\n                text: text\n            }\n        },\n        position: {\n            my: 'top left',\n            at: 'bottom center',\n            viewport: jQuery('#bpmnModel')\n        },\n        hide: {\n            fixed: true, delay: 500,\n            event: 'click mouseleave'\n        },\n        style: {\n            classes: 'ui-tooltip-kisbpm-bpmn'\n        }\n    });\n}\n\nfunction _expandCollapsedElement(element) {\n    if (bpmnData.collapsed) {\n        for (var i = 0; i < bpmnData.collapsed.length; i++) {\n            var collapsedItem = bpmnData.collapsed[i];\n            if (element.id == collapsedItem.id) {\n                paper.clear();\n                \n                var modelElements = collapsedItem.elements;\n                for (var i = 0; i < modelElements.length; i++) {\n                    var subElement = modelElements[i];\n                    var drawFunction = eval(\"_draw\" + subElement.type);\n                    drawFunction(subElement);\n                }\n                \n                if (collapsedItem.flows) {\n                    for (var i = 0; i < collapsedItem.flows.length; i++) {\n                        var subFlow = collapsedItem.flows[i];\n                        _drawFlow(subFlow);\n                    }\n                }\n                \n                var collapsedName;\n                if (element.name) {\n                    collapsedName = element.name;\n                } else {\n                    collapsedName = 'sub process ' + element.id;\n                }\n                \n                collapsedItemNavigation.push({\n                    \"id\": element.id,\n                    \"name\": collapsedName\n                });\n                \n                _buildNavigationTree();\n                \n                break;\n            }\n        }\n    }\n}\n\nfunction _navigateTo(elementId) {\n    var modelElements = undefined;\n    var modelFlows = undefined;\n    newCollapsedItemNavigation = new Array();\n    \n    if (elementId == 'FLOWABLE_ROOT_PROCESS') {\n        modelElements = bpmnData.elements;\n        modelFlows = bpmnData.flows;\n        \n    } else {\n    \n        for (var i = 0; i < bpmnData.collapsed.length; i++) {\n            var collapsedItem = bpmnData.collapsed[i];\n            \n            var collapsedName = undefined;\n            for (var j = 0; j < collapsedItemNavigation.length; j++) {\n                if (elementId == collapsedItemNavigation[j].id) {\n                    collapsedName = collapsedItemNavigation[j].name;\n                    break;\n                }\n            }\n        \n            if (!collapsedName) {\n                continue;\n            }\n            \n            newCollapsedItemNavigation.push({\n                \"id\": collapsedItem.id,\n                \"name\": collapsedName\n            });\n            \n            if (elementId == collapsedItem.id) {\n                modelElements = collapsedItem.elements;\n                modelFlows = collapsedItem.flows;\n                break;\n            }\n        }\n    }\n    \n    if (modelElements) {\n        paper.clear();\n                    \n        for (var i = 0; i < modelElements.length; i++) {\n            var subElement = modelElements[i];\n            var drawFunction = eval(\"_draw\" + subElement.type);\n            drawFunction(subElement);\n        }\n        \n        if (modelFlows) {\n            for (var i = 0; i < modelFlows.length; i++) {\n                var subFlow = modelFlows[i];\n                _drawFlow(subFlow);\n            }\n        }\n        \n        collapsedItemNavigation = newCollapsedItemNavigation;\n        \n        _buildNavigationTree();\n    }\n}\n\nfunction _buildNavigationTree() {\n    var navigationUrl = '| <a href=\"javascript:_navigateTo(\\'FLOWABLE_ROOT_PROCESS\\')\">Root</a>';\n                \n    for (var i = 0; i < collapsedItemNavigation.length; i++) {\n        navigationUrl += ' > <a href=\"javascript:_navigateTo(\\'' + collapsedItemNavigation[i].id + '\\')\">' + \n            collapsedItemNavigation[i].name + '</a>';\n    }\n    \n    $('#navigationTree').html(navigationUrl);\n}\n\nfunction _addHoverLogic(element, type, defaultColor)\n{\n    var strokeColor = _bpmnGetColor(element, defaultColor);\n    var topBodyRect = null;\n    if (type === \"rect\")\n    {\n        topBodyRect = paper.rect(element.x, element.y, element.width, element.height);\n    }\n    else if (type === \"circle\")\n    {\n        var x = element.x + (element.width / 2);\n        var y = element.y + (element.height / 2);\n        topBodyRect = paper.circle(x, y, 15);\n    }\n    else if (type === \"rhombus\")\n    {\n        topBodyRect = paper.path(\"M\" + element.x + \" \" + (element.y + (element.height / 2)) +\n            \"L\" + (element.x + (element.width / 2)) + \" \" + (element.y + element.height) +\n            \"L\" + (element.x + element.width) + \" \" + (element.y + (element.height / 2)) +\n            \"L\" + (element.x + (element.width / 2)) + \" \" + element.y + \"z\"\n        );\n    }\n\n    var opacity = 0;\n    var fillColor = \"#ffffff\";\n    if (jQuery.inArray(element.id, elementsAdded) >= 0)\n    {\n        opacity = 0.2;\n        fillColor = \"green\";\n    }\n\n    if (jQuery.inArray(element.id, elementsRemoved) >= 0)\n    {\n        opacity = 0.2;\n        fillColor = \"red\";\n    }\n\n    topBodyRect.attr({\n        \"opacity\": opacity,\n        \"stroke\" : \"none\",\n        \"fill\" : fillColor\n    });\n    _showTip(jQuery(topBodyRect.node), element);\n\n    topBodyRect.mouseover(function () {\n        paper.getById(element.id).attr({\"stroke\": HOVER_COLOR});\n    });\n\n    topBodyRect.mouseout(function () {\n        paper.getById(element.id).attr({\"stroke\": _bpmnGetColor(element, defaultColor)});\n    });\n\n    if (isDebuggerEnabled) {\n        if (element.current || element.brokenExecutions) {\n            topBodyRect.click(function () {\n                if (selectedElement != element.id) {\n                    paper.getById(element.id).attr({\"stroke\": \"green\"});\n                    selectedElement = element.id;\n                    paper.getById(element.id).attr({\"stroke\": \"red\"});\n                    _executionClicked(element.id);\n                } else {\n                    selectedElement = undefined;\n                    paper.getById(element.id).attr({\"stroke\": \"green\"});\n                    var scope = angular.element(document.querySelector('#bpmnModel')).scope();\n                    modelDiv.attr(\"selected-execution\", scope.model.processInstance.id);\n                    scope.model.selectedExecution = scope.model.processInstance.id;\n                    angular.element(document.querySelector('#variablesUi')).scope().loadVariables();\n                }\n            });\n        }\n    }\n}\n\nfunction _executionClicked(activityId) {\n    var executions = angular.element(document.querySelector('#bpmnModel')).scope().model.executions;\n    for (var i in executions) {\n        if (executions[i][\"activityId\"] == activityId) {\n            var activityToUnselect = modelDiv.attr(\"selected-activity\");\n            if (activityToUnselect) {\n                var rectangleToUnselect = paper.getById(activityToUnselect);\n                if (rectangleToUnselect) {\n                    rectangleToUnselect.attr({\"stroke\": \"green\"});\n                }\n            }\n            modelDiv.attr(\"selected-execution\", executions[i].id);\n            modelDiv.attr(\"selected-activity\", activityId);\n            if (activityId) {\n                paper.getById(activityId).attr({\"stroke\": \"red\"});\n            }\n\n            var scope = angular.element(document.querySelector('#bpmnModel')).scope();\n            if (scope.gridExecutions.data) {\n                for (var j = 0; j < scope.gridExecutions.data.length; j++) {\n                    if (executions[i].id == scope.gridExecutions.data[j].id) {\n                        scope.gridExecutionsApi.selection.selectRow(scope.gridExecutions.data[j]);\n                        j = scope.gridExecutions.data.length;\n                    }\n                }\n            }\n            scope.loadVariables();\n            return;\n        }\n    }\n}\n\nfunction _breakpointRestCall(actionType, activityId) {\n    $.ajax({\n        type: actionType,\n        url: '../app/rest/debugger/breakpoints',\n        contentType: 'application/json; charset=utf-8',\n        data: JSON.stringify({\n            activityId: activityId\n        }),\n        success: function () {\n            paper.clear();\n            angular.element(document.querySelector('#bpmnModel')).scope().getEventLog();\n            _showProcessDiagram();\n        }\n    })\n}\n\nfunction _drawBreakpoint(element, breakpoints) {\n\n    var circle = paper.circle(element.x + 10, element.y - 10, 7);\n\n    var breakpointFillColor = \"white\";\n    var breakpointStrokeColor = \"gray\";\n    var breakpointTipText = \"Inactive element\";\n    if (element.current) {\n        breakpointFillColor = \"red\";\n        breakpointTipText = \"Active execution\"\n    }\n\n    if (element.breakpoint) {\n        breakpointTipText = breakpointTipText + \"<br/> Click to remove breakpoint\";\n        breakpointStrokeColor = \"red\";\n        circle.click(function () {\n            _breakpointRestCall(\"DELETE\", element.id);\n        });\n\n    } else {\n        breakpointTipText = breakpointTipText + \"<br/> Click to add breakpoint\";\n        circle.click(function () {\n            _breakpointRestCall(\"POST\", element.id);\n        });\n    }\n\n    circle.attr(\"stroke\", breakpointStrokeColor);\n    circle.attr(\"stroke-width\", \"3\");\n    circle.attr(\"fill\", breakpointFillColor);\n\n\n    var circleHtmlNode = jQuery(circle.node);\n    circleHtmlNode.qtip({\n        content: {\n            text: breakpointTipText,\n            button: false\n        },\n        position: {\n            my: 'top left',\n            at: 'bottom center',\n            viewport: jQuery('#bpmnModel')\n        },\n        hide: {\n            fixed: true, delay: 500,\n            event: 'click mouseleave'\n        },\n        style: {\n            classes: 'ui-tooltip-kisbpm-bpmn'\n        }\n    });\n\n}\n\nfunction _zoom(zoomIn) {\n    var tmpCanvasWidth, tmpCanvasHeight;\n    if (zoomIn) {\n        tmpCanvasWidth = canvasWidth * (1.0 / 0.90);\n        tmpCanvasHeight = canvasHeight * (1.0 / 0.90);\n    }\n    else {\n        tmpCanvasWidth = canvasWidth * (1.0 / 1.10);\n        tmpCanvasHeight = canvasHeight * (1.0 / 1.10);\n    }\n\n    if (tmpCanvasWidth != canvasWidth || tmpCanvasHeight != canvasHeight) {\n        canvasWidth = tmpCanvasWidth;\n        canvasHeight = tmpCanvasHeight;\n        paper.setSize(canvasWidth, canvasHeight);\n    }\n}\n\nvar modelUrl;\n\nif (modelType == 'runtime') {\n    if (historyModelId) {\n        modelUrl = FLOWABLE.CONFIG.contextRoot + '/app/rest/process-instances/history/' + historyModelId + '/model-json';\n    } else if (isDebuggerEnabled) {\n        modelUrl = FLOWABLE.CONFIG.contextRoot + '/app/rest/process-instances/debugger/' + modelId + '/model-json';\n    } else {\n        modelUrl = FLOWABLE.CONFIG.contextRoot + '/app/rest/process-instances/' + modelId + '/model-json';\n    }\n} else if (modelType == 'design') {\n    if (historyModelId) {\n        modelUrl = FLOWABLE.CONFIG.contextRoot + '/app/rest/models/' + modelId + '/history/' + historyModelId + '/model-json';\n    } else {\n        modelUrl = FLOWABLE.CONFIG.contextRoot + '/app/rest/models/' + modelId + '/model-json';\n    }\n} else if (modelType == 'process-definition') {\n    modelUrl = FLOWABLE.CONFIG.contextRoot + '/app/rest/process-definitions/' + processDefinitionId + '/model-json';\n}\n\nfunction _drawContinueExecution(x, y , executionId, activityId) {\n    var arrow = paper.path(\"M \"+ x +\" \"+ y + \" L \"+ (x+8) +\" \"+ (y+4) +\" \"+ x +\" \"+ (y+8) +\" z\");\n\n    arrow.click(function () {\n            $.ajax({\n                type: 'PUT',\n                url: '../app/rest/debugger/breakpoints/' + executionId + '/continue',\n                contentType: 'application/json; charset=utf-8',\n                success: function () {\n                    paper.clear();\n                    var processInstanceId = angular.element(document.querySelector('#bpmnModel')).scope().model.processInstance.id;\n                    modelDiv.attr(\"selected-execution\", processInstanceId);\n                    angular.element(document.querySelector('#bpmnModel')).scope().model.selectedExecution = processInstanceId;\n                    angular.element(document.querySelector('#bpmnModel')).scope().getExecutions();\n                    angular.element(document.querySelector('#bpmnModel')).scope().model.variables = undefined;\n                    angular.element(document.querySelector('#bpmnModel')).scope().loadVariables();\n                    angular.element(document.querySelector('#bpmnModel')).scope().getEventLog();\n                    _showProcessDiagram();\n                },\n                error: function () {\n                    alert(\"error\");\n                }\n            })\n        }\n    );\n    arrow.attr(\"stroke\", \"green\");\n    arrow.attr(\"stroke-width\", \"3\");\n    arrow.attr(\"fill\", \"green\");\n\n    var arrowHtmlNode = jQuery(arrow.node);\n    arrowHtmlNode.qtip({\n        content: {\n            text: \"Fire execution \"+ executionId+\", activity \" + activityId,\n            button: false\n        },\n        position: {\n            my: 'top left',\n            at: 'bottom center',\n            viewport: jQuery('#bpmnModel')\n        },\n        hide: {\n            fixed: true, delay: 500,\n            event: 'click mouseleave'\n        },\n        style: {\n            classes: 'ui-tooltip-kisbpm-bpmn'\n        }\n    });\n\n}\n\nfunction _showProcessDiagram() {\n    var request = jQuery.ajax({\n        type: 'get',\n        url: modelUrl + '?nocaching=' + new Date().getTime()\n    });\n\n    request.success(function (data, textStatus, jqXHR) {\n\n        if ((!data.elements || data.elements.length == 0) && (!data.pools || data.pools.length == 0)) return;\n\n        INITIAL_CANVAS_WIDTH = data.diagramWidth;\n\n        if (modelType == 'design') {\n            INITIAL_CANVAS_WIDTH += 20;\n        } else {\n            INITIAL_CANVAS_WIDTH += 30;\n        }\n\n        INITIAL_CANVAS_HEIGHT = data.diagramHeight + 50;\n        canvasWidth = INITIAL_CANVAS_WIDTH;\n        canvasHeight = INITIAL_CANVAS_HEIGHT;\n        viewBoxWidth = INITIAL_CANVAS_WIDTH;\n        viewBoxHeight = INITIAL_CANVAS_HEIGHT;\n\n        if (modelType == 'design') {\n            var headerBarHeight = 170;\n            var offsetY = 0;\n            if (jQuery(window).height() > (canvasHeight + headerBarHeight)) {\n                offsetY = (jQuery(window).height() - headerBarHeight - canvasHeight) / 2;\n            }\n\n            if (offsetY > 50) {\n                offsetY = 50;\n            }\n\n            jQuery('#bpmnModel').css('marginTop', offsetY);\n        }\n\n        jQuery('#bpmnModel').width(INITIAL_CANVAS_WIDTH);\n        jQuery('#bpmnModel').height(INITIAL_CANVAS_HEIGHT);\n        paper = Raphael(document.getElementById('bpmnModel'), canvasWidth, canvasHeight);\n        paper.setViewBox(0, 0, viewBoxWidth, viewBoxHeight, false);\n        paper.renderfix();\n\n        if (data.pools) {\n            for (var i = 0; i < data.pools.length; i++) {\n                var pool = data.pools[i];\n                _drawPool(pool);\n            }\n        }\n\n        var modelElements = data.elements;\n\n        for (var i = 0; i < modelElements.length; i++) {\n            var element = modelElements[i];\n//            try {\n            var drawFunction = eval(\"_draw\" + element.type);\n            drawFunction(element);\n            if (isDebuggerEnabled) {\n                _drawBreakpoint(element);\n\n                if (element.brokenExecutions) {\n                    for (var j = 0; j < element.brokenExecutions.length; j++) {\n                        _drawContinueExecution(element.x + 25 + j * 10, element.y - 15, element.brokenExecutions[j], element.id);\n                    }\n                }\n            }\n//            } catch(err) {console.log(err);}\n        }\n\n        if (data.flows) {\n            for (var i = 0; i < data.flows.length; i++) {\n                var flow = data.flows[i];\n                if (flow.type === 'sequenceFlow') {\n                    _drawFlow(flow);\n                } else if (flow.type === 'association') {\n                    _drawAssociation(flow);\n                }\n            }\n        }\n        \n        bpmnData = data;\n    });\n\n    request.error(function (jqXHR, textStatus, errorThrown) {\n        alert(\"error\");\n    });\n}\n\n_showProcessDiagram();\n"
  },
  {
    "path": "flowable-ui-web/task/display/package.json",
    "content": "{\n  \"name\": \"displaymodel\",\n  \"version\": \"1.0.0\",\n  \"dependencies\": {},\n  \"devDependencies\": {\n    \"grunt\": \"0.4.2\",\n    \"grunt-autoprefixer\": \"0.4.0\",\n    \"grunt-bower-install\": \"0.7.0\",\n    \"grunt-concurrent\": \"0.4.1\",\n    \"grunt-contrib-clean\": \"0.5.0\",\n    \"grunt-contrib-coffee\": \"0.7.0\",\n    \"grunt-contrib-compass\": \"0.6.0\",\n    \"grunt-contrib-concat\": \"0.3.0\",\n    \"grunt-contrib-connect\": \"0.5.0\",\n    \"grunt-contrib-copy\": \"0.4.1\",\n    \"grunt-contrib-cssmin\": \"0.7.0\",\n    \"grunt-contrib-htmlmin\": \"0.1.3\",\n    \"grunt-contrib-imagemin\": \"0.3.0\",\n    \"grunt-contrib-jshint\": \"0.7.1\",\n    \"grunt-contrib-uglify\": \"0.2.0\",\n    \"grunt-contrib-watch\": \"0.5.2\",\n    \"grunt-google-cdn\": \"0.2.0\",\n    \"grunt-newer\": \"0.5.4\",\n    \"grunt-ng-annotate\": \"0.5.0\",\n    \"grunt-rev\": \"0.1.0\",\n    \"grunt-svgmin\": \"0.2.0\",\n    \"grunt-usemin\": \"2.0.0\",\n    \"jshint-stylish\": \"0.1.3\",\n    \"load-grunt-tasks\": \"0.2.0\",\n    \"time-grunt\": \"0.2.1\",\n    \"grunt-text-replace\": \"0.3.11\",\n    \"grunt-contrib-rename\": \"0.0.3\"\n  },\n  \"engines\": {\n    \"node\": \">=0.8.0\"\n  }\n}\n"
  },
  {
    "path": "flowable-ui-web/task/display-cmmn/cmmn-draw.js",
    "content": "/* 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\nfunction _cmmnGetColor(element, defaultColor)\n{\n    var strokeColor;\n    if (element.current) {\n        strokeColor = CURRENT_COLOR;\n    } else if (element.completed) {\n        strokeColor = COMPLETED_COLOR;\n    } else if (element.available) {\n        strokeColor = AVAILABLE_COLOR;\n    } else {\n        strokeColor = defaultColor;\n    }\n    return strokeColor;\n}\n\nfunction _drawPlanModel(planModel)\n{\n\tvar rect = paper.rect(planModel.x, planModel.y, planModel.width, planModel.height);\n\n\trect.attr({\"stroke-width\": 1,\n\t\t\"stroke\": \"#000000\",\n\t\t\"fill\": \"white\"\n \t});\n\n\tif (planModel.name)\n\t{\n\t\tvar planModelName = paper.text(planModel.x + 14, planModel.y + (planModel.height / 2), planModel.name).attr({\n\t        \"text-anchor\" : \"middle\",\n\t        \"font-family\" : \"Arial\",\n\t        \"font-size\" : \"12\",\n\t        \"fill\" : \"#000000\"\n\t  \t});\n\n\t\tplanModelName.transform(\"r270\");\n\t}\n}\n\nfunction _drawSubProcess(element)\n{\n\tvar rect = paper.rect(element.x, element.y, element.width, element.height, 4);\n\n\tvar strokeColor = _cmmnGetColor(element, MAIN_STROKE_COLOR);\n\n\trect.attr({\"stroke-width\": 1,\n\t\t\"stroke\": strokeColor,\n\t\t\"fill\": \"white\"\n \t});\n}\n\nfunction _drawVariableServiceTaskIcon(element)\n{\n\t_drawTask(element);\n\tif (element.taskType === \"mail\")\n\t{\n\t\t_drawSendTaskIcon(paper, element.x + 4, element.y + 4);\n\t}\n\telse if (element.taskType === \"camel\")\n\t{\n\t\t_drawCamelTaskIcon(paper, element.x + 4, element.y + 4);\n\t}\n\telse if (element.taskType === \"mule\")\n\t{\n\t\t_drawMuleTaskIcon(paper, element.x + 4, element.y + 4);\n\t}\n    else if (element.taskType === \"http\")\n    {\n        _drawHttpTaskIcon(paper, element.x + 4, element.y + 4);\n    }\n\telse if (element.stencilIconId)\n\t{\n\t\tpaper.image(\"../service/stencilitem/\" + element.stencilIconId + \"/icon\", element.x + 4, element.y + 4, 16, 16);\n\t}\n\telse\n\t{\n\t\t_drawServiceTaskIcon(paper, element.x + 4, element.y + 4);\n\t}\n\t_addHoverLogic(element, \"rect\", ACTIVITY_STROKE_COLOR);\n}\n\nfunction _drawHttpServiceTask(element)\n{\n    _drawTask(element);\n    _drawHttpTaskIcon(paper, element.x + 4, element.y + 4);\n    _addHoverLogic(element, \"rect\", ACTIVITY_STROKE_COLOR);\n}\n\nfunction _drawHumanTask(element)\n{\n\t_drawTask(element);\n\t_drawHumanTaskIcon(paper, element.x + 4, element.y + 4);\n\t_addHoverLogic(element, \"rect\", ACTIVITY_STROKE_COLOR);\n}\n\nfunction _drawCaseTask(element)\n{\n    _drawTask(element);\n    _drawCaseTaskIcon(paper, element.x + 1, element.y + 1);\n    _addHoverLogic(element, \"rect\", ACTIVITY_STROKE_COLOR);\n}\n\nfunction _drawProcessTask(element)\n{\n    _drawTask(element);\n    _drawProcessTaskIcon(paper, element.x + 1, element.y + 1);\n    _addHoverLogic(element, \"rect\", ACTIVITY_STROKE_COLOR);\n}\n\nfunction _drawScriptTaskIcon(paper, startX, startY)\n{\n\tvar path1 = paper.path(\"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\tpath1.attr({\n\t\t\"opacity\": 1,\n\t\t\"stroke\": \"none\",\n\t\t\"fill\": \"#72a7d0\"\n \t});\n\n\tvar scriptTaskIcon = paper.set();\n\tscriptTaskIcon.push(path1);\n\n\tscriptTaskIcon.transform(\"T\" + startX + \",\" + startY);\n}\n\nfunction _drawScriptServiceTask(element)\n{\n\t_drawTask(element);\n\t_drawScriptTaskIcon(paper, element.x + 4, element.y + 4);\n\t_addHoverLogic(element, \"rect\", ACTIVITY_STROKE_COLOR);\n}\n\nfunction _drawDecisionTask(element)\n{\n    _drawTask(element);\n    _drawDecisionTaskIcon(paper, element.x + 1, element.y + 1);\n    _addHoverLogic(element, \"rect\", ACTIVITY_STROKE_COLOR);\n}\n\nfunction _drawServiceTask(element)\n{\n    _drawTask(element);\n    _drawVariableServiceTaskIcon(element);\n    _addHoverLogic(element, \"rect\", ACTIVITY_STROKE_COLOR);\n}\n\nfunction _drawTask(element)\n{\n    var rectAttrs = {};\n\n    // Stroke\n    var strokeColor = _cmmnGetColor(element, ACTIVITY_STROKE_COLOR);\n    rectAttrs['stroke'] = strokeColor;\n\n    var strokeWidth;\n    if (strokeColor === ACTIVITY_STROKE_COLOR) {\n        strokeWidth = TASK_STROKE;\n    } else {\n        strokeWidth = TASK_HIGHLIGHT_STROKE;\n    }\n\n\tvar width = element.width - (strokeWidth / 2);\n\tvar height = element.height - (strokeWidth / 2);\n\n\tvar rect = paper.rect(element.x, element.y, width, height, 4);\n    rectAttrs['stroke-width'] = strokeWidth;\n\n    // Fill\n\trectAttrs['fill'] = ACTIVITY_FILL_COLOR;\n\n    rect.attr(rectAttrs);\n\trect.id = element.id;\n\n\tif (element.name) {\n\t\tthis._drawMultilineText(element.name, element.x, element.y, element.width, element.height, \"middle\", \"middle\", 11);\n\t}\n}\n\nfunction _drawTimerEventListener(element)\n{\n    _drawEventListener(element);\n    _drawTimerEventListenerIcon(paper, element);\n    _addHoverLogic(element, \"rect\", ACTIVITY_STROKE_COLOR);\n}\n\nfunction _drawUserEventListener(element)\n{\n    _drawEventListener(element);\n    _drawUserEventListenerIcon(paper, element);\n    _addHoverLogic(element, \"rect\", ACTIVITY_STROKE_COLOR);\n}\n\nfunction _drawGenericEventListener(element)\n{\n    _drawEventListener(element);\n    _addHoverLogic(element, \"rect\", ACTIVITY_STROKE_COLOR);\n}\n\nfunction _drawEventListener(element)\n{\n    var x = element.x + (element.width / 2);\n\tvar y = element.y + (element.height / 2);\n\n\tvar circle = paper.circle(x, y, 15);\n\n    circle.attr({\"stroke-width\": 1,\n        \"stroke\": \"black\",\n        \"fill\": \"white\"\n    });\n\n\tcircle.id = element.id;\n}\n\nfunction _drawMilestone(element)\n{\n    var rectAttrs = {};\n\n    // Stroke\n    var strokeColor = _cmmnGetColor(element, ACTIVITY_STROKE_COLOR);\n    rectAttrs['stroke'] = strokeColor;\n\n    var strokeWidth;\n    if (strokeColor === ACTIVITY_STROKE_COLOR) {\n        strokeWidth = TASK_STROKE;\n    } else {\n        strokeWidth = TASK_HIGHLIGHT_STROKE;\n    }\n\n    var width = element.width - (strokeWidth / 2);\n    var height = element.height - (strokeWidth / 2);\n\n    var rect = paper.rect(element.x, element.y, width, height, 24);\n    rectAttrs['stroke-width'] = strokeWidth;\n\n    // Fill\n    rectAttrs['fill'] = WHITE_FILL_COLOR;\n\n    rect.attr(rectAttrs);\n    rect.id = element.id;\n\n    if (element.name) {\n        this._drawMultilineText(element.name, element.x, element.y, element.width, element.height, \"middle\", \"middle\", 11);\n    }\n}\n\nfunction _drawStage(element)\n{\n    var rectAttrs = {};\n\n    // Stroke\n    var strokeColor = _cmmnGetColor(element, ACTIVITY_STROKE_COLOR);\n    rectAttrs['stroke'] = strokeColor;\n\n    var strokeWidth;\n    if (strokeColor === ACTIVITY_STROKE_COLOR) {\n        strokeWidth = TASK_STROKE;\n    } else {\n        strokeWidth = TASK_HIGHLIGHT_STROKE;\n    }\n\n    var width = element.width - (strokeWidth / 2);\n    var height = element.height - (strokeWidth / 2);\n\n    var rect = paper.rect(element.x, element.y, width, height, 16);\n    rectAttrs['stroke-width'] = strokeWidth;\n\n    // Fill\n    rectAttrs['fill'] = WHITE_FILL_COLOR;\n\n    rect.attr(rectAttrs);\n    rect.id = element.id;\n\n    if (element.name) {\n        this._drawMultilineText(element.name, element.x + 10, element.y + 5, element.width, element.height, \"start\", \"top\", 11);\n    }\n}\n\nfunction _drawPlanModel(element)\n{\n    var rectAttrs = {};\n\n    // Stroke\n    var strokeColor = _cmmnGetColor(element, ACTIVITY_STROKE_COLOR);\n    rectAttrs['stroke'] = strokeColor;\n\n    var strokeWidth;\n    if (strokeColor === ACTIVITY_STROKE_COLOR) {\n        strokeWidth = TASK_STROKE;\n    } else {\n        strokeWidth = TASK_HIGHLIGHT_STROKE;\n    }\n\n    var width = element.width - (strokeWidth / 2);\n    var height = element.height - (strokeWidth / 2);\n\n    var rect = paper.rect(element.x, element.y, width, height, 4);\n    rectAttrs['stroke-width'] = strokeWidth;\n\n    // Fill\n    rectAttrs['fill'] = WHITE_FILL_COLOR;\n\n    rect.attr(rectAttrs);\n    rect.id = element.id;\n\n    var path1 = paper.path(\"M20 55 L37 34 L275 34 L291 55\");\n    path1.attr({\n        \"opacity\": 1,\n        \"stroke\": strokeColor,\n        \"fill\": \"#ffffff\"\n    });\n\n    var planModelHeader = paper.set();\n    planModelHeader.push(path1);\n\n    planModelHeader.translate(element.x, element.y - 55);\n    if (element.name) {\n        this._drawMultilineText(element.name, element.x + 10, element.y - 16, 275, element.height, \"middle\", \"top\", 11);\n    }\n}\n\nfunction _drawEntryCriterion(element)\n{\n    var strokeColor = _cmmnGetColor(element, MAIN_STROKE_COLOR);\n\n    var rhombus = paper.path(\"M\" + element.x + \" \" + (element.y + (element.height / 2)) +\n        \"L\" + (element.x + (element.width / 2)) + \" \" + (element.y + element.height) +\n        \"L\" + (element.x + element.width) + \" \" + (element.y + (element.height / 2)) +\n        \"L\" + (element.x + (element.width / 2)) + \" \" + element.y + \"z\"\n    );\n\n    // Fill\n    var gatewayFillColor = WHITE_FILL_COLOR;\n\n    // Opacity\n    var gatewayOpacity = 1.0;\n\n    rhombus.attr(\"stroke-width\", 1);\n    rhombus.attr(\"stroke\", strokeColor);\n    rhombus.attr(\"fill\", gatewayFillColor);\n    rhombus.attr(\"fill-opacity\", gatewayOpacity);\n\n    rhombus.id = element.id;\n}\n\nfunction _drawExitCriterion(element)\n{\n    var strokeColor = _cmmnGetColor(element, MAIN_STROKE_COLOR);\n\n    var rhombus = paper.path(\"M\" + element.x + \" \" + (element.y + (element.height / 2)) +\n        \"L\" + (element.x + (element.width / 2)) + \" \" + (element.y + element.height) +\n        \"L\" + (element.x + element.width) + \" \" + (element.y + (element.height / 2)) +\n        \"L\" + (element.x + (element.width / 2)) + \" \" + element.y + \"z\"\n    );\n\n    // Fill\n    var gatewayFillColor = '#000000';\n\n    // Opacity\n    var gatewayOpacity = 1.0;\n\n    rhombus.attr(\"stroke-width\", 1);\n    rhombus.attr(\"stroke\", strokeColor);\n    rhombus.attr(\"fill\", gatewayFillColor);\n    rhombus.attr(\"fill-opacity\", gatewayOpacity);\n\n    rhombus.id = element.id;\n}\n\nfunction _drawMultilineText(text, x, y, boxWidth, boxHeight, horizontalAnchor, verticalAnchor, fontSize)\n{\n\tif (!text || text == \"\")\n\t{\n\t\treturn;\n\t}\n\n\tvar textBoxX, textBoxY;\n    var width = boxWidth - (2 * TEXT_PADDING);\n\n    if (horizontalAnchor === \"middle\")\n    {\n    \ttextBoxX = x + (boxWidth / 2);\n    }\n    else if (horizontalAnchor === \"start\")\n    {\n    \ttextBoxX = x;\n    }\n\n    textBoxY = y + (boxHeight / 2);\n\n \tvar t = paper.text(textBoxX + TEXT_PADDING, textBoxY + TEXT_PADDING).attr({\n        \"text-anchor\" : horizontalAnchor,\n        \"font-family\" : \"Arial\",\n        \"font-size\" : fontSize,\n        \"fill\" : \"#373e48\"\n  \t});\n\n    var abc = \"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ\";\n    t.attr({\n        \"text\" : abc\n    });\n    var letterWidth = t.getBBox().width / abc.length;\n\n    t.attr({\n        \"text\" : text\n    });\n    var removedLineBreaks = text.split(\"\\n\");\n    var x = 0, s = [];\n    for (var r = 0; r < removedLineBreaks.length; r++)\n    {\n  \t    var words = removedLineBreaks[r].split(\" \");\n  \t    for ( var i = 0; i < words.length; i++) {\n\n  \t        var l = words[i].length;\n  \t        if (x + (l * letterWidth) > width) {\n  \t            s.push(\"\\n\");\n  \t            x = 0;\n  \t        }\n  \t        x += l * letterWidth;\n  \t        s.push(words[i] + \" \");\n  \t    }\n\t  \ts.push(\"\\n\");\n        x = 0;\n    }\n    t.attr({\n    \t\"text\" : s.join(\"\")\n    });\n\n    if (verticalAnchor && verticalAnchor === \"top\")\n    {\n    \tt.attr({\"y\": y + (t.getBBox().height / 2)});\n    }\n}\n\nfunction _drawAssociation(flow){\n\n\tvar polyline = new Polyline(flow.id, flow.waypoints, ASSOCIATION_STROKE, paper);\n\tpolyline.element = paper.path(polyline.path);\n\tpolyline.element.attr({\"stroke-width\": ASSOCIATION_STROKE});\n\tpolyline.element.attr({\"stroke-dasharray\": \". \"});\n\tpolyline.element.attr({\"stroke\":\"#585858\"});\n\n\tpolyline.element.id = flow.id;\n\n\tvar polylineInvisible = new Polyline(flow.id, flow.waypoints, ASSOCIATION_STROKE, paper);\n\n\tpolylineInvisible.element = paper.path(polyline.path);\n\tpolylineInvisible.element.attr({\n\t\t\t\"opacity\": 0,\n\t\t\t\"stroke-width\": 8,\n            \"stroke\" : \"#000000\"\n\t});\n\n\t_showTip(jQuery(polylineInvisible.element.node), flow);\n\n\tpolylineInvisible.element.mouseover(function() {\n\t\tpaper.getById(polyline.element.id).attr({\"stroke\":\"blue\"});\n\t});\n\n\tpolylineInvisible.element.mouseout(function() {\n\t\tpaper.getById(polyline.element.id).attr({\"stroke\":\"#585858\"});\n\t});\n}\n\nfunction _drawArrowHead(line, connectionType)\n{\n\tvar doubleArrowWidth = 2 * ARROW_WIDTH;\n\n\tvar arrowHead = paper.path(\"M0 0L-\" + (ARROW_WIDTH / 2 + .5) + \" -\" + doubleArrowWidth + \"L\" + (ARROW_WIDTH/2 + .5) + \" -\" + doubleArrowWidth + \"z\");\n\n\t// anti smoothing\n\tif (this.strokeWidth%2 == 1)\n\t\tline.x2 += .5, line.y2 += .5;\n\n\tarrowHead.transform(\"t\" + line.x2 + \",\" + line.y2 + \"\");\n\tarrowHead.transform(\"...r\" + Raphael.deg(line.angle - Math.PI / 2) + \" \" + 0 + \" \" + 0);\n\n\tarrowHead.attr(\"fill\", \"#585858\");\n\n\tarrowHead.attr(\"stroke-width\", SEQUENCEFLOW_STROKE);\n\tarrowHead.attr(\"stroke\", \"#585858\");\n\n\treturn arrowHead;\n}\n"
  },
  {
    "path": "flowable-ui-web/task/display-cmmn/cmmn-icons.js",
    "content": "/* 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\nfunction _drawHumanTaskIcon(paper, startX, startY)\n{\n\tvar path1 = paper.path(\"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\tpath1.attr({\n\t\t\"opacity\": 1,\n\t\t\"stroke\": \"none\",\n\t\t\"fill\": \"#d1b575\"\n \t});\n\n\tvar userTaskIcon = paper.set();\n\tuserTaskIcon.push(path1);\n\n\tuserTaskIcon.transform(\"T\" + startX + \",\" + startY);\n}\n\nfunction _drawServiceTaskIcon(paper, startX, startY)\n{\n\tvar path1 = paper.path(\"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\tpath1.attr({\n\t\t\"opacity\": 1,\n\t\t\"stroke\": \"none\",\n\t\t\"fill\": \"#72a7d0\"\n \t});\n\n\tvar serviceTaskIcon = paper.set();\n\tserviceTaskIcon.push(path1);\n\n\tserviceTaskIcon.transform(\"T\" + startX + \",\" + startY);\n}\n\nfunction _drawCaseTaskIcon(paper, startX, startY)\n{\n    var path1 = paper.path(\"M5 8 L9 4 L18 4 L 21 7\");\n    path1.attr({\n        \"opacity\": 1,\n        \"stroke\": \"#000000\",\n        \"fill\": \"#000000\"\n    });\n\n    var path2 = paper.path(\"M1 23 L1 4 L30 4 L30 23z\");\n    path2.attr({\n        \"opacity\": 1,\n        \"stroke\": \"#000000\",\n        \"fill\": \"#F4F6F7\"\n    });\n\n    var caseTaskIcon = paper.set();\n    caseTaskIcon.push(path1);\n    caseTaskIcon.push(path2);\n\n    caseTaskIcon.translate(startX, startY);\n    caseTaskIcon.scale(0.7, 0.7);\n}\n\nfunction _drawProcessTaskIcon(paper, startX, startY)\n{\n    var path1 = paper.path(\"M1 23 L7 11 L1 0 L30 0 L 35 11 L 30 23z\");\n    path1.attr({\n        \"opacity\": 1,\n        \"stroke\": \"#000000\",\n        \"fill\": \"#F4F6F7\"\n    });\n\n    var processTaskIcon = paper.set();\n    processTaskIcon.push(path1);\n\n    processTaskIcon.translate(startX, startY);\n    processTaskIcon.scale(0.7, 0.7);\n}\n\nfunction _drawDecisionTaskIcon(paper, startX, startY)\n{\n    var path1 = paper.path(\"m 1,2 0,14 16,0 0,-14 z m 1.9,2.4000386 3.7,0 0,2.7999224 -3.7,0 z m 4.36364,0 3.7,0 0,2.7999224 -3.7,0 z m 4.36364,0 3.7,0 0,2.7999224 -3.7,0 z m -8.67364,3.9 3.7,0 0,2.7999224 -3.7,0 z m 4.36364,0 3.7,0 0,2.7999224 -3.7,0 z m 4.36364,0 3.7,0 0,2.7999224 -3.7,0 z m -8.67364,3.9 3.7,0 0,2.7999224 -3.7,0 z m 4.36364,0 3.7,0 0,2.7999224 -3.7,0 z m 4.36364,0 3.7,0 0,2.7999224 -3.7,0 z\");\n    path1.attr({\n        \"opacity\": 1,\n        \"stroke\": \"#000000\",\n        \"fill\": \"#F4F6F7\"\n    });\n\n    var decisionTaskIcon = paper.set();\n    decisionTaskIcon.push(path1);\n\n    decisionTaskIcon.translate(startX, startY);\n    decisionTaskIcon.scale(0.7, 0.7);\n}\n\nfunction _drawHttpTaskIcon(paper, startX, startY)\n{\n    var path = paper.path(\"m 16.704699,5.9229055 q 0.358098,0 0.608767,0.2506681 0.250669,0.250668 0.250669,0.6087677 0,0.3580997 -0.250669,0.6087677 -0.250669,0.2506679 -0.608767,0.2506679 -0.358098,0 -0.608767,-0.2506679 -0.250669,-0.250668 -0.250669,-0.6087677 0,-0.3580997 0.250669,-0.6087677 0.250669,-0.2506681 0.608767,-0.2506681 z m 2.578308,-2.0053502 q -2.229162,0 -3.854034,0.6759125 -1.624871,0.6759067 -3.227361,2.2694472 -0.716197,0.725146 -1.575633,1.7457293 L 7.2329969,8.7876913 Q 7.0897576,8.8055849 7.000233,8.9309334 L 4.9948821,12.368677 q -0.035811,0.06267 -0.035811,0.143242 0,0.107426 0.080572,0.205905 l 0.5729577,0.572957 q 0.125334,0.116384 0.2864786,0.07162 l 2.4708789,-0.760963 2.5156417,2.515645 -0.76096,2.470876 q -0.009,0.02687 -0.009,0.08057 0,0.125338 0.08058,0.205905 l 0.572957,0.572958 q 0.170096,0.152194 0.349146,0.04476 l 3.437744,-2.005351 q 0.125335,-0.08953 0.143239,-0.232763 l 0.17905,-3.392986 q 1.02058,-0.859435 1.745729,-1.575629 1.67411,-1.6830612 2.309735,-3.2049805 0.635625,-1.5219191 0.635625,-3.8585111 0,-0.1253369 -0.08505,-0.2148575 -0.08505,-0.089526 -0.201431,-0.089526 z\");\n    path.attr({\n        \"opacity\": 1,\n        \"stroke\": \"none\",\n        \"fill\": \"#16964d\"\n    });\n\n    startX += -2;\n    startY += -2;\n\n    path.transform(\"T\" + startX + \",\" + startY);\n\n}\n\nfunction _drawBusinessRuleTaskIcon(paper, startX, startY) {\n    var path1 = paper.path(\"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    path1.attr({\n        \"stroke\": \"none\",\n        \"fill\": \"#72a7d0\"\n    });\n\n    var businessRuleTaskIcon = paper.set();\n    businessRuleTaskIcon.push(path1);\n\n    businessRuleTaskIcon.transform(\"T\" + startX + \",\" + startY);\n}\n\nfunction _drawTimerEventListenerIcon(paper, element)\n{\n\tvar x = element.x + (element.width / 2);\n    var y = element.y + (element.height / 2);\n\n\tvar circle = paper.circle(x, y, 10);\n\n\tcircle.attr({\"stroke-width\": 1,\n\t\t\"stroke\": \"black\",\n\t\t\"fill\": \"none\"\n \t});\n\n\tvar path = paper.path(\"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\tpath.attr({\n\t\t\"stroke\": \"none\",\n\t\t\"fill\": \"#585858\"\n \t});\n\tpath.transform(\"T\" + (element.x + 5) + \",\" + (element.y + 5));\n\treturn path;\n}\n\nfunction _drawUserEventListenerIcon(paper, element) {\n    var userTaskIcon = paper.set();\n    var path1 = paper.path(\"M0.585,24.167h24.083v-7.833c0,0-2.333-3.917-7.083-5.167h-9.25 c-4.417,1.333-7.833,5.75-7.833,5.75L0.585,24.167z\");\n    path1.attr({\"opacity\": 1, \"stroke\": \"none\", \"fill\": \"#F4F6F7\"});\n    userTaskIcon.push(path1);\n\n    var path2 = paper.path(\"M6,20L6,24\");\n    path2.attr({\"opacity\": 1, \"stroke\": \"white\", \"fill\": \"none\"});\n    userTaskIcon.push(path2);\n\n    var path3 = paper.path(\"M20,20L20,24\");\n    path3.attr({\"opacity\": 1, \"stroke\": \"white\", \"fill\": \"none\"});\n    userTaskIcon.push(path3);\n\n    var circle = paper.circle(13.002, 5.916, 5.417);\n    circle.attr({\"stroke-width\": 1, \"stroke\": \"black\", \"fill\": \"#000000\"});\n    userTaskIcon.push(circle);\n\n    var path4 = paper.path(\"M8.043,7.083c0,0,2.814-2.426,5.376-1.807s4.624-0.693,4.624-0.693 c0.25,1.688,0.042,3.75-1.458,5.584c0,0,1.083,0.75,1.083,1.5s0.125,1.875-1,3s-5.5,1.25-6.75,0S8.668,12.834,8.668,12 s0.583-1.25,1.25-1.917C8.835,9.5,7.419,7.708,8.043,7.083z\");\n    path4.attr({\"opacity\": 1, \"stroke\": \"none\", \"fill\": \"#F0EFF0\"});\n    userTaskIcon.push(path4);\n\n    var x = (element.width / 2) - 2;\n    var y = (element.height / 2) - 2;\n    var circle2 = paper.circle(x, y, 17);\n    circle2.attr({\"stroke-width\": 1, \"stroke\": \"#F0EFF0\", \"fill\": \"none\"});\n    userTaskIcon.push(circle2);\n\n    userTaskIcon.transform(\"S0.7,0.7\" + \"T\" + (element.x + 2) + \",\" + (element.y + 2));\n    return userTaskIcon;\n}\n"
  },
  {
    "path": "flowable-ui-web/task/display-cmmn/displaymodel.css",
    "content": "div[class*='ui-tooltip-flowable-'] {\n    background-color: #ffffff;\n    border-color: #c5c5c5;\n    color: #4a4a4a;\n    font-family: Verdana;\n    font-size: 12px;\n}\n\ndiv[class*='ui-tooltip-flowable-'] .qtip-content {\n  color: #4a4a4a;\n  background-color: #ffffff;\n  font-family: Verdana;\n  font-size: 12px;\n}\n\n.ui-tooltip-flowable-cmmn .qtip-titlebar {\n  color: #FFFFFF;\n  font-size: 12px;\n  background: #2B414F;\n}\n\n.ui-tooltip-flowable-cmmn .qtip-tip {\n  background-color: #2B414F;\n}\n"
  },
  {
    "path": "flowable-ui-web/task/display-cmmn/displaymodel.html",
    "content": "<html>  \n    <head>\n\n        <link type=\"text/css\" rel=\"stylesheet\" href=\"../display/jquery.qtip.min.css\" />\n        <link type=\"text/css\" rel=\"stylesheet\" href=\"displaymodel.css\" />\n\n        <script type=\"text/javascript\" src=\"../display/jquery.qtip.min.js\"></script>\n        <script type=\"text/javascript\" src=\"../display/raphael.min.js\"></script>\n        <script type=\"text/javascript\" src=\"cmmn-draw.js\"></script>\n        <script type=\"text/javascript\" src=\"cmmn-icons.js\"></script>\n        <script type=\"text/javascript\" src=\"../display/Polyline.js\"></script>\n        <script type=\"text/javascript\" src=\"\"></script>\n\n    </head>\n</html>"
  },
  {
    "path": "flowable-ui-web/task/display-cmmn/displaymodel.js",
    "content": "/* 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 */\nvar NORMAL_STROKE = 1;\nvar ASSOCIATION_STROKE = 2;\nvar TASK_STROKE = 1;\nvar TASK_HIGHLIGHT_STROKE = 2;\n\nvar COMPLETED_COLOR = \"#2632aa\";\nvar TEXT_COLOR= \"#373e48\";\nvar CURRENT_COLOR= \"#017501\";\nvar AVAILABLE_COLOR = \"#e3da82\";\nvar HOVER_COLOR= \"#666666\";\nvar ACTIVITY_STROKE_COLOR = \"#bbbbbb\";\nvar ACTIVITY_FILL_COLOR = \"#f9f9f9\";\nvar WHITE_FILL_COLOR = \"#ffffff\";\nvar MAIN_STROKE_COLOR = \"#585858\";\n\nvar TEXT_PADDING = 3;\nvar ARROW_WIDTH = 4;\nvar MARKER_WIDTH = 12;\n\nvar TASK_FONT = {font: \"11px Arial\", opacity: 1, fill: Raphael.rgb(0, 0, 0)};\n\n// icons\nvar ICON_SIZE = 16;\nvar ICON_PADDING = 4;\n\nvar INITIAL_CANVAS_WIDTH;\nvar INITIAL_CANVAS_HEIGHT;\n\nvar paper;\nvar viewBox;\nvar viewBoxWidth;\nvar viewBoxHeight;\n\nvar canvasWidth;\nvar canvasHeight;\n\nvar modelDiv = jQuery('#cmmnModel');\nvar modelId = modelDiv.attr('data-model-id');\nvar historyModelId = modelDiv.attr('data-history-id');\nvar caseDefinitionId = modelDiv.attr('data-case-definition-id');\nvar modelType = modelDiv.attr('data-model-type');\n\nvar elementsAdded = new Array();\nvar elementsRemoved = new Array();\n\nfunction _showTip(htmlNode, element)\n{\n    // Default tooltip, no custom tool tip set\n    if (documentation === undefined) {\n        var documentation = \"\";\n        if (element.name && element.name.length > 0) {\n            documentation += \"<b>Name</b>: <i>\" + element.name + \"</i><br/><br/>\";\n        }\n\n        if (element.properties) {\n            for (var i = 0; i < element.properties.length; i++) {\n                var propName = element.properties[i].name;\n                if (element.properties[i].type && element.properties[i].type === 'list') {\n                    documentation += '<b>' + propName + '</b>:<br/>';\n                    for (var j = 0; j < element.properties[i].value.length; j++) {\n                        documentation += '<i>' + element.properties[i].value[j] + '</i><br/>';\n                    }\n                }\n                else {\n                    documentation += '<b>' + propName + '</b>: <i>' + element.properties[i].value + '</i><br/>';\n                }\n            }\n        }\n    }\n\n    var text = element.type + \" \";\n    if (element.name && element.name.length > 0)\n    {\n        text += element.name;\n    }\n    else\n    {\n        text += element.id;\n    }\n\n    htmlNode.qtip({\n        content: {\n            text: documentation,\n            title: {\n                text: text\n            }\n        },\n        position: {\n            my: 'top left',\n            at: 'bottom center',\n            viewport: jQuery('#cmmnModel')\n        },\n        hide: {\n            fixed: true, delay: 500,\n            event: 'click mouseleave'\n        },\n        style: {\n            classes: 'ui-tooltip-flowable-cmmn'\n        }\n    });\n}\n\nfunction _addHoverLogic(element, type, defaultColor)\n{\n    var strokeColor = _cmmnGetColor(element, defaultColor);\n    var topBodyRect = null;\n    if (type === \"rect\")\n    {\n        topBodyRect = paper.rect(element.x, element.y, element.width, element.height);\n    }\n    else if (type === \"circle\")\n    {\n        var x = element.x + (element.width / 2);\n        var y = element.y + (element.height / 2);\n        topBodyRect = paper.circle(x, y, 15);\n    }\n    else if (type === \"rhombus\")\n    {\n        topBodyRect = paper.path(\"M\" + element.x + \" \" + (element.y + (element.height / 2)) +\n            \"L\" + (element.x + (element.width / 2)) + \" \" + (element.y + element.height) +\n            \"L\" + (element.x + element.width) + \" \" + (element.y + (element.height / 2)) +\n            \"L\" + (element.x + (element.width / 2)) + \" \" + element.y + \"z\"\n        );\n    }\n\n    var opacity = 0;\n    var fillColor = \"#ffffff\";\n    if (jQuery.inArray(element.id, elementsAdded) >= 0)\n    {\n        opacity = 0.2;\n        fillColor = \"green\";\n    }\n\n    if (jQuery.inArray(element.id, elementsRemoved) >= 0)\n    {\n        opacity = 0.2;\n        fillColor = \"red\";\n    }\n\n    topBodyRect.attr({\n        \"opacity\": opacity,\n        \"stroke\" : \"none\",\n        \"fill\" : fillColor\n    });\n    _showTip(jQuery(topBodyRect.node), element);\n\n    topBodyRect.mouseover(function() {\n        paper.getById(element.id).attr({\"stroke\":HOVER_COLOR});\n    });\n\n    topBodyRect.mouseout(function() {\n        paper.getById(element.id).attr({\"stroke\":strokeColor});\n    });\n}\n\nfunction _zoom(zoomIn)\n{\n    var tmpCanvasWidth, tmpCanvasHeight;\n    if (zoomIn)\n    {\n        tmpCanvasWidth = canvasWidth * (1.0/0.90);\n        tmpCanvasHeight = canvasHeight * (1.0/0.90);\n    }\n    else\n    {\n        tmpCanvasWidth = canvasWidth * (1.0/1.10);\n        tmpCanvasHeight = canvasHeight * (1.0/1.10);\n    }\n\n    if (tmpCanvasWidth != canvasWidth || tmpCanvasHeight != canvasHeight)\n    {\n        canvasWidth = tmpCanvasWidth;\n        canvasHeight = tmpCanvasHeight;\n        paper.setSize(canvasWidth, canvasHeight);\n    }\n}\n\nvar modelUrl;\n\nif (modelType == 'runtime') {\n\tif (historyModelId) {\n    \tmodelUrl = FLOWABLE.CONFIG.contextRoot + '/app/rest/case-instances/history/' + historyModelId + '/model-json';\n\t} else {\n    \tmodelUrl = FLOWABLE.CONFIG.contextRoot + '/app/rest/case-instances/' + modelId + '/model-json';\n\t}\n} else if (modelType == 'design') {\n\tif (historyModelId) {\n    \tmodelUrl = FLOWABLE.CONFIG.contextRoot + '/app/rest/models/' + modelId + '/history/' + historyModelId + '/model-json';\n\t} else {\n    \tmodelUrl = FLOWABLE.CONFIG.contextRoot + '/app/rest/models/' + modelId + '/model-json';\n\t}\n} else if (modelType == 'case-definition') {\n    modelUrl = FLOWABLE.CONFIG.contextRoot + '/app/rest/case-definitions/' + caseDefinitionId + '/model-json';\n}\n\nvar request = jQuery.ajax({\n    type: 'get',\n    url: modelUrl + '?nocaching=' + new Date().getTime()\n});\n\nrequest.success(function(data, textStatus, jqXHR) {\n\n    if ((!data.elements || data.elements.length == 0) && (!data.pools || data.pools.length == 0)) return;\n\n    INITIAL_CANVAS_WIDTH = data.diagramWidth;\n    \n    if (modelType == 'design') {\n    \tINITIAL_CANVAS_WIDTH += 20;\n    } else {\n        INITIAL_CANVAS_WIDTH += 30;\n    }\n    \n    INITIAL_CANVAS_HEIGHT = data.diagramHeight + 50;\n    canvasWidth = INITIAL_CANVAS_WIDTH;\n    canvasHeight = INITIAL_CANVAS_HEIGHT;\n    viewBoxWidth = INITIAL_CANVAS_WIDTH;\n    viewBoxHeight = INITIAL_CANVAS_HEIGHT;\n    \n    if (modelType == 'design') {\n    \tvar headerBarHeight = 170;\n    \tvar offsetY = 0;\n    \tif (jQuery(window).height() > (canvasHeight + headerBarHeight))\n    \t{\n        \toffsetY = (jQuery(window).height() - headerBarHeight - canvasHeight) / 2;\n    \t}\n\n    \tif (offsetY > 50) {\n        \toffsetY = 50;\n    \t}\n\n    \tjQuery('#cmmnModel').css('marginTop', offsetY);\n    }\n\n    jQuery('#cmmnModel').width(INITIAL_CANVAS_WIDTH);\n    jQuery('#cmmnModel').height(INITIAL_CANVAS_HEIGHT);\n    paper = Raphael(document.getElementById('cmmnModel'), canvasWidth, canvasHeight);\n    paper.setViewBox(0, 0, viewBoxWidth, viewBoxHeight, false);\n    paper.renderfix();\n\n    var modelElements = data.elements;\n    for (var i = 0; i < modelElements.length; i++)\n    {\n        var element = modelElements[i];\n        //try {\n        var drawFunction = eval(\"_draw\" + element.type);\n        drawFunction(element);\n        //} catch(err) {console.log(err);}\n    }\n\n    if (data.flows)\n    {\n        for (var i = 0; i < data.flows.length; i++)\n        {\n            var flow = data.flows[i];\n            _drawAssociation(flow);\n        }\n    }\n});\n\nrequest.error(function(jqXHR, textStatus, errorThrown) {\n    alert(\"error\");\n});\n"
  },
  {
    "path": "flowable-ui-web/task/error/404.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"utf-8\">\n    <title>Page Not Found :(</title>\n    <style>\n      ::-moz-selection {\n        background: #b3d4fc;\n        text-shadow: none;\n      }\n\n      ::selection {\n        background: #b3d4fc;\n        text-shadow: none;\n      }\n\n      html {\n        padding: 30px 10px;\n        font-size: 20px;\n        line-height: 1.4;\n        color: #737373;\n        background: #f0f0f0;\n        -webkit-text-size-adjust: 100%;\n        -ms-text-size-adjust: 100%;\n      }\n\n      html,\n      input {\n        font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n      }\n\n      body {\n        max-width: 500px;\n        _width: 500px;\n        padding: 30px 20px 50px;\n        border: 1px solid #b3b3b3;\n        border-radius: 4px;\n        margin: 0 auto;\n        box-shadow: 0 1px 10px #a7a7a7, inset 0 1px 0 #fff;\n        background: #fcfcfc;\n      }\n\n      h1 {\n        margin: 0 10px;\n        font-size: 50px;\n        text-align: center;\n      }\n\n      h1 span {\n        color: #bbb;\n      }\n\n      h3 {\n        margin: 1.5em 0 0.5em;\n      }\n\n      p {\n        margin: 1em 0;\n      }\n\n      ul {\n        padding: 0 0 0 40px;\n        margin: 1em 0;\n      }\n\n      .container {\n        max-width: 380px;\n        _width: 380px;\n        margin: 0 auto;\n      }\n\n      /* google search */\n\n      #goog-fixurl ul {\n        list-style: none;\n        padding: 0;\n        margin: 0;\n      }\n\n      #goog-fixurl form {\n        margin: 0;\n      }\n\n      #goog-wm-qt,\n      #goog-wm-sb {\n        border: 1px solid #bbb;\n        font-size: 16px;\n        line-height: normal;\n        vertical-align: top;\n        color: #444;\n        border-radius: 2px;\n      }\n\n      #goog-wm-qt {\n        width: 220px;\n        height: 20px;\n        padding: 5px;\n        margin: 5px 10px 0 0;\n        box-shadow: inset 0 1px 1px #ccc;\n      }\n\n      #goog-wm-sb {\n        display: inline-block;\n        height: 32px;\n        padding: 0 10px;\n        margin: 5px 0 0;\n        white-space: nowrap;\n        cursor: pointer;\n        background-color: #f5f5f5;\n        background-image: -webkit-linear-gradient(rgba(255,255,255,0), #f1f1f1);\n        background-image: -moz-linear-gradient(rgba(255,255,255,0), #f1f1f1);\n        background-image: -ms-linear-gradient(rgba(255,255,255,0), #f1f1f1);\n        background-image: -o-linear-gradient(rgba(255,255,255,0), #f1f1f1);\n        -webkit-appearance: none;\n        -moz-appearance: none;\n        appearance: none;\n        *overflow: visible;\n        *display: inline;\n        *zoom: 1;\n      }\n\n      #goog-wm-sb:hover,\n      #goog-wm-sb:focus {\n        border-color: #aaa;\n        box-shadow: 0 1px 1px rgba(0, 0, 0, 0.1);\n        background-color: #f8f8f8;\n      }\n\n      #goog-wm-qt:hover,\n      #goog-wm-qt:focus {\n        border-color: #105cb6;\n        outline: 0;\n        color: #222;\n      }\n\n      input::-moz-focus-inner {\n        padding: 0;\n        border: 0;\n      }\n    </style>\n  </head>\n  <body>\n    <div class=\"container\">\n      <h1>Not found <span>:(</span></h1>\n      <p>Sorry, but the page you were trying to view does not exist.</p>\n      <p>It looks like this was the result of either:</p>\n      <ul>\n        <li>a mistyped address</li>\n        <li>an out-of-date link</li>\n      </ul>\n      <script>\n        var GOOG_FIXURL_LANG = (navigator.language || '').slice(0,2),GOOG_FIXURL_SITE = location.host;\n      </script>\n      <script src=\"//linkhelp.clients.google.com/tbproxy/lh/wm/fixurl.js\"></script>\n    </div>\n  </body>\n</html>\n"
  },
  {
    "path": "flowable-ui-web/task/i18n/en.json",
    "content": "{\n   \"GENERAL\": {\n        \"MAIN-TITLE\": \"Flowable\",\n        \"ERROR\": {\n            \"GENERIC\": \"Sorry, an error occured...\",\n            \"UNKNOWN\": \"Sorry, an error occured while performing the requested operation.\",\n            \"BAD_REQUEST\": \"An error occured while performing the requested operation\",\n            \"NOT_FOUND\": \"The resource you are trying to access does not exist\",\n            \"UNAUTHORIZED\": \"You should sign in in order to perform the requested operation.\",\n            \"FORBIDDEN\": \"You are not allowed to perform the requested operation\",\n            \"INTERNAL_SERVER_ERROR\": \"Sorry, an unexpected error occured while performing the requested operation.\"\n        },\n        \"ACTION\": {\n            \"LOGOUT\": \"Sign out\",\n            \"HELP\": \"Getting started\",\n            \"EDIT-PROFILE\": \"Edit profile\",\n            \"SAVE\": \"Save\",\n            \"CANCEL\": \"Cancel\",\n            \"CLOSE\": \"Close\",\n            \"DEPLOY\": \"Deploy\",\n            \"ABOUT\": \"About Flowable\"\n        }\n    },\n    \"LOGIN\": {\n        \"TITLE\": \"Sign in\",\n        \"USERNAME\": \"Username\",\n        \"USERNAME-PLACEHOLDER\": \"Enter your username\",\n        \"PASSWORD\": \"Password\",\n        \"PASSWORD-PLACEHOLDER\": \"Enter your password\",\n        \"INVALID-CREDENTIALS\": \"Invalid credentials\",\n        \"ACTION\": {\n            \"CONFIRM\": \"Sign in\"\n        }\n    },\n    \"ACCOUNT\": {\n        \"ACTIVATE\": {\n          \"TITLE\": \"Activate account\",\n          \"ACTIVATING-MESSAGE\": \"Hold on tight {{userFullName}} we're activating your account...\",\n          \"SUCCESS-MESSAGE\": \"Your account has been activated. Please sign in below to start designing and running processes\",\n          \"FAILURE-MESSAGE\": \"Your account cannot be activated. Either it has already been activated or the activation link has expired.\"\n        },\n\n        \"RESET-PASSWORD-REQUEST\": {\n          \"MESSAGE\": \"Forgot your password? Enter your email address below to receive an email to reset your password.\",\n          \"TITLE\": \"Reset password\",\n          \"EMAIL\": \"Email address\",\n          \"EMAIL-PLACEHOLDER\": \"Enter your email\",\n          \"SECURITY-SECTION\": \"Security check\",\n          \"CONFIRM\": \"Request password reset\",\n          \"SUCCESS-MESSAGE\": \"You will receive a mail shortly with a link to reset your password.\",\n          \"ERROR\": {\n              \"UNEXISTING-USER\": \"User with the given email address does not exist.\"\n          }\n        },\n\n        \"RESET-PASSWORD\": {\n          \"TITLE\": \"Reset password\",\n          \"PASSWORD\": \"Password\",\n          \"PASSWORD-CONFIRM\": \"Confirm password\",\n          \"PASSWORD-PLACEHOLDER\": \"Enter a new password\",\n          \"PASSWORD-CONFIRM-PLACEHOLDER\": \"Confirm the new password\",\n          \"CONFIRM\": \"Change password\",\n          \"LOADING\": \"Resetting password...\",\n          \"SUCCESS-MESSAGE\": \"Your password has been changed.\",\n          \"LOGIN\": \"Sign in now\",\n          \"FAILURE-MESSAGE\": \"Your password cannot be reset. The reset link is invalid or expired.\"\n        }\n    },\n    \"APP\": {\n        \"KICKSTART\": {\n            \"TITLE\": \"Kickstart App\",\n            \"DESCRIPTION\": \"Create process models, forms and app definitions, then share your models and definitions with other people.\"\n        },\n        \"TASKS\": {\n            \"TITLE\": \"Task App\",\n            \"DESCRIPTION\": \"Access your full task list and work on any tasks assigned to you from any process app. Also, start new processes and tasks.\"\n        },\n        \"IDENTITY-MANAGEMENT\": {\n            \"TITLE\": \"Identity management\",\n            \"TITLE-TENANT-ADMIN\": \"Identity management\",\n            \"DESCRIPTION\": \"Manage your profile: change your picture, name and other settings. As an admin user, manage users and groups.\",\n            \"DESCRIPTION-TENANT-ADMIN\": \"Manage the users and groups in your organization.\"\n        },\n        \"CUSTOM-APP\" : {\n            \"TITLE-TASKS\": \"tasks\",\n            \"TITLE-PROCESSES\": \"processes\"\n        },\n        \"POPUP\" : {\n            \"ADD-APP-TITLE\": \"Add app to landing page\",\n            \"ADD-APP-SUMMARY\": \"Add an app to your landing page\"\n        },\n        \"ACTION\": {\n            \"DELETE\": \"Remove app\"\n        },\n        \"MESSAGE\": {\n            \"DELETED\": \"App was successfully removed\"\n        }\n    }\n}\n"
  },
  {
    "path": "flowable-ui-web/task/i18n/fr.json",
    "content": "{\n   \"GENERAL\": {\n        \"MAIN-TITLE\": \"Flowable\",\n        \"ERROR\": {\n            \"GENERIC\": \"Désolé, une erreur s'est produite...\",\n            \"UNKNOWN\": \"Désolé, une erreur s'est produite lors de l'exécution de l'opération.\",\n            \"BAD_REQUEST\": \"Une erreur s'est produite lors de l'exécution de l'opération demandée.\",\n            \"NOT_FOUND\": \"La resource demandée n'existe pas\",\n            \"UNAUTHORIZED\": \"Veuillez d'abord vous connecter pour effectuer cette opération.\",\n            \"FORBIDDEN\": \"Vous n'êtes pas autorisé à effectuer cette opération.\",\n            \"INTERNAL_SERVER_ERROR\": \"Désolé, une erreur inattendue s'est produite lors de l'exécution de l'opération.\"\n        },\n        \"ACTION\": {\n            \"LOGOUT\": \"Déconnexion\",\n            \"HELP\": \"Prise en main\",\n            \"EDIT-PROFILE\": \"Editer profil\",\n            \"SAVE\": \"Sauver\",\n            \"CANCEL\": \"Annuler\",\n            \"CLOSE\": \"Fermer\",\n            \"DEPLOY\": \"Déployer\",\n            \"ABOUT\": \"A propos\"\n        }\n    },\n    \"LOGIN\": {\n        \"TITLE\": \"Se connecter\",\n        \"USERNAME\": \"Nom d'utilisateur\",\n        \"USERNAME-PLACEHOLDER\": \"Veuillez saisir votre nom d'utilisateur\",\n        \"PASSWORD\": \"Mot de passe\",\n        \"PASSWORD-PLACEHOLDER\": \"Veuillez saisir votre mot de passe\",\n        \"INVALID-CREDENTIALS\": \"Identifiants invalides\",\n        \"ACTION\": {\n            \"CONFIRM\": \"Connexion\"\n        }\n    },\n    \"ACCOUNT\": {\n        \"ACTIVATE\": {\n          \"TITLE\": \"Activer votre compte\",\n          \"ACTIVATING-MESSAGE\": \"Tenez bon {{userFullName}} nous activons votre compte...\",\n          \"SUCCESS-MESSAGE\": \"Votre compte a été activé. Veuillez vous connecter ci dessous pour concevoir et executer des processus.\",\n          \"FAILURE-MESSAGE\": \"Votre compte ne peut être activé. Il est soit déjà actif soit le lien d'activation a expiré.\"\n        },\n\n        \"RESET-PASSWORD-REQUEST\": {\n          \"MESSAGE\": \"Mot de pass oublié ? Veuillez saisir votre adresse e-mail ci dessous afin de recevoir un email de réinitialisation\",\n          \"TITLE\": \"Réinitialiser mot de passe\",\n          \"EMAIL\": \"Adresse e-mail\",\n          \"EMAIL-PLACEHOLDER\": \"Veuillez saisir votre e-mail\",\n          \"SECURITY-SECTION\": \"Vérifications de sécurité\",\n          \"CONFIRM\": \"Demande de réinitialisation du mot de passe\",\n          \"SUCCESS-MESSAGE\": \"Vous recevrez sous peu un e-mail vous expliquant comment réinitialiser votre mot de passe.\",\n          \"ERROR\": {\n              \"UNEXISTING-USER\": \"Aucun utilisateur n'existe avec cet adresse e-mail.\"\n          }\n        },\n\n        \"RESET-PASSWORD\": {\n          \"TITLE\": \"Réinitialiser mot de passe\",\n          \"PASSWORD\": \"Mot de passe\",\n          \"PASSWORD-CONFIRM\": \"Confirmez le mot de passe\",\n          \"PASSWORD-PLACEHOLDER\": \"Entrez un nouveau mot de passe\",\n          \"PASSWORD-CONFIRM-PLACEHOLDER\": \"Confirmez le nouveau mot de passe \",\n          \"CONFIRM\": \"Changer le mot de passe\",\n          \"LOADING\": \"Réinitialisation du mot de passe...\",\n          \"SUCCESS-MESSAGE\": \"Votre mot de passe a été modifié.\",\n          \"LOGIN\": \"Se connecter\",\n          \"FAILURE-MESSAGE\": \"Votre mot de passe ne peut être réinitialisé. Le lien a expiré ou est invalide.\"\n        }\n    },\n    \"APP\": {\n        \"KICKSTART\": {\n            \"TITLE\": \"Conception\",\n            \"DESCRIPTION\": \"Créez des modèles de processus, des formulaires et des définitions d'applications puis partagez les avec d'autres personnes.\"\n        },\n        \"TASKS\": {\n            \"TITLE\": \"Tâches\",\n            \"DESCRIPTION\": \"Accédez à votre liste de tâches et travaillez sur celles qui vous sont assignées. Vous pouvez aussi démarrer des processus et des tâches.\"\n        },\n        \"IDENTITY-MANAGEMENT\": {\n            \"TITLE\": \"Gestion des identités\",\n            \"TITLE-TENANT-ADMIN\": \"Gestion des identités\",\n            \"DESCRIPTION\": \"Gérer votre profil: modifier votre photo, votre nom et d'autres paramètres. En tant qu'administrateur, gérer les utilisateurs et groupes.\",\n            \"DESCRIPTION-TENANT-ADMIN\": \"Gérer les groupes et utilisateurs de votre organisation.\"\n        },\n        \"CUSTOM-APP\" : {\n            \"TITLE-TASKS\": \"tâches\",\n            \"TITLE-PROCESSES\": \"processus\"\n        },\n        \"POPUP\" : {\n            \"ADD-APP-TITLE\": \"Ajouter une application à la page d'accueil\",\n            \"ADD-APP-SUMMARY\": \"Ajouter une application sur votre page d'accueil\"\n        },\n        \"ACTION\": {\n            \"DELETE\": \"Enlever une application\"\n        },\n        \"MESSAGE\": {\n            \"DELETED\": \"L'application a été enlevée avec succès.\"\n        }\n    }\n}\n"
  },
  {
    "path": "flowable-ui-web/task/i18n/pt-BR.json",
    "content": "{\n  \"GENERAL\":{\n    \"MAIN-TITLE\":\"Flowable\",\n    \"ERROR\":{\n      \"GENERIC\":\"Desculpe, ocorreu um erro...\",\n      \"UNKNOWN\":\"Desculpe, um erro ocorreu durante a execução da operação solicitada.\",\n      \"BAD_REQUEST\":\"Um erro ocorreu durante a execução da operação solicitada\",\n      \"NOT_FOUND\":\"O recurso que você está tentando acessar não existe\",\n      \"UNAUTHORIZED\":\"Você deveria assinar para executar a operação solicitada.\",\n      \"FORBIDDEN\":\"Você não está autorizado a executar a operação solicitada\",\n      \"INTERNAL_SERVER_ERROR\":\"Desculpe, um erro inesperado ocorreu durante a execução da operação solicitada.\"\n    },\n    \"ACTION\":{\n      \"LOGOUT\":\"Sair\",\n      \"HELP\":\"Guia de introdução\",\n      \"EDIT-PROFILE\":\"Editar perfil\",\n      \"SAVE\":\"Salvar\",\n      \"CANCEL\":\"Cancelar\",\n      \"CLOSE\":\"Fechar\",\n      \"DEPLOY\":\"Implantar\",\n      \"ABOUT\":\"Sobre Flowable\"\n    }\n  },\n  \"LOGIN\":{\n    \"TITLE\":\"Entrar\",\n    \"USERNAME\":\"Nome de Usuário\",\n    \"USERNAME-PLACEHOLDER\":\"Digite seu nome de usuário\",\n    \"PASSWORD\":\"Senha\",\n    \"PASSWORD-PLACEHOLDER\":\"Digite sua senha\",\n    \"INVALID-CREDENTIALS\":\"Credenciais inválidas\",\n    \"ACTION\":{\n      \"CONFIRM\":\"Entrar\"\n    }\n  },\n  \"ACCOUNT\":{\n    \"ACTIVATE\":{\n      \"TITLE\":\"Ativar Conta\",\n      \"ACTIVATING-MESSAGE\":\"Aguarde um momento {{userFullName}} que estamos ativando sua conta...\",\n      \"SUCCESS-MESSAGE\":\"Sua conta foi ativada. Por favor, Cadastre-se abaixo para começar a desenhar e executar processos\",\n      \"FAILURE-MESSAGE\":\"Sua conta não pode ser ativada. Ou já foi ativada ou o link de ativação expirou.\"\n    },\n    \"RESET-PASSWORD-REQUEST\":{\n      \"MESSAGE\":\"Esqueceu sua senha? Digite seu endereço de e-mail abaixo para receber um e-mail e redefinir sua senha.\",\n      \"TITLE\":\"Redefinir senha\",\n      \"EMAIL\":\"E-mail\",\n      \"EMAIL-PLACEHOLDER\":\"Digite seu e-mail\",\n      \"SECURITY-SECTION\":\"Verificação de segurança\",\n      \"CONFIRM\":\"Pedido de redefinição de senha\",\n      \"SUCCESS-MESSAGE\":\"Em breve você receberá um e-mail com um link para redefinir sua senha.\",\n      \"ERROR\":{\n        \"UNEXISTING-USER\":\"O usuário com o endereço de e-mail fornecido não existe.\"\n      }\n    },\n    \"RESET-PASSWORD\":{\n      \"TITLE\":\"Redefinir senha\",\n      \"PASSWORD\":\"Senha\",\n      \"PASSWORD-CONFIRM\":\"Confirme a senha\",\n      \"PASSWORD-PLACEHOLDER\":\"Digite a nova senha\",\n      \"PASSWORD-CONFIRM-PLACEHOLDER\":\"Confirme a nova senha\",\n      \"CONFIRM\":\"Alterar a senha\",\n      \"LOADING\":\"Redefinindo senha...\",\n      \"SUCCESS-MESSAGE\":\"Sua senha foi alterada.\",\n      \"LOGIN\":\"Entrar agora\",\n      \"FAILURE-MESSAGE\":\"Sua senha não pode ser redefinida. O link de redefinição é inválido ou está expirado.\"\n    }\n  },\n  \"APP\":{\n    \"KICKSTART\":{\n      \"TITLE\":\"Aplicativo inicial\",\n      \"DESCRIPTION\":\"Crie modelos de processos, formulários e definições de aplicativo, em seguida, compartilhe seus modelos e definições com outras pessoas.\"\n    },\n    \"TASKS\":{\n      \"TITLE\":\"Aplicativo de Tarefa\",\n      \"DESCRIPTION\":\"Acesse a sua lista de tarefa completa e trabalhe em qualquer tarefa atribuídas a você de qualquer aplicativo de processo. Além disso, inicie novos processos e tarefas.\"\n    },\n    \"IDENTITY-MANAGEMENT\":{\n      \"TITLE\":\"Gerenciamento de identidade\",\n      \"TITLE-TENANT-ADMIN\":\"Gerenciamento de identidade\",\n      \"DESCRIPTION\":\"Gerenciar seu perfil: mude sua imagem, nome e outras configurações. Como um usuário administrador, gerencie usuários e grupos.\",\n      \"DESCRIPTION-TENANT-ADMIN\":\"Gerencie usuários e grupos em sua organização.\"\n    },\n    \"CUSTOM-APP\":{\n      \"TITLE-TASKS\":\"tarefas\",\n      \"TITLE-PROCESSES\":\"processos\"\n    },\n    \"POPUP\":{\n      \"ADD-APP-TITLE\":\"Adicione o aplicativo na página inicial\",\n      \"ADD-APP-SUMMARY\":\"Adicionar um aplicativo em sua página inicial\"\n    },\n    \"ACTION\":{\n      \"DELETE\":\"Remover aplicativo\"\n    },\n    \"MESSAGE\":{\n      \"DELETED\":\"O aplicativo foi removido com êxito\"\n    }\n  }\n}\n"
  },
  {
    "path": "flowable-ui-web/task/i18n/zh-CN.json",
    "content": "{\n   \"GENERAL\": {\n        \"MAIN-TITLE\": \"Flowable\",\n        \"ERROR\": {\n            \"GENERIC\": \"对不起, 发生了错误...\",\n            \"UNKNOWN\": \"对不起, 执行请求的操作时出错。\",\n            \"BAD_REQUEST\": \"执行请求的操作时发生错误\",\n            \"NOT_FOUND\": \"您试图访问的资源不存在\",\n            \"UNAUTHORIZED\": \"您应该登录才能执行请求的操作。\",\n            \"FORBIDDEN\": \"您不允许执行请求的操作\",\n            \"INTERNAL_SERVER_ERROR\": \"对不起, 执行请求的操作时出现意外错误。\"\n        },\n        \"ACTION\": {\n            \"LOGOUT\": \"退出\",\n            \"HELP\": \"入门\",\n            \"EDIT-PROFILE\": \"编辑配置文件\",\n            \"SAVE\": \"保存\",\n            \"CANCEL\": \"取消\",\n            \"CLOSE\": \"关闭\",\n            \"DEPLOY\": \"部署\",\n            \"ABOUT\": \"关于Flowable\"\n        }\n    },\n    \"LOGIN\": {\n        \"TITLE\": \"登录\",\n        \"USERNAME\": \"用户名\",\n        \"USERNAME-PLACEHOLDER\": \"输入您的用户名\",\n        \"PASSWORD\": \"密码\",\n        \"PASSWORD-PLACEHOLDER\": \"输入您的密码\",\n        \"INVALID-CREDENTIALS\": \"无效凭据\",\n        \"ACTION\": {\n            \"CONFIRM\": \"登录\"\n        }\n    },\n    \"ACCOUNT\": {\n        \"ACTIVATE\": {\n          \"TITLE\": \"激活帐户\",\n          \"ACTIVATING-MESSAGE\": \"{{userFullName}} , 请稍候, 我们正在激活您的帐户 ...\",\n          \"SUCCESS-MESSAGE\": \"您的帐户已被激活。请在下面登录, 开始设计和运行流程\",\n          \"FAILURE-MESSAGE\": \"您的帐户无法激活。它已被激活或激活链接已过期。\"\n        },\n\n        \"RESET-PASSWORD-REQUEST\": {\n          \"MESSAGE\": \"忘记了您的密码？在下面输入您的电子邮件地址, 以接收电子邮件来重置您的密码。\",\n          \"TITLE\":\"重置密码\",\n          \"EMAIL\":\"电子邮件地址\",\n          \"EMAIL-PLACEHOLDER\":\"输入您的电子邮件\",\n          \"SECURITY-SECTION\":\"安全检查\",\n          \"CONFIRM\":\"请求密码重置\",\n          \"SUCCESS-MESSAGE\":\"你会收到一封邮件的链接, 重置您的密码。\",\n          \"ERROR\": {\n              \"UNEXISTING-USER\":\"具有给定电子邮件地址的用户不存在。\"\n          }\n        },\n\n        \"RESET-PASSWORD\": {\n          \"TITLE\":\"重置密码\",\n          \"PASSWORD\":\"密码\",\n          \"PASSWORD-CONFIRM\":\"确认密码\",\n          \"PASSWORD-PLACEHOLDER\":\"输入新密码\",\n          \"PASSWORD-CONFIRM-PLACEHOLDER\":\"确认新密码\",\n          \"CONFIRM\":\"更改密码\",\n          \"LOADING\":\"重置密码...\",\n          \"SUCCESS-MESSAGE\":\"您的密码已更改。\",\n          \"LOGIN\":\"现在登录\",\n          \"FAILURE-MESSAGE\":\"您的密码无法重置。重置链接无效或已过期。\"\n        }\n    },\n    \"APP\": {\n        \"KICKSTART\": {\n            \"TITLE\": \"启动应用程序\",\n            \"DESCRIPTION\": \"创建流程模型、表单和应用程序定义, 然后与他人共享您的模型和定义。\"\n        },\n        \"TASKS\": {\n            \"TITLE\": \"任务应用程序\",\n            \"DESCRIPTION\": \" 访问您的完成任务列表, 并处理从任何流程应用程序分配给您的任何任务。此外, 启动新的进程和任务。\"\n        },\n        \"IDENTITY-MANAGEMENT\": {\n            \"TITLE\": \"身份管理\",\n            \"TITLE-TENANT-ADMIN\": \"身份管理\",\n            \"DESCRIPTION\": \"管理您的个人资料: 更改您的图片、名称和其他设置。作为Admin用户, 可以管理用户和组。\",\n            \"DESCRIPTION-TENANT-ADMIN\": \"管理组织中的用户和组。\"\n        },\n        \"CUSTOM-APP\" : {\n            \"TITLE-TASKS\": \"任务\",\n            \"TITLE-PROCESSES\": \"流程\"\n        },\n        \"POPUP\" : {\n            \"ADD-APP-TITLE\": \"将应用程序添加到登录页\",\n            \"ADD-APP-SUMMARY\": \"将应用程序添加到您的登录页\"\n        },\n        \"ACTION\": {\n            \"DELETE\": \"删除应用程序\"\n        },\n        \"MESSAGE\": {\n            \"DELETED\": \"应用程序已成功删除\"\n        }\n    }\n}\n"
  },
  {
    "path": "flowable-ui-web/task/index.html",
    "content": "<!doctype html>\n<!--[if lt IE 7]>      <html class=\"no-js lt-ie9 lt-ie8 lt-ie7\"> <![endif]-->\n<!--[if IE 7]>         <html class=\"no-js lt-ie9 lt-ie8\"> <![endif]-->\n<!--[if IE 8]>         <html class=\"no-js lt-ie9\"> <![endif]-->\n<!--[if gt IE 8]><!--> <html class=\"no-js\"> <!--<![endif]-->\n<head>\n    <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=\"theme-color\" content=\"#ffffff\">\n    <title>Flowable Task</title>\n\n    <link rel=\"apple-touch-icon\" sizes=\"180x180\" href=\"images/apple-touch-icon.png?v=Om5N75Y123\">\n    <link rel=\"icon\" type=\"image/png\" href=\"images/favicon-32x32.png?v=Om5N75Y123\" sizes=\"32x32\">\n    <link rel=\"icon\" type=\"image/png\" href=\"images/favicon-16x16.png?v=Om5N75Y123\" sizes=\"16x16\">\n    <link rel=\"manifest\" href=\"manifest.json\">\n    <link rel=\"mask-icon\" href=\"images/safari-pinned-tab.svg?v=Om5N75Y123\" color=\"#506d75\">\n    <link rel=\"shortcut icon\" href=\"favicon.ico?v=Om5N75Y123\">\n\n    <!-- build:css styles/common/3thparty.css -->\n    <link href=\"styles/common/bootstrap.min.css\" rel=\"stylesheet\">\n    <link href=\"libs/nvd3_1.1.15-beta/nvd3.min.css\" rel=\"stylesheet\">\n    <link href=\"libs/bootstrap-daterangepicker_1.3.7/daterangepicker-bs3.css\" rel=\"stylesheet\">\n    <link href=\"libs/ui-grid_3.0.0/ui-grid.min.css\" rel=\"stylesheet\">\n    <!-- endbuild -->\n\n    <!-- build:css styles/style.css -->\n    <link href=\"styles/style-landing.css\" rel=\"stylesheet\">\n    <!-- endbuild -->\n\n    <!-- build:css styles/common/style.css -->\n    <link href=\"styles/common/style.css\" rel=\"stylesheet\">\n    <link href=\"styles/common/style-retina.css\" rel=\"stylesheet\">\n    <!-- endbuild -->\n\n</head>\n<body ng-app=\"flowableLanding\" ng-cloak>\n\n    <div ng-if=\"!onLogin\">\n\n        <div class=\"navbar navbar-fixed-top navbar-inverse\" role=\"navigation\" id=\"main-nav\">\n            <div class=\"fixed-container\">\n                <div class=\"navbar-header\">\n                    <a ng-click=\"backToLanding()\" class=\"landing-logo\" ng-if=\"account != null && account != undefined\">\n                        <img ng-src=\"{{appResourceRoot}}images/flowable-logo.png\" ng-srcset=\"{{appResourceRoot}}images/flowable-logo.png 1x, {{appResourceRoot}}images/flowable-logo@2x.png 2x\">\n                    </a>\n                </div>\n                <div class=\"pull-right\">\n                    <div class=\"dropdown btn-group btn-group-sm\">\n                        <button type=\"button\" class=\"btn btn-default dropdown-toggle\" data-toggle=\"dropdown\"> {{account.firstName}} {{account.lastName}}\n                            <span class=\"glyphicon glyphicon-chevron-down\" style=\"font-size: 10px\" aria-hidden=\"true\"></span>\n                        </button>\n                        <ul class=\"dropdown-menu pull-right\">\n                            <li><a ng-click=\"logout()\" translate=\"GENERAL.ACTION.LOGOUT\"></a></li>\n                        </ul>\n                    </div>\n\n                </div>\n            </div>\n        </div>\n\n        <div class=\"alert-wrapper\" ng-cloak>\n            <div class=\"alert {{alerts.current.type}}\" ng-show=\"alerts.current\" ng-click=\"dismissAlert()\">\n                <span>{{alerts.current.message}}</span>\n                <span class=\"badge\" ng-show=\"alerts.queue.length\">{{alerts.queue.length + 1}}</span>\n            </div>\n        </div>\n\n        <div class=\"apps-wrapper clearfix\" ng-view=\"\" ng-cloak ng-style=\"{height: window.height + 'px'}\">\n        </div>\n\n    </div>\n\n    <div ng-if=\"onLogin\">\n        <div class=\"alert-wrapper\" ng-cloak>\n            <div class=\"alert {{alerts.current.type}}\" ng-show=\"alerts.current\" ng-click=\"dismissAlert()\">\n                <span>{{alerts.current.message}}</span>\n                <span class=\"badge\" ng-show=\"alerts.queue.length\">{{alerts.queue.length + 1}}</span>\n            </div>\n        </div>\n        <div ng-view=\"\" ng-cloak ng-style=\"{height: window.height + 'px'}\"></div>\n    </div>\n\n    <!--[if lt IE 9]>\n    <div class=\"unsupported-browser\">\n        <p class=\"alert error\">You are using an unsupported browser. Please upgrade your browser in order to use the editor.</p>\n    </div>\n    <![endif]-->\n\n    <!--[if lt IE 9]>\n    <script src=\"libs/es5-shim-15.3.4.5/es5-shim.js\"></script>\n    <script src=\"libs/json3_3.2.6/lib/json3.min.js\"></script>\n    <![endif]-->\n\n    <!-- 3rd party libs -->\n    <script src=\"libs/jquery_1.11.0/jquery.min.js\"></script>\n    <script src=\"libs/jquery-ui-1.10.3.custom.min.js\"></script>\n\n    <script src=\"libs/angular_1.3.13/angular.js\"></script>\n    <script src=\"libs/angular-animate_1.3.13/angular-animate.min.js\"></script>\n    <script src=\"libs/bootstrap_3.1.1/js/bootstrap.min.js\"></script>\n    <script src=\"libs/angular-resource_1.3.13/angular-resource.min.js\"></script>\n    <script src=\"libs/angular-cookies_1.3.13/angular-cookies.min.js\"></script>\n    <script src=\"libs/angular-sanitize_1.3.13/angular-sanitize.min.js\"></script>\n    <script src=\"libs/angular-route_1.3.13/angular-route.min.js\"></script>\n    <script src=\"libs/angular-translate_2.15.1/angular-translate.min.js\"></script>\n    <script src=\"libs/angular-translate-storage-cookie/angular-translate-storage-cookie.js\"></script>\n    <script src=\"libs/angular-translate-loader-static-files/angular-translate-loader-static-files.js\"></script>\n    <script src=\"libs/angular-strap_2.1.6/angular-strap.min.js\"></script>\n    <script src=\"libs/angular-strap_2.1.6/angular-strap.tpl.min.js\"></script>\n    <script src=\"libs/ui-grid_3.0.0/ui-grid.min.js\"></script>\n    <script src=\"libs/autofill-events_1.0.0/autofill-event.js\"></script>\n\n    <!-- Configuration -->\n    <script src=\"scripts/app-cfg.js?v=2\"></script>\n\n    <!-- build:js scripts/scripts.js -->\n    <script src=\"scripts/landing-app.js\"></script>\n    <script src=\"scripts/common/services/related-content-service.js\"></script>\n    <script src=\"scripts/common/services/runtime-app-definition-service.js\"></script>\n    <script src=\"scripts/common/directives.js\"></script>\n    <script src=\"scripts/common/providers-config.js\"></script>\n    <script src=\"scripts/landing-controller.js\"></script>\n\n    <script src=\"scripts/common/controllers/about.js\"></script>\n    <!-- endbuild -->\n\n    <!-- Integration extensions -->\n    <script src=\"scripts/resource-loader.js?v=2\" app=\"landing\"></script>\n\n</body>\n</html>\n"
  },
  {
    "path": "flowable-ui-web/task/libs/angular-animate_1.3.13/angular-animate.js",
    "content": "/**\n * @license AngularJS v1.3.13\n * (c) 2010-2014 Google, Inc. http://angularjs.org\n * License: MIT\n */\n(function(window, angular, undefined) {'use strict';\n\n/* jshint maxlen: false */\n\n/**\n * @ngdoc module\n * @name ngAnimate\n * @description\n *\n * The `ngAnimate` module provides support for JavaScript, CSS3 transition and CSS3 keyframe animation hooks within existing core and custom directives.\n *\n * <div doc-module-components=\"ngAnimate\"></div>\n *\n * # Usage\n *\n * To see animations in action, all that is required is to define the appropriate CSS classes\n * or to register a JavaScript animation via the `myModule.animation()` function. The directives that support animation automatically are:\n * `ngRepeat`, `ngInclude`, `ngIf`, `ngSwitch`, `ngShow`, `ngHide`, `ngView` and `ngClass`. Custom directives can take advantage of animation\n * by using the `$animate` service.\n *\n * Below is a more detailed breakdown of the supported animation events provided by pre-existing ng directives:\n *\n * | Directive                                                                                                | Supported Animations                                                     |\n * |----------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------|\n * | {@link ng.directive:ngRepeat#animations ngRepeat}                                                        | enter, leave and move                                                    |\n * | {@link ngRoute.directive:ngView#animations ngView}                                                       | enter and leave                                                          |\n * | {@link ng.directive:ngInclude#animations ngInclude}                                                      | enter and leave                                                          |\n * | {@link ng.directive:ngSwitch#animations ngSwitch}                                                        | enter and leave                                                          |\n * | {@link ng.directive:ngIf#animations ngIf}                                                                | enter and leave                                                          |\n * | {@link ng.directive:ngClass#animations ngClass}                                                          | add and remove (the CSS class(es) present)                               |\n * | {@link ng.directive:ngShow#animations ngShow} & {@link ng.directive:ngHide#animations ngHide}            | add and remove (the ng-hide class value)                                 |\n * | {@link ng.directive:form#animation-hooks form} & {@link ng.directive:ngModel#animation-hooks ngModel}    | add and remove (dirty, pristine, valid, invalid & all other validations) |\n * | {@link module:ngMessages#animations ngMessages}                                                          | add and remove (ng-active & ng-inactive)                                 |\n * | {@link module:ngMessages#animations ngMessage}                                                           | enter and leave                                                          |\n *\n * You can find out more information about animations upon visiting each directive page.\n *\n * Below is an example of how to apply animations to a directive that supports animation hooks:\n *\n * ```html\n * <style type=\"text/css\">\n * .slide.ng-enter, .slide.ng-leave {\n *   -webkit-transition:0.5s linear all;\n *   transition:0.5s linear all;\n * }\n *\n * .slide.ng-enter { }        /&#42; starting animations for enter &#42;/\n * .slide.ng-enter.ng-enter-active { } /&#42; terminal animations for enter &#42;/\n * .slide.ng-leave { }        /&#42; starting animations for leave &#42;/\n * .slide.ng-leave.ng-leave-active { } /&#42; terminal animations for leave &#42;/\n * </style>\n *\n * <!--\n * the animate service will automatically add .ng-enter and .ng-leave to the element\n * to trigger the CSS transition/animations\n * -->\n * <ANY class=\"slide\" ng-include=\"...\"></ANY>\n * ```\n *\n * Keep in mind that, by default, if an animation is running, any child elements cannot be animated\n * until the parent element's animation has completed. This blocking feature can be overridden by\n * placing the `ng-animate-children` attribute on a parent container tag.\n *\n * ```html\n * <div class=\"slide-animation\" ng-if=\"on\" ng-animate-children>\n *   <div class=\"fade-animation\" ng-if=\"on\">\n *     <div class=\"explode-animation\" ng-if=\"on\">\n *        ...\n *     </div>\n *   </div>\n * </div>\n * ```\n *\n * When the `on` expression value changes and an animation is triggered then each of the elements within\n * will all animate without the block being applied to child elements.\n *\n * ## Are animations run when the application starts?\n * No they are not. When an application is bootstrapped Angular will disable animations from running to avoid\n * a frenzy of animations from being triggered as soon as the browser has rendered the screen. For this to work,\n * Angular will wait for two digest cycles until enabling animations. From there on, any animation-triggering\n * layout changes in the application will trigger animations as normal.\n *\n * In addition, upon bootstrap, if the routing system or any directives or load remote data (via $http) then Angular\n * will automatically extend the wait time to enable animations once **all** of the outbound HTTP requests\n * are complete.\n *\n * ## CSS-defined Animations\n * The animate service will automatically apply two CSS classes to the animated element and these two CSS classes\n * are designed to contain the start and end CSS styling. Both CSS transitions and keyframe animations are supported\n * and can be used to play along with this naming structure.\n *\n * The following code below demonstrates how to perform animations using **CSS transitions** with Angular:\n *\n * ```html\n * <style type=\"text/css\">\n * /&#42;\n *  The animate class is apart of the element and the ng-enter class\n *  is attached to the element once the enter animation event is triggered\n * &#42;/\n * .reveal-animation.ng-enter {\n *  -webkit-transition: 1s linear all; /&#42; Safari/Chrome &#42;/\n *  transition: 1s linear all; /&#42; All other modern browsers and IE10+ &#42;/\n *\n *  /&#42; The animation preparation code &#42;/\n *  opacity: 0;\n * }\n *\n * /&#42;\n *  Keep in mind that you want to combine both CSS\n *  classes together to avoid any CSS-specificity\n *  conflicts\n * &#42;/\n * .reveal-animation.ng-enter.ng-enter-active {\n *  /&#42; The animation code itself &#42;/\n *  opacity: 1;\n * }\n * </style>\n *\n * <div class=\"view-container\">\n *   <div ng-view class=\"reveal-animation\"></div>\n * </div>\n * ```\n *\n * The following code below demonstrates how to perform animations using **CSS animations** with Angular:\n *\n * ```html\n * <style type=\"text/css\">\n * .reveal-animation.ng-enter {\n *   -webkit-animation: enter_sequence 1s linear; /&#42; Safari/Chrome &#42;/\n *   animation: enter_sequence 1s linear; /&#42; IE10+ and Future Browsers &#42;/\n * }\n * @-webkit-keyframes enter_sequence {\n *   from { opacity:0; }\n *   to { opacity:1; }\n * }\n * @keyframes enter_sequence {\n *   from { opacity:0; }\n *   to { opacity:1; }\n * }\n * </style>\n *\n * <div class=\"view-container\">\n *   <div ng-view class=\"reveal-animation\"></div>\n * </div>\n * ```\n *\n * Both CSS3 animations and transitions can be used together and the animate service will figure out the correct duration and delay timing.\n *\n * Upon DOM mutation, the event class is added first (something like `ng-enter`), then the browser prepares itself to add\n * the active class (in this case `ng-enter-active`) which then triggers the animation. The animation module will automatically\n * detect the CSS code to determine when the animation ends. Once the animation is over then both CSS classes will be\n * removed from the DOM. If a browser does not support CSS transitions or CSS animations then the animation will start and end\n * immediately resulting in a DOM element that is at its final state. This final state is when the DOM element\n * has no CSS transition/animation classes applied to it.\n *\n * ### Structural transition animations\n *\n * Structural transitions (such as enter, leave and move) will always apply a `0s none` transition\n * value to force the browser into rendering the styles defined in the setup (`.ng-enter`, `.ng-leave`\n * or `.ng-move`) class. This means that any active transition animations operating on the element\n * will be cut off to make way for the enter, leave or move animation.\n *\n * ### Class-based transition animations\n *\n * Class-based transitions refer to transition animations that are triggered when a CSS class is\n * added to or removed from the element (via `$animate.addClass`, `$animate.removeClass`,\n * `$animate.setClass`, or by directives such as `ngClass`, `ngModel` and `form`).\n * They are different when compared to structural animations since they **do not cancel existing\n * animations** nor do they **block successive transitions** from rendering on the same element.\n * This distinction allows for **multiple class-based transitions** to be performed on the same element.\n *\n * In addition to ngAnimate supporting the default (natural) functionality of class-based transition\n * animations, ngAnimate also decorates the element with starting and ending CSS classes to aid the\n * developer in further styling the element throughout the transition animation. Earlier versions\n * of ngAnimate may have caused natural CSS transitions to break and not render properly due to\n * $animate temporarily blocking transitions using `0s none` in order to allow the setup CSS class\n * (the `-add` or `-remove` class) to be applied without triggering an animation. However, as of\n * **version 1.3**, this workaround has been removed with ngAnimate and all non-ngAnimate CSS\n * class transitions are compatible with ngAnimate.\n *\n * There is, however, one special case when dealing with class-based transitions in ngAnimate.\n * When rendering class-based transitions that make use of the setup and active CSS classes\n * (e.g. `.fade-add` and `.fade-add-active` for when `.fade` is added) be sure to define\n * the transition value **on the active CSS class** and not the setup class.\n *\n * ```css\n * .fade-add {\n *   /&#42; remember to place a 0s transition here\n *      to ensure that the styles are applied instantly\n *      even if the element already has a transition style &#42;/\n *   transition:0s linear all;\n *\n *   /&#42; starting CSS styles &#42;/\n *   opacity:1;\n * }\n * .fade-add.fade-add-active {\n *   /&#42; this will be the length of the animation &#42;/\n *   transition:1s linear all;\n *   opacity:0;\n * }\n * ```\n *\n * The setup CSS class (in this case `.fade-add`) also has a transition style property, however, it\n * has a duration of zero. This may not be required, however, incase the browser is unable to render\n * the styling present in this CSS class instantly then it could be that the browser is attempting\n * to perform an unnecessary transition.\n *\n * This workaround, however, does not apply to  standard class-based transitions that are rendered\n * when a CSS class containing a transition is applied to an element:\n *\n * ```css\n * /&#42; this works as expected &#42;/\n * .fade {\n *   transition:1s linear all;\n *   opacity:0;\n * }\n * ```\n *\n * Please keep this in mind when coding the CSS markup that will be used within class-based transitions.\n * Also, try not to mix the two class-based animation flavors together since the CSS code may become\n * overly complex.\n *\n *\n * ### Preventing Collisions With Third Party Libraries\n *\n * Some third-party frameworks place animation duration defaults across many element or className\n * selectors in order to make their code small and reuseable. This can lead to issues with ngAnimate, which\n * is expecting actual animations on these elements and has to wait for their completion.\n *\n * You can prevent this unwanted behavior by using a prefix on all your animation classes:\n *\n * ```css\n * /&#42; prefixed with animate- &#42;/\n * .animate-fade-add.animate-fade-add-active {\n *   transition:1s linear all;\n *   opacity:0;\n * }\n * ```\n *\n * You then configure `$animate` to enforce this prefix:\n *\n * ```js\n * $animateProvider.classNameFilter(/animate-/);\n * ```\n * </div>\n *\n * ### CSS Staggering Animations\n * A Staggering animation is a collection of animations that are issued with a slight delay in between each successive operation resulting in a\n * curtain-like effect. The ngAnimate module (versions >=1.2) supports staggering animations and the stagger effect can be\n * performed by creating a **ng-EVENT-stagger** CSS class and attaching that class to the base CSS class used for\n * the animation. The style property expected within the stagger class can either be a **transition-delay** or an\n * **animation-delay** property (or both if your animation contains both transitions and keyframe animations).\n *\n * ```css\n * .my-animation.ng-enter {\n *   /&#42; standard transition code &#42;/\n *   -webkit-transition: 1s linear all;\n *   transition: 1s linear all;\n *   opacity:0;\n * }\n * .my-animation.ng-enter-stagger {\n *   /&#42; this will have a 100ms delay between each successive leave animation &#42;/\n *   -webkit-transition-delay: 0.1s;\n *   transition-delay: 0.1s;\n *\n *   /&#42; in case the stagger doesn't work then these two values\n *    must be set to 0 to avoid an accidental CSS inheritance &#42;/\n *   -webkit-transition-duration: 0s;\n *   transition-duration: 0s;\n * }\n * .my-animation.ng-enter.ng-enter-active {\n *   /&#42; standard transition styles &#42;/\n *   opacity:1;\n * }\n * ```\n *\n * Staggering animations work by default in ngRepeat (so long as the CSS class is defined). Outside of ngRepeat, to use staggering animations\n * on your own, they can be triggered by firing multiple calls to the same event on $animate. However, the restrictions surrounding this\n * are that each of the elements must have the same CSS className value as well as the same parent element. A stagger operation\n * will also be reset if more than 10ms has passed after the last animation has been fired.\n *\n * The following code will issue the **ng-leave-stagger** event on the element provided:\n *\n * ```js\n * var kids = parent.children();\n *\n * $animate.leave(kids[0]); //stagger index=0\n * $animate.leave(kids[1]); //stagger index=1\n * $animate.leave(kids[2]); //stagger index=2\n * $animate.leave(kids[3]); //stagger index=3\n * $animate.leave(kids[4]); //stagger index=4\n *\n * $timeout(function() {\n *   //stagger has reset itself\n *   $animate.leave(kids[5]); //stagger index=0\n *   $animate.leave(kids[6]); //stagger index=1\n * }, 100, false);\n * ```\n *\n * Stagger animations are currently only supported within CSS-defined animations.\n *\n * ## JavaScript-defined Animations\n * In the event that you do not want to use CSS3 transitions or CSS3 animations or if you wish to offer animations on browsers that do not\n * yet support CSS transitions/animations, then you can make use of JavaScript animations defined inside of your AngularJS module.\n *\n * ```js\n * //!annotate=\"YourApp\" Your AngularJS Module|Replace this or ngModule with the module that you used to define your application.\n * var ngModule = angular.module('YourApp', ['ngAnimate']);\n * ngModule.animation('.my-crazy-animation', function() {\n *   return {\n *     enter: function(element, done) {\n *       //run the animation here and call done when the animation is complete\n *       return function(cancelled) {\n *         //this (optional) function will be called when the animation\n *         //completes or when the animation is cancelled (the cancelled\n *         //flag will be set to true if cancelled).\n *       };\n *     },\n *     leave: function(element, done) { },\n *     move: function(element, done) { },\n *\n *     //animation that can be triggered before the class is added\n *     beforeAddClass: function(element, className, done) { },\n *\n *     //animation that can be triggered after the class is added\n *     addClass: function(element, className, done) { },\n *\n *     //animation that can be triggered before the class is removed\n *     beforeRemoveClass: function(element, className, done) { },\n *\n *     //animation that can be triggered after the class is removed\n *     removeClass: function(element, className, done) { }\n *   };\n * });\n * ```\n *\n * JavaScript-defined animations are created with a CSS-like class selector and a collection of events which are set to run\n * a javascript callback function. When an animation is triggered, $animate will look for a matching animation which fits\n * the element's CSS class attribute value and then run the matching animation event function (if found).\n * In other words, if the CSS classes present on the animated element match any of the JavaScript animations then the callback function will\n * be executed. It should be also noted that only simple, single class selectors are allowed (compound class selectors are not supported).\n *\n * Within a JavaScript animation, an object containing various event callback animation functions is expected to be returned.\n * As explained above, these callbacks are triggered based on the animation event. Therefore if an enter animation is run,\n * and the JavaScript animation is found, then the enter callback will handle that animation (in addition to the CSS keyframe animation\n * or transition code that is defined via a stylesheet).\n *\n *\n * ### Applying Directive-specific Styles to an Animation\n * In some cases a directive or service may want to provide `$animate` with extra details that the animation will\n * include into its animation. Let's say for example we wanted to render an animation that animates an element\n * towards the mouse coordinates as to where the user clicked last. By collecting the X/Y coordinates of the click\n * (via the event parameter) we can set the `top` and `left` styles into an object and pass that into our function\n * call to `$animate.addClass`.\n *\n * ```js\n * canvas.on('click', function(e) {\n *   $animate.addClass(element, 'on', {\n *     to: {\n *       left : e.client.x + 'px',\n *       top : e.client.y + 'px'\n *     }\n *   }):\n * });\n * ```\n *\n * Now when the animation runs, and a transition or keyframe animation is picked up, then the animation itself will\n * also include and transition the styling of the `left` and `top` properties into its running animation. If we want\n * to provide some starting animation values then we can do so by placing the starting animations styles into an object\n * called `from` in the same object as the `to` animations.\n *\n * ```js\n * canvas.on('click', function(e) {\n *   $animate.addClass(element, 'on', {\n *     from: {\n *        position: 'absolute',\n *        left: '0px',\n *        top: '0px'\n *     },\n *     to: {\n *       left : e.client.x + 'px',\n *       top : e.client.y + 'px'\n *     }\n *   }):\n * });\n * ```\n *\n * Once the animation is complete or cancelled then the union of both the before and after styles are applied to the\n * element. If `ngAnimate` is not present then the styles will be applied immediately.\n *\n */\n\nangular.module('ngAnimate', ['ng'])\n\n  /**\n   * @ngdoc provider\n   * @name $animateProvider\n   * @description\n   *\n   * The `$animateProvider` allows developers to register JavaScript animation event handlers directly inside of a module.\n   * When an animation is triggered, the $animate service will query the $animate service to find any animations that match\n   * the provided name value.\n   *\n   * Requires the {@link ngAnimate `ngAnimate`} module to be installed.\n   *\n   * Please visit the {@link ngAnimate `ngAnimate`} module overview page learn more about how to use animations in your application.\n   *\n   */\n  .directive('ngAnimateChildren', function() {\n    var NG_ANIMATE_CHILDREN = '$$ngAnimateChildren';\n    return function(scope, element, attrs) {\n      var val = attrs.ngAnimateChildren;\n      if (angular.isString(val) && val.length === 0) { //empty attribute\n        element.data(NG_ANIMATE_CHILDREN, true);\n      } else {\n        scope.$watch(val, function(value) {\n          element.data(NG_ANIMATE_CHILDREN, !!value);\n        });\n      }\n    };\n  })\n\n  //this private service is only used within CSS-enabled animations\n  //IE8 + IE9 do not support rAF natively, but that is fine since they\n  //also don't support transitions and keyframes which means that the code\n  //below will never be used by the two browsers.\n  .factory('$$animateReflow', ['$$rAF', '$document', function($$rAF, $document) {\n    var bod = $document[0].body;\n    return function(fn) {\n      //the returned function acts as the cancellation function\n      return $$rAF(function() {\n        //the line below will force the browser to perform a repaint\n        //so that all the animated elements within the animation frame\n        //will be properly updated and drawn on screen. This is\n        //required to perform multi-class CSS based animations with\n        //Firefox. DO NOT REMOVE THIS LINE.\n        var a = bod.offsetWidth + 1;\n        fn();\n      });\n    };\n  }])\n\n  .config(['$provide', '$animateProvider', function($provide, $animateProvider) {\n    var noop = angular.noop;\n    var forEach = angular.forEach;\n    var selectors = $animateProvider.$$selectors;\n    var isArray = angular.isArray;\n    var isString = angular.isString;\n    var isObject = angular.isObject;\n\n    var ELEMENT_NODE = 1;\n    var NG_ANIMATE_STATE = '$$ngAnimateState';\n    var NG_ANIMATE_CHILDREN = '$$ngAnimateChildren';\n    var NG_ANIMATE_CLASS_NAME = 'ng-animate';\n    var rootAnimateState = {running: true};\n\n    function extractElementNode(element) {\n      for (var i = 0; i < element.length; i++) {\n        var elm = element[i];\n        if (elm.nodeType == ELEMENT_NODE) {\n          return elm;\n        }\n      }\n    }\n\n    function prepareElement(element) {\n      return element && angular.element(element);\n    }\n\n    function stripCommentsFromElement(element) {\n      return angular.element(extractElementNode(element));\n    }\n\n    function isMatchingElement(elm1, elm2) {\n      return extractElementNode(elm1) == extractElementNode(elm2);\n    }\n    var $$jqLite;\n    $provide.decorator('$animate',\n        ['$delegate', '$$q', '$injector', '$sniffer', '$rootElement', '$$asyncCallback', '$rootScope', '$document', '$templateRequest', '$$jqLite',\n function($delegate,   $$q,   $injector,   $sniffer,   $rootElement,   $$asyncCallback,   $rootScope,   $document,   $templateRequest,   $$$jqLite) {\n\n      $$jqLite = $$$jqLite;\n      $rootElement.data(NG_ANIMATE_STATE, rootAnimateState);\n\n      // Wait until all directive and route-related templates are downloaded and\n      // compiled. The $templateRequest.totalPendingRequests variable keeps track of\n      // all of the remote templates being currently downloaded. If there are no\n      // templates currently downloading then the watcher will still fire anyway.\n      var deregisterWatch = $rootScope.$watch(\n        function() { return $templateRequest.totalPendingRequests; },\n        function(val, oldVal) {\n          if (val !== 0) return;\n          deregisterWatch();\n\n          // Now that all templates have been downloaded, $animate will wait until\n          // the post digest queue is empty before enabling animations. By having two\n          // calls to $postDigest calls we can ensure that the flag is enabled at the\n          // very end of the post digest queue. Since all of the animations in $animate\n          // use $postDigest, it's important that the code below executes at the end.\n          // This basically means that the page is fully downloaded and compiled before\n          // any animations are triggered.\n          $rootScope.$$postDigest(function() {\n            $rootScope.$$postDigest(function() {\n              rootAnimateState.running = false;\n            });\n          });\n        }\n      );\n\n      var globalAnimationCounter = 0;\n      var classNameFilter = $animateProvider.classNameFilter();\n      var isAnimatableClassName = !classNameFilter\n              ? function() { return true; }\n              : function(className) {\n                return classNameFilter.test(className);\n              };\n\n      function classBasedAnimationsBlocked(element, setter) {\n        var data = element.data(NG_ANIMATE_STATE) || {};\n        if (setter) {\n          data.running = true;\n          data.structural = true;\n          element.data(NG_ANIMATE_STATE, data);\n        }\n        return data.disabled || (data.running && data.structural);\n      }\n\n      function runAnimationPostDigest(fn) {\n        var cancelFn, defer = $$q.defer();\n        defer.promise.$$cancelFn = function() {\n          cancelFn && cancelFn();\n        };\n        $rootScope.$$postDigest(function() {\n          cancelFn = fn(function() {\n            defer.resolve();\n          });\n        });\n        return defer.promise;\n      }\n\n      function parseAnimateOptions(options) {\n        // some plugin code may still be passing in the callback\n        // function as the last param for the $animate methods so\n        // it's best to only allow string or array values for now\n        if (isObject(options)) {\n          if (options.tempClasses && isString(options.tempClasses)) {\n            options.tempClasses = options.tempClasses.split(/\\s+/);\n          }\n          return options;\n        }\n      }\n\n      function resolveElementClasses(element, cache, runningAnimations) {\n        runningAnimations = runningAnimations || {};\n\n        var lookup = {};\n        forEach(runningAnimations, function(data, selector) {\n          forEach(selector.split(' '), function(s) {\n            lookup[s]=data;\n          });\n        });\n\n        var hasClasses = Object.create(null);\n        forEach((element.attr('class') || '').split(/\\s+/), function(className) {\n          hasClasses[className] = true;\n        });\n\n        var toAdd = [], toRemove = [];\n        forEach((cache && cache.classes) || [], function(status, className) {\n          var hasClass = hasClasses[className];\n          var matchingAnimation = lookup[className] || {};\n\n          // When addClass and removeClass is called then $animate will check to\n          // see if addClass and removeClass cancel each other out. When there are\n          // more calls to removeClass than addClass then the count falls below 0\n          // and then the removeClass animation will be allowed. Otherwise if the\n          // count is above 0 then that means an addClass animation will commence.\n          // Once an animation is allowed then the code will also check to see if\n          // there exists any on-going animation that is already adding or remvoing\n          // the matching CSS class.\n          if (status === false) {\n            //does it have the class or will it have the class\n            if (hasClass || matchingAnimation.event == 'addClass') {\n              toRemove.push(className);\n            }\n          } else if (status === true) {\n            //is the class missing or will it be removed?\n            if (!hasClass || matchingAnimation.event == 'removeClass') {\n              toAdd.push(className);\n            }\n          }\n        });\n\n        return (toAdd.length + toRemove.length) > 0 && [toAdd.join(' '), toRemove.join(' ')];\n      }\n\n      function lookup(name) {\n        if (name) {\n          var matches = [],\n              flagMap = {},\n              classes = name.substr(1).split('.');\n\n          //the empty string value is the default animation\n          //operation which performs CSS transition and keyframe\n          //animations sniffing. This is always included for each\n          //element animation procedure if the browser supports\n          //transitions and/or keyframe animations. The default\n          //animation is added to the top of the list to prevent\n          //any previous animations from affecting the element styling\n          //prior to the element being animated.\n          if ($sniffer.transitions || $sniffer.animations) {\n            matches.push($injector.get(selectors['']));\n          }\n\n          for (var i=0; i < classes.length; i++) {\n            var klass = classes[i],\n                selectorFactoryName = selectors[klass];\n            if (selectorFactoryName && !flagMap[klass]) {\n              matches.push($injector.get(selectorFactoryName));\n              flagMap[klass] = true;\n            }\n          }\n          return matches;\n        }\n      }\n\n      function animationRunner(element, animationEvent, className, options) {\n        //transcluded directives may sometimes fire an animation using only comment nodes\n        //best to catch this early on to prevent any animation operations from occurring\n        var node = element[0];\n        if (!node) {\n          return;\n        }\n\n        if (options) {\n          options.to = options.to || {};\n          options.from = options.from || {};\n        }\n\n        var classNameAdd;\n        var classNameRemove;\n        if (isArray(className)) {\n          classNameAdd = className[0];\n          classNameRemove = className[1];\n          if (!classNameAdd) {\n            className = classNameRemove;\n            animationEvent = 'removeClass';\n          } else if (!classNameRemove) {\n            className = classNameAdd;\n            animationEvent = 'addClass';\n          } else {\n            className = classNameAdd + ' ' + classNameRemove;\n          }\n        }\n\n        var isSetClassOperation = animationEvent == 'setClass';\n        var isClassBased = isSetClassOperation\n                           || animationEvent == 'addClass'\n                           || animationEvent == 'removeClass'\n                           || animationEvent == 'animate';\n\n        var currentClassName = element.attr('class');\n        var classes = currentClassName + ' ' + className;\n        if (!isAnimatableClassName(classes)) {\n          return;\n        }\n\n        var beforeComplete = noop,\n            beforeCancel = [],\n            before = [],\n            afterComplete = noop,\n            afterCancel = [],\n            after = [];\n\n        var animationLookup = (' ' + classes).replace(/\\s+/g,'.');\n        forEach(lookup(animationLookup), function(animationFactory) {\n          var created = registerAnimation(animationFactory, animationEvent);\n          if (!created && isSetClassOperation) {\n            registerAnimation(animationFactory, 'addClass');\n            registerAnimation(animationFactory, 'removeClass');\n          }\n        });\n\n        function registerAnimation(animationFactory, event) {\n          var afterFn = animationFactory[event];\n          var beforeFn = animationFactory['before' + event.charAt(0).toUpperCase() + event.substr(1)];\n          if (afterFn || beforeFn) {\n            if (event == 'leave') {\n              beforeFn = afterFn;\n              //when set as null then animation knows to skip this phase\n              afterFn = null;\n            }\n            after.push({\n              event: event, fn: afterFn\n            });\n            before.push({\n              event: event, fn: beforeFn\n            });\n            return true;\n          }\n        }\n\n        function run(fns, cancellations, allCompleteFn) {\n          var animations = [];\n          forEach(fns, function(animation) {\n            animation.fn && animations.push(animation);\n          });\n\n          var count = 0;\n          function afterAnimationComplete(index) {\n            if (cancellations) {\n              (cancellations[index] || noop)();\n              if (++count < animations.length) return;\n              cancellations = null;\n            }\n            allCompleteFn();\n          }\n\n          //The code below adds directly to the array in order to work with\n          //both sync and async animations. Sync animations are when the done()\n          //operation is called right away. DO NOT REFACTOR!\n          forEach(animations, function(animation, index) {\n            var progress = function() {\n              afterAnimationComplete(index);\n            };\n            switch (animation.event) {\n              case 'setClass':\n                cancellations.push(animation.fn(element, classNameAdd, classNameRemove, progress, options));\n                break;\n              case 'animate':\n                cancellations.push(animation.fn(element, className, options.from, options.to, progress));\n                break;\n              case 'addClass':\n                cancellations.push(animation.fn(element, classNameAdd || className,     progress, options));\n                break;\n              case 'removeClass':\n                cancellations.push(animation.fn(element, classNameRemove || className,  progress, options));\n                break;\n              default:\n                cancellations.push(animation.fn(element, progress, options));\n                break;\n            }\n          });\n\n          if (cancellations && cancellations.length === 0) {\n            allCompleteFn();\n          }\n        }\n\n        return {\n          node: node,\n          event: animationEvent,\n          className: className,\n          isClassBased: isClassBased,\n          isSetClassOperation: isSetClassOperation,\n          applyStyles: function() {\n            if (options) {\n              element.css(angular.extend(options.from || {}, options.to || {}));\n            }\n          },\n          before: function(allCompleteFn) {\n            beforeComplete = allCompleteFn;\n            run(before, beforeCancel, function() {\n              beforeComplete = noop;\n              allCompleteFn();\n            });\n          },\n          after: function(allCompleteFn) {\n            afterComplete = allCompleteFn;\n            run(after, afterCancel, function() {\n              afterComplete = noop;\n              allCompleteFn();\n            });\n          },\n          cancel: function() {\n            if (beforeCancel) {\n              forEach(beforeCancel, function(cancelFn) {\n                (cancelFn || noop)(true);\n              });\n              beforeComplete(true);\n            }\n            if (afterCancel) {\n              forEach(afterCancel, function(cancelFn) {\n                (cancelFn || noop)(true);\n              });\n              afterComplete(true);\n            }\n          }\n        };\n      }\n\n      /**\n       * @ngdoc service\n       * @name $animate\n       * @kind object\n       *\n       * @description\n       * The `$animate` service provides animation detection support while performing DOM operations (enter, leave and move) as well as during addClass and removeClass operations.\n       * When any of these operations are run, the $animate service\n       * will examine any JavaScript-defined animations (which are defined by using the $animateProvider provider object)\n       * as well as any CSS-defined animations against the CSS classes present on the element once the DOM operation is run.\n       *\n       * The `$animate` service is used behind the scenes with pre-existing directives and animation with these directives\n       * will work out of the box without any extra configuration.\n       *\n       * Requires the {@link ngAnimate `ngAnimate`} module to be installed.\n       *\n       * Please visit the {@link ngAnimate `ngAnimate`} module overview page learn more about how to use animations in your application.\n       * ## Callback Promises\n       * With AngularJS 1.3, each of the animation methods, on the `$animate` service, return a promise when called. The\n       * promise itself is then resolved once the animation has completed itself, has been cancelled or has been\n       * skipped due to animations being disabled. (Note that even if the animation is cancelled it will still\n       * call the resolve function of the animation.)\n       *\n       * ```js\n       * $animate.enter(element, container).then(function() {\n       *   //...this is called once the animation is complete...\n       * });\n       * ```\n       *\n       * Also note that, due to the nature of the callback promise, if any Angular-specific code (like changing the scope,\n       * location of the page, etc...) is executed within the callback promise then be sure to wrap the code using\n       * `$scope.$apply(...)`;\n       *\n       * ```js\n       * $animate.leave(element).then(function() {\n       *   $scope.$apply(function() {\n       *     $location.path('/new-page');\n       *   });\n       * });\n       * ```\n       *\n       * An animation can also be cancelled by calling the `$animate.cancel(promise)` method with the provided\n       * promise that was returned when the animation was started.\n       *\n       * ```js\n       * var promise = $animate.addClass(element, 'super-long-animation');\n       * promise.then(function() {\n       *   //this will still be called even if cancelled\n       * });\n       *\n       * element.on('click', function() {\n       *   //tooo lazy to wait for the animation to end\n       *   $animate.cancel(promise);\n       * });\n       * ```\n       *\n       * (Keep in mind that the promise cancellation is unique to `$animate` since promises in\n       * general cannot be cancelled.)\n       *\n       */\n      return {\n        /**\n         * @ngdoc method\n         * @name $animate#animate\n         * @kind function\n         *\n         * @description\n         * Performs an inline animation on the element which applies the provided `to` and `from` CSS styles to the element.\n         * If any detected CSS transition, keyframe or JavaScript matches the provided `className` value then the animation\n         * will take on the provided styles. For example, if a transition animation is set for the given className then the\n         * provided `from` and `to` styles will be applied alongside the given transition. If a JavaScript animation is\n         * detected then the provided styles will be given in as function paramters.\n         *\n         * ```js\n         * ngModule.animation('.my-inline-animation', function() {\n         *   return {\n         *     animate : function(element, className, from, to, done) {\n         *       //styles\n         *     }\n         *   }\n         * });\n         * ```\n         *\n         * Below is a breakdown of each step that occurs during the `animate` animation:\n         *\n         * | Animation Step                                                                                                        | What the element class attribute looks like                  |\n         * |-----------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------|\n         * | 1. `$animate.animate(...)` is called                                                                                  | `class=\"my-animation\"`                                       |\n         * | 2. `$animate` waits for the next digest to start the animation                                                        | `class=\"my-animation ng-animate\"`                            |\n         * | 3. `$animate` runs the JavaScript-defined animations detected on the element                                          | `class=\"my-animation ng-animate\"`                            |\n         * | 4. the `className` class value is added to the element                                                                | `class=\"my-animation ng-animate className\"`                  |\n         * | 5. `$animate` scans the element styles to get the CSS transition/animation duration and delay                         | `class=\"my-animation ng-animate className\"`                  |\n         * | 6. `$animate` blocks all CSS transitions on the element to ensure the `.className` class styling is applied right away| `class=\"my-animation ng-animate className\"`                  |\n         * | 7. `$animate` applies the provided collection of `from` CSS styles to the element                                     | `class=\"my-animation ng-animate className\"`                  |\n         * | 8. `$animate` waits for a single animation frame (this performs a reflow)                                             | `class=\"my-animation ng-animate className\"`                  |\n         * | 9. `$animate` removes the CSS transition block placed on the element                                                  | `class=\"my-animation ng-animate className\"`                  |\n         * | 10. the `className-active` class is added (this triggers the CSS transition/animation)                                | `class=\"my-animation ng-animate className className-active\"` |\n         * | 11. `$animate` applies the collection of `to` CSS styles to the element which are then handled by the transition      | `class=\"my-animation ng-animate className className-active\"` |\n         * | 12. `$animate` waits for the animation to complete (via events and timeout)                                           | `class=\"my-animation ng-animate className className-active\"` |\n         * | 13. The animation ends and all generated CSS classes are removed from the element                                     | `class=\"my-animation\"`                                       |\n         * | 14. The returned promise is resolved.                                                                                 | `class=\"my-animation\"`                                       |\n         *\n         * @param {DOMElement} element the element that will be the focus of the enter animation\n         * @param {object} from a collection of CSS styles that will be applied to the element at the start of the animation\n         * @param {object} to a collection of CSS styles that the element will animate towards\n         * @param {string=} className an optional CSS class that will be added to the element for the duration of the animation (the default class is `ng-inline-animate`)\n         * @param {object=} options an optional collection of options that will be picked up by the CSS transition/animation\n         * @return {Promise} the animation callback promise\n        */\n        animate: function(element, from, to, className, options) {\n          className = className || 'ng-inline-animate';\n          options = parseAnimateOptions(options) || {};\n          options.from = to ? from : null;\n          options.to   = to ? to : from;\n\n          return runAnimationPostDigest(function(done) {\n            return performAnimation('animate', className, stripCommentsFromElement(element), null, null, noop, options, done);\n          });\n        },\n\n        /**\n         * @ngdoc method\n         * @name $animate#enter\n         * @kind function\n         *\n         * @description\n         * Appends the element to the parentElement element that resides in the document and then runs the enter animation. Once\n         * the animation is started, the following CSS classes will be present on the element for the duration of the animation:\n         *\n         * Below is a breakdown of each step that occurs during enter animation:\n         *\n         * | Animation Step                                                                                                        | What the element class attribute looks like                |\n         * |-----------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------|\n         * | 1. `$animate.enter(...)` is called                                                                                    | `class=\"my-animation\"`                                     |\n         * | 2. element is inserted into the `parentElement` element or beside the `afterElement` element                          | `class=\"my-animation\"`                                     |\n         * | 3. `$animate` waits for the next digest to start the animation                                                        | `class=\"my-animation ng-animate\"`                          |\n         * | 4. `$animate` runs the JavaScript-defined animations detected on the element                                          | `class=\"my-animation ng-animate\"`                          |\n         * | 5. the `.ng-enter` class is added to the element                                                                      | `class=\"my-animation ng-animate ng-enter\"`                 |\n         * | 6. `$animate` scans the element styles to get the CSS transition/animation duration and delay                         | `class=\"my-animation ng-animate ng-enter\"`                 |\n         * | 7. `$animate` blocks all CSS transitions on the element to ensure the `.ng-enter` class styling is applied right away | `class=\"my-animation ng-animate ng-enter\"`                 |\n         * | 8. `$animate` waits for a single animation frame (this performs a reflow)                                             | `class=\"my-animation ng-animate ng-enter\"`                 |\n         * | 9. `$animate` removes the CSS transition block placed on the element                                                  | `class=\"my-animation ng-animate ng-enter\"`                 |\n         * | 10. the `.ng-enter-active` class is added (this triggers the CSS transition/animation)                                | `class=\"my-animation ng-animate ng-enter ng-enter-active\"` |\n         * | 11. `$animate` waits for the animation to complete (via events and timeout)                                           | `class=\"my-animation ng-animate ng-enter ng-enter-active\"` |\n         * | 12. The animation ends and all generated CSS classes are removed from the element                                     | `class=\"my-animation\"`                                     |\n         * | 13. The returned promise is resolved.                                                                                 | `class=\"my-animation\"`                                     |\n         *\n         * @param {DOMElement} element the element that will be the focus of the enter animation\n         * @param {DOMElement} parentElement the parent element of the element that will be the focus of the enter animation\n         * @param {DOMElement} afterElement the sibling element (which is the previous element) of the element that will be the focus of the enter animation\n         * @param {object=} options an optional collection of options that will be picked up by the CSS transition/animation\n         * @return {Promise} the animation callback promise\n        */\n        enter: function(element, parentElement, afterElement, options) {\n          options = parseAnimateOptions(options);\n          element = angular.element(element);\n          parentElement = prepareElement(parentElement);\n          afterElement = prepareElement(afterElement);\n\n          classBasedAnimationsBlocked(element, true);\n          $delegate.enter(element, parentElement, afterElement);\n          return runAnimationPostDigest(function(done) {\n            return performAnimation('enter', 'ng-enter', stripCommentsFromElement(element), parentElement, afterElement, noop, options, done);\n          });\n        },\n\n        /**\n         * @ngdoc method\n         * @name $animate#leave\n         * @kind function\n         *\n         * @description\n         * Runs the leave animation operation and, upon completion, removes the element from the DOM. Once\n         * the animation is started, the following CSS classes will be added for the duration of the animation:\n         *\n         * Below is a breakdown of each step that occurs during leave animation:\n         *\n         * | Animation Step                                                                                                        | What the element class attribute looks like                |\n         * |-----------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------|\n         * | 1. `$animate.leave(...)` is called                                                                                    | `class=\"my-animation\"`                                     |\n         * | 2. `$animate` runs the JavaScript-defined animations detected on the element                                          | `class=\"my-animation ng-animate\"`                          |\n         * | 3. `$animate` waits for the next digest to start the animation                                                        | `class=\"my-animation ng-animate\"`                          |\n         * | 4. the `.ng-leave` class is added to the element                                                                      | `class=\"my-animation ng-animate ng-leave\"`                 |\n         * | 5. `$animate` scans the element styles to get the CSS transition/animation duration and delay                         | `class=\"my-animation ng-animate ng-leave\"`                 |\n         * | 6. `$animate` blocks all CSS transitions on the element to ensure the `.ng-leave` class styling is applied right away | `class=\"my-animation ng-animate ng-leave\"`                 |\n         * | 7. `$animate` waits for a single animation frame (this performs a reflow)                                             | `class=\"my-animation ng-animate ng-leave\"`                 |\n         * | 8. `$animate` removes the CSS transition block placed on the element                                                  | `class=\"my-animation ng-animate ng-leave\"`                 |\n         * | 9. the `.ng-leave-active` class is added (this triggers the CSS transition/animation)                                 | `class=\"my-animation ng-animate ng-leave ng-leave-active\"` |\n         * | 10. `$animate` waits for the animation to complete (via events and timeout)                                           | `class=\"my-animation ng-animate ng-leave ng-leave-active\"` |\n         * | 11. The animation ends and all generated CSS classes are removed from the element                                     | `class=\"my-animation\"`                                     |\n         * | 12. The element is removed from the DOM                                                                               | ...                                                        |\n         * | 13. The returned promise is resolved.                                                                                 | ...                                                        |\n         *\n         * @param {DOMElement} element the element that will be the focus of the leave animation\n         * @param {object=} options an optional collection of styles that will be picked up by the CSS transition/animation\n         * @return {Promise} the animation callback promise\n        */\n        leave: function(element, options) {\n          options = parseAnimateOptions(options);\n          element = angular.element(element);\n\n          cancelChildAnimations(element);\n          classBasedAnimationsBlocked(element, true);\n          return runAnimationPostDigest(function(done) {\n            return performAnimation('leave', 'ng-leave', stripCommentsFromElement(element), null, null, function() {\n              $delegate.leave(element);\n            }, options, done);\n          });\n        },\n\n        /**\n         * @ngdoc method\n         * @name $animate#move\n         * @kind function\n         *\n         * @description\n         * Fires the move DOM operation. Just before the animation starts, the animate service will either append it into the parentElement container or\n         * add the element directly after the afterElement element if present. Then the move animation will be run. Once\n         * the animation is started, the following CSS classes will be added for the duration of the animation:\n         *\n         * Below is a breakdown of each step that occurs during move animation:\n         *\n         * | Animation Step                                                                                                       | What the element class attribute looks like              |\n         * |----------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------|\n         * | 1. `$animate.move(...)` is called                                                                                    | `class=\"my-animation\"`                                   |\n         * | 2. element is moved into the parentElement element or beside the afterElement element                                | `class=\"my-animation\"`                                   |\n         * | 3. `$animate` waits for the next digest to start the animation                                                       | `class=\"my-animation ng-animate\"`                        |\n         * | 4. `$animate` runs the JavaScript-defined animations detected on the element                                         | `class=\"my-animation ng-animate\"`                        |\n         * | 5. the `.ng-move` class is added to the element                                                                      | `class=\"my-animation ng-animate ng-move\"`                |\n         * | 6. `$animate` scans the element styles to get the CSS transition/animation duration and delay                        | `class=\"my-animation ng-animate ng-move\"`                |\n         * | 7. `$animate` blocks all CSS transitions on the element to ensure the `.ng-move` class styling is applied right away | `class=\"my-animation ng-animate ng-move\"`                |\n         * | 8. `$animate` waits for a single animation frame (this performs a reflow)                                            | `class=\"my-animation ng-animate ng-move\"`                |\n         * | 9. `$animate` removes the CSS transition block placed on the element                                                 | `class=\"my-animation ng-animate ng-move\"`                |\n         * | 10. the `.ng-move-active` class is added (this triggers the CSS transition/animation)                                | `class=\"my-animation ng-animate ng-move ng-move-active\"` |\n         * | 11. `$animate` waits for the animation to complete (via events and timeout)                                          | `class=\"my-animation ng-animate ng-move ng-move-active\"` |\n         * | 12. The animation ends and all generated CSS classes are removed from the element                                    | `class=\"my-animation\"`                                   |\n         * | 13. The returned promise is resolved.                                                                                | `class=\"my-animation\"`                                   |\n         *\n         * @param {DOMElement} element the element that will be the focus of the move animation\n         * @param {DOMElement} parentElement the parentElement element of the element that will be the focus of the move animation\n         * @param {DOMElement} afterElement the sibling element (which is the previous element) of the element that will be the focus of the move animation\n         * @param {object=} options an optional collection of styles that will be picked up by the CSS transition/animation\n         * @return {Promise} the animation callback promise\n        */\n        move: function(element, parentElement, afterElement, options) {\n          options = parseAnimateOptions(options);\n          element = angular.element(element);\n          parentElement = prepareElement(parentElement);\n          afterElement = prepareElement(afterElement);\n\n          cancelChildAnimations(element);\n          classBasedAnimationsBlocked(element, true);\n          $delegate.move(element, parentElement, afterElement);\n          return runAnimationPostDigest(function(done) {\n            return performAnimation('move', 'ng-move', stripCommentsFromElement(element), parentElement, afterElement, noop, options, done);\n          });\n        },\n\n        /**\n         * @ngdoc method\n         * @name $animate#addClass\n         *\n         * @description\n         * Triggers a custom animation event based off the className variable and then attaches the className value to the element as a CSS class.\n         * Unlike the other animation methods, the animate service will suffix the className value with {@type -add} in order to provide\n         * the animate service the setup and active CSS classes in order to trigger the animation (this will be skipped if no CSS transitions\n         * or keyframes are defined on the -add-active or base CSS class).\n         *\n         * Below is a breakdown of each step that occurs during addClass animation:\n         *\n         * | Animation Step                                                                                         | What the element class attribute looks like                        |\n         * |--------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------|\n         * | 1. `$animate.addClass(element, 'super')` is called                                                     | `class=\"my-animation\"`                                             |\n         * | 2. `$animate` runs the JavaScript-defined animations detected on the element                           | `class=\"my-animation ng-animate\"`                                  |\n         * | 3. the `.super-add` class is added to the element                                                      | `class=\"my-animation ng-animate super-add\"`                        |\n         * | 4. `$animate` waits for a single animation frame (this performs a reflow)                              | `class=\"my-animation ng-animate super-add\"`                        |\n         * | 5. the `.super` and `.super-add-active` classes are added (this triggers the CSS transition/animation) | `class=\"my-animation ng-animate super super-add super-add-active\"` |\n         * | 6. `$animate` scans the element styles to get the CSS transition/animation duration and delay          | `class=\"my-animation ng-animate super super-add super-add-active\"` |\n         * | 7. `$animate` waits for the animation to complete (via events and timeout)                             | `class=\"my-animation ng-animate super super-add super-add-active\"` |\n         * | 8. The animation ends and all generated CSS classes are removed from the element                       | `class=\"my-animation super\"`                                       |\n         * | 9. The super class is kept on the element                                                              | `class=\"my-animation super\"`                                       |\n         * | 10. The returned promise is resolved.                                                                  | `class=\"my-animation super\"`                                       |\n         *\n         * @param {DOMElement} element the element that will be animated\n         * @param {string} className the CSS class that will be added to the element and then animated\n         * @param {object=} options an optional collection of styles that will be picked up by the CSS transition/animation\n         * @return {Promise} the animation callback promise\n        */\n        addClass: function(element, className, options) {\n          return this.setClass(element, className, [], options);\n        },\n\n        /**\n         * @ngdoc method\n         * @name $animate#removeClass\n         *\n         * @description\n         * Triggers a custom animation event based off the className variable and then removes the CSS class provided by the className value\n         * from the element. Unlike the other animation methods, the animate service will suffix the className value with {@type -remove} in\n         * order to provide the animate service the setup and active CSS classes in order to trigger the animation (this will be skipped if\n         * no CSS transitions or keyframes are defined on the -remove or base CSS classes).\n         *\n         * Below is a breakdown of each step that occurs during removeClass animation:\n         *\n         * | Animation Step                                                                                                       | What the element class attribute looks like                        |\n         * |----------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------|\n         * | 1. `$animate.removeClass(element, 'super')` is called                                                                | `class=\"my-animation super\"`                                       |\n         * | 2. `$animate` runs the JavaScript-defined animations detected on the element                                         | `class=\"my-animation super ng-animate\"`                            |\n         * | 3. the `.super-remove` class is added to the element                                                                 | `class=\"my-animation super ng-animate super-remove\"`               |\n         * | 4. `$animate` waits for a single animation frame (this performs a reflow)                                            | `class=\"my-animation super ng-animate super-remove\"`               |\n         * | 5. the `.super-remove-active` classes are added and `.super` is removed (this triggers the CSS transition/animation) | `class=\"my-animation ng-animate super-remove super-remove-active\"` |\n         * | 6. `$animate` scans the element styles to get the CSS transition/animation duration and delay                        | `class=\"my-animation ng-animate super-remove super-remove-active\"` |\n         * | 7. `$animate` waits for the animation to complete (via events and timeout)                                           | `class=\"my-animation ng-animate super-remove super-remove-active\"` |\n         * | 8. The animation ends and all generated CSS classes are removed from the element                                     | `class=\"my-animation\"`                                             |\n         * | 9. The returned promise is resolved.                                                                                 | `class=\"my-animation\"`                                             |\n         *\n         *\n         * @param {DOMElement} element the element that will be animated\n         * @param {string} className the CSS class that will be animated and then removed from the element\n         * @param {object=} options an optional collection of styles that will be picked up by the CSS transition/animation\n         * @return {Promise} the animation callback promise\n        */\n        removeClass: function(element, className, options) {\n          return this.setClass(element, [], className, options);\n        },\n\n        /**\n         *\n         * @ngdoc method\n         * @name $animate#setClass\n         *\n         * @description Adds and/or removes the given CSS classes to and from the element.\n         * Once complete, the `done()` callback will be fired (if provided).\n         *\n         * | Animation Step                                                                                                                               | What the element class attribute looks like                                            |\n         * |----------------------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------|\n         * | 1. `$animate.setClass(element, 'on', 'off')` is called                                                                                       | `class=\"my-animation off\"`                                                             |\n         * | 2. `$animate` runs the JavaScript-defined animations detected on the element                                                                 | `class=\"my-animation ng-animate off\"`                                                  |\n         * | 3. the `.on-add` and `.off-remove` classes are added to the element                                                                          | `class=\"my-animation ng-animate on-add off-remove off\"`                                |\n         * | 4. `$animate` waits for a single animation frame (this performs a reflow)                                                                    | `class=\"my-animation ng-animate on-add off-remove off\"`                                |\n         * | 5. the `.on`, `.on-add-active` and `.off-remove-active` classes are added and `.off` is removed (this triggers the CSS transition/animation) | `class=\"my-animation ng-animate on on-add on-add-active off-remove off-remove-active\"` |\n         * | 6. `$animate` scans the element styles to get the CSS transition/animation duration and delay                                                | `class=\"my-animation ng-animate on on-add on-add-active off-remove off-remove-active\"` |\n         * | 7. `$animate` waits for the animation to complete (via events and timeout)                                                                   | `class=\"my-animation ng-animate on on-add on-add-active off-remove off-remove-active\"` |\n         * | 8. The animation ends and all generated CSS classes are removed from the element                                                             | `class=\"my-animation on\"`                                                              |\n         * | 9. The returned promise is resolved.                                                                                                         | `class=\"my-animation on\"`                                                              |\n         *\n         * @param {DOMElement} element the element which will have its CSS classes changed\n         *   removed from it\n         * @param {string} add the CSS classes which will be added to the element\n         * @param {string} remove the CSS class which will be removed from the element\n         *   CSS classes have been set on the element\n         * @param {object=} options an optional collection of styles that will be picked up by the CSS transition/animation\n         * @return {Promise} the animation callback promise\n         */\n        setClass: function(element, add, remove, options) {\n          options = parseAnimateOptions(options);\n\n          var STORAGE_KEY = '$$animateClasses';\n          element = angular.element(element);\n          element = stripCommentsFromElement(element);\n\n          if (classBasedAnimationsBlocked(element)) {\n            return $delegate.$$setClassImmediately(element, add, remove, options);\n          }\n\n          // we're using a combined array for both the add and remove\n          // operations since the ORDER OF addClass and removeClass matters\n          var classes, cache = element.data(STORAGE_KEY);\n          var hasCache = !!cache;\n          if (!cache) {\n            cache = {};\n            cache.classes = {};\n          }\n          classes = cache.classes;\n\n          add = isArray(add) ? add : add.split(' ');\n          forEach(add, function(c) {\n            if (c && c.length) {\n              classes[c] = true;\n            }\n          });\n\n          remove = isArray(remove) ? remove : remove.split(' ');\n          forEach(remove, function(c) {\n            if (c && c.length) {\n              classes[c] = false;\n            }\n          });\n\n          if (hasCache) {\n            if (options && cache.options) {\n              cache.options = angular.extend(cache.options || {}, options);\n            }\n\n            //the digest cycle will combine all the animations into one function\n            return cache.promise;\n          } else {\n            element.data(STORAGE_KEY, cache = {\n              classes: classes,\n              options: options\n            });\n          }\n\n          return cache.promise = runAnimationPostDigest(function(done) {\n            var parentElement = element.parent();\n            var elementNode = extractElementNode(element);\n            var parentNode = elementNode.parentNode;\n            // TODO(matsko): move this code into the animationsDisabled() function once #8092 is fixed\n            if (!parentNode || parentNode['$$NG_REMOVED'] || elementNode['$$NG_REMOVED']) {\n              done();\n              return;\n            }\n\n            var cache = element.data(STORAGE_KEY);\n            element.removeData(STORAGE_KEY);\n\n            var state = element.data(NG_ANIMATE_STATE) || {};\n            var classes = resolveElementClasses(element, cache, state.active);\n            return !classes\n              ? done()\n              : performAnimation('setClass', classes, element, parentElement, null, function() {\n                  if (classes[0]) $delegate.$$addClassImmediately(element, classes[0]);\n                  if (classes[1]) $delegate.$$removeClassImmediately(element, classes[1]);\n                }, cache.options, done);\n          });\n        },\n\n        /**\n         * @ngdoc method\n         * @name $animate#cancel\n         * @kind function\n         *\n         * @param {Promise} animationPromise The animation promise that is returned when an animation is started.\n         *\n         * @description\n         * Cancels the provided animation.\n        */\n        cancel: function(promise) {\n          promise.$$cancelFn();\n        },\n\n        /**\n         * @ngdoc method\n         * @name $animate#enabled\n         * @kind function\n         *\n         * @param {boolean=} value If provided then set the animation on or off.\n         * @param {DOMElement=} element If provided then the element will be used to represent the enable/disable operation\n         * @return {boolean} Current animation state.\n         *\n         * @description\n         * Globally enables/disables animations.\n         *\n        */\n        enabled: function(value, element) {\n          switch (arguments.length) {\n            case 2:\n              if (value) {\n                cleanup(element);\n              } else {\n                var data = element.data(NG_ANIMATE_STATE) || {};\n                data.disabled = true;\n                element.data(NG_ANIMATE_STATE, data);\n              }\n            break;\n\n            case 1:\n              rootAnimateState.disabled = !value;\n            break;\n\n            default:\n              value = !rootAnimateState.disabled;\n            break;\n          }\n          return !!value;\n         }\n      };\n\n      /*\n        all animations call this shared animation triggering function internally.\n        The animationEvent variable refers to the JavaScript animation event that will be triggered\n        and the className value is the name of the animation that will be applied within the\n        CSS code. Element, `parentElement` and `afterElement` are provided DOM elements for the animation\n        and the onComplete callback will be fired once the animation is fully complete.\n      */\n      function performAnimation(animationEvent, className, element, parentElement, afterElement, domOperation, options, doneCallback) {\n        var noopCancel = noop;\n        var runner = animationRunner(element, animationEvent, className, options);\n        if (!runner) {\n          fireDOMOperation();\n          fireBeforeCallbackAsync();\n          fireAfterCallbackAsync();\n          closeAnimation();\n          return noopCancel;\n        }\n\n        animationEvent = runner.event;\n        className = runner.className;\n        var elementEvents = angular.element._data(runner.node);\n        elementEvents = elementEvents && elementEvents.events;\n\n        if (!parentElement) {\n          parentElement = afterElement ? afterElement.parent() : element.parent();\n        }\n\n        //skip the animation if animations are disabled, a parent is already being animated,\n        //the element is not currently attached to the document body or then completely close\n        //the animation if any matching animations are not found at all.\n        //NOTE: IE8 + IE9 should close properly (run closeAnimation()) in case an animation was found.\n        if (animationsDisabled(element, parentElement)) {\n          fireDOMOperation();\n          fireBeforeCallbackAsync();\n          fireAfterCallbackAsync();\n          closeAnimation();\n          return noopCancel;\n        }\n\n        var ngAnimateState  = element.data(NG_ANIMATE_STATE) || {};\n        var runningAnimations     = ngAnimateState.active || {};\n        var totalActiveAnimations = ngAnimateState.totalActive || 0;\n        var lastAnimation         = ngAnimateState.last;\n        var skipAnimation = false;\n\n        if (totalActiveAnimations > 0) {\n          var animationsToCancel = [];\n          if (!runner.isClassBased) {\n            if (animationEvent == 'leave' && runningAnimations['ng-leave']) {\n              skipAnimation = true;\n            } else {\n              //cancel all animations when a structural animation takes place\n              for (var klass in runningAnimations) {\n                animationsToCancel.push(runningAnimations[klass]);\n              }\n              ngAnimateState = {};\n              cleanup(element, true);\n            }\n          } else if (lastAnimation.event == 'setClass') {\n            animationsToCancel.push(lastAnimation);\n            cleanup(element, className);\n          } else if (runningAnimations[className]) {\n            var current = runningAnimations[className];\n            if (current.event == animationEvent) {\n              skipAnimation = true;\n            } else {\n              animationsToCancel.push(current);\n              cleanup(element, className);\n            }\n          }\n\n          if (animationsToCancel.length > 0) {\n            forEach(animationsToCancel, function(operation) {\n              operation.cancel();\n            });\n          }\n        }\n\n        if (runner.isClassBased\n            && !runner.isSetClassOperation\n            && animationEvent != 'animate'\n            && !skipAnimation) {\n          skipAnimation = (animationEvent == 'addClass') == element.hasClass(className); //opposite of XOR\n        }\n\n        if (skipAnimation) {\n          fireDOMOperation();\n          fireBeforeCallbackAsync();\n          fireAfterCallbackAsync();\n          fireDoneCallbackAsync();\n          return noopCancel;\n        }\n\n        runningAnimations     = ngAnimateState.active || {};\n        totalActiveAnimations = ngAnimateState.totalActive || 0;\n\n        if (animationEvent == 'leave') {\n          //there's no need to ever remove the listener since the element\n          //will be removed (destroyed) after the leave animation ends or\n          //is cancelled midway\n          element.one('$destroy', function(e) {\n            var element = angular.element(this);\n            var state = element.data(NG_ANIMATE_STATE);\n            if (state) {\n              var activeLeaveAnimation = state.active['ng-leave'];\n              if (activeLeaveAnimation) {\n                activeLeaveAnimation.cancel();\n                cleanup(element, 'ng-leave');\n              }\n            }\n          });\n        }\n\n        //the ng-animate class does nothing, but it's here to allow for\n        //parent animations to find and cancel child animations when needed\n        $$jqLite.addClass(element, NG_ANIMATE_CLASS_NAME);\n        if (options && options.tempClasses) {\n          forEach(options.tempClasses, function(className) {\n            $$jqLite.addClass(element, className);\n          });\n        }\n\n        var localAnimationCount = globalAnimationCounter++;\n        totalActiveAnimations++;\n        runningAnimations[className] = runner;\n\n        element.data(NG_ANIMATE_STATE, {\n          last: runner,\n          active: runningAnimations,\n          index: localAnimationCount,\n          totalActive: totalActiveAnimations\n        });\n\n        //first we run the before animations and when all of those are complete\n        //then we perform the DOM operation and run the next set of animations\n        fireBeforeCallbackAsync();\n        runner.before(function(cancelled) {\n          var data = element.data(NG_ANIMATE_STATE);\n          cancelled = cancelled ||\n                        !data || !data.active[className] ||\n                        (runner.isClassBased && data.active[className].event != animationEvent);\n\n          fireDOMOperation();\n          if (cancelled === true) {\n            closeAnimation();\n          } else {\n            fireAfterCallbackAsync();\n            runner.after(closeAnimation);\n          }\n        });\n\n        return runner.cancel;\n\n        function fireDOMCallback(animationPhase) {\n          var eventName = '$animate:' + animationPhase;\n          if (elementEvents && elementEvents[eventName] && elementEvents[eventName].length > 0) {\n            $$asyncCallback(function() {\n              element.triggerHandler(eventName, {\n                event: animationEvent,\n                className: className\n              });\n            });\n          }\n        }\n\n        function fireBeforeCallbackAsync() {\n          fireDOMCallback('before');\n        }\n\n        function fireAfterCallbackAsync() {\n          fireDOMCallback('after');\n        }\n\n        function fireDoneCallbackAsync() {\n          fireDOMCallback('close');\n          doneCallback();\n        }\n\n        //it is less complicated to use a flag than managing and canceling\n        //timeouts containing multiple callbacks.\n        function fireDOMOperation() {\n          if (!fireDOMOperation.hasBeenRun) {\n            fireDOMOperation.hasBeenRun = true;\n            domOperation();\n          }\n        }\n\n        function closeAnimation() {\n          if (!closeAnimation.hasBeenRun) {\n            if (runner) { //the runner doesn't exist if it fails to instantiate\n              runner.applyStyles();\n            }\n\n            closeAnimation.hasBeenRun = true;\n            if (options && options.tempClasses) {\n              forEach(options.tempClasses, function(className) {\n                $$jqLite.removeClass(element, className);\n              });\n            }\n\n            var data = element.data(NG_ANIMATE_STATE);\n            if (data) {\n\n              /* only structural animations wait for reflow before removing an\n                 animation, but class-based animations don't. An example of this\n                 failing would be when a parent HTML tag has a ng-class attribute\n                 causing ALL directives below to skip animations during the digest */\n              if (runner && runner.isClassBased) {\n                cleanup(element, className);\n              } else {\n                $$asyncCallback(function() {\n                  var data = element.data(NG_ANIMATE_STATE) || {};\n                  if (localAnimationCount == data.index) {\n                    cleanup(element, className, animationEvent);\n                  }\n                });\n                element.data(NG_ANIMATE_STATE, data);\n              }\n            }\n            fireDoneCallbackAsync();\n          }\n        }\n      }\n\n      function cancelChildAnimations(element) {\n        var node = extractElementNode(element);\n        if (node) {\n          var nodes = angular.isFunction(node.getElementsByClassName) ?\n            node.getElementsByClassName(NG_ANIMATE_CLASS_NAME) :\n            node.querySelectorAll('.' + NG_ANIMATE_CLASS_NAME);\n          forEach(nodes, function(element) {\n            element = angular.element(element);\n            var data = element.data(NG_ANIMATE_STATE);\n            if (data && data.active) {\n              forEach(data.active, function(runner) {\n                runner.cancel();\n              });\n            }\n          });\n        }\n      }\n\n      function cleanup(element, className) {\n        if (isMatchingElement(element, $rootElement)) {\n          if (!rootAnimateState.disabled) {\n            rootAnimateState.running = false;\n            rootAnimateState.structural = false;\n          }\n        } else if (className) {\n          var data = element.data(NG_ANIMATE_STATE) || {};\n\n          var removeAnimations = className === true;\n          if (!removeAnimations && data.active && data.active[className]) {\n            data.totalActive--;\n            delete data.active[className];\n          }\n\n          if (removeAnimations || !data.totalActive) {\n            $$jqLite.removeClass(element, NG_ANIMATE_CLASS_NAME);\n            element.removeData(NG_ANIMATE_STATE);\n          }\n        }\n      }\n\n      function animationsDisabled(element, parentElement) {\n        if (rootAnimateState.disabled) {\n          return true;\n        }\n\n        if (isMatchingElement(element, $rootElement)) {\n          return rootAnimateState.running;\n        }\n\n        var allowChildAnimations, parentRunningAnimation, hasParent;\n        do {\n          //the element did not reach the root element which means that it\n          //is not apart of the DOM. Therefore there is no reason to do\n          //any animations on it\n          if (parentElement.length === 0) break;\n\n          var isRoot = isMatchingElement(parentElement, $rootElement);\n          var state = isRoot ? rootAnimateState : (parentElement.data(NG_ANIMATE_STATE) || {});\n          if (state.disabled) {\n            return true;\n          }\n\n          //no matter what, for an animation to work it must reach the root element\n          //this implies that the element is attached to the DOM when the animation is run\n          if (isRoot) {\n            hasParent = true;\n          }\n\n          //once a flag is found that is strictly false then everything before\n          //it will be discarded and all child animations will be restricted\n          if (allowChildAnimations !== false) {\n            var animateChildrenFlag = parentElement.data(NG_ANIMATE_CHILDREN);\n            if (angular.isDefined(animateChildrenFlag)) {\n              allowChildAnimations = animateChildrenFlag;\n            }\n          }\n\n          parentRunningAnimation = parentRunningAnimation ||\n                                   state.running ||\n                                   (state.last && !state.last.isClassBased);\n        }\n        while (parentElement = parentElement.parent());\n\n        return !hasParent || (!allowChildAnimations && parentRunningAnimation);\n      }\n    }]);\n\n    $animateProvider.register('', ['$window', '$sniffer', '$timeout', '$$animateReflow',\n                           function($window,   $sniffer,   $timeout,   $$animateReflow) {\n      // Detect proper transitionend/animationend event names.\n      var CSS_PREFIX = '', TRANSITION_PROP, TRANSITIONEND_EVENT, ANIMATION_PROP, ANIMATIONEND_EVENT;\n\n      // If unprefixed events are not supported but webkit-prefixed are, use the latter.\n      // Otherwise, just use W3C names, browsers not supporting them at all will just ignore them.\n      // Note: Chrome implements `window.onwebkitanimationend` and doesn't implement `window.onanimationend`\n      // but at the same time dispatches the `animationend` event and not `webkitAnimationEnd`.\n      // Register both events in case `window.onanimationend` is not supported because of that,\n      // do the same for `transitionend` as Safari is likely to exhibit similar behavior.\n      // Also, the only modern browser that uses vendor prefixes for transitions/keyframes is webkit\n      // therefore there is no reason to test anymore for other vendor prefixes: http://caniuse.com/#search=transition\n      if (window.ontransitionend === undefined && window.onwebkittransitionend !== undefined) {\n        CSS_PREFIX = '-webkit-';\n        TRANSITION_PROP = 'WebkitTransition';\n        TRANSITIONEND_EVENT = 'webkitTransitionEnd transitionend';\n      } else {\n        TRANSITION_PROP = 'transition';\n        TRANSITIONEND_EVENT = 'transitionend';\n      }\n\n      if (window.onanimationend === undefined && window.onwebkitanimationend !== undefined) {\n        CSS_PREFIX = '-webkit-';\n        ANIMATION_PROP = 'WebkitAnimation';\n        ANIMATIONEND_EVENT = 'webkitAnimationEnd animationend';\n      } else {\n        ANIMATION_PROP = 'animation';\n        ANIMATIONEND_EVENT = 'animationend';\n      }\n\n      var DURATION_KEY = 'Duration';\n      var PROPERTY_KEY = 'Property';\n      var DELAY_KEY = 'Delay';\n      var ANIMATION_ITERATION_COUNT_KEY = 'IterationCount';\n      var ANIMATION_PLAYSTATE_KEY = 'PlayState';\n      var NG_ANIMATE_PARENT_KEY = '$$ngAnimateKey';\n      var NG_ANIMATE_CSS_DATA_KEY = '$$ngAnimateCSS3Data';\n      var ELAPSED_TIME_MAX_DECIMAL_PLACES = 3;\n      var CLOSING_TIME_BUFFER = 1.5;\n      var ONE_SECOND = 1000;\n\n      var lookupCache = {};\n      var parentCounter = 0;\n      var animationReflowQueue = [];\n      var cancelAnimationReflow;\n      function clearCacheAfterReflow() {\n        if (!cancelAnimationReflow) {\n          cancelAnimationReflow = $$animateReflow(function() {\n            animationReflowQueue = [];\n            cancelAnimationReflow = null;\n            lookupCache = {};\n          });\n        }\n      }\n\n      function afterReflow(element, callback) {\n        if (cancelAnimationReflow) {\n          cancelAnimationReflow();\n        }\n        animationReflowQueue.push(callback);\n        cancelAnimationReflow = $$animateReflow(function() {\n          forEach(animationReflowQueue, function(fn) {\n            fn();\n          });\n\n          animationReflowQueue = [];\n          cancelAnimationReflow = null;\n          lookupCache = {};\n        });\n      }\n\n      var closingTimer = null;\n      var closingTimestamp = 0;\n      var animationElementQueue = [];\n      function animationCloseHandler(element, totalTime) {\n        var node = extractElementNode(element);\n        element = angular.element(node);\n\n        //this item will be garbage collected by the closing\n        //animation timeout\n        animationElementQueue.push(element);\n\n        //but it may not need to cancel out the existing timeout\n        //if the timestamp is less than the previous one\n        var futureTimestamp = Date.now() + totalTime;\n        if (futureTimestamp <= closingTimestamp) {\n          return;\n        }\n\n        $timeout.cancel(closingTimer);\n\n        closingTimestamp = futureTimestamp;\n        closingTimer = $timeout(function() {\n          closeAllAnimations(animationElementQueue);\n          animationElementQueue = [];\n        }, totalTime, false);\n      }\n\n      function closeAllAnimations(elements) {\n        forEach(elements, function(element) {\n          var elementData = element.data(NG_ANIMATE_CSS_DATA_KEY);\n          if (elementData) {\n            forEach(elementData.closeAnimationFns, function(fn) {\n              fn();\n            });\n          }\n        });\n      }\n\n      function getElementAnimationDetails(element, cacheKey) {\n        var data = cacheKey ? lookupCache[cacheKey] : null;\n        if (!data) {\n          var transitionDuration = 0;\n          var transitionDelay = 0;\n          var animationDuration = 0;\n          var animationDelay = 0;\n\n          //we want all the styles defined before and after\n          forEach(element, function(element) {\n            if (element.nodeType == ELEMENT_NODE) {\n              var elementStyles = $window.getComputedStyle(element) || {};\n\n              var transitionDurationStyle = elementStyles[TRANSITION_PROP + DURATION_KEY];\n              transitionDuration = Math.max(parseMaxTime(transitionDurationStyle), transitionDuration);\n\n              var transitionDelayStyle = elementStyles[TRANSITION_PROP + DELAY_KEY];\n              transitionDelay  = Math.max(parseMaxTime(transitionDelayStyle), transitionDelay);\n\n              var animationDelayStyle = elementStyles[ANIMATION_PROP + DELAY_KEY];\n              animationDelay   = Math.max(parseMaxTime(elementStyles[ANIMATION_PROP + DELAY_KEY]), animationDelay);\n\n              var aDuration  = parseMaxTime(elementStyles[ANIMATION_PROP + DURATION_KEY]);\n\n              if (aDuration > 0) {\n                aDuration *= parseInt(elementStyles[ANIMATION_PROP + ANIMATION_ITERATION_COUNT_KEY], 10) || 1;\n              }\n              animationDuration = Math.max(aDuration, animationDuration);\n            }\n          });\n          data = {\n            total: 0,\n            transitionDelay: transitionDelay,\n            transitionDuration: transitionDuration,\n            animationDelay: animationDelay,\n            animationDuration: animationDuration\n          };\n          if (cacheKey) {\n            lookupCache[cacheKey] = data;\n          }\n        }\n        return data;\n      }\n\n      function parseMaxTime(str) {\n        var maxValue = 0;\n        var values = isString(str) ?\n          str.split(/\\s*,\\s*/) :\n          [];\n        forEach(values, function(value) {\n          maxValue = Math.max(parseFloat(value) || 0, maxValue);\n        });\n        return maxValue;\n      }\n\n      function getCacheKey(element) {\n        var parentElement = element.parent();\n        var parentID = parentElement.data(NG_ANIMATE_PARENT_KEY);\n        if (!parentID) {\n          parentElement.data(NG_ANIMATE_PARENT_KEY, ++parentCounter);\n          parentID = parentCounter;\n        }\n        return parentID + '-' + extractElementNode(element).getAttribute('class');\n      }\n\n      function animateSetup(animationEvent, element, className, styles) {\n        var structural = ['ng-enter','ng-leave','ng-move'].indexOf(className) >= 0;\n\n        var cacheKey = getCacheKey(element);\n        var eventCacheKey = cacheKey + ' ' + className;\n        var itemIndex = lookupCache[eventCacheKey] ? ++lookupCache[eventCacheKey].total : 0;\n\n        var stagger = {};\n        if (itemIndex > 0) {\n          var staggerClassName = className + '-stagger';\n          var staggerCacheKey = cacheKey + ' ' + staggerClassName;\n          var applyClasses = !lookupCache[staggerCacheKey];\n\n          applyClasses && $$jqLite.addClass(element, staggerClassName);\n\n          stagger = getElementAnimationDetails(element, staggerCacheKey);\n\n          applyClasses && $$jqLite.removeClass(element, staggerClassName);\n        }\n\n        $$jqLite.addClass(element, className);\n\n        var formerData = element.data(NG_ANIMATE_CSS_DATA_KEY) || {};\n        var timings = getElementAnimationDetails(element, eventCacheKey);\n        var transitionDuration = timings.transitionDuration;\n        var animationDuration = timings.animationDuration;\n\n        if (structural && transitionDuration === 0 && animationDuration === 0) {\n          $$jqLite.removeClass(element, className);\n          return false;\n        }\n\n        var blockTransition = styles || (structural && transitionDuration > 0);\n        var blockAnimation = animationDuration > 0 &&\n                             stagger.animationDelay > 0 &&\n                             stagger.animationDuration === 0;\n\n        var closeAnimationFns = formerData.closeAnimationFns || [];\n        element.data(NG_ANIMATE_CSS_DATA_KEY, {\n          stagger: stagger,\n          cacheKey: eventCacheKey,\n          running: formerData.running || 0,\n          itemIndex: itemIndex,\n          blockTransition: blockTransition,\n          closeAnimationFns: closeAnimationFns\n        });\n\n        var node = extractElementNode(element);\n\n        if (blockTransition) {\n          blockTransitions(node, true);\n          if (styles) {\n            element.css(styles);\n          }\n        }\n\n        if (blockAnimation) {\n          blockAnimations(node, true);\n        }\n\n        return true;\n      }\n\n      function animateRun(animationEvent, element, className, activeAnimationComplete, styles) {\n        var node = extractElementNode(element);\n        var elementData = element.data(NG_ANIMATE_CSS_DATA_KEY);\n        if (node.getAttribute('class').indexOf(className) == -1 || !elementData) {\n          activeAnimationComplete();\n          return;\n        }\n\n        var activeClassName = '';\n        var pendingClassName = '';\n        forEach(className.split(' '), function(klass, i) {\n          var prefix = (i > 0 ? ' ' : '') + klass;\n          activeClassName += prefix + '-active';\n          pendingClassName += prefix + '-pending';\n        });\n\n        var style = '';\n        var appliedStyles = [];\n        var itemIndex = elementData.itemIndex;\n        var stagger = elementData.stagger;\n        var staggerTime = 0;\n        if (itemIndex > 0) {\n          var transitionStaggerDelay = 0;\n          if (stagger.transitionDelay > 0 && stagger.transitionDuration === 0) {\n            transitionStaggerDelay = stagger.transitionDelay * itemIndex;\n          }\n\n          var animationStaggerDelay = 0;\n          if (stagger.animationDelay > 0 && stagger.animationDuration === 0) {\n            animationStaggerDelay = stagger.animationDelay * itemIndex;\n            appliedStyles.push(CSS_PREFIX + 'animation-play-state');\n          }\n\n          staggerTime = Math.round(Math.max(transitionStaggerDelay, animationStaggerDelay) * 100) / 100;\n        }\n\n        if (!staggerTime) {\n          $$jqLite.addClass(element, activeClassName);\n          if (elementData.blockTransition) {\n            blockTransitions(node, false);\n          }\n        }\n\n        var eventCacheKey = elementData.cacheKey + ' ' + activeClassName;\n        var timings = getElementAnimationDetails(element, eventCacheKey);\n        var maxDuration = Math.max(timings.transitionDuration, timings.animationDuration);\n        if (maxDuration === 0) {\n          $$jqLite.removeClass(element, activeClassName);\n          animateClose(element, className);\n          activeAnimationComplete();\n          return;\n        }\n\n        if (!staggerTime && styles && Object.keys(styles).length > 0) {\n          if (!timings.transitionDuration) {\n            element.css('transition', timings.animationDuration + 's linear all');\n            appliedStyles.push('transition');\n          }\n          element.css(styles);\n        }\n\n        var maxDelay = Math.max(timings.transitionDelay, timings.animationDelay);\n        var maxDelayTime = maxDelay * ONE_SECOND;\n\n        if (appliedStyles.length > 0) {\n          //the element being animated may sometimes contain comment nodes in\n          //the jqLite object, so we're safe to use a single variable to house\n          //the styles since there is always only one element being animated\n          var oldStyle = node.getAttribute('style') || '';\n          if (oldStyle.charAt(oldStyle.length - 1) !== ';') {\n            oldStyle += ';';\n          }\n          node.setAttribute('style', oldStyle + ' ' + style);\n        }\n\n        var startTime = Date.now();\n        var css3AnimationEvents = ANIMATIONEND_EVENT + ' ' + TRANSITIONEND_EVENT;\n        var animationTime     = (maxDelay + maxDuration) * CLOSING_TIME_BUFFER;\n        var totalTime         = (staggerTime + animationTime) * ONE_SECOND;\n\n        var staggerTimeout;\n        if (staggerTime > 0) {\n          $$jqLite.addClass(element, pendingClassName);\n          staggerTimeout = $timeout(function() {\n            staggerTimeout = null;\n\n            if (timings.transitionDuration > 0) {\n              blockTransitions(node, false);\n            }\n            if (timings.animationDuration > 0) {\n              blockAnimations(node, false);\n            }\n\n            $$jqLite.addClass(element, activeClassName);\n            $$jqLite.removeClass(element, pendingClassName);\n\n            if (styles) {\n              if (timings.transitionDuration === 0) {\n                element.css('transition', timings.animationDuration + 's linear all');\n              }\n              element.css(styles);\n              appliedStyles.push('transition');\n            }\n          }, staggerTime * ONE_SECOND, false);\n        }\n\n        element.on(css3AnimationEvents, onAnimationProgress);\n        elementData.closeAnimationFns.push(function() {\n          onEnd();\n          activeAnimationComplete();\n        });\n\n        elementData.running++;\n        animationCloseHandler(element, totalTime);\n        return onEnd;\n\n        // This will automatically be called by $animate so\n        // there is no need to attach this internally to the\n        // timeout done method.\n        function onEnd() {\n          element.off(css3AnimationEvents, onAnimationProgress);\n          $$jqLite.removeClass(element, activeClassName);\n          $$jqLite.removeClass(element, pendingClassName);\n          if (staggerTimeout) {\n            $timeout.cancel(staggerTimeout);\n          }\n          animateClose(element, className);\n          var node = extractElementNode(element);\n          for (var i in appliedStyles) {\n            node.style.removeProperty(appliedStyles[i]);\n          }\n        }\n\n        function onAnimationProgress(event) {\n          event.stopPropagation();\n          var ev = event.originalEvent || event;\n          var timeStamp = ev.$manualTimeStamp || ev.timeStamp || Date.now();\n\n          /* Firefox (or possibly just Gecko) likes to not round values up\n           * when a ms measurement is used for the animation */\n          var elapsedTime = parseFloat(ev.elapsedTime.toFixed(ELAPSED_TIME_MAX_DECIMAL_PLACES));\n\n          /* $manualTimeStamp is a mocked timeStamp value which is set\n           * within browserTrigger(). This is only here so that tests can\n           * mock animations properly. Real events fallback to event.timeStamp,\n           * or, if they don't, then a timeStamp is automatically created for them.\n           * We're checking to see if the timeStamp surpasses the expected delay,\n           * but we're using elapsedTime instead of the timeStamp on the 2nd\n           * pre-condition since animations sometimes close off early */\n          if (Math.max(timeStamp - startTime, 0) >= maxDelayTime && elapsedTime >= maxDuration) {\n            activeAnimationComplete();\n          }\n        }\n      }\n\n      function blockTransitions(node, bool) {\n        node.style[TRANSITION_PROP + PROPERTY_KEY] = bool ? 'none' : '';\n      }\n\n      function blockAnimations(node, bool) {\n        node.style[ANIMATION_PROP + ANIMATION_PLAYSTATE_KEY] = bool ? 'paused' : '';\n      }\n\n      function animateBefore(animationEvent, element, className, styles) {\n        if (animateSetup(animationEvent, element, className, styles)) {\n          return function(cancelled) {\n            cancelled && animateClose(element, className);\n          };\n        }\n      }\n\n      function animateAfter(animationEvent, element, className, afterAnimationComplete, styles) {\n        if (element.data(NG_ANIMATE_CSS_DATA_KEY)) {\n          return animateRun(animationEvent, element, className, afterAnimationComplete, styles);\n        } else {\n          animateClose(element, className);\n          afterAnimationComplete();\n        }\n      }\n\n      function animate(animationEvent, element, className, animationComplete, options) {\n        //If the animateSetup function doesn't bother returning a\n        //cancellation function then it means that there is no animation\n        //to perform at all\n        var preReflowCancellation = animateBefore(animationEvent, element, className, options.from);\n        if (!preReflowCancellation) {\n          clearCacheAfterReflow();\n          animationComplete();\n          return;\n        }\n\n        //There are two cancellation functions: one is before the first\n        //reflow animation and the second is during the active state\n        //animation. The first function will take care of removing the\n        //data from the element which will not make the 2nd animation\n        //happen in the first place\n        var cancel = preReflowCancellation;\n        afterReflow(element, function() {\n          //once the reflow is complete then we point cancel to\n          //the new cancellation function which will remove all of the\n          //animation properties from the active animation\n          cancel = animateAfter(animationEvent, element, className, animationComplete, options.to);\n        });\n\n        return function(cancelled) {\n          (cancel || noop)(cancelled);\n        };\n      }\n\n      function animateClose(element, className) {\n        $$jqLite.removeClass(element, className);\n        var data = element.data(NG_ANIMATE_CSS_DATA_KEY);\n        if (data) {\n          if (data.running) {\n            data.running--;\n          }\n          if (!data.running || data.running === 0) {\n            element.removeData(NG_ANIMATE_CSS_DATA_KEY);\n          }\n        }\n      }\n\n      return {\n        animate: function(element, className, from, to, animationCompleted, options) {\n          options = options || {};\n          options.from = from;\n          options.to = to;\n          return animate('animate', element, className, animationCompleted, options);\n        },\n\n        enter: function(element, animationCompleted, options) {\n          options = options || {};\n          return animate('enter', element, 'ng-enter', animationCompleted, options);\n        },\n\n        leave: function(element, animationCompleted, options) {\n          options = options || {};\n          return animate('leave', element, 'ng-leave', animationCompleted, options);\n        },\n\n        move: function(element, animationCompleted, options) {\n          options = options || {};\n          return animate('move', element, 'ng-move', animationCompleted, options);\n        },\n\n        beforeSetClass: function(element, add, remove, animationCompleted, options) {\n          options = options || {};\n          var className = suffixClasses(remove, '-remove') + ' ' +\n                          suffixClasses(add, '-add');\n          var cancellationMethod = animateBefore('setClass', element, className, options.from);\n          if (cancellationMethod) {\n            afterReflow(element, animationCompleted);\n            return cancellationMethod;\n          }\n          clearCacheAfterReflow();\n          animationCompleted();\n        },\n\n        beforeAddClass: function(element, className, animationCompleted, options) {\n          options = options || {};\n          var cancellationMethod = animateBefore('addClass', element, suffixClasses(className, '-add'), options.from);\n          if (cancellationMethod) {\n            afterReflow(element, animationCompleted);\n            return cancellationMethod;\n          }\n          clearCacheAfterReflow();\n          animationCompleted();\n        },\n\n        beforeRemoveClass: function(element, className, animationCompleted, options) {\n          options = options || {};\n          var cancellationMethod = animateBefore('removeClass', element, suffixClasses(className, '-remove'), options.from);\n          if (cancellationMethod) {\n            afterReflow(element, animationCompleted);\n            return cancellationMethod;\n          }\n          clearCacheAfterReflow();\n          animationCompleted();\n        },\n\n        setClass: function(element, add, remove, animationCompleted, options) {\n          options = options || {};\n          remove = suffixClasses(remove, '-remove');\n          add = suffixClasses(add, '-add');\n          var className = remove + ' ' + add;\n          return animateAfter('setClass', element, className, animationCompleted, options.to);\n        },\n\n        addClass: function(element, className, animationCompleted, options) {\n          options = options || {};\n          return animateAfter('addClass', element, suffixClasses(className, '-add'), animationCompleted, options.to);\n        },\n\n        removeClass: function(element, className, animationCompleted, options) {\n          options = options || {};\n          return animateAfter('removeClass', element, suffixClasses(className, '-remove'), animationCompleted, options.to);\n        }\n      };\n\n      function suffixClasses(classes, suffix) {\n        var className = '';\n        classes = isArray(classes) ? classes : classes.split(/\\s+/);\n        forEach(classes, function(klass, i) {\n          if (klass && klass.length > 0) {\n            className += (i > 0 ? ' ' : '') + klass + suffix;\n          }\n        });\n        return className;\n      }\n    }]);\n  }]);\n\n\n})(window, window.angular);\n"
  },
  {
    "path": "flowable-ui-web/task/libs/angular-cookies_1.3.13/angular-cookies.js",
    "content": "/**\n * @license AngularJS v1.3.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 module\n * @name ngCookies\n * @description\n *\n * # ngCookies\n *\n * The `ngCookies` module provides a convenient wrapper for reading and writing browser cookies.\n *\n *\n * <div doc-module-components=\"ngCookies\"></div>\n *\n * See {@link ngCookies.$cookies `$cookies`} and\n * {@link ngCookies.$cookieStore `$cookieStore`} for usage.\n */\n\n\nangular.module('ngCookies', ['ng']).\n  /**\n   * @ngdoc service\n   * @name $cookies\n   *\n   * @description\n   * Provides read/write access to browser's cookies.\n   *\n   * Only a simple Object is exposed and by adding or removing properties to/from this object, new\n   * cookies are created/deleted at the end of current $eval.\n   * The object's properties can only be strings.\n   *\n   * Requires the {@link ngCookies `ngCookies`} module to be installed.\n   *\n   * @example\n   *\n   * ```js\n   * angular.module('cookiesExample', ['ngCookies'])\n   *   .controller('ExampleController', ['$cookies', function($cookies) {\n   *     // Retrieving a cookie\n   *     var favoriteCookie = $cookies.myFavorite;\n   *     // Setting a cookie\n   *     $cookies.myFavorite = 'oatmeal';\n   *   }]);\n   * ```\n   */\n   factory('$cookies', ['$rootScope', '$browser', function($rootScope, $browser) {\n      var cookies = {},\n          lastCookies = {},\n          lastBrowserCookies,\n          runEval = false,\n          copy = angular.copy,\n          isUndefined = angular.isUndefined;\n\n      //creates a poller fn that copies all cookies from the $browser to service & inits the service\n      $browser.addPollFn(function() {\n        var currentCookies = $browser.cookies();\n        if (lastBrowserCookies != currentCookies) { //relies on browser.cookies() impl\n          lastBrowserCookies = currentCookies;\n          copy(currentCookies, lastCookies);\n          copy(currentCookies, cookies);\n          if (runEval) $rootScope.$apply();\n        }\n      })();\n\n      runEval = true;\n\n      //at the end of each eval, push cookies\n      //TODO: this should happen before the \"delayed\" watches fire, because if some cookies are not\n      //      strings or browser refuses to store some cookies, we update the model in the push fn.\n      $rootScope.$watch(push);\n\n      return cookies;\n\n\n      /**\n       * Pushes all the cookies from the service to the browser and verifies if all cookies were\n       * stored.\n       */\n      function push() {\n        var name,\n            value,\n            browserCookies,\n            updated;\n\n        //delete any cookies deleted in $cookies\n        for (name in lastCookies) {\n          if (isUndefined(cookies[name])) {\n            $browser.cookies(name, undefined);\n          }\n        }\n\n        //update all cookies updated in $cookies\n        for (name in cookies) {\n          value = cookies[name];\n          if (!angular.isString(value)) {\n            value = '' + value;\n            cookies[name] = value;\n          }\n          if (value !== lastCookies[name]) {\n            $browser.cookies(name, value);\n            updated = true;\n          }\n        }\n\n        //verify what was actually stored\n        if (updated) {\n          updated = false;\n          browserCookies = $browser.cookies();\n\n          for (name in cookies) {\n            if (cookies[name] !== browserCookies[name]) {\n              //delete or reset all cookies that the browser dropped from $cookies\n              if (isUndefined(browserCookies[name])) {\n                delete cookies[name];\n              } else {\n                cookies[name] = browserCookies[name];\n              }\n              updated = true;\n            }\n          }\n        }\n      }\n    }]).\n\n\n  /**\n   * @ngdoc service\n   * @name $cookieStore\n   * @requires $cookies\n   *\n   * @description\n   * Provides a key-value (string-object) storage, that is backed by session cookies.\n   * Objects put or retrieved from this storage are automatically serialized or\n   * deserialized by angular's toJson/fromJson.\n   *\n   * Requires the {@link ngCookies `ngCookies`} module to be installed.\n   *\n   * @example\n   *\n   * ```js\n   * angular.module('cookieStoreExample', ['ngCookies'])\n   *   .controller('ExampleController', ['$cookieStore', function($cookieStore) {\n   *     // Put cookie\n   *     $cookieStore.put('myFavorite','oatmeal');\n   *     // Get cookie\n   *     var favoriteCookie = $cookieStore.get('myFavorite');\n   *     // Removing a cookie\n   *     $cookieStore.remove('myFavorite');\n   *   }]);\n   * ```\n   */\n   factory('$cookieStore', ['$cookies', function($cookies) {\n\n      return {\n        /**\n         * @ngdoc method\n         * @name $cookieStore#get\n         *\n         * @description\n         * Returns the value of given cookie key\n         *\n         * @param {string} key Id to use for lookup.\n         * @returns {Object} Deserialized cookie value.\n         */\n        get: function(key) {\n          var value = $cookies[key];\n          return value ? angular.fromJson(value) : value;\n        },\n\n        /**\n         * @ngdoc method\n         * @name $cookieStore#put\n         *\n         * @description\n         * Sets a value for given cookie key\n         *\n         * @param {string} key Id for the `value`.\n         * @param {Object} value Value to be stored.\n         */\n        put: function(key, value) {\n          $cookies[key] = angular.toJson(value);\n        },\n\n        /**\n         * @ngdoc method\n         * @name $cookieStore#remove\n         *\n         * @description\n         * Remove given cookie\n         *\n         * @param {string} key Id of the key-value pair to delete.\n         */\n        remove: function(key) {\n          delete $cookies[key];\n        }\n      };\n\n    }]);\n\n\n})(window, window.angular);\n"
  },
  {
    "path": "flowable-ui-web/task/libs/angular-drag-and-drop-lists_1.2.0/angular-drag-and-drop-lists.js",
    "content": "/**\n * angular-drag-and-drop-lists v1.2.0\n *\n * Copyright (c) 2014 Marcel Juenemann mail@marcel-junemann.de\n * https://github.com/marceljuenemann/angular-drag-and-drop-lists\n *\n * License: MIT\n */\nangular.module('dndLists', [])\n\n  /**\n   * Use the dnd-draggable attribute to make your element draggable\n   *\n   * Attributes:\n   * - dnd-draggable      Required attribute. The value has to be an object that represents the data\n   *                      of the element. In case of a drag and drop operation the object will be\n   *                      serialized and unserialized on the receiving end.\n   * - dnd-selected       Callback that is invoked when the element was clicked but not dragged.\n   *                      The original click event will be provided in the local event variable.\n   * - dnd-effect-allowed Use this attribute to limit the operations that can be performed. Options:\n   *                      - \"move\": The drag operation will move the element. This is the default.\n   *                      - \"copy\": The drag operation will copy the element. Shows a copy cursor.\n   *                      - \"copyMove\": The user can choose between copy and move by pressing the\n   *                        ctrl or shift key. *Not supported in IE:* In Internet Explorer this\n   *                        option will be the same as \"copy\". *Not fully supported in Chrome on\n   *                        Windows:* In the Windows version of Chrome the cursor will always be the\n   *                        move cursor. However, when the user drops an element and has the ctrl\n   *                        key pressed, we will perform a copy anyways.\n   *                      - HTML5 also specifies the \"link\" option, but this library does not\n   *                        actively support it yet, so use it at your own risk.\n   * - dnd-moved          Callback that is invoked when the element was moved. Usually you will\n   *                      remove your element from the original list in this callback, since the\n   *                      directive is not doing that for you automatically. The original dragend\n   *                      event will be provided in the local event variable.\n   * - dnd-copied         Same as dnd-moved, just that it is called when the element was copied\n   *                      instead of moved. The original dragend event will be provided in the local\n   *                      event variable.\n   * - dnd-dragstart      Callback that is invoked when the element was dragged. The original\n   *                      dragstart event will be provided in the local event variable.\n   * - dnd-type           Use this attribute if you have different kinds of items in your\n   *                      application and you want to limit which items can be dropped into which\n   *                      lists. Combine with dnd-allowed-types on the dnd-list(s). This attribute\n   *                      should evaluate to a string, although this restriction is not enforced.\n   * - dnd-disable-if     You can use this attribute to dynamically disable the draggability of the\n   *                      element. This is useful if you have certain list items that you don't want\n   *                      to be draggable, or if you want to disable drag & drop completely without\n   *                      having two different code branches (e.g. only allow for admins).\n   *                      **Note**: If your element is not draggable, the user is probably able to\n   *                      select text or images inside of it. Since a selection is always draggable,\n   *                      this breaks your UI. You most likely want to disable user selection via\n   *                      CSS (see user-select).\n   *\n   * CSS classes:\n   * - dndDragging        This class will be added to the element while the element is being\n   *                      dragged. It will affect both the element you see while dragging and the\n   *                      source element that stays at it's position. Do not try to hide the source\n   *                      element with this class, because that will abort the drag operation.\n   * - dndDraggingSource  This class will be added to the element after the drag operation was\n   *                      started, meaning it only affects the original element that is still at\n   *                      it's source position, and not the \"element\" that the user is dragging with\n   *                      his mouse pointer.\n   */\n  .directive('dndDraggable', ['$parse', '$timeout', 'dndDropEffectWorkaround', 'dndDragTypeWorkaround',\n                      function($parse,   $timeout,   dndDropEffectWorkaround,   dndDragTypeWorkaround) {\n    return function(scope, element, attr) {\n      // Set the HTML5 draggable attribute on the element\n      element.attr(\"draggable\", \"true\");\n\n      // If the dnd-disable-if attribute is set, we have to watch that\n      if (attr.dndDisableIf) {\n        scope.$watch(attr.dndDisableIf, function(disabled) {\n          element.attr(\"draggable\", !disabled);\n        });\n      }\n\n      /**\n       * When the drag operation is started we have to prepare the dataTransfer object,\n       * which is the primary way we communicate with the target element\n       */\n      element.on('dragstart', function(event) {\n        event = event.originalEvent || event;\n\n        // Serialize the data associated with this element. IE only supports the Text drag type\n        event.dataTransfer.setData(\"Text\", angular.toJson(scope.$eval(attr.dndDraggable)));\n\n        // Only allow actions specified in dnd-effect-allowed attribute\n        event.dataTransfer.effectAllowed = attr.dndEffectAllowed || \"move\";\n\n        // Add CSS classes. See documentation above\n        element.addClass(\"dndDragging\");\n\n        // Workarounds for stupid browsers, see description below\n        dndDropEffectWorkaround.dropEffect = \"none\";\n        dndDragTypeWorkaround.isDragging = true;\n\n        // <FLOWABLE>\n        // This code was originally placed after element.addClass.\n        // This timeout is invoked after the 'dragend' event in IE9 (at leats on slooow virtual box)\n        // and since this class is used to hide elements it seems like the element is gone,\n        // therefor make sure the dragging still is happening when adding this class\n        $timeout(function() {\n          // Flowable This code\n          if (dndDragTypeWorkaround.isDragging) {\n            element.addClass(\"dndDraggingSource\");\n          }\n        }, 0);\n        // </FLOWABLE>\n\n        // Save type of item in global state. Usually, this would go into the dataTransfer\n        // typename, but we have to use \"Text\" there to support IE\n        dndDragTypeWorkaround.dragType = attr.dndType ? scope.$eval(attr.dndType) : undefined;\n\n        // Invoke callback\n        $parse(attr.dndDragstart)(scope, {event: event});\n\n        event.stopPropagation();\n      });\n\n      /**\n       * The dragend event is triggered when the element was dropped or when the drag\n       * operation was aborted (e.g. hit escape button). Depending on the executed action\n       * we will invoke the callbacks specified with the dnd-moved or dnd-copied attribute.\n       */\n      element.on('dragend', function(event) {\n        event = event.originalEvent || event;\n\n        // Invoke callbacks. Usually we would use event.dataTransfer.dropEffect to determine\n        // the used effect, but Chrome has not implemented that field correctly. On Windows\n        // it always sets it to 'none', while Chrome on Linux sometimes sets it to something\n        // else when it's supposed to send 'none' (drag operation aborted).\n        var dropEffect = dndDropEffectWorkaround.dropEffect;\n        scope.$apply(function() {\n          switch (dropEffect) {\n            case \"move\":\n              $parse(attr.dndMoved)(scope, {event: event});\n              break;\n\n            case \"copy\":\n              $parse(attr.dndCopied)(scope, {event: event});\n              break;\n          }\n        });\n\n        // Clean up\n        element.removeClass(\"dndDragging\");\n        element.removeClass(\"dndDraggingSource\");\n        dndDragTypeWorkaround.isDragging = false;\n        event.stopPropagation();\n      });\n\n      /**\n       * When the element is clicked we invoke the callback function\n       * specified with the dnd-selected attribute.\n       */\n      element.on('click', function(event) {\n        event = event.originalEvent || event;\n\n        scope.$apply(function() {\n          $parse(attr.dndSelected)(scope, {event: event});\n        });\n\n        event.stopPropagation();\n      });\n\n      /**\n       * Workaround to make element draggable in IE9\n       */\n      element.on('selectstart', function() {\n        if (this.dragDrop) this.dragDrop();\n        return false;\n      });\n    };\n  }])\n\n  /**\n   * Use the dnd-list attribute to make your list element a dropzone. Usually you will add a single\n   * li element as child with the ng-repeat directive. If you don't do that, we will not be able to\n   * position the dropped element correctly. If you want your list to be sortable, also add the\n   * dnd-draggable directive to your li element(s). Both the dnd-list and it's direct children must\n   * have position: relative CSS style, otherwise the positioning algorithm will not be able to\n   * determine the correct placeholder position in all browsers.\n   *\n   * Attributes:\n   * - dnd-list             Required attribute. The value has to be the array in which the data of\n   *                        the dropped element should be inserted.\n   * - dnd-allowed-types    Optional array of allowed item types. When used, only items that had a\n   *                        matching dnd-type attribute will be dropable.\n   * - dnd-disable-if       Optional boolean expresssion. When it evaluates to true, no dropping\n   *                        into the list is possible. Note that this also disables rearranging\n   *                        items inside the list.\n   * - dnd-horizontal-list  Optional boolean expresssion. When it evaluates to true, the positioning\n   *                        algorithm will use the left and right halfs of the list items instead of\n   *                        the upper and lower halfs.\n   * - dnd-dragover         Optional expression that is invoked when an element is dragged over the\n   *                        list. If the expression is set, but does not return true, the element is\n   *                        not allowed to be dropped. The following variables will be available:\n   *                        - event: The original dragover event sent by the browser.\n   *                        - index: The position in the list at which the element would be dropped.\n   *                        - type: The dnd-type set on the dnd-draggable, or undefined if unset.\n   * - dnd-drop             Optional expression that is invoked when an element is dropped over the\n   *                        list. If the expression is set, it must return the object that will be\n   *                        inserted into the list. If it returns false, the drop will be aborted\n   *                        and the event is propagated. The following variables will be available:\n   *                        - event: The original drop event sent by the browser.\n   *                        - index: The position in the list at which the element would be dropped.\n   *                        - item: The transferred object.\n   *                        - type: The dnd-type set on the dnd-draggable, or undefined if unset.\n   * - dnd-external-sources Optional boolean expression. When it evaluates to true, the list accepts\n   *                        drops from sources outside of the current browser tab. This allows to\n   *                        drag and drop accross different browser tabs. Note that this will allow\n   *                        to drop arbitrary text into the list, thus it is highly recommended to\n   *                        implement the dnd-drop callback to check the incoming element for\n   *                        sanity. Furthermore, the dnd-type of external sources can not be\n   *                        determined, therefore do not rely on restrictions of dnd-allowed-type.\n   *\n   * CSS classes:\n   * - dndPlaceholder       When an element is dragged over the list, a new placeholder child\n   *                        element will be added. This element is of type li and has the class\n   *                        dndPlaceholder set.\n   * - dndDragover          Will be added to the list while an element is dragged over the list.\n   */\n  .directive('dndList', ['$parse', '$timeout', 'dndDropEffectWorkaround', 'dndDragTypeWorkaround',\n                 function($parse,   $timeout,   dndDropEffectWorkaround,   dndDragTypeWorkaround) {\n    return function(scope, element, attr) {\n      // While an element is dragged over the list, this placeholder element is inserted\n      // at the location where the element would be inserted after dropping\n      var placeholder = angular.element(\"<li class='dndPlaceholder'></li>\");\n      var placeholderNode = placeholder[0];\n      var listNode = element[0];\n\n      var horizontal = attr.dndHorizontalList && scope.$eval(attr.dndHorizontalList);\n      var externalSources = attr.dndExternalSources && scope.$eval(attr.dndExternalSources);\n\n      /**\n       * The dragover event is triggered \"every few hundred milliseconds\" while an element\n       * is being dragged over our list, or over an child element.\n       */\n      element.on('dragover', function(event) {\n        event = event.originalEvent || event;\n\n        if (!isDropAllowed(event)) {\n            return true;\n        }\n\n        // First of all, make sure that the placeholder is shown\n        // This is especially important if the list is empty\n        if (placeholderNode.parentNode != listNode) {\n          element.append(placeholder);\n        }\n\n        if (event.target !== listNode) {\n          // Try to find the node direct directly below the list node.\n          var listItemNode = event.target;\n          while (listItemNode.parentNode !== listNode && listItemNode.parentNode) {\n            listItemNode = listItemNode.parentNode;\n          }\n\n          if (listItemNode.parentNode === listNode && listItemNode !== placeholderNode) {\n            // If the mouse pointer is in the upper half of the child element,\n            // we place it before the child element, otherwise below it.\n            if (isMouseInFirstHalf(event, listItemNode)) {\n              listNode.insertBefore(placeholderNode, listItemNode);\n            } else {\n              listNode.insertBefore(placeholderNode, listItemNode.nextSibling);\n            }\n          }\n        } else {\n          // This branch is reached when we are dragging directly over the list element.\n          // Usually we wouldn't need to do anything here, but the IE does not fire it's\n          // events for the child element, only for the list directly. Therefore we repeat\n          // the positioning algorithm for IE here.\n          if (isMouseInFirstHalf(event, placeholderNode, true)) {\n            // Check if we should move the placeholder element one spot towards the top.\n            // Note that display none elements will have offsetTop and offsetHeight set to\n            // zero, therefore we need a special check for them.\n            while (placeholderNode.previousElementSibling\n                 && (isMouseInFirstHalf(event, placeholderNode.previousElementSibling, true)\n                 || placeholderNode.previousElementSibling.offsetHeight === 0)) {\n              listNode.insertBefore(placeholderNode, placeholderNode.previousElementSibling);\n            }\n          } else {\n            // Check if we should move the placeholder element one spot towards the bottom\n            while (placeholderNode.nextElementSibling &&\n                 !isMouseInFirstHalf(event, placeholderNode.nextElementSibling, true)) {\n              listNode.insertBefore(placeholderNode,\n                  placeholderNode.nextElementSibling.nextElementSibling);\n            }\n          }\n        }\n\n        // At this point we invoke the callback, which still can disallow the drop.\n        // We can't do this earlier because we want to pass the index of the placeholder.\n        if (attr.dndDragover && !invokeCallback(attr.dndDragover, event)) {\n          return stopDragover();\n        }\n\n        element.addClass(\"dndDragover\");\n        event.preventDefault();\n        event.stopPropagation();\n        return false;\n      });\n\n      /**\n       * When the element is dropped, we use the position of the placeholder element as the\n       * position where we insert the transferred data. This assumes that the list has exactly\n       * one child element per array element.\n       */\n      element.on('drop', function(event) {\n        event = event.originalEvent || event;\n\n        if (!isDropAllowed(event)) return true;\n\n        // The default behavior in Firefox is to interpret the dropped element as URL and\n        // forward to it. We want to prevent that even if our drop is aborted.\n        event.preventDefault();\n\n        // Unserialize the data that was serialized in dragstart. According to the HTML5 specs,\n        // the \"Text\" drag type will be converted to text/plain, but IE does not do that.\n        var data = event.dataTransfer.getData(\"Text\") || event.dataTransfer.getData(\"text/plain\");\n        var transferredObject;\n        try {\n          transferredObject = JSON.parse(data);\n        } catch(e) {\n          return stopDragover();\n        }\n\n        // Invoke the callback, which can transform the transferredObject and even abort the drop.\n        if (attr.dndDrop) {\n          transferredObject = invokeCallback(attr.dndDrop, event, transferredObject);\n          if (!transferredObject) {\n            return stopDragover();\n          }\n        }\n\n        // Retrieve the JSON array and insert the transferred object into it.\n        var targetArray = scope.$eval(attr.dndList);\n        scope.$apply(function() {\n          targetArray.splice(getPlaceholderIndex(), 0, transferredObject);\n        });\n\n        // Invoke the callback, after the transfered objrct is added to the new container.\n        if (attr.dndAfterDrop) {\n           invokeCallback(attr.dndAfterDrop, event, transferredObject);\n        }\n        // In Chrome on Windows the dropEffect will always be none...\n        // We have to determine the actual effect manually from the allowed effects\n        if (event.dataTransfer.dropEffect === \"none\") {\n          if (event.dataTransfer.effectAllowed === \"copy\" ||\n              event.dataTransfer.effectAllowed === \"move\") {\n            dndDropEffectWorkaround.dropEffect = event.dataTransfer.effectAllowed;\n          } else {\n            dndDropEffectWorkaround.dropEffect = event.ctrlKey ? \"copy\" : \"move\";\n          }\n        } else {\n          dndDropEffectWorkaround.dropEffect = event.dataTransfer.dropEffect;\n        }\n\n        // Clean up\n        stopDragover();\n        event.stopPropagation();\n        return false;\n      });\n\n      /**\n       * We have to remove the placeholder when the element is no longer dragged over our list. The\n       * problem is that the dragleave event is not only fired when the element leaves our list,\n       * but also when it leaves a child element -- so practically it's fired all the time. As a\n       * workaround we wait a few milliseconds and then check if the dndDragover class was added\n       * again. If it is there, dragover must have been called in the meantime, i.e. the element\n       * is still dragging over the list. If you know a better way of doing this, please tell me!\n       */\n      element.on('dragleave', function(event) {\n        event = event.originalEvent || event;\n\n        element.removeClass(\"dndDragover\");\n        $timeout(function() {\n          if (!element.hasClass(\"dndDragover\")) {\n            placeholder.remove();\n          }\n        }, 100);\n      });\n\n      /**\n       * Checks whether the mouse pointer is in the first half of the given target element.\n       *\n       * In Chrome we can just use offsetY, but in Firefox we have to use layerY, which only\n       * works if the child element has position relative. In IE the events are only triggered\n       * on the listNode instead of the listNodeItem, therefore the mouse positions are\n       * relative to the parent element of targetNode.\n       */\n      function isMouseInFirstHalf(event, targetNode, relativeToParent) {\n        var mousePointer = horizontal ? (event.offsetX || event.layerX)\n                                      : (event.offsetY || event.layerY);\n        var targetSize = horizontal ? targetNode.offsetWidth : targetNode.offsetHeight;\n        var targetPosition = horizontal ? targetNode.offsetLeft : targetNode.offsetTop;\n        targetPosition = relativeToParent ? targetPosition : 0;\n        return mousePointer < targetPosition + targetSize / 2;\n      }\n\n        /**\n         * Flowable-patched version of isMouseInFirstHalf that uses page and bounding client rect\n         * instead of the offsetX and layerX properties to determine which half of target the mouse pointer is hovering\n         * this is more natural since th method now actually works like above, but it also adds some mild\n         * flickering when sorting inside the list, why its still not in use.\n         */\n        function isMouseInFirstHalf_new(event, targetNode, relativeToParent) {\n            var targetNodeRect = targetNode.getBoundingClientRect();\n            if (horizontal) {\n                return (event.pageX - targetNodeRect.left) < (targetNodeRect.width / 2);\n            }\n            else {\n                return (event.pageY - targetNodeRect.top) < (targetNodeRect.height / 2);\n            }\n        }\n      /**\n       * We use the position of the placeholder node to determine at which position of the array the\n       * object needs to be inserted\n       */\n      function getPlaceholderIndex() {\n        return Array.prototype.indexOf.call(listNode.children, placeholderNode);\n      }\n\n      /**\n       * Checks various conditions that must be fulfilled for a drop to be allowed\n       */\n      function isDropAllowed(event) {\n        // Disallow drop from external source unless it's allowed explicitly.\n        if (!dndDragTypeWorkaround.isDragging && !externalSources) return false;\n\n        // Check mimetype. Usually we would use a custom drag type instead of Text, but IE doesn't\n        // support that.\n        if (!hasTextMimetype(event.dataTransfer.types)) return false;\n\n        // Now check the dnd-allowed-types against the type of the incoming element. For drops from\n        // external sources we don't know the type, so it will need to be checked via dnd-drop.\n        if (attr.dndAllowedTypes && dndDragTypeWorkaround.isDragging) {\n          var allowed = scope.$eval(attr.dndAllowedTypes);\n          if (angular.isArray(allowed) && allowed.indexOf(dndDragTypeWorkaround.dragType) === -1) {\n            return false;\n          }\n        }\n\n        // Check whether droping is disabled completely\n        if (attr.dndDisableIf && scope.$eval(attr.dndDisableIf)) return false;\n\n        return true;\n      }\n\n      /**\n       * Small helper function that cleans up if we aborted a drop.\n       */\n      function stopDragover() {\n        placeholder.remove();\n        element.removeClass(\"dndDragover\");\n        return true;\n      }\n\n      /**\n       * Invokes a callback with some interesting parameters and returns the callbacks return value.\n       */\n      function invokeCallback(expression, event, item) {\n        return $parse(expression)(scope, {\n          event: event,\n          index: getPlaceholderIndex(),\n          item: item || undefined,\n          external: !dndDragTypeWorkaround.isDragging,\n          type: dndDragTypeWorkaround.isDragging ? dndDragTypeWorkaround.dragType : undefined\n        });\n      }\n\n      /**\n       * Check if the dataTransfer object contains a drag type that we can handle. In old versions\n       * of IE the types collection will not even be there, so we just assume a drop is possible.\n       */\n      function hasTextMimetype(types) {\n        if (!types) return true;\n        for (var i = 0; i < types.length; i++) {\n          if (types[i] === \"Text\" || types[i] === \"text/plain\") return true;\n        }\n\n        return false;\n      }\n    };\n  }])\n\n  /**\n   * This workaround handles the fact that Internet Explorer does not support drag types other than\n   * \"Text\" and \"URL\". That means we can not know whether the data comes from one of our elements or\n   * is just some other data like a text selection. As a workaround we save the isDragging flag in\n   * here. When a dropover event occurs, we only allow the drop if we are already dragging, because\n   * that means the element is ours.\n   */\n  .factory('dndDragTypeWorkaround', function(){ return {} })\n\n  /**\n   * Chrome on Windows does not set the dropEffect field, which we need in dragend to determine\n   * whether a drag operation was successful. Therefore we have to maintain it in this global\n   * variable. The bug report for that has been open for years:\n   * https://code.google.com/p/chromium/issues/detail?id=39399\n   */\n  .factory('dndDropEffectWorkaround', function(){ return {} });\n"
  },
  {
    "path": "flowable-ui-web/task/libs/angular-dragdrop_1.0.11/angular-dragdrop.js",
    "content": "/**\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\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell 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\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\n/**\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.11\n *\n * (c) 2013 Amit Gharat a.k.a codef0rmer <amit.2006.it@gmail.com> - amitgharat.wordpress.com\n */\n\n(function (window, angular, $, undefined) {\n    'use strict';\n\n    var jqyoui = angular.module('ngDragDrop', []).service('ngDragDropService', ['$timeout', '$parse', function($timeout, $parse) {\n        this.draggableScope = null;\n        this.droppableScope = null;\n\n        this.callEventCallback = function (scope, callbackName, event, ui) {\n            if (!callbackName) return;\n\n            var objExtract = extract(callbackName),\n                callback = objExtract.callback,\n                constructor = objExtract.constructor,\n                args = [event, ui].concat(objExtract.args);\n\n            // call either $scoped method i.e. $scope.dropCallback or constructor's method i.e. this.dropCallback.\n            // Removing scope.$apply call that was performance intensive (especially onDrag) and does not require it\n            // always. So call it within the callback if needed.\n            return (scope[callback] || scope[constructor][callback]).apply(scope, args);\n\n            function extract(callbackName) {\n                var atStartBracket = callbackName.indexOf('(') !== -1 ? callbackName.indexOf('(') : callbackName.length,\n                    atEndBracket = callbackName.lastIndexOf(')') !== -1 ? callbackName.lastIndexOf(')') : callbackName.length,\n                    args = callbackName.substring(atStartBracket + 1, atEndBracket), // matching function arguments inside brackets\n                    constructor = callbackName.match(/^[^.]+.\\s*/)[0].slice(0, -1); // matching a string upto a dot to check ctrl as syntax\n                constructor = scope[constructor] && typeof scope[constructor].constructor === 'function' ? constructor : null;\n\n                return {\n                    callback: callbackName.substring(constructor && constructor.length + 1 || 0, atStartBracket),\n                    args: $.map(args && args.split(',') || [], function(item) { return [$parse(item)(scope)]; }),\n                    constructor: constructor\n                }\n            }\n        };\n\n        this.invokeDrop = function ($draggable, $droppable, event, ui) {\n            var dragModel = '',\n                dropModel = '',\n                dragSettings = {},\n                dropSettings = {},\n                jqyoui_pos = null,\n                dragItem = {},\n                dropItem = {},\n                dragModelValue,\n                dropModelValue,\n                $droppableDraggable = null,\n                droppableScope = this.droppableScope,\n                draggableScope = this.draggableScope;\n\n            dragModel = $draggable.ngattr('ng-model');\n            dropModel = $droppable.ngattr('ng-model');\n            dragModelValue = draggableScope.$eval(dragModel);\n            dropModelValue = droppableScope.$eval(dropModel);\n\n            $droppableDraggable = $droppable.find('[jqyoui-draggable]:last,[data-jqyoui-draggable]:last');\n            dropSettings = droppableScope.$eval($droppable.attr('jqyoui-droppable') || $droppable.attr('data-jqyoui-droppable')) || [];\n            dragSettings = draggableScope.$eval($draggable.attr('jqyoui-draggable') || $draggable.attr('data-jqyoui-draggable')) || [];\n\n            // Helps pick up the right item\n            dragSettings.index = this.fixIndex(draggableScope, dragSettings, dragModelValue);\n            dropSettings.index = this.fixIndex(droppableScope, dropSettings, dropModelValue);\n\n            jqyoui_pos = angular.isArray(dragModelValue) ? dragSettings.index : null;\n            dragItem = angular.isArray(dragModelValue) ? dragModelValue[jqyoui_pos] : dragModelValue;\n\n            if (dragSettings.deepCopy) {\n                dragItem = angular.copy(dragItem);\n            }\n\n            if (angular.isArray(dropModelValue) && dropSettings && dropSettings.index !== undefined) {\n                dropItem = dropModelValue[dropSettings.index];\n            } else if (!angular.isArray(dropModelValue)) {\n                dropItem = dropModelValue;\n            } else {\n                dropItem = {};\n            }\n\n            if (dropSettings.deepCopy) {\n                dropItem = angular.copy(dropItem);\n            }\n\n            if (dragSettings.animate === true) {\n                this.move($draggable, $droppableDraggable.length > 0 ? $droppableDraggable : $droppable, null, 'fast', dropSettings, null);\n                this.move($droppableDraggable.length > 0 && !dropSettings.multiple ? $droppableDraggable : [], $draggable.parent('[jqyoui-droppable],[data-jqyoui-droppable]'), jqyoui.startXY, 'fast', dropSettings, angular.bind(this, function() {\n                    $timeout(angular.bind(this, function() {\n                        // Do not move this into move() to avoid flickering issue\n                        $draggable.css({'position': 'relative', 'left': '', 'top': ''});\n                        // Angular v1.2 uses ng-hide to hide an element not display property\n                        // so we've to manually remove display:none set in this.move()\n                        $droppableDraggable.css({'position': 'relative', 'left': '', 'top': '', 'display': $droppableDraggable.css('display') === 'none' ? '' : $droppableDraggable.css('display')});\n\n                        this.mutateDraggable(draggableScope, dropSettings, dragSettings, dragModel, dropModel, dropItem, $draggable);\n                        this.mutateDroppable(droppableScope, dropSettings, dragSettings, dropModel, dragItem, jqyoui_pos);\n                        this.callEventCallback(droppableScope, dropSettings.onDrop, event, ui);\n                    }));\n                }));\n            } else {\n                $timeout(angular.bind(this, function() {\n                    this.mutateDraggable(draggableScope, dropSettings, dragSettings, dragModel, dropModel, dropItem, $draggable);\n                    this.mutateDroppable(droppableScope, dropSettings, dragSettings, dropModel, dragItem, jqyoui_pos);\n                    this.callEventCallback(droppableScope, dropSettings.onDrop, event, ui);\n                }));\n            }\n        };\n\n        this.move = function($fromEl, $toEl, toPos, duration, dropSettings, callback) {\n            if ($fromEl.length === 0) {\n                if (callback) {\n                    window.setTimeout(function() {\n                        callback();\n                    }, 300);\n                }\n                return false;\n            }\n\n            var zIndex = $fromEl.css('z-index'),\n                fromPos = $fromEl[dropSettings.containment || 'offset'](),\n                displayProperty = $toEl.css('display'), // sometimes `display` is other than `block`\n                hadNgHideCls = $toEl.hasClass('ng-hide');\n\n            if (toPos === null && $toEl.length > 0) {\n                if (($toEl.attr('jqyoui-draggable') || $toEl.attr('data-jqyoui-draggable')) !== undefined && $toEl.ngattr('ng-model') !== undefined && $toEl.is(':visible') && dropSettings && dropSettings.multiple) {\n                    toPos = $toEl[dropSettings.containment || 'offset']();\n                    if (dropSettings.stack === false) {\n                        toPos.left+= $toEl.outerWidth(true);\n                    } else {\n                        toPos.top+= $toEl.outerHeight(true);\n                    }\n                } else {\n                    // Angular v1.2 uses ng-hide to hide an element\n                    // so we've to remove it in order to grab its position\n                    if (hadNgHideCls) $toEl.removeClass('ng-hide');\n                    toPos = $toEl.css({'visibility': 'hidden', 'display': 'block'})[dropSettings.containment || 'offset']();\n                    $toEl.css({'visibility': '','display': displayProperty});\n                }\n            }\n\n            $fromEl.css({'position': 'absolute', 'z-index': 9999})\n                .css(fromPos)\n                .animate(toPos, duration, function() {\n                    // Angular v1.2 uses ng-hide to hide an element\n                    // and as we remove it above, we've to put it back to\n                    // hide the element (while swapping) if it was hidden already\n                    // because we remove the display:none in this.invokeDrop()\n                    if (hadNgHideCls) $toEl.addClass('ng-hide');\n                    $fromEl.css('z-index', zIndex);\n                    if (callback) callback();\n                });\n        };\n\n        this.mutateDroppable = function(scope, dropSettings, dragSettings, dropModel, dragItem, jqyoui_pos) {\n            var dropModelValue = scope.$eval(dropModel);\n\n            scope.dndDragItem = dragItem;\n\n            if (angular.isArray(dropModelValue)) {\n                if (dropSettings && dropSettings.index >= 0) {\n                    dropModelValue[dropSettings.index] = dragItem;\n                } else {\n                    dropModelValue.push(dragItem);\n                }\n                if (dragSettings && dragSettings.placeholder === true) {\n                    dropModelValue[dropModelValue.length - 1]['jqyoui_pos'] = jqyoui_pos;\n                }\n            } else {\n                $parse(dropModel + ' = dndDragItem')(scope);\n                if (dragSettings && dragSettings.placeholder === true) {\n                    dropModelValue['jqyoui_pos'] = jqyoui_pos;\n                }\n            }\n        };\n\n        this.mutateDraggable = function(scope, dropSettings, dragSettings, dragModel, dropModel, dropItem, $draggable) {\n            var isEmpty = angular.equals(dropItem, {}) || !dropItem,\n                dragModelValue = scope.$eval(dragModel);\n\n            scope.dndDropItem = dropItem;\n\n            if (dragSettings && dragSettings.placeholder) {\n                if (dragSettings.placeholder != 'keep'){\n                    if (angular.isArray(dragModelValue) && dragSettings.index !== undefined) {\n                        dragModelValue[dragSettings.index] = dropItem;\n                    } else {\n                        $parse(dragModel + ' = dndDropItem')(scope);\n                    }\n                }\n            } else {\n                if (angular.isArray(dragModelValue)) {\n                    if (isEmpty) {\n                        if (dragSettings && ( dragSettings.placeholder !== true && dragSettings.placeholder !== 'keep' )) {\n                            dragModelValue.splice(dragSettings.index, 1);\n                        }\n                    } else {\n                        dragModelValue[dragSettings.index] = dropItem;\n                    }\n                } else {\n                    // Fix: LIST(object) to LIST(array) - model does not get updated using just scope[dragModel] = {...}\n                    // P.S.: Could not figure out why it happened\n                    $parse(dragModel + ' = dndDropItem')(scope);\n                    if (scope.$parent) {\n                        $parse(dragModel + ' = dndDropItem')(scope.$parent);\n                    }\n                }\n            }\n\n            $draggable.css({'z-index': '', 'left': '', 'top': ''});\n        };\n\n        this.fixIndex = function(scope, settings, modelValue) {\n            if (settings.applyFilter && angular.isArray(modelValue) && modelValue.length > 0) {\n                var dragModelValueFiltered = scope[settings.applyFilter](),\n                    lookup = dragModelValueFiltered[settings.index],\n                    actualIndex = undefined;\n\n                modelValue.forEach(function(item, i) {\n                    if (angular.equals(item, lookup)) {\n                        actualIndex = i;\n                    }\n                });\n\n                return actualIndex;\n            }\n\n            return settings.index;\n        };\n    }]).directive('jqyouiDraggable', ['ngDragDropService', function(ngDragDropService) {\n        return {\n            require: '?jqyouiDroppable',\n            restrict: 'A',\n            link: function(scope, element, attrs) {\n                var dragSettings, jqyouiOptions, zIndex;\n                var updateDraggable = function(newValue, oldValue) {\n                    if (newValue) {\n                        dragSettings = scope.$eval(element.attr('jqyoui-draggable') || element.attr('data-jqyoui-draggable')) || {};\n                        jqyouiOptions = scope.$eval(attrs.jqyouiOptions) || {};\n                        element\n                            .draggable({disabled: false})\n                            .draggable(jqyouiOptions)\n                            .draggable({\n                                start: function(event, ui) {\n                                    ngDragDropService.draggableScope = scope;\n                                    zIndex = angular.element(jqyouiOptions.helper ? ui.helper : this).css('z-index');\n                                    angular.element(jqyouiOptions.helper ? ui.helper : this).css('z-index', 9999);\n                                    jqyoui.startXY = angular.element(this)[dragSettings.containment || 'offset']();\n                                    ngDragDropService.callEventCallback(scope, dragSettings.onStart, event, ui);\n                                },\n                                stop: function(event, ui) {\n                                    angular.element(jqyouiOptions.helper ? ui.helper : this).css('z-index', zIndex);\n                                    ngDragDropService.callEventCallback(scope, dragSettings.onStop, event, ui);\n                                },\n                                drag: function(event, ui) {\n                                    ngDragDropService.callEventCallback(scope, dragSettings.onDrag, event, ui);\n                                }\n                            });\n                    } else {\n                        element.draggable({disabled: true});\n                    }\n                };\n                scope.$watch(function() { return scope.$eval(attrs.drag); }, updateDraggable);\n                updateDraggable();\n\n                element.on('$destroy', function() {\n                    element.draggable({disabled: true}).draggable('destroy');\n                });\n            }\n        };\n    }]).directive('jqyouiDroppable', ['ngDragDropService', '$q', function(ngDragDropService, $q) {\n        return {\n            restrict: 'A',\n            priority: 1,\n            link: function(scope, element, attrs) {\n                var dropSettings;\n                var updateDroppable = function(newValue, oldValue) {\n                    if (newValue) {\n                        dropSettings = scope.$eval(angular.element(element).attr('jqyoui-droppable') || angular.element(element).attr('data-jqyoui-droppable')) || {};\n                        element\n                            .droppable({disabled: false})\n                            .droppable(scope.$eval(attrs.jqyouiOptions) || {})\n                            .droppable({\n                                over: function(event, ui) {\n                                    ngDragDropService.callEventCallback(scope, dropSettings.onOver, event, ui);\n                                },\n                                out: function(event, ui) {\n                                    ngDragDropService.callEventCallback(scope, dropSettings.onOut, event, ui);\n                                },\n                                drop: function(event, ui) {\n                                    var beforeDropPromise = null;\n\n                                    if (dropSettings.beforeDrop) {\n                                        beforeDropPromise = ngDragDropService.callEventCallback(scope, dropSettings.beforeDrop, event, ui);\n                                    } else {\n                                        beforeDropPromise = (function() {\n                                            var deferred = $q.defer();\n                                            deferred.resolve();\n                                            return deferred.promise;\n                                        })();\n                                    }\n\n                                    beforeDropPromise.then(angular.bind(this, function() {\n                                        if (angular.element(ui.draggable).ngattr('ng-model') && attrs.ngModel) {\n                                            ngDragDropService.droppableScope = scope;\n                                            ngDragDropService.invokeDrop(angular.element(ui.draggable), angular.element(this), event, ui);\n                                        } else {\n                                            ngDragDropService.callEventCallback(scope, dropSettings.onDrop, event, ui);\n                                        }\n                                    }), function() {\n                                        ui.draggable.css({left: '', top: ''});\n                                    });\n                                }\n                            });\n                    } else {\n                        element.droppable({disabled: true});\n                    }\n                };\n\n                scope.$watch(function() { return scope.$eval(attrs.drop); }, updateDroppable);\n                updateDroppable();\n\n                element.on('$destroy', function() {\n                    element.droppable({disabled: true}).droppable('destroy');\n                });\n            }\n        };\n    }]);\n\n    angular.element.prototype.ngattr = function(name, value) {\n        var element = angular.element(this).get(0);\n\n        return element.getAttribute(name) || element.getAttribute('data-' + name);\n    };\n})(window, window.angular, window.jQuery);"
  },
  {
    "path": "flowable-ui-web/task/libs/angular-gridster_0.11.7/angular-gridster.js",
    "content": "(function(angular) {\n\n    'use strict';\n\n    angular.module('gridster', [])\n\n        .constant('gridsterConfig', {\n            columns: 6, // number of columns in the grid\n            pushing: true, // whether to push other items out of the way\n            floating: true, // whether to automatically float items up so they stack\n            swapping: false, // whether or not to have items switch places instead of push down if they are the same size\n            width: 'auto', // width of the grid. \"auto\" will expand the grid to its parent container\n            colWidth: 'auto', // width of grid columns. \"auto\" will divide the width of the grid evenly among the columns\n            rowHeight: 'match', // height of grid rows. 'match' will make it the same as the column width, a numeric value will be interpreted as pixels, '/2' is half the column width, '*5' is five times the column width, etc.\n            margins: [10, 10], // margins in between grid items\n            outerMargin: true,\n            isMobile: false, // toggle mobile view\n            mobileBreakPoint: 600, // width threshold to toggle mobile mode\n            mobileModeEnabled: true, // whether or not to toggle mobile mode when screen width is less than mobileBreakPoint\n            minColumns: 1, // minimum amount of columns the grid can scale down to\n            minRows: 1, // minimum amount of rows to show if the grid is empty\n            maxRows: 100, // maximum amount of rows in the grid\n            defaultSizeX: 2, // default width of an item in columns\n            defaultSizeY: 1, // default height of an item in rows\n            minSizeX: 1, // minimum column width of an item\n            maxSizeX: null, // maximum column width of an item\n            minSizeY: 1, // minumum row height of an item\n            maxSizeY: null, // maximum row height of an item\n            saveGridItemCalculatedHeightInMobile: false, // grid item height in mobile display. true- to use the calculated height by sizeY given\n            resizable: { // options to pass to resizable handler\n                enabled: true,\n                handles: ['s', 'e', 'n', 'w', 'se', 'ne', 'sw', 'nw']\n            },\n            draggable: { // options to pass to draggable handler\n                enabled: true,\n                scrollSensitivity: 20, // Distance in pixels from the edge of the viewport after which the viewport should scroll, relative to pointer\n                scrollSpeed: 15 // Speed at which the window should scroll once the mouse pointer gets within scrollSensitivity distance\n            }\n        })\n\n        .controller('GridsterCtrl', ['gridsterConfig', '$timeout',\n            function(gridsterConfig, $timeout) {\n\n                var gridster = this;\n\n                /**\n                 * Create options from gridsterConfig constant\n                 */\n                angular.extend(this, gridsterConfig);\n\n                this.resizable = angular.extend({}, gridsterConfig.resizable || {});\n                this.draggable = angular.extend({}, gridsterConfig.draggable || {});\n\n                var flag = false;\n                this.layoutChanged = function() {\n                    if (flag) {\n                        return;\n                    }\n                    flag = true;\n                    $timeout(function() {\n                        flag = false;\n                        if (gridster.loaded) {\n                            gridster.floatItemsUp();\n                        }\n                        gridster.updateHeight(gridster.movingItem ? gridster.movingItem.sizeY : 0);\n                    });\n                };\n\n                /**\n                 * A positional array of the items in the grid\n                 */\n                this.grid = [];\n\n                /**\n                 * Clean up after yourself\n                 */\n                this.destroy = function() {\n                    if (this.grid) {\n                        this.grid.length = 0;\n                        this.grid = null;\n                    }\n                };\n\n                /**\n                 * Overrides default options\n                 *\n                 * @param {object} options The options to override\n                 */\n                this.setOptions = function(options) {\n                    if (!options) {\n                        return;\n                    }\n\n                    options = angular.extend({}, options);\n\n                    // all this to avoid using jQuery...\n                    if (options.draggable) {\n                        angular.extend(this.draggable, options.draggable);\n                        delete(options.draggable);\n                    }\n                    if (options.resizable) {\n                        angular.extend(this.resizable, options.resizable);\n                        delete(options.resizable);\n                    }\n\n                    angular.extend(this, options);\n\n                    if (!this.margins || this.margins.length !== 2) {\n                        this.margins = [0, 0];\n                    } else {\n                        for (var x = 0, l = this.margins.length; x < l; ++x) {\n                            this.margins[x] = parseInt(this.margins[x], 10);\n                            if (isNaN(this.margins[x])) {\n                                this.margins[x] = 0;\n                            }\n                        }\n                    }\n                };\n\n                /**\n                 * Check if item can occupy a specified position in the grid\n                 *\n                 * @param {object} item The item in question\n                 * @param {number} row The row index\n                 * @param {number} column The column index\n                 * @returns {boolean} True if if item fits\n                 */\n                this.canItemOccupy = function(item, row, column) {\n                    return row > -1 && column > -1 && item.sizeX + column <= this.columns && item.sizeY + row <= this.maxRows;\n                };\n\n                /**\n                 * Set the item in the first suitable position\n                 *\n                 * @param {object} item The item to insert\n                 */\n                this.autoSetItemPosition = function(item) {\n                    // walk through each row and column looking for a place it will fit\n                    for (var rowIndex = 0; rowIndex < this.maxRows; ++rowIndex) {\n                        for (var colIndex = 0; colIndex < this.columns; ++colIndex) {\n                            // only insert if position is not already taken and it can fit\n                            var items = this.getItems(rowIndex, colIndex, item.sizeX, item.sizeY, item);\n                            if (items.length === 0 && this.canItemOccupy(item, rowIndex, colIndex)) {\n                                this.putItem(item, rowIndex, colIndex);\n                                return;\n                            }\n                        }\n                    }\n                    throw new Error('Unable to place item!');\n                };\n\n                /**\n                 * Gets items at a specific coordinate\n                 *\n                 * @param {number} row\n                 * @param {number} column\n                 * @param {number} sizeX\n                 * @param {number} sizeY\n                 * @param {array} excludeItems An array of items to exclude from selection\n                 * @returns {array} Items that match the criteria\n                 */\n                this.getItems = function(row, column, sizeX, sizeY, excludeItems) {\n                    var items = [];\n                    if (!sizeX || !sizeY) {\n                        sizeX = sizeY = 1;\n                    }\n                    if (excludeItems && !(excludeItems instanceof Array)) {\n                        excludeItems = [excludeItems];\n                    }\n                    for (var h = 0; h < sizeY; ++h) {\n                        for (var w = 0; w < sizeX; ++w) {\n                            var item = this.getItem(row + h, column + w, excludeItems);\n                            if (item && (!excludeItems || excludeItems.indexOf(item) === -1) && items.indexOf(item) === -1) {\n                                items.push(item);\n                            }\n                        }\n                    }\n                    return items;\n                };\n\n                this.getBoundingBox = function(items) {\n\n                    if (items.length === 0) {\n                        return null;\n                    }\n                    if (items.length === 1) {\n                        return {\n                            row: items[0].row,\n                            col: items[0].col,\n                            sizeY: items[0].sizeY,\n                            sizeX: items[0].sizeX\n                        };\n                    }\n\n                    var maxRow = 0;\n                    var maxCol = 0;\n                    var minRow = 9999;\n                    var minCol = 9999;\n\n                    for (var i = 0, l = items.length; i < l; ++i) {\n                        var item = items[i];\n                        minRow = Math.min(item.row, minRow);\n                        minCol = Math.min(item.col, minCol);\n                        maxRow = Math.max(item.row + item.sizeY, maxRow);\n                        maxCol = Math.max(item.col + item.sizeX, maxCol);\n                    }\n\n                    return {\n                        row: minRow,\n                        col: minCol,\n                        sizeY: maxRow - minRow,\n                        sizeX: maxCol - minCol\n                    };\n                };\n\n\n                /**\n                 * Removes an item from the grid\n                 *\n                 * @param {object} item\n                 */\n                this.removeItem = function(item) {\n                    for (var rowIndex = 0, l = this.grid.length; rowIndex < l; ++rowIndex) {\n                        var columns = this.grid[rowIndex];\n                        if (!columns) {\n                            continue;\n                        }\n                        var index = columns.indexOf(item);\n                        if (index !== -1) {\n                            columns[index] = null;\n                            break;\n                        }\n                    }\n                    this.layoutChanged();\n                };\n\n                /**\n                 * Returns the item at a specified coordinate\n                 *\n                 * @param {number} row\n                 * @param {number} column\n                 * @param {array} excludeitems Items to exclude from selection\n                 * @returns {object} The matched item or null\n                 */\n                this.getItem = function(row, column, excludeItems) {\n                    if (excludeItems && !(excludeItems instanceof Array)) {\n                        excludeItems = [excludeItems];\n                    }\n                    var sizeY = 1;\n                    while (row > -1) {\n                        var sizeX = 1,\n                            col = column;\n                        while (col > -1) {\n                            var items = this.grid[row];\n                            if (items) {\n                                var item = items[col];\n                                if (item && (!excludeItems || excludeItems.indexOf(item) === -1) && item.sizeX >= sizeX && item.sizeY >= sizeY) {\n                                    return item;\n                                }\n                            }\n                            ++sizeX;\n                            --col;\n                        }\n                        --row;\n                        ++sizeY;\n                    }\n                    return null;\n                };\n\n                /**\n                 * Insert an array of items into the grid\n                 *\n                 * @param {array} items An array of items to insert\n                 */\n                this.putItems = function(items) {\n                    for (var i = 0, l = items.length; i < l; ++i) {\n                        this.putItem(items[i]);\n                    }\n                };\n\n                /**\n                 * Insert a single item into the grid\n                 *\n                 * @param {object} item The item to insert\n                 * @param {number} row (Optional) Specifies the items row index\n                 * @param {number} column (Optional) Specifies the items column index\n                 * @param {array} ignoreItems\n                 */\n                this.putItem = function(item, row, column, ignoreItems) {\n                    if (typeof row === 'undefined' || row === null) {\n                        row = item.row;\n                        column = item.col;\n                        if (typeof row === 'undefined' || row === null) {\n                            this.autoSetItemPosition(item);\n                            return;\n                        }\n                    }\n                    if (!this.canItemOccupy(item, row, column)) {\n                        column = Math.min(this.columns - item.sizeX, Math.max(0, column));\n                        row = Math.min(this.maxRows - item.sizeY, Math.max(0, row));\n                    }\n\n                    if (item.oldRow !== null && typeof item.oldRow !== 'undefined') {\n                        var samePosition = item.oldRow === row && item.oldColumn === column;\n                        var inGrid = this.grid[row] && this.grid[row][column] === item;\n                        if (samePosition && inGrid) {\n                            item.row = row;\n                            item.col = column;\n                            return;\n                        } else {\n                            // remove from old position\n                            var oldRow = this.grid[item.oldRow];\n                            if (oldRow && oldRow[item.oldColumn] === item) {\n                                delete oldRow[item.oldColumn];\n                            }\n                        }\n                    }\n\n                    item.oldRow = item.row = row;\n                    item.oldColumn = item.col = column;\n\n                    this.moveOverlappingItems(item, ignoreItems);\n\n                    if (!this.grid[row]) {\n                        this.grid[row] = [];\n                    }\n                    this.grid[row][column] = item;\n\n                    if (this.movingItem === item) {\n                        this.floatItemUp(item);\n                    }\n                    this.layoutChanged();\n                };\n\n                /**\n                 * Trade row and column if item1 with item2\n                 *\n                 * @param {object} item1\n                 * @param {object} item2\n                 */\n                this.swapItems = function(item1, item2) {\n                    this.grid[item1.row][item1.col] = item2;\n                    this.grid[item2.row][item2.col] = item1;\n\n                    var item1Row = item1.row;\n                    var item1Col = item1.col;\n                    item1.row = item2.row;\n                    item1.col = item2.col;\n                    item2.row = item1Row;\n                    item2.col = item1Col;\n                };\n\n                /**\n                 * Prevents items from being overlapped\n                 *\n                 * @param {object} item The item that should remain\n                 * @param {array} ignoreItems\n                 */\n                this.moveOverlappingItems = function(item, ignoreItems) {\n                    if (ignoreItems) {\n                        if (ignoreItems.indexOf(item) === -1) {\n                            ignoreItems = ignoreItems.slice(0);\n                            ignoreItems.push(item);\n                        }\n                    } else {\n                        ignoreItems = [item];\n                    }\n                    var overlappingItems = this.getItems(\n                        item.row,\n                        item.col,\n                        item.sizeX,\n                        item.sizeY,\n                        ignoreItems\n                    );\n                    this.moveItemsDown(overlappingItems, item.row + item.sizeY, ignoreItems);\n                };\n\n                /**\n                 * Moves an array of items to a specified row\n                 *\n                 * @param {array} items The items to move\n                 * @param {number} newRow The target row\n                 * @param {array} ignoreItems\n                 */\n                this.moveItemsDown = function(items, newRow, ignoreItems) {\n                    if (!items || items.length === 0) {\n                        return;\n                    }\n                    items.sort(function(a, b) {\n                        return a.row - b.row;\n                    });\n                    ignoreItems = ignoreItems ? ignoreItems.slice(0) : [];\n                    var topRows = {},\n                        item, i, l;\n                    // calculate the top rows in each column\n                    for (i = 0, l = items.length; i < l; ++i) {\n                        item = items[i];\n                        var topRow = topRows[item.col];\n                        if (typeof topRow === 'undefined' || item.row < topRow) {\n                            topRows[item.col] = item.row;\n                        }\n                    }\n                    // move each item down from the top row in its column to the row\n                    for (i = 0, l = items.length; i < l; ++i) {\n                        item = items[i];\n                        var rowsToMove = newRow - topRows[item.col];\n                        this.moveItemDown(item, item.row + rowsToMove, ignoreItems);\n                        ignoreItems.push(item);\n                    }\n                };\n\n                this.moveItemDown = function(item, newRow, ignoreItems) {\n                    if (item.row >= newRow) {\n                        return;\n                    }\n                    while (item.row < newRow) {\n                        ++item.row;\n                        this.moveOverlappingItems(item, ignoreItems);\n                    }\n                    this.putItem(item, item.row, item.col, ignoreItems);\n                };\n\n                /**\n                 * Moves all items up as much as possible\n                 */\n                this.floatItemsUp = function() {\n                    if (this.floating === false) {\n                        return;\n                    }\n                    for (var rowIndex = 0, l = this.grid.length; rowIndex < l; ++rowIndex) {\n                        var columns = this.grid[rowIndex];\n                        if (!columns) {\n                            continue;\n                        }\n                        for (var colIndex = 0, len = columns.length; colIndex < len; ++colIndex) {\n                            var item = columns[colIndex];\n                            if (item) {\n                                this.floatItemUp(item);\n                            }\n                        }\n                    }\n                };\n\n                /**\n                 * Float an item up to the most suitable row\n                 *\n                 * @param {object} item The item to move\n                 */\n                this.floatItemUp = function(item) {\n                    if (this.floating === false) {\n                        return;\n                    }\n                    var colIndex = item.col,\n                        sizeY = item.sizeY,\n                        sizeX = item.sizeX,\n                        bestRow = null,\n                        bestColumn = null,\n                        rowIndex = item.row - 1;\n\n                    while (rowIndex > -1) {\n                        var items = this.getItems(rowIndex, colIndex, sizeX, sizeY, item);\n                        if (items.length !== 0) {\n                            break;\n                        }\n                        bestRow = rowIndex;\n                        bestColumn = colIndex;\n                        --rowIndex;\n                    }\n                    if (bestRow !== null) {\n                        this.putItem(item, bestRow, bestColumn);\n                    }\n                };\n\n                /**\n                 * Update gridsters height\n                 *\n                 * @param {number} plus (Optional) Additional height to add\n                 */\n                this.updateHeight = function(plus) {\n                    var maxHeight = this.minRows;\n                    plus = plus || 0;\n                    for (var rowIndex = this.grid.length; rowIndex >= 0; --rowIndex) {\n                        var columns = this.grid[rowIndex];\n                        if (!columns) {\n                            continue;\n                        }\n                        for (var colIndex = 0, len = columns.length; colIndex < len; ++colIndex) {\n                            if (columns[colIndex]) {\n                                maxHeight = Math.max(maxHeight, rowIndex + plus + columns[colIndex].sizeY);\n                            }\n                        }\n                    }\n                    this.gridHeight = this.maxRows - maxHeight > 0 ? Math.min(this.maxRows, maxHeight) : Math.max(this.maxRows, maxHeight);\n                };\n\n                /**\n                 * Returns the number of rows that will fit in given amount of pixels\n                 *\n                 * @param {number} pixels\n                 * @param {boolean} ceilOrFloor (Optional) Determines rounding method\n                 */\n                this.pixelsToRows = function(pixels, ceilOrFloor) {\n                    if (ceilOrFloor === true) {\n                        return Math.ceil(pixels / this.curRowHeight);\n                    } else if (ceilOrFloor === false) {\n                        return Math.floor(pixels / this.curRowHeight);\n                    }\n\n                    return Math.round(pixels / this.curRowHeight);\n                };\n\n                /**\n                 * Returns the number of columns that will fit in a given amount of pixels\n                 *\n                 * @param {number} pixels\n                 * @param {boolean} ceilOrFloor (Optional) Determines rounding method\n                 * @returns {number} The number of columns\n                 */\n                this.pixelsToColumns = function(pixels, ceilOrFloor) {\n                    if (ceilOrFloor === true) {\n                        return Math.ceil(pixels / this.curColWidth);\n                    } else if (ceilOrFloor === false) {\n                        return Math.floor(pixels / this.curColWidth);\n                    }\n\n                    return Math.round(pixels / this.curColWidth);\n                };\n\n                // unified input handling\n                // adopted from a msdn blogs sample\n                this.unifiedInput = function(target, startEvent, moveEvent, endEvent) {\n                    var lastXYById = {};\n\n                    //  Opera doesn't have Object.keys so we use this wrapper\n                    var numberOfKeys = function(theObject) {\n                        if (Object.keys) {\n                            return Object.keys(theObject).length;\n                        }\n\n                        var n = 0,\n                            key;\n                        for (key in theObject) {\n                            ++n;\n                        }\n\n                        return n;\n                    };\n\n                    //  this calculates the delta needed to convert pageX/Y to offsetX/Y because offsetX/Y don't exist in the TouchEvent object or in Firefox's MouseEvent object\n                    var computeDocumentToElementDelta = function(theElement) {\n                        var elementLeft = 0;\n                        var elementTop = 0;\n                        var oldIEUserAgent = navigator.userAgent.match(/\\bMSIE\\b/);\n\n                        for (var offsetElement = theElement; offsetElement != null; offsetElement = offsetElement.offsetParent) {\n                            //  the following is a major hack for versions of IE less than 8 to avoid an apparent problem on the IEBlog with double-counting the offsets\n                            //  this may not be a general solution to IE7's problem with offsetLeft/offsetParent\n                            if (oldIEUserAgent &&\n                                (!document.documentMode || document.documentMode < 8) &&\n                                offsetElement.currentStyle.position === 'relative' && offsetElement.offsetParent && offsetElement.offsetParent.currentStyle.position === 'relative' && offsetElement.offsetLeft === offsetElement.offsetParent.offsetLeft) {\n                                // add only the top\n                                elementTop += offsetElement.offsetTop;\n                            } else {\n                                elementLeft += offsetElement.offsetLeft;\n                                elementTop += offsetElement.offsetTop;\n                            }\n                        }\n\n                        return {\n                            x: elementLeft,\n                            y: elementTop\n                        };\n                    };\n\n                    //  cache the delta from the document to our event target (reinitialized each mousedown/MSPointerDown/touchstart)\n                    var documentToTargetDelta = computeDocumentToElementDelta(target);\n\n                    //  common event handler for the mouse/pointer/touch models and their down/start, move, up/end, and cancel events\n                    var doEvent = function(theEvtObj) {\n\n                        if (theEvtObj.type === 'mousemove' && numberOfKeys(lastXYById) === 0) {\n                            return;\n                        }\n\n                        var prevent = true;\n\n                        var pointerList = theEvtObj.changedTouches ? theEvtObj.changedTouches : [theEvtObj];\n                        for (var i = 0; i < pointerList.length; ++i) {\n                            var pointerObj = pointerList[i];\n                            var pointerId = (typeof pointerObj.identifier !== 'undefined') ? pointerObj.identifier : (typeof pointerObj.pointerId !== 'undefined') ? pointerObj.pointerId : 1;\n\n                            //  use the pageX/Y coordinates to compute target-relative coordinates when we have them (in ie < 9, we need to do a little work to put them there)\n                            if (typeof pointerObj.pageX === 'undefined') {\n                                //  initialize assuming our source element is our target\n                                pointerObj.pageX = pointerObj.offsetX + documentToTargetDelta.x;\n                                pointerObj.pageY = pointerObj.offsetY + documentToTargetDelta.y;\n\n                                if (pointerObj.srcElement.offsetParent === target && document.documentMode && document.documentMode === 8 && pointerObj.type === 'mousedown') {\n                                    //  source element is a child piece of VML, we're in IE8, and we've not called setCapture yet - add the origin of the source element\n                                    pointerObj.pageX += pointerObj.srcElement.offsetLeft;\n                                    pointerObj.pageY += pointerObj.srcElement.offsetTop;\n                                } else if (pointerObj.srcElement !== target && !document.documentMode || document.documentMode < 8) {\n                                    //  source element isn't the target (most likely it's a child piece of VML) and we're in a version of IE before IE8 -\n                                    //  the offsetX/Y values are unpredictable so use the clientX/Y values and adjust by the scroll offsets of its parents\n                                    //  to get the document-relative coordinates (the same as pageX/Y)\n                                    var sx = -2,\n                                        sy = -2; // adjust for old IE's 2-pixel border\n                                    for (var scrollElement = pointerObj.srcElement; scrollElement !== null; scrollElement = scrollElement.parentNode) {\n                                        sx += scrollElement.scrollLeft ? scrollElement.scrollLeft : 0;\n                                        sy += scrollElement.scrollTop ? scrollElement.scrollTop : 0;\n                                    }\n\n                                    pointerObj.pageX = pointerObj.clientX + sx;\n                                    pointerObj.pageY = pointerObj.clientY + sy;\n                                }\n                            }\n\n\n                            var pageX = pointerObj.pageX;\n                            var pageY = pointerObj.pageY;\n\n                            if (theEvtObj.type.match(/(start|down)$/i)) {\n                                //  clause for processing MSPointerDown, touchstart, and mousedown\n\n                                //  refresh the document-to-target delta on start in case the target has moved relative to document\n                                documentToTargetDelta = computeDocumentToElementDelta(target);\n\n                                //  protect against failing to get an up or end on this pointerId\n                                if (lastXYById[pointerId]) {\n                                    if (endEvent) {\n                                        endEvent({\n                                            target: theEvtObj.target,\n                                            which: theEvtObj.which,\n                                            pointerId: pointerId,\n                                            pageX: pageX,\n                                            pageY: pageY\n                                        });\n                                    }\n\n                                    delete lastXYById[pointerId];\n                                }\n\n                                if (startEvent) {\n                                    if (prevent) {\n                                        prevent = startEvent({\n                                            target: theEvtObj.target,\n                                            which: theEvtObj.which,\n                                            pointerId: pointerId,\n                                            pageX: pageX,\n                                            pageY: pageY\n                                        });\n                                    }\n                                }\n\n                                //  init last page positions for this pointer\n                                lastXYById[pointerId] = {\n                                    x: pageX,\n                                    y: pageY\n                                };\n\n                                // IE pointer model\n                                if (target.msSetPointerCapture) {\n                                    target.msSetPointerCapture(pointerId);\n                                } else if (theEvtObj.type === 'mousedown' && numberOfKeys(lastXYById) === 1) {\n                                    if (useSetReleaseCapture) {\n                                        target.setCapture(true);\n                                    } else {\n                                        document.addEventListener('mousemove', doEvent, false);\n                                        document.addEventListener('mouseup', doEvent, false);\n                                    }\n                                }\n                            } else if (theEvtObj.type.match(/move$/i)) {\n                                //  clause handles mousemove, MSPointerMove, and touchmove\n\n                                if (lastXYById[pointerId] && !(lastXYById[pointerId].x === pageX && lastXYById[pointerId].y === pageY)) {\n                                    //  only extend if the pointer is down and it's not the same as the last point\n\n                                    if (moveEvent && prevent) {\n                                        prevent = moveEvent({\n                                            target: theEvtObj.target,\n                                            which: theEvtObj.which,\n                                            pointerId: pointerId,\n                                            pageX: pageX,\n                                            pageY: pageY\n                                        });\n                                    }\n\n                                    //  update last page positions for this pointer\n                                    lastXYById[pointerId].x = pageX;\n                                    lastXYById[pointerId].y = pageY;\n                                }\n                            } else if (lastXYById[pointerId] && theEvtObj.type.match(/(up|end|cancel)$/i)) {\n                                //  clause handles up/end/cancel\n\n                                if (endEvent && prevent) {\n                                    prevent = endEvent({\n                                        target: theEvtObj.target,\n                                        which: theEvtObj.which,\n                                        pointerId: pointerId,\n                                        pageX: pageX,\n                                        pageY: pageY\n                                    });\n                                }\n\n                                //  delete last page positions for this pointer\n                                delete lastXYById[pointerId];\n\n                                //  in the Microsoft pointer model, release the capture for this pointer\n                                //  in the mouse model, release the capture or remove document-level event handlers if there are no down points\n                                //  nothing is required for the iOS touch model because capture is implied on touchstart\n                                if (target.msReleasePointerCapture) {\n                                    target.msReleasePointerCapture(pointerId);\n                                } else if (theEvtObj.type === 'mouseup' && numberOfKeys(lastXYById) === 0) {\n                                    if (useSetReleaseCapture) {\n                                        target.releaseCapture();\n                                    } else {\n                                        document.removeEventListener('mousemove', doEvent, false);\n                                        document.removeEventListener('mouseup', doEvent, false);\n                                    }\n                                }\n                            }\n                        }\n\n                        if (prevent) {\n                            if (theEvtObj.preventDefault) {\n                                theEvtObj.preventDefault();\n                            }\n\n                            if (theEvtObj.preventManipulation) {\n                                theEvtObj.preventManipulation();\n                            }\n\n                            if (theEvtObj.preventMouseEvent) {\n                                theEvtObj.preventMouseEvent();\n                            }\n                        }\n                    };\n\n                    var useSetReleaseCapture = false;\n                    // saving the settings for contentZooming and touchaction before activation\n                    var contentZooming, msTouchAction;\n\n                    this.enable = function() {\n\n                        if (window.navigator.msPointerEnabled) {\n                            //  Microsoft pointer model\n                            target.addEventListener('MSPointerDown', doEvent, false);\n                            target.addEventListener('MSPointerMove', doEvent, false);\n                            target.addEventListener('MSPointerUp', doEvent, false);\n                            target.addEventListener('MSPointerCancel', doEvent, false);\n\n                            //  css way to prevent panning in our target area\n                            if (typeof target.style.msContentZooming !== 'undefined') {\n                                contentZooming = target.style.msContentZooming;\n                                target.style.msContentZooming = 'none';\n                            }\n\n                            //  new in Windows Consumer Preview: css way to prevent all built-in touch actions on our target\n                            //  without this, you cannot touch draw on the element because IE will intercept the touch events\n                            if (typeof target.style.msTouchAction !== 'undefined') {\n                                msTouchAction = target.style.msTouchAction;\n                                target.style.msTouchAction = 'none';\n                            }\n                        } else if (target.addEventListener) {\n                            //  iOS touch model\n                            target.addEventListener('touchstart', doEvent, false);\n                            target.addEventListener('touchmove', doEvent, false);\n                            target.addEventListener('touchend', doEvent, false);\n                            target.addEventListener('touchcancel', doEvent, false);\n\n                            //  mouse model\n                            target.addEventListener('mousedown', doEvent, false);\n\n                            //  mouse model with capture\n                            //  rejecting gecko because, unlike ie, firefox does not send events to target when the mouse is outside target\n                            if (target.setCapture && !window.navigator.userAgent.match(/\\bGecko\\b/)) {\n                                useSetReleaseCapture = true;\n\n                                target.addEventListener('mousemove', doEvent, false);\n                                target.addEventListener('mouseup', doEvent, false);\n                            }\n                        } else if (target.attachEvent && target.setCapture) {\n                            //  legacy IE mode - mouse with capture\n                            useSetReleaseCapture = true;\n                            target.attachEvent('onmousedown', function() {\n                                doEvent(window.event);\n                                window.event.returnValue = false;\n                                return false;\n                            });\n                            target.attachEvent('onmousemove', function() {\n                                doEvent(window.event);\n                                window.event.returnValue = false;\n                                return false;\n                            });\n                            target.attachEvent('onmouseup', function() {\n                                doEvent(window.event);\n                                window.event.returnValue = false;\n                                return false;\n                            });\n                        }\n                    };\n\n                    this.disable = function() {\n                        if (window.navigator.msPointerEnabled) {\n                            //  Microsoft pointer model\n                            target.removeEventListener('MSPointerDown', doEvent, false);\n                            target.removeEventListener('MSPointerMove', doEvent, false);\n                            target.removeEventListener('MSPointerUp', doEvent, false);\n                            target.removeEventListener('MSPointerCancel', doEvent, false);\n\n                            //  reset zooming to saved value\n                            if (contentZooming) {\n                                target.style.msContentZooming = contentZooming;\n                            }\n\n                            // reset touch action setting\n                            if (msTouchAction) {\n                                target.style.msTouchAction = msTouchAction;\n                            }\n                        } else if (target.removeEventListener) {\n                            //  iOS touch model\n                            target.removeEventListener('touchstart', doEvent, false);\n                            target.removeEventListener('touchmove', doEvent, false);\n                            target.removeEventListener('touchend', doEvent, false);\n                            target.removeEventListener('touchcancel', doEvent, false);\n\n                            //  mouse model\n                            target.removeEventListener('mousedown', doEvent, false);\n\n                            //  mouse model with capture\n                            //  rejecting gecko because, unlike ie, firefox does not send events to target when the mouse is outside target\n                            if (target.setCapture && !window.navigator.userAgent.match(/\\bGecko\\b/)) {\n                                useSetReleaseCapture = true;\n\n                                target.removeEventListener('mousemove', doEvent, false);\n                                target.removeEventListener('mouseup', doEvent, false);\n                            }\n                        } else if (target.detachEvent && target.setCapture) {\n                            //  legacy IE mode - mouse with capture\n                            useSetReleaseCapture = true;\n                            target.detachEvent('onmousedown');\n                            target.detachEvent('onmousemove');\n                            target.detachEvent('onmouseup');\n                        }\n                    };\n\n                    return this;\n                };\n\n            }\n        ])\n\n    /**\n     * The gridster directive\n     *\n     * @param {object} $parse\n     * @param {object} $timeout\n     */\n        .directive('gridster', ['$timeout', '$rootScope', '$window',\n            function($timeout, $rootScope, $window) {\n                return {\n                    restrict: 'EAC',\n                    // without transclude, some child items may lose their parent scope\n                    transclude: true,\n                    replace: true,\n                    template: '<div ng-class=\"gridsterClass()\"><div ng-style=\"previewStyle()\" class=\"gridster-item gridster-preview-holder\"></div><div class=\"gridster-content\" ng-transclude></div></div>',\n                    controller: 'GridsterCtrl',\n                    controllerAs: 'gridster',\n                    scope: {\n                        config: '=?gridster'\n                    },\n                    compile: function() {\n\n                        return function(scope, $elem, attrs, gridster) {\n                            gridster.loaded = false;\n\n                            scope.gridsterClass = function() {\n                                return {\n                                    gridster: true,\n                                    'gridster-desktop': !gridster.isMobile,\n                                    'gridster-mobile': gridster.isMobile,\n                                    'gridster-loaded': gridster.loaded\n                                };\n                            };\n\n                            /**\n                             * @returns {Object} style object for preview element\n                             */\n                            scope.previewStyle = function() {\n                                if (!gridster.movingItem) {\n                                    return {\n                                        display: 'none'\n                                    };\n                                }\n\n                                return {\n                                    display: 'block',\n                                    height: (gridster.movingItem.sizeY * gridster.curRowHeight - gridster.margins[0]) + 'px',\n                                    width: (gridster.movingItem.sizeX * gridster.curColWidth - gridster.margins[1]) + 'px',\n                                    top: (gridster.movingItem.row * gridster.curRowHeight + (gridster.outerMargin ? gridster.margins[0] : 0)) + 'px',\n                                    left: (gridster.movingItem.col * gridster.curColWidth + (gridster.outerMargin ? gridster.margins[1] : 0)) + 'px'\n                                };\n                            };\n\n                            var refresh = function() {\n                                gridster.setOptions(scope.config);\n\n                                // resolve \"auto\" & \"match\" values\n                                if (gridster.width === 'auto') {\n                                    gridster.curWidth = $elem[0].offsetWidth || parseInt($elem.css('width'), 10);\n                                } else {\n                                    gridster.curWidth = gridster.width;\n                                }\n\n                                if (gridster.colWidth === 'auto') {\n                                    gridster.curColWidth = (gridster.curWidth + (gridster.outerMargin ? -gridster.margins[1] : gridster.margins[1])) / gridster.columns;\n                                } else {\n                                    gridster.curColWidth = gridster.colWidth;\n                                }\n\n                                gridster.curRowHeight = gridster.rowHeight;\n                                if (typeof gridster.rowHeight === 'string') {\n                                    if (gridster.rowHeight === 'match') {\n                                        gridster.curRowHeight = Math.round(gridster.curColWidth);\n                                    } else if (gridster.rowHeight.indexOf('*') !== -1) {\n                                        gridster.curRowHeight = Math.round(gridster.curColWidth * gridster.rowHeight.replace('*', '').replace(' ', ''));\n                                    } else if (gridster.rowHeight.indexOf('/') !== -1) {\n                                        gridster.curRowHeight = Math.round(gridster.curColWidth / gridster.rowHeight.replace('/', '').replace(' ', ''));\n                                    }\n                                }\n\n                                gridster.isMobile = gridster.mobileModeEnabled && gridster.curWidth <= gridster.mobileBreakPoint;\n\n                                // loop through all items and reset their CSS\n                                for (var rowIndex = 0, l = gridster.grid.length; rowIndex < l; ++rowIndex) {\n                                    var columns = gridster.grid[rowIndex];\n                                    if (!columns) {\n                                        continue;\n                                    }\n\n                                    for (var colIndex = 0, len = columns.length; colIndex < len; ++colIndex) {\n                                        if (columns[colIndex]) {\n                                            var item = columns[colIndex];\n                                            item.setElementPosition();\n                                            item.setElementSizeY();\n                                            item.setElementSizeX();\n                                        }\n                                    }\n                                }\n\n                                updateHeight();\n                            };\n\n                            // update grid items on config changes\n                            scope.$watch('config', refresh, true);\n\n                            scope.$watch('config.draggable', function() {\n                                $rootScope.$broadcast('gridster-draggable-changed');\n                            }, true);\n\n                            scope.$watch('config.resizable', function() {\n                                $rootScope.$broadcast('gridster-resizable-changed');\n                            }, true);\n\n                            var updateHeight = function() {\n                                $elem.css('height', (gridster.gridHeight * gridster.curRowHeight) + (gridster.outerMargin ? gridster.margins[0] : -gridster.margins[0]) + 'px');\n                            };\n\n                            scope.$watch('gridster.gridHeight', updateHeight);\n\n                            scope.$watch('gridster.movingItem', function() {\n                                gridster.updateHeight(gridster.movingItem ? gridster.movingItem.sizeY : 0);\n                            });\n\n                            var prevWidth = $elem[0].offsetWidth || parseInt($elem.css('width'), 10);\n\n                            function resize() {\n                                var width = $elem[0].offsetWidth || parseInt($elem.css('width'), 10);\n\n                                if (!width || width === prevWidth || gridster.movingItem) {\n                                    return;\n                                }\n                                prevWidth = width;\n\n                                if (gridster.loaded) {\n                                    $elem.removeClass('gridster-loaded');\n                                }\n\n                                refresh();\n\n                                if (gridster.loaded) {\n                                    $elem.addClass('gridster-loaded');\n                                }\n\n                                scope.$parent.$broadcast('gridster-resized', [width, $elem.offsetHeight]);\n                            }\n\n                            // track element width changes any way we can\n                            function onResize() {\n                                resize();\n                                $timeout(function() {\n                                    scope.$apply();\n                                });\n                            }\n                            if (typeof $elem.resize === 'function') {\n                                $elem.resize(onResize);\n                            }\n                            var $win = angular.element($window);\n                            $win.on('resize', onResize);\n\n                            scope.$watch(function() {\n                                return $elem[0].offsetWidth || parseInt($elem.css('width'), 10);\n                            }, resize);\n\n                            // be sure to cleanup\n                            scope.$on('$destroy', function() {\n                                gridster.destroy();\n                                $win.off('resize', onResize);\n                            });\n\n                            // allow a little time to place items before floating up\n                            $timeout(function() {\n                                scope.$watch('gridster.floating', function() {\n                                    gridster.floatItemsUp();\n                                });\n                                gridster.loaded = true;\n                            }, 100);\n\n\n\n                            // Custom code\n\n                            /**\n                             * Callback called when starting to drag from palette to canvas.\n                             */\n                            $rootScope.startDragCallback = function (event, ui) {\n                                $timeout(function () {\n                                    var fieldId = event.target.id;\n                                    var fieldType;\n\n                                    var colspan = 1;\n                                    if (fieldId === 'group' || fieldId === 'dynamic-table') {\n                                        colspan = 2;\n                                    }\n\n                                    var numberOfRows = 1;\n                                    if (fieldId === 'multi-line-text') {\n                                        numberOfRows = 2;\n                                    } else if (fieldId === 'dynamic-table') {\n                                        numberOfRows = 2;\n                                    }\n\n                                    scope.startDragItem = {\n                                        type: fieldId,\n                                        fieldType: fieldType,\n                                        name: 'Label',\n                                        required: false,\n                                        readOnly: false,\n                                        sizeX: colspan,\n                                        sizeY: numberOfRows,\n                                        row: -1,\n                                        col: -1\n                                    };\n\n                                    if (fieldId === 'radio-buttons' || fieldId === 'dropdown') {\n                                        scope.startDragItem.options = [\n                                            {name: 'Option 1'}\n                                        ];\n                                    }\n\n                                }, 0);\n                            };\n\n                            /**\n                             * Callback called when stopping to drag from palette to canvas.\n                             */\n                            $rootScope.dropCallback = function (event, ui) {\n                                $timeout(function () {\n                                    gridster.movingItem = null;\n                                    var offset = jQuery($elem[0]).offset();\n                                    var row = gridster.pixelsToRows(event.clientY - offset.top, true) - 1;\n                                    var column = gridster.pixelsToColumns(event.clientX - offset.left, true) - 1;\n                                    if (row >= 0 && column >= 0) {\n\n                                        scope.startDragItem.row = row;\n                                        scope.startDragItem.col = column;\n                                    }\n                                }, 0);\n                            };\n\n                            /**\n                             * Callback called during dragging from palette to canvas.\n                             */\n                            $rootScope.dragCallback = function (event, ui) {\n\n                                    var offset = jQuery($elem[0]).offset();\n                                    var row = gridster.pixelsToRows(event.clientY - offset.top, true) - 1;\n                                    var column = gridster.pixelsToColumns(event.clientX - offset.left, true) - 1;\n\n                                    if (!scope.startDragItem) {\n                                        return;\n                                    }\n\n                                    if (scope.startDragItem.row === row && scope.startDragItem.col === column) {\n                                        return;\n                                    }\n\n                                    if ( ((scope.startDragItem.row === -1 || scope.startDragItem.col === -1) && row >= 0 && column >= 0)\n                                        || (scope.startDragItem.row >= 0 && scope.startDragItem.col >= 0 && (row < 0 || column < 0)) ) {\n                                        $timeout(function () {\n                                            if ((scope.startDragItem.row === -1 || scope.startDragItem.col === -1) && row >= 0 && column >= 0) {\n                                                scope.$parent.formItems.push(scope.startDragItem);\n\n                                                gridster.movingItem = scope.startDragItem;\n                                                gridster.updateHeight(1);\n                                            }\n\n                                            if (scope.startDragItem.row >= 0 && scope.startDragItem.col >= 0 && (row < 0 || column < 0)) {\n                                                scope.$parent.formItems.pop();\n                                                gridster.movingItem = null;\n                                            }\n\n\n                                        }, 0);\n                                    }\n\n                                $timeout(function () {\n                                    scope.startDragItem.row = row;\n                                    scope.startDragItem.col = column;\n                                }, 0);\n\n                            };\n\n                            // END custom code\n\n\n                        };\n                    }\n                };\n            }\n        ])\n\n        .controller('GridsterItemCtrl', function() {\n            this.$element = null;\n            this.gridster = null;\n            this.row = null;\n            this.col = null;\n            this.sizeX = null;\n            this.sizeY = null;\n            this.minSizeX = 0;\n            this.minSizeY = 0;\n            this.maxSizeX = null;\n            this.maxSizeY = null;\n\n            this.init = function($element, gridster) {\n                this.$element = $element;\n                this.gridster = gridster;\n                this.sizeX = gridster.defaultSizeX;\n                this.sizeY = gridster.defaultSizeY;\n            };\n\n            this.destroy = function() {\n                this.gridster = null;\n                this.$element = null;\n            };\n\n            /**\n             * Returns the items most important attributes\n             */\n            this.toJSON = function() {\n                return {\n                    row: this.row,\n                    col: this.col,\n                    sizeY: this.sizeY,\n                    sizeX: this.sizeX\n                };\n            };\n\n            this.isMoving = function() {\n                return this.gridster.movingItem === this;\n            };\n\n            /**\n             * Set the items position\n             *\n             * @param {number} row\n             * @param {number} column\n             */\n            this.setPosition = function(row, column) {\n                this.gridster.putItem(this, row, column);\n\n                if (!this.isMoving()) {\n                    this.setElementPosition();\n                }\n            };\n\n            /**\n             * Sets a specified size property\n             *\n             * @param {string} key Can be either \"x\" or \"y\"\n             * @param {number} value The size amount\n             */\n            this.setSize = function(key, value, preventMove) {\n                key = key.toUpperCase();\n                var camelCase = 'size' + key,\n                    titleCase = 'Size' + key;\n                if (value === '') {\n                    return;\n                }\n                value = parseInt(value, 10);\n                if (isNaN(value) || value === 0) {\n                    value = this.gridster['default' + titleCase];\n                }\n                var max = key === 'X' ? this.gridster.columns : this.gridster.maxRows;\n                if (this['max' + titleCase]) {\n                    max = Math.min(this['max' + titleCase], max);\n                }\n                if (this.gridster['max' + titleCase]) {\n                    max = Math.min(this.gridster['max' + titleCase], max);\n                }\n                if (key === 'X' && this.cols) {\n                    max -= this.cols;\n                } else if (key === 'Y' && this.rows) {\n                    max -= this.rows;\n                }\n\n                var min = 0;\n                if (this['min' + titleCase]) {\n                    min = Math.max(this['min' + titleCase], min);\n                }\n                if (this.gridster['min' + titleCase]) {\n                    min = Math.max(this.gridster['min' + titleCase], min);\n                }\n\n                value = Math.max(Math.min(value, max), min);\n\n                var changed = (this[camelCase] !== value || (this['old' + titleCase] && this['old' + titleCase] !== value));\n                this['old' + titleCase] = this[camelCase] = value;\n\n                if (!this.isMoving()) {\n                    this['setElement' + titleCase]();\n                }\n                if (!preventMove && changed) {\n                    this.gridster.moveOverlappingItems(this);\n                    this.gridster.layoutChanged();\n                }\n\n                return changed;\n            };\n\n            /**\n             * Sets the items sizeY property\n             *\n             * @param {number} rows\n             */\n            this.setSizeY = function(rows, preventMove) {\n                return this.setSize('Y', rows, preventMove);\n            };\n\n            /**\n             * Sets the items sizeX property\n             *\n             * @param {number} rows\n             */\n            this.setSizeX = function(columns, preventMove) {\n                return this.setSize('X', columns, preventMove);\n            };\n\n            /**\n             * Sets an elements position on the page\n             *\n             * @param {number} row\n             * @param {number} column\n             */\n            this.setElementPosition = function() {\n                if (this.gridster.isMobile) {\n                    this.$element.css({\n                        marginLeft: this.gridster.margins[0] + 'px',\n                        marginRight: this.gridster.margins[0] + 'px',\n                        marginTop: this.gridster.margins[1] + 'px',\n                        marginBottom: this.gridster.margins[1] + 'px',\n                        top: '',\n                        left: ''\n                    });\n                } else {\n                    this.$element.css({\n                        margin: 0,\n                        top: (this.row * this.gridster.curRowHeight + (this.gridster.outerMargin ? this.gridster.margins[0] : 0)) + 'px',\n                        left: (this.col * this.gridster.curColWidth + (this.gridster.outerMargin ? this.gridster.margins[1] : 0)) + 'px'\n                    });\n                }\n            };\n\n            /**\n             * Sets an elements height\n             */\n            this.setElementSizeY = function() {\n                if (this.gridster.isMobile && !this.gridster.saveGridItemCalculatedHeightInMobile) {\n                    this.$element.css('height', '');\n                } else {\n                    this.$element.css('height', (this.sizeY * this.gridster.curRowHeight - this.gridster.margins[0]) + 'px');\n                }\n            };\n\n            /**\n             * Sets an elements width\n             */\n            this.setElementSizeX = function() {\n                if (this.gridster.isMobile) {\n                    this.$element.css('width', '');\n                } else {\n                    this.$element.css('width', (this.sizeX * this.gridster.curColWidth - this.gridster.margins[1]) + 'px');\n                }\n            };\n\n            /**\n             * Gets an element's width\n             */\n            this.getElementSizeX = function() {\n                return (this.sizeX * this.gridster.curColWidth - this.gridster.margins[1]);\n            };\n\n            /**\n             * Gets an element's height\n             */\n            this.getElementSizeY = function() {\n                return (this.sizeY * this.gridster.curRowHeight - this.gridster.margins[0]);\n            };\n\n        })\n\n        .factory('GridsterDraggable', ['$document', '$timeout', '$window',\n            function($document, $timeout, $window) {\n                function GridsterDraggable($el, scope, gridster, item, itemOptions) {\n\n                    var elmX, elmY, elmW, elmH,\n\n                        mouseX = 0,\n                        mouseY = 0,\n                        lastMouseX = 0,\n                        lastMouseY = 0,\n                        mOffX = 0,\n                        mOffY = 0,\n\n                        minTop = 0,\n                        maxTop = 9999,\n                        minLeft = 0,\n                        realdocument = $document[0];\n\n                    var originalCol, originalRow;\n                    var inputTags = ['select', 'input', 'textarea', 'button'];\n\n                    function mouseDown(e) {\n                        if (inputTags.indexOf(e.target.nodeName.toLowerCase()) !== -1) {\n                            return false;\n                        }\n\n                        // exit, if a resize handle was hit\n                        if (angular.element(e.target).hasClass('gridster-item-resizable-handler')) {\n                            return false;\n                        }\n\n                        // exit, if the target has it's own click event\n                        if (angular.element(e.target).attr('onclick') || angular.element(e.target).attr('ng-click')) {\n                            return false;\n                        }\n\n                        switch (e.which) {\n                            case 1:\n                                // left mouse button\n                                break;\n                            case 2:\n                            case 3:\n                                // right or middle mouse button\n                                return;\n                        }\n\n                        lastMouseX = e.pageX;\n                        lastMouseY = e.pageY;\n\n                        elmX = parseInt($el.css('left'), 10);\n                        elmY = parseInt($el.css('top'), 10);\n                        elmW = $el[0].offsetWidth;\n                        elmH = $el[0].offsetHeight;\n\n                        originalCol = item.col;\n                        originalRow = item.row;\n\n                        dragStart(e);\n\n                        return true;\n                    }\n\n                    function mouseMove(e) {\n                        if (!$el.hasClass('gridster-item-moving') || $el.hasClass('gridster-item-resizing')) {\n                            return false;\n                        }\n\n                        var maxLeft = gridster.curWidth - 1;\n\n                        // Get the current mouse position.\n                        mouseX = e.pageX;\n                        mouseY = e.pageY;\n\n                        // Get the deltas\n                        var diffX = mouseX - lastMouseX + mOffX;\n                        var diffY = mouseY - lastMouseY + mOffY;\n                        mOffX = mOffY = 0;\n\n                        // Update last processed mouse positions.\n                        lastMouseX = mouseX;\n                        lastMouseY = mouseY;\n\n                        var dX = diffX,\n                            dY = diffY;\n                        if (elmX + dX < minLeft) {\n                            diffX = minLeft - elmX;\n                            mOffX = dX - diffX;\n                        } else if (elmX + elmW + dX > maxLeft) {\n                            diffX = maxLeft - elmX - elmW;\n                            mOffX = dX - diffX;\n                        }\n\n                        if (elmY + dY < minTop) {\n                            diffY = minTop - elmY;\n                            mOffY = dY - diffY;\n                        } else if (elmY + elmH + dY > maxTop) {\n                            diffY = maxTop - elmY - elmH;\n                            mOffY = dY - diffY;\n                        }\n                        elmX += diffX;\n                        elmY += diffY;\n\n                        // set new position\n                        $el.css({\n                            'top': elmY + 'px',\n                            'left': elmX + 'px'\n                        });\n\n                        drag(e);\n\n                        return true;\n                    }\n\n                    function mouseUp(e) {\n                        if (!$el.hasClass('gridster-item-moving') || $el.hasClass('gridster-item-resizing')) {\n                            return false;\n                        }\n\n                        mOffX = mOffY = 0;\n\n                        dragStop(e);\n\n                        return true;\n                    }\n\n                    function dragStart(event) {\n                        $el.addClass('gridster-item-moving');\n                        gridster.movingItem = item;\n\n                        gridster.updateHeight(item.sizeY);\n                        scope.$apply(function() {\n                            if (gridster.draggable && gridster.draggable.start) {\n                                gridster.draggable.start(event, $el, itemOptions);\n                            }\n                        });\n                    }\n\n                    function drag(event) {\n                        var oldRow = item.row,\n                            oldCol = item.col,\n                            hasCallback = gridster.draggable && gridster.draggable.drag,\n                            scrollSensitivity = gridster.draggable.scrollSensitivity,\n                            scrollSpeed = gridster.draggable.scrollSpeed;\n\n                        var row = gridster.pixelsToRows(elmY);\n                        var col = gridster.pixelsToColumns(elmX);\n\n                        var itemsInTheWay = gridster.getItems(row, col, item.sizeX, item.sizeY, item);\n                        var hasItemsInTheWay = itemsInTheWay.length !== 0;\n\n                        if (gridster.swapping === true && hasItemsInTheWay) {\n                            var boundingBoxItem = gridster.getBoundingBox(itemsInTheWay);\n                            var sameSize = boundingBoxItem.sizeX === item.sizeX && boundingBoxItem.sizeY === item.sizeY;\n                            var sameRow = boundingBoxItem.row === row;\n                            var sameCol = boundingBoxItem.col === col;\n                            var samePosition = sameRow && sameCol;\n                            var inline = sameRow || sameCol;\n\n                            if (sameSize && itemsInTheWay.length === 1) {\n                                if (samePosition) {\n                                    gridster.swapItems(item, itemsInTheWay[0]);\n                                } else if (inline) {\n                                    return;\n                                }\n                            } else if (boundingBoxItem.sizeX <= item.sizeX && boundingBoxItem.sizeY <= item.sizeY && inline) {\n                                var emptyRow = item.row <= row ? item.row : row + item.sizeY;\n                                var emptyCol = item.col <= col ? item.col : col + item.sizeX;\n                                var rowOffset = emptyRow - boundingBoxItem.row;\n                                var colOffset = emptyCol - boundingBoxItem.col;\n\n                                for (var i = 0, l = itemsInTheWay.length; i < l; ++i) {\n                                    var itemInTheWay = itemsInTheWay[i];\n\n                                    var itemsInFreeSpace = gridster.getItems(\n                                            itemInTheWay.row + rowOffset,\n                                            itemInTheWay.col + colOffset,\n                                        itemInTheWay.sizeX,\n                                        itemInTheWay.sizeY,\n                                        item\n                                    );\n\n                                    if (itemsInFreeSpace.length === 0) {\n                                        gridster.putItem(itemInTheWay, itemInTheWay.row + rowOffset, itemInTheWay.col + colOffset);\n                                    }\n                                }\n                            }\n                        }\n\n                        if (gridster.pushing !== false || !hasItemsInTheWay) {\n                            item.row = row;\n                            item.col = col;\n                        }\n\n                        if (event.pageY - realdocument.body.scrollTop < scrollSensitivity) {\n                            realdocument.body.scrollTop = realdocument.body.scrollTop - scrollSpeed;\n                        } else if ($window.innerHeight - (event.pageY - realdocument.body.scrollTop) < scrollSensitivity) {\n                            realdocument.body.scrollTop = realdocument.body.scrollTop + scrollSpeed;\n                        }\n\n                        if (event.pageX - realdocument.body.scrollLeft < scrollSensitivity) {\n                            realdocument.body.scrollLeft = realdocument.body.scrollLeft - scrollSpeed;\n                        } else if ($window.innerWidth - (event.pageX - realdocument.body.scrollLeft) < scrollSensitivity) {\n                            realdocument.body.scrollLeft = realdocument.body.scrollLeft + scrollSpeed;\n                        }\n\n                        if (hasCallback || oldRow !== item.row || oldCol !== item.col) {\n                            scope.$apply(function() {\n                                if (hasCallback) {\n                                    gridster.draggable.drag(event, $el, itemOptions);\n                                }\n                            });\n                        }\n                    }\n\n                    function dragStop(event) {\n                        $el.removeClass('gridster-item-moving');\n                        var row = gridster.pixelsToRows(elmY);\n                        var col = gridster.pixelsToColumns(elmX);\n                        if (gridster.pushing !== false || gridster.getItems(row, col, item.sizeX, item.sizeY, item).length === 0) {\n                            item.row = row;\n                            item.col = col;\n                        }\n                        gridster.movingItem = null;\n                        item.setPosition(item.row, item.col);\n\n                        scope.$apply(function() {\n                            if (gridster.draggable && gridster.draggable.stop) {\n                                gridster.draggable.stop(event, $el, itemOptions);\n                            }\n                        });\n                    }\n\n                    var enabled = false;\n                    var $dragHandle = null;\n                    var unifiedInput;\n\n                    this.enable = function() {\n                        var self = this;\n                        // disable and timeout required for some template rendering\n                        $timeout(function() {\n                            self.disable();\n\n                            if (gridster.draggable && gridster.draggable.handle) {\n                                $dragHandle = angular.element($el[0].querySelector(gridster.draggable.handle));\n                                if ($dragHandle.length === 0) {\n                                    // fall back to element if handle not found...\n                                    $dragHandle = $el;\n                                }\n                            } else {\n                                $dragHandle = $el;\n                            }\n\n                            unifiedInput = new gridster.unifiedInput($dragHandle[0], mouseDown, mouseMove, mouseUp);\n                            unifiedInput.enable();\n\n                            enabled = true;\n                        });\n                    };\n\n                    this.disable = function() {\n                        if (!enabled) {\n                            return;\n                        }\n\n                        unifiedInput.disable();\n                        unifiedInput = undefined;\n                        enabled = false;\n                    };\n\n                    this.toggle = function(enabled) {\n                        if (enabled) {\n                            this.enable();\n                        } else {\n                            this.disable();\n                        }\n                    };\n\n                    this.destroy = function() {\n                        this.disable();\n                    };\n                }\n\n                return GridsterDraggable;\n            }\n        ])\n\n        .factory('GridsterResizable', [\n            function() {\n                function GridsterResizable($el, scope, gridster, item, itemOptions) {\n\n                    function ResizeHandle(handleClass) {\n\n                        var hClass = handleClass;\n\n                        var elmX, elmY, elmW, elmH,\n\n                            mouseX = 0,\n                            mouseY = 0,\n                            lastMouseX = 0,\n                            lastMouseY = 0,\n                            mOffX = 0,\n                            mOffY = 0,\n\n                            minTop = 0,\n                            maxTop = 9999,\n                            minLeft = 0;\n\n                        var getMinHeight = function() {\n                            return gridster.curRowHeight - gridster.margins[0];\n                        };\n                        var getMinWidth = function() {\n                            return gridster.curColWidth - gridster.margins[1];\n                        };\n\n                        var originalWidth, originalHeight;\n                        var savedDraggable;\n\n                        function mouseDown(e) {\n                            switch (e.which) {\n                                case 1:\n                                    // left mouse button\n                                    break;\n                                case 2:\n                                case 3:\n                                    // right or middle mouse button\n                                    return;\n                            }\n\n                            // save the draggable setting to restore after resize\n                            savedDraggable = gridster.draggable.enabled;\n                            if (savedDraggable) {\n                                gridster.draggable.enabled = false;\n                                scope.$broadcast('gridster-draggable-changed');\n                            }\n\n                            // Get the current mouse position.\n                            lastMouseX = e.pageX;\n                            lastMouseY = e.pageY;\n\n                            // Record current widget dimensions\n                            elmX = parseInt($el.css('left'), 10);\n                            elmY = parseInt($el.css('top'), 10);\n                            elmW = $el[0].offsetWidth;\n                            elmH = $el[0].offsetHeight;\n\n                            originalWidth = item.sizeX;\n                            originalHeight = item.sizeY;\n\n                            resizeStart(e);\n\n                            return true;\n                        }\n\n                        function resizeStart(e) {\n                            $el.addClass('gridster-item-moving');\n                            $el.addClass('gridster-item-resizing');\n\n                            gridster.movingItem = item;\n\n                            item.setElementSizeX();\n                            item.setElementSizeY();\n                            item.setElementPosition();\n                            gridster.updateHeight(1);\n\n                            scope.$apply(function() {\n                                // callback\n                                if (gridster.resizable && gridster.resizable.start) {\n                                    gridster.resizable.start(e, $el, itemOptions); // options is the item model\n                                }\n                            });\n                        }\n\n                        function mouseMove(e) {\n                            var maxLeft = gridster.curWidth - 1;\n\n                            // Get the current mouse position.\n                            mouseX = e.pageX;\n                            mouseY = e.pageY;\n\n                            // Get the deltas\n                            var diffX = mouseX - lastMouseX + mOffX;\n                            var diffY = mouseY - lastMouseY + mOffY;\n                            mOffX = mOffY = 0;\n\n                            // Update last processed mouse positions.\n                            lastMouseX = mouseX;\n                            lastMouseY = mouseY;\n\n                            var dY = diffY,\n                                dX = diffX;\n\n                            if (hClass.indexOf('n') >= 0) {\n                                if (elmH - dY < getMinHeight()) {\n                                    diffY = elmH - getMinHeight();\n                                    mOffY = dY - diffY;\n                                } else if (elmY + dY < minTop) {\n                                    diffY = minTop - elmY;\n                                    mOffY = dY - diffY;\n                                }\n                                elmY += diffY;\n                                elmH -= diffY;\n                            }\n                            if (hClass.indexOf('s') >= 0) {\n                                if (elmH + dY < getMinHeight()) {\n                                    diffY = getMinHeight() - elmH;\n                                    mOffY = dY - diffY;\n                                } else if (elmY + elmH + dY > maxTop) {\n                                    diffY = maxTop - elmY - elmH;\n                                    mOffY = dY - diffY;\n                                }\n                                elmH += diffY;\n                            }\n                            if (hClass.indexOf('w') >= 0) {\n                                if (elmW - dX < getMinWidth()) {\n                                    diffX = elmW - getMinWidth();\n                                    mOffX = dX - diffX;\n                                } else if (elmX + dX < minLeft) {\n                                    diffX = minLeft - elmX;\n                                    mOffX = dX - diffX;\n                                }\n                                elmX += diffX;\n                                elmW -= diffX;\n                            }\n                            if (hClass.indexOf('e') >= 0) {\n                                if (elmW + dX < getMinWidth()) {\n                                    diffX = getMinWidth() - elmW;\n                                    mOffX = dX - diffX;\n                                } else if (elmX + elmW + dX > maxLeft) {\n                                    diffX = maxLeft - elmX - elmW;\n                                    mOffX = dX - diffX;\n                                }\n                                elmW += diffX;\n                            }\n\n                            // set new position\n                            $el.css({\n                                'top': elmY + 'px',\n                                'left': elmX + 'px',\n                                'width': elmW + 'px',\n                                'height': elmH + 'px'\n                            });\n\n                            resize(e);\n\n                            return true;\n                        }\n\n                        function mouseUp(e) {\n                            // restore draggable setting to its original state\n                            if (gridster.draggable.enabled !== savedDraggable) {\n                                gridster.draggable.enabled = savedDraggable;\n                                scope.$broadcast('gridster-draggable-changed');\n                            }\n\n                            mOffX = mOffY = 0;\n\n                            resizeStop(e);\n\n                            return true;\n                        }\n\n                        function resize(e) {\n                            var oldRow = item.row,\n                                oldCol = item.col,\n                                oldSizeX = item.sizeX,\n                                oldSizeY = item.sizeY,\n                                hasCallback = gridster.resizable && gridster.resizable.resize;\n\n                            var col = item.col;\n                            // only change column if grabbing left edge\n                            if (['w', 'nw', 'sw'].indexOf(handleClass) !== -1) {\n                                col = gridster.pixelsToColumns(elmX, false);\n                            }\n\n                            var row = item.row;\n                            // only change row if grabbing top edge\n                            if (['n', 'ne', 'nw'].indexOf(handleClass) !== -1) {\n                                row = gridster.pixelsToRows(elmY, false);\n                            }\n\n                            var sizeX = item.sizeX;\n                            // only change row if grabbing left or right edge\n                            if (['n', 's'].indexOf(handleClass) === -1) {\n                                sizeX = gridster.pixelsToColumns(elmW, true);\n                            }\n\n                            var sizeY = item.sizeY;\n                            // only change row if grabbing top or bottom edge\n                            if (['e', 'w'].indexOf(handleClass) === -1) {\n                                sizeY = gridster.pixelsToRows(elmH, true);\n                            }\n\n                            if (gridster.pushing !== false || gridster.getItems(row, col, sizeX, sizeY, item).length === 0) {\n                                item.row = row;\n                                item.col = col;\n                                item.sizeX = sizeX;\n                                item.sizeY = sizeY;\n                            }\n                            var isChanged = item.row !== oldRow || item.col !== oldCol || item.sizeX !== oldSizeX || item.sizeY !== oldSizeY;\n\n                            if (hasCallback || isChanged) {\n                                scope.$apply(function() {\n                                    if (hasCallback) {\n                                        gridster.resizable.resize(e, $el, itemOptions); // options is the item model\n                                    }\n                                });\n                            }\n                        }\n\n                        function resizeStop(e) {\n                            $el.removeClass('gridster-item-moving');\n                            $el.removeClass('gridster-item-resizing');\n\n                            gridster.movingItem = null;\n\n                            item.setPosition(item.row, item.col);\n                            item.setSizeY(item.sizeY);\n                            item.setSizeX(item.sizeX);\n\n                            scope.$apply(function() {\n                                if (gridster.resizable && gridster.resizable.stop) {\n                                    gridster.resizable.stop(e, $el, itemOptions); // options is the item model\n                                }\n                            });\n                        }\n\n                        var $dragHandle = null;\n                        var unifiedInput;\n\n                        this.enable = function() {\n                            if (!$dragHandle) {\n                                $dragHandle = angular.element('<div class=\"gridster-item-resizable-handler handle-' + hClass + '\"></div>');\n                                $el.append($dragHandle);\n                            }\n\n                            unifiedInput = new gridster.unifiedInput($dragHandle[0], mouseDown, mouseMove, mouseUp);\n                            unifiedInput.enable();\n                        };\n\n                        this.disable = function() {\n                            if ($dragHandle) {\n                                $dragHandle.remove();\n                                $dragHandle = null;\n                            }\n\n                            unifiedInput.disable();\n                            unifiedInput = undefined;\n                        };\n\n                        this.destroy = function() {\n                            this.disable();\n                        };\n                    }\n\n                    var handles = [];\n                    var handlesOpts = gridster.resizable.handles;\n                    if (typeof handlesOpts === 'string') {\n                        handlesOpts = gridster.resizable.handles.split(',');\n                    }\n                    var enabled = false;\n\n                    for (var c = 0, l = handlesOpts.length; c < l; c++) {\n                        handles.push(new ResizeHandle(handlesOpts[c]));\n                    }\n\n                    this.enable = function() {\n                        if (enabled) {\n                            return;\n                        }\n                        for (var c = 0, l = handles.length; c < l; c++) {\n                            handles[c].enable();\n                        }\n                        enabled = true;\n                    };\n\n                    this.disable = function() {\n                        if (!enabled) {\n                            return;\n                        }\n                        for (var c = 0, l = handles.length; c < l; c++) {\n                            handles[c].disable();\n                        }\n                        enabled = false;\n                    };\n\n                    this.toggle = function(enabled) {\n                        if (enabled) {\n                            this.enable();\n                        } else {\n                            this.disable();\n                        }\n                    };\n\n                    this.destroy = function() {\n                        for (var c = 0, l = handles.length; c < l; c++) {\n                            handles[c].destroy();\n                        }\n                    };\n                }\n                return GridsterResizable;\n            }\n        ])\n\n    /**\n     * GridsterItem directive\n     */\n        .directive('gridsterItem', ['$parse', 'GridsterDraggable', 'GridsterResizable',\n            function($parse, GridsterDraggable, GridsterResizable) {\n                return {\n                    restrict: 'EA',\n                    controller: 'GridsterItemCtrl',\n                    require: ['^gridster', 'gridsterItem'],\n                    link: function(scope, $el, attrs, controllers) {\n                        var optionsKey = attrs.gridsterItem,\n                            options;\n\n                        var gridster = controllers[0],\n                            item = controllers[1];\n\n                        // bind the item's position properties\n                        if (optionsKey) {\n                            var $optionsGetter = $parse(optionsKey);\n                            options = $optionsGetter(scope) || {};\n                            if (!options && $optionsGetter.assign) {\n                                options = {\n                                    row: item.row,\n                                    col: item.col,\n                                    sizeX: item.sizeX,\n                                    sizeY: item.sizeY,\n                                    minSizeX: 0,\n                                    minSizeY: 0,\n                                    maxSizeX: null,\n                                    maxSizeY: null\n                                };\n                                $optionsGetter.assign(scope, options);\n                            }\n                        } else {\n                            options = attrs;\n                        }\n\n                        item.init($el, gridster);\n\n                        $el.addClass('gridster-item');\n\n                        var aspects = ['minSizeX', 'maxSizeX', 'minSizeY', 'maxSizeY', 'sizeX', 'sizeY', 'row', 'col'],\n                            $getters = {};\n\n                        var aspectFn = function(aspect) {\n                            var key;\n                            if (typeof options[aspect] === 'string') {\n                                key = options[aspect];\n                            } else if (typeof options[aspect.toLowerCase()] === 'string') {\n                                key = options[aspect.toLowerCase()];\n                            } else if (optionsKey) {\n                                key = $parse(optionsKey + '.' + aspect);\n                            } else {\n                                return;\n                            }\n                            $getters[aspect] = $parse(key);\n\n                            // when the value changes externally, update the internal item object\n                            scope.$watch(key, function(newVal) {\n                                newVal = parseInt(newVal, 10);\n                                if (!isNaN(newVal)) {\n                                    item[aspect] = newVal;\n                                }\n                            });\n\n                            // initial set\n                            var val = $getters[aspect](scope);\n                            if (typeof val === 'number') {\n                                item[aspect] = val;\n                            }\n                        };\n\n                        for (var i = 0, l = aspects.length; i < l; ++i) {\n                            aspectFn(aspects[i]);\n                        }\n\n                        scope.$broadcast('gridster-item-initialized', [item.sizeY, item.sizeX, item.getElementSizeY(), item.getElementSizeX()]);\n\n                        function positionChanged() {\n                            // call setPosition so the element and gridster controller are updated\n                            item.setPosition(item.row, item.col);\n\n                            // when internal item position changes, update externally bound values\n                            if ($getters.row && $getters.row.assign) {\n                                $getters.row.assign(scope, item.row);\n                            }\n                            if ($getters.col && $getters.col.assign) {\n                                $getters.col.assign(scope, item.col);\n                            }\n                        }\n                        scope.$watch(function() {\n                            return item.row + ',' + item.col;\n                        }, positionChanged);\n\n                        function sizeChanged() {\n                            var changedX = item.setSizeX(item.sizeX, true);\n                            if (changedX && $getters.sizeX && $getters.sizeX.assign) {\n                                $getters.sizeX.assign(scope, item.sizeX);\n                            }\n                            var changedY = item.setSizeY(item.sizeY, true);\n                            if (changedY && $getters.sizeY && $getters.sizeY.assign) {\n                                $getters.sizeY.assign(scope, item.sizeY);\n                            }\n\n                            if (changedX || changedY) {\n                                item.gridster.moveOverlappingItems(item);\n                                gridster.layoutChanged();\n                            }\n                        }\n                        scope.$watch(function() {\n                            return item.sizeY + ',' + item.sizeX + '|' + item.minSizeX + ',' + item.maxSizeX + ',' + item.minSizeY + ',' + item.maxSizeY;\n                        }, sizeChanged);\n\n                        var draggable = new GridsterDraggable($el, scope, gridster, item, options);\n                        var resizable = new GridsterResizable($el, scope, gridster, item, options);\n\n                        scope.$on('gridster-draggable-changed', function() {\n                            draggable.toggle(!gridster.isMobile && gridster.draggable && gridster.draggable.enabled);\n                        });\n                        scope.$on('gridster-resizable-changed', function() {\n                            resizable.toggle(!gridster.isMobile && gridster.resizable && gridster.resizable.enabled);\n                        });\n                        scope.$on('gridster-resized', function() {\n                            resizable.toggle(!gridster.isMobile && gridster.resizable && gridster.resizable.enabled);\n                        });\n                        scope.$watch(function() {\n                            return gridster.isMobile;\n                        }, function() {\n                            resizable.toggle(!gridster.isMobile && gridster.resizable && gridster.resizable.enabled);\n                            draggable.toggle(!gridster.isMobile && gridster.draggable && gridster.draggable.enabled);\n                        });\n\n                        function whichTransitionEvent() {\n                            var el = document.createElement('div');\n                            var transitions = {\n                                'transition': 'transitionend',\n                                'OTransition': 'oTransitionEnd',\n                                'MozTransition': 'transitionend',\n                                'WebkitTransition': 'webkitTransitionEnd'\n                            };\n                            for (var t in transitions) {\n                                if (el.style[t] !== undefined) {\n                                    return transitions[t];\n                                }\n                            }\n                        }\n\n                        $el.on(whichTransitionEvent(), function() {\n                            scope.$apply(function() {\n                                scope.$broadcast('gridster-item-transition-end');\n                            });\n                        });\n\n                        return scope.$on('$destroy', function() {\n                            try {\n                                resizable.destroy();\n                                draggable.destroy();\n                            } catch (e) {}\n\n                            try {\n                                gridster.removeItem(item);\n                            } catch (e) {}\n\n                            try {\n                                item.destroy();\n                            } catch (e) {}\n                        });\n                    }\n                };\n            }\n        ])\n\n    ;\n\n})(angular);"
  },
  {
    "path": "flowable-ui-web/task/libs/angular-hotkeys_1.4.5/hotkeys--activiti-patch.js",
    "content": "/*! \n * angular-hotkeys v1.4.5\n * https://chieffancypants.github.io/angular-hotkeys\n * Copyright (c) 2014 Wes Cruver\n * License: MIT\n */\n/*\n * angular-hotkeys\n *\n * Automatic keyboard shortcuts for your angular apps\n *\n * (c) 2014 Wes Cruver\n * License: MIT\n */\n\n(function() {\n\n  'use strict';\n\n  angular.module('cfp.hotkeys', []).provider('hotkeys', function() {\n\n    /**\n     * Configurable setting to disable the cheatsheet entirely\n     * @type {Boolean}\n     */\n    this.includeCheatSheet = true;\n\n    /**\n     * Configurable setting for the cheat sheet title\n     * @type {String}\n     */\n\n    this.templateTitle = 'Keyboard Shortcuts:';\n\n    /**\n     * Cheat sheet template in the event you want to totally customize it.\n     * @type {String}\n     */\n    this.template = '<div class=\"cfp-hotkeys-container fade\" ng-class=\"{in: helpVisible}\" style=\"display: none;\"><div class=\"cfp-hotkeys\">' +\n                      '<h4 class=\"cfp-hotkeys-title\">{{ title }}</h4>' +\n                      '<table><tbody>' +\n                        '<tr ng-repeat=\"hotkey in hotkeys | filter:{ description: \\'!$$undefined$$\\' }\">' +\n                          '<td class=\"cfp-hotkeys-keys\">' +\n                            '<span ng-repeat=\"key in hotkey.format() track by $index\" class=\"cfp-hotkeys-key\">{{ key }}</span>' +\n                          '</td>' +\n                          '<td class=\"cfp-hotkeys-text\">{{ hotkey.description }}</td>' +\n                        '</tr>' +\n                      '</tbody></table>' +\n                      '<div class=\"cfp-hotkeys-close\" ng-click=\"toggleCheatSheet()\">×</div>' +\n                    '</div></div>';\n\n    /**\n     * Configurable setting for the cheat sheet hotkey\n     * @type {String}\n     */\n    this.cheatSheetHotkey = '?';\n\n    /**\n     * Configurable setting for the cheat sheet description\n     * @type {String}\n     */\n    this.cheatSheetDescription = 'Show / hide this help menu';\n\n    this.$get = ['$rootElement', '$rootScope', '$compile', '$window', '$document', function ($rootElement, $rootScope, $compile, $window, $document) {\n\n      // monkeypatch Mousetrap's stopCallback() function\n      // this version doesn't return true when the element is an INPUT, SELECT, or TEXTAREA\n      // (instead we will perform this check per-key in the _add() method)\n      Mousetrap.stopCallback = function(event, element) {\n        // if the element has the class \"mousetrap\" then no need to stop\n        if ((' ' + element.className + ' ').indexOf(' mousetrap ') > -1) {\n          return false;\n        }\n\n        return (element.contentEditable && element.contentEditable == 'true');\n      };\n\n      /**\n       * Convert strings like cmd into symbols like ⌘\n       * @param  {String} combo Key combination, e.g. 'mod+f'\n       * @return {String}       The key combination with symbols\n       */\n      function symbolize (combo) {\n        var map = {\n          command   : '⌘',\n          shift     : '⇧',\n          left      : '←',\n          right     : '→',\n          up        : '↑',\n          down      : '↓',\n          'return'  : '↩',\n          backspace : '⌫'\n        };\n        combo = combo.split('+');\n\n        for (var i = 0; i < combo.length; i++) {\n          // try to resolve command / ctrl based on OS:\n          if (combo[i] === 'mod') {\n            if ($window.navigator && $window.navigator.platform.indexOf('Mac') >=0 ) {\n              combo[i] = 'command';\n            } else {\n              combo[i] = 'ctrl';\n            }\n          }\n\n          combo[i] = map[combo[i]] || combo[i];\n        }\n\n        return combo.join(' + ');\n      }\n\n      /**\n       * Hotkey object used internally for consistency\n       *\n       * @param {array}    combo       The keycombo. it's an array to support multiple combos\n       * @param {String}   description Description for the keycombo\n       * @param {Function} callback    function to execute when keycombo pressed\n       * @param {string}   action      the type of event to listen for (for mousetrap)\n       * @param {array}    allowIn     an array of tag names to allow this combo in ('INPUT', 'SELECT', and/or 'TEXTAREA')\n       * @param {Boolean}  persistent  Whether the hotkey persists navigation events\n       */\n      function Hotkey (combo, description, callback, action, allowIn, persistent) {\n        // TODO: Check that the values are sane because we could\n        // be trying to instantiate a new Hotkey with outside dev's\n        // supplied values\n\n        this.combo = combo instanceof Array ? combo : [combo];\n        this.description = description;\n        this.callback = callback;\n        this.action = action;\n        this.allowIn = allowIn;\n        this.persistent = persistent;\n      }\n\n      /**\n       * Helper method to format (symbolize) the key combo for display\n       *\n       * @return {[Array]} An array of the key combination sequence\n       *   for example: \"command+g c i\" becomes [\"⌘ + g\", \"c\", \"i\"]\n       *\n       * TODO: this gets called a lot.  We should cache the result\n       */\n      Hotkey.prototype.format = function() {\n\n        // Don't show all the possible key combos, just the first one.  Not sure\n        // of usecase here, so open a ticket if my assumptions are wrong\n        var combo = this.combo[0];\n\n        var sequence = combo.split(/[\\s]/);\n        for (var i = 0; i < sequence.length; i++) {\n          sequence[i] = symbolize(sequence[i]);\n        }\n\n        return sequence;\n      };\n\n      /**\n       * A new scope used internally for the cheatsheet\n       * @type {$rootScope.Scope}\n       */\n      var scope = $rootScope.$new();\n\n      /**\n       * Holds an array of Hotkey objects currently bound\n       * @type {Array}\n       */\n      scope.hotkeys = [];\n\n      /**\n       * Contains the state of the help's visibility\n       * @type {Boolean}\n       */\n      scope.helpVisible = false;\n\n      /**\n       * Holds the title string for the help menu\n       * @type {String}\n       */\n      scope.title = this.templateTitle;\n\n      /**\n       * Expose toggleCheatSheet to hotkeys scope so we can call it using\n       * ng-click from the template\n       * @type {function}\n       */\n      scope.toggleCheatSheet = toggleCheatSheet;\n\n\n      /**\n       * Holds references to the different scopes that have bound hotkeys\n       * attached.  This is useful to catch when the scopes are `$destroy`d and\n       * then automatically unbind the hotkey.\n       *\n       * @type {Array}\n       */\n      var boundScopes = [];\n\n\n      $rootScope.$on('$routeChangeSuccess', function (event, route) {\n        purgeHotkeys();\n\n        if (route && route.hotkeys) {\n          angular.forEach(route.hotkeys, function (hotkey) {\n            // a string was given, which implies this is a function that is to be\n            // $eval()'d within that controller's scope\n            // TODO: hotkey here is super confusing.  sometimes a function (that gets turned into an array), sometimes a string\n            var callback = hotkey[2];\n            if (typeof(callback) === 'string' || callback instanceof String) {\n              hotkey[2] = [callback, route];\n            }\n\n            // todo: perform check to make sure not already defined:\n            // this came from a route, so it's likely not meant to be persistent\n            hotkey[5] = false;\n            _add.apply(this, hotkey);\n          });\n        }\n      });\n\n\n      // Auto-create a help menu:\n      if (this.includeCheatSheet) {\n        var document = $document[0];\n        var element = $rootElement[0];\n        var helpMenu = angular.element(this.template);\n        _add(this.cheatSheetHotkey, this.cheatSheetDescription, toggleCheatSheet);\n\n        // If $rootElement is document or documentElement, then body must be used\n        if (element === document || element === document.documentElement) {\n          element = document.body;\n        }\n\n        angular.element(element).append($compile(helpMenu)(scope));\n      }\n\n\n      /**\n       * Purges all non-persistent hotkeys (such as those defined in routes)\n       *\n       * Without this, the same hotkey would get recreated everytime\n       * the route is accessed.\n       */\n      function purgeHotkeys() {\n        var i = scope.hotkeys.length;\n        while (i--) {\n          var hotkey = scope.hotkeys[i];\n          if (hotkey && !hotkey.persistent) {\n            _del(hotkey);\n          }\n        }\n      }\n\n      /**\n       * Toggles the help menu element's visiblity\n       */\n      var previousEsc = false;\n\n      function toggleCheatSheet() {\n        scope.helpVisible = !scope.helpVisible;\n\n        // Bind to esc to remove the cheat sheet.  Ideally, this would be done\n        // as a directive in the template, but that would create a nasty\n        // circular dependency issue that I don't feel like sorting out.\n        if (scope.helpVisible) {\n          previousEsc = _get('esc');\n          _del('esc');\n\n          // Here's an odd way to do this: we're going to use the original\n          // description of the hotkey on the cheat sheet so that it shows up.\n          // without it, no entry for esc will ever show up (#22)\n          _add('esc', previousEsc.description, toggleCheatSheet);\n        } else {\n          _del('esc');\n\n          // restore the previously bound ESC key\n          if (previousEsc !== false) {\n            _add(previousEsc);\n          }\n        }\n      }\n\n      /**\n       * Creates a new Hotkey and creates the Mousetrap binding\n       *\n       * @param {string}   combo       mousetrap key binding\n       * @param {string}   description description for the help menu\n       * @param {Function} callback    method to call when key is pressed\n       * @param {string}   action      the type of event to listen for (for mousetrap)\n       * @param {array}    allowIn     an array of tag names to allow this combo in ('INPUT', 'SELECT', and/or 'TEXTAREA')\n       * @param {boolean}  persistent  if true, the binding is preserved upon route changes\n       */\n      function _add (combo, description, callback, action, allowIn, persistent) {\n\n        // used to save original callback for \"allowIn\" wrapping:\n        var _callback;\n\n        // these elements are prevented by the default Mousetrap.stopCallback():\n        var preventIn = ['INPUT', 'SELECT', 'TEXTAREA'];\n\n        // Determine if object format was given:\n        var objType = Object.prototype.toString.call(combo);\n\n        if (objType === '[object Object]') {\n          description = combo.description;\n          callback    = combo.callback;\n          action      = combo.action;\n          persistent  = combo.persistent;\n          allowIn     = combo.allowIn;\n          combo       = combo.combo;\n        }\n\n        // description is optional:\n        if (description instanceof Function) {\n          action = callback;\n          callback = description;\n          description = '$$undefined$$';\n        } else if (angular.isUndefined(description)) {\n          description = '$$undefined$$';\n        }\n\n        // any items added through the public API are for controllers\n        // that persist through navigation, and thus undefined should mean\n        // true in this case.\n        if (persistent === undefined) {\n          persistent = true;\n        }\n\n        // if callback is defined, then wrap it in a function\n        // that checks if the event originated from a form element.\n        // the function blocks the callback from executing unless the element is specified\n        // in allowIn (emulates Mousetrap.stopCallback() on a per-key level)\n        if (typeof callback === 'function') {\n\n          // save the original callback\n          _callback = callback;\n\n          // make sure allowIn is an array\n          if (!(allowIn instanceof Array)) {\n            allowIn = [];\n          }\n\n          // remove anything from preventIn that's present in allowIn\n          var index;\n          for (var i=0; i < allowIn.length; i++) {\n            allowIn[i] = allowIn[i].toUpperCase();\n            index = preventIn.indexOf(allowIn[i]);\n            if (index !== -1) {\n              preventIn.splice(index, 1);\n            }\n          }\n\n          // create the new wrapper callback\n          callback = function(event) {\n            var shouldExecute = true;\n            var target = event.target || event.srcElement; // srcElement is IE only\n            var nodeName = target.nodeName.toUpperCase();\n\n            // check if the input has a mousetrap class, and skip checking preventIn if so\n            if ((' ' + target.className + ' ').indexOf(' mousetrap ') > -1) {\n              shouldExecute = true;\n            } else {\n              // don't execute callback if the event was fired from inside an element listed in preventIn\n              for (var i=0; i<preventIn.length; i++) {\n                if (preventIn[i] === nodeName) {\n                  shouldExecute = false;\n                  break;\n                }\n              }\n            }\n\n            if (shouldExecute) {\n              wrapApply(_callback.apply(this, arguments));\n            }\n          };\n        }\n\n        if (typeof(action) === 'string') {\n          Mousetrap.bind(combo, wrapApply(callback), action);\n        } else {\n          Mousetrap.bind(combo, wrapApply(callback));\n        }\n\n        var hotkey = new Hotkey(combo, description, callback, action, allowIn, persistent);\n        scope.hotkeys.push(hotkey);\n        return hotkey;\n      }\n\n      /**\n       * delete and unbind a Hotkey\n       *\n       * @param  {mixed} hotkey   Either the bound key or an instance of Hotkey\n       * @return {boolean}        true if successful\n       */\n      function _del (hotkey) {\n        var combo = (hotkey instanceof Hotkey) ? hotkey.combo : hotkey;\n\n        Mousetrap.unbind(combo);\n\n        if (angular.isArray(combo)) {\n          var retStatus = true;\n          var i = combo.length;\n          while (i--) {\n            retStatus = _del(combo[i]) && retStatus;\n          }\n          return retStatus;\n        } else {\n          var index = scope.hotkeys.indexOf(_get(combo));\n\n          if (index > -1) {\n            // if the combo has other combos bound, don't unbind the whole thing, just the one combo:\n            if (scope.hotkeys[index].combo.length > 1) {\n              scope.hotkeys[index].combo.splice(scope.hotkeys[index].combo.indexOf(combo), 1);\n            } else {\n              scope.hotkeys.splice(index, 1);\n            }\n            return true;\n          }\n        }\n\n        return false;\n\n      }\n\n      /**\n       * Get a Hotkey object by key binding\n       *\n       * @param  {[string]} combo  the key the Hotkey is bound to\n       * @return {Hotkey}          The Hotkey object\n       */\n      function _get (combo) {\n\n        var hotkey;\n\n        for (var i = 0; i < scope.hotkeys.length; i++) {\n          hotkey = scope.hotkeys[i];\n\n          if (hotkey.combo.indexOf(combo) > -1) {\n            return hotkey;\n          }\n        }\n\n        return false;\n      }\n\n      /**\n       * Binds the hotkey to a particular scope.  Useful if the scope is\n       * destroyed, we can automatically destroy the hotkey binding.\n       *\n       * @param  {Object} scope The scope to bind to\n       */\n      function bindTo (scope) {\n        // Only initialize once to allow multiple calls for same scope.\n        if (!(scope.$id in boundScopes)) {\n\n          // Add the scope to the list of bound scopes\n          boundScopes[scope.$id] = [];\n\n          scope.$on('$destroy', function () {\n            var i = boundScopes[scope.$id].length;\n            while (i--) {\n              _del(boundScopes[scope.$id][i]);\n              delete boundScopes[scope.$id][i];\n            }\n          });\n        }\n        // return an object with an add function so we can keep track of the\n        // hotkeys and their scope that we added via this chaining method\n        return {\n          add: function (args) {\n            var hotkey;\n\n            if (arguments.length > 1) {\n              hotkey = _add.apply(this, arguments);\n            } else {\n              hotkey = _add(args);\n            }\n\n            boundScopes[scope.$id].push(hotkey);\n            return this;\n          }\n        };\n      }\n\n      /**\n       * All callbacks sent to Mousetrap are wrapped using this function\n       * so that we can force a $scope.$apply()\n       *\n       * @param  {Function} callback [description]\n       * @return {[type]}            [description]\n       */\n      function wrapApply (callback) {\n        // return mousetrap a function to call\n        return function (event, combo) {\n\n          // if this is an array, it means we provided a route object\n          // because the scope wasn't available yet, so rewrap the callback\n          // now that the scope is available:\n          if (callback instanceof Array) {\n            var funcString = callback[0];\n            var route = callback[1];\n            callback = function (event) {\n              route.scope.$eval(funcString);\n            };\n          }\n\n          // this takes place outside angular, so we'll have to call\n          // $apply() to make sure angular's digest happens\n          $rootScope.$apply(function() {\n            // call the original hotkey callback with the keyboard event\n            callback(event, _get(combo));\n          });\n        };\n      }\n\n\n      var publicApi = {\n        add                   : _add,\n        del                   : _del,\n        get                   : _get,\n        bindTo                : bindTo,\n        template              : this.template,\n        toggleCheatSheet      : toggleCheatSheet,\n        includeCheatSheet     : this.includeCheatSheet,\n        cheatSheetHotkey      : this.cheatSheetHotkey,\n        cheatSheetDescription : this.cheatSheetDescription,\n        purgeHotkeys          : purgeHotkeys,\n        templateTitle         : this.templateTitle\n      };\n\n      return publicApi;\n\n    }];\n  })\n\n  .directive('hotkey', ['hotkeys', function (hotkeys) {\n    return {\n      restrict: 'A',\n      link: function (scope, el, attrs) {\n        var key, allowIn;\n\n        angular.forEach(scope.$eval(attrs.hotkey), function (func, hotkey) {\n          // split and trim the hotkeys string into array\n          allowIn = typeof attrs.hotkeyAllowIn === \"string\" ? attrs.hotkeyAllowIn.split(/[\\s,]+/) : [];\n\n          key = hotkey;\n\n          hotkeys.add({\n            combo: hotkey,\n            description: attrs.hotkeyDescription,\n            callback: func,\n            action: attrs.hotkeyAction,\n            allowIn: allowIn\n          });\n        });\n\n        // remove the hotkey if the directive is destroyed:\n        el.bind('$destroy', function() {\n          hotkeys.del(key);\n        });\n      }\n    };\n  }])\n\n  .run(['hotkeys', function(hotkeys) {\n    // force hotkeys to run by injecting it. Without this, hotkeys only runs\n    // when a controller or something else asks for it via DI.\n  }]);\n\n})();\n\n/*global define:false */\n/**\n * Copyright 2013 Craig Campbell\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 * Mousetrap is a simple keyboard shortcut library for Javascript with\n * no external dependencies\n *\n * @version 1.4.6\n * @url craig.is/killing/mice\n */\n(function(window, document, undefined) {\n\n    /**\n     * mapping of special keycodes to their corresponding keys\n     *\n     * everything in this dictionary cannot use keypress events\n     * so it has to be here to map to the correct keycodes for\n     * keyup/keydown events\n     *\n     * @type {Object}\n     */\n    var _MAP = {\n            8: 'backspace',\n            9: 'tab',\n            13: 'enter',\n            16: 'shift',\n            17: 'ctrl',\n            18: 'alt',\n            20: 'capslock',\n            27: 'esc',\n            32: 'space',\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: 'ins',\n            46: 'del',\n            91: 'meta',\n            93: 'meta',\n            224: 'meta'\n        },\n\n        /**\n         * mapping for special characters so they can support\n         *\n         * this dictionary is only used incase you want to bind a\n         * keyup or keydown event to one of these keys\n         *\n         * @type {Object}\n         */\n        _KEYCODE_MAP = {\n            106: '*',\n            107: '+',\n            109: '-',\n            110: '.',\n            111 : '/',\n            186: ';',\n            187: '=',\n            188: ',',\n            189: '-',\n            190: '.',\n            191: '/',\n            192: '`',\n            219: '[',\n            220: '\\\\',\n            221: ']',\n            222: '\\''\n        },\n\n        /**\n         * this is a mapping of keys that require shift on a US keypad\n         * back to the non shift equivelents\n         *\n         * this is so you can use keyup events with these keys\n         *\n         * note that this will only work reliably on US keyboards\n         *\n         * @type {Object}\n         */\n        _SHIFT_MAP = {\n            '~': '`',\n            '!': '1',\n            '@': '2',\n            '#': '3',\n            '$': '4',\n            '%': '5',\n            '^': '6',\n            '&': '7',\n            '*': '8',\n            '(': '9',\n            ')': '0',\n            '_': '-',\n            '+': '=',\n            ':': ';',\n            '\\\"': '\\'',\n            '<': ',',\n            '>': '.',\n            '?': '/',\n            '|': '\\\\'\n        },\n\n        /**\n         * this is a list of special strings you can use to map\n         * to modifier keys when you specify your keyboard shortcuts\n         *\n         * @type {Object}\n         */\n        _SPECIAL_ALIASES = {\n            'option': 'alt',\n            'command': 'meta',\n            'return': 'enter',\n            'escape': 'esc',\n            'mod': /Mac|iPod|iPhone|iPad/.test(navigator.platform) ? 'meta' : 'ctrl'\n        },\n\n        /**\n         * variable to store the flipped version of _MAP from above\n         * needed to check if we should use keypress or not when no action\n         * is specified\n         *\n         * @type {Object|undefined}\n         */\n        _REVERSE_MAP,\n\n        /**\n         * a list of all the callbacks setup via Mousetrap.bind()\n         *\n         * @type {Object}\n         */\n        _callbacks = {},\n\n        /**\n         * direct map of string combinations to callbacks used for trigger()\n         *\n         * @type {Object}\n         */\n        _directMap = {},\n\n        /**\n         * keeps track of what level each sequence is at since multiple\n         * sequences can start out with the same sequence\n         *\n         * @type {Object}\n         */\n        _sequenceLevels = {},\n\n        /**\n         * variable to store the setTimeout call\n         *\n         * @type {null|number}\n         */\n        _resetTimer,\n\n        /**\n         * temporary state where we will ignore the next keyup\n         *\n         * @type {boolean|string}\n         */\n        _ignoreNextKeyup = false,\n\n        /**\n         * temporary state where we will ignore the next keypress\n         *\n         * @type {boolean}\n         */\n        _ignoreNextKeypress = false,\n\n        /**\n         * are we currently inside of a sequence?\n         * type of action (\"keyup\" or \"keydown\" or \"keypress\") or false\n         *\n         * @type {boolean|string}\n         */\n        _nextExpectedAction = false;\n\n    /**\n     * loop through the f keys, f1 to f19 and add them to the map\n     * programatically\n     */\n    for (var i = 1; i < 20; ++i) {\n        _MAP[111 + i] = 'f' + i;\n    }\n\n    /**\n     * loop through to map numbers on the numeric keypad\n     */\n    for (i = 0; i <= 9; ++i) {\n        _MAP[i + 96] = i;\n    }\n\n    /**\n     * cross browser add event method\n     *\n     * @param {Element|HTMLDocument} object\n     * @param {string} type\n     * @param {Function} callback\n     * @returns void\n     */\n    function _addEvent(object, type, callback) {\n        if (object.addEventListener) {\n            object.addEventListener(type, callback, false);\n            return;\n        }\n\n        object.attachEvent('on' + type, callback);\n    }\n\n    /**\n     * takes the event and returns the key character\n     *\n     * @param {Event} e\n     * @return {string}\n     */\n    function _characterFromEvent(e) {\n\n        // for keypress events we should return the character as is\n        if (e.type == 'keypress') {\n            var character = String.fromCharCode(e.which);\n\n            // if the shift key is not pressed then it is safe to assume\n            // that we want the character to be lowercase.  this means if\n            // you accidentally have caps lock on then your key bindings\n            // will continue to work\n            //\n            // the only side effect that might not be desired is if you\n            // bind something like 'A' cause you want to trigger an\n            // event when capital A is pressed caps lock will no longer\n            // trigger the event.  shift+a will though.\n            if (!e.shiftKey) {\n                character = character.toLowerCase();\n            }\n\n            return character;\n        }\n\n        // for non keypress events the special maps are needed\n        if (_MAP[e.which]) {\n            return _MAP[e.which];\n        }\n\n        if (_KEYCODE_MAP[e.which]) {\n            return _KEYCODE_MAP[e.which];\n        }\n\n        // if it is not in the special map\n\n        // with keydown and keyup events the character seems to always\n        // come in as an uppercase character whether you are pressing shift\n        // or not.  we should make sure it is always lowercase for comparisons\n        return String.fromCharCode(e.which).toLowerCase();\n    }\n\n    /**\n     * checks if two arrays are equal\n     *\n     * @param {Array} modifiers1\n     * @param {Array} modifiers2\n     * @returns {boolean}\n     */\n    function _modifiersMatch(modifiers1, modifiers2) {\n        return modifiers1.sort().join(',') === modifiers2.sort().join(',');\n    }\n\n    /**\n     * resets all sequence counters except for the ones passed in\n     *\n     * @param {Object} doNotReset\n     * @returns void\n     */\n    function _resetSequences(doNotReset) {\n        doNotReset = doNotReset || {};\n\n        var activeSequences = false,\n            key;\n\n        for (key in _sequenceLevels) {\n            if (doNotReset[key]) {\n                activeSequences = true;\n                continue;\n            }\n            _sequenceLevels[key] = 0;\n        }\n\n        if (!activeSequences) {\n            _nextExpectedAction = false;\n        }\n    }\n\n    /**\n     * finds all callbacks that match based on the keycode, modifiers,\n     * and action\n     *\n     * @param {string} character\n     * @param {Array} modifiers\n     * @param {Event|Object} e\n     * @param {string=} sequenceName - name of the sequence we are looking for\n     * @param {string=} combination\n     * @param {number=} level\n     * @returns {Array}\n     */\n    function _getMatches(character, modifiers, e, sequenceName, combination, level) {\n        var i,\n            callback,\n            matches = [],\n            action = e.type;\n\n        // if there are no events related to this keycode\n        if (!_callbacks[character]) {\n            return [];\n        }\n\n        // if a modifier key is coming up on its own we should allow it\n        if (action == 'keyup' && _isModifier(character)) {\n            modifiers = [character];\n        }\n\n        // loop through all callbacks for the key that was pressed\n        // and see if any of them match\n        for (i = 0; i < _callbacks[character].length; ++i) {\n            callback = _callbacks[character][i];\n\n            // if a sequence name is not specified, but this is a sequence at\n            // the wrong level then move onto the next match\n            if (!sequenceName && callback.seq && _sequenceLevels[callback.seq] != callback.level) {\n                continue;\n            }\n\n            // if the action we are looking for doesn't match the action we got\n            // then we should keep going\n            if (action != callback.action) {\n                continue;\n            }\n\n            // if this is a keypress event and the meta key and control key\n            // are not pressed that means that we need to only look at the\n            // character, otherwise check the modifiers as well\n            //\n            // chrome will not fire a keypress if meta or control is down\n            // safari will fire a keypress if meta or meta+shift is down\n            // firefox will fire a keypress if meta or control is down\n            if ((action == 'keypress' && !e.metaKey && !e.ctrlKey) || _modifiersMatch(modifiers, callback.modifiers)) {\n\n                // when you bind a combination or sequence a second time it\n                // should overwrite the first one.  if a sequenceName or\n                // combination is specified in this call it does just that\n                //\n                // @todo make deleting its own method?\n                var deleteCombo = !sequenceName && callback.combo == combination;\n                var deleteSequence = sequenceName && callback.seq == sequenceName && callback.level == level;\n                if (deleteCombo || deleteSequence) {\n                    _callbacks[character].splice(i, 1);\n                }\n\n                matches.push(callback);\n            }\n        }\n\n        return matches;\n    }\n\n    /**\n     * takes a key event and figures out what the modifiers are\n     *\n     * @param {Event} e\n     * @returns {Array}\n     */\n    function _eventModifiers(e) {\n        var modifiers = [];\n\n        if (e.shiftKey) {\n            modifiers.push('shift');\n        }\n\n        if (e.altKey) {\n            modifiers.push('alt');\n        }\n\n        if (e.ctrlKey) {\n            modifiers.push('ctrl');\n        }\n\n        if (e.metaKey) {\n            modifiers.push('meta');\n        }\n\n        return modifiers;\n    }\n\n    /**\n     * prevents default for this event\n     *\n     * @param {Event} e\n     * @returns void\n     */\n    function _preventDefault(e) {\n        if (e.preventDefault) {\n            e.preventDefault();\n            return;\n        }\n\n        e.returnValue = false;\n    }\n\n    /**\n     * stops propogation for this event\n     *\n     * @param {Event} e\n     * @returns void\n     */\n    function _stopPropagation(e) {\n        if (e.stopPropagation) {\n            e.stopPropagation();\n            return;\n        }\n\n        e.cancelBubble = true;\n    }\n\n    /**\n     * actually calls the callback function\n     *\n     * if your callback function returns false this will use the jquery\n     * convention - prevent default and stop propogation on the event\n     *\n     * @param {Function} callback\n     * @param {Event} e\n     * @returns void\n     */\n    function _fireCallback(callback, e, combo, sequence) {\n\n        // if this event should not happen stop here\n        if (Mousetrap.stopCallback(e, e.target || e.srcElement, combo, sequence)) {\n            return;\n        }\n\n        if (callback(e, combo) === false) {\n            _preventDefault(e);\n            _stopPropagation(e);\n        }\n    }\n\n    /**\n     * handles a character key event\n     *\n     * @param {string} character\n     * @param {Array} modifiers\n     * @param {Event} e\n     * @returns void\n     */\n    function _handleKey(character, modifiers, e) {\n        var callbacks = _getMatches(character, modifiers, e),\n            i,\n            doNotReset = {},\n            maxLevel = 0,\n            processedSequenceCallback = false;\n\n        // Calculate the maxLevel for sequences so we can only execute the longest callback sequence\n        for (i = 0; i < callbacks.length; ++i) {\n            if (callbacks[i].seq) {\n                maxLevel = Math.max(maxLevel, callbacks[i].level);\n            }\n        }\n\n        // loop through matching callbacks for this key event\n        for (i = 0; i < callbacks.length; ++i) {\n\n            // fire for all sequence callbacks\n            // this is because if for example you have multiple sequences\n            // bound such as \"g i\" and \"g t\" they both need to fire the\n            // callback for matching g cause otherwise you can only ever\n            // match the first one\n            if (callbacks[i].seq) {\n\n                // only fire callbacks for the maxLevel to prevent\n                // subsequences from also firing\n                //\n                // for example 'a option b' should not cause 'option b' to fire\n                // even though 'option b' is part of the other sequence\n                //\n                // any sequences that do not match here will be discarded\n                // below by the _resetSequences call\n                if (callbacks[i].level != maxLevel) {\n                    continue;\n                }\n\n                processedSequenceCallback = true;\n\n                // keep a list of which sequences were matches for later\n                doNotReset[callbacks[i].seq] = 1;\n                _fireCallback(callbacks[i].callback, e, callbacks[i].combo, callbacks[i].seq);\n                continue;\n            }\n\n            // if there were no sequence matches but we are still here\n            // that means this is a regular match so we should fire that\n            if (!processedSequenceCallback) {\n                _fireCallback(callbacks[i].callback, e, callbacks[i].combo);\n            }\n        }\n\n        // if the key you pressed matches the type of sequence without\n        // being a modifier (ie \"keyup\" or \"keypress\") then we should\n        // reset all sequences that were not matched by this event\n        //\n        // this is so, for example, if you have the sequence \"h a t\" and you\n        // type \"h e a r t\" it does not match.  in this case the \"e\" will\n        // cause the sequence to reset\n        //\n        // modifier keys are ignored because you can have a sequence\n        // that contains modifiers such as \"enter ctrl+space\" and in most\n        // cases the modifier key will be pressed before the next key\n        //\n        // also if you have a sequence such as \"ctrl+b a\" then pressing the\n        // \"b\" key will trigger a \"keypress\" and a \"keydown\"\n        //\n        // the \"keydown\" is expected when there is a modifier, but the\n        // \"keypress\" ends up matching the _nextExpectedAction since it occurs\n        // after and that causes the sequence to reset\n        //\n        // we ignore keypresses in a sequence that directly follow a keydown\n        // for the same character\n        var ignoreThisKeypress = e.type == 'keypress' && _ignoreNextKeypress;\n        if (e.type == _nextExpectedAction && !_isModifier(character) && !ignoreThisKeypress) {\n            _resetSequences(doNotReset);\n        }\n\n        _ignoreNextKeypress = processedSequenceCallback && e.type == 'keydown';\n    }\n\n    /**\n     * handles a keydown event\n     *\n     * @param {Event} e\n     * @returns void\n     */\n    function _handleKeyEvent(e) {\n\n        // normalize e.which for key events\n        // @see http://stackoverflow.com/questions/4285627/javascript-keycode-vs-charcode-utter-confusion\n        if (typeof e.which !== 'number') {\n            e.which = e.keyCode;\n        }\n\n        var character = _characterFromEvent(e);\n\n        // no character found then stop\n        if (!character) {\n            return;\n        }\n\n        // need to use === for the character check because the character can be 0\n        if (e.type == 'keyup' && _ignoreNextKeyup === character) {\n            _ignoreNextKeyup = false;\n            return;\n        }\n\n        Mousetrap.handleKey(character, _eventModifiers(e), e);\n    }\n\n    /**\n     * determines if the keycode specified is a modifier key or not\n     *\n     * @param {string} key\n     * @returns {boolean}\n     */\n    function _isModifier(key) {\n        return key == 'shift' || key == 'ctrl' || key == 'alt' || key == 'meta';\n    }\n\n    /**\n     * called to set a 1 second timeout on the specified sequence\n     *\n     * this is so after each key press in the sequence you have 1 second\n     * to press the next key before you have to start over\n     *\n     * @returns void\n     */\n    function _resetSequenceTimer() {\n        clearTimeout(_resetTimer);\n        _resetTimer = setTimeout(_resetSequences, 1000);\n    }\n\n    /**\n     * reverses the map lookup so that we can look for specific keys\n     * to see what can and can't use keypress\n     *\n     * @return {Object}\n     */\n    function _getReverseMap() {\n        if (!_REVERSE_MAP) {\n            _REVERSE_MAP = {};\n            for (var key in _MAP) {\n\n                // pull out the numeric keypad from here cause keypress should\n                // be able to detect the keys from the character\n                if (key > 95 && key < 112) {\n                    continue;\n                }\n\n                if (_MAP.hasOwnProperty(key)) {\n                    _REVERSE_MAP[_MAP[key]] = key;\n                }\n            }\n        }\n        return _REVERSE_MAP;\n    }\n\n    /**\n     * picks the best action based on the key combination\n     *\n     * @param {string} key - character for key\n     * @param {Array} modifiers\n     * @param {string=} action passed in\n     */\n    function _pickBestAction(key, modifiers, action) {\n\n        // if no action was picked in we should try to pick the one\n        // that we think would work best for this key\n        if (!action) {\n            action = _getReverseMap()[key] ? 'keydown' : 'keypress';\n        }\n\n        // modifier keys don't work as expected with keypress,\n        // switch to keydown\n        if (action == 'keypress' && modifiers.length) {\n            action = 'keydown';\n        }\n\n        return action;\n    }\n\n    /**\n     * binds a key sequence to an event\n     *\n     * @param {string} combo - combo specified in bind call\n     * @param {Array} keys\n     * @param {Function} callback\n     * @param {string=} action\n     * @returns void\n     */\n    function _bindSequence(combo, keys, callback, action) {\n\n        // start off by adding a sequence level record for this combination\n        // and setting the level to 0\n        _sequenceLevels[combo] = 0;\n\n        /**\n         * callback to increase the sequence level for this sequence and reset\n         * all other sequences that were active\n         *\n         * @param {string} nextAction\n         * @returns {Function}\n         */\n        function _increaseSequence(nextAction) {\n            return function() {\n                _nextExpectedAction = nextAction;\n                ++_sequenceLevels[combo];\n                _resetSequenceTimer();\n            };\n        }\n\n        /**\n         * wraps the specified callback inside of another function in order\n         * to reset all sequence counters as soon as this sequence is done\n         *\n         * @param {Event} e\n         * @returns void\n         */\n        function _callbackAndReset(e) {\n            _fireCallback(callback, e, combo);\n\n            // we should ignore the next key up if the action is key down\n            // or keypress.  this is so if you finish a sequence and\n            // release the key the final key will not trigger a keyup\n            if (action !== 'keyup') {\n                _ignoreNextKeyup = _characterFromEvent(e);\n            }\n\n            // weird race condition if a sequence ends with the key\n            // another sequence begins with\n            setTimeout(_resetSequences, 10);\n        }\n\n        // loop through keys one at a time and bind the appropriate callback\n        // function.  for any key leading up to the final one it should\n        // increase the sequence. after the final, it should reset all sequences\n        //\n        // if an action is specified in the original bind call then that will\n        // be used throughout.  otherwise we will pass the action that the\n        // next key in the sequence should match.  this allows a sequence\n        // to mix and match keypress and keydown events depending on which\n        // ones are better suited to the key provided\n        for (var i = 0; i < keys.length; ++i) {\n            var isFinal = i + 1 === keys.length;\n            var wrappedCallback = isFinal ? _callbackAndReset : _increaseSequence(action || _getKeyInfo(keys[i + 1]).action);\n            _bindSingle(keys[i], wrappedCallback, action, combo, i);\n        }\n    }\n\n    /**\n     * Converts from a string key combination to an array\n     *\n     * @param  {string} combination like \"command+shift+l\"\n     * @return {Array}\n     */\n    function _keysFromString(combination) {\n        if (combination === '+') {\n            return ['+'];\n        }\n\n        return combination.split('+');\n    }\n\n    /**\n     * Gets info for a specific key combination\n     *\n     * @param  {string} combination key combination (\"command+s\" or \"a\" or \"*\")\n     * @param  {string=} action\n     * @returns {Object}\n     */\n    function _getKeyInfo(combination, action) {\n        var keys,\n            key,\n            i,\n            modifiers = [];\n\n        // take the keys from this pattern and figure out what the actual\n        // pattern is all about\n        keys = _keysFromString(combination);\n\n        for (i = 0; i < keys.length; ++i) {\n            key = keys[i];\n\n            // normalize key names\n            if (_SPECIAL_ALIASES[key]) {\n                key = _SPECIAL_ALIASES[key];\n            }\n\n            // if this is not a keypress event then we should\n            // be smart about using shift keys\n            // this will only work for US keyboards however\n            if (action && action != 'keypress' && _SHIFT_MAP[key]) {\n                key = _SHIFT_MAP[key];\n                modifiers.push('shift');\n            }\n\n            // if this key is a modifier then add it to the list of modifiers\n            if (_isModifier(key)) {\n                modifiers.push(key);\n            }\n        }\n\n        // depending on what the key combination is\n        // we will try to pick the best event for it\n        action = _pickBestAction(key, modifiers, action);\n\n        return {\n            key: key,\n            modifiers: modifiers,\n            action: action\n        };\n    }\n\n    /**\n     * binds a single keyboard combination\n     *\n     * @param {string} combination\n     * @param {Function} callback\n     * @param {string=} action\n     * @param {string=} sequenceName - name of sequence if part of sequence\n     * @param {number=} level - what part of the sequence the command is\n     * @returns void\n     */\n    function _bindSingle(combination, callback, action, sequenceName, level) {\n\n        // store a direct mapped reference for use with Mousetrap.trigger\n        _directMap[combination + ':' + action] = callback;\n\n        // make sure multiple spaces in a row become a single space\n        combination = combination.replace(/\\s+/g, ' ');\n\n        var sequence = combination.split(' '),\n            info;\n\n        // if this pattern is a sequence of keys then run through this method\n        // to reprocess each pattern one key at a time\n        if (sequence.length > 1) {\n            _bindSequence(combination, sequence, callback, action);\n            return;\n        }\n\n        info = _getKeyInfo(combination, action);\n\n        // make sure to initialize array if this is the first time\n        // a callback is added for this key\n        _callbacks[info.key] = _callbacks[info.key] || [];\n\n        // remove an existing match if there is one\n        _getMatches(info.key, info.modifiers, {type: info.action}, sequenceName, combination, level);\n\n        // add this call back to the array\n        // if it is a sequence put it at the beginning\n        // if not put it at the end\n        //\n        // this is important because the way these are processed expects\n        // the sequence ones to come first\n        _callbacks[info.key][sequenceName ? 'unshift' : 'push']({\n            callback: callback,\n            modifiers: info.modifiers,\n            action: info.action,\n            seq: sequenceName,\n            level: level,\n            combo: combination\n        });\n    }\n\n    /**\n     * binds multiple combinations to the same callback\n     *\n     * @param {Array} combinations\n     * @param {Function} callback\n     * @param {string|undefined} action\n     * @returns void\n     */\n    function _bindMultiple(combinations, callback, action) {\n        for (var i = 0; i < combinations.length; ++i) {\n            _bindSingle(combinations[i], callback, action);\n        }\n    }\n\n    // start!\n    _addEvent(document, 'keypress', _handleKeyEvent);\n    _addEvent(document, 'keydown', _handleKeyEvent);\n    _addEvent(document, 'keyup', _handleKeyEvent);\n\n    var Mousetrap = {\n\n        /**\n         * binds an event to mousetrap\n         *\n         * can be a single key, a combination of keys separated with +,\n         * an array of keys, or a sequence of keys separated by spaces\n         *\n         * be sure to list the modifier keys first to make sure that the\n         * correct key ends up getting bound (the last key in the pattern)\n         *\n         * @param {string|Array} keys\n         * @param {Function} callback\n         * @param {string=} action - 'keypress', 'keydown', or 'keyup'\n         * @returns void\n         */\n        bind: function(keys, callback, action) {\n            keys = keys instanceof Array ? keys : [keys];\n            _bindMultiple(keys, callback, action);\n            return this;\n        },\n\n        /**\n         * unbinds an event to mousetrap\n         *\n         * the unbinding sets the callback function of the specified key combo\n         * to an empty function and deletes the corresponding key in the\n         * _directMap dict.\n         *\n         * TODO: actually remove this from the _callbacks dictionary instead\n         * of binding an empty function\n         *\n         * the keycombo+action has to be exactly the same as\n         * it was defined in the bind method\n         *\n         * @param {string|Array} keys\n         * @param {string} action\n         * @returns void\n         */\n        unbind: function(keys, action) {\n            return Mousetrap.bind(keys, function() {}, action);\n        },\n\n        /**\n         * triggers an event that has already been bound\n         *\n         * @param {string} keys\n         * @param {string=} action\n         * @returns void\n         */\n        trigger: function(keys, action) {\n            if (_directMap[keys + ':' + action]) {\n                _directMap[keys + ':' + action]({}, keys);\n            }\n            return this;\n        },\n\n        /**\n         * resets the library back to its initial state.  this is useful\n         * if you want to clear out the current keyboard shortcuts and bind\n         * new ones - for example if you switch to another page\n         *\n         * @returns void\n         */\n        reset: function() {\n            _callbacks = {};\n            _directMap = {};\n            return this;\n        },\n\n       /**\n        * should we stop this event before firing off callbacks\n        *\n        * @param {Event} e\n        * @param {Element} element\n        * @return {boolean}\n        */\n        stopCallback: function(e, element) {\n\n            // if the element has the class \"mousetrap\" then no need to stop\n            if ((' ' + element.className + ' ').indexOf(' mousetrap ') > -1) {\n                return false;\n            }\n\n            // stop for input, select, and textarea\n            return element.tagName == 'INPUT' || element.tagName == 'SELECT' || element.tagName == 'TEXTAREA' || element.isContentEditable;\n        },\n\n        /**\n         * exposes _handleKey publicly so it can be overwritten by extensions\n         */\n        handleKey: _handleKey\n    };\n\n    // expose mousetrap to the global object\n    window.Mousetrap = Mousetrap;\n\n    /*\n    <FLOWABLE PATCH START>\n     Can't let hotkeys define itself as a module since it will cause Flowable to not work in Alfresco Share:\n     In Share this file is being loaded from a <script> element (and not using dojos and define/require calls)\n     dojo therefor throws an error named \"multipleDefine\" ( http://dojotoolkit.org/reference-guide/1.10/loader/amd.html )\n     and stops the app.\n\n    // expose mousetrap as an AMD module\n    if (typeof define === 'function' && define.amd) {\n        define(Mousetrap);\n    }\n\n     <FLOWABLE PATCH STOP>\n    */\n}) (window, document);\n"
  },
  {
    "path": "flowable-ui-web/task/libs/angular-hotkeys_1.4.5/hotkeys.css",
    "content": "/*! \n * angular-hotkeys v1.4.5\n * https://chieffancypants.github.io/angular-hotkeys\n * Copyright (c) 2014 Wes Cruver\n * License: MIT\n */\n.cfp-hotkeys-container {\n  display: table !important;\n  position: fixed;\n  width: 100%;\n  height: 100%;\n  top: 0;\n  left: 0;\n  color: #333;\n  font-size: 1em;\n  background-color: rgba(255,255,255,0.9);\n}\n\n.cfp-hotkeys-container.fade {\n  z-index: -1024;\n  visibility: hidden;\n  opacity: 0;\n  -webkit-transition: opacity 0.15s linear;\n  -moz-transition: opacity 0.15s linear;\n  -o-transition: opacity 0.15s linear;\n  transition: opacity 0.15s linear;\n}\n\n.cfp-hotkeys-container.fade.in {\n  z-index: 10002;\n  visibility: visible;\n  opacity: 1;\n}\n\n.cfp-hotkeys-title {\n  font-weight: bold;\n  text-align: center;\n  font-size: 1.2em;\n}\n\n.cfp-hotkeys {\n  width: 100%;\n  height: 100%;\n  display: table-cell;\n  vertical-align: middle;\n}\n\n.cfp-hotkeys table {\n  margin: auto;\n  color: #333;\n}\n\n.cfp-content {\n  display: table-cell;\n  vertical-align: middle;\n}\n\n.cfp-hotkeys-keys {\n  padding: 5px;\n  text-align: right;\n}\n\n.cfp-hotkeys-key {\n  display: inline-block;\n  color: #fff;\n  background-color: #333;\n  border: 1px solid #333;\n  border-radius: 5px;\n  text-align: center;\n  margin-right: 5px;\n  box-shadow: inset 0 1px 0 #666, 0 1px 0 #bbb;\n  padding: 5px 9px;\n  font-size: 1em;\n}\n\n.cfp-hotkeys-text {\n  padding-left: 10px;\n  font-size: 1em;\n}\n\n.cfp-hotkeys-close {\n  position: fixed;\n  top: 20px;\n  right: 20px;\n  font-size: 2em;\n  font-weight: bold;\n  padding: 5px 10px;\n  border: 1px solid #ddd;\n  border-radius: 5px;\n  min-height: 45px;\n  min-width: 45px;\n  text-align: center;\n}\n\n.cfp-hotkeys-close:hover {\n  background-color: #fff;\n  cursor: pointer;\n}\n\n@media all and (max-width: 500px) {\n  .cfp-hotkeys {\n    font-size: 0.8em;\n  }\n}\n\n@media all and (min-width: 750px) {\n  .cfp-hotkeys {\n    font-size: 1.2em;\n  }\n}\n"
  },
  {
    "path": "flowable-ui-web/task/libs/angular-hotkeys_1.4.5/hotkeys.js",
    "content": "/*! \n * angular-hotkeys v1.4.5\n * https://chieffancypants.github.io/angular-hotkeys\n * Copyright (c) 2014 Wes Cruver\n * License: MIT\n */\n/*\n * angular-hotkeys\n *\n * Automatic keyboard shortcuts for your angular apps\n *\n * (c) 2014 Wes Cruver\n * License: MIT\n */\n\n(function() {\n\n  'use strict';\n\n  angular.module('cfp.hotkeys', []).provider('hotkeys', function() {\n\n    /**\n     * Configurable setting to disable the cheatsheet entirely\n     * @type {Boolean}\n     */\n    this.includeCheatSheet = true;\n\n    /**\n     * Configurable setting for the cheat sheet title\n     * @type {String}\n     */\n\n    this.templateTitle = 'Keyboard Shortcuts:';\n\n    /**\n     * Cheat sheet template in the event you want to totally customize it.\n     * @type {String}\n     */\n    this.template = '<div class=\"cfp-hotkeys-container fade\" ng-class=\"{in: helpVisible}\" style=\"display: none;\"><div class=\"cfp-hotkeys\">' +\n                      '<h4 class=\"cfp-hotkeys-title\">{{ title }}</h4>' +\n                      '<table><tbody>' +\n                        '<tr ng-repeat=\"hotkey in hotkeys | filter:{ description: \\'!$$undefined$$\\' }\">' +\n                          '<td class=\"cfp-hotkeys-keys\">' +\n                            '<span ng-repeat=\"key in hotkey.format() track by $index\" class=\"cfp-hotkeys-key\">{{ key }}</span>' +\n                          '</td>' +\n                          '<td class=\"cfp-hotkeys-text\">{{ hotkey.description }}</td>' +\n                        '</tr>' +\n                      '</tbody></table>' +\n                      '<div class=\"cfp-hotkeys-close\" ng-click=\"toggleCheatSheet()\">×</div>' +\n                    '</div></div>';\n\n    /**\n     * Configurable setting for the cheat sheet hotkey\n     * @type {String}\n     */\n    this.cheatSheetHotkey = '?';\n\n    /**\n     * Configurable setting for the cheat sheet description\n     * @type {String}\n     */\n    this.cheatSheetDescription = 'Show / hide this help menu';\n\n    this.$get = ['$rootElement', '$rootScope', '$compile', '$window', '$document', function ($rootElement, $rootScope, $compile, $window, $document) {\n\n      // monkeypatch Mousetrap's stopCallback() function\n      // this version doesn't return true when the element is an INPUT, SELECT, or TEXTAREA\n      // (instead we will perform this check per-key in the _add() method)\n      Mousetrap.stopCallback = function(event, element) {\n        // if the element has the class \"mousetrap\" then no need to stop\n        if ((' ' + element.className + ' ').indexOf(' mousetrap ') > -1) {\n          return false;\n        }\n\n        return (element.contentEditable && element.contentEditable == 'true');\n      };\n\n      /**\n       * Convert strings like cmd into symbols like ⌘\n       * @param  {String} combo Key combination, e.g. 'mod+f'\n       * @return {String}       The key combination with symbols\n       */\n      function symbolize (combo) {\n        var map = {\n          command   : '⌘',\n          shift     : '⇧',\n          left      : '←',\n          right     : '→',\n          up        : '↑',\n          down      : '↓',\n          'return'  : '↩',\n          backspace : '⌫'\n        };\n        combo = combo.split('+');\n\n        for (var i = 0; i < combo.length; i++) {\n          // try to resolve command / ctrl based on OS:\n          if (combo[i] === 'mod') {\n            if ($window.navigator && $window.navigator.platform.indexOf('Mac') >=0 ) {\n              combo[i] = 'command';\n            } else {\n              combo[i] = 'ctrl';\n            }\n          }\n\n          combo[i] = map[combo[i]] || combo[i];\n        }\n\n        return combo.join(' + ');\n      }\n\n      /**\n       * Hotkey object used internally for consistency\n       *\n       * @param {array}    combo       The keycombo. it's an array to support multiple combos\n       * @param {String}   description Description for the keycombo\n       * @param {Function} callback    function to execute when keycombo pressed\n       * @param {string}   action      the type of event to listen for (for mousetrap)\n       * @param {array}    allowIn     an array of tag names to allow this combo in ('INPUT', 'SELECT', and/or 'TEXTAREA')\n       * @param {Boolean}  persistent  Whether the hotkey persists navigation events\n       */\n      function Hotkey (combo, description, callback, action, allowIn, persistent) {\n        // TODO: Check that the values are sane because we could\n        // be trying to instantiate a new Hotkey with outside dev's\n        // supplied values\n\n        this.combo = combo instanceof Array ? combo : [combo];\n        this.description = description;\n        this.callback = callback;\n        this.action = action;\n        this.allowIn = allowIn;\n        this.persistent = persistent;\n      }\n\n      /**\n       * Helper method to format (symbolize) the key combo for display\n       *\n       * @return {[Array]} An array of the key combination sequence\n       *   for example: \"command+g c i\" becomes [\"⌘ + g\", \"c\", \"i\"]\n       *\n       * TODO: this gets called a lot.  We should cache the result\n       */\n      Hotkey.prototype.format = function() {\n\n        // Don't show all the possible key combos, just the first one.  Not sure\n        // of usecase here, so open a ticket if my assumptions are wrong\n        var combo = this.combo[0];\n\n        var sequence = combo.split(/[\\s]/);\n        for (var i = 0; i < sequence.length; i++) {\n          sequence[i] = symbolize(sequence[i]);\n        }\n\n        return sequence;\n      };\n\n      /**\n       * A new scope used internally for the cheatsheet\n       * @type {$rootScope.Scope}\n       */\n      var scope = $rootScope.$new();\n\n      /**\n       * Holds an array of Hotkey objects currently bound\n       * @type {Array}\n       */\n      scope.hotkeys = [];\n\n      /**\n       * Contains the state of the help's visibility\n       * @type {Boolean}\n       */\n      scope.helpVisible = false;\n\n      /**\n       * Holds the title string for the help menu\n       * @type {String}\n       */\n      scope.title = this.templateTitle;\n\n      /**\n       * Expose toggleCheatSheet to hotkeys scope so we can call it using\n       * ng-click from the template\n       * @type {function}\n       */\n      scope.toggleCheatSheet = toggleCheatSheet;\n\n\n      /**\n       * Holds references to the different scopes that have bound hotkeys\n       * attached.  This is useful to catch when the scopes are `$destroy`d and\n       * then automatically unbind the hotkey.\n       *\n       * @type {Array}\n       */\n      var boundScopes = [];\n\n\n      $rootScope.$on('$routeChangeSuccess', function (event, route) {\n        purgeHotkeys();\n\n        if (route && route.hotkeys) {\n          angular.forEach(route.hotkeys, function (hotkey) {\n            // a string was given, which implies this is a function that is to be\n            // $eval()'d within that controller's scope\n            // TODO: hotkey here is super confusing.  sometimes a function (that gets turned into an array), sometimes a string\n            var callback = hotkey[2];\n            if (typeof(callback) === 'string' || callback instanceof String) {\n              hotkey[2] = [callback, route];\n            }\n\n            // todo: perform check to make sure not already defined:\n            // this came from a route, so it's likely not meant to be persistent\n            hotkey[5] = false;\n            _add.apply(this, hotkey);\n          });\n        }\n      });\n\n\n      // Auto-create a help menu:\n      if (this.includeCheatSheet) {\n        var document = $document[0];\n        var element = $rootElement[0];\n        var helpMenu = angular.element(this.template);\n        _add(this.cheatSheetHotkey, this.cheatSheetDescription, toggleCheatSheet);\n\n        // If $rootElement is document or documentElement, then body must be used\n        if (element === document || element === document.documentElement) {\n          element = document.body;\n        }\n\n        angular.element(element).append($compile(helpMenu)(scope));\n      }\n\n\n      /**\n       * Purges all non-persistent hotkeys (such as those defined in routes)\n       *\n       * Without this, the same hotkey would get recreated everytime\n       * the route is accessed.\n       */\n      function purgeHotkeys() {\n        var i = scope.hotkeys.length;\n        while (i--) {\n          var hotkey = scope.hotkeys[i];\n          if (hotkey && !hotkey.persistent) {\n            _del(hotkey);\n          }\n        }\n      }\n\n      /**\n       * Toggles the help menu element's visiblity\n       */\n      var previousEsc = false;\n\n      function toggleCheatSheet() {\n        scope.helpVisible = !scope.helpVisible;\n\n        // Bind to esc to remove the cheat sheet.  Ideally, this would be done\n        // as a directive in the template, but that would create a nasty\n        // circular dependency issue that I don't feel like sorting out.\n        if (scope.helpVisible) {\n          previousEsc = _get('esc');\n          _del('esc');\n\n          // Here's an odd way to do this: we're going to use the original\n          // description of the hotkey on the cheat sheet so that it shows up.\n          // without it, no entry for esc will ever show up (#22)\n          _add('esc', previousEsc.description, toggleCheatSheet);\n        } else {\n          _del('esc');\n\n          // restore the previously bound ESC key\n          if (previousEsc !== false) {\n            _add(previousEsc);\n          }\n        }\n      }\n\n      /**\n       * Creates a new Hotkey and creates the Mousetrap binding\n       *\n       * @param {string}   combo       mousetrap key binding\n       * @param {string}   description description for the help menu\n       * @param {Function} callback    method to call when key is pressed\n       * @param {string}   action      the type of event to listen for (for mousetrap)\n       * @param {array}    allowIn     an array of tag names to allow this combo in ('INPUT', 'SELECT', and/or 'TEXTAREA')\n       * @param {boolean}  persistent  if true, the binding is preserved upon route changes\n       */\n      function _add (combo, description, callback, action, allowIn, persistent) {\n\n        // used to save original callback for \"allowIn\" wrapping:\n        var _callback;\n\n        // these elements are prevented by the default Mousetrap.stopCallback():\n        var preventIn = ['INPUT', 'SELECT', 'TEXTAREA'];\n\n        // Determine if object format was given:\n        var objType = Object.prototype.toString.call(combo);\n\n        if (objType === '[object Object]') {\n          description = combo.description;\n          callback    = combo.callback;\n          action      = combo.action;\n          persistent  = combo.persistent;\n          allowIn     = combo.allowIn;\n          combo       = combo.combo;\n        }\n\n        // description is optional:\n        if (description instanceof Function) {\n          action = callback;\n          callback = description;\n          description = '$$undefined$$';\n        } else if (angular.isUndefined(description)) {\n          description = '$$undefined$$';\n        }\n\n        // any items added through the public API are for controllers\n        // that persist through navigation, and thus undefined should mean\n        // true in this case.\n        if (persistent === undefined) {\n          persistent = true;\n        }\n\n        // if callback is defined, then wrap it in a function\n        // that checks if the event originated from a form element.\n        // the function blocks the callback from executing unless the element is specified\n        // in allowIn (emulates Mousetrap.stopCallback() on a per-key level)\n        if (typeof callback === 'function') {\n\n          // save the original callback\n          _callback = callback;\n\n          // make sure allowIn is an array\n          if (!(allowIn instanceof Array)) {\n            allowIn = [];\n          }\n\n          // remove anything from preventIn that's present in allowIn\n          var index;\n          for (var i=0; i < allowIn.length; i++) {\n            allowIn[i] = allowIn[i].toUpperCase();\n            index = preventIn.indexOf(allowIn[i]);\n            if (index !== -1) {\n              preventIn.splice(index, 1);\n            }\n          }\n\n          // create the new wrapper callback\n          callback = function(event) {\n            var shouldExecute = true;\n            var target = event.target || event.srcElement; // srcElement is IE only\n            var nodeName = target.nodeName.toUpperCase();\n\n            // check if the input has a mousetrap class, and skip checking preventIn if so\n            if ((' ' + target.className + ' ').indexOf(' mousetrap ') > -1) {\n              shouldExecute = true;\n            } else {\n              // don't execute callback if the event was fired from inside an element listed in preventIn\n              for (var i=0; i<preventIn.length; i++) {\n                if (preventIn[i] === nodeName) {\n                  shouldExecute = false;\n                  break;\n                }\n              }\n            }\n\n            if (shouldExecute) {\n              wrapApply(_callback.apply(this, arguments));\n            }\n          };\n        }\n\n        if (typeof(action) === 'string') {\n          Mousetrap.bind(combo, wrapApply(callback), action);\n        } else {\n          Mousetrap.bind(combo, wrapApply(callback));\n        }\n\n        var hotkey = new Hotkey(combo, description, callback, action, allowIn, persistent);\n        scope.hotkeys.push(hotkey);\n        return hotkey;\n      }\n\n      /**\n       * delete and unbind a Hotkey\n       *\n       * @param  {mixed} hotkey   Either the bound key or an instance of Hotkey\n       * @return {boolean}        true if successful\n       */\n      function _del (hotkey) {\n        var combo = (hotkey instanceof Hotkey) ? hotkey.combo : hotkey;\n\n        Mousetrap.unbind(combo);\n\n        if (angular.isArray(combo)) {\n          var retStatus = true;\n          var i = combo.length;\n          while (i--) {\n            retStatus = _del(combo[i]) && retStatus;\n          }\n          return retStatus;\n        } else {\n          var index = scope.hotkeys.indexOf(_get(combo));\n\n          if (index > -1) {\n            // if the combo has other combos bound, don't unbind the whole thing, just the one combo:\n            if (scope.hotkeys[index].combo.length > 1) {\n              scope.hotkeys[index].combo.splice(scope.hotkeys[index].combo.indexOf(combo), 1);\n            } else {\n              scope.hotkeys.splice(index, 1);\n            }\n            return true;\n          }\n        }\n\n        return false;\n\n      }\n\n      /**\n       * Get a Hotkey object by key binding\n       *\n       * @param  {[string]} combo  the key the Hotkey is bound to\n       * @return {Hotkey}          The Hotkey object\n       */\n      function _get (combo) {\n\n        var hotkey;\n\n        for (var i = 0; i < scope.hotkeys.length; i++) {\n          hotkey = scope.hotkeys[i];\n\n          if (hotkey.combo.indexOf(combo) > -1) {\n            return hotkey;\n          }\n        }\n\n        return false;\n      }\n\n      /**\n       * Binds the hotkey to a particular scope.  Useful if the scope is\n       * destroyed, we can automatically destroy the hotkey binding.\n       *\n       * @param  {Object} scope The scope to bind to\n       */\n      function bindTo (scope) {\n        // Only initialize once to allow multiple calls for same scope.\n        if (!(scope.$id in boundScopes)) {\n\n          // Add the scope to the list of bound scopes\n          boundScopes[scope.$id] = [];\n\n          scope.$on('$destroy', function () {\n            var i = boundScopes[scope.$id].length;\n            while (i--) {\n              _del(boundScopes[scope.$id][i]);\n              delete boundScopes[scope.$id][i];\n            }\n          });\n        }\n        // return an object with an add function so we can keep track of the\n        // hotkeys and their scope that we added via this chaining method\n        return {\n          add: function (args) {\n            var hotkey;\n\n            if (arguments.length > 1) {\n              hotkey = _add.apply(this, arguments);\n            } else {\n              hotkey = _add(args);\n            }\n\n            boundScopes[scope.$id].push(hotkey);\n            return this;\n          }\n        };\n      }\n\n      /**\n       * All callbacks sent to Mousetrap are wrapped using this function\n       * so that we can force a $scope.$apply()\n       *\n       * @param  {Function} callback [description]\n       * @return {[type]}            [description]\n       */\n      function wrapApply (callback) {\n        // return mousetrap a function to call\n        return function (event, combo) {\n\n          // if this is an array, it means we provided a route object\n          // because the scope wasn't available yet, so rewrap the callback\n          // now that the scope is available:\n          if (callback instanceof Array) {\n            var funcString = callback[0];\n            var route = callback[1];\n            callback = function (event) {\n              route.scope.$eval(funcString);\n            };\n          }\n\n          // this takes place outside angular, so we'll have to call\n          // $apply() to make sure angular's digest happens\n          $rootScope.$apply(function() {\n            // call the original hotkey callback with the keyboard event\n            callback(event, _get(combo));\n          });\n        };\n      }\n\n\n      var publicApi = {\n        add                   : _add,\n        del                   : _del,\n        get                   : _get,\n        bindTo                : bindTo,\n        template              : this.template,\n        toggleCheatSheet      : toggleCheatSheet,\n        includeCheatSheet     : this.includeCheatSheet,\n        cheatSheetHotkey      : this.cheatSheetHotkey,\n        cheatSheetDescription : this.cheatSheetDescription,\n        purgeHotkeys          : purgeHotkeys,\n        templateTitle         : this.templateTitle\n      };\n\n      return publicApi;\n\n    }];\n  })\n\n  .directive('hotkey', ['hotkeys', function (hotkeys) {\n    return {\n      restrict: 'A',\n      link: function (scope, el, attrs) {\n        var key, allowIn;\n\n        angular.forEach(scope.$eval(attrs.hotkey), function (func, hotkey) {\n          // split and trim the hotkeys string into array\n          allowIn = typeof attrs.hotkeyAllowIn === \"string\" ? attrs.hotkeyAllowIn.split(/[\\s,]+/) : [];\n\n          key = hotkey;\n\n          hotkeys.add({\n            combo: hotkey,\n            description: attrs.hotkeyDescription,\n            callback: func,\n            action: attrs.hotkeyAction,\n            allowIn: allowIn\n          });\n        });\n\n        // remove the hotkey if the directive is destroyed:\n        el.bind('$destroy', function() {\n          hotkeys.del(key);\n        });\n      }\n    };\n  }])\n\n  .run(['hotkeys', function(hotkeys) {\n    // force hotkeys to run by injecting it. Without this, hotkeys only runs\n    // when a controller or something else asks for it via DI.\n  }]);\n\n})();\n\n/*global define:false */\n/**\n * Copyright 2013 Craig Campbell\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 * Mousetrap is a simple keyboard shortcut library for Javascript with\n * no external dependencies\n *\n * @version 1.4.6\n * @url craig.is/killing/mice\n */\n(function(window, document, undefined) {\n\n    /**\n     * mapping of special keycodes to their corresponding keys\n     *\n     * everything in this dictionary cannot use keypress events\n     * so it has to be here to map to the correct keycodes for\n     * keyup/keydown events\n     *\n     * @type {Object}\n     */\n    var _MAP = {\n            8: 'backspace',\n            9: 'tab',\n            13: 'enter',\n            16: 'shift',\n            17: 'ctrl',\n            18: 'alt',\n            20: 'capslock',\n            27: 'esc',\n            32: 'space',\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: 'ins',\n            46: 'del',\n            91: 'meta',\n            93: 'meta',\n            224: 'meta'\n        },\n\n        /**\n         * mapping for special characters so they can support\n         *\n         * this dictionary is only used incase you want to bind a\n         * keyup or keydown event to one of these keys\n         *\n         * @type {Object}\n         */\n        _KEYCODE_MAP = {\n            106: '*',\n            107: '+',\n            109: '-',\n            110: '.',\n            111 : '/',\n            186: ';',\n            187: '=',\n            188: ',',\n            189: '-',\n            190: '.',\n            191: '/',\n            192: '`',\n            219: '[',\n            220: '\\\\',\n            221: ']',\n            222: '\\''\n        },\n\n        /**\n         * this is a mapping of keys that require shift on a US keypad\n         * back to the non shift equivelents\n         *\n         * this is so you can use keyup events with these keys\n         *\n         * note that this will only work reliably on US keyboards\n         *\n         * @type {Object}\n         */\n        _SHIFT_MAP = {\n            '~': '`',\n            '!': '1',\n            '@': '2',\n            '#': '3',\n            '$': '4',\n            '%': '5',\n            '^': '6',\n            '&': '7',\n            '*': '8',\n            '(': '9',\n            ')': '0',\n            '_': '-',\n            '+': '=',\n            ':': ';',\n            '\\\"': '\\'',\n            '<': ',',\n            '>': '.',\n            '?': '/',\n            '|': '\\\\'\n        },\n\n        /**\n         * this is a list of special strings you can use to map\n         * to modifier keys when you specify your keyboard shortcuts\n         *\n         * @type {Object}\n         */\n        _SPECIAL_ALIASES = {\n            'option': 'alt',\n            'command': 'meta',\n            'return': 'enter',\n            'escape': 'esc',\n            'mod': /Mac|iPod|iPhone|iPad/.test(navigator.platform) ? 'meta' : 'ctrl'\n        },\n\n        /**\n         * variable to store the flipped version of _MAP from above\n         * needed to check if we should use keypress or not when no action\n         * is specified\n         *\n         * @type {Object|undefined}\n         */\n        _REVERSE_MAP,\n\n        /**\n         * a list of all the callbacks setup via Mousetrap.bind()\n         *\n         * @type {Object}\n         */\n        _callbacks = {},\n\n        /**\n         * direct map of string combinations to callbacks used for trigger()\n         *\n         * @type {Object}\n         */\n        _directMap = {},\n\n        /**\n         * keeps track of what level each sequence is at since multiple\n         * sequences can start out with the same sequence\n         *\n         * @type {Object}\n         */\n        _sequenceLevels = {},\n\n        /**\n         * variable to store the setTimeout call\n         *\n         * @type {null|number}\n         */\n        _resetTimer,\n\n        /**\n         * temporary state where we will ignore the next keyup\n         *\n         * @type {boolean|string}\n         */\n        _ignoreNextKeyup = false,\n\n        /**\n         * temporary state where we will ignore the next keypress\n         *\n         * @type {boolean}\n         */\n        _ignoreNextKeypress = false,\n\n        /**\n         * are we currently inside of a sequence?\n         * type of action (\"keyup\" or \"keydown\" or \"keypress\") or false\n         *\n         * @type {boolean|string}\n         */\n        _nextExpectedAction = false;\n\n    /**\n     * loop through the f keys, f1 to f19 and add them to the map\n     * programatically\n     */\n    for (var i = 1; i < 20; ++i) {\n        _MAP[111 + i] = 'f' + i;\n    }\n\n    /**\n     * loop through to map numbers on the numeric keypad\n     */\n    for (i = 0; i <= 9; ++i) {\n        _MAP[i + 96] = i;\n    }\n\n    /**\n     * cross browser add event method\n     *\n     * @param {Element|HTMLDocument} object\n     * @param {string} type\n     * @param {Function} callback\n     * @returns void\n     */\n    function _addEvent(object, type, callback) {\n        if (object.addEventListener) {\n            object.addEventListener(type, callback, false);\n            return;\n        }\n\n        object.attachEvent('on' + type, callback);\n    }\n\n    /**\n     * takes the event and returns the key character\n     *\n     * @param {Event} e\n     * @return {string}\n     */\n    function _characterFromEvent(e) {\n\n        // for keypress events we should return the character as is\n        if (e.type == 'keypress') {\n            var character = String.fromCharCode(e.which);\n\n            // if the shift key is not pressed then it is safe to assume\n            // that we want the character to be lowercase.  this means if\n            // you accidentally have caps lock on then your key bindings\n            // will continue to work\n            //\n            // the only side effect that might not be desired is if you\n            // bind something like 'A' cause you want to trigger an\n            // event when capital A is pressed caps lock will no longer\n            // trigger the event.  shift+a will though.\n            if (!e.shiftKey) {\n                character = character.toLowerCase();\n            }\n\n            return character;\n        }\n\n        // for non keypress events the special maps are needed\n        if (_MAP[e.which]) {\n            return _MAP[e.which];\n        }\n\n        if (_KEYCODE_MAP[e.which]) {\n            return _KEYCODE_MAP[e.which];\n        }\n\n        // if it is not in the special map\n\n        // with keydown and keyup events the character seems to always\n        // come in as an uppercase character whether you are pressing shift\n        // or not.  we should make sure it is always lowercase for comparisons\n        return String.fromCharCode(e.which).toLowerCase();\n    }\n\n    /**\n     * checks if two arrays are equal\n     *\n     * @param {Array} modifiers1\n     * @param {Array} modifiers2\n     * @returns {boolean}\n     */\n    function _modifiersMatch(modifiers1, modifiers2) {\n        return modifiers1.sort().join(',') === modifiers2.sort().join(',');\n    }\n\n    /**\n     * resets all sequence counters except for the ones passed in\n     *\n     * @param {Object} doNotReset\n     * @returns void\n     */\n    function _resetSequences(doNotReset) {\n        doNotReset = doNotReset || {};\n\n        var activeSequences = false,\n            key;\n\n        for (key in _sequenceLevels) {\n            if (doNotReset[key]) {\n                activeSequences = true;\n                continue;\n            }\n            _sequenceLevels[key] = 0;\n        }\n\n        if (!activeSequences) {\n            _nextExpectedAction = false;\n        }\n    }\n\n    /**\n     * finds all callbacks that match based on the keycode, modifiers,\n     * and action\n     *\n     * @param {string} character\n     * @param {Array} modifiers\n     * @param {Event|Object} e\n     * @param {string=} sequenceName - name of the sequence we are looking for\n     * @param {string=} combination\n     * @param {number=} level\n     * @returns {Array}\n     */\n    function _getMatches(character, modifiers, e, sequenceName, combination, level) {\n        var i,\n            callback,\n            matches = [],\n            action = e.type;\n\n        // if there are no events related to this keycode\n        if (!_callbacks[character]) {\n            return [];\n        }\n\n        // if a modifier key is coming up on its own we should allow it\n        if (action == 'keyup' && _isModifier(character)) {\n            modifiers = [character];\n        }\n\n        // loop through all callbacks for the key that was pressed\n        // and see if any of them match\n        for (i = 0; i < _callbacks[character].length; ++i) {\n            callback = _callbacks[character][i];\n\n            // if a sequence name is not specified, but this is a sequence at\n            // the wrong level then move onto the next match\n            if (!sequenceName && callback.seq && _sequenceLevels[callback.seq] != callback.level) {\n                continue;\n            }\n\n            // if the action we are looking for doesn't match the action we got\n            // then we should keep going\n            if (action != callback.action) {\n                continue;\n            }\n\n            // if this is a keypress event and the meta key and control key\n            // are not pressed that means that we need to only look at the\n            // character, otherwise check the modifiers as well\n            //\n            // chrome will not fire a keypress if meta or control is down\n            // safari will fire a keypress if meta or meta+shift is down\n            // firefox will fire a keypress if meta or control is down\n            if ((action == 'keypress' && !e.metaKey && !e.ctrlKey) || _modifiersMatch(modifiers, callback.modifiers)) {\n\n                // when you bind a combination or sequence a second time it\n                // should overwrite the first one.  if a sequenceName or\n                // combination is specified in this call it does just that\n                //\n                // @todo make deleting its own method?\n                var deleteCombo = !sequenceName && callback.combo == combination;\n                var deleteSequence = sequenceName && callback.seq == sequenceName && callback.level == level;\n                if (deleteCombo || deleteSequence) {\n                    _callbacks[character].splice(i, 1);\n                }\n\n                matches.push(callback);\n            }\n        }\n\n        return matches;\n    }\n\n    /**\n     * takes a key event and figures out what the modifiers are\n     *\n     * @param {Event} e\n     * @returns {Array}\n     */\n    function _eventModifiers(e) {\n        var modifiers = [];\n\n        if (e.shiftKey) {\n            modifiers.push('shift');\n        }\n\n        if (e.altKey) {\n            modifiers.push('alt');\n        }\n\n        if (e.ctrlKey) {\n            modifiers.push('ctrl');\n        }\n\n        if (e.metaKey) {\n            modifiers.push('meta');\n        }\n\n        return modifiers;\n    }\n\n    /**\n     * prevents default for this event\n     *\n     * @param {Event} e\n     * @returns void\n     */\n    function _preventDefault(e) {\n        if (e.preventDefault) {\n            e.preventDefault();\n            return;\n        }\n\n        e.returnValue = false;\n    }\n\n    /**\n     * stops propogation for this event\n     *\n     * @param {Event} e\n     * @returns void\n     */\n    function _stopPropagation(e) {\n        if (e.stopPropagation) {\n            e.stopPropagation();\n            return;\n        }\n\n        e.cancelBubble = true;\n    }\n\n    /**\n     * actually calls the callback function\n     *\n     * if your callback function returns false this will use the jquery\n     * convention - prevent default and stop propogation on the event\n     *\n     * @param {Function} callback\n     * @param {Event} e\n     * @returns void\n     */\n    function _fireCallback(callback, e, combo, sequence) {\n\n        // if this event should not happen stop here\n        if (Mousetrap.stopCallback(e, e.target || e.srcElement, combo, sequence)) {\n            return;\n        }\n\n        if (callback(e, combo) === false) {\n            _preventDefault(e);\n            _stopPropagation(e);\n        }\n    }\n\n    /**\n     * handles a character key event\n     *\n     * @param {string} character\n     * @param {Array} modifiers\n     * @param {Event} e\n     * @returns void\n     */\n    function _handleKey(character, modifiers, e) {\n        var callbacks = _getMatches(character, modifiers, e),\n            i,\n            doNotReset = {},\n            maxLevel = 0,\n            processedSequenceCallback = false;\n\n        // Calculate the maxLevel for sequences so we can only execute the longest callback sequence\n        for (i = 0; i < callbacks.length; ++i) {\n            if (callbacks[i].seq) {\n                maxLevel = Math.max(maxLevel, callbacks[i].level);\n            }\n        }\n\n        // loop through matching callbacks for this key event\n        for (i = 0; i < callbacks.length; ++i) {\n\n            // fire for all sequence callbacks\n            // this is because if for example you have multiple sequences\n            // bound such as \"g i\" and \"g t\" they both need to fire the\n            // callback for matching g cause otherwise you can only ever\n            // match the first one\n            if (callbacks[i].seq) {\n\n                // only fire callbacks for the maxLevel to prevent\n                // subsequences from also firing\n                //\n                // for example 'a option b' should not cause 'option b' to fire\n                // even though 'option b' is part of the other sequence\n                //\n                // any sequences that do not match here will be discarded\n                // below by the _resetSequences call\n                if (callbacks[i].level != maxLevel) {\n                    continue;\n                }\n\n                processedSequenceCallback = true;\n\n                // keep a list of which sequences were matches for later\n                doNotReset[callbacks[i].seq] = 1;\n                _fireCallback(callbacks[i].callback, e, callbacks[i].combo, callbacks[i].seq);\n                continue;\n            }\n\n            // if there were no sequence matches but we are still here\n            // that means this is a regular match so we should fire that\n            if (!processedSequenceCallback) {\n                _fireCallback(callbacks[i].callback, e, callbacks[i].combo);\n            }\n        }\n\n        // if the key you pressed matches the type of sequence without\n        // being a modifier (ie \"keyup\" or \"keypress\") then we should\n        // reset all sequences that were not matched by this event\n        //\n        // this is so, for example, if you have the sequence \"h a t\" and you\n        // type \"h e a r t\" it does not match.  in this case the \"e\" will\n        // cause the sequence to reset\n        //\n        // modifier keys are ignored because you can have a sequence\n        // that contains modifiers such as \"enter ctrl+space\" and in most\n        // cases the modifier key will be pressed before the next key\n        //\n        // also if you have a sequence such as \"ctrl+b a\" then pressing the\n        // \"b\" key will trigger a \"keypress\" and a \"keydown\"\n        //\n        // the \"keydown\" is expected when there is a modifier, but the\n        // \"keypress\" ends up matching the _nextExpectedAction since it occurs\n        // after and that causes the sequence to reset\n        //\n        // we ignore keypresses in a sequence that directly follow a keydown\n        // for the same character\n        var ignoreThisKeypress = e.type == 'keypress' && _ignoreNextKeypress;\n        if (e.type == _nextExpectedAction && !_isModifier(character) && !ignoreThisKeypress) {\n            _resetSequences(doNotReset);\n        }\n\n        _ignoreNextKeypress = processedSequenceCallback && e.type == 'keydown';\n    }\n\n    /**\n     * handles a keydown event\n     *\n     * @param {Event} e\n     * @returns void\n     */\n    function _handleKeyEvent(e) {\n\n        // normalize e.which for key events\n        // @see http://stackoverflow.com/questions/4285627/javascript-keycode-vs-charcode-utter-confusion\n        if (typeof e.which !== 'number') {\n            e.which = e.keyCode;\n        }\n\n        var character = _characterFromEvent(e);\n\n        // no character found then stop\n        if (!character) {\n            return;\n        }\n\n        // need to use === for the character check because the character can be 0\n        if (e.type == 'keyup' && _ignoreNextKeyup === character) {\n            _ignoreNextKeyup = false;\n            return;\n        }\n\n        Mousetrap.handleKey(character, _eventModifiers(e), e);\n    }\n\n    /**\n     * determines if the keycode specified is a modifier key or not\n     *\n     * @param {string} key\n     * @returns {boolean}\n     */\n    function _isModifier(key) {\n        return key == 'shift' || key == 'ctrl' || key == 'alt' || key == 'meta';\n    }\n\n    /**\n     * called to set a 1 second timeout on the specified sequence\n     *\n     * this is so after each key press in the sequence you have 1 second\n     * to press the next key before you have to start over\n     *\n     * @returns void\n     */\n    function _resetSequenceTimer() {\n        clearTimeout(_resetTimer);\n        _resetTimer = setTimeout(_resetSequences, 1000);\n    }\n\n    /**\n     * reverses the map lookup so that we can look for specific keys\n     * to see what can and can't use keypress\n     *\n     * @return {Object}\n     */\n    function _getReverseMap() {\n        if (!_REVERSE_MAP) {\n            _REVERSE_MAP = {};\n            for (var key in _MAP) {\n\n                // pull out the numeric keypad from here cause keypress should\n                // be able to detect the keys from the character\n                if (key > 95 && key < 112) {\n                    continue;\n                }\n\n                if (_MAP.hasOwnProperty(key)) {\n                    _REVERSE_MAP[_MAP[key]] = key;\n                }\n            }\n        }\n        return _REVERSE_MAP;\n    }\n\n    /**\n     * picks the best action based on the key combination\n     *\n     * @param {string} key - character for key\n     * @param {Array} modifiers\n     * @param {string=} action passed in\n     */\n    function _pickBestAction(key, modifiers, action) {\n\n        // if no action was picked in we should try to pick the one\n        // that we think would work best for this key\n        if (!action) {\n            action = _getReverseMap()[key] ? 'keydown' : 'keypress';\n        }\n\n        // modifier keys don't work as expected with keypress,\n        // switch to keydown\n        if (action == 'keypress' && modifiers.length) {\n            action = 'keydown';\n        }\n\n        return action;\n    }\n\n    /**\n     * binds a key sequence to an event\n     *\n     * @param {string} combo - combo specified in bind call\n     * @param {Array} keys\n     * @param {Function} callback\n     * @param {string=} action\n     * @returns void\n     */\n    function _bindSequence(combo, keys, callback, action) {\n\n        // start off by adding a sequence level record for this combination\n        // and setting the level to 0\n        _sequenceLevels[combo] = 0;\n\n        /**\n         * callback to increase the sequence level for this sequence and reset\n         * all other sequences that were active\n         *\n         * @param {string} nextAction\n         * @returns {Function}\n         */\n        function _increaseSequence(nextAction) {\n            return function() {\n                _nextExpectedAction = nextAction;\n                ++_sequenceLevels[combo];\n                _resetSequenceTimer();\n            };\n        }\n\n        /**\n         * wraps the specified callback inside of another function in order\n         * to reset all sequence counters as soon as this sequence is done\n         *\n         * @param {Event} e\n         * @returns void\n         */\n        function _callbackAndReset(e) {\n            _fireCallback(callback, e, combo);\n\n            // we should ignore the next key up if the action is key down\n            // or keypress.  this is so if you finish a sequence and\n            // release the key the final key will not trigger a keyup\n            if (action !== 'keyup') {\n                _ignoreNextKeyup = _characterFromEvent(e);\n            }\n\n            // weird race condition if a sequence ends with the key\n            // another sequence begins with\n            setTimeout(_resetSequences, 10);\n        }\n\n        // loop through keys one at a time and bind the appropriate callback\n        // function.  for any key leading up to the final one it should\n        // increase the sequence. after the final, it should reset all sequences\n        //\n        // if an action is specified in the original bind call then that will\n        // be used throughout.  otherwise we will pass the action that the\n        // next key in the sequence should match.  this allows a sequence\n        // to mix and match keypress and keydown events depending on which\n        // ones are better suited to the key provided\n        for (var i = 0; i < keys.length; ++i) {\n            var isFinal = i + 1 === keys.length;\n            var wrappedCallback = isFinal ? _callbackAndReset : _increaseSequence(action || _getKeyInfo(keys[i + 1]).action);\n            _bindSingle(keys[i], wrappedCallback, action, combo, i);\n        }\n    }\n\n    /**\n     * Converts from a string key combination to an array\n     *\n     * @param  {string} combination like \"command+shift+l\"\n     * @return {Array}\n     */\n    function _keysFromString(combination) {\n        if (combination === '+') {\n            return ['+'];\n        }\n\n        return combination.split('+');\n    }\n\n    /**\n     * Gets info for a specific key combination\n     *\n     * @param  {string} combination key combination (\"command+s\" or \"a\" or \"*\")\n     * @param  {string=} action\n     * @returns {Object}\n     */\n    function _getKeyInfo(combination, action) {\n        var keys,\n            key,\n            i,\n            modifiers = [];\n\n        // take the keys from this pattern and figure out what the actual\n        // pattern is all about\n        keys = _keysFromString(combination);\n\n        for (i = 0; i < keys.length; ++i) {\n            key = keys[i];\n\n            // normalize key names\n            if (_SPECIAL_ALIASES[key]) {\n                key = _SPECIAL_ALIASES[key];\n            }\n\n            // if this is not a keypress event then we should\n            // be smart about using shift keys\n            // this will only work for US keyboards however\n            if (action && action != 'keypress' && _SHIFT_MAP[key]) {\n                key = _SHIFT_MAP[key];\n                modifiers.push('shift');\n            }\n\n            // if this key is a modifier then add it to the list of modifiers\n            if (_isModifier(key)) {\n                modifiers.push(key);\n            }\n        }\n\n        // depending on what the key combination is\n        // we will try to pick the best event for it\n        action = _pickBestAction(key, modifiers, action);\n\n        return {\n            key: key,\n            modifiers: modifiers,\n            action: action\n        };\n    }\n\n    /**\n     * binds a single keyboard combination\n     *\n     * @param {string} combination\n     * @param {Function} callback\n     * @param {string=} action\n     * @param {string=} sequenceName - name of sequence if part of sequence\n     * @param {number=} level - what part of the sequence the command is\n     * @returns void\n     */\n    function _bindSingle(combination, callback, action, sequenceName, level) {\n\n        // store a direct mapped reference for use with Mousetrap.trigger\n        _directMap[combination + ':' + action] = callback;\n\n        // make sure multiple spaces in a row become a single space\n        combination = combination.replace(/\\s+/g, ' ');\n\n        var sequence = combination.split(' '),\n            info;\n\n        // if this pattern is a sequence of keys then run through this method\n        // to reprocess each pattern one key at a time\n        if (sequence.length > 1) {\n            _bindSequence(combination, sequence, callback, action);\n            return;\n        }\n\n        info = _getKeyInfo(combination, action);\n\n        // make sure to initialize array if this is the first time\n        // a callback is added for this key\n        _callbacks[info.key] = _callbacks[info.key] || [];\n\n        // remove an existing match if there is one\n        _getMatches(info.key, info.modifiers, {type: info.action}, sequenceName, combination, level);\n\n        // add this call back to the array\n        // if it is a sequence put it at the beginning\n        // if not put it at the end\n        //\n        // this is important because the way these are processed expects\n        // the sequence ones to come first\n        _callbacks[info.key][sequenceName ? 'unshift' : 'push']({\n            callback: callback,\n            modifiers: info.modifiers,\n            action: info.action,\n            seq: sequenceName,\n            level: level,\n            combo: combination\n        });\n    }\n\n    /**\n     * binds multiple combinations to the same callback\n     *\n     * @param {Array} combinations\n     * @param {Function} callback\n     * @param {string|undefined} action\n     * @returns void\n     */\n    function _bindMultiple(combinations, callback, action) {\n        for (var i = 0; i < combinations.length; ++i) {\n            _bindSingle(combinations[i], callback, action);\n        }\n    }\n\n    // start!\n    _addEvent(document, 'keypress', _handleKeyEvent);\n    _addEvent(document, 'keydown', _handleKeyEvent);\n    _addEvent(document, 'keyup', _handleKeyEvent);\n\n    var Mousetrap = {\n\n        /**\n         * binds an event to mousetrap\n         *\n         * can be a single key, a combination of keys separated with +,\n         * an array of keys, or a sequence of keys separated by spaces\n         *\n         * be sure to list the modifier keys first to make sure that the\n         * correct key ends up getting bound (the last key in the pattern)\n         *\n         * @param {string|Array} keys\n         * @param {Function} callback\n         * @param {string=} action - 'keypress', 'keydown', or 'keyup'\n         * @returns void\n         */\n        bind: function(keys, callback, action) {\n            keys = keys instanceof Array ? keys : [keys];\n            _bindMultiple(keys, callback, action);\n            return this;\n        },\n\n        /**\n         * unbinds an event to mousetrap\n         *\n         * the unbinding sets the callback function of the specified key combo\n         * to an empty function and deletes the corresponding key in the\n         * _directMap dict.\n         *\n         * TODO: actually remove this from the _callbacks dictionary instead\n         * of binding an empty function\n         *\n         * the keycombo+action has to be exactly the same as\n         * it was defined in the bind method\n         *\n         * @param {string|Array} keys\n         * @param {string} action\n         * @returns void\n         */\n        unbind: function(keys, action) {\n            return Mousetrap.bind(keys, function() {}, action);\n        },\n\n        /**\n         * triggers an event that has already been bound\n         *\n         * @param {string} keys\n         * @param {string=} action\n         * @returns void\n         */\n        trigger: function(keys, action) {\n            if (_directMap[keys + ':' + action]) {\n                _directMap[keys + ':' + action]({}, keys);\n            }\n            return this;\n        },\n\n        /**\n         * resets the library back to its initial state.  this is useful\n         * if you want to clear out the current keyboard shortcuts and bind\n         * new ones - for example if you switch to another page\n         *\n         * @returns void\n         */\n        reset: function() {\n            _callbacks = {};\n            _directMap = {};\n            return this;\n        },\n\n       /**\n        * should we stop this event before firing off callbacks\n        *\n        * @param {Event} e\n        * @param {Element} element\n        * @return {boolean}\n        */\n        stopCallback: function(e, element) {\n\n            // if the element has the class \"mousetrap\" then no need to stop\n            if ((' ' + element.className + ' ').indexOf(' mousetrap ') > -1) {\n                return false;\n            }\n\n            // stop for input, select, and textarea\n            return element.tagName == 'INPUT' || element.tagName == 'SELECT' || element.tagName == 'TEXTAREA' || element.isContentEditable;\n        },\n\n        /**\n         * exposes _handleKey publicly so it can be overwritten by extensions\n         */\n        handleKey: _handleKey\n    };\n\n    // expose mousetrap to the global object\n    window.Mousetrap = Mousetrap;\n\n    // expose mousetrap as an AMD module\n    if (typeof define === 'function' && define.amd) {\n        define(Mousetrap);\n    }\n}) (window, document);\n"
  },
  {
    "path": "flowable-ui-web/task/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": "flowable-ui-web/task/libs/angular-resource_1.3.13/angular-resource.js",
    "content": "/**\n * @license AngularJS v1.3.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 module\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 *\n * <div doc-module-components=\"ngResource\"></div>\n *\n * See {@link ngResource.$resource `$resource`} for usage.\n */\n\n/**\n * @ngdoc service\n * @name $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 * By default, trailing slashes will be stripped from the calculated URLs,\n * which can pose problems with server backends that do not expect that\n * behavior.  This can be disabled by configuring the `$resourceProvider` like\n * this:\n *\n * ```js\n     app.config(['$resourceProvider', function($resourceProvider) {\n       // Don't strip trailing slashes from calculated URLs\n       $resourceProvider.defaults.stripTrailingSlashes = false;\n     }]);\n * ```\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 for that parameter will be extracted\n *   from the corresponding property on the `data` object (provided when calling an action method).  For\n *   example, if the `defaultParam` object is `{someParam: '@someProp'}` then the value of `someParam`\n *   will be `data.someProp`.\n *\n * @param {Object.<Object>=} actions Hash with declaration of custom actions that should extend\n *   the default set of resource actions. The declaration should be created in the format of {@link\n *   ng.$http#usage $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} – Case insensitive HTTP method (e.g. `GET`, `POST`, `PUT`,\n *     `DELETE`, `JSONP`, etc).\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 *     By default, transformRequest will contain one function that checks if the request data is\n *     an object and serializes to using `angular.toJson`. To prevent this behavior, set\n *     `transformRequest` to an empty array: `transformRequest: []`\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 *     By default, transformResponse will contain one function that checks if the response looks like\n *     a JSON string and deserializes it using `angular.fromJson`. To prevent this behavior, set\n *     `transformResponse` to an empty array: `transformResponse: []`\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\n *     [requests with credentials](https://developer.mozilla.org/en/http_access_control#section_5)\n *     for more information.\n *   - **`responseType`** - `{string}` - see\n *     [requestType](https://developer.mozilla.org/en-US/docs/DOM/XMLHttpRequest#responseType).\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 * @param {Object} options Hash with custom settings that should extend the\n *   default `$resourceProvider` behavior.  The only supported option is\n *\n *   Where:\n *\n *   - **`stripTrailingSlashes`** – {boolean} – If true then the trailing\n *   slashes from any calculated URL will be stripped. (Defaults to true.)\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 *   ```js\n *   { 'get':    {method:'GET'},\n *     'save':   {method:'POST'},\n *     'query':  {method:'GET', isArray:true},\n *     'remove': {method:'DELETE'},\n *     'delete': {method:'DELETE'} };\n *   ```\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 *   ```js\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 *   ```\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 *     If an interceptor object was provided, the promise will instead be resolved with the value\n *     returned by the interceptor.\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 * ```js\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 * ```\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   ```js\n     var User = $resource('/user/:userId', {userId:'@id'});\n     User.get({userId:123}, function(user) {\n       user.abc = true;\n       user.$save();\n     });\n   ```\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   ```js\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   ```\n *\n * You can also access the raw `$http` promise via the `$promise` property on the object returned\n *\n   ```\n     var User = $resource('/user/:userId', {userId:'@id'});\n     User.get({userId:123})\n         .$promise.then(function(user) {\n           $scope.user = user;\n         });\n   ```\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 * ```js\n *    var app = angular.module('app', ['ngResource', 'ngRoute']);\n *\n *    // Some APIs expect a PUT request in the format URL/object/ID\n *    // Here we are creating an 'update' method\n *    app.factory('Notes', ['$resource', function($resource) {\n *    return $resource('/notes/:id', null,\n *        {\n *            'update': { method:'PUT' }\n *        });\n *    }]);\n *\n *    // In our controller we get the ID from the URL using ngRoute and $routeParams\n *    // We pass in $routeParams and our Notes factory along with $scope\n *    app.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 *    }]);\n * ```\n */\nangular.module('ngResource', ['ng']).\n  provider('$resource', function() {\n    var provider = this;\n\n    this.defaults = {\n      // Strip slashes by default\n      stripTrailingSlashes: true,\n\n      // Default actions configuration\n      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    };\n\n    this.$get = ['$http', '$q', function($http, $q) {\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\n       * (pchar) allowed in path 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 = extend({}, provider.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 (unless this behavior is specifically disabled)\n          if (self.defaults.stripTrailingSlashes) {\n            url = url.replace(/\\/+$/, '') || '/';\n          }\n\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, options) {\n        var route = new Route(url, options);\n\n        actions = extend({}, provider.defaults.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        Resource.prototype.toJSON = function() {\n          var data = extend({}, this);\n          delete data.$promise;\n          delete data.$resolved;\n          return data;\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',\n                      'Error in resource configuration for action `{0}`. Expected response to ' +\n                      'contain an {1} but got an {2}', name, action.isArray ? 'array' : 'object',\n                    angular.isArray(data) ? 'array' : 'object');\n                }\n                // jshint +W018\n                if (action.isArray) {\n                  value.length = 0;\n                  forEach(data, function(item) {\n                    if (typeof item === \"object\") {\n                      value.push(new Resource(item));\n                    } else {\n                      // Valid JSON values may be string literals, and these should not be converted\n                      // into objects. These items will not have access to the Resource prototype\n                      // methods, but unfortunately there\n                      value.push(item);\n                    }\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\n})(window, window.angular);\n"
  },
  {
    "path": "flowable-ui-web/task/libs/angular-route_1.3.13/angular-route.js",
    "content": "/**\n * @license AngularJS v1.3.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 module\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 *\n * <div doc-module-components=\"ngRoute\"></div>\n */\n /* global -ngRouteModule */\nvar ngRouteModule = angular.module('ngRoute', ['ng']).\n                        provider('$route', $RouteProvider),\n    $routeMinErr = angular.$$minErr('ngRoute');\n\n/**\n * @ngdoc provider\n * @name $routeProvider\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(Object.create(parent), extra);\n  }\n\n  var routes = {};\n\n  /**\n   * @ngdoc method\n   * @name $routeProvider#when\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/slashes/edit` and extract:\n   *\n   *    * `color: brown`\n   *    * `largecode: code/with/slashes`.\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 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    //copy original route object to preserve params inherited from proto chain\n    var routeCopy = angular.copy(route);\n    if (angular.isUndefined(routeCopy.reloadOnSearch)) {\n      routeCopy.reloadOnSearch = true;\n    }\n    if (angular.isUndefined(routeCopy.caseInsensitiveMatch)) {\n      routeCopy.caseInsensitiveMatch = this.caseInsensitiveMatch;\n    }\n    routes[path] = angular.extend(\n      routeCopy,\n      path && pathRegExp(path, routeCopy)\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, routeCopy)\n      );\n    }\n\n    return this;\n  };\n\n  /**\n   * @ngdoc property\n   * @name $routeProvider#caseInsensitiveMatch\n   * @description\n   *\n   * A boolean property indicating if routes defined\n   * using this provider should be matched using a case insensitive\n   * algorithm. Defaults to `false`.\n   */\n  this.caseInsensitiveMatch = false;\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 $routeProvider#otherwise\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|string} params Mapping information to be assigned to `$route.current`.\n   * If called with a string, the value maps to `redirectTo`.\n   * @returns {Object} self\n   */\n  this.otherwise = function(params) {\n    if (typeof params === 'string') {\n      params = {redirectTo: params};\n    }\n    this.when(null, params);\n    return this;\n  };\n\n\n  this.$get = ['$rootScope',\n               '$location',\n               '$routeParams',\n               '$q',\n               '$injector',\n               '$templateRequest',\n               '$sce',\n      function($rootScope, $location, $routeParams, $q, $injector, $templateRequest, $sce) {\n\n    /**\n     * @ngdoc service\n     * @name $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 {Object} routes Object with all route configuration Objects as its properties.\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     * <example name=\"$route-service\" module=\"ngRouteExample\"\n     *          deps=\"angular-route.js\" fixBase=\"true\">\n     *   <file name=\"index.html\">\n     *     <div ng-controller=\"MainController\">\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     *\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('ngRouteExample', ['ngRoute'])\n     *\n     *      .controller('MainController', function($scope, $route, $routeParams, $location) {\n     *          $scope.$route = $route;\n     *          $scope.$location = $location;\n     *          $scope.$routeParams = $routeParams;\n     *      })\n     *\n     *      .controller('BookController', function($scope, $routeParams) {\n     *          $scope.name = \"BookController\";\n     *          $scope.params = $routeParams;\n     *      })\n     *\n     *      .controller('ChapterController', function($scope, $routeParams) {\n     *          $scope.name = \"ChapterController\";\n     *          $scope.params = $routeParams;\n     *      })\n     *\n     *     .config(function($routeProvider, $locationProvider) {\n     *       $routeProvider\n     *        .when('/Book/:bookId', {\n     *         templateUrl: 'book.html',\n     *         controller: 'BookController',\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     *       .when('/Book/:bookId/ch/:chapterId', {\n     *         templateUrl: 'chapter.html',\n     *         controller: 'ChapterController'\n     *       });\n     *\n     *       // configure html5 to get links working on jsfiddle\n     *       $locationProvider.html5Mode(true);\n     *     });\n     *\n     *   </file>\n     *\n     *   <file name=\"protractor.js\" type=\"protractor\">\n     *     it('should load and compile correct template', function() {\n     *       element(by.linkText('Moby: Ch1')).click();\n     *       var content = element(by.css('[ng-view]')).getText();\n     *       expect(content).toMatch(/controller\\: ChapterController/);\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('[ng-view]')).getText();\n     *       expect(content).toMatch(/controller\\: BookController/);\n     *       expect(content).toMatch(/Book Id\\: Scarlet/);\n     *     });\n     *   </file>\n     * </example>\n     */\n\n    /**\n     * @ngdoc event\n     * @name $route#$routeChangeStart\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     * The route change (and the `$location` change that triggered it) can be prevented\n     * by calling `preventDefault` method of the event. See {@link ng.$rootScope.Scope#$on}\n     * for more details about event object.\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 $route#$routeChangeSuccess\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 $route#$routeChangeError\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 $route#$routeUpdate\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        preparedRoute,\n        preparedRouteIsUpdateOnly,\n        $route = {\n          routes: routes,\n\n          /**\n           * @ngdoc method\n           * @name $route#reload\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 and reinstantiates the controller.\n           */\n          reload: function() {\n            forceReload = true;\n            $rootScope.$evalAsync(function() {\n              // Don't support cancellation of a reload for now...\n              prepareRoute();\n              commitRoute();\n            });\n          },\n\n          /**\n           * @ngdoc method\n           * @name $route#updateParams\n           *\n           * @description\n           * Causes `$route` service to update the current URL, replacing\n           * current route parameters with those specified in `newParams`.\n           * Provided property names that match the route's path segment\n           * definitions will be interpolated into the location's path, while\n           * remaining properties will be treated as query params.\n           *\n           * @param {!Object<string, string>} newParams mapping of URL parameter names to values\n           */\n          updateParams: function(newParams) {\n            if (this.current && this.current.$$route) {\n              newParams = angular.extend({}, this.current.params, newParams);\n              $location.path(interpolate(this.current.$$route.originalPath, newParams));\n              // interpolate modifies newParams, only query params are left\n              $location.search(newParams);\n            } else {\n              throw $routeMinErr('norout', 'Tried updating route when with no current route');\n            }\n          }\n        };\n\n    $rootScope.$on('$locationChangeStart', prepareRoute);\n    $rootScope.$on('$locationChangeSuccess', commitRoute);\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 = m[i];\n\n        if (key && val) {\n          params[key.name] = val;\n        }\n      }\n      return params;\n    }\n\n    function prepareRoute($locationEvent) {\n      var lastRoute = $route.current;\n\n      preparedRoute = parseRoute();\n      preparedRouteIsUpdateOnly = preparedRoute && lastRoute && preparedRoute.$$route === lastRoute.$$route\n          && angular.equals(preparedRoute.pathParams, lastRoute.pathParams)\n          && !preparedRoute.reloadOnSearch && !forceReload;\n\n      if (!preparedRouteIsUpdateOnly && (lastRoute || preparedRoute)) {\n        if ($rootScope.$broadcast('$routeChangeStart', preparedRoute, lastRoute).defaultPrevented) {\n          if ($locationEvent) {\n            $locationEvent.preventDefault();\n          }\n        }\n      }\n    }\n\n    function commitRoute() {\n      var lastRoute = $route.current;\n      var nextRoute = preparedRoute;\n\n      if (preparedRouteIsUpdateOnly) {\n        lastRoute.params = nextRoute.params;\n        angular.copy(lastRoute.params, $routeParams);\n        $rootScope.$broadcast('$routeUpdate', lastRoute);\n      } else if (nextRoute || lastRoute) {\n        forceReload = false;\n        $route.current = nextRoute;\n        if (nextRoute) {\n          if (nextRoute.redirectTo) {\n            if (angular.isString(nextRoute.redirectTo)) {\n              $location.path(interpolate(nextRoute.redirectTo, nextRoute.params)).search(nextRoute.params)\n                       .replace();\n            } else {\n              $location.url(nextRoute.redirectTo(nextRoute.pathParams, $location.path(), $location.search()))\n                       .replace();\n            }\n          }\n        }\n\n        $q.when(nextRoute).\n          then(function() {\n            if (nextRoute) {\n              var locals = angular.extend({}, nextRoute.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, null, null, key);\n              });\n\n              if (angular.isDefined(template = nextRoute.template)) {\n                if (angular.isFunction(template)) {\n                  template = template(nextRoute.params);\n                }\n              } else if (angular.isDefined(templateUrl = nextRoute.templateUrl)) {\n                if (angular.isFunction(templateUrl)) {\n                  templateUrl = templateUrl(nextRoute.params);\n                }\n                templateUrl = $sce.getTrustedResourceUrl(templateUrl);\n                if (angular.isDefined(templateUrl)) {\n                  nextRoute.loadedTemplateUrl = templateUrl;\n                  template = $templateRequest(templateUrl);\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 (nextRoute == $route.current) {\n              if (nextRoute) {\n                nextRoute.locals = locals;\n                angular.copy(nextRoute.params, $routeParams);\n              }\n              $rootScope.$broadcast('$routeChangeSuccess', nextRoute, lastRoute);\n            }\n          }, function(error) {\n            if (nextRoute == $route.current) {\n              $rootScope.$broadcast('$routeChangeError', nextRoute, lastRoute, error);\n            }\n          });\n      }\n    }\n\n\n    /**\n     * @returns {Object} 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 {string} 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 service\n * @name $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#search `search()`} and {@link ng.$location#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 * ```js\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 * ```\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 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 name=\"ngView-directive\" module=\"ngViewExample\"\n             deps=\"angular-route.js;angular-animate.js\"\n             animations=\"true\" fixBase=\"true\">\n      <file name=\"index.html\">\n        <div ng-controller=\"MainCtrl 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>$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          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          .config(['$routeProvider', '$locationProvider',\n            function($routeProvider, $locationProvider) {\n              $routeProvider\n                .when('/Book/:bookId', {\n                  templateUrl: 'book.html',\n                  controller: 'BookCtrl',\n                  controllerAs: 'book'\n                })\n                .when('/Book/:bookId/ch/:chapterId', {\n                  templateUrl: 'chapter.html',\n                  controller: 'ChapterCtrl',\n                  controllerAs: 'chapter'\n                });\n\n              $locationProvider.html5Mode(true);\n          }])\n          .controller('MainCtrl', ['$route', '$routeParams', '$location',\n            function($route, $routeParams, $location) {\n              this.$route = $route;\n              this.$location = $location;\n              this.$routeParams = $routeParams;\n          }])\n          .controller('BookCtrl', ['$routeParams', function($routeParams) {\n            this.name = \"BookCtrl\";\n            this.params = $routeParams;\n          }])\n          .controller('ChapterCtrl', ['$routeParams', function($routeParams) {\n            this.name = \"ChapterCtrl\";\n            this.params = $routeParams;\n          }]);\n\n      </file>\n\n      <file name=\"protractor.js\" type=\"protractor\">\n        it('should load and compile correct template', function() {\n          element(by.linkText('Moby: Ch1')).click();\n          var content = element(by.css('[ng-view]')).getText();\n          expect(content).toMatch(/controller\\: ChapterCtrl/);\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('[ng-view]')).getText();\n          expect(content).toMatch(/controller\\: BookCtrl/);\n          expect(content).toMatch(/Book Id\\: Scarlet/);\n        });\n      </file>\n    </example>\n */\n\n\n/**\n * @ngdoc event\n * @name ngView#$viewContentLoaded\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            previousLeaveAnimation,\n            autoScrollExp = attr.autoscroll,\n            onloadExp = attr.onload || '';\n\n        scope.$on('$routeChangeSuccess', update);\n        update();\n\n        function cleanupLastView() {\n          if (previousLeaveAnimation) {\n            $animate.cancel(previousLeaveAnimation);\n            previousLeaveAnimation = null;\n          }\n\n          if (currentScope) {\n            currentScope.$destroy();\n            currentScope = null;\n          }\n          if (currentElement) {\n            previousLeaveAnimation = $animate.leave(currentElement);\n            previousLeaveAnimation.then(function() {\n              previousLeaveAnimation = null;\n            });\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).then(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": "flowable-ui-web/task/libs/angular-sanitize_1.3.13/angular-sanitize.js",
    "content": "/**\n * @license AngularJS v1.3.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 module\n * @name ngSanitize\n * @description\n *\n * # ngSanitize\n *\n * The `ngSanitize` module provides functionality to sanitize HTML.\n *\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 $sanitize\n * @kind 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. The input may also contain SVG markup.\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   <example module=\"sanitizeExample\" deps=\"angular-sanitize.js\">\n   <file name=\"index.html\">\n     <script>\n         angular.module('sanitizeExample', ['ngSanitize'])\n           .controller('ExampleController', ['$scope', '$sce', function($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=\"ExampleController\">\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   </file>\n   <file name=\"protractor.js\" type=\"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   </file>\n   </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       /^<((?:[a-zA-Z])[\\w:-]*)((?:\\s+[\\w:-]+(?:\\s*=\\s*(?:(?:\"[^\"]*\")|(?:'[^']*')|[^>\\s]+))?)*)\\s*(\\/?)\\s*(>?)/,\n  END_TAG_REGEXP = /^<\\/\\s*([\\w:-]+)[^>]*>/,\n  ATTR_REGEXP = /([\\w:-]+)(?:\\s*=\\s*(?:(?:\"((?:[^\"])*)\")|(?:'((?:[^'])*)')|([^>\\s]+)))?/g,\n  BEGIN_TAG_REGEXP = /^</,\n  BEGING_END_TAGE_REGEXP = /^<\\//,\n  COMMENT_REGEXP = /<!--(.*?)-->/g,\n  DOCTYPE_REGEXP = /<!DOCTYPE([^>]*?)>/i,\n  CDATA_REGEXP = /<!\\[CDATA\\[(.*?)]]>/g,\n  SURROGATE_PAIR_REGEXP = /[\\uD800-\\uDBFF][\\uDC00-\\uDFFF]/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// SVG Elements\n// https://wiki.whatwg.org/wiki/Sanitization_rules#svg_Elements\nvar svgElements = makeMap(\"animate,animateColor,animateMotion,animateTransform,circle,defs,\" +\n        \"desc,ellipse,font-face,font-face-name,font-face-src,g,glyph,hkern,image,linearGradient,\" +\n        \"line,marker,metadata,missing-glyph,mpath,path,polygon,polyline,radialGradient,rect,set,\" +\n        \"stop,svg,switch,text,title,tspan,use\");\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                                   svgElements);\n\n//Attributes that have href and hence need to be sanitized\nvar uriAttrs = makeMap(\"background,cite,href,longdesc,src,usemap,xlink:href\");\n\nvar htmlAttrs = makeMap('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\n// SVG attributes (without \"id\" and \"name\" attributes)\n// https://wiki.whatwg.org/wiki/Sanitization_rules#svg_Attributes\nvar svgAttrs = makeMap('accent-height,accumulate,additive,alphabetic,arabic-form,ascent,' +\n    'attributeName,attributeType,baseProfile,bbox,begin,by,calcMode,cap-height,class,color,' +\n    'color-rendering,content,cx,cy,d,dx,dy,descent,display,dur,end,fill,fill-rule,font-family,' +\n    'font-size,font-stretch,font-style,font-variant,font-weight,from,fx,fy,g1,g2,glyph-name,' +\n    'gradientUnits,hanging,height,horiz-adv-x,horiz-origin-x,ideographic,k,keyPoints,' +\n    'keySplines,keyTimes,lang,marker-end,marker-mid,marker-start,markerHeight,markerUnits,' +\n    'markerWidth,mathematical,max,min,offset,opacity,orient,origin,overline-position,' +\n    'overline-thickness,panose-1,path,pathLength,points,preserveAspectRatio,r,refX,refY,' +\n    'repeatCount,repeatDur,requiredExtensions,requiredFeatures,restart,rotate,rx,ry,slope,stemh,' +\n    'stemv,stop-color,stop-opacity,strikethrough-position,strikethrough-thickness,stroke,' +\n    'stroke-dasharray,stroke-dashoffset,stroke-linecap,stroke-linejoin,stroke-miterlimit,' +\n    'stroke-opacity,stroke-width,systemLanguage,target,text-anchor,to,transform,type,u1,u2,' +\n    'underline-position,underline-thickness,unicode,unicode-range,units-per-em,values,version,' +\n    'viewBox,visibility,width,widths,x,x-height,x1,x2,xlink:actuate,xlink:arcrole,xlink:role,' +\n    'xlink:show,xlink:title,xlink:type,xml:base,xml:lang,xml:space,xmlns,xmlns:xlink,y,y1,y2,' +\n    'zoomAndPan');\n\nvar validAttrs = angular.extend({},\n                                uriAttrs,\n                                svgAttrs,\n                                htmlAttrs);\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  if (typeof html !== 'string') {\n    if (html === null || typeof html === 'undefined') {\n      html = '';\n    } else {\n      html = '' + html;\n    }\n  }\n  var index, chars, match, stack = [], last = html, text;\n  stack.last = function() { return stack[stack.length - 1]; };\n\n  while (html) {\n    text = '';\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          // We only have a valid start-tag if there is a '>'.\n          if (match[4]) {\n            html = html.substring(match[0].length);\n            match[0].replace(START_TAG_REGEXP, parseStartTag);\n          }\n          chars = false;\n        } else {\n          // no ending tag found --- this piece should be encoded as an entity.\n          text += '<';\n          html = html.substring(1);\n        }\n      }\n\n      if (chars) {\n        index = html.indexOf(\"<\");\n\n        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      // IE versions 9 and 10 do not understand the regex '[^]', so using a workaround with [\\W\\w].\n      html = html.replace(new RegExp(\"([\\\\W\\\\w]*)<\\\\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 {string} escaped text\n */\nfunction encodeEntities(value) {\n  return value.\n    replace(/&/g, '&amp;').\n    replace(SURROGATE_PAIR_REGEXP, function(value) {\n      var hi = value.charCodeAt(0);\n      var low = value.charCodeAt(1);\n      return '&#' + (((hi - 0xD800) * 0x400) + (low - 0xDC00) + 0x10000) + ';';\n    }).\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 linky\n * @kind 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   <example module=\"linkyExample\" deps=\"angular-sanitize.js\">\n     <file name=\"index.html\">\n       <script>\n         angular.module('linkyExample', ['ngSanitize'])\n           .controller('ExampleController', ['$scope', function($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=\"ExampleController\">\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     </file>\n     <file name=\"protractor.js\" type=\"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     </file>\n   </example>\n */\nangular.module('ngSanitize').filter('linky', ['$sanitize', function($sanitize) {\n  var LINKY_URL_REGEXP =\n        /((ftp|https?):\\/\\/|(www\\.)|(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/www/mailto then assume mailto\n      if (!match[2] && !match[4]) {\n        url = (match[3] ? 'http://' : 'mailto:') + url;\n      }\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                  target,\n                  '\" ');\n      }\n      html.push('href=\"',\n                url.replace(/\"/g, '&quot;'),\n                '\">');\n      addText(text);\n      html.push('</a>');\n    }\n  };\n}]);\n\n\n})(window, window.angular);\n"
  },
  {
    "path": "flowable-ui-web/task/libs/angular-spectrum-colorpicker_1.0.13/spectrum.css",
    "content": "/***\nSpectrum Colorpicker v1.3.4\nhttps://github.com/bgrins/spectrum\nAuthor: Brian Grinstead\nLicense: MIT\n***/\n\n.sp-container {\n    position:absolute;\n    top:0;\n    left:0;\n    display:inline-block;\n    *display: inline;\n    *zoom: 1;\n    /* https://github.com/bgrins/spectrum/issues/40 */\n    z-index: 9999994;\n    overflow: hidden;\n}\n.sp-container.sp-flat {\n    position: relative;\n}\n\n/* Fix for * { box-sizing: border-box; } */\n.sp-container,\n.sp-container * {\n    -webkit-box-sizing: content-box;\n       -moz-box-sizing: content-box;\n            box-sizing: content-box;\n}\n\n/* http://ansciath.tumblr.com/post/7347495869/css-aspect-ratio */\n.sp-top {\n  position:relative;\n  width: 100%;\n  display:inline-block;\n}\n.sp-top-inner {\n   position:absolute;\n   top:0;\n   left:0;\n   bottom:0;\n   right:0;\n}\n.sp-color {\n    position: absolute;\n    top:0;\n    left:0;\n    bottom:0;\n    right:20%;\n}\n.sp-hue {\n    position: absolute;\n    top:0;\n    right:0;\n    bottom:0;\n    left:84%;\n    height: 100%;\n}\n\n.sp-clear-enabled .sp-hue {\n    top:33px;\n    height: 77.5%;\n}\n\n.sp-fill {\n    padding-top: 80%;\n}\n.sp-sat, .sp-val {\n    position: absolute;\n    top:0;\n    left:0;\n    right:0;\n    bottom:0;\n}\n\n.sp-alpha-enabled .sp-top {\n    margin-bottom: 18px;\n}\n.sp-alpha-enabled .sp-alpha {\n    display: block;\n}\n.sp-alpha-handle {\n    position:absolute;\n    top:-4px;\n    bottom: -4px;\n    width: 6px;\n    left: 50%;\n    cursor: pointer;\n    border: 1px solid black;\n    background: white;\n    opacity: .8;\n}\n.sp-alpha {\n    display: none;\n    position: absolute;\n    bottom: -14px;\n    right: 0;\n    left: 0;\n    height: 8px;\n}\n.sp-alpha-inner {\n    border: solid 1px #333;\n}\n\n.sp-clear {\n    display: none;\n}\n\n.sp-clear.sp-clear-display {\n    background-position: center;\n}\n\n.sp-clear-enabled .sp-clear {\n    display: block;\n    position:absolute;\n    top:0px;\n    right:0;\n    bottom:0;\n    left:84%;\n    height: 28px;\n}\n\n/* Don't allow text selection */\n.sp-container, .sp-replacer, .sp-preview, .sp-dragger, .sp-slider, .sp-alpha, .sp-clear, .sp-alpha-handle, .sp-container.sp-dragging .sp-input, .sp-container button  {\n    -webkit-user-select:none;\n    -moz-user-select: -moz-none;\n    -o-user-select:none;\n    user-select: none;\n}\n\n.sp-container.sp-input-disabled .sp-input-container {\n    display: none;\n}\n.sp-container.sp-buttons-disabled .sp-button-container {\n    display: none;\n}\n.sp-palette-only .sp-picker-container {\n    display: none;\n}\n.sp-palette-disabled .sp-palette-container {\n    display: none;\n}\n\n.sp-initial-disabled .sp-initial {\n    display: none;\n}\n\n\n/* Gradients for hue, saturation and value instead of images.  Not pretty... but it works */\n.sp-sat {\n    background-image: -webkit-gradient(linear,  0 0, 100% 0, from(#FFF), to(rgba(204, 154, 129, 0)));\n    background-image: -webkit-linear-gradient(left, #FFF, rgba(204, 154, 129, 0));\n    background-image: -moz-linear-gradient(left, #fff, rgba(204, 154, 129, 0));\n    background-image: -o-linear-gradient(left, #fff, rgba(204, 154, 129, 0));\n    background-image: -ms-linear-gradient(left, #fff, rgba(204, 154, 129, 0));\n    background-image: linear-gradient(to right, #fff, rgba(204, 154, 129, 0));\n    -ms-filter: \"progid:DXImageTransform.Microsoft.gradient(GradientType = 1, startColorstr=#FFFFFFFF, endColorstr=#00CC9A81)\";\n    filter : progid:DXImageTransform.Microsoft.gradient(GradientType = 1, startColorstr='#FFFFFFFF', endColorstr='#00CC9A81');\n}\n.sp-val {\n    background-image: -webkit-gradient(linear, 0 100%, 0 0, from(#000000), to(rgba(204, 154, 129, 0)));\n    background-image: -webkit-linear-gradient(bottom, #000000, rgba(204, 154, 129, 0));\n    background-image: -moz-linear-gradient(bottom, #000, rgba(204, 154, 129, 0));\n    background-image: -o-linear-gradient(bottom, #000, rgba(204, 154, 129, 0));\n    background-image: -ms-linear-gradient(bottom, #000, rgba(204, 154, 129, 0));\n    background-image: linear-gradient(to top, #000, rgba(204, 154, 129, 0));\n    -ms-filter: \"progid:DXImageTransform.Microsoft.gradient(startColorstr=#00CC9A81, endColorstr=#FF000000)\";\n    filter : progid:DXImageTransform.Microsoft.gradient(startColorstr='#00CC9A81', endColorstr='#FF000000');\n}\n\n.sp-hue {\n    background: -moz-linear-gradient(top, #ff0000 0%, #ffff00 17%, #00ff00 33%, #00ffff 50%, #0000ff 67%, #ff00ff 83%, #ff0000 100%);\n    background: -ms-linear-gradient(top, #ff0000 0%, #ffff00 17%, #00ff00 33%, #00ffff 50%, #0000ff 67%, #ff00ff 83%, #ff0000 100%);\n    background: -o-linear-gradient(top, #ff0000 0%, #ffff00 17%, #00ff00 33%, #00ffff 50%, #0000ff 67%, #ff00ff 83%, #ff0000 100%);\n    background: -webkit-gradient(linear, left top, left bottom, from(#ff0000), color-stop(0.17, #ffff00), color-stop(0.33, #00ff00), color-stop(0.5, #00ffff), color-stop(0.67, #0000ff), color-stop(0.83, #ff00ff), to(#ff0000));\n    background: -webkit-linear-gradient(top, #ff0000 0%, #ffff00 17%, #00ff00 33%, #00ffff 50%, #0000ff 67%, #ff00ff 83%, #ff0000 100%);\n}\n\n/* IE filters do not support multiple color stops.\n   Generate 6 divs, line them up, and do two color gradients for each.\n   Yes, really.\n */\n.sp-1 {\n    height:17%;\n    filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0000', endColorstr='#ffff00');\n}\n.sp-2 {\n    height:16%;\n    filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffff00', endColorstr='#00ff00');\n}\n.sp-3 {\n    height:17%;\n    filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#00ff00', endColorstr='#00ffff');\n}\n.sp-4 {\n    height:17%;\n    filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#00ffff', endColorstr='#0000ff');\n}\n.sp-5 {\n    height:16%;\n    filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#0000ff', endColorstr='#ff00ff');\n}\n.sp-6 {\n    height:17%;\n    filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff00ff', endColorstr='#ff0000');\n}\n\n.sp-hidden {\n    display: none !important;\n}\n\n/* Clearfix hack */\n.sp-cf:before, .sp-cf:after { content: \"\"; display: table; }\n.sp-cf:after { clear: both; }\n.sp-cf { *zoom: 1; }\n\n/* Mobile devices, make hue slider bigger so it is easier to slide */\n@media (max-device-width: 480px) {\n    .sp-color { right: 40%; }\n    .sp-hue { left: 63%; }\n    .sp-fill { padding-top: 60%; }\n}\n.sp-dragger {\n   border-radius: 5px;\n   height: 5px;\n   width: 5px;\n   border: 1px solid #fff;\n   background: #000;\n   cursor: pointer;\n   position:absolute;\n   top:0;\n   left: 0;\n}\n.sp-slider {\n    position: absolute;\n    top:0;\n    cursor:pointer;\n    height: 3px;\n    left: -1px;\n    right: -1px;\n    border: 1px solid #000;\n    background: white;\n    opacity: .8;\n}\n\n/*\nTheme authors:\nHere are the basic themeable display options (colors, fonts, global widths).\nSee http://bgrins.github.io/spectrum/themes/ for instructions.\n*/\n\n.sp-container {\n    border-radius: 0;\n    background-color: #ECECEC;\n    border: solid 1px #f0c49B;\n    padding: 0;\n}\n.sp-container, .sp-container button, .sp-container input, .sp-color, .sp-hue, .sp-clear\n{\n    font: normal 12px \"Lucida Grande\", \"Lucida Sans Unicode\", \"Lucida Sans\", Geneva, Verdana, sans-serif;\n    -webkit-box-sizing: border-box;\n    -moz-box-sizing: border-box;\n    -ms-box-sizing: border-box;\n    box-sizing: border-box;\n}\n.sp-top\n{\n    margin-bottom: 3px;\n}\n.sp-color, .sp-hue, .sp-clear\n{\n    border: solid 1px #666;\n}\n\n/* Input */\n.sp-input-container {\n    float:right;\n    width: 100px;\n    margin-bottom: 4px;\n}\n.sp-initial-disabled  .sp-input-container {\n    width: 100%;\n}\n.sp-input {\n   font-size: 12px !important;\n   border: 1px inset;\n   padding: 4px 5px;\n   margin: 0;\n   width: 100%;\n   background:transparent;\n   border-radius: 3px;\n   color: #222;\n}\n.sp-input:focus  {\n    border: 1px solid orange;\n}\n.sp-input.sp-validation-error\n{\n    border: 1px solid red;\n    background: #fdd;\n}\n.sp-picker-container , .sp-palette-container\n{\n    float:left;\n    position: relative;\n    padding: 10px;\n    padding-bottom: 300px;\n    margin-bottom: -290px;\n}\n.sp-picker-container\n{\n    width: 172px;\n    border-left: solid 1px #fff;\n}\n\n/* Palettes */\n.sp-palette-container\n{\n    border-right: solid 1px #ccc;\n}\n\n.sp-palette .sp-thumb-el {\n    display: block;\n    position:relative;\n    float:left;\n    width: 24px;\n    height: 15px;\n    margin: 3px;\n    cursor: pointer;\n    border:solid 2px transparent;\n}\n.sp-palette .sp-thumb-el:hover, .sp-palette .sp-thumb-el.sp-thumb-active {\n    border-color: orange;\n}\n.sp-thumb-el\n{\n    position:relative;\n}\n\n/* Initial */\n.sp-initial\n{\n    float: left;\n    border: solid 1px #333;\n}\n.sp-initial span {\n    width: 30px;\n    height: 25px;\n    border:none;\n    display:block;\n    float:left;\n    margin:0;\n}\n\n.sp-initial .sp-clear-display {\n    background-position: center;\n}\n\n/* Buttons */\n.sp-button-container {\n    float: right;\n}\n\n/* Replacer (the little preview div that shows up instead of the <input>) */\n.sp-replacer {\n    margin:0;\n    overflow:hidden;\n    cursor:pointer;\n    padding: 4px;\n    display:inline-block;\n    *zoom: 1;\n    *display: inline;\n    border: solid 1px #91765d;\n    background: #eee;\n    color: #333;\n    vertical-align: middle;\n}\n.sp-replacer:hover, .sp-replacer.sp-active {\n    border-color: #F0C49B;\n    color: #111;\n}\n.sp-replacer.sp-disabled {\n    cursor:default;\n    border-color: silver;\n    color: silver;\n}\n.sp-dd {\n    padding: 2px 0;\n    height: 16px;\n    line-height: 16px;\n    float:left;\n    font-size:10px;\n}\n.sp-preview\n{\n    position:relative;\n    width:25px;\n    height: 20px;\n    border: solid 1px #222;\n    margin-right: 5px;\n    float:left;\n    z-index: 0;\n}\n\n.sp-palette\n{\n    *width: 220px;\n    max-width: 220px;\n}\n.sp-palette .sp-thumb-el\n{\n    width:16px;\n    height: 16px;\n    margin:2px 1px;\n    border: solid 1px #d0d0d0;\n}\n\n.sp-container\n{\n    padding-bottom:0;\n}\n\n\n/* Buttons: http://hellohappy.org/css3-buttons/ */\n.sp-container button {\n  background-color: #eeeeee;\n  background-image: -webkit-linear-gradient(top, #eeeeee, #cccccc);\n  background-image: -moz-linear-gradient(top, #eeeeee, #cccccc);\n  background-image: -ms-linear-gradient(top, #eeeeee, #cccccc);\n  background-image: -o-linear-gradient(top, #eeeeee, #cccccc);\n  background-image: linear-gradient(to bottom, #eeeeee, #cccccc);\n  border: 1px solid #ccc;\n  border-bottom: 1px solid #bbb;\n  border-radius: 3px;\n  color: #333;\n  font-size: 14px;\n  line-height: 1;\n  padding: 5px 4px;\n  text-align: center;\n  text-shadow: 0 1px 0 #eee;\n  vertical-align: middle;\n}\n.sp-container button:hover {\n    background-color: #dddddd;\n    background-image: -webkit-linear-gradient(top, #dddddd, #bbbbbb);\n    background-image: -moz-linear-gradient(top, #dddddd, #bbbbbb);\n    background-image: -ms-linear-gradient(top, #dddddd, #bbbbbb);\n    background-image: -o-linear-gradient(top, #dddddd, #bbbbbb);\n    background-image: linear-gradient(to bottom, #dddddd, #bbbbbb);\n    border: 1px solid #bbb;\n    border-bottom: 1px solid #999;\n    cursor: pointer;\n    text-shadow: 0 1px 0 #ddd;\n}\n.sp-container button:active {\n    border: 1px solid #aaa;\n    border-bottom: 1px solid #888;\n    -webkit-box-shadow: inset 0 0 5px 2px #aaaaaa, 0 1px 0 0 #eeeeee;\n    -moz-box-shadow: inset 0 0 5px 2px #aaaaaa, 0 1px 0 0 #eeeeee;\n    -ms-box-shadow: inset 0 0 5px 2px #aaaaaa, 0 1px 0 0 #eeeeee;\n    -o-box-shadow: inset 0 0 5px 2px #aaaaaa, 0 1px 0 0 #eeeeee;\n    box-shadow: inset 0 0 5px 2px #aaaaaa, 0 1px 0 0 #eeeeee;\n}\n.sp-cancel\n{\n    font-size: 11px;\n    color: #d93f3f !important;\n    margin:0;\n    padding:2px;\n    margin-right: 5px;\n    vertical-align: middle;\n    text-decoration:none;\n\n}\n.sp-cancel:hover\n{\n    color: #d93f3f !important;\n    text-decoration: underline;\n}\n\n\n.sp-palette span:hover, .sp-palette span.sp-thumb-active\n{\n    border-color: #000;\n}\n\n.sp-preview, .sp-alpha, .sp-thumb-el\n{\n    position:relative;\n    background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAIAAADZF8uwAAAAGUlEQVQYV2M4gwH+YwCGIasIUwhT25BVBADtzYNYrHvv4gAAAABJRU5ErkJggg==);\n}\n.sp-preview-inner, .sp-alpha-inner, .sp-thumb-inner\n{\n    display:block;\n    position:absolute;\n    top:0;left:0;bottom:0;right:0;\n}\n\n.sp-palette .sp-thumb-inner\n{\n    background-position: 50% 50%;\n    background-repeat: no-repeat;\n}\n\n.sp-palette .sp-thumb-light.sp-thumb-active .sp-thumb-inner\n{\n    background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAYAAABWzo5XAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAIVJREFUeNpiYBhsgJFMffxAXABlN5JruT4Q3wfi/0DsT64h8UD8HmpIPCWG/KemIfOJCUB+Aoacx6EGBZyHBqI+WsDCwuQ9mhxeg2A210Ntfo8klk9sOMijaURm7yc1UP2RNCMbKE9ODK1HM6iegYLkfx8pligC9lCD7KmRof0ZhjQACDAAceovrtpVBRkAAAAASUVORK5CYII=);\n}\n\n.sp-palette .sp-thumb-dark.sp-thumb-active .sp-thumb-inner\n{\n    background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAYAAABWzo5XAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAadEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My41LjEwMPRyoQAAAMdJREFUOE+tkgsNwzAMRMugEAahEAahEAZhEAqlEAZhEAohEAYh81X2dIm8fKpEspLGvudPOsUYpxE2BIJCroJmEW9qJ+MKaBFhEMNabSy9oIcIPwrB+afvAUFoK4H0tMaQ3XtlrggDhOVVMuT4E5MMG0FBbCEYzjYT7OxLEvIHQLY2zWwQ3D+9luyOQTfKDiFD3iUIfPk8VqrKjgAiSfGFPecrg6HN6m/iBcwiDAo7WiBeawa+Kwh7tZoSCGLMqwlSAzVDhoK+6vH4G0P5wdkAAAAASUVORK5CYII=);\n}\n\n.sp-clear-display {\n    background-repeat:no-repeat;\n    background-position: center;\n    background-image: url(data:image/gif;base64,R0lGODlhFAAUAPcAAAAAAJmZmZ2dnZ6enqKioqOjo6SkpKWlpaampqenp6ioqKmpqaqqqqurq/Hx8fLy8vT09PX19ff39/j4+Pn5+fr6+vv7+wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAP8ALAAAAAAUABQAAAihAP9FoPCvoMGDBy08+EdhQAIJCCMybCDAAYUEARBAlFiQQoMABQhKUJBxY0SPICEYHBnggEmDKAuoPMjS5cGYMxHW3IiT478JJA8M/CjTZ0GgLRekNGpwAsYABHIypcAgQMsITDtWJYBR6NSqMico9cqR6tKfY7GeBCuVwlipDNmefAtTrkSzB1RaIAoXodsABiZAEFB06gIBWC1mLVgBa0AAOw==);\n}\n"
  },
  {
    "path": "flowable-ui-web/task/libs/angular-spectrum-colorpicker_1.0.13/spectrum.js",
    "content": "// Spectrum Colorpicker v1.3.4\n// https://github.com/bgrins/spectrum\n// Author: Brian Grinstead\n// License: MIT\n\n(function (window, $, undefined) {\n    var defaultOpts = {\n\n        // Callbacks\n        beforeShow: noop,\n        move: noop,\n        change: noop,\n        show: noop,\n        hide: noop,\n\n        // Options\n        color: false,\n        flat: false,\n        showInput: false,\n        allowEmpty: false,\n        showButtons: true,\n        clickoutFiresChange: false,\n        showInitial: false,\n        showPalette: false,\n        showPaletteOnly: false,\n        showSelectionPalette: true,\n        localStorageKey: false,\n        appendTo: \"body\",\n        maxSelectionSize: 7,\n        cancelText: \"cancel\",\n        chooseText: \"choose\",\n        clearText: \"Clear Color Selection\",\n        preferredFormat: false,\n        className: \"\", // Deprecated - use containerClassName and replacerClassName instead.\n        containerClassName: \"\",\n        replacerClassName: \"\",\n        showAlpha: false,\n        theme: \"sp-light\",\n        palette: [[\"#ffffff\", \"#000000\", \"#ff0000\", \"#ff8000\", \"#ffff00\", \"#008000\", \"#0000ff\", \"#4b0082\", \"#9400d3\"]],\n        selectionPalette: [],\n        disabled: false\n    },\n    spectrums = [],\n    IE = !!/msie/i.exec( window.navigator.userAgent ),\n    rgbaSupport = (function() {\n        function contains( str, substr ) {\n            return !!~('' + str).indexOf(substr);\n        }\n\n        var elem = document.createElement('div');\n        var style = elem.style;\n        style.cssText = 'background-color:rgba(0,0,0,.5)';\n        return contains(style.backgroundColor, 'rgba') || contains(style.backgroundColor, 'hsla');\n    })(),\n    inputTypeColorSupport = (function() {\n        var colorInput = $(\"<input type='color' value='!' />\")[0];\n        return colorInput.type === \"color\" && colorInput.value !== \"!\";\n    })(),\n    replaceInput = [\n        \"<div class='sp-replacer'>\",\n            \"<div class='sp-preview'><div class='sp-preview-inner'></div></div>\",\n            \"<div class='sp-dd'>&#9660;</div>\",\n        \"</div>\"\n    ].join(''),\n    markup = (function () {\n\n        // IE does not support gradients with multiple stops, so we need to simulate\n        //  that for the rainbow slider with 8 divs that each have a single gradient\n        var gradientFix = \"\";\n        if (IE) {\n            for (var i = 1; i <= 6; i++) {\n                gradientFix += \"<div class='sp-\" + i + \"'></div>\";\n            }\n        }\n\n        return [\n            \"<div class='sp-container sp-hidden'>\",\n                \"<div class='sp-palette-container'>\",\n                    \"<div class='sp-palette sp-thumb sp-cf'></div>\",\n                \"</div>\",\n                \"<div class='sp-picker-container'>\",\n                    \"<div class='sp-top sp-cf'>\",\n                        \"<div class='sp-fill'></div>\",\n                        \"<div class='sp-top-inner'>\",\n                            \"<div class='sp-color'>\",\n                                \"<div class='sp-sat'>\",\n                                    \"<div class='sp-val'>\",\n                                        \"<div class='sp-dragger'></div>\",\n                                    \"</div>\",\n                                \"</div>\",\n                            \"</div>\",\n                            \"<div class='sp-clear sp-clear-display'>\",\n                            \"</div>\",\n                            \"<div class='sp-hue'>\",\n                                \"<div class='sp-slider'></div>\",\n                                gradientFix,\n                            \"</div>\",\n                        \"</div>\",\n                        \"<div class='sp-alpha'><div class='sp-alpha-inner'><div class='sp-alpha-handle'></div></div></div>\",\n                    \"</div>\",\n                    \"<div class='sp-input-container sp-cf'>\",\n                        \"<input class='sp-input' type='text' spellcheck='false'  />\",\n                    \"</div>\",\n                    \"<div class='sp-initial sp-thumb sp-cf'></div>\",\n                    \"<div class='sp-button-container sp-cf'>\",\n                        \"<a class='sp-cancel' href='#'></a>\",\n                        \"<button type='button' class='sp-choose'></button>\",\n                    \"</div>\",\n                \"</div>\",\n            \"</div>\"\n        ].join(\"\");\n    })();\n\n    function paletteTemplate (p, color, className, tooltipFormat) {\n        var html = [];\n        for (var i = 0; i < p.length; i++) {\n            var current = p[i];\n            if(current) {\n                var tiny = tinycolor(current);\n                var c = tiny.toHsl().l < 0.5 ? \"sp-thumb-el sp-thumb-dark\" : \"sp-thumb-el sp-thumb-light\";\n                c += (tinycolor.equals(color, current)) ? \" sp-thumb-active\" : \"\";\n\n                var formattedString = tiny.toString(tooltipFormat || \"rgb\");\n                var swatchStyle = rgbaSupport ? (\"background-color:\" + tiny.toRgbString()) : \"filter:\" + tiny.toFilter();\n                html.push('<span title=\"' + formattedString + '\" data-color=\"' + tiny.toRgbString() + '\" class=\"' + c + '\"><span class=\"sp-thumb-inner\" style=\"' + swatchStyle + ';\" /></span>');\n            } else {\n                var cls = 'sp-clear-display';\n                html.push('<span title=\"No Color Selected\" data-color=\"\" style=\"background-color:transparent;\" class=\"' + cls + '\"></span>');\n            }\n        }\n        return \"<div class='sp-cf \" + className + \"'>\" + html.join('') + \"</div>\";\n    }\n\n    function hideAll() {\n        for (var i = 0; i < spectrums.length; i++) {\n            if (spectrums[i]) {\n                spectrums[i].hide();\n            }\n        }\n    }\n\n    function instanceOptions(o, callbackContext) {\n        var opts = $.extend({}, defaultOpts, o);\n        opts.callbacks = {\n            'move': bind(opts.move, callbackContext),\n            'change': bind(opts.change, callbackContext),\n            'show': bind(opts.show, callbackContext),\n            'hide': bind(opts.hide, callbackContext),\n            'beforeShow': bind(opts.beforeShow, callbackContext)\n        };\n\n        return opts;\n    }\n\n    function spectrum(element, o) {\n\n        var opts = instanceOptions(o, element),\n            flat = opts.flat,\n            showSelectionPalette = opts.showSelectionPalette,\n            localStorageKey = opts.localStorageKey,\n            theme = opts.theme,\n            callbacks = opts.callbacks,\n            resize = throttle(reflow, 10),\n            visible = false,\n            dragWidth = 0,\n            dragHeight = 0,\n            dragHelperHeight = 0,\n            slideHeight = 0,\n            slideWidth = 0,\n            alphaWidth = 0,\n            alphaSlideHelperWidth = 0,\n            slideHelperHeight = 0,\n            currentHue = 0,\n            currentSaturation = 0,\n            currentValue = 0,\n            currentAlpha = 1,\n            palette = [],\n            paletteArray = [],\n            paletteLookup = {},\n            selectionPalette = opts.selectionPalette.slice(0),\n            maxSelectionSize = opts.maxSelectionSize,\n            draggingClass = \"sp-dragging\",\n            shiftMovementDirection = null;\n\n        var doc = element.ownerDocument,\n            body = doc.body,\n            boundElement = $(element),\n            disabled = false,\n            container = $(markup, doc).addClass(theme),\n            dragger = container.find(\".sp-color\"),\n            dragHelper = container.find(\".sp-dragger\"),\n            slider = container.find(\".sp-hue\"),\n            slideHelper = container.find(\".sp-slider\"),\n            alphaSliderInner = container.find(\".sp-alpha-inner\"),\n            alphaSlider = container.find(\".sp-alpha\"),\n            alphaSlideHelper = container.find(\".sp-alpha-handle\"),\n            textInput = container.find(\".sp-input\"),\n            paletteContainer = container.find(\".sp-palette\"),\n            initialColorContainer = container.find(\".sp-initial\"),\n            cancelButton = container.find(\".sp-cancel\"),\n            clearButton = container.find(\".sp-clear\"),\n            chooseButton = container.find(\".sp-choose\"),\n            isInput = boundElement.is(\"input\"),\n            isInputTypeColor = isInput && inputTypeColorSupport && boundElement.attr(\"type\") === \"color\",\n            shouldReplace = isInput && !flat,\n            replacer = (shouldReplace) ? $(replaceInput).addClass(theme).addClass(opts.className).addClass(opts.replacerClassName) : $([]),\n            offsetElement = (shouldReplace) ? replacer : boundElement,\n            previewElement = replacer.find(\".sp-preview-inner\"),\n            initialColor = opts.color || (isInput && boundElement.val()),\n            colorOnShow = false,\n            preferredFormat = opts.preferredFormat,\n            currentPreferredFormat = preferredFormat,\n            clickoutFiresChange = !opts.showButtons || opts.clickoutFiresChange,\n            isEmpty = !initialColor,\n            allowEmpty = opts.allowEmpty && !isInputTypeColor;\n\n        function applyOptions() {\n\n            if (opts.showPaletteOnly) {\n                opts.showPalette = true;\n            }\n\n            if (opts.palette) {\n                palette = opts.palette.slice(0);\n                paletteArray = $.isArray(palette[0]) ? palette : [palette];\n                paletteLookup = {};\n                for (var i = 0; i < paletteArray.length; i++) {\n                    for (var j = 0; j < paletteArray[i].length; j++) {\n                        var rgb = tinycolor(paletteArray[i][j]).toRgbString();\n                        paletteLookup[rgb] = true;\n                    }\n                }\n            }\n\n            container.toggleClass(\"sp-flat\", flat);\n            container.toggleClass(\"sp-input-disabled\", !opts.showInput);\n            container.toggleClass(\"sp-alpha-enabled\", opts.showAlpha);\n            container.toggleClass(\"sp-clear-enabled\", allowEmpty);\n            container.toggleClass(\"sp-buttons-disabled\", !opts.showButtons);\n            container.toggleClass(\"sp-palette-disabled\", !opts.showPalette);\n            container.toggleClass(\"sp-palette-only\", opts.showPaletteOnly);\n            container.toggleClass(\"sp-initial-disabled\", !opts.showInitial);\n            container.addClass(opts.className).addClass(opts.containerClassName);\n\n            reflow();\n        }\n\n        function initialize() {\n\n            if (IE) {\n                container.find(\"*:not(input)\").attr(\"unselectable\", \"on\");\n            }\n\n            applyOptions();\n\n            if (shouldReplace) {\n                boundElement.after(replacer).hide();\n            }\n\n            if (!allowEmpty) {\n                clearButton.hide();\n            }\n\n            if (flat) {\n                boundElement.after(container).hide();\n            }\n            else {\n\n                var appendTo = opts.appendTo === \"parent\" ? boundElement.parent() : $(opts.appendTo);\n                if (appendTo.length !== 1) {\n                    appendTo = $(\"body\");\n                }\n\n                appendTo.append(container);\n            }\n\n            updateSelectionPaletteFromStorage();\n\n            offsetElement.bind(\"click.spectrum touchstart.spectrum\", function (e) {\n                if (!disabled) {\n                    toggle();\n                }\n\n                e.stopPropagation();\n\n                if (!$(e.target).is(\"input\")) {\n                    e.preventDefault();\n                }\n            });\n\n            if(boundElement.is(\":disabled\") || (opts.disabled === true)) {\n                disable();\n            }\n\n            // Prevent clicks from bubbling up to document.  This would cause it to be hidden.\n            container.click(stopPropagation);\n\n            // Handle user typed input\n            textInput.change(setFromTextInput);\n            textInput.bind(\"paste\", function () {\n                setTimeout(setFromTextInput, 1);\n            });\n            textInput.keydown(function (e) { if (e.keyCode == 13) { setFromTextInput(); } });\n\n            cancelButton.text(opts.cancelText);\n            cancelButton.bind(\"click.spectrum\", function (e) {\n                e.stopPropagation();\n                e.preventDefault();\n                hide(\"cancel\");\n            });\n\n            clearButton.attr(\"title\", opts.clearText);\n            clearButton.bind(\"click.spectrum\", function (e) {\n                e.stopPropagation();\n                e.preventDefault();\n                isEmpty = true;\n                move();\n\n                if(flat) {\n                    //for the flat style, this is a change event\n                    updateOriginalInput(true);\n                }\n            });\n\n            chooseButton.text(opts.chooseText);\n            chooseButton.bind(\"click.spectrum\", function (e) {\n                e.stopPropagation();\n                e.preventDefault();\n\n                if (isValid()) {\n                    updateOriginalInput(true);\n                    hide();\n                }\n            });\n\n            draggable(alphaSlider, function (dragX, dragY, e) {\n                currentAlpha = (dragX / alphaWidth);\n                isEmpty = false;\n                if (e.shiftKey) {\n                    currentAlpha = Math.round(currentAlpha * 10) / 10;\n                }\n\n                move();\n            }, dragStart, dragStop);\n\n            draggable(slider, function (dragX, dragY) {\n                currentHue = parseFloat(dragY / slideHeight);\n                isEmpty = false;\n                if (!opts.showAlpha) {\n                    currentAlpha = 1;\n                }\n                move();\n            }, dragStart, dragStop);\n\n            draggable(dragger, function (dragX, dragY, e) {\n\n                // shift+drag should snap the movement to either the x or y axis.\n                if (!e.shiftKey) {\n                    shiftMovementDirection = null;\n                }\n                else if (!shiftMovementDirection) {\n                    var oldDragX = currentSaturation * dragWidth;\n                    var oldDragY = dragHeight - (currentValue * dragHeight);\n                    var furtherFromX = Math.abs(dragX - oldDragX) > Math.abs(dragY - oldDragY);\n\n                    shiftMovementDirection = furtherFromX ? \"x\" : \"y\";\n                }\n\n                var setSaturation = !shiftMovementDirection || shiftMovementDirection === \"x\";\n                var setValue = !shiftMovementDirection || shiftMovementDirection === \"y\";\n\n                if (setSaturation) {\n                    currentSaturation = parseFloat(dragX / dragWidth);\n                }\n                if (setValue) {\n                    currentValue = parseFloat((dragHeight - dragY) / dragHeight);\n                }\n\n                isEmpty = false;\n                if (!opts.showAlpha) {\n                    currentAlpha = 1;\n                }\n\n                move();\n\n            }, dragStart, dragStop);\n\n            if (!!initialColor) {\n                set(initialColor);\n\n                // In case color was black - update the preview UI and set the format\n                // since the set function will not run (default color is black).\n                updateUI();\n                currentPreferredFormat = preferredFormat || tinycolor(initialColor).format;\n\n                addColorToSelectionPalette(initialColor);\n            }\n            else {\n                updateUI();\n            }\n\n            if (flat) {\n                show();\n            }\n\n            function palletElementClick(e) {\n                if (e.data && e.data.ignore) {\n                    set($(this).data(\"color\"));\n                    move();\n                }\n                else {\n                    set($(this).data(\"color\"));\n                    move();\n                    updateOriginalInput(true);\n                    hide();\n                }\n\n                return false;\n            }\n\n            var paletteEvent = IE ? \"mousedown.spectrum\" : \"click.spectrum touchstart.spectrum\";\n            paletteContainer.delegate(\".sp-thumb-el\", paletteEvent, palletElementClick);\n            initialColorContainer.delegate(\".sp-thumb-el:nth-child(1)\", paletteEvent, { ignore: true }, palletElementClick);\n        }\n\n        function updateSelectionPaletteFromStorage() {\n\n            if (localStorageKey && window.localStorage) {\n\n                // Migrate old palettes over to new format.  May want to remove this eventually.\n                try {\n                    var oldPalette = window.localStorage[localStorageKey].split(\",#\");\n                    if (oldPalette.length > 1) {\n                        delete window.localStorage[localStorageKey];\n                        $.each(oldPalette, function(i, c) {\n                             addColorToSelectionPalette(c);\n                        });\n                    }\n                }\n                catch(e) { }\n\n                try {\n                    selectionPalette = window.localStorage[localStorageKey].split(\";\");\n                }\n                catch (e) { }\n            }\n        }\n\n        function addColorToSelectionPalette(color) {\n            if (showSelectionPalette) {\n                var rgb = tinycolor(color).toRgbString();\n                if (!paletteLookup[rgb] && $.inArray(rgb, selectionPalette) === -1) {\n                    selectionPalette.push(rgb);\n                    while(selectionPalette.length > maxSelectionSize) {\n                        selectionPalette.shift();\n                    }\n                }\n\n                if (localStorageKey && window.localStorage) {\n                    try {\n                        window.localStorage[localStorageKey] = selectionPalette.join(\";\");\n                    }\n                    catch(e) { }\n                }\n            }\n        }\n\n        function getUniqueSelectionPalette() {\n            var unique = [];\n            if (opts.showPalette) {\n                for (i = 0; i < selectionPalette.length; i++) {\n                    var rgb = tinycolor(selectionPalette[i]).toRgbString();\n\n                    if (!paletteLookup[rgb]) {\n                        unique.push(selectionPalette[i]);\n                    }\n                }\n            }\n\n            return unique.reverse().slice(0, opts.maxSelectionSize);\n        }\n\n        function drawPalette() {\n\n            var currentColor = get();\n\n            var html = $.map(paletteArray, function (palette, i) {\n                return paletteTemplate(palette, currentColor, \"sp-palette-row sp-palette-row-\" + i, opts.preferredFormat);\n            });\n\n            updateSelectionPaletteFromStorage();\n\n            if (selectionPalette) {\n                html.push(paletteTemplate(getUniqueSelectionPalette(), currentColor, \"sp-palette-row sp-palette-row-selection\", opts.preferredFormat));\n            }\n\n            paletteContainer.html(html.join(\"\"));\n        }\n\n        function drawInitial() {\n            if (opts.showInitial) {\n                var initial = colorOnShow;\n                var current = get();\n                initialColorContainer.html(paletteTemplate([initial, current], current, \"sp-palette-row-initial\", opts.preferredFormat));\n            }\n        }\n\n        function dragStart() {\n            if (dragHeight <= 0 || dragWidth <= 0 || slideHeight <= 0) {\n                reflow();\n            }\n            container.addClass(draggingClass);\n            shiftMovementDirection = null;\n            boundElement.trigger('dragstart.spectrum', [ get() ]);\n        }\n\n        function dragStop() {\n            container.removeClass(draggingClass);\n            boundElement.trigger('dragstop.spectrum', [ get() ]);\n        }\n\n        function setFromTextInput() {\n\n            var value = textInput.val();\n\n            if ((value === null || value === \"\") && allowEmpty) {\n                set(null);\n                updateOriginalInput(true);\n            }\n            else {\n                var tiny = tinycolor(value);\n                if (tiny.ok) {\n                    set(tiny);\n                    updateOriginalInput(true);\n                }\n                else {\n                    textInput.addClass(\"sp-validation-error\");\n                }\n            }\n        }\n\n        function toggle() {\n            if (visible) {\n                hide();\n            }\n            else {\n                show();\n            }\n        }\n\n        function show() {\n            var event = $.Event('beforeShow.spectrum');\n\n            if (visible) {\n                reflow();\n                return;\n            }\n\n            boundElement.trigger(event, [ get() ]);\n\n            if (callbacks.beforeShow(get()) === false || event.isDefaultPrevented()) {\n                return;\n            }\n\n            hideAll();\n            visible = true;\n\n            $(doc).bind(\"click.spectrum\", hide);\n            $(window).bind(\"resize.spectrum\", resize);\n            replacer.addClass(\"sp-active\");\n            container.removeClass(\"sp-hidden\");\n\n            reflow();\n            updateUI();\n\n            colorOnShow = get();\n\n            drawInitial();\n            callbacks.show(colorOnShow);\n            boundElement.trigger('show.spectrum', [ colorOnShow ]);\n        }\n\n        function hide(e) {\n\n            // Return on right click\n            if (e && e.type == \"click\" && e.button == 2) { return; }\n\n            // Return if hiding is unnecessary\n            if (!visible || flat) { return; }\n            visible = false;\n\n            $(doc).unbind(\"click.spectrum\", hide);\n            $(window).unbind(\"resize.spectrum\", resize);\n\n            replacer.removeClass(\"sp-active\");\n            container.addClass(\"sp-hidden\");\n\n            var colorHasChanged = !tinycolor.equals(get(), colorOnShow);\n\n            if (colorHasChanged) {\n                if (clickoutFiresChange && e !== \"cancel\") {\n                    updateOriginalInput(true);\n                }\n                else {\n                    revert();\n                }\n            }\n\n            callbacks.hide(get());\n            boundElement.trigger('hide.spectrum', [ get() ]);\n        }\n\n        function revert() {\n            set(colorOnShow, true);\n        }\n\n        function set(color, ignoreFormatChange) {\n            if (tinycolor.equals(color, get())) {\n                // Update UI just in case a validation error needs\n                // to be cleared.\n                updateUI();\n                return;\n            }\n\n            var newColor, newHsv;\n            if (!color && allowEmpty) {\n                isEmpty = true;\n            } else {\n                isEmpty = false;\n                newColor = tinycolor(color);\n                newHsv = newColor.toHsv();\n\n                currentHue = (newHsv.h % 360) / 360;\n                currentSaturation = newHsv.s;\n                currentValue = newHsv.v;\n                currentAlpha = newHsv.a;\n            }\n            updateUI();\n\n            if (newColor && newColor.ok && !ignoreFormatChange) {\n                currentPreferredFormat = preferredFormat || newColor.format;\n            }\n        }\n\n        function get(opts) {\n            opts = opts || { };\n\n            if (allowEmpty && isEmpty) {\n                return null;\n            }\n\n            return tinycolor.fromRatio({\n                h: currentHue,\n                s: currentSaturation,\n                v: currentValue,\n                a: Math.round(currentAlpha * 100) / 100\n            }, { format: opts.format || currentPreferredFormat });\n        }\n\n        function isValid() {\n            return !textInput.hasClass(\"sp-validation-error\");\n        }\n\n        function move() {\n            updateUI();\n\n            callbacks.move(get());\n            boundElement.trigger('move.spectrum', [ get() ]);\n        }\n\n        function updateUI() {\n\n            textInput.removeClass(\"sp-validation-error\");\n\n            updateHelperLocations();\n\n            // Update dragger background color (gradients take care of saturation and value).\n            var flatColor = tinycolor.fromRatio({ h: currentHue, s: 1, v: 1 });\n            dragger.css(\"background-color\", flatColor.toHexString());\n\n            // Get a format that alpha will be included in (hex and names ignore alpha)\n            var format = currentPreferredFormat;\n            if (currentAlpha < 1 && !(currentAlpha === 0 && format === \"name\")) {\n                if (format === \"hex\" || format === \"hex3\" || format === \"hex6\" || format === \"name\") {\n                    format = \"rgb\";\n                }\n            }\n\n            var realColor = get({ format: format }),\n                displayColor = '';\n\n             //reset background info for preview element\n            previewElement.removeClass(\"sp-clear-display\");\n            previewElement.css('background-color', 'transparent');\n\n            if (!realColor && allowEmpty) {\n                // Update the replaced elements background with icon indicating no color selection\n                previewElement.addClass(\"sp-clear-display\");\n            }\n            else {\n                var realHex = realColor.toHexString(),\n                    realRgb = realColor.toRgbString();\n\n                // Update the replaced elements background color (with actual selected color)\n                if (rgbaSupport || realColor.alpha === 1) {\n                    previewElement.css(\"background-color\", realRgb);\n                }\n                else {\n                    previewElement.css(\"background-color\", \"transparent\");\n                    previewElement.css(\"filter\", realColor.toFilter());\n                }\n\n                if (opts.showAlpha) {\n                    var rgb = realColor.toRgb();\n                    rgb.a = 0;\n                    var realAlpha = tinycolor(rgb).toRgbString();\n                    var gradient = \"linear-gradient(left, \" + realAlpha + \", \" + realHex + \")\";\n\n                    if (IE) {\n                        alphaSliderInner.css(\"filter\", tinycolor(realAlpha).toFilter({ gradientType: 1 }, realHex));\n                    }\n                    else {\n                        alphaSliderInner.css(\"background\", \"-webkit-\" + gradient);\n                        alphaSliderInner.css(\"background\", \"-moz-\" + gradient);\n                        alphaSliderInner.css(\"background\", \"-ms-\" + gradient);\n                        // Use current syntax gradient on unprefixed property.\n                        alphaSliderInner.css(\"background\",\n                            \"linear-gradient(to right, \" + realAlpha + \", \" + realHex + \")\");\n                    }\n                }\n\n                displayColor = realColor.toString(format);\n            }\n\n            // Update the text entry input as it changes happen\n            if (opts.showInput) {\n                textInput.val(displayColor);\n            }\n\n            if (opts.showPalette) {\n                drawPalette();\n            }\n\n            drawInitial();\n        }\n\n        function updateHelperLocations() {\n            var s = currentSaturation;\n            var v = currentValue;\n\n            if(allowEmpty && isEmpty) {\n                //if selected color is empty, hide the helpers\n                alphaSlideHelper.hide();\n                slideHelper.hide();\n                dragHelper.hide();\n            }\n            else {\n                //make sure helpers are visible\n                alphaSlideHelper.show();\n                slideHelper.show();\n                dragHelper.show();\n\n                // Where to show the little circle in that displays your current selected color\n                var dragX = s * dragWidth;\n                var dragY = dragHeight - (v * dragHeight);\n                dragX = Math.max(\n                    -dragHelperHeight,\n                    Math.min(dragWidth - dragHelperHeight, dragX - dragHelperHeight)\n                );\n                dragY = Math.max(\n                    -dragHelperHeight,\n                    Math.min(dragHeight - dragHelperHeight, dragY - dragHelperHeight)\n                );\n                dragHelper.css({\n                    \"top\": dragY + \"px\",\n                    \"left\": dragX + \"px\"\n                });\n\n                var alphaX = currentAlpha * alphaWidth;\n                alphaSlideHelper.css({\n                    \"left\": (alphaX - (alphaSlideHelperWidth / 2)) + \"px\"\n                });\n\n                // Where to show the bar that displays your current selected hue\n                var slideY = (currentHue) * slideHeight;\n                slideHelper.css({\n                    \"top\": (slideY - slideHelperHeight) + \"px\"\n                });\n            }\n        }\n\n        function updateOriginalInput(fireCallback) {\n            var color = get(),\n                displayColor = '',\n                hasChanged = !tinycolor.equals(color, colorOnShow);\n\n            if (color) {\n                displayColor = color.toString(currentPreferredFormat);\n                // Update the selection palette with the current color\n                addColorToSelectionPalette(color);\n            }\n\n            if (isInput) {\n                boundElement.val(displayColor);\n            }\n\n            colorOnShow = color;\n\n            if (fireCallback && hasChanged) {\n                callbacks.change(color);\n                boundElement.trigger('change', [ color ]);\n            }\n        }\n\n        function reflow() {\n            dragWidth = dragger.width();\n            dragHeight = dragger.height();\n            dragHelperHeight = dragHelper.height();\n            slideWidth = slider.width();\n            slideHeight = slider.height();\n            slideHelperHeight = slideHelper.height();\n            alphaWidth = alphaSlider.width();\n            alphaSlideHelperWidth = alphaSlideHelper.width();\n\n            if (!flat) {\n                container.css(\"position\", \"absolute\");\n                container.offset(getOffset(container, offsetElement));\n            }\n\n            updateHelperLocations();\n\n            if (opts.showPalette) {\n                drawPalette();\n            }\n\n            boundElement.trigger('reflow.spectrum');\n        }\n\n        function destroy() {\n            boundElement.show();\n            offsetElement.unbind(\"click.spectrum touchstart.spectrum\");\n            container.remove();\n            replacer.remove();\n            spectrums[spect.id] = null;\n        }\n\n        function option(optionName, optionValue) {\n            if (optionName === undefined) {\n                return $.extend({}, opts);\n            }\n            if (optionValue === undefined) {\n                return opts[optionName];\n            }\n\n            opts[optionName] = optionValue;\n            applyOptions();\n        }\n\n        function enable() {\n            disabled = false;\n            boundElement.attr(\"disabled\", false);\n            offsetElement.removeClass(\"sp-disabled\");\n        }\n\n        function disable() {\n            hide();\n            disabled = true;\n            boundElement.attr(\"disabled\", true);\n            offsetElement.addClass(\"sp-disabled\");\n        }\n\n        initialize();\n\n        var spect = {\n            show: show,\n            hide: hide,\n            toggle: toggle,\n            reflow: reflow,\n            option: option,\n            enable: enable,\n            disable: disable,\n            set: function (c) {\n                set(c);\n                updateOriginalInput();\n            },\n            get: get,\n            destroy: destroy,\n            container: container\n        };\n\n        spect.id = spectrums.push(spect) - 1;\n\n        return spect;\n    }\n\n    /**\n    * checkOffset - get the offset below/above and left/right element depending on screen position\n    * Thanks https://github.com/jquery/jquery-ui/blob/master/ui/jquery.ui.datepicker.js\n    */\n    function getOffset(picker, input) {\n        var extraY = 0;\n        var dpWidth = picker.outerWidth();\n        var dpHeight = picker.outerHeight();\n        var inputHeight = input.outerHeight();\n        var doc = picker[0].ownerDocument;\n        var docElem = doc.documentElement;\n        var viewWidth = docElem.clientWidth + $(doc).scrollLeft();\n        var viewHeight = docElem.clientHeight + $(doc).scrollTop();\n        var offset = input.offset();\n        offset.top += inputHeight;\n\n        offset.left -=\n            Math.min(offset.left, (offset.left + dpWidth > viewWidth && viewWidth > dpWidth) ?\n            Math.abs(offset.left + dpWidth - viewWidth) : 0);\n\n        offset.top -=\n            Math.min(offset.top, ((offset.top + dpHeight > viewHeight && viewHeight > dpHeight) ?\n            Math.abs(dpHeight + inputHeight - extraY) : extraY));\n\n        return offset;\n    }\n\n    /**\n    * noop - do nothing\n    */\n    function noop() {\n\n    }\n\n    /**\n    * stopPropagation - makes the code only doing this a little easier to read in line\n    */\n    function stopPropagation(e) {\n        e.stopPropagation();\n    }\n\n    /**\n    * Create a function bound to a given object\n    * Thanks to underscore.js\n    */\n    function bind(func, obj) {\n        var slice = Array.prototype.slice;\n        var args = slice.call(arguments, 2);\n        return function () {\n            return func.apply(obj, args.concat(slice.call(arguments)));\n        };\n    }\n\n    /**\n    * Lightweight drag helper.  Handles containment within the element, so that\n    * when dragging, the x is within [0,element.width] and y is within [0,element.height]\n    */\n    function draggable(element, onmove, onstart, onstop) {\n        onmove = onmove || function () { };\n        onstart = onstart || function () { };\n        onstop = onstop || function () { };\n        var doc = element.ownerDocument || document;\n        var dragging = false;\n        var offset = {};\n        var maxHeight = 0;\n        var maxWidth = 0;\n        var hasTouch = ('ontouchstart' in window);\n\n        var duringDragEvents = {};\n        duringDragEvents[\"selectstart\"] = prevent;\n        duringDragEvents[\"dragstart\"] = prevent;\n        duringDragEvents[\"touchmove mousemove\"] = move;\n        duringDragEvents[\"touchend mouseup\"] = stop;\n\n        function prevent(e) {\n            if (e.stopPropagation) {\n                e.stopPropagation();\n            }\n            if (e.preventDefault) {\n                e.preventDefault();\n            }\n            e.returnValue = false;\n        }\n\n        function move(e) {\n            if (dragging) {\n                // Mouseup happened outside of window\n                if (IE && document.documentMode < 9 && !e.button) {\n                    return stop();\n                }\n\n                var touches = e.originalEvent.touches;\n                var pageX = touches ? touches[0].pageX : e.pageX;\n                var pageY = touches ? touches[0].pageY : e.pageY;\n\n                var dragX = Math.max(0, Math.min(pageX - offset.left, maxWidth));\n                var dragY = Math.max(0, Math.min(pageY - offset.top, maxHeight));\n\n                if (hasTouch) {\n                    // Stop scrolling in iOS\n                    prevent(e);\n                }\n\n                onmove.apply(element, [dragX, dragY, e]);\n            }\n        }\n\n        function start(e) {\n            var rightclick = (e.which) ? (e.which == 3) : (e.button == 2);\n            var touches = e.originalEvent.touches;\n\n            if (!rightclick && !dragging) {\n                if (onstart.apply(element, arguments) !== false) {\n                    dragging = true;\n                    maxHeight = $(element).height();\n                    maxWidth = $(element).width();\n                    offset = $(element).offset();\n\n                    $(doc).bind(duringDragEvents);\n                    $(doc.body).addClass(\"sp-dragging\");\n\n                    if (!hasTouch) {\n                        move(e);\n                    }\n\n                    prevent(e);\n                }\n            }\n        }\n\n        function stop() {\n            if (dragging) {\n                $(doc).unbind(duringDragEvents);\n                $(doc.body).removeClass(\"sp-dragging\");\n                onstop.apply(element, arguments);\n            }\n            dragging = false;\n        }\n\n        $(element).bind(\"touchstart mousedown\", start);\n    }\n\n    function throttle(func, wait, debounce) {\n        var timeout;\n        return function () {\n            var context = this, args = arguments;\n            var throttler = function () {\n                timeout = null;\n                func.apply(context, args);\n            };\n            if (debounce) clearTimeout(timeout);\n            if (debounce || !timeout) timeout = setTimeout(throttler, wait);\n        };\n    }\n\n    function log(){/* jshint -W021 */if(window.console){if(Function.prototype.bind)log=Function.prototype.bind.call(console.log,console);else log=function(){Function.prototype.apply.call(console.log,console,arguments);};log.apply(this,arguments);}}\n\n    /**\n    * Define a jQuery plugin\n    */\n    var dataID = \"spectrum.id\";\n    $.fn.spectrum = function (opts, extra) {\n\n        if (typeof opts == \"string\") {\n\n            var returnValue = this;\n            var args = Array.prototype.slice.call( arguments, 1 );\n\n            this.each(function () {\n                var spect = spectrums[$(this).data(dataID)];\n                if (spect) {\n                    var method = spect[opts];\n                    if (!method) {\n                        throw new Error( \"Spectrum: no such method: '\" + opts + \"'\" );\n                    }\n\n                    if (opts == \"get\") {\n                        returnValue = spect.get();\n                    }\n                    else if (opts == \"container\") {\n                        returnValue = spect.container;\n                    }\n                    else if (opts == \"option\") {\n                        returnValue = spect.option.apply(spect, args);\n                    }\n                    else if (opts == \"destroy\") {\n                        spect.destroy();\n                        $(this).removeData(dataID);\n                    }\n                    else {\n                        method.apply(spect, args);\n                    }\n                }\n            });\n\n            return returnValue;\n        }\n\n        // Initializing a new instance of spectrum\n        return this.spectrum(\"destroy\").each(function () {\n            var options = $.extend({}, opts, $(this).data());\n            var spect = spectrum(this, options);\n            $(this).data(dataID, spect.id);\n        });\n    };\n\n    $.fn.spectrum.load = true;\n    $.fn.spectrum.loadOpts = {};\n    $.fn.spectrum.draggable = draggable;\n    $.fn.spectrum.defaults = defaultOpts;\n\n    $.spectrum = { };\n    $.spectrum.localization = { };\n    $.spectrum.palettes = { };\n\n    $.fn.spectrum.processNativeColorInputs = function () {\n        if (!inputTypeColorSupport) {\n            $(\"input[type=color]\").spectrum({\n                preferredFormat: \"hex6\"\n            });\n        }\n    };\n\n    // TinyColor v0.9.17\n    // https://github.com/bgrins/TinyColor\n    // 2013-08-10, Brian Grinstead, MIT License\n\n    (function() {\n\n    var trimLeft = /^[\\s,#]+/,\n        trimRight = /\\s+$/,\n        tinyCounter = 0,\n        math = Math,\n        mathRound = math.round,\n        mathMin = math.min,\n        mathMax = math.max,\n        mathRandom = math.random;\n\n    function tinycolor (color, opts) {\n\n        color = (color) ? color : '';\n        opts = opts || { };\n\n        // If input is already a tinycolor, return itself\n        if (typeof color == \"object\" && color.hasOwnProperty(\"_tc_id\")) {\n           return color;\n        }\n\n        var rgb = inputToRGB(color);\n        var r = rgb.r,\n            g = rgb.g,\n            b = rgb.b,\n            a = rgb.a,\n            roundA = mathRound(100*a) / 100,\n            format = opts.format || rgb.format;\n\n        // Don't let the range of [0,255] come back in [0,1].\n        // Potentially lose a little bit of precision here, but will fix issues where\n        // .5 gets interpreted as half of the total, instead of half of 1\n        // If it was supposed to be 128, this was already taken care of by `inputToRgb`\n        if (r < 1) { r = mathRound(r); }\n        if (g < 1) { g = mathRound(g); }\n        if (b < 1) { b = mathRound(b); }\n\n        return {\n            ok: rgb.ok,\n            format: format,\n            _tc_id: tinyCounter++,\n            alpha: a,\n            getAlpha: function() {\n                return a;\n            },\n            setAlpha: function(value) {\n                a = boundAlpha(value);\n                roundA = mathRound(100*a) / 100;\n            },\n            toHsv: function() {\n                var hsv = rgbToHsv(r, g, b);\n                return { h: hsv.h * 360, s: hsv.s, v: hsv.v, a: a };\n            },\n            toHsvString: function() {\n                var hsv = rgbToHsv(r, g, b);\n                var h = mathRound(hsv.h * 360), s = mathRound(hsv.s * 100), v = mathRound(hsv.v * 100);\n                return (a == 1) ?\n                  \"hsv(\"  + h + \", \" + s + \"%, \" + v + \"%)\" :\n                  \"hsva(\" + h + \", \" + s + \"%, \" + v + \"%, \"+ roundA + \")\";\n            },\n            toHsl: function() {\n                var hsl = rgbToHsl(r, g, b);\n                return { h: hsl.h * 360, s: hsl.s, l: hsl.l, a: a };\n            },\n            toHslString: function() {\n                var hsl = rgbToHsl(r, g, b);\n                var h = mathRound(hsl.h * 360), s = mathRound(hsl.s * 100), l = mathRound(hsl.l * 100);\n                return (a == 1) ?\n                  \"hsl(\"  + h + \", \" + s + \"%, \" + l + \"%)\" :\n                  \"hsla(\" + h + \", \" + s + \"%, \" + l + \"%, \"+ roundA + \")\";\n            },\n            toHex: function(allow3Char) {\n                return rgbToHex(r, g, b, allow3Char);\n            },\n            toHexString: function(allow3Char) {\n                return '#' + this.toHex(allow3Char);\n            },\n            toHex8: function() {\n                return rgbaToHex(r, g, b, a);\n            },\n            toHex8String: function() {\n                return '#' + this.toHex8();\n            },\n            toRgb: function() {\n                return { r: mathRound(r), g: mathRound(g), b: mathRound(b), a: a };\n            },\n            toRgbString: function() {\n                return (a == 1) ?\n                  \"rgb(\"  + mathRound(r) + \", \" + mathRound(g) + \", \" + mathRound(b) + \")\" :\n                  \"rgba(\" + mathRound(r) + \", \" + mathRound(g) + \", \" + mathRound(b) + \", \" + roundA + \")\";\n            },\n            toPercentageRgb: function() {\n                return { r: mathRound(bound01(r, 255) * 100) + \"%\", g: mathRound(bound01(g, 255) * 100) + \"%\", b: mathRound(bound01(b, 255) * 100) + \"%\", a: a };\n            },\n            toPercentageRgbString: function() {\n                return (a == 1) ?\n                  \"rgb(\"  + mathRound(bound01(r, 255) * 100) + \"%, \" + mathRound(bound01(g, 255) * 100) + \"%, \" + mathRound(bound01(b, 255) * 100) + \"%)\" :\n                  \"rgba(\" + mathRound(bound01(r, 255) * 100) + \"%, \" + mathRound(bound01(g, 255) * 100) + \"%, \" + mathRound(bound01(b, 255) * 100) + \"%, \" + roundA + \")\";\n            },\n            toName: function() {\n                if (a === 0) {\n                    return \"transparent\";\n                }\n\n                return hexNames[rgbToHex(r, g, b, true)] || false;\n            },\n            toFilter: function(secondColor) {\n                var hex8String = '#' + rgbaToHex(r, g, b, a);\n                var secondHex8String = hex8String;\n                var gradientType = opts && opts.gradientType ? \"GradientType = 1, \" : \"\";\n\n                if (secondColor) {\n                    var s = tinycolor(secondColor);\n                    secondHex8String = s.toHex8String();\n                }\n\n                return \"progid:DXImageTransform.Microsoft.gradient(\"+gradientType+\"startColorstr=\"+hex8String+\",endColorstr=\"+secondHex8String+\")\";\n            },\n            toString: function(format) {\n                var formatSet = !!format;\n                format = format || this.format;\n\n                var formattedString = false;\n                var hasAlphaAndFormatNotSet = !formatSet && a < 1 && a > 0;\n                var formatWithAlpha = hasAlphaAndFormatNotSet && (format === \"hex\" || format === \"hex6\" || format === \"hex3\" || format === \"name\");\n\n                if (format === \"rgb\") {\n                    formattedString = this.toRgbString();\n                }\n                if (format === \"prgb\") {\n                    formattedString = this.toPercentageRgbString();\n                }\n                if (format === \"hex\" || format === \"hex6\") {\n                    formattedString = this.toHexString();\n                }\n                if (format === \"hex3\") {\n                    formattedString = this.toHexString(true);\n                }\n                if (format === \"hex8\") {\n                    formattedString = this.toHex8String();\n                }\n                if (format === \"name\") {\n                    formattedString = this.toName();\n                }\n                if (format === \"hsl\") {\n                    formattedString = this.toHslString();\n                }\n                if (format === \"hsv\") {\n                    formattedString = this.toHsvString();\n                }\n\n                if (formatWithAlpha) {\n                    return this.toRgbString();\n                }\n\n                return formattedString || this.toHexString();\n            }\n        };\n    }\n\n    // If input is an object, force 1 into \"1.0\" to handle ratios properly\n    // String input requires \"1.0\" as input, so 1 will be treated as 1\n    tinycolor.fromRatio = function(color, opts) {\n        if (typeof color == \"object\") {\n            var newColor = {};\n            for (var i in color) {\n                if (color.hasOwnProperty(i)) {\n                    if (i === \"a\") {\n                        newColor[i] = color[i];\n                    }\n                    else {\n                        newColor[i] = convertToPercentage(color[i]);\n                    }\n                }\n            }\n            color = newColor;\n        }\n\n        return tinycolor(color, opts);\n    };\n\n    // Given a string or object, convert that input to RGB\n    // Possible string inputs:\n    //\n    //     \"red\"\n    //     \"#f00\" or \"f00\"\n    //     \"#ff0000\" or \"ff0000\"\n    //     \"#ff000000\" or \"ff000000\"\n    //     \"rgb 255 0 0\" or \"rgb (255, 0, 0)\"\n    //     \"rgb 1.0 0 0\" or \"rgb (1, 0, 0)\"\n    //     \"rgba (255, 0, 0, 1)\" or \"rgba 255, 0, 0, 1\"\n    //     \"rgba (1.0, 0, 0, 1)\" or \"rgba 1.0, 0, 0, 1\"\n    //     \"hsl(0, 100%, 50%)\" or \"hsl 0 100% 50%\"\n    //     \"hsla(0, 100%, 50%, 1)\" or \"hsla 0 100% 50%, 1\"\n    //     \"hsv(0, 100%, 100%)\" or \"hsv 0 100% 100%\"\n    //\n    function inputToRGB(color) {\n\n        var rgb = { r: 0, g: 0, b: 0 };\n        var a = 1;\n        var ok = false;\n        var format = false;\n\n        if (typeof color == \"string\") {\n            color = stringInputToObject(color);\n        }\n\n        if (typeof color == \"object\") {\n            if (color.hasOwnProperty(\"r\") && color.hasOwnProperty(\"g\") && color.hasOwnProperty(\"b\")) {\n                rgb = rgbToRgb(color.r, color.g, color.b);\n                ok = true;\n                format = String(color.r).substr(-1) === \"%\" ? \"prgb\" : \"rgb\";\n            }\n            else if (color.hasOwnProperty(\"h\") && color.hasOwnProperty(\"s\") && color.hasOwnProperty(\"v\")) {\n                color.s = convertToPercentage(color.s);\n                color.v = convertToPercentage(color.v);\n                rgb = hsvToRgb(color.h, color.s, color.v);\n                ok = true;\n                format = \"hsv\";\n            }\n            else if (color.hasOwnProperty(\"h\") && color.hasOwnProperty(\"s\") && color.hasOwnProperty(\"l\")) {\n                color.s = convertToPercentage(color.s);\n                color.l = convertToPercentage(color.l);\n                rgb = hslToRgb(color.h, color.s, color.l);\n                ok = true;\n                format = \"hsl\";\n            }\n\n            if (color.hasOwnProperty(\"a\")) {\n                a = color.a;\n            }\n        }\n\n        a = boundAlpha(a);\n\n        return {\n            ok: ok,\n            format: color.format || format,\n            r: mathMin(255, mathMax(rgb.r, 0)),\n            g: mathMin(255, mathMax(rgb.g, 0)),\n            b: mathMin(255, mathMax(rgb.b, 0)),\n            a: a\n        };\n    }\n\n\n    // Conversion Functions\n    // --------------------\n\n    // `rgbToHsl`, `rgbToHsv`, `hslToRgb`, `hsvToRgb` modified from:\n    // <http://mjijackson.com/2008/02/rgb-to-hsl-and-rgb-to-hsv-color-model-conversion-algorithms-in-javascript>\n\n    // `rgbToRgb`\n    // Handle bounds / percentage checking to conform to CSS color spec\n    // <http://www.w3.org/TR/css3-color/>\n    // *Assumes:* r, g, b in [0, 255] or [0, 1]\n    // *Returns:* { r, g, b } in [0, 255]\n    function rgbToRgb(r, g, b){\n        return {\n            r: bound01(r, 255) * 255,\n            g: bound01(g, 255) * 255,\n            b: bound01(b, 255) * 255\n        };\n    }\n\n    // `rgbToHsl`\n    // Converts an RGB color value to HSL.\n    // *Assumes:* r, g, and b are contained in [0, 255] or [0, 1]\n    // *Returns:* { h, s, l } in [0,1]\n    function rgbToHsl(r, g, b) {\n\n        r = bound01(r, 255);\n        g = bound01(g, 255);\n        b = bound01(b, 255);\n\n        var max = mathMax(r, g, b), min = mathMin(r, g, b);\n        var h, s, l = (max + min) / 2;\n\n        if(max == min) {\n            h = s = 0; // achromatic\n        }\n        else {\n            var d = max - min;\n            s = l > 0.5 ? d / (2 - max - min) : d / (max + min);\n            switch(max) {\n                case r: h = (g - b) / d + (g < b ? 6 : 0); break;\n                case g: h = (b - r) / d + 2; break;\n                case b: h = (r - g) / d + 4; break;\n            }\n\n            h /= 6;\n        }\n\n        return { h: h, s: s, l: l };\n    }\n\n    // `hslToRgb`\n    // Converts an HSL color value to RGB.\n    // *Assumes:* h is contained in [0, 1] or [0, 360] and s and l are contained [0, 1] or [0, 100]\n    // *Returns:* { r, g, b } in the set [0, 255]\n    function hslToRgb(h, s, l) {\n        var r, g, b;\n\n        h = bound01(h, 360);\n        s = bound01(s, 100);\n        l = bound01(l, 100);\n\n        function hue2rgb(p, q, t) {\n            if(t < 0) t += 1;\n            if(t > 1) t -= 1;\n            if(t < 1/6) return p + (q - p) * 6 * t;\n            if(t < 1/2) return q;\n            if(t < 2/3) return p + (q - p) * (2/3 - t) * 6;\n            return p;\n        }\n\n        if(s === 0) {\n            r = g = b = l; // achromatic\n        }\n        else {\n            var q = l < 0.5 ? l * (1 + s) : l + s - l * s;\n            var p = 2 * l - q;\n            r = hue2rgb(p, q, h + 1/3);\n            g = hue2rgb(p, q, h);\n            b = hue2rgb(p, q, h - 1/3);\n        }\n\n        return { r: r * 255, g: g * 255, b: b * 255 };\n    }\n\n    // `rgbToHsv`\n    // Converts an RGB color value to HSV\n    // *Assumes:* r, g, and b are contained in the set [0, 255] or [0, 1]\n    // *Returns:* { h, s, v } in [0,1]\n    function rgbToHsv(r, g, b) {\n\n        r = bound01(r, 255);\n        g = bound01(g, 255);\n        b = bound01(b, 255);\n\n        var max = mathMax(r, g, b), min = mathMin(r, g, b);\n        var h, s, v = max;\n\n        var d = max - min;\n        s = max === 0 ? 0 : d / max;\n\n        if(max == min) {\n            h = 0; // achromatic\n        }\n        else {\n            switch(max) {\n                case r: h = (g - b) / d + (g < b ? 6 : 0); break;\n                case g: h = (b - r) / d + 2; break;\n                case b: h = (r - g) / d + 4; break;\n            }\n            h /= 6;\n        }\n        return { h: h, s: s, v: v };\n    }\n\n    // `hsvToRgb`\n    // Converts an HSV color value to RGB.\n    // *Assumes:* h is contained in [0, 1] or [0, 360] and s and v are contained in [0, 1] or [0, 100]\n    // *Returns:* { r, g, b } in the set [0, 255]\n     function hsvToRgb(h, s, v) {\n\n        h = bound01(h, 360) * 6;\n        s = bound01(s, 100);\n        v = bound01(v, 100);\n\n        var i = math.floor(h),\n            f = h - i,\n            p = v * (1 - s),\n            q = v * (1 - f * s),\n            t = v * (1 - (1 - f) * s),\n            mod = i % 6,\n            r = [v, q, p, p, t, v][mod],\n            g = [t, v, v, q, p, p][mod],\n            b = [p, p, t, v, v, q][mod];\n\n        return { r: r * 255, g: g * 255, b: b * 255 };\n    }\n\n    // `rgbToHex`\n    // Converts an RGB color to hex\n    // Assumes r, g, and b are contained in the set [0, 255]\n    // Returns a 3 or 6 character hex\n    function rgbToHex(r, g, b, allow3Char) {\n\n        var hex = [\n            pad2(mathRound(r).toString(16)),\n            pad2(mathRound(g).toString(16)),\n            pad2(mathRound(b).toString(16))\n        ];\n\n        // Return a 3 character hex if possible\n        if (allow3Char && hex[0].charAt(0) == hex[0].charAt(1) && hex[1].charAt(0) == hex[1].charAt(1) && hex[2].charAt(0) == hex[2].charAt(1)) {\n            return hex[0].charAt(0) + hex[1].charAt(0) + hex[2].charAt(0);\n        }\n\n        return hex.join(\"\");\n    }\n        // `rgbaToHex`\n        // Converts an RGBA color plus alpha transparency to hex\n        // Assumes r, g, b and a are contained in the set [0, 255]\n        // Returns an 8 character hex\n        function rgbaToHex(r, g, b, a) {\n\n            var hex = [\n                pad2(convertDecimalToHex(a)),\n                pad2(mathRound(r).toString(16)),\n                pad2(mathRound(g).toString(16)),\n                pad2(mathRound(b).toString(16))\n            ];\n\n            return hex.join(\"\");\n        }\n\n    // `equals`\n    // Can be called with any tinycolor input\n    tinycolor.equals = function (color1, color2) {\n        if (!color1 || !color2) { return false; }\n        return tinycolor(color1).toRgbString() == tinycolor(color2).toRgbString();\n    };\n    tinycolor.random = function() {\n        return tinycolor.fromRatio({\n            r: mathRandom(),\n            g: mathRandom(),\n            b: mathRandom()\n        });\n    };\n\n\n    // Modification Functions\n    // ----------------------\n    // Thanks to less.js for some of the basics here\n    // <https://github.com/cloudhead/less.js/blob/master/lib/less/functions.js>\n\n    tinycolor.desaturate = function (color, amount) {\n        amount = (amount === 0) ? 0 : (amount || 10);\n        var hsl = tinycolor(color).toHsl();\n        hsl.s -= amount / 100;\n        hsl.s = clamp01(hsl.s);\n        return tinycolor(hsl);\n    };\n    tinycolor.saturate = function (color, amount) {\n        amount = (amount === 0) ? 0 : (amount || 10);\n        var hsl = tinycolor(color).toHsl();\n        hsl.s += amount / 100;\n        hsl.s = clamp01(hsl.s);\n        return tinycolor(hsl);\n    };\n    tinycolor.greyscale = function(color) {\n        return tinycolor.desaturate(color, 100);\n    };\n    tinycolor.lighten = function(color, amount) {\n        amount = (amount === 0) ? 0 : (amount || 10);\n        var hsl = tinycolor(color).toHsl();\n        hsl.l += amount / 100;\n        hsl.l = clamp01(hsl.l);\n        return tinycolor(hsl);\n    };\n    tinycolor.darken = function (color, amount) {\n        amount = (amount === 0) ? 0 : (amount || 10);\n        var hsl = tinycolor(color).toHsl();\n        hsl.l -= amount / 100;\n        hsl.l = clamp01(hsl.l);\n        return tinycolor(hsl);\n    };\n    tinycolor.complement = function(color) {\n        var hsl = tinycolor(color).toHsl();\n        hsl.h = (hsl.h + 180) % 360;\n        return tinycolor(hsl);\n    };\n\n\n    // Combination Functions\n    // ---------------------\n    // Thanks to jQuery xColor for some of the ideas behind these\n    // <https://github.com/infusion/jQuery-xcolor/blob/master/jquery.xcolor.js>\n\n    tinycolor.triad = function(color) {\n        var hsl = tinycolor(color).toHsl();\n        var h = hsl.h;\n        return [\n            tinycolor(color),\n            tinycolor({ h: (h + 120) % 360, s: hsl.s, l: hsl.l }),\n            tinycolor({ h: (h + 240) % 360, s: hsl.s, l: hsl.l })\n        ];\n    };\n    tinycolor.tetrad = function(color) {\n        var hsl = tinycolor(color).toHsl();\n        var h = hsl.h;\n        return [\n            tinycolor(color),\n            tinycolor({ h: (h + 90) % 360, s: hsl.s, l: hsl.l }),\n            tinycolor({ h: (h + 180) % 360, s: hsl.s, l: hsl.l }),\n            tinycolor({ h: (h + 270) % 360, s: hsl.s, l: hsl.l })\n        ];\n    };\n    tinycolor.splitcomplement = function(color) {\n        var hsl = tinycolor(color).toHsl();\n        var h = hsl.h;\n        return [\n            tinycolor(color),\n            tinycolor({ h: (h + 72) % 360, s: hsl.s, l: hsl.l}),\n            tinycolor({ h: (h + 216) % 360, s: hsl.s, l: hsl.l})\n        ];\n    };\n    tinycolor.analogous = function(color, results, slices) {\n        results = results || 6;\n        slices = slices || 30;\n\n        var hsl = tinycolor(color).toHsl();\n        var part = 360 / slices;\n        var ret = [tinycolor(color)];\n\n        for (hsl.h = ((hsl.h - (part * results >> 1)) + 720) % 360; --results; ) {\n            hsl.h = (hsl.h + part) % 360;\n            ret.push(tinycolor(hsl));\n        }\n        return ret;\n    };\n    tinycolor.monochromatic = function(color, results) {\n        results = results || 6;\n        var hsv = tinycolor(color).toHsv();\n        var h = hsv.h, s = hsv.s, v = hsv.v;\n        var ret = [];\n        var modification = 1 / results;\n\n        while (results--) {\n            ret.push(tinycolor({ h: h, s: s, v: v}));\n            v = (v + modification) % 1;\n        }\n\n        return ret;\n    };\n\n\n    // Readability Functions\n    // ---------------------\n    // <http://www.w3.org/TR/AERT#color-contrast>\n\n    // `readability`\n    // Analyze the 2 colors and returns an object with the following properties:\n    //    `brightness`: difference in brightness between the two colors\n    //    `color`: difference in color/hue between the two colors\n    tinycolor.readability = function(color1, color2) {\n        var a = tinycolor(color1).toRgb();\n        var b = tinycolor(color2).toRgb();\n        var brightnessA = (a.r * 299 + a.g * 587 + a.b * 114) / 1000;\n        var brightnessB = (b.r * 299 + b.g * 587 + b.b * 114) / 1000;\n        var colorDiff = (\n            Math.max(a.r, b.r) - Math.min(a.r, b.r) +\n            Math.max(a.g, b.g) - Math.min(a.g, b.g) +\n            Math.max(a.b, b.b) - Math.min(a.b, b.b)\n        );\n\n        return {\n            brightness: Math.abs(brightnessA - brightnessB),\n            color: colorDiff\n        };\n    };\n\n    // `readable`\n    // http://www.w3.org/TR/AERT#color-contrast\n    // Ensure that foreground and background color combinations provide sufficient contrast.\n    // *Example*\n    //    tinycolor.readable(\"#000\", \"#111\") => false\n    tinycolor.readable = function(color1, color2) {\n        var readability = tinycolor.readability(color1, color2);\n        return readability.brightness > 125 && readability.color > 500;\n    };\n\n    // `mostReadable`\n    // Given a base color and a list of possible foreground or background\n    // colors for that base, returns the most readable color.\n    // *Example*\n    //    tinycolor.mostReadable(\"#123\", [\"#fff\", \"#000\"]) => \"#000\"\n    tinycolor.mostReadable = function(baseColor, colorList) {\n        var bestColor = null;\n        var bestScore = 0;\n        var bestIsReadable = false;\n        for (var i=0; i < colorList.length; i++) {\n\n            // We normalize both around the \"acceptable\" breaking point,\n            // but rank brightness constrast higher than hue.\n\n            var readability = tinycolor.readability(baseColor, colorList[i]);\n            var readable = readability.brightness > 125 && readability.color > 500;\n            var score = 3 * (readability.brightness / 125) + (readability.color / 500);\n\n            if ((readable && ! bestIsReadable) ||\n                (readable && bestIsReadable && score > bestScore) ||\n                ((! readable) && (! bestIsReadable) && score > bestScore)) {\n                bestIsReadable = readable;\n                bestScore = score;\n                bestColor = tinycolor(colorList[i]);\n            }\n        }\n        return bestColor;\n    };\n\n\n    // Big List of Colors\n    // ------------------\n    // <http://www.w3.org/TR/css3-color/#svg-color>\n    var names = tinycolor.names = {\n        aliceblue: \"f0f8ff\",\n        antiquewhite: \"faebd7\",\n        aqua: \"0ff\",\n        aquamarine: \"7fffd4\",\n        azure: \"f0ffff\",\n        beige: \"f5f5dc\",\n        bisque: \"ffe4c4\",\n        black: \"000\",\n        blanchedalmond: \"ffebcd\",\n        blue: \"00f\",\n        blueviolet: \"8a2be2\",\n        brown: \"a52a2a\",\n        burlywood: \"deb887\",\n        burntsienna: \"ea7e5d\",\n        cadetblue: \"5f9ea0\",\n        chartreuse: \"7fff00\",\n        chocolate: \"d2691e\",\n        coral: \"ff7f50\",\n        cornflowerblue: \"6495ed\",\n        cornsilk: \"fff8dc\",\n        crimson: \"dc143c\",\n        cyan: \"0ff\",\n        darkblue: \"00008b\",\n        darkcyan: \"008b8b\",\n        darkgoldenrod: \"b8860b\",\n        darkgray: \"a9a9a9\",\n        darkgreen: \"006400\",\n        darkgrey: \"a9a9a9\",\n        darkkhaki: \"bdb76b\",\n        darkmagenta: \"8b008b\",\n        darkolivegreen: \"556b2f\",\n        darkorange: \"ff8c00\",\n        darkorchid: \"9932cc\",\n        darkred: \"8b0000\",\n        darksalmon: \"e9967a\",\n        darkseagreen: \"8fbc8f\",\n        darkslateblue: \"483d8b\",\n        darkslategray: \"2f4f4f\",\n        darkslategrey: \"2f4f4f\",\n        darkturquoise: \"00ced1\",\n        darkviolet: \"9400d3\",\n        deeppink: \"ff1493\",\n        deepskyblue: \"00bfff\",\n        dimgray: \"696969\",\n        dimgrey: \"696969\",\n        dodgerblue: \"1e90ff\",\n        firebrick: \"b22222\",\n        floralwhite: \"fffaf0\",\n        forestgreen: \"228b22\",\n        fuchsia: \"f0f\",\n        gainsboro: \"dcdcdc\",\n        ghostwhite: \"f8f8ff\",\n        gold: \"ffd700\",\n        goldenrod: \"daa520\",\n        gray: \"808080\",\n        green: \"008000\",\n        greenyellow: \"adff2f\",\n        grey: \"808080\",\n        honeydew: \"f0fff0\",\n        hotpink: \"ff69b4\",\n        indianred: \"cd5c5c\",\n        indigo: \"4b0082\",\n        ivory: \"fffff0\",\n        khaki: \"f0e68c\",\n        lavender: \"e6e6fa\",\n        lavenderblush: \"fff0f5\",\n        lawngreen: \"7cfc00\",\n        lemonchiffon: \"fffacd\",\n        lightblue: \"add8e6\",\n        lightcoral: \"f08080\",\n        lightcyan: \"e0ffff\",\n        lightgoldenrodyellow: \"fafad2\",\n        lightgray: \"d3d3d3\",\n        lightgreen: \"90ee90\",\n        lightgrey: \"d3d3d3\",\n        lightpink: \"ffb6c1\",\n        lightsalmon: \"ffa07a\",\n        lightseagreen: \"20b2aa\",\n        lightskyblue: \"87cefa\",\n        lightslategray: \"789\",\n        lightslategrey: \"789\",\n        lightsteelblue: \"b0c4de\",\n        lightyellow: \"ffffe0\",\n        lime: \"0f0\",\n        limegreen: \"32cd32\",\n        linen: \"faf0e6\",\n        magenta: \"f0f\",\n        maroon: \"800000\",\n        mediumaquamarine: \"66cdaa\",\n        mediumblue: \"0000cd\",\n        mediumorchid: \"ba55d3\",\n        mediumpurple: \"9370db\",\n        mediumseagreen: \"3cb371\",\n        mediumslateblue: \"7b68ee\",\n        mediumspringgreen: \"00fa9a\",\n        mediumturquoise: \"48d1cc\",\n        mediumvioletred: \"c71585\",\n        midnightblue: \"191970\",\n        mintcream: \"f5fffa\",\n        mistyrose: \"ffe4e1\",\n        moccasin: \"ffe4b5\",\n        navajowhite: \"ffdead\",\n        navy: \"000080\",\n        oldlace: \"fdf5e6\",\n        olive: \"808000\",\n        olivedrab: \"6b8e23\",\n        orange: \"ffa500\",\n        orangered: \"ff4500\",\n        orchid: \"da70d6\",\n        palegoldenrod: \"eee8aa\",\n        palegreen: \"98fb98\",\n        paleturquoise: \"afeeee\",\n        palevioletred: \"db7093\",\n        papayawhip: \"ffefd5\",\n        peachpuff: \"ffdab9\",\n        peru: \"cd853f\",\n        pink: \"ffc0cb\",\n        plum: \"dda0dd\",\n        powderblue: \"b0e0e6\",\n        purple: \"800080\",\n        red: \"f00\",\n        rosybrown: \"bc8f8f\",\n        royalblue: \"4169e1\",\n        saddlebrown: \"8b4513\",\n        salmon: \"fa8072\",\n        sandybrown: \"f4a460\",\n        seagreen: \"2e8b57\",\n        seashell: \"fff5ee\",\n        sienna: \"a0522d\",\n        silver: \"c0c0c0\",\n        skyblue: \"87ceeb\",\n        slateblue: \"6a5acd\",\n        slategray: \"708090\",\n        slategrey: \"708090\",\n        snow: \"fffafa\",\n        springgreen: \"00ff7f\",\n        steelblue: \"4682b4\",\n        tan: \"d2b48c\",\n        teal: \"008080\",\n        thistle: \"d8bfd8\",\n        tomato: \"ff6347\",\n        turquoise: \"40e0d0\",\n        violet: \"ee82ee\",\n        wheat: \"f5deb3\",\n        white: \"fff\",\n        whitesmoke: \"f5f5f5\",\n        yellow: \"ff0\",\n        yellowgreen: \"9acd32\"\n    };\n\n    // Make it easy to access colors via `hexNames[hex]`\n    var hexNames = tinycolor.hexNames = flip(names);\n\n\n    // Utilities\n    // ---------\n\n    // `{ 'name1': 'val1' }` becomes `{ 'val1': 'name1' }`\n    function flip(o) {\n        var flipped = { };\n        for (var i in o) {\n            if (o.hasOwnProperty(i)) {\n                flipped[o[i]] = i;\n            }\n        }\n        return flipped;\n    }\n\n    // Return a valid alpha value [0,1] with all invalid values being set to 1\n    function boundAlpha(a) {\n        a = parseFloat(a);\n\n        if (isNaN(a) || a < 0 || a > 1) {\n            a = 1;\n        }\n\n        return a;\n    }\n\n    // Take input from [0, n] and return it as [0, 1]\n    function bound01(n, max) {\n        if (isOnePointZero(n)) { n = \"100%\"; }\n\n        var processPercent = isPercentage(n);\n        n = mathMin(max, mathMax(0, parseFloat(n)));\n\n        // Automatically convert percentage into number\n        if (processPercent) {\n            n = parseInt(n * max, 10) / 100;\n        }\n\n        // Handle floating point rounding errors\n        if ((math.abs(n - max) < 0.000001)) {\n            return 1;\n        }\n\n        // Convert into [0, 1] range if it isn't already\n        return (n % max) / parseFloat(max);\n    }\n\n    // Force a number between 0 and 1\n    function clamp01(val) {\n        return mathMin(1, mathMax(0, val));\n    }\n\n    // Parse a base-16 hex value into a base-10 integer\n    function parseIntFromHex(val) {\n        return parseInt(val, 16);\n    }\n\n    // Need to handle 1.0 as 100%, since once it is a number, there is no difference between it and 1\n    // <http://stackoverflow.com/questions/7422072/javascript-how-to-detect-number-as-a-decimal-including-1-0>\n    function isOnePointZero(n) {\n        return typeof n == \"string\" && n.indexOf('.') != -1 && parseFloat(n) === 1;\n    }\n\n    // Check to see if string passed in is a percentage\n    function isPercentage(n) {\n        return typeof n === \"string\" && n.indexOf('%') != -1;\n    }\n\n    // Force a hex value to have 2 characters\n    function pad2(c) {\n        return c.length == 1 ? '0' + c : '' + c;\n    }\n\n    // Replace a decimal with it's percentage value\n    function convertToPercentage(n) {\n        if (n <= 1) {\n            n = (n * 100) + \"%\";\n        }\n\n        return n;\n    }\n\n    // Converts a decimal to a hex value\n    function convertDecimalToHex(d) {\n        return Math.round(parseFloat(d) * 255).toString(16);\n    }\n    // Converts a hex value to a decimal\n    function convertHexToDecimal(h) {\n        return (parseIntFromHex(h) / 255);\n    }\n\n    var matchers = (function() {\n\n        // <http://www.w3.org/TR/css3-values/#integers>\n        var CSS_INTEGER = \"[-\\\\+]?\\\\d+%?\";\n\n        // <http://www.w3.org/TR/css3-values/#number-value>\n        var CSS_NUMBER = \"[-\\\\+]?\\\\d*\\\\.\\\\d+%?\";\n\n        // Allow positive/negative integer/number.  Don't capture the either/or, just the entire outcome.\n        var CSS_UNIT = \"(?:\" + CSS_NUMBER + \")|(?:\" + CSS_INTEGER + \")\";\n\n        // Actual matching.\n        // Parentheses and commas are optional, but not required.\n        // Whitespace can take the place of commas or opening paren\n        var PERMISSIVE_MATCH3 = \"[\\\\s|\\\\(]+(\" + CSS_UNIT + \")[,|\\\\s]+(\" + CSS_UNIT + \")[,|\\\\s]+(\" + CSS_UNIT + \")\\\\s*\\\\)?\";\n        var PERMISSIVE_MATCH4 = \"[\\\\s|\\\\(]+(\" + CSS_UNIT + \")[,|\\\\s]+(\" + CSS_UNIT + \")[,|\\\\s]+(\" + CSS_UNIT + \")[,|\\\\s]+(\" + CSS_UNIT + \")\\\\s*\\\\)?\";\n\n        return {\n            rgb: new RegExp(\"rgb\" + PERMISSIVE_MATCH3),\n            rgba: new RegExp(\"rgba\" + PERMISSIVE_MATCH4),\n            hsl: new RegExp(\"hsl\" + PERMISSIVE_MATCH3),\n            hsla: new RegExp(\"hsla\" + PERMISSIVE_MATCH4),\n            hsv: new RegExp(\"hsv\" + PERMISSIVE_MATCH3),\n            hex3: /^([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/,\n            hex6: /^([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/,\n            hex8: /^([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/\n        };\n    })();\n\n    // `stringInputToObject`\n    // Permissive string parsing.  Take in a number of formats, and output an object\n    // based on detected format.  Returns `{ r, g, b }` or `{ h, s, l }` or `{ h, s, v}`\n    function stringInputToObject(color) {\n\n        color = color.replace(trimLeft,'').replace(trimRight, '').toLowerCase();\n        var named = false;\n        if (names[color]) {\n            color = names[color];\n            named = true;\n        }\n        else if (color == 'transparent') {\n            return { r: 0, g: 0, b: 0, a: 0, format: \"name\" };\n        }\n\n        // Try to match string input using regular expressions.\n        // Keep most of the number bounding out of this function - don't worry about [0,1] or [0,100] or [0,360]\n        // Just return an object and let the conversion functions handle that.\n        // This way the result will be the same whether the tinycolor is initialized with string or object.\n        var match;\n        if ((match = matchers.rgb.exec(color))) {\n            return { r: match[1], g: match[2], b: match[3] };\n        }\n        if ((match = matchers.rgba.exec(color))) {\n            return { r: match[1], g: match[2], b: match[3], a: match[4] };\n        }\n        if ((match = matchers.hsl.exec(color))) {\n            return { h: match[1], s: match[2], l: match[3] };\n        }\n        if ((match = matchers.hsla.exec(color))) {\n            return { h: match[1], s: match[2], l: match[3], a: match[4] };\n        }\n        if ((match = matchers.hsv.exec(color))) {\n            return { h: match[1], s: match[2], v: match[3] };\n        }\n        if ((match = matchers.hex8.exec(color))) {\n            return {\n                a: convertHexToDecimal(match[1]),\n                r: parseIntFromHex(match[2]),\n                g: parseIntFromHex(match[3]),\n                b: parseIntFromHex(match[4]),\n                format: named ? \"name\" : \"hex8\"\n            };\n        }\n        if ((match = matchers.hex6.exec(color))) {\n            return {\n                r: parseIntFromHex(match[1]),\n                g: parseIntFromHex(match[2]),\n                b: parseIntFromHex(match[3]),\n                format: named ? \"name\" : \"hex\"\n            };\n        }\n        if ((match = matchers.hex3.exec(color))) {\n            return {\n                r: parseIntFromHex(match[1] + '' + match[1]),\n                g: parseIntFromHex(match[2] + '' + match[2]),\n                b: parseIntFromHex(match[3] + '' + match[3]),\n                format: named ? \"name\" : \"hex\"\n            };\n        }\n\n        return false;\n    }\n\n    // Expose tinycolor to window, does not need to run in non-browser context.\n    window.tinycolor = tinycolor;\n\n    })();\n\n\n    $(function () {\n        if ($.fn.spectrum.load) {\n            $.fn.spectrum.processNativeColorInputs();\n        }\n    });\n\n})(window, jQuery);\n"
  },
  {
    "path": "flowable-ui-web/task/libs/angular-strap_2.1.6/angular-strap.js",
    "content": "/**\n * angular-strap\n * @version v2.1.6 - 2015-01-11\n * @link http://mgcrea.github.io/angular-strap\n * @author Olivier Louvignes (olivier@mg-crea.com)\n * @license MIT License, http://www.opensource.org/licenses/MIT\n */\n(function(window, document, undefined) {\n'use strict';\n// Source: module.js\nangular.module('mgcrea.ngStrap', [\n  'mgcrea.ngStrap.modal',\n  'mgcrea.ngStrap.aside',\n  'mgcrea.ngStrap.alert',\n  'mgcrea.ngStrap.button',\n  'mgcrea.ngStrap.select',\n  'mgcrea.ngStrap.datepicker',\n  'mgcrea.ngStrap.timepicker',\n  'mgcrea.ngStrap.navbar',\n  'mgcrea.ngStrap.tooltip',\n  'mgcrea.ngStrap.popover',\n  'mgcrea.ngStrap.dropdown',\n  'mgcrea.ngStrap.typeahead',\n  'mgcrea.ngStrap.scrollspy',\n  'mgcrea.ngStrap.affix',\n  'mgcrea.ngStrap.tab',\n  'mgcrea.ngStrap.collapse'\n]);\n\n// Source: affix.js\nangular.module('mgcrea.ngStrap.affix', ['mgcrea.ngStrap.helpers.dimensions', 'mgcrea.ngStrap.helpers.debounce'])\n\n  .provider('$affix', function() {\n\n    var defaults = this.defaults = {\n      offsetTop: 'auto'\n    };\n\n    this.$get = [\"$window\", \"debounce\", \"dimensions\", function($window, debounce, dimensions) {\n\n      var bodyEl = angular.element($window.document.body);\n      var windowEl = angular.element($window);\n\n      function AffixFactory(element, config) {\n\n        var $affix = {};\n\n        // Common vars\n        var options = angular.extend({}, defaults, config);\n        var targetEl = options.target;\n\n        // Initial private vars\n        var reset = 'affix affix-top affix-bottom',\n            setWidth = false,\n            initialAffixTop = 0,\n            initialOffsetTop = 0,\n            offsetTop = 0,\n            offsetBottom = 0,\n            affixed = null,\n            unpin = null;\n\n        var parent = element.parent();\n        // Options: custom parent\n        if (options.offsetParent) {\n          if (options.offsetParent.match(/^\\d+$/)) {\n            for (var i = 0; i < (options.offsetParent * 1) - 1; i++) {\n              parent = parent.parent();\n            }\n          }\n          else {\n            parent = angular.element(options.offsetParent);\n          }\n        }\n\n        $affix.init = function() {\n\n          this.$parseOffsets();\n          initialOffsetTop = dimensions.offset(element[0]).top + initialAffixTop;\n          setWidth = !element[0].style.width;\n\n          // Bind events\n          targetEl.on('scroll', this.checkPosition);\n          targetEl.on('click', this.checkPositionWithEventLoop);\n          windowEl.on('resize', this.$debouncedOnResize);\n\n          // Both of these checkPosition() calls are necessary for the case where\n          // the user hits refresh after scrolling to the bottom of the page.\n          this.checkPosition();\n          this.checkPositionWithEventLoop();\n\n        };\n\n        $affix.destroy = function() {\n\n          // Unbind events\n          targetEl.off('scroll', this.checkPosition);\n          targetEl.off('click', this.checkPositionWithEventLoop);\n          windowEl.off('resize', this.$debouncedOnResize);\n\n        };\n\n        $affix.checkPositionWithEventLoop = function() {\n\n          // IE 9 throws an error if we use 'this' instead of '$affix'\n          // in this setTimeout call\n          setTimeout($affix.checkPosition, 1);\n\n        };\n\n        $affix.checkPosition = function() {\n          // if (!this.$element.is(':visible')) return\n\n          var scrollTop = getScrollTop();\n          var position = dimensions.offset(element[0]);\n          var elementHeight = dimensions.height(element[0]);\n\n          // Get required affix class according to position\n          var affix = getRequiredAffixClass(unpin, position, elementHeight);\n\n          // Did affix status changed this last check?\n          if(affixed === affix) return;\n          affixed = affix;\n\n          // Add proper affix class\n          element.removeClass(reset).addClass('affix' + ((affix !== 'middle') ? '-' + affix : ''));\n\n          if(affix === 'top') {\n            unpin = null;\n            element.css('position', (options.offsetParent) ? '' : 'relative');\n            if(setWidth) {\n              element.css('width', '');\n            }\n            element.css('top', '');\n          } else if(affix === 'bottom') {\n            if (options.offsetUnpin) {\n              unpin = -(options.offsetUnpin * 1);\n            }\n            else {\n              // Calculate unpin threshold when affixed to bottom.\n              // Hopefully the browser scrolls pixel by pixel.\n              unpin = position.top - scrollTop;\n            }\n            if(setWidth) {\n              element.css('width', '');\n            }\n            element.css('position', (options.offsetParent) ? '' : 'relative');\n            element.css('top', (options.offsetParent) ? '' : ((bodyEl[0].offsetHeight - offsetBottom - elementHeight - initialOffsetTop) + 'px'));\n          } else { // affix === 'middle'\n            unpin = null;\n            if(setWidth) {\n              element.css('width', element[0].offsetWidth + 'px');\n            }\n            element.css('position', 'fixed');\n            element.css('top', initialAffixTop + 'px');\n          }\n\n        };\n\n        $affix.$onResize = function() {\n          $affix.$parseOffsets();\n          $affix.checkPosition();\n        };\n        $affix.$debouncedOnResize = debounce($affix.$onResize, 50);\n\n        $affix.$parseOffsets = function() {\n          var initialPosition = element.css('position');\n          // Reset position to calculate correct offsetTop\n          element.css('position', (options.offsetParent) ? '' : 'relative');\n\n          if(options.offsetTop) {\n            if(options.offsetTop === 'auto') {\n              options.offsetTop = '+0';\n            }\n            if(options.offsetTop.match(/^[-+]\\d+$/)) {\n              initialAffixTop = - options.offsetTop * 1;\n              if(options.offsetParent) {\n                offsetTop = dimensions.offset(parent[0]).top + (options.offsetTop * 1);\n              }\n              else {\n                offsetTop = dimensions.offset(element[0]).top - dimensions.css(element[0], 'marginTop', true) + (options.offsetTop * 1);\n              }\n            }\n            else {\n              offsetTop = options.offsetTop * 1;\n            }\n          }\n\n          if(options.offsetBottom) {\n            if(options.offsetParent && options.offsetBottom.match(/^[-+]\\d+$/)) {\n              // add 1 pixel due to rounding problems...\n              offsetBottom = getScrollHeight() - (dimensions.offset(parent[0]).top + dimensions.height(parent[0])) + (options.offsetBottom * 1) + 1;\n            }\n            else {\n              offsetBottom = options.offsetBottom * 1;\n            }\n          }\n\n          // Bring back the element's position after calculations\n          element.css('position', initialPosition);\n        };\n\n        // Private methods\n\n        function getRequiredAffixClass(unpin, position, elementHeight) {\n\n          var scrollTop = getScrollTop();\n          var scrollHeight = getScrollHeight();\n\n          if(scrollTop <= offsetTop) {\n            return 'top';\n          } else if(unpin !== null && (scrollTop + unpin <= position.top)) {\n            return 'middle';\n          } else if(offsetBottom !== null && (position.top + elementHeight + initialAffixTop >= scrollHeight - offsetBottom)) {\n            return 'bottom';\n          } else {\n            return 'middle';\n          }\n\n        }\n\n        function getScrollTop() {\n          return targetEl[0] === $window ? $window.pageYOffset : targetEl[0].scrollTop;\n        }\n\n        function getScrollHeight() {\n          return targetEl[0] === $window ? $window.document.body.scrollHeight : targetEl[0].scrollHeight;\n        }\n\n        $affix.init();\n        return $affix;\n\n      }\n\n      return AffixFactory;\n\n    }];\n\n  })\n\n  .directive('bsAffix', [\"$affix\", \"$window\", function($affix, $window) {\n\n    return {\n      restrict: 'EAC',\n      require: '^?bsAffixTarget',\n      link: function postLink(scope, element, attr, affixTarget) {\n\n        var options = {scope: scope, offsetTop: 'auto', target: affixTarget ? affixTarget.$element : angular.element($window)};\n        angular.forEach(['offsetTop', 'offsetBottom', 'offsetParent', 'offsetUnpin'], function(key) {\n          if(angular.isDefined(attr[key])) options[key] = attr[key];\n        });\n\n        var affix = $affix(element, options);\n        scope.$on('$destroy', function() {\n          affix && affix.destroy();\n          options = null;\n          affix = null;\n        });\n\n      }\n    };\n\n  }])\n\n  .directive('bsAffixTarget', function() {\n    return {\n      controller: [\"$element\", function($element) {\n        this.$element = $element;\n      }]\n    };\n  });\n\n// Source: alert.js\n// @BUG: following snippet won't compile correctly\n// @TODO: submit issue to core\n// '<span ng-if=\"title\"><strong ng-bind=\"title\"></strong>&nbsp;</span><span ng-bind-html=\"content\"></span>' +\n\nangular.module('mgcrea.ngStrap.alert', ['mgcrea.ngStrap.modal'])\n\n  .provider('$alert', function() {\n\n    var defaults = this.defaults = {\n      animation: 'am-fade',\n      prefixClass: 'alert',\n      prefixEvent: 'alert',\n      placement: null,\n      template: 'alert/alert.tpl.html',\n      container: false,\n      element: null,\n      backdrop: false,\n      keyboard: true,\n      show: true,\n      // Specific options\n      duration: false,\n      type: false,\n      dismissable: true\n    };\n\n    this.$get = [\"$modal\", \"$timeout\", function($modal, $timeout) {\n\n      function AlertFactory(config) {\n\n        var $alert = {};\n\n        // Common vars\n        var options = angular.extend({}, defaults, config);\n\n        $alert = $modal(options);\n\n        // Support scope as string options [/*title, content, */ type, dismissable]\n        $alert.$scope.dismissable = !!options.dismissable;\n        if(options.type) {\n          $alert.$scope.type = options.type;\n        }\n\n        // Support auto-close duration\n        var show = $alert.show;\n        if(options.duration) {\n          $alert.show = function() {\n            show();\n            $timeout(function() {\n              $alert.hide();\n            }, options.duration * 1000);\n          };\n        }\n\n        return $alert;\n\n      }\n\n      return AlertFactory;\n\n    }];\n\n  })\n\n  .directive('bsAlert', [\"$window\", \"$sce\", \"$alert\", function($window, $sce, $alert) {\n\n    var requestAnimationFrame = $window.requestAnimationFrame || $window.setTimeout;\n\n    return {\n      restrict: 'EAC',\n      scope: true,\n      link: function postLink(scope, element, attr, transclusion) {\n\n        // Directive options\n        var options = {scope: scope, element: element, show: false};\n        angular.forEach(['template', 'placement', 'keyboard', 'html', 'container', 'animation', 'duration', 'dismissable'], function(key) {\n          if(angular.isDefined(attr[key])) options[key] = attr[key];\n        });\n\n        // Support scope as data-attrs\n        angular.forEach(['title', 'content', 'type'], function(key) {\n          attr[key] && attr.$observe(key, function(newValue, oldValue) {\n            scope[key] = $sce.trustAsHtml(newValue);\n          });\n        });\n\n        // Support scope as an object\n        attr.bsAlert && scope.$watch(attr.bsAlert, function(newValue, oldValue) {\n          if(angular.isObject(newValue)) {\n            angular.extend(scope, newValue);\n          } else {\n            scope.content = newValue;\n          }\n        }, true);\n\n        // Initialize alert\n        var alert = $alert(options);\n\n        // Trigger\n        element.on(attr.trigger || 'click', alert.toggle);\n\n        // Garbage collection\n        scope.$on('$destroy', function() {\n          if (alert) alert.destroy();\n          options = null;\n          alert = null;\n        });\n\n      }\n    };\n\n  }]);\n\n// Source: aside.js\nangular.module('mgcrea.ngStrap.aside', ['mgcrea.ngStrap.modal'])\n\n  .provider('$aside', function() {\n\n    var defaults = this.defaults = {\n      animation: 'am-fade-and-slide-right',\n      prefixClass: 'aside',\n      prefixEvent: 'aside',\n      placement: 'right',\n      template: 'aside/aside.tpl.html',\n      contentTemplate: false,\n      container: false,\n      element: null,\n      backdrop: true,\n      keyboard: true,\n      html: false,\n      show: true\n    };\n\n    this.$get = [\"$modal\", function($modal) {\n\n      function AsideFactory(config) {\n\n        var $aside = {};\n\n        // Common vars\n        var options = angular.extend({}, defaults, config);\n\n        $aside = $modal(options);\n\n        return $aside;\n\n      }\n\n      return AsideFactory;\n\n    }];\n\n  })\n\n  .directive('bsAside', [\"$window\", \"$sce\", \"$aside\", function($window, $sce, $aside) {\n\n    var requestAnimationFrame = $window.requestAnimationFrame || $window.setTimeout;\n\n    return {\n      restrict: 'EAC',\n      scope: true,\n      link: function postLink(scope, element, attr, transclusion) {\n        // Directive options\n        var options = {scope: scope, element: element, show: false};\n        angular.forEach(['template', 'contentTemplate', 'placement', 'backdrop', 'keyboard', 'html', 'container', 'animation'], function(key) {\n          if(angular.isDefined(attr[key])) options[key] = attr[key];\n        });\n\n        // Support scope as data-attrs\n        angular.forEach(['title', 'content'], function(key) {\n          attr[key] && attr.$observe(key, function(newValue, oldValue) {\n            scope[key] = $sce.trustAsHtml(newValue);\n          });\n        });\n\n        // Support scope as an object\n        attr.bsAside && scope.$watch(attr.bsAside, function(newValue, oldValue) {\n          if(angular.isObject(newValue)) {\n            angular.extend(scope, newValue);\n          } else {\n            scope.content = newValue;\n          }\n        }, true);\n\n        // Initialize aside\n        var aside = $aside(options);\n\n        // Trigger\n        element.on(attr.trigger || 'click', aside.toggle);\n\n        // Garbage collection\n        scope.$on('$destroy', function() {\n          if (aside) aside.destroy();\n          options = null;\n          aside = null;\n        });\n\n      }\n    };\n\n  }]);\n\n// Source: button.js\nangular.module('mgcrea.ngStrap.button', [])\n\n  .provider('$button', function() {\n\n    var defaults = this.defaults = {\n      activeClass:'active',\n      toggleEvent:'click'\n    };\n\n    this.$get = function() {\n      return {defaults: defaults};\n    };\n\n  })\n\n  .directive('bsCheckboxGroup', function() {\n\n    return {\n      restrict: 'A',\n      require: 'ngModel',\n      compile: function postLink(element, attr) {\n        element.attr('data-toggle', 'buttons');\n        element.removeAttr('ng-model');\n        var children = element[0].querySelectorAll('input[type=\"checkbox\"]');\n        angular.forEach(children, function(child) {\n          var childEl = angular.element(child);\n          childEl.attr('bs-checkbox', '');\n          childEl.attr('ng-model', attr.ngModel + '.' + childEl.attr('value'));\n        });\n      }\n\n    };\n\n  })\n\n  .directive('bsCheckbox', [\"$button\", \"$$rAF\", function($button, $$rAF) {\n\n    var defaults = $button.defaults;\n    var constantValueRegExp = /^(true|false|\\d+)$/;\n\n    return {\n      restrict: 'A',\n      require: 'ngModel',\n      link: function postLink(scope, element, attr, controller) {\n\n        var options = defaults;\n\n        // Support label > input[type=\"checkbox\"]\n        var isInput = element[0].nodeName === 'INPUT';\n        var activeElement = isInput ? element.parent() : element;\n\n        var trueValue = angular.isDefined(attr.trueValue) ? attr.trueValue : true;\n        if(constantValueRegExp.test(attr.trueValue)) {\n          trueValue = scope.$eval(attr.trueValue);\n        }\n        var falseValue = angular.isDefined(attr.falseValue) ? attr.falseValue : false;\n        if(constantValueRegExp.test(attr.falseValue)) {\n          falseValue = scope.$eval(attr.falseValue);\n        }\n\n        // Parse exotic values\n        var hasExoticValues = typeof trueValue !== 'boolean' || typeof falseValue !== 'boolean';\n        if(hasExoticValues) {\n          controller.$parsers.push(function(viewValue) {\n            // console.warn('$parser', element.attr('ng-model'), 'viewValue', viewValue);\n            return viewValue ? trueValue : falseValue;\n          });\n          // modelValue -> $formatters -> viewValue\n          controller.$formatters.push(function(modelValue) {\n             // console.warn('$formatter(\"%s\"): modelValue=%o (%o)', element.attr('ng-model'), modelValue, typeof modelValue);\n             return angular.equals(modelValue, trueValue);\n          });\n          // Fix rendering for exotic values\n          scope.$watch(attr.ngModel, function(newValue, oldValue) {\n            controller.$render();\n          });\n        }\n\n        // model -> view\n        controller.$render = function () {\n          // console.warn('$render', element.attr('ng-model'), 'controller.$modelValue', typeof controller.$modelValue, controller.$modelValue, 'controller.$viewValue', typeof controller.$viewValue, controller.$viewValue);\n          var isActive = angular.equals(controller.$modelValue, trueValue);\n          $$rAF(function() {\n            if(isInput) element[0].checked = isActive;\n            activeElement.toggleClass(options.activeClass, isActive);\n          });\n        };\n\n        // view -> model\n        element.bind(options.toggleEvent, function() {\n          scope.$apply(function () {\n            // console.warn('!click', element.attr('ng-model'), 'controller.$viewValue', typeof controller.$viewValue, controller.$viewValue, 'controller.$modelValue', typeof controller.$modelValue, controller.$modelValue);\n            if(!isInput) {\n              controller.$setViewValue(!activeElement.hasClass('active'));\n            }\n            if(!hasExoticValues) {\n              controller.$render();\n            }\n          });\n        });\n\n      }\n\n    };\n\n  }])\n\n  .directive('bsRadioGroup', function() {\n\n    return {\n      restrict: 'A',\n      require: 'ngModel',\n      compile: function postLink(element, attr) {\n        element.attr('data-toggle', 'buttons');\n        element.removeAttr('ng-model');\n        var children = element[0].querySelectorAll('input[type=\"radio\"]');\n        angular.forEach(children, function(child) {\n          angular.element(child).attr('bs-radio', '');\n          angular.element(child).attr('ng-model', attr.ngModel);\n        });\n      }\n\n    };\n\n  })\n\n  .directive('bsRadio', [\"$button\", \"$$rAF\", function($button, $$rAF) {\n\n    var defaults = $button.defaults;\n    var constantValueRegExp = /^(true|false|\\d+)$/;\n\n    return {\n      restrict: 'A',\n      require: 'ngModel',\n      link: function postLink(scope, element, attr, controller) {\n\n        var options = defaults;\n\n        // Support `label > input[type=\"radio\"]` markup\n        var isInput = element[0].nodeName === 'INPUT';\n        var activeElement = isInput ? element.parent() : element;\n\n        var value = constantValueRegExp.test(attr.value) ? scope.$eval(attr.value) : attr.value;\n\n        // model -> view\n        controller.$render = function () {\n          // console.warn('$render', element.attr('value'), 'controller.$modelValue', typeof controller.$modelValue, controller.$modelValue, 'controller.$viewValue', typeof controller.$viewValue, controller.$viewValue);\n          var isActive = angular.equals(controller.$modelValue, value);\n          $$rAF(function() {\n            if(isInput) element[0].checked = isActive;\n            activeElement.toggleClass(options.activeClass, isActive);\n          });\n        };\n\n        // view -> model\n        element.bind(options.toggleEvent, function() {\n          scope.$apply(function () {\n            // console.warn('!click', element.attr('value'), 'controller.$viewValue', typeof controller.$viewValue, controller.$viewValue, 'controller.$modelValue', typeof controller.$modelValue, controller.$modelValue);\n            controller.$setViewValue(value);\n            controller.$render();\n          });\n        });\n\n      }\n\n    };\n\n  }]);\n\n// Source: collapse.js\nangular.module('mgcrea.ngStrap.collapse', [])\n\n  .provider('$collapse', function() {\n\n    var defaults = this.defaults = {\n      animation: 'am-collapse',\n      disallowToggle: false,\n      activeClass: 'in',\n      startCollapsed: false,\n      allowMultiple: false\n    };\n\n    var controller = this.controller = function($scope, $element, $attrs) {\n      var self = this;\n\n      // Attributes options\n      self.$options = angular.copy(defaults);\n      angular.forEach(['animation', 'disallowToggle', 'activeClass', 'startCollapsed', 'allowMultiple'], function (key) {\n        if(angular.isDefined($attrs[key])) self.$options[key] = $attrs[key];\n      });\n\n      self.$toggles = [];\n      self.$targets = [];\n\n      self.$viewChangeListeners = [];\n\n      self.$registerToggle = function(element) {\n        self.$toggles.push(element);\n      };\n      self.$registerTarget = function(element) {\n        self.$targets.push(element);\n      };\n\n      self.$unregisterToggle = function(element) {\n        var index = self.$toggles.indexOf(element);\n        // remove toggle from $toggles array\n        self.$toggles.splice(index, 1);\n      };\n      self.$unregisterTarget = function(element) {\n        var index = self.$targets.indexOf(element);\n\n        // remove element from $targets array\n        self.$targets.splice(index, 1);\n\n        if (self.$options.allowMultiple) {\n          // remove target index from $active array values\n          deactivateItem(element);\n        }\n\n        // fix active item indexes\n        fixActiveItemIndexes(index);\n\n        self.$viewChangeListeners.forEach(function(fn) {\n          fn();\n        });\n      };\n\n      // use array to store all the currently open panels\n      self.$targets.$active = !self.$options.startCollapsed ? [0] : [];\n      self.$setActive = $scope.$setActive = function(value) {\n        if(angular.isArray(value)) {\n          self.$targets.$active = angular.copy(value);\n        }\n        else if(!self.$options.disallowToggle) {\n          // toogle element active status\n          isActive(value) ? deactivateItem(value) : activateItem(value);\n        } else {\n          activateItem(value);\n        }\n\n        self.$viewChangeListeners.forEach(function(fn) {\n          fn();\n        });\n      };\n\n      self.$activeIndexes = function() {\n        return self.$options.allowMultiple ? self.$targets.$active :\n          self.$targets.$active.length === 1 ? self.$targets.$active[0] : -1;\n      };\n\n      function fixActiveItemIndexes(index) {\n        // item with index was removed, so we\n        // need to adjust other items index values\n        var activeIndexes = self.$targets.$active;\n        for(var i = 0; i < activeIndexes.length; i++) {\n          if (index < activeIndexes[i]) {\n            activeIndexes[i] = activeIndexes[i] - 1;\n          }\n\n          // the last item is active, so we need to\n          // adjust its index\n          if (activeIndexes[i] === self.$targets.length) {\n            activeIndexes[i] = self.$targets.length - 1;\n          }\n        }\n      }\n\n      function isActive(value) {\n        var activeItems = self.$targets.$active;\n        return activeItems.indexOf(value) === -1 ? false : true;\n      }\n\n      function deactivateItem(value) {\n        var index = self.$targets.$active.indexOf(value);\n        if (index !== -1) {\n          self.$targets.$active.splice(index, 1);\n        }\n      }\n\n      function activateItem(value) {\n        if (!self.$options.allowMultiple) {\n          // remove current selected item\n          self.$targets.$active.splice(0, 1);\n        }\n\n        if (self.$targets.$active.indexOf(value) === -1) {\n          self.$targets.$active.push(value);\n        }\n      }\n\n    };\n\n    this.$get = function() {\n      var $collapse = {};\n      $collapse.defaults = defaults;\n      $collapse.controller = controller;\n      return $collapse;\n    };\n\n  })\n\n  .directive('bsCollapse', [\"$window\", \"$animate\", \"$collapse\", function($window, $animate, $collapse) {\n\n    var defaults = $collapse.defaults;\n\n    return {\n      require: ['?ngModel', 'bsCollapse'],\n      controller: ['$scope', '$element', '$attrs', $collapse.controller],\n      link: function postLink(scope, element, attrs, controllers) {\n\n        var ngModelCtrl = controllers[0];\n        var bsCollapseCtrl = controllers[1];\n\n        if(ngModelCtrl) {\n\n          // Update the modelValue following\n          bsCollapseCtrl.$viewChangeListeners.push(function() {\n            ngModelCtrl.$setViewValue(bsCollapseCtrl.$activeIndexes());\n          });\n\n          // modelValue -> $formatters -> viewValue\n          ngModelCtrl.$formatters.push(function(modelValue) {\n            // console.warn('$formatter(\"%s\"): modelValue=%o (%o)', element.attr('ng-model'), modelValue, typeof modelValue);\n            if (angular.isArray(modelValue)) {\n              // model value is an array, so just replace\n              // the active items directly\n              bsCollapseCtrl.$setActive(modelValue);\n            }\n            else {\n              var activeIndexes = bsCollapseCtrl.$activeIndexes();\n\n              if (angular.isArray(activeIndexes)) {\n                // we have an array of selected indexes\n                if (activeIndexes.indexOf(modelValue * 1) === -1) {\n                  // item with modelValue index is not active\n                  bsCollapseCtrl.$setActive(modelValue * 1);\n                }\n              }\n              else if (activeIndexes !== modelValue * 1) {\n                bsCollapseCtrl.$setActive(modelValue * 1);\n              }\n            }\n            return modelValue;\n          });\n\n        }\n\n      }\n    };\n\n  }])\n\n  .directive('bsCollapseToggle', function() {\n\n    return {\n      require: ['^?ngModel', '^bsCollapse'],\n      link: function postLink(scope, element, attrs, controllers) {\n\n        var ngModelCtrl = controllers[0];\n        var bsCollapseCtrl = controllers[1];\n\n        // Add base attr\n        element.attr('data-toggle', 'collapse');\n\n        // Push pane to parent bsCollapse controller\n        bsCollapseCtrl.$registerToggle(element);\n\n        // remove toggle from collapse controller when toggle is destroyed\n        scope.$on('$destroy', function() {\n          bsCollapseCtrl.$unregisterToggle(element);\n        });\n\n        element.on('click', function() {\n          var index = attrs.bsCollapseToggle || bsCollapseCtrl.$toggles.indexOf(element);\n          bsCollapseCtrl.$setActive(index * 1);\n          scope.$apply();\n        });\n\n      }\n    };\n\n  })\n\n  .directive('bsCollapseTarget', [\"$animate\", function($animate) {\n\n    return {\n      require: ['^?ngModel', '^bsCollapse'],\n      // scope: true,\n      link: function postLink(scope, element, attrs, controllers) {\n\n        var ngModelCtrl = controllers[0];\n        var bsCollapseCtrl = controllers[1];\n\n        // Add base class\n        element.addClass('collapse');\n\n        // Add animation class\n        if(bsCollapseCtrl.$options.animation) {\n          element.addClass(bsCollapseCtrl.$options.animation);\n        }\n\n        // Push pane to parent bsCollapse controller\n        bsCollapseCtrl.$registerTarget(element);\n\n        // remove pane target from collapse controller when target is destroyed\n        scope.$on('$destroy', function() {\n          bsCollapseCtrl.$unregisterTarget(element);\n        });\n\n        function render() {\n          var index = bsCollapseCtrl.$targets.indexOf(element);\n          var active = bsCollapseCtrl.$activeIndexes();\n          var action = 'removeClass';\n          if (angular.isArray(active)) {\n            if (active.indexOf(index) !== -1) {\n              action = 'addClass';\n            }\n          }\n          else if (index === active) {\n            action = 'addClass';\n          }\n\n          $animate[action](element, bsCollapseCtrl.$options.activeClass);\n        }\n\n        bsCollapseCtrl.$viewChangeListeners.push(function() {\n          render();\n        });\n        render();\n\n      }\n    };\n\n  }]);\n\n// Source: datepicker.js\nangular.module('mgcrea.ngStrap.datepicker', [\n  'mgcrea.ngStrap.helpers.dateParser',\n  'mgcrea.ngStrap.helpers.dateFormatter',\n  'mgcrea.ngStrap.tooltip'])\n\n  .provider('$datepicker', function() {\n\n    var defaults = this.defaults = {\n      animation: 'am-fade',\n      prefixClass: 'datepicker',\n      placement: 'bottom-left',\n      template: 'datepicker/datepicker.tpl.html',\n      trigger: 'focus',\n      container: false,\n      keyboard: true,\n      html: false,\n      delay: 0,\n      // lang: $locale.id,\n      useNative: false,\n      dateType: 'date',\n      dateFormat: 'shortDate',\n      modelDateFormat: null,\n      dayFormat: 'dd',\n      monthFormat: 'MMM',\n      yearFormat: 'yyyy',\n      monthTitleFormat: 'MMMM yyyy',\n      yearTitleFormat: 'yyyy',\n      strictFormat: false,\n      autoclose: false,\n      minDate: -Infinity,\n      maxDate: +Infinity,\n      startView: 0,\n      minView: 0,\n      startWeek: 0,\n      daysOfWeekDisabled: '',\n      iconLeft: 'glyphicon glyphicon-chevron-left',\n      iconRight: 'glyphicon glyphicon-chevron-right'\n    };\n\n    this.$get = [\"$window\", \"$document\", \"$rootScope\", \"$sce\", \"$dateFormatter\", \"datepickerViews\", \"$tooltip\", \"$timeout\", function($window, $document, $rootScope, $sce, $dateFormatter, datepickerViews, $tooltip, $timeout) {\n\n      var bodyEl = angular.element($window.document.body);\n      var isNative = /(ip(a|o)d|iphone|android)/ig.test($window.navigator.userAgent);\n      var isTouch = ('createTouch' in $window.document) && isNative;\n      if(!defaults.lang) defaults.lang = $dateFormatter.getDefaultLocale();\n\n      function DatepickerFactory(element, controller, config) {\n\n        var $datepicker = $tooltip(element, angular.extend({}, defaults, config));\n        var parentScope = config.scope;\n        var options = $datepicker.$options;\n        var scope = $datepicker.$scope;\n        if(options.startView) options.startView -= options.minView;\n\n        // View vars\n\n        var pickerViews = datepickerViews($datepicker);\n        $datepicker.$views = pickerViews.views;\n        var viewDate = pickerViews.viewDate;\n        scope.$mode = options.startView;\n        scope.$iconLeft = options.iconLeft;\n        scope.$iconRight = options.iconRight;\n        var $picker = $datepicker.$views[scope.$mode];\n\n        // Scope methods\n\n        scope.$select = function(date) {\n          $datepicker.select(date);\n        };\n        scope.$selectPane = function(value) {\n          $datepicker.$selectPane(value);\n        };\n        scope.$toggleMode = function() {\n          $datepicker.setMode((scope.$mode + 1) % $datepicker.$views.length);\n        };\n\n        // Public methods\n\n        $datepicker.update = function(date) {\n          // console.warn('$datepicker.update() newValue=%o', date);\n          if(angular.isDate(date) && !isNaN(date.getTime())) {\n            $datepicker.$date = date;\n            $picker.update.call($picker, date);\n          }\n          // Build only if pristine\n          $datepicker.$build(true);\n        };\n\n        $datepicker.updateDisabledDates = function(dateRanges) {\n          options.disabledDateRanges = dateRanges;\n          for(var i = 0, l = scope.rows.length; i < l; i++) {\n            angular.forEach(scope.rows[i], $datepicker.$setDisabledEl);\n          }\n        };\n\n        $datepicker.select = function(date, keep) {\n          // console.warn('$datepicker.select', date, scope.$mode);\n          if(!angular.isDate(controller.$dateValue)) controller.$dateValue = new Date(date);\n          if(!scope.$mode || keep) {\n            controller.$setViewValue(angular.copy(date));\n            controller.$render();\n            if(options.autoclose && !keep) {\n              $timeout(function() { $datepicker.hide(true); });\n            }\n          } else {\n            angular.extend(viewDate, {year: date.getFullYear(), month: date.getMonth(), date: date.getDate()});\n            $datepicker.setMode(scope.$mode - 1);\n            $datepicker.$build();\n          }\n        };\n\n        $datepicker.setMode = function(mode) {\n          // console.warn('$datepicker.setMode', mode);\n          scope.$mode = mode;\n          $picker = $datepicker.$views[scope.$mode];\n          $datepicker.$build();\n        };\n\n        // Protected methods\n\n        $datepicker.$build = function(pristine) {\n          // console.warn('$datepicker.$build() viewDate=%o', viewDate);\n          if(pristine === true && $picker.built) return;\n          if(pristine === false && !$picker.built) return;\n          $picker.build.call($picker);\n        };\n\n        $datepicker.$updateSelected = function() {\n          for(var i = 0, l = scope.rows.length; i < l; i++) {\n            angular.forEach(scope.rows[i], updateSelected);\n          }\n        };\n\n        $datepicker.$isSelected = function(date) {\n          return $picker.isSelected(date);\n        };\n\n        $datepicker.$setDisabledEl = function(el) {\n          el.disabled = $picker.isDisabled(el.date);\n        };\n\n        $datepicker.$selectPane = function(value) {\n          var steps = $picker.steps;\n          // set targetDate to first day of month to avoid problems with\n          // date values rollover. This assumes the viewDate does not\n          // depend on the day of the month\n          var targetDate = new Date(Date.UTC(viewDate.year + ((steps.year || 0) * value), viewDate.month + ((steps.month || 0) * value), 1));\n          angular.extend(viewDate, {year: targetDate.getUTCFullYear(), month: targetDate.getUTCMonth(), date: targetDate.getUTCDate()});\n          $datepicker.$build();\n        };\n\n        $datepicker.$onMouseDown = function(evt) {\n          // Prevent blur on mousedown on .dropdown-menu\n          evt.preventDefault();\n          evt.stopPropagation();\n          // Emulate click for mobile devices\n          if(isTouch) {\n            var targetEl = angular.element(evt.target);\n            if(targetEl[0].nodeName.toLowerCase() !== 'button') {\n              targetEl = targetEl.parent();\n            }\n            targetEl.triggerHandler('click');\n          }\n        };\n\n        $datepicker.$onKeyDown = function(evt) {\n          if (!/(38|37|39|40|13)/.test(evt.keyCode) || evt.shiftKey || evt.altKey) return;\n          evt.preventDefault();\n          evt.stopPropagation();\n\n          if(evt.keyCode === 13) {\n            if(!scope.$mode) {\n              return $datepicker.hide(true);\n            } else {\n              return scope.$apply(function() { $datepicker.setMode(scope.$mode - 1); });\n            }\n          }\n\n          // Navigate with keyboard\n          $picker.onKeyDown(evt);\n          parentScope.$digest();\n        };\n\n        // Private\n\n        function updateSelected(el) {\n          el.selected = $datepicker.$isSelected(el.date);\n        }\n\n        function focusElement() {\n          element[0].focus();\n        }\n\n        // Overrides\n\n        var _init = $datepicker.init;\n        $datepicker.init = function() {\n          if(isNative && options.useNative) {\n            element.prop('type', 'date');\n            element.css('-webkit-appearance', 'textfield');\n            return;\n          } else if(isTouch) {\n            element.prop('type', 'text');\n            element.attr('readonly', 'true');\n            element.on('click', focusElement);\n          }\n          _init();\n        };\n\n        var _destroy = $datepicker.destroy;\n        $datepicker.destroy = function() {\n          if(isNative && options.useNative) {\n            element.off('click', focusElement);\n          }\n          _destroy();\n        };\n\n        var _show = $datepicker.show;\n        $datepicker.show = function() {\n          _show();\n          // use timeout to hookup the events to prevent\n          // event bubbling from being processed imediately.\n          $timeout(function() {\n            // if $datepicker is no longer showing, don't setup events\n            if(!$datepicker.$isShown) return;\n            $datepicker.$element.on(isTouch ? 'touchstart' : 'mousedown', $datepicker.$onMouseDown);\n            if(options.keyboard) {\n              element.on('keydown', $datepicker.$onKeyDown);\n            }\n          }, 0, false);\n        };\n\n        var _hide = $datepicker.hide;\n        $datepicker.hide = function(blur) {\n          if(!$datepicker.$isShown) return;\n          $datepicker.$element.off(isTouch ? 'touchstart' : 'mousedown', $datepicker.$onMouseDown);\n          if(options.keyboard) {\n            element.off('keydown', $datepicker.$onKeyDown);\n          }\n          _hide(blur);\n        };\n\n        return $datepicker;\n\n      }\n\n      DatepickerFactory.defaults = defaults;\n      return DatepickerFactory;\n\n    }];\n\n  })\n\n  .directive('bsDatepicker', [\"$window\", \"$parse\", \"$q\", \"$dateFormatter\", \"$dateParser\", \"$datepicker\", function($window, $parse, $q, $dateFormatter, $dateParser, $datepicker) {\n\n    var defaults = $datepicker.defaults;\n    var isNative = /(ip(a|o)d|iphone|android)/ig.test($window.navigator.userAgent);\n\n    return {\n      restrict: 'EAC',\n      require: 'ngModel',\n      link: function postLink(scope, element, attr, controller) {\n\n        // Directive options\n        var options = {scope: scope, controller: controller};\n        angular.forEach(['placement', 'container', 'delay', 'trigger', 'keyboard', 'html', 'animation', 'template', 'autoclose', 'dateType', 'dateFormat', 'modelDateFormat', 'dayFormat', 'strictFormat', 'startWeek', 'startDate', 'useNative', 'lang', 'startView', 'minView', 'iconLeft', 'iconRight', 'daysOfWeekDisabled', 'id'], function(key) {\n          if(angular.isDefined(attr[key])) options[key] = attr[key];\n        });\n\n        // Visibility binding support\n        attr.bsShow && scope.$watch(attr.bsShow, function(newValue, oldValue) {\n          if(!datepicker || !angular.isDefined(newValue)) return;\n          if(angular.isString(newValue)) newValue = !!newValue.match(/true|,?(datepicker),?/i);\n          newValue === true ? datepicker.show() : datepicker.hide();\n        });\n\n        // Initialize datepicker\n        var datepicker = $datepicker(element, controller, options);\n        options = datepicker.$options;\n        // Set expected iOS format\n        if(isNative && options.useNative) options.dateFormat = 'yyyy-MM-dd';\n\n        var lang = options.lang;\n\n        var formatDate = function(date, format) {\n          return $dateFormatter.formatDate(date, format, lang);\n        };\n\n        var dateParser = $dateParser({format: options.dateFormat, lang: lang, strict: options.strictFormat});\n\n        // Observe attributes for changes\n        angular.forEach(['minDate', 'maxDate'], function(key) {\n          // console.warn('attr.$observe(%s)', key, attr[key]);\n          angular.isDefined(attr[key]) && attr.$observe(key, function(newValue) {\n            // console.warn('attr.$observe(%s)=%o', key, newValue);\n            datepicker.$options[key] = dateParser.getDateForAttribute(key, newValue);\n            // Build only if dirty\n            !isNaN(datepicker.$options[key]) && datepicker.$build(false);\n            validateAgainstMinMaxDate(controller.$dateValue);\n          });\n        });\n\n        // Watch model for changes\n        scope.$watch(attr.ngModel, function(newValue, oldValue) {\n          datepicker.update(controller.$dateValue);\n        }, true);\n\n        // Normalize undefined/null/empty array,\n        // so that we don't treat changing from undefined->null as a change.\n        function normalizeDateRanges(ranges) {\n          if (!ranges || !ranges.length) return null;\n          return ranges;\n        }\n\n        if (angular.isDefined(attr.disabledDates)) {\n          scope.$watch(attr.disabledDates, function(disabledRanges, previousValue) {\n            disabledRanges = normalizeDateRanges(disabledRanges);\n            previousValue = normalizeDateRanges(previousValue);\n\n            if (disabledRanges) {\n              datepicker.updateDisabledDates(disabledRanges);\n            }\n          });\n        }\n\n        function validateAgainstMinMaxDate(parsedDate) {\n          if (!angular.isDate(parsedDate)) return;\n          var isMinValid = isNaN(datepicker.$options.minDate) || parsedDate.getTime() >= datepicker.$options.minDate;\n          var isMaxValid = isNaN(datepicker.$options.maxDate) || parsedDate.getTime() <= datepicker.$options.maxDate;\n          var isValid = isMinValid && isMaxValid;\n          controller.$setValidity('date', isValid);\n          controller.$setValidity('min', isMinValid);\n          controller.$setValidity('max', isMaxValid);\n          // Only update the model when we have a valid date\n          if(isValid) controller.$dateValue = parsedDate;\n        }\n\n        // viewValue -> $parsers -> modelValue\n        controller.$parsers.unshift(function(viewValue) {\n          // console.warn('$parser(\"%s\"): viewValue=%o', element.attr('ng-model'), viewValue);\n          // Null values should correctly reset the model value & validity\n          if(!viewValue) {\n            controller.$setValidity('date', true);\n            // BREAKING CHANGE:\n            // return null (not undefined) when input value is empty, so angularjs 1.3\n            // ngModelController can go ahead and run validators, like ngRequired\n            return null;\n          }\n          var parsedDate = dateParser.parse(viewValue, controller.$dateValue);\n          if(!parsedDate || isNaN(parsedDate.getTime())) {\n            controller.$setValidity('date', false);\n            // return undefined, causes ngModelController to\n            // invalidate model value\n            return;\n          } else {\n            validateAgainstMinMaxDate(parsedDate);\n          }\n          if(options.dateType === 'string') {\n            return formatDate(parsedDate, options.modelDateFormat || options.dateFormat);\n          } else if(options.dateType === 'number') {\n            return controller.$dateValue.getTime();\n          } else if(options.dateType === 'unix') {\n            return controller.$dateValue.getTime() / 1000;\n          } else if(options.dateType === 'iso') {\n            return controller.$dateValue.toISOString();\n          } else {\n            return new Date(controller.$dateValue);\n          }\n        });\n\n        // modelValue -> $formatters -> viewValue\n        controller.$formatters.push(function(modelValue) {\n          // console.warn('$formatter(\"%s\"): modelValue=%o (%o)', element.attr('ng-model'), modelValue, typeof modelValue);\n          var date;\n          if(angular.isUndefined(modelValue) || modelValue === null) {\n            date = NaN;\n          } else if(angular.isDate(modelValue)) {\n            date = modelValue;\n          } else if(options.dateType === 'string') {\n            date = dateParser.parse(modelValue, null, options.modelDateFormat);\n          } else if(options.dateType === 'unix') {\n            date = new Date(modelValue * 1000);\n          } else {\n            date = new Date(modelValue);\n          }\n          // Setup default value?\n          // if(isNaN(date.getTime())) {\n          //   var today = new Date();\n          //   date = new Date(today.getFullYear(), today.getMonth(), today.getDate(), 0, 0, 0, 0);\n          // }\n          controller.$dateValue = date;\n          return getDateFormattedString();\n        });\n\n        // viewValue -> element\n        controller.$render = function() {\n          // console.warn('$render(\"%s\"): viewValue=%o', element.attr('ng-model'), controller.$viewValue);\n          element.val(getDateFormattedString());\n        };\n\n        function getDateFormattedString() {\n          return !controller.$dateValue || isNaN(controller.$dateValue.getTime()) ? '' : formatDate(controller.$dateValue, options.dateFormat);\n        }\n\n        // Garbage collection\n        scope.$on('$destroy', function() {\n          if(datepicker) datepicker.destroy();\n          options = null;\n          datepicker = null;\n        });\n\n      }\n    };\n\n  }])\n\n  .provider('datepickerViews', function() {\n\n    var defaults = this.defaults = {\n      dayFormat: 'dd',\n      daySplit: 7\n    };\n\n    // Split array into smaller arrays\n    function split(arr, size) {\n      var arrays = [];\n      while(arr.length > 0) {\n        arrays.push(arr.splice(0, size));\n      }\n      return arrays;\n    }\n\n    // Modulus operator\n    function mod(n, m) {\n      return ((n % m) + m) % m;\n    }\n\n    this.$get = [\"$dateFormatter\", \"$dateParser\", \"$sce\", function($dateFormatter, $dateParser, $sce) {\n\n      return function(picker) {\n\n        var scope = picker.$scope;\n        var options = picker.$options;\n\n        var lang = options.lang;\n        var formatDate = function(date, format) {\n          return $dateFormatter.formatDate(date, format, lang);\n        };\n        var dateParser = $dateParser({format: options.dateFormat, lang: lang, strict: options.strictFormat});\n\n        var weekDaysMin = $dateFormatter.weekdaysShort(lang);\n        var weekDaysLabels = weekDaysMin.slice(options.startWeek).concat(weekDaysMin.slice(0, options.startWeek));\n        var weekDaysLabelsHtml = $sce.trustAsHtml('<th class=\"dow text-center\">' + weekDaysLabels.join('</th><th class=\"dow text-center\">') + '</th>');\n\n        var startDate = picker.$date || (options.startDate ? dateParser.getDateForAttribute('startDate', options.startDate) : new Date());\n        var viewDate = {year: startDate.getFullYear(), month: startDate.getMonth(), date: startDate.getDate()};\n        var timezoneOffset = startDate.getTimezoneOffset() * 6e4;\n\n        var views = [{\n            format: options.dayFormat,\n            split: 7,\n            steps: { month: 1 },\n            update: function(date, force) {\n              if(!this.built || force || date.getFullYear() !== viewDate.year || date.getMonth() !== viewDate.month) {\n                angular.extend(viewDate, {year: picker.$date.getFullYear(), month: picker.$date.getMonth(), date: picker.$date.getDate()});\n                picker.$build();\n              } else if(date.getDate() !== viewDate.date) {\n                viewDate.date = picker.$date.getDate();\n                picker.$updateSelected();\n              }\n            },\n            build: function() {\n              var firstDayOfMonth = new Date(viewDate.year, viewDate.month, 1), firstDayOfMonthOffset = firstDayOfMonth.getTimezoneOffset();\n              var firstDate = new Date(+firstDayOfMonth - mod(firstDayOfMonth.getDay() - options.startWeek, 7) * 864e5), firstDateOffset = firstDate.getTimezoneOffset();\n              var today = new Date().toDateString();\n              // Handle daylight time switch\n              if(firstDateOffset !== firstDayOfMonthOffset) firstDate = new Date(+firstDate + (firstDateOffset - firstDayOfMonthOffset) * 60e3);\n              var days = [], day;\n              for(var i = 0; i < 42; i++) { // < 7 * 6\n                day = dateParser.daylightSavingAdjust(new Date(firstDate.getFullYear(), firstDate.getMonth(), firstDate.getDate() + i));\n                days.push({date: day, isToday: day.toDateString() === today, label: formatDate(day, this.format), selected: picker.$date && this.isSelected(day), muted: day.getMonth() !== viewDate.month, disabled: this.isDisabled(day)});\n              }\n              scope.title = formatDate(firstDayOfMonth, options.monthTitleFormat);\n              scope.showLabels = true;\n              scope.labels = weekDaysLabelsHtml;\n              scope.rows = split(days, this.split);\n              this.built = true;\n            },\n            isSelected: function(date) {\n              return picker.$date && date.getFullYear() === picker.$date.getFullYear() && date.getMonth() === picker.$date.getMonth() && date.getDate() === picker.$date.getDate();\n            },\n            isDisabled: function(date) {\n              var time = date.getTime();\n\n              // Disabled because of min/max date.\n              if (time < options.minDate || time > options.maxDate) return true;\n\n              // Disabled due to being a disabled day of the week\n              if (options.daysOfWeekDisabled.indexOf(date.getDay()) !== -1) return true;\n\n              // Disabled because of disabled date range.\n              if (options.disabledDateRanges) {\n                for (var i = 0; i < options.disabledDateRanges.length; i++) {\n                  if (time >= options.disabledDateRanges[i].start && time <= options.disabledDateRanges[i].end) {\n                    return true;\n                  }\n                }\n              }\n\n              return false;\n            },\n            onKeyDown: function(evt) {\n              if (!picker.$date) {\n                return;\n              }\n              var actualTime = picker.$date.getTime();\n              var newDate;\n\n              if(evt.keyCode === 37) newDate = new Date(actualTime - 1 * 864e5);\n              else if(evt.keyCode === 38) newDate = new Date(actualTime - 7 * 864e5);\n              else if(evt.keyCode === 39) newDate = new Date(actualTime + 1 * 864e5);\n              else if(evt.keyCode === 40) newDate = new Date(actualTime + 7 * 864e5);\n\n              if (!this.isDisabled(newDate)) picker.select(newDate, true);\n            }\n          }, {\n            name: 'month',\n            format: options.monthFormat,\n            split: 4,\n            steps: { year: 1 },\n            update: function(date, force) {\n              if(!this.built || date.getFullYear() !== viewDate.year) {\n                angular.extend(viewDate, {year: picker.$date.getFullYear(), month: picker.$date.getMonth(), date: picker.$date.getDate()});\n                picker.$build();\n              } else if(date.getMonth() !== viewDate.month) {\n                angular.extend(viewDate, {month: picker.$date.getMonth(), date: picker.$date.getDate()});\n                picker.$updateSelected();\n              }\n            },\n            build: function() {\n              var firstMonth = new Date(viewDate.year, 0, 1);\n              var months = [], month;\n              for (var i = 0; i < 12; i++) {\n                month = new Date(viewDate.year, i, 1);\n                months.push({date: month, label: formatDate(month, this.format), selected: picker.$isSelected(month), disabled: this.isDisabled(month)});\n              }\n              scope.title = formatDate(month, options.yearTitleFormat);\n              scope.showLabels = false;\n              scope.rows = split(months, this.split);\n              this.built = true;\n            },\n            isSelected: function(date) {\n              return picker.$date && date.getFullYear() === picker.$date.getFullYear() && date.getMonth() === picker.$date.getMonth();\n            },\n            isDisabled: function(date) {\n              var lastDate = +new Date(date.getFullYear(), date.getMonth() + 1, 0);\n              return lastDate < options.minDate || date.getTime() > options.maxDate;\n            },\n            onKeyDown: function(evt) {\n              if (!picker.$date) {\n                return;\n              }\n              var actualMonth = picker.$date.getMonth();\n              var newDate = new Date(picker.$date);\n\n              if(evt.keyCode === 37) newDate.setMonth(actualMonth - 1);\n              else if(evt.keyCode === 38) newDate.setMonth(actualMonth - 4);\n              else if(evt.keyCode === 39) newDate.setMonth(actualMonth + 1);\n              else if(evt.keyCode === 40) newDate.setMonth(actualMonth + 4);\n\n              if (!this.isDisabled(newDate)) picker.select(newDate, true);\n            }\n          }, {\n            name: 'year',\n            format: options.yearFormat,\n            split: 4,\n            steps: { year: 12 },\n            update: function(date, force) {\n              if(!this.built || force || parseInt(date.getFullYear()/20, 10) !== parseInt(viewDate.year/20, 10)) {\n                angular.extend(viewDate, {year: picker.$date.getFullYear(), month: picker.$date.getMonth(), date: picker.$date.getDate()});\n                picker.$build();\n              } else if(date.getFullYear() !== viewDate.year) {\n                angular.extend(viewDate, {year: picker.$date.getFullYear(), month: picker.$date.getMonth(), date: picker.$date.getDate()});\n                picker.$updateSelected();\n              }\n            },\n            build: function() {\n              var firstYear = viewDate.year - viewDate.year % (this.split * 3);\n              var years = [], year;\n              for (var i = 0; i < 12; i++) {\n                year = new Date(firstYear + i, 0, 1);\n                years.push({date: year, label: formatDate(year, this.format), selected: picker.$isSelected(year), disabled: this.isDisabled(year)});\n              }\n              scope.title = years[0].label + '-' + years[years.length - 1].label;\n              scope.showLabels = false;\n              scope.rows = split(years, this.split);\n              this.built = true;\n            },\n            isSelected: function(date) {\n              return picker.$date && date.getFullYear() === picker.$date.getFullYear();\n            },\n            isDisabled: function(date) {\n              var lastDate = +new Date(date.getFullYear() + 1, 0, 0);\n              return lastDate < options.minDate || date.getTime() > options.maxDate;\n            },\n            onKeyDown: function(evt) {\n              if (!picker.$date) {\n                return;\n              }\n              var actualYear = picker.$date.getFullYear(),\n                  newDate = new Date(picker.$date);\n\n              if(evt.keyCode === 37) newDate.setYear(actualYear - 1);\n              else if(evt.keyCode === 38) newDate.setYear(actualYear - 4);\n              else if(evt.keyCode === 39) newDate.setYear(actualYear + 1);\n              else if(evt.keyCode === 40) newDate.setYear(actualYear + 4);\n\n              if (!this.isDisabled(newDate)) picker.select(newDate, true);\n            }\n          }];\n\n        return {\n          views: options.minView ? Array.prototype.slice.call(views, options.minView) : views,\n          viewDate: viewDate\n        };\n\n      };\n\n    }];\n\n  });\n\n// Source: dropdown.js\nangular.module('mgcrea.ngStrap.dropdown', ['mgcrea.ngStrap.tooltip'])\n\n  .provider('$dropdown', function() {\n\n    var defaults = this.defaults = {\n      animation: 'am-fade',\n      prefixClass: 'dropdown',\n      placement: 'bottom-left',\n      template: 'dropdown/dropdown.tpl.html',\n      trigger: 'click',\n      container: false,\n      keyboard: true,\n      html: false,\n      delay: 0\n    };\n\n    this.$get = [\"$window\", \"$rootScope\", \"$tooltip\", \"$timeout\", function($window, $rootScope, $tooltip, $timeout) {\n\n      var bodyEl = angular.element($window.document.body);\n      var matchesSelector = Element.prototype.matchesSelector || Element.prototype.webkitMatchesSelector || Element.prototype.mozMatchesSelector || Element.prototype.msMatchesSelector || Element.prototype.oMatchesSelector;\n\n      function DropdownFactory(element, config) {\n\n        var $dropdown = {};\n\n        // Common vars\n        var options = angular.extend({}, defaults, config);\n        var scope = $dropdown.$scope = options.scope && options.scope.$new() || $rootScope.$new();\n\n        $dropdown = $tooltip(element, options);\n        var parentEl = element.parent();\n\n        // Protected methods\n\n        $dropdown.$onKeyDown = function(evt) {\n          if (!/(38|40)/.test(evt.keyCode)) return;\n          evt.preventDefault();\n          evt.stopPropagation();\n\n          // Retrieve focused index\n          var items = angular.element($dropdown.$element[0].querySelectorAll('li:not(.divider) a'));\n          if(!items.length) return;\n          var index;\n          angular.forEach(items, function(el, i) {\n            if(matchesSelector && matchesSelector.call(el, ':focus')) index = i;\n          });\n\n          // Navigate with keyboard\n          if(evt.keyCode === 38 && index > 0) index--;\n          else if(evt.keyCode === 40 && index < items.length - 1) index++;\n          else if(angular.isUndefined(index)) index = 0;\n          items.eq(index)[0].focus();\n\n        };\n\n        // Overrides\n\n        var show = $dropdown.show;\n        $dropdown.show = function() {\n          show();\n          // use timeout to hookup the events to prevent\n          // event bubbling from being processed imediately.\n          $timeout(function() {\n            options.keyboard && $dropdown.$element.on('keydown', $dropdown.$onKeyDown);\n            bodyEl.on('click', onBodyClick);\n          }, 0, false);\n          parentEl.hasClass('dropdown') && parentEl.addClass('open');\n        };\n\n        var hide = $dropdown.hide;\n        $dropdown.hide = function() {\n          if(!$dropdown.$isShown) return;\n          options.keyboard && $dropdown.$element.off('keydown', $dropdown.$onKeyDown);\n          bodyEl.off('click', onBodyClick);\n          parentEl.hasClass('dropdown') && parentEl.removeClass('open');\n          hide();\n        };\n\n        var destroy = $dropdown.destroy;\n        $dropdown.destroy = function() {\n          bodyEl.off('click', onBodyClick);\n          destroy();\n        };\n\n        // Private functions\n\n        function onBodyClick(evt) {\n          if(evt.target === element[0]) return;\n          return evt.target !== element[0] && $dropdown.hide();\n        }\n\n        return $dropdown;\n\n      }\n\n      return DropdownFactory;\n\n    }];\n\n  })\n\n  .directive('bsDropdown', [\"$window\", \"$sce\", \"$dropdown\", function($window, $sce, $dropdown) {\n\n    return {\n      restrict: 'EAC',\n      scope: true,\n      link: function postLink(scope, element, attr, transclusion) {\n\n        // Directive options\n        var options = {scope: scope};\n        angular.forEach(['placement', 'container', 'delay', 'trigger', 'keyboard', 'html', 'animation', 'template', 'id'], function(key) {\n          if(angular.isDefined(attr[key])) options[key] = attr[key];\n        });\n\n        // Support scope as an object\n        attr.bsDropdown && scope.$watch(attr.bsDropdown, function(newValue, oldValue) {\n          scope.content = newValue;\n        }, true);\n\n        // Visibility binding support\n        attr.bsShow && scope.$watch(attr.bsShow, function(newValue, oldValue) {\n          if(!dropdown || !angular.isDefined(newValue)) return;\n          if(angular.isString(newValue)) newValue = !!newValue.match(/true|,?(dropdown),?/i);\n          newValue === true ? dropdown.show() : dropdown.hide();\n        });\n\n        // Initialize dropdown\n        var dropdown = $dropdown(element, options);\n\n        // Garbage collection\n        scope.$on('$destroy', function() {\n          if (dropdown) dropdown.destroy();\n          options = null;\n          dropdown = null;\n        });\n\n      }\n    };\n\n  }]);\n\n// Source: date-formatter.js\nangular.module('mgcrea.ngStrap.helpers.dateFormatter', [])\n\n  .service('$dateFormatter', [\"$locale\", \"dateFilter\", function($locale, dateFilter) {\n\n    // The unused `lang` arguments are on purpose. The default implementation does not\n    // use them and it always uses the locale loaded into the `$locale` service.\n    // Custom implementations might use it, thus allowing different directives to\n    // have different languages.\n\n    this.getDefaultLocale = function() {\n      return $locale.id;\n    };\n\n    // Format is either a data format name, e.g. \"shortTime\" or \"fullDate\", or a date format\n    // Return either the corresponding date format or the given date format.\n    this.getDatetimeFormat = function(format, lang) {\n      return $locale.DATETIME_FORMATS[format] || format;\n    };\n\n    this.weekdaysShort = function(lang) {\n      return $locale.DATETIME_FORMATS.SHORTDAY;\n    };\n\n    function splitTimeFormat(format) {\n      return /(h+)([:\\.])?(m+)[ ]?(a?)/i.exec(format).slice(1);\n    }\n\n    // h:mm a => h\n    this.hoursFormat = function(timeFormat) {\n      return splitTimeFormat(timeFormat)[0];\n    };\n\n    // h:mm a => mm\n    this.minutesFormat = function(timeFormat) {\n      return splitTimeFormat(timeFormat)[2];\n    };\n\n    // h:mm a => :\n    this.timeSeparator = function(timeFormat) {\n      return splitTimeFormat(timeFormat)[1];\n    };\n\n    // h:mm a => true, H.mm => false\n    this.showAM = function(timeFormat) {\n      return !!splitTimeFormat(timeFormat)[3];\n    };\n\n    this.formatDate = function(date, format, lang){\n      return dateFilter(date, format);\n    };\n\n  }]);\n\n// Source: date-parser.js\nangular.module('mgcrea.ngStrap.helpers.dateParser', [])\n\n.provider('$dateParser', [\"$localeProvider\", function($localeProvider) {\n\n  // define a custom ParseDate object to use instead of native Date\n  // to avoid date values wrapping when setting date component values\n  function ParseDate() {\n    this.year = 1970;\n    this.month = 0;\n    this.day = 1;\n    this.hours = 0;\n    this.minutes = 0;\n    this.seconds = 0;\n    this.milliseconds = 0;\n  }\n\n  ParseDate.prototype.setMilliseconds = function(value) { this.milliseconds = value; };\n  ParseDate.prototype.setSeconds = function(value) { this.seconds = value; };\n  ParseDate.prototype.setMinutes = function(value) { this.minutes = value; };\n  ParseDate.prototype.setHours = function(value) { this.hours = value; };\n  ParseDate.prototype.getHours = function() { return this.hours; };\n  ParseDate.prototype.setDate = function(value) { this.day = value; };\n  ParseDate.prototype.setMonth = function(value) { this.month = value; };\n  ParseDate.prototype.setFullYear = function(value) { this.year = value; };\n  ParseDate.prototype.fromDate = function(value) {\n    this.year = value.getFullYear();\n    this.month = value.getMonth();\n    this.day = value.getDate();\n    this.hours = value.getHours();\n    this.minutes = value.getMinutes();\n    this.seconds = value.getSeconds();\n    this.milliseconds = value.getMilliseconds();\n    return this;\n  };\n\n  ParseDate.prototype.toDate = function() {\n    return new Date(this.year, this.month, this.day, this.hours, this.minutes, this.seconds, this.milliseconds);\n  };\n\n  var proto = ParseDate.prototype;\n\n  function noop() {\n  }\n\n  function isNumeric(n) {\n    return !isNaN(parseFloat(n)) && isFinite(n);\n  }\n\n  function indexOfCaseInsensitive(array, value) {\n    var len = array.length, str=value.toString().toLowerCase();\n    for (var i=0; i<len; i++) {\n      if (array[i].toLowerCase() === str) { return i; }\n    }\n    return -1; // Return -1 per the \"Array.indexOf()\" method.\n  }\n\n  var defaults = this.defaults = {\n    format: 'shortDate',\n    strict: false\n  };\n\n  this.$get = [\"$locale\", \"dateFilter\", function($locale, dateFilter) {\n\n    var DateParserFactory = function(config) {\n\n      var options = angular.extend({}, defaults, config);\n\n      var $dateParser = {};\n\n      var regExpMap = {\n        'sss'   : '[0-9]{3}',\n        'ss'    : '[0-5][0-9]',\n        's'     : options.strict ? '[1-5]?[0-9]' : '[0-9]|[0-5][0-9]',\n        'mm'    : '[0-5][0-9]',\n        'm'     : options.strict ? '[1-5]?[0-9]' : '[0-9]|[0-5][0-9]',\n        'HH'    : '[01][0-9]|2[0-3]',\n        'H'     : options.strict ? '1?[0-9]|2[0-3]' : '[01]?[0-9]|2[0-3]',\n        'hh'    : '[0][1-9]|[1][012]',\n        'h'     : options.strict ? '[1-9]|1[012]' : '0?[1-9]|1[012]',\n        'a'     : 'AM|PM',\n        'EEEE'  : $locale.DATETIME_FORMATS.DAY.join('|'),\n        'EEE'   : $locale.DATETIME_FORMATS.SHORTDAY.join('|'),\n        'dd'    : '0[1-9]|[12][0-9]|3[01]',\n        'd'     : options.strict ? '[1-9]|[1-2][0-9]|3[01]' : '0?[1-9]|[1-2][0-9]|3[01]',\n        'MMMM'  : $locale.DATETIME_FORMATS.MONTH.join('|'),\n        'MMM'   : $locale.DATETIME_FORMATS.SHORTMONTH.join('|'),\n        'MM'    : '0[1-9]|1[012]',\n        'M'     : options.strict ? '[1-9]|1[012]' : '0?[1-9]|1[012]',\n        'yyyy'  : '[1]{1}[0-9]{3}|[2]{1}[0-9]{3}',\n        'yy'    : '[0-9]{2}',\n        'y'     : options.strict ? '-?(0|[1-9][0-9]{0,3})' : '-?0*[0-9]{1,4}',\n      };\n\n      var setFnMap = {\n        'sss'   : proto.setMilliseconds,\n        'ss'    : proto.setSeconds,\n        's'     : proto.setSeconds,\n        'mm'    : proto.setMinutes,\n        'm'     : proto.setMinutes,\n        'HH'    : proto.setHours,\n        'H'     : proto.setHours,\n        'hh'    : proto.setHours,\n        'h'     : proto.setHours,\n        'EEEE'  : noop,\n        'EEE'   : noop,\n        'dd'    : proto.setDate,\n        'd'     : proto.setDate,\n        'a'     : function(value) { var hours = this.getHours() % 12; return this.setHours(value.match(/pm/i) ? hours + 12 : hours); },\n        'MMMM'  : function(value) { return this.setMonth(indexOfCaseInsensitive($locale.DATETIME_FORMATS.MONTH, value)); },\n        'MMM'   : function(value) { return this.setMonth(indexOfCaseInsensitive($locale.DATETIME_FORMATS.SHORTMONTH, value)); },\n        'MM'    : function(value) { return this.setMonth(1 * value - 1); },\n        'M'     : function(value) { return this.setMonth(1 * value - 1); },\n        'yyyy'  : proto.setFullYear,\n        'yy'    : function(value) { return this.setFullYear(2000 + 1 * value); },\n        'y'     : proto.setFullYear\n      };\n\n      var regex, setMap;\n\n      $dateParser.init = function() {\n        $dateParser.$format = $locale.DATETIME_FORMATS[options.format] || options.format;\n        regex = regExpForFormat($dateParser.$format);\n        setMap = setMapForFormat($dateParser.$format);\n      };\n\n      $dateParser.isValid = function(date) {\n        if(angular.isDate(date)) return !isNaN(date.getTime());\n        return regex.test(date);\n      };\n\n      $dateParser.parse = function(value, baseDate, format) {\n        // check for date format special names\n        if(format) format = $locale.DATETIME_FORMATS[format] || format;\n        if(angular.isDate(value)) value = dateFilter(value, format || $dateParser.$format);\n        var formatRegex = format ? regExpForFormat(format) : regex;\n        var formatSetMap = format ? setMapForFormat(format) : setMap;\n        var matches = formatRegex.exec(value);\n        if(!matches) return false;\n        // use custom ParseDate object to set parsed values\n        var date = baseDate && !isNaN(baseDate.getTime()) ? new ParseDate().fromDate(baseDate) : new ParseDate().fromDate(new Date(1970, 0, 1, 0));\n        for(var i = 0; i < matches.length - 1; i++) {\n          formatSetMap[i] && formatSetMap[i].call(date, matches[i+1]);\n        }\n        // convert back to native Date object\n        var newDate = date.toDate();\n\n        // check new native Date object for day values overflow\n        if (parseInt(date.day, 10) !== newDate.getDate()) {\n          return false;\n        }\n\n        return newDate;\n      };\n\n      $dateParser.getDateForAttribute = function(key, value) {\n        var date;\n\n        if(value === 'today') {\n          var today = new Date();\n          date = new Date(today.getFullYear(), today.getMonth(), today.getDate() + (key === 'maxDate' ? 1 : 0), 0, 0, 0, (key === 'minDate' ? 0 : -1));\n        } else if(angular.isString(value) && value.match(/^\".+\"$/)) { // Support {{ dateObj }}\n          date = new Date(value.substr(1, value.length - 2));\n        } else if(isNumeric(value)) {\n          date = new Date(parseInt(value, 10));\n        } else if (angular.isString(value) && 0 === value.length) { // Reset date\n          date = key === 'minDate' ? -Infinity : +Infinity;\n        } else {\n          date = new Date(value);\n        }\n\n        return date;\n      };\n\n      $dateParser.getTimeForAttribute = function(key, value) {\n        var time;\n\n        if(value === 'now') {\n          time = new Date().setFullYear(1970, 0, 1);\n        } else if(angular.isString(value) && value.match(/^\".+\"$/)) {\n          time = new Date(value.substr(1, value.length - 2)).setFullYear(1970, 0, 1);\n        } else if(isNumeric(value)) {\n          time = new Date(parseInt(value, 10)).setFullYear(1970, 0, 1);\n        } else if (angular.isString(value) && 0 === value.length) { // Reset time\n          time = key === 'minTime' ? -Infinity : +Infinity;\n        } else {\n          time = $dateParser.parse(value, new Date(1970, 0, 1, 0));\n        }\n\n        return time;\n      };\n\n      /* Handle switch to/from daylight saving.\n      * Hours may be non-zero on daylight saving cut-over:\n      * > 12 when midnight changeover, but then cannot generate\n      * midnight datetime, so jump to 1AM, otherwise reset.\n      * @param  date  (Date) the date to check\n      * @return  (Date) the corrected date\n      *\n      * __ copied from jquery ui datepicker __\n      */\n      $dateParser.daylightSavingAdjust = function(date) {\n        if (!date) {\n          return null;\n        }\n        date.setHours(date.getHours() > 12 ? date.getHours() + 2 : 0);\n        return date;\n      };\n\n      // Private functions\n\n      function setMapForFormat(format) {\n        var keys = Object.keys(setFnMap), i;\n        var map = [], sortedMap = [];\n        // Map to setFn\n        var clonedFormat = format;\n        for(i = 0; i < keys.length; i++) {\n          if(format.split(keys[i]).length > 1) {\n            var index = clonedFormat.search(keys[i]);\n            format = format.split(keys[i]).join('');\n            if(setFnMap[keys[i]]) {\n              map[index] = setFnMap[keys[i]];\n            }\n          }\n        }\n        // Sort result map\n        angular.forEach(map, function(v) {\n          // conditional required since angular.forEach broke around v1.2.21\n          // related pr: https://github.com/angular/angular.js/pull/8525\n          if(v) sortedMap.push(v);\n        });\n        return sortedMap;\n      }\n\n      function escapeReservedSymbols(text) {\n        return text.replace(/\\//g, '[\\\\/]').replace('/-/g', '[-]').replace(/\\./g, '[.]').replace(/\\\\s/g, '[\\\\s]');\n      }\n\n      function regExpForFormat(format) {\n        var keys = Object.keys(regExpMap), i;\n\n        var re = format;\n        // Abstract replaces to avoid collisions\n        for(i = 0; i < keys.length; i++) {\n          re = re.split(keys[i]).join('${' + i + '}');\n        }\n        // Replace abstracted values\n        for(i = 0; i < keys.length; i++) {\n          re = re.split('${' + i + '}').join('(' + regExpMap[keys[i]] + ')');\n        }\n        format = escapeReservedSymbols(format);\n\n        return new RegExp('^' + re + '$', ['i']);\n      }\n\n      $dateParser.init();\n      return $dateParser;\n\n    };\n\n    return DateParserFactory;\n\n  }];\n\n}]);\n\n// Source: debounce.js\nangular.module('mgcrea.ngStrap.helpers.debounce', [])\n\n// @source jashkenas/underscore\n// @url https://github.com/jashkenas/underscore/blob/1.5.2/underscore.js#L693\n.factory('debounce', [\"$timeout\", function($timeout) {\n  return function(func, wait, immediate) {\n    var timeout = null;\n    return function() {\n      var context = this,\n        args = arguments,\n        callNow = immediate && !timeout;\n      if(timeout) {\n        $timeout.cancel(timeout);\n      }\n      timeout = $timeout(function later() {\n        timeout = null;\n        if(!immediate) {\n          func.apply(context, args);\n        }\n      }, wait, false);\n      if(callNow) {\n        func.apply(context, args);\n      }\n      return timeout;\n    };\n  };\n}])\n\n\n// @source jashkenas/underscore\n// @url https://github.com/jashkenas/underscore/blob/1.5.2/underscore.js#L661\n.factory('throttle', [\"$timeout\", function($timeout) {\n  return function(func, wait, options) {\n    var timeout = null;\n    options || (options = {});\n    return function() {\n      var context = this,\n        args = arguments;\n      if(!timeout) {\n        if(options.leading !== false) {\n          func.apply(context, args);\n        }\n        timeout = $timeout(function later() {\n          timeout = null;\n          if(options.trailing !== false) {\n            func.apply(context, args);\n          }\n        }, wait, false);\n      }\n    };\n  };\n}]);\n\n// Source: dimensions.js\nangular.module('mgcrea.ngStrap.helpers.dimensions', [])\n\n  .factory('dimensions', [\"$document\", \"$window\", function($document, $window) {\n\n    var jqLite = angular.element;\n    var fn = {};\n\n    /**\n     * Test the element nodeName\n     * @param element\n     * @param name\n     */\n    var nodeName = fn.nodeName = function(element, name) {\n      return element.nodeName && element.nodeName.toLowerCase() === name.toLowerCase();\n    };\n\n    /**\n     * Returns the element computed style\n     * @param element\n     * @param prop\n     * @param extra\n     */\n    fn.css = function(element, prop, extra) {\n      var value;\n      if (element.currentStyle) { //IE\n        value = element.currentStyle[prop];\n      } else if (window.getComputedStyle) {\n        value = window.getComputedStyle(element)[prop];\n      } else {\n        value = element.style[prop];\n      }\n      return extra === true ? parseFloat(value) || 0 : value;\n    };\n\n    /**\n     * Provides read-only equivalent of jQuery's offset function:\n     * @required-by bootstrap-tooltip, bootstrap-affix\n     * @url http://api.jquery.com/offset/\n     * @param element\n     */\n    fn.offset = function(element) {\n      var boxRect = element.getBoundingClientRect();\n      var docElement = element.ownerDocument;\n      return {\n        width: boxRect.width || element.offsetWidth,\n        height: boxRect.height || element.offsetHeight,\n        top: boxRect.top + (window.pageYOffset || docElement.documentElement.scrollTop) - (docElement.documentElement.clientTop || 0),\n        left: boxRect.left + (window.pageXOffset || docElement.documentElement.scrollLeft) - (docElement.documentElement.clientLeft || 0)\n      };\n    };\n\n    /**\n     * Provides read-only equivalent of jQuery's position function\n     * @required-by bootstrap-tooltip, bootstrap-affix\n     * @url http://api.jquery.com/offset/\n     * @param element\n     */\n    fn.position = function(element) {\n\n      var offsetParentRect = {top: 0, left: 0},\n          offsetParentElement,\n          offset;\n\n      // Fixed elements are offset from window (parentOffset = {top:0, left: 0}, because it is it's only offset parent\n      if (fn.css(element, 'position') === 'fixed') {\n\n        // We assume that getBoundingClientRect is available when computed position is fixed\n        offset = element.getBoundingClientRect();\n\n      } else {\n\n        // Get *real* offsetParentElement\n        offsetParentElement = offsetParent(element);\n\n        // Get correct offsets\n        offset = fn.offset(element);\n        if (!nodeName(offsetParentElement, 'html')) {\n          offsetParentRect = fn.offset(offsetParentElement);\n        }\n\n        // Add offsetParent borders\n        offsetParentRect.top += fn.css(offsetParentElement, 'borderTopWidth', true);\n        offsetParentRect.left += fn.css(offsetParentElement, 'borderLeftWidth', true);\n      }\n\n      // Subtract parent offsets and element margins\n      return {\n        width: element.offsetWidth,\n        height: element.offsetHeight,\n        top: offset.top - offsetParentRect.top - fn.css(element, 'marginTop', true),\n        left: offset.left - offsetParentRect.left - fn.css(element, 'marginLeft', true)\n      };\n\n    };\n\n    /**\n     * Returns the closest, non-statically positioned offsetParent of a given element\n     * @required-by fn.position\n     * @param element\n     */\n    var offsetParent = function offsetParentElement(element) {\n      var docElement = element.ownerDocument;\n      var offsetParent = element.offsetParent || docElement;\n      if(nodeName(offsetParent, '#document')) return docElement.documentElement;\n      while(offsetParent && !nodeName(offsetParent, 'html') && fn.css(offsetParent, 'position') === 'static') {\n        offsetParent = offsetParent.offsetParent;\n      }\n      return offsetParent || docElement.documentElement;\n    };\n\n    /**\n     * Provides equivalent of jQuery's height function\n     * @required-by bootstrap-affix\n     * @url http://api.jquery.com/height/\n     * @param element\n     * @param outer\n     */\n    fn.height = function(element, outer) {\n      var value = element.offsetHeight;\n      if(outer) {\n        value += fn.css(element, 'marginTop', true) + fn.css(element, 'marginBottom', true);\n      } else {\n        value -= fn.css(element, 'paddingTop', true) + fn.css(element, 'paddingBottom', true) + fn.css(element, 'borderTopWidth', true) + fn.css(element, 'borderBottomWidth', true);\n      }\n      return value;\n    };\n\n    /**\n     * Provides equivalent of jQuery's width function\n     * @required-by bootstrap-affix\n     * @url http://api.jquery.com/width/\n     * @param element\n     * @param outer\n     */\n    fn.width = function(element, outer) {\n      var value = element.offsetWidth;\n      if(outer) {\n        value += fn.css(element, 'marginLeft', true) + fn.css(element, 'marginRight', true);\n      } else {\n        value -= fn.css(element, 'paddingLeft', true) + fn.css(element, 'paddingRight', true) + fn.css(element, 'borderLeftWidth', true) + fn.css(element, 'borderRightWidth', true);\n      }\n      return value;\n    };\n\n    return fn;\n\n  }]);\n\n// Source: parse-options.js\nangular.module('mgcrea.ngStrap.helpers.parseOptions', [])\n\n  .provider('$parseOptions', function() {\n\n    var defaults = this.defaults = {\n      regexp: /^\\s*(.*?)(?:\\s+as\\s+(.*?))?(?:\\s+group\\s+by\\s+(.*))?\\s+for\\s+(?:([\\$\\w][\\$\\w]*)|(?:\\(\\s*([\\$\\w][\\$\\w]*)\\s*,\\s*([\\$\\w][\\$\\w]*)\\s*\\)))\\s+in\\s+(.*?)(?:\\s+track\\s+by\\s+(.*?))?$/\n    };\n\n    this.$get = [\"$parse\", \"$q\", function($parse, $q) {\n\n      function ParseOptionsFactory(attr, config) {\n\n        var $parseOptions = {};\n\n        // Common vars\n        var options = angular.extend({}, defaults, config);\n        $parseOptions.$values = [];\n\n        // Private vars\n        var match, displayFn, valueName, keyName, groupByFn, valueFn, valuesFn;\n\n        $parseOptions.init = function() {\n          $parseOptions.$match = match = attr.match(options.regexp);\n          displayFn = $parse(match[2] || match[1]),\n          valueName = match[4] || match[6],\n          keyName = match[5],\n          groupByFn = $parse(match[3] || ''),\n          valueFn = $parse(match[2] ? match[1] : valueName),\n          valuesFn = $parse(match[7]);\n        };\n\n        $parseOptions.valuesFn = function(scope, controller) {\n          return $q.when(valuesFn(scope, controller))\n          .then(function(values) {\n            $parseOptions.$values = values ? parseValues(values, scope) : {};\n            return $parseOptions.$values;\n          });\n        };\n\n        $parseOptions.displayValue = function(modelValue) {\n          var scope = {};\n          scope[valueName] = modelValue;\n          return displayFn(scope);\n        };\n\n        // Private functions\n\n        function parseValues(values, scope) {\n          return values.map(function(match, index) {\n            var locals = {}, label, value;\n            locals[valueName] = match;\n            label = displayFn(scope, locals);\n            value = valueFn(scope, locals);\n            return {label: label, value: value, index: index};\n          });\n        }\n\n        $parseOptions.init();\n        return $parseOptions;\n\n      }\n\n      return ParseOptionsFactory;\n\n    }];\n\n  });\n\n// Source: raf.js\n(angular.version.minor < 3 && angular.version.dot < 14) && angular.module('ng')\n\n.factory('$$rAF', [\"$window\", \"$timeout\", function($window, $timeout) {\n\n  var requestAnimationFrame = $window.requestAnimationFrame ||\n                              $window.webkitRequestAnimationFrame ||\n                              $window.mozRequestAnimationFrame;\n\n  var cancelAnimationFrame = $window.cancelAnimationFrame ||\n                             $window.webkitCancelAnimationFrame ||\n                             $window.mozCancelAnimationFrame ||\n                             $window.webkitCancelRequestAnimationFrame;\n\n  var rafSupported = !!requestAnimationFrame;\n  var raf = rafSupported ?\n    function(fn) {\n      var id = requestAnimationFrame(fn);\n      return function() {\n        cancelAnimationFrame(id);\n      };\n    } :\n    function(fn) {\n      var timer = $timeout(fn, 16.66, false); // 1000 / 60 = 16.666\n      return function() {\n        $timeout.cancel(timer);\n      };\n    };\n\n  raf.supported = rafSupported;\n\n  return raf;\n\n}]);\n\n// .factory('$$animateReflow', function($$rAF, $document) {\n\n//   var bodyEl = $document[0].body;\n\n//   return function(fn) {\n//     //the returned function acts as the cancellation function\n//     return $$rAF(function() {\n//       //the line below will force the browser to perform a repaint\n//       //so that all the animated elements within the animation frame\n//       //will be properly updated and drawn on screen. This is\n//       //required to perform multi-class CSS based animations with\n//       //Firefox. DO NOT REMOVE THIS LINE.\n//       var a = bodyEl.offsetWidth + 1;\n//       fn();\n//     });\n//   };\n\n// });\n\n// Source: modal.js\nangular.module('mgcrea.ngStrap.modal', ['mgcrea.ngStrap.helpers.dimensions'])\n\n  .provider('$modal', function() {\n\n    var defaults = this.defaults = {\n      animation: 'am-fade',\n      backdropAnimation: 'am-fade',\n      prefixClass: 'modal',\n      prefixEvent: 'modal',\n      placement: 'top',\n      template: 'modal/modal.tpl.html',\n      contentTemplate: false,\n      container: false,\n      element: null,\n      backdrop: true,\n      keyboard: true,\n      html: false,\n      show: true\n    };\n\n    this.$get = [\"$window\", \"$rootScope\", \"$compile\", \"$q\", \"$templateCache\", \"$http\", \"$animate\", \"$timeout\", \"$sce\", \"dimensions\", function($window, $rootScope, $compile, $q, $templateCache, $http, $animate, $timeout, $sce, dimensions) {\n\n      var forEach = angular.forEach;\n      var trim = String.prototype.trim;\n      var requestAnimationFrame = $window.requestAnimationFrame || $window.setTimeout;\n      var bodyElement = angular.element($window.document.body);\n      var htmlReplaceRegExp = /ng-bind=\"/ig;\n\n      function ModalFactory(config) {\n\n        var $modal = {};\n\n        // Common vars\n        var options = $modal.$options = angular.extend({}, defaults, config);\n        $modal.$promise = fetchTemplate(options.template);\n        var scope = $modal.$scope = options.scope && options.scope.$new() || $rootScope.$new();\n        if(!options.element && !options.container) {\n          options.container = 'body';\n        }\n\n        // store $id to identify the triggering element in events\n        // give priority to options.id, otherwise, try to use\n        // element id if defined\n        $modal.$id = options.id || options.element && options.element.attr('id') || '';\n\n        // Support scope as string options\n        forEach(['title', 'content'], function(key) {\n          if(options[key]) scope[key] = $sce.trustAsHtml(options[key]);\n        });\n\n        // Provide scope helpers\n        scope.$hide = function() {\n          scope.$$postDigest(function() {\n            $modal.hide();\n          });\n        };\n        scope.$show = function() {\n          scope.$$postDigest(function() {\n            $modal.show();\n          });\n        };\n        scope.$toggle = function() {\n          scope.$$postDigest(function() {\n            $modal.toggle();\n          });\n        };\n        // Publish isShown as a protected var on scope\n        $modal.$isShown = scope.$isShown = false;\n\n        // Support contentTemplate option\n        if(options.contentTemplate) {\n          $modal.$promise = $modal.$promise.then(function(template) {\n            var templateEl = angular.element(template);\n            return fetchTemplate(options.contentTemplate)\n            .then(function(contentTemplate) {\n              var contentEl = findElement('[ng-bind=\"content\"]', templateEl[0]).removeAttr('ng-bind').html(contentTemplate);\n              // Drop the default footer as you probably don't want it if you use a custom contentTemplate\n              if(!config.template) contentEl.next().remove();\n              return templateEl[0].outerHTML;\n            });\n          });\n        }\n\n        // Fetch, compile then initialize modal\n        var modalLinker, modalElement;\n        var backdropElement = angular.element('<div class=\"' + options.prefixClass + '-backdrop\"/>');\n        $modal.$promise.then(function(template) {\n          if(angular.isObject(template)) template = template.data;\n          if(options.html) template = template.replace(htmlReplaceRegExp, 'ng-bind-html=\"');\n          template = trim.apply(template);\n          modalLinker = $compile(template);\n          $modal.init();\n        });\n\n        $modal.init = function() {\n\n          // Options: show\n          if(options.show) {\n            scope.$$postDigest(function() {\n              $modal.show();\n            });\n          }\n\n        };\n\n        $modal.destroy = function() {\n\n          // Remove element\n          if(modalElement) {\n            modalElement.remove();\n            modalElement = null;\n          }\n          if(backdropElement) {\n            backdropElement.remove();\n            backdropElement = null;\n          }\n\n          // Destroy scope\n          scope.$destroy();\n\n        };\n\n        $modal.show = function() {\n          if($modal.$isShown) return;\n\n          if(scope.$emit(options.prefixEvent + '.show.before', $modal).defaultPrevented) {\n            return;\n          }\n          var parent, after;\n          if(angular.isElement(options.container)) {\n            parent = options.container;\n            after = options.container[0].lastChild ? angular.element(options.container[0].lastChild) : null;\n          } else {\n            if (options.container) {\n              parent = findElement(options.container);\n              after = parent[0].lastChild ? angular.element(parent[0].lastChild) : null;\n            } else {\n              parent = null;\n              after = options.element;\n            }\n          }\n\n          // Fetch a cloned element linked from template\n          modalElement = $modal.$element = modalLinker(scope, function(clonedElement, scope) {});\n\n          // Set the initial positioning.\n          modalElement.css({display: 'block'}).addClass(options.placement);\n\n          // Options: animation\n          if(options.animation) {\n            if(options.backdrop) {\n              backdropElement.addClass(options.backdropAnimation);\n            }\n            modalElement.addClass(options.animation);\n          }\n\n          if(options.backdrop) {\n            $animate.enter(backdropElement, bodyElement, null);\n          }\n          // Support v1.3+ $animate\n          // https://github.com/angular/angular.js/commit/bf0f5502b1bbfddc5cdd2f138efd9188b8c652a9\n          var promise = $animate.enter(modalElement, parent, after, enterAnimateCallback);\n          if(promise && promise.then) promise.then(enterAnimateCallback);\n\n          $modal.$isShown = scope.$isShown = true;\n          safeDigest(scope);\n          // Focus once the enter-animation has started\n          // Weird PhantomJS bug hack\n          var el = modalElement[0];\n          requestAnimationFrame(function() {\n            el.focus();\n          });\n\n          bodyElement.addClass(options.prefixClass + '-open');\n          if(options.animation) {\n            bodyElement.addClass(options.prefixClass + '-with-' + options.animation);\n          }\n\n          // Bind events\n          if(options.backdrop) {\n            modalElement.on('click', hideOnBackdropClick);\n            backdropElement.on('click', hideOnBackdropClick);\n            backdropElement.on('wheel', preventEventDefault);\n          }\n          if(options.keyboard) {\n            modalElement.on('keyup', $modal.$onKeyUp);\n          }\n        };\n\n        function enterAnimateCallback() {\n          scope.$emit(options.prefixEvent + '.show', $modal);\n        }\n\n        $modal.hide = function() {\n          if(!$modal.$isShown) return;\n\n          if(scope.$emit(options.prefixEvent + '.hide.before', $modal).defaultPrevented) {\n            return;\n          }\n          var promise = $animate.leave(modalElement, leaveAnimateCallback);\n          // Support v1.3+ $animate\n          // https://github.com/angular/angular.js/commit/bf0f5502b1bbfddc5cdd2f138efd9188b8c652a9\n          if(promise && promise.then) promise.then(leaveAnimateCallback);\n\n          if(options.backdrop) {\n            $animate.leave(backdropElement);\n          }\n          $modal.$isShown = scope.$isShown = false;\n          safeDigest(scope);\n\n          // Unbind events\n          if(options.backdrop) {\n            modalElement.off('click', hideOnBackdropClick);\n            backdropElement.off('click', hideOnBackdropClick);\n            backdropElement.off('wheel', preventEventDefault);\n          }\n          if(options.keyboard) {\n            modalElement.off('keyup', $modal.$onKeyUp);\n          }\n        };\n\n        function leaveAnimateCallback() {\n          scope.$emit(options.prefixEvent + '.hide', $modal);\n          bodyElement.removeClass(options.prefixClass + '-open');\n          if(options.animation) {\n            bodyElement.removeClass(options.prefixClass + '-with-' + options.animation);\n          }\n        }\n\n        $modal.toggle = function() {\n\n          $modal.$isShown ? $modal.hide() : $modal.show();\n\n        };\n\n        $modal.focus = function() {\n          modalElement[0].focus();\n        };\n\n        // Protected methods\n\n        $modal.$onKeyUp = function(evt) {\n\n          if (evt.which === 27 && $modal.$isShown) {\n            $modal.hide();\n            evt.stopPropagation();\n          }\n\n        };\n\n        // Private methods\n\n        function hideOnBackdropClick(evt) {\n          if(evt.target !== evt.currentTarget) return;\n          options.backdrop === 'static' ? $modal.focus() : $modal.hide();\n        }\n\n        function preventEventDefault(evt) {\n          evt.preventDefault();\n        }\n\n        return $modal;\n\n      }\n\n      // Helper functions\n\n      function safeDigest(scope) {\n        scope.$$phase || (scope.$root && scope.$root.$$phase) || scope.$digest();\n      }\n\n      function findElement(query, element) {\n        return angular.element((element || document).querySelectorAll(query));\n      }\n\n      var fetchPromises = {};\n      function fetchTemplate(template) {\n        if(fetchPromises[template]) return fetchPromises[template];\n        return (fetchPromises[template] = $q.when($templateCache.get(template) || $http.get(template))\n        .then(function(res) {\n          if(angular.isObject(res)) {\n            $templateCache.put(template, res.data);\n            return res.data;\n          }\n          return res;\n        }));\n      }\n\n      return ModalFactory;\n\n    }];\n\n  })\n\n  .directive('bsModal', [\"$window\", \"$sce\", \"$modal\", function($window, $sce, $modal) {\n\n    return {\n      restrict: 'EAC',\n      scope: true,\n      link: function postLink(scope, element, attr, transclusion) {\n\n        // Directive options\n        var options = {scope: scope, element: element, show: false};\n        angular.forEach(['template', 'contentTemplate', 'placement', 'backdrop', 'keyboard', 'html', 'container', 'animation', 'id'], function(key) {\n          if(angular.isDefined(attr[key])) options[key] = attr[key];\n        });\n\n        // Support scope as data-attrs\n        angular.forEach(['title', 'content'], function(key) {\n          attr[key] && attr.$observe(key, function(newValue, oldValue) {\n            scope[key] = $sce.trustAsHtml(newValue);\n          });\n        });\n\n        // Support scope as an object\n        attr.bsModal && scope.$watch(attr.bsModal, function(newValue, oldValue) {\n          if(angular.isObject(newValue)) {\n            angular.extend(scope, newValue);\n          } else {\n            scope.content = newValue;\n          }\n        }, true);\n\n        // Initialize modal\n        var modal = $modal(options);\n\n        // Trigger\n        element.on(attr.trigger || 'click', modal.toggle);\n\n        // Garbage collection\n        scope.$on('$destroy', function() {\n          if (modal) modal.destroy();\n          options = null;\n          modal = null;\n        });\n\n      }\n    };\n\n  }]);\n\n// Source: navbar.js\nangular.module('mgcrea.ngStrap.navbar', [])\n\n  .provider('$navbar', function() {\n\n    var defaults = this.defaults = {\n      activeClass: 'active',\n      routeAttr: 'data-match-route',\n      strict: false\n    };\n\n    this.$get = function() {\n      return {defaults: defaults};\n    };\n\n  })\n\n  .directive('bsNavbar', [\"$window\", \"$location\", \"$navbar\", function($window, $location, $navbar) {\n\n    var defaults = $navbar.defaults;\n\n    return {\n      restrict: 'A',\n      link: function postLink(scope, element, attr, controller) {\n\n        // Directive options\n        var options = angular.copy(defaults);\n        angular.forEach(Object.keys(defaults), function(key) {\n          if(angular.isDefined(attr[key])) options[key] = attr[key];\n        });\n\n        // Watch for the $location\n        scope.$watch(function() {\n\n          return $location.path();\n\n        }, function(newValue, oldValue) {\n\n          var liElements = element[0].querySelectorAll('li[' + options.routeAttr + ']');\n\n          angular.forEach(liElements, function(li) {\n\n            var liElement = angular.element(li);\n            var pattern = liElement.attr(options.routeAttr).replace('/', '\\\\/');\n            if(options.strict) {\n              pattern = '^' + pattern + '$';\n            }\n            var regexp = new RegExp(pattern, ['i']);\n\n            if(regexp.test(newValue)) {\n              liElement.addClass(options.activeClass);\n            } else {\n              liElement.removeClass(options.activeClass);\n            }\n\n          });\n\n        });\n\n      }\n\n    };\n\n  }]);\n\n// Source: popover.js\nangular.module('mgcrea.ngStrap.popover', ['mgcrea.ngStrap.tooltip'])\n\n  .provider('$popover', function() {\n\n    var defaults = this.defaults = {\n      animation: 'am-fade',\n      customClass: '',\n      container: false,\n      target: false,\n      placement: 'right',\n      template: 'popover/popover.tpl.html',\n      contentTemplate: false,\n      trigger: 'click',\n      keyboard: true,\n      html: false,\n      title: '',\n      content: '',\n      delay: 0,\n      autoClose: false\n    };\n\n    this.$get = [\"$tooltip\", function($tooltip) {\n\n      function PopoverFactory(element, config) {\n\n        // Common vars\n        var options = angular.extend({}, defaults, config);\n\n        var $popover = $tooltip(element, options);\n\n        // Support scope as string options [/*title, */content]\n        if(options.content) {\n          $popover.$scope.content = options.content;\n        }\n\n        return $popover;\n\n      }\n\n      return PopoverFactory;\n\n    }];\n\n  })\n\n  .directive('bsPopover', [\"$window\", \"$sce\", \"$popover\", function($window, $sce, $popover) {\n\n    var requestAnimationFrame = $window.requestAnimationFrame || $window.setTimeout;\n\n    return {\n      restrict: 'EAC',\n      scope: true,\n      link: function postLink(scope, element, attr) {\n\n        // Directive options\n        var options = {scope: scope};\n        angular.forEach(['template', 'contentTemplate', 'placement', 'container', 'target', 'delay', 'trigger', 'keyboard', 'html', 'animation', 'customClass', 'autoClose', 'id'], function(key) {\n          if(angular.isDefined(attr[key])) options[key] = attr[key];\n        });\n\n        // Support scope as data-attrs\n        angular.forEach(['title', 'content'], function(key) {\n          attr[key] && attr.$observe(key, function(newValue, oldValue) {\n            scope[key] = $sce.trustAsHtml(newValue);\n            angular.isDefined(oldValue) && requestAnimationFrame(function() {\n              popover && popover.$applyPlacement();\n            });\n          });\n        });\n\n        // Support scope as an object\n        attr.bsPopover && scope.$watch(attr.bsPopover, function(newValue, oldValue) {\n          if(angular.isObject(newValue)) {\n            angular.extend(scope, newValue);\n          } else {\n            scope.content = newValue;\n          }\n          angular.isDefined(oldValue) && requestAnimationFrame(function() {\n            popover && popover.$applyPlacement();\n          });\n        }, true);\n\n        // Visibility binding support\n        attr.bsShow && scope.$watch(attr.bsShow, function(newValue, oldValue) {\n          if(!popover || !angular.isDefined(newValue)) return;\n          if(angular.isString(newValue)) newValue = !!newValue.match(/true|,?(popover),?/i);\n          newValue === true ? popover.show() : popover.hide();\n        });\n\n        // Initialize popover\n        var popover = $popover(element, options);\n\n        // Garbage collection\n        scope.$on('$destroy', function() {\n          if (popover) popover.destroy();\n          options = null;\n          popover = null;\n        });\n\n      }\n    };\n\n  }]);\n\n// Source: select.js\nangular.module('mgcrea.ngStrap.select', ['mgcrea.ngStrap.tooltip', 'mgcrea.ngStrap.helpers.parseOptions'])\n\n  .provider('$select', function() {\n\n    var defaults = this.defaults = {\n      animation: 'am-fade',\n      prefixClass: 'select',\n      prefixEvent: '$select',\n      placement: 'bottom-left',\n      template: 'select/select.tpl.html',\n      trigger: 'focus',\n      container: false,\n      keyboard: true,\n      html: false,\n      delay: 0,\n      multiple: false,\n      allNoneButtons: false,\n      sort: true,\n      caretHtml: '&nbsp;<span class=\"caret\"></span>',\n      placeholder: 'Choose among the following...',\n      allText: 'All',\n      noneText: 'None',\n      maxLength: 3,\n      maxLengthHtml: 'selected',\n      iconCheckmark: 'glyphicon glyphicon-ok'\n    };\n\n    this.$get = [\"$window\", \"$document\", \"$rootScope\", \"$tooltip\", \"$timeout\", function($window, $document, $rootScope, $tooltip, $timeout) {\n\n      var bodyEl = angular.element($window.document.body);\n      var isNative = /(ip(a|o)d|iphone|android)/ig.test($window.navigator.userAgent);\n      var isTouch = ('createTouch' in $window.document) && isNative;\n\n      function SelectFactory(element, controller, config) {\n\n        var $select = {};\n\n        // Common vars\n        var options = angular.extend({}, defaults, config);\n\n        $select = $tooltip(element, options);\n        var scope = $select.$scope;\n\n        scope.$matches = [];\n        scope.$activeIndex = 0;\n        scope.$isMultiple = options.multiple;\n        scope.$showAllNoneButtons = options.allNoneButtons && options.multiple;\n        scope.$iconCheckmark = options.iconCheckmark;\n        scope.$allText = options.allText;\n        scope.$noneText = options.noneText;\n\n        scope.$activate = function(index) {\n          scope.$$postDigest(function() {\n            $select.activate(index);\n          });\n        };\n\n        scope.$select = function(index, evt) {\n          scope.$$postDigest(function() {\n            $select.select(index);\n          });\n        };\n\n        scope.$isVisible = function() {\n          return $select.$isVisible();\n        };\n\n        scope.$isActive = function(index) {\n          return $select.$isActive(index);\n        };\n\n        scope.$selectAll = function () {\n          for (var i = 0; i < scope.$matches.length; i++) {\n            if (!scope.$isActive(i)) {\n              scope.$select(i);\n            }\n          }\n        };\n\n        scope.$selectNone = function () {\n          for (var i = 0; i < scope.$matches.length; i++) {\n            if (scope.$isActive(i)) {\n              scope.$select(i);\n            }\n          }\n        };\n\n        // Public methods\n\n        $select.update = function(matches) {\n          scope.$matches = matches;\n          $select.$updateActiveIndex();\n        };\n\n        $select.activate = function(index) {\n          if(options.multiple) {\n            scope.$activeIndex.sort();\n            $select.$isActive(index) ? scope.$activeIndex.splice(scope.$activeIndex.indexOf(index), 1) : scope.$activeIndex.push(index);\n            if(options.sort) scope.$activeIndex.sort();\n          } else {\n            scope.$activeIndex = index;\n          }\n          return scope.$activeIndex;\n        };\n\n        $select.select = function(index) {\n          var value = scope.$matches[index].value;\n          scope.$apply(function() {\n            $select.activate(index);\n            if(options.multiple) {\n              controller.$setViewValue(scope.$activeIndex.map(function(index) {\n                return scope.$matches[index].value;\n              }));\n            } else {\n              controller.$setViewValue(value);\n              // Hide if single select\n              $select.hide();\n            }\n          });\n          // Emit event\n          scope.$emit(options.prefixEvent + '.select', value, index, $select);\n        };\n\n        // Protected methods\n\n        $select.$updateActiveIndex = function() {\n          if(controller.$modelValue && scope.$matches.length) {\n            if(options.multiple && angular.isArray(controller.$modelValue)) {\n              scope.$activeIndex = controller.$modelValue.map(function(value) {\n                return $select.$getIndex(value);\n              });\n            } else {\n              scope.$activeIndex = $select.$getIndex(controller.$modelValue);\n            }\n          } else if(scope.$activeIndex >= scope.$matches.length) {\n            scope.$activeIndex = options.multiple ? [] : 0;\n          }\n        };\n\n        $select.$isVisible = function() {\n          if(!options.minLength || !controller) {\n            return scope.$matches.length;\n          }\n          // minLength support\n          return scope.$matches.length && controller.$viewValue.length >= options.minLength;\n        };\n\n        $select.$isActive = function(index) {\n          if(options.multiple) {\n            return scope.$activeIndex.indexOf(index) !== -1;\n          } else {\n            return scope.$activeIndex === index;\n          }\n        };\n\n        $select.$getIndex = function(value) {\n          var l = scope.$matches.length, i = l;\n          if(!l) return;\n          for(i = l; i--;) {\n            if(scope.$matches[i].value === value) break;\n          }\n          if(i < 0) return;\n          return i;\n        };\n\n        $select.$onMouseDown = function(evt) {\n          // Prevent blur on mousedown on .dropdown-menu\n          evt.preventDefault();\n          evt.stopPropagation();\n          // Emulate click for mobile devices\n          if(isTouch) {\n            var targetEl = angular.element(evt.target);\n            targetEl.triggerHandler('click');\n          }\n        };\n\n        $select.$onKeyDown = function(evt) {\n          if (!/(9|13|38|40)/.test(evt.keyCode)) return;\n          evt.preventDefault();\n          evt.stopPropagation();\n\n          // Select with enter\n          if(!options.multiple && (evt.keyCode === 13 || evt.keyCode === 9)) {\n            return $select.select(scope.$activeIndex);\n          }\n\n          // Navigate with keyboard\n          if(evt.keyCode === 38 && scope.$activeIndex > 0) scope.$activeIndex--;\n          else if(evt.keyCode === 40 && scope.$activeIndex < scope.$matches.length - 1) scope.$activeIndex++;\n          else if(angular.isUndefined(scope.$activeIndex)) scope.$activeIndex = 0;\n          scope.$digest();\n        };\n\n        // Overrides\n\n        var _show = $select.show;\n        $select.show = function() {\n          _show();\n          if(options.multiple) {\n            $select.$element.addClass('select-multiple');\n          }\n          // use timeout to hookup the events to prevent\n          // event bubbling from being processed imediately.\n          $timeout(function() {\n            $select.$element.on(isTouch ? 'touchstart' : 'mousedown', $select.$onMouseDown);\n            if(options.keyboard) {\n              element.on('keydown', $select.$onKeyDown);\n            }\n          }, 0, false);\n        };\n\n        var _hide = $select.hide;\n        $select.hide = function() {\n          $select.$element.off(isTouch ? 'touchstart' : 'mousedown', $select.$onMouseDown);\n          if(options.keyboard) {\n            element.off('keydown', $select.$onKeyDown);\n          }\n          _hide(true);\n        };\n\n        return $select;\n\n      }\n\n      SelectFactory.defaults = defaults;\n      return SelectFactory;\n\n    }];\n\n  })\n\n  .directive('bsSelect', [\"$window\", \"$parse\", \"$q\", \"$select\", \"$parseOptions\", function($window, $parse, $q, $select, $parseOptions) {\n\n    var defaults = $select.defaults;\n\n    return {\n      restrict: 'EAC',\n      require: 'ngModel',\n      link: function postLink(scope, element, attr, controller) {\n\n        // Directive options\n        var options = {scope: scope, placeholder: defaults.placeholder};\n        angular.forEach(['placement', 'container', 'delay', 'trigger', 'keyboard', 'html', 'animation', 'template', 'placeholder', 'multiple', 'allNoneButtons', 'maxLength', 'maxLengthHtml', 'allText', 'noneText', 'iconCheckmark', 'autoClose', 'id'], function(key) {\n          if(angular.isDefined(attr[key])) options[key] = attr[key];\n        });\n\n        // Add support for select markup\n        if(element[0].nodeName.toLowerCase() === 'select') {\n          var inputEl = element;\n          inputEl.css('display', 'none');\n          element = angular.element('<button type=\"button\" class=\"btn btn-default\"></button>');\n          inputEl.after(element);\n        }\n\n        // Build proper ngOptions\n        var parsedOptions = $parseOptions(attr.ngOptions);\n\n        // Initialize select\n        var select = $select(element, controller, options);\n\n        // Watch ngOptions values before filtering for changes\n        var watchedOptions = parsedOptions.$match[7].replace(/\\|.+/, '').trim();\n        scope.$watch(watchedOptions, function(newValue, oldValue) {\n          // console.warn('scope.$watch(%s)', watchedOptions, newValue, oldValue);\n          parsedOptions.valuesFn(scope, controller)\n          .then(function(values) {\n            select.update(values);\n            controller.$render();\n          });\n        }, true);\n\n        // Watch model for changes\n        scope.$watch(attr.ngModel, function(newValue, oldValue) {\n          // console.warn('scope.$watch(%s)', attr.ngModel, newValue, oldValue);\n          select.$updateActiveIndex();\n          controller.$render();\n        }, true);\n\n        // Model rendering in view\n        controller.$render = function () {\n          // console.warn('$render', element.attr('ng-model'), 'controller.$modelValue', typeof controller.$modelValue, controller.$modelValue, 'controller.$viewValue', typeof controller.$viewValue, controller.$viewValue);\n          var selected, index;\n          if(options.multiple && angular.isArray(controller.$modelValue)) {\n            selected = controller.$modelValue.map(function(value) {\n              index = select.$getIndex(value);\n              return angular.isDefined(index) ? select.$scope.$matches[index].label : false;\n            }).filter(angular.isDefined);\n            if(selected.length > (options.maxLength || defaults.maxLength)) {\n              selected = selected.length + ' ' + (options.maxLengthHtml || defaults.maxLengthHtml);\n            } else {\n              selected = selected.join(', ');\n            }\n          } else {\n            index = select.$getIndex(controller.$modelValue);\n            selected = angular.isDefined(index) ? select.$scope.$matches[index].label : false;\n          }\n          element.html((selected ? selected : options.placeholder) + defaults.caretHtml);\n        };\n\n        if(options.multiple){\n          controller.$isEmpty = function(value){\n            return !value || value.length === 0;\n          };\n        }\n\n        // Garbage collection\n        scope.$on('$destroy', function() {\n          if (select) select.destroy();\n          options = null;\n          select = null;\n        });\n\n      }\n    };\n\n  }]);\n\n// Source: tab.js\nangular.module('mgcrea.ngStrap.tab', [])\n\n  .provider('$tab', function() {\n\n    var defaults = this.defaults = {\n      animation: 'am-fade',\n      template: 'tab/tab.tpl.html',\n      navClass: 'nav-tabs',\n      activeClass: 'active'\n    };\n\n    var controller = this.controller = function($scope, $element, $attrs) {\n      var self = this;\n\n      // Attributes options\n      self.$options = angular.copy(defaults);\n      angular.forEach(['animation', 'navClass', 'activeClass'], function(key) {\n        if(angular.isDefined($attrs[key])) self.$options[key] = $attrs[key];\n      });\n\n      // Publish options on scope\n      $scope.$navClass = self.$options.navClass;\n      $scope.$activeClass = self.$options.activeClass;\n\n      self.$panes = $scope.$panes = [];\n\n      // DEPRECATED: $viewChangeListeners, please use $activePaneChangeListeners\n      // Because we deprecated ngModel usage, we rename viewChangeListeners to \n      // activePaneChangeListeners to make more sense.\n      self.$activePaneChangeListeners = self.$viewChangeListeners = [];\n\n      self.$push = function(pane) {\n        self.$panes.push(pane);\n      };\n\n      self.$remove = function(pane) {\n        var index = self.$panes.indexOf(pane);\n        var activeIndex = self.$panes.$active;\n\n        // remove pane from $panes array\n        self.$panes.splice(index, 1);\n\n        if (index < activeIndex) {\n          // we removed a pane before the active pane, so we need to \n          // decrement the active pane index\n          activeIndex--;\n        }\n        else if (index === activeIndex && activeIndex === self.$panes.length) {\n          // we remove the active pane and it was the one at the end,\n          // so select the previous one\n          activeIndex--;\n        }\n        self.$setActive(activeIndex);\n      };\n\n      self.$panes.$active = 0;\n      self.$setActive = $scope.$setActive = function(value) {\n        self.$panes.$active = value;\n        self.$activePaneChangeListeners.forEach(function(fn) {\n          fn();\n        });\n      };\n\n    };\n\n    this.$get = function() {\n      var $tab = {};\n      $tab.defaults = defaults;\n      $tab.controller = controller;\n      return $tab;\n    };\n\n  })\n\n  .directive('bsTabs', [\"$window\", \"$animate\", \"$tab\", \"$parse\", function($window, $animate, $tab, $parse) {\n\n    var defaults = $tab.defaults;\n\n    return {\n      require: ['?ngModel', 'bsTabs'],\n      transclude: true,\n      scope: true,\n      controller: ['$scope', '$element', '$attrs', $tab.controller],\n      templateUrl: function(element, attr) {\n        return attr.template || defaults.template;\n      },\n      link: function postLink(scope, element, attrs, controllers) {\n\n        var ngModelCtrl = controllers[0];\n        var bsTabsCtrl = controllers[1];\n\n        // DEPRECATED: ngModel, please use bsActivePane\n        // 'ngModel' is deprecated bacause if interferes with form validation\n        // and status, so avoid using it here.\n        if(ngModelCtrl) {\n          console.warn('Usage of ngModel is deprecated, please use bsActivePane instead!');\n\n          // Update the modelValue following\n          bsTabsCtrl.$activePaneChangeListeners.push(function() {\n            ngModelCtrl.$setViewValue(bsTabsCtrl.$panes.$active);\n          });\n\n          // modelValue -> $formatters -> viewValue\n          ngModelCtrl.$formatters.push(function(modelValue) {\n            // console.warn('$formatter(\"%s\"): modelValue=%o (%o)', element.attr('ng-model'), modelValue, typeof modelValue);\n            bsTabsCtrl.$setActive(modelValue * 1);\n            return modelValue;\n          });\n\n        }\n\n        if (attrs.bsActivePane) {\n          // adapted from angularjs ngModelController bindings\n          // https://github.com/angular/angular.js/blob/v1.3.1/src%2Fng%2Fdirective%2Finput.js#L1730\n          var parsedBsActivePane = $parse(attrs.bsActivePane);\n\n          // Update bsActivePane value with change\n          bsTabsCtrl.$activePaneChangeListeners.push(function() {\n            parsedBsActivePane.assign(scope, bsTabsCtrl.$panes.$active);\n          });\n\n          // watch bsActivePane for value changes\n          scope.$watch(attrs.bsActivePane, function(newValue, oldValue) {\n            bsTabsCtrl.$setActive(newValue * 1);\n          }, true);\n        }\n      }\n    };\n\n  }])\n\n  .directive('bsPane', [\"$window\", \"$animate\", \"$sce\", function($window, $animate, $sce) {\n\n    return {\n      require: ['^?ngModel', '^bsTabs'],\n      scope: true,\n      link: function postLink(scope, element, attrs, controllers) {\n\n        var ngModelCtrl = controllers[0];\n        var bsTabsCtrl = controllers[1];\n\n        // Add base class\n        element.addClass('tab-pane');\n\n        // Observe title attribute for change\n        attrs.$observe('title', function(newValue, oldValue) {\n          scope.title = $sce.trustAsHtml(newValue);\n        });\n\n        // Add animation class\n        if(bsTabsCtrl.$options.animation) {\n          element.addClass(bsTabsCtrl.$options.animation);\n        }\n\n        // Push pane to parent bsTabs controller\n        bsTabsCtrl.$push(scope);\n\n        // remove pane from tab controller when pane is destroyed\n        scope.$on('$destroy', function() {\n          bsTabsCtrl.$remove(scope);\n        });\n\n        function render() {\n          var index = bsTabsCtrl.$panes.indexOf(scope);\n          var active = bsTabsCtrl.$panes.$active;\n          $animate[index === active ? 'addClass' : 'removeClass'](element, bsTabsCtrl.$options.activeClass);\n        }\n\n        bsTabsCtrl.$activePaneChangeListeners.push(function() {\n          render();\n        });\n        render();\n\n      }\n    };\n\n  }]);\n\n// Source: scrollspy.js\nangular.module('mgcrea.ngStrap.scrollspy', ['mgcrea.ngStrap.helpers.debounce', 'mgcrea.ngStrap.helpers.dimensions'])\n\n  .provider('$scrollspy', function() {\n\n    // Pool of registered spies\n    var spies = this.$$spies = {};\n\n    var defaults = this.defaults = {\n      debounce: 150,\n      throttle: 100,\n      offset: 100\n    };\n\n    this.$get = [\"$window\", \"$document\", \"$rootScope\", \"dimensions\", \"debounce\", \"throttle\", function($window, $document, $rootScope, dimensions, debounce, throttle) {\n\n      var windowEl = angular.element($window);\n      var docEl = angular.element($document.prop('documentElement'));\n      var bodyEl = angular.element($window.document.body);\n\n      // Helper functions\n\n      function nodeName(element, name) {\n        return element[0].nodeName && element[0].nodeName.toLowerCase() === name.toLowerCase();\n      }\n\n      function ScrollSpyFactory(config) {\n\n        // Common vars\n        var options = angular.extend({}, defaults, config);\n        if(!options.element) options.element = bodyEl;\n        var isWindowSpy = nodeName(options.element, 'body');\n        var scrollEl = isWindowSpy ? windowEl : options.element;\n        var scrollId = isWindowSpy ? 'window' : options.id;\n\n        // Use existing spy\n        if(spies[scrollId]) {\n          spies[scrollId].$$count++;\n          return spies[scrollId];\n        }\n\n        var $scrollspy = {};\n\n        // Private vars\n        var unbindViewContentLoaded, unbindIncludeContentLoaded;\n        var trackedElements = $scrollspy.$trackedElements = [];\n        var sortedElements = [];\n        var activeTarget;\n        var debouncedCheckPosition;\n        var throttledCheckPosition;\n        var debouncedCheckOffsets;\n        var viewportHeight;\n        var scrollTop;\n\n        $scrollspy.init = function() {\n\n          // Setup internal ref counter\n          this.$$count = 1;\n\n          // Bind events\n          debouncedCheckPosition = debounce(this.checkPosition, options.debounce);\n          throttledCheckPosition = throttle(this.checkPosition, options.throttle);\n          scrollEl.on('click', this.checkPositionWithEventLoop);\n          windowEl.on('resize', debouncedCheckPosition);\n          scrollEl.on('scroll', throttledCheckPosition);\n\n          debouncedCheckOffsets = debounce(this.checkOffsets, options.debounce);\n          unbindViewContentLoaded = $rootScope.$on('$viewContentLoaded', debouncedCheckOffsets);\n          unbindIncludeContentLoaded = $rootScope.$on('$includeContentLoaded', debouncedCheckOffsets);\n          debouncedCheckOffsets();\n\n          // Register spy for reuse\n          if(scrollId) {\n            spies[scrollId] = $scrollspy;\n          }\n\n        };\n\n        $scrollspy.destroy = function() {\n\n          // Check internal ref counter\n          this.$$count--;\n          if(this.$$count > 0) {\n            return;\n          }\n\n          // Unbind events\n          scrollEl.off('click', this.checkPositionWithEventLoop);\n          windowEl.off('resize', debouncedCheckPosition);\n          scrollEl.off('scroll', throttledCheckPosition);\n          unbindViewContentLoaded();\n          unbindIncludeContentLoaded();\n          if (scrollId) {\n            delete spies[scrollId];\n          }\n        };\n\n        $scrollspy.checkPosition = function() {\n\n          // Not ready yet\n          if(!sortedElements.length) return;\n\n          // Calculate the scroll position\n          scrollTop = (isWindowSpy ? $window.pageYOffset : scrollEl.prop('scrollTop')) || 0;\n\n          // Calculate the viewport height for use by the components\n          viewportHeight = Math.max($window.innerHeight, docEl.prop('clientHeight'));\n\n          // Activate first element if scroll is smaller\n          if(scrollTop < sortedElements[0].offsetTop && activeTarget !== sortedElements[0].target) {\n            return $scrollspy.$activateElement(sortedElements[0]);\n          }\n\n          // Activate proper element\n          for (var i = sortedElements.length; i--;) {\n            if(angular.isUndefined(sortedElements[i].offsetTop) || sortedElements[i].offsetTop === null) continue;\n            if(activeTarget === sortedElements[i].target) continue;\n            if(scrollTop < sortedElements[i].offsetTop) continue;\n            if(sortedElements[i + 1] && scrollTop > sortedElements[i + 1].offsetTop) continue;\n            return $scrollspy.$activateElement(sortedElements[i]);\n          }\n\n        };\n\n        $scrollspy.checkPositionWithEventLoop = function() {\n          // IE 9 throws an error if we use 'this' instead of '$scrollspy'\n          // in this setTimeout call\n          setTimeout($scrollspy.checkPosition, 1);\n        };\n\n        // Protected methods\n\n        $scrollspy.$activateElement = function(element) {\n          if(activeTarget) {\n            var activeElement = $scrollspy.$getTrackedElement(activeTarget);\n            if(activeElement) {\n              activeElement.source.removeClass('active');\n              if(nodeName(activeElement.source, 'li') && nodeName(activeElement.source.parent().parent(), 'li')) {\n                activeElement.source.parent().parent().removeClass('active');\n              }\n            }\n          }\n          activeTarget = element.target;\n          element.source.addClass('active');\n          if(nodeName(element.source, 'li') && nodeName(element.source.parent().parent(), 'li')) {\n            element.source.parent().parent().addClass('active');\n          }\n        };\n\n        $scrollspy.$getTrackedElement = function(target) {\n          return trackedElements.filter(function(obj) {\n            return obj.target === target;\n          })[0];\n        };\n\n        // Track offsets behavior\n\n        $scrollspy.checkOffsets = function() {\n\n          angular.forEach(trackedElements, function(trackedElement) {\n            var targetElement = document.querySelector(trackedElement.target);\n            trackedElement.offsetTop = targetElement ? dimensions.offset(targetElement).top : null;\n            if(options.offset && trackedElement.offsetTop !== null) trackedElement.offsetTop -= options.offset * 1;\n          });\n\n          sortedElements = trackedElements\n          .filter(function(el) {\n            return el.offsetTop !== null;\n          })\n          .sort(function(a, b) {\n            return a.offsetTop - b.offsetTop;\n          });\n\n          debouncedCheckPosition();\n\n        };\n\n        $scrollspy.trackElement = function(target, source) {\n          trackedElements.push({target: target, source: source});\n        };\n\n        $scrollspy.untrackElement = function(target, source) {\n          var toDelete;\n          for (var i = trackedElements.length; i--;) {\n            if(trackedElements[i].target === target && trackedElements[i].source === source) {\n              toDelete = i;\n              break;\n            }\n          }\n          trackedElements = trackedElements.splice(toDelete, 1);\n        };\n\n        $scrollspy.activate = function(i) {\n          trackedElements[i].addClass('active');\n        };\n\n        // Initialize plugin\n\n        $scrollspy.init();\n        return $scrollspy;\n\n      }\n\n      return ScrollSpyFactory;\n\n    }];\n\n  })\n\n  .directive('bsScrollspy', [\"$rootScope\", \"debounce\", \"dimensions\", \"$scrollspy\", function($rootScope, debounce, dimensions, $scrollspy) {\n\n    return {\n      restrict: 'EAC',\n      link: function postLink(scope, element, attr) {\n\n        var options = {scope: scope};\n        angular.forEach(['offset', 'target'], function(key) {\n          if(angular.isDefined(attr[key])) options[key] = attr[key];\n        });\n\n        var scrollspy = $scrollspy(options);\n        scrollspy.trackElement(options.target, element);\n\n        scope.$on('$destroy', function() {\n          if (scrollspy) {\n            scrollspy.untrackElement(options.target, element);\n            scrollspy.destroy();\n          }\n          options = null;\n          scrollspy = null;\n        });\n\n      }\n    };\n\n  }])\n\n\n  .directive('bsScrollspyList', [\"$rootScope\", \"debounce\", \"dimensions\", \"$scrollspy\", function($rootScope, debounce, dimensions, $scrollspy) {\n\n    return {\n      restrict: 'A',\n      compile: function postLink(element, attr) {\n        var children = element[0].querySelectorAll('li > a[href]');\n        angular.forEach(children, function(child) {\n          var childEl = angular.element(child);\n          childEl.parent().attr('bs-scrollspy', '').attr('data-target', childEl.attr('href'));\n        });\n      }\n\n    };\n\n  }]);\n\n// Source: timepicker.js\nangular.module('mgcrea.ngStrap.timepicker', [\n  'mgcrea.ngStrap.helpers.dateParser',\n  'mgcrea.ngStrap.helpers.dateFormatter',\n  'mgcrea.ngStrap.tooltip'])\n\n  .provider('$timepicker', function() {\n\n    var defaults = this.defaults = {\n      animation: 'am-fade',\n      prefixClass: 'timepicker',\n      placement: 'bottom-left',\n      template: 'timepicker/timepicker.tpl.html',\n      trigger: 'focus',\n      container: false,\n      keyboard: true,\n      html: false,\n      delay: 0,\n      // lang: $locale.id,\n      useNative: true,\n      timeType: 'date',\n      timeFormat: 'shortTime',\n      modelTimeFormat: null,\n      autoclose: false,\n      minTime: -Infinity,\n      maxTime: +Infinity,\n      length: 5,\n      hourStep: 1,\n      minuteStep: 5,\n      iconUp: 'glyphicon glyphicon-chevron-up',\n      iconDown: 'glyphicon glyphicon-chevron-down',\n      arrowBehavior: 'pager'\n    };\n\n    this.$get = [\"$window\", \"$document\", \"$rootScope\", \"$sce\", \"$dateFormatter\", \"$tooltip\", \"$timeout\", function($window, $document, $rootScope, $sce, $dateFormatter, $tooltip, $timeout) {\n\n      var bodyEl = angular.element($window.document.body);\n      var isNative = /(ip(a|o)d|iphone|android)/ig.test($window.navigator.userAgent);\n      var isTouch = ('createTouch' in $window.document) && isNative;\n      if(!defaults.lang) defaults.lang = $dateFormatter.getDefaultLocale();\n\n      function timepickerFactory(element, controller, config) {\n\n        var $timepicker = $tooltip(element, angular.extend({}, defaults, config));\n        var parentScope = config.scope;\n        var options = $timepicker.$options;\n        var scope = $timepicker.$scope;\n\n        var lang = options.lang;\n        var formatDate = function(date, format) {\n          return $dateFormatter.formatDate(date, format, lang);\n        };\n\n        // View vars\n\n        var selectedIndex = 0;\n        var startDate = controller.$dateValue || new Date();\n        var viewDate = {hour: startDate.getHours(), meridian: startDate.getHours() < 12, minute: startDate.getMinutes(), second: startDate.getSeconds(), millisecond: startDate.getMilliseconds()};\n\n        var format = $dateFormatter.getDatetimeFormat(options.timeFormat, lang);\n\n        var hoursFormat = $dateFormatter.hoursFormat(format),\n          timeSeparator = $dateFormatter.timeSeparator(format),\n          minutesFormat = $dateFormatter.minutesFormat(format),\n          showAM = $dateFormatter.showAM(format);\n\n        scope.$iconUp = options.iconUp;\n        scope.$iconDown = options.iconDown;\n\n        // Scope methods\n\n        scope.$select = function(date, index) {\n          $timepicker.select(date, index);\n        };\n        scope.$moveIndex = function(value, index) {\n          $timepicker.$moveIndex(value, index);\n        };\n        scope.$switchMeridian = function(date) {\n          $timepicker.switchMeridian(date);\n        };\n\n        // Public methods\n\n        $timepicker.update = function(date) {\n          // console.warn('$timepicker.update() newValue=%o', date);\n          if(angular.isDate(date) && !isNaN(date.getTime())) {\n            $timepicker.$date = date;\n            angular.extend(viewDate, {hour: date.getHours(), minute: date.getMinutes(), second: date.getSeconds(), millisecond: date.getMilliseconds()});\n            $timepicker.$build();\n          } else if(!$timepicker.$isBuilt) {\n            $timepicker.$build();\n          }\n        };\n\n        $timepicker.select = function(date, index, keep) {\n          // console.warn('$timepicker.select', date, scope.$mode);\n          if(!controller.$dateValue || isNaN(controller.$dateValue.getTime())) controller.$dateValue = new Date(1970, 0, 1);\n          if(!angular.isDate(date)) date = new Date(date);\n          if(index === 0) controller.$dateValue.setHours(date.getHours());\n          else if(index === 1) controller.$dateValue.setMinutes(date.getMinutes());\n          controller.$setViewValue(angular.copy(controller.$dateValue));\n          controller.$render();\n          if(options.autoclose && !keep) {\n            $timeout(function() { $timepicker.hide(true); });\n          }\n        };\n\n        $timepicker.switchMeridian = function(date) {\n          if (!controller.$dateValue || isNaN(controller.$dateValue.getTime())) {\n            return;\n          }\n          var hours = (date || controller.$dateValue).getHours();\n          controller.$dateValue.setHours(hours < 12 ? hours + 12 : hours - 12);\n          controller.$setViewValue(angular.copy(controller.$dateValue));\n          controller.$render();\n        };\n\n        // Protected methods\n\n        $timepicker.$build = function() {\n          // console.warn('$timepicker.$build() viewDate=%o', viewDate);\n          var i, midIndex = scope.midIndex = parseInt(options.length / 2, 10);\n          var hours = [], hour;\n          for(i = 0; i < options.length; i++) {\n            hour = new Date(1970, 0, 1, viewDate.hour - (midIndex - i) * options.hourStep);\n            hours.push({date: hour, label: formatDate(hour, hoursFormat), selected: $timepicker.$date && $timepicker.$isSelected(hour, 0), disabled: $timepicker.$isDisabled(hour, 0)});\n          }\n          var minutes = [], minute;\n          for(i = 0; i < options.length; i++) {\n            minute = new Date(1970, 0, 1, 0, viewDate.minute - (midIndex - i) * options.minuteStep);\n            minutes.push({date: minute, label: formatDate(minute, minutesFormat), selected: $timepicker.$date && $timepicker.$isSelected(minute, 1), disabled: $timepicker.$isDisabled(minute, 1)});\n          }\n\n          var rows = [];\n          for(i = 0; i < options.length; i++) {\n            rows.push([hours[i], minutes[i]]);\n          }\n          scope.rows = rows;\n          scope.showAM = showAM;\n          scope.isAM = ($timepicker.$date || hours[midIndex].date).getHours() < 12;\n          scope.timeSeparator = timeSeparator;\n          $timepicker.$isBuilt = true;\n        };\n\n        $timepicker.$isSelected = function(date, index) {\n          if(!$timepicker.$date) return false;\n          else if(index === 0) {\n            return date.getHours() === $timepicker.$date.getHours();\n          } else if(index === 1) {\n            return date.getMinutes() === $timepicker.$date.getMinutes();\n          }\n        };\n\n        $timepicker.$isDisabled = function(date, index) {\n          var selectedTime;\n          if(index === 0) {\n            selectedTime = date.getTime() + viewDate.minute * 6e4;\n          } else if(index === 1) {\n            selectedTime = date.getTime() + viewDate.hour * 36e5;\n          }\n          return selectedTime < options.minTime * 1 || selectedTime > options.maxTime * 1;\n        };\n\n        scope.$arrowAction = function (value, index) {\n          if (options.arrowBehavior === 'picker') {\n            $timepicker.$setTimeByStep(value,index);\n          } else {\n            $timepicker.$moveIndex(value,index);\n          }\n        };\n\n        $timepicker.$setTimeByStep = function(value, index) {\n          var newDate = new Date($timepicker.$date);\n          var hours = newDate.getHours(), hoursLength = formatDate(newDate, hoursFormat).length;\n          var minutes = newDate.getMinutes(), minutesLength = formatDate(newDate, minutesFormat).length;\n          if (index === 0) {\n            newDate.setHours(hours - (parseInt(options.hourStep, 10) * value));\n          }\n          else {\n            newDate.setMinutes(minutes - (parseInt(options.minuteStep, 10) * value));\n          }\n          $timepicker.select(newDate, index, true);\n        };\n\n        $timepicker.$moveIndex = function(value, index) {\n          var targetDate;\n          if(index === 0) {\n            targetDate = new Date(1970, 0, 1, viewDate.hour + (value * options.length), viewDate.minute);\n            angular.extend(viewDate, {hour: targetDate.getHours()});\n          } else if(index === 1) {\n            targetDate = new Date(1970, 0, 1, viewDate.hour, viewDate.minute + (value * options.length * options.minuteStep));\n            angular.extend(viewDate, {minute: targetDate.getMinutes()});\n          }\n          $timepicker.$build();\n        };\n\n        $timepicker.$onMouseDown = function(evt) {\n          // Prevent blur on mousedown on .dropdown-menu\n          if(evt.target.nodeName.toLowerCase() !== 'input') evt.preventDefault();\n          evt.stopPropagation();\n          // Emulate click for mobile devices\n          if(isTouch) {\n            var targetEl = angular.element(evt.target);\n            if(targetEl[0].nodeName.toLowerCase() !== 'button') {\n              targetEl = targetEl.parent();\n            }\n            targetEl.triggerHandler('click');\n          }\n        };\n\n        $timepicker.$onKeyDown = function(evt) {\n          if (!/(38|37|39|40|13)/.test(evt.keyCode) || evt.shiftKey || evt.altKey) return;\n          evt.preventDefault();\n          evt.stopPropagation();\n\n          // Close on enter\n          if(evt.keyCode === 13) return $timepicker.hide(true);\n\n          // Navigate with keyboard\n          var newDate = new Date($timepicker.$date);\n          var hours = newDate.getHours(), hoursLength = formatDate(newDate, hoursFormat).length;\n          var minutes = newDate.getMinutes(), minutesLength = formatDate(newDate, minutesFormat).length;\n          var lateralMove = /(37|39)/.test(evt.keyCode);\n          var count = 2 + showAM * 1;\n\n          // Navigate indexes (left, right)\n          if (lateralMove) {\n            if(evt.keyCode === 37) selectedIndex = selectedIndex < 1 ? count - 1 : selectedIndex - 1;\n            else if(evt.keyCode === 39) selectedIndex = selectedIndex < count - 1 ? selectedIndex + 1 : 0;\n          }\n\n          // Update values (up, down)\n          var selectRange = [0, hoursLength];\n          if(selectedIndex === 0) {\n            if(evt.keyCode === 38) newDate.setHours(hours - parseInt(options.hourStep, 10));\n            else if(evt.keyCode === 40) newDate.setHours(hours + parseInt(options.hourStep, 10));\n            // re-calculate hours length because we have changed hours value\n            hoursLength = formatDate(newDate, hoursFormat).length;\n            selectRange = [0, hoursLength];\n          } else if(selectedIndex === 1) {\n            if(evt.keyCode === 38) newDate.setMinutes(minutes - parseInt(options.minuteStep, 10));\n            else if(evt.keyCode === 40) newDate.setMinutes(minutes + parseInt(options.minuteStep, 10));\n            // re-calculate minutes length because we have changes minutes value\n            minutesLength = formatDate(newDate, minutesFormat).length;\n            selectRange = [hoursLength + 1, hoursLength + 1 + minutesLength];\n          } else if(selectedIndex === 2) {\n            if(!lateralMove) $timepicker.switchMeridian();\n            selectRange = [hoursLength + 1 + minutesLength + 1, hoursLength + 1 + minutesLength + 3];\n          }\n          $timepicker.select(newDate, selectedIndex, true);\n          createSelection(selectRange[0], selectRange[1]);\n          parentScope.$digest();\n        };\n\n        // Private\n\n        function createSelection(start, end) {\n          if(element[0].createTextRange) {\n            var selRange = element[0].createTextRange();\n            selRange.collapse(true);\n            selRange.moveStart('character', start);\n            selRange.moveEnd('character', end);\n            selRange.select();\n          } else if(element[0].setSelectionRange) {\n            element[0].setSelectionRange(start, end);\n          } else if(angular.isUndefined(element[0].selectionStart)) {\n            element[0].selectionStart = start;\n            element[0].selectionEnd = end;\n          }\n        }\n\n        function focusElement() {\n          element[0].focus();\n        }\n\n        // Overrides\n\n        var _init = $timepicker.init;\n        $timepicker.init = function() {\n          if(isNative && options.useNative) {\n            element.prop('type', 'time');\n            element.css('-webkit-appearance', 'textfield');\n            return;\n          } else if(isTouch) {\n            element.prop('type', 'text');\n            element.attr('readonly', 'true');\n            element.on('click', focusElement);\n          }\n          _init();\n        };\n\n        var _destroy = $timepicker.destroy;\n        $timepicker.destroy = function() {\n          if(isNative && options.useNative) {\n            element.off('click', focusElement);\n          }\n          _destroy();\n        };\n\n        var _show = $timepicker.show;\n        $timepicker.show = function() {\n          _show();\n          // use timeout to hookup the events to prevent\n          // event bubbling from being processed imediately.\n          $timeout(function() {\n            $timepicker.$element.on(isTouch ? 'touchstart' : 'mousedown', $timepicker.$onMouseDown);\n            if(options.keyboard) {\n              element.on('keydown', $timepicker.$onKeyDown);\n            }\n          }, 0, false);\n        };\n\n        var _hide = $timepicker.hide;\n        $timepicker.hide = function(blur) {\n          if(!$timepicker.$isShown) return;\n          $timepicker.$element.off(isTouch ? 'touchstart' : 'mousedown', $timepicker.$onMouseDown);\n          if(options.keyboard) {\n            element.off('keydown', $timepicker.$onKeyDown);\n          }\n          _hide(blur);\n        };\n\n        return $timepicker;\n\n      }\n\n      timepickerFactory.defaults = defaults;\n      return timepickerFactory;\n\n    }];\n\n  })\n\n\n  .directive('bsTimepicker', [\"$window\", \"$parse\", \"$q\", \"$dateFormatter\", \"$dateParser\", \"$timepicker\", function($window, $parse, $q, $dateFormatter, $dateParser, $timepicker) {\n\n    var defaults = $timepicker.defaults;\n    var isNative = /(ip(a|o)d|iphone|android)/ig.test($window.navigator.userAgent);\n    var requestAnimationFrame = $window.requestAnimationFrame || $window.setTimeout;\n\n    return {\n      restrict: 'EAC',\n      require: 'ngModel',\n      link: function postLink(scope, element, attr, controller) {\n\n        // Directive options\n        var options = {scope: scope, controller: controller};\n        angular.forEach(['placement', 'container', 'delay', 'trigger', 'keyboard', 'html', 'animation', 'template', 'autoclose', 'timeType', 'timeFormat', 'modelTimeFormat', 'useNative', 'hourStep', 'minuteStep', 'length', 'arrowBehavior', 'iconUp', 'iconDown', 'id'], function(key) {\n          if(angular.isDefined(attr[key])) options[key] = attr[key];\n        });\n\n        // Visibility binding support\n        attr.bsShow && scope.$watch(attr.bsShow, function(newValue, oldValue) {\n          if(!timepicker || !angular.isDefined(newValue)) return;\n          if(angular.isString(newValue)) newValue = !!newValue.match(/true|,?(timepicker),?/i);\n          newValue === true ? timepicker.show() : timepicker.hide();\n        });\n\n        // Initialize timepicker\n        if(isNative && (options.useNative || defaults.useNative)) options.timeFormat = 'HH:mm';\n        var timepicker = $timepicker(element, controller, options);\n        options = timepicker.$options;\n\n        var lang = options.lang;\n        var formatDate = function(date, format) {\n          return $dateFormatter.formatDate(date, format, lang);\n        };\n\n        // Initialize parser\n        var dateParser = $dateParser({format: options.timeFormat, lang: lang});\n\n        // Observe attributes for changes\n        angular.forEach(['minTime', 'maxTime'], function(key) {\n          // console.warn('attr.$observe(%s)', key, attr[key]);\n          angular.isDefined(attr[key]) && attr.$observe(key, function(newValue) {\n            timepicker.$options[key] = dateParser.getTimeForAttribute(key, newValue);\n            !isNaN(timepicker.$options[key]) && timepicker.$build();\n            validateAgainstMinMaxTime(controller.$dateValue);\n          });\n        });\n\n        // Watch model for changes\n        scope.$watch(attr.ngModel, function(newValue, oldValue) {\n          // console.warn('scope.$watch(%s)', attr.ngModel, newValue, oldValue, controller.$dateValue);\n          timepicker.update(controller.$dateValue);\n        }, true);\n\n        function validateAgainstMinMaxTime(parsedTime) {\n          if (!angular.isDate(parsedTime)) return;\n          var isMinValid = isNaN(options.minTime) || new Date(parsedTime.getTime()).setFullYear(1970, 0, 1) >= options.minTime;\n          var isMaxValid = isNaN(options.maxTime) || new Date(parsedTime.getTime()).setFullYear(1970, 0, 1) <= options.maxTime;\n          var isValid = isMinValid && isMaxValid;\n          controller.$setValidity('date', isValid);\n          controller.$setValidity('min', isMinValid);\n          controller.$setValidity('max', isMaxValid);\n          // Only update the model when we have a valid date\n          if(!isValid) {\n              return;\n          }\n          controller.$dateValue = parsedTime;\n        }\n\n        // viewValue -> $parsers -> modelValue\n        controller.$parsers.unshift(function(viewValue) {\n          // console.warn('$parser(\"%s\"): viewValue=%o', element.attr('ng-model'), viewValue);\n          // Null values should correctly reset the model value & validity\n          if(!viewValue) {\n            // BREAKING CHANGE:\n            // return null (not undefined) when input value is empty, so angularjs 1.3\n            // ngModelController can go ahead and run validators, like ngRequired\n            controller.$setValidity('date', true);\n            return null;\n          }\n          var parsedTime = angular.isDate(viewValue) ? viewValue : dateParser.parse(viewValue, controller.$dateValue);\n          if(!parsedTime || isNaN(parsedTime.getTime())) {\n            controller.$setValidity('date', false);\n            // return undefined, causes ngModelController to\n            // invalidate model value\n            return;\n          } else {\n            validateAgainstMinMaxTime(parsedTime);\n          }\n          if(options.timeType === 'string') {\n            return formatDate(parsedTime, options.modelTimeFormat || options.timeFormat);\n          } else if(options.timeType === 'number') {\n            return controller.$dateValue.getTime();\n          } else if(options.timeType === 'unix') {\n            return controller.$dateValue.getTime() / 1000;\n          } else if(options.timeType === 'iso') {\n            return controller.$dateValue.toISOString();\n          } else {\n            return new Date(controller.$dateValue);\n          }\n        });\n\n        // modelValue -> $formatters -> viewValue\n        controller.$formatters.push(function(modelValue) {\n          // console.warn('$formatter(\"%s\"): modelValue=%o (%o)', element.attr('ng-model'), modelValue, typeof modelValue);\n          var date;\n          if(angular.isUndefined(modelValue) || modelValue === null) {\n            date = NaN;\n          } else if(angular.isDate(modelValue)) {\n            date = modelValue;\n          } else if(options.timeType === 'string') {\n            date = dateParser.parse(modelValue, null, options.modelTimeFormat);\n          } else if(options.timeType === 'unix') {\n            date = new Date(modelValue * 1000);\n          } else {\n            date = new Date(modelValue);\n          }\n          // Setup default value?\n          // if(isNaN(date.getTime())) date = new Date(new Date().setMinutes(0) + 36e5);\n          controller.$dateValue = date;\n          return getTimeFormattedString();\n        });\n\n        // viewValue -> element\n        controller.$render = function() {\n          // console.warn('$render(\"%s\"): viewValue=%o', element.attr('ng-model'), controller.$viewValue);\n          element.val(getTimeFormattedString());\n        };\n\n        function getTimeFormattedString() {\n          return !controller.$dateValue || isNaN(controller.$dateValue.getTime()) ? '' : formatDate(controller.$dateValue, options.timeFormat);\n        }\n\n        // Garbage collection\n        scope.$on('$destroy', function() {\n          if (timepicker) timepicker.destroy();\n          options = null;\n          timepicker = null;\n        });\n\n      }\n    };\n\n  }]);\n\n// Source: tooltip.js\nangular.module('mgcrea.ngStrap.tooltip', ['mgcrea.ngStrap.helpers.dimensions'])\n\n  .provider('$tooltip', function() {\n\n    var defaults = this.defaults = {\n      animation: 'am-fade',\n      customClass: '',\n      prefixClass: 'tooltip',\n      prefixEvent: 'tooltip',\n      container: false,\n      target: false,\n      placement: 'top',\n      template: 'tooltip/tooltip.tpl.html',\n      contentTemplate: false,\n      trigger: 'hover focus',\n      keyboard: false,\n      html: false,\n      show: false,\n      title: '',\n      type: '',\n      delay: 0,\n      autoClose: false,\n      bsEnabled: true\n    };\n\n    this.$get = [\"$window\", \"$rootScope\", \"$compile\", \"$q\", \"$templateCache\", \"$http\", \"$animate\", \"$sce\", \"dimensions\", \"$$rAF\", \"$timeout\", function($window, $rootScope, $compile, $q, $templateCache, $http, $animate, $sce, dimensions, $$rAF, $timeout) {\n\n      var trim = String.prototype.trim;\n      var isTouch = 'createTouch' in $window.document;\n      var htmlReplaceRegExp = /ng-bind=\"/ig;\n      var $body = angular.element($window.document);\n\n      function TooltipFactory(element, config) {\n\n        var $tooltip = {};\n\n        // Common vars\n        var nodeName = element[0].nodeName.toLowerCase();\n        var options = $tooltip.$options = angular.extend({}, defaults, config);\n        $tooltip.$promise = fetchTemplate(options.template);\n        var scope = $tooltip.$scope = options.scope && options.scope.$new() || $rootScope.$new();\n        if(options.delay && angular.isString(options.delay)) {\n          var split = options.delay.split(',').map(parseFloat);\n          options.delay = split.length > 1 ? {show: split[0], hide: split[1]} : split[0];\n        }\n\n        // store $id to identify the triggering element in events\n        // give priority to options.id, otherwise, try to use\n        // element id if defined\n        $tooltip.$id = options.id || element.attr('id') || '';\n\n        // Support scope as string options\n        if(options.title) {\n          scope.title = $sce.trustAsHtml(options.title);\n        }\n\n        // Provide scope helpers\n        scope.$setEnabled = function(isEnabled) {\n          scope.$$postDigest(function() {\n            $tooltip.setEnabled(isEnabled);\n          });\n        };\n        scope.$hide = function() {\n          scope.$$postDigest(function() {\n            $tooltip.hide();\n          });\n        };\n        scope.$show = function() {\n          scope.$$postDigest(function() {\n            $tooltip.show();\n          });\n        };\n        scope.$toggle = function() {\n          scope.$$postDigest(function() {\n            $tooltip.toggle();\n          });\n        };\n        // Publish isShown as a protected var on scope\n        $tooltip.$isShown = scope.$isShown = false;\n\n        // Private vars\n        var timeout, hoverState;\n\n        // Support contentTemplate option\n        if(options.contentTemplate) {\n          $tooltip.$promise = $tooltip.$promise.then(function(template) {\n            var templateEl = angular.element(template);\n            return fetchTemplate(options.contentTemplate)\n            .then(function(contentTemplate) {\n              var contentEl = findElement('[ng-bind=\"content\"]', templateEl[0]);\n              if(!contentEl.length) contentEl = findElement('[ng-bind=\"title\"]', templateEl[0]);\n              contentEl.removeAttr('ng-bind').html(contentTemplate);\n              return templateEl[0].outerHTML;\n            });\n          });\n        }\n\n        // Fetch, compile then initialize tooltip\n        var tipLinker, tipElement, tipTemplate, tipContainer, tipScope;\n        $tooltip.$promise.then(function(template) {\n          if(angular.isObject(template)) template = template.data;\n          if(options.html) template = template.replace(htmlReplaceRegExp, 'ng-bind-html=\"');\n          template = trim.apply(template);\n          tipTemplate = template;\n          tipLinker = $compile(template);\n          $tooltip.init();\n        });\n\n        $tooltip.init = function() {\n\n          // Options: delay\n          if (options.delay && angular.isNumber(options.delay)) {\n            options.delay = {\n              show: options.delay,\n              hide: options.delay\n            };\n          }\n\n          // Replace trigger on touch devices ?\n          // if(isTouch && options.trigger === defaults.trigger) {\n          //   options.trigger.replace(/hover/g, 'click');\n          // }\n\n          // Options : container\n          if(options.container === 'self') {\n            tipContainer = element;\n          } else if(angular.isElement(options.container)) {\n            tipContainer = options.container;\n          } else if(options.container) {\n            tipContainer = findElement(options.container);\n          }\n\n          // Options: trigger\n          bindTriggerEvents();\n\n          // Options: target\n          if(options.target) {\n            options.target = angular.isElement(options.target) ? options.target : findElement(options.target);\n          }\n\n          // Options: show\n          if(options.show) {\n            scope.$$postDigest(function() {\n              options.trigger === 'focus' ? element[0].focus() : $tooltip.show();\n            });\n          }\n\n        };\n\n        $tooltip.destroy = function() {\n\n          // Unbind events\n          unbindTriggerEvents();\n\n          // Remove element\n          destroyTipElement();\n\n          // Destroy scope\n          scope.$destroy();\n\n        };\n\n        $tooltip.enter = function() {\n\n          clearTimeout(timeout);\n          hoverState = 'in';\n          if (!options.delay || !options.delay.show) {\n            return $tooltip.show();\n          }\n\n          timeout = setTimeout(function() {\n            if (hoverState ==='in') $tooltip.show();\n          }, options.delay.show);\n\n        };\n\n        $tooltip.show = function() {\n          if (!options.bsEnabled || $tooltip.$isShown) return;\n\n          scope.$emit(options.prefixEvent + '.show.before', $tooltip);\n          var parent, after;\n          if (options.container) {\n            parent = tipContainer;\n            if (tipContainer[0].lastChild) {\n              after = angular.element(tipContainer[0].lastChild);\n            } else {\n              after = null;\n            }\n          } else {\n            parent = null;\n            after = element;\n          }\n\n\n          // Hide any existing tipElement\n          if(tipElement) destroyTipElement();\n          // Fetch a cloned element linked from template\n          tipScope = $tooltip.$scope.$new();\n          tipElement = $tooltip.$element = tipLinker(tipScope, function(clonedElement, scope) {});\n\n          // Set the initial positioning.  Make the tooltip invisible\n          // so IE doesn't try to focus on it off screen.\n          tipElement.css({top: '-9999px', left: '-9999px', display: 'block', visibility: 'hidden'});\n\n          // Options: animation\n          if(options.animation) tipElement.addClass(options.animation);\n          // Options: type\n          if(options.type) tipElement.addClass(options.prefixClass + '-' + options.type);\n          // Options: custom classes\n          if(options.customClass) tipElement.addClass(options.customClass);\n\n          // Support v1.3+ $animate\n          // https://github.com/angular/angular.js/commit/bf0f5502b1bbfddc5cdd2f138efd9188b8c652a9\n          var promise = $animate.enter(tipElement, parent, after, enterAnimateCallback);\n          if(promise && promise.then) promise.then(enterAnimateCallback);\n\n          $tooltip.$isShown = scope.$isShown = true;\n          safeDigest(scope);\n          $$rAF(function () {\n            $tooltip.$applyPlacement();\n\n            // Once placed, make the tooltip visible\n            if(tipElement) tipElement.css({visibility: 'visible'});\n          }); // var a = bodyEl.offsetWidth + 1; ?\n\n          // Bind events\n          if(options.keyboard) {\n            if(options.trigger !== 'focus') {\n              $tooltip.focus();\n            }\n            bindKeyboardEvents();\n          }\n\n          if(options.autoClose) {\n            bindAutoCloseEvents();\n          }\n\n        };\n\n        function enterAnimateCallback() {\n          scope.$emit(options.prefixEvent + '.show', $tooltip);\n        }\n\n        $tooltip.leave = function() {\n\n          clearTimeout(timeout);\n          hoverState = 'out';\n          if (!options.delay || !options.delay.hide) {\n            return $tooltip.hide();\n          }\n          timeout = setTimeout(function () {\n            if (hoverState === 'out') {\n              $tooltip.hide();\n            }\n          }, options.delay.hide);\n\n        };\n\n        var _blur;\n        var _tipToHide;\n        $tooltip.hide = function(blur) {\n\n          if(!$tooltip.$isShown) return;\n          scope.$emit(options.prefixEvent + '.hide.before', $tooltip);\n\n          // store blur value for leaveAnimateCallback to use\n          _blur = blur;\n\n          // store current tipElement reference to use\n          // in leaveAnimateCallback\n          _tipToHide = tipElement;\n\n          // Support v1.3+ $animate\n          // https://github.com/angular/angular.js/commit/bf0f5502b1bbfddc5cdd2f138efd9188b8c652a9\n          var promise = $animate.leave(tipElement, leaveAnimateCallback);\n          if(promise && promise.then) promise.then(leaveAnimateCallback);\n\n          $tooltip.$isShown = scope.$isShown = false;\n          safeDigest(scope);\n\n          // Unbind events\n          if(options.keyboard && tipElement !== null) {\n            unbindKeyboardEvents();\n          }\n\n          if(options.autoClose && tipElement !== null) {\n            unbindAutoCloseEvents();\n          }\n        };\n\n        function leaveAnimateCallback() {\n          scope.$emit(options.prefixEvent + '.hide', $tooltip);\n\n          // check if current tipElement still references\n          // the same element when hide was called\n          if (tipElement === _tipToHide) {\n            // Allow to blur the input when hidden, like when pressing enter key\n            if(_blur && options.trigger === 'focus') {\n              return element[0].blur();\n            }\n\n            // clean up child scopes\n            destroyTipElement();\n          }\n        }\n\n        $tooltip.toggle = function() {\n          $tooltip.$isShown ? $tooltip.leave() : $tooltip.enter();\n        };\n\n        $tooltip.focus = function() {\n          tipElement[0].focus();\n        };\n\n        $tooltip.setEnabled = function(isEnabled) {\n          options.bsEnabled = isEnabled;\n        };\n\n        // Protected methods\n\n        $tooltip.$applyPlacement = function() {\n          if(!tipElement) return;\n\n          // Determine if we're doing an auto or normal placement\n          var placement = options.placement,\n              autoToken = /\\s?auto?\\s?/i,\n              autoPlace  = autoToken.test(placement);\n\n          if (autoPlace) {\n            placement = placement.replace(autoToken, '') || defaults.placement;\n          }\n\n          // Need to add the position class before we get\n          // the offsets\n          tipElement.addClass(options.placement);\n\n          // Get the position of the target element\n          // and the height and width of the tooltip so we can center it.\n          var elementPosition = getPosition(),\n              tipWidth = tipElement.prop('offsetWidth'),\n              tipHeight = tipElement.prop('offsetHeight');\n\n          // If we're auto placing, we need to check the positioning\n          if (autoPlace) {\n            var originalPlacement = placement;\n            var container = options.container ? angular.element(document.querySelector(options.container)) : element.parent();\n            var containerPosition = getPosition(container);\n\n            // Determine if the vertical placement\n            if (originalPlacement.indexOf('bottom') >= 0 && elementPosition.bottom + tipHeight > containerPosition.bottom) {\n              placement = originalPlacement.replace('bottom', 'top');\n            } else if (originalPlacement.indexOf('top') >= 0 && elementPosition.top - tipHeight < containerPosition.top) {\n              placement = originalPlacement.replace('top', 'bottom');\n            }\n\n            // Determine the horizontal placement\n            // The exotic placements of left and right are opposite of the standard placements.  Their arrows are put on the left/right\n            // and flow in the opposite direction of their placement.\n            if ((originalPlacement === 'right' || originalPlacement === 'bottom-left' || originalPlacement === 'top-left') &&\n                elementPosition.right + tipWidth > containerPosition.width) {\n\n              placement = originalPlacement === 'right' ? 'left' : placement.replace('left', 'right');\n            } else if ((originalPlacement === 'left' || originalPlacement === 'bottom-right' || originalPlacement === 'top-right') &&\n                elementPosition.left - tipWidth < containerPosition.left) {\n\n              placement = originalPlacement === 'left' ? 'right' : placement.replace('right', 'left');\n            }\n\n            tipElement.removeClass(originalPlacement).addClass(placement);\n          }\n\n          // Get the tooltip's top and left coordinates to center it with this directive.\n          var tipPosition = getCalculatedOffset(placement, elementPosition, tipWidth, tipHeight);\n          applyPlacementCss(tipPosition.top, tipPosition.left);\n        };\n\n        $tooltip.$onKeyUp = function(evt) {\n          if (evt.which === 27 && $tooltip.$isShown) {\n            $tooltip.hide();\n            evt.stopPropagation();\n          }\n        };\n\n        $tooltip.$onFocusKeyUp = function(evt) {\n          if (evt.which === 27) {\n            element[0].blur();\n            evt.stopPropagation();\n          }\n        };\n\n        $tooltip.$onFocusElementMouseDown = function(evt) {\n          evt.preventDefault();\n          evt.stopPropagation();\n          // Some browsers do not auto-focus buttons (eg. Safari)\n          $tooltip.$isShown ? element[0].blur() : element[0].focus();\n        };\n\n        // bind/unbind events\n        function bindTriggerEvents() {\n          var triggers = options.trigger.split(' ');\n          angular.forEach(triggers, function(trigger) {\n            if(trigger === 'click') {\n              element.on('click', $tooltip.toggle);\n            } else if(trigger !== 'manual') {\n              element.on(trigger === 'hover' ? 'mouseenter' : 'focus', $tooltip.enter);\n              element.on(trigger === 'hover' ? 'mouseleave' : 'blur', $tooltip.leave);\n              nodeName === 'button' && trigger !== 'hover' && element.on(isTouch ? 'touchstart' : 'mousedown', $tooltip.$onFocusElementMouseDown);\n            }\n          });\n        }\n\n        function unbindTriggerEvents() {\n          var triggers = options.trigger.split(' ');\n          for (var i = triggers.length; i--;) {\n            var trigger = triggers[i];\n            if(trigger === 'click') {\n              element.off('click', $tooltip.toggle);\n            } else if(trigger !== 'manual') {\n              element.off(trigger === 'hover' ? 'mouseenter' : 'focus', $tooltip.enter);\n              element.off(trigger === 'hover' ? 'mouseleave' : 'blur', $tooltip.leave);\n              nodeName === 'button' && trigger !== 'hover' && element.off(isTouch ? 'touchstart' : 'mousedown', $tooltip.$onFocusElementMouseDown);\n            }\n          }\n        }\n\n        function bindKeyboardEvents() {\n          if(options.trigger !== 'focus') {\n            tipElement.on('keyup', $tooltip.$onKeyUp);\n          } else {\n            element.on('keyup', $tooltip.$onFocusKeyUp);\n          }\n        }\n\n        function unbindKeyboardEvents() {\n          if(options.trigger !== 'focus') {\n            tipElement.off('keyup', $tooltip.$onKeyUp);\n          } else {\n            element.off('keyup', $tooltip.$onFocusKeyUp);\n          }\n        }\n\n        var _autoCloseEventsBinded = false;\n        function bindAutoCloseEvents() {\n          // use timeout to hookup the events to prevent\n          // event bubbling from being processed imediately.\n          $timeout(function() {\n            // Stop propagation when clicking inside tooltip\n            tipElement.on('click', stopEventPropagation);\n\n            // Hide when clicking outside tooltip\n            $body.on('click', $tooltip.hide);\n\n            _autoCloseEventsBinded = true;\n          }, 0, false);\n        }\n\n        function unbindAutoCloseEvents() {\n          if (_autoCloseEventsBinded) {\n            tipElement.off('click', stopEventPropagation);\n            $body.off('click', $tooltip.hide);\n            _autoCloseEventsBinded = false;\n          }\n        }\n\n        function stopEventPropagation(event) {\n          event.stopPropagation();\n        }\n\n        // Private methods\n\n        function getPosition($element) {\n          $element = $element || (options.target || element);\n\n          var el = $element[0];\n\n          var elRect = el.getBoundingClientRect();\n          if (elRect.width === null) {\n            // width and height are missing in IE8, so compute them manually; see https://github.com/twbs/bootstrap/issues/14093\n            elRect = angular.extend({}, elRect, { width: elRect.right - elRect.left, height: elRect.bottom - elRect.top });\n          }\n\n          var elPos;\n          if (options.container === 'body') {\n            elPos = dimensions.offset(el);\n          } else {\n            elPos = dimensions.position(el);\n          }\n\n          return angular.extend({}, elRect, elPos);\n        }\n\n        function getCalculatedOffset(placement, position, actualWidth, actualHeight) {\n          var offset;\n          var split = placement.split('-');\n\n          switch (split[0]) {\n          case 'right':\n            offset = {\n              top: position.top + position.height / 2 - actualHeight / 2,\n              left: position.left + position.width\n            };\n            break;\n          case 'bottom':\n            offset = {\n              top: position.top + position.height,\n              left: position.left + position.width / 2 - actualWidth / 2\n            };\n            break;\n          case 'left':\n            offset = {\n              top: position.top + position.height / 2 - actualHeight / 2,\n              left: position.left - actualWidth\n            };\n            break;\n          default:\n            offset = {\n              top: position.top - actualHeight,\n              left: position.left + position.width / 2 - actualWidth / 2\n            };\n            break;\n          }\n\n          if(!split[1]) {\n            return offset;\n          }\n\n          // Add support for corners @todo css\n          if(split[0] === 'top' || split[0] === 'bottom') {\n            switch (split[1]) {\n            case 'left':\n              offset.left = position.left;\n              break;\n            case 'right':\n              offset.left =  position.left + position.width - actualWidth;\n            }\n          } else if(split[0] === 'left' || split[0] === 'right') {\n            switch (split[1]) {\n            case 'top':\n              offset.top = position.top - actualHeight;\n              break;\n            case 'bottom':\n              offset.top = position.top + position.height;\n            }\n          }\n\n          return offset;\n        }\n\n        function applyPlacementCss(top, left) {\n          tipElement.css({ top: top + 'px', left: left + 'px' });\n        }\n\n        function destroyTipElement() {\n          // Cancel pending callbacks\n          clearTimeout(timeout);\n\n          if($tooltip.$isShown && tipElement !== null) {\n            if(options.autoClose) {\n              unbindAutoCloseEvents();\n            }\n\n            if(options.keyboard) {\n              unbindKeyboardEvents();\n            }\n          }\n\n          if(tipScope) {\n            tipScope.$destroy();\n            tipScope = null;\n          }\n\n          if(tipElement) {\n            tipElement.remove();\n            tipElement = $tooltip.$element = null;\n          }\n        }\n\n        return $tooltip;\n\n      }\n\n      // Helper functions\n\n      function safeDigest(scope) {\n        scope.$$phase || (scope.$root && scope.$root.$$phase) || scope.$digest();\n      }\n\n      function findElement(query, element) {\n        return angular.element((element || document).querySelectorAll(query));\n      }\n\n      var fetchPromises = {};\n      function fetchTemplate(template) {\n        if(fetchPromises[template]) return fetchPromises[template];\n        return (fetchPromises[template] = $q.when($templateCache.get(template) || $http.get(template))\n        .then(function(res) {\n          if(angular.isObject(res)) {\n            $templateCache.put(template, res.data);\n            return res.data;\n          }\n          return res;\n        }));\n      }\n\n      return TooltipFactory;\n\n    }];\n\n  })\n\n  .directive('bsTooltip', [\"$window\", \"$location\", \"$sce\", \"$tooltip\", \"$$rAF\", function($window, $location, $sce, $tooltip, $$rAF) {\n\n    return {\n      restrict: 'EAC',\n      scope: true,\n      link: function postLink(scope, element, attr, transclusion) {\n\n        // Directive options\n        var options = {scope: scope};\n        angular.forEach(['template', 'contentTemplate', 'placement', 'container', 'target', 'delay', 'trigger', 'keyboard', 'html', 'animation', 'backdropAnimation', 'type', 'customClass', 'id'], function(key) {\n          if(angular.isDefined(attr[key])) options[key] = attr[key];\n        });\n\n        // overwrite inherited title value when no value specified\n        // fix for angular 1.3.1 531a8de72c439d8ddd064874bf364c00cedabb11\n        if (!scope.hasOwnProperty('title')){\n          scope.title = '';\n        }\n\n        // Observe scope attributes for change\n        attr.$observe('title', function(newValue) {\n          if (angular.isDefined(newValue) || !scope.hasOwnProperty('title')) {\n            var oldValue = scope.title;\n            scope.title = $sce.trustAsHtml(newValue);\n            angular.isDefined(oldValue) && $$rAF(function() {\n              tooltip && tooltip.$applyPlacement();\n            });\n          }\n        });\n\n        // Support scope as an object\n        attr.bsTooltip && scope.$watch(attr.bsTooltip, function(newValue, oldValue) {\n          if(angular.isObject(newValue)) {\n            angular.extend(scope, newValue);\n          } else {\n            scope.title = newValue;\n          }\n          angular.isDefined(oldValue) && $$rAF(function() {\n            tooltip && tooltip.$applyPlacement();\n          });\n        }, true);\n\n        // Visibility binding support\n        attr.bsShow && scope.$watch(attr.bsShow, function(newValue, oldValue) {\n          if(!tooltip || !angular.isDefined(newValue)) return;\n          if(angular.isString(newValue)) newValue = !!newValue.match(/true|,?(tooltip),?/i);\n          newValue === true ? tooltip.show() : tooltip.hide();\n        });\n\n        // Enabled binding support\n        attr.bsEnabled && scope.$watch(attr.bsEnabled, function(newValue, oldValue) {\n          // console.warn('scope.$watch(%s)', attr.bsEnabled, newValue, oldValue);\n          if(!tooltip || !angular.isDefined(newValue)) return;\n          if(angular.isString(newValue)) newValue = !!newValue.match(/true|1|,?(tooltip),?/i);\n          newValue === false ? tooltip.setEnabled(false) : tooltip.setEnabled(true);\n        });\n\n        // Initialize popover\n        var tooltip = $tooltip(element, options);\n\n        // Garbage collection\n        scope.$on('$destroy', function() {\n          if(tooltip) tooltip.destroy();\n          options = null;\n          tooltip = null;\n        });\n\n      }\n    };\n\n  }]);\n\n// Source: typeahead.js\nangular.module('mgcrea.ngStrap.typeahead', ['mgcrea.ngStrap.tooltip', 'mgcrea.ngStrap.helpers.parseOptions'])\n\n  .provider('$typeahead', function() {\n\n    var defaults = this.defaults = {\n      animation: 'am-fade',\n      prefixClass: 'typeahead',\n      prefixEvent: '$typeahead',\n      placement: 'bottom-left',\n      template: 'typeahead/typeahead.tpl.html',\n      trigger: 'focus',\n      container: false,\n      keyboard: true,\n      html: false,\n      delay: 0,\n      minLength: 1,\n      filter: 'filter',\n      limit: 6,\n      comparator: ''\n    };\n\n    this.$get = [\"$window\", \"$rootScope\", \"$tooltip\", \"$timeout\", function($window, $rootScope, $tooltip, $timeout) {\n\n      var bodyEl = angular.element($window.document.body);\n\n      function TypeaheadFactory(element, controller, config) {\n\n        var $typeahead = {};\n\n        // Common vars\n        var options = angular.extend({}, defaults, config);\n\n        $typeahead = $tooltip(element, options);\n        var parentScope = config.scope;\n        var scope = $typeahead.$scope;\n\n        scope.$resetMatches = function(){\n          scope.$matches = [];\n          scope.$activeIndex = 0;\n        };\n        scope.$resetMatches();\n\n        scope.$activate = function(index) {\n          scope.$$postDigest(function() {\n            $typeahead.activate(index);\n          });\n        };\n\n        scope.$select = function(index, evt) {\n          scope.$$postDigest(function() {\n            $typeahead.select(index);\n          });\n        };\n\n        scope.$isVisible = function() {\n          return $typeahead.$isVisible();\n        };\n\n        // Public methods\n\n        $typeahead.update = function(matches) {\n          scope.$matches = matches;\n          if(scope.$activeIndex >= matches.length) {\n            scope.$activeIndex = 0;\n          }\n        };\n\n        $typeahead.activate = function(index) {\n          scope.$activeIndex = index;\n        };\n\n        $typeahead.select = function(index) {\n          var value = scope.$matches[index].value;\n          // console.log('$setViewValue', value);\n          controller.$setViewValue(value);\n          controller.$render();\n          scope.$resetMatches();\n          if(parentScope) parentScope.$digest();\n          // Emit event\n          scope.$emit(options.prefixEvent + '.select', value, index, $typeahead);\n        };\n\n        // Protected methods\n\n        $typeahead.$isVisible = function() {\n          if(!options.minLength || !controller) {\n            return !!scope.$matches.length;\n          }\n          // minLength support\n          return scope.$matches.length && angular.isString(controller.$viewValue) && controller.$viewValue.length >= options.minLength;\n        };\n\n        $typeahead.$getIndex = function(value) {\n          var l = scope.$matches.length, i = l;\n          if(!l) return;\n          for(i = l; i--;) {\n            if(scope.$matches[i].value === value) break;\n          }\n          if(i < 0) return;\n          return i;\n        };\n\n        $typeahead.$onMouseDown = function(evt) {\n          // Prevent blur on mousedown\n          evt.preventDefault();\n          evt.stopPropagation();\n        };\n\n        $typeahead.$onKeyDown = function(evt) {\n          if(!/(38|40|13)/.test(evt.keyCode)) return;\n\n          // Let ngSubmit pass if the typeahead tip is hidden\n          if($typeahead.$isVisible()) {\n            evt.preventDefault();\n            evt.stopPropagation();\n          }\n\n          // Select with enter\n          if(evt.keyCode === 13 && scope.$matches.length) {\n            $typeahead.select(scope.$activeIndex);\n          }\n\n          // Navigate with keyboard\n          else if(evt.keyCode === 38 && scope.$activeIndex > 0) scope.$activeIndex--;\n          else if(evt.keyCode === 40 && scope.$activeIndex < scope.$matches.length - 1) scope.$activeIndex++;\n          else if(angular.isUndefined(scope.$activeIndex)) scope.$activeIndex = 0;\n          scope.$digest();\n        };\n\n        // Overrides\n\n        var show = $typeahead.show;\n        $typeahead.show = function() {\n          show();\n          // use timeout to hookup the events to prevent\n          // event bubbling from being processed imediately.\n          $timeout(function() {\n            $typeahead.$element.on('mousedown', $typeahead.$onMouseDown);\n            if(options.keyboard) {\n              element.on('keydown', $typeahead.$onKeyDown);\n            }\n          }, 0, false);\n        };\n\n        var hide = $typeahead.hide;\n        $typeahead.hide = function() {\n          $typeahead.$element.off('mousedown', $typeahead.$onMouseDown);\n          if(options.keyboard) {\n            element.off('keydown', $typeahead.$onKeyDown);\n          }\n          hide();\n        };\n\n        return $typeahead;\n\n      }\n\n      TypeaheadFactory.defaults = defaults;\n      return TypeaheadFactory;\n\n    }];\n\n  })\n\n  .directive('bsTypeahead', [\"$window\", \"$parse\", \"$q\", \"$typeahead\", \"$parseOptions\", function($window, $parse, $q, $typeahead, $parseOptions) {\n\n    var defaults = $typeahead.defaults;\n\n    return {\n      restrict: 'EAC',\n      require: 'ngModel',\n      link: function postLink(scope, element, attr, controller) {\n\n        // Directive options\n        var options = {scope: scope};\n        angular.forEach(['placement', 'container', 'delay', 'trigger', 'keyboard', 'html', 'animation', 'template', 'filter', 'limit', 'minLength', 'watchOptions', 'selectMode', 'comparator', 'id'], function(key) {\n          if(angular.isDefined(attr[key])) options[key] = attr[key];\n        });\n\n        // Build proper ngOptions\n        var filter = options.filter || defaults.filter;\n        var limit = options.limit || defaults.limit;\n        var comparator = options.comparator || defaults.comparator;\n\n        var ngOptions = attr.ngOptions;\n        if(filter) ngOptions += ' | ' + filter + ':$viewValue';\n        if (comparator) ngOptions += ':' + comparator;\n        if(limit) ngOptions += ' | limitTo:' + limit;\n        var parsedOptions = $parseOptions(ngOptions);\n\n        // Initialize typeahead\n        var typeahead = $typeahead(element, controller, options);\n\n        // Watch options on demand\n        if(options.watchOptions) {\n          // Watch ngOptions values before filtering for changes, drop function calls\n          var watchedOptions = parsedOptions.$match[7].replace(/\\|.+/, '').replace(/\\(.*\\)/g, '').trim();\n          scope.$watch(watchedOptions, function (newValue, oldValue) {\n            // console.warn('scope.$watch(%s)', watchedOptions, newValue, oldValue);\n            parsedOptions.valuesFn(scope, controller).then(function (values) {\n              typeahead.update(values);\n              controller.$render();\n            });\n          }, true);\n        }\n\n        // Watch model for changes\n        scope.$watch(attr.ngModel, function(newValue, oldValue) {\n          // console.warn('$watch', element.attr('ng-model'), newValue);\n          scope.$modelValue = newValue; // Publish modelValue on scope for custom templates\n          parsedOptions.valuesFn(scope, controller)\n          .then(function(values) {\n            // Prevent input with no future prospect if selectMode is truthy\n            // @TODO test selectMode\n            if(options.selectMode && !values.length && newValue.length > 0) {\n              controller.$setViewValue(controller.$viewValue.substring(0, controller.$viewValue.length - 1));\n              return;\n            }\n            if(values.length > limit) values = values.slice(0, limit);\n            var isVisible = typeahead.$isVisible();\n            isVisible && typeahead.update(values);\n            // Do not re-queue an update if a correct value has been selected\n            if(values.length === 1 && values[0].value === newValue) return;\n            !isVisible && typeahead.update(values);\n            // Queue a new rendering that will leverage collection loading\n            controller.$render();\n          });\n        });\n\n        // modelValue -> $formatters -> viewValue\n        controller.$formatters.push(function(modelValue) {\n          // console.warn('$formatter(\"%s\"): modelValue=%o (%o)', element.attr('ng-model'), modelValue, typeof modelValue);\n          var displayValue = parsedOptions.displayValue(modelValue);\n          return displayValue === undefined ? '' : displayValue;\n        });\n\n        // Model rendering in view\n        controller.$render = function () {\n          // console.warn('$render', element.attr('ng-model'), 'controller.$modelValue', typeof controller.$modelValue, controller.$modelValue, 'controller.$viewValue', typeof controller.$viewValue, controller.$viewValue);\n          if(controller.$isEmpty(controller.$viewValue)) return element.val('');\n          var index = typeahead.$getIndex(controller.$modelValue);\n          var selected = angular.isDefined(index) ? typeahead.$scope.$matches[index].label : controller.$viewValue;\n          selected = angular.isObject(selected) ? parsedOptions.displayValue(selected) : selected;\n          element.val(selected ? selected.toString().replace(/<(?:.|\\n)*?>/gm, '').trim() : '');\n        };\n\n        // Garbage collection\n        scope.$on('$destroy', function() {\n          if (typeahead) typeahead.destroy();\n          options = null;\n          typeahead = null;\n        });\n\n      }\n    };\n\n  }]);\n\n})(window, document);\n"
  },
  {
    "path": "flowable-ui-web/task/libs/angular-strap_2.1.6/angular-strap.tpl.js",
    "content": "/**\n * angular-strap\n * @version v2.1.6 - 2015-01-11\n * @link http://mgcrea.github.io/angular-strap\n * @author Olivier Louvignes (olivier@mg-crea.com)\n * @license MIT License, http://www.opensource.org/licenses/MIT\n */\n(function(window, document, undefined) {\n'use strict';\n\n// Source: alert.tpl.js\nangular.module('mgcrea.ngStrap.alert').run(['$templateCache', function($templateCache) {\n\n  $templateCache.put('alert/alert.tpl.html', '<div class=\"alert\" ng-class=\"[type ? \\'alert-\\' + type : null]\"><button type=\"button\" class=\"close\" ng-if=\"dismissable\" ng-click=\"$hide()\">&times;</button> <strong ng-bind=\"title\"></strong>&nbsp;<span ng-bind-html=\"content\"></span></div>');\n\n}]);\n\n// Source: aside.tpl.js\nangular.module('mgcrea.ngStrap.aside').run(['$templateCache', function($templateCache) {\n\n  $templateCache.put('aside/aside.tpl.html', '<div class=\"aside\" tabindex=\"-1\" role=\"dialog\"><div class=\"aside-dialog\"><div class=\"aside-content\"><div class=\"aside-header\" ng-show=\"title\"><button type=\"button\" class=\"close\" ng-click=\"$hide()\">&times;</button><h4 class=\"aside-title\" ng-bind=\"title\"></h4></div><div class=\"aside-body\" ng-bind=\"content\"></div><div class=\"aside-footer\"><button type=\"button\" class=\"btn btn-default\" ng-click=\"$hide()\">Close</button></div></div></div></div>');\n\n}]);\n\n// Source: datepicker.tpl.js\nangular.module('mgcrea.ngStrap.datepicker').run(['$templateCache', function($templateCache) {\n\n  $templateCache.put('datepicker/datepicker.tpl.html', '<div class=\"dropdown-menu datepicker\" ng-class=\"\\'datepicker-mode-\\' + $mode\" style=\"max-width: 320px\"><table style=\"table-layout: fixed; height: 100%; width: 100%\"><thead><tr class=\"text-center\"><th><button tabindex=\"-1\" type=\"button\" class=\"btn btn-default pull-left\" ng-click=\"$selectPane(-1)\"><i class=\"{{$iconLeft}}\"></i></button></th><th colspan=\"{{ rows[0].length - 2 }}\"><button tabindex=\"-1\" type=\"button\" class=\"btn btn-default btn-block text-strong\" ng-click=\"$toggleMode()\"><strong style=\"text-transform: capitalize\" ng-bind=\"title\"></strong></button></th><th><button tabindex=\"-1\" type=\"button\" class=\"btn btn-default pull-right\" ng-click=\"$selectPane(+1)\"><i class=\"{{$iconRight}}\"></i></button></th></tr><tr ng-show=\"showLabels\" ng-bind-html=\"labels\"></tr></thead><tbody><tr ng-repeat=\"(i, row) in rows\" height=\"{{ 100 / rows.length }}%\"><td class=\"text-center\" ng-repeat=\"(j, el) in row\"><button tabindex=\"-1\" type=\"button\" class=\"btn btn-default\" style=\"width: 100%\" ng-class=\"{\\'btn-primary\\': el.selected, \\'btn-info btn-today\\': el.isToday && !el.selected}\" ng-click=\"$select(el.date)\" ng-disabled=\"el.disabled\"><span ng-class=\"{\\'text-muted\\': el.muted}\" ng-bind=\"el.label\"></span></button></td></tr></tbody></table></div>');\n\n}]);\n\n// Source: dropdown.tpl.js\nangular.module('mgcrea.ngStrap.dropdown').run(['$templateCache', function($templateCache) {\n\n  $templateCache.put('dropdown/dropdown.tpl.html', '<ul tabindex=\"-1\" class=\"dropdown-menu\" role=\"menu\"><li role=\"presentation\" ng-class=\"{divider: item.divider}\" ng-repeat=\"item in content\"><a role=\"menuitem\" tabindex=\"-1\" ng-href=\"{{item.href}}\" ng-if=\"!item.divider && item.href\" target=\"{{item.target || \\'\\'}}\" ng-bind=\"item.text\"></a> <a role=\"menuitem\" tabindex=\"-1\" href=\"javascript:void(0)\" ng-if=\"!item.divider && item.click\" ng-click=\"$eval(item.click);$hide()\" ng-bind=\"item.text\"></a></li></ul>');\n\n}]);\n\n// Source: modal.tpl.js\nangular.module('mgcrea.ngStrap.modal').run(['$templateCache', function($templateCache) {\n\n  $templateCache.put('modal/modal.tpl.html', '<div class=\"modal\" tabindex=\"-1\" role=\"dialog\"><div class=\"modal-dialog\"><div class=\"modal-content\"><div class=\"modal-header\" ng-show=\"title\"><button type=\"button\" class=\"close\" ng-click=\"$hide()\">&times;</button><h4 class=\"modal-title\" ng-bind=\"title\"></h4></div><div class=\"modal-body\" ng-bind=\"content\"></div><div class=\"modal-footer\"><button type=\"button\" class=\"btn btn-default\" ng-click=\"$hide()\">Close</button></div></div></div></div>');\n\n}]);\n\n// Source: popover.tpl.js\nangular.module('mgcrea.ngStrap.popover').run(['$templateCache', function($templateCache) {\n\n  $templateCache.put('popover/popover.tpl.html', '<div class=\"popover\"><div class=\"arrow\"></div><h3 class=\"popover-title\" ng-bind=\"title\" ng-show=\"title\"></h3><div class=\"popover-content\" ng-bind=\"content\"></div></div>');\n\n}]);\n\n// Source: select.tpl.js\nangular.module('mgcrea.ngStrap.select').run(['$templateCache', function($templateCache) {\n\n  $templateCache.put('select/select.tpl.html', '<ul tabindex=\"-1\" class=\"select dropdown-menu\" ng-show=\"$isVisible()\" role=\"select\"><li ng-if=\"$showAllNoneButtons\"><div class=\"btn-group\" style=\"margin-bottom: 5px; margin-left: 5px\"><button type=\"button\" class=\"btn btn-default btn-xs\" ng-click=\"$selectAll()\">{{$allText}}</button> <button type=\"button\" class=\"btn btn-default btn-xs\" ng-click=\"$selectNone()\">{{$noneText}}</button></div></li><li role=\"presentation\" ng-repeat=\"match in $matches\" ng-class=\"{active: $isActive($index)}\"><a style=\"cursor: default\" role=\"menuitem\" tabindex=\"-1\" ng-click=\"$select($index, $event)\"><i class=\"{{$iconCheckmark}} pull-right\" ng-if=\"$isMultiple && $isActive($index)\"></i> <span ng-bind=\"match.label\"></span></a></li></ul>');\n\n}]);\n\n// Source: tab.tpl.js\nangular.module('mgcrea.ngStrap.tab').run(['$templateCache', function($templateCache) {\n\n  $templateCache.put('tab/tab.tpl.html', '<ul class=\"nav\" ng-class=\"$navClass\" role=\"tablist\"><li ng-repeat=\"$pane in $panes track by $index\" ng-class=\"$index == $panes.$active ? $activeClass : \\'\\'\"><a role=\"tab\" data-toggle=\"tab\" ng-click=\"$setActive($index)\" data-index=\"{{ $index }}\" ng-bind-html=\"$pane.title\"></a></li></ul><div ng-transclude class=\"tab-content\"></div>');\n\n}]);\n\n// Source: timepicker.tpl.js\nangular.module('mgcrea.ngStrap.timepicker').run(['$templateCache', function($templateCache) {\n\n  $templateCache.put('timepicker/timepicker.tpl.html', '<div class=\"dropdown-menu timepicker\" style=\"min-width: 0px;width: auto\"><table height=\"100%\"><thead><tr class=\"text-center\"><th><button tabindex=\"-1\" type=\"button\" class=\"btn btn-default pull-left\" ng-click=\"$arrowAction(-1, 0)\"><i class=\"{{ $iconUp }}\"></i></button></th><th>&nbsp;</th><th><button tabindex=\"-1\" type=\"button\" class=\"btn btn-default pull-left\" ng-click=\"$arrowAction(-1, 1)\"><i class=\"{{ $iconUp }}\"></i></button></th></tr></thead><tbody><tr ng-repeat=\"(i, row) in rows\"><td class=\"text-center\"><button tabindex=\"-1\" style=\"width: 100%\" type=\"button\" class=\"btn btn-default\" ng-class=\"{\\'btn-primary\\': row[0].selected}\" ng-click=\"$select(row[0].date, 0)\" ng-disabled=\"row[0].disabled\"><span ng-class=\"{\\'text-muted\\': row[0].muted}\" ng-bind=\"row[0].label\"></span></button></td><td><span ng-bind=\"i == midIndex ? timeSeparator : \\' \\'\"></span></td><td class=\"text-center\"><button tabindex=\"-1\" ng-if=\"row[1].date\" style=\"width: 100%\" type=\"button\" class=\"btn btn-default\" ng-class=\"{\\'btn-primary\\': row[1].selected}\" ng-click=\"$select(row[1].date, 1)\" ng-disabled=\"row[1].disabled\"><span ng-class=\"{\\'text-muted\\': row[1].muted}\" ng-bind=\"row[1].label\"></span></button></td><td ng-if=\"showAM\">&nbsp;</td><td ng-if=\"showAM\"><button tabindex=\"-1\" ng-show=\"i == midIndex - !isAM * 1\" style=\"width: 100%\" type=\"button\" ng-class=\"{\\'btn-primary\\': !!isAM}\" class=\"btn btn-default\" ng-click=\"$switchMeridian()\" ng-disabled=\"el.disabled\">AM</button> <button tabindex=\"-1\" ng-show=\"i == midIndex + 1 - !isAM * 1\" style=\"width: 100%\" type=\"button\" ng-class=\"{\\'btn-primary\\': !isAM}\" class=\"btn btn-default\" ng-click=\"$switchMeridian()\" ng-disabled=\"el.disabled\">PM</button></td></tr></tbody><tfoot><tr class=\"text-center\"><th><button tabindex=\"-1\" type=\"button\" class=\"btn btn-default pull-left\" ng-click=\"$arrowAction(1, 0)\"><i class=\"{{ $iconDown }}\"></i></button></th><th>&nbsp;</th><th><button tabindex=\"-1\" type=\"button\" class=\"btn btn-default pull-left\" ng-click=\"$arrowAction(1, 1)\"><i class=\"{{ $iconDown }}\"></i></button></th></tr></tfoot></table></div>');\n\n}]);\n\n// Source: tooltip.tpl.js\nangular.module('mgcrea.ngStrap.tooltip').run(['$templateCache', function($templateCache) {\n\n  $templateCache.put('tooltip/tooltip.tpl.html', '<div class=\"tooltip in\" ng-show=\"title\"><div class=\"tooltip-arrow\"></div><div class=\"tooltip-inner\" ng-bind=\"title\"></div></div>');\n\n}]);\n\n// Source: typeahead.tpl.js\nangular.module('mgcrea.ngStrap.typeahead').run(['$templateCache', function($templateCache) {\n\n  $templateCache.put('typeahead/typeahead.tpl.html', '<ul tabindex=\"-1\" class=\"typeahead dropdown-menu\" ng-show=\"$isVisible()\" role=\"select\"><li role=\"presentation\" ng-repeat=\"match in $matches\" ng-class=\"{active: $index == $activeIndex}\"><a role=\"menuitem\" tabindex=\"-1\" ng-click=\"$select($index, $event)\" ng-bind=\"match.label\"></a></li></ul>');\n\n}]);\n\n\n})(window, document);\n"
  },
  {
    "path": "flowable-ui-web/task/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": "flowable-ui-web/task/libs/angular-translate-loader-static-files/angular-translate-loader-static-files.js",
    "content": "/*!\n * angular-translate - v2.15.1 - 2017-03-04\n * \n * Copyright (c) 2017 The angular-translate team, Pascal Precht; Licensed MIT\n */\n(function (root, factory) {\n  if (typeof define === 'function' && define.amd) {\n    // AMD. Register as an anonymous module unless amdModuleId is set\n    define([], function () {\n      return (factory());\n    });\n  } else if (typeof exports === 'object') {\n    // Node. Does not work with strict CommonJS, but\n    // only CommonJS-like environments that support module.exports,\n    // like Node.\n    module.exports = factory();\n  } else {\n    factory();\n  }\n}(this, function () {\n\n$translateStaticFilesLoader.$inject = ['$q', '$http'];\nangular.module('pascalprecht.translate')\n/**\n * @ngdoc object\n * @name pascalprecht.translate.$translateStaticFilesLoader\n * @requires $q\n * @requires $http\n *\n * @description\n * Creates a loading function for a typical static file url pattern:\n * \"lang-en_US.json\", \"lang-de_DE.json\", etc. Using this builder,\n * the response of these urls must be an object of key-value pairs.\n *\n * @param {object} options Options object, which gets prefix, suffix, key, and fileMap\n */\n.factory('$translateStaticFilesLoader', $translateStaticFilesLoader);\n\nfunction $translateStaticFilesLoader($q, $http) {\n\n  'use strict';\n\n  return function (options) {\n\n    if (!options || (!angular.isArray(options.files) && (!angular.isString(options.prefix) || !angular.isString(options.suffix)))) {\n      throw new Error('Couldn\\'t load static files, no files and prefix or suffix specified!');\n    }\n\n    if (!options.files) {\n      options.files = [{\n        prefix: options.prefix,\n        suffix: options.suffix\n      }];\n    }\n\n    var load = function (file) {\n      if (!file || (!angular.isString(file.prefix) || !angular.isString(file.suffix))) {\n        throw new Error('Couldn\\'t load static file, no prefix or suffix specified!');\n      }\n\n      var fileUrl = [\n        file.prefix,\n        options.key,\n        file.suffix\n      ].join('');\n\n      if (angular.isObject(options.fileMap) && options.fileMap[fileUrl]) {\n        fileUrl = options.fileMap[fileUrl];\n      }\n\n      return $http(angular.extend({\n        url: fileUrl,\n        method: 'GET'\n      }, options.$http))\n        .then(function(result) {\n          return result.data;\n        }, function () {\n          return $q.reject(options.key);\n        });\n    };\n\n    var promises = [],\n        length = options.files.length;\n\n    for (var i = 0; i < length; i++) {\n      promises.push(load({\n        prefix: options.files[i].prefix,\n        key: options.key,\n        suffix: options.files[i].suffix\n      }));\n    }\n\n    return $q.all(promises)\n      .then(function (data) {\n        var length = data.length,\n            mergedData = {};\n\n        for (var i = 0; i < length; i++) {\n          for (var key in data[i]) {\n            mergedData[key] = data[i][key];\n          }\n        }\n\n        return mergedData;\n      });\n  };\n}\n\n$translateStaticFilesLoader.displayName = '$translateStaticFilesLoader';\nreturn 'pascalprecht.translate';\n\n}));\n"
  },
  {
    "path": "flowable-ui-web/task/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": "flowable-ui-web/task/libs/angular-translate-storage-cookie/angular-translate-storage-cookie.js",
    "content": "/*!\n * angular-translate - v2.15.1 - 2017-03-04\n * \n * Copyright (c) 2017 The angular-translate team, Pascal Precht; Licensed MIT\n */\n(function (root, factory) {\n  if (typeof define === 'function' && define.amd) {\n    // AMD. Register as an anonymous module unless amdModuleId is set\n    define([], function () {\n      return (factory());\n    });\n  } else if (typeof exports === 'object') {\n    // Node. Does not work with strict CommonJS, but\n    // only CommonJS-like environments that support module.exports,\n    // like Node.\n    module.exports = factory();\n  } else {\n    factory();\n  }\n}(this, function () {\n\n$translateCookieStorageFactory.$inject = ['$injector'];\nangular.module('pascalprecht.translate')\n\n/**\n * @ngdoc object\n * @name pascalprecht.translate.$translateCookieStorage\n * @requires $cookieStore\n *\n * @description\n * Abstraction layer for cookieStore. This service is used when telling angular-translate\n * to use cookieStore as storage.\n *\n */\n  .factory('$translateCookieStorage', $translateCookieStorageFactory);\n\nfunction $translateCookieStorageFactory($injector) {\n\n  'use strict';\n\n  // Since AngularJS 1.4, $cookieStore is deprecated\n  var delegate;\n  if (angular.version.major === 1 && angular.version.minor >= 4) {\n    var $cookies = $injector.get('$cookies');\n    delegate = {\n      get : function (key) {\n        return $cookies.get(key);\n      },\n      put : function (key, value) {\n        $cookies.put(key, value);\n      }\n    };\n  } else {\n    var $cookieStore = $injector.get('$cookieStore');\n    delegate = {\n      get : function (key) {\n        return $cookieStore.get(key);\n      },\n      put : function (key, value) {\n        $cookieStore.put(key, value);\n      }\n    };\n  }\n\n  var $translateCookieStorage = {\n\n    /**\n     * @ngdoc function\n     * @name pascalprecht.translate.$translateCookieStorage#get\n     * @methodOf pascalprecht.translate.$translateCookieStorage\n     *\n     * @description\n     * Returns an item from cookieStorage by given name.\n     *\n     * @param {string} name Item name\n     * @return {string} Value of item name\n     */\n    get : function (name) {\n      return delegate.get(name);\n    },\n\n    /**\n     * @ngdoc function\n     * @name pascalprecht.translate.$translateCookieStorage#set\n     * @methodOf pascalprecht.translate.$translateCookieStorage\n     *\n     * @description\n     * Sets an item in cookieStorage by given name.\n     *\n     * @deprecated use #put\n     *\n     * @param {string} name Item name\n     * @param {string} value Item value\n     */\n    set : function (name, value) {\n      delegate.put(name, value);\n    },\n\n    /**\n     * @ngdoc function\n     * @name pascalprecht.translate.$translateCookieStorage#put\n     * @methodOf pascalprecht.translate.$translateCookieStorage\n     *\n     * @description\n     * Sets an item in cookieStorage by given name.\n     *\n     * @param {string} name Item name\n     * @param {string} value Item value\n     */\n    put : function (name, value) {\n      delegate.put(name, value);\n    }\n  };\n\n  return $translateCookieStorage;\n}\n\n$translateCookieStorageFactory.displayName = '$translateCookieStorage';\nreturn 'pascalprecht.translate';\n\n}));\n"
  },
  {
    "path": "flowable-ui-web/task/libs/angular-translate_2.15.1/angular-translate.js",
    "content": "/*!\n * angular-translate - v2.15.1 - 2017-03-04\n * \n * Copyright (c) 2017 The angular-translate team, Pascal Precht; Licensed MIT\n */\n(function (root, factory) {\n  if (typeof define === 'function' && define.amd) {\n    // AMD. Register as an anonymous module unless amdModuleId is set\n    define([], function () {\n      return (factory());\n    });\n  } else if (typeof exports === 'object') {\n    // Node. Does not work with strict CommonJS, but\n    // only CommonJS-like environments that support module.exports,\n    // like Node.\n    module.exports = factory();\n  } else {\n    factory();\n  }\n}(this, function () {\n\n/**\n * @ngdoc overview\n * @name pascalprecht.translate\n *\n * @description\n * The main module which holds everything together.\n */\nrunTranslate.$inject = ['$translate'];\n$translate.$inject = ['$STORAGE_KEY', '$windowProvider', '$translateSanitizationProvider', 'pascalprechtTranslateOverrider'];\n$translateDefaultInterpolation.$inject = ['$interpolate', '$translateSanitization'];\ntranslateDirective.$inject = ['$translate', '$interpolate', '$compile', '$parse', '$rootScope'];\ntranslateAttrDirective.$inject = ['$translate', '$rootScope'];\ntranslateCloakDirective.$inject = ['$translate', '$rootScope'];\ntranslateFilterFactory.$inject = ['$parse', '$translate'];\n$translationCache.$inject = ['$cacheFactory'];\nangular.module('pascalprecht.translate', ['ng'])\n  .run(runTranslate);\n\nfunction runTranslate($translate) {\n\n  'use strict';\n\n  var key = $translate.storageKey(),\n    storage = $translate.storage();\n\n  var fallbackFromIncorrectStorageValue = function () {\n    var preferred = $translate.preferredLanguage();\n    if (angular.isString(preferred)) {\n      $translate.use(preferred);\n      // $translate.use() will also remember the language.\n      // So, we don't need to call storage.put() here.\n    } else {\n      storage.put(key, $translate.use());\n    }\n  };\n\n  fallbackFromIncorrectStorageValue.displayName = 'fallbackFromIncorrectStorageValue';\n\n  if (storage) {\n    if (!storage.get(key)) {\n      fallbackFromIncorrectStorageValue();\n    } else {\n      $translate.use(storage.get(key))['catch'](fallbackFromIncorrectStorageValue);\n    }\n  } else if (angular.isString($translate.preferredLanguage())) {\n    $translate.use($translate.preferredLanguage());\n  }\n}\n\nrunTranslate.displayName = 'runTranslate';\n\n/**\n * @ngdoc object\n * @name pascalprecht.translate.$translateSanitizationProvider\n *\n * @description\n *\n * Configurations for $translateSanitization\n */\nangular.module('pascalprecht.translate').provider('$translateSanitization', $translateSanitizationProvider);\n\nfunction $translateSanitizationProvider () {\n\n  'use strict';\n\n  var $sanitize,\n      $sce,\n      currentStrategy = null, // TODO change to either 'sanitize', 'escape' or ['sanitize', 'escapeParameters'] in 3.0.\n      hasConfiguredStrategy = false,\n      hasShownNoStrategyConfiguredWarning = false,\n      strategies;\n\n  /**\n   * Definition of a sanitization strategy function\n   * @callback StrategyFunction\n   * @param {string|object} value - value to be sanitized (either a string or an interpolated value map)\n   * @param {string} mode - either 'text' for a string (translation) or 'params' for the interpolated params\n   * @return {string|object}\n   */\n\n  /**\n   * @ngdoc property\n   * @name strategies\n   * @propertyOf pascalprecht.translate.$translateSanitizationProvider\n   *\n   * @description\n   * Following strategies are built-in:\n   * <dl>\n   *   <dt>sanitize</dt>\n   *   <dd>Sanitizes HTML in the translation text using $sanitize</dd>\n   *   <dt>escape</dt>\n   *   <dd>Escapes HTML in the translation</dd>\n   *   <dt>sanitizeParameters</dt>\n   *   <dd>Sanitizes HTML in the values of the interpolation parameters using $sanitize</dd>\n   *   <dt>escapeParameters</dt>\n   *   <dd>Escapes HTML in the values of the interpolation parameters</dd>\n   *   <dt>escaped</dt>\n   *   <dd>Support legacy strategy name 'escaped' for backwards compatibility (will be removed in 3.0)</dd>\n   * </dl>\n   *\n   */\n\n  strategies = {\n    sanitize: function (value, mode/*, context*/) {\n      if (mode === 'text') {\n        value = htmlSanitizeValue(value);\n      }\n      return value;\n    },\n    escape: function (value, mode/*, context*/) {\n      if (mode === 'text') {\n        value = htmlEscapeValue(value);\n      }\n      return value;\n    },\n    sanitizeParameters: function (value, mode/*, context*/) {\n      if (mode === 'params') {\n        value = mapInterpolationParameters(value, htmlSanitizeValue);\n      }\n      return value;\n    },\n    escapeParameters: function (value, mode/*, context*/) {\n      if (mode === 'params') {\n        value = mapInterpolationParameters(value, htmlEscapeValue);\n      }\n      return value;\n    },\n    sce: function (value, mode, context) {\n      if (mode === 'text') {\n        value = htmlTrustValue(value);\n      } else if (mode === 'params') {\n        if (context !== 'filter') {\n          // do html escape in filter context #1101\n          value = mapInterpolationParameters(value, htmlEscapeValue);\n        }\n      }\n      return value;\n    },\n    sceParameters: function (value, mode/*, context*/) {\n      if (mode === 'params') {\n        value = mapInterpolationParameters(value, htmlTrustValue);\n      }\n      return value;\n    }\n  };\n  // Support legacy strategy name 'escaped' for backwards compatibility.\n  // TODO should be removed in 3.0\n  strategies.escaped = strategies.escapeParameters;\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateSanitizationProvider#addStrategy\n   * @methodOf pascalprecht.translate.$translateSanitizationProvider\n   *\n   * @description\n   * Adds a sanitization strategy to the list of known strategies.\n   *\n   * @param {string} strategyName - unique key for a strategy\n   * @param {StrategyFunction} strategyFunction - strategy function\n   * @returns {object} this\n   */\n  this.addStrategy = function (strategyName, strategyFunction) {\n    strategies[strategyName] = strategyFunction;\n    return this;\n  };\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateSanitizationProvider#removeStrategy\n   * @methodOf pascalprecht.translate.$translateSanitizationProvider\n   *\n   * @description\n   * Removes a sanitization strategy from the list of known strategies.\n   *\n   * @param {string} strategyName - unique key for a strategy\n   * @returns {object} this\n   */\n  this.removeStrategy = function (strategyName) {\n    delete strategies[strategyName];\n    return this;\n  };\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateSanitizationProvider#useStrategy\n   * @methodOf pascalprecht.translate.$translateSanitizationProvider\n   *\n   * @description\n   * Selects a sanitization strategy. When an array is provided the strategies will be executed in order.\n   *\n   * @param {string|StrategyFunction|array} strategy The sanitization strategy / strategies which should be used. Either a name of an existing strategy, a custom strategy function, or an array consisting of multiple names and / or custom functions.\n   * @returns {object} this\n   */\n  this.useStrategy = function (strategy) {\n    hasConfiguredStrategy = true;\n    currentStrategy = strategy;\n    return this;\n  };\n\n  /**\n   * @ngdoc object\n   * @name pascalprecht.translate.$translateSanitization\n   * @requires $injector\n   * @requires $log\n   *\n   * @description\n   * Sanitizes interpolation parameters and translated texts.\n   *\n   */\n  this.$get = ['$injector', '$log', function ($injector, $log) {\n\n    var cachedStrategyMap = {};\n\n    var applyStrategies = function (value, mode, context, selectedStrategies) {\n      angular.forEach(selectedStrategies, function (selectedStrategy) {\n        if (angular.isFunction(selectedStrategy)) {\n          value = selectedStrategy(value, mode, context);\n        } else if (angular.isFunction(strategies[selectedStrategy])) {\n          value = strategies[selectedStrategy](value, mode, context);\n        } else if (angular.isString(strategies[selectedStrategy])) {\n          if (!cachedStrategyMap[strategies[selectedStrategy]]) {\n            try {\n              cachedStrategyMap[strategies[selectedStrategy]] = $injector.get(strategies[selectedStrategy]);\n            } catch (e) {\n              cachedStrategyMap[strategies[selectedStrategy]] = function() {};\n              throw new Error('pascalprecht.translate.$translateSanitization: Unknown sanitization strategy: \\'' + selectedStrategy + '\\'');\n            }\n          }\n          value = cachedStrategyMap[strategies[selectedStrategy]](value, mode, context);\n        } else {\n          throw new Error('pascalprecht.translate.$translateSanitization: Unknown sanitization strategy: \\'' + selectedStrategy + '\\'');\n        }\n      });\n      return value;\n    };\n\n    // TODO: should be removed in 3.0\n    var showNoStrategyConfiguredWarning = function () {\n      if (!hasConfiguredStrategy && !hasShownNoStrategyConfiguredWarning) {\n        $log.warn('pascalprecht.translate.$translateSanitization: No sanitization strategy has been configured. This can have serious security implications. See http://angular-translate.github.io/docs/#/guide/19_security for details.');\n        hasShownNoStrategyConfiguredWarning = true;\n      }\n    };\n\n    if ($injector.has('$sanitize')) {\n      $sanitize = $injector.get('$sanitize');\n    }\n    if ($injector.has('$sce')) {\n      $sce = $injector.get('$sce');\n    }\n\n    return {\n      /**\n       * @ngdoc function\n       * @name pascalprecht.translate.$translateSanitization#useStrategy\n       * @methodOf pascalprecht.translate.$translateSanitization\n       *\n       * @description\n       * Selects a sanitization strategy. When an array is provided the strategies will be executed in order.\n       *\n       * @param {string|StrategyFunction|array} strategy The sanitization strategy / strategies which should be used. Either a name of an existing strategy, a custom strategy function, or an array consisting of multiple names and / or custom functions.\n       */\n      useStrategy: (function (self) {\n        return function (strategy) {\n          self.useStrategy(strategy);\n        };\n      })(this),\n\n      /**\n       * @ngdoc function\n       * @name pascalprecht.translate.$translateSanitization#sanitize\n       * @methodOf pascalprecht.translate.$translateSanitization\n       *\n       * @description\n       * Sanitizes a value.\n       *\n       * @param {string|object} value The value which should be sanitized.\n       * @param {string} mode The current sanitization mode, either 'params' or 'text'.\n       * @param {string|StrategyFunction|array} [strategy] Optional custom strategy which should be used instead of the currently selected strategy.\n       * @param {string} [context] The context of this call: filter, service. Default is service\n       * @returns {string|object} sanitized value\n       */\n      sanitize: function (value, mode, strategy, context) {\n        if (!currentStrategy) {\n          showNoStrategyConfiguredWarning();\n        }\n\n        if (!strategy && strategy !== null) {\n          strategy = currentStrategy;\n        }\n\n        if (!strategy) {\n          return value;\n        }\n\n        if (!context) {\n          context = 'service';\n        }\n\n        var selectedStrategies = angular.isArray(strategy) ? strategy : [strategy];\n        return applyStrategies(value, mode, context, selectedStrategies);\n      }\n    };\n  }];\n\n  var htmlEscapeValue = function (value) {\n    var element = angular.element('<div></div>');\n    element.text(value); // not chainable, see #1044\n    return element.html();\n  };\n\n  var htmlSanitizeValue = function (value) {\n    if (!$sanitize) {\n      throw new Error('pascalprecht.translate.$translateSanitization: Error cannot find $sanitize service. Either include the ngSanitize module (https://docs.angularjs.org/api/ngSanitize) or use a sanitization strategy which does not depend on $sanitize, such as \\'escape\\'.');\n    }\n    return $sanitize(value);\n  };\n\n  var htmlTrustValue = function (value) {\n    if (!$sce) {\n      throw new Error('pascalprecht.translate.$translateSanitization: Error cannot find $sce service.');\n    }\n    return $sce.trustAsHtml(value);\n  };\n\n  var mapInterpolationParameters = function (value, iteratee, stack) {\n    if (angular.isDate(value)) {\n      return value;\n    } else if (angular.isObject(value)) {\n      var result = angular.isArray(value) ? [] : {};\n\n      if (!stack) {\n        stack = [];\n      } else {\n        if (stack.indexOf(value) > -1) {\n          throw new Error('pascalprecht.translate.$translateSanitization: Error cannot interpolate parameter due recursive object');\n        }\n      }\n\n      stack.push(value);\n      angular.forEach(value, function (propertyValue, propertyKey) {\n\n        /* Skipping function properties. */\n        if (angular.isFunction(propertyValue)) {\n          return;\n        }\n\n        result[propertyKey] = mapInterpolationParameters(propertyValue, iteratee, stack);\n      });\n      stack.splice(-1, 1); // remove last\n\n      return result;\n    } else if (angular.isNumber(value)) {\n      return value;\n    } else if (!angular.isUndefined(value) && value !== null) {\n      return iteratee(value);\n    } else {\n      return value;\n    }\n  };\n}\n\n/**\n * @ngdoc object\n * @name pascalprecht.translate.$translateProvider\n * @description\n *\n * $translateProvider allows developers to register translation-tables, asynchronous loaders\n * and similar to configure translation behavior directly inside of a module.\n *\n */\nangular.module('pascalprecht.translate')\n  .constant('pascalprechtTranslateOverrider', {})\n  .provider('$translate', $translate);\n\nfunction $translate($STORAGE_KEY, $windowProvider, $translateSanitizationProvider, pascalprechtTranslateOverrider) {\n\n  'use strict';\n\n  var $translationTable = {},\n    $preferredLanguage,\n    $availableLanguageKeys = [],\n    $languageKeyAliases,\n    $fallbackLanguage,\n    $fallbackWasString,\n    $uses,\n    $nextLang,\n    $storageFactory,\n    $storageKey = $STORAGE_KEY,\n    $storagePrefix,\n    $missingTranslationHandlerFactory,\n    $interpolationFactory,\n    $interpolatorFactories = [],\n    $loaderFactory,\n    $cloakClassName = 'translate-cloak',\n    $loaderOptions,\n    $notFoundIndicatorLeft,\n    $notFoundIndicatorRight,\n    $postCompilingEnabled = false,\n    $forceAsyncReloadEnabled = false,\n    $nestedObjectDelimeter = '.',\n    $isReady = false,\n    $keepContent = false,\n    loaderCache,\n    directivePriority = 0,\n    statefulFilter = true,\n    postProcessFn,\n    uniformLanguageTagResolver = 'default',\n    languageTagResolver = {\n      'default' : function (tag) {\n        return (tag || '').split('-').join('_');\n      },\n      java : function (tag) {\n        var temp = (tag || '').split('-').join('_');\n        var parts = temp.split('_');\n        return parts.length > 1 ? (parts[0].toLowerCase() + '_' + parts[1].toUpperCase()) : temp;\n      },\n      bcp47 : function (tag) {\n        var temp = (tag || '').split('_').join('-');\n        var parts = temp.split('-');\n        return parts.length > 1 ? (parts[0].toLowerCase() + '-' + parts[1].toUpperCase()) : temp;\n      },\n      'iso639-1' : function (tag) {\n        var temp = (tag || '').split('_').join('-');\n        var parts = temp.split('-');\n        return parts[0].toLowerCase();\n      }\n    };\n\n  var version = '2.15.1';\n\n  // tries to determine the browsers language\n  var getFirstBrowserLanguage = function () {\n\n    // internal purpose only\n    if (angular.isFunction(pascalprechtTranslateOverrider.getLocale)) {\n      return pascalprechtTranslateOverrider.getLocale();\n    }\n\n    var nav = $windowProvider.$get().navigator,\n      browserLanguagePropertyKeys = ['language', 'browserLanguage', 'systemLanguage', 'userLanguage'],\n      i,\n      language;\n\n    // support for HTML 5.1 \"navigator.languages\"\n    if (angular.isArray(nav.languages)) {\n      for (i = 0; i < nav.languages.length; i++) {\n        language = nav.languages[i];\n        if (language && language.length) {\n          return language;\n        }\n      }\n    }\n\n    // support for other well known properties in browsers\n    for (i = 0; i < browserLanguagePropertyKeys.length; i++) {\n      language = nav[browserLanguagePropertyKeys[i]];\n      if (language && language.length) {\n        return language;\n      }\n    }\n\n    return null;\n  };\n  getFirstBrowserLanguage.displayName = 'angular-translate/service: getFirstBrowserLanguage';\n\n  // tries to determine the browsers locale\n  var getLocale = function () {\n    var locale = getFirstBrowserLanguage() || '';\n    if (languageTagResolver[uniformLanguageTagResolver]) {\n      locale = languageTagResolver[uniformLanguageTagResolver](locale);\n    }\n    return locale;\n  };\n  getLocale.displayName = 'angular-translate/service: getLocale';\n\n  /**\n   * @name indexOf\n   * @private\n   *\n   * @description\n   * indexOf polyfill. Kinda sorta.\n   *\n   * @param {array} array Array to search in.\n   * @param {string} searchElement Element to search for.\n   *\n   * @returns {int} Index of search element.\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\n  /**\n   * @name trim\n   * @private\n   *\n   * @description\n   * trim polyfill\n   *\n   * @returns {string} The string stripped of whitespace from both ends\n   */\n  var trim = function () {\n    return this.toString().replace(/^\\s+|\\s+$/g, '');\n  };\n\n  var negotiateLocale = function (preferred) {\n    if (!preferred) {\n      return;\n    }\n\n    var avail = [],\n      locale = angular.lowercase(preferred),\n      i = 0,\n      n = $availableLanguageKeys.length;\n\n    for (; i < n; i++) {\n      avail.push(angular.lowercase($availableLanguageKeys[i]));\n    }\n\n    // Check for an exact match in our list of available keys\n    if (indexOf(avail, locale) > -1) {\n      return preferred;\n    }\n\n    if ($languageKeyAliases) {\n      var alias;\n      for (var langKeyAlias in $languageKeyAliases) {\n        if ($languageKeyAliases.hasOwnProperty(langKeyAlias)) {\n          var hasWildcardKey = false;\n          var hasExactKey = Object.prototype.hasOwnProperty.call($languageKeyAliases, langKeyAlias) &&\n            angular.lowercase(langKeyAlias) === angular.lowercase(preferred);\n\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    }\n\n    // Check for a language code without region\n    var parts = preferred.split('_');\n\n    if (parts.length > 1 && indexOf(avail, angular.lowercase(parts[0])) > -1) {\n      return parts[0];\n    }\n\n    // If everything fails, return undefined.\n    return;\n  };\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#translations\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * Registers a new translation table for specific language key.\n   *\n   * To register a translation table for specific language, pass a defined language\n   * key as first parameter.\n   *\n   * <pre>\n   *  // register translation table for language: 'de_DE'\n   *  $translateProvider.translations('de_DE', {\n   *    'GREETING': 'Hallo Welt!'\n   *  });\n   *\n   *  // register another one\n   *  $translateProvider.translations('en_US', {\n   *    'GREETING': 'Hello world!'\n   *  });\n   * </pre>\n   *\n   * When registering multiple translation tables for for the same language key,\n   * the actual translation table gets extended. This allows you to define module\n   * specific translation which only get added, once a specific module is loaded in\n   * your app.\n   *\n   * Invoking this method with no arguments returns the translation table which was\n   * registered with no language key. Invoking it with a language key returns the\n   * related translation table.\n   *\n   * @param {string} langKey A language key.\n   * @param {object} translationTable A plain old JavaScript object that represents a translation table.\n   *\n   */\n  var translations = function (langKey, translationTable) {\n\n    if (!langKey && !translationTable) {\n      return $translationTable;\n    }\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\n  this.translations = translations;\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#cloakClassName\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   *\n   * Let's you change the class name for `translate-cloak` directive.\n   * Default class name is `translate-cloak`.\n   *\n   * @param {string} name translate-cloak class name\n   */\n  this.cloakClassName = function (name) {\n    if (!name) {\n      return $cloakClassName;\n    }\n    $cloakClassName = name;\n    return this;\n  };\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#nestedObjectDelimeter\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   *\n   * Let's you change the delimiter for namespaced translations.\n   * Default delimiter is `.`.\n   *\n   * @param {string} delimiter namespace separator\n   */\n  this.nestedObjectDelimeter = function (delimiter) {\n    if (!delimiter) {\n      return $nestedObjectDelimeter;\n    }\n    $nestedObjectDelimeter = delimiter;\n    return this;\n  };\n\n  /**\n   * @name flatObject\n   * @private\n   *\n   * @description\n   * Flats an object. This function is used to flatten given translation data with\n   * namespaces, so they are later accessible via dot notation.\n   */\n  var flatObject = function (data, path, result, prevKey) {\n    var key, keyWithPath, keyWithShortPath, val;\n\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($nestedObjectDelimeter) + $nestedObjectDelimeter + key) : key;\n        if (path.length && key === prevKey) {\n          // Create shortcut path (foo.bar == foo.bar.bar)\n          keyWithShortPath = '' + path.join($nestedObjectDelimeter);\n          // Link it to original path\n          result[keyWithShortPath] = '@:' + keyWithPath;\n        }\n        result[keyWithPath] = val;\n      }\n    }\n    return result;\n  };\n  flatObject.displayName = 'flatObject';\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#addInterpolation\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * Adds interpolation services to angular-translate, so it can manage them.\n   *\n   * @param {object} factory Interpolation service factory\n   */\n  this.addInterpolation = function (factory) {\n    $interpolatorFactories.push(factory);\n    return this;\n  };\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#useMessageFormatInterpolation\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * Tells angular-translate to use interpolation functionality of messageformat.js.\n   * This is useful when having high level pluralization and gender selection.\n   */\n  this.useMessageFormatInterpolation = function () {\n    return this.useInterpolation('$translateMessageFormatInterpolation');\n  };\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#useInterpolation\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * Tells angular-translate which interpolation style to use as default, application-wide.\n   * Simply pass a factory/service name. The interpolation service has to implement\n   * the correct interface.\n   *\n   * @param {string} factory Interpolation service name.\n   */\n  this.useInterpolation = function (factory) {\n    $interpolationFactory = factory;\n    return this;\n  };\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#useSanitizeStrategy\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * Simply sets a sanitation strategy type.\n   *\n   * @param {string} value Strategy type.\n   */\n  this.useSanitizeValueStrategy = function (value) {\n    $translateSanitizationProvider.useStrategy(value);\n    return this;\n  };\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#preferredLanguage\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * Tells the module which of the registered translation tables to use for translation\n   * at initial startup by passing a language key. Similar to `$translateProvider#use`\n   * only that it says which language to **prefer**.\n   *\n   * @param {string} langKey A language key.\n   */\n  this.preferredLanguage = function (langKey) {\n    if (langKey) {\n      setupPreferredLanguage(langKey);\n      return this;\n    }\n    return $preferredLanguage;\n  };\n  var setupPreferredLanguage = function (langKey) {\n    if (langKey) {\n      $preferredLanguage = langKey;\n    }\n    return $preferredLanguage;\n  };\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#translationNotFoundIndicator\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * Sets an indicator which is used when a translation isn't found. E.g. when\n   * setting the indicator as 'X' and one tries to translate a translation id\n   * called `NOT_FOUND`, this will result in `X NOT_FOUND X`.\n   *\n   * Internally this methods sets a left indicator and a right indicator using\n   * `$translateProvider.translationNotFoundIndicatorLeft()` and\n   * `$translateProvider.translationNotFoundIndicatorRight()`.\n   *\n   * **Note**: These methods automatically add a whitespace between the indicators\n   * and the translation id.\n   *\n   * @param {string} indicator An indicator, could be any string.\n   */\n  this.translationNotFoundIndicator = function (indicator) {\n    this.translationNotFoundIndicatorLeft(indicator);\n    this.translationNotFoundIndicatorRight(indicator);\n    return this;\n  };\n\n  /**\n   * ngdoc function\n   * @name pascalprecht.translate.$translateProvider#translationNotFoundIndicatorLeft\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * Sets an indicator which is used when a translation isn't found left to the\n   * translation id.\n   *\n   * @param {string} indicator An indicator.\n   */\n  this.translationNotFoundIndicatorLeft = function (indicator) {\n    if (!indicator) {\n      return $notFoundIndicatorLeft;\n    }\n    $notFoundIndicatorLeft = indicator;\n    return this;\n  };\n\n  /**\n   * ngdoc function\n   * @name pascalprecht.translate.$translateProvider#translationNotFoundIndicatorLeft\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * Sets an indicator which is used when a translation isn't found right to the\n   * translation id.\n   *\n   * @param {string} indicator An indicator.\n   */\n  this.translationNotFoundIndicatorRight = function (indicator) {\n    if (!indicator) {\n      return $notFoundIndicatorRight;\n    }\n    $notFoundIndicatorRight = indicator;\n    return this;\n  };\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#fallbackLanguage\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * Tells the module which of the registered translation tables to use when missing translations\n   * at initial startup by passing a language key. Similar to `$translateProvider#use`\n   * only that it says which language to **fallback**.\n   *\n   * @param {string||array} langKey A language key.\n   *\n   */\n  this.fallbackLanguage = function (langKey) {\n    fallbackStack(langKey);\n    return this;\n  };\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\n      return this;\n    } else {\n      if ($fallbackWasString) {\n        return $fallbackLanguage[0];\n      } else {\n        return $fallbackLanguage;\n      }\n    }\n  };\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#use\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * Set which translation table to use for translation by given language key. When\n   * trying to 'use' a language which isn't provided, it'll throw an error.\n   *\n   * You actually don't have to use this method since `$translateProvider#preferredLanguage`\n   * does the job too.\n   *\n   * @param {string} langKey A language key.\n   */\n  this.use = function (langKey) {\n    if (langKey) {\n      if (!$translationTable[langKey] && (!$loaderFactory)) {\n        // only throw an error, when not loading translation data asynchronously\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\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#resolveClientLocale\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * This returns the current browser/client's language key. The result is processed with the configured uniform tag resolver.\n   *\n   * @returns {string} the current client/browser language key\n   */\n  this.resolveClientLocale = function () {\n    return getLocale();\n  };\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#storageKey\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * Tells the module which key must represent the choosed language by a user in the storage.\n   *\n   * @param {string} key A key for the storage.\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    return this;\n  };\n\n  this.storageKey = storageKey;\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#useUrlLoader\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * Tells angular-translate to use `$translateUrlLoader` extension service as loader.\n   *\n   * @param {string} url Url\n   * @param {Object=} options Optional configuration object\n   */\n  this.useUrlLoader = function (url, options) {\n    return this.useLoader('$translateUrlLoader', angular.extend({url : url}, options));\n  };\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#useStaticFilesLoader\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * Tells angular-translate to use `$translateStaticFilesLoader` extension service as loader.\n   *\n   * @param {Object=} options Optional configuration object\n   */\n  this.useStaticFilesLoader = function (options) {\n    return this.useLoader('$translateStaticFilesLoader', options);\n  };\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#useLoader\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * Tells angular-translate to use any other service as loader.\n   *\n   * @param {string} loaderFactory Factory name to use\n   * @param {Object=} options Optional configuration object\n   */\n  this.useLoader = function (loaderFactory, options) {\n    $loaderFactory = loaderFactory;\n    $loaderOptions = options || {};\n    return this;\n  };\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#useLocalStorage\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * Tells angular-translate to use `$translateLocalStorage` service as storage layer.\n   *\n   */\n  this.useLocalStorage = function () {\n    return this.useStorage('$translateLocalStorage');\n  };\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#useCookieStorage\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * Tells angular-translate to use `$translateCookieStorage` service as storage layer.\n   */\n  this.useCookieStorage = function () {\n    return this.useStorage('$translateCookieStorage');\n  };\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#useStorage\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * Tells angular-translate to use custom service as storage layer.\n   */\n  this.useStorage = function (storageFactory) {\n    $storageFactory = storageFactory;\n    return this;\n  };\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#storagePrefix\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * Sets prefix for storage key.\n   *\n   * @param {string} prefix Storage key prefix\n   */\n  this.storagePrefix = function (prefix) {\n    if (!prefix) {\n      return prefix;\n    }\n    $storagePrefix = prefix;\n    return this;\n  };\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#useMissingTranslationHandlerLog\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * Tells angular-translate to use built-in log handler when trying to translate\n   * a translation Id which doesn't exist.\n   *\n   * This is actually a shortcut method for `useMissingTranslationHandler()`.\n   *\n   */\n  this.useMissingTranslationHandlerLog = function () {\n    return this.useMissingTranslationHandler('$translateMissingTranslationHandlerLog');\n  };\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#useMissingTranslationHandler\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * Expects a factory name which later gets instantiated with `$injector`.\n   * This method can be used to tell angular-translate to use a custom\n   * missingTranslationHandler. Just build a factory which returns a function\n   * and expects a translation id as argument.\n   *\n   * Example:\n   * <pre>\n   *  app.config(function ($translateProvider) {\n   *    $translateProvider.useMissingTranslationHandler('customHandler');\n   *  });\n   *\n   *  app.factory('customHandler', function (dep1, dep2) {\n   *    return function (translationId) {\n   *      // something with translationId and dep1 and dep2\n   *    };\n   *  });\n   * </pre>\n   *\n   * @param {string} factory Factory name\n   */\n  this.useMissingTranslationHandler = function (factory) {\n    $missingTranslationHandlerFactory = factory;\n    return this;\n  };\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#usePostCompiling\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * If post compiling is enabled, all translated values will be processed\n   * again with AngularJS' $compile.\n   *\n   * Example:\n   * <pre>\n   *  app.config(function ($translateProvider) {\n   *    $translateProvider.usePostCompiling(true);\n   *  });\n   * </pre>\n   *\n   * @param {string} factory Factory name\n   */\n  this.usePostCompiling = function (value) {\n    $postCompilingEnabled = !(!value);\n    return this;\n  };\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#forceAsyncReload\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * If force async reload is enabled, async loader will always be called\n   * even if $translationTable already contains the language key, adding\n   * possible new entries to the $translationTable.\n   *\n   * Example:\n   * <pre>\n   *  app.config(function ($translateProvider) {\n   *    $translateProvider.forceAsyncReload(true);\n   *  });\n   * </pre>\n   *\n   * @param {boolean} value - valid values are true or false\n   */\n  this.forceAsyncReload = function (value) {\n    $forceAsyncReloadEnabled = !(!value);\n    return this;\n  };\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#uniformLanguageTag\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * Tells angular-translate which language tag should be used as a result when determining\n   * the current browser language.\n   *\n   * This setting must be set before invoking {@link pascalprecht.translate.$translateProvider#methods_determinePreferredLanguage determinePreferredLanguage()}.\n   *\n   * <pre>\n   * $translateProvider\n   *   .uniformLanguageTag('bcp47')\n   *   .determinePreferredLanguage()\n   * </pre>\n   *\n   * The resolver currently supports:\n   * * default\n   *     (traditionally: hyphens will be converted into underscores, i.e. en-US => en_US)\n   *     en-US => en_US\n   *     en_US => en_US\n   *     en-us => en_us\n   * * java\n   *     like default, but the second part will be always in uppercase\n   *     en-US => en_US\n   *     en_US => en_US\n   *     en-us => en_US\n   * * BCP 47 (RFC 4646 & 4647)\n   *     en-US => en-US\n   *     en_US => en-US\n   *     en-us => en-US\n   *\n   * See also:\n   * * http://en.wikipedia.org/wiki/IETF_language_tag\n   * * http://www.w3.org/International/core/langtags/\n   * * http://tools.ietf.org/html/bcp47\n   *\n   * @param {string|object} options - options (or standard)\n   * @param {string} options.standard - valid values are 'default', 'bcp47', 'java'\n   */\n  this.uniformLanguageTag = function (options) {\n\n    if (!options) {\n      options = {};\n    } else if (angular.isString(options)) {\n      options = {\n        standard : options\n      };\n    }\n\n    uniformLanguageTagResolver = options.standard;\n\n    return this;\n  };\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#determinePreferredLanguage\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * Tells angular-translate to try to determine on its own which language key\n   * to set as preferred language. When `fn` is given, angular-translate uses it\n   * to determine a language key, otherwise it uses the built-in `getLocale()`\n   * method.\n   *\n   * The `getLocale()` returns a language key in the format `[lang]_[country]` or\n   * `[lang]` depending on what the browser provides.\n   *\n   * Use this method at your own risk, since not all browsers return a valid\n   * locale (see {@link pascalprecht.translate.$translateProvider#methods_uniformLanguageTag uniformLanguageTag()}).\n   *\n   * @param {Function=} fn Function to determine a browser's locale\n   */\n  this.determinePreferredLanguage = function (fn) {\n\n    var locale = (fn && angular.isFunction(fn)) ? fn() : getLocale();\n\n    if (!$availableLanguageKeys.length) {\n      $preferredLanguage = locale;\n    } else {\n      $preferredLanguage = negotiateLocale(locale) || locale;\n    }\n\n    return this;\n  };\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#registerAvailableLanguageKeys\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * Registers a set of language keys the app will work with. Use this method in\n   * combination with\n   * {@link pascalprecht.translate.$translateProvider#determinePreferredLanguage determinePreferredLanguage}.\n   * When available languages keys are registered, angular-translate\n   * tries to find the best fitting language key depending on the browsers locale,\n   * considering your language key convention.\n   *\n   * @param {object} languageKeys Array of language keys the your app will use\n   * @param {object=} aliases Alias map.\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\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#useLoaderCache\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * Registers a cache for internal $http based loaders.\n   * {@link pascalprecht.translate.$translationCache $translationCache}.\n   * When false the cache will be disabled (default). When true or undefined\n   * the cache will be a default (see $cacheFactory). When an object it will\n   * be treat as a cache object itself: the usage is $http({cache: cache})\n   *\n   * @param {object} cache boolean, string or cache-object\n   */\n  this.useLoaderCache = function (cache) {\n    if (cache === false) {\n      // disable cache\n      loaderCache = undefined;\n    } else if (cache === true) {\n      // enable cache using AJS defaults\n      loaderCache = true;\n    } else if (typeof(cache) === 'undefined') {\n      // enable cache using default\n      loaderCache = '$translationCache';\n    } else if (cache) {\n      // enable cache using given one (see $cacheFactory)\n      loaderCache = cache;\n    }\n    return this;\n  };\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#directivePriority\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * Sets the default priority of the translate directive. The standard value is `0`.\n   * Calling this function without an argument will return the current value.\n   *\n   * @param {number} priority for the translate-directive\n   */\n  this.directivePriority = function (priority) {\n    if (priority === undefined) {\n      // getter\n      return directivePriority;\n    } else {\n      // setter with chaining\n      directivePriority = priority;\n      return this;\n    }\n  };\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#statefulFilter\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * Since AngularJS 1.3, filters which are not stateless (depending at the scope)\n   * have to explicit define this behavior.\n   * Sets whether the translate filter should be stateful or stateless. The standard value is `true`\n   * meaning being stateful.\n   * Calling this function without an argument will return the current value.\n   *\n   * @param {boolean} state - defines the state of the filter\n   */\n  this.statefulFilter = function (state) {\n    if (state === undefined) {\n      // getter\n      return statefulFilter;\n    } else {\n      // setter with chaining\n      statefulFilter = state;\n      return this;\n    }\n  };\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#postProcess\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * The post processor will be intercept right after the translation result. It can modify the result.\n   *\n   * @param {object} fn Function or service name (string) to be called after the translation value has been set / resolved. The function itself will enrich every value being processed and then continue the normal resolver process\n   */\n  this.postProcess = function (fn) {\n    if (fn) {\n      postProcessFn = fn;\n    } else {\n      postProcessFn = undefined;\n    }\n    return this;\n  };\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#keepContent\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * If keepContent is set to true than translate directive will always use innerHTML\n   * as a default translation\n   *\n   * Example:\n   * <pre>\n   *  app.config(function ($translateProvider) {\n   *    $translateProvider.keepContent(true);\n   *  });\n   * </pre>\n   *\n   * @param {boolean} value - valid values are true or false\n   */\n  this.keepContent = function (value) {\n    $keepContent = !(!value);\n    return this;\n  };\n\n  /**\n   * @ngdoc object\n   * @name pascalprecht.translate.$translate\n   * @requires $interpolate\n   * @requires $log\n   * @requires $rootScope\n   * @requires $q\n   *\n   * @description\n   * The `$translate` service is the actual core of angular-translate. It expects a translation id\n   * and optional interpolate parameters to translate contents.\n   *\n   * <pre>\n   *  $translate('HEADLINE_TEXT').then(function (translation) {\n   *    $scope.translatedText = translation;\n   *  });\n   * </pre>\n   *\n   * @param {string|array} translationId A token which represents a translation id\n   *                                     This can be optionally an array of translation ids which\n   *                                     results that the function returns an object where each key\n   *                                     is the translation id and the value the translation.\n   * @param {object=} interpolateParams An object hash for dynamic values\n   * @param {string} interpolationId The id of the interpolation to use\n   * @param {string} defaultTranslationText the optional default translation text that is written as\n   *                                        as default text in case it is not found in any configured language\n   * @param {string} forceLanguage A language to be used instead of the current language\n   * @returns {object} promise\n   */\n  this.$get = ['$log', '$injector', '$rootScope', '$q', function ($log, $injector, $rootScope, $q) {\n\n    var Storage,\n      defaultInterpolator = $injector.get($interpolationFactory || '$translateDefaultInterpolation'),\n      pendingLoader = false,\n      interpolatorHashMap = {},\n      langPromises = {},\n      fallbackIndex,\n      startFallbackIteration;\n\n    var $translate = function (translationId, interpolateParams, interpolationId, defaultTranslationText, forceLanguage) {\n      if (!$uses && $preferredLanguage) {\n        $uses = $preferredLanguage;\n      }\n      var uses = (forceLanguage && forceLanguage !== $uses) ? // we don't want to re-negotiate $uses\n        (negotiateLocale(forceLanguage) || forceLanguage) : $uses;\n\n      // Check forceLanguage is present\n      if (forceLanguage) {\n        loadTranslationsIfMissing(forceLanguage);\n      }\n\n      // Duck detection: If the first argument is an array, a bunch of translations was requested.\n      // The result is an object.\n      if (angular.isArray(translationId)) {\n        // Inspired by Q.allSettled by Kris Kowal\n        // https://github.com/kriskowal/q/blob/b0fa72980717dc202ffc3cbf03b936e10ebbb9d7/q.js#L1553-1563\n        // This transforms all promises regardless resolved or rejected\n        var translateAll = function (translationIds) {\n          var results = {}; // storing the actual results\n          var promises = []; // promises to wait for\n          // Wraps the promise a) being always resolved and b) storing the link id->value\n          var translate = function (translationId) {\n            var deferred = $q.defer();\n            var regardless = function (value) {\n              results[translationId] = value;\n              deferred.resolve([translationId, value]);\n            };\n            // we don't care whether the promise was resolved or rejected; just store the values\n            $translate(translationId, interpolateParams, interpolationId, defaultTranslationText, forceLanguage).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          // wait for all (including storing to results)\n          return $q.all(promises).then(function () {\n            // return the results\n            return results;\n          });\n        };\n        return translateAll(translationId);\n      }\n\n      var deferred = $q.defer();\n\n      // trim off any whitespace\n      if (translationId) {\n        translationId = trim.apply(translationId);\n      }\n\n      var promiseToWaitFor = (function () {\n        var promise = $preferredLanguage ?\n          langPromises[$preferredLanguage] :\n          langPromises[uses];\n\n        fallbackIndex = 0;\n\n        if ($storageFactory && !promise) {\n          // looks like there's no pending promise for $preferredLanguage or\n          // $uses. Maybe there's one pending for a language that comes from\n          // storage.\n          var langKey = Storage.get($storageKey);\n          promise = langPromises[langKey];\n\n          if ($fallbackLanguage && $fallbackLanguage.length) {\n            var index = indexOf($fallbackLanguage, langKey);\n            // maybe the language from storage is also defined as fallback language\n            // we increase the fallback language index to not search in that language\n            // as fallback, since it's probably the first used language\n            // in that case the index starts after the first element\n            fallbackIndex = (index === 0) ? 1 : 0;\n\n            // but we can make sure to ALWAYS fallback to preferred language at least\n            if (indexOf($fallbackLanguage, $preferredLanguage) < 0) {\n              $fallbackLanguage.push($preferredLanguage);\n            }\n          }\n        }\n        return promise;\n      }());\n\n      if (!promiseToWaitFor) {\n        // no promise to wait for? okay. Then there's no loader registered\n        // nor is a one pending for language that comes from storage.\n        // We can just translate.\n        determineTranslation(translationId, interpolateParams, interpolationId, defaultTranslationText, uses).then(deferred.resolve, deferred.reject);\n      } else {\n        var promiseResolved = function () {\n          // $uses may have changed while waiting\n          if (!forceLanguage) {\n            uses = $uses;\n          }\n          determineTranslation(translationId, interpolateParams, interpolationId, defaultTranslationText, uses).then(deferred.resolve, deferred.reject);\n        };\n        promiseResolved.displayName = 'promiseResolved';\n\n        promiseToWaitFor['finally'](promiseResolved)\n          .catch(angular.noop); // we don't care about errors here, already handled\n      }\n      return deferred.promise;\n    };\n\n    /**\n     * @name applyNotFoundIndicators\n     * @private\n     *\n     * @description\n     * Applies not fount indicators to given translation id, if needed.\n     * This function gets only executed, if a translation id doesn't exist,\n     * which is why a translation id is expected as argument.\n     *\n     * @param {string} translationId Translation id.\n     * @returns {string} Same as given translation id but applied with not found\n     * indicators.\n     */\n    var applyNotFoundIndicators = function (translationId) {\n      // applying notFoundIndicators\n      if ($notFoundIndicatorLeft) {\n        translationId = [$notFoundIndicatorLeft, translationId].join(' ');\n      }\n      if ($notFoundIndicatorRight) {\n        translationId = [translationId, $notFoundIndicatorRight].join(' ');\n      }\n      return translationId;\n    };\n\n    /**\n     * @name useLanguage\n     * @private\n     *\n     * @description\n     * Makes actual use of a language by setting a given language key as used\n     * language and informs registered interpolators to also use the given\n     * key as locale.\n     *\n     * @param {string} key Locale key.\n     */\n    var useLanguage = function (key) {\n      $uses = key;\n\n      // make sure to store new language key before triggering success event\n      if ($storageFactory) {\n        Storage.put($translate.storageKey(), $uses);\n      }\n\n      $rootScope.$emit('$translateChangeSuccess', {language : key});\n\n      // inform default interpolator\n      defaultInterpolator.setLocale($uses);\n\n      var eachInterpolator = function (interpolator, id) {\n        interpolatorHashMap[id].setLocale($uses);\n      };\n      eachInterpolator.displayName = 'eachInterpolatorLocaleSetter';\n\n      // inform all others too!\n      angular.forEach(interpolatorHashMap, eachInterpolator);\n      $rootScope.$emit('$translateChangeEnd', {language : key});\n    };\n\n    /**\n     * @name loadAsync\n     * @private\n     *\n     * @description\n     * Kicks off registered async loader using `$injector` and applies existing\n     * loader options. When resolved, it updates translation tables accordingly\n     * or rejects with given language key.\n     *\n     * @param {string} key Language key.\n     * @return {Promise} A promise.\n     */\n    var loadAsync = function (key) {\n      if (!key) {\n        throw 'No language key specified for loading.';\n      }\n\n      var deferred = $q.defer();\n\n      $rootScope.$emit('$translateLoadingStart', {language : key});\n      pendingLoader = true;\n\n      var cache = loaderCache;\n      if (typeof(cache) === 'string') {\n        // getting on-demand instance of loader\n        cache = $injector.get(cache);\n      }\n\n      var loaderOptions = angular.extend({}, $loaderOptions, {\n        key : key,\n        $http : angular.extend({}, {\n          cache : cache\n        }, $loaderOptions.$http)\n      });\n\n      var onLoaderSuccess = function (data) {\n        var translationTable = {};\n        $rootScope.$emit('$translateLoadingSuccess', {language : key});\n\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      };\n      onLoaderSuccess.displayName = 'onLoaderSuccess';\n\n      var onLoaderError = function (key) {\n        $rootScope.$emit('$translateLoadingError', {language : key});\n        deferred.reject(key);\n        $rootScope.$emit('$translateLoadingEnd', {language : key});\n      };\n      onLoaderError.displayName = 'onLoaderError';\n\n      $injector.get($loaderFactory)(loaderOptions)\n        .then(onLoaderSuccess, onLoaderError);\n\n      return deferred.promise;\n    };\n\n    if ($storageFactory) {\n      Storage = $injector.get($storageFactory);\n\n      if (!Storage.get || !Storage.put) {\n        throw new Error('Couldn\\'t use storage \\'' + $storageFactory + '\\', missing get() or put() method!');\n      }\n    }\n\n    // if we have additional interpolations that were added via\n    // $translateProvider.addInterpolation(), we have to map'em\n    if ($interpolatorFactories.length) {\n      var eachInterpolationFactory = function (interpolatorFactory) {\n        var interpolator = $injector.get(interpolatorFactory);\n        // setting initial locale for each interpolation service\n        interpolator.setLocale($preferredLanguage || $uses);\n        // make'em recognizable through id\n        interpolatorHashMap[interpolator.getInterpolationIdentifier()] = interpolator;\n      };\n      eachInterpolationFactory.displayName = 'interpolationFactoryAdder';\n\n      angular.forEach($interpolatorFactories, eachInterpolationFactory);\n    }\n\n    /**\n     * @name getTranslationTable\n     * @private\n     *\n     * @description\n     * Returns a promise that resolves to the translation table\n     * or is rejected if an error occurred.\n     *\n     * @param langKey\n     * @returns {Q.promise}\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        var onResolve = function (data) {\n          translations(data.key, data.table);\n          deferred.resolve(data.table);\n        };\n        onResolve.displayName = 'translationTableResolver';\n        langPromises[langKey].then(onResolve, deferred.reject);\n      } else {\n        deferred.reject();\n      }\n      return deferred.promise;\n    };\n\n    /**\n     * @name getFallbackTranslation\n     * @private\n     *\n     * @description\n     * Returns a promise that will resolve to the translation\n     * or be rejected if no translation was found for the language.\n     * This function is currently only used for fallback language translation.\n     *\n     * @param langKey The language to translate to.\n     * @param translationId\n     * @param interpolateParams\n     * @param Interpolator\n     * @param sanitizeStrategy\n     * @returns {Q.promise}\n     */\n    var getFallbackTranslation = function (langKey, translationId, interpolateParams, Interpolator, sanitizeStrategy) {\n      var deferred = $q.defer();\n\n      var onResolve = function (translationTable) {\n        if (Object.prototype.hasOwnProperty.call(translationTable, translationId) && translationTable[translationId] !== null) {\n          Interpolator.setLocale(langKey);\n          var translation = translationTable[translationId];\n          if (translation.substr(0, 2) === '@:') {\n            getFallbackTranslation(langKey, translation.substr(2), interpolateParams, Interpolator, sanitizeStrategy)\n              .then(deferred.resolve, deferred.reject);\n          } else {\n            var interpolatedValue = Interpolator.interpolate(translationTable[translationId], interpolateParams, 'service', sanitizeStrategy, translationId);\n            interpolatedValue = applyPostProcessing(translationId, translationTable[translationId], interpolatedValue, interpolateParams, langKey);\n\n            deferred.resolve(interpolatedValue);\n\n          }\n          Interpolator.setLocale($uses);\n        } else {\n          deferred.reject();\n        }\n      };\n      onResolve.displayName = 'fallbackTranslationResolver';\n\n      getTranslationTable(langKey).then(onResolve, deferred.reject);\n\n      return deferred.promise;\n    };\n\n    /**\n     * @name getFallbackTranslationInstant\n     * @private\n     *\n     * @description\n     * Returns a translation\n     * This function is currently only used for fallback language translation.\n     *\n     * @param langKey The language to translate to.\n     * @param translationId\n     * @param interpolateParams\n     * @param Interpolator\n     * @param sanitizeStrategy sanitize strategy override\n     *\n     * @returns {string} translation\n     */\n    var getFallbackTranslationInstant = function (langKey, translationId, interpolateParams, Interpolator, sanitizeStrategy) {\n      var result, translationTable = $translationTable[langKey];\n\n      if (translationTable && Object.prototype.hasOwnProperty.call(translationTable, translationId) && translationTable[translationId] !== null) {\n        Interpolator.setLocale(langKey);\n        result = Interpolator.interpolate(translationTable[translationId], interpolateParams, 'filter', sanitizeStrategy, translationId);\n        result = applyPostProcessing(translationId, translationTable[translationId], result, interpolateParams, langKey, sanitizeStrategy);\n        // workaround for TrustedValueHolderType\n        if (!angular.isString(result) && angular.isFunction(result.$$unwrapTrustedValue)) {\n          var result2 = result.$$unwrapTrustedValue();\n          if (result2.substr(0, 2) === '@:') {\n            return getFallbackTranslationInstant(langKey, result2.substr(2), interpolateParams, Interpolator, sanitizeStrategy);\n          }\n        } else if (result.substr(0, 2) === '@:') {\n          return getFallbackTranslationInstant(langKey, result.substr(2), interpolateParams, Interpolator, sanitizeStrategy);\n        }\n        Interpolator.setLocale($uses);\n      }\n\n      return result;\n    };\n\n\n    /**\n     * @name translateByHandler\n     * @private\n     *\n     * Translate by missing translation handler.\n     *\n     * @param translationId\n     * @param interpolateParams\n     * @param defaultTranslationText\n     * @param sanitizeStrategy sanitize strategy override\n     *\n     * @returns translation created by $missingTranslationHandler or translationId is $missingTranslationHandler is\n     * absent\n     */\n    var translateByHandler = function (translationId, interpolateParams, defaultTranslationText, sanitizeStrategy) {\n      // If we have a handler factory - we might also call it here to determine if it provides\n      // a default text for a translationid that can't be found anywhere in our tables\n      if ($missingTranslationHandlerFactory) {\n        return $injector.get($missingTranslationHandlerFactory)(translationId, $uses, interpolateParams, defaultTranslationText, sanitizeStrategy);\n      } else {\n        return translationId;\n      }\n    };\n\n    /**\n     * @name resolveForFallbackLanguage\n     * @private\n     *\n     * Recursive helper function for fallbackTranslation that will sequentially look\n     * for a translation in the fallbackLanguages starting with fallbackLanguageIndex.\n     *\n     * @param fallbackLanguageIndex\n     * @param translationId\n     * @param interpolateParams\n     * @param Interpolator\n     * @param defaultTranslationText\n     * @param sanitizeStrategy\n     * @returns {Q.promise} Promise that will resolve to the translation.\n     */\n    var resolveForFallbackLanguage = function (fallbackLanguageIndex, translationId, interpolateParams, Interpolator, defaultTranslationText, sanitizeStrategy) {\n      var deferred = $q.defer();\n\n      if (fallbackLanguageIndex < $fallbackLanguage.length) {\n        var langKey = $fallbackLanguage[fallbackLanguageIndex];\n        getFallbackTranslation(langKey, translationId, interpolateParams, Interpolator, sanitizeStrategy).then(\n          function (data) {\n            deferred.resolve(data);\n          },\n          function () {\n            // Look in the next fallback language for a translation.\n            // It delays the resolving by passing another promise to resolve.\n            return resolveForFallbackLanguage(fallbackLanguageIndex + 1, translationId, interpolateParams, Interpolator, defaultTranslationText, sanitizeStrategy).then(deferred.resolve, deferred.reject);\n          }\n        );\n      } else {\n        // No translation found in any fallback language\n        // if a default translation text is set in the directive, then return this as a result\n        if (defaultTranslationText) {\n          deferred.resolve(defaultTranslationText);\n        } else {\n          var missingTranslationHandlerTranslation = translateByHandler(translationId, interpolateParams, defaultTranslationText);\n\n          // if no default translation is set and an error handler is defined, send it to the handler\n          // and then return the result if it isn't undefined\n          if ($missingTranslationHandlerFactory && missingTranslationHandlerTranslation) {\n            deferred.resolve(missingTranslationHandlerTranslation);\n          } else {\n            deferred.reject(applyNotFoundIndicators(translationId));\n          }\n        }\n      }\n      return deferred.promise;\n    };\n\n    /**\n     * @name resolveForFallbackLanguageInstant\n     * @private\n     *\n     * Recursive helper function for fallbackTranslation that will sequentially look\n     * for a translation in the fallbackLanguages starting with fallbackLanguageIndex.\n     *\n     * @param fallbackLanguageIndex\n     * @param translationId\n     * @param interpolateParams\n     * @param Interpolator\n     * @param sanitizeStrategy\n     * @returns {string} translation\n     */\n    var resolveForFallbackLanguageInstant = function (fallbackLanguageIndex, translationId, interpolateParams, Interpolator, sanitizeStrategy) {\n      var result;\n\n      if (fallbackLanguageIndex < $fallbackLanguage.length) {\n        var langKey = $fallbackLanguage[fallbackLanguageIndex];\n        result = getFallbackTranslationInstant(langKey, translationId, interpolateParams, Interpolator, sanitizeStrategy);\n        if (!result && result !== '') {\n          result = resolveForFallbackLanguageInstant(fallbackLanguageIndex + 1, translationId, interpolateParams, Interpolator);\n        }\n      }\n      return result;\n    };\n\n    /**\n     * Translates with the usage of the fallback languages.\n     *\n     * @param translationId\n     * @param interpolateParams\n     * @param Interpolator\n     * @param defaultTranslationText\n     * @param sanitizeStrategy\n     * @returns {Q.promise} Promise, that resolves to the translation.\n     */\n    var fallbackTranslation = function (translationId, interpolateParams, Interpolator, defaultTranslationText, sanitizeStrategy) {\n      // Start with the fallbackLanguage with index 0\n      return resolveForFallbackLanguage((startFallbackIteration > 0 ? startFallbackIteration : fallbackIndex), translationId, interpolateParams, Interpolator, defaultTranslationText, sanitizeStrategy);\n    };\n\n    /**\n     * Translates with the usage of the fallback languages.\n     *\n     * @param translationId\n     * @param interpolateParams\n     * @param Interpolator\n     * @param sanitizeStrategy\n     * @returns {String} translation\n     */\n    var fallbackTranslationInstant = function (translationId, interpolateParams, Interpolator, sanitizeStrategy) {\n      // Start with the fallbackLanguage with index 0\n      return resolveForFallbackLanguageInstant((startFallbackIteration > 0 ? startFallbackIteration : fallbackIndex), translationId, interpolateParams, Interpolator, sanitizeStrategy);\n    };\n\n    var determineTranslation = function (translationId, interpolateParams, interpolationId, defaultTranslationText, uses, sanitizeStrategy) {\n\n      var deferred = $q.defer();\n\n      var table = uses ? $translationTable[uses] : $translationTable,\n        Interpolator = (interpolationId) ? interpolatorHashMap[interpolationId] : defaultInterpolator;\n\n      // if the translation id exists, we can just interpolate it\n      if (table && Object.prototype.hasOwnProperty.call(table, translationId) && table[translationId] !== null) {\n        var translation = table[translationId];\n\n        // If using link, rerun $translate with linked translationId and return it\n        if (translation.substr(0, 2) === '@:') {\n\n          $translate(translation.substr(2), interpolateParams, interpolationId, defaultTranslationText, uses)\n            .then(deferred.resolve, deferred.reject);\n        } else {\n          //\n          var resolvedTranslation = Interpolator.interpolate(translation, interpolateParams, 'service', sanitizeStrategy, translationId);\n          resolvedTranslation = applyPostProcessing(translationId, translation, resolvedTranslation, interpolateParams, uses);\n          deferred.resolve(resolvedTranslation);\n        }\n      } else {\n        var missingTranslationHandlerTranslation;\n        // for logging purposes only (as in $translateMissingTranslationHandlerLog), value is not returned to promise\n        if ($missingTranslationHandlerFactory && !pendingLoader) {\n          missingTranslationHandlerTranslation = translateByHandler(translationId, interpolateParams, defaultTranslationText);\n        }\n\n        // since we couldn't translate the inital requested translation id,\n        // we try it now with one or more fallback languages, if fallback language(s) is\n        // configured.\n        if (uses && $fallbackLanguage && $fallbackLanguage.length) {\n          fallbackTranslation(translationId, interpolateParams, Interpolator, defaultTranslationText, sanitizeStrategy)\n            .then(function (translation) {\n              deferred.resolve(translation);\n            }, function (_translationId) {\n              deferred.reject(applyNotFoundIndicators(_translationId));\n            });\n        } else if ($missingTranslationHandlerFactory && !pendingLoader && missingTranslationHandlerTranslation) {\n          // looks like the requested translation id doesn't exists.\n          // Now, if there is a registered handler for missing translations and no\n          // asyncLoader is pending, we execute the handler\n          if (defaultTranslationText) {\n            deferred.resolve(defaultTranslationText);\n          } else {\n            deferred.resolve(missingTranslationHandlerTranslation);\n          }\n        } else {\n          if (defaultTranslationText) {\n            deferred.resolve(defaultTranslationText);\n          } else {\n            deferred.reject(applyNotFoundIndicators(translationId));\n          }\n        }\n      }\n      return deferred.promise;\n    };\n\n    var determineTranslationInstant = function (translationId, interpolateParams, interpolationId, uses, sanitizeStrategy) {\n\n      var result, table = uses ? $translationTable[uses] : $translationTable,\n        Interpolator = defaultInterpolator;\n\n      // if the interpolation id exists use custom interpolator\n      if (interpolatorHashMap && Object.prototype.hasOwnProperty.call(interpolatorHashMap, interpolationId)) {\n        Interpolator = interpolatorHashMap[interpolationId];\n      }\n\n      // if the translation id exists, we can just interpolate it\n      if (table && Object.prototype.hasOwnProperty.call(table, translationId) && table[translationId] !== null) {\n        var translation = table[translationId];\n\n        // If using link, rerun $translate with linked translationId and return it\n        if (translation.substr(0, 2) === '@:') {\n          result = determineTranslationInstant(translation.substr(2), interpolateParams, interpolationId, uses, sanitizeStrategy);\n        } else {\n          result = Interpolator.interpolate(translation, interpolateParams, 'filter', sanitizeStrategy, translationId);\n          result = applyPostProcessing(translationId, translation, result, interpolateParams, uses, sanitizeStrategy);\n        }\n      } else {\n        var missingTranslationHandlerTranslation;\n        // for logging purposes only (as in $translateMissingTranslationHandlerLog), value is not returned to promise\n        if ($missingTranslationHandlerFactory && !pendingLoader) {\n          missingTranslationHandlerTranslation = translateByHandler(translationId, interpolateParams, sanitizeStrategy);\n        }\n\n        // since we couldn't translate the inital requested translation id,\n        // we try it now with one or more fallback languages, if fallback language(s) is\n        // configured.\n        if (uses && $fallbackLanguage && $fallbackLanguage.length) {\n          fallbackIndex = 0;\n          result = fallbackTranslationInstant(translationId, interpolateParams, Interpolator, sanitizeStrategy);\n        } else if ($missingTranslationHandlerFactory && !pendingLoader && missingTranslationHandlerTranslation) {\n          // looks like the requested translation id doesn't exists.\n          // Now, if there is a registered handler for missing translations and no\n          // asyncLoader is pending, we execute the handler\n          result = missingTranslationHandlerTranslation;\n        } else {\n          result = applyNotFoundIndicators(translationId);\n        }\n      }\n\n      return result;\n    };\n\n    var clearNextLangAndPromise = function (key) {\n      if ($nextLang === key) {\n        $nextLang = undefined;\n      }\n      langPromises[key] = undefined;\n    };\n\n    var applyPostProcessing = function (translationId, translation, resolvedTranslation, interpolateParams, uses, sanitizeStrategy) {\n      var fn = postProcessFn;\n\n      if (fn) {\n\n        if (typeof(fn) === 'string') {\n          // getting on-demand instance\n          fn = $injector.get(fn);\n        }\n        if (fn) {\n          return fn(translationId, translation, resolvedTranslation, interpolateParams, uses, sanitizeStrategy);\n        }\n      }\n\n      return resolvedTranslation;\n    };\n\n    var loadTranslationsIfMissing = function (key) {\n      if (!$translationTable[key] && $loaderFactory && !langPromises[key]) {\n        langPromises[key] = loadAsync(key).then(function (translation) {\n          translations(translation.key, translation.table);\n          return translation;\n        });\n      }\n    };\n\n    /**\n     * @ngdoc function\n     * @name pascalprecht.translate.$translate#preferredLanguage\n     * @methodOf pascalprecht.translate.$translate\n     *\n     * @description\n     * Returns the language key for the preferred language.\n     *\n     * @param {string} langKey language String or Array to be used as preferredLanguage (changing at runtime)\n     *\n     * @return {string} preferred language key\n     */\n    $translate.preferredLanguage = function (langKey) {\n      if (langKey) {\n        setupPreferredLanguage(langKey);\n      }\n      return $preferredLanguage;\n    };\n\n    /**\n     * @ngdoc function\n     * @name pascalprecht.translate.$translate#cloakClassName\n     * @methodOf pascalprecht.translate.$translate\n     *\n     * @description\n     * Returns the configured class name for `translate-cloak` directive.\n     *\n     * @return {string} cloakClassName\n     */\n    $translate.cloakClassName = function () {\n      return $cloakClassName;\n    };\n\n    /**\n     * @ngdoc function\n     * @name pascalprecht.translate.$translate#nestedObjectDelimeter\n     * @methodOf pascalprecht.translate.$translate\n     *\n     * @description\n     * Returns the configured delimiter for nested namespaces.\n     *\n     * @return {string} nestedObjectDelimeter\n     */\n    $translate.nestedObjectDelimeter = function () {\n      return $nestedObjectDelimeter;\n    };\n\n    /**\n     * @ngdoc function\n     * @name pascalprecht.translate.$translate#fallbackLanguage\n     * @methodOf pascalprecht.translate.$translate\n     *\n     * @description\n     * Returns the language key for the fallback languages or sets a new fallback stack.\n     *\n     * @param {string=} langKey language String or Array of fallback languages to be used (to change stack at runtime)\n     *\n     * @return {string||array} fallback language key\n     */\n    $translate.fallbackLanguage = function (langKey) {\n      if (langKey !== undefined && langKey !== null) {\n        fallbackStack(langKey);\n\n        // as we might have an async loader initiated and a new translation language might have been defined\n        // we need to add the promise to the stack also. So - iterate.\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    };\n\n    /**\n     * @ngdoc function\n     * @name pascalprecht.translate.$translate#useFallbackLanguage\n     * @methodOf pascalprecht.translate.$translate\n     *\n     * @description\n     * Sets the first key of the fallback language stack to be used for translation.\n     * Therefore all languages in the fallback array BEFORE this key will be skipped!\n     *\n     * @param {string=} langKey Contains the langKey the iteration shall start with. Set to false if you want to\n     * get back to the whole stack\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\n    };\n\n    /**\n     * @ngdoc function\n     * @name pascalprecht.translate.$translate#proposedLanguage\n     * @methodOf pascalprecht.translate.$translate\n     *\n     * @description\n     * Returns the language key of language that is currently loaded asynchronously.\n     *\n     * @return {string} language key\n     */\n    $translate.proposedLanguage = function () {\n      return $nextLang;\n    };\n\n    /**\n     * @ngdoc function\n     * @name pascalprecht.translate.$translate#storage\n     * @methodOf pascalprecht.translate.$translate\n     *\n     * @description\n     * Returns registered storage.\n     *\n     * @return {object} Storage\n     */\n    $translate.storage = function () {\n      return Storage;\n    };\n\n    /**\n     * @ngdoc function\n     * @name pascalprecht.translate.$translate#negotiateLocale\n     * @methodOf pascalprecht.translate.$translate\n     *\n     * @description\n     * Returns a language key based on available languages and language aliases. If a\n     * language key cannot be resolved, returns undefined.\n     *\n     * If no or a falsy key is given, returns undefined.\n     *\n     * @param {string} [key] Language key\n     * @return {string|undefined} Language key or undefined if no language key is found.\n     */\n    $translate.negotiateLocale = negotiateLocale;\n\n    /**\n     * @ngdoc function\n     * @name pascalprecht.translate.$translate#use\n     * @methodOf pascalprecht.translate.$translate\n     *\n     * @description\n     * Tells angular-translate which language to use by given language key. This method is\n     * used to change language at runtime. It also takes care of storing the language\n     * key in a configured store to let your app remember the choosed language.\n     *\n     * When trying to 'use' a language which isn't available it tries to load it\n     * asynchronously with registered loaders.\n     *\n     * Returns promise object with loaded language file data or string of the currently used language.\n     *\n     * If no or a falsy key is given it returns the currently used language key.\n     * The returned string will be ```undefined``` if setting up $translate hasn't finished.\n     * @example\n     * $translate.use(\"en_US\").then(function(data){\n       *   $scope.text = $translate(\"HELLO\");\n       * });\n     *\n     * @param {string} [key] Language key\n     * @return {object|string} Promise with loaded language data or the language key if a falsy param was given.\n     */\n    $translate.use = function (key) {\n      if (!key) {\n        return $uses;\n      }\n\n      var deferred = $q.defer();\n      deferred.promise.then(null, angular.noop); // AJS \"Possibly unhandled rejection\"\n\n      $rootScope.$emit('$translateChangeStart', {language : key});\n\n      // Try to get the aliased language key\n      var aliasedKey = negotiateLocale(key);\n      // Ensure only registered language keys will be loaded\n      if ($availableLanguageKeys.length > 0 && !aliasedKey) {\n        return $q.reject(key);\n      }\n\n      if (aliasedKey) {\n        key = aliasedKey;\n      }\n\n      // if there isn't a translation table for the language we've requested,\n      // we load it asynchronously\n      $nextLang = key;\n      if (($forceAsyncReloadEnabled || !$translationTable[key]) && $loaderFactory && !langPromises[key]) {\n        langPromises[key] = loadAsync(key).then(function (translation) {\n          translations(translation.key, translation.table);\n          deferred.resolve(translation.key);\n          if ($nextLang === key) {\n            useLanguage(translation.key);\n          }\n          return translation;\n        }, function (key) {\n          $rootScope.$emit('$translateChangeError', {language : key});\n          deferred.reject(key);\n          $rootScope.$emit('$translateChangeEnd', {language : key});\n          return $q.reject(key);\n        });\n        langPromises[key]['finally'](function () {\n          clearNextLangAndPromise(key);\n        }).catch(angular.noop); // we don't care about errors (clearing)\n      } else if (langPromises[key]) {\n        // we are already loading this asynchronously\n        // resolve our new deferred when the old langPromise is resolved\n        langPromises[key].then(function (translation) {\n          if ($nextLang === translation.key) {\n            useLanguage(translation.key);\n          }\n          deferred.resolve(translation.key);\n          return translation;\n        }, function (key) {\n          // find first available fallback language if that request has failed\n          if (!$uses && $fallbackLanguage && $fallbackLanguage.length > 0 && $fallbackLanguage[0] !== key) {\n            return $translate.use($fallbackLanguage[0]).then(deferred.resolve, deferred.reject);\n          } else {\n            return deferred.reject(key);\n          }\n        });\n      } else {\n        deferred.resolve(key);\n        useLanguage(key);\n      }\n\n      return deferred.promise;\n    };\n\n    /**\n     * @ngdoc function\n     * @name pascalprecht.translate.$translate#resolveClientLocale\n     * @methodOf pascalprecht.translate.$translate\n     *\n     * @description\n     * This returns the current browser/client's language key. The result is processed with the configured uniform tag resolver.\n     *\n     * @returns {string} the current client/browser language key\n     */\n    $translate.resolveClientLocale = function () {\n      return getLocale();\n    };\n\n    /**\n     * @ngdoc function\n     * @name pascalprecht.translate.$translate#storageKey\n     * @methodOf pascalprecht.translate.$translate\n     *\n     * @description\n     * Returns the key for the storage.\n     *\n     * @return {string} storage key\n     */\n    $translate.storageKey = function () {\n      return storageKey();\n    };\n\n    /**\n     * @ngdoc function\n     * @name pascalprecht.translate.$translate#isPostCompilingEnabled\n     * @methodOf pascalprecht.translate.$translate\n     *\n     * @description\n     * Returns whether post compiling is enabled or not\n     *\n     * @return {bool} storage key\n     */\n    $translate.isPostCompilingEnabled = function () {\n      return $postCompilingEnabled;\n    };\n\n    /**\n     * @ngdoc function\n     * @name pascalprecht.translate.$translate#isForceAsyncReloadEnabled\n     * @methodOf pascalprecht.translate.$translate\n     *\n     * @description\n     * Returns whether force async reload is enabled or not\n     *\n     * @return {boolean} forceAsyncReload value\n     */\n    $translate.isForceAsyncReloadEnabled = function () {\n      return $forceAsyncReloadEnabled;\n    };\n\n    /**\n     * @ngdoc function\n     * @name pascalprecht.translate.$translate#isKeepContent\n     * @methodOf pascalprecht.translate.$translate\n     *\n     * @description\n     * Returns whether keepContent or not\n     *\n     * @return {boolean} keepContent value\n     */\n    $translate.isKeepContent = function () {\n      return $keepContent;\n    };\n\n    /**\n     * @ngdoc function\n     * @name pascalprecht.translate.$translate#refresh\n     * @methodOf pascalprecht.translate.$translate\n     *\n     * @description\n     * Refreshes a translation table pointed by the given langKey. If langKey is not specified,\n     * the module will drop all existent translation tables and load new version of those which\n     * are currently in use.\n     *\n     * Refresh means that the module will drop target translation table and try to load it again.\n     *\n     * In case there are no loaders registered the refresh() method will throw an Error.\n     *\n     * If the module is able to refresh translation tables refresh() method will broadcast\n     * $translateRefreshStart and $translateRefreshEnd events.\n     *\n     * @example\n     * // this will drop all currently existent translation tables and reload those which are\n     * // currently in use\n     * $translate.refresh();\n     * // this will refresh a translation table for the en_US language\n     * $translate.refresh('en_US');\n     *\n     * @param {string} langKey A language key of the table, which has to be refreshed\n     *\n     * @return {promise} Promise, which will be resolved in case a translation tables refreshing\n     * process is finished successfully, and reject if not.\n     */\n    $translate.refresh = function (langKey) {\n      if (!$loaderFactory) {\n        throw new Error('Couldn\\'t refresh translation table, no loader registered!');\n      }\n\n      $rootScope.$emit('$translateRefreshStart', {language : langKey});\n\n      var deferred = $q.defer(), updatedLanguages = {};\n\n      //private helper\n      function loadNewData(languageKey) {\n        var promise = loadAsync(languageKey);\n        //update the load promise cache for this language\n        langPromises[languageKey] = promise;\n        //register a data handler for the promise\n        promise.then(function (data) {\n            //clear the cache for this language\n            $translationTable[languageKey] = {};\n            //add the new data for this language\n            translations(languageKey, data.table);\n            //track that we updated this language\n            updatedLanguages[languageKey] = true;\n          },\n          //handle rejection to appease the $q validation\n          angular.noop);\n        return promise;\n      }\n\n      //set up post-processing\n      deferred.promise.then(\n        function () {\n          for (var key in $translationTable) {\n            if ($translationTable.hasOwnProperty(key)) {\n              //delete cache entries that were not updated\n              if (!(key in updatedLanguages)) {\n                delete $translationTable[key];\n              }\n            }\n          }\n          if ($uses) {\n            useLanguage($uses);\n          }\n        },\n        //handle rejection to appease the $q validation\n        angular.noop\n      ).finally(\n        function () {\n          $rootScope.$emit('$translateRefreshEnd', {language : langKey});\n        }\n      );\n\n      if (!langKey) {\n        // if there's no language key specified we refresh ALL THE THINGS!\n        var languagesToReload = $fallbackLanguage && $fallbackLanguage.slice() || [];\n        if ($uses && languagesToReload.indexOf($uses) === -1) {\n          languagesToReload.push($uses);\n        }\n        $q.all(languagesToReload.map(loadNewData)).then(deferred.resolve, deferred.reject);\n\n      } else if ($translationTable[langKey]) {\n        //just refresh the specified language cache\n        loadNewData(langKey).then(deferred.resolve, deferred.reject);\n\n      } else {\n        deferred.reject();\n      }\n\n      return deferred.promise;\n    };\n\n    /**\n     * @ngdoc function\n     * @name pascalprecht.translate.$translate#instant\n     * @methodOf pascalprecht.translate.$translate\n     *\n     * @description\n     * Returns a translation instantly from the internal state of loaded translation. All rules\n     * regarding the current language, the preferred language of even fallback languages will be\n     * used except any promise handling. If a language was not found, an asynchronous loading\n     * will be invoked in the background.\n     *\n     * @param {string|array} translationId A token which represents a translation id\n     *                                     This can be optionally an array of translation ids which\n     *                                     results that the function's promise returns an object where\n     *                                     each key is the translation id and the value the translation.\n     * @param {object} interpolateParams Params\n     * @param {string} interpolationId The id of the interpolation to use\n     * @param {string} forceLanguage A language to be used instead of the current language\n     * @param {string} sanitizeStrategy force sanitize strategy for this call instead of using the configured one\n     *\n     * @return {string|object} translation\n     */\n    $translate.instant = function (translationId, interpolateParams, interpolationId, forceLanguage, sanitizeStrategy) {\n\n      // we don't want to re-negotiate $uses\n      var uses = (forceLanguage && forceLanguage !== $uses) ? // we don't want to re-negotiate $uses\n        (negotiateLocale(forceLanguage) || forceLanguage) : $uses;\n\n      // Detect undefined and null values to shorten the execution and prevent exceptions\n      if (translationId === null || angular.isUndefined(translationId)) {\n        return translationId;\n      }\n\n      // Check forceLanguage is present\n      if (forceLanguage) {\n        loadTranslationsIfMissing(forceLanguage);\n      }\n\n      // Duck detection: If the first argument is an array, a bunch of translations was requested.\n      // The result is an object.\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, forceLanguage, sanitizeStrategy);\n        }\n        return results;\n      }\n\n      // We discarded unacceptable values. So we just need to verify if translationId is empty String\n      if (angular.isString(translationId) && translationId.length < 1) {\n        return translationId;\n      }\n\n      // trim off any whitespace\n      if (translationId) {\n        translationId = trim.apply(translationId);\n      }\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, uses, sanitizeStrategy);\n          }\n        }\n        if (typeof result !== 'undefined') {\n          break;\n        }\n      }\n\n      if (!result && result !== '') {\n        if ($notFoundIndicatorLeft || $notFoundIndicatorRight) {\n          result = applyNotFoundIndicators(translationId);\n        } else {\n          // Return translation of default interpolator if not found anything.\n          result = defaultInterpolator.interpolate(translationId, interpolateParams, 'filter', sanitizeStrategy);\n\n          // looks like the requested translation id doesn't exists.\n          // Now, if there is a registered handler for missing translations and no\n          // asyncLoader is pending, we execute the handler\n          var missingTranslationHandlerTranslation;\n          if ($missingTranslationHandlerFactory && !pendingLoader) {\n            missingTranslationHandlerTranslation = translateByHandler(translationId, interpolateParams, sanitizeStrategy);\n          }\n\n          if ($missingTranslationHandlerFactory && !pendingLoader && missingTranslationHandlerTranslation) {\n            result = missingTranslationHandlerTranslation;\n          }\n        }\n      }\n\n      return result;\n    };\n\n    /**\n     * @ngdoc function\n     * @name pascalprecht.translate.$translate#versionInfo\n     * @methodOf pascalprecht.translate.$translate\n     *\n     * @description\n     * Returns the current version information for the angular-translate library\n     *\n     * @return {string} angular-translate version\n     */\n    $translate.versionInfo = function () {\n      return version;\n    };\n\n    /**\n     * @ngdoc function\n     * @name pascalprecht.translate.$translate#loaderCache\n     * @methodOf pascalprecht.translate.$translate\n     *\n     * @description\n     * Returns the defined loaderCache.\n     *\n     * @return {boolean|string|object} current value of loaderCache\n     */\n    $translate.loaderCache = function () {\n      return loaderCache;\n    };\n\n    // internal purpose only\n    $translate.directivePriority = function () {\n      return directivePriority;\n    };\n\n    // internal purpose only\n    $translate.statefulFilter = function () {\n      return statefulFilter;\n    };\n\n    /**\n     * @ngdoc function\n     * @name pascalprecht.translate.$translate#isReady\n     * @methodOf pascalprecht.translate.$translate\n     *\n     * @description\n     * Returns whether the service is \"ready\" to translate (i.e. loading 1st language).\n     *\n     * See also {@link pascalprecht.translate.$translate#methods_onReady onReady()}.\n     *\n     * @return {boolean} current value of ready\n     */\n    $translate.isReady = function () {\n      return $isReady;\n    };\n\n    var $onReadyDeferred = $q.defer();\n    $onReadyDeferred.promise.then(function () {\n      $isReady = true;\n    });\n\n    /**\n     * @ngdoc function\n     * @name pascalprecht.translate.$translate#onReady\n     * @methodOf pascalprecht.translate.$translate\n     *\n     * @description\n     * Calls the function provided or resolved the returned promise after the service is \"ready\" to translate (i.e. loading 1st language).\n     *\n     * See also {@link pascalprecht.translate.$translate#methods_isReady isReady()}.\n     *\n     * @param {Function=} fn Function to invoke when service is ready\n     * @return {object} Promise resolved when service is ready\n     */\n    $translate.onReady = function (fn) {\n      var deferred = $q.defer();\n      if (angular.isFunction(fn)) {\n        deferred.promise.then(fn);\n      }\n      if ($isReady) {\n        deferred.resolve();\n      } else {\n        $onReadyDeferred.promise.then(deferred.resolve);\n      }\n      return deferred.promise;\n    };\n\n    /**\n     * @ngdoc function\n     * @name pascalprecht.translate.$translate#getAvailableLanguageKeys\n     * @methodOf pascalprecht.translate.$translate\n     *\n     * @description\n     * This function simply returns the registered language keys being defined before in the config phase\n     * With this, an application can use the array to provide a language selection dropdown or similar\n     * without any additional effort\n     *\n     * @returns {object} returns the list of possibly registered language keys and mapping or null if not defined\n     */\n    $translate.getAvailableLanguageKeys = function () {\n      if ($availableLanguageKeys.length > 0) {\n        return $availableLanguageKeys;\n      }\n      return null;\n    };\n\n    /**\n     * @ngdoc function\n     * @name pascalprecht.translate.$translate#getTranslationTable\n     * @methodOf pascalprecht.translate.$translate\n     *\n     * @description\n     * Returns translation table by the given language key.\n     *\n     * Unless a language is provided it returns a translation table of the current one.\n     * Note: If translation dictionary is currently downloading or in progress\n     * it will return null.\n     *\n     * @param {string} langKey A token which represents a translation id\n     *\n     * @return {object} a copy of angular-translate $translationTable\n     */\n    $translate.getTranslationTable = function (langKey) {\n      langKey = langKey || $translate.use();\n      if (langKey && $translationTable[langKey]) {\n        return angular.copy($translationTable[langKey]);\n      }\n      return null;\n    };\n\n    // Whenever $translateReady is being fired, this will ensure the state of $isReady\n    var globalOnReadyListener = $rootScope.$on('$translateReady', function () {\n      $onReadyDeferred.resolve();\n      globalOnReadyListener(); // one time only\n      globalOnReadyListener = null;\n    });\n    var globalOnChangeListener = $rootScope.$on('$translateChangeEnd', function () {\n      $onReadyDeferred.resolve();\n      globalOnChangeListener(); // one time only\n      globalOnChangeListener = null;\n    });\n\n    if ($loaderFactory) {\n\n      // If at least one async loader is defined and there are no\n      // (default) translations available we should try to load them.\n      if (angular.equals($translationTable, {})) {\n        if ($translate.use()) {\n          $translate.use($translate.use());\n        }\n      }\n\n      // Also, if there are any fallback language registered, we start\n      // loading them asynchronously as soon as we can.\n      if ($fallbackLanguage && $fallbackLanguage.length) {\n        var processAsyncResult = function (translation) {\n          translations(translation.key, translation.table);\n          $rootScope.$emit('$translateChangeEnd', {language : translation.key});\n          return translation;\n        };\n        for (var i = 0, len = $fallbackLanguage.length; i < len; i++) {\n          var fallbackLanguageId = $fallbackLanguage[i];\n          if ($forceAsyncReloadEnabled || !$translationTable[fallbackLanguageId]) {\n            langPromises[fallbackLanguageId] = loadAsync(fallbackLanguageId).then(processAsyncResult);\n          }\n        }\n      }\n    } else {\n      $rootScope.$emit('$translateReady', {language : $translate.use()});\n    }\n\n    return $translate;\n  }];\n}\n\n$translate.displayName = 'displayName';\n\n/**\n * @ngdoc object\n * @name pascalprecht.translate.$translateDefaultInterpolation\n * @requires $interpolate\n *\n * @description\n * Uses angular's `$interpolate` services to interpolate strings against some values.\n *\n * Be aware to configure a proper sanitization strategy.\n *\n * See also:\n * * {@link pascalprecht.translate.$translateSanitization}\n *\n * @return {object} $translateDefaultInterpolation Interpolator service\n */\nangular.module('pascalprecht.translate').factory('$translateDefaultInterpolation', $translateDefaultInterpolation);\n\nfunction $translateDefaultInterpolation ($interpolate, $translateSanitization) {\n\n  'use strict';\n\n  var $translateInterpolator = {},\n      $locale,\n      $identifier = 'default';\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateDefaultInterpolation#setLocale\n   * @methodOf pascalprecht.translate.$translateDefaultInterpolation\n   *\n   * @description\n   * Sets current locale (this is currently not use in this interpolation).\n   *\n   * @param {string} locale Language key or locale.\n   */\n  $translateInterpolator.setLocale = function (locale) {\n    $locale = locale;\n  };\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateDefaultInterpolation#getInterpolationIdentifier\n   * @methodOf pascalprecht.translate.$translateDefaultInterpolation\n   *\n   * @description\n   * Returns an identifier for this interpolation service.\n   *\n   * @returns {string} $identifier\n   */\n  $translateInterpolator.getInterpolationIdentifier = function () {\n    return $identifier;\n  };\n\n  /**\n   * @deprecated will be removed in 3.0\n   * @see {@link pascalprecht.translate.$translateSanitization}\n   */\n  $translateInterpolator.useSanitizeValueStrategy = function (value) {\n    $translateSanitization.useStrategy(value);\n    return this;\n  };\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateDefaultInterpolation#interpolate\n   * @methodOf pascalprecht.translate.$translateDefaultInterpolation\n   *\n   * @description\n   * Interpolates given value agains given interpolate params using angulars\n   * `$interpolate` service.\n   *\n   * Since AngularJS 1.5, `value` must not be a string but can be anything input.\n   *\n   * @param {string} value translation\n   * @param {object} interpolationParams interpolation params\n   * @param {string} context current context (filter, directive, service)\n   * @param {string} sanitizeStrategy sanitize strategy\n   * @param {string} translationId current translationId\n   *\n   * @returns {string} interpolated string\n   */\n  $translateInterpolator.interpolate = function (value, interpolationParams, context, sanitizeStrategy, translationId) { // jshint ignore:line\n    interpolationParams = interpolationParams || {};\n    interpolationParams = $translateSanitization.sanitize(interpolationParams, 'params', sanitizeStrategy, context);\n\n    var interpolatedText;\n    if (angular.isNumber(value)) {\n      // numbers are safe\n      interpolatedText = '' + value;\n    } else if (angular.isString(value)) {\n      // strings must be interpolated (that's the job here)\n      interpolatedText = $interpolate(value)(interpolationParams);\n      interpolatedText = $translateSanitization.sanitize(interpolatedText, 'text', sanitizeStrategy, context);\n    } else {\n      // neither a number or a string, cant interpolate => empty string\n      interpolatedText = '';\n    }\n\n    return interpolatedText;\n  };\n\n  return $translateInterpolator;\n}\n\n$translateDefaultInterpolation.displayName = '$translateDefaultInterpolation';\n\nangular.module('pascalprecht.translate').constant('$STORAGE_KEY', 'NG_TRANSLATE_LANG_KEY');\n\nangular.module('pascalprecht.translate')\n/**\n * @ngdoc directive\n * @name pascalprecht.translate.directive:translate\n * @requires $interpolate, \n * @requires $compile, \n * @requires $parse, \n * @requires $rootScope\n * @restrict AE\n *\n * @description\n * Translates given translation id either through attribute or DOM content.\n * Internally it uses $translate service to translate the translation id. It possible to\n * pass an optional `translate-values` object literal as string into translation id.\n *\n * @param {string=} translate Translation id which could be either string or interpolated string.\n * @param {string=} translate-values Values to pass into translation id. Can be passed as object literal string or interpolated object.\n * @param {string=} translate-attr-ATTR translate Translation id and put it into ATTR attribute.\n * @param {string=} translate-default will be used unless translation was successful\n * @param {boolean=} translate-compile (default true if present) defines locally activation of {@link pascalprecht.translate.$translateProvider#methods_usePostCompiling}\n * @param {boolean=} translate-keep-content (default true if present) defines that in case a KEY could not be translated, that the existing content is left in the innerHTML}\n *\n * @example\n   <example module=\"ngView\">\n    <file name=\"index.html\">\n      <div ng-controller=\"TranslateCtrl\">\n\n        <pre translate=\"TRANSLATION_ID\"></pre>\n        <pre translate>TRANSLATION_ID</pre>\n        <pre translate translate-attr-title=\"TRANSLATION_ID\"></pre>\n        <pre translate=\"{{translationId}}\"></pre>\n        <pre translate>{{translationId}}</pre>\n        <pre translate=\"WITH_VALUES\" translate-values=\"{value: 5}\"></pre>\n        <pre translate translate-values=\"{value: 5}\">WITH_VALUES</pre>\n        <pre translate=\"WITH_VALUES\" translate-values=\"{{values}}\"></pre>\n        <pre translate translate-values=\"{{values}}\">WITH_VALUES</pre>\n        <pre translate translate-attr-title=\"WITH_VALUES\" translate-values=\"{{values}}\"></pre>\n        <pre translate=\"WITH_CAMEL_CASE_KEY\" translate-value-camel-case-key=\"Hi\"></pre>\n\n      </div>\n    </file>\n    <file name=\"script.js\">\n      angular.module('ngView', ['pascalprecht.translate'])\n\n      .config(function ($translateProvider) {\n\n        $translateProvider.translations('en',{\n          'TRANSLATION_ID': 'Hello there!',\n          'WITH_VALUES': 'The following value is dynamic: {{value}}',\n          'WITH_CAMEL_CASE_KEY': 'The interpolation key is camel cased: {{camelCaseKey}}'\n        }).preferredLanguage('en');\n\n      });\n\n      angular.module('ngView').controller('TranslateCtrl', function ($scope) {\n        $scope.translationId = 'TRANSLATION_ID';\n\n        $scope.values = {\n          value: 78\n        };\n      });\n    </file>\n    <file name=\"scenario.js\">\n      it('should translate', function () {\n        inject(function ($rootScope, $compile) {\n          $rootScope.translationId = 'TRANSLATION_ID';\n\n          element = $compile('<p translate=\"TRANSLATION_ID\"></p>')($rootScope);\n          $rootScope.$digest();\n          expect(element.text()).toBe('Hello there!');\n\n          element = $compile('<p translate=\"{{translationId}}\"></p>')($rootScope);\n          $rootScope.$digest();\n          expect(element.text()).toBe('Hello there!');\n\n          element = $compile('<p translate>TRANSLATION_ID</p>')($rootScope);\n          $rootScope.$digest();\n          expect(element.text()).toBe('Hello there!');\n\n          element = $compile('<p translate>{{translationId}}</p>')($rootScope);\n          $rootScope.$digest();\n          expect(element.text()).toBe('Hello there!');\n\n          element = $compile('<p translate translate-attr-title=\"TRANSLATION_ID\"></p>')($rootScope);\n          $rootScope.$digest();\n          expect(element.attr('title')).toBe('Hello there!');\n\n          element = $compile('<p translate=\"WITH_CAMEL_CASE_KEY\" translate-value-camel-case-key=\"Hello\"></p>')($rootScope);\n          $rootScope.$digest();\n          expect(element.text()).toBe('The interpolation key is camel cased: Hello');\n        });\n      });\n    </file>\n   </example>\n */\n.directive('translate', translateDirective);\nfunction translateDirective($translate, $interpolate, $compile, $parse, $rootScope) {\n\n  'use strict';\n\n  /**\n   * @name trim\n   * @private\n   *\n   * @description\n   * trim polyfill\n   *\n   * @returns {string} The string stripped of whitespace from both ends\n   */\n  var trim = function() {\n    return this.toString().replace(/^\\s+|\\s+$/g, '');\n  };\n\n  return {\n    restrict: 'AE',\n    scope: true,\n    priority: $translate.directivePriority(),\n    compile: function (tElement, tAttr) {\n\n      var translateValuesExist = (tAttr.translateValues) ?\n        tAttr.translateValues : undefined;\n\n      var translateInterpolation = (tAttr.translateInterpolation) ?\n        tAttr.translateInterpolation : undefined;\n\n      var translateValueExist = tElement[0].outerHTML.match(/translate-value-+/i);\n\n      var interpolateRegExp = '^(.*)(' + $interpolate.startSymbol() + '.*' + $interpolate.endSymbol() + ')(.*)',\n          watcherRegExp = '^(.*)' + $interpolate.startSymbol() + '(.*)' + $interpolate.endSymbol() + '(.*)';\n\n      return function linkFn(scope, iElement, iAttr) {\n\n        scope.interpolateParams = {};\n        scope.preText = '';\n        scope.postText = '';\n        scope.translateNamespace = getTranslateNamespace(scope);\n        var translationIds = {};\n\n        var initInterpolationParams = function (interpolateParams, iAttr, tAttr) {\n          // initial setup\n          if (iAttr.translateValues) {\n            angular.extend(interpolateParams, $parse(iAttr.translateValues)(scope.$parent));\n          }\n          // initially fetch all attributes if existing and fill the params\n          if (translateValueExist) {\n            for (var attr in tAttr) {\n              if (Object.prototype.hasOwnProperty.call(iAttr, attr) && attr.substr(0, 14) === 'translateValue' && attr !== 'translateValues') {\n                var attributeName = angular.lowercase(attr.substr(14, 1)) + attr.substr(15);\n                interpolateParams[attributeName] = tAttr[attr];\n              }\n            }\n          }\n        };\n\n        // Ensures any change of the attribute \"translate\" containing the id will\n        // be re-stored to the scope's \"translationId\".\n        // If the attribute has no content, the element's text value (white spaces trimmed off) will be used.\n        var observeElementTranslation = function (translationId) {\n\n          // Remove any old watcher\n          if (angular.isFunction(observeElementTranslation._unwatchOld)) {\n            observeElementTranslation._unwatchOld();\n            observeElementTranslation._unwatchOld = undefined;\n          }\n\n          if (angular.equals(translationId , '') || !angular.isDefined(translationId)) {\n            var iElementText = trim.apply(iElement.text());\n\n            // Resolve translation id by inner html if required\n            var interpolateMatches = iElementText.match(interpolateRegExp);\n            // Interpolate translation id if required\n            if (angular.isArray(interpolateMatches)) {\n              scope.preText = interpolateMatches[1];\n              scope.postText = interpolateMatches[3];\n              translationIds.translate = $interpolate(interpolateMatches[2])(scope.$parent);\n              var watcherMatches = iElementText.match(watcherRegExp);\n              if (angular.isArray(watcherMatches) && watcherMatches[2] && watcherMatches[2].length) {\n                observeElementTranslation._unwatchOld = scope.$watch(watcherMatches[2], function (newValue) {\n                  translationIds.translate = newValue;\n                  updateTranslations();\n                });\n              }\n            } else {\n              // do not assigne the translation id if it is empty.\n              translationIds.translate = !iElementText ? undefined : iElementText;\n            }\n          } else {\n            translationIds.translate = translationId;\n          }\n          updateTranslations();\n        };\n\n        var observeAttributeTranslation = function (translateAttr) {\n          iAttr.$observe(translateAttr, function (translationId) {\n            translationIds[translateAttr] = translationId;\n            updateTranslations();\n          });\n        };\n\n        // initial setup with values\n        initInterpolationParams(scope.interpolateParams, iAttr, tAttr);\n\n        var firstAttributeChangedEvent = true;\n        iAttr.$observe('translate', function (translationId) {\n          if (typeof translationId === 'undefined') {\n            // case of element \"<translate>xyz</translate>\"\n            observeElementTranslation('');\n          } else {\n            // case of regular attribute\n            if (translationId !== '' || !firstAttributeChangedEvent) {\n              translationIds.translate = translationId;\n              updateTranslations();\n            }\n          }\n          firstAttributeChangedEvent = false;\n        });\n\n        for (var translateAttr in iAttr) {\n          if (iAttr.hasOwnProperty(translateAttr) && translateAttr.substr(0, 13) === 'translateAttr' && translateAttr.length > 13) {\n            observeAttributeTranslation(translateAttr);\n          }\n        }\n\n        iAttr.$observe('translateDefault', function (value) {\n          scope.defaultText = value;\n          updateTranslations();\n        });\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\n        if (translateValueExist) {\n          var observeValueAttribute = function (attrName) {\n            iAttr.$observe(attrName, function (value) {\n              var attributeName = angular.lowercase(attrName.substr(14, 1)) + attrName.substr(15);\n              scope.interpolateParams[attributeName] = 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              observeValueAttribute(attr);\n            }\n          }\n        }\n\n        // Master update function\n        var updateTranslations = function () {\n          for (var key in translationIds) {\n            if (translationIds.hasOwnProperty(key) && translationIds[key] !== undefined) {\n              updateTranslation(key, translationIds[key], scope, scope.interpolateParams, scope.defaultText, scope.translateNamespace);\n            }\n          }\n        };\n\n        // Put translation processing function outside loop\n        var updateTranslation = function(translateAttr, translationId, scope, interpolateParams, defaultTranslationText, translateNamespace) {\n          if (translationId) {\n            // if translation id starts with '.' and translateNamespace given, prepend namespace\n            if (translateNamespace && translationId.charAt(0) === '.') {\n              translationId = translateNamespace + translationId;\n            }\n\n            $translate(translationId, interpolateParams, translateInterpolation, defaultTranslationText, scope.translateLanguage)\n              .then(function (translation) {\n                applyTranslation(translation, scope, true, translateAttr);\n              }, function (translationId) {\n                applyTranslation(translationId, scope, false, translateAttr);\n              });\n          } else {\n            // as an empty string cannot be translated, we can solve this using successful=false\n            applyTranslation(translationId, scope, false, translateAttr);\n          }\n        };\n\n        var applyTranslation = function (value, scope, successful, translateAttr) {\n          if (!successful) {\n            if (typeof scope.defaultText !== 'undefined') {\n              value = scope.defaultText;\n            }\n          }\n          if (translateAttr === 'translate') {\n            // default translate into innerHTML\n            if (successful || (!successful && !$translate.isKeepContent() && typeof iAttr.translateKeepContent === 'undefined')) {\n              iElement.empty().append(scope.preText + value + scope.postText);\n            }\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          } else {\n            // translate attribute\n            var attributeName = iAttr.$attr[translateAttr];\n            if (attributeName.substr(0, 5) === 'data-') {\n              // ensure html5 data prefix is stripped\n              attributeName = attributeName.substr(5);\n            }\n            attributeName = attributeName.substr(15);\n            iElement.attr(attributeName, value);\n          }\n        };\n\n        if (translateValuesExist || translateValueExist || iAttr.translateDefault) {\n          scope.$watch('interpolateParams', updateTranslations, true);\n        }\n\n        // Replaced watcher on translateLanguage with event listener\n        scope.$on('translateLanguageChanged', updateTranslations);\n\n        // Ensures the text will be refreshed after the current language was changed\n        // w/ $translate.use(...)\n        var unbind = $rootScope.$on('$translateChangeSuccess', updateTranslations);\n\n        // ensure translation will be looked up at least one\n        if (iElement.text().length) {\n          if (iAttr.translate) {\n            observeElementTranslation(iAttr.translate);\n          } else {\n            observeElementTranslation('');\n          }\n        } else if (iAttr.translate) {\n          // ensure attribute will be not skipped\n          observeElementTranslation(iAttr.translate);\n        }\n        updateTranslations();\n        scope.$on('$destroy', unbind);\n      };\n    }\n  };\n}\n\n/**\n * Returns the scope's namespace.\n * @private\n * @param scope\n * @returns {string}\n */\nfunction getTranslateNamespace(scope) {\n  'use strict';\n  if (scope.translateNamespace) {\n    return scope.translateNamespace;\n  }\n  if (scope.$parent) {\n    return getTranslateNamespace(scope.$parent);\n  }\n}\n\ntranslateDirective.displayName = 'translateDirective';\n\nangular.module('pascalprecht.translate')\n/**\n * @ngdoc directive\n * @name pascalprecht.translate.directive:translate-attr\n * @restrict A\n *\n * @description\n * Translates attributes like translate-attr-ATTR, but with an object like ng-class.\n * Internally it uses `translate` service to translate translation id. It possible to\n * pass an optional `translate-values` object literal as string into translation id.\n *\n * @param {string=} translate-attr Object literal mapping attributes to translation ids.\n * @param {string=} translate-values Values to pass into the translation ids. Can be passed as object literal string.\n *\n * @example\n   <example module=\"ngView\">\n    <file name=\"index.html\">\n      <div ng-controller=\"TranslateCtrl\">\n\n        <input translate-attr=\"{ placeholder: translationId, title: 'WITH_VALUES' }\" translate-values=\"{value: 5}\" />\n\n      </div>\n    </file>\n    <file name=\"script.js\">\n      angular.module('ngView', ['pascalprecht.translate'])\n\n      .config(function ($translateProvider) {\n\n        $translateProvider.translations('en',{\n          'TRANSLATION_ID': 'Hello there!',\n          'WITH_VALUES': 'The following value is dynamic: {{value}}',\n        }).preferredLanguage('en');\n\n      });\n\n      angular.module('ngView').controller('TranslateCtrl', function ($scope) {\n        $scope.translationId = 'TRANSLATION_ID';\n\n        $scope.values = {\n          value: 78\n        };\n      });\n    </file>\n    <file name=\"scenario.js\">\n      it('should translate', function () {\n        inject(function ($rootScope, $compile) {\n          $rootScope.translationId = 'TRANSLATION_ID';\n\n          element = $compile('<input translate-attr=\"{ placeholder: translationId, title: 'WITH_VALUES' }\" translate-values=\"{ value: 5 }\" />')($rootScope);\n          $rootScope.$digest();\n          expect(element.attr('placeholder)).toBe('Hello there!');\n          expect(element.attr('title)).toBe('The following value is dynamic: 5');\n        });\n      });\n    </file>\n   </example>\n */\n.directive('translateAttr', translateAttrDirective);\nfunction translateAttrDirective($translate, $rootScope) {\n\n  'use strict';\n\n  return {\n    restrict: 'A',\n    priority: $translate.directivePriority(),\n    link: function linkFn(scope, element, attr) {\n\n      var translateAttr,\n          translateValues,\n          previousAttributes = {};\n\n      // Main update translations function\n      var updateTranslations = function () {\n        angular.forEach(translateAttr, function (translationId, attributeName) {\n          if (!translationId) {\n            return;\n          }\n          previousAttributes[attributeName] = true;\n\n          // if translation id starts with '.' and translateNamespace given, prepend namespace\n          if (scope.translateNamespace && translationId.charAt(0) === '.') {\n            translationId = scope.translateNamespace + translationId;\n          }\n          $translate(translationId, translateValues, attr.translateInterpolation, undefined, scope.translateLanguage)\n            .then(function (translation) {\n              element.attr(attributeName, translation);\n            }, function (translationId) {\n              element.attr(attributeName, translationId);\n            });\n        });\n\n        // Removing unused attributes that were previously used\n        angular.forEach(previousAttributes, function (flag, attributeName) {\n          if (!translateAttr[attributeName]) {\n            element.removeAttr(attributeName);\n            delete previousAttributes[attributeName];\n          }\n        });\n      };\n\n      // Watch for attribute changes\n      watchAttribute(\n        scope,\n        attr.translateAttr,\n        function (newValue) { translateAttr = newValue; },\n        updateTranslations\n      );\n      // Watch for value changes\n      watchAttribute(\n        scope,\n        attr.translateValues,\n        function (newValue) { translateValues = newValue; },\n        updateTranslations\n      );\n\n      if (attr.translateValues) {\n        scope.$watch(attr.translateValues, updateTranslations, true);\n      }\n\n      // Replaced watcher on translateLanguage with event listener\n      scope.$on('translateLanguageChanged', updateTranslations);\n\n      // Ensures the text will be refreshed after the current language was changed\n      // w/ $translate.use(...)\n      var unbind = $rootScope.$on('$translateChangeSuccess', updateTranslations);\n\n      updateTranslations();\n      scope.$on('$destroy', unbind);\n    }\n  };\n}\n\nfunction watchAttribute(scope, attribute, valueCallback, changeCallback) {\n  'use strict';\n  if (!attribute) {\n    return;\n  }\n  if (attribute.substr(0, 2) === '::') {\n    attribute = attribute.substr(2);\n  } else {\n    scope.$watch(attribute, function(newValue) {\n      valueCallback(newValue);\n      changeCallback();\n    }, true);\n  }\n  valueCallback(scope.$eval(attribute));\n}\n\ntranslateAttrDirective.displayName = 'translateAttrDirective';\n\nangular.module('pascalprecht.translate')\n/**\n * @ngdoc directive\n * @name pascalprecht.translate.directive:translateCloak\n * @requires $translate\n * @restrict A\n *\n * $description\n * Adds a `translate-cloak` class name to the given element where this directive\n * is applied initially and removes it, once a loader has finished loading.\n *\n * This directive can be used to prevent initial flickering when loading translation\n * data asynchronously.\n *\n * The class name is defined in\n * {@link pascalprecht.translate.$translateProvider#cloakClassName $translate.cloakClassName()}.\n *\n * @param {string=} translate-cloak If a translationId is provided, it will be used for showing\n *                                  or hiding the cloak. Basically it relies on the translation\n *                                  resolve.\n */\n.directive('translateCloak', translateCloakDirective);\n\nfunction translateCloakDirective($translate, $rootScope) {\n\n  'use strict';\n\n  return {\n    compile : function (tElement) {\n      var applyCloak = function (element) {\n          element.addClass($translate.cloakClassName());\n        },\n        removeCloak = function (element) {\n          element.removeClass($translate.cloakClassName());\n        };\n      applyCloak(tElement);\n\n      return function linkFn(scope, iElement, iAttr) {\n        //Create bound functions that incorporate the active DOM element.\n        var iRemoveCloak = removeCloak.bind(this, iElement), iApplyCloak = applyCloak.bind(this, iElement);\n        if (iAttr.translateCloak && iAttr.translateCloak.length) {\n          // Register a watcher for the defined translation allowing a fine tuned cloak\n          iAttr.$observe('translateCloak', function (translationId) {\n            $translate(translationId).then(iRemoveCloak, iApplyCloak);\n          });\n          $rootScope.$on('$translateChangeSuccess', function () {\n            $translate(iAttr.translateCloak).then(iRemoveCloak, iApplyCloak);\n          });\n        } else {\n          $translate.onReady(iRemoveCloak);\n        }\n      };\n    }\n  };\n}\n\ntranslateCloakDirective.displayName = 'translateCloakDirective';\n\nangular.module('pascalprecht.translate')\n/**\n * @ngdoc directive\n * @name pascalprecht.translate.directive:translateNamespace\n * @restrict A\n *\n * @description\n * Translates given translation id either through attribute or DOM content.\n * Internally it uses `translate` filter to translate translation id. It possible to\n * pass an optional `translate-values` object literal as string into translation id.\n *\n * @param {string=} translate namespace name which could be either string or interpolated string.\n *\n * @example\n   <example module=\"ngView\">\n    <file name=\"index.html\">\n      <div translate-namespace=\"CONTENT\">\n\n        <div>\n            <h1 translate>.HEADERS.TITLE</h1>\n            <h1 translate>.HEADERS.WELCOME</h1>\n        </div>\n\n        <div translate-namespace=\".HEADERS\">\n            <h1 translate>.TITLE</h1>\n            <h1 translate>.WELCOME</h1>\n        </div>\n\n      </div>\n    </file>\n    <file name=\"script.js\">\n      angular.module('ngView', ['pascalprecht.translate'])\n\n      .config(function ($translateProvider) {\n\n        $translateProvider.translations('en',{\n          'TRANSLATION_ID': 'Hello there!',\n          'CONTENT': {\n            'HEADERS': {\n                TITLE: 'Title'\n            }\n          },\n          'CONTENT.HEADERS.WELCOME': 'Welcome'\n        }).preferredLanguage('en');\n\n      });\n\n    </file>\n   </example>\n */\n.directive('translateNamespace', translateNamespaceDirective);\n\nfunction translateNamespaceDirective() {\n\n  'use strict';\n\n  return {\n    restrict: 'A',\n    scope: true,\n    compile: function () {\n      return {\n        pre: function (scope, iElement, iAttrs) {\n          scope.translateNamespace = getTranslateNamespace(scope);\n\n          if (scope.translateNamespace && iAttrs.translateNamespace.charAt(0) === '.') {\n            scope.translateNamespace += iAttrs.translateNamespace;\n          } else {\n            scope.translateNamespace = iAttrs.translateNamespace;\n          }\n        }\n      };\n    }\n  };\n}\n\n/**\n * Returns the scope's namespace.\n * @private\n * @param scope\n * @returns {string}\n */\nfunction getTranslateNamespace(scope) {\n  'use strict';\n  if (scope.translateNamespace) {\n    return scope.translateNamespace;\n  }\n  if (scope.$parent) {\n    return getTranslateNamespace(scope.$parent);\n  }\n}\n\ntranslateNamespaceDirective.displayName = 'translateNamespaceDirective';\n\nangular.module('pascalprecht.translate')\n/**\n * @ngdoc directive\n * @name pascalprecht.translate.directive:translateLanguage\n * @restrict A\n *\n * @description\n * Forces the language to the directives in the underlying scope.\n *\n * @param {string=} translate language that will be negotiated.\n *\n * @example\n   <example module=\"ngView\">\n    <file name=\"index.html\">\n      <div>\n\n        <div>\n            <h1 translate>HELLO</h1>\n        </div>\n\n        <div translate-language=\"de\">\n            <h1 translate>HELLO</h1>\n        </div>\n\n      </div>\n    </file>\n    <file name=\"script.js\">\n      angular.module('ngView', ['pascalprecht.translate'])\n\n      .config(function ($translateProvider) {\n\n        $translateProvider\n          .translations('en',{\n            'HELLO': 'Hello world!'\n          })\n          .translations('de',{\n            'HELLO': 'Hallo Welt!'\n          })\n          .preferredLanguage('en');\n\n      });\n\n    </file>\n   </example>\n */\n.directive('translateLanguage', translateLanguageDirective);\n\nfunction translateLanguageDirective() {\n\n  'use strict';\n\n  return {\n    restrict: 'A',\n    scope: true,\n    compile: function () {\n      return function linkFn(scope, iElement, iAttrs) {\n\n        iAttrs.$observe('translateLanguage', function (newTranslateLanguage) {\n          scope.translateLanguage = newTranslateLanguage;\n        });\n\n        scope.$watch('translateLanguage', function(){\n          scope.$broadcast('translateLanguageChanged');\n        });\n      };\n    }\n  };\n}\n\ntranslateLanguageDirective.displayName = 'translateLanguageDirective';\n\nangular.module('pascalprecht.translate')\n/**\n * @ngdoc filter\n * @name pascalprecht.translate.filter:translate\n * @requires $parse\n * @requires pascalprecht.translate.$translate\n * @function\n *\n * @description\n * Uses `$translate` service to translate contents. Accepts interpolate parameters\n * to pass dynamized values though translation.\n *\n * @param {string} translationId A translation id to be translated.\n * @param {*=} interpolateParams Optional object literal (as hash or string) to pass values into translation.\n *\n * @returns {string} Translated text.\n *\n * @example\n   <example module=\"ngView\">\n    <file name=\"index.html\">\n      <div ng-controller=\"TranslateCtrl\">\n\n        <pre>{{ 'TRANSLATION_ID' | translate }}</pre>\n        <pre>{{ translationId | translate }}</pre>\n        <pre>{{ 'WITH_VALUES' | translate:'{value: 5}' }}</pre>\n        <pre>{{ 'WITH_VALUES' | translate:values }}</pre>\n\n      </div>\n    </file>\n    <file name=\"script.js\">\n      angular.module('ngView', ['pascalprecht.translate'])\n\n      .config(function ($translateProvider) {\n\n        $translateProvider.translations('en', {\n          'TRANSLATION_ID': 'Hello there!',\n          'WITH_VALUES': 'The following value is dynamic: {{value}}'\n        });\n        $translateProvider.preferredLanguage('en');\n\n      });\n\n      angular.module('ngView').controller('TranslateCtrl', function ($scope) {\n        $scope.translationId = 'TRANSLATION_ID';\n\n        $scope.values = {\n          value: 78\n        };\n      });\n    </file>\n   </example>\n */\n.filter('translate', translateFilterFactory);\n\nfunction translateFilterFactory($parse, $translate) {\n\n  'use strict';\n\n  var translateFilter = function (translationId, interpolateParams, interpolation, forceLanguage) {\n    if (!angular.isObject(interpolateParams)) {\n      var ctx = this || {\n        '__SCOPE_IS_NOT_AVAILABLE': 'More info at https://github.com/angular/angular.js/commit/8863b9d04c722b278fa93c5d66ad1e578ad6eb1f'\n        };\n      interpolateParams = $parse(interpolateParams)(ctx);\n    }\n\n    return $translate.instant(translationId, interpolateParams, interpolation, forceLanguage);\n  };\n\n  if ($translate.statefulFilter()) {\n    translateFilter.$stateful = true;\n  }\n\n  return translateFilter;\n}\n\ntranslateFilterFactory.displayName = 'translateFilterFactory';\n\nangular.module('pascalprecht.translate')\n\n/**\n * @ngdoc object\n * @name pascalprecht.translate.$translationCache\n * @requires $cacheFactory\n *\n * @description\n * The first time a translation table is used, it is loaded in the translation cache for quick retrieval. You\n * can load translation tables directly into the cache by consuming the\n * `$translationCache` service directly.\n *\n * @return {object} $cacheFactory object.\n */\n  .factory('$translationCache', $translationCache);\n\nfunction $translationCache($cacheFactory) {\n\n  'use strict';\n\n  return $cacheFactory('translations');\n}\n\n$translationCache.displayName = '$translationCache';\nreturn 'pascalprecht.translate';\n\n}));\n"
  },
  {
    "path": "flowable-ui-web/task/libs/angular_1.3.13/angular.js",
    "content": "/**\n * @license AngularJS v1.3.13\n * (c) 2010-2014 Google, Inc. http://angularjs.org\n * License: MIT\n */\n(function(window, document, undefined) {'use strict';\n\n/**\n * @description\n *\n * This object provides a utility for producing rich Error messages within\n * Angular. It can be called as follows:\n *\n * var exampleMinErr = minErr('example');\n * throw exampleMinErr('one', 'This {0} is {1}', foo, bar);\n *\n * The above creates an instance of minErr in the example namespace. The\n * resulting error will have a namespaced error code of example.one.  The\n * resulting error will replace {0} with the value of foo, and {1} with the\n * value of bar. The object is not restricted in the number of arguments it can\n * take.\n *\n * If fewer arguments are specified than necessary for interpolation, the extra\n * interpolation markers will be preserved in the final string.\n *\n * Since data will be parsed statically during a build step, some restrictions\n * are applied with respect to how minErr instances are created and called.\n * Instances should have names of the form namespaceMinErr for a minErr created\n * using minErr('namespace') . Error codes, namespaces and template strings\n * should all be static strings, not variables or general expressions.\n *\n * @param {string} module The namespace to use for the new minErr instance.\n * @param {function} ErrorConstructor Custom error constructor to be instantiated when returning\n *   error from returned function, for cases when a particular type of error is useful.\n * @returns {function(code:string, template:string, ...templateArgs): Error} minErr instance\n */\n\nfunction minErr(module, ErrorConstructor) {\n  ErrorConstructor = ErrorConstructor || Error;\n  return function() {\n    var code = arguments[0],\n      prefix = '[' + (module ? module + ':' : '') + code + '] ',\n      template = arguments[1],\n      templateArgs = arguments,\n\n      message, i;\n\n    message = prefix + template.replace(/\\{\\d+\\}/g, function(match) {\n      var index = +match.slice(1, -1), arg;\n\n      if (index + 2 < templateArgs.length) {\n        return toDebugString(templateArgs[index + 2]);\n      }\n      return match;\n    });\n\n    message = message + '\\nhttp://errors.angularjs.org/1.3.13/' +\n      (module ? module + '/' : '') + code;\n    for (i = 2; i < arguments.length; i++) {\n      message = message + (i == 2 ? '?' : '&') + 'p' + (i - 2) + '=' +\n        encodeURIComponent(toDebugString(arguments[i]));\n    }\n    return new ErrorConstructor(message);\n  };\n}\n\n/* We need to tell jshint what variables are being exported */\n/* global angular: true,\n  msie: true,\n  jqLite: true,\n  jQuery: true,\n  slice: true,\n  splice: true,\n  push: true,\n  toString: true,\n  ngMinErr: true,\n  angularModule: true,\n  uid: true,\n  REGEX_STRING_REGEXP: true,\n  VALIDITY_STATE_PROPERTY: true,\n\n  lowercase: true,\n  uppercase: true,\n  manualLowercase: true,\n  manualUppercase: true,\n  nodeName_: true,\n  isArrayLike: true,\n  forEach: true,\n  sortedKeys: true,\n  forEachSorted: true,\n  reverseParams: true,\n  nextUid: true,\n  setHashKey: true,\n  extend: true,\n  int: true,\n  inherit: true,\n  noop: true,\n  identity: true,\n  valueFn: true,\n  isUndefined: true,\n  isDefined: true,\n  isObject: true,\n  isString: true,\n  isNumber: true,\n  isDate: true,\n  isArray: true,\n  isFunction: true,\n  isRegExp: true,\n  isWindow: true,\n  isScope: true,\n  isFile: true,\n  isFormData: true,\n  isBlob: true,\n  isBoolean: true,\n  isPromiseLike: true,\n  trim: true,\n  escapeForRegexp: true,\n  isElement: true,\n  makeMap: true,\n  includes: true,\n  arrayRemove: true,\n  copy: true,\n  shallowCopy: true,\n  equals: true,\n  csp: true,\n  concat: true,\n  sliceArgs: true,\n  bind: true,\n  toJsonReplacer: true,\n  toJson: true,\n  fromJson: true,\n  startingTag: true,\n  tryDecodeURIComponent: true,\n  parseKeyValue: true,\n  toKeyValue: true,\n  encodeUriSegment: true,\n  encodeUriQuery: true,\n  angularInit: true,\n  bootstrap: true,\n  getTestability: true,\n  snake_case: true,\n  bindJQuery: true,\n  assertArg: true,\n  assertArgFn: true,\n  assertNotHasOwnProperty: true,\n  getter: true,\n  getBlockNodes: true,\n  hasOwnProperty: true,\n  createMap: true,\n\n  NODE_TYPE_ELEMENT: true,\n  NODE_TYPE_TEXT: true,\n  NODE_TYPE_COMMENT: true,\n  NODE_TYPE_DOCUMENT: true,\n  NODE_TYPE_DOCUMENT_FRAGMENT: true,\n*/\n\n////////////////////////////////////\n\n/**\n * @ngdoc module\n * @name ng\n * @module ng\n * @description\n *\n * # ng (core module)\n * The ng module is loaded by default when an AngularJS application is started. The module itself\n * contains the essential components for an AngularJS application to function. The table below\n * lists a high level breakdown of each of the services/factories, filters, directives and testing\n * components available within this core module.\n *\n * <div doc-module-components=\"ng\"></div>\n */\n\nvar REGEX_STRING_REGEXP = /^\\/(.+)\\/([a-z]*)$/;\n\n// The name of a form control's ValidityState property.\n// This is used so that it's possible for internal tests to create mock ValidityStates.\nvar VALIDITY_STATE_PROPERTY = 'validity';\n\n/**\n * @ngdoc function\n * @name angular.lowercase\n * @module ng\n * @kind function\n *\n * @description Converts the specified string to lowercase.\n * @param {string} string String to be converted to lowercase.\n * @returns {string} Lowercased string.\n */\nvar lowercase = function(string) {return isString(string) ? string.toLowerCase() : string;};\nvar hasOwnProperty = Object.prototype.hasOwnProperty;\n\n/**\n * @ngdoc function\n * @name angular.uppercase\n * @module ng\n * @kind function\n *\n * @description Converts the specified string to uppercase.\n * @param {string} string String to be converted to uppercase.\n * @returns {string} Uppercased string.\n */\nvar uppercase = function(string) {return isString(string) ? string.toUpperCase() : string;};\n\n\nvar manualLowercase = function(s) {\n  /* jshint bitwise: false */\n  return isString(s)\n      ? s.replace(/[A-Z]/g, function(ch) {return String.fromCharCode(ch.charCodeAt(0) | 32);})\n      : s;\n};\nvar manualUppercase = function(s) {\n  /* jshint bitwise: false */\n  return isString(s)\n      ? s.replace(/[a-z]/g, function(ch) {return String.fromCharCode(ch.charCodeAt(0) & ~32);})\n      : s;\n};\n\n\n// String#toLowerCase and String#toUpperCase don't produce correct results in browsers with Turkish\n// locale, for this reason we need to detect this case and redefine lowercase/uppercase methods\n// with correct but slower alternatives.\nif ('i' !== 'I'.toLowerCase()) {\n  lowercase = manualLowercase;\n  uppercase = manualUppercase;\n}\n\n\nvar\n    msie,             // holds major version number for IE, or NaN if UA is not IE.\n    jqLite,           // delay binding since jQuery could be loaded after us.\n    jQuery,           // delay binding\n    slice             = [].slice,\n    splice            = [].splice,\n    push              = [].push,\n    toString          = Object.prototype.toString,\n    ngMinErr          = minErr('ng'),\n\n    /** @name angular */\n    angular           = window.angular || (window.angular = {}),\n    angularModule,\n    uid               = 0;\n\n/**\n * documentMode is an IE-only property\n * http://msdn.microsoft.com/en-us/library/ie/cc196988(v=vs.85).aspx\n */\nmsie = document.documentMode;\n\n\n/**\n * @private\n * @param {*} obj\n * @return {boolean} Returns true if `obj` is an array or array-like object (NodeList, Arguments,\n *                   String ...)\n */\nfunction isArrayLike(obj) {\n  if (obj == null || isWindow(obj)) {\n    return false;\n  }\n\n  var length = obj.length;\n\n  if (obj.nodeType === NODE_TYPE_ELEMENT && length) {\n    return true;\n  }\n\n  return isString(obj) || isArray(obj) || length === 0 ||\n         typeof length === 'number' && length > 0 && (length - 1) in obj;\n}\n\n/**\n * @ngdoc function\n * @name angular.forEach\n * @module ng\n * @kind function\n *\n * @description\n * Invokes the `iterator` function once for each item in `obj` collection, which can be either an\n * object or an array. The `iterator` function is invoked with `iterator(value, key, obj)`, where `value`\n * is the value of an object property or an array element, `key` is the object property key or\n * array element index and obj is the `obj` itself. Specifying a `context` for the function is optional.\n *\n * It is worth noting that `.forEach` does not iterate over inherited properties because it filters\n * using the `hasOwnProperty` method.\n *\n * Unlike ES262's\n * [Array.prototype.forEach](http://www.ecma-international.org/ecma-262/5.1/#sec-15.4.4.18),\n * Providing 'undefined' or 'null' values for `obj` will not throw a TypeError, but rather just\n * return the value provided.\n *\n   ```js\n     var values = {name: 'misko', gender: 'male'};\n     var log = [];\n     angular.forEach(values, function(value, key) {\n       this.push(key + ': ' + value);\n     }, log);\n     expect(log).toEqual(['name: misko', 'gender: male']);\n   ```\n *\n * @param {Object|Array} obj Object to iterate over.\n * @param {Function} iterator Iterator function.\n * @param {Object=} context Object to become context (`this`) for the iterator function.\n * @returns {Object|Array} Reference to `obj`.\n */\n\nfunction forEach(obj, iterator, context) {\n  var key, length;\n  if (obj) {\n    if (isFunction(obj)) {\n      for (key in obj) {\n        // Need to check if hasOwnProperty exists,\n        // as on IE8 the result of querySelectorAll is an object without a hasOwnProperty function\n        if (key != 'prototype' && key != 'length' && key != 'name' && (!obj.hasOwnProperty || obj.hasOwnProperty(key))) {\n          iterator.call(context, obj[key], key, obj);\n        }\n      }\n    } else if (isArray(obj) || isArrayLike(obj)) {\n      var isPrimitive = typeof obj !== 'object';\n      for (key = 0, length = obj.length; key < length; key++) {\n        if (isPrimitive || key in obj) {\n          iterator.call(context, obj[key], key, obj);\n        }\n      }\n    } else if (obj.forEach && obj.forEach !== forEach) {\n        obj.forEach(iterator, context, obj);\n    } else {\n      for (key in obj) {\n        if (obj.hasOwnProperty(key)) {\n          iterator.call(context, obj[key], key, obj);\n        }\n      }\n    }\n  }\n  return obj;\n}\n\nfunction sortedKeys(obj) {\n  return Object.keys(obj).sort();\n}\n\nfunction forEachSorted(obj, iterator, context) {\n  var keys = sortedKeys(obj);\n  for (var i = 0; i < keys.length; i++) {\n    iterator.call(context, obj[keys[i]], keys[i]);\n  }\n  return keys;\n}\n\n\n/**\n * when using forEach the params are value, key, but it is often useful to have key, value.\n * @param {function(string, *)} iteratorFn\n * @returns {function(*, string)}\n */\nfunction reverseParams(iteratorFn) {\n  return function(value, key) { iteratorFn(key, value); };\n}\n\n/**\n * A consistent way of creating unique IDs in angular.\n *\n * Using simple numbers allows us to generate 28.6 million unique ids per second for 10 years before\n * we hit number precision issues in JavaScript.\n *\n * Math.pow(2,53) / 60 / 60 / 24 / 365 / 10 = 28.6M\n *\n * @returns {number} an unique alpha-numeric string\n */\nfunction nextUid() {\n  return ++uid;\n}\n\n\n/**\n * Set or clear the hashkey for an object.\n * @param obj object\n * @param h the hashkey (!truthy to delete the hashkey)\n */\nfunction setHashKey(obj, h) {\n  if (h) {\n    obj.$$hashKey = h;\n  } else {\n    delete obj.$$hashKey;\n  }\n}\n\n/**\n * @ngdoc function\n * @name angular.extend\n * @module ng\n * @kind function\n *\n * @description\n * Extends the destination object `dst` by copying own enumerable properties from the `src` object(s)\n * to `dst`. You can specify multiple `src` objects. If you want to preserve original objects, you can do so\n * by passing an empty object as the target: `var object = angular.extend({}, object1, object2)`.\n * Note: Keep in mind that `angular.extend` does not support recursive merge (deep copy).\n *\n * @param {Object} dst Destination object.\n * @param {...Object} src Source object(s).\n * @returns {Object} Reference to `dst`.\n */\nfunction extend(dst) {\n  var h = dst.$$hashKey;\n\n  for (var i = 1, ii = arguments.length; i < ii; i++) {\n    var obj = arguments[i];\n    if (obj) {\n      var keys = Object.keys(obj);\n      for (var j = 0, jj = keys.length; j < jj; j++) {\n        var key = keys[j];\n        dst[key] = obj[key];\n      }\n    }\n  }\n\n  setHashKey(dst, h);\n  return dst;\n}\n\nfunction int(str) {\n  return parseInt(str, 10);\n}\n\n\nfunction inherit(parent, extra) {\n  return extend(Object.create(parent), extra);\n}\n\n/**\n * @ngdoc function\n * @name angular.noop\n * @module ng\n * @kind function\n *\n * @description\n * A function that performs no operations. This function can be useful when writing code in the\n * functional style.\n   ```js\n     function foo(callback) {\n       var result = calculateResult();\n       (callback || angular.noop)(result);\n     }\n   ```\n */\nfunction noop() {}\nnoop.$inject = [];\n\n\n/**\n * @ngdoc function\n * @name angular.identity\n * @module ng\n * @kind function\n *\n * @description\n * A function that returns its first argument. This function is useful when writing code in the\n * functional style.\n *\n   ```js\n     function transformer(transformationFn, value) {\n       return (transformationFn || angular.identity)(value);\n     };\n   ```\n  * @param {*} value to be returned.\n  * @returns {*} the value passed in.\n */\nfunction identity($) {return $;}\nidentity.$inject = [];\n\n\nfunction valueFn(value) {return function() {return value;};}\n\n/**\n * @ngdoc function\n * @name angular.isUndefined\n * @module ng\n * @kind function\n *\n * @description\n * Determines if a reference is undefined.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is undefined.\n */\nfunction isUndefined(value) {return typeof value === 'undefined';}\n\n\n/**\n * @ngdoc function\n * @name angular.isDefined\n * @module ng\n * @kind function\n *\n * @description\n * Determines if a reference is defined.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is defined.\n */\nfunction isDefined(value) {return typeof value !== 'undefined';}\n\n\n/**\n * @ngdoc function\n * @name angular.isObject\n * @module ng\n * @kind function\n *\n * @description\n * Determines if a reference is an `Object`. Unlike `typeof` in JavaScript, `null`s are not\n * considered to be objects. Note that JavaScript arrays are objects.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is an `Object` but not `null`.\n */\nfunction isObject(value) {\n  // http://jsperf.com/isobject4\n  return value !== null && typeof value === 'object';\n}\n\n\n/**\n * @ngdoc function\n * @name angular.isString\n * @module ng\n * @kind function\n *\n * @description\n * Determines if a reference is a `String`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `String`.\n */\nfunction isString(value) {return typeof value === 'string';}\n\n\n/**\n * @ngdoc function\n * @name angular.isNumber\n * @module ng\n * @kind function\n *\n * @description\n * Determines if a reference is a `Number`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Number`.\n */\nfunction isNumber(value) {return typeof value === 'number';}\n\n\n/**\n * @ngdoc function\n * @name angular.isDate\n * @module ng\n * @kind function\n *\n * @description\n * Determines if a value is a date.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Date`.\n */\nfunction isDate(value) {\n  return toString.call(value) === '[object Date]';\n}\n\n\n/**\n * @ngdoc function\n * @name angular.isArray\n * @module ng\n * @kind function\n *\n * @description\n * Determines if a reference is an `Array`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is an `Array`.\n */\nvar isArray = Array.isArray;\n\n/**\n * @ngdoc function\n * @name angular.isFunction\n * @module ng\n * @kind function\n *\n * @description\n * Determines if a reference is a `Function`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Function`.\n */\nfunction isFunction(value) {return typeof value === 'function';}\n\n\n/**\n * Determines if a value is a regular expression object.\n *\n * @private\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `RegExp`.\n */\nfunction isRegExp(value) {\n  return toString.call(value) === '[object RegExp]';\n}\n\n\n/**\n * Checks if `obj` is a window object.\n *\n * @private\n * @param {*} obj Object to check\n * @returns {boolean} True if `obj` is a window obj.\n */\nfunction isWindow(obj) {\n  return obj && obj.window === obj;\n}\n\n\nfunction isScope(obj) {\n  return obj && obj.$evalAsync && obj.$watch;\n}\n\n\nfunction isFile(obj) {\n  return toString.call(obj) === '[object File]';\n}\n\n\nfunction isFormData(obj) {\n  return toString.call(obj) === '[object FormData]';\n}\n\n\nfunction isBlob(obj) {\n  return toString.call(obj) === '[object Blob]';\n}\n\n\nfunction isBoolean(value) {\n  return typeof value === 'boolean';\n}\n\n\nfunction isPromiseLike(obj) {\n  return obj && isFunction(obj.then);\n}\n\n\nvar trim = function(value) {\n  return isString(value) ? value.trim() : value;\n};\n\n// Copied from:\n// http://docs.closure-library.googlecode.com/git/local_closure_goog_string_string.js.source.html#line1021\n// Prereq: s is a string.\nvar escapeForRegexp = function(s) {\n  return s.replace(/([-()\\[\\]{}+?*.$\\^|,:#<!\\\\])/g, '\\\\$1').\n           replace(/\\x08/g, '\\\\x08');\n};\n\n\n/**\n * @ngdoc function\n * @name angular.isElement\n * @module ng\n * @kind function\n *\n * @description\n * Determines if a reference is a DOM element (or wrapped jQuery element).\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a DOM element (or wrapped jQuery element).\n */\nfunction isElement(node) {\n  return !!(node &&\n    (node.nodeName  // we are a direct element\n    || (node.prop && node.attr && node.find)));  // we have an on and find method part of jQuery API\n}\n\n/**\n * @param str 'key1,key2,...'\n * @returns {object} in the form of {key1:true, key2:true, ...}\n */\nfunction makeMap(str) {\n  var obj = {}, items = str.split(\",\"), i;\n  for (i = 0; i < items.length; i++)\n    obj[items[i]] = true;\n  return obj;\n}\n\n\nfunction nodeName_(element) {\n  return lowercase(element.nodeName || (element[0] && element[0].nodeName));\n}\n\nfunction includes(array, obj) {\n  return Array.prototype.indexOf.call(array, obj) != -1;\n}\n\nfunction arrayRemove(array, value) {\n  var index = array.indexOf(value);\n  if (index >= 0)\n    array.splice(index, 1);\n  return value;\n}\n\n/**\n * @ngdoc function\n * @name angular.copy\n * @module ng\n * @kind function\n *\n * @description\n * Creates a deep copy of `source`, which should be an object or an array.\n *\n * * If no destination is supplied, a copy of the object or array is created.\n * * If a destination is provided, all of its elements (for arrays) or properties (for objects)\n *   are deleted and then all elements/properties from the source are copied to it.\n * * If `source` is not an object or array (inc. `null` and `undefined`), `source` is returned.\n * * If `source` is identical to 'destination' an exception will be thrown.\n *\n * @param {*} source The source that will be used to make a copy.\n *                   Can be any type, including primitives, `null`, and `undefined`.\n * @param {(Object|Array)=} destination Destination into which the source is copied. If\n *     provided, must be of the same type as `source`.\n * @returns {*} The copy or updated `destination`, if `destination` was specified.\n *\n * @example\n <example module=\"copyExample\">\n <file name=\"index.html\">\n <div ng-controller=\"ExampleController\">\n <form novalidate class=\"simple-form\">\n Name: <input type=\"text\" ng-model=\"user.name\" /><br />\n E-mail: <input type=\"email\" ng-model=\"user.email\" /><br />\n Gender: <input type=\"radio\" ng-model=\"user.gender\" value=\"male\" />male\n <input type=\"radio\" ng-model=\"user.gender\" value=\"female\" />female<br />\n <button ng-click=\"reset()\">RESET</button>\n <button ng-click=\"update(user)\">SAVE</button>\n </form>\n <pre>form = {{user | json}}</pre>\n <pre>master = {{master | json}}</pre>\n </div>\n\n <script>\n  angular.module('copyExample', [])\n    .controller('ExampleController', ['$scope', function($scope) {\n      $scope.master= {};\n\n      $scope.update = function(user) {\n        // Example with 1 argument\n        $scope.master= angular.copy(user);\n      };\n\n      $scope.reset = function() {\n        // Example with 2 arguments\n        angular.copy($scope.master, $scope.user);\n      };\n\n      $scope.reset();\n    }]);\n </script>\n </file>\n </example>\n */\nfunction copy(source, destination, stackSource, stackDest) {\n  if (isWindow(source) || isScope(source)) {\n    throw ngMinErr('cpws',\n      \"Can't copy! Making copies of Window or Scope instances is not supported.\");\n  }\n\n  if (!destination) {\n    destination = source;\n    if (source) {\n      if (isArray(source)) {\n        destination = copy(source, [], stackSource, stackDest);\n      } else if (isDate(source)) {\n        destination = new Date(source.getTime());\n      } else if (isRegExp(source)) {\n        destination = new RegExp(source.source, source.toString().match(/[^\\/]*$/)[0]);\n        destination.lastIndex = source.lastIndex;\n      } else if (isObject(source)) {\n        var emptyObject = Object.create(Object.getPrototypeOf(source));\n        destination = copy(source, emptyObject, stackSource, stackDest);\n      }\n    }\n  } else {\n    if (source === destination) throw ngMinErr('cpi',\n      \"Can't copy! Source and destination are identical.\");\n\n    stackSource = stackSource || [];\n    stackDest = stackDest || [];\n\n    if (isObject(source)) {\n      var index = stackSource.indexOf(source);\n      if (index !== -1) return stackDest[index];\n\n      stackSource.push(source);\n      stackDest.push(destination);\n    }\n\n    var result;\n    if (isArray(source)) {\n      destination.length = 0;\n      for (var i = 0; i < source.length; i++) {\n        result = copy(source[i], null, stackSource, stackDest);\n        if (isObject(source[i])) {\n          stackSource.push(source[i]);\n          stackDest.push(result);\n        }\n        destination.push(result);\n      }\n    } else {\n      var h = destination.$$hashKey;\n      if (isArray(destination)) {\n        destination.length = 0;\n      } else {\n        forEach(destination, function(value, key) {\n          delete destination[key];\n        });\n      }\n      for (var key in source) {\n        if (source.hasOwnProperty(key)) {\n          result = copy(source[key], null, stackSource, stackDest);\n          if (isObject(source[key])) {\n            stackSource.push(source[key]);\n            stackDest.push(result);\n          }\n          destination[key] = result;\n        }\n      }\n      setHashKey(destination,h);\n    }\n\n  }\n  return destination;\n}\n\n/**\n * Creates a shallow copy of an object, an array or a primitive.\n *\n * Assumes that there are no proto properties for objects.\n */\nfunction shallowCopy(src, dst) {\n  if (isArray(src)) {\n    dst = dst || [];\n\n    for (var i = 0, ii = src.length; i < ii; i++) {\n      dst[i] = src[i];\n    }\n  } else if (isObject(src)) {\n    dst = dst || {};\n\n    for (var key in src) {\n      if (!(key.charAt(0) === '$' && key.charAt(1) === '$')) {\n        dst[key] = src[key];\n      }\n    }\n  }\n\n  return dst || src;\n}\n\n\n/**\n * @ngdoc function\n * @name angular.equals\n * @module ng\n * @kind function\n *\n * @description\n * Determines if two objects or two values are equivalent. Supports value types, regular\n * expressions, arrays and objects.\n *\n * Two objects or values are considered equivalent if at least one of the following is true:\n *\n * * Both objects or values pass `===` comparison.\n * * Both objects or values are of the same type and all of their properties are equal by\n *   comparing them with `angular.equals`.\n * * Both values are NaN. (In JavaScript, NaN == NaN => false. But we consider two NaN as equal)\n * * Both values represent the same regular expression (In JavaScript,\n *   /abc/ == /abc/ => false. But we consider two regular expressions as equal when their textual\n *   representation matches).\n *\n * During a property comparison, properties of `function` type and properties with names\n * that begin with `$` are ignored.\n *\n * Scope and DOMWindow objects are being compared only by identify (`===`).\n *\n * @param {*} o1 Object or value to compare.\n * @param {*} o2 Object or value to compare.\n * @returns {boolean} True if arguments are equal.\n */\nfunction equals(o1, o2) {\n  if (o1 === o2) return true;\n  if (o1 === null || o2 === null) return false;\n  if (o1 !== o1 && o2 !== o2) return true; // NaN === NaN\n  var t1 = typeof o1, t2 = typeof o2, length, key, keySet;\n  if (t1 == t2) {\n    if (t1 == 'object') {\n      if (isArray(o1)) {\n        if (!isArray(o2)) return false;\n        if ((length = o1.length) == o2.length) {\n          for (key = 0; key < length; key++) {\n            if (!equals(o1[key], o2[key])) return false;\n          }\n          return true;\n        }\n      } else if (isDate(o1)) {\n        if (!isDate(o2)) return false;\n        return equals(o1.getTime(), o2.getTime());\n      } else if (isRegExp(o1) && isRegExp(o2)) {\n        return o1.toString() == o2.toString();\n      } else {\n        if (isScope(o1) || isScope(o2) || isWindow(o1) || isWindow(o2) || isArray(o2)) return false;\n        keySet = {};\n        for (key in o1) {\n          if (key.charAt(0) === '$' || isFunction(o1[key])) continue;\n          if (!equals(o1[key], o2[key])) return false;\n          keySet[key] = true;\n        }\n        for (key in o2) {\n          if (!keySet.hasOwnProperty(key) &&\n              key.charAt(0) !== '$' &&\n              o2[key] !== undefined &&\n              !isFunction(o2[key])) return false;\n        }\n        return true;\n      }\n    }\n  }\n  return false;\n}\n\nvar csp = function() {\n  if (isDefined(csp.isActive_)) return csp.isActive_;\n\n  var active = !!(document.querySelector('[ng-csp]') ||\n                  document.querySelector('[data-ng-csp]'));\n\n  if (!active) {\n    try {\n      /* jshint -W031, -W054 */\n      new Function('');\n      /* jshint +W031, +W054 */\n    } catch (e) {\n      active = true;\n    }\n  }\n\n  return (csp.isActive_ = active);\n};\n\n\n\nfunction concat(array1, array2, index) {\n  return array1.concat(slice.call(array2, index));\n}\n\nfunction sliceArgs(args, startIndex) {\n  return slice.call(args, startIndex || 0);\n}\n\n\n/* jshint -W101 */\n/**\n * @ngdoc function\n * @name angular.bind\n * @module ng\n * @kind function\n *\n * @description\n * Returns a function which calls function `fn` bound to `self` (`self` becomes the `this` for\n * `fn`). You can supply optional `args` that are prebound to the function. This feature is also\n * known as [partial application](http://en.wikipedia.org/wiki/Partial_application), as\n * distinguished from [function currying](http://en.wikipedia.org/wiki/Currying#Contrast_with_partial_function_application).\n *\n * @param {Object} self Context which `fn` should be evaluated in.\n * @param {function()} fn Function to be bound.\n * @param {...*} args Optional arguments to be prebound to the `fn` function call.\n * @returns {function()} Function that wraps the `fn` with all the specified bindings.\n */\n/* jshint +W101 */\nfunction bind(self, fn) {\n  var curryArgs = arguments.length > 2 ? sliceArgs(arguments, 2) : [];\n  if (isFunction(fn) && !(fn instanceof RegExp)) {\n    return curryArgs.length\n      ? function() {\n          return arguments.length\n            ? fn.apply(self, concat(curryArgs, arguments, 0))\n            : fn.apply(self, curryArgs);\n        }\n      : function() {\n          return arguments.length\n            ? fn.apply(self, arguments)\n            : fn.call(self);\n        };\n  } else {\n    // in IE, native methods are not functions so they cannot be bound (note: they don't need to be)\n    return fn;\n  }\n}\n\n\nfunction toJsonReplacer(key, value) {\n  var val = value;\n\n  if (typeof key === 'string' && key.charAt(0) === '$' && key.charAt(1) === '$') {\n    val = undefined;\n  } else if (isWindow(value)) {\n    val = '$WINDOW';\n  } else if (value &&  document === value) {\n    val = '$DOCUMENT';\n  } else if (isScope(value)) {\n    val = '$SCOPE';\n  }\n\n  return val;\n}\n\n\n/**\n * @ngdoc function\n * @name angular.toJson\n * @module ng\n * @kind function\n *\n * @description\n * Serializes input into a JSON-formatted string. Properties with leading $$ characters will be\n * stripped since angular uses this notation internally.\n *\n * @param {Object|Array|Date|string|number} obj Input to be serialized into JSON.\n * @param {boolean|number=} pretty If set to true, the JSON output will contain newlines and whitespace.\n *    If set to an integer, the JSON output will contain that many spaces per indentation (the default is 2).\n * @returns {string|undefined} JSON-ified string representing `obj`.\n */\nfunction toJson(obj, pretty) {\n  if (typeof obj === 'undefined') return undefined;\n  if (!isNumber(pretty)) {\n    pretty = pretty ? 2 : null;\n  }\n  return JSON.stringify(obj, toJsonReplacer, pretty);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.fromJson\n * @module ng\n * @kind function\n *\n * @description\n * Deserializes a JSON string.\n *\n * @param {string} json JSON string to deserialize.\n * @returns {Object|Array|string|number} Deserialized JSON string.\n */\nfunction fromJson(json) {\n  return isString(json)\n      ? JSON.parse(json)\n      : json;\n}\n\n\n/**\n * @returns {string} Returns the string representation of the element.\n */\nfunction startingTag(element) {\n  element = jqLite(element).clone();\n  try {\n    // turns out IE does not let you set .html() on elements which\n    // are not allowed to have children. So we just ignore it.\n    element.empty();\n  } catch (e) {}\n  var elemHtml = jqLite('<div>').append(element).html();\n  try {\n    return element[0].nodeType === NODE_TYPE_TEXT ? lowercase(elemHtml) :\n        elemHtml.\n          match(/^(<[^>]+>)/)[1].\n          replace(/^<([\\w\\-]+)/, function(match, nodeName) { return '<' + lowercase(nodeName); });\n  } catch (e) {\n    return lowercase(elemHtml);\n  }\n\n}\n\n\n/////////////////////////////////////////////////\n\n/**\n * Tries to decode the URI component without throwing an exception.\n *\n * @private\n * @param str value potential URI component to check.\n * @returns {boolean} True if `value` can be decoded\n * with the decodeURIComponent function.\n */\nfunction tryDecodeURIComponent(value) {\n  try {\n    return decodeURIComponent(value);\n  } catch (e) {\n    // Ignore any invalid uri component\n  }\n}\n\n\n/**\n * Parses an escaped url query string into key-value pairs.\n * @returns {Object.<string,boolean|Array>}\n */\nfunction parseKeyValue(/**string*/keyValue) {\n  var obj = {}, key_value, key;\n  forEach((keyValue || \"\").split('&'), function(keyValue) {\n    if (keyValue) {\n      key_value = keyValue.replace(/\\+/g,'%20').split('=');\n      key = tryDecodeURIComponent(key_value[0]);\n      if (isDefined(key)) {\n        var val = isDefined(key_value[1]) ? tryDecodeURIComponent(key_value[1]) : true;\n        if (!hasOwnProperty.call(obj, key)) {\n          obj[key] = val;\n        } else if (isArray(obj[key])) {\n          obj[key].push(val);\n        } else {\n          obj[key] = [obj[key],val];\n        }\n      }\n    }\n  });\n  return obj;\n}\n\nfunction toKeyValue(obj) {\n  var parts = [];\n  forEach(obj, function(value, key) {\n    if (isArray(value)) {\n      forEach(value, function(arrayValue) {\n        parts.push(encodeUriQuery(key, true) +\n                   (arrayValue === true ? '' : '=' + encodeUriQuery(arrayValue, true)));\n      });\n    } else {\n    parts.push(encodeUriQuery(key, true) +\n               (value === true ? '' : '=' + encodeUriQuery(value, true)));\n    }\n  });\n  return parts.length ? parts.join('&') : '';\n}\n\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 */\nfunction 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 custom\n * method because encodeURIComponent is too aggressive and encodes stuff that doesn't have to be\n * 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 */\nfunction 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(/%3B/gi, ';').\n             replace(/%20/g, (pctEncodeSpaces ? '%20' : '+'));\n}\n\nvar ngAttrPrefixes = ['ng-', 'data-ng-', 'ng:', 'x-ng-'];\n\nfunction getNgAttribute(element, ngAttr) {\n  var attr, i, ii = ngAttrPrefixes.length;\n  element = jqLite(element);\n  for (i = 0; i < ii; ++i) {\n    attr = ngAttrPrefixes[i] + ngAttr;\n    if (isString(attr = element.attr(attr))) {\n      return attr;\n    }\n  }\n  return null;\n}\n\n/**\n * @ngdoc directive\n * @name ngApp\n * @module ng\n *\n * @element ANY\n * @param {angular.Module} ngApp an optional application\n *   {@link angular.module module} name to load.\n * @param {boolean=} ngStrictDi if this attribute is present on the app element, the injector will be\n *   created in \"strict-di\" mode. This means that the application will fail to invoke functions which\n *   do not use explicit function annotation (and are thus unsuitable for minification), as described\n *   in {@link guide/di the Dependency Injection guide}, and useful debugging info will assist in\n *   tracking down the root of these bugs.\n *\n * @description\n *\n * Use this directive to **auto-bootstrap** an AngularJS application. The `ngApp` directive\n * designates the **root element** of the application and is typically placed near the root element\n * of the page - e.g. on the `<body>` or `<html>` tags.\n *\n * Only one AngularJS application can be auto-bootstrapped per HTML document. The first `ngApp`\n * found in the document will be used to define the root element to auto-bootstrap as an\n * application. To run multiple applications in an HTML document you must manually bootstrap them using\n * {@link angular.bootstrap} instead. AngularJS applications cannot be nested within each other.\n *\n * You can specify an **AngularJS module** to be used as the root module for the application.  This\n * module will be loaded into the {@link auto.$injector} when the application is bootstrapped. It\n * should contain the application code needed or have dependencies on other modules that will\n * contain the code. See {@link angular.module} for more information.\n *\n * In the example below if the `ngApp` directive were not placed on the `html` element then the\n * document would not be compiled, the `AppController` would not be instantiated and the `{{ a+b }}`\n * would not be resolved to `3`.\n *\n * `ngApp` is the easiest, and most common way to bootstrap an application.\n *\n <example module=\"ngAppDemo\">\n   <file name=\"index.html\">\n   <div ng-controller=\"ngAppDemoController\">\n     I can add: {{a}} + {{b}} =  {{ a+b }}\n   </div>\n   </file>\n   <file name=\"script.js\">\n   angular.module('ngAppDemo', []).controller('ngAppDemoController', function($scope) {\n     $scope.a = 1;\n     $scope.b = 2;\n   });\n   </file>\n </example>\n *\n * Using `ngStrictDi`, you would see something like this:\n *\n <example ng-app-included=\"true\">\n   <file name=\"index.html\">\n   <div ng-app=\"ngAppStrictDemo\" ng-strict-di>\n       <div ng-controller=\"GoodController1\">\n           I can add: {{a}} + {{b}} =  {{ a+b }}\n\n           <p>This renders because the controller does not fail to\n              instantiate, by using explicit annotation style (see\n              script.js for details)\n           </p>\n       </div>\n\n       <div ng-controller=\"GoodController2\">\n           Name: <input ng-model=\"name\"><br />\n           Hello, {{name}}!\n\n           <p>This renders because the controller does not fail to\n              instantiate, by using explicit annotation style\n              (see script.js for details)\n           </p>\n       </div>\n\n       <div ng-controller=\"BadController\">\n           I can add: {{a}} + {{b}} =  {{ a+b }}\n\n           <p>The controller could not be instantiated, due to relying\n              on automatic function annotations (which are disabled in\n              strict mode). As such, the content of this section is not\n              interpolated, and there should be an error in your web console.\n           </p>\n       </div>\n   </div>\n   </file>\n   <file name=\"script.js\">\n   angular.module('ngAppStrictDemo', [])\n     // BadController will fail to instantiate, due to relying on automatic function annotation,\n     // rather than an explicit annotation\n     .controller('BadController', function($scope) {\n       $scope.a = 1;\n       $scope.b = 2;\n     })\n     // Unlike BadController, GoodController1 and GoodController2 will not fail to be instantiated,\n     // due to using explicit annotations using the array style and $inject property, respectively.\n     .controller('GoodController1', ['$scope', function($scope) {\n       $scope.a = 1;\n       $scope.b = 2;\n     }])\n     .controller('GoodController2', GoodController2);\n     function GoodController2($scope) {\n       $scope.name = \"World\";\n     }\n     GoodController2.$inject = ['$scope'];\n   </file>\n   <file name=\"style.css\">\n   div[ng-controller] {\n       margin-bottom: 1em;\n       -webkit-border-radius: 4px;\n       border-radius: 4px;\n       border: 1px solid;\n       padding: .5em;\n   }\n   div[ng-controller^=Good] {\n       border-color: #d6e9c6;\n       background-color: #dff0d8;\n       color: #3c763d;\n   }\n   div[ng-controller^=Bad] {\n       border-color: #ebccd1;\n       background-color: #f2dede;\n       color: #a94442;\n       margin-bottom: 0;\n   }\n   </file>\n </example>\n */\nfunction angularInit(element, bootstrap) {\n  var appElement,\n      module,\n      config = {};\n\n  // The element `element` has priority over any other element\n  forEach(ngAttrPrefixes, function(prefix) {\n    var name = prefix + 'app';\n\n    if (!appElement && element.hasAttribute && element.hasAttribute(name)) {\n      appElement = element;\n      module = element.getAttribute(name);\n    }\n  });\n  forEach(ngAttrPrefixes, function(prefix) {\n    var name = prefix + 'app';\n    var candidate;\n\n    if (!appElement && (candidate = element.querySelector('[' + name.replace(':', '\\\\:') + ']'))) {\n      appElement = candidate;\n      module = candidate.getAttribute(name);\n    }\n  });\n  if (appElement) {\n    config.strictDi = getNgAttribute(appElement, \"strict-di\") !== null;\n    bootstrap(appElement, module ? [module] : [], config);\n  }\n}\n\n/**\n * @ngdoc function\n * @name angular.bootstrap\n * @module ng\n * @description\n * Use this function to manually start up angular application.\n *\n * See: {@link guide/bootstrap Bootstrap}\n *\n * Note that Protractor based end-to-end tests cannot use this function to bootstrap manually.\n * They must use {@link ng.directive:ngApp ngApp}.\n *\n * Angular will detect if it has been loaded into the browser more than once and only allow the\n * first loaded script to be bootstrapped and will report a warning to the browser console for\n * each of the subsequent scripts. This prevents strange results in applications, where otherwise\n * multiple instances of Angular try to work on the DOM.\n *\n * ```html\n * <!doctype html>\n * <html>\n * <body>\n * <div ng-controller=\"WelcomeController\">\n *   {{greeting}}\n * </div>\n *\n * <script src=\"angular.js\"></script>\n * <script>\n *   var app = angular.module('demo', [])\n *   .controller('WelcomeController', function($scope) {\n *       $scope.greeting = 'Welcome!';\n *   });\n *   angular.bootstrap(document, ['demo']);\n * </script>\n * </body>\n * </html>\n * ```\n *\n * @param {DOMElement} element DOM element which is the root of angular application.\n * @param {Array<String|Function|Array>=} modules an array of modules to load into the application.\n *     Each item in the array should be the name of a predefined module or a (DI annotated)\n *     function that will be invoked by the injector as a `config` block.\n *     See: {@link angular.module modules}\n * @param {Object=} config an object for defining configuration options for the application. The\n *     following keys are supported:\n *\n * * `strictDi` - disable automatic function annotation for the application. This is meant to\n *   assist in finding bugs which break minified code. Defaults to `false`.\n *\n * @returns {auto.$injector} Returns the newly created injector for this app.\n */\nfunction bootstrap(element, modules, config) {\n  if (!isObject(config)) config = {};\n  var defaultConfig = {\n    strictDi: false\n  };\n  config = extend(defaultConfig, config);\n  var doBootstrap = function() {\n    element = jqLite(element);\n\n    if (element.injector()) {\n      var tag = (element[0] === document) ? 'document' : startingTag(element);\n      //Encode angle brackets to prevent input from being sanitized to empty string #8683\n      throw ngMinErr(\n          'btstrpd',\n          \"App Already Bootstrapped with this Element '{0}'\",\n          tag.replace(/</,'&lt;').replace(/>/,'&gt;'));\n    }\n\n    modules = modules || [];\n    modules.unshift(['$provide', function($provide) {\n      $provide.value('$rootElement', element);\n    }]);\n\n    if (config.debugInfoEnabled) {\n      // Pushing so that this overrides `debugInfoEnabled` setting defined in user's `modules`.\n      modules.push(['$compileProvider', function($compileProvider) {\n        $compileProvider.debugInfoEnabled(true);\n      }]);\n    }\n\n    modules.unshift('ng');\n    var injector = createInjector(modules, config.strictDi);\n    injector.invoke(['$rootScope', '$rootElement', '$compile', '$injector',\n       function bootstrapApply(scope, element, compile, injector) {\n        scope.$apply(function() {\n          element.data('$injector', injector);\n          compile(element)(scope);\n        });\n      }]\n    );\n    return injector;\n  };\n\n  var NG_ENABLE_DEBUG_INFO = /^NG_ENABLE_DEBUG_INFO!/;\n  var NG_DEFER_BOOTSTRAP = /^NG_DEFER_BOOTSTRAP!/;\n\n  if (window && NG_ENABLE_DEBUG_INFO.test(window.name)) {\n    config.debugInfoEnabled = true;\n    window.name = window.name.replace(NG_ENABLE_DEBUG_INFO, '');\n  }\n\n  if (window && !NG_DEFER_BOOTSTRAP.test(window.name)) {\n    return doBootstrap();\n  }\n\n  window.name = window.name.replace(NG_DEFER_BOOTSTRAP, '');\n  angular.resumeBootstrap = function(extraModules) {\n    forEach(extraModules, function(module) {\n      modules.push(module);\n    });\n    return doBootstrap();\n  };\n\n  if (isFunction(angular.resumeDeferredBootstrap)) {\n    angular.resumeDeferredBootstrap();\n  }\n}\n\n/**\n * @ngdoc function\n * @name angular.reloadWithDebugInfo\n * @module ng\n * @description\n * Use this function to reload the current application with debug information turned on.\n * This takes precedence over a call to `$compileProvider.debugInfoEnabled(false)`.\n *\n * See {@link ng.$compileProvider#debugInfoEnabled} for more.\n */\nfunction reloadWithDebugInfo() {\n  window.name = 'NG_ENABLE_DEBUG_INFO!' + window.name;\n  window.location.reload();\n}\n\n/**\n * @name angular.getTestability\n * @module ng\n * @description\n * Get the testability service for the instance of Angular on the given\n * element.\n * @param {DOMElement} element DOM element which is the root of angular application.\n */\nfunction getTestability(rootElement) {\n  var injector = angular.element(rootElement).injector();\n  if (!injector) {\n    throw ngMinErr('test',\n      'no injector found for element argument to getTestability');\n  }\n  return injector.get('$$testability');\n}\n\nvar SNAKE_CASE_REGEXP = /[A-Z]/g;\nfunction snake_case(name, separator) {\n  separator = separator || '_';\n  return name.replace(SNAKE_CASE_REGEXP, function(letter, pos) {\n    return (pos ? separator : '') + letter.toLowerCase();\n  });\n}\n\nvar bindJQueryFired = false;\nvar skipDestroyOnNextJQueryCleanData;\nfunction bindJQuery() {\n  var originalCleanData;\n\n  if (bindJQueryFired) {\n    return;\n  }\n\n  // bind to jQuery if present;\n  jQuery = window.jQuery;\n  // Use jQuery if it exists with proper functionality, otherwise default to us.\n  // Angular 1.2+ requires jQuery 1.7+ for on()/off() support.\n  // Angular 1.3+ technically requires at least jQuery 2.1+ but it may work with older\n  // versions. It will not work for sure with jQuery <1.7, though.\n  if (jQuery && jQuery.fn.on) {\n    jqLite = jQuery;\n    extend(jQuery.fn, {\n      scope: JQLitePrototype.scope,\n      isolateScope: JQLitePrototype.isolateScope,\n      controller: JQLitePrototype.controller,\n      injector: JQLitePrototype.injector,\n      inheritedData: JQLitePrototype.inheritedData\n    });\n\n    // All nodes removed from the DOM via various jQuery APIs like .remove()\n    // are passed through jQuery.cleanData. Monkey-patch this method to fire\n    // the $destroy event on all removed nodes.\n    originalCleanData = jQuery.cleanData;\n    jQuery.cleanData = function(elems) {\n      var events;\n      if (!skipDestroyOnNextJQueryCleanData) {\n        for (var i = 0, elem; (elem = elems[i]) != null; i++) {\n          events = jQuery._data(elem, \"events\");\n          if (events && events.$destroy) {\n            jQuery(elem).triggerHandler('$destroy');\n          }\n        }\n      } else {\n        skipDestroyOnNextJQueryCleanData = false;\n      }\n      originalCleanData(elems);\n    };\n  } else {\n    jqLite = JQLite;\n  }\n\n  angular.element = jqLite;\n\n  // Prevent double-proxying.\n  bindJQueryFired = true;\n}\n\n/**\n * throw error if the argument is falsy.\n */\nfunction assertArg(arg, name, reason) {\n  if (!arg) {\n    throw ngMinErr('areq', \"Argument '{0}' is {1}\", (name || '?'), (reason || \"required\"));\n  }\n  return arg;\n}\n\nfunction assertArgFn(arg, name, acceptArrayAnnotation) {\n  if (acceptArrayAnnotation && isArray(arg)) {\n      arg = arg[arg.length - 1];\n  }\n\n  assertArg(isFunction(arg), name, 'not a function, got ' +\n      (arg && typeof arg === 'object' ? arg.constructor.name || 'Object' : typeof arg));\n  return arg;\n}\n\n/**\n * throw error if the name given is hasOwnProperty\n * @param  {String} name    the name to test\n * @param  {String} context the context in which the name is used, such as module or directive\n */\nfunction assertNotHasOwnProperty(name, context) {\n  if (name === 'hasOwnProperty') {\n    throw ngMinErr('badname', \"hasOwnProperty is not a valid {0} name\", context);\n  }\n}\n\n/**\n * Return the value accessible from the object by path. Any undefined traversals are ignored\n * @param {Object} obj starting object\n * @param {String} path path to traverse\n * @param {boolean} [bindFnToScope=true]\n * @returns {Object} value as accessible by path\n */\n//TODO(misko): this function needs to be removed\nfunction getter(obj, path, bindFnToScope) {\n  if (!path) return obj;\n  var keys = path.split('.');\n  var key;\n  var lastInstance = obj;\n  var len = keys.length;\n\n  for (var i = 0; i < len; i++) {\n    key = keys[i];\n    if (obj) {\n      obj = (lastInstance = obj)[key];\n    }\n  }\n  if (!bindFnToScope && isFunction(obj)) {\n    return bind(lastInstance, obj);\n  }\n  return obj;\n}\n\n/**\n * Return the DOM siblings between the first and last node in the given array.\n * @param {Array} array like object\n * @returns {jqLite} jqLite collection containing the nodes\n */\nfunction getBlockNodes(nodes) {\n  // TODO(perf): just check if all items in `nodes` are siblings and if they are return the original\n  //             collection, otherwise update the original collection.\n  var node = nodes[0];\n  var endNode = nodes[nodes.length - 1];\n  var blockNodes = [node];\n\n  do {\n    node = node.nextSibling;\n    if (!node) break;\n    blockNodes.push(node);\n  } while (node !== endNode);\n\n  return jqLite(blockNodes);\n}\n\n\n/**\n * Creates a new object without a prototype. This object is useful for lookup without having to\n * guard against prototypically inherited properties via hasOwnProperty.\n *\n * Related micro-benchmarks:\n * - http://jsperf.com/object-create2\n * - http://jsperf.com/proto-map-lookup/2\n * - http://jsperf.com/for-in-vs-object-keys2\n *\n * @returns {Object}\n */\nfunction createMap() {\n  return Object.create(null);\n}\n\nvar NODE_TYPE_ELEMENT = 1;\nvar NODE_TYPE_TEXT = 3;\nvar NODE_TYPE_COMMENT = 8;\nvar NODE_TYPE_DOCUMENT = 9;\nvar NODE_TYPE_DOCUMENT_FRAGMENT = 11;\n\n/**\n * @ngdoc type\n * @name angular.Module\n * @module ng\n * @description\n *\n * Interface for configuring angular {@link angular.module modules}.\n */\n\nfunction setupModuleLoader(window) {\n\n  var $injectorMinErr = minErr('$injector');\n  var ngMinErr = minErr('ng');\n\n  function ensure(obj, name, factory) {\n    return obj[name] || (obj[name] = factory());\n  }\n\n  var angular = ensure(window, 'angular', Object);\n\n  // We need to expose `angular.$$minErr` to modules such as `ngResource` that reference it during bootstrap\n  angular.$$minErr = angular.$$minErr || minErr;\n\n  return ensure(angular, 'module', function() {\n    /** @type {Object.<string, angular.Module>} */\n    var modules = {};\n\n    /**\n     * @ngdoc function\n     * @name angular.module\n     * @module ng\n     * @description\n     *\n     * The `angular.module` is a global place for creating, registering and retrieving Angular\n     * modules.\n     * All modules (angular core or 3rd party) that should be available to an application must be\n     * registered using this mechanism.\n     *\n     * When passed two or more arguments, a new module is created.  If passed only one argument, an\n     * existing module (the name passed as the first argument to `module`) is retrieved.\n     *\n     *\n     * # Module\n     *\n     * A module is a collection of services, directives, controllers, filters, and configuration information.\n     * `angular.module` is used to configure the {@link auto.$injector $injector}.\n     *\n     * ```js\n     * // Create a new module\n     * var myModule = angular.module('myModule', []);\n     *\n     * // register a new service\n     * myModule.value('appName', 'MyCoolApp');\n     *\n     * // configure existing services inside initialization blocks.\n     * myModule.config(['$locationProvider', function($locationProvider) {\n     *   // Configure existing providers\n     *   $locationProvider.hashPrefix('!');\n     * }]);\n     * ```\n     *\n     * Then you can create an injector and load your modules like this:\n     *\n     * ```js\n     * var injector = angular.injector(['ng', 'myModule'])\n     * ```\n     *\n     * However it's more likely that you'll just use\n     * {@link ng.directive:ngApp ngApp} or\n     * {@link angular.bootstrap} to simplify this process for you.\n     *\n     * @param {!string} name The name of the module to create or retrieve.\n     * @param {!Array.<string>=} requires If specified then new module is being created. If\n     *        unspecified then the module is being retrieved for further configuration.\n     * @param {Function=} configFn Optional configuration function for the module. Same as\n     *        {@link angular.Module#config Module#config()}.\n     * @returns {module} new module with the {@link angular.Module} api.\n     */\n    return function module(name, requires, configFn) {\n      var assertNotHasOwnProperty = function(name, context) {\n        if (name === 'hasOwnProperty') {\n          throw ngMinErr('badname', 'hasOwnProperty is not a valid {0} name', context);\n        }\n      };\n\n      assertNotHasOwnProperty(name, 'module');\n      if (requires && modules.hasOwnProperty(name)) {\n        modules[name] = null;\n      }\n      return ensure(modules, name, function() {\n        if (!requires) {\n          throw $injectorMinErr('nomod', \"Module '{0}' is not available! You either misspelled \" +\n             \"the module name or forgot to load it. If registering a module ensure that you \" +\n             \"specify the dependencies as the second argument.\", name);\n        }\n\n        /** @type {!Array.<Array.<*>>} */\n        var invokeQueue = [];\n\n        /** @type {!Array.<Function>} */\n        var configBlocks = [];\n\n        /** @type {!Array.<Function>} */\n        var runBlocks = [];\n\n        var config = invokeLater('$injector', 'invoke', 'push', configBlocks);\n\n        /** @type {angular.Module} */\n        var moduleInstance = {\n          // Private state\n          _invokeQueue: invokeQueue,\n          _configBlocks: configBlocks,\n          _runBlocks: runBlocks,\n\n          /**\n           * @ngdoc property\n           * @name angular.Module#requires\n           * @module ng\n           *\n           * @description\n           * Holds the list of modules which the injector will load before the current module is\n           * loaded.\n           */\n          requires: requires,\n\n          /**\n           * @ngdoc property\n           * @name angular.Module#name\n           * @module ng\n           *\n           * @description\n           * Name of the module.\n           */\n          name: name,\n\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#provider\n           * @module ng\n           * @param {string} name service name\n           * @param {Function} providerType Construction function for creating new instance of the\n           *                                service.\n           * @description\n           * See {@link auto.$provide#provider $provide.provider()}.\n           */\n          provider: invokeLater('$provide', 'provider'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#factory\n           * @module ng\n           * @param {string} name service name\n           * @param {Function} providerFunction Function for creating new instance of the service.\n           * @description\n           * See {@link auto.$provide#factory $provide.factory()}.\n           */\n          factory: invokeLater('$provide', 'factory'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#service\n           * @module ng\n           * @param {string} name service name\n           * @param {Function} constructor A constructor function that will be instantiated.\n           * @description\n           * See {@link auto.$provide#service $provide.service()}.\n           */\n          service: invokeLater('$provide', 'service'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#value\n           * @module ng\n           * @param {string} name service name\n           * @param {*} object Service instance object.\n           * @description\n           * See {@link auto.$provide#value $provide.value()}.\n           */\n          value: invokeLater('$provide', 'value'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#constant\n           * @module ng\n           * @param {string} name constant name\n           * @param {*} object Constant value.\n           * @description\n           * Because the constant are fixed, they get applied before other provide methods.\n           * See {@link auto.$provide#constant $provide.constant()}.\n           */\n          constant: invokeLater('$provide', 'constant', 'unshift'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#animation\n           * @module ng\n           * @param {string} name animation name\n           * @param {Function} animationFactory Factory function for creating new instance of an\n           *                                    animation.\n           * @description\n           *\n           * **NOTE**: animations take effect only if the **ngAnimate** module is loaded.\n           *\n           *\n           * Defines an animation hook that can be later used with\n           * {@link ngAnimate.$animate $animate} service and directives that use this service.\n           *\n           * ```js\n           * module.animation('.animation-name', function($inject1, $inject2) {\n           *   return {\n           *     eventName : function(element, done) {\n           *       //code to run the animation\n           *       //once complete, then run done()\n           *       return function cancellationFunction(element) {\n           *         //code to cancel the animation\n           *       }\n           *     }\n           *   }\n           * })\n           * ```\n           *\n           * See {@link ng.$animateProvider#register $animateProvider.register()} and\n           * {@link ngAnimate ngAnimate module} for more information.\n           */\n          animation: invokeLater('$animateProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#filter\n           * @module ng\n           * @param {string} name Filter name.\n           * @param {Function} filterFactory Factory function for creating new instance of filter.\n           * @description\n           * See {@link ng.$filterProvider#register $filterProvider.register()}.\n           */\n          filter: invokeLater('$filterProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#controller\n           * @module ng\n           * @param {string|Object} name Controller name, or an object map of controllers where the\n           *    keys are the names and the values are the constructors.\n           * @param {Function} constructor Controller constructor function.\n           * @description\n           * See {@link ng.$controllerProvider#register $controllerProvider.register()}.\n           */\n          controller: invokeLater('$controllerProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#directive\n           * @module ng\n           * @param {string|Object} name Directive name, or an object map of directives where the\n           *    keys are the names and the values are the factories.\n           * @param {Function} directiveFactory Factory function for creating new instance of\n           * directives.\n           * @description\n           * See {@link ng.$compileProvider#directive $compileProvider.directive()}.\n           */\n          directive: invokeLater('$compileProvider', 'directive'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#config\n           * @module ng\n           * @param {Function} configFn Execute this function on module load. Useful for service\n           *    configuration.\n           * @description\n           * Use this method to register work which needs to be performed on module loading.\n           * For more about how to configure services, see\n           * {@link providers#provider-recipe Provider Recipe}.\n           */\n          config: config,\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#run\n           * @module ng\n           * @param {Function} initializationFn Execute this function after injector creation.\n           *    Useful for application initialization.\n           * @description\n           * Use this method to register work which should be performed when the injector is done\n           * loading all modules.\n           */\n          run: function(block) {\n            runBlocks.push(block);\n            return this;\n          }\n        };\n\n        if (configFn) {\n          config(configFn);\n        }\n\n        return moduleInstance;\n\n        /**\n         * @param {string} provider\n         * @param {string} method\n         * @param {String=} insertMethod\n         * @returns {angular.Module}\n         */\n        function invokeLater(provider, method, insertMethod, queue) {\n          if (!queue) queue = invokeQueue;\n          return function() {\n            queue[insertMethod || 'push']([provider, method, arguments]);\n            return moduleInstance;\n          };\n        }\n      });\n    };\n  });\n\n}\n\n/* global: toDebugString: true */\n\nfunction serializeObject(obj) {\n  var seen = [];\n\n  return JSON.stringify(obj, function(key, val) {\n    val = toJsonReplacer(key, val);\n    if (isObject(val)) {\n\n      if (seen.indexOf(val) >= 0) return '<<already seen>>';\n\n      seen.push(val);\n    }\n    return val;\n  });\n}\n\nfunction toDebugString(obj) {\n  if (typeof obj === 'function') {\n    return obj.toString().replace(/ \\{[\\s\\S]*$/, '');\n  } else if (typeof obj === 'undefined') {\n    return 'undefined';\n  } else if (typeof obj !== 'string') {\n    return serializeObject(obj);\n  }\n  return obj;\n}\n\n/* global angularModule: true,\n  version: true,\n\n  $LocaleProvider,\n  $CompileProvider,\n\n  htmlAnchorDirective,\n  inputDirective,\n  inputDirective,\n  formDirective,\n  scriptDirective,\n  selectDirective,\n  styleDirective,\n  optionDirective,\n  ngBindDirective,\n  ngBindHtmlDirective,\n  ngBindTemplateDirective,\n  ngClassDirective,\n  ngClassEvenDirective,\n  ngClassOddDirective,\n  ngCspDirective,\n  ngCloakDirective,\n  ngControllerDirective,\n  ngFormDirective,\n  ngHideDirective,\n  ngIfDirective,\n  ngIncludeDirective,\n  ngIncludeFillContentDirective,\n  ngInitDirective,\n  ngNonBindableDirective,\n  ngPluralizeDirective,\n  ngRepeatDirective,\n  ngShowDirective,\n  ngStyleDirective,\n  ngSwitchDirective,\n  ngSwitchWhenDirective,\n  ngSwitchDefaultDirective,\n  ngOptionsDirective,\n  ngTranscludeDirective,\n  ngModelDirective,\n  ngListDirective,\n  ngChangeDirective,\n  patternDirective,\n  patternDirective,\n  requiredDirective,\n  requiredDirective,\n  minlengthDirective,\n  minlengthDirective,\n  maxlengthDirective,\n  maxlengthDirective,\n  ngValueDirective,\n  ngModelOptionsDirective,\n  ngAttributeAliasDirectives,\n  ngEventDirectives,\n\n  $AnchorScrollProvider,\n  $AnimateProvider,\n  $BrowserProvider,\n  $CacheFactoryProvider,\n  $ControllerProvider,\n  $DocumentProvider,\n  $ExceptionHandlerProvider,\n  $FilterProvider,\n  $InterpolateProvider,\n  $IntervalProvider,\n  $HttpProvider,\n  $HttpBackendProvider,\n  $LocationProvider,\n  $LogProvider,\n  $ParseProvider,\n  $RootScopeProvider,\n  $QProvider,\n  $$QProvider,\n  $$SanitizeUriProvider,\n  $SceProvider,\n  $SceDelegateProvider,\n  $SnifferProvider,\n  $TemplateCacheProvider,\n  $TemplateRequestProvider,\n  $$TestabilityProvider,\n  $TimeoutProvider,\n  $$RAFProvider,\n  $$AsyncCallbackProvider,\n  $WindowProvider,\n  $$jqLiteProvider\n*/\n\n\n/**\n * @ngdoc object\n * @name angular.version\n * @module ng\n * @description\n * An object that contains information about the current AngularJS version. This object has the\n * following properties:\n *\n * - `full` – `{string}` – Full version string, such as \"0.9.18\".\n * - `major` – `{number}` – Major version number, such as \"0\".\n * - `minor` – `{number}` – Minor version number, such as \"9\".\n * - `dot` – `{number}` – Dot version number, such as \"18\".\n * - `codeName` – `{string}` – Code name of the release, such as \"jiggling-armfat\".\n */\nvar version = {\n  full: '1.3.13',    // all of these placeholder strings will be replaced by grunt's\n  major: 1,    // package task\n  minor: 3,\n  dot: 13,\n  codeName: 'meticulous-riffleshuffle'\n};\n\n\nfunction publishExternalAPI(angular) {\n  extend(angular, {\n    'bootstrap': bootstrap,\n    'copy': copy,\n    'extend': extend,\n    'equals': equals,\n    'element': jqLite,\n    'forEach': forEach,\n    'injector': createInjector,\n    'noop': noop,\n    'bind': bind,\n    'toJson': toJson,\n    'fromJson': fromJson,\n    'identity': identity,\n    'isUndefined': isUndefined,\n    'isDefined': isDefined,\n    'isString': isString,\n    'isFunction': isFunction,\n    'isObject': isObject,\n    'isNumber': isNumber,\n    'isElement': isElement,\n    'isArray': isArray,\n    'version': version,\n    'isDate': isDate,\n    'lowercase': lowercase,\n    'uppercase': uppercase,\n    'callbacks': {counter: 0},\n    'getTestability': getTestability,\n    '$$minErr': minErr,\n    '$$csp': csp,\n    'reloadWithDebugInfo': reloadWithDebugInfo\n  });\n\n  angularModule = setupModuleLoader(window);\n  try {\n    angularModule('ngLocale');\n  } catch (e) {\n    angularModule('ngLocale', []).provider('$locale', $LocaleProvider);\n  }\n\n  angularModule('ng', ['ngLocale'], ['$provide',\n    function ngModule($provide) {\n      // $$sanitizeUriProvider needs to be before $compileProvider as it is used by it.\n      $provide.provider({\n        $$sanitizeUri: $$SanitizeUriProvider\n      });\n      $provide.provider('$compile', $CompileProvider).\n        directive({\n            a: htmlAnchorDirective,\n            input: inputDirective,\n            textarea: inputDirective,\n            form: formDirective,\n            script: scriptDirective,\n            select: selectDirective,\n            style: styleDirective,\n            option: optionDirective,\n            ngBind: ngBindDirective,\n            ngBindHtml: ngBindHtmlDirective,\n            ngBindTemplate: ngBindTemplateDirective,\n            ngClass: ngClassDirective,\n            ngClassEven: ngClassEvenDirective,\n            ngClassOdd: ngClassOddDirective,\n            ngCloak: ngCloakDirective,\n            ngController: ngControllerDirective,\n            ngForm: ngFormDirective,\n            ngHide: ngHideDirective,\n            ngIf: ngIfDirective,\n            ngInclude: ngIncludeDirective,\n            ngInit: ngInitDirective,\n            ngNonBindable: ngNonBindableDirective,\n            ngPluralize: ngPluralizeDirective,\n            ngRepeat: ngRepeatDirective,\n            ngShow: ngShowDirective,\n            ngStyle: ngStyleDirective,\n            ngSwitch: ngSwitchDirective,\n            ngSwitchWhen: ngSwitchWhenDirective,\n            ngSwitchDefault: ngSwitchDefaultDirective,\n            ngOptions: ngOptionsDirective,\n            ngTransclude: ngTranscludeDirective,\n            ngModel: ngModelDirective,\n            ngList: ngListDirective,\n            ngChange: ngChangeDirective,\n            pattern: patternDirective,\n            ngPattern: patternDirective,\n            required: requiredDirective,\n            ngRequired: requiredDirective,\n            minlength: minlengthDirective,\n            ngMinlength: minlengthDirective,\n            maxlength: maxlengthDirective,\n            ngMaxlength: maxlengthDirective,\n            ngValue: ngValueDirective,\n            ngModelOptions: ngModelOptionsDirective\n        }).\n        directive({\n          ngInclude: ngIncludeFillContentDirective\n        }).\n        directive(ngAttributeAliasDirectives).\n        directive(ngEventDirectives);\n      $provide.provider({\n        $anchorScroll: $AnchorScrollProvider,\n        $animate: $AnimateProvider,\n        $browser: $BrowserProvider,\n        $cacheFactory: $CacheFactoryProvider,\n        $controller: $ControllerProvider,\n        $document: $DocumentProvider,\n        $exceptionHandler: $ExceptionHandlerProvider,\n        $filter: $FilterProvider,\n        $interpolate: $InterpolateProvider,\n        $interval: $IntervalProvider,\n        $http: $HttpProvider,\n        $httpBackend: $HttpBackendProvider,\n        $location: $LocationProvider,\n        $log: $LogProvider,\n        $parse: $ParseProvider,\n        $rootScope: $RootScopeProvider,\n        $q: $QProvider,\n        $$q: $$QProvider,\n        $sce: $SceProvider,\n        $sceDelegate: $SceDelegateProvider,\n        $sniffer: $SnifferProvider,\n        $templateCache: $TemplateCacheProvider,\n        $templateRequest: $TemplateRequestProvider,\n        $$testability: $$TestabilityProvider,\n        $timeout: $TimeoutProvider,\n        $window: $WindowProvider,\n        $$rAF: $$RAFProvider,\n        $$asyncCallback: $$AsyncCallbackProvider,\n        $$jqLite: $$jqLiteProvider\n      });\n    }\n  ]);\n}\n\n/* global JQLitePrototype: true,\n  addEventListenerFn: true,\n  removeEventListenerFn: true,\n  BOOLEAN_ATTR: true,\n  ALIASED_ATTR: true,\n*/\n\n//////////////////////////////////\n//JQLite\n//////////////////////////////////\n\n/**\n * @ngdoc function\n * @name angular.element\n * @module ng\n * @kind function\n *\n * @description\n * Wraps a raw DOM element or HTML string as a [jQuery](http://jquery.com) element.\n *\n * If jQuery is available, `angular.element` is an alias for the\n * [jQuery](http://api.jquery.com/jQuery/) function. If jQuery is not available, `angular.element`\n * delegates to Angular's built-in subset of jQuery, called \"jQuery lite\" or \"jqLite.\"\n *\n * <div class=\"alert alert-success\">jqLite is a tiny, API-compatible subset of jQuery that allows\n * Angular to manipulate the DOM in a cross-browser compatible way. **jqLite** implements only the most\n * commonly needed functionality with the goal of having a very small footprint.</div>\n *\n * To use jQuery, simply load it before `DOMContentLoaded` event fired.\n *\n * <div class=\"alert\">**Note:** all element references in Angular are always wrapped with jQuery or\n * jqLite; they are never raw DOM references.</div>\n *\n * ## Angular's jqLite\n * jqLite provides only the following jQuery methods:\n *\n * - [`addClass()`](http://api.jquery.com/addClass/)\n * - [`after()`](http://api.jquery.com/after/)\n * - [`append()`](http://api.jquery.com/append/)\n * - [`attr()`](http://api.jquery.com/attr/) - Does not support functions as parameters\n * - [`bind()`](http://api.jquery.com/bind/) - Does not support namespaces, selectors or eventData\n * - [`children()`](http://api.jquery.com/children/) - Does not support selectors\n * - [`clone()`](http://api.jquery.com/clone/)\n * - [`contents()`](http://api.jquery.com/contents/)\n * - [`css()`](http://api.jquery.com/css/) - Only retrieves inline-styles, does not call `getComputedStyle()`\n * - [`data()`](http://api.jquery.com/data/)\n * - [`detach()`](http://api.jquery.com/detach/)\n * - [`empty()`](http://api.jquery.com/empty/)\n * - [`eq()`](http://api.jquery.com/eq/)\n * - [`find()`](http://api.jquery.com/find/) - Limited to lookups by tag name\n * - [`hasClass()`](http://api.jquery.com/hasClass/)\n * - [`html()`](http://api.jquery.com/html/)\n * - [`next()`](http://api.jquery.com/next/) - Does not support selectors\n * - [`on()`](http://api.jquery.com/on/) - Does not support namespaces, selectors or eventData\n * - [`off()`](http://api.jquery.com/off/) - Does not support namespaces or selectors\n * - [`one()`](http://api.jquery.com/one/) - Does not support namespaces or selectors\n * - [`parent()`](http://api.jquery.com/parent/) - Does not support selectors\n * - [`prepend()`](http://api.jquery.com/prepend/)\n * - [`prop()`](http://api.jquery.com/prop/)\n * - [`ready()`](http://api.jquery.com/ready/)\n * - [`remove()`](http://api.jquery.com/remove/)\n * - [`removeAttr()`](http://api.jquery.com/removeAttr/)\n * - [`removeClass()`](http://api.jquery.com/removeClass/)\n * - [`removeData()`](http://api.jquery.com/removeData/)\n * - [`replaceWith()`](http://api.jquery.com/replaceWith/)\n * - [`text()`](http://api.jquery.com/text/)\n * - [`toggleClass()`](http://api.jquery.com/toggleClass/)\n * - [`triggerHandler()`](http://api.jquery.com/triggerHandler/) - Passes a dummy event object to handlers.\n * - [`unbind()`](http://api.jquery.com/unbind/) - Does not support namespaces\n * - [`val()`](http://api.jquery.com/val/)\n * - [`wrap()`](http://api.jquery.com/wrap/)\n *\n * ## jQuery/jqLite Extras\n * Angular also provides the following additional methods and events to both jQuery and jqLite:\n *\n * ### Events\n * - `$destroy` - AngularJS intercepts all jqLite/jQuery's DOM destruction apis and fires this event\n *    on all DOM nodes being removed.  This can be used to clean up any 3rd party bindings to the DOM\n *    element before it is removed.\n *\n * ### Methods\n * - `controller(name)` - retrieves the controller of the current element or its parent. By default\n *   retrieves controller associated with the `ngController` directive. If `name` is provided as\n *   camelCase directive name, then the controller for this directive will be retrieved (e.g.\n *   `'ngModel'`).\n * - `injector()` - retrieves the injector of the current element or its parent.\n * - `scope()` - retrieves the {@link ng.$rootScope.Scope scope} of the current\n *   element or its parent. Requires {@link guide/production#disabling-debug-data Debug Data} to\n *   be enabled.\n * - `isolateScope()` - retrieves an isolate {@link ng.$rootScope.Scope scope} if one is attached directly to the\n *   current element. This getter should be used only on elements that contain a directive which starts a new isolate\n *   scope. Calling `scope()` on this element always returns the original non-isolate scope.\n *   Requires {@link guide/production#disabling-debug-data Debug Data} to be enabled.\n * - `inheritedData()` - same as `data()`, but walks up the DOM until a value is found or the top\n *   parent element is reached.\n *\n * @param {string|DOMElement} element HTML string or DOMElement to be wrapped into jQuery.\n * @returns {Object} jQuery object.\n */\n\nJQLite.expando = 'ng339';\n\nvar jqCache = JQLite.cache = {},\n    jqId = 1,\n    addEventListenerFn = function(element, type, fn) {\n      element.addEventListener(type, fn, false);\n    },\n    removeEventListenerFn = function(element, type, fn) {\n      element.removeEventListener(type, fn, false);\n    };\n\n/*\n * !!! This is an undocumented \"private\" function !!!\n */\nJQLite._data = function(node) {\n  //jQuery always returns an object on cache miss\n  return this.cache[node[this.expando]] || {};\n};\n\nfunction jqNextId() { return ++jqId; }\n\n\nvar SPECIAL_CHARS_REGEXP = /([\\:\\-\\_]+(.))/g;\nvar MOZ_HACK_REGEXP = /^moz([A-Z])/;\nvar MOUSE_EVENT_MAP= { mouseleave: \"mouseout\", mouseenter: \"mouseover\"};\nvar jqLiteMinErr = minErr('jqLite');\n\n/**\n * Converts snake_case to camelCase.\n * Also there is special case for Moz prefix starting with upper case letter.\n * @param name Name to normalize\n */\nfunction camelCase(name) {\n  return name.\n    replace(SPECIAL_CHARS_REGEXP, function(_, separator, letter, offset) {\n      return offset ? letter.toUpperCase() : letter;\n    }).\n    replace(MOZ_HACK_REGEXP, 'Moz$1');\n}\n\nvar SINGLE_TAG_REGEXP = /^<(\\w+)\\s*\\/?>(?:<\\/\\1>|)$/;\nvar HTML_REGEXP = /<|&#?\\w+;/;\nvar TAG_NAME_REGEXP = /<([\\w:]+)/;\nvar XHTML_TAG_REGEXP = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\\w:]+)[^>]*)\\/>/gi;\n\nvar wrapMap = {\n  'option': [1, '<select multiple=\"multiple\">', '</select>'],\n\n  'thead': [1, '<table>', '</table>'],\n  'col': [2, '<table><colgroup>', '</colgroup></table>'],\n  'tr': [2, '<table><tbody>', '</tbody></table>'],\n  'td': [3, '<table><tbody><tr>', '</tr></tbody></table>'],\n  '_default': [0, \"\", \"\"]\n};\n\nwrapMap.optgroup = wrapMap.option;\nwrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;\nwrapMap.th = wrapMap.td;\n\n\nfunction jqLiteIsTextNode(html) {\n  return !HTML_REGEXP.test(html);\n}\n\nfunction jqLiteAcceptsData(node) {\n  // The window object can accept data but has no nodeType\n  // Otherwise we are only interested in elements (1) and documents (9)\n  var nodeType = node.nodeType;\n  return nodeType === NODE_TYPE_ELEMENT || !nodeType || nodeType === NODE_TYPE_DOCUMENT;\n}\n\nfunction jqLiteBuildFragment(html, context) {\n  var tmp, tag, wrap,\n      fragment = context.createDocumentFragment(),\n      nodes = [], i;\n\n  if (jqLiteIsTextNode(html)) {\n    // Convert non-html into a text node\n    nodes.push(context.createTextNode(html));\n  } else {\n    // Convert html into DOM nodes\n    tmp = tmp || fragment.appendChild(context.createElement(\"div\"));\n    tag = (TAG_NAME_REGEXP.exec(html) || [\"\", \"\"])[1].toLowerCase();\n    wrap = wrapMap[tag] || wrapMap._default;\n    tmp.innerHTML = wrap[1] + html.replace(XHTML_TAG_REGEXP, \"<$1></$2>\") + wrap[2];\n\n    // Descend through wrappers to the right content\n    i = wrap[0];\n    while (i--) {\n      tmp = tmp.lastChild;\n    }\n\n    nodes = concat(nodes, tmp.childNodes);\n\n    tmp = fragment.firstChild;\n    tmp.textContent = \"\";\n  }\n\n  // Remove wrapper from fragment\n  fragment.textContent = \"\";\n  fragment.innerHTML = \"\"; // Clear inner HTML\n  forEach(nodes, function(node) {\n    fragment.appendChild(node);\n  });\n\n  return fragment;\n}\n\nfunction jqLiteParseHTML(html, context) {\n  context = context || document;\n  var parsed;\n\n  if ((parsed = SINGLE_TAG_REGEXP.exec(html))) {\n    return [context.createElement(parsed[1])];\n  }\n\n  if ((parsed = jqLiteBuildFragment(html, context))) {\n    return parsed.childNodes;\n  }\n\n  return [];\n}\n\n/////////////////////////////////////////////\nfunction JQLite(element) {\n  if (element instanceof JQLite) {\n    return element;\n  }\n\n  var argIsString;\n\n  if (isString(element)) {\n    element = trim(element);\n    argIsString = true;\n  }\n  if (!(this instanceof JQLite)) {\n    if (argIsString && element.charAt(0) != '<') {\n      throw jqLiteMinErr('nosel', 'Looking up elements via selectors is not supported by jqLite! See: http://docs.angularjs.org/api/angular.element');\n    }\n    return new JQLite(element);\n  }\n\n  if (argIsString) {\n    jqLiteAddNodes(this, jqLiteParseHTML(element));\n  } else {\n    jqLiteAddNodes(this, element);\n  }\n}\n\nfunction jqLiteClone(element) {\n  return element.cloneNode(true);\n}\n\nfunction jqLiteDealoc(element, onlyDescendants) {\n  if (!onlyDescendants) jqLiteRemoveData(element);\n\n  if (element.querySelectorAll) {\n    var descendants = element.querySelectorAll('*');\n    for (var i = 0, l = descendants.length; i < l; i++) {\n      jqLiteRemoveData(descendants[i]);\n    }\n  }\n}\n\nfunction jqLiteOff(element, type, fn, unsupported) {\n  if (isDefined(unsupported)) throw jqLiteMinErr('offargs', 'jqLite#off() does not support the `selector` argument');\n\n  var expandoStore = jqLiteExpandoStore(element);\n  var events = expandoStore && expandoStore.events;\n  var handle = expandoStore && expandoStore.handle;\n\n  if (!handle) return; //no listeners registered\n\n  if (!type) {\n    for (type in events) {\n      if (type !== '$destroy') {\n        removeEventListenerFn(element, type, handle);\n      }\n      delete events[type];\n    }\n  } else {\n    forEach(type.split(' '), function(type) {\n      if (isDefined(fn)) {\n        var listenerFns = events[type];\n        arrayRemove(listenerFns || [], fn);\n        if (listenerFns && listenerFns.length > 0) {\n          return;\n        }\n      }\n\n      removeEventListenerFn(element, type, handle);\n      delete events[type];\n    });\n  }\n}\n\nfunction jqLiteRemoveData(element, name) {\n  var expandoId = element.ng339;\n  var expandoStore = expandoId && jqCache[expandoId];\n\n  if (expandoStore) {\n    if (name) {\n      delete expandoStore.data[name];\n      return;\n    }\n\n    if (expandoStore.handle) {\n      if (expandoStore.events.$destroy) {\n        expandoStore.handle({}, '$destroy');\n      }\n      jqLiteOff(element);\n    }\n    delete jqCache[expandoId];\n    element.ng339 = undefined; // don't delete DOM expandos. IE and Chrome don't like it\n  }\n}\n\n\nfunction jqLiteExpandoStore(element, createIfNecessary) {\n  var expandoId = element.ng339,\n      expandoStore = expandoId && jqCache[expandoId];\n\n  if (createIfNecessary && !expandoStore) {\n    element.ng339 = expandoId = jqNextId();\n    expandoStore = jqCache[expandoId] = {events: {}, data: {}, handle: undefined};\n  }\n\n  return expandoStore;\n}\n\n\nfunction jqLiteData(element, key, value) {\n  if (jqLiteAcceptsData(element)) {\n\n    var isSimpleSetter = isDefined(value);\n    var isSimpleGetter = !isSimpleSetter && key && !isObject(key);\n    var massGetter = !key;\n    var expandoStore = jqLiteExpandoStore(element, !isSimpleGetter);\n    var data = expandoStore && expandoStore.data;\n\n    if (isSimpleSetter) { // data('key', value)\n      data[key] = value;\n    } else {\n      if (massGetter) {  // data()\n        return data;\n      } else {\n        if (isSimpleGetter) { // data('key')\n          // don't force creation of expandoStore if it doesn't exist yet\n          return data && data[key];\n        } else { // mass-setter: data({key1: val1, key2: val2})\n          extend(data, key);\n        }\n      }\n    }\n  }\n}\n\nfunction jqLiteHasClass(element, selector) {\n  if (!element.getAttribute) return false;\n  return ((\" \" + (element.getAttribute('class') || '') + \" \").replace(/[\\n\\t]/g, \" \").\n      indexOf(\" \" + selector + \" \") > -1);\n}\n\nfunction jqLiteRemoveClass(element, cssClasses) {\n  if (cssClasses && element.setAttribute) {\n    forEach(cssClasses.split(' '), function(cssClass) {\n      element.setAttribute('class', trim(\n          (\" \" + (element.getAttribute('class') || '') + \" \")\n          .replace(/[\\n\\t]/g, \" \")\n          .replace(\" \" + trim(cssClass) + \" \", \" \"))\n      );\n    });\n  }\n}\n\nfunction jqLiteAddClass(element, cssClasses) {\n  if (cssClasses && element.setAttribute) {\n    var existingClasses = (' ' + (element.getAttribute('class') || '') + ' ')\n                            .replace(/[\\n\\t]/g, \" \");\n\n    forEach(cssClasses.split(' '), function(cssClass) {\n      cssClass = trim(cssClass);\n      if (existingClasses.indexOf(' ' + cssClass + ' ') === -1) {\n        existingClasses += cssClass + ' ';\n      }\n    });\n\n    element.setAttribute('class', trim(existingClasses));\n  }\n}\n\n\nfunction jqLiteAddNodes(root, elements) {\n  // THIS CODE IS VERY HOT. Don't make changes without benchmarking.\n\n  if (elements) {\n\n    // if a Node (the most common case)\n    if (elements.nodeType) {\n      root[root.length++] = elements;\n    } else {\n      var length = elements.length;\n\n      // if an Array or NodeList and not a Window\n      if (typeof length === 'number' && elements.window !== elements) {\n        if (length) {\n          for (var i = 0; i < length; i++) {\n            root[root.length++] = elements[i];\n          }\n        }\n      } else {\n        root[root.length++] = elements;\n      }\n    }\n  }\n}\n\n\nfunction jqLiteController(element, name) {\n  return jqLiteInheritedData(element, '$' + (name || 'ngController') + 'Controller');\n}\n\nfunction jqLiteInheritedData(element, name, value) {\n  // if element is the document object work with the html element instead\n  // this makes $(document).scope() possible\n  if (element.nodeType == NODE_TYPE_DOCUMENT) {\n    element = element.documentElement;\n  }\n  var names = isArray(name) ? name : [name];\n\n  while (element) {\n    for (var i = 0, ii = names.length; i < ii; i++) {\n      if ((value = jqLite.data(element, names[i])) !== undefined) return value;\n    }\n\n    // If dealing with a document fragment node with a host element, and no parent, use the host\n    // element as the parent. This enables directives within a Shadow DOM or polyfilled Shadow DOM\n    // to lookup parent controllers.\n    element = element.parentNode || (element.nodeType === NODE_TYPE_DOCUMENT_FRAGMENT && element.host);\n  }\n}\n\nfunction jqLiteEmpty(element) {\n  jqLiteDealoc(element, true);\n  while (element.firstChild) {\n    element.removeChild(element.firstChild);\n  }\n}\n\nfunction jqLiteRemove(element, keepData) {\n  if (!keepData) jqLiteDealoc(element);\n  var parent = element.parentNode;\n  if (parent) parent.removeChild(element);\n}\n\n\nfunction jqLiteDocumentLoaded(action, win) {\n  win = win || window;\n  if (win.document.readyState === 'complete') {\n    // Force the action to be run async for consistent behaviour\n    // from the action's point of view\n    // i.e. it will definitely not be in a $apply\n    win.setTimeout(action);\n  } else {\n    // No need to unbind this handler as load is only ever called once\n    jqLite(win).on('load', action);\n  }\n}\n\n//////////////////////////////////////////\n// Functions which are declared directly.\n//////////////////////////////////////////\nvar JQLitePrototype = JQLite.prototype = {\n  ready: function(fn) {\n    var fired = false;\n\n    function trigger() {\n      if (fired) return;\n      fired = true;\n      fn();\n    }\n\n    // check if document is already loaded\n    if (document.readyState === 'complete') {\n      setTimeout(trigger);\n    } else {\n      this.on('DOMContentLoaded', trigger); // works for modern browsers and IE9\n      // we can not use jqLite since we are not done loading and jQuery could be loaded later.\n      // jshint -W064\n      JQLite(window).on('load', trigger); // fallback to window.onload for others\n      // jshint +W064\n    }\n  },\n  toString: function() {\n    var value = [];\n    forEach(this, function(e) { value.push('' + e);});\n    return '[' + value.join(', ') + ']';\n  },\n\n  eq: function(index) {\n      return (index >= 0) ? jqLite(this[index]) : jqLite(this[this.length + index]);\n  },\n\n  length: 0,\n  push: push,\n  sort: [].sort,\n  splice: [].splice\n};\n\n//////////////////////////////////////////\n// Functions iterating getter/setters.\n// these functions return self on setter and\n// value on get.\n//////////////////////////////////////////\nvar BOOLEAN_ATTR = {};\nforEach('multiple,selected,checked,disabled,readOnly,required,open'.split(','), function(value) {\n  BOOLEAN_ATTR[lowercase(value)] = value;\n});\nvar BOOLEAN_ELEMENTS = {};\nforEach('input,select,option,textarea,button,form,details'.split(','), function(value) {\n  BOOLEAN_ELEMENTS[value] = true;\n});\nvar ALIASED_ATTR = {\n  'ngMinlength': 'minlength',\n  'ngMaxlength': 'maxlength',\n  'ngMin': 'min',\n  'ngMax': 'max',\n  'ngPattern': 'pattern'\n};\n\nfunction getBooleanAttrName(element, name) {\n  // check dom last since we will most likely fail on name\n  var booleanAttr = BOOLEAN_ATTR[name.toLowerCase()];\n\n  // booleanAttr is here twice to minimize DOM access\n  return booleanAttr && BOOLEAN_ELEMENTS[nodeName_(element)] && booleanAttr;\n}\n\nfunction getAliasedAttrName(element, name) {\n  var nodeName = element.nodeName;\n  return (nodeName === 'INPUT' || nodeName === 'TEXTAREA') && ALIASED_ATTR[name];\n}\n\nforEach({\n  data: jqLiteData,\n  removeData: jqLiteRemoveData\n}, function(fn, name) {\n  JQLite[name] = fn;\n});\n\nforEach({\n  data: jqLiteData,\n  inheritedData: jqLiteInheritedData,\n\n  scope: function(element) {\n    // Can't use jqLiteData here directly so we stay compatible with jQuery!\n    return jqLite.data(element, '$scope') || jqLiteInheritedData(element.parentNode || element, ['$isolateScope', '$scope']);\n  },\n\n  isolateScope: function(element) {\n    // Can't use jqLiteData here directly so we stay compatible with jQuery!\n    return jqLite.data(element, '$isolateScope') || jqLite.data(element, '$isolateScopeNoTemplate');\n  },\n\n  controller: jqLiteController,\n\n  injector: function(element) {\n    return jqLiteInheritedData(element, '$injector');\n  },\n\n  removeAttr: function(element, name) {\n    element.removeAttribute(name);\n  },\n\n  hasClass: jqLiteHasClass,\n\n  css: function(element, name, value) {\n    name = camelCase(name);\n\n    if (isDefined(value)) {\n      element.style[name] = value;\n    } else {\n      return element.style[name];\n    }\n  },\n\n  attr: function(element, name, value) {\n    var lowercasedName = lowercase(name);\n    if (BOOLEAN_ATTR[lowercasedName]) {\n      if (isDefined(value)) {\n        if (!!value) {\n          element[name] = true;\n          element.setAttribute(name, lowercasedName);\n        } else {\n          element[name] = false;\n          element.removeAttribute(lowercasedName);\n        }\n      } else {\n        return (element[name] ||\n                 (element.attributes.getNamedItem(name) || noop).specified)\n               ? lowercasedName\n               : undefined;\n      }\n    } else if (isDefined(value)) {\n      element.setAttribute(name, value);\n    } else if (element.getAttribute) {\n      // the extra argument \"2\" is to get the right thing for a.href in IE, see jQuery code\n      // some elements (e.g. Document) don't have get attribute, so return undefined\n      var ret = element.getAttribute(name, 2);\n      // normalize non-existing attributes to undefined (as jQuery)\n      return ret === null ? undefined : ret;\n    }\n  },\n\n  prop: function(element, name, value) {\n    if (isDefined(value)) {\n      element[name] = value;\n    } else {\n      return element[name];\n    }\n  },\n\n  text: (function() {\n    getText.$dv = '';\n    return getText;\n\n    function getText(element, value) {\n      if (isUndefined(value)) {\n        var nodeType = element.nodeType;\n        return (nodeType === NODE_TYPE_ELEMENT || nodeType === NODE_TYPE_TEXT) ? element.textContent : '';\n      }\n      element.textContent = value;\n    }\n  })(),\n\n  val: function(element, value) {\n    if (isUndefined(value)) {\n      if (element.multiple && nodeName_(element) === 'select') {\n        var result = [];\n        forEach(element.options, function(option) {\n          if (option.selected) {\n            result.push(option.value || option.text);\n          }\n        });\n        return result.length === 0 ? null : result;\n      }\n      return element.value;\n    }\n    element.value = value;\n  },\n\n  html: function(element, value) {\n    if (isUndefined(value)) {\n      return element.innerHTML;\n    }\n    jqLiteDealoc(element, true);\n    element.innerHTML = value;\n  },\n\n  empty: jqLiteEmpty\n}, function(fn, name) {\n  /**\n   * Properties: writes return selection, reads return first value\n   */\n  JQLite.prototype[name] = function(arg1, arg2) {\n    var i, key;\n    var nodeCount = this.length;\n\n    // jqLiteHasClass has only two arguments, but is a getter-only fn, so we need to special-case it\n    // in a way that survives minification.\n    // jqLiteEmpty takes no arguments but is a setter.\n    if (fn !== jqLiteEmpty &&\n        (((fn.length == 2 && (fn !== jqLiteHasClass && fn !== jqLiteController)) ? arg1 : arg2) === undefined)) {\n      if (isObject(arg1)) {\n\n        // we are a write, but the object properties are the key/values\n        for (i = 0; i < nodeCount; i++) {\n          if (fn === jqLiteData) {\n            // data() takes the whole object in jQuery\n            fn(this[i], arg1);\n          } else {\n            for (key in arg1) {\n              fn(this[i], key, arg1[key]);\n            }\n          }\n        }\n        // return self for chaining\n        return this;\n      } else {\n        // we are a read, so read the first child.\n        // TODO: do we still need this?\n        var value = fn.$dv;\n        // Only if we have $dv do we iterate over all, otherwise it is just the first element.\n        var jj = (value === undefined) ? Math.min(nodeCount, 1) : nodeCount;\n        for (var j = 0; j < jj; j++) {\n          var nodeValue = fn(this[j], arg1, arg2);\n          value = value ? value + nodeValue : nodeValue;\n        }\n        return value;\n      }\n    } else {\n      // we are a write, so apply to all children\n      for (i = 0; i < nodeCount; i++) {\n        fn(this[i], arg1, arg2);\n      }\n      // return self for chaining\n      return this;\n    }\n  };\n});\n\nfunction createEventHandler(element, events) {\n  var eventHandler = function(event, type) {\n    // jQuery specific api\n    event.isDefaultPrevented = function() {\n      return event.defaultPrevented;\n    };\n\n    var eventFns = events[type || event.type];\n    var eventFnsLength = eventFns ? eventFns.length : 0;\n\n    if (!eventFnsLength) return;\n\n    if (isUndefined(event.immediatePropagationStopped)) {\n      var originalStopImmediatePropagation = event.stopImmediatePropagation;\n      event.stopImmediatePropagation = function() {\n        event.immediatePropagationStopped = true;\n\n        if (event.stopPropagation) {\n          event.stopPropagation();\n        }\n\n        if (originalStopImmediatePropagation) {\n          originalStopImmediatePropagation.call(event);\n        }\n      };\n    }\n\n    event.isImmediatePropagationStopped = function() {\n      return event.immediatePropagationStopped === true;\n    };\n\n    // Copy event handlers in case event handlers array is modified during execution.\n    if ((eventFnsLength > 1)) {\n      eventFns = shallowCopy(eventFns);\n    }\n\n    for (var i = 0; i < eventFnsLength; i++) {\n      if (!event.isImmediatePropagationStopped()) {\n        eventFns[i].call(element, event);\n      }\n    }\n  };\n\n  // TODO: this is a hack for angularMocks/clearDataCache that makes it possible to deregister all\n  //       events on `element`\n  eventHandler.elem = element;\n  return eventHandler;\n}\n\n//////////////////////////////////////////\n// Functions iterating traversal.\n// These functions chain results into a single\n// selector.\n//////////////////////////////////////////\nforEach({\n  removeData: jqLiteRemoveData,\n\n  on: function jqLiteOn(element, type, fn, unsupported) {\n    if (isDefined(unsupported)) throw jqLiteMinErr('onargs', 'jqLite#on() does not support the `selector` or `eventData` parameters');\n\n    // Do not add event handlers to non-elements because they will not be cleaned up.\n    if (!jqLiteAcceptsData(element)) {\n      return;\n    }\n\n    var expandoStore = jqLiteExpandoStore(element, true);\n    var events = expandoStore.events;\n    var handle = expandoStore.handle;\n\n    if (!handle) {\n      handle = expandoStore.handle = createEventHandler(element, events);\n    }\n\n    // http://jsperf.com/string-indexof-vs-split\n    var types = type.indexOf(' ') >= 0 ? type.split(' ') : [type];\n    var i = types.length;\n\n    while (i--) {\n      type = types[i];\n      var eventFns = events[type];\n\n      if (!eventFns) {\n        events[type] = [];\n\n        if (type === 'mouseenter' || type === 'mouseleave') {\n          // Refer to jQuery's implementation of mouseenter & mouseleave\n          // Read about mouseenter and mouseleave:\n          // http://www.quirksmode.org/js/events_mouse.html#link8\n\n          jqLiteOn(element, MOUSE_EVENT_MAP[type], function(event) {\n            var target = this, related = event.relatedTarget;\n            // For mousenter/leave call the handler if related is outside the target.\n            // NB: No relatedTarget if the mouse left/entered the browser window\n            if (!related || (related !== target && !target.contains(related))) {\n              handle(event, type);\n            }\n          });\n\n        } else {\n          if (type !== '$destroy') {\n            addEventListenerFn(element, type, handle);\n          }\n        }\n        eventFns = events[type];\n      }\n      eventFns.push(fn);\n    }\n  },\n\n  off: jqLiteOff,\n\n  one: function(element, type, fn) {\n    element = jqLite(element);\n\n    //add the listener twice so that when it is called\n    //you can remove the original function and still be\n    //able to call element.off(ev, fn) normally\n    element.on(type, function onFn() {\n      element.off(type, fn);\n      element.off(type, onFn);\n    });\n    element.on(type, fn);\n  },\n\n  replaceWith: function(element, replaceNode) {\n    var index, parent = element.parentNode;\n    jqLiteDealoc(element);\n    forEach(new JQLite(replaceNode), function(node) {\n      if (index) {\n        parent.insertBefore(node, index.nextSibling);\n      } else {\n        parent.replaceChild(node, element);\n      }\n      index = node;\n    });\n  },\n\n  children: function(element) {\n    var children = [];\n    forEach(element.childNodes, function(element) {\n      if (element.nodeType === NODE_TYPE_ELEMENT)\n        children.push(element);\n    });\n    return children;\n  },\n\n  contents: function(element) {\n    return element.contentDocument || element.childNodes || [];\n  },\n\n  append: function(element, node) {\n    var nodeType = element.nodeType;\n    if (nodeType !== NODE_TYPE_ELEMENT && nodeType !== NODE_TYPE_DOCUMENT_FRAGMENT) return;\n\n    node = new JQLite(node);\n\n    for (var i = 0, ii = node.length; i < ii; i++) {\n      var child = node[i];\n      element.appendChild(child);\n    }\n  },\n\n  prepend: function(element, node) {\n    if (element.nodeType === NODE_TYPE_ELEMENT) {\n      var index = element.firstChild;\n      forEach(new JQLite(node), function(child) {\n        element.insertBefore(child, index);\n      });\n    }\n  },\n\n  wrap: function(element, wrapNode) {\n    wrapNode = jqLite(wrapNode).eq(0).clone()[0];\n    var parent = element.parentNode;\n    if (parent) {\n      parent.replaceChild(wrapNode, element);\n    }\n    wrapNode.appendChild(element);\n  },\n\n  remove: jqLiteRemove,\n\n  detach: function(element) {\n    jqLiteRemove(element, true);\n  },\n\n  after: function(element, newElement) {\n    var index = element, parent = element.parentNode;\n    newElement = new JQLite(newElement);\n\n    for (var i = 0, ii = newElement.length; i < ii; i++) {\n      var node = newElement[i];\n      parent.insertBefore(node, index.nextSibling);\n      index = node;\n    }\n  },\n\n  addClass: jqLiteAddClass,\n  removeClass: jqLiteRemoveClass,\n\n  toggleClass: function(element, selector, condition) {\n    if (selector) {\n      forEach(selector.split(' '), function(className) {\n        var classCondition = condition;\n        if (isUndefined(classCondition)) {\n          classCondition = !jqLiteHasClass(element, className);\n        }\n        (classCondition ? jqLiteAddClass : jqLiteRemoveClass)(element, className);\n      });\n    }\n  },\n\n  parent: function(element) {\n    var parent = element.parentNode;\n    return parent && parent.nodeType !== NODE_TYPE_DOCUMENT_FRAGMENT ? parent : null;\n  },\n\n  next: function(element) {\n    return element.nextElementSibling;\n  },\n\n  find: function(element, selector) {\n    if (element.getElementsByTagName) {\n      return element.getElementsByTagName(selector);\n    } else {\n      return [];\n    }\n  },\n\n  clone: jqLiteClone,\n\n  triggerHandler: function(element, event, extraParameters) {\n\n    var dummyEvent, eventFnsCopy, handlerArgs;\n    var eventName = event.type || event;\n    var expandoStore = jqLiteExpandoStore(element);\n    var events = expandoStore && expandoStore.events;\n    var eventFns = events && events[eventName];\n\n    if (eventFns) {\n      // Create a dummy event to pass to the handlers\n      dummyEvent = {\n        preventDefault: function() { this.defaultPrevented = true; },\n        isDefaultPrevented: function() { return this.defaultPrevented === true; },\n        stopImmediatePropagation: function() { this.immediatePropagationStopped = true; },\n        isImmediatePropagationStopped: function() { return this.immediatePropagationStopped === true; },\n        stopPropagation: noop,\n        type: eventName,\n        target: element\n      };\n\n      // If a custom event was provided then extend our dummy event with it\n      if (event.type) {\n        dummyEvent = extend(dummyEvent, event);\n      }\n\n      // Copy event handlers in case event handlers array is modified during execution.\n      eventFnsCopy = shallowCopy(eventFns);\n      handlerArgs = extraParameters ? [dummyEvent].concat(extraParameters) : [dummyEvent];\n\n      forEach(eventFnsCopy, function(fn) {\n        if (!dummyEvent.isImmediatePropagationStopped()) {\n          fn.apply(element, handlerArgs);\n        }\n      });\n    }\n  }\n}, function(fn, name) {\n  /**\n   * chaining functions\n   */\n  JQLite.prototype[name] = function(arg1, arg2, arg3) {\n    var value;\n\n    for (var i = 0, ii = this.length; i < ii; i++) {\n      if (isUndefined(value)) {\n        value = fn(this[i], arg1, arg2, arg3);\n        if (isDefined(value)) {\n          // any function which returns a value needs to be wrapped\n          value = jqLite(value);\n        }\n      } else {\n        jqLiteAddNodes(value, fn(this[i], arg1, arg2, arg3));\n      }\n    }\n    return isDefined(value) ? value : this;\n  };\n\n  // bind legacy bind/unbind to on/off\n  JQLite.prototype.bind = JQLite.prototype.on;\n  JQLite.prototype.unbind = JQLite.prototype.off;\n});\n\n\n// Provider for private $$jqLite service\nfunction $$jqLiteProvider() {\n  this.$get = function $$jqLite() {\n    return extend(JQLite, {\n      hasClass: function(node, classes) {\n        if (node.attr) node = node[0];\n        return jqLiteHasClass(node, classes);\n      },\n      addClass: function(node, classes) {\n        if (node.attr) node = node[0];\n        return jqLiteAddClass(node, classes);\n      },\n      removeClass: function(node, classes) {\n        if (node.attr) node = node[0];\n        return jqLiteRemoveClass(node, classes);\n      }\n    });\n  };\n}\n\n/**\n * Computes a hash of an 'obj'.\n * Hash of a:\n *  string is string\n *  number is number as string\n *  object is either result of calling $$hashKey function on the object or uniquely generated id,\n *         that is also assigned to the $$hashKey property of the object.\n *\n * @param obj\n * @returns {string} hash string such that the same input will have the same hash string.\n *         The resulting string key is in 'type:hashKey' format.\n */\nfunction hashKey(obj, nextUidFn) {\n  var key = obj && obj.$$hashKey;\n\n  if (key) {\n    if (typeof key === 'function') {\n      key = obj.$$hashKey();\n    }\n    return key;\n  }\n\n  var objType = typeof obj;\n  if (objType == 'function' || (objType == 'object' && obj !== null)) {\n    key = obj.$$hashKey = objType + ':' + (nextUidFn || nextUid)();\n  } else {\n    key = objType + ':' + obj;\n  }\n\n  return key;\n}\n\n/**\n * HashMap which can use objects as keys\n */\nfunction HashMap(array, isolatedUid) {\n  if (isolatedUid) {\n    var uid = 0;\n    this.nextUid = function() {\n      return ++uid;\n    };\n  }\n  forEach(array, this.put, this);\n}\nHashMap.prototype = {\n  /**\n   * Store key value pair\n   * @param key key to store can be any type\n   * @param value value to store can be any type\n   */\n  put: function(key, value) {\n    this[hashKey(key, this.nextUid)] = value;\n  },\n\n  /**\n   * @param key\n   * @returns {Object} the value for the key\n   */\n  get: function(key) {\n    return this[hashKey(key, this.nextUid)];\n  },\n\n  /**\n   * Remove the key/value pair\n   * @param key\n   */\n  remove: function(key) {\n    var value = this[key = hashKey(key, this.nextUid)];\n    delete this[key];\n    return value;\n  }\n};\n\n/**\n * @ngdoc function\n * @module ng\n * @name angular.injector\n * @kind function\n *\n * @description\n * Creates an injector object that can be used for retrieving services as well as for\n * dependency injection (see {@link guide/di dependency injection}).\n *\n * @param {Array.<string|Function>} modules A list of module functions or their aliases. See\n *     {@link angular.module}. The `ng` module must be explicitly added.\n * @param {boolean=} [strictDi=false] Whether the injector should be in strict mode, which\n *     disallows argument name annotation inference.\n * @returns {injector} Injector object. See {@link auto.$injector $injector}.\n *\n * @example\n * Typical usage\n * ```js\n *   // create an injector\n *   var $injector = angular.injector(['ng']);\n *\n *   // use the injector to kick off your application\n *   // use the type inference to auto inject arguments, or use implicit injection\n *   $injector.invoke(function($rootScope, $compile, $document) {\n *     $compile($document)($rootScope);\n *     $rootScope.$digest();\n *   });\n * ```\n *\n * Sometimes you want to get access to the injector of a currently running Angular app\n * from outside Angular. Perhaps, you want to inject and compile some markup after the\n * application has been bootstrapped. You can do this using the extra `injector()` added\n * to JQuery/jqLite elements. See {@link angular.element}.\n *\n * *This is fairly rare but could be the case if a third party library is injecting the\n * markup.*\n *\n * In the following example a new block of HTML containing a `ng-controller`\n * directive is added to the end of the document body by JQuery. We then compile and link\n * it into the current AngularJS scope.\n *\n * ```js\n * var $div = $('<div ng-controller=\"MyCtrl\">{{content.label}}</div>');\n * $(document.body).append($div);\n *\n * angular.element(document).injector().invoke(function($compile) {\n *   var scope = angular.element($div).scope();\n *   $compile($div)(scope);\n * });\n * ```\n */\n\n\n/**\n * @ngdoc module\n * @name auto\n * @description\n *\n * Implicit module which gets automatically added to each {@link auto.$injector $injector}.\n */\n\nvar FN_ARGS = /^function\\s*[^\\(]*\\(\\s*([^\\)]*)\\)/m;\nvar FN_ARG_SPLIT = /,/;\nvar FN_ARG = /^\\s*(_?)(\\S+?)\\1\\s*$/;\nvar STRIP_COMMENTS = /((\\/\\/.*$)|(\\/\\*[\\s\\S]*?\\*\\/))/mg;\nvar $injectorMinErr = minErr('$injector');\n\nfunction anonFn(fn) {\n  // For anonymous functions, showing at the very least the function signature can help in\n  // debugging.\n  var fnText = fn.toString().replace(STRIP_COMMENTS, ''),\n      args = fnText.match(FN_ARGS);\n  if (args) {\n    return 'function(' + (args[1] || '').replace(/[\\s\\r\\n]+/, ' ') + ')';\n  }\n  return 'fn';\n}\n\nfunction annotate(fn, strictDi, name) {\n  var $inject,\n      fnText,\n      argDecl,\n      last;\n\n  if (typeof fn === 'function') {\n    if (!($inject = fn.$inject)) {\n      $inject = [];\n      if (fn.length) {\n        if (strictDi) {\n          if (!isString(name) || !name) {\n            name = fn.name || anonFn(fn);\n          }\n          throw $injectorMinErr('strictdi',\n            '{0} is not using explicit annotation and cannot be invoked in strict mode', name);\n        }\n        fnText = fn.toString().replace(STRIP_COMMENTS, '');\n        argDecl = fnText.match(FN_ARGS);\n        forEach(argDecl[1].split(FN_ARG_SPLIT), function(arg) {\n          arg.replace(FN_ARG, function(all, underscore, name) {\n            $inject.push(name);\n          });\n        });\n      }\n      fn.$inject = $inject;\n    }\n  } else if (isArray(fn)) {\n    last = fn.length - 1;\n    assertArgFn(fn[last], 'fn');\n    $inject = fn.slice(0, last);\n  } else {\n    assertArgFn(fn, 'fn', true);\n  }\n  return $inject;\n}\n\n///////////////////////////////////////\n\n/**\n * @ngdoc service\n * @name $injector\n *\n * @description\n *\n * `$injector` is used to retrieve object instances as defined by\n * {@link auto.$provide provider}, instantiate types, invoke methods,\n * and load modules.\n *\n * The following always holds true:\n *\n * ```js\n *   var $injector = angular.injector();\n *   expect($injector.get('$injector')).toBe($injector);\n *   expect($injector.invoke(function($injector) {\n *     return $injector;\n *   })).toBe($injector);\n * ```\n *\n * # Injection Function Annotation\n *\n * JavaScript does not have annotations, and annotations are needed for dependency injection. The\n * following are all valid ways of annotating function with injection arguments and are equivalent.\n *\n * ```js\n *   // inferred (only works if code not minified/obfuscated)\n *   $injector.invoke(function(serviceA){});\n *\n *   // annotated\n *   function explicit(serviceA) {};\n *   explicit.$inject = ['serviceA'];\n *   $injector.invoke(explicit);\n *\n *   // inline\n *   $injector.invoke(['serviceA', function(serviceA){}]);\n * ```\n *\n * ## Inference\n *\n * In JavaScript calling `toString()` on a function returns the function definition. The definition\n * can then be parsed and the function arguments can be extracted. This method of discovering\n * annotations is disallowed when the injector is in strict mode.\n * *NOTE:* This does not work with minification, and obfuscation tools since these tools change the\n * argument names.\n *\n * ## `$inject` Annotation\n * By adding an `$inject` property onto a function the injection parameters can be specified.\n *\n * ## Inline\n * As an array of injection names, where the last item in the array is the function to call.\n */\n\n/**\n * @ngdoc method\n * @name $injector#get\n *\n * @description\n * Return an instance of the service.\n *\n * @param {string} name The name of the instance to retrieve.\n * @param {string} caller An optional string to provide the origin of the function call for error messages.\n * @return {*} The instance.\n */\n\n/**\n * @ngdoc method\n * @name $injector#invoke\n *\n * @description\n * Invoke the method and supply the method arguments from the `$injector`.\n *\n * @param {!Function} fn The function to invoke. Function parameters are injected according to the\n *   {@link guide/di $inject Annotation} rules.\n * @param {Object=} self The `this` for the invoked method.\n * @param {Object=} locals Optional object. If preset then any argument names are read from this\n *                         object first, before the `$injector` is consulted.\n * @returns {*} the value returned by the invoked `fn` function.\n */\n\n/**\n * @ngdoc method\n * @name $injector#has\n *\n * @description\n * Allows the user to query if the particular service exists.\n *\n * @param {string} name Name of the service to query.\n * @returns {boolean} `true` if injector has given service.\n */\n\n/**\n * @ngdoc method\n * @name $injector#instantiate\n * @description\n * Create a new instance of JS type. The method takes a constructor function, invokes the new\n * operator, and supplies all of the arguments to the constructor function as specified by the\n * constructor annotation.\n *\n * @param {Function} Type Annotated constructor function.\n * @param {Object=} locals Optional object. If preset then any argument names are read from this\n * object first, before the `$injector` is consulted.\n * @returns {Object} new instance of `Type`.\n */\n\n/**\n * @ngdoc method\n * @name $injector#annotate\n *\n * @description\n * Returns an array of service names which the function is requesting for injection. This API is\n * used by the injector to determine which services need to be injected into the function when the\n * function is invoked. There are three ways in which the function can be annotated with the needed\n * dependencies.\n *\n * # Argument names\n *\n * The simplest form is to extract the dependencies from the arguments of the function. This is done\n * by converting the function into a string using `toString()` method and extracting the argument\n * names.\n * ```js\n *   // Given\n *   function MyController($scope, $route) {\n *     // ...\n *   }\n *\n *   // Then\n *   expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);\n * ```\n *\n * You can disallow this method by using strict injection mode.\n *\n * This method does not work with code minification / obfuscation. For this reason the following\n * annotation strategies are supported.\n *\n * # The `$inject` property\n *\n * If a function has an `$inject` property and its value is an array of strings, then the strings\n * represent names of services to be injected into the function.\n * ```js\n *   // Given\n *   var MyController = function(obfuscatedScope, obfuscatedRoute) {\n *     // ...\n *   }\n *   // Define function dependencies\n *   MyController['$inject'] = ['$scope', '$route'];\n *\n *   // Then\n *   expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);\n * ```\n *\n * # The array notation\n *\n * It is often desirable to inline Injected functions and that's when setting the `$inject` property\n * is very inconvenient. In these situations using the array notation to specify the dependencies in\n * a way that survives minification is a better choice:\n *\n * ```js\n *   // We wish to write this (not minification / obfuscation safe)\n *   injector.invoke(function($compile, $rootScope) {\n *     // ...\n *   });\n *\n *   // We are forced to write break inlining\n *   var tmpFn = function(obfuscatedCompile, obfuscatedRootScope) {\n *     // ...\n *   };\n *   tmpFn.$inject = ['$compile', '$rootScope'];\n *   injector.invoke(tmpFn);\n *\n *   // To better support inline function the inline annotation is supported\n *   injector.invoke(['$compile', '$rootScope', function(obfCompile, obfRootScope) {\n *     // ...\n *   }]);\n *\n *   // Therefore\n *   expect(injector.annotate(\n *      ['$compile', '$rootScope', function(obfus_$compile, obfus_$rootScope) {}])\n *    ).toEqual(['$compile', '$rootScope']);\n * ```\n *\n * @param {Function|Array.<string|Function>} fn Function for which dependent service names need to\n * be retrieved as described above.\n *\n * @param {boolean=} [strictDi=false] Disallow argument name annotation inference.\n *\n * @returns {Array.<string>} The names of the services which the function requires.\n */\n\n\n\n\n/**\n * @ngdoc service\n * @name $provide\n *\n * @description\n *\n * The {@link auto.$provide $provide} service has a number of methods for registering components\n * with the {@link auto.$injector $injector}. Many of these functions are also exposed on\n * {@link angular.Module}.\n *\n * An Angular **service** is a singleton object created by a **service factory**.  These **service\n * factories** are functions which, in turn, are created by a **service provider**.\n * The **service providers** are constructor functions. When instantiated they must contain a\n * property called `$get`, which holds the **service factory** function.\n *\n * When you request a service, the {@link auto.$injector $injector} is responsible for finding the\n * correct **service provider**, instantiating it and then calling its `$get` **service factory**\n * function to get the instance of the **service**.\n *\n * Often services have no configuration options and there is no need to add methods to the service\n * provider.  The provider will be no more than a constructor function with a `$get` property. For\n * these cases the {@link auto.$provide $provide} service has additional helper methods to register\n * services without specifying a provider.\n *\n * * {@link auto.$provide#provider provider(provider)} - registers a **service provider** with the\n *     {@link auto.$injector $injector}\n * * {@link auto.$provide#constant constant(obj)} - registers a value/object that can be accessed by\n *     providers and services.\n * * {@link auto.$provide#value value(obj)} - registers a value/object that can only be accessed by\n *     services, not providers.\n * * {@link auto.$provide#factory factory(fn)} - registers a service **factory function**, `fn`,\n *     that will be wrapped in a **service provider** object, whose `$get` property will contain the\n *     given factory function.\n * * {@link auto.$provide#service service(class)} - registers a **constructor function**, `class`\n *     that will be wrapped in a **service provider** object, whose `$get` property will instantiate\n *      a new object using the given constructor function.\n *\n * See the individual methods for more information and examples.\n */\n\n/**\n * @ngdoc method\n * @name $provide#provider\n * @description\n *\n * Register a **provider function** with the {@link auto.$injector $injector}. Provider functions\n * are constructor functions, whose instances are responsible for \"providing\" a factory for a\n * service.\n *\n * Service provider names start with the name of the service they provide followed by `Provider`.\n * For example, the {@link ng.$log $log} service has a provider called\n * {@link ng.$logProvider $logProvider}.\n *\n * Service provider objects can have additional methods which allow configuration of the provider\n * and its service. Importantly, you can configure what kind of service is created by the `$get`\n * method, or how that service will act. For example, the {@link ng.$logProvider $logProvider} has a\n * method {@link ng.$logProvider#debugEnabled debugEnabled}\n * which lets you specify whether the {@link ng.$log $log} service will log debug messages to the\n * console or not.\n *\n * @param {string} name The name of the instance. NOTE: the provider will be available under `name +\n                        'Provider'` key.\n * @param {(Object|function())} provider If the provider is:\n *\n *   - `Object`: then it should have a `$get` method. The `$get` method will be invoked using\n *     {@link auto.$injector#invoke $injector.invoke()} when an instance needs to be created.\n *   - `Constructor`: a new instance of the provider will be created using\n *     {@link auto.$injector#instantiate $injector.instantiate()}, then treated as `object`.\n *\n * @returns {Object} registered provider instance\n\n * @example\n *\n * The following example shows how to create a simple event tracking service and register it using\n * {@link auto.$provide#provider $provide.provider()}.\n *\n * ```js\n *  // Define the eventTracker provider\n *  function EventTrackerProvider() {\n *    var trackingUrl = '/track';\n *\n *    // A provider method for configuring where the tracked events should been saved\n *    this.setTrackingUrl = function(url) {\n *      trackingUrl = url;\n *    };\n *\n *    // The service factory function\n *    this.$get = ['$http', function($http) {\n *      var trackedEvents = {};\n *      return {\n *        // Call this to track an event\n *        event: function(event) {\n *          var count = trackedEvents[event] || 0;\n *          count += 1;\n *          trackedEvents[event] = count;\n *          return count;\n *        },\n *        // Call this to save the tracked events to the trackingUrl\n *        save: function() {\n *          $http.post(trackingUrl, trackedEvents);\n *        }\n *      };\n *    }];\n *  }\n *\n *  describe('eventTracker', function() {\n *    var postSpy;\n *\n *    beforeEach(module(function($provide) {\n *      // Register the eventTracker provider\n *      $provide.provider('eventTracker', EventTrackerProvider);\n *    }));\n *\n *    beforeEach(module(function(eventTrackerProvider) {\n *      // Configure eventTracker provider\n *      eventTrackerProvider.setTrackingUrl('/custom-track');\n *    }));\n *\n *    it('tracks events', inject(function(eventTracker) {\n *      expect(eventTracker.event('login')).toEqual(1);\n *      expect(eventTracker.event('login')).toEqual(2);\n *    }));\n *\n *    it('saves to the tracking url', inject(function(eventTracker, $http) {\n *      postSpy = spyOn($http, 'post');\n *      eventTracker.event('login');\n *      eventTracker.save();\n *      expect(postSpy).toHaveBeenCalled();\n *      expect(postSpy.mostRecentCall.args[0]).not.toEqual('/track');\n *      expect(postSpy.mostRecentCall.args[0]).toEqual('/custom-track');\n *      expect(postSpy.mostRecentCall.args[1]).toEqual({ 'login': 1 });\n *    }));\n *  });\n * ```\n */\n\n/**\n * @ngdoc method\n * @name $provide#factory\n * @description\n *\n * Register a **service factory**, which will be called to return the service instance.\n * This is short for registering a service where its provider consists of only a `$get` property,\n * which is the given service factory function.\n * You should use {@link auto.$provide#factory $provide.factory(getFn)} if you do not need to\n * configure your service in a provider.\n *\n * @param {string} name The name of the instance.\n * @param {function()} $getFn The $getFn for the instance creation. Internally this is a short hand\n *                            for `$provide.provider(name, {$get: $getFn})`.\n * @returns {Object} registered provider instance\n *\n * @example\n * Here is an example of registering a service\n * ```js\n *   $provide.factory('ping', ['$http', function($http) {\n *     return function ping() {\n *       return $http.send('/ping');\n *     };\n *   }]);\n * ```\n * You would then inject and use this service like this:\n * ```js\n *   someModule.controller('Ctrl', ['ping', function(ping) {\n *     ping();\n *   }]);\n * ```\n */\n\n\n/**\n * @ngdoc method\n * @name $provide#service\n * @description\n *\n * Register a **service constructor**, which will be invoked with `new` to create the service\n * instance.\n * This is short for registering a service where its provider's `$get` property is the service\n * constructor function that will be used to instantiate the service instance.\n *\n * You should use {@link auto.$provide#service $provide.service(class)} if you define your service\n * as a type/class.\n *\n * @param {string} name The name of the instance.\n * @param {Function} constructor A class (constructor function) that will be instantiated.\n * @returns {Object} registered provider instance\n *\n * @example\n * Here is an example of registering a service using\n * {@link auto.$provide#service $provide.service(class)}.\n * ```js\n *   var Ping = function($http) {\n *     this.$http = $http;\n *   };\n *\n *   Ping.$inject = ['$http'];\n *\n *   Ping.prototype.send = function() {\n *     return this.$http.get('/ping');\n *   };\n *   $provide.service('ping', Ping);\n * ```\n * You would then inject and use this service like this:\n * ```js\n *   someModule.controller('Ctrl', ['ping', function(ping) {\n *     ping.send();\n *   }]);\n * ```\n */\n\n\n/**\n * @ngdoc method\n * @name $provide#value\n * @description\n *\n * Register a **value service** with the {@link auto.$injector $injector}, such as a string, a\n * number, an array, an object or a function.  This is short for registering a service where its\n * provider's `$get` property is a factory function that takes no arguments and returns the **value\n * service**.\n *\n * Value services are similar to constant services, except that they cannot be injected into a\n * module configuration function (see {@link angular.Module#config}) but they can be overridden by\n * an Angular\n * {@link auto.$provide#decorator decorator}.\n *\n * @param {string} name The name of the instance.\n * @param {*} value The value.\n * @returns {Object} registered provider instance\n *\n * @example\n * Here are some examples of creating value services.\n * ```js\n *   $provide.value('ADMIN_USER', 'admin');\n *\n *   $provide.value('RoleLookup', { admin: 0, writer: 1, reader: 2 });\n *\n *   $provide.value('halfOf', function(value) {\n *     return value / 2;\n *   });\n * ```\n */\n\n\n/**\n * @ngdoc method\n * @name $provide#constant\n * @description\n *\n * Register a **constant service**, such as a string, a number, an array, an object or a function,\n * with the {@link auto.$injector $injector}. Unlike {@link auto.$provide#value value} it can be\n * injected into a module configuration function (see {@link angular.Module#config}) and it cannot\n * be overridden by an Angular {@link auto.$provide#decorator decorator}.\n *\n * @param {string} name The name of the constant.\n * @param {*} value The constant value.\n * @returns {Object} registered instance\n *\n * @example\n * Here a some examples of creating constants:\n * ```js\n *   $provide.constant('SHARD_HEIGHT', 306);\n *\n *   $provide.constant('MY_COLOURS', ['red', 'blue', 'grey']);\n *\n *   $provide.constant('double', function(value) {\n *     return value * 2;\n *   });\n * ```\n */\n\n\n/**\n * @ngdoc method\n * @name $provide#decorator\n * @description\n *\n * Register a **service decorator** with the {@link auto.$injector $injector}. A service decorator\n * intercepts the creation of a service, allowing it to override or modify the behaviour of the\n * service. The object returned by the decorator may be the original service, or a new service\n * object which replaces or wraps and delegates to the original service.\n *\n * @param {string} name The name of the service to decorate.\n * @param {function()} decorator This function will be invoked when the service needs to be\n *    instantiated and should return the decorated service instance. The function is called using\n *    the {@link auto.$injector#invoke injector.invoke} method and is therefore fully injectable.\n *    Local injection arguments:\n *\n *    * `$delegate` - The original service instance, which can be monkey patched, configured,\n *      decorated or delegated to.\n *\n * @example\n * Here we decorate the {@link ng.$log $log} service to convert warnings to errors by intercepting\n * calls to {@link ng.$log#error $log.warn()}.\n * ```js\n *   $provide.decorator('$log', ['$delegate', function($delegate) {\n *     $delegate.warn = $delegate.error;\n *     return $delegate;\n *   }]);\n * ```\n */\n\n\nfunction createInjector(modulesToLoad, strictDi) {\n  strictDi = (strictDi === true);\n  var INSTANTIATING = {},\n      providerSuffix = 'Provider',\n      path = [],\n      loadedModules = new HashMap([], true),\n      providerCache = {\n        $provide: {\n            provider: supportObject(provider),\n            factory: supportObject(factory),\n            service: supportObject(service),\n            value: supportObject(value),\n            constant: supportObject(constant),\n            decorator: decorator\n          }\n      },\n      providerInjector = (providerCache.$injector =\n          createInternalInjector(providerCache, function(serviceName, caller) {\n            if (angular.isString(caller)) {\n              path.push(caller);\n            }\n            throw $injectorMinErr('unpr', \"Unknown provider: {0}\", path.join(' <- '));\n          })),\n      instanceCache = {},\n      instanceInjector = (instanceCache.$injector =\n          createInternalInjector(instanceCache, function(serviceName, caller) {\n            var provider = providerInjector.get(serviceName + providerSuffix, caller);\n            return instanceInjector.invoke(provider.$get, provider, undefined, serviceName);\n          }));\n\n\n  forEach(loadModules(modulesToLoad), function(fn) { instanceInjector.invoke(fn || noop); });\n\n  return instanceInjector;\n\n  ////////////////////////////////////\n  // $provider\n  ////////////////////////////////////\n\n  function supportObject(delegate) {\n    return function(key, value) {\n      if (isObject(key)) {\n        forEach(key, reverseParams(delegate));\n      } else {\n        return delegate(key, value);\n      }\n    };\n  }\n\n  function provider(name, provider_) {\n    assertNotHasOwnProperty(name, 'service');\n    if (isFunction(provider_) || isArray(provider_)) {\n      provider_ = providerInjector.instantiate(provider_);\n    }\n    if (!provider_.$get) {\n      throw $injectorMinErr('pget', \"Provider '{0}' must define $get factory method.\", name);\n    }\n    return providerCache[name + providerSuffix] = provider_;\n  }\n\n  function enforceReturnValue(name, factory) {\n    return function enforcedReturnValue() {\n      var result = instanceInjector.invoke(factory, this);\n      if (isUndefined(result)) {\n        throw $injectorMinErr('undef', \"Provider '{0}' must return a value from $get factory method.\", name);\n      }\n      return result;\n    };\n  }\n\n  function factory(name, factoryFn, enforce) {\n    return provider(name, {\n      $get: enforce !== false ? enforceReturnValue(name, factoryFn) : factoryFn\n    });\n  }\n\n  function service(name, constructor) {\n    return factory(name, ['$injector', function($injector) {\n      return $injector.instantiate(constructor);\n    }]);\n  }\n\n  function value(name, val) { return factory(name, valueFn(val), false); }\n\n  function constant(name, value) {\n    assertNotHasOwnProperty(name, 'constant');\n    providerCache[name] = value;\n    instanceCache[name] = value;\n  }\n\n  function decorator(serviceName, decorFn) {\n    var origProvider = providerInjector.get(serviceName + providerSuffix),\n        orig$get = origProvider.$get;\n\n    origProvider.$get = function() {\n      var origInstance = instanceInjector.invoke(orig$get, origProvider);\n      return instanceInjector.invoke(decorFn, null, {$delegate: origInstance});\n    };\n  }\n\n  ////////////////////////////////////\n  // Module Loading\n  ////////////////////////////////////\n  function loadModules(modulesToLoad) {\n    var runBlocks = [], moduleFn;\n    forEach(modulesToLoad, function(module) {\n      if (loadedModules.get(module)) return;\n      loadedModules.put(module, true);\n\n      function runInvokeQueue(queue) {\n        var i, ii;\n        for (i = 0, ii = queue.length; i < ii; i++) {\n          var invokeArgs = queue[i],\n              provider = providerInjector.get(invokeArgs[0]);\n\n          provider[invokeArgs[1]].apply(provider, invokeArgs[2]);\n        }\n      }\n\n      try {\n        if (isString(module)) {\n          moduleFn = angularModule(module);\n          runBlocks = runBlocks.concat(loadModules(moduleFn.requires)).concat(moduleFn._runBlocks);\n          runInvokeQueue(moduleFn._invokeQueue);\n          runInvokeQueue(moduleFn._configBlocks);\n        } else if (isFunction(module)) {\n            runBlocks.push(providerInjector.invoke(module));\n        } else if (isArray(module)) {\n            runBlocks.push(providerInjector.invoke(module));\n        } else {\n          assertArgFn(module, 'module');\n        }\n      } catch (e) {\n        if (isArray(module)) {\n          module = module[module.length - 1];\n        }\n        if (e.message && e.stack && e.stack.indexOf(e.message) == -1) {\n          // Safari & FF's stack traces don't contain error.message content\n          // unlike those of Chrome and IE\n          // So if stack doesn't contain message, we create a new string that contains both.\n          // Since error.stack is read-only in Safari, I'm overriding e and not e.stack here.\n          /* jshint -W022 */\n          e = e.message + '\\n' + e.stack;\n        }\n        throw $injectorMinErr('modulerr', \"Failed to instantiate module {0} due to:\\n{1}\",\n                  module, e.stack || e.message || e);\n      }\n    });\n    return runBlocks;\n  }\n\n  ////////////////////////////////////\n  // internal Injector\n  ////////////////////////////////////\n\n  function createInternalInjector(cache, factory) {\n\n    function getService(serviceName, caller) {\n      if (cache.hasOwnProperty(serviceName)) {\n        if (cache[serviceName] === INSTANTIATING) {\n          throw $injectorMinErr('cdep', 'Circular dependency found: {0}',\n                    serviceName + ' <- ' + path.join(' <- '));\n        }\n        return cache[serviceName];\n      } else {\n        try {\n          path.unshift(serviceName);\n          cache[serviceName] = INSTANTIATING;\n          return cache[serviceName] = factory(serviceName, caller);\n        } catch (err) {\n          if (cache[serviceName] === INSTANTIATING) {\n            delete cache[serviceName];\n          }\n          throw err;\n        } finally {\n          path.shift();\n        }\n      }\n    }\n\n    function invoke(fn, self, locals, serviceName) {\n      if (typeof locals === 'string') {\n        serviceName = locals;\n        locals = null;\n      }\n\n      var args = [],\n          $inject = createInjector.$$annotate(fn, strictDi, serviceName),\n          length, i,\n          key;\n\n      for (i = 0, length = $inject.length; i < length; i++) {\n        key = $inject[i];\n        if (typeof key !== 'string') {\n          throw $injectorMinErr('itkn',\n                  'Incorrect injection token! Expected service name as string, got {0}', key);\n        }\n        args.push(\n          locals && locals.hasOwnProperty(key)\n          ? locals[key]\n          : getService(key, serviceName)\n        );\n      }\n      if (isArray(fn)) {\n        fn = fn[length];\n      }\n\n      // http://jsperf.com/angularjs-invoke-apply-vs-switch\n      // #5388\n      return fn.apply(self, args);\n    }\n\n    function instantiate(Type, locals, serviceName) {\n      // Check if Type is annotated and use just the given function at n-1 as parameter\n      // e.g. someModule.factory('greeter', ['$window', function(renamed$window) {}]);\n      // Object creation: http://jsperf.com/create-constructor/2\n      var instance = Object.create((isArray(Type) ? Type[Type.length - 1] : Type).prototype || null);\n      var returnedValue = invoke(Type, instance, locals, serviceName);\n\n      return isObject(returnedValue) || isFunction(returnedValue) ? returnedValue : instance;\n    }\n\n    return {\n      invoke: invoke,\n      instantiate: instantiate,\n      get: getService,\n      annotate: createInjector.$$annotate,\n      has: function(name) {\n        return providerCache.hasOwnProperty(name + providerSuffix) || cache.hasOwnProperty(name);\n      }\n    };\n  }\n}\n\ncreateInjector.$$annotate = annotate;\n\n/**\n * @ngdoc provider\n * @name $anchorScrollProvider\n *\n * @description\n * Use `$anchorScrollProvider` to disable automatic scrolling whenever\n * {@link ng.$location#hash $location.hash()} changes.\n */\nfunction $AnchorScrollProvider() {\n\n  var autoScrollingEnabled = true;\n\n  /**\n   * @ngdoc method\n   * @name $anchorScrollProvider#disableAutoScrolling\n   *\n   * @description\n   * By default, {@link ng.$anchorScroll $anchorScroll()} will automatically detect changes to\n   * {@link ng.$location#hash $location.hash()} and scroll to the element matching the new hash.<br />\n   * Use this method to disable automatic scrolling.\n   *\n   * If automatic scrolling is disabled, one must explicitly call\n   * {@link ng.$anchorScroll $anchorScroll()} in order to scroll to the element related to the\n   * current hash.\n   */\n  this.disableAutoScrolling = function() {\n    autoScrollingEnabled = false;\n  };\n\n  /**\n   * @ngdoc service\n   * @name $anchorScroll\n   * @kind function\n   * @requires $window\n   * @requires $location\n   * @requires $rootScope\n   *\n   * @description\n   * When called, it checks the current value of {@link ng.$location#hash $location.hash()} and\n   * scrolls to the related element, according to the rules specified in the\n   * [Html5 spec](http://dev.w3.org/html5/spec/Overview.html#the-indicated-part-of-the-document).\n   *\n   * It also watches the {@link ng.$location#hash $location.hash()} and automatically scrolls to\n   * match any anchor whenever it changes. This can be disabled by calling\n   * {@link ng.$anchorScrollProvider#disableAutoScrolling $anchorScrollProvider.disableAutoScrolling()}.\n   *\n   * Additionally, you can use its {@link ng.$anchorScroll#yOffset yOffset} property to specify a\n   * vertical scroll-offset (either fixed or dynamic).\n   *\n   * @property {(number|function|jqLite)} yOffset\n   * If set, specifies a vertical scroll-offset. This is often useful when there are fixed\n   * positioned elements at the top of the page, such as navbars, headers etc.\n   *\n   * `yOffset` can be specified in various ways:\n   * - **number**: A fixed number of pixels to be used as offset.<br /><br />\n   * - **function**: A getter function called everytime `$anchorScroll()` is executed. Must return\n   *   a number representing the offset (in pixels).<br /><br />\n   * - **jqLite**: A jqLite/jQuery element to be used for specifying the offset. The distance from\n   *   the top of the page to the element's bottom will be used as offset.<br />\n   *   **Note**: The element will be taken into account only as long as its `position` is set to\n   *   `fixed`. This option is useful, when dealing with responsive navbars/headers that adjust\n   *   their height and/or positioning according to the viewport's size.\n   *\n   * <br />\n   * <div class=\"alert alert-warning\">\n   * In order for `yOffset` to work properly, scrolling should take place on the document's root and\n   * not some child element.\n   * </div>\n   *\n   * @example\n     <example module=\"anchorScrollExample\">\n       <file name=\"index.html\">\n         <div id=\"scrollArea\" ng-controller=\"ScrollController\">\n           <a ng-click=\"gotoBottom()\">Go to bottom</a>\n           <a id=\"bottom\"></a> You're at the bottom!\n         </div>\n       </file>\n       <file name=\"script.js\">\n         angular.module('anchorScrollExample', [])\n           .controller('ScrollController', ['$scope', '$location', '$anchorScroll',\n             function ($scope, $location, $anchorScroll) {\n               $scope.gotoBottom = function() {\n                 // set the location.hash to the id of\n                 // the element you wish to scroll to.\n                 $location.hash('bottom');\n\n                 // call $anchorScroll()\n                 $anchorScroll();\n               };\n             }]);\n       </file>\n       <file name=\"style.css\">\n         #scrollArea {\n           height: 280px;\n           overflow: auto;\n         }\n\n         #bottom {\n           display: block;\n           margin-top: 2000px;\n         }\n       </file>\n     </example>\n   *\n   * <hr />\n   * The example below illustrates the use of a vertical scroll-offset (specified as a fixed value).\n   * See {@link ng.$anchorScroll#yOffset $anchorScroll.yOffset} for more details.\n   *\n   * @example\n     <example module=\"anchorScrollOffsetExample\">\n       <file name=\"index.html\">\n         <div class=\"fixed-header\" ng-controller=\"headerCtrl\">\n           <a href=\"\" ng-click=\"gotoAnchor(x)\" ng-repeat=\"x in [1,2,3,4,5]\">\n             Go to anchor {{x}}\n           </a>\n         </div>\n         <div id=\"anchor{{x}}\" class=\"anchor\" ng-repeat=\"x in [1,2,3,4,5]\">\n           Anchor {{x}} of 5\n         </div>\n       </file>\n       <file name=\"script.js\">\n         angular.module('anchorScrollOffsetExample', [])\n           .run(['$anchorScroll', function($anchorScroll) {\n             $anchorScroll.yOffset = 50;   // always scroll by 50 extra pixels\n           }])\n           .controller('headerCtrl', ['$anchorScroll', '$location', '$scope',\n             function ($anchorScroll, $location, $scope) {\n               $scope.gotoAnchor = function(x) {\n                 var newHash = 'anchor' + x;\n                 if ($location.hash() !== newHash) {\n                   // set the $location.hash to `newHash` and\n                   // $anchorScroll will automatically scroll to it\n                   $location.hash('anchor' + x);\n                 } else {\n                   // call $anchorScroll() explicitly,\n                   // since $location.hash hasn't changed\n                   $anchorScroll();\n                 }\n               };\n             }\n           ]);\n       </file>\n       <file name=\"style.css\">\n         body {\n           padding-top: 50px;\n         }\n\n         .anchor {\n           border: 2px dashed DarkOrchid;\n           padding: 10px 10px 200px 10px;\n         }\n\n         .fixed-header {\n           background-color: rgba(0, 0, 0, 0.2);\n           height: 50px;\n           position: fixed;\n           top: 0; left: 0; right: 0;\n         }\n\n         .fixed-header > a {\n           display: inline-block;\n           margin: 5px 15px;\n         }\n       </file>\n     </example>\n   */\n  this.$get = ['$window', '$location', '$rootScope', function($window, $location, $rootScope) {\n    var document = $window.document;\n\n    // Helper function to get first anchor from a NodeList\n    // (using `Array#some()` instead of `angular#forEach()` since it's more performant\n    //  and working in all supported browsers.)\n    function getFirstAnchor(list) {\n      var result = null;\n      Array.prototype.some.call(list, function(element) {\n        if (nodeName_(element) === 'a') {\n          result = element;\n          return true;\n        }\n      });\n      return result;\n    }\n\n    function getYOffset() {\n\n      var offset = scroll.yOffset;\n\n      if (isFunction(offset)) {\n        offset = offset();\n      } else if (isElement(offset)) {\n        var elem = offset[0];\n        var style = $window.getComputedStyle(elem);\n        if (style.position !== 'fixed') {\n          offset = 0;\n        } else {\n          offset = elem.getBoundingClientRect().bottom;\n        }\n      } else if (!isNumber(offset)) {\n        offset = 0;\n      }\n\n      return offset;\n    }\n\n    function scrollTo(elem) {\n      if (elem) {\n        elem.scrollIntoView();\n\n        var offset = getYOffset();\n\n        if (offset) {\n          // `offset` is the number of pixels we should scroll UP in order to align `elem` properly.\n          // This is true ONLY if the call to `elem.scrollIntoView()` initially aligns `elem` at the\n          // top of the viewport.\n          //\n          // IF the number of pixels from the top of `elem` to the end of the page's content is less\n          // than the height of the viewport, then `elem.scrollIntoView()` will align the `elem` some\n          // way down the page.\n          //\n          // This is often the case for elements near the bottom of the page.\n          //\n          // In such cases we do not need to scroll the whole `offset` up, just the difference between\n          // the top of the element and the offset, which is enough to align the top of `elem` at the\n          // desired position.\n          var elemTop = elem.getBoundingClientRect().top;\n          $window.scrollBy(0, elemTop - offset);\n        }\n      } else {\n        $window.scrollTo(0, 0);\n      }\n    }\n\n    function scroll() {\n      var hash = $location.hash(), elm;\n\n      // empty hash, scroll to the top of the page\n      if (!hash) scrollTo(null);\n\n      // element with given id\n      else if ((elm = document.getElementById(hash))) scrollTo(elm);\n\n      // first anchor with given name :-D\n      else if ((elm = getFirstAnchor(document.getElementsByName(hash)))) scrollTo(elm);\n\n      // no element and hash == 'top', scroll to the top of the page\n      else if (hash === 'top') scrollTo(null);\n    }\n\n    // does not scroll when user clicks on anchor link that is currently on\n    // (no url change, no $location.hash() change), browser native does scroll\n    if (autoScrollingEnabled) {\n      $rootScope.$watch(function autoScrollWatch() {return $location.hash();},\n        function autoScrollWatchAction(newVal, oldVal) {\n          // skip the initial scroll if $location.hash is empty\n          if (newVal === oldVal && newVal === '') return;\n\n          jqLiteDocumentLoaded(function() {\n            $rootScope.$evalAsync(scroll);\n          });\n        });\n    }\n\n    return scroll;\n  }];\n}\n\nvar $animateMinErr = minErr('$animate');\n\n/**\n * @ngdoc provider\n * @name $animateProvider\n *\n * @description\n * Default implementation of $animate that doesn't perform any animations, instead just\n * synchronously performs DOM\n * updates and calls done() callbacks.\n *\n * In order to enable animations the ngAnimate module has to be loaded.\n *\n * To see the functional implementation check out src/ngAnimate/animate.js\n */\nvar $AnimateProvider = ['$provide', function($provide) {\n\n\n  this.$$selectors = {};\n\n\n  /**\n   * @ngdoc method\n   * @name $animateProvider#register\n   *\n   * @description\n   * Registers a new injectable animation factory function. The factory function produces the\n   * animation object which contains callback functions for each event that is expected to be\n   * animated.\n   *\n   *   * `eventFn`: `function(Element, doneFunction)` The element to animate, the `doneFunction`\n   *   must be called once the element animation is complete. If a function is returned then the\n   *   animation service will use this function to cancel the animation whenever a cancel event is\n   *   triggered.\n   *\n   *\n   * ```js\n   *   return {\n     *     eventFn : function(element, done) {\n     *       //code to run the animation\n     *       //once complete, then run done()\n     *       return function cancellationFunction() {\n     *         //code to cancel the animation\n     *       }\n     *     }\n     *   }\n   * ```\n   *\n   * @param {string} name The name of the animation.\n   * @param {Function} factory The factory function that will be executed to return the animation\n   *                           object.\n   */\n  this.register = function(name, factory) {\n    var key = name + '-animation';\n    if (name && name.charAt(0) != '.') throw $animateMinErr('notcsel',\n        \"Expecting class selector starting with '.' got '{0}'.\", name);\n    this.$$selectors[name.substr(1)] = key;\n    $provide.factory(key, factory);\n  };\n\n  /**\n   * @ngdoc method\n   * @name $animateProvider#classNameFilter\n   *\n   * @description\n   * Sets and/or returns the CSS class regular expression that is checked when performing\n   * an animation. Upon bootstrap the classNameFilter value is not set at all and will\n   * therefore enable $animate to attempt to perform an animation on any element.\n   * When setting the classNameFilter value, animations will only be performed on elements\n   * that successfully match the filter expression. This in turn can boost performance\n   * for low-powered devices as well as applications containing a lot of structural operations.\n   * @param {RegExp=} expression The className expression which will be checked against all animations\n   * @return {RegExp} The current CSS className expression value. If null then there is no expression value\n   */\n  this.classNameFilter = function(expression) {\n    if (arguments.length === 1) {\n      this.$$classNameFilter = (expression instanceof RegExp) ? expression : null;\n    }\n    return this.$$classNameFilter;\n  };\n\n  this.$get = ['$$q', '$$asyncCallback', '$rootScope', function($$q, $$asyncCallback, $rootScope) {\n\n    var currentDefer;\n\n    function runAnimationPostDigest(fn) {\n      var cancelFn, defer = $$q.defer();\n      defer.promise.$$cancelFn = function ngAnimateMaybeCancel() {\n        cancelFn && cancelFn();\n      };\n\n      $rootScope.$$postDigest(function ngAnimatePostDigest() {\n        cancelFn = fn(function ngAnimateNotifyComplete() {\n          defer.resolve();\n        });\n      });\n\n      return defer.promise;\n    }\n\n    function resolveElementClasses(element, classes) {\n      var toAdd = [], toRemove = [];\n\n      var hasClasses = createMap();\n      forEach((element.attr('class') || '').split(/\\s+/), function(className) {\n        hasClasses[className] = true;\n      });\n\n      forEach(classes, function(status, className) {\n        var hasClass = hasClasses[className];\n\n        // If the most recent class manipulation (via $animate) was to remove the class, and the\n        // element currently has the class, the class is scheduled for removal. Otherwise, if\n        // the most recent class manipulation (via $animate) was to add the class, and the\n        // element does not currently have the class, the class is scheduled to be added.\n        if (status === false && hasClass) {\n          toRemove.push(className);\n        } else if (status === true && !hasClass) {\n          toAdd.push(className);\n        }\n      });\n\n      return (toAdd.length + toRemove.length) > 0 &&\n        [toAdd.length ? toAdd : null, toRemove.length ? toRemove : null];\n    }\n\n    function cachedClassManipulation(cache, classes, op) {\n      for (var i=0, ii = classes.length; i < ii; ++i) {\n        var className = classes[i];\n        cache[className] = op;\n      }\n    }\n\n    function asyncPromise() {\n      // only serve one instance of a promise in order to save CPU cycles\n      if (!currentDefer) {\n        currentDefer = $$q.defer();\n        $$asyncCallback(function() {\n          currentDefer.resolve();\n          currentDefer = null;\n        });\n      }\n      return currentDefer.promise;\n    }\n\n    function applyStyles(element, options) {\n      if (angular.isObject(options)) {\n        var styles = extend(options.from || {}, options.to || {});\n        element.css(styles);\n      }\n    }\n\n    /**\n     *\n     * @ngdoc service\n     * @name $animate\n     * @description The $animate service provides rudimentary DOM manipulation functions to\n     * insert, remove and move elements within the DOM, as well as adding and removing classes.\n     * This service is the core service used by the ngAnimate $animator service which provides\n     * high-level animation hooks for CSS and JavaScript.\n     *\n     * $animate is available in the AngularJS core, however, the ngAnimate module must be included\n     * to enable full out animation support. Otherwise, $animate will only perform simple DOM\n     * manipulation operations.\n     *\n     * To learn more about enabling animation support, click here to visit the {@link ngAnimate\n     * ngAnimate module page} as well as the {@link ngAnimate.$animate ngAnimate $animate service\n     * page}.\n     */\n    return {\n      animate: function(element, from, to) {\n        applyStyles(element, { from: from, to: to });\n        return asyncPromise();\n      },\n\n      /**\n       *\n       * @ngdoc method\n       * @name $animate#enter\n       * @kind function\n       * @description Inserts the element into the DOM either after the `after` element or\n       * as the first child within the `parent` element. When the function is called a promise\n       * is returned that will be resolved at a later time.\n       * @param {DOMElement} element the element which will be inserted into the DOM\n       * @param {DOMElement} parent the parent element which will append the element as\n       *   a child (if the after element is not present)\n       * @param {DOMElement} after the sibling element which will append the element\n       *   after itself\n       * @param {object=} options an optional collection of styles that will be applied to the element.\n       * @return {Promise} the animation callback promise\n       */\n      enter: function(element, parent, after, options) {\n        applyStyles(element, options);\n        after ? after.after(element)\n              : parent.prepend(element);\n        return asyncPromise();\n      },\n\n      /**\n       *\n       * @ngdoc method\n       * @name $animate#leave\n       * @kind function\n       * @description Removes the element from the DOM. When the function is called a promise\n       * is returned that will be resolved at a later time.\n       * @param {DOMElement} element the element which will be removed from the DOM\n       * @param {object=} options an optional collection of options that will be applied to the element.\n       * @return {Promise} the animation callback promise\n       */\n      leave: function(element, options) {\n        element.remove();\n        return asyncPromise();\n      },\n\n      /**\n       *\n       * @ngdoc method\n       * @name $animate#move\n       * @kind function\n       * @description Moves the position of the provided element within the DOM to be placed\n       * either after the `after` element or inside of the `parent` element. When the function\n       * is called a promise is returned that will be resolved at a later time.\n       *\n       * @param {DOMElement} element the element which will be moved around within the\n       *   DOM\n       * @param {DOMElement} parent the parent element where the element will be\n       *   inserted into (if the after element is not present)\n       * @param {DOMElement} after the sibling element where the element will be\n       *   positioned next to\n       * @param {object=} options an optional collection of options that will be applied to the element.\n       * @return {Promise} the animation callback promise\n       */\n      move: function(element, parent, after, options) {\n        // Do not remove element before insert. Removing will cause data associated with the\n        // element to be dropped. Insert will implicitly do the remove.\n        return this.enter(element, parent, after, options);\n      },\n\n      /**\n       *\n       * @ngdoc method\n       * @name $animate#addClass\n       * @kind function\n       * @description Adds the provided className CSS class value to the provided element.\n       * When the function is called a promise is returned that will be resolved at a later time.\n       * @param {DOMElement} element the element which will have the className value\n       *   added to it\n       * @param {string} className the CSS class which will be added to the element\n       * @param {object=} options an optional collection of options that will be applied to the element.\n       * @return {Promise} the animation callback promise\n       */\n      addClass: function(element, className, options) {\n        return this.setClass(element, className, [], options);\n      },\n\n      $$addClassImmediately: function(element, className, options) {\n        element = jqLite(element);\n        className = !isString(className)\n                        ? (isArray(className) ? className.join(' ') : '')\n                        : className;\n        forEach(element, function(element) {\n          jqLiteAddClass(element, className);\n        });\n        applyStyles(element, options);\n        return asyncPromise();\n      },\n\n      /**\n       *\n       * @ngdoc method\n       * @name $animate#removeClass\n       * @kind function\n       * @description Removes the provided className CSS class value from the provided element.\n       * When the function is called a promise is returned that will be resolved at a later time.\n       * @param {DOMElement} element the element which will have the className value\n       *   removed from it\n       * @param {string} className the CSS class which will be removed from the element\n       * @param {object=} options an optional collection of options that will be applied to the element.\n       * @return {Promise} the animation callback promise\n       */\n      removeClass: function(element, className, options) {\n        return this.setClass(element, [], className, options);\n      },\n\n      $$removeClassImmediately: function(element, className, options) {\n        element = jqLite(element);\n        className = !isString(className)\n                        ? (isArray(className) ? className.join(' ') : '')\n                        : className;\n        forEach(element, function(element) {\n          jqLiteRemoveClass(element, className);\n        });\n        applyStyles(element, options);\n        return asyncPromise();\n      },\n\n      /**\n       *\n       * @ngdoc method\n       * @name $animate#setClass\n       * @kind function\n       * @description Adds and/or removes the given CSS classes to and from the element.\n       * When the function is called a promise is returned that will be resolved at a later time.\n       * @param {DOMElement} element the element which will have its CSS classes changed\n       *   removed from it\n       * @param {string} add the CSS classes which will be added to the element\n       * @param {string} remove the CSS class which will be removed from the element\n       * @param {object=} options an optional collection of options that will be applied to the element.\n       * @return {Promise} the animation callback promise\n       */\n      setClass: function(element, add, remove, options) {\n        var self = this;\n        var STORAGE_KEY = '$$animateClasses';\n        var createdCache = false;\n        element = jqLite(element);\n\n        var cache = element.data(STORAGE_KEY);\n        if (!cache) {\n          cache = {\n            classes: {},\n            options: options\n          };\n          createdCache = true;\n        } else if (options && cache.options) {\n          cache.options = angular.extend(cache.options || {}, options);\n        }\n\n        var classes = cache.classes;\n\n        add = isArray(add) ? add : add.split(' ');\n        remove = isArray(remove) ? remove : remove.split(' ');\n        cachedClassManipulation(classes, add, true);\n        cachedClassManipulation(classes, remove, false);\n\n        if (createdCache) {\n          cache.promise = runAnimationPostDigest(function(done) {\n            var cache = element.data(STORAGE_KEY);\n            element.removeData(STORAGE_KEY);\n\n            // in the event that the element is removed before postDigest\n            // is run then the cache will be undefined and there will be\n            // no need anymore to add or remove and of the element classes\n            if (cache) {\n              var classes = resolveElementClasses(element, cache.classes);\n              if (classes) {\n                self.$$setClassImmediately(element, classes[0], classes[1], cache.options);\n              }\n            }\n\n            done();\n          });\n          element.data(STORAGE_KEY, cache);\n        }\n\n        return cache.promise;\n      },\n\n      $$setClassImmediately: function(element, add, remove, options) {\n        add && this.$$addClassImmediately(element, add);\n        remove && this.$$removeClassImmediately(element, remove);\n        applyStyles(element, options);\n        return asyncPromise();\n      },\n\n      enabled: noop,\n      cancel: noop\n    };\n  }];\n}];\n\nfunction $$AsyncCallbackProvider() {\n  this.$get = ['$$rAF', '$timeout', function($$rAF, $timeout) {\n    return $$rAF.supported\n      ? function(fn) { return $$rAF(fn); }\n      : function(fn) {\n        return $timeout(fn, 0, false);\n      };\n  }];\n}\n\n/* global stripHash: true */\n\n/**\n * ! This is a private undocumented service !\n *\n * @name $browser\n * @requires $log\n * @description\n * This object has two goals:\n *\n * - hide all the global state in the browser caused by the window object\n * - abstract away all the browser specific features and inconsistencies\n *\n * For tests we provide {@link ngMock.$browser mock implementation} of the `$browser`\n * service, which can be used for convenient testing of the application without the interaction with\n * the real browser apis.\n */\n/**\n * @param {object} window The global window object.\n * @param {object} document jQuery wrapped document.\n * @param {object} $log window.console or an object with the same interface.\n * @param {object} $sniffer $sniffer service\n */\nfunction Browser(window, document, $log, $sniffer) {\n  var self = this,\n      rawDocument = document[0],\n      location = window.location,\n      history = window.history,\n      setTimeout = window.setTimeout,\n      clearTimeout = window.clearTimeout,\n      pendingDeferIds = {};\n\n  self.isMock = false;\n\n  var outstandingRequestCount = 0;\n  var outstandingRequestCallbacks = [];\n\n  // TODO(vojta): remove this temporary api\n  self.$$completeOutstandingRequest = completeOutstandingRequest;\n  self.$$incOutstandingRequestCount = function() { outstandingRequestCount++; };\n\n  /**\n   * Executes the `fn` function(supports currying) and decrements the `outstandingRequestCallbacks`\n   * counter. If the counter reaches 0, all the `outstandingRequestCallbacks` are executed.\n   */\n  function completeOutstandingRequest(fn) {\n    try {\n      fn.apply(null, sliceArgs(arguments, 1));\n    } finally {\n      outstandingRequestCount--;\n      if (outstandingRequestCount === 0) {\n        while (outstandingRequestCallbacks.length) {\n          try {\n            outstandingRequestCallbacks.pop()();\n          } catch (e) {\n            $log.error(e);\n          }\n        }\n      }\n    }\n  }\n\n  function getHash(url) {\n    var index = url.indexOf('#');\n    return index === -1 ? '' : url.substr(index + 1);\n  }\n\n  /**\n   * @private\n   * Note: this method is used only by scenario runner\n   * TODO(vojta): prefix this method with $$ ?\n   * @param {function()} callback Function that will be called when no outstanding request\n   */\n  self.notifyWhenNoOutstandingRequests = function(callback) {\n    // force browser to execute all pollFns - this is needed so that cookies and other pollers fire\n    // at some deterministic time in respect to the test runner's actions. Leaving things up to the\n    // regular poller would result in flaky tests.\n    forEach(pollFns, function(pollFn) { pollFn(); });\n\n    if (outstandingRequestCount === 0) {\n      callback();\n    } else {\n      outstandingRequestCallbacks.push(callback);\n    }\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Poll Watcher API\n  //////////////////////////////////////////////////////////////\n  var pollFns = [],\n      pollTimeout;\n\n  /**\n   * @name $browser#addPollFn\n   *\n   * @param {function()} fn Poll function to add\n   *\n   * @description\n   * Adds a function to the list of functions that poller periodically executes,\n   * and starts polling if not started yet.\n   *\n   * @returns {function()} the added function\n   */\n  self.addPollFn = function(fn) {\n    if (isUndefined(pollTimeout)) startPoller(100, setTimeout);\n    pollFns.push(fn);\n    return fn;\n  };\n\n  /**\n   * @param {number} interval How often should browser call poll functions (ms)\n   * @param {function()} setTimeout Reference to a real or fake `setTimeout` function.\n   *\n   * @description\n   * Configures the poller to run in the specified intervals, using the specified\n   * setTimeout fn and kicks it off.\n   */\n  function startPoller(interval, setTimeout) {\n    (function check() {\n      forEach(pollFns, function(pollFn) { pollFn(); });\n      pollTimeout = setTimeout(check, interval);\n    })();\n  }\n\n  //////////////////////////////////////////////////////////////\n  // URL API\n  //////////////////////////////////////////////////////////////\n\n  var cachedState, lastHistoryState,\n      lastBrowserUrl = location.href,\n      baseElement = document.find('base'),\n      reloadLocation = null;\n\n  cacheState();\n  lastHistoryState = cachedState;\n\n  /**\n   * @name $browser#url\n   *\n   * @description\n   * GETTER:\n   * Without any argument, this method just returns current value of location.href.\n   *\n   * SETTER:\n   * With at least one argument, this method sets url to new value.\n   * If html5 history api supported, pushState/replaceState is used, otherwise\n   * location.href/location.replace is used.\n   * Returns its own instance to allow chaining\n   *\n   * NOTE: this api is intended for use only by the $location service. Please use the\n   * {@link ng.$location $location service} to change url.\n   *\n   * @param {string} url New url (when used as setter)\n   * @param {boolean=} replace Should new url replace current history record?\n   * @param {object=} state object to use with pushState/replaceState\n   */\n  self.url = function(url, replace, state) {\n    // In modern browsers `history.state` is `null` by default; treating it separately\n    // from `undefined` would cause `$browser.url('/foo')` to change `history.state`\n    // to undefined via `pushState`. Instead, let's change `undefined` to `null` here.\n    if (isUndefined(state)) {\n      state = null;\n    }\n\n    // Android Browser BFCache causes location, history reference to become stale.\n    if (location !== window.location) location = window.location;\n    if (history !== window.history) history = window.history;\n\n    // setter\n    if (url) {\n      var sameState = lastHistoryState === state;\n\n      // Don't change anything if previous and current URLs and states match. This also prevents\n      // IE<10 from getting into redirect loop when in LocationHashbangInHtml5Url mode.\n      // See https://github.com/angular/angular.js/commit/ffb2701\n      if (lastBrowserUrl === url && (!$sniffer.history || sameState)) {\n        return self;\n      }\n      var sameBase = lastBrowserUrl && stripHash(lastBrowserUrl) === stripHash(url);\n      lastBrowserUrl = url;\n      lastHistoryState = state;\n      // Don't use history API if only the hash changed\n      // due to a bug in IE10/IE11 which leads\n      // to not firing a `hashchange` nor `popstate` event\n      // in some cases (see #9143).\n      if ($sniffer.history && (!sameBase || !sameState)) {\n        history[replace ? 'replaceState' : 'pushState'](state, '', url);\n        cacheState();\n        // Do the assignment again so that those two variables are referentially identical.\n        lastHistoryState = cachedState;\n      } else {\n        if (!sameBase) {\n          reloadLocation = url;\n        }\n        if (replace) {\n          location.replace(url);\n        } else if (!sameBase) {\n          location.href = url;\n        } else {\n          location.hash = getHash(url);\n        }\n      }\n      return self;\n    // getter\n    } else {\n      // - reloadLocation is needed as browsers don't allow to read out\n      //   the new location.href if a reload happened.\n      // - the replacement is a workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=407172\n      return reloadLocation || location.href.replace(/%27/g,\"'\");\n    }\n  };\n\n  /**\n   * @name $browser#state\n   *\n   * @description\n   * This method is a getter.\n   *\n   * Return history.state or null if history.state is undefined.\n   *\n   * @returns {object} state\n   */\n  self.state = function() {\n    return cachedState;\n  };\n\n  var urlChangeListeners = [],\n      urlChangeInit = false;\n\n  function cacheStateAndFireUrlChange() {\n    cacheState();\n    fireUrlChange();\n  }\n\n  // This variable should be used *only* inside the cacheState function.\n  var lastCachedState = null;\n  function cacheState() {\n    // This should be the only place in $browser where `history.state` is read.\n    cachedState = window.history.state;\n    cachedState = isUndefined(cachedState) ? null : cachedState;\n\n    // Prevent callbacks fo fire twice if both hashchange & popstate were fired.\n    if (equals(cachedState, lastCachedState)) {\n      cachedState = lastCachedState;\n    }\n    lastCachedState = cachedState;\n  }\n\n  function fireUrlChange() {\n    if (lastBrowserUrl === self.url() && lastHistoryState === cachedState) {\n      return;\n    }\n\n    lastBrowserUrl = self.url();\n    lastHistoryState = cachedState;\n    forEach(urlChangeListeners, function(listener) {\n      listener(self.url(), cachedState);\n    });\n  }\n\n  /**\n   * @name $browser#onUrlChange\n   *\n   * @description\n   * Register callback function that will be called, when url changes.\n   *\n   * It's only called when the url is changed from outside of angular:\n   * - user types different url into address bar\n   * - user clicks on history (forward/back) button\n   * - user clicks on a link\n   *\n   * It's not called when url is changed by $browser.url() method\n   *\n   * The listener gets called with new url as parameter.\n   *\n   * NOTE: this api is intended for use only by the $location service. Please use the\n   * {@link ng.$location $location service} to monitor url changes in angular apps.\n   *\n   * @param {function(string)} listener Listener function to be called when url changes.\n   * @return {function(string)} Returns the registered listener fn - handy if the fn is anonymous.\n   */\n  self.onUrlChange = function(callback) {\n    // TODO(vojta): refactor to use node's syntax for events\n    if (!urlChangeInit) {\n      // We listen on both (hashchange/popstate) when available, as some browsers (e.g. Opera)\n      // don't fire popstate when user change the address bar and don't fire hashchange when url\n      // changed by push/replaceState\n\n      // html5 history api - popstate event\n      if ($sniffer.history) jqLite(window).on('popstate', cacheStateAndFireUrlChange);\n      // hashchange event\n      jqLite(window).on('hashchange', cacheStateAndFireUrlChange);\n\n      urlChangeInit = true;\n    }\n\n    urlChangeListeners.push(callback);\n    return callback;\n  };\n\n  /**\n   * Checks whether the url has changed outside of Angular.\n   * Needs to be exported to be able to check for changes that have been done in sync,\n   * as hashchange/popstate events fire in async.\n   */\n  self.$$checkUrlChange = fireUrlChange;\n\n  //////////////////////////////////////////////////////////////\n  // Misc API\n  //////////////////////////////////////////////////////////////\n\n  /**\n   * @name $browser#baseHref\n   *\n   * @description\n   * Returns current <base href>\n   * (always relative - without domain)\n   *\n   * @returns {string} The current base href\n   */\n  self.baseHref = function() {\n    var href = baseElement.attr('href');\n    return href ? href.replace(/^(https?\\:)?\\/\\/[^\\/]*/, '') : '';\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Cookies API\n  //////////////////////////////////////////////////////////////\n  var lastCookies = {};\n  var lastCookieString = '';\n  var cookiePath = self.baseHref();\n\n  function safeDecodeURIComponent(str) {\n    try {\n      return decodeURIComponent(str);\n    } catch (e) {\n      return str;\n    }\n  }\n\n  /**\n   * @name $browser#cookies\n   *\n   * @param {string=} name Cookie name\n   * @param {string=} value Cookie value\n   *\n   * @description\n   * The cookies method provides a 'private' low level access to browser cookies.\n   * It is not meant to be used directly, use the $cookie service instead.\n   *\n   * The return values vary depending on the arguments that the method was called with as follows:\n   *\n   * - cookies() -> hash of all cookies, this is NOT a copy of the internal state, so do not modify\n   *   it\n   * - cookies(name, value) -> set name to value, if value is undefined delete the cookie\n   * - cookies(name) -> the same as (name, undefined) == DELETES (no one calls it right now that\n   *   way)\n   *\n   * @returns {Object} Hash of all cookies (if called without any parameter)\n   */\n  self.cookies = function(name, value) {\n    var cookieLength, cookieArray, cookie, i, index;\n\n    if (name) {\n      if (value === undefined) {\n        rawDocument.cookie = encodeURIComponent(name) + \"=;path=\" + cookiePath +\n                                \";expires=Thu, 01 Jan 1970 00:00:00 GMT\";\n      } else {\n        if (isString(value)) {\n          cookieLength = (rawDocument.cookie = encodeURIComponent(name) + '=' + encodeURIComponent(value) +\n                                ';path=' + cookiePath).length + 1;\n\n          // per http://www.ietf.org/rfc/rfc2109.txt browser must allow at minimum:\n          // - 300 cookies\n          // - 20 cookies per unique domain\n          // - 4096 bytes per cookie\n          if (cookieLength > 4096) {\n            $log.warn(\"Cookie '\" + name +\n              \"' possibly not set or overflowed because it was too large (\" +\n              cookieLength + \" > 4096 bytes)!\");\n          }\n        }\n      }\n    } else {\n      if (rawDocument.cookie !== lastCookieString) {\n        lastCookieString = rawDocument.cookie;\n        cookieArray = lastCookieString.split(\"; \");\n        lastCookies = {};\n\n        for (i = 0; i < cookieArray.length; i++) {\n          cookie = cookieArray[i];\n          index = cookie.indexOf('=');\n          if (index > 0) { //ignore nameless cookies\n            name = safeDecodeURIComponent(cookie.substring(0, index));\n            // the first value that is seen for a cookie is the most\n            // specific one.  values for the same cookie name that\n            // follow are for less specific paths.\n            if (lastCookies[name] === undefined) {\n              lastCookies[name] = safeDecodeURIComponent(cookie.substring(index + 1));\n            }\n          }\n        }\n      }\n      return lastCookies;\n    }\n  };\n\n\n  /**\n   * @name $browser#defer\n   * @param {function()} fn A function, who's execution should be deferred.\n   * @param {number=} [delay=0] of milliseconds to defer the function execution.\n   * @returns {*} DeferId that can be used to cancel the task via `$browser.defer.cancel()`.\n   *\n   * @description\n   * Executes a fn asynchronously via `setTimeout(fn, delay)`.\n   *\n   * Unlike when calling `setTimeout` directly, in test this function is mocked and instead of using\n   * `setTimeout` in tests, the fns are queued in an array, which can be programmatically flushed\n   * via `$browser.defer.flush()`.\n   *\n   */\n  self.defer = function(fn, delay) {\n    var timeoutId;\n    outstandingRequestCount++;\n    timeoutId = setTimeout(function() {\n      delete pendingDeferIds[timeoutId];\n      completeOutstandingRequest(fn);\n    }, delay || 0);\n    pendingDeferIds[timeoutId] = true;\n    return timeoutId;\n  };\n\n\n  /**\n   * @name $browser#defer.cancel\n   *\n   * @description\n   * Cancels a deferred task identified with `deferId`.\n   *\n   * @param {*} deferId Token returned by the `$browser.defer` function.\n   * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfully\n   *                    canceled.\n   */\n  self.defer.cancel = function(deferId) {\n    if (pendingDeferIds[deferId]) {\n      delete pendingDeferIds[deferId];\n      clearTimeout(deferId);\n      completeOutstandingRequest(noop);\n      return true;\n    }\n    return false;\n  };\n\n}\n\nfunction $BrowserProvider() {\n  this.$get = ['$window', '$log', '$sniffer', '$document',\n      function($window, $log, $sniffer, $document) {\n        return new Browser($window, $document, $log, $sniffer);\n      }];\n}\n\n/**\n * @ngdoc service\n * @name $cacheFactory\n *\n * @description\n * Factory that constructs {@link $cacheFactory.Cache Cache} objects and gives access to\n * them.\n *\n * ```js\n *\n *  var cache = $cacheFactory('cacheId');\n *  expect($cacheFactory.get('cacheId')).toBe(cache);\n *  expect($cacheFactory.get('noSuchCacheId')).not.toBeDefined();\n *\n *  cache.put(\"key\", \"value\");\n *  cache.put(\"another key\", \"another value\");\n *\n *  // We've specified no options on creation\n *  expect(cache.info()).toEqual({id: 'cacheId', size: 2});\n *\n * ```\n *\n *\n * @param {string} cacheId Name or id of the newly created cache.\n * @param {object=} options Options object that specifies the cache behavior. Properties:\n *\n *   - `{number=}` `capacity` — turns the cache into LRU cache.\n *\n * @returns {object} Newly created cache object with the following set of methods:\n *\n * - `{object}` `info()` — Returns id, size, and options of cache.\n * - `{{*}}` `put({string} key, {*} value)` — Puts a new key-value pair into the cache and returns\n *   it.\n * - `{{*}}` `get({string} key)` — Returns cached value for `key` or undefined for cache miss.\n * - `{void}` `remove({string} key)` — Removes a key-value pair from the cache.\n * - `{void}` `removeAll()` — Removes all cached values.\n * - `{void}` `destroy()` — Removes references to this cache from $cacheFactory.\n *\n * @example\n   <example module=\"cacheExampleApp\">\n     <file name=\"index.html\">\n       <div ng-controller=\"CacheController\">\n         <input ng-model=\"newCacheKey\" placeholder=\"Key\">\n         <input ng-model=\"newCacheValue\" placeholder=\"Value\">\n         <button ng-click=\"put(newCacheKey, newCacheValue)\">Cache</button>\n\n         <p ng-if=\"keys.length\">Cached Values</p>\n         <div ng-repeat=\"key in keys\">\n           <span ng-bind=\"key\"></span>\n           <span>: </span>\n           <b ng-bind=\"cache.get(key)\"></b>\n         </div>\n\n         <p>Cache Info</p>\n         <div ng-repeat=\"(key, value) in cache.info()\">\n           <span ng-bind=\"key\"></span>\n           <span>: </span>\n           <b ng-bind=\"value\"></b>\n         </div>\n       </div>\n     </file>\n     <file name=\"script.js\">\n       angular.module('cacheExampleApp', []).\n         controller('CacheController', ['$scope', '$cacheFactory', function($scope, $cacheFactory) {\n           $scope.keys = [];\n           $scope.cache = $cacheFactory('cacheId');\n           $scope.put = function(key, value) {\n             if ($scope.cache.get(key) === undefined) {\n               $scope.keys.push(key);\n             }\n             $scope.cache.put(key, value === undefined ? null : value);\n           };\n         }]);\n     </file>\n     <file name=\"style.css\">\n       p {\n         margin: 10px 0 3px;\n       }\n     </file>\n   </example>\n */\nfunction $CacheFactoryProvider() {\n\n  this.$get = function() {\n    var caches = {};\n\n    function cacheFactory(cacheId, options) {\n      if (cacheId in caches) {\n        throw minErr('$cacheFactory')('iid', \"CacheId '{0}' is already taken!\", cacheId);\n      }\n\n      var size = 0,\n          stats = extend({}, options, {id: cacheId}),\n          data = {},\n          capacity = (options && options.capacity) || Number.MAX_VALUE,\n          lruHash = {},\n          freshEnd = null,\n          staleEnd = null;\n\n      /**\n       * @ngdoc type\n       * @name $cacheFactory.Cache\n       *\n       * @description\n       * A cache object used to store and retrieve data, primarily used by\n       * {@link $http $http} and the {@link ng.directive:script script} directive to cache\n       * templates and other data.\n       *\n       * ```js\n       *  angular.module('superCache')\n       *    .factory('superCache', ['$cacheFactory', function($cacheFactory) {\n       *      return $cacheFactory('super-cache');\n       *    }]);\n       * ```\n       *\n       * Example test:\n       *\n       * ```js\n       *  it('should behave like a cache', inject(function(superCache) {\n       *    superCache.put('key', 'value');\n       *    superCache.put('another key', 'another value');\n       *\n       *    expect(superCache.info()).toEqual({\n       *      id: 'super-cache',\n       *      size: 2\n       *    });\n       *\n       *    superCache.remove('another key');\n       *    expect(superCache.get('another key')).toBeUndefined();\n       *\n       *    superCache.removeAll();\n       *    expect(superCache.info()).toEqual({\n       *      id: 'super-cache',\n       *      size: 0\n       *    });\n       *  }));\n       * ```\n       */\n      return caches[cacheId] = {\n\n        /**\n         * @ngdoc method\n         * @name $cacheFactory.Cache#put\n         * @kind function\n         *\n         * @description\n         * Inserts a named entry into the {@link $cacheFactory.Cache Cache} object to be\n         * retrieved later, and incrementing the size of the cache if the key was not already\n         * present in the cache. If behaving like an LRU cache, it will also remove stale\n         * entries from the set.\n         *\n         * It will not insert undefined values into the cache.\n         *\n         * @param {string} key the key under which the cached data is stored.\n         * @param {*} value the value to store alongside the key. If it is undefined, the key\n         *    will not be stored.\n         * @returns {*} the value stored.\n         */\n        put: function(key, value) {\n          if (capacity < Number.MAX_VALUE) {\n            var lruEntry = lruHash[key] || (lruHash[key] = {key: key});\n\n            refresh(lruEntry);\n          }\n\n          if (isUndefined(value)) return;\n          if (!(key in data)) size++;\n          data[key] = value;\n\n          if (size > capacity) {\n            this.remove(staleEnd.key);\n          }\n\n          return value;\n        },\n\n        /**\n         * @ngdoc method\n         * @name $cacheFactory.Cache#get\n         * @kind function\n         *\n         * @description\n         * Retrieves named data stored in the {@link $cacheFactory.Cache Cache} object.\n         *\n         * @param {string} key the key of the data to be retrieved\n         * @returns {*} the value stored.\n         */\n        get: function(key) {\n          if (capacity < Number.MAX_VALUE) {\n            var lruEntry = lruHash[key];\n\n            if (!lruEntry) return;\n\n            refresh(lruEntry);\n          }\n\n          return data[key];\n        },\n\n\n        /**\n         * @ngdoc method\n         * @name $cacheFactory.Cache#remove\n         * @kind function\n         *\n         * @description\n         * Removes an entry from the {@link $cacheFactory.Cache Cache} object.\n         *\n         * @param {string} key the key of the entry to be removed\n         */\n        remove: function(key) {\n          if (capacity < Number.MAX_VALUE) {\n            var lruEntry = lruHash[key];\n\n            if (!lruEntry) return;\n\n            if (lruEntry == freshEnd) freshEnd = lruEntry.p;\n            if (lruEntry == staleEnd) staleEnd = lruEntry.n;\n            link(lruEntry.n,lruEntry.p);\n\n            delete lruHash[key];\n          }\n\n          delete data[key];\n          size--;\n        },\n\n\n        /**\n         * @ngdoc method\n         * @name $cacheFactory.Cache#removeAll\n         * @kind function\n         *\n         * @description\n         * Clears the cache object of any entries.\n         */\n        removeAll: function() {\n          data = {};\n          size = 0;\n          lruHash = {};\n          freshEnd = staleEnd = null;\n        },\n\n\n        /**\n         * @ngdoc method\n         * @name $cacheFactory.Cache#destroy\n         * @kind function\n         *\n         * @description\n         * Destroys the {@link $cacheFactory.Cache Cache} object entirely,\n         * removing it from the {@link $cacheFactory $cacheFactory} set.\n         */\n        destroy: function() {\n          data = null;\n          stats = null;\n          lruHash = null;\n          delete caches[cacheId];\n        },\n\n\n        /**\n         * @ngdoc method\n         * @name $cacheFactory.Cache#info\n         * @kind function\n         *\n         * @description\n         * Retrieve information regarding a particular {@link $cacheFactory.Cache Cache}.\n         *\n         * @returns {object} an object with the following properties:\n         *   <ul>\n         *     <li>**id**: the id of the cache instance</li>\n         *     <li>**size**: the number of entries kept in the cache instance</li>\n         *     <li>**...**: any additional properties from the options object when creating the\n         *       cache.</li>\n         *   </ul>\n         */\n        info: function() {\n          return extend({}, stats, {size: size});\n        }\n      };\n\n\n      /**\n       * makes the `entry` the freshEnd of the LRU linked list\n       */\n      function refresh(entry) {\n        if (entry != freshEnd) {\n          if (!staleEnd) {\n            staleEnd = entry;\n          } else if (staleEnd == entry) {\n            staleEnd = entry.n;\n          }\n\n          link(entry.n, entry.p);\n          link(entry, freshEnd);\n          freshEnd = entry;\n          freshEnd.n = null;\n        }\n      }\n\n\n      /**\n       * bidirectionally links two entries of the LRU linked list\n       */\n      function link(nextEntry, prevEntry) {\n        if (nextEntry != prevEntry) {\n          if (nextEntry) nextEntry.p = prevEntry; //p stands for previous, 'prev' didn't minify\n          if (prevEntry) prevEntry.n = nextEntry; //n stands for next, 'next' didn't minify\n        }\n      }\n    }\n\n\n  /**\n   * @ngdoc method\n   * @name $cacheFactory#info\n   *\n   * @description\n   * Get information about all the caches that have been created\n   *\n   * @returns {Object} - key-value map of `cacheId` to the result of calling `cache#info`\n   */\n    cacheFactory.info = function() {\n      var info = {};\n      forEach(caches, function(cache, cacheId) {\n        info[cacheId] = cache.info();\n      });\n      return info;\n    };\n\n\n  /**\n   * @ngdoc method\n   * @name $cacheFactory#get\n   *\n   * @description\n   * Get access to a cache object by the `cacheId` used when it was created.\n   *\n   * @param {string} cacheId Name or id of a cache to access.\n   * @returns {object} Cache object identified by the cacheId or undefined if no such cache.\n   */\n    cacheFactory.get = function(cacheId) {\n      return caches[cacheId];\n    };\n\n\n    return cacheFactory;\n  };\n}\n\n/**\n * @ngdoc service\n * @name $templateCache\n *\n * @description\n * The first time a template is used, it is loaded in the template cache for quick retrieval. You\n * can load templates directly into the cache in a `script` tag, or by consuming the\n * `$templateCache` service directly.\n *\n * Adding via the `script` tag:\n *\n * ```html\n *   <script type=\"text/ng-template\" id=\"templateId.html\">\n *     <p>This is the content of the template</p>\n *   </script>\n * ```\n *\n * **Note:** the `script` tag containing the template does not need to be included in the `head` of\n * the document, but it must be a descendent of the {@link ng.$rootElement $rootElement} (IE,\n * element with ng-app attribute), otherwise the template will be ignored.\n *\n * Adding via the $templateCache service:\n *\n * ```js\n * var myApp = angular.module('myApp', []);\n * myApp.run(function($templateCache) {\n *   $templateCache.put('templateId.html', 'This is the content of the template');\n * });\n * ```\n *\n * To retrieve the template later, simply use it in your HTML:\n * ```html\n * <div ng-include=\" 'templateId.html' \"></div>\n * ```\n *\n * or get it via Javascript:\n * ```js\n * $templateCache.get('templateId.html')\n * ```\n *\n * See {@link ng.$cacheFactory $cacheFactory}.\n *\n */\nfunction $TemplateCacheProvider() {\n  this.$get = ['$cacheFactory', function($cacheFactory) {\n    return $cacheFactory('templates');\n  }];\n}\n\n/* ! VARIABLE/FUNCTION NAMING CONVENTIONS THAT APPLY TO THIS FILE!\n *\n * DOM-related variables:\n *\n * - \"node\" - DOM Node\n * - \"element\" - DOM Element or Node\n * - \"$node\" or \"$element\" - jqLite-wrapped node or element\n *\n *\n * Compiler related stuff:\n *\n * - \"linkFn\" - linking fn of a single directive\n * - \"nodeLinkFn\" - function that aggregates all linking fns for a particular node\n * - \"childLinkFn\" -  function that aggregates all linking fns for child nodes of a particular node\n * - \"compositeLinkFn\" - function that aggregates all linking fns for a compilation root (nodeList)\n */\n\n\n/**\n * @ngdoc service\n * @name $compile\n * @kind function\n *\n * @description\n * Compiles an HTML string or DOM into a template and produces a template function, which\n * can then be used to link {@link ng.$rootScope.Scope `scope`} and the template together.\n *\n * The compilation is a process of walking the DOM tree and matching DOM elements to\n * {@link ng.$compileProvider#directive directives}.\n *\n * <div class=\"alert alert-warning\">\n * **Note:** This document is an in-depth reference of all directive options.\n * For a gentle introduction to directives with examples of common use cases,\n * see the {@link guide/directive directive guide}.\n * </div>\n *\n * ## Comprehensive Directive API\n *\n * There are many different options for a directive.\n *\n * The difference resides in the return value of the factory function.\n * You can either return a \"Directive Definition Object\" (see below) that defines the directive properties,\n * or just the `postLink` function (all other properties will have the default values).\n *\n * <div class=\"alert alert-success\">\n * **Best Practice:** It's recommended to use the \"directive definition object\" form.\n * </div>\n *\n * Here's an example directive declared with a Directive Definition Object:\n *\n * ```js\n *   var myModule = angular.module(...);\n *\n *   myModule.directive('directiveName', function factory(injectables) {\n *     var directiveDefinitionObject = {\n *       priority: 0,\n *       template: '<div></div>', // or // function(tElement, tAttrs) { ... },\n *       // or\n *       // templateUrl: 'directive.html', // or // function(tElement, tAttrs) { ... },\n *       transclude: false,\n *       restrict: 'A',\n *       templateNamespace: 'html',\n *       scope: false,\n *       controller: function($scope, $element, $attrs, $transclude, otherInjectables) { ... },\n *       controllerAs: 'stringAlias',\n *       require: 'siblingDirectiveName', // or // ['^parentDirectiveName', '?optionalDirectiveName', '?^optionalParent'],\n *       compile: function compile(tElement, tAttrs, transclude) {\n *         return {\n *           pre: function preLink(scope, iElement, iAttrs, controller) { ... },\n *           post: function postLink(scope, iElement, iAttrs, controller) { ... }\n *         }\n *         // or\n *         // return function postLink( ... ) { ... }\n *       },\n *       // or\n *       // link: {\n *       //  pre: function preLink(scope, iElement, iAttrs, controller) { ... },\n *       //  post: function postLink(scope, iElement, iAttrs, controller) { ... }\n *       // }\n *       // or\n *       // link: function postLink( ... ) { ... }\n *     };\n *     return directiveDefinitionObject;\n *   });\n * ```\n *\n * <div class=\"alert alert-warning\">\n * **Note:** Any unspecified options will use the default value. You can see the default values below.\n * </div>\n *\n * Therefore the above can be simplified as:\n *\n * ```js\n *   var myModule = angular.module(...);\n *\n *   myModule.directive('directiveName', function factory(injectables) {\n *     var directiveDefinitionObject = {\n *       link: function postLink(scope, iElement, iAttrs) { ... }\n *     };\n *     return directiveDefinitionObject;\n *     // or\n *     // return function postLink(scope, iElement, iAttrs) { ... }\n *   });\n * ```\n *\n *\n *\n * ### Directive Definition Object\n *\n * The directive definition object provides instructions to the {@link ng.$compile\n * compiler}. The attributes are:\n *\n * #### `multiElement`\n * When this property is set to true, the HTML compiler will collect DOM nodes between\n * nodes with the attributes `directive-name-start` and `directive-name-end`, and group them\n * together as the directive elements. It is recommended that this feature be used on directives\n * which are not strictly behavioural (such as {@link ngClick}), and which\n * do not manipulate or replace child nodes (such as {@link ngInclude}).\n *\n * #### `priority`\n * When there are multiple directives defined on a single DOM element, sometimes it\n * is necessary to specify the order in which the directives are applied. The `priority` is used\n * to sort the directives before their `compile` functions get called. Priority is defined as a\n * number. Directives with greater numerical `priority` are compiled first. Pre-link functions\n * are also run in priority order, but post-link functions are run in reverse order. The order\n * of directives with the same priority is undefined. The default priority is `0`.\n *\n * #### `terminal`\n * If set to true then the current `priority` will be the last set of directives\n * which will execute (any directives at the current priority will still execute\n * as the order of execution on same `priority` is undefined). Note that expressions\n * and other directives used in the directive's template will also be excluded from execution.\n *\n * #### `scope`\n * **If set to `true`,** then a new scope will be created for this directive. If multiple directives on the\n * same element request a new scope, only one new scope is created. The new scope rule does not\n * apply for the root of the template since the root of the template always gets a new scope.\n *\n * **If set to `{}` (object hash),** then a new \"isolate\" scope is created. The 'isolate' scope differs from\n * normal scope in that it does not prototypically inherit from the parent scope. This is useful\n * when creating reusable components, which should not accidentally read or modify data in the\n * parent scope.\n *\n * The 'isolate' scope takes an object hash which defines a set of local scope properties\n * derived from the parent scope. These local properties are useful for aliasing values for\n * templates. Locals definition is a hash of local scope property to its source:\n *\n * * `@` or `@attr` - bind a local scope property to the value of DOM attribute. The result is\n *   always a string since DOM attributes are strings. If no `attr` name is specified  then the\n *   attribute name is assumed to be the same as the local name.\n *   Given `<widget my-attr=\"hello {{name}}\">` and widget definition\n *   of `scope: { localName:'@myAttr' }`, then widget scope property `localName` will reflect\n *   the interpolated value of `hello {{name}}`. As the `name` attribute changes so will the\n *   `localName` property on the widget scope. The `name` is read from the parent scope (not\n *   component scope).\n *\n * * `=` or `=attr` - set up bi-directional binding between a local scope property and the\n *   parent scope property of name defined via the value of the `attr` attribute. If no `attr`\n *   name is specified then the attribute name is assumed to be the same as the local name.\n *   Given `<widget my-attr=\"parentModel\">` and widget definition of\n *   `scope: { localModel:'=myAttr' }`, then widget scope property `localModel` will reflect the\n *   value of `parentModel` on the parent scope. Any changes to `parentModel` will be reflected\n *   in `localModel` and any changes in `localModel` will reflect in `parentModel`. If the parent\n *   scope property doesn't exist, it will throw a NON_ASSIGNABLE_MODEL_EXPRESSION exception. You\n *   can avoid this behavior using `=?` or `=?attr` in order to flag the property as optional. If\n *   you want to shallow watch for changes (i.e. $watchCollection instead of $watch) you can use\n *   `=*` or `=*attr` (`=*?` or `=*?attr` if the property is optional).\n *\n * * `&` or `&attr` - provides a way to execute an expression in the context of the parent scope.\n *   If no `attr` name is specified then the attribute name is assumed to be the same as the\n *   local name. Given `<widget my-attr=\"count = count + value\">` and widget definition of\n *   `scope: { localFn:'&myAttr' }`, then isolate scope property `localFn` will point to\n *   a function wrapper for the `count = count + value` expression. Often it's desirable to\n *   pass data from the isolated scope via an expression to the parent scope, this can be\n *   done by passing a map of local variable names and values into the expression wrapper fn.\n *   For example, if the expression is `increment(amount)` then we can specify the amount value\n *   by calling the `localFn` as `localFn({amount: 22})`.\n *\n *\n * #### `bindToController`\n * When an isolate scope is used for a component (see above), and `controllerAs` is used, `bindToController: true` will\n * allow a component to have its properties bound to the controller, rather than to scope. When the controller\n * is instantiated, the initial values of the isolate scope bindings are already available.\n *\n * #### `controller`\n * Controller constructor function. The controller is instantiated before the\n * pre-linking phase and it is shared with other directives (see\n * `require` attribute). This allows the directives to communicate with each other and augment\n * each other's behavior. The controller is injectable (and supports bracket notation) with the following locals:\n *\n * * `$scope` - Current scope associated with the element\n * * `$element` - Current element\n * * `$attrs` - Current attributes object for the element\n * * `$transclude` - A transclude linking function pre-bound to the correct transclusion scope:\n *   `function([scope], cloneLinkingFn, futureParentElement)`.\n *    * `scope`: optional argument to override the scope.\n *    * `cloneLinkingFn`: optional argument to create clones of the original transcluded content.\n *    * `futureParentElement`:\n *        * defines the parent to which the `cloneLinkingFn` will add the cloned elements.\n *        * default: `$element.parent()` resp. `$element` for `transclude:'element'` resp. `transclude:true`.\n *        * only needed for transcludes that are allowed to contain non html elements (e.g. SVG elements)\n *          and when the `cloneLinkinFn` is passed,\n *          as those elements need to created and cloned in a special way when they are defined outside their\n *          usual containers (e.g. like `<svg>`).\n *        * See also the `directive.templateNamespace` property.\n *\n *\n * #### `require`\n * Require another directive and inject its controller as the fourth argument to the linking function. The\n * `require` takes a string name (or array of strings) of the directive(s) to pass in. If an array is used, the\n * injected argument will be an array in corresponding order. If no such directive can be\n * found, or if the directive does not have a controller, then an error is raised. The name can be prefixed with:\n *\n * * (no prefix) - Locate the required controller on the current element. Throw an error if not found.\n * * `?` - Attempt to locate the required controller or pass `null` to the `link` fn if not found.\n * * `^` - Locate the required controller by searching the element and its parents. Throw an error if not found.\n * * `^^` - Locate the required controller by searching the element's parents. Throw an error if not found.\n * * `?^` - Attempt to locate the required controller by searching the element and its parents or pass\n *   `null` to the `link` fn if not found.\n * * `?^^` - Attempt to locate the required controller by searching the element's parents, or pass\n *   `null` to the `link` fn if not found.\n *\n *\n * #### `controllerAs`\n * Controller alias at the directive scope. An alias for the controller so it\n * can be referenced at the directive template. The directive needs to define a scope for this\n * configuration to be used. Useful in the case when directive is used as component.\n *\n *\n * #### `restrict`\n * String of subset of `EACM` which restricts the directive to a specific directive\n * declaration style. If omitted, the defaults (elements and attributes) are used.\n *\n * * `E` - Element name (default): `<my-directive></my-directive>`\n * * `A` - Attribute (default): `<div my-directive=\"exp\"></div>`\n * * `C` - Class: `<div class=\"my-directive: exp;\"></div>`\n * * `M` - Comment: `<!-- directive: my-directive exp -->`\n *\n *\n * #### `templateNamespace`\n * String representing the document type used by the markup in the template.\n * AngularJS needs this information as those elements need to be created and cloned\n * in a special way when they are defined outside their usual containers like `<svg>` and `<math>`.\n *\n * * `html` - All root nodes in the template are HTML. Root nodes may also be\n *   top-level elements such as `<svg>` or `<math>`.\n * * `svg` - The root nodes in the template are SVG elements (excluding `<math>`).\n * * `math` - The root nodes in the template are MathML elements (excluding `<svg>`).\n *\n * If no `templateNamespace` is specified, then the namespace is considered to be `html`.\n *\n * #### `template`\n * HTML markup that may:\n * * Replace the contents of the directive's element (default).\n * * Replace the directive's element itself (if `replace` is true - DEPRECATED).\n * * Wrap the contents of the directive's element (if `transclude` is true).\n *\n * Value may be:\n *\n * * A string. For example `<div red-on-hover>{{delete_str}}</div>`.\n * * A function which takes two arguments `tElement` and `tAttrs` (described in the `compile`\n *   function api below) and returns a string value.\n *\n *\n * #### `templateUrl`\n * This is similar to `template` but the template is loaded from the specified URL, asynchronously.\n *\n * Because template loading is asynchronous the compiler will suspend compilation of directives on that element\n * for later when the template has been resolved.  In the meantime it will continue to compile and link\n * sibling and parent elements as though this element had not contained any directives.\n *\n * The compiler does not suspend the entire compilation to wait for templates to be loaded because this\n * would result in the whole app \"stalling\" until all templates are loaded asynchronously - even in the\n * case when only one deeply nested directive has `templateUrl`.\n *\n * Template loading is asynchronous even if the template has been preloaded into the {@link $templateCache}\n *\n * You can specify `templateUrl` as a string representing the URL or as a function which takes two\n * arguments `tElement` and `tAttrs` (described in the `compile` function api below) and returns\n * a string value representing the url.  In either case, the template URL is passed through {@link\n * $sce#getTrustedResourceUrl $sce.getTrustedResourceUrl}.\n *\n *\n * #### `replace` ([*DEPRECATED*!], will be removed in next major release - i.e. v2.0)\n * specify what the template should replace. Defaults to `false`.\n *\n * * `true` - the template will replace the directive's element.\n * * `false` - the template will replace the contents of the directive's element.\n *\n * The replacement process migrates all of the attributes / classes from the old element to the new\n * one. See the {@link guide/directive#template-expanding-directive\n * Directives Guide} for an example.\n *\n * There are very few scenarios where element replacement is required for the application function,\n * the main one being reusable custom components that are used within SVG contexts\n * (because SVG doesn't work with custom elements in the DOM tree).\n *\n * #### `transclude`\n * Extract the contents of the element where the directive appears and make it available to the directive.\n * The contents are compiled and provided to the directive as a **transclusion function**. See the\n * {@link $compile#transclusion Transclusion} section below.\n *\n * There are two kinds of transclusion depending upon whether you want to transclude just the contents of the\n * directive's element or the entire element:\n *\n * * `true` - transclude the content (i.e. the child nodes) of the directive's element.\n * * `'element'` - transclude the whole of the directive's element including any directives on this\n *   element that defined at a lower priority than this directive. When used, the `template`\n *   property is ignored.\n *\n *\n * #### `compile`\n *\n * ```js\n *   function compile(tElement, tAttrs, transclude) { ... }\n * ```\n *\n * The compile function deals with transforming the template DOM. Since most directives do not do\n * template transformation, it is not used often. The compile function takes the following arguments:\n *\n *   * `tElement` - template element - The element where the directive has been declared. It is\n *     safe to do template transformation on the element and child elements only.\n *\n *   * `tAttrs` - template attributes - Normalized list of attributes declared on this element shared\n *     between all directive compile functions.\n *\n *   * `transclude` -  [*DEPRECATED*!] A transclude linking function: `function(scope, cloneLinkingFn)`\n *\n * <div class=\"alert alert-warning\">\n * **Note:** The template instance and the link instance may be different objects if the template has\n * been cloned. For this reason it is **not** safe to do anything other than DOM transformations that\n * apply to all cloned DOM nodes within the compile function. Specifically, DOM listener registration\n * should be done in a linking function rather than in a compile function.\n * </div>\n\n * <div class=\"alert alert-warning\">\n * **Note:** The compile function cannot handle directives that recursively use themselves in their\n * own templates or compile functions. Compiling these directives results in an infinite loop and a\n * stack overflow errors.\n *\n * This can be avoided by manually using $compile in the postLink function to imperatively compile\n * a directive's template instead of relying on automatic template compilation via `template` or\n * `templateUrl` declaration or manual compilation inside the compile function.\n * </div>\n *\n * <div class=\"alert alert-error\">\n * **Note:** The `transclude` function that is passed to the compile function is deprecated, as it\n *   e.g. does not know about the right outer scope. Please use the transclude function that is passed\n *   to the link function instead.\n * </div>\n\n * A compile function can have a return value which can be either a function or an object.\n *\n * * returning a (post-link) function - is equivalent to registering the linking function via the\n *   `link` property of the config object when the compile function is empty.\n *\n * * returning an object with function(s) registered via `pre` and `post` properties - allows you to\n *   control when a linking function should be called during the linking phase. See info about\n *   pre-linking and post-linking functions below.\n *\n *\n * #### `link`\n * This property is used only if the `compile` property is not defined.\n *\n * ```js\n *   function link(scope, iElement, iAttrs, controller, transcludeFn) { ... }\n * ```\n *\n * The link function is responsible for registering DOM listeners as well as updating the DOM. It is\n * executed after the template has been cloned. This is where most of the directive logic will be\n * put.\n *\n *   * `scope` - {@link ng.$rootScope.Scope Scope} - The scope to be used by the\n *     directive for registering {@link ng.$rootScope.Scope#$watch watches}.\n *\n *   * `iElement` - instance element - The element where the directive is to be used. It is safe to\n *     manipulate the children of the element only in `postLink` function since the children have\n *     already been linked.\n *\n *   * `iAttrs` - instance attributes - Normalized list of attributes declared on this element shared\n *     between all directive linking functions.\n *\n *   * `controller` - a controller instance - A controller instance if at least one directive on the\n *     element defines a controller. The controller is shared among all the directives, which allows\n *     the directives to use the controllers as a communication channel.\n *\n *   * `transcludeFn` - A transclude linking function pre-bound to the correct transclusion scope.\n *     This is the same as the `$transclude`\n *     parameter of directive controllers, see there for details.\n *     `function([scope], cloneLinkingFn, futureParentElement)`.\n *\n * #### Pre-linking function\n *\n * Executed before the child elements are linked. Not safe to do DOM transformation since the\n * compiler linking function will fail to locate the correct elements for linking.\n *\n * #### Post-linking function\n *\n * Executed after the child elements are linked.\n *\n * Note that child elements that contain `templateUrl` directives will not have been compiled\n * and linked since they are waiting for their template to load asynchronously and their own\n * compilation and linking has been suspended until that occurs.\n *\n * It is safe to do DOM transformation in the post-linking function on elements that are not waiting\n * for their async templates to be resolved.\n *\n *\n * ### Transclusion\n *\n * Transclusion is the process of extracting a collection of DOM element from one part of the DOM and\n * copying them to another part of the DOM, while maintaining their connection to the original AngularJS\n * scope from where they were taken.\n *\n * Transclusion is used (often with {@link ngTransclude}) to insert the\n * original contents of a directive's element into a specified place in the template of the directive.\n * The benefit of transclusion, over simply moving the DOM elements manually, is that the transcluded\n * content has access to the properties on the scope from which it was taken, even if the directive\n * has isolated scope.\n * See the {@link guide/directive#creating-a-directive-that-wraps-other-elements Directives Guide}.\n *\n * This makes it possible for the widget to have private state for its template, while the transcluded\n * content has access to its originating scope.\n *\n * <div class=\"alert alert-warning\">\n * **Note:** When testing an element transclude directive you must not place the directive at the root of the\n * DOM fragment that is being compiled. See {@link guide/unit-testing#testing-transclusion-directives\n * Testing Transclusion Directives}.\n * </div>\n *\n * #### Transclusion Functions\n *\n * When a directive requests transclusion, the compiler extracts its contents and provides a **transclusion\n * function** to the directive's `link` function and `controller`. This transclusion function is a special\n * **linking function** that will return the compiled contents linked to a new transclusion scope.\n *\n * <div class=\"alert alert-info\">\n * If you are just using {@link ngTransclude} then you don't need to worry about this function, since\n * ngTransclude will deal with it for us.\n * </div>\n *\n * If you want to manually control the insertion and removal of the transcluded content in your directive\n * then you must use this transclude function. When you call a transclude function it returns a a jqLite/JQuery\n * object that contains the compiled DOM, which is linked to the correct transclusion scope.\n *\n * When you call a transclusion function you can pass in a **clone attach function**. This function accepts\n * two parameters, `function(clone, scope) { ... }`, where the `clone` is a fresh compiled copy of your transcluded\n * content and the `scope` is the newly created transclusion scope, to which the clone is bound.\n *\n * <div class=\"alert alert-info\">\n * **Best Practice**: Always provide a `cloneFn` (clone attach function) when you call a translude function\n * since you then get a fresh clone of the original DOM and also have access to the new transclusion scope.\n * </div>\n *\n * It is normal practice to attach your transcluded content (`clone`) to the DOM inside your **clone\n * attach function**:\n *\n * ```js\n * var transcludedContent, transclusionScope;\n *\n * $transclude(function(clone, scope) {\n *   element.append(clone);\n *   transcludedContent = clone;\n *   transclusionScope = scope;\n * });\n * ```\n *\n * Later, if you want to remove the transcluded content from your DOM then you should also destroy the\n * associated transclusion scope:\n *\n * ```js\n * transcludedContent.remove();\n * transclusionScope.$destroy();\n * ```\n *\n * <div class=\"alert alert-info\">\n * **Best Practice**: if you intend to add and remove transcluded content manually in your directive\n * (by calling the transclude function to get the DOM and and calling `element.remove()` to remove it),\n * then you are also responsible for calling `$destroy` on the transclusion scope.\n * </div>\n *\n * The built-in DOM manipulation directives, such as {@link ngIf}, {@link ngSwitch} and {@link ngRepeat}\n * automatically destroy their transluded clones as necessary so you do not need to worry about this if\n * you are simply using {@link ngTransclude} to inject the transclusion into your directive.\n *\n *\n * #### Transclusion Scopes\n *\n * When you call a transclude function it returns a DOM fragment that is pre-bound to a **transclusion\n * scope**. This scope is special, in that it is a child of the directive's scope (and so gets destroyed\n * when the directive's scope gets destroyed) but it inherits the properties of the scope from which it\n * was taken.\n *\n * For example consider a directive that uses transclusion and isolated scope. The DOM hierarchy might look\n * like this:\n *\n * ```html\n * <div ng-app>\n *   <div isolate>\n *     <div transclusion>\n *     </div>\n *   </div>\n * </div>\n * ```\n *\n * The `$parent` scope hierarchy will look like this:\n *\n * ```\n * - $rootScope\n *   - isolate\n *     - transclusion\n * ```\n *\n * but the scopes will inherit prototypically from different scopes to their `$parent`.\n *\n * ```\n * - $rootScope\n *   - transclusion\n * - isolate\n * ```\n *\n *\n * ### Attributes\n *\n * The {@link ng.$compile.directive.Attributes Attributes} object - passed as a parameter in the\n * `link()` or `compile()` functions. It has a variety of uses.\n *\n * accessing *Normalized attribute names:*\n * Directives like 'ngBind' can be expressed in many ways: 'ng:bind', `data-ng-bind`, or 'x-ng-bind'.\n * the attributes object allows for normalized access to\n *   the attributes.\n *\n * * *Directive inter-communication:* All directives share the same instance of the attributes\n *   object which allows the directives to use the attributes object as inter directive\n *   communication.\n *\n * * *Supports interpolation:* Interpolation attributes are assigned to the attribute object\n *   allowing other directives to read the interpolated value.\n *\n * * *Observing interpolated attributes:* Use `$observe` to observe the value changes of attributes\n *   that contain interpolation (e.g. `src=\"{{bar}}\"`). Not only is this very efficient but it's also\n *   the only way to easily get the actual value because during the linking phase the interpolation\n *   hasn't been evaluated yet and so the value is at this time set to `undefined`.\n *\n * ```js\n * function linkingFn(scope, elm, attrs, ctrl) {\n *   // get the attribute value\n *   console.log(attrs.ngModel);\n *\n *   // change the attribute\n *   attrs.$set('ngModel', 'new value');\n *\n *   // observe changes to interpolated attribute\n *   attrs.$observe('ngModel', function(value) {\n *     console.log('ngModel has changed value to ' + value);\n *   });\n * }\n * ```\n *\n * ## Example\n *\n * <div class=\"alert alert-warning\">\n * **Note**: Typically directives are registered with `module.directive`. The example below is\n * to illustrate how `$compile` works.\n * </div>\n *\n <example module=\"compileExample\">\n   <file name=\"index.html\">\n    <script>\n      angular.module('compileExample', [], function($compileProvider) {\n        // configure new 'compile' directive by passing a directive\n        // factory function. The factory function injects the '$compile'\n        $compileProvider.directive('compile', function($compile) {\n          // directive factory creates a link function\n          return function(scope, element, attrs) {\n            scope.$watch(\n              function(scope) {\n                 // watch the 'compile' expression for changes\n                return scope.$eval(attrs.compile);\n              },\n              function(value) {\n                // when the 'compile' expression changes\n                // assign it into the current DOM\n                element.html(value);\n\n                // compile the new DOM and link it to the current\n                // scope.\n                // NOTE: we only compile .childNodes so that\n                // we don't get into infinite loop compiling ourselves\n                $compile(element.contents())(scope);\n              }\n            );\n          };\n        });\n      })\n      .controller('GreeterController', ['$scope', function($scope) {\n        $scope.name = 'Angular';\n        $scope.html = 'Hello {{name}}';\n      }]);\n    </script>\n    <div ng-controller=\"GreeterController\">\n      <input ng-model=\"name\"> <br>\n      <textarea ng-model=\"html\"></textarea> <br>\n      <div compile=\"html\"></div>\n    </div>\n   </file>\n   <file name=\"protractor.js\" type=\"protractor\">\n     it('should auto compile', function() {\n       var textarea = $('textarea');\n       var output = $('div[compile]');\n       // The initial state reads 'Hello Angular'.\n       expect(output.getText()).toBe('Hello Angular');\n       textarea.clear();\n       textarea.sendKeys('{{name}}!');\n       expect(output.getText()).toBe('Angular!');\n     });\n   </file>\n </example>\n\n *\n *\n * @param {string|DOMElement} element Element or HTML string to compile into a template function.\n * @param {function(angular.Scope, cloneAttachFn=)} transclude function available to directives - DEPRECATED.\n *\n * <div class=\"alert alert-error\">\n * **Note:** Passing a `transclude` function to the $compile function is deprecated, as it\n *   e.g. will not use the right outer scope. Please pass the transclude function as a\n *   `parentBoundTranscludeFn` to the link function instead.\n * </div>\n *\n * @param {number} maxPriority only apply directives lower than given priority (Only effects the\n *                 root element(s), not their children)\n * @returns {function(scope, cloneAttachFn=, options=)} a link function which is used to bind template\n * (a DOM element/tree) to a scope. Where:\n *\n *  * `scope` - A {@link ng.$rootScope.Scope Scope} to bind to.\n *  * `cloneAttachFn` - If `cloneAttachFn` is provided, then the link function will clone the\n *  `template` and call the `cloneAttachFn` function allowing the caller to attach the\n *  cloned elements to the DOM document at the appropriate place. The `cloneAttachFn` is\n *  called as: <br> `cloneAttachFn(clonedElement, scope)` where:\n *\n *      * `clonedElement` - is a clone of the original `element` passed into the compiler.\n *      * `scope` - is the current scope with which the linking function is working with.\n *\n *  * `options` - An optional object hash with linking options. If `options` is provided, then the following\n *  keys may be used to control linking behavior:\n *\n *      * `parentBoundTranscludeFn` - the transclude function made available to\n *        directives; if given, it will be passed through to the link functions of\n *        directives found in `element` during compilation.\n *      * `transcludeControllers` - an object hash with keys that map controller names\n *        to controller instances; if given, it will make the controllers\n *        available to directives.\n *      * `futureParentElement` - defines the parent to which the `cloneAttachFn` will add\n *        the cloned elements; only needed for transcludes that are allowed to contain non html\n *        elements (e.g. SVG elements). See also the directive.controller property.\n *\n * Calling the linking function returns the element of the template. It is either the original\n * element passed in, or the clone of the element if the `cloneAttachFn` is provided.\n *\n * After linking the view is not updated until after a call to $digest which typically is done by\n * Angular automatically.\n *\n * If you need access to the bound view, there are two ways to do it:\n *\n * - If you are not asking the linking function to clone the template, create the DOM element(s)\n *   before you send them to the compiler and keep this reference around.\n *   ```js\n *     var element = $compile('<p>{{total}}</p>')(scope);\n *   ```\n *\n * - if on the other hand, you need the element to be cloned, the view reference from the original\n *   example would not point to the clone, but rather to the original template that was cloned. In\n *   this case, you can access the clone via the cloneAttachFn:\n *   ```js\n *     var templateElement = angular.element('<p>{{total}}</p>'),\n *         scope = ....;\n *\n *     var clonedElement = $compile(templateElement)(scope, function(clonedElement, scope) {\n *       //attach the clone to DOM document at the right place\n *     });\n *\n *     //now we have reference to the cloned DOM via `clonedElement`\n *   ```\n *\n *\n * For information on how the compiler works, see the\n * {@link guide/compiler Angular HTML Compiler} section of the Developer Guide.\n */\n\nvar $compileMinErr = minErr('$compile');\n\n/**\n * @ngdoc provider\n * @name $compileProvider\n *\n * @description\n */\n$CompileProvider.$inject = ['$provide', '$$sanitizeUriProvider'];\nfunction $CompileProvider($provide, $$sanitizeUriProvider) {\n  var hasDirectives = {},\n      Suffix = 'Directive',\n      COMMENT_DIRECTIVE_REGEXP = /^\\s*directive\\:\\s*([\\w\\-]+)\\s+(.*)$/,\n      CLASS_DIRECTIVE_REGEXP = /(([\\w\\-]+)(?:\\:([^;]+))?;?)/,\n      ALL_OR_NOTHING_ATTRS = makeMap('ngSrc,ngSrcset,src,srcset'),\n      REQUIRE_PREFIX_REGEXP = /^(?:(\\^\\^?)?(\\?)?(\\^\\^?)?)?/;\n\n  // Ref: http://developers.whatwg.org/webappapis.html#event-handler-idl-attributes\n  // The assumption is that future DOM event attribute names will begin with\n  // 'on' and be composed of only English letters.\n  var EVENT_HANDLER_ATTR_REGEXP = /^(on[a-z]+|formaction)$/;\n\n  function parseIsolateBindings(scope, directiveName) {\n    var LOCAL_REGEXP = /^\\s*([@&]|=(\\*?))(\\??)\\s*(\\w*)\\s*$/;\n\n    var bindings = {};\n\n    forEach(scope, function(definition, scopeName) {\n      var match = definition.match(LOCAL_REGEXP);\n\n      if (!match) {\n        throw $compileMinErr('iscp',\n            \"Invalid isolate scope definition for directive '{0}'.\" +\n            \" Definition: {... {1}: '{2}' ...}\",\n            directiveName, scopeName, definition);\n      }\n\n      bindings[scopeName] = {\n        mode: match[1][0],\n        collection: match[2] === '*',\n        optional: match[3] === '?',\n        attrName: match[4] || scopeName\n      };\n    });\n\n    return bindings;\n  }\n\n  /**\n   * @ngdoc method\n   * @name $compileProvider#directive\n   * @kind function\n   *\n   * @description\n   * Register a new directive with the compiler.\n   *\n   * @param {string|Object} name Name of the directive in camel-case (i.e. <code>ngBind</code> which\n   *    will match as <code>ng-bind</code>), or an object map of directives where the keys are the\n   *    names and the values are the factories.\n   * @param {Function|Array} directiveFactory An injectable directive factory function. See\n   *    {@link guide/directive} for more info.\n   * @returns {ng.$compileProvider} Self for chaining.\n   */\n   this.directive = function registerDirective(name, directiveFactory) {\n    assertNotHasOwnProperty(name, 'directive');\n    if (isString(name)) {\n      assertArg(directiveFactory, 'directiveFactory');\n      if (!hasDirectives.hasOwnProperty(name)) {\n        hasDirectives[name] = [];\n        $provide.factory(name + Suffix, ['$injector', '$exceptionHandler',\n          function($injector, $exceptionHandler) {\n            var directives = [];\n            forEach(hasDirectives[name], function(directiveFactory, index) {\n              try {\n                var directive = $injector.invoke(directiveFactory);\n                if (isFunction(directive)) {\n                  directive = { compile: valueFn(directive) };\n                } else if (!directive.compile && directive.link) {\n                  directive.compile = valueFn(directive.link);\n                }\n                directive.priority = directive.priority || 0;\n                directive.index = index;\n                directive.name = directive.name || name;\n                directive.require = directive.require || (directive.controller && directive.name);\n                directive.restrict = directive.restrict || 'EA';\n                if (isObject(directive.scope)) {\n                  directive.$$isolateBindings = parseIsolateBindings(directive.scope, directive.name);\n                }\n                directives.push(directive);\n              } catch (e) {\n                $exceptionHandler(e);\n              }\n            });\n            return directives;\n          }]);\n      }\n      hasDirectives[name].push(directiveFactory);\n    } else {\n      forEach(name, reverseParams(registerDirective));\n    }\n    return this;\n  };\n\n\n  /**\n   * @ngdoc method\n   * @name $compileProvider#aHrefSanitizationWhitelist\n   * @kind function\n   *\n   * @description\n   * Retrieves or overrides the default regular expression that is used for whitelisting of safe\n   * urls during a[href] sanitization.\n   *\n   * The sanitization is a security measure aimed at preventing XSS attacks via html links.\n   *\n   * Any url about to be assigned to a[href] via data-binding is first normalized and turned into\n   * an absolute url. Afterwards, the url is matched against the `aHrefSanitizationWhitelist`\n   * regular expression. If a match is found, the original url is written into the dom. Otherwise,\n   * the absolute url is prefixed with `'unsafe:'` string and only then is it written into the DOM.\n   *\n   * @param {RegExp=} regexp New regexp to whitelist urls with.\n   * @returns {RegExp|ng.$compileProvider} Current RegExp if called without value or self for\n   *    chaining otherwise.\n   */\n  this.aHrefSanitizationWhitelist = function(regexp) {\n    if (isDefined(regexp)) {\n      $$sanitizeUriProvider.aHrefSanitizationWhitelist(regexp);\n      return this;\n    } else {\n      return $$sanitizeUriProvider.aHrefSanitizationWhitelist();\n    }\n  };\n\n\n  /**\n   * @ngdoc method\n   * @name $compileProvider#imgSrcSanitizationWhitelist\n   * @kind function\n   *\n   * @description\n   * Retrieves or overrides the default regular expression that is used for whitelisting of safe\n   * urls during img[src] sanitization.\n   *\n   * The sanitization is a security measure aimed at prevent XSS attacks via html links.\n   *\n   * Any url about to be assigned to img[src] via data-binding is first normalized and turned into\n   * an absolute url. Afterwards, the url is matched against the `imgSrcSanitizationWhitelist`\n   * regular expression. If a match is found, the original url is written into the dom. Otherwise,\n   * the absolute url is prefixed with `'unsafe:'` string and only then is it written into the DOM.\n   *\n   * @param {RegExp=} regexp New regexp to whitelist urls with.\n   * @returns {RegExp|ng.$compileProvider} Current RegExp if called without value or self for\n   *    chaining otherwise.\n   */\n  this.imgSrcSanitizationWhitelist = function(regexp) {\n    if (isDefined(regexp)) {\n      $$sanitizeUriProvider.imgSrcSanitizationWhitelist(regexp);\n      return this;\n    } else {\n      return $$sanitizeUriProvider.imgSrcSanitizationWhitelist();\n    }\n  };\n\n  /**\n   * @ngdoc method\n   * @name  $compileProvider#debugInfoEnabled\n   *\n   * @param {boolean=} enabled update the debugInfoEnabled state if provided, otherwise just return the\n   * current debugInfoEnabled state\n   * @returns {*} current value if used as getter or itself (chaining) if used as setter\n   *\n   * @kind function\n   *\n   * @description\n   * Call this method to enable/disable various debug runtime information in the compiler such as adding\n   * binding information and a reference to the current scope on to DOM elements.\n   * If enabled, the compiler will add the following to DOM elements that have been bound to the scope\n   * * `ng-binding` CSS class\n   * * `$binding` data property containing an array of the binding expressions\n   *\n   * You may want to disable this in production for a significant performance boost. See\n   * {@link guide/production#disabling-debug-data Disabling Debug Data} for more.\n   *\n   * The default value is true.\n   */\n  var debugInfoEnabled = true;\n  this.debugInfoEnabled = function(enabled) {\n    if (isDefined(enabled)) {\n      debugInfoEnabled = enabled;\n      return this;\n    }\n    return debugInfoEnabled;\n  };\n\n  this.$get = [\n            '$injector', '$interpolate', '$exceptionHandler', '$templateRequest', '$parse',\n            '$controller', '$rootScope', '$document', '$sce', '$animate', '$$sanitizeUri',\n    function($injector,   $interpolate,   $exceptionHandler,   $templateRequest,   $parse,\n             $controller,   $rootScope,   $document,   $sce,   $animate,   $$sanitizeUri) {\n\n    var Attributes = function(element, attributesToCopy) {\n      if (attributesToCopy) {\n        var keys = Object.keys(attributesToCopy);\n        var i, l, key;\n\n        for (i = 0, l = keys.length; i < l; i++) {\n          key = keys[i];\n          this[key] = attributesToCopy[key];\n        }\n      } else {\n        this.$attr = {};\n      }\n\n      this.$$element = element;\n    };\n\n    Attributes.prototype = {\n      /**\n       * @ngdoc method\n       * @name $compile.directive.Attributes#$normalize\n       * @kind function\n       *\n       * @description\n       * Converts an attribute name (e.g. dash/colon/underscore-delimited string, optionally prefixed with `x-` or\n       * `data-`) to its normalized, camelCase form.\n       *\n       * Also there is special case for Moz prefix starting with upper case letter.\n       *\n       * For further information check out the guide on {@link guide/directive#matching-directives Matching Directives}\n       *\n       * @param {string} name Name to normalize\n       */\n      $normalize: directiveNormalize,\n\n\n      /**\n       * @ngdoc method\n       * @name $compile.directive.Attributes#$addClass\n       * @kind function\n       *\n       * @description\n       * Adds the CSS class value specified by the classVal parameter to the element. If animations\n       * are enabled then an animation will be triggered for the class addition.\n       *\n       * @param {string} classVal The className value that will be added to the element\n       */\n      $addClass: function(classVal) {\n        if (classVal && classVal.length > 0) {\n          $animate.addClass(this.$$element, classVal);\n        }\n      },\n\n      /**\n       * @ngdoc method\n       * @name $compile.directive.Attributes#$removeClass\n       * @kind function\n       *\n       * @description\n       * Removes the CSS class value specified by the classVal parameter from the element. If\n       * animations are enabled then an animation will be triggered for the class removal.\n       *\n       * @param {string} classVal The className value that will be removed from the element\n       */\n      $removeClass: function(classVal) {\n        if (classVal && classVal.length > 0) {\n          $animate.removeClass(this.$$element, classVal);\n        }\n      },\n\n      /**\n       * @ngdoc method\n       * @name $compile.directive.Attributes#$updateClass\n       * @kind function\n       *\n       * @description\n       * Adds and removes the appropriate CSS class values to the element based on the difference\n       * between the new and old CSS class values (specified as newClasses and oldClasses).\n       *\n       * @param {string} newClasses The current CSS className value\n       * @param {string} oldClasses The former CSS className value\n       */\n      $updateClass: function(newClasses, oldClasses) {\n        var toAdd = tokenDifference(newClasses, oldClasses);\n        if (toAdd && toAdd.length) {\n          $animate.addClass(this.$$element, toAdd);\n        }\n\n        var toRemove = tokenDifference(oldClasses, newClasses);\n        if (toRemove && toRemove.length) {\n          $animate.removeClass(this.$$element, toRemove);\n        }\n      },\n\n      /**\n       * Set a normalized attribute on the element in a way such that all directives\n       * can share the attribute. This function properly handles boolean attributes.\n       * @param {string} key Normalized key. (ie ngAttribute)\n       * @param {string|boolean} value The value to set. If `null` attribute will be deleted.\n       * @param {boolean=} writeAttr If false, does not write the value to DOM element attribute.\n       *     Defaults to true.\n       * @param {string=} attrName Optional none normalized name. Defaults to key.\n       */\n      $set: function(key, value, writeAttr, attrName) {\n        // TODO: decide whether or not to throw an error if \"class\"\n        //is set through this function since it may cause $updateClass to\n        //become unstable.\n\n        var node = this.$$element[0],\n            booleanKey = getBooleanAttrName(node, key),\n            aliasedKey = getAliasedAttrName(node, key),\n            observer = key,\n            nodeName;\n\n        if (booleanKey) {\n          this.$$element.prop(key, value);\n          attrName = booleanKey;\n        } else if (aliasedKey) {\n          this[aliasedKey] = value;\n          observer = aliasedKey;\n        }\n\n        this[key] = value;\n\n        // translate normalized key to actual key\n        if (attrName) {\n          this.$attr[key] = attrName;\n        } else {\n          attrName = this.$attr[key];\n          if (!attrName) {\n            this.$attr[key] = attrName = snake_case(key, '-');\n          }\n        }\n\n        nodeName = nodeName_(this.$$element);\n\n        if ((nodeName === 'a' && key === 'href') ||\n            (nodeName === 'img' && key === 'src')) {\n          // sanitize a[href] and img[src] values\n          this[key] = value = $$sanitizeUri(value, key === 'src');\n        } else if (nodeName === 'img' && key === 'srcset') {\n          // sanitize img[srcset] values\n          var result = \"\";\n\n          // first check if there are spaces because it's not the same pattern\n          var trimmedSrcset = trim(value);\n          //                (   999x   ,|   999w   ,|   ,|,   )\n          var srcPattern = /(\\s+\\d+x\\s*,|\\s+\\d+w\\s*,|\\s+,|,\\s+)/;\n          var pattern = /\\s/.test(trimmedSrcset) ? srcPattern : /(,)/;\n\n          // split srcset into tuple of uri and descriptor except for the last item\n          var rawUris = trimmedSrcset.split(pattern);\n\n          // for each tuples\n          var nbrUrisWith2parts = Math.floor(rawUris.length / 2);\n          for (var i = 0; i < nbrUrisWith2parts; i++) {\n            var innerIdx = i * 2;\n            // sanitize the uri\n            result += $$sanitizeUri(trim(rawUris[innerIdx]), true);\n            // add the descriptor\n            result += (\" \" + trim(rawUris[innerIdx + 1]));\n          }\n\n          // split the last item into uri and descriptor\n          var lastTuple = trim(rawUris[i * 2]).split(/\\s/);\n\n          // sanitize the last uri\n          result += $$sanitizeUri(trim(lastTuple[0]), true);\n\n          // and add the last descriptor if any\n          if (lastTuple.length === 2) {\n            result += (\" \" + trim(lastTuple[1]));\n          }\n          this[key] = value = result;\n        }\n\n        if (writeAttr !== false) {\n          if (value === null || value === undefined) {\n            this.$$element.removeAttr(attrName);\n          } else {\n            this.$$element.attr(attrName, value);\n          }\n        }\n\n        // fire observers\n        var $$observers = this.$$observers;\n        $$observers && forEach($$observers[observer], function(fn) {\n          try {\n            fn(value);\n          } catch (e) {\n            $exceptionHandler(e);\n          }\n        });\n      },\n\n\n      /**\n       * @ngdoc method\n       * @name $compile.directive.Attributes#$observe\n       * @kind function\n       *\n       * @description\n       * Observes an interpolated attribute.\n       *\n       * The observer function will be invoked once during the next `$digest` following\n       * compilation. The observer is then invoked whenever the interpolated value\n       * changes.\n       *\n       * @param {string} key Normalized key. (ie ngAttribute) .\n       * @param {function(interpolatedValue)} fn Function that will be called whenever\n                the interpolated value of the attribute changes.\n       *        See the {@link guide/directive#text-and-attribute-bindings Directives} guide for more info.\n       * @returns {function()} Returns a deregistration function for this observer.\n       */\n      $observe: function(key, fn) {\n        var attrs = this,\n            $$observers = (attrs.$$observers || (attrs.$$observers = createMap())),\n            listeners = ($$observers[key] || ($$observers[key] = []));\n\n        listeners.push(fn);\n        $rootScope.$evalAsync(function() {\n          if (!listeners.$$inter && attrs.hasOwnProperty(key)) {\n            // no one registered attribute interpolation function, so lets call it manually\n            fn(attrs[key]);\n          }\n        });\n\n        return function() {\n          arrayRemove(listeners, fn);\n        };\n      }\n    };\n\n\n    function safeAddClass($element, className) {\n      try {\n        $element.addClass(className);\n      } catch (e) {\n        // ignore, since it means that we are trying to set class on\n        // SVG element, where class name is read-only.\n      }\n    }\n\n\n    var startSymbol = $interpolate.startSymbol(),\n        endSymbol = $interpolate.endSymbol(),\n        denormalizeTemplate = (startSymbol == '{{' || endSymbol  == '}}')\n            ? identity\n            : function denormalizeTemplate(template) {\n              return template.replace(/\\{\\{/g, startSymbol).replace(/}}/g, endSymbol);\n        },\n        NG_ATTR_BINDING = /^ngAttr[A-Z]/;\n\n    compile.$$addBindingInfo = debugInfoEnabled ? function $$addBindingInfo($element, binding) {\n      var bindings = $element.data('$binding') || [];\n\n      if (isArray(binding)) {\n        bindings = bindings.concat(binding);\n      } else {\n        bindings.push(binding);\n      }\n\n      $element.data('$binding', bindings);\n    } : noop;\n\n    compile.$$addBindingClass = debugInfoEnabled ? function $$addBindingClass($element) {\n      safeAddClass($element, 'ng-binding');\n    } : noop;\n\n    compile.$$addScopeInfo = debugInfoEnabled ? function $$addScopeInfo($element, scope, isolated, noTemplate) {\n      var dataName = isolated ? (noTemplate ? '$isolateScopeNoTemplate' : '$isolateScope') : '$scope';\n      $element.data(dataName, scope);\n    } : noop;\n\n    compile.$$addScopeClass = debugInfoEnabled ? function $$addScopeClass($element, isolated) {\n      safeAddClass($element, isolated ? 'ng-isolate-scope' : 'ng-scope');\n    } : noop;\n\n    return compile;\n\n    //================================\n\n    function compile($compileNodes, transcludeFn, maxPriority, ignoreDirective,\n                        previousCompileContext) {\n      if (!($compileNodes instanceof jqLite)) {\n        // jquery always rewraps, whereas we need to preserve the original selector so that we can\n        // modify it.\n        $compileNodes = jqLite($compileNodes);\n      }\n      // We can not compile top level text elements since text nodes can be merged and we will\n      // not be able to attach scope data to them, so we will wrap them in <span>\n      forEach($compileNodes, function(node, index) {\n        if (node.nodeType == NODE_TYPE_TEXT && node.nodeValue.match(/\\S+/) /* non-empty */ ) {\n          $compileNodes[index] = jqLite(node).wrap('<span></span>').parent()[0];\n        }\n      });\n      var compositeLinkFn =\n              compileNodes($compileNodes, transcludeFn, $compileNodes,\n                           maxPriority, ignoreDirective, previousCompileContext);\n      compile.$$addScopeClass($compileNodes);\n      var namespace = null;\n      return function publicLinkFn(scope, cloneConnectFn, options) {\n        assertArg(scope, 'scope');\n\n        options = options || {};\n        var parentBoundTranscludeFn = options.parentBoundTranscludeFn,\n          transcludeControllers = options.transcludeControllers,\n          futureParentElement = options.futureParentElement;\n\n        // When `parentBoundTranscludeFn` is passed, it is a\n        // `controllersBoundTransclude` function (it was previously passed\n        // as `transclude` to directive.link) so we must unwrap it to get\n        // its `boundTranscludeFn`\n        if (parentBoundTranscludeFn && parentBoundTranscludeFn.$$boundTransclude) {\n          parentBoundTranscludeFn = parentBoundTranscludeFn.$$boundTransclude;\n        }\n\n        if (!namespace) {\n          namespace = detectNamespaceForChildElements(futureParentElement);\n        }\n        var $linkNode;\n        if (namespace !== 'html') {\n          // When using a directive with replace:true and templateUrl the $compileNodes\n          // (or a child element inside of them)\n          // might change, so we need to recreate the namespace adapted compileNodes\n          // for call to the link function.\n          // Note: This will already clone the nodes...\n          $linkNode = jqLite(\n            wrapTemplate(namespace, jqLite('<div>').append($compileNodes).html())\n          );\n        } else if (cloneConnectFn) {\n          // important!!: we must call our jqLite.clone() since the jQuery one is trying to be smart\n          // and sometimes changes the structure of the DOM.\n          $linkNode = JQLitePrototype.clone.call($compileNodes);\n        } else {\n          $linkNode = $compileNodes;\n        }\n\n        if (transcludeControllers) {\n          for (var controllerName in transcludeControllers) {\n            $linkNode.data('$' + controllerName + 'Controller', transcludeControllers[controllerName].instance);\n          }\n        }\n\n        compile.$$addScopeInfo($linkNode, scope);\n\n        if (cloneConnectFn) cloneConnectFn($linkNode, scope);\n        if (compositeLinkFn) compositeLinkFn(scope, $linkNode, $linkNode, parentBoundTranscludeFn);\n        return $linkNode;\n      };\n    }\n\n    function detectNamespaceForChildElements(parentElement) {\n      // TODO: Make this detect MathML as well...\n      var node = parentElement && parentElement[0];\n      if (!node) {\n        return 'html';\n      } else {\n        return nodeName_(node) !== 'foreignobject' && node.toString().match(/SVG/) ? 'svg' : 'html';\n      }\n    }\n\n    /**\n     * Compile function matches each node in nodeList against the directives. Once all directives\n     * for a particular node are collected their compile functions are executed. The compile\n     * functions return values - the linking functions - are combined into a composite linking\n     * function, which is the a linking function for the node.\n     *\n     * @param {NodeList} nodeList an array of nodes or NodeList to compile\n     * @param {function(angular.Scope, cloneAttachFn=)} transcludeFn A linking function, where the\n     *        scope argument is auto-generated to the new child of the transcluded parent scope.\n     * @param {DOMElement=} $rootElement If the nodeList is the root of the compilation tree then\n     *        the rootElement must be set the jqLite collection of the compile root. This is\n     *        needed so that the jqLite collection items can be replaced with widgets.\n     * @param {number=} maxPriority Max directive priority.\n     * @returns {Function} A composite linking function of all of the matched directives or null.\n     */\n    function compileNodes(nodeList, transcludeFn, $rootElement, maxPriority, ignoreDirective,\n                            previousCompileContext) {\n      var linkFns = [],\n          attrs, directives, nodeLinkFn, childNodes, childLinkFn, linkFnFound, nodeLinkFnFound;\n\n      for (var i = 0; i < nodeList.length; i++) {\n        attrs = new Attributes();\n\n        // we must always refer to nodeList[i] since the nodes can be replaced underneath us.\n        directives = collectDirectives(nodeList[i], [], attrs, i === 0 ? maxPriority : undefined,\n                                        ignoreDirective);\n\n        nodeLinkFn = (directives.length)\n            ? applyDirectivesToNode(directives, nodeList[i], attrs, transcludeFn, $rootElement,\n                                      null, [], [], previousCompileContext)\n            : null;\n\n        if (nodeLinkFn && nodeLinkFn.scope) {\n          compile.$$addScopeClass(attrs.$$element);\n        }\n\n        childLinkFn = (nodeLinkFn && nodeLinkFn.terminal ||\n                      !(childNodes = nodeList[i].childNodes) ||\n                      !childNodes.length)\n            ? null\n            : compileNodes(childNodes,\n                 nodeLinkFn ? (\n                  (nodeLinkFn.transcludeOnThisElement || !nodeLinkFn.templateOnThisElement)\n                     && nodeLinkFn.transclude) : transcludeFn);\n\n        if (nodeLinkFn || childLinkFn) {\n          linkFns.push(i, nodeLinkFn, childLinkFn);\n          linkFnFound = true;\n          nodeLinkFnFound = nodeLinkFnFound || nodeLinkFn;\n        }\n\n        //use the previous context only for the first element in the virtual group\n        previousCompileContext = null;\n      }\n\n      // return a linking function if we have found anything, null otherwise\n      return linkFnFound ? compositeLinkFn : null;\n\n      function compositeLinkFn(scope, nodeList, $rootElement, parentBoundTranscludeFn) {\n        var nodeLinkFn, childLinkFn, node, childScope, i, ii, idx, childBoundTranscludeFn;\n        var stableNodeList;\n\n\n        if (nodeLinkFnFound) {\n          // copy nodeList so that if a nodeLinkFn removes or adds an element at this DOM level our\n          // offsets don't get screwed up\n          var nodeListLength = nodeList.length;\n          stableNodeList = new Array(nodeListLength);\n\n          // create a sparse array by only copying the elements which have a linkFn\n          for (i = 0; i < linkFns.length; i+=3) {\n            idx = linkFns[i];\n            stableNodeList[idx] = nodeList[idx];\n          }\n        } else {\n          stableNodeList = nodeList;\n        }\n\n        for (i = 0, ii = linkFns.length; i < ii;) {\n          node = stableNodeList[linkFns[i++]];\n          nodeLinkFn = linkFns[i++];\n          childLinkFn = linkFns[i++];\n\n          if (nodeLinkFn) {\n            if (nodeLinkFn.scope) {\n              childScope = scope.$new();\n              compile.$$addScopeInfo(jqLite(node), childScope);\n            } else {\n              childScope = scope;\n            }\n\n            if (nodeLinkFn.transcludeOnThisElement) {\n              childBoundTranscludeFn = createBoundTranscludeFn(\n                  scope, nodeLinkFn.transclude, parentBoundTranscludeFn,\n                  nodeLinkFn.elementTranscludeOnThisElement);\n\n            } else if (!nodeLinkFn.templateOnThisElement && parentBoundTranscludeFn) {\n              childBoundTranscludeFn = parentBoundTranscludeFn;\n\n            } else if (!parentBoundTranscludeFn && transcludeFn) {\n              childBoundTranscludeFn = createBoundTranscludeFn(scope, transcludeFn);\n\n            } else {\n              childBoundTranscludeFn = null;\n            }\n\n            nodeLinkFn(childLinkFn, childScope, node, $rootElement, childBoundTranscludeFn);\n\n          } else if (childLinkFn) {\n            childLinkFn(scope, node.childNodes, undefined, parentBoundTranscludeFn);\n          }\n        }\n      }\n    }\n\n    function createBoundTranscludeFn(scope, transcludeFn, previousBoundTranscludeFn, elementTransclusion) {\n\n      var boundTranscludeFn = function(transcludedScope, cloneFn, controllers, futureParentElement, containingScope) {\n\n        if (!transcludedScope) {\n          transcludedScope = scope.$new(false, containingScope);\n          transcludedScope.$$transcluded = true;\n        }\n\n        return transcludeFn(transcludedScope, cloneFn, {\n          parentBoundTranscludeFn: previousBoundTranscludeFn,\n          transcludeControllers: controllers,\n          futureParentElement: futureParentElement\n        });\n      };\n\n      return boundTranscludeFn;\n    }\n\n    /**\n     * Looks for directives on the given node and adds them to the directive collection which is\n     * sorted.\n     *\n     * @param node Node to search.\n     * @param directives An array to which the directives are added to. This array is sorted before\n     *        the function returns.\n     * @param attrs The shared attrs object which is used to populate the normalized attributes.\n     * @param {number=} maxPriority Max directive priority.\n     */\n    function collectDirectives(node, directives, attrs, maxPriority, ignoreDirective) {\n      var nodeType = node.nodeType,\n          attrsMap = attrs.$attr,\n          match,\n          className;\n\n      switch (nodeType) {\n        case NODE_TYPE_ELEMENT: /* Element */\n          // use the node name: <directive>\n          addDirective(directives,\n              directiveNormalize(nodeName_(node)), 'E', maxPriority, ignoreDirective);\n\n          // iterate over the attributes\n          for (var attr, name, nName, ngAttrName, value, isNgAttr, nAttrs = node.attributes,\n                   j = 0, jj = nAttrs && nAttrs.length; j < jj; j++) {\n            var attrStartName = false;\n            var attrEndName = false;\n\n            attr = nAttrs[j];\n            name = attr.name;\n            value = trim(attr.value);\n\n            // support ngAttr attribute binding\n            ngAttrName = directiveNormalize(name);\n            if (isNgAttr = NG_ATTR_BINDING.test(ngAttrName)) {\n              name = name.replace(PREFIX_REGEXP, '')\n                .substr(8).replace(/_(.)/g, function(match, letter) {\n                  return letter.toUpperCase();\n                });\n            }\n\n            var directiveNName = ngAttrName.replace(/(Start|End)$/, '');\n            if (directiveIsMultiElement(directiveNName)) {\n              if (ngAttrName === directiveNName + 'Start') {\n                attrStartName = name;\n                attrEndName = name.substr(0, name.length - 5) + 'end';\n                name = name.substr(0, name.length - 6);\n              }\n            }\n\n            nName = directiveNormalize(name.toLowerCase());\n            attrsMap[nName] = name;\n            if (isNgAttr || !attrs.hasOwnProperty(nName)) {\n                attrs[nName] = value;\n                if (getBooleanAttrName(node, nName)) {\n                  attrs[nName] = true; // presence means true\n                }\n            }\n            addAttrInterpolateDirective(node, directives, value, nName, isNgAttr);\n            addDirective(directives, nName, 'A', maxPriority, ignoreDirective, attrStartName,\n                          attrEndName);\n          }\n\n          // use class as directive\n          className = node.className;\n          if (isObject(className)) {\n              // Maybe SVGAnimatedString\n              className = className.animVal;\n          }\n          if (isString(className) && className !== '') {\n            while (match = CLASS_DIRECTIVE_REGEXP.exec(className)) {\n              nName = directiveNormalize(match[2]);\n              if (addDirective(directives, nName, 'C', maxPriority, ignoreDirective)) {\n                attrs[nName] = trim(match[3]);\n              }\n              className = className.substr(match.index + match[0].length);\n            }\n          }\n          break;\n        case NODE_TYPE_TEXT: /* Text Node */\n          addTextInterpolateDirective(directives, node.nodeValue);\n          break;\n        case NODE_TYPE_COMMENT: /* Comment */\n          try {\n            match = COMMENT_DIRECTIVE_REGEXP.exec(node.nodeValue);\n            if (match) {\n              nName = directiveNormalize(match[1]);\n              if (addDirective(directives, nName, 'M', maxPriority, ignoreDirective)) {\n                attrs[nName] = trim(match[2]);\n              }\n            }\n          } catch (e) {\n            // turns out that under some circumstances IE9 throws errors when one attempts to read\n            // comment's node value.\n            // Just ignore it and continue. (Can't seem to reproduce in test case.)\n          }\n          break;\n      }\n\n      directives.sort(byPriority);\n      return directives;\n    }\n\n    /**\n     * Given a node with an directive-start it collects all of the siblings until it finds\n     * directive-end.\n     * @param node\n     * @param attrStart\n     * @param attrEnd\n     * @returns {*}\n     */\n    function groupScan(node, attrStart, attrEnd) {\n      var nodes = [];\n      var depth = 0;\n      if (attrStart && node.hasAttribute && node.hasAttribute(attrStart)) {\n        do {\n          if (!node) {\n            throw $compileMinErr('uterdir',\n                      \"Unterminated attribute, found '{0}' but no matching '{1}' found.\",\n                      attrStart, attrEnd);\n          }\n          if (node.nodeType == NODE_TYPE_ELEMENT) {\n            if (node.hasAttribute(attrStart)) depth++;\n            if (node.hasAttribute(attrEnd)) depth--;\n          }\n          nodes.push(node);\n          node = node.nextSibling;\n        } while (depth > 0);\n      } else {\n        nodes.push(node);\n      }\n\n      return jqLite(nodes);\n    }\n\n    /**\n     * Wrapper for linking function which converts normal linking function into a grouped\n     * linking function.\n     * @param linkFn\n     * @param attrStart\n     * @param attrEnd\n     * @returns {Function}\n     */\n    function groupElementsLinkFnWrapper(linkFn, attrStart, attrEnd) {\n      return function(scope, element, attrs, controllers, transcludeFn) {\n        element = groupScan(element[0], attrStart, attrEnd);\n        return linkFn(scope, element, attrs, controllers, transcludeFn);\n      };\n    }\n\n    /**\n     * Once the directives have been collected, their compile functions are executed. This method\n     * is responsible for inlining directive templates as well as terminating the application\n     * of the directives if the terminal directive has been reached.\n     *\n     * @param {Array} directives Array of collected directives to execute their compile function.\n     *        this needs to be pre-sorted by priority order.\n     * @param {Node} compileNode The raw DOM node to apply the compile functions to\n     * @param {Object} templateAttrs The shared attribute function\n     * @param {function(angular.Scope, cloneAttachFn=)} transcludeFn A linking function, where the\n     *                                                  scope argument is auto-generated to the new\n     *                                                  child of the transcluded parent scope.\n     * @param {JQLite} jqCollection If we are working on the root of the compile tree then this\n     *                              argument has the root jqLite array so that we can replace nodes\n     *                              on it.\n     * @param {Object=} originalReplaceDirective An optional directive that will be ignored when\n     *                                           compiling the transclusion.\n     * @param {Array.<Function>} preLinkFns\n     * @param {Array.<Function>} postLinkFns\n     * @param {Object} previousCompileContext Context used for previous compilation of the current\n     *                                        node\n     * @returns {Function} linkFn\n     */\n    function applyDirectivesToNode(directives, compileNode, templateAttrs, transcludeFn,\n                                   jqCollection, originalReplaceDirective, preLinkFns, postLinkFns,\n                                   previousCompileContext) {\n      previousCompileContext = previousCompileContext || {};\n\n      var terminalPriority = -Number.MAX_VALUE,\n          newScopeDirective,\n          controllerDirectives = previousCompileContext.controllerDirectives,\n          controllers,\n          newIsolateScopeDirective = previousCompileContext.newIsolateScopeDirective,\n          templateDirective = previousCompileContext.templateDirective,\n          nonTlbTranscludeDirective = previousCompileContext.nonTlbTranscludeDirective,\n          hasTranscludeDirective = false,\n          hasTemplate = false,\n          hasElementTranscludeDirective = previousCompileContext.hasElementTranscludeDirective,\n          $compileNode = templateAttrs.$$element = jqLite(compileNode),\n          directive,\n          directiveName,\n          $template,\n          replaceDirective = originalReplaceDirective,\n          childTranscludeFn = transcludeFn,\n          linkFn,\n          directiveValue;\n\n      // executes all directives on the current element\n      for (var i = 0, ii = directives.length; i < ii; i++) {\n        directive = directives[i];\n        var attrStart = directive.$$start;\n        var attrEnd = directive.$$end;\n\n        // collect multiblock sections\n        if (attrStart) {\n          $compileNode = groupScan(compileNode, attrStart, attrEnd);\n        }\n        $template = undefined;\n\n        if (terminalPriority > directive.priority) {\n          break; // prevent further processing of directives\n        }\n\n        if (directiveValue = directive.scope) {\n\n          // skip the check for directives with async templates, we'll check the derived sync\n          // directive when the template arrives\n          if (!directive.templateUrl) {\n            if (isObject(directiveValue)) {\n              // This directive is trying to add an isolated scope.\n              // Check that there is no scope of any kind already\n              assertNoDuplicate('new/isolated scope', newIsolateScopeDirective || newScopeDirective,\n                                directive, $compileNode);\n              newIsolateScopeDirective = directive;\n            } else {\n              // This directive is trying to add a child scope.\n              // Check that there is no isolated scope already\n              assertNoDuplicate('new/isolated scope', newIsolateScopeDirective, directive,\n                                $compileNode);\n            }\n          }\n\n          newScopeDirective = newScopeDirective || directive;\n        }\n\n        directiveName = directive.name;\n\n        if (!directive.templateUrl && directive.controller) {\n          directiveValue = directive.controller;\n          controllerDirectives = controllerDirectives || {};\n          assertNoDuplicate(\"'\" + directiveName + \"' controller\",\n              controllerDirectives[directiveName], directive, $compileNode);\n          controllerDirectives[directiveName] = directive;\n        }\n\n        if (directiveValue = directive.transclude) {\n          hasTranscludeDirective = true;\n\n          // Special case ngIf and ngRepeat so that we don't complain about duplicate transclusion.\n          // This option should only be used by directives that know how to safely handle element transclusion,\n          // where the transcluded nodes are added or replaced after linking.\n          if (!directive.$$tlb) {\n            assertNoDuplicate('transclusion', nonTlbTranscludeDirective, directive, $compileNode);\n            nonTlbTranscludeDirective = directive;\n          }\n\n          if (directiveValue == 'element') {\n            hasElementTranscludeDirective = true;\n            terminalPriority = directive.priority;\n            $template = $compileNode;\n            $compileNode = templateAttrs.$$element =\n                jqLite(document.createComment(' ' + directiveName + ': ' +\n                                              templateAttrs[directiveName] + ' '));\n            compileNode = $compileNode[0];\n            replaceWith(jqCollection, sliceArgs($template), compileNode);\n\n            childTranscludeFn = compile($template, transcludeFn, terminalPriority,\n                                        replaceDirective && replaceDirective.name, {\n                                          // Don't pass in:\n                                          // - controllerDirectives - otherwise we'll create duplicates controllers\n                                          // - newIsolateScopeDirective or templateDirective - combining templates with\n                                          //   element transclusion doesn't make sense.\n                                          //\n                                          // We need only nonTlbTranscludeDirective so that we prevent putting transclusion\n                                          // on the same element more than once.\n                                          nonTlbTranscludeDirective: nonTlbTranscludeDirective\n                                        });\n          } else {\n            $template = jqLite(jqLiteClone(compileNode)).contents();\n            $compileNode.empty(); // clear contents\n            childTranscludeFn = compile($template, transcludeFn);\n          }\n        }\n\n        if (directive.template) {\n          hasTemplate = true;\n          assertNoDuplicate('template', templateDirective, directive, $compileNode);\n          templateDirective = directive;\n\n          directiveValue = (isFunction(directive.template))\n              ? directive.template($compileNode, templateAttrs)\n              : directive.template;\n\n          directiveValue = denormalizeTemplate(directiveValue);\n\n          if (directive.replace) {\n            replaceDirective = directive;\n            if (jqLiteIsTextNode(directiveValue)) {\n              $template = [];\n            } else {\n              $template = removeComments(wrapTemplate(directive.templateNamespace, trim(directiveValue)));\n            }\n            compileNode = $template[0];\n\n            if ($template.length != 1 || compileNode.nodeType !== NODE_TYPE_ELEMENT) {\n              throw $compileMinErr('tplrt',\n                  \"Template for directive '{0}' must have exactly one root element. {1}\",\n                  directiveName, '');\n            }\n\n            replaceWith(jqCollection, $compileNode, compileNode);\n\n            var newTemplateAttrs = {$attr: {}};\n\n            // combine directives from the original node and from the template:\n            // - take the array of directives for this element\n            // - split it into two parts, those that already applied (processed) and those that weren't (unprocessed)\n            // - collect directives from the template and sort them by priority\n            // - combine directives as: processed + template + unprocessed\n            var templateDirectives = collectDirectives(compileNode, [], newTemplateAttrs);\n            var unprocessedDirectives = directives.splice(i + 1, directives.length - (i + 1));\n\n            if (newIsolateScopeDirective) {\n              markDirectivesAsIsolate(templateDirectives);\n            }\n            directives = directives.concat(templateDirectives).concat(unprocessedDirectives);\n            mergeTemplateAttributes(templateAttrs, newTemplateAttrs);\n\n            ii = directives.length;\n          } else {\n            $compileNode.html(directiveValue);\n          }\n        }\n\n        if (directive.templateUrl) {\n          hasTemplate = true;\n          assertNoDuplicate('template', templateDirective, directive, $compileNode);\n          templateDirective = directive;\n\n          if (directive.replace) {\n            replaceDirective = directive;\n          }\n\n          nodeLinkFn = compileTemplateUrl(directives.splice(i, directives.length - i), $compileNode,\n              templateAttrs, jqCollection, hasTranscludeDirective && childTranscludeFn, preLinkFns, postLinkFns, {\n                controllerDirectives: controllerDirectives,\n                newIsolateScopeDirective: newIsolateScopeDirective,\n                templateDirective: templateDirective,\n                nonTlbTranscludeDirective: nonTlbTranscludeDirective\n              });\n          ii = directives.length;\n        } else if (directive.compile) {\n          try {\n            linkFn = directive.compile($compileNode, templateAttrs, childTranscludeFn);\n            if (isFunction(linkFn)) {\n              addLinkFns(null, linkFn, attrStart, attrEnd);\n            } else if (linkFn) {\n              addLinkFns(linkFn.pre, linkFn.post, attrStart, attrEnd);\n            }\n          } catch (e) {\n            $exceptionHandler(e, startingTag($compileNode));\n          }\n        }\n\n        if (directive.terminal) {\n          nodeLinkFn.terminal = true;\n          terminalPriority = Math.max(terminalPriority, directive.priority);\n        }\n\n      }\n\n      nodeLinkFn.scope = newScopeDirective && newScopeDirective.scope === true;\n      nodeLinkFn.transcludeOnThisElement = hasTranscludeDirective;\n      nodeLinkFn.elementTranscludeOnThisElement = hasElementTranscludeDirective;\n      nodeLinkFn.templateOnThisElement = hasTemplate;\n      nodeLinkFn.transclude = childTranscludeFn;\n\n      previousCompileContext.hasElementTranscludeDirective = hasElementTranscludeDirective;\n\n      // might be normal or delayed nodeLinkFn depending on if templateUrl is present\n      return nodeLinkFn;\n\n      ////////////////////\n\n      function addLinkFns(pre, post, attrStart, attrEnd) {\n        if (pre) {\n          if (attrStart) pre = groupElementsLinkFnWrapper(pre, attrStart, attrEnd);\n          pre.require = directive.require;\n          pre.directiveName = directiveName;\n          if (newIsolateScopeDirective === directive || directive.$$isolateScope) {\n            pre = cloneAndAnnotateFn(pre, {isolateScope: true});\n          }\n          preLinkFns.push(pre);\n        }\n        if (post) {\n          if (attrStart) post = groupElementsLinkFnWrapper(post, attrStart, attrEnd);\n          post.require = directive.require;\n          post.directiveName = directiveName;\n          if (newIsolateScopeDirective === directive || directive.$$isolateScope) {\n            post = cloneAndAnnotateFn(post, {isolateScope: true});\n          }\n          postLinkFns.push(post);\n        }\n      }\n\n\n      function getControllers(directiveName, require, $element, elementControllers) {\n        var value, retrievalMethod = 'data', optional = false;\n        var $searchElement = $element;\n        var match;\n        if (isString(require)) {\n          match = require.match(REQUIRE_PREFIX_REGEXP);\n          require = require.substring(match[0].length);\n\n          if (match[3]) {\n            if (match[1]) match[3] = null;\n            else match[1] = match[3];\n          }\n          if (match[1] === '^') {\n            retrievalMethod = 'inheritedData';\n          } else if (match[1] === '^^') {\n            retrievalMethod = 'inheritedData';\n            $searchElement = $element.parent();\n          }\n          if (match[2] === '?') {\n            optional = true;\n          }\n\n          value = null;\n\n          if (elementControllers && retrievalMethod === 'data') {\n            if (value = elementControllers[require]) {\n              value = value.instance;\n            }\n          }\n          value = value || $searchElement[retrievalMethod]('$' + require + 'Controller');\n\n          if (!value && !optional) {\n            throw $compileMinErr('ctreq',\n                \"Controller '{0}', required by directive '{1}', can't be found!\",\n                require, directiveName);\n          }\n          return value || null;\n        } else if (isArray(require)) {\n          value = [];\n          forEach(require, function(require) {\n            value.push(getControllers(directiveName, require, $element, elementControllers));\n          });\n        }\n        return value;\n      }\n\n\n      function nodeLinkFn(childLinkFn, scope, linkNode, $rootElement, boundTranscludeFn) {\n        var i, ii, linkFn, controller, isolateScope, elementControllers, transcludeFn, $element,\n            attrs;\n\n        if (compileNode === linkNode) {\n          attrs = templateAttrs;\n          $element = templateAttrs.$$element;\n        } else {\n          $element = jqLite(linkNode);\n          attrs = new Attributes($element, templateAttrs);\n        }\n\n        if (newIsolateScopeDirective) {\n          isolateScope = scope.$new(true);\n        }\n\n        if (boundTranscludeFn) {\n          // track `boundTranscludeFn` so it can be unwrapped if `transcludeFn`\n          // is later passed as `parentBoundTranscludeFn` to `publicLinkFn`\n          transcludeFn = controllersBoundTransclude;\n          transcludeFn.$$boundTransclude = boundTranscludeFn;\n        }\n\n        if (controllerDirectives) {\n          // TODO: merge `controllers` and `elementControllers` into single object.\n          controllers = {};\n          elementControllers = {};\n          forEach(controllerDirectives, function(directive) {\n            var locals = {\n              $scope: directive === newIsolateScopeDirective || directive.$$isolateScope ? isolateScope : scope,\n              $element: $element,\n              $attrs: attrs,\n              $transclude: transcludeFn\n            }, controllerInstance;\n\n            controller = directive.controller;\n            if (controller == '@') {\n              controller = attrs[directive.name];\n            }\n\n            controllerInstance = $controller(controller, locals, true, directive.controllerAs);\n\n            // For directives with element transclusion the element is a comment,\n            // but jQuery .data doesn't support attaching data to comment nodes as it's hard to\n            // clean up (http://bugs.jquery.com/ticket/8335).\n            // Instead, we save the controllers for the element in a local hash and attach to .data\n            // later, once we have the actual element.\n            elementControllers[directive.name] = controllerInstance;\n            if (!hasElementTranscludeDirective) {\n              $element.data('$' + directive.name + 'Controller', controllerInstance.instance);\n            }\n\n            controllers[directive.name] = controllerInstance;\n          });\n        }\n\n        if (newIsolateScopeDirective) {\n          compile.$$addScopeInfo($element, isolateScope, true, !(templateDirective && (templateDirective === newIsolateScopeDirective ||\n              templateDirective === newIsolateScopeDirective.$$originalDirective)));\n          compile.$$addScopeClass($element, true);\n\n          var isolateScopeController = controllers && controllers[newIsolateScopeDirective.name];\n          var isolateBindingContext = isolateScope;\n          if (isolateScopeController && isolateScopeController.identifier &&\n              newIsolateScopeDirective.bindToController === true) {\n            isolateBindingContext = isolateScopeController.instance;\n          }\n\n          forEach(isolateScope.$$isolateBindings = newIsolateScopeDirective.$$isolateBindings, function(definition, scopeName) {\n            var attrName = definition.attrName,\n                optional = definition.optional,\n                mode = definition.mode, // @, =, or &\n                lastValue,\n                parentGet, parentSet, compare;\n\n            switch (mode) {\n\n              case '@':\n                attrs.$observe(attrName, function(value) {\n                  isolateBindingContext[scopeName] = value;\n                });\n                attrs.$$observers[attrName].$$scope = scope;\n                if (attrs[attrName]) {\n                  // If the attribute has been provided then we trigger an interpolation to ensure\n                  // the value is there for use in the link fn\n                  isolateBindingContext[scopeName] = $interpolate(attrs[attrName])(scope);\n                }\n                break;\n\n              case '=':\n                if (optional && !attrs[attrName]) {\n                  return;\n                }\n                parentGet = $parse(attrs[attrName]);\n                if (parentGet.literal) {\n                  compare = equals;\n                } else {\n                  compare = function(a, b) { return a === b || (a !== a && b !== b); };\n                }\n                parentSet = parentGet.assign || function() {\n                  // reset the change, or we will throw this exception on every $digest\n                  lastValue = isolateBindingContext[scopeName] = parentGet(scope);\n                  throw $compileMinErr('nonassign',\n                      \"Expression '{0}' used with directive '{1}' is non-assignable!\",\n                      attrs[attrName], newIsolateScopeDirective.name);\n                };\n                lastValue = isolateBindingContext[scopeName] = parentGet(scope);\n                var parentValueWatch = function parentValueWatch(parentValue) {\n                  if (!compare(parentValue, isolateBindingContext[scopeName])) {\n                    // we are out of sync and need to copy\n                    if (!compare(parentValue, lastValue)) {\n                      // parent changed and it has precedence\n                      isolateBindingContext[scopeName] = parentValue;\n                    } else {\n                      // if the parent can be assigned then do so\n                      parentSet(scope, parentValue = isolateBindingContext[scopeName]);\n                    }\n                  }\n                  return lastValue = parentValue;\n                };\n                parentValueWatch.$stateful = true;\n                var unwatch;\n                if (definition.collection) {\n                  unwatch = scope.$watchCollection(attrs[attrName], parentValueWatch);\n                } else {\n                  unwatch = scope.$watch($parse(attrs[attrName], parentValueWatch), null, parentGet.literal);\n                }\n                isolateScope.$on('$destroy', unwatch);\n                break;\n\n              case '&':\n                parentGet = $parse(attrs[attrName]);\n                isolateBindingContext[scopeName] = function(locals) {\n                  return parentGet(scope, locals);\n                };\n                break;\n            }\n          });\n        }\n        if (controllers) {\n          forEach(controllers, function(controller) {\n            controller();\n          });\n          controllers = null;\n        }\n\n        // PRELINKING\n        for (i = 0, ii = preLinkFns.length; i < ii; i++) {\n          linkFn = preLinkFns[i];\n          invokeLinkFn(linkFn,\n              linkFn.isolateScope ? isolateScope : scope,\n              $element,\n              attrs,\n              linkFn.require && getControllers(linkFn.directiveName, linkFn.require, $element, elementControllers),\n              transcludeFn\n          );\n        }\n\n        // RECURSION\n        // We only pass the isolate scope, if the isolate directive has a template,\n        // otherwise the child elements do not belong to the isolate directive.\n        var scopeToChild = scope;\n        if (newIsolateScopeDirective && (newIsolateScopeDirective.template || newIsolateScopeDirective.templateUrl === null)) {\n          scopeToChild = isolateScope;\n        }\n        childLinkFn && childLinkFn(scopeToChild, linkNode.childNodes, undefined, boundTranscludeFn);\n\n        // POSTLINKING\n        for (i = postLinkFns.length - 1; i >= 0; i--) {\n          linkFn = postLinkFns[i];\n          invokeLinkFn(linkFn,\n              linkFn.isolateScope ? isolateScope : scope,\n              $element,\n              attrs,\n              linkFn.require && getControllers(linkFn.directiveName, linkFn.require, $element, elementControllers),\n              transcludeFn\n          );\n        }\n\n        // This is the function that is injected as `$transclude`.\n        // Note: all arguments are optional!\n        function controllersBoundTransclude(scope, cloneAttachFn, futureParentElement) {\n          var transcludeControllers;\n\n          // No scope passed in:\n          if (!isScope(scope)) {\n            futureParentElement = cloneAttachFn;\n            cloneAttachFn = scope;\n            scope = undefined;\n          }\n\n          if (hasElementTranscludeDirective) {\n            transcludeControllers = elementControllers;\n          }\n          if (!futureParentElement) {\n            futureParentElement = hasElementTranscludeDirective ? $element.parent() : $element;\n          }\n          return boundTranscludeFn(scope, cloneAttachFn, transcludeControllers, futureParentElement, scopeToChild);\n        }\n      }\n    }\n\n    function markDirectivesAsIsolate(directives) {\n      // mark all directives as needing isolate scope.\n      for (var j = 0, jj = directives.length; j < jj; j++) {\n        directives[j] = inherit(directives[j], {$$isolateScope: true});\n      }\n    }\n\n    /**\n     * looks up the directive and decorates it with exception handling and proper parameters. We\n     * call this the boundDirective.\n     *\n     * @param {string} name name of the directive to look up.\n     * @param {string} location The directive must be found in specific format.\n     *   String containing any of theses characters:\n     *\n     *   * `E`: element name\n     *   * `A': attribute\n     *   * `C`: class\n     *   * `M`: comment\n     * @returns {boolean} true if directive was added.\n     */\n    function addDirective(tDirectives, name, location, maxPriority, ignoreDirective, startAttrName,\n                          endAttrName) {\n      if (name === ignoreDirective) return null;\n      var match = null;\n      if (hasDirectives.hasOwnProperty(name)) {\n        for (var directive, directives = $injector.get(name + Suffix),\n            i = 0, ii = directives.length; i < ii; i++) {\n          try {\n            directive = directives[i];\n            if ((maxPriority === undefined || maxPriority > directive.priority) &&\n                 directive.restrict.indexOf(location) != -1) {\n              if (startAttrName) {\n                directive = inherit(directive, {$$start: startAttrName, $$end: endAttrName});\n              }\n              tDirectives.push(directive);\n              match = directive;\n            }\n          } catch (e) { $exceptionHandler(e); }\n        }\n      }\n      return match;\n    }\n\n\n    /**\n     * looks up the directive and returns true if it is a multi-element directive,\n     * and therefore requires DOM nodes between -start and -end markers to be grouped\n     * together.\n     *\n     * @param {string} name name of the directive to look up.\n     * @returns true if directive was registered as multi-element.\n     */\n    function directiveIsMultiElement(name) {\n      if (hasDirectives.hasOwnProperty(name)) {\n        for (var directive, directives = $injector.get(name + Suffix),\n            i = 0, ii = directives.length; i < ii; i++) {\n          directive = directives[i];\n          if (directive.multiElement) {\n            return true;\n          }\n        }\n      }\n      return false;\n    }\n\n    /**\n     * When the element is replaced with HTML template then the new attributes\n     * on the template need to be merged with the existing attributes in the DOM.\n     * The desired effect is to have both of the attributes present.\n     *\n     * @param {object} dst destination attributes (original DOM)\n     * @param {object} src source attributes (from the directive template)\n     */\n    function mergeTemplateAttributes(dst, src) {\n      var srcAttr = src.$attr,\n          dstAttr = dst.$attr,\n          $element = dst.$$element;\n\n      // reapply the old attributes to the new element\n      forEach(dst, function(value, key) {\n        if (key.charAt(0) != '$') {\n          if (src[key] && src[key] !== value) {\n            value += (key === 'style' ? ';' : ' ') + src[key];\n          }\n          dst.$set(key, value, true, srcAttr[key]);\n        }\n      });\n\n      // copy the new attributes on the old attrs object\n      forEach(src, function(value, key) {\n        if (key == 'class') {\n          safeAddClass($element, value);\n          dst['class'] = (dst['class'] ? dst['class'] + ' ' : '') + value;\n        } else if (key == 'style') {\n          $element.attr('style', $element.attr('style') + ';' + value);\n          dst['style'] = (dst['style'] ? dst['style'] + ';' : '') + value;\n          // `dst` will never contain hasOwnProperty as DOM parser won't let it.\n          // You will get an \"InvalidCharacterError: DOM Exception 5\" error if you\n          // have an attribute like \"has-own-property\" or \"data-has-own-property\", etc.\n        } else if (key.charAt(0) != '$' && !dst.hasOwnProperty(key)) {\n          dst[key] = value;\n          dstAttr[key] = srcAttr[key];\n        }\n      });\n    }\n\n\n    function compileTemplateUrl(directives, $compileNode, tAttrs,\n        $rootElement, childTranscludeFn, preLinkFns, postLinkFns, previousCompileContext) {\n      var linkQueue = [],\n          afterTemplateNodeLinkFn,\n          afterTemplateChildLinkFn,\n          beforeTemplateCompileNode = $compileNode[0],\n          origAsyncDirective = directives.shift(),\n          derivedSyncDirective = inherit(origAsyncDirective, {\n            templateUrl: null, transclude: null, replace: null, $$originalDirective: origAsyncDirective\n          }),\n          templateUrl = (isFunction(origAsyncDirective.templateUrl))\n              ? origAsyncDirective.templateUrl($compileNode, tAttrs)\n              : origAsyncDirective.templateUrl,\n          templateNamespace = origAsyncDirective.templateNamespace;\n\n      $compileNode.empty();\n\n      $templateRequest($sce.getTrustedResourceUrl(templateUrl))\n        .then(function(content) {\n          var compileNode, tempTemplateAttrs, $template, childBoundTranscludeFn;\n\n          content = denormalizeTemplate(content);\n\n          if (origAsyncDirective.replace) {\n            if (jqLiteIsTextNode(content)) {\n              $template = [];\n            } else {\n              $template = removeComments(wrapTemplate(templateNamespace, trim(content)));\n            }\n            compileNode = $template[0];\n\n            if ($template.length != 1 || compileNode.nodeType !== NODE_TYPE_ELEMENT) {\n              throw $compileMinErr('tplrt',\n                  \"Template for directive '{0}' must have exactly one root element. {1}\",\n                  origAsyncDirective.name, templateUrl);\n            }\n\n            tempTemplateAttrs = {$attr: {}};\n            replaceWith($rootElement, $compileNode, compileNode);\n            var templateDirectives = collectDirectives(compileNode, [], tempTemplateAttrs);\n\n            if (isObject(origAsyncDirective.scope)) {\n              markDirectivesAsIsolate(templateDirectives);\n            }\n            directives = templateDirectives.concat(directives);\n            mergeTemplateAttributes(tAttrs, tempTemplateAttrs);\n          } else {\n            compileNode = beforeTemplateCompileNode;\n            $compileNode.html(content);\n          }\n\n          directives.unshift(derivedSyncDirective);\n\n          afterTemplateNodeLinkFn = applyDirectivesToNode(directives, compileNode, tAttrs,\n              childTranscludeFn, $compileNode, origAsyncDirective, preLinkFns, postLinkFns,\n              previousCompileContext);\n          forEach($rootElement, function(node, i) {\n            if (node == compileNode) {\n              $rootElement[i] = $compileNode[0];\n            }\n          });\n          afterTemplateChildLinkFn = compileNodes($compileNode[0].childNodes, childTranscludeFn);\n\n          while (linkQueue.length) {\n            var scope = linkQueue.shift(),\n                beforeTemplateLinkNode = linkQueue.shift(),\n                linkRootElement = linkQueue.shift(),\n                boundTranscludeFn = linkQueue.shift(),\n                linkNode = $compileNode[0];\n\n            if (scope.$$destroyed) continue;\n\n            if (beforeTemplateLinkNode !== beforeTemplateCompileNode) {\n              var oldClasses = beforeTemplateLinkNode.className;\n\n              if (!(previousCompileContext.hasElementTranscludeDirective &&\n                  origAsyncDirective.replace)) {\n                // it was cloned therefore we have to clone as well.\n                linkNode = jqLiteClone(compileNode);\n              }\n              replaceWith(linkRootElement, jqLite(beforeTemplateLinkNode), linkNode);\n\n              // Copy in CSS classes from original node\n              safeAddClass(jqLite(linkNode), oldClasses);\n            }\n            if (afterTemplateNodeLinkFn.transcludeOnThisElement) {\n              childBoundTranscludeFn = createBoundTranscludeFn(scope, afterTemplateNodeLinkFn.transclude, boundTranscludeFn);\n            } else {\n              childBoundTranscludeFn = boundTranscludeFn;\n            }\n            afterTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, linkNode, $rootElement,\n              childBoundTranscludeFn);\n          }\n          linkQueue = null;\n        });\n\n      return function delayedNodeLinkFn(ignoreChildLinkFn, scope, node, rootElement, boundTranscludeFn) {\n        var childBoundTranscludeFn = boundTranscludeFn;\n        if (scope.$$destroyed) return;\n        if (linkQueue) {\n          linkQueue.push(scope,\n                         node,\n                         rootElement,\n                         childBoundTranscludeFn);\n        } else {\n          if (afterTemplateNodeLinkFn.transcludeOnThisElement) {\n            childBoundTranscludeFn = createBoundTranscludeFn(scope, afterTemplateNodeLinkFn.transclude, boundTranscludeFn);\n          }\n          afterTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, node, rootElement, childBoundTranscludeFn);\n        }\n      };\n    }\n\n\n    /**\n     * Sorting function for bound directives.\n     */\n    function byPriority(a, b) {\n      var diff = b.priority - a.priority;\n      if (diff !== 0) return diff;\n      if (a.name !== b.name) return (a.name < b.name) ? -1 : 1;\n      return a.index - b.index;\n    }\n\n\n    function assertNoDuplicate(what, previousDirective, directive, element) {\n      if (previousDirective) {\n        throw $compileMinErr('multidir', 'Multiple directives [{0}, {1}] asking for {2} on: {3}',\n            previousDirective.name, directive.name, what, startingTag(element));\n      }\n    }\n\n\n    function addTextInterpolateDirective(directives, text) {\n      var interpolateFn = $interpolate(text, true);\n      if (interpolateFn) {\n        directives.push({\n          priority: 0,\n          compile: function textInterpolateCompileFn(templateNode) {\n            var templateNodeParent = templateNode.parent(),\n                hasCompileParent = !!templateNodeParent.length;\n\n            // When transcluding a template that has bindings in the root\n            // we don't have a parent and thus need to add the class during linking fn.\n            if (hasCompileParent) compile.$$addBindingClass(templateNodeParent);\n\n            return function textInterpolateLinkFn(scope, node) {\n              var parent = node.parent();\n              if (!hasCompileParent) compile.$$addBindingClass(parent);\n              compile.$$addBindingInfo(parent, interpolateFn.expressions);\n              scope.$watch(interpolateFn, function interpolateFnWatchAction(value) {\n                node[0].nodeValue = value;\n              });\n            };\n          }\n        });\n      }\n    }\n\n\n    function wrapTemplate(type, template) {\n      type = lowercase(type || 'html');\n      switch (type) {\n      case 'svg':\n      case 'math':\n        var wrapper = document.createElement('div');\n        wrapper.innerHTML = '<' + type + '>' + template + '</' + type + '>';\n        return wrapper.childNodes[0].childNodes;\n      default:\n        return template;\n      }\n    }\n\n\n    function getTrustedContext(node, attrNormalizedName) {\n      if (attrNormalizedName == \"srcdoc\") {\n        return $sce.HTML;\n      }\n      var tag = nodeName_(node);\n      // maction[xlink:href] can source SVG.  It's not limited to <maction>.\n      if (attrNormalizedName == \"xlinkHref\" ||\n          (tag == \"form\" && attrNormalizedName == \"action\") ||\n          (tag != \"img\" && (attrNormalizedName == \"src\" ||\n                            attrNormalizedName == \"ngSrc\"))) {\n        return $sce.RESOURCE_URL;\n      }\n    }\n\n\n    function addAttrInterpolateDirective(node, directives, value, name, allOrNothing) {\n      var trustedContext = getTrustedContext(node, name);\n      allOrNothing = ALL_OR_NOTHING_ATTRS[name] || allOrNothing;\n\n      var interpolateFn = $interpolate(value, true, trustedContext, allOrNothing);\n\n      // no interpolation found -> ignore\n      if (!interpolateFn) return;\n\n\n      if (name === \"multiple\" && nodeName_(node) === \"select\") {\n        throw $compileMinErr(\"selmulti\",\n            \"Binding to the 'multiple' attribute is not supported. Element: {0}\",\n            startingTag(node));\n      }\n\n      directives.push({\n        priority: 100,\n        compile: function() {\n            return {\n              pre: function attrInterpolatePreLinkFn(scope, element, attr) {\n                var $$observers = (attr.$$observers || (attr.$$observers = {}));\n\n                if (EVENT_HANDLER_ATTR_REGEXP.test(name)) {\n                  throw $compileMinErr('nodomevents',\n                      \"Interpolations for HTML DOM event attributes are disallowed.  Please use the \" +\n                          \"ng- versions (such as ng-click instead of onclick) instead.\");\n                }\n\n                // If the attribute has changed since last $interpolate()ed\n                var newValue = attr[name];\n                if (newValue !== value) {\n                  // we need to interpolate again since the attribute value has been updated\n                  // (e.g. by another directive's compile function)\n                  // ensure unset/empty values make interpolateFn falsy\n                  interpolateFn = newValue && $interpolate(newValue, true, trustedContext, allOrNothing);\n                  value = newValue;\n                }\n\n                // if attribute was updated so that there is no interpolation going on we don't want to\n                // register any observers\n                if (!interpolateFn) return;\n\n                // initialize attr object so that it's ready in case we need the value for isolate\n                // scope initialization, otherwise the value would not be available from isolate\n                // directive's linking fn during linking phase\n                attr[name] = interpolateFn(scope);\n\n                ($$observers[name] || ($$observers[name] = [])).$$inter = true;\n                (attr.$$observers && attr.$$observers[name].$$scope || scope).\n                  $watch(interpolateFn, function interpolateFnWatchAction(newValue, oldValue) {\n                    //special case for class attribute addition + removal\n                    //so that class changes can tap into the animation\n                    //hooks provided by the $animate service. Be sure to\n                    //skip animations when the first digest occurs (when\n                    //both the new and the old values are the same) since\n                    //the CSS classes are the non-interpolated values\n                    if (name === 'class' && newValue != oldValue) {\n                      attr.$updateClass(newValue, oldValue);\n                    } else {\n                      attr.$set(name, newValue);\n                    }\n                  });\n              }\n            };\n          }\n      });\n    }\n\n\n    /**\n     * This is a special jqLite.replaceWith, which can replace items which\n     * have no parents, provided that the containing jqLite collection is provided.\n     *\n     * @param {JqLite=} $rootElement The root of the compile tree. Used so that we can replace nodes\n     *                               in the root of the tree.\n     * @param {JqLite} elementsToRemove The jqLite element which we are going to replace. We keep\n     *                                  the shell, but replace its DOM node reference.\n     * @param {Node} newNode The new DOM node.\n     */\n    function replaceWith($rootElement, elementsToRemove, newNode) {\n      var firstElementToRemove = elementsToRemove[0],\n          removeCount = elementsToRemove.length,\n          parent = firstElementToRemove.parentNode,\n          i, ii;\n\n      if ($rootElement) {\n        for (i = 0, ii = $rootElement.length; i < ii; i++) {\n          if ($rootElement[i] == firstElementToRemove) {\n            $rootElement[i++] = newNode;\n            for (var j = i, j2 = j + removeCount - 1,\n                     jj = $rootElement.length;\n                 j < jj; j++, j2++) {\n              if (j2 < jj) {\n                $rootElement[j] = $rootElement[j2];\n              } else {\n                delete $rootElement[j];\n              }\n            }\n            $rootElement.length -= removeCount - 1;\n\n            // If the replaced element is also the jQuery .context then replace it\n            // .context is a deprecated jQuery api, so we should set it only when jQuery set it\n            // http://api.jquery.com/context/\n            if ($rootElement.context === firstElementToRemove) {\n              $rootElement.context = newNode;\n            }\n            break;\n          }\n        }\n      }\n\n      if (parent) {\n        parent.replaceChild(newNode, firstElementToRemove);\n      }\n\n      // TODO(perf): what's this document fragment for? is it needed? can we at least reuse it?\n      var fragment = document.createDocumentFragment();\n      fragment.appendChild(firstElementToRemove);\n\n      // Copy over user data (that includes Angular's $scope etc.). Don't copy private\n      // data here because there's no public interface in jQuery to do that and copying over\n      // event listeners (which is the main use of private data) wouldn't work anyway.\n      jqLite(newNode).data(jqLite(firstElementToRemove).data());\n\n      // Remove data of the replaced element. We cannot just call .remove()\n      // on the element it since that would deallocate scope that is needed\n      // for the new node. Instead, remove the data \"manually\".\n      if (!jQuery) {\n        delete jqLite.cache[firstElementToRemove[jqLite.expando]];\n      } else {\n        // jQuery 2.x doesn't expose the data storage. Use jQuery.cleanData to clean up after\n        // the replaced element. The cleanData version monkey-patched by Angular would cause\n        // the scope to be trashed and we do need the very same scope to work with the new\n        // element. However, we cannot just cache the non-patched version and use it here as\n        // that would break if another library patches the method after Angular does (one\n        // example is jQuery UI). Instead, set a flag indicating scope destroying should be\n        // skipped this one time.\n        skipDestroyOnNextJQueryCleanData = true;\n        jQuery.cleanData([firstElementToRemove]);\n      }\n\n      for (var k = 1, kk = elementsToRemove.length; k < kk; k++) {\n        var element = elementsToRemove[k];\n        jqLite(element).remove(); // must do this way to clean up expando\n        fragment.appendChild(element);\n        delete elementsToRemove[k];\n      }\n\n      elementsToRemove[0] = newNode;\n      elementsToRemove.length = 1;\n    }\n\n\n    function cloneAndAnnotateFn(fn, annotation) {\n      return extend(function() { return fn.apply(null, arguments); }, fn, annotation);\n    }\n\n\n    function invokeLinkFn(linkFn, scope, $element, attrs, controllers, transcludeFn) {\n      try {\n        linkFn(scope, $element, attrs, controllers, transcludeFn);\n      } catch (e) {\n        $exceptionHandler(e, startingTag($element));\n      }\n    }\n  }];\n}\n\nvar PREFIX_REGEXP = /^((?:x|data)[\\:\\-_])/i;\n/**\n * Converts all accepted directives format into proper directive name.\n * @param name Name to normalize\n */\nfunction directiveNormalize(name) {\n  return camelCase(name.replace(PREFIX_REGEXP, ''));\n}\n\n/**\n * @ngdoc type\n * @name $compile.directive.Attributes\n *\n * @description\n * A shared object between directive compile / linking functions which contains normalized DOM\n * element attributes. The values reflect current binding state `{{ }}`. The normalization is\n * needed since all of these are treated as equivalent in Angular:\n *\n * ```\n *    <span ng:bind=\"a\" ng-bind=\"a\" data-ng-bind=\"a\" x-ng-bind=\"a\">\n * ```\n */\n\n/**\n * @ngdoc property\n * @name $compile.directive.Attributes#$attr\n *\n * @description\n * A map of DOM element attribute names to the normalized name. This is\n * needed to do reverse lookup from normalized name back to actual name.\n */\n\n\n/**\n * @ngdoc method\n * @name $compile.directive.Attributes#$set\n * @kind function\n *\n * @description\n * Set DOM element attribute value.\n *\n *\n * @param {string} name Normalized element attribute name of the property to modify. The name is\n *          reverse-translated using the {@link ng.$compile.directive.Attributes#$attr $attr}\n *          property to the original name.\n * @param {string} value Value to set the attribute to. The value can be an interpolated string.\n */\n\n\n\n/**\n * Closure compiler type information\n */\n\nfunction nodesetLinkingFn(\n  /* angular.Scope */ scope,\n  /* NodeList */ nodeList,\n  /* Element */ rootElement,\n  /* function(Function) */ boundTranscludeFn\n) {}\n\nfunction directiveLinkingFn(\n  /* nodesetLinkingFn */ nodesetLinkingFn,\n  /* angular.Scope */ scope,\n  /* Node */ node,\n  /* Element */ rootElement,\n  /* function(Function) */ boundTranscludeFn\n) {}\n\nfunction tokenDifference(str1, str2) {\n  var values = '',\n      tokens1 = str1.split(/\\s+/),\n      tokens2 = str2.split(/\\s+/);\n\n  outer:\n  for (var i = 0; i < tokens1.length; i++) {\n    var token = tokens1[i];\n    for (var j = 0; j < tokens2.length; j++) {\n      if (token == tokens2[j]) continue outer;\n    }\n    values += (values.length > 0 ? ' ' : '') + token;\n  }\n  return values;\n}\n\nfunction removeComments(jqNodes) {\n  jqNodes = jqLite(jqNodes);\n  var i = jqNodes.length;\n\n  if (i <= 1) {\n    return jqNodes;\n  }\n\n  while (i--) {\n    var node = jqNodes[i];\n    if (node.nodeType === NODE_TYPE_COMMENT) {\n      splice.call(jqNodes, i, 1);\n    }\n  }\n  return jqNodes;\n}\n\nvar $controllerMinErr = minErr('$controller');\n\n/**\n * @ngdoc provider\n * @name $controllerProvider\n * @description\n * The {@link ng.$controller $controller service} is used by Angular to create new\n * controllers.\n *\n * This provider allows controller registration via the\n * {@link ng.$controllerProvider#register register} method.\n */\nfunction $ControllerProvider() {\n  var controllers = {},\n      globals = false,\n      CNTRL_REG = /^(\\S+)(\\s+as\\s+(\\w+))?$/;\n\n\n  /**\n   * @ngdoc method\n   * @name $controllerProvider#register\n   * @param {string|Object} name Controller name, or an object map of controllers where the keys are\n   *    the names and the values are the constructors.\n   * @param {Function|Array} constructor Controller constructor fn (optionally decorated with DI\n   *    annotations in the array notation).\n   */\n  this.register = function(name, constructor) {\n    assertNotHasOwnProperty(name, 'controller');\n    if (isObject(name)) {\n      extend(controllers, name);\n    } else {\n      controllers[name] = constructor;\n    }\n  };\n\n  /**\n   * @ngdoc method\n   * @name $controllerProvider#allowGlobals\n   * @description If called, allows `$controller` to find controller constructors on `window`\n   */\n  this.allowGlobals = function() {\n    globals = true;\n  };\n\n\n  this.$get = ['$injector', '$window', function($injector, $window) {\n\n    /**\n     * @ngdoc service\n     * @name $controller\n     * @requires $injector\n     *\n     * @param {Function|string} constructor If called with a function then it's considered to be the\n     *    controller constructor function. Otherwise it's considered to be a string which is used\n     *    to retrieve the controller constructor using the following steps:\n     *\n     *    * check if a controller with given name is registered via `$controllerProvider`\n     *    * check if evaluating the string on the current scope returns a constructor\n     *    * if $controllerProvider#allowGlobals, check `window[constructor]` on the global\n     *      `window` object (not recommended)\n     *\n     *    The string can use the `controller as property` syntax, where the controller instance is published\n     *    as the specified property on the `scope`; the `scope` must be injected into `locals` param for this\n     *    to work correctly.\n     *\n     * @param {Object} locals Injection locals for Controller.\n     * @return {Object} Instance of given controller.\n     *\n     * @description\n     * `$controller` service is responsible for instantiating controllers.\n     *\n     * It's just a simple call to {@link auto.$injector $injector}, but extracted into\n     * a service, so that one can override this service with [BC version](https://gist.github.com/1649788).\n     */\n    return function(expression, locals, later, ident) {\n      // PRIVATE API:\n      //   param `later` --- indicates that the controller's constructor is invoked at a later time.\n      //                     If true, $controller will allocate the object with the correct\n      //                     prototype chain, but will not invoke the controller until a returned\n      //                     callback is invoked.\n      //   param `ident` --- An optional label which overrides the label parsed from the controller\n      //                     expression, if any.\n      var instance, match, constructor, identifier;\n      later = later === true;\n      if (ident && isString(ident)) {\n        identifier = ident;\n      }\n\n      if (isString(expression)) {\n        match = expression.match(CNTRL_REG);\n        if (!match) {\n          throw $controllerMinErr('ctrlfmt',\n            \"Badly formed controller string '{0}'. \" +\n            \"Must match `__name__ as __id__` or `__name__`.\", expression);\n        }\n        constructor = match[1],\n        identifier = identifier || match[3];\n        expression = controllers.hasOwnProperty(constructor)\n            ? controllers[constructor]\n            : getter(locals.$scope, constructor, true) ||\n                (globals ? getter($window, constructor, true) : undefined);\n\n        assertArgFn(expression, constructor, true);\n      }\n\n      if (later) {\n        // Instantiate controller later:\n        // This machinery is used to create an instance of the object before calling the\n        // controller's constructor itself.\n        //\n        // This allows properties to be added to the controller before the constructor is\n        // invoked. Primarily, this is used for isolate scope bindings in $compile.\n        //\n        // This feature is not intended for use by applications, and is thus not documented\n        // publicly.\n        // Object creation: http://jsperf.com/create-constructor/2\n        var controllerPrototype = (isArray(expression) ?\n          expression[expression.length - 1] : expression).prototype;\n        instance = Object.create(controllerPrototype || null);\n\n        if (identifier) {\n          addIdentifier(locals, identifier, instance, constructor || expression.name);\n        }\n\n        return extend(function() {\n          $injector.invoke(expression, instance, locals, constructor);\n          return instance;\n        }, {\n          instance: instance,\n          identifier: identifier\n        });\n      }\n\n      instance = $injector.instantiate(expression, locals, constructor);\n\n      if (identifier) {\n        addIdentifier(locals, identifier, instance, constructor || expression.name);\n      }\n\n      return instance;\n    };\n\n    function addIdentifier(locals, identifier, instance, name) {\n      if (!(locals && isObject(locals.$scope))) {\n        throw minErr('$controller')('noscp',\n          \"Cannot export controller '{0}' as '{1}'! No $scope object provided via `locals`.\",\n          name, identifier);\n      }\n\n      locals.$scope[identifier] = instance;\n    }\n  }];\n}\n\n/**\n * @ngdoc service\n * @name $document\n * @requires $window\n *\n * @description\n * A {@link angular.element jQuery or jqLite} wrapper for the browser's `window.document` object.\n *\n * @example\n   <example module=\"documentExample\">\n     <file name=\"index.html\">\n       <div ng-controller=\"ExampleController\">\n         <p>$document title: <b ng-bind=\"title\"></b></p>\n         <p>window.document title: <b ng-bind=\"windowTitle\"></b></p>\n       </div>\n     </file>\n     <file name=\"script.js\">\n       angular.module('documentExample', [])\n         .controller('ExampleController', ['$scope', '$document', function($scope, $document) {\n           $scope.title = $document[0].title;\n           $scope.windowTitle = angular.element(window.document)[0].title;\n         }]);\n     </file>\n   </example>\n */\nfunction $DocumentProvider() {\n  this.$get = ['$window', function(window) {\n    return jqLite(window.document);\n  }];\n}\n\n/**\n * @ngdoc service\n * @name $exceptionHandler\n * @requires ng.$log\n *\n * @description\n * Any uncaught exception in angular expressions is delegated to this service.\n * The default implementation simply delegates to `$log.error` which logs it into\n * the browser console.\n *\n * In unit tests, if `angular-mocks.js` is loaded, this service is overridden by\n * {@link ngMock.$exceptionHandler mock $exceptionHandler} which aids in testing.\n *\n * ## Example:\n *\n * ```js\n *   angular.module('exceptionOverride', []).factory('$exceptionHandler', function() {\n *     return function(exception, cause) {\n *       exception.message += ' (caused by \"' + cause + '\")';\n *       throw exception;\n *     };\n *   });\n * ```\n *\n * This example will override the normal action of `$exceptionHandler`, to make angular\n * exceptions fail hard when they happen, instead of just logging to the console.\n *\n * <hr />\n * Note, that code executed in event-listeners (even those registered using jqLite's `on`/`bind`\n * methods) does not delegate exceptions to the {@link ng.$exceptionHandler $exceptionHandler}\n * (unless executed during a digest).\n *\n * If you wish, you can manually delegate exceptions, e.g.\n * `try { ... } catch(e) { $exceptionHandler(e); }`\n *\n * @param {Error} exception Exception associated with the error.\n * @param {string=} cause optional information about the context in which\n *       the error was thrown.\n *\n */\nfunction $ExceptionHandlerProvider() {\n  this.$get = ['$log', function($log) {\n    return function(exception, cause) {\n      $log.error.apply($log, arguments);\n    };\n  }];\n}\n\nvar APPLICATION_JSON = 'application/json';\nvar CONTENT_TYPE_APPLICATION_JSON = {'Content-Type': APPLICATION_JSON + ';charset=utf-8'};\nvar JSON_START = /^\\[|^\\{(?!\\{)/;\nvar JSON_ENDS = {\n  '[': /]$/,\n  '{': /}$/\n};\nvar JSON_PROTECTION_PREFIX = /^\\)\\]\\}',?\\n/;\n\nfunction defaultHttpResponseTransform(data, headers) {\n  if (isString(data)) {\n    // Strip json vulnerability protection prefix and trim whitespace\n    var tempData = data.replace(JSON_PROTECTION_PREFIX, '').trim();\n\n    if (tempData) {\n      var contentType = headers('Content-Type');\n      if ((contentType && (contentType.indexOf(APPLICATION_JSON) === 0)) || isJsonLike(tempData)) {\n        data = fromJson(tempData);\n      }\n    }\n  }\n\n  return data;\n}\n\nfunction isJsonLike(str) {\n    var jsonStart = str.match(JSON_START);\n    return jsonStart && JSON_ENDS[jsonStart[0]].test(str);\n}\n\n/**\n * Parse headers into key value object\n *\n * @param {string} headers Raw headers as a string\n * @returns {Object} Parsed headers as key value object\n */\nfunction parseHeaders(headers) {\n  var parsed = createMap(), key, val, i;\n\n  if (!headers) return parsed;\n\n  forEach(headers.split('\\n'), function(line) {\n    i = line.indexOf(':');\n    key = lowercase(trim(line.substr(0, i)));\n    val = trim(line.substr(i + 1));\n\n    if (key) {\n      parsed[key] = parsed[key] ? parsed[key] + ', ' + val : val;\n    }\n  });\n\n  return parsed;\n}\n\n\n/**\n * Returns a function that provides access to parsed headers.\n *\n * Headers are lazy parsed when first requested.\n * @see parseHeaders\n *\n * @param {(string|Object)} headers Headers to provide access to.\n * @returns {function(string=)} Returns a getter function which if called with:\n *\n *   - if called with single an argument returns a single header value or null\n *   - if called with no arguments returns an object containing all headers.\n */\nfunction headersGetter(headers) {\n  var headersObj = isObject(headers) ? headers : undefined;\n\n  return function(name) {\n    if (!headersObj) headersObj =  parseHeaders(headers);\n\n    if (name) {\n      var value = headersObj[lowercase(name)];\n      if (value === void 0) {\n        value = null;\n      }\n      return value;\n    }\n\n    return headersObj;\n  };\n}\n\n\n/**\n * Chain all given functions\n *\n * This function is used for both request and response transforming\n *\n * @param {*} data Data to transform.\n * @param {function(string=)} headers HTTP headers getter fn.\n * @param {number} status HTTP status code of the response.\n * @param {(Function|Array.<Function>)} fns Function or an array of functions.\n * @returns {*} Transformed data.\n */\nfunction transformData(data, headers, status, fns) {\n  if (isFunction(fns))\n    return fns(data, headers, status);\n\n  forEach(fns, function(fn) {\n    data = fn(data, headers, status);\n  });\n\n  return data;\n}\n\n\nfunction isSuccess(status) {\n  return 200 <= status && status < 300;\n}\n\n\n/**\n * @ngdoc provider\n * @name $httpProvider\n * @description\n * Use `$httpProvider` to change the default behavior of the {@link ng.$http $http} service.\n * */\nfunction $HttpProvider() {\n  /**\n   * @ngdoc property\n   * @name $httpProvider#defaults\n   * @description\n   *\n   * Object containing default values for all {@link ng.$http $http} requests.\n   *\n   * - **`defaults.cache`** - {Object} - an object built with {@link ng.$cacheFactory `$cacheFactory`}\n   * that will provide the cache for all requests who set their `cache` property to `true`.\n   * If you set the `default.cache = false` then only requests that specify their own custom\n   * cache object will be cached. See {@link $http#caching $http Caching} for more information.\n   *\n   * - **`defaults.xsrfCookieName`** - {string} - Name of cookie containing the XSRF token.\n   * Defaults value is `'XSRF-TOKEN'`.\n   *\n   * - **`defaults.xsrfHeaderName`** - {string} - Name of HTTP header to populate with the\n   * XSRF token. Defaults value is `'X-XSRF-TOKEN'`.\n   *\n   * - **`defaults.headers`** - {Object} - Default headers for all $http requests.\n   * Refer to {@link ng.$http#setting-http-headers $http} for documentation on\n   * setting default headers.\n   *     - **`defaults.headers.common`**\n   *     - **`defaults.headers.post`**\n   *     - **`defaults.headers.put`**\n   *     - **`defaults.headers.patch`**\n   *\n   **/\n  var defaults = this.defaults = {\n    // transform incoming response data\n    transformResponse: [defaultHttpResponseTransform],\n\n    // transform outgoing request data\n    transformRequest: [function(d) {\n      return isObject(d) && !isFile(d) && !isBlob(d) && !isFormData(d) ? toJson(d) : d;\n    }],\n\n    // default headers\n    headers: {\n      common: {\n        'Accept': 'application/json, text/plain, */*'\n      },\n      post:   shallowCopy(CONTENT_TYPE_APPLICATION_JSON),\n      put:    shallowCopy(CONTENT_TYPE_APPLICATION_JSON),\n      patch:  shallowCopy(CONTENT_TYPE_APPLICATION_JSON)\n    },\n\n    xsrfCookieName: 'XSRF-TOKEN',\n    xsrfHeaderName: 'X-XSRF-TOKEN'\n  };\n\n  var useApplyAsync = false;\n  /**\n   * @ngdoc method\n   * @name $httpProvider#useApplyAsync\n   * @description\n   *\n   * Configure $http service to combine processing of multiple http responses received at around\n   * the same time via {@link ng.$rootScope.Scope#$applyAsync $rootScope.$applyAsync}. This can result in\n   * significant performance improvement for bigger applications that make many HTTP requests\n   * concurrently (common during application bootstrap).\n   *\n   * Defaults to false. If no value is specifed, returns the current configured value.\n   *\n   * @param {boolean=} value If true, when requests are loaded, they will schedule a deferred\n   *    \"apply\" on the next tick, giving time for subsequent requests in a roughly ~10ms window\n   *    to load and share the same digest cycle.\n   *\n   * @returns {boolean|Object} If a value is specified, returns the $httpProvider for chaining.\n   *    otherwise, returns the current configured value.\n   **/\n  this.useApplyAsync = function(value) {\n    if (isDefined(value)) {\n      useApplyAsync = !!value;\n      return this;\n    }\n    return useApplyAsync;\n  };\n\n  /**\n   * @ngdoc property\n   * @name $httpProvider#interceptors\n   * @description\n   *\n   * Array containing service factories for all synchronous or asynchronous {@link ng.$http $http}\n   * pre-processing of request or postprocessing of responses.\n   *\n   * These service factories are ordered by request, i.e. they are applied in the same order as the\n   * array, on request, but reverse order, on response.\n   *\n   * {@link ng.$http#interceptors Interceptors detailed info}\n   **/\n  var interceptorFactories = this.interceptors = [];\n\n  this.$get = ['$httpBackend', '$browser', '$cacheFactory', '$rootScope', '$q', '$injector',\n      function($httpBackend, $browser, $cacheFactory, $rootScope, $q, $injector) {\n\n    var defaultCache = $cacheFactory('$http');\n\n    /**\n     * Interceptors stored in reverse order. Inner interceptors before outer interceptors.\n     * The reversal is needed so that we can build up the interception chain around the\n     * server request.\n     */\n    var reversedInterceptors = [];\n\n    forEach(interceptorFactories, function(interceptorFactory) {\n      reversedInterceptors.unshift(isString(interceptorFactory)\n          ? $injector.get(interceptorFactory) : $injector.invoke(interceptorFactory));\n    });\n\n    /**\n     * @ngdoc service\n     * @kind function\n     * @name $http\n     * @requires ng.$httpBackend\n     * @requires $cacheFactory\n     * @requires $rootScope\n     * @requires $q\n     * @requires $injector\n     *\n     * @description\n     * The `$http` service is a core Angular service that facilitates communication with the remote\n     * HTTP servers via the browser's [XMLHttpRequest](https://developer.mozilla.org/en/xmlhttprequest)\n     * object or via [JSONP](http://en.wikipedia.org/wiki/JSONP).\n     *\n     * For unit testing applications that use `$http` service, see\n     * {@link ngMock.$httpBackend $httpBackend mock}.\n     *\n     * For a higher level of abstraction, please check out the {@link ngResource.$resource\n     * $resource} service.\n     *\n     * The $http API is based on the {@link ng.$q deferred/promise APIs} exposed by\n     * the $q service. While for simple usage patterns this doesn't matter much, for advanced usage\n     * it is important to familiarize yourself with these APIs and the guarantees they provide.\n     *\n     *\n     * ## General usage\n     * The `$http` service is a function which takes a single argument — a configuration object —\n     * that is used to generate an HTTP request and returns  a {@link ng.$q promise}\n     * with two $http specific methods: `success` and `error`.\n     *\n     * ```js\n     *   // Simple GET request example :\n     *   $http.get('/someUrl').\n     *     success(function(data, status, headers, config) {\n     *       // this callback will be called asynchronously\n     *       // when the response is available\n     *     }).\n     *     error(function(data, status, headers, config) {\n     *       // called asynchronously if an error occurs\n     *       // or server returns response with an error status.\n     *     });\n     * ```\n     *\n     * ```js\n     *   // Simple POST request example (passing data) :\n     *   $http.post('/someUrl', {msg:'hello word!'}).\n     *     success(function(data, status, headers, config) {\n     *       // this callback will be called asynchronously\n     *       // when the response is available\n     *     }).\n     *     error(function(data, status, headers, config) {\n     *       // called asynchronously if an error occurs\n     *       // or server returns response with an error status.\n     *     });\n     * ```\n     *\n     *\n     * Since the returned value of calling the $http function is a `promise`, you can also use\n     * the `then` method to register callbacks, and these callbacks will receive a single argument –\n     * an object representing the response. See the API signature and type info below for more\n     * details.\n     *\n     * A response status code between 200 and 299 is considered a success status and\n     * will result in the success callback being called. Note that if the response is a redirect,\n     * XMLHttpRequest will transparently follow it, meaning that the error callback will not be\n     * called for such responses.\n     *\n     * ## Writing Unit Tests that use $http\n     * When unit testing (using {@link ngMock ngMock}), it is necessary to call\n     * {@link ngMock.$httpBackend#flush $httpBackend.flush()} to flush each pending\n     * request using trained responses.\n     *\n     * ```\n     * $httpBackend.expectGET(...);\n     * $http.get(...);\n     * $httpBackend.flush();\n     * ```\n     *\n     * ## Shortcut methods\n     *\n     * Shortcut methods are also available. All shortcut methods require passing in the URL, and\n     * request data must be passed in for POST/PUT requests.\n     *\n     * ```js\n     *   $http.get('/someUrl').success(successCallback);\n     *   $http.post('/someUrl', data).success(successCallback);\n     * ```\n     *\n     * Complete list of shortcut methods:\n     *\n     * - {@link ng.$http#get $http.get}\n     * - {@link ng.$http#head $http.head}\n     * - {@link ng.$http#post $http.post}\n     * - {@link ng.$http#put $http.put}\n     * - {@link ng.$http#delete $http.delete}\n     * - {@link ng.$http#jsonp $http.jsonp}\n     * - {@link ng.$http#patch $http.patch}\n     *\n     *\n     * ## Setting HTTP Headers\n     *\n     * The $http service will automatically add certain HTTP headers to all requests. These defaults\n     * can be fully configured by accessing the `$httpProvider.defaults.headers` configuration\n     * object, which currently contains this default configuration:\n     *\n     * - `$httpProvider.defaults.headers.common` (headers that are common for all requests):\n     *   - `Accept: application/json, text/plain, * / *`\n     * - `$httpProvider.defaults.headers.post`: (header defaults for POST requests)\n     *   - `Content-Type: application/json`\n     * - `$httpProvider.defaults.headers.put` (header defaults for PUT requests)\n     *   - `Content-Type: application/json`\n     *\n     * To add or overwrite these defaults, simply add or remove a property from these configuration\n     * objects. To add headers for an HTTP method other than POST or PUT, simply add a new object\n     * with the lowercased HTTP method name as the key, e.g.\n     * `$httpProvider.defaults.headers.get = { 'My-Header' : 'value' }.\n     *\n     * The defaults can also be set at runtime via the `$http.defaults` object in the same\n     * fashion. For example:\n     *\n     * ```\n     * module.run(function($http) {\n     *   $http.defaults.headers.common.Authorization = 'Basic YmVlcDpib29w'\n     * });\n     * ```\n     *\n     * In addition, you can supply a `headers` property in the config object passed when\n     * calling `$http(config)`, which overrides the defaults without changing them globally.\n     *\n     * To explicitly remove a header automatically added via $httpProvider.defaults.headers on a per request basis,\n     * Use the `headers` property, setting the desired header to `undefined`. For example:\n     *\n     * ```js\n     * var req = {\n     *  method: 'POST',\n     *  url: 'http://example.com',\n     *  headers: {\n     *    'Content-Type': undefined\n     *  },\n     *  data: { test: 'test' },\n     * }\n     *\n     * $http(req).success(function(){...}).error(function(){...});\n     * ```\n     *\n     * ## Transforming Requests and Responses\n     *\n     * Both requests and responses can be transformed using transformation functions: `transformRequest`\n     * and `transformResponse`. These properties can be a single function that returns\n     * the transformed value (`function(data, headersGetter, status)`) or an array of such transformation functions,\n     * which allows you to `push` or `unshift` a new transformation function into the transformation chain.\n     *\n     * ### Default Transformations\n     *\n     * The `$httpProvider` provider and `$http` service expose `defaults.transformRequest` and\n     * `defaults.transformResponse` properties. If a request does not provide its own transformations\n     * then these will be applied.\n     *\n     * You can augment or replace the default transformations by modifying these properties by adding to or\n     * replacing the array.\n     *\n     * Angular provides the following default transformations:\n     *\n     * Request transformations (`$httpProvider.defaults.transformRequest` and `$http.defaults.transformRequest`):\n     *\n     * - If the `data` property of the request configuration object contains an object, serialize it\n     *   into JSON format.\n     *\n     * Response transformations (`$httpProvider.defaults.transformResponse` and `$http.defaults.transformResponse`):\n     *\n     *  - If XSRF prefix is detected, strip it (see Security Considerations section below).\n     *  - If JSON response is detected, deserialize it using a JSON parser.\n     *\n     *\n     * ### Overriding the Default Transformations Per Request\n     *\n     * If you wish override the request/response transformations only for a single request then provide\n     * `transformRequest` and/or `transformResponse` properties on the configuration object passed\n     * into `$http`.\n     *\n     * Note that if you provide these properties on the config object the default transformations will be\n     * overwritten. If you wish to augment the default transformations then you must include them in your\n     * local transformation array.\n     *\n     * The following code demonstrates adding a new response transformation to be run after the default response\n     * transformations have been run.\n     *\n     * ```js\n     * function appendTransform(defaults, transform) {\n     *\n     *   // We can't guarantee that the default transformation is an array\n     *   defaults = angular.isArray(defaults) ? defaults : [defaults];\n     *\n     *   // Append the new transformation to the defaults\n     *   return defaults.concat(transform);\n     * }\n     *\n     * $http({\n     *   url: '...',\n     *   method: 'GET',\n     *   transformResponse: appendTransform($http.defaults.transformResponse, function(value) {\n     *     return doTransform(value);\n     *   })\n     * });\n     * ```\n     *\n     *\n     * ## Caching\n     *\n     * To enable caching, set the request configuration `cache` property to `true` (to use default\n     * cache) or to a custom cache object (built with {@link ng.$cacheFactory `$cacheFactory`}).\n     * When the cache is enabled, `$http` stores the response from the server in the specified\n     * cache. The next time the same request is made, the response is served from the cache without\n     * sending a request to the server.\n     *\n     * Note that even if the response is served from cache, delivery of the data is asynchronous in\n     * the same way that real requests are.\n     *\n     * If there are multiple GET requests for the same URL that should be cached using the same\n     * cache, but the cache is not populated yet, only one request to the server will be made and\n     * the remaining requests will be fulfilled using the response from the first request.\n     *\n     * You can change the default cache to a new object (built with\n     * {@link ng.$cacheFactory `$cacheFactory`}) by updating the\n     * {@link ng.$http#defaults `$http.defaults.cache`} property. All requests who set\n     * their `cache` property to `true` will now use this cache object.\n     *\n     * If you set the default cache to `false` then only requests that specify their own custom\n     * cache object will be cached.\n     *\n     * ## Interceptors\n     *\n     * Before you start creating interceptors, be sure to understand the\n     * {@link ng.$q $q and deferred/promise APIs}.\n     *\n     * For purposes of global error handling, authentication, or any kind of synchronous or\n     * asynchronous pre-processing of request or postprocessing of responses, it is desirable to be\n     * able to intercept requests before they are handed to the server and\n     * responses before they are handed over to the application code that\n     * initiated these requests. The interceptors leverage the {@link ng.$q\n     * promise APIs} to fulfill this need for both synchronous and asynchronous pre-processing.\n     *\n     * The interceptors are service factories that are registered with the `$httpProvider` by\n     * adding them to the `$httpProvider.interceptors` array. The factory is called and\n     * injected with dependencies (if specified) and returns the interceptor.\n     *\n     * There are two kinds of interceptors (and two kinds of rejection interceptors):\n     *\n     *   * `request`: interceptors get called with a http `config` object. The function is free to\n     *     modify the `config` object or create a new one. The function needs to return the `config`\n     *     object directly, or a promise containing the `config` or a new `config` object.\n     *   * `requestError`: interceptor gets called when a previous interceptor threw an error or\n     *     resolved with a rejection.\n     *   * `response`: interceptors get called with http `response` object. The function is free to\n     *     modify the `response` object or create a new one. The function needs to return the `response`\n     *     object directly, or as a promise containing the `response` or a new `response` object.\n     *   * `responseError`: interceptor gets called when a previous interceptor threw an error or\n     *     resolved with a rejection.\n     *\n     *\n     * ```js\n     *   // register the interceptor as a service\n     *   $provide.factory('myHttpInterceptor', function($q, dependency1, dependency2) {\n     *     return {\n     *       // optional method\n     *       'request': function(config) {\n     *         // do something on success\n     *         return config;\n     *       },\n     *\n     *       // optional method\n     *      'requestError': function(rejection) {\n     *         // do something on error\n     *         if (canRecover(rejection)) {\n     *           return responseOrNewPromise\n     *         }\n     *         return $q.reject(rejection);\n     *       },\n     *\n     *\n     *\n     *       // optional method\n     *       'response': function(response) {\n     *         // do something on success\n     *         return response;\n     *       },\n     *\n     *       // optional method\n     *      'responseError': function(rejection) {\n     *         // do something on error\n     *         if (canRecover(rejection)) {\n     *           return responseOrNewPromise\n     *         }\n     *         return $q.reject(rejection);\n     *       }\n     *     };\n     *   });\n     *\n     *   $httpProvider.interceptors.push('myHttpInterceptor');\n     *\n     *\n     *   // alternatively, register the interceptor via an anonymous factory\n     *   $httpProvider.interceptors.push(function($q, dependency1, dependency2) {\n     *     return {\n     *      'request': function(config) {\n     *          // same as above\n     *       },\n     *\n     *       'response': function(response) {\n     *          // same as above\n     *       }\n     *     };\n     *   });\n     * ```\n     *\n     * ## Security Considerations\n     *\n     * When designing web applications, consider security threats from:\n     *\n     * - [JSON vulnerability](http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx)\n     * - [XSRF](http://en.wikipedia.org/wiki/Cross-site_request_forgery)\n     *\n     * Both server and the client must cooperate in order to eliminate these threats. Angular comes\n     * pre-configured with strategies that address these issues, but for this to work backend server\n     * cooperation is required.\n     *\n     * ### JSON Vulnerability Protection\n     *\n     * A [JSON vulnerability](http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx)\n     * allows third party website to turn your JSON resource URL into\n     * [JSONP](http://en.wikipedia.org/wiki/JSONP) request under some conditions. To\n     * counter this your server can prefix all JSON requests with following string `\")]}',\\n\"`.\n     * Angular will automatically strip the prefix before processing it as JSON.\n     *\n     * For example if your server needs to return:\n     * ```js\n     * ['one','two']\n     * ```\n     *\n     * which is vulnerable to attack, your server can return:\n     * ```js\n     * )]}',\n     * ['one','two']\n     * ```\n     *\n     * Angular will strip the prefix, before processing the JSON.\n     *\n     *\n     * ### Cross Site Request Forgery (XSRF) Protection\n     *\n     * [XSRF](http://en.wikipedia.org/wiki/Cross-site_request_forgery) is a technique by which\n     * an unauthorized site can gain your user's private data. Angular provides a mechanism\n     * to counter XSRF. When performing XHR requests, the $http service reads a token from a cookie\n     * (by default, `XSRF-TOKEN`) and sets it as an HTTP header (`X-XSRF-TOKEN`). Since only\n     * JavaScript that runs on your domain could read the cookie, your server can be assured that\n     * the XHR came from JavaScript running on your domain. The header will not be set for\n     * cross-domain requests.\n     *\n     * To take advantage of this, your server needs to set a token in a JavaScript readable session\n     * cookie called `XSRF-TOKEN` on the first HTTP GET request. On subsequent XHR requests the\n     * server can verify that the cookie matches `X-XSRF-TOKEN` HTTP header, and therefore be sure\n     * that only JavaScript running on your domain could have sent the request. The token must be\n     * unique for each user and must be verifiable by the server (to prevent the JavaScript from\n     * making up its own tokens). We recommend that the token is a digest of your site's\n     * authentication cookie with a [salt](https://en.wikipedia.org/wiki/Salt_(cryptography&#41;)\n     * for added security.\n     *\n     * The name of the headers can be specified using the xsrfHeaderName and xsrfCookieName\n     * properties of either $httpProvider.defaults at config-time, $http.defaults at run-time,\n     * or the per-request config object.\n     *\n     *\n     * @param {object} config Object describing the request to be made and how it should be\n     *    processed. The object has following properties:\n     *\n     *    - **method** – `{string}` – HTTP method (e.g. 'GET', 'POST', etc)\n     *    - **url** – `{string}` – Absolute or relative URL of the resource that is being requested.\n     *    - **params** – `{Object.<string|Object>}` – Map of strings or objects which will be turned\n     *      to `?key1=value1&key2=value2` after the url. If the value is not a string, it will be\n     *      JSONified.\n     *    - **data** – `{string|Object}` – Data to be sent as the request message data.\n     *    - **headers** – `{Object}` – Map of strings or functions which return strings representing\n     *      HTTP headers to send to the server. If the return value of a function is null, the\n     *      header will not be sent.\n     *    - **xsrfHeaderName** – `{string}` – Name of HTTP header to populate with the XSRF token.\n     *    - **xsrfCookieName** – `{string}` – Name of cookie containing the XSRF token.\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     *      See {@link ng.$http#overriding-the-default-transformations-per-request\n     *      Overriding the Default Transformations}\n     *    - **transformResponse** –\n     *      `{function(data, headersGetter, status)|Array.<function(data, headersGetter, status)>}` –\n     *      transform function or an array of such functions. The transform function takes the http\n     *      response body, headers and status and returns its transformed (typically deserialized) version.\n     *      See {@link ng.$http#overriding-the-default-transformations-per-request\n     *      Overriding the Default Transformations}\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}\n     *      that should abort the request when resolved.\n     *    - **withCredentials** - `{boolean}` - whether to set the `withCredentials` flag on the\n     *      XHR object. See [requests with credentials](https://developer.mozilla.org/docs/Web/HTTP/Access_control_CORS#Requests_with_credentials)\n     *      for more information.\n     *    - **responseType** - `{string}` - see\n     *      [requestType](https://developer.mozilla.org/en-US/docs/DOM/XMLHttpRequest#responseType).\n     *\n     * @returns {HttpPromise} Returns a {@link ng.$q promise} object with the\n     *   standard `then` method and two http specific methods: `success` and `error`. The `then`\n     *   method takes two arguments a success and an error callback which will be called with a\n     *   response object. The `success` and `error` methods take a single argument - a function that\n     *   will be called when the request succeeds or fails respectively. The arguments passed into\n     *   these functions are destructured representation of the response object passed into the\n     *   `then` method. The response object has these properties:\n     *\n     *   - **data** – `{string|Object}` – The response body transformed with the transform\n     *     functions.\n     *   - **status** – `{number}` – HTTP status code of the response.\n     *   - **headers** – `{function([headerName])}` – Header getter function.\n     *   - **config** – `{Object}` – The configuration object that was used to generate the request.\n     *   - **statusText** – `{string}` – HTTP status text of the response.\n     *\n     * @property {Array.<Object>} pendingRequests Array of config objects for currently pending\n     *   requests. This is primarily meant to be used for debugging purposes.\n     *\n     *\n     * @example\n<example module=\"httpExample\">\n<file name=\"index.html\">\n  <div ng-controller=\"FetchController\">\n    <select ng-model=\"method\">\n      <option>GET</option>\n      <option>JSONP</option>\n    </select>\n    <input type=\"text\" ng-model=\"url\" size=\"80\"/>\n    <button id=\"fetchbtn\" ng-click=\"fetch()\">fetch</button><br>\n    <button id=\"samplegetbtn\" ng-click=\"updateModel('GET', 'http-hello.html')\">Sample GET</button>\n    <button id=\"samplejsonpbtn\"\n      ng-click=\"updateModel('JSONP',\n                    'https://angularjs.org/greet.php?callback=JSON_CALLBACK&name=Super%20Hero')\">\n      Sample JSONP\n    </button>\n    <button id=\"invalidjsonpbtn\"\n      ng-click=\"updateModel('JSONP', 'https://angularjs.org/doesntexist&callback=JSON_CALLBACK')\">\n        Invalid JSONP\n      </button>\n    <pre>http status code: {{status}}</pre>\n    <pre>http response data: {{data}}</pre>\n  </div>\n</file>\n<file name=\"script.js\">\n  angular.module('httpExample', [])\n    .controller('FetchController', ['$scope', '$http', '$templateCache',\n      function($scope, $http, $templateCache) {\n        $scope.method = 'GET';\n        $scope.url = 'http-hello.html';\n\n        $scope.fetch = function() {\n          $scope.code = null;\n          $scope.response = null;\n\n          $http({method: $scope.method, url: $scope.url, cache: $templateCache}).\n            success(function(data, status) {\n              $scope.status = status;\n              $scope.data = data;\n            }).\n            error(function(data, status) {\n              $scope.data = data || \"Request failed\";\n              $scope.status = status;\n          });\n        };\n\n        $scope.updateModel = function(method, url) {\n          $scope.method = method;\n          $scope.url = url;\n        };\n      }]);\n</file>\n<file name=\"http-hello.html\">\n  Hello, $http!\n</file>\n<file name=\"protractor.js\" type=\"protractor\">\n  var status = element(by.binding('status'));\n  var data = element(by.binding('data'));\n  var fetchBtn = element(by.id('fetchbtn'));\n  var sampleGetBtn = element(by.id('samplegetbtn'));\n  var sampleJsonpBtn = element(by.id('samplejsonpbtn'));\n  var invalidJsonpBtn = element(by.id('invalidjsonpbtn'));\n\n  it('should make an xhr GET request', function() {\n    sampleGetBtn.click();\n    fetchBtn.click();\n    expect(status.getText()).toMatch('200');\n    expect(data.getText()).toMatch(/Hello, \\$http!/);\n  });\n\n// Commented out due to flakes. See https://github.com/angular/angular.js/issues/9185\n// it('should make a JSONP request to angularjs.org', function() {\n//   sampleJsonpBtn.click();\n//   fetchBtn.click();\n//   expect(status.getText()).toMatch('200');\n//   expect(data.getText()).toMatch(/Super Hero!/);\n// });\n\n  it('should make JSONP request to invalid URL and invoke the error handler',\n      function() {\n    invalidJsonpBtn.click();\n    fetchBtn.click();\n    expect(status.getText()).toMatch('0');\n    expect(data.getText()).toMatch('Request failed');\n  });\n</file>\n</example>\n     */\n    function $http(requestConfig) {\n\n      if (!angular.isObject(requestConfig)) {\n        throw minErr('$http')('badreq', 'Http request configuration must be an object.  Received: {0}', requestConfig);\n      }\n\n      var config = extend({\n        method: 'get',\n        transformRequest: defaults.transformRequest,\n        transformResponse: defaults.transformResponse\n      }, requestConfig);\n\n      config.headers = mergeHeaders(requestConfig);\n      config.method = uppercase(config.method);\n\n      var serverRequest = function(config) {\n        var headers = config.headers;\n        var reqData = transformData(config.data, headersGetter(headers), undefined, config.transformRequest);\n\n        // strip content-type if data is undefined\n        if (isUndefined(reqData)) {\n          forEach(headers, function(value, header) {\n            if (lowercase(header) === 'content-type') {\n                delete headers[header];\n            }\n          });\n        }\n\n        if (isUndefined(config.withCredentials) && !isUndefined(defaults.withCredentials)) {\n          config.withCredentials = defaults.withCredentials;\n        }\n\n        // send request\n        return sendReq(config, reqData).then(transformResponse, transformResponse);\n      };\n\n      var chain = [serverRequest, undefined];\n      var promise = $q.when(config);\n\n      // apply interceptors\n      forEach(reversedInterceptors, function(interceptor) {\n        if (interceptor.request || interceptor.requestError) {\n          chain.unshift(interceptor.request, interceptor.requestError);\n        }\n        if (interceptor.response || interceptor.responseError) {\n          chain.push(interceptor.response, interceptor.responseError);\n        }\n      });\n\n      while (chain.length) {\n        var thenFn = chain.shift();\n        var rejectFn = chain.shift();\n\n        promise = promise.then(thenFn, rejectFn);\n      }\n\n      promise.success = function(fn) {\n        promise.then(function(response) {\n          fn(response.data, response.status, response.headers, config);\n        });\n        return promise;\n      };\n\n      promise.error = function(fn) {\n        promise.then(null, function(response) {\n          fn(response.data, response.status, response.headers, config);\n        });\n        return promise;\n      };\n\n      return promise;\n\n      function transformResponse(response) {\n        // make a copy since the response must be cacheable\n        var resp = extend({}, response);\n        if (!response.data) {\n          resp.data = response.data;\n        } else {\n          resp.data = transformData(response.data, response.headers, response.status, config.transformResponse);\n        }\n        return (isSuccess(response.status))\n          ? resp\n          : $q.reject(resp);\n      }\n\n      function executeHeaderFns(headers) {\n        var headerContent, processedHeaders = {};\n\n        forEach(headers, function(headerFn, header) {\n          if (isFunction(headerFn)) {\n            headerContent = headerFn();\n            if (headerContent != null) {\n              processedHeaders[header] = headerContent;\n            }\n          } else {\n            processedHeaders[header] = headerFn;\n          }\n        });\n\n        return processedHeaders;\n      }\n\n      function mergeHeaders(config) {\n        var defHeaders = defaults.headers,\n            reqHeaders = extend({}, config.headers),\n            defHeaderName, lowercaseDefHeaderName, reqHeaderName;\n\n        defHeaders = extend({}, defHeaders.common, defHeaders[lowercase(config.method)]);\n\n        // using for-in instead of forEach to avoid unecessary iteration after header has been found\n        defaultHeadersIteration:\n        for (defHeaderName in defHeaders) {\n          lowercaseDefHeaderName = lowercase(defHeaderName);\n\n          for (reqHeaderName in reqHeaders) {\n            if (lowercase(reqHeaderName) === lowercaseDefHeaderName) {\n              continue defaultHeadersIteration;\n            }\n          }\n\n          reqHeaders[defHeaderName] = defHeaders[defHeaderName];\n        }\n\n        // execute if header value is a function for merged headers\n        return executeHeaderFns(reqHeaders);\n      }\n    }\n\n    $http.pendingRequests = [];\n\n    /**\n     * @ngdoc method\n     * @name $http#get\n     *\n     * @description\n     * Shortcut method to perform `GET` request.\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name $http#delete\n     *\n     * @description\n     * Shortcut method to perform `DELETE` request.\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name $http#head\n     *\n     * @description\n     * Shortcut method to perform `HEAD` request.\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name $http#jsonp\n     *\n     * @description\n     * Shortcut method to perform `JSONP` request.\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request.\n     *                     The name of the callback should be the string `JSON_CALLBACK`.\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n    createShortMethods('get', 'delete', 'head', 'jsonp');\n\n    /**\n     * @ngdoc method\n     * @name $http#post\n     *\n     * @description\n     * Shortcut method to perform `POST` request.\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {*} data Request content\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name $http#put\n     *\n     * @description\n     * Shortcut method to perform `PUT` request.\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {*} data Request content\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n     /**\n      * @ngdoc method\n      * @name $http#patch\n      *\n      * @description\n      * Shortcut method to perform `PATCH` request.\n      *\n      * @param {string} url Relative or absolute URL specifying the destination of the request\n      * @param {*} data Request content\n      * @param {Object=} config Optional configuration object\n      * @returns {HttpPromise} Future object\n      */\n    createShortMethodsWithData('post', 'put', 'patch');\n\n        /**\n         * @ngdoc property\n         * @name $http#defaults\n         *\n         * @description\n         * Runtime equivalent of the `$httpProvider.defaults` property. Allows configuration of\n         * default headers, withCredentials as well as request and response transformations.\n         *\n         * See \"Setting HTTP Headers\" and \"Transforming Requests and Responses\" sections above.\n         */\n    $http.defaults = defaults;\n\n\n    return $http;\n\n\n    function createShortMethods(names) {\n      forEach(arguments, function(name) {\n        $http[name] = function(url, config) {\n          return $http(extend(config || {}, {\n            method: name,\n            url: url\n          }));\n        };\n      });\n    }\n\n\n    function createShortMethodsWithData(name) {\n      forEach(arguments, function(name) {\n        $http[name] = function(url, data, config) {\n          return $http(extend(config || {}, {\n            method: name,\n            url: url,\n            data: data\n          }));\n        };\n      });\n    }\n\n\n    /**\n     * Makes the request.\n     *\n     * !!! ACCESSES CLOSURE VARS:\n     * $httpBackend, defaults, $log, $rootScope, defaultCache, $http.pendingRequests\n     */\n    function sendReq(config, reqData) {\n      var deferred = $q.defer(),\n          promise = deferred.promise,\n          cache,\n          cachedResp,\n          reqHeaders = config.headers,\n          url = buildUrl(config.url, config.params);\n\n      $http.pendingRequests.push(config);\n      promise.then(removePendingReq, removePendingReq);\n\n\n      if ((config.cache || defaults.cache) && config.cache !== false &&\n          (config.method === 'GET' || config.method === 'JSONP')) {\n        cache = isObject(config.cache) ? config.cache\n              : isObject(defaults.cache) ? defaults.cache\n              : defaultCache;\n      }\n\n      if (cache) {\n        cachedResp = cache.get(url);\n        if (isDefined(cachedResp)) {\n          if (isPromiseLike(cachedResp)) {\n            // cached request has already been sent, but there is no response yet\n            cachedResp.then(resolvePromiseWithResult, resolvePromiseWithResult);\n          } else {\n            // serving from cache\n            if (isArray(cachedResp)) {\n              resolvePromise(cachedResp[1], cachedResp[0], shallowCopy(cachedResp[2]), cachedResp[3]);\n            } else {\n              resolvePromise(cachedResp, 200, {}, 'OK');\n            }\n          }\n        } else {\n          // put the promise for the non-transformed response into cache as a placeholder\n          cache.put(url, promise);\n        }\n      }\n\n\n      // if we won't have the response in cache, set the xsrf headers and\n      // send the request to the backend\n      if (isUndefined(cachedResp)) {\n        var xsrfValue = urlIsSameOrigin(config.url)\n            ? $browser.cookies()[config.xsrfCookieName || defaults.xsrfCookieName]\n            : undefined;\n        if (xsrfValue) {\n          reqHeaders[(config.xsrfHeaderName || defaults.xsrfHeaderName)] = xsrfValue;\n        }\n\n        $httpBackend(config.method, url, reqData, done, reqHeaders, config.timeout,\n            config.withCredentials, config.responseType);\n      }\n\n      return promise;\n\n\n      /**\n       * Callback registered to $httpBackend():\n       *  - caches the response if desired\n       *  - resolves the raw $http promise\n       *  - calls $apply\n       */\n      function done(status, response, headersString, statusText) {\n        if (cache) {\n          if (isSuccess(status)) {\n            cache.put(url, [status, response, parseHeaders(headersString), statusText]);\n          } else {\n            // remove promise from the cache\n            cache.remove(url);\n          }\n        }\n\n        function resolveHttpPromise() {\n          resolvePromise(response, status, headersString, statusText);\n        }\n\n        if (useApplyAsync) {\n          $rootScope.$applyAsync(resolveHttpPromise);\n        } else {\n          resolveHttpPromise();\n          if (!$rootScope.$$phase) $rootScope.$apply();\n        }\n      }\n\n\n      /**\n       * Resolves the raw $http promise.\n       */\n      function resolvePromise(response, status, headers, statusText) {\n        // normalize internal statuses to 0\n        status = Math.max(status, 0);\n\n        (isSuccess(status) ? deferred.resolve : deferred.reject)({\n          data: response,\n          status: status,\n          headers: headersGetter(headers),\n          config: config,\n          statusText: statusText\n        });\n      }\n\n      function resolvePromiseWithResult(result) {\n        resolvePromise(result.data, result.status, shallowCopy(result.headers()), result.statusText);\n      }\n\n      function removePendingReq() {\n        var idx = $http.pendingRequests.indexOf(config);\n        if (idx !== -1) $http.pendingRequests.splice(idx, 1);\n      }\n    }\n\n\n    function buildUrl(url, params) {\n      if (!params) return url;\n      var parts = [];\n      forEachSorted(params, function(value, key) {\n        if (value === null || isUndefined(value)) return;\n        if (!isArray(value)) value = [value];\n\n        forEach(value, function(v) {\n          if (isObject(v)) {\n            if (isDate(v)) {\n              v = v.toISOString();\n            } else {\n              v = toJson(v);\n            }\n          }\n          parts.push(encodeUriQuery(key) + '=' +\n                     encodeUriQuery(v));\n        });\n      });\n      if (parts.length > 0) {\n        url += ((url.indexOf('?') == -1) ? '?' : '&') + parts.join('&');\n      }\n      return url;\n    }\n  }];\n}\n\nfunction createXhr() {\n    return new window.XMLHttpRequest();\n}\n\n/**\n * @ngdoc service\n * @name $httpBackend\n * @requires $window\n * @requires $document\n *\n * @description\n * HTTP backend used by the {@link ng.$http service} that delegates to\n * XMLHttpRequest object or JSONP and deals with browser incompatibilities.\n *\n * You should never need to use this service directly, instead use the higher-level abstractions:\n * {@link ng.$http $http} or {@link ngResource.$resource $resource}.\n *\n * During testing this implementation is swapped with {@link ngMock.$httpBackend mock\n * $httpBackend} which can be trained with responses.\n */\nfunction $HttpBackendProvider() {\n  this.$get = ['$browser', '$window', '$document', function($browser, $window, $document) {\n    return createHttpBackend($browser, createXhr, $browser.defer, $window.angular.callbacks, $document[0]);\n  }];\n}\n\nfunction createHttpBackend($browser, createXhr, $browserDefer, callbacks, rawDocument) {\n  // TODO(vojta): fix the signature\n  return function(method, url, post, callback, headers, timeout, withCredentials, responseType) {\n    $browser.$$incOutstandingRequestCount();\n    url = url || $browser.url();\n\n    if (lowercase(method) == 'jsonp') {\n      var callbackId = '_' + (callbacks.counter++).toString(36);\n      callbacks[callbackId] = function(data) {\n        callbacks[callbackId].data = data;\n        callbacks[callbackId].called = true;\n      };\n\n      var jsonpDone = jsonpReq(url.replace('JSON_CALLBACK', 'angular.callbacks.' + callbackId),\n          callbackId, function(status, text) {\n        completeRequest(callback, status, callbacks[callbackId].data, \"\", text);\n        callbacks[callbackId] = noop;\n      });\n    } else {\n\n      var xhr = createXhr();\n\n      xhr.open(method, url, true);\n      forEach(headers, function(value, key) {\n        if (isDefined(value)) {\n            xhr.setRequestHeader(key, value);\n        }\n      });\n\n      xhr.onload = function requestLoaded() {\n        var statusText = xhr.statusText || '';\n\n        // responseText is the old-school way of retrieving response (supported by IE8 & 9)\n        // response/responseType properties were introduced in XHR Level2 spec (supported by IE10)\n        var response = ('response' in xhr) ? xhr.response : xhr.responseText;\n\n        // normalize IE9 bug (http://bugs.jquery.com/ticket/1450)\n        var status = xhr.status === 1223 ? 204 : xhr.status;\n\n        // fix status code when it is 0 (0 status is undocumented).\n        // Occurs when accessing file resources or on Android 4.1 stock browser\n        // while retrieving files from application cache.\n        if (status === 0) {\n          status = response ? 200 : urlResolve(url).protocol == 'file' ? 404 : 0;\n        }\n\n        completeRequest(callback,\n            status,\n            response,\n            xhr.getAllResponseHeaders(),\n            statusText);\n      };\n\n      var requestError = function() {\n        // The response is always empty\n        // See https://xhr.spec.whatwg.org/#request-error-steps and https://fetch.spec.whatwg.org/#concept-network-error\n        completeRequest(callback, -1, null, null, '');\n      };\n\n      xhr.onerror = requestError;\n      xhr.onabort = requestError;\n\n      if (withCredentials) {\n        xhr.withCredentials = true;\n      }\n\n      if (responseType) {\n        try {\n          xhr.responseType = responseType;\n        } catch (e) {\n          // WebKit added support for the json responseType value on 09/03/2013\n          // https://bugs.webkit.org/show_bug.cgi?id=73648. Versions of Safari prior to 7 are\n          // known to throw when setting the value \"json\" as the response type. Other older\n          // browsers implementing the responseType\n          //\n          // The json response type can be ignored if not supported, because JSON payloads are\n          // parsed on the client-side regardless.\n          if (responseType !== 'json') {\n            throw e;\n          }\n        }\n      }\n\n      xhr.send(post || null);\n    }\n\n    if (timeout > 0) {\n      var timeoutId = $browserDefer(timeoutRequest, timeout);\n    } else if (isPromiseLike(timeout)) {\n      timeout.then(timeoutRequest);\n    }\n\n\n    function timeoutRequest() {\n      jsonpDone && jsonpDone();\n      xhr && xhr.abort();\n    }\n\n    function completeRequest(callback, status, response, headersString, statusText) {\n      // cancel timeout and subsequent timeout promise resolution\n      if (timeoutId !== undefined) {\n        $browserDefer.cancel(timeoutId);\n      }\n      jsonpDone = xhr = null;\n\n      callback(status, response, headersString, statusText);\n      $browser.$$completeOutstandingRequest(noop);\n    }\n  };\n\n  function jsonpReq(url, callbackId, done) {\n    // we can't use jQuery/jqLite here because jQuery does crazy shit with script elements, e.g.:\n    // - fetches local scripts via XHR and evals them\n    // - adds and immediately removes script elements from the document\n    var script = rawDocument.createElement('script'), callback = null;\n    script.type = \"text/javascript\";\n    script.src = url;\n    script.async = true;\n\n    callback = function(event) {\n      removeEventListenerFn(script, \"load\", callback);\n      removeEventListenerFn(script, \"error\", callback);\n      rawDocument.body.removeChild(script);\n      script = null;\n      var status = -1;\n      var text = \"unknown\";\n\n      if (event) {\n        if (event.type === \"load\" && !callbacks[callbackId].called) {\n          event = { type: \"error\" };\n        }\n        text = event.type;\n        status = event.type === \"error\" ? 404 : 200;\n      }\n\n      if (done) {\n        done(status, text);\n      }\n    };\n\n    addEventListenerFn(script, \"load\", callback);\n    addEventListenerFn(script, \"error\", callback);\n    rawDocument.body.appendChild(script);\n    return callback;\n  }\n}\n\nvar $interpolateMinErr = minErr('$interpolate');\n\n/**\n * @ngdoc provider\n * @name $interpolateProvider\n *\n * @description\n *\n * Used for configuring the interpolation markup. Defaults to `{{` and `}}`.\n *\n * @example\n<example module=\"customInterpolationApp\">\n<file name=\"index.html\">\n<script>\n  var customInterpolationApp = angular.module('customInterpolationApp', []);\n\n  customInterpolationApp.config(function($interpolateProvider) {\n    $interpolateProvider.startSymbol('//');\n    $interpolateProvider.endSymbol('//');\n  });\n\n\n  customInterpolationApp.controller('DemoController', function() {\n      this.label = \"This binding is brought you by // interpolation symbols.\";\n  });\n</script>\n<div ng-app=\"App\" ng-controller=\"DemoController as demo\">\n    //demo.label//\n</div>\n</file>\n<file name=\"protractor.js\" type=\"protractor\">\n  it('should interpolate binding with custom symbols', function() {\n    expect(element(by.binding('demo.label')).getText()).toBe('This binding is brought you by // interpolation symbols.');\n  });\n</file>\n</example>\n */\nfunction $InterpolateProvider() {\n  var startSymbol = '{{';\n  var endSymbol = '}}';\n\n  /**\n   * @ngdoc method\n   * @name $interpolateProvider#startSymbol\n   * @description\n   * Symbol to denote start of expression in the interpolated string. Defaults to `{{`.\n   *\n   * @param {string=} value new value to set the starting symbol to.\n   * @returns {string|self} Returns the symbol when used as getter and self if used as setter.\n   */\n  this.startSymbol = function(value) {\n    if (value) {\n      startSymbol = value;\n      return this;\n    } else {\n      return startSymbol;\n    }\n  };\n\n  /**\n   * @ngdoc method\n   * @name $interpolateProvider#endSymbol\n   * @description\n   * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.\n   *\n   * @param {string=} value new value to set the ending symbol to.\n   * @returns {string|self} Returns the symbol when used as getter and self if used as setter.\n   */\n  this.endSymbol = function(value) {\n    if (value) {\n      endSymbol = value;\n      return this;\n    } else {\n      return endSymbol;\n    }\n  };\n\n\n  this.$get = ['$parse', '$exceptionHandler', '$sce', function($parse, $exceptionHandler, $sce) {\n    var startSymbolLength = startSymbol.length,\n        endSymbolLength = endSymbol.length,\n        escapedStartRegexp = new RegExp(startSymbol.replace(/./g, escape), 'g'),\n        escapedEndRegexp = new RegExp(endSymbol.replace(/./g, escape), 'g');\n\n    function escape(ch) {\n      return '\\\\\\\\\\\\' + ch;\n    }\n\n    /**\n     * @ngdoc service\n     * @name $interpolate\n     * @kind function\n     *\n     * @requires $parse\n     * @requires $sce\n     *\n     * @description\n     *\n     * Compiles a string with markup into an interpolation function. This service is used by the\n     * HTML {@link ng.$compile $compile} service for data binding. See\n     * {@link ng.$interpolateProvider $interpolateProvider} for configuring the\n     * interpolation markup.\n     *\n     *\n     * ```js\n     *   var $interpolate = ...; // injected\n     *   var exp = $interpolate('Hello {{name | uppercase}}!');\n     *   expect(exp({name:'Angular'}).toEqual('Hello ANGULAR!');\n     * ```\n     *\n     * `$interpolate` takes an optional fourth argument, `allOrNothing`. If `allOrNothing` is\n     * `true`, the interpolation function will return `undefined` unless all embedded expressions\n     * evaluate to a value other than `undefined`.\n     *\n     * ```js\n     *   var $interpolate = ...; // injected\n     *   var context = {greeting: 'Hello', name: undefined };\n     *\n     *   // default \"forgiving\" mode\n     *   var exp = $interpolate('{{greeting}} {{name}}!');\n     *   expect(exp(context)).toEqual('Hello !');\n     *\n     *   // \"allOrNothing\" mode\n     *   exp = $interpolate('{{greeting}} {{name}}!', false, null, true);\n     *   expect(exp(context)).toBeUndefined();\n     *   context.name = 'Angular';\n     *   expect(exp(context)).toEqual('Hello Angular!');\n     * ```\n     *\n     * `allOrNothing` is useful for interpolating URLs. `ngSrc` and `ngSrcset` use this behavior.\n     *\n     * ####Escaped Interpolation\n     * $interpolate provides a mechanism for escaping interpolation markers. Start and end markers\n     * can be escaped by preceding each of their characters with a REVERSE SOLIDUS U+005C (backslash).\n     * It will be rendered as a regular start/end marker, and will not be interpreted as an expression\n     * or binding.\n     *\n     * This enables web-servers to prevent script injection attacks and defacing attacks, to some\n     * degree, while also enabling code examples to work without relying on the\n     * {@link ng.directive:ngNonBindable ngNonBindable} directive.\n     *\n     * **For security purposes, it is strongly encouraged that web servers escape user-supplied data,\n     * replacing angle brackets (&lt;, &gt;) with &amp;lt; and &amp;gt; respectively, and replacing all\n     * interpolation start/end markers with their escaped counterparts.**\n     *\n     * Escaped interpolation markers are only replaced with the actual interpolation markers in rendered\n     * output when the $interpolate service processes the text. So, for HTML elements interpolated\n     * by {@link ng.$compile $compile}, or otherwise interpolated with the `mustHaveExpression` parameter\n     * set to `true`, the interpolated text must contain an unescaped interpolation expression. As such,\n     * this is typically useful only when user-data is used in rendering a template from the server, or\n     * when otherwise untrusted data is used by a directive.\n     *\n     * <example>\n     *  <file name=\"index.html\">\n     *    <div ng-init=\"username='A user'\">\n     *      <p ng-init=\"apptitle='Escaping demo'\">{{apptitle}}: \\{\\{ username = \"defaced value\"; \\}\\}\n     *        </p>\n     *      <p><strong>{{username}}</strong> attempts to inject code which will deface the\n     *        application, but fails to accomplish their task, because the server has correctly\n     *        escaped the interpolation start/end markers with REVERSE SOLIDUS U+005C (backslash)\n     *        characters.</p>\n     *      <p>Instead, the result of the attempted script injection is visible, and can be removed\n     *        from the database by an administrator.</p>\n     *    </div>\n     *  </file>\n     * </example>\n     *\n     * @param {string} text The text with markup to interpolate.\n     * @param {boolean=} mustHaveExpression if set to true then the interpolation string must have\n     *    embedded expression in order to return an interpolation function. Strings with no\n     *    embedded expression will return null for the interpolation function.\n     * @param {string=} trustedContext when provided, the returned function passes the interpolated\n     *    result through {@link ng.$sce#getTrusted $sce.getTrusted(interpolatedResult,\n     *    trustedContext)} before returning it.  Refer to the {@link ng.$sce $sce} service that\n     *    provides Strict Contextual Escaping for details.\n     * @param {boolean=} allOrNothing if `true`, then the returned function returns undefined\n     *    unless all embedded expressions evaluate to a value other than `undefined`.\n     * @returns {function(context)} an interpolation function which is used to compute the\n     *    interpolated string. The function has these parameters:\n     *\n     * - `context`: evaluation context for all expressions embedded in the interpolated text\n     */\n    function $interpolate(text, mustHaveExpression, trustedContext, allOrNothing) {\n      allOrNothing = !!allOrNothing;\n      var startIndex,\n          endIndex,\n          index = 0,\n          expressions = [],\n          parseFns = [],\n          textLength = text.length,\n          exp,\n          concat = [],\n          expressionPositions = [];\n\n      while (index < textLength) {\n        if (((startIndex = text.indexOf(startSymbol, index)) != -1) &&\n             ((endIndex = text.indexOf(endSymbol, startIndex + startSymbolLength)) != -1)) {\n          if (index !== startIndex) {\n            concat.push(unescapeText(text.substring(index, startIndex)));\n          }\n          exp = text.substring(startIndex + startSymbolLength, endIndex);\n          expressions.push(exp);\n          parseFns.push($parse(exp, parseStringifyInterceptor));\n          index = endIndex + endSymbolLength;\n          expressionPositions.push(concat.length);\n          concat.push('');\n        } else {\n          // we did not find an interpolation, so we have to add the remainder to the separators array\n          if (index !== textLength) {\n            concat.push(unescapeText(text.substring(index)));\n          }\n          break;\n        }\n      }\n\n      // Concatenating expressions makes it hard to reason about whether some combination of\n      // concatenated values are unsafe to use and could easily lead to XSS.  By requiring that a\n      // single expression be used for iframe[src], object[src], etc., we ensure that the value\n      // that's used is assigned or constructed by some JS code somewhere that is more testable or\n      // make it obvious that you bound the value to some user controlled value.  This helps reduce\n      // the load when auditing for XSS issues.\n      if (trustedContext && concat.length > 1) {\n          throw $interpolateMinErr('noconcat',\n              \"Error while interpolating: {0}\\nStrict Contextual Escaping disallows \" +\n              \"interpolations that concatenate multiple expressions when a trusted value is \" +\n              \"required.  See http://docs.angularjs.org/api/ng.$sce\", text);\n      }\n\n      if (!mustHaveExpression || expressions.length) {\n        var compute = function(values) {\n          for (var i = 0, ii = expressions.length; i < ii; i++) {\n            if (allOrNothing && isUndefined(values[i])) return;\n            concat[expressionPositions[i]] = values[i];\n          }\n          return concat.join('');\n        };\n\n        var getValue = function(value) {\n          return trustedContext ?\n            $sce.getTrusted(trustedContext, value) :\n            $sce.valueOf(value);\n        };\n\n        var stringify = function(value) {\n          if (value == null) { // null || undefined\n            return '';\n          }\n          switch (typeof value) {\n            case 'string':\n              break;\n            case 'number':\n              value = '' + value;\n              break;\n            default:\n              value = toJson(value);\n          }\n\n          return value;\n        };\n\n        return extend(function interpolationFn(context) {\n            var i = 0;\n            var ii = expressions.length;\n            var values = new Array(ii);\n\n            try {\n              for (; i < ii; i++) {\n                values[i] = parseFns[i](context);\n              }\n\n              return compute(values);\n            } catch (err) {\n              var newErr = $interpolateMinErr('interr', \"Can't interpolate: {0}\\n{1}\", text,\n                  err.toString());\n              $exceptionHandler(newErr);\n            }\n\n          }, {\n          // all of these properties are undocumented for now\n          exp: text, //just for compatibility with regular watchers created via $watch\n          expressions: expressions,\n          $$watchDelegate: function(scope, listener, objectEquality) {\n            var lastValue;\n            return scope.$watchGroup(parseFns, function interpolateFnWatcher(values, oldValues) {\n              var currValue = compute(values);\n              if (isFunction(listener)) {\n                listener.call(this, currValue, values !== oldValues ? lastValue : currValue, scope);\n              }\n              lastValue = currValue;\n            }, objectEquality);\n          }\n        });\n      }\n\n      function unescapeText(text) {\n        return text.replace(escapedStartRegexp, startSymbol).\n          replace(escapedEndRegexp, endSymbol);\n      }\n\n      function parseStringifyInterceptor(value) {\n        try {\n          value = getValue(value);\n          return allOrNothing && !isDefined(value) ? value : stringify(value);\n        } catch (err) {\n          var newErr = $interpolateMinErr('interr', \"Can't interpolate: {0}\\n{1}\", text,\n            err.toString());\n          $exceptionHandler(newErr);\n        }\n      }\n    }\n\n\n    /**\n     * @ngdoc method\n     * @name $interpolate#startSymbol\n     * @description\n     * Symbol to denote the start of expression in the interpolated string. Defaults to `{{`.\n     *\n     * Use {@link ng.$interpolateProvider#startSymbol `$interpolateProvider.startSymbol`} to change\n     * the symbol.\n     *\n     * @returns {string} start symbol.\n     */\n    $interpolate.startSymbol = function() {\n      return startSymbol;\n    };\n\n\n    /**\n     * @ngdoc method\n     * @name $interpolate#endSymbol\n     * @description\n     * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.\n     *\n     * Use {@link ng.$interpolateProvider#endSymbol `$interpolateProvider.endSymbol`} to change\n     * the symbol.\n     *\n     * @returns {string} end symbol.\n     */\n    $interpolate.endSymbol = function() {\n      return endSymbol;\n    };\n\n    return $interpolate;\n  }];\n}\n\nfunction $IntervalProvider() {\n  this.$get = ['$rootScope', '$window', '$q', '$$q',\n       function($rootScope,   $window,   $q,   $$q) {\n    var intervals = {};\n\n\n     /**\n      * @ngdoc service\n      * @name $interval\n      *\n      * @description\n      * Angular's wrapper for `window.setInterval`. The `fn` function is executed every `delay`\n      * milliseconds.\n      *\n      * The return value of registering an interval function is a promise. This promise will be\n      * notified upon each tick of the interval, and will be resolved after `count` iterations, or\n      * run indefinitely if `count` is not defined. The value of the notification will be the\n      * number of iterations that have run.\n      * To cancel an interval, call `$interval.cancel(promise)`.\n      *\n      * In tests you can use {@link ngMock.$interval#flush `$interval.flush(millis)`} to\n      * move forward by `millis` milliseconds and trigger any functions scheduled to run in that\n      * time.\n      *\n      * <div class=\"alert alert-warning\">\n      * **Note**: Intervals created by this service must be explicitly destroyed when you are finished\n      * with them.  In particular they are not automatically destroyed when a controller's scope or a\n      * directive's element are destroyed.\n      * You should take this into consideration and make sure to always cancel the interval at the\n      * appropriate moment.  See the example below for more details on how and when to do this.\n      * </div>\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#$apply $apply} block.\n      * @returns {promise} A promise which will be notified on each iteration.\n      *\n      * @example\n      * <example module=\"intervalExample\">\n      * <file name=\"index.html\">\n      *   <script>\n      *     angular.module('intervalExample', [])\n      *       .controller('ExampleController', ['$scope', '$interval',\n      *         function($scope, $interval) {\n      *           $scope.format = 'M/d/yy h:mm:ss a';\n      *           $scope.blood_1 = 100;\n      *           $scope.blood_2 = 120;\n      *\n      *           var stop;\n      *           $scope.fight = function() {\n      *             // Don't start a new fight if we are already fighting\n      *             if ( angular.isDefined(stop) ) return;\n      *\n      *             stop = $interval(function() {\n      *               if ($scope.blood_1 > 0 && $scope.blood_2 > 0) {\n      *                 $scope.blood_1 = $scope.blood_1 - 3;\n      *                 $scope.blood_2 = $scope.blood_2 - 4;\n      *               } else {\n      *                 $scope.stopFight();\n      *               }\n      *             }, 100);\n      *           };\n      *\n      *           $scope.stopFight = function() {\n      *             if (angular.isDefined(stop)) {\n      *               $interval.cancel(stop);\n      *               stop = undefined;\n      *             }\n      *           };\n      *\n      *           $scope.resetFight = function() {\n      *             $scope.blood_1 = 100;\n      *             $scope.blood_2 = 120;\n      *           };\n      *\n      *           $scope.$on('$destroy', function() {\n      *             // Make sure that the interval is destroyed too\n      *             $scope.stopFight();\n      *           });\n      *         }])\n      *       // Register the 'myCurrentTime' directive factory method.\n      *       // We inject $interval and dateFilter service since the factory method is DI.\n      *       .directive('myCurrentTime', ['$interval', 'dateFilter',\n      *         function($interval, dateFilter) {\n      *           // return the directive link function. (compile function not needed)\n      *           return function(scope, element, attrs) {\n      *             var format,  // date format\n      *                 stopTime; // so that we can cancel the time updates\n      *\n      *             // used to update the UI\n      *             function updateTime() {\n      *               element.text(dateFilter(new Date(), format));\n      *             }\n      *\n      *             // watch the expression, and update the UI on change.\n      *             scope.$watch(attrs.myCurrentTime, function(value) {\n      *               format = value;\n      *               updateTime();\n      *             });\n      *\n      *             stopTime = $interval(updateTime, 1000);\n      *\n      *             // listen on DOM destroy (removal) event, and cancel the next UI update\n      *             // to prevent updating time after the DOM element was removed.\n      *             element.on('$destroy', function() {\n      *               $interval.cancel(stopTime);\n      *             });\n      *           }\n      *         }]);\n      *   </script>\n      *\n      *   <div>\n      *     <div ng-controller=\"ExampleController\">\n      *       Date format: <input ng-model=\"format\"> <hr/>\n      *       Current time is: <span my-current-time=\"format\"></span>\n      *       <hr/>\n      *       Blood 1 : <font color='red'>{{blood_1}}</font>\n      *       Blood 2 : <font color='red'>{{blood_2}}</font>\n      *       <button type=\"button\" data-ng-click=\"fight()\">Fight</button>\n      *       <button type=\"button\" data-ng-click=\"stopFight()\">StopFight</button>\n      *       <button type=\"button\" data-ng-click=\"resetFight()\">resetFight</button>\n      *     </div>\n      *   </div>\n      *\n      * </file>\n      * </example>\n      */\n    function interval(fn, delay, count, invokeApply) {\n      var setInterval = $window.setInterval,\n          clearInterval = $window.clearInterval,\n          iteration = 0,\n          skipApply = (isDefined(invokeApply) && !invokeApply),\n          deferred = (skipApply ? $$q : $q).defer(),\n          promise = deferred.promise;\n\n      count = isDefined(count) ? count : 0;\n\n      promise.then(null, null, fn);\n\n      promise.$$intervalId = setInterval(function tick() {\n        deferred.notify(iteration++);\n\n        if (count > 0 && iteration >= count) {\n          deferred.resolve(iteration);\n          clearInterval(promise.$$intervalId);\n          delete intervals[promise.$$intervalId];\n        }\n\n        if (!skipApply) $rootScope.$apply();\n\n      }, delay);\n\n      intervals[promise.$$intervalId] = deferred;\n\n      return promise;\n    }\n\n\n     /**\n      * @ngdoc method\n      * @name $interval#cancel\n      *\n      * @description\n      * Cancels a task associated with the `promise`.\n      *\n      * @param {promise} promise returned by the `$interval` function.\n      * @returns {boolean} Returns `true` if the task was successfully canceled.\n      */\n    interval.cancel = function(promise) {\n      if (promise && promise.$$intervalId in intervals) {\n        intervals[promise.$$intervalId].reject('canceled');\n        $window.clearInterval(promise.$$intervalId);\n        delete intervals[promise.$$intervalId];\n        return true;\n      }\n      return false;\n    };\n\n    return interval;\n  }];\n}\n\n/**\n * @ngdoc service\n * @name $locale\n *\n * @description\n * $locale service provides localization rules for various Angular components. As of right now the\n * only public api is:\n *\n * * `id` – `{string}` – locale id formatted as `languageId-countryId` (e.g. `en-us`)\n */\nfunction $LocaleProvider() {\n  this.$get = function() {\n    return {\n      id: 'en-us',\n\n      NUMBER_FORMATS: {\n        DECIMAL_SEP: '.',\n        GROUP_SEP: ',',\n        PATTERNS: [\n          { // Decimal Pattern\n            minInt: 1,\n            minFrac: 0,\n            maxFrac: 3,\n            posPre: '',\n            posSuf: '',\n            negPre: '-',\n            negSuf: '',\n            gSize: 3,\n            lgSize: 3\n          },{ //Currency Pattern\n            minInt: 1,\n            minFrac: 2,\n            maxFrac: 2,\n            posPre: '\\u00A4',\n            posSuf: '',\n            negPre: '(\\u00A4',\n            negSuf: ')',\n            gSize: 3,\n            lgSize: 3\n          }\n        ],\n        CURRENCY_SYM: '$'\n      },\n\n      DATETIME_FORMATS: {\n        MONTH:\n            'January,February,March,April,May,June,July,August,September,October,November,December'\n            .split(','),\n        SHORTMONTH:  'Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec'.split(','),\n        DAY: 'Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday'.split(','),\n        SHORTDAY: 'Sun,Mon,Tue,Wed,Thu,Fri,Sat'.split(','),\n        AMPMS: ['AM','PM'],\n        medium: 'MMM d, y h:mm:ss a',\n        'short': 'M/d/yy h:mm a',\n        fullDate: 'EEEE, MMMM d, y',\n        longDate: 'MMMM d, y',\n        mediumDate: 'MMM d, y',\n        shortDate: 'M/d/yy',\n        mediumTime: 'h:mm:ss a',\n        shortTime: 'h:mm a'\n      },\n\n      pluralCat: function(num) {\n        if (num === 1) {\n          return 'one';\n        }\n        return 'other';\n      }\n    };\n  };\n}\n\nvar PATH_MATCH = /^([^\\?#]*)(\\?([^#]*))?(#(.*))?$/,\n    DEFAULT_PORTS = {'http': 80, 'https': 443, 'ftp': 21};\nvar $locationMinErr = minErr('$location');\n\n\n/**\n * Encode path using encodeUriSegment, ignoring forward slashes\n *\n * @param {string} path Path to encode\n * @returns {string}\n */\nfunction encodePath(path) {\n  var segments = path.split('/'),\n      i = segments.length;\n\n  while (i--) {\n    segments[i] = encodeUriSegment(segments[i]);\n  }\n\n  return segments.join('/');\n}\n\nfunction parseAbsoluteUrl(absoluteUrl, locationObj) {\n  var parsedUrl = urlResolve(absoluteUrl);\n\n  locationObj.$$protocol = parsedUrl.protocol;\n  locationObj.$$host = parsedUrl.hostname;\n  locationObj.$$port = int(parsedUrl.port) || DEFAULT_PORTS[parsedUrl.protocol] || null;\n}\n\n\nfunction parseAppUrl(relativeUrl, locationObj) {\n  var prefixed = (relativeUrl.charAt(0) !== '/');\n  if (prefixed) {\n    relativeUrl = '/' + relativeUrl;\n  }\n  var match = urlResolve(relativeUrl);\n  locationObj.$$path = decodeURIComponent(prefixed && match.pathname.charAt(0) === '/' ?\n      match.pathname.substring(1) : match.pathname);\n  locationObj.$$search = parseKeyValue(match.search);\n  locationObj.$$hash = decodeURIComponent(match.hash);\n\n  // make sure path starts with '/';\n  if (locationObj.$$path && locationObj.$$path.charAt(0) != '/') {\n    locationObj.$$path = '/' + locationObj.$$path;\n  }\n}\n\n\n/**\n *\n * @param {string} begin\n * @param {string} whole\n * @returns {string} returns text from whole after begin or undefined if it does not begin with\n *                   expected string.\n */\nfunction beginsWith(begin, whole) {\n  if (whole.indexOf(begin) === 0) {\n    return whole.substr(begin.length);\n  }\n}\n\n\nfunction stripHash(url) {\n  var index = url.indexOf('#');\n  return index == -1 ? url : url.substr(0, index);\n}\n\nfunction trimEmptyHash(url) {\n  return url.replace(/(#.+)|#$/, '$1');\n}\n\n\nfunction stripFile(url) {\n  return url.substr(0, stripHash(url).lastIndexOf('/') + 1);\n}\n\n/* return the server only (scheme://host:port) */\nfunction serverBase(url) {\n  return url.substring(0, url.indexOf('/', url.indexOf('//') + 2));\n}\n\n\n/**\n * LocationHtml5Url represents an url\n * This object is exposed as $location service when HTML5 mode is enabled and supported\n *\n * @constructor\n * @param {string} appBase application base URL\n * @param {string} basePrefix url path prefix\n */\nfunction LocationHtml5Url(appBase, basePrefix) {\n  this.$$html5 = true;\n  basePrefix = basePrefix || '';\n  var appBaseNoFile = stripFile(appBase);\n  parseAbsoluteUrl(appBase, this);\n\n\n  /**\n   * Parse given html5 (regular) url string into properties\n   * @param {string} url HTML5 url\n   * @private\n   */\n  this.$$parse = function(url) {\n    var pathUrl = beginsWith(appBaseNoFile, url);\n    if (!isString(pathUrl)) {\n      throw $locationMinErr('ipthprfx', 'Invalid url \"{0}\", missing path prefix \"{1}\".', url,\n          appBaseNoFile);\n    }\n\n    parseAppUrl(pathUrl, this);\n\n    if (!this.$$path) {\n      this.$$path = '/';\n    }\n\n    this.$$compose();\n  };\n\n  /**\n   * Compose url and update `absUrl` property\n   * @private\n   */\n  this.$$compose = function() {\n    var search = toKeyValue(this.$$search),\n        hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';\n\n    this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;\n    this.$$absUrl = appBaseNoFile + this.$$url.substr(1); // first char is always '/'\n  };\n\n  this.$$parseLinkUrl = function(url, relHref) {\n    if (relHref && relHref[0] === '#') {\n      // special case for links to hash fragments:\n      // keep the old url and only replace the hash fragment\n      this.hash(relHref.slice(1));\n      return true;\n    }\n    var appUrl, prevAppUrl;\n    var rewrittenUrl;\n\n    if ((appUrl = beginsWith(appBase, url)) !== undefined) {\n      prevAppUrl = appUrl;\n      if ((appUrl = beginsWith(basePrefix, appUrl)) !== undefined) {\n        rewrittenUrl = appBaseNoFile + (beginsWith('/', appUrl) || appUrl);\n      } else {\n        rewrittenUrl = appBase + prevAppUrl;\n      }\n    } else if ((appUrl = beginsWith(appBaseNoFile, url)) !== undefined) {\n      rewrittenUrl = appBaseNoFile + appUrl;\n    } else if (appBaseNoFile == url + '/') {\n      rewrittenUrl = appBaseNoFile;\n    }\n    if (rewrittenUrl) {\n      this.$$parse(rewrittenUrl);\n    }\n    return !!rewrittenUrl;\n  };\n}\n\n\n/**\n * LocationHashbangUrl represents url\n * This object is exposed as $location service when developer doesn't opt into html5 mode.\n * It also serves as the base class for html5 mode fallback on legacy browsers.\n *\n * @constructor\n * @param {string} appBase application base URL\n * @param {string} hashPrefix hashbang prefix\n */\nfunction LocationHashbangUrl(appBase, hashPrefix) {\n  var appBaseNoFile = stripFile(appBase);\n\n  parseAbsoluteUrl(appBase, this);\n\n\n  /**\n   * Parse given hashbang url into properties\n   * @param {string} url Hashbang url\n   * @private\n   */\n  this.$$parse = function(url) {\n    var withoutBaseUrl = beginsWith(appBase, url) || beginsWith(appBaseNoFile, url);\n    var withoutHashUrl;\n\n    if (withoutBaseUrl.charAt(0) === '#') {\n\n      // The rest of the url starts with a hash so we have\n      // got either a hashbang path or a plain hash fragment\n      withoutHashUrl = beginsWith(hashPrefix, withoutBaseUrl);\n      if (isUndefined(withoutHashUrl)) {\n        // There was no hashbang prefix so we just have a hash fragment\n        withoutHashUrl = withoutBaseUrl;\n      }\n\n    } else {\n      // There was no hashbang path nor hash fragment:\n      // If we are in HTML5 mode we use what is left as the path;\n      // Otherwise we ignore what is left\n      withoutHashUrl = this.$$html5 ? withoutBaseUrl : '';\n    }\n\n    parseAppUrl(withoutHashUrl, this);\n\n    this.$$path = removeWindowsDriveName(this.$$path, withoutHashUrl, appBase);\n\n    this.$$compose();\n\n    /*\n     * In Windows, on an anchor node on documents loaded from\n     * the filesystem, the browser will return a pathname\n     * prefixed with the drive name ('/C:/path') when a\n     * pathname without a drive is set:\n     *  * a.setAttribute('href', '/foo')\n     *   * a.pathname === '/C:/foo' //true\n     *\n     * Inside of Angular, we're always using pathnames that\n     * do not include drive names for routing.\n     */\n    function removeWindowsDriveName(path, url, base) {\n      /*\n      Matches paths for file protocol on windows,\n      such as /C:/foo/bar, and captures only /foo/bar.\n      */\n      var windowsFilePathExp = /^\\/[A-Z]:(\\/.*)/;\n\n      var firstPathSegmentMatch;\n\n      //Get the relative path from the input URL.\n      if (url.indexOf(base) === 0) {\n        url = url.replace(base, '');\n      }\n\n      // The input URL intentionally contains a first path segment that ends with a colon.\n      if (windowsFilePathExp.exec(url)) {\n        return path;\n      }\n\n      firstPathSegmentMatch = windowsFilePathExp.exec(path);\n      return firstPathSegmentMatch ? firstPathSegmentMatch[1] : path;\n    }\n  };\n\n  /**\n   * Compose hashbang url and update `absUrl` property\n   * @private\n   */\n  this.$$compose = function() {\n    var search = toKeyValue(this.$$search),\n        hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';\n\n    this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;\n    this.$$absUrl = appBase + (this.$$url ? hashPrefix + this.$$url : '');\n  };\n\n  this.$$parseLinkUrl = function(url, relHref) {\n    if (stripHash(appBase) == stripHash(url)) {\n      this.$$parse(url);\n      return true;\n    }\n    return false;\n  };\n}\n\n\n/**\n * LocationHashbangUrl represents url\n * This object is exposed as $location service when html5 history api is enabled but the browser\n * does not support it.\n *\n * @constructor\n * @param {string} appBase application base URL\n * @param {string} hashPrefix hashbang prefix\n */\nfunction LocationHashbangInHtml5Url(appBase, hashPrefix) {\n  this.$$html5 = true;\n  LocationHashbangUrl.apply(this, arguments);\n\n  var appBaseNoFile = stripFile(appBase);\n\n  this.$$parseLinkUrl = function(url, relHref) {\n    if (relHref && relHref[0] === '#') {\n      // special case for links to hash fragments:\n      // keep the old url and only replace the hash fragment\n      this.hash(relHref.slice(1));\n      return true;\n    }\n\n    var rewrittenUrl;\n    var appUrl;\n\n    if (appBase == stripHash(url)) {\n      rewrittenUrl = url;\n    } else if ((appUrl = beginsWith(appBaseNoFile, url))) {\n      rewrittenUrl = appBase + hashPrefix + appUrl;\n    } else if (appBaseNoFile === url + '/') {\n      rewrittenUrl = appBaseNoFile;\n    }\n    if (rewrittenUrl) {\n      this.$$parse(rewrittenUrl);\n    }\n    return !!rewrittenUrl;\n  };\n\n  this.$$compose = function() {\n    var search = toKeyValue(this.$$search),\n        hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';\n\n    this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;\n    // include hashPrefix in $$absUrl when $$url is empty so IE8 & 9 do not reload page because of removal of '#'\n    this.$$absUrl = appBase + hashPrefix + this.$$url;\n  };\n\n}\n\n\nvar locationPrototype = {\n\n  /**\n   * Are we in html5 mode?\n   * @private\n   */\n  $$html5: false,\n\n  /**\n   * Has any change been replacing?\n   * @private\n   */\n  $$replace: false,\n\n  /**\n   * @ngdoc method\n   * @name $location#absUrl\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return full url representation with all segments encoded according to rules specified in\n   * [RFC 3986](http://www.ietf.org/rfc/rfc3986.txt).\n   *\n   *\n   * ```js\n   * // given url http://example.com/#/some/path?foo=bar&baz=xoxo\n   * var absUrl = $location.absUrl();\n   * // => \"http://example.com/#/some/path?foo=bar&baz=xoxo\"\n   * ```\n   *\n   * @return {string} full url\n   */\n  absUrl: locationGetter('$$absUrl'),\n\n  /**\n   * @ngdoc method\n   * @name $location#url\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return url (e.g. `/path?a=b#hash`) when called without any parameter.\n   *\n   * Change path, search and hash, when called with parameter and return `$location`.\n   *\n   *\n   * ```js\n   * // given url http://example.com/#/some/path?foo=bar&baz=xoxo\n   * var url = $location.url();\n   * // => \"/some/path?foo=bar&baz=xoxo\"\n   * ```\n   *\n   * @param {string=} url New url without base prefix (e.g. `/path?a=b#hash`)\n   * @return {string} url\n   */\n  url: function(url) {\n    if (isUndefined(url))\n      return this.$$url;\n\n    var match = PATH_MATCH.exec(url);\n    if (match[1] || url === '') this.path(decodeURIComponent(match[1]));\n    if (match[2] || match[1] || url === '') this.search(match[3] || '');\n    this.hash(match[5] || '');\n\n    return this;\n  },\n\n  /**\n   * @ngdoc method\n   * @name $location#protocol\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return protocol of current url.\n   *\n   *\n   * ```js\n   * // given url http://example.com/#/some/path?foo=bar&baz=xoxo\n   * var protocol = $location.protocol();\n   * // => \"http\"\n   * ```\n   *\n   * @return {string} protocol of current url\n   */\n  protocol: locationGetter('$$protocol'),\n\n  /**\n   * @ngdoc method\n   * @name $location#host\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return host of current url.\n   *\n   *\n   * ```js\n   * // given url http://example.com/#/some/path?foo=bar&baz=xoxo\n   * var host = $location.host();\n   * // => \"example.com\"\n   * ```\n   *\n   * @return {string} host of current url.\n   */\n  host: locationGetter('$$host'),\n\n  /**\n   * @ngdoc method\n   * @name $location#port\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return port of current url.\n   *\n   *\n   * ```js\n   * // given url http://example.com/#/some/path?foo=bar&baz=xoxo\n   * var port = $location.port();\n   * // => 80\n   * ```\n   *\n   * @return {Number} port\n   */\n  port: locationGetter('$$port'),\n\n  /**\n   * @ngdoc method\n   * @name $location#path\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return path of current url when called without any parameter.\n   *\n   * Change path when called with parameter and return `$location`.\n   *\n   * Note: Path should always begin with forward slash (/), this method will add the forward slash\n   * if it is missing.\n   *\n   *\n   * ```js\n   * // given url http://example.com/#/some/path?foo=bar&baz=xoxo\n   * var path = $location.path();\n   * // => \"/some/path\"\n   * ```\n   *\n   * @param {(string|number)=} path New path\n   * @return {string} path\n   */\n  path: locationGetterSetter('$$path', function(path) {\n    path = path !== null ? path.toString() : '';\n    return path.charAt(0) == '/' ? path : '/' + path;\n  }),\n\n  /**\n   * @ngdoc method\n   * @name $location#search\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return search part (as object) of current url when called without any parameter.\n   *\n   * Change search part when called with parameter and return `$location`.\n   *\n   *\n   * ```js\n   * // given url http://example.com/#/some/path?foo=bar&baz=xoxo\n   * var searchObject = $location.search();\n   * // => {foo: 'bar', baz: 'xoxo'}\n   *\n   * // set foo to 'yipee'\n   * $location.search('foo', 'yipee');\n   * // $location.search() => {foo: 'yipee', baz: 'xoxo'}\n   * ```\n   *\n   * @param {string|Object.<string>|Object.<Array.<string>>} search New search params - string or\n   * hash object.\n   *\n   * When called with a single argument the method acts as a setter, setting the `search` component\n   * of `$location` to the specified value.\n   *\n   * If the argument is a hash object containing an array of values, these values will be encoded\n   * as duplicate search parameters in the url.\n   *\n   * @param {(string|Number|Array<string>|boolean)=} paramValue If `search` is a string or number, then `paramValue`\n   * will override only a single search property.\n   *\n   * If `paramValue` is an array, it will override the property of the `search` component of\n   * `$location` specified via the first argument.\n   *\n   * If `paramValue` is `null`, the property specified via the first argument will be deleted.\n   *\n   * If `paramValue` is `true`, the property specified via the first argument will be added with no\n   * value nor trailing equal sign.\n   *\n   * @return {Object} If called with no arguments returns the parsed `search` object. If called with\n   * one or more arguments returns `$location` object itself.\n   */\n  search: function(search, paramValue) {\n    switch (arguments.length) {\n      case 0:\n        return this.$$search;\n      case 1:\n        if (isString(search) || isNumber(search)) {\n          search = search.toString();\n          this.$$search = parseKeyValue(search);\n        } else if (isObject(search)) {\n          search = copy(search, {});\n          // remove object undefined or null properties\n          forEach(search, function(value, key) {\n            if (value == null) delete search[key];\n          });\n\n          this.$$search = search;\n        } else {\n          throw $locationMinErr('isrcharg',\n              'The first argument of the `$location#search()` call must be a string or an object.');\n        }\n        break;\n      default:\n        if (isUndefined(paramValue) || paramValue === null) {\n          delete this.$$search[search];\n        } else {\n          this.$$search[search] = paramValue;\n        }\n    }\n\n    this.$$compose();\n    return this;\n  },\n\n  /**\n   * @ngdoc method\n   * @name $location#hash\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return hash fragment when called without any parameter.\n   *\n   * Change hash fragment when called with parameter and return `$location`.\n   *\n   *\n   * ```js\n   * // given url http://example.com/#/some/path?foo=bar&baz=xoxo#hashValue\n   * var hash = $location.hash();\n   * // => \"hashValue\"\n   * ```\n   *\n   * @param {(string|number)=} hash New hash fragment\n   * @return {string} hash\n   */\n  hash: locationGetterSetter('$$hash', function(hash) {\n    return hash !== null ? hash.toString() : '';\n  }),\n\n  /**\n   * @ngdoc method\n   * @name $location#replace\n   *\n   * @description\n   * If called, all changes to $location during current `$digest` will be replacing current history\n   * record, instead of adding new one.\n   */\n  replace: function() {\n    this.$$replace = true;\n    return this;\n  }\n};\n\nforEach([LocationHashbangInHtml5Url, LocationHashbangUrl, LocationHtml5Url], function(Location) {\n  Location.prototype = Object.create(locationPrototype);\n\n  /**\n   * @ngdoc method\n   * @name $location#state\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return the history state object when called without any parameter.\n   *\n   * Change the history state object when called with one parameter and return `$location`.\n   * The state object is later passed to `pushState` or `replaceState`.\n   *\n   * NOTE: This method is supported only in HTML5 mode and only in browsers supporting\n   * the HTML5 History API (i.e. methods `pushState` and `replaceState`). If you need to support\n   * older browsers (like IE9 or Android < 4.0), don't use this method.\n   *\n   * @param {object=} state State object for pushState or replaceState\n   * @return {object} state\n   */\n  Location.prototype.state = function(state) {\n    if (!arguments.length)\n      return this.$$state;\n\n    if (Location !== LocationHtml5Url || !this.$$html5) {\n      throw $locationMinErr('nostate', 'History API state support is available only ' +\n        'in HTML5 mode and only in browsers supporting HTML5 History API');\n    }\n    // The user might modify `stateObject` after invoking `$location.state(stateObject)`\n    // but we're changing the $$state reference to $browser.state() during the $digest\n    // so the modification window is narrow.\n    this.$$state = isUndefined(state) ? null : state;\n\n    return this;\n  };\n});\n\n\nfunction locationGetter(property) {\n  return function() {\n    return this[property];\n  };\n}\n\n\nfunction locationGetterSetter(property, preprocess) {\n  return function(value) {\n    if (isUndefined(value))\n      return this[property];\n\n    this[property] = preprocess(value);\n    this.$$compose();\n\n    return this;\n  };\n}\n\n\n/**\n * @ngdoc service\n * @name $location\n *\n * @requires $rootElement\n *\n * @description\n * The $location service parses the URL in the browser address bar (based on the\n * [window.location](https://developer.mozilla.org/en/window.location)) and makes the URL\n * available to your application. Changes to the URL in the address bar are reflected into\n * $location service and changes to $location are reflected into the browser address bar.\n *\n * **The $location service:**\n *\n * - Exposes the current URL in the browser address bar, so you can\n *   - Watch and observe the URL.\n *   - Change the URL.\n * - Synchronizes the URL with the browser when the user\n *   - Changes the address bar.\n *   - Clicks the back or forward button (or clicks a History link).\n *   - Clicks on a link.\n * - Represents the URL object as a set of methods (protocol, host, port, path, search, hash).\n *\n * For more information see {@link guide/$location Developer Guide: Using $location}\n */\n\n/**\n * @ngdoc provider\n * @name $locationProvider\n * @description\n * Use the `$locationProvider` to configure how the application deep linking paths are stored.\n */\nfunction $LocationProvider() {\n  var hashPrefix = '',\n      html5Mode = {\n        enabled: false,\n        requireBase: true,\n        rewriteLinks: true\n      };\n\n  /**\n   * @ngdoc method\n   * @name $locationProvider#hashPrefix\n   * @description\n   * @param {string=} prefix Prefix for hash part (containing path and search)\n   * @returns {*} current value if used as getter or itself (chaining) if used as setter\n   */\n  this.hashPrefix = function(prefix) {\n    if (isDefined(prefix)) {\n      hashPrefix = prefix;\n      return this;\n    } else {\n      return hashPrefix;\n    }\n  };\n\n  /**\n   * @ngdoc method\n   * @name $locationProvider#html5Mode\n   * @description\n   * @param {(boolean|Object)=} mode If boolean, sets `html5Mode.enabled` to value.\n   *   If object, sets `enabled`, `requireBase` and `rewriteLinks` to respective values. Supported\n   *   properties:\n   *   - **enabled** – `{boolean}` – (default: false) If true, will rely on `history.pushState` to\n   *     change urls where supported. Will fall back to hash-prefixed paths in browsers that do not\n   *     support `pushState`.\n   *   - **requireBase** - `{boolean}` - (default: `true`) When html5Mode is enabled, specifies\n   *     whether or not a <base> tag is required to be present. If `enabled` and `requireBase` are\n   *     true, and a base tag is not present, an error will be thrown when `$location` is injected.\n   *     See the {@link guide/$location $location guide for more information}\n   *   - **rewriteLinks** - `{boolean}` - (default: `true`) When html5Mode is enabled,\n   *     enables/disables url rewriting for relative links.\n   *\n   * @returns {Object} html5Mode object if used as getter or itself (chaining) if used as setter\n   */\n  this.html5Mode = function(mode) {\n    if (isBoolean(mode)) {\n      html5Mode.enabled = mode;\n      return this;\n    } else if (isObject(mode)) {\n\n      if (isBoolean(mode.enabled)) {\n        html5Mode.enabled = mode.enabled;\n      }\n\n      if (isBoolean(mode.requireBase)) {\n        html5Mode.requireBase = mode.requireBase;\n      }\n\n      if (isBoolean(mode.rewriteLinks)) {\n        html5Mode.rewriteLinks = mode.rewriteLinks;\n      }\n\n      return this;\n    } else {\n      return html5Mode;\n    }\n  };\n\n  /**\n   * @ngdoc event\n   * @name $location#$locationChangeStart\n   * @eventType broadcast on root scope\n   * @description\n   * Broadcasted before a URL will change.\n   *\n   * This change can be prevented by calling\n   * `preventDefault` method of the event. See {@link ng.$rootScope.Scope#$on} for more\n   * details about event object. Upon successful change\n   * {@link ng.$location#$locationChangeSuccess $locationChangeSuccess} is fired.\n   *\n   * The `newState` and `oldState` parameters may be defined only in HTML5 mode and when\n   * the browser supports the HTML5 History API.\n   *\n   * @param {Object} angularEvent Synthetic event object.\n   * @param {string} newUrl New URL\n   * @param {string=} oldUrl URL that was before it was changed.\n   * @param {string=} newState New history state object\n   * @param {string=} oldState History state object that was before it was changed.\n   */\n\n  /**\n   * @ngdoc event\n   * @name $location#$locationChangeSuccess\n   * @eventType broadcast on root scope\n   * @description\n   * Broadcasted after a URL was changed.\n   *\n   * The `newState` and `oldState` parameters may be defined only in HTML5 mode and when\n   * the browser supports the HTML5 History API.\n   *\n   * @param {Object} angularEvent Synthetic event object.\n   * @param {string} newUrl New URL\n   * @param {string=} oldUrl URL that was before it was changed.\n   * @param {string=} newState New history state object\n   * @param {string=} oldState History state object that was before it was changed.\n   */\n\n  this.$get = ['$rootScope', '$browser', '$sniffer', '$rootElement', '$window',\n      function($rootScope, $browser, $sniffer, $rootElement, $window) {\n    var $location,\n        LocationMode,\n        baseHref = $browser.baseHref(), // if base[href] is undefined, it defaults to ''\n        initialUrl = $browser.url(),\n        appBase;\n\n    if (html5Mode.enabled) {\n      if (!baseHref && html5Mode.requireBase) {\n        throw $locationMinErr('nobase',\n          \"$location in HTML5 mode requires a <base> tag to be present!\");\n      }\n      appBase = serverBase(initialUrl) + (baseHref || '/');\n      LocationMode = $sniffer.history ? LocationHtml5Url : LocationHashbangInHtml5Url;\n    } else {\n      appBase = stripHash(initialUrl);\n      LocationMode = LocationHashbangUrl;\n    }\n    $location = new LocationMode(appBase, '#' + hashPrefix);\n    $location.$$parseLinkUrl(initialUrl, initialUrl);\n\n    $location.$$state = $browser.state();\n\n    var IGNORE_URI_REGEXP = /^\\s*(javascript|mailto):/i;\n\n    function setBrowserUrlWithFallback(url, replace, state) {\n      var oldUrl = $location.url();\n      var oldState = $location.$$state;\n      try {\n        $browser.url(url, replace, state);\n\n        // Make sure $location.state() returns referentially identical (not just deeply equal)\n        // state object; this makes possible quick checking if the state changed in the digest\n        // loop. Checking deep equality would be too expensive.\n        $location.$$state = $browser.state();\n      } catch (e) {\n        // Restore old values if pushState fails\n        $location.url(oldUrl);\n        $location.$$state = oldState;\n\n        throw e;\n      }\n    }\n\n    $rootElement.on('click', function(event) {\n      // TODO(vojta): rewrite link when opening in new tab/window (in legacy browser)\n      // currently we open nice url link and redirect then\n\n      if (!html5Mode.rewriteLinks || event.ctrlKey || event.metaKey || event.shiftKey || event.which == 2 || event.button == 2) return;\n\n      var elm = jqLite(event.target);\n\n      // traverse the DOM up to find first A tag\n      while (nodeName_(elm[0]) !== 'a') {\n        // ignore rewriting if no A tag (reached root element, or no parent - removed from document)\n        if (elm[0] === $rootElement[0] || !(elm = elm.parent())[0]) return;\n      }\n\n      var absHref = elm.prop('href');\n      // get the actual href attribute - see\n      // http://msdn.microsoft.com/en-us/library/ie/dd347148(v=vs.85).aspx\n      var relHref = elm.attr('href') || elm.attr('xlink:href');\n\n      if (isObject(absHref) && absHref.toString() === '[object SVGAnimatedString]') {\n        // SVGAnimatedString.animVal should be identical to SVGAnimatedString.baseVal, unless during\n        // an animation.\n        absHref = urlResolve(absHref.animVal).href;\n      }\n\n      // Ignore when url is started with javascript: or mailto:\n      if (IGNORE_URI_REGEXP.test(absHref)) return;\n\n      if (absHref && !elm.attr('target') && !event.isDefaultPrevented()) {\n        if ($location.$$parseLinkUrl(absHref, relHref)) {\n          // We do a preventDefault for all urls that are part of the angular application,\n          // in html5mode and also without, so that we are able to abort navigation without\n          // getting double entries in the location history.\n          event.preventDefault();\n          // update location manually\n          if ($location.absUrl() != $browser.url()) {\n            $rootScope.$apply();\n            // hack to work around FF6 bug 684208 when scenario runner clicks on links\n            $window.angular['ff-684208-preventDefault'] = true;\n          }\n        }\n      }\n    });\n\n\n    // rewrite hashbang url <> html5 url\n    if (trimEmptyHash($location.absUrl()) != trimEmptyHash(initialUrl)) {\n      $browser.url($location.absUrl(), true);\n    }\n\n    var initializing = true;\n\n    // update $location when $browser url changes\n    $browser.onUrlChange(function(newUrl, newState) {\n      $rootScope.$evalAsync(function() {\n        var oldUrl = $location.absUrl();\n        var oldState = $location.$$state;\n        var defaultPrevented;\n\n        $location.$$parse(newUrl);\n        $location.$$state = newState;\n\n        defaultPrevented = $rootScope.$broadcast('$locationChangeStart', newUrl, oldUrl,\n            newState, oldState).defaultPrevented;\n\n        // if the location was changed by a `$locationChangeStart` handler then stop\n        // processing this location change\n        if ($location.absUrl() !== newUrl) return;\n\n        if (defaultPrevented) {\n          $location.$$parse(oldUrl);\n          $location.$$state = oldState;\n          setBrowserUrlWithFallback(oldUrl, false, oldState);\n        } else {\n          initializing = false;\n          afterLocationChange(oldUrl, oldState);\n        }\n      });\n      if (!$rootScope.$$phase) $rootScope.$digest();\n    });\n\n    // update browser\n    $rootScope.$watch(function $locationWatch() {\n      var oldUrl = trimEmptyHash($browser.url());\n      var newUrl = trimEmptyHash($location.absUrl());\n      var oldState = $browser.state();\n      var currentReplace = $location.$$replace;\n      var urlOrStateChanged = oldUrl !== newUrl ||\n        ($location.$$html5 && $sniffer.history && oldState !== $location.$$state);\n\n      if (initializing || urlOrStateChanged) {\n        initializing = false;\n\n        $rootScope.$evalAsync(function() {\n          var newUrl = $location.absUrl();\n          var defaultPrevented = $rootScope.$broadcast('$locationChangeStart', newUrl, oldUrl,\n              $location.$$state, oldState).defaultPrevented;\n\n          // if the location was changed by a `$locationChangeStart` handler then stop\n          // processing this location change\n          if ($location.absUrl() !== newUrl) return;\n\n          if (defaultPrevented) {\n            $location.$$parse(oldUrl);\n            $location.$$state = oldState;\n          } else {\n            if (urlOrStateChanged) {\n              setBrowserUrlWithFallback(newUrl, currentReplace,\n                                        oldState === $location.$$state ? null : $location.$$state);\n            }\n            afterLocationChange(oldUrl, oldState);\n          }\n        });\n      }\n\n      $location.$$replace = false;\n\n      // we don't need to return anything because $evalAsync will make the digest loop dirty when\n      // there is a change\n    });\n\n    return $location;\n\n    function afterLocationChange(oldUrl, oldState) {\n      $rootScope.$broadcast('$locationChangeSuccess', $location.absUrl(), oldUrl,\n        $location.$$state, oldState);\n    }\n}];\n}\n\n/**\n * @ngdoc service\n * @name $log\n * @requires $window\n *\n * @description\n * Simple service for logging. Default implementation safely writes the message\n * into the browser's console (if present).\n *\n * The main purpose of this service is to simplify debugging and troubleshooting.\n *\n * The default is to log `debug` messages. You can use\n * {@link ng.$logProvider ng.$logProvider#debugEnabled} to change this.\n *\n * @example\n   <example module=\"logExample\">\n     <file name=\"script.js\">\n       angular.module('logExample', [])\n         .controller('LogController', ['$scope', '$log', function($scope, $log) {\n           $scope.$log = $log;\n           $scope.message = 'Hello World!';\n         }]);\n     </file>\n     <file name=\"index.html\">\n       <div ng-controller=\"LogController\">\n         <p>Reload this page with open console, enter text and hit the log button...</p>\n         Message:\n         <input type=\"text\" ng-model=\"message\"/>\n         <button ng-click=\"$log.log(message)\">log</button>\n         <button ng-click=\"$log.warn(message)\">warn</button>\n         <button ng-click=\"$log.info(message)\">info</button>\n         <button ng-click=\"$log.error(message)\">error</button>\n       </div>\n     </file>\n   </example>\n */\n\n/**\n * @ngdoc provider\n * @name $logProvider\n * @description\n * Use the `$logProvider` to configure how the application logs messages\n */\nfunction $LogProvider() {\n  var debug = true,\n      self = this;\n\n  /**\n   * @ngdoc method\n   * @name $logProvider#debugEnabled\n   * @description\n   * @param {boolean=} flag enable or disable debug level messages\n   * @returns {*} current value if used as getter or itself (chaining) if used as setter\n   */\n  this.debugEnabled = function(flag) {\n    if (isDefined(flag)) {\n      debug = flag;\n    return this;\n    } else {\n      return debug;\n    }\n  };\n\n  this.$get = ['$window', function($window) {\n    return {\n      /**\n       * @ngdoc method\n       * @name $log#log\n       *\n       * @description\n       * Write a log message\n       */\n      log: consoleLog('log'),\n\n      /**\n       * @ngdoc method\n       * @name $log#info\n       *\n       * @description\n       * Write an information message\n       */\n      info: consoleLog('info'),\n\n      /**\n       * @ngdoc method\n       * @name $log#warn\n       *\n       * @description\n       * Write a warning message\n       */\n      warn: consoleLog('warn'),\n\n      /**\n       * @ngdoc method\n       * @name $log#error\n       *\n       * @description\n       * Write an error message\n       */\n      error: consoleLog('error'),\n\n      /**\n       * @ngdoc method\n       * @name $log#debug\n       *\n       * @description\n       * Write a debug message\n       */\n      debug: (function() {\n        var fn = consoleLog('debug');\n\n        return function() {\n          if (debug) {\n            fn.apply(self, arguments);\n          }\n        };\n      }())\n    };\n\n    function formatError(arg) {\n      if (arg instanceof Error) {\n        if (arg.stack) {\n          arg = (arg.message && arg.stack.indexOf(arg.message) === -1)\n              ? 'Error: ' + arg.message + '\\n' + arg.stack\n              : arg.stack;\n        } else if (arg.sourceURL) {\n          arg = arg.message + '\\n' + arg.sourceURL + ':' + arg.line;\n        }\n      }\n      return arg;\n    }\n\n    function consoleLog(type) {\n      var console = $window.console || {},\n          logFn = console[type] || console.log || noop,\n          hasApply = false;\n\n      // Note: reading logFn.apply throws an error in IE11 in IE8 document mode.\n      // The reason behind this is that console.log has type \"object\" in IE8...\n      try {\n        hasApply = !!logFn.apply;\n      } catch (e) {}\n\n      if (hasApply) {\n        return function() {\n          var args = [];\n          forEach(arguments, function(arg) {\n            args.push(formatError(arg));\n          });\n          return logFn.apply(console, args);\n        };\n      }\n\n      // we are IE which either doesn't have window.console => this is noop and we do nothing,\n      // or we are IE where console.log doesn't have apply so we log at least first 2 args\n      return function(arg1, arg2) {\n        logFn(arg1, arg2 == null ? '' : arg2);\n      };\n    }\n  }];\n}\n\nvar $parseMinErr = minErr('$parse');\n\n// Sandboxing Angular Expressions\n// ------------------------------\n// Angular expressions are generally considered safe because these expressions only have direct\n// access to `$scope` and locals. However, one can obtain the ability to execute arbitrary JS code by\n// obtaining a reference to native JS functions such as the Function constructor.\n//\n// As an example, consider the following Angular expression:\n//\n//   {}.toString.constructor('alert(\"evil JS code\")')\n//\n// This sandboxing technique is not perfect and doesn't aim to be. The goal is to prevent exploits\n// against the expression language, but not to prevent exploits that were enabled by exposing\n// sensitive JavaScript or browser APIs on Scope. Exposing such objects on a Scope is never a good\n// practice and therefore we are not even trying to protect against interaction with an object\n// explicitly exposed in this way.\n//\n// In general, it is not possible to access a Window object from an angular expression unless a\n// window or some DOM object that has a reference to window is published onto a Scope.\n// Similarly we prevent invocations of function known to be dangerous, as well as assignments to\n// native objects.\n//\n// See https://docs.angularjs.org/guide/security\n\n\nfunction ensureSafeMemberName(name, fullExpression) {\n  if (name === \"__defineGetter__\" || name === \"__defineSetter__\"\n      || name === \"__lookupGetter__\" || name === \"__lookupSetter__\"\n      || name === \"__proto__\") {\n    throw $parseMinErr('isecfld',\n        'Attempting to access a disallowed field in Angular expressions! '\n        + 'Expression: {0}', fullExpression);\n  }\n  return name;\n}\n\nfunction ensureSafeObject(obj, fullExpression) {\n  // nifty check if obj is Function that is fast and works across iframes and other contexts\n  if (obj) {\n    if (obj.constructor === obj) {\n      throw $parseMinErr('isecfn',\n          'Referencing Function in Angular expressions is disallowed! Expression: {0}',\n          fullExpression);\n    } else if (// isWindow(obj)\n        obj.window === obj) {\n      throw $parseMinErr('isecwindow',\n          'Referencing the Window in Angular expressions is disallowed! Expression: {0}',\n          fullExpression);\n    } else if (// isElement(obj)\n        obj.children && (obj.nodeName || (obj.prop && obj.attr && obj.find))) {\n      throw $parseMinErr('isecdom',\n          'Referencing DOM nodes in Angular expressions is disallowed! Expression: {0}',\n          fullExpression);\n    } else if (// block Object so that we can't get hold of dangerous Object.* methods\n        obj === Object) {\n      throw $parseMinErr('isecobj',\n          'Referencing Object in Angular expressions is disallowed! Expression: {0}',\n          fullExpression);\n    }\n  }\n  return obj;\n}\n\nvar CALL = Function.prototype.call;\nvar APPLY = Function.prototype.apply;\nvar BIND = Function.prototype.bind;\n\nfunction ensureSafeFunction(obj, fullExpression) {\n  if (obj) {\n    if (obj.constructor === obj) {\n      throw $parseMinErr('isecfn',\n        'Referencing Function in Angular expressions is disallowed! Expression: {0}',\n        fullExpression);\n    } else if (obj === CALL || obj === APPLY || obj === BIND) {\n      throw $parseMinErr('isecff',\n        'Referencing call, apply or bind in Angular expressions is disallowed! Expression: {0}',\n        fullExpression);\n    }\n  }\n}\n\n//Keyword constants\nvar CONSTANTS = createMap();\nforEach({\n  'null': function() { return null; },\n  'true': function() { return true; },\n  'false': function() { return false; },\n  'undefined': function() {}\n}, function(constantGetter, name) {\n  constantGetter.constant = constantGetter.literal = constantGetter.sharedGetter = true;\n  CONSTANTS[name] = constantGetter;\n});\n\n//Not quite a constant, but can be lex/parsed the same\nCONSTANTS['this'] = function(self) { return self; };\nCONSTANTS['this'].sharedGetter = true;\n\n\n//Operators - will be wrapped by binaryFn/unaryFn/assignment/filter\nvar OPERATORS = extend(createMap(), {\n    '+':function(self, locals, a, b) {\n      a=a(self, locals); b=b(self, locals);\n      if (isDefined(a)) {\n        if (isDefined(b)) {\n          return a + b;\n        }\n        return a;\n      }\n      return isDefined(b) ? b : undefined;},\n    '-':function(self, locals, a, b) {\n          a=a(self, locals); b=b(self, locals);\n          return (isDefined(a) ? a : 0) - (isDefined(b) ? b : 0);\n        },\n    '*':function(self, locals, a, b) {return a(self, locals) * b(self, locals);},\n    '/':function(self, locals, a, b) {return a(self, locals) / b(self, locals);},\n    '%':function(self, locals, a, b) {return a(self, locals) % b(self, locals);},\n    '===':function(self, locals, a, b) {return a(self, locals) === b(self, locals);},\n    '!==':function(self, locals, a, b) {return a(self, locals) !== b(self, locals);},\n    '==':function(self, locals, a, b) {return a(self, locals) == b(self, locals);},\n    '!=':function(self, locals, a, b) {return a(self, locals) != b(self, locals);},\n    '<':function(self, locals, a, b) {return a(self, locals) < b(self, locals);},\n    '>':function(self, locals, a, b) {return a(self, locals) > b(self, locals);},\n    '<=':function(self, locals, a, b) {return a(self, locals) <= b(self, locals);},\n    '>=':function(self, locals, a, b) {return a(self, locals) >= b(self, locals);},\n    '&&':function(self, locals, a, b) {return a(self, locals) && b(self, locals);},\n    '||':function(self, locals, a, b) {return a(self, locals) || b(self, locals);},\n    '!':function(self, locals, a) {return !a(self, locals);},\n\n    //Tokenized as operators but parsed as assignment/filters\n    '=':true,\n    '|':true\n});\nvar ESCAPE = {\"n\":\"\\n\", \"f\":\"\\f\", \"r\":\"\\r\", \"t\":\"\\t\", \"v\":\"\\v\", \"'\":\"'\", '\"':'\"'};\n\n\n/////////////////////////////////////////\n\n\n/**\n * @constructor\n */\nvar Lexer = function(options) {\n  this.options = options;\n};\n\nLexer.prototype = {\n  constructor: Lexer,\n\n  lex: function(text) {\n    this.text = text;\n    this.index = 0;\n    this.tokens = [];\n\n    while (this.index < this.text.length) {\n      var ch = this.text.charAt(this.index);\n      if (ch === '\"' || ch === \"'\") {\n        this.readString(ch);\n      } else if (this.isNumber(ch) || ch === '.' && this.isNumber(this.peek())) {\n        this.readNumber();\n      } else if (this.isIdent(ch)) {\n        this.readIdent();\n      } else if (this.is(ch, '(){}[].,;:?')) {\n        this.tokens.push({index: this.index, text: ch});\n        this.index++;\n      } else if (this.isWhitespace(ch)) {\n        this.index++;\n      } else {\n        var ch2 = ch + this.peek();\n        var ch3 = ch2 + this.peek(2);\n        var op1 = OPERATORS[ch];\n        var op2 = OPERATORS[ch2];\n        var op3 = OPERATORS[ch3];\n        if (op1 || op2 || op3) {\n          var token = op3 ? ch3 : (op2 ? ch2 : ch);\n          this.tokens.push({index: this.index, text: token, operator: true});\n          this.index += token.length;\n        } else {\n          this.throwError('Unexpected next character ', this.index, this.index + 1);\n        }\n      }\n    }\n    return this.tokens;\n  },\n\n  is: function(ch, chars) {\n    return chars.indexOf(ch) !== -1;\n  },\n\n  peek: function(i) {\n    var num = i || 1;\n    return (this.index + num < this.text.length) ? this.text.charAt(this.index + num) : false;\n  },\n\n  isNumber: function(ch) {\n    return ('0' <= ch && ch <= '9') && typeof ch === \"string\";\n  },\n\n  isWhitespace: function(ch) {\n    // IE treats non-breaking space as \\u00A0\n    return (ch === ' ' || ch === '\\r' || ch === '\\t' ||\n            ch === '\\n' || ch === '\\v' || ch === '\\u00A0');\n  },\n\n  isIdent: function(ch) {\n    return ('a' <= ch && ch <= 'z' ||\n            'A' <= ch && ch <= 'Z' ||\n            '_' === ch || ch === '$');\n  },\n\n  isExpOperator: function(ch) {\n    return (ch === '-' || ch === '+' || this.isNumber(ch));\n  },\n\n  throwError: function(error, start, end) {\n    end = end || this.index;\n    var colStr = (isDefined(start)\n            ? 's ' + start +  '-' + this.index + ' [' + this.text.substring(start, end) + ']'\n            : ' ' + end);\n    throw $parseMinErr('lexerr', 'Lexer Error: {0} at column{1} in expression [{2}].',\n        error, colStr, this.text);\n  },\n\n  readNumber: function() {\n    var number = '';\n    var start = this.index;\n    while (this.index < this.text.length) {\n      var ch = lowercase(this.text.charAt(this.index));\n      if (ch == '.' || this.isNumber(ch)) {\n        number += ch;\n      } else {\n        var peekCh = this.peek();\n        if (ch == 'e' && this.isExpOperator(peekCh)) {\n          number += ch;\n        } else if (this.isExpOperator(ch) &&\n            peekCh && this.isNumber(peekCh) &&\n            number.charAt(number.length - 1) == 'e') {\n          number += ch;\n        } else if (this.isExpOperator(ch) &&\n            (!peekCh || !this.isNumber(peekCh)) &&\n            number.charAt(number.length - 1) == 'e') {\n          this.throwError('Invalid exponent');\n        } else {\n          break;\n        }\n      }\n      this.index++;\n    }\n    this.tokens.push({\n      index: start,\n      text: number,\n      constant: true,\n      value: Number(number)\n    });\n  },\n\n  readIdent: function() {\n    var start = this.index;\n    while (this.index < this.text.length) {\n      var ch = this.text.charAt(this.index);\n      if (!(this.isIdent(ch) || this.isNumber(ch))) {\n        break;\n      }\n      this.index++;\n    }\n    this.tokens.push({\n      index: start,\n      text: this.text.slice(start, this.index),\n      identifier: true\n    });\n  },\n\n  readString: function(quote) {\n    var start = this.index;\n    this.index++;\n    var string = '';\n    var rawString = quote;\n    var escape = false;\n    while (this.index < this.text.length) {\n      var ch = this.text.charAt(this.index);\n      rawString += ch;\n      if (escape) {\n        if (ch === 'u') {\n          var hex = this.text.substring(this.index + 1, this.index + 5);\n          if (!hex.match(/[\\da-f]{4}/i))\n            this.throwError('Invalid unicode escape [\\\\u' + hex + ']');\n          this.index += 4;\n          string += String.fromCharCode(parseInt(hex, 16));\n        } else {\n          var rep = ESCAPE[ch];\n          string = string + (rep || ch);\n        }\n        escape = false;\n      } else if (ch === '\\\\') {\n        escape = true;\n      } else if (ch === quote) {\n        this.index++;\n        this.tokens.push({\n          index: start,\n          text: rawString,\n          constant: true,\n          value: string\n        });\n        return;\n      } else {\n        string += ch;\n      }\n      this.index++;\n    }\n    this.throwError('Unterminated quote', start);\n  }\n};\n\n\nfunction isConstant(exp) {\n  return exp.constant;\n}\n\n/**\n * @constructor\n */\nvar Parser = function(lexer, $filter, options) {\n  this.lexer = lexer;\n  this.$filter = $filter;\n  this.options = options;\n};\n\nParser.ZERO = extend(function() {\n  return 0;\n}, {\n  sharedGetter: true,\n  constant: true\n});\n\nParser.prototype = {\n  constructor: Parser,\n\n  parse: function(text) {\n    this.text = text;\n    this.tokens = this.lexer.lex(text);\n\n    var value = this.statements();\n\n    if (this.tokens.length !== 0) {\n      this.throwError('is an unexpected token', this.tokens[0]);\n    }\n\n    value.literal = !!value.literal;\n    value.constant = !!value.constant;\n\n    return value;\n  },\n\n  primary: function() {\n    var primary;\n    if (this.expect('(')) {\n      primary = this.filterChain();\n      this.consume(')');\n    } else if (this.expect('[')) {\n      primary = this.arrayDeclaration();\n    } else if (this.expect('{')) {\n      primary = this.object();\n    } else if (this.peek().identifier && this.peek().text in CONSTANTS) {\n      primary = CONSTANTS[this.consume().text];\n    } else if (this.peek().identifier) {\n      primary = this.identifier();\n    } else if (this.peek().constant) {\n      primary = this.constant();\n    } else {\n      this.throwError('not a primary expression', this.peek());\n    }\n\n    var next, context;\n    while ((next = this.expect('(', '[', '.'))) {\n      if (next.text === '(') {\n        primary = this.functionCall(primary, context);\n        context = null;\n      } else if (next.text === '[') {\n        context = primary;\n        primary = this.objectIndex(primary);\n      } else if (next.text === '.') {\n        context = primary;\n        primary = this.fieldAccess(primary);\n      } else {\n        this.throwError('IMPOSSIBLE');\n      }\n    }\n    return primary;\n  },\n\n  throwError: function(msg, token) {\n    throw $parseMinErr('syntax',\n        'Syntax Error: Token \\'{0}\\' {1} at column {2} of the expression [{3}] starting at [{4}].',\n          token.text, msg, (token.index + 1), this.text, this.text.substring(token.index));\n  },\n\n  peekToken: function() {\n    if (this.tokens.length === 0)\n      throw $parseMinErr('ueoe', 'Unexpected end of expression: {0}', this.text);\n    return this.tokens[0];\n  },\n\n  peek: function(e1, e2, e3, e4) {\n    return this.peekAhead(0, e1, e2, e3, e4);\n  },\n  peekAhead: function(i, e1, e2, e3, e4) {\n    if (this.tokens.length > i) {\n      var token = this.tokens[i];\n      var t = token.text;\n      if (t === e1 || t === e2 || t === e3 || t === e4 ||\n          (!e1 && !e2 && !e3 && !e4)) {\n        return token;\n      }\n    }\n    return false;\n  },\n\n  expect: function(e1, e2, e3, e4) {\n    var token = this.peek(e1, e2, e3, e4);\n    if (token) {\n      this.tokens.shift();\n      return token;\n    }\n    return false;\n  },\n\n  consume: function(e1) {\n    if (this.tokens.length === 0) {\n      throw $parseMinErr('ueoe', 'Unexpected end of expression: {0}', this.text);\n    }\n\n    var token = this.expect(e1);\n    if (!token) {\n      this.throwError('is unexpected, expecting [' + e1 + ']', this.peek());\n    }\n    return token;\n  },\n\n  unaryFn: function(op, right) {\n    var fn = OPERATORS[op];\n    return extend(function $parseUnaryFn(self, locals) {\n      return fn(self, locals, right);\n    }, {\n      constant:right.constant,\n      inputs: [right]\n    });\n  },\n\n  binaryFn: function(left, op, right, isBranching) {\n    var fn = OPERATORS[op];\n    return extend(function $parseBinaryFn(self, locals) {\n      return fn(self, locals, left, right);\n    }, {\n      constant: left.constant && right.constant,\n      inputs: !isBranching && [left, right]\n    });\n  },\n\n  identifier: function() {\n    var id = this.consume().text;\n\n    //Continue reading each `.identifier` unless it is a method invocation\n    while (this.peek('.') && this.peekAhead(1).identifier && !this.peekAhead(2, '(')) {\n      id += this.consume().text + this.consume().text;\n    }\n\n    return getterFn(id, this.options, this.text);\n  },\n\n  constant: function() {\n    var value = this.consume().value;\n\n    return extend(function $parseConstant() {\n      return value;\n    }, {\n      constant: true,\n      literal: true\n    });\n  },\n\n  statements: function() {\n    var statements = [];\n    while (true) {\n      if (this.tokens.length > 0 && !this.peek('}', ')', ';', ']'))\n        statements.push(this.filterChain());\n      if (!this.expect(';')) {\n        // optimize for the common case where there is only one statement.\n        // TODO(size): maybe we should not support multiple statements?\n        return (statements.length === 1)\n            ? statements[0]\n            : function $parseStatements(self, locals) {\n                var value;\n                for (var i = 0, ii = statements.length; i < ii; i++) {\n                  value = statements[i](self, locals);\n                }\n                return value;\n              };\n      }\n    }\n  },\n\n  filterChain: function() {\n    var left = this.expression();\n    var token;\n    while ((token = this.expect('|'))) {\n      left = this.filter(left);\n    }\n    return left;\n  },\n\n  filter: function(inputFn) {\n    var fn = this.$filter(this.consume().text);\n    var argsFn;\n    var args;\n\n    if (this.peek(':')) {\n      argsFn = [];\n      args = []; // we can safely reuse the array\n      while (this.expect(':')) {\n        argsFn.push(this.expression());\n      }\n    }\n\n    var inputs = [inputFn].concat(argsFn || []);\n\n    return extend(function $parseFilter(self, locals) {\n      var input = inputFn(self, locals);\n      if (args) {\n        args[0] = input;\n\n        var i = argsFn.length;\n        while (i--) {\n          args[i + 1] = argsFn[i](self, locals);\n        }\n\n        return fn.apply(undefined, args);\n      }\n\n      return fn(input);\n    }, {\n      constant: !fn.$stateful && inputs.every(isConstant),\n      inputs: !fn.$stateful && inputs\n    });\n  },\n\n  expression: function() {\n    return this.assignment();\n  },\n\n  assignment: function() {\n    var left = this.ternary();\n    var right;\n    var token;\n    if ((token = this.expect('='))) {\n      if (!left.assign) {\n        this.throwError('implies assignment but [' +\n            this.text.substring(0, token.index) + '] can not be assigned to', token);\n      }\n      right = this.ternary();\n      return extend(function $parseAssignment(scope, locals) {\n        return left.assign(scope, right(scope, locals), locals);\n      }, {\n        inputs: [left, right]\n      });\n    }\n    return left;\n  },\n\n  ternary: function() {\n    var left = this.logicalOR();\n    var middle;\n    var token;\n    if ((token = this.expect('?'))) {\n      middle = this.assignment();\n      if (this.consume(':')) {\n        var right = this.assignment();\n\n        return extend(function $parseTernary(self, locals) {\n          return left(self, locals) ? middle(self, locals) : right(self, locals);\n        }, {\n          constant: left.constant && middle.constant && right.constant\n        });\n      }\n    }\n\n    return left;\n  },\n\n  logicalOR: function() {\n    var left = this.logicalAND();\n    var token;\n    while ((token = this.expect('||'))) {\n      left = this.binaryFn(left, token.text, this.logicalAND(), true);\n    }\n    return left;\n  },\n\n  logicalAND: function() {\n    var left = this.equality();\n    var token;\n    while ((token = this.expect('&&'))) {\n      left = this.binaryFn(left, token.text, this.equality(), true);\n    }\n    return left;\n  },\n\n  equality: function() {\n    var left = this.relational();\n    var token;\n    while ((token = this.expect('==','!=','===','!=='))) {\n      left = this.binaryFn(left, token.text, this.relational());\n    }\n    return left;\n  },\n\n  relational: function() {\n    var left = this.additive();\n    var token;\n    while ((token = this.expect('<', '>', '<=', '>='))) {\n      left = this.binaryFn(left, token.text, this.additive());\n    }\n    return left;\n  },\n\n  additive: function() {\n    var left = this.multiplicative();\n    var token;\n    while ((token = this.expect('+','-'))) {\n      left = this.binaryFn(left, token.text, this.multiplicative());\n    }\n    return left;\n  },\n\n  multiplicative: function() {\n    var left = this.unary();\n    var token;\n    while ((token = this.expect('*','/','%'))) {\n      left = this.binaryFn(left, token.text, this.unary());\n    }\n    return left;\n  },\n\n  unary: function() {\n    var token;\n    if (this.expect('+')) {\n      return this.primary();\n    } else if ((token = this.expect('-'))) {\n      return this.binaryFn(Parser.ZERO, token.text, this.unary());\n    } else if ((token = this.expect('!'))) {\n      return this.unaryFn(token.text, this.unary());\n    } else {\n      return this.primary();\n    }\n  },\n\n  fieldAccess: function(object) {\n    var getter = this.identifier();\n\n    return extend(function $parseFieldAccess(scope, locals, self) {\n      var o = self || object(scope, locals);\n      return (o == null) ? undefined : getter(o);\n    }, {\n      assign: function(scope, value, locals) {\n        var o = object(scope, locals);\n        if (!o) object.assign(scope, o = {}, locals);\n        return getter.assign(o, value);\n      }\n    });\n  },\n\n  objectIndex: function(obj) {\n    var expression = this.text;\n\n    var indexFn = this.expression();\n    this.consume(']');\n\n    return extend(function $parseObjectIndex(self, locals) {\n      var o = obj(self, locals),\n          i = indexFn(self, locals),\n          v;\n\n      ensureSafeMemberName(i, expression);\n      if (!o) return undefined;\n      v = ensureSafeObject(o[i], expression);\n      return v;\n    }, {\n      assign: function(self, value, locals) {\n        var key = ensureSafeMemberName(indexFn(self, locals), expression);\n        // prevent overwriting of Function.constructor which would break ensureSafeObject check\n        var o = ensureSafeObject(obj(self, locals), expression);\n        if (!o) obj.assign(self, o = {}, locals);\n        return o[key] = value;\n      }\n    });\n  },\n\n  functionCall: function(fnGetter, contextGetter) {\n    var argsFn = [];\n    if (this.peekToken().text !== ')') {\n      do {\n        argsFn.push(this.expression());\n      } while (this.expect(','));\n    }\n    this.consume(')');\n\n    var expressionText = this.text;\n    // we can safely reuse the array across invocations\n    var args = argsFn.length ? [] : null;\n\n    return function $parseFunctionCall(scope, locals) {\n      var context = contextGetter ? contextGetter(scope, locals) : isDefined(contextGetter) ? undefined : scope;\n      var fn = fnGetter(scope, locals, context) || noop;\n\n      if (args) {\n        var i = argsFn.length;\n        while (i--) {\n          args[i] = ensureSafeObject(argsFn[i](scope, locals), expressionText);\n        }\n      }\n\n      ensureSafeObject(context, expressionText);\n      ensureSafeFunction(fn, expressionText);\n\n      // IE doesn't have apply for some native functions\n      var v = fn.apply\n            ? fn.apply(context, args)\n            : fn(args[0], args[1], args[2], args[3], args[4]);\n\n      if (args) {\n        // Free-up the memory (arguments of the last function call).\n        args.length = 0;\n      }\n\n      return ensureSafeObject(v, expressionText);\n      };\n  },\n\n  // This is used with json array declaration\n  arrayDeclaration: function() {\n    var elementFns = [];\n    if (this.peekToken().text !== ']') {\n      do {\n        if (this.peek(']')) {\n          // Support trailing commas per ES5.1.\n          break;\n        }\n        elementFns.push(this.expression());\n      } while (this.expect(','));\n    }\n    this.consume(']');\n\n    return extend(function $parseArrayLiteral(self, locals) {\n      var array = [];\n      for (var i = 0, ii = elementFns.length; i < ii; i++) {\n        array.push(elementFns[i](self, locals));\n      }\n      return array;\n    }, {\n      literal: true,\n      constant: elementFns.every(isConstant),\n      inputs: elementFns\n    });\n  },\n\n  object: function() {\n    var keys = [], valueFns = [];\n    if (this.peekToken().text !== '}') {\n      do {\n        if (this.peek('}')) {\n          // Support trailing commas per ES5.1.\n          break;\n        }\n        var token = this.consume();\n        if (token.constant) {\n          keys.push(token.value);\n        } else if (token.identifier) {\n          keys.push(token.text);\n        } else {\n          this.throwError(\"invalid key\", token);\n        }\n        this.consume(':');\n        valueFns.push(this.expression());\n      } while (this.expect(','));\n    }\n    this.consume('}');\n\n    return extend(function $parseObjectLiteral(self, locals) {\n      var object = {};\n      for (var i = 0, ii = valueFns.length; i < ii; i++) {\n        object[keys[i]] = valueFns[i](self, locals);\n      }\n      return object;\n    }, {\n      literal: true,\n      constant: valueFns.every(isConstant),\n      inputs: valueFns\n    });\n  }\n};\n\n\n//////////////////////////////////////////////////\n// Parser helper functions\n//////////////////////////////////////////////////\n\nfunction setter(obj, locals, path, setValue, fullExp) {\n  ensureSafeObject(obj, fullExp);\n  ensureSafeObject(locals, fullExp);\n\n  var element = path.split('.'), key;\n  for (var i = 0; element.length > 1; i++) {\n    key = ensureSafeMemberName(element.shift(), fullExp);\n    var propertyObj = (i === 0 && locals && locals[key]) || obj[key];\n    if (!propertyObj) {\n      propertyObj = {};\n      obj[key] = propertyObj;\n    }\n    obj = ensureSafeObject(propertyObj, fullExp);\n  }\n  key = ensureSafeMemberName(element.shift(), fullExp);\n  ensureSafeObject(obj[key], fullExp);\n  obj[key] = setValue;\n  return setValue;\n}\n\nvar getterFnCacheDefault = createMap();\nvar getterFnCacheExpensive = createMap();\n\nfunction isPossiblyDangerousMemberName(name) {\n  return name == 'constructor';\n}\n\n/**\n * Implementation of the \"Black Hole\" variant from:\n * - http://jsperf.com/angularjs-parse-getter/4\n * - http://jsperf.com/path-evaluation-simplified/7\n */\nfunction cspSafeGetterFn(key0, key1, key2, key3, key4, fullExp, expensiveChecks) {\n  ensureSafeMemberName(key0, fullExp);\n  ensureSafeMemberName(key1, fullExp);\n  ensureSafeMemberName(key2, fullExp);\n  ensureSafeMemberName(key3, fullExp);\n  ensureSafeMemberName(key4, fullExp);\n  var eso = function(o) {\n    return ensureSafeObject(o, fullExp);\n  };\n  var eso0 = (expensiveChecks || isPossiblyDangerousMemberName(key0)) ? eso : identity;\n  var eso1 = (expensiveChecks || isPossiblyDangerousMemberName(key1)) ? eso : identity;\n  var eso2 = (expensiveChecks || isPossiblyDangerousMemberName(key2)) ? eso : identity;\n  var eso3 = (expensiveChecks || isPossiblyDangerousMemberName(key3)) ? eso : identity;\n  var eso4 = (expensiveChecks || isPossiblyDangerousMemberName(key4)) ? eso : identity;\n\n  return function cspSafeGetter(scope, locals) {\n    var pathVal = (locals && locals.hasOwnProperty(key0)) ? locals : scope;\n\n    if (pathVal == null) return pathVal;\n    pathVal = eso0(pathVal[key0]);\n\n    if (!key1) return pathVal;\n    if (pathVal == null) return undefined;\n    pathVal = eso1(pathVal[key1]);\n\n    if (!key2) return pathVal;\n    if (pathVal == null) return undefined;\n    pathVal = eso2(pathVal[key2]);\n\n    if (!key3) return pathVal;\n    if (pathVal == null) return undefined;\n    pathVal = eso3(pathVal[key3]);\n\n    if (!key4) return pathVal;\n    if (pathVal == null) return undefined;\n    pathVal = eso4(pathVal[key4]);\n\n    return pathVal;\n  };\n}\n\nfunction getterFnWithEnsureSafeObject(fn, fullExpression) {\n  return function(s, l) {\n    return fn(s, l, ensureSafeObject, fullExpression);\n  };\n}\n\nfunction getterFn(path, options, fullExp) {\n  var expensiveChecks = options.expensiveChecks;\n  var getterFnCache = (expensiveChecks ? getterFnCacheExpensive : getterFnCacheDefault);\n  var fn = getterFnCache[path];\n  if (fn) return fn;\n\n\n  var pathKeys = path.split('.'),\n      pathKeysLength = pathKeys.length;\n\n  // http://jsperf.com/angularjs-parse-getter/6\n  if (options.csp) {\n    if (pathKeysLength < 6) {\n      fn = cspSafeGetterFn(pathKeys[0], pathKeys[1], pathKeys[2], pathKeys[3], pathKeys[4], fullExp, expensiveChecks);\n    } else {\n      fn = function cspSafeGetter(scope, locals) {\n        var i = 0, val;\n        do {\n          val = cspSafeGetterFn(pathKeys[i++], pathKeys[i++], pathKeys[i++], pathKeys[i++],\n                                pathKeys[i++], fullExp, expensiveChecks)(scope, locals);\n\n          locals = undefined; // clear after first iteration\n          scope = val;\n        } while (i < pathKeysLength);\n        return val;\n      };\n    }\n  } else {\n    var code = '';\n    if (expensiveChecks) {\n      code += 's = eso(s, fe);\\nl = eso(l, fe);\\n';\n    }\n    var needsEnsureSafeObject = expensiveChecks;\n    forEach(pathKeys, function(key, index) {\n      ensureSafeMemberName(key, fullExp);\n      var lookupJs = (index\n                      // we simply dereference 's' on any .dot notation\n                      ? 's'\n                      // but if we are first then we check locals first, and if so read it first\n                      : '((l&&l.hasOwnProperty(\"' + key + '\"))?l:s)') + '.' + key;\n      if (expensiveChecks || isPossiblyDangerousMemberName(key)) {\n        lookupJs = 'eso(' + lookupJs + ', fe)';\n        needsEnsureSafeObject = true;\n      }\n      code += 'if(s == null) return undefined;\\n' +\n              's=' + lookupJs + ';\\n';\n    });\n    code += 'return s;';\n\n    /* jshint -W054 */\n    var evaledFnGetter = new Function('s', 'l', 'eso', 'fe', code); // s=scope, l=locals, eso=ensureSafeObject\n    /* jshint +W054 */\n    evaledFnGetter.toString = valueFn(code);\n    if (needsEnsureSafeObject) {\n      evaledFnGetter = getterFnWithEnsureSafeObject(evaledFnGetter, fullExp);\n    }\n    fn = evaledFnGetter;\n  }\n\n  fn.sharedGetter = true;\n  fn.assign = function(self, value, locals) {\n    return setter(self, locals, path, value, path);\n  };\n  getterFnCache[path] = fn;\n  return fn;\n}\n\nvar objectValueOf = Object.prototype.valueOf;\n\nfunction getValueOf(value) {\n  return isFunction(value.valueOf) ? value.valueOf() : objectValueOf.call(value);\n}\n\n///////////////////////////////////\n\n/**\n * @ngdoc service\n * @name $parse\n * @kind function\n *\n * @description\n *\n * Converts Angular {@link guide/expression expression} into a function.\n *\n * ```js\n *   var getter = $parse('user.name');\n *   var setter = getter.assign;\n *   var context = {user:{name:'angular'}};\n *   var locals = {user:{name:'local'}};\n *\n *   expect(getter(context)).toEqual('angular');\n *   setter(context, 'newValue');\n *   expect(context.user.name).toEqual('newValue');\n *   expect(getter(context, locals)).toEqual('local');\n * ```\n *\n *\n * @param {string} expression String expression to compile.\n * @returns {function(context, locals)} a function which represents the compiled expression:\n *\n *    * `context` – `{object}` – an object against which any expressions embedded in the strings\n *      are evaluated against (typically a scope object).\n *    * `locals` – `{object=}` – local variables context object, useful for overriding values in\n *      `context`.\n *\n *    The returned function also has the following properties:\n *      * `literal` – `{boolean}` – whether the expression's top-level node is a JavaScript\n *        literal.\n *      * `constant` – `{boolean}` – whether the expression is made entirely of JavaScript\n *        constant literals.\n *      * `assign` – `{?function(context, value)}` – if the expression is assignable, this will be\n *        set to a function to change its value on the given context.\n *\n */\n\n\n/**\n * @ngdoc provider\n * @name $parseProvider\n *\n * @description\n * `$parseProvider` can be used for configuring the default behavior of the {@link ng.$parse $parse}\n *  service.\n */\nfunction $ParseProvider() {\n  var cacheDefault = createMap();\n  var cacheExpensive = createMap();\n\n\n\n  this.$get = ['$filter', '$sniffer', function($filter, $sniffer) {\n    var $parseOptions = {\n          csp: $sniffer.csp,\n          expensiveChecks: false\n        },\n        $parseOptionsExpensive = {\n          csp: $sniffer.csp,\n          expensiveChecks: true\n        };\n\n    function wrapSharedExpression(exp) {\n      var wrapped = exp;\n\n      if (exp.sharedGetter) {\n        wrapped = function $parseWrapper(self, locals) {\n          return exp(self, locals);\n        };\n        wrapped.literal = exp.literal;\n        wrapped.constant = exp.constant;\n        wrapped.assign = exp.assign;\n      }\n\n      return wrapped;\n    }\n\n    return function $parse(exp, interceptorFn, expensiveChecks) {\n      var parsedExpression, oneTime, cacheKey;\n\n      switch (typeof exp) {\n        case 'string':\n          cacheKey = exp = exp.trim();\n\n          var cache = (expensiveChecks ? cacheExpensive : cacheDefault);\n          parsedExpression = cache[cacheKey];\n\n          if (!parsedExpression) {\n            if (exp.charAt(0) === ':' && exp.charAt(1) === ':') {\n              oneTime = true;\n              exp = exp.substring(2);\n            }\n\n            var parseOptions = expensiveChecks ? $parseOptionsExpensive : $parseOptions;\n            var lexer = new Lexer(parseOptions);\n            var parser = new Parser(lexer, $filter, parseOptions);\n            parsedExpression = parser.parse(exp);\n\n            if (parsedExpression.constant) {\n              parsedExpression.$$watchDelegate = constantWatchDelegate;\n            } else if (oneTime) {\n              //oneTime is not part of the exp passed to the Parser so we may have to\n              //wrap the parsedExpression before adding a $$watchDelegate\n              parsedExpression = wrapSharedExpression(parsedExpression);\n              parsedExpression.$$watchDelegate = parsedExpression.literal ?\n                oneTimeLiteralWatchDelegate : oneTimeWatchDelegate;\n            } else if (parsedExpression.inputs) {\n              parsedExpression.$$watchDelegate = inputsWatchDelegate;\n            }\n\n            cache[cacheKey] = parsedExpression;\n          }\n          return addInterceptor(parsedExpression, interceptorFn);\n\n        case 'function':\n          return addInterceptor(exp, interceptorFn);\n\n        default:\n          return addInterceptor(noop, interceptorFn);\n      }\n    };\n\n    function collectExpressionInputs(inputs, list) {\n      for (var i = 0, ii = inputs.length; i < ii; i++) {\n        var input = inputs[i];\n        if (!input.constant) {\n          if (input.inputs) {\n            collectExpressionInputs(input.inputs, list);\n          } else if (list.indexOf(input) === -1) { // TODO(perf) can we do better?\n            list.push(input);\n          }\n        }\n      }\n\n      return list;\n    }\n\n    function expressionInputDirtyCheck(newValue, oldValueOfValue) {\n\n      if (newValue == null || oldValueOfValue == null) { // null/undefined\n        return newValue === oldValueOfValue;\n      }\n\n      if (typeof newValue === 'object') {\n\n        // attempt to convert the value to a primitive type\n        // TODO(docs): add a note to docs that by implementing valueOf even objects and arrays can\n        //             be cheaply dirty-checked\n        newValue = getValueOf(newValue);\n\n        if (typeof newValue === 'object') {\n          // objects/arrays are not supported - deep-watching them would be too expensive\n          return false;\n        }\n\n        // fall-through to the primitive equality check\n      }\n\n      //Primitive or NaN\n      return newValue === oldValueOfValue || (newValue !== newValue && oldValueOfValue !== oldValueOfValue);\n    }\n\n    function inputsWatchDelegate(scope, listener, objectEquality, parsedExpression) {\n      var inputExpressions = parsedExpression.$$inputs ||\n                    (parsedExpression.$$inputs = collectExpressionInputs(parsedExpression.inputs, []));\n\n      var lastResult;\n\n      if (inputExpressions.length === 1) {\n        var oldInputValue = expressionInputDirtyCheck; // init to something unique so that equals check fails\n        inputExpressions = inputExpressions[0];\n        return scope.$watch(function expressionInputWatch(scope) {\n          var newInputValue = inputExpressions(scope);\n          if (!expressionInputDirtyCheck(newInputValue, oldInputValue)) {\n            lastResult = parsedExpression(scope);\n            oldInputValue = newInputValue && getValueOf(newInputValue);\n          }\n          return lastResult;\n        }, listener, objectEquality);\n      }\n\n      var oldInputValueOfValues = [];\n      for (var i = 0, ii = inputExpressions.length; i < ii; i++) {\n        oldInputValueOfValues[i] = expressionInputDirtyCheck; // init to something unique so that equals check fails\n      }\n\n      return scope.$watch(function expressionInputsWatch(scope) {\n        var changed = false;\n\n        for (var i = 0, ii = inputExpressions.length; i < ii; i++) {\n          var newInputValue = inputExpressions[i](scope);\n          if (changed || (changed = !expressionInputDirtyCheck(newInputValue, oldInputValueOfValues[i]))) {\n            oldInputValueOfValues[i] = newInputValue && getValueOf(newInputValue);\n          }\n        }\n\n        if (changed) {\n          lastResult = parsedExpression(scope);\n        }\n\n        return lastResult;\n      }, listener, objectEquality);\n    }\n\n    function oneTimeWatchDelegate(scope, listener, objectEquality, parsedExpression) {\n      var unwatch, lastValue;\n      return unwatch = scope.$watch(function oneTimeWatch(scope) {\n        return parsedExpression(scope);\n      }, function oneTimeListener(value, old, scope) {\n        lastValue = value;\n        if (isFunction(listener)) {\n          listener.apply(this, arguments);\n        }\n        if (isDefined(value)) {\n          scope.$$postDigest(function() {\n            if (isDefined(lastValue)) {\n              unwatch();\n            }\n          });\n        }\n      }, objectEquality);\n    }\n\n    function oneTimeLiteralWatchDelegate(scope, listener, objectEquality, parsedExpression) {\n      var unwatch, lastValue;\n      return unwatch = scope.$watch(function oneTimeWatch(scope) {\n        return parsedExpression(scope);\n      }, function oneTimeListener(value, old, scope) {\n        lastValue = value;\n        if (isFunction(listener)) {\n          listener.call(this, value, old, scope);\n        }\n        if (isAllDefined(value)) {\n          scope.$$postDigest(function() {\n            if (isAllDefined(lastValue)) unwatch();\n          });\n        }\n      }, objectEquality);\n\n      function isAllDefined(value) {\n        var allDefined = true;\n        forEach(value, function(val) {\n          if (!isDefined(val)) allDefined = false;\n        });\n        return allDefined;\n      }\n    }\n\n    function constantWatchDelegate(scope, listener, objectEquality, parsedExpression) {\n      var unwatch;\n      return unwatch = scope.$watch(function constantWatch(scope) {\n        return parsedExpression(scope);\n      }, function constantListener(value, old, scope) {\n        if (isFunction(listener)) {\n          listener.apply(this, arguments);\n        }\n        unwatch();\n      }, objectEquality);\n    }\n\n    function addInterceptor(parsedExpression, interceptorFn) {\n      if (!interceptorFn) return parsedExpression;\n      var watchDelegate = parsedExpression.$$watchDelegate;\n\n      var regularWatch =\n          watchDelegate !== oneTimeLiteralWatchDelegate &&\n          watchDelegate !== oneTimeWatchDelegate;\n\n      var fn = regularWatch ? function regularInterceptedExpression(scope, locals) {\n        var value = parsedExpression(scope, locals);\n        return interceptorFn(value, scope, locals);\n      } : function oneTimeInterceptedExpression(scope, locals) {\n        var value = parsedExpression(scope, locals);\n        var result = interceptorFn(value, scope, locals);\n        // we only return the interceptor's result if the\n        // initial value is defined (for bind-once)\n        return isDefined(value) ? result : value;\n      };\n\n      // Propagate $$watchDelegates other then inputsWatchDelegate\n      if (parsedExpression.$$watchDelegate &&\n          parsedExpression.$$watchDelegate !== inputsWatchDelegate) {\n        fn.$$watchDelegate = parsedExpression.$$watchDelegate;\n      } else if (!interceptorFn.$stateful) {\n        // If there is an interceptor, but no watchDelegate then treat the interceptor like\n        // we treat filters - it is assumed to be a pure function unless flagged with $stateful\n        fn.$$watchDelegate = inputsWatchDelegate;\n        fn.inputs = [parsedExpression];\n      }\n\n      return fn;\n    }\n  }];\n}\n\n/**\n * @ngdoc service\n * @name $q\n * @requires $rootScope\n *\n * @description\n * A service that helps you run functions asynchronously, and use their return values (or exceptions)\n * when they are done processing.\n *\n * This is an implementation of promises/deferred objects inspired by\n * [Kris Kowal's Q](https://github.com/kriskowal/q).\n *\n * $q can be used in two fashions --- one which is more similar to Kris Kowal's Q or jQuery's Deferred\n * implementations, and the other which resembles ES6 promises to some degree.\n *\n * # $q constructor\n *\n * The streamlined ES6 style promise is essentially just using $q as a constructor which takes a `resolver`\n * function as the first argument. This is similar to the native Promise implementation from ES6 Harmony,\n * see [MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise).\n *\n * While the constructor-style use is supported, not all of the supporting methods from ES6 Harmony promises are\n * available yet.\n *\n * It can be used like so:\n *\n * ```js\n *   // for the purpose of this example let's assume that variables `$q` and `okToGreet`\n *   // are available in the current lexical scope (they could have been injected or passed in).\n *\n *   function asyncGreet(name) {\n *     // perform some asynchronous operation, resolve or reject the promise when appropriate.\n *     return $q(function(resolve, reject) {\n *       setTimeout(function() {\n *         if (okToGreet(name)) {\n *           resolve('Hello, ' + name + '!');\n *         } else {\n *           reject('Greeting ' + name + ' is not allowed.');\n *         }\n *       }, 1000);\n *     });\n *   }\n *\n *   var promise = asyncGreet('Robin Hood');\n *   promise.then(function(greeting) {\n *     alert('Success: ' + greeting);\n *   }, function(reason) {\n *     alert('Failed: ' + reason);\n *   });\n * ```\n *\n * Note: progress/notify callbacks are not currently supported via the ES6-style interface.\n *\n * However, the more traditional CommonJS-style usage is still available, and documented below.\n *\n * [The CommonJS Promise proposal](http://wiki.commonjs.org/wiki/Promises) describes a promise as an\n * interface for interacting with an object that represents the result of an action that is\n * performed asynchronously, and may or may not be finished at any given point in time.\n *\n * From the perspective of dealing with error handling, deferred and promise APIs are to\n * asynchronous programming what `try`, `catch` and `throw` keywords are to synchronous programming.\n *\n * ```js\n *   // for the purpose of this example let's assume that variables `$q` and `okToGreet`\n *   // are available in the current lexical scope (they could have been injected or passed in).\n *\n *   function asyncGreet(name) {\n *     var deferred = $q.defer();\n *\n *     setTimeout(function() {\n *       deferred.notify('About to greet ' + name + '.');\n *\n *       if (okToGreet(name)) {\n *         deferred.resolve('Hello, ' + name + '!');\n *       } else {\n *         deferred.reject('Greeting ' + name + ' is not allowed.');\n *       }\n *     }, 1000);\n *\n *     return deferred.promise;\n *   }\n *\n *   var promise = asyncGreet('Robin Hood');\n *   promise.then(function(greeting) {\n *     alert('Success: ' + greeting);\n *   }, function(reason) {\n *     alert('Failed: ' + reason);\n *   }, function(update) {\n *     alert('Got notification: ' + update);\n *   });\n * ```\n *\n * At first it might not be obvious why this extra complexity is worth the trouble. The payoff\n * comes in the way of guarantees that promise and deferred APIs make, see\n * https://github.com/kriskowal/uncommonjs/blob/master/promises/specification.md.\n *\n * Additionally the promise api allows for composition that is very hard to do with the\n * traditional callback ([CPS](http://en.wikipedia.org/wiki/Continuation-passing_style)) approach.\n * For more on this please see the [Q documentation](https://github.com/kriskowal/q) especially the\n * section on serial or parallel joining of promises.\n *\n * # The Deferred API\n *\n * A new instance of deferred is constructed by calling `$q.defer()`.\n *\n * The purpose of the deferred object is to expose the associated Promise instance as well as APIs\n * that can be used for signaling the successful or unsuccessful completion, as well as the status\n * of the task.\n *\n * **Methods**\n *\n * - `resolve(value)` – resolves the derived promise with the `value`. If the value is a rejection\n *   constructed via `$q.reject`, the promise will be rejected instead.\n * - `reject(reason)` – rejects the derived promise with the `reason`. This is equivalent to\n *   resolving it with a rejection constructed via `$q.reject`.\n * - `notify(value)` - provides updates on the status of the promise's execution. This may be called\n *   multiple times before the promise is either resolved or rejected.\n *\n * **Properties**\n *\n * - promise – `{Promise}` – promise object associated with this deferred.\n *\n *\n * # The Promise API\n *\n * A new promise instance is created when a deferred instance is created and can be retrieved by\n * calling `deferred.promise`.\n *\n * The purpose of the promise object is to allow for interested parties to get access to the result\n * of the deferred task when it completes.\n *\n * **Methods**\n *\n * - `then(successCallback, errorCallback, notifyCallback)` – regardless of when the promise was or\n *   will be resolved or rejected, `then` calls one of the success or error callbacks asynchronously\n *   as soon as the result is available. The callbacks are called with a single argument: the result\n *   or rejection reason. Additionally, the notify callback may be called zero or more times to\n *   provide a progress indication, before the promise is resolved or rejected.\n *\n *   This method *returns a new promise* which is resolved or rejected via the return value of the\n *   `successCallback`, `errorCallback`. It also notifies via the return value of the\n *   `notifyCallback` method. The promise cannot be resolved or rejected from the notifyCallback\n *   method.\n *\n * - `catch(errorCallback)` – shorthand for `promise.then(null, errorCallback)`\n *\n * - `finally(callback, notifyCallback)` – allows you to observe either the fulfillment or rejection of a promise,\n *   but to do so without modifying the final value. This is useful to release resources or do some\n *   clean-up that needs to be done whether the promise was rejected or resolved. See the [full\n *   specification](https://github.com/kriskowal/q/wiki/API-Reference#promisefinallycallback) for\n *   more information.\n *\n * # Chaining promises\n *\n * Because calling the `then` method of a promise returns a new derived promise, it is easily\n * possible to create a chain of promises:\n *\n * ```js\n *   promiseB = promiseA.then(function(result) {\n *     return result + 1;\n *   });\n *\n *   // promiseB will be resolved immediately after promiseA is resolved and its value\n *   // will be the result of promiseA incremented by 1\n * ```\n *\n * It is possible to create chains of any length and since a promise can be resolved with another\n * promise (which will defer its resolution further), it is possible to pause/defer resolution of\n * the promises at any point in the chain. This makes it possible to implement powerful APIs like\n * $http's response interceptors.\n *\n *\n * # Differences between Kris Kowal's Q and $q\n *\n *  There are two main differences:\n *\n * - $q is integrated with the {@link ng.$rootScope.Scope} Scope model observation\n *   mechanism in angular, which means faster propagation of resolution or rejection into your\n *   models and avoiding unnecessary browser repaints, which would result in flickering UI.\n * - Q has many more features than $q, but that comes at a cost of bytes. $q is tiny, but contains\n *   all the important functionality needed for common async tasks.\n *\n *  # Testing\n *\n *  ```js\n *    it('should simulate promise', inject(function($q, $rootScope) {\n *      var deferred = $q.defer();\n *      var promise = deferred.promise;\n *      var resolvedValue;\n *\n *      promise.then(function(value) { resolvedValue = value; });\n *      expect(resolvedValue).toBeUndefined();\n *\n *      // Simulate resolving of promise\n *      deferred.resolve(123);\n *      // Note that the 'then' function does not get called synchronously.\n *      // This is because we want the promise API to always be async, whether or not\n *      // it got called synchronously or asynchronously.\n *      expect(resolvedValue).toBeUndefined();\n *\n *      // Propagate promise resolution to 'then' functions using $apply().\n *      $rootScope.$apply();\n *      expect(resolvedValue).toEqual(123);\n *    }));\n *  ```\n *\n * @param {function(function, function)} resolver Function which is responsible for resolving or\n *   rejecting the newly created promise. The first parameter is a function which resolves the\n *   promise, the second parameter is a function which rejects the promise.\n *\n * @returns {Promise} The newly created promise.\n */\nfunction $QProvider() {\n\n  this.$get = ['$rootScope', '$exceptionHandler', function($rootScope, $exceptionHandler) {\n    return qFactory(function(callback) {\n      $rootScope.$evalAsync(callback);\n    }, $exceptionHandler);\n  }];\n}\n\nfunction $$QProvider() {\n  this.$get = ['$browser', '$exceptionHandler', function($browser, $exceptionHandler) {\n    return qFactory(function(callback) {\n      $browser.defer(callback);\n    }, $exceptionHandler);\n  }];\n}\n\n/**\n * Constructs a promise manager.\n *\n * @param {function(function)} nextTick Function for executing functions in the next turn.\n * @param {function(...*)} exceptionHandler Function into which unexpected exceptions are passed for\n *     debugging purposes.\n * @returns {object} Promise manager.\n */\nfunction qFactory(nextTick, exceptionHandler) {\n  var $qMinErr = minErr('$q', TypeError);\n  function callOnce(self, resolveFn, rejectFn) {\n    var called = false;\n    function wrap(fn) {\n      return function(value) {\n        if (called) return;\n        called = true;\n        fn.call(self, value);\n      };\n    }\n\n    return [wrap(resolveFn), wrap(rejectFn)];\n  }\n\n  /**\n   * @ngdoc method\n   * @name ng.$q#defer\n   * @kind function\n   *\n   * @description\n   * Creates a `Deferred` object which represents a task which will finish in the future.\n   *\n   * @returns {Deferred} Returns a new instance of deferred.\n   */\n  var defer = function() {\n    return new Deferred();\n  };\n\n  function Promise() {\n    this.$$state = { status: 0 };\n  }\n\n  Promise.prototype = {\n    then: function(onFulfilled, onRejected, progressBack) {\n      var result = new Deferred();\n\n      this.$$state.pending = this.$$state.pending || [];\n      this.$$state.pending.push([result, onFulfilled, onRejected, progressBack]);\n      if (this.$$state.status > 0) scheduleProcessQueue(this.$$state);\n\n      return result.promise;\n    },\n\n    \"catch\": function(callback) {\n      return this.then(null, callback);\n    },\n\n    \"finally\": function(callback, progressBack) {\n      return this.then(function(value) {\n        return handleCallback(value, true, callback);\n      }, function(error) {\n        return handleCallback(error, false, callback);\n      }, progressBack);\n    }\n  };\n\n  //Faster, more basic than angular.bind http://jsperf.com/angular-bind-vs-custom-vs-native\n  function simpleBind(context, fn) {\n    return function(value) {\n      fn.call(context, value);\n    };\n  }\n\n  function processQueue(state) {\n    var fn, promise, pending;\n\n    pending = state.pending;\n    state.processScheduled = false;\n    state.pending = undefined;\n    for (var i = 0, ii = pending.length; i < ii; ++i) {\n      promise = pending[i][0];\n      fn = pending[i][state.status];\n      try {\n        if (isFunction(fn)) {\n          promise.resolve(fn(state.value));\n        } else if (state.status === 1) {\n          promise.resolve(state.value);\n        } else {\n          promise.reject(state.value);\n        }\n      } catch (e) {\n        promise.reject(e);\n        exceptionHandler(e);\n      }\n    }\n  }\n\n  function scheduleProcessQueue(state) {\n    if (state.processScheduled || !state.pending) return;\n    state.processScheduled = true;\n    nextTick(function() { processQueue(state); });\n  }\n\n  function Deferred() {\n    this.promise = new Promise();\n    //Necessary to support unbound execution :/\n    this.resolve = simpleBind(this, this.resolve);\n    this.reject = simpleBind(this, this.reject);\n    this.notify = simpleBind(this, this.notify);\n  }\n\n  Deferred.prototype = {\n    resolve: function(val) {\n      if (this.promise.$$state.status) return;\n      if (val === this.promise) {\n        this.$$reject($qMinErr(\n          'qcycle',\n          \"Expected promise to be resolved with value other than itself '{0}'\",\n          val));\n      } else {\n        this.$$resolve(val);\n      }\n\n    },\n\n    $$resolve: function(val) {\n      var then, fns;\n\n      fns = callOnce(this, this.$$resolve, this.$$reject);\n      try {\n        if ((isObject(val) || isFunction(val))) then = val && val.then;\n        if (isFunction(then)) {\n          this.promise.$$state.status = -1;\n          then.call(val, fns[0], fns[1], this.notify);\n        } else {\n          this.promise.$$state.value = val;\n          this.promise.$$state.status = 1;\n          scheduleProcessQueue(this.promise.$$state);\n        }\n      } catch (e) {\n        fns[1](e);\n        exceptionHandler(e);\n      }\n    },\n\n    reject: function(reason) {\n      if (this.promise.$$state.status) return;\n      this.$$reject(reason);\n    },\n\n    $$reject: function(reason) {\n      this.promise.$$state.value = reason;\n      this.promise.$$state.status = 2;\n      scheduleProcessQueue(this.promise.$$state);\n    },\n\n    notify: function(progress) {\n      var callbacks = this.promise.$$state.pending;\n\n      if ((this.promise.$$state.status <= 0) && callbacks && callbacks.length) {\n        nextTick(function() {\n          var callback, result;\n          for (var i = 0, ii = callbacks.length; i < ii; i++) {\n            result = callbacks[i][0];\n            callback = callbacks[i][3];\n            try {\n              result.notify(isFunction(callback) ? callback(progress) : progress);\n            } catch (e) {\n              exceptionHandler(e);\n            }\n          }\n        });\n      }\n    }\n  };\n\n  /**\n   * @ngdoc method\n   * @name $q#reject\n   * @kind function\n   *\n   * @description\n   * Creates a promise that is resolved as rejected with the specified `reason`. This api should be\n   * used to forward rejection in a chain of promises. If you are dealing with the last promise in\n   * a promise chain, you don't need to worry about it.\n   *\n   * When comparing deferreds/promises to the familiar behavior of try/catch/throw, think of\n   * `reject` as the `throw` keyword in JavaScript. This also means that if you \"catch\" an error via\n   * a promise error callback and you want to forward the error to the promise derived from the\n   * current promise, you have to \"rethrow\" the error by returning a rejection constructed via\n   * `reject`.\n   *\n   * ```js\n   *   promiseB = promiseA.then(function(result) {\n   *     // success: do something and resolve promiseB\n   *     //          with the old or a new result\n   *     return result;\n   *   }, function(reason) {\n   *     // error: handle the error if possible and\n   *     //        resolve promiseB with newPromiseOrValue,\n   *     //        otherwise forward the rejection to promiseB\n   *     if (canHandle(reason)) {\n   *      // handle the error and recover\n   *      return newPromiseOrValue;\n   *     }\n   *     return $q.reject(reason);\n   *   });\n   * ```\n   *\n   * @param {*} reason Constant, message, exception or an object representing the rejection reason.\n   * @returns {Promise} Returns a promise that was already resolved as rejected with the `reason`.\n   */\n  var reject = function(reason) {\n    var result = new Deferred();\n    result.reject(reason);\n    return result.promise;\n  };\n\n  var makePromise = function makePromise(value, resolved) {\n    var result = new Deferred();\n    if (resolved) {\n      result.resolve(value);\n    } else {\n      result.reject(value);\n    }\n    return result.promise;\n  };\n\n  var handleCallback = function handleCallback(value, isResolved, callback) {\n    var callbackOutput = null;\n    try {\n      if (isFunction(callback)) callbackOutput = callback();\n    } catch (e) {\n      return makePromise(e, false);\n    }\n    if (isPromiseLike(callbackOutput)) {\n      return callbackOutput.then(function() {\n        return makePromise(value, isResolved);\n      }, function(error) {\n        return makePromise(error, false);\n      });\n    } else {\n      return makePromise(value, isResolved);\n    }\n  };\n\n  /**\n   * @ngdoc method\n   * @name $q#when\n   * @kind function\n   *\n   * @description\n   * Wraps an object that might be a value or a (3rd party) then-able promise into a $q promise.\n   * This is useful when you are dealing with an object that might or might not be a promise, or if\n   * the promise comes from a source that can't be trusted.\n   *\n   * @param {*} value Value or a promise\n   * @returns {Promise} Returns a promise of the passed value or promise\n   */\n\n\n  var when = function(value, callback, errback, progressBack) {\n    var result = new Deferred();\n    result.resolve(value);\n    return result.promise.then(callback, errback, progressBack);\n  };\n\n  /**\n   * @ngdoc method\n   * @name $q#all\n   * @kind function\n   *\n   * @description\n   * Combines multiple promises into a single promise that is resolved when all of the input\n   * promises are resolved.\n   *\n   * @param {Array.<Promise>|Object.<Promise>} promises An array or hash of promises.\n   * @returns {Promise} Returns a single promise that will be resolved with an array/hash of values,\n   *   each value corresponding to the promise at the same index/key in the `promises` array/hash.\n   *   If any of the promises is resolved with a rejection, this resulting promise will be rejected\n   *   with the same rejection value.\n   */\n\n  function all(promises) {\n    var deferred = new Deferred(),\n        counter = 0,\n        results = isArray(promises) ? [] : {};\n\n    forEach(promises, function(promise, key) {\n      counter++;\n      when(promise).then(function(value) {\n        if (results.hasOwnProperty(key)) return;\n        results[key] = value;\n        if (!(--counter)) deferred.resolve(results);\n      }, function(reason) {\n        if (results.hasOwnProperty(key)) return;\n        deferred.reject(reason);\n      });\n    });\n\n    if (counter === 0) {\n      deferred.resolve(results);\n    }\n\n    return deferred.promise;\n  }\n\n  var $Q = function Q(resolver) {\n    if (!isFunction(resolver)) {\n      throw $qMinErr('norslvr', \"Expected resolverFn, got '{0}'\", resolver);\n    }\n\n    if (!(this instanceof Q)) {\n      // More useful when $Q is the Promise itself.\n      return new Q(resolver);\n    }\n\n    var deferred = new Deferred();\n\n    function resolveFn(value) {\n      deferred.resolve(value);\n    }\n\n    function rejectFn(reason) {\n      deferred.reject(reason);\n    }\n\n    resolver(resolveFn, rejectFn);\n\n    return deferred.promise;\n  };\n\n  $Q.defer = defer;\n  $Q.reject = reject;\n  $Q.when = when;\n  $Q.all = all;\n\n  return $Q;\n}\n\nfunction $$RAFProvider() { //rAF\n  this.$get = ['$window', '$timeout', function($window, $timeout) {\n    var requestAnimationFrame = $window.requestAnimationFrame ||\n                                $window.webkitRequestAnimationFrame;\n\n    var cancelAnimationFrame = $window.cancelAnimationFrame ||\n                               $window.webkitCancelAnimationFrame ||\n                               $window.webkitCancelRequestAnimationFrame;\n\n    var rafSupported = !!requestAnimationFrame;\n    var raf = rafSupported\n      ? function(fn) {\n          var id = requestAnimationFrame(fn);\n          return function() {\n            cancelAnimationFrame(id);\n          };\n        }\n      : function(fn) {\n          var timer = $timeout(fn, 16.66, false); // 1000 / 60 = 16.666\n          return function() {\n            $timeout.cancel(timer);\n          };\n        };\n\n    raf.supported = rafSupported;\n\n    return raf;\n  }];\n}\n\n/**\n * DESIGN NOTES\n *\n * The design decisions behind the scope are heavily favored for speed and memory consumption.\n *\n * The typical use of scope is to watch the expressions, which most of the time return the same\n * value as last time so we optimize the operation.\n *\n * Closures construction is expensive in terms of speed as well as memory:\n *   - No closures, instead use prototypical inheritance for API\n *   - Internal state needs to be stored on scope directly, which means that private state is\n *     exposed as $$____ properties\n *\n * Loop operations are optimized by using while(count--) { ... }\n *   - this means that in order to keep the same order of execution as addition we have to add\n *     items to the array at the beginning (unshift) instead of at the end (push)\n *\n * Child scopes are created and removed often\n *   - Using an array would be slow since inserts in middle are expensive so we use linked list\n *\n * There are few watches then a lot of observers. This is why you don't want the observer to be\n * implemented in the same way as watch. Watch requires return of initialization function which\n * are expensive to construct.\n */\n\n\n/**\n * @ngdoc provider\n * @name $rootScopeProvider\n * @description\n *\n * Provider for the $rootScope service.\n */\n\n/**\n * @ngdoc method\n * @name $rootScopeProvider#digestTtl\n * @description\n *\n * Sets the number of `$digest` iterations the scope should attempt to execute before giving up and\n * assuming that the model is unstable.\n *\n * The current default is 10 iterations.\n *\n * In complex applications it's possible that the dependencies between `$watch`s will result in\n * several digest iterations. However if an application needs more than the default 10 digest\n * iterations for its model to stabilize then you should investigate what is causing the model to\n * continuously change during the digest.\n *\n * Increasing the TTL could have performance implications, so you should not change it without\n * proper justification.\n *\n * @param {number} limit The number of digest iterations.\n */\n\n\n/**\n * @ngdoc service\n * @name $rootScope\n * @description\n *\n * Every application has a single root {@link ng.$rootScope.Scope scope}.\n * All other scopes are descendant scopes of the root scope. Scopes provide separation\n * between the model and the view, via a mechanism for watching the model for changes.\n * They also provide an event emission/broadcast and subscription facility. See the\n * {@link guide/scope developer guide on scopes}.\n */\nfunction $RootScopeProvider() {\n  var TTL = 10;\n  var $rootScopeMinErr = minErr('$rootScope');\n  var lastDirtyWatch = null;\n  var applyAsyncId = null;\n\n  this.digestTtl = function(value) {\n    if (arguments.length) {\n      TTL = value;\n    }\n    return TTL;\n  };\n\n  this.$get = ['$injector', '$exceptionHandler', '$parse', '$browser',\n      function($injector, $exceptionHandler, $parse, $browser) {\n\n    /**\n     * @ngdoc type\n     * @name $rootScope.Scope\n     *\n     * @description\n     * A root scope can be retrieved using the {@link ng.$rootScope $rootScope} key from the\n     * {@link auto.$injector $injector}. Child scopes are created using the\n     * {@link ng.$rootScope.Scope#$new $new()} method. (Most scopes are created automatically when\n     * compiled HTML template is executed.)\n     *\n     * Here is a simple scope snippet to show how you can interact with the scope.\n     * ```html\n     * <file src=\"./test/ng/rootScopeSpec.js\" tag=\"docs1\" />\n     * ```\n     *\n     * # Inheritance\n     * A scope can inherit from a parent scope, as in this example:\n     * ```js\n         var parent = $rootScope;\n         var child = parent.$new();\n\n         parent.salutation = \"Hello\";\n         expect(child.salutation).toEqual('Hello');\n\n         child.salutation = \"Welcome\";\n         expect(child.salutation).toEqual('Welcome');\n         expect(parent.salutation).toEqual('Hello');\n     * ```\n     *\n     * When interacting with `Scope` in tests, additional helper methods are available on the\n     * instances of `Scope` type. See {@link ngMock.$rootScope.Scope ngMock Scope} for additional\n     * details.\n     *\n     *\n     * @param {Object.<string, function()>=} providers Map of service factory which need to be\n     *                                       provided for the current scope. Defaults to {@link ng}.\n     * @param {Object.<string, *>=} instanceCache Provides pre-instantiated services which should\n     *                              append/override services provided by `providers`. This is handy\n     *                              when unit-testing and having the need to override a default\n     *                              service.\n     * @returns {Object} Newly created scope.\n     *\n     */\n    function Scope() {\n      this.$id = nextUid();\n      this.$$phase = this.$parent = this.$$watchers =\n                     this.$$nextSibling = this.$$prevSibling =\n                     this.$$childHead = this.$$childTail = null;\n      this.$root = this;\n      this.$$destroyed = false;\n      this.$$listeners = {};\n      this.$$listenerCount = {};\n      this.$$isolateBindings = null;\n    }\n\n    /**\n     * @ngdoc property\n     * @name $rootScope.Scope#$id\n     *\n     * @description\n     * Unique scope ID (monotonically increasing) useful for debugging.\n     */\n\n     /**\n      * @ngdoc property\n      * @name $rootScope.Scope#$parent\n      *\n      * @description\n      * Reference to the parent scope.\n      */\n\n      /**\n       * @ngdoc property\n       * @name $rootScope.Scope#$root\n       *\n       * @description\n       * Reference to the root scope.\n       */\n\n    Scope.prototype = {\n      constructor: Scope,\n      /**\n       * @ngdoc method\n       * @name $rootScope.Scope#$new\n       * @kind function\n       *\n       * @description\n       * Creates a new child {@link ng.$rootScope.Scope scope}.\n       *\n       * The parent scope will propagate the {@link ng.$rootScope.Scope#$digest $digest()} event.\n       * The scope can be removed from the scope hierarchy using {@link ng.$rootScope.Scope#$destroy $destroy()}.\n       *\n       * {@link ng.$rootScope.Scope#$destroy $destroy()} must be called on a scope when it is\n       * desired for the scope and its child scopes to be permanently detached from the parent and\n       * thus stop participating in model change detection and listener notification by invoking.\n       *\n       * @param {boolean} isolate If true, then the scope does not prototypically inherit from the\n       *         parent scope. The scope is isolated, as it can not see parent scope properties.\n       *         When creating widgets, it is useful for the widget to not accidentally read parent\n       *         state.\n       *\n       * @param {Scope} [parent=this] The {@link ng.$rootScope.Scope `Scope`} that will be the `$parent`\n       *                              of the newly created scope. Defaults to `this` scope if not provided.\n       *                              This is used when creating a transclude scope to correctly place it\n       *                              in the scope hierarchy while maintaining the correct prototypical\n       *                              inheritance.\n       *\n       * @returns {Object} The newly created child scope.\n       *\n       */\n      $new: function(isolate, parent) {\n        var child;\n\n        parent = parent || this;\n\n        if (isolate) {\n          child = new Scope();\n          child.$root = this.$root;\n        } else {\n          // Only create a child scope class if somebody asks for one,\n          // but cache it to allow the VM to optimize lookups.\n          if (!this.$$ChildScope) {\n            this.$$ChildScope = function ChildScope() {\n              this.$$watchers = this.$$nextSibling =\n                  this.$$childHead = this.$$childTail = null;\n              this.$$listeners = {};\n              this.$$listenerCount = {};\n              this.$id = nextUid();\n              this.$$ChildScope = null;\n            };\n            this.$$ChildScope.prototype = this;\n          }\n          child = new this.$$ChildScope();\n        }\n        child.$parent = parent;\n        child.$$prevSibling = parent.$$childTail;\n        if (parent.$$childHead) {\n          parent.$$childTail.$$nextSibling = child;\n          parent.$$childTail = child;\n        } else {\n          parent.$$childHead = parent.$$childTail = child;\n        }\n\n        // When the new scope is not isolated or we inherit from `this`, and\n        // the parent scope is destroyed, the property `$$destroyed` is inherited\n        // prototypically. In all other cases, this property needs to be set\n        // when the parent scope is destroyed.\n        // The listener needs to be added after the parent is set\n        if (isolate || parent != this) child.$on('$destroy', destroyChild);\n\n        return child;\n\n        function destroyChild() {\n          child.$$destroyed = true;\n        }\n      },\n\n      /**\n       * @ngdoc method\n       * @name $rootScope.Scope#$watch\n       * @kind function\n       *\n       * @description\n       * Registers a `listener` callback to be executed whenever the `watchExpression` changes.\n       *\n       * - The `watchExpression` is called on every call to {@link ng.$rootScope.Scope#$digest\n       *   $digest()} and should return the value that will be watched. (Since\n       *   {@link ng.$rootScope.Scope#$digest $digest()} reruns when it detects changes the\n       *   `watchExpression` can execute multiple times per\n       *   {@link ng.$rootScope.Scope#$digest $digest()} and should be idempotent.)\n       * - The `listener` is called only when the value from the current `watchExpression` and the\n       *   previous call to `watchExpression` are not equal (with the exception of the initial run,\n       *   see below). Inequality is determined according to reference inequality,\n       *   [strict comparison](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Comparison_Operators)\n       *    via the `!==` Javascript operator, unless `objectEquality == true`\n       *   (see next point)\n       * - When `objectEquality == true`, inequality of the `watchExpression` is determined\n       *   according to the {@link angular.equals} function. To save the value of the object for\n       *   later comparison, the {@link angular.copy} function is used. This therefore means that\n       *   watching complex objects will have adverse memory and performance implications.\n       * - The watch `listener` may change the model, which may trigger other `listener`s to fire.\n       *   This is achieved by rerunning the watchers until no changes are detected. The rerun\n       *   iteration limit is 10 to prevent an infinite loop deadlock.\n       *\n       *\n       * If you want to be notified whenever {@link ng.$rootScope.Scope#$digest $digest} is called,\n       * you can register a `watchExpression` function with no `listener`. (Since `watchExpression`\n       * can execute multiple times per {@link ng.$rootScope.Scope#$digest $digest} cycle when a\n       * change is detected, be prepared for multiple calls to your listener.)\n       *\n       * After a watcher is registered with the scope, the `listener` fn is called asynchronously\n       * (via {@link ng.$rootScope.Scope#$evalAsync $evalAsync}) to initialize the\n       * watcher. In rare cases, this is undesirable because the listener is called when the result\n       * of `watchExpression` didn't change. To detect this scenario within the `listener` fn, you\n       * can compare the `newVal` and `oldVal`. If these two values are identical (`===`) then the\n       * listener was called due to initialization.\n       *\n       *\n       *\n       * # Example\n       * ```js\n           // let's assume that scope was dependency injected as the $rootScope\n           var scope = $rootScope;\n           scope.name = 'misko';\n           scope.counter = 0;\n\n           expect(scope.counter).toEqual(0);\n           scope.$watch('name', function(newValue, oldValue) {\n             scope.counter = scope.counter + 1;\n           });\n           expect(scope.counter).toEqual(0);\n\n           scope.$digest();\n           // the listener is always called during the first $digest loop after it was registered\n           expect(scope.counter).toEqual(1);\n\n           scope.$digest();\n           // but now it will not be called unless the value changes\n           expect(scope.counter).toEqual(1);\n\n           scope.name = 'adam';\n           scope.$digest();\n           expect(scope.counter).toEqual(2);\n\n\n\n           // Using a function as a watchExpression\n           var food;\n           scope.foodCounter = 0;\n           expect(scope.foodCounter).toEqual(0);\n           scope.$watch(\n             // This function returns the value being watched. It is called for each turn of the $digest loop\n             function() { return food; },\n             // This is the change listener, called when the value returned from the above function changes\n             function(newValue, oldValue) {\n               if ( newValue !== oldValue ) {\n                 // Only increment the counter if the value changed\n                 scope.foodCounter = scope.foodCounter + 1;\n               }\n             }\n           );\n           // No digest has been run so the counter will be zero\n           expect(scope.foodCounter).toEqual(0);\n\n           // Run the digest but since food has not changed count will still be zero\n           scope.$digest();\n           expect(scope.foodCounter).toEqual(0);\n\n           // Update food and run digest.  Now the counter will increment\n           food = 'cheeseburger';\n           scope.$digest();\n           expect(scope.foodCounter).toEqual(1);\n\n       * ```\n       *\n       *\n       *\n       * @param {(function()|string)} watchExpression Expression that is evaluated on each\n       *    {@link ng.$rootScope.Scope#$digest $digest} cycle. A change in the return value triggers\n       *    a call to the `listener`.\n       *\n       *    - `string`: Evaluated as {@link guide/expression expression}\n       *    - `function(scope)`: called with current `scope` as a parameter.\n       * @param {function(newVal, oldVal, scope)} listener Callback called whenever the value\n       *    of `watchExpression` changes.\n       *\n       *    - `newVal` contains the current value of the `watchExpression`\n       *    - `oldVal` contains the previous value of the `watchExpression`\n       *    - `scope` refers to the current scope\n       * @param {boolean=} objectEquality Compare for object equality using {@link angular.equals} instead of\n       *     comparing for reference equality.\n       * @returns {function()} Returns a deregistration function for this listener.\n       */\n      $watch: function(watchExp, listener, objectEquality) {\n        var get = $parse(watchExp);\n\n        if (get.$$watchDelegate) {\n          return get.$$watchDelegate(this, listener, objectEquality, get);\n        }\n        var scope = this,\n            array = scope.$$watchers,\n            watcher = {\n              fn: listener,\n              last: initWatchVal,\n              get: get,\n              exp: watchExp,\n              eq: !!objectEquality\n            };\n\n        lastDirtyWatch = null;\n\n        if (!isFunction(listener)) {\n          watcher.fn = noop;\n        }\n\n        if (!array) {\n          array = scope.$$watchers = [];\n        }\n        // we use unshift since we use a while loop in $digest for speed.\n        // the while loop reads in reverse order.\n        array.unshift(watcher);\n\n        return function deregisterWatch() {\n          arrayRemove(array, watcher);\n          lastDirtyWatch = null;\n        };\n      },\n\n      /**\n       * @ngdoc method\n       * @name $rootScope.Scope#$watchGroup\n       * @kind function\n       *\n       * @description\n       * A variant of {@link ng.$rootScope.Scope#$watch $watch()} where it watches an array of `watchExpressions`.\n       * If any one expression in the collection changes the `listener` is executed.\n       *\n       * - The items in the `watchExpressions` array are observed via standard $watch operation and are examined on every\n       *   call to $digest() to see if any items changes.\n       * - The `listener` is called whenever any expression in the `watchExpressions` array changes.\n       *\n       * @param {Array.<string|Function(scope)>} watchExpressions Array of expressions that will be individually\n       * watched using {@link ng.$rootScope.Scope#$watch $watch()}\n       *\n       * @param {function(newValues, oldValues, scope)} listener Callback called whenever the return value of any\n       *    expression in `watchExpressions` changes\n       *    The `newValues` array contains the current values of the `watchExpressions`, with the indexes matching\n       *    those of `watchExpression`\n       *    and the `oldValues` array contains the previous values of the `watchExpressions`, with the indexes matching\n       *    those of `watchExpression`\n       *    The `scope` refers to the current scope.\n       * @returns {function()} Returns a de-registration function for all listeners.\n       */\n      $watchGroup: function(watchExpressions, listener) {\n        var oldValues = new Array(watchExpressions.length);\n        var newValues = new Array(watchExpressions.length);\n        var deregisterFns = [];\n        var self = this;\n        var changeReactionScheduled = false;\n        var firstRun = true;\n\n        if (!watchExpressions.length) {\n          // No expressions means we call the listener ASAP\n          var shouldCall = true;\n          self.$evalAsync(function() {\n            if (shouldCall) listener(newValues, newValues, self);\n          });\n          return function deregisterWatchGroup() {\n            shouldCall = false;\n          };\n        }\n\n        if (watchExpressions.length === 1) {\n          // Special case size of one\n          return this.$watch(watchExpressions[0], function watchGroupAction(value, oldValue, scope) {\n            newValues[0] = value;\n            oldValues[0] = oldValue;\n            listener(newValues, (value === oldValue) ? newValues : oldValues, scope);\n          });\n        }\n\n        forEach(watchExpressions, function(expr, i) {\n          var unwatchFn = self.$watch(expr, function watchGroupSubAction(value, oldValue) {\n            newValues[i] = value;\n            oldValues[i] = oldValue;\n            if (!changeReactionScheduled) {\n              changeReactionScheduled = true;\n              self.$evalAsync(watchGroupAction);\n            }\n          });\n          deregisterFns.push(unwatchFn);\n        });\n\n        function watchGroupAction() {\n          changeReactionScheduled = false;\n\n          if (firstRun) {\n            firstRun = false;\n            listener(newValues, newValues, self);\n          } else {\n            listener(newValues, oldValues, self);\n          }\n        }\n\n        return function deregisterWatchGroup() {\n          while (deregisterFns.length) {\n            deregisterFns.shift()();\n          }\n        };\n      },\n\n\n      /**\n       * @ngdoc method\n       * @name $rootScope.Scope#$watchCollection\n       * @kind function\n       *\n       * @description\n       * Shallow watches the properties of an object and fires whenever any of the properties change\n       * (for arrays, this implies watching the array items; for object maps, this implies watching\n       * the properties). If a change is detected, the `listener` callback is fired.\n       *\n       * - The `obj` collection is observed via standard $watch operation and is examined on every\n       *   call to $digest() to see if any items have been added, removed, or moved.\n       * - The `listener` is called whenever anything within the `obj` has changed. Examples include\n       *   adding, removing, and moving items belonging to an object or array.\n       *\n       *\n       * # Example\n       * ```js\n          $scope.names = ['igor', 'matias', 'misko', 'james'];\n          $scope.dataCount = 4;\n\n          $scope.$watchCollection('names', function(newNames, oldNames) {\n            $scope.dataCount = newNames.length;\n          });\n\n          expect($scope.dataCount).toEqual(4);\n          $scope.$digest();\n\n          //still at 4 ... no changes\n          expect($scope.dataCount).toEqual(4);\n\n          $scope.names.pop();\n          $scope.$digest();\n\n          //now there's been a change\n          expect($scope.dataCount).toEqual(3);\n       * ```\n       *\n       *\n       * @param {string|function(scope)} obj Evaluated as {@link guide/expression expression}. The\n       *    expression value should evaluate to an object or an array which is observed on each\n       *    {@link ng.$rootScope.Scope#$digest $digest} cycle. Any shallow change within the\n       *    collection will trigger a call to the `listener`.\n       *\n       * @param {function(newCollection, oldCollection, scope)} listener a callback function called\n       *    when a change is detected.\n       *    - The `newCollection` object is the newly modified data obtained from the `obj` expression\n       *    - The `oldCollection` object is a copy of the former collection data.\n       *      Due to performance considerations, the`oldCollection` value is computed only if the\n       *      `listener` function declares two or more arguments.\n       *    - The `scope` argument refers to the current scope.\n       *\n       * @returns {function()} Returns a de-registration function for this listener. When the\n       *    de-registration function is executed, the internal watch operation is terminated.\n       */\n      $watchCollection: function(obj, listener) {\n        $watchCollectionInterceptor.$stateful = true;\n\n        var self = this;\n        // the current value, updated on each dirty-check run\n        var newValue;\n        // a shallow copy of the newValue from the last dirty-check run,\n        // updated to match newValue during dirty-check run\n        var oldValue;\n        // a shallow copy of the newValue from when the last change happened\n        var veryOldValue;\n        // only track veryOldValue if the listener is asking for it\n        var trackVeryOldValue = (listener.length > 1);\n        var changeDetected = 0;\n        var changeDetector = $parse(obj, $watchCollectionInterceptor);\n        var internalArray = [];\n        var internalObject = {};\n        var initRun = true;\n        var oldLength = 0;\n\n        function $watchCollectionInterceptor(_value) {\n          newValue = _value;\n          var newLength, key, bothNaN, newItem, oldItem;\n\n          // If the new value is undefined, then return undefined as the watch may be a one-time watch\n          if (isUndefined(newValue)) return;\n\n          if (!isObject(newValue)) { // if primitive\n            if (oldValue !== newValue) {\n              oldValue = newValue;\n              changeDetected++;\n            }\n          } else if (isArrayLike(newValue)) {\n            if (oldValue !== internalArray) {\n              // we are transitioning from something which was not an array into array.\n              oldValue = internalArray;\n              oldLength = oldValue.length = 0;\n              changeDetected++;\n            }\n\n            newLength = newValue.length;\n\n            if (oldLength !== newLength) {\n              // if lengths do not match we need to trigger change notification\n              changeDetected++;\n              oldValue.length = oldLength = newLength;\n            }\n            // copy the items to oldValue and look for changes.\n            for (var i = 0; i < newLength; i++) {\n              oldItem = oldValue[i];\n              newItem = newValue[i];\n\n              bothNaN = (oldItem !== oldItem) && (newItem !== newItem);\n              if (!bothNaN && (oldItem !== newItem)) {\n                changeDetected++;\n                oldValue[i] = newItem;\n              }\n            }\n          } else {\n            if (oldValue !== internalObject) {\n              // we are transitioning from something which was not an object into object.\n              oldValue = internalObject = {};\n              oldLength = 0;\n              changeDetected++;\n            }\n            // copy the items to oldValue and look for changes.\n            newLength = 0;\n            for (key in newValue) {\n              if (newValue.hasOwnProperty(key)) {\n                newLength++;\n                newItem = newValue[key];\n                oldItem = oldValue[key];\n\n                if (key in oldValue) {\n                  bothNaN = (oldItem !== oldItem) && (newItem !== newItem);\n                  if (!bothNaN && (oldItem !== newItem)) {\n                    changeDetected++;\n                    oldValue[key] = newItem;\n                  }\n                } else {\n                  oldLength++;\n                  oldValue[key] = newItem;\n                  changeDetected++;\n                }\n              }\n            }\n            if (oldLength > newLength) {\n              // we used to have more keys, need to find them and destroy them.\n              changeDetected++;\n              for (key in oldValue) {\n                if (!newValue.hasOwnProperty(key)) {\n                  oldLength--;\n                  delete oldValue[key];\n                }\n              }\n            }\n          }\n          return changeDetected;\n        }\n\n        function $watchCollectionAction() {\n          if (initRun) {\n            initRun = false;\n            listener(newValue, newValue, self);\n          } else {\n            listener(newValue, veryOldValue, self);\n          }\n\n          // make a copy for the next time a collection is changed\n          if (trackVeryOldValue) {\n            if (!isObject(newValue)) {\n              //primitive\n              veryOldValue = newValue;\n            } else if (isArrayLike(newValue)) {\n              veryOldValue = new Array(newValue.length);\n              for (var i = 0; i < newValue.length; i++) {\n                veryOldValue[i] = newValue[i];\n              }\n            } else { // if object\n              veryOldValue = {};\n              for (var key in newValue) {\n                if (hasOwnProperty.call(newValue, key)) {\n                  veryOldValue[key] = newValue[key];\n                }\n              }\n            }\n          }\n        }\n\n        return this.$watch(changeDetector, $watchCollectionAction);\n      },\n\n      /**\n       * @ngdoc method\n       * @name $rootScope.Scope#$digest\n       * @kind function\n       *\n       * @description\n       * Processes all of the {@link ng.$rootScope.Scope#$watch watchers} of the current scope and\n       * its children. Because a {@link ng.$rootScope.Scope#$watch watcher}'s listener can change\n       * the model, the `$digest()` keeps calling the {@link ng.$rootScope.Scope#$watch watchers}\n       * until no more listeners are firing. This means that it is possible to get into an infinite\n       * loop. This function will throw `'Maximum iteration limit exceeded.'` if the number of\n       * iterations exceeds 10.\n       *\n       * Usually, you don't call `$digest()` directly in\n       * {@link ng.directive:ngController controllers} or in\n       * {@link ng.$compileProvider#directive directives}.\n       * Instead, you should call {@link ng.$rootScope.Scope#$apply $apply()} (typically from within\n       * a {@link ng.$compileProvider#directive directive}), which will force a `$digest()`.\n       *\n       * If you want to be notified whenever `$digest()` is called,\n       * you can register a `watchExpression` function with\n       * {@link ng.$rootScope.Scope#$watch $watch()} with no `listener`.\n       *\n       * In unit tests, you may need to call `$digest()` to simulate the scope life cycle.\n       *\n       * # Example\n       * ```js\n           var scope = ...;\n           scope.name = 'misko';\n           scope.counter = 0;\n\n           expect(scope.counter).toEqual(0);\n           scope.$watch('name', function(newValue, oldValue) {\n             scope.counter = scope.counter + 1;\n           });\n           expect(scope.counter).toEqual(0);\n\n           scope.$digest();\n           // the listener is always called during the first $digest loop after it was registered\n           expect(scope.counter).toEqual(1);\n\n           scope.$digest();\n           // but now it will not be called unless the value changes\n           expect(scope.counter).toEqual(1);\n\n           scope.name = 'adam';\n           scope.$digest();\n           expect(scope.counter).toEqual(2);\n       * ```\n       *\n       */\n      $digest: function() {\n        var watch, value, last,\n            watchers,\n            length,\n            dirty, ttl = TTL,\n            next, current, target = this,\n            watchLog = [],\n            logIdx, logMsg, asyncTask;\n\n        beginPhase('$digest');\n        // Check for changes to browser url that happened in sync before the call to $digest\n        $browser.$$checkUrlChange();\n\n        if (this === $rootScope && applyAsyncId !== null) {\n          // If this is the root scope, and $applyAsync has scheduled a deferred $apply(), then\n          // cancel the scheduled $apply and flush the queue of expressions to be evaluated.\n          $browser.defer.cancel(applyAsyncId);\n          flushApplyAsync();\n        }\n\n        lastDirtyWatch = null;\n\n        do { // \"while dirty\" loop\n          dirty = false;\n          current = target;\n\n          while (asyncQueue.length) {\n            try {\n              asyncTask = asyncQueue.shift();\n              asyncTask.scope.$eval(asyncTask.expression, asyncTask.locals);\n            } catch (e) {\n              $exceptionHandler(e);\n            }\n            lastDirtyWatch = null;\n          }\n\n          traverseScopesLoop:\n          do { // \"traverse the scopes\" loop\n            if ((watchers = current.$$watchers)) {\n              // process our watches\n              length = watchers.length;\n              while (length--) {\n                try {\n                  watch = watchers[length];\n                  // Most common watches are on primitives, in which case we can short\n                  // circuit it with === operator, only when === fails do we use .equals\n                  if (watch) {\n                    if ((value = watch.get(current)) !== (last = watch.last) &&\n                        !(watch.eq\n                            ? equals(value, last)\n                            : (typeof value === 'number' && typeof last === 'number'\n                               && isNaN(value) && isNaN(last)))) {\n                      dirty = true;\n                      lastDirtyWatch = watch;\n                      watch.last = watch.eq ? copy(value, null) : value;\n                      watch.fn(value, ((last === initWatchVal) ? value : last), current);\n                      if (ttl < 5) {\n                        logIdx = 4 - ttl;\n                        if (!watchLog[logIdx]) watchLog[logIdx] = [];\n                        watchLog[logIdx].push({\n                          msg: isFunction(watch.exp) ? 'fn: ' + (watch.exp.name || watch.exp.toString()) : watch.exp,\n                          newVal: value,\n                          oldVal: last\n                        });\n                      }\n                    } else if (watch === lastDirtyWatch) {\n                      // If the most recently dirty watcher is now clean, short circuit since the remaining watchers\n                      // have already been tested.\n                      dirty = false;\n                      break traverseScopesLoop;\n                    }\n                  }\n                } catch (e) {\n                  $exceptionHandler(e);\n                }\n              }\n            }\n\n            // Insanity Warning: scope depth-first traversal\n            // yes, this code is a bit crazy, but it works and we have tests to prove it!\n            // this piece should be kept in sync with the traversal in $broadcast\n            if (!(next = (current.$$childHead ||\n                (current !== target && current.$$nextSibling)))) {\n              while (current !== target && !(next = current.$$nextSibling)) {\n                current = current.$parent;\n              }\n            }\n          } while ((current = next));\n\n          // `break traverseScopesLoop;` takes us to here\n\n          if ((dirty || asyncQueue.length) && !(ttl--)) {\n            clearPhase();\n            throw $rootScopeMinErr('infdig',\n                '{0} $digest() iterations reached. Aborting!\\n' +\n                'Watchers fired in the last 5 iterations: {1}',\n                TTL, watchLog);\n          }\n\n        } while (dirty || asyncQueue.length);\n\n        clearPhase();\n\n        while (postDigestQueue.length) {\n          try {\n            postDigestQueue.shift()();\n          } catch (e) {\n            $exceptionHandler(e);\n          }\n        }\n      },\n\n\n      /**\n       * @ngdoc event\n       * @name $rootScope.Scope#$destroy\n       * @eventType broadcast on scope being destroyed\n       *\n       * @description\n       * Broadcasted when a scope and its children are being destroyed.\n       *\n       * Note that, in AngularJS, there is also a `$destroy` jQuery event, which can be used to\n       * clean up DOM bindings before an element is removed from the DOM.\n       */\n\n      /**\n       * @ngdoc method\n       * @name $rootScope.Scope#$destroy\n       * @kind function\n       *\n       * @description\n       * Removes the current scope (and all of its children) from the parent scope. Removal implies\n       * that calls to {@link ng.$rootScope.Scope#$digest $digest()} will no longer\n       * propagate to the current scope and its children. Removal also implies that the current\n       * scope is eligible for garbage collection.\n       *\n       * The `$destroy()` is usually used by directives such as\n       * {@link ng.directive:ngRepeat ngRepeat} for managing the\n       * unrolling of the loop.\n       *\n       * Just before a scope is destroyed, a `$destroy` event is broadcasted on this scope.\n       * Application code can register a `$destroy` event handler that will give it a chance to\n       * perform any necessary cleanup.\n       *\n       * Note that, in AngularJS, there is also a `$destroy` jQuery event, which can be used to\n       * clean up DOM bindings before an element is removed from the DOM.\n       */\n      $destroy: function() {\n        // we can't destroy the root scope or a scope that has been already destroyed\n        if (this.$$destroyed) return;\n        var parent = this.$parent;\n\n        this.$broadcast('$destroy');\n        this.$$destroyed = true;\n        if (this === $rootScope) return;\n\n        for (var eventName in this.$$listenerCount) {\n          decrementListenerCount(this, this.$$listenerCount[eventName], eventName);\n        }\n\n        // sever all the references to parent scopes (after this cleanup, the current scope should\n        // not be retained by any of our references and should be eligible for garbage collection)\n        if (parent.$$childHead == this) parent.$$childHead = this.$$nextSibling;\n        if (parent.$$childTail == this) parent.$$childTail = this.$$prevSibling;\n        if (this.$$prevSibling) this.$$prevSibling.$$nextSibling = this.$$nextSibling;\n        if (this.$$nextSibling) this.$$nextSibling.$$prevSibling = this.$$prevSibling;\n\n        // Disable listeners, watchers and apply/digest methods\n        this.$destroy = this.$digest = this.$apply = this.$evalAsync = this.$applyAsync = noop;\n        this.$on = this.$watch = this.$watchGroup = function() { return noop; };\n        this.$$listeners = {};\n\n        // All of the code below is bogus code that works around V8's memory leak via optimized code\n        // and inline caches.\n        //\n        // see:\n        // - https://code.google.com/p/v8/issues/detail?id=2073#c26\n        // - https://github.com/angular/angular.js/issues/6794#issuecomment-38648909\n        // - https://github.com/angular/angular.js/issues/1313#issuecomment-10378451\n\n        this.$parent = this.$$nextSibling = this.$$prevSibling = this.$$childHead =\n            this.$$childTail = this.$root = this.$$watchers = null;\n      },\n\n      /**\n       * @ngdoc method\n       * @name $rootScope.Scope#$eval\n       * @kind function\n       *\n       * @description\n       * Executes the `expression` on the current scope and returns the result. Any exceptions in\n       * the expression are propagated (uncaught). This is useful when evaluating Angular\n       * expressions.\n       *\n       * # Example\n       * ```js\n           var scope = ng.$rootScope.Scope();\n           scope.a = 1;\n           scope.b = 2;\n\n           expect(scope.$eval('a+b')).toEqual(3);\n           expect(scope.$eval(function(scope){ return scope.a + scope.b; })).toEqual(3);\n       * ```\n       *\n       * @param {(string|function())=} expression An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in  {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with the current `scope` parameter.\n       *\n       * @param {(object)=} locals Local variables object, useful for overriding values in scope.\n       * @returns {*} The result of evaluating the expression.\n       */\n      $eval: function(expr, locals) {\n        return $parse(expr)(this, locals);\n      },\n\n      /**\n       * @ngdoc method\n       * @name $rootScope.Scope#$evalAsync\n       * @kind function\n       *\n       * @description\n       * Executes the expression on the current scope at a later point in time.\n       *\n       * The `$evalAsync` makes no guarantees as to when the `expression` will be executed, only\n       * that:\n       *\n       *   - it will execute after the function that scheduled the evaluation (preferably before DOM\n       *     rendering).\n       *   - at least one {@link ng.$rootScope.Scope#$digest $digest cycle} will be performed after\n       *     `expression` execution.\n       *\n       * Any exceptions from the execution of the expression are forwarded to the\n       * {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * __Note:__ if this function is called outside of a `$digest` cycle, a new `$digest` cycle\n       * will be scheduled. However, it is encouraged to always call code that changes the model\n       * from within an `$apply` call. That includes code evaluated via `$evalAsync`.\n       *\n       * @param {(string|function())=} expression An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with the current `scope` parameter.\n       *\n       * @param {(object)=} locals Local variables object, useful for overriding values in scope.\n       */\n      $evalAsync: function(expr, locals) {\n        // if we are outside of an $digest loop and this is the first time we are scheduling async\n        // task also schedule async auto-flush\n        if (!$rootScope.$$phase && !asyncQueue.length) {\n          $browser.defer(function() {\n            if (asyncQueue.length) {\n              $rootScope.$digest();\n            }\n          });\n        }\n\n        asyncQueue.push({scope: this, expression: expr, locals: locals});\n      },\n\n      $$postDigest: function(fn) {\n        postDigestQueue.push(fn);\n      },\n\n      /**\n       * @ngdoc method\n       * @name $rootScope.Scope#$apply\n       * @kind function\n       *\n       * @description\n       * `$apply()` is used to execute an expression in angular from outside of the angular\n       * framework. (For example from browser DOM events, setTimeout, XHR or third party libraries).\n       * Because we are calling into the angular framework we need to perform proper scope life\n       * cycle of {@link ng.$exceptionHandler exception handling},\n       * {@link ng.$rootScope.Scope#$digest executing watches}.\n       *\n       * ## Life cycle\n       *\n       * # Pseudo-Code of `$apply()`\n       * ```js\n           function $apply(expr) {\n             try {\n               return $eval(expr);\n             } catch (e) {\n               $exceptionHandler(e);\n             } finally {\n               $root.$digest();\n             }\n           }\n       * ```\n       *\n       *\n       * Scope's `$apply()` method transitions through the following stages:\n       *\n       * 1. The {@link guide/expression expression} is executed using the\n       *    {@link ng.$rootScope.Scope#$eval $eval()} method.\n       * 2. Any exceptions from the execution of the expression are forwarded to the\n       *    {@link ng.$exceptionHandler $exceptionHandler} service.\n       * 3. The {@link ng.$rootScope.Scope#$watch watch} listeners are fired immediately after the\n       *    expression was executed using the {@link ng.$rootScope.Scope#$digest $digest()} method.\n       *\n       *\n       * @param {(string|function())=} exp An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with current `scope` parameter.\n       *\n       * @returns {*} The result of evaluating the expression.\n       */\n      $apply: function(expr) {\n        try {\n          beginPhase('$apply');\n          return this.$eval(expr);\n        } catch (e) {\n          $exceptionHandler(e);\n        } finally {\n          clearPhase();\n          try {\n            $rootScope.$digest();\n          } catch (e) {\n            $exceptionHandler(e);\n            throw e;\n          }\n        }\n      },\n\n      /**\n       * @ngdoc method\n       * @name $rootScope.Scope#$applyAsync\n       * @kind function\n       *\n       * @description\n       * Schedule the invocation of $apply to occur at a later time. The actual time difference\n       * varies across browsers, but is typically around ~10 milliseconds.\n       *\n       * This can be used to queue up multiple expressions which need to be evaluated in the same\n       * digest.\n       *\n       * @param {(string|function())=} exp An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with current `scope` parameter.\n       */\n      $applyAsync: function(expr) {\n        var scope = this;\n        expr && applyAsyncQueue.push($applyAsyncExpression);\n        scheduleApplyAsync();\n\n        function $applyAsyncExpression() {\n          scope.$eval(expr);\n        }\n      },\n\n      /**\n       * @ngdoc method\n       * @name $rootScope.Scope#$on\n       * @kind function\n       *\n       * @description\n       * Listens on events of a given type. See {@link ng.$rootScope.Scope#$emit $emit} for\n       * discussion of event life cycle.\n       *\n       * The event listener function format is: `function(event, args...)`. The `event` object\n       * passed into the listener has the following attributes:\n       *\n       *   - `targetScope` - `{Scope}`: the scope on which the event was `$emit`-ed or\n       *     `$broadcast`-ed.\n       *   - `currentScope` - `{Scope}`: the scope that is currently handling the event. Once the\n       *     event propagates through the scope hierarchy, this property is set to null.\n       *   - `name` - `{string}`: name of the event.\n       *   - `stopPropagation` - `{function=}`: calling `stopPropagation` function will cancel\n       *     further event propagation (available only for events that were `$emit`-ed).\n       *   - `preventDefault` - `{function}`: calling `preventDefault` sets `defaultPrevented` flag\n       *     to true.\n       *   - `defaultPrevented` - `{boolean}`: true if `preventDefault` was called.\n       *\n       * @param {string} name Event name to listen on.\n       * @param {function(event, ...args)} listener Function to call when the event is emitted.\n       * @returns {function()} Returns a deregistration function for this listener.\n       */\n      $on: function(name, listener) {\n        var namedListeners = this.$$listeners[name];\n        if (!namedListeners) {\n          this.$$listeners[name] = namedListeners = [];\n        }\n        namedListeners.push(listener);\n\n        var current = this;\n        do {\n          if (!current.$$listenerCount[name]) {\n            current.$$listenerCount[name] = 0;\n          }\n          current.$$listenerCount[name]++;\n        } while ((current = current.$parent));\n\n        var self = this;\n        return function() {\n          var indexOfListener = namedListeners.indexOf(listener);\n          if (indexOfListener !== -1) {\n            namedListeners[indexOfListener] = null;\n            decrementListenerCount(self, 1, name);\n          }\n        };\n      },\n\n\n      /**\n       * @ngdoc method\n       * @name $rootScope.Scope#$emit\n       * @kind function\n       *\n       * @description\n       * Dispatches an event `name` upwards through the scope hierarchy notifying the\n       * registered {@link ng.$rootScope.Scope#$on} listeners.\n       *\n       * The event life cycle starts at the scope on which `$emit` was called. All\n       * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get\n       * notified. Afterwards, the event traverses upwards toward the root scope and calls all\n       * registered listeners along the way. The event will stop propagating if one of the listeners\n       * cancels it.\n       *\n       * Any exception emitted from the {@link ng.$rootScope.Scope#$on listeners} will be passed\n       * onto the {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {string} name Event name to emit.\n       * @param {...*} args Optional one or more arguments which will be passed onto the event listeners.\n       * @return {Object} Event object (see {@link ng.$rootScope.Scope#$on}).\n       */\n      $emit: function(name, args) {\n        var empty = [],\n            namedListeners,\n            scope = this,\n            stopPropagation = false,\n            event = {\n              name: name,\n              targetScope: scope,\n              stopPropagation: function() {stopPropagation = true;},\n              preventDefault: function() {\n                event.defaultPrevented = true;\n              },\n              defaultPrevented: false\n            },\n            listenerArgs = concat([event], arguments, 1),\n            i, length;\n\n        do {\n          namedListeners = scope.$$listeners[name] || empty;\n          event.currentScope = scope;\n          for (i = 0, length = namedListeners.length; i < length; i++) {\n\n            // if listeners were deregistered, defragment the array\n            if (!namedListeners[i]) {\n              namedListeners.splice(i, 1);\n              i--;\n              length--;\n              continue;\n            }\n            try {\n              //allow all listeners attached to the current scope to run\n              namedListeners[i].apply(null, listenerArgs);\n            } catch (e) {\n              $exceptionHandler(e);\n            }\n          }\n          //if any listener on the current scope stops propagation, prevent bubbling\n          if (stopPropagation) {\n            event.currentScope = null;\n            return event;\n          }\n          //traverse upwards\n          scope = scope.$parent;\n        } while (scope);\n\n        event.currentScope = null;\n\n        return event;\n      },\n\n\n      /**\n       * @ngdoc method\n       * @name $rootScope.Scope#$broadcast\n       * @kind function\n       *\n       * @description\n       * Dispatches an event `name` downwards to all child scopes (and their children) notifying the\n       * registered {@link ng.$rootScope.Scope#$on} listeners.\n       *\n       * The event life cycle starts at the scope on which `$broadcast` was called. All\n       * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get\n       * notified. Afterwards, the event propagates to all direct and indirect scopes of the current\n       * scope and calls all registered listeners along the way. The event cannot be canceled.\n       *\n       * Any exception emitted from the {@link ng.$rootScope.Scope#$on listeners} will be passed\n       * onto the {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {string} name Event name to broadcast.\n       * @param {...*} args Optional one or more arguments which will be passed onto the event listeners.\n       * @return {Object} Event object, see {@link ng.$rootScope.Scope#$on}\n       */\n      $broadcast: function(name, args) {\n        var target = this,\n            current = target,\n            next = target,\n            event = {\n              name: name,\n              targetScope: target,\n              preventDefault: function() {\n                event.defaultPrevented = true;\n              },\n              defaultPrevented: false\n            };\n\n        if (!target.$$listenerCount[name]) return event;\n\n        var listenerArgs = concat([event], arguments, 1),\n            listeners, i, length;\n\n        //down while you can, then up and next sibling or up and next sibling until back at root\n        while ((current = next)) {\n          event.currentScope = current;\n          listeners = current.$$listeners[name] || [];\n          for (i = 0, length = listeners.length; i < length; i++) {\n            // if listeners were deregistered, defragment the array\n            if (!listeners[i]) {\n              listeners.splice(i, 1);\n              i--;\n              length--;\n              continue;\n            }\n\n            try {\n              listeners[i].apply(null, listenerArgs);\n            } catch (e) {\n              $exceptionHandler(e);\n            }\n          }\n\n          // Insanity Warning: scope depth-first traversal\n          // yes, this code is a bit crazy, but it works and we have tests to prove it!\n          // this piece should be kept in sync with the traversal in $digest\n          // (though it differs due to having the extra check for $$listenerCount)\n          if (!(next = ((current.$$listenerCount[name] && current.$$childHead) ||\n              (current !== target && current.$$nextSibling)))) {\n            while (current !== target && !(next = current.$$nextSibling)) {\n              current = current.$parent;\n            }\n          }\n        }\n\n        event.currentScope = null;\n        return event;\n      }\n    };\n\n    var $rootScope = new Scope();\n\n    //The internal queues. Expose them on the $rootScope for debugging/testing purposes.\n    var asyncQueue = $rootScope.$$asyncQueue = [];\n    var postDigestQueue = $rootScope.$$postDigestQueue = [];\n    var applyAsyncQueue = $rootScope.$$applyAsyncQueue = [];\n\n    return $rootScope;\n\n\n    function beginPhase(phase) {\n      if ($rootScope.$$phase) {\n        throw $rootScopeMinErr('inprog', '{0} already in progress', $rootScope.$$phase);\n      }\n\n      $rootScope.$$phase = phase;\n    }\n\n    function clearPhase() {\n      $rootScope.$$phase = null;\n    }\n\n\n    function decrementListenerCount(current, count, name) {\n      do {\n        current.$$listenerCount[name] -= count;\n\n        if (current.$$listenerCount[name] === 0) {\n          delete current.$$listenerCount[name];\n        }\n      } while ((current = current.$parent));\n    }\n\n    /**\n     * function used as an initial value for watchers.\n     * because it's unique we can easily tell it apart from other values\n     */\n    function initWatchVal() {}\n\n    function flushApplyAsync() {\n      while (applyAsyncQueue.length) {\n        try {\n          applyAsyncQueue.shift()();\n        } catch (e) {\n          $exceptionHandler(e);\n        }\n      }\n      applyAsyncId = null;\n    }\n\n    function scheduleApplyAsync() {\n      if (applyAsyncId === null) {\n        applyAsyncId = $browser.defer(function() {\n          $rootScope.$apply(flushApplyAsync);\n        });\n      }\n    }\n  }];\n}\n\n/**\n * @description\n * Private service to sanitize uris for links and images. Used by $compile and $sanitize.\n */\nfunction $$SanitizeUriProvider() {\n  var aHrefSanitizationWhitelist = /^\\s*(https?|ftp|mailto|tel|file):/,\n    imgSrcSanitizationWhitelist = /^\\s*((https?|ftp|file|blob):|data:image\\/)/;\n\n  /**\n   * @description\n   * Retrieves or overrides the default regular expression that is used for whitelisting of safe\n   * urls during a[href] sanitization.\n   *\n   * The sanitization is a security measure aimed at prevent XSS attacks via html links.\n   *\n   * Any url about to be assigned to a[href] via data-binding is first normalized and turned into\n   * an absolute url. Afterwards, the url is matched against the `aHrefSanitizationWhitelist`\n   * regular expression. If a match is found, the original url is written into the dom. Otherwise,\n   * the absolute url is prefixed with `'unsafe:'` string and only then is it written into the DOM.\n   *\n   * @param {RegExp=} regexp New regexp to whitelist urls with.\n   * @returns {RegExp|ng.$compileProvider} Current RegExp if called without value or self for\n   *    chaining otherwise.\n   */\n  this.aHrefSanitizationWhitelist = function(regexp) {\n    if (isDefined(regexp)) {\n      aHrefSanitizationWhitelist = regexp;\n      return this;\n    }\n    return aHrefSanitizationWhitelist;\n  };\n\n\n  /**\n   * @description\n   * Retrieves or overrides the default regular expression that is used for whitelisting of safe\n   * urls during img[src] sanitization.\n   *\n   * The sanitization is a security measure aimed at prevent XSS attacks via html links.\n   *\n   * Any url about to be assigned to img[src] via data-binding is first normalized and turned into\n   * an absolute url. Afterwards, the url is matched against the `imgSrcSanitizationWhitelist`\n   * regular expression. If a match is found, the original url is written into the dom. Otherwise,\n   * the absolute url is prefixed with `'unsafe:'` string and only then is it written into the DOM.\n   *\n   * @param {RegExp=} regexp New regexp to whitelist urls with.\n   * @returns {RegExp|ng.$compileProvider} Current RegExp if called without value or self for\n   *    chaining otherwise.\n   */\n  this.imgSrcSanitizationWhitelist = function(regexp) {\n    if (isDefined(regexp)) {\n      imgSrcSanitizationWhitelist = regexp;\n      return this;\n    }\n    return imgSrcSanitizationWhitelist;\n  };\n\n  this.$get = function() {\n    return function sanitizeUri(uri, isImage) {\n      var regex = isImage ? imgSrcSanitizationWhitelist : aHrefSanitizationWhitelist;\n      var normalizedVal;\n      normalizedVal = urlResolve(uri).href;\n      if (normalizedVal !== '' && !normalizedVal.match(regex)) {\n        return 'unsafe:' + normalizedVal;\n      }\n      return uri;\n    };\n  };\n}\n\nvar $sceMinErr = minErr('$sce');\n\nvar SCE_CONTEXTS = {\n  HTML: 'html',\n  CSS: 'css',\n  URL: 'url',\n  // RESOURCE_URL is a subtype of URL used in contexts where a privileged resource is sourced from a\n  // url.  (e.g. ng-include, script src, templateUrl)\n  RESOURCE_URL: 'resourceUrl',\n  JS: 'js'\n};\n\n// Helper functions follow.\n\nfunction adjustMatcher(matcher) {\n  if (matcher === 'self') {\n    return matcher;\n  } else if (isString(matcher)) {\n    // Strings match exactly except for 2 wildcards - '*' and '**'.\n    // '*' matches any character except those from the set ':/.?&'.\n    // '**' matches any character (like .* in a RegExp).\n    // More than 2 *'s raises an error as it's ill defined.\n    if (matcher.indexOf('***') > -1) {\n      throw $sceMinErr('iwcard',\n          'Illegal sequence *** in string matcher.  String: {0}', matcher);\n    }\n    matcher = escapeForRegexp(matcher).\n                  replace('\\\\*\\\\*', '.*').\n                  replace('\\\\*', '[^:/.?&;]*');\n    return new RegExp('^' + matcher + '$');\n  } else if (isRegExp(matcher)) {\n    // The only other type of matcher allowed is a Regexp.\n    // Match entire URL / disallow partial matches.\n    // Flags are reset (i.e. no global, ignoreCase or multiline)\n    return new RegExp('^' + matcher.source + '$');\n  } else {\n    throw $sceMinErr('imatcher',\n        'Matchers may only be \"self\", string patterns or RegExp objects');\n  }\n}\n\n\nfunction adjustMatchers(matchers) {\n  var adjustedMatchers = [];\n  if (isDefined(matchers)) {\n    forEach(matchers, function(matcher) {\n      adjustedMatchers.push(adjustMatcher(matcher));\n    });\n  }\n  return adjustedMatchers;\n}\n\n\n/**\n * @ngdoc service\n * @name $sceDelegate\n * @kind function\n *\n * @description\n *\n * `$sceDelegate` is a service that is used by the `$sce` service to provide {@link ng.$sce Strict\n * Contextual Escaping (SCE)} services to AngularJS.\n *\n * Typically, you would configure or override the {@link ng.$sceDelegate $sceDelegate} instead of\n * the `$sce` service to customize the way Strict Contextual Escaping works in AngularJS.  This is\n * because, while the `$sce` provides numerous shorthand methods, etc., you really only need to\n * override 3 core functions (`trustAs`, `getTrusted` and `valueOf`) to replace the way things\n * work because `$sce` delegates to `$sceDelegate` for these operations.\n *\n * Refer {@link ng.$sceDelegateProvider $sceDelegateProvider} to configure this service.\n *\n * The default instance of `$sceDelegate` should work out of the box with little pain.  While you\n * can override it completely to change the behavior of `$sce`, the common case would\n * involve configuring the {@link ng.$sceDelegateProvider $sceDelegateProvider} instead by setting\n * your own whitelists and blacklists for trusting URLs used for loading AngularJS resources such as\n * templates.  Refer {@link ng.$sceDelegateProvider#resourceUrlWhitelist\n * $sceDelegateProvider.resourceUrlWhitelist} and {@link\n * ng.$sceDelegateProvider#resourceUrlBlacklist $sceDelegateProvider.resourceUrlBlacklist}\n */\n\n/**\n * @ngdoc provider\n * @name $sceDelegateProvider\n * @description\n *\n * The `$sceDelegateProvider` provider allows developers to configure the {@link ng.$sceDelegate\n * $sceDelegate} service.  This allows one to get/set the whitelists and blacklists used to ensure\n * that the URLs used for sourcing Angular templates are safe.  Refer {@link\n * ng.$sceDelegateProvider#resourceUrlWhitelist $sceDelegateProvider.resourceUrlWhitelist} and\n * {@link ng.$sceDelegateProvider#resourceUrlBlacklist $sceDelegateProvider.resourceUrlBlacklist}\n *\n * For the general details about this service in Angular, read the main page for {@link ng.$sce\n * Strict Contextual Escaping (SCE)}.\n *\n * **Example**:  Consider the following case. <a name=\"example\"></a>\n *\n * - your app is hosted at url `http://myapp.example.com/`\n * - but some of your templates are hosted on other domains you control such as\n *   `http://srv01.assets.example.com/`,  `http://srv02.assets.example.com/`, etc.\n * - and you have an open redirect at `http://myapp.example.com/clickThru?...`.\n *\n * Here is what a secure configuration for this scenario might look like:\n *\n * ```\n *  angular.module('myApp', []).config(function($sceDelegateProvider) {\n *    $sceDelegateProvider.resourceUrlWhitelist([\n *      // Allow same origin resource loads.\n *      'self',\n *      // Allow loading from our assets domain.  Notice the difference between * and **.\n *      'http://srv*.assets.example.com/**'\n *    ]);\n *\n *    // The blacklist overrides the whitelist so the open redirect here is blocked.\n *    $sceDelegateProvider.resourceUrlBlacklist([\n *      'http://myapp.example.com/clickThru**'\n *    ]);\n *  });\n * ```\n */\n\nfunction $SceDelegateProvider() {\n  this.SCE_CONTEXTS = SCE_CONTEXTS;\n\n  // Resource URLs can also be trusted by policy.\n  var resourceUrlWhitelist = ['self'],\n      resourceUrlBlacklist = [];\n\n  /**\n   * @ngdoc method\n   * @name $sceDelegateProvider#resourceUrlWhitelist\n   * @kind function\n   *\n   * @param {Array=} whitelist When provided, replaces the resourceUrlWhitelist with the value\n   *     provided.  This must be an array or null.  A snapshot of this array is used so further\n   *     changes to the array are ignored.\n   *\n   *     Follow {@link ng.$sce#resourceUrlPatternItem this link} for a description of the items\n   *     allowed in this array.\n   *\n   *     Note: **an empty whitelist array will block all URLs**!\n   *\n   * @return {Array} the currently set whitelist array.\n   *\n   * The **default value** when no whitelist has been explicitly set is `['self']` allowing only\n   * same origin resource requests.\n   *\n   * @description\n   * Sets/Gets the whitelist of trusted resource URLs.\n   */\n  this.resourceUrlWhitelist = function(value) {\n    if (arguments.length) {\n      resourceUrlWhitelist = adjustMatchers(value);\n    }\n    return resourceUrlWhitelist;\n  };\n\n  /**\n   * @ngdoc method\n   * @name $sceDelegateProvider#resourceUrlBlacklist\n   * @kind function\n   *\n   * @param {Array=} blacklist When provided, replaces the resourceUrlBlacklist with the value\n   *     provided.  This must be an array or null.  A snapshot of this array is used so further\n   *     changes to the array are ignored.\n   *\n   *     Follow {@link ng.$sce#resourceUrlPatternItem this link} for a description of the items\n   *     allowed in this array.\n   *\n   *     The typical usage for the blacklist is to **block\n   *     [open redirects](http://cwe.mitre.org/data/definitions/601.html)** served by your domain as\n   *     these would otherwise be trusted but actually return content from the redirected domain.\n   *\n   *     Finally, **the blacklist overrides the whitelist** and has the final say.\n   *\n   * @return {Array} the currently set blacklist array.\n   *\n   * The **default value** when no whitelist has been explicitly set is the empty array (i.e. there\n   * is no blacklist.)\n   *\n   * @description\n   * Sets/Gets the blacklist of trusted resource URLs.\n   */\n\n  this.resourceUrlBlacklist = function(value) {\n    if (arguments.length) {\n      resourceUrlBlacklist = adjustMatchers(value);\n    }\n    return resourceUrlBlacklist;\n  };\n\n  this.$get = ['$injector', function($injector) {\n\n    var htmlSanitizer = function htmlSanitizer(html) {\n      throw $sceMinErr('unsafe', 'Attempting to use an unsafe value in a safe context.');\n    };\n\n    if ($injector.has('$sanitize')) {\n      htmlSanitizer = $injector.get('$sanitize');\n    }\n\n\n    function matchUrl(matcher, parsedUrl) {\n      if (matcher === 'self') {\n        return urlIsSameOrigin(parsedUrl);\n      } else {\n        // definitely a regex.  See adjustMatchers()\n        return !!matcher.exec(parsedUrl.href);\n      }\n    }\n\n    function isResourceUrlAllowedByPolicy(url) {\n      var parsedUrl = urlResolve(url.toString());\n      var i, n, allowed = false;\n      // Ensure that at least one item from the whitelist allows this url.\n      for (i = 0, n = resourceUrlWhitelist.length; i < n; i++) {\n        if (matchUrl(resourceUrlWhitelist[i], parsedUrl)) {\n          allowed = true;\n          break;\n        }\n      }\n      if (allowed) {\n        // Ensure that no item from the blacklist blocked this url.\n        for (i = 0, n = resourceUrlBlacklist.length; i < n; i++) {\n          if (matchUrl(resourceUrlBlacklist[i], parsedUrl)) {\n            allowed = false;\n            break;\n          }\n        }\n      }\n      return allowed;\n    }\n\n    function generateHolderType(Base) {\n      var holderType = function TrustedValueHolderType(trustedValue) {\n        this.$$unwrapTrustedValue = function() {\n          return trustedValue;\n        };\n      };\n      if (Base) {\n        holderType.prototype = new Base();\n      }\n      holderType.prototype.valueOf = function sceValueOf() {\n        return this.$$unwrapTrustedValue();\n      };\n      holderType.prototype.toString = function sceToString() {\n        return this.$$unwrapTrustedValue().toString();\n      };\n      return holderType;\n    }\n\n    var trustedValueHolderBase = generateHolderType(),\n        byType = {};\n\n    byType[SCE_CONTEXTS.HTML] = generateHolderType(trustedValueHolderBase);\n    byType[SCE_CONTEXTS.CSS] = generateHolderType(trustedValueHolderBase);\n    byType[SCE_CONTEXTS.URL] = generateHolderType(trustedValueHolderBase);\n    byType[SCE_CONTEXTS.JS] = generateHolderType(trustedValueHolderBase);\n    byType[SCE_CONTEXTS.RESOURCE_URL] = generateHolderType(byType[SCE_CONTEXTS.URL]);\n\n    /**\n     * @ngdoc method\n     * @name $sceDelegate#trustAs\n     *\n     * @description\n     * Returns an object that is trusted by angular for use in specified strict\n     * contextual escaping contexts (such as ng-bind-html, ng-include, any src\n     * attribute interpolation, any dom event binding attribute interpolation\n     * such as for onclick,  etc.) that uses the provided value.\n     * See {@link ng.$sce $sce} for enabling strict contextual escaping.\n     *\n     * @param {string} type The kind of context in which this value is safe for use.  e.g. url,\n     *   resourceUrl, html, js and css.\n     * @param {*} value The value that that should be considered trusted/safe.\n     * @returns {*} A value that can be used to stand in for the provided `value` in places\n     * where Angular expects a $sce.trustAs() return value.\n     */\n    function trustAs(type, trustedValue) {\n      var Constructor = (byType.hasOwnProperty(type) ? byType[type] : null);\n      if (!Constructor) {\n        throw $sceMinErr('icontext',\n            'Attempted to trust a value in invalid context. Context: {0}; Value: {1}',\n            type, trustedValue);\n      }\n      if (trustedValue === null || trustedValue === undefined || trustedValue === '') {\n        return trustedValue;\n      }\n      // All the current contexts in SCE_CONTEXTS happen to be strings.  In order to avoid trusting\n      // mutable objects, we ensure here that the value passed in is actually a string.\n      if (typeof trustedValue !== 'string') {\n        throw $sceMinErr('itype',\n            'Attempted to trust a non-string value in a content requiring a string: Context: {0}',\n            type);\n      }\n      return new Constructor(trustedValue);\n    }\n\n    /**\n     * @ngdoc method\n     * @name $sceDelegate#valueOf\n     *\n     * @description\n     * If the passed parameter had been returned by a prior call to {@link ng.$sceDelegate#trustAs\n     * `$sceDelegate.trustAs`}, returns the value that had been passed to {@link\n     * ng.$sceDelegate#trustAs `$sceDelegate.trustAs`}.\n     *\n     * If the passed parameter is not a value that had been returned by {@link\n     * ng.$sceDelegate#trustAs `$sceDelegate.trustAs`}, returns it as-is.\n     *\n     * @param {*} value The result of a prior {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs`}\n     *      call or anything else.\n     * @returns {*} The `value` that was originally provided to {@link ng.$sceDelegate#trustAs\n     *     `$sceDelegate.trustAs`} if `value` is the result of such a call.  Otherwise, returns\n     *     `value` unchanged.\n     */\n    function valueOf(maybeTrusted) {\n      if (maybeTrusted instanceof trustedValueHolderBase) {\n        return maybeTrusted.$$unwrapTrustedValue();\n      } else {\n        return maybeTrusted;\n      }\n    }\n\n    /**\n     * @ngdoc method\n     * @name $sceDelegate#getTrusted\n     *\n     * @description\n     * Takes the result of a {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs`} call and\n     * returns the originally supplied value if the queried context type is a supertype of the\n     * created type.  If this condition isn't satisfied, throws an exception.\n     *\n     * @param {string} type The kind of context in which this value is to be used.\n     * @param {*} maybeTrusted The result of a prior {@link ng.$sceDelegate#trustAs\n     *     `$sceDelegate.trustAs`} call.\n     * @returns {*} The value the was originally provided to {@link ng.$sceDelegate#trustAs\n     *     `$sceDelegate.trustAs`} if valid in this context.  Otherwise, throws an exception.\n     */\n    function getTrusted(type, maybeTrusted) {\n      if (maybeTrusted === null || maybeTrusted === undefined || maybeTrusted === '') {\n        return maybeTrusted;\n      }\n      var constructor = (byType.hasOwnProperty(type) ? byType[type] : null);\n      if (constructor && maybeTrusted instanceof constructor) {\n        return maybeTrusted.$$unwrapTrustedValue();\n      }\n      // If we get here, then we may only take one of two actions.\n      // 1. sanitize the value for the requested type, or\n      // 2. throw an exception.\n      if (type === SCE_CONTEXTS.RESOURCE_URL) {\n        if (isResourceUrlAllowedByPolicy(maybeTrusted)) {\n          return maybeTrusted;\n        } else {\n          throw $sceMinErr('insecurl',\n              'Blocked loading resource from url not allowed by $sceDelegate policy.  URL: {0}',\n              maybeTrusted.toString());\n        }\n      } else if (type === SCE_CONTEXTS.HTML) {\n        return htmlSanitizer(maybeTrusted);\n      }\n      throw $sceMinErr('unsafe', 'Attempting to use an unsafe value in a safe context.');\n    }\n\n    return { trustAs: trustAs,\n             getTrusted: getTrusted,\n             valueOf: valueOf };\n  }];\n}\n\n\n/**\n * @ngdoc provider\n * @name $sceProvider\n * @description\n *\n * The $sceProvider provider allows developers to configure the {@link ng.$sce $sce} service.\n * -   enable/disable Strict Contextual Escaping (SCE) in a module\n * -   override the default implementation with a custom delegate\n *\n * Read more about {@link ng.$sce Strict Contextual Escaping (SCE)}.\n */\n\n/* jshint maxlen: false*/\n\n/**\n * @ngdoc service\n * @name $sce\n * @kind function\n *\n * @description\n *\n * `$sce` is a service that provides Strict Contextual Escaping services to AngularJS.\n *\n * # Strict Contextual Escaping\n *\n * Strict Contextual Escaping (SCE) is a mode in which AngularJS requires bindings in certain\n * contexts to result in a value that is marked as safe to use for that context.  One example of\n * such a context is binding arbitrary html controlled by the user via `ng-bind-html`.  We refer\n * to these contexts as privileged or SCE contexts.\n *\n * As of version 1.2, Angular ships with SCE enabled by default.\n *\n * Note:  When enabled (the default), IE<11 in quirks mode is not supported.  In this mode, IE<11 allow\n * one to execute arbitrary javascript by the use of the expression() syntax.  Refer\n * <http://blogs.msdn.com/b/ie/archive/2008/10/16/ending-expressions.aspx> to learn more about them.\n * You can ensure your document is in standards mode and not quirks mode by adding `<!doctype html>`\n * to the top of your HTML document.\n *\n * SCE assists in writing code in way that (a) is secure by default and (b) makes auditing for\n * security vulnerabilities such as XSS, clickjacking, etc. a lot easier.\n *\n * Here's an example of a binding in a privileged context:\n *\n * ```\n * <input ng-model=\"userHtml\">\n * <div ng-bind-html=\"userHtml\"></div>\n * ```\n *\n * Notice that `ng-bind-html` is bound to `userHtml` controlled by the user.  With SCE\n * disabled, this application allows the user to render arbitrary HTML into the DIV.\n * In a more realistic example, one may be rendering user comments, blog articles, etc. via\n * bindings.  (HTML is just one example of a context where rendering user controlled input creates\n * security vulnerabilities.)\n *\n * For the case of HTML, you might use a library, either on the client side, or on the server side,\n * to sanitize unsafe HTML before binding to the value and rendering it in the document.\n *\n * How would you ensure that every place that used these types of bindings was bound to a value that\n * was sanitized by your library (or returned as safe for rendering by your server?)  How can you\n * ensure that you didn't accidentally delete the line that sanitized the value, or renamed some\n * properties/fields and forgot to update the binding to the sanitized value?\n *\n * To be secure by default, you want to ensure that any such bindings are disallowed unless you can\n * determine that something explicitly says it's safe to use a value for binding in that\n * context.  You can then audit your code (a simple grep would do) to ensure that this is only done\n * for those values that you can easily tell are safe - because they were received from your server,\n * sanitized by your library, etc.  You can organize your codebase to help with this - perhaps\n * allowing only the files in a specific directory to do this.  Ensuring that the internal API\n * exposed by that code doesn't markup arbitrary values as safe then becomes a more manageable task.\n *\n * In the case of AngularJS' SCE service, one uses {@link ng.$sce#trustAs $sce.trustAs}\n * (and shorthand methods such as {@link ng.$sce#trustAsHtml $sce.trustAsHtml}, etc.) to\n * obtain values that will be accepted by SCE / privileged contexts.\n *\n *\n * ## How does it work?\n *\n * In privileged contexts, directives and code will bind to the result of {@link ng.$sce#getTrusted\n * $sce.getTrusted(context, value)} rather than to the value directly.  Directives use {@link\n * ng.$sce#parseAs $sce.parseAs} rather than `$parse` to watch attribute bindings, which performs the\n * {@link ng.$sce#getTrusted $sce.getTrusted} behind the scenes on non-constant literals.\n *\n * As an example, {@link ng.directive:ngBindHtml ngBindHtml} uses {@link\n * ng.$sce#parseAsHtml $sce.parseAsHtml(binding expression)}.  Here's the actual code (slightly\n * simplified):\n *\n * ```\n * var ngBindHtmlDirective = ['$sce', function($sce) {\n *   return function(scope, element, attr) {\n *     scope.$watch($sce.parseAsHtml(attr.ngBindHtml), function(value) {\n *       element.html(value || '');\n *     });\n *   };\n * }];\n * ```\n *\n * ## Impact on loading templates\n *\n * This applies both to the {@link ng.directive:ngInclude `ng-include`} directive as well as\n * `templateUrl`'s specified by {@link guide/directive directives}.\n *\n * By default, Angular only loads templates from the same domain and protocol as the application\n * document.  This is done by calling {@link ng.$sce#getTrustedResourceUrl\n * $sce.getTrustedResourceUrl} on the template URL.  To load templates from other domains and/or\n * protocols, you may either either {@link ng.$sceDelegateProvider#resourceUrlWhitelist whitelist\n * them} or {@link ng.$sce#trustAsResourceUrl wrap it} into a trusted value.\n *\n * *Please note*:\n * The browser's\n * [Same Origin Policy](https://code.google.com/p/browsersec/wiki/Part2#Same-origin_policy_for_XMLHttpRequest)\n * and [Cross-Origin Resource Sharing (CORS)](http://www.w3.org/TR/cors/)\n * policy apply in addition to this and may further restrict whether the template is successfully\n * loaded.  This means that without the right CORS policy, loading templates from a different domain\n * won't work on all browsers.  Also, loading templates from `file://` URL does not work on some\n * browsers.\n *\n * ## This feels like too much overhead\n *\n * It's important to remember that SCE only applies to interpolation expressions.\n *\n * If your expressions are constant literals, they're automatically trusted and you don't need to\n * call `$sce.trustAs` on them (remember to include the `ngSanitize` module) (e.g.\n * `<div ng-bind-html=\"'<b>implicitly trusted</b>'\"></div>`) just works.\n *\n * Additionally, `a[href]` and `img[src]` automatically sanitize their URLs and do not pass them\n * through {@link ng.$sce#getTrusted $sce.getTrusted}.  SCE doesn't play a role here.\n *\n * The included {@link ng.$sceDelegate $sceDelegate} comes with sane defaults to allow you to load\n * templates in `ng-include` from your application's domain without having to even know about SCE.\n * It blocks loading templates from other domains or loading templates over http from an https\n * served document.  You can change these by setting your own custom {@link\n * ng.$sceDelegateProvider#resourceUrlWhitelist whitelists} and {@link\n * ng.$sceDelegateProvider#resourceUrlBlacklist blacklists} for matching such URLs.\n *\n * This significantly reduces the overhead.  It is far easier to pay the small overhead and have an\n * application that's secure and can be audited to verify that with much more ease than bolting\n * security onto an application later.\n *\n * <a name=\"contexts\"></a>\n * ## What trusted context types are supported?\n *\n * | Context             | Notes          |\n * |---------------------|----------------|\n * | `$sce.HTML`         | For HTML that's safe to source into the application.  The {@link ng.directive:ngBindHtml ngBindHtml} directive uses this context for bindings. If an unsafe value is encountered and the {@link ngSanitize $sanitize} module is present this will sanitize the value instead of throwing an error. |\n * | `$sce.CSS`          | For CSS that's safe to source into the application.  Currently unused.  Feel free to use it in your own directives. |\n * | `$sce.URL`          | For URLs that are safe to follow as links.  Currently unused (`<a href=` and `<img src=` sanitize their urls and don't constitute an SCE context. |\n * | `$sce.RESOURCE_URL` | For URLs that are not only safe to follow as links, but whose contents are also safe to include in your application.  Examples include `ng-include`, `src` / `ngSrc` bindings for tags other than `IMG` (e.g. `IFRAME`, `OBJECT`, etc.)  <br><br>Note that `$sce.RESOURCE_URL` makes a stronger statement about the URL than `$sce.URL` does and therefore contexts requiring values trusted for `$sce.RESOURCE_URL` can be used anywhere that values trusted for `$sce.URL` are required. |\n * | `$sce.JS`           | For JavaScript that is safe to execute in your application's context.  Currently unused.  Feel free to use it in your own directives. |\n *\n * ## Format of items in {@link ng.$sceDelegateProvider#resourceUrlWhitelist resourceUrlWhitelist}/{@link ng.$sceDelegateProvider#resourceUrlBlacklist Blacklist} <a name=\"resourceUrlPatternItem\"></a>\n *\n *  Each element in these arrays must be one of the following:\n *\n *  - **'self'**\n *    - The special **string**, `'self'`, can be used to match against all URLs of the **same\n *      domain** as the application document using the **same protocol**.\n *  - **String** (except the special value `'self'`)\n *    - The string is matched against the full *normalized / absolute URL* of the resource\n *      being tested (substring matches are not good enough.)\n *    - There are exactly **two wildcard sequences** - `*` and `**`.  All other characters\n *      match themselves.\n *    - `*`: matches zero or more occurrences of any character other than one of the following 6\n *      characters: '`:`', '`/`', '`.`', '`?`', '`&`' and ';'.  It's a useful wildcard for use\n *      in a whitelist.\n *    - `**`: matches zero or more occurrences of *any* character.  As such, it's not\n *      not appropriate to use in for a scheme, domain, etc. as it would match too much.  (e.g.\n *      http://**.example.com/ would match http://evil.com/?ignore=.example.com/ and that might\n *      not have been the intention.)  Its usage at the very end of the path is ok.  (e.g.\n *      http://foo.example.com/templates/**).\n *  - **RegExp** (*see caveat below*)\n *    - *Caveat*:  While regular expressions are powerful and offer great flexibility,  their syntax\n *      (and all the inevitable escaping) makes them *harder to maintain*.  It's easy to\n *      accidentally introduce a bug when one updates a complex expression (imho, all regexes should\n *      have good test coverage.).  For instance, the use of `.` in the regex is correct only in a\n *      small number of cases.  A `.` character in the regex used when matching the scheme or a\n *      subdomain could be matched against a `:` or literal `.` that was likely not intended.   It\n *      is highly recommended to use the string patterns and only fall back to regular expressions\n *      if they as a last resort.\n *    - The regular expression must be an instance of RegExp (i.e. not a string.)  It is\n *      matched against the **entire** *normalized / absolute URL* of the resource being tested\n *      (even when the RegExp did not have the `^` and `$` codes.)  In addition, any flags\n *      present on the RegExp (such as multiline, global, ignoreCase) are ignored.\n *    - If you are generating your JavaScript from some other templating engine (not\n *      recommended, e.g. in issue [#4006](https://github.com/angular/angular.js/issues/4006)),\n *      remember to escape your regular expression (and be aware that you might need more than\n *      one level of escaping depending on your templating engine and the way you interpolated\n *      the value.)  Do make use of your platform's escaping mechanism as it might be good\n *      enough before coding your own.  e.g. Ruby has\n *      [Regexp.escape(str)](http://www.ruby-doc.org/core-2.0.0/Regexp.html#method-c-escape)\n *      and Python has [re.escape](http://docs.python.org/library/re.html#re.escape).\n *      Javascript lacks a similar built in function for escaping.  Take a look at Google\n *      Closure library's [goog.string.regExpEscape(s)](\n *      http://docs.closure-library.googlecode.com/git/closure_goog_string_string.js.source.html#line962).\n *\n * Refer {@link ng.$sceDelegateProvider $sceDelegateProvider} for an example.\n *\n * ## Show me an example using SCE.\n *\n * <example module=\"mySceApp\" deps=\"angular-sanitize.js\">\n * <file name=\"index.html\">\n *   <div ng-controller=\"AppController as myCtrl\">\n *     <i ng-bind-html=\"myCtrl.explicitlyTrustedHtml\" id=\"explicitlyTrustedHtml\"></i><br><br>\n *     <b>User comments</b><br>\n *     By default, HTML that isn't explicitly trusted (e.g. Alice's comment) is sanitized when\n *     $sanitize is available.  If $sanitize isn't available, this results in an error instead of an\n *     exploit.\n *     <div class=\"well\">\n *       <div ng-repeat=\"userComment in myCtrl.userComments\">\n *         <b>{{userComment.name}}</b>:\n *         <span ng-bind-html=\"userComment.htmlComment\" class=\"htmlComment\"></span>\n *         <br>\n *       </div>\n *     </div>\n *   </div>\n * </file>\n *\n * <file name=\"script.js\">\n *   angular.module('mySceApp', ['ngSanitize'])\n *     .controller('AppController', ['$http', '$templateCache', '$sce',\n *       function($http, $templateCache, $sce) {\n *         var self = this;\n *         $http.get(\"test_data.json\", {cache: $templateCache}).success(function(userComments) {\n *           self.userComments = userComments;\n *         });\n *         self.explicitlyTrustedHtml = $sce.trustAsHtml(\n *             '<span onmouseover=\"this.textContent=&quot;Explicitly trusted HTML bypasses ' +\n *             'sanitization.&quot;\">Hover over this text.</span>');\n *       }]);\n * </file>\n *\n * <file name=\"test_data.json\">\n * [\n *   { \"name\": \"Alice\",\n *     \"htmlComment\":\n *         \"<span onmouseover='this.textContent=\\\"PWN3D!\\\"'>Is <i>anyone</i> reading this?</span>\"\n *   },\n *   { \"name\": \"Bob\",\n *     \"htmlComment\": \"<i>Yes!</i>  Am I the only other one?\"\n *   }\n * ]\n * </file>\n *\n * <file name=\"protractor.js\" type=\"protractor\">\n *   describe('SCE doc demo', function() {\n *     it('should sanitize untrusted values', function() {\n *       expect(element.all(by.css('.htmlComment')).first().getInnerHtml())\n *           .toBe('<span>Is <i>anyone</i> reading this?</span>');\n *     });\n *\n *     it('should NOT sanitize explicitly trusted values', function() {\n *       expect(element(by.id('explicitlyTrustedHtml')).getInnerHtml()).toBe(\n *           '<span onmouseover=\"this.textContent=&quot;Explicitly trusted HTML bypasses ' +\n *           'sanitization.&quot;\">Hover over this text.</span>');\n *     });\n *   });\n * </file>\n * </example>\n *\n *\n *\n * ## Can I disable SCE completely?\n *\n * Yes, you can.  However, this is strongly discouraged.  SCE gives you a lot of security benefits\n * for little coding overhead.  It will be much harder to take an SCE disabled application and\n * either secure it on your own or enable SCE at a later stage.  It might make sense to disable SCE\n * for cases where you have a lot of existing code that was written before SCE was introduced and\n * you're migrating them a module at a time.\n *\n * That said, here's how you can completely disable SCE:\n *\n * ```\n * angular.module('myAppWithSceDisabledmyApp', []).config(function($sceProvider) {\n *   // Completely disable SCE.  For demonstration purposes only!\n *   // Do not use in new projects.\n *   $sceProvider.enabled(false);\n * });\n * ```\n *\n */\n/* jshint maxlen: 100 */\n\nfunction $SceProvider() {\n  var enabled = true;\n\n  /**\n   * @ngdoc method\n   * @name $sceProvider#enabled\n   * @kind function\n   *\n   * @param {boolean=} value If provided, then enables/disables SCE.\n   * @return {boolean} true if SCE is enabled, false otherwise.\n   *\n   * @description\n   * Enables/disables SCE and returns the current value.\n   */\n  this.enabled = function(value) {\n    if (arguments.length) {\n      enabled = !!value;\n    }\n    return enabled;\n  };\n\n\n  /* Design notes on the default implementation for SCE.\n   *\n   * The API contract for the SCE delegate\n   * -------------------------------------\n   * The SCE delegate object must provide the following 3 methods:\n   *\n   * - trustAs(contextEnum, value)\n   *     This method is used to tell the SCE service that the provided value is OK to use in the\n   *     contexts specified by contextEnum.  It must return an object that will be accepted by\n   *     getTrusted() for a compatible contextEnum and return this value.\n   *\n   * - valueOf(value)\n   *     For values that were not produced by trustAs(), return them as is.  For values that were\n   *     produced by trustAs(), return the corresponding input value to trustAs.  Basically, if\n   *     trustAs is wrapping the given values into some type, this operation unwraps it when given\n   *     such a value.\n   *\n   * - getTrusted(contextEnum, value)\n   *     This function should return the a value that is safe to use in the context specified by\n   *     contextEnum or throw and exception otherwise.\n   *\n   * NOTE: This contract deliberately does NOT state that values returned by trustAs() must be\n   * opaque or wrapped in some holder object.  That happens to be an implementation detail.  For\n   * instance, an implementation could maintain a registry of all trusted objects by context.  In\n   * such a case, trustAs() would return the same object that was passed in.  getTrusted() would\n   * return the same object passed in if it was found in the registry under a compatible context or\n   * throw an exception otherwise.  An implementation might only wrap values some of the time based\n   * on some criteria.  getTrusted() might return a value and not throw an exception for special\n   * constants or objects even if not wrapped.  All such implementations fulfill this contract.\n   *\n   *\n   * A note on the inheritance model for SCE contexts\n   * ------------------------------------------------\n   * I've used inheritance and made RESOURCE_URL wrapped types a subtype of URL wrapped types.  This\n   * is purely an implementation details.\n   *\n   * The contract is simply this:\n   *\n   *     getTrusted($sce.RESOURCE_URL, value) succeeding implies that getTrusted($sce.URL, value)\n   *     will also succeed.\n   *\n   * Inheritance happens to capture this in a natural way.  In some future, we\n   * may not use inheritance anymore.  That is OK because no code outside of\n   * sce.js and sceSpecs.js would need to be aware of this detail.\n   */\n\n  this.$get = ['$parse', '$sceDelegate', function(\n                $parse,   $sceDelegate) {\n    // Prereq: Ensure that we're not running in IE<11 quirks mode.  In that mode, IE < 11 allow\n    // the \"expression(javascript expression)\" syntax which is insecure.\n    if (enabled && msie < 8) {\n      throw $sceMinErr('iequirks',\n        'Strict Contextual Escaping does not support Internet Explorer version < 11 in quirks ' +\n        'mode.  You can fix this by adding the text <!doctype html> to the top of your HTML ' +\n        'document.  See http://docs.angularjs.org/api/ng.$sce for more information.');\n    }\n\n    var sce = shallowCopy(SCE_CONTEXTS);\n\n    /**\n     * @ngdoc method\n     * @name $sce#isEnabled\n     * @kind function\n     *\n     * @return {Boolean} true if SCE is enabled, false otherwise.  If you want to set the value, you\n     * have to do it at module config time on {@link ng.$sceProvider $sceProvider}.\n     *\n     * @description\n     * Returns a boolean indicating if SCE is enabled.\n     */\n    sce.isEnabled = function() {\n      return enabled;\n    };\n    sce.trustAs = $sceDelegate.trustAs;\n    sce.getTrusted = $sceDelegate.getTrusted;\n    sce.valueOf = $sceDelegate.valueOf;\n\n    if (!enabled) {\n      sce.trustAs = sce.getTrusted = function(type, value) { return value; };\n      sce.valueOf = identity;\n    }\n\n    /**\n     * @ngdoc method\n     * @name $sce#parseAs\n     *\n     * @description\n     * Converts Angular {@link guide/expression expression} into a function.  This is like {@link\n     * ng.$parse $parse} and is identical when the expression is a literal constant.  Otherwise, it\n     * wraps the expression in a call to {@link ng.$sce#getTrusted $sce.getTrusted(*type*,\n     * *result*)}\n     *\n     * @param {string} type The kind of SCE context in which this result will be used.\n     * @param {string} expression String expression to compile.\n     * @returns {function(context, locals)} a function which represents the compiled expression:\n     *\n     *    * `context` – `{object}` – an object against which any expressions embedded in the strings\n     *      are evaluated against (typically a scope object).\n     *    * `locals` – `{object=}` – local variables context object, useful for overriding values in\n     *      `context`.\n     */\n    sce.parseAs = function sceParseAs(type, expr) {\n      var parsed = $parse(expr);\n      if (parsed.literal && parsed.constant) {\n        return parsed;\n      } else {\n        return $parse(expr, function(value) {\n          return sce.getTrusted(type, value);\n        });\n      }\n    };\n\n    /**\n     * @ngdoc method\n     * @name $sce#trustAs\n     *\n     * @description\n     * Delegates to {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs`}.  As such,\n     * returns an object that is trusted by angular for use in specified strict contextual\n     * escaping contexts (such as ng-bind-html, ng-include, any src attribute\n     * interpolation, any dom event binding attribute interpolation such as for onclick,  etc.)\n     * that uses the provided value.  See * {@link ng.$sce $sce} for enabling strict contextual\n     * escaping.\n     *\n     * @param {string} type The kind of context in which this value is safe for use.  e.g. url,\n     *   resource_url, html, js and css.\n     * @param {*} value The value that that should be considered trusted/safe.\n     * @returns {*} A value that can be used to stand in for the provided `value` in places\n     * where Angular expects a $sce.trustAs() return value.\n     */\n\n    /**\n     * @ngdoc method\n     * @name $sce#trustAsHtml\n     *\n     * @description\n     * Shorthand method.  `$sce.trustAsHtml(value)` →\n     *     {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs($sce.HTML, value)`}\n     *\n     * @param {*} value The value to trustAs.\n     * @returns {*} An object that can be passed to {@link ng.$sce#getTrustedHtml\n     *     $sce.getTrustedHtml(value)} to obtain the original value.  (privileged directives\n     *     only accept expressions that are either literal constants or are the\n     *     return value of {@link ng.$sce#trustAs $sce.trustAs}.)\n     */\n\n    /**\n     * @ngdoc method\n     * @name $sce#trustAsUrl\n     *\n     * @description\n     * Shorthand method.  `$sce.trustAsUrl(value)` →\n     *     {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs($sce.URL, value)`}\n     *\n     * @param {*} value The value to trustAs.\n     * @returns {*} An object that can be passed to {@link ng.$sce#getTrustedUrl\n     *     $sce.getTrustedUrl(value)} to obtain the original value.  (privileged directives\n     *     only accept expressions that are either literal constants or are the\n     *     return value of {@link ng.$sce#trustAs $sce.trustAs}.)\n     */\n\n    /**\n     * @ngdoc method\n     * @name $sce#trustAsResourceUrl\n     *\n     * @description\n     * Shorthand method.  `$sce.trustAsResourceUrl(value)` →\n     *     {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs($sce.RESOURCE_URL, value)`}\n     *\n     * @param {*} value The value to trustAs.\n     * @returns {*} An object that can be passed to {@link ng.$sce#getTrustedResourceUrl\n     *     $sce.getTrustedResourceUrl(value)} to obtain the original value.  (privileged directives\n     *     only accept expressions that are either literal constants or are the return\n     *     value of {@link ng.$sce#trustAs $sce.trustAs}.)\n     */\n\n    /**\n     * @ngdoc method\n     * @name $sce#trustAsJs\n     *\n     * @description\n     * Shorthand method.  `$sce.trustAsJs(value)` →\n     *     {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs($sce.JS, value)`}\n     *\n     * @param {*} value The value to trustAs.\n     * @returns {*} An object that can be passed to {@link ng.$sce#getTrustedJs\n     *     $sce.getTrustedJs(value)} to obtain the original value.  (privileged directives\n     *     only accept expressions that are either literal constants or are the\n     *     return value of {@link ng.$sce#trustAs $sce.trustAs}.)\n     */\n\n    /**\n     * @ngdoc method\n     * @name $sce#getTrusted\n     *\n     * @description\n     * Delegates to {@link ng.$sceDelegate#getTrusted `$sceDelegate.getTrusted`}.  As such,\n     * takes the result of a {@link ng.$sce#trustAs `$sce.trustAs`}() call and returns the\n     * originally supplied value if the queried context type is a supertype of the created type.\n     * If this condition isn't satisfied, throws an exception.\n     *\n     * @param {string} type The kind of context in which this value is to be used.\n     * @param {*} maybeTrusted The result of a prior {@link ng.$sce#trustAs `$sce.trustAs`}\n     *                         call.\n     * @returns {*} The value the was originally provided to\n     *              {@link ng.$sce#trustAs `$sce.trustAs`} if valid in this context.\n     *              Otherwise, throws an exception.\n     */\n\n    /**\n     * @ngdoc method\n     * @name $sce#getTrustedHtml\n     *\n     * @description\n     * Shorthand method.  `$sce.getTrustedHtml(value)` →\n     *     {@link ng.$sceDelegate#getTrusted `$sceDelegate.getTrusted($sce.HTML, value)`}\n     *\n     * @param {*} value The value to pass to `$sce.getTrusted`.\n     * @returns {*} The return value of `$sce.getTrusted($sce.HTML, value)`\n     */\n\n    /**\n     * @ngdoc method\n     * @name $sce#getTrustedCss\n     *\n     * @description\n     * Shorthand method.  `$sce.getTrustedCss(value)` →\n     *     {@link ng.$sceDelegate#getTrusted `$sceDelegate.getTrusted($sce.CSS, value)`}\n     *\n     * @param {*} value The value to pass to `$sce.getTrusted`.\n     * @returns {*} The return value of `$sce.getTrusted($sce.CSS, value)`\n     */\n\n    /**\n     * @ngdoc method\n     * @name $sce#getTrustedUrl\n     *\n     * @description\n     * Shorthand method.  `$sce.getTrustedUrl(value)` →\n     *     {@link ng.$sceDelegate#getTrusted `$sceDelegate.getTrusted($sce.URL, value)`}\n     *\n     * @param {*} value The value to pass to `$sce.getTrusted`.\n     * @returns {*} The return value of `$sce.getTrusted($sce.URL, value)`\n     */\n\n    /**\n     * @ngdoc method\n     * @name $sce#getTrustedResourceUrl\n     *\n     * @description\n     * Shorthand method.  `$sce.getTrustedResourceUrl(value)` →\n     *     {@link ng.$sceDelegate#getTrusted `$sceDelegate.getTrusted($sce.RESOURCE_URL, value)`}\n     *\n     * @param {*} value The value to pass to `$sceDelegate.getTrusted`.\n     * @returns {*} The return value of `$sce.getTrusted($sce.RESOURCE_URL, value)`\n     */\n\n    /**\n     * @ngdoc method\n     * @name $sce#getTrustedJs\n     *\n     * @description\n     * Shorthand method.  `$sce.getTrustedJs(value)` →\n     *     {@link ng.$sceDelegate#getTrusted `$sceDelegate.getTrusted($sce.JS, value)`}\n     *\n     * @param {*} value The value to pass to `$sce.getTrusted`.\n     * @returns {*} The return value of `$sce.getTrusted($sce.JS, value)`\n     */\n\n    /**\n     * @ngdoc method\n     * @name $sce#parseAsHtml\n     *\n     * @description\n     * Shorthand method.  `$sce.parseAsHtml(expression string)` →\n     *     {@link ng.$sce#parseAs `$sce.parseAs($sce.HTML, value)`}\n     *\n     * @param {string} expression String expression to compile.\n     * @returns {function(context, locals)} a function which represents the compiled expression:\n     *\n     *    * `context` – `{object}` – an object against which any expressions embedded in the strings\n     *      are evaluated against (typically a scope object).\n     *    * `locals` – `{object=}` – local variables context object, useful for overriding values in\n     *      `context`.\n     */\n\n    /**\n     * @ngdoc method\n     * @name $sce#parseAsCss\n     *\n     * @description\n     * Shorthand method.  `$sce.parseAsCss(value)` →\n     *     {@link ng.$sce#parseAs `$sce.parseAs($sce.CSS, value)`}\n     *\n     * @param {string} expression String expression to compile.\n     * @returns {function(context, locals)} a function which represents the compiled expression:\n     *\n     *    * `context` – `{object}` – an object against which any expressions embedded in the strings\n     *      are evaluated against (typically a scope object).\n     *    * `locals` – `{object=}` – local variables context object, useful for overriding values in\n     *      `context`.\n     */\n\n    /**\n     * @ngdoc method\n     * @name $sce#parseAsUrl\n     *\n     * @description\n     * Shorthand method.  `$sce.parseAsUrl(value)` →\n     *     {@link ng.$sce#parseAs `$sce.parseAs($sce.URL, value)`}\n     *\n     * @param {string} expression String expression to compile.\n     * @returns {function(context, locals)} a function which represents the compiled expression:\n     *\n     *    * `context` – `{object}` – an object against which any expressions embedded in the strings\n     *      are evaluated against (typically a scope object).\n     *    * `locals` – `{object=}` – local variables context object, useful for overriding values in\n     *      `context`.\n     */\n\n    /**\n     * @ngdoc method\n     * @name $sce#parseAsResourceUrl\n     *\n     * @description\n     * Shorthand method.  `$sce.parseAsResourceUrl(value)` →\n     *     {@link ng.$sce#parseAs `$sce.parseAs($sce.RESOURCE_URL, value)`}\n     *\n     * @param {string} expression String expression to compile.\n     * @returns {function(context, locals)} a function which represents the compiled expression:\n     *\n     *    * `context` – `{object}` – an object against which any expressions embedded in the strings\n     *      are evaluated against (typically a scope object).\n     *    * `locals` – `{object=}` – local variables context object, useful for overriding values in\n     *      `context`.\n     */\n\n    /**\n     * @ngdoc method\n     * @name $sce#parseAsJs\n     *\n     * @description\n     * Shorthand method.  `$sce.parseAsJs(value)` →\n     *     {@link ng.$sce#parseAs `$sce.parseAs($sce.JS, value)`}\n     *\n     * @param {string} expression String expression to compile.\n     * @returns {function(context, locals)} a function which represents the compiled expression:\n     *\n     *    * `context` – `{object}` – an object against which any expressions embedded in the strings\n     *      are evaluated against (typically a scope object).\n     *    * `locals` – `{object=}` – local variables context object, useful for overriding values in\n     *      `context`.\n     */\n\n    // Shorthand delegations.\n    var parse = sce.parseAs,\n        getTrusted = sce.getTrusted,\n        trustAs = sce.trustAs;\n\n    forEach(SCE_CONTEXTS, function(enumValue, name) {\n      var lName = lowercase(name);\n      sce[camelCase(\"parse_as_\" + lName)] = function(expr) {\n        return parse(enumValue, expr);\n      };\n      sce[camelCase(\"get_trusted_\" + lName)] = function(value) {\n        return getTrusted(enumValue, value);\n      };\n      sce[camelCase(\"trust_as_\" + lName)] = function(value) {\n        return trustAs(enumValue, value);\n      };\n    });\n\n    return sce;\n  }];\n}\n\n/**\n * !!! This is an undocumented \"private\" service !!!\n *\n * @name $sniffer\n * @requires $window\n * @requires $document\n *\n * @property {boolean} history Does the browser support html5 history api ?\n * @property {boolean} transitions Does the browser support CSS transition events ?\n * @property {boolean} animations Does the browser support CSS animation events ?\n *\n * @description\n * This is very simple implementation of testing browser's features.\n */\nfunction $SnifferProvider() {\n  this.$get = ['$window', '$document', function($window, $document) {\n    var eventSupport = {},\n        android =\n          int((/android (\\d+)/.exec(lowercase(($window.navigator || {}).userAgent)) || [])[1]),\n        boxee = /Boxee/i.test(($window.navigator || {}).userAgent),\n        document = $document[0] || {},\n        vendorPrefix,\n        vendorRegex = /^(Moz|webkit|ms)(?=[A-Z])/,\n        bodyStyle = document.body && document.body.style,\n        transitions = false,\n        animations = false,\n        match;\n\n    if (bodyStyle) {\n      for (var prop in bodyStyle) {\n        if (match = vendorRegex.exec(prop)) {\n          vendorPrefix = match[0];\n          vendorPrefix = vendorPrefix.substr(0, 1).toUpperCase() + vendorPrefix.substr(1);\n          break;\n        }\n      }\n\n      if (!vendorPrefix) {\n        vendorPrefix = ('WebkitOpacity' in bodyStyle) && 'webkit';\n      }\n\n      transitions = !!(('transition' in bodyStyle) || (vendorPrefix + 'Transition' in bodyStyle));\n      animations  = !!(('animation' in bodyStyle) || (vendorPrefix + 'Animation' in bodyStyle));\n\n      if (android && (!transitions ||  !animations)) {\n        transitions = isString(document.body.style.webkitTransition);\n        animations = isString(document.body.style.webkitAnimation);\n      }\n    }\n\n\n    return {\n      // Android has history.pushState, but it does not update location correctly\n      // so let's not use the history API at all.\n      // http://code.google.com/p/android/issues/detail?id=17471\n      // https://github.com/angular/angular.js/issues/904\n\n      // older webkit browser (533.9) on Boxee box has exactly the same problem as Android has\n      // so let's not use the history API also\n      // We are purposefully using `!(android < 4)` to cover the case when `android` is undefined\n      // jshint -W018\n      history: !!($window.history && $window.history.pushState && !(android < 4) && !boxee),\n      // jshint +W018\n      hasEvent: function(event) {\n        // IE9 implements 'input' event it's so fubared that we rather pretend that it doesn't have\n        // it. In particular the event is not fired when backspace or delete key are pressed or\n        // when cut operation is performed.\n        // IE10+ implements 'input' event but it erroneously fires under various situations,\n        // e.g. when placeholder changes, or a form is focused.\n        if (event === 'input' && msie <= 11) return false;\n\n        if (isUndefined(eventSupport[event])) {\n          var divElm = document.createElement('div');\n          eventSupport[event] = 'on' + event in divElm;\n        }\n\n        return eventSupport[event];\n      },\n      csp: csp(),\n      vendorPrefix: vendorPrefix,\n      transitions: transitions,\n      animations: animations,\n      android: android\n    };\n  }];\n}\n\nvar $compileMinErr = minErr('$compile');\n\n/**\n * @ngdoc service\n * @name $templateRequest\n *\n * @description\n * The `$templateRequest` service downloads the provided template using `$http` and, upon success,\n * stores the contents inside of `$templateCache`. If the HTTP request fails or the response data\n * of the HTTP request is empty, a `$compile` error will be thrown (the exception can be thwarted\n * by setting the 2nd parameter of the function to true).\n *\n * @param {string} tpl The HTTP request template URL\n * @param {boolean=} ignoreRequestError Whether or not to ignore the exception when the request fails or the template is empty\n *\n * @return {Promise} the HTTP Promise for the given.\n *\n * @property {number} totalPendingRequests total amount of pending template requests being downloaded.\n */\nfunction $TemplateRequestProvider() {\n  this.$get = ['$templateCache', '$http', '$q', function($templateCache, $http, $q) {\n    function handleRequestFn(tpl, ignoreRequestError) {\n      handleRequestFn.totalPendingRequests++;\n\n      var transformResponse = $http.defaults && $http.defaults.transformResponse;\n\n      if (isArray(transformResponse)) {\n        transformResponse = transformResponse.filter(function(transformer) {\n          return transformer !== defaultHttpResponseTransform;\n        });\n      } else if (transformResponse === defaultHttpResponseTransform) {\n        transformResponse = null;\n      }\n\n      var httpOptions = {\n        cache: $templateCache,\n        transformResponse: transformResponse\n      };\n\n      return $http.get(tpl, httpOptions)\n        .finally(function() {\n          handleRequestFn.totalPendingRequests--;\n        })\n        .then(function(response) {\n          return response.data;\n        }, handleError);\n\n      function handleError(resp) {\n        if (!ignoreRequestError) {\n          throw $compileMinErr('tpload', 'Failed to load template: {0}', tpl);\n        }\n        return $q.reject(resp);\n      }\n    }\n\n    handleRequestFn.totalPendingRequests = 0;\n\n    return handleRequestFn;\n  }];\n}\n\nfunction $$TestabilityProvider() {\n  this.$get = ['$rootScope', '$browser', '$location',\n       function($rootScope,   $browser,   $location) {\n\n    /**\n     * @name $testability\n     *\n     * @description\n     * The private $$testability service provides a collection of methods for use when debugging\n     * or by automated test and debugging tools.\n     */\n    var testability = {};\n\n    /**\n     * @name $$testability#findBindings\n     *\n     * @description\n     * Returns an array of elements that are bound (via ng-bind or {{}})\n     * to expressions matching the input.\n     *\n     * @param {Element} element The element root to search from.\n     * @param {string} expression The binding expression to match.\n     * @param {boolean} opt_exactMatch If true, only returns exact matches\n     *     for the expression. Filters and whitespace are ignored.\n     */\n    testability.findBindings = function(element, expression, opt_exactMatch) {\n      var bindings = element.getElementsByClassName('ng-binding');\n      var matches = [];\n      forEach(bindings, function(binding) {\n        var dataBinding = angular.element(binding).data('$binding');\n        if (dataBinding) {\n          forEach(dataBinding, function(bindingName) {\n            if (opt_exactMatch) {\n              var matcher = new RegExp('(^|\\\\s)' + escapeForRegexp(expression) + '(\\\\s|\\\\||$)');\n              if (matcher.test(bindingName)) {\n                matches.push(binding);\n              }\n            } else {\n              if (bindingName.indexOf(expression) != -1) {\n                matches.push(binding);\n              }\n            }\n          });\n        }\n      });\n      return matches;\n    };\n\n    /**\n     * @name $$testability#findModels\n     *\n     * @description\n     * Returns an array of elements that are two-way found via ng-model to\n     * expressions matching the input.\n     *\n     * @param {Element} element The element root to search from.\n     * @param {string} expression The model expression to match.\n     * @param {boolean} opt_exactMatch If true, only returns exact matches\n     *     for the expression.\n     */\n    testability.findModels = function(element, expression, opt_exactMatch) {\n      var prefixes = ['ng-', 'data-ng-', 'ng\\\\:'];\n      for (var p = 0; p < prefixes.length; ++p) {\n        var attributeEquals = opt_exactMatch ? '=' : '*=';\n        var selector = '[' + prefixes[p] + 'model' + attributeEquals + '\"' + expression + '\"]';\n        var elements = element.querySelectorAll(selector);\n        if (elements.length) {\n          return elements;\n        }\n      }\n    };\n\n    /**\n     * @name $$testability#getLocation\n     *\n     * @description\n     * Shortcut for getting the location in a browser agnostic way. Returns\n     *     the path, search, and hash. (e.g. /path?a=b#hash)\n     */\n    testability.getLocation = function() {\n      return $location.url();\n    };\n\n    /**\n     * @name $$testability#setLocation\n     *\n     * @description\n     * Shortcut for navigating to a location without doing a full page reload.\n     *\n     * @param {string} url The location url (path, search and hash,\n     *     e.g. /path?a=b#hash) to go to.\n     */\n    testability.setLocation = function(url) {\n      if (url !== $location.url()) {\n        $location.url(url);\n        $rootScope.$digest();\n      }\n    };\n\n    /**\n     * @name $$testability#whenStable\n     *\n     * @description\n     * Calls the callback when $timeout and $http requests are completed.\n     *\n     * @param {function} callback\n     */\n    testability.whenStable = function(callback) {\n      $browser.notifyWhenNoOutstandingRequests(callback);\n    };\n\n    return testability;\n  }];\n}\n\nfunction $TimeoutProvider() {\n  this.$get = ['$rootScope', '$browser', '$q', '$$q', '$exceptionHandler',\n       function($rootScope,   $browser,   $q,   $$q,   $exceptionHandler) {\n    var deferreds = {};\n\n\n     /**\n      * @ngdoc service\n      * @name $timeout\n      *\n      * @description\n      * Angular's wrapper for `window.setTimeout`. The `fn` function is wrapped into a try/catch\n      * block and delegates any exceptions to\n      * {@link ng.$exceptionHandler $exceptionHandler} service.\n      *\n      * The return value of registering a timeout function is a promise, which will be resolved when\n      * the timeout is reached and the timeout function is executed.\n      *\n      * To cancel a timeout request, call `$timeout.cancel(promise)`.\n      *\n      * In tests you can use {@link ngMock.$timeout `$timeout.flush()`} to\n      * synchronously flush the queue of deferred functions.\n      *\n      * @param {function()} fn A function, whose execution should be delayed.\n      * @param {number=} [delay=0] Delay in milliseconds.\n      * @param {boolean=} [invokeApply=true] If set to `false` skips model dirty checking, otherwise\n      *   will invoke `fn` within the {@link ng.$rootScope.Scope#$apply $apply} block.\n      * @returns {Promise} Promise that will be resolved when the timeout is reached. The value this\n      *   promise will be resolved with is the return value of the `fn` function.\n      *\n      */\n    function timeout(fn, delay, invokeApply) {\n      var skipApply = (isDefined(invokeApply) && !invokeApply),\n          deferred = (skipApply ? $$q : $q).defer(),\n          promise = deferred.promise,\n          timeoutId;\n\n      timeoutId = $browser.defer(function() {\n        try {\n          deferred.resolve(fn());\n        } catch (e) {\n          deferred.reject(e);\n          $exceptionHandler(e);\n        }\n        finally {\n          delete deferreds[promise.$$timeoutId];\n        }\n\n        if (!skipApply) $rootScope.$apply();\n      }, delay);\n\n      promise.$$timeoutId = timeoutId;\n      deferreds[timeoutId] = deferred;\n\n      return promise;\n    }\n\n\n     /**\n      * @ngdoc method\n      * @name $timeout#cancel\n      *\n      * @description\n      * Cancels a task associated with the `promise`. As a result of this, the promise will be\n      * resolved with a rejection.\n      *\n      * @param {Promise=} promise Promise returned by the `$timeout` function.\n      * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfully\n      *   canceled.\n      */\n    timeout.cancel = function(promise) {\n      if (promise && promise.$$timeoutId in deferreds) {\n        deferreds[promise.$$timeoutId].reject('canceled');\n        delete deferreds[promise.$$timeoutId];\n        return $browser.defer.cancel(promise.$$timeoutId);\n      }\n      return false;\n    };\n\n    return timeout;\n  }];\n}\n\n// NOTE:  The usage of window and document instead of $window and $document here is\n// deliberate.  This service depends on the specific behavior of anchor nodes created by the\n// browser (resolving and parsing URLs) that is unlikely to be provided by mock objects and\n// cause us to break tests.  In addition, when the browser resolves a URL for XHR, it\n// doesn't know about mocked locations and resolves URLs to the real document - which is\n// exactly the behavior needed here.  There is little value is mocking these out for this\n// service.\nvar urlParsingNode = document.createElement(\"a\");\nvar originUrl = urlResolve(window.location.href);\n\n\n/**\n *\n * Implementation Notes for non-IE browsers\n * ----------------------------------------\n * Assigning a URL to the href property of an anchor DOM node, even one attached to the DOM,\n * results both in the normalizing and parsing of the URL.  Normalizing means that a relative\n * URL will be resolved into an absolute URL in the context of the application document.\n * Parsing means that the anchor node's host, hostname, protocol, port, pathname and related\n * properties are all populated to reflect the normalized URL.  This approach has wide\n * compatibility - Safari 1+, Mozilla 1+, Opera 7+,e etc.  See\n * http://www.aptana.com/reference/html/api/HTMLAnchorElement.html\n *\n * Implementation Notes for IE\n * ---------------------------\n * IE >= 8 and <= 10 normalizes the URL when assigned to the anchor node similar to the other\n * browsers.  However, the parsed components will not be set if the URL assigned did not specify\n * them.  (e.g. if you assign a.href = \"foo\", then a.protocol, a.host, etc. will be empty.)  We\n * work around that by performing the parsing in a 2nd step by taking a previously normalized\n * URL (e.g. by assigning to a.href) and assigning it a.href again.  This correctly populates the\n * properties such as protocol, hostname, port, etc.\n *\n * IE7 does not normalize the URL when assigned to an anchor node.  (Apparently, it does, if one\n * uses the inner HTML approach to assign the URL as part of an HTML snippet -\n * http://stackoverflow.com/a/472729)  However, setting img[src] does normalize the URL.\n * Unfortunately, setting img[src] to something like \"javascript:foo\" on IE throws an exception.\n * Since the primary usage for normalizing URLs is to sanitize such URLs, we can't use that\n * method and IE < 8 is unsupported.\n *\n * References:\n *   http://developer.mozilla.org/en-US/docs/Web/API/HTMLAnchorElement\n *   http://www.aptana.com/reference/html/api/HTMLAnchorElement.html\n *   http://url.spec.whatwg.org/#urlutils\n *   https://github.com/angular/angular.js/pull/2902\n *   http://james.padolsey.com/javascript/parsing-urls-with-the-dom/\n *\n * @kind function\n * @param {string} url The URL to be parsed.\n * @description Normalizes and parses a URL.\n * @returns {object} Returns the normalized URL as a dictionary.\n *\n *   | member name   | Description    |\n *   |---------------|----------------|\n *   | href          | A normalized version of the provided URL if it was not an absolute URL |\n *   | protocol      | The protocol including the trailing colon                              |\n *   | host          | The host and port (if the port is non-default) of the normalizedUrl    |\n *   | search        | The search params, minus the question mark                             |\n *   | hash          | The hash string, minus the hash symbol\n *   | hostname      | The hostname\n *   | port          | The port, without \":\"\n *   | pathname      | The pathname, beginning with \"/\"\n *\n */\nfunction urlResolve(url) {\n  var href = url;\n\n  if (msie) {\n    // Normalize before parse.  Refer Implementation Notes on why this is\n    // done in two steps on IE.\n    urlParsingNode.setAttribute(\"href\", href);\n    href = urlParsingNode.href;\n  }\n\n  urlParsingNode.setAttribute('href', href);\n\n  // urlParsingNode provides the UrlUtils interface - http://url.spec.whatwg.org/#urlutils\n  return {\n    href: urlParsingNode.href,\n    protocol: urlParsingNode.protocol ? urlParsingNode.protocol.replace(/:$/, '') : '',\n    host: urlParsingNode.host,\n    search: urlParsingNode.search ? urlParsingNode.search.replace(/^\\?/, '') : '',\n    hash: urlParsingNode.hash ? urlParsingNode.hash.replace(/^#/, '') : '',\n    hostname: urlParsingNode.hostname,\n    port: urlParsingNode.port,\n    pathname: (urlParsingNode.pathname.charAt(0) === '/')\n      ? urlParsingNode.pathname\n      : '/' + urlParsingNode.pathname\n  };\n}\n\n/**\n * Parse a request URL and determine whether this is a same-origin request as the application document.\n *\n * @param {string|object} requestUrl The url of the request as a string that will be resolved\n * or a parsed URL object.\n * @returns {boolean} Whether the request is for the same origin as the application document.\n */\nfunction urlIsSameOrigin(requestUrl) {\n  var parsed = (isString(requestUrl)) ? urlResolve(requestUrl) : requestUrl;\n  return (parsed.protocol === originUrl.protocol &&\n          parsed.host === originUrl.host);\n}\n\n/**\n * @ngdoc service\n * @name $window\n *\n * @description\n * A reference to the browser's `window` object. While `window`\n * is globally available in JavaScript, it causes testability problems, because\n * it is a global variable. In angular we always refer to it through the\n * `$window` service, so it may be overridden, removed or mocked for testing.\n *\n * Expressions, like the one defined for the `ngClick` directive in the example\n * below, are evaluated with respect to the current scope.  Therefore, there is\n * no risk of inadvertently coding in a dependency on a global value in such an\n * expression.\n *\n * @example\n   <example module=\"windowExample\">\n     <file name=\"index.html\">\n       <script>\n         angular.module('windowExample', [])\n           .controller('ExampleController', ['$scope', '$window', function($scope, $window) {\n             $scope.greeting = 'Hello, World!';\n             $scope.doGreeting = function(greeting) {\n               $window.alert(greeting);\n             };\n           }]);\n       </script>\n       <div ng-controller=\"ExampleController\">\n         <input type=\"text\" ng-model=\"greeting\" />\n         <button ng-click=\"doGreeting(greeting)\">ALERT</button>\n       </div>\n     </file>\n     <file name=\"protractor.js\" type=\"protractor\">\n      it('should display the greeting in the input box', function() {\n       element(by.model('greeting')).sendKeys('Hello, E2E Tests');\n       // If we click the button it will block the test runner\n       // element(':button').click();\n      });\n     </file>\n   </example>\n */\nfunction $WindowProvider() {\n  this.$get = valueFn(window);\n}\n\n/* global currencyFilter: true,\n dateFilter: true,\n filterFilter: true,\n jsonFilter: true,\n limitToFilter: true,\n lowercaseFilter: true,\n numberFilter: true,\n orderByFilter: true,\n uppercaseFilter: true,\n */\n\n/**\n * @ngdoc provider\n * @name $filterProvider\n * @description\n *\n * Filters are just functions which transform input to an output. However filters need to be\n * Dependency Injected. To achieve this a filter definition consists of a factory function which is\n * annotated with dependencies and is responsible for creating a filter function.\n *\n * ```js\n *   // Filter registration\n *   function MyModule($provide, $filterProvider) {\n *     // create a service to demonstrate injection (not always needed)\n *     $provide.value('greet', function(name){\n *       return 'Hello ' + name + '!';\n *     });\n *\n *     // register a filter factory which uses the\n *     // greet service to demonstrate DI.\n *     $filterProvider.register('greet', function(greet){\n *       // return the filter function which uses the greet service\n *       // to generate salutation\n *       return function(text) {\n *         // filters need to be forgiving so check input validity\n *         return text && greet(text) || text;\n *       };\n *     });\n *   }\n * ```\n *\n * The filter function is registered with the `$injector` under the filter name suffix with\n * `Filter`.\n *\n * ```js\n *   it('should be the same instance', inject(\n *     function($filterProvider) {\n *       $filterProvider.register('reverse', function(){\n *         return ...;\n *       });\n *     },\n *     function($filter, reverseFilter) {\n *       expect($filter('reverse')).toBe(reverseFilter);\n *     });\n * ```\n *\n *\n * For more information about how angular filters work, and how to create your own filters, see\n * {@link guide/filter Filters} in the Angular Developer Guide.\n */\n\n/**\n * @ngdoc service\n * @name $filter\n * @kind function\n * @description\n * Filters are used for formatting data displayed to the user.\n *\n * The general syntax in templates is as follows:\n *\n *         {{ expression [| filter_name[:parameter_value] ... ] }}\n *\n * @param {String} name Name of the filter function to retrieve\n * @return {Function} the filter function\n * @example\n   <example name=\"$filter\" module=\"filterExample\">\n     <file name=\"index.html\">\n       <div ng-controller=\"MainCtrl\">\n        <h3>{{ originalText }}</h3>\n        <h3>{{ filteredText }}</h3>\n       </div>\n     </file>\n\n     <file name=\"script.js\">\n      angular.module('filterExample', [])\n      .controller('MainCtrl', function($scope, $filter) {\n        $scope.originalText = 'hello';\n        $scope.filteredText = $filter('uppercase')($scope.originalText);\n      });\n     </file>\n   </example>\n  */\n$FilterProvider.$inject = ['$provide'];\nfunction $FilterProvider($provide) {\n  var suffix = 'Filter';\n\n  /**\n   * @ngdoc method\n   * @name $filterProvider#register\n   * @param {string|Object} name Name of the filter function, or an object map of filters where\n   *    the keys are the filter names and the values are the filter factories.\n   * @returns {Object} Registered filter instance, or if a map of filters was provided then a map\n   *    of the registered filter instances.\n   */\n  function register(name, factory) {\n    if (isObject(name)) {\n      var filters = {};\n      forEach(name, function(filter, key) {\n        filters[key] = register(key, filter);\n      });\n      return filters;\n    } else {\n      return $provide.factory(name + suffix, factory);\n    }\n  }\n  this.register = register;\n\n  this.$get = ['$injector', function($injector) {\n    return function(name) {\n      return $injector.get(name + suffix);\n    };\n  }];\n\n  ////////////////////////////////////////\n\n  /* global\n    currencyFilter: false,\n    dateFilter: false,\n    filterFilter: false,\n    jsonFilter: false,\n    limitToFilter: false,\n    lowercaseFilter: false,\n    numberFilter: false,\n    orderByFilter: false,\n    uppercaseFilter: false,\n  */\n\n  register('currency', currencyFilter);\n  register('date', dateFilter);\n  register('filter', filterFilter);\n  register('json', jsonFilter);\n  register('limitTo', limitToFilter);\n  register('lowercase', lowercaseFilter);\n  register('number', numberFilter);\n  register('orderBy', orderByFilter);\n  register('uppercase', uppercaseFilter);\n}\n\n/**\n * @ngdoc filter\n * @name filter\n * @kind function\n *\n * @description\n * Selects a subset of items from `array` and returns it as a new array.\n *\n * @param {Array} array The source array.\n * @param {string|Object|function()} expression The predicate to be used for selecting items from\n *   `array`.\n *\n *   Can be one of:\n *\n *   - `string`: The string is used for matching against the contents of the `array`. All strings or\n *     objects with string properties in `array` that match this string will be returned. This also\n *     applies to nested object properties.\n *     The predicate can be negated by prefixing the string with `!`.\n *\n *   - `Object`: A pattern object can be used to filter specific properties on objects contained\n *     by `array`. For example `{name:\"M\", phone:\"1\"}` predicate will return an array of items\n *     which have property `name` containing \"M\" and property `phone` containing \"1\". A special\n *     property name `$` can be used (as in `{$:\"text\"}`) to accept a match against any\n *     property of the object or its nested object properties. That's equivalent to the simple\n *     substring match with a `string` as described above. The predicate can be negated by prefixing\n *     the string with `!`.\n *     For example `{name: \"!M\"}` predicate will return an array of items which have property `name`\n *     not containing \"M\".\n *\n *     Note that a named property will match properties on the same level only, while the special\n *     `$` property will match properties on the same level or deeper. E.g. an array item like\n *     `{name: {first: 'John', last: 'Doe'}}` will **not** be matched by `{name: 'John'}`, but\n *     **will** be matched by `{$: 'John'}`.\n *\n *   - `function(value, index)`: A predicate function can be used to write arbitrary filters. The\n *     function is called for each element of `array`. The final result is an array of those\n *     elements that the predicate returned true for.\n *\n * @param {function(actual, expected)|true|undefined} comparator Comparator which is used in\n *     determining if the expected value (from the filter expression) and actual value (from\n *     the object in the array) should be considered a match.\n *\n *   Can be one of:\n *\n *   - `function(actual, expected)`:\n *     The function will be given the object value and the predicate value to compare and\n *     should return true if both values should be considered equal.\n *\n *   - `true`: A shorthand for `function(actual, expected) { return angular.equals(actual, expected)}`.\n *     This is essentially strict comparison of expected and actual.\n *\n *   - `false|undefined`: A short hand for a function which will look for a substring match in case\n *     insensitive way.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n       <div ng-init=\"friends = [{name:'John', phone:'555-1276'},\n                                {name:'Mary', phone:'800-BIG-MARY'},\n                                {name:'Mike', phone:'555-4321'},\n                                {name:'Adam', phone:'555-5678'},\n                                {name:'Julie', phone:'555-8765'},\n                                {name:'Juliette', phone:'555-5678'}]\"></div>\n\n       Search: <input ng-model=\"searchText\">\n       <table id=\"searchTextResults\">\n         <tr><th>Name</th><th>Phone</th></tr>\n         <tr ng-repeat=\"friend in friends | filter:searchText\">\n           <td>{{friend.name}}</td>\n           <td>{{friend.phone}}</td>\n         </tr>\n       </table>\n       <hr>\n       Any: <input ng-model=\"search.$\"> <br>\n       Name only <input ng-model=\"search.name\"><br>\n       Phone only <input ng-model=\"search.phone\"><br>\n       Equality <input type=\"checkbox\" ng-model=\"strict\"><br>\n       <table id=\"searchObjResults\">\n         <tr><th>Name</th><th>Phone</th></tr>\n         <tr ng-repeat=\"friendObj in friends | filter:search:strict\">\n           <td>{{friendObj.name}}</td>\n           <td>{{friendObj.phone}}</td>\n         </tr>\n       </table>\n     </file>\n     <file name=\"protractor.js\" type=\"protractor\">\n       var expectFriendNames = function(expectedNames, key) {\n         element.all(by.repeater(key + ' in friends').column(key + '.name')).then(function(arr) {\n           arr.forEach(function(wd, i) {\n             expect(wd.getText()).toMatch(expectedNames[i]);\n           });\n         });\n       };\n\n       it('should search across all fields when filtering with a string', function() {\n         var searchText = element(by.model('searchText'));\n         searchText.clear();\n         searchText.sendKeys('m');\n         expectFriendNames(['Mary', 'Mike', 'Adam'], 'friend');\n\n         searchText.clear();\n         searchText.sendKeys('76');\n         expectFriendNames(['John', 'Julie'], 'friend');\n       });\n\n       it('should search in specific fields when filtering with a predicate object', function() {\n         var searchAny = element(by.model('search.$'));\n         searchAny.clear();\n         searchAny.sendKeys('i');\n         expectFriendNames(['Mary', 'Mike', 'Julie', 'Juliette'], 'friendObj');\n       });\n       it('should use a equal comparison when comparator is true', function() {\n         var searchName = element(by.model('search.name'));\n         var strict = element(by.model('strict'));\n         searchName.clear();\n         searchName.sendKeys('Julie');\n         strict.click();\n         expectFriendNames(['Julie'], 'friendObj');\n       });\n     </file>\n   </example>\n */\nfunction filterFilter() {\n  return function(array, expression, comparator) {\n    if (!isArray(array)) return array;\n\n    var predicateFn;\n    var matchAgainstAnyProp;\n\n    switch (typeof expression) {\n      case 'function':\n        predicateFn = expression;\n        break;\n      case 'boolean':\n      case 'number':\n      case 'string':\n        matchAgainstAnyProp = true;\n        //jshint -W086\n      case 'object':\n        //jshint +W086\n        predicateFn = createPredicateFn(expression, comparator, matchAgainstAnyProp);\n        break;\n      default:\n        return array;\n    }\n\n    return array.filter(predicateFn);\n  };\n}\n\n// Helper functions for `filterFilter`\nfunction createPredicateFn(expression, comparator, matchAgainstAnyProp) {\n  var shouldMatchPrimitives = isObject(expression) && ('$' in expression);\n  var predicateFn;\n\n  if (comparator === true) {\n    comparator = equals;\n  } else if (!isFunction(comparator)) {\n    comparator = function(actual, expected) {\n      if (isObject(actual) || isObject(expected)) {\n        // Prevent an object to be considered equal to a string like `'[object'`\n        return false;\n      }\n\n      actual = lowercase('' + actual);\n      expected = lowercase('' + expected);\n      return actual.indexOf(expected) !== -1;\n    };\n  }\n\n  predicateFn = function(item) {\n    if (shouldMatchPrimitives && !isObject(item)) {\n      return deepCompare(item, expression.$, comparator, false);\n    }\n    return deepCompare(item, expression, comparator, matchAgainstAnyProp);\n  };\n\n  return predicateFn;\n}\n\nfunction deepCompare(actual, expected, comparator, matchAgainstAnyProp, dontMatchWholeObject) {\n  var actualType = typeof actual;\n  var expectedType = typeof expected;\n\n  if ((expectedType === 'string') && (expected.charAt(0) === '!')) {\n    return !deepCompare(actual, expected.substring(1), comparator, matchAgainstAnyProp);\n  } else if (isArray(actual)) {\n    // In case `actual` is an array, consider it a match\n    // if ANY of it's items matches `expected`\n    return actual.some(function(item) {\n      return deepCompare(item, expected, comparator, matchAgainstAnyProp);\n    });\n  }\n\n  switch (actualType) {\n    case 'object':\n      var key;\n      if (matchAgainstAnyProp) {\n        for (key in actual) {\n          if ((key.charAt(0) !== '$') && deepCompare(actual[key], expected, comparator, true)) {\n            return true;\n          }\n        }\n        return dontMatchWholeObject ? false : deepCompare(actual, expected, comparator, false);\n      } else if (expectedType === 'object') {\n        for (key in expected) {\n          var expectedVal = expected[key];\n          if (isFunction(expectedVal)) {\n            continue;\n          }\n\n          var matchAnyProperty = key === '$';\n          var actualVal = matchAnyProperty ? actual : actual[key];\n          if (!deepCompare(actualVal, expectedVal, comparator, matchAnyProperty, matchAnyProperty)) {\n            return false;\n          }\n        }\n        return true;\n      } else {\n        return comparator(actual, expected);\n      }\n      break;\n    case 'function':\n      return false;\n    default:\n      return comparator(actual, expected);\n  }\n}\n\n/**\n * @ngdoc filter\n * @name currency\n * @kind function\n *\n * @description\n * Formats a number as a currency (ie $1,234.56). When no currency symbol is provided, default\n * symbol for current locale is used.\n *\n * @param {number} amount Input to filter.\n * @param {string=} symbol Currency symbol or identifier to be displayed.\n * @param {number=} fractionSize Number of decimal places to round the amount to, defaults to default max fraction size for current locale\n * @returns {string} Formatted number.\n *\n *\n * @example\n   <example module=\"currencyExample\">\n     <file name=\"index.html\">\n       <script>\n         angular.module('currencyExample', [])\n           .controller('ExampleController', ['$scope', function($scope) {\n             $scope.amount = 1234.56;\n           }]);\n       </script>\n       <div ng-controller=\"ExampleController\">\n         <input type=\"number\" ng-model=\"amount\"> <br>\n         default currency symbol ($): <span id=\"currency-default\">{{amount | currency}}</span><br>\n         custom currency identifier (USD$): <span id=\"currency-custom\">{{amount | currency:\"USD$\"}}</span>\n         no fractions (0): <span id=\"currency-no-fractions\">{{amount | currency:\"USD$\":0}}</span>\n       </div>\n     </file>\n     <file name=\"protractor.js\" type=\"protractor\">\n       it('should init with 1234.56', function() {\n         expect(element(by.id('currency-default')).getText()).toBe('$1,234.56');\n         expect(element(by.id('currency-custom')).getText()).toBe('USD$1,234.56');\n         expect(element(by.id('currency-no-fractions')).getText()).toBe('USD$1,235');\n       });\n       it('should update', function() {\n         if (browser.params.browser == 'safari') {\n           // Safari does not understand the minus key. See\n           // https://github.com/angular/protractor/issues/481\n           return;\n         }\n         element(by.model('amount')).clear();\n         element(by.model('amount')).sendKeys('-1234');\n         expect(element(by.id('currency-default')).getText()).toBe('($1,234.00)');\n         expect(element(by.id('currency-custom')).getText()).toBe('(USD$1,234.00)');\n         expect(element(by.id('currency-no-fractions')).getText()).toBe('(USD$1,234)');\n       });\n     </file>\n   </example>\n */\ncurrencyFilter.$inject = ['$locale'];\nfunction currencyFilter($locale) {\n  var formats = $locale.NUMBER_FORMATS;\n  return function(amount, currencySymbol, fractionSize) {\n    if (isUndefined(currencySymbol)) {\n      currencySymbol = formats.CURRENCY_SYM;\n    }\n\n    if (isUndefined(fractionSize)) {\n      fractionSize = formats.PATTERNS[1].maxFrac;\n    }\n\n    // if null or undefined pass it through\n    return (amount == null)\n        ? amount\n        : formatNumber(amount, formats.PATTERNS[1], formats.GROUP_SEP, formats.DECIMAL_SEP, fractionSize).\n            replace(/\\u00A4/g, currencySymbol);\n  };\n}\n\n/**\n * @ngdoc filter\n * @name number\n * @kind function\n *\n * @description\n * Formats a number as text.\n *\n * If the input is not a number an empty string is returned.\n *\n * @param {number|string} number Number to format.\n * @param {(number|string)=} fractionSize Number of decimal places to round the number to.\n * If this is not provided then the fraction size is computed from the current locale's number\n * formatting pattern. In the case of the default locale, it will be 3.\n * @returns {string} Number rounded to decimalPlaces and places a “,” after each third digit.\n *\n * @example\n   <example module=\"numberFilterExample\">\n     <file name=\"index.html\">\n       <script>\n         angular.module('numberFilterExample', [])\n           .controller('ExampleController', ['$scope', function($scope) {\n             $scope.val = 1234.56789;\n           }]);\n       </script>\n       <div ng-controller=\"ExampleController\">\n         Enter number: <input ng-model='val'><br>\n         Default formatting: <span id='number-default'>{{val | number}}</span><br>\n         No fractions: <span>{{val | number:0}}</span><br>\n         Negative number: <span>{{-val | number:4}}</span>\n       </div>\n     </file>\n     <file name=\"protractor.js\" type=\"protractor\">\n       it('should format numbers', function() {\n         expect(element(by.id('number-default')).getText()).toBe('1,234.568');\n         expect(element(by.binding('val | number:0')).getText()).toBe('1,235');\n         expect(element(by.binding('-val | number:4')).getText()).toBe('-1,234.5679');\n       });\n\n       it('should update', function() {\n         element(by.model('val')).clear();\n         element(by.model('val')).sendKeys('3374.333');\n         expect(element(by.id('number-default')).getText()).toBe('3,374.333');\n         expect(element(by.binding('val | number:0')).getText()).toBe('3,374');\n         expect(element(by.binding('-val | number:4')).getText()).toBe('-3,374.3330');\n      });\n     </file>\n   </example>\n */\n\n\nnumberFilter.$inject = ['$locale'];\nfunction numberFilter($locale) {\n  var formats = $locale.NUMBER_FORMATS;\n  return function(number, fractionSize) {\n\n    // if null or undefined pass it through\n    return (number == null)\n        ? number\n        : formatNumber(number, formats.PATTERNS[0], formats.GROUP_SEP, formats.DECIMAL_SEP,\n                       fractionSize);\n  };\n}\n\nvar DECIMAL_SEP = '.';\nfunction formatNumber(number, pattern, groupSep, decimalSep, fractionSize) {\n  if (!isFinite(number) || isObject(number)) return '';\n\n  var isNegative = number < 0;\n  number = Math.abs(number);\n  var numStr = number + '',\n      formatedText = '',\n      parts = [];\n\n  var hasExponent = false;\n  if (numStr.indexOf('e') !== -1) {\n    var match = numStr.match(/([\\d\\.]+)e(-?)(\\d+)/);\n    if (match && match[2] == '-' && match[3] > fractionSize + 1) {\n      number = 0;\n    } else {\n      formatedText = numStr;\n      hasExponent = true;\n    }\n  }\n\n  if (!hasExponent) {\n    var fractionLen = (numStr.split(DECIMAL_SEP)[1] || '').length;\n\n    // determine fractionSize if it is not specified\n    if (isUndefined(fractionSize)) {\n      fractionSize = Math.min(Math.max(pattern.minFrac, fractionLen), pattern.maxFrac);\n    }\n\n    // safely round numbers in JS without hitting imprecisions of floating-point arithmetics\n    // inspired by:\n    // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/round\n    number = +(Math.round(+(number.toString() + 'e' + fractionSize)).toString() + 'e' + -fractionSize);\n\n    var fraction = ('' + number).split(DECIMAL_SEP);\n    var whole = fraction[0];\n    fraction = fraction[1] || '';\n\n    var i, pos = 0,\n        lgroup = pattern.lgSize,\n        group = pattern.gSize;\n\n    if (whole.length >= (lgroup + group)) {\n      pos = whole.length - lgroup;\n      for (i = 0; i < pos; i++) {\n        if ((pos - i) % group === 0 && i !== 0) {\n          formatedText += groupSep;\n        }\n        formatedText += whole.charAt(i);\n      }\n    }\n\n    for (i = pos; i < whole.length; i++) {\n      if ((whole.length - i) % lgroup === 0 && i !== 0) {\n        formatedText += groupSep;\n      }\n      formatedText += whole.charAt(i);\n    }\n\n    // format fraction part.\n    while (fraction.length < fractionSize) {\n      fraction += '0';\n    }\n\n    if (fractionSize && fractionSize !== \"0\") formatedText += decimalSep + fraction.substr(0, fractionSize);\n  } else {\n    if (fractionSize > 0 && number < 1) {\n      formatedText = number.toFixed(fractionSize);\n      number = parseFloat(formatedText);\n    }\n  }\n\n  if (number === 0) {\n    isNegative = false;\n  }\n\n  parts.push(isNegative ? pattern.negPre : pattern.posPre,\n             formatedText,\n             isNegative ? pattern.negSuf : pattern.posSuf);\n  return parts.join('');\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\nfunction dateGetter(name, size, offset, trim) {\n  offset = offset || 0;\n  return function(date) {\n    var value = date['get' + name]();\n    if (offset > 0 || value > -offset)\n      value += offset;\n    if (value === 0 && offset == -12) value = 12;\n    return padNumber(value, size, trim);\n  };\n}\n\nfunction dateStrGetter(name, shortForm) {\n  return function(date, formats) {\n    var value = date['get' + name]();\n    var get = uppercase(shortForm ? ('SHORT' + name) : name);\n\n    return formats[get][value];\n  };\n}\n\nfunction timeZoneGetter(date) {\n  var zone = -1 * date.getTimezoneOffset();\n  var paddedZone = (zone >= 0) ? \"+\" : \"\";\n\n  paddedZone += padNumber(Math[zone > 0 ? 'floor' : 'ceil'](zone / 60), 2) +\n                padNumber(Math.abs(zone % 60), 2);\n\n  return paddedZone;\n}\n\nfunction getFirstThursdayOfYear(year) {\n    // 0 = index of January\n    var dayOfWeekOnFirst = (new Date(year, 0, 1)).getDay();\n    // 4 = index of Thursday (+1 to account for 1st = 5)\n    // 11 = index of *next* Thursday (+1 account for 1st = 12)\n    return new Date(year, 0, ((dayOfWeekOnFirst <= 4) ? 5 : 12) - dayOfWeekOnFirst);\n}\n\nfunction getThursdayThisWeek(datetime) {\n    return new Date(datetime.getFullYear(), datetime.getMonth(),\n      // 4 = index of Thursday\n      datetime.getDate() + (4 - datetime.getDay()));\n}\n\nfunction weekGetter(size) {\n   return function(date) {\n      var firstThurs = getFirstThursdayOfYear(date.getFullYear()),\n         thisThurs = getThursdayThisWeek(date);\n\n      var diff = +thisThurs - +firstThurs,\n         result = 1 + Math.round(diff / 6.048e8); // 6.048e8 ms per week\n\n      return padNumber(result, size);\n   };\n}\n\nfunction ampmGetter(date, formats) {\n  return date.getHours() < 12 ? formats.AMPMS[0] : formats.AMPMS[1];\n}\n\nvar DATE_FORMATS = {\n  yyyy: dateGetter('FullYear', 4),\n    yy: dateGetter('FullYear', 2, 0, true),\n     y: dateGetter('FullYear', 1),\n  MMMM: dateStrGetter('Month'),\n   MMM: dateStrGetter('Month', true),\n    MM: dateGetter('Month', 2, 1),\n     M: dateGetter('Month', 1, 1),\n    dd: dateGetter('Date', 2),\n     d: dateGetter('Date', 1),\n    HH: dateGetter('Hours', 2),\n     H: dateGetter('Hours', 1),\n    hh: dateGetter('Hours', 2, -12),\n     h: dateGetter('Hours', 1, -12),\n    mm: dateGetter('Minutes', 2),\n     m: dateGetter('Minutes', 1),\n    ss: dateGetter('Seconds', 2),\n     s: dateGetter('Seconds', 1),\n     // while ISO 8601 requires fractions to be prefixed with `.` or `,`\n     // we can be just safely rely on using `sss` since we currently don't support single or two digit fractions\n   sss: dateGetter('Milliseconds', 3),\n  EEEE: dateStrGetter('Day'),\n   EEE: dateStrGetter('Day', true),\n     a: ampmGetter,\n     Z: timeZoneGetter,\n    ww: weekGetter(2),\n     w: weekGetter(1)\n};\n\nvar DATE_FORMATS_SPLIT = /((?:[^yMdHhmsaZEw']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+|H+|h+|m+|s+|a|Z|w+))(.*)/,\n    NUMBER_STRING = /^\\-?\\d+$/;\n\n/**\n * @ngdoc filter\n * @name date\n * @kind function\n *\n * @description\n *   Formats `date` to a string based on the requested `format`.\n *\n *   `format` string can be composed of the following elements:\n *\n *   * `'yyyy'`: 4 digit representation of year (e.g. AD 1 => 0001, AD 2010 => 2010)\n *   * `'yy'`: 2 digit representation of year, padded (00-99). (e.g. AD 2001 => 01, AD 2010 => 10)\n *   * `'y'`: 1 digit representation of year, e.g. (AD 1 => 1, AD 199 => 199)\n *   * `'MMMM'`: Month in year (January-December)\n *   * `'MMM'`: Month in year (Jan-Dec)\n *   * `'MM'`: Month in year, padded (01-12)\n *   * `'M'`: Month in year (1-12)\n *   * `'dd'`: Day in month, padded (01-31)\n *   * `'d'`: Day in month (1-31)\n *   * `'EEEE'`: Day in Week,(Sunday-Saturday)\n *   * `'EEE'`: Day in Week, (Sun-Sat)\n *   * `'HH'`: Hour in day, padded (00-23)\n *   * `'H'`: Hour in day (0-23)\n *   * `'hh'`: Hour in AM/PM, padded (01-12)\n *   * `'h'`: Hour in AM/PM, (1-12)\n *   * `'mm'`: Minute in hour, padded (00-59)\n *   * `'m'`: Minute in hour (0-59)\n *   * `'ss'`: Second in minute, padded (00-59)\n *   * `'s'`: Second in minute (0-59)\n *   * `'sss'`: Millisecond in second, padded (000-999)\n *   * `'a'`: AM/PM marker\n *   * `'Z'`: 4 digit (+sign) representation of the timezone offset (-1200-+1200)\n *   * `'ww'`: Week of year, padded (00-53). Week 01 is the week with the first Thursday of the year\n *   * `'w'`: Week of year (0-53). Week 1 is the week with the first Thursday of the year\n *\n *   `format` string can also be one of the following predefined\n *   {@link guide/i18n localizable formats}:\n *\n *   * `'medium'`: equivalent to `'MMM d, y h:mm:ss a'` for en_US locale\n *     (e.g. Sep 3, 2010 12:05:08 PM)\n *   * `'short'`: equivalent to `'M/d/yy h:mm a'` for en_US  locale (e.g. 9/3/10 12:05 PM)\n *   * `'fullDate'`: equivalent to `'EEEE, MMMM d, y'` for en_US  locale\n *     (e.g. Friday, September 3, 2010)\n *   * `'longDate'`: equivalent to `'MMMM d, y'` for en_US  locale (e.g. September 3, 2010)\n *   * `'mediumDate'`: equivalent to `'MMM d, y'` for en_US  locale (e.g. Sep 3, 2010)\n *   * `'shortDate'`: equivalent to `'M/d/yy'` for en_US locale (e.g. 9/3/10)\n *   * `'mediumTime'`: equivalent to `'h:mm:ss a'` for en_US locale (e.g. 12:05:08 PM)\n *   * `'shortTime'`: equivalent to `'h:mm a'` for en_US locale (e.g. 12:05 PM)\n *\n *   `format` string can contain literal values. These need to be escaped by surrounding with single quotes (e.g.\n *   `\"h 'in the morning'\"`). In order to output a single quote, escape it - i.e., two single quotes in a sequence\n *   (e.g. `\"h 'o''clock'\"`).\n *\n * @param {(Date|number|string)} date Date to format either as Date object, milliseconds (string or\n *    number) or various ISO 8601 datetime string formats (e.g. yyyy-MM-ddTHH:mm:ss.sssZ and its\n *    shorter versions like yyyy-MM-ddTHH:mmZ, yyyy-MM-dd or yyyyMMddTHHmmssZ). If no timezone is\n *    specified in the string input, the time is considered to be in the local timezone.\n * @param {string=} format Formatting rules (see Description). If not specified,\n *    `mediumDate` is used.\n * @param {string=} timezone Timezone to be used for formatting. Right now, only `'UTC'` is supported.\n *    If not specified, the timezone of the browser will be used.\n * @returns {string} Formatted string or the input if input is not recognized as date/millis.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n       <span ng-non-bindable>{{1288323623006 | date:'medium'}}</span>:\n           <span>{{1288323623006 | date:'medium'}}</span><br>\n       <span ng-non-bindable>{{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}</span>:\n          <span>{{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}</span><br>\n       <span ng-non-bindable>{{1288323623006 | date:'MM/dd/yyyy @ h:mma'}}</span>:\n          <span>{{'1288323623006' | date:'MM/dd/yyyy @ h:mma'}}</span><br>\n       <span ng-non-bindable>{{1288323623006 | date:\"MM/dd/yyyy 'at' h:mma\"}}</span>:\n          <span>{{'1288323623006' | date:\"MM/dd/yyyy 'at' h:mma\"}}</span><br>\n     </file>\n     <file name=\"protractor.js\" type=\"protractor\">\n       it('should format date', function() {\n         expect(element(by.binding(\"1288323623006 | date:'medium'\")).getText()).\n            toMatch(/Oct 2\\d, 2010 \\d{1,2}:\\d{2}:\\d{2} (AM|PM)/);\n         expect(element(by.binding(\"1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'\")).getText()).\n            toMatch(/2010\\-10\\-2\\d \\d{2}:\\d{2}:\\d{2} (\\-|\\+)?\\d{4}/);\n         expect(element(by.binding(\"'1288323623006' | date:'MM/dd/yyyy @ h:mma'\")).getText()).\n            toMatch(/10\\/2\\d\\/2010 @ \\d{1,2}:\\d{2}(AM|PM)/);\n         expect(element(by.binding(\"'1288323623006' | date:\\\"MM/dd/yyyy 'at' h:mma\\\"\")).getText()).\n            toMatch(/10\\/2\\d\\/2010 at \\d{1,2}:\\d{2}(AM|PM)/);\n       });\n     </file>\n   </example>\n */\ndateFilter.$inject = ['$locale'];\nfunction dateFilter($locale) {\n\n\n  var R_ISO8601_STR = /^(\\d{4})-?(\\d\\d)-?(\\d\\d)(?:T(\\d\\d)(?::?(\\d\\d)(?::?(\\d\\d)(?:\\.(\\d+))?)?)?(Z|([+-])(\\d\\d):?(\\d\\d))?)?$/;\n                     // 1        2       3         4          5          6          7          8  9     10      11\n  function jsonStringToDate(string) {\n    var match;\n    if (match = string.match(R_ISO8601_STR)) {\n      var date = new Date(0),\n          tzHour = 0,\n          tzMin  = 0,\n          dateSetter = match[8] ? date.setUTCFullYear : date.setFullYear,\n          timeSetter = match[8] ? date.setUTCHours : date.setHours;\n\n      if (match[9]) {\n        tzHour = int(match[9] + match[10]);\n        tzMin = int(match[9] + match[11]);\n      }\n      dateSetter.call(date, int(match[1]), int(match[2]) - 1, int(match[3]));\n      var h = int(match[4] || 0) - tzHour;\n      var m = int(match[5] || 0) - tzMin;\n      var s = int(match[6] || 0);\n      var ms = Math.round(parseFloat('0.' + (match[7] || 0)) * 1000);\n      timeSetter.call(date, h, m, s, ms);\n      return date;\n    }\n    return string;\n  }\n\n\n  return function(date, format, timezone) {\n    var text = '',\n        parts = [],\n        fn, match;\n\n    format = format || 'mediumDate';\n    format = $locale.DATETIME_FORMATS[format] || format;\n    if (isString(date)) {\n      date = NUMBER_STRING.test(date) ? int(date) : jsonStringToDate(date);\n    }\n\n    if (isNumber(date)) {\n      date = new Date(date);\n    }\n\n    if (!isDate(date)) {\n      return date;\n    }\n\n    while (format) {\n      match = DATE_FORMATS_SPLIT.exec(format);\n      if (match) {\n        parts = concat(parts, match, 1);\n        format = parts.pop();\n      } else {\n        parts.push(format);\n        format = null;\n      }\n    }\n\n    if (timezone && timezone === 'UTC') {\n      date = new Date(date.getTime());\n      date.setMinutes(date.getMinutes() + date.getTimezoneOffset());\n    }\n    forEach(parts, function(value) {\n      fn = DATE_FORMATS[value];\n      text += fn ? fn(date, $locale.DATETIME_FORMATS)\n                 : value.replace(/(^'|'$)/g, '').replace(/''/g, \"'\");\n    });\n\n    return text;\n  };\n}\n\n\n/**\n * @ngdoc filter\n * @name json\n * @kind function\n *\n * @description\n *   Allows you to convert a JavaScript object into JSON string.\n *\n *   This filter is mostly useful for debugging. When using the double curly {{value}} notation\n *   the binding is automatically converted to JSON.\n *\n * @param {*} object Any JavaScript object (including arrays and primitive types) to filter.\n * @param {number=} spacing The number of spaces to use per indentation, defaults to 2.\n * @returns {string} JSON string.\n *\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n       <pre id=\"default-spacing\">{{ {'name':'value'} | json }}</pre>\n       <pre id=\"custom-spacing\">{{ {'name':'value'} | json:4 }}</pre>\n     </file>\n     <file name=\"protractor.js\" type=\"protractor\">\n       it('should jsonify filtered objects', function() {\n         expect(element(by.id('default-spacing')).getText()).toMatch(/\\{\\n  \"name\": ?\"value\"\\n}/);\n         expect(element(by.id('custom-spacing')).getText()).toMatch(/\\{\\n    \"name\": ?\"value\"\\n}/);\n       });\n     </file>\n   </example>\n *\n */\nfunction jsonFilter() {\n  return function(object, spacing) {\n    if (isUndefined(spacing)) {\n        spacing = 2;\n    }\n    return toJson(object, spacing);\n  };\n}\n\n\n/**\n * @ngdoc filter\n * @name lowercase\n * @kind function\n * @description\n * Converts string to lowercase.\n * @see angular.lowercase\n */\nvar lowercaseFilter = valueFn(lowercase);\n\n\n/**\n * @ngdoc filter\n * @name uppercase\n * @kind function\n * @description\n * Converts string to uppercase.\n * @see angular.uppercase\n */\nvar uppercaseFilter = valueFn(uppercase);\n\n/**\n * @ngdoc filter\n * @name limitTo\n * @kind function\n *\n * @description\n * Creates a new array or string containing only a specified number of elements. The elements\n * are taken from either the beginning or the end of the source array, string or number, as specified by\n * the value and sign (positive or negative) of `limit`. If a number is used as input, it is\n * converted to a string.\n *\n * @param {Array|string|number} input Source array, string or number to be limited.\n * @param {string|number} limit The length of the returned array or string. If the `limit` number\n *     is positive, `limit` number of items from the beginning of the source array/string are copied.\n *     If the number is negative, `limit` number  of items from the end of the source array/string\n *     are copied. The `limit` will be trimmed if it exceeds `array.length`\n * @returns {Array|string} A new sub-array or substring of length `limit` or less if input array\n *     had less than `limit` elements.\n *\n * @example\n   <example module=\"limitToExample\">\n     <file name=\"index.html\">\n       <script>\n         angular.module('limitToExample', [])\n           .controller('ExampleController', ['$scope', function($scope) {\n             $scope.numbers = [1,2,3,4,5,6,7,8,9];\n             $scope.letters = \"abcdefghi\";\n             $scope.longNumber = 2345432342;\n             $scope.numLimit = 3;\n             $scope.letterLimit = 3;\n             $scope.longNumberLimit = 3;\n           }]);\n       </script>\n       <div ng-controller=\"ExampleController\">\n         Limit {{numbers}} to: <input type=\"number\" step=\"1\" ng-model=\"numLimit\">\n         <p>Output numbers: {{ numbers | limitTo:numLimit }}</p>\n         Limit {{letters}} to: <input type=\"number\" step=\"1\" ng-model=\"letterLimit\">\n         <p>Output letters: {{ letters | limitTo:letterLimit }}</p>\n         Limit {{longNumber}} to: <input type=\"number\" step=\"1\" ng-model=\"longNumberLimit\">\n         <p>Output long number: {{ longNumber | limitTo:longNumberLimit }}</p>\n       </div>\n     </file>\n     <file name=\"protractor.js\" type=\"protractor\">\n       var numLimitInput = element(by.model('numLimit'));\n       var letterLimitInput = element(by.model('letterLimit'));\n       var longNumberLimitInput = element(by.model('longNumberLimit'));\n       var limitedNumbers = element(by.binding('numbers | limitTo:numLimit'));\n       var limitedLetters = element(by.binding('letters | limitTo:letterLimit'));\n       var limitedLongNumber = element(by.binding('longNumber | limitTo:longNumberLimit'));\n\n       it('should limit the number array to first three items', function() {\n         expect(numLimitInput.getAttribute('value')).toBe('3');\n         expect(letterLimitInput.getAttribute('value')).toBe('3');\n         expect(longNumberLimitInput.getAttribute('value')).toBe('3');\n         expect(limitedNumbers.getText()).toEqual('Output numbers: [1,2,3]');\n         expect(limitedLetters.getText()).toEqual('Output letters: abc');\n         expect(limitedLongNumber.getText()).toEqual('Output long number: 234');\n       });\n\n       // There is a bug in safari and protractor that doesn't like the minus key\n       // it('should update the output when -3 is entered', function() {\n       //   numLimitInput.clear();\n       //   numLimitInput.sendKeys('-3');\n       //   letterLimitInput.clear();\n       //   letterLimitInput.sendKeys('-3');\n       //   longNumberLimitInput.clear();\n       //   longNumberLimitInput.sendKeys('-3');\n       //   expect(limitedNumbers.getText()).toEqual('Output numbers: [7,8,9]');\n       //   expect(limitedLetters.getText()).toEqual('Output letters: ghi');\n       //   expect(limitedLongNumber.getText()).toEqual('Output long number: 342');\n       // });\n\n       it('should not exceed the maximum size of input array', function() {\n         numLimitInput.clear();\n         numLimitInput.sendKeys('100');\n         letterLimitInput.clear();\n         letterLimitInput.sendKeys('100');\n         longNumberLimitInput.clear();\n         longNumberLimitInput.sendKeys('100');\n         expect(limitedNumbers.getText()).toEqual('Output numbers: [1,2,3,4,5,6,7,8,9]');\n         expect(limitedLetters.getText()).toEqual('Output letters: abcdefghi');\n         expect(limitedLongNumber.getText()).toEqual('Output long number: 2345432342');\n       });\n     </file>\n   </example>\n*/\nfunction limitToFilter() {\n  return function(input, limit) {\n    if (isNumber(input)) input = input.toString();\n    if (!isArray(input) && !isString(input)) return input;\n\n    if (Math.abs(Number(limit)) === Infinity) {\n      limit = Number(limit);\n    } else {\n      limit = int(limit);\n    }\n\n    //NaN check on limit\n    if (limit) {\n      return limit > 0 ? input.slice(0, limit) : input.slice(limit);\n    } else {\n      return isString(input) ? \"\" : [];\n    }\n  };\n}\n\n/**\n * @ngdoc filter\n * @name orderBy\n * @kind function\n *\n * @description\n * Orders a specified `array` by the `expression` predicate. It is ordered alphabetically\n * for strings and numerically for numbers. Note: if you notice numbers are not being sorted\n * correctly, make sure they are actually being saved as numbers and not strings.\n *\n * @param {Array} array The array to sort.\n * @param {function(*)|string|Array.<(function(*)|string)>=} expression A predicate to be\n *    used by the comparator to determine the order of elements.\n *\n *    Can be one of:\n *\n *    - `function`: Getter function. The result of this function will be sorted using the\n *      `<`, `=`, `>` operator.\n *    - `string`: An Angular expression. The result of this expression is used to compare elements\n *      (for example `name` to sort by a property called `name` or `name.substr(0, 3)` to sort by\n *      3 first characters of a property called `name`). The result of a constant expression\n *      is interpreted as a property name to be used in comparisons (for example `\"special name\"`\n *      to sort object by the value of their `special name` property). An expression can be\n *      optionally prefixed with `+` or `-` to control ascending or descending sort order\n *      (for example, `+name` or `-name`). If no property is provided, (e.g. `'+'`) then the array\n *      element itself is used to compare where sorting.\n *    - `Array`: An array of function or string predicates. The first predicate in the array\n *      is used for sorting, but when two items are equivalent, the next predicate is used.\n *\n *    If the predicate is missing or empty then it defaults to `'+'`.\n *\n * @param {boolean=} reverse Reverse the order of the array.\n * @returns {Array} Sorted copy of the source array.\n *\n * @example\n   <example module=\"orderByExample\">\n     <file name=\"index.html\">\n       <script>\n         angular.module('orderByExample', [])\n           .controller('ExampleController', ['$scope', function($scope) {\n             $scope.friends =\n                 [{name:'John', phone:'555-1212', age:10},\n                  {name:'Mary', phone:'555-9876', age:19},\n                  {name:'Mike', phone:'555-4321', age:21},\n                  {name:'Adam', phone:'555-5678', age:35},\n                  {name:'Julie', phone:'555-8765', age:29}];\n             $scope.predicate = '-age';\n           }]);\n       </script>\n       <div ng-controller=\"ExampleController\">\n         <pre>Sorting predicate = {{predicate}}; reverse = {{reverse}}</pre>\n         <hr/>\n         [ <a href=\"\" ng-click=\"predicate=''\">unsorted</a> ]\n         <table class=\"friend\">\n           <tr>\n             <th><a href=\"\" ng-click=\"predicate = 'name'; reverse=false\">Name</a>\n                 (<a href=\"\" ng-click=\"predicate = '-name'; reverse=false\">^</a>)</th>\n             <th><a href=\"\" ng-click=\"predicate = 'phone'; reverse=!reverse\">Phone Number</a></th>\n             <th><a href=\"\" ng-click=\"predicate = 'age'; reverse=!reverse\">Age</a></th>\n           </tr>\n           <tr ng-repeat=\"friend in friends | orderBy:predicate:reverse\">\n             <td>{{friend.name}}</td>\n             <td>{{friend.phone}}</td>\n             <td>{{friend.age}}</td>\n           </tr>\n         </table>\n       </div>\n     </file>\n   </example>\n *\n * It's also possible to call the orderBy filter manually, by injecting `$filter`, retrieving the\n * filter routine with `$filter('orderBy')`, and calling the returned filter routine with the\n * desired parameters.\n *\n * Example:\n *\n * @example\n  <example module=\"orderByExample\">\n    <file name=\"index.html\">\n      <div ng-controller=\"ExampleController\">\n        <table class=\"friend\">\n          <tr>\n            <th><a href=\"\" ng-click=\"reverse=false;order('name', false)\">Name</a>\n              (<a href=\"\" ng-click=\"order('-name',false)\">^</a>)</th>\n            <th><a href=\"\" ng-click=\"reverse=!reverse;order('phone', reverse)\">Phone Number</a></th>\n            <th><a href=\"\" ng-click=\"reverse=!reverse;order('age',reverse)\">Age</a></th>\n          </tr>\n          <tr ng-repeat=\"friend in friends\">\n            <td>{{friend.name}}</td>\n            <td>{{friend.phone}}</td>\n            <td>{{friend.age}}</td>\n          </tr>\n        </table>\n      </div>\n    </file>\n\n    <file name=\"script.js\">\n      angular.module('orderByExample', [])\n        .controller('ExampleController', ['$scope', '$filter', function($scope, $filter) {\n          var orderBy = $filter('orderBy');\n          $scope.friends = [\n            { name: 'John',    phone: '555-1212',    age: 10 },\n            { name: 'Mary',    phone: '555-9876',    age: 19 },\n            { name: 'Mike',    phone: '555-4321',    age: 21 },\n            { name: 'Adam',    phone: '555-5678',    age: 35 },\n            { name: 'Julie',   phone: '555-8765',    age: 29 }\n          ];\n          $scope.order = function(predicate, reverse) {\n            $scope.friends = orderBy($scope.friends, predicate, reverse);\n          };\n          $scope.order('-age',false);\n        }]);\n    </file>\n</example>\n */\norderByFilter.$inject = ['$parse'];\nfunction orderByFilter($parse) {\n  return function(array, sortPredicate, reverseOrder) {\n    if (!(isArrayLike(array))) return array;\n    sortPredicate = isArray(sortPredicate) ? sortPredicate : [sortPredicate];\n    if (sortPredicate.length === 0) { sortPredicate = ['+']; }\n    sortPredicate = sortPredicate.map(function(predicate) {\n      var descending = false, get = predicate || identity;\n      if (isString(predicate)) {\n        if ((predicate.charAt(0) == '+' || predicate.charAt(0) == '-')) {\n          descending = predicate.charAt(0) == '-';\n          predicate = predicate.substring(1);\n        }\n        if (predicate === '') {\n          // Effectively no predicate was passed so we compare identity\n          return reverseComparator(compare, descending);\n        }\n        get = $parse(predicate);\n        if (get.constant) {\n          var key = get();\n          return reverseComparator(function(a, b) {\n            return compare(a[key], b[key]);\n          }, descending);\n        }\n      }\n      return reverseComparator(function(a, b) {\n        return compare(get(a),get(b));\n      }, descending);\n    });\n    return slice.call(array).sort(reverseComparator(comparator, reverseOrder));\n\n    function comparator(o1, o2) {\n      for (var i = 0; i < sortPredicate.length; i++) {\n        var comp = sortPredicate[i](o1, o2);\n        if (comp !== 0) return comp;\n      }\n      return 0;\n    }\n    function reverseComparator(comp, descending) {\n      return descending\n          ? function(a, b) {return comp(b,a);}\n          : comp;\n    }\n\n    function isPrimitive(value) {\n      switch (typeof value) {\n        case 'number': /* falls through */\n        case 'boolean': /* falls through */\n        case 'string':\n          return true;\n        default:\n          return false;\n      }\n    }\n\n    function objectToString(value) {\n      if (value === null) return 'null';\n      if (typeof value.valueOf === 'function') {\n        value = value.valueOf();\n        if (isPrimitive(value)) return value;\n      }\n      if (typeof value.toString === 'function') {\n        value = value.toString();\n        if (isPrimitive(value)) return value;\n      }\n      return '';\n    }\n\n    function compare(v1, v2) {\n      var t1 = typeof v1;\n      var t2 = typeof v2;\n      if (t1 === t2 && t1 === \"object\") {\n        v1 = objectToString(v1);\n        v2 = objectToString(v2);\n      }\n      if (t1 === t2) {\n        if (t1 === \"string\") {\n           v1 = v1.toLowerCase();\n           v2 = v2.toLowerCase();\n        }\n        if (v1 === v2) return 0;\n        return v1 < v2 ? -1 : 1;\n      } else {\n        return t1 < t2 ? -1 : 1;\n      }\n    }\n  };\n}\n\nfunction ngDirective(directive) {\n  if (isFunction(directive)) {\n    directive = {\n      link: directive\n    };\n  }\n  directive.restrict = directive.restrict || 'AC';\n  return valueFn(directive);\n}\n\n/**\n * @ngdoc directive\n * @name a\n * @restrict E\n *\n * @description\n * Modifies the default behavior of the html A tag so that the default action is prevented when\n * the href attribute is empty.\n *\n * This change permits the easy creation of action links with the `ngClick` directive\n * without changing the location or causing page reloads, e.g.:\n * `<a href=\"\" ng-click=\"list.addItem()\">Add Item</a>`\n */\nvar htmlAnchorDirective = valueFn({\n  restrict: 'E',\n  compile: function(element, attr) {\n    if (!attr.href && !attr.xlinkHref && !attr.name) {\n      return function(scope, element) {\n        // If the linked element is not an anchor tag anymore, do nothing\n        if (element[0].nodeName.toLowerCase() !== 'a') return;\n\n        // SVGAElement does not use the href attribute, but rather the 'xlinkHref' attribute.\n        var href = toString.call(element.prop('href')) === '[object SVGAnimatedString]' ?\n                   'xlink:href' : 'href';\n        element.on('click', function(event) {\n          // if we have no href url, then don't navigate anywhere.\n          if (!element.attr(href)) {\n            event.preventDefault();\n          }\n        });\n      };\n    }\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ngHref\n * @restrict A\n * @priority 99\n *\n * @description\n * Using Angular markup like `{{hash}}` in an href attribute will\n * make the link go to the wrong URL if the user clicks it before\n * Angular has a chance to replace the `{{hash}}` markup with its\n * value. Until Angular replaces the markup the link will be broken\n * and will most likely return a 404 error. The `ngHref` directive\n * solves this problem.\n *\n * The wrong way to write it:\n * ```html\n * <a href=\"http://www.gravatar.com/avatar/{{hash}}\">link1</a>\n * ```\n *\n * The correct way to write it:\n * ```html\n * <a ng-href=\"http://www.gravatar.com/avatar/{{hash}}\">link1</a>\n * ```\n *\n * @element A\n * @param {template} ngHref any string which can contain `{{}}` markup.\n *\n * @example\n * This example shows various combinations of `href`, `ng-href` and `ng-click` attributes\n * in links and their different behaviors:\n    <example>\n      <file name=\"index.html\">\n        <input ng-model=\"value\" /><br />\n        <a id=\"link-1\" href ng-click=\"value = 1\">link 1</a> (link, don't reload)<br />\n        <a id=\"link-2\" href=\"\" ng-click=\"value = 2\">link 2</a> (link, don't reload)<br />\n        <a id=\"link-3\" ng-href=\"/{{'123'}}\">link 3</a> (link, reload!)<br />\n        <a id=\"link-4\" href=\"\" name=\"xx\" ng-click=\"value = 4\">anchor</a> (link, don't reload)<br />\n        <a id=\"link-5\" name=\"xxx\" ng-click=\"value = 5\">anchor</a> (no link)<br />\n        <a id=\"link-6\" ng-href=\"{{value}}\">link</a> (link, change location)\n      </file>\n      <file name=\"protractor.js\" type=\"protractor\">\n        it('should execute ng-click but not reload when href without value', function() {\n          element(by.id('link-1')).click();\n          expect(element(by.model('value')).getAttribute('value')).toEqual('1');\n          expect(element(by.id('link-1')).getAttribute('href')).toBe('');\n        });\n\n        it('should execute ng-click but not reload when href empty string', function() {\n          element(by.id('link-2')).click();\n          expect(element(by.model('value')).getAttribute('value')).toEqual('2');\n          expect(element(by.id('link-2')).getAttribute('href')).toBe('');\n        });\n\n        it('should execute ng-click and change url when ng-href specified', function() {\n          expect(element(by.id('link-3')).getAttribute('href')).toMatch(/\\/123$/);\n\n          element(by.id('link-3')).click();\n\n          // At this point, we navigate away from an Angular page, so we need\n          // to use browser.driver to get the base webdriver.\n\n          browser.wait(function() {\n            return browser.driver.getCurrentUrl().then(function(url) {\n              return url.match(/\\/123$/);\n            });\n          }, 5000, 'page should navigate to /123');\n        });\n\n        xit('should execute ng-click but not reload when href empty string and name specified', function() {\n          element(by.id('link-4')).click();\n          expect(element(by.model('value')).getAttribute('value')).toEqual('4');\n          expect(element(by.id('link-4')).getAttribute('href')).toBe('');\n        });\n\n        it('should execute ng-click but not reload when no href but name specified', function() {\n          element(by.id('link-5')).click();\n          expect(element(by.model('value')).getAttribute('value')).toEqual('5');\n          expect(element(by.id('link-5')).getAttribute('href')).toBe(null);\n        });\n\n        it('should only change url when only ng-href', function() {\n          element(by.model('value')).clear();\n          element(by.model('value')).sendKeys('6');\n          expect(element(by.id('link-6')).getAttribute('href')).toMatch(/\\/6$/);\n\n          element(by.id('link-6')).click();\n\n          // At this point, we navigate away from an Angular page, so we need\n          // to use browser.driver to get the base webdriver.\n          browser.wait(function() {\n            return browser.driver.getCurrentUrl().then(function(url) {\n              return url.match(/\\/6$/);\n            });\n          }, 5000, 'page should navigate to /6');\n        });\n      </file>\n    </example>\n */\n\n/**\n * @ngdoc directive\n * @name ngSrc\n * @restrict A\n * @priority 99\n *\n * @description\n * Using Angular markup like `{{hash}}` in a `src` attribute doesn't\n * work right: The browser will fetch from the URL with the literal\n * text `{{hash}}` until Angular replaces the expression inside\n * `{{hash}}`. The `ngSrc` directive solves this problem.\n *\n * The buggy way to write it:\n * ```html\n * <img src=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * ```\n *\n * The correct way to write it:\n * ```html\n * <img ng-src=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * ```\n *\n * @element IMG\n * @param {template} ngSrc any string which can contain `{{}}` markup.\n */\n\n/**\n * @ngdoc directive\n * @name ngSrcset\n * @restrict A\n * @priority 99\n *\n * @description\n * Using Angular markup like `{{hash}}` in a `srcset` attribute doesn't\n * work right: The browser will fetch from the URL with the literal\n * text `{{hash}}` until Angular replaces the expression inside\n * `{{hash}}`. The `ngSrcset` directive solves this problem.\n *\n * The buggy way to write it:\n * ```html\n * <img srcset=\"http://www.gravatar.com/avatar/{{hash}} 2x\"/>\n * ```\n *\n * The correct way to write it:\n * ```html\n * <img ng-srcset=\"http://www.gravatar.com/avatar/{{hash}} 2x\"/>\n * ```\n *\n * @element IMG\n * @param {template} ngSrcset any string which can contain `{{}}` markup.\n */\n\n/**\n * @ngdoc directive\n * @name ngDisabled\n * @restrict A\n * @priority 100\n *\n * @description\n *\n * We shouldn't do this, because it will make the button enabled on Chrome/Firefox but not on IE8 and older IEs:\n * ```html\n * <div ng-init=\"scope = { isDisabled: false }\">\n *  <button disabled=\"{{scope.isDisabled}}\">Disabled</button>\n * </div>\n * ```\n *\n * The HTML specification does not require browsers to preserve the values of boolean attributes\n * such as disabled. (Their presence means true and their absence means false.)\n * If we put an Angular interpolation expression into such an attribute then the\n * binding information would be lost when the browser removes the attribute.\n * The `ngDisabled` directive solves this problem for the `disabled` attribute.\n * This complementary directive is not removed by the browser and so provides\n * a permanent reliable place to store the binding information.\n *\n * @example\n    <example>\n      <file name=\"index.html\">\n        Click me to toggle: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        <button ng-model=\"button\" ng-disabled=\"checked\">Button</button>\n      </file>\n      <file name=\"protractor.js\" type=\"protractor\">\n        it('should toggle button', function() {\n          expect(element(by.css('button')).getAttribute('disabled')).toBeFalsy();\n          element(by.model('checked')).click();\n          expect(element(by.css('button')).getAttribute('disabled')).toBeTruthy();\n        });\n      </file>\n    </example>\n *\n * @element INPUT\n * @param {expression} ngDisabled If the {@link guide/expression expression} is truthy,\n *     then special attribute \"disabled\" will be set on the element\n */\n\n\n/**\n * @ngdoc directive\n * @name ngChecked\n * @restrict A\n * @priority 100\n *\n * @description\n * The HTML specification does not require browsers to preserve the values of boolean attributes\n * such as checked. (Their presence means true and their absence means false.)\n * If we put an Angular interpolation expression into such an attribute then the\n * binding information would be lost when the browser removes the attribute.\n * The `ngChecked` directive solves this problem for the `checked` attribute.\n * This complementary directive is not removed by the browser and so provides\n * a permanent reliable place to store the binding information.\n * @example\n    <example>\n      <file name=\"index.html\">\n        Check me to check both: <input type=\"checkbox\" ng-model=\"master\"><br/>\n        <input id=\"checkSlave\" type=\"checkbox\" ng-checked=\"master\">\n      </file>\n      <file name=\"protractor.js\" type=\"protractor\">\n        it('should check both checkBoxes', function() {\n          expect(element(by.id('checkSlave')).getAttribute('checked')).toBeFalsy();\n          element(by.model('master')).click();\n          expect(element(by.id('checkSlave')).getAttribute('checked')).toBeTruthy();\n        });\n      </file>\n    </example>\n *\n * @element INPUT\n * @param {expression} ngChecked If the {@link guide/expression expression} is truthy,\n *     then special attribute \"checked\" will be set on the element\n */\n\n\n/**\n * @ngdoc directive\n * @name ngReadonly\n * @restrict A\n * @priority 100\n *\n * @description\n * The HTML specification does not require browsers to preserve the values of boolean attributes\n * such as readonly. (Their presence means true and their absence means false.)\n * If we put an Angular interpolation expression into such an attribute then the\n * binding information would be lost when the browser removes the attribute.\n * The `ngReadonly` directive solves this problem for the `readonly` attribute.\n * This complementary directive is not removed by the browser and so provides\n * a permanent reliable place to store the binding information.\n * @example\n    <example>\n      <file name=\"index.html\">\n        Check me to make text readonly: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        <input type=\"text\" ng-readonly=\"checked\" value=\"I'm Angular\"/>\n      </file>\n      <file name=\"protractor.js\" type=\"protractor\">\n        it('should toggle readonly attr', function() {\n          expect(element(by.css('[type=\"text\"]')).getAttribute('readonly')).toBeFalsy();\n          element(by.model('checked')).click();\n          expect(element(by.css('[type=\"text\"]')).getAttribute('readonly')).toBeTruthy();\n        });\n      </file>\n    </example>\n *\n * @element INPUT\n * @param {expression} ngReadonly If the {@link guide/expression expression} is truthy,\n *     then special attribute \"readonly\" will be set on the element\n */\n\n\n/**\n * @ngdoc directive\n * @name ngSelected\n * @restrict A\n * @priority 100\n *\n * @description\n * The HTML specification does not require browsers to preserve the values of boolean attributes\n * such as selected. (Their presence means true and their absence means false.)\n * If we put an Angular interpolation expression into such an attribute then the\n * binding information would be lost when the browser removes the attribute.\n * The `ngSelected` directive solves this problem for the `selected` attribute.\n * This complementary directive is not removed by the browser and so provides\n * a permanent reliable place to store the binding information.\n *\n * @example\n    <example>\n      <file name=\"index.html\">\n        Check me to select: <input type=\"checkbox\" ng-model=\"selected\"><br/>\n        <select>\n          <option>Hello!</option>\n          <option id=\"greet\" ng-selected=\"selected\">Greetings!</option>\n        </select>\n      </file>\n      <file name=\"protractor.js\" type=\"protractor\">\n        it('should select Greetings!', function() {\n          expect(element(by.id('greet')).getAttribute('selected')).toBeFalsy();\n          element(by.model('selected')).click();\n          expect(element(by.id('greet')).getAttribute('selected')).toBeTruthy();\n        });\n      </file>\n    </example>\n *\n * @element OPTION\n * @param {expression} ngSelected If the {@link guide/expression expression} is truthy,\n *     then special attribute \"selected\" will be set on the element\n */\n\n/**\n * @ngdoc directive\n * @name ngOpen\n * @restrict A\n * @priority 100\n *\n * @description\n * The HTML specification does not require browsers to preserve the values of boolean attributes\n * such as open. (Their presence means true and their absence means false.)\n * If we put an Angular interpolation expression into such an attribute then the\n * binding information would be lost when the browser removes the attribute.\n * The `ngOpen` directive solves this problem for the `open` attribute.\n * This complementary directive is not removed by the browser and so provides\n * a permanent reliable place to store the binding information.\n * @example\n     <example>\n       <file name=\"index.html\">\n         Check me check multiple: <input type=\"checkbox\" ng-model=\"open\"><br/>\n         <details id=\"details\" ng-open=\"open\">\n            <summary>Show/Hide me</summary>\n         </details>\n       </file>\n       <file name=\"protractor.js\" type=\"protractor\">\n         it('should toggle open', function() {\n           expect(element(by.id('details')).getAttribute('open')).toBeFalsy();\n           element(by.model('open')).click();\n           expect(element(by.id('details')).getAttribute('open')).toBeTruthy();\n         });\n       </file>\n     </example>\n *\n * @element DETAILS\n * @param {expression} ngOpen If the {@link guide/expression expression} is truthy,\n *     then special attribute \"open\" will be set on the element\n */\n\nvar ngAttributeAliasDirectives = {};\n\n\n// boolean attrs are evaluated\nforEach(BOOLEAN_ATTR, function(propName, attrName) {\n  // binding to multiple is not supported\n  if (propName == \"multiple\") return;\n\n  var normalized = directiveNormalize('ng-' + attrName);\n  ngAttributeAliasDirectives[normalized] = function() {\n    return {\n      restrict: 'A',\n      priority: 100,\n      link: function(scope, element, attr) {\n        scope.$watch(attr[normalized], function ngBooleanAttrWatchAction(value) {\n          attr.$set(attrName, !!value);\n        });\n      }\n    };\n  };\n});\n\n// aliased input attrs are evaluated\nforEach(ALIASED_ATTR, function(htmlAttr, ngAttr) {\n  ngAttributeAliasDirectives[ngAttr] = function() {\n    return {\n      priority: 100,\n      link: function(scope, element, attr) {\n        //special case ngPattern when a literal regular expression value\n        //is used as the expression (this way we don't have to watch anything).\n        if (ngAttr === \"ngPattern\" && attr.ngPattern.charAt(0) == \"/\") {\n          var match = attr.ngPattern.match(REGEX_STRING_REGEXP);\n          if (match) {\n            attr.$set(\"ngPattern\", new RegExp(match[1], match[2]));\n            return;\n          }\n        }\n\n        scope.$watch(attr[ngAttr], function ngAttrAliasWatchAction(value) {\n          attr.$set(ngAttr, value);\n        });\n      }\n    };\n  };\n});\n\n// ng-src, ng-srcset, ng-href are interpolated\nforEach(['src', 'srcset', 'href'], function(attrName) {\n  var normalized = directiveNormalize('ng-' + attrName);\n  ngAttributeAliasDirectives[normalized] = function() {\n    return {\n      priority: 99, // it needs to run after the attributes are interpolated\n      link: function(scope, element, attr) {\n        var propName = attrName,\n            name = attrName;\n\n        if (attrName === 'href' &&\n            toString.call(element.prop('href')) === '[object SVGAnimatedString]') {\n          name = 'xlinkHref';\n          attr.$attr[name] = 'xlink:href';\n          propName = null;\n        }\n\n        attr.$observe(normalized, function(value) {\n          if (!value) {\n            if (attrName === 'href') {\n              attr.$set(name, null);\n            }\n            return;\n          }\n\n          attr.$set(name, value);\n\n          // on IE, if \"ng:src\" directive declaration is used and \"src\" attribute doesn't exist\n          // then calling element.setAttribute('src', 'foo') doesn't do anything, so we need\n          // to set the property as well to achieve the desired effect.\n          // we use attr[attrName] value since $set can sanitize the url.\n          if (msie && propName) element.prop(propName, attr[name]);\n        });\n      }\n    };\n  };\n});\n\n/* global -nullFormCtrl, -SUBMITTED_CLASS, addSetValidityMethod: true\n */\nvar nullFormCtrl = {\n  $addControl: noop,\n  $$renameControl: nullFormRenameControl,\n  $removeControl: noop,\n  $setValidity: noop,\n  $setDirty: noop,\n  $setPristine: noop,\n  $setSubmitted: noop\n},\nSUBMITTED_CLASS = 'ng-submitted';\n\nfunction nullFormRenameControl(control, name) {\n  control.$name = name;\n}\n\n/**\n * @ngdoc type\n * @name form.FormController\n *\n * @property {boolean} $pristine True if user has not interacted with the form yet.\n * @property {boolean} $dirty True if user has already interacted with the form.\n * @property {boolean} $valid True if all of the containing forms and controls are valid.\n * @property {boolean} $invalid True if at least one containing control or form is invalid.\n * @property {boolean} $submitted True if user has submitted the form even if its invalid.\n *\n * @property {Object} $error Is an object hash, containing references to controls or\n *  forms with failing validators, where:\n *\n *  - keys are validation tokens (error names),\n *  - values are arrays of controls or forms that have a failing validator for given error name.\n *\n *  Built-in validation tokens:\n *\n *  - `email`\n *  - `max`\n *  - `maxlength`\n *  - `min`\n *  - `minlength`\n *  - `number`\n *  - `pattern`\n *  - `required`\n *  - `url`\n *  - `date`\n *  - `datetimelocal`\n *  - `time`\n *  - `week`\n *  - `month`\n *\n * @description\n * `FormController` keeps track of all its controls and nested forms as well as the state of them,\n * such as being valid/invalid or dirty/pristine.\n *\n * Each {@link ng.directive:form form} directive creates an instance\n * of `FormController`.\n *\n */\n//asks for $scope to fool the BC controller module\nFormController.$inject = ['$element', '$attrs', '$scope', '$animate', '$interpolate'];\nfunction FormController(element, attrs, $scope, $animate, $interpolate) {\n  var form = this,\n      controls = [];\n\n  var parentForm = form.$$parentForm = element.parent().controller('form') || nullFormCtrl;\n\n  // init state\n  form.$error = {};\n  form.$$success = {};\n  form.$pending = undefined;\n  form.$name = $interpolate(attrs.name || attrs.ngForm || '')($scope);\n  form.$dirty = false;\n  form.$pristine = true;\n  form.$valid = true;\n  form.$invalid = false;\n  form.$submitted = false;\n\n  parentForm.$addControl(form);\n\n  /**\n   * @ngdoc method\n   * @name form.FormController#$rollbackViewValue\n   *\n   * @description\n   * Rollback all form controls pending updates to the `$modelValue`.\n   *\n   * Updates may be pending by a debounced event or because the input is waiting for a some future\n   * event defined in `ng-model-options`. This method is typically needed by the reset button of\n   * a form that uses `ng-model-options` to pend updates.\n   */\n  form.$rollbackViewValue = function() {\n    forEach(controls, function(control) {\n      control.$rollbackViewValue();\n    });\n  };\n\n  /**\n   * @ngdoc method\n   * @name form.FormController#$commitViewValue\n   *\n   * @description\n   * Commit all form controls pending updates to the `$modelValue`.\n   *\n   * Updates may be pending by a debounced event or because the input is waiting for a some future\n   * event defined in `ng-model-options`. This method is rarely needed as `NgModelController`\n   * usually handles calling this in response to input events.\n   */\n  form.$commitViewValue = function() {\n    forEach(controls, function(control) {\n      control.$commitViewValue();\n    });\n  };\n\n  /**\n   * @ngdoc method\n   * @name form.FormController#$addControl\n   *\n   * @description\n   * Register a control with the form.\n   *\n   * Input elements using ngModelController do this automatically when they are linked.\n   */\n  form.$addControl = function(control) {\n    // Breaking change - before, inputs whose name was \"hasOwnProperty\" were quietly ignored\n    // and not added to the scope.  Now we throw an error.\n    assertNotHasOwnProperty(control.$name, 'input');\n    controls.push(control);\n\n    if (control.$name) {\n      form[control.$name] = control;\n    }\n  };\n\n  // Private API: rename a form control\n  form.$$renameControl = function(control, newName) {\n    var oldName = control.$name;\n\n    if (form[oldName] === control) {\n      delete form[oldName];\n    }\n    form[newName] = control;\n    control.$name = newName;\n  };\n\n  /**\n   * @ngdoc method\n   * @name form.FormController#$removeControl\n   *\n   * @description\n   * Deregister a control from the form.\n   *\n   * Input elements using ngModelController do this automatically when they are destroyed.\n   */\n  form.$removeControl = function(control) {\n    if (control.$name && form[control.$name] === control) {\n      delete form[control.$name];\n    }\n    forEach(form.$pending, function(value, name) {\n      form.$setValidity(name, null, control);\n    });\n    forEach(form.$error, function(value, name) {\n      form.$setValidity(name, null, control);\n    });\n    forEach(form.$$success, function(value, name) {\n      form.$setValidity(name, null, control);\n    });\n\n    arrayRemove(controls, control);\n  };\n\n\n  /**\n   * @ngdoc method\n   * @name form.FormController#$setValidity\n   *\n   * @description\n   * Sets the validity of a form control.\n   *\n   * This method will also propagate to parent forms.\n   */\n  addSetValidityMethod({\n    ctrl: this,\n    $element: element,\n    set: function(object, property, controller) {\n      var list = object[property];\n      if (!list) {\n        object[property] = [controller];\n      } else {\n        var index = list.indexOf(controller);\n        if (index === -1) {\n          list.push(controller);\n        }\n      }\n    },\n    unset: function(object, property, controller) {\n      var list = object[property];\n      if (!list) {\n        return;\n      }\n      arrayRemove(list, controller);\n      if (list.length === 0) {\n        delete object[property];\n      }\n    },\n    parentForm: parentForm,\n    $animate: $animate\n  });\n\n  /**\n   * @ngdoc method\n   * @name form.FormController#$setDirty\n   *\n   * @description\n   * Sets the form to a dirty state.\n   *\n   * This method can be called to add the 'ng-dirty' class and set the form to a dirty\n   * state (ng-dirty class). This method will also propagate to parent forms.\n   */\n  form.$setDirty = function() {\n    $animate.removeClass(element, PRISTINE_CLASS);\n    $animate.addClass(element, DIRTY_CLASS);\n    form.$dirty = true;\n    form.$pristine = false;\n    parentForm.$setDirty();\n  };\n\n  /**\n   * @ngdoc method\n   * @name form.FormController#$setPristine\n   *\n   * @description\n   * Sets the form to its pristine state.\n   *\n   * This method can be called to remove the 'ng-dirty' class and set the form to its pristine\n   * state (ng-pristine class). This method will also propagate to all the controls contained\n   * in this form.\n   *\n   * Setting a form back to a pristine state is often useful when we want to 'reuse' a form after\n   * saving or resetting it.\n   */\n  form.$setPristine = function() {\n    $animate.setClass(element, PRISTINE_CLASS, DIRTY_CLASS + ' ' + SUBMITTED_CLASS);\n    form.$dirty = false;\n    form.$pristine = true;\n    form.$submitted = false;\n    forEach(controls, function(control) {\n      control.$setPristine();\n    });\n  };\n\n  /**\n   * @ngdoc method\n   * @name form.FormController#$setUntouched\n   *\n   * @description\n   * Sets the form to its untouched state.\n   *\n   * This method can be called to remove the 'ng-touched' class and set the form controls to their\n   * untouched state (ng-untouched class).\n   *\n   * Setting a form controls back to their untouched state is often useful when setting the form\n   * back to its pristine state.\n   */\n  form.$setUntouched = function() {\n    forEach(controls, function(control) {\n      control.$setUntouched();\n    });\n  };\n\n  /**\n   * @ngdoc method\n   * @name form.FormController#$setSubmitted\n   *\n   * @description\n   * Sets the form to its submitted state.\n   */\n  form.$setSubmitted = function() {\n    $animate.addClass(element, SUBMITTED_CLASS);\n    form.$submitted = true;\n    parentForm.$setSubmitted();\n  };\n}\n\n/**\n * @ngdoc directive\n * @name ngForm\n * @restrict EAC\n *\n * @description\n * Nestable alias of {@link ng.directive:form `form`} directive. HTML\n * does not allow nesting of form elements. It is useful to nest forms, for example if the validity of a\n * sub-group of controls needs to be determined.\n *\n * Note: the purpose of `ngForm` is to group controls,\n * but not to be a replacement for the `<form>` tag with all of its capabilities\n * (e.g. posting to the server, ...).\n *\n * @param {string=} ngForm|name Name of the form. If specified, the form controller will be published into\n *                       related scope, under this name.\n *\n */\n\n /**\n * @ngdoc directive\n * @name form\n * @restrict E\n *\n * @description\n * Directive that instantiates\n * {@link form.FormController FormController}.\n *\n * If the `name` attribute is specified, the form controller is published onto the current scope under\n * this name.\n *\n * # Alias: {@link ng.directive:ngForm `ngForm`}\n *\n * In Angular forms can be nested. This means that the outer form is valid when all of the child\n * forms are valid as well. However, browsers do not allow nesting of `<form>` elements, so\n * Angular provides the {@link ng.directive:ngForm `ngForm`} directive which behaves identically to\n * `<form>` but can be nested.  This allows you to have nested forms, which is very useful when\n * using Angular validation directives in forms that are dynamically generated using the\n * {@link ng.directive:ngRepeat `ngRepeat`} directive. Since you cannot dynamically generate the `name`\n * attribute of input elements using interpolation, you have to wrap each set of repeated inputs in an\n * `ngForm` directive and nest these in an outer `form` element.\n *\n *\n * # CSS classes\n *  - `ng-valid` is set if the form is valid.\n *  - `ng-invalid` is set if the form is invalid.\n *  - `ng-pristine` is set if the form is pristine.\n *  - `ng-dirty` is set if the form is dirty.\n *  - `ng-submitted` is set if the form was submitted.\n *\n * Keep in mind that ngAnimate can detect each of these classes when added and removed.\n *\n *\n * # Submitting a form and preventing the default action\n *\n * Since the role of forms in client-side Angular applications is different than in classical\n * roundtrip apps, it is desirable for the browser not to translate the form submission into a full\n * page reload that sends the data to the server. Instead some javascript logic should be triggered\n * to handle the form submission in an application-specific way.\n *\n * For this reason, Angular prevents the default action (form submission to the server) unless the\n * `<form>` element has an `action` attribute specified.\n *\n * You can use one of the following two ways to specify what javascript method should be called when\n * a form is submitted:\n *\n * - {@link ng.directive:ngSubmit ngSubmit} directive on the form element\n * - {@link ng.directive:ngClick ngClick} directive on the first\n  *  button or input field of type submit (input[type=submit])\n *\n * To prevent double execution of the handler, use only one of the {@link ng.directive:ngSubmit ngSubmit}\n * or {@link ng.directive:ngClick ngClick} directives.\n * This is because of the following form submission rules in the HTML specification:\n *\n * - If a form has only one input field then hitting enter in this field triggers form submit\n * (`ngSubmit`)\n * - if a form has 2+ input fields and no buttons or input[type=submit] then hitting enter\n * doesn't trigger submit\n * - if a form has one or more input fields and one or more buttons or input[type=submit] then\n * hitting enter in any of the input fields will trigger the click handler on the *first* button or\n * input[type=submit] (`ngClick`) *and* a submit handler on the enclosing form (`ngSubmit`)\n *\n * Any pending `ngModelOptions` changes will take place immediately when an enclosing form is\n * submitted. Note that `ngClick` events will occur before the model is updated. Use `ngSubmit`\n * to have access to the updated model.\n *\n * ## Animation Hooks\n *\n * Animations in ngForm are triggered when any of the associated CSS classes are added and removed.\n * These classes are: `.ng-pristine`, `.ng-dirty`, `.ng-invalid` and `.ng-valid` as well as any\n * other validations that are performed within the form. Animations in ngForm are similar to how\n * they work in ngClass and animations can be hooked into using CSS transitions, keyframes as well\n * as JS animations.\n *\n * The following example shows a simple way to utilize CSS transitions to style a form element\n * that has been rendered as invalid after it has been validated:\n *\n * <pre>\n * //be sure to include ngAnimate as a module to hook into more\n * //advanced animations\n * .my-form {\n *   transition:0.5s linear all;\n *   background: white;\n * }\n * .my-form.ng-invalid {\n *   background: red;\n *   color:white;\n * }\n * </pre>\n *\n * @example\n    <example deps=\"angular-animate.js\" animations=\"true\" fixBase=\"true\" module=\"formExample\">\n      <file name=\"index.html\">\n       <script>\n         angular.module('formExample', [])\n           .controller('FormController', ['$scope', function($scope) {\n             $scope.userType = 'guest';\n           }]);\n       </script>\n       <style>\n        .my-form {\n          -webkit-transition:all linear 0.5s;\n          transition:all linear 0.5s;\n          background: transparent;\n        }\n        .my-form.ng-invalid {\n          background: red;\n        }\n       </style>\n       <form name=\"myForm\" ng-controller=\"FormController\" class=\"my-form\">\n         userType: <input name=\"input\" ng-model=\"userType\" required>\n         <span class=\"error\" ng-show=\"myForm.input.$error.required\">Required!</span><br>\n         <tt>userType = {{userType}}</tt><br>\n         <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br>\n         <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br>\n        </form>\n      </file>\n      <file name=\"protractor.js\" type=\"protractor\">\n        it('should initialize to model', function() {\n          var userType = element(by.binding('userType'));\n          var valid = element(by.binding('myForm.input.$valid'));\n\n          expect(userType.getText()).toContain('guest');\n          expect(valid.getText()).toContain('true');\n        });\n\n        it('should be invalid if empty', function() {\n          var userType = element(by.binding('userType'));\n          var valid = element(by.binding('myForm.input.$valid'));\n          var userInput = element(by.model('userType'));\n\n          userInput.clear();\n          userInput.sendKeys('');\n\n          expect(userType.getText()).toEqual('userType =');\n          expect(valid.getText()).toContain('false');\n        });\n      </file>\n    </example>\n *\n * @param {string=} name Name of the form. If specified, the form controller will be published into\n *                       related scope, under this name.\n */\nvar formDirectiveFactory = function(isNgForm) {\n  return ['$timeout', function($timeout) {\n    var formDirective = {\n      name: 'form',\n      restrict: isNgForm ? 'EAC' : 'E',\n      controller: FormController,\n      compile: function ngFormCompile(formElement) {\n        // Setup initial state of the control\n        formElement.addClass(PRISTINE_CLASS).addClass(VALID_CLASS);\n\n        return {\n          pre: function ngFormPreLink(scope, formElement, attr, controller) {\n            // if `action` attr is not present on the form, prevent the default action (submission)\n            if (!('action' in attr)) {\n              // we can't use jq events because if a form is destroyed during submission the default\n              // action is not prevented. see #1238\n              //\n              // IE 9 is not affected because it doesn't fire a submit event and try to do a full\n              // page reload if the form was destroyed by submission of the form via a click handler\n              // on a button in the form. Looks like an IE9 specific bug.\n              var handleFormSubmission = function(event) {\n                scope.$apply(function() {\n                  controller.$commitViewValue();\n                  controller.$setSubmitted();\n                });\n\n                event.preventDefault();\n              };\n\n              addEventListenerFn(formElement[0], 'submit', handleFormSubmission);\n\n              // unregister the preventDefault listener so that we don't not leak memory but in a\n              // way that will achieve the prevention of the default action.\n              formElement.on('$destroy', function() {\n                $timeout(function() {\n                  removeEventListenerFn(formElement[0], 'submit', handleFormSubmission);\n                }, 0, false);\n              });\n            }\n\n            var parentFormCtrl = controller.$$parentForm,\n                alias = controller.$name;\n\n            if (alias) {\n              setter(scope, null, alias, controller, alias);\n              attr.$observe(attr.name ? 'name' : 'ngForm', function(newValue) {\n                if (alias === newValue) return;\n                setter(scope, null, alias, undefined, alias);\n                alias = newValue;\n                setter(scope, null, alias, controller, alias);\n                parentFormCtrl.$$renameControl(controller, alias);\n              });\n            }\n            formElement.on('$destroy', function() {\n              parentFormCtrl.$removeControl(controller);\n              if (alias) {\n                setter(scope, null, alias, undefined, alias);\n              }\n              extend(controller, nullFormCtrl); //stop propagating child destruction handlers upwards\n            });\n          }\n        };\n      }\n    };\n\n    return formDirective;\n  }];\n};\n\nvar formDirective = formDirectiveFactory();\nvar ngFormDirective = formDirectiveFactory(true);\n\n/* global VALID_CLASS: false,\n  INVALID_CLASS: false,\n  PRISTINE_CLASS: false,\n  DIRTY_CLASS: false,\n  UNTOUCHED_CLASS: false,\n  TOUCHED_CLASS: false,\n  $ngModelMinErr: false,\n*/\n\n// Regex code is obtained from SO: https://stackoverflow.com/questions/3143070/javascript-regex-iso-datetime#answer-3143231\nvar ISO_DATE_REGEXP = /\\d{4}-[01]\\d-[0-3]\\dT[0-2]\\d:[0-5]\\d:[0-5]\\d\\.\\d+([+-][0-2]\\d:[0-5]\\d|Z)/;\nvar URL_REGEXP = /^(ftp|http|https):\\/\\/(\\w+:{0,1}\\w*@)?(\\S+)(:[0-9]+)?(\\/|\\/([\\w#!:.?+=&%@!\\-\\/]))?$/;\nvar EMAIL_REGEXP = /^[a-z0-9!#$%&'*+\\/=?^_`{|}~.-]+@[a-z0-9]([a-z0-9-]*[a-z0-9])?(\\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)*$/i;\nvar NUMBER_REGEXP = /^\\s*(\\-|\\+)?(\\d+|(\\d*(\\.\\d*)))\\s*$/;\nvar DATE_REGEXP = /^(\\d{4})-(\\d{2})-(\\d{2})$/;\nvar DATETIMELOCAL_REGEXP = /^(\\d{4})-(\\d\\d)-(\\d\\d)T(\\d\\d):(\\d\\d)(?::(\\d\\d)(\\.\\d{1,3})?)?$/;\nvar WEEK_REGEXP = /^(\\d{4})-W(\\d\\d)$/;\nvar MONTH_REGEXP = /^(\\d{4})-(\\d\\d)$/;\nvar TIME_REGEXP = /^(\\d\\d):(\\d\\d)(?::(\\d\\d)(\\.\\d{1,3})?)?$/;\n\nvar inputType = {\n\n  /**\n   * @ngdoc input\n   * @name input[text]\n   *\n   * @description\n   * Standard HTML text input with angular data binding, inherited by most of the `input` elements.\n   *\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Adds `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength. Setting the attribute to a negative or non-numeric value, allows view values of\n   *    any length.\n   * @param {string=} pattern Similar to `ngPattern` except that the attribute value is the actual string\n   *    that contains the regular expression body that will be converted to a regular expression\n   *    as in the ngPattern directive.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the ngModel value does not match\n   *    a RegExp found by evaluating the Angular expression given in the attribute value.\n   *    If the expression evaluates to a RegExp object then this is used directly.\n   *    If the expression is a string then it will be converted to a RegExp after wrapping it in `^` and `$`\n   *    characters. For instance, `\"abc\"` will be converted to `new RegExp('^abc$')`.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   * @param {boolean=} [ngTrim=true] If set to false Angular will not automatically trim the input.\n   *    This parameter is ignored for input[type=password] controls, which will never trim the\n   *    input.\n   *\n   * @example\n      <example name=\"text-input-directive\" module=\"textInputExample\">\n        <file name=\"index.html\">\n         <script>\n           angular.module('textInputExample', [])\n             .controller('ExampleController', ['$scope', function($scope) {\n               $scope.example = {\n                 text: 'guest',\n                 word: /^\\s*\\w*\\s*$/\n               };\n             }]);\n         </script>\n         <form name=\"myForm\" ng-controller=\"ExampleController\">\n           Single word: <input type=\"text\" name=\"input\" ng-model=\"example.text\"\n                               ng-pattern=\"example.word\" required ng-trim=\"false\">\n           <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.input.$error.pattern\">\n             Single word only!</span>\n\n           <tt>text = {{example.text}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n          </form>\n        </file>\n        <file name=\"protractor.js\" type=\"protractor\">\n          var text = element(by.binding('example.text'));\n          var valid = element(by.binding('myForm.input.$valid'));\n          var input = element(by.model('example.text'));\n\n          it('should initialize to model', function() {\n            expect(text.getText()).toContain('guest');\n            expect(valid.getText()).toContain('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input.clear();\n            input.sendKeys('');\n\n            expect(text.getText()).toEqual('text =');\n            expect(valid.getText()).toContain('false');\n          });\n\n          it('should be invalid if multi word', function() {\n            input.clear();\n            input.sendKeys('hello world');\n\n            expect(valid.getText()).toContain('false');\n          });\n        </file>\n      </example>\n   */\n  'text': textInputType,\n\n    /**\n     * @ngdoc input\n     * @name input[date]\n     *\n     * @description\n     * Input with date validation and transformation. In browsers that do not yet support\n     * the HTML5 date input, a text element will be used. In that case, text must be entered in a valid ISO-8601\n     * date format (yyyy-MM-dd), for example: `2009-01-06`. Since many\n     * modern browsers do not yet support this input type, it is important to provide cues to users on the\n     * expected input format via a placeholder or label.\n     *\n     * The model must always be a Date object, otherwise Angular will throw an error.\n     * Invalid `Date` objects (dates whose `getTime()` is `NaN`) will be rendered as an empty string.\n     *\n     * The timezone to be used to read/write the `Date` instance in the model can be defined using\n     * {@link ng.directive:ngModelOptions ngModelOptions}. By default, this is the timezone of the browser.\n     *\n     * @param {string} ngModel Assignable angular expression to data-bind to.\n     * @param {string=} name Property name of the form under which the control is published.\n     * @param {string=} min Sets the `min` validation error key if the value entered is less than `min`. This must be a\n     * valid ISO date string (yyyy-MM-dd).\n     * @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`. This must be\n     * a valid ISO date string (yyyy-MM-dd).\n     * @param {string=} required Sets `required` validation error key if the value is not entered.\n     * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n     *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n     *    `required` when you want to data-bind to the `required` attribute.\n     * @param {string=} ngChange Angular expression to be executed when input changes due to user\n     *    interaction with the input element.\n     *\n     * @example\n     <example name=\"date-input-directive\" module=\"dateInputExample\">\n     <file name=\"index.html\">\n       <script>\n          angular.module('dateInputExample', [])\n            .controller('DateController', ['$scope', function($scope) {\n              $scope.example = {\n                value: new Date(2013, 9, 22)\n              };\n            }]);\n       </script>\n       <form name=\"myForm\" ng-controller=\"DateController as dateCtrl\">\n          Pick a date in 2013:\n          <input type=\"date\" id=\"exampleInput\" name=\"input\" ng-model=\"example.value\"\n              placeholder=\"yyyy-MM-dd\" min=\"2013-01-01\" max=\"2013-12-31\" required />\n          <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n              Required!</span>\n          <span class=\"error\" ng-show=\"myForm.input.$error.date\">\n              Not a valid date!</span>\n           <tt>value = {{example.value | date: \"yyyy-MM-dd\"}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n       </form>\n     </file>\n     <file name=\"protractor.js\" type=\"protractor\">\n        var value = element(by.binding('example.value | date: \"yyyy-MM-dd\"'));\n        var valid = element(by.binding('myForm.input.$valid'));\n        var input = element(by.model('example.value'));\n\n        // currently protractor/webdriver does not support\n        // sending keys to all known HTML5 input controls\n        // for various browsers (see https://github.com/angular/protractor/issues/562).\n        function setInput(val) {\n          // set the value of the element and force validation.\n          var scr = \"var ipt = document.getElementById('exampleInput'); \" +\n          \"ipt.value = '\" + val + \"';\" +\n          \"angular.element(ipt).scope().$apply(function(s) { s.myForm[ipt.name].$setViewValue('\" + val + \"'); });\";\n          browser.executeScript(scr);\n        }\n\n        it('should initialize to model', function() {\n          expect(value.getText()).toContain('2013-10-22');\n          expect(valid.getText()).toContain('myForm.input.$valid = true');\n        });\n\n        it('should be invalid if empty', function() {\n          setInput('');\n          expect(value.getText()).toEqual('value =');\n          expect(valid.getText()).toContain('myForm.input.$valid = false');\n        });\n\n        it('should be invalid if over max', function() {\n          setInput('2015-01-01');\n          expect(value.getText()).toContain('');\n          expect(valid.getText()).toContain('myForm.input.$valid = false');\n        });\n     </file>\n     </example>\n     */\n  'date': createDateInputType('date', DATE_REGEXP,\n         createDateParser(DATE_REGEXP, ['yyyy', 'MM', 'dd']),\n         'yyyy-MM-dd'),\n\n   /**\n    * @ngdoc input\n    * @name input[datetime-local]\n    *\n    * @description\n    * Input with datetime validation and transformation. In browsers that do not yet support\n    * the HTML5 date input, a text element will be used. In that case, the text must be entered in a valid ISO-8601\n    * local datetime format (yyyy-MM-ddTHH:mm:ss), for example: `2010-12-28T14:57:00`.\n    *\n    * The model must always be a Date object, otherwise Angular will throw an error.\n    * Invalid `Date` objects (dates whose `getTime()` is `NaN`) will be rendered as an empty string.\n    *\n    * The timezone to be used to read/write the `Date` instance in the model can be defined using\n    * {@link ng.directive:ngModelOptions ngModelOptions}. By default, this is the timezone of the browser.\n    *\n    * @param {string} ngModel Assignable angular expression to data-bind to.\n    * @param {string=} name Property name of the form under which the control is published.\n    * @param {string=} min Sets the `min` validation error key if the value entered is less than `min`. This must be a\n    * valid ISO datetime format (yyyy-MM-ddTHH:mm:ss).\n    * @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`. This must be\n    * a valid ISO datetime format (yyyy-MM-ddTHH:mm:ss).\n    * @param {string=} required Sets `required` validation error key if the value is not entered.\n    * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n    *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n    *    `required` when you want to data-bind to the `required` attribute.\n    * @param {string=} ngChange Angular expression to be executed when input changes due to user\n    *    interaction with the input element.\n    *\n    * @example\n    <example name=\"datetimelocal-input-directive\" module=\"dateExample\">\n    <file name=\"index.html\">\n      <script>\n        angular.module('dateExample', [])\n          .controller('DateController', ['$scope', function($scope) {\n            $scope.example = {\n              value: new Date(2010, 11, 28, 14, 57)\n            };\n          }]);\n      </script>\n      <form name=\"myForm\" ng-controller=\"DateController as dateCtrl\">\n        Pick a date between in 2013:\n        <input type=\"datetime-local\" id=\"exampleInput\" name=\"input\" ng-model=\"example.value\"\n            placeholder=\"yyyy-MM-ddTHH:mm:ss\" min=\"2001-01-01T00:00:00\" max=\"2013-12-31T00:00:00\" required />\n        <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n            Required!</span>\n        <span class=\"error\" ng-show=\"myForm.input.$error.datetimelocal\">\n            Not a valid date!</span>\n        <tt>value = {{example.value | date: \"yyyy-MM-ddTHH:mm:ss\"}}</tt><br/>\n        <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n        <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n        <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n        <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n      </form>\n    </file>\n    <file name=\"protractor.js\" type=\"protractor\">\n      var value = element(by.binding('example.value | date: \"yyyy-MM-ddTHH:mm:ss\"'));\n      var valid = element(by.binding('myForm.input.$valid'));\n      var input = element(by.model('example.value'));\n\n      // currently protractor/webdriver does not support\n      // sending keys to all known HTML5 input controls\n      // for various browsers (https://github.com/angular/protractor/issues/562).\n      function setInput(val) {\n        // set the value of the element and force validation.\n        var scr = \"var ipt = document.getElementById('exampleInput'); \" +\n        \"ipt.value = '\" + val + \"';\" +\n        \"angular.element(ipt).scope().$apply(function(s) { s.myForm[ipt.name].$setViewValue('\" + val + \"'); });\";\n        browser.executeScript(scr);\n      }\n\n      it('should initialize to model', function() {\n        expect(value.getText()).toContain('2010-12-28T14:57:00');\n        expect(valid.getText()).toContain('myForm.input.$valid = true');\n      });\n\n      it('should be invalid if empty', function() {\n        setInput('');\n        expect(value.getText()).toEqual('value =');\n        expect(valid.getText()).toContain('myForm.input.$valid = false');\n      });\n\n      it('should be invalid if over max', function() {\n        setInput('2015-01-01T23:59:00');\n        expect(value.getText()).toContain('');\n        expect(valid.getText()).toContain('myForm.input.$valid = false');\n      });\n    </file>\n    </example>\n    */\n  'datetime-local': createDateInputType('datetimelocal', DATETIMELOCAL_REGEXP,\n      createDateParser(DATETIMELOCAL_REGEXP, ['yyyy', 'MM', 'dd', 'HH', 'mm', 'ss', 'sss']),\n      'yyyy-MM-ddTHH:mm:ss.sss'),\n\n  /**\n   * @ngdoc input\n   * @name input[time]\n   *\n   * @description\n   * Input with time validation and transformation. In browsers that do not yet support\n   * the HTML5 date input, a text element will be used. In that case, the text must be entered in a valid ISO-8601\n   * local time format (HH:mm:ss), for example: `14:57:00`. Model must be a Date object. This binding will always output a\n   * Date object to the model of January 1, 1970, or local date `new Date(1970, 0, 1, HH, mm, ss)`.\n   *\n   * The model must always be a Date object, otherwise Angular will throw an error.\n   * Invalid `Date` objects (dates whose `getTime()` is `NaN`) will be rendered as an empty string.\n   *\n   * The timezone to be used to read/write the `Date` instance in the model can be defined using\n   * {@link ng.directive:ngModelOptions ngModelOptions}. By default, this is the timezone of the browser.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} min Sets the `min` validation error key if the value entered is less than `min`. This must be a\n   * valid ISO time format (HH:mm:ss).\n   * @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`. This must be a\n   * valid ISO time format (HH:mm:ss).\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n   <example name=\"time-input-directive\" module=\"timeExample\">\n   <file name=\"index.html\">\n     <script>\n      angular.module('timeExample', [])\n        .controller('DateController', ['$scope', function($scope) {\n          $scope.example = {\n            value: new Date(1970, 0, 1, 14, 57, 0)\n          };\n        }]);\n     </script>\n     <form name=\"myForm\" ng-controller=\"DateController as dateCtrl\">\n        Pick a between 8am and 5pm:\n        <input type=\"time\" id=\"exampleInput\" name=\"input\" ng-model=\"example.value\"\n            placeholder=\"HH:mm:ss\" min=\"08:00:00\" max=\"17:00:00\" required />\n        <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n            Required!</span>\n        <span class=\"error\" ng-show=\"myForm.input.$error.time\">\n            Not a valid date!</span>\n        <tt>value = {{example.value | date: \"HH:mm:ss\"}}</tt><br/>\n        <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n        <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n        <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n        <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n     </form>\n   </file>\n   <file name=\"protractor.js\" type=\"protractor\">\n      var value = element(by.binding('example.value | date: \"HH:mm:ss\"'));\n      var valid = element(by.binding('myForm.input.$valid'));\n      var input = element(by.model('example.value'));\n\n      // currently protractor/webdriver does not support\n      // sending keys to all known HTML5 input controls\n      // for various browsers (https://github.com/angular/protractor/issues/562).\n      function setInput(val) {\n        // set the value of the element and force validation.\n        var scr = \"var ipt = document.getElementById('exampleInput'); \" +\n        \"ipt.value = '\" + val + \"';\" +\n        \"angular.element(ipt).scope().$apply(function(s) { s.myForm[ipt.name].$setViewValue('\" + val + \"'); });\";\n        browser.executeScript(scr);\n      }\n\n      it('should initialize to model', function() {\n        expect(value.getText()).toContain('14:57:00');\n        expect(valid.getText()).toContain('myForm.input.$valid = true');\n      });\n\n      it('should be invalid if empty', function() {\n        setInput('');\n        expect(value.getText()).toEqual('value =');\n        expect(valid.getText()).toContain('myForm.input.$valid = false');\n      });\n\n      it('should be invalid if over max', function() {\n        setInput('23:59:00');\n        expect(value.getText()).toContain('');\n        expect(valid.getText()).toContain('myForm.input.$valid = false');\n      });\n   </file>\n   </example>\n   */\n  'time': createDateInputType('time', TIME_REGEXP,\n      createDateParser(TIME_REGEXP, ['HH', 'mm', 'ss', 'sss']),\n     'HH:mm:ss.sss'),\n\n   /**\n    * @ngdoc input\n    * @name input[week]\n    *\n    * @description\n    * Input with week-of-the-year validation and transformation to Date. In browsers that do not yet support\n    * the HTML5 week input, a text element will be used. In that case, the text must be entered in a valid ISO-8601\n    * week format (yyyy-W##), for example: `2013-W02`.\n    *\n    * The model must always be a Date object, otherwise Angular will throw an error.\n    * Invalid `Date` objects (dates whose `getTime()` is `NaN`) will be rendered as an empty string.\n    *\n    * The timezone to be used to read/write the `Date` instance in the model can be defined using\n    * {@link ng.directive:ngModelOptions ngModelOptions}. By default, this is the timezone of the browser.\n    *\n    * @param {string} ngModel Assignable angular expression to data-bind to.\n    * @param {string=} name Property name of the form under which the control is published.\n    * @param {string=} min Sets the `min` validation error key if the value entered is less than `min`. This must be a\n    * valid ISO week format (yyyy-W##).\n    * @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`. This must be\n    * a valid ISO week format (yyyy-W##).\n    * @param {string=} required Sets `required` validation error key if the value is not entered.\n    * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n    *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n    *    `required` when you want to data-bind to the `required` attribute.\n    * @param {string=} ngChange Angular expression to be executed when input changes due to user\n    *    interaction with the input element.\n    *\n    * @example\n    <example name=\"week-input-directive\" module=\"weekExample\">\n    <file name=\"index.html\">\n      <script>\n      angular.module('weekExample', [])\n        .controller('DateController', ['$scope', function($scope) {\n          $scope.example = {\n            value: new Date(2013, 0, 3)\n          };\n        }]);\n      </script>\n      <form name=\"myForm\" ng-controller=\"DateController as dateCtrl\">\n        Pick a date between in 2013:\n        <input id=\"exampleInput\" type=\"week\" name=\"input\" ng-model=\"example.value\"\n            placeholder=\"YYYY-W##\" min=\"2012-W32\" max=\"2013-W52\" required />\n        <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n            Required!</span>\n        <span class=\"error\" ng-show=\"myForm.input.$error.week\">\n            Not a valid date!</span>\n        <tt>value = {{example.value | date: \"yyyy-Www\"}}</tt><br/>\n        <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n        <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n        <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n        <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n      </form>\n    </file>\n    <file name=\"protractor.js\" type=\"protractor\">\n      var value = element(by.binding('example.value | date: \"yyyy-Www\"'));\n      var valid = element(by.binding('myForm.input.$valid'));\n      var input = element(by.model('example.value'));\n\n      // currently protractor/webdriver does not support\n      // sending keys to all known HTML5 input controls\n      // for various browsers (https://github.com/angular/protractor/issues/562).\n      function setInput(val) {\n        // set the value of the element and force validation.\n        var scr = \"var ipt = document.getElementById('exampleInput'); \" +\n        \"ipt.value = '\" + val + \"';\" +\n        \"angular.element(ipt).scope().$apply(function(s) { s.myForm[ipt.name].$setViewValue('\" + val + \"'); });\";\n        browser.executeScript(scr);\n      }\n\n      it('should initialize to model', function() {\n        expect(value.getText()).toContain('2013-W01');\n        expect(valid.getText()).toContain('myForm.input.$valid = true');\n      });\n\n      it('should be invalid if empty', function() {\n        setInput('');\n        expect(value.getText()).toEqual('value =');\n        expect(valid.getText()).toContain('myForm.input.$valid = false');\n      });\n\n      it('should be invalid if over max', function() {\n        setInput('2015-W01');\n        expect(value.getText()).toContain('');\n        expect(valid.getText()).toContain('myForm.input.$valid = false');\n      });\n    </file>\n    </example>\n    */\n  'week': createDateInputType('week', WEEK_REGEXP, weekParser, 'yyyy-Www'),\n\n  /**\n   * @ngdoc input\n   * @name input[month]\n   *\n   * @description\n   * Input with month validation and transformation. In browsers that do not yet support\n   * the HTML5 month input, a text element will be used. In that case, the text must be entered in a valid ISO-8601\n   * month format (yyyy-MM), for example: `2009-01`.\n   *\n   * The model must always be a Date object, otherwise Angular will throw an error.\n   * Invalid `Date` objects (dates whose `getTime()` is `NaN`) will be rendered as an empty string.\n   * If the model is not set to the first of the month, the next view to model update will set it\n   * to the first of the month.\n   *\n   * The timezone to be used to read/write the `Date` instance in the model can be defined using\n   * {@link ng.directive:ngModelOptions ngModelOptions}. By default, this is the timezone of the browser.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} min Sets the `min` validation error key if the value entered is less than `min`. This must be\n   * a valid ISO month format (yyyy-MM).\n   * @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`. This must\n   * be a valid ISO month format (yyyy-MM).\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n   <example name=\"month-input-directive\" module=\"monthExample\">\n   <file name=\"index.html\">\n     <script>\n      angular.module('monthExample', [])\n        .controller('DateController', ['$scope', function($scope) {\n          $scope.example = {\n            value: new Date(2013, 9, 1)\n          };\n        }]);\n     </script>\n     <form name=\"myForm\" ng-controller=\"DateController as dateCtrl\">\n       Pick a month in 2013:\n       <input id=\"exampleInput\" type=\"month\" name=\"input\" ng-model=\"example.value\"\n          placeholder=\"yyyy-MM\" min=\"2013-01\" max=\"2013-12\" required />\n       <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n          Required!</span>\n       <span class=\"error\" ng-show=\"myForm.input.$error.month\">\n          Not a valid month!</span>\n       <tt>value = {{example.value | date: \"yyyy-MM\"}}</tt><br/>\n       <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n       <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n       <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n       <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n     </form>\n   </file>\n   <file name=\"protractor.js\" type=\"protractor\">\n      var value = element(by.binding('example.value | date: \"yyyy-MM\"'));\n      var valid = element(by.binding('myForm.input.$valid'));\n      var input = element(by.model('example.value'));\n\n      // currently protractor/webdriver does not support\n      // sending keys to all known HTML5 input controls\n      // for various browsers (https://github.com/angular/protractor/issues/562).\n      function setInput(val) {\n        // set the value of the element and force validation.\n        var scr = \"var ipt = document.getElementById('exampleInput'); \" +\n        \"ipt.value = '\" + val + \"';\" +\n        \"angular.element(ipt).scope().$apply(function(s) { s.myForm[ipt.name].$setViewValue('\" + val + \"'); });\";\n        browser.executeScript(scr);\n      }\n\n      it('should initialize to model', function() {\n        expect(value.getText()).toContain('2013-10');\n        expect(valid.getText()).toContain('myForm.input.$valid = true');\n      });\n\n      it('should be invalid if empty', function() {\n        setInput('');\n        expect(value.getText()).toEqual('value =');\n        expect(valid.getText()).toContain('myForm.input.$valid = false');\n      });\n\n      it('should be invalid if over max', function() {\n        setInput('2015-01');\n        expect(value.getText()).toContain('');\n        expect(valid.getText()).toContain('myForm.input.$valid = false');\n      });\n   </file>\n   </example>\n   */\n  'month': createDateInputType('month', MONTH_REGEXP,\n     createDateParser(MONTH_REGEXP, ['yyyy', 'MM']),\n     'yyyy-MM'),\n\n  /**\n   * @ngdoc input\n   * @name input[number]\n   *\n   * @description\n   * Text input with number validation and transformation. Sets the `number` validation\n   * error if not a valid number.\n   *\n   * The model must always be a number, otherwise Angular will throw an error.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} min Sets the `min` validation error key if the value entered is less than `min`.\n   * @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength. Setting the attribute to a negative or non-numeric value, allows view values of\n   *    any length.\n   * @param {string=} pattern Similar to `ngPattern` except that the attribute value is the actual string\n   *    that contains the regular expression body that will be converted to a regular expression\n   *    as in the ngPattern directive.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the ngModel value does not match\n   *    a RegExp found by evaluating the Angular expression given in the attribute value.\n   *    If the expression evaluates to a RegExp object then this is used directly.\n   *    If the expression is a string then it will be converted to a RegExp after wrapping it in `^` and `$`\n   *    characters. For instance, `\"abc\"` will be converted to `new RegExp('^abc$')`.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <example name=\"number-input-directive\" module=\"numberExample\">\n        <file name=\"index.html\">\n         <script>\n           angular.module('numberExample', [])\n             .controller('ExampleController', ['$scope', function($scope) {\n               $scope.example = {\n                 value: 12\n               };\n             }]);\n         </script>\n         <form name=\"myForm\" ng-controller=\"ExampleController\">\n           Number: <input type=\"number\" name=\"input\" ng-model=\"example.value\"\n                          min=\"0\" max=\"99\" required>\n           <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.input.$error.number\">\n             Not valid number!</span>\n           <tt>value = {{example.value}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n          </form>\n        </file>\n        <file name=\"protractor.js\" type=\"protractor\">\n          var value = element(by.binding('example.value'));\n          var valid = element(by.binding('myForm.input.$valid'));\n          var input = element(by.model('example.value'));\n\n          it('should initialize to model', function() {\n            expect(value.getText()).toContain('12');\n            expect(valid.getText()).toContain('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input.clear();\n            input.sendKeys('');\n            expect(value.getText()).toEqual('value =');\n            expect(valid.getText()).toContain('false');\n          });\n\n          it('should be invalid if over max', function() {\n            input.clear();\n            input.sendKeys('123');\n            expect(value.getText()).toEqual('value =');\n            expect(valid.getText()).toContain('false');\n          });\n        </file>\n      </example>\n   */\n  'number': numberInputType,\n\n\n  /**\n   * @ngdoc input\n   * @name input[url]\n   *\n   * @description\n   * Text input with URL validation. Sets the `url` validation error key if the content is not a\n   * valid URL.\n   *\n   * <div class=\"alert alert-warning\">\n   * **Note:** `input[url]` uses a regex to validate urls that is derived from the regex\n   * used in Chromium. If you need stricter validation, you can use `ng-pattern` or modify\n   * the built-in validators (see the {@link guide/forms Forms guide})\n   * </div>\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength. Setting the attribute to a negative or non-numeric value, allows view values of\n   *    any length.\n   * @param {string=} pattern Similar to `ngPattern` except that the attribute value is the actual string\n   *    that contains the regular expression body that will be converted to a regular expression\n   *    as in the ngPattern directive.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the ngModel value does not match\n   *    a RegExp found by evaluating the Angular expression given in the attribute value.\n   *    If the expression evaluates to a RegExp object then this is used directly.\n   *    If the expression is a string then it will be converted to a RegExp after wrapping it in `^` and `$`\n   *    characters. For instance, `\"abc\"` will be converted to `new RegExp('^abc$')`.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <example name=\"url-input-directive\" module=\"urlExample\">\n        <file name=\"index.html\">\n         <script>\n           angular.module('urlExample', [])\n             .controller('ExampleController', ['$scope', function($scope) {\n               $scope.url = {\n                 text: 'http://google.com'\n               };\n             }]);\n         </script>\n         <form name=\"myForm\" ng-controller=\"ExampleController\">\n           URL: <input type=\"url\" name=\"input\" ng-model=\"url.text\" required>\n           <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.input.$error.url\">\n             Not valid url!</span>\n           <tt>text = {{url.text}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n           <tt>myForm.$error.url = {{!!myForm.$error.url}}</tt><br/>\n          </form>\n        </file>\n        <file name=\"protractor.js\" type=\"protractor\">\n          var text = element(by.binding('url.text'));\n          var valid = element(by.binding('myForm.input.$valid'));\n          var input = element(by.model('url.text'));\n\n          it('should initialize to model', function() {\n            expect(text.getText()).toContain('http://google.com');\n            expect(valid.getText()).toContain('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input.clear();\n            input.sendKeys('');\n\n            expect(text.getText()).toEqual('text =');\n            expect(valid.getText()).toContain('false');\n          });\n\n          it('should be invalid if not url', function() {\n            input.clear();\n            input.sendKeys('box');\n\n            expect(valid.getText()).toContain('false');\n          });\n        </file>\n      </example>\n   */\n  'url': urlInputType,\n\n\n  /**\n   * @ngdoc input\n   * @name input[email]\n   *\n   * @description\n   * Text input with email validation. Sets the `email` validation error key if not a valid email\n   * address.\n   *\n   * <div class=\"alert alert-warning\">\n   * **Note:** `input[email]` uses a regex to validate email addresses that is derived from the regex\n   * used in Chromium. If you need stricter validation (e.g. requiring a top-level domain), you can\n   * use `ng-pattern` or modify the built-in validators (see the {@link guide/forms Forms guide})\n   * </div>\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength. Setting the attribute to a negative or non-numeric value, allows view values of\n   *    any length.\n   * @param {string=} pattern Similar to `ngPattern` except that the attribute value is the actual string\n   *    that contains the regular expression body that will be converted to a regular expression\n   *    as in the ngPattern directive.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the ngModel value does not match\n   *    a RegExp found by evaluating the Angular expression given in the attribute value.\n   *    If the expression evaluates to a RegExp object then this is used directly.\n   *    If the expression is a string then it will be converted to a RegExp after wrapping it in `^` and `$`\n   *    characters. For instance, `\"abc\"` will be converted to `new RegExp('^abc$')`.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <example name=\"email-input-directive\" module=\"emailExample\">\n        <file name=\"index.html\">\n         <script>\n           angular.module('emailExample', [])\n             .controller('ExampleController', ['$scope', function($scope) {\n               $scope.email = {\n                 text: 'me@example.com'\n               };\n             }]);\n         </script>\n           <form name=\"myForm\" ng-controller=\"ExampleController\">\n             Email: <input type=\"email\" name=\"input\" ng-model=\"email.text\" required>\n             <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n               Required!</span>\n             <span class=\"error\" ng-show=\"myForm.input.$error.email\">\n               Not valid email!</span>\n             <tt>text = {{email.text}}</tt><br/>\n             <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n             <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n             <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n             <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n             <tt>myForm.$error.email = {{!!myForm.$error.email}}</tt><br/>\n           </form>\n         </file>\n        <file name=\"protractor.js\" type=\"protractor\">\n          var text = element(by.binding('email.text'));\n          var valid = element(by.binding('myForm.input.$valid'));\n          var input = element(by.model('email.text'));\n\n          it('should initialize to model', function() {\n            expect(text.getText()).toContain('me@example.com');\n            expect(valid.getText()).toContain('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input.clear();\n            input.sendKeys('');\n            expect(text.getText()).toEqual('text =');\n            expect(valid.getText()).toContain('false');\n          });\n\n          it('should be invalid if not email', function() {\n            input.clear();\n            input.sendKeys('xxx');\n\n            expect(valid.getText()).toContain('false');\n          });\n        </file>\n      </example>\n   */\n  'email': emailInputType,\n\n\n  /**\n   * @ngdoc input\n   * @name input[radio]\n   *\n   * @description\n   * HTML radio button.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string} value The value to which the expression should be set when selected.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   * @param {string} ngValue Angular expression which sets the value to which the expression should\n   *    be set when selected.\n   *\n   * @example\n      <example name=\"radio-input-directive\" module=\"radioExample\">\n        <file name=\"index.html\">\n         <script>\n           angular.module('radioExample', [])\n             .controller('ExampleController', ['$scope', function($scope) {\n               $scope.color = {\n                 name: 'blue'\n               };\n               $scope.specialValue = {\n                 \"id\": \"12345\",\n                 \"value\": \"green\"\n               };\n             }]);\n         </script>\n         <form name=\"myForm\" ng-controller=\"ExampleController\">\n           <input type=\"radio\" ng-model=\"color.name\" value=\"red\">  Red <br/>\n           <input type=\"radio\" ng-model=\"color.name\" ng-value=\"specialValue\"> Green <br/>\n           <input type=\"radio\" ng-model=\"color.name\" value=\"blue\"> Blue <br/>\n           <tt>color = {{color.name | json}}</tt><br/>\n          </form>\n          Note that `ng-value=\"specialValue\"` sets radio item's value to be the value of `$scope.specialValue`.\n        </file>\n        <file name=\"protractor.js\" type=\"protractor\">\n          it('should change state', function() {\n            var color = element(by.binding('color.name'));\n\n            expect(color.getText()).toContain('blue');\n\n            element.all(by.model('color.name')).get(0).click();\n\n            expect(color.getText()).toContain('red');\n          });\n        </file>\n      </example>\n   */\n  'radio': radioInputType,\n\n\n  /**\n   * @ngdoc input\n   * @name input[checkbox]\n   *\n   * @description\n   * HTML checkbox.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {expression=} ngTrueValue The value to which the expression should be set when selected.\n   * @param {expression=} ngFalseValue The value to which the expression should be set when not selected.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <example name=\"checkbox-input-directive\" module=\"checkboxExample\">\n        <file name=\"index.html\">\n         <script>\n           angular.module('checkboxExample', [])\n             .controller('ExampleController', ['$scope', function($scope) {\n               $scope.checkboxModel = {\n                value1 : true,\n                value2 : 'YES'\n              };\n             }]);\n         </script>\n         <form name=\"myForm\" ng-controller=\"ExampleController\">\n           Value1: <input type=\"checkbox\" ng-model=\"checkboxModel.value1\"> <br/>\n           Value2: <input type=\"checkbox\" ng-model=\"checkboxModel.value2\"\n                          ng-true-value=\"'YES'\" ng-false-value=\"'NO'\"> <br/>\n           <tt>value1 = {{checkboxModel.value1}}</tt><br/>\n           <tt>value2 = {{checkboxModel.value2}}</tt><br/>\n          </form>\n        </file>\n        <file name=\"protractor.js\" type=\"protractor\">\n          it('should change state', function() {\n            var value1 = element(by.binding('checkboxModel.value1'));\n            var value2 = element(by.binding('checkboxModel.value2'));\n\n            expect(value1.getText()).toContain('true');\n            expect(value2.getText()).toContain('YES');\n\n            element(by.model('checkboxModel.value1')).click();\n            element(by.model('checkboxModel.value2')).click();\n\n            expect(value1.getText()).toContain('false');\n            expect(value2.getText()).toContain('NO');\n          });\n        </file>\n      </example>\n   */\n  'checkbox': checkboxInputType,\n\n  'hidden': noop,\n  'button': noop,\n  'submit': noop,\n  'reset': noop,\n  'file': noop\n};\n\nfunction stringBasedInputType(ctrl) {\n  ctrl.$formatters.push(function(value) {\n    return ctrl.$isEmpty(value) ? value : value.toString();\n  });\n}\n\nfunction textInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  baseInputType(scope, element, attr, ctrl, $sniffer, $browser);\n  stringBasedInputType(ctrl);\n}\n\nfunction baseInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  var type = lowercase(element[0].type);\n\n  // In composition mode, users are still inputing intermediate text buffer,\n  // hold the listener until composition is done.\n  // More about composition events: https://developer.mozilla.org/en-US/docs/Web/API/CompositionEvent\n  if (!$sniffer.android) {\n    var composing = false;\n\n    element.on('compositionstart', function(data) {\n      composing = true;\n    });\n\n    element.on('compositionend', function() {\n      composing = false;\n      listener();\n    });\n  }\n\n  var listener = function(ev) {\n    if (timeout) {\n      $browser.defer.cancel(timeout);\n      timeout = null;\n    }\n    if (composing) return;\n    var value = element.val(),\n        event = ev && ev.type;\n\n    // By default we will trim the value\n    // If the attribute ng-trim exists we will avoid trimming\n    // If input type is 'password', the value is never trimmed\n    if (type !== 'password' && (!attr.ngTrim || attr.ngTrim !== 'false')) {\n      value = trim(value);\n    }\n\n    // If a control is suffering from bad input (due to native validators), browsers discard its\n    // value, so it may be necessary to revalidate (by calling $setViewValue again) even if the\n    // control's value is the same empty value twice in a row.\n    if (ctrl.$viewValue !== value || (value === '' && ctrl.$$hasNativeValidators)) {\n      ctrl.$setViewValue(value, event);\n    }\n  };\n\n  // if the browser does support \"input\" event, we are fine - except on IE9 which doesn't fire the\n  // input event on backspace, delete or cut\n  if ($sniffer.hasEvent('input')) {\n    element.on('input', listener);\n  } else {\n    var timeout;\n\n    var deferListener = function(ev, input, origValue) {\n      if (!timeout) {\n        timeout = $browser.defer(function() {\n          timeout = null;\n          if (!input || input.value !== origValue) {\n            listener(ev);\n          }\n        });\n      }\n    };\n\n    element.on('keydown', function(event) {\n      var key = event.keyCode;\n\n      // ignore\n      //    command            modifiers                   arrows\n      if (key === 91 || (15 < key && key < 19) || (37 <= key && key <= 40)) return;\n\n      deferListener(event, this, this.value);\n    });\n\n    // if user modifies input value using context menu in IE, we need \"paste\" and \"cut\" events to catch it\n    if ($sniffer.hasEvent('paste')) {\n      element.on('paste cut', deferListener);\n    }\n  }\n\n  // if user paste into input using mouse on older browser\n  // or form autocomplete on newer browser, we need \"change\" event to catch it\n  element.on('change', listener);\n\n  ctrl.$render = function() {\n    element.val(ctrl.$isEmpty(ctrl.$viewValue) ? '' : ctrl.$viewValue);\n  };\n}\n\nfunction weekParser(isoWeek, existingDate) {\n  if (isDate(isoWeek)) {\n    return isoWeek;\n  }\n\n  if (isString(isoWeek)) {\n    WEEK_REGEXP.lastIndex = 0;\n    var parts = WEEK_REGEXP.exec(isoWeek);\n    if (parts) {\n      var year = +parts[1],\n          week = +parts[2],\n          hours = 0,\n          minutes = 0,\n          seconds = 0,\n          milliseconds = 0,\n          firstThurs = getFirstThursdayOfYear(year),\n          addDays = (week - 1) * 7;\n\n      if (existingDate) {\n        hours = existingDate.getHours();\n        minutes = existingDate.getMinutes();\n        seconds = existingDate.getSeconds();\n        milliseconds = existingDate.getMilliseconds();\n      }\n\n      return new Date(year, 0, firstThurs.getDate() + addDays, hours, minutes, seconds, milliseconds);\n    }\n  }\n\n  return NaN;\n}\n\nfunction createDateParser(regexp, mapping) {\n  return function(iso, date) {\n    var parts, map;\n\n    if (isDate(iso)) {\n      return iso;\n    }\n\n    if (isString(iso)) {\n      // When a date is JSON'ified to wraps itself inside of an extra\n      // set of double quotes. This makes the date parsing code unable\n      // to match the date string and parse it as a date.\n      if (iso.charAt(0) == '\"' && iso.charAt(iso.length - 1) == '\"') {\n        iso = iso.substring(1, iso.length - 1);\n      }\n      if (ISO_DATE_REGEXP.test(iso)) {\n        return new Date(iso);\n      }\n      regexp.lastIndex = 0;\n      parts = regexp.exec(iso);\n\n      if (parts) {\n        parts.shift();\n        if (date) {\n          map = {\n            yyyy: date.getFullYear(),\n            MM: date.getMonth() + 1,\n            dd: date.getDate(),\n            HH: date.getHours(),\n            mm: date.getMinutes(),\n            ss: date.getSeconds(),\n            sss: date.getMilliseconds() / 1000\n          };\n        } else {\n          map = { yyyy: 1970, MM: 1, dd: 1, HH: 0, mm: 0, ss: 0, sss: 0 };\n        }\n\n        forEach(parts, function(part, index) {\n          if (index < mapping.length) {\n            map[mapping[index]] = +part;\n          }\n        });\n        return new Date(map.yyyy, map.MM - 1, map.dd, map.HH, map.mm, map.ss || 0, map.sss * 1000 || 0);\n      }\n    }\n\n    return NaN;\n  };\n}\n\nfunction createDateInputType(type, regexp, parseDate, format) {\n  return function dynamicDateInputType(scope, element, attr, ctrl, $sniffer, $browser, $filter) {\n    badInputChecker(scope, element, attr, ctrl);\n    baseInputType(scope, element, attr, ctrl, $sniffer, $browser);\n    var timezone = ctrl && ctrl.$options && ctrl.$options.timezone;\n    var previousDate;\n\n    ctrl.$$parserName = type;\n    ctrl.$parsers.push(function(value) {\n      if (ctrl.$isEmpty(value)) return null;\n      if (regexp.test(value)) {\n        // Note: We cannot read ctrl.$modelValue, as there might be a different\n        // parser/formatter in the processing chain so that the model\n        // contains some different data format!\n        var parsedDate = parseDate(value, previousDate);\n        if (timezone === 'UTC') {\n          parsedDate.setMinutes(parsedDate.getMinutes() - parsedDate.getTimezoneOffset());\n        }\n        return parsedDate;\n      }\n      return undefined;\n    });\n\n    ctrl.$formatters.push(function(value) {\n      if (value && !isDate(value)) {\n        throw $ngModelMinErr('datefmt', 'Expected `{0}` to be a date', value);\n      }\n      if (isValidDate(value)) {\n        previousDate = value;\n        if (previousDate && timezone === 'UTC') {\n          var timezoneOffset = 60000 * previousDate.getTimezoneOffset();\n          previousDate = new Date(previousDate.getTime() + timezoneOffset);\n        }\n        return $filter('date')(value, format, timezone);\n      } else {\n        previousDate = null;\n        return '';\n      }\n    });\n\n    if (isDefined(attr.min) || attr.ngMin) {\n      var minVal;\n      ctrl.$validators.min = function(value) {\n        return !isValidDate(value) || isUndefined(minVal) || parseDate(value) >= minVal;\n      };\n      attr.$observe('min', function(val) {\n        minVal = parseObservedDateValue(val);\n        ctrl.$validate();\n      });\n    }\n\n    if (isDefined(attr.max) || attr.ngMax) {\n      var maxVal;\n      ctrl.$validators.max = function(value) {\n        return !isValidDate(value) || isUndefined(maxVal) || parseDate(value) <= maxVal;\n      };\n      attr.$observe('max', function(val) {\n        maxVal = parseObservedDateValue(val);\n        ctrl.$validate();\n      });\n    }\n\n    function isValidDate(value) {\n      // Invalid Date: getTime() returns NaN\n      return value && !(value.getTime && value.getTime() !== value.getTime());\n    }\n\n    function parseObservedDateValue(val) {\n      return isDefined(val) ? (isDate(val) ? val : parseDate(val)) : undefined;\n    }\n  };\n}\n\nfunction badInputChecker(scope, element, attr, ctrl) {\n  var node = element[0];\n  var nativeValidation = ctrl.$$hasNativeValidators = isObject(node.validity);\n  if (nativeValidation) {\n    ctrl.$parsers.push(function(value) {\n      var validity = element.prop(VALIDITY_STATE_PROPERTY) || {};\n      // Detect bug in FF35 for input[email] (https://bugzilla.mozilla.org/show_bug.cgi?id=1064430):\n      // - also sets validity.badInput (should only be validity.typeMismatch).\n      // - see http://www.whatwg.org/specs/web-apps/current-work/multipage/forms.html#e-mail-state-(type=email)\n      // - can ignore this case as we can still read out the erroneous email...\n      return validity.badInput && !validity.typeMismatch ? undefined : value;\n    });\n  }\n}\n\nfunction numberInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  badInputChecker(scope, element, attr, ctrl);\n  baseInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  ctrl.$$parserName = 'number';\n  ctrl.$parsers.push(function(value) {\n    if (ctrl.$isEmpty(value))      return null;\n    if (NUMBER_REGEXP.test(value)) return parseFloat(value);\n    return undefined;\n  });\n\n  ctrl.$formatters.push(function(value) {\n    if (!ctrl.$isEmpty(value)) {\n      if (!isNumber(value)) {\n        throw $ngModelMinErr('numfmt', 'Expected `{0}` to be a number', value);\n      }\n      value = value.toString();\n    }\n    return value;\n  });\n\n  if (attr.min || attr.ngMin) {\n    var minVal;\n    ctrl.$validators.min = function(value) {\n      return ctrl.$isEmpty(value) || isUndefined(minVal) || value >= minVal;\n    };\n\n    attr.$observe('min', function(val) {\n      if (isDefined(val) && !isNumber(val)) {\n        val = parseFloat(val, 10);\n      }\n      minVal = isNumber(val) && !isNaN(val) ? val : undefined;\n      // TODO(matsko): implement validateLater to reduce number of validations\n      ctrl.$validate();\n    });\n  }\n\n  if (attr.max || attr.ngMax) {\n    var maxVal;\n    ctrl.$validators.max = function(value) {\n      return ctrl.$isEmpty(value) || isUndefined(maxVal) || value <= maxVal;\n    };\n\n    attr.$observe('max', function(val) {\n      if (isDefined(val) && !isNumber(val)) {\n        val = parseFloat(val, 10);\n      }\n      maxVal = isNumber(val) && !isNaN(val) ? val : undefined;\n      // TODO(matsko): implement validateLater to reduce number of validations\n      ctrl.$validate();\n    });\n  }\n}\n\nfunction urlInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  // Note: no badInputChecker here by purpose as `url` is only a validation\n  // in browsers, i.e. we can always read out input.value even if it is not valid!\n  baseInputType(scope, element, attr, ctrl, $sniffer, $browser);\n  stringBasedInputType(ctrl);\n\n  ctrl.$$parserName = 'url';\n  ctrl.$validators.url = function(modelValue, viewValue) {\n    var value = modelValue || viewValue;\n    return ctrl.$isEmpty(value) || URL_REGEXP.test(value);\n  };\n}\n\nfunction emailInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  // Note: no badInputChecker here by purpose as `url` is only a validation\n  // in browsers, i.e. we can always read out input.value even if it is not valid!\n  baseInputType(scope, element, attr, ctrl, $sniffer, $browser);\n  stringBasedInputType(ctrl);\n\n  ctrl.$$parserName = 'email';\n  ctrl.$validators.email = function(modelValue, viewValue) {\n    var value = modelValue || viewValue;\n    return ctrl.$isEmpty(value) || EMAIL_REGEXP.test(value);\n  };\n}\n\nfunction radioInputType(scope, element, attr, ctrl) {\n  // make the name unique, if not defined\n  if (isUndefined(attr.name)) {\n    element.attr('name', nextUid());\n  }\n\n  var listener = function(ev) {\n    if (element[0].checked) {\n      ctrl.$setViewValue(attr.value, ev && ev.type);\n    }\n  };\n\n  element.on('click', listener);\n\n  ctrl.$render = function() {\n    var value = attr.value;\n    element[0].checked = (value == ctrl.$viewValue);\n  };\n\n  attr.$observe('value', ctrl.$render);\n}\n\nfunction parseConstantExpr($parse, context, name, expression, fallback) {\n  var parseFn;\n  if (isDefined(expression)) {\n    parseFn = $parse(expression);\n    if (!parseFn.constant) {\n      throw minErr('ngModel')('constexpr', 'Expected constant expression for `{0}`, but saw ' +\n                                   '`{1}`.', name, expression);\n    }\n    return parseFn(context);\n  }\n  return fallback;\n}\n\nfunction checkboxInputType(scope, element, attr, ctrl, $sniffer, $browser, $filter, $parse) {\n  var trueValue = parseConstantExpr($parse, scope, 'ngTrueValue', attr.ngTrueValue, true);\n  var falseValue = parseConstantExpr($parse, scope, 'ngFalseValue', attr.ngFalseValue, false);\n\n  var listener = function(ev) {\n    ctrl.$setViewValue(element[0].checked, ev && ev.type);\n  };\n\n  element.on('click', listener);\n\n  ctrl.$render = function() {\n    element[0].checked = ctrl.$viewValue;\n  };\n\n  // Override the standard `$isEmpty` because the $viewValue of an empty checkbox is always set to `false`\n  // This is because of the parser below, which compares the `$modelValue` with `trueValue` to convert\n  // it to a boolean.\n  ctrl.$isEmpty = function(value) {\n    return value === false;\n  };\n\n  ctrl.$formatters.push(function(value) {\n    return equals(value, trueValue);\n  });\n\n  ctrl.$parsers.push(function(value) {\n    return value ? trueValue : falseValue;\n  });\n}\n\n\n/**\n * @ngdoc directive\n * @name textarea\n * @restrict E\n *\n * @description\n * HTML textarea element control with angular data-binding. The data-binding and validation\n * properties of this element are exactly the same as those of the\n * {@link ng.directive:input input element}.\n *\n * @param {string} ngModel Assignable angular expression to data-bind to.\n * @param {string=} name Property name of the form under which the control is published.\n * @param {string=} required Sets `required` validation error key if the value is not entered.\n * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n *    `required` when you want to data-bind to the `required` attribute.\n * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n *    minlength.\n * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n *    maxlength. Setting the attribute to a negative or non-numeric value, allows view values of any\n *    length.\n * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n *    patterns defined as scope expressions.\n * @param {string=} ngChange Angular expression to be executed when input changes due to user\n *    interaction with the input element.\n * @param {boolean=} [ngTrim=true] If set to false Angular will not automatically trim the input.\n */\n\n\n/**\n * @ngdoc directive\n * @name input\n * @restrict E\n *\n * @description\n * HTML input element control. When used together with {@link ngModel `ngModel`}, it provides data-binding,\n * input state control, and validation.\n * Input control follows HTML5 input types and polyfills the HTML5 validation behavior for older browsers.\n *\n * <div class=\"alert alert-warning\">\n * **Note:** Not every feature offered is available for all input types.\n * Specifically, data binding and event handling via `ng-model` is unsupported for `input[file]`.\n * </div>\n *\n * @param {string} ngModel Assignable angular expression to data-bind to.\n * @param {string=} name Property name of the form under which the control is published.\n * @param {string=} required Sets `required` validation error key if the value is not entered.\n * @param {boolean=} ngRequired Sets `required` attribute if set to true\n * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n *    minlength.\n * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n *    maxlength. Setting the attribute to a negative or non-numeric value, allows view values of any\n *    length.\n * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n *    patterns defined as scope expressions.\n * @param {string=} ngChange Angular expression to be executed when input changes due to user\n *    interaction with the input element.\n * @param {boolean=} [ngTrim=true] If set to false Angular will not automatically trim the input.\n *    This parameter is ignored for input[type=password] controls, which will never trim the\n *    input.\n *\n * @example\n    <example name=\"input-directive\" module=\"inputExample\">\n      <file name=\"index.html\">\n       <script>\n          angular.module('inputExample', [])\n            .controller('ExampleController', ['$scope', function($scope) {\n              $scope.user = {name: 'guest', last: 'visitor'};\n            }]);\n       </script>\n       <div ng-controller=\"ExampleController\">\n         <form name=\"myForm\">\n           User name: <input type=\"text\" name=\"userName\" ng-model=\"user.name\" required>\n           <span class=\"error\" ng-show=\"myForm.userName.$error.required\">\n             Required!</span><br>\n           Last name: <input type=\"text\" name=\"lastName\" ng-model=\"user.last\"\n             ng-minlength=\"3\" ng-maxlength=\"10\">\n           <span class=\"error\" ng-show=\"myForm.lastName.$error.minlength\">\n             Too short!</span>\n           <span class=\"error\" ng-show=\"myForm.lastName.$error.maxlength\">\n             Too long!</span><br>\n         </form>\n         <hr>\n         <tt>user = {{user}}</tt><br/>\n         <tt>myForm.userName.$valid = {{myForm.userName.$valid}}</tt><br>\n         <tt>myForm.userName.$error = {{myForm.userName.$error}}</tt><br>\n         <tt>myForm.lastName.$valid = {{myForm.lastName.$valid}}</tt><br>\n         <tt>myForm.lastName.$error = {{myForm.lastName.$error}}</tt><br>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br>\n         <tt>myForm.$error.minlength = {{!!myForm.$error.minlength}}</tt><br>\n         <tt>myForm.$error.maxlength = {{!!myForm.$error.maxlength}}</tt><br>\n       </div>\n      </file>\n      <file name=\"protractor.js\" type=\"protractor\">\n        var user = element(by.exactBinding('user'));\n        var userNameValid = element(by.binding('myForm.userName.$valid'));\n        var lastNameValid = element(by.binding('myForm.lastName.$valid'));\n        var lastNameError = element(by.binding('myForm.lastName.$error'));\n        var formValid = element(by.binding('myForm.$valid'));\n        var userNameInput = element(by.model('user.name'));\n        var userLastInput = element(by.model('user.last'));\n\n        it('should initialize to model', function() {\n          expect(user.getText()).toContain('{\"name\":\"guest\",\"last\":\"visitor\"}');\n          expect(userNameValid.getText()).toContain('true');\n          expect(formValid.getText()).toContain('true');\n        });\n\n        it('should be invalid if empty when required', function() {\n          userNameInput.clear();\n          userNameInput.sendKeys('');\n\n          expect(user.getText()).toContain('{\"last\":\"visitor\"}');\n          expect(userNameValid.getText()).toContain('false');\n          expect(formValid.getText()).toContain('false');\n        });\n\n        it('should be valid if empty when min length is set', function() {\n          userLastInput.clear();\n          userLastInput.sendKeys('');\n\n          expect(user.getText()).toContain('{\"name\":\"guest\",\"last\":\"\"}');\n          expect(lastNameValid.getText()).toContain('true');\n          expect(formValid.getText()).toContain('true');\n        });\n\n        it('should be invalid if less than required min length', function() {\n          userLastInput.clear();\n          userLastInput.sendKeys('xx');\n\n          expect(user.getText()).toContain('{\"name\":\"guest\"}');\n          expect(lastNameValid.getText()).toContain('false');\n          expect(lastNameError.getText()).toContain('minlength');\n          expect(formValid.getText()).toContain('false');\n        });\n\n        it('should be invalid if longer than max length', function() {\n          userLastInput.clear();\n          userLastInput.sendKeys('some ridiculously long name');\n\n          expect(user.getText()).toContain('{\"name\":\"guest\"}');\n          expect(lastNameValid.getText()).toContain('false');\n          expect(lastNameError.getText()).toContain('maxlength');\n          expect(formValid.getText()).toContain('false');\n        });\n      </file>\n    </example>\n */\nvar inputDirective = ['$browser', '$sniffer', '$filter', '$parse',\n    function($browser, $sniffer, $filter, $parse) {\n  return {\n    restrict: 'E',\n    require: ['?ngModel'],\n    link: {\n      pre: function(scope, element, attr, ctrls) {\n        if (ctrls[0]) {\n          (inputType[lowercase(attr.type)] || inputType.text)(scope, element, attr, ctrls[0], $sniffer,\n                                                              $browser, $filter, $parse);\n        }\n      }\n    }\n  };\n}];\n\n\n\nvar CONSTANT_VALUE_REGEXP = /^(true|false|\\d+)$/;\n/**\n * @ngdoc directive\n * @name ngValue\n *\n * @description\n * Binds the given expression to the value of `<option>` or {@link input[radio] `input[radio]`},\n * so that when the element is selected, the {@link ngModel `ngModel`} of that element is set to\n * the bound value.\n *\n * `ngValue` is useful when dynamically generating lists of radio buttons using\n * {@link ngRepeat `ngRepeat`}, as shown below.\n *\n * Likewise, `ngValue` can be used to generate `<option>` elements for\n * the {@link select `select`} element. In that case however, only strings are supported\n * for the `value `attribute, so the resulting `ngModel` will always be a string.\n * Support for `select` models with non-string values is available via `ngOptions`.\n *\n * @element input\n * @param {string=} ngValue angular expression, whose value will be bound to the `value` attribute\n *   of the `input` element\n *\n * @example\n    <example name=\"ngValue-directive\" module=\"valueExample\">\n      <file name=\"index.html\">\n       <script>\n          angular.module('valueExample', [])\n            .controller('ExampleController', ['$scope', function($scope) {\n              $scope.names = ['pizza', 'unicorns', 'robots'];\n              $scope.my = { favorite: 'unicorns' };\n            }]);\n       </script>\n        <form ng-controller=\"ExampleController\">\n          <h2>Which is your favorite?</h2>\n            <label ng-repeat=\"name in names\" for=\"{{name}}\">\n              {{name}}\n              <input type=\"radio\"\n                     ng-model=\"my.favorite\"\n                     ng-value=\"name\"\n                     id=\"{{name}}\"\n                     name=\"favorite\">\n            </label>\n          <div>You chose {{my.favorite}}</div>\n        </form>\n      </file>\n      <file name=\"protractor.js\" type=\"protractor\">\n        var favorite = element(by.binding('my.favorite'));\n\n        it('should initialize to model', function() {\n          expect(favorite.getText()).toContain('unicorns');\n        });\n        it('should bind the values to the inputs', function() {\n          element.all(by.model('my.favorite')).get(0).click();\n          expect(favorite.getText()).toContain('pizza');\n        });\n      </file>\n    </example>\n */\nvar ngValueDirective = function() {\n  return {\n    restrict: 'A',\n    priority: 100,\n    compile: function(tpl, tplAttr) {\n      if (CONSTANT_VALUE_REGEXP.test(tplAttr.ngValue)) {\n        return function ngValueConstantLink(scope, elm, attr) {\n          attr.$set('value', scope.$eval(attr.ngValue));\n        };\n      } else {\n        return function ngValueLink(scope, elm, attr) {\n          scope.$watch(attr.ngValue, function valueWatchAction(value) {\n            attr.$set('value', value);\n          });\n        };\n      }\n    }\n  };\n};\n\n/**\n * @ngdoc directive\n * @name ngBind\n * @restrict AC\n *\n * @description\n * The `ngBind` attribute tells Angular to replace the text content of the specified HTML element\n * with the value of a given expression, and to update the text content when the value of that\n * expression changes.\n *\n * Typically, you don't use `ngBind` directly, but instead you use the double curly markup like\n * `{{ expression }}` which is similar but less verbose.\n *\n * It is preferable to use `ngBind` instead of `{{ expression }}` if a template is momentarily\n * displayed by the browser in its raw state before Angular compiles it. Since `ngBind` is an\n * element attribute, it makes the bindings invisible to the user while the page is loading.\n *\n * An alternative solution to this problem would be using the\n * {@link ng.directive:ngCloak ngCloak} directive.\n *\n *\n * @element ANY\n * @param {expression} ngBind {@link guide/expression Expression} to evaluate.\n *\n * @example\n * Enter a name in the Live Preview text box; the greeting below the text box changes instantly.\n   <example module=\"bindExample\">\n     <file name=\"index.html\">\n       <script>\n         angular.module('bindExample', [])\n           .controller('ExampleController', ['$scope', function($scope) {\n             $scope.name = 'Whirled';\n           }]);\n       </script>\n       <div ng-controller=\"ExampleController\">\n         Enter name: <input type=\"text\" ng-model=\"name\"><br>\n         Hello <span ng-bind=\"name\"></span>!\n       </div>\n     </file>\n     <file name=\"protractor.js\" type=\"protractor\">\n       it('should check ng-bind', function() {\n         var nameInput = element(by.model('name'));\n\n         expect(element(by.binding('name')).getText()).toBe('Whirled');\n         nameInput.clear();\n         nameInput.sendKeys('world');\n         expect(element(by.binding('name')).getText()).toBe('world');\n       });\n     </file>\n   </example>\n */\nvar ngBindDirective = ['$compile', function($compile) {\n  return {\n    restrict: 'AC',\n    compile: function ngBindCompile(templateElement) {\n      $compile.$$addBindingClass(templateElement);\n      return function ngBindLink(scope, element, attr) {\n        $compile.$$addBindingInfo(element, attr.ngBind);\n        element = element[0];\n        scope.$watch(attr.ngBind, function ngBindWatchAction(value) {\n          element.textContent = value === undefined ? '' : value;\n        });\n      };\n    }\n  };\n}];\n\n\n/**\n * @ngdoc directive\n * @name ngBindTemplate\n *\n * @description\n * The `ngBindTemplate` directive specifies that the element\n * text content should be replaced with the interpolation of the template\n * in the `ngBindTemplate` attribute.\n * Unlike `ngBind`, the `ngBindTemplate` can contain multiple `{{` `}}`\n * expressions. This directive is needed since some HTML elements\n * (such as TITLE and OPTION) cannot contain SPAN elements.\n *\n * @element ANY\n * @param {string} ngBindTemplate template of form\n *   <tt>{{</tt> <tt>expression</tt> <tt>}}</tt> to eval.\n *\n * @example\n * Try it here: enter text in text box and watch the greeting change.\n   <example module=\"bindExample\">\n     <file name=\"index.html\">\n       <script>\n         angular.module('bindExample', [])\n           .controller('ExampleController', ['$scope', function($scope) {\n             $scope.salutation = 'Hello';\n             $scope.name = 'World';\n           }]);\n       </script>\n       <div ng-controller=\"ExampleController\">\n        Salutation: <input type=\"text\" ng-model=\"salutation\"><br>\n        Name: <input type=\"text\" ng-model=\"name\"><br>\n        <pre ng-bind-template=\"{{salutation}} {{name}}!\"></pre>\n       </div>\n     </file>\n     <file name=\"protractor.js\" type=\"protractor\">\n       it('should check ng-bind', function() {\n         var salutationElem = element(by.binding('salutation'));\n         var salutationInput = element(by.model('salutation'));\n         var nameInput = element(by.model('name'));\n\n         expect(salutationElem.getText()).toBe('Hello World!');\n\n         salutationInput.clear();\n         salutationInput.sendKeys('Greetings');\n         nameInput.clear();\n         nameInput.sendKeys('user');\n\n         expect(salutationElem.getText()).toBe('Greetings user!');\n       });\n     </file>\n   </example>\n */\nvar ngBindTemplateDirective = ['$interpolate', '$compile', function($interpolate, $compile) {\n  return {\n    compile: function ngBindTemplateCompile(templateElement) {\n      $compile.$$addBindingClass(templateElement);\n      return function ngBindTemplateLink(scope, element, attr) {\n        var interpolateFn = $interpolate(element.attr(attr.$attr.ngBindTemplate));\n        $compile.$$addBindingInfo(element, interpolateFn.expressions);\n        element = element[0];\n        attr.$observe('ngBindTemplate', function(value) {\n          element.textContent = value === undefined ? '' : value;\n        });\n      };\n    }\n  };\n}];\n\n\n/**\n * @ngdoc directive\n * @name ngBindHtml\n *\n * @description\n * Evaluates the expression and inserts the resulting HTML into the element in a secure way. By default,\n * the resulting HTML content will be sanitized using the {@link ngSanitize.$sanitize $sanitize} service.\n * To utilize this functionality, ensure that `$sanitize` is available, for example, by including {@link\n * ngSanitize} in your module's dependencies (not in core Angular). In order to use {@link ngSanitize}\n * in your module's dependencies, you need to include \"angular-sanitize.js\" in your application.\n *\n * You may also bypass sanitization for values you know are safe. To do so, bind to\n * an explicitly trusted value via {@link ng.$sce#trustAsHtml $sce.trustAsHtml}.  See the example\n * under {@link ng.$sce#show-me-an-example-using-sce- Strict Contextual Escaping (SCE)}.\n *\n * Note: If a `$sanitize` service is unavailable and the bound value isn't explicitly trusted, you\n * will have an exception (instead of an exploit.)\n *\n * @element ANY\n * @param {expression} ngBindHtml {@link guide/expression Expression} to evaluate.\n *\n * @example\n\n   <example module=\"bindHtmlExample\" deps=\"angular-sanitize.js\">\n     <file name=\"index.html\">\n       <div ng-controller=\"ExampleController\">\n        <p ng-bind-html=\"myHTML\"></p>\n       </div>\n     </file>\n\n     <file name=\"script.js\">\n       angular.module('bindHtmlExample', ['ngSanitize'])\n         .controller('ExampleController', ['$scope', function($scope) {\n           $scope.myHTML =\n              'I am an <code>HTML</code>string with ' +\n              '<a href=\"#\">links!</a> and other <em>stuff</em>';\n         }]);\n     </file>\n\n     <file name=\"protractor.js\" type=\"protractor\">\n       it('should check ng-bind-html', function() {\n         expect(element(by.binding('myHTML')).getText()).toBe(\n             'I am an HTMLstring with links! and other stuff');\n       });\n     </file>\n   </example>\n */\nvar ngBindHtmlDirective = ['$sce', '$parse', '$compile', function($sce, $parse, $compile) {\n  return {\n    restrict: 'A',\n    compile: function ngBindHtmlCompile(tElement, tAttrs) {\n      var ngBindHtmlGetter = $parse(tAttrs.ngBindHtml);\n      var ngBindHtmlWatch = $parse(tAttrs.ngBindHtml, function getStringValue(value) {\n        return (value || '').toString();\n      });\n      $compile.$$addBindingClass(tElement);\n\n      return function ngBindHtmlLink(scope, element, attr) {\n        $compile.$$addBindingInfo(element, attr.ngBindHtml);\n\n        scope.$watch(ngBindHtmlWatch, function ngBindHtmlWatchAction() {\n          // we re-evaluate the expr because we want a TrustedValueHolderType\n          // for $sce, not a string\n          element.html($sce.getTrustedHtml(ngBindHtmlGetter(scope)) || '');\n        });\n      };\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ngChange\n *\n * @description\n * Evaluate the given expression when the user changes the input.\n * The expression is evaluated immediately, unlike the JavaScript onchange event\n * which only triggers at the end of a change (usually, when the user leaves the\n * form element or presses the return key).\n *\n * The `ngChange` expression is only evaluated when a change in the input value causes\n * a new value to be committed to the model.\n *\n * It will not be evaluated:\n * * if the value returned from the `$parsers` transformation pipeline has not changed\n * * if the input has continued to be invalid since the model will stay `null`\n * * if the model is changed programmatically and not by a change to the input value\n *\n *\n * Note, this directive requires `ngModel` to be present.\n *\n * @element input\n * @param {expression} ngChange {@link guide/expression Expression} to evaluate upon change\n * in input value.\n *\n * @example\n * <example name=\"ngChange-directive\" module=\"changeExample\">\n *   <file name=\"index.html\">\n *     <script>\n *       angular.module('changeExample', [])\n *         .controller('ExampleController', ['$scope', function($scope) {\n *           $scope.counter = 0;\n *           $scope.change = function() {\n *             $scope.counter++;\n *           };\n *         }]);\n *     </script>\n *     <div ng-controller=\"ExampleController\">\n *       <input type=\"checkbox\" ng-model=\"confirmed\" ng-change=\"change()\" id=\"ng-change-example1\" />\n *       <input type=\"checkbox\" ng-model=\"confirmed\" id=\"ng-change-example2\" />\n *       <label for=\"ng-change-example2\">Confirmed</label><br />\n *       <tt>debug = {{confirmed}}</tt><br/>\n *       <tt>counter = {{counter}}</tt><br/>\n *     </div>\n *   </file>\n *   <file name=\"protractor.js\" type=\"protractor\">\n *     var counter = element(by.binding('counter'));\n *     var debug = element(by.binding('confirmed'));\n *\n *     it('should evaluate the expression if changing from view', function() {\n *       expect(counter.getText()).toContain('0');\n *\n *       element(by.id('ng-change-example1')).click();\n *\n *       expect(counter.getText()).toContain('1');\n *       expect(debug.getText()).toContain('true');\n *     });\n *\n *     it('should not evaluate the expression if changing from model', function() {\n *       element(by.id('ng-change-example2')).click();\n\n *       expect(counter.getText()).toContain('0');\n *       expect(debug.getText()).toContain('true');\n *     });\n *   </file>\n * </example>\n */\nvar ngChangeDirective = valueFn({\n  restrict: 'A',\n  require: 'ngModel',\n  link: function(scope, element, attr, ctrl) {\n    ctrl.$viewChangeListeners.push(function() {\n      scope.$eval(attr.ngChange);\n    });\n  }\n});\n\nfunction classDirective(name, selector) {\n  name = 'ngClass' + name;\n  return ['$animate', function($animate) {\n    return {\n      restrict: 'AC',\n      link: function(scope, element, attr) {\n        var oldVal;\n\n        scope.$watch(attr[name], ngClassWatchAction, true);\n\n        attr.$observe('class', function(value) {\n          ngClassWatchAction(scope.$eval(attr[name]));\n        });\n\n\n        if (name !== 'ngClass') {\n          scope.$watch('$index', function($index, old$index) {\n            // jshint bitwise: false\n            var mod = $index & 1;\n            if (mod !== (old$index & 1)) {\n              var classes = arrayClasses(scope.$eval(attr[name]));\n              mod === selector ?\n                addClasses(classes) :\n                removeClasses(classes);\n            }\n          });\n        }\n\n        function addClasses(classes) {\n          var newClasses = digestClassCounts(classes, 1);\n          attr.$addClass(newClasses);\n        }\n\n        function removeClasses(classes) {\n          var newClasses = digestClassCounts(classes, -1);\n          attr.$removeClass(newClasses);\n        }\n\n        function digestClassCounts(classes, count) {\n          var classCounts = element.data('$classCounts') || {};\n          var classesToUpdate = [];\n          forEach(classes, function(className) {\n            if (count > 0 || classCounts[className]) {\n              classCounts[className] = (classCounts[className] || 0) + count;\n              if (classCounts[className] === +(count > 0)) {\n                classesToUpdate.push(className);\n              }\n            }\n          });\n          element.data('$classCounts', classCounts);\n          return classesToUpdate.join(' ');\n        }\n\n        function updateClasses(oldClasses, newClasses) {\n          var toAdd = arrayDifference(newClasses, oldClasses);\n          var toRemove = arrayDifference(oldClasses, newClasses);\n          toAdd = digestClassCounts(toAdd, 1);\n          toRemove = digestClassCounts(toRemove, -1);\n          if (toAdd && toAdd.length) {\n            $animate.addClass(element, toAdd);\n          }\n          if (toRemove && toRemove.length) {\n            $animate.removeClass(element, toRemove);\n          }\n        }\n\n        function ngClassWatchAction(newVal) {\n          if (selector === true || scope.$index % 2 === selector) {\n            var newClasses = arrayClasses(newVal || []);\n            if (!oldVal) {\n              addClasses(newClasses);\n            } else if (!equals(newVal,oldVal)) {\n              var oldClasses = arrayClasses(oldVal);\n              updateClasses(oldClasses, newClasses);\n            }\n          }\n          oldVal = shallowCopy(newVal);\n        }\n      }\n    };\n\n    function arrayDifference(tokens1, tokens2) {\n      var values = [];\n\n      outer:\n      for (var i = 0; i < tokens1.length; i++) {\n        var token = tokens1[i];\n        for (var j = 0; j < tokens2.length; j++) {\n          if (token == tokens2[j]) continue outer;\n        }\n        values.push(token);\n      }\n      return values;\n    }\n\n    function arrayClasses(classVal) {\n      if (isArray(classVal)) {\n        return classVal;\n      } else if (isString(classVal)) {\n        return classVal.split(' ');\n      } else if (isObject(classVal)) {\n        var classes = [];\n        forEach(classVal, function(v, k) {\n          if (v) {\n            classes = classes.concat(k.split(' '));\n          }\n        });\n        return classes;\n      }\n      return classVal;\n    }\n  }];\n}\n\n/**\n * @ngdoc directive\n * @name ngClass\n * @restrict AC\n *\n * @description\n * The `ngClass` directive allows you to dynamically set CSS classes on an HTML element by databinding\n * an expression that represents all classes to be added.\n *\n * The directive operates in three different ways, depending on which of three types the expression\n * evaluates to:\n *\n * 1. If the expression evaluates to a string, the string should be one or more space-delimited class\n * names.\n *\n * 2. If the expression evaluates to an array, each element of the array should be a string that is\n * one or more space-delimited class names.\n *\n * 3. If the expression evaluates to an object, then for each key-value pair of the\n * object with a truthy value the corresponding key is used as a class name.\n *\n * The directive won't add duplicate classes if a particular class was already set.\n *\n * When the expression changes, the previously added classes are removed and only then the\n * new classes are added.\n *\n * @animations\n * **add** - happens just before the class is applied to the elements\n *\n * **remove** - happens just before the class is removed from the element\n *\n * @element ANY\n * @param {expression} ngClass {@link guide/expression Expression} to eval. The result\n *   of the evaluation can be a string representing space delimited class\n *   names, an array, or a map of class names to boolean values. In the case of a map, the\n *   names of the properties whose values are truthy will be added as css classes to the\n *   element.\n *\n * @example Example that demonstrates basic bindings via ngClass directive.\n   <example>\n     <file name=\"index.html\">\n       <p ng-class=\"{strike: deleted, bold: important, red: error}\">Map Syntax Example</p>\n       <input type=\"checkbox\" ng-model=\"deleted\"> deleted (apply \"strike\" class)<br>\n       <input type=\"checkbox\" ng-model=\"important\"> important (apply \"bold\" class)<br>\n       <input type=\"checkbox\" ng-model=\"error\"> error (apply \"red\" class)\n       <hr>\n       <p ng-class=\"style\">Using String Syntax</p>\n       <input type=\"text\" ng-model=\"style\" placeholder=\"Type: bold strike red\">\n       <hr>\n       <p ng-class=\"[style1, style2, style3]\">Using Array Syntax</p>\n       <input ng-model=\"style1\" placeholder=\"Type: bold, strike or red\"><br>\n       <input ng-model=\"style2\" placeholder=\"Type: bold, strike or red\"><br>\n       <input ng-model=\"style3\" placeholder=\"Type: bold, strike or red\"><br>\n     </file>\n     <file name=\"style.css\">\n       .strike {\n         text-decoration: line-through;\n       }\n       .bold {\n           font-weight: bold;\n       }\n       .red {\n           color: red;\n       }\n     </file>\n     <file name=\"protractor.js\" type=\"protractor\">\n       var ps = element.all(by.css('p'));\n\n       it('should let you toggle the class', function() {\n\n         expect(ps.first().getAttribute('class')).not.toMatch(/bold/);\n         expect(ps.first().getAttribute('class')).not.toMatch(/red/);\n\n         element(by.model('important')).click();\n         expect(ps.first().getAttribute('class')).toMatch(/bold/);\n\n         element(by.model('error')).click();\n         expect(ps.first().getAttribute('class')).toMatch(/red/);\n       });\n\n       it('should let you toggle string example', function() {\n         expect(ps.get(1).getAttribute('class')).toBe('');\n         element(by.model('style')).clear();\n         element(by.model('style')).sendKeys('red');\n         expect(ps.get(1).getAttribute('class')).toBe('red');\n       });\n\n       it('array example should have 3 classes', function() {\n         expect(ps.last().getAttribute('class')).toBe('');\n         element(by.model('style1')).sendKeys('bold');\n         element(by.model('style2')).sendKeys('strike');\n         element(by.model('style3')).sendKeys('red');\n         expect(ps.last().getAttribute('class')).toBe('bold strike red');\n       });\n     </file>\n   </example>\n\n   ## Animations\n\n   The example below demonstrates how to perform animations using ngClass.\n\n   <example module=\"ngAnimate\" deps=\"angular-animate.js\" animations=\"true\">\n     <file name=\"index.html\">\n      <input id=\"setbtn\" type=\"button\" value=\"set\" ng-click=\"myVar='my-class'\">\n      <input id=\"clearbtn\" type=\"button\" value=\"clear\" ng-click=\"myVar=''\">\n      <br>\n      <span class=\"base-class\" ng-class=\"myVar\">Sample Text</span>\n     </file>\n     <file name=\"style.css\">\n       .base-class {\n         -webkit-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;\n         transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;\n       }\n\n       .base-class.my-class {\n         color: red;\n         font-size:3em;\n       }\n     </file>\n     <file name=\"protractor.js\" type=\"protractor\">\n       it('should check ng-class', function() {\n         expect(element(by.css('.base-class')).getAttribute('class')).not.\n           toMatch(/my-class/);\n\n         element(by.id('setbtn')).click();\n\n         expect(element(by.css('.base-class')).getAttribute('class')).\n           toMatch(/my-class/);\n\n         element(by.id('clearbtn')).click();\n\n         expect(element(by.css('.base-class')).getAttribute('class')).not.\n           toMatch(/my-class/);\n       });\n     </file>\n   </example>\n\n\n   ## ngClass and pre-existing CSS3 Transitions/Animations\n   The ngClass directive still supports CSS3 Transitions/Animations even if they do not follow the ngAnimate CSS naming structure.\n   Upon animation ngAnimate will apply supplementary CSS classes to track the start and end of an animation, but this will not hinder\n   any pre-existing CSS transitions already on the element. To get an idea of what happens during a class-based animation, be sure\n   to view the step by step details of {@link ng.$animate#addClass $animate.addClass} and\n   {@link ng.$animate#removeClass $animate.removeClass}.\n */\nvar ngClassDirective = classDirective('', true);\n\n/**\n * @ngdoc directive\n * @name ngClassOdd\n * @restrict AC\n *\n * @description\n * The `ngClassOdd` and `ngClassEven` directives work exactly as\n * {@link ng.directive:ngClass ngClass}, except they work in\n * conjunction with `ngRepeat` and take effect only on odd (even) rows.\n *\n * This directive can be applied only within the scope of an\n * {@link ng.directive:ngRepeat ngRepeat}.\n *\n * @element ANY\n * @param {expression} ngClassOdd {@link guide/expression Expression} to eval. The result\n *   of the evaluation can be a string representing space delimited class names or an array.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <ol ng-init=\"names=['John', 'Mary', 'Cate', 'Suz']\">\n          <li ng-repeat=\"name in names\">\n           <span ng-class-odd=\"'odd'\" ng-class-even=\"'even'\">\n             {{name}}\n           </span>\n          </li>\n        </ol>\n     </file>\n     <file name=\"style.css\">\n       .odd {\n         color: red;\n       }\n       .even {\n         color: blue;\n       }\n     </file>\n     <file name=\"protractor.js\" type=\"protractor\">\n       it('should check ng-class-odd and ng-class-even', function() {\n         expect(element(by.repeater('name in names').row(0).column('name')).getAttribute('class')).\n           toMatch(/odd/);\n         expect(element(by.repeater('name in names').row(1).column('name')).getAttribute('class')).\n           toMatch(/even/);\n       });\n     </file>\n   </example>\n */\nvar ngClassOddDirective = classDirective('Odd', 0);\n\n/**\n * @ngdoc directive\n * @name ngClassEven\n * @restrict AC\n *\n * @description\n * The `ngClassOdd` and `ngClassEven` directives work exactly as\n * {@link ng.directive:ngClass ngClass}, except they work in\n * conjunction with `ngRepeat` and take effect only on odd (even) rows.\n *\n * This directive can be applied only within the scope of an\n * {@link ng.directive:ngRepeat ngRepeat}.\n *\n * @element ANY\n * @param {expression} ngClassEven {@link guide/expression Expression} to eval. The\n *   result of the evaluation can be a string representing space delimited class names or an array.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <ol ng-init=\"names=['John', 'Mary', 'Cate', 'Suz']\">\n          <li ng-repeat=\"name in names\">\n           <span ng-class-odd=\"'odd'\" ng-class-even=\"'even'\">\n             {{name}} &nbsp; &nbsp; &nbsp;\n           </span>\n          </li>\n        </ol>\n     </file>\n     <file name=\"style.css\">\n       .odd {\n         color: red;\n       }\n       .even {\n         color: blue;\n       }\n     </file>\n     <file name=\"protractor.js\" type=\"protractor\">\n       it('should check ng-class-odd and ng-class-even', function() {\n         expect(element(by.repeater('name in names').row(0).column('name')).getAttribute('class')).\n           toMatch(/odd/);\n         expect(element(by.repeater('name in names').row(1).column('name')).getAttribute('class')).\n           toMatch(/even/);\n       });\n     </file>\n   </example>\n */\nvar ngClassEvenDirective = classDirective('Even', 1);\n\n/**\n * @ngdoc directive\n * @name ngCloak\n * @restrict AC\n *\n * @description\n * The `ngCloak` directive is used to prevent the Angular html template from being briefly\n * displayed by the browser in its raw (uncompiled) form while your application is loading. Use this\n * directive to avoid the undesirable flicker effect caused by the html template display.\n *\n * The directive can be applied to the `<body>` element, but the preferred usage is to apply\n * multiple `ngCloak` directives to small portions of the page to permit progressive rendering\n * of the browser view.\n *\n * `ngCloak` works in cooperation with the following css rule embedded within `angular.js` and\n * `angular.min.js`.\n * For CSP mode please add `angular-csp.css` to your html file (see {@link ng.directive:ngCsp ngCsp}).\n *\n * ```css\n * [ng\\:cloak], [ng-cloak], [data-ng-cloak], [x-ng-cloak], .ng-cloak, .x-ng-cloak {\n *   display: none !important;\n * }\n * ```\n *\n * When this css rule is loaded by the browser, all html elements (including their children) that\n * are tagged with the `ngCloak` directive are hidden. When Angular encounters this directive\n * during the compilation of the template it deletes the `ngCloak` element attribute, making\n * the compiled element visible.\n *\n * For the best result, the `angular.js` script must be loaded in the head section of the html\n * document; alternatively, the css rule above must be included in the external stylesheet of the\n * application.\n *\n * Legacy browsers, like IE7, do not provide attribute selector support (added in CSS 2.1) so they\n * cannot match the `[ng\\:cloak]` selector. To work around this limitation, you must add the css\n * class `ng-cloak` in addition to the `ngCloak` directive as shown in the example below.\n *\n * @element ANY\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <div id=\"template1\" ng-cloak>{{ 'hello' }}</div>\n        <div id=\"template2\" ng-cloak class=\"ng-cloak\">{{ 'hello IE7' }}</div>\n     </file>\n     <file name=\"protractor.js\" type=\"protractor\">\n       it('should remove the template directive and css class', function() {\n         expect($('#template1').getAttribute('ng-cloak')).\n           toBeNull();\n         expect($('#template2').getAttribute('ng-cloak')).\n           toBeNull();\n       });\n     </file>\n   </example>\n *\n */\nvar ngCloakDirective = ngDirective({\n  compile: function(element, attr) {\n    attr.$set('ngCloak', undefined);\n    element.removeClass('ng-cloak');\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ngController\n *\n * @description\n * The `ngController` directive attaches a controller class to the view. This is a key aspect of how angular\n * supports the principles behind the Model-View-Controller design pattern.\n *\n * MVC components in angular:\n *\n * * Model — Models are the properties of a scope; scopes are attached to the DOM where scope properties\n *   are accessed through bindings.\n * * View — The template (HTML with data bindings) that is rendered into the View.\n * * Controller — The `ngController` directive specifies a Controller class; the class contains business\n *   logic behind the application to decorate the scope with functions and values\n *\n * Note that you can also attach controllers to the DOM by declaring it in a route definition\n * via the {@link ngRoute.$route $route} service. A common mistake is to declare the controller\n * again using `ng-controller` in the template itself.  This will cause the controller to be attached\n * and executed twice.\n *\n * @element ANY\n * @scope\n * @priority 500\n * @param {expression} ngController Name of a constructor function registered with the current\n * {@link ng.$controllerProvider $controllerProvider} or an {@link guide/expression expression}\n * that on the current scope evaluates to a constructor function.\n *\n * The controller instance can be published into a scope property by specifying\n * `ng-controller=\"as propertyName\"`.\n *\n * If the current `$controllerProvider` is configured to use globals (via\n * {@link ng.$controllerProvider#allowGlobals `$controllerProvider.allowGlobals()` }), this may\n * also be the name of a globally accessible constructor function (not recommended).\n *\n * @example\n * Here is a simple form for editing user contact information. Adding, removing, clearing, and\n * greeting are methods declared on the controller (see source tab). These methods can\n * easily be called from the angular markup. Any changes to the data are automatically reflected\n * in the View without the need for a manual update.\n *\n * Two different declaration styles are included below:\n *\n * * one binds methods and properties directly onto the controller using `this`:\n * `ng-controller=\"SettingsController1 as settings\"`\n * * one injects `$scope` into the controller:\n * `ng-controller=\"SettingsController2\"`\n *\n * The second option is more common in the Angular community, and is generally used in boilerplates\n * and in this guide. However, there are advantages to binding properties directly to the controller\n * and avoiding scope.\n *\n * * Using `controller as` makes it obvious which controller you are accessing in the template when\n * multiple controllers apply to an element.\n * * If you are writing your controllers as classes you have easier access to the properties and\n * methods, which will appear on the scope, from inside the controller code.\n * * Since there is always a `.` in the bindings, you don't have to worry about prototypal\n * inheritance masking primitives.\n *\n * This example demonstrates the `controller as` syntax.\n *\n * <example name=\"ngControllerAs\" module=\"controllerAsExample\">\n *   <file name=\"index.html\">\n *    <div id=\"ctrl-as-exmpl\" ng-controller=\"SettingsController1 as settings\">\n *      Name: <input type=\"text\" ng-model=\"settings.name\"/>\n *      [ <a href=\"\" ng-click=\"settings.greet()\">greet</a> ]<br/>\n *      Contact:\n *      <ul>\n *        <li ng-repeat=\"contact in settings.contacts\">\n *          <select ng-model=\"contact.type\">\n *             <option>phone</option>\n *             <option>email</option>\n *          </select>\n *          <input type=\"text\" ng-model=\"contact.value\"/>\n *          [ <a href=\"\" ng-click=\"settings.clearContact(contact)\">clear</a>\n *          | <a href=\"\" ng-click=\"settings.removeContact(contact)\">X</a> ]\n *        </li>\n *        <li>[ <a href=\"\" ng-click=\"settings.addContact()\">add</a> ]</li>\n *     </ul>\n *    </div>\n *   </file>\n *   <file name=\"app.js\">\n *    angular.module('controllerAsExample', [])\n *      .controller('SettingsController1', SettingsController1);\n *\n *    function SettingsController1() {\n *      this.name = \"John Smith\";\n *      this.contacts = [\n *        {type: 'phone', value: '408 555 1212'},\n *        {type: 'email', value: 'john.smith@example.org'} ];\n *    }\n *\n *    SettingsController1.prototype.greet = function() {\n *      alert(this.name);\n *    };\n *\n *    SettingsController1.prototype.addContact = function() {\n *      this.contacts.push({type: 'email', value: 'yourname@example.org'});\n *    };\n *\n *    SettingsController1.prototype.removeContact = function(contactToRemove) {\n *     var index = this.contacts.indexOf(contactToRemove);\n *      this.contacts.splice(index, 1);\n *    };\n *\n *    SettingsController1.prototype.clearContact = function(contact) {\n *      contact.type = 'phone';\n *      contact.value = '';\n *    };\n *   </file>\n *   <file name=\"protractor.js\" type=\"protractor\">\n *     it('should check controller as', function() {\n *       var container = element(by.id('ctrl-as-exmpl'));\n *         expect(container.element(by.model('settings.name'))\n *           .getAttribute('value')).toBe('John Smith');\n *\n *       var firstRepeat =\n *           container.element(by.repeater('contact in settings.contacts').row(0));\n *       var secondRepeat =\n *           container.element(by.repeater('contact in settings.contacts').row(1));\n *\n *       expect(firstRepeat.element(by.model('contact.value')).getAttribute('value'))\n *           .toBe('408 555 1212');\n *\n *       expect(secondRepeat.element(by.model('contact.value')).getAttribute('value'))\n *           .toBe('john.smith@example.org');\n *\n *       firstRepeat.element(by.linkText('clear')).click();\n *\n *       expect(firstRepeat.element(by.model('contact.value')).getAttribute('value'))\n *           .toBe('');\n *\n *       container.element(by.linkText('add')).click();\n *\n *       expect(container.element(by.repeater('contact in settings.contacts').row(2))\n *           .element(by.model('contact.value'))\n *           .getAttribute('value'))\n *           .toBe('yourname@example.org');\n *     });\n *   </file>\n * </example>\n *\n * This example demonstrates the \"attach to `$scope`\" style of controller.\n *\n * <example name=\"ngController\" module=\"controllerExample\">\n *  <file name=\"index.html\">\n *   <div id=\"ctrl-exmpl\" ng-controller=\"SettingsController2\">\n *     Name: <input type=\"text\" ng-model=\"name\"/>\n *     [ <a href=\"\" ng-click=\"greet()\">greet</a> ]<br/>\n *     Contact:\n *     <ul>\n *       <li ng-repeat=\"contact in contacts\">\n *         <select ng-model=\"contact.type\">\n *            <option>phone</option>\n *            <option>email</option>\n *         </select>\n *         <input type=\"text\" ng-model=\"contact.value\"/>\n *         [ <a href=\"\" ng-click=\"clearContact(contact)\">clear</a>\n *         | <a href=\"\" ng-click=\"removeContact(contact)\">X</a> ]\n *       </li>\n *       <li>[ <a href=\"\" ng-click=\"addContact()\">add</a> ]</li>\n *    </ul>\n *   </div>\n *  </file>\n *  <file name=\"app.js\">\n *   angular.module('controllerExample', [])\n *     .controller('SettingsController2', ['$scope', SettingsController2]);\n *\n *   function SettingsController2($scope) {\n *     $scope.name = \"John Smith\";\n *     $scope.contacts = [\n *       {type:'phone', value:'408 555 1212'},\n *       {type:'email', value:'john.smith@example.org'} ];\n *\n *     $scope.greet = function() {\n *       alert($scope.name);\n *     };\n *\n *     $scope.addContact = function() {\n *       $scope.contacts.push({type:'email', value:'yourname@example.org'});\n *     };\n *\n *     $scope.removeContact = function(contactToRemove) {\n *       var index = $scope.contacts.indexOf(contactToRemove);\n *       $scope.contacts.splice(index, 1);\n *     };\n *\n *     $scope.clearContact = function(contact) {\n *       contact.type = 'phone';\n *       contact.value = '';\n *     };\n *   }\n *  </file>\n *  <file name=\"protractor.js\" type=\"protractor\">\n *    it('should check controller', function() {\n *      var container = element(by.id('ctrl-exmpl'));\n *\n *      expect(container.element(by.model('name'))\n *          .getAttribute('value')).toBe('John Smith');\n *\n *      var firstRepeat =\n *          container.element(by.repeater('contact in contacts').row(0));\n *      var secondRepeat =\n *          container.element(by.repeater('contact in contacts').row(1));\n *\n *      expect(firstRepeat.element(by.model('contact.value')).getAttribute('value'))\n *          .toBe('408 555 1212');\n *      expect(secondRepeat.element(by.model('contact.value')).getAttribute('value'))\n *          .toBe('john.smith@example.org');\n *\n *      firstRepeat.element(by.linkText('clear')).click();\n *\n *      expect(firstRepeat.element(by.model('contact.value')).getAttribute('value'))\n *          .toBe('');\n *\n *      container.element(by.linkText('add')).click();\n *\n *      expect(container.element(by.repeater('contact in contacts').row(2))\n *          .element(by.model('contact.value'))\n *          .getAttribute('value'))\n *          .toBe('yourname@example.org');\n *    });\n *  </file>\n *</example>\n\n */\nvar ngControllerDirective = [function() {\n  return {\n    restrict: 'A',\n    scope: true,\n    controller: '@',\n    priority: 500\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ngCsp\n *\n * @element html\n * @description\n * Enables [CSP (Content Security Policy)](https://developer.mozilla.org/en/Security/CSP) support.\n *\n * This is necessary when developing things like Google Chrome Extensions or Universal Windows Apps.\n *\n * CSP forbids apps to use `eval` or `Function(string)` generated functions (among other things).\n * For Angular to be CSP compatible there are only two things that we need to do differently:\n *\n * - don't use `Function` constructor to generate optimized value getters\n * - don't inject custom stylesheet into the document\n *\n * AngularJS uses `Function(string)` generated functions as a speed optimization. Applying the `ngCsp`\n * directive will cause Angular to use CSP compatibility mode. When this mode is on AngularJS will\n * evaluate all expressions up to 30% slower than in non-CSP mode, but no security violations will\n * be raised.\n *\n * CSP forbids JavaScript to inline stylesheet rules. In non CSP mode Angular automatically\n * includes some CSS rules (e.g. {@link ng.directive:ngCloak ngCloak}).\n * To make those directives work in CSP mode, include the `angular-csp.css` manually.\n *\n * Angular tries to autodetect if CSP is active and automatically turn on the CSP-safe mode. This\n * autodetection however triggers a CSP error to be logged in the console:\n *\n * ```\n * Refused to evaluate a string as JavaScript because 'unsafe-eval' is not an allowed source of\n * script in the following Content Security Policy directive: \"default-src 'self'\". Note that\n * 'script-src' was not explicitly set, so 'default-src' is used as a fallback.\n * ```\n *\n * This error is harmless but annoying. To prevent the error from showing up, put the `ngCsp`\n * directive on the root element of the application or on the `angular.js` script tag, whichever\n * appears first in the html document.\n *\n * *Note: This directive is only available in the `ng-csp` and `data-ng-csp` attribute form.*\n *\n * @example\n * This example shows how to apply the `ngCsp` directive to the `html` tag.\n   ```html\n     <!doctype html>\n     <html ng-app ng-csp>\n     ...\n     ...\n     </html>\n   ```\n  * @example\n      // Note: the suffix `.csp` in the example name triggers\n      // csp mode in our http server!\n      <example name=\"example.csp\" module=\"cspExample\" ng-csp=\"true\">\n        <file name=\"index.html\">\n          <div ng-controller=\"MainController as ctrl\">\n            <div>\n              <button ng-click=\"ctrl.inc()\" id=\"inc\">Increment</button>\n              <span id=\"counter\">\n                {{ctrl.counter}}\n              </span>\n            </div>\n\n            <div>\n              <button ng-click=\"ctrl.evil()\" id=\"evil\">Evil</button>\n              <span id=\"evilError\">\n                {{ctrl.evilError}}\n              </span>\n            </div>\n          </div>\n        </file>\n        <file name=\"script.js\">\n           angular.module('cspExample', [])\n             .controller('MainController', function() {\n                this.counter = 0;\n                this.inc = function() {\n                  this.counter++;\n                };\n                this.evil = function() {\n                  // jshint evil:true\n                  try {\n                    eval('1+2');\n                  } catch (e) {\n                    this.evilError = e.message;\n                  }\n                };\n              });\n        </file>\n        <file name=\"protractor.js\" type=\"protractor\">\n          var util, webdriver;\n\n          var incBtn = element(by.id('inc'));\n          var counter = element(by.id('counter'));\n          var evilBtn = element(by.id('evil'));\n          var evilError = element(by.id('evilError'));\n\n          function getAndClearSevereErrors() {\n            return browser.manage().logs().get('browser').then(function(browserLog) {\n              return browserLog.filter(function(logEntry) {\n                return logEntry.level.value > webdriver.logging.Level.WARNING.value;\n              });\n            });\n          }\n\n          function clearErrors() {\n            getAndClearSevereErrors();\n          }\n\n          function expectNoErrors() {\n            getAndClearSevereErrors().then(function(filteredLog) {\n              expect(filteredLog.length).toEqual(0);\n              if (filteredLog.length) {\n                console.log('browser console errors: ' + util.inspect(filteredLog));\n              }\n            });\n          }\n\n          function expectError(regex) {\n            getAndClearSevereErrors().then(function(filteredLog) {\n              var found = false;\n              filteredLog.forEach(function(log) {\n                if (log.message.match(regex)) {\n                  found = true;\n                }\n              });\n              if (!found) {\n                throw new Error('expected an error that matches ' + regex);\n              }\n            });\n          }\n\n          beforeEach(function() {\n            util = require('util');\n            webdriver = require('protractor/node_modules/selenium-webdriver');\n          });\n\n          // For now, we only test on Chrome,\n          // as Safari does not load the page with Protractor's injected scripts,\n          // and Firefox webdriver always disables content security policy (#6358)\n          if (browser.params.browser !== 'chrome') {\n            return;\n          }\n\n          it('should not report errors when the page is loaded', function() {\n            // clear errors so we are not dependent on previous tests\n            clearErrors();\n            // Need to reload the page as the page is already loaded when\n            // we come here\n            browser.driver.getCurrentUrl().then(function(url) {\n              browser.get(url);\n            });\n            expectNoErrors();\n          });\n\n          it('should evaluate expressions', function() {\n            expect(counter.getText()).toEqual('0');\n            incBtn.click();\n            expect(counter.getText()).toEqual('1');\n            expectNoErrors();\n          });\n\n          it('should throw and report an error when using \"eval\"', function() {\n            evilBtn.click();\n            expect(evilError.getText()).toMatch(/Content Security Policy/);\n            expectError(/Content Security Policy/);\n          });\n        </file>\n      </example>\n  */\n\n// ngCsp is not implemented as a proper directive any more, because we need it be processed while we\n// bootstrap the system (before $parse is instantiated), for this reason we just have\n// the csp.isActive() fn that looks for ng-csp attribute anywhere in the current doc\n\n/**\n * @ngdoc directive\n * @name ngClick\n *\n * @description\n * The ngClick directive allows you to specify custom behavior when\n * an element is clicked.\n *\n * @element ANY\n * @priority 0\n * @param {expression} ngClick {@link guide/expression Expression} to evaluate upon\n * click. ({@link guide/expression#-event- Event object is available as `$event`})\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n      <button ng-click=\"count = count + 1\" ng-init=\"count=0\">\n        Increment\n      </button>\n      <span>\n        count: {{count}}\n      </span>\n     </file>\n     <file name=\"protractor.js\" type=\"protractor\">\n       it('should check ng-click', function() {\n         expect(element(by.binding('count')).getText()).toMatch('0');\n         element(by.css('button')).click();\n         expect(element(by.binding('count')).getText()).toMatch('1');\n       });\n     </file>\n   </example>\n */\n/*\n * A collection of directives that allows creation of custom event handlers that are defined as\n * angular expressions and are compiled and executed within the current scope.\n */\nvar ngEventDirectives = {};\n\n// For events that might fire synchronously during DOM manipulation\n// we need to execute their event handlers asynchronously using $evalAsync,\n// so that they are not executed in an inconsistent state.\nvar forceAsyncEvents = {\n  'blur': true,\n  'focus': true\n};\nforEach(\n  'click dblclick mousedown mouseup mouseover mouseout mousemove mouseenter mouseleave keydown keyup keypress submit focus blur copy cut paste'.split(' '),\n  function(eventName) {\n    var directiveName = directiveNormalize('ng-' + eventName);\n    ngEventDirectives[directiveName] = ['$parse', '$rootScope', function($parse, $rootScope) {\n      return {\n        restrict: 'A',\n        compile: function($element, attr) {\n          // We expose the powerful $event object on the scope that provides access to the Window,\n          // etc. that isn't protected by the fast paths in $parse.  We explicitly request better\n          // checks at the cost of speed since event handler expressions are not executed as\n          // frequently as regular change detection.\n          var fn = $parse(attr[directiveName], /* interceptorFn */ null, /* expensiveChecks */ true);\n          return function ngEventHandler(scope, element) {\n            element.on(eventName, function(event) {\n              var callback = function() {\n                fn(scope, {$event:event});\n              };\n              if (forceAsyncEvents[eventName] && $rootScope.$$phase) {\n                scope.$evalAsync(callback);\n              } else {\n                scope.$apply(callback);\n              }\n            });\n          };\n        }\n      };\n    }];\n  }\n);\n\n/**\n * @ngdoc directive\n * @name ngDblclick\n *\n * @description\n * The `ngDblclick` directive allows you to specify custom behavior on a dblclick event.\n *\n * @element ANY\n * @priority 0\n * @param {expression} ngDblclick {@link guide/expression Expression} to evaluate upon\n * a dblclick. (The Event object is available as `$event`)\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n      <button ng-dblclick=\"count = count + 1\" ng-init=\"count=0\">\n        Increment (on double click)\n      </button>\n      count: {{count}}\n     </file>\n   </example>\n */\n\n\n/**\n * @ngdoc directive\n * @name ngMousedown\n *\n * @description\n * The ngMousedown directive allows you to specify custom behavior on mousedown event.\n *\n * @element ANY\n * @priority 0\n * @param {expression} ngMousedown {@link guide/expression Expression} to evaluate upon\n * mousedown. ({@link guide/expression#-event- Event object is available as `$event`})\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n      <button ng-mousedown=\"count = count + 1\" ng-init=\"count=0\">\n        Increment (on mouse down)\n      </button>\n      count: {{count}}\n     </file>\n   </example>\n */\n\n\n/**\n * @ngdoc directive\n * @name ngMouseup\n *\n * @description\n * Specify custom behavior on mouseup event.\n *\n * @element ANY\n * @priority 0\n * @param {expression} ngMouseup {@link guide/expression Expression} to evaluate upon\n * mouseup. ({@link guide/expression#-event- Event object is available as `$event`})\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n      <button ng-mouseup=\"count = count + 1\" ng-init=\"count=0\">\n        Increment (on mouse up)\n      </button>\n      count: {{count}}\n     </file>\n   </example>\n */\n\n/**\n * @ngdoc directive\n * @name ngMouseover\n *\n * @description\n * Specify custom behavior on mouseover event.\n *\n * @element ANY\n * @priority 0\n * @param {expression} ngMouseover {@link guide/expression Expression} to evaluate upon\n * mouseover. ({@link guide/expression#-event- Event object is available as `$event`})\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n      <button ng-mouseover=\"count = count + 1\" ng-init=\"count=0\">\n        Increment (when mouse is over)\n      </button>\n      count: {{count}}\n     </file>\n   </example>\n */\n\n\n/**\n * @ngdoc directive\n * @name ngMouseenter\n *\n * @description\n * Specify custom behavior on mouseenter event.\n *\n * @element ANY\n * @priority 0\n * @param {expression} ngMouseenter {@link guide/expression Expression} to evaluate upon\n * mouseenter. ({@link guide/expression#-event- Event object is available as `$event`})\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n      <button ng-mouseenter=\"count = count + 1\" ng-init=\"count=0\">\n        Increment (when mouse enters)\n      </button>\n      count: {{count}}\n     </file>\n   </example>\n */\n\n\n/**\n * @ngdoc directive\n * @name ngMouseleave\n *\n * @description\n * Specify custom behavior on mouseleave event.\n *\n * @element ANY\n * @priority 0\n * @param {expression} ngMouseleave {@link guide/expression Expression} to evaluate upon\n * mouseleave. ({@link guide/expression#-event- Event object is available as `$event`})\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n      <button ng-mouseleave=\"count = count + 1\" ng-init=\"count=0\">\n        Increment (when mouse leaves)\n      </button>\n      count: {{count}}\n     </file>\n   </example>\n */\n\n\n/**\n * @ngdoc directive\n * @name ngMousemove\n *\n * @description\n * Specify custom behavior on mousemove event.\n *\n * @element ANY\n * @priority 0\n * @param {expression} ngMousemove {@link guide/expression Expression} to evaluate upon\n * mousemove. ({@link guide/expression#-event- Event object is available as `$event`})\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n      <button ng-mousemove=\"count = count + 1\" ng-init=\"count=0\">\n        Increment (when mouse moves)\n      </button>\n      count: {{count}}\n     </file>\n   </example>\n */\n\n\n/**\n * @ngdoc directive\n * @name ngKeydown\n *\n * @description\n * Specify custom behavior on keydown event.\n *\n * @element ANY\n * @priority 0\n * @param {expression} ngKeydown {@link guide/expression Expression} to evaluate upon\n * keydown. (Event object is available as `$event` and can be interrogated for keyCode, altKey, etc.)\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n      <input ng-keydown=\"count = count + 1\" ng-init=\"count=0\">\n      key down count: {{count}}\n     </file>\n   </example>\n */\n\n\n/**\n * @ngdoc directive\n * @name ngKeyup\n *\n * @description\n * Specify custom behavior on keyup event.\n *\n * @element ANY\n * @priority 0\n * @param {expression} ngKeyup {@link guide/expression Expression} to evaluate upon\n * keyup. (Event object is available as `$event` and can be interrogated for keyCode, altKey, etc.)\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n       <p>Typing in the input box below updates the key count</p>\n       <input ng-keyup=\"count = count + 1\" ng-init=\"count=0\"> key up count: {{count}}\n\n       <p>Typing in the input box below updates the keycode</p>\n       <input ng-keyup=\"event=$event\">\n       <p>event keyCode: {{ event.keyCode }}</p>\n       <p>event altKey: {{ event.altKey }}</p>\n     </file>\n   </example>\n */\n\n\n/**\n * @ngdoc directive\n * @name ngKeypress\n *\n * @description\n * Specify custom behavior on keypress event.\n *\n * @element ANY\n * @param {expression} ngKeypress {@link guide/expression Expression} to evaluate upon\n * keypress. ({@link guide/expression#-event- Event object is available as `$event`}\n * and can be interrogated for keyCode, altKey, etc.)\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n      <input ng-keypress=\"count = count + 1\" ng-init=\"count=0\">\n      key press count: {{count}}\n     </file>\n   </example>\n */\n\n\n/**\n * @ngdoc directive\n * @name ngSubmit\n *\n * @description\n * Enables binding angular expressions to onsubmit events.\n *\n * Additionally it prevents the default action (which for form means sending the request to the\n * server and reloading the current page), but only if the form does not contain `action`,\n * `data-action`, or `x-action` attributes.\n *\n * <div class=\"alert alert-warning\">\n * **Warning:** Be careful not to cause \"double-submission\" by using both the `ngClick` and\n * `ngSubmit` handlers together. See the\n * {@link form#submitting-a-form-and-preventing-the-default-action `form` directive documentation}\n * for a detailed discussion of when `ngSubmit` may be triggered.\n * </div>\n *\n * @element form\n * @priority 0\n * @param {expression} ngSubmit {@link guide/expression Expression} to eval.\n * ({@link guide/expression#-event- Event object is available as `$event`})\n *\n * @example\n   <example module=\"submitExample\">\n     <file name=\"index.html\">\n      <script>\n        angular.module('submitExample', [])\n          .controller('ExampleController', ['$scope', function($scope) {\n            $scope.list = [];\n            $scope.text = 'hello';\n            $scope.submit = function() {\n              if ($scope.text) {\n                $scope.list.push(this.text);\n                $scope.text = '';\n              }\n            };\n          }]);\n      </script>\n      <form ng-submit=\"submit()\" ng-controller=\"ExampleController\">\n        Enter text and hit enter:\n        <input type=\"text\" ng-model=\"text\" name=\"text\" />\n        <input type=\"submit\" id=\"submit\" value=\"Submit\" />\n        <pre>list={{list}}</pre>\n      </form>\n     </file>\n     <file name=\"protractor.js\" type=\"protractor\">\n       it('should check ng-submit', function() {\n         expect(element(by.binding('list')).getText()).toBe('list=[]');\n         element(by.css('#submit')).click();\n         expect(element(by.binding('list')).getText()).toContain('hello');\n         expect(element(by.model('text')).getAttribute('value')).toBe('');\n       });\n       it('should ignore empty strings', function() {\n         expect(element(by.binding('list')).getText()).toBe('list=[]');\n         element(by.css('#submit')).click();\n         element(by.css('#submit')).click();\n         expect(element(by.binding('list')).getText()).toContain('hello');\n        });\n     </file>\n   </example>\n */\n\n/**\n * @ngdoc directive\n * @name ngFocus\n *\n * @description\n * Specify custom behavior on focus event.\n *\n * Note: As the `focus` event is executed synchronously when calling `input.focus()`\n * AngularJS executes the expression using `scope.$evalAsync` if the event is fired\n * during an `$apply` to ensure a consistent state.\n *\n * @element window, input, select, textarea, a\n * @priority 0\n * @param {expression} ngFocus {@link guide/expression Expression} to evaluate upon\n * focus. ({@link guide/expression#-event- Event object is available as `$event`})\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n/**\n * @ngdoc directive\n * @name ngBlur\n *\n * @description\n * Specify custom behavior on blur event.\n *\n * A [blur event](https://developer.mozilla.org/en-US/docs/Web/Events/blur) fires when\n * an element has lost focus.\n *\n * Note: As the `blur` event is executed synchronously also during DOM manipulations\n * (e.g. removing a focussed input),\n * AngularJS executes the expression using `scope.$evalAsync` if the event is fired\n * during an `$apply` to ensure a consistent state.\n *\n * @element window, input, select, textarea, a\n * @priority 0\n * @param {expression} ngBlur {@link guide/expression Expression} to evaluate upon\n * blur. ({@link guide/expression#-event- Event object is available as `$event`})\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n/**\n * @ngdoc directive\n * @name ngCopy\n *\n * @description\n * Specify custom behavior on copy event.\n *\n * @element window, input, select, textarea, a\n * @priority 0\n * @param {expression} ngCopy {@link guide/expression Expression} to evaluate upon\n * copy. ({@link guide/expression#-event- Event object is available as `$event`})\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n      <input ng-copy=\"copied=true\" ng-init=\"copied=false; value='copy me'\" ng-model=\"value\">\n      copied: {{copied}}\n     </file>\n   </example>\n */\n\n/**\n * @ngdoc directive\n * @name ngCut\n *\n * @description\n * Specify custom behavior on cut event.\n *\n * @element window, input, select, textarea, a\n * @priority 0\n * @param {expression} ngCut {@link guide/expression Expression} to evaluate upon\n * cut. ({@link guide/expression#-event- Event object is available as `$event`})\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n      <input ng-cut=\"cut=true\" ng-init=\"cut=false; value='cut me'\" ng-model=\"value\">\n      cut: {{cut}}\n     </file>\n   </example>\n */\n\n/**\n * @ngdoc directive\n * @name ngPaste\n *\n * @description\n * Specify custom behavior on paste event.\n *\n * @element window, input, select, textarea, a\n * @priority 0\n * @param {expression} ngPaste {@link guide/expression Expression} to evaluate upon\n * paste. ({@link guide/expression#-event- Event object is available as `$event`})\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n      <input ng-paste=\"paste=true\" ng-init=\"paste=false\" placeholder='paste here'>\n      pasted: {{paste}}\n     </file>\n   </example>\n */\n\n/**\n * @ngdoc directive\n * @name ngIf\n * @restrict A\n *\n * @description\n * The `ngIf` directive removes or recreates a portion of the DOM tree based on an\n * {expression}. If the expression assigned to `ngIf` evaluates to a false\n * value then the element is removed from the DOM, otherwise a clone of the\n * element is reinserted into the DOM.\n *\n * `ngIf` differs from `ngShow` and `ngHide` in that `ngIf` completely removes and recreates the\n * element in the DOM rather than changing its visibility via the `display` css property.  A common\n * case when this difference is significant is when using css selectors that rely on an element's\n * position within the DOM, such as the `:first-child` or `:last-child` pseudo-classes.\n *\n * Note that when an element is removed using `ngIf` its scope is destroyed and a new scope\n * is created when the element is restored.  The scope created within `ngIf` inherits from\n * its parent scope using\n * [prototypal inheritance](https://github.com/angular/angular.js/wiki/Understanding-Scopes#javascript-prototypal-inheritance).\n * An important implication of this is if `ngModel` is used within `ngIf` to bind to\n * a javascript primitive defined in the parent scope. In this case any modifications made to the\n * variable within the child scope will override (hide) the value in the parent scope.\n *\n * Also, `ngIf` recreates elements using their compiled state. An example of this behavior\n * is if an element's class attribute is directly modified after it's compiled, using something like\n * jQuery's `.addClass()` method, and the element is later removed. When `ngIf` recreates the element\n * the added class will be lost because the original compiled state is used to regenerate the element.\n *\n * Additionally, you can provide animations via the `ngAnimate` module to animate the `enter`\n * and `leave` effects.\n *\n * @animations\n * enter - happens just after the `ngIf` contents change and a new DOM element is created and injected into the `ngIf` container\n * leave - happens just before the `ngIf` contents are removed from the DOM\n *\n * @element ANY\n * @scope\n * @priority 600\n * @param {expression} ngIf If the {@link guide/expression expression} is falsy then\n *     the element is removed from the DOM tree. If it is truthy a copy of the compiled\n *     element is added to the DOM tree.\n *\n * @example\n  <example module=\"ngAnimate\" deps=\"angular-animate.js\" animations=\"true\">\n    <file name=\"index.html\">\n      Click me: <input type=\"checkbox\" ng-model=\"checked\" ng-init=\"checked=true\" /><br/>\n      Show when checked:\n      <span ng-if=\"checked\" class=\"animate-if\">\n        This is removed when the checkbox is unchecked.\n      </span>\n    </file>\n    <file name=\"animations.css\">\n      .animate-if {\n        background:white;\n        border:1px solid black;\n        padding:10px;\n      }\n\n      .animate-if.ng-enter, .animate-if.ng-leave {\n        -webkit-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;\n        transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;\n      }\n\n      .animate-if.ng-enter,\n      .animate-if.ng-leave.ng-leave-active {\n        opacity:0;\n      }\n\n      .animate-if.ng-leave,\n      .animate-if.ng-enter.ng-enter-active {\n        opacity:1;\n      }\n    </file>\n  </example>\n */\nvar ngIfDirective = ['$animate', function($animate) {\n  return {\n    multiElement: true,\n    transclude: 'element',\n    priority: 600,\n    terminal: true,\n    restrict: 'A',\n    $$tlb: true,\n    link: function($scope, $element, $attr, ctrl, $transclude) {\n        var block, childScope, previousElements;\n        $scope.$watch($attr.ngIf, function ngIfWatchAction(value) {\n\n          if (value) {\n            if (!childScope) {\n              $transclude(function(clone, newScope) {\n                childScope = newScope;\n                clone[clone.length++] = document.createComment(' end ngIf: ' + $attr.ngIf + ' ');\n                // Note: We only need the first/last node of the cloned nodes.\n                // However, we need to keep the reference to the jqlite wrapper as it might be changed later\n                // by a directive with templateUrl when its template arrives.\n                block = {\n                  clone: clone\n                };\n                $animate.enter(clone, $element.parent(), $element);\n              });\n            }\n          } else {\n            if (previousElements) {\n              previousElements.remove();\n              previousElements = null;\n            }\n            if (childScope) {\n              childScope.$destroy();\n              childScope = null;\n            }\n            if (block) {\n              previousElements = getBlockNodes(block.clone);\n              $animate.leave(previousElements).then(function() {\n                previousElements = null;\n              });\n              block = null;\n            }\n          }\n        });\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ngInclude\n * @restrict ECA\n *\n * @description\n * Fetches, compiles and includes an external HTML fragment.\n *\n * By default, the template URL is restricted to the same domain and protocol as the\n * application document. This is done by calling {@link $sce#getTrustedResourceUrl\n * $sce.getTrustedResourceUrl} on it. To load templates from other domains or protocols\n * you may either {@link ng.$sceDelegateProvider#resourceUrlWhitelist whitelist them} or\n * {@link $sce#trustAsResourceUrl wrap them} as trusted values. Refer to Angular's {@link\n * ng.$sce Strict Contextual Escaping}.\n *\n * In addition, the browser's\n * [Same Origin Policy](https://code.google.com/p/browsersec/wiki/Part2#Same-origin_policy_for_XMLHttpRequest)\n * and [Cross-Origin Resource Sharing (CORS)](http://www.w3.org/TR/cors/)\n * policy may further restrict whether the template is successfully loaded.\n * For example, `ngInclude` won't work for cross-domain requests on all browsers and for `file://`\n * access on some browsers.\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 *\n * @param {string} ngInclude|src angular expression evaluating to URL. If the source is a string constant,\n *                 make sure you wrap it in **single** quotes, e.g. `src=\"'myPartialTemplate.html'\"`.\n * @param {string=} onload Expression to evaluate when a new partial is loaded.\n *\n * @param {string=} autoscroll Whether `ngInclude` should call {@link ng.$anchorScroll\n *                  $anchorScroll} to scroll the viewport after the content is loaded.\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 expression evaluates to truthy value.\n *\n * @example\n  <example module=\"includeExample\" deps=\"angular-animate.js\" animations=\"true\">\n    <file name=\"index.html\">\n     <div ng-controller=\"ExampleController\">\n       <select ng-model=\"template\" ng-options=\"t.name for t in templates\">\n        <option value=\"\">(blank)</option>\n       </select>\n       url of the template: <code>{{template.url}}</code>\n       <hr/>\n       <div class=\"slide-animate-container\">\n         <div class=\"slide-animate\" ng-include=\"template.url\"></div>\n       </div>\n     </div>\n    </file>\n    <file name=\"script.js\">\n      angular.module('includeExample', ['ngAnimate'])\n        .controller('ExampleController', ['$scope', function($scope) {\n          $scope.templates =\n            [ { name: 'template1.html', url: 'template1.html'},\n              { name: 'template2.html', url: 'template2.html'} ];\n          $scope.template = $scope.templates[0];\n        }]);\n     </file>\n    <file name=\"template1.html\">\n      Content of template1.html\n    </file>\n    <file name=\"template2.html\">\n      Content of template2.html\n    </file>\n    <file name=\"animations.css\">\n      .slide-animate-container {\n        position:relative;\n        background:white;\n        border:1px solid black;\n        height:40px;\n        overflow:hidden;\n      }\n\n      .slide-animate {\n        padding:10px;\n      }\n\n      .slide-animate.ng-enter, .slide-animate.ng-leave {\n        -webkit-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;\n        transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;\n\n        position:absolute;\n        top:0;\n        left:0;\n        right:0;\n        bottom:0;\n        display:block;\n        padding:10px;\n      }\n\n      .slide-animate.ng-enter {\n        top:-50px;\n      }\n      .slide-animate.ng-enter.ng-enter-active {\n        top:0;\n      }\n\n      .slide-animate.ng-leave {\n        top:0;\n      }\n      .slide-animate.ng-leave.ng-leave-active {\n        top:50px;\n      }\n    </file>\n    <file name=\"protractor.js\" type=\"protractor\">\n      var templateSelect = element(by.model('template'));\n      var includeElem = element(by.css('[ng-include]'));\n\n      it('should load template1.html', function() {\n        expect(includeElem.getText()).toMatch(/Content of template1.html/);\n      });\n\n      it('should load template2.html', function() {\n        if (browser.params.browser == 'firefox') {\n          // Firefox can't handle using selects\n          // See https://github.com/angular/protractor/issues/480\n          return;\n        }\n        templateSelect.click();\n        templateSelect.all(by.css('option')).get(2).click();\n        expect(includeElem.getText()).toMatch(/Content of template2.html/);\n      });\n\n      it('should change to blank', function() {\n        if (browser.params.browser == 'firefox') {\n          // Firefox can't handle using selects\n          return;\n        }\n        templateSelect.click();\n        templateSelect.all(by.css('option')).get(0).click();\n        expect(includeElem.isPresent()).toBe(false);\n      });\n    </file>\n  </example>\n */\n\n\n/**\n * @ngdoc event\n * @name ngInclude#$includeContentRequested\n * @eventType emit on the scope ngInclude was declared in\n * @description\n * Emitted every time the ngInclude content is requested.\n *\n * @param {Object} angularEvent Synthetic event object.\n * @param {String} src URL of content to load.\n */\n\n\n/**\n * @ngdoc event\n * @name ngInclude#$includeContentLoaded\n * @eventType emit on the current ngInclude scope\n * @description\n * Emitted every time the ngInclude content is reloaded.\n *\n * @param {Object} angularEvent Synthetic event object.\n * @param {String} src URL of content to load.\n */\n\n\n/**\n * @ngdoc event\n * @name ngInclude#$includeContentError\n * @eventType emit on the scope ngInclude was declared in\n * @description\n * Emitted when a template HTTP request yields an erroneous response (status < 200 || status > 299)\n *\n * @param {Object} angularEvent Synthetic event object.\n * @param {String} src URL of content to load.\n */\nvar ngIncludeDirective = ['$templateRequest', '$anchorScroll', '$animate', '$sce',\n                  function($templateRequest,   $anchorScroll,   $animate,   $sce) {\n  return {\n    restrict: 'ECA',\n    priority: 400,\n    terminal: true,\n    transclude: 'element',\n    controller: angular.noop,\n    compile: function(element, attr) {\n      var srcExp = attr.ngInclude || attr.src,\n          onloadExp = attr.onload || '',\n          autoScrollExp = attr.autoscroll;\n\n      return function(scope, $element, $attr, ctrl, $transclude) {\n        var changeCounter = 0,\n            currentScope,\n            previousElement,\n            currentElement;\n\n        var cleanupLastIncludeContent = function() {\n          if (previousElement) {\n            previousElement.remove();\n            previousElement = null;\n          }\n          if (currentScope) {\n            currentScope.$destroy();\n            currentScope = null;\n          }\n          if (currentElement) {\n            $animate.leave(currentElement).then(function() {\n              previousElement = null;\n            });\n            previousElement = currentElement;\n            currentElement = null;\n          }\n        };\n\n        scope.$watch($sce.parseAsResourceUrl(srcExp), function ngIncludeWatchAction(src) {\n          var afterAnimation = function() {\n            if (isDefined(autoScrollExp) && (!autoScrollExp || scope.$eval(autoScrollExp))) {\n              $anchorScroll();\n            }\n          };\n          var thisChangeId = ++changeCounter;\n\n          if (src) {\n            //set the 2nd param to true to ignore the template request error so that the inner\n            //contents and scope can be cleaned up.\n            $templateRequest(src, true).then(function(response) {\n              if (thisChangeId !== changeCounter) return;\n              var newScope = scope.$new();\n              ctrl.template = response;\n\n              // Note: This will also link all children of ng-include that were contained in the original\n              // html. If that content contains controllers, ... they could pollute/change the scope.\n              // However, using ng-include 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                cleanupLastIncludeContent();\n                $animate.enter(clone, null, $element).then(afterAnimation);\n              });\n\n              currentScope = newScope;\n              currentElement = clone;\n\n              currentScope.$emit('$includeContentLoaded', src);\n              scope.$eval(onloadExp);\n            }, function() {\n              if (thisChangeId === changeCounter) {\n                cleanupLastIncludeContent();\n                scope.$emit('$includeContentError', src);\n              }\n            });\n            scope.$emit('$includeContentRequested', src);\n          } else {\n            cleanupLastIncludeContent();\n            ctrl.template = null;\n          }\n        });\n      };\n    }\n  };\n}];\n\n// This directive is called during the $transclude call of the first `ngInclude` 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 ngInclude\n// is called.\nvar ngIncludeFillContentDirective = ['$compile',\n  function($compile) {\n    return {\n      restrict: 'ECA',\n      priority: -400,\n      require: 'ngInclude',\n      link: function(scope, $element, $attr, ctrl) {\n        if (/SVG/.test($element[0].toString())) {\n          // WebKit: https://bugs.webkit.org/show_bug.cgi?id=135698 --- SVG elements do not\n          // support innerHTML, so detect this here and try to generate the contents\n          // specially.\n          $element.empty();\n          $compile(jqLiteBuildFragment(ctrl.template, document).childNodes)(scope,\n              function namespaceAdaptedClone(clone) {\n            $element.append(clone);\n          }, {futureParentElement: $element});\n          return;\n        }\n\n        $element.html(ctrl.template);\n        $compile($element.contents())(scope);\n      }\n    };\n  }];\n\n/**\n * @ngdoc directive\n * @name ngInit\n * @restrict AC\n *\n * @description\n * The `ngInit` directive allows you to evaluate an expression in the\n * current scope.\n *\n * <div class=\"alert alert-error\">\n * The only appropriate use of `ngInit` is for aliasing special properties of\n * {@link ng.directive:ngRepeat `ngRepeat`}, as seen in the demo below. Besides this case, you\n * should use {@link guide/controller controllers} rather than `ngInit`\n * to initialize values on a scope.\n * </div>\n * <div class=\"alert alert-warning\">\n * **Note**: If you have assignment in `ngInit` along with {@link ng.$filter `$filter`}, make\n * sure you have parenthesis for correct precedence:\n * <pre class=\"prettyprint\">\n * `<div ng-init=\"test1 = (data | orderBy:'name')\"></div>`\n * </pre>\n * </div>\n *\n * @priority 450\n *\n * @element ANY\n * @param {expression} ngInit {@link guide/expression Expression} to eval.\n *\n * @example\n   <example module=\"initExample\">\n     <file name=\"index.html\">\n   <script>\n     angular.module('initExample', [])\n       .controller('ExampleController', ['$scope', function($scope) {\n         $scope.list = [['a', 'b'], ['c', 'd']];\n       }]);\n   </script>\n   <div ng-controller=\"ExampleController\">\n     <div ng-repeat=\"innerList in list\" ng-init=\"outerIndex = $index\">\n       <div ng-repeat=\"value in innerList\" ng-init=\"innerIndex = $index\">\n          <span class=\"example-init\">list[ {{outerIndex}} ][ {{innerIndex}} ] = {{value}};</span>\n       </div>\n     </div>\n   </div>\n     </file>\n     <file name=\"protractor.js\" type=\"protractor\">\n       it('should alias index positions', function() {\n         var elements = element.all(by.css('.example-init'));\n         expect(elements.get(0).getText()).toBe('list[ 0 ][ 0 ] = a;');\n         expect(elements.get(1).getText()).toBe('list[ 0 ][ 1 ] = b;');\n         expect(elements.get(2).getText()).toBe('list[ 1 ][ 0 ] = c;');\n         expect(elements.get(3).getText()).toBe('list[ 1 ][ 1 ] = d;');\n       });\n     </file>\n   </example>\n */\nvar ngInitDirective = ngDirective({\n  priority: 450,\n  compile: function() {\n    return {\n      pre: function(scope, element, attrs) {\n        scope.$eval(attrs.ngInit);\n      }\n    };\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ngList\n *\n * @description\n * Text input that converts between a delimited string and an array of strings. The default\n * delimiter is a comma followed by a space - equivalent to `ng-list=\", \"`. You can specify a custom\n * delimiter as the value of the `ngList` attribute - for example, `ng-list=\" | \"`.\n *\n * The behaviour of the directive is affected by the use of the `ngTrim` attribute.\n * * If `ngTrim` is set to `\"false\"` then whitespace around both the separator and each\n *   list item is respected. This implies that the user of the directive is responsible for\n *   dealing with whitespace but also allows you to use whitespace as a delimiter, such as a\n *   tab or newline character.\n * * Otherwise whitespace around the delimiter is ignored when splitting (although it is respected\n *   when joining the list items back together) and whitespace around each list item is stripped\n *   before it is added to the model.\n *\n * ### Example with Validation\n *\n * <example name=\"ngList-directive\" module=\"listExample\">\n *   <file name=\"app.js\">\n *      angular.module('listExample', [])\n *        .controller('ExampleController', ['$scope', function($scope) {\n *          $scope.names = ['morpheus', 'neo', 'trinity'];\n *        }]);\n *   </file>\n *   <file name=\"index.html\">\n *    <form name=\"myForm\" ng-controller=\"ExampleController\">\n *      List: <input name=\"namesInput\" ng-model=\"names\" ng-list required>\n *      <span class=\"error\" ng-show=\"myForm.namesInput.$error.required\">\n *        Required!</span>\n *      <br>\n *      <tt>names = {{names}}</tt><br/>\n *      <tt>myForm.namesInput.$valid = {{myForm.namesInput.$valid}}</tt><br/>\n *      <tt>myForm.namesInput.$error = {{myForm.namesInput.$error}}</tt><br/>\n *      <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n *      <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n *     </form>\n *   </file>\n *   <file name=\"protractor.js\" type=\"protractor\">\n *     var listInput = element(by.model('names'));\n *     var names = element(by.exactBinding('names'));\n *     var valid = element(by.binding('myForm.namesInput.$valid'));\n *     var error = element(by.css('span.error'));\n *\n *     it('should initialize to model', function() {\n *       expect(names.getText()).toContain('[\"morpheus\",\"neo\",\"trinity\"]');\n *       expect(valid.getText()).toContain('true');\n *       expect(error.getCssValue('display')).toBe('none');\n *     });\n *\n *     it('should be invalid if empty', function() {\n *       listInput.clear();\n *       listInput.sendKeys('');\n *\n *       expect(names.getText()).toContain('');\n *       expect(valid.getText()).toContain('false');\n *       expect(error.getCssValue('display')).not.toBe('none');\n *     });\n *   </file>\n * </example>\n *\n * ### Example - splitting on whitespace\n * <example name=\"ngList-directive-newlines\">\n *   <file name=\"index.html\">\n *    <textarea ng-model=\"list\" ng-list=\"&#10;\" ng-trim=\"false\"></textarea>\n *    <pre>{{ list | json }}</pre>\n *   </file>\n *   <file name=\"protractor.js\" type=\"protractor\">\n *     it(\"should split the text by newlines\", function() {\n *       var listInput = element(by.model('list'));\n *       var output = element(by.binding('list | json'));\n *       listInput.sendKeys('abc\\ndef\\nghi');\n *       expect(output.getText()).toContain('[\\n  \"abc\",\\n  \"def\",\\n  \"ghi\"\\n]');\n *     });\n *   </file>\n * </example>\n *\n * @element input\n * @param {string=} ngList optional delimiter that should be used to split the value.\n */\nvar ngListDirective = function() {\n  return {\n    restrict: 'A',\n    priority: 100,\n    require: 'ngModel',\n    link: function(scope, element, attr, ctrl) {\n      // We want to control whitespace trimming so we use this convoluted approach\n      // to access the ngList attribute, which doesn't pre-trim the attribute\n      var ngList = element.attr(attr.$attr.ngList) || ', ';\n      var trimValues = attr.ngTrim !== 'false';\n      var separator = trimValues ? trim(ngList) : ngList;\n\n      var parse = function(viewValue) {\n        // If the viewValue is invalid (say required but empty) it will be `undefined`\n        if (isUndefined(viewValue)) return;\n\n        var list = [];\n\n        if (viewValue) {\n          forEach(viewValue.split(separator), function(value) {\n            if (value) list.push(trimValues ? trim(value) : value);\n          });\n        }\n\n        return list;\n      };\n\n      ctrl.$parsers.push(parse);\n      ctrl.$formatters.push(function(value) {\n        if (isArray(value)) {\n          return value.join(ngList);\n        }\n\n        return undefined;\n      });\n\n      // Override the standard $isEmpty because an empty array means the input is empty.\n      ctrl.$isEmpty = function(value) {\n        return !value || !value.length;\n      };\n    }\n  };\n};\n\n/* global VALID_CLASS: true,\n  INVALID_CLASS: true,\n  PRISTINE_CLASS: true,\n  DIRTY_CLASS: true,\n  UNTOUCHED_CLASS: true,\n  TOUCHED_CLASS: true,\n*/\n\nvar VALID_CLASS = 'ng-valid',\n    INVALID_CLASS = 'ng-invalid',\n    PRISTINE_CLASS = 'ng-pristine',\n    DIRTY_CLASS = 'ng-dirty',\n    UNTOUCHED_CLASS = 'ng-untouched',\n    TOUCHED_CLASS = 'ng-touched',\n    PENDING_CLASS = 'ng-pending';\n\n\nvar $ngModelMinErr = new minErr('ngModel');\n\n/**\n * @ngdoc type\n * @name ngModel.NgModelController\n *\n * @property {string} $viewValue Actual string value in the view.\n * @property {*} $modelValue The value in the model that the control is bound to.\n * @property {Array.<Function>} $parsers Array of functions to execute, as a pipeline, whenever\n       the control reads value from the DOM. The functions are called in array order, each passing\n       its return value through to the next. The last return value is forwarded to the\n       {@link ngModel.NgModelController#$validators `$validators`} collection.\n\nParsers are used to sanitize / convert the {@link ngModel.NgModelController#$viewValue\n`$viewValue`}.\n\nReturning `undefined` from a parser means a parse error occurred. In that case,\nno {@link ngModel.NgModelController#$validators `$validators`} will run and the `ngModel`\nwill be set to `undefined` unless {@link ngModelOptions `ngModelOptions.allowInvalid`}\nis set to `true`. The parse error is stored in `ngModel.$error.parse`.\n\n *\n * @property {Array.<Function>} $formatters Array of functions to execute, as a pipeline, whenever\n       the model value changes. The functions are called in reverse array order, each passing the value through to the\n       next. The last return value is used as the actual DOM value.\n       Used to format / convert values for display in the control.\n * ```js\n * function formatter(value) {\n *   if (value) {\n *     return value.toUpperCase();\n *   }\n * }\n * ngModel.$formatters.push(formatter);\n * ```\n *\n * @property {Object.<string, function>} $validators A collection of validators that are applied\n *      whenever the model value changes. The key value within the object refers to the name of the\n *      validator while the function refers to the validation operation. The validation operation is\n *      provided with the model value as an argument and must return a true or false value depending\n *      on the response of that validation.\n *\n * ```js\n * ngModel.$validators.validCharacters = function(modelValue, viewValue) {\n *   var value = modelValue || viewValue;\n *   return /[0-9]+/.test(value) &&\n *          /[a-z]+/.test(value) &&\n *          /[A-Z]+/.test(value) &&\n *          /\\W+/.test(value);\n * };\n * ```\n *\n * @property {Object.<string, function>} $asyncValidators A collection of validations that are expected to\n *      perform an asynchronous validation (e.g. a HTTP request). The validation function that is provided\n *      is expected to return a promise when it is run during the model validation process. Once the promise\n *      is delivered then the validation status will be set to true when fulfilled and false when rejected.\n *      When the asynchronous validators are triggered, each of the validators will run in parallel and the model\n *      value will only be updated once all validators have been fulfilled. As long as an asynchronous validator\n *      is unfulfilled, its key will be added to the controllers `$pending` property. Also, all asynchronous validators\n *      will only run once all synchronous validators have passed.\n *\n * Please note that if $http is used then it is important that the server returns a success HTTP response code\n * in order to fulfill the validation and a status level of `4xx` in order to reject the validation.\n *\n * ```js\n * ngModel.$asyncValidators.uniqueUsername = function(modelValue, viewValue) {\n *   var value = modelValue || viewValue;\n *\n *   // Lookup user by username\n *   return $http.get('/api/users/' + value).\n *      then(function resolved() {\n *        //username exists, this means validation fails\n *        return $q.reject('exists');\n *      }, function rejected() {\n *        //username does not exist, therefore this validation passes\n *        return true;\n *      });\n * };\n * ```\n *\n * @property {Array.<Function>} $viewChangeListeners Array of functions to execute whenever the\n *     view value has changed. It is called with no arguments, and its return value is ignored.\n *     This can be used in place of additional $watches against the model value.\n *\n * @property {Object} $error An object hash with all failing validator ids as keys.\n * @property {Object} $pending An object hash with all pending validator ids as keys.\n *\n * @property {boolean} $untouched True if control has not lost focus yet.\n * @property {boolean} $touched True if control has lost focus.\n * @property {boolean} $pristine True if user has not interacted with the control yet.\n * @property {boolean} $dirty True if user has already interacted with the control.\n * @property {boolean} $valid True if there is no error.\n * @property {boolean} $invalid True if at least one error on the control.\n * @property {string} $name The name attribute of the control.\n *\n * @description\n *\n * `NgModelController` provides API for the {@link ngModel `ngModel`} directive.\n * The controller contains services for data-binding, validation, CSS updates, and value formatting\n * and parsing. It purposefully does not contain any logic which deals with DOM rendering or\n * listening to DOM events.\n * Such DOM related logic should be provided by other directives which make use of\n * `NgModelController` for data-binding to control elements.\n * Angular provides this DOM logic for most {@link input `input`} elements.\n * At the end of this page you can find a {@link ngModel.NgModelController#custom-control-example\n * custom control example} that uses `ngModelController` to bind to `contenteditable` elements.\n *\n * @example\n * ### Custom Control Example\n * This example shows how to use `NgModelController` with a custom control to achieve\n * data-binding. Notice how different directives (`contenteditable`, `ng-model`, and `required`)\n * collaborate together to achieve the desired result.\n *\n * Note that `contenteditable` is an HTML5 attribute, which tells the browser to let the element\n * contents be edited in place by the user.  This will not work on older browsers.\n *\n * We are using the {@link ng.service:$sce $sce} service here and include the {@link ngSanitize $sanitize}\n * module to automatically remove \"bad\" content like inline event listener (e.g. `<span onclick=\"...\">`).\n * However, as we are using `$sce` the model can still decide to provide unsafe content if it marks\n * that content using the `$sce` service.\n *\n * <example name=\"NgModelController\" module=\"customControl\" deps=\"angular-sanitize.js\">\n    <file name=\"style.css\">\n      [contenteditable] {\n        border: 1px solid black;\n        background-color: white;\n        min-height: 20px;\n      }\n\n      .ng-invalid {\n        border: 1px solid red;\n      }\n\n    </file>\n    <file name=\"script.js\">\n      angular.module('customControl', ['ngSanitize']).\n        directive('contenteditable', ['$sce', function($sce) {\n          return {\n            restrict: 'A', // only activate on element attribute\n            require: '?ngModel', // get a hold of NgModelController\n            link: function(scope, element, attrs, ngModel) {\n              if (!ngModel) return; // do nothing if no ng-model\n\n              // Specify how UI should be updated\n              ngModel.$render = function() {\n                element.html($sce.getTrustedHtml(ngModel.$viewValue || ''));\n              };\n\n              // Listen for change events to enable binding\n              element.on('blur keyup change', function() {\n                scope.$evalAsync(read);\n              });\n              read(); // initialize\n\n              // Write data to the model\n              function read() {\n                var html = element.html();\n                // When we clear the content editable the browser leaves a <br> behind\n                // If strip-br attribute is provided then we strip this out\n                if ( attrs.stripBr && html == '<br>' ) {\n                  html = '';\n                }\n                ngModel.$setViewValue(html);\n              }\n            }\n          };\n        }]);\n    </file>\n    <file name=\"index.html\">\n      <form name=\"myForm\">\n       <div contenteditable\n            name=\"myWidget\" ng-model=\"userContent\"\n            strip-br=\"true\"\n            required>Change me!</div>\n        <span ng-show=\"myForm.myWidget.$error.required\">Required!</span>\n       <hr>\n       <textarea ng-model=\"userContent\"></textarea>\n      </form>\n    </file>\n    <file name=\"protractor.js\" type=\"protractor\">\n    it('should data-bind and become invalid', function() {\n      if (browser.params.browser == 'safari' || browser.params.browser == 'firefox') {\n        // SafariDriver can't handle contenteditable\n        // and Firefox driver can't clear contenteditables very well\n        return;\n      }\n      var contentEditable = element(by.css('[contenteditable]'));\n      var content = 'Change me!';\n\n      expect(contentEditable.getText()).toEqual(content);\n\n      contentEditable.clear();\n      contentEditable.sendKeys(protractor.Key.BACK_SPACE);\n      expect(contentEditable.getText()).toEqual('');\n      expect(contentEditable.getAttribute('class')).toMatch(/ng-invalid-required/);\n    });\n    </file>\n * </example>\n *\n *\n */\nvar NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$parse', '$animate', '$timeout', '$rootScope', '$q', '$interpolate',\n    function($scope, $exceptionHandler, $attr, $element, $parse, $animate, $timeout, $rootScope, $q, $interpolate) {\n  this.$viewValue = Number.NaN;\n  this.$modelValue = Number.NaN;\n  this.$$rawModelValue = undefined; // stores the parsed modelValue / model set from scope regardless of validity.\n  this.$validators = {};\n  this.$asyncValidators = {};\n  this.$parsers = [];\n  this.$formatters = [];\n  this.$viewChangeListeners = [];\n  this.$untouched = true;\n  this.$touched = false;\n  this.$pristine = true;\n  this.$dirty = false;\n  this.$valid = true;\n  this.$invalid = false;\n  this.$error = {}; // keep invalid keys here\n  this.$$success = {}; // keep valid keys here\n  this.$pending = undefined; // keep pending keys here\n  this.$name = $interpolate($attr.name || '', false)($scope);\n\n\n  var parsedNgModel = $parse($attr.ngModel),\n      parsedNgModelAssign = parsedNgModel.assign,\n      ngModelGet = parsedNgModel,\n      ngModelSet = parsedNgModelAssign,\n      pendingDebounce = null,\n      ctrl = this;\n\n  this.$$setOptions = function(options) {\n    ctrl.$options = options;\n    if (options && options.getterSetter) {\n      var invokeModelGetter = $parse($attr.ngModel + '()'),\n          invokeModelSetter = $parse($attr.ngModel + '($$$p)');\n\n      ngModelGet = function($scope) {\n        var modelValue = parsedNgModel($scope);\n        if (isFunction(modelValue)) {\n          modelValue = invokeModelGetter($scope);\n        }\n        return modelValue;\n      };\n      ngModelSet = function($scope, newValue) {\n        if (isFunction(parsedNgModel($scope))) {\n          invokeModelSetter($scope, {$$$p: ctrl.$modelValue});\n        } else {\n          parsedNgModelAssign($scope, ctrl.$modelValue);\n        }\n      };\n    } else if (!parsedNgModel.assign) {\n      throw $ngModelMinErr('nonassign', \"Expression '{0}' is non-assignable. Element: {1}\",\n          $attr.ngModel, startingTag($element));\n    }\n  };\n\n  /**\n   * @ngdoc method\n   * @name ngModel.NgModelController#$render\n   *\n   * @description\n   * Called when the view needs to be updated. It is expected that the user of the ng-model\n   * directive will implement this method.\n   *\n   * The `$render()` method is invoked in the following situations:\n   *\n   * * `$rollbackViewValue()` is called.  If we are rolling back the view value to the last\n   *   committed value then `$render()` is called to update the input control.\n   * * The value referenced by `ng-model` is changed programmatically and both the `$modelValue` and\n   *   the `$viewValue` are different to last time.\n   *\n   * Since `ng-model` does not do a deep watch, `$render()` is only invoked if the values of\n   * `$modelValue` and `$viewValue` are actually different to their previous value. If `$modelValue`\n   * or `$viewValue` are objects (rather than a string or number) then `$render()` will not be\n   * invoked if you only change a property on the objects.\n   */\n  this.$render = noop;\n\n  /**\n   * @ngdoc method\n   * @name ngModel.NgModelController#$isEmpty\n   *\n   * @description\n   * This is called when we need to determine if the value of an input is empty.\n   *\n   * For instance, the required directive does this to work out if the input has data or not.\n   *\n   * The default `$isEmpty` function checks whether the value is `undefined`, `''`, `null` or `NaN`.\n   *\n   * You can override this for input directives whose concept of being empty is different to the\n   * default. The `checkboxInputType` directive does this because in its case a value of `false`\n   * implies empty.\n   *\n   * @param {*} value The value of the input to check for emptiness.\n   * @returns {boolean} True if `value` is \"empty\".\n   */\n  this.$isEmpty = function(value) {\n    return isUndefined(value) || value === '' || value === null || value !== value;\n  };\n\n  var parentForm = $element.inheritedData('$formController') || nullFormCtrl,\n      currentValidationRunId = 0;\n\n  /**\n   * @ngdoc method\n   * @name ngModel.NgModelController#$setValidity\n   *\n   * @description\n   * Change the validity state, and notify the form.\n   *\n   * This method can be called within $parsers/$formatters or a custom validation implementation.\n   * However, in most cases it should be sufficient to use the `ngModel.$validators` and\n   * `ngModel.$asyncValidators` collections which will call `$setValidity` automatically.\n   *\n   * @param {string} validationErrorKey Name of the validator. The `validationErrorKey` will be assigned\n   *        to either `$error[validationErrorKey]` or `$pending[validationErrorKey]`\n   *        (for unfulfilled `$asyncValidators`), so that it is available for data-binding.\n   *        The `validationErrorKey` should be in camelCase and will get converted into dash-case\n   *        for class name. Example: `myError` will result in `ng-valid-my-error` and `ng-invalid-my-error`\n   *        class and can be bound to as  `{{someForm.someControl.$error.myError}}` .\n   * @param {boolean} isValid Whether the current state is valid (true), invalid (false), pending (undefined),\n   *                          or skipped (null). Pending is used for unfulfilled `$asyncValidators`.\n   *                          Skipped is used by Angular when validators do not run because of parse errors and\n   *                          when `$asyncValidators` do not run because any of the `$validators` failed.\n   */\n  addSetValidityMethod({\n    ctrl: this,\n    $element: $element,\n    set: function(object, property) {\n      object[property] = true;\n    },\n    unset: function(object, property) {\n      delete object[property];\n    },\n    parentForm: parentForm,\n    $animate: $animate\n  });\n\n  /**\n   * @ngdoc method\n   * @name ngModel.NgModelController#$setPristine\n   *\n   * @description\n   * Sets the control to its pristine state.\n   *\n   * This method can be called to remove the `ng-dirty` class and set the control to its pristine\n   * state (`ng-pristine` class). A model is considered to be pristine when the control\n   * has not been changed from when first compiled.\n   */\n  this.$setPristine = function() {\n    ctrl.$dirty = false;\n    ctrl.$pristine = true;\n    $animate.removeClass($element, DIRTY_CLASS);\n    $animate.addClass($element, PRISTINE_CLASS);\n  };\n\n  /**\n   * @ngdoc method\n   * @name ngModel.NgModelController#$setDirty\n   *\n   * @description\n   * Sets the control to its dirty state.\n   *\n   * This method can be called to remove the `ng-pristine` class and set the control to its dirty\n   * state (`ng-dirty` class). A model is considered to be dirty when the control has been changed\n   * from when first compiled.\n   */\n  this.$setDirty = function() {\n    ctrl.$dirty = true;\n    ctrl.$pristine = false;\n    $animate.removeClass($element, PRISTINE_CLASS);\n    $animate.addClass($element, DIRTY_CLASS);\n    parentForm.$setDirty();\n  };\n\n  /**\n   * @ngdoc method\n   * @name ngModel.NgModelController#$setUntouched\n   *\n   * @description\n   * Sets the control to its untouched state.\n   *\n   * This method can be called to remove the `ng-touched` class and set the control to its\n   * untouched state (`ng-untouched` class). Upon compilation, a model is set as untouched\n   * by default, however this function can be used to restore that state if the model has\n   * already been touched by the user.\n   */\n  this.$setUntouched = function() {\n    ctrl.$touched = false;\n    ctrl.$untouched = true;\n    $animate.setClass($element, UNTOUCHED_CLASS, TOUCHED_CLASS);\n  };\n\n  /**\n   * @ngdoc method\n   * @name ngModel.NgModelController#$setTouched\n   *\n   * @description\n   * Sets the control to its touched state.\n   *\n   * This method can be called to remove the `ng-untouched` class and set the control to its\n   * touched state (`ng-touched` class). A model is considered to be touched when the user has\n   * first focused the control element and then shifted focus away from the control (blur event).\n   */\n  this.$setTouched = function() {\n    ctrl.$touched = true;\n    ctrl.$untouched = false;\n    $animate.setClass($element, TOUCHED_CLASS, UNTOUCHED_CLASS);\n  };\n\n  /**\n   * @ngdoc method\n   * @name ngModel.NgModelController#$rollbackViewValue\n   *\n   * @description\n   * Cancel an update and reset the input element's value to prevent an update to the `$modelValue`,\n   * which may be caused by a pending debounced event or because the input is waiting for a some\n   * future event.\n   *\n   * If you have an input that uses `ng-model-options` to set up debounced events or events such\n   * as blur you can have a situation where there is a period when the `$viewValue`\n   * is out of synch with the ngModel's `$modelValue`.\n   *\n   * In this case, you can run into difficulties if you try to update the ngModel's `$modelValue`\n   * programmatically before these debounced/future events have resolved/occurred, because Angular's\n   * dirty checking mechanism is not able to tell whether the model has actually changed or not.\n   *\n   * The `$rollbackViewValue()` method should be called before programmatically changing the model of an\n   * input which may have such events pending. This is important in order to make sure that the\n   * input field will be updated with the new model value and any pending operations are cancelled.\n   *\n   * <example name=\"ng-model-cancel-update\" module=\"cancel-update-example\">\n   *   <file name=\"app.js\">\n   *     angular.module('cancel-update-example', [])\n   *\n   *     .controller('CancelUpdateController', ['$scope', function($scope) {\n   *       $scope.resetWithCancel = function(e) {\n   *         if (e.keyCode == 27) {\n   *           $scope.myForm.myInput1.$rollbackViewValue();\n   *           $scope.myValue = '';\n   *         }\n   *       };\n   *       $scope.resetWithoutCancel = function(e) {\n   *         if (e.keyCode == 27) {\n   *           $scope.myValue = '';\n   *         }\n   *       };\n   *     }]);\n   *   </file>\n   *   <file name=\"index.html\">\n   *     <div ng-controller=\"CancelUpdateController\">\n   *       <p>Try typing something in each input.  See that the model only updates when you\n   *          blur off the input.\n   *        </p>\n   *        <p>Now see what happens if you start typing then press the Escape key</p>\n   *\n   *       <form name=\"myForm\" ng-model-options=\"{ updateOn: 'blur' }\">\n   *         <p>With $rollbackViewValue()</p>\n   *         <input name=\"myInput1\" ng-model=\"myValue\" ng-keydown=\"resetWithCancel($event)\"><br/>\n   *         myValue: \"{{ myValue }}\"\n   *\n   *         <p>Without $rollbackViewValue()</p>\n   *         <input name=\"myInput2\" ng-model=\"myValue\" ng-keydown=\"resetWithoutCancel($event)\"><br/>\n   *         myValue: \"{{ myValue }}\"\n   *       </form>\n   *     </div>\n   *   </file>\n   * </example>\n   */\n  this.$rollbackViewValue = function() {\n    $timeout.cancel(pendingDebounce);\n    ctrl.$viewValue = ctrl.$$lastCommittedViewValue;\n    ctrl.$render();\n  };\n\n  /**\n   * @ngdoc method\n   * @name ngModel.NgModelController#$validate\n   *\n   * @description\n   * Runs each of the registered validators (first synchronous validators and then\n   * asynchronous validators).\n   * If the validity changes to invalid, the model will be set to `undefined`,\n   * unless {@link ngModelOptions `ngModelOptions.allowInvalid`} is `true`.\n   * If the validity changes to valid, it will set the model to the last available valid\n   * modelValue, i.e. either the last parsed value or the last value set from the scope.\n   */\n  this.$validate = function() {\n    // ignore $validate before model is initialized\n    if (isNumber(ctrl.$modelValue) && isNaN(ctrl.$modelValue)) {\n      return;\n    }\n\n    var viewValue = ctrl.$$lastCommittedViewValue;\n    // Note: we use the $$rawModelValue as $modelValue might have been\n    // set to undefined during a view -> model update that found validation\n    // errors. We can't parse the view here, since that could change\n    // the model although neither viewValue nor the model on the scope changed\n    var modelValue = ctrl.$$rawModelValue;\n\n    // Check if the there's a parse error, so we don't unset it accidentially\n    var parserName = ctrl.$$parserName || 'parse';\n    var parserValid = ctrl.$error[parserName] ? false : undefined;\n\n    var prevValid = ctrl.$valid;\n    var prevModelValue = ctrl.$modelValue;\n\n    var allowInvalid = ctrl.$options && ctrl.$options.allowInvalid;\n\n    ctrl.$$runValidators(parserValid, modelValue, viewValue, function(allValid) {\n      // If there was no change in validity, don't update the model\n      // This prevents changing an invalid modelValue to undefined\n      if (!allowInvalid && prevValid !== allValid) {\n        // Note: Don't check ctrl.$valid here, as we could have\n        // external validators (e.g. calculated on the server),\n        // that just call $setValidity and need the model value\n        // to calculate their validity.\n        ctrl.$modelValue = allValid ? modelValue : undefined;\n\n        if (ctrl.$modelValue !== prevModelValue) {\n          ctrl.$$writeModelToScope();\n        }\n      }\n    });\n\n  };\n\n  this.$$runValidators = function(parseValid, modelValue, viewValue, doneCallback) {\n    currentValidationRunId++;\n    var localValidationRunId = currentValidationRunId;\n\n    // check parser error\n    if (!processParseErrors(parseValid)) {\n      validationDone(false);\n      return;\n    }\n    if (!processSyncValidators()) {\n      validationDone(false);\n      return;\n    }\n    processAsyncValidators();\n\n    function processParseErrors(parseValid) {\n      var errorKey = ctrl.$$parserName || 'parse';\n      if (parseValid === undefined) {\n        setValidity(errorKey, null);\n      } else {\n        setValidity(errorKey, parseValid);\n        if (!parseValid) {\n          forEach(ctrl.$validators, function(v, name) {\n            setValidity(name, null);\n          });\n          forEach(ctrl.$asyncValidators, function(v, name) {\n            setValidity(name, null);\n          });\n          return false;\n        }\n      }\n      return true;\n    }\n\n    function processSyncValidators() {\n      var syncValidatorsValid = true;\n      forEach(ctrl.$validators, function(validator, name) {\n        var result = validator(modelValue, viewValue);\n        syncValidatorsValid = syncValidatorsValid && result;\n        setValidity(name, result);\n      });\n      if (!syncValidatorsValid) {\n        forEach(ctrl.$asyncValidators, function(v, name) {\n          setValidity(name, null);\n        });\n        return false;\n      }\n      return true;\n    }\n\n    function processAsyncValidators() {\n      var validatorPromises = [];\n      var allValid = true;\n      forEach(ctrl.$asyncValidators, function(validator, name) {\n        var promise = validator(modelValue, viewValue);\n        if (!isPromiseLike(promise)) {\n          throw $ngModelMinErr(\"$asyncValidators\",\n            \"Expected asynchronous validator to return a promise but got '{0}' instead.\", promise);\n        }\n        setValidity(name, undefined);\n        validatorPromises.push(promise.then(function() {\n          setValidity(name, true);\n        }, function(error) {\n          allValid = false;\n          setValidity(name, false);\n        }));\n      });\n      if (!validatorPromises.length) {\n        validationDone(true);\n      } else {\n        $q.all(validatorPromises).then(function() {\n          validationDone(allValid);\n        }, noop);\n      }\n    }\n\n    function setValidity(name, isValid) {\n      if (localValidationRunId === currentValidationRunId) {\n        ctrl.$setValidity(name, isValid);\n      }\n    }\n\n    function validationDone(allValid) {\n      if (localValidationRunId === currentValidationRunId) {\n\n        doneCallback(allValid);\n      }\n    }\n  };\n\n  /**\n   * @ngdoc method\n   * @name ngModel.NgModelController#$commitViewValue\n   *\n   * @description\n   * Commit a pending update to the `$modelValue`.\n   *\n   * Updates may be pending by a debounced event or because the input is waiting for a some future\n   * event defined in `ng-model-options`. this method is rarely needed as `NgModelController`\n   * usually handles calling this in response to input events.\n   */\n  this.$commitViewValue = function() {\n    var viewValue = ctrl.$viewValue;\n\n    $timeout.cancel(pendingDebounce);\n\n    // If the view value has not changed then we should just exit, except in the case where there is\n    // a native validator on the element. In this case the validation state may have changed even though\n    // the viewValue has stayed empty.\n    if (ctrl.$$lastCommittedViewValue === viewValue && (viewValue !== '' || !ctrl.$$hasNativeValidators)) {\n      return;\n    }\n    ctrl.$$lastCommittedViewValue = viewValue;\n\n    // change to dirty\n    if (ctrl.$pristine) {\n      this.$setDirty();\n    }\n    this.$$parseAndValidate();\n  };\n\n  this.$$parseAndValidate = function() {\n    var viewValue = ctrl.$$lastCommittedViewValue;\n    var modelValue = viewValue;\n    var parserValid = isUndefined(modelValue) ? undefined : true;\n\n    if (parserValid) {\n      for (var i = 0; i < ctrl.$parsers.length; i++) {\n        modelValue = ctrl.$parsers[i](modelValue);\n        if (isUndefined(modelValue)) {\n          parserValid = false;\n          break;\n        }\n      }\n    }\n    if (isNumber(ctrl.$modelValue) && isNaN(ctrl.$modelValue)) {\n      // ctrl.$modelValue has not been touched yet...\n      ctrl.$modelValue = ngModelGet($scope);\n    }\n    var prevModelValue = ctrl.$modelValue;\n    var allowInvalid = ctrl.$options && ctrl.$options.allowInvalid;\n    ctrl.$$rawModelValue = modelValue;\n\n    if (allowInvalid) {\n      ctrl.$modelValue = modelValue;\n      writeToModelIfNeeded();\n    }\n\n    // Pass the $$lastCommittedViewValue here, because the cached viewValue might be out of date.\n    // This can happen if e.g. $setViewValue is called from inside a parser\n    ctrl.$$runValidators(parserValid, modelValue, ctrl.$$lastCommittedViewValue, function(allValid) {\n      if (!allowInvalid) {\n        // Note: Don't check ctrl.$valid here, as we could have\n        // external validators (e.g. calculated on the server),\n        // that just call $setValidity and need the model value\n        // to calculate their validity.\n        ctrl.$modelValue = allValid ? modelValue : undefined;\n        writeToModelIfNeeded();\n      }\n    });\n\n    function writeToModelIfNeeded() {\n      if (ctrl.$modelValue !== prevModelValue) {\n        ctrl.$$writeModelToScope();\n      }\n    }\n  };\n\n  this.$$writeModelToScope = function() {\n    ngModelSet($scope, ctrl.$modelValue);\n    forEach(ctrl.$viewChangeListeners, function(listener) {\n      try {\n        listener();\n      } catch (e) {\n        $exceptionHandler(e);\n      }\n    });\n  };\n\n  /**\n   * @ngdoc method\n   * @name ngModel.NgModelController#$setViewValue\n   *\n   * @description\n   * Update the view value.\n   *\n   * This method should be called when an input directive want to change the view value; typically,\n   * this is done from within a DOM event handler.\n   *\n   * For example {@link ng.directive:input input} calls it when the value of the input changes and\n   * {@link ng.directive:select select} calls it when an option is selected.\n   *\n   * If the new `value` is an object (rather than a string or a number), we should make a copy of the\n   * object before passing it to `$setViewValue`.  This is because `ngModel` does not perform a deep\n   * watch of objects, it only looks for a change of identity. If you only change the property of\n   * the object then ngModel will not realise that the object has changed and will not invoke the\n   * `$parsers` and `$validators` pipelines.\n   *\n   * For this reason, you should not change properties of the copy once it has been passed to\n   * `$setViewValue`. Otherwise you may cause the model value on the scope to change incorrectly.\n   *\n   * When this method is called, the new `value` will be staged for committing through the `$parsers`\n   * and `$validators` pipelines. If there are no special {@link ngModelOptions} specified then the staged\n   * value sent directly for processing, finally to be applied to `$modelValue` and then the\n   * **expression** specified in the `ng-model` attribute.\n   *\n   * Lastly, all the registered change listeners, in the `$viewChangeListeners` list, are called.\n   *\n   * In case the {@link ng.directive:ngModelOptions ngModelOptions} directive is used with `updateOn`\n   * and the `default` trigger is not listed, all those actions will remain pending until one of the\n   * `updateOn` events is triggered on the DOM element.\n   * All these actions will be debounced if the {@link ng.directive:ngModelOptions ngModelOptions}\n   * directive is used with a custom debounce for this particular event.\n   *\n   * Note that calling this function does not trigger a `$digest`.\n   *\n   * @param {string} value Value from the view.\n   * @param {string} trigger Event that triggered the update.\n   */\n  this.$setViewValue = function(value, trigger) {\n    ctrl.$viewValue = value;\n    if (!ctrl.$options || ctrl.$options.updateOnDefault) {\n      ctrl.$$debounceViewValueCommit(trigger);\n    }\n  };\n\n  this.$$debounceViewValueCommit = function(trigger) {\n    var debounceDelay = 0,\n        options = ctrl.$options,\n        debounce;\n\n    if (options && isDefined(options.debounce)) {\n      debounce = options.debounce;\n      if (isNumber(debounce)) {\n        debounceDelay = debounce;\n      } else if (isNumber(debounce[trigger])) {\n        debounceDelay = debounce[trigger];\n      } else if (isNumber(debounce['default'])) {\n        debounceDelay = debounce['default'];\n      }\n    }\n\n    $timeout.cancel(pendingDebounce);\n    if (debounceDelay) {\n      pendingDebounce = $timeout(function() {\n        ctrl.$commitViewValue();\n      }, debounceDelay);\n    } else if ($rootScope.$$phase) {\n      ctrl.$commitViewValue();\n    } else {\n      $scope.$apply(function() {\n        ctrl.$commitViewValue();\n      });\n    }\n  };\n\n  // model -> value\n  // Note: we cannot use a normal scope.$watch as we want to detect the following:\n  // 1. scope value is 'a'\n  // 2. user enters 'b'\n  // 3. ng-change kicks in and reverts scope value to 'a'\n  //    -> scope value did not change since the last digest as\n  //       ng-change executes in apply phase\n  // 4. view should be changed back to 'a'\n  $scope.$watch(function ngModelWatch() {\n    var modelValue = ngModelGet($scope);\n\n    // if scope model value and ngModel value are out of sync\n    // TODO(perf): why not move this to the action fn?\n    if (modelValue !== ctrl.$modelValue) {\n      ctrl.$modelValue = ctrl.$$rawModelValue = modelValue;\n\n      var formatters = ctrl.$formatters,\n          idx = formatters.length;\n\n      var viewValue = modelValue;\n      while (idx--) {\n        viewValue = formatters[idx](viewValue);\n      }\n      if (ctrl.$viewValue !== viewValue) {\n        ctrl.$viewValue = ctrl.$$lastCommittedViewValue = viewValue;\n        ctrl.$render();\n\n        ctrl.$$runValidators(undefined, modelValue, viewValue, noop);\n      }\n    }\n\n    return modelValue;\n  });\n}];\n\n\n/**\n * @ngdoc directive\n * @name ngModel\n *\n * @element input\n * @priority 1\n *\n * @description\n * The `ngModel` directive binds an `input`,`select`, `textarea` (or custom form control) to a\n * property on the scope using {@link ngModel.NgModelController NgModelController},\n * which is created and exposed by this directive.\n *\n * `ngModel` is responsible for:\n *\n * - Binding the view into the model, which other directives such as `input`, `textarea` or `select`\n *   require.\n * - Providing validation behavior (i.e. required, number, email, url).\n * - Keeping the state of the control (valid/invalid, dirty/pristine, touched/untouched, validation errors).\n * - Setting related css classes on the element (`ng-valid`, `ng-invalid`, `ng-dirty`, `ng-pristine`, `ng-touched`, `ng-untouched`) including animations.\n * - Registering the control with its parent {@link ng.directive:form form}.\n *\n * Note: `ngModel` will try to bind to the property given by evaluating the expression on the\n * current scope. If the property doesn't already exist on this scope, it will be created\n * implicitly and added to the scope.\n *\n * For best practices on using `ngModel`, see:\n *\n *  - [Understanding Scopes](https://github.com/angular/angular.js/wiki/Understanding-Scopes)\n *\n * For basic examples, how to use `ngModel`, see:\n *\n *  - {@link ng.directive:input input}\n *    - {@link input[text] text}\n *    - {@link input[checkbox] checkbox}\n *    - {@link input[radio] radio}\n *    - {@link input[number] number}\n *    - {@link input[email] email}\n *    - {@link input[url] url}\n *    - {@link input[date] date}\n *    - {@link input[datetime-local] datetime-local}\n *    - {@link input[time] time}\n *    - {@link input[month] month}\n *    - {@link input[week] week}\n *  - {@link ng.directive:select select}\n *  - {@link ng.directive:textarea textarea}\n *\n * # CSS classes\n * The following CSS classes are added and removed on the associated input/select/textarea element\n * depending on the validity of the model.\n *\n *  - `ng-valid`: the model is valid\n *  - `ng-invalid`: the model is invalid\n *  - `ng-valid-[key]`: for each valid key added by `$setValidity`\n *  - `ng-invalid-[key]`: for each invalid key added by `$setValidity`\n *  - `ng-pristine`: the control hasn't been interacted with yet\n *  - `ng-dirty`: the control has been interacted with\n *  - `ng-touched`: the control has been blurred\n *  - `ng-untouched`: the control hasn't been blurred\n *  - `ng-pending`: any `$asyncValidators` are unfulfilled\n *\n * Keep in mind that ngAnimate can detect each of these classes when added and removed.\n *\n * ## Animation Hooks\n *\n * Animations within models are triggered when any of the associated CSS classes are added and removed\n * on the input element which is attached to the model. These classes are: `.ng-pristine`, `.ng-dirty`,\n * `.ng-invalid` and `.ng-valid` as well as any other validations that are performed on the model itself.\n * The animations that are triggered within ngModel are similar to how they work in ngClass and\n * animations can be hooked into using CSS transitions, keyframes as well as JS animations.\n *\n * The following example shows a simple way to utilize CSS transitions to style an input element\n * that has been rendered as invalid after it has been validated:\n *\n * <pre>\n * //be sure to include ngAnimate as a module to hook into more\n * //advanced animations\n * .my-input {\n *   transition:0.5s linear all;\n *   background: white;\n * }\n * .my-input.ng-invalid {\n *   background: red;\n *   color:white;\n * }\n * </pre>\n *\n * @example\n * <example deps=\"angular-animate.js\" animations=\"true\" fixBase=\"true\" module=\"inputExample\">\n     <file name=\"index.html\">\n       <script>\n        angular.module('inputExample', [])\n          .controller('ExampleController', ['$scope', function($scope) {\n            $scope.val = '1';\n          }]);\n       </script>\n       <style>\n         .my-input {\n           -webkit-transition:all linear 0.5s;\n           transition:all linear 0.5s;\n           background: transparent;\n         }\n         .my-input.ng-invalid {\n           color:white;\n           background: red;\n         }\n       </style>\n       Update input to see transitions when valid/invalid.\n       Integer is a valid value.\n       <form name=\"testForm\" ng-controller=\"ExampleController\">\n         <input ng-model=\"val\" ng-pattern=\"/^\\d+$/\" name=\"anim\" class=\"my-input\" />\n       </form>\n     </file>\n * </example>\n *\n * ## Binding to a getter/setter\n *\n * Sometimes it's helpful to bind `ngModel` to a getter/setter function.  A getter/setter is a\n * function that returns a representation of the model when called with zero arguments, and sets\n * the internal state of a model when called with an argument. It's sometimes useful to use this\n * for models that have an internal representation that's different than what the model exposes\n * to the view.\n *\n * <div class=\"alert alert-success\">\n * **Best Practice:** It's best to keep getters fast because Angular is likely to call them more\n * frequently than other parts of your code.\n * </div>\n *\n * You use this behavior by adding `ng-model-options=\"{ getterSetter: true }\"` to an element that\n * has `ng-model` attached to it. You can also add `ng-model-options=\"{ getterSetter: true }\"` to\n * a `<form>`, which will enable this behavior for all `<input>`s within it. See\n * {@link ng.directive:ngModelOptions `ngModelOptions`} for more.\n *\n * The following example shows how to use `ngModel` with a getter/setter:\n *\n * @example\n * <example name=\"ngModel-getter-setter\" module=\"getterSetterExample\">\n     <file name=\"index.html\">\n       <div ng-controller=\"ExampleController\">\n         <form name=\"userForm\">\n           Name:\n           <input type=\"text\" name=\"userName\"\n                  ng-model=\"user.name\"\n                  ng-model-options=\"{ getterSetter: true }\" />\n         </form>\n         <pre>user.name = <span ng-bind=\"user.name()\"></span></pre>\n       </div>\n     </file>\n     <file name=\"app.js\">\n       angular.module('getterSetterExample', [])\n         .controller('ExampleController', ['$scope', function($scope) {\n           var _name = 'Brian';\n           $scope.user = {\n             name: function(newName) {\n               if (angular.isDefined(newName)) {\n                 _name = newName;\n               }\n               return _name;\n             }\n           };\n         }]);\n     </file>\n * </example>\n */\nvar ngModelDirective = ['$rootScope', function($rootScope) {\n  return {\n    restrict: 'A',\n    require: ['ngModel', '^?form', '^?ngModelOptions'],\n    controller: NgModelController,\n    // Prelink needs to run before any input directive\n    // so that we can set the NgModelOptions in NgModelController\n    // before anyone else uses it.\n    priority: 1,\n    compile: function ngModelCompile(element) {\n      // Setup initial state of the control\n      element.addClass(PRISTINE_CLASS).addClass(UNTOUCHED_CLASS).addClass(VALID_CLASS);\n\n      return {\n        pre: function ngModelPreLink(scope, element, attr, ctrls) {\n          var modelCtrl = ctrls[0],\n              formCtrl = ctrls[1] || nullFormCtrl;\n\n          modelCtrl.$$setOptions(ctrls[2] && ctrls[2].$options);\n\n          // notify others, especially parent forms\n          formCtrl.$addControl(modelCtrl);\n\n          attr.$observe('name', function(newValue) {\n            if (modelCtrl.$name !== newValue) {\n              formCtrl.$$renameControl(modelCtrl, newValue);\n            }\n          });\n\n          scope.$on('$destroy', function() {\n            formCtrl.$removeControl(modelCtrl);\n          });\n        },\n        post: function ngModelPostLink(scope, element, attr, ctrls) {\n          var modelCtrl = ctrls[0];\n          if (modelCtrl.$options && modelCtrl.$options.updateOn) {\n            element.on(modelCtrl.$options.updateOn, function(ev) {\n              modelCtrl.$$debounceViewValueCommit(ev && ev.type);\n            });\n          }\n\n          element.on('blur', function(ev) {\n            if (modelCtrl.$touched) return;\n\n            if ($rootScope.$$phase) {\n              scope.$evalAsync(modelCtrl.$setTouched);\n            } else {\n              scope.$apply(modelCtrl.$setTouched);\n            }\n          });\n        }\n      };\n    }\n  };\n}];\n\nvar DEFAULT_REGEXP = /(\\s+|^)default(\\s+|$)/;\n\n/**\n * @ngdoc directive\n * @name ngModelOptions\n *\n * @description\n * Allows tuning how model updates are done. Using `ngModelOptions` you can specify a custom list of\n * events that will trigger a model update and/or a debouncing delay so that the actual update only\n * takes place when a timer expires; this timer will be reset after another change takes place.\n *\n * Given the nature of `ngModelOptions`, the value displayed inside input fields in the view might\n * be different than the value in the actual model. This means that if you update the model you\n * should also invoke {@link ngModel.NgModelController `$rollbackViewValue`} on the relevant input field in\n * order to make sure it is synchronized with the model and that any debounced action is canceled.\n *\n * The easiest way to reference the control's {@link ngModel.NgModelController `$rollbackViewValue`}\n * method is by making sure the input is placed inside a form that has a `name` attribute. This is\n * important because `form` controllers are published to the related scope under the name in their\n * `name` attribute.\n *\n * Any pending changes will take place immediately when an enclosing form is submitted via the\n * `submit` event. Note that `ngClick` events will occur before the model is updated. Use `ngSubmit`\n * to have access to the updated model.\n *\n * `ngModelOptions` has an effect on the element it's declared on and its descendants.\n *\n * @param {Object} ngModelOptions options to apply to the current model. Valid keys are:\n *   - `updateOn`: string specifying which event should the input be bound to. You can set several\n *     events using an space delimited list. There is a special event called `default` that\n *     matches the default events belonging of the control.\n *   - `debounce`: integer value which contains the debounce model update value in milliseconds. A\n *     value of 0 triggers an immediate update. If an object is supplied instead, you can specify a\n *     custom value for each event. For example:\n *     `ng-model-options=\"{ updateOn: 'default blur', debounce: {'default': 500, 'blur': 0} }\"`\n *   - `allowInvalid`: boolean value which indicates that the model can be set with values that did\n *     not validate correctly instead of the default behavior of setting the model to undefined.\n *   - `getterSetter`: boolean value which determines whether or not to treat functions bound to\n       `ngModel` as getters/setters.\n *   - `timezone`: Defines the timezone to be used to read/write the `Date` instance in the model for\n *     `<input type=\"date\">`, `<input type=\"time\">`, ... . Right now, the only supported value is `'UTC'`,\n *     otherwise the default timezone of the browser will be used.\n *\n * @example\n\n  The following example shows how to override immediate updates. Changes on the inputs within the\n  form will update the model only when the control loses focus (blur event). If `escape` key is\n  pressed while the input field is focused, the value is reset to the value in the current model.\n\n  <example name=\"ngModelOptions-directive-blur\" module=\"optionsExample\">\n    <file name=\"index.html\">\n      <div ng-controller=\"ExampleController\">\n        <form name=\"userForm\">\n          Name:\n          <input type=\"text\" name=\"userName\"\n                 ng-model=\"user.name\"\n                 ng-model-options=\"{ updateOn: 'blur' }\"\n                 ng-keyup=\"cancel($event)\" /><br />\n\n          Other data:\n          <input type=\"text\" ng-model=\"user.data\" /><br />\n        </form>\n        <pre>user.name = <span ng-bind=\"user.name\"></span></pre>\n      </div>\n    </file>\n    <file name=\"app.js\">\n      angular.module('optionsExample', [])\n        .controller('ExampleController', ['$scope', function($scope) {\n          $scope.user = { name: 'say', data: '' };\n\n          $scope.cancel = function(e) {\n            if (e.keyCode == 27) {\n              $scope.userForm.userName.$rollbackViewValue();\n            }\n          };\n        }]);\n    </file>\n    <file name=\"protractor.js\" type=\"protractor\">\n      var model = element(by.binding('user.name'));\n      var input = element(by.model('user.name'));\n      var other = element(by.model('user.data'));\n\n      it('should allow custom events', function() {\n        input.sendKeys(' hello');\n        input.click();\n        expect(model.getText()).toEqual('say');\n        other.click();\n        expect(model.getText()).toEqual('say hello');\n      });\n\n      it('should $rollbackViewValue when model changes', function() {\n        input.sendKeys(' hello');\n        expect(input.getAttribute('value')).toEqual('say hello');\n        input.sendKeys(protractor.Key.ESCAPE);\n        expect(input.getAttribute('value')).toEqual('say');\n        other.click();\n        expect(model.getText()).toEqual('say');\n      });\n    </file>\n  </example>\n\n  This one shows how to debounce model changes. Model will be updated only 1 sec after last change.\n  If the `Clear` button is pressed, any debounced action is canceled and the value becomes empty.\n\n  <example name=\"ngModelOptions-directive-debounce\" module=\"optionsExample\">\n    <file name=\"index.html\">\n      <div ng-controller=\"ExampleController\">\n        <form name=\"userForm\">\n          Name:\n          <input type=\"text\" name=\"userName\"\n                 ng-model=\"user.name\"\n                 ng-model-options=\"{ debounce: 1000 }\" />\n          <button ng-click=\"userForm.userName.$rollbackViewValue(); user.name=''\">Clear</button><br />\n        </form>\n        <pre>user.name = <span ng-bind=\"user.name\"></span></pre>\n      </div>\n    </file>\n    <file name=\"app.js\">\n      angular.module('optionsExample', [])\n        .controller('ExampleController', ['$scope', function($scope) {\n          $scope.user = { name: 'say' };\n        }]);\n    </file>\n  </example>\n\n  This one shows how to bind to getter/setters:\n\n  <example name=\"ngModelOptions-directive-getter-setter\" module=\"getterSetterExample\">\n    <file name=\"index.html\">\n      <div ng-controller=\"ExampleController\">\n        <form name=\"userForm\">\n          Name:\n          <input type=\"text\" name=\"userName\"\n                 ng-model=\"user.name\"\n                 ng-model-options=\"{ getterSetter: true }\" />\n        </form>\n        <pre>user.name = <span ng-bind=\"user.name()\"></span></pre>\n      </div>\n    </file>\n    <file name=\"app.js\">\n      angular.module('getterSetterExample', [])\n        .controller('ExampleController', ['$scope', function($scope) {\n          var _name = 'Brian';\n          $scope.user = {\n            name: function(newName) {\n              return angular.isDefined(newName) ? (_name = newName) : _name;\n            }\n          };\n        }]);\n    </file>\n  </example>\n */\nvar ngModelOptionsDirective = function() {\n  return {\n    restrict: 'A',\n    controller: ['$scope', '$attrs', function($scope, $attrs) {\n      var that = this;\n      this.$options = $scope.$eval($attrs.ngModelOptions);\n      // Allow adding/overriding bound events\n      if (this.$options.updateOn !== undefined) {\n        this.$options.updateOnDefault = false;\n        // extract \"default\" pseudo-event from list of events that can trigger a model update\n        this.$options.updateOn = trim(this.$options.updateOn.replace(DEFAULT_REGEXP, function() {\n          that.$options.updateOnDefault = true;\n          return ' ';\n        }));\n      } else {\n        this.$options.updateOnDefault = true;\n      }\n    }]\n  };\n};\n\n\n\n// helper methods\nfunction addSetValidityMethod(context) {\n  var ctrl = context.ctrl,\n      $element = context.$element,\n      classCache = {},\n      set = context.set,\n      unset = context.unset,\n      parentForm = context.parentForm,\n      $animate = context.$animate;\n\n  classCache[INVALID_CLASS] = !(classCache[VALID_CLASS] = $element.hasClass(VALID_CLASS));\n\n  ctrl.$setValidity = setValidity;\n\n  function setValidity(validationErrorKey, state, controller) {\n    if (state === undefined) {\n      createAndSet('$pending', validationErrorKey, controller);\n    } else {\n      unsetAndCleanup('$pending', validationErrorKey, controller);\n    }\n    if (!isBoolean(state)) {\n      unset(ctrl.$error, validationErrorKey, controller);\n      unset(ctrl.$$success, validationErrorKey, controller);\n    } else {\n      if (state) {\n        unset(ctrl.$error, validationErrorKey, controller);\n        set(ctrl.$$success, validationErrorKey, controller);\n      } else {\n        set(ctrl.$error, validationErrorKey, controller);\n        unset(ctrl.$$success, validationErrorKey, controller);\n      }\n    }\n    if (ctrl.$pending) {\n      cachedToggleClass(PENDING_CLASS, true);\n      ctrl.$valid = ctrl.$invalid = undefined;\n      toggleValidationCss('', null);\n    } else {\n      cachedToggleClass(PENDING_CLASS, false);\n      ctrl.$valid = isObjectEmpty(ctrl.$error);\n      ctrl.$invalid = !ctrl.$valid;\n      toggleValidationCss('', ctrl.$valid);\n    }\n\n    // re-read the state as the set/unset methods could have\n    // combined state in ctrl.$error[validationError] (used for forms),\n    // where setting/unsetting only increments/decrements the value,\n    // and does not replace it.\n    var combinedState;\n    if (ctrl.$pending && ctrl.$pending[validationErrorKey]) {\n      combinedState = undefined;\n    } else if (ctrl.$error[validationErrorKey]) {\n      combinedState = false;\n    } else if (ctrl.$$success[validationErrorKey]) {\n      combinedState = true;\n    } else {\n      combinedState = null;\n    }\n\n    toggleValidationCss(validationErrorKey, combinedState);\n    parentForm.$setValidity(validationErrorKey, combinedState, ctrl);\n  }\n\n  function createAndSet(name, value, controller) {\n    if (!ctrl[name]) {\n      ctrl[name] = {};\n    }\n    set(ctrl[name], value, controller);\n  }\n\n  function unsetAndCleanup(name, value, controller) {\n    if (ctrl[name]) {\n      unset(ctrl[name], value, controller);\n    }\n    if (isObjectEmpty(ctrl[name])) {\n      ctrl[name] = undefined;\n    }\n  }\n\n  function cachedToggleClass(className, switchValue) {\n    if (switchValue && !classCache[className]) {\n      $animate.addClass($element, className);\n      classCache[className] = true;\n    } else if (!switchValue && classCache[className]) {\n      $animate.removeClass($element, className);\n      classCache[className] = false;\n    }\n  }\n\n  function toggleValidationCss(validationErrorKey, isValid) {\n    validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : '';\n\n    cachedToggleClass(VALID_CLASS + validationErrorKey, isValid === true);\n    cachedToggleClass(INVALID_CLASS + validationErrorKey, isValid === false);\n  }\n}\n\nfunction isObjectEmpty(obj) {\n  if (obj) {\n    for (var prop in obj) {\n      return false;\n    }\n  }\n  return true;\n}\n\n/**\n * @ngdoc directive\n * @name ngNonBindable\n * @restrict AC\n * @priority 1000\n *\n * @description\n * The `ngNonBindable` directive tells Angular not to compile or bind the contents of the current\n * DOM element. This is useful if the element contains what appears to be Angular directives and\n * bindings but which should be ignored by Angular. This could be the case if you have a site that\n * displays snippets of code, for instance.\n *\n * @element ANY\n *\n * @example\n * In this example there are two locations where a simple interpolation binding (`{{}}`) is present,\n * but the one wrapped in `ngNonBindable` is left alone.\n *\n * @example\n    <example>\n      <file name=\"index.html\">\n        <div>Normal: {{1 + 2}}</div>\n        <div ng-non-bindable>Ignored: {{1 + 2}}</div>\n      </file>\n      <file name=\"protractor.js\" type=\"protractor\">\n       it('should check ng-non-bindable', function() {\n         expect(element(by.binding('1 + 2')).getText()).toContain('3');\n         expect(element.all(by.css('div')).last().getText()).toMatch(/1 \\+ 2/);\n       });\n      </file>\n    </example>\n */\nvar ngNonBindableDirective = ngDirective({ terminal: true, priority: 1000 });\n\n/**\n * @ngdoc directive\n * @name ngPluralize\n * @restrict EA\n *\n * @description\n * `ngPluralize` is a directive that displays messages according to en-US localization rules.\n * These rules are bundled with angular.js, but can be overridden\n * (see {@link guide/i18n Angular i18n} dev guide). You configure ngPluralize directive\n * by specifying the mappings between\n * [plural categories](http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html)\n * and the strings to be displayed.\n *\n * # Plural categories and explicit number rules\n * There are two\n * [plural categories](http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html)\n * in Angular's default en-US locale: \"one\" and \"other\".\n *\n * While a plural category may match many numbers (for example, in en-US locale, \"other\" can match\n * any number that is not 1), an explicit number rule can only match one number. For example, the\n * explicit number rule for \"3\" matches the number 3. There are examples of plural categories\n * and explicit number rules throughout the rest of this documentation.\n *\n * # Configuring ngPluralize\n * You configure ngPluralize by providing 2 attributes: `count` and `when`.\n * You can also provide an optional attribute, `offset`.\n *\n * The value of the `count` attribute can be either a string or an {@link guide/expression\n * Angular expression}; these are evaluated on the current scope for its bound value.\n *\n * The `when` attribute specifies the mappings between plural categories and the actual\n * string to be displayed. The value of the attribute should be a JSON object.\n *\n * The following example shows how to configure ngPluralize:\n *\n * ```html\n * <ng-pluralize count=\"personCount\"\n                 when=\"{'0': 'Nobody is viewing.',\n *                      'one': '1 person is viewing.',\n *                      'other': '{} people are viewing.'}\">\n * </ng-pluralize>\n *```\n *\n * In the example, `\"0: Nobody is viewing.\"` is an explicit number rule. If you did not\n * specify this rule, 0 would be matched to the \"other\" category and \"0 people are viewing\"\n * would be shown instead of \"Nobody is viewing\". You can specify an explicit number rule for\n * other numbers, for example 12, so that instead of showing \"12 people are viewing\", you can\n * show \"a dozen people are viewing\".\n *\n * You can use a set of closed braces (`{}`) as a placeholder for the number that you want substituted\n * into pluralized strings. In the previous example, Angular will replace `{}` with\n * <span ng-non-bindable>`{{personCount}}`</span>. The closed braces `{}` is a placeholder\n * for <span ng-non-bindable>{{numberExpression}}</span>.\n *\n * # Configuring ngPluralize with offset\n * The `offset` attribute allows further customization of pluralized text, which can result in\n * a better user experience. For example, instead of the message \"4 people are viewing this document\",\n * you might display \"John, Kate and 2 others are viewing this document\".\n * The offset attribute allows you to offset a number by any desired value.\n * Let's take a look at an example:\n *\n * ```html\n * <ng-pluralize count=\"personCount\" offset=2\n *               when=\"{'0': 'Nobody is viewing.',\n *                      '1': '{{person1}} is viewing.',\n *                      '2': '{{person1}} and {{person2}} are viewing.',\n *                      'one': '{{person1}}, {{person2}} and one other person are viewing.',\n *                      'other': '{{person1}}, {{person2}} and {} other people are viewing.'}\">\n * </ng-pluralize>\n * ```\n *\n * Notice that we are still using two plural categories(one, other), but we added\n * three explicit number rules 0, 1 and 2.\n * When one person, perhaps John, views the document, \"John is viewing\" will be shown.\n * When three people view the document, no explicit number rule is found, so\n * an offset of 2 is taken off 3, and Angular uses 1 to decide the plural category.\n * In this case, plural category 'one' is matched and \"John, Mary and one other person are viewing\"\n * is shown.\n *\n * Note that when you specify offsets, you must provide explicit number rules for\n * numbers from 0 up to and including the offset. If you use an offset of 3, for example,\n * you must provide explicit number rules for 0, 1, 2 and 3. You must also provide plural strings for\n * plural categories \"one\" and \"other\".\n *\n * @param {string|expression} count The variable to be bound to.\n * @param {string} when The mapping between plural category to its corresponding strings.\n * @param {number=} offset Offset to deduct from the total number.\n *\n * @example\n    <example module=\"pluralizeExample\">\n      <file name=\"index.html\">\n        <script>\n          angular.module('pluralizeExample', [])\n            .controller('ExampleController', ['$scope', function($scope) {\n              $scope.person1 = 'Igor';\n              $scope.person2 = 'Misko';\n              $scope.personCount = 1;\n            }]);\n        </script>\n        <div ng-controller=\"ExampleController\">\n          Person 1:<input type=\"text\" ng-model=\"person1\" value=\"Igor\" /><br/>\n          Person 2:<input type=\"text\" ng-model=\"person2\" value=\"Misko\" /><br/>\n          Number of People:<input type=\"text\" ng-model=\"personCount\" value=\"1\" /><br/>\n\n          <!--- Example with simple pluralization rules for en locale --->\n          Without Offset:\n          <ng-pluralize count=\"personCount\"\n                        when=\"{'0': 'Nobody is viewing.',\n                               'one': '1 person is viewing.',\n                               'other': '{} people are viewing.'}\">\n          </ng-pluralize><br>\n\n          <!--- Example with offset --->\n          With Offset(2):\n          <ng-pluralize count=\"personCount\" offset=2\n                        when=\"{'0': 'Nobody is viewing.',\n                               '1': '{{person1}} is viewing.',\n                               '2': '{{person1}} and {{person2}} are viewing.',\n                               'one': '{{person1}}, {{person2}} and one other person are viewing.',\n                               'other': '{{person1}}, {{person2}} and {} other people are viewing.'}\">\n          </ng-pluralize>\n        </div>\n      </file>\n      <file name=\"protractor.js\" type=\"protractor\">\n        it('should show correct pluralized string', function() {\n          var withoutOffset = element.all(by.css('ng-pluralize')).get(0);\n          var withOffset = element.all(by.css('ng-pluralize')).get(1);\n          var countInput = element(by.model('personCount'));\n\n          expect(withoutOffset.getText()).toEqual('1 person is viewing.');\n          expect(withOffset.getText()).toEqual('Igor is viewing.');\n\n          countInput.clear();\n          countInput.sendKeys('0');\n\n          expect(withoutOffset.getText()).toEqual('Nobody is viewing.');\n          expect(withOffset.getText()).toEqual('Nobody is viewing.');\n\n          countInput.clear();\n          countInput.sendKeys('2');\n\n          expect(withoutOffset.getText()).toEqual('2 people are viewing.');\n          expect(withOffset.getText()).toEqual('Igor and Misko are viewing.');\n\n          countInput.clear();\n          countInput.sendKeys('3');\n\n          expect(withoutOffset.getText()).toEqual('3 people are viewing.');\n          expect(withOffset.getText()).toEqual('Igor, Misko and one other person are viewing.');\n\n          countInput.clear();\n          countInput.sendKeys('4');\n\n          expect(withoutOffset.getText()).toEqual('4 people are viewing.');\n          expect(withOffset.getText()).toEqual('Igor, Misko and 2 other people are viewing.');\n        });\n        it('should show data-bound names', function() {\n          var withOffset = element.all(by.css('ng-pluralize')).get(1);\n          var personCount = element(by.model('personCount'));\n          var person1 = element(by.model('person1'));\n          var person2 = element(by.model('person2'));\n          personCount.clear();\n          personCount.sendKeys('4');\n          person1.clear();\n          person1.sendKeys('Di');\n          person2.clear();\n          person2.sendKeys('Vojta');\n          expect(withOffset.getText()).toEqual('Di, Vojta and 2 other people are viewing.');\n        });\n      </file>\n    </example>\n */\nvar ngPluralizeDirective = ['$locale', '$interpolate', function($locale, $interpolate) {\n  var BRACE = /{}/g,\n      IS_WHEN = /^when(Minus)?(.+)$/;\n\n  return {\n    restrict: 'EA',\n    link: function(scope, element, attr) {\n      var numberExp = attr.count,\n          whenExp = attr.$attr.when && element.attr(attr.$attr.when), // we have {{}} in attrs\n          offset = attr.offset || 0,\n          whens = scope.$eval(whenExp) || {},\n          whensExpFns = {},\n          startSymbol = $interpolate.startSymbol(),\n          endSymbol = $interpolate.endSymbol(),\n          braceReplacement = startSymbol + numberExp + '-' + offset + endSymbol,\n          watchRemover = angular.noop,\n          lastCount;\n\n      forEach(attr, function(expression, attributeName) {\n        var tmpMatch = IS_WHEN.exec(attributeName);\n        if (tmpMatch) {\n          var whenKey = (tmpMatch[1] ? '-' : '') + lowercase(tmpMatch[2]);\n          whens[whenKey] = element.attr(attr.$attr[attributeName]);\n        }\n      });\n      forEach(whens, function(expression, key) {\n        whensExpFns[key] = $interpolate(expression.replace(BRACE, braceReplacement));\n\n      });\n\n      scope.$watch(numberExp, function ngPluralizeWatchAction(newVal) {\n        var count = parseFloat(newVal);\n        var countIsNaN = isNaN(count);\n\n        if (!countIsNaN && !(count in whens)) {\n          // If an explicit number rule such as 1, 2, 3... is defined, just use it.\n          // Otherwise, check it against pluralization rules in $locale service.\n          count = $locale.pluralCat(count - offset);\n        }\n\n        // If both `count` and `lastCount` are NaN, we don't need to re-register a watch.\n        // In JS `NaN !== NaN`, so we have to exlicitly check.\n        if ((count !== lastCount) && !(countIsNaN && isNaN(lastCount))) {\n          watchRemover();\n          watchRemover = scope.$watch(whensExpFns[count], updateElementText);\n          lastCount = count;\n        }\n      });\n\n      function updateElementText(newText) {\n        element.text(newText || '');\n      }\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ngRepeat\n *\n * @description\n * The `ngRepeat` directive instantiates a template once per item from a collection. Each template\n * instance gets its own scope, where the given loop variable is set to the current collection item,\n * and `$index` is set to the item index or key.\n *\n * Special properties are exposed on the local scope of each template instance, including:\n *\n * | Variable  | Type            | Details                                                                     |\n * |-----------|-----------------|-----------------------------------------------------------------------------|\n * | `$index`  | {@type number}  | iterator offset of the repeated element (0..length-1)                       |\n * | `$first`  | {@type boolean} | true if the repeated element is first in the iterator.                      |\n * | `$middle` | {@type boolean} | true if the repeated element is between the first and last in the iterator. |\n * | `$last`   | {@type boolean} | true if the repeated element is last in the iterator.                       |\n * | `$even`   | {@type boolean} | true if the iterator position `$index` is even (otherwise false).           |\n * | `$odd`    | {@type boolean} | true if the iterator position `$index` is odd (otherwise false).            |\n *\n * Creating aliases for these properties is possible with {@link ng.directive:ngInit `ngInit`}.\n * This may be useful when, for instance, nesting ngRepeats.\n *\n * # Iterating over object properties\n *\n * It is possible to get `ngRepeat` to iterate over the properties of an object using the following\n * syntax:\n *\n * ```js\n * <div ng-repeat=\"(key, value) in myObj\"> ... </div>\n * ```\n *\n * You need to be aware that the JavaScript specification does not define what order\n * it will return the keys for an object. In order to have a guaranteed deterministic order\n * for the keys, Angular versions up to and including 1.3 **sort the keys alphabetically**.\n *\n * If this is not desired, the recommended workaround is to convert your object into an array\n * that is sorted into the order that you prefer before providing it to `ngRepeat`.  You could\n * do this with a filter such as [toArrayFilter](http://ngmodules.org/modules/angular-toArrayFilter)\n * or implement a `$watch` on the object yourself.\n *\n * In version 1.4 we will remove the sorting, since it seems that browsers generally follow the\n * strategy of providing keys in the order in which they were defined, although there are exceptions\n * when keys are deleted and reinstated.\n *\n *\n * # Special repeat start and end points\n * To repeat a series of elements instead of just one parent element, ngRepeat (as well as other ng directives) supports extending\n * the range of the repeater by defining explicit start and end points by using **ng-repeat-start** and **ng-repeat-end** respectively.\n * The **ng-repeat-start** directive works the same as **ng-repeat**, but will repeat all the HTML code (including the tag it's defined on)\n * up to and including the ending HTML tag where **ng-repeat-end** is placed.\n *\n * The example below makes use of this feature:\n * ```html\n *   <header ng-repeat-start=\"item in items\">\n *     Header {{ item }}\n *   </header>\n *   <div class=\"body\">\n *     Body {{ item }}\n *   </div>\n *   <footer ng-repeat-end>\n *     Footer {{ item }}\n *   </footer>\n * ```\n *\n * And with an input of {@type ['A','B']} for the items variable in the example above, the output will evaluate to:\n * ```html\n *   <header>\n *     Header A\n *   </header>\n *   <div class=\"body\">\n *     Body A\n *   </div>\n *   <footer>\n *     Footer A\n *   </footer>\n *   <header>\n *     Header B\n *   </header>\n *   <div class=\"body\">\n *     Body B\n *   </div>\n *   <footer>\n *     Footer B\n *   </footer>\n * ```\n *\n * The custom start and end points for ngRepeat also support all other HTML directive syntax flavors provided in AngularJS (such\n * as **data-ng-repeat-start**, **x-ng-repeat-start** and **ng:repeat-start**).\n *\n * @animations\n * **.enter** - when a new item is added to the list or when an item is revealed after a filter\n *\n * **.leave** - when an item is removed from the list or when an item is filtered out\n *\n * **.move** - when an adjacent item is filtered out causing a reorder or when the item contents are reordered\n *\n * @element ANY\n * @scope\n * @priority 1000\n * @param {repeat_expression} ngRepeat The expression indicating how to enumerate a collection. These\n *   formats are currently supported:\n *\n *   * `variable in expression` – where variable is the user defined loop variable and `expression`\n *     is a scope expression giving the collection to enumerate.\n *\n *     For example: `album in artist.albums`.\n *\n *   * `(key, value) in expression` – where `key` and `value` can be any user defined identifiers,\n *     and `expression` is the scope expression giving the collection to enumerate.\n *\n *     For example: `(name, age) in {'adam':10, 'amalie':12}`.\n *\n *   * `variable in expression track by tracking_expression` – You can also provide an optional tracking function\n *     which can be used to associate the objects in the collection with the DOM elements. If no tracking function\n *     is specified the ng-repeat associates elements by identity in the collection. It is an error to have\n *     more than one tracking function to resolve to the same key. (This would mean that two distinct objects are\n *     mapped to the same DOM element, which is not possible.)  Filters should be applied to the expression,\n *     before specifying a tracking expression.\n *\n *     For example: `item in items` is equivalent to `item in items track by $id(item)`. This implies that the DOM elements\n *     will be associated by item identity in the array.\n *\n *     For example: `item in items track by $id(item)`. A built in `$id()` function can be used to assign a unique\n *     `$$hashKey` property to each item in the array. This property is then used as a key to associated DOM elements\n *     with the corresponding item in the array by identity. Moving the same object in array would move the DOM\n *     element in the same way in the DOM.\n *\n *     For example: `item in items track by item.id` is a typical pattern when the items come from the database. In this\n *     case the object identity does not matter. Two objects are considered equivalent as long as their `id`\n *     property is same.\n *\n *     For example: `item in items | filter:searchText track by item.id` is a pattern that might be used to apply a filter\n *     to items in conjunction with a tracking expression.\n *\n *   * `variable in expression as alias_expression` – You can also provide an optional alias expression which will then store the\n *     intermediate results of the repeater after the filters have been applied. Typically this is used to render a special message\n *     when a filter is active on the repeater, but the filtered result set is empty.\n *\n *     For example: `item in items | filter:x as results` will store the fragment of the repeated items as `results`, but only after\n *     the items have been processed through the filter.\n *\n * @example\n * This example initializes the scope to a list of names and\n * then uses `ngRepeat` to display every person:\n  <example module=\"ngAnimate\" deps=\"angular-animate.js\" animations=\"true\">\n    <file name=\"index.html\">\n      <div ng-init=\"friends = [\n        {name:'John', age:25, gender:'boy'},\n        {name:'Jessie', age:30, gender:'girl'},\n        {name:'Johanna', age:28, gender:'girl'},\n        {name:'Joy', age:15, gender:'girl'},\n        {name:'Mary', age:28, gender:'girl'},\n        {name:'Peter', age:95, gender:'boy'},\n        {name:'Sebastian', age:50, gender:'boy'},\n        {name:'Erika', age:27, gender:'girl'},\n        {name:'Patrick', age:40, gender:'boy'},\n        {name:'Samantha', age:60, gender:'girl'}\n      ]\">\n        I have {{friends.length}} friends. They are:\n        <input type=\"search\" ng-model=\"q\" placeholder=\"filter friends...\" />\n        <ul class=\"example-animate-container\">\n          <li class=\"animate-repeat\" ng-repeat=\"friend in friends | filter:q as results\">\n            [{{$index + 1}}] {{friend.name}} who is {{friend.age}} years old.\n          </li>\n          <li class=\"animate-repeat\" ng-if=\"results.length == 0\">\n            <strong>No results found...</strong>\n          </li>\n        </ul>\n      </div>\n    </file>\n    <file name=\"animations.css\">\n      .example-animate-container {\n        background:white;\n        border:1px solid black;\n        list-style:none;\n        margin:0;\n        padding:0 10px;\n      }\n\n      .animate-repeat {\n        line-height:40px;\n        list-style:none;\n        box-sizing:border-box;\n      }\n\n      .animate-repeat.ng-move,\n      .animate-repeat.ng-enter,\n      .animate-repeat.ng-leave {\n        -webkit-transition:all linear 0.5s;\n        transition:all linear 0.5s;\n      }\n\n      .animate-repeat.ng-leave.ng-leave-active,\n      .animate-repeat.ng-move,\n      .animate-repeat.ng-enter {\n        opacity:0;\n        max-height:0;\n      }\n\n      .animate-repeat.ng-leave,\n      .animate-repeat.ng-move.ng-move-active,\n      .animate-repeat.ng-enter.ng-enter-active {\n        opacity:1;\n        max-height:40px;\n      }\n    </file>\n    <file name=\"protractor.js\" type=\"protractor\">\n      var friends = element.all(by.repeater('friend in friends'));\n\n      it('should render initial data set', function() {\n        expect(friends.count()).toBe(10);\n        expect(friends.get(0).getText()).toEqual('[1] John who is 25 years old.');\n        expect(friends.get(1).getText()).toEqual('[2] Jessie who is 30 years old.');\n        expect(friends.last().getText()).toEqual('[10] Samantha who is 60 years old.');\n        expect(element(by.binding('friends.length')).getText())\n            .toMatch(\"I have 10 friends. They are:\");\n      });\n\n       it('should update repeater when filter predicate changes', function() {\n         expect(friends.count()).toBe(10);\n\n         element(by.model('q')).sendKeys('ma');\n\n         expect(friends.count()).toBe(2);\n         expect(friends.get(0).getText()).toEqual('[1] Mary who is 28 years old.');\n         expect(friends.last().getText()).toEqual('[2] Samantha who is 60 years old.');\n       });\n      </file>\n    </example>\n */\nvar ngRepeatDirective = ['$parse', '$animate', function($parse, $animate) {\n  var NG_REMOVED = '$$NG_REMOVED';\n  var ngRepeatMinErr = minErr('ngRepeat');\n\n  var updateScope = function(scope, index, valueIdentifier, value, keyIdentifier, key, arrayLength) {\n    // TODO(perf): generate setters to shave off ~40ms or 1-1.5%\n    scope[valueIdentifier] = value;\n    if (keyIdentifier) scope[keyIdentifier] = key;\n    scope.$index = index;\n    scope.$first = (index === 0);\n    scope.$last = (index === (arrayLength - 1));\n    scope.$middle = !(scope.$first || scope.$last);\n    // jshint bitwise: false\n    scope.$odd = !(scope.$even = (index&1) === 0);\n    // jshint bitwise: true\n  };\n\n  var getBlockStart = function(block) {\n    return block.clone[0];\n  };\n\n  var getBlockEnd = function(block) {\n    return block.clone[block.clone.length - 1];\n  };\n\n\n  return {\n    restrict: 'A',\n    multiElement: true,\n    transclude: 'element',\n    priority: 1000,\n    terminal: true,\n    $$tlb: true,\n    compile: function ngRepeatCompile($element, $attr) {\n      var expression = $attr.ngRepeat;\n      var ngRepeatEndComment = document.createComment(' end ngRepeat: ' + expression + ' ');\n\n      var match = expression.match(/^\\s*([\\s\\S]+?)\\s+in\\s+([\\s\\S]+?)(?:\\s+as\\s+([\\s\\S]+?))?(?:\\s+track\\s+by\\s+([\\s\\S]+?))?\\s*$/);\n\n      if (!match) {\n        throw ngRepeatMinErr('iexp', \"Expected expression in form of '_item_ in _collection_[ track by _id_]' but got '{0}'.\",\n            expression);\n      }\n\n      var lhs = match[1];\n      var rhs = match[2];\n      var aliasAs = match[3];\n      var trackByExp = match[4];\n\n      match = lhs.match(/^(?:(\\s*[\\$\\w]+)|\\(\\s*([\\$\\w]+)\\s*,\\s*([\\$\\w]+)\\s*\\))$/);\n\n      if (!match) {\n        throw ngRepeatMinErr('iidexp', \"'_item_' in '_item_ in _collection_' should be an identifier or '(_key_, _value_)' expression, but got '{0}'.\",\n            lhs);\n      }\n      var valueIdentifier = match[3] || match[1];\n      var keyIdentifier = match[2];\n\n      if (aliasAs && (!/^[$a-zA-Z_][$a-zA-Z0-9_]*$/.test(aliasAs) ||\n          /^(null|undefined|this|\\$index|\\$first|\\$middle|\\$last|\\$even|\\$odd|\\$parent|\\$root|\\$id)$/.test(aliasAs))) {\n        throw ngRepeatMinErr('badident', \"alias '{0}' is invalid --- must be a valid JS identifier which is not a reserved name.\",\n          aliasAs);\n      }\n\n      var trackByExpGetter, trackByIdExpFn, trackByIdArrayFn, trackByIdObjFn;\n      var hashFnLocals = {$id: hashKey};\n\n      if (trackByExp) {\n        trackByExpGetter = $parse(trackByExp);\n      } else {\n        trackByIdArrayFn = function(key, value) {\n          return hashKey(value);\n        };\n        trackByIdObjFn = function(key) {\n          return key;\n        };\n      }\n\n      return function ngRepeatLink($scope, $element, $attr, ctrl, $transclude) {\n\n        if (trackByExpGetter) {\n          trackByIdExpFn = function(key, value, index) {\n            // assign key, value, and $index to the locals so that they can be used in hash functions\n            if (keyIdentifier) hashFnLocals[keyIdentifier] = key;\n            hashFnLocals[valueIdentifier] = value;\n            hashFnLocals.$index = index;\n            return trackByExpGetter($scope, hashFnLocals);\n          };\n        }\n\n        // Store a list of elements from previous run. This is a hash where key is the item from the\n        // iterator, and the value is objects with following properties.\n        //   - scope: bound scope\n        //   - element: previous element.\n        //   - index: position\n        //\n        // We are using no-proto object so that we don't need to guard against inherited props via\n        // hasOwnProperty.\n        var lastBlockMap = createMap();\n\n        //watch props\n        $scope.$watchCollection(rhs, function ngRepeatAction(collection) {\n          var index, length,\n              previousNode = $element[0],     // node that cloned nodes should be inserted after\n                                              // initialized to the comment node anchor\n              nextNode,\n              // Same as lastBlockMap but it has the current state. It will become the\n              // lastBlockMap on the next iteration.\n              nextBlockMap = createMap(),\n              collectionLength,\n              key, value, // key/value of iteration\n              trackById,\n              trackByIdFn,\n              collectionKeys,\n              block,       // last object information {scope, element, id}\n              nextBlockOrder,\n              elementsToRemove;\n\n          if (aliasAs) {\n            $scope[aliasAs] = collection;\n          }\n\n          if (isArrayLike(collection)) {\n            collectionKeys = collection;\n            trackByIdFn = trackByIdExpFn || trackByIdArrayFn;\n          } else {\n            trackByIdFn = trackByIdExpFn || trackByIdObjFn;\n            // if object, extract keys, sort them and use to determine order of iteration over obj props\n            collectionKeys = [];\n            for (var itemKey in collection) {\n              if (collection.hasOwnProperty(itemKey) && itemKey.charAt(0) != '$') {\n                collectionKeys.push(itemKey);\n              }\n            }\n            collectionKeys.sort();\n          }\n\n          collectionLength = collectionKeys.length;\n          nextBlockOrder = new Array(collectionLength);\n\n          // locate existing items\n          for (index = 0; index < collectionLength; index++) {\n            key = (collection === collectionKeys) ? index : collectionKeys[index];\n            value = collection[key];\n            trackById = trackByIdFn(key, value, index);\n            if (lastBlockMap[trackById]) {\n              // found previously seen block\n              block = lastBlockMap[trackById];\n              delete lastBlockMap[trackById];\n              nextBlockMap[trackById] = block;\n              nextBlockOrder[index] = block;\n            } else if (nextBlockMap[trackById]) {\n              // if collision detected. restore lastBlockMap and throw an error\n              forEach(nextBlockOrder, function(block) {\n                if (block && block.scope) lastBlockMap[block.id] = block;\n              });\n              throw ngRepeatMinErr('dupes',\n                  \"Duplicates in a repeater are not allowed. Use 'track by' expression to specify unique keys. Repeater: {0}, Duplicate key: {1}, Duplicate value: {2}\",\n                  expression, trackById, value);\n            } else {\n              // new never before seen block\n              nextBlockOrder[index] = {id: trackById, scope: undefined, clone: undefined};\n              nextBlockMap[trackById] = true;\n            }\n          }\n\n          // remove leftover items\n          for (var blockKey in lastBlockMap) {\n            block = lastBlockMap[blockKey];\n            elementsToRemove = getBlockNodes(block.clone);\n            $animate.leave(elementsToRemove);\n            if (elementsToRemove[0].parentNode) {\n              // if the element was not removed yet because of pending animation, mark it as deleted\n              // so that we can ignore it later\n              for (index = 0, length = elementsToRemove.length; index < length; index++) {\n                elementsToRemove[index][NG_REMOVED] = true;\n              }\n            }\n            block.scope.$destroy();\n          }\n\n          // we are not using forEach for perf reasons (trying to avoid #call)\n          for (index = 0; index < collectionLength; index++) {\n            key = (collection === collectionKeys) ? index : collectionKeys[index];\n            value = collection[key];\n            block = nextBlockOrder[index];\n\n            if (block.scope) {\n              // if we have already seen this object, then we need to reuse the\n              // associated scope/element\n\n              nextNode = previousNode;\n\n              // skip nodes that are already pending removal via leave animation\n              do {\n                nextNode = nextNode.nextSibling;\n              } while (nextNode && nextNode[NG_REMOVED]);\n\n              if (getBlockStart(block) != nextNode) {\n                // existing item which got moved\n                $animate.move(getBlockNodes(block.clone), null, jqLite(previousNode));\n              }\n              previousNode = getBlockEnd(block);\n              updateScope(block.scope, index, valueIdentifier, value, keyIdentifier, key, collectionLength);\n            } else {\n              // new item which we don't know about\n              $transclude(function ngRepeatTransclude(clone, scope) {\n                block.scope = scope;\n                // http://jsperf.com/clone-vs-createcomment\n                var endNode = ngRepeatEndComment.cloneNode(false);\n                clone[clone.length++] = endNode;\n\n                // TODO(perf): support naked previousNode in `enter` to avoid creation of jqLite wrapper?\n                $animate.enter(clone, null, jqLite(previousNode));\n                previousNode = endNode;\n                // Note: We only need the first/last node of the cloned nodes.\n                // However, we need to keep the reference to the jqlite wrapper as it might be changed later\n                // by a directive with templateUrl when its template arrives.\n                block.clone = clone;\n                nextBlockMap[block.id] = block;\n                updateScope(block.scope, index, valueIdentifier, value, keyIdentifier, key, collectionLength);\n              });\n            }\n          }\n          lastBlockMap = nextBlockMap;\n        });\n      };\n    }\n  };\n}];\n\nvar NG_HIDE_CLASS = 'ng-hide';\nvar NG_HIDE_IN_PROGRESS_CLASS = 'ng-hide-animate';\n/**\n * @ngdoc directive\n * @name ngShow\n *\n * @description\n * The `ngShow` directive shows or hides the given HTML element based on the expression\n * provided to the `ngShow` attribute. The element is shown or hidden by removing or adding\n * the `.ng-hide` CSS class onto the element. The `.ng-hide` CSS class is predefined\n * in AngularJS and sets the display style to none (using an !important flag).\n * For CSP mode please add `angular-csp.css` to your html file (see {@link ng.directive:ngCsp ngCsp}).\n *\n * ```html\n * <!-- when $scope.myValue is truthy (element is visible) -->\n * <div ng-show=\"myValue\"></div>\n *\n * <!-- when $scope.myValue is falsy (element is hidden) -->\n * <div ng-show=\"myValue\" class=\"ng-hide\"></div>\n * ```\n *\n * When the `ngShow` expression evaluates to a falsy value then the `.ng-hide` CSS class is added to the class\n * attribute on the element causing it to become hidden. When truthy, the `.ng-hide` CSS class is removed\n * from the element causing the element not to appear hidden.\n *\n * ## Why is !important used?\n *\n * You may be wondering why !important is used for the `.ng-hide` CSS class. This is because the `.ng-hide` selector\n * can be easily overridden by heavier selectors. For example, something as simple\n * as changing the display style on a HTML list item would make hidden elements appear visible.\n * This also becomes a bigger issue when dealing with CSS frameworks.\n *\n * By using !important, the show and hide behavior will work as expected despite any clash between CSS selector\n * specificity (when !important isn't used with any conflicting styles). If a developer chooses to override the\n * styling to change how to hide an element then it is just a matter of using !important in their own CSS code.\n *\n * ### Overriding `.ng-hide`\n *\n * By default, the `.ng-hide` class will style the element with `display: none!important`. If you wish to change\n * the hide behavior with ngShow/ngHide then this can be achieved by restating the styles for the `.ng-hide`\n * class CSS. Note that the selector that needs to be used is actually `.ng-hide:not(.ng-hide-animate)` to cope\n * with extra animation classes that can be added.\n *\n * ```css\n * .ng-hide:not(.ng-hide-animate) {\n *   /&#42; this is just another form of hiding an element &#42;/\n *   display: block!important;\n *   position: absolute;\n *   top: -9999px;\n *   left: -9999px;\n * }\n * ```\n *\n * By default you don't need to override in CSS anything and the animations will work around the display style.\n *\n * ## A note about animations with `ngShow`\n *\n * Animations in ngShow/ngHide work with the show and hide events that are triggered when the directive expression\n * is true and false. This system works like the animation system present with ngClass except that\n * you must also include the !important flag to override the display property\n * so that you can perform an animation when the element is hidden during the time of the animation.\n *\n * ```css\n * //\n * //a working example can be found at the bottom of this page\n * //\n * .my-element.ng-hide-add, .my-element.ng-hide-remove {\n *   /&#42; this is required as of 1.3x to properly\n *      apply all styling in a show/hide animation &#42;/\n *   transition: 0s linear all;\n * }\n *\n * .my-element.ng-hide-add-active,\n * .my-element.ng-hide-remove-active {\n *   /&#42; the transition is defined in the active class &#42;/\n *   transition: 1s linear all;\n * }\n *\n * .my-element.ng-hide-add { ... }\n * .my-element.ng-hide-add.ng-hide-add-active { ... }\n * .my-element.ng-hide-remove { ... }\n * .my-element.ng-hide-remove.ng-hide-remove-active { ... }\n * ```\n *\n * Keep in mind that, as of AngularJS version 1.3.0-beta.11, there is no need to change the display\n * property to block during animation states--ngAnimate will handle the style toggling automatically for you.\n *\n * @animations\n * addClass: `.ng-hide` - happens after the `ngShow` expression evaluates to a truthy value and the just before contents are set to visible\n * removeClass: `.ng-hide` - happens after the `ngShow` expression evaluates to a non truthy value and just before the contents are set to hidden\n *\n * @element ANY\n * @param {expression} ngShow If the {@link guide/expression expression} is truthy\n *     then the element is shown or hidden respectively.\n *\n * @example\n  <example module=\"ngAnimate\" deps=\"angular-animate.js\" animations=\"true\">\n    <file name=\"index.html\">\n      Click me: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n      <div>\n        Show:\n        <div class=\"check-element animate-show\" ng-show=\"checked\">\n          <span class=\"glyphicon glyphicon-thumbs-up\"></span> I show up when your checkbox is checked.\n        </div>\n      </div>\n      <div>\n        Hide:\n        <div class=\"check-element animate-show\" ng-hide=\"checked\">\n          <span class=\"glyphicon glyphicon-thumbs-down\"></span> I hide when your checkbox is checked.\n        </div>\n      </div>\n    </file>\n    <file name=\"glyphicons.css\">\n      @import url(../../components/bootstrap-3.1.1/css/bootstrap.css);\n    </file>\n    <file name=\"animations.css\">\n      .animate-show {\n        line-height: 20px;\n        opacity: 1;\n        padding: 10px;\n        border: 1px solid black;\n        background: white;\n      }\n\n      .animate-show.ng-hide-add.ng-hide-add-active,\n      .animate-show.ng-hide-remove.ng-hide-remove-active {\n        -webkit-transition: all linear 0.5s;\n        transition: all linear 0.5s;\n      }\n\n      .animate-show.ng-hide {\n        line-height: 0;\n        opacity: 0;\n        padding: 0 10px;\n      }\n\n      .check-element {\n        padding: 10px;\n        border: 1px solid black;\n        background: white;\n      }\n    </file>\n    <file name=\"protractor.js\" type=\"protractor\">\n      var thumbsUp = element(by.css('span.glyphicon-thumbs-up'));\n      var thumbsDown = element(by.css('span.glyphicon-thumbs-down'));\n\n      it('should check ng-show / ng-hide', function() {\n        expect(thumbsUp.isDisplayed()).toBeFalsy();\n        expect(thumbsDown.isDisplayed()).toBeTruthy();\n\n        element(by.model('checked')).click();\n\n        expect(thumbsUp.isDisplayed()).toBeTruthy();\n        expect(thumbsDown.isDisplayed()).toBeFalsy();\n      });\n    </file>\n  </example>\n */\nvar ngShowDirective = ['$animate', function($animate) {\n  return {\n    restrict: 'A',\n    multiElement: true,\n    link: function(scope, element, attr) {\n      scope.$watch(attr.ngShow, function ngShowWatchAction(value) {\n        // we're adding a temporary, animation-specific class for ng-hide since this way\n        // we can control when the element is actually displayed on screen without having\n        // to have a global/greedy CSS selector that breaks when other animations are run.\n        // Read: https://github.com/angular/angular.js/issues/9103#issuecomment-58335845\n        $animate[value ? 'removeClass' : 'addClass'](element, NG_HIDE_CLASS, {\n          tempClasses: NG_HIDE_IN_PROGRESS_CLASS\n        });\n      });\n    }\n  };\n}];\n\n\n/**\n * @ngdoc directive\n * @name ngHide\n *\n * @description\n * The `ngHide` directive shows or hides the given HTML element based on the expression\n * provided to the `ngHide` attribute. The element is shown or hidden by removing or adding\n * the `ng-hide` CSS class onto the element. The `.ng-hide` CSS class is predefined\n * in AngularJS and sets the display style to none (using an !important flag).\n * For CSP mode please add `angular-csp.css` to your html file (see {@link ng.directive:ngCsp ngCsp}).\n *\n * ```html\n * <!-- when $scope.myValue is truthy (element is hidden) -->\n * <div ng-hide=\"myValue\" class=\"ng-hide\"></div>\n *\n * <!-- when $scope.myValue is falsy (element is visible) -->\n * <div ng-hide=\"myValue\"></div>\n * ```\n *\n * When the `ngHide` expression evaluates to a truthy value then the `.ng-hide` CSS class is added to the class\n * attribute on the element causing it to become hidden. When falsy, the `.ng-hide` CSS class is removed\n * from the element causing the element not to appear hidden.\n *\n * ## Why is !important used?\n *\n * You may be wondering why !important is used for the `.ng-hide` CSS class. This is because the `.ng-hide` selector\n * can be easily overridden by heavier selectors. For example, something as simple\n * as changing the display style on a HTML list item would make hidden elements appear visible.\n * This also becomes a bigger issue when dealing with CSS frameworks.\n *\n * By using !important, the show and hide behavior will work as expected despite any clash between CSS selector\n * specificity (when !important isn't used with any conflicting styles). If a developer chooses to override the\n * styling to change how to hide an element then it is just a matter of using !important in their own CSS code.\n *\n * ### Overriding `.ng-hide`\n *\n * By default, the `.ng-hide` class will style the element with `display: none!important`. If you wish to change\n * the hide behavior with ngShow/ngHide then this can be achieved by restating the styles for the `.ng-hide`\n * class in CSS:\n *\n * ```css\n * .ng-hide {\n *   /&#42; this is just another form of hiding an element &#42;/\n *   display: block!important;\n *   position: absolute;\n *   top: -9999px;\n *   left: -9999px;\n * }\n * ```\n *\n * By default you don't need to override in CSS anything and the animations will work around the display style.\n *\n * ## A note about animations with `ngHide`\n *\n * Animations in ngShow/ngHide work with the show and hide events that are triggered when the directive expression\n * is true and false. This system works like the animation system present with ngClass, except that the `.ng-hide`\n * CSS class is added and removed for you instead of your own CSS class.\n *\n * ```css\n * //\n * //a working example can be found at the bottom of this page\n * //\n * .my-element.ng-hide-add, .my-element.ng-hide-remove {\n *   transition: 0.5s linear all;\n * }\n *\n * .my-element.ng-hide-add { ... }\n * .my-element.ng-hide-add.ng-hide-add-active { ... }\n * .my-element.ng-hide-remove { ... }\n * .my-element.ng-hide-remove.ng-hide-remove-active { ... }\n * ```\n *\n * Keep in mind that, as of AngularJS version 1.3.0-beta.11, there is no need to change the display\n * property to block during animation states--ngAnimate will handle the style toggling automatically for you.\n *\n * @animations\n * removeClass: `.ng-hide` - happens after the `ngHide` expression evaluates to a truthy value and just before the contents are set to hidden\n * addClass: `.ng-hide` - happens after the `ngHide` expression evaluates to a non truthy value and just before the contents are set to visible\n *\n * @element ANY\n * @param {expression} ngHide If the {@link guide/expression expression} is truthy then\n *     the element is shown or hidden respectively.\n *\n * @example\n  <example module=\"ngAnimate\" deps=\"angular-animate.js\" animations=\"true\">\n    <file name=\"index.html\">\n      Click me: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n      <div>\n        Show:\n        <div class=\"check-element animate-hide\" ng-show=\"checked\">\n          <span class=\"glyphicon glyphicon-thumbs-up\"></span> I show up when your checkbox is checked.\n        </div>\n      </div>\n      <div>\n        Hide:\n        <div class=\"check-element animate-hide\" ng-hide=\"checked\">\n          <span class=\"glyphicon glyphicon-thumbs-down\"></span> I hide when your checkbox is checked.\n        </div>\n      </div>\n    </file>\n    <file name=\"glyphicons.css\">\n      @import url(../../components/bootstrap-3.1.1/css/bootstrap.css);\n    </file>\n    <file name=\"animations.css\">\n      .animate-hide {\n        -webkit-transition: all linear 0.5s;\n        transition: all linear 0.5s;\n        line-height: 20px;\n        opacity: 1;\n        padding: 10px;\n        border: 1px solid black;\n        background: white;\n      }\n\n      .animate-hide.ng-hide {\n        line-height: 0;\n        opacity: 0;\n        padding: 0 10px;\n      }\n\n      .check-element {\n        padding: 10px;\n        border: 1px solid black;\n        background: white;\n      }\n    </file>\n    <file name=\"protractor.js\" type=\"protractor\">\n      var thumbsUp = element(by.css('span.glyphicon-thumbs-up'));\n      var thumbsDown = element(by.css('span.glyphicon-thumbs-down'));\n\n      it('should check ng-show / ng-hide', function() {\n        expect(thumbsUp.isDisplayed()).toBeFalsy();\n        expect(thumbsDown.isDisplayed()).toBeTruthy();\n\n        element(by.model('checked')).click();\n\n        expect(thumbsUp.isDisplayed()).toBeTruthy();\n        expect(thumbsDown.isDisplayed()).toBeFalsy();\n      });\n    </file>\n  </example>\n */\nvar ngHideDirective = ['$animate', function($animate) {\n  return {\n    restrict: 'A',\n    multiElement: true,\n    link: function(scope, element, attr) {\n      scope.$watch(attr.ngHide, function ngHideWatchAction(value) {\n        // The comment inside of the ngShowDirective explains why we add and\n        // remove a temporary class for the show/hide animation\n        $animate[value ? 'addClass' : 'removeClass'](element,NG_HIDE_CLASS, {\n          tempClasses: NG_HIDE_IN_PROGRESS_CLASS\n        });\n      });\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ngStyle\n * @restrict AC\n *\n * @description\n * The `ngStyle` directive allows you to set CSS style on an HTML element conditionally.\n *\n * @element ANY\n * @param {expression} ngStyle\n *\n * {@link guide/expression Expression} which evals to an\n * object whose keys are CSS style names and values are corresponding values for those CSS\n * keys.\n *\n * Since some CSS style names are not valid keys for an object, they must be quoted.\n * See the 'background-color' style in the example below.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <input type=\"button\" value=\"set color\" ng-click=\"myStyle={color:'red'}\">\n        <input type=\"button\" value=\"set background\" ng-click=\"myStyle={'background-color':'blue'}\">\n        <input type=\"button\" value=\"clear\" ng-click=\"myStyle={}\">\n        <br/>\n        <span ng-style=\"myStyle\">Sample Text</span>\n        <pre>myStyle={{myStyle}}</pre>\n     </file>\n     <file name=\"style.css\">\n       span {\n         color: black;\n       }\n     </file>\n     <file name=\"protractor.js\" type=\"protractor\">\n       var colorSpan = element(by.css('span'));\n\n       it('should check ng-style', function() {\n         expect(colorSpan.getCssValue('color')).toBe('rgba(0, 0, 0, 1)');\n         element(by.css('input[value=\\'set color\\']')).click();\n         expect(colorSpan.getCssValue('color')).toBe('rgba(255, 0, 0, 1)');\n         element(by.css('input[value=clear]')).click();\n         expect(colorSpan.getCssValue('color')).toBe('rgba(0, 0, 0, 1)');\n       });\n     </file>\n   </example>\n */\nvar ngStyleDirective = ngDirective(function(scope, element, attr) {\n  scope.$watchCollection(attr.ngStyle, function ngStyleWatchAction(newStyles, oldStyles) {\n    if (oldStyles && (newStyles !== oldStyles)) {\n      forEach(oldStyles, function(val, style) { element.css(style, '');});\n    }\n    if (newStyles) element.css(newStyles);\n  });\n});\n\n/**\n * @ngdoc directive\n * @name ngSwitch\n * @restrict EA\n *\n * @description\n * The `ngSwitch` directive is used to conditionally swap DOM structure on your template based on a scope expression.\n * Elements within `ngSwitch` but without `ngSwitchWhen` or `ngSwitchDefault` directives will be preserved at the location\n * as specified in the template.\n *\n * The directive itself works similar to ngInclude, however, instead of downloading template code (or loading it\n * from the template cache), `ngSwitch` simply chooses one of the nested elements and makes it visible based on which element\n * matches the value obtained from the evaluated expression. In other words, you define a container element\n * (where you place the directive), place an expression on the **`on=\"...\"` attribute**\n * (or the **`ng-switch=\"...\"` attribute**), define any inner elements inside of the directive and place\n * a when attribute per element. The when attribute is used to inform ngSwitch which element to display when the on\n * expression is evaluated. If a matching expression is not found via a when attribute then an element with the default\n * attribute is displayed.\n *\n * <div class=\"alert alert-info\">\n * Be aware that the attribute values to match against cannot be expressions. They are interpreted\n * as literal string values to match against.\n * For example, **`ng-switch-when=\"someVal\"`** will match against the string `\"someVal\"` not against the\n * value of the expression `$scope.someVal`.\n * </div>\n\n * @animations\n * enter - happens after the ngSwitch contents change and the matched child element is placed inside the container\n * leave - happens just after the ngSwitch contents change and just before the former contents are removed from the DOM\n *\n * @usage\n *\n * ```\n * <ANY ng-switch=\"expression\">\n *   <ANY ng-switch-when=\"matchValue1\">...</ANY>\n *   <ANY ng-switch-when=\"matchValue2\">...</ANY>\n *   <ANY ng-switch-default>...</ANY>\n * </ANY>\n * ```\n *\n *\n * @scope\n * @priority 1200\n * @param {*} ngSwitch|on expression to match against <tt>ng-switch-when</tt>.\n * On child elements add:\n *\n * * `ngSwitchWhen`: the case statement to match against. If match then this\n *   case will be displayed. If the same match appears multiple times, all the\n *   elements will be displayed.\n * * `ngSwitchDefault`: the default case when no other case match. If there\n *   are multiple default cases, all of them will be displayed when no other\n *   case match.\n *\n *\n * @example\n  <example module=\"switchExample\" deps=\"angular-animate.js\" animations=\"true\">\n    <file name=\"index.html\">\n      <div ng-controller=\"ExampleController\">\n        <select ng-model=\"selection\" ng-options=\"item for item in items\">\n        </select>\n        <tt>selection={{selection}}</tt>\n        <hr/>\n        <div class=\"animate-switch-container\"\n          ng-switch on=\"selection\">\n            <div class=\"animate-switch\" ng-switch-when=\"settings\">Settings Div</div>\n            <div class=\"animate-switch\" ng-switch-when=\"home\">Home Span</div>\n            <div class=\"animate-switch\" ng-switch-default>default</div>\n        </div>\n      </div>\n    </file>\n    <file name=\"script.js\">\n      angular.module('switchExample', ['ngAnimate'])\n        .controller('ExampleController', ['$scope', function($scope) {\n          $scope.items = ['settings', 'home', 'other'];\n          $scope.selection = $scope.items[0];\n        }]);\n    </file>\n    <file name=\"animations.css\">\n      .animate-switch-container {\n        position:relative;\n        background:white;\n        border:1px solid black;\n        height:40px;\n        overflow:hidden;\n      }\n\n      .animate-switch {\n        padding:10px;\n      }\n\n      .animate-switch.ng-animate {\n        -webkit-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;\n        transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;\n\n        position:absolute;\n        top:0;\n        left:0;\n        right:0;\n        bottom:0;\n      }\n\n      .animate-switch.ng-leave.ng-leave-active,\n      .animate-switch.ng-enter {\n        top:-50px;\n      }\n      .animate-switch.ng-leave,\n      .animate-switch.ng-enter.ng-enter-active {\n        top:0;\n      }\n    </file>\n    <file name=\"protractor.js\" type=\"protractor\">\n      var switchElem = element(by.css('[ng-switch]'));\n      var select = element(by.model('selection'));\n\n      it('should start in settings', function() {\n        expect(switchElem.getText()).toMatch(/Settings Div/);\n      });\n      it('should change to home', function() {\n        select.all(by.css('option')).get(1).click();\n        expect(switchElem.getText()).toMatch(/Home Span/);\n      });\n      it('should select default', function() {\n        select.all(by.css('option')).get(2).click();\n        expect(switchElem.getText()).toMatch(/default/);\n      });\n    </file>\n  </example>\n */\nvar ngSwitchDirective = ['$animate', function($animate) {\n  return {\n    restrict: 'EA',\n    require: 'ngSwitch',\n\n    // asks for $scope to fool the BC controller module\n    controller: ['$scope', function ngSwitchController() {\n     this.cases = {};\n    }],\n    link: function(scope, element, attr, ngSwitchController) {\n      var watchExpr = attr.ngSwitch || attr.on,\n          selectedTranscludes = [],\n          selectedElements = [],\n          previousLeaveAnimations = [],\n          selectedScopes = [];\n\n      var spliceFactory = function(array, index) {\n          return function() { array.splice(index, 1); };\n      };\n\n      scope.$watch(watchExpr, function ngSwitchWatchAction(value) {\n        var i, ii;\n        for (i = 0, ii = previousLeaveAnimations.length; i < ii; ++i) {\n          $animate.cancel(previousLeaveAnimations[i]);\n        }\n        previousLeaveAnimations.length = 0;\n\n        for (i = 0, ii = selectedScopes.length; i < ii; ++i) {\n          var selected = getBlockNodes(selectedElements[i].clone);\n          selectedScopes[i].$destroy();\n          var promise = previousLeaveAnimations[i] = $animate.leave(selected);\n          promise.then(spliceFactory(previousLeaveAnimations, i));\n        }\n\n        selectedElements.length = 0;\n        selectedScopes.length = 0;\n\n        if ((selectedTranscludes = ngSwitchController.cases['!' + value] || ngSwitchController.cases['?'])) {\n          forEach(selectedTranscludes, function(selectedTransclude) {\n            selectedTransclude.transclude(function(caseElement, selectedScope) {\n              selectedScopes.push(selectedScope);\n              var anchor = selectedTransclude.element;\n              caseElement[caseElement.length++] = document.createComment(' end ngSwitchWhen: ');\n              var block = { clone: caseElement };\n\n              selectedElements.push(block);\n              $animate.enter(caseElement, anchor.parent(), anchor);\n            });\n          });\n        }\n      });\n    }\n  };\n}];\n\nvar ngSwitchWhenDirective = ngDirective({\n  transclude: 'element',\n  priority: 1200,\n  require: '^ngSwitch',\n  multiElement: true,\n  link: function(scope, element, attrs, ctrl, $transclude) {\n    ctrl.cases['!' + attrs.ngSwitchWhen] = (ctrl.cases['!' + attrs.ngSwitchWhen] || []);\n    ctrl.cases['!' + attrs.ngSwitchWhen].push({ transclude: $transclude, element: element });\n  }\n});\n\nvar ngSwitchDefaultDirective = ngDirective({\n  transclude: 'element',\n  priority: 1200,\n  require: '^ngSwitch',\n  multiElement: true,\n  link: function(scope, element, attr, ctrl, $transclude) {\n    ctrl.cases['?'] = (ctrl.cases['?'] || []);\n    ctrl.cases['?'].push({ transclude: $transclude, element: element });\n   }\n});\n\n/**\n * @ngdoc directive\n * @name ngTransclude\n * @restrict EAC\n *\n * @description\n * Directive that marks the insertion point for the transcluded DOM of the nearest parent directive that uses transclusion.\n *\n * Any existing content of the element that this directive is placed on will be removed before the transcluded content is inserted.\n *\n * @element ANY\n *\n * @example\n   <example module=\"transcludeExample\">\n     <file name=\"index.html\">\n       <script>\n         angular.module('transcludeExample', [])\n          .directive('pane', function(){\n             return {\n               restrict: 'E',\n               transclude: true,\n               scope: { title:'@' },\n               template: '<div style=\"border: 1px solid black;\">' +\n                           '<div style=\"background-color: gray\">{{title}}</div>' +\n                           '<ng-transclude></ng-transclude>' +\n                         '</div>'\n             };\n         })\n         .controller('ExampleController', ['$scope', function($scope) {\n           $scope.title = 'Lorem Ipsum';\n           $scope.text = 'Neque porro quisquam est qui dolorem ipsum quia dolor...';\n         }]);\n       </script>\n       <div ng-controller=\"ExampleController\">\n         <input ng-model=\"title\"> <br/>\n         <textarea ng-model=\"text\"></textarea> <br/>\n         <pane title=\"{{title}}\">{{text}}</pane>\n       </div>\n     </file>\n     <file name=\"protractor.js\" type=\"protractor\">\n        it('should have transcluded', function() {\n          var titleElement = element(by.model('title'));\n          titleElement.clear();\n          titleElement.sendKeys('TITLE');\n          var textElement = element(by.model('text'));\n          textElement.clear();\n          textElement.sendKeys('TEXT');\n          expect(element(by.binding('title')).getText()).toEqual('TITLE');\n          expect(element(by.binding('text')).getText()).toEqual('TEXT');\n        });\n     </file>\n   </example>\n *\n */\nvar ngTranscludeDirective = ngDirective({\n  restrict: 'EAC',\n  link: function($scope, $element, $attrs, controller, $transclude) {\n    if (!$transclude) {\n      throw minErr('ngTransclude')('orphan',\n       'Illegal use of ngTransclude directive in the template! ' +\n       'No parent directive that requires a transclusion found. ' +\n       'Element: {0}',\n       startingTag($element));\n    }\n\n    $transclude(function(clone) {\n      $element.empty();\n      $element.append(clone);\n    });\n  }\n});\n\n/**\n * @ngdoc directive\n * @name script\n * @restrict E\n *\n * @description\n * Load the content of a `<script>` element into {@link ng.$templateCache `$templateCache`}, so that the\n * template can be used by {@link ng.directive:ngInclude `ngInclude`},\n * {@link ngRoute.directive:ngView `ngView`}, or {@link guide/directive directives}. The type of the\n * `<script>` element must be specified as `text/ng-template`, and a cache name for the template must be\n * assigned through the element's `id`, which can then be used as a directive's `templateUrl`.\n *\n * @param {string} type Must be set to `'text/ng-template'`.\n * @param {string} id Cache name of the template.\n *\n * @example\n  <example>\n    <file name=\"index.html\">\n      <script type=\"text/ng-template\" id=\"/tpl.html\">\n        Content of the template.\n      </script>\n\n      <a ng-click=\"currentTpl='/tpl.html'\" id=\"tpl-link\">Load inlined template</a>\n      <div id=\"tpl-content\" ng-include src=\"currentTpl\"></div>\n    </file>\n    <file name=\"protractor.js\" type=\"protractor\">\n      it('should load template defined inside script tag', function() {\n        element(by.css('#tpl-link')).click();\n        expect(element(by.css('#tpl-content')).getText()).toMatch(/Content of the template/);\n      });\n    </file>\n  </example>\n */\nvar scriptDirective = ['$templateCache', function($templateCache) {\n  return {\n    restrict: 'E',\n    terminal: true,\n    compile: function(element, attr) {\n      if (attr.type == 'text/ng-template') {\n        var templateUrl = attr.id,\n            text = element[0].text;\n\n        $templateCache.put(templateUrl, text);\n      }\n    }\n  };\n}];\n\nvar ngOptionsMinErr = minErr('ngOptions');\n/**\n * @ngdoc directive\n * @name select\n * @restrict E\n *\n * @description\n * HTML `SELECT` element with angular data-binding.\n *\n * # `ngOptions`\n *\n * The `ngOptions` attribute can be used to dynamically generate a list of `<option>`\n * elements for the `<select>` element using the array or object obtained by evaluating the\n * `ngOptions` comprehension expression.\n *\n * In many cases, `ngRepeat` can be used on `<option>` elements instead of `ngOptions` to achieve a\n * similar result. However, `ngOptions` provides some benefits such as reducing memory and\n * increasing speed by not creating a new scope for each repeated instance, as well as providing\n * more flexibility in how the `<select>`'s model is assigned via the `select` **`as`** part of the\n * comprehension expression. `ngOptions` should be used when the `<select>` model needs to be bound\n *  to a non-string value. This is because an option element can only be bound to string values at\n * present.\n *\n * When an item in the `<select>` menu is selected, the array element or object property\n * represented by the selected option will be bound to the model identified by the `ngModel`\n * directive.\n *\n * Optionally, a single hard-coded `<option>` element, with the value set to an empty string, can\n * be nested into the `<select>` element. This element will then represent the `null` or \"not selected\"\n * option. See example below for demonstration.\n *\n * <div class=\"alert alert-warning\">\n * **Note:** `ngModel` compares by reference, not value. This is important when binding to an\n * array of objects. See an example [in this jsfiddle](http://jsfiddle.net/qWzTb/).\n * </div>\n *\n * ## `select` **`as`**\n *\n * Using `select` **`as`** will bind the result of the `select` expression to the model, but\n * the value of the `<select>` and `<option>` html elements will be either the index (for array data sources)\n * or property name (for object data sources) of the value within the collection. If a **`track by`** expression\n * is used, the result of that expression will be set as the value of the `option` and `select` elements.\n *\n *\n * ### `select` **`as`** and **`track by`**\n *\n * <div class=\"alert alert-warning\">\n * Do not use `select` **`as`** and **`track by`** in the same expression. They are not designed to work together.\n * </div>\n *\n * Consider the following example:\n *\n * ```html\n * <select ng-options=\"item.subItem as item.label for item in values track by item.id\" ng-model=\"selected\">\n * ```\n *\n * ```js\n * $scope.values = [{\n *   id: 1,\n *   label: 'aLabel',\n *   subItem: { name: 'aSubItem' }\n * }, {\n *   id: 2,\n *   label: 'bLabel',\n *   subItem: { name: 'bSubItem' }\n * }];\n *\n * $scope.selected = { name: 'aSubItem' };\n * ```\n *\n * With the purpose of preserving the selection, the **`track by`** expression is always applied to the element\n * of the data source (to `item` in this example). To calculate whether an element is selected, we do the\n * following:\n *\n * 1. Apply **`track by`** to the elements in the array. In the example: `[1, 2]`\n * 2. Apply **`track by`** to the already selected value in `ngModel`.\n *    In the example: this is not possible as **`track by`** refers to `item.id`, but the selected\n *    value from `ngModel` is `{name: 'aSubItem'}`, so the **`track by`** expression is applied to\n *    a wrong object, the selected element can't be found, `<select>` is always reset to the \"not\n *    selected\" option.\n *\n *\n * @param {string} ngModel Assignable angular expression to data-bind to.\n * @param {string=} name Property name of the form under which the control is published.\n * @param {string=} required The control is considered valid only if value is entered.\n * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n *    `required` when you want to data-bind to the `required` attribute.\n * @param {comprehension_expression=} ngOptions in one of the following forms:\n *\n *   * for array data sources:\n *     * `label` **`for`** `value` **`in`** `array`\n *     * `select` **`as`** `label` **`for`** `value` **`in`** `array`\n *     * `label` **`group by`** `group` **`for`** `value` **`in`** `array`\n *     * `label` **`group by`** `group` **`for`** `value` **`in`** `array` **`track by`** `trackexpr`\n *     * `label` **`for`** `value` **`in`** `array` | orderBy:`orderexpr` **`track by`** `trackexpr`\n *        (for including a filter with `track by`)\n *   * for object data sources:\n *     * `label` **`for (`**`key` **`,`** `value`**`) in`** `object`\n *     * `select` **`as`** `label` **`for (`**`key` **`,`** `value`**`) in`** `object`\n *     * `label` **`group by`** `group` **`for (`**`key`**`,`** `value`**`) in`** `object`\n *     * `select` **`as`** `label` **`group by`** `group`\n *         **`for` `(`**`key`**`,`** `value`**`) in`** `object`\n *\n * Where:\n *\n *   * `array` / `object`: an expression which evaluates to an array / object to iterate over.\n *   * `value`: local variable which will refer to each item in the `array` or each property value\n *      of `object` during iteration.\n *   * `key`: local variable which will refer to a property name in `object` during iteration.\n *   * `label`: The result of this expression will be the label for `<option>` element. The\n *     `expression` will most likely refer to the `value` variable (e.g. `value.propertyName`).\n *   * `select`: The result of this expression will be bound to the model of the parent `<select>`\n *      element. If not specified, `select` expression will default to `value`.\n *   * `group`: The result of this expression will be used to group options using the `<optgroup>`\n *      DOM element.\n *   * `trackexpr`: Used when working with an array of objects. The result of this expression will be\n *      used to identify the objects in the array. The `trackexpr` will most likely refer to the\n *     `value` variable (e.g. `value.propertyName`). With this the selection is preserved\n *      even when the options are recreated (e.g. reloaded from the server).\n *\n * @example\n    <example module=\"selectExample\">\n      <file name=\"index.html\">\n        <script>\n        angular.module('selectExample', [])\n          .controller('ExampleController', ['$scope', function($scope) {\n            $scope.colors = [\n              {name:'black', shade:'dark'},\n              {name:'white', shade:'light'},\n              {name:'red', shade:'dark'},\n              {name:'blue', shade:'dark'},\n              {name:'yellow', shade:'light'}\n            ];\n            $scope.myColor = $scope.colors[2]; // red\n          }]);\n        </script>\n        <div ng-controller=\"ExampleController\">\n          <ul>\n            <li ng-repeat=\"color in colors\">\n              Name: <input ng-model=\"color.name\">\n              [<a href ng-click=\"colors.splice($index, 1)\">X</a>]\n            </li>\n            <li>\n              [<a href ng-click=\"colors.push({})\">add</a>]\n            </li>\n          </ul>\n          <hr/>\n          Color (null not allowed):\n          <select ng-model=\"myColor\" ng-options=\"color.name for color in colors\"></select><br>\n\n          Color (null allowed):\n          <span  class=\"nullable\">\n            <select ng-model=\"myColor\" ng-options=\"color.name for color in colors\">\n              <option value=\"\">-- choose color --</option>\n            </select>\n          </span><br/>\n\n          Color grouped by shade:\n          <select ng-model=\"myColor\" ng-options=\"color.name group by color.shade for color in colors\">\n          </select><br/>\n\n\n          Select <a href ng-click=\"myColor = { name:'not in list', shade: 'other' }\">bogus</a>.<br>\n          <hr/>\n          Currently selected: {{ {selected_color:myColor} }}\n          <div style=\"border:solid 1px black; height:20px\"\n               ng-style=\"{'background-color':myColor.name}\">\n          </div>\n        </div>\n      </file>\n      <file name=\"protractor.js\" type=\"protractor\">\n         it('should check ng-options', function() {\n           expect(element(by.binding('{selected_color:myColor}')).getText()).toMatch('red');\n           element.all(by.model('myColor')).first().click();\n           element.all(by.css('select[ng-model=\"myColor\"] option')).first().click();\n           expect(element(by.binding('{selected_color:myColor}')).getText()).toMatch('black');\n           element(by.css('.nullable select[ng-model=\"myColor\"]')).click();\n           element.all(by.css('.nullable select[ng-model=\"myColor\"] option')).first().click();\n           expect(element(by.binding('{selected_color:myColor}')).getText()).toMatch('null');\n         });\n      </file>\n    </example>\n */\n\nvar ngOptionsDirective = valueFn({\n  restrict: 'A',\n  terminal: true\n});\n\n// jshint maxlen: false\nvar selectDirective = ['$compile', '$parse', function($compile,   $parse) {\n                         //000011111111110000000000022222222220000000000000000000003333333333000000000000004444444444444440000000005555555555555550000000666666666666666000000000000000777777777700000000000000000008888888888\n  var NG_OPTIONS_REGEXP = /^\\s*([\\s\\S]+?)(?:\\s+as\\s+([\\s\\S]+?))?(?:\\s+group\\s+by\\s+([\\s\\S]+?))?\\s+for\\s+(?:([\\$\\w][\\$\\w]*)|(?:\\(\\s*([\\$\\w][\\$\\w]*)\\s*,\\s*([\\$\\w][\\$\\w]*)\\s*\\)))\\s+in\\s+([\\s\\S]+?)(?:\\s+track\\s+by\\s+([\\s\\S]+?))?$/,\n      nullModelCtrl = {$setViewValue: noop};\n// jshint maxlen: 100\n\n  return {\n    restrict: 'E',\n    require: ['select', '?ngModel'],\n    controller: ['$element', '$scope', '$attrs', function($element, $scope, $attrs) {\n      var self = this,\n          optionsMap = {},\n          ngModelCtrl = nullModelCtrl,\n          nullOption,\n          unknownOption;\n\n\n      self.databound = $attrs.ngModel;\n\n\n      self.init = function(ngModelCtrl_, nullOption_, unknownOption_) {\n        ngModelCtrl = ngModelCtrl_;\n        nullOption = nullOption_;\n        unknownOption = unknownOption_;\n      };\n\n\n      self.addOption = function(value, element) {\n        assertNotHasOwnProperty(value, '\"option value\"');\n        optionsMap[value] = true;\n\n        if (ngModelCtrl.$viewValue == value) {\n          $element.val(value);\n          if (unknownOption.parent()) unknownOption.remove();\n        }\n        // Workaround for https://code.google.com/p/chromium/issues/detail?id=381459\n        // Adding an <option selected=\"selected\"> element to a <select required=\"required\"> should\n        // automatically select the new element\n        if (element && element[0].hasAttribute('selected')) {\n          element[0].selected = true;\n        }\n      };\n\n\n      self.removeOption = function(value) {\n        if (this.hasOption(value)) {\n          delete optionsMap[value];\n          if (ngModelCtrl.$viewValue === value) {\n            this.renderUnknownOption(value);\n          }\n        }\n      };\n\n\n      self.renderUnknownOption = function(val) {\n        var unknownVal = '? ' + hashKey(val) + ' ?';\n        unknownOption.val(unknownVal);\n        $element.prepend(unknownOption);\n        $element.val(unknownVal);\n        unknownOption.prop('selected', true); // needed for IE\n      };\n\n\n      self.hasOption = function(value) {\n        return optionsMap.hasOwnProperty(value);\n      };\n\n      $scope.$on('$destroy', function() {\n        // disable unknown option so that we don't do work when the whole select is being destroyed\n        self.renderUnknownOption = noop;\n      });\n    }],\n\n    link: function(scope, element, attr, ctrls) {\n      // if ngModel is not defined, we don't need to do anything\n      if (!ctrls[1]) return;\n\n      var selectCtrl = ctrls[0],\n          ngModelCtrl = ctrls[1],\n          multiple = attr.multiple,\n          optionsExp = attr.ngOptions,\n          nullOption = false, // if false, user will not be able to select it (used by ngOptions)\n          emptyOption,\n          renderScheduled = false,\n          // we can't just jqLite('<option>') since jqLite is not smart enough\n          // to create it in <select> and IE barfs otherwise.\n          optionTemplate = jqLite(document.createElement('option')),\n          optGroupTemplate =jqLite(document.createElement('optgroup')),\n          unknownOption = optionTemplate.clone();\n\n      // find \"null\" option\n      for (var i = 0, children = element.children(), ii = children.length; i < ii; i++) {\n        if (children[i].value === '') {\n          emptyOption = nullOption = children.eq(i);\n          break;\n        }\n      }\n\n      selectCtrl.init(ngModelCtrl, nullOption, unknownOption);\n\n      // required validator\n      if (multiple) {\n        ngModelCtrl.$isEmpty = function(value) {\n          return !value || value.length === 0;\n        };\n      }\n\n      if (optionsExp) setupAsOptions(scope, element, ngModelCtrl);\n      else if (multiple) setupAsMultiple(scope, element, ngModelCtrl);\n      else setupAsSingle(scope, element, ngModelCtrl, selectCtrl);\n\n\n      ////////////////////////////\n\n\n\n      function setupAsSingle(scope, selectElement, ngModelCtrl, selectCtrl) {\n        ngModelCtrl.$render = function() {\n          var viewValue = ngModelCtrl.$viewValue;\n\n          if (selectCtrl.hasOption(viewValue)) {\n            if (unknownOption.parent()) unknownOption.remove();\n            selectElement.val(viewValue);\n            if (viewValue === '') emptyOption.prop('selected', true); // to make IE9 happy\n          } else {\n            if (isUndefined(viewValue) && emptyOption) {\n              selectElement.val('');\n            } else {\n              selectCtrl.renderUnknownOption(viewValue);\n            }\n          }\n        };\n\n        selectElement.on('change', function() {\n          scope.$apply(function() {\n            if (unknownOption.parent()) unknownOption.remove();\n            ngModelCtrl.$setViewValue(selectElement.val());\n          });\n        });\n      }\n\n      function setupAsMultiple(scope, selectElement, ctrl) {\n        var lastView;\n        ctrl.$render = function() {\n          var items = new HashMap(ctrl.$viewValue);\n          forEach(selectElement.find('option'), function(option) {\n            option.selected = isDefined(items.get(option.value));\n          });\n        };\n\n        // we have to do it on each watch since ngModel watches reference, but\n        // we need to work of an array, so we need to see if anything was inserted/removed\n        scope.$watch(function selectMultipleWatch() {\n          if (!equals(lastView, ctrl.$viewValue)) {\n            lastView = shallowCopy(ctrl.$viewValue);\n            ctrl.$render();\n          }\n        });\n\n        selectElement.on('change', function() {\n          scope.$apply(function() {\n            var array = [];\n            forEach(selectElement.find('option'), function(option) {\n              if (option.selected) {\n                array.push(option.value);\n              }\n            });\n            ctrl.$setViewValue(array);\n          });\n        });\n      }\n\n      function setupAsOptions(scope, selectElement, ctrl) {\n        var match;\n\n        if (!(match = optionsExp.match(NG_OPTIONS_REGEXP))) {\n          throw ngOptionsMinErr('iexp',\n            \"Expected expression in form of \" +\n            \"'_select_ (as _label_)? for (_key_,)?_value_ in _collection_'\" +\n            \" but got '{0}'. Element: {1}\",\n            optionsExp, startingTag(selectElement));\n        }\n\n        var displayFn = $parse(match[2] || match[1]),\n            valueName = match[4] || match[6],\n            selectAs = / as /.test(match[0]) && match[1],\n            selectAsFn = selectAs ? $parse(selectAs) : null,\n            keyName = match[5],\n            groupByFn = $parse(match[3] || ''),\n            valueFn = $parse(match[2] ? match[1] : valueName),\n            valuesFn = $parse(match[7]),\n            track = match[8],\n            trackFn = track ? $parse(match[8]) : null,\n            trackKeysCache = {},\n            // This is an array of array of existing option groups in DOM.\n            // We try to reuse these if possible\n            // - optionGroupsCache[0] is the options with no option group\n            // - optionGroupsCache[?][0] is the parent: either the SELECT or OPTGROUP element\n            optionGroupsCache = [[{element: selectElement, label:''}]],\n            //re-usable object to represent option's locals\n            locals = {};\n\n        if (nullOption) {\n          // compile the element since there might be bindings in it\n          $compile(nullOption)(scope);\n\n          // remove the class, which is added automatically because we recompile the element and it\n          // becomes the compilation root\n          nullOption.removeClass('ng-scope');\n\n          // we need to remove it before calling selectElement.empty() because otherwise IE will\n          // remove the label from the element. wtf?\n          nullOption.remove();\n        }\n\n        // clear contents, we'll add what's needed based on the model\n        selectElement.empty();\n\n        selectElement.on('change', selectionChanged);\n\n        ctrl.$render = render;\n\n        scope.$watchCollection(valuesFn, scheduleRendering);\n        scope.$watchCollection(getLabels, scheduleRendering);\n\n        if (multiple) {\n          scope.$watchCollection(function() { return ctrl.$modelValue; }, scheduleRendering);\n        }\n\n        // ------------------------------------------------------------------ //\n\n        function callExpression(exprFn, key, value) {\n          locals[valueName] = value;\n          if (keyName) locals[keyName] = key;\n          return exprFn(scope, locals);\n        }\n\n        function selectionChanged() {\n          scope.$apply(function() {\n            var collection = valuesFn(scope) || [];\n            var viewValue;\n            if (multiple) {\n              viewValue = [];\n              forEach(selectElement.val(), function(selectedKey) {\n                  selectedKey = trackFn ? trackKeysCache[selectedKey] : selectedKey;\n                viewValue.push(getViewValue(selectedKey, collection[selectedKey]));\n              });\n            } else {\n              var selectedKey = trackFn ? trackKeysCache[selectElement.val()] : selectElement.val();\n              viewValue = getViewValue(selectedKey, collection[selectedKey]);\n            }\n            ctrl.$setViewValue(viewValue);\n            render();\n          });\n        }\n\n        function getViewValue(key, value) {\n          if (key === '?') {\n            return undefined;\n          } else if (key === '') {\n            return null;\n          } else {\n            var viewValueFn = selectAsFn ? selectAsFn : valueFn;\n            return callExpression(viewValueFn, key, value);\n          }\n        }\n\n        function getLabels() {\n          var values = valuesFn(scope);\n          var toDisplay;\n          if (values && isArray(values)) {\n            toDisplay = new Array(values.length);\n            for (var i = 0, ii = values.length; i < ii; i++) {\n              toDisplay[i] = callExpression(displayFn, i, values[i]);\n            }\n            return toDisplay;\n          } else if (values) {\n            // TODO: Add a test for this case\n            toDisplay = {};\n            for (var prop in values) {\n              if (values.hasOwnProperty(prop)) {\n                toDisplay[prop] = callExpression(displayFn, prop, values[prop]);\n              }\n            }\n          }\n          return toDisplay;\n        }\n\n        function createIsSelectedFn(viewValue) {\n          var selectedSet;\n          if (multiple) {\n            if (trackFn && isArray(viewValue)) {\n\n              selectedSet = new HashMap([]);\n              for (var trackIndex = 0; trackIndex < viewValue.length; trackIndex++) {\n                // tracking by key\n                selectedSet.put(callExpression(trackFn, null, viewValue[trackIndex]), true);\n              }\n            } else {\n              selectedSet = new HashMap(viewValue);\n            }\n          } else if (trackFn) {\n            viewValue = callExpression(trackFn, null, viewValue);\n          }\n\n          return function isSelected(key, value) {\n            var compareValueFn;\n            if (trackFn) {\n              compareValueFn = trackFn;\n            } else if (selectAsFn) {\n              compareValueFn = selectAsFn;\n            } else {\n              compareValueFn = valueFn;\n            }\n\n            if (multiple) {\n              return isDefined(selectedSet.remove(callExpression(compareValueFn, key, value)));\n            } else {\n              return viewValue === callExpression(compareValueFn, key, value);\n            }\n          };\n        }\n\n        function scheduleRendering() {\n          if (!renderScheduled) {\n            scope.$$postDigest(render);\n            renderScheduled = true;\n          }\n        }\n\n        /**\n         * A new labelMap is created with each render.\n         * This function is called for each existing option with added=false,\n         * and each new option with added=true.\n         * - Labels that are passed to this method twice,\n         * (once with added=true and once with added=false) will end up with a value of 0, and\n         * will cause no change to happen to the corresponding option.\n         * - Labels that are passed to this method only once with added=false will end up with a\n         * value of -1 and will eventually be passed to selectCtrl.removeOption()\n         * - Labels that are passed to this method only once with added=true will end up with a\n         * value of 1 and will eventually be passed to selectCtrl.addOption()\n        */\n        function updateLabelMap(labelMap, label, added) {\n          labelMap[label] = labelMap[label] || 0;\n          labelMap[label] += (added ? 1 : -1);\n        }\n\n        function render() {\n          renderScheduled = false;\n\n          // Temporary location for the option groups before we render them\n          var optionGroups = {'':[]},\n              optionGroupNames = [''],\n              optionGroupName,\n              optionGroup,\n              option,\n              existingParent, existingOptions, existingOption,\n              viewValue = ctrl.$viewValue,\n              values = valuesFn(scope) || [],\n              keys = keyName ? sortedKeys(values) : values,\n              key,\n              value,\n              groupLength, length,\n              groupIndex, index,\n              labelMap = {},\n              selected,\n              isSelected = createIsSelectedFn(viewValue),\n              anySelected = false,\n              lastElement,\n              element,\n              label,\n              optionId;\n\n          trackKeysCache = {};\n\n          // We now build up the list of options we need (we merge later)\n          for (index = 0; length = keys.length, index < length; index++) {\n            key = index;\n            if (keyName) {\n              key = keys[index];\n              if (key.charAt(0) === '$') continue;\n            }\n            value = values[key];\n\n            optionGroupName = callExpression(groupByFn, key, value) || '';\n            if (!(optionGroup = optionGroups[optionGroupName])) {\n              optionGroup = optionGroups[optionGroupName] = [];\n              optionGroupNames.push(optionGroupName);\n            }\n\n            selected = isSelected(key, value);\n            anySelected = anySelected || selected;\n\n            label = callExpression(displayFn, key, value); // what will be seen by the user\n\n            // doing displayFn(scope, locals) || '' overwrites zero values\n            label = isDefined(label) ? label : '';\n            optionId = trackFn ? trackFn(scope, locals) : (keyName ? keys[index] : index);\n            if (trackFn) {\n              trackKeysCache[optionId] = key;\n            }\n\n            optionGroup.push({\n              // either the index into array or key from object\n              id: optionId,\n              label: label,\n              selected: selected                   // determine if we should be selected\n            });\n          }\n          if (!multiple) {\n            if (nullOption || viewValue === null) {\n              // insert null option if we have a placeholder, or the model is null\n              optionGroups[''].unshift({id:'', label:'', selected:!anySelected});\n            } else if (!anySelected) {\n              // option could not be found, we have to insert the undefined item\n              optionGroups[''].unshift({id:'?', label:'', selected:true});\n            }\n          }\n\n          // Now we need to update the list of DOM nodes to match the optionGroups we computed above\n          for (groupIndex = 0, groupLength = optionGroupNames.length;\n               groupIndex < groupLength;\n               groupIndex++) {\n            // current option group name or '' if no group\n            optionGroupName = optionGroupNames[groupIndex];\n\n            // list of options for that group. (first item has the parent)\n            optionGroup = optionGroups[optionGroupName];\n\n            if (optionGroupsCache.length <= groupIndex) {\n              // we need to grow the optionGroups\n              existingParent = {\n                element: optGroupTemplate.clone().attr('label', optionGroupName),\n                label: optionGroup.label\n              };\n              existingOptions = [existingParent];\n              optionGroupsCache.push(existingOptions);\n              selectElement.append(existingParent.element);\n            } else {\n              existingOptions = optionGroupsCache[groupIndex];\n              existingParent = existingOptions[0];  // either SELECT (no group) or OPTGROUP element\n\n              // update the OPTGROUP label if not the same.\n              if (existingParent.label != optionGroupName) {\n                existingParent.element.attr('label', existingParent.label = optionGroupName);\n              }\n            }\n\n            lastElement = null;  // start at the beginning\n            for (index = 0, length = optionGroup.length; index < length; index++) {\n              option = optionGroup[index];\n              if ((existingOption = existingOptions[index + 1])) {\n                // reuse elements\n                lastElement = existingOption.element;\n                if (existingOption.label !== option.label) {\n                  updateLabelMap(labelMap, existingOption.label, false);\n                  updateLabelMap(labelMap, option.label, true);\n                  lastElement.text(existingOption.label = option.label);\n                  lastElement.prop('label', existingOption.label);\n                }\n                if (existingOption.id !== option.id) {\n                  lastElement.val(existingOption.id = option.id);\n                }\n                // lastElement.prop('selected') provided by jQuery has side-effects\n                if (lastElement[0].selected !== option.selected) {\n                  lastElement.prop('selected', (existingOption.selected = option.selected));\n                  if (msie) {\n                    // See #7692\n                    // The selected item wouldn't visually update on IE without this.\n                    // Tested on Win7: IE9, IE10 and IE11. Future IEs should be tested as well\n                    lastElement.prop('selected', existingOption.selected);\n                  }\n                }\n              } else {\n                // grow elements\n\n                // if it's a null option\n                if (option.id === '' && nullOption) {\n                  // put back the pre-compiled element\n                  element = nullOption;\n                } else {\n                  // jQuery(v1.4.2) Bug: We should be able to chain the method calls, but\n                  // in this version of jQuery on some browser the .text() returns a string\n                  // rather then the element.\n                  (element = optionTemplate.clone())\n                      .val(option.id)\n                      .prop('selected', option.selected)\n                      .attr('selected', option.selected)\n                      .prop('label', option.label)\n                      .text(option.label);\n                }\n\n                existingOptions.push(existingOption = {\n                    element: element,\n                    label: option.label,\n                    id: option.id,\n                    selected: option.selected\n                });\n                updateLabelMap(labelMap, option.label, true);\n                if (lastElement) {\n                  lastElement.after(element);\n                } else {\n                  existingParent.element.append(element);\n                }\n                lastElement = element;\n              }\n            }\n            // remove any excessive OPTIONs in a group\n            index++; // increment since the existingOptions[0] is parent element not OPTION\n            while (existingOptions.length > index) {\n              option = existingOptions.pop();\n              updateLabelMap(labelMap, option.label, false);\n              option.element.remove();\n            }\n          }\n          // remove any excessive OPTGROUPs from select\n          while (optionGroupsCache.length > groupIndex) {\n            // remove all the labels in the option group\n            optionGroup = optionGroupsCache.pop();\n            for (index = 1; index < optionGroup.length; ++index) {\n              updateLabelMap(labelMap, optionGroup[index].label, false);\n            }\n            optionGroup[0].element.remove();\n          }\n          forEach(labelMap, function(count, label) {\n            if (count > 0) {\n              selectCtrl.addOption(label);\n            } else if (count < 0) {\n              selectCtrl.removeOption(label);\n            }\n          });\n        }\n      }\n    }\n  };\n}];\n\nvar optionDirective = ['$interpolate', function($interpolate) {\n  var nullSelectCtrl = {\n    addOption: noop,\n    removeOption: noop\n  };\n\n  return {\n    restrict: 'E',\n    priority: 100,\n    compile: function(element, attr) {\n      if (isUndefined(attr.value)) {\n        var interpolateFn = $interpolate(element.text(), true);\n        if (!interpolateFn) {\n          attr.$set('value', element.text());\n        }\n      }\n\n      return function(scope, element, attr) {\n        var selectCtrlName = '$selectController',\n            parent = element.parent(),\n            selectCtrl = parent.data(selectCtrlName) ||\n              parent.parent().data(selectCtrlName); // in case we are in optgroup\n\n        if (!selectCtrl || !selectCtrl.databound) {\n          selectCtrl = nullSelectCtrl;\n        }\n\n        if (interpolateFn) {\n          scope.$watch(interpolateFn, function interpolateWatchAction(newVal, oldVal) {\n            attr.$set('value', newVal);\n            if (oldVal !== newVal) {\n              selectCtrl.removeOption(oldVal);\n            }\n            selectCtrl.addOption(newVal, element);\n          });\n        } else {\n          selectCtrl.addOption(attr.value, element);\n        }\n\n        element.on('$destroy', function() {\n          selectCtrl.removeOption(attr.value);\n        });\n      };\n    }\n  };\n}];\n\nvar styleDirective = valueFn({\n  restrict: 'E',\n  terminal: false\n});\n\nvar requiredDirective = function() {\n  return {\n    restrict: 'A',\n    require: '?ngModel',\n    link: function(scope, elm, attr, ctrl) {\n      if (!ctrl) return;\n      attr.required = true; // force truthy in case we are on non input element\n\n      ctrl.$validators.required = function(modelValue, viewValue) {\n        return !attr.required || !ctrl.$isEmpty(viewValue);\n      };\n\n      attr.$observe('required', function() {\n        ctrl.$validate();\n      });\n    }\n  };\n};\n\n\nvar patternDirective = function() {\n  return {\n    restrict: 'A',\n    require: '?ngModel',\n    link: function(scope, elm, attr, ctrl) {\n      if (!ctrl) return;\n\n      var regexp, patternExp = attr.ngPattern || attr.pattern;\n      attr.$observe('pattern', function(regex) {\n        if (isString(regex) && regex.length > 0) {\n          regex = new RegExp('^' + regex + '$');\n        }\n\n        if (regex && !regex.test) {\n          throw minErr('ngPattern')('noregexp',\n            'Expected {0} to be a RegExp but was {1}. Element: {2}', patternExp,\n            regex, startingTag(elm));\n        }\n\n        regexp = regex || undefined;\n        ctrl.$validate();\n      });\n\n      ctrl.$validators.pattern = function(value) {\n        return ctrl.$isEmpty(value) || isUndefined(regexp) || regexp.test(value);\n      };\n    }\n  };\n};\n\n\nvar maxlengthDirective = function() {\n  return {\n    restrict: 'A',\n    require: '?ngModel',\n    link: function(scope, elm, attr, ctrl) {\n      if (!ctrl) return;\n\n      var maxlength = -1;\n      attr.$observe('maxlength', function(value) {\n        var intVal = int(value);\n        maxlength = isNaN(intVal) ? -1 : intVal;\n        ctrl.$validate();\n      });\n      ctrl.$validators.maxlength = function(modelValue, viewValue) {\n        return (maxlength < 0) || ctrl.$isEmpty(viewValue) || (viewValue.length <= maxlength);\n      };\n    }\n  };\n};\n\nvar minlengthDirective = function() {\n  return {\n    restrict: 'A',\n    require: '?ngModel',\n    link: function(scope, elm, attr, ctrl) {\n      if (!ctrl) return;\n\n      var minlength = 0;\n      attr.$observe('minlength', function(value) {\n        minlength = int(value) || 0;\n        ctrl.$validate();\n      });\n      ctrl.$validators.minlength = function(modelValue, viewValue) {\n        return ctrl.$isEmpty(viewValue) || viewValue.length >= minlength;\n      };\n    }\n  };\n};\n\n  if (window.angular.bootstrap) {\n    //AngularJS is already loaded, so we can return here...\n    console.log('WARNING: Tried to load angular more than once.');\n    return;\n  }\n\n  //try to bind to jquery now so that one can write jqLite(document).ready()\n  //but we will rebind on bootstrap again.\n  bindJQuery();\n\n  publishExternalAPI(angular);\n\n  jqLite(document).ready(function() {\n    angularInit(document, bootstrap);\n  });\n\n})(window, document);\n\n!window.angular.$$csp() && window.angular.element(document).find('head').prepend('<style type=\"text/css\">@charset \"UTF-8\";[ng\\\\:cloak],[ng-cloak],[data-ng-cloak],[x-ng-cloak],.ng-cloak,.x-ng-cloak,.ng-hide:not(.ng-hide-animate){display:none !important;}ng\\\\:form{display:block;}</style>');"
  },
  {
    "path": "flowable-ui-web/task/libs/autofill-events_1.0.0/autofill-event.js",
    "content": "/**\n * Autofill event polyfill ##version:1.0.0##\n * (c) 2014 Google, Inc.\n * License: MIT\n */\n(function(window) {\n  var $ = window.jQuery || window.angular.element;\n  var rootElement = window.document.documentElement,\n    $rootElement = $(rootElement);\n\n  addGlobalEventListener('change', markValue);\n  addValueChangeByJsListener(markValue);\n\n  $.prototype.checkAndTriggerAutoFillEvent = jqCheckAndTriggerAutoFillEvent;\n\n  // Need to use blur and not change event\n  // as Chrome does not fire change events in all cases an input is changed\n  // (e.g. when starting to type and then finish the input by auto filling a username)\n  addGlobalEventListener('blur', function(target) {\n    // setTimeout needed for Chrome as it fills other\n    // form fields a little later...\n    window.setTimeout(function() {\n      findParentForm(target).find('input').checkAndTriggerAutoFillEvent();\n    }, 20);\n  });\n\n  function DOMContentLoadedListener() {\n      // mark all values that are present when the DOM is ready.\n      // We don't need to trigger a change event here,\n      // as js libs start with those values already being set!\n      forEach(document.getElementsByTagName('input'), markValue);\n\n      // The timeout is needed for Chrome as it auto fills\n      // login forms some time after DOMContentLoaded!\n      window.setTimeout(function() {\n        $rootElement.find('input').checkAndTriggerAutoFillEvent();\n      }, 200);\n  }\n\n  //IE8 compatibility issue\n  if(!window.document.addEventListener){\n    window.document.attachEvent('DOMContentLoaded', DOMContentLoadedListener);    \n  }else{\n    window.document.addEventListener('DOMContentLoaded', DOMContentLoadedListener, false);\n  }\n\n  return;\n\n  // ----------\n\n  function jqCheckAndTriggerAutoFillEvent() {\n    var i, el;\n    for (i=0; i<this.length; i++) {\n      el = this[i];\n      if (!valueMarked(el)) {\n        markValue(el);\n        triggerChangeEvent(el);\n      }\n    }\n  }\n\n  function valueMarked(el) {\n    var val = el.value,\n         $$currentValue = el.$$currentValue;\n    if (!val && !$$currentValue) {\n      return true;\n    }\n    return val === $$currentValue;\n  }\n\n  function markValue(el) {\n    el.$$currentValue = el.value;\n  }\n\n  function addValueChangeByJsListener(listener) {\n    var jq = window.jQuery || window.angular.element,\n        jqProto = jq.prototype;\n    var _val = jqProto.val;\n    jqProto.val = function(newValue) {\n      var res = _val.apply(this, arguments);\n      if (arguments.length > 0) {\n        forEach(this, function(el) {\n          listener(el, newValue);\n        });\n      }\n      return res;\n    }\n  }\n\n  function addGlobalEventListener(eventName, listener) {\n      // Use a capturing event listener so that\n      // we also get the event when it's stopped!\n      // Also, the blur event does not bubble.\n      if(!rootElement.addEventListener){\n          rootElement.attachEvent(eventName, onEvent);      \n      }else{\n          rootElement.addEventListener(eventName, onEvent, true);\n      }\n\n      function onEvent(event) {\n          var target = event.target;\n          listener(target);\n      }\n  }\n\n  function findParentForm(el) {\n    while (el) {\n      if (el.nodeName === 'FORM') {\n        return $(el);\n      }\n      el = el.parentNode;\n    }\n    return $();\n  }\n\n  function forEach(arr, listener) {\n    if (arr.forEach) {\n      return arr.forEach(listener);\n    }\n    var i;\n    for (i=0; i<arr.length; i++) {\n      listener(arr[i]);\n    }\n  }\n\n  function triggerChangeEvent(element) {\n    var doc = window.document;\n    var event = doc.createEvent(\"HTMLEvents\");\n    event.initEvent(\"change\", true, true);\n    element.dispatchEvent(event);\n  }\n\n})(window);\n"
  },
  {
    "path": "flowable-ui-web/task/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": "flowable-ui-web/task/libs/bootstrap-daterangepicker_1.3.7/daterangepicker.js",
    "content": "/**\n * @version: 1.3.7\n * @author: Dan Grossman http://www.dangrossman.info/\n * @date: 2014-04-29\n * @copyright: Copyright (c) 2012-2014 Dan Grossman. All rights reserved.\n * @license: Licensed under Apache License v2.0. See http://www.apache.org/licenses/LICENSE-2.0\n * @website: http://www.improvely.com/\n */\n!function ($, moment) {\n\n    var DateRangePicker = function (element, options, cb) {\n\n        // by default, the daterangepicker element is placed at the bottom of HTML body\n        this.parentEl = 'body';\n\n        //element that triggered the date range picker\n        this.element = $(element);\n\n        //create the picker HTML object\n        var DRPTemplate = '<div class=\"daterangepicker dropdown-menu\">' +\n            '<div class=\"calendar left\"></div>' +\n            '<div class=\"calendar right\"></div>' +\n            '<div class=\"ranges\">' +\n            '<div class=\"range_inputs\">' +\n            '<div class=\"daterangepicker_start_input\">' +\n            '<label for=\"daterangepicker_start\"></label>' +\n            '<input class=\"input-mini\" type=\"text\" name=\"daterangepicker_start\" value=\"\" disabled=\"disabled\" />' +\n            '</div>' +\n            '<div class=\"daterangepicker_end_input\">' +\n            '<label for=\"daterangepicker_end\"></label>' +\n            '<input class=\"input-mini\" type=\"text\" name=\"daterangepicker_end\" value=\"\" disabled=\"disabled\" />' +\n            '</div>' +\n            '<button class=\"applyBtn\" disabled=\"disabled\"></button>&nbsp;' +\n            '<button class=\"cancelBtn\"></button>' +\n            '</div>' +\n            '</div>' +\n            '</div>';\n\n        //custom options\n        if (typeof options !== 'object' || options === null)\n            options = {};\n\n        this.parentEl = (typeof options === 'object' && options.parentEl && $(options.parentEl).length) ? $(options.parentEl) : $(this.parentEl);\n        this.container = $(DRPTemplate).appendTo(this.parentEl);\n\n        this.setOptions(options, cb);\n\n        //apply CSS classes and labels to buttons\n        var c = this.container;\n        $.each(this.buttonClasses, function (idx, val) {\n            c.find('button').addClass(val);\n        });\n        this.container.find('.daterangepicker_start_input label').html(this.locale.fromLabel);\n        this.container.find('.daterangepicker_end_input label').html(this.locale.toLabel);\n        if (this.applyClass.length)\n            this.container.find('.applyBtn').addClass(this.applyClass);\n        if (this.cancelClass.length)\n            this.container.find('.cancelBtn').addClass(this.cancelClass);\n        this.container.find('.applyBtn').html(this.locale.applyLabel);\n        this.container.find('.cancelBtn').html(this.locale.cancelLabel);\n\n        //event listeners\n\n        this.container.find('.calendar')\n            .on('click.daterangepicker', '.prev', $.proxy(this.clickPrev, this))\n            .on('click.daterangepicker', '.next', $.proxy(this.clickNext, this))\n            .on('click.daterangepicker', 'td.available', $.proxy(this.clickDate, this))\n            .on('mouseenter.daterangepicker', 'td.available', $.proxy(this.enterDate, this))\n            .on('mouseleave.daterangepicker', 'td.available', $.proxy(this.updateFormInputs, this))\n            .on('change.daterangepicker', 'select.yearselect', $.proxy(this.updateMonthYear, this))\n            .on('change.daterangepicker', 'select.monthselect', $.proxy(this.updateMonthYear, this))\n            .on('change.daterangepicker', 'select.hourselect,select.minuteselect,select.ampmselect', $.proxy(this.updateTime, this));\n\n        this.container.find('.ranges')\n            .on('click.daterangepicker', 'button.applyBtn', $.proxy(this.clickApply, this))\n            .on('click.daterangepicker', 'button.cancelBtn', $.proxy(this.clickCancel, this))\n            .on('click.daterangepicker', '.daterangepicker_start_input,.daterangepicker_end_input', $.proxy(this.showCalendars, this))\n            .on('click.daterangepicker', 'li', $.proxy(this.clickRange, this))\n            .on('mouseenter.daterangepicker', 'li', $.proxy(this.enterRange, this))\n            .on('mouseleave.daterangepicker', 'li', $.proxy(this.updateFormInputs, this));\n\n        if (this.element.is('input')) {\n            this.element.on({\n                'click.daterangepicker': $.proxy(this.show, this),\n                'focus.daterangepicker': $.proxy(this.show, this),\n                'keyup.daterangepicker': $.proxy(this.updateFromControl, this)\n            });\n        } else {\n            this.element.on('click.daterangepicker', $.proxy(this.toggle, this));\n        }\n\n    };\n\n    DateRangePicker.prototype = {\n\n        constructor: DateRangePicker,\n\n        setOptions: function(options, callback) {\n\n            this.startDate = moment().startOf('day');\n            this.endDate = moment().endOf('day');\n            this.minDate = false;\n            this.maxDate = false;\n            this.dateLimit = false;\n\n            this.showDropdowns = false;\n            this.showWeekNumbers = false;\n            this.timePicker = false;\n            this.timePickerIncrement = 30;\n            this.timePicker12Hour = true;\n            this.singleDatePicker = false;\n            this.ranges = {};\n\n            this.opens = 'right';\n            if (this.element.hasClass('pull-right'))\n                this.opens = 'left';\n\n            this.buttonClasses = ['btn', 'btn-small'];\n            this.applyClass = 'btn-success';\n            this.cancelClass = 'btn-default';\n\n            this.format = 'MM/DD/YYYY';\n            this.separator = ' - ';\n\n            this.locale = {\n                applyLabel: 'Apply',\n                cancelLabel: 'Cancel',\n                fromLabel: 'From',\n                toLabel: 'To',\n                weekLabel: 'W',\n                customRangeLabel: 'Custom Range',\n                daysOfWeek: moment()._lang._weekdaysMin.slice(),\n                monthNames: moment()._lang._monthsShort.slice(),\n                firstDay: 0\n            };\n\n            this.cb = function () { };\n\n            if (typeof options.format === 'string')\n                this.format = options.format;\n\n            if (typeof options.separator === 'string')\n                this.separator = options.separator;\n\n            if (typeof options.startDate === 'string')\n                this.startDate = moment(options.startDate, this.format);\n\n            if (typeof options.endDate === 'string')\n                this.endDate = moment(options.endDate, this.format);\n\n            if (typeof options.minDate === 'string')\n                this.minDate = moment(options.minDate, this.format);\n\n            if (typeof options.maxDate === 'string')\n                this.maxDate = moment(options.maxDate, this.format);\n\n            if (typeof options.startDate === 'object')\n                this.startDate = moment(options.startDate);\n\n            if (typeof options.endDate === 'object')\n                this.endDate = moment(options.endDate);\n\n            if (typeof options.minDate === 'object')\n                this.minDate = moment(options.minDate);\n\n            if (typeof options.maxDate === 'object')\n                this.maxDate = moment(options.maxDate);\n\n            if (typeof options.applyClass === 'string')\n                this.applyClass = options.applyClass;\n\n            if (typeof options.cancelClass === 'string')\n                this.cancelClass = options.cancelClass;\n\n            if (typeof options.dateLimit === 'object')\n                this.dateLimit = options.dateLimit;\n\n            // update day names order to firstDay\n            if (typeof options.locale === 'object') {\n\n                if (typeof options.locale.daysOfWeek === 'object') {\n                    // Create a copy of daysOfWeek to avoid modification of original\n                    // options object for reusability in multiple daterangepicker instances\n                    this.locale.daysOfWeek = options.locale.daysOfWeek.slice();\n                }\n\n                if (typeof options.locale.monthNames === 'object') {\n                    this.locale.monthNames = options.locale.monthNames.slice();\n                }\n\n                if (typeof options.locale.firstDay === 'number') {\n                    this.locale.firstDay = options.locale.firstDay;\n                    var iterator = options.locale.firstDay;\n                    while (iterator > 0) {\n                        this.locale.daysOfWeek.push(this.locale.daysOfWeek.shift());\n                        iterator--;\n                    }\n                }\n\n                if (typeof options.locale.applyLabel === 'string') {\n                    this.locale.applyLabel = options.locale.applyLabel;\n                }\n\n                if (typeof options.locale.cancelLabel === 'string') {\n                    this.locale.cancelLabel = options.locale.cancelLabel;\n                }\n\n                if (typeof options.locale.fromLabel === 'string') {\n                    this.locale.fromLabel = options.locale.fromLabel;\n                }\n\n                if (typeof options.locale.toLabel === 'string') {\n                    this.locale.toLabel = options.locale.toLabel;\n                }\n\n                if (typeof options.locale.weekLabel === 'string') {\n                    this.locale.weekLabel = options.locale.weekLabel;\n                }\n\n                if (typeof options.locale.customRangeLabel === 'string') {\n                    this.locale.customRangeLabel = options.locale.customRangeLabel;\n                }\n            }\n\n            if (typeof options.opens === 'string')\n                this.opens = options.opens;\n\n            if (typeof options.showWeekNumbers === 'boolean') {\n                this.showWeekNumbers = options.showWeekNumbers;\n            }\n\n            if (typeof options.buttonClasses === 'string') {\n                this.buttonClasses = [options.buttonClasses];\n            }\n\n            if (typeof options.buttonClasses === 'object') {\n                this.buttonClasses = options.buttonClasses;\n            }\n\n            if (typeof options.showDropdowns === 'boolean') {\n                this.showDropdowns = options.showDropdowns;\n            }\n\n            if (typeof options.singleDatePicker === 'boolean') {\n                this.singleDatePicker = options.singleDatePicker;\n            }\n\n            if (typeof options.timePicker === 'boolean') {\n                this.timePicker = options.timePicker;\n            }\n\n            if (typeof options.timePickerIncrement === 'number') {\n                this.timePickerIncrement = options.timePickerIncrement;\n            }\n\n            if (typeof options.timePicker12Hour === 'boolean') {\n                this.timePicker12Hour = options.timePicker12Hour;\n            }\n\n            var start, end, range;\n\n            //if no start/end dates set, check if an input element contains initial values\n            if (typeof options.startDate === 'undefined' && typeof options.endDate === 'undefined') {\n                if ($(this.element).is('input[type=text]')) {\n                    var val = $(this.element).val();\n                    var split = val.split(this.separator);\n                    start = end = null;\n                    if (split.length == 2) {\n                        start = moment(split[0], this.format);\n                        end = moment(split[1], this.format);\n                    } else if (this.singleDatePicker) {\n                        start = moment(val, this.format);\n                        end = moment(val, this.format);\n                    }\n                    if (start !== null && end !== null) {\n                        this.startDate = start;\n                        this.endDate = end;\n                    }\n                }\n            }\n\n            if (typeof options.ranges === 'object') {\n                for (range in options.ranges) {\n\n                    start = moment(options.ranges[range][0]);\n                    end = moment(options.ranges[range][1]);\n\n                    // If we have a min/max date set, bound this range\n                    // to it, but only if it would otherwise fall\n                    // outside of the min/max.\n                    if (this.minDate && start.isBefore(this.minDate))\n                        start = moment(this.minDate);\n\n                    if (this.maxDate && end.isAfter(this.maxDate))\n                        end = moment(this.maxDate);\n\n                    // If the end of the range is before the minimum (if min is set) OR\n                    // the start of the range is after the max (also if set) don't display this\n                    // range option.\n                    if ((this.minDate && end.isBefore(this.minDate)) || (this.maxDate && start.isAfter(this.maxDate))) {\n                        continue;\n                    }\n\n                    this.ranges[range] = [start, end];\n                }\n\n                var list = '<ul>';\n                for (range in this.ranges) {\n                    list += '<li>' + range + '</li>';\n                }\n                list += '<li>' + this.locale.customRangeLabel + '</li>';\n                list += '</ul>';\n                this.container.find('.ranges ul').remove();\n                this.container.find('.ranges').prepend(list);\n            }\n\n            if (typeof callback === 'function') {\n                this.cb = callback;\n            }\n\n            if (!this.timePicker) {\n                this.startDate = this.startDate.startOf('day');\n                this.endDate = this.endDate.endOf('day');\n            }\n\n            if (this.singleDatePicker) {\n                this.opens = 'right';\n                this.container.find('.calendar.right').show();\n                this.container.find('.calendar.left').hide();\n                this.container.find('.ranges').hide();\n                if (!this.container.find('.calendar.right').hasClass('single'))\n                    this.container.find('.calendar.right').addClass('single');\n            } else {\n                this.container.find('.calendar.right').removeClass('single');\n                this.container.find('.ranges').show();\n            }\n\n            this.oldStartDate = this.startDate.clone();\n            this.oldEndDate = this.endDate.clone();\n            this.oldChosenLabel = this.chosenLabel;\n\n            this.leftCalendar = {\n                month: moment([this.startDate.year(), this.startDate.month(), 1, this.startDate.hour(), this.startDate.minute()]),\n                calendar: []\n            };\n\n            this.rightCalendar = {\n                month: moment([this.endDate.year(), this.endDate.month(), 1, this.endDate.hour(), this.endDate.minute()]),\n                calendar: []\n            };\n\n            if (this.opens == 'right') {\n                //swap calendar positions\n                var left = this.container.find('.calendar.left');\n                var right = this.container.find('.calendar.right');\n                left.removeClass('left').addClass('right');\n                right.removeClass('right').addClass('left');\n            }\n\n            if (typeof options.ranges === 'undefined' && !this.singleDatePicker) {\n                this.container.addClass('show-calendar');\n            }\n\n            this.container.addClass('opens' + this.opens);\n\n            this.updateView();\n            this.updateCalendars();\n\n        },\n\n        setStartDate: function(startDate) {\n            if (typeof startDate === 'string')\n                this.startDate = moment(startDate, this.format);\n\n            if (typeof startDate === 'object')\n                this.startDate = moment(startDate);\n\n            if (!this.timePicker)\n                this.startDate = this.startDate.startOf('day');\n\n            this.oldStartDate = this.startDate.clone();\n\n            this.updateView();\n            this.updateCalendars();\n        },\n\n        setEndDate: function(endDate) {\n            if (typeof endDate === 'string')\n                this.endDate = moment(endDate, this.format);\n\n            if (typeof endDate === 'object')\n                this.endDate = moment(endDate);\n\n            if (!this.timePicker)\n                this.endDate = this.endDate.endOf('day');\n\n            this.oldEndDate = this.endDate.clone();\n\n            this.updateView();\n            this.updateCalendars();\n        },\n\n        updateView: function () {\n            this.leftCalendar.month.month(this.startDate.month()).year(this.startDate.year());\n            this.rightCalendar.month.month(this.endDate.month()).year(this.endDate.year());\n            this.updateFormInputs();\n        },\n\n        updateFormInputs: function () {\n            this.container.find('input[name=daterangepicker_start]').val(this.startDate.format(this.format));\n            this.container.find('input[name=daterangepicker_end]').val(this.endDate.format(this.format));\n\n            if (this.startDate.isSame(this.endDate) || this.startDate.isBefore(this.endDate)) {\n                this.container.find('button.applyBtn').removeAttr('disabled');\n            } else {\n                this.container.find('button.applyBtn').attr('disabled', 'disabled');\n            }\n        },\n\n        updateFromControl: function () {\n            if (!this.element.is('input')) return;\n            if (!this.element.val().length) return;\n\n            var dateString = this.element.val().split(this.separator),\n                start = null,\n                end = null;\n\n            if(dateString.length === 2) {\n                start = moment(dateString[0], this.format);\n                end = moment(dateString[1], this.format);\n            }\n\n            if (this.singleDatePicker || start === null || end === null) {\n                start = moment(this.element.val(), this.format);\n                end = start;\n            }\n\n            if (end.isBefore(start)) return;\n\n            this.oldStartDate = this.startDate.clone();\n            this.oldEndDate = this.endDate.clone();\n\n            this.startDate = start;\n            this.endDate = end;\n\n            if (!this.startDate.isSame(this.oldStartDate) || !this.endDate.isSame(this.oldEndDate))\n                this.notify();\n\n            this.updateCalendars();\n        },\n\n        notify: function () {\n            this.updateView();\n            this.cb(this.startDate, this.endDate, this.chosenLabel);\n        },\n\n        move: function () {\n            var parentOffset = { top: 0, left: 0 };\n            if (!this.parentEl.is('body')) {\n                parentOffset = {\n                    top: this.parentEl.offset().top - this.parentEl.scrollTop(),\n                    left: this.parentEl.offset().left - this.parentEl.scrollLeft()\n                };\n            }\n\n            if (this.opens == 'left') {\n                this.container.css({\n                    top: this.element.offset().top + this.element.outerHeight() - parentOffset.top,\n                    right: $(window).width() - this.element.offset().left - this.element.outerWidth() - parentOffset.left,\n                    left: 'auto'\n                });\n                if (this.container.offset().left < 0) {\n                    this.container.css({\n                        right: 'auto',\n                        left: 9\n                    });\n                }\n            } else {\n                this.container.css({\n                    top: this.element.offset().top + this.element.outerHeight() - parentOffset.top,\n                    left: this.element.offset().left - parentOffset.left,\n                    right: 'auto'\n                });\n                if (this.container.offset().left + this.container.outerWidth() > $(window).width()) {\n                    this.container.css({\n                        left: 'auto',\n                        right: 0\n                    });\n                }\n            }\n        },\n\n        toggle: function (e) {\n            if (this.element.hasClass('active')) {\n                this.hide();\n            } else {\n                this.show();\n            }\n        },\n\n        show: function (e) {\n            this.element.addClass('active');\n            this.container.show();\n            this.move();\n\n            // Create a click proxy that is private to this instance of datepicker, for unbinding\n            this._outsideClickProxy = $.proxy(function (e) { this.outsideClick(e); }, this);\n            // Bind global datepicker mousedown for hiding and\n            $(document)\n                .on('mousedown.daterangepicker', this._outsideClickProxy)\n                // also explicitly play nice with Bootstrap dropdowns, which stopPropagation when clicking them\n                .on('click.daterangepicker', '[data-toggle=dropdown]', this._outsideClickProxy)\n                // and also close when focus changes to outside the picker (eg. tabbing between controls)\n                .on('focusin.daterangepicker', this._outsideClickProxy);\n\n            this.element.trigger('show.daterangepicker', this);\n        },\n\n        outsideClick: function (e) {\n            var target = $(e.target);\n            // if the page is clicked anywhere except within the daterangerpicker/button\n            // itself then call this.hide()\n            if (\n                target.closest(this.element).length ||\n                target.closest(this.container).length ||\n                target.closest('.calendar-date').length\n                ) return;\n            this.hide();\n        },\n\n        hide: function (e) {\n            $(document)\n                .off('mousedown.daterangepicker', this._outsideClickProxy)\n                .off('click.daterangepicker', this._outsideClickProxy)\n                .off('focusin.daterangepicker', this._outsideClickProxy);\n\n            this.element.removeClass('active');\n            this.container.hide();\n\n            if (!this.startDate.isSame(this.oldStartDate) || !this.endDate.isSame(this.oldEndDate))\n                this.notify();\n\n            this.oldStartDate = this.startDate.clone();\n            this.oldEndDate = this.endDate.clone();\n\n            this.element.trigger('hide.daterangepicker', this);\n        },\n\n        enterRange: function (e) {\n            // mouse pointer has entered a range label\n            var label = e.target.innerHTML;\n            if (label == this.locale.customRangeLabel) {\n                this.updateView();\n            } else {\n                var dates = this.ranges[label];\n                this.container.find('input[name=daterangepicker_start]').val(dates[0].format(this.format));\n                this.container.find('input[name=daterangepicker_end]').val(dates[1].format(this.format));\n            }\n        },\n\n        showCalendars: function() {\n            this.container.addClass('show-calendar');\n            this.move();\n        },\n\n        hideCalendars: function() {\n            this.container.removeClass('show-calendar');\n        },\n\n        updateInputText: function() {\n            if (this.element.is('input') && !this.singleDatePicker) {\n                this.element.val(this.startDate.format(this.format) + this.separator + this.endDate.format(this.format));\n            } else if (this.element.is('input')) {\n                this.element.val(this.startDate.format(this.format));\n            }\n        },\n\n        clickRange: function (e) {\n            var label = e.target.innerHTML;\n            this.chosenLabel = label;\n            if (label == this.locale.customRangeLabel) {\n                this.showCalendars();\n            } else {\n                var dates = this.ranges[label];\n\n                this.startDate = dates[0];\n                this.endDate = dates[1];\n\n                if (!this.timePicker) {\n                    this.startDate.startOf('day');\n                    this.endDate.endOf('day');\n                }\n\n                this.leftCalendar.month.month(this.startDate.month()).year(this.startDate.year()).hour(this.startDate.hour()).minute(this.startDate.minute());\n                this.rightCalendar.month.month(this.endDate.month()).year(this.endDate.year()).hour(this.endDate.hour()).minute(this.endDate.minute());\n                this.updateCalendars();\n\n                this.updateInputText();\n\n                this.hideCalendars();\n                this.hide();\n                this.element.trigger('apply.daterangepicker', this);\n            }\n        },\n\n        clickPrev: function (e) {\n            var cal = $(e.target).parents('.calendar');\n            if (cal.hasClass('left')) {\n                this.leftCalendar.month.subtract('month', 1);\n            } else {\n                this.rightCalendar.month.subtract('month', 1);\n            }\n            this.updateCalendars();\n        },\n\n        clickNext: function (e) {\n            var cal = $(e.target).parents('.calendar');\n            if (cal.hasClass('left')) {\n                this.leftCalendar.month.add('month', 1);\n            } else {\n                this.rightCalendar.month.add('month', 1);\n            }\n            this.updateCalendars();\n        },\n\n        enterDate: function (e) {\n\n            var title = $(e.target).attr('data-title');\n            var row = title.substr(1, 1);\n            var col = title.substr(3, 1);\n            var cal = $(e.target).parents('.calendar');\n\n            if (cal.hasClass('left')) {\n                this.container.find('input[name=daterangepicker_start]').val(this.leftCalendar.calendar[row][col].format(this.format));\n            } else {\n                this.container.find('input[name=daterangepicker_end]').val(this.rightCalendar.calendar[row][col].format(this.format));\n            }\n\n        },\n\n        clickDate: function (e) {\n            var title = $(e.target).attr('data-title');\n            var row = title.substr(1, 1);\n            var col = title.substr(3, 1);\n            var cal = $(e.target).parents('.calendar');\n\n            var startDate, endDate;\n            if (cal.hasClass('left')) {\n                startDate = this.leftCalendar.calendar[row][col];\n                endDate = this.endDate;\n                if (typeof this.dateLimit === 'object') {\n                    var maxDate = moment(startDate).add(this.dateLimit).startOf('day');\n                    if (endDate.isAfter(maxDate)) {\n                        endDate = maxDate;\n                    }\n                }\n            } else {\n                startDate = this.startDate;\n                endDate = this.rightCalendar.calendar[row][col];\n                if (typeof this.dateLimit === 'object') {\n                    var minDate = moment(endDate).subtract(this.dateLimit).startOf('day');\n                    if (startDate.isBefore(minDate)) {\n                        startDate = minDate;\n                    }\n                }\n            }\n\n            if (this.singleDatePicker && cal.hasClass('left')) {\n                endDate = startDate.clone();\n            } else if (this.singleDatePicker && cal.hasClass('right')) {\n                startDate = endDate.clone();\n            }\n\n            cal.find('td').removeClass('active');\n\n            if (startDate.isSame(endDate) || startDate.isBefore(endDate)) {\n                $(e.target).addClass('active');\n                this.startDate = startDate;\n                this.endDate = endDate;\n                this.chosenLabel = this.locale.customRangeLabel;\n            } else if (startDate.isAfter(endDate)) {\n                $(e.target).addClass('active');\n                var difference = this.endDate.diff(this.startDate);\n                this.startDate = startDate;\n                this.endDate = moment(startDate).add('ms', difference);\n                this.chosenLabel = this.locale.customRangeLabel;\n            }\n\n            this.leftCalendar.month.month(this.startDate.month()).year(this.startDate.year());\n            this.rightCalendar.month.month(this.endDate.month()).year(this.endDate.year());\n            this.updateCalendars();\n\n            if (!this.timePicker)\n                endDate.endOf('day');\n\n            if (this.singleDatePicker)\n                this.clickApply();\n        },\n\n        clickApply: function (e) {\n            this.updateInputText();\n            this.hide();\n            this.element.trigger('apply.daterangepicker', this);\n        },\n\n        clickCancel: function (e) {\n            this.startDate = this.oldStartDate;\n            this.endDate = this.oldEndDate;\n            this.chosenLabel = this.oldChosenLabel;\n            this.updateView();\n            this.updateCalendars();\n            this.hide();\n            this.element.trigger('cancel.daterangepicker', this);\n        },\n\n        updateMonthYear: function (e) {\n            var isLeft = $(e.target).closest('.calendar').hasClass('left'),\n                leftOrRight = isLeft ? 'left' : 'right',\n                cal = this.container.find('.calendar.'+leftOrRight);\n\n            // Month must be Number for new moment versions\n            var month = parseInt(cal.find('.monthselect').val(), 10);\n            var year = cal.find('.yearselect').val();\n\n            this[leftOrRight+'Calendar'].month.month(month).year(year);\n            this.updateCalendars();\n        },\n\n        updateTime: function(e) {\n\n            var cal = $(e.target).closest('.calendar'),\n                isLeft = cal.hasClass('left');\n\n            var hour = parseInt(cal.find('.hourselect').val(), 10);\n            var minute = parseInt(cal.find('.minuteselect').val(), 10);\n\n            if (this.timePicker12Hour) {\n                var ampm = cal.find('.ampmselect').val();\n                if (ampm === 'PM' && hour < 12)\n                    hour += 12;\n                if (ampm === 'AM' && hour === 12)\n                    hour = 0;\n            }\n\n            if (isLeft) {\n                var start = this.startDate.clone();\n                start.hour(hour);\n                start.minute(minute);\n                this.startDate = start;\n                this.leftCalendar.month.hour(hour).minute(minute);\n            } else {\n                var end = this.endDate.clone();\n                end.hour(hour);\n                end.minute(minute);\n                this.endDate = end;\n                this.rightCalendar.month.hour(hour).minute(minute);\n            }\n\n            this.updateCalendars();\n        },\n\n        updateCalendars: function () {\n            this.leftCalendar.calendar = this.buildCalendar(this.leftCalendar.month.month(), this.leftCalendar.month.year(), this.leftCalendar.month.hour(), this.leftCalendar.month.minute(), 'left');\n            this.rightCalendar.calendar = this.buildCalendar(this.rightCalendar.month.month(), this.rightCalendar.month.year(), this.rightCalendar.month.hour(), this.rightCalendar.month.minute(), 'right');\n            this.container.find('.calendar.left').empty().html(this.renderCalendar(this.leftCalendar.calendar, this.startDate, this.minDate, this.maxDate));\n            this.container.find('.calendar.right').empty().html(this.renderCalendar(this.rightCalendar.calendar, this.endDate, this.startDate, this.maxDate));\n\n            this.container.find('.ranges li').removeClass('active');\n            var customRange = true;\n            var i = 0;\n            for (var range in this.ranges) {\n                if (this.timePicker) {\n                    if (this.startDate.isSame(this.ranges[range][0]) && this.endDate.isSame(this.ranges[range][1])) {\n                        customRange = false;\n                        this.chosenLabel = this.container.find('.ranges li:eq(' + i + ')')\n                            .addClass('active').html();\n                    }\n                } else {\n                    //ignore times when comparing dates if time picker is not enabled\n                    if (this.startDate.format('YYYY-MM-DD') == this.ranges[range][0].format('YYYY-MM-DD') && this.endDate.format('YYYY-MM-DD') == this.ranges[range][1].format('YYYY-MM-DD')) {\n                        customRange = false;\n                        this.chosenLabel = this.container.find('.ranges li:eq(' + i + ')')\n                            .addClass('active').html();\n                    }\n                }\n                i++;\n            }\n            if (customRange) {\n                this.chosenLabel = this.container.find('.ranges li:last')\n                    .addClass('active').html();\n            }\n        },\n\n        buildCalendar: function (month, year, hour, minute, side) {\n            var firstDay = moment([year, month, 1]);\n            var lastMonth = moment(firstDay).subtract('month', 1).month();\n            var lastYear = moment(firstDay).subtract('month', 1).year();\n\n            var daysInLastMonth = moment([lastYear, lastMonth]).daysInMonth();\n\n            var dayOfWeek = firstDay.day();\n\n            var i;\n\n            //initialize a 6 rows x 7 columns array for the calendar\n            var calendar = [];\n            for (i = 0; i < 6; i++) {\n                calendar[i] = [];\n            }\n\n            //populate the calendar with date objects\n            var startDay = daysInLastMonth - dayOfWeek + this.locale.firstDay + 1;\n            if (startDay > daysInLastMonth)\n                startDay -= 7;\n\n            if (dayOfWeek == this.locale.firstDay)\n                startDay = daysInLastMonth - 6;\n\n            var curDate = moment([lastYear, lastMonth, startDay, 12, minute]);\n            var col, row;\n            for (i = 0, col = 0, row = 0; i < 42; i++, col++, curDate = moment(curDate).add('hour', 24)) {\n                if (i > 0 && col % 7 === 0) {\n                    col = 0;\n                    row++;\n                }\n                calendar[row][col] = curDate.clone().hour(hour);\n                curDate.hour(12);\n            }\n\n            return calendar;\n        },\n\n        renderDropdowns: function (selected, minDate, maxDate) {\n            var currentMonth = selected.month();\n            var monthHtml = '<select class=\"monthselect\">';\n            var inMinYear = false;\n            var inMaxYear = false;\n\n            for (var m = 0; m < 12; m++) {\n                if ((!inMinYear || m >= minDate.month()) && (!inMaxYear || m <= maxDate.month())) {\n                    monthHtml += \"<option value='\" + m + \"'\" +\n                        (m === currentMonth ? \" selected='selected'\" : \"\") +\n                        \">\" + this.locale.monthNames[m] + \"</option>\";\n                }\n            }\n            monthHtml += \"</select>\";\n\n            var currentYear = selected.year();\n            var maxYear = (maxDate && maxDate.year()) || (currentYear + 5);\n            var minYear = (minDate && minDate.year()) || (currentYear - 50);\n            var yearHtml = '<select class=\"yearselect\">';\n\n            for (var y = minYear; y <= maxYear; y++) {\n                yearHtml += '<option value=\"' + y + '\"' +\n                    (y === currentYear ? ' selected=\"selected\"' : '') +\n                    '>' + y + '</option>';\n            }\n\n            yearHtml += '</select>';\n\n            return monthHtml + yearHtml;\n        },\n\n        renderCalendar: function (calendar, selected, minDate, maxDate) {\n\n            var html = '<div class=\"calendar-date\">';\n            html += '<table class=\"table-condensed\">';\n            html += '<thead>';\n            html += '<tr>';\n\n            // add empty cell for week number\n            if (this.showWeekNumbers)\n                html += '<th></th>';\n\n            if (!minDate || minDate.isBefore(calendar[1][1])) {\n                html += '<th class=\"prev available\"><i class=\"fa fa-arrow-left icon-arrow-left glyphicon glyphicon-arrow-left\"></i></th>';\n            } else {\n                html += '<th></th>';\n            }\n\n            var dateHtml = this.locale.monthNames[calendar[1][1].month()] + calendar[1][1].format(\" YYYY\");\n\n            if (this.showDropdowns) {\n                dateHtml = this.renderDropdowns(calendar[1][1], minDate, maxDate);\n            }\n\n            html += '<th colspan=\"5\" class=\"month\">' + dateHtml + '</th>';\n            if (!maxDate || maxDate.isAfter(calendar[1][1])) {\n                html += '<th class=\"next available\"><i class=\"fa fa-arrow-right icon-arrow-right glyphicon glyphicon-arrow-right\"></i></th>';\n            } else {\n                html += '<th></th>';\n            }\n\n            html += '</tr>';\n            html += '<tr>';\n\n            // add week number label\n            if (this.showWeekNumbers)\n                html += '<th class=\"week\">' + this.locale.weekLabel + '</th>';\n\n            $.each(this.locale.daysOfWeek, function (index, dayOfWeek) {\n                html += '<th>' + dayOfWeek + '</th>';\n            });\n\n            html += '</tr>';\n            html += '</thead>';\n            html += '<tbody>';\n\n            for (var row = 0; row < 6; row++) {\n                html += '<tr>';\n\n                // add week number\n                if (this.showWeekNumbers)\n                    html += '<td class=\"week\">' + calendar[row][0].week() + '</td>';\n\n                for (var col = 0; col < 7; col++) {\n                    var cname = 'available ';\n                    cname += (calendar[row][col].month() == calendar[1][1].month()) ? '' : 'off';\n\n                    if ((minDate && calendar[row][col].isBefore(minDate, 'day')) || (maxDate && calendar[row][col].isAfter(maxDate, 'day'))) {\n                        cname = ' off disabled ';\n                    } else if (calendar[row][col].format('YYYY-MM-DD') == selected.format('YYYY-MM-DD')) {\n                        cname += ' active ';\n                        if (calendar[row][col].format('YYYY-MM-DD') == this.startDate.format('YYYY-MM-DD')) {\n                            cname += ' start-date ';\n                        }\n                        if (calendar[row][col].format('YYYY-MM-DD') == this.endDate.format('YYYY-MM-DD')) {\n                            cname += ' end-date ';\n                        }\n                    } else if (calendar[row][col] >= this.startDate && calendar[row][col] <= this.endDate) {\n                        cname += ' in-range ';\n                        if (calendar[row][col].isSame(this.startDate)) { cname += ' start-date '; }\n                        if (calendar[row][col].isSame(this.endDate)) { cname += ' end-date '; }\n                    }\n\n                    var title = 'r' + row + 'c' + col;\n                    html += '<td class=\"' + cname.replace(/\\s+/g, ' ').replace(/^\\s?(.*?)\\s?$/, '$1') + '\" data-title=\"' + title + '\">' + calendar[row][col].date() + '</td>';\n                }\n                html += '</tr>';\n            }\n\n            html += '</tbody>';\n            html += '</table>';\n            html += '</div>';\n\n            var i;\n            if (this.timePicker) {\n\n                html += '<div class=\"calendar-time\">';\n                html += '<select class=\"hourselect\">';\n                var start = 0;\n                var end = 23;\n                var selected_hour = selected.hour();\n                if (this.timePicker12Hour) {\n                    start = 1;\n                    end = 12;\n                    if (selected_hour >= 12)\n                        selected_hour -= 12;\n                    if (selected_hour === 0)\n                        selected_hour = 12;\n                }\n\n                for (i = start; i <= end; i++) {\n                    if (i == selected_hour) {\n                        html += '<option value=\"' + i + '\" selected=\"selected\">' + i + '</option>';\n                    } else {\n                        html += '<option value=\"' + i + '\">' + i + '</option>';\n                    }\n                }\n\n                html += '</select> : ';\n\n                html += '<select class=\"minuteselect\">';\n\n                for (i = 0; i < 60; i += this.timePickerIncrement) {\n                    var num = i;\n                    if (num < 10)\n                        num = '0' + num;\n                    if (i == selected.minute()) {\n                        html += '<option value=\"' + i + '\" selected=\"selected\">' + num + '</option>';\n                    } else {\n                        html += '<option value=\"' + i + '\">' + num + '</option>';\n                    }\n                }\n\n                html += '</select> ';\n\n                if (this.timePicker12Hour) {\n                    html += '<select class=\"ampmselect\">';\n                    if (selected.hour() >= 12) {\n                        html += '<option value=\"AM\">AM</option><option value=\"PM\" selected=\"selected\">PM</option>';\n                    } else {\n                        html += '<option value=\"AM\" selected=\"selected\">AM</option><option value=\"PM\">PM</option>';\n                    }\n                    html += '</select>';\n                }\n\n                html += '</div>';\n\n            }\n\n            return html;\n\n        },\n\n        remove: function() {\n\n            this.container.remove();\n            this.element.off('.daterangepicker');\n            this.element.removeData('daterangepicker');\n\n        }\n\n    };\n\n    $.fn.daterangepicker = function (options, cb) {\n        this.each(function () {\n            var el = $(this);\n            if (el.data('daterangepicker'))\n                el.data('daterangepicker').remove();\n            el.data('daterangepicker', new DateRangePicker(el, options, cb));\n        });\n        return this;\n    };\n\n}(window.jQuery, window.moment);"
  },
  {
    "path": "flowable-ui-web/task/libs/bootstrap-tour_0.9.1/bootstrap-tour.js",
    "content": "/* ===========================================================\n # bootstrap-tour - v0.9.1\n # http://bootstraptour.com\n # ==============================================================\n # Copyright 2012-2013 Ulrich Sossou\n #\n # Licensed under the Apache License, Version 2.0 (the \"License\");\n # you may not use this file except in compliance with the License.\n # You may obtain a copy of the License at\n #\n #     http://www.apache.org/licenses/LICENSE-2.0\n #\n # Unless required by applicable law or agreed to in writing, software\n # distributed under the License is distributed on an \"AS IS\" BASIS,\n # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n # See the License for the specific language governing permissions and\n # limitations under the License.\n */\n(function($, window) {\n    var Tour, document;\n    document = window.document;\n    Tour = (function() {\n        function Tour(options) {\n            this._options = $.extend({\n                name: \"tour\",\n                steps: [],\n                container: \"body\",\n                keyboard: true,\n                storage: window.localStorage,\n                debug: false,\n                backdrop: false,\n                redirect: true,\n                orphan: false,\n                duration: false,\n                basePath: \"\",\n                template: \"<div class='popover'> <div class='arrow'></div> <h3 class='popover-title'></h3> <div class='popover-content'></div> <div class='popover-navigation'> <div class='btn-group'> <button class='btn btn-sm btn-default' data-role='prev'>&laquo; Prev</button> <button class='btn btn-sm btn-default' data-role='next'>Next &raquo;</button> <button class='btn btn-sm btn-default' data-role='pause-resume' data-pause-text='Pause' data-resume-text='Resume'>Pause</button> </div> <button class='btn btn-sm btn-default' data-role='end'>End tour</button> </div> </div>\",\n                afterSetState: function(key, value) {},\n                afterGetState: function(key, value) {},\n                afterRemoveState: function(key) {},\n                onStart: function(tour) {},\n                onEnd: function(tour) {},\n                onShow: function(tour) {},\n                onShown: function(tour) {},\n                onHide: function(tour) {},\n                onHidden: function(tour) {},\n                onNext: function(tour) {},\n                onPrev: function(tour) {},\n                onPause: function(tour, duration) {},\n                onResume: function(tour, duration) {}\n            }, options);\n            this._force = false;\n            this._inited = false;\n            this.backdrop = {\n                overlay: null,\n                $element: null,\n                $background: null,\n                backgroundShown: false,\n                overlayElementShown: false\n            };\n            this;\n        }\n\n        Tour.prototype.addSteps = function(steps) {\n            var step, _i, _len;\n            for (_i = 0, _len = steps.length; _i < _len; _i++) {\n                step = steps[_i];\n                this.addStep(step);\n            }\n            return this;\n        };\n\n        Tour.prototype.addStep = function(step) {\n            this._options.steps.push(step);\n            return this;\n        };\n\n        Tour.prototype.getStep = function(i) {\n            if (this._options.steps[i] != null) {\n                return $.extend({\n                    id: \"step-\" + i,\n                    path: \"\",\n                    placement: \"right\",\n                    title: \"\",\n                    content: \"<p></p>\",\n                    next: i === this._options.steps.length - 1 ? -1 : i + 1,\n                    prev: i - 1,\n                    animation: true,\n                    container: this._options.container,\n                    backdrop: this._options.backdrop,\n                    redirect: this._options.redirect,\n                    orphan: this._options.orphan,\n                    duration: this._options.duration,\n                    template: this._options.template,\n                    onShow: this._options.onShow,\n                    onShown: this._options.onShown,\n                    onHide: this._options.onHide,\n                    onHidden: this._options.onHidden,\n                    onNext: this._options.onNext,\n                    onPrev: this._options.onPrev,\n                    onPause: this._options.onPause,\n                    onResume: this._options.onResume\n                }, this._options.steps[i]);\n            }\n        };\n\n        Tour.prototype.init = function(force) {\n            this._force = force;\n            if (this.ended()) {\n                this._debug(\"Tour ended, init prevented.\");\n                return this;\n            }\n            this.setCurrentStep();\n            this._initMouseNavigation();\n            this._initKeyboardNavigation();\n            this._onResize((function(_this) {\n                return function() {\n                    return _this.showStep(_this._current);\n                };\n            })(this));\n            if (this._current !== null) {\n                this.showStep(this._current);\n            }\n            this._inited = true;\n            return this;\n        };\n\n        Tour.prototype.start = function(force) {\n            var promise;\n            if (force == null) {\n                force = false;\n            }\n            if (!this._inited) {\n                this.init(force);\n            }\n            if (this._current === null) {\n                promise = this._makePromise(this._options.onStart != null ? this._options.onStart(this) : void 0);\n                this._callOnPromiseDone(promise, this.showStep, 0);\n            }\n            return this;\n        };\n\n        Tour.prototype.next = function() {\n            var promise;\n            promise = this.hideStep(this._current);\n            return this._callOnPromiseDone(promise, this._showNextStep);\n        };\n\n        Tour.prototype.prev = function() {\n            var promise;\n            promise = this.hideStep(this._current);\n            return this._callOnPromiseDone(promise, this._showPrevStep);\n        };\n\n        Tour.prototype.goTo = function(i) {\n            var promise;\n            promise = this.hideStep(this._current);\n            return this._callOnPromiseDone(promise, this.showStep, i);\n        };\n\n        Tour.prototype.end = function() {\n            var endHelper, promise;\n            endHelper = (function(_this) {\n                return function(e) {\n                    $(document).off(\"click.tour-\" + _this._options.name);\n                    $(document).off(\"keyup.tour-\" + _this._options.name);\n                    $(window).off(\"resize.tour-\" + _this._options.name);\n                    _this._setState(\"end\", \"yes\");\n                    _this._inited = false;\n                    _this._force = false;\n                    _this._clearTimer();\n                    if (_this._options.onEnd != null) {\n                        return _this._options.onEnd(_this);\n                    }\n                };\n            })(this);\n            promise = this.hideStep(this._current);\n            return this._callOnPromiseDone(promise, endHelper);\n        };\n\n        Tour.prototype.ended = function() {\n            return !this._force && !!this._getState(\"end\");\n        };\n\n        Tour.prototype.restart = function() {\n            this._removeState(\"current_step\");\n            this._removeState(\"end\");\n            this.setCurrentStep(0);\n            return this.start();\n        };\n\n        Tour.prototype.pause = function() {\n            var step;\n            step = this.getStep(this._current);\n            if (!(step && step.duration)) {\n                return this;\n            }\n            this._paused = true;\n            this._duration -= new Date().getTime() - this._start;\n            window.clearTimeout(this._timer);\n            this._debug(\"Paused/Stopped step \" + (this._current + 1) + \" timer (\" + this._duration + \" remaining).\");\n            if (step.onPause != null) {\n                return step.onPause(this, this._duration);\n            }\n        };\n\n        Tour.prototype.resume = function() {\n            var step;\n            step = this.getStep(this._current);\n            if (!(step && step.duration)) {\n                return this;\n            }\n            this._paused = false;\n            this._start = new Date().getTime();\n            this._duration = this._duration || step.duration;\n            this._timer = window.setTimeout((function(_this) {\n                return function() {\n                    if (_this._isLast()) {\n                        return _this.next();\n                    } else {\n                        return _this.end();\n                    }\n                };\n            })(this), this._duration);\n            this._debug(\"Started step \" + (this._current + 1) + \" timer with duration \" + this._duration);\n            if ((step.onResume != null) && this._duration !== step.duration) {\n                return step.onResume(this, this._duration);\n            }\n        };\n\n        Tour.prototype.hideStep = function(i) {\n            var hideStepHelper, promise, step;\n            step = this.getStep(i);\n            if (!step) {\n                return;\n            }\n            this._clearTimer();\n            promise = this._makePromise(step.onHide != null ? step.onHide(this, i) : void 0);\n            hideStepHelper = (function(_this) {\n                return function(e) {\n                    var $element;\n                    $element = $(step.element);\n                    if (!($element.data(\"bs.popover\") || $element.data(\"popover\"))) {\n                        $element = $(\"body\");\n                    }\n                    $element.popover(\"destroy\").removeClass(\"tour-\" + _this._options.name + \"-element tour-\" + _this._options.name + \"-\" + i + \"-element\");\n                    if (step.reflex) {\n                        $element.css(\"cursor\", \"\").off(\"click.tour-\" + _this._options.name);\n                    }\n                    if (step.backdrop) {\n                        _this._hideBackdrop();\n                    }\n                    if (step.onHidden != null) {\n                        return step.onHidden(_this);\n                    }\n                };\n            })(this);\n            this._callOnPromiseDone(promise, hideStepHelper);\n            return promise;\n        };\n\n        Tour.prototype.showStep = function(i) {\n            var promise, showStepHelper, skipToPrevious, step;\n            if (this.ended()) {\n                this._debug(\"Tour ended, showStep prevented.\");\n                return this;\n            }\n            step = this.getStep(i);\n            if (!step) {\n                return;\n            }\n            skipToPrevious = i < this._current;\n            promise = this._makePromise(step.onShow != null ? step.onShow(this, i) : void 0);\n            showStepHelper = (function(_this) {\n                return function(e) {\n                    var current_path, path;\n                    _this.setCurrentStep(i);\n                    path = (function() {\n                        switch ({}.toString.call(step.path)) {\n                            case \"[object Function]\":\n                                return step.path();\n                            case \"[object String]\":\n                                return this._options.basePath + step.path;\n                            default:\n                                return step.path;\n                        }\n                    }).call(_this);\n                    current_path = [document.location.pathname, document.location.hash].join(\"\");\n                    if (_this._isRedirect(path, current_path)) {\n                        _this._redirect(step, path);\n                        return;\n                    }\n                    if (_this._isOrphan(step)) {\n                        if (!step.orphan) {\n                            _this._debug(\"Skip the orphan step \" + (_this._current + 1) + \". Orphan option is false and the element doesn't exist or is hidden.\");\n                            if (skipToPrevious) {\n                                _this._showPrevStep();\n                            } else {\n                                _this._showNextStep();\n                            }\n                            return;\n                        }\n                        _this._debug(\"Show the orphan step \" + (_this._current + 1) + \". Orphans option is true.\");\n                    }\n                    if (step.backdrop) {\n                        _this._showBackdrop(!_this._isOrphan(step) ? step.element : void 0);\n                    }\n                    _this._scrollIntoView(step.element, function() {\n                        if ((step.element != null) && step.backdrop) {\n                            _this._showOverlayElement(step.element);\n                        }\n                        _this._showPopover(step, i);\n                        if (step.onShown != null) {\n                            step.onShown(_this);\n                        }\n                        return _this._debug(\"Step \" + (_this._current + 1) + \" of \" + _this._options.steps.length);\n                    });\n                    if (step.duration) {\n                        return _this.resume();\n                    }\n                };\n            })(this);\n            this._callOnPromiseDone(promise, showStepHelper);\n            return promise;\n        };\n\n        Tour.prototype.getCurrentStep = function() {\n            return this._current;\n        };\n\n        Tour.prototype.setCurrentStep = function(value) {\n            if (value != null) {\n                this._current = value;\n                this._setState(\"current_step\", value);\n            } else {\n                this._current = this._getState(\"current_step\");\n                this._current = this._current === null ? null : parseInt(this._current, 10);\n            }\n            return this;\n        };\n\n        Tour.prototype._setState = function(key, value) {\n            var e, keyName;\n            if (this._options.storage) {\n                keyName = \"\" + this._options.name + \"_\" + key;\n                try {\n                    this._options.storage.setItem(keyName, value);\n                } catch (_error) {\n                    e = _error;\n                    if (e.code === DOMException.QUOTA_EXCEEDED_ERR) {\n                        this.debug(\"LocalStorage quota exceeded. State storage failed.\");\n                    }\n                }\n                return this._options.afterSetState(keyName, value);\n            } else {\n                if (this._state == null) {\n                    this._state = {};\n                }\n                return this._state[key] = value;\n            }\n        };\n\n        Tour.prototype._removeState = function(key) {\n            var keyName;\n            if (this._options.storage) {\n                keyName = \"\" + this._options.name + \"_\" + key;\n                this._options.storage.removeItem(keyName);\n                return this._options.afterRemoveState(keyName);\n            } else {\n                if (this._state != null) {\n                    return delete this._state[key];\n                }\n            }\n        };\n\n        Tour.prototype._getState = function(key) {\n            var keyName, value;\n            if (this._options.storage) {\n                keyName = \"\" + this._options.name + \"_\" + key;\n                value = this._options.storage.getItem(keyName);\n            } else {\n                if (this._state != null) {\n                    value = this._state[key];\n                }\n            }\n            if (value === void 0 || value === \"null\") {\n                value = null;\n            }\n            this._options.afterGetState(key, value);\n            return value;\n        };\n\n        Tour.prototype._showNextStep = function() {\n            var promise, showNextStepHelper, step;\n            step = this.getStep(this._current);\n            showNextStepHelper = (function(_this) {\n                return function(e) {\n                    return _this.showStep(step.next);\n                };\n            })(this);\n            promise = this._makePromise(step.onNext != null ? step.onNext(this) : void 0);\n            return this._callOnPromiseDone(promise, showNextStepHelper);\n        };\n\n        Tour.prototype._showPrevStep = function() {\n            var promise, showPrevStepHelper, step;\n            step = this.getStep(this._current);\n            showPrevStepHelper = (function(_this) {\n                return function(e) {\n                    return _this.showStep(step.prev);\n                };\n            })(this);\n            promise = this._makePromise(step.onPrev != null ? step.onPrev(this) : void 0);\n            return this._callOnPromiseDone(promise, showPrevStepHelper);\n        };\n\n        Tour.prototype._debug = function(text) {\n            if (this._options.debug) {\n                return window.console.log(\"Bootstrap Tour '\" + this._options.name + \"' | \" + text);\n            }\n        };\n\n        Tour.prototype._isRedirect = function(path, currentPath) {\n            return (path != null) && path !== \"\" && ((toString.call(path) === \"[object RegExp]\" && !path.test(currentPath)) || (toString.call(path) === \"[object String]\" && path.replace(/\\?.*$/, \"\").replace(/\\/?$/, \"\") !== currentPath.replace(/\\/?$/, \"\")));\n        };\n\n        Tour.prototype._redirect = function(step, path) {\n            if ($.isFunction(step.redirect)) {\n                return step.redirect.call(this, path);\n            } else if (step.redirect === true) {\n                this._debug(\"Redirect to \" + path);\n                return document.location.href = path;\n            }\n        };\n\n        Tour.prototype._isOrphan = function(step) {\n            return (step.element == null) || !$(step.element).length || $(step.element).is(\":hidden\") && ($(step.element)[0].namespaceURI !== \"http://www.w3.org/2000/svg\");\n        };\n\n        Tour.prototype._isLast = function() {\n            return this._current < this._options.steps.length - 1;\n        };\n\n        Tour.prototype._showPopover = function(step, i) {\n            var $element, $navigation, $template, $tip, isOrphan, options;\n            options = $.extend({}, this._options);\n            $template = $.isFunction(step.template) ? $(step.template(i, step)) : $(step.template);\n            $navigation = $template.find(\".popover-navigation\");\n            isOrphan = this._isOrphan(step);\n            if (isOrphan) {\n                step.element = \"body\";\n                step.placement = \"top\";\n                $template = $template.addClass(\"orphan\");\n            }\n            $element = $(step.element);\n            $template.addClass(\"tour-\" + this._options.name + \" tour-\" + this._options.name + \"-\" + i);\n            $element.addClass(\"tour-\" + this._options.name + \"-element tour-\" + this._options.name + \"-\" + i + \"-element\");\n            if (step.options) {\n                $.extend(options, step.options);\n            }\n            if (step.reflex) {\n                $element.css(\"cursor\", \"pointer\").on(\"click.tour-\" + this._options.name, (function(_this) {\n                    return function() {\n                        if (_this._isLast()) {\n                            return _this.next();\n                        } else {\n                            return _this.end();\n                        }\n                    };\n                })(this));\n            }\n            if (step.prev < 0) {\n                $navigation.find(\"[data-role='prev']\").addClass(\"disabled\");\n            }\n            if (step.next < 0) {\n                $navigation.find(\"[data-role='next']\").addClass(\"disabled\");\n            }\n            if (!step.duration) {\n                $navigation.find(\"[data-role='pause-resume']\").remove();\n            }\n            step.template = $template.clone().wrap(\"<div>\").parent().html();\n            $element.popover({\n                placement: step.placement,\n                trigger: \"manual\",\n                title: step.title,\n                content: step.content,\n                html: true,\n                animation: step.animation,\n                container: step.container,\n                template: step.template,\n                selector: step.element\n            }).popover(\"show\");\n            $tip = $element.data(\"bs.popover\") ? $element.data(\"bs.popover\").tip() : $element.data(\"popover\").tip();\n            $tip.attr(\"id\", step.id);\n            this._reposition($tip, step);\n            if (isOrphan) {\n                return this._center($tip);\n            }\n        };\n\n        Tour.prototype._reposition = function($tip, step) {\n            var offsetBottom, offsetHeight, offsetRight, offsetWidth, originalLeft, originalTop, tipOffset;\n            offsetWidth = $tip[0].offsetWidth;\n            offsetHeight = $tip[0].offsetHeight;\n            tipOffset = $tip.offset();\n            originalLeft = tipOffset.left;\n            originalTop = tipOffset.top;\n            offsetBottom = $(document).outerHeight() - tipOffset.top - $tip.outerHeight();\n            if (offsetBottom < 0) {\n                tipOffset.top = tipOffset.top + offsetBottom;\n            }\n            offsetRight = $(\"html\").outerWidth() - tipOffset.left - $tip.outerWidth();\n            if (offsetRight < 0) {\n                tipOffset.left = tipOffset.left + offsetRight;\n            }\n            if (tipOffset.top < 0) {\n                tipOffset.top = 0;\n            }\n            if (tipOffset.left < 0) {\n                tipOffset.left = 0;\n            }\n            $tip.offset(tipOffset);\n            if (step.placement === \"bottom\" || step.placement === \"top\") {\n                if (originalLeft !== tipOffset.left) {\n                    return this._replaceArrow($tip, (tipOffset.left - originalLeft) * 2, offsetWidth, \"left\");\n                }\n            } else {\n                if (originalTop !== tipOffset.top) {\n                    return this._replaceArrow($tip, (tipOffset.top - originalTop) * 2, offsetHeight, \"top\");\n                }\n            }\n        };\n\n        Tour.prototype._center = function($tip) {\n            return $tip.css(\"top\", $(window).outerHeight() / 2 - $tip.outerHeight() / 2);\n        };\n\n        Tour.prototype._replaceArrow = function($tip, delta, dimension, position) {\n            return $tip.find(\".arrow\").css(position, delta ? 50 * (1 - delta / dimension) + \"%\" : \"\");\n        };\n\n        Tour.prototype._scrollIntoView = function(element, callback) {\n            var $element, $window, counter, offsetTop, scrollTop, windowHeight;\n            $element = $(element);\n            if (!$element.length) {\n                return callback();\n            }\n            $window = $(window);\n            offsetTop = $element.offset().top;\n            windowHeight = $window.height();\n            scrollTop = Math.max(0, offsetTop - (windowHeight / 2));\n            this._debug(\"Scroll into view. ScrollTop: \" + scrollTop + \". Element offset: \" + offsetTop + \". Window height: \" + windowHeight + \".\");\n            counter = 0;\n            return $(\"body,html\").stop(true, true).animate({\n                scrollTop: Math.ceil(scrollTop)\n            }, (function(_this) {\n                return function() {\n                    if (++counter === 2) {\n                        callback();\n                        return _this._debug(\"Scroll into view. Animation end element offset: \" + ($element.offset().top) + \". Window height: \" + ($window.height()) + \".\");\n                    }\n                };\n            })(this));\n        };\n\n        Tour.prototype._onResize = function(callback, timeout) {\n            return $(window).on(\"resize.tour-\" + this._options.name, function() {\n                clearTimeout(timeout);\n                return timeout = setTimeout(callback, 100);\n            });\n        };\n\n        Tour.prototype._initMouseNavigation = function() {\n            var _this;\n            _this = this;\n            return $(document).off(\"click.tour-\" + this._options.name, \".popover.tour-\" + this._options.name + \" *[data-role='prev']:not(.disabled)\").off(\"click.tour-\" + this._options.name, \".popover.tour-\" + this._options.name + \" *[data-role='next']:not(.disabled)\").off(\"click.tour-\" + this._options.name, \".popover.tour-\" + this._options.name + \" *[data-role='end']\").off(\"click.tour-\" + this._options.name, \".popover.tour-\" + this._options.name + \" *[data-role='pause-resume']\").on(\"click.tour-\" + this._options.name, \".popover.tour-\" + this._options.name + \" *[data-role='next']:not(.disabled)\", (function(_this) {\n                return function(e) {\n                    e.preventDefault();\n                    return _this.next();\n                };\n            })(this)).on(\"click.tour-\" + this._options.name, \".popover.tour-\" + this._options.name + \" *[data-role='prev']:not(.disabled)\", (function(_this) {\n                return function(e) {\n                    e.preventDefault();\n                    return _this.prev();\n                };\n            })(this)).on(\"click.tour-\" + this._options.name, \".popover.tour-\" + this._options.name + \" *[data-role='end']\", (function(_this) {\n                return function(e) {\n                    e.preventDefault();\n                    return _this.end();\n                };\n            })(this)).on(\"click.tour-\" + this._options.name, \".popover.tour-\" + this._options.name + \" *[data-role='pause-resume']\", function(e) {\n                var $this;\n                e.preventDefault();\n                $this = $(this);\n                $this.text(_this._paused ? $this.data(\"pause-text\") : $this.data(\"resume-text\"));\n                if (_this._paused) {\n                    return _this.resume();\n                } else {\n                    return _this.pause();\n                }\n            });\n        };\n\n        Tour.prototype._initKeyboardNavigation = function() {\n            if (!this._options.keyboard) {\n                return;\n            }\n            return $(document).on(\"keyup.tour-\" + this._options.name, (function(_this) {\n                return function(e) {\n                    if (!e.which) {\n                        return;\n                    }\n                    switch (e.which) {\n                        case 39:\n                            e.preventDefault();\n                            if (_this._isLast()) {\n                                return _this.next();\n                            } else {\n                                return _this.end();\n                            }\n                            break;\n                        case 37:\n                            e.preventDefault();\n                            if (_this._current > 0) {\n                                return _this.prev();\n                            }\n                            break;\n                        case 27:\n                            e.preventDefault();\n                            return _this.end();\n                    }\n                };\n            })(this));\n        };\n\n        Tour.prototype._makePromise = function(result) {\n            if (result && $.isFunction(result.then)) {\n                return result;\n            } else {\n                return null;\n            }\n        };\n\n        Tour.prototype._callOnPromiseDone = function(promise, cb, arg) {\n            if (promise) {\n                return promise.then((function(_this) {\n                    return function(e) {\n                        return cb.call(_this, arg);\n                    };\n                })(this));\n            } else {\n                return cb.call(this, arg);\n            }\n        };\n\n        Tour.prototype._showBackdrop = function(element) {\n            if (this.backdrop.backgroundShown) {\n                return;\n            }\n            this.backdrop = $(\"<div/>\", {\n                \"class\": \"tour-backdrop\"\n            });\n            this.backdrop.backgroundShown = true;\n            return $(\"body\").append(this.backdrop);\n        };\n\n        Tour.prototype._hideBackdrop = function() {\n            this._hideOverlayElement();\n            return this._hideBackground();\n        };\n\n        Tour.prototype._hideBackground = function() {\n            this.backdrop.remove();\n            this.backdrop.overlay = null;\n            return this.backdrop.backgroundShown = false;\n        };\n\n        Tour.prototype._showOverlayElement = function(element) {\n            var $background, $element, offset;\n            $element = $(element);\n            if (!$element || $element.length === 0 || this.backdrop.overlayElementShown) {\n                return;\n            }\n            this.backdrop.overlayElementShown = true;\n            $background = $(\"<div/>\");\n            offset = $element.offset();\n            offset.top = offset.top;\n            offset.left = offset.left;\n            $background.width($element.innerWidth()).height($element.innerHeight()).addClass(\"tour-step-background\").offset(offset);\n            $element.addClass(\"tour-step-backdrop\");\n            $(\"body\").append($background);\n            this.backdrop.$element = $element;\n            return this.backdrop.$background = $background;\n        };\n\n        Tour.prototype._hideOverlayElement = function() {\n            if (!this.backdrop.overlayElementShown) {\n                return;\n            }\n            this.backdrop.$element.removeClass(\"tour-step-backdrop\");\n            this.backdrop.$background.remove();\n            this.backdrop.$element = null;\n            this.backdrop.$background = null;\n            return this.backdrop.overlayElementShown = false;\n        };\n\n        Tour.prototype._clearTimer = function() {\n            window.clearTimeout(this._timer);\n            this._timer = null;\n            return this._duration = null;\n        };\n\n        return Tour;\n\n    })();\n    return window.Tour = Tour;\n})(jQuery, window);"
  },
  {
    "path": "flowable-ui-web/task/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": "flowable-ui-web/task/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": "flowable-ui-web/task/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": "flowable-ui-web/task/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": "flowable-ui-web/task/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": "flowable-ui-web/task/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": "flowable-ui-web/task/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": "flowable-ui-web/task/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": "flowable-ui-web/task/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": "flowable-ui-web/task/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": "flowable-ui-web/task/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": "flowable-ui-web/task/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": "flowable-ui-web/task/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": "flowable-ui-web/task/libs/es5-shim-15.3.4.5/tests/helpers/h.js",
    "content": "function implement() {\n    throw 'Not implemented';\n}"
  },
  {
    "path": "flowable-ui-web/task/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": "flowable-ui-web/task/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": "flowable-ui-web/task/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": "flowable-ui-web/task/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": "flowable-ui-web/task/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": "flowable-ui-web/task/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": "flowable-ui-web/task/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": "flowable-ui-web/task/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": "flowable-ui-web/task/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": "flowable-ui-web/task/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": "flowable-ui-web/task/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": "flowable-ui-web/task/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": "flowable-ui-web/task/libs/html2canvas_0.4.1/html2canvas.js",
    "content": "/*\n  html2canvas 0.4.1 <http://html2canvas.hertzen.com>\n  Copyright (c) 2013 Niklas von Hertzen\n\n  Released under MIT License\n*/\n\n(function(window, document, undefined){\n\n\"use strict\";\n\nvar _html2canvas = {},\npreviousElement,\ncomputedCSS,\nhtml2canvas;\n\n_html2canvas.Util = {};\n\n_html2canvas.Util.log = function(a) {\n  if (_html2canvas.logging && window.console && window.console.log) {\n    window.console.log(a);\n  }\n};\n\n_html2canvas.Util.trimText = (function(isNative){\n  return function(input) {\n    return isNative ? isNative.apply(input) : ((input || '') + '').replace( /^\\s+|\\s+$/g , '' );\n  };\n})(String.prototype.trim);\n\n_html2canvas.Util.asFloat = function(v) {\n  return parseFloat(v);\n};\n\n(function() {\n  // TODO: support all possible length values\n  var TEXT_SHADOW_PROPERTY = /((rgba|rgb)\\([^\\)]+\\)(\\s-?\\d+px){0,})/g;\n  var TEXT_SHADOW_VALUES = /(-?\\d+px)|(#.+)|(rgb\\(.+\\))|(rgba\\(.+\\))/g;\n  _html2canvas.Util.parseTextShadows = function (value) {\n    if (!value || value === 'none') {\n      return [];\n    }\n\n    // find multiple shadow declarations\n    var shadows = value.match(TEXT_SHADOW_PROPERTY),\n      results = [];\n    for (var i = 0; shadows && (i < shadows.length); i++) {\n      var s = shadows[i].match(TEXT_SHADOW_VALUES);\n      results.push({\n        color: s[0],\n        offsetX: s[1] ? s[1].replace('px', '') : 0,\n        offsetY: s[2] ? s[2].replace('px', '') : 0,\n        blur: s[3] ? s[3].replace('px', '') : 0\n      });\n    }\n    return results;\n  };\n})();\n\n\n_html2canvas.Util.parseBackgroundImage = function (value) {\n    var whitespace = ' \\r\\n\\t',\n        method, definition, prefix, prefix_i, block, results = [],\n        c, mode = 0, numParen = 0, quote, args;\n\n    var appendResult = function(){\n        if(method) {\n            if(definition.substr( 0, 1 ) === '\"') {\n                definition = definition.substr( 1, definition.length - 2 );\n            }\n            if(definition) {\n                args.push(definition);\n            }\n            if(method.substr( 0, 1 ) === '-' &&\n                    (prefix_i = method.indexOf( '-', 1 ) + 1) > 0) {\n                prefix = method.substr( 0, prefix_i);\n                method = method.substr( prefix_i );\n            }\n            results.push({\n                prefix: prefix,\n                method: method.toLowerCase(),\n                value: block,\n                args: args\n            });\n        }\n        args = []; //for some odd reason, setting .length = 0 didn't work in safari\n        method =\n            prefix =\n            definition =\n            block = '';\n    };\n\n    appendResult();\n    for(var i = 0, ii = value.length; i<ii; i++) {\n        c = value[i];\n        if(mode === 0 && whitespace.indexOf( c ) > -1){\n            continue;\n        }\n        switch(c) {\n            case '\"':\n                if(!quote) {\n                    quote = c;\n                }\n                else if(quote === c) {\n                    quote = null;\n                }\n                break;\n\n            case '(':\n                if(quote) { break; }\n                else if(mode === 0) {\n                    mode = 1;\n                    block += c;\n                    continue;\n                } else {\n                    numParen++;\n                }\n                break;\n\n            case ')':\n                if(quote) { break; }\n                else if(mode === 1) {\n                    if(numParen === 0) {\n                        mode = 0;\n                        block += c;\n                        appendResult();\n                        continue;\n                    } else {\n                        numParen--;\n                    }\n                }\n                break;\n\n            case ',':\n                if(quote) { break; }\n                else if(mode === 0) {\n                    appendResult();\n                    continue;\n                }\n                else if (mode === 1) {\n                    if(numParen === 0 && !method.match(/^url$/i)) {\n                        args.push(definition);\n                        definition = '';\n                        block += c;\n                        continue;\n                    }\n                }\n                break;\n        }\n\n        block += c;\n        if(mode === 0) { method += c; }\n        else { definition += c; }\n    }\n    appendResult();\n\n    return results;\n};\n\n_html2canvas.Util.Bounds = function (element) {\n  var clientRect, bounds = {};\n\n  if (element.getBoundingClientRect){\n    clientRect = element.getBoundingClientRect();\n\n    // TODO add scroll position to bounds, so no scrolling of window necessary\n    bounds.top = clientRect.top;\n    bounds.bottom = clientRect.bottom || (clientRect.top + clientRect.height);\n    bounds.left = clientRect.left;\n\n    bounds.width = element.offsetWidth;\n    bounds.height = element.offsetHeight;\n  }\n\n  return bounds;\n};\n\n// TODO ideally, we'd want everything to go through this function instead of Util.Bounds,\n// but would require further work to calculate the correct positions for elements with offsetParents\n_html2canvas.Util.OffsetBounds = function (element) {\n  var parent = element.offsetParent ? _html2canvas.Util.OffsetBounds(element.offsetParent) : {top: 0, left: 0};\n\n  return {\n    top: element.offsetTop + parent.top,\n    bottom: element.offsetTop + element.offsetHeight + parent.top,\n    left: element.offsetLeft + parent.left,\n    width: element.offsetWidth,\n    height: element.offsetHeight\n  };\n};\n\nfunction toPX(element, attribute, value ) {\n    var rsLeft = element.runtimeStyle && element.runtimeStyle[attribute],\n        left,\n        style = element.style;\n\n    // Check if we are not dealing with pixels, (Opera has issues with this)\n    // Ported from jQuery css.js\n    // From the awesome hack by Dean Edwards\n    // http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291\n\n    // If we're not dealing with a regular pixel number\n    // but a number that has a weird ending, we need to convert it to pixels\n\n    if ( !/^-?[0-9]+\\.?[0-9]*(?:px)?$/i.test( value ) && /^-?\\d/.test(value) ) {\n        // Remember the original values\n        left = style.left;\n\n        // Put in the new values to get a computed value out\n        if (rsLeft) {\n            element.runtimeStyle.left = element.currentStyle.left;\n        }\n        style.left = attribute === \"fontSize\" ? \"1em\" : (value || 0);\n        value = style.pixelLeft + \"px\";\n\n        // Revert the changed values\n        style.left = left;\n        if (rsLeft) {\n            element.runtimeStyle.left = rsLeft;\n        }\n    }\n\n    if (!/^(thin|medium|thick)$/i.test(value)) {\n        return Math.round(parseFloat(value)) + \"px\";\n    }\n\n    return value;\n}\n\nfunction asInt(val) {\n    return parseInt(val, 10);\n}\n\nfunction parseBackgroundSizePosition(value, element, attribute, index) {\n    value = (value || '').split(',');\n    value = value[index || 0] || value[0] || 'auto';\n    value = _html2canvas.Util.trimText(value).split(' ');\n\n    if(attribute === 'backgroundSize' && (!value[0] || value[0].match(/cover|contain|auto/))) {\n        //these values will be handled in the parent function\n    } else {\n        value[0] = (value[0].indexOf( \"%\" ) === -1) ? toPX(element, attribute + \"X\", value[0]) : value[0];\n        if(value[1] === undefined) {\n            if(attribute === 'backgroundSize') {\n                value[1] = 'auto';\n                return value;\n            } else {\n                // IE 9 doesn't return double digit always\n                value[1] = value[0];\n            }\n        }\n        value[1] = (value[1].indexOf(\"%\") === -1) ? toPX(element, attribute + \"Y\", value[1]) : value[1];\n    }\n    return value;\n}\n\n_html2canvas.Util.getCSS = function (element, attribute, index) {\n    if (previousElement !== element) {\n      computedCSS = document.defaultView.getComputedStyle(element, null);\n    }\n\n    var value = computedCSS[attribute];\n\n    if (/^background(Size|Position)$/.test(attribute)) {\n        return parseBackgroundSizePosition(value, element, attribute, index);\n    } else if (/border(Top|Bottom)(Left|Right)Radius/.test(attribute)) {\n      var arr = value.split(\" \");\n      if (arr.length <= 1) {\n          arr[1] = arr[0];\n      }\n      return arr.map(asInt);\n    }\n\n  return value;\n};\n\n_html2canvas.Util.resizeBounds = function( current_width, current_height, target_width, target_height, stretch_mode ){\n  var target_ratio = target_width / target_height,\n    current_ratio = current_width / current_height,\n    output_width, output_height;\n\n  if(!stretch_mode || stretch_mode === 'auto') {\n    output_width = target_width;\n    output_height = target_height;\n  } else if(target_ratio < current_ratio ^ stretch_mode === 'contain') {\n    output_height = target_height;\n    output_width = target_height * current_ratio;\n  } else {\n    output_width = target_width;\n    output_height = target_width / current_ratio;\n  }\n\n  return {\n    width: output_width,\n    height: output_height\n  };\n};\n\nfunction backgroundBoundsFactory( prop, el, bounds, image, imageIndex, backgroundSize ) {\n    var bgposition =  _html2canvas.Util.getCSS( el, prop, imageIndex ) ,\n    topPos,\n    left,\n    percentage,\n    val;\n\n    if (bgposition.length === 1){\n      val = bgposition[0];\n\n      bgposition = [];\n\n      bgposition[0] = val;\n      bgposition[1] = val;\n    }\n\n    if (bgposition[0].toString().indexOf(\"%\") !== -1){\n      percentage = (parseFloat(bgposition[0])/100);\n      left = bounds.width * percentage;\n      if(prop !== 'backgroundSize') {\n        left -= (backgroundSize || image).width*percentage;\n      }\n    } else {\n      if(prop === 'backgroundSize') {\n        if(bgposition[0] === 'auto') {\n          left = image.width;\n        } else {\n          if (/contain|cover/.test(bgposition[0])) {\n            var resized = _html2canvas.Util.resizeBounds(image.width, image.height, bounds.width, bounds.height, bgposition[0]);\n            left = resized.width;\n            topPos = resized.height;\n          } else {\n            left = parseInt(bgposition[0], 10);\n          }\n        }\n      } else {\n        left = parseInt( bgposition[0], 10);\n      }\n    }\n\n\n    if(bgposition[1] === 'auto') {\n      topPos = left / image.width * image.height;\n    } else if (bgposition[1].toString().indexOf(\"%\") !== -1){\n      percentage = (parseFloat(bgposition[1])/100);\n      topPos =  bounds.height * percentage;\n      if(prop !== 'backgroundSize') {\n        topPos -= (backgroundSize || image).height * percentage;\n      }\n\n    } else {\n      topPos = parseInt(bgposition[1],10);\n    }\n\n    return [left, topPos];\n}\n\n_html2canvas.Util.BackgroundPosition = function( el, bounds, image, imageIndex, backgroundSize ) {\n    var result = backgroundBoundsFactory( 'backgroundPosition', el, bounds, image, imageIndex, backgroundSize );\n    return { left: result[0], top: result[1] };\n};\n\n_html2canvas.Util.BackgroundSize = function( el, bounds, image, imageIndex ) {\n    var result = backgroundBoundsFactory( 'backgroundSize', el, bounds, image, imageIndex );\n    return { width: result[0], height: result[1] };\n};\n\n_html2canvas.Util.Extend = function (options, defaults) {\n  for (var key in options) {\n    if (options.hasOwnProperty(key)) {\n      defaults[key] = options[key];\n    }\n  }\n  return defaults;\n};\n\n\n/*\n * Derived from jQuery.contents()\n * Copyright 2010, John Resig\n * Dual licensed under the MIT or GPL Version 2 licenses.\n * http://jquery.org/license\n */\n_html2canvas.Util.Children = function( elem ) {\n  var children;\n  try {\n    children = (elem.nodeName && elem.nodeName.toUpperCase() === \"IFRAME\") ? elem.contentDocument || elem.contentWindow.document : (function(array) {\n      var ret = [];\n      if (array !== null) {\n        (function(first, second ) {\n          var i = first.length,\n          j = 0;\n\n          if (typeof second.length === \"number\") {\n            for (var l = second.length; j < l; j++) {\n              first[i++] = second[j];\n            }\n          } else {\n            while (second[j] !== undefined) {\n              first[i++] = second[j++];\n            }\n          }\n\n          first.length = i;\n\n          return first;\n        })(ret, array);\n      }\n      return ret;\n    })(elem.childNodes);\n\n  } catch (ex) {\n    _html2canvas.Util.log(\"html2canvas.Util.Children failed with exception: \" + ex.message);\n    children = [];\n  }\n  return children;\n};\n\n_html2canvas.Util.isTransparent = function(backgroundColor) {\n  return (backgroundColor === \"transparent\" || backgroundColor === \"rgba(0, 0, 0, 0)\");\n};\n_html2canvas.Util.Font = (function () {\n\n  var fontData = {};\n\n  return function(font, fontSize, doc) {\n    if (fontData[font + \"-\" + fontSize] !== undefined) {\n      return fontData[font + \"-\" + fontSize];\n    }\n\n    var container = doc.createElement('div'),\n    img = doc.createElement('img'),\n    span = doc.createElement('span'),\n    sampleText = 'Hidden Text',\n    baseline,\n    middle,\n    metricsObj;\n\n    container.style.visibility = \"hidden\";\n    container.style.fontFamily = font;\n    container.style.fontSize = fontSize;\n    container.style.margin = 0;\n    container.style.padding = 0;\n\n    doc.body.appendChild(container);\n\n    // http://probablyprogramming.com/2009/03/15/the-tiniest-gif-ever (handtinywhite.gif)\n    img.src = \"data:image/gif;base64,R0lGODlhAQABAIABAP///wAAACwAAAAAAQABAAACAkQBADs=\";\n    img.width = 1;\n    img.height = 1;\n\n    img.style.margin = 0;\n    img.style.padding = 0;\n    img.style.verticalAlign = \"baseline\";\n\n    span.style.fontFamily = font;\n    span.style.fontSize = fontSize;\n    span.style.margin = 0;\n    span.style.padding = 0;\n\n    span.appendChild(doc.createTextNode(sampleText));\n    container.appendChild(span);\n    container.appendChild(img);\n    baseline = (img.offsetTop - span.offsetTop) + 1;\n\n    container.removeChild(span);\n    container.appendChild(doc.createTextNode(sampleText));\n\n    container.style.lineHeight = \"normal\";\n    img.style.verticalAlign = \"super\";\n\n    middle = (img.offsetTop-container.offsetTop) + 1;\n    metricsObj = {\n      baseline: baseline,\n      lineWidth: 1,\n      middle: middle\n    };\n\n    fontData[font + \"-\" + fontSize] = metricsObj;\n\n    doc.body.removeChild(container);\n\n    return metricsObj;\n  };\n})();\n\n(function(){\n  var Util = _html2canvas.Util,\n    Generate = {};\n\n  _html2canvas.Generate = Generate;\n\n  var reGradients = [\n  /^(-webkit-linear-gradient)\\(([a-z\\s]+)([\\w\\d\\.\\s,%\\(\\)]+)\\)$/,\n  /^(-o-linear-gradient)\\(([a-z\\s]+)([\\w\\d\\.\\s,%\\(\\)]+)\\)$/,\n  /^(-webkit-gradient)\\((linear|radial),\\s((?:\\d{1,3}%?)\\s(?:\\d{1,3}%?),\\s(?:\\d{1,3}%?)\\s(?:\\d{1,3}%?))([\\w\\d\\.\\s,%\\(\\)\\-]+)\\)$/,\n  /^(-moz-linear-gradient)\\(((?:\\d{1,3}%?)\\s(?:\\d{1,3}%?))([\\w\\d\\.\\s,%\\(\\)]+)\\)$/,\n  /^(-webkit-radial-gradient)\\(((?:\\d{1,3}%?)\\s(?:\\d{1,3}%?)),\\s(\\w+)\\s([a-z\\-]+)([\\w\\d\\.\\s,%\\(\\)]+)\\)$/,\n  /^(-moz-radial-gradient)\\(((?:\\d{1,3}%?)\\s(?:\\d{1,3}%?)),\\s(\\w+)\\s?([a-z\\-]*)([\\w\\d\\.\\s,%\\(\\)]+)\\)$/,\n  /^(-o-radial-gradient)\\(((?:\\d{1,3}%?)\\s(?:\\d{1,3}%?)),\\s(\\w+)\\s([a-z\\-]+)([\\w\\d\\.\\s,%\\(\\)]+)\\)$/\n  ];\n\n  /*\n * TODO: Add IE10 vendor prefix (-ms) support\n * TODO: Add W3C gradient (linear-gradient) support\n * TODO: Add old Webkit -webkit-gradient(radial, ...) support\n * TODO: Maybe some RegExp optimizations are possible ;o)\n */\n  Generate.parseGradient = function(css, bounds) {\n    var gradient, i, len = reGradients.length, m1, stop, m2, m2Len, step, m3, tl,tr,br,bl;\n\n    for(i = 0; i < len; i+=1){\n      m1 = css.match(reGradients[i]);\n      if(m1) {\n        break;\n      }\n    }\n\n    if(m1) {\n      switch(m1[1]) {\n        case '-webkit-linear-gradient':\n        case '-o-linear-gradient':\n\n          gradient = {\n            type: 'linear',\n            x0: null,\n            y0: null,\n            x1: null,\n            y1: null,\n            colorStops: []\n          };\n\n          // get coordinates\n          m2 = m1[2].match(/\\w+/g);\n          if(m2){\n            m2Len = m2.length;\n            for(i = 0; i < m2Len; i+=1){\n              switch(m2[i]) {\n                case 'top':\n                  gradient.y0 = 0;\n                  gradient.y1 = bounds.height;\n                  break;\n\n                case 'right':\n                  gradient.x0 = bounds.width;\n                  gradient.x1 = 0;\n                  break;\n\n                case 'bottom':\n                  gradient.y0 = bounds.height;\n                  gradient.y1 = 0;\n                  break;\n\n                case 'left':\n                  gradient.x0 = 0;\n                  gradient.x1 = bounds.width;\n                  break;\n              }\n            }\n          }\n          if(gradient.x0 === null && gradient.x1 === null){ // center\n            gradient.x0 = gradient.x1 = bounds.width / 2;\n          }\n          if(gradient.y0 === null && gradient.y1 === null){ // center\n            gradient.y0 = gradient.y1 = bounds.height / 2;\n          }\n\n          // get colors and stops\n          m2 = m1[3].match(/((?:rgb|rgba)\\(\\d{1,3},\\s\\d{1,3},\\s\\d{1,3}(?:,\\s[0-9\\.]+)?\\)(?:\\s\\d{1,3}(?:%|px))?)+/g);\n          if(m2){\n            m2Len = m2.length;\n            step = 1 / Math.max(m2Len - 1, 1);\n            for(i = 0; i < m2Len; i+=1){\n              m3 = m2[i].match(/((?:rgb|rgba)\\(\\d{1,3},\\s\\d{1,3},\\s\\d{1,3}(?:,\\s[0-9\\.]+)?\\))\\s*(\\d{1,3})?(%|px)?/);\n              if(m3[2]){\n                stop = parseFloat(m3[2]);\n                if(m3[3] === '%'){\n                  stop /= 100;\n                } else { // px - stupid opera\n                  stop /= bounds.width;\n                }\n              } else {\n                stop = i * step;\n              }\n              gradient.colorStops.push({\n                color: m3[1],\n                stop: stop\n              });\n            }\n          }\n          break;\n\n        case '-webkit-gradient':\n\n          gradient = {\n            type: m1[2] === 'radial' ? 'circle' : m1[2], // TODO: Add radial gradient support for older mozilla definitions\n            x0: 0,\n            y0: 0,\n            x1: 0,\n            y1: 0,\n            colorStops: []\n          };\n\n          // get coordinates\n          m2 = m1[3].match(/(\\d{1,3})%?\\s(\\d{1,3})%?,\\s(\\d{1,3})%?\\s(\\d{1,3})%?/);\n          if(m2){\n            gradient.x0 = (m2[1] * bounds.width) / 100;\n            gradient.y0 = (m2[2] * bounds.height) / 100;\n            gradient.x1 = (m2[3] * bounds.width) / 100;\n            gradient.y1 = (m2[4] * bounds.height) / 100;\n          }\n\n          // get colors and stops\n          m2 = m1[4].match(/((?:from|to|color-stop)\\((?:[0-9\\.]+,\\s)?(?:rgb|rgba)\\(\\d{1,3},\\s\\d{1,3},\\s\\d{1,3}(?:,\\s[0-9\\.]+)?\\)\\))+/g);\n          if(m2){\n            m2Len = m2.length;\n            for(i = 0; i < m2Len; i+=1){\n              m3 = m2[i].match(/(from|to|color-stop)\\(([0-9\\.]+)?(?:,\\s)?((?:rgb|rgba)\\(\\d{1,3},\\s\\d{1,3},\\s\\d{1,3}(?:,\\s[0-9\\.]+)?\\))\\)/);\n              stop = parseFloat(m3[2]);\n              if(m3[1] === 'from') {\n                stop = 0.0;\n              }\n              if(m3[1] === 'to') {\n                stop = 1.0;\n              }\n              gradient.colorStops.push({\n                color: m3[3],\n                stop: stop\n              });\n            }\n          }\n          break;\n\n        case '-moz-linear-gradient':\n\n          gradient = {\n            type: 'linear',\n            x0: 0,\n            y0: 0,\n            x1: 0,\n            y1: 0,\n            colorStops: []\n          };\n\n          // get coordinates\n          m2 = m1[2].match(/(\\d{1,3})%?\\s(\\d{1,3})%?/);\n\n          // m2[1] == 0%   -> left\n          // m2[1] == 50%  -> center\n          // m2[1] == 100% -> right\n\n          // m2[2] == 0%   -> top\n          // m2[2] == 50%  -> center\n          // m2[2] == 100% -> bottom\n\n          if(m2){\n            gradient.x0 = (m2[1] * bounds.width) / 100;\n            gradient.y0 = (m2[2] * bounds.height) / 100;\n            gradient.x1 = bounds.width - gradient.x0;\n            gradient.y1 = bounds.height - gradient.y0;\n          }\n\n          // get colors and stops\n          m2 = m1[3].match(/((?:rgb|rgba)\\(\\d{1,3},\\s\\d{1,3},\\s\\d{1,3}(?:,\\s[0-9\\.]+)?\\)(?:\\s\\d{1,3}%)?)+/g);\n          if(m2){\n            m2Len = m2.length;\n            step = 1 / Math.max(m2Len - 1, 1);\n            for(i = 0; i < m2Len; i+=1){\n              m3 = m2[i].match(/((?:rgb|rgba)\\(\\d{1,3},\\s\\d{1,3},\\s\\d{1,3}(?:,\\s[0-9\\.]+)?\\))\\s*(\\d{1,3})?(%)?/);\n              if(m3[2]){\n                stop = parseFloat(m3[2]);\n                if(m3[3]){ // percentage\n                  stop /= 100;\n                }\n              } else {\n                stop = i * step;\n              }\n              gradient.colorStops.push({\n                color: m3[1],\n                stop: stop\n              });\n            }\n          }\n          break;\n\n        case '-webkit-radial-gradient':\n        case '-moz-radial-gradient':\n        case '-o-radial-gradient':\n\n          gradient = {\n            type: 'circle',\n            x0: 0,\n            y0: 0,\n            x1: bounds.width,\n            y1: bounds.height,\n            cx: 0,\n            cy: 0,\n            rx: 0,\n            ry: 0,\n            colorStops: []\n          };\n\n          // center\n          m2 = m1[2].match(/(\\d{1,3})%?\\s(\\d{1,3})%?/);\n          if(m2){\n            gradient.cx = (m2[1] * bounds.width) / 100;\n            gradient.cy = (m2[2] * bounds.height) / 100;\n          }\n\n          // size\n          m2 = m1[3].match(/\\w+/);\n          m3 = m1[4].match(/[a-z\\-]*/);\n          if(m2 && m3){\n            switch(m3[0]){\n              case 'farthest-corner':\n              case 'cover': // is equivalent to farthest-corner\n              case '': // mozilla removes \"cover\" from definition :(\n                tl = Math.sqrt(Math.pow(gradient.cx, 2) + Math.pow(gradient.cy, 2));\n                tr = Math.sqrt(Math.pow(gradient.cx, 2) + Math.pow(gradient.y1 - gradient.cy, 2));\n                br = Math.sqrt(Math.pow(gradient.x1 - gradient.cx, 2) + Math.pow(gradient.y1 - gradient.cy, 2));\n                bl = Math.sqrt(Math.pow(gradient.x1 - gradient.cx, 2) + Math.pow(gradient.cy, 2));\n                gradient.rx = gradient.ry = Math.max(tl, tr, br, bl);\n                break;\n              case 'closest-corner':\n                tl = Math.sqrt(Math.pow(gradient.cx, 2) + Math.pow(gradient.cy, 2));\n                tr = Math.sqrt(Math.pow(gradient.cx, 2) + Math.pow(gradient.y1 - gradient.cy, 2));\n                br = Math.sqrt(Math.pow(gradient.x1 - gradient.cx, 2) + Math.pow(gradient.y1 - gradient.cy, 2));\n                bl = Math.sqrt(Math.pow(gradient.x1 - gradient.cx, 2) + Math.pow(gradient.cy, 2));\n                gradient.rx = gradient.ry = Math.min(tl, tr, br, bl);\n                break;\n              case 'farthest-side':\n                if(m2[0] === 'circle'){\n                  gradient.rx = gradient.ry = Math.max(\n                    gradient.cx,\n                    gradient.cy,\n                    gradient.x1 - gradient.cx,\n                    gradient.y1 - gradient.cy\n                    );\n                } else { // ellipse\n\n                  gradient.type = m2[0];\n\n                  gradient.rx = Math.max(\n                    gradient.cx,\n                    gradient.x1 - gradient.cx\n                    );\n                  gradient.ry = Math.max(\n                    gradient.cy,\n                    gradient.y1 - gradient.cy\n                    );\n                }\n                break;\n              case 'closest-side':\n              case 'contain': // is equivalent to closest-side\n                if(m2[0] === 'circle'){\n                  gradient.rx = gradient.ry = Math.min(\n                    gradient.cx,\n                    gradient.cy,\n                    gradient.x1 - gradient.cx,\n                    gradient.y1 - gradient.cy\n                    );\n                } else { // ellipse\n\n                  gradient.type = m2[0];\n\n                  gradient.rx = Math.min(\n                    gradient.cx,\n                    gradient.x1 - gradient.cx\n                    );\n                  gradient.ry = Math.min(\n                    gradient.cy,\n                    gradient.y1 - gradient.cy\n                    );\n                }\n                break;\n\n            // TODO: add support for \"30px 40px\" sizes (webkit only)\n            }\n          }\n\n          // color stops\n          m2 = m1[5].match(/((?:rgb|rgba)\\(\\d{1,3},\\s\\d{1,3},\\s\\d{1,3}(?:,\\s[0-9\\.]+)?\\)(?:\\s\\d{1,3}(?:%|px))?)+/g);\n          if(m2){\n            m2Len = m2.length;\n            step = 1 / Math.max(m2Len - 1, 1);\n            for(i = 0; i < m2Len; i+=1){\n              m3 = m2[i].match(/((?:rgb|rgba)\\(\\d{1,3},\\s\\d{1,3},\\s\\d{1,3}(?:,\\s[0-9\\.]+)?\\))\\s*(\\d{1,3})?(%|px)?/);\n              if(m3[2]){\n                stop = parseFloat(m3[2]);\n                if(m3[3] === '%'){\n                  stop /= 100;\n                } else { // px - stupid opera\n                  stop /= bounds.width;\n                }\n              } else {\n                stop = i * step;\n              }\n              gradient.colorStops.push({\n                color: m3[1],\n                stop: stop\n              });\n            }\n          }\n          break;\n      }\n    }\n\n    return gradient;\n  };\n\n  function addScrollStops(grad) {\n    return function(colorStop) {\n      try {\n        grad.addColorStop(colorStop.stop, colorStop.color);\n      }\n      catch(e) {\n        Util.log(['failed to add color stop: ', e, '; tried to add: ', colorStop]);\n      }\n    };\n  }\n\n  Generate.Gradient = function(src, bounds) {\n    if(bounds.width === 0 || bounds.height === 0) {\n      return;\n    }\n\n    var canvas = document.createElement('canvas'),\n    ctx = canvas.getContext('2d'),\n    gradient, grad;\n\n    canvas.width = bounds.width;\n    canvas.height = bounds.height;\n\n    // TODO: add support for multi defined background gradients\n    gradient = _html2canvas.Generate.parseGradient(src, bounds);\n\n    if(gradient) {\n      switch(gradient.type) {\n        case 'linear':\n          grad = ctx.createLinearGradient(gradient.x0, gradient.y0, gradient.x1, gradient.y1);\n          gradient.colorStops.forEach(addScrollStops(grad));\n          ctx.fillStyle = grad;\n          ctx.fillRect(0, 0, bounds.width, bounds.height);\n          break;\n\n        case 'circle':\n          grad = ctx.createRadialGradient(gradient.cx, gradient.cy, 0, gradient.cx, gradient.cy, gradient.rx);\n          gradient.colorStops.forEach(addScrollStops(grad));\n          ctx.fillStyle = grad;\n          ctx.fillRect(0, 0, bounds.width, bounds.height);\n          break;\n\n        case 'ellipse':\n          var canvasRadial = document.createElement('canvas'),\n            ctxRadial = canvasRadial.getContext('2d'),\n            ri = Math.max(gradient.rx, gradient.ry),\n            di = ri * 2;\n\n          canvasRadial.width = canvasRadial.height = di;\n\n          grad = ctxRadial.createRadialGradient(gradient.rx, gradient.ry, 0, gradient.rx, gradient.ry, ri);\n          gradient.colorStops.forEach(addScrollStops(grad));\n\n          ctxRadial.fillStyle = grad;\n          ctxRadial.fillRect(0, 0, di, di);\n\n          ctx.fillStyle = gradient.colorStops[gradient.colorStops.length - 1].color;\n          ctx.fillRect(0, 0, canvas.width, canvas.height);\n          ctx.drawImage(canvasRadial, gradient.cx - gradient.rx, gradient.cy - gradient.ry, 2 * gradient.rx, 2 * gradient.ry);\n          break;\n      }\n    }\n\n    return canvas;\n  };\n\n  Generate.ListAlpha = function(number) {\n    var tmp = \"\",\n    modulus;\n\n    do {\n      modulus = number % 26;\n      tmp = String.fromCharCode((modulus) + 64) + tmp;\n      number = number / 26;\n    }while((number*26) > 26);\n\n    return tmp;\n  };\n\n  Generate.ListRoman = function(number) {\n    var romanArray = [\"M\", \"CM\", \"D\", \"CD\", \"C\", \"XC\", \"L\", \"XL\", \"X\", \"IX\", \"V\", \"IV\", \"I\"],\n    decimal = [1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1],\n    roman = \"\",\n    v,\n    len = romanArray.length;\n\n    if (number <= 0 || number >= 4000) {\n      return number;\n    }\n\n    for (v=0; v < len; v+=1) {\n      while (number >= decimal[v]) {\n        number -= decimal[v];\n        roman += romanArray[v];\n      }\n    }\n\n    return roman;\n  };\n})();\nfunction h2cRenderContext(width, height) {\n  var storage = [];\n  return {\n    storage: storage,\n    width: width,\n    height: height,\n    clip: function() {\n      storage.push({\n        type: \"function\",\n        name: \"clip\",\n        'arguments': arguments\n      });\n    },\n    translate: function() {\n      storage.push({\n        type: \"function\",\n        name: \"translate\",\n        'arguments': arguments\n      });\n    },\n    fill: function() {\n      storage.push({\n        type: \"function\",\n        name: \"fill\",\n        'arguments': arguments\n      });\n    },\n    save: function() {\n      storage.push({\n        type: \"function\",\n        name: \"save\",\n        'arguments': arguments\n      });\n    },\n    restore: function() {\n      storage.push({\n        type: \"function\",\n        name: \"restore\",\n        'arguments': arguments\n      });\n    },\n    fillRect: function () {\n      storage.push({\n        type: \"function\",\n        name: \"fillRect\",\n        'arguments': arguments\n      });\n    },\n    createPattern: function() {\n      storage.push({\n        type: \"function\",\n        name: \"createPattern\",\n        'arguments': arguments\n      });\n    },\n    drawShape: function() {\n\n      var shape = [];\n\n      storage.push({\n        type: \"function\",\n        name: \"drawShape\",\n        'arguments': shape\n      });\n\n      return {\n        moveTo: function() {\n          shape.push({\n            name: \"moveTo\",\n            'arguments': arguments\n          });\n        },\n        lineTo: function() {\n          shape.push({\n            name: \"lineTo\",\n            'arguments': arguments\n          });\n        },\n        arcTo: function() {\n          shape.push({\n            name: \"arcTo\",\n            'arguments': arguments\n          });\n        },\n        bezierCurveTo: function() {\n          shape.push({\n            name: \"bezierCurveTo\",\n            'arguments': arguments\n          });\n        },\n        quadraticCurveTo: function() {\n          shape.push({\n            name: \"quadraticCurveTo\",\n            'arguments': arguments\n          });\n        }\n      };\n\n    },\n    drawImage: function () {\n      storage.push({\n        type: \"function\",\n        name: \"drawImage\",\n        'arguments': arguments\n      });\n    },\n    fillText: function () {\n      storage.push({\n        type: \"function\",\n        name: \"fillText\",\n        'arguments': arguments\n      });\n    },\n    setVariable: function (variable, value) {\n      storage.push({\n        type: \"variable\",\n        name: variable,\n        'arguments': value\n      });\n      return value;\n    }\n  };\n}\n_html2canvas.Parse = function (images, options) {\n  window.scroll(0,0);\n\n  var element = (( options.elements === undefined ) ? document.body : options.elements[0]), // select body by default\n  numDraws = 0,\n  doc = element.ownerDocument,\n  Util = _html2canvas.Util,\n  support = Util.Support(options, doc),\n  ignoreElementsRegExp = new RegExp(\"(\" + options.ignoreElements + \")\"),\n  body = doc.body,\n  getCSS = Util.getCSS,\n  pseudoHide = \"___html2canvas___pseudoelement\",\n  hidePseudoElements = doc.createElement('style');\n\n  hidePseudoElements.innerHTML = '.' + pseudoHide + '-before:before { content: \"\" !important; display: none !important; }' +\n  '.' + pseudoHide + '-after:after { content: \"\" !important; display: none !important; }';\n\n  body.appendChild(hidePseudoElements);\n\n  images = images || {};\n\n  function documentWidth () {\n    return Math.max(\n      Math.max(doc.body.scrollWidth, doc.documentElement.scrollWidth),\n      Math.max(doc.body.offsetWidth, doc.documentElement.offsetWidth),\n      Math.max(doc.body.clientWidth, doc.documentElement.clientWidth)\n      );\n  }\n\n  function documentHeight () {\n    return Math.max(\n      Math.max(doc.body.scrollHeight, doc.documentElement.scrollHeight),\n      Math.max(doc.body.offsetHeight, doc.documentElement.offsetHeight),\n      Math.max(doc.body.clientHeight, doc.documentElement.clientHeight)\n      );\n  }\n\n  function getCSSInt(element, attribute) {\n    var val = parseInt(getCSS(element, attribute), 10);\n    return (isNaN(val)) ? 0 : val; // borders in old IE are throwing 'medium' for demo.html\n  }\n\n  function renderRect (ctx, x, y, w, h, bgcolor) {\n    if (bgcolor !== \"transparent\"){\n      ctx.setVariable(\"fillStyle\", bgcolor);\n      ctx.fillRect(x, y, w, h);\n      numDraws+=1;\n    }\n  }\n\n  function capitalize(m, p1, p2) {\n    if (m.length > 0) {\n      return p1 + p2.toUpperCase();\n    }\n  }\n\n  function textTransform (text, transform) {\n    switch(transform){\n      case \"lowercase\":\n        return text.toLowerCase();\n      case \"capitalize\":\n        return text.replace( /(^|\\s|:|-|\\(|\\))([a-z])/g, capitalize);\n      case \"uppercase\":\n        return text.toUpperCase();\n      default:\n        return text;\n    }\n  }\n\n  function noLetterSpacing(letter_spacing) {\n    return (/^(normal|none|0px)$/.test(letter_spacing));\n  }\n\n  function drawText(currentText, x, y, ctx){\n    if (currentText !== null && Util.trimText(currentText).length > 0) {\n      ctx.fillText(currentText, x, y);\n      numDraws+=1;\n    }\n  }\n\n  function setTextVariables(ctx, el, text_decoration, color) {\n    var align = false,\n    bold = getCSS(el, \"fontWeight\"),\n    family = getCSS(el, \"fontFamily\"),\n    size = getCSS(el, \"fontSize\"),\n    shadows = Util.parseTextShadows(getCSS(el, \"textShadow\"));\n\n    switch(parseInt(bold, 10)){\n      case 401:\n        bold = \"bold\";\n        break;\n      case 400:\n        bold = \"normal\";\n        break;\n    }\n\n    ctx.setVariable(\"fillStyle\", color);\n    ctx.setVariable(\"font\", [getCSS(el, \"fontStyle\"), getCSS(el, \"fontVariant\"), bold, size, family].join(\" \"));\n    ctx.setVariable(\"textAlign\", (align) ? \"right\" : \"left\");\n\n    if (shadows.length) {\n      // TODO: support multiple text shadows\n      // apply the first text shadow\n      ctx.setVariable(\"shadowColor\", shadows[0].color);\n      ctx.setVariable(\"shadowOffsetX\", shadows[0].offsetX);\n      ctx.setVariable(\"shadowOffsetY\", shadows[0].offsetY);\n      ctx.setVariable(\"shadowBlur\", shadows[0].blur);\n    }\n\n    if (text_decoration !== \"none\"){\n      return Util.Font(family, size, doc);\n    }\n  }\n\n  function renderTextDecoration(ctx, text_decoration, bounds, metrics, color) {\n    switch(text_decoration) {\n      case \"underline\":\n        // Draws a line at the baseline of the font\n        // TODO As some browsers display the line as more than 1px if the font-size is big, need to take that into account both in position and size\n        renderRect(ctx, bounds.left, Math.round(bounds.top + metrics.baseline + metrics.lineWidth), bounds.width, 1, color);\n        break;\n      case \"overline\":\n        renderRect(ctx, bounds.left, Math.round(bounds.top), bounds.width, 1, color);\n        break;\n      case \"line-through\":\n        // TODO try and find exact position for line-through\n        renderRect(ctx, bounds.left, Math.ceil(bounds.top + metrics.middle + metrics.lineWidth), bounds.width, 1, color);\n        break;\n    }\n  }\n\n  function getTextBounds(state, text, textDecoration, isLast, transform) {\n    var bounds;\n    if (support.rangeBounds && !transform) {\n      if (textDecoration !== \"none\" || Util.trimText(text).length !== 0) {\n        bounds = textRangeBounds(text, state.node, state.textOffset);\n      }\n      state.textOffset += text.length;\n    } else if (state.node && typeof state.node.nodeValue === \"string\" ){\n      var newTextNode = (isLast) ? state.node.splitText(text.length) : null;\n      bounds = textWrapperBounds(state.node, transform);\n      state.node = newTextNode;\n    }\n    return bounds;\n  }\n\n  function textRangeBounds(text, textNode, textOffset) {\n    var range = doc.createRange();\n    range.setStart(textNode, textOffset);\n    range.setEnd(textNode, textOffset + text.length);\n    return range.getBoundingClientRect();\n  }\n\n  function textWrapperBounds(oldTextNode, transform) {\n    var parent = oldTextNode.parentNode,\n    wrapElement = doc.createElement('wrapper'),\n    backupText = oldTextNode.cloneNode(true);\n\n    wrapElement.appendChild(oldTextNode.cloneNode(true));\n    parent.replaceChild(wrapElement, oldTextNode);\n\n    var bounds = transform ? Util.OffsetBounds(wrapElement) : Util.Bounds(wrapElement);\n    parent.replaceChild(backupText, wrapElement);\n    return bounds;\n  }\n\n  function renderText(el, textNode, stack) {\n    var ctx = stack.ctx,\n    color = getCSS(el, \"color\"),\n    textDecoration = getCSS(el, \"textDecoration\"),\n    textAlign = getCSS(el, \"textAlign\"),\n    metrics,\n    textList,\n    state = {\n      node: textNode,\n      textOffset: 0\n    };\n\n    if (Util.trimText(textNode.nodeValue).length > 0) {\n      textNode.nodeValue = textTransform(textNode.nodeValue, getCSS(el, \"textTransform\"));\n      textAlign = textAlign.replace([\"-webkit-auto\"],[\"auto\"]);\n\n      textList = (!options.letterRendering && /^(left|right|justify|auto)$/.test(textAlign) && noLetterSpacing(getCSS(el, \"letterSpacing\"))) ?\n      textNode.nodeValue.split(/(\\b| )/)\n      : textNode.nodeValue.split(\"\");\n\n      metrics = setTextVariables(ctx, el, textDecoration, color);\n\n      if (options.chinese) {\n        textList.forEach(function(word, index) {\n          if (/.*[\\u4E00-\\u9FA5].*$/.test(word)) {\n            word = word.split(\"\");\n            word.unshift(index, 1);\n            textList.splice.apply(textList, word);\n          }\n        });\n      }\n\n      textList.forEach(function(text, index) {\n        var bounds = getTextBounds(state, text, textDecoration, (index < textList.length - 1), stack.transform.matrix);\n        if (bounds) {\n          drawText(text, bounds.left, bounds.bottom, ctx);\n          renderTextDecoration(ctx, textDecoration, bounds, metrics, color);\n        }\n      });\n    }\n  }\n\n  function listPosition (element, val) {\n    var boundElement = doc.createElement( \"boundelement\" ),\n    originalType,\n    bounds;\n\n    boundElement.style.display = \"inline\";\n\n    originalType = element.style.listStyleType;\n    element.style.listStyleType = \"none\";\n\n    boundElement.appendChild(doc.createTextNode(val));\n\n    element.insertBefore(boundElement, element.firstChild);\n\n    bounds = Util.Bounds(boundElement);\n    element.removeChild(boundElement);\n    element.style.listStyleType = originalType;\n    return bounds;\n  }\n\n  function elementIndex(el) {\n    var i = -1,\n    count = 1,\n    childs = el.parentNode.childNodes;\n\n    if (el.parentNode) {\n      while(childs[++i] !== el) {\n        if (childs[i].nodeType === 1) {\n          count++;\n        }\n      }\n      return count;\n    } else {\n      return -1;\n    }\n  }\n\n  function listItemText(element, type) {\n    var currentIndex = elementIndex(element), text;\n    switch(type){\n      case \"decimal\":\n        text = currentIndex;\n        break;\n      case \"decimal-leading-zero\":\n        text = (currentIndex.toString().length === 1) ? currentIndex = \"0\" + currentIndex.toString() : currentIndex.toString();\n        break;\n      case \"upper-roman\":\n        text = _html2canvas.Generate.ListRoman( currentIndex );\n        break;\n      case \"lower-roman\":\n        text = _html2canvas.Generate.ListRoman( currentIndex ).toLowerCase();\n        break;\n      case \"lower-alpha\":\n        text = _html2canvas.Generate.ListAlpha( currentIndex ).toLowerCase();\n        break;\n      case \"upper-alpha\":\n        text = _html2canvas.Generate.ListAlpha( currentIndex );\n        break;\n    }\n\n    return text + \". \";\n  }\n\n  function renderListItem(element, stack, elBounds) {\n    var x,\n    text,\n    ctx = stack.ctx,\n    type = getCSS(element, \"listStyleType\"),\n    listBounds;\n\n    if (/^(decimal|decimal-leading-zero|upper-alpha|upper-latin|upper-roman|lower-alpha|lower-greek|lower-latin|lower-roman)$/i.test(type)) {\n      text = listItemText(element, type);\n      listBounds = listPosition(element, text);\n      setTextVariables(ctx, element, \"none\", getCSS(element, \"color\"));\n\n      if (getCSS(element, \"listStylePosition\") === \"inside\") {\n        ctx.setVariable(\"textAlign\", \"left\");\n        x = elBounds.left;\n      } else {\n        return;\n      }\n\n      drawText(text, x, listBounds.bottom, ctx);\n    }\n  }\n\n  function loadImage (src){\n    var img = images[src];\n    return (img && img.succeeded === true) ? img.img : false;\n  }\n\n  function clipBounds(src, dst){\n    var x = Math.max(src.left, dst.left),\n    y = Math.max(src.top, dst.top),\n    x2 = Math.min((src.left + src.width), (dst.left + dst.width)),\n    y2 = Math.min((src.top + src.height), (dst.top + dst.height));\n\n    return {\n      left:x,\n      top:y,\n      width:x2-x,\n      height:y2-y\n    };\n  }\n\n  function setZ(element, stack, parentStack){\n    var newContext,\n    isPositioned = stack.cssPosition !== 'static',\n    zIndex = isPositioned ? getCSS(element, 'zIndex') : 'auto',\n    opacity = getCSS(element, 'opacity'),\n    isFloated = getCSS(element, 'cssFloat') !== 'none';\n\n    // https://developer.mozilla.org/en-US/docs/Web/Guide/CSS/Understanding_z_index/The_stacking_context\n    // When a new stacking context should be created:\n    // the root element (HTML),\n    // positioned (absolutely or relatively) with a z-index value other than \"auto\",\n    // elements with an opacity value less than 1. (See the specification for opacity),\n    // on mobile WebKit and Chrome 22+, position: fixed always creates a new stacking context, even when z-index is \"auto\" (See this post)\n\n    stack.zIndex = newContext = h2czContext(zIndex);\n    newContext.isPositioned = isPositioned;\n    newContext.isFloated = isFloated;\n    newContext.opacity = opacity;\n    newContext.ownStacking = (zIndex !== 'auto' || opacity < 1);\n\n    if (parentStack) {\n      parentStack.zIndex.children.push(stack);\n    }\n  }\n\n  function renderImage(ctx, element, image, bounds, borders) {\n\n    var paddingLeft = getCSSInt(element, 'paddingLeft'),\n    paddingTop = getCSSInt(element, 'paddingTop'),\n    paddingRight = getCSSInt(element, 'paddingRight'),\n    paddingBottom = getCSSInt(element, 'paddingBottom');\n\n    drawImage(\n      ctx,\n      image,\n      0, //sx\n      0, //sy\n      image.width, //sw\n      image.height, //sh\n      bounds.left + paddingLeft + borders[3].width, //dx\n      bounds.top + paddingTop + borders[0].width, // dy\n      bounds.width - (borders[1].width + borders[3].width + paddingLeft + paddingRight), //dw\n      bounds.height - (borders[0].width + borders[2].width + paddingTop + paddingBottom) //dh\n      );\n  }\n\n  function getBorderData(element) {\n    return [\"Top\", \"Right\", \"Bottom\", \"Left\"].map(function(side) {\n      return {\n        width: getCSSInt(element, 'border' + side + 'Width'),\n        color: getCSS(element, 'border' + side + 'Color')\n      };\n    });\n  }\n\n  function getBorderRadiusData(element) {\n    return [\"TopLeft\", \"TopRight\", \"BottomRight\", \"BottomLeft\"].map(function(side) {\n      return getCSS(element, 'border' + side + 'Radius');\n    });\n  }\n\n  var getCurvePoints = (function(kappa) {\n\n    return function(x, y, r1, r2) {\n      var ox = (r1) * kappa, // control point offset horizontal\n      oy = (r2) * kappa, // control point offset vertical\n      xm = x + r1, // x-middle\n      ym = y + r2; // y-middle\n      return {\n        topLeft: bezierCurve({\n          x:x,\n          y:ym\n        }, {\n          x:x,\n          y:ym - oy\n        }, {\n          x:xm - ox,\n          y:y\n        }, {\n          x:xm,\n          y:y\n        }),\n        topRight: bezierCurve({\n          x:x,\n          y:y\n        }, {\n          x:x + ox,\n          y:y\n        }, {\n          x:xm,\n          y:ym - oy\n        }, {\n          x:xm,\n          y:ym\n        }),\n        bottomRight: bezierCurve({\n          x:xm,\n          y:y\n        }, {\n          x:xm,\n          y:y + oy\n        }, {\n          x:x + ox,\n          y:ym\n        }, {\n          x:x,\n          y:ym\n        }),\n        bottomLeft: bezierCurve({\n          x:xm,\n          y:ym\n        }, {\n          x:xm - ox,\n          y:ym\n        }, {\n          x:x,\n          y:y + oy\n        }, {\n          x:x,\n          y:y\n        })\n      };\n    };\n  })(4 * ((Math.sqrt(2) - 1) / 3));\n\n  function bezierCurve(start, startControl, endControl, end) {\n\n    var lerp = function (a, b, t) {\n      return {\n        x:a.x + (b.x - a.x) * t,\n        y:a.y + (b.y - a.y) * t\n      };\n    };\n\n    return {\n      start: start,\n      startControl: startControl,\n      endControl: endControl,\n      end: end,\n      subdivide: function(t) {\n        var ab = lerp(start, startControl, t),\n        bc = lerp(startControl, endControl, t),\n        cd = lerp(endControl, end, t),\n        abbc = lerp(ab, bc, t),\n        bccd = lerp(bc, cd, t),\n        dest = lerp(abbc, bccd, t);\n        return [bezierCurve(start, ab, abbc, dest), bezierCurve(dest, bccd, cd, end)];\n      },\n      curveTo: function(borderArgs) {\n        borderArgs.push([\"bezierCurve\", startControl.x, startControl.y, endControl.x, endControl.y, end.x, end.y]);\n      },\n      curveToReversed: function(borderArgs) {\n        borderArgs.push([\"bezierCurve\", endControl.x, endControl.y, startControl.x, startControl.y, start.x, start.y]);\n      }\n    };\n  }\n\n  function parseCorner(borderArgs, radius1, radius2, corner1, corner2, x, y) {\n    if (radius1[0] > 0 || radius1[1] > 0) {\n      borderArgs.push([\"line\", corner1[0].start.x, corner1[0].start.y]);\n      corner1[0].curveTo(borderArgs);\n      corner1[1].curveTo(borderArgs);\n    } else {\n      borderArgs.push([\"line\", x, y]);\n    }\n\n    if (radius2[0] > 0 || radius2[1] > 0) {\n      borderArgs.push([\"line\", corner2[0].start.x, corner2[0].start.y]);\n    }\n  }\n\n  function drawSide(borderData, radius1, radius2, outer1, inner1, outer2, inner2) {\n    var borderArgs = [];\n\n    if (radius1[0] > 0 || radius1[1] > 0) {\n      borderArgs.push([\"line\", outer1[1].start.x, outer1[1].start.y]);\n      outer1[1].curveTo(borderArgs);\n    } else {\n      borderArgs.push([ \"line\", borderData.c1[0], borderData.c1[1]]);\n    }\n\n    if (radius2[0] > 0 || radius2[1] > 0) {\n      borderArgs.push([\"line\", outer2[0].start.x, outer2[0].start.y]);\n      outer2[0].curveTo(borderArgs);\n      borderArgs.push([\"line\", inner2[0].end.x, inner2[0].end.y]);\n      inner2[0].curveToReversed(borderArgs);\n    } else {\n      borderArgs.push([ \"line\", borderData.c2[0], borderData.c2[1]]);\n      borderArgs.push([ \"line\", borderData.c3[0], borderData.c3[1]]);\n    }\n\n    if (radius1[0] > 0 || radius1[1] > 0) {\n      borderArgs.push([\"line\", inner1[1].end.x, inner1[1].end.y]);\n      inner1[1].curveToReversed(borderArgs);\n    } else {\n      borderArgs.push([ \"line\", borderData.c4[0], borderData.c4[1]]);\n    }\n\n    return borderArgs;\n  }\n\n  function calculateCurvePoints(bounds, borderRadius, borders) {\n\n    var x = bounds.left,\n    y = bounds.top,\n    width = bounds.width,\n    height = bounds.height,\n\n    tlh = borderRadius[0][0],\n    tlv = borderRadius[0][1],\n    trh = borderRadius[1][0],\n    trv = borderRadius[1][1],\n    brh = borderRadius[2][0],\n    brv = borderRadius[2][1],\n    blh = borderRadius[3][0],\n    blv = borderRadius[3][1],\n\n    topWidth = width - trh,\n    rightHeight = height - brv,\n    bottomWidth = width - brh,\n    leftHeight = height - blv;\n\n    return {\n      topLeftOuter: getCurvePoints(\n        x,\n        y,\n        tlh,\n        tlv\n        ).topLeft.subdivide(0.5),\n\n      topLeftInner: getCurvePoints(\n        x + borders[3].width,\n        y + borders[0].width,\n        Math.max(0, tlh - borders[3].width),\n        Math.max(0, tlv - borders[0].width)\n        ).topLeft.subdivide(0.5),\n\n      topRightOuter: getCurvePoints(\n        x + topWidth,\n        y,\n        trh,\n        trv\n        ).topRight.subdivide(0.5),\n\n      topRightInner: getCurvePoints(\n        x + Math.min(topWidth, width + borders[3].width),\n        y + borders[0].width,\n        (topWidth > width + borders[3].width) ? 0 :trh - borders[3].width,\n        trv - borders[0].width\n        ).topRight.subdivide(0.5),\n\n      bottomRightOuter: getCurvePoints(\n        x + bottomWidth,\n        y + rightHeight,\n        brh,\n        brv\n        ).bottomRight.subdivide(0.5),\n\n      bottomRightInner: getCurvePoints(\n        x + Math.min(bottomWidth, width + borders[3].width),\n        y + Math.min(rightHeight, height + borders[0].width),\n        Math.max(0, brh - borders[1].width),\n        Math.max(0, brv - borders[2].width)\n        ).bottomRight.subdivide(0.5),\n\n      bottomLeftOuter: getCurvePoints(\n        x,\n        y + leftHeight,\n        blh,\n        blv\n        ).bottomLeft.subdivide(0.5),\n\n      bottomLeftInner: getCurvePoints(\n        x + borders[3].width,\n        y + leftHeight,\n        Math.max(0, blh - borders[3].width),\n        Math.max(0, blv - borders[2].width)\n        ).bottomLeft.subdivide(0.5)\n    };\n  }\n\n  function getBorderClip(element, borderPoints, borders, radius, bounds) {\n    var backgroundClip = getCSS(element, 'backgroundClip'),\n    borderArgs = [];\n\n    switch(backgroundClip) {\n      case \"content-box\":\n      case \"padding-box\":\n        parseCorner(borderArgs, radius[0], radius[1], borderPoints.topLeftInner, borderPoints.topRightInner, bounds.left + borders[3].width, bounds.top + borders[0].width);\n        parseCorner(borderArgs, radius[1], radius[2], borderPoints.topRightInner, borderPoints.bottomRightInner, bounds.left + bounds.width - borders[1].width, bounds.top + borders[0].width);\n        parseCorner(borderArgs, radius[2], radius[3], borderPoints.bottomRightInner, borderPoints.bottomLeftInner, bounds.left + bounds.width - borders[1].width, bounds.top + bounds.height - borders[2].width);\n        parseCorner(borderArgs, radius[3], radius[0], borderPoints.bottomLeftInner, borderPoints.topLeftInner, bounds.left + borders[3].width, bounds.top + bounds.height - borders[2].width);\n        break;\n\n      default:\n        parseCorner(borderArgs, radius[0], radius[1], borderPoints.topLeftOuter, borderPoints.topRightOuter, bounds.left, bounds.top);\n        parseCorner(borderArgs, radius[1], radius[2], borderPoints.topRightOuter, borderPoints.bottomRightOuter, bounds.left + bounds.width, bounds.top);\n        parseCorner(borderArgs, radius[2], radius[3], borderPoints.bottomRightOuter, borderPoints.bottomLeftOuter, bounds.left + bounds.width, bounds.top + bounds.height);\n        parseCorner(borderArgs, radius[3], radius[0], borderPoints.bottomLeftOuter, borderPoints.topLeftOuter, bounds.left, bounds.top + bounds.height);\n        break;\n    }\n\n    return borderArgs;\n  }\n\n  function parseBorders(element, bounds, borders){\n    var x = bounds.left,\n    y = bounds.top,\n    width = bounds.width,\n    height = bounds.height,\n    borderSide,\n    bx,\n    by,\n    bw,\n    bh,\n    borderArgs,\n    // http://www.w3.org/TR/css3-background/#the-border-radius\n    borderRadius = getBorderRadiusData(element),\n    borderPoints = calculateCurvePoints(bounds, borderRadius, borders),\n    borderData = {\n      clip: getBorderClip(element, borderPoints, borders, borderRadius, bounds),\n      borders: []\n    };\n\n    for (borderSide = 0; borderSide < 4; borderSide++) {\n\n      if (borders[borderSide].width > 0) {\n        bx = x;\n        by = y;\n        bw = width;\n        bh = height - (borders[2].width);\n\n        switch(borderSide) {\n          case 0:\n            // top border\n            bh = borders[0].width;\n\n            borderArgs = drawSide({\n              c1: [bx, by],\n              c2: [bx + bw, by],\n              c3: [bx + bw - borders[1].width, by + bh],\n              c4: [bx + borders[3].width, by + bh]\n            }, borderRadius[0], borderRadius[1],\n            borderPoints.topLeftOuter, borderPoints.topLeftInner, borderPoints.topRightOuter, borderPoints.topRightInner);\n            break;\n          case 1:\n            // right border\n            bx = x + width - (borders[1].width);\n            bw = borders[1].width;\n\n            borderArgs = drawSide({\n              c1: [bx + bw, by],\n              c2: [bx + bw, by + bh + borders[2].width],\n              c3: [bx, by + bh],\n              c4: [bx, by + borders[0].width]\n            }, borderRadius[1], borderRadius[2],\n            borderPoints.topRightOuter, borderPoints.topRightInner, borderPoints.bottomRightOuter, borderPoints.bottomRightInner);\n            break;\n          case 2:\n            // bottom border\n            by = (by + height) - (borders[2].width);\n            bh = borders[2].width;\n\n            borderArgs = drawSide({\n              c1: [bx + bw, by + bh],\n              c2: [bx, by + bh],\n              c3: [bx + borders[3].width, by],\n              c4: [bx + bw - borders[3].width, by]\n            }, borderRadius[2], borderRadius[3],\n            borderPoints.bottomRightOuter, borderPoints.bottomRightInner, borderPoints.bottomLeftOuter, borderPoints.bottomLeftInner);\n            break;\n          case 3:\n            // left border\n            bw = borders[3].width;\n\n            borderArgs = drawSide({\n              c1: [bx, by + bh + borders[2].width],\n              c2: [bx, by],\n              c3: [bx + bw, by + borders[0].width],\n              c4: [bx + bw, by + bh]\n            }, borderRadius[3], borderRadius[0],\n            borderPoints.bottomLeftOuter, borderPoints.bottomLeftInner, borderPoints.topLeftOuter, borderPoints.topLeftInner);\n            break;\n        }\n\n        borderData.borders.push({\n          args: borderArgs,\n          color: borders[borderSide].color\n        });\n\n      }\n    }\n\n    return borderData;\n  }\n\n  function createShape(ctx, args) {\n    var shape = ctx.drawShape();\n    args.forEach(function(border, index) {\n      shape[(index === 0) ? \"moveTo\" : border[0] + \"To\" ].apply(null, border.slice(1));\n    });\n    return shape;\n  }\n\n  function renderBorders(ctx, borderArgs, color) {\n    if (color !== \"transparent\") {\n      ctx.setVariable( \"fillStyle\", color);\n      createShape(ctx, borderArgs);\n      ctx.fill();\n      numDraws+=1;\n    }\n  }\n\n  function renderFormValue (el, bounds, stack){\n\n    var valueWrap = doc.createElement('valuewrap'),\n    cssPropertyArray = ['lineHeight','textAlign','fontFamily','color','fontSize','paddingLeft','paddingTop','width','height','border','borderLeftWidth','borderTopWidth'],\n    textValue,\n    textNode;\n\n    cssPropertyArray.forEach(function(property) {\n      try {\n        valueWrap.style[property] = getCSS(el, property);\n      } catch(e) {\n        // Older IE has issues with \"border\"\n        Util.log(\"html2canvas: Parse: Exception caught in renderFormValue: \" + e.message);\n      }\n    });\n\n    valueWrap.style.borderColor = \"black\";\n    valueWrap.style.borderStyle = \"solid\";\n    valueWrap.style.display = \"block\";\n    valueWrap.style.position = \"absolute\";\n\n    if (/^(submit|reset|button|text|password)$/.test(el.type) || el.nodeName === \"SELECT\"){\n      valueWrap.style.lineHeight = getCSS(el, \"height\");\n    }\n\n    valueWrap.style.top = bounds.top + \"px\";\n    valueWrap.style.left = bounds.left + \"px\";\n\n    textValue = (el.nodeName === \"SELECT\") ? (el.options[el.selectedIndex] || 0).text : el.value;\n    if(!textValue) {\n      textValue = el.placeholder;\n    }\n\n    textNode = doc.createTextNode(textValue);\n\n    valueWrap.appendChild(textNode);\n    body.appendChild(valueWrap);\n\n    renderText(el, textNode, stack);\n    body.removeChild(valueWrap);\n  }\n\n  function drawImage (ctx) {\n    ctx.drawImage.apply(ctx, Array.prototype.slice.call(arguments, 1));\n    numDraws+=1;\n  }\n\n  function getPseudoElement(el, which) {\n    var elStyle = window.getComputedStyle(el, which);\n    if(!elStyle || !elStyle.content || elStyle.content === \"none\" || elStyle.content === \"-moz-alt-content\" || elStyle.display === \"none\") {\n      return;\n    }\n    var content = elStyle.content + '',\n    first = content.substr( 0, 1 );\n    //strips quotes\n    if(first === content.substr( content.length - 1 ) && first.match(/'|\"/)) {\n      content = content.substr( 1, content.length - 2 );\n    }\n\n    var isImage = content.substr( 0, 3 ) === 'url',\n    elps = document.createElement( isImage ? 'img' : 'span' );\n\n    elps.className = pseudoHide + \"-before \" + pseudoHide + \"-after\";\n\n    Object.keys(elStyle).filter(indexedProperty).forEach(function(prop) {\n      // Prevent assigning of read only CSS Rules, ex. length, parentRule\n      try {\n        elps.style[prop] = elStyle[prop];\n      } catch (e) {\n        Util.log(['Tried to assign readonly property ', prop, 'Error:', e]);\n      }\n    });\n\n    if(isImage) {\n      elps.src = Util.parseBackgroundImage(content)[0].args[0];\n    } else {\n      elps.innerHTML = content;\n    }\n    return elps;\n  }\n\n  function indexedProperty(property) {\n    return (isNaN(window.parseInt(property, 10)));\n  }\n\n  function injectPseudoElements(el, stack) {\n    var before = getPseudoElement(el, ':before'),\n    after = getPseudoElement(el, ':after');\n    if(!before && !after) {\n      return;\n    }\n\n    if(before) {\n      el.className += \" \" + pseudoHide + \"-before\";\n      el.parentNode.insertBefore(before, el);\n      parseElement(before, stack, true);\n      el.parentNode.removeChild(before);\n      el.className = el.className.replace(pseudoHide + \"-before\", \"\").trim();\n    }\n\n    if (after) {\n      el.className += \" \" + pseudoHide + \"-after\";\n      el.appendChild(after);\n      parseElement(after, stack, true);\n      el.removeChild(after);\n      el.className = el.className.replace(pseudoHide + \"-after\", \"\").trim();\n    }\n\n  }\n\n  function renderBackgroundRepeat(ctx, image, backgroundPosition, bounds) {\n    var offsetX = Math.round(bounds.left + backgroundPosition.left),\n    offsetY = Math.round(bounds.top + backgroundPosition.top);\n\n    ctx.createPattern(image);\n    ctx.translate(offsetX, offsetY);\n    ctx.fill();\n    ctx.translate(-offsetX, -offsetY);\n  }\n\n  function backgroundRepeatShape(ctx, image, backgroundPosition, bounds, left, top, width, height) {\n    var args = [];\n    args.push([\"line\", Math.round(left), Math.round(top)]);\n    args.push([\"line\", Math.round(left + width), Math.round(top)]);\n    args.push([\"line\", Math.round(left + width), Math.round(height + top)]);\n    args.push([\"line\", Math.round(left), Math.round(height + top)]);\n    createShape(ctx, args);\n    ctx.save();\n    ctx.clip();\n    renderBackgroundRepeat(ctx, image, backgroundPosition, bounds);\n    ctx.restore();\n  }\n\n  function renderBackgroundColor(ctx, backgroundBounds, bgcolor) {\n    renderRect(\n      ctx,\n      backgroundBounds.left,\n      backgroundBounds.top,\n      backgroundBounds.width,\n      backgroundBounds.height,\n      bgcolor\n      );\n  }\n\n  function renderBackgroundRepeating(el, bounds, ctx, image, imageIndex) {\n    var backgroundSize = Util.BackgroundSize(el, bounds, image, imageIndex),\n    backgroundPosition = Util.BackgroundPosition(el, bounds, image, imageIndex, backgroundSize),\n    backgroundRepeat = getCSS(el, \"backgroundRepeat\").split(\",\").map(Util.trimText);\n\n    image = resizeImage(image, backgroundSize);\n\n    backgroundRepeat = backgroundRepeat[imageIndex] || backgroundRepeat[0];\n\n    switch (backgroundRepeat) {\n      case \"repeat-x\":\n        backgroundRepeatShape(ctx, image, backgroundPosition, bounds,\n          bounds.left, bounds.top + backgroundPosition.top, 99999, image.height);\n        break;\n\n      case \"repeat-y\":\n        backgroundRepeatShape(ctx, image, backgroundPosition, bounds,\n          bounds.left + backgroundPosition.left, bounds.top, image.width, 99999);\n        break;\n\n      case \"no-repeat\":\n        backgroundRepeatShape(ctx, image, backgroundPosition, bounds,\n          bounds.left + backgroundPosition.left, bounds.top + backgroundPosition.top, image.width, image.height);\n        break;\n\n      default:\n        renderBackgroundRepeat(ctx, image, backgroundPosition, {\n          top: bounds.top,\n          left: bounds.left,\n          width: image.width,\n          height: image.height\n        });\n        break;\n    }\n  }\n\n  function renderBackgroundImage(element, bounds, ctx) {\n    var backgroundImage = getCSS(element, \"backgroundImage\"),\n    backgroundImages = Util.parseBackgroundImage(backgroundImage),\n    image,\n    imageIndex = backgroundImages.length;\n\n    while(imageIndex--) {\n      backgroundImage = backgroundImages[imageIndex];\n\n      if (!backgroundImage.args || backgroundImage.args.length === 0) {\n        continue;\n      }\n\n      var key = backgroundImage.method === 'url' ?\n      backgroundImage.args[0] :\n      backgroundImage.value;\n\n      image = loadImage(key);\n\n      // TODO add support for background-origin\n      if (image) {\n        renderBackgroundRepeating(element, bounds, ctx, image, imageIndex);\n      } else {\n        Util.log(\"html2canvas: Error loading background:\", backgroundImage);\n      }\n    }\n  }\n\n  function resizeImage(image, bounds) {\n    if(image.width === bounds.width && image.height === bounds.height) {\n      return image;\n    }\n\n    var ctx, canvas = doc.createElement('canvas');\n    canvas.width = bounds.width;\n    canvas.height = bounds.height;\n    ctx = canvas.getContext(\"2d\");\n    drawImage(ctx, image, 0, 0, image.width, image.height, 0, 0, bounds.width, bounds.height );\n    return canvas;\n  }\n\n  function setOpacity(ctx, element, parentStack) {\n    return ctx.setVariable(\"globalAlpha\", getCSS(element, \"opacity\") * ((parentStack) ? parentStack.opacity : 1));\n  }\n\n  function removePx(str) {\n    return str.replace(\"px\", \"\");\n  }\n\n  var transformRegExp = /(matrix)\\((.+)\\)/;\n\n  function getTransform(element, parentStack) {\n    var transform = getCSS(element, \"transform\") || getCSS(element, \"-webkit-transform\") || getCSS(element, \"-moz-transform\") || getCSS(element, \"-ms-transform\") || getCSS(element, \"-o-transform\");\n    var transformOrigin = getCSS(element, \"transform-origin\") || getCSS(element, \"-webkit-transform-origin\") || getCSS(element, \"-moz-transform-origin\") || getCSS(element, \"-ms-transform-origin\") || getCSS(element, \"-o-transform-origin\") || \"0px 0px\";\n\n    transformOrigin = transformOrigin.split(\" \").map(removePx).map(Util.asFloat);\n\n    var matrix;\n    if (transform && transform !== \"none\") {\n      var match = transform.match(transformRegExp);\n      if (match) {\n        switch(match[1]) {\n          case \"matrix\":\n            matrix = match[2].split(\",\").map(Util.trimText).map(Util.asFloat);\n            break;\n        }\n      }\n    }\n\n    return {\n      origin: transformOrigin,\n      matrix: matrix\n    };\n  }\n\n  function createStack(element, parentStack, bounds, transform) {\n    var ctx = h2cRenderContext((!parentStack) ? documentWidth() : bounds.width , (!parentStack) ? documentHeight() : bounds.height),\n    stack = {\n      ctx: ctx,\n      opacity: setOpacity(ctx, element, parentStack),\n      cssPosition: getCSS(element, \"position\"),\n      borders: getBorderData(element),\n      transform: transform,\n      clip: (parentStack && parentStack.clip) ? Util.Extend( {}, parentStack.clip ) : null\n    };\n\n    setZ(element, stack, parentStack);\n\n    // TODO correct overflow for absolute content residing under a static position\n    if (options.useOverflow === true && /(hidden|scroll|auto)/.test(getCSS(element, \"overflow\")) === true && /(BODY)/i.test(element.nodeName) === false){\n      stack.clip = (stack.clip) ? clipBounds(stack.clip, bounds) : bounds;\n    }\n\n    return stack;\n  }\n\n  function getBackgroundBounds(borders, bounds, clip) {\n    var backgroundBounds = {\n      left: bounds.left + borders[3].width,\n      top: bounds.top + borders[0].width,\n      width: bounds.width - (borders[1].width + borders[3].width),\n      height: bounds.height - (borders[0].width + borders[2].width)\n    };\n\n    if (clip) {\n      backgroundBounds = clipBounds(backgroundBounds, clip);\n    }\n\n    return backgroundBounds;\n  }\n\n  function getBounds(element, transform) {\n    var bounds = (transform.matrix) ? Util.OffsetBounds(element) : Util.Bounds(element);\n    transform.origin[0] += bounds.left;\n    transform.origin[1] += bounds.top;\n    return bounds;\n  }\n\n  function renderElement(element, parentStack, pseudoElement, ignoreBackground) {\n    var transform = getTransform(element, parentStack),\n    bounds = getBounds(element, transform),\n    image,\n    stack = createStack(element, parentStack, bounds, transform),\n    borders = stack.borders,\n    ctx = stack.ctx,\n    backgroundBounds = getBackgroundBounds(borders, bounds, stack.clip),\n    borderData = parseBorders(element, bounds, borders),\n    backgroundColor = (ignoreElementsRegExp.test(element.nodeName)) ? \"#efefef\" : getCSS(element, \"backgroundColor\");\n\n\n    createShape(ctx, borderData.clip);\n\n    ctx.save();\n    ctx.clip();\n\n    if (backgroundBounds.height > 0 && backgroundBounds.width > 0 && !ignoreBackground) {\n      renderBackgroundColor(ctx, bounds, backgroundColor);\n      renderBackgroundImage(element, backgroundBounds, ctx);\n    } else if (ignoreBackground) {\n      stack.backgroundColor =  backgroundColor;\n    }\n\n    ctx.restore();\n\n    borderData.borders.forEach(function(border) {\n      renderBorders(ctx, border.args, border.color);\n    });\n\n    if (!pseudoElement) {\n      injectPseudoElements(element, stack);\n    }\n\n    switch(element.nodeName){\n      case \"IMG\":\n        if ((image = loadImage(element.getAttribute('src')))) {\n          renderImage(ctx, element, image, bounds, borders);\n        } else {\n          Util.log(\"html2canvas: Error loading <img>:\" + element.getAttribute('src'));\n        }\n        break;\n      case \"INPUT\":\n        // TODO add all relevant type's, i.e. HTML5 new stuff\n        // todo add support for placeholder attribute for browsers which support it\n        if (/^(text|url|email|submit|button|reset)$/.test(element.type) && (element.value || element.placeholder || \"\").length > 0){\n          renderFormValue(element, bounds, stack);\n        }\n        break;\n      case \"TEXTAREA\":\n        if ((element.value || element.placeholder || \"\").length > 0){\n          renderFormValue(element, bounds, stack);\n        }\n        break;\n      case \"SELECT\":\n        if ((element.options||element.placeholder || \"\").length > 0){\n          renderFormValue(element, bounds, stack);\n        }\n        break;\n      case \"LI\":\n        renderListItem(element, stack, backgroundBounds);\n        break;\n      case \"CANVAS\":\n        renderImage(ctx, element, element, bounds, borders);\n        break;\n    }\n\n    return stack;\n  }\n\n  function isElementVisible(element) {\n    return (getCSS(element, 'display') !== \"none\" && getCSS(element, 'visibility') !== \"hidden\" && !element.hasAttribute(\"data-html2canvas-ignore\"));\n  }\n\n  function parseElement (element, stack, pseudoElement) {\n    if (isElementVisible(element)) {\n      stack = renderElement(element, stack, pseudoElement, false) || stack;\n      if (!ignoreElementsRegExp.test(element.nodeName)) {\n        parseChildren(element, stack, pseudoElement);\n      }\n    }\n  }\n\n  function parseChildren(element, stack, pseudoElement) {\n    Util.Children(element).forEach(function(node) {\n      if (node.nodeType === node.ELEMENT_NODE) {\n        parseElement(node, stack, pseudoElement);\n      } else if (node.nodeType === node.TEXT_NODE) {\n        renderText(element, node, stack);\n      }\n    });\n  }\n\n  function init() {\n    var background = getCSS(document.documentElement, \"backgroundColor\"),\n      transparentBackground = (Util.isTransparent(background) && element === document.body),\n      stack = renderElement(element, null, false, transparentBackground);\n    parseChildren(element, stack);\n\n    if (transparentBackground) {\n      background = stack.backgroundColor;\n    }\n\n    body.removeChild(hidePseudoElements);\n    return {\n      backgroundColor: background,\n      stack: stack\n    };\n  }\n\n  return init();\n};\n\nfunction h2czContext(zindex) {\n  return {\n    zindex: zindex,\n    children: []\n  };\n}\n\n_html2canvas.Preload = function( options ) {\n\n  var images = {\n    numLoaded: 0,   // also failed are counted here\n    numFailed: 0,\n    numTotal: 0,\n    cleanupDone: false\n  },\n  pageOrigin,\n  Util = _html2canvas.Util,\n  methods,\n  i,\n  count = 0,\n  element = options.elements[0] || document.body,\n  doc = element.ownerDocument,\n  domImages = element.getElementsByTagName('img'), // Fetch images of the present element only\n  imgLen = domImages.length,\n  link = doc.createElement(\"a\"),\n  supportCORS = (function( img ){\n    return (img.crossOrigin !== undefined);\n  })(new Image()),\n  timeoutTimer;\n\n  link.href = window.location.href;\n  pageOrigin  = link.protocol + link.host;\n\n  function isSameOrigin(url){\n    link.href = url;\n    link.href = link.href; // YES, BELIEVE IT OR NOT, that is required for IE9 - http://jsfiddle.net/niklasvh/2e48b/\n    var origin = link.protocol + link.host;\n    return (origin === pageOrigin);\n  }\n\n  function start(){\n    Util.log(\"html2canvas: start: images: \" + images.numLoaded + \" / \" + images.numTotal + \" (failed: \" + images.numFailed + \")\");\n    if (!images.firstRun && images.numLoaded >= images.numTotal){\n      Util.log(\"Finished loading images: # \" + images.numTotal + \" (failed: \" + images.numFailed + \")\");\n\n      if (typeof options.complete === \"function\"){\n        options.complete(images);\n      }\n\n    }\n  }\n\n  // TODO modify proxy to serve images with CORS enabled, where available\n  function proxyGetImage(url, img, imageObj){\n    var callback_name,\n    scriptUrl = options.proxy,\n    script;\n\n    link.href = url;\n    url = link.href; // work around for pages with base href=\"\" set - WARNING: this may change the url\n\n    callback_name = 'html2canvas_' + (count++);\n    imageObj.callbackname = callback_name;\n\n    if (scriptUrl.indexOf(\"?\") > -1) {\n      scriptUrl += \"&\";\n    } else {\n      scriptUrl += \"?\";\n    }\n    scriptUrl += 'url=' + encodeURIComponent(url) + '&callback=' + callback_name;\n    script = doc.createElement(\"script\");\n\n    window[callback_name] = function(a){\n      if (a.substring(0,6) === \"error:\"){\n        imageObj.succeeded = false;\n        images.numLoaded++;\n        images.numFailed++;\n        start();\n      } else {\n        setImageLoadHandlers(img, imageObj);\n        img.src = a;\n      }\n      window[callback_name] = undefined; // to work with IE<9  // NOTE: that the undefined callback property-name still exists on the window object (for IE<9)\n      try {\n        delete window[callback_name];  // for all browser that support this\n      } catch(ex) {}\n      script.parentNode.removeChild(script);\n      script = null;\n      delete imageObj.script;\n      delete imageObj.callbackname;\n    };\n\n    script.setAttribute(\"type\", \"text/javascript\");\n    script.setAttribute(\"src\", scriptUrl);\n    imageObj.script = script;\n    window.document.body.appendChild(script);\n\n  }\n\n  function loadPseudoElement(element, type) {\n    var style = window.getComputedStyle(element, type),\n    content = style.content;\n    if (content.substr(0, 3) === 'url') {\n      methods.loadImage(_html2canvas.Util.parseBackgroundImage(content)[0].args[0]);\n    }\n    loadBackgroundImages(style.backgroundImage, element);\n  }\n\n  function loadPseudoElementImages(element) {\n    loadPseudoElement(element, \":before\");\n    loadPseudoElement(element, \":after\");\n  }\n\n  function loadGradientImage(backgroundImage, bounds) {\n    var img = _html2canvas.Generate.Gradient(backgroundImage, bounds);\n\n    if (img !== undefined){\n      images[backgroundImage] = {\n        img: img,\n        succeeded: true\n      };\n      images.numTotal++;\n      images.numLoaded++;\n      start();\n    }\n  }\n\n  function invalidBackgrounds(background_image) {\n    return (background_image && background_image.method && background_image.args && background_image.args.length > 0 );\n  }\n\n  function loadBackgroundImages(background_image, el) {\n    var bounds;\n\n    _html2canvas.Util.parseBackgroundImage(background_image).filter(invalidBackgrounds).forEach(function(background_image) {\n      if (background_image.method === 'url') {\n        methods.loadImage(background_image.args[0]);\n      } else if(background_image.method.match(/\\-?gradient$/)) {\n        if(bounds === undefined) {\n          bounds = _html2canvas.Util.Bounds(el);\n        }\n        loadGradientImage(background_image.value, bounds);\n      }\n    });\n  }\n\n  function getImages (el) {\n    var elNodeType = false;\n\n    // Firefox fails with permission denied on pages with iframes\n    try {\n      Util.Children(el).forEach(getImages);\n    }\n    catch( e ) {}\n\n    try {\n      elNodeType = el.nodeType;\n    } catch (ex) {\n      elNodeType = false;\n      Util.log(\"html2canvas: failed to access some element's nodeType - Exception: \" + ex.message);\n    }\n\n    if (elNodeType === 1 || elNodeType === undefined) {\n      loadPseudoElementImages(el);\n      try {\n        loadBackgroundImages(Util.getCSS(el, 'backgroundImage'), el);\n      } catch(e) {\n        Util.log(\"html2canvas: failed to get background-image - Exception: \" + e.message);\n      }\n      loadBackgroundImages(el);\n    }\n  }\n\n  function setImageLoadHandlers(img, imageObj) {\n    img.onload = function() {\n      if ( imageObj.timer !== undefined ) {\n        // CORS succeeded\n        window.clearTimeout( imageObj.timer );\n      }\n\n      images.numLoaded++;\n      imageObj.succeeded = true;\n      img.onerror = img.onload = null;\n      start();\n    };\n    img.onerror = function() {\n      if (img.crossOrigin === \"anonymous\") {\n        // CORS failed\n        window.clearTimeout( imageObj.timer );\n\n        // let's try with proxy instead\n        if ( options.proxy ) {\n          var src = img.src;\n          img = new Image();\n          imageObj.img = img;\n          img.src = src;\n\n          proxyGetImage( img.src, img, imageObj );\n          return;\n        }\n      }\n\n      images.numLoaded++;\n      images.numFailed++;\n      imageObj.succeeded = false;\n      img.onerror = img.onload = null;\n      start();\n    };\n  }\n\n  methods = {\n    loadImage: function( src ) {\n      var img, imageObj;\n      if ( src && images[src] === undefined ) {\n        img = new Image();\n        if ( src.match(/data:image\\/.*;base64,/i) ) {\n          img.src = src.replace(/url\\(['\"]{0,}|['\"]{0,}\\)$/ig, '');\n          imageObj = images[src] = {\n            img: img\n          };\n          images.numTotal++;\n          setImageLoadHandlers(img, imageObj);\n        } else if ( isSameOrigin( src ) || options.allowTaint ===  true ) {\n          imageObj = images[src] = {\n            img: img\n          };\n          images.numTotal++;\n          setImageLoadHandlers(img, imageObj);\n          img.src = src;\n        } else if ( supportCORS && !options.allowTaint && options.useCORS ) {\n          // attempt to load with CORS\n\n          img.crossOrigin = \"anonymous\";\n          imageObj = images[src] = {\n            img: img\n          };\n          images.numTotal++;\n          setImageLoadHandlers(img, imageObj);\n          img.src = src;\n        } else if ( options.proxy ) {\n          imageObj = images[src] = {\n            img: img\n          };\n          images.numTotal++;\n          proxyGetImage( src, img, imageObj );\n        }\n      }\n\n    },\n    cleanupDOM: function(cause) {\n      var img, src;\n      if (!images.cleanupDone) {\n        if (cause && typeof cause === \"string\") {\n          Util.log(\"html2canvas: Cleanup because: \" + cause);\n        } else {\n          Util.log(\"html2canvas: Cleanup after timeout: \" + options.timeout + \" ms.\");\n        }\n\n        for (src in images) {\n          if (images.hasOwnProperty(src)) {\n            img = images[src];\n            if (typeof img === \"object\" && img.callbackname && img.succeeded === undefined) {\n              // cancel proxy image request\n              window[img.callbackname] = undefined; // to work with IE<9  // NOTE: that the undefined callback property-name still exists on the window object (for IE<9)\n              try {\n                delete window[img.callbackname];  // for all browser that support this\n              } catch(ex) {}\n              if (img.script && img.script.parentNode) {\n                img.script.setAttribute(\"src\", \"about:blank\");  // try to cancel running request\n                img.script.parentNode.removeChild(img.script);\n              }\n              images.numLoaded++;\n              images.numFailed++;\n              Util.log(\"html2canvas: Cleaned up failed img: '\" + src + \"' Steps: \" + images.numLoaded + \" / \" + images.numTotal);\n            }\n          }\n        }\n\n        // cancel any pending requests\n        if(window.stop !== undefined) {\n          window.stop();\n        } else if(document.execCommand !== undefined) {\n          document.execCommand(\"Stop\", false);\n        }\n        if (document.close !== undefined) {\n          document.close();\n        }\n        images.cleanupDone = true;\n        if (!(cause && typeof cause === \"string\")) {\n          start();\n        }\n      }\n    },\n\n    renderingDone: function() {\n      if (timeoutTimer) {\n        window.clearTimeout(timeoutTimer);\n      }\n    }\n  };\n\n  if (options.timeout > 0) {\n    timeoutTimer = window.setTimeout(methods.cleanupDOM, options.timeout);\n  }\n\n  Util.log('html2canvas: Preload starts: finding background-images');\n  images.firstRun = true;\n\n  getImages(element);\n\n  Util.log('html2canvas: Preload: Finding images');\n  // load <img> images\n  for (i = 0; i < imgLen; i+=1){\n    methods.loadImage( domImages[i].getAttribute( \"src\" ) );\n  }\n\n  images.firstRun = false;\n  Util.log('html2canvas: Preload: Done.');\n  if (images.numTotal === images.numLoaded) {\n    start();\n  }\n\n  return methods;\n};\n\n_html2canvas.Renderer = function(parseQueue, options){\n\n  // http://www.w3.org/TR/CSS21/zindex.html\n  function createRenderQueue(parseQueue) {\n    var queue = [],\n    rootContext;\n\n    rootContext = (function buildStackingContext(rootNode) {\n      var rootContext = {};\n      function insert(context, node, specialParent) {\n        var zi = (node.zIndex.zindex === 'auto') ? 0 : Number(node.zIndex.zindex),\n        contextForChildren = context, // the stacking context for children\n        isPositioned = node.zIndex.isPositioned,\n        isFloated = node.zIndex.isFloated,\n        stub = {node: node},\n        childrenDest = specialParent; // where children without z-index should be pushed into\n\n        if (node.zIndex.ownStacking) {\n          // '!' comes before numbers in sorted array\n          contextForChildren = stub.context = { '!': [{node:node, children: []}]};\n          childrenDest = undefined;\n        } else if (isPositioned || isFloated) {\n          childrenDest = stub.children = [];\n        }\n\n        if (zi === 0 && specialParent) {\n          specialParent.push(stub);\n        } else {\n          if (!context[zi]) { context[zi] = []; }\n          context[zi].push(stub);\n        }\n\n        node.zIndex.children.forEach(function(childNode) {\n          insert(contextForChildren, childNode, childrenDest);\n        });\n      }\n      insert(rootContext, rootNode);\n      return rootContext;\n    })(parseQueue);\n\n    function sortZ(context) {\n      Object.keys(context).sort().forEach(function(zi) {\n        var nonPositioned = [],\n        floated = [],\n        positioned = [],\n        list = [];\n\n        // positioned after static\n        context[zi].forEach(function(v) {\n          if (v.node.zIndex.isPositioned || v.node.zIndex.opacity < 1) {\n            // http://www.w3.org/TR/css3-color/#transparency\n            // non-positioned element with opactiy < 1 should be stacked as if it were a positioned element with ‘z-index: 0’ and ‘opacity: 1’.\n            positioned.push(v);\n          } else if (v.node.zIndex.isFloated) {\n            floated.push(v);\n          } else {\n            nonPositioned.push(v);\n          }\n        });\n\n        (function walk(arr) {\n          arr.forEach(function(v) {\n            list.push(v);\n            if (v.children) { walk(v.children); }\n          });\n        })(nonPositioned.concat(floated, positioned));\n\n        list.forEach(function(v) {\n          if (v.context) {\n            sortZ(v.context);\n          } else {\n            queue.push(v.node);\n          }\n        });\n      });\n    }\n\n    sortZ(rootContext);\n\n    return queue;\n  }\n\n  function getRenderer(rendererName) {\n    var renderer;\n\n    if (typeof options.renderer === \"string\" && _html2canvas.Renderer[rendererName] !== undefined) {\n      renderer = _html2canvas.Renderer[rendererName](options);\n    } else if (typeof rendererName === \"function\") {\n      renderer = rendererName(options);\n    } else {\n      throw new Error(\"Unknown renderer\");\n    }\n\n    if ( typeof renderer !== \"function\" ) {\n      throw new Error(\"Invalid renderer defined\");\n    }\n    return renderer;\n  }\n\n  return getRenderer(options.renderer)(parseQueue, options, document, createRenderQueue(parseQueue.stack), _html2canvas);\n};\n\n_html2canvas.Util.Support = function (options, doc) {\n\n  function supportSVGRendering() {\n    var img = new Image(),\n    canvas = doc.createElement(\"canvas\"),\n    ctx = (canvas.getContext === undefined) ? false : canvas.getContext(\"2d\");\n    if (ctx === false) {\n      return false;\n    }\n    canvas.width = canvas.height = 10;\n    img.src = [\n    \"data:image/svg+xml,\",\n    \"<svg xmlns='http://www.w3.org/2000/svg' width='10' height='10'>\",\n    \"<foreignObject width='10' height='10'>\",\n    \"<div xmlns='http://www.w3.org/1999/xhtml' style='width:10;height:10;'>\",\n    \"sup\",\n    \"</div>\",\n    \"</foreignObject>\",\n    \"</svg>\"\n    ].join(\"\");\n    try {\n      ctx.drawImage(img, 0, 0);\n      canvas.toDataURL();\n    } catch(e) {\n      return false;\n    }\n    _html2canvas.Util.log('html2canvas: Parse: SVG powered rendering available');\n    return true;\n  }\n\n  // Test whether we can use ranges to measure bounding boxes\n  // Opera doesn't provide valid bounds.height/bottom even though it supports the method.\n\n  function supportRangeBounds() {\n    var r, testElement, rangeBounds, rangeHeight, support = false;\n\n    if (doc.createRange) {\n      r = doc.createRange();\n      if (r.getBoundingClientRect) {\n        testElement = doc.createElement('boundtest');\n        testElement.style.height = \"123px\";\n        testElement.style.display = \"block\";\n        doc.body.appendChild(testElement);\n\n        r.selectNode(testElement);\n        rangeBounds = r.getBoundingClientRect();\n        rangeHeight = rangeBounds.height;\n\n        if (rangeHeight === 123) {\n          support = true;\n        }\n        doc.body.removeChild(testElement);\n      }\n    }\n\n    return support;\n  }\n\n  return {\n    rangeBounds: supportRangeBounds(),\n    svgRendering: options.svgRendering && supportSVGRendering()\n  };\n};\nwindow.html2canvas = function(elements, opts) {\n  elements = (elements.length) ? elements : [elements];\n  var queue,\n  canvas,\n  options = {\n    // general\n    logging: false,\n    elements: elements,\n    background: \"#fff\",\n\n    // preload options\n    proxy: null,\n    timeout: 0,    // no timeout\n    useCORS: false, // try to load images as CORS (where available), before falling back to proxy\n    allowTaint: false, // whether to allow images to taint the canvas, won't need proxy if set to true\n\n    // parse options\n    svgRendering: false, // use svg powered rendering where available (FF11+)\n    ignoreElements: \"IFRAME|OBJECT|PARAM\",\n    useOverflow: true,\n    letterRendering: false,\n    chinese: false,\n\n    // render options\n\n    width: null,\n    height: null,\n    taintTest: true, // do a taint test with all images before applying to canvas\n    renderer: \"Canvas\"\n  };\n\n  options = _html2canvas.Util.Extend(opts, options);\n\n  _html2canvas.logging = options.logging;\n  options.complete = function( images ) {\n\n    if (typeof options.onpreloaded === \"function\") {\n      if ( options.onpreloaded( images ) === false ) {\n        return;\n      }\n    }\n    queue = _html2canvas.Parse( images, options );\n\n    if (typeof options.onparsed === \"function\") {\n      if ( options.onparsed( queue ) === false ) {\n        return;\n      }\n    }\n\n    canvas = _html2canvas.Renderer( queue, options );\n\n    if (typeof options.onrendered === \"function\") {\n      options.onrendered( canvas );\n    }\n\n\n  };\n\n  // for pages without images, we still want this to be async, i.e. return methods before executing\n  window.setTimeout( function(){\n    _html2canvas.Preload( options );\n  }, 0 );\n\n  return {\n    render: function( queue, opts ) {\n      return _html2canvas.Renderer( queue, _html2canvas.Util.Extend(opts, options) );\n    },\n    parse: function( images, opts ) {\n      return _html2canvas.Parse( images, _html2canvas.Util.Extend(opts, options) );\n    },\n    preload: function( opts ) {\n      return _html2canvas.Preload( _html2canvas.Util.Extend(opts, options) );\n    },\n    log: _html2canvas.Util.log\n  };\n};\n\nwindow.html2canvas.log = _html2canvas.Util.log; // for renderers\nwindow.html2canvas.Renderer = {\n  Canvas: undefined // We are assuming this will be used\n};\n_html2canvas.Renderer.Canvas = function(options) {\n  options = options || {};\n\n  var doc = document,\n  safeImages = [],\n  testCanvas = document.createElement(\"canvas\"),\n  testctx = testCanvas.getContext(\"2d\"),\n  Util = _html2canvas.Util,\n  canvas = options.canvas || doc.createElement('canvas');\n\n  function createShape(ctx, args) {\n    ctx.beginPath();\n    args.forEach(function(arg) {\n      ctx[arg.name].apply(ctx, arg['arguments']);\n    });\n    ctx.closePath();\n  }\n\n  function safeImage(item) {\n    if (safeImages.indexOf(item['arguments'][0].src ) === -1) {\n      testctx.drawImage(item['arguments'][0], 0, 0);\n      try {\n        testctx.getImageData(0, 0, 1, 1);\n      } catch(e) {\n        testCanvas = doc.createElement(\"canvas\");\n        testctx = testCanvas.getContext(\"2d\");\n        return false;\n      }\n      safeImages.push(item['arguments'][0].src);\n    }\n    return true;\n  }\n\n  function renderItem(ctx, item) {\n    switch(item.type){\n      case \"variable\":\n        ctx[item.name] = item['arguments'];\n        break;\n      case \"function\":\n        switch(item.name) {\n          case \"createPattern\":\n            if (item['arguments'][0].width > 0 && item['arguments'][0].height > 0) {\n              try {\n                ctx.fillStyle = ctx.createPattern(item['arguments'][0], \"repeat\");\n              }\n              catch(e) {\n                Util.log(\"html2canvas: Renderer: Error creating pattern\", e.message);\n              }\n            }\n            break;\n          case \"drawShape\":\n            createShape(ctx, item['arguments']);\n            break;\n          case \"drawImage\":\n            if (item['arguments'][8] > 0 && item['arguments'][7] > 0) {\n              if (!options.taintTest || (options.taintTest && safeImage(item))) {\n                ctx.drawImage.apply( ctx, item['arguments'] );\n              }\n            }\n            break;\n          default:\n            ctx[item.name].apply(ctx, item['arguments']);\n        }\n        break;\n    }\n  }\n\n  return function(parsedData, options, document, queue, _html2canvas) {\n    var ctx = canvas.getContext(\"2d\"),\n    newCanvas,\n    bounds,\n    fstyle,\n    zStack = parsedData.stack;\n\n    canvas.width = canvas.style.width =  options.width || zStack.ctx.width;\n    canvas.height = canvas.style.height = options.height || zStack.ctx.height;\n\n    fstyle = ctx.fillStyle;\n    ctx.fillStyle = (Util.isTransparent(zStack.backgroundColor) && options.background !== undefined) ? options.background : parsedData.backgroundColor;\n    ctx.fillRect(0, 0, canvas.width, canvas.height);\n    ctx.fillStyle = fstyle;\n\n    queue.forEach(function(storageContext) {\n      // set common settings for canvas\n      ctx.textBaseline = \"bottom\";\n      ctx.save();\n\n      if (storageContext.transform.matrix) {\n        ctx.translate(storageContext.transform.origin[0], storageContext.transform.origin[1]);\n        ctx.transform.apply(ctx, storageContext.transform.matrix);\n        ctx.translate(-storageContext.transform.origin[0], -storageContext.transform.origin[1]);\n      }\n\n      if (storageContext.clip){\n        ctx.beginPath();\n        ctx.rect(storageContext.clip.left, storageContext.clip.top, storageContext.clip.width, storageContext.clip.height);\n        ctx.clip();\n      }\n\n      if (storageContext.ctx.storage) {\n        storageContext.ctx.storage.forEach(function(item) {\n          renderItem(ctx, item);\n        });\n      }\n\n      ctx.restore();\n    });\n\n    Util.log(\"html2canvas: Renderer: Canvas renderer done - returning canvas obj\");\n\n    if (options.elements.length === 1) {\n      if (typeof options.elements[0] === \"object\" && options.elements[0].nodeName !== \"BODY\") {\n        // crop image to the bounds of selected (single) element\n        bounds = _html2canvas.Util.Bounds(options.elements[0]);\n        newCanvas = document.createElement('canvas');\n        newCanvas.width = Math.ceil(bounds.width);\n        newCanvas.height = Math.ceil(bounds.height);\n        ctx = newCanvas.getContext(\"2d\");\n\n        // fix https://github.com/niklasvh/html2canvas/commit/f61ceea01d0240624aaee5b24d02f4e2fe6a69d2\n        //ctx.drawImage(canvas, bounds.left, bounds.top, bounds.width, bounds.height, 0, 0, bounds.width, bounds.height);\n        var imgData = canvas.getContext(\"2d\").getImageData(bounds.left, bounds.top, bounds.width, bounds.height);\n        ctx.putImageData(imgData, 0, 0);\n        canvas = null;\n        return newCanvas;\n      }\n    }\n\n    return canvas;\n  };\n};\n})(window,document);"
  },
  {
    "path": "flowable-ui-web/task/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": "flowable-ui-web/task/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": "flowable-ui-web/task/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": "flowable-ui-web/task/libs/ng-file-upload/FileAPI.js",
    "content": "/*! FileAPI 2.0.7 - BSD | git://github.com/mailru/FileAPI.git\n * FileAPI — a set of  javascript tools for working with files. Multiupload, drag'n'drop and chunked file upload. Images: crop, resize and auto orientation by EXIF.\n */\n\n/*\n * JavaScript Canvas to Blob 2.0.5\n * https://github.com/blueimp/JavaScript-Canvas-to-Blob\n *\n * Copyright 2012, Sebastian Tschan\n * https://blueimp.net\n *\n * Licensed under the MIT license:\n * http://www.opensource.org/licenses/MIT\n *\n * Based on stackoverflow user Stoive's code snippet:\n * http://stackoverflow.com/q/4998908\n */\n\n/*jslint nomen: true, regexp: true */\n/*global window, atob, Blob, ArrayBuffer, Uint8Array */\n\n(function (window) {\n    'use strict';\n    var CanvasPrototype = window.HTMLCanvasElement &&\n            window.HTMLCanvasElement.prototype,\n        hasBlobConstructor = window.Blob && (function () {\n            try {\n                return Boolean(new Blob());\n            } catch (e) {\n                return false;\n            }\n        }()),\n        hasArrayBufferViewSupport = hasBlobConstructor && window.Uint8Array &&\n            (function () {\n                try {\n                    return new Blob([new Uint8Array(100)]).size === 100;\n                } catch (e) {\n                    return false;\n                }\n            }()),\n        BlobBuilder = window.BlobBuilder || window.WebKitBlobBuilder ||\n            window.MozBlobBuilder || window.MSBlobBuilder,\n        dataURLtoBlob = (hasBlobConstructor || BlobBuilder) && window.atob &&\n            window.ArrayBuffer && window.Uint8Array && function (dataURI) {\n                var byteString,\n                    arrayBuffer,\n                    intArray,\n                    i,\n                    mimeString,\n                    bb;\n                if (dataURI.split(',')[0].indexOf('base64') >= 0) {\n                    // Convert base64 to raw binary data held in a string:\n                    byteString = atob(dataURI.split(',')[1]);\n                } else {\n                    // Convert base64/URLEncoded data component to raw binary data:\n                    byteString = decodeURIComponent(dataURI.split(',')[1]);\n                }\n                // Write the bytes of the string to an ArrayBuffer:\n                arrayBuffer = new ArrayBuffer(byteString.length);\n                intArray = new Uint8Array(arrayBuffer);\n                for (i = 0; i < byteString.length; i += 1) {\n                    intArray[i] = byteString.charCodeAt(i);\n                }\n                // Separate out the mime component:\n                mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0];\n                // Write the ArrayBuffer (or ArrayBufferView) to a blob:\n                if (hasBlobConstructor) {\n                    return new Blob(\n                        [hasArrayBufferViewSupport ? intArray : arrayBuffer],\n                        {type: mimeString}\n                    );\n                }\n                bb = new BlobBuilder();\n                bb.append(arrayBuffer);\n                return bb.getBlob(mimeString);\n            };\n    if (window.HTMLCanvasElement && !CanvasPrototype.toBlob) {\n        if (CanvasPrototype.mozGetAsFile) {\n            CanvasPrototype.toBlob = function (callback, type, quality) {\n                if (quality && CanvasPrototype.toDataURL && dataURLtoBlob) {\n                    callback(dataURLtoBlob(this.toDataURL(type, quality)));\n                } else {\n                    callback(this.mozGetAsFile('blob', type));\n                }\n            };\n        } else if (CanvasPrototype.toDataURL && dataURLtoBlob) {\n            CanvasPrototype.toBlob = function (callback, type, quality) {\n                callback(dataURLtoBlob(this.toDataURL(type, quality)));\n            };\n        }\n    }\n    window.dataURLtoBlob = dataURLtoBlob;\n})(window);\n\n/*jslint evil: true */\n/*global window, URL, webkitURL, ActiveXObject */\n\n(function (window, undef){\n\t'use strict';\n\n\tvar\n\t\tgid = 1,\n\t\tnoop = function (){},\n\n\t\tdocument = window.document,\n\t\tdoctype = document.doctype || {},\n\t\tuserAgent = window.navigator.userAgent,\n\n\t\t// https://github.com/blueimp/JavaScript-Load-Image/blob/master/load-image.js#L48\n\t\tapiURL = (window.createObjectURL && window) || (window.URL && URL.revokeObjectURL && URL) || (window.webkitURL && webkitURL),\n\n\t\tBlob = window.Blob,\n\t\tFile = window.File,\n\t\tFileReader = window.FileReader,\n\t\tFormData = window.FormData,\n\n\n\t\tXMLHttpRequest = window.XMLHttpRequest,\n\t\tjQuery = window.jQuery,\n\n\t\thtml5 =    !!(File && (FileReader && (window.Uint8Array || FormData || XMLHttpRequest.prototype.sendAsBinary)))\n\t\t\t\t&& !(/safari\\//i.test(userAgent) && !/chrome\\//i.test(userAgent) && /windows/i.test(userAgent)), // BugFix: https://github.com/mailru/FileAPI/issues/25\n\n\t\tcors = html5 && ('withCredentials' in (new XMLHttpRequest)),\n\n\t\tchunked = html5 && !!Blob && !!(Blob.prototype.webkitSlice || Blob.prototype.mozSlice || Blob.prototype.slice),\n\n\t\t// https://github.com/blueimp/JavaScript-Canvas-to-Blob\n\t\tdataURLtoBlob = window.dataURLtoBlob,\n\n\n\t\t_rimg = /img/i,\n\t\t_rcanvas = /canvas/i,\n\t\t_rimgcanvas = /img|canvas/i,\n\t\t_rinput = /input/i,\n\t\t_rdata = /^data:[^,]+,/,\n\n\t\t_toString = {}.toString,\n\n\n\t\tMath = window.Math,\n\n\t\t_SIZE_CONST = function (pow){\n\t\t\tpow = new window.Number(Math.pow(1024, pow));\n\t\t\tpow.from = function (sz){ return Math.round(sz * this); };\n\t\t\treturn\tpow;\n\t\t},\n\n\t\t_elEvents = {}, // element event listeners\n\t\t_infoReader = [], // list of file info processors\n\n\t\t_readerEvents = 'abort progress error load loadend',\n\t\t_xhrPropsExport = 'status statusText readyState response responseXML responseText responseBody'.split(' '),\n\n\t\tcurrentTarget = 'currentTarget', // for minimize\n\t\tpreventDefault = 'preventDefault', // and this too\n\n\t\t_isArray = function (ar) {\n\t\t\treturn\tar && ('length' in ar);\n\t\t},\n\n\t\t/**\n\t\t * Iterate over a object or array\n\t\t */\n\t\t_each = function (obj, fn, ctx){\n\t\t\tif( obj ){\n\t\t\t\tif( _isArray(obj) ){\n\t\t\t\t\tfor( var i = 0, n = obj.length; i < n; i++ ){\n\t\t\t\t\t\tif( i in obj ){\n\t\t\t\t\t\t\tfn.call(ctx, obj[i], i, obj);\n\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\tfor( var key in obj ){\n\t\t\t\t\t\tif( obj.hasOwnProperty(key) ){\n\t\t\t\t\t\t\tfn.call(ctx, obj[key], key, obj);\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/**\n\t\t * Merge the contents of two or more objects together into the first object\n\t\t */\n\t\t_extend = function (dst){\n\t\t\tvar args = arguments, i = 1, _ext = function (val, key){ dst[key] = val; };\n\t\t\tfor( ; i < args.length; i++ ){\n\t\t\t\t_each(args[i], _ext);\n\t\t\t}\n\t\t\treturn  dst;\n\t\t},\n\n\t\t/**\n\t\t * Add event listener\n\t\t */\n\t\t_on = function (el, type, fn){\n\t\t\tif( el ){\n\t\t\t\tvar uid = api.uid(el);\n\n\t\t\t\tif( !_elEvents[uid] ){\n\t\t\t\t\t_elEvents[uid] = {};\n\t\t\t\t}\n\n\t\t\t\tvar isFileReader = (FileReader && el) && (el instanceof FileReader);\n\t\t\t\t_each(type.split(/\\s+/), function (type){\n\t\t\t\t\tif( jQuery && !isFileReader){\n\t\t\t\t\t\tjQuery.event.add(el, type, fn);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif( !_elEvents[uid][type] ){\n\t\t\t\t\t\t\t_elEvents[uid][type] = [];\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t_elEvents[uid][type].push(fn);\n\n\t\t\t\t\t\tif( el.addEventListener ){ el.addEventListener(type, fn, false); }\n\t\t\t\t\t\telse if( el.attachEvent ){ el.attachEvent('on'+type, fn); }\n\t\t\t\t\t\telse { el['on'+type] = fn; }\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t},\n\n\n\t\t/**\n\t\t * Remove event listener\n\t\t */\n\t\t_off = function (el, type, fn){\n\t\t\tif( el ){\n\t\t\t\tvar uid = api.uid(el), events = _elEvents[uid] || {};\n\n\t\t\t\tvar isFileReader = (FileReader && el) && (el instanceof FileReader);\n\t\t\t\t_each(type.split(/\\s+/), function (type){\n\t\t\t\t\tif( jQuery && !isFileReader){\n\t\t\t\t\t\tjQuery.event.remove(el, type, fn);\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\tvar fns = events[type] || [], i = fns.length;\n\n\t\t\t\t\t\twhile( i-- ){\n\t\t\t\t\t\t\tif( fns[i] === fn ){\n\t\t\t\t\t\t\t\tfns.splice(i, 1);\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\n\t\t\t\t\t\tif( el.addEventListener ){ el.removeEventListener(type, fn, false); }\n\t\t\t\t\t\telse if( el.detachEvent ){ el.detachEvent('on'+type, fn); }\n\t\t\t\t\t\telse { el['on'+type] = null; }\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t},\n\n\n\t\t_one = function(el, type, fn){\n\t\t\t_on(el, type, function _(evt){\n\t\t\t\t_off(el, type, _);\n\t\t\t\tfn(evt);\n\t\t\t});\n\t\t},\n\n\n\t\t_fixEvent = function (evt){\n\t\t\tif( !evt.target ){ evt.target = window.event && window.event.srcElement || document; }\n\t\t\tif( evt.target.nodeType === 3 ){ evt.target = evt.target.parentNode; }\n\t\t\treturn  evt;\n\t\t},\n\n\n\t\t_supportInputAttr = function (attr){\n\t\t\tvar input = document.createElement('input');\n\t\t\tinput.setAttribute('type', \"file\");\n\t\t\treturn attr in input;\n\t\t},\n\n\n\t\t/**\n\t\t * FileAPI (core object)\n\t\t */\n\t\tapi = {\n\t\t\tversion: '2.0.7',\n\n\t\t\tcors: false,\n\t\t\thtml5: true,\n\t\t\tmedia: false,\n\t\t\tformData: true,\n\t\t\tmultiPassResize: true,\n\n\t\t\tdebug: false,\n\t\t\tpingUrl: false,\n\t\t\tmultiFlash: false,\n\t\t\tflashAbortTimeout: 0,\n\t\t\twithCredentials: true,\n\n\t\t\tstaticPath: './dist/',\n\n\t\t\tflashUrl: 0, // @default: './FileAPI.flash.swf'\n\t\t\tflashImageUrl: 0, // @default: './FileAPI.flash.image.swf'\n\n\t\t\tpostNameConcat: function (name, idx){\n\t\t\t\treturn\tname + (idx != null ? '['+ idx +']' : '');\n\t\t\t},\n\n\t\t\text2mime: {\n\t\t\t\t  jpg:\t'image/jpeg'\n\t\t\t\t, tif:\t'image/tiff'\n\t\t\t\t, txt:\t'text/plain'\n\t\t\t},\n\n\t\t\t// Fallback for flash\n\t\t\taccept: {\n\t\t\t\t  'image/*': 'art bm bmp dwg dxf cbr cbz fif fpx gif ico iefs jfif jpe jpeg jpg jps jut mcf nap nif pbm pcx pgm pict pm png pnm qif qtif ras rast rf rp svf tga tif tiff xbm xbm xpm xwd'\n\t\t\t\t, 'audio/*': 'm4a flac aac rm mpa wav wma ogg mp3 mp2 m3u mod amf dmf dsm far gdm imf it m15 med okt s3m stm sfx ult uni xm sid ac3 dts cue aif aiff wpl ape mac mpc mpp shn wv nsf spc gym adplug adx dsp adp ymf ast afc hps xs'\n\t\t\t\t, 'video/*': 'm4v 3gp nsv ts ty strm rm rmvb m3u ifo mov qt divx xvid bivx vob nrg img iso pva wmv asf asx ogm m2v avi bin dat dvr-ms mpg mpeg mp4 mkv avc vp3 svq3 nuv viv dv fli flv wpl'\n\t\t\t},\n\n\t\t\tuploadRetry : 0,\n\t\t\tnetworkDownRetryTimeout : 5000, // milliseconds, don't flood when network is down\n\n\t\t\tchunkSize : 0,\n\t\t\tchunkUploadRetry : 0,\n\t\t\tchunkNetworkDownRetryTimeout : 2000, // milliseconds, don't flood when network is down\n\n\t\t\tKB: _SIZE_CONST(1),\n\t\t\tMB: _SIZE_CONST(2),\n\t\t\tGB: _SIZE_CONST(3),\n\t\t\tTB: _SIZE_CONST(4),\n\n\t\t\tEMPTY_PNG: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAC0lEQVQIW2NkAAIAAAoAAggA9GkAAAAASUVORK5CYII=',\n\n\t\t\texpando: 'fileapi' + (new Date).getTime(),\n\n\t\t\tuid: function (obj){\n\t\t\t\treturn\tobj\n\t\t\t\t\t? (obj[api.expando] = obj[api.expando] || api.uid())\n\t\t\t\t\t: (++gid, api.expando + gid)\n\t\t\t\t;\n\t\t\t},\n\n\t\t\tlog: function (){\n\t\t\t\tif( api.debug && window.console && console.log ){\n\t\t\t\t\tif( console.log.apply ){\n\t\t\t\t\t\tconsole.log.apply(console, arguments);\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\tconsole.log([].join.call(arguments, ' '));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\n\t\t\t/**\n\t\t\t * Create new image\n\t\t\t *\n\t\t\t * @param {String} [src]\n\t\t\t * @param {Function} [fn]   1. error -- boolean, 2. img -- Image element\n\t\t\t * @returns {HTMLElement}\n\t\t\t */\n\t\t\tnewImage: function (src, fn){\n\t\t\t\tvar img = document.createElement('img');\n\t\t\t\tif( fn ){\n\t\t\t\t\tapi.event.one(img, 'error load', function (evt){\n\t\t\t\t\t\tfn(evt.type == 'error', img);\n\t\t\t\t\t\timg = null;\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\timg.src = src;\n\t\t\t\treturn\timg;\n\t\t\t},\n\n\t\t\t/**\n\t\t\t * Get XHR\n\t\t\t * @returns {XMLHttpRequest}\n\t\t\t */\n\t\t\tgetXHR: function (){\n\t\t\t\tvar xhr;\n\n\t\t\t\tif( XMLHttpRequest ){\n\t\t\t\t\txhr = new XMLHttpRequest;\n\t\t\t\t}\n\t\t\t\telse if( window.ActiveXObject ){\n\t\t\t\t\ttry {\n\t\t\t\t\t\txhr = new ActiveXObject('MSXML2.XMLHttp.3.0');\n\t\t\t\t\t} catch (e) {\n\t\t\t\t\t\txhr = new ActiveXObject('Microsoft.XMLHTTP');\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn  xhr;\n\t\t\t},\n\n\t\t\tisArray: _isArray,\n\n\t\t\tsupport: {\n\t\t\t\tdnd:     cors && ('ondrop' in document.createElement('div')),\n\t\t\t\tcors:    cors,\n\t\t\t\thtml5:   html5,\n\t\t\t\tchunked: chunked,\n\t\t\t\tdataURI: true,\n\t\t\t\taccept:   _supportInputAttr('accept'),\n\t\t\t\tmultiple: _supportInputAttr('multiple')\n\t\t\t},\n\n\t\t\tevent: {\n\t\t\t\t  on: _on\n\t\t\t\t, off: _off\n\t\t\t\t, one: _one\n\t\t\t\t, fix: _fixEvent\n\t\t\t},\n\n\n\t\t\tthrottle: function(fn, delay) {\n\t\t\t\tvar id, args;\n\n\t\t\t\treturn function _throttle(){\n\t\t\t\t\targs = arguments;\n\n\t\t\t\t\tif( !id ){\n\t\t\t\t\t\tfn.apply(window, args);\n\t\t\t\t\t\tid = setTimeout(function (){\n\t\t\t\t\t\t\tid = 0;\n\t\t\t\t\t\t\tfn.apply(window, args);\n\t\t\t\t\t\t}, delay);\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\t},\n\n\n\t\t\tF: function (){},\n\n\n\t\t\tparseJSON: function (str){\n\t\t\t\tvar json;\n\t\t\t\tif( window.JSON && JSON.parse ){\n\t\t\t\t\tjson = JSON.parse(str);\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tjson = (new Function('return ('+str.replace(/([\\r\\n])/g, '\\\\$1')+');'))();\n\t\t\t\t}\n\t\t\t\treturn json;\n\t\t\t},\n\n\n\t\t\ttrim: function (str){\n\t\t\t\tstr = String(str);\n\t\t\t\treturn\tstr.trim ? str.trim() : str.replace(/^\\s+|\\s+$/g, '');\n\t\t\t},\n\n\t\t\t/**\n\t\t\t * Simple Defer\n\t\t\t * @return\t{Object}\n\t\t\t */\n\t\t\tdefer: function (){\n\t\t\t\tvar\n\t\t\t\t\t  list = []\n\t\t\t\t\t, result\n\t\t\t\t\t, error\n\t\t\t\t\t, defer = {\n\t\t\t\t\t\tresolve: function (err, res){\n\t\t\t\t\t\t\tdefer.resolve = noop;\n\t\t\t\t\t\t\terror\t= err || false;\n\t\t\t\t\t\t\tresult\t= res;\n\n\t\t\t\t\t\t\twhile( res = list.shift() ){\n\t\t\t\t\t\t\t\tres(error, result);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\n\t\t\t\t\t\tthen: function (fn){\n\t\t\t\t\t\t\tif( error !== undef ){\n\t\t\t\t\t\t\t\tfn(error, result);\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tlist.push(fn);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t};\n\n\t\t\t\treturn\tdefer;\n\t\t\t},\n\n\t\t\tqueue: function (fn){\n\t\t\t\tvar\n\t\t\t\t\t  _idx = 0\n\t\t\t\t\t, _length = 0\n\t\t\t\t\t, _fail = false\n\t\t\t\t\t, _end = false\n\t\t\t\t\t, queue = {\n\t\t\t\t\t\tinc: function (){\n\t\t\t\t\t\t\t_length++;\n\t\t\t\t\t\t},\n\n\t\t\t\t\t\tnext: function (){\n\t\t\t\t\t\t\t_idx++;\n\t\t\t\t\t\t\tsetTimeout(queue.check, 0);\n\t\t\t\t\t\t},\n\n\t\t\t\t\t\tcheck: function (){\n\t\t\t\t\t\t\t(_idx >= _length) && !_fail && queue.end();\n\t\t\t\t\t\t},\n\n\t\t\t\t\t\tisFail: function (){\n\t\t\t\t\t\t\treturn _fail;\n\t\t\t\t\t\t},\n\n\t\t\t\t\t\tfail: function (){\n\t\t\t\t\t\t\t!_fail && fn(_fail = true);\n\t\t\t\t\t\t},\n\n\t\t\t\t\t\tend: function (){\n\t\t\t\t\t\t\tif( !_end ){\n\t\t\t\t\t\t\t\t_end = true;\n\t\t\t\t\t\t\t\tfn();\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 queue;\n\t\t\t},\n\n\n\t\t\t/**\n\t\t\t * For each object\n\t\t\t *\n\t\t\t * @param\t{Object|Array}\tobj\n\t\t\t * @param\t{Function}\t\tfn\n\t\t\t * @param\t{*}\t\t\t\t[ctx]\n\t\t\t */\n\t\t\teach: _each,\n\n\n\t\t\t/**\n\t\t\t * Async for\n\t\t\t * @param {Array} array\n\t\t\t * @param {Function} callback\n\t\t\t */\n\t\t\tafor: function (array, callback){\n\t\t\t\tvar i = 0, n = array.length;\n\n\t\t\t\tif( _isArray(array) && n-- ){\n\t\t\t\t\t(function _next(){\n\t\t\t\t\t\tcallback(n != i && _next, array[i], i++);\n\t\t\t\t\t})();\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tcallback(false);\n\t\t\t\t}\n\t\t\t},\n\n\n\t\t\t/**\n\t\t\t * Merge the contents of two or more objects together into the first object\n\t\t\t *\n\t\t\t * @param\t{Object}\tdst\n\t\t\t * @return\t{Object}\n\t\t\t */\n\t\t\textend: _extend,\n\n\n\t\t\t/**\n\t\t\t * Is file?\n\t\t\t * @param  {File}  file\n\t\t\t * @return {Boolean}\n\t\t\t */\n\t\t\tisFile: function (file){\n\t\t\t\treturn _toString.call(file) === '[object File]';\n\t\t\t},\n\n\n\t\t\t/**\n\t\t\t * Is blob?\n\t\t\t * @param   {Blob}  blob\n\t\t\t * @returns {Boolean}\n\t\t\t */\n\t\t\tisBlob: function (blob) {\n\t\t\t\treturn this.isFile(blob) || (_toString.call(blob) === '[object Blob]');\n\t\t\t},\n\n\n\t\t\t/**\n\t\t\t * Is canvas element\n\t\t\t *\n\t\t\t * @param\t{HTMLElement}\tel\n\t\t\t * @return\t{Boolean}\n\t\t\t */\n\t\t\tisCanvas: function (el){\n\t\t\t\treturn\tel && _rcanvas.test(el.nodeName);\n\t\t\t},\n\n\n\t\t\tgetFilesFilter: function (filter){\n\t\t\t\tfilter = typeof filter == 'string' ? filter : (filter.getAttribute && filter.getAttribute('accept') || '');\n\t\t\t\treturn\tfilter ? new RegExp('('+ filter.replace(/\\./g, '\\\\.').replace(/,/g, '|') +')$', 'i') : /./;\n\t\t\t},\n\n\n\n\t\t\t/**\n\t\t\t * Read as DataURL\n\t\t\t *\n\t\t\t * @param {File|Element} file\n\t\t\t * @param {Function} fn\n\t\t\t */\n\t\t\treadAsDataURL: function (file, fn){\n\t\t\t\tif( api.isCanvas(file) ){\n\t\t\t\t\t_emit(file, fn, 'load', api.toDataURL(file));\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\t_readAs(file, fn, 'DataURL');\n\t\t\t\t}\n\t\t\t},\n\n\n\t\t\t/**\n\t\t\t * Read as Binary string\n\t\t\t *\n\t\t\t * @param {File} file\n\t\t\t * @param {Function} fn\n\t\t\t */\n\t\t\treadAsBinaryString: function (file, fn){\n\t\t\t\tif( _hasSupportReadAs('BinaryString') ){\n\t\t\t\t\t_readAs(file, fn, 'BinaryString');\n\t\t\t\t} else {\n\t\t\t\t\t// Hello IE10!\n\t\t\t\t\t_readAs(file, function (evt){\n\t\t\t\t\t\tif( evt.type == 'load' ){\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t// dataURL -> binaryString\n\t\t\t\t\t\t\t\tevt.result = api.toBinaryString(evt.result);\n\t\t\t\t\t\t\t} catch (e){\n\t\t\t\t\t\t\t\tevt.type = 'error';\n\t\t\t\t\t\t\t\tevt.message = e.toString();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tfn(evt);\n\t\t\t\t\t}, 'DataURL');\n\t\t\t\t}\n\t\t\t},\n\n\n\t\t\t/**\n\t\t\t * Read as ArrayBuffer\n\t\t\t *\n\t\t\t * @param {File} file\n\t\t\t * @param {Function} fn\n\t\t\t */\n\t\t\treadAsArrayBuffer: function(file, fn){\n\t\t\t\t_readAs(file, fn, 'ArrayBuffer');\n\t\t\t},\n\n\n\t\t\t/**\n\t\t\t * Read as text\n\t\t\t *\n\t\t\t * @param {File} file\n\t\t\t * @param {String} encoding\n\t\t\t * @param {Function} [fn]\n\t\t\t */\n\t\t\treadAsText: function(file, encoding, fn){\n\t\t\t\tif( !fn ){\n\t\t\t\t\tfn\t= encoding;\n\t\t\t\t\tencoding = 'utf-8';\n\t\t\t\t}\n\n\t\t\t\t_readAs(file, fn, 'Text', encoding);\n\t\t\t},\n\n\n\t\t\t/**\n\t\t\t * Convert image or canvas to DataURL\n\t\t\t *\n\t\t\t * @param   {Element}  el      Image or Canvas element\n\t\t\t * @param   {String}   [type]  mime-type\n\t\t\t * @return  {String}\n\t\t\t */\n\t\t\ttoDataURL: function (el, type){\n\t\t\t\tif( typeof el == 'string' ){\n\t\t\t\t\treturn  el;\n\t\t\t\t}\n\t\t\t\telse if( el.toDataURL ){\n\t\t\t\t\treturn  el.toDataURL(type || 'image/png');\n\t\t\t\t}\n\t\t\t},\n\n\n\t\t\t/**\n\t\t\t * Canvert string, image or canvas to binary string\n\t\t\t *\n\t\t\t * @param   {String|Element} val\n\t\t\t * @return  {String}\n\t\t\t */\n\t\t\ttoBinaryString: function (val){\n\t\t\t\treturn  window.atob(api.toDataURL(val).replace(_rdata, ''));\n\t\t\t},\n\n\n\t\t\t/**\n\t\t\t * Read file or DataURL as ImageElement\n\t\t\t *\n\t\t\t * @param\t{File|String}\tfile\n\t\t\t * @param\t{Function}\t\tfn\n\t\t\t * @param\t{Boolean}\t\t[progress]\n\t\t\t */\n\t\t\treadAsImage: function (file, fn, progress){\n\t\t\t\tif( api.isFile(file) ){\n\t\t\t\t\tif( apiURL ){\n\t\t\t\t\t\t/** @namespace apiURL.createObjectURL */\n\t\t\t\t\t\tvar data = apiURL.createObjectURL(file);\n\t\t\t\t\t\tif( data === undef ){\n\t\t\t\t\t\t\t_emit(file, fn, 'error');\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse {\n\t\t\t\t\t\t\tapi.readAsImage(data, fn, progress);\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\tapi.readAsDataURL(file, function (evt){\n\t\t\t\t\t\t\tif( evt.type == 'load' ){\n\t\t\t\t\t\t\t\tapi.readAsImage(evt.result, fn, progress);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse if( progress || evt.type == 'error' ){\n\t\t\t\t\t\t\t\t_emit(file, fn, evt, null, { loaded: evt.loaded, total: evt.total });\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\telse if( api.isCanvas(file) ){\n\t\t\t\t\t_emit(file, fn, 'load', file);\n\t\t\t\t}\n\t\t\t\telse if( _rimg.test(file.nodeName) ){\n\t\t\t\t\tif( file.complete ){\n\t\t\t\t\t\t_emit(file, fn, 'load', file);\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\tvar events = 'error abort load';\n\t\t\t\t\t\t_one(file, events, function _fn(evt){\n\t\t\t\t\t\t\tif( evt.type == 'load' && apiURL ){\n\t\t\t\t\t\t\t\t/** @namespace apiURL.revokeObjectURL */\n\t\t\t\t\t\t\t\tapiURL.revokeObjectURL(file.src);\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t_off(file, events, _fn);\n\t\t\t\t\t\t\t_emit(file, fn, evt, file);\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse if( file.iframe ){\n\t\t\t\t\t_emit(file, fn, { type: 'error' });\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\t// Created image\n\t\t\t\t\tvar img = api.newImage(file.dataURL || file);\n\t\t\t\t\tapi.readAsImage(img, fn, progress);\n\t\t\t\t}\n\t\t\t},\n\n\n\t\t\t/**\n\t\t\t * Make file by name\n\t\t\t *\n\t\t\t * @param\t{String}\tname\n\t\t\t * @return\t{Array}\n\t\t\t */\n\t\t\tcheckFileObj: function (name){\n\t\t\t\tvar file = {}, accept = api.accept;\n\n\t\t\t\tif( typeof name == 'object' ){\n\t\t\t\t\tfile = name;\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tfile.name = (name + '').split(/\\\\|\\//g).pop();\n\t\t\t\t}\n\n\t\t\t\tif( file.type == null ){\n\t\t\t\t\tfile.type = file.name.split('.').pop();\n\t\t\t\t}\n\n\t\t\t\t_each(accept, function (ext, type){\n\t\t\t\t\text = new RegExp(ext.replace(/\\s/g, '|'), 'i');\n\t\t\t\t\tif( ext.test(file.type) || api.ext2mime[file.type] ){\n\t\t\t\t\t\tfile.type = api.ext2mime[file.type] || (type.split('/')[0] +'/'+ file.type);\n\t\t\t\t\t}\n\t\t\t\t});\n\n\t\t\t\treturn\tfile;\n\t\t\t},\n\n\n\t\t\t/**\n\t\t\t * Get drop files\n\t\t\t *\n\t\t\t * @param\t{Event}\tevt\n\t\t\t * @param\t{Function} callback\n\t\t\t */\n\t\t\tgetDropFiles: function (evt, callback){\n\t\t\t\tvar\n\t\t\t\t\t  files = []\n\t\t\t\t\t, dataTransfer = _getDataTransfer(evt)\n\t\t\t\t\t, entrySupport = _isArray(dataTransfer.items) && dataTransfer.items[0] && _getAsEntry(dataTransfer.items[0])\n\t\t\t\t\t, queue = api.queue(function (){ callback(files); })\n\t\t\t\t;\n\n\t\t\t\t_each((entrySupport ? dataTransfer.items : dataTransfer.files) || [], function (item){\n\t\t\t\t\tqueue.inc();\n\n\t\t\t\t\ttry {\n\t\t\t\t\t\tif( entrySupport ){\n\t\t\t\t\t\t\t_readEntryAsFiles(item, function (err, entryFiles){\n\t\t\t\t\t\t\t\tif( err ){\n\t\t\t\t\t\t\t\t\tapi.log('[err] getDropFiles:', err);\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tfiles.push.apply(files, entryFiles);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tqueue.next();\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\t_isRegularFile(item, function (yes){\n\t\t\t\t\t\t\t\tyes && files.push(item);\n\t\t\t\t\t\t\t\tqueue.next();\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\tcatch( err ){\n\t\t\t\t\t\tqueue.next();\n\t\t\t\t\t\tapi.log('[err] getDropFiles: ', err);\n\t\t\t\t\t}\n\t\t\t\t});\n\n\t\t\t\tqueue.check();\n\t\t\t},\n\n\n\t\t\t/**\n\t\t\t * Get file list\n\t\t\t *\n\t\t\t * @param\t{HTMLInputElement|Event}\tinput\n\t\t\t * @param\t{String|Function}\t[filter]\n\t\t\t * @param\t{Function}\t\t\t[callback]\n\t\t\t * @return\t{Array|Null}\n\t\t\t */\n\t\t\tgetFiles: function (input, filter, callback){\n\t\t\t\tvar files = [];\n\n\t\t\t\tif( callback ){\n\t\t\t\t\tapi.filterFiles(api.getFiles(input), filter, callback);\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\n\t\t\t\tif( input.jquery ){\n\t\t\t\t\t// jQuery object\n\t\t\t\t\tinput.each(function (){\n\t\t\t\t\t\tfiles = files.concat(api.getFiles(this));\n\t\t\t\t\t});\n\t\t\t\t\tinput\t= files;\n\t\t\t\t\tfiles\t= [];\n\t\t\t\t}\n\n\t\t\t\tif( typeof filter == 'string' ){\n\t\t\t\t\tfilter\t= api.getFilesFilter(filter);\n\t\t\t\t}\n\n\t\t\t\tif( input.originalEvent ){\n\t\t\t\t\t// jQuery event\n\t\t\t\t\tinput = _fixEvent(input.originalEvent);\n\t\t\t\t}\n\t\t\t\telse if( input.srcElement ){\n\t\t\t\t\t// IE Event\n\t\t\t\t\tinput = _fixEvent(input);\n\t\t\t\t}\n\n\n\t\t\t\tif( input.dataTransfer ){\n\t\t\t\t\t// Drag'n'Drop\n\t\t\t\t\tinput = input.dataTransfer;\n\t\t\t\t}\n\t\t\t\telse if( input.target ){\n\t\t\t\t\t// Event\n\t\t\t\t\tinput = input.target;\n\t\t\t\t}\n\n\t\t\t\tif( input.files ){\n\t\t\t\t\t// Input[type=\"file\"]\n\t\t\t\t\tfiles = input.files;\n\n\t\t\t\t\tif( !html5 ){\n\t\t\t\t\t\t// Partial support for file api\n\t\t\t\t\t\tfiles[0].blob\t= input;\n\t\t\t\t\t\tfiles[0].iframe\t= true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse if( !html5 && isInputFile(input) ){\n\t\t\t\t\tif( api.trim(input.value) ){\n\t\t\t\t\t\tfiles = [api.checkFileObj(input.value)];\n\t\t\t\t\t\tfiles[0].blob   = input;\n\t\t\t\t\t\tfiles[0].iframe = true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse if( _isArray(input) ){\n\t\t\t\t\tfiles\t= input;\n\t\t\t\t}\n\n\t\t\t\treturn\tapi.filter(files, function (file){ return !filter || filter.test(file.name); });\n\t\t\t},\n\n\n\t\t\t/**\n\t\t\t * Get total file size\n\t\t\t * @param\t{Array}\tfiles\n\t\t\t * @return\t{Number}\n\t\t\t */\n\t\t\tgetTotalSize: function (files){\n\t\t\t\tvar size = 0, i = files && files.length;\n\t\t\t\twhile( i-- ){\n\t\t\t\t\tsize += files[i].size;\n\t\t\t\t}\n\t\t\t\treturn\tsize;\n\t\t\t},\n\n\n\t\t\t/**\n\t\t\t * Get image information\n\t\t\t *\n\t\t\t * @param\t{File}\t\tfile\n\t\t\t * @param\t{Function}\tfn\n\t\t\t */\n\t\t\tgetInfo: function (file, fn){\n\t\t\t\tvar info = {}, readers = _infoReader.concat();\n\n\t\t\t\tif( api.isFile(file) ){\n\t\t\t\t\t(function _next(){\n\t\t\t\t\t\tvar reader = readers.shift();\n\t\t\t\t\t\tif( reader ){\n\t\t\t\t\t\t\tif( reader.test(file.type) ){\n\t\t\t\t\t\t\t\treader(file, function (err, res){\n\t\t\t\t\t\t\t\t\tif( err ){\n\t\t\t\t\t\t\t\t\t\tfn(err);\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\t_extend(info, res);\n\t\t\t\t\t\t\t\t\t\t_next();\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\telse {\n\t\t\t\t\t\t\t\t_next();\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\tfn(false, info);\n\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\tfn('not_support_info', info);\n\t\t\t\t}\n\t\t\t},\n\n\n\t\t\t/**\n\t\t\t * Add information reader\n\t\t\t *\n\t\t\t * @param {RegExp} mime\n\t\t\t * @param {Function} fn\n\t\t\t */\n\t\t\taddInfoReader: function (mime, fn){\n\t\t\t\tfn.test = function (type){ return mime.test(type); };\n\t\t\t\t_infoReader.push(fn);\n\t\t\t},\n\n\n\t\t\t/**\n\t\t\t * Filter of array\n\t\t\t *\n\t\t\t * @param\t{Array}\t\tinput\n\t\t\t * @param\t{Function}\tfn\n\t\t\t * @return\t{Array}\n\t\t\t */\n\t\t\tfilter: function (input, fn){\n\t\t\t\tvar result = [], i = 0, n = input.length, val;\n\n\t\t\t\tfor( ; i < n; i++ ){\n\t\t\t\t\tif( i in input ){\n\t\t\t\t\t\tval = input[i];\n\t\t\t\t\t\tif( fn.call(val, val, i, input) ){\n\t\t\t\t\t\t\tresult.push(val);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn\tresult;\n\t\t\t},\n\n\n\t\t\t/**\n\t\t\t * Filter files\n\t\t\t *\n\t\t\t * @param\t{Array}\t\tfiles\n\t\t\t * @param\t{Function}\teachFn\n\t\t\t * @param\t{Function}\tresultFn\n\t\t\t */\n\t\t\tfilterFiles: function (files, eachFn, resultFn){\n\t\t\t\tif( files.length ){\n\t\t\t\t\t// HTML5 or Flash\n\t\t\t\t\tvar queue = files.concat(), file, result = [], deleted = [];\n\n\t\t\t\t\t(function _next(){\n\t\t\t\t\t\tif( queue.length ){\n\t\t\t\t\t\t\tfile = queue.shift();\n\t\t\t\t\t\t\tapi.getInfo(file, function (err, info){\n\t\t\t\t\t\t\t\t(eachFn(file, err ? false : info) ? result : deleted).push(file);\n\t\t\t\t\t\t\t\t_next();\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\tresultFn(result, deleted);\n\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\tresultFn([], files);\n\t\t\t\t}\n\t\t\t},\n\n\n\t\t\tupload: function (options){\n\t\t\t\toptions = _extend({\n\t\t\t\t\t  jsonp: 'callback'\n\t\t\t\t\t, prepare: api.F\n\t\t\t\t\t, beforeupload: api.F\n\t\t\t\t\t, upload: api.F\n\t\t\t\t\t, fileupload: api.F\n\t\t\t\t\t, fileprogress: api.F\n\t\t\t\t\t, filecomplete: api.F\n\t\t\t\t\t, progress: api.F\n\t\t\t\t\t, complete: api.F\n\t\t\t\t\t, pause: api.F\n\t\t\t\t\t, imageOriginal: true\n\t\t\t\t\t, chunkSize: api.chunkSize\n\t\t\t\t\t, chunkUploadRetry: api.chunkUploadRetry\n\t\t\t\t\t, uploadRetry: api.uploadRetry\n\t\t\t\t}, options);\n\n\n\t\t\t\tif( options.imageAutoOrientation && !options.imageTransform ){\n\t\t\t\t\toptions.imageTransform = { rotate: 'auto' };\n\t\t\t\t}\n\n\n\t\t\t\tvar\n\t\t\t\t\t  proxyXHR = new api.XHR(options)\n\t\t\t\t\t, dataArray = this._getFilesDataArray(options.files)\n\t\t\t\t\t, _this = this\n\t\t\t\t\t, _total = 0\n\t\t\t\t\t, _loaded = 0\n\t\t\t\t\t, _nextFile\n\t\t\t\t\t, _complete = false\n\t\t\t\t;\n\n\n\t\t\t\t// calc total size\n\t\t\t\t_each(dataArray, function (data){\n\t\t\t\t\t_total += data.size;\n\t\t\t\t});\n\n\t\t\t\t// Array of files\n\t\t\t\tproxyXHR.files = [];\n\t\t\t\t_each(dataArray, function (data){\n\t\t\t\t\tproxyXHR.files.push(data.file);\n\t\t\t\t});\n\n\t\t\t\t// Set upload status props\n\t\t\t\tproxyXHR.total\t= _total;\n\t\t\t\tproxyXHR.loaded\t= 0;\n\t\t\t\tproxyXHR.filesLeft = dataArray.length;\n\n\t\t\t\t// emit \"beforeupload\"  event\n\t\t\t\toptions.beforeupload(proxyXHR, options);\n\n\t\t\t\t// Upload by file\n\t\t\t\t_nextFile = function (){\n\t\t\t\t\tvar\n\t\t\t\t\t\t  data = dataArray.shift()\n\t\t\t\t\t\t, _file = data && data.file\n\t\t\t\t\t\t, _fileLoaded = false\n\t\t\t\t\t\t, _fileOptions = _simpleClone(options)\n\t\t\t\t\t;\n\n\t\t\t\t\tproxyXHR.filesLeft = dataArray.length;\n\n\t\t\t\t\tif( _file && _file.name === api.expando ){\n\t\t\t\t\t\t_file = null;\n\t\t\t\t\t\tapi.log('[warn] FileAPI.upload() — called without files');\n\t\t\t\t\t}\n\n\t\t\t\t\tif( ( proxyXHR.statusText != 'abort' || proxyXHR.current ) && data ){\n\t\t\t\t\t\t// Mark active job\n\t\t\t\t\t\t_complete = false;\n\n\t\t\t\t\t\t// Set current upload file\n\t\t\t\t\t\tproxyXHR.currentFile = _file;\n\n\t\t\t\t\t\t// Prepare file options\n\t\t\t\t\t\tif (_file && options.prepare(_file, _fileOptions) === false) {\n\t\t\t\t\t\t\t_nextFile.call(_this);\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t\t_fileOptions.file = _file;\n\n\t\t\t\t\t\t_this._getFormData(_fileOptions, data, function (form){\n\t\t\t\t\t\t\tif( !_loaded ){\n\t\t\t\t\t\t\t\t// emit \"upload\" event\n\t\t\t\t\t\t\t\toptions.upload(proxyXHR, options);\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tvar xhr = new api.XHR(_extend({}, _fileOptions, {\n\n\t\t\t\t\t\t\t\tupload: _file ? function (){\n\t\t\t\t\t\t\t\t\t// emit \"fileupload\" event\n\t\t\t\t\t\t\t\t\toptions.fileupload(_file, xhr, _fileOptions);\n\t\t\t\t\t\t\t\t} : noop,\n\n\t\t\t\t\t\t\t\tprogress: _file ? function (evt){\n\t\t\t\t\t\t\t\t\tif( !_fileLoaded ){\n\t\t\t\t\t\t\t\t\t\t// For ignore the double calls.\n\t\t\t\t\t\t\t\t\t\t_fileLoaded = (evt.loaded === evt.total);\n\n\t\t\t\t\t\t\t\t\t\t// emit \"fileprogress\" event\n\t\t\t\t\t\t\t\t\t\toptions.fileprogress({\n\t\t\t\t\t\t\t\t\t\t\t  type:   'progress'\n\t\t\t\t\t\t\t\t\t\t\t, total:  data.total = evt.total\n\t\t\t\t\t\t\t\t\t\t\t, loaded: data.loaded = evt.loaded\n\t\t\t\t\t\t\t\t\t\t}, _file, xhr, _fileOptions);\n\n\t\t\t\t\t\t\t\t\t\t// emit \"progress\" event\n\t\t\t\t\t\t\t\t\t\toptions.progress({\n\t\t\t\t\t\t\t\t\t\t\t  type:   'progress'\n\t\t\t\t\t\t\t\t\t\t\t, total:  _total\n\t\t\t\t\t\t\t\t\t\t\t, loaded: proxyXHR.loaded = (_loaded + data.size * (evt.loaded/evt.total))|0\n\t\t\t\t\t\t\t\t\t\t}, _file, xhr, _fileOptions);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t} : noop,\n\n\t\t\t\t\t\t\t\tcomplete: function (err){\n\t\t\t\t\t\t\t\t\t_each(_xhrPropsExport, function (name){\n\t\t\t\t\t\t\t\t\t\tproxyXHR[name] = xhr[name];\n\t\t\t\t\t\t\t\t\t});\n\n\t\t\t\t\t\t\t\t\tif( _file ){\n\t\t\t\t\t\t\t\t\t\tdata.total = (data.total || data.size);\n\t\t\t\t\t\t\t\t\t\tdata.loaded\t= data.total;\n\n\t\t\t\t\t\t\t\t\t\tif( !err ) {\n\t\t\t\t\t\t\t\t\t\t\t// emulate 100% \"progress\"\n\t\t\t\t\t\t\t\t\t\t\tthis.progress(data);\n\n\t\t\t\t\t\t\t\t\t\t\t// fixed throttle event\n\t\t\t\t\t\t\t\t\t\t\t_fileLoaded = true;\n\n\t\t\t\t\t\t\t\t\t\t\t// bytes loaded\n\t\t\t\t\t\t\t\t\t\t\t_loaded += data.size; // data.size != data.total, it's desirable fix this\n\t\t\t\t\t\t\t\t\t\t\tproxyXHR.loaded = _loaded;\n\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t// emit \"filecomplete\" event\n\t\t\t\t\t\t\t\t\t\toptions.filecomplete(err, xhr, _file, _fileOptions);\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t// upload next file\n\t\t\t\t\t\t\t\t\tsetTimeout(function () {_nextFile.call(_this);}, 0);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t})); // xhr\n\n\n\t\t\t\t\t\t\t// ...\n\t\t\t\t\t\t\tproxyXHR.abort = function (current){\n\t\t\t\t\t\t\t\tif (!current) { dataArray.length = 0; }\n\t\t\t\t\t\t\t\tthis.current = current;\n\t\t\t\t\t\t\t\txhr.abort();\n\t\t\t\t\t\t\t};\n\n\t\t\t\t\t\t\t// Start upload\n\t\t\t\t\t\t\txhr.send(form);\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\tvar successful = proxyXHR.status == 200 || proxyXHR.status == 201 || proxyXHR.status == 204;\n\t\t\t\t\t\toptions.complete(successful ? false : (proxyXHR.statusText || 'error'), proxyXHR, options);\n\t\t\t\t\t\t// Mark done state\n\t\t\t\t\t\t_complete = true;\n\t\t\t\t\t}\n\t\t\t\t};\n\n\n\t\t\t\t// Next tick\n\t\t\t\tsetTimeout(_nextFile, 0);\n\n\n\t\t\t\t// Append more files to the existing request\n\t\t\t\t// first - add them to the queue head/tail\n\t\t\t\tproxyXHR.append = function (files, first) {\n\t\t\t\t\tfiles = api._getFilesDataArray([].concat(files));\n\n\t\t\t\t\t_each(files, function (data) {\n\t\t\t\t\t\t_total += data.size;\n\t\t\t\t\t\tproxyXHR.files.push(data.file);\n\t\t\t\t\t\tif (first) {\n\t\t\t\t\t\t\tdataArray.unshift(data);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tdataArray.push(data);\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\n\t\t\t\t\tproxyXHR.statusText = \"\";\n\n\t\t\t\t\tif( _complete ){\n\t\t\t\t\t\t_nextFile.call(_this);\n\t\t\t\t\t}\n\t\t\t\t};\n\n\n\t\t\t\t// Removes file from queue by file reference and returns it\n\t\t\t\tproxyXHR.remove = function (file) {\n\t\t\t\t    var i = dataArray.length, _file;\n\t\t\t\t    while( i-- ){\n\t\t\t\t\t\tif( dataArray[i].file == file ){\n\t\t\t\t\t\t\t_file = dataArray.splice(i, 1);\n\t\t\t\t\t\t\t_total -= _file.size;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\treturn\t_file;\n\t\t\t\t};\n\n\t\t\t\treturn proxyXHR;\n\t\t\t},\n\n\n\t\t\t_getFilesDataArray: function (data){\n\t\t\t\tvar files = [], oFiles = {};\n\n\t\t\t\tif( isInputFile(data) ){\n\t\t\t\t\tvar tmp = api.getFiles(data);\n\t\t\t\t\toFiles[data.name || 'file'] = data.getAttribute('multiple') !== null ? tmp : tmp[0];\n\t\t\t\t}\n\t\t\t\telse if( _isArray(data) && isInputFile(data[0]) ){\n\t\t\t\t\t_each(data, function (input){\n\t\t\t\t\t\toFiles[input.name || 'file'] = api.getFiles(input);\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\toFiles = data;\n\t\t\t\t}\n\n\t\t\t\t_each(oFiles, function add(file, name){\n\t\t\t\t\tif( _isArray(file) ){\n\t\t\t\t\t\t_each(file, function (file){\n\t\t\t\t\t\t\tadd(file, name);\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t\telse if( file && (file.name || file.image) ){\n\t\t\t\t\t\tfiles.push({\n\t\t\t\t\t\t\t  name: name\n\t\t\t\t\t\t\t, file: file\n\t\t\t\t\t\t\t, size: file.size\n\t\t\t\t\t\t\t, total: file.size\n\t\t\t\t\t\t\t, loaded: 0\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t});\n\n\t\t\t\tif( !files.length ){\n\t\t\t\t\t// Create fake `file` object\n\t\t\t\t\tfiles.push({ file: { name: api.expando } });\n\t\t\t\t}\n\n\t\t\t\treturn\tfiles;\n\t\t\t},\n\n\n\t\t\t_getFormData: function (options, data, fn){\n\t\t\t\tvar\n\t\t\t\t\t  file = data.file\n\t\t\t\t\t, name = data.name\n\t\t\t\t\t, filename = file.name\n\t\t\t\t\t, filetype = file.type\n\t\t\t\t\t, trans = api.support.transform && options.imageTransform\n\t\t\t\t\t, Form = new api.Form\n\t\t\t\t\t, queue = api.queue(function (){ fn(Form); })\n\t\t\t\t\t, isOrignTrans = trans && _isOriginTransform(trans)\n\t\t\t\t\t, postNameConcat = api.postNameConcat\n\t\t\t\t;\n\n\t\t\t\t// Append data\n\t\t\t\t_each(options.data, function add(val, name){\n\t\t\t\t\tif( typeof val == 'object' ){\n\t\t\t\t\t\t_each(val, function (v, i){\n\t\t\t\t\t\t\tadd(v, postNameConcat(name, 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\tForm.append(name, val);\n\t\t\t\t\t}\n\t\t\t\t});\n\n\t\t\t\t(function _addFile(file/**Object*/){\n\t\t\t\t\tif( file.image ){ // This is a FileAPI.Image\n\t\t\t\t\t\tqueue.inc();\n\n\t\t\t\t\t\tfile.toData(function (err, image){\n\t\t\t\t\t\t\t// @todo: error\n\t\t\t\t\t\t\tfilename = filename || (new Date).getTime()+'.png';\n\n\t\t\t\t\t\t\t_addFile(image);\n\t\t\t\t\t\t\tqueue.next();\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t\telse if( api.Image && trans && (/^image/.test(file.type) || _rimgcanvas.test(file.nodeName)) ){\n\t\t\t\t\t\tqueue.inc();\n\n\t\t\t\t\t\tif( isOrignTrans ){\n\t\t\t\t\t\t\t// Convert to array for transform function\n\t\t\t\t\t\t\ttrans = [trans];\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tapi.Image.transform(file, trans, options.imageAutoOrientation, function (err, images){\n\t\t\t\t\t\t\tif( isOrignTrans && !err ){\n\t\t\t\t\t\t\t\tif( !dataURLtoBlob && !api.flashEngine ){\n\t\t\t\t\t\t\t\t\t// Canvas.toBlob or Flash not supported, use multipart\n\t\t\t\t\t\t\t\t\tForm.multipart = true;\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\tForm.append(name, images[0], filename,  trans[0].type || filetype);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse {\n\t\t\t\t\t\t\t\tvar addOrigin = 0;\n\n\t\t\t\t\t\t\t\tif( !err ){\n\t\t\t\t\t\t\t\t\t_each(images, function (image, idx){\n\t\t\t\t\t\t\t\t\t\tif( !dataURLtoBlob && !api.flashEngine ){\n\t\t\t\t\t\t\t\t\t\t\tForm.multipart = true;\n\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\tif( !trans[idx].postName ){\n\t\t\t\t\t\t\t\t\t\t\taddOrigin = 1;\n\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\tForm.append(trans[idx].postName || postNameConcat(name, idx), image, filename, trans[idx].type || filetype);\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\tif( err || options.imageOriginal ){\n\t\t\t\t\t\t\t\t\tForm.append(postNameConcat(name, (addOrigin ? 'original' : null)), file, filename, filetype);\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\tqueue.next();\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t\telse if( filename !== api.expando ){\n\t\t\t\t\t\tForm.append(name, file, filename);\n\t\t\t\t\t}\n\t\t\t\t})(file);\n\n\t\t\t\tqueue.check();\n\t\t\t},\n\n\n\t\t\treset: function (inp, notRemove){\n\t\t\t\tvar parent, clone;\n\n\t\t\t\tif( jQuery ){\n\t\t\t\t\tclone = jQuery(inp).clone(true).insertBefore(inp).val('')[0];\n\t\t\t\t\tif( !notRemove ){\n\t\t\t\t\t\tjQuery(inp).remove();\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tparent  = inp.parentNode;\n\t\t\t\t\tclone   = parent.insertBefore(inp.cloneNode(true), inp);\n\t\t\t\t\tclone.value = '';\n\n\t\t\t\t\tif( !notRemove ){\n\t\t\t\t\t\tparent.removeChild(inp);\n\t\t\t\t\t}\n\n\t\t\t\t\t_each(_elEvents[api.uid(inp)], function (fns, type){\n\t\t\t\t\t\t_each(fns, function (fn){\n\t\t\t\t\t\t\t_off(inp, type, fn);\n\t\t\t\t\t\t\t_on(clone, type, fn);\n\t\t\t\t\t\t});\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\treturn  clone;\n\t\t\t},\n\n\n\t\t\t/**\n\t\t\t * Load remote file\n\t\t\t *\n\t\t\t * @param   {String}    url\n\t\t\t * @param   {Function}  fn\n\t\t\t * @return  {XMLHttpRequest}\n\t\t\t */\n\t\t\tload: function (url, fn){\n\t\t\t\tvar xhr = api.getXHR();\n\t\t\t\tif( xhr ){\n\t\t\t\t\txhr.open('GET', url, true);\n\n\t\t\t\t\tif( xhr.overrideMimeType ){\n\t\t\t\t        xhr.overrideMimeType('text/plain; charset=x-user-defined');\n\t\t\t\t\t}\n\n\t\t\t\t\t_on(xhr, 'progress', function (/**Event*/evt){\n\t\t\t\t\t\t/** @namespace evt.lengthComputable */\n\t\t\t\t\t\tif( evt.lengthComputable ){\n\t\t\t\t\t\t\tfn({ type: evt.type, loaded: evt.loaded, total: evt.total }, xhr);\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\n\t\t\t\t\txhr.onreadystatechange = function(){\n\t\t\t\t\t\tif( xhr.readyState == 4 ){\n\t\t\t\t\t\t\txhr.onreadystatechange = null;\n\t\t\t\t\t\t\tif( xhr.status == 200 ){\n\t\t\t\t\t\t\t\turl = url.split('/');\n\t\t\t\t\t\t\t\t/** @namespace xhr.responseBody */\n\t\t\t\t\t\t\t\tvar file = {\n\t\t\t\t\t\t\t\t      name: url[url.length-1]\n\t\t\t\t\t\t\t\t\t, size: xhr.getResponseHeader('Content-Length')\n\t\t\t\t\t\t\t\t\t, type: xhr.getResponseHeader('Content-Type')\n\t\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\t\tfile.dataURL = 'data:'+file.type+';base64,' + api.encode64(xhr.responseBody || xhr.responseText);\n\t\t\t\t\t\t\t\tfn({ type: 'load', result: file }, xhr);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse {\n\t\t\t\t\t\t\t\tfn({ type: 'error' }, xhr);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t    }\n\t\t\t\t\t};\n\t\t\t\t    xhr.send(null);\n\t\t\t\t} else {\n\t\t\t\t\tfn({ type: 'error' });\n\t\t\t\t}\n\n\t\t\t\treturn  xhr;\n\t\t\t},\n\n\t\t\tencode64: function (str){\n\t\t\t\tvar b64 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=', outStr = '', i = 0;\n\n\t\t\t\tif( typeof str !== 'string' ){\n\t\t\t\t\tstr\t= String(str);\n\t\t\t\t}\n\n\t\t\t\twhile( i < str.length ){\n\t\t\t\t\t//all three \"& 0xff\" added below are there to fix a known bug\n\t\t\t\t\t//with bytes returned by xhr.responseText\n\t\t\t\t\tvar\n\t\t\t\t\t\t  byte1 = str.charCodeAt(i++) & 0xff\n\t\t\t\t\t\t, byte2 = str.charCodeAt(i++) & 0xff\n\t\t\t\t\t\t, byte3 = str.charCodeAt(i++) & 0xff\n\t\t\t\t\t\t, enc1 = byte1 >> 2\n\t\t\t\t\t\t, enc2 = ((byte1 & 3) << 4) | (byte2 >> 4)\n\t\t\t\t\t\t, enc3, enc4\n\t\t\t\t\t;\n\n\t\t\t\t\tif( isNaN(byte2) ){\n\t\t\t\t\t\tenc3 = enc4 = 64;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tenc3 = ((byte2 & 15) << 2) | (byte3 >> 6);\n\t\t\t\t\t\tenc4 = isNaN(byte3) ? 64 : byte3 & 63;\n\t\t\t\t\t}\n\n\t\t\t\t\toutStr += b64.charAt(enc1) + b64.charAt(enc2) + b64.charAt(enc3) + b64.charAt(enc4);\n\t\t\t\t}\n\n\t\t\t\treturn  outStr;\n\t\t\t}\n\n\t\t} // api\n\t;\n\n\n\tfunction _emit(target, fn, name, res, ext){\n\t\tvar evt = {\n\t\t\t  type:\t\tname.type || name\n\t\t\t, target:\ttarget\n\t\t\t, result:\tres\n\t\t};\n\t\t_extend(evt, ext);\n\t\tfn(evt);\n\t}\n\n\n\tfunction _hasSupportReadAs(as){\n\t\treturn\tFileReader && !!FileReader.prototype['readAs'+as];\n\t}\n\n\n\tfunction _readAs(file, fn, as, encoding){\n\t\tif( api.isBlob(file) && _hasSupportReadAs(as) ){\n\t\t\tvar Reader = new FileReader;\n\n\t\t\t// Add event listener\n\t\t\t_on(Reader, _readerEvents, function _fn(evt){\n\t\t\t\tvar type = evt.type;\n\t\t\t\tif( type == 'progress' ){\n\t\t\t\t\t_emit(file, fn, evt, evt.target.result, { loaded: evt.loaded, total: evt.total });\n\t\t\t\t}\n\t\t\t\telse if( type == 'loadend' ){\n\t\t\t\t\t_off(Reader, _readerEvents, _fn);\n\t\t\t\t\tReader = null;\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\t_emit(file, fn, evt, evt.target.result);\n\t\t\t\t}\n\t\t\t});\n\n\n\t\t\ttry {\n\t\t\t\t// ReadAs ...\n\t\t\t\tif( encoding ){\n\t\t\t\t\tReader['readAs'+as](file, encoding);\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tReader['readAs'+as](file);\n\t\t\t\t}\n\t\t\t}\n\t\t\tcatch (err){\n\t\t\t\t_emit(file, fn, 'error', undef, { error: err.toString() });\n\t\t\t}\n\t\t}\n\t\telse {\n\t\t\t_emit(file, fn, 'error', undef, { error: 'filreader_not_support_'+as });\n\t\t}\n\t}\n\n\n\tfunction _isRegularFile(file, callback){\n\t\t// http://stackoverflow.com/questions/8856628/detecting-folders-directories-in-javascript-filelist-objects\n\t\tif( !file.type && (file.size % 4096) === 0 && (file.size <= 102400) ){\n\t\t\tif( FileReader ){\n\t\t\t\ttry {\n\t\t\t\t\tvar Reader = new FileReader();\n\n\t\t\t\t\t_one(Reader, _readerEvents, function (evt){\n\t\t\t\t\t\tvar isFile = evt.type != 'error';\n\t\t\t\t\t\tcallback(isFile);\n\t\t\t\t\t\tif( isFile ){\n\t\t\t\t\t\t\tReader.abort();\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\n\t\t\t\t\tReader.readAsDataURL(file);\n\t\t\t\t} catch( err ){\n\t\t\t\t\tcallback(false);\n\t\t\t\t}\n\t\t\t}\n\t\t\telse {\n\t\t\t\tcallback(null);\n\t\t\t}\n\t\t}\n\t\telse {\n\t\t\tcallback(true);\n\t\t}\n\t}\n\n\n\tfunction _getAsEntry(item){\n\t\tvar entry;\n\t\tif( item.getAsEntry ){ entry = item.getAsEntry(); }\n\t\telse if( item.webkitGetAsEntry ){ entry = item.webkitGetAsEntry(); }\n\t\treturn\tentry;\n\t}\n\n\n\tfunction _readEntryAsFiles(entry, callback){\n\t\tif( !entry ){\n\t\t\t// error\n\t\t\tcallback('invalid entry');\n\t\t}\n\t\telse if( entry.isFile ){\n\t\t\t// Read as file\n\t\t\tentry.file(function(file){\n\t\t\t\t// success\n\t\t\t\tfile.fullPath = entry.fullPath;\n\t\t\t\tcallback(false, [file]);\n\t\t\t}, function (err){\n\t\t\t\t// error\n\t\t\t\tcallback('FileError.code: '+err.code);\n\t\t\t});\n\t\t}\n\t\telse if( entry.isDirectory ){\n\t\t\tvar reader = entry.createReader(), result = [];\n\n\t\t\treader.readEntries(function(entries){\n\t\t\t\t// success\n\t\t\t\tapi.afor(entries, function (next, entry){\n\t\t\t\t\t_readEntryAsFiles(entry, function (err, files){\n\t\t\t\t\t\tif( err ){\n\t\t\t\t\t\t\tapi.log(err);\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse {\n\t\t\t\t\t\t\tresult = result.concat(files);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif( next ){\n\t\t\t\t\t\t\tnext();\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse {\n\t\t\t\t\t\t\tcallback(false, result);\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t});\n\t\t\t}, function (err){\n\t\t\t\t// error\n\t\t\t\tcallback('directory_reader: ' + err);\n\t\t\t});\n\t\t}\n\t\telse {\n\t\t\t_readEntryAsFiles(_getAsEntry(entry), callback);\n\t\t}\n\t}\n\n\n\tfunction _simpleClone(obj){\n\t\tvar copy = {};\n\t\t_each(obj, function (val, key){\n\t\t\tif( val && (typeof val === 'object') && (val.nodeType === void 0) ){\n\t\t\t\tval = _extend({}, val);\n\t\t\t}\n\t\t\tcopy[key] = val;\n\t\t});\n\t\treturn\tcopy;\n\t}\n\n\n\tfunction isInputFile(el){\n\t\treturn\t_rinput.test(el && el.tagName);\n\t}\n\n\n\tfunction _getDataTransfer(evt){\n\t\treturn\t(evt.originalEvent || evt || '').dataTransfer || {};\n\t}\n\n\n\tfunction _isOriginTransform(trans){\n\t\tvar key;\n\t\tfor( key in trans ){\n\t\t\tif( trans.hasOwnProperty(key) ){\n\t\t\t\tif( !(trans[key] instanceof Object || key === 'overlay' || key === 'filter') ){\n\t\t\t\t\treturn\ttrue;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn\tfalse;\n\t}\n\n\n\t// Add default image info reader\n\tapi.addInfoReader(/^image/, function (file/**File*/, callback/**Function*/){\n\t\tif( !file.__dimensions ){\n\t\t\tvar defer = file.__dimensions = api.defer();\n\n\t\t\tapi.readAsImage(file, function (evt){\n\t\t\t\tvar img = evt.target;\n\t\t\t\tdefer.resolve(evt.type == 'load' ? false : 'error', {\n\t\t\t\t\t  width:  img.width\n\t\t\t\t\t, height: img.height\n\t\t\t\t});\n                img.src = api.EMPTY_PNG;\n\t\t\t\timg = null;\n\t\t\t});\n\t\t}\n\n\t\tfile.__dimensions.then(callback);\n\t});\n\n\n\t/**\n\t * Drag'n'Drop special event\n\t *\n\t * @param\t{HTMLElement}\tel\n\t * @param\t{Function}\t\tonHover\n\t * @param\t{Function}\t\tonDrop\n\t */\n\tapi.event.dnd = function (el, onHover, onDrop){\n\t\tvar _id, _type;\n\n\t\tif( !onDrop ){\n\t\t\tonDrop = onHover;\n\t\t\tonHover = api.F;\n\t\t}\n\n\t\tif( FileReader ){\n\t\t\t// Hover\n\t\t\t_on(el, 'dragenter dragleave dragover', onHover.ff = onHover.ff || function (evt){\n\t\t\t\tvar\n\t\t\t\t\t  types = _getDataTransfer(evt).types\n\t\t\t\t\t, i = types && types.length\n\t\t\t\t\t, debounceTrigger = false\n\t\t\t\t;\n\n\t\t\t\twhile( i-- ){\n\t\t\t\t\tif( ~types[i].indexOf('File') ){\n\t\t\t\t\t\tevt[preventDefault]();\n\n\t\t\t\t\t\tif( _type !== evt.type ){\n\t\t\t\t\t\t\t_type = evt.type; // Store current type of event\n\n\t\t\t\t\t\t\tif( _type != 'dragleave' ){\n\t\t\t\t\t\t\t\tonHover.call(evt[currentTarget], true, evt);\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tdebounceTrigger = true;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tbreak; // exit from \"while\"\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif( debounceTrigger ){\n\t\t\t\t\tclearTimeout(_id);\n\t\t\t\t\t_id = setTimeout(function (){\n\t\t\t\t\t\tonHover.call(evt[currentTarget], _type != 'dragleave', evt);\n\t\t\t\t\t}, 50);\n\t\t\t\t}\n\t\t\t});\n\n\n\t\t\t// Drop\n\t\t\t_on(el, 'drop', onDrop.ff = onDrop.ff || function (evt){\n\t\t\t\tevt[preventDefault]();\n\n\t\t\t\t_type = 0;\n\t\t\t\tonHover.call(evt[currentTarget], false, evt);\n\n\t\t\t\tapi.getDropFiles(evt, function (files){\n\t\t\t\t\tonDrop.call(evt[currentTarget], files, evt);\n\t\t\t\t});\n\t\t\t});\n\t\t}\n\t\telse {\n\t\t\tapi.log(\"Drag'n'Drop -- not supported\");\n\t\t}\n\t};\n\n\n\t/**\n\t * Remove drag'n'drop\n\t * @param\t{HTMLElement}\tel\n\t * @param\t{Function}\t\tonHover\n\t * @param\t{Function}\t\tonDrop\n\t */\n\tapi.event.dnd.off = function (el, onHover, onDrop){\n\t\t_off(el, 'dragenter dragleave dragover', onHover.ff);\n\t\t_off(el, 'drop', onDrop.ff);\n\t};\n\n\n\t// Support jQuery\n\tif( jQuery && !jQuery.fn.dnd ){\n\t\tjQuery.fn.dnd = function (onHover, onDrop){\n\t\t\treturn this.each(function (){\n\t\t\t\tapi.event.dnd(this, onHover, onDrop);\n\t\t\t});\n\t\t};\n\n\t\tjQuery.fn.offdnd = function (onHover, onDrop){\n\t\t\treturn this.each(function (){\n\t\t\t\tapi.event.dnd.off(this, onHover, onDrop);\n\t\t\t});\n\t\t};\n\t}\n\n\t// @export\n\twindow.FileAPI  = _extend(api, window.FileAPI);\n\n\n\t// Debug info\n\tapi.log('FileAPI: ' + api.version);\n\tapi.log('protocol: ' + window.location.protocol);\n\tapi.log('doctype: [' + doctype.name + '] ' + doctype.publicId + ' ' + doctype.systemId);\n\n\n\t// @detect 'x-ua-compatible'\n\t_each(document.getElementsByTagName('meta'), function (meta){\n\t\tif( /x-ua-compatible/i.test(meta.getAttribute('http-equiv')) ){\n\t\t\tapi.log('meta.http-equiv: ' + meta.getAttribute('content'));\n\t\t}\n\t});\n\n\n\t// @configuration\n\tif( !api.flashUrl ){ api.flashUrl = api.staticPath + 'FileAPI.flash.swf'; }\n\tif( !api.flashImageUrl ){ api.flashImageUrl = api.staticPath + 'FileAPI.flash.image.swf'; }\n\tif( !api.flashWebcamUrl ){ api.flashWebcamUrl = api.staticPath + 'FileAPI.flash.camera.swf'; }\n})(window, void 0);\n\n/*global window, FileAPI, document */\n\n(function (api, document, undef) {\n\t'use strict';\n\n\tvar\n\t\tmin = Math.min,\n\t\tround = Math.round,\n\t\tgetCanvas = function () { return document.createElement('canvas'); },\n\t\tsupport = false,\n\t\texifOrientation = {\n\t\t\t  8:\t270\n\t\t\t, 3:\t180\n\t\t\t, 6:\t90\n\t\t\t, 7:\t270\n\t\t\t, 4:\t180\n\t\t\t, 5:\t90\n\t\t}\n\t;\n\n\ttry {\n\t\tsupport = getCanvas().toDataURL('image/png').indexOf('data:image/png') > -1;\n\t}\n\tcatch (e){}\n\n\n\tfunction Image(file){\n\t\tif( file instanceof Image ){\n\t\t\tvar img = new Image(file.file);\n\t\t\tapi.extend(img.matrix, file.matrix);\n\t\t\treturn\timg;\n\t\t}\n\t\telse if( !(this instanceof Image) ){\n\t\t\treturn\tnew Image(file);\n\t\t}\n\n\t\tthis.file   = file;\n\t\tthis.size   = file.size || 100;\n\n\t\tthis.matrix\t= {\n\t\t\tsx: 0,\n\t\t\tsy: 0,\n\t\t\tsw: 0,\n\t\t\tsh: 0,\n\t\t\tdx: 0,\n\t\t\tdy: 0,\n\t\t\tdw: 0,\n\t\t\tdh: 0,\n\t\t\tresize: 0, // min, max OR preview\n\t\t\tdeg: 0,\n\t\t\tquality: 1, // jpeg quality\n\t\t\tfilter: 0\n\t\t};\n\t}\n\n\n\tImage.prototype = {\n\t\timage: true,\n\t\tconstructor: Image,\n\n\t\tset: function (attrs){\n\t\t\tapi.extend(this.matrix, attrs);\n\t\t\treturn\tthis;\n\t\t},\n\n\t\tcrop: function (x, y, w, h){\n\t\t\tif( w === undef ){\n\t\t\t\tw\t= x;\n\t\t\t\th\t= y;\n\t\t\t\tx = y = 0;\n\t\t\t}\n\t\t\treturn\tthis.set({ sx: x, sy: y, sw: w, sh: h || w });\n\t\t},\n\n\t\tresize: function (w, h, strategy){\n\t\t\tif( /min|max/.test(h) ){\n\t\t\t\tstrategy = h;\n\t\t\t\th = w;\n\t\t\t}\n\n\t\t\treturn\tthis.set({ dw: w, dh: h || w, resize: strategy });\n\t\t},\n\n\t\tpreview: function (w, h){\n\t\t\treturn\tthis.resize(w, h || w, 'preview');\n\t\t},\n\n\t\trotate: function (deg){\n\t\t\treturn\tthis.set({ deg: deg });\n\t\t},\n\n\t\tfilter: function (filter){\n\t\t\treturn\tthis.set({ filter: filter });\n\t\t},\n\n\t\toverlay: function (images){\n\t\t\treturn\tthis.set({ overlay: images });\n\t\t},\n\n\t\tclone: function (){\n\t\t\treturn\tnew Image(this);\n\t\t},\n\n\t\t_load: function (image, fn){\n\t\t\tvar self = this;\n\n\t\t\tif( /img|video/i.test(image.nodeName) ){\n\t\t\t\tfn.call(self, null, image);\n\t\t\t}\n\t\t\telse {\n\t\t\t\tapi.readAsImage(image, function (evt){\n\t\t\t\t\tfn.call(self, evt.type != 'load', evt.result);\n\t\t\t\t});\n\t\t\t}\n\t\t},\n\n\t\t_apply: function (image, fn){\n\t\t\tvar\n\t\t\t\t  canvas = getCanvas()\n\t\t\t\t, m = this.getMatrix(image)\n\t\t\t\t, ctx = canvas.getContext('2d')\n\t\t\t\t, width = image.videoWidth || image.width\n\t\t\t\t, height = image.videoHeight || image.height\n\t\t\t\t, deg = m.deg\n\t\t\t\t, dw = m.dw\n\t\t\t\t, dh = m.dh\n\t\t\t\t, w = width\n\t\t\t\t, h = height\n\t\t\t\t, filter = m.filter\n\t\t\t\t, copy // canvas copy\n\t\t\t\t, buffer = image\n\t\t\t\t, overlay = m.overlay\n\t\t\t\t, queue = api.queue(function (){ image.src = api.EMPTY_PNG; fn(false, canvas); })\n\t\t\t\t, renderImageToCanvas = api.renderImageToCanvas\n\t\t\t;\n\n\t\t\t// Normalize angle\n\t\t\tdeg = deg - Math.floor(deg/360)*360;\n\n\t\t\t// For `renderImageToCanvas`\n\t\t\timage._type = this.file.type;\n\n\t\t\twhile(m.multipass && min(w/dw, h/dh) > 2 ){\n\t\t\t\tw = (w/2 + 0.5)|0;\n\t\t\t\th = (h/2 + 0.5)|0;\n\n\t\t\t\tcopy = getCanvas();\n\t\t\t\tcopy.width  = w;\n\t\t\t\tcopy.height = h;\n\n\t\t\t\tif( buffer !== image ){\n\t\t\t\t\trenderImageToCanvas(copy, buffer, 0, 0, buffer.width, buffer.height, 0, 0, w, h);\n\t\t\t\t\tbuffer = copy;\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tbuffer = copy;\n\t\t\t\t\trenderImageToCanvas(buffer, image, m.sx, m.sy, m.sw, m.sh, 0, 0, w, h);\n\t\t\t\t\tm.sx = m.sy = m.sw = m.sh = 0;\n\t\t\t\t}\n\t\t\t}\n\n\n\t\t\tcanvas.width  = (deg % 180) ? dh : dw;\n\t\t\tcanvas.height = (deg % 180) ? dw : dh;\n\n\t\t\tcanvas.type = m.type;\n\t\t\tcanvas.quality = m.quality;\n\n\t\t\tctx.rotate(deg * Math.PI / 180);\n\t\t\trenderImageToCanvas(ctx.canvas, buffer\n\t\t\t\t, m.sx, m.sy\n\t\t\t\t, m.sw || buffer.width\n\t\t\t\t, m.sh || buffer.height\n\t\t\t\t, (deg == 180 || deg == 270 ? -dw : 0)\n\t\t\t\t, (deg == 90 || deg == 180 ? -dh : 0)\n\t\t\t\t, dw, dh\n\t\t\t);\n\t\t\tdw = canvas.width;\n\t\t\tdh = canvas.height;\n\n\t\t\t// Apply overlay\n\t\t\toverlay && api.each([].concat(overlay), function (over){\n\t\t\t\tqueue.inc();\n\t\t\t\t// preload\n\t\t\t\tvar img = new window.Image, fn = function (){\n\t\t\t\t\tvar\n\t\t\t\t\t\t  x = over.x|0\n\t\t\t\t\t\t, y = over.y|0\n\t\t\t\t\t\t, w = over.w || img.width\n\t\t\t\t\t\t, h = over.h || img.height\n\t\t\t\t\t\t, rel = over.rel\n\t\t\t\t\t;\n\n\t\t\t\t\t// center  |  right  |  left\n\t\t\t\t\tx = (rel == 1 || rel == 4 || rel == 7) ? (dw - w + x)/2 : (rel == 2 || rel == 5 || rel == 8 ? dw - (w + x) : x);\n\n\t\t\t\t\t// center  |  bottom  |  top\n\t\t\t\t\ty = (rel == 3 || rel == 4 || rel == 5) ? (dh - h + y)/2 : (rel >= 6 ? dh - (h + y) : y);\n\n\t\t\t\t\tapi.event.off(img, 'error load abort', fn);\n\n\t\t\t\t\ttry {\n\t\t\t\t\t\tctx.globalAlpha = over.opacity || 1;\n\t\t\t\t\t\tctx.drawImage(img, x, y, w, h);\n\t\t\t\t\t}\n\t\t\t\t\tcatch (er){}\n\n\t\t\t\t\tqueue.next();\n\t\t\t\t};\n\n\t\t\t\tapi.event.on(img, 'error load abort', fn);\n\t\t\t\timg.src = over.src;\n\n\t\t\t\tif( img.complete ){\n\t\t\t\t\tfn();\n\t\t\t\t}\n\t\t\t});\n\n\t\t\tif( filter ){\n\t\t\t\tqueue.inc();\n\t\t\t\tImage.applyFilter(canvas, filter, queue.next);\n\t\t\t}\n\n\t\t\tqueue.check();\n\t\t},\n\n\t\tgetMatrix: function (image){\n\t\t\tvar\n\t\t\t\t  m  = api.extend({}, this.matrix)\n\t\t\t\t, sw = m.sw = m.sw || image.videoWidth || image.naturalWidth ||  image.width\n\t\t\t\t, sh = m.sh = m.sh || image.videoHeight || image.naturalHeight || image.height\n\t\t\t\t, dw = m.dw = m.dw || sw\n\t\t\t\t, dh = m.dh = m.dh || sh\n\t\t\t\t, sf = sw/sh, df = dw/dh\n\t\t\t\t, strategy = m.resize\n\t\t\t;\n\n\t\t\tif( strategy == 'preview' ){\n\t\t\t\tif( dw != sw || dh != sh ){\n\t\t\t\t\t// Make preview\n\t\t\t\t\tvar w, h;\n\n\t\t\t\t\tif( df >= sf ){\n\t\t\t\t\t\tw\t= sw;\n\t\t\t\t\t\th\t= w / df;\n\t\t\t\t\t} else {\n\t\t\t\t\t\th\t= sh;\n\t\t\t\t\t\tw\t= h * df;\n\t\t\t\t\t}\n\n\t\t\t\t\tif( w != sw || h != sh ){\n\t\t\t\t\t\tm.sx\t= ~~((sw - w)/2);\n\t\t\t\t\t\tm.sy\t= ~~((sh - h)/2);\n\t\t\t\t\t\tsw\t\t= w;\n\t\t\t\t\t\tsh\t\t= h;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\telse if( strategy ){\n\t\t\t\tif( !(sw > dw || sh > dh) ){\n\t\t\t\t\tdw = sw;\n\t\t\t\t\tdh = sh;\n\t\t\t\t}\n\t\t\t\telse if( strategy == 'min' ){\n\t\t\t\t\tdw = round(sf < df ? min(sw, dw) : dh*sf);\n\t\t\t\t\tdh = round(sf < df ? dw/sf : min(sh, dh));\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tdw = round(sf >= df ? min(sw, dw) : dh*sf);\n\t\t\t\t\tdh = round(sf >= df ? dw/sf : min(sh, dh));\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tm.sw = sw;\n\t\t\tm.sh = sh;\n\t\t\tm.dw = dw;\n\t\t\tm.dh = dh;\n\t\t\tm.multipass = api.multiPassResize;\n\t\t\treturn\tm;\n\t\t},\n\n\t\t_trans: function (fn){\n\t\t\tthis._load(this.file, function (err, image){\n\t\t\t\tif( err ){\n\t\t\t\t\tfn(err);\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tthis._apply(image, fn);\n\t\t\t\t\t} catch (err){\n\t\t\t\t\t\tapi.log('[err] FileAPI.Image.fn._apply:', err);\n\t\t\t\t\t\tfn(err);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t},\n\n\n\t\tget: function (fn){\n\t\t\tif( api.support.transform ){\n\t\t\t\tvar _this = this, matrix = _this.matrix;\n\n\t\t\t\tif( matrix.deg == 'auto' ){\n\t\t\t\t\tapi.getInfo(_this.file, function (err, info){\n\t\t\t\t\t\t// rotate by exif orientation\n\t\t\t\t\t\tmatrix.deg = exifOrientation[info && info.exif && info.exif.Orientation] || 0;\n\t\t\t\t\t\t_this._trans(fn);\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\t_this._trans(fn);\n\t\t\t\t}\n\t\t\t}\n\t\t\telse {\n\t\t\t\tfn('not_support_transform');\n\t\t\t}\n\n\t\t\treturn this;\n\t\t},\n\n\n\t\ttoData: function (fn){\n\t\t\treturn this.get(fn);\n\t\t}\n\n\t};\n\n\n\tImage.exifOrientation = exifOrientation;\n\n\n\tImage.transform = function (file, transform, autoOrientation, fn){\n\t\tfunction _transform(err, img){\n\t\t\t// img -- info object\n\t\t\tvar\n\t\t\t\t  images = {}\n\t\t\t\t, queue = api.queue(function (err){\n\t\t\t\t\tfn(err, images);\n\t\t\t\t})\n\t\t\t;\n\n\t\t\tif( !err ){\n\t\t\t\tapi.each(transform, function (params, name){\n\t\t\t\t\tif( !queue.isFail() ){\n\t\t\t\t\t\tvar ImgTrans = new Image(img.nodeType ? img : file), isFn = typeof params == 'function';\n\n\t\t\t\t\t\tif( isFn ){\n\t\t\t\t\t\t\tparams(img, ImgTrans);\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse if( params.width ){\n\t\t\t\t\t\t\tImgTrans[params.preview ? 'preview' : 'resize'](params.width, params.height, params.strategy);\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse {\n\t\t\t\t\t\t\tif( params.maxWidth && (img.width > params.maxWidth || img.height > params.maxHeight) ){\n\t\t\t\t\t\t\t\tImgTrans.resize(params.maxWidth, params.maxHeight, 'max');\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif( params.crop ){\n\t\t\t\t\t\t\tvar crop = params.crop;\n\t\t\t\t\t\t\tImgTrans.crop(crop.x|0, crop.y|0, crop.w || crop.width, crop.h || crop.height);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif( params.rotate === undef && autoOrientation ){\n\t\t\t\t\t\t\tparams.rotate = 'auto';\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tImgTrans.set({ type: ImgTrans.matrix.type || params.type || file.type || 'image/png' });\n\n\t\t\t\t\t\tif( !isFn ){\n\t\t\t\t\t\t\tImgTrans.set({\n\t\t\t\t\t\t\t\t  deg: params.rotate\n\t\t\t\t\t\t\t\t, overlay: params.overlay\n\t\t\t\t\t\t\t\t, filter: params.filter\n\t\t\t\t\t\t\t\t, quality: params.quality || 1\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tqueue.inc();\n\t\t\t\t\t\tImgTrans.toData(function (err, image){\n\t\t\t\t\t\t\tif( err ){\n\t\t\t\t\t\t\t\tqueue.fail();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse {\n\t\t\t\t\t\t\t\timages[name] = image;\n\t\t\t\t\t\t\t\tqueue.next();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t\telse {\n\t\t\t\tqueue.fail();\n\t\t\t}\n\t\t}\n\n\n\t\t// @todo: Оло-ло, нужно рефакторить это место\n\t\tif( file.width ){\n\t\t\t_transform(false, file);\n\t\t} else {\n\t\t\tapi.getInfo(file, _transform);\n\t\t}\n\t};\n\n\n\t// @const\n\tapi.each(['TOP', 'CENTER', 'BOTTOM'], function (x, i){\n\t\tapi.each(['LEFT', 'CENTER', 'RIGHT'], function (y, j){\n\t\t\tImage[x+'_'+y] = i*3 + j;\n\t\t\tImage[y+'_'+x] = i*3 + j;\n\t\t});\n\t});\n\n\n\t/**\n\t * Trabsform element to canvas\n\t *\n\t * @param    {Image|HTMLVideoElement}   el\n\t * @returns  {Canvas}\n\t */\n\tImage.toCanvas = function(el){\n\t\tvar canvas\t\t= document.createElement('canvas');\n\t\tcanvas.width\t= el.videoWidth || el.width;\n\t\tcanvas.height\t= el.videoHeight || el.height;\n\t\tcanvas.getContext('2d').drawImage(el, 0, 0);\n\t\treturn\tcanvas;\n\t};\n\n\n\t/**\n\t * Create image from DataURL\n\t * @param  {String}  dataURL\n\t * @param  {Object}  size\n\t * @param  {Function}  callback\n\t */\n\tImage.fromDataURL = function (dataURL, size, callback){\n\t\tvar img = api.newImage(dataURL);\n\t\tapi.extend(img, size);\n\t\tcallback(img);\n\t};\n\n\n\t/**\n\t * Apply filter (caman.js)\n\t *\n\t * @param  {Canvas|Image}   canvas\n\t * @param  {String|Function}  filter\n\t * @param  {Function}  doneFn\n\t */\n\tImage.applyFilter = function (canvas, filter, doneFn){\n\t\tif( typeof filter == 'function' ){\n\t\t\tfilter(canvas, doneFn);\n\t\t}\n\t\telse if( window.Caman ){\n\t\t\t// http://camanjs.com/guides/\n\t\t\twindow.Caman(canvas.tagName == 'IMG' ? Image.toCanvas(canvas) : canvas, function (){\n\t\t\t\tif( typeof filter == 'string' ){\n\t\t\t\t\tthis[filter]();\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tapi.each(filter, function (val, method){\n\t\t\t\t\t\tthis[method](val);\n\t\t\t\t\t}, this);\n\t\t\t\t}\n\t\t\t\tthis.render(doneFn);\n\t\t\t});\n\t\t}\n\t};\n\n\n\t/**\n\t * For load-image-ios.js\n\t */\n\tapi.renderImageToCanvas = function (canvas, img, sx, sy, sw, sh, dx, dy, dw, dh){\n\t\ttry {\n\t\t\treturn canvas.getContext('2d').drawImage(img, sx, sy, sw, sh, dx, dy, dw, dh);\n\t\t} catch (ex) {\n\t\t\tapi.log('renderImageToCanvas failed');\n\t\t\tthrow ex;\n\t\t}\n\t};\n\n\n\t// @export\n\tapi.support.canvas = api.support.transform = support;\n\tapi.Image = Image;\n})(FileAPI, document);\n\n/*\n * JavaScript Load Image iOS scaling fixes 1.0.3\n * https://github.com/blueimp/JavaScript-Load-Image\n *\n * Copyright 2013, Sebastian Tschan\n * https://blueimp.net\n *\n * iOS image scaling fixes based on\n * https://github.com/stomita/ios-imagefile-megapixel\n *\n * Licensed under the MIT license:\n * http://www.opensource.org/licenses/MIT\n */\n\n/*jslint nomen: true, bitwise: true */\n/*global FileAPI, window, document */\n\n(function (factory) {\n\t'use strict';\n\tfactory(FileAPI);\n}(function (loadImage) {\n    'use strict';\n\n    // Only apply fixes on the iOS platform:\n    if (!window.navigator || !window.navigator.platform ||\n             !(/iP(hone|od|ad)/).test(window.navigator.platform)) {\n        return;\n    }\n\n    var originalRenderMethod = loadImage.renderImageToCanvas;\n\n    // Detects subsampling in JPEG images:\n    loadImage.detectSubsampling = function (img) {\n        var canvas,\n            context;\n        if (img.width * img.height > 1024 * 1024) { // only consider mexapixel images\n            canvas = document.createElement('canvas');\n            canvas.width = canvas.height = 1;\n            context = canvas.getContext('2d');\n            context.drawImage(img, -img.width + 1, 0);\n            // subsampled image becomes half smaller in rendering size.\n            // check alpha channel value to confirm image is covering edge pixel or not.\n            // if alpha value is 0 image is not covering, hence subsampled.\n            return context.getImageData(0, 0, 1, 1).data[3] === 0;\n        }\n        return false;\n    };\n\n    // Detects vertical squash in JPEG images:\n    loadImage.detectVerticalSquash = function (img, subsampled) {\n        var naturalHeight = img.naturalHeight || img.height,\n            canvas = document.createElement('canvas'),\n            context = canvas.getContext('2d'),\n            data,\n            sy,\n            ey,\n            py,\n            alpha;\n        if (subsampled) {\n            naturalHeight /= 2;\n        }\n        canvas.width = 1;\n        canvas.height = naturalHeight;\n        context.drawImage(img, 0, 0);\n        data = context.getImageData(0, 0, 1, naturalHeight).data;\n        // search image edge pixel position in case it is squashed vertically:\n        sy = 0;\n        ey = naturalHeight;\n        py = naturalHeight;\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        return (py / naturalHeight) || 1;\n    };\n\n    // Renders image to canvas while working around iOS image scaling bugs:\n    // https://github.com/blueimp/JavaScript-Load-Image/issues/13\n    loadImage.renderImageToCanvas = function (\n        canvas,\n        img,\n        sourceX,\n        sourceY,\n        sourceWidth,\n        sourceHeight,\n        destX,\n        destY,\n        destWidth,\n        destHeight\n    ) {\n        if (img._type === 'image/jpeg') {\n            var context = canvas.getContext('2d'),\n                tmpCanvas = document.createElement('canvas'),\n                tileSize = 1024,\n                tmpContext = tmpCanvas.getContext('2d'),\n                subsampled,\n                vertSquashRatio,\n                tileX,\n                tileY;\n            tmpCanvas.width = tileSize;\n            tmpCanvas.height = tileSize;\n            context.save();\n            subsampled = loadImage.detectSubsampling(img);\n            if (subsampled) {\n                sourceX /= 2;\n                sourceY /= 2;\n                sourceWidth /= 2;\n                sourceHeight /= 2;\n            }\n            vertSquashRatio = loadImage.detectVerticalSquash(img, subsampled);\n            if (subsampled || vertSquashRatio !== 1) {\n                sourceY *= vertSquashRatio;\n                destWidth = Math.ceil(tileSize * destWidth / sourceWidth);\n                destHeight = Math.ceil(\n                    tileSize * destHeight / sourceHeight / vertSquashRatio\n                );\n                destY = 0;\n                tileY = 0;\n                while (tileY < sourceHeight) {\n                    destX = 0;\n                    tileX = 0;\n                    while (tileX < sourceWidth) {\n                        tmpContext.clearRect(0, 0, tileSize, tileSize);\n                        tmpContext.drawImage(\n                            img,\n                            sourceX,\n                            sourceY,\n                            sourceWidth,\n                            sourceHeight,\n                            -tileX,\n                            -tileY,\n                            sourceWidth,\n                            sourceHeight\n                        );\n                        context.drawImage(\n                            tmpCanvas,\n                            0,\n                            0,\n                            tileSize,\n                            tileSize,\n                            destX,\n                            destY,\n                            destWidth,\n                            destHeight\n                        );\n                        tileX += tileSize;\n                        destX += destWidth;\n                    }\n                    tileY += tileSize;\n                    destY += destHeight;\n                }\n                context.restore();\n                return canvas;\n            }\n        }\n        return originalRenderMethod(\n            canvas,\n            img,\n            sourceX,\n            sourceY,\n            sourceWidth,\n            sourceHeight,\n            destX,\n            destY,\n            destWidth,\n            destHeight\n        );\n    };\n\n}));\n\n/*global window, FileAPI */\n\n(function (api, window){\n\t\"use strict\";\n\n\tvar\n\t\t  document = window.document\n\t\t, FormData = window.FormData\n\t\t, Form = function (){ this.items = []; }\n\t\t, encodeURIComponent = window.encodeURIComponent\n\t;\n\n\n\tForm.prototype = {\n\n\t\tappend: function (name, blob, file, type){\n\t\t\tthis.items.push({\n\t\t\t\t  name: name\n\t\t\t\t, blob: blob && blob.blob || (blob == void 0 ? '' : blob)\n\t\t\t\t, file: blob && (file || blob.name)\n\t\t\t\t, type:\tblob && (type || blob.type)\n\t\t\t});\n\t\t},\n\n\t\teach: function (fn){\n\t\t\tvar i = 0, n = this.items.length;\n\t\t\tfor( ; i < n; i++ ){\n\t\t\t\tfn.call(this, this.items[i]);\n\t\t\t}\n\t\t},\n\n\t\ttoData: function (fn, options){\n\t\t    // allow chunked transfer if we have only one file to send\n\t\t    // flag is used below and in XHR._send\n\t\t    options._chunked = api.support.chunked && options.chunkSize > 0 && api.filter(this.items, function (item){ return item.file; }).length == 1;\n\n\t\t\tif( !api.support.html5 ){\n\t\t\t\tapi.log('FileAPI.Form.toHtmlData');\n\t\t\t\tthis.toHtmlData(fn);\n\t\t\t}\n\t\t\telse if( !api.formData || this.multipart || !FormData ){\n\t\t\t\tapi.log('FileAPI.Form.toMultipartData');\n\t\t\t\tthis.toMultipartData(fn);\n\t\t\t}\n\t\t\telse if( options._chunked ){\n\t\t\t\tapi.log('FileAPI.Form.toPlainData');\n\t\t\t\tthis.toPlainData(fn);\n\t\t\t}\n\t\t\telse {\n\t\t\t\tapi.log('FileAPI.Form.toFormData');\n\t\t\t\tthis.toFormData(fn);\n\t\t\t}\n\t\t},\n\n\t\t_to: function (data, complete, next, arg){\n\t\t\tvar queue = api.queue(function (){\n\t\t\t\tcomplete(data);\n\t\t\t});\n\n\t\t\tthis.each(function (file){\n\t\t\t\tnext(file, data, queue, arg);\n\t\t\t});\n\n\t\t\tqueue.check();\n\t\t},\n\n\n\t\ttoHtmlData: function (fn){\n\t\t\tthis._to(document.createDocumentFragment(), fn, function (file, data/**DocumentFragment*/){\n\t\t\t\tvar blob = file.blob, hidden;\n\n\t\t\t\tif( file.file ){\n\t\t\t\t\tapi.reset(blob, true);\n\t\t\t\t\t// set new name\n\t\t\t\t\tblob.name = file.name;\n\t\t\t\t\tblob.disabled = false;\n\t\t\t\t\tdata.appendChild(blob);\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\thidden = document.createElement('input');\n\t\t\t\t\thidden.name  = file.name;\n\t\t\t\t\thidden.type  = 'hidden';\n\t\t\t\t\thidden.value = blob;\n\t\t\t\t\tdata.appendChild(hidden);\n\t\t\t\t}\n\t\t\t});\n\t\t},\n\n\t\ttoPlainData: function (fn){\n\t\t\tthis._to({}, fn, function (file, data, queue){\n\t\t\t\tif( file.file ){\n\t\t\t\t\tdata.type = file.file;\n\t\t\t\t}\n\n\t\t\t\tif( file.blob.toBlob ){\n\t\t\t\t    // canvas\n\t\t\t\t\tqueue.inc();\n\t\t\t\t\t_convertFile(file, function (file, blob){\n\t\t\t\t\t\tdata.name = file.name;\n\t\t\t\t\t\tdata.file = blob;\n\t\t\t\t\t\tdata.size = blob.length;\n\t\t\t\t\t\tdata.type = file.type;\n\t\t\t\t\t\tqueue.next();\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\telse if( file.file ){\n\t\t\t\t    // file\n\t\t\t\t\tdata.name = file.blob.name;\n\t\t\t\t\tdata.file = file.blob;\n\t\t\t\t\tdata.size = file.blob.size;\n\t\t\t\t\tdata.type = file.type;\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t    // additional data\n\t\t\t\t    if( !data.params ){\n\t\t\t\t        data.params = [];\n\t\t\t\t    }\n\t\t\t\t    data.params.push(encodeURIComponent(file.name) +\"=\"+ encodeURIComponent(file.blob));\n\t\t\t\t}\n\n\t\t\t\tdata.start = -1;\n\t\t\t\tdata.end = data.file && data.file.FileAPIReadPosition || -1;\n\t\t\t\tdata.retry = 0;\n\t\t\t});\n\t\t},\n\n\t\ttoFormData: function (fn){\n\t\t\tthis._to(new FormData, fn, function (file, data, queue){\n\t\t\t\tif( file.blob && file.blob.toBlob ){\n\t\t\t\t\tqueue.inc();\n\t\t\t\t\t_convertFile(file, function (file, blob){\n\t\t\t\t\t\tdata.append(file.name, blob, file.file);\n\t\t\t\t\t\tqueue.next();\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\telse if( file.file ){\n\t\t\t\t\tdata.append(file.name, file.blob, file.file);\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tdata.append(file.name, file.blob);\n\t\t\t\t}\n\n\t\t\t\tif( file.file ){\n\t\t\t\t\tdata.append('_'+file.name, file.file);\n\t\t\t\t}\n\t\t\t});\n\t\t},\n\n\n\t\ttoMultipartData: function (fn){\n\t\t\tthis._to([], fn, function (file, data, queue, boundary){\n\t\t\t\tqueue.inc();\n\t\t\t\t_convertFile(file, function (file, blob){\n\t\t\t\t\tdata.push(\n\t\t\t\t\t\t  '--_' + boundary + ('\\r\\nContent-Disposition: form-data; name=\"'+ file.name +'\"'+ (file.file ? '; filename=\"'+ encodeURIComponent(file.file) +'\"' : '')\n\t\t\t\t\t\t+ (file.file ? '\\r\\nContent-Type: '+ (file.type || 'application/octet-stream') : '')\n\t\t\t\t\t\t+ '\\r\\n'\n\t\t\t\t\t\t+ '\\r\\n'+ (file.file ? blob : encodeURIComponent(blob))\n\t\t\t\t\t\t+ '\\r\\n')\n\t\t\t\t\t);\n\t\t\t\t\tqueue.next();\n\t\t\t\t}, true);\n\t\t\t}, api.expando);\n\t\t}\n\t};\n\n\n\tfunction _convertFile(file, fn, useBinaryString){\n\t\tvar blob = file.blob, filename = file.file;\n\n\t\tif( filename ){\n\t\t\tif( !blob.toDataURL ){\n\t\t\t\t// The Blob is not an image.\n\t\t\t\tapi.readAsBinaryString(blob, function (evt){\n\t\t\t\t\tif( evt.type == 'load' ){\n\t\t\t\t\t\tfn(file, evt.result);\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tvar\n\t\t\t\t  mime = { 'image/jpeg': '.jpe?g', 'image/png': '.png' }\n\t\t\t\t, type = mime[file.type] ? file.type : 'image/png'\n\t\t\t\t, ext  = mime[type] || '.png'\n\t\t\t\t, quality = blob.quality || 1\n\t\t\t;\n\n\t\t\tif( !filename.match(new RegExp(ext+'$', 'i')) ){\n\t\t\t\t// Does not change the current extension, but add a new one.\n\t\t\t\tfilename += ext.replace('?', '');\n\t\t\t}\n\n\t\t\tfile.file = filename;\n\t\t\tfile.type = type;\n\n\t\t\tif( !useBinaryString && blob.toBlob ){\n\t\t\t\tblob.toBlob(function (blob){\n\t\t\t\t\tfn(file, blob);\n\t\t\t\t}, type, quality);\n\t\t\t}\n\t\t\telse {\n\t\t\t\tfn(file, api.toBinaryString(blob.toDataURL(type, quality)));\n\t\t\t}\n\t\t}\n\t\telse {\n\t\t\tfn(file, blob);\n\t\t}\n\t}\n\n\n\t// @export\n\tapi.Form = Form;\n})(FileAPI, window);\n\n/*global window, FileAPI, Uint8Array */\n\n(function (window, api){\n\t\"use strict\";\n\n\tvar\n\t\t  noop = function (){}\n\t\t, document = window.document\n\n\t\t, XHR = function (options){\n\t\t\tthis.uid = api.uid();\n\t\t\tthis.xhr = {\n\t\t\t\t  abort: noop\n\t\t\t\t, getResponseHeader: noop\n\t\t\t\t, getAllResponseHeaders: noop\n\t\t\t};\n\t\t\tthis.options = options;\n\t\t},\n\n\t\t_xhrResponsePostfix = { '': 1, XML: 1, Text: 1, Body: 1 }\n\t;\n\n\n\tXHR.prototype = {\n\t\tstatus: 0,\n\t\tstatusText: '',\n\t\tconstructor: XHR,\n\n\t\tgetResponseHeader: function (name){\n\t\t\treturn this.xhr.getResponseHeader(name);\n\t\t},\n\n\t\tgetAllResponseHeaders: function (){\n\t\t\treturn this.xhr.getAllResponseHeaders() || {};\n\t\t},\n\n\t\tend: function (status, statusText){\n\t\t\tvar _this = this, options = _this.options;\n\n\t\t\t_this.end\t\t=\n\t\t\t_this.abort\t\t= noop;\n\t\t\t_this.status\t= status;\n\n\t\t\tif( statusText ){\n\t\t\t\t_this.statusText = statusText;\n\t\t\t}\n\n\t\t\tapi.log('xhr.end:', status, statusText);\n\t\t\toptions.complete(status == 200 || status == 201 ? false : _this.statusText || 'unknown', _this);\n\n\t\t\tif( _this.xhr && _this.xhr.node ){\n\t\t\t\tsetTimeout(function (){\n\t\t\t\t\tvar node = _this.xhr.node;\n\t\t\t\t\ttry { node.parentNode.removeChild(node); } catch (e){}\n\t\t\t\t\ttry { delete window[_this.uid]; } catch (e){}\n\t\t\t\t\twindow[_this.uid] = _this.xhr.node = null;\n\t\t\t\t}, 9);\n\t\t\t}\n\t\t},\n\n\t\tabort: function (){\n\t\t\tthis.end(0, 'abort');\n\n\t\t\tif( this.xhr ){\n\t\t\t\tthis.xhr.aborted = true;\n\t\t\t\tthis.xhr.abort();\n\t\t\t}\n\t\t},\n\n\t\tsend: function (FormData){\n\t\t\tvar _this = this, options = this.options;\n\n\t\t\tFormData.toData(function (data){\n\t\t\t\t// Start uploading\n\t\t\t\toptions.upload(options, _this);\n\t\t\t\t_this._send.call(_this, options, data);\n\t\t\t}, options);\n\t\t},\n\n\t\t_send: function (options, data){\n\t\t\tvar _this = this, xhr, uid = _this.uid, onloadFuncName = _this.uid + \"Load\", url = options.url;\n\n\t\t\tapi.log('XHR._send:', data);\n\n\t\t\tif( !options.cache ){\n\t\t\t\t// No cache\n\t\t\t\turl += (~url.indexOf('?') ? '&' : '?') + api.uid();\n\t\t\t}\n\n\t\t\tif( data.nodeName ){\n\t\t\t\tvar jsonp = options.jsonp;\n\n\t\t\t\t// prepare callback in GET\n\t\t\t\turl = url.replace(/([a-z]+)=(\\?)/i, '$1='+uid);\n\n\t\t\t\t// legacy\n\t\t\t\toptions.upload(options, _this);\n\n\t\t\t\tvar\n\t\t\t\t\tonPostMessage = function (evt){\n\t\t\t\t\t\tif( ~url.indexOf(evt.origin) ){\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\tvar result = api.parseJSON(evt.data);\n\t\t\t\t\t\t\t\tif( result.id == uid ){\n\t\t\t\t\t\t\t\t\tcomplete(result.status, result.statusText, result.response);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} catch( err ){\n\t\t\t\t\t\t\t\tcomplete(0, err.message);\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// jsonp-callack\n\t\t\t\t\tcomplete = window[uid] = function (status, statusText, response){\n\t\t\t\t\t\t_this.readyState\t= 4;\n\t\t\t\t\t\t_this.responseText\t= response;\n\t\t\t\t\t\t_this.end(status, statusText);\n\n\t\t\t\t\t\tapi.event.off(window, 'message', onPostMessage);\n\t\t\t\t\t\twindow[uid] = xhr = transport = window[onloadFuncName] = null;\n\t\t\t\t\t}\n\t\t\t\t;\n\n\t\t\t\t_this.xhr.abort = function (){\n\t\t\t\t\ttry {\n\t\t\t\t\t\tif( transport.stop ){ transport.stop(); }\n\t\t\t\t\t\telse if( transport.contentWindow.stop ){ transport.contentWindow.stop(); }\n\t\t\t\t\t\telse { transport.contentWindow.document.execCommand('Stop'); }\n\t\t\t\t\t}\n\t\t\t\t\tcatch (er) {}\n\t\t\t\t\tcomplete(0, \"abort\");\n\t\t\t\t};\n\n\t\t\t\tapi.event.on(window, 'message', onPostMessage);\n\n\t\t\t\twindow[onloadFuncName] = function (){\n\t\t\t\t\ttry {\n\t\t\t\t\t\tvar\n\t\t\t\t\t\t\t  win = transport.contentWindow\n\t\t\t\t\t\t\t, doc = win.document\n\t\t\t\t\t\t\t, result = win.result || api.parseJSON(doc.body.innerHTML)\n\t\t\t\t\t\t;\n\t\t\t\t\t\tcomplete(result.status, result.statusText, result.response);\n\t\t\t\t\t} catch (e){\n\t\t\t\t\t\tapi.log('[transport.onload]', e);\n\t\t\t\t\t}\n\t\t\t\t};\n\n\t\t\t\txhr = document.createElement('div');\n\t\t\t\txhr.innerHTML = '<form target=\"'+ uid +'\" action=\"'+ url +'\" method=\"POST\" enctype=\"multipart/form-data\" style=\"position: absolute; top: -1000px; overflow: hidden; width: 1px; height: 1px;\">'\n\t\t\t\t\t\t\t+ '<iframe name=\"'+ uid +'\" src=\"javascript:false;\" onload=\"' + onloadFuncName + '()\"></iframe>'\n\t\t\t\t\t\t\t+ (jsonp && (options.url.indexOf('=?') < 0) ? '<input value=\"'+ uid +'\" name=\"'+jsonp+'\" type=\"hidden\"/>' : '')\n\t\t\t\t\t\t\t+ '</form>'\n\t\t\t\t;\n\n\t\t\t\t// get form-data & transport\n\t\t\t\tvar\n\t\t\t\t\t  form = xhr.getElementsByTagName('form')[0]\n\t\t\t\t\t, transport = xhr.getElementsByTagName('iframe')[0]\n\t\t\t\t;\n\n\t\t\t\tform.appendChild(data);\n\n\t\t\t\tapi.log(form.parentNode.innerHTML);\n\n\t\t\t\t// append to DOM\n\t\t\t\tdocument.body.appendChild(xhr);\n\n\t\t\t\t// keep a reference to node-transport\n\t\t\t\t_this.xhr.node = xhr;\n\n\t\t\t\t// send\n\t\t\t\t_this.readyState = 2; // loaded\n\t\t\t\tform.submit();\n\t\t\t\tform = null;\n\t\t\t}\n\t\t\telse {\n\t\t\t\t// Clean url\n\t\t\t\turl = url.replace(/([a-z]+)=(\\?)&?/i, '');\n\n\t\t\t\t// html5\n\t\t\t\tif (this.xhr && this.xhr.aborted) {\n\t\t\t\t\tapi.log(\"Error: already aborted\");\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\txhr = _this.xhr = api.getXHR();\n\n\t\t\t\tif (data.params) {\n\t\t\t\t\turl += (url.indexOf('?') < 0 ? \"?\" : \"&\") + data.params.join(\"&\");\n\t\t\t\t}\n\n\t\t\t\txhr.open('POST', url, true);\n\n\t\t\t\tif( api.withCredentials ){\n\t\t\t\t\txhr.withCredentials = \"true\";\n\t\t\t\t}\n\n\t\t\t\tif( !options.headers || !options.headers['X-Requested-With'] ){\n\t\t\t\t\txhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');\n\t\t\t\t}\n\n\t\t\t\tapi.each(options.headers, function (val, key){\n\t\t\t\t\txhr.setRequestHeader(key, val);\n\t\t\t\t});\n\n\n\t\t\t\tif ( options._chunked ) {\n\t\t\t\t\t// chunked upload\n\t\t\t\t\tif( xhr.upload ){\n\t\t\t\t\t\txhr.upload.addEventListener('progress', api.throttle(function (/**Event*/evt){\n\t\t\t\t\t\t\tif (!data.retry) {\n\t\t\t\t\t\t\t\t// show progress only for correct chunk uploads\n\t\t\t\t\t\t\t\toptions.progress({\n\t\t\t\t\t\t\t\t\t  type:\t\t\tevt.type\n\t\t\t\t\t\t\t\t\t, total:\t\tdata.size\n\t\t\t\t\t\t\t\t\t, loaded:\t\tdata.start + evt.loaded\n\t\t\t\t\t\t\t\t\t, totalSize:\tdata.size\n\t\t\t\t\t\t\t\t}, _this, options);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}, 100), false);\n\t\t\t\t\t}\n\n\t\t\t\t\txhr.onreadystatechange = function (){\n\t\t\t\t\t\tvar lkb = parseInt(xhr.getResponseHeader('X-Last-Known-Byte'), 10);\n\n\t\t\t\t\t\t_this.status     = xhr.status;\n\t\t\t\t\t\t_this.statusText = xhr.statusText;\n\t\t\t\t\t\t_this.readyState = xhr.readyState;\n\n\t\t\t\t\t\tif( xhr.readyState == 4 ){\n\t\t\t\t\t\t\tfor( var k in _xhrResponsePostfix ){\n\t\t\t\t\t\t\t\t_this['response'+k]  = xhr['response'+k];\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\txhr.onreadystatechange = null;\n\n\t\t\t\t\t\t\tif (!xhr.status || xhr.status - 201 > 0) {\n\t\t\t\t\t\t\t\tapi.log(\"Error: \" + xhr.status);\n\t\t\t\t\t\t\t\t// some kind of error\n\t\t\t\t\t\t\t\t// 0 - connection fail or timeout, if xhr.aborted is true, then it's not recoverable user action\n\t\t\t\t\t\t\t\t// up - server error\n\t\t\t\t\t\t\t\tif (((!xhr.status && !xhr.aborted) || 500 == xhr.status || 416 == xhr.status) && ++data.retry <= options.chunkUploadRetry) {\n\t\t\t\t\t\t\t\t\t// let's try again the same chunk\n\t\t\t\t\t\t\t\t\t// only applicable for recoverable error codes 500 && 416\n\t\t\t\t\t\t\t\t\tvar delay = xhr.status ? 0 : api.chunkNetworkDownRetryTimeout;\n\n\t\t\t\t\t\t\t\t\t// inform about recoverable problems\n\t\t\t\t\t\t\t\t\toptions.pause(data.file, options);\n\n\t\t\t\t\t\t\t\t\t// smart restart if server reports about the last known byte\n\t\t\t\t\t\t\t\t\tapi.log(\"X-Last-Known-Byte: \" + lkb);\n\t\t\t\t\t\t\t\t\tif (lkb) {\n\t\t\t\t\t\t\t\t\t\tdata.end = lkb;\n\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\tdata.end = data.start - 1;\n\t\t\t\t\t\t\t\t\t\tif (416 == xhr.status) {\n\t\t\t\t\t\t\t\t\t\t\tdata.end = data.end - options.chunkSize;\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\tsetTimeout(function () {\n\t\t\t\t\t\t\t\t\t\t_this._send(options, data);\n\t\t\t\t\t\t\t\t\t}, delay);\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t// no mo retries\n\t\t\t\t\t\t\t\t\t_this.end(xhr.status);\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\t// success\n\t\t\t\t\t\t\t\tdata.retry = 0;\n\n\t\t\t\t\t\t\t\tif (data.end == data.size - 1) {\n\t\t\t\t\t\t\t\t\t// finished\n\t\t\t\t\t\t\t\t\t_this.end(xhr.status);\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t// next chunk\n\n\t\t\t\t\t\t\t\t\t// shift position if server reports about the last known byte\n\t\t\t\t\t\t\t\t\tapi.log(\"X-Last-Known-Byte: \" + lkb);\n\t\t\t\t\t\t\t\t\tif (lkb) {\n\t\t\t\t\t\t\t\t\t\tdata.end = lkb;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tdata.file.FileAPIReadPosition = data.end;\n\n\t\t\t\t\t\t\t\t\tsetTimeout(function () {\n\t\t\t\t\t\t\t\t\t\t_this._send(options, data);\n\t\t\t\t\t\t\t\t\t}, 0);\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\txhr = null;\n\t\t\t\t\t\t}\n\t\t\t\t\t};\n\n\t\t\t\t\tdata.start = data.end + 1;\n\t\t\t\t\tdata.end = Math.max(Math.min(data.start + options.chunkSize, data.size) - 1, data.start);\n\n\t\t\t\t\t// Retrieve a slice of file\n\t\t\t\t\tvar\n\t\t\t\t\t\t  file = data.file\n\t\t\t\t\t\t, slice = (file.slice || file.mozSlice || file.webkitSlice).call(file, data.start, data.end + 1)\n\t\t\t\t\t;\n\n\t\t\t\t\tif( data.size && !slice.size ){\n\t\t\t\t\t\tsetTimeout(function (){\n\t\t\t\t\t\t\t_this.end(-1);\n\t\t\t\t\t\t});\n\t\t\t\t\t} else {\n\t\t\t\t\t\txhr.setRequestHeader(\"Content-Range\", \"bytes \" + data.start + \"-\" + data.end + \"/\" + data.size);\n\t\t\t\t\t\txhr.setRequestHeader(\"Content-Disposition\", 'attachment; filename=' + encodeURIComponent(data.name));\n\t\t\t\t\t\txhr.setRequestHeader(\"Content-Type\", data.type || \"application/octet-stream\");\n\n\t\t\t\t\t\txhr.send(slice);\n\t\t\t\t\t}\n\n\t\t\t\t\tfile = slice = null;\n\t\t\t\t} else {\n\t\t\t\t\t// single piece upload\n\t\t\t\t\tif( xhr.upload ){\n\t\t\t\t\t\t// https://github.com/blueimp/jQuery-File-Upload/wiki/Fixing-Safari-hanging-on-very-high-speed-connections-%281Gbps%29\n\t\t\t\t\t\txhr.upload.addEventListener('progress', api.throttle(function (/**Event*/evt){\n\t\t\t\t\t\t\toptions.progress(evt, _this, options);\n\t\t\t\t\t\t}, 100), false);\n\t\t\t\t\t}\n\n\t\t\t\t\txhr.onreadystatechange = function (){\n\t\t\t\t\t\t_this.status     = xhr.status;\n\t\t\t\t\t\t_this.statusText = xhr.statusText;\n\t\t\t\t\t\t_this.readyState = xhr.readyState;\n\n\t\t\t\t\t\tif( xhr.readyState == 4 ){\n\t\t\t\t\t\t\tfor( var k in _xhrResponsePostfix ){\n\t\t\t\t\t\t\t\t_this['response'+k]  = xhr['response'+k];\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\txhr.onreadystatechange = null;\n\n\t\t\t\t\t\t\tif (!xhr.status || xhr.status > 201) {\n\t\t\t\t\t\t\t\tapi.log(\"Error: \" + xhr.status);\n\t\t\t\t\t\t\t\tif (((!xhr.status && !xhr.aborted) || 500 == xhr.status) && (options.retry || 0) < options.uploadRetry) {\n\t\t\t\t\t\t\t\t\toptions.retry = (options.retry || 0) + 1;\n\t\t\t\t\t\t\t\t\tvar delay = api.networkDownRetryTimeout;\n\n\t\t\t\t\t\t\t\t\t// inform about recoverable problems\n\t\t\t\t\t\t\t\t\toptions.pause(options.file, options);\n\n\t\t\t\t\t\t\t\t\tsetTimeout(function () {\n\t\t\t\t\t\t\t\t\t\t_this._send(options, data);\n\t\t\t\t\t\t\t\t\t}, delay);\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t//success\n\t\t\t\t\t\t\t\t\t_this.end(xhr.status);\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\t//success\n\t\t\t\t\t\t\t\t_this.end(xhr.status);\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\txhr = null;\n\t\t\t\t\t\t}\n\t\t\t\t\t};\n\n\t\t\t\t\tif( api.isArray(data) ){\n\t\t\t\t\t\t// multipart\n\t\t\t\t\t\txhr.setRequestHeader('Content-Type', 'multipart/form-data; boundary=_'+api.expando);\n\t\t\t\t\t\tvar rawData = data.join('') +'--_'+ api.expando +'--';\n\n\t\t\t\t\t\t/** @namespace  xhr.sendAsBinary  https://developer.mozilla.org/ru/XMLHttpRequest#Sending_binary_content */\n\t\t\t\t\t\tif( xhr.sendAsBinary ){\n\t\t\t\t\t\t\txhr.sendAsBinary(rawData);\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse {\n\t\t\t\t\t\t\tvar bytes = Array.prototype.map.call(rawData, function(c){ return c.charCodeAt(0) & 0xff; });\n\t\t\t\t\t\t\txhr.send(new Uint8Array(bytes).buffer);\n\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// FormData\n\t\t\t\t\t\txhr.send(data);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t};\n\n\n\t// @export\n\tapi.XHR = XHR;\n})(window, FileAPI);\n\n/**\n * @class\tFileAPI.Camera\n * @author\tRubaXa\t<trash@rubaxa.org>\n * @support\tChrome 21+, FF 18+, Opera 12+\n */\n\n/*global window, FileAPI, jQuery */\n/** @namespace LocalMediaStream -- https://developer.mozilla.org/en-US/docs/WebRTC/MediaStream_API#LocalMediaStream */\n(function (window, api){\n\t\"use strict\";\n\n\tvar\n\t\tURL = window.URL || window.webkitURL,\n\n\t\tdocument = window.document,\n\t\tnavigator = window.navigator,\n\n\t\tgetMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia,\n\n\t\thtml5 = !!getMedia\n\t;\n\n\n\t// Support \"media\"\n\tapi.support.media = html5;\n\n\n\tvar Camera = function (video){\n\t\tthis.video = video;\n\t};\n\n\n\tCamera.prototype = {\n\t\tisActive: function (){\n\t\t\treturn\t!!this._active;\n\t\t},\n\n\n\t\t/**\n\t\t * Start camera streaming\n\t\t * @param\t{Function}\tcallback\n\t\t */\n\t\tstart: function (callback){\n\t\t\tvar\n\t\t\t\t  _this = this\n\t\t\t\t, video = _this.video\n\t\t\t\t, _successId\n\t\t\t\t, _failId\n\t\t\t\t, _complete = function (err){\n\t\t\t\t\t_this._active = !err;\n\t\t\t\t\tclearTimeout(_failId);\n\t\t\t\t\tclearTimeout(_successId);\n//\t\t\t\t\tapi.event.off(video, 'loadedmetadata', _complete);\n\t\t\t\t\tcallback && callback(err, _this);\n\t\t\t\t}\n\t\t\t;\n\n\t\t\tgetMedia.call(navigator, { video: true }, function (stream/**LocalMediaStream*/){\n\t\t\t\t// Success\n\t\t\t\t_this.stream = stream;\n\n//\t\t\t\tapi.event.on(video, 'loadedmetadata', function (){\n//\t\t\t\t\t_complete(null);\n//\t\t\t\t});\n\n\t\t\t\t// Set camera stream\n\t\t\t\tvideo.src = URL.createObjectURL(stream);\n\n\t\t\t\t// Note: onloadedmetadata doesn't fire in Chrome when using it with getUserMedia.\n\t\t\t\t// See crbug.com/110938.\n\t\t\t\t_successId = setInterval(function (){\n\t\t\t\t\tif( _detectVideoSignal(video) ){\n\t\t\t\t\t\t_complete(null);\n\t\t\t\t\t}\n\t\t\t\t}, 1000);\n\n\t\t\t\t_failId = setTimeout(function (){\n\t\t\t\t\t_complete('timeout');\n\t\t\t\t}, 5000);\n\n\t\t\t\t// Go-go-go!\n\t\t\t\tvideo.play();\n\t\t\t}, _complete/*error*/);\n\t\t},\n\n\n\t\t/**\n\t\t * Stop camera streaming\n\t\t */\n\t\tstop: function (){\n\t\t\ttry {\n\t\t\t\tthis._active = false;\n\t\t\t\tthis.video.pause();\n\t\t\t\tthis.stream.stop();\n\t\t\t} catch( err ){ }\n\t\t},\n\n\n\t\t/**\n\t\t * Create screenshot\n\t\t * @return {FileAPI.Camera.Shot}\n\t\t */\n\t\tshot: function (){\n\t\t\treturn\tnew Shot(this.video);\n\t\t}\n\t};\n\n\n\t/**\n\t * Get camera element from container\n\t *\n\t * @static\n\t * @param\t{HTMLElement}\tel\n\t * @return\t{Camera}\n\t */\n\tCamera.get = function (el){\n\t\treturn\tnew Camera(el.firstChild);\n\t};\n\n\n\t/**\n\t * Publish camera element into container\n\t *\n\t * @static\n\t * @param\t{HTMLElement}\tel\n\t * @param\t{Object}\t\toptions\n\t * @param\t{Function}\t\t[callback]\n\t */\n\tCamera.publish = function (el, options, callback){\n\t\tif( typeof options == 'function' ){\n\t\t\tcallback = options;\n\t\t\toptions = {};\n\t\t}\n\n\t\t// Dimensions of \"camera\"\n\t\toptions = api.extend({}, {\n\t\t\t  width:\t'100%'\n\t\t\t, height:\t'100%'\n\t\t\t, start:\ttrue\n\t\t}, options);\n\n\n\t\tif( el.jquery ){\n\t\t\t// Extract first element, from jQuery collection\n\t\t\tel = el[0];\n\t\t}\n\n\n\t\tvar doneFn = function (err){\n\t\t\tif( err ){\n\t\t\t\tcallback(err);\n\t\t\t}\n\t\t\telse {\n\t\t\t\t// Get camera\n\t\t\t\tvar cam = Camera.get(el);\n\t\t\t\tif( options.start ){\n\t\t\t\t\tcam.start(callback);\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tcallback(null, cam);\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\n\n\t\tel.style.width\t= _px(options.width);\n\t\tel.style.height\t= _px(options.height);\n\n\n\t\tif( api.html5 && html5 ){\n\t\t\t// Create video element\n\t\t\tvar video = document.createElement('video');\n\n\t\t\t// Set dimensions\n\t\t\tvideo.style.width\t= _px(options.width);\n\t\t\tvideo.style.height\t= _px(options.height);\n\n\t\t\t// Clean container\n\t\t\tif( window.jQuery ){\n\t\t\t\tjQuery(el).empty();\n\t\t\t} else {\n\t\t\t\tel.innerHTML = '';\n\t\t\t}\n\n\t\t\t// Add \"camera\" to container\n\t\t\tel.appendChild(video);\n\n\t\t\t// end\n\t\t\tdoneFn();\n\t\t}\n\t\telse {\n\t\t\tCamera.fallback(el, options, doneFn);\n\t\t}\n\t};\n\n\n\tCamera.fallback = function (el, options, callback){\n\t\tcallback('not_support_camera');\n\t};\n\n\n\t/**\n\t * @class\tFileAPI.Camera.Shot\n\t */\n\tvar Shot = function (video){\n\t\tvar canvas\t= video.nodeName ? api.Image.toCanvas(video) : video;\n\t\tvar shot\t= api.Image(canvas);\n\t\tshot.type\t= 'image/png';\n\t\tshot.width\t= canvas.width;\n\t\tshot.height\t= canvas.height;\n\t\tshot.size\t= canvas.width * canvas.height * 4;\n\t\treturn\tshot;\n\t};\n\n\n\t/**\n\t * Add \"px\" postfix, if value is a number\n\t *\n\t * @private\n\t * @param\t{*}  val\n\t * @return\t{String}\n\t */\n\tfunction _px(val){\n\t\treturn\tval >= 0 ? val + 'px' : val;\n\t}\n\n\n\t/**\n\t * @private\n\t * @param\t{HTMLVideoElement} video\n\t * @return\t{Boolean}\n\t */\n\tfunction _detectVideoSignal(video){\n\t\tvar canvas = document.createElement('canvas'), ctx, res = false;\n\t\ttry {\n\t\t\tctx = canvas.getContext('2d');\n\t\t\tctx.drawImage(video, 0, 0, 1, 1);\n\t\t\tres = ctx.getImageData(0, 0, 1, 1).data[4] != 255;\n\t\t}\n\t\tcatch( e ){}\n\t\treturn\tres;\n\t}\n\n\n\t// @export\n\tCamera.Shot\t= Shot;\n\tapi.Camera\t= Camera;\n})(window, FileAPI);\n\n/**\n * FileAPI fallback to Flash\n *\n * @flash-developer  \"Vladimir Demidov\" <v.demidov@corp.mail.ru>\n */\n\n/*global window, ActiveXObject, FileAPI */\n(function (window, jQuery, api) {\n\t\"use strict\";\n\n\tvar\n\t\t  document = window.document\n\t\t, location = window.location\n\t\t, navigator = window.navigator\n\t\t, _each = api.each\n\t;\n\n\n\tapi.support.flash = (function (){\n\t\tvar mime = navigator.mimeTypes, has = false;\n\n\t\tif( navigator.plugins && typeof navigator.plugins['Shockwave Flash'] == 'object' ){\n\t\t\thas\t= navigator.plugins['Shockwave Flash'].description && !(mime && mime['application/x-shockwave-flash'] && !mime['application/x-shockwave-flash'].enabledPlugin);\n\t\t}\n\t\telse {\n\t\t\ttry {\n\t\t\t\thas\t= !!(window.ActiveXObject && new ActiveXObject('ShockwaveFlash.ShockwaveFlash'));\n\t\t\t}\n\t\t\tcatch(er){\n\t\t\t\tapi.log('Flash -- does not supported.');\n\t\t\t}\n\t\t}\n\n\t\tif( has && /^file:/i.test(location) ){\n\t\t\tapi.log('[warn] Flash does not work on `file:` protocol.');\n\t\t}\n\n\t\treturn\thas;\n\t})();\n\n\n\t   api.support.flash\n\t&& (0\n\t\t|| !api.html5 || !api.support.html5\n\t\t|| (api.cors && !api.support.cors)\n\t\t|| (api.media && !api.support.media)\n\t)\n\t&& (function (){\n\t\tvar\n\t\t\t  _attr  = api.uid()\n\t\t\t, _retry = 0\n\t\t\t, _files = {}\n\t\t\t, _rhttp = /^https?:/i\n\n\t\t\t, flash = {\n\t\t\t\t_fn: {},\n\n\n\t\t\t\t/**\n\t\t\t\t * Initialization & preload flash object\n\t\t\t\t */\n\t\t\t\tinit: function (){\n\t\t\t\t\tvar child = document.body && document.body.firstChild;\n\n\t\t\t\t\tif( child ){\n\t\t\t\t\t\tdo {\n\t\t\t\t\t\t\tif( child.nodeType == 1 ){\n\t\t\t\t\t\t\t\tapi.log('FlashAPI.state: awaiting');\n\n\t\t\t\t\t\t\t\tvar dummy = document.createElement('div');\n\n\t\t\t\t\t\t\t\tdummy.id = '_' + _attr;\n\n\t\t\t\t\t\t\t\t_css(dummy, {\n\t\t\t\t\t\t\t\t\t  top: 1\n\t\t\t\t\t\t\t\t\t, right: 1\n\t\t\t\t\t\t\t\t\t, width: 5\n\t\t\t\t\t\t\t\t\t, height: 5\n\t\t\t\t\t\t\t\t\t, position: 'absolute'\n\t\t\t\t\t\t\t\t\t, zIndex: 1e6+'' // set max zIndex\n\t\t\t\t\t\t\t\t});\n\n\t\t\t\t\t\t\t\tchild.parentNode.insertBefore(dummy, child);\n\t\t\t\t\t\t\t\tflash.publish(dummy, _attr);\n\n\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\twhile( child = child.nextSibling );\n\t\t\t\t\t}\n\n\t\t\t\t\tif( _retry < 10 ){\n\t\t\t\t\t\tsetTimeout(flash.init, ++_retry*50);\n\t\t\t\t\t}\n\t\t\t\t},\n\n\n\t\t\t\t/**\n\t\t\t\t * Publish flash-object\n\t\t\t\t *\n\t\t\t\t * @param {HTMLElement} el\n\t\t\t\t * @param {String} id\n\t\t\t\t * @param {Object} [opts]\n\t\t\t\t */\n\t\t\t\tpublish: function (el, id, opts){\n\t\t\t\t\topts = opts || {};\n\t\t\t\t\tel.innerHTML = _makeFlashHTML({\n\t\t\t\t\t\t  id: id\n\t\t\t\t\t\t, src: _getUrl(api.flashUrl, 'r=' + api.version)\n//\t\t\t\t\t\t, src: _getUrl('http://v.demidov.boom.corp.mail.ru/uploaderfileapi/FlashFileAPI.swf?1')\n\t\t\t\t\t\t, wmode: opts.camera ? '' : 'transparent'\n\t\t\t\t\t\t, flashvars: 'callback=' + (opts.onEvent || 'FileAPI.Flash.onEvent')\n\t\t\t\t\t\t\t+ '&flashId='+ id\n\t\t\t\t\t\t\t+ '&storeKey='+ navigator.userAgent.match(/\\d/ig).join('') +'_'+ api.version\n\t\t\t\t\t\t\t+ (flash.isReady || (api.pingUrl ? '&ping='+api.pingUrl : ''))\n\t\t\t\t\t\t\t+ '&timeout='+api.flashAbortTimeout\n\t\t\t\t\t\t\t+ (opts.camera ? '&useCamera=' + _getUrl(api.flashWebcamUrl) : '')\n\t\t\t\t\t\t\t+ '&debug='+(api.debug?\"1\":\"\")\n\t\t\t\t\t}, opts);\n\t\t\t\t},\n\n\n\t\t\t\tready: function (){\n\t\t\t\t\tapi.log('FlashAPI.state: ready');\n\n\t\t\t\t\tflash.ready = api.F;\n\t\t\t\t\tflash.isReady = true;\n\t\t\t\t\tflash.patch();\n\t\t\t\t\tflash.patchCamera && flash.patchCamera();\n\t\t\t\t\tapi.event.on(document, 'mouseover', flash.mouseover);\n\t\t\t\t\tapi.event.on(document, 'click', function (evt){\n\t\t\t\t\t\tif( flash.mouseover(evt) ){\n\t\t\t\t\t\t\tevt.preventDefault\n\t\t\t\t\t\t\t\t? evt.preventDefault()\n\t\t\t\t\t\t\t\t: (evt.returnValue = 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\n\t\t\t\tgetEl: function (){\n\t\t\t\t\treturn\tdocument.getElementById('_'+_attr);\n\t\t\t\t},\n\n\n\t\t\t\tgetWrapper: function (node){\n\t\t\t\t\tdo {\n\t\t\t\t\t\tif( /js-fileapi-wrapper/.test(node.className) ){\n\t\t\t\t\t\t\treturn\tnode;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\twhile( (node = node.parentNode) && (node !== document.body) );\n\t\t\t\t},\n\t\t\t\t\n\t\t\t\tdisableMouseover: false,\n\n\t\t\t\tmouseover: function (evt){\n\t\t\t\t\tif (!flash.disableMouseover) {\n\t\t\t\t\t\tvar target = api.event.fix(evt).target;\n\t\n\t\t\t\t\t\tif( /input/i.test(target.nodeName) && target.type == 'file' && !target.disabled ){\n\t\t\t\t\t\t\tvar\n\t\t\t\t\t\t\t\t  state = target.getAttribute(_attr)\n\t\t\t\t\t\t\t\t, wrapper = flash.getWrapper(target)\n\t\t\t\t\t\t\t;\n\t\n\t\t\t\t\t\t\tif( api.multiFlash ){\n\t\t\t\t\t\t\t\t// check state:\n\t\t\t\t\t\t\t\t//   i — published\n\t\t\t\t\t\t\t\t//   i — initialization\n\t\t\t\t\t\t\t\t//   r — ready\n\t\t\t\t\t\t\t\tif( state == 'i' || state == 'r' ){\n\t\t\t\t\t\t\t\t\t// publish fail\n\t\t\t\t\t\t\t\t\treturn\tfalse;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\telse if( state != 'p' ){\n\t\t\t\t\t\t\t\t\t// set \"init\" state\n\t\t\t\t\t\t\t\t\ttarget.setAttribute(_attr, 'i');\n\t\n\t\t\t\t\t\t\t\t\tvar dummy = document.createElement('div');\n\t\n\t\t\t\t\t\t\t\t\tif( !wrapper ){\n\t\t\t\t\t\t\t\t\t\tapi.log('[err] FlashAPI.mouseover: js-fileapi-wrapper not found');\n\t\t\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t\t\t}\n\t\n\t\t\t\t\t\t\t\t\t_css(dummy, {\n\t\t\t\t\t\t\t\t\t\t  top:    0\n\t\t\t\t\t\t\t\t\t\t, left:   0\n\t\t\t\t\t\t\t\t\t\t, width:  target.offsetWidth\n\t\t\t\t\t\t\t\t\t\t, height: target.offsetHeight\n\t\t\t\t\t\t\t\t\t\t, zIndex: 1e6+'' // set max zIndex\n\t\t\t\t\t\t\t\t\t\t, position: 'absolute'\n\t\t\t\t\t\t\t\t\t});\n\t\n\t\t\t\t\t\t\t\t\twrapper.appendChild(dummy);\n\t\t\t\t\t\t\t\t\tflash.publish(dummy, api.uid());\n\t\n\t\t\t\t\t\t\t\t\t// set \"publish\" state\n\t\t\t\t\t\t\t\t\ttarget.setAttribute(_attr, 'p');\n\t\t\t\t\t\t\t\t}\n\t\n\t\t\t\t\t\t\t\treturn\ttrue;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse if( wrapper ){\n\t\t\t\t\t\t\t\t// Use one flash element\n\t\t\t\t\t\t\t\tvar box = _getDimensions(wrapper);\n\t\t\t\t\t\t\t\t_css(flash.getEl(), box);\n\t\n\t\t\t\t\t\t\t\t// Set current input\n\t\t\t\t\t\t\t\tflash.curInp = target;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse if( !/object|embed/i.test(target.nodeName) ){\n\t\t\t\t\t\t\t_css(flash.getEl(), { top: 1, left: 1, width: 5, height: 5 });\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t},\n\n\t\t\t\tonEvent: function (evt){\n\t\t\t\t\tvar type = evt.type;\n\t\t\t\t\t\n\t\t\t\t\tif( type == 'ready' ){\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t// set \"ready\" state\n\t\t\t\t\t\t\tflash.getInput(evt.flashId).setAttribute(_attr, 'r');\n\t\t\t\t\t\t} catch (e){\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tflash.ready();\n\t\t\t\t\t\tsetTimeout(function (){ flash.mouseenter(evt); }, 50);\n\t\t\t\t\t\treturn\ttrue;\n\t\t\t\t\t}\n\t\t\t\t\telse if( type === 'ping' ){\n\t\t\t\t\t\tapi.log('(flash -> js).ping:', [evt.status, evt.savedStatus], evt.error);\n\t\t\t\t\t}\n\t\t\t\t\telse if( type === 'log' ){\n\t\t\t\t\t\tapi.log('(flash -> js).log:', evt.target);\n\t\t\t\t\t}\n\t\t\t\t\telse if( type in flash ){\n\t\t\t\t\t\tsetTimeout(function (){\n\t\t\t\t\t\t\tapi.log('FlashAPI.event.'+evt.type+':', evt);\n\t\t\t\t\t\t\tflash[type](evt);\n\t\t\t\t\t\t}, 1);\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tmouseDown: function(evt) {\n\t\t\t\t\tflash.disableMouseover = true;\n\t\t\t\t},\n\t\t\t\tcancel: function(evt) {\n\t\t\t\t\tflash.disableMouseover = false;\n\t\t\t\t},\n\t\t\t\tmouseenter: function (evt){\n\t\t\t\t\tvar node = flash.getInput(evt.flashId);\n\n\t\t\t\t\tif( node ){\n\t\t\t\t\t\t// Set multiple mode\n\t\t\t\t\t\tflash.cmd(evt, 'multiple', node.getAttribute('multiple') != null);\n\n\n\t\t\t\t\t\t// Set files filter\n\t\t\t\t\t\tvar accept = [], exts = {};\n\n\t\t\t\t\t\t_each((node.getAttribute('accept') || '').split(/,\\s*/), function (mime){\n\t\t\t\t\t\t\tapi.accept[mime] && _each(api.accept[mime].split(' '), function (ext){\n\t\t\t\t\t\t\t\texts[ext] = 1;\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t});\n\n\t\t\t\t\t\t_each(exts, function (i, ext){\n\t\t\t\t\t\t\taccept.push( ext );\n\t\t\t\t\t\t});\n\n\t\t\t\t\t\tflash.cmd(evt, 'accept', accept.length ? accept.join(',')+','+accept.join(',').toUpperCase() : '*');\n\t\t\t\t\t}\n\t\t\t\t},\n\n\n\t\t\t\tget: function (id){\n\t\t\t\t\treturn\tdocument[id] || window[id] || document.embeds[id];\n\t\t\t\t},\n\n\n\t\t\t\tgetInput: function (id){\n\t\t\t\t\tif( api.multiFlash ){\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tvar node = flash.getWrapper(flash.get(id));\n\t\t\t\t\t\t\tif( node ){\n\t\t\t\t\t\t\t\treturn node.getElementsByTagName('input')[0];\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} catch (e){\n\t\t\t\t\t\t\tapi.log('[err] Can not find \"input\" by flashId:', id, e);\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\treturn\tflash.curInp;\n\t\t\t\t\t}\n\t\t\t\t},\n\n\n\t\t\t\tselect: function (evt){\n\t\t\t\t\ttry {\n\t\t\t\t\t\tvar\n\t\t\t\t\t\t\t  inp = flash.getInput(evt.flashId)\n\t\t\t\t\t\t\t, uid = api.uid(inp)\n\t\t\t\t\t\t\t, files = evt.target.files\n\t\t\t\t\t\t\t, event\n\t\t\t\t\t\t;\n\t\t\t\t\t\t_each(files, function (file){\n\t\t\t\t\t\t\tapi.checkFileObj(file);\n\t\t\t\t\t\t});\n\t\n\t\t\t\t\t\t_files[uid] = files;\n\t\n\t\t\t\t\t\tif( document.createEvent ){\n\t\t\t\t\t\t\tevent = document.createEvent('Event');\n\t\t\t\t\t\t\tevent.files = files;\n\t\t\t\t\t\t\tevent.initEvent('change', true, true);\n\t\t\t\t\t\t\tinp.dispatchEvent(event);\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse if( jQuery ){\n\t\t\t\t\t\t\tjQuery(inp).trigger({ type: 'change', files: files });\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse {\n\t\t\t\t\t\t\tevent = document.createEventObject();\n\t\t\t\t\t\t\tevent.files = files;\n\t\t\t\t\t\t\tinp.fireEvent('onchange', event);\n\t\t\t\t\t\t}\n\t\t\t\t\t} finally {\n\t\t\t\t\t\tflash.disableMouseover = false;\n\t\t\t\t\t}\n\t\t\t\t},\n\n\n\t\t\t\tcmd: function (id, name, data, last){\n\t\t\t\t\ttry {\n\t\t\t\t\t\tapi.log('(js -> flash).'+name+':', data);\n\t\t\t\t\t\treturn flash.get(id.flashId || id).cmd(name, data);\n\t\t\t\t\t} catch (e){\n\t\t\t\t\t\tapi.log('(js -> flash).onError:', e);\n\t\t\t\t\t\tif( !last ){\n\t\t\t\t\t\t\t// try again\n\t\t\t\t\t\t\tsetTimeout(function (){ flash.cmd(id, name, data, true); }, 50);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t},\n\n\n\t\t\t\tpatch: function (){\n\t\t\t\t\tapi.flashEngine = true;\n\n\t\t\t\t\t// FileAPI\n\t\t\t\t\t_inherit(api, {\n\t\t\t\t\t\tgetFiles: function (input, filter, callback){\n\t\t\t\t\t\t\tif( callback ){\n\t\t\t\t\t\t\t\tapi.filterFiles(api.getFiles(input), filter, callback);\n\t\t\t\t\t\t\t\treturn null;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tvar files = api.isArray(input) ? input : _files[api.uid(input.target || input.srcElement || input)];\n\n\n\t\t\t\t\t\t\tif( !files ){\n\t\t\t\t\t\t\t\t// Файлов нету, вызываем родительский метод\n\t\t\t\t\t\t\t\treturn\tthis.parent.apply(this, arguments);\n\t\t\t\t\t\t\t}\n\n\n\t\t\t\t\t\t\tif( filter ){\n\t\t\t\t\t\t\t\tfilter\t= api.getFilesFilter(filter);\n\t\t\t\t\t\t\t\tfiles\t= api.filter(files, function (file){ return filter.test(file.name); });\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\treturn\tfiles;\n\t\t\t\t\t\t},\n\n\n\t\t\t\t\t\tgetInfo: function (file, fn){\n\t\t\t\t\t\t\tif( _isHtmlFile(file) ){\n\t\t\t\t\t\t\t\tthis.parent.apply(this, arguments);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse if( file.isShot ){\n\t\t\t\t\t\t\t\tfn(null, file.info = {\n\t\t\t\t\t\t\t\t\twidth: file.width,\n\t\t\t\t\t\t\t\t\theight: file.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\telse {\n\t\t\t\t\t\t\t\tif( !file.__info ){\n\t\t\t\t\t\t\t\t\tvar defer = file.__info = api.defer();\n\n//\t\t\t\t\t\t\t\t\tflash.cmd(file, 'getFileInfo', {\n//\t\t\t\t\t\t\t\t\t\t  id: file.id\n//\t\t\t\t\t\t\t\t\t\t, callback: _wrap(function _(err, info){\n//\t\t\t\t\t\t\t\t\t\t\t_unwrap(_);\n//\t\t\t\t\t\t\t\t\t\t\tdefer.resolve(err, file.info = info);\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\tdefer.resolve(null, file.info = null);\n\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\tfile.__info.then(fn);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\n\n\t\t\t\t\t// FileAPI.Image\n\t\t\t\t\tapi.support.transform = true;\n\t\t\t\t\tapi.Image && _inherit(api.Image.prototype, {\n\t\t\t\t\t\tget: function (fn, scaleMode){\n\t\t\t\t\t\t\tthis.set({ scaleMode: scaleMode || 'noScale' }); // noScale, exactFit\n\t\t\t\t\t\t\treturn this.parent(fn);\n\t\t\t\t\t\t},\n\n\t\t\t\t\t\t_load: function (file, fn){\n\t\t\t\t\t\t\tapi.log('FlashAPI.Image._load:', file);\n\n\t\t\t\t\t\t\tif( _isHtmlFile(file) ){\n\t\t\t\t\t\t\t\tthis.parent.apply(this, arguments);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse {\n\t\t\t\t\t\t\t\tvar _this = this;\n\t\t\t\t\t\t\t\tapi.getInfo(file, function (err){\n\t\t\t\t\t\t\t\t\tfn.call(_this, err, file);\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_apply: function (file, fn){\n\t\t\t\t\t\t\tapi.log('FlashAPI.Image._apply:', file);\n\n\t\t\t\t\t\t\tif( _isHtmlFile(file) ){\n\t\t\t\t\t\t\t\tthis.parent.apply(this, arguments);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse {\n\t\t\t\t\t\t\t\tvar m = this.getMatrix(file.info), doneFn = fn;\n\n\t\t\t\t\t\t\t\tflash.cmd(file, 'imageTransform', {\n\t\t\t\t\t\t\t\t\t  id: file.id\n\t\t\t\t\t\t\t\t\t, matrix: m\n\t\t\t\t\t\t\t\t\t, callback: _wrap(function _(err, base64){\n\t\t\t\t\t\t\t\t\t\tapi.log('FlashAPI.Image._apply.callback:', err);\n\t\t\t\t\t\t\t\t\t\t_unwrap(_);\n\n\t\t\t\t\t\t\t\t\t\tif( err ){\n\t\t\t\t\t\t\t\t\t\t\tdoneFn(err);\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\telse if( !api.support.html5 && (!api.support.dataURI || base64.length > 3e4) ){\n\t\t\t\t\t\t\t\t\t\t\t_makeFlashImage({\n\t\t\t\t\t\t\t\t\t\t\t\t  width:\t(m.deg % 180) ? m.dh : m.dw\n\t\t\t\t\t\t\t\t\t\t\t\t, height:\t(m.deg % 180) ? m.dw : m.dh\n\t\t\t\t\t\t\t\t\t\t\t\t, scale:\tm.scaleMode\n\t\t\t\t\t\t\t\t\t\t\t}, base64, doneFn);\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\telse {\n\t\t\t\t\t\t\t\t\t\t\tif( m.filter ){\n\t\t\t\t\t\t\t\t\t\t\t\tdoneFn = function (err, img){\n\t\t\t\t\t\t\t\t\t\t\t\t\tif( err ){\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tfn(err);\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\telse {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tapi.Image.applyFilter(img, m.filter, function (){\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tfn(err, this.canvas);\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};\n\t\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t\tapi.newImage('data:'+ file.type +';base64,'+ base64, doneFn);\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\ttoData: function (fn){\n\t\t\t\t\t\t\tvar\n\t\t\t\t\t\t\t\t  file = this.file\n\t\t\t\t\t\t\t\t, info = file.info\n\t\t\t\t\t\t\t\t, matrix = this.getMatrix(info)\n\t\t\t\t\t\t\t;\n\t\t\t\t\t\t\tapi.log('FlashAPI.Image.toData');\n\n\t\t\t\t\t\t\tif( _isHtmlFile(file) ){\n\t\t\t\t\t\t\t\tthis.parent.apply(this, arguments);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse {\n\t\t\t\t\t\t\t\tif( matrix.deg == 'auto' ){\n\t\t\t\t\t\t\t\t\tmatrix.deg = api.Image.exifOrientation[info && info.exif && info.exif.Orientation] || 0;\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\tfn.call(this, !file.info, {\n\t\t\t\t\t\t\t\t\t  id:\t\tfile.id\n\t\t\t\t\t\t\t\t\t, flashId:\tfile.flashId\n\t\t\t\t\t\t\t\t\t, name:\t\tfile.name\n\t\t\t\t\t\t\t\t\t, type:\t\tfile.type\n\t\t\t\t\t\t\t\t\t, matrix:\tmatrix\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\n\n\t\t\t\t\tapi.Image && _inherit(api.Image, {\n\t\t\t\t\t\tfromDataURL: function (dataURL, size, callback){\n\t\t\t\t\t\t\tif( !api.support.dataURI || dataURL.length > 3e4 ){\n\t\t\t\t\t\t\t\t_makeFlashImage(\n\t\t\t\t\t\t\t\t\t  api.extend({ scale: 'exactFit' }, size)\n\t\t\t\t\t\t\t\t\t, dataURL.replace(/^data:[^,]+,/, '')\n\t\t\t\t\t\t\t\t\t, function (err, el){ callback(el); }\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\tthis.parent(dataURL, size, callback);\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// FileAPI.Form\n\t\t\t\t\t_inherit(api.Form.prototype, {\n\t\t\t\t\t\ttoData: function (fn){\n\t\t\t\t\t\t\tvar items = this.items, i = items.length;\n\n\t\t\t\t\t\t\tfor( ; i--; ){\n\t\t\t\t\t\t\t\tif( items[i].file && _isHtmlFile(items[i].blob) ){\n\t\t\t\t\t\t\t\t\treturn this.parent.apply(this, arguments);\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\tapi.log('FlashAPI.Form.toData');\n\t\t\t\t\t\t\tfn(items);\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\n\n\t\t\t\t\t// FileAPI.XHR\n\t\t\t\t\t_inherit(api.XHR.prototype, {\n\t\t\t\t\t\t_send: function (options, formData){\n\t\t\t\t\t\t\tif(\n\t\t\t\t\t\t\t\t   formData.nodeName\n\t\t\t\t\t\t\t\t|| formData.append && api.support.html5\n\t\t\t\t\t\t\t\t|| api.isArray(formData) && (typeof formData[0] === 'string')\n\t\t\t\t\t\t\t){\n\t\t\t\t\t\t\t\t// HTML5, Multipart or IFrame\n\t\t\t\t\t\t\t\treturn\tthis.parent.apply(this, arguments);\n\t\t\t\t\t\t\t}\n\n\n\t\t\t\t\t\t\tvar\n\t\t\t\t\t\t\t\t  data = {}\n\t\t\t\t\t\t\t\t, files = {}\n\t\t\t\t\t\t\t\t, _this = this\n\t\t\t\t\t\t\t\t, flashId\n\t\t\t\t\t\t\t\t, fileId\n\t\t\t\t\t\t\t;\n\n\t\t\t\t\t\t\t_each(formData, function (item){\n\t\t\t\t\t\t\t\tif( item.file ){\n\t\t\t\t\t\t\t\t\tfiles[item.name] = item = _getFileDescr(item.blob);\n\t\t\t\t\t\t\t\t\tfileId  = item.id;\n\t\t\t\t\t\t\t\t\tflashId = item.flashId;\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\tdata[item.name] = item.blob;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t});\n\n\t\t\t\t\t\t\tif( !fileId ){\n\t\t\t\t\t\t\t\tflashId = _attr;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tif( !flashId ){\n\t\t\t\t\t\t\t\tapi.log('[err] FlashAPI._send: flashId -- undefined');\n\t\t\t\t\t\t\t\treturn this.parent.apply(this, arguments);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse {\n\t\t\t\t\t\t\t\tapi.log('FlashAPI.XHR._send: '+ flashId +' -> '+ fileId);\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t_this.xhr = {\n\t\t\t\t\t\t\t\theaders: {},\n\t\t\t\t\t\t\t\tabort: function (){ flash.cmd(flashId, 'abort', { id: fileId }); },\n\t\t\t\t\t\t\t\tgetResponseHeader: function (name){ return this.headers[name]; },\n\t\t\t\t\t\t\t\tgetAllResponseHeaders: function (){ return this.headers; }\n\t\t\t\t\t\t\t};\n\n\t\t\t\t\t\t\tvar queue = api.queue(function (){\n\t\t\t\t\t\t\t\tflash.cmd(flashId, 'upload', {\n\t\t\t\t\t\t\t\t\t  url: _getUrl(options.url.replace(/([a-z]+)=(\\?)&?/i, ''))\n\t\t\t\t\t\t\t\t\t, data: data\n\t\t\t\t\t\t\t\t\t, files: fileId ? files : null\n\t\t\t\t\t\t\t\t\t, headers: options.headers || {}\n\t\t\t\t\t\t\t\t\t, callback: _wrap(function upload(evt){\n\t\t\t\t\t\t\t\t\t\tvar type = evt.type, result = evt.result;\n\n\t\t\t\t\t\t\t\t\t\tapi.log('FlashAPI.upload.'+type);\n\n\t\t\t\t\t\t\t\t\t\tif( type == 'progress' ){\n\t\t\t\t\t\t\t\t\t\t\tevt.loaded = Math.min(evt.loaded, evt.total); // @todo fixme\n\t\t\t\t\t\t\t\t\t\t\tevt.lengthComputable = true;\n\t\t\t\t\t\t\t\t\t\t\toptions.progress(evt);\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\telse if( type == 'complete' ){\n\t\t\t\t\t\t\t\t\t\t\t_unwrap(upload);\n\n\t\t\t\t\t\t\t\t\t\t\tif( typeof result == 'string' ){\n\t\t\t\t\t\t\t\t\t\t\t\t_this.responseText\t= result.replace(/%22/g, \"\\\"\").replace(/%5c/g, \"\\\\\").replace(/%26/g, \"&\").replace(/%25/g, \"%\");\n\t\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t\t_this.end(evt.status || 200);\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\telse if( type == 'abort' || type == 'error' ){\n\t\t\t\t\t\t\t\t\t\t\t_this.end(evt.status || 0, evt.message);\n\t\t\t\t\t\t\t\t\t\t\t_unwrap(upload);\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\n\n\t\t\t\t\t\t\t// #2174: FileReference.load() call while FileReference.upload() or vice versa\n\t\t\t\t\t\t\t_each(files, function (file){\n\t\t\t\t\t\t\t\tqueue.inc();\n\t\t\t\t\t\t\t\tapi.getInfo(file, queue.next);\n\t\t\t\t\t\t\t});\n\n\t\t\t\t\t\t\tqueue.check();\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\n\t\tfunction _makeFlashHTML(opts){\n\t\t\treturn ('<object id=\"#id#\" classid=\"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000\" width=\"'+(opts.width || '100%')+'\" height=\"'+(opts.height || '100%')+'\">'\n\t\t\t\t+ '<param name=\"movie\" value=\"#src#\" />'\n\t\t\t\t+ '<param name=\"flashvars\" value=\"#flashvars#\" />'\n\t\t\t\t+ '<param name=\"swliveconnect\" value=\"true\" />'\n\t\t\t\t+ '<param name=\"allowscriptaccess\" value=\"always\" />'\n\t\t\t\t+ '<param name=\"allownetworking\" value=\"all\" />'\n\t\t\t\t+ '<param name=\"menu\" value=\"false\" />'\n\t\t\t\t+ '<param name=\"wmode\" value=\"#wmode#\" />'\n\t\t\t\t+ '<embed flashvars=\"#flashvars#\" swliveconnect=\"true\" allownetworking=\"all\" allowscriptaccess=\"always\" name=\"#id#\" src=\"#src#\" width=\"'+(opts.width || '100%')+'\" height=\"'+(opts.height || '100%')+'\" menu=\"false\" wmode=\"transparent\" type=\"application/x-shockwave-flash\"></embed>'\n\t\t\t\t+ '</object>').replace(/#(\\w+)#/ig, function (a, name){ return opts[name]; })\n\t\t\t;\n\t\t}\n\n\n\t\tfunction _css(el, css){\n\t\t\tif( el && el.style ){\n\t\t\t\tvar key, val;\n\t\t\t\tfor( key in css ){\n\t\t\t\t\tval = css[key];\n\t\t\t\t\tif( typeof val == 'number' ){\n\t\t\t\t\t\tval += 'px';\n\t\t\t\t\t}\n\t\t\t\t\ttry { el.style[key] = val; } catch (e) {}\n\t\t\t\t}\n\t\t\t\t\n\t\t\t}\n\t\t}\n\n\n\t\tfunction _inherit(obj, methods){\n\t\t\t_each(methods, function (fn, name){\n\t\t\t\tvar prev = obj[name];\n\t\t\t\tobj[name] = function (){\n\t\t\t\t\tthis.parent = prev;\n\t\t\t\t\treturn fn.apply(this, arguments);\n\t\t\t\t};\n\t\t\t});\n\t\t}\n\n\t\tfunction _isHtmlFile(file){\n\t\t\treturn\tfile && !file.flashId;\n\t\t}\n\n\t\tfunction _wrap(fn){\n\t\t\tvar id = fn.wid = api.uid();\n\t\t\tflash._fn[id] = fn;\n\t\t\treturn\t'FileAPI.Flash._fn.'+id;\n\t\t}\n\n\n\t\tfunction _unwrap(fn){\n\t\t\ttry {\n\t\t\t\tflash._fn[fn.wid] = null;\n\t\t\t\tdelete\tflash._fn[fn.wid];\n\t\t\t}\n\t\t\tcatch(e){}\n\t\t}\n\n\n\t\tfunction _getUrl(url, params){\n\t\t\tif( !_rhttp.test(url) ){\n\t\t\t\tif( /^\\.\\//.test(url) || '/' != url.charAt(0) ){\n\t\t\t\t\tvar path = location.pathname;\n\t\t\t\t\tpath = path.substr(0, path.lastIndexOf('/'));\n\t\t\t\t\turl = (path +'/'+ url).replace('/./', '/');\n\t\t\t\t}\n\n\t\t\t\tif( '//' != url.substr(0, 2) ){\n\t\t\t\t\turl = '//' + location.host + url;\n\t\t\t\t}\n\n\t\t\t\tif( !_rhttp.test(url) ){\n\t\t\t\t\turl = location.protocol + url;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif( params ){\n\t\t\t\turl += (/\\?/.test(url) ? '&' : '?') + params;\n\t\t\t}\n\n\t\t\treturn\turl;\n\t\t}\n\n\n\t\tfunction _makeFlashImage(opts, base64, fn){\n\t\t\tvar\n\t\t\t\t  key\n\t\t\t\t, flashId = api.uid()\n\t\t\t\t, el = document.createElement('div')\n\t\t\t\t, attempts = 10\n\t\t\t;\n\n\t\t\tfor( key in opts ){\n\t\t\t\tel.setAttribute(key, opts[key]);\n\t\t\t\tel[key] = opts[key];\n\t\t\t}\n\n\t\t\t_css(el, opts);\n\n\t\t\topts.width\t= '100%';\n\t\t\topts.height\t= '100%';\n\n\t\t\tel.innerHTML = _makeFlashHTML(api.extend({\n\t\t\t\t  id: flashId\n\t\t\t\t, src: _getUrl(api.flashImageUrl, 'r='+ api.uid())\n\t\t\t\t, wmode: 'opaque'\n\t\t\t\t, flashvars: 'scale='+ opts.scale +'&callback='+_wrap(function _(){\n\t\t\t\t\t_unwrap(_);\n\t\t\t\t\tif( --attempts > 0 ){\n\t\t\t\t\t\t_setImage();\n\t\t\t\t\t}\n\t\t\t\t\treturn true;\n\t\t\t\t})\n\t\t\t}, opts));\n\n\t\t\tfunction _setImage(){\n\t\t\t\ttry {\n\t\t\t\t\t// Get flash-object by id\n\t\t\t\t\tvar img = flash.get(flashId);\n\t\t\t\t\timg.setImage(base64);\n\t\t\t\t} catch (e){\n\t\t\t\t\tapi.log('[err] FlashAPI.Preview.setImage -- can not set \"base64\":', e);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfn(false, el);\n\t\t\tel = null;\n\t\t}\n\n\n\t\tfunction _getFileDescr(file){\n\t\t\treturn\t{\n\t\t\t\t  id: file.id\n\t\t\t\t, name: file.name\n\t\t\t\t, matrix: file.matrix\n\t\t\t\t, flashId: file.flashId\n\t\t\t};\n\t\t}\n\n\n\t\tfunction _getDimensions(el){\n\t\t\tvar\n\t\t\t\t  box = el.getBoundingClientRect()\n\t\t\t\t, body = document.body\n\t\t\t\t, docEl = (el && el.ownerDocument).documentElement\n\t\t\t;\n\t\t\t\n\t\t\tfunction getOffset(obj) {\n\t\t\t    var left, top;\n\t\t\t    left = top = 0;\n\t\t\t    if (obj.offsetParent) {\n\t\t\t        do {\n\t\t\t            left += obj.offsetLeft;\n\t\t\t            top  += obj.offsetTop;\n\t\t\t        } while (obj = obj.offsetParent);\n\t\t\t    }\n\t\t\t    return {\n\t\t\t        left : left,\n\t\t\t        top : top\n\t\t\t    };\n\t\t\t};\n\t\t\t\n\t\t\treturn {\n\t\t\t\t  top:\t\tgetOffset(el).top\n\t\t\t\t, left:\t\tgetOffset(el).left\n\t\t\t\t, width:\tel.offsetWidth\n\t\t\t\t, height:\tel.offsetHeight\n\t\t\t};\n\t\t}\n\n\t\t// @export\n\t\tapi.Flash = flash;\n\n\n\t\t// Check dataURI support\n\t\tapi.newImage('data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///ywAAAAAAQABAAACAUwAOw==', function (err, img){\n\t\t\tapi.support.dataURI = !(img.width != 1 || img.height != 1);\n\t\t\tflash.init();\n\t\t});\n\t})();\n})(window, window.jQuery, FileAPI);\n\n/**\n * FileAPI fallback to Flash\n *\n * @flash-developer  \"Vladimir Demidov\" <v.demidov@corp.mail.ru>\n */\n\n/*global window, FileAPI */\n(function (window, jQuery, api) {\n    \"use strict\";\n\n    var _each = api.each,\n        _cameraQueue = [];\n\n\n    if (api.support.flash && (api.media && !api.support.media)) {\n        (function () {\n\n            function _wrap(fn) {\n                var id = fn.wid = api.uid();\n                api.Flash._fn[id] = fn;\n                return 'FileAPI.Flash._fn.' + id;\n            }\n\n\n            function _unwrap(fn) {\n                try {\n                    api.Flash._fn[fn.wid] = null;\n                    delete api.Flash._fn[fn.wid];\n                } catch (e) {\n                }\n            }\n\n            var flash = api.Flash;\n            api.extend(api.Flash, {\n\n                patchCamera: function () {\n                    api.Camera.fallback = function (el, options, callback) {\n                        var camId = api.uid();\n                        api.log('FlashAPI.Camera.publish: ' + camId);\n                        flash.publish(el, camId, api.extend(options, {\n                            camera: true,\n                            onEvent: _wrap(function _(evt) {\n                                if (evt.type === 'camera') {\n                                    _unwrap(_);\n\n                                    if (evt.error) {\n                                        api.log('FlashAPI.Camera.publish.error: ' + evt.error);\n                                        callback(evt.error);\n                                    } else {\n                                        api.log('FlashAPI.Camera.publish.success: ' + camId);\n                                        callback(null);\n                                    }\n                                }\n                            })\n                        }));\n                    };\n                    // Run\n                    _each(_cameraQueue, function (args) {\n                        api.Camera.fallback.apply(api.Camera, args);\n                    });\n                    _cameraQueue = [];\n\n\n                    // FileAPI.Camera:proto\n                    api.extend(api.Camera.prototype, {\n                        _id: function () {\n                            return this.video.id;\n                        },\n\n                        start: function (callback) {\n                            var _this = this;\n                            flash.cmd(this._id(), 'camera.on', {\n                                callback: _wrap(function _(evt) {\n                                    _unwrap(_);\n\n                                    if (evt.error) {\n                                        api.log('FlashAPI.camera.on.error: ' + evt.error);\n                                        callback(evt.error, _this);\n                                    } else {\n                                        api.log('FlashAPI.camera.on.success: ' + _this._id());\n                                        _this._active = true;\n                                        callback(null, _this);\n                                    }\n                                })\n                            });\n                        },\n\n                        stop: function () {\n                            this._active = false;\n                            flash.cmd(this._id(), 'camera.off');\n                        },\n\n                        shot: function () {\n                            api.log('FlashAPI.Camera.shot:', this._id());\n\n                            var shot = api.Flash.cmd(this._id(), 'shot', {});\n                            shot.type = 'image/png';\n                            shot.flashId = this._id();\n                            shot.isShot = true;\n\n                            return new api.Camera.Shot(shot);\n                        }\n                    });\n                }\n            });\n\n            api.Camera.fallback = function () {\n                _cameraQueue.push(arguments);\n            };\n\n        }());\n    }\n}(window, window.jQuery, FileAPI));\nif( typeof define === \"function\" && define.amd ){ define(\"FileAPI\", [], function (){ return FileAPI; }); }"
  },
  {
    "path": "flowable-ui-web/task/libs/ng-file-upload/ng-file-upload-all.js",
    "content": "/**!\n * AngularJS file upload/drop directive and service with progress and abort\n * @author  Danial  <danial.farid@gmail.com>\n * @version 4.1.0\n */\n(function () {\n\nvar key, i;\nfunction patchXHR(fnName, newFn) {\n    window.XMLHttpRequest.prototype[fnName] = newFn(window.XMLHttpRequest.prototype[fnName]);\n}\n\nif (window.XMLHttpRequest && !window.XMLHttpRequest.__isFileAPIShim) {\n    patchXHR('setRequestHeader', function (orig) {\n        return function (header, value) {\n            if (header === '__setXHR_') {\n                var val = value(this);\n                // fix for angular < 1.2.0\n                if (val instanceof Function) {\n                    val(this);\n                }\n            } else {\n                orig.apply(this, arguments);\n            }\n        }\n    });\n}\n\nvar ngFileUpload = angular.module('ngFileUpload', []);\n\nngFileUpload.version = '4.1.0';\nngFileUpload.service('Upload', ['$http', '$q', '$timeout', function ($http, $q, $timeout) {\n    function sendHttp(config) {\n        config.method = config.method || 'POST';\n        config.headers = config.headers || {};\n        config.transformRequest = config.transformRequest || function (data, headersGetter) {\n            if (window.ArrayBuffer && data instanceof window.ArrayBuffer) {\n                return data;\n            }\n            return $http.defaults.transformRequest[0](data, headersGetter);\n        };\n        var deferred = $q.defer();\n        var promise = deferred.promise;\n\n        config.headers['__setXHR_'] = function () {\n            return function (xhr) {\n                if (!xhr) return;\n                config.__XHR = xhr;\n                config.xhrFn && config.xhrFn(xhr);\n                xhr.upload.addEventListener('progress', function (e) {\n                    e.config = config;\n                    deferred.notify ? deferred.notify(e) : promise.progress_fn && $timeout(function () {\n                        promise.progress_fn(e)\n                    });\n                }, false);\n                //fix for firefox not firing upload progress end, also IE8-9\n                xhr.upload.addEventListener('load', function (e) {\n                    if (e.lengthComputable) {\n                        e.config = config;\n                        deferred.notify ? deferred.notify(e) : promise.progress_fn && $timeout(function () {\n                            promise.progress_fn(e)\n                        });\n                    }\n                }, false);\n            };\n        };\n\n        $http(config).then(function (r) {\n            deferred.resolve(r)\n        }, function (e) {\n            deferred.reject(e)\n        }, function (n) {\n            deferred.notify(n)\n        });\n\n        promise.success = function (fn) {\n            promise.then(function (response) {\n                fn(response.data, response.status, response.headers, config);\n            });\n            return promise;\n        };\n\n        promise.error = function (fn) {\n            promise.then(null, function (response) {\n                fn(response.data, response.status, response.headers, config);\n            });\n            return promise;\n        };\n\n        promise.progress = function (fn) {\n            promise.progress_fn = fn;\n            promise.then(null, null, function (update) {\n                fn(update);\n            });\n            return promise;\n        };\n        promise.abort = function () {\n            if (config.__XHR) {\n                $timeout(function () {\n                    config.__XHR.abort();\n                });\n            }\n            return promise;\n        };\n        promise.xhr = function (fn) {\n            config.xhrFn = (function (origXhrFn) {\n                return function () {\n                    origXhrFn && origXhrFn.apply(promise, arguments);\n                    fn.apply(promise, arguments);\n                }\n            })(config.xhrFn);\n            return promise;\n        };\n\n        return promise;\n    }\n\n    this.upload = function (config) {\n        config.headers = config.headers || {};\n        config.headers['Content-Type'] = undefined;\n        config.transformRequest = config.transformRequest ?\n            (angular.isArray(config.transformRequest) ?\n                config.transformRequest : [config.transformRequest]) : [];\n        config.transformRequest.push(function (data) {\n            var formData = new FormData();\n            var allFields = {};\n            for (key in config.fields) {\n                if (config.fields.hasOwnProperty(key)) {\n                    allFields[key] = config.fields[key];\n                }\n            }\n            if (data) allFields['data'] = data;\n\n            if (config.formDataAppender) {\n                for (key in allFields) {\n                    if (allFields.hasOwnProperty(key)) {\n                        config.formDataAppender(formData, key, allFields[key]);\n                    }\n                }\n            } else {\n                for (key in allFields) {\n                    if (allFields.hasOwnProperty(key)) {\n                        var val = allFields[key];\n                        if (val !== undefined) {\n                            if (angular.isDate(val)) {\n                                val = val.toISOString();\n                            }\n                            if (angular.isString(val)) {\n                                formData.append(key, val);\n                            } else {\n                                if (config.sendObjectsAsJsonBlob && angular.isObject(val)) {\n                                    formData.append(key, new Blob([val], {type: 'application/json'}));\n                                } else {\n                                    formData.append(key, JSON.stringify(val));\n                                }\n                            }\n\n                        }\n                    }\n                }\n            }\n\n            if (config.file != null) {\n                var fileFormName = config.fileFormDataName || 'file';\n\n                if (angular.isArray(config.file)) {\n                    var isFileFormNameString = angular.isString(fileFormName);\n                    for (var i = 0; i < config.file.length; i++) {\n                        formData.append(isFileFormNameString ? fileFormName : fileFormName[i], config.file[i],\n                            (config.fileName && config.fileName[i]) || config.file[i].name);\n                    }\n                } else {\n                    formData.append(fileFormName, config.file, config.fileName || config.file.name);\n                }\n            }\n            return formData;\n        });\n\n        return sendHttp(config);\n    };\n\n    this.http = function (config) {\n        return sendHttp(config);\n    };\n}]);\n\nngFileUpload.directive('ngfSelect', ['$parse', '$timeout', '$compile',\n    function ($parse, $timeout, $compile) {\n        return {\n            restrict: 'AEC',\n            require: '?ngModel',\n            link: function (scope, elem, attr, ngModel) {\n                linkFileSelect(scope, elem, attr, ngModel, $parse, $timeout, $compile);\n            }\n        }\n    }]);\n\nfunction linkFileSelect(scope, elem, attr, ngModel, $parse, $timeout, $compile) {\n    function isInputTypeFile() {\n        return elem[0].tagName.toLowerCase() === 'input' && elem.attr('type') && elem.attr('type').toLowerCase() === 'file';\n    }\n    var changeFnAttr = attr.ngfChange || (attr.ngfSelect && attr.ngfSelect.indexOf('(') > 0);\n    var isUpdating = false;\n    function changeFn(evt) {\n        if (!isUpdating) {\n            isUpdating = true;\n            try {\n                var fileList = evt.__files_ || (evt.target && evt.target.files);\n                var files = [], rejFiles = [];\n\n                for (var i = 0; i < fileList.length; i++) {\n                    var file = fileList.item(i);\n                    if (validate(scope, $parse, attr, file, evt)) {\n                        files.push(file);\n                    } else {\n                        rejFiles.push(file);\n                    }\n                }\n                updateModel($parse, $timeout, scope, ngModel, attr, changeFnAttr, files, rejFiles, evt);\n                if (files.length == 0) evt.target.value = files;\n//                if (evt.target && evt.target.getAttribute('__ngf_gen__')) {\n//                    angular.element(evt.target).remove();\n//                }\n            } finally {\n                isUpdating = false;\n            }\n        }\n    }\n\n    function bindAttrToFileInput(fileElem) {\n        if (attr.ngfMultiple) fileElem.attr('multiple', $parse(attr.ngfMultiple)(scope));\n        if (!$parse(attr.ngfMultiple)(scope)) fileElem.attr('multiple', undefined);\n        if (attr['accept']) fileElem.attr('accept', attr['accept']);\n        if (attr.ngfCapture) fileElem.attr('capture', $parse(attr.ngfCapture)(scope));\n        if (attr.ngfDisabled) fileElem.attr('disabled', $parse(attr.ngfDisabled)(scope));\n        for (var i = 0; i < elem[0].attributes.length; i++) {\n            var attribute = elem[0].attributes[i];\n            if (attribute.name !== 'type' && attribute.name !== 'class' && attribute.name !== 'id' && attribute.name !== 'style') {\n            \tfileElem.attr(attribute.name, attribute.value);\n            }\n        }\n    }\n\n    function createFileInput(evt) {\n        if (elem.attr('disabled')) {\n            return;\n        }\n        var fileElem = angular.element('<input type=\"file\">');\n        bindAttrToFileInput(fileElem);\n\n        if (isInputTypeFile()) {\n            elem.replaceWith(fileElem);\n            elem = fileElem;\n        } else {\n            fileElem.css('display', 'none').attr('tabindex', '-1').attr('__ngf_gen__', true);\n            if (elem.__ngf_ref_elem__) {elem.__ngf_ref_elem__.remove();}\n            elem.__ngf_ref_elem__ = fileElem;\n            document.body.appendChild(fileElem[0]);\n        }\n\n        return fileElem;\n    }\n\n    function resetModel(evt) {\n        updateModel($parse, $timeout, scope, ngModel, attr, changeFnAttr, [], [], evt, true);\n    }\n\n    function clickHandler(evt) {\n    \tevt.preventDefault();\n        var fileElem = createFileInput(evt);\n        if (fileElem) {\n        \tfileElem.bind('change', changeFn);\n        \tresetModel(evt);\n\n        \tfunction clickAndAssign() {\n            \tfileElem[0].click();\n    \t        if (isInputTypeFile()) {\n    \t            elem.bind('click touchend', clickHandler);\n    \t            evt.preventDefault()\n    \t        }\n        \t}\n        \t\n        \t// fix for android native browser\n        \tif (navigator.userAgent.toLowerCase().match(/android/)) {\n                setTimeout(function() {\n                \tclickAndAssign();\n                }, 0);        \t\t\n        \t} else {\n        \t\tclickAndAssign();\n        \t}\n        }\n    }\n\n    if (window.FileAPI && window.FileAPI.ngfFixIE) {\n        window.FileAPI.ngfFixIE(elem, createFileInput, bindAttrToFileInput, changeFn, resetModel);\n    } else {\n        elem.bind('click touchend', clickHandler);\n    }\n}\n\nngFileUpload.directive('ngfDrop', ['$parse', '$timeout', '$location', function ($parse, $timeout, $location) {\n    return {\n        restrict: 'AEC',\n        require: '?ngModel',\n        link: function (scope, elem, attr, ngModel) {\n            linkDrop(scope, elem, attr, ngModel, $parse, $timeout, $location);\n        }\n    }\n}]);\n\nngFileUpload.directive('ngfNoFileDrop', function () {\n    return function (scope, elem) {\n        if (dropAvailable()) elem.css('display', 'none')\n    }\n});\n\nngFileUpload.directive('ngfDropAvailable', ['$parse', '$timeout', function ($parse, $timeout) {\n    return function (scope, elem, attr) {\n        if (dropAvailable()) {\n            var fn = $parse(attr.ngfDropAvailable);\n            $timeout(function () {\n                fn(scope);\n                if (fn.assign) {\n                    fn.assign(scope, true);                \t\n                }\n            });\n        }\n    }\n}]);\n\nfunction linkDrop(scope, elem, attr, ngModel, $parse, $timeout, $location) {\n    var available = dropAvailable();\n    if (attr.dropAvailable) {\n        $timeout(function () {\n        \tscope[attr.dropAvailable] ? scope[attr.dropAvailable].value = available : scope[attr.dropAvailable] = available;\n        });\n    }\n    if (!available) {\n        if ($parse(attr.ngfHideOnDropNotAvailable)(scope) == true) {\n            elem.css('display', 'none');\n        }\n        return;\n    }\n    var leaveTimeout = null;\n    var stopPropagation = $parse(attr.ngfStopPropagation);\n    var dragOverDelay = 1;\n    var accept = $parse(attr.ngfAccept);\n    var disabled = $parse(attr.ngfDisabled);\n    var actualDragOverClass;\n\n    elem[0].addEventListener('dragover', function (evt) {\n        if (disabled(scope)) return;\n        evt.preventDefault();\n        if (stopPropagation(scope)) evt.stopPropagation();\n        // handling dragover events from the Chrome download bar\n        if (navigator.userAgent.indexOf(\"Chrome\") > -1) {\n            var b = evt.dataTransfer.effectAllowed;\n            evt.dataTransfer.dropEffect = ('move' === b || 'linkMove' === b) ? 'move' : 'copy';\n        }\n        $timeout.cancel(leaveTimeout);\n        if (!scope.actualDragOverClass) {\n            actualDragOverClass = calculateDragOverClass(scope, attr, evt);\n        }\n        elem.addClass(actualDragOverClass);\n    }, false);\n    elem[0].addEventListener('dragenter', function (evt) {\n        if (disabled(scope)) return;\n        evt.preventDefault();\n        if (stopPropagation(scope)) evt.stopPropagation();\n    }, false);\n    elem[0].addEventListener('dragleave', function () {\n        if (disabled(scope)) return;\n        leaveTimeout = $timeout(function () {\n            elem.removeClass(actualDragOverClass);\n            actualDragOverClass = null;\n        }, dragOverDelay || 1);\n    }, false);\n    elem[0].addEventListener('drop', function (evt) {\n        if (disabled(scope)) return;\n        evt.preventDefault();\n        if (stopPropagation(scope)) evt.stopPropagation();\n        elem.removeClass(actualDragOverClass);\n        actualDragOverClass = null;\n        extractFiles(evt, function (files, rejFiles) {\n            updateModel($parse, $timeout, scope, ngModel, attr,\n                attr.ngfChange || (attr.ngfDrop && attr.ngfDrop.indexOf('(') > 0), files, rejFiles, evt)\n        }, $parse(attr.ngfAllowDir)(scope) != false, attr.multiple || $parse(attr.ngfMultiple)(scope));\n    }, false);\n\n    function calculateDragOverClass(scope, attr, evt) {\n        var accepted = true;\n        var items = evt.dataTransfer.items;\n        if (items != null) {\n            for (var i = 0; i < items.length && accepted; i++) {\n                accepted = accepted\n                    && (items[i].kind == 'file' || items[i].kind == '')\n                    && validate(scope, $parse, attr, items[i], evt);\n            }\n        }\n        var clazz = $parse(attr.ngfDragOverClass)(scope, {$event: evt});\n        if (clazz) {\n            if (clazz.delay) dragOverDelay = clazz.delay;\n            if (clazz.accept) clazz = accepted ? clazz.accept : clazz.reject;\n        }\n        return clazz || attr.ngfDragOverClass || 'dragover';\n    }\n\n    function extractFiles(evt, callback, allowDir, multiple) {\n        var files = [], rejFiles = [], items = evt.dataTransfer.items, processing = 0;\n\n        function addFile(file) {\n            if (validate(scope, $parse, attr, file, evt)) {\n                files.push(file);\n            } else {\n                rejFiles.push(file);\n            }\n        }\n\n        if (items && items.length > 0 && $location.protocol() != 'file') {\n            for (var i = 0; i < items.length; i++) {\n                if (items[i].webkitGetAsEntry && items[i].webkitGetAsEntry() && items[i].webkitGetAsEntry().isDirectory) {\n                    var entry = items[i].webkitGetAsEntry();\n                    if (entry.isDirectory && !allowDir) {\n                        continue;\n                    }\n                    if (entry != null) {\n                        traverseFileTree(files, entry);\n                    }\n                } else {\n                    var f = items[i].getAsFile();\n                    if (f != null) addFile(f);\n                }\n                if (!multiple && files.length > 0) break;\n            }\n        } else {\n            var fileList = evt.dataTransfer.files;\n            if (fileList != null) {\n                for (var i = 0; i < fileList.length; i++) {\n                    addFile(fileList.item(i));\n                    if (!multiple && files.length > 0) break;\n                }\n            }\n        }\n        var delays = 0;\n        (function waitForProcess(delay) {\n            $timeout(function () {\n                if (!processing) {\n                    if (!multiple && files.length > 1) {\n                        i = 0;\n                        while (files[i].type == 'directory') i++;\n                        files = [files[i]];\n                    }\n                    callback(files, rejFiles);\n                } else {\n                    if (delays++ * 10 < 20 * 1000) {\n                        waitForProcess(10);\n                    }\n                }\n            }, delay || 0)\n        })();\n\n        function traverseFileTree(files, entry, path) {\n            if (entry != null) {\n                if (entry.isDirectory) {\n                    var filePath = (path || '') + entry.name;\n                    addFile({name: entry.name, type: 'directory', path: filePath});\n                    var dirReader = entry.createReader();\n                    var entries = [];\n                    processing++;\n                    var readEntries = function () {\n                        dirReader.readEntries(function (results) {\n                            try {\n                                if (!results.length) {\n                                    for (var i = 0; i < entries.length; i++) {\n                                        traverseFileTree(files, entries[i], (path ? path : '') + entry.name + '/');\n                                    }\n                                    processing--;\n                                } else {\n                                    entries = entries.concat(Array.prototype.slice.call(results || [], 0));\n                                    readEntries();\n                                }\n                            } catch (e) {\n                                processing--;\n                                console.error(e);\n                            }\n                        }, function () {\n                            processing--;\n                        });\n                    };\n                    readEntries();\n                } else {\n                    processing++;\n                    entry.file(function (file) {\n                        try {\n                            processing--;\n                            file.path = (path ? path : '') + file.name;\n                            addFile(file);\n                        } catch (e) {\n                            processing--;\n                            console.error(e);\n                        }\n                    }, function () {\n                        processing--;\n                    });\n                }\n            }\n        }\n    }\n}\n\nngFileUpload.directive('ngfSrc', ['$parse', '$timeout', function ($parse, $timeout) {\n\treturn {\n\t\trestrict: 'AE',\n\t\tlink: function (scope, elem, attr, file) {\n\t\t\tif (window.FileReader) {\n\t\t\t\tscope.$watch(attr.ngfSrc, function(file) {\n\t\t\t\t\tif (file) {\n\t\t\t\t\t\t$timeout(function() {\n\t\t\t\t\t\t\tvar fileReader = new FileReader();\n\t\t\t\t\t\t\tfileReader.readAsDataURL(file);\n\t\t\t\t\t\t\tfileReader.onload = function(e) {\n\t\t\t\t\t\t\t\t$timeout(function() {\n\t\t\t\t\t\t\t\t\telem.attr('src', e.target.result);\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t});\n\t\t\t\t\t} else {\n\t\t\t\t\t\telem.attr('src', '');\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n}]);\n\nfunction dropAvailable() {\n    var div = document.createElement('div');\n    return ('draggable' in div) && ('ondrop' in div);\n}\n\nfunction updateModel($parse, $timeout, scope, ngModel, attr, fileChange, files, rejFiles, evt, noDelay) {\n    function update() {\n        if (ngModel) {\n            $parse(attr.ngModel).assign(scope, files);\n            $timeout(function () {\n                ngModel && ngModel.$setViewValue(files != null && files.length == 0 ? null : files);\n            });\n        }\n        if (attr.ngModelRejected) {\n            $parse(attr.ngModelRejected).assign(scope, rejFiles);\n        }\n        if (fileChange) {\n            $parse(fileChange)(scope, {\n                $files: files,\n                $rejectedFiles: rejFiles,\n                $event: evt\n            });\n\n        }\n    }\n    if (noDelay) {\n        update();\n    } else {\n        $timeout(function () {\n            update();\n        });\n    }\n}\n\nfunction validate(scope, $parse, attr, file, evt) {\n    var accept = $parse(attr.ngfAccept);\n    var fileSizeMax = $parse(attr.ngfMaxSize)(scope) || 9007199254740991;\n    var fileSizeMin = $parse(attr.ngfMinSize)(scope) || -1;\n    var val = accept(scope, {$file: file, $event: evt}), match = false;\n    if (val != null && angular.isString(val)) {\n        var regexp = new RegExp(globStringToRegex(val), 'gi');\n        match = (file.type != null && file.type.match(regexp)) ||\n        \t\t(file.name != null && file.name.match(regexp));\n    }\n    return (val == null || match) && (file.size == null || (file.size < fileSizeMax && file.size > fileSizeMin));\n}\n\nfunction globStringToRegex(str) {\n    if (str.length > 2 && str[0] === '/' && str[str.length - 1] === '/') {\n        return str.substring(1, str.length - 1);\n    }\n    var split = str.split(','), result = '';\n    if (split.length > 1) {\n        for (var i = 0; i < split.length; i++) {\n            result += '(' + globStringToRegex(split[i]) + ')';\n            if (i < split.length - 1) {\n                result += '|'\n            }\n        }\n    } else {\n        if (str.indexOf('.') == 0) {\n            str = '*' + str;\n        }\n        result = '^' + str.replace(new RegExp('[.\\\\\\\\+*?\\\\[\\\\^\\\\]$(){}=!<>|:\\\\' + '-]', 'g'), '\\\\$&') + '$';\n        result = result.replace(/\\\\\\*/g, '.*').replace(/\\\\\\?/g, '.');\n    }\n    return result;\n}\n\n})();\n\n/**!\n * AngularJS file upload/drop directive and service with progress and abort\n * FileAPI Flash shim for old browsers not supporting FormData \n * @author  Danial  <danial.farid@gmail.com>\n * @version 4.1.0\n */\n\n(function() {\n\nvar hasFlash = function() {\n\ttry {\n\t  var fo = new ActiveXObject('ShockwaveFlash.ShockwaveFlash');\n\t  if (fo) return true;\n\t} catch(e) {\n\t  if (navigator.mimeTypes['application/x-shockwave-flash'] != undefined) return true;\n\t}\n\treturn false;\n}\n\nfunction patchXHR(fnName, newFn) {\n\twindow.XMLHttpRequest.prototype[fnName] = newFn(window.XMLHttpRequest.prototype[fnName]);\n};\n\nif ((window.XMLHttpRequest && !window.FormData) || (window.FileAPI && FileAPI.forceLoad)) {\n\tvar initializeUploadListener = function(xhr) {\n\t\tif (!xhr.__listeners) {\n\t\t\tif (!xhr.upload) xhr.upload = {};\n\t\t\txhr.__listeners = [];\n\t\t\tvar origAddEventListener = xhr.upload.addEventListener;\n\t\t\txhr.upload.addEventListener = function(t, fn, b) {\n\t\t\t\txhr.__listeners[t] = fn;\n\t\t\t\torigAddEventListener && origAddEventListener.apply(this, arguments);\n\t\t\t};\n\t\t}\n\t}\n\t\n\tpatchXHR('open', function(orig) {\n\t\treturn function(m, url, b) {\n\t\t\tinitializeUploadListener(this);\n\t\t\tthis.__url = url;\n\t\t\ttry {\n\t\t\t\torig.apply(this, [m, url, b]);\n\t\t\t} catch (e) {\n\t\t\t\tif (e.message.indexOf('Access is denied') > -1) {\n\t\t\t\t\tthis.__origError = e;\n\t\t\t\t\torig.apply(this, [m, '_fix_for_ie_crossdomain__', b]);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t});\n\n\tpatchXHR('getResponseHeader', function(orig) {\n\t\treturn function(h) {\n\t\t\treturn this.__fileApiXHR && this.__fileApiXHR.getResponseHeader ? this.__fileApiXHR.getResponseHeader(h) : (orig == null ? null : orig.apply(this, [h]));\n\t\t};\n\t});\n\n\tpatchXHR('getAllResponseHeaders', function(orig) {\n\t\treturn function() {\n\t\t\treturn this.__fileApiXHR && this.__fileApiXHR.getAllResponseHeaders ? this.__fileApiXHR.getAllResponseHeaders() : (orig == null ? null : orig.apply(this));\n\t\t}\n\t});\n\n\tpatchXHR('abort', function(orig) {\n\t\treturn function() {\n\t\t\treturn this.__fileApiXHR && this.__fileApiXHR.abort ? this.__fileApiXHR.abort() : (orig == null ? null : orig.apply(this));\n\t\t}\n\t});\n\n\tpatchXHR('setRequestHeader', function(orig) {\n\t\treturn function(header, value) {\n\t\t\tif (header === '__setXHR_') {\n\t\t\t\tinitializeUploadListener(this);\n\t\t\t\tvar val = value(this);\n\t\t\t\t// fix for angular < 1.2.0\n\t\t\t\tif (val instanceof Function) {\n\t\t\t\t\tval(this);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tthis.__requestHeaders = this.__requestHeaders || {};\n\t\t\t\tthis.__requestHeaders[header] = value;\n\t\t\t\torig.apply(this, arguments);\n\t\t\t}\n\t\t}\n\t});\n\t\n\tfunction redefineProp(xhr, prop, fn) {\n\t\ttry {\n\t\t\tObject.defineProperty(xhr, prop, {get: fn});\n\t\t} catch (e) {/*ignore*/}\n\t}\n\n\tpatchXHR('send', function(orig) {\n\t\treturn function() {\n\t\t\tvar xhr = this;\n\t\t\tif (arguments[0] && arguments[0].__isFileAPIShim) {\n\t\t\t\tvar formData = arguments[0];\n\t\t\t\tvar config = {\n\t\t\t\t\turl: xhr.__url,\n\t\t\t\t\tjsonp: false, //removes the callback form param\n\t\t\t\t\tcache: true, //removes the ?fileapiXXX in the url\n\t\t\t\t\tcomplete: function(err, fileApiXHR) {\n\t\t\t\t\t\txhr.__completed = true;\n\t\t\t\t\t\tif (!err && xhr.__listeners['load']) \n\t\t\t\t\t\t\txhr.__listeners['load']({type: 'load', loaded: xhr.__loaded, total: xhr.__total, target: xhr, lengthComputable: true});\n\t\t\t\t\t\tif (!err && xhr.__listeners['loadend']) \n\t\t\t\t\t\t\txhr.__listeners['loadend']({type: 'loadend', loaded: xhr.__loaded, total: xhr.__total, target: xhr, lengthComputable: true});\n\t\t\t\t\t\tif (err === 'abort' && xhr.__listeners['abort']) \n\t\t\t\t\t\t\txhr.__listeners['abort']({type: 'abort', loaded: xhr.__loaded, total: xhr.__total, target: xhr, lengthComputable: true});\n\t\t\t\t\t\tif (fileApiXHR.status !== undefined) redefineProp(xhr, 'status', function() {return (fileApiXHR.status == 0 && err && err !== 'abort') ? 500 : fileApiXHR.status});\n\t\t\t\t\t\tif (fileApiXHR.statusText !== undefined) redefineProp(xhr, 'statusText', function() {return fileApiXHR.statusText});\n\t\t\t\t\t\tredefineProp(xhr, 'readyState', function() {return 4});\n\t\t\t\t\t\tif (fileApiXHR.response !== undefined) redefineProp(xhr, 'response', function() {return fileApiXHR.response});\n\t\t\t\t\t\tvar resp = fileApiXHR.responseText || (err && fileApiXHR.status == 0 && err !== 'abort' ? err : undefined);\n\t\t\t\t\t\tredefineProp(xhr, 'responseText', function() {return resp});\n\t\t\t\t\t\tredefineProp(xhr, 'response', function() {return resp});\n\t\t\t\t\t\tif (err) redefineProp(xhr, 'err', function() {return err});\n\t\t\t\t\t\txhr.__fileApiXHR = fileApiXHR;\n\t\t\t\t\t\tif (xhr.onreadystatechange) xhr.onreadystatechange();\n\t\t\t\t\t\tif (xhr.onload) xhr.onload();\n\t\t\t\t\t},\n\t\t\t\t\tfileprogress: function(e) {\n\t\t\t\t\t\te.target = xhr;\n\t\t\t\t\t\txhr.__listeners['progress'] && xhr.__listeners['progress'](e);\n\t\t\t\t\t\txhr.__total = e.total;\n\t\t\t\t\t\txhr.__loaded = e.loaded;\n\t\t\t\t\t\tif (e.total === e.loaded) {\n\t\t\t\t\t\t\t// fix flash issue that doesn't call complete if there is no response text from the server  \n\t\t\t\t\t\t\tvar _this = this\n\t\t\t\t\t\t\tsetTimeout(function() {\n\t\t\t\t\t\t\t\tif (!xhr.__completed) {\n\t\t\t\t\t\t\t\t\txhr.getAllResponseHeaders = function(){};\n\t\t\t\t\t\t\t\t\t_this.complete(null, {status: 204, statusText: 'No Content'});\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}, FileAPI.noContentTimeout || 10000);\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\theaders: xhr.__requestHeaders\n\t\t\t\t}\n\t\t\t\tconfig.data = {};\n\t\t\t\tconfig.files = {}\n\t\t\t\tfor (var i = 0; i < formData.data.length; i++) {\n\t\t\t\t\tvar item = formData.data[i];\n\t\t\t\t\tif (item.val != null && item.val.name != null && item.val.size != null && item.val.type != null) {\n\t\t\t\t\t\tconfig.files[item.key] = item.val;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tconfig.data[item.key] = item.val;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tsetTimeout(function() {\n\t\t\t\t\tif (!hasFlash()) {\n\t\t\t\t\t\tthrow 'Adode Flash Player need to be installed. To check ahead use \"FileAPI.hasFlash\"';\n\t\t\t\t\t}\n\t\t\t\t\txhr.__fileApiXHR = FileAPI.upload(config);\n\t\t\t\t}, 1);\n\t\t\t} else {\n\t\t\t\tif (this.__origError) {\n\t\t\t\t\tthrow this.__origError;\n\t\t\t\t}\n\t\t\t\torig.apply(xhr, arguments);\n\t\t\t}\n\t\t}\n\t});\n\twindow.XMLHttpRequest.__isFileAPIShim = true;\n\n\tfunction isInputTypeFile(elem) {\n\t\treturn elem[0].tagName.toLowerCase() === 'input' && elem.attr('type') && elem.attr('type').toLowerCase() === 'file';\n\t}\n\t\n\twindow.FormData = FormData = function() {\n\t\treturn {\n\t\t\tappend: function(key, val, name) {\n\t\t\t\tif (val.__isFileAPIBlobShim) {\n\t\t\t\t\tval = val.data[0];\n\t\t\t\t}\n\t\t\t\tthis.data.push({\n\t\t\t\t\tkey: key,\n\t\t\t\t\tval: val,\n\t\t\t\t\tname: name\n\t\t\t\t});\n\t\t\t},\n\t\t\tdata: [],\n\t\t\t__isFileAPIShim: true\n\t\t};\n\t};\n\n\twindow.Blob = Blob = function(b) {\n\t\treturn {\n\t\t\tdata: b,\n\t\t\t__isFileAPIBlobShim: true\n\t\t};\n\t};\n\n\t(function () {\n\t\t//load FileAPI\n\t\tif (!window.FileAPI) {\n\t\t\twindow.FileAPI = {};\n\t\t}\n\t\tif (FileAPI.forceLoad) {\n\t\t\tFileAPI.html5 = false;\n\t\t}\n\t\t\n\t\tif (!FileAPI.upload) {\n\t\t\tvar jsUrl, basePath, script = document.createElement('script'), allScripts = document.getElementsByTagName('script'), i, index, src;\n\t\t\tif (window.FileAPI.jsUrl) {\n\t\t\t\tjsUrl = window.FileAPI.jsUrl;\n\t\t\t} else if (window.FileAPI.jsPath) {\n\t\t\t\tbasePath = window.FileAPI.jsPath;\n\t\t\t} else {\n\t\t\t\tfor (i = 0; i < allScripts.length; i++) {\n\t\t\t\t\tsrc = allScripts[i].src;\n\t\t\t\t\tindex = src.search(/\\/ng\\-file\\-upload[\\-a-zA-z0-9\\.]*\\.js/)\n\t\t\t\t\tif (index > -1) {\n\t\t\t\t\t\tbasePath = src.substring(0, index + 1);\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\tif (FileAPI.staticPath == null) FileAPI.staticPath = basePath;\n\t\t\tscript.setAttribute('src', jsUrl || basePath + 'FileAPI.min.js');\n\t\t\tdocument.getElementsByTagName('head')[0].appendChild(script);\n\t\t\tFileAPI.hasFlash = hasFlash();\n\t\t}\n\t})();\n\t\n\tFileAPI.ngfFixIE = function(elem, createFileElemFn, bindAttr, changeFn, resetModel) {\n\t\tif (!hasFlash()) {\n\t\t\tthrow 'Adode Flash Player need to be installed. To check ahead use \"FileAPI.hasFlash\"';\n\t\t}\n\t\tvar makeFlashInput = function(evt) {\n\t\t\tif (elem.attr('disabled')) {\n\t\t\t\telem.__ngf_elem__.removeClass('js-fileapi-wrapper');\n\t\t\t} else {\n\t\t\t\tvar fileElem = elem.__ngf_elem__;\n\t\t\t\tif (!fileElem) {\n\t\t\t\t\tfileElem = elem.__ngf_elem__ = createFileElemFn();\n\t\t\t\t\tfileElem.addClass('js-fileapi-wrapper');\n\t\t\t\t\tif (!isInputTypeFile(elem)) {\n//\t\t\t\t\t\tif (fileElem.parent().css('position') === '' || fileElem.parent().css('position') === 'static') {\n//\t\t\t\t\t\t\tfileElem.parent().css('position', 'relative');\n//\t\t\t\t\t\t}\n//\t\t\t\t\t\telem.parent()[0].insertBefore(fileElem[0], elem[0]);\n//\t\t\t\t\t\telem.css('overflow', 'hidden');\n\t\t\t\t\t}\n\t\t\t\t\tsetTimeout(function() {\n\t\t\t\t\t\tfileElem.bind('mouseenter', makeFlashInput);\n\t\t\t\t\t}, 10);\n\t\t\t\t\tfileElem.bind('change', function(evt) {\n\t\t\t\t    \tfileApiChangeFn.apply(this, [evt]);\n\t\t\t\t\t\tchangeFn.apply(this, [evt]);\n//\t\t\t\t\t\talert('change' +  evt);\n\t\t\t\t\t});\n\t\t\t\t} else {\n\t\t\t\t\tbindAttr(elem.__ngf_elem__);\n\t\t\t\t}\n\t\t\t\tif (!isInputTypeFile(elem)) {\n\t\t\t\t\tfileElem.css('position', 'absolute')\n\t\t\t\t\t\t\t.css('top', getOffset(elem[0]).top + 'px').css('left', getOffset(elem[0]).left + 'px')\n\t\t\t\t\t\t\t.css('width', elem[0].offsetWidth + 'px').css('height', elem[0].offsetHeight + 'px')\n\t\t\t\t\t\t\t.css('filter', 'alpha(opacity=0)').css('display', elem.css('display'))\n\t\t\t\t\t\t\t.css('overflow', 'hidden').css('z-index', '900000');\n\t\t\t\t}\n\t\t\t}\n\t\t\tfunction getOffset(obj) {\n\t\t\t    var left, top;\n\t\t\t    left = top = 0;\n\t\t\t    if (obj.offsetParent) {\n\t\t\t        do {\n\t\t\t            left += obj.offsetLeft;\n\t\t\t            top  += obj.offsetTop;\n\t\t\t        } while (obj = obj.offsetParent);\n\t\t\t    }\n\t\t\t    return {\n\t\t\t        left : left,\n\t\t\t        top : top\n\t\t\t    };\n\t\t\t};\n\t\t};\n\n\t\telem.bind('mouseenter', makeFlashInput);\n\n\t\tvar fileApiChangeFn = function(evt) {\n\t\t\tvar files = FileAPI.getFiles(evt);\n\t\t\t//just a double check for #233\n\t\t\tfor (var i = 0; i < files.length; i++) {\n\t\t\t\tif (files[i].size === undefined) files[i].size = 0;\n\t\t\t\tif (files[i].name === undefined) files[i].name = 'file';\n\t\t\t\tif (files[i].type === undefined) files[i].type = 'undefined';\n\t\t\t}\n\t\t\tif (!evt.target) {\n\t\t\t\tevt.target = {};\n\t\t\t}\n\t\t\tevt.target.files = files;\n\t\t\t// if evt.target.files is not writable use helper field\n\t\t\tif (evt.target.files != files) {\n\t\t\t\tevt.__files_ = files;\n\t\t\t}\n\t\t\t(evt.__files_ || evt.target.files).item = function(i) {\n\t\t\t\treturn (evt.__files_ || evt.target.files)[i] || null;\n\t\t\t};\n\t\t};\n\t};\n\n\tFileAPI.disableFileInput = function(elem, disable) {\n\t\tif (disable) {\n\t\t\telem.removeClass('js-fileapi-wrapper')\n\t\t} else {\n\t\t\telem.addClass('js-fileapi-wrapper');\n\t\t}\n\t};\n}\n\n\nif (!window.FileReader) {\n\twindow.FileReader = function() {\n\t\tvar _this = this, loadStarted = false;\n\t\tthis.listeners = {};\n\t\tthis.addEventListener = function(type, fn) {\n\t\t\t_this.listeners[type] = _this.listeners[type] || [];\n\t\t\t_this.listeners[type].push(fn);\n\t\t};\n\t\tthis.removeEventListener = function(type, fn) {\n\t\t\t_this.listeners[type] && _this.listeners[type].splice(_this.listeners[type].indexOf(fn), 1);\n\t\t};\n\t\tthis.dispatchEvent = function(evt) {\n\t\t\tvar list = _this.listeners[evt.type];\n\t\t\tif (list) {\n\t\t\t\tfor (var i = 0; i < list.length; i++) {\n\t\t\t\t\tlist[i].call(_this, evt);\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t\tthis.onabort = this.onerror = this.onload = this.onloadstart = this.onloadend = this.onprogress = null;\n\n\t\tvar constructEvent = function(type, evt) {\n\t\t\tvar e = {type: type, target: _this, loaded: evt.loaded, total: evt.total, error: evt.error};\n\t\t\tif (evt.result != null) e.target.result = evt.result;\n\t\t\treturn e;\n\t\t};\n\t\tvar listener = function(evt) {\n\t\t\tif (!loadStarted) {\n\t\t\t\tloadStarted = true;\n\t\t\t\t_this.onloadstart && _this.onloadstart(constructEvent('loadstart', evt));\n\t\t\t}\n\t\t\tif (evt.type === 'load') {\n\t\t\t\t_this.onloadend && _this.onloadend(constructEvent('loadend', evt));\n\t\t\t\tvar e = constructEvent('load', evt);\n\t\t\t\t_this.onload && _this.onload(e);\n\t\t\t\t_this.dispatchEvent(e);\n\t\t\t} else if (evt.type === 'progress') {\n\t\t\t\tvar e = constructEvent('progress', evt);\n\t\t\t\t_this.onprogress && _this.onprogress(e);\n\t\t\t\t_this.dispatchEvent(e);\n\t\t\t} else {\n\t\t\t\tvar e = constructEvent('error', evt);\n\t\t\t\t_this.onerror && _this.onerror(e);\n\t\t\t\t_this.dispatchEvent(e);\n\t\t\t}\n\t\t};\n\t\tthis.readAsArrayBuffer = function(file) {\n\t\t\tFileAPI.readAsBinaryString(file, listener);\n\t\t}\n\t\tthis.readAsBinaryString = function(file) {\n\t\t\tFileAPI.readAsBinaryString(file, listener);\n\t\t}\n\t\tthis.readAsDataURL = function(file) {\n\t\t\tFileAPI.readAsDataURL(file, listener);\n\t\t}\n\t\tthis.readAsText = function(file) {\n\t\t\tFileAPI.readAsText(file, listener);\n\t\t}\n\t}\n}\n})();\n"
  },
  {
    "path": "flowable-ui-web/task/libs/ng-file-upload/ng-file-upload-shim.js",
    "content": "/**!\n * AngularJS file upload/drop directive and service with progress and abort\n * FileAPI Flash shim for old browsers not supporting FormData \n * @author  Danial  <danial.farid@gmail.com>\n * @version 4.1.0\n */\n\n(function() {\n\nvar hasFlash = function() {\n\ttry {\n\t  var fo = new ActiveXObject('ShockwaveFlash.ShockwaveFlash');\n\t  if (fo) return true;\n\t} catch(e) {\n\t  if (navigator.mimeTypes['application/x-shockwave-flash'] != undefined) return true;\n\t}\n\treturn false;\n}\n\nfunction patchXHR(fnName, newFn) {\n\twindow.XMLHttpRequest.prototype[fnName] = newFn(window.XMLHttpRequest.prototype[fnName]);\n};\n\nif ((window.XMLHttpRequest && !window.FormData) || (window.FileAPI && FileAPI.forceLoad)) {\n\tvar initializeUploadListener = function(xhr) {\n\t\tif (!xhr.__listeners) {\n\t\t\tif (!xhr.upload) xhr.upload = {};\n\t\t\txhr.__listeners = [];\n\t\t\tvar origAddEventListener = xhr.upload.addEventListener;\n\t\t\txhr.upload.addEventListener = function(t, fn, b) {\n\t\t\t\txhr.__listeners[t] = fn;\n\t\t\t\torigAddEventListener && origAddEventListener.apply(this, arguments);\n\t\t\t};\n\t\t}\n\t}\n\t\n\tpatchXHR('open', function(orig) {\n\t\treturn function(m, url, b) {\n\t\t\tinitializeUploadListener(this);\n\t\t\tthis.__url = url;\n\t\t\ttry {\n\t\t\t\torig.apply(this, [m, url, b]);\n\t\t\t} catch (e) {\n\t\t\t\tif (e.message.indexOf('Access is denied') > -1) {\n\t\t\t\t\tthis.__origError = e;\n\t\t\t\t\torig.apply(this, [m, '_fix_for_ie_crossdomain__', b]);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t});\n\n\tpatchXHR('getResponseHeader', function(orig) {\n\t\treturn function(h) {\n\t\t\treturn this.__fileApiXHR && this.__fileApiXHR.getResponseHeader ? this.__fileApiXHR.getResponseHeader(h) : (orig == null ? null : orig.apply(this, [h]));\n\t\t};\n\t});\n\n\tpatchXHR('getAllResponseHeaders', function(orig) {\n\t\treturn function() {\n\t\t\treturn this.__fileApiXHR && this.__fileApiXHR.getAllResponseHeaders ? this.__fileApiXHR.getAllResponseHeaders() : (orig == null ? null : orig.apply(this));\n\t\t}\n\t});\n\n\tpatchXHR('abort', function(orig) {\n\t\treturn function() {\n\t\t\treturn this.__fileApiXHR && this.__fileApiXHR.abort ? this.__fileApiXHR.abort() : (orig == null ? null : orig.apply(this));\n\t\t}\n\t});\n\n\tpatchXHR('setRequestHeader', function(orig) {\n\t\treturn function(header, value) {\n\t\t\tif (header === '__setXHR_') {\n\t\t\t\tinitializeUploadListener(this);\n\t\t\t\tvar val = value(this);\n\t\t\t\t// fix for angular < 1.2.0\n\t\t\t\tif (val instanceof Function) {\n\t\t\t\t\tval(this);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tthis.__requestHeaders = this.__requestHeaders || {};\n\t\t\t\tthis.__requestHeaders[header] = value;\n\t\t\t\torig.apply(this, arguments);\n\t\t\t}\n\t\t}\n\t});\n\t\n\tfunction redefineProp(xhr, prop, fn) {\n\t\ttry {\n\t\t\tObject.defineProperty(xhr, prop, {get: fn});\n\t\t} catch (e) {/*ignore*/}\n\t}\n\n\tpatchXHR('send', function(orig) {\n\t\treturn function() {\n\t\t\tvar xhr = this;\n\t\t\tif (arguments[0] && arguments[0].__isFileAPIShim) {\n\t\t\t\tvar formData = arguments[0];\n\t\t\t\tvar config = {\n\t\t\t\t\turl: xhr.__url,\n\t\t\t\t\tjsonp: false, //removes the callback form param\n\t\t\t\t\tcache: true, //removes the ?fileapiXXX in the url\n\t\t\t\t\tcomplete: function(err, fileApiXHR) {\n\t\t\t\t\t\txhr.__completed = true;\n\t\t\t\t\t\tif (!err && xhr.__listeners['load']) \n\t\t\t\t\t\t\txhr.__listeners['load']({type: 'load', loaded: xhr.__loaded, total: xhr.__total, target: xhr, lengthComputable: true});\n\t\t\t\t\t\tif (!err && xhr.__listeners['loadend']) \n\t\t\t\t\t\t\txhr.__listeners['loadend']({type: 'loadend', loaded: xhr.__loaded, total: xhr.__total, target: xhr, lengthComputable: true});\n\t\t\t\t\t\tif (err === 'abort' && xhr.__listeners['abort']) \n\t\t\t\t\t\t\txhr.__listeners['abort']({type: 'abort', loaded: xhr.__loaded, total: xhr.__total, target: xhr, lengthComputable: true});\n\t\t\t\t\t\tif (fileApiXHR.status !== undefined) redefineProp(xhr, 'status', function() {return (fileApiXHR.status == 0 && err && err !== 'abort') ? 500 : fileApiXHR.status});\n\t\t\t\t\t\tif (fileApiXHR.statusText !== undefined) redefineProp(xhr, 'statusText', function() {return fileApiXHR.statusText});\n\t\t\t\t\t\tredefineProp(xhr, 'readyState', function() {return 4});\n\t\t\t\t\t\tif (fileApiXHR.response !== undefined) redefineProp(xhr, 'response', function() {return fileApiXHR.response});\n\t\t\t\t\t\tvar resp = fileApiXHR.responseText || (err && fileApiXHR.status == 0 && err !== 'abort' ? err : undefined);\n\t\t\t\t\t\tredefineProp(xhr, 'responseText', function() {return resp});\n\t\t\t\t\t\tredefineProp(xhr, 'response', function() {return resp});\n\t\t\t\t\t\tif (err) redefineProp(xhr, 'err', function() {return err});\n\t\t\t\t\t\txhr.__fileApiXHR = fileApiXHR;\n\t\t\t\t\t\tif (xhr.onreadystatechange) xhr.onreadystatechange();\n\t\t\t\t\t\tif (xhr.onload) xhr.onload();\n\t\t\t\t\t},\n\t\t\t\t\tfileprogress: function(e) {\n\t\t\t\t\t\te.target = xhr;\n\t\t\t\t\t\txhr.__listeners['progress'] && xhr.__listeners['progress'](e);\n\t\t\t\t\t\txhr.__total = e.total;\n\t\t\t\t\t\txhr.__loaded = e.loaded;\n\t\t\t\t\t\tif (e.total === e.loaded) {\n\t\t\t\t\t\t\t// fix flash issue that doesn't call complete if there is no response text from the server  \n\t\t\t\t\t\t\tvar _this = this\n\t\t\t\t\t\t\tsetTimeout(function() {\n\t\t\t\t\t\t\t\tif (!xhr.__completed) {\n\t\t\t\t\t\t\t\t\txhr.getAllResponseHeaders = function(){};\n\t\t\t\t\t\t\t\t\t_this.complete(null, {status: 204, statusText: 'No Content'});\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}, FileAPI.noContentTimeout || 10000);\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\theaders: xhr.__requestHeaders\n\t\t\t\t}\n\t\t\t\tconfig.data = {};\n\t\t\t\tconfig.files = {}\n\t\t\t\tfor (var i = 0; i < formData.data.length; i++) {\n\t\t\t\t\tvar item = formData.data[i];\n\t\t\t\t\tif (item.val != null && item.val.name != null && item.val.size != null && item.val.type != null) {\n\t\t\t\t\t\tconfig.files[item.key] = item.val;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tconfig.data[item.key] = item.val;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tsetTimeout(function() {\n\t\t\t\t\tif (!hasFlash()) {\n\t\t\t\t\t\tthrow 'Adode Flash Player need to be installed. To check ahead use \"FileAPI.hasFlash\"';\n\t\t\t\t\t}\n\t\t\t\t\txhr.__fileApiXHR = FileAPI.upload(config);\n\t\t\t\t}, 1);\n\t\t\t} else {\n\t\t\t\tif (this.__origError) {\n\t\t\t\t\tthrow this.__origError;\n\t\t\t\t}\n\t\t\t\torig.apply(xhr, arguments);\n\t\t\t}\n\t\t}\n\t});\n\twindow.XMLHttpRequest.__isFileAPIShim = true;\n\n\tfunction isInputTypeFile(elem) {\n\t\treturn elem[0].tagName.toLowerCase() === 'input' && elem.attr('type') && elem.attr('type').toLowerCase() === 'file';\n\t}\n\t\n\twindow.FormData = FormData = function() {\n\t\treturn {\n\t\t\tappend: function(key, val, name) {\n\t\t\t\tif (val.__isFileAPIBlobShim) {\n\t\t\t\t\tval = val.data[0];\n\t\t\t\t}\n\t\t\t\tthis.data.push({\n\t\t\t\t\tkey: key,\n\t\t\t\t\tval: val,\n\t\t\t\t\tname: name\n\t\t\t\t});\n\t\t\t},\n\t\t\tdata: [],\n\t\t\t__isFileAPIShim: true\n\t\t};\n\t};\n\n\twindow.Blob = Blob = function(b) {\n\t\treturn {\n\t\t\tdata: b,\n\t\t\t__isFileAPIBlobShim: true\n\t\t};\n\t};\n\n\t(function () {\n\t\t//load FileAPI\n\t\tif (!window.FileAPI) {\n\t\t\twindow.FileAPI = {};\n\t\t}\n\t\tif (FileAPI.forceLoad) {\n\t\t\tFileAPI.html5 = false;\n\t\t}\n\t\t\n\t\tif (!FileAPI.upload) {\n\t\t\tvar jsUrl, basePath, script = document.createElement('script'), allScripts = document.getElementsByTagName('script'), i, index, src;\n\t\t\tif (window.FileAPI.jsUrl) {\n\t\t\t\tjsUrl = window.FileAPI.jsUrl;\n\t\t\t} else if (window.FileAPI.jsPath) {\n\t\t\t\tbasePath = window.FileAPI.jsPath;\n\t\t\t} else {\n\t\t\t\tfor (i = 0; i < allScripts.length; i++) {\n\t\t\t\t\tsrc = allScripts[i].src;\n\t\t\t\t\tindex = src.search(/\\/ng\\-file\\-upload[\\-a-zA-z0-9\\.]*\\.js/)\n\t\t\t\t\tif (index > -1) {\n\t\t\t\t\t\tbasePath = src.substring(0, index + 1);\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\tif (FileAPI.staticPath == null) FileAPI.staticPath = basePath;\n\t\t\tscript.setAttribute('src', jsUrl || basePath + 'FileAPI.min.js');\n\t\t\tdocument.getElementsByTagName('head')[0].appendChild(script);\n\t\t\tFileAPI.hasFlash = hasFlash();\n\t\t}\n\t})();\n\t\n\tFileAPI.ngfFixIE = function(elem, createFileElemFn, bindAttr, changeFn, resetModel) {\n\t\tif (!hasFlash()) {\n\t\t\tthrow 'Adode Flash Player need to be installed. To check ahead use \"FileAPI.hasFlash\"';\n\t\t}\n\t\tvar makeFlashInput = function(evt) {\n\t\t\tif (elem.attr('disabled')) {\n\t\t\t\telem.__ngf_elem__.removeClass('js-fileapi-wrapper');\n\t\t\t} else {\n\t\t\t\tvar fileElem = elem.__ngf_elem__;\n\t\t\t\tif (!fileElem) {\n\t\t\t\t\tfileElem = elem.__ngf_elem__ = createFileElemFn();\n\t\t\t\t\tfileElem.addClass('js-fileapi-wrapper');\n\t\t\t\t\tif (!isInputTypeFile(elem)) {\n//\t\t\t\t\t\tif (fileElem.parent().css('position') === '' || fileElem.parent().css('position') === 'static') {\n//\t\t\t\t\t\t\tfileElem.parent().css('position', 'relative');\n//\t\t\t\t\t\t}\n//\t\t\t\t\t\telem.parent()[0].insertBefore(fileElem[0], elem[0]);\n//\t\t\t\t\t\telem.css('overflow', 'hidden');\n\t\t\t\t\t}\n\t\t\t\t\tsetTimeout(function() {\n\t\t\t\t\t\tfileElem.bind('mouseenter', makeFlashInput);\n\t\t\t\t\t}, 10);\n\t\t\t\t\tfileElem.bind('change', function(evt) {\n\t\t\t\t    \tfileApiChangeFn.apply(this, [evt]);\n\t\t\t\t\t\tchangeFn.apply(this, [evt]);\n//\t\t\t\t\t\talert('change' +  evt);\n\t\t\t\t\t});\n\t\t\t\t} else {\n\t\t\t\t\tbindAttr(elem.__ngf_elem__);\n\t\t\t\t}\n\t\t\t\tif (!isInputTypeFile(elem)) {\n\t\t\t\t\tfileElem.css('position', 'absolute')\n\t\t\t\t\t\t\t.css('top', getOffset(elem[0]).top + 'px').css('left', getOffset(elem[0]).left + 'px')\n\t\t\t\t\t\t\t.css('width', elem[0].offsetWidth + 'px').css('height', elem[0].offsetHeight + 'px')\n\t\t\t\t\t\t\t.css('filter', 'alpha(opacity=0)').css('display', elem.css('display'))\n\t\t\t\t\t\t\t.css('overflow', 'hidden').css('z-index', '900000');\n\t\t\t\t}\n\t\t\t}\n\t\t\tfunction getOffset(obj) {\n\t\t\t    var left, top;\n\t\t\t    left = top = 0;\n\t\t\t    if (obj.offsetParent) {\n\t\t\t        do {\n\t\t\t            left += obj.offsetLeft;\n\t\t\t            top  += obj.offsetTop;\n\t\t\t        } while (obj = obj.offsetParent);\n\t\t\t    }\n\t\t\t    return {\n\t\t\t        left : left,\n\t\t\t        top : top\n\t\t\t    };\n\t\t\t};\n\t\t};\n\n\t\telem.bind('mouseenter', makeFlashInput);\n\n\t\tvar fileApiChangeFn = function(evt) {\n\t\t\tvar files = FileAPI.getFiles(evt);\n\t\t\t//just a double check for #233\n\t\t\tfor (var i = 0; i < files.length; i++) {\n\t\t\t\tif (files[i].size === undefined) files[i].size = 0;\n\t\t\t\tif (files[i].name === undefined) files[i].name = 'file';\n\t\t\t\tif (files[i].type === undefined) files[i].type = 'undefined';\n\t\t\t}\n\t\t\tif (!evt.target) {\n\t\t\t\tevt.target = {};\n\t\t\t}\n\t\t\tevt.target.files = files;\n\t\t\t// if evt.target.files is not writable use helper field\n\t\t\tif (evt.target.files != files) {\n\t\t\t\tevt.__files_ = files;\n\t\t\t}\n\t\t\t(evt.__files_ || evt.target.files).item = function(i) {\n\t\t\t\treturn (evt.__files_ || evt.target.files)[i] || null;\n\t\t\t};\n\t\t};\n\t};\n\n\tFileAPI.disableFileInput = function(elem, disable) {\n\t\tif (disable) {\n\t\t\telem.removeClass('js-fileapi-wrapper')\n\t\t} else {\n\t\t\telem.addClass('js-fileapi-wrapper');\n\t\t}\n\t};\n}\n\n\nif (!window.FileReader) {\n\twindow.FileReader = function() {\n\t\tvar _this = this, loadStarted = false;\n\t\tthis.listeners = {};\n\t\tthis.addEventListener = function(type, fn) {\n\t\t\t_this.listeners[type] = _this.listeners[type] || [];\n\t\t\t_this.listeners[type].push(fn);\n\t\t};\n\t\tthis.removeEventListener = function(type, fn) {\n\t\t\t_this.listeners[type] && _this.listeners[type].splice(_this.listeners[type].indexOf(fn), 1);\n\t\t};\n\t\tthis.dispatchEvent = function(evt) {\n\t\t\tvar list = _this.listeners[evt.type];\n\t\t\tif (list) {\n\t\t\t\tfor (var i = 0; i < list.length; i++) {\n\t\t\t\t\tlist[i].call(_this, evt);\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t\tthis.onabort = this.onerror = this.onload = this.onloadstart = this.onloadend = this.onprogress = null;\n\n\t\tvar constructEvent = function(type, evt) {\n\t\t\tvar e = {type: type, target: _this, loaded: evt.loaded, total: evt.total, error: evt.error};\n\t\t\tif (evt.result != null) e.target.result = evt.result;\n\t\t\treturn e;\n\t\t};\n\t\tvar listener = function(evt) {\n\t\t\tif (!loadStarted) {\n\t\t\t\tloadStarted = true;\n\t\t\t\t_this.onloadstart && _this.onloadstart(constructEvent('loadstart', evt));\n\t\t\t}\n\t\t\tif (evt.type === 'load') {\n\t\t\t\t_this.onloadend && _this.onloadend(constructEvent('loadend', evt));\n\t\t\t\tvar e = constructEvent('load', evt);\n\t\t\t\t_this.onload && _this.onload(e);\n\t\t\t\t_this.dispatchEvent(e);\n\t\t\t} else if (evt.type === 'progress') {\n\t\t\t\tvar e = constructEvent('progress', evt);\n\t\t\t\t_this.onprogress && _this.onprogress(e);\n\t\t\t\t_this.dispatchEvent(e);\n\t\t\t} else {\n\t\t\t\tvar e = constructEvent('error', evt);\n\t\t\t\t_this.onerror && _this.onerror(e);\n\t\t\t\t_this.dispatchEvent(e);\n\t\t\t}\n\t\t};\n\t\tthis.readAsArrayBuffer = function(file) {\n\t\t\tFileAPI.readAsBinaryString(file, listener);\n\t\t}\n\t\tthis.readAsBinaryString = function(file) {\n\t\t\tFileAPI.readAsBinaryString(file, listener);\n\t\t}\n\t\tthis.readAsDataURL = function(file) {\n\t\t\tFileAPI.readAsDataURL(file, listener);\n\t\t}\n\t\tthis.readAsText = function(file) {\n\t\t\tFileAPI.readAsText(file, listener);\n\t\t}\n\t}\n}\n})();\n"
  },
  {
    "path": "flowable-ui-web/task/libs/ng-file-upload/ng-file-upload.js",
    "content": "/**!\n * AngularJS file upload/drop directive and service with progress and abort\n * @author  Danial  <danial.farid@gmail.com>\n * @version 4.1.0\n */\n(function () {\n\nvar key, i;\nfunction patchXHR(fnName, newFn) {\n    window.XMLHttpRequest.prototype[fnName] = newFn(window.XMLHttpRequest.prototype[fnName]);\n}\n\nif (window.XMLHttpRequest && !window.XMLHttpRequest.__isFileAPIShim) {\n    patchXHR('setRequestHeader', function (orig) {\n        return function (header, value) {\n            if (header === '__setXHR_') {\n                var val = value(this);\n                // fix for angular < 1.2.0\n                if (val instanceof Function) {\n                    val(this);\n                }\n            } else {\n                orig.apply(this, arguments);\n            }\n        }\n    });\n}\n\nvar ngFileUpload = angular.module('ngFileUpload', []);\n\nngFileUpload.version = '4.1.0';\nngFileUpload.service('Upload', ['$http', '$q', '$timeout', function ($http, $q, $timeout) {\n    function sendHttp(config) {\n        config.method = config.method || 'POST';\n        config.headers = config.headers || {};\n        config.transformRequest = config.transformRequest || function (data, headersGetter) {\n            if (window.ArrayBuffer && data instanceof window.ArrayBuffer) {\n                return data;\n            }\n            return $http.defaults.transformRequest[0](data, headersGetter);\n        };\n        var deferred = $q.defer();\n        var promise = deferred.promise;\n\n        config.headers['__setXHR_'] = function () {\n            return function (xhr) {\n                if (!xhr) return;\n                config.__XHR = xhr;\n                config.xhrFn && config.xhrFn(xhr);\n                xhr.upload.addEventListener('progress', function (e) {\n                    e.config = config;\n                    deferred.notify ? deferred.notify(e) : promise.progress_fn && $timeout(function () {\n                        promise.progress_fn(e)\n                    });\n                }, false);\n                //fix for firefox not firing upload progress end, also IE8-9\n                xhr.upload.addEventListener('load', function (e) {\n                    if (e.lengthComputable) {\n                        e.config = config;\n                        deferred.notify ? deferred.notify(e) : promise.progress_fn && $timeout(function () {\n                            promise.progress_fn(e)\n                        });\n                    }\n                }, false);\n            };\n        };\n\n        $http(config).then(function (r) {\n            deferred.resolve(r)\n        }, function (e) {\n            deferred.reject(e)\n        }, function (n) {\n            deferred.notify(n)\n        });\n\n        promise.success = function (fn) {\n            promise.then(function (response) {\n                fn(response.data, response.status, response.headers, config);\n            });\n            return promise;\n        };\n\n        promise.error = function (fn) {\n            promise.then(null, function (response) {\n                fn(response.data, response.status, response.headers, config);\n            });\n            return promise;\n        };\n\n        promise.progress = function (fn) {\n            promise.progress_fn = fn;\n            promise.then(null, null, function (update) {\n                fn(update);\n            });\n            return promise;\n        };\n        promise.abort = function () {\n            if (config.__XHR) {\n                $timeout(function () {\n                    config.__XHR.abort();\n                });\n            }\n            return promise;\n        };\n        promise.xhr = function (fn) {\n            config.xhrFn = (function (origXhrFn) {\n                return function () {\n                    origXhrFn && origXhrFn.apply(promise, arguments);\n                    fn.apply(promise, arguments);\n                }\n            })(config.xhrFn);\n            return promise;\n        };\n\n        return promise;\n    }\n\n    this.upload = function (config) {\n        config.headers = config.headers || {};\n        config.headers['Content-Type'] = undefined;\n        config.transformRequest = config.transformRequest ?\n            (angular.isArray(config.transformRequest) ?\n                config.transformRequest : [config.transformRequest]) : [];\n        config.transformRequest.push(function (data) {\n            var formData = new FormData();\n            var allFields = {};\n            for (key in config.fields) {\n                if (config.fields.hasOwnProperty(key)) {\n                    allFields[key] = config.fields[key];\n                }\n            }\n            if (data) allFields['data'] = data;\n\n            if (config.formDataAppender) {\n                for (key in allFields) {\n                    if (allFields.hasOwnProperty(key)) {\n                        config.formDataAppender(formData, key, allFields[key]);\n                    }\n                }\n            } else {\n                for (key in allFields) {\n                    if (allFields.hasOwnProperty(key)) {\n                        var val = allFields[key];\n                        if (val !== undefined) {\n                            if (angular.isDate(val)) {\n                                val = val.toISOString();\n                            }\n                            if (angular.isString(val)) {\n                                formData.append(key, val);\n                            } else {\n                                if (config.sendObjectsAsJsonBlob && angular.isObject(val)) {\n                                    formData.append(key, new Blob([val], {type: 'application/json'}));\n                                } else {\n                                    formData.append(key, JSON.stringify(val));\n                                }\n                            }\n\n                        }\n                    }\n                }\n            }\n\n            if (config.file != null) {\n                var fileFormName = config.fileFormDataName || 'file';\n\n                if (angular.isArray(config.file)) {\n                    var isFileFormNameString = angular.isString(fileFormName);\n                    for (var i = 0; i < config.file.length; i++) {\n                        formData.append(isFileFormNameString ? fileFormName : fileFormName[i], config.file[i],\n                            (config.fileName && config.fileName[i]) || config.file[i].name);\n                    }\n                } else {\n                    formData.append(fileFormName, config.file, config.fileName || config.file.name);\n                }\n            }\n            return formData;\n        });\n\n        return sendHttp(config);\n    };\n\n    this.http = function (config) {\n        return sendHttp(config);\n    };\n}]);\n\nngFileUpload.directive('ngfSelect', ['$parse', '$timeout', '$compile',\n    function ($parse, $timeout, $compile) {\n        return {\n            restrict: 'AEC',\n            require: '?ngModel',\n            link: function (scope, elem, attr, ngModel) {\n                linkFileSelect(scope, elem, attr, ngModel, $parse, $timeout, $compile);\n            }\n        }\n    }]);\n\nfunction linkFileSelect(scope, elem, attr, ngModel, $parse, $timeout, $compile) {\n    function isInputTypeFile() {\n        return elem[0].tagName.toLowerCase() === 'input' && elem.attr('type') && elem.attr('type').toLowerCase() === 'file';\n    }\n    var changeFnAttr = attr.ngfChange || (attr.ngfSelect && attr.ngfSelect.indexOf('(') > 0);\n    var isUpdating = false;\n    function changeFn(evt) {\n        if (!isUpdating) {\n            isUpdating = true;\n            try {\n                var fileList = evt.__files_ || (evt.target && evt.target.files);\n                var files = [], rejFiles = [];\n\n                for (var i = 0; i < fileList.length; i++) {\n                    var file = fileList.item(i);\n                    if (validate(scope, $parse, attr, file, evt)) {\n                        files.push(file);\n                    } else {\n                        rejFiles.push(file);\n                    }\n                }\n                updateModel($parse, $timeout, scope, ngModel, attr, changeFnAttr, files, rejFiles, evt);\n                if (files.length == 0) evt.target.value = files;\n//                if (evt.target && evt.target.getAttribute('__ngf_gen__')) {\n//                    angular.element(evt.target).remove();\n//                }\n            } finally {\n                isUpdating = false;\n            }\n        }\n    }\n\n    function bindAttrToFileInput(fileElem) {\n        if (attr.ngfMultiple) fileElem.attr('multiple', $parse(attr.ngfMultiple)(scope));\n        if (!$parse(attr.ngfMultiple)(scope)) fileElem.attr('multiple', undefined);\n        if (attr['accept']) fileElem.attr('accept', attr['accept']);\n        if (attr.ngfCapture) fileElem.attr('capture', $parse(attr.ngfCapture)(scope));\n        if (attr.ngfDisabled) fileElem.attr('disabled', $parse(attr.ngfDisabled)(scope));\n        for (var i = 0; i < elem[0].attributes.length; i++) {\n            var attribute = elem[0].attributes[i];\n            if (attribute.name !== 'type' && attribute.name !== 'class' && attribute.name !== 'id' && attribute.name !== 'style') {\n            \tfileElem.attr(attribute.name, attribute.value);\n            }\n        }\n    }\n\n    function createFileInput(evt) {\n        if (elem.attr('disabled')) {\n            return;\n        }\n        var fileElem = angular.element('<input type=\"file\">');\n        bindAttrToFileInput(fileElem);\n\n        if (isInputTypeFile()) {\n            elem.replaceWith(fileElem);\n            elem = fileElem;\n        } else {\n            fileElem.css('display', 'none').attr('tabindex', '-1').attr('__ngf_gen__', true);\n            if (elem.__ngf_ref_elem__) {elem.__ngf_ref_elem__.remove();}\n            elem.__ngf_ref_elem__ = fileElem;\n            document.body.appendChild(fileElem[0]);\n        }\n\n        return fileElem;\n    }\n\n    function resetModel(evt) {\n        updateModel($parse, $timeout, scope, ngModel, attr, changeFnAttr, [], [], evt, true);\n    }\n\n    function clickHandler(evt) {\n    \tevt.preventDefault();\n        var fileElem = createFileInput(evt);\n        if (fileElem) {\n        \tfileElem.bind('change', changeFn);\n        \tresetModel(evt);\n\n        \tfunction clickAndAssign() {\n            \tfileElem[0].click();\n    \t        if (isInputTypeFile()) {\n    \t            elem.bind('click touchend', clickHandler);\n    \t            evt.preventDefault()\n    \t        }\n        \t}\n        \t\n        \t// fix for android native browser\n        \tif (navigator.userAgent.toLowerCase().match(/android/)) {\n                setTimeout(function() {\n                \tclickAndAssign();\n                }, 0);        \t\t\n        \t} else {\n        \t\tclickAndAssign();\n        \t}\n        }\n    }\n\n    if (window.FileAPI && window.FileAPI.ngfFixIE) {\n        window.FileAPI.ngfFixIE(elem, createFileInput, bindAttrToFileInput, changeFn, resetModel);\n    } else {\n        elem.bind('click touchend', clickHandler);\n    }\n}\n\nngFileUpload.directive('ngfDrop', ['$parse', '$timeout', '$location', function ($parse, $timeout, $location) {\n    return {\n        restrict: 'AEC',\n        require: '?ngModel',\n        link: function (scope, elem, attr, ngModel) {\n            linkDrop(scope, elem, attr, ngModel, $parse, $timeout, $location);\n        }\n    }\n}]);\n\nngFileUpload.directive('ngfNoFileDrop', function () {\n    return function (scope, elem) {\n        if (dropAvailable()) elem.css('display', 'none')\n    }\n});\n\nngFileUpload.directive('ngfDropAvailable', ['$parse', '$timeout', function ($parse, $timeout) {\n    return function (scope, elem, attr) {\n        if (dropAvailable()) {\n            var fn = $parse(attr.ngfDropAvailable);\n            $timeout(function () {\n                fn(scope);\n                if (fn.assign) {\n                    fn.assign(scope, true);                \t\n                }\n            });\n        }\n    }\n}]);\n\nfunction linkDrop(scope, elem, attr, ngModel, $parse, $timeout, $location) {\n    var available = dropAvailable();\n    if (attr.dropAvailable) {\n        $timeout(function () {\n        \tscope[attr.dropAvailable] ? scope[attr.dropAvailable].value = available : scope[attr.dropAvailable] = available;\n        });\n    }\n    if (!available) {\n        if ($parse(attr.ngfHideOnDropNotAvailable)(scope) == true) {\n            elem.css('display', 'none');\n        }\n        return;\n    }\n    var leaveTimeout = null;\n    var stopPropagation = $parse(attr.ngfStopPropagation);\n    var dragOverDelay = 1;\n    var accept = $parse(attr.ngfAccept);\n    var disabled = $parse(attr.ngfDisabled);\n    var actualDragOverClass;\n\n    elem[0].addEventListener('dragover', function (evt) {\n        if (disabled(scope)) return;\n        evt.preventDefault();\n        if (stopPropagation(scope)) evt.stopPropagation();\n        // handling dragover events from the Chrome download bar\n        if (navigator.userAgent.indexOf(\"Chrome\") > -1) {\n            var b = evt.dataTransfer.effectAllowed;\n            evt.dataTransfer.dropEffect = ('move' === b || 'linkMove' === b) ? 'move' : 'copy';\n        }\n        $timeout.cancel(leaveTimeout);\n        if (!scope.actualDragOverClass) {\n            actualDragOverClass = calculateDragOverClass(scope, attr, evt);\n        }\n        elem.addClass(actualDragOverClass);\n    }, false);\n    elem[0].addEventListener('dragenter', function (evt) {\n        if (disabled(scope)) return;\n        evt.preventDefault();\n        if (stopPropagation(scope)) evt.stopPropagation();\n    }, false);\n    elem[0].addEventListener('dragleave', function () {\n        if (disabled(scope)) return;\n        leaveTimeout = $timeout(function () {\n            elem.removeClass(actualDragOverClass);\n            actualDragOverClass = null;\n        }, dragOverDelay || 1);\n    }, false);\n    elem[0].addEventListener('drop', function (evt) {\n        if (disabled(scope)) return;\n        evt.preventDefault();\n        if (stopPropagation(scope)) evt.stopPropagation();\n        elem.removeClass(actualDragOverClass);\n        actualDragOverClass = null;\n        extractFiles(evt, function (files, rejFiles) {\n            updateModel($parse, $timeout, scope, ngModel, attr,\n                attr.ngfChange || (attr.ngfDrop && attr.ngfDrop.indexOf('(') > 0), files, rejFiles, evt)\n        }, $parse(attr.ngfAllowDir)(scope) != false, attr.multiple || $parse(attr.ngfMultiple)(scope));\n    }, false);\n\n    function calculateDragOverClass(scope, attr, evt) {\n        var accepted = true;\n        var items = evt.dataTransfer.items;\n        if (items != null) {\n            for (var i = 0; i < items.length && accepted; i++) {\n                accepted = accepted\n                    && (items[i].kind == 'file' || items[i].kind == '')\n                    && validate(scope, $parse, attr, items[i], evt);\n            }\n        }\n        var clazz = $parse(attr.ngfDragOverClass)(scope, {$event: evt});\n        if (clazz) {\n            if (clazz.delay) dragOverDelay = clazz.delay;\n            if (clazz.accept) clazz = accepted ? clazz.accept : clazz.reject;\n        }\n        return clazz || attr.ngfDragOverClass || 'dragover';\n    }\n\n    function extractFiles(evt, callback, allowDir, multiple) {\n        var files = [], rejFiles = [], items = evt.dataTransfer.items, processing = 0;\n\n        function addFile(file) {\n            if (validate(scope, $parse, attr, file, evt)) {\n                files.push(file);\n            } else {\n                rejFiles.push(file);\n            }\n        }\n\n        if (items && items.length > 0 && $location.protocol() != 'file') {\n            for (var i = 0; i < items.length; i++) {\n                if (items[i].webkitGetAsEntry && items[i].webkitGetAsEntry() && items[i].webkitGetAsEntry().isDirectory) {\n                    var entry = items[i].webkitGetAsEntry();\n                    if (entry.isDirectory && !allowDir) {\n                        continue;\n                    }\n                    if (entry != null) {\n                        traverseFileTree(files, entry);\n                    }\n                } else {\n                    var f = items[i].getAsFile();\n                    if (f != null) addFile(f);\n                }\n                if (!multiple && files.length > 0) break;\n            }\n        } else {\n            var fileList = evt.dataTransfer.files;\n            if (fileList != null) {\n                for (var i = 0; i < fileList.length; i++) {\n                    addFile(fileList.item(i));\n                    if (!multiple && files.length > 0) break;\n                }\n            }\n        }\n        var delays = 0;\n        (function waitForProcess(delay) {\n            $timeout(function () {\n                if (!processing) {\n                    if (!multiple && files.length > 1) {\n                        i = 0;\n                        while (files[i].type == 'directory') i++;\n                        files = [files[i]];\n                    }\n                    callback(files, rejFiles);\n                } else {\n                    if (delays++ * 10 < 20 * 1000) {\n                        waitForProcess(10);\n                    }\n                }\n            }, delay || 0)\n        })();\n\n        function traverseFileTree(files, entry, path) {\n            if (entry != null) {\n                if (entry.isDirectory) {\n                    var filePath = (path || '') + entry.name;\n                    addFile({name: entry.name, type: 'directory', path: filePath});\n                    var dirReader = entry.createReader();\n                    var entries = [];\n                    processing++;\n                    var readEntries = function () {\n                        dirReader.readEntries(function (results) {\n                            try {\n                                if (!results.length) {\n                                    for (var i = 0; i < entries.length; i++) {\n                                        traverseFileTree(files, entries[i], (path ? path : '') + entry.name + '/');\n                                    }\n                                    processing--;\n                                } else {\n                                    entries = entries.concat(Array.prototype.slice.call(results || [], 0));\n                                    readEntries();\n                                }\n                            } catch (e) {\n                                processing--;\n                                console.error(e);\n                            }\n                        }, function () {\n                            processing--;\n                        });\n                    };\n                    readEntries();\n                } else {\n                    processing++;\n                    entry.file(function (file) {\n                        try {\n                            processing--;\n                            file.path = (path ? path : '') + file.name;\n                            addFile(file);\n                        } catch (e) {\n                            processing--;\n                            console.error(e);\n                        }\n                    }, function () {\n                        processing--;\n                    });\n                }\n            }\n        }\n    }\n}\n\nngFileUpload.directive('ngfSrc', ['$parse', '$timeout', function ($parse, $timeout) {\n\treturn {\n\t\trestrict: 'AE',\n\t\tlink: function (scope, elem, attr, file) {\n\t\t\tif (window.FileReader) {\n\t\t\t\tscope.$watch(attr.ngfSrc, function(file) {\n\t\t\t\t\tif (file) {\n\t\t\t\t\t\t$timeout(function() {\n\t\t\t\t\t\t\tvar fileReader = new FileReader();\n\t\t\t\t\t\t\tfileReader.readAsDataURL(file);\n\t\t\t\t\t\t\tfileReader.onload = function(e) {\n\t\t\t\t\t\t\t\t$timeout(function() {\n\t\t\t\t\t\t\t\t\telem.attr('src', e.target.result);\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t});\n\t\t\t\t\t} else {\n\t\t\t\t\t\telem.attr('src', '');\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n}]);\n\nfunction dropAvailable() {\n    var div = document.createElement('div');\n    return ('draggable' in div) && ('ondrop' in div);\n}\n\nfunction updateModel($parse, $timeout, scope, ngModel, attr, fileChange, files, rejFiles, evt, noDelay) {\n    function update() {\n        if (ngModel) {\n            $parse(attr.ngModel).assign(scope, files);\n            $timeout(function () {\n                ngModel && ngModel.$setViewValue(files != null && files.length == 0 ? null : files);\n            });\n        }\n        if (attr.ngModelRejected) {\n            $parse(attr.ngModelRejected).assign(scope, rejFiles);\n        }\n        if (fileChange) {\n            $parse(fileChange)(scope, {\n                $files: files,\n                $rejectedFiles: rejFiles,\n                $event: evt\n            });\n\n        }\n    }\n    if (noDelay) {\n        update();\n    } else {\n        $timeout(function () {\n            update();\n        });\n    }\n}\n\nfunction validate(scope, $parse, attr, file, evt) {\n    var accept = $parse(attr.ngfAccept);\n    var fileSizeMax = $parse(attr.ngfMaxSize)(scope) || 9007199254740991;\n    var fileSizeMin = $parse(attr.ngfMinSize)(scope) || -1;\n    var val = accept(scope, {$file: file, $event: evt}), match = false;\n    if (val != null && angular.isString(val)) {\n        var regexp = new RegExp(globStringToRegex(val), 'gi');\n        match = (file.type != null && file.type.match(regexp)) ||\n        \t\t(file.name != null && file.name.match(regexp));\n    }\n    return (val == null || match) && (file.size == null || (file.size < fileSizeMax && file.size > fileSizeMin));\n}\n\nfunction globStringToRegex(str) {\n    if (str.length > 2 && str[0] === '/' && str[str.length - 1] === '/') {\n        return str.substring(1, str.length - 1);\n    }\n    var split = str.split(','), result = '';\n    if (split.length > 1) {\n        for (var i = 0; i < split.length; i++) {\n            result += '(' + globStringToRegex(split[i]) + ')';\n            if (i < split.length - 1) {\n                result += '|'\n            }\n        }\n    } else {\n        if (str.indexOf('.') == 0) {\n            str = '*' + str;\n        }\n        result = '^' + str.replace(new RegExp('[.\\\\\\\\+*?\\\\[\\\\^\\\\]$(){}=!<>|:\\\\' + '-]', 'g'), '\\\\$&') + '$';\n        result = result.replace(/\\\\\\*/g, '.*').replace(/\\\\\\?/g, '.');\n    }\n    return result;\n}\n\n})();\n"
  },
  {
    "path": "flowable-ui-web/task/libs/sizzle_1.10.16/.bower.json",
    "content": "{\n  \"name\": \"sizzle\",\n  \"version\": \"1.10.16\",\n  \"main\": \"./dist/sizzle.js\",\n  \"devDependencies\": {\n    \"qunit\": \"~1.12.0\",\n    \"benchmark\": \"~1.0.0\",\n    \"requirejs\": \"~2.1.8\",\n    \"requirejs-domready\": \"~2.0.1\",\n    \"requirejs-text\": \"~2.0.10\"\n  },\n  \"ignore\": [\n    \"**/.*\",\n    \"package.json\",\n    \"bower.json\",\n    \"speed\",\n    \"Makefile\",\n    \"*.md\",\n    \"*.txt\",\n    \"src\",\n    \"Gruntfile.js\"\n  ],\n  \"homepage\": \"https://github.com/jquery/sizzle\",\n  \"_release\": \"1.10.16\",\n  \"_resolution\": {\n    \"type\": \"version\",\n    \"tag\": \"1.10.16\",\n    \"commit\": \"0fd151739d05648118002914c7a638411bbd0dbe\"\n  },\n  \"_source\": \"git://github.com/jquery/sizzle.git\",\n  \"_target\": \"1.10.16\",\n  \"_originalSource\": \"sizzle\"\n}"
  },
  {
    "path": "flowable-ui-web/task/libs/sizzle_1.10.16/tasks/commit.js",
    "content": "\"use strict\";\n\nvar exec = require( \"child_process\" ).exec;\n\nmodule.exports = function( grunt ) {\n\tgrunt.registerTask( \"commit\", \"Add and commit changes\", function( message ) {\n\t\t// Always add dist directory\n\t\texec( \"git add dist && git commit -m \" + message, this.async() );\n\t});\n};\n"
  },
  {
    "path": "flowable-ui-web/task/libs/sizzle_1.10.16/tasks/compile.js",
    "content": "\"use strict\";\n\nmodule.exports = function( grunt ) {\n\tgrunt.registerMultiTask(\n\t\t\"compile\",\n\t\t\"Compile sizzle.js to the dist directory. Embed date/version.\",\n\t\tfunction() {\n\t\t\tvar data = this.data,\n\t\t\t\tdest = data.dest,\n\t\t\t\tsrc = data.src,\n\t\t\t\tversion = grunt.config( \"pkg.version\" ),\n\t\t\t\tcompiled = grunt.file.read( src );\n\n\t\t\t// Embed version and date\n\t\t\tcompiled = compiled\n\t\t\t\t.replace( /@VERSION/g, version )\n\t\t\t\t.replace( \"@DATE\", function() {\n\t\t\t\t\tvar date = new Date();\n\n\t\t\t\t\t// YYYY-MM-DD\n\t\t\t\t\treturn [\n\t\t\t\t\t\tdate.getFullYear(),\n\t\t\t\t\t\t( \"0\" + ( date.getMonth() + 1 ) ).slice( -2 ),\n\t\t\t\t\t\t( \"0\" + date.getDate() ).slice( -2 )\n\t\t\t\t\t].join( \"-\" );\n\t\t\t\t});\n\n\t\t\t// Write source to file\n\t\t\tgrunt.file.write( dest, compiled );\n\n\t\t\tgrunt.log.ok( \"File written to \" + dest );\n\t\t}\n\t);\n};\n"
  },
  {
    "path": "flowable-ui-web/task/libs/sizzle_1.10.16/tasks/dist.js",
    "content": "\"use strict\";\n\nvar fs = require( \"fs\" );\n\nmodule.exports = function( grunt ) {\n\tgrunt.registerTask( \"dist\", \"Process files for distribution\", function() {\n\t\tvar files = grunt.file.expand( { filter: \"isFile\" }, \"dist/*\" );\n\n\t\tfiles.forEach(function( filename ) {\n\t\t\tvar map,\n\t\t\t\ttext = fs.readFileSync( filename, \"utf8\" );\n\n\t\t\t// Modify map/min so that it points to files in the same folder;\n\t\t\t// see https://github.com/mishoo/UglifyJS2/issues/47\n\t\t\tif ( /\\.map$/.test( filename ) ) {\n\t\t\t\ttext = text.replace( /\"dist\\//g, \"\\\"\" );\n\t\t\t\tfs.writeFileSync( filename, text, \"utf-8\" );\n\t\t\t} else if ( /\\.min\\.js$/.test( filename ) ) {\n\t\t\t\t// Wrap sourceMap directive in multiline comments (#13274)\n\t\t\t\ttext = text.replace( /\\n?(\\/\\/@\\s*sourceMappingURL=)(.*)/,\n\t\t\t\t\tfunction( _, directive, path ) {\n\t\t\t\t\t\tmap = \"\\n\" + directive + path.replace( /^dist\\//, \"\" );\n\t\t\t\t\t\treturn \"\";\n\t\t\t\t\t});\n\t\t\t\tif ( map ) {\n\t\t\t\t\ttext = text.replace( /(^\\/\\*[\\w\\W]*?)\\s*\\*\\/|$/,\n\t\t\t\t\t\tfunction( _, comment ) {\n\t\t\t\t\t\t\treturn ( comment || \"\\n/*\" ) + map + \"\\n*/\";\n\t\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tfs.writeFileSync( filename, text, \"utf-8\" );\n\t\t\t}\n\t\t});\n\t});\n};\n"
  },
  {
    "path": "flowable-ui-web/task/libs/sizzle_1.10.16/tasks/release.js",
    "content": "\"use strict\";\n\nvar exec = require( \"child_process\" ).exec;\n\nmodule.exports = function( grunt ) {\n\tvar rpreversion = /(\\d\\.\\d+\\.\\d+)-pre/;\n\n\tgrunt.registerTask( \"release\",\n\t\t\"Release a version of sizzle, updates a pre version to released, \" +\n\t\t\"inserts `next` as the new pre version\", function( next ) {\n\t\t\n\t\tif ( !rpreversion.test( next ) ) {\n\t\t\tgrunt.fatal( \"Next version should be a -pre version (x.x.x-pre): \" + next );\n\t\t\treturn;\n\t\t}\n\n\t\tvar done,\n\t\t\tversion = grunt.config( \"pkg.version\" );\n\t\tif ( !rpreversion.test( version ) ) {\n\t\t\tgrunt.fatal( \"Existing version is not a pre version: \" + version );\n\t\t\treturn;\n\t\t}\n\t\tversion = version.replace( rpreversion, \"$1\" );\n\n\t\tdone = this.async();\n\t\texec( \"git diff --quiet HEAD\", function( err ) {\n\t\t\tif ( err ) {\n\t\t\t\tgrunt.fatal( \"The working directory should be clean when releasing. Commit or stash changes.\" );\n\t\t\t\treturn;\n\t\t\t}\n\t\t\t// Build to dist directories along with a map and tag the release\n\t\t\tgrunt.task.run([\n\t\t\t\t// Commit new version\n\t\t\t\t\"version:\" + version,\n\t\t\t\t// Tag new version\n\t\t\t\t\"tag:\" + version,\n\t\t\t\t// Commit next version\n\t\t\t\t\"version:\" + next\n\t\t\t]);\n\t\t\tdone();\n\t\t});\n\t});\n};\n"
  },
  {
    "path": "flowable-ui-web/task/libs/sizzle_1.10.16/tasks/tag.js",
    "content": "\"use strict\";\n\nvar exec = require( \"child_process\" ).exec;\n\nmodule.exports = function( grunt ) {\n\tgrunt.registerTask( \"tag\", \"Tag the specified version\", function( version ) {\n\t\texec( \"git tag \" + version, this.async() );\n\t});\n};\n"
  },
  {
    "path": "flowable-ui-web/task/libs/sizzle_1.10.16/tasks/version.js",
    "content": "\"use strict\";\n\nvar exec = require( \"child_process\" ).exec;\n\nmodule.exports = function( grunt ) {\n\tgrunt.registerTask( \"version\", \"Commit a new version\", function( version ) {\n\t\tif ( !/\\d\\.\\d+\\.\\d+(?:-pre)?/.test( version ) ) {\n\t\t\tgrunt.fatal( \"Version must follow semver release format: \" + version );\n\t\t\treturn;\n\t\t}\n\n\t\tvar done = this.async(),\n\t\t\tfiles = grunt.config( \"version.files\" ),\n\t\t\trversion = /(\"version\":\\s*\")[^\"]+/;\n\n\t\t// Update version in specified files\n\t\tfiles.forEach(function( filename ) {\n\t\t\tvar text = grunt.file.read( filename );\n\t\t\ttext = text.replace( rversion, \"$1\" + version );\n\t\t\tgrunt.file.write( filename, text );\n\t\t});\n\n\t\t// Add files to git index\n\t\texec( \"git add -A\", function( err ) {\n\t\t\tif ( err ) {\n\t\t\t\tgrunt.fatal( err );\n\t\t\t\treturn;\n\t\t\t}\n\t\t\t// Commit next pre version\n\t\t\tgrunt.config( \"pkg.version\", version );\n\t\t\tgrunt.task.run([ \"build\", \"uglify\", \"dist\", \"commit:'Update version to \" + version + \"'\" ]);\n\t\t\tdone();\n\t\t});\n\t});\n};\n"
  },
  {
    "path": "flowable-ui-web/task/libs/sizzle_1.10.16/test/data/empty.js",
    "content": ""
  },
  {
    "path": "flowable-ui-web/task/libs/sizzle_1.10.16/test/data/mixed_sort.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />\n\t<script>var QUnit = parent.QUnit</script>\n\t<script src=\"testinit.js\"></script>\n\t<script src=\"../../dist/sizzle.js\"></script>\n</head>\n<body>\n\t<script>\n\t\tvar doc = parent.document,\n\t\t\tunframed = [ doc.getElementById( \"qunit-fixture\" ), doc.body, doc.documentElement ],\n\t\t\tframed = Sizzle( \"*\" );\n\n\t\twindow.parent.iframeCallback(\n\t\t\tSizzle.uniqueSort( unframed.concat( framed ) ),\n\t\t\tframed.concat( unframed.reverse() ),\n\t\t\t\"Mixed array was sorted correctly\"\n\t\t);\n\t</script>\n</body>\n</html>\n"
  },
  {
    "path": "flowable-ui-web/task/libs/sizzle_1.10.16/test/data/testinit.js",
    "content": "var fireNative,\n\tjQuery = this.jQuery || \"jQuery\", // For testing .noConflict()\n\t$ = this.$ || \"$\",\n\toriginaljQuery = jQuery,\n\toriginal$ = $;\n\n(function() {\n\t// Config parameter to force basic code paths\n\tQUnit.config.urlConfig.push({\n\t\tid: \"basic\",\n\t\tlabel: \"Bypass optimizations\",\n\t\ttooltip: \"Force use of the most basic code by disabling native querySelectorAll; contains; compareDocumentPosition\"\n\t});\n\tif ( QUnit.urlParams.basic ) {\n\t\tdocument.querySelectorAll = null;\n\t\tdocument.documentElement.contains = null;\n\t\tdocument.documentElement.compareDocumentPosition = null;\n\t\t// Return array of length two to pass assertion\n\t\t// But support should be false as its not native\n\t\tdocument.getElementsByClassName = function() { return [ 0, 1 ]; };\n\t}\n})();\n\n/**\n * Returns an array of elements with the given IDs\n * @example q(\"main\", \"foo\", \"bar\")\n * @result [<div id=\"main\">, <span id=\"foo\">, <input id=\"bar\">]\n */\nfunction q() {\n\tvar r = [],\n\t\ti = 0;\n\n\tfor ( ; i < arguments.length; i++ ) {\n\t\tr.push( document.getElementById( arguments[i] ) );\n\t}\n\treturn r;\n}\n\n/**\n * Asserts that a select matches the given IDs\n * @param {String} a - Assertion name\n * @param {String} b - Sizzle selector\n * @param {String} c - Array of ids to construct what is expected\n * @example t(\"Check for something\", \"//[a]\", [\"foo\", \"baar\"]);\n * @result returns true if \"//[a]\" return two elements with the IDs 'foo' and 'baar'\n */\nfunction t( a, b, c ) {\n\tvar f = Sizzle(b),\n\t\ts = \"\",\n\t\ti = 0;\n\n\tfor ( ; i < f.length; i++ ) {\n\t\ts += ( s && \",\" ) + '\"' + f[ i ].id + '\"';\n\t}\n\n\tdeepEqual(f, q.apply( q, c ), a + \" (\" + b + \")\");\n}\n\n/**\n * Add random number to url to stop caching\n *\n * @example url(\"data/test.html\")\n * @result \"data/test.html?10538358428943\"\n *\n * @example url(\"data/test.php?foo=bar\")\n * @result \"data/test.php?foo=bar&10538358345554\"\n */\nfunction url( value ) {\n\treturn value + (/\\?/.test(value) ? \"&\" : \"?\") + new Date().getTime() + \"\" + parseInt(Math.random()*100000);\n}\n\nvar createWithFriesXML = function() {\n\tvar string = '<?xml version=\"1.0\" encoding=\"UTF-8\"?> \\\n\t<soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\" \\\n\t\txmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" \\\n\t\txmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"> \\\n\t\t<soap:Body> \\\n\t\t\t<jsconf xmlns=\"http://www.example.com/ns1\"> \\\n\t\t\t\t<response xmlns:ab=\"http://www.example.com/ns2\"> \\\n\t\t\t\t\t<meta> \\\n\t\t\t\t\t\t<component id=\"seite1\" class=\"component\"> \\\n\t\t\t\t\t\t\t<properties xmlns:cd=\"http://www.example.com/ns3\"> \\\n\t\t\t\t\t\t\t\t<property name=\"prop1\"> \\\n\t\t\t\t\t\t\t\t\t<thing /> \\\n\t\t\t\t\t\t\t\t\t<value>1</value> \\\n\t\t\t\t\t\t\t\t</property> \\\n\t\t\t\t\t\t\t\t<property name=\"prop2\"> \\\n\t\t\t\t\t\t\t\t\t<thing att=\"something\" /> \\\n\t\t\t\t\t\t\t\t</property> \\\n\t\t\t\t\t\t\t\t<foo_bar>foo</foo_bar> \\\n\t\t\t\t\t\t\t</properties> \\\n\t\t\t\t\t\t</component> \\\n\t\t\t\t\t</meta> \\\n\t\t\t\t</response> \\\n\t\t\t</jsconf> \\\n\t\t</soap:Body> \\\n\t</soap:Envelope>';\n\n\treturn jQuery.parseXML( string );\n};\n\nfireNative = document.createEvent ?\n\tfunction( node, type ) {\n\t\tvar event = document.createEvent(\"HTMLEvents\");\n\t\tevent.initEvent( type, true, true );\n\t\tnode.dispatchEvent( event );\n\t} :\n\tfunction( node, type ) {\n\t\tvar event = document.createEventObject();\n\t\tnode.fireEvent( \"on\" + type, event );\n\t};\n\nfunction testIframeWithCallback( title, fileName, func ) {\n\ttest( title, function() {\n\t\tvar iframe;\n\n\t\tstop();\n\t\twindow.iframeCallback = function() {\n\t\t\tvar self = this,\n\t\t\t\targs = arguments;\n\t\t\tsetTimeout(function() {\n\t\t\t\twindow.iframeCallback = undefined;\n\t\t\t\tiframe.remove();\n\t\t\t\tfunc.apply( self, args );\n\t\t\t\tfunc = function() {};\n\t\t\t\tstart();\n\t\t\t}, 0 );\n\t\t};\n\t\tiframe = jQuery( \"<div/>\" ).css({ position: \"absolute\", width: \"500px\", left: \"-600px\" })\n\t\t\t.append( jQuery( \"<iframe/>\" ).attr( \"src\", url( \"./data/\" + fileName ) ) )\n\t\t\t.appendTo( \"#qunit-fixture\" );\n\t});\n};\nwindow.iframeCallback = undefined;\n\nfunction moduleTeardown() {}\n"
  },
  {
    "path": "flowable-ui-web/task/libs/sizzle_1.10.16/test/index.html",
    "content": "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\" dir=\"ltr\" id=\"html\">\n<head>\n\t<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />\n\t<title>Sizzle Test Suite</title>\n\t<link rel=\"Stylesheet\" media=\"screen\" href=\"libs/qunit/qunit.css\" />\n\t<script type=\"text/javascript\" src=\"libs/qunit/qunit.js\"></script>\n\t<script type=\"text/javascript\" src=\"data/testinit.js\"></script>\n\t<script type=\"text/javascript\" src=\"jquery.js\"></script>\n\t<script type=\"text/javascript\" src=\"../dist/sizzle.js\"></script>\n\t<script type=\"text/javascript\" src=\"unit/selector.js\"></script>\n\t<script type=\"text/javascript\" src=\"unit/utilities.js\"></script>\n\t<script type=\"text/javascript\" src=\"unit/extending.js\"></script>\n</head>\n\n<body id=\"body\">\n\t<div id=\"qunit\"></div>\n\n\t<!-- Test HTML -->\n\t<dl id=\"dl\" style=\"position:absolute;top:-32767px;left:-32767px;width:1px\">\n\t<div id=\"qunit-fixture\">\n\t\t<p id=\"firstp\">See <a id=\"simon1\" href=\"http://simon.incutio.com/archive/2003/03/25/#getElementsBySelector\" rel=\"bookmark\">this blog entry</a> for more information.</p>\n\t\t<p id=\"ap\">\n\t\t\tHere are some [links] in a normal paragraph: <a id=\"google\" href=\"http://www.google.com/\" title=\"Google!\">Google</a>,\n\t\t\t<a id=\"groups\" href=\"http://groups.google.com/\" class=\"GROUPS\">Google Groups (Link)</a>.\n\t\t\tThis link has <code id=\"code1\"><a href=\"http://smin\" id=\"anchor1\">class=\"blog\"</a></code>:\n\t\t\t<a href=\"http://diveintomark.org/\" class=\"blog\" hreflang=\"en\" id=\"mark\">diveintomark</a>\n\n\t\t</p>\n\t\t<div id=\"foo\">\n\t\t\t<p id=\"sndp\">Everything inside the red border is inside a div with <code>id=\"foo\"</code>.</p>\n\t\t\t<p lang=\"en\" id=\"en\">This is a normal link: <a id=\"yahoo\" href=\"http://www.yahoo.com/\" class=\"blogTest\">Yahoo</a></p>\n\t\t\t<p id=\"sap\">This link has <code><a href=\"#2\" id=\"anchor2\">class=\"blog\"</a></code>: <a href=\"http://simon.incutio.com/\" class=\"blog link\" id=\"simon\">Simon Willison's Weblog</a></p>\n\n\t\t</div>\n\t\t<div id=\"nothiddendiv\" style=\"height:1px;background:white;\" class=\"nothiddendiv\">\n\t\t\t<div id=\"nothiddendivchild\"></div>\n\t\t</div>\n\t\t<span id=\"name+value\"></span>\n\t\t<p id=\"first\">Try them out:</p>\n\t\t<ul id=\"firstUL\"></ul>\n\t\t<ol id=\"empty\"><!-- comment --></ol>\n\t\t<form id=\"form\" action=\"formaction\">\n\t\t\t<label for=\"action\" id=\"label-for\">Action:</label>\n\t\t\t<input type=\"text\" name=\"action\" value=\"Test\" id=\"text1\" maxlength=\"30\"/>\n\t\t\t<input type=\"text\" name=\"text2\" value=\"Test\" id=\"text2\" disabled=\"disabled\"/>\n\t\t\t<input type=\"radio\" name=\"radio1\" id=\"radio1\" value=\"on\"/>\n\n\t\t\t<input type=\"radio\" name=\"radio2\" id=\"radio2\" checked=\"checked\"/>\n\t\t\t<input type=\"checkbox\" name=\"check\" id=\"check1\" checked=\"checked\"/>\n\t\t\t<input type=\"checkbox\" id=\"check2\" value=\"on\"/>\n\n\t\t\t<input type=\"hidden\" name=\"hidden\" id=\"hidden1\"/>\n\t\t\t<input type=\"text\" style=\"display:none;\" name=\"foo[bar]\" id=\"hidden2\"/>\n\n\t\t\t<input type=\"text\" id=\"name\" name=\"name\" value=\"name\" />\n\t\t\t<input type=\"search\" id=\"search\" name=\"search\" value=\"search\" />\n\n\t\t\t<button id=\"button\" name=\"button\" type=\"button\">Button</button>\n\n\t\t\t<textarea id=\"area1\" maxlength=\"30\">foobar</textarea>\n\n\t\t\t<select name=\"select1\" id=\"select1\">\n\t\t\t\t<option id=\"option1a\" class=\"emptyopt\" value=\"\">Nothing</option>\n\t\t\t\t<option id=\"option1b\" value=\"1\">1</option>\n\t\t\t\t<option id=\"option1c\" value=\"2\">2</option>\n\t\t\t\t<option id=\"option1d\" value=\"3\">3</option>\n\t\t\t</select>\n\t\t\t<select name=\"select2\" id=\"select2\">\n\t\t\t\t<option id=\"option2a\" class=\"emptyopt\" value=\"\">Nothing</option>\n\t\t\t\t<option id=\"option2b\" value=\"1\">1</option>\n\t\t\t\t<option id=\"option2c\" value=\"2\">2</option>\n\t\t\t\t<option id=\"option2d\" selected=\"selected\" value=\"3\">3</option>\n\t\t\t</select>\n\t\t\t<select name=\"select3\" id=\"select3\" multiple=\"multiple\">\n\t\t\t\t<option id=\"option3a\" class=\"emptyopt\" value=\"\">Nothing</option>\n\t\t\t\t<option id=\"option3b\" selected=\"selected\" value=\"1\">1</option>\n\t\t\t\t<option id=\"option3c\" selected=\"selected\" value=\"2\">2</option>\n\t\t\t\t<option id=\"option3d\" value=\"3\">3</option>\n\t\t\t\t<option id=\"option3e\">no value</option>\n\t\t\t</select>\n\t\t\t<select name=\"select4\" id=\"select4\" multiple=\"multiple\">\n\t\t\t\t<optgroup disabled=\"disabled\">\n\t\t\t\t\t<option id=\"option4a\" class=\"emptyopt\" value=\"\">Nothing</option>\n\t\t\t\t\t<option id=\"option4b\" disabled=\"disabled\" selected=\"selected\" value=\"1\">1</option>\n\t\t\t\t\t<option id=\"option4c\" selected=\"selected\" value=\"2\">2</option>\n\t\t\t\t</optgroup>\n\t\t\t\t<option selected=\"selected\" disabled=\"disabled\" id=\"option4d\" value=\"3\">3</option>\n\t\t\t\t<option id=\"option4e\">no value</option>\n\t\t\t</select>\n\t\t\t<select name=\"select5\" id=\"select5\">\n\t\t\t\t<option id=\"option5a\" value=\"3\">1</option>\n\t\t\t\t<option id=\"option5b\" value=\"2\">2</option>\n\t\t\t\t<option id=\"option5c\" value=\"1\">3</option>\n\t\t\t</select>\n\n\t\t\t<object id=\"object1\" codebase=\"stupid\">\n\t\t\t\t<param name=\"p1\" value=\"x1\" />\n\t\t\t\t<param name=\"p2\" value=\"x2\" />\n\t\t\t</object>\n\n\t\t\t<span id=\"台北Táiběi\"></span>\n\t\t\t<span id=\"台北\" lang=\"中文\"></span>\n\t\t\t<span id=\"utf8class1\" class=\"台北Táiběi 台北\"></span>\n\t\t\t<span id=\"utf8class2\" class=\"台北\"></span>\n\t\t\t<span id=\"foo:bar\" class=\"foo:bar\"><span id=\"foo_descendent\"></span></span>\n\t\t\t<span id=\"test.foo[5]bar\" class=\"test.foo[5]bar\"></span>\n\n\t\t\t<foo_bar id=\"foobar\">test element</foo_bar>\n\t\t</form>\n\t\t<b id=\"floatTest\">Float test.</b>\n\t\t<iframe id=\"iframe\" name=\"iframe\"></iframe>\n\t\t<form id=\"lengthtest\">\n\t\t\t<input type=\"text\" id=\"length\" name=\"test\"/>\n\t\t\t<input type=\"text\" id=\"idTest\" name=\"id\"/>\n\t\t</form>\n\t\t<table id=\"table\"></table>\n\n\t\t<form id=\"name-tests\">\n\t\t\t<!-- Inputs with a grouped name attribute. -->\n\t\t\t<input name=\"types[]\" id=\"types_all\" type=\"checkbox\" value=\"all\" />\n\t\t\t<input name=\"types[]\" id=\"types_anime\" type=\"checkbox\" value=\"anime\" />\n\t\t\t<input name=\"types[]\" id=\"types_movie\" type=\"checkbox\" value=\"movie\" />\n\t\t</form>\n\n\t\t<form id=\"testForm\" action=\"#\" method=\"get\">\n\t\t\t<textarea name=\"T3\" rows=\"2\" cols=\"15\">?\nZ</textarea>\n\t\t\t<input type=\"hidden\" name=\"H1\" value=\"x\" />\n\t\t\t<input type=\"hidden\" name=\"H2\" />\n\t\t\t<input name=\"PWD\" type=\"password\" value=\"\" />\n\t\t\t<input name=\"T1\" type=\"text\" />\n\t\t\t<input name=\"T2\" type=\"text\" value=\"YES\" readonly=\"readonly\" />\n\t\t\t<input type=\"checkbox\" name=\"C1\" value=\"1\" />\n\t\t\t<input type=\"checkbox\" name=\"C2\" />\n\t\t\t<input type=\"radio\" name=\"R1\" value=\"1\" />\n\t\t\t<input type=\"radio\" name=\"R1\" value=\"2\" />\n\t\t\t<input type=\"text\" name=\"My Name\" value=\"me\" />\n\t\t\t<input type=\"reset\" name=\"reset\" value=\"NO\" />\n\t\t\t<select name=\"S1\">\n\t\t\t\t<option value=\"abc\">ABC</option>\n\t\t\t\t<option value=\"abc\">ABC</option>\n\t\t\t\t<option value=\"abc\">ABC</option>\n\t\t\t</select>\n\t\t\t<select name=\"S2\" multiple=\"multiple\" size=\"3\">\n\t\t\t\t<option value=\"abc\">ABC</option>\n\t\t\t\t<option value=\"abc\">ABC</option>\n\t\t\t\t<option value=\"abc\">ABC</option>\n\t\t\t</select>\n\t\t\t<select name=\"S3\">\n\t\t\t\t<option selected=\"selected\">YES</option>\n\t\t\t</select>\n\t\t\t<select name=\"S4\">\n\t\t\t\t<option value=\"\" selected=\"selected\">NO</option>\n\t\t\t</select>\n\t\t\t<input type=\"submit\" name=\"sub1\" value=\"NO\" />\n\t\t\t<input type=\"submit\" name=\"sub2\" value=\"NO\" />\n\t\t\t<input type=\"image\" name=\"sub3\" value=\"NO\" />\n\t\t\t<button name=\"sub4\" type=\"submit\" value=\"NO\">NO</button>\n\t\t\t<input name=\"D1\" type=\"text\" value=\"NO\" disabled=\"disabled\" />\n\t\t\t<input type=\"checkbox\" checked=\"checked\" disabled=\"disabled\" name=\"D2\" value=\"NO\" />\n\t\t\t<input type=\"radio\" name=\"D3\" value=\"NO\" checked=\"checked\" disabled=\"disabled\" />\n\t\t\t<select name=\"D4\" disabled=\"disabled\">\n\t\t\t\t<option selected=\"selected\" value=\"NO\">NO</option>\n\t\t\t</select>\n\t\t\t<input id=\"list-test\" type=\"text\" />\n\t\t\t<datalist id=\"datalist\">\n\t\t\t\t<option value=\"option\"></option>\n\t\t\t</datalist>\n\t\t</form>\n\t\t<div id=\"moretests\">\n\t\t\t<form>\n\t\t\t\t<div id=\"checkedtest\" style=\"display:none;\">\n\t\t\t\t\t<input type=\"radio\" name=\"checkedtestradios\" checked=\"checked\"/>\n\t\t\t\t\t<input type=\"radio\" name=\"checkedtestradios\" value=\"on\"/>\n\t\t\t\t\t<input type=\"checkbox\" name=\"checkedtestcheckboxes\" checked=\"checked\"/>\n\t\t\t\t\t<input type=\"checkbox\" name=\"checkedtestcheckboxes\" />\n\t\t\t\t</div>\n\t\t\t</form>\n\t\t\t<div id=\"nonnodes\"><span>hi</span> there <!-- mon ami --></div>\n\t\t\t<div id=\"t2037\">\n\t\t\t\t<div><div class=\"hidden\">hidden</div></div>\n\t\t\t</div>\n\t\t\t<div id=\"t6652\">\n\t\t\t\t<div></div>\n\t\t\t</div>\n\t\t\t<div id=\"t12087\">\n\t\t\t\t<input type=\"hidden\" id=\"el12087\" data-comma=\"0,1\"/>\n\t\t\t</div>\n\t\t\t<div id=\"no-clone-exception\"><object><embed></embed></object></div>\n\t\t\t<div id=\"names-group\">\n\t\t\t\t<span id=\"name-is-example\" name=\"example\"></span>\n\t\t\t\t<span id=\"name-is-div\" name=\"div\"></span>\n\t\t\t</div>\n\t\t\t<script id=\"script-no-src\"></script>\n\t\t\t<script id=\"script-src\" src=\"data/empty.js\"></script>\n\t\t\t<div id=\"id-name-tests\">\n\t\t\t\t<a id=\"tName1ID\" name=\"tName1\"><span></span></a>\n\t\t\t\t<a id=\"tName2ID\" name=\"tName2\"><span></span></a>\n\t\t\t\t<div id=\"tName1\"><span id=\"tName1-span\">C</span></div>\n\t\t\t</div>\n\t\t</div>\n\n\t\t<div id=\"tabindex-tests\">\n\t\t\t<ol id=\"listWithTabIndex\" tabindex=\"5\">\n\t\t\t\t<li id=\"foodWithNegativeTabIndex\" tabindex=\"-1\">Rice</li>\n\t\t\t\t<li id=\"foodNoTabIndex\">Beans</li>\n\t\t\t\t<li>Blinis</li>\n\t\t\t\t<li>Tofu</li>\n\t\t\t</ol>\n\n\t\t\t<div id=\"divWithNoTabIndex\">I'm hungry. I should...</div>\n\t\t\t<span>...</span><a href=\"#\" id=\"linkWithNoTabIndex\">Eat lots of food</a><span>...</span> |\n\t\t\t<span>...</span><a href=\"#\" id=\"linkWithTabIndex\" tabindex=\"2\">Eat a little food</a><span>...</span> |\n\t\t\t<span>...</span><a href=\"#\" id=\"linkWithNegativeTabIndex\" tabindex=\"-1\">Eat no food</a><span>...</span>\n\t\t\t<span>...</span><a id=\"linkWithNoHrefWithNoTabIndex\">Eat a burger</a><span>...</span>\n\t\t\t<span>...</span><a id=\"linkWithNoHrefWithTabIndex\" tabindex=\"1\">Eat some funyuns</a><span>...</span>\n\t\t\t<span>...</span><a id=\"linkWithNoHrefWithNegativeTabIndex\" tabindex=\"-1\">Eat some funyuns</a><span>...</span>\n\t\t</div>\n\n\t\t<div id=\"liveHandlerOrder\">\n\t\t\t<span id=\"liveSpan1\"><a href=\"#\" id=\"liveLink1\"></a></span>\n\t\t\t<span id=\"liveSpan2\"><a href=\"#\" id=\"liveLink2\"></a></span>\n\t\t</div>\n\n\t\t<div id=\"siblingTest\">\n\t\t\t<em id=\"siblingfirst\">1</em>\n\t\t\t<em id=\"siblingnext\">2</em>\n\t\t\t<em id=\"siblingthird\">\n\t\t\t\t<em id=\"siblingchild\">\n\t\t\t\t\t<em id=\"siblinggrandchild\">\n\t\t\t\t\t\t<em id=\"siblinggreatgrandchild\"></em>\n\t\t\t\t\t</em>\n\t\t\t\t</em>\n\t\t\t</em>\n\t\t\t<span id=\"siblingspan\"></span>\n\t\t</div>​\n\t</div>\n\t</dl>\n\t<br id=\"last\"/>\n</body>\n</html>\n"
  },
  {
    "path": "flowable-ui-web/task/libs/sizzle_1.10.16/test/jquery.js",
    "content": "/*!\n * jQuery JavaScript Library v1.9.1\n * http://jquery.com/\n *\n * Includes Sizzle.js\n * http://sizzlejs.com/\n *\n * Copyright 2005, 2012 jQuery Foundation, Inc. and other contributors\n * Released under the MIT license\n * http://jquery.org/license\n *\n * Date: 2013-2-4\n */\n(function( window, undefined ) {\n\n// Can't do this because several apps including ASP.NET trace\n// the stack via arguments.caller.callee and Firefox dies if\n// you try to trace through \"use strict\" call chains. (#13335)\n// Support: Firefox 18+\n//\"use strict\";\nvar\n\t// The deferred used on DOM ready\n\treadyList,\n\n\t// A central reference to the root jQuery(document)\n\trootjQuery,\n\n\t// Support: IE<9\n\t// For `typeof node.method` instead of `node.method !== undefined`\n\tcore_strundefined = typeof undefined,\n\n\t// Use the correct document accordingly with window argument (sandbox)\n\tdocument = window.document,\n\tlocation = window.location,\n\n\t// Map over jQuery in case of overwrite\n\t_jQuery = window.jQuery,\n\n\t// Map over the $ in case of overwrite\n\t_$ = window.$,\n\n\t// [[Class]] -> type pairs\n\tclass2type = {},\n\n\t// List of deleted data cache ids, so we can reuse them\n\tcore_deletedIds = [],\n\n\tcore_version = \"1.9.1\",\n\n\t// Save a reference to some core methods\n\tcore_concat = core_deletedIds.concat,\n\tcore_push = core_deletedIds.push,\n\tcore_slice = core_deletedIds.slice,\n\tcore_indexOf = core_deletedIds.indexOf,\n\tcore_toString = class2type.toString,\n\tcore_hasOwn = class2type.hasOwnProperty,\n\tcore_trim = core_version.trim,\n\n\t// Define a local copy of jQuery\n\tjQuery = function( selector, context ) {\n\t\t// The jQuery object is actually just the init constructor 'enhanced'\n\t\treturn new jQuery.fn.init( selector, context, rootjQuery );\n\t},\n\n\t// Used for matching numbers\n\tcore_pnum = /[+-]?(?:\\d*\\.|)\\d+(?:[eE][+-]?\\d+|)/.source,\n\n\t// Used for splitting on whitespace\n\tcore_rnotwhite = /\\S+/g,\n\n\t// Make sure we trim BOM and NBSP (here's looking at you, Safari 5.0 and IE)\n\trtrim = /^[\\s\\uFEFF\\xA0]+|[\\s\\uFEFF\\xA0]+$/g,\n\n\t// A simple way to check for HTML strings\n\t// Prioritize #id over <tag> to avoid XSS via location.hash (#9521)\n\t// Strict HTML recognition (#11290: must start with <)\n\trquickExpr = /^(?:(<[\\w\\W]+>)[^>]*|#([\\w-]*))$/,\n\n\t// Match a standalone tag\n\trsingleTag = /^<(\\w+)\\s*\\/?>(?:<\\/\\1>|)$/,\n\n\t// JSON RegExp\n\trvalidchars = /^[\\],:{}\\s]*$/,\n\trvalidbraces = /(?:^|:|,)(?:\\s*\\[)+/g,\n\trvalidescape = /\\\\(?:[\"\\\\\\/bfnrt]|u[\\da-fA-F]{4})/g,\n\trvalidtokens = /\"[^\"\\\\\\r\\n]*\"|true|false|null|-?(?:\\d+\\.|)\\d+(?:[eE][+-]?\\d+|)/g,\n\n\t// Matches dashed string for camelizing\n\trmsPrefix = /^-ms-/,\n\trdashAlpha = /-([\\da-z])/gi,\n\n\t// Used by jQuery.camelCase as callback to replace()\n\tfcamelCase = function( all, letter ) {\n\t\treturn letter.toUpperCase();\n\t},\n\n\t// The ready event handler\n\tcompleted = function( event ) {\n\n\t\t// readyState === \"complete\" is good enough for us to call the dom ready in oldIE\n\t\tif ( document.addEventListener || event.type === \"load\" || document.readyState === \"complete\" ) {\n\t\t\tdetach();\n\t\t\tjQuery.ready();\n\t\t}\n\t},\n\t// Clean-up method for dom ready events\n\tdetach = function() {\n\t\tif ( document.addEventListener ) {\n\t\t\tdocument.removeEventListener( \"DOMContentLoaded\", completed, false );\n\t\t\twindow.removeEventListener( \"load\", completed, false );\n\n\t\t} else {\n\t\t\tdocument.detachEvent( \"onreadystatechange\", completed );\n\t\t\twindow.detachEvent( \"onload\", completed );\n\t\t}\n\t};\n\njQuery.fn = jQuery.prototype = {\n\t// The current version of jQuery being used\n\tjquery: core_version,\n\n\tconstructor: jQuery,\n\tinit: function( selector, context, rootjQuery ) {\n\t\tvar match, elem;\n\n\t\t// HANDLE: $(\"\"), $(null), $(undefined), $(false)\n\t\tif ( !selector ) {\n\t\t\treturn this;\n\t\t}\n\n\t\t// Handle HTML strings\n\t\tif ( typeof selector === \"string\" ) {\n\t\t\tif ( selector.charAt(0) === \"<\" && selector.charAt( selector.length - 1 ) === \">\" && selector.length >= 3 ) {\n\t\t\t\t// Assume that strings that start and end with <> are HTML and skip the regex check\n\t\t\t\tmatch = [ null, selector, null ];\n\n\t\t\t} else {\n\t\t\t\tmatch = rquickExpr.exec( selector );\n\t\t\t}\n\n\t\t\t// Match html or make sure no context is specified for #id\n\t\t\tif ( match && (match[1] || !context) ) {\n\n\t\t\t\t// HANDLE: $(html) -> $(array)\n\t\t\t\tif ( match[1] ) {\n\t\t\t\t\tcontext = context instanceof jQuery ? context[0] : context;\n\n\t\t\t\t\t// scripts is true for back-compat\n\t\t\t\t\tjQuery.merge( this, jQuery.parseHTML(\n\t\t\t\t\t\tmatch[1],\n\t\t\t\t\t\tcontext && context.nodeType ? context.ownerDocument || context : document,\n\t\t\t\t\t\ttrue\n\t\t\t\t\t) );\n\n\t\t\t\t\t// HANDLE: $(html, props)\n\t\t\t\t\tif ( rsingleTag.test( match[1] ) && jQuery.isPlainObject( context ) ) {\n\t\t\t\t\t\tfor ( match in context ) {\n\t\t\t\t\t\t\t// Properties of context are called as methods if possible\n\t\t\t\t\t\t\tif ( jQuery.isFunction( this[ match ] ) ) {\n\t\t\t\t\t\t\t\tthis[ match ]( context[ match ] );\n\n\t\t\t\t\t\t\t// ...and otherwise set as attributes\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tthis.attr( match, context[ match ] );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\treturn this;\n\n\t\t\t\t// HANDLE: $(#id)\n\t\t\t\t} else {\n\t\t\t\t\telem = document.getElementById( match[2] );\n\n\t\t\t\t\t// Check parentNode to catch when Blackberry 4.6 returns\n\t\t\t\t\t// nodes that are no longer in the document #6963\n\t\t\t\t\tif ( elem && elem.parentNode ) {\n\t\t\t\t\t\t// Handle the case where IE and Opera return items\n\t\t\t\t\t\t// by name instead of ID\n\t\t\t\t\t\tif ( elem.id !== match[2] ) {\n\t\t\t\t\t\t\treturn rootjQuery.find( selector );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Otherwise, we inject the element directly into the jQuery object\n\t\t\t\t\t\tthis.length = 1;\n\t\t\t\t\t\tthis[0] = elem;\n\t\t\t\t\t}\n\n\t\t\t\t\tthis.context = document;\n\t\t\t\t\tthis.selector = selector;\n\t\t\t\t\treturn this;\n\t\t\t\t}\n\n\t\t\t// HANDLE: $(expr, $(...))\n\t\t\t} else if ( !context || context.jquery ) {\n\t\t\t\treturn ( context || rootjQuery ).find( selector );\n\n\t\t\t// HANDLE: $(expr, context)\n\t\t\t// (which is just equivalent to: $(context).find(expr)\n\t\t\t} else {\n\t\t\t\treturn this.constructor( context ).find( selector );\n\t\t\t}\n\n\t\t// HANDLE: $(DOMElement)\n\t\t} else if ( selector.nodeType ) {\n\t\t\tthis.context = this[0] = selector;\n\t\t\tthis.length = 1;\n\t\t\treturn this;\n\n\t\t// HANDLE: $(function)\n\t\t// Shortcut for document ready\n\t\t} else if ( jQuery.isFunction( selector ) ) {\n\t\t\treturn rootjQuery.ready( selector );\n\t\t}\n\n\t\tif ( selector.selector !== undefined ) {\n\t\t\tthis.selector = selector.selector;\n\t\t\tthis.context = selector.context;\n\t\t}\n\n\t\treturn jQuery.makeArray( selector, this );\n\t},\n\n\t// Start with an empty selector\n\tselector: \"\",\n\n\t// The default length of a jQuery object is 0\n\tlength: 0,\n\n\t// The number of elements contained in the matched element set\n\tsize: function() {\n\t\treturn this.length;\n\t},\n\n\ttoArray: function() {\n\t\treturn core_slice.call( this );\n\t},\n\n\t// Get the Nth element in the matched element set OR\n\t// Get the whole matched element set as a clean array\n\tget: function( num ) {\n\t\treturn num == null ?\n\n\t\t\t// Return a 'clean' array\n\t\t\tthis.toArray() :\n\n\t\t\t// Return just the object\n\t\t\t( num < 0 ? this[ this.length + num ] : this[ num ] );\n\t},\n\n\t// Take an array of elements and push it onto the stack\n\t// (returning the new matched element set)\n\tpushStack: function( elems ) {\n\n\t\t// Build a new jQuery matched element set\n\t\tvar ret = jQuery.merge( this.constructor(), elems );\n\n\t\t// Add the old object onto the stack (as a reference)\n\t\tret.prevObject = this;\n\t\tret.context = this.context;\n\n\t\t// Return the newly-formed element set\n\t\treturn ret;\n\t},\n\n\t// Execute a callback for every element in the matched set.\n\t// (You can seed the arguments with an array of args, but this is\n\t// only used internally.)\n\teach: function( callback, args ) {\n\t\treturn jQuery.each( this, callback, args );\n\t},\n\n\tready: function( fn ) {\n\t\t// Add the callback\n\t\tjQuery.ready.promise().done( fn );\n\n\t\treturn this;\n\t},\n\n\tslice: function() {\n\t\treturn this.pushStack( core_slice.apply( this, arguments ) );\n\t},\n\n\tfirst: function() {\n\t\treturn this.eq( 0 );\n\t},\n\n\tlast: function() {\n\t\treturn this.eq( -1 );\n\t},\n\n\teq: function( i ) {\n\t\tvar len = this.length,\n\t\t\tj = +i + ( i < 0 ? len : 0 );\n\t\treturn this.pushStack( j >= 0 && j < len ? [ this[j] ] : [] );\n\t},\n\n\tmap: function( callback ) {\n\t\treturn this.pushStack( jQuery.map(this, function( elem, i ) {\n\t\t\treturn callback.call( elem, i, elem );\n\t\t}));\n\t},\n\n\tend: function() {\n\t\treturn this.prevObject || this.constructor(null);\n\t},\n\n\t// For internal use only.\n\t// Behaves like an Array's method, not like a jQuery method.\n\tpush: core_push,\n\tsort: [].sort,\n\tsplice: [].splice\n};\n\n// Give the init function the jQuery prototype for later instantiation\njQuery.fn.init.prototype = jQuery.fn;\n\njQuery.extend = jQuery.fn.extend = function() {\n\tvar src, copyIsArray, copy, name, options, clone,\n\t\ttarget = arguments[0] || {},\n\t\ti = 1,\n\t\tlength = arguments.length,\n\t\tdeep = false;\n\n\t// Handle a deep copy situation\n\tif ( typeof target === \"boolean\" ) {\n\t\tdeep = target;\n\t\ttarget = arguments[1] || {};\n\t\t// skip the boolean and the target\n\t\ti = 2;\n\t}\n\n\t// Handle case when target is a string or something (possible in deep copy)\n\tif ( typeof target !== \"object\" && !jQuery.isFunction(target) ) {\n\t\ttarget = {};\n\t}\n\n\t// extend jQuery itself if only one argument is passed\n\tif ( length === i ) {\n\t\ttarget = this;\n\t\t--i;\n\t}\n\n\tfor ( ; i < length; i++ ) {\n\t\t// Only deal with non-null/undefined values\n\t\tif ( (options = arguments[ i ]) != null ) {\n\t\t\t// Extend the base object\n\t\t\tfor ( name in options ) {\n\t\t\t\tsrc = target[ name ];\n\t\t\t\tcopy = options[ name ];\n\n\t\t\t\t// Prevent never-ending loop\n\t\t\t\tif ( target === copy ) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\t// Recurse if we're merging plain objects or arrays\n\t\t\t\tif ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {\n\t\t\t\t\tif ( copyIsArray ) {\n\t\t\t\t\t\tcopyIsArray = false;\n\t\t\t\t\t\tclone = src && jQuery.isArray(src) ? src : [];\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\tclone = src && jQuery.isPlainObject(src) ? src : {};\n\t\t\t\t\t}\n\n\t\t\t\t\t// Never move original objects, clone them\n\t\t\t\t\ttarget[ name ] = jQuery.extend( deep, clone, copy );\n\n\t\t\t\t// Don't bring in undefined values\n\t\t\t\t} else if ( copy !== undefined ) {\n\t\t\t\t\ttarget[ name ] = copy;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Return the modified object\n\treturn target;\n};\n\njQuery.extend({\n\tnoConflict: function( deep ) {\n\t\tif ( window.$ === jQuery ) {\n\t\t\twindow.$ = _$;\n\t\t}\n\n\t\tif ( deep && window.jQuery === jQuery ) {\n\t\t\twindow.jQuery = _jQuery;\n\t\t}\n\n\t\treturn jQuery;\n\t},\n\n\t// Is the DOM ready to be used? Set to true once it occurs.\n\tisReady: false,\n\n\t// A counter to track how many items to wait for before\n\t// the ready event fires. See #6781\n\treadyWait: 1,\n\n\t// Hold (or release) the ready event\n\tholdReady: function( hold ) {\n\t\tif ( hold ) {\n\t\t\tjQuery.readyWait++;\n\t\t} else {\n\t\t\tjQuery.ready( true );\n\t\t}\n\t},\n\n\t// Handle when the DOM is ready\n\tready: function( wait ) {\n\n\t\t// Abort if there are pending holds or we're already ready\n\t\tif ( wait === true ? --jQuery.readyWait : jQuery.isReady ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).\n\t\tif ( !document.body ) {\n\t\t\treturn setTimeout( jQuery.ready );\n\t\t}\n\n\t\t// Remember that the DOM is ready\n\t\tjQuery.isReady = true;\n\n\t\t// If a normal DOM Ready event fired, decrement, and wait if need be\n\t\tif ( wait !== true && --jQuery.readyWait > 0 ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// If there are functions bound, to execute\n\t\treadyList.resolveWith( document, [ jQuery ] );\n\n\t\t// Trigger any bound ready events\n\t\tif ( jQuery.fn.trigger ) {\n\t\t\tjQuery( document ).trigger(\"ready\").off(\"ready\");\n\t\t}\n\t},\n\n\t// See test/unit/core.js for details concerning isFunction.\n\t// Since version 1.3, DOM methods and functions like alert\n\t// aren't supported. They return false on IE (#2968).\n\tisFunction: function( obj ) {\n\t\treturn jQuery.type(obj) === \"function\";\n\t},\n\n\tisArray: Array.isArray || function( obj ) {\n\t\treturn jQuery.type(obj) === \"array\";\n\t},\n\n\tisWindow: function( obj ) {\n\t\treturn obj != null && obj == obj.window;\n\t},\n\n\tisNumeric: function( obj ) {\n\t\treturn !isNaN( parseFloat(obj) ) && isFinite( obj );\n\t},\n\n\ttype: function( obj ) {\n\t\tif ( obj == null ) {\n\t\t\treturn String( obj );\n\t\t}\n\t\treturn typeof obj === \"object\" || typeof obj === \"function\" ?\n\t\t\tclass2type[ core_toString.call(obj) ] || \"object\" :\n\t\t\ttypeof obj;\n\t},\n\n\tisPlainObject: function( obj ) {\n\t\t// Must be an Object.\n\t\t// Because of IE, we also have to check the presence of the constructor property.\n\t\t// Make sure that DOM nodes and window objects don't pass through, as well\n\t\tif ( !obj || jQuery.type(obj) !== \"object\" || obj.nodeType || jQuery.isWindow( obj ) ) {\n\t\t\treturn false;\n\t\t}\n\n\t\ttry {\n\t\t\t// Not own constructor property must be Object\n\t\t\tif ( obj.constructor &&\n\t\t\t\t!core_hasOwn.call(obj, \"constructor\") &&\n\t\t\t\t!core_hasOwn.call(obj.constructor.prototype, \"isPrototypeOf\") ) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t} catch ( e ) {\n\t\t\t// IE8,9 Will throw exceptions on certain host objects #9897\n\t\t\treturn false;\n\t\t}\n\n\t\t// Own properties are enumerated firstly, so to speed up,\n\t\t// if last one is own, then all properties are own.\n\n\t\tvar key;\n\t\tfor ( key in obj ) {}\n\n\t\treturn key === undefined || core_hasOwn.call( obj, key );\n\t},\n\n\tisEmptyObject: function( obj ) {\n\t\tvar name;\n\t\tfor ( name in obj ) {\n\t\t\treturn false;\n\t\t}\n\t\treturn true;\n\t},\n\n\terror: function( msg ) {\n\t\tthrow new Error( msg );\n\t},\n\n\t// data: string of html\n\t// context (optional): If specified, the fragment will be created in this context, defaults to document\n\t// keepScripts (optional): If true, will include scripts passed in the html string\n\tparseHTML: function( data, context, keepScripts ) {\n\t\tif ( !data || typeof data !== \"string\" ) {\n\t\t\treturn null;\n\t\t}\n\t\tif ( typeof context === \"boolean\" ) {\n\t\t\tkeepScripts = context;\n\t\t\tcontext = false;\n\t\t}\n\t\tcontext = context || document;\n\n\t\tvar parsed = rsingleTag.exec( data ),\n\t\t\tscripts = !keepScripts && [];\n\n\t\t// Single tag\n\t\tif ( parsed ) {\n\t\t\treturn [ context.createElement( parsed[1] ) ];\n\t\t}\n\n\t\tparsed = jQuery.buildFragment( [ data ], context, scripts );\n\t\tif ( scripts ) {\n\t\t\tjQuery( scripts ).remove();\n\t\t}\n\t\treturn jQuery.merge( [], parsed.childNodes );\n\t},\n\n\tparseJSON: function( data ) {\n\t\t// Attempt to parse using the native JSON parser first\n\t\tif ( window.JSON && window.JSON.parse ) {\n\t\t\treturn window.JSON.parse( data );\n\t\t}\n\n\t\tif ( data === null ) {\n\t\t\treturn data;\n\t\t}\n\n\t\tif ( typeof data === \"string\" ) {\n\n\t\t\t// Make sure leading/trailing whitespace is removed (IE can't handle it)\n\t\t\tdata = jQuery.trim( data );\n\n\t\t\tif ( data ) {\n\t\t\t\t// Make sure the incoming data is actual JSON\n\t\t\t\t// Logic borrowed from http://json.org/json2.js\n\t\t\t\tif ( rvalidchars.test( data.replace( rvalidescape, \"@\" )\n\t\t\t\t\t.replace( rvalidtokens, \"]\" )\n\t\t\t\t\t.replace( rvalidbraces, \"\")) ) {\n\n\t\t\t\t\treturn ( new Function( \"return \" + data ) )();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tjQuery.error( \"Invalid JSON: \" + data );\n\t},\n\n\t// Cross-browser xml parsing\n\tparseXML: function( data ) {\n\t\tvar xml, tmp;\n\t\tif ( !data || typeof data !== \"string\" ) {\n\t\t\treturn null;\n\t\t}\n\t\ttry {\n\t\t\tif ( window.DOMParser ) { // Standard\n\t\t\t\ttmp = new DOMParser();\n\t\t\t\txml = tmp.parseFromString( data , \"text/xml\" );\n\t\t\t} else { // IE\n\t\t\t\txml = new ActiveXObject( \"Microsoft.XMLDOM\" );\n\t\t\t\txml.async = \"false\";\n\t\t\t\txml.loadXML( data );\n\t\t\t}\n\t\t} catch( e ) {\n\t\t\txml = undefined;\n\t\t}\n\t\tif ( !xml || !xml.documentElement || xml.getElementsByTagName( \"parsererror\" ).length ) {\n\t\t\tjQuery.error( \"Invalid XML: \" + data );\n\t\t}\n\t\treturn xml;\n\t},\n\n\tnoop: function() {},\n\n\t// Evaluates a script in a global context\n\t// Workarounds based on findings by Jim Driscoll\n\t// http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context\n\tglobalEval: function( data ) {\n\t\tif ( data && jQuery.trim( data ) ) {\n\t\t\t// We use execScript on Internet Explorer\n\t\t\t// We use an anonymous function so that context is window\n\t\t\t// rather than jQuery in Firefox\n\t\t\t( window.execScript || function( data ) {\n\t\t\t\twindow[ \"eval\" ].call( window, data );\n\t\t\t} )( data );\n\t\t}\n\t},\n\n\t// Convert dashed to camelCase; used by the css and data modules\n\t// Microsoft forgot to hump their vendor prefix (#9572)\n\tcamelCase: function( string ) {\n\t\treturn string.replace( rmsPrefix, \"ms-\" ).replace( rdashAlpha, fcamelCase );\n\t},\n\n\tnodeName: function( elem, name ) {\n\t\treturn elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase();\n\t},\n\n\t// args is for internal usage only\n\teach: function( obj, callback, args ) {\n\t\tvar value,\n\t\t\ti = 0,\n\t\t\tlength = obj.length,\n\t\t\tisArray = isArraylike( obj );\n\n\t\tif ( args ) {\n\t\t\tif ( isArray ) {\n\t\t\t\tfor ( ; i < length; i++ ) {\n\t\t\t\t\tvalue = callback.apply( obj[ i ], args );\n\n\t\t\t\t\tif ( value === false ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tfor ( i in obj ) {\n\t\t\t\t\tvalue = callback.apply( obj[ i ], args );\n\n\t\t\t\t\tif ( value === false ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t// A special, fast, case for the most common use of each\n\t\t} else {\n\t\t\tif ( isArray ) {\n\t\t\t\tfor ( ; i < length; i++ ) {\n\t\t\t\t\tvalue = callback.call( obj[ i ], i, obj[ i ] );\n\n\t\t\t\t\tif ( value === false ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tfor ( i in obj ) {\n\t\t\t\t\tvalue = callback.call( obj[ i ], i, obj[ i ] );\n\n\t\t\t\t\tif ( value === false ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn obj;\n\t},\n\n\t// Use native String.trim function wherever possible\n\ttrim: core_trim && !core_trim.call(\"\\uFEFF\\xA0\") ?\n\t\tfunction( text ) {\n\t\t\treturn text == null ?\n\t\t\t\t\"\" :\n\t\t\t\tcore_trim.call( text );\n\t\t} :\n\n\t\t// Otherwise use our own trimming functionality\n\t\tfunction( text ) {\n\t\t\treturn text == null ?\n\t\t\t\t\"\" :\n\t\t\t\t( text + \"\" ).replace( rtrim, \"\" );\n\t\t},\n\n\t// results is for internal usage only\n\tmakeArray: function( arr, results ) {\n\t\tvar ret = results || [];\n\n\t\tif ( arr != null ) {\n\t\t\tif ( isArraylike( Object(arr) ) ) {\n\t\t\t\tjQuery.merge( ret,\n\t\t\t\t\ttypeof arr === \"string\" ?\n\t\t\t\t\t[ arr ] : arr\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\tcore_push.call( ret, arr );\n\t\t\t}\n\t\t}\n\n\t\treturn ret;\n\t},\n\n\tinArray: function( elem, arr, i ) {\n\t\tvar len;\n\n\t\tif ( arr ) {\n\t\t\tif ( core_indexOf ) {\n\t\t\t\treturn core_indexOf.call( arr, elem, i );\n\t\t\t}\n\n\t\t\tlen = arr.length;\n\t\t\ti = i ? i < 0 ? Math.max( 0, len + i ) : i : 0;\n\n\t\t\tfor ( ; i < len; i++ ) {\n\t\t\t\t// Skip accessing in sparse arrays\n\t\t\t\tif ( i in arr && arr[ i ] === elem ) {\n\t\t\t\t\treturn i;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn -1;\n\t},\n\n\tmerge: function( first, second ) {\n\t\tvar l = second.length,\n\t\t\ti = first.length,\n\t\t\tj = 0;\n\n\t\tif ( typeof l === \"number\" ) {\n\t\t\tfor ( ; j < l; j++ ) {\n\t\t\t\tfirst[ i++ ] = second[ j ];\n\t\t\t}\n\t\t} else {\n\t\t\twhile ( second[j] !== undefined ) {\n\t\t\t\tfirst[ i++ ] = second[ j++ ];\n\t\t\t}\n\t\t}\n\n\t\tfirst.length = i;\n\n\t\treturn first;\n\t},\n\n\tgrep: function( elems, callback, inv ) {\n\t\tvar retVal,\n\t\t\tret = [],\n\t\t\ti = 0,\n\t\t\tlength = elems.length;\n\t\tinv = !!inv;\n\n\t\t// Go through the array, only saving the items\n\t\t// that pass the validator function\n\t\tfor ( ; i < length; i++ ) {\n\t\t\tretVal = !!callback( elems[ i ], i );\n\t\t\tif ( inv !== retVal ) {\n\t\t\t\tret.push( elems[ i ] );\n\t\t\t}\n\t\t}\n\n\t\treturn ret;\n\t},\n\n\t// arg is for internal usage only\n\tmap: function( elems, callback, arg ) {\n\t\tvar value,\n\t\t\ti = 0,\n\t\t\tlength = elems.length,\n\t\t\tisArray = isArraylike( elems ),\n\t\t\tret = [];\n\n\t\t// Go through the array, translating each of the items to their\n\t\tif ( isArray ) {\n\t\t\tfor ( ; i < length; i++ ) {\n\t\t\t\tvalue = callback( elems[ i ], i, arg );\n\n\t\t\t\tif ( value != null ) {\n\t\t\t\t\tret[ ret.length ] = value;\n\t\t\t\t}\n\t\t\t}\n\n\t\t// Go through every key on the object,\n\t\t} else {\n\t\t\tfor ( i in elems ) {\n\t\t\t\tvalue = callback( elems[ i ], i, arg );\n\n\t\t\t\tif ( value != null ) {\n\t\t\t\t\tret[ ret.length ] = value;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Flatten any nested arrays\n\t\treturn core_concat.apply( [], ret );\n\t},\n\n\t// A global GUID counter for objects\n\tguid: 1,\n\n\t// Bind a function to a context, optionally partially applying any\n\t// arguments.\n\tproxy: function( fn, context ) {\n\t\tvar args, proxy, tmp;\n\n\t\tif ( typeof context === \"string\" ) {\n\t\t\ttmp = fn[ context ];\n\t\t\tcontext = fn;\n\t\t\tfn = tmp;\n\t\t}\n\n\t\t// Quick check to determine if target is callable, in the spec\n\t\t// this throws a TypeError, but we will just return undefined.\n\t\tif ( !jQuery.isFunction( fn ) ) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\t// Simulated bind\n\t\targs = core_slice.call( arguments, 2 );\n\t\tproxy = function() {\n\t\t\treturn fn.apply( context || this, args.concat( core_slice.call( arguments ) ) );\n\t\t};\n\n\t\t// Set the guid of unique handler to the same of original handler, so it can be removed\n\t\tproxy.guid = fn.guid = fn.guid || jQuery.guid++;\n\n\t\treturn proxy;\n\t},\n\n\t// Multifunctional method to get and set values of a collection\n\t// The value/s can optionally be executed if it's a function\n\taccess: function( elems, fn, key, value, chainable, emptyGet, raw ) {\n\t\tvar i = 0,\n\t\t\tlength = elems.length,\n\t\t\tbulk = key == null;\n\n\t\t// Sets many values\n\t\tif ( jQuery.type( key ) === \"object\" ) {\n\t\t\tchainable = true;\n\t\t\tfor ( i in key ) {\n\t\t\t\tjQuery.access( elems, fn, i, key[i], true, emptyGet, raw );\n\t\t\t}\n\n\t\t// Sets one value\n\t\t} else if ( value !== undefined ) {\n\t\t\tchainable = true;\n\n\t\t\tif ( !jQuery.isFunction( value ) ) {\n\t\t\t\traw = true;\n\t\t\t}\n\n\t\t\tif ( bulk ) {\n\t\t\t\t// Bulk operations run against the entire set\n\t\t\t\tif ( raw ) {\n\t\t\t\t\tfn.call( elems, value );\n\t\t\t\t\tfn = null;\n\n\t\t\t\t// ...except when executing function values\n\t\t\t\t} else {\n\t\t\t\t\tbulk = fn;\n\t\t\t\t\tfn = function( elem, key, value ) {\n\t\t\t\t\t\treturn bulk.call( jQuery( elem ), value );\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( fn ) {\n\t\t\t\tfor ( ; i < length; i++ ) {\n\t\t\t\t\tfn( elems[i], key, raw ? value : value.call( elems[i], i, fn( elems[i], key ) ) );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn chainable ?\n\t\t\telems :\n\n\t\t\t// Gets\n\t\t\tbulk ?\n\t\t\t\tfn.call( elems ) :\n\t\t\t\tlength ? fn( elems[0], key ) : emptyGet;\n\t},\n\n\tnow: function() {\n\t\treturn ( new Date() ).getTime();\n\t}\n});\n\njQuery.ready.promise = function( obj ) {\n\tif ( !readyList ) {\n\n\t\treadyList = jQuery.Deferred();\n\n\t\t// Catch cases where $(document).ready() is called after the browser event has already occurred.\n\t\t// we once tried to use readyState \"interactive\" here, but it caused issues like the one\n\t\t// discovered by ChrisS here: http://bugs.jquery.com/ticket/12282#comment:15\n\t\tif ( document.readyState === \"complete\" ) {\n\t\t\t// Handle it asynchronously to allow scripts the opportunity to delay ready\n\t\t\tsetTimeout( jQuery.ready );\n\n\t\t// Standards-based browsers support DOMContentLoaded\n\t\t} else if ( document.addEventListener ) {\n\t\t\t// Use the handy event callback\n\t\t\tdocument.addEventListener( \"DOMContentLoaded\", completed, false );\n\n\t\t\t// A fallback to window.onload, that will always work\n\t\t\twindow.addEventListener( \"load\", completed, false );\n\n\t\t// If IE event model is used\n\t\t} else {\n\t\t\t// Ensure firing before onload, maybe late but safe also for iframes\n\t\t\tdocument.attachEvent( \"onreadystatechange\", completed );\n\n\t\t\t// A fallback to window.onload, that will always work\n\t\t\twindow.attachEvent( \"onload\", completed );\n\n\t\t\t// If IE and not a frame\n\t\t\t// continually check to see if the document is ready\n\t\t\tvar top = false;\n\n\t\t\ttry {\n\t\t\t\ttop = window.frameElement == null && document.documentElement;\n\t\t\t} catch(e) {}\n\n\t\t\tif ( top && top.doScroll ) {\n\t\t\t\t(function doScrollCheck() {\n\t\t\t\t\tif ( !jQuery.isReady ) {\n\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t// Use the trick by Diego Perini\n\t\t\t\t\t\t\t// http://javascript.nwbox.com/IEContentLoaded/\n\t\t\t\t\t\t\ttop.doScroll(\"left\");\n\t\t\t\t\t\t} catch(e) {\n\t\t\t\t\t\t\treturn setTimeout( doScrollCheck, 50 );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// detach all dom ready events\n\t\t\t\t\t\tdetach();\n\n\t\t\t\t\t\t// and execute any waiting functions\n\t\t\t\t\t\tjQuery.ready();\n\t\t\t\t\t}\n\t\t\t\t})();\n\t\t\t}\n\t\t}\n\t}\n\treturn readyList.promise( obj );\n};\n\n// Populate the class2type map\njQuery.each(\"Boolean Number String Function Array Date RegExp Object Error\".split(\" \"), function(i, name) {\n\tclass2type[ \"[object \" + name + \"]\" ] = name.toLowerCase();\n});\n\nfunction isArraylike( obj ) {\n\tvar length = obj.length,\n\t\ttype = jQuery.type( obj );\n\n\tif ( jQuery.isWindow( obj ) ) {\n\t\treturn false;\n\t}\n\n\tif ( obj.nodeType === 1 && length ) {\n\t\treturn true;\n\t}\n\n\treturn type === \"array\" || type !== \"function\" &&\n\t\t( length === 0 ||\n\t\ttypeof length === \"number\" && length > 0 && ( length - 1 ) in obj );\n}\n\n// All jQuery objects should point back to these\nrootjQuery = jQuery(document);\n// String to Object options format cache\nvar optionsCache = {};\n\n// Convert String-formatted options into Object-formatted ones and store in cache\nfunction createOptions( options ) {\n\tvar object = optionsCache[ options ] = {};\n\tjQuery.each( options.match( core_rnotwhite ) || [], function( _, flag ) {\n\t\tobject[ flag ] = true;\n\t});\n\treturn object;\n}\n\n/*\n * Create a callback list using the following parameters:\n *\n *\toptions: an optional list of space-separated options that will change how\n *\t\t\tthe callback list behaves or a more traditional option object\n *\n * By default a callback list will act like an event callback list and can be\n * \"fired\" multiple times.\n *\n * Possible options:\n *\n *\tonce:\t\t\twill ensure the callback list can only be fired once (like a Deferred)\n *\n *\tmemory:\t\t\twill keep track of previous values and will call any callback added\n *\t\t\t\t\tafter the list has been fired right away with the latest \"memorized\"\n *\t\t\t\t\tvalues (like a Deferred)\n *\n *\tunique:\t\t\twill ensure a callback can only be added once (no duplicate in the list)\n *\n *\tstopOnFalse:\tinterrupt callings when a callback returns false\n *\n */\njQuery.Callbacks = function( options ) {\n\n\t// Convert options from String-formatted to Object-formatted if needed\n\t// (we check in cache first)\n\toptions = typeof options === \"string\" ?\n\t\t( optionsCache[ options ] || createOptions( options ) ) :\n\t\tjQuery.extend( {}, options );\n\n\tvar // Flag to know if list is currently firing\n\t\tfiring,\n\t\t// Last fire value (for non-forgettable lists)\n\t\tmemory,\n\t\t// Flag to know if list was already fired\n\t\tfired,\n\t\t// End of the loop when firing\n\t\tfiringLength,\n\t\t// Index of currently firing callback (modified by remove if needed)\n\t\tfiringIndex,\n\t\t// First callback to fire (used internally by add and fireWith)\n\t\tfiringStart,\n\t\t// Actual callback list\n\t\tlist = [],\n\t\t// Stack of fire calls for repeatable lists\n\t\tstack = !options.once && [],\n\t\t// Fire callbacks\n\t\tfire = function( data ) {\n\t\t\tmemory = options.memory && data;\n\t\t\tfired = true;\n\t\t\tfiringIndex = firingStart || 0;\n\t\t\tfiringStart = 0;\n\t\t\tfiringLength = list.length;\n\t\t\tfiring = true;\n\t\t\tfor ( ; list && firingIndex < firingLength; firingIndex++ ) {\n\t\t\t\tif ( list[ firingIndex ].apply( data[ 0 ], data[ 1 ] ) === false && options.stopOnFalse ) {\n\t\t\t\t\tmemory = false; // To prevent further calls using add\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tfiring = false;\n\t\t\tif ( list ) {\n\t\t\t\tif ( stack ) {\n\t\t\t\t\tif ( stack.length ) {\n\t\t\t\t\t\tfire( stack.shift() );\n\t\t\t\t\t}\n\t\t\t\t} else if ( memory ) {\n\t\t\t\t\tlist = [];\n\t\t\t\t} else {\n\t\t\t\t\tself.disable();\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t// Actual Callbacks object\n\t\tself = {\n\t\t\t// Add a callback or a collection of callbacks to the list\n\t\t\tadd: function() {\n\t\t\t\tif ( list ) {\n\t\t\t\t\t// First, we save the current length\n\t\t\t\t\tvar start = list.length;\n\t\t\t\t\t(function add( args ) {\n\t\t\t\t\t\tjQuery.each( args, function( _, arg ) {\n\t\t\t\t\t\t\tvar type = jQuery.type( arg );\n\t\t\t\t\t\t\tif ( type === \"function\" ) {\n\t\t\t\t\t\t\t\tif ( !options.unique || !self.has( arg ) ) {\n\t\t\t\t\t\t\t\t\tlist.push( arg );\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} else if ( arg && arg.length && type !== \"string\" ) {\n\t\t\t\t\t\t\t\t// Inspect recursively\n\t\t\t\t\t\t\t\tadd( arg );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t});\n\t\t\t\t\t})( arguments );\n\t\t\t\t\t// Do we need to add the callbacks to the\n\t\t\t\t\t// current firing batch?\n\t\t\t\t\tif ( firing ) {\n\t\t\t\t\t\tfiringLength = list.length;\n\t\t\t\t\t// With memory, if we're not firing then\n\t\t\t\t\t// we should call right away\n\t\t\t\t\t} else if ( memory ) {\n\t\t\t\t\t\tfiringStart = start;\n\t\t\t\t\t\tfire( memory );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Remove a callback from the list\n\t\t\tremove: function() {\n\t\t\t\tif ( list ) {\n\t\t\t\t\tjQuery.each( arguments, function( _, arg ) {\n\t\t\t\t\t\tvar index;\n\t\t\t\t\t\twhile( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) {\n\t\t\t\t\t\t\tlist.splice( index, 1 );\n\t\t\t\t\t\t\t// Handle firing indexes\n\t\t\t\t\t\t\tif ( firing ) {\n\t\t\t\t\t\t\t\tif ( index <= firingLength ) {\n\t\t\t\t\t\t\t\t\tfiringLength--;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif ( index <= firingIndex ) {\n\t\t\t\t\t\t\t\t\tfiringIndex--;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Check if a given callback is in the list.\n\t\t\t// If no argument is given, return whether or not list has callbacks attached.\n\t\t\thas: function( fn ) {\n\t\t\t\treturn fn ? jQuery.inArray( fn, list ) > -1 : !!( list && list.length );\n\t\t\t},\n\t\t\t// Remove all callbacks from the list\n\t\t\tempty: function() {\n\t\t\t\tlist = [];\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Have the list do nothing anymore\n\t\t\tdisable: function() {\n\t\t\t\tlist = stack = memory = undefined;\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Is it disabled?\n\t\t\tdisabled: function() {\n\t\t\t\treturn !list;\n\t\t\t},\n\t\t\t// Lock the list in its current state\n\t\t\tlock: function() {\n\t\t\t\tstack = undefined;\n\t\t\t\tif ( !memory ) {\n\t\t\t\t\tself.disable();\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Is it locked?\n\t\t\tlocked: function() {\n\t\t\t\treturn !stack;\n\t\t\t},\n\t\t\t// Call all callbacks with the given context and arguments\n\t\t\tfireWith: function( context, args ) {\n\t\t\t\targs = args || [];\n\t\t\t\targs = [ context, args.slice ? args.slice() : args ];\n\t\t\t\tif ( list && ( !fired || stack ) ) {\n\t\t\t\t\tif ( firing ) {\n\t\t\t\t\t\tstack.push( args );\n\t\t\t\t\t} else {\n\t\t\t\t\t\tfire( args );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Call all the callbacks with the given arguments\n\t\t\tfire: function() {\n\t\t\t\tself.fireWith( this, arguments );\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// To know if the callbacks have already been called at least once\n\t\t\tfired: function() {\n\t\t\t\treturn !!fired;\n\t\t\t}\n\t\t};\n\n\treturn self;\n};\njQuery.extend({\n\n\tDeferred: function( func ) {\n\t\tvar tuples = [\n\t\t\t\t// action, add listener, listener list, final state\n\t\t\t\t[ \"resolve\", \"done\", jQuery.Callbacks(\"once memory\"), \"resolved\" ],\n\t\t\t\t[ \"reject\", \"fail\", jQuery.Callbacks(\"once memory\"), \"rejected\" ],\n\t\t\t\t[ \"notify\", \"progress\", jQuery.Callbacks(\"memory\") ]\n\t\t\t],\n\t\t\tstate = \"pending\",\n\t\t\tpromise = {\n\t\t\t\tstate: function() {\n\t\t\t\t\treturn state;\n\t\t\t\t},\n\t\t\t\talways: function() {\n\t\t\t\t\tdeferred.done( arguments ).fail( arguments );\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\t\t\t\tthen: function( /* fnDone, fnFail, fnProgress */ ) {\n\t\t\t\t\tvar fns = arguments;\n\t\t\t\t\treturn jQuery.Deferred(function( newDefer ) {\n\t\t\t\t\t\tjQuery.each( tuples, function( i, tuple ) {\n\t\t\t\t\t\t\tvar action = tuple[ 0 ],\n\t\t\t\t\t\t\t\tfn = jQuery.isFunction( fns[ i ] ) && fns[ i ];\n\t\t\t\t\t\t\t// deferred[ done | fail | progress ] for forwarding actions to newDefer\n\t\t\t\t\t\t\tdeferred[ tuple[1] ](function() {\n\t\t\t\t\t\t\t\tvar returned = fn && fn.apply( this, arguments );\n\t\t\t\t\t\t\t\tif ( returned && jQuery.isFunction( returned.promise ) ) {\n\t\t\t\t\t\t\t\t\treturned.promise()\n\t\t\t\t\t\t\t\t\t\t.done( newDefer.resolve )\n\t\t\t\t\t\t\t\t\t\t.fail( newDefer.reject )\n\t\t\t\t\t\t\t\t\t\t.progress( newDefer.notify );\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tnewDefer[ action + \"With\" ]( this === promise ? newDefer.promise() : this, fn ? [ returned ] : arguments );\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t});\n\t\t\t\t\t\tfns = null;\n\t\t\t\t\t}).promise();\n\t\t\t\t},\n\t\t\t\t// Get a promise for this deferred\n\t\t\t\t// If obj is provided, the promise aspect is added to the object\n\t\t\t\tpromise: function( obj ) {\n\t\t\t\t\treturn obj != null ? jQuery.extend( obj, promise ) : promise;\n\t\t\t\t}\n\t\t\t},\n\t\t\tdeferred = {};\n\n\t\t// Keep pipe for back-compat\n\t\tpromise.pipe = promise.then;\n\n\t\t// Add list-specific methods\n\t\tjQuery.each( tuples, function( i, tuple ) {\n\t\t\tvar list = tuple[ 2 ],\n\t\t\t\tstateString = tuple[ 3 ];\n\n\t\t\t// promise[ done | fail | progress ] = list.add\n\t\t\tpromise[ tuple[1] ] = list.add;\n\n\t\t\t// Handle state\n\t\t\tif ( stateString ) {\n\t\t\t\tlist.add(function() {\n\t\t\t\t\t// state = [ resolved | rejected ]\n\t\t\t\t\tstate = stateString;\n\n\t\t\t\t// [ reject_list | resolve_list ].disable; progress_list.lock\n\t\t\t\t}, tuples[ i ^ 1 ][ 2 ].disable, tuples[ 2 ][ 2 ].lock );\n\t\t\t}\n\n\t\t\t// deferred[ resolve | reject | notify ]\n\t\t\tdeferred[ tuple[0] ] = function() {\n\t\t\t\tdeferred[ tuple[0] + \"With\" ]( this === deferred ? promise : this, arguments );\n\t\t\t\treturn this;\n\t\t\t};\n\t\t\tdeferred[ tuple[0] + \"With\" ] = list.fireWith;\n\t\t});\n\n\t\t// Make the deferred a promise\n\t\tpromise.promise( deferred );\n\n\t\t// Call given func if any\n\t\tif ( func ) {\n\t\t\tfunc.call( deferred, deferred );\n\t\t}\n\n\t\t// All done!\n\t\treturn deferred;\n\t},\n\n\t// Deferred helper\n\twhen: function( subordinate /* , ..., subordinateN */ ) {\n\t\tvar i = 0,\n\t\t\tresolveValues = core_slice.call( arguments ),\n\t\t\tlength = resolveValues.length,\n\n\t\t\t// the count of uncompleted subordinates\n\t\t\tremaining = length !== 1 || ( subordinate && jQuery.isFunction( subordinate.promise ) ) ? length : 0,\n\n\t\t\t// the master Deferred. If resolveValues consist of only a single Deferred, just use that.\n\t\t\tdeferred = remaining === 1 ? subordinate : jQuery.Deferred(),\n\n\t\t\t// Update function for both resolve and progress values\n\t\t\tupdateFunc = function( i, contexts, values ) {\n\t\t\t\treturn function( value ) {\n\t\t\t\t\tcontexts[ i ] = this;\n\t\t\t\t\tvalues[ i ] = arguments.length > 1 ? core_slice.call( arguments ) : value;\n\t\t\t\t\tif( values === progressValues ) {\n\t\t\t\t\t\tdeferred.notifyWith( contexts, values );\n\t\t\t\t\t} else if ( !( --remaining ) ) {\n\t\t\t\t\t\tdeferred.resolveWith( contexts, values );\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\t},\n\n\t\t\tprogressValues, progressContexts, resolveContexts;\n\n\t\t// add listeners to Deferred subordinates; treat others as resolved\n\t\tif ( length > 1 ) {\n\t\t\tprogressValues = new Array( length );\n\t\t\tprogressContexts = new Array( length );\n\t\t\tresolveContexts = new Array( length );\n\t\t\tfor ( ; i < length; i++ ) {\n\t\t\t\tif ( resolveValues[ i ] && jQuery.isFunction( resolveValues[ i ].promise ) ) {\n\t\t\t\t\tresolveValues[ i ].promise()\n\t\t\t\t\t\t.done( updateFunc( i, resolveContexts, resolveValues ) )\n\t\t\t\t\t\t.fail( deferred.reject )\n\t\t\t\t\t\t.progress( updateFunc( i, progressContexts, progressValues ) );\n\t\t\t\t} else {\n\t\t\t\t\t--remaining;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// if we're not waiting on anything, resolve the master\n\t\tif ( !remaining ) {\n\t\t\tdeferred.resolveWith( resolveContexts, resolveValues );\n\t\t}\n\n\t\treturn deferred.promise();\n\t}\n});\njQuery.support = (function() {\n\n\tvar support, all, a,\n\t\tinput, select, fragment,\n\t\topt, eventName, isSupported, i,\n\t\tdiv = document.createElement(\"div\");\n\n\t// Setup\n\tdiv.setAttribute( \"className\", \"t\" );\n\tdiv.innerHTML = \"  <link/><table></table><a href='/a'>a</a><input type='checkbox'/>\";\n\n\t// Support tests won't run in some limited or non-browser environments\n\tall = div.getElementsByTagName(\"*\");\n\ta = div.getElementsByTagName(\"a\")[ 0 ];\n\tif ( !all || !a || !all.length ) {\n\t\treturn {};\n\t}\n\n\t// First batch of tests\n\tselect = document.createElement(\"select\");\n\topt = select.appendChild( document.createElement(\"option\") );\n\tinput = div.getElementsByTagName(\"input\")[ 0 ];\n\n\ta.style.cssText = \"top:1px;float:left;opacity:.5\";\n\tsupport = {\n\t\t// Test setAttribute on camelCase class. If it works, we need attrFixes when doing get/setAttribute (ie6/7)\n\t\tgetSetAttribute: div.className !== \"t\",\n\n\t\t// IE strips leading whitespace when .innerHTML is used\n\t\tleadingWhitespace: div.firstChild.nodeType === 3,\n\n\t\t// Make sure that tbody elements aren't automatically inserted\n\t\t// IE will insert them into empty tables\n\t\ttbody: !div.getElementsByTagName(\"tbody\").length,\n\n\t\t// Make sure that link elements get serialized correctly by innerHTML\n\t\t// This requires a wrapper element in IE\n\t\thtmlSerialize: !!div.getElementsByTagName(\"link\").length,\n\n\t\t// Get the style information from getAttribute\n\t\t// (IE uses .cssText instead)\n\t\tstyle: /top/.test( a.getAttribute(\"style\") ),\n\n\t\t// Make sure that URLs aren't manipulated\n\t\t// (IE normalizes it by default)\n\t\threfNormalized: a.getAttribute(\"href\") === \"/a\",\n\n\t\t// Make sure that element opacity exists\n\t\t// (IE uses filter instead)\n\t\t// Use a regex to work around a WebKit issue. See #5145\n\t\topacity: /^0.5/.test( a.style.opacity ),\n\n\t\t// Verify style float existence\n\t\t// (IE uses styleFloat instead of cssFloat)\n\t\tcssFloat: !!a.style.cssFloat,\n\n\t\t// Check the default checkbox/radio value (\"\" on WebKit; \"on\" elsewhere)\n\t\tcheckOn: !!input.value,\n\n\t\t// Make sure that a selected-by-default option has a working selected property.\n\t\t// (WebKit defaults to false instead of true, IE too, if it's in an optgroup)\n\t\toptSelected: opt.selected,\n\n\t\t// Tests for enctype support on a form (#6743)\n\t\tenctype: !!document.createElement(\"form\").enctype,\n\n\t\t// Makes sure cloning an html5 element does not cause problems\n\t\t// Where outerHTML is undefined, this still works\n\t\thtml5Clone: document.createElement(\"nav\").cloneNode( true ).outerHTML !== \"<:nav></:nav>\",\n\n\t\t// jQuery.support.boxModel DEPRECATED in 1.8 since we don't support Quirks Mode\n\t\tboxModel: document.compatMode === \"CSS1Compat\",\n\n\t\t// Will be defined later\n\t\tdeleteExpando: true,\n\t\tnoCloneEvent: true,\n\t\tinlineBlockNeedsLayout: false,\n\t\tshrinkWrapBlocks: false,\n\t\treliableMarginRight: true,\n\t\tboxSizingReliable: true,\n\t\tpixelPosition: false\n\t};\n\n\t// Make sure checked status is properly cloned\n\tinput.checked = true;\n\tsupport.noCloneChecked = input.cloneNode( true ).checked;\n\n\t// Make sure that the options inside disabled selects aren't marked as disabled\n\t// (WebKit marks them as disabled)\n\tselect.disabled = true;\n\tsupport.optDisabled = !opt.disabled;\n\n\t// Support: IE<9\n\ttry {\n\t\tdelete div.test;\n\t} catch( e ) {\n\t\tsupport.deleteExpando = false;\n\t}\n\n\t// Check if we can trust getAttribute(\"value\")\n\tinput = document.createElement(\"input\");\n\tinput.setAttribute( \"value\", \"\" );\n\tsupport.input = input.getAttribute( \"value\" ) === \"\";\n\n\t// Check if an input maintains its value after becoming a radio\n\tinput.value = \"t\";\n\tinput.setAttribute( \"type\", \"radio\" );\n\tsupport.radioValue = input.value === \"t\";\n\n\t// #11217 - WebKit loses check when the name is after the checked attribute\n\tinput.setAttribute( \"checked\", \"t\" );\n\tinput.setAttribute( \"name\", \"t\" );\n\n\tfragment = document.createDocumentFragment();\n\tfragment.appendChild( input );\n\n\t// Check if a disconnected checkbox will retain its checked\n\t// value of true after appended to the DOM (IE6/7)\n\tsupport.appendChecked = input.checked;\n\n\t// WebKit doesn't clone checked state correctly in fragments\n\tsupport.checkClone = fragment.cloneNode( true ).cloneNode( true ).lastChild.checked;\n\n\t// Support: IE<9\n\t// Opera does not clone events (and typeof div.attachEvent === undefined).\n\t// IE9-10 clones events bound via attachEvent, but they don't trigger with .click()\n\tif ( div.attachEvent ) {\n\t\tdiv.attachEvent( \"onclick\", function() {\n\t\t\tsupport.noCloneEvent = false;\n\t\t});\n\n\t\tdiv.cloneNode( true ).click();\n\t}\n\n\t// Support: IE<9 (lack submit/change bubble), Firefox 17+ (lack focusin event)\n\t// Beware of CSP restrictions (https://developer.mozilla.org/en/Security/CSP), test/csp.php\n\tfor ( i in { submit: true, change: true, focusin: true }) {\n\t\tdiv.setAttribute( eventName = \"on\" + i, \"t\" );\n\n\t\tsupport[ i + \"Bubbles\" ] = eventName in window || div.attributes[ eventName ].expando === false;\n\t}\n\n\tdiv.style.backgroundClip = \"content-box\";\n\tdiv.cloneNode( true ).style.backgroundClip = \"\";\n\tsupport.clearCloneStyle = div.style.backgroundClip === \"content-box\";\n\n\t// Run tests that need a body at doc ready\n\tjQuery(function() {\n\t\tvar container, marginDiv, tds,\n\t\t\tdivReset = \"padding:0;margin:0;border:0;display:block;box-sizing:content-box;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;\",\n\t\t\tbody = document.getElementsByTagName(\"body\")[0];\n\n\t\tif ( !body ) {\n\t\t\t// Return for frameset docs that don't have a body\n\t\t\treturn;\n\t\t}\n\n\t\tcontainer = document.createElement(\"div\");\n\t\tcontainer.style.cssText = \"border:0;width:0;height:0;position:absolute;top:0;left:-9999px;margin-top:1px\";\n\n\t\tbody.appendChild( container ).appendChild( div );\n\n\t\t// Support: IE8\n\t\t// Check if table cells still have offsetWidth/Height when they are set\n\t\t// to display:none and there are still other visible table cells in a\n\t\t// table row; if so, offsetWidth/Height are not reliable for use when\n\t\t// determining if an element has been hidden directly using\n\t\t// display:none (it is still safe to use offsets if a parent element is\n\t\t// hidden; don safety goggles and see bug #4512 for more information).\n\t\tdiv.innerHTML = \"<table><tr><td></td><td>t</td></tr></table>\";\n\t\ttds = div.getElementsByTagName(\"td\");\n\t\ttds[ 0 ].style.cssText = \"padding:0;margin:0;border:0;display:none\";\n\t\tisSupported = ( tds[ 0 ].offsetHeight === 0 );\n\n\t\ttds[ 0 ].style.display = \"\";\n\t\ttds[ 1 ].style.display = \"none\";\n\n\t\t// Support: IE8\n\t\t// Check if empty table cells still have offsetWidth/Height\n\t\tsupport.reliableHiddenOffsets = isSupported && ( tds[ 0 ].offsetHeight === 0 );\n\n\t\t// Check box-sizing and margin behavior\n\t\tdiv.innerHTML = \"\";\n\t\tdiv.style.cssText = \"box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%;\";\n\t\tsupport.boxSizing = ( div.offsetWidth === 4 );\n\t\tsupport.doesNotIncludeMarginInBodyOffset = ( body.offsetTop !== 1 );\n\n\t\t// Use window.getComputedStyle because jsdom on node.js will break without it.\n\t\tif ( window.getComputedStyle ) {\n\t\t\tsupport.pixelPosition = ( window.getComputedStyle( div, null ) || {} ).top !== \"1%\";\n\t\t\tsupport.boxSizingReliable = ( window.getComputedStyle( div, null ) || { width: \"4px\" } ).width === \"4px\";\n\n\t\t\t// Check if div with explicit width and no margin-right incorrectly\n\t\t\t// gets computed margin-right based on width of container. (#3333)\n\t\t\t// Fails in WebKit before Feb 2011 nightlies\n\t\t\t// WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right\n\t\t\tmarginDiv = div.appendChild( document.createElement(\"div\") );\n\t\t\tmarginDiv.style.cssText = div.style.cssText = divReset;\n\t\t\tmarginDiv.style.marginRight = marginDiv.style.width = \"0\";\n\t\t\tdiv.style.width = \"1px\";\n\n\t\t\tsupport.reliableMarginRight =\n\t\t\t\t!parseFloat( ( window.getComputedStyle( marginDiv, null ) || {} ).marginRight );\n\t\t}\n\n\t\tif ( typeof div.style.zoom !== core_strundefined ) {\n\t\t\t// Support: IE<8\n\t\t\t// Check if natively block-level elements act like inline-block\n\t\t\t// elements when setting their display to 'inline' and giving\n\t\t\t// them layout\n\t\t\tdiv.innerHTML = \"\";\n\t\t\tdiv.style.cssText = divReset + \"width:1px;padding:1px;display:inline;zoom:1\";\n\t\t\tsupport.inlineBlockNeedsLayout = ( div.offsetWidth === 3 );\n\n\t\t\t// Support: IE6\n\t\t\t// Check if elements with layout shrink-wrap their children\n\t\t\tdiv.style.display = \"block\";\n\t\t\tdiv.innerHTML = \"<div></div>\";\n\t\t\tdiv.firstChild.style.width = \"5px\";\n\t\t\tsupport.shrinkWrapBlocks = ( div.offsetWidth !== 3 );\n\n\t\t\tif ( support.inlineBlockNeedsLayout ) {\n\t\t\t\t// Prevent IE 6 from affecting layout for positioned elements #11048\n\t\t\t\t// Prevent IE from shrinking the body in IE 7 mode #12869\n\t\t\t\t// Support: IE<8\n\t\t\t\tbody.style.zoom = 1;\n\t\t\t}\n\t\t}\n\n\t\tbody.removeChild( container );\n\n\t\t// Null elements to avoid leaks in IE\n\t\tcontainer = div = tds = marginDiv = null;\n\t});\n\n\t// Null elements to avoid leaks in IE\n\tall = select = fragment = opt = a = input = null;\n\n\treturn support;\n})();\n\nvar rbrace = /(?:\\{[\\s\\S]*\\}|\\[[\\s\\S]*\\])$/,\n\trmultiDash = /([A-Z])/g;\n\nfunction internalData( elem, name, data, pvt /* Internal Use Only */ ){\n\tif ( !jQuery.acceptData( elem ) ) {\n\t\treturn;\n\t}\n\n\tvar thisCache, ret,\n\t\tinternalKey = jQuery.expando,\n\t\tgetByName = typeof name === \"string\",\n\n\t\t// We have to handle DOM nodes and JS objects differently because IE6-7\n\t\t// can't GC object references properly across the DOM-JS boundary\n\t\tisNode = elem.nodeType,\n\n\t\t// Only DOM nodes need the global jQuery cache; JS object data is\n\t\t// attached directly to the object so GC can occur automatically\n\t\tcache = isNode ? jQuery.cache : elem,\n\n\t\t// Only defining an ID for JS objects if its cache already exists allows\n\t\t// the code to shortcut on the same path as a DOM node with no cache\n\t\tid = isNode ? elem[ internalKey ] : elem[ internalKey ] && internalKey;\n\n\t// Avoid doing any more work than we need to when trying to get data on an\n\t// object that has no data at all\n\tif ( (!id || !cache[id] || (!pvt && !cache[id].data)) && getByName && data === undefined ) {\n\t\treturn;\n\t}\n\n\tif ( !id ) {\n\t\t// Only DOM nodes need a new unique ID for each element since their data\n\t\t// ends up in the global cache\n\t\tif ( isNode ) {\n\t\t\telem[ internalKey ] = id = core_deletedIds.pop() || jQuery.guid++;\n\t\t} else {\n\t\t\tid = internalKey;\n\t\t}\n\t}\n\n\tif ( !cache[ id ] ) {\n\t\tcache[ id ] = {};\n\n\t\t// Avoids exposing jQuery metadata on plain JS objects when the object\n\t\t// is serialized using JSON.stringify\n\t\tif ( !isNode ) {\n\t\t\tcache[ id ].toJSON = jQuery.noop;\n\t\t}\n\t}\n\n\t// An object can be passed to jQuery.data instead of a key/value pair; this gets\n\t// shallow copied over onto the existing cache\n\tif ( typeof name === \"object\" || typeof name === \"function\" ) {\n\t\tif ( pvt ) {\n\t\t\tcache[ id ] = jQuery.extend( cache[ id ], name );\n\t\t} else {\n\t\t\tcache[ id ].data = jQuery.extend( cache[ id ].data, name );\n\t\t}\n\t}\n\n\tthisCache = cache[ id ];\n\n\t// jQuery data() is stored in a separate object inside the object's internal data\n\t// cache in order to avoid key collisions between internal data and user-defined\n\t// data.\n\tif ( !pvt ) {\n\t\tif ( !thisCache.data ) {\n\t\t\tthisCache.data = {};\n\t\t}\n\n\t\tthisCache = thisCache.data;\n\t}\n\n\tif ( data !== undefined ) {\n\t\tthisCache[ jQuery.camelCase( name ) ] = data;\n\t}\n\n\t// Check for both converted-to-camel and non-converted data property names\n\t// If a data property was specified\n\tif ( getByName ) {\n\n\t\t// First Try to find as-is property data\n\t\tret = thisCache[ name ];\n\n\t\t// Test for null|undefined property data\n\t\tif ( ret == null ) {\n\n\t\t\t// Try to find the camelCased property\n\t\t\tret = thisCache[ jQuery.camelCase( name ) ];\n\t\t}\n\t} else {\n\t\tret = thisCache;\n\t}\n\n\treturn ret;\n}\n\nfunction internalRemoveData( elem, name, pvt ) {\n\tif ( !jQuery.acceptData( elem ) ) {\n\t\treturn;\n\t}\n\n\tvar i, l, thisCache,\n\t\tisNode = elem.nodeType,\n\n\t\t// See jQuery.data for more information\n\t\tcache = isNode ? jQuery.cache : elem,\n\t\tid = isNode ? elem[ jQuery.expando ] : jQuery.expando;\n\n\t// If there is already no cache entry for this object, there is no\n\t// purpose in continuing\n\tif ( !cache[ id ] ) {\n\t\treturn;\n\t}\n\n\tif ( name ) {\n\n\t\tthisCache = pvt ? cache[ id ] : cache[ id ].data;\n\n\t\tif ( thisCache ) {\n\n\t\t\t// Support array or space separated string names for data keys\n\t\t\tif ( !jQuery.isArray( name ) ) {\n\n\t\t\t\t// try the string as a key before any manipulation\n\t\t\t\tif ( name in thisCache ) {\n\t\t\t\t\tname = [ name ];\n\t\t\t\t} else {\n\n\t\t\t\t\t// split the camel cased version by spaces unless a key with the spaces exists\n\t\t\t\t\tname = jQuery.camelCase( name );\n\t\t\t\t\tif ( name in thisCache ) {\n\t\t\t\t\t\tname = [ name ];\n\t\t\t\t\t} else {\n\t\t\t\t\t\tname = name.split(\" \");\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// If \"name\" is an array of keys...\n\t\t\t\t// When data is initially created, via (\"key\", \"val\") signature,\n\t\t\t\t// keys will be converted to camelCase.\n\t\t\t\t// Since there is no way to tell _how_ a key was added, remove\n\t\t\t\t// both plain key and camelCase key. #12786\n\t\t\t\t// This will only penalize the array argument path.\n\t\t\t\tname = name.concat( jQuery.map( name, jQuery.camelCase ) );\n\t\t\t}\n\n\t\t\tfor ( i = 0, l = name.length; i < l; i++ ) {\n\t\t\t\tdelete thisCache[ name[i] ];\n\t\t\t}\n\n\t\t\t// If there is no data left in the cache, we want to continue\n\t\t\t// and let the cache object itself get destroyed\n\t\t\tif ( !( pvt ? isEmptyDataObject : jQuery.isEmptyObject )( thisCache ) ) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t}\n\n\t// See jQuery.data for more information\n\tif ( !pvt ) {\n\t\tdelete cache[ id ].data;\n\n\t\t// Don't destroy the parent cache unless the internal data object\n\t\t// had been the only thing left in it\n\t\tif ( !isEmptyDataObject( cache[ id ] ) ) {\n\t\t\treturn;\n\t\t}\n\t}\n\n\t// Destroy the cache\n\tif ( isNode ) {\n\t\tjQuery.cleanData( [ elem ], true );\n\n\t// Use delete when supported for expandos or `cache` is not a window per isWindow (#10080)\n\t} else if ( jQuery.support.deleteExpando || cache != cache.window ) {\n\t\tdelete cache[ id ];\n\n\t// When all else fails, null\n\t} else {\n\t\tcache[ id ] = null;\n\t}\n}\n\njQuery.extend({\n\tcache: {},\n\n\t// Unique for each copy of jQuery on the page\n\t// Non-digits removed to match rinlinejQuery\n\texpando: \"jQuery\" + ( core_version + Math.random() ).replace( /\\D/g, \"\" ),\n\n\t// The following elements throw uncatchable exceptions if you\n\t// attempt to add expando properties to them.\n\tnoData: {\n\t\t\"embed\": true,\n\t\t// Ban all objects except for Flash (which handle expandos)\n\t\t\"object\": \"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000\",\n\t\t\"applet\": true\n\t},\n\n\thasData: function( elem ) {\n\t\telem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ];\n\t\treturn !!elem && !isEmptyDataObject( elem );\n\t},\n\n\tdata: function( elem, name, data ) {\n\t\treturn internalData( elem, name, data );\n\t},\n\n\tremoveData: function( elem, name ) {\n\t\treturn internalRemoveData( elem, name );\n\t},\n\n\t// For internal use only.\n\t_data: function( elem, name, data ) {\n\t\treturn internalData( elem, name, data, true );\n\t},\n\n\t_removeData: function( elem, name ) {\n\t\treturn internalRemoveData( elem, name, true );\n\t},\n\n\t// A method for determining if a DOM node can handle the data expando\n\tacceptData: function( elem ) {\n\t\t// Do not set data on non-element because it will not be cleared (#8335).\n\t\tif ( elem.nodeType && elem.nodeType !== 1 && elem.nodeType !== 9 ) {\n\t\t\treturn false;\n\t\t}\n\n\t\tvar noData = elem.nodeName && jQuery.noData[ elem.nodeName.toLowerCase() ];\n\n\t\t// nodes accept data unless otherwise specified; rejection can be conditional\n\t\treturn !noData || noData !== true && elem.getAttribute(\"classid\") === noData;\n\t}\n});\n\njQuery.fn.extend({\n\tdata: function( key, value ) {\n\t\tvar attrs, name,\n\t\t\telem = this[0],\n\t\t\ti = 0,\n\t\t\tdata = null;\n\n\t\t// Gets all values\n\t\tif ( key === undefined ) {\n\t\t\tif ( this.length ) {\n\t\t\t\tdata = jQuery.data( elem );\n\n\t\t\t\tif ( elem.nodeType === 1 && !jQuery._data( elem, \"parsedAttrs\" ) ) {\n\t\t\t\t\tattrs = elem.attributes;\n\t\t\t\t\tfor ( ; i < attrs.length; i++ ) {\n\t\t\t\t\t\tname = attrs[i].name;\n\n\t\t\t\t\t\tif ( !name.indexOf( \"data-\" ) ) {\n\t\t\t\t\t\t\tname = jQuery.camelCase( name.slice(5) );\n\n\t\t\t\t\t\t\tdataAttr( elem, name, data[ name ] );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tjQuery._data( elem, \"parsedAttrs\", true );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn data;\n\t\t}\n\n\t\t// Sets multiple values\n\t\tif ( typeof key === \"object\" ) {\n\t\t\treturn this.each(function() {\n\t\t\t\tjQuery.data( this, key );\n\t\t\t});\n\t\t}\n\n\t\treturn jQuery.access( this, function( value ) {\n\n\t\t\tif ( value === undefined ) {\n\t\t\t\t// Try to fetch any internally stored data first\n\t\t\t\treturn elem ? dataAttr( elem, key, jQuery.data( elem, key ) ) : null;\n\t\t\t}\n\n\t\t\tthis.each(function() {\n\t\t\t\tjQuery.data( this, key, value );\n\t\t\t});\n\t\t}, null, value, arguments.length > 1, null, true );\n\t},\n\n\tremoveData: function( key ) {\n\t\treturn this.each(function() {\n\t\t\tjQuery.removeData( this, key );\n\t\t});\n\t}\n});\n\nfunction dataAttr( elem, key, data ) {\n\t// If nothing was found internally, try to fetch any\n\t// data from the HTML5 data-* attribute\n\tif ( data === undefined && elem.nodeType === 1 ) {\n\n\t\tvar name = \"data-\" + key.replace( rmultiDash, \"-$1\" ).toLowerCase();\n\n\t\tdata = elem.getAttribute( name );\n\n\t\tif ( typeof data === \"string\" ) {\n\t\t\ttry {\n\t\t\t\tdata = data === \"true\" ? true :\n\t\t\t\t\tdata === \"false\" ? false :\n\t\t\t\t\tdata === \"null\" ? null :\n\t\t\t\t\t// Only convert to a number if it doesn't change the string\n\t\t\t\t\t+data + \"\" === data ? +data :\n\t\t\t\t\trbrace.test( data ) ? jQuery.parseJSON( data ) :\n\t\t\t\t\t\tdata;\n\t\t\t} catch( e ) {}\n\n\t\t\t// Make sure we set the data so it isn't changed later\n\t\t\tjQuery.data( elem, key, data );\n\n\t\t} else {\n\t\t\tdata = undefined;\n\t\t}\n\t}\n\n\treturn data;\n}\n\n// checks a cache object for emptiness\nfunction isEmptyDataObject( obj ) {\n\tvar name;\n\tfor ( name in obj ) {\n\n\t\t// if the public data object is empty, the private is still empty\n\t\tif ( name === \"data\" && jQuery.isEmptyObject( obj[name] ) ) {\n\t\t\tcontinue;\n\t\t}\n\t\tif ( name !== \"toJSON\" ) {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\treturn true;\n}\njQuery.extend({\n\tqueue: function( elem, type, data ) {\n\t\tvar queue;\n\n\t\tif ( elem ) {\n\t\t\ttype = ( type || \"fx\" ) + \"queue\";\n\t\t\tqueue = jQuery._data( elem, type );\n\n\t\t\t// Speed up dequeue by getting out quickly if this is just a lookup\n\t\t\tif ( data ) {\n\t\t\t\tif ( !queue || jQuery.isArray(data) ) {\n\t\t\t\t\tqueue = jQuery._data( elem, type, jQuery.makeArray(data) );\n\t\t\t\t} else {\n\t\t\t\t\tqueue.push( data );\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn queue || [];\n\t\t}\n\t},\n\n\tdequeue: function( elem, type ) {\n\t\ttype = type || \"fx\";\n\n\t\tvar queue = jQuery.queue( elem, type ),\n\t\t\tstartLength = queue.length,\n\t\t\tfn = queue.shift(),\n\t\t\thooks = jQuery._queueHooks( elem, type ),\n\t\t\tnext = function() {\n\t\t\t\tjQuery.dequeue( elem, type );\n\t\t\t};\n\n\t\t// If the fx queue is dequeued, always remove the progress sentinel\n\t\tif ( fn === \"inprogress\" ) {\n\t\t\tfn = queue.shift();\n\t\t\tstartLength--;\n\t\t}\n\n\t\thooks.cur = fn;\n\t\tif ( fn ) {\n\n\t\t\t// Add a progress sentinel to prevent the fx queue from being\n\t\t\t// automatically dequeued\n\t\t\tif ( type === \"fx\" ) {\n\t\t\t\tqueue.unshift( \"inprogress\" );\n\t\t\t}\n\n\t\t\t// clear up the last queue stop function\n\t\t\tdelete hooks.stop;\n\t\t\tfn.call( elem, next, hooks );\n\t\t}\n\n\t\tif ( !startLength && hooks ) {\n\t\t\thooks.empty.fire();\n\t\t}\n\t},\n\n\t// not intended for public consumption - generates a queueHooks object, or returns the current one\n\t_queueHooks: function( elem, type ) {\n\t\tvar key = type + \"queueHooks\";\n\t\treturn jQuery._data( elem, key ) || jQuery._data( elem, key, {\n\t\t\tempty: jQuery.Callbacks(\"once memory\").add(function() {\n\t\t\t\tjQuery._removeData( elem, type + \"queue\" );\n\t\t\t\tjQuery._removeData( elem, key );\n\t\t\t})\n\t\t});\n\t}\n});\n\njQuery.fn.extend({\n\tqueue: function( type, data ) {\n\t\tvar setter = 2;\n\n\t\tif ( typeof type !== \"string\" ) {\n\t\t\tdata = type;\n\t\t\ttype = \"fx\";\n\t\t\tsetter--;\n\t\t}\n\n\t\tif ( arguments.length < setter ) {\n\t\t\treturn jQuery.queue( this[0], type );\n\t\t}\n\n\t\treturn data === undefined ?\n\t\t\tthis :\n\t\t\tthis.each(function() {\n\t\t\t\tvar queue = jQuery.queue( this, type, data );\n\n\t\t\t\t// ensure a hooks for this queue\n\t\t\t\tjQuery._queueHooks( this, type );\n\n\t\t\t\tif ( type === \"fx\" && queue[0] !== \"inprogress\" ) {\n\t\t\t\t\tjQuery.dequeue( this, type );\n\t\t\t\t}\n\t\t\t});\n\t},\n\tdequeue: function( type ) {\n\t\treturn this.each(function() {\n\t\t\tjQuery.dequeue( this, type );\n\t\t});\n\t},\n\t// Based off of the plugin by Clint Helfers, with permission.\n\t// http://blindsignals.com/index.php/2009/07/jquery-delay/\n\tdelay: function( time, type ) {\n\t\ttime = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time;\n\t\ttype = type || \"fx\";\n\n\t\treturn this.queue( type, function( next, hooks ) {\n\t\t\tvar timeout = setTimeout( next, time );\n\t\t\thooks.stop = function() {\n\t\t\t\tclearTimeout( timeout );\n\t\t\t};\n\t\t});\n\t},\n\tclearQueue: function( type ) {\n\t\treturn this.queue( type || \"fx\", [] );\n\t},\n\t// Get a promise resolved when queues of a certain type\n\t// are emptied (fx is the type by default)\n\tpromise: function( type, obj ) {\n\t\tvar tmp,\n\t\t\tcount = 1,\n\t\t\tdefer = jQuery.Deferred(),\n\t\t\telements = this,\n\t\t\ti = this.length,\n\t\t\tresolve = function() {\n\t\t\t\tif ( !( --count ) ) {\n\t\t\t\t\tdefer.resolveWith( elements, [ elements ] );\n\t\t\t\t}\n\t\t\t};\n\n\t\tif ( typeof type !== \"string\" ) {\n\t\t\tobj = type;\n\t\t\ttype = undefined;\n\t\t}\n\t\ttype = type || \"fx\";\n\n\t\twhile( i-- ) {\n\t\t\ttmp = jQuery._data( elements[ i ], type + \"queueHooks\" );\n\t\t\tif ( tmp && tmp.empty ) {\n\t\t\t\tcount++;\n\t\t\t\ttmp.empty.add( resolve );\n\t\t\t}\n\t\t}\n\t\tresolve();\n\t\treturn defer.promise( obj );\n\t}\n});\nvar nodeHook, boolHook,\n\trclass = /[\\t\\r\\n]/g,\n\trreturn = /\\r/g,\n\trfocusable = /^(?:input|select|textarea|button|object)$/i,\n\trclickable = /^(?:a|area)$/i,\n\trboolean = /^(?:checked|selected|autofocus|autoplay|async|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped)$/i,\n\truseDefault = /^(?:checked|selected)$/i,\n\tgetSetAttribute = jQuery.support.getSetAttribute,\n\tgetSetInput = jQuery.support.input;\n\njQuery.fn.extend({\n\tattr: function( name, value ) {\n\t\treturn jQuery.access( this, jQuery.attr, name, value, arguments.length > 1 );\n\t},\n\n\tremoveAttr: function( name ) {\n\t\treturn this.each(function() {\n\t\t\tjQuery.removeAttr( this, name );\n\t\t});\n\t},\n\n\tprop: function( name, value ) {\n\t\treturn jQuery.access( this, jQuery.prop, name, value, arguments.length > 1 );\n\t},\n\n\tremoveProp: function( name ) {\n\t\tname = jQuery.propFix[ name ] || name;\n\t\treturn this.each(function() {\n\t\t\t// try/catch handles cases where IE balks (such as removing a property on window)\n\t\t\ttry {\n\t\t\t\tthis[ name ] = undefined;\n\t\t\t\tdelete this[ name ];\n\t\t\t} catch( e ) {}\n\t\t});\n\t},\n\n\taddClass: function( value ) {\n\t\tvar classes, elem, cur, clazz, j,\n\t\t\ti = 0,\n\t\t\tlen = this.length,\n\t\t\tproceed = typeof value === \"string\" && value;\n\n\t\tif ( jQuery.isFunction( value ) ) {\n\t\t\treturn this.each(function( j ) {\n\t\t\t\tjQuery( this ).addClass( value.call( this, j, this.className ) );\n\t\t\t});\n\t\t}\n\n\t\tif ( proceed ) {\n\t\t\t// The disjunction here is for better compressibility (see removeClass)\n\t\t\tclasses = ( value || \"\" ).match( core_rnotwhite ) || [];\n\n\t\t\tfor ( ; i < len; i++ ) {\n\t\t\t\telem = this[ i ];\n\t\t\t\tcur = elem.nodeType === 1 && ( elem.className ?\n\t\t\t\t\t( \" \" + elem.className + \" \" ).replace( rclass, \" \" ) :\n\t\t\t\t\t\" \"\n\t\t\t\t);\n\n\t\t\t\tif ( cur ) {\n\t\t\t\t\tj = 0;\n\t\t\t\t\twhile ( (clazz = classes[j++]) ) {\n\t\t\t\t\t\tif ( cur.indexOf( \" \" + clazz + \" \" ) < 0 ) {\n\t\t\t\t\t\t\tcur += clazz + \" \";\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\telem.className = jQuery.trim( cur );\n\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\tremoveClass: function( value ) {\n\t\tvar classes, elem, cur, clazz, j,\n\t\t\ti = 0,\n\t\t\tlen = this.length,\n\t\t\tproceed = arguments.length === 0 || typeof value === \"string\" && value;\n\n\t\tif ( jQuery.isFunction( value ) ) {\n\t\t\treturn this.each(function( j ) {\n\t\t\t\tjQuery( this ).removeClass( value.call( this, j, this.className ) );\n\t\t\t});\n\t\t}\n\t\tif ( proceed ) {\n\t\t\tclasses = ( value || \"\" ).match( core_rnotwhite ) || [];\n\n\t\t\tfor ( ; i < len; i++ ) {\n\t\t\t\telem = this[ i ];\n\t\t\t\t// This expression is here for better compressibility (see addClass)\n\t\t\t\tcur = elem.nodeType === 1 && ( elem.className ?\n\t\t\t\t\t( \" \" + elem.className + \" \" ).replace( rclass, \" \" ) :\n\t\t\t\t\t\"\"\n\t\t\t\t);\n\n\t\t\t\tif ( cur ) {\n\t\t\t\t\tj = 0;\n\t\t\t\t\twhile ( (clazz = classes[j++]) ) {\n\t\t\t\t\t\t// Remove *all* instances\n\t\t\t\t\t\twhile ( cur.indexOf( \" \" + clazz + \" \" ) >= 0 ) {\n\t\t\t\t\t\t\tcur = cur.replace( \" \" + clazz + \" \", \" \" );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\telem.className = value ? jQuery.trim( cur ) : \"\";\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\ttoggleClass: function( value, stateVal ) {\n\t\tvar type = typeof value,\n\t\t\tisBool = typeof stateVal === \"boolean\";\n\n\t\tif ( jQuery.isFunction( value ) ) {\n\t\t\treturn this.each(function( i ) {\n\t\t\t\tjQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal );\n\t\t\t});\n\t\t}\n\n\t\treturn this.each(function() {\n\t\t\tif ( type === \"string\" ) {\n\t\t\t\t// toggle individual class names\n\t\t\t\tvar className,\n\t\t\t\t\ti = 0,\n\t\t\t\t\tself = jQuery( this ),\n\t\t\t\t\tstate = stateVal,\n\t\t\t\t\tclassNames = value.match( core_rnotwhite ) || [];\n\n\t\t\t\twhile ( (className = classNames[ i++ ]) ) {\n\t\t\t\t\t// check each className given, space separated list\n\t\t\t\t\tstate = isBool ? state : !self.hasClass( className );\n\t\t\t\t\tself[ state ? \"addClass\" : \"removeClass\" ]( className );\n\t\t\t\t}\n\n\t\t\t// Toggle whole class name\n\t\t\t} else if ( type === core_strundefined || type === \"boolean\" ) {\n\t\t\t\tif ( this.className ) {\n\t\t\t\t\t// store className if set\n\t\t\t\t\tjQuery._data( this, \"__className__\", this.className );\n\t\t\t\t}\n\n\t\t\t\t// If the element has a class name or if we're passed \"false\",\n\t\t\t\t// then remove the whole classname (if there was one, the above saved it).\n\t\t\t\t// Otherwise bring back whatever was previously saved (if anything),\n\t\t\t\t// falling back to the empty string if nothing was stored.\n\t\t\t\tthis.className = this.className || value === false ? \"\" : jQuery._data( this, \"__className__\" ) || \"\";\n\t\t\t}\n\t\t});\n\t},\n\n\thasClass: function( selector ) {\n\t\tvar className = \" \" + selector + \" \",\n\t\t\ti = 0,\n\t\t\tl = this.length;\n\t\tfor ( ; i < l; i++ ) {\n\t\t\tif ( this[i].nodeType === 1 && (\" \" + this[i].className + \" \").replace(rclass, \" \").indexOf( className ) >= 0 ) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\n\t\treturn false;\n\t},\n\n\tval: function( value ) {\n\t\tvar ret, hooks, isFunction,\n\t\t\telem = this[0];\n\n\t\tif ( !arguments.length ) {\n\t\t\tif ( elem ) {\n\t\t\t\thooks = jQuery.valHooks[ elem.type ] || jQuery.valHooks[ elem.nodeName.toLowerCase() ];\n\n\t\t\t\tif ( hooks && \"get\" in hooks && (ret = hooks.get( elem, \"value\" )) !== undefined ) {\n\t\t\t\t\treturn ret;\n\t\t\t\t}\n\n\t\t\t\tret = elem.value;\n\n\t\t\t\treturn typeof ret === \"string\" ?\n\t\t\t\t\t// handle most common string cases\n\t\t\t\t\tret.replace(rreturn, \"\") :\n\t\t\t\t\t// handle cases where value is null/undef or number\n\t\t\t\t\tret == null ? \"\" : ret;\n\t\t\t}\n\n\t\t\treturn;\n\t\t}\n\n\t\tisFunction = jQuery.isFunction( value );\n\n\t\treturn this.each(function( i ) {\n\t\t\tvar val,\n\t\t\t\tself = jQuery(this);\n\n\t\t\tif ( this.nodeType !== 1 ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif ( isFunction ) {\n\t\t\t\tval = value.call( this, i, self.val() );\n\t\t\t} else {\n\t\t\t\tval = value;\n\t\t\t}\n\n\t\t\t// Treat null/undefined as \"\"; convert numbers to string\n\t\t\tif ( val == null ) {\n\t\t\t\tval = \"\";\n\t\t\t} else if ( typeof val === \"number\" ) {\n\t\t\t\tval += \"\";\n\t\t\t} else if ( jQuery.isArray( val ) ) {\n\t\t\t\tval = jQuery.map(val, function ( value ) {\n\t\t\t\t\treturn value == null ? \"\" : value + \"\";\n\t\t\t\t});\n\t\t\t}\n\n\t\t\thooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ];\n\n\t\t\t// If set returns undefined, fall back to normal setting\n\t\t\tif ( !hooks || !(\"set\" in hooks) || hooks.set( this, val, \"value\" ) === undefined ) {\n\t\t\t\tthis.value = val;\n\t\t\t}\n\t\t});\n\t}\n});\n\njQuery.extend({\n\tvalHooks: {\n\t\toption: {\n\t\t\tget: function( elem ) {\n\t\t\t\t// attributes.value is undefined in Blackberry 4.7 but\n\t\t\t\t// uses .value. See #6932\n\t\t\t\tvar val = elem.attributes.value;\n\t\t\t\treturn !val || val.specified ? elem.value : elem.text;\n\t\t\t}\n\t\t},\n\t\tselect: {\n\t\t\tget: function( elem ) {\n\t\t\t\tvar value, option,\n\t\t\t\t\toptions = elem.options,\n\t\t\t\t\tindex = elem.selectedIndex,\n\t\t\t\t\tone = elem.type === \"select-one\" || index < 0,\n\t\t\t\t\tvalues = one ? null : [],\n\t\t\t\t\tmax = one ? index + 1 : options.length,\n\t\t\t\t\ti = index < 0 ?\n\t\t\t\t\t\tmax :\n\t\t\t\t\t\tone ? index : 0;\n\n\t\t\t\t// Loop through all the selected options\n\t\t\t\tfor ( ; i < max; i++ ) {\n\t\t\t\t\toption = options[ i ];\n\n\t\t\t\t\t// oldIE doesn't update selected after form reset (#2551)\n\t\t\t\t\tif ( ( option.selected || i === index ) &&\n\t\t\t\t\t\t\t// Don't return options that are disabled or in a disabled optgroup\n\t\t\t\t\t\t\t( jQuery.support.optDisabled ? !option.disabled : option.getAttribute(\"disabled\") === null ) &&\n\t\t\t\t\t\t\t( !option.parentNode.disabled || !jQuery.nodeName( option.parentNode, \"optgroup\" ) ) ) {\n\n\t\t\t\t\t\t// Get the specific value for the option\n\t\t\t\t\t\tvalue = jQuery( option ).val();\n\n\t\t\t\t\t\t// We don't need an array for one selects\n\t\t\t\t\t\tif ( one ) {\n\t\t\t\t\t\t\treturn value;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Multi-Selects return an array\n\t\t\t\t\t\tvalues.push( value );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn values;\n\t\t\t},\n\n\t\t\tset: function( elem, value ) {\n\t\t\t\tvar values = jQuery.makeArray( value );\n\n\t\t\t\tjQuery(elem).find(\"option\").each(function() {\n\t\t\t\t\tthis.selected = jQuery.inArray( jQuery(this).val(), values ) >= 0;\n\t\t\t\t});\n\n\t\t\t\tif ( !values.length ) {\n\t\t\t\t\telem.selectedIndex = -1;\n\t\t\t\t}\n\t\t\t\treturn values;\n\t\t\t}\n\t\t}\n\t},\n\n\tattr: function( elem, name, value ) {\n\t\tvar hooks, notxml, ret,\n\t\t\tnType = elem.nodeType;\n\n\t\t// don't get/set attributes on text, comment and attribute nodes\n\t\tif ( !elem || nType === 3 || nType === 8 || nType === 2 ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Fallback to prop when attributes are not supported\n\t\tif ( typeof elem.getAttribute === core_strundefined ) {\n\t\t\treturn jQuery.prop( elem, name, value );\n\t\t}\n\n\t\tnotxml = nType !== 1 || !jQuery.isXMLDoc( elem );\n\n\t\t// All attributes are lowercase\n\t\t// Grab necessary hook if one is defined\n\t\tif ( notxml ) {\n\t\t\tname = name.toLowerCase();\n\t\t\thooks = jQuery.attrHooks[ name ] || ( rboolean.test( name ) ? boolHook : nodeHook );\n\t\t}\n\n\t\tif ( value !== undefined ) {\n\n\t\t\tif ( value === null ) {\n\t\t\t\tjQuery.removeAttr( elem, name );\n\n\t\t\t} else if ( hooks && notxml && \"set\" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) {\n\t\t\t\treturn ret;\n\n\t\t\t} else {\n\t\t\t\telem.setAttribute( name, value + \"\" );\n\t\t\t\treturn value;\n\t\t\t}\n\n\t\t} else if ( hooks && notxml && \"get\" in hooks && (ret = hooks.get( elem, name )) !== null ) {\n\t\t\treturn ret;\n\n\t\t} else {\n\n\t\t\t// In IE9+, Flash objects don't have .getAttribute (#12945)\n\t\t\t// Support: IE9+\n\t\t\tif ( typeof elem.getAttribute !== core_strundefined ) {\n\t\t\t\tret =  elem.getAttribute( name );\n\t\t\t}\n\n\t\t\t// Non-existent attributes return null, we normalize to undefined\n\t\t\treturn ret == null ?\n\t\t\t\tundefined :\n\t\t\t\tret;\n\t\t}\n\t},\n\n\tremoveAttr: function( elem, value ) {\n\t\tvar name, propName,\n\t\t\ti = 0,\n\t\t\tattrNames = value && value.match( core_rnotwhite );\n\n\t\tif ( attrNames && elem.nodeType === 1 ) {\n\t\t\twhile ( (name = attrNames[i++]) ) {\n\t\t\t\tpropName = jQuery.propFix[ name ] || name;\n\n\t\t\t\t// Boolean attributes get special treatment (#10870)\n\t\t\t\tif ( rboolean.test( name ) ) {\n\t\t\t\t\t// Set corresponding property to false for boolean attributes\n\t\t\t\t\t// Also clear defaultChecked/defaultSelected (if appropriate) for IE<8\n\t\t\t\t\tif ( !getSetAttribute && ruseDefault.test( name ) ) {\n\t\t\t\t\t\telem[ jQuery.camelCase( \"default-\" + name ) ] =\n\t\t\t\t\t\t\telem[ propName ] = false;\n\t\t\t\t\t} else {\n\t\t\t\t\t\telem[ propName ] = false;\n\t\t\t\t\t}\n\n\t\t\t\t// See #9699 for explanation of this approach (setting first, then removal)\n\t\t\t\t} else {\n\t\t\t\t\tjQuery.attr( elem, name, \"\" );\n\t\t\t\t}\n\n\t\t\t\telem.removeAttribute( getSetAttribute ? name : propName );\n\t\t\t}\n\t\t}\n\t},\n\n\tattrHooks: {\n\t\ttype: {\n\t\t\tset: function( elem, value ) {\n\t\t\t\tif ( !jQuery.support.radioValue && value === \"radio\" && jQuery.nodeName(elem, \"input\") ) {\n\t\t\t\t\t// Setting the type on a radio button after the value resets the value in IE6-9\n\t\t\t\t\t// Reset value to default in case type is set after value during creation\n\t\t\t\t\tvar val = elem.value;\n\t\t\t\t\telem.setAttribute( \"type\", value );\n\t\t\t\t\tif ( val ) {\n\t\t\t\t\t\telem.value = val;\n\t\t\t\t\t}\n\t\t\t\t\treturn value;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\n\tpropFix: {\n\t\ttabindex: \"tabIndex\",\n\t\treadonly: \"readOnly\",\n\t\t\"for\": \"htmlFor\",\n\t\t\"class\": \"className\",\n\t\tmaxlength: \"maxLength\",\n\t\tcellspacing: \"cellSpacing\",\n\t\tcellpadding: \"cellPadding\",\n\t\trowspan: \"rowSpan\",\n\t\tcolspan: \"colSpan\",\n\t\tusemap: \"useMap\",\n\t\tframeborder: \"frameBorder\",\n\t\tcontenteditable: \"contentEditable\"\n\t},\n\n\tprop: function( elem, name, value ) {\n\t\tvar ret, hooks, notxml,\n\t\t\tnType = elem.nodeType;\n\n\t\t// don't get/set properties on text, comment and attribute nodes\n\t\tif ( !elem || nType === 3 || nType === 8 || nType === 2 ) {\n\t\t\treturn;\n\t\t}\n\n\t\tnotxml = nType !== 1 || !jQuery.isXMLDoc( elem );\n\n\t\tif ( notxml ) {\n\t\t\t// Fix name and attach hooks\n\t\t\tname = jQuery.propFix[ name ] || name;\n\t\t\thooks = jQuery.propHooks[ name ];\n\t\t}\n\n\t\tif ( value !== undefined ) {\n\t\t\tif ( hooks && \"set\" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) {\n\t\t\t\treturn ret;\n\n\t\t\t} else {\n\t\t\t\treturn ( elem[ name ] = value );\n\t\t\t}\n\n\t\t} else {\n\t\t\tif ( hooks && \"get\" in hooks && (ret = hooks.get( elem, name )) !== null ) {\n\t\t\t\treturn ret;\n\n\t\t\t} else {\n\t\t\t\treturn elem[ name ];\n\t\t\t}\n\t\t}\n\t},\n\n\tpropHooks: {\n\t\ttabIndex: {\n\t\t\tget: function( elem ) {\n\t\t\t\t// elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set\n\t\t\t\t// http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/\n\t\t\t\tvar attributeNode = elem.getAttributeNode(\"tabindex\");\n\n\t\t\t\treturn attributeNode && attributeNode.specified ?\n\t\t\t\t\tparseInt( attributeNode.value, 10 ) :\n\t\t\t\t\trfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ?\n\t\t\t\t\t\t0 :\n\t\t\t\t\t\tundefined;\n\t\t\t}\n\t\t}\n\t}\n});\n\n// Hook for boolean attributes\nboolHook = {\n\tget: function( elem, name ) {\n\t\tvar\n\t\t\t// Use .prop to determine if this attribute is understood as boolean\n\t\t\tprop = jQuery.prop( elem, name ),\n\n\t\t\t// Fetch it accordingly\n\t\t\tattr = typeof prop === \"boolean\" && elem.getAttribute( name ),\n\t\t\tdetail = typeof prop === \"boolean\" ?\n\n\t\t\t\tgetSetInput && getSetAttribute ?\n\t\t\t\t\tattr != null :\n\t\t\t\t\t// oldIE fabricates an empty string for missing boolean attributes\n\t\t\t\t\t// and conflates checked/selected into attroperties\n\t\t\t\t\truseDefault.test( name ) ?\n\t\t\t\t\t\telem[ jQuery.camelCase( \"default-\" + name ) ] :\n\t\t\t\t\t\t!!attr :\n\n\t\t\t\t// fetch an attribute node for properties not recognized as boolean\n\t\t\t\telem.getAttributeNode( name );\n\n\t\treturn detail && detail.value !== false ?\n\t\t\tname.toLowerCase() :\n\t\t\tundefined;\n\t},\n\tset: function( elem, value, name ) {\n\t\tif ( value === false ) {\n\t\t\t// Remove boolean attributes when set to false\n\t\t\tjQuery.removeAttr( elem, name );\n\t\t} else if ( getSetInput && getSetAttribute || !ruseDefault.test( name ) ) {\n\t\t\t// IE<8 needs the *property* name\n\t\t\telem.setAttribute( !getSetAttribute && jQuery.propFix[ name ] || name, name );\n\n\t\t// Use defaultChecked and defaultSelected for oldIE\n\t\t} else {\n\t\t\telem[ jQuery.camelCase( \"default-\" + name ) ] = elem[ name ] = true;\n\t\t}\n\n\t\treturn name;\n\t}\n};\n\n// fix oldIE value attroperty\nif ( !getSetInput || !getSetAttribute ) {\n\tjQuery.attrHooks.value = {\n\t\tget: function( elem, name ) {\n\t\t\tvar ret = elem.getAttributeNode( name );\n\t\t\treturn jQuery.nodeName( elem, \"input\" ) ?\n\n\t\t\t\t// Ignore the value *property* by using defaultValue\n\t\t\t\telem.defaultValue :\n\n\t\t\t\tret && ret.specified ? ret.value : undefined;\n\t\t},\n\t\tset: function( elem, value, name ) {\n\t\t\tif ( jQuery.nodeName( elem, \"input\" ) ) {\n\t\t\t\t// Does not return so that setAttribute is also used\n\t\t\t\telem.defaultValue = value;\n\t\t\t} else {\n\t\t\t\t// Use nodeHook if defined (#1954); otherwise setAttribute is fine\n\t\t\t\treturn nodeHook && nodeHook.set( elem, value, name );\n\t\t\t}\n\t\t}\n\t};\n}\n\n// IE6/7 do not support getting/setting some attributes with get/setAttribute\nif ( !getSetAttribute ) {\n\n\t// Use this for any attribute in IE6/7\n\t// This fixes almost every IE6/7 issue\n\tnodeHook = jQuery.valHooks.button = {\n\t\tget: function( elem, name ) {\n\t\t\tvar ret = elem.getAttributeNode( name );\n\t\t\treturn ret && ( name === \"id\" || name === \"name\" || name === \"coords\" ? ret.value !== \"\" : ret.specified ) ?\n\t\t\t\tret.value :\n\t\t\t\tundefined;\n\t\t},\n\t\tset: function( elem, value, name ) {\n\t\t\t// Set the existing or create a new attribute node\n\t\t\tvar ret = elem.getAttributeNode( name );\n\t\t\tif ( !ret ) {\n\t\t\t\telem.setAttributeNode(\n\t\t\t\t\t(ret = elem.ownerDocument.createAttribute( name ))\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tret.value = value += \"\";\n\n\t\t\t// Break association with cloned elements by also using setAttribute (#9646)\n\t\t\treturn name === \"value\" || value === elem.getAttribute( name ) ?\n\t\t\t\tvalue :\n\t\t\t\tundefined;\n\t\t}\n\t};\n\n\t// Set contenteditable to false on removals(#10429)\n\t// Setting to empty string throws an error as an invalid value\n\tjQuery.attrHooks.contenteditable = {\n\t\tget: nodeHook.get,\n\t\tset: function( elem, value, name ) {\n\t\t\tnodeHook.set( elem, value === \"\" ? false : value, name );\n\t\t}\n\t};\n\n\t// Set width and height to auto instead of 0 on empty string( Bug #8150 )\n\t// This is for removals\n\tjQuery.each([ \"width\", \"height\" ], function( i, name ) {\n\t\tjQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], {\n\t\t\tset: function( elem, value ) {\n\t\t\t\tif ( value === \"\" ) {\n\t\t\t\t\telem.setAttribute( name, \"auto\" );\n\t\t\t\t\treturn value;\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t});\n}\n\n\n// Some attributes require a special call on IE\n// http://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx\nif ( !jQuery.support.hrefNormalized ) {\n\tjQuery.each([ \"href\", \"src\", \"width\", \"height\" ], function( i, name ) {\n\t\tjQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], {\n\t\t\tget: function( elem ) {\n\t\t\t\tvar ret = elem.getAttribute( name, 2 );\n\t\t\t\treturn ret == null ? undefined : ret;\n\t\t\t}\n\t\t});\n\t});\n\n\t// href/src property should get the full normalized URL (#10299/#12915)\n\tjQuery.each([ \"href\", \"src\" ], function( i, name ) {\n\t\tjQuery.propHooks[ name ] = {\n\t\t\tget: function( elem ) {\n\t\t\t\treturn elem.getAttribute( name, 4 );\n\t\t\t}\n\t\t};\n\t});\n}\n\nif ( !jQuery.support.style ) {\n\tjQuery.attrHooks.style = {\n\t\tget: function( elem ) {\n\t\t\t// Return undefined in the case of empty string\n\t\t\t// Note: IE uppercases css property names, but if we were to .toLowerCase()\n\t\t\t// .cssText, that would destroy case senstitivity in URL's, like in \"background\"\n\t\t\treturn elem.style.cssText || undefined;\n\t\t},\n\t\tset: function( elem, value ) {\n\t\t\treturn ( elem.style.cssText = value + \"\" );\n\t\t}\n\t};\n}\n\n// Safari mis-reports the default selected property of an option\n// Accessing the parent's selectedIndex property fixes it\nif ( !jQuery.support.optSelected ) {\n\tjQuery.propHooks.selected = jQuery.extend( jQuery.propHooks.selected, {\n\t\tget: function( elem ) {\n\t\t\tvar parent = elem.parentNode;\n\n\t\t\tif ( parent ) {\n\t\t\t\tparent.selectedIndex;\n\n\t\t\t\t// Make sure that it also works with optgroups, see #5701\n\t\t\t\tif ( parent.parentNode ) {\n\t\t\t\t\tparent.parentNode.selectedIndex;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn null;\n\t\t}\n\t});\n}\n\n// IE6/7 call enctype encoding\nif ( !jQuery.support.enctype ) {\n\tjQuery.propFix.enctype = \"encoding\";\n}\n\n// Radios and checkboxes getter/setter\nif ( !jQuery.support.checkOn ) {\n\tjQuery.each([ \"radio\", \"checkbox\" ], function() {\n\t\tjQuery.valHooks[ this ] = {\n\t\t\tget: function( elem ) {\n\t\t\t\t// Handle the case where in Webkit \"\" is returned instead of \"on\" if a value isn't specified\n\t\t\t\treturn elem.getAttribute(\"value\") === null ? \"on\" : elem.value;\n\t\t\t}\n\t\t};\n\t});\n}\njQuery.each([ \"radio\", \"checkbox\" ], function() {\n\tjQuery.valHooks[ this ] = jQuery.extend( jQuery.valHooks[ this ], {\n\t\tset: function( elem, value ) {\n\t\t\tif ( jQuery.isArray( value ) ) {\n\t\t\t\treturn ( elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0 );\n\t\t\t}\n\t\t}\n\t});\n});\nvar rformElems = /^(?:input|select|textarea)$/i,\n\trkeyEvent = /^key/,\n\trmouseEvent = /^(?:mouse|contextmenu)|click/,\n\trfocusMorph = /^(?:focusinfocus|focusoutblur)$/,\n\trtypenamespace = /^([^.]*)(?:\\.(.+)|)$/;\n\nfunction returnTrue() {\n\treturn true;\n}\n\nfunction returnFalse() {\n\treturn false;\n}\n\n/*\n * Helper functions for managing events -- not part of the public interface.\n * Props to Dean Edwards' addEvent library for many of the ideas.\n */\njQuery.event = {\n\n\tglobal: {},\n\n\tadd: function( elem, types, handler, data, selector ) {\n\t\tvar tmp, events, t, handleObjIn,\n\t\t\tspecial, eventHandle, handleObj,\n\t\t\thandlers, type, namespaces, origType,\n\t\t\telemData = jQuery._data( elem );\n\n\t\t// Don't attach events to noData or text/comment nodes (but allow plain objects)\n\t\tif ( !elemData ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Caller can pass in an object of custom data in lieu of the handler\n\t\tif ( handler.handler ) {\n\t\t\thandleObjIn = handler;\n\t\t\thandler = handleObjIn.handler;\n\t\t\tselector = handleObjIn.selector;\n\t\t}\n\n\t\t// Make sure that the handler has a unique ID, used to find/remove it later\n\t\tif ( !handler.guid ) {\n\t\t\thandler.guid = jQuery.guid++;\n\t\t}\n\n\t\t// Init the element's event structure and main handler, if this is the first\n\t\tif ( !(events = elemData.events) ) {\n\t\t\tevents = elemData.events = {};\n\t\t}\n\t\tif ( !(eventHandle = elemData.handle) ) {\n\t\t\teventHandle = elemData.handle = function( e ) {\n\t\t\t\t// Discard the second event of a jQuery.event.trigger() and\n\t\t\t\t// when an event is called after a page has unloaded\n\t\t\t\treturn typeof jQuery !== core_strundefined && (!e || jQuery.event.triggered !== e.type) ?\n\t\t\t\t\tjQuery.event.dispatch.apply( eventHandle.elem, arguments ) :\n\t\t\t\t\tundefined;\n\t\t\t};\n\t\t\t// Add elem as a property of the handle fn to prevent a memory leak with IE non-native events\n\t\t\teventHandle.elem = elem;\n\t\t}\n\n\t\t// Handle multiple events separated by a space\n\t\t// jQuery(...).bind(\"mouseover mouseout\", fn);\n\t\ttypes = ( types || \"\" ).match( core_rnotwhite ) || [\"\"];\n\t\tt = types.length;\n\t\twhile ( t-- ) {\n\t\t\ttmp = rtypenamespace.exec( types[t] ) || [];\n\t\t\ttype = origType = tmp[1];\n\t\t\tnamespaces = ( tmp[2] || \"\" ).split( \".\" ).sort();\n\n\t\t\t// If event changes its type, use the special event handlers for the changed type\n\t\t\tspecial = jQuery.event.special[ type ] || {};\n\n\t\t\t// If selector defined, determine special event api type, otherwise given type\n\t\t\ttype = ( selector ? special.delegateType : special.bindType ) || type;\n\n\t\t\t// Update special based on newly reset type\n\t\t\tspecial = jQuery.event.special[ type ] || {};\n\n\t\t\t// handleObj is passed to all event handlers\n\t\t\thandleObj = jQuery.extend({\n\t\t\t\ttype: type,\n\t\t\t\torigType: origType,\n\t\t\t\tdata: data,\n\t\t\t\thandler: handler,\n\t\t\t\tguid: handler.guid,\n\t\t\t\tselector: selector,\n\t\t\t\tneedsContext: selector && jQuery.expr.match.needsContext.test( selector ),\n\t\t\t\tnamespace: namespaces.join(\".\")\n\t\t\t}, handleObjIn );\n\n\t\t\t// Init the event handler queue if we're the first\n\t\t\tif ( !(handlers = events[ type ]) ) {\n\t\t\t\thandlers = events[ type ] = [];\n\t\t\t\thandlers.delegateCount = 0;\n\n\t\t\t\t// Only use addEventListener/attachEvent if the special events handler returns false\n\t\t\t\tif ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) {\n\t\t\t\t\t// Bind the global event handler to the element\n\t\t\t\t\tif ( elem.addEventListener ) {\n\t\t\t\t\t\telem.addEventListener( type, eventHandle, false );\n\n\t\t\t\t\t} else if ( elem.attachEvent ) {\n\t\t\t\t\t\telem.attachEvent( \"on\" + type, eventHandle );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( special.add ) {\n\t\t\t\tspecial.add.call( elem, handleObj );\n\n\t\t\t\tif ( !handleObj.handler.guid ) {\n\t\t\t\t\thandleObj.handler.guid = handler.guid;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Add to the element's handler list, delegates in front\n\t\t\tif ( selector ) {\n\t\t\t\thandlers.splice( handlers.delegateCount++, 0, handleObj );\n\t\t\t} else {\n\t\t\t\thandlers.push( handleObj );\n\t\t\t}\n\n\t\t\t// Keep track of which events have ever been used, for event optimization\n\t\t\tjQuery.event.global[ type ] = true;\n\t\t}\n\n\t\t// Nullify elem to prevent memory leaks in IE\n\t\telem = null;\n\t},\n\n\t// Detach an event or set of events from an element\n\tremove: function( elem, types, handler, selector, mappedTypes ) {\n\t\tvar j, handleObj, tmp,\n\t\t\torigCount, t, events,\n\t\t\tspecial, handlers, type,\n\t\t\tnamespaces, origType,\n\t\t\telemData = jQuery.hasData( elem ) && jQuery._data( elem );\n\n\t\tif ( !elemData || !(events = elemData.events) ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Once for each type.namespace in types; type may be omitted\n\t\ttypes = ( types || \"\" ).match( core_rnotwhite ) || [\"\"];\n\t\tt = types.length;\n\t\twhile ( t-- ) {\n\t\t\ttmp = rtypenamespace.exec( types[t] ) || [];\n\t\t\ttype = origType = tmp[1];\n\t\t\tnamespaces = ( tmp[2] || \"\" ).split( \".\" ).sort();\n\n\t\t\t// Unbind all events (on this namespace, if provided) for the element\n\t\t\tif ( !type ) {\n\t\t\t\tfor ( type in events ) {\n\t\t\t\t\tjQuery.event.remove( elem, type + types[ t ], handler, selector, true );\n\t\t\t\t}\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tspecial = jQuery.event.special[ type ] || {};\n\t\t\ttype = ( selector ? special.delegateType : special.bindType ) || type;\n\t\t\thandlers = events[ type ] || [];\n\t\t\ttmp = tmp[2] && new RegExp( \"(^|\\\\.)\" + namespaces.join(\"\\\\.(?:.*\\\\.|)\") + \"(\\\\.|$)\" );\n\n\t\t\t// Remove matching events\n\t\t\torigCount = j = handlers.length;\n\t\t\twhile ( j-- ) {\n\t\t\t\thandleObj = handlers[ j ];\n\n\t\t\t\tif ( ( mappedTypes || origType === handleObj.origType ) &&\n\t\t\t\t\t( !handler || handler.guid === handleObj.guid ) &&\n\t\t\t\t\t( !tmp || tmp.test( handleObj.namespace ) ) &&\n\t\t\t\t\t( !selector || selector === handleObj.selector || selector === \"**\" && handleObj.selector ) ) {\n\t\t\t\t\thandlers.splice( j, 1 );\n\n\t\t\t\t\tif ( handleObj.selector ) {\n\t\t\t\t\t\thandlers.delegateCount--;\n\t\t\t\t\t}\n\t\t\t\t\tif ( special.remove ) {\n\t\t\t\t\t\tspecial.remove.call( elem, handleObj );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Remove generic event handler if we removed something and no more handlers exist\n\t\t\t// (avoids potential for endless recursion during removal of special event handlers)\n\t\t\tif ( origCount && !handlers.length ) {\n\t\t\t\tif ( !special.teardown || special.teardown.call( elem, namespaces, elemData.handle ) === false ) {\n\t\t\t\t\tjQuery.removeEvent( elem, type, elemData.handle );\n\t\t\t\t}\n\n\t\t\t\tdelete events[ type ];\n\t\t\t}\n\t\t}\n\n\t\t// Remove the expando if it's no longer used\n\t\tif ( jQuery.isEmptyObject( events ) ) {\n\t\t\tdelete elemData.handle;\n\n\t\t\t// removeData also checks for emptiness and clears the expando if empty\n\t\t\t// so use it instead of delete\n\t\t\tjQuery._removeData( elem, \"events\" );\n\t\t}\n\t},\n\n\ttrigger: function( event, data, elem, onlyHandlers ) {\n\t\tvar handle, ontype, cur,\n\t\t\tbubbleType, special, tmp, i,\n\t\t\teventPath = [ elem || document ],\n\t\t\ttype = core_hasOwn.call( event, \"type\" ) ? event.type : event,\n\t\t\tnamespaces = core_hasOwn.call( event, \"namespace\" ) ? event.namespace.split(\".\") : [];\n\n\t\tcur = tmp = elem = elem || document;\n\n\t\t// Don't do events on text and comment nodes\n\t\tif ( elem.nodeType === 3 || elem.nodeType === 8 ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// focus/blur morphs to focusin/out; ensure we're not firing them right now\n\t\tif ( rfocusMorph.test( type + jQuery.event.triggered ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( type.indexOf(\".\") >= 0 ) {\n\t\t\t// Namespaced trigger; create a regexp to match event type in handle()\n\t\t\tnamespaces = type.split(\".\");\n\t\t\ttype = namespaces.shift();\n\t\t\tnamespaces.sort();\n\t\t}\n\t\tontype = type.indexOf(\":\") < 0 && \"on\" + type;\n\n\t\t// Caller can pass in a jQuery.Event object, Object, or just an event type string\n\t\tevent = event[ jQuery.expando ] ?\n\t\t\tevent :\n\t\t\tnew jQuery.Event( type, typeof event === \"object\" && event );\n\n\t\tevent.isTrigger = true;\n\t\tevent.namespace = namespaces.join(\".\");\n\t\tevent.namespace_re = event.namespace ?\n\t\t\tnew RegExp( \"(^|\\\\.)\" + namespaces.join(\"\\\\.(?:.*\\\\.|)\") + \"(\\\\.|$)\" ) :\n\t\t\tnull;\n\n\t\t// Clean up the event in case it is being reused\n\t\tevent.result = undefined;\n\t\tif ( !event.target ) {\n\t\t\tevent.target = elem;\n\t\t}\n\n\t\t// Clone any incoming data and prepend the event, creating the handler arg list\n\t\tdata = data == null ?\n\t\t\t[ event ] :\n\t\t\tjQuery.makeArray( data, [ event ] );\n\n\t\t// Allow special events to draw outside the lines\n\t\tspecial = jQuery.event.special[ type ] || {};\n\t\tif ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Determine event propagation path in advance, per W3C events spec (#9951)\n\t\t// Bubble up to document, then to window; watch for a global ownerDocument var (#9724)\n\t\tif ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) {\n\n\t\t\tbubbleType = special.delegateType || type;\n\t\t\tif ( !rfocusMorph.test( bubbleType + type ) ) {\n\t\t\t\tcur = cur.parentNode;\n\t\t\t}\n\t\t\tfor ( ; cur; cur = cur.parentNode ) {\n\t\t\t\teventPath.push( cur );\n\t\t\t\ttmp = cur;\n\t\t\t}\n\n\t\t\t// Only add window if we got to document (e.g., not plain obj or detached DOM)\n\t\t\tif ( tmp === (elem.ownerDocument || document) ) {\n\t\t\t\teventPath.push( tmp.defaultView || tmp.parentWindow || window );\n\t\t\t}\n\t\t}\n\n\t\t// Fire handlers on the event path\n\t\ti = 0;\n\t\twhile ( (cur = eventPath[i++]) && !event.isPropagationStopped() ) {\n\n\t\t\tevent.type = i > 1 ?\n\t\t\t\tbubbleType :\n\t\t\t\tspecial.bindType || type;\n\n\t\t\t// jQuery handler\n\t\t\thandle = ( jQuery._data( cur, \"events\" ) || {} )[ event.type ] && jQuery._data( cur, \"handle\" );\n\t\t\tif ( handle ) {\n\t\t\t\thandle.apply( cur, data );\n\t\t\t}\n\n\t\t\t// Native handler\n\t\t\thandle = ontype && cur[ ontype ];\n\t\t\tif ( handle && jQuery.acceptData( cur ) && handle.apply && handle.apply( cur, data ) === false ) {\n\t\t\t\tevent.preventDefault();\n\t\t\t}\n\t\t}\n\t\tevent.type = type;\n\n\t\t// If nobody prevented the default action, do it now\n\t\tif ( !onlyHandlers && !event.isDefaultPrevented() ) {\n\n\t\t\tif ( (!special._default || special._default.apply( elem.ownerDocument, data ) === false) &&\n\t\t\t\t!(type === \"click\" && jQuery.nodeName( elem, \"a\" )) && jQuery.acceptData( elem ) ) {\n\n\t\t\t\t// Call a native DOM method on the target with the same name name as the event.\n\t\t\t\t// Can't use an .isFunction() check here because IE6/7 fails that test.\n\t\t\t\t// Don't do default actions on window, that's where global variables be (#6170)\n\t\t\t\tif ( ontype && elem[ type ] && !jQuery.isWindow( elem ) ) {\n\n\t\t\t\t\t// Don't re-trigger an onFOO event when we call its FOO() method\n\t\t\t\t\ttmp = elem[ ontype ];\n\n\t\t\t\t\tif ( tmp ) {\n\t\t\t\t\t\telem[ ontype ] = null;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Prevent re-triggering of the same event, since we already bubbled it above\n\t\t\t\t\tjQuery.event.triggered = type;\n\t\t\t\t\ttry {\n\t\t\t\t\t\telem[ type ]();\n\t\t\t\t\t} catch ( e ) {\n\t\t\t\t\t\t// IE<9 dies on focus/blur to hidden element (#1486,#12518)\n\t\t\t\t\t\t// only reproducible on winXP IE8 native, not IE9 in IE8 mode\n\t\t\t\t\t}\n\t\t\t\t\tjQuery.event.triggered = undefined;\n\n\t\t\t\t\tif ( tmp ) {\n\t\t\t\t\t\telem[ ontype ] = tmp;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn event.result;\n\t},\n\n\tdispatch: function( event ) {\n\n\t\t// Make a writable jQuery.Event from the native event object\n\t\tevent = jQuery.event.fix( event );\n\n\t\tvar i, ret, handleObj, matched, j,\n\t\t\thandlerQueue = [],\n\t\t\targs = core_slice.call( arguments ),\n\t\t\thandlers = ( jQuery._data( this, \"events\" ) || {} )[ event.type ] || [],\n\t\t\tspecial = jQuery.event.special[ event.type ] || {};\n\n\t\t// Use the fix-ed jQuery.Event rather than the (read-only) native event\n\t\targs[0] = event;\n\t\tevent.delegateTarget = this;\n\n\t\t// Call the preDispatch hook for the mapped type, and let it bail if desired\n\t\tif ( special.preDispatch && special.preDispatch.call( this, event ) === false ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Determine handlers\n\t\thandlerQueue = jQuery.event.handlers.call( this, event, handlers );\n\n\t\t// Run delegates first; they may want to stop propagation beneath us\n\t\ti = 0;\n\t\twhile ( (matched = handlerQueue[ i++ ]) && !event.isPropagationStopped() ) {\n\t\t\tevent.currentTarget = matched.elem;\n\n\t\t\tj = 0;\n\t\t\twhile ( (handleObj = matched.handlers[ j++ ]) && !event.isImmediatePropagationStopped() ) {\n\n\t\t\t\t// Triggered event must either 1) have no namespace, or\n\t\t\t\t// 2) have namespace(s) a subset or equal to those in the bound event (both can have no namespace).\n\t\t\t\tif ( !event.namespace_re || event.namespace_re.test( handleObj.namespace ) ) {\n\n\t\t\t\t\tevent.handleObj = handleObj;\n\t\t\t\t\tevent.data = handleObj.data;\n\n\t\t\t\t\tret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler )\n\t\t\t\t\t\t\t.apply( matched.elem, args );\n\n\t\t\t\t\tif ( ret !== undefined ) {\n\t\t\t\t\t\tif ( (event.result = ret) === false ) {\n\t\t\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\t\t\tevent.stopPropagation();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Call the postDispatch hook for the mapped type\n\t\tif ( special.postDispatch ) {\n\t\t\tspecial.postDispatch.call( this, event );\n\t\t}\n\n\t\treturn event.result;\n\t},\n\n\thandlers: function( event, handlers ) {\n\t\tvar sel, handleObj, matches, i,\n\t\t\thandlerQueue = [],\n\t\t\tdelegateCount = handlers.delegateCount,\n\t\t\tcur = event.target;\n\n\t\t// Find delegate handlers\n\t\t// Black-hole SVG <use> instance trees (#13180)\n\t\t// Avoid non-left-click bubbling in Firefox (#3861)\n\t\tif ( delegateCount && cur.nodeType && (!event.button || event.type !== \"click\") ) {\n\n\t\t\tfor ( ; cur != this; cur = cur.parentNode || this ) {\n\n\t\t\t\t// Don't check non-elements (#13208)\n\t\t\t\t// Don't process clicks on disabled elements (#6911, #8165, #11382, #11764)\n\t\t\t\tif ( cur.nodeType === 1 && (cur.disabled !== true || event.type !== \"click\") ) {\n\t\t\t\t\tmatches = [];\n\t\t\t\t\tfor ( i = 0; i < delegateCount; i++ ) {\n\t\t\t\t\t\thandleObj = handlers[ i ];\n\n\t\t\t\t\t\t// Don't conflict with Object.prototype properties (#13203)\n\t\t\t\t\t\tsel = handleObj.selector + \" \";\n\n\t\t\t\t\t\tif ( matches[ sel ] === undefined ) {\n\t\t\t\t\t\t\tmatches[ sel ] = handleObj.needsContext ?\n\t\t\t\t\t\t\t\tjQuery( sel, this ).index( cur ) >= 0 :\n\t\t\t\t\t\t\t\tjQuery.find( sel, this, null, [ cur ] ).length;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif ( matches[ sel ] ) {\n\t\t\t\t\t\t\tmatches.push( handleObj );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif ( matches.length ) {\n\t\t\t\t\t\thandlerQueue.push({ elem: cur, handlers: matches });\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Add the remaining (directly-bound) handlers\n\t\tif ( delegateCount < handlers.length ) {\n\t\t\thandlerQueue.push({ elem: this, handlers: handlers.slice( delegateCount ) });\n\t\t}\n\n\t\treturn handlerQueue;\n\t},\n\n\tfix: function( event ) {\n\t\tif ( event[ jQuery.expando ] ) {\n\t\t\treturn event;\n\t\t}\n\n\t\t// Create a writable copy of the event object and normalize some properties\n\t\tvar i, prop, copy,\n\t\t\ttype = event.type,\n\t\t\toriginalEvent = event,\n\t\t\tfixHook = this.fixHooks[ type ];\n\n\t\tif ( !fixHook ) {\n\t\t\tthis.fixHooks[ type ] = fixHook =\n\t\t\t\trmouseEvent.test( type ) ? this.mouseHooks :\n\t\t\t\trkeyEvent.test( type ) ? this.keyHooks :\n\t\t\t\t{};\n\t\t}\n\t\tcopy = fixHook.props ? this.props.concat( fixHook.props ) : this.props;\n\n\t\tevent = new jQuery.Event( originalEvent );\n\n\t\ti = copy.length;\n\t\twhile ( i-- ) {\n\t\t\tprop = copy[ i ];\n\t\t\tevent[ prop ] = originalEvent[ prop ];\n\t\t}\n\n\t\t// Support: IE<9\n\t\t// Fix target property (#1925)\n\t\tif ( !event.target ) {\n\t\t\tevent.target = originalEvent.srcElement || document;\n\t\t}\n\n\t\t// Support: Chrome 23+, Safari?\n\t\t// Target should not be a text node (#504, #13143)\n\t\tif ( event.target.nodeType === 3 ) {\n\t\t\tevent.target = event.target.parentNode;\n\t\t}\n\n\t\t// Support: IE<9\n\t\t// For mouse/key events, metaKey==false if it's undefined (#3368, #11328)\n\t\tevent.metaKey = !!event.metaKey;\n\n\t\treturn fixHook.filter ? fixHook.filter( event, originalEvent ) : event;\n\t},\n\n\t// Includes some event props shared by KeyEvent and MouseEvent\n\tprops: \"altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which\".split(\" \"),\n\n\tfixHooks: {},\n\n\tkeyHooks: {\n\t\tprops: \"char charCode key keyCode\".split(\" \"),\n\t\tfilter: function( event, original ) {\n\n\t\t\t// Add which for key events\n\t\t\tif ( event.which == null ) {\n\t\t\t\tevent.which = original.charCode != null ? original.charCode : original.keyCode;\n\t\t\t}\n\n\t\t\treturn event;\n\t\t}\n\t},\n\n\tmouseHooks: {\n\t\tprops: \"button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement\".split(\" \"),\n\t\tfilter: function( event, original ) {\n\t\t\tvar body, eventDoc, doc,\n\t\t\t\tbutton = original.button,\n\t\t\t\tfromElement = original.fromElement;\n\n\t\t\t// Calculate pageX/Y if missing and clientX/Y available\n\t\t\tif ( event.pageX == null && original.clientX != null ) {\n\t\t\t\teventDoc = event.target.ownerDocument || document;\n\t\t\t\tdoc = eventDoc.documentElement;\n\t\t\t\tbody = eventDoc.body;\n\n\t\t\t\tevent.pageX = original.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && body.clientLeft || 0 );\n\t\t\t\tevent.pageY = original.clientY + ( doc && doc.scrollTop  || body && body.scrollTop  || 0 ) - ( doc && doc.clientTop  || body && body.clientTop  || 0 );\n\t\t\t}\n\n\t\t\t// Add relatedTarget, if necessary\n\t\t\tif ( !event.relatedTarget && fromElement ) {\n\t\t\t\tevent.relatedTarget = fromElement === event.target ? original.toElement : fromElement;\n\t\t\t}\n\n\t\t\t// Add which for click: 1 === left; 2 === middle; 3 === right\n\t\t\t// Note: button is not normalized, so don't use it\n\t\t\tif ( !event.which && button !== undefined ) {\n\t\t\t\tevent.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) );\n\t\t\t}\n\n\t\t\treturn event;\n\t\t}\n\t},\n\n\tspecial: {\n\t\tload: {\n\t\t\t// Prevent triggered image.load events from bubbling to window.load\n\t\t\tnoBubble: true\n\t\t},\n\t\tclick: {\n\t\t\t// For checkbox, fire native event so checked state will be right\n\t\t\ttrigger: function() {\n\t\t\t\tif ( jQuery.nodeName( this, \"input\" ) && this.type === \"checkbox\" && this.click ) {\n\t\t\t\t\tthis.click();\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\tfocus: {\n\t\t\t// Fire native event if possible so blur/focus sequence is correct\n\t\t\ttrigger: function() {\n\t\t\t\tif ( this !== document.activeElement && this.focus ) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tthis.focus();\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t} catch ( e ) {\n\t\t\t\t\t\t// Support: IE<9\n\t\t\t\t\t\t// If we error on focus to hidden element (#1486, #12518),\n\t\t\t\t\t\t// let .trigger() run the handlers\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\tdelegateType: \"focusin\"\n\t\t},\n\t\tblur: {\n\t\t\ttrigger: function() {\n\t\t\t\tif ( this === document.activeElement && this.blur ) {\n\t\t\t\t\tthis.blur();\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t},\n\t\t\tdelegateType: \"focusout\"\n\t\t},\n\n\t\tbeforeunload: {\n\t\t\tpostDispatch: function( event ) {\n\n\t\t\t\t// Even when returnValue equals to undefined Firefox will still show alert\n\t\t\t\tif ( event.result !== undefined ) {\n\t\t\t\t\tevent.originalEvent.returnValue = event.result;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\n\tsimulate: function( type, elem, event, bubble ) {\n\t\t// Piggyback on a donor event to simulate a different one.\n\t\t// Fake originalEvent to avoid donor's stopPropagation, but if the\n\t\t// simulated event prevents default then we do the same on the donor.\n\t\tvar e = jQuery.extend(\n\t\t\tnew jQuery.Event(),\n\t\t\tevent,\n\t\t\t{ type: type,\n\t\t\t\tisSimulated: true,\n\t\t\t\toriginalEvent: {}\n\t\t\t}\n\t\t);\n\t\tif ( bubble ) {\n\t\t\tjQuery.event.trigger( e, null, elem );\n\t\t} else {\n\t\t\tjQuery.event.dispatch.call( elem, e );\n\t\t}\n\t\tif ( e.isDefaultPrevented() ) {\n\t\t\tevent.preventDefault();\n\t\t}\n\t}\n};\n\njQuery.removeEvent = document.removeEventListener ?\n\tfunction( elem, type, handle ) {\n\t\tif ( elem.removeEventListener ) {\n\t\t\telem.removeEventListener( type, handle, false );\n\t\t}\n\t} :\n\tfunction( elem, type, handle ) {\n\t\tvar name = \"on\" + type;\n\n\t\tif ( elem.detachEvent ) {\n\n\t\t\t// #8545, #7054, preventing memory leaks for custom events in IE6-8\n\t\t\t// detachEvent needed property on element, by name of that event, to properly expose it to GC\n\t\t\tif ( typeof elem[ name ] === core_strundefined ) {\n\t\t\t\telem[ name ] = null;\n\t\t\t}\n\n\t\t\telem.detachEvent( name, handle );\n\t\t}\n\t};\n\njQuery.Event = function( src, props ) {\n\t// Allow instantiation without the 'new' keyword\n\tif ( !(this instanceof jQuery.Event) ) {\n\t\treturn new jQuery.Event( src, props );\n\t}\n\n\t// Event object\n\tif ( src && src.type ) {\n\t\tthis.originalEvent = src;\n\t\tthis.type = src.type;\n\n\t\t// Events bubbling up the document may have been marked as prevented\n\t\t// by a handler lower down the tree; reflect the correct value.\n\t\tthis.isDefaultPrevented = ( src.defaultPrevented || src.returnValue === false ||\n\t\t\tsrc.getPreventDefault && src.getPreventDefault() ) ? returnTrue : returnFalse;\n\n\t// Event type\n\t} else {\n\t\tthis.type = src;\n\t}\n\n\t// Put explicitly provided properties onto the event object\n\tif ( props ) {\n\t\tjQuery.extend( this, props );\n\t}\n\n\t// Create a timestamp if incoming event doesn't have one\n\tthis.timeStamp = src && src.timeStamp || jQuery.now();\n\n\t// Mark it as fixed\n\tthis[ jQuery.expando ] = true;\n};\n\n// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding\n// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html\njQuery.Event.prototype = {\n\tisDefaultPrevented: returnFalse,\n\tisPropagationStopped: returnFalse,\n\tisImmediatePropagationStopped: returnFalse,\n\n\tpreventDefault: function() {\n\t\tvar e = this.originalEvent;\n\n\t\tthis.isDefaultPrevented = returnTrue;\n\t\tif ( !e ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// If preventDefault exists, run it on the original event\n\t\tif ( e.preventDefault ) {\n\t\t\te.preventDefault();\n\n\t\t// Support: IE\n\t\t// Otherwise set the returnValue property of the original event to false\n\t\t} else {\n\t\t\te.returnValue = false;\n\t\t}\n\t},\n\tstopPropagation: function() {\n\t\tvar e = this.originalEvent;\n\n\t\tthis.isPropagationStopped = returnTrue;\n\t\tif ( !e ) {\n\t\t\treturn;\n\t\t}\n\t\t// If stopPropagation exists, run it on the original event\n\t\tif ( e.stopPropagation ) {\n\t\t\te.stopPropagation();\n\t\t}\n\n\t\t// Support: IE\n\t\t// Set the cancelBubble property of the original event to true\n\t\te.cancelBubble = true;\n\t},\n\tstopImmediatePropagation: function() {\n\t\tthis.isImmediatePropagationStopped = returnTrue;\n\t\tthis.stopPropagation();\n\t}\n};\n\n// Create mouseenter/leave events using mouseover/out and event-time checks\njQuery.each({\n\tmouseenter: \"mouseover\",\n\tmouseleave: \"mouseout\"\n}, function( orig, fix ) {\n\tjQuery.event.special[ orig ] = {\n\t\tdelegateType: fix,\n\t\tbindType: fix,\n\n\t\thandle: function( event ) {\n\t\t\tvar ret,\n\t\t\t\ttarget = this,\n\t\t\t\trelated = event.relatedTarget,\n\t\t\t\thandleObj = event.handleObj;\n\n\t\t\t// For mousenter/leave call the handler if related is outside the target.\n\t\t\t// NB: No relatedTarget if the mouse left/entered the browser window\n\t\t\tif ( !related || (related !== target && !jQuery.contains( target, related )) ) {\n\t\t\t\tevent.type = handleObj.origType;\n\t\t\t\tret = handleObj.handler.apply( this, arguments );\n\t\t\t\tevent.type = fix;\n\t\t\t}\n\t\t\treturn ret;\n\t\t}\n\t};\n});\n\n// IE submit delegation\nif ( !jQuery.support.submitBubbles ) {\n\n\tjQuery.event.special.submit = {\n\t\tsetup: function() {\n\t\t\t// Only need this for delegated form submit events\n\t\t\tif ( jQuery.nodeName( this, \"form\" ) ) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\t// Lazy-add a submit handler when a descendant form may potentially be submitted\n\t\t\tjQuery.event.add( this, \"click._submit keypress._submit\", function( e ) {\n\t\t\t\t// Node name check avoids a VML-related crash in IE (#9807)\n\t\t\t\tvar elem = e.target,\n\t\t\t\t\tform = jQuery.nodeName( elem, \"input\" ) || jQuery.nodeName( elem, \"button\" ) ? elem.form : undefined;\n\t\t\t\tif ( form && !jQuery._data( form, \"submitBubbles\" ) ) {\n\t\t\t\t\tjQuery.event.add( form, \"submit._submit\", function( event ) {\n\t\t\t\t\t\tevent._submit_bubble = true;\n\t\t\t\t\t});\n\t\t\t\t\tjQuery._data( form, \"submitBubbles\", true );\n\t\t\t\t}\n\t\t\t});\n\t\t\t// return undefined since we don't need an event listener\n\t\t},\n\n\t\tpostDispatch: function( event ) {\n\t\t\t// If form was submitted by the user, bubble the event up the tree\n\t\t\tif ( event._submit_bubble ) {\n\t\t\t\tdelete event._submit_bubble;\n\t\t\t\tif ( this.parentNode && !event.isTrigger ) {\n\t\t\t\t\tjQuery.event.simulate( \"submit\", this.parentNode, event, true );\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\tteardown: function() {\n\t\t\t// Only need this for delegated form submit events\n\t\t\tif ( jQuery.nodeName( this, \"form\" ) ) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\t// Remove delegated handlers; cleanData eventually reaps submit handlers attached above\n\t\t\tjQuery.event.remove( this, \"._submit\" );\n\t\t}\n\t};\n}\n\n// IE change delegation and checkbox/radio fix\nif ( !jQuery.support.changeBubbles ) {\n\n\tjQuery.event.special.change = {\n\n\t\tsetup: function() {\n\n\t\t\tif ( rformElems.test( this.nodeName ) ) {\n\t\t\t\t// IE doesn't fire change on a check/radio until blur; trigger it on click\n\t\t\t\t// after a propertychange. Eat the blur-change in special.change.handle.\n\t\t\t\t// This still fires onchange a second time for check/radio after blur.\n\t\t\t\tif ( this.type === \"checkbox\" || this.type === \"radio\" ) {\n\t\t\t\t\tjQuery.event.add( this, \"propertychange._change\", function( event ) {\n\t\t\t\t\t\tif ( event.originalEvent.propertyName === \"checked\" ) {\n\t\t\t\t\t\t\tthis._just_changed = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t\tjQuery.event.add( this, \"click._change\", function( event ) {\n\t\t\t\t\t\tif ( this._just_changed && !event.isTrigger ) {\n\t\t\t\t\t\t\tthis._just_changed = false;\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// Allow triggered, simulated change events (#11500)\n\t\t\t\t\t\tjQuery.event.simulate( \"change\", this, event, true );\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\t// Delegated event; lazy-add a change handler on descendant inputs\n\t\t\tjQuery.event.add( this, \"beforeactivate._change\", function( e ) {\n\t\t\t\tvar elem = e.target;\n\n\t\t\t\tif ( rformElems.test( elem.nodeName ) && !jQuery._data( elem, \"changeBubbles\" ) ) {\n\t\t\t\t\tjQuery.event.add( elem, \"change._change\", function( event ) {\n\t\t\t\t\t\tif ( this.parentNode && !event.isSimulated && !event.isTrigger ) {\n\t\t\t\t\t\t\tjQuery.event.simulate( \"change\", this.parentNode, event, true );\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t\tjQuery._data( elem, \"changeBubbles\", true );\n\t\t\t\t}\n\t\t\t});\n\t\t},\n\n\t\thandle: function( event ) {\n\t\t\tvar elem = event.target;\n\n\t\t\t// Swallow native change events from checkbox/radio, we already triggered them above\n\t\t\tif ( this !== elem || event.isSimulated || event.isTrigger || (elem.type !== \"radio\" && elem.type !== \"checkbox\") ) {\n\t\t\t\treturn event.handleObj.handler.apply( this, arguments );\n\t\t\t}\n\t\t},\n\n\t\tteardown: function() {\n\t\t\tjQuery.event.remove( this, \"._change\" );\n\n\t\t\treturn !rformElems.test( this.nodeName );\n\t\t}\n\t};\n}\n\n// Create \"bubbling\" focus and blur events\nif ( !jQuery.support.focusinBubbles ) {\n\tjQuery.each({ focus: \"focusin\", blur: \"focusout\" }, function( orig, fix ) {\n\n\t\t// Attach a single capturing handler while someone wants focusin/focusout\n\t\tvar attaches = 0,\n\t\t\thandler = function( event ) {\n\t\t\t\tjQuery.event.simulate( fix, event.target, jQuery.event.fix( event ), true );\n\t\t\t};\n\n\t\tjQuery.event.special[ fix ] = {\n\t\t\tsetup: function() {\n\t\t\t\tif ( attaches++ === 0 ) {\n\t\t\t\t\tdocument.addEventListener( orig, handler, true );\n\t\t\t\t}\n\t\t\t},\n\t\t\tteardown: function() {\n\t\t\t\tif ( --attaches === 0 ) {\n\t\t\t\t\tdocument.removeEventListener( orig, handler, true );\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t});\n}\n\njQuery.fn.extend({\n\n\ton: function( types, selector, data, fn, /*INTERNAL*/ one ) {\n\t\tvar type, origFn;\n\n\t\t// Types can be a map of types/handlers\n\t\tif ( typeof types === \"object\" ) {\n\t\t\t// ( types-Object, selector, data )\n\t\t\tif ( typeof selector !== \"string\" ) {\n\t\t\t\t// ( types-Object, data )\n\t\t\t\tdata = data || selector;\n\t\t\t\tselector = undefined;\n\t\t\t}\n\t\t\tfor ( type in types ) {\n\t\t\t\tthis.on( type, selector, data, types[ type ], one );\n\t\t\t}\n\t\t\treturn this;\n\t\t}\n\n\t\tif ( data == null && fn == null ) {\n\t\t\t// ( types, fn )\n\t\t\tfn = selector;\n\t\t\tdata = selector = undefined;\n\t\t} else if ( fn == null ) {\n\t\t\tif ( typeof selector === \"string\" ) {\n\t\t\t\t// ( types, selector, fn )\n\t\t\t\tfn = data;\n\t\t\t\tdata = undefined;\n\t\t\t} else {\n\t\t\t\t// ( types, data, fn )\n\t\t\t\tfn = data;\n\t\t\t\tdata = selector;\n\t\t\t\tselector = undefined;\n\t\t\t}\n\t\t}\n\t\tif ( fn === false ) {\n\t\t\tfn = returnFalse;\n\t\t} else if ( !fn ) {\n\t\t\treturn this;\n\t\t}\n\n\t\tif ( one === 1 ) {\n\t\t\torigFn = fn;\n\t\t\tfn = function( event ) {\n\t\t\t\t// Can use an empty set, since event contains the info\n\t\t\t\tjQuery().off( event );\n\t\t\t\treturn origFn.apply( this, arguments );\n\t\t\t};\n\t\t\t// Use same guid so caller can remove using origFn\n\t\t\tfn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ );\n\t\t}\n\t\treturn this.each( function() {\n\t\t\tjQuery.event.add( this, types, fn, data, selector );\n\t\t});\n\t},\n\tone: function( types, selector, data, fn ) {\n\t\treturn this.on( types, selector, data, fn, 1 );\n\t},\n\toff: function( types, selector, fn ) {\n\t\tvar handleObj, type;\n\t\tif ( types && types.preventDefault && types.handleObj ) {\n\t\t\t// ( event )  dispatched jQuery.Event\n\t\t\thandleObj = types.handleObj;\n\t\t\tjQuery( types.delegateTarget ).off(\n\t\t\t\thandleObj.namespace ? handleObj.origType + \".\" + handleObj.namespace : handleObj.origType,\n\t\t\t\thandleObj.selector,\n\t\t\t\thandleObj.handler\n\t\t\t);\n\t\t\treturn this;\n\t\t}\n\t\tif ( typeof types === \"object\" ) {\n\t\t\t// ( types-object [, selector] )\n\t\t\tfor ( type in types ) {\n\t\t\t\tthis.off( type, selector, types[ type ] );\n\t\t\t}\n\t\t\treturn this;\n\t\t}\n\t\tif ( selector === false || typeof selector === \"function\" ) {\n\t\t\t// ( types [, fn] )\n\t\t\tfn = selector;\n\t\t\tselector = undefined;\n\t\t}\n\t\tif ( fn === false ) {\n\t\t\tfn = returnFalse;\n\t\t}\n\t\treturn this.each(function() {\n\t\t\tjQuery.event.remove( this, types, fn, selector );\n\t\t});\n\t},\n\n\tbind: function( types, data, fn ) {\n\t\treturn this.on( types, null, data, fn );\n\t},\n\tunbind: function( types, fn ) {\n\t\treturn this.off( types, null, fn );\n\t},\n\n\tdelegate: function( selector, types, data, fn ) {\n\t\treturn this.on( types, selector, data, fn );\n\t},\n\tundelegate: function( selector, types, fn ) {\n\t\t// ( namespace ) or ( selector, types [, fn] )\n\t\treturn arguments.length === 1 ? this.off( selector, \"**\" ) : this.off( types, selector || \"**\", fn );\n\t},\n\n\ttrigger: function( type, data ) {\n\t\treturn this.each(function() {\n\t\t\tjQuery.event.trigger( type, data, this );\n\t\t});\n\t},\n\ttriggerHandler: function( type, data ) {\n\t\tvar elem = this[0];\n\t\tif ( elem ) {\n\t\t\treturn jQuery.event.trigger( type, data, elem, true );\n\t\t}\n\t}\n});\n/*!\n * Sizzle CSS Selector Engine\n * Copyright 2012 jQuery Foundation and other contributors\n * Released under the MIT license\n * http://sizzlejs.com/\n */\n(function( window, undefined ) {\n\nvar i,\n\tcachedruns,\n\tExpr,\n\tgetText,\n\tisXML,\n\tcompile,\n\thasDuplicate,\n\toutermostContext,\n\n\t// Local document vars\n\tsetDocument,\n\tdocument,\n\tdocElem,\n\tdocumentIsXML,\n\trbuggyQSA,\n\trbuggyMatches,\n\tmatches,\n\tcontains,\n\tsortOrder,\n\n\t// Instance-specific data\n\texpando = \"sizzle\" + -(new Date()),\n\tpreferredDoc = window.document,\n\tsupport = {},\n\tdirruns = 0,\n\tdone = 0,\n\tclassCache = createCache(),\n\ttokenCache = createCache(),\n\tcompilerCache = createCache(),\n\n\t// General-purpose constants\n\tstrundefined = typeof undefined,\n\tMAX_NEGATIVE = 1 << 31,\n\n\t// Array methods\n\tarr = [],\n\tpop = arr.pop,\n\tpush = arr.push,\n\tslice = arr.slice,\n\t// Use a stripped-down indexOf if we can't use a native one\n\tindexOf = arr.indexOf || function( elem ) {\n\t\tvar i = 0,\n\t\t\tlen = this.length;\n\t\tfor ( ; i < len; i++ ) {\n\t\t\tif ( this[i] === elem ) {\n\t\t\t\treturn i;\n\t\t\t}\n\t\t}\n\t\treturn -1;\n\t},\n\n\n\t// Regular expressions\n\n\t// Whitespace characters http://www.w3.org/TR/css3-selectors/#whitespace\n\twhitespace = \"[\\\\x20\\\\t\\\\r\\\\n\\\\f]\",\n\t// http://www.w3.org/TR/css3-syntax/#characters\n\tcharacterEncoding = \"(?:\\\\\\\\.|[\\\\w-]|[^\\\\x00-\\\\xa0])+\",\n\n\t// Loosely modeled on CSS identifier characters\n\t// An unquoted value should be a CSS identifier http://www.w3.org/TR/css3-selectors/#attribute-selectors\n\t// Proper syntax: http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier\n\tidentifier = characterEncoding.replace( \"w\", \"w#\" ),\n\n\t// Acceptable operators http://www.w3.org/TR/selectors/#attribute-selectors\n\toperators = \"([*^$|!~]?=)\",\n\tattributes = \"\\\\[\" + whitespace + \"*(\" + characterEncoding + \")\" + whitespace +\n\t\t\"*(?:\" + operators + whitespace + \"*(?:(['\\\"])((?:\\\\\\\\.|[^\\\\\\\\])*?)\\\\3|(\" + identifier + \")|)|)\" + whitespace + \"*\\\\]\",\n\n\t// Prefer arguments quoted,\n\t//   then not containing pseudos/brackets,\n\t//   then attribute selectors/non-parenthetical expressions,\n\t//   then anything else\n\t// These preferences are here to reduce the number of selectors\n\t//   needing tokenize in the PSEUDO preFilter\n\tpseudos = \":(\" + characterEncoding + \")(?:\\\\(((['\\\"])((?:\\\\\\\\.|[^\\\\\\\\])*?)\\\\3|((?:\\\\\\\\.|[^\\\\\\\\()[\\\\]]|\" + attributes.replace( 3, 8 ) + \")*)|.*)\\\\)|)\",\n\n\t// Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter\n\trtrim = new RegExp( \"^\" + whitespace + \"+|((?:^|[^\\\\\\\\])(?:\\\\\\\\.)*)\" + whitespace + \"+$\", \"g\" ),\n\n\trcomma = new RegExp( \"^\" + whitespace + \"*,\" + whitespace + \"*\" ),\n\trcombinators = new RegExp( \"^\" + whitespace + \"*([\\\\x20\\\\t\\\\r\\\\n\\\\f>+~])\" + whitespace + \"*\" ),\n\trpseudo = new RegExp( pseudos ),\n\tridentifier = new RegExp( \"^\" + identifier + \"$\" ),\n\n\tmatchExpr = {\n\t\t\"ID\": new RegExp( \"^#(\" + characterEncoding + \")\" ),\n\t\t\"CLASS\": new RegExp( \"^\\\\.(\" + characterEncoding + \")\" ),\n\t\t\"NAME\": new RegExp( \"^\\\\[name=['\\\"]?(\" + characterEncoding + \")['\\\"]?\\\\]\" ),\n\t\t\"TAG\": new RegExp( \"^(\" + characterEncoding.replace( \"w\", \"w*\" ) + \")\" ),\n\t\t\"ATTR\": new RegExp( \"^\" + attributes ),\n\t\t\"PSEUDO\": new RegExp( \"^\" + pseudos ),\n\t\t\"CHILD\": new RegExp( \"^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\\\(\" + whitespace +\n\t\t\t\"*(even|odd|(([+-]|)(\\\\d*)n|)\" + whitespace + \"*(?:([+-]|)\" + whitespace +\n\t\t\t\"*(\\\\d+)|))\" + whitespace + \"*\\\\)|)\", \"i\" ),\n\t\t// For use in libraries implementing .is()\n\t\t// We use this for POS matching in `select`\n\t\t\"needsContext\": new RegExp( \"^\" + whitespace + \"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\\\(\" +\n\t\t\twhitespace + \"*((?:-\\\\d)?\\\\d*)\" + whitespace + \"*\\\\)|)(?=[^-]|$)\", \"i\" )\n\t},\n\n\trsibling = /[\\x20\\t\\r\\n\\f]*[+~]/,\n\n\trnative = /^[^{]+\\{\\s*\\[native code/,\n\n\t// Easily-parseable/retrievable ID or TAG or CLASS selectors\n\trquickExpr = /^(?:#([\\w-]+)|(\\w+)|\\.([\\w-]+))$/,\n\n\trinputs = /^(?:input|select|textarea|button)$/i,\n\trheader = /^h\\d$/i,\n\n\trescape = /'|\\\\/g,\n\trattributeQuotes = /\\=[\\x20\\t\\r\\n\\f]*([^'\"\\]]*)[\\x20\\t\\r\\n\\f]*\\]/g,\n\n\t// CSS escapes http://www.w3.org/TR/CSS21/syndata.html#escaped-characters\n\trunescape = /\\\\([\\da-fA-F]{1,6}[\\x20\\t\\r\\n\\f]?|.)/g,\n\tfunescape = function( _, escaped ) {\n\t\tvar high = \"0x\" + escaped - 0x10000;\n\t\t// NaN means non-codepoint\n\t\treturn high !== high ?\n\t\t\tescaped :\n\t\t\t// BMP codepoint\n\t\t\thigh < 0 ?\n\t\t\t\tString.fromCharCode( high + 0x10000 ) :\n\t\t\t\t// Supplemental Plane codepoint (surrogate pair)\n\t\t\t\tString.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 );\n\t};\n\n// Use a stripped-down slice if we can't use a native one\ntry {\n\tslice.call( preferredDoc.documentElement.childNodes, 0 )[0].nodeType;\n} catch ( e ) {\n\tslice = function( i ) {\n\t\tvar elem,\n\t\t\tresults = [];\n\t\twhile ( (elem = this[i++]) ) {\n\t\t\tresults.push( elem );\n\t\t}\n\t\treturn results;\n\t};\n}\n\n/**\n * For feature detection\n * @param {Function} fn The function to test for native support\n */\nfunction isNative( fn ) {\n\treturn rnative.test( fn + \"\" );\n}\n\n/**\n * Create key-value caches of limited size\n * @returns {Function(string, Object)} Returns the Object data after storing it on itself with\n *\tproperty name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength)\n *\tdeleting the oldest entry\n */\nfunction createCache() {\n\tvar cache,\n\t\tkeys = [];\n\n\treturn (cache = function( key, value ) {\n\t\t// Use (key + \" \") to avoid collision with native prototype properties (see Issue #157)\n\t\tif ( keys.push( key += \" \" ) > Expr.cacheLength ) {\n\t\t\t// Only keep the most recent entries\n\t\t\tdelete cache[ keys.shift() ];\n\t\t}\n\t\treturn (cache[ key ] = value);\n\t});\n}\n\n/**\n * Mark a function for special use by Sizzle\n * @param {Function} fn The function to mark\n */\nfunction markFunction( fn ) {\n\tfn[ expando ] = true;\n\treturn fn;\n}\n\n/**\n * Support testing using an element\n * @param {Function} fn Passed the created div and expects a boolean result\n */\nfunction assert( fn ) {\n\tvar div = document.createElement(\"div\");\n\n\ttry {\n\t\treturn fn( div );\n\t} catch (e) {\n\t\treturn false;\n\t} finally {\n\t\t// release memory in IE\n\t\tdiv = null;\n\t}\n}\n\nfunction Sizzle( selector, context, results, seed ) {\n\tvar match, elem, m, nodeType,\n\t\t// QSA vars\n\t\ti, groups, old, nid, newContext, newSelector;\n\n\tif ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) {\n\t\tsetDocument( context );\n\t}\n\n\tcontext = context || document;\n\tresults = results || [];\n\n\tif ( !selector || typeof selector !== \"string\" ) {\n\t\treturn results;\n\t}\n\n\tif ( (nodeType = context.nodeType) !== 1 && nodeType !== 9 ) {\n\t\treturn [];\n\t}\n\n\tif ( !documentIsXML && !seed ) {\n\n\t\t// Shortcuts\n\t\tif ( (match = rquickExpr.exec( selector )) ) {\n\t\t\t// Speed-up: Sizzle(\"#ID\")\n\t\t\tif ( (m = match[1]) ) {\n\t\t\t\tif ( nodeType === 9 ) {\n\t\t\t\t\telem = context.getElementById( m );\n\t\t\t\t\t// Check parentNode to catch when Blackberry 4.6 returns\n\t\t\t\t\t// nodes that are no longer in the document #6963\n\t\t\t\t\tif ( elem && elem.parentNode ) {\n\t\t\t\t\t\t// Handle the case where IE, Opera, and Webkit return items\n\t\t\t\t\t\t// by name instead of ID\n\t\t\t\t\t\tif ( elem.id === m ) {\n\t\t\t\t\t\t\tresults.push( elem );\n\t\t\t\t\t\t\treturn results;\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\treturn results;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\t// Context is not a document\n\t\t\t\t\tif ( context.ownerDocument && (elem = context.ownerDocument.getElementById( m )) &&\n\t\t\t\t\t\tcontains( context, elem ) && elem.id === m ) {\n\t\t\t\t\t\tresults.push( elem );\n\t\t\t\t\t\treturn results;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t// Speed-up: Sizzle(\"TAG\")\n\t\t\t} else if ( match[2] ) {\n\t\t\t\tpush.apply( results, slice.call(context.getElementsByTagName( selector ), 0) );\n\t\t\t\treturn results;\n\n\t\t\t// Speed-up: Sizzle(\".CLASS\")\n\t\t\t} else if ( (m = match[3]) && support.getByClassName && context.getElementsByClassName ) {\n\t\t\t\tpush.apply( results, slice.call(context.getElementsByClassName( m ), 0) );\n\t\t\t\treturn results;\n\t\t\t}\n\t\t}\n\n\t\t// QSA path\n\t\tif ( support.qsa && !rbuggyQSA.test(selector) ) {\n\t\t\told = true;\n\t\t\tnid = expando;\n\t\t\tnewContext = context;\n\t\t\tnewSelector = nodeType === 9 && selector;\n\n\t\t\t// qSA works strangely on Element-rooted queries\n\t\t\t// We can work around this by specifying an extra ID on the root\n\t\t\t// and working up from there (Thanks to Andrew Dupont for the technique)\n\t\t\t// IE 8 doesn't work on object elements\n\t\t\tif ( nodeType === 1 && context.nodeName.toLowerCase() !== \"object\" ) {\n\t\t\t\tgroups = tokenize( selector );\n\n\t\t\t\tif ( (old = context.getAttribute(\"id\")) ) {\n\t\t\t\t\tnid = old.replace( rescape, \"\\\\$&\" );\n\t\t\t\t} else {\n\t\t\t\t\tcontext.setAttribute( \"id\", nid );\n\t\t\t\t}\n\t\t\t\tnid = \"[id='\" + nid + \"'] \";\n\n\t\t\t\ti = groups.length;\n\t\t\t\twhile ( i-- ) {\n\t\t\t\t\tgroups[i] = nid + toSelector( groups[i] );\n\t\t\t\t}\n\t\t\t\tnewContext = rsibling.test( selector ) && context.parentNode || context;\n\t\t\t\tnewSelector = groups.join(\",\");\n\t\t\t}\n\n\t\t\tif ( newSelector ) {\n\t\t\t\ttry {\n\t\t\t\t\tpush.apply( results, slice.call( newContext.querySelectorAll(\n\t\t\t\t\t\tnewSelector\n\t\t\t\t\t), 0 ) );\n\t\t\t\t\treturn results;\n\t\t\t\t} catch(qsaError) {\n\t\t\t\t} finally {\n\t\t\t\t\tif ( !old ) {\n\t\t\t\t\t\tcontext.removeAttribute(\"id\");\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// All others\n\treturn select( selector.replace( rtrim, \"$1\" ), context, results, seed );\n}\n\n/**\n * Detect xml\n * @param {Element|Object} elem An element or a document\n */\nisXML = Sizzle.isXML = function( elem ) {\n\t// documentElement is verified for cases where it doesn't yet exist\n\t// (such as loading iframes in IE - #4833)\n\tvar documentElement = elem && (elem.ownerDocument || elem).documentElement;\n\treturn documentElement ? documentElement.nodeName !== \"HTML\" : false;\n};\n\n/**\n * Sets document-related variables once based on the current document\n * @param {Element|Object} [doc] An element or document object to use to set the document\n * @returns {Object} Returns the current document\n */\nsetDocument = Sizzle.setDocument = function( node ) {\n\tvar doc = node ? node.ownerDocument || node : preferredDoc;\n\n\t// If no document and documentElement is available, return\n\tif ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) {\n\t\treturn document;\n\t}\n\n\t// Set our document\n\tdocument = doc;\n\tdocElem = doc.documentElement;\n\n\t// Support tests\n\tdocumentIsXML = isXML( doc );\n\n\t// Check if getElementsByTagName(\"*\") returns only elements\n\tsupport.tagNameNoComments = assert(function( div ) {\n\t\tdiv.appendChild( doc.createComment(\"\") );\n\t\treturn !div.getElementsByTagName(\"*\").length;\n\t});\n\n\t// Check if attributes should be retrieved by attribute nodes\n\tsupport.attributes = assert(function( div ) {\n\t\tdiv.innerHTML = \"<select></select>\";\n\t\tvar type = typeof div.lastChild.getAttribute(\"multiple\");\n\t\t// IE8 returns a string for some attributes even when not present\n\t\treturn type !== \"boolean\" && type !== \"string\";\n\t});\n\n\t// Check if getElementsByClassName can be trusted\n\tsupport.getByClassName = assert(function( div ) {\n\t\t// Opera can't find a second classname (in 9.6)\n\t\tdiv.innerHTML = \"<div class='hidden e'></div><div class='hidden'></div>\";\n\t\tif ( !div.getElementsByClassName || !div.getElementsByClassName(\"e\").length ) {\n\t\t\treturn false;\n\t\t}\n\n\t\t// Safari 3.2 caches class attributes and doesn't catch changes\n\t\tdiv.lastChild.className = \"e\";\n\t\treturn div.getElementsByClassName(\"e\").length === 2;\n\t});\n\n\t// Check if getElementById returns elements by name\n\t// Check if getElementsByName privileges form controls or returns elements by ID\n\tsupport.getByName = assert(function( div ) {\n\t\t// Inject content\n\t\tdiv.id = expando + 0;\n\t\tdiv.innerHTML = \"<a name='\" + expando + \"'></a><div name='\" + expando + \"'></div>\";\n\t\tdocElem.insertBefore( div, docElem.firstChild );\n\n\t\t// Test\n\t\tvar pass = doc.getElementsByName &&\n\t\t\t// buggy browsers will return fewer than the correct 2\n\t\t\tdoc.getElementsByName( expando ).length === 2 +\n\t\t\t// buggy browsers will return more than the correct 0\n\t\t\tdoc.getElementsByName( expando + 0 ).length;\n\t\tsupport.getIdNotName = !doc.getElementById( expando );\n\n\t\t// Cleanup\n\t\tdocElem.removeChild( div );\n\n\t\treturn pass;\n\t});\n\n\t// IE6/7 return modified attributes\n\tExpr.attrHandle = assert(function( div ) {\n\t\tdiv.innerHTML = \"<a href='#'></a>\";\n\t\treturn div.firstChild && typeof div.firstChild.getAttribute !== strundefined &&\n\t\t\tdiv.firstChild.getAttribute(\"href\") === \"#\";\n\t}) ?\n\t\t{} :\n\t\t{\n\t\t\t\"href\": function( elem ) {\n\t\t\t\treturn elem.getAttribute( \"href\", 2 );\n\t\t\t},\n\t\t\t\"type\": function( elem ) {\n\t\t\t\treturn elem.getAttribute(\"type\");\n\t\t\t}\n\t\t};\n\n\t// ID find and filter\n\tif ( support.getIdNotName ) {\n\t\tExpr.find[\"ID\"] = function( id, context ) {\n\t\t\tif ( typeof context.getElementById !== strundefined && !documentIsXML ) {\n\t\t\t\tvar m = context.getElementById( id );\n\t\t\t\t// Check parentNode to catch when Blackberry 4.6 returns\n\t\t\t\t// nodes that are no longer in the document #6963\n\t\t\t\treturn m && m.parentNode ? [m] : [];\n\t\t\t}\n\t\t};\n\t\tExpr.filter[\"ID\"] = function( id ) {\n\t\t\tvar attrId = id.replace( runescape, funescape );\n\t\t\treturn function( elem ) {\n\t\t\t\treturn elem.getAttribute(\"id\") === attrId;\n\t\t\t};\n\t\t};\n\t} else {\n\t\tExpr.find[\"ID\"] = function( id, context ) {\n\t\t\tif ( typeof context.getElementById !== strundefined && !documentIsXML ) {\n\t\t\t\tvar m = context.getElementById( id );\n\n\t\t\t\treturn m ?\n\t\t\t\t\tm.id === id || typeof m.getAttributeNode !== strundefined && m.getAttributeNode(\"id\").value === id ?\n\t\t\t\t\t\t[m] :\n\t\t\t\t\t\tundefined :\n\t\t\t\t\t[];\n\t\t\t}\n\t\t};\n\t\tExpr.filter[\"ID\"] =  function( id ) {\n\t\t\tvar attrId = id.replace( runescape, funescape );\n\t\t\treturn function( elem ) {\n\t\t\t\tvar node = typeof elem.getAttributeNode !== strundefined && elem.getAttributeNode(\"id\");\n\t\t\t\treturn node && node.value === attrId;\n\t\t\t};\n\t\t};\n\t}\n\n\t// Tag\n\tExpr.find[\"TAG\"] = support.tagNameNoComments ?\n\t\tfunction( tag, context ) {\n\t\t\tif ( typeof context.getElementsByTagName !== strundefined ) {\n\t\t\t\treturn context.getElementsByTagName( tag );\n\t\t\t}\n\t\t} :\n\t\tfunction( tag, context ) {\n\t\t\tvar elem,\n\t\t\t\ttmp = [],\n\t\t\t\ti = 0,\n\t\t\t\tresults = context.getElementsByTagName( tag );\n\n\t\t\t// Filter out possible comments\n\t\t\tif ( tag === \"*\" ) {\n\t\t\t\twhile ( (elem = results[i++]) ) {\n\t\t\t\t\tif ( elem.nodeType === 1 ) {\n\t\t\t\t\t\ttmp.push( elem );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn tmp;\n\t\t\t}\n\t\t\treturn results;\n\t\t};\n\n\t// Name\n\tExpr.find[\"NAME\"] = support.getByName && function( tag, context ) {\n\t\tif ( typeof context.getElementsByName !== strundefined ) {\n\t\t\treturn context.getElementsByName( name );\n\t\t}\n\t};\n\n\t// Class\n\tExpr.find[\"CLASS\"] = support.getByClassName && function( className, context ) {\n\t\tif ( typeof context.getElementsByClassName !== strundefined && !documentIsXML ) {\n\t\t\treturn context.getElementsByClassName( className );\n\t\t}\n\t};\n\n\t// QSA and matchesSelector support\n\n\t// matchesSelector(:active) reports false when true (IE9/Opera 11.5)\n\trbuggyMatches = [];\n\n\t// qSa(:focus) reports false when true (Chrome 21),\n\t// no need to also add to buggyMatches since matches checks buggyQSA\n\t// A support test would require too much code (would include document ready)\n\trbuggyQSA = [ \":focus\" ];\n\n\tif ( (support.qsa = isNative(doc.querySelectorAll)) ) {\n\t\t// Build QSA regex\n\t\t// Regex strategy adopted from Diego Perini\n\t\tassert(function( div ) {\n\t\t\t// Select is set to empty string on purpose\n\t\t\t// This is to test IE's treatment of not explictly\n\t\t\t// setting a boolean content attribute,\n\t\t\t// since its presence should be enough\n\t\t\t// http://bugs.jquery.com/ticket/12359\n\t\t\tdiv.innerHTML = \"<select><option selected=''></option></select>\";\n\n\t\t\t// IE8 - Some boolean attributes are not treated correctly\n\t\t\tif ( !div.querySelectorAll(\"[selected]\").length ) {\n\t\t\t\trbuggyQSA.push( \"\\\\[\" + whitespace + \"*(?:checked|disabled|ismap|multiple|readonly|selected|value)\" );\n\t\t\t}\n\n\t\t\t// Webkit/Opera - :checked should return selected option elements\n\t\t\t// http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked\n\t\t\t// IE8 throws error here and will not see later tests\n\t\t\tif ( !div.querySelectorAll(\":checked\").length ) {\n\t\t\t\trbuggyQSA.push(\":checked\");\n\t\t\t}\n\t\t});\n\n\t\tassert(function( div ) {\n\n\t\t\t// Opera 10-12/IE8 - ^= $= *= and empty values\n\t\t\t// Should not select anything\n\t\t\tdiv.innerHTML = \"<input type='hidden' i=''/>\";\n\t\t\tif ( div.querySelectorAll(\"[i^='']\").length ) {\n\t\t\t\trbuggyQSA.push( \"[*^$]=\" + whitespace + \"*(?:\\\"\\\"|'')\" );\n\t\t\t}\n\n\t\t\t// FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled)\n\t\t\t// IE8 throws error here and will not see later tests\n\t\t\tif ( !div.querySelectorAll(\":enabled\").length ) {\n\t\t\t\trbuggyQSA.push( \":enabled\", \":disabled\" );\n\t\t\t}\n\n\t\t\t// Opera 10-11 does not throw on post-comma invalid pseudos\n\t\t\tdiv.querySelectorAll(\"*,:x\");\n\t\t\trbuggyQSA.push(\",.*:\");\n\t\t});\n\t}\n\n\tif ( (support.matchesSelector = isNative( (matches = docElem.matchesSelector ||\n\t\tdocElem.mozMatchesSelector ||\n\t\tdocElem.webkitMatchesSelector ||\n\t\tdocElem.oMatchesSelector ||\n\t\tdocElem.msMatchesSelector) )) ) {\n\n\t\tassert(function( div ) {\n\t\t\t// Check to see if it's possible to do matchesSelector\n\t\t\t// on a disconnected node (IE 9)\n\t\t\tsupport.disconnectedMatch = matches.call( div, \"div\" );\n\n\t\t\t// This should fail with an exception\n\t\t\t// Gecko does not error, returns false instead\n\t\t\tmatches.call( div, \"[s!='']:x\" );\n\t\t\trbuggyMatches.push( \"!=\", pseudos );\n\t\t});\n\t}\n\n\trbuggyQSA = new RegExp( rbuggyQSA.join(\"|\") );\n\trbuggyMatches = new RegExp( rbuggyMatches.join(\"|\") );\n\n\t// Element contains another\n\t// Purposefully does not implement inclusive descendent\n\t// As in, an element does not contain itself\n\tcontains = isNative(docElem.contains) || docElem.compareDocumentPosition ?\n\t\tfunction( a, b ) {\n\t\t\tvar adown = a.nodeType === 9 ? a.documentElement : a,\n\t\t\t\tbup = b && b.parentNode;\n\t\t\treturn a === bup || !!( bup && bup.nodeType === 1 && (\n\t\t\t\tadown.contains ?\n\t\t\t\t\tadown.contains( bup ) :\n\t\t\t\t\ta.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16\n\t\t\t));\n\t\t} :\n\t\tfunction( a, b ) {\n\t\t\tif ( b ) {\n\t\t\t\twhile ( (b = b.parentNode) ) {\n\t\t\t\t\tif ( b === a ) {\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn false;\n\t\t};\n\n\t// Document order sorting\n\tsortOrder = docElem.compareDocumentPosition ?\n\tfunction( a, b ) {\n\t\tvar compare;\n\n\t\tif ( a === b ) {\n\t\t\thasDuplicate = true;\n\t\t\treturn 0;\n\t\t}\n\n\t\tif ( (compare = b.compareDocumentPosition && a.compareDocumentPosition && a.compareDocumentPosition( b )) ) {\n\t\t\tif ( compare & 1 || a.parentNode && a.parentNode.nodeType === 11 ) {\n\t\t\t\tif ( a === doc || contains( preferredDoc, a ) ) {\n\t\t\t\t\treturn -1;\n\t\t\t\t}\n\t\t\t\tif ( b === doc || contains( preferredDoc, b ) ) {\n\t\t\t\t\treturn 1;\n\t\t\t\t}\n\t\t\t\treturn 0;\n\t\t\t}\n\t\t\treturn compare & 4 ? -1 : 1;\n\t\t}\n\n\t\treturn a.compareDocumentPosition ? -1 : 1;\n\t} :\n\tfunction( a, b ) {\n\t\tvar cur,\n\t\t\ti = 0,\n\t\t\taup = a.parentNode,\n\t\t\tbup = b.parentNode,\n\t\t\tap = [ a ],\n\t\t\tbp = [ b ];\n\n\t\t// Exit early if the nodes are identical\n\t\tif ( a === b ) {\n\t\t\thasDuplicate = true;\n\t\t\treturn 0;\n\n\t\t// Parentless nodes are either documents or disconnected\n\t\t} else if ( !aup || !bup ) {\n\t\t\treturn a === doc ? -1 :\n\t\t\t\tb === doc ? 1 :\n\t\t\t\taup ? -1 :\n\t\t\t\tbup ? 1 :\n\t\t\t\t0;\n\n\t\t// If the nodes are siblings, we can do a quick check\n\t\t} else if ( aup === bup ) {\n\t\t\treturn siblingCheck( a, b );\n\t\t}\n\n\t\t// Otherwise we need full lists of their ancestors for comparison\n\t\tcur = a;\n\t\twhile ( (cur = cur.parentNode) ) {\n\t\t\tap.unshift( cur );\n\t\t}\n\t\tcur = b;\n\t\twhile ( (cur = cur.parentNode) ) {\n\t\t\tbp.unshift( cur );\n\t\t}\n\n\t\t// Walk down the tree looking for a discrepancy\n\t\twhile ( ap[i] === bp[i] ) {\n\t\t\ti++;\n\t\t}\n\n\t\treturn i ?\n\t\t\t// Do a sibling check if the nodes have a common ancestor\n\t\t\tsiblingCheck( ap[i], bp[i] ) :\n\n\t\t\t// Otherwise nodes in our document sort first\n\t\t\tap[i] === preferredDoc ? -1 :\n\t\t\tbp[i] === preferredDoc ? 1 :\n\t\t\t0;\n\t};\n\n\t// Always assume the presence of duplicates if sort doesn't\n\t// pass them to our comparison function (as in Google Chrome).\n\thasDuplicate = false;\n\t[0, 0].sort( sortOrder );\n\tsupport.detectDuplicates = hasDuplicate;\n\n\treturn document;\n};\n\nSizzle.matches = function( expr, elements ) {\n\treturn Sizzle( expr, null, null, elements );\n};\n\nSizzle.matchesSelector = function( elem, expr ) {\n\t// Set document vars if needed\n\tif ( ( elem.ownerDocument || elem ) !== document ) {\n\t\tsetDocument( elem );\n\t}\n\n\t// Make sure that attribute selectors are quoted\n\texpr = expr.replace( rattributeQuotes, \"='$1']\" );\n\n\t// rbuggyQSA always contains :focus, so no need for an existence check\n\tif ( support.matchesSelector && !documentIsXML && (!rbuggyMatches || !rbuggyMatches.test(expr)) && !rbuggyQSA.test(expr) ) {\n\t\ttry {\n\t\t\tvar ret = matches.call( elem, expr );\n\n\t\t\t// IE 9's matchesSelector returns false on disconnected nodes\n\t\t\tif ( ret || support.disconnectedMatch ||\n\t\t\t\t\t// As well, disconnected nodes are said to be in a document\n\t\t\t\t\t// fragment in IE 9\n\t\t\t\t\telem.document && elem.document.nodeType !== 11 ) {\n\t\t\t\treturn ret;\n\t\t\t}\n\t\t} catch(e) {}\n\t}\n\n\treturn Sizzle( expr, document, null, [elem] ).length > 0;\n};\n\nSizzle.contains = function( context, elem ) {\n\t// Set document vars if needed\n\tif ( ( context.ownerDocument || context ) !== document ) {\n\t\tsetDocument( context );\n\t}\n\treturn contains( context, elem );\n};\n\nSizzle.attr = function( elem, name ) {\n\tvar val;\n\n\t// Set document vars if needed\n\tif ( ( elem.ownerDocument || elem ) !== document ) {\n\t\tsetDocument( elem );\n\t}\n\n\tif ( !documentIsXML ) {\n\t\tname = name.toLowerCase();\n\t}\n\tif ( (val = Expr.attrHandle[ name ]) ) {\n\t\treturn val( elem );\n\t}\n\tif ( documentIsXML || support.attributes ) {\n\t\treturn elem.getAttribute( name );\n\t}\n\treturn ( (val = elem.getAttributeNode( name )) || elem.getAttribute( name ) ) && elem[ name ] === true ?\n\t\tname :\n\t\tval && val.specified ? val.value : null;\n};\n\nSizzle.error = function( msg ) {\n\tthrow new Error( \"Syntax error, unrecognized expression: \" + msg );\n};\n\n// Document sorting and removing duplicates\nSizzle.uniqueSort = function( results ) {\n\tvar elem,\n\t\tduplicates = [],\n\t\ti = 1,\n\t\tj = 0;\n\n\t// Unless we *know* we can detect duplicates, assume their presence\n\thasDuplicate = !support.detectDuplicates;\n\tresults.sort( sortOrder );\n\n\tif ( hasDuplicate ) {\n\t\tfor ( ; (elem = results[i]); i++ ) {\n\t\t\tif ( elem === results[ i - 1 ] ) {\n\t\t\t\tj = duplicates.push( i );\n\t\t\t}\n\t\t}\n\t\twhile ( j-- ) {\n\t\t\tresults.splice( duplicates[ j ], 1 );\n\t\t}\n\t}\n\n\treturn results;\n};\n\nfunction siblingCheck( a, b ) {\n\tvar cur = b && a,\n\t\tdiff = cur && ( ~b.sourceIndex || MAX_NEGATIVE ) - ( ~a.sourceIndex || MAX_NEGATIVE );\n\n\t// Use IE sourceIndex if available on both nodes\n\tif ( diff ) {\n\t\treturn diff;\n\t}\n\n\t// Check if b follows a\n\tif ( cur ) {\n\t\twhile ( (cur = cur.nextSibling) ) {\n\t\t\tif ( cur === b ) {\n\t\t\t\treturn -1;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn a ? 1 : -1;\n}\n\n// Returns a function to use in pseudos for input types\nfunction createInputPseudo( type ) {\n\treturn function( elem ) {\n\t\tvar name = elem.nodeName.toLowerCase();\n\t\treturn name === \"input\" && elem.type === type;\n\t};\n}\n\n// Returns a function to use in pseudos for buttons\nfunction createButtonPseudo( type ) {\n\treturn function( elem ) {\n\t\tvar name = elem.nodeName.toLowerCase();\n\t\treturn (name === \"input\" || name === \"button\") && elem.type === type;\n\t};\n}\n\n// Returns a function to use in pseudos for positionals\nfunction createPositionalPseudo( fn ) {\n\treturn markFunction(function( argument ) {\n\t\targument = +argument;\n\t\treturn markFunction(function( seed, matches ) {\n\t\t\tvar j,\n\t\t\t\tmatchIndexes = fn( [], seed.length, argument ),\n\t\t\t\ti = matchIndexes.length;\n\n\t\t\t// Match elements found at the specified indexes\n\t\t\twhile ( i-- ) {\n\t\t\t\tif ( seed[ (j = matchIndexes[i]) ] ) {\n\t\t\t\t\tseed[j] = !(matches[j] = seed[j]);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t});\n}\n\n/**\n * Utility function for retrieving the text value of an array of DOM nodes\n * @param {Array|Element} elem\n */\ngetText = Sizzle.getText = function( elem ) {\n\tvar node,\n\t\tret = \"\",\n\t\ti = 0,\n\t\tnodeType = elem.nodeType;\n\n\tif ( !nodeType ) {\n\t\t// If no nodeType, this is expected to be an array\n\t\tfor ( ; (node = elem[i]); i++ ) {\n\t\t\t// Do not traverse comment nodes\n\t\t\tret += getText( node );\n\t\t}\n\t} else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) {\n\t\t// Use textContent for elements\n\t\t// innerText usage removed for consistency of new lines (see #11153)\n\t\tif ( typeof elem.textContent === \"string\" ) {\n\t\t\treturn elem.textContent;\n\t\t} else {\n\t\t\t// Traverse its children\n\t\t\tfor ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {\n\t\t\t\tret += getText( elem );\n\t\t\t}\n\t\t}\n\t} else if ( nodeType === 3 || nodeType === 4 ) {\n\t\treturn elem.nodeValue;\n\t}\n\t// Do not include comment or processing instruction nodes\n\n\treturn ret;\n};\n\nExpr = Sizzle.selectors = {\n\n\t// Can be adjusted by the user\n\tcacheLength: 50,\n\n\tcreatePseudo: markFunction,\n\n\tmatch: matchExpr,\n\n\tfind: {},\n\n\trelative: {\n\t\t\">\": { dir: \"parentNode\", first: true },\n\t\t\" \": { dir: \"parentNode\" },\n\t\t\"+\": { dir: \"previousSibling\", first: true },\n\t\t\"~\": { dir: \"previousSibling\" }\n\t},\n\n\tpreFilter: {\n\t\t\"ATTR\": function( match ) {\n\t\t\tmatch[1] = match[1].replace( runescape, funescape );\n\n\t\t\t// Move the given value to match[3] whether quoted or unquoted\n\t\t\tmatch[3] = ( match[4] || match[5] || \"\" ).replace( runescape, funescape );\n\n\t\t\tif ( match[2] === \"~=\" ) {\n\t\t\t\tmatch[3] = \" \" + match[3] + \" \";\n\t\t\t}\n\n\t\t\treturn match.slice( 0, 4 );\n\t\t},\n\n\t\t\"CHILD\": function( match ) {\n\t\t\t/* matches from matchExpr[\"CHILD\"]\n\t\t\t\t1 type (only|nth|...)\n\t\t\t\t2 what (child|of-type)\n\t\t\t\t3 argument (even|odd|\\d*|\\d*n([+-]\\d+)?|...)\n\t\t\t\t4 xn-component of xn+y argument ([+-]?\\d*n|)\n\t\t\t\t5 sign of xn-component\n\t\t\t\t6 x of xn-component\n\t\t\t\t7 sign of y-component\n\t\t\t\t8 y of y-component\n\t\t\t*/\n\t\t\tmatch[1] = match[1].toLowerCase();\n\n\t\t\tif ( match[1].slice( 0, 3 ) === \"nth\" ) {\n\t\t\t\t// nth-* requires argument\n\t\t\t\tif ( !match[3] ) {\n\t\t\t\t\tSizzle.error( match[0] );\n\t\t\t\t}\n\n\t\t\t\t// numeric x and y parameters for Expr.filter.CHILD\n\t\t\t\t// remember that false/true cast respectively to 0/1\n\t\t\t\tmatch[4] = +( match[4] ? match[5] + (match[6] || 1) : 2 * ( match[3] === \"even\" || match[3] === \"odd\" ) );\n\t\t\t\tmatch[5] = +( ( match[7] + match[8] ) || match[3] === \"odd\" );\n\n\t\t\t// other types prohibit arguments\n\t\t\t} else if ( match[3] ) {\n\t\t\t\tSizzle.error( match[0] );\n\t\t\t}\n\n\t\t\treturn match;\n\t\t},\n\n\t\t\"PSEUDO\": function( match ) {\n\t\t\tvar excess,\n\t\t\t\tunquoted = !match[5] && match[2];\n\n\t\t\tif ( matchExpr[\"CHILD\"].test( match[0] ) ) {\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\t// Accept quoted arguments as-is\n\t\t\tif ( match[4] ) {\n\t\t\t\tmatch[2] = match[4];\n\n\t\t\t// Strip excess characters from unquoted arguments\n\t\t\t} else if ( unquoted && rpseudo.test( unquoted ) &&\n\t\t\t\t// Get excess from tokenize (recursively)\n\t\t\t\t(excess = tokenize( unquoted, true )) &&\n\t\t\t\t// advance to the next closing parenthesis\n\t\t\t\t(excess = unquoted.indexOf( \")\", unquoted.length - excess ) - unquoted.length) ) {\n\n\t\t\t\t// excess is a negative index\n\t\t\t\tmatch[0] = match[0].slice( 0, excess );\n\t\t\t\tmatch[2] = unquoted.slice( 0, excess );\n\t\t\t}\n\n\t\t\t// Return only captures needed by the pseudo filter method (type and argument)\n\t\t\treturn match.slice( 0, 3 );\n\t\t}\n\t},\n\n\tfilter: {\n\n\t\t\"TAG\": function( nodeName ) {\n\t\t\tif ( nodeName === \"*\" ) {\n\t\t\t\treturn function() { return true; };\n\t\t\t}\n\n\t\t\tnodeName = nodeName.replace( runescape, funescape ).toLowerCase();\n\t\t\treturn function( elem ) {\n\t\t\t\treturn elem.nodeName && elem.nodeName.toLowerCase() === nodeName;\n\t\t\t};\n\t\t},\n\n\t\t\"CLASS\": function( className ) {\n\t\t\tvar pattern = classCache[ className + \" \" ];\n\n\t\t\treturn pattern ||\n\t\t\t\t(pattern = new RegExp( \"(^|\" + whitespace + \")\" + className + \"(\" + whitespace + \"|$)\" )) &&\n\t\t\t\tclassCache( className, function( elem ) {\n\t\t\t\t\treturn pattern.test( elem.className || (typeof elem.getAttribute !== strundefined && elem.getAttribute(\"class\")) || \"\" );\n\t\t\t\t});\n\t\t},\n\n\t\t\"ATTR\": function( name, operator, check ) {\n\t\t\treturn function( elem ) {\n\t\t\t\tvar result = Sizzle.attr( elem, name );\n\n\t\t\t\tif ( result == null ) {\n\t\t\t\t\treturn operator === \"!=\";\n\t\t\t\t}\n\t\t\t\tif ( !operator ) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\n\t\t\t\tresult += \"\";\n\n\t\t\t\treturn operator === \"=\" ? result === check :\n\t\t\t\t\toperator === \"!=\" ? result !== check :\n\t\t\t\t\toperator === \"^=\" ? check && result.indexOf( check ) === 0 :\n\t\t\t\t\toperator === \"*=\" ? check && result.indexOf( check ) > -1 :\n\t\t\t\t\toperator === \"$=\" ? check && result.slice( -check.length ) === check :\n\t\t\t\t\toperator === \"~=\" ? ( \" \" + result + \" \" ).indexOf( check ) > -1 :\n\t\t\t\t\toperator === \"|=\" ? result === check || result.slice( 0, check.length + 1 ) === check + \"-\" :\n\t\t\t\t\tfalse;\n\t\t\t};\n\t\t},\n\n\t\t\"CHILD\": function( type, what, argument, first, last ) {\n\t\t\tvar simple = type.slice( 0, 3 ) !== \"nth\",\n\t\t\t\tforward = type.slice( -4 ) !== \"last\",\n\t\t\t\tofType = what === \"of-type\";\n\n\t\t\treturn first === 1 && last === 0 ?\n\n\t\t\t\t// Shortcut for :nth-*(n)\n\t\t\t\tfunction( elem ) {\n\t\t\t\t\treturn !!elem.parentNode;\n\t\t\t\t} :\n\n\t\t\t\tfunction( elem, context, xml ) {\n\t\t\t\t\tvar cache, outerCache, node, diff, nodeIndex, start,\n\t\t\t\t\t\tdir = simple !== forward ? \"nextSibling\" : \"previousSibling\",\n\t\t\t\t\t\tparent = elem.parentNode,\n\t\t\t\t\t\tname = ofType && elem.nodeName.toLowerCase(),\n\t\t\t\t\t\tuseCache = !xml && !ofType;\n\n\t\t\t\t\tif ( parent ) {\n\n\t\t\t\t\t\t// :(first|last|only)-(child|of-type)\n\t\t\t\t\t\tif ( simple ) {\n\t\t\t\t\t\t\twhile ( dir ) {\n\t\t\t\t\t\t\t\tnode = elem;\n\t\t\t\t\t\t\t\twhile ( (node = node[ dir ]) ) {\n\t\t\t\t\t\t\t\t\tif ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) {\n\t\t\t\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t// Reverse direction for :only-* (if we haven't yet done so)\n\t\t\t\t\t\t\t\tstart = dir = type === \"only\" && !start && \"nextSibling\";\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tstart = [ forward ? parent.firstChild : parent.lastChild ];\n\n\t\t\t\t\t\t// non-xml :nth-child(...) stores cache data on `parent`\n\t\t\t\t\t\tif ( forward && useCache ) {\n\t\t\t\t\t\t\t// Seek `elem` from a previously-cached index\n\t\t\t\t\t\t\touterCache = parent[ expando ] || (parent[ expando ] = {});\n\t\t\t\t\t\t\tcache = outerCache[ type ] || [];\n\t\t\t\t\t\t\tnodeIndex = cache[0] === dirruns && cache[1];\n\t\t\t\t\t\t\tdiff = cache[0] === dirruns && cache[2];\n\t\t\t\t\t\t\tnode = nodeIndex && parent.childNodes[ nodeIndex ];\n\n\t\t\t\t\t\t\twhile ( (node = ++nodeIndex && node && node[ dir ] ||\n\n\t\t\t\t\t\t\t\t// Fallback to seeking `elem` from the start\n\t\t\t\t\t\t\t\t(diff = nodeIndex = 0) || start.pop()) ) {\n\n\t\t\t\t\t\t\t\t// When found, cache indexes on `parent` and break\n\t\t\t\t\t\t\t\tif ( node.nodeType === 1 && ++diff && node === elem ) {\n\t\t\t\t\t\t\t\t\touterCache[ type ] = [ dirruns, nodeIndex, diff ];\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Use previously-cached element index if available\n\t\t\t\t\t\t} else if ( useCache && (cache = (elem[ expando ] || (elem[ expando ] = {}))[ type ]) && cache[0] === dirruns ) {\n\t\t\t\t\t\t\tdiff = cache[1];\n\n\t\t\t\t\t\t// xml :nth-child(...) or :nth-last-child(...) or :nth(-last)?-of-type(...)\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t// Use the same loop as above to seek `elem` from the start\n\t\t\t\t\t\t\twhile ( (node = ++nodeIndex && node && node[ dir ] ||\n\t\t\t\t\t\t\t\t(diff = nodeIndex = 0) || start.pop()) ) {\n\n\t\t\t\t\t\t\t\tif ( ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) && ++diff ) {\n\t\t\t\t\t\t\t\t\t// Cache the index of each encountered element\n\t\t\t\t\t\t\t\t\tif ( useCache ) {\n\t\t\t\t\t\t\t\t\t\t(node[ expando ] || (node[ expando ] = {}))[ type ] = [ dirruns, diff ];\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\tif ( node === elem ) {\n\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Incorporate the offset, then check against cycle size\n\t\t\t\t\t\tdiff -= last;\n\t\t\t\t\t\treturn diff === first || ( diff % first === 0 && diff / first >= 0 );\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t},\n\n\t\t\"PSEUDO\": function( pseudo, argument ) {\n\t\t\t// pseudo-class names are case-insensitive\n\t\t\t// http://www.w3.org/TR/selectors/#pseudo-classes\n\t\t\t// Prioritize by case sensitivity in case custom pseudos are added with uppercase letters\n\t\t\t// Remember that setFilters inherits from pseudos\n\t\t\tvar args,\n\t\t\t\tfn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] ||\n\t\t\t\t\tSizzle.error( \"unsupported pseudo: \" + pseudo );\n\n\t\t\t// The user may use createPseudo to indicate that\n\t\t\t// arguments are needed to create the filter function\n\t\t\t// just as Sizzle does\n\t\t\tif ( fn[ expando ] ) {\n\t\t\t\treturn fn( argument );\n\t\t\t}\n\n\t\t\t// But maintain support for old signatures\n\t\t\tif ( fn.length > 1 ) {\n\t\t\t\targs = [ pseudo, pseudo, \"\", argument ];\n\t\t\t\treturn Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ?\n\t\t\t\t\tmarkFunction(function( seed, matches ) {\n\t\t\t\t\t\tvar idx,\n\t\t\t\t\t\t\tmatched = fn( seed, argument ),\n\t\t\t\t\t\t\ti = matched.length;\n\t\t\t\t\t\twhile ( i-- ) {\n\t\t\t\t\t\t\tidx = indexOf.call( seed, matched[i] );\n\t\t\t\t\t\t\tseed[ idx ] = !( matches[ idx ] = matched[i] );\n\t\t\t\t\t\t}\n\t\t\t\t\t}) :\n\t\t\t\t\tfunction( elem ) {\n\t\t\t\t\t\treturn fn( elem, 0, args );\n\t\t\t\t\t};\n\t\t\t}\n\n\t\t\treturn fn;\n\t\t}\n\t},\n\n\tpseudos: {\n\t\t// Potentially complex pseudos\n\t\t\"not\": markFunction(function( selector ) {\n\t\t\t// Trim the selector passed to compile\n\t\t\t// to avoid treating leading and trailing\n\t\t\t// spaces as combinators\n\t\t\tvar input = [],\n\t\t\t\tresults = [],\n\t\t\t\tmatcher = compile( selector.replace( rtrim, \"$1\" ) );\n\n\t\t\treturn matcher[ expando ] ?\n\t\t\t\tmarkFunction(function( seed, matches, context, xml ) {\n\t\t\t\t\tvar elem,\n\t\t\t\t\t\tunmatched = matcher( seed, null, xml, [] ),\n\t\t\t\t\t\ti = seed.length;\n\n\t\t\t\t\t// Match elements unmatched by `matcher`\n\t\t\t\t\twhile ( i-- ) {\n\t\t\t\t\t\tif ( (elem = unmatched[i]) ) {\n\t\t\t\t\t\t\tseed[i] = !(matches[i] = elem);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}) :\n\t\t\t\tfunction( elem, context, xml ) {\n\t\t\t\t\tinput[0] = elem;\n\t\t\t\t\tmatcher( input, null, xml, results );\n\t\t\t\t\treturn !results.pop();\n\t\t\t\t};\n\t\t}),\n\n\t\t\"has\": markFunction(function( selector ) {\n\t\t\treturn function( elem ) {\n\t\t\t\treturn Sizzle( selector, elem ).length > 0;\n\t\t\t};\n\t\t}),\n\n\t\t\"contains\": markFunction(function( text ) {\n\t\t\treturn function( elem ) {\n\t\t\t\treturn ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1;\n\t\t\t};\n\t\t}),\n\n\t\t// \"Whether an element is represented by a :lang() selector\n\t\t// is based solely on the element's language value\n\t\t// being equal to the identifier C,\n\t\t// or beginning with the identifier C immediately followed by \"-\".\n\t\t// The matching of C against the element's language value is performed case-insensitively.\n\t\t// The identifier C does not have to be a valid language name.\"\n\t\t// http://www.w3.org/TR/selectors/#lang-pseudo\n\t\t\"lang\": markFunction( function( lang ) {\n\t\t\t// lang value must be a valid identifider\n\t\t\tif ( !ridentifier.test(lang || \"\") ) {\n\t\t\t\tSizzle.error( \"unsupported lang: \" + lang );\n\t\t\t}\n\t\t\tlang = lang.replace( runescape, funescape ).toLowerCase();\n\t\t\treturn function( elem ) {\n\t\t\t\tvar elemLang;\n\t\t\t\tdo {\n\t\t\t\t\tif ( (elemLang = documentIsXML ?\n\t\t\t\t\t\telem.getAttribute(\"xml:lang\") || elem.getAttribute(\"lang\") :\n\t\t\t\t\t\telem.lang) ) {\n\n\t\t\t\t\t\telemLang = elemLang.toLowerCase();\n\t\t\t\t\t\treturn elemLang === lang || elemLang.indexOf( lang + \"-\" ) === 0;\n\t\t\t\t\t}\n\t\t\t\t} while ( (elem = elem.parentNode) && elem.nodeType === 1 );\n\t\t\t\treturn false;\n\t\t\t};\n\t\t}),\n\n\t\t// Miscellaneous\n\t\t\"target\": function( elem ) {\n\t\t\tvar hash = window.location && window.location.hash;\n\t\t\treturn hash && hash.slice( 1 ) === elem.id;\n\t\t},\n\n\t\t\"root\": function( elem ) {\n\t\t\treturn elem === docElem;\n\t\t},\n\n\t\t\"focus\": function( elem ) {\n\t\t\treturn elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex);\n\t\t},\n\n\t\t// Boolean properties\n\t\t\"enabled\": function( elem ) {\n\t\t\treturn elem.disabled === false;\n\t\t},\n\n\t\t\"disabled\": function( elem ) {\n\t\t\treturn elem.disabled === true;\n\t\t},\n\n\t\t\"checked\": function( elem ) {\n\t\t\t// In CSS3, :checked should return both checked and selected elements\n\t\t\t// http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked\n\t\t\tvar nodeName = elem.nodeName.toLowerCase();\n\t\t\treturn (nodeName === \"input\" && !!elem.checked) || (nodeName === \"option\" && !!elem.selected);\n\t\t},\n\n\t\t\"selected\": function( elem ) {\n\t\t\t// Accessing this property makes selected-by-default\n\t\t\t// options in Safari work properly\n\t\t\tif ( elem.parentNode ) {\n\t\t\t\telem.parentNode.selectedIndex;\n\t\t\t}\n\n\t\t\treturn elem.selected === true;\n\t\t},\n\n\t\t// Contents\n\t\t\"empty\": function( elem ) {\n\t\t\t// http://www.w3.org/TR/selectors/#empty-pseudo\n\t\t\t// :empty is only affected by element nodes and content nodes(including text(3), cdata(4)),\n\t\t\t//   not comment, processing instructions, or others\n\t\t\t// Thanks to Diego Perini for the nodeName shortcut\n\t\t\t//   Greater than \"@\" means alpha characters (specifically not starting with \"#\" or \"?\")\n\t\t\tfor ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {\n\t\t\t\tif ( elem.nodeName > \"@\" || elem.nodeType === 3 || elem.nodeType === 4 ) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn true;\n\t\t},\n\n\t\t\"parent\": function( elem ) {\n\t\t\treturn !Expr.pseudos[\"empty\"]( elem );\n\t\t},\n\n\t\t// Element/input types\n\t\t\"header\": function( elem ) {\n\t\t\treturn rheader.test( elem.nodeName );\n\t\t},\n\n\t\t\"input\": function( elem ) {\n\t\t\treturn rinputs.test( elem.nodeName );\n\t\t},\n\n\t\t\"button\": function( elem ) {\n\t\t\tvar name = elem.nodeName.toLowerCase();\n\t\t\treturn name === \"input\" && elem.type === \"button\" || name === \"button\";\n\t\t},\n\n\t\t\"text\": function( elem ) {\n\t\t\tvar attr;\n\t\t\t// IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc)\n\t\t\t// use getAttribute instead to test this case\n\t\t\treturn elem.nodeName.toLowerCase() === \"input\" &&\n\t\t\t\telem.type === \"text\" &&\n\t\t\t\t( (attr = elem.getAttribute(\"type\")) == null || attr.toLowerCase() === elem.type );\n\t\t},\n\n\t\t// Position-in-collection\n\t\t\"first\": createPositionalPseudo(function() {\n\t\t\treturn [ 0 ];\n\t\t}),\n\n\t\t\"last\": createPositionalPseudo(function( matchIndexes, length ) {\n\t\t\treturn [ length - 1 ];\n\t\t}),\n\n\t\t\"eq\": createPositionalPseudo(function( matchIndexes, length, argument ) {\n\t\t\treturn [ argument < 0 ? argument + length : argument ];\n\t\t}),\n\n\t\t\"even\": createPositionalPseudo(function( matchIndexes, length ) {\n\t\t\tvar i = 0;\n\t\t\tfor ( ; i < length; i += 2 ) {\n\t\t\t\tmatchIndexes.push( i );\n\t\t\t}\n\t\t\treturn matchIndexes;\n\t\t}),\n\n\t\t\"odd\": createPositionalPseudo(function( matchIndexes, length ) {\n\t\t\tvar i = 1;\n\t\t\tfor ( ; i < length; i += 2 ) {\n\t\t\t\tmatchIndexes.push( i );\n\t\t\t}\n\t\t\treturn matchIndexes;\n\t\t}),\n\n\t\t\"lt\": createPositionalPseudo(function( matchIndexes, length, argument ) {\n\t\t\tvar i = argument < 0 ? argument + length : argument;\n\t\t\tfor ( ; --i >= 0; ) {\n\t\t\t\tmatchIndexes.push( i );\n\t\t\t}\n\t\t\treturn matchIndexes;\n\t\t}),\n\n\t\t\"gt\": createPositionalPseudo(function( matchIndexes, length, argument ) {\n\t\t\tvar i = argument < 0 ? argument + length : argument;\n\t\t\tfor ( ; ++i < length; ) {\n\t\t\t\tmatchIndexes.push( i );\n\t\t\t}\n\t\t\treturn matchIndexes;\n\t\t})\n\t}\n};\n\n// Add button/input type pseudos\nfor ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) {\n\tExpr.pseudos[ i ] = createInputPseudo( i );\n}\nfor ( i in { submit: true, reset: true } ) {\n\tExpr.pseudos[ i ] = createButtonPseudo( i );\n}\n\nfunction tokenize( selector, parseOnly ) {\n\tvar matched, match, tokens, type,\n\t\tsoFar, groups, preFilters,\n\t\tcached = tokenCache[ selector + \" \" ];\n\n\tif ( cached ) {\n\t\treturn parseOnly ? 0 : cached.slice( 0 );\n\t}\n\n\tsoFar = selector;\n\tgroups = [];\n\tpreFilters = Expr.preFilter;\n\n\twhile ( soFar ) {\n\n\t\t// Comma and first run\n\t\tif ( !matched || (match = rcomma.exec( soFar )) ) {\n\t\t\tif ( match ) {\n\t\t\t\t// Don't consume trailing commas as valid\n\t\t\t\tsoFar = soFar.slice( match[0].length ) || soFar;\n\t\t\t}\n\t\t\tgroups.push( tokens = [] );\n\t\t}\n\n\t\tmatched = false;\n\n\t\t// Combinators\n\t\tif ( (match = rcombinators.exec( soFar )) ) {\n\t\t\tmatched = match.shift();\n\t\t\ttokens.push( {\n\t\t\t\tvalue: matched,\n\t\t\t\t// Cast descendant combinators to space\n\t\t\t\ttype: match[0].replace( rtrim, \" \" )\n\t\t\t} );\n\t\t\tsoFar = soFar.slice( matched.length );\n\t\t}\n\n\t\t// Filters\n\t\tfor ( type in Expr.filter ) {\n\t\t\tif ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] ||\n\t\t\t\t(match = preFilters[ type ]( match ))) ) {\n\t\t\t\tmatched = match.shift();\n\t\t\t\ttokens.push( {\n\t\t\t\t\tvalue: matched,\n\t\t\t\t\ttype: type,\n\t\t\t\t\tmatches: match\n\t\t\t\t} );\n\t\t\t\tsoFar = soFar.slice( matched.length );\n\t\t\t}\n\t\t}\n\n\t\tif ( !matched ) {\n\t\t\tbreak;\n\t\t}\n\t}\n\n\t// Return the length of the invalid excess\n\t// if we're just parsing\n\t// Otherwise, throw an error or return tokens\n\treturn parseOnly ?\n\t\tsoFar.length :\n\t\tsoFar ?\n\t\t\tSizzle.error( selector ) :\n\t\t\t// Cache the tokens\n\t\t\ttokenCache( selector, groups ).slice( 0 );\n}\n\nfunction toSelector( tokens ) {\n\tvar i = 0,\n\t\tlen = tokens.length,\n\t\tselector = \"\";\n\tfor ( ; i < len; i++ ) {\n\t\tselector += tokens[i].value;\n\t}\n\treturn selector;\n}\n\nfunction addCombinator( matcher, combinator, base ) {\n\tvar dir = combinator.dir,\n\t\tcheckNonElements = base && dir === \"parentNode\",\n\t\tdoneName = done++;\n\n\treturn combinator.first ?\n\t\t// Check against closest ancestor/preceding element\n\t\tfunction( elem, context, xml ) {\n\t\t\twhile ( (elem = elem[ dir ]) ) {\n\t\t\t\tif ( elem.nodeType === 1 || checkNonElements ) {\n\t\t\t\t\treturn matcher( elem, context, xml );\n\t\t\t\t}\n\t\t\t}\n\t\t} :\n\n\t\t// Check against all ancestor/preceding elements\n\t\tfunction( elem, context, xml ) {\n\t\t\tvar data, cache, outerCache,\n\t\t\t\tdirkey = dirruns + \" \" + doneName;\n\n\t\t\t// We can't set arbitrary data on XML nodes, so they don't benefit from dir caching\n\t\t\tif ( xml ) {\n\t\t\t\twhile ( (elem = elem[ dir ]) ) {\n\t\t\t\t\tif ( elem.nodeType === 1 || checkNonElements ) {\n\t\t\t\t\t\tif ( matcher( elem, context, xml ) ) {\n\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\twhile ( (elem = elem[ dir ]) ) {\n\t\t\t\t\tif ( elem.nodeType === 1 || checkNonElements ) {\n\t\t\t\t\t\touterCache = elem[ expando ] || (elem[ expando ] = {});\n\t\t\t\t\t\tif ( (cache = outerCache[ dir ]) && cache[0] === dirkey ) {\n\t\t\t\t\t\t\tif ( (data = cache[1]) === true || data === cachedruns ) {\n\t\t\t\t\t\t\t\treturn data === true;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tcache = outerCache[ dir ] = [ dirkey ];\n\t\t\t\t\t\t\tcache[1] = matcher( elem, context, xml ) || cachedruns;\n\t\t\t\t\t\t\tif ( cache[1] === true ) {\n\t\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t};\n}\n\nfunction elementMatcher( matchers ) {\n\treturn matchers.length > 1 ?\n\t\tfunction( elem, context, xml ) {\n\t\t\tvar i = matchers.length;\n\t\t\twhile ( i-- ) {\n\t\t\t\tif ( !matchers[i]( elem, context, xml ) ) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn true;\n\t\t} :\n\t\tmatchers[0];\n}\n\nfunction condense( unmatched, map, filter, context, xml ) {\n\tvar elem,\n\t\tnewUnmatched = [],\n\t\ti = 0,\n\t\tlen = unmatched.length,\n\t\tmapped = map != null;\n\n\tfor ( ; i < len; i++ ) {\n\t\tif ( (elem = unmatched[i]) ) {\n\t\t\tif ( !filter || filter( elem, context, xml ) ) {\n\t\t\t\tnewUnmatched.push( elem );\n\t\t\t\tif ( mapped ) {\n\t\t\t\t\tmap.push( i );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn newUnmatched;\n}\n\nfunction setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) {\n\tif ( postFilter && !postFilter[ expando ] ) {\n\t\tpostFilter = setMatcher( postFilter );\n\t}\n\tif ( postFinder && !postFinder[ expando ] ) {\n\t\tpostFinder = setMatcher( postFinder, postSelector );\n\t}\n\treturn markFunction(function( seed, results, context, xml ) {\n\t\tvar temp, i, elem,\n\t\t\tpreMap = [],\n\t\t\tpostMap = [],\n\t\t\tpreexisting = results.length,\n\n\t\t\t// Get initial elements from seed or context\n\t\t\telems = seed || multipleContexts( selector || \"*\", context.nodeType ? [ context ] : context, [] ),\n\n\t\t\t// Prefilter to get matcher input, preserving a map for seed-results synchronization\n\t\t\tmatcherIn = preFilter && ( seed || !selector ) ?\n\t\t\t\tcondense( elems, preMap, preFilter, context, xml ) :\n\t\t\t\telems,\n\n\t\t\tmatcherOut = matcher ?\n\t\t\t\t// If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results,\n\t\t\t\tpostFinder || ( seed ? preFilter : preexisting || postFilter ) ?\n\n\t\t\t\t\t// ...intermediate processing is necessary\n\t\t\t\t\t[] :\n\n\t\t\t\t\t// ...otherwise use results directly\n\t\t\t\t\tresults :\n\t\t\t\tmatcherIn;\n\n\t\t// Find primary matches\n\t\tif ( matcher ) {\n\t\t\tmatcher( matcherIn, matcherOut, context, xml );\n\t\t}\n\n\t\t// Apply postFilter\n\t\tif ( postFilter ) {\n\t\t\ttemp = condense( matcherOut, postMap );\n\t\t\tpostFilter( temp, [], context, xml );\n\n\t\t\t// Un-match failing elements by moving them back to matcherIn\n\t\t\ti = temp.length;\n\t\t\twhile ( i-- ) {\n\t\t\t\tif ( (elem = temp[i]) ) {\n\t\t\t\t\tmatcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif ( seed ) {\n\t\t\tif ( postFinder || preFilter ) {\n\t\t\t\tif ( postFinder ) {\n\t\t\t\t\t// Get the final matcherOut by condensing this intermediate into postFinder contexts\n\t\t\t\t\ttemp = [];\n\t\t\t\t\ti = matcherOut.length;\n\t\t\t\t\twhile ( i-- ) {\n\t\t\t\t\t\tif ( (elem = matcherOut[i]) ) {\n\t\t\t\t\t\t\t// Restore matcherIn since elem is not yet a final match\n\t\t\t\t\t\t\ttemp.push( (matcherIn[i] = elem) );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tpostFinder( null, (matcherOut = []), temp, xml );\n\t\t\t\t}\n\n\t\t\t\t// Move matched elements from seed to results to keep them synchronized\n\t\t\t\ti = matcherOut.length;\n\t\t\t\twhile ( i-- ) {\n\t\t\t\t\tif ( (elem = matcherOut[i]) &&\n\t\t\t\t\t\t(temp = postFinder ? indexOf.call( seed, elem ) : preMap[i]) > -1 ) {\n\n\t\t\t\t\t\tseed[temp] = !(results[temp] = elem);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t// Add elements to results, through postFinder if defined\n\t\t} else {\n\t\t\tmatcherOut = condense(\n\t\t\t\tmatcherOut === results ?\n\t\t\t\t\tmatcherOut.splice( preexisting, matcherOut.length ) :\n\t\t\t\t\tmatcherOut\n\t\t\t);\n\t\t\tif ( postFinder ) {\n\t\t\t\tpostFinder( null, results, matcherOut, xml );\n\t\t\t} else {\n\t\t\t\tpush.apply( results, matcherOut );\n\t\t\t}\n\t\t}\n\t});\n}\n\nfunction matcherFromTokens( tokens ) {\n\tvar checkContext, matcher, j,\n\t\tlen = tokens.length,\n\t\tleadingRelative = Expr.relative[ tokens[0].type ],\n\t\timplicitRelative = leadingRelative || Expr.relative[\" \"],\n\t\ti = leadingRelative ? 1 : 0,\n\n\t\t// The foundational matcher ensures that elements are reachable from top-level context(s)\n\t\tmatchContext = addCombinator( function( elem ) {\n\t\t\treturn elem === checkContext;\n\t\t}, implicitRelative, true ),\n\t\tmatchAnyContext = addCombinator( function( elem ) {\n\t\t\treturn indexOf.call( checkContext, elem ) > -1;\n\t\t}, implicitRelative, true ),\n\t\tmatchers = [ function( elem, context, xml ) {\n\t\t\treturn ( !leadingRelative && ( xml || context !== outermostContext ) ) || (\n\t\t\t\t(checkContext = context).nodeType ?\n\t\t\t\t\tmatchContext( elem, context, xml ) :\n\t\t\t\t\tmatchAnyContext( elem, context, xml ) );\n\t\t} ];\n\n\tfor ( ; i < len; i++ ) {\n\t\tif ( (matcher = Expr.relative[ tokens[i].type ]) ) {\n\t\t\tmatchers = [ addCombinator(elementMatcher( matchers ), matcher) ];\n\t\t} else {\n\t\t\tmatcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches );\n\n\t\t\t// Return special upon seeing a positional matcher\n\t\t\tif ( matcher[ expando ] ) {\n\t\t\t\t// Find the next relative operator (if any) for proper handling\n\t\t\t\tj = ++i;\n\t\t\t\tfor ( ; j < len; j++ ) {\n\t\t\t\t\tif ( Expr.relative[ tokens[j].type ] ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn setMatcher(\n\t\t\t\t\ti > 1 && elementMatcher( matchers ),\n\t\t\t\t\ti > 1 && toSelector( tokens.slice( 0, i - 1 ) ).replace( rtrim, \"$1\" ),\n\t\t\t\t\tmatcher,\n\t\t\t\t\ti < j && matcherFromTokens( tokens.slice( i, j ) ),\n\t\t\t\t\tj < len && matcherFromTokens( (tokens = tokens.slice( j )) ),\n\t\t\t\t\tj < len && toSelector( tokens )\n\t\t\t\t);\n\t\t\t}\n\t\t\tmatchers.push( matcher );\n\t\t}\n\t}\n\n\treturn elementMatcher( matchers );\n}\n\nfunction matcherFromGroupMatchers( elementMatchers, setMatchers ) {\n\t// A counter to specify which element is currently being matched\n\tvar matcherCachedRuns = 0,\n\t\tbySet = setMatchers.length > 0,\n\t\tbyElement = elementMatchers.length > 0,\n\t\tsuperMatcher = function( seed, context, xml, results, expandContext ) {\n\t\t\tvar elem, j, matcher,\n\t\t\t\tsetMatched = [],\n\t\t\t\tmatchedCount = 0,\n\t\t\t\ti = \"0\",\n\t\t\t\tunmatched = seed && [],\n\t\t\t\toutermost = expandContext != null,\n\t\t\t\tcontextBackup = outermostContext,\n\t\t\t\t// We must always have either seed elements or context\n\t\t\t\telems = seed || byElement && Expr.find[\"TAG\"]( \"*\", expandContext && context.parentNode || context ),\n\t\t\t\t// Use integer dirruns iff this is the outermost matcher\n\t\t\t\tdirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1);\n\n\t\t\tif ( outermost ) {\n\t\t\t\toutermostContext = context !== document && context;\n\t\t\t\tcachedruns = matcherCachedRuns;\n\t\t\t}\n\n\t\t\t// Add elements passing elementMatchers directly to results\n\t\t\t// Keep `i` a string if there are no elements so `matchedCount` will be \"00\" below\n\t\t\tfor ( ; (elem = elems[i]) != null; i++ ) {\n\t\t\t\tif ( byElement && elem ) {\n\t\t\t\t\tj = 0;\n\t\t\t\t\twhile ( (matcher = elementMatchers[j++]) ) {\n\t\t\t\t\t\tif ( matcher( elem, context, xml ) ) {\n\t\t\t\t\t\t\tresults.push( elem );\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif ( outermost ) {\n\t\t\t\t\t\tdirruns = dirrunsUnique;\n\t\t\t\t\t\tcachedruns = ++matcherCachedRuns;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Track unmatched elements for set filters\n\t\t\t\tif ( bySet ) {\n\t\t\t\t\t// They will have gone through all possible matchers\n\t\t\t\t\tif ( (elem = !matcher && elem) ) {\n\t\t\t\t\t\tmatchedCount--;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Lengthen the array for every element, matched or not\n\t\t\t\t\tif ( seed ) {\n\t\t\t\t\t\tunmatched.push( elem );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Apply set filters to unmatched elements\n\t\t\tmatchedCount += i;\n\t\t\tif ( bySet && i !== matchedCount ) {\n\t\t\t\tj = 0;\n\t\t\t\twhile ( (matcher = setMatchers[j++]) ) {\n\t\t\t\t\tmatcher( unmatched, setMatched, context, xml );\n\t\t\t\t}\n\n\t\t\t\tif ( seed ) {\n\t\t\t\t\t// Reintegrate element matches to eliminate the need for sorting\n\t\t\t\t\tif ( matchedCount > 0 ) {\n\t\t\t\t\t\twhile ( i-- ) {\n\t\t\t\t\t\t\tif ( !(unmatched[i] || setMatched[i]) ) {\n\t\t\t\t\t\t\t\tsetMatched[i] = pop.call( results );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Discard index placeholder values to get only actual matches\n\t\t\t\t\tsetMatched = condense( setMatched );\n\t\t\t\t}\n\n\t\t\t\t// Add matches to results\n\t\t\t\tpush.apply( results, setMatched );\n\n\t\t\t\t// Seedless set matches succeeding multiple successful matchers stipulate sorting\n\t\t\t\tif ( outermost && !seed && setMatched.length > 0 &&\n\t\t\t\t\t( matchedCount + setMatchers.length ) > 1 ) {\n\n\t\t\t\t\tSizzle.uniqueSort( results );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Override manipulation of globals by nested matchers\n\t\t\tif ( outermost ) {\n\t\t\t\tdirruns = dirrunsUnique;\n\t\t\t\toutermostContext = contextBackup;\n\t\t\t}\n\n\t\t\treturn unmatched;\n\t\t};\n\n\treturn bySet ?\n\t\tmarkFunction( superMatcher ) :\n\t\tsuperMatcher;\n}\n\ncompile = Sizzle.compile = function( selector, group /* Internal Use Only */ ) {\n\tvar i,\n\t\tsetMatchers = [],\n\t\telementMatchers = [],\n\t\tcached = compilerCache[ selector + \" \" ];\n\n\tif ( !cached ) {\n\t\t// Generate a function of recursive functions that can be used to check each element\n\t\tif ( !group ) {\n\t\t\tgroup = tokenize( selector );\n\t\t}\n\t\ti = group.length;\n\t\twhile ( i-- ) {\n\t\t\tcached = matcherFromTokens( group[i] );\n\t\t\tif ( cached[ expando ] ) {\n\t\t\t\tsetMatchers.push( cached );\n\t\t\t} else {\n\t\t\t\telementMatchers.push( cached );\n\t\t\t}\n\t\t}\n\n\t\t// Cache the compiled function\n\t\tcached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) );\n\t}\n\treturn cached;\n};\n\nfunction multipleContexts( selector, contexts, results ) {\n\tvar i = 0,\n\t\tlen = contexts.length;\n\tfor ( ; i < len; i++ ) {\n\t\tSizzle( selector, contexts[i], results );\n\t}\n\treturn results;\n}\n\nfunction select( selector, context, results, seed ) {\n\tvar i, tokens, token, type, find,\n\t\tmatch = tokenize( selector );\n\n\tif ( !seed ) {\n\t\t// Try to minimize operations if there is only one group\n\t\tif ( match.length === 1 ) {\n\n\t\t\t// Take a shortcut and set the context if the root selector is an ID\n\t\t\ttokens = match[0] = match[0].slice( 0 );\n\t\t\tif ( tokens.length > 2 && (token = tokens[0]).type === \"ID\" &&\n\t\t\t\t\tcontext.nodeType === 9 && !documentIsXML &&\n\t\t\t\t\tExpr.relative[ tokens[1].type ] ) {\n\n\t\t\t\tcontext = Expr.find[\"ID\"]( token.matches[0].replace( runescape, funescape ), context )[0];\n\t\t\t\tif ( !context ) {\n\t\t\t\t\treturn results;\n\t\t\t\t}\n\n\t\t\t\tselector = selector.slice( tokens.shift().value.length );\n\t\t\t}\n\n\t\t\t// Fetch a seed set for right-to-left matching\n\t\t\ti = matchExpr[\"needsContext\"].test( selector ) ? 0 : tokens.length;\n\t\t\twhile ( i-- ) {\n\t\t\t\ttoken = tokens[i];\n\n\t\t\t\t// Abort if we hit a combinator\n\t\t\t\tif ( Expr.relative[ (type = token.type) ] ) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tif ( (find = Expr.find[ type ]) ) {\n\t\t\t\t\t// Search, expanding context for leading sibling combinators\n\t\t\t\t\tif ( (seed = find(\n\t\t\t\t\t\ttoken.matches[0].replace( runescape, funescape ),\n\t\t\t\t\t\trsibling.test( tokens[0].type ) && context.parentNode || context\n\t\t\t\t\t)) ) {\n\n\t\t\t\t\t\t// If seed is empty or no tokens remain, we can return early\n\t\t\t\t\t\ttokens.splice( i, 1 );\n\t\t\t\t\t\tselector = seed.length && toSelector( tokens );\n\t\t\t\t\t\tif ( !selector ) {\n\t\t\t\t\t\t\tpush.apply( results, slice.call( seed, 0 ) );\n\t\t\t\t\t\t\treturn results;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Compile and execute a filtering function\n\t// Provide `match` to avoid retokenization if we modified the selector above\n\tcompile( selector, match )(\n\t\tseed,\n\t\tcontext,\n\t\tdocumentIsXML,\n\t\tresults,\n\t\trsibling.test( selector )\n\t);\n\treturn results;\n}\n\n// Deprecated\nExpr.pseudos[\"nth\"] = Expr.pseudos[\"eq\"];\n\n// Easy API for creating new setFilters\nfunction setFilters() {}\nExpr.filters = setFilters.prototype = Expr.pseudos;\nExpr.setFilters = new setFilters();\n\n// Initialize with the default document\nsetDocument();\n\n// Override sizzle attribute retrieval\nSizzle.attr = jQuery.attr;\njQuery.find = Sizzle;\njQuery.expr = Sizzle.selectors;\njQuery.expr[\":\"] = jQuery.expr.pseudos;\njQuery.unique = Sizzle.uniqueSort;\njQuery.text = Sizzle.getText;\njQuery.isXMLDoc = Sizzle.isXML;\njQuery.contains = Sizzle.contains;\n\n\n})( window );\nvar runtil = /Until$/,\n\trparentsprev = /^(?:parents|prev(?:Until|All))/,\n\tisSimple = /^.[^:#\\[\\.,]*$/,\n\trneedsContext = jQuery.expr.match.needsContext,\n\t// methods guaranteed to produce a unique set when starting from a unique set\n\tguaranteedUnique = {\n\t\tchildren: true,\n\t\tcontents: true,\n\t\tnext: true,\n\t\tprev: true\n\t};\n\njQuery.fn.extend({\n\tfind: function( selector ) {\n\t\tvar i, ret, self,\n\t\t\tlen = this.length;\n\n\t\tif ( typeof selector !== \"string\" ) {\n\t\t\tself = this;\n\t\t\treturn this.pushStack( jQuery( selector ).filter(function() {\n\t\t\t\tfor ( i = 0; i < len; i++ ) {\n\t\t\t\t\tif ( jQuery.contains( self[ i ], this ) ) {\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}) );\n\t\t}\n\n\t\tret = [];\n\t\tfor ( i = 0; i < len; i++ ) {\n\t\t\tjQuery.find( selector, this[ i ], ret );\n\t\t}\n\n\t\t// Needed because $( selector, context ) becomes $( context ).find( selector )\n\t\tret = this.pushStack( len > 1 ? jQuery.unique( ret ) : ret );\n\t\tret.selector = ( this.selector ? this.selector + \" \" : \"\" ) + selector;\n\t\treturn ret;\n\t},\n\n\thas: function( target ) {\n\t\tvar i,\n\t\t\ttargets = jQuery( target, this ),\n\t\t\tlen = targets.length;\n\n\t\treturn this.filter(function() {\n\t\t\tfor ( i = 0; i < len; i++ ) {\n\t\t\t\tif ( jQuery.contains( this, targets[i] ) ) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t},\n\n\tnot: function( selector ) {\n\t\treturn this.pushStack( winnow(this, selector, false) );\n\t},\n\n\tfilter: function( selector ) {\n\t\treturn this.pushStack( winnow(this, selector, true) );\n\t},\n\n\tis: function( selector ) {\n\t\treturn !!selector && (\n\t\t\ttypeof selector === \"string\" ?\n\t\t\t\t// If this is a positional/relative selector, check membership in the returned set\n\t\t\t\t// so $(\"p:first\").is(\"p:last\") won't return true for a doc with two \"p\".\n\t\t\t\trneedsContext.test( selector ) ?\n\t\t\t\t\tjQuery( selector, this.context ).index( this[0] ) >= 0 :\n\t\t\t\t\tjQuery.filter( selector, this ).length > 0 :\n\t\t\t\tthis.filter( selector ).length > 0 );\n\t},\n\n\tclosest: function( selectors, context ) {\n\t\tvar cur,\n\t\t\ti = 0,\n\t\t\tl = this.length,\n\t\t\tret = [],\n\t\t\tpos = rneedsContext.test( selectors ) || typeof selectors !== \"string\" ?\n\t\t\t\tjQuery( selectors, context || this.context ) :\n\t\t\t\t0;\n\n\t\tfor ( ; i < l; i++ ) {\n\t\t\tcur = this[i];\n\n\t\t\twhile ( cur && cur.ownerDocument && cur !== context && cur.nodeType !== 11 ) {\n\t\t\t\tif ( pos ? pos.index(cur) > -1 : jQuery.find.matchesSelector(cur, selectors) ) {\n\t\t\t\t\tret.push( cur );\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcur = cur.parentNode;\n\t\t\t}\n\t\t}\n\n\t\treturn this.pushStack( ret.length > 1 ? jQuery.unique( ret ) : ret );\n\t},\n\n\t// Determine the position of an element within\n\t// the matched set of elements\n\tindex: function( elem ) {\n\n\t\t// No argument, return index in parent\n\t\tif ( !elem ) {\n\t\t\treturn ( this[0] && this[0].parentNode ) ? this.first().prevAll().length : -1;\n\t\t}\n\n\t\t// index in selector\n\t\tif ( typeof elem === \"string\" ) {\n\t\t\treturn jQuery.inArray( this[0], jQuery( elem ) );\n\t\t}\n\n\t\t// Locate the position of the desired element\n\t\treturn jQuery.inArray(\n\t\t\t// If it receives a jQuery object, the first element is used\n\t\t\telem.jquery ? elem[0] : elem, this );\n\t},\n\n\tadd: function( selector, context ) {\n\t\tvar set = typeof selector === \"string\" ?\n\t\t\t\tjQuery( selector, context ) :\n\t\t\t\tjQuery.makeArray( selector && selector.nodeType ? [ selector ] : selector ),\n\t\t\tall = jQuery.merge( this.get(), set );\n\n\t\treturn this.pushStack( jQuery.unique(all) );\n\t},\n\n\taddBack: function( selector ) {\n\t\treturn this.add( selector == null ?\n\t\t\tthis.prevObject : this.prevObject.filter(selector)\n\t\t);\n\t}\n});\n\njQuery.fn.andSelf = jQuery.fn.addBack;\n\nfunction sibling( cur, dir ) {\n\tdo {\n\t\tcur = cur[ dir ];\n\t} while ( cur && cur.nodeType !== 1 );\n\n\treturn cur;\n}\n\njQuery.each({\n\tparent: function( elem ) {\n\t\tvar parent = elem.parentNode;\n\t\treturn parent && parent.nodeType !== 11 ? parent : null;\n\t},\n\tparents: function( elem ) {\n\t\treturn jQuery.dir( elem, \"parentNode\" );\n\t},\n\tparentsUntil: function( elem, i, until ) {\n\t\treturn jQuery.dir( elem, \"parentNode\", until );\n\t},\n\tnext: function( elem ) {\n\t\treturn sibling( elem, \"nextSibling\" );\n\t},\n\tprev: function( elem ) {\n\t\treturn sibling( elem, \"previousSibling\" );\n\t},\n\tnextAll: function( elem ) {\n\t\treturn jQuery.dir( elem, \"nextSibling\" );\n\t},\n\tprevAll: function( elem ) {\n\t\treturn jQuery.dir( elem, \"previousSibling\" );\n\t},\n\tnextUntil: function( elem, i, until ) {\n\t\treturn jQuery.dir( elem, \"nextSibling\", until );\n\t},\n\tprevUntil: function( elem, i, until ) {\n\t\treturn jQuery.dir( elem, \"previousSibling\", until );\n\t},\n\tsiblings: function( elem ) {\n\t\treturn jQuery.sibling( ( elem.parentNode || {} ).firstChild, elem );\n\t},\n\tchildren: function( elem ) {\n\t\treturn jQuery.sibling( elem.firstChild );\n\t},\n\tcontents: function( elem ) {\n\t\treturn jQuery.nodeName( elem, \"iframe\" ) ?\n\t\t\telem.contentDocument || elem.contentWindow.document :\n\t\t\tjQuery.merge( [], elem.childNodes );\n\t}\n}, function( name, fn ) {\n\tjQuery.fn[ name ] = function( until, selector ) {\n\t\tvar ret = jQuery.map( this, fn, until );\n\n\t\tif ( !runtil.test( name ) ) {\n\t\t\tselector = until;\n\t\t}\n\n\t\tif ( selector && typeof selector === \"string\" ) {\n\t\t\tret = jQuery.filter( selector, ret );\n\t\t}\n\n\t\tret = this.length > 1 && !guaranteedUnique[ name ] ? jQuery.unique( ret ) : ret;\n\n\t\tif ( this.length > 1 && rparentsprev.test( name ) ) {\n\t\t\tret = ret.reverse();\n\t\t}\n\n\t\treturn this.pushStack( ret );\n\t};\n});\n\njQuery.extend({\n\tfilter: function( expr, elems, not ) {\n\t\tif ( not ) {\n\t\t\texpr = \":not(\" + expr + \")\";\n\t\t}\n\n\t\treturn elems.length === 1 ?\n\t\t\tjQuery.find.matchesSelector(elems[0], expr) ? [ elems[0] ] : [] :\n\t\t\tjQuery.find.matches(expr, elems);\n\t},\n\n\tdir: function( elem, dir, until ) {\n\t\tvar matched = [],\n\t\t\tcur = elem[ dir ];\n\n\t\twhile ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) {\n\t\t\tif ( cur.nodeType === 1 ) {\n\t\t\t\tmatched.push( cur );\n\t\t\t}\n\t\t\tcur = cur[dir];\n\t\t}\n\t\treturn matched;\n\t},\n\n\tsibling: function( n, elem ) {\n\t\tvar r = [];\n\n\t\tfor ( ; n; n = n.nextSibling ) {\n\t\t\tif ( n.nodeType === 1 && n !== elem ) {\n\t\t\t\tr.push( n );\n\t\t\t}\n\t\t}\n\n\t\treturn r;\n\t}\n});\n\n// Implement the identical functionality for filter and not\nfunction winnow( elements, qualifier, keep ) {\n\n\t// Can't pass null or undefined to indexOf in Firefox 4\n\t// Set to 0 to skip string check\n\tqualifier = qualifier || 0;\n\n\tif ( jQuery.isFunction( qualifier ) ) {\n\t\treturn jQuery.grep(elements, function( elem, i ) {\n\t\t\tvar retVal = !!qualifier.call( elem, i, elem );\n\t\t\treturn retVal === keep;\n\t\t});\n\n\t} else if ( qualifier.nodeType ) {\n\t\treturn jQuery.grep(elements, function( elem ) {\n\t\t\treturn ( elem === qualifier ) === keep;\n\t\t});\n\n\t} else if ( typeof qualifier === \"string\" ) {\n\t\tvar filtered = jQuery.grep(elements, function( elem ) {\n\t\t\treturn elem.nodeType === 1;\n\t\t});\n\n\t\tif ( isSimple.test( qualifier ) ) {\n\t\t\treturn jQuery.filter(qualifier, filtered, !keep);\n\t\t} else {\n\t\t\tqualifier = jQuery.filter( qualifier, filtered );\n\t\t}\n\t}\n\n\treturn jQuery.grep(elements, function( elem ) {\n\t\treturn ( jQuery.inArray( elem, qualifier ) >= 0 ) === keep;\n\t});\n}\nfunction createSafeFragment( document ) {\n\tvar list = nodeNames.split( \"|\" ),\n\t\tsafeFrag = document.createDocumentFragment();\n\n\tif ( safeFrag.createElement ) {\n\t\twhile ( list.length ) {\n\t\t\tsafeFrag.createElement(\n\t\t\t\tlist.pop()\n\t\t\t);\n\t\t}\n\t}\n\treturn safeFrag;\n}\n\nvar nodeNames = \"abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|\" +\n\t\t\"header|hgroup|mark|meter|nav|output|progress|section|summary|time|video\",\n\trinlinejQuery = / jQuery\\d+=\"(?:null|\\d+)\"/g,\n\trnoshimcache = new RegExp(\"<(?:\" + nodeNames + \")[\\\\s/>]\", \"i\"),\n\trleadingWhitespace = /^\\s+/,\n\trxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\\w:]+)[^>]*)\\/>/gi,\n\trtagName = /<([\\w:]+)/,\n\trtbody = /<tbody/i,\n\trhtml = /<|&#?\\w+;/,\n\trnoInnerhtml = /<(?:script|style|link)/i,\n\tmanipulation_rcheckableType = /^(?:checkbox|radio)$/i,\n\t// checked=\"checked\" or checked\n\trchecked = /checked\\s*(?:[^=]|=\\s*.checked.)/i,\n\trscriptType = /^$|\\/(?:java|ecma)script/i,\n\trscriptTypeMasked = /^true\\/(.*)/,\n\trcleanScript = /^\\s*<!(?:\\[CDATA\\[|--)|(?:\\]\\]|--)>\\s*$/g,\n\n\t// We have to close these tags to support XHTML (#13200)\n\twrapMap = {\n\t\toption: [ 1, \"<select multiple='multiple'>\", \"</select>\" ],\n\t\tlegend: [ 1, \"<fieldset>\", \"</fieldset>\" ],\n\t\tarea: [ 1, \"<map>\", \"</map>\" ],\n\t\tparam: [ 1, \"<object>\", \"</object>\" ],\n\t\tthead: [ 1, \"<table>\", \"</table>\" ],\n\t\ttr: [ 2, \"<table><tbody>\", \"</tbody></table>\" ],\n\t\tcol: [ 2, \"<table><tbody></tbody><colgroup>\", \"</colgroup></table>\" ],\n\t\ttd: [ 3, \"<table><tbody><tr>\", \"</tr></tbody></table>\" ],\n\n\t\t// IE6-8 can't serialize link, script, style, or any html5 (NoScope) tags,\n\t\t// unless wrapped in a div with non-breaking characters in front of it.\n\t\t_default: jQuery.support.htmlSerialize ? [ 0, \"\", \"\" ] : [ 1, \"X<div>\", \"</div>\"  ]\n\t},\n\tsafeFragment = createSafeFragment( document ),\n\tfragmentDiv = safeFragment.appendChild( document.createElement(\"div\") );\n\nwrapMap.optgroup = wrapMap.option;\nwrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;\nwrapMap.th = wrapMap.td;\n\njQuery.fn.extend({\n\ttext: function( value ) {\n\t\treturn jQuery.access( this, function( value ) {\n\t\t\treturn value === undefined ?\n\t\t\t\tjQuery.text( this ) :\n\t\t\t\tthis.empty().append( ( this[0] && this[0].ownerDocument || document ).createTextNode( value ) );\n\t\t}, null, value, arguments.length );\n\t},\n\n\twrapAll: function( html ) {\n\t\tif ( jQuery.isFunction( html ) ) {\n\t\t\treturn this.each(function(i) {\n\t\t\t\tjQuery(this).wrapAll( html.call(this, i) );\n\t\t\t});\n\t\t}\n\n\t\tif ( this[0] ) {\n\t\t\t// The elements to wrap the target around\n\t\t\tvar wrap = jQuery( html, this[0].ownerDocument ).eq(0).clone(true);\n\n\t\t\tif ( this[0].parentNode ) {\n\t\t\t\twrap.insertBefore( this[0] );\n\t\t\t}\n\n\t\t\twrap.map(function() {\n\t\t\t\tvar elem = this;\n\n\t\t\t\twhile ( elem.firstChild && elem.firstChild.nodeType === 1 ) {\n\t\t\t\t\telem = elem.firstChild;\n\t\t\t\t}\n\n\t\t\t\treturn elem;\n\t\t\t}).append( this );\n\t\t}\n\n\t\treturn this;\n\t},\n\n\twrapInner: function( html ) {\n\t\tif ( jQuery.isFunction( html ) ) {\n\t\t\treturn this.each(function(i) {\n\t\t\t\tjQuery(this).wrapInner( html.call(this, i) );\n\t\t\t});\n\t\t}\n\n\t\treturn this.each(function() {\n\t\t\tvar self = jQuery( this ),\n\t\t\t\tcontents = self.contents();\n\n\t\t\tif ( contents.length ) {\n\t\t\t\tcontents.wrapAll( html );\n\n\t\t\t} else {\n\t\t\t\tself.append( html );\n\t\t\t}\n\t\t});\n\t},\n\n\twrap: function( html ) {\n\t\tvar isFunction = jQuery.isFunction( html );\n\n\t\treturn this.each(function(i) {\n\t\t\tjQuery( this ).wrapAll( isFunction ? html.call(this, i) : html );\n\t\t});\n\t},\n\n\tunwrap: function() {\n\t\treturn this.parent().each(function() {\n\t\t\tif ( !jQuery.nodeName( this, \"body\" ) ) {\n\t\t\t\tjQuery( this ).replaceWith( this.childNodes );\n\t\t\t}\n\t\t}).end();\n\t},\n\n\tappend: function() {\n\t\treturn this.domManip(arguments, true, function( elem ) {\n\t\t\tif ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {\n\t\t\t\tthis.appendChild( elem );\n\t\t\t}\n\t\t});\n\t},\n\n\tprepend: function() {\n\t\treturn this.domManip(arguments, true, function( elem ) {\n\t\t\tif ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {\n\t\t\t\tthis.insertBefore( elem, this.firstChild );\n\t\t\t}\n\t\t});\n\t},\n\n\tbefore: function() {\n\t\treturn this.domManip( arguments, false, function( elem ) {\n\t\t\tif ( this.parentNode ) {\n\t\t\t\tthis.parentNode.insertBefore( elem, this );\n\t\t\t}\n\t\t});\n\t},\n\n\tafter: function() {\n\t\treturn this.domManip( arguments, false, function( elem ) {\n\t\t\tif ( this.parentNode ) {\n\t\t\t\tthis.parentNode.insertBefore( elem, this.nextSibling );\n\t\t\t}\n\t\t});\n\t},\n\n\t// keepData is for internal use only--do not document\n\tremove: function( selector, keepData ) {\n\t\tvar elem,\n\t\t\ti = 0;\n\n\t\tfor ( ; (elem = this[i]) != null; i++ ) {\n\t\t\tif ( !selector || jQuery.filter( selector, [ elem ] ).length > 0 ) {\n\t\t\t\tif ( !keepData && elem.nodeType === 1 ) {\n\t\t\t\t\tjQuery.cleanData( getAll( elem ) );\n\t\t\t\t}\n\n\t\t\t\tif ( elem.parentNode ) {\n\t\t\t\t\tif ( keepData && jQuery.contains( elem.ownerDocument, elem ) ) {\n\t\t\t\t\t\tsetGlobalEval( getAll( elem, \"script\" ) );\n\t\t\t\t\t}\n\t\t\t\t\telem.parentNode.removeChild( elem );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\tempty: function() {\n\t\tvar elem,\n\t\t\ti = 0;\n\n\t\tfor ( ; (elem = this[i]) != null; i++ ) {\n\t\t\t// Remove element nodes and prevent memory leaks\n\t\t\tif ( elem.nodeType === 1 ) {\n\t\t\t\tjQuery.cleanData( getAll( elem, false ) );\n\t\t\t}\n\n\t\t\t// Remove any remaining nodes\n\t\t\twhile ( elem.firstChild ) {\n\t\t\t\telem.removeChild( elem.firstChild );\n\t\t\t}\n\n\t\t\t// If this is a select, ensure that it displays empty (#12336)\n\t\t\t// Support: IE<9\n\t\t\tif ( elem.options && jQuery.nodeName( elem, \"select\" ) ) {\n\t\t\t\telem.options.length = 0;\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\tclone: function( dataAndEvents, deepDataAndEvents ) {\n\t\tdataAndEvents = dataAndEvents == null ? false : dataAndEvents;\n\t\tdeepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents;\n\n\t\treturn this.map( function () {\n\t\t\treturn jQuery.clone( this, dataAndEvents, deepDataAndEvents );\n\t\t});\n\t},\n\n\thtml: function( value ) {\n\t\treturn jQuery.access( this, function( value ) {\n\t\t\tvar elem = this[0] || {},\n\t\t\t\ti = 0,\n\t\t\t\tl = this.length;\n\n\t\t\tif ( value === undefined ) {\n\t\t\t\treturn elem.nodeType === 1 ?\n\t\t\t\t\telem.innerHTML.replace( rinlinejQuery, \"\" ) :\n\t\t\t\t\tundefined;\n\t\t\t}\n\n\t\t\t// See if we can take a shortcut and just use innerHTML\n\t\t\tif ( typeof value === \"string\" && !rnoInnerhtml.test( value ) &&\n\t\t\t\t( jQuery.support.htmlSerialize || !rnoshimcache.test( value )  ) &&\n\t\t\t\t( jQuery.support.leadingWhitespace || !rleadingWhitespace.test( value ) ) &&\n\t\t\t\t!wrapMap[ ( rtagName.exec( value ) || [\"\", \"\"] )[1].toLowerCase() ] ) {\n\n\t\t\t\tvalue = value.replace( rxhtmlTag, \"<$1></$2>\" );\n\n\t\t\t\ttry {\n\t\t\t\t\tfor (; i < l; i++ ) {\n\t\t\t\t\t\t// Remove element nodes and prevent memory leaks\n\t\t\t\t\t\telem = this[i] || {};\n\t\t\t\t\t\tif ( elem.nodeType === 1 ) {\n\t\t\t\t\t\t\tjQuery.cleanData( getAll( elem, false ) );\n\t\t\t\t\t\t\telem.innerHTML = value;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\telem = 0;\n\n\t\t\t\t// If using innerHTML throws an exception, use the fallback method\n\t\t\t\t} catch(e) {}\n\t\t\t}\n\n\t\t\tif ( elem ) {\n\t\t\t\tthis.empty().append( value );\n\t\t\t}\n\t\t}, null, value, arguments.length );\n\t},\n\n\treplaceWith: function( value ) {\n\t\tvar isFunc = jQuery.isFunction( value );\n\n\t\t// Make sure that the elements are removed from the DOM before they are inserted\n\t\t// this can help fix replacing a parent with child elements\n\t\tif ( !isFunc && typeof value !== \"string\" ) {\n\t\t\tvalue = jQuery( value ).not( this ).detach();\n\t\t}\n\n\t\treturn this.domManip( [ value ], true, function( elem ) {\n\t\t\tvar next = this.nextSibling,\n\t\t\t\tparent = this.parentNode;\n\n\t\t\tif ( parent ) {\n\t\t\t\tjQuery( this ).remove();\n\t\t\t\tparent.insertBefore( elem, next );\n\t\t\t}\n\t\t});\n\t},\n\n\tdetach: function( selector ) {\n\t\treturn this.remove( selector, true );\n\t},\n\n\tdomManip: function( args, table, callback ) {\n\n\t\t// Flatten any nested arrays\n\t\targs = core_concat.apply( [], args );\n\n\t\tvar first, node, hasScripts,\n\t\t\tscripts, doc, fragment,\n\t\t\ti = 0,\n\t\t\tl = this.length,\n\t\t\tset = this,\n\t\t\tiNoClone = l - 1,\n\t\t\tvalue = args[0],\n\t\t\tisFunction = jQuery.isFunction( value );\n\n\t\t// We can't cloneNode fragments that contain checked, in WebKit\n\t\tif ( isFunction || !( l <= 1 || typeof value !== \"string\" || jQuery.support.checkClone || !rchecked.test( value ) ) ) {\n\t\t\treturn this.each(function( index ) {\n\t\t\t\tvar self = set.eq( index );\n\t\t\t\tif ( isFunction ) {\n\t\t\t\t\targs[0] = value.call( this, index, table ? self.html() : undefined );\n\t\t\t\t}\n\t\t\t\tself.domManip( args, table, callback );\n\t\t\t});\n\t\t}\n\n\t\tif ( l ) {\n\t\t\tfragment = jQuery.buildFragment( args, this[ 0 ].ownerDocument, false, this );\n\t\t\tfirst = fragment.firstChild;\n\n\t\t\tif ( fragment.childNodes.length === 1 ) {\n\t\t\t\tfragment = first;\n\t\t\t}\n\n\t\t\tif ( first ) {\n\t\t\t\ttable = table && jQuery.nodeName( first, \"tr\" );\n\t\t\t\tscripts = jQuery.map( getAll( fragment, \"script\" ), disableScript );\n\t\t\t\thasScripts = scripts.length;\n\n\t\t\t\t// Use the original fragment for the last item instead of the first because it can end up\n\t\t\t\t// being emptied incorrectly in certain situations (#8070).\n\t\t\t\tfor ( ; i < l; i++ ) {\n\t\t\t\t\tnode = fragment;\n\n\t\t\t\t\tif ( i !== iNoClone ) {\n\t\t\t\t\t\tnode = jQuery.clone( node, true, true );\n\n\t\t\t\t\t\t// Keep references to cloned scripts for later restoration\n\t\t\t\t\t\tif ( hasScripts ) {\n\t\t\t\t\t\t\tjQuery.merge( scripts, getAll( node, \"script\" ) );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tcallback.call(\n\t\t\t\t\t\ttable && jQuery.nodeName( this[i], \"table\" ) ?\n\t\t\t\t\t\t\tfindOrAppend( this[i], \"tbody\" ) :\n\t\t\t\t\t\t\tthis[i],\n\t\t\t\t\t\tnode,\n\t\t\t\t\t\ti\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\tif ( hasScripts ) {\n\t\t\t\t\tdoc = scripts[ scripts.length - 1 ].ownerDocument;\n\n\t\t\t\t\t// Reenable scripts\n\t\t\t\t\tjQuery.map( scripts, restoreScript );\n\n\t\t\t\t\t// Evaluate executable scripts on first document insertion\n\t\t\t\t\tfor ( i = 0; i < hasScripts; i++ ) {\n\t\t\t\t\t\tnode = scripts[ i ];\n\t\t\t\t\t\tif ( rscriptType.test( node.type || \"\" ) &&\n\t\t\t\t\t\t\t!jQuery._data( node, \"globalEval\" ) && jQuery.contains( doc, node ) ) {\n\n\t\t\t\t\t\t\tif ( node.src ) {\n\t\t\t\t\t\t\t\t// Hope ajax is available...\n\t\t\t\t\t\t\t\tjQuery.ajax({\n\t\t\t\t\t\t\t\t\turl: node.src,\n\t\t\t\t\t\t\t\t\ttype: \"GET\",\n\t\t\t\t\t\t\t\t\tdataType: \"script\",\n\t\t\t\t\t\t\t\t\tasync: false,\n\t\t\t\t\t\t\t\t\tglobal: false,\n\t\t\t\t\t\t\t\t\t\"throws\": true\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tjQuery.globalEval( ( node.text || node.textContent || node.innerHTML || \"\" ).replace( rcleanScript, \"\" ) );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Fix #11809: Avoid leaking memory\n\t\t\t\tfragment = first = null;\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t}\n});\n\nfunction findOrAppend( elem, tag ) {\n\treturn elem.getElementsByTagName( tag )[0] || elem.appendChild( elem.ownerDocument.createElement( tag ) );\n}\n\n// Replace/restore the type attribute of script elements for safe DOM manipulation\nfunction disableScript( elem ) {\n\tvar attr = elem.getAttributeNode(\"type\");\n\telem.type = ( attr && attr.specified ) + \"/\" + elem.type;\n\treturn elem;\n}\nfunction restoreScript( elem ) {\n\tvar match = rscriptTypeMasked.exec( elem.type );\n\tif ( match ) {\n\t\telem.type = match[1];\n\t} else {\n\t\telem.removeAttribute(\"type\");\n\t}\n\treturn elem;\n}\n\n// Mark scripts as having already been evaluated\nfunction setGlobalEval( elems, refElements ) {\n\tvar elem,\n\t\ti = 0;\n\tfor ( ; (elem = elems[i]) != null; i++ ) {\n\t\tjQuery._data( elem, \"globalEval\", !refElements || jQuery._data( refElements[i], \"globalEval\" ) );\n\t}\n}\n\nfunction cloneCopyEvent( src, dest ) {\n\n\tif ( dest.nodeType !== 1 || !jQuery.hasData( src ) ) {\n\t\treturn;\n\t}\n\n\tvar type, i, l,\n\t\toldData = jQuery._data( src ),\n\t\tcurData = jQuery._data( dest, oldData ),\n\t\tevents = oldData.events;\n\n\tif ( events ) {\n\t\tdelete curData.handle;\n\t\tcurData.events = {};\n\n\t\tfor ( type in events ) {\n\t\t\tfor ( i = 0, l = events[ type ].length; i < l; i++ ) {\n\t\t\t\tjQuery.event.add( dest, type, events[ type ][ i ] );\n\t\t\t}\n\t\t}\n\t}\n\n\t// make the cloned public data object a copy from the original\n\tif ( curData.data ) {\n\t\tcurData.data = jQuery.extend( {}, curData.data );\n\t}\n}\n\nfunction fixCloneNodeIssues( src, dest ) {\n\tvar nodeName, e, data;\n\n\t// We do not need to do anything for non-Elements\n\tif ( dest.nodeType !== 1 ) {\n\t\treturn;\n\t}\n\n\tnodeName = dest.nodeName.toLowerCase();\n\n\t// IE6-8 copies events bound via attachEvent when using cloneNode.\n\tif ( !jQuery.support.noCloneEvent && dest[ jQuery.expando ] ) {\n\t\tdata = jQuery._data( dest );\n\n\t\tfor ( e in data.events ) {\n\t\t\tjQuery.removeEvent( dest, e, data.handle );\n\t\t}\n\n\t\t// Event data gets referenced instead of copied if the expando gets copied too\n\t\tdest.removeAttribute( jQuery.expando );\n\t}\n\n\t// IE blanks contents when cloning scripts, and tries to evaluate newly-set text\n\tif ( nodeName === \"script\" && dest.text !== src.text ) {\n\t\tdisableScript( dest ).text = src.text;\n\t\trestoreScript( dest );\n\n\t// IE6-10 improperly clones children of object elements using classid.\n\t// IE10 throws NoModificationAllowedError if parent is null, #12132.\n\t} else if ( nodeName === \"object\" ) {\n\t\tif ( dest.parentNode ) {\n\t\t\tdest.outerHTML = src.outerHTML;\n\t\t}\n\n\t\t// This path appears unavoidable for IE9. When cloning an object\n\t\t// element in IE9, the outerHTML strategy above is not sufficient.\n\t\t// If the src has innerHTML and the destination does not,\n\t\t// copy the src.innerHTML into the dest.innerHTML. #10324\n\t\tif ( jQuery.support.html5Clone && ( src.innerHTML && !jQuery.trim(dest.innerHTML) ) ) {\n\t\t\tdest.innerHTML = src.innerHTML;\n\t\t}\n\n\t} else if ( nodeName === \"input\" && manipulation_rcheckableType.test( src.type ) ) {\n\t\t// IE6-8 fails to persist the checked state of a cloned checkbox\n\t\t// or radio button. Worse, IE6-7 fail to give the cloned element\n\t\t// a checked appearance if the defaultChecked value isn't also set\n\n\t\tdest.defaultChecked = dest.checked = src.checked;\n\n\t\t// IE6-7 get confused and end up setting the value of a cloned\n\t\t// checkbox/radio button to an empty string instead of \"on\"\n\t\tif ( dest.value !== src.value ) {\n\t\t\tdest.value = src.value;\n\t\t}\n\n\t// IE6-8 fails to return the selected option to the default selected\n\t// state when cloning options\n\t} else if ( nodeName === \"option\" ) {\n\t\tdest.defaultSelected = dest.selected = src.defaultSelected;\n\n\t// IE6-8 fails to set the defaultValue to the correct value when\n\t// cloning other types of input fields\n\t} else if ( nodeName === \"input\" || nodeName === \"textarea\" ) {\n\t\tdest.defaultValue = src.defaultValue;\n\t}\n}\n\njQuery.each({\n\tappendTo: \"append\",\n\tprependTo: \"prepend\",\n\tinsertBefore: \"before\",\n\tinsertAfter: \"after\",\n\treplaceAll: \"replaceWith\"\n}, function( name, original ) {\n\tjQuery.fn[ name ] = function( selector ) {\n\t\tvar elems,\n\t\t\ti = 0,\n\t\t\tret = [],\n\t\t\tinsert = jQuery( selector ),\n\t\t\tlast = insert.length - 1;\n\n\t\tfor ( ; i <= last; i++ ) {\n\t\t\telems = i === last ? this : this.clone(true);\n\t\t\tjQuery( insert[i] )[ original ]( elems );\n\n\t\t\t// Modern browsers can apply jQuery collections as arrays, but oldIE needs a .get()\n\t\t\tcore_push.apply( ret, elems.get() );\n\t\t}\n\n\t\treturn this.pushStack( ret );\n\t};\n});\n\nfunction getAll( context, tag ) {\n\tvar elems, elem,\n\t\ti = 0,\n\t\tfound = typeof context.getElementsByTagName !== core_strundefined ? context.getElementsByTagName( tag || \"*\" ) :\n\t\t\ttypeof context.querySelectorAll !== core_strundefined ? context.querySelectorAll( tag || \"*\" ) :\n\t\t\tundefined;\n\n\tif ( !found ) {\n\t\tfor ( found = [], elems = context.childNodes || context; (elem = elems[i]) != null; i++ ) {\n\t\t\tif ( !tag || jQuery.nodeName( elem, tag ) ) {\n\t\t\t\tfound.push( elem );\n\t\t\t} else {\n\t\t\t\tjQuery.merge( found, getAll( elem, tag ) );\n\t\t\t}\n\t\t}\n\t}\n\n\treturn tag === undefined || tag && jQuery.nodeName( context, tag ) ?\n\t\tjQuery.merge( [ context ], found ) :\n\t\tfound;\n}\n\n// Used in buildFragment, fixes the defaultChecked property\nfunction fixDefaultChecked( elem ) {\n\tif ( manipulation_rcheckableType.test( elem.type ) ) {\n\t\telem.defaultChecked = elem.checked;\n\t}\n}\n\njQuery.extend({\n\tclone: function( elem, dataAndEvents, deepDataAndEvents ) {\n\t\tvar destElements, node, clone, i, srcElements,\n\t\t\tinPage = jQuery.contains( elem.ownerDocument, elem );\n\n\t\tif ( jQuery.support.html5Clone || jQuery.isXMLDoc(elem) || !rnoshimcache.test( \"<\" + elem.nodeName + \">\" ) ) {\n\t\t\tclone = elem.cloneNode( true );\n\n\t\t// IE<=8 does not properly clone detached, unknown element nodes\n\t\t} else {\n\t\t\tfragmentDiv.innerHTML = elem.outerHTML;\n\t\t\tfragmentDiv.removeChild( clone = fragmentDiv.firstChild );\n\t\t}\n\n\t\tif ( (!jQuery.support.noCloneEvent || !jQuery.support.noCloneChecked) &&\n\t\t\t\t(elem.nodeType === 1 || elem.nodeType === 11) && !jQuery.isXMLDoc(elem) ) {\n\n\t\t\t// We eschew Sizzle here for performance reasons: http://jsperf.com/getall-vs-sizzle/2\n\t\t\tdestElements = getAll( clone );\n\t\t\tsrcElements = getAll( elem );\n\n\t\t\t// Fix all IE cloning issues\n\t\t\tfor ( i = 0; (node = srcElements[i]) != null; ++i ) {\n\t\t\t\t// Ensure that the destination node is not null; Fixes #9587\n\t\t\t\tif ( destElements[i] ) {\n\t\t\t\t\tfixCloneNodeIssues( node, destElements[i] );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Copy the events from the original to the clone\n\t\tif ( dataAndEvents ) {\n\t\t\tif ( deepDataAndEvents ) {\n\t\t\t\tsrcElements = srcElements || getAll( elem );\n\t\t\t\tdestElements = destElements || getAll( clone );\n\n\t\t\t\tfor ( i = 0; (node = srcElements[i]) != null; i++ ) {\n\t\t\t\t\tcloneCopyEvent( node, destElements[i] );\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tcloneCopyEvent( elem, clone );\n\t\t\t}\n\t\t}\n\n\t\t// Preserve script evaluation history\n\t\tdestElements = getAll( clone, \"script\" );\n\t\tif ( destElements.length > 0 ) {\n\t\t\tsetGlobalEval( destElements, !inPage && getAll( elem, \"script\" ) );\n\t\t}\n\n\t\tdestElements = srcElements = node = null;\n\n\t\t// Return the cloned set\n\t\treturn clone;\n\t},\n\n\tbuildFragment: function( elems, context, scripts, selection ) {\n\t\tvar j, elem, contains,\n\t\t\ttmp, tag, tbody, wrap,\n\t\t\tl = elems.length,\n\n\t\t\t// Ensure a safe fragment\n\t\t\tsafe = createSafeFragment( context ),\n\n\t\t\tnodes = [],\n\t\t\ti = 0;\n\n\t\tfor ( ; i < l; i++ ) {\n\t\t\telem = elems[ i ];\n\n\t\t\tif ( elem || elem === 0 ) {\n\n\t\t\t\t// Add nodes directly\n\t\t\t\tif ( jQuery.type( elem ) === \"object\" ) {\n\t\t\t\t\tjQuery.merge( nodes, elem.nodeType ? [ elem ] : elem );\n\n\t\t\t\t// Convert non-html into a text node\n\t\t\t\t} else if ( !rhtml.test( elem ) ) {\n\t\t\t\t\tnodes.push( context.createTextNode( elem ) );\n\n\t\t\t\t// Convert html into DOM nodes\n\t\t\t\t} else {\n\t\t\t\t\ttmp = tmp || safe.appendChild( context.createElement(\"div\") );\n\n\t\t\t\t\t// Deserialize a standard representation\n\t\t\t\t\ttag = ( rtagName.exec( elem ) || [\"\", \"\"] )[1].toLowerCase();\n\t\t\t\t\twrap = wrapMap[ tag ] || wrapMap._default;\n\n\t\t\t\t\ttmp.innerHTML = wrap[1] + elem.replace( rxhtmlTag, \"<$1></$2>\" ) + wrap[2];\n\n\t\t\t\t\t// Descend through wrappers to the right content\n\t\t\t\t\tj = wrap[0];\n\t\t\t\t\twhile ( j-- ) {\n\t\t\t\t\t\ttmp = tmp.lastChild;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Manually add leading whitespace removed by IE\n\t\t\t\t\tif ( !jQuery.support.leadingWhitespace && rleadingWhitespace.test( elem ) ) {\n\t\t\t\t\t\tnodes.push( context.createTextNode( rleadingWhitespace.exec( elem )[0] ) );\n\t\t\t\t\t}\n\n\t\t\t\t\t// Remove IE's autoinserted <tbody> from table fragments\n\t\t\t\t\tif ( !jQuery.support.tbody ) {\n\n\t\t\t\t\t\t// String was a <table>, *may* have spurious <tbody>\n\t\t\t\t\t\telem = tag === \"table\" && !rtbody.test( elem ) ?\n\t\t\t\t\t\t\ttmp.firstChild :\n\n\t\t\t\t\t\t\t// String was a bare <thead> or <tfoot>\n\t\t\t\t\t\t\twrap[1] === \"<table>\" && !rtbody.test( elem ) ?\n\t\t\t\t\t\t\t\ttmp :\n\t\t\t\t\t\t\t\t0;\n\n\t\t\t\t\t\tj = elem && elem.childNodes.length;\n\t\t\t\t\t\twhile ( j-- ) {\n\t\t\t\t\t\t\tif ( jQuery.nodeName( (tbody = elem.childNodes[j]), \"tbody\" ) && !tbody.childNodes.length ) {\n\t\t\t\t\t\t\t\telem.removeChild( tbody );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tjQuery.merge( nodes, tmp.childNodes );\n\n\t\t\t\t\t// Fix #12392 for WebKit and IE > 9\n\t\t\t\t\ttmp.textContent = \"\";\n\n\t\t\t\t\t// Fix #12392 for oldIE\n\t\t\t\t\twhile ( tmp.firstChild ) {\n\t\t\t\t\t\ttmp.removeChild( tmp.firstChild );\n\t\t\t\t\t}\n\n\t\t\t\t\t// Remember the top-level container for proper cleanup\n\t\t\t\t\ttmp = safe.lastChild;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Fix #11356: Clear elements from fragment\n\t\tif ( tmp ) {\n\t\t\tsafe.removeChild( tmp );\n\t\t}\n\n\t\t// Reset defaultChecked for any radios and checkboxes\n\t\t// about to be appended to the DOM in IE 6/7 (#8060)\n\t\tif ( !jQuery.support.appendChecked ) {\n\t\t\tjQuery.grep( getAll( nodes, \"input\" ), fixDefaultChecked );\n\t\t}\n\n\t\ti = 0;\n\t\twhile ( (elem = nodes[ i++ ]) ) {\n\n\t\t\t// #4087 - If origin and destination elements are the same, and this is\n\t\t\t// that element, do not do anything\n\t\t\tif ( selection && jQuery.inArray( elem, selection ) !== -1 ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tcontains = jQuery.contains( elem.ownerDocument, elem );\n\n\t\t\t// Append to fragment\n\t\t\ttmp = getAll( safe.appendChild( elem ), \"script\" );\n\n\t\t\t// Preserve script evaluation history\n\t\t\tif ( contains ) {\n\t\t\t\tsetGlobalEval( tmp );\n\t\t\t}\n\n\t\t\t// Capture executables\n\t\t\tif ( scripts ) {\n\t\t\t\tj = 0;\n\t\t\t\twhile ( (elem = tmp[ j++ ]) ) {\n\t\t\t\t\tif ( rscriptType.test( elem.type || \"\" ) ) {\n\t\t\t\t\t\tscripts.push( elem );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\ttmp = null;\n\n\t\treturn safe;\n\t},\n\n\tcleanData: function( elems, /* internal */ acceptData ) {\n\t\tvar elem, type, id, data,\n\t\t\ti = 0,\n\t\t\tinternalKey = jQuery.expando,\n\t\t\tcache = jQuery.cache,\n\t\t\tdeleteExpando = jQuery.support.deleteExpando,\n\t\t\tspecial = jQuery.event.special;\n\n\t\tfor ( ; (elem = elems[i]) != null; i++ ) {\n\n\t\t\tif ( acceptData || jQuery.acceptData( elem ) ) {\n\n\t\t\t\tid = elem[ internalKey ];\n\t\t\t\tdata = id && cache[ id ];\n\n\t\t\t\tif ( data ) {\n\t\t\t\t\tif ( data.events ) {\n\t\t\t\t\t\tfor ( type in data.events ) {\n\t\t\t\t\t\t\tif ( special[ type ] ) {\n\t\t\t\t\t\t\t\tjQuery.event.remove( elem, type );\n\n\t\t\t\t\t\t\t// This is a shortcut to avoid jQuery.event.remove's overhead\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tjQuery.removeEvent( elem, type, data.handle );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Remove cache only if it was not already removed by jQuery.event.remove\n\t\t\t\t\tif ( cache[ id ] ) {\n\n\t\t\t\t\t\tdelete cache[ id ];\n\n\t\t\t\t\t\t// IE does not allow us to delete expando properties from nodes,\n\t\t\t\t\t\t// nor does it have a removeAttribute function on Document nodes;\n\t\t\t\t\t\t// we must handle all of these cases\n\t\t\t\t\t\tif ( deleteExpando ) {\n\t\t\t\t\t\t\tdelete elem[ internalKey ];\n\n\t\t\t\t\t\t} else if ( typeof elem.removeAttribute !== core_strundefined ) {\n\t\t\t\t\t\t\telem.removeAttribute( internalKey );\n\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\telem[ internalKey ] = null;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tcore_deletedIds.push( id );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n});\nvar iframe, getStyles, curCSS,\n\tralpha = /alpha\\([^)]*\\)/i,\n\tropacity = /opacity\\s*=\\s*([^)]*)/,\n\trposition = /^(top|right|bottom|left)$/,\n\t// swappable if display is none or starts with table except \"table\", \"table-cell\", or \"table-caption\"\n\t// see here for display values: https://developer.mozilla.org/en-US/docs/CSS/display\n\trdisplayswap = /^(none|table(?!-c[ea]).+)/,\n\trmargin = /^margin/,\n\trnumsplit = new RegExp( \"^(\" + core_pnum + \")(.*)$\", \"i\" ),\n\trnumnonpx = new RegExp( \"^(\" + core_pnum + \")(?!px)[a-z%]+$\", \"i\" ),\n\trrelNum = new RegExp( \"^([+-])=(\" + core_pnum + \")\", \"i\" ),\n\telemdisplay = { BODY: \"block\" },\n\n\tcssShow = { position: \"absolute\", visibility: \"hidden\", display: \"block\" },\n\tcssNormalTransform = {\n\t\tletterSpacing: 0,\n\t\tfontWeight: 400\n\t},\n\n\tcssExpand = [ \"Top\", \"Right\", \"Bottom\", \"Left\" ],\n\tcssPrefixes = [ \"Webkit\", \"O\", \"Moz\", \"ms\" ];\n\n// return a css property mapped to a potentially vendor prefixed property\nfunction vendorPropName( style, name ) {\n\n\t// shortcut for names that are not vendor prefixed\n\tif ( name in style ) {\n\t\treturn name;\n\t}\n\n\t// check for vendor prefixed names\n\tvar capName = name.charAt(0).toUpperCase() + name.slice(1),\n\t\torigName = name,\n\t\ti = cssPrefixes.length;\n\n\twhile ( i-- ) {\n\t\tname = cssPrefixes[ i ] + capName;\n\t\tif ( name in style ) {\n\t\t\treturn name;\n\t\t}\n\t}\n\n\treturn origName;\n}\n\nfunction isHidden( elem, el ) {\n\t// isHidden might be called from jQuery#filter function;\n\t// in that case, element will be second argument\n\telem = el || elem;\n\treturn jQuery.css( elem, \"display\" ) === \"none\" || !jQuery.contains( elem.ownerDocument, elem );\n}\n\nfunction showHide( elements, show ) {\n\tvar display, elem, hidden,\n\t\tvalues = [],\n\t\tindex = 0,\n\t\tlength = elements.length;\n\n\tfor ( ; index < length; index++ ) {\n\t\telem = elements[ index ];\n\t\tif ( !elem.style ) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tvalues[ index ] = jQuery._data( elem, \"olddisplay\" );\n\t\tdisplay = elem.style.display;\n\t\tif ( show ) {\n\t\t\t// Reset the inline display of this element to learn if it is\n\t\t\t// being hidden by cascaded rules or not\n\t\t\tif ( !values[ index ] && display === \"none\" ) {\n\t\t\t\telem.style.display = \"\";\n\t\t\t}\n\n\t\t\t// Set elements which have been overridden with display: none\n\t\t\t// in a stylesheet to whatever the default browser style is\n\t\t\t// for such an element\n\t\t\tif ( elem.style.display === \"\" && isHidden( elem ) ) {\n\t\t\t\tvalues[ index ] = jQuery._data( elem, \"olddisplay\", css_defaultDisplay(elem.nodeName) );\n\t\t\t}\n\t\t} else {\n\n\t\t\tif ( !values[ index ] ) {\n\t\t\t\thidden = isHidden( elem );\n\n\t\t\t\tif ( display && display !== \"none\" || !hidden ) {\n\t\t\t\t\tjQuery._data( elem, \"olddisplay\", hidden ? display : jQuery.css( elem, \"display\" ) );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Set the display of most of the elements in a second loop\n\t// to avoid the constant reflow\n\tfor ( index = 0; index < length; index++ ) {\n\t\telem = elements[ index ];\n\t\tif ( !elem.style ) {\n\t\t\tcontinue;\n\t\t}\n\t\tif ( !show || elem.style.display === \"none\" || elem.style.display === \"\" ) {\n\t\t\telem.style.display = show ? values[ index ] || \"\" : \"none\";\n\t\t}\n\t}\n\n\treturn elements;\n}\n\njQuery.fn.extend({\n\tcss: function( name, value ) {\n\t\treturn jQuery.access( this, function( elem, name, value ) {\n\t\t\tvar len, styles,\n\t\t\t\tmap = {},\n\t\t\t\ti = 0;\n\n\t\t\tif ( jQuery.isArray( name ) ) {\n\t\t\t\tstyles = getStyles( elem );\n\t\t\t\tlen = name.length;\n\n\t\t\t\tfor ( ; i < len; i++ ) {\n\t\t\t\t\tmap[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles );\n\t\t\t\t}\n\n\t\t\t\treturn map;\n\t\t\t}\n\n\t\t\treturn value !== undefined ?\n\t\t\t\tjQuery.style( elem, name, value ) :\n\t\t\t\tjQuery.css( elem, name );\n\t\t}, name, value, arguments.length > 1 );\n\t},\n\tshow: function() {\n\t\treturn showHide( this, true );\n\t},\n\thide: function() {\n\t\treturn showHide( this );\n\t},\n\ttoggle: function( state ) {\n\t\tvar bool = typeof state === \"boolean\";\n\n\t\treturn this.each(function() {\n\t\t\tif ( bool ? state : isHidden( this ) ) {\n\t\t\t\tjQuery( this ).show();\n\t\t\t} else {\n\t\t\t\tjQuery( this ).hide();\n\t\t\t}\n\t\t});\n\t}\n});\n\njQuery.extend({\n\t// Add in style property hooks for overriding the default\n\t// behavior of getting and setting a style property\n\tcssHooks: {\n\t\topacity: {\n\t\t\tget: function( elem, computed ) {\n\t\t\t\tif ( computed ) {\n\t\t\t\t\t// We should always get a number back from opacity\n\t\t\t\t\tvar ret = curCSS( elem, \"opacity\" );\n\t\t\t\t\treturn ret === \"\" ? \"1\" : ret;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\n\t// Exclude the following css properties to add px\n\tcssNumber: {\n\t\t\"columnCount\": true,\n\t\t\"fillOpacity\": true,\n\t\t\"fontWeight\": true,\n\t\t\"lineHeight\": true,\n\t\t\"opacity\": true,\n\t\t\"orphans\": true,\n\t\t\"widows\": true,\n\t\t\"zIndex\": true,\n\t\t\"zoom\": true\n\t},\n\n\t// Add in properties whose names you wish to fix before\n\t// setting or getting the value\n\tcssProps: {\n\t\t// normalize float css property\n\t\t\"float\": jQuery.support.cssFloat ? \"cssFloat\" : \"styleFloat\"\n\t},\n\n\t// Get and set the style property on a DOM Node\n\tstyle: function( elem, name, value, extra ) {\n\t\t// Don't set styles on text and comment nodes\n\t\tif ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Make sure that we're working with the right name\n\t\tvar ret, type, hooks,\n\t\t\torigName = jQuery.camelCase( name ),\n\t\t\tstyle = elem.style;\n\n\t\tname = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( style, origName ) );\n\n\t\t// gets hook for the prefixed version\n\t\t// followed by the unprefixed version\n\t\thooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];\n\n\t\t// Check if we're setting a value\n\t\tif ( value !== undefined ) {\n\t\t\ttype = typeof value;\n\n\t\t\t// convert relative number strings (+= or -=) to relative numbers. #7345\n\t\t\tif ( type === \"string\" && (ret = rrelNum.exec( value )) ) {\n\t\t\t\tvalue = ( ret[1] + 1 ) * ret[2] + parseFloat( jQuery.css( elem, name ) );\n\t\t\t\t// Fixes bug #9237\n\t\t\t\ttype = \"number\";\n\t\t\t}\n\n\t\t\t// Make sure that NaN and null values aren't set. See: #7116\n\t\t\tif ( value == null || type === \"number\" && isNaN( value ) ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// If a number was passed in, add 'px' to the (except for certain CSS properties)\n\t\t\tif ( type === \"number\" && !jQuery.cssNumber[ origName ] ) {\n\t\t\t\tvalue += \"px\";\n\t\t\t}\n\n\t\t\t// Fixes #8908, it can be done more correctly by specifing setters in cssHooks,\n\t\t\t// but it would mean to define eight (for every problematic property) identical functions\n\t\t\tif ( !jQuery.support.clearCloneStyle && value === \"\" && name.indexOf(\"background\") === 0 ) {\n\t\t\t\tstyle[ name ] = \"inherit\";\n\t\t\t}\n\n\t\t\t// If a hook was provided, use that value, otherwise just set the specified value\n\t\t\tif ( !hooks || !(\"set\" in hooks) || (value = hooks.set( elem, value, extra )) !== undefined ) {\n\n\t\t\t\t// Wrapped to prevent IE from throwing errors when 'invalid' values are provided\n\t\t\t\t// Fixes bug #5509\n\t\t\t\ttry {\n\t\t\t\t\tstyle[ name ] = value;\n\t\t\t\t} catch(e) {}\n\t\t\t}\n\n\t\t} else {\n\t\t\t// If a hook was provided get the non-computed value from there\n\t\t\tif ( hooks && \"get\" in hooks && (ret = hooks.get( elem, false, extra )) !== undefined ) {\n\t\t\t\treturn ret;\n\t\t\t}\n\n\t\t\t// Otherwise just get the value from the style object\n\t\t\treturn style[ name ];\n\t\t}\n\t},\n\n\tcss: function( elem, name, extra, styles ) {\n\t\tvar num, val, hooks,\n\t\t\torigName = jQuery.camelCase( name );\n\n\t\t// Make sure that we're working with the right name\n\t\tname = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( elem.style, origName ) );\n\n\t\t// gets hook for the prefixed version\n\t\t// followed by the unprefixed version\n\t\thooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];\n\n\t\t// If a hook was provided get the computed value from there\n\t\tif ( hooks && \"get\" in hooks ) {\n\t\t\tval = hooks.get( elem, true, extra );\n\t\t}\n\n\t\t// Otherwise, if a way to get the computed value exists, use that\n\t\tif ( val === undefined ) {\n\t\t\tval = curCSS( elem, name, styles );\n\t\t}\n\n\t\t//convert \"normal\" to computed value\n\t\tif ( val === \"normal\" && name in cssNormalTransform ) {\n\t\t\tval = cssNormalTransform[ name ];\n\t\t}\n\n\t\t// Return, converting to number if forced or a qualifier was provided and val looks numeric\n\t\tif ( extra === \"\" || extra ) {\n\t\t\tnum = parseFloat( val );\n\t\t\treturn extra === true || jQuery.isNumeric( num ) ? num || 0 : val;\n\t\t}\n\t\treturn val;\n\t},\n\n\t// A method for quickly swapping in/out CSS properties to get correct calculations\n\tswap: function( elem, options, callback, args ) {\n\t\tvar ret, name,\n\t\t\told = {};\n\n\t\t// Remember the old values, and insert the new ones\n\t\tfor ( name in options ) {\n\t\t\told[ name ] = elem.style[ name ];\n\t\t\telem.style[ name ] = options[ name ];\n\t\t}\n\n\t\tret = callback.apply( elem, args || [] );\n\n\t\t// Revert the old values\n\t\tfor ( name in options ) {\n\t\t\telem.style[ name ] = old[ name ];\n\t\t}\n\n\t\treturn ret;\n\t}\n});\n\n// NOTE: we've included the \"window\" in window.getComputedStyle\n// because jsdom on node.js will break without it.\nif ( window.getComputedStyle ) {\n\tgetStyles = function( elem ) {\n\t\treturn window.getComputedStyle( elem, null );\n\t};\n\n\tcurCSS = function( elem, name, _computed ) {\n\t\tvar width, minWidth, maxWidth,\n\t\t\tcomputed = _computed || getStyles( elem ),\n\n\t\t\t// getPropertyValue is only needed for .css('filter') in IE9, see #12537\n\t\t\tret = computed ? computed.getPropertyValue( name ) || computed[ name ] : undefined,\n\t\t\tstyle = elem.style;\n\n\t\tif ( computed ) {\n\n\t\t\tif ( ret === \"\" && !jQuery.contains( elem.ownerDocument, elem ) ) {\n\t\t\t\tret = jQuery.style( elem, name );\n\t\t\t}\n\n\t\t\t// A tribute to the \"awesome hack by Dean Edwards\"\n\t\t\t// Chrome < 17 and Safari 5.0 uses \"computed value\" instead of \"used value\" for margin-right\n\t\t\t// Safari 5.1.7 (at least) returns percentage for a larger set of values, but width seems to be reliably pixels\n\t\t\t// this is against the CSSOM draft spec: http://dev.w3.org/csswg/cssom/#resolved-values\n\t\t\tif ( rnumnonpx.test( ret ) && rmargin.test( name ) ) {\n\n\t\t\t\t// Remember the original values\n\t\t\t\twidth = style.width;\n\t\t\t\tminWidth = style.minWidth;\n\t\t\t\tmaxWidth = style.maxWidth;\n\n\t\t\t\t// Put in the new values to get a computed value out\n\t\t\t\tstyle.minWidth = style.maxWidth = style.width = ret;\n\t\t\t\tret = computed.width;\n\n\t\t\t\t// Revert the changed values\n\t\t\t\tstyle.width = width;\n\t\t\t\tstyle.minWidth = minWidth;\n\t\t\t\tstyle.maxWidth = maxWidth;\n\t\t\t}\n\t\t}\n\n\t\treturn ret;\n\t};\n} else if ( document.documentElement.currentStyle ) {\n\tgetStyles = function( elem ) {\n\t\treturn elem.currentStyle;\n\t};\n\n\tcurCSS = function( elem, name, _computed ) {\n\t\tvar left, rs, rsLeft,\n\t\t\tcomputed = _computed || getStyles( elem ),\n\t\t\tret = computed ? computed[ name ] : undefined,\n\t\t\tstyle = elem.style;\n\n\t\t// Avoid setting ret to empty string here\n\t\t// so we don't default to auto\n\t\tif ( ret == null && style && style[ name ] ) {\n\t\t\tret = style[ name ];\n\t\t}\n\n\t\t// From the awesome hack by Dean Edwards\n\t\t// http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291\n\n\t\t// If we're not dealing with a regular pixel number\n\t\t// but a number that has a weird ending, we need to convert it to pixels\n\t\t// but not position css attributes, as those are proportional to the parent element instead\n\t\t// and we can't measure the parent instead because it might trigger a \"stacking dolls\" problem\n\t\tif ( rnumnonpx.test( ret ) && !rposition.test( name ) ) {\n\n\t\t\t// Remember the original values\n\t\t\tleft = style.left;\n\t\t\trs = elem.runtimeStyle;\n\t\t\trsLeft = rs && rs.left;\n\n\t\t\t// Put in the new values to get a computed value out\n\t\t\tif ( rsLeft ) {\n\t\t\t\trs.left = elem.currentStyle.left;\n\t\t\t}\n\t\t\tstyle.left = name === \"fontSize\" ? \"1em\" : ret;\n\t\t\tret = style.pixelLeft + \"px\";\n\n\t\t\t// Revert the changed values\n\t\t\tstyle.left = left;\n\t\t\tif ( rsLeft ) {\n\t\t\t\trs.left = rsLeft;\n\t\t\t}\n\t\t}\n\n\t\treturn ret === \"\" ? \"auto\" : ret;\n\t};\n}\n\nfunction setPositiveNumber( elem, value, subtract ) {\n\tvar matches = rnumsplit.exec( value );\n\treturn matches ?\n\t\t// Guard against undefined \"subtract\", e.g., when used as in cssHooks\n\t\tMath.max( 0, matches[ 1 ] - ( subtract || 0 ) ) + ( matches[ 2 ] || \"px\" ) :\n\t\tvalue;\n}\n\nfunction augmentWidthOrHeight( elem, name, extra, isBorderBox, styles ) {\n\tvar i = extra === ( isBorderBox ? \"border\" : \"content\" ) ?\n\t\t// If we already have the right measurement, avoid augmentation\n\t\t4 :\n\t\t// Otherwise initialize for horizontal or vertical properties\n\t\tname === \"width\" ? 1 : 0,\n\n\t\tval = 0;\n\n\tfor ( ; i < 4; i += 2 ) {\n\t\t// both box models exclude margin, so add it if we want it\n\t\tif ( extra === \"margin\" ) {\n\t\t\tval += jQuery.css( elem, extra + cssExpand[ i ], true, styles );\n\t\t}\n\n\t\tif ( isBorderBox ) {\n\t\t\t// border-box includes padding, so remove it if we want content\n\t\t\tif ( extra === \"content\" ) {\n\t\t\t\tval -= jQuery.css( elem, \"padding\" + cssExpand[ i ], true, styles );\n\t\t\t}\n\n\t\t\t// at this point, extra isn't border nor margin, so remove border\n\t\t\tif ( extra !== \"margin\" ) {\n\t\t\t\tval -= jQuery.css( elem, \"border\" + cssExpand[ i ] + \"Width\", true, styles );\n\t\t\t}\n\t\t} else {\n\t\t\t// at this point, extra isn't content, so add padding\n\t\t\tval += jQuery.css( elem, \"padding\" + cssExpand[ i ], true, styles );\n\n\t\t\t// at this point, extra isn't content nor padding, so add border\n\t\t\tif ( extra !== \"padding\" ) {\n\t\t\t\tval += jQuery.css( elem, \"border\" + cssExpand[ i ] + \"Width\", true, styles );\n\t\t\t}\n\t\t}\n\t}\n\n\treturn val;\n}\n\nfunction getWidthOrHeight( elem, name, extra ) {\n\n\t// Start with offset property, which is equivalent to the border-box value\n\tvar valueIsBorderBox = true,\n\t\tval = name === \"width\" ? elem.offsetWidth : elem.offsetHeight,\n\t\tstyles = getStyles( elem ),\n\t\tisBorderBox = jQuery.support.boxSizing && jQuery.css( elem, \"boxSizing\", false, styles ) === \"border-box\";\n\n\t// some non-html elements return undefined for offsetWidth, so check for null/undefined\n\t// svg - https://bugzilla.mozilla.org/show_bug.cgi?id=649285\n\t// MathML - https://bugzilla.mozilla.org/show_bug.cgi?id=491668\n\tif ( val <= 0 || val == null ) {\n\t\t// Fall back to computed then uncomputed css if necessary\n\t\tval = curCSS( elem, name, styles );\n\t\tif ( val < 0 || val == null ) {\n\t\t\tval = elem.style[ name ];\n\t\t}\n\n\t\t// Computed unit is not pixels. Stop here and return.\n\t\tif ( rnumnonpx.test(val) ) {\n\t\t\treturn val;\n\t\t}\n\n\t\t// we need the check for style in case a browser which returns unreliable values\n\t\t// for getComputedStyle silently falls back to the reliable elem.style\n\t\tvalueIsBorderBox = isBorderBox && ( jQuery.support.boxSizingReliable || val === elem.style[ name ] );\n\n\t\t// Normalize \"\", auto, and prepare for extra\n\t\tval = parseFloat( val ) || 0;\n\t}\n\n\t// use the active box-sizing model to add/subtract irrelevant styles\n\treturn ( val +\n\t\taugmentWidthOrHeight(\n\t\t\telem,\n\t\t\tname,\n\t\t\textra || ( isBorderBox ? \"border\" : \"content\" ),\n\t\t\tvalueIsBorderBox,\n\t\t\tstyles\n\t\t)\n\t) + \"px\";\n}\n\n// Try to determine the default display value of an element\nfunction css_defaultDisplay( nodeName ) {\n\tvar doc = document,\n\t\tdisplay = elemdisplay[ nodeName ];\n\n\tif ( !display ) {\n\t\tdisplay = actualDisplay( nodeName, doc );\n\n\t\t// If the simple way fails, read from inside an iframe\n\t\tif ( display === \"none\" || !display ) {\n\t\t\t// Use the already-created iframe if possible\n\t\t\tiframe = ( iframe ||\n\t\t\t\tjQuery(\"<iframe frameborder='0' width='0' height='0'/>\")\n\t\t\t\t.css( \"cssText\", \"display:block !important\" )\n\t\t\t).appendTo( doc.documentElement );\n\n\t\t\t// Always write a new HTML skeleton so Webkit and Firefox don't choke on reuse\n\t\t\tdoc = ( iframe[0].contentWindow || iframe[0].contentDocument ).document;\n\t\t\tdoc.write(\"<!doctype html><html><body>\");\n\t\t\tdoc.close();\n\n\t\t\tdisplay = actualDisplay( nodeName, doc );\n\t\t\tiframe.detach();\n\t\t}\n\n\t\t// Store the correct default display\n\t\telemdisplay[ nodeName ] = display;\n\t}\n\n\treturn display;\n}\n\n// Called ONLY from within css_defaultDisplay\nfunction actualDisplay( name, doc ) {\n\tvar elem = jQuery( doc.createElement( name ) ).appendTo( doc.body ),\n\t\tdisplay = jQuery.css( elem[0], \"display\" );\n\telem.remove();\n\treturn display;\n}\n\njQuery.each([ \"height\", \"width\" ], function( i, name ) {\n\tjQuery.cssHooks[ name ] = {\n\t\tget: function( elem, computed, extra ) {\n\t\t\tif ( computed ) {\n\t\t\t\t// certain elements can have dimension info if we invisibly show them\n\t\t\t\t// however, it must have a current display style that would benefit from this\n\t\t\t\treturn elem.offsetWidth === 0 && rdisplayswap.test( jQuery.css( elem, \"display\" ) ) ?\n\t\t\t\t\tjQuery.swap( elem, cssShow, function() {\n\t\t\t\t\t\treturn getWidthOrHeight( elem, name, extra );\n\t\t\t\t\t}) :\n\t\t\t\t\tgetWidthOrHeight( elem, name, extra );\n\t\t\t}\n\t\t},\n\n\t\tset: function( elem, value, extra ) {\n\t\t\tvar styles = extra && getStyles( elem );\n\t\t\treturn setPositiveNumber( elem, value, extra ?\n\t\t\t\taugmentWidthOrHeight(\n\t\t\t\t\telem,\n\t\t\t\t\tname,\n\t\t\t\t\textra,\n\t\t\t\t\tjQuery.support.boxSizing && jQuery.css( elem, \"boxSizing\", false, styles ) === \"border-box\",\n\t\t\t\t\tstyles\n\t\t\t\t) : 0\n\t\t\t);\n\t\t}\n\t};\n});\n\nif ( !jQuery.support.opacity ) {\n\tjQuery.cssHooks.opacity = {\n\t\tget: function( elem, computed ) {\n\t\t\t// IE uses filters for opacity\n\t\t\treturn ropacity.test( (computed && elem.currentStyle ? elem.currentStyle.filter : elem.style.filter) || \"\" ) ?\n\t\t\t\t( 0.01 * parseFloat( RegExp.$1 ) ) + \"\" :\n\t\t\t\tcomputed ? \"1\" : \"\";\n\t\t},\n\n\t\tset: function( elem, value ) {\n\t\t\tvar style = elem.style,\n\t\t\t\tcurrentStyle = elem.currentStyle,\n\t\t\t\topacity = jQuery.isNumeric( value ) ? \"alpha(opacity=\" + value * 100 + \")\" : \"\",\n\t\t\t\tfilter = currentStyle && currentStyle.filter || style.filter || \"\";\n\n\t\t\t// IE has trouble with opacity if it does not have layout\n\t\t\t// Force it by setting the zoom level\n\t\t\tstyle.zoom = 1;\n\n\t\t\t// if setting opacity to 1, and no other filters exist - attempt to remove filter attribute #6652\n\t\t\t// if value === \"\", then remove inline opacity #12685\n\t\t\tif ( ( value >= 1 || value === \"\" ) &&\n\t\t\t\t\tjQuery.trim( filter.replace( ralpha, \"\" ) ) === \"\" &&\n\t\t\t\t\tstyle.removeAttribute ) {\n\n\t\t\t\t// Setting style.filter to null, \"\" & \" \" still leave \"filter:\" in the cssText\n\t\t\t\t// if \"filter:\" is present at all, clearType is disabled, we want to avoid this\n\t\t\t\t// style.removeAttribute is IE Only, but so apparently is this code path...\n\t\t\t\tstyle.removeAttribute( \"filter\" );\n\n\t\t\t\t// if there is no filter style applied in a css rule or unset inline opacity, we are done\n\t\t\t\tif ( value === \"\" || currentStyle && !currentStyle.filter ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// otherwise, set new filter values\n\t\t\tstyle.filter = ralpha.test( filter ) ?\n\t\t\t\tfilter.replace( ralpha, opacity ) :\n\t\t\t\tfilter + \" \" + opacity;\n\t\t}\n\t};\n}\n\n// These hooks cannot be added until DOM ready because the support test\n// for it is not run until after DOM ready\njQuery(function() {\n\tif ( !jQuery.support.reliableMarginRight ) {\n\t\tjQuery.cssHooks.marginRight = {\n\t\t\tget: function( elem, computed ) {\n\t\t\t\tif ( computed ) {\n\t\t\t\t\t// WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right\n\t\t\t\t\t// Work around by temporarily setting element display to inline-block\n\t\t\t\t\treturn jQuery.swap( elem, { \"display\": \"inline-block\" },\n\t\t\t\t\t\tcurCSS, [ elem, \"marginRight\" ] );\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t}\n\n\t// Webkit bug: https://bugs.webkit.org/show_bug.cgi?id=29084\n\t// getComputedStyle returns percent when specified for top/left/bottom/right\n\t// rather than make the css module depend on the offset module, we just check for it here\n\tif ( !jQuery.support.pixelPosition && jQuery.fn.position ) {\n\t\tjQuery.each( [ \"top\", \"left\" ], function( i, prop ) {\n\t\t\tjQuery.cssHooks[ prop ] = {\n\t\t\t\tget: function( elem, computed ) {\n\t\t\t\t\tif ( computed ) {\n\t\t\t\t\t\tcomputed = curCSS( elem, prop );\n\t\t\t\t\t\t// if curCSS returns percentage, fallback to offset\n\t\t\t\t\t\treturn rnumnonpx.test( computed ) ?\n\t\t\t\t\t\t\tjQuery( elem ).position()[ prop ] + \"px\" :\n\t\t\t\t\t\t\tcomputed;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t};\n\t\t});\n\t}\n\n});\n\nif ( jQuery.expr && jQuery.expr.filters ) {\n\tjQuery.expr.filters.hidden = function( elem ) {\n\t\t// Support: Opera <= 12.12\n\t\t// Opera reports offsetWidths and offsetHeights less than zero on some elements\n\t\treturn elem.offsetWidth <= 0 && elem.offsetHeight <= 0 ||\n\t\t\t(!jQuery.support.reliableHiddenOffsets && ((elem.style && elem.style.display) || jQuery.css( elem, \"display\" )) === \"none\");\n\t};\n\n\tjQuery.expr.filters.visible = function( elem ) {\n\t\treturn !jQuery.expr.filters.hidden( elem );\n\t};\n}\n\n// These hooks are used by animate to expand properties\njQuery.each({\n\tmargin: \"\",\n\tpadding: \"\",\n\tborder: \"Width\"\n}, function( prefix, suffix ) {\n\tjQuery.cssHooks[ prefix + suffix ] = {\n\t\texpand: function( value ) {\n\t\t\tvar i = 0,\n\t\t\t\texpanded = {},\n\n\t\t\t\t// assumes a single number if not a string\n\t\t\t\tparts = typeof value === \"string\" ? value.split(\" \") : [ value ];\n\n\t\t\tfor ( ; i < 4; i++ ) {\n\t\t\t\texpanded[ prefix + cssExpand[ i ] + suffix ] =\n\t\t\t\t\tparts[ i ] || parts[ i - 2 ] || parts[ 0 ];\n\t\t\t}\n\n\t\t\treturn expanded;\n\t\t}\n\t};\n\n\tif ( !rmargin.test( prefix ) ) {\n\t\tjQuery.cssHooks[ prefix + suffix ].set = setPositiveNumber;\n\t}\n});\nvar r20 = /%20/g,\n\trbracket = /\\[\\]$/,\n\trCRLF = /\\r?\\n/g,\n\trsubmitterTypes = /^(?:submit|button|image|reset|file)$/i,\n\trsubmittable = /^(?:input|select|textarea|keygen)/i;\n\njQuery.fn.extend({\n\tserialize: function() {\n\t\treturn jQuery.param( this.serializeArray() );\n\t},\n\tserializeArray: function() {\n\t\treturn this.map(function(){\n\t\t\t// Can add propHook for \"elements\" to filter or add form elements\n\t\t\tvar elements = jQuery.prop( this, \"elements\" );\n\t\t\treturn elements ? jQuery.makeArray( elements ) : this;\n\t\t})\n\t\t.filter(function(){\n\t\t\tvar type = this.type;\n\t\t\t// Use .is(\":disabled\") so that fieldset[disabled] works\n\t\t\treturn this.name && !jQuery( this ).is( \":disabled\" ) &&\n\t\t\t\trsubmittable.test( this.nodeName ) && !rsubmitterTypes.test( type ) &&\n\t\t\t\t( this.checked || !manipulation_rcheckableType.test( type ) );\n\t\t})\n\t\t.map(function( i, elem ){\n\t\t\tvar val = jQuery( this ).val();\n\n\t\t\treturn val == null ?\n\t\t\t\tnull :\n\t\t\t\tjQuery.isArray( val ) ?\n\t\t\t\t\tjQuery.map( val, function( val ){\n\t\t\t\t\t\treturn { name: elem.name, value: val.replace( rCRLF, \"\\r\\n\" ) };\n\t\t\t\t\t}) :\n\t\t\t\t\t{ name: elem.name, value: val.replace( rCRLF, \"\\r\\n\" ) };\n\t\t}).get();\n\t}\n});\n\n//Serialize an array of form elements or a set of\n//key/values into a query string\njQuery.param = function( a, traditional ) {\n\tvar prefix,\n\t\ts = [],\n\t\tadd = function( key, value ) {\n\t\t\t// If value is a function, invoke it and return its value\n\t\t\tvalue = jQuery.isFunction( value ) ? value() : ( value == null ? \"\" : value );\n\t\t\ts[ s.length ] = encodeURIComponent( key ) + \"=\" + encodeURIComponent( value );\n\t\t};\n\n\t// Set traditional to true for jQuery <= 1.3.2 behavior.\n\tif ( traditional === undefined ) {\n\t\ttraditional = jQuery.ajaxSettings && jQuery.ajaxSettings.traditional;\n\t}\n\n\t// If an array was passed in, assume that it is an array of form elements.\n\tif ( jQuery.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) {\n\t\t// Serialize the form elements\n\t\tjQuery.each( a, function() {\n\t\t\tadd( this.name, this.value );\n\t\t});\n\n\t} else {\n\t\t// If traditional, encode the \"old\" way (the way 1.3.2 or older\n\t\t// did it), otherwise encode params recursively.\n\t\tfor ( prefix in a ) {\n\t\t\tbuildParams( prefix, a[ prefix ], traditional, add );\n\t\t}\n\t}\n\n\t// Return the resulting serialization\n\treturn s.join( \"&\" ).replace( r20, \"+\" );\n};\n\nfunction buildParams( prefix, obj, traditional, add ) {\n\tvar name;\n\n\tif ( jQuery.isArray( obj ) ) {\n\t\t// Serialize array item.\n\t\tjQuery.each( obj, function( i, v ) {\n\t\t\tif ( traditional || rbracket.test( prefix ) ) {\n\t\t\t\t// Treat each array item as a scalar.\n\t\t\t\tadd( prefix, v );\n\n\t\t\t} else {\n\t\t\t\t// Item is non-scalar (array or object), encode its numeric index.\n\t\t\t\tbuildParams( prefix + \"[\" + ( typeof v === \"object\" ? i : \"\" ) + \"]\", v, traditional, add );\n\t\t\t}\n\t\t});\n\n\t} else if ( !traditional && jQuery.type( obj ) === \"object\" ) {\n\t\t// Serialize object item.\n\t\tfor ( name in obj ) {\n\t\t\tbuildParams( prefix + \"[\" + name + \"]\", obj[ name ], traditional, add );\n\t\t}\n\n\t} else {\n\t\t// Serialize scalar item.\n\t\tadd( prefix, obj );\n\t}\n}\njQuery.each( (\"blur focus focusin focusout load resize scroll unload click dblclick \" +\n\t\"mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave \" +\n\t\"change select submit keydown keypress keyup error contextmenu\").split(\" \"), function( i, name ) {\n\n\t// Handle event binding\n\tjQuery.fn[ name ] = function( data, fn ) {\n\t\treturn arguments.length > 0 ?\n\t\t\tthis.on( name, null, data, fn ) :\n\t\t\tthis.trigger( name );\n\t};\n});\n\njQuery.fn.hover = function( fnOver, fnOut ) {\n\treturn this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );\n};\nvar\n\t// Document location\n\tajaxLocParts,\n\tajaxLocation,\n\tajax_nonce = jQuery.now(),\n\n\tajax_rquery = /\\?/,\n\trhash = /#.*$/,\n\trts = /([?&])_=[^&]*/,\n\trheaders = /^(.*?):[ \\t]*([^\\r\\n]*)\\r?$/mg, // IE leaves an \\r character at EOL\n\t// #7653, #8125, #8152: local protocol detection\n\trlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/,\n\trnoContent = /^(?:GET|HEAD)$/,\n\trprotocol = /^\\/\\//,\n\trurl = /^([\\w.+-]+:)(?:\\/\\/([^\\/?#:]*)(?::(\\d+)|)|)/,\n\n\t// Keep a copy of the old load method\n\t_load = jQuery.fn.load,\n\n\t/* Prefilters\n\t * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example)\n\t * 2) These are called:\n\t *    - BEFORE asking for a transport\n\t *    - AFTER param serialization (s.data is a string if s.processData is true)\n\t * 3) key is the dataType\n\t * 4) the catchall symbol \"*\" can be used\n\t * 5) execution will start with transport dataType and THEN continue down to \"*\" if needed\n\t */\n\tprefilters = {},\n\n\t/* Transports bindings\n\t * 1) key is the dataType\n\t * 2) the catchall symbol \"*\" can be used\n\t * 3) selection will start with transport dataType and THEN go to \"*\" if needed\n\t */\n\ttransports = {},\n\n\t// Avoid comment-prolog char sequence (#10098); must appease lint and evade compression\n\tallTypes = \"*/\".concat(\"*\");\n\n// #8138, IE may throw an exception when accessing\n// a field from window.location if document.domain has been set\ntry {\n\tajaxLocation = location.href;\n} catch( e ) {\n\t// Use the href attribute of an A element\n\t// since IE will modify it given document.location\n\tajaxLocation = document.createElement( \"a\" );\n\tajaxLocation.href = \"\";\n\tajaxLocation = ajaxLocation.href;\n}\n\n// Segment location into parts\najaxLocParts = rurl.exec( ajaxLocation.toLowerCase() ) || [];\n\n// Base \"constructor\" for jQuery.ajaxPrefilter and jQuery.ajaxTransport\nfunction addToPrefiltersOrTransports( structure ) {\n\n\t// dataTypeExpression is optional and defaults to \"*\"\n\treturn function( dataTypeExpression, func ) {\n\n\t\tif ( typeof dataTypeExpression !== \"string\" ) {\n\t\t\tfunc = dataTypeExpression;\n\t\t\tdataTypeExpression = \"*\";\n\t\t}\n\n\t\tvar dataType,\n\t\t\ti = 0,\n\t\t\tdataTypes = dataTypeExpression.toLowerCase().match( core_rnotwhite ) || [];\n\n\t\tif ( jQuery.isFunction( func ) ) {\n\t\t\t// For each dataType in the dataTypeExpression\n\t\t\twhile ( (dataType = dataTypes[i++]) ) {\n\t\t\t\t// Prepend if requested\n\t\t\t\tif ( dataType[0] === \"+\" ) {\n\t\t\t\t\tdataType = dataType.slice( 1 ) || \"*\";\n\t\t\t\t\t(structure[ dataType ] = structure[ dataType ] || []).unshift( func );\n\n\t\t\t\t// Otherwise append\n\t\t\t\t} else {\n\t\t\t\t\t(structure[ dataType ] = structure[ dataType ] || []).push( func );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t};\n}\n\n// Base inspection function for prefilters and transports\nfunction inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR ) {\n\n\tvar inspected = {},\n\t\tseekingTransport = ( structure === transports );\n\n\tfunction inspect( dataType ) {\n\t\tvar selected;\n\t\tinspected[ dataType ] = true;\n\t\tjQuery.each( structure[ dataType ] || [], function( _, prefilterOrFactory ) {\n\t\t\tvar dataTypeOrTransport = prefilterOrFactory( options, originalOptions, jqXHR );\n\t\t\tif( typeof dataTypeOrTransport === \"string\" && !seekingTransport && !inspected[ dataTypeOrTransport ] ) {\n\t\t\t\toptions.dataTypes.unshift( dataTypeOrTransport );\n\t\t\t\tinspect( dataTypeOrTransport );\n\t\t\t\treturn false;\n\t\t\t} else if ( seekingTransport ) {\n\t\t\t\treturn !( selected = dataTypeOrTransport );\n\t\t\t}\n\t\t});\n\t\treturn selected;\n\t}\n\n\treturn inspect( options.dataTypes[ 0 ] ) || !inspected[ \"*\" ] && inspect( \"*\" );\n}\n\n// A special extend for ajax options\n// that takes \"flat\" options (not to be deep extended)\n// Fixes #9887\nfunction ajaxExtend( target, src ) {\n\tvar deep, key,\n\t\tflatOptions = jQuery.ajaxSettings.flatOptions || {};\n\n\tfor ( key in src ) {\n\t\tif ( src[ key ] !== undefined ) {\n\t\t\t( flatOptions[ key ] ? target : ( deep || (deep = {}) ) )[ key ] = src[ key ];\n\t\t}\n\t}\n\tif ( deep ) {\n\t\tjQuery.extend( true, target, deep );\n\t}\n\n\treturn target;\n}\n\njQuery.fn.load = function( url, params, callback ) {\n\tif ( typeof url !== \"string\" && _load ) {\n\t\treturn _load.apply( this, arguments );\n\t}\n\n\tvar selector, response, type,\n\t\tself = this,\n\t\toff = url.indexOf(\" \");\n\n\tif ( off >= 0 ) {\n\t\tselector = url.slice( off, url.length );\n\t\turl = url.slice( 0, off );\n\t}\n\n\t// If it's a function\n\tif ( jQuery.isFunction( params ) ) {\n\n\t\t// We assume that it's the callback\n\t\tcallback = params;\n\t\tparams = undefined;\n\n\t// Otherwise, build a param string\n\t} else if ( params && typeof params === \"object\" ) {\n\t\ttype = \"POST\";\n\t}\n\n\t// If we have elements to modify, make the request\n\tif ( self.length > 0 ) {\n\t\tjQuery.ajax({\n\t\t\turl: url,\n\n\t\t\t// if \"type\" variable is undefined, then \"GET\" method will be used\n\t\t\ttype: type,\n\t\t\tdataType: \"html\",\n\t\t\tdata: params\n\t\t}).done(function( responseText ) {\n\n\t\t\t// Save response for use in complete callback\n\t\t\tresponse = arguments;\n\n\t\t\tself.html( selector ?\n\n\t\t\t\t// If a selector was specified, locate the right elements in a dummy div\n\t\t\t\t// Exclude scripts to avoid IE 'Permission Denied' errors\n\t\t\t\tjQuery(\"<div>\").append( jQuery.parseHTML( responseText ) ).find( selector ) :\n\n\t\t\t\t// Otherwise use the full result\n\t\t\t\tresponseText );\n\n\t\t}).complete( callback && function( jqXHR, status ) {\n\t\t\tself.each( callback, response || [ jqXHR.responseText, status, jqXHR ] );\n\t\t});\n\t}\n\n\treturn this;\n};\n\n// Attach a bunch of functions for handling common AJAX events\njQuery.each( [ \"ajaxStart\", \"ajaxStop\", \"ajaxComplete\", \"ajaxError\", \"ajaxSuccess\", \"ajaxSend\" ], function( i, type ){\n\tjQuery.fn[ type ] = function( fn ){\n\t\treturn this.on( type, fn );\n\t};\n});\n\njQuery.each( [ \"get\", \"post\" ], function( i, method ) {\n\tjQuery[ method ] = function( url, data, callback, type ) {\n\t\t// shift arguments if data argument was omitted\n\t\tif ( jQuery.isFunction( data ) ) {\n\t\t\ttype = type || callback;\n\t\t\tcallback = data;\n\t\t\tdata = undefined;\n\t\t}\n\n\t\treturn jQuery.ajax({\n\t\t\turl: url,\n\t\t\ttype: method,\n\t\t\tdataType: type,\n\t\t\tdata: data,\n\t\t\tsuccess: callback\n\t\t});\n\t};\n});\n\njQuery.extend({\n\n\t// Counter for holding the number of active queries\n\tactive: 0,\n\n\t// Last-Modified header cache for next request\n\tlastModified: {},\n\tetag: {},\n\n\tajaxSettings: {\n\t\turl: ajaxLocation,\n\t\ttype: \"GET\",\n\t\tisLocal: rlocalProtocol.test( ajaxLocParts[ 1 ] ),\n\t\tglobal: true,\n\t\tprocessData: true,\n\t\tasync: true,\n\t\tcontentType: \"application/x-www-form-urlencoded; charset=UTF-8\",\n\t\t/*\n\t\ttimeout: 0,\n\t\tdata: null,\n\t\tdataType: null,\n\t\tusername: null,\n\t\tpassword: null,\n\t\tcache: null,\n\t\tthrows: false,\n\t\ttraditional: false,\n\t\theaders: {},\n\t\t*/\n\n\t\taccepts: {\n\t\t\t\"*\": allTypes,\n\t\t\ttext: \"text/plain\",\n\t\t\thtml: \"text/html\",\n\t\t\txml: \"application/xml, text/xml\",\n\t\t\tjson: \"application/json, text/javascript\"\n\t\t},\n\n\t\tcontents: {\n\t\t\txml: /xml/,\n\t\t\thtml: /html/,\n\t\t\tjson: /json/\n\t\t},\n\n\t\tresponseFields: {\n\t\t\txml: \"responseXML\",\n\t\t\ttext: \"responseText\"\n\t\t},\n\n\t\t// Data converters\n\t\t// Keys separate source (or catchall \"*\") and destination types with a single space\n\t\tconverters: {\n\n\t\t\t// Convert anything to text\n\t\t\t\"* text\": window.String,\n\n\t\t\t// Text to html (true = no transformation)\n\t\t\t\"text html\": true,\n\n\t\t\t// Evaluate text as a json expression\n\t\t\t\"text json\": jQuery.parseJSON,\n\n\t\t\t// Parse text as xml\n\t\t\t\"text xml\": jQuery.parseXML\n\t\t},\n\n\t\t// For options that shouldn't be deep extended:\n\t\t// you can add your own custom options here if\n\t\t// and when you create one that shouldn't be\n\t\t// deep extended (see ajaxExtend)\n\t\tflatOptions: {\n\t\t\turl: true,\n\t\t\tcontext: true\n\t\t}\n\t},\n\n\t// Creates a full fledged settings object into target\n\t// with both ajaxSettings and settings fields.\n\t// If target is omitted, writes into ajaxSettings.\n\tajaxSetup: function( target, settings ) {\n\t\treturn settings ?\n\n\t\t\t// Building a settings object\n\t\t\tajaxExtend( ajaxExtend( target, jQuery.ajaxSettings ), settings ) :\n\n\t\t\t// Extending ajaxSettings\n\t\t\tajaxExtend( jQuery.ajaxSettings, target );\n\t},\n\n\tajaxPrefilter: addToPrefiltersOrTransports( prefilters ),\n\tajaxTransport: addToPrefiltersOrTransports( transports ),\n\n\t// Main method\n\tajax: function( url, options ) {\n\n\t\t// If url is an object, simulate pre-1.5 signature\n\t\tif ( typeof url === \"object\" ) {\n\t\t\toptions = url;\n\t\t\turl = undefined;\n\t\t}\n\n\t\t// Force options to be an object\n\t\toptions = options || {};\n\n\t\tvar // Cross-domain detection vars\n\t\t\tparts,\n\t\t\t// Loop variable\n\t\t\ti,\n\t\t\t// URL without anti-cache param\n\t\t\tcacheURL,\n\t\t\t// Response headers as string\n\t\t\tresponseHeadersString,\n\t\t\t// timeout handle\n\t\t\ttimeoutTimer,\n\n\t\t\t// To know if global events are to be dispatched\n\t\t\tfireGlobals,\n\n\t\t\ttransport,\n\t\t\t// Response headers\n\t\t\tresponseHeaders,\n\t\t\t// Create the final options object\n\t\t\ts = jQuery.ajaxSetup( {}, options ),\n\t\t\t// Callbacks context\n\t\t\tcallbackContext = s.context || s,\n\t\t\t// Context for global events is callbackContext if it is a DOM node or jQuery collection\n\t\t\tglobalEventContext = s.context && ( callbackContext.nodeType || callbackContext.jquery ) ?\n\t\t\t\tjQuery( callbackContext ) :\n\t\t\t\tjQuery.event,\n\t\t\t// Deferreds\n\t\t\tdeferred = jQuery.Deferred(),\n\t\t\tcompleteDeferred = jQuery.Callbacks(\"once memory\"),\n\t\t\t// Status-dependent callbacks\n\t\t\tstatusCode = s.statusCode || {},\n\t\t\t// Headers (they are sent all at once)\n\t\t\trequestHeaders = {},\n\t\t\trequestHeadersNames = {},\n\t\t\t// The jqXHR state\n\t\t\tstate = 0,\n\t\t\t// Default abort message\n\t\t\tstrAbort = \"canceled\",\n\t\t\t// Fake xhr\n\t\t\tjqXHR = {\n\t\t\t\treadyState: 0,\n\n\t\t\t\t// Builds headers hashtable if needed\n\t\t\t\tgetResponseHeader: function( key ) {\n\t\t\t\t\tvar match;\n\t\t\t\t\tif ( state === 2 ) {\n\t\t\t\t\t\tif ( !responseHeaders ) {\n\t\t\t\t\t\t\tresponseHeaders = {};\n\t\t\t\t\t\t\twhile ( (match = rheaders.exec( responseHeadersString )) ) {\n\t\t\t\t\t\t\t\tresponseHeaders[ match[1].toLowerCase() ] = match[ 2 ];\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tmatch = responseHeaders[ key.toLowerCase() ];\n\t\t\t\t\t}\n\t\t\t\t\treturn match == null ? null : match;\n\t\t\t\t},\n\n\t\t\t\t// Raw string\n\t\t\t\tgetAllResponseHeaders: function() {\n\t\t\t\t\treturn state === 2 ? responseHeadersString : null;\n\t\t\t\t},\n\n\t\t\t\t// Caches the header\n\t\t\t\tsetRequestHeader: function( name, value ) {\n\t\t\t\t\tvar lname = name.toLowerCase();\n\t\t\t\t\tif ( !state ) {\n\t\t\t\t\t\tname = requestHeadersNames[ lname ] = requestHeadersNames[ lname ] || name;\n\t\t\t\t\t\trequestHeaders[ name ] = value;\n\t\t\t\t\t}\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\n\t\t\t\t// Overrides response content-type header\n\t\t\t\toverrideMimeType: function( type ) {\n\t\t\t\t\tif ( !state ) {\n\t\t\t\t\t\ts.mimeType = type;\n\t\t\t\t\t}\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\n\t\t\t\t// Status-dependent callbacks\n\t\t\t\tstatusCode: function( map ) {\n\t\t\t\t\tvar code;\n\t\t\t\t\tif ( map ) {\n\t\t\t\t\t\tif ( state < 2 ) {\n\t\t\t\t\t\t\tfor ( code in map ) {\n\t\t\t\t\t\t\t\t// Lazy-add the new callback in a way that preserves old ones\n\t\t\t\t\t\t\t\tstatusCode[ code ] = [ statusCode[ code ], map[ code ] ];\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t// Execute the appropriate callbacks\n\t\t\t\t\t\t\tjqXHR.always( map[ jqXHR.status ] );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\n\t\t\t\t// Cancel the request\n\t\t\t\tabort: function( statusText ) {\n\t\t\t\t\tvar finalText = statusText || strAbort;\n\t\t\t\t\tif ( transport ) {\n\t\t\t\t\t\ttransport.abort( finalText );\n\t\t\t\t\t}\n\t\t\t\t\tdone( 0, finalText );\n\t\t\t\t\treturn this;\n\t\t\t\t}\n\t\t\t};\n\n\t\t// Attach deferreds\n\t\tdeferred.promise( jqXHR ).complete = completeDeferred.add;\n\t\tjqXHR.success = jqXHR.done;\n\t\tjqXHR.error = jqXHR.fail;\n\n\t\t// Remove hash character (#7531: and string promotion)\n\t\t// Add protocol if not provided (#5866: IE7 issue with protocol-less urls)\n\t\t// Handle falsy url in the settings object (#10093: consistency with old signature)\n\t\t// We also use the url parameter if available\n\t\ts.url = ( ( url || s.url || ajaxLocation ) + \"\" ).replace( rhash, \"\" ).replace( rprotocol, ajaxLocParts[ 1 ] + \"//\" );\n\n\t\t// Alias method option to type as per ticket #12004\n\t\ts.type = options.method || options.type || s.method || s.type;\n\n\t\t// Extract dataTypes list\n\t\ts.dataTypes = jQuery.trim( s.dataType || \"*\" ).toLowerCase().match( core_rnotwhite ) || [\"\"];\n\n\t\t// A cross-domain request is in order when we have a protocol:host:port mismatch\n\t\tif ( s.crossDomain == null ) {\n\t\t\tparts = rurl.exec( s.url.toLowerCase() );\n\t\t\ts.crossDomain = !!( parts &&\n\t\t\t\t( parts[ 1 ] !== ajaxLocParts[ 1 ] || parts[ 2 ] !== ajaxLocParts[ 2 ] ||\n\t\t\t\t\t( parts[ 3 ] || ( parts[ 1 ] === \"http:\" ? 80 : 443 ) ) !=\n\t\t\t\t\t\t( ajaxLocParts[ 3 ] || ( ajaxLocParts[ 1 ] === \"http:\" ? 80 : 443 ) ) )\n\t\t\t);\n\t\t}\n\n\t\t// Convert data if not already a string\n\t\tif ( s.data && s.processData && typeof s.data !== \"string\" ) {\n\t\t\ts.data = jQuery.param( s.data, s.traditional );\n\t\t}\n\n\t\t// Apply prefilters\n\t\tinspectPrefiltersOrTransports( prefilters, s, options, jqXHR );\n\n\t\t// If request was aborted inside a prefilter, stop there\n\t\tif ( state === 2 ) {\n\t\t\treturn jqXHR;\n\t\t}\n\n\t\t// We can fire global events as of now if asked to\n\t\tfireGlobals = s.global;\n\n\t\t// Watch for a new set of requests\n\t\tif ( fireGlobals && jQuery.active++ === 0 ) {\n\t\t\tjQuery.event.trigger(\"ajaxStart\");\n\t\t}\n\n\t\t// Uppercase the type\n\t\ts.type = s.type.toUpperCase();\n\n\t\t// Determine if request has content\n\t\ts.hasContent = !rnoContent.test( s.type );\n\n\t\t// Save the URL in case we're toying with the If-Modified-Since\n\t\t// and/or If-None-Match header later on\n\t\tcacheURL = s.url;\n\n\t\t// More options handling for requests with no content\n\t\tif ( !s.hasContent ) {\n\n\t\t\t// If data is available, append data to url\n\t\t\tif ( s.data ) {\n\t\t\t\tcacheURL = ( s.url += ( ajax_rquery.test( cacheURL ) ? \"&\" : \"?\" ) + s.data );\n\t\t\t\t// #9682: remove data so that it's not used in an eventual retry\n\t\t\t\tdelete s.data;\n\t\t\t}\n\n\t\t\t// Add anti-cache in url if needed\n\t\t\tif ( s.cache === false ) {\n\t\t\t\ts.url = rts.test( cacheURL ) ?\n\n\t\t\t\t\t// If there is already a '_' parameter, set its value\n\t\t\t\t\tcacheURL.replace( rts, \"$1_=\" + ajax_nonce++ ) :\n\n\t\t\t\t\t// Otherwise add one to the end\n\t\t\t\t\tcacheURL + ( ajax_rquery.test( cacheURL ) ? \"&\" : \"?\" ) + \"_=\" + ajax_nonce++;\n\t\t\t}\n\t\t}\n\n\t\t// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.\n\t\tif ( s.ifModified ) {\n\t\t\tif ( jQuery.lastModified[ cacheURL ] ) {\n\t\t\t\tjqXHR.setRequestHeader( \"If-Modified-Since\", jQuery.lastModified[ cacheURL ] );\n\t\t\t}\n\t\t\tif ( jQuery.etag[ cacheURL ] ) {\n\t\t\t\tjqXHR.setRequestHeader( \"If-None-Match\", jQuery.etag[ cacheURL ] );\n\t\t\t}\n\t\t}\n\n\t\t// Set the correct header, if data is being sent\n\t\tif ( s.data && s.hasContent && s.contentType !== false || options.contentType ) {\n\t\t\tjqXHR.setRequestHeader( \"Content-Type\", s.contentType );\n\t\t}\n\n\t\t// Set the Accepts header for the server, depending on the dataType\n\t\tjqXHR.setRequestHeader(\n\t\t\t\"Accept\",\n\t\t\ts.dataTypes[ 0 ] && s.accepts[ s.dataTypes[0] ] ?\n\t\t\t\ts.accepts[ s.dataTypes[0] ] + ( s.dataTypes[ 0 ] !== \"*\" ? \", \" + allTypes + \"; q=0.01\" : \"\" ) :\n\t\t\t\ts.accepts[ \"*\" ]\n\t\t);\n\n\t\t// Check for headers option\n\t\tfor ( i in s.headers ) {\n\t\t\tjqXHR.setRequestHeader( i, s.headers[ i ] );\n\t\t}\n\n\t\t// Allow custom headers/mimetypes and early abort\n\t\tif ( s.beforeSend && ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || state === 2 ) ) {\n\t\t\t// Abort if not done already and return\n\t\t\treturn jqXHR.abort();\n\t\t}\n\n\t\t// aborting is no longer a cancellation\n\t\tstrAbort = \"abort\";\n\n\t\t// Install callbacks on deferreds\n\t\tfor ( i in { success: 1, error: 1, complete: 1 } ) {\n\t\t\tjqXHR[ i ]( s[ i ] );\n\t\t}\n\n\t\t// Get transport\n\t\ttransport = inspectPrefiltersOrTransports( transports, s, options, jqXHR );\n\n\t\t// If no transport, we auto-abort\n\t\tif ( !transport ) {\n\t\t\tdone( -1, \"No Transport\" );\n\t\t} else {\n\t\t\tjqXHR.readyState = 1;\n\n\t\t\t// Send global event\n\t\t\tif ( fireGlobals ) {\n\t\t\t\tglobalEventContext.trigger( \"ajaxSend\", [ jqXHR, s ] );\n\t\t\t}\n\t\t\t// Timeout\n\t\t\tif ( s.async && s.timeout > 0 ) {\n\t\t\t\ttimeoutTimer = setTimeout(function() {\n\t\t\t\t\tjqXHR.abort(\"timeout\");\n\t\t\t\t}, s.timeout );\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tstate = 1;\n\t\t\t\ttransport.send( requestHeaders, done );\n\t\t\t} catch ( e ) {\n\t\t\t\t// Propagate exception as error if not done\n\t\t\t\tif ( state < 2 ) {\n\t\t\t\t\tdone( -1, e );\n\t\t\t\t// Simply rethrow otherwise\n\t\t\t\t} else {\n\t\t\t\t\tthrow e;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Callback for when everything is done\n\t\tfunction done( status, nativeStatusText, responses, headers ) {\n\t\t\tvar isSuccess, success, error, response, modified,\n\t\t\t\tstatusText = nativeStatusText;\n\n\t\t\t// Called once\n\t\t\tif ( state === 2 ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// State is \"done\" now\n\t\t\tstate = 2;\n\n\t\t\t// Clear timeout if it exists\n\t\t\tif ( timeoutTimer ) {\n\t\t\t\tclearTimeout( timeoutTimer );\n\t\t\t}\n\n\t\t\t// Dereference transport for early garbage collection\n\t\t\t// (no matter how long the jqXHR object will be used)\n\t\t\ttransport = undefined;\n\n\t\t\t// Cache response headers\n\t\t\tresponseHeadersString = headers || \"\";\n\n\t\t\t// Set readyState\n\t\t\tjqXHR.readyState = status > 0 ? 4 : 0;\n\n\t\t\t// Get response data\n\t\t\tif ( responses ) {\n\t\t\t\tresponse = ajaxHandleResponses( s, jqXHR, responses );\n\t\t\t}\n\n\t\t\t// If successful, handle type chaining\n\t\t\tif ( status >= 200 && status < 300 || status === 304 ) {\n\n\t\t\t\t// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.\n\t\t\t\tif ( s.ifModified ) {\n\t\t\t\t\tmodified = jqXHR.getResponseHeader(\"Last-Modified\");\n\t\t\t\t\tif ( modified ) {\n\t\t\t\t\t\tjQuery.lastModified[ cacheURL ] = modified;\n\t\t\t\t\t}\n\t\t\t\t\tmodified = jqXHR.getResponseHeader(\"etag\");\n\t\t\t\t\tif ( modified ) {\n\t\t\t\t\t\tjQuery.etag[ cacheURL ] = modified;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// if no content\n\t\t\t\tif ( status === 204 ) {\n\t\t\t\t\tisSuccess = true;\n\t\t\t\t\tstatusText = \"nocontent\";\n\n\t\t\t\t// if not modified\n\t\t\t\t} else if ( status === 304 ) {\n\t\t\t\t\tisSuccess = true;\n\t\t\t\t\tstatusText = \"notmodified\";\n\n\t\t\t\t// If we have data, let's convert it\n\t\t\t\t} else {\n\t\t\t\t\tisSuccess = ajaxConvert( s, response );\n\t\t\t\t\tstatusText = isSuccess.state;\n\t\t\t\t\tsuccess = isSuccess.data;\n\t\t\t\t\terror = isSuccess.error;\n\t\t\t\t\tisSuccess = !error;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// We extract error from statusText\n\t\t\t\t// then normalize statusText and status for non-aborts\n\t\t\t\terror = statusText;\n\t\t\t\tif ( status || !statusText ) {\n\t\t\t\t\tstatusText = \"error\";\n\t\t\t\t\tif ( status < 0 ) {\n\t\t\t\t\t\tstatus = 0;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Set data for the fake xhr object\n\t\t\tjqXHR.status = status;\n\t\t\tjqXHR.statusText = ( nativeStatusText || statusText ) + \"\";\n\n\t\t\t// Success/Error\n\t\t\tif ( isSuccess ) {\n\t\t\t\tdeferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] );\n\t\t\t} else {\n\t\t\t\tdeferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] );\n\t\t\t}\n\n\t\t\t// Status-dependent callbacks\n\t\t\tjqXHR.statusCode( statusCode );\n\t\t\tstatusCode = undefined;\n\n\t\t\tif ( fireGlobals ) {\n\t\t\t\tglobalEventContext.trigger( isSuccess ? \"ajaxSuccess\" : \"ajaxError\",\n\t\t\t\t\t[ jqXHR, s, isSuccess ? success : error ] );\n\t\t\t}\n\n\t\t\t// Complete\n\t\t\tcompleteDeferred.fireWith( callbackContext, [ jqXHR, statusText ] );\n\n\t\t\tif ( fireGlobals ) {\n\t\t\t\tglobalEventContext.trigger( \"ajaxComplete\", [ jqXHR, s ] );\n\t\t\t\t// Handle the global AJAX counter\n\t\t\t\tif ( !( --jQuery.active ) ) {\n\t\t\t\t\tjQuery.event.trigger(\"ajaxStop\");\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn jqXHR;\n\t},\n\n\tgetScript: function( url, callback ) {\n\t\treturn jQuery.get( url, undefined, callback, \"script\" );\n\t},\n\n\tgetJSON: function( url, data, callback ) {\n\t\treturn jQuery.get( url, data, callback, \"json\" );\n\t}\n});\n\n/* Handles responses to an ajax request:\n * - sets all responseXXX fields accordingly\n * - finds the right dataType (mediates between content-type and expected dataType)\n * - returns the corresponding response\n */\nfunction ajaxHandleResponses( s, jqXHR, responses ) {\n\tvar firstDataType, ct, finalDataType, type,\n\t\tcontents = s.contents,\n\t\tdataTypes = s.dataTypes,\n\t\tresponseFields = s.responseFields;\n\n\t// Fill responseXXX fields\n\tfor ( type in responseFields ) {\n\t\tif ( type in responses ) {\n\t\t\tjqXHR[ responseFields[type] ] = responses[ type ];\n\t\t}\n\t}\n\n\t// Remove auto dataType and get content-type in the process\n\twhile( dataTypes[ 0 ] === \"*\" ) {\n\t\tdataTypes.shift();\n\t\tif ( ct === undefined ) {\n\t\t\tct = s.mimeType || jqXHR.getResponseHeader(\"Content-Type\");\n\t\t}\n\t}\n\n\t// Check if we're dealing with a known content-type\n\tif ( ct ) {\n\t\tfor ( type in contents ) {\n\t\t\tif ( contents[ type ] && contents[ type ].test( ct ) ) {\n\t\t\t\tdataTypes.unshift( type );\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\t// Check to see if we have a response for the expected dataType\n\tif ( dataTypes[ 0 ] in responses ) {\n\t\tfinalDataType = dataTypes[ 0 ];\n\t} else {\n\t\t// Try convertible dataTypes\n\t\tfor ( type in responses ) {\n\t\t\tif ( !dataTypes[ 0 ] || s.converters[ type + \" \" + dataTypes[0] ] ) {\n\t\t\t\tfinalDataType = type;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif ( !firstDataType ) {\n\t\t\t\tfirstDataType = type;\n\t\t\t}\n\t\t}\n\t\t// Or just use first one\n\t\tfinalDataType = finalDataType || firstDataType;\n\t}\n\n\t// If we found a dataType\n\t// We add the dataType to the list if needed\n\t// and return the corresponding response\n\tif ( finalDataType ) {\n\t\tif ( finalDataType !== dataTypes[ 0 ] ) {\n\t\t\tdataTypes.unshift( finalDataType );\n\t\t}\n\t\treturn responses[ finalDataType ];\n\t}\n}\n\n// Chain conversions given the request and the original response\nfunction ajaxConvert( s, response ) {\n\tvar conv2, current, conv, tmp,\n\t\tconverters = {},\n\t\ti = 0,\n\t\t// Work with a copy of dataTypes in case we need to modify it for conversion\n\t\tdataTypes = s.dataTypes.slice(),\n\t\tprev = dataTypes[ 0 ];\n\n\t// Apply the dataFilter if provided\n\tif ( s.dataFilter ) {\n\t\tresponse = s.dataFilter( response, s.dataType );\n\t}\n\n\t// Create converters map with lowercased keys\n\tif ( dataTypes[ 1 ] ) {\n\t\tfor ( conv in s.converters ) {\n\t\t\tconverters[ conv.toLowerCase() ] = s.converters[ conv ];\n\t\t}\n\t}\n\n\t// Convert to each sequential dataType, tolerating list modification\n\tfor ( ; (current = dataTypes[++i]); ) {\n\n\t\t// There's only work to do if current dataType is non-auto\n\t\tif ( current !== \"*\" ) {\n\n\t\t\t// Convert response if prev dataType is non-auto and differs from current\n\t\t\tif ( prev !== \"*\" && prev !== current ) {\n\n\t\t\t\t// Seek a direct converter\n\t\t\t\tconv = converters[ prev + \" \" + current ] || converters[ \"* \" + current ];\n\n\t\t\t\t// If none found, seek a pair\n\t\t\t\tif ( !conv ) {\n\t\t\t\t\tfor ( conv2 in converters ) {\n\n\t\t\t\t\t\t// If conv2 outputs current\n\t\t\t\t\t\ttmp = conv2.split(\" \");\n\t\t\t\t\t\tif ( tmp[ 1 ] === current ) {\n\n\t\t\t\t\t\t\t// If prev can be converted to accepted input\n\t\t\t\t\t\t\tconv = converters[ prev + \" \" + tmp[ 0 ] ] ||\n\t\t\t\t\t\t\t\tconverters[ \"* \" + tmp[ 0 ] ];\n\t\t\t\t\t\t\tif ( conv ) {\n\t\t\t\t\t\t\t\t// Condense equivalence converters\n\t\t\t\t\t\t\t\tif ( conv === true ) {\n\t\t\t\t\t\t\t\t\tconv = converters[ conv2 ];\n\n\t\t\t\t\t\t\t\t// Otherwise, insert the intermediate dataType\n\t\t\t\t\t\t\t\t} else if ( converters[ conv2 ] !== true ) {\n\t\t\t\t\t\t\t\t\tcurrent = tmp[ 0 ];\n\t\t\t\t\t\t\t\t\tdataTypes.splice( i--, 0, current );\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Apply converter (if not an equivalence)\n\t\t\t\tif ( conv !== true ) {\n\n\t\t\t\t\t// Unless errors are allowed to bubble, catch and return them\n\t\t\t\t\tif ( conv && s[\"throws\"] ) {\n\t\t\t\t\t\tresponse = conv( response );\n\t\t\t\t\t} else {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tresponse = conv( response );\n\t\t\t\t\t\t} catch ( e ) {\n\t\t\t\t\t\t\treturn { state: \"parsererror\", error: conv ? e : \"No conversion from \" + prev + \" to \" + current };\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Update prev for next iteration\n\t\t\tprev = current;\n\t\t}\n\t}\n\n\treturn { state: \"success\", data: response };\n}\n// Install script dataType\njQuery.ajaxSetup({\n\taccepts: {\n\t\tscript: \"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript\"\n\t},\n\tcontents: {\n\t\tscript: /(?:java|ecma)script/\n\t},\n\tconverters: {\n\t\t\"text script\": function( text ) {\n\t\t\tjQuery.globalEval( text );\n\t\t\treturn text;\n\t\t}\n\t}\n});\n\n// Handle cache's special case and global\njQuery.ajaxPrefilter( \"script\", function( s ) {\n\tif ( s.cache === undefined ) {\n\t\ts.cache = false;\n\t}\n\tif ( s.crossDomain ) {\n\t\ts.type = \"GET\";\n\t\ts.global = false;\n\t}\n});\n\n// Bind script tag hack transport\njQuery.ajaxTransport( \"script\", function(s) {\n\n\t// This transport only deals with cross domain requests\n\tif ( s.crossDomain ) {\n\n\t\tvar script,\n\t\t\thead = document.head || jQuery(\"head\")[0] || document.documentElement;\n\n\t\treturn {\n\n\t\t\tsend: function( _, callback ) {\n\n\t\t\t\tscript = document.createElement(\"script\");\n\n\t\t\t\tscript.async = true;\n\n\t\t\t\tif ( s.scriptCharset ) {\n\t\t\t\t\tscript.charset = s.scriptCharset;\n\t\t\t\t}\n\n\t\t\t\tscript.src = s.url;\n\n\t\t\t\t// Attach handlers for all browsers\n\t\t\t\tscript.onload = script.onreadystatechange = function( _, isAbort ) {\n\n\t\t\t\t\tif ( isAbort || !script.readyState || /loaded|complete/.test( script.readyState ) ) {\n\n\t\t\t\t\t\t// Handle memory leak in IE\n\t\t\t\t\t\tscript.onload = script.onreadystatechange = null;\n\n\t\t\t\t\t\t// Remove the script\n\t\t\t\t\t\tif ( script.parentNode ) {\n\t\t\t\t\t\t\tscript.parentNode.removeChild( script );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Dereference the script\n\t\t\t\t\t\tscript = null;\n\n\t\t\t\t\t\t// Callback if not abort\n\t\t\t\t\t\tif ( !isAbort ) {\n\t\t\t\t\t\t\tcallback( 200, \"success\" );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t};\n\n\t\t\t\t// Circumvent IE6 bugs with base elements (#2709 and #4378) by prepending\n\t\t\t\t// Use native DOM manipulation to avoid our domManip AJAX trickery\n\t\t\t\thead.insertBefore( script, head.firstChild );\n\t\t\t},\n\n\t\t\tabort: function() {\n\t\t\t\tif ( script ) {\n\t\t\t\t\tscript.onload( undefined, true );\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t}\n});\nvar oldCallbacks = [],\n\trjsonp = /(=)\\?(?=&|$)|\\?\\?/;\n\n// Default jsonp settings\njQuery.ajaxSetup({\n\tjsonp: \"callback\",\n\tjsonpCallback: function() {\n\t\tvar callback = oldCallbacks.pop() || ( jQuery.expando + \"_\" + ( ajax_nonce++ ) );\n\t\tthis[ callback ] = true;\n\t\treturn callback;\n\t}\n});\n\n// Detect, normalize options and install callbacks for jsonp requests\njQuery.ajaxPrefilter( \"json jsonp\", function( s, originalSettings, jqXHR ) {\n\n\tvar callbackName, overwritten, responseContainer,\n\t\tjsonProp = s.jsonp !== false && ( rjsonp.test( s.url ) ?\n\t\t\t\"url\" :\n\t\t\ttypeof s.data === \"string\" && !( s.contentType || \"\" ).indexOf(\"application/x-www-form-urlencoded\") && rjsonp.test( s.data ) && \"data\"\n\t\t);\n\n\t// Handle iff the expected data type is \"jsonp\" or we have a parameter to set\n\tif ( jsonProp || s.dataTypes[ 0 ] === \"jsonp\" ) {\n\n\t\t// Get callback name, remembering preexisting value associated with it\n\t\tcallbackName = s.jsonpCallback = jQuery.isFunction( s.jsonpCallback ) ?\n\t\t\ts.jsonpCallback() :\n\t\t\ts.jsonpCallback;\n\n\t\t// Insert callback into url or form data\n\t\tif ( jsonProp ) {\n\t\t\ts[ jsonProp ] = s[ jsonProp ].replace( rjsonp, \"$1\" + callbackName );\n\t\t} else if ( s.jsonp !== false ) {\n\t\t\ts.url += ( ajax_rquery.test( s.url ) ? \"&\" : \"?\" ) + s.jsonp + \"=\" + callbackName;\n\t\t}\n\n\t\t// Use data converter to retrieve json after script execution\n\t\ts.converters[\"script json\"] = function() {\n\t\t\tif ( !responseContainer ) {\n\t\t\t\tjQuery.error( callbackName + \" was not called\" );\n\t\t\t}\n\t\t\treturn responseContainer[ 0 ];\n\t\t};\n\n\t\t// force json dataType\n\t\ts.dataTypes[ 0 ] = \"json\";\n\n\t\t// Install callback\n\t\toverwritten = window[ callbackName ];\n\t\twindow[ callbackName ] = function() {\n\t\t\tresponseContainer = arguments;\n\t\t};\n\n\t\t// Clean-up function (fires after converters)\n\t\tjqXHR.always(function() {\n\t\t\t// Restore preexisting value\n\t\t\twindow[ callbackName ] = overwritten;\n\n\t\t\t// Save back as free\n\t\t\tif ( s[ callbackName ] ) {\n\t\t\t\t// make sure that re-using the options doesn't screw things around\n\t\t\t\ts.jsonpCallback = originalSettings.jsonpCallback;\n\n\t\t\t\t// save the callback name for future use\n\t\t\t\toldCallbacks.push( callbackName );\n\t\t\t}\n\n\t\t\t// Call if it was a function and we have a response\n\t\t\tif ( responseContainer && jQuery.isFunction( overwritten ) ) {\n\t\t\t\toverwritten( responseContainer[ 0 ] );\n\t\t\t}\n\n\t\t\tresponseContainer = overwritten = undefined;\n\t\t});\n\n\t\t// Delegate to script\n\t\treturn \"script\";\n\t}\n});\nvar xhrCallbacks, xhrSupported,\n\txhrId = 0,\n\t// #5280: Internet Explorer will keep connections alive if we don't abort on unload\n\txhrOnUnloadAbort = window.ActiveXObject && function() {\n\t\t// Abort all pending requests\n\t\tvar key;\n\t\tfor ( key in xhrCallbacks ) {\n\t\t\txhrCallbacks[ key ]( undefined, true );\n\t\t}\n\t};\n\n// Functions to create xhrs\nfunction createStandardXHR() {\n\ttry {\n\t\treturn new window.XMLHttpRequest();\n\t} catch( e ) {}\n}\n\nfunction createActiveXHR() {\n\ttry {\n\t\treturn new window.ActiveXObject(\"Microsoft.XMLHTTP\");\n\t} catch( e ) {}\n}\n\n// Create the request object\n// (This is still attached to ajaxSettings for backward compatibility)\njQuery.ajaxSettings.xhr = window.ActiveXObject ?\n\t/* Microsoft failed to properly\n\t * implement the XMLHttpRequest in IE7 (can't request local files),\n\t * so we use the ActiveXObject when it is available\n\t * Additionally XMLHttpRequest can be disabled in IE7/IE8 so\n\t * we need a fallback.\n\t */\n\tfunction() {\n\t\treturn !this.isLocal && createStandardXHR() || createActiveXHR();\n\t} :\n\t// For all other browsers, use the standard XMLHttpRequest object\n\tcreateStandardXHR;\n\n// Determine support properties\nxhrSupported = jQuery.ajaxSettings.xhr();\njQuery.support.cors = !!xhrSupported && ( \"withCredentials\" in xhrSupported );\nxhrSupported = jQuery.support.ajax = !!xhrSupported;\n\n// Create transport if the browser can provide an xhr\nif ( xhrSupported ) {\n\n\tjQuery.ajaxTransport(function( s ) {\n\t\t// Cross domain only allowed if supported through XMLHttpRequest\n\t\tif ( !s.crossDomain || jQuery.support.cors ) {\n\n\t\t\tvar callback;\n\n\t\t\treturn {\n\t\t\t\tsend: function( headers, complete ) {\n\n\t\t\t\t\t// Get a new xhr\n\t\t\t\t\tvar handle, i,\n\t\t\t\t\t\txhr = s.xhr();\n\n\t\t\t\t\t// Open the socket\n\t\t\t\t\t// Passing null username, generates a login popup on Opera (#2865)\n\t\t\t\t\tif ( s.username ) {\n\t\t\t\t\t\txhr.open( s.type, s.url, s.async, s.username, s.password );\n\t\t\t\t\t} else {\n\t\t\t\t\t\txhr.open( s.type, s.url, s.async );\n\t\t\t\t\t}\n\n\t\t\t\t\t// Apply custom fields if provided\n\t\t\t\t\tif ( s.xhrFields ) {\n\t\t\t\t\t\tfor ( i in s.xhrFields ) {\n\t\t\t\t\t\t\txhr[ i ] = s.xhrFields[ i ];\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Override mime type if needed\n\t\t\t\t\tif ( s.mimeType && xhr.overrideMimeType ) {\n\t\t\t\t\t\txhr.overrideMimeType( s.mimeType );\n\t\t\t\t\t}\n\n\t\t\t\t\t// X-Requested-With header\n\t\t\t\t\t// For cross-domain requests, seeing as conditions for a preflight are\n\t\t\t\t\t// akin to a jigsaw puzzle, we simply never set it to be sure.\n\t\t\t\t\t// (it can always be set on a per-request basis or even using ajaxSetup)\n\t\t\t\t\t// For same-domain requests, won't change header if already provided.\n\t\t\t\t\tif ( !s.crossDomain && !headers[\"X-Requested-With\"] ) {\n\t\t\t\t\t\theaders[\"X-Requested-With\"] = \"XMLHttpRequest\";\n\t\t\t\t\t}\n\n\t\t\t\t\t// Need an extra try/catch for cross domain requests in Firefox 3\n\t\t\t\t\ttry {\n\t\t\t\t\t\tfor ( i in headers ) {\n\t\t\t\t\t\t\txhr.setRequestHeader( i, headers[ i ] );\n\t\t\t\t\t\t}\n\t\t\t\t\t} catch( err ) {}\n\n\t\t\t\t\t// Do send the request\n\t\t\t\t\t// This may raise an exception which is actually\n\t\t\t\t\t// handled in jQuery.ajax (so no try/catch here)\n\t\t\t\t\txhr.send( ( s.hasContent && s.data ) || null );\n\n\t\t\t\t\t// Listener\n\t\t\t\t\tcallback = function( _, isAbort ) {\n\t\t\t\t\t\tvar status, responseHeaders, statusText, responses;\n\n\t\t\t\t\t\t// Firefox throws exceptions when accessing properties\n\t\t\t\t\t\t// of an xhr when a network error occurred\n\t\t\t\t\t\t// http://helpful.knobs-dials.com/index.php/Component_returned_failure_code:_0x80040111_(NS_ERROR_NOT_AVAILABLE)\n\t\t\t\t\t\ttry {\n\n\t\t\t\t\t\t\t// Was never called and is aborted or complete\n\t\t\t\t\t\t\tif ( callback && ( isAbort || xhr.readyState === 4 ) ) {\n\n\t\t\t\t\t\t\t\t// Only called once\n\t\t\t\t\t\t\t\tcallback = undefined;\n\n\t\t\t\t\t\t\t\t// Do not keep as active anymore\n\t\t\t\t\t\t\t\tif ( handle ) {\n\t\t\t\t\t\t\t\t\txhr.onreadystatechange = jQuery.noop;\n\t\t\t\t\t\t\t\t\tif ( xhrOnUnloadAbort ) {\n\t\t\t\t\t\t\t\t\t\tdelete xhrCallbacks[ handle ];\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t// If it's an abort\n\t\t\t\t\t\t\t\tif ( isAbort ) {\n\t\t\t\t\t\t\t\t\t// Abort it manually if needed\n\t\t\t\t\t\t\t\t\tif ( xhr.readyState !== 4 ) {\n\t\t\t\t\t\t\t\t\t\txhr.abort();\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tresponses = {};\n\t\t\t\t\t\t\t\t\tstatus = xhr.status;\n\t\t\t\t\t\t\t\t\tresponseHeaders = xhr.getAllResponseHeaders();\n\n\t\t\t\t\t\t\t\t\t// When requesting binary data, IE6-9 will throw an exception\n\t\t\t\t\t\t\t\t\t// on any attempt to access responseText (#11426)\n\t\t\t\t\t\t\t\t\tif ( typeof xhr.responseText === \"string\" ) {\n\t\t\t\t\t\t\t\t\t\tresponses.text = xhr.responseText;\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t// Firefox throws an exception when accessing\n\t\t\t\t\t\t\t\t\t// statusText for faulty cross-domain requests\n\t\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\t\tstatusText = xhr.statusText;\n\t\t\t\t\t\t\t\t\t} catch( e ) {\n\t\t\t\t\t\t\t\t\t\t// We normalize with Webkit giving an empty statusText\n\t\t\t\t\t\t\t\t\t\tstatusText = \"\";\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t// Filter status for non standard behaviors\n\n\t\t\t\t\t\t\t\t\t// If the request is local and we have data: assume a success\n\t\t\t\t\t\t\t\t\t// (success with no data won't get notified, that's the best we\n\t\t\t\t\t\t\t\t\t// can do given current implementations)\n\t\t\t\t\t\t\t\t\tif ( !status && s.isLocal && !s.crossDomain ) {\n\t\t\t\t\t\t\t\t\t\tstatus = responses.text ? 200 : 404;\n\t\t\t\t\t\t\t\t\t// IE - #1450: sometimes returns 1223 when it should be 204\n\t\t\t\t\t\t\t\t\t} else if ( status === 1223 ) {\n\t\t\t\t\t\t\t\t\t\tstatus = 204;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} catch( firefoxAccessException ) {\n\t\t\t\t\t\t\tif ( !isAbort ) {\n\t\t\t\t\t\t\t\tcomplete( -1, firefoxAccessException );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Call complete if needed\n\t\t\t\t\t\tif ( responses ) {\n\t\t\t\t\t\t\tcomplete( status, statusText, responses, responseHeaders );\n\t\t\t\t\t\t}\n\t\t\t\t\t};\n\n\t\t\t\t\tif ( !s.async ) {\n\t\t\t\t\t\t// if we're in sync mode we fire the callback\n\t\t\t\t\t\tcallback();\n\t\t\t\t\t} else if ( xhr.readyState === 4 ) {\n\t\t\t\t\t\t// (IE6 & IE7) if it's in cache and has been\n\t\t\t\t\t\t// retrieved directly we need to fire the callback\n\t\t\t\t\t\tsetTimeout( callback );\n\t\t\t\t\t} else {\n\t\t\t\t\t\thandle = ++xhrId;\n\t\t\t\t\t\tif ( xhrOnUnloadAbort ) {\n\t\t\t\t\t\t\t// Create the active xhrs callbacks list if needed\n\t\t\t\t\t\t\t// and attach the unload handler\n\t\t\t\t\t\t\tif ( !xhrCallbacks ) {\n\t\t\t\t\t\t\t\txhrCallbacks = {};\n\t\t\t\t\t\t\t\tjQuery( window ).unload( xhrOnUnloadAbort );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t// Add to list of active xhrs callbacks\n\t\t\t\t\t\t\txhrCallbacks[ handle ] = callback;\n\t\t\t\t\t\t}\n\t\t\t\t\t\txhr.onreadystatechange = callback;\n\t\t\t\t\t}\n\t\t\t\t},\n\n\t\t\t\tabort: function() {\n\t\t\t\t\tif ( callback ) {\n\t\t\t\t\t\tcallback( undefined, true );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t};\n\t\t}\n\t});\n}\nvar fxNow, timerId,\n\trfxtypes = /^(?:toggle|show|hide)$/,\n\trfxnum = new RegExp( \"^(?:([+-])=|)(\" + core_pnum + \")([a-z%]*)$\", \"i\" ),\n\trrun = /queueHooks$/,\n\tanimationPrefilters = [ defaultPrefilter ],\n\ttweeners = {\n\t\t\"*\": [function( prop, value ) {\n\t\t\tvar end, unit,\n\t\t\t\ttween = this.createTween( prop, value ),\n\t\t\t\tparts = rfxnum.exec( value ),\n\t\t\t\ttarget = tween.cur(),\n\t\t\t\tstart = +target || 0,\n\t\t\t\tscale = 1,\n\t\t\t\tmaxIterations = 20;\n\n\t\t\tif ( parts ) {\n\t\t\t\tend = +parts[2];\n\t\t\t\tunit = parts[3] || ( jQuery.cssNumber[ prop ] ? \"\" : \"px\" );\n\n\t\t\t\t// We need to compute starting value\n\t\t\t\tif ( unit !== \"px\" && start ) {\n\t\t\t\t\t// Iteratively approximate from a nonzero starting point\n\t\t\t\t\t// Prefer the current property, because this process will be trivial if it uses the same units\n\t\t\t\t\t// Fallback to end or a simple constant\n\t\t\t\t\tstart = jQuery.css( tween.elem, prop, true ) || end || 1;\n\n\t\t\t\t\tdo {\n\t\t\t\t\t\t// If previous iteration zeroed out, double until we get *something*\n\t\t\t\t\t\t// Use a string for doubling factor so we don't accidentally see scale as unchanged below\n\t\t\t\t\t\tscale = scale || \".5\";\n\n\t\t\t\t\t\t// Adjust and apply\n\t\t\t\t\t\tstart = start / scale;\n\t\t\t\t\t\tjQuery.style( tween.elem, prop, start + unit );\n\n\t\t\t\t\t// Update scale, tolerating zero or NaN from tween.cur()\n\t\t\t\t\t// And breaking the loop if scale is unchanged or perfect, or if we've just had enough\n\t\t\t\t\t} while ( scale !== (scale = tween.cur() / target) && scale !== 1 && --maxIterations );\n\t\t\t\t}\n\n\t\t\t\ttween.unit = unit;\n\t\t\t\ttween.start = start;\n\t\t\t\t// If a +=/-= token was provided, we're doing a relative animation\n\t\t\t\ttween.end = parts[1] ? start + ( parts[1] + 1 ) * end : end;\n\t\t\t}\n\t\t\treturn tween;\n\t\t}]\n\t};\n\n// Animations created synchronously will run synchronously\nfunction createFxNow() {\n\tsetTimeout(function() {\n\t\tfxNow = undefined;\n\t});\n\treturn ( fxNow = jQuery.now() );\n}\n\nfunction createTweens( animation, props ) {\n\tjQuery.each( props, function( prop, value ) {\n\t\tvar collection = ( tweeners[ prop ] || [] ).concat( tweeners[ \"*\" ] ),\n\t\t\tindex = 0,\n\t\t\tlength = collection.length;\n\t\tfor ( ; index < length; index++ ) {\n\t\t\tif ( collection[ index ].call( animation, prop, value ) ) {\n\n\t\t\t\t// we're done with this property\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t});\n}\n\nfunction Animation( elem, properties, options ) {\n\tvar result,\n\t\tstopped,\n\t\tindex = 0,\n\t\tlength = animationPrefilters.length,\n\t\tdeferred = jQuery.Deferred().always( function() {\n\t\t\t// don't match elem in the :animated selector\n\t\t\tdelete tick.elem;\n\t\t}),\n\t\ttick = function() {\n\t\t\tif ( stopped ) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tvar currentTime = fxNow || createFxNow(),\n\t\t\t\tremaining = Math.max( 0, animation.startTime + animation.duration - currentTime ),\n\t\t\t\t// archaic crash bug won't allow us to use 1 - ( 0.5 || 0 ) (#12497)\n\t\t\t\ttemp = remaining / animation.duration || 0,\n\t\t\t\tpercent = 1 - temp,\n\t\t\t\tindex = 0,\n\t\t\t\tlength = animation.tweens.length;\n\n\t\t\tfor ( ; index < length ; index++ ) {\n\t\t\t\tanimation.tweens[ index ].run( percent );\n\t\t\t}\n\n\t\t\tdeferred.notifyWith( elem, [ animation, percent, remaining ]);\n\n\t\t\tif ( percent < 1 && length ) {\n\t\t\t\treturn remaining;\n\t\t\t} else {\n\t\t\t\tdeferred.resolveWith( elem, [ animation ] );\n\t\t\t\treturn false;\n\t\t\t}\n\t\t},\n\t\tanimation = deferred.promise({\n\t\t\telem: elem,\n\t\t\tprops: jQuery.extend( {}, properties ),\n\t\t\topts: jQuery.extend( true, { specialEasing: {} }, options ),\n\t\t\toriginalProperties: properties,\n\t\t\toriginalOptions: options,\n\t\t\tstartTime: fxNow || createFxNow(),\n\t\t\tduration: options.duration,\n\t\t\ttweens: [],\n\t\t\tcreateTween: function( prop, end ) {\n\t\t\t\tvar tween = jQuery.Tween( elem, animation.opts, prop, end,\n\t\t\t\t\t\tanimation.opts.specialEasing[ prop ] || animation.opts.easing );\n\t\t\t\tanimation.tweens.push( tween );\n\t\t\t\treturn tween;\n\t\t\t},\n\t\t\tstop: function( gotoEnd ) {\n\t\t\t\tvar index = 0,\n\t\t\t\t\t// if we are going to the end, we want to run all the tweens\n\t\t\t\t\t// otherwise we skip this part\n\t\t\t\t\tlength = gotoEnd ? animation.tweens.length : 0;\n\t\t\t\tif ( stopped ) {\n\t\t\t\t\treturn this;\n\t\t\t\t}\n\t\t\t\tstopped = true;\n\t\t\t\tfor ( ; index < length ; index++ ) {\n\t\t\t\t\tanimation.tweens[ index ].run( 1 );\n\t\t\t\t}\n\n\t\t\t\t// resolve when we played the last frame\n\t\t\t\t// otherwise, reject\n\t\t\t\tif ( gotoEnd ) {\n\t\t\t\t\tdeferred.resolveWith( elem, [ animation, gotoEnd ] );\n\t\t\t\t} else {\n\t\t\t\t\tdeferred.rejectWith( elem, [ animation, gotoEnd ] );\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t}\n\t\t}),\n\t\tprops = animation.props;\n\n\tpropFilter( props, animation.opts.specialEasing );\n\n\tfor ( ; index < length ; index++ ) {\n\t\tresult = animationPrefilters[ index ].call( animation, elem, props, animation.opts );\n\t\tif ( result ) {\n\t\t\treturn result;\n\t\t}\n\t}\n\n\tcreateTweens( animation, props );\n\n\tif ( jQuery.isFunction( animation.opts.start ) ) {\n\t\tanimation.opts.start.call( elem, animation );\n\t}\n\n\tjQuery.fx.timer(\n\t\tjQuery.extend( tick, {\n\t\t\telem: elem,\n\t\t\tanim: animation,\n\t\t\tqueue: animation.opts.queue\n\t\t})\n\t);\n\n\t// attach callbacks from options\n\treturn animation.progress( animation.opts.progress )\n\t\t.done( animation.opts.done, animation.opts.complete )\n\t\t.fail( animation.opts.fail )\n\t\t.always( animation.opts.always );\n}\n\nfunction propFilter( props, specialEasing ) {\n\tvar value, name, index, easing, hooks;\n\n\t// camelCase, specialEasing and expand cssHook pass\n\tfor ( index in props ) {\n\t\tname = jQuery.camelCase( index );\n\t\teasing = specialEasing[ name ];\n\t\tvalue = props[ index ];\n\t\tif ( jQuery.isArray( value ) ) {\n\t\t\teasing = value[ 1 ];\n\t\t\tvalue = props[ index ] = value[ 0 ];\n\t\t}\n\n\t\tif ( index !== name ) {\n\t\t\tprops[ name ] = value;\n\t\t\tdelete props[ index ];\n\t\t}\n\n\t\thooks = jQuery.cssHooks[ name ];\n\t\tif ( hooks && \"expand\" in hooks ) {\n\t\t\tvalue = hooks.expand( value );\n\t\t\tdelete props[ name ];\n\n\t\t\t// not quite $.extend, this wont overwrite keys already present.\n\t\t\t// also - reusing 'index' from above because we have the correct \"name\"\n\t\t\tfor ( index in value ) {\n\t\t\t\tif ( !( index in props ) ) {\n\t\t\t\t\tprops[ index ] = value[ index ];\n\t\t\t\t\tspecialEasing[ index ] = easing;\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tspecialEasing[ name ] = easing;\n\t\t}\n\t}\n}\n\njQuery.Animation = jQuery.extend( Animation, {\n\n\ttweener: function( props, callback ) {\n\t\tif ( jQuery.isFunction( props ) ) {\n\t\t\tcallback = props;\n\t\t\tprops = [ \"*\" ];\n\t\t} else {\n\t\t\tprops = props.split(\" \");\n\t\t}\n\n\t\tvar prop,\n\t\t\tindex = 0,\n\t\t\tlength = props.length;\n\n\t\tfor ( ; index < length ; index++ ) {\n\t\t\tprop = props[ index ];\n\t\t\ttweeners[ prop ] = tweeners[ prop ] || [];\n\t\t\ttweeners[ prop ].unshift( callback );\n\t\t}\n\t},\n\n\tprefilter: function( callback, prepend ) {\n\t\tif ( prepend ) {\n\t\t\tanimationPrefilters.unshift( callback );\n\t\t} else {\n\t\t\tanimationPrefilters.push( callback );\n\t\t}\n\t}\n});\n\nfunction defaultPrefilter( elem, props, opts ) {\n\t/*jshint validthis:true */\n\tvar prop, index, length,\n\t\tvalue, dataShow, toggle,\n\t\ttween, hooks, oldfire,\n\t\tanim = this,\n\t\tstyle = elem.style,\n\t\torig = {},\n\t\thandled = [],\n\t\thidden = elem.nodeType && isHidden( elem );\n\n\t// handle queue: false promises\n\tif ( !opts.queue ) {\n\t\thooks = jQuery._queueHooks( elem, \"fx\" );\n\t\tif ( hooks.unqueued == null ) {\n\t\t\thooks.unqueued = 0;\n\t\t\toldfire = hooks.empty.fire;\n\t\t\thooks.empty.fire = function() {\n\t\t\t\tif ( !hooks.unqueued ) {\n\t\t\t\t\toldfire();\n\t\t\t\t}\n\t\t\t};\n\t\t}\n\t\thooks.unqueued++;\n\n\t\tanim.always(function() {\n\t\t\t// doing this makes sure that the complete handler will be called\n\t\t\t// before this completes\n\t\t\tanim.always(function() {\n\t\t\t\thooks.unqueued--;\n\t\t\t\tif ( !jQuery.queue( elem, \"fx\" ).length ) {\n\t\t\t\t\thooks.empty.fire();\n\t\t\t\t}\n\t\t\t});\n\t\t});\n\t}\n\n\t// height/width overflow pass\n\tif ( elem.nodeType === 1 && ( \"height\" in props || \"width\" in props ) ) {\n\t\t// Make sure that nothing sneaks out\n\t\t// Record all 3 overflow attributes because IE does not\n\t\t// change the overflow attribute when overflowX and\n\t\t// overflowY are set to the same value\n\t\topts.overflow = [ style.overflow, style.overflowX, style.overflowY ];\n\n\t\t// Set display property to inline-block for height/width\n\t\t// animations on inline elements that are having width/height animated\n\t\tif ( jQuery.css( elem, \"display\" ) === \"inline\" &&\n\t\t\t\tjQuery.css( elem, \"float\" ) === \"none\" ) {\n\n\t\t\t// inline-level elements accept inline-block;\n\t\t\t// block-level elements need to be inline with layout\n\t\t\tif ( !jQuery.support.inlineBlockNeedsLayout || css_defaultDisplay( elem.nodeName ) === \"inline\" ) {\n\t\t\t\tstyle.display = \"inline-block\";\n\n\t\t\t} else {\n\t\t\t\tstyle.zoom = 1;\n\t\t\t}\n\t\t}\n\t}\n\n\tif ( opts.overflow ) {\n\t\tstyle.overflow = \"hidden\";\n\t\tif ( !jQuery.support.shrinkWrapBlocks ) {\n\t\t\tanim.always(function() {\n\t\t\t\tstyle.overflow = opts.overflow[ 0 ];\n\t\t\t\tstyle.overflowX = opts.overflow[ 1 ];\n\t\t\t\tstyle.overflowY = opts.overflow[ 2 ];\n\t\t\t});\n\t\t}\n\t}\n\n\n\t// show/hide pass\n\tfor ( index in props ) {\n\t\tvalue = props[ index ];\n\t\tif ( rfxtypes.exec( value ) ) {\n\t\t\tdelete props[ index ];\n\t\t\ttoggle = toggle || value === \"toggle\";\n\t\t\tif ( value === ( hidden ? \"hide\" : \"show\" ) ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\thandled.push( index );\n\t\t}\n\t}\n\n\tlength = handled.length;\n\tif ( length ) {\n\t\tdataShow = jQuery._data( elem, \"fxshow\" ) || jQuery._data( elem, \"fxshow\", {} );\n\t\tif ( \"hidden\" in dataShow ) {\n\t\t\thidden = dataShow.hidden;\n\t\t}\n\n\t\t// store state if its toggle - enables .stop().toggle() to \"reverse\"\n\t\tif ( toggle ) {\n\t\t\tdataShow.hidden = !hidden;\n\t\t}\n\t\tif ( hidden ) {\n\t\t\tjQuery( elem ).show();\n\t\t} else {\n\t\t\tanim.done(function() {\n\t\t\t\tjQuery( elem ).hide();\n\t\t\t});\n\t\t}\n\t\tanim.done(function() {\n\t\t\tvar prop;\n\t\t\tjQuery._removeData( elem, \"fxshow\" );\n\t\t\tfor ( prop in orig ) {\n\t\t\t\tjQuery.style( elem, prop, orig[ prop ] );\n\t\t\t}\n\t\t});\n\t\tfor ( index = 0 ; index < length ; index++ ) {\n\t\t\tprop = handled[ index ];\n\t\t\ttween = anim.createTween( prop, hidden ? dataShow[ prop ] : 0 );\n\t\t\torig[ prop ] = dataShow[ prop ] || jQuery.style( elem, prop );\n\n\t\t\tif ( !( prop in dataShow ) ) {\n\t\t\t\tdataShow[ prop ] = tween.start;\n\t\t\t\tif ( hidden ) {\n\t\t\t\t\ttween.end = tween.start;\n\t\t\t\t\ttween.start = prop === \"width\" || prop === \"height\" ? 1 : 0;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunction Tween( elem, options, prop, end, easing ) {\n\treturn new Tween.prototype.init( elem, options, prop, end, easing );\n}\njQuery.Tween = Tween;\n\nTween.prototype = {\n\tconstructor: Tween,\n\tinit: function( elem, options, prop, end, easing, unit ) {\n\t\tthis.elem = elem;\n\t\tthis.prop = prop;\n\t\tthis.easing = easing || \"swing\";\n\t\tthis.options = options;\n\t\tthis.start = this.now = this.cur();\n\t\tthis.end = end;\n\t\tthis.unit = unit || ( jQuery.cssNumber[ prop ] ? \"\" : \"px\" );\n\t},\n\tcur: function() {\n\t\tvar hooks = Tween.propHooks[ this.prop ];\n\n\t\treturn hooks && hooks.get ?\n\t\t\thooks.get( this ) :\n\t\t\tTween.propHooks._default.get( this );\n\t},\n\trun: function( percent ) {\n\t\tvar eased,\n\t\t\thooks = Tween.propHooks[ this.prop ];\n\n\t\tif ( this.options.duration ) {\n\t\t\tthis.pos = eased = jQuery.easing[ this.easing ](\n\t\t\t\tpercent, this.options.duration * percent, 0, 1, this.options.duration\n\t\t\t);\n\t\t} else {\n\t\t\tthis.pos = eased = percent;\n\t\t}\n\t\tthis.now = ( this.end - this.start ) * eased + this.start;\n\n\t\tif ( this.options.step ) {\n\t\t\tthis.options.step.call( this.elem, this.now, this );\n\t\t}\n\n\t\tif ( hooks && hooks.set ) {\n\t\t\thooks.set( this );\n\t\t} else {\n\t\t\tTween.propHooks._default.set( this );\n\t\t}\n\t\treturn this;\n\t}\n};\n\nTween.prototype.init.prototype = Tween.prototype;\n\nTween.propHooks = {\n\t_default: {\n\t\tget: function( tween ) {\n\t\t\tvar result;\n\n\t\t\tif ( tween.elem[ tween.prop ] != null &&\n\t\t\t\t(!tween.elem.style || tween.elem.style[ tween.prop ] == null) ) {\n\t\t\t\treturn tween.elem[ tween.prop ];\n\t\t\t}\n\n\t\t\t// passing an empty string as a 3rd parameter to .css will automatically\n\t\t\t// attempt a parseFloat and fallback to a string if the parse fails\n\t\t\t// so, simple values such as \"10px\" are parsed to Float.\n\t\t\t// complex values such as \"rotate(1rad)\" are returned as is.\n\t\t\tresult = jQuery.css( tween.elem, tween.prop, \"\" );\n\t\t\t// Empty strings, null, undefined and \"auto\" are converted to 0.\n\t\t\treturn !result || result === \"auto\" ? 0 : result;\n\t\t},\n\t\tset: function( tween ) {\n\t\t\t// use step hook for back compat - use cssHook if its there - use .style if its\n\t\t\t// available and use plain properties where available\n\t\t\tif ( jQuery.fx.step[ tween.prop ] ) {\n\t\t\t\tjQuery.fx.step[ tween.prop ]( tween );\n\t\t\t} else if ( tween.elem.style && ( tween.elem.style[ jQuery.cssProps[ tween.prop ] ] != null || jQuery.cssHooks[ tween.prop ] ) ) {\n\t\t\t\tjQuery.style( tween.elem, tween.prop, tween.now + tween.unit );\n\t\t\t} else {\n\t\t\t\ttween.elem[ tween.prop ] = tween.now;\n\t\t\t}\n\t\t}\n\t}\n};\n\n// Remove in 2.0 - this supports IE8's panic based approach\n// to setting things on disconnected nodes\n\nTween.propHooks.scrollTop = Tween.propHooks.scrollLeft = {\n\tset: function( tween ) {\n\t\tif ( tween.elem.nodeType && tween.elem.parentNode ) {\n\t\t\ttween.elem[ tween.prop ] = tween.now;\n\t\t}\n\t}\n};\n\njQuery.each([ \"toggle\", \"show\", \"hide\" ], function( i, name ) {\n\tvar cssFn = jQuery.fn[ name ];\n\tjQuery.fn[ name ] = function( speed, easing, callback ) {\n\t\treturn speed == null || typeof speed === \"boolean\" ?\n\t\t\tcssFn.apply( this, arguments ) :\n\t\t\tthis.animate( genFx( name, true ), speed, easing, callback );\n\t};\n});\n\njQuery.fn.extend({\n\tfadeTo: function( speed, to, easing, callback ) {\n\n\t\t// show any hidden elements after setting opacity to 0\n\t\treturn this.filter( isHidden ).css( \"opacity\", 0 ).show()\n\n\t\t\t// animate to the value specified\n\t\t\t.end().animate({ opacity: to }, speed, easing, callback );\n\t},\n\tanimate: function( prop, speed, easing, callback ) {\n\t\tvar empty = jQuery.isEmptyObject( prop ),\n\t\t\toptall = jQuery.speed( speed, easing, callback ),\n\t\t\tdoAnimation = function() {\n\t\t\t\t// Operate on a copy of prop so per-property easing won't be lost\n\t\t\t\tvar anim = Animation( this, jQuery.extend( {}, prop ), optall );\n\t\t\t\tdoAnimation.finish = function() {\n\t\t\t\t\tanim.stop( true );\n\t\t\t\t};\n\t\t\t\t// Empty animations, or finishing resolves immediately\n\t\t\t\tif ( empty || jQuery._data( this, \"finish\" ) ) {\n\t\t\t\t\tanim.stop( true );\n\t\t\t\t}\n\t\t\t};\n\t\t\tdoAnimation.finish = doAnimation;\n\n\t\treturn empty || optall.queue === false ?\n\t\t\tthis.each( doAnimation ) :\n\t\t\tthis.queue( optall.queue, doAnimation );\n\t},\n\tstop: function( type, clearQueue, gotoEnd ) {\n\t\tvar stopQueue = function( hooks ) {\n\t\t\tvar stop = hooks.stop;\n\t\t\tdelete hooks.stop;\n\t\t\tstop( gotoEnd );\n\t\t};\n\n\t\tif ( typeof type !== \"string\" ) {\n\t\t\tgotoEnd = clearQueue;\n\t\t\tclearQueue = type;\n\t\t\ttype = undefined;\n\t\t}\n\t\tif ( clearQueue && type !== false ) {\n\t\t\tthis.queue( type || \"fx\", [] );\n\t\t}\n\n\t\treturn this.each(function() {\n\t\t\tvar dequeue = true,\n\t\t\t\tindex = type != null && type + \"queueHooks\",\n\t\t\t\ttimers = jQuery.timers,\n\t\t\t\tdata = jQuery._data( this );\n\n\t\t\tif ( index ) {\n\t\t\t\tif ( data[ index ] && data[ index ].stop ) {\n\t\t\t\t\tstopQueue( data[ index ] );\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tfor ( index in data ) {\n\t\t\t\t\tif ( data[ index ] && data[ index ].stop && rrun.test( index ) ) {\n\t\t\t\t\t\tstopQueue( data[ index ] );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfor ( index = timers.length; index--; ) {\n\t\t\t\tif ( timers[ index ].elem === this && (type == null || timers[ index ].queue === type) ) {\n\t\t\t\t\ttimers[ index ].anim.stop( gotoEnd );\n\t\t\t\t\tdequeue = false;\n\t\t\t\t\ttimers.splice( index, 1 );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// start the next in the queue if the last step wasn't forced\n\t\t\t// timers currently will call their complete callbacks, which will dequeue\n\t\t\t// but only if they were gotoEnd\n\t\t\tif ( dequeue || !gotoEnd ) {\n\t\t\t\tjQuery.dequeue( this, type );\n\t\t\t}\n\t\t});\n\t},\n\tfinish: function( type ) {\n\t\tif ( type !== false ) {\n\t\t\ttype = type || \"fx\";\n\t\t}\n\t\treturn this.each(function() {\n\t\t\tvar index,\n\t\t\t\tdata = jQuery._data( this ),\n\t\t\t\tqueue = data[ type + \"queue\" ],\n\t\t\t\thooks = data[ type + \"queueHooks\" ],\n\t\t\t\ttimers = jQuery.timers,\n\t\t\t\tlength = queue ? queue.length : 0;\n\n\t\t\t// enable finishing flag on private data\n\t\t\tdata.finish = true;\n\n\t\t\t// empty the queue first\n\t\t\tjQuery.queue( this, type, [] );\n\n\t\t\tif ( hooks && hooks.cur && hooks.cur.finish ) {\n\t\t\t\thooks.cur.finish.call( this );\n\t\t\t}\n\n\t\t\t// look for any active animations, and finish them\n\t\t\tfor ( index = timers.length; index--; ) {\n\t\t\t\tif ( timers[ index ].elem === this && timers[ index ].queue === type ) {\n\t\t\t\t\ttimers[ index ].anim.stop( true );\n\t\t\t\t\ttimers.splice( index, 1 );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// look for any animations in the old queue and finish them\n\t\t\tfor ( index = 0; index < length; index++ ) {\n\t\t\t\tif ( queue[ index ] && queue[ index ].finish ) {\n\t\t\t\t\tqueue[ index ].finish.call( this );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// turn off finishing flag\n\t\t\tdelete data.finish;\n\t\t});\n\t}\n});\n\n// Generate parameters to create a standard animation\nfunction genFx( type, includeWidth ) {\n\tvar which,\n\t\tattrs = { height: type },\n\t\ti = 0;\n\n\t// if we include width, step value is 1 to do all cssExpand values,\n\t// if we don't include width, step value is 2 to skip over Left and Right\n\tincludeWidth = includeWidth? 1 : 0;\n\tfor( ; i < 4 ; i += 2 - includeWidth ) {\n\t\twhich = cssExpand[ i ];\n\t\tattrs[ \"margin\" + which ] = attrs[ \"padding\" + which ] = type;\n\t}\n\n\tif ( includeWidth ) {\n\t\tattrs.opacity = attrs.width = type;\n\t}\n\n\treturn attrs;\n}\n\n// Generate shortcuts for custom animations\njQuery.each({\n\tslideDown: genFx(\"show\"),\n\tslideUp: genFx(\"hide\"),\n\tslideToggle: genFx(\"toggle\"),\n\tfadeIn: { opacity: \"show\" },\n\tfadeOut: { opacity: \"hide\" },\n\tfadeToggle: { opacity: \"toggle\" }\n}, function( name, props ) {\n\tjQuery.fn[ name ] = function( speed, easing, callback ) {\n\t\treturn this.animate( props, speed, easing, callback );\n\t};\n});\n\njQuery.speed = function( speed, easing, fn ) {\n\tvar opt = speed && typeof speed === \"object\" ? jQuery.extend( {}, speed ) : {\n\t\tcomplete: fn || !fn && easing ||\n\t\t\tjQuery.isFunction( speed ) && speed,\n\t\tduration: speed,\n\t\teasing: fn && easing || easing && !jQuery.isFunction( easing ) && easing\n\t};\n\n\topt.duration = jQuery.fx.off ? 0 : typeof opt.duration === \"number\" ? opt.duration :\n\t\topt.duration in jQuery.fx.speeds ? jQuery.fx.speeds[ opt.duration ] : jQuery.fx.speeds._default;\n\n\t// normalize opt.queue - true/undefined/null -> \"fx\"\n\tif ( opt.queue == null || opt.queue === true ) {\n\t\topt.queue = \"fx\";\n\t}\n\n\t// Queueing\n\topt.old = opt.complete;\n\n\topt.complete = function() {\n\t\tif ( jQuery.isFunction( opt.old ) ) {\n\t\t\topt.old.call( this );\n\t\t}\n\n\t\tif ( opt.queue ) {\n\t\t\tjQuery.dequeue( this, opt.queue );\n\t\t}\n\t};\n\n\treturn opt;\n};\n\njQuery.easing = {\n\tlinear: function( p ) {\n\t\treturn p;\n\t},\n\tswing: function( p ) {\n\t\treturn 0.5 - Math.cos( p*Math.PI ) / 2;\n\t}\n};\n\njQuery.timers = [];\njQuery.fx = Tween.prototype.init;\njQuery.fx.tick = function() {\n\tvar timer,\n\t\ttimers = jQuery.timers,\n\t\ti = 0;\n\n\tfxNow = jQuery.now();\n\n\tfor ( ; i < timers.length; i++ ) {\n\t\ttimer = timers[ i ];\n\t\t// Checks the timer has not already been removed\n\t\tif ( !timer() && timers[ i ] === timer ) {\n\t\t\ttimers.splice( i--, 1 );\n\t\t}\n\t}\n\n\tif ( !timers.length ) {\n\t\tjQuery.fx.stop();\n\t}\n\tfxNow = undefined;\n};\n\njQuery.fx.timer = function( timer ) {\n\tif ( timer() && jQuery.timers.push( timer ) ) {\n\t\tjQuery.fx.start();\n\t}\n};\n\njQuery.fx.interval = 13;\n\njQuery.fx.start = function() {\n\tif ( !timerId ) {\n\t\ttimerId = setInterval( jQuery.fx.tick, jQuery.fx.interval );\n\t}\n};\n\njQuery.fx.stop = function() {\n\tclearInterval( timerId );\n\ttimerId = null;\n};\n\njQuery.fx.speeds = {\n\tslow: 600,\n\tfast: 200,\n\t// Default speed\n\t_default: 400\n};\n\n// Back Compat <1.8 extension point\njQuery.fx.step = {};\n\nif ( jQuery.expr && jQuery.expr.filters ) {\n\tjQuery.expr.filters.animated = function( elem ) {\n\t\treturn jQuery.grep(jQuery.timers, function( fn ) {\n\t\t\treturn elem === fn.elem;\n\t\t}).length;\n\t};\n}\njQuery.fn.offset = function( options ) {\n\tif ( arguments.length ) {\n\t\treturn options === undefined ?\n\t\t\tthis :\n\t\t\tthis.each(function( i ) {\n\t\t\t\tjQuery.offset.setOffset( this, options, i );\n\t\t\t});\n\t}\n\n\tvar docElem, win,\n\t\tbox = { top: 0, left: 0 },\n\t\telem = this[ 0 ],\n\t\tdoc = elem && elem.ownerDocument;\n\n\tif ( !doc ) {\n\t\treturn;\n\t}\n\n\tdocElem = doc.documentElement;\n\n\t// Make sure it's not a disconnected DOM node\n\tif ( !jQuery.contains( docElem, elem ) ) {\n\t\treturn box;\n\t}\n\n\t// If we don't have gBCR, just use 0,0 rather than error\n\t// BlackBerry 5, iOS 3 (original iPhone)\n\tif ( typeof elem.getBoundingClientRect !== core_strundefined ) {\n\t\tbox = elem.getBoundingClientRect();\n\t}\n\twin = getWindow( doc );\n\treturn {\n\t\ttop: box.top  + ( win.pageYOffset || docElem.scrollTop )  - ( docElem.clientTop  || 0 ),\n\t\tleft: box.left + ( win.pageXOffset || docElem.scrollLeft ) - ( docElem.clientLeft || 0 )\n\t};\n};\n\njQuery.offset = {\n\n\tsetOffset: function( elem, options, i ) {\n\t\tvar position = jQuery.css( elem, \"position\" );\n\n\t\t// set position first, in-case top/left are set even on static elem\n\t\tif ( position === \"static\" ) {\n\t\t\telem.style.position = \"relative\";\n\t\t}\n\n\t\tvar curElem = jQuery( elem ),\n\t\t\tcurOffset = curElem.offset(),\n\t\t\tcurCSSTop = jQuery.css( elem, \"top\" ),\n\t\t\tcurCSSLeft = jQuery.css( elem, \"left\" ),\n\t\t\tcalculatePosition = ( position === \"absolute\" || position === \"fixed\" ) && jQuery.inArray(\"auto\", [curCSSTop, curCSSLeft]) > -1,\n\t\t\tprops = {}, curPosition = {}, curTop, curLeft;\n\n\t\t// need to be able to calculate position if either top or left is auto and position is either absolute or fixed\n\t\tif ( calculatePosition ) {\n\t\t\tcurPosition = curElem.position();\n\t\t\tcurTop = curPosition.top;\n\t\t\tcurLeft = curPosition.left;\n\t\t} else {\n\t\t\tcurTop = parseFloat( curCSSTop ) || 0;\n\t\t\tcurLeft = parseFloat( curCSSLeft ) || 0;\n\t\t}\n\n\t\tif ( jQuery.isFunction( options ) ) {\n\t\t\toptions = options.call( elem, i, curOffset );\n\t\t}\n\n\t\tif ( options.top != null ) {\n\t\t\tprops.top = ( options.top - curOffset.top ) + curTop;\n\t\t}\n\t\tif ( options.left != null ) {\n\t\t\tprops.left = ( options.left - curOffset.left ) + curLeft;\n\t\t}\n\n\t\tif ( \"using\" in options ) {\n\t\t\toptions.using.call( elem, props );\n\t\t} else {\n\t\t\tcurElem.css( props );\n\t\t}\n\t}\n};\n\n\njQuery.fn.extend({\n\n\tposition: function() {\n\t\tif ( !this[ 0 ] ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar offsetParent, offset,\n\t\t\tparentOffset = { top: 0, left: 0 },\n\t\t\telem = this[ 0 ];\n\n\t\t// fixed elements are offset from window (parentOffset = {top:0, left: 0}, because it is it's only offset parent\n\t\tif ( jQuery.css( elem, \"position\" ) === \"fixed\" ) {\n\t\t\t// we assume that getBoundingClientRect is available when computed position is fixed\n\t\t\toffset = elem.getBoundingClientRect();\n\t\t} else {\n\t\t\t// Get *real* offsetParent\n\t\t\toffsetParent = this.offsetParent();\n\n\t\t\t// Get correct offsets\n\t\t\toffset = this.offset();\n\t\t\tif ( !jQuery.nodeName( offsetParent[ 0 ], \"html\" ) ) {\n\t\t\t\tparentOffset = offsetParent.offset();\n\t\t\t}\n\n\t\t\t// Add offsetParent borders\n\t\t\tparentOffset.top  += jQuery.css( offsetParent[ 0 ], \"borderTopWidth\", true );\n\t\t\tparentOffset.left += jQuery.css( offsetParent[ 0 ], \"borderLeftWidth\", true );\n\t\t}\n\n\t\t// Subtract parent offsets and element margins\n\t\t// note: when an element has margin: auto the offsetLeft and marginLeft\n\t\t// are the same in Safari causing offset.left to incorrectly be 0\n\t\treturn {\n\t\t\ttop:  offset.top  - parentOffset.top - jQuery.css( elem, \"marginTop\", true ),\n\t\t\tleft: offset.left - parentOffset.left - jQuery.css( elem, \"marginLeft\", true)\n\t\t};\n\t},\n\n\toffsetParent: function() {\n\t\treturn this.map(function() {\n\t\t\tvar offsetParent = this.offsetParent || document.documentElement;\n\t\t\twhile ( offsetParent && ( !jQuery.nodeName( offsetParent, \"html\" ) && jQuery.css( offsetParent, \"position\") === \"static\" ) ) {\n\t\t\t\toffsetParent = offsetParent.offsetParent;\n\t\t\t}\n\t\t\treturn offsetParent || document.documentElement;\n\t\t});\n\t}\n});\n\n\n// Create scrollLeft and scrollTop methods\njQuery.each( {scrollLeft: \"pageXOffset\", scrollTop: \"pageYOffset\"}, function( method, prop ) {\n\tvar top = /Y/.test( prop );\n\n\tjQuery.fn[ method ] = function( val ) {\n\t\treturn jQuery.access( this, function( elem, method, val ) {\n\t\t\tvar win = getWindow( elem );\n\n\t\t\tif ( val === undefined ) {\n\t\t\t\treturn win ? (prop in win) ? win[ prop ] :\n\t\t\t\t\twin.document.documentElement[ method ] :\n\t\t\t\t\telem[ method ];\n\t\t\t}\n\n\t\t\tif ( win ) {\n\t\t\t\twin.scrollTo(\n\t\t\t\t\t!top ? val : jQuery( win ).scrollLeft(),\n\t\t\t\t\ttop ? val : jQuery( win ).scrollTop()\n\t\t\t\t);\n\n\t\t\t} else {\n\t\t\t\telem[ method ] = val;\n\t\t\t}\n\t\t}, method, val, arguments.length, null );\n\t};\n});\n\nfunction getWindow( elem ) {\n\treturn jQuery.isWindow( elem ) ?\n\t\telem :\n\t\telem.nodeType === 9 ?\n\t\t\telem.defaultView || elem.parentWindow :\n\t\t\tfalse;\n}\n// Create innerHeight, innerWidth, height, width, outerHeight and outerWidth methods\njQuery.each( { Height: \"height\", Width: \"width\" }, function( name, type ) {\n\tjQuery.each( { padding: \"inner\" + name, content: type, \"\": \"outer\" + name }, function( defaultExtra, funcName ) {\n\t\t// margin is only for outerHeight, outerWidth\n\t\tjQuery.fn[ funcName ] = function( margin, value ) {\n\t\t\tvar chainable = arguments.length && ( defaultExtra || typeof margin !== \"boolean\" ),\n\t\t\t\textra = defaultExtra || ( margin === true || value === true ? \"margin\" : \"border\" );\n\n\t\t\treturn jQuery.access( this, function( elem, type, value ) {\n\t\t\t\tvar doc;\n\n\t\t\t\tif ( jQuery.isWindow( elem ) ) {\n\t\t\t\t\t// As of 5/8/2012 this will yield incorrect results for Mobile Safari, but there\n\t\t\t\t\t// isn't a whole lot we can do. See pull request at this URL for discussion:\n\t\t\t\t\t// https://github.com/jquery/jquery/pull/764\n\t\t\t\t\treturn elem.document.documentElement[ \"client\" + name ];\n\t\t\t\t}\n\n\t\t\t\t// Get document width or height\n\t\t\t\tif ( elem.nodeType === 9 ) {\n\t\t\t\t\tdoc = elem.documentElement;\n\n\t\t\t\t\t// Either scroll[Width/Height] or offset[Width/Height] or client[Width/Height], whichever is greatest\n\t\t\t\t\t// unfortunately, this causes bug #3838 in IE6/8 only, but there is currently no good, small way to fix it.\n\t\t\t\t\treturn Math.max(\n\t\t\t\t\t\telem.body[ \"scroll\" + name ], doc[ \"scroll\" + name ],\n\t\t\t\t\t\telem.body[ \"offset\" + name ], doc[ \"offset\" + name ],\n\t\t\t\t\t\tdoc[ \"client\" + name ]\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\treturn value === undefined ?\n\t\t\t\t\t// Get width or height on the element, requesting but not forcing parseFloat\n\t\t\t\t\tjQuery.css( elem, type, extra ) :\n\n\t\t\t\t\t// Set width or height on the element\n\t\t\t\t\tjQuery.style( elem, type, value, extra );\n\t\t\t}, type, chainable ? margin : undefined, chainable, null );\n\t\t};\n\t});\n});\n// Limit scope pollution from any deprecated API\n// (function() {\n\n// })();\n// Expose jQuery to the global object\nwindow.jQuery = window.$ = jQuery;\n\n// Expose jQuery as an AMD module, but only for AMD loaders that\n// understand the issues with loading multiple versions of jQuery\n// in a page that all might call define(). The loader will indicate\n// they have special allowances for multiple jQuery versions by\n// specifying define.amd.jQuery = true. Register as a named module,\n// since jQuery can be concatenated with other files that may use define,\n// but not use a proper concatenation script that understands anonymous\n// AMD modules. A named AMD is safest and most robust way to register.\n// Lowercase jquery is used because AMD module names are derived from\n// file names, and jQuery is normally delivered in a lowercase file name.\n// Do this after creating the global so that if an AMD module wants to call\n// noConflict to hide this version of jQuery, it will work.\nif ( typeof define === \"function\" && define.amd && define.amd.jQuery ) {\n\tdefine( \"jquery\", [], function () { return jQuery; } );\n}\n\n})( window );"
  },
  {
    "path": "flowable-ui-web/task/libs/sizzle_1.10.16/test/libs/qunit/qunit.css",
    "content": "/**\n * QUnit v1.12.0 - A JavaScript Unit Testing Framework\n *\n * http://qunitjs.com\n *\n * Copyright 2012 jQuery Foundation and other contributors\n * Released under the MIT license.\n * http://jquery.org/license\n */\n\n/** Font Family and Sizes */\n\n#qunit-tests, #qunit-header, #qunit-banner, #qunit-testrunner-toolbar, #qunit-userAgent, #qunit-testresult {\n\tfont-family: \"Helvetica Neue Light\", \"HelveticaNeue-Light\", \"Helvetica Neue\", Calibri, Helvetica, Arial, sans-serif;\n}\n\n#qunit-testrunner-toolbar, #qunit-userAgent, #qunit-testresult, #qunit-tests li { font-size: small; }\n#qunit-tests { font-size: smaller; }\n\n\n/** Resets */\n\n#qunit-tests, #qunit-header, #qunit-banner, #qunit-userAgent, #qunit-testresult, #qunit-modulefilter {\n\tmargin: 0;\n\tpadding: 0;\n}\n\n\n/** Header */\n\n#qunit-header {\n\tpadding: 0.5em 0 0.5em 1em;\n\n\tcolor: #8699a4;\n\tbackground-color: #0d3349;\n\n\tfont-size: 1.5em;\n\tline-height: 1em;\n\tfont-weight: normal;\n\n\tborder-radius: 5px 5px 0 0;\n\t-moz-border-radius: 5px 5px 0 0;\n\t-webkit-border-top-right-radius: 5px;\n\t-webkit-border-top-left-radius: 5px;\n}\n\n#qunit-header a {\n\ttext-decoration: none;\n\tcolor: #c2ccd1;\n}\n\n#qunit-header a:hover,\n#qunit-header a:focus {\n\tcolor: #fff;\n}\n\n#qunit-testrunner-toolbar label {\n\tdisplay: inline-block;\n\tpadding: 0 .5em 0 .1em;\n}\n\n#qunit-banner {\n\theight: 5px;\n}\n\n#qunit-testrunner-toolbar {\n\tpadding: 0.5em 0 0.5em 2em;\n\tcolor: #5E740B;\n\tbackground-color: #eee;\n\toverflow: hidden;\n}\n\n#qunit-userAgent {\n\tpadding: 0.5em 0 0.5em 2.5em;\n\tbackground-color: #2b81af;\n\tcolor: #fff;\n\ttext-shadow: rgba(0, 0, 0, 0.5) 2px 2px 1px;\n}\n\n#qunit-modulefilter-container {\n\tfloat: right;\n}\n\n/** Tests: Pass/Fail */\n\n#qunit-tests {\n\tlist-style-position: inside;\n}\n\n#qunit-tests li {\n\tpadding: 0.4em 0.5em 0.4em 2.5em;\n\tborder-bottom: 1px solid #fff;\n\tlist-style-position: inside;\n}\n\n#qunit-tests.hidepass li.pass, #qunit-tests.hidepass li.running  {\n\tdisplay: none;\n}\n\n#qunit-tests li strong {\n\tcursor: pointer;\n}\n\n#qunit-tests li a {\n\tpadding: 0.5em;\n\tcolor: #c2ccd1;\n\ttext-decoration: none;\n}\n#qunit-tests li a:hover,\n#qunit-tests li a:focus {\n\tcolor: #000;\n}\n\n#qunit-tests li .runtime {\n\tfloat: right;\n\tfont-size: smaller;\n}\n\n.qunit-assert-list {\n\tmargin-top: 0.5em;\n\tpadding: 0.5em;\n\n\tbackground-color: #fff;\n\n\tborder-radius: 5px;\n\t-moz-border-radius: 5px;\n\t-webkit-border-radius: 5px;\n}\n\n.qunit-collapsed {\n\tdisplay: none;\n}\n\n#qunit-tests table {\n\tborder-collapse: collapse;\n\tmargin-top: .2em;\n}\n\n#qunit-tests th {\n\ttext-align: right;\n\tvertical-align: top;\n\tpadding: 0 .5em 0 0;\n}\n\n#qunit-tests td {\n\tvertical-align: top;\n}\n\n#qunit-tests pre {\n\tmargin: 0;\n\twhite-space: pre-wrap;\n\tword-wrap: break-word;\n}\n\n#qunit-tests del {\n\tbackground-color: #e0f2be;\n\tcolor: #374e0c;\n\ttext-decoration: none;\n}\n\n#qunit-tests ins {\n\tbackground-color: #ffcaca;\n\tcolor: #500;\n\ttext-decoration: none;\n}\n\n/*** Test Counts */\n\n#qunit-tests b.counts                       { color: black; }\n#qunit-tests b.passed                       { color: #5E740B; }\n#qunit-tests b.failed                       { color: #710909; }\n\n#qunit-tests li li {\n\tpadding: 5px;\n\tbackground-color: #fff;\n\tborder-bottom: none;\n\tlist-style-position: inside;\n}\n\n/*** Passing Styles */\n\n#qunit-tests li li.pass {\n\tcolor: #3c510c;\n\tbackground-color: #fff;\n\tborder-left: 10px solid #C6E746;\n}\n\n#qunit-tests .pass                          { color: #528CE0; background-color: #D2E0E6; }\n#qunit-tests .pass .test-name               { color: #366097; }\n\n#qunit-tests .pass .test-actual,\n#qunit-tests .pass .test-expected           { color: #999999; }\n\n#qunit-banner.qunit-pass                    { background-color: #C6E746; }\n\n/*** Failing Styles */\n\n#qunit-tests li li.fail {\n\tcolor: #710909;\n\tbackground-color: #fff;\n\tborder-left: 10px solid #EE5757;\n\twhite-space: pre;\n}\n\n#qunit-tests > li:last-child {\n\tborder-radius: 0 0 5px 5px;\n\t-moz-border-radius: 0 0 5px 5px;\n\t-webkit-border-bottom-right-radius: 5px;\n\t-webkit-border-bottom-left-radius: 5px;\n}\n\n#qunit-tests .fail                          { color: #000000; background-color: #EE5757; }\n#qunit-tests .fail .test-name,\n#qunit-tests .fail .module-name             { color: #000000; }\n\n#qunit-tests .fail .test-actual             { color: #EE5757; }\n#qunit-tests .fail .test-expected           { color: green;   }\n\n#qunit-banner.qunit-fail                    { background-color: #EE5757; }\n\n\n/** Result */\n\n#qunit-testresult {\n\tpadding: 0.5em 0.5em 0.5em 2.5em;\n\n\tcolor: #2b81af;\n\tbackground-color: #D2E0E6;\n\n\tborder-bottom: 1px solid white;\n}\n#qunit-testresult .module-name {\n\tfont-weight: bold;\n}\n\n/** Fixture */\n\n#qunit-fixture {\n\tposition: absolute;\n\ttop: -10000px;\n\tleft: -10000px;\n\twidth: 1000px;\n\theight: 1000px;\n}\n"
  },
  {
    "path": "flowable-ui-web/task/libs/sizzle_1.10.16/test/libs/qunit/qunit.js",
    "content": "/**\n * QUnit v1.12.0 - A JavaScript Unit Testing Framework\n *\n * http://qunitjs.com\n *\n * Copyright 2013 jQuery Foundation and other contributors\n * Released under the MIT license.\n * https://jquery.org/license/\n */\n\n(function( window ) {\n\nvar QUnit,\n\tassert,\n\tconfig,\n\tonErrorFnPrev,\n\ttestId = 0,\n\tfileName = (sourceFromStacktrace( 0 ) || \"\" ).replace(/(:\\d+)+\\)?/, \"\").replace(/.+\\//, \"\"),\n\ttoString = Object.prototype.toString,\n\thasOwn = Object.prototype.hasOwnProperty,\n\t// Keep a local reference to Date (GH-283)\n\tDate = window.Date,\n\tsetTimeout = window.setTimeout,\n\tdefined = {\n\t\tsetTimeout: typeof window.setTimeout !== \"undefined\",\n\t\tsessionStorage: (function() {\n\t\t\tvar x = \"qunit-test-string\";\n\t\t\ttry {\n\t\t\t\tsessionStorage.setItem( x, x );\n\t\t\t\tsessionStorage.removeItem( x );\n\t\t\t\treturn true;\n\t\t\t} catch( e ) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}())\n\t},\n\t/**\n\t * Provides a normalized error string, correcting an issue\n\t * with IE 7 (and prior) where Error.prototype.toString is\n\t * not properly implemented\n\t *\n\t * Based on http://es5.github.com/#x15.11.4.4\n\t *\n\t * @param {String|Error} error\n\t * @return {String} error message\n\t */\n\terrorString = function( error ) {\n\t\tvar name, message,\n\t\t\terrorString = error.toString();\n\t\tif ( errorString.substring( 0, 7 ) === \"[object\" ) {\n\t\t\tname = error.name ? error.name.toString() : \"Error\";\n\t\t\tmessage = error.message ? error.message.toString() : \"\";\n\t\t\tif ( name && message ) {\n\t\t\t\treturn name + \": \" + message;\n\t\t\t} else if ( name ) {\n\t\t\t\treturn name;\n\t\t\t} else if ( message ) {\n\t\t\t\treturn message;\n\t\t\t} else {\n\t\t\t\treturn \"Error\";\n\t\t\t}\n\t\t} else {\n\t\t\treturn errorString;\n\t\t}\n\t},\n\t/**\n\t * Makes a clone of an object using only Array or Object as base,\n\t * and copies over the own enumerable properties.\n\t *\n\t * @param {Object} obj\n\t * @return {Object} New object with only the own properties (recursively).\n\t */\n\tobjectValues = function( obj ) {\n\t\t// Grunt 0.3.x uses an older version of jshint that still has jshint/jshint#392.\n\t\t/*jshint newcap: false */\n\t\tvar key, val,\n\t\t\tvals = QUnit.is( \"array\", obj ) ? [] : {};\n\t\tfor ( key in obj ) {\n\t\t\tif ( hasOwn.call( obj, key ) ) {\n\t\t\t\tval = obj[key];\n\t\t\t\tvals[key] = val === Object(val) ? objectValues(val) : val;\n\t\t\t}\n\t\t}\n\t\treturn vals;\n\t};\n\nfunction Test( settings ) {\n\textend( this, settings );\n\tthis.assertions = [];\n\tthis.testNumber = ++Test.count;\n}\n\nTest.count = 0;\n\nTest.prototype = {\n\tinit: function() {\n\t\tvar a, b, li,\n\t\t\ttests = id( \"qunit-tests\" );\n\n\t\tif ( tests ) {\n\t\t\tb = document.createElement( \"strong\" );\n\t\t\tb.innerHTML = this.nameHtml;\n\n\t\t\t// `a` initialized at top of scope\n\t\t\ta = document.createElement( \"a\" );\n\t\t\ta.innerHTML = \"Rerun\";\n\t\t\ta.href = QUnit.url({ testNumber: this.testNumber });\n\n\t\t\tli = document.createElement( \"li\" );\n\t\t\tli.appendChild( b );\n\t\t\tli.appendChild( a );\n\t\t\tli.className = \"running\";\n\t\t\tli.id = this.id = \"qunit-test-output\" + testId++;\n\n\t\t\ttests.appendChild( li );\n\t\t}\n\t},\n\tsetup: function() {\n\t\tif (\n\t\t\t// Emit moduleStart when we're switching from one module to another\n\t\t\tthis.module !== config.previousModule ||\n\t\t\t\t// They could be equal (both undefined) but if the previousModule property doesn't\n\t\t\t\t// yet exist it means this is the first test in a suite that isn't wrapped in a\n\t\t\t\t// module, in which case we'll just emit a moduleStart event for 'undefined'.\n\t\t\t\t// Without this, reporters can get testStart before moduleStart  which is a problem.\n\t\t\t\t!hasOwn.call( config, \"previousModule\" )\n\t\t) {\n\t\t\tif ( hasOwn.call( config, \"previousModule\" ) ) {\n\t\t\t\trunLoggingCallbacks( \"moduleDone\", QUnit, {\n\t\t\t\t\tname: config.previousModule,\n\t\t\t\t\tfailed: config.moduleStats.bad,\n\t\t\t\t\tpassed: config.moduleStats.all - config.moduleStats.bad,\n\t\t\t\t\ttotal: config.moduleStats.all\n\t\t\t\t});\n\t\t\t}\n\t\t\tconfig.previousModule = this.module;\n\t\t\tconfig.moduleStats = { all: 0, bad: 0 };\n\t\t\trunLoggingCallbacks( \"moduleStart\", QUnit, {\n\t\t\t\tname: this.module\n\t\t\t});\n\t\t}\n\n\t\tconfig.current = this;\n\n\t\tthis.testEnvironment = extend({\n\t\t\tsetup: function() {},\n\t\t\tteardown: function() {}\n\t\t}, this.moduleTestEnvironment );\n\n\t\tthis.started = +new Date();\n\t\trunLoggingCallbacks( \"testStart\", QUnit, {\n\t\t\tname: this.testName,\n\t\t\tmodule: this.module\n\t\t});\n\n\t\t/*jshint camelcase:false */\n\n\n\t\t/**\n\t\t * Expose the current test environment.\n\t\t *\n\t\t * @deprecated since 1.12.0: Use QUnit.config.current.testEnvironment instead.\n\t\t */\n\t\tQUnit.current_testEnvironment = this.testEnvironment;\n\n\t\t/*jshint camelcase:true */\n\n\t\tif ( !config.pollution ) {\n\t\t\tsaveGlobal();\n\t\t}\n\t\tif ( config.notrycatch ) {\n\t\t\tthis.testEnvironment.setup.call( this.testEnvironment, QUnit.assert );\n\t\t\treturn;\n\t\t}\n\t\ttry {\n\t\t\tthis.testEnvironment.setup.call( this.testEnvironment, QUnit.assert );\n\t\t} catch( e ) {\n\t\t\tQUnit.pushFailure( \"Setup failed on \" + this.testName + \": \" + ( e.message || e ), extractStacktrace( e, 1 ) );\n\t\t}\n\t},\n\trun: function() {\n\t\tconfig.current = this;\n\n\t\tvar running = id( \"qunit-testresult\" );\n\n\t\tif ( running ) {\n\t\t\trunning.innerHTML = \"Running: <br/>\" + this.nameHtml;\n\t\t}\n\n\t\tif ( this.async ) {\n\t\t\tQUnit.stop();\n\t\t}\n\n\t\tthis.callbackStarted = +new Date();\n\n\t\tif ( config.notrycatch ) {\n\t\t\tthis.callback.call( this.testEnvironment, QUnit.assert );\n\t\t\tthis.callbackRuntime = +new Date() - this.callbackStarted;\n\t\t\treturn;\n\t\t}\n\n\t\ttry {\n\t\t\tthis.callback.call( this.testEnvironment, QUnit.assert );\n\t\t\tthis.callbackRuntime = +new Date() - this.callbackStarted;\n\t\t} catch( e ) {\n\t\t\tthis.callbackRuntime = +new Date() - this.callbackStarted;\n\n\t\t\tQUnit.pushFailure( \"Died on test #\" + (this.assertions.length + 1) + \" \" + this.stack + \": \" + ( e.message || e ), extractStacktrace( e, 0 ) );\n\t\t\t// else next test will carry the responsibility\n\t\t\tsaveGlobal();\n\n\t\t\t// Restart the tests if they're blocking\n\t\t\tif ( config.blocking ) {\n\t\t\t\tQUnit.start();\n\t\t\t}\n\t\t}\n\t},\n\tteardown: function() {\n\t\tconfig.current = this;\n\t\tif ( config.notrycatch ) {\n\t\t\tif ( typeof this.callbackRuntime === \"undefined\" ) {\n\t\t\t\tthis.callbackRuntime = +new Date() - this.callbackStarted;\n\t\t\t}\n\t\t\tthis.testEnvironment.teardown.call( this.testEnvironment, QUnit.assert );\n\t\t\treturn;\n\t\t} else {\n\t\t\ttry {\n\t\t\t\tthis.testEnvironment.teardown.call( this.testEnvironment, QUnit.assert );\n\t\t\t} catch( e ) {\n\t\t\t\tQUnit.pushFailure( \"Teardown failed on \" + this.testName + \": \" + ( e.message || e ), extractStacktrace( e, 1 ) );\n\t\t\t}\n\t\t}\n\t\tcheckPollution();\n\t},\n\tfinish: function() {\n\t\tconfig.current = this;\n\t\tif ( config.requireExpects && this.expected === null ) {\n\t\t\tQUnit.pushFailure( \"Expected number of assertions to be defined, but expect() was not called.\", this.stack );\n\t\t} else if ( this.expected !== null && this.expected !== this.assertions.length ) {\n\t\t\tQUnit.pushFailure( \"Expected \" + this.expected + \" assertions, but \" + this.assertions.length + \" were run\", this.stack );\n\t\t} else if ( this.expected === null && !this.assertions.length ) {\n\t\t\tQUnit.pushFailure( \"Expected at least one assertion, but none were run - call expect(0) to accept zero assertions.\", this.stack );\n\t\t}\n\n\t\tvar i, assertion, a, b, time, li, ol,\n\t\t\ttest = this,\n\t\t\tgood = 0,\n\t\t\tbad = 0,\n\t\t\ttests = id( \"qunit-tests\" );\n\n\t\tthis.runtime = +new Date() - this.started;\n\t\tconfig.stats.all += this.assertions.length;\n\t\tconfig.moduleStats.all += this.assertions.length;\n\n\t\tif ( tests ) {\n\t\t\tol = document.createElement( \"ol\" );\n\t\t\tol.className = \"qunit-assert-list\";\n\n\t\t\tfor ( i = 0; i < this.assertions.length; i++ ) {\n\t\t\t\tassertion = this.assertions[i];\n\n\t\t\t\tli = document.createElement( \"li\" );\n\t\t\t\tli.className = assertion.result ? \"pass\" : \"fail\";\n\t\t\t\tli.innerHTML = assertion.message || ( assertion.result ? \"okay\" : \"failed\" );\n\t\t\t\tol.appendChild( li );\n\n\t\t\t\tif ( assertion.result ) {\n\t\t\t\t\tgood++;\n\t\t\t\t} else {\n\t\t\t\t\tbad++;\n\t\t\t\t\tconfig.stats.bad++;\n\t\t\t\t\tconfig.moduleStats.bad++;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// store result when possible\n\t\t\tif ( QUnit.config.reorder && defined.sessionStorage ) {\n\t\t\t\tif ( bad ) {\n\t\t\t\t\tsessionStorage.setItem( \"qunit-test-\" + this.module + \"-\" + this.testName, bad );\n\t\t\t\t} else {\n\t\t\t\t\tsessionStorage.removeItem( \"qunit-test-\" + this.module + \"-\" + this.testName );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( bad === 0 ) {\n\t\t\t\taddClass( ol, \"qunit-collapsed\" );\n\t\t\t}\n\n\t\t\t// `b` initialized at top of scope\n\t\t\tb = document.createElement( \"strong\" );\n\t\t\tb.innerHTML = this.nameHtml + \" <b class='counts'>(<b class='failed'>\" + bad + \"</b>, <b class='passed'>\" + good + \"</b>, \" + this.assertions.length + \")</b>\";\n\n\t\t\taddEvent(b, \"click\", function() {\n\t\t\t\tvar next = b.parentNode.lastChild,\n\t\t\t\t\tcollapsed = hasClass( next, \"qunit-collapsed\" );\n\t\t\t\t( collapsed ? removeClass : addClass )( next, \"qunit-collapsed\" );\n\t\t\t});\n\n\t\t\taddEvent(b, \"dblclick\", function( e ) {\n\t\t\t\tvar target = e && e.target ? e.target : window.event.srcElement;\n\t\t\t\tif ( target.nodeName.toLowerCase() === \"span\" || target.nodeName.toLowerCase() === \"b\" ) {\n\t\t\t\t\ttarget = target.parentNode;\n\t\t\t\t}\n\t\t\t\tif ( window.location && target.nodeName.toLowerCase() === \"strong\" ) {\n\t\t\t\t\twindow.location = QUnit.url({ testNumber: test.testNumber });\n\t\t\t\t}\n\t\t\t});\n\n\t\t\t// `time` initialized at top of scope\n\t\t\ttime = document.createElement( \"span\" );\n\t\t\ttime.className = \"runtime\";\n\t\t\ttime.innerHTML = this.runtime + \" ms\";\n\n\t\t\t// `li` initialized at top of scope\n\t\t\tli = id( this.id );\n\t\t\tli.className = bad ? \"fail\" : \"pass\";\n\t\t\tli.removeChild( li.firstChild );\n\t\t\ta = li.firstChild;\n\t\t\tli.appendChild( b );\n\t\t\tli.appendChild( a );\n\t\t\tli.appendChild( time );\n\t\t\tli.appendChild( ol );\n\n\t\t} else {\n\t\t\tfor ( i = 0; i < this.assertions.length; i++ ) {\n\t\t\t\tif ( !this.assertions[i].result ) {\n\t\t\t\t\tbad++;\n\t\t\t\t\tconfig.stats.bad++;\n\t\t\t\t\tconfig.moduleStats.bad++;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\trunLoggingCallbacks( \"testDone\", QUnit, {\n\t\t\tname: this.testName,\n\t\t\tmodule: this.module,\n\t\t\tfailed: bad,\n\t\t\tpassed: this.assertions.length - bad,\n\t\t\ttotal: this.assertions.length,\n\t\t\tduration: this.runtime\n\t\t});\n\n\t\tQUnit.reset();\n\n\t\tconfig.current = undefined;\n\t},\n\n\tqueue: function() {\n\t\tvar bad,\n\t\t\ttest = this;\n\n\t\tsynchronize(function() {\n\t\t\ttest.init();\n\t\t});\n\t\tfunction run() {\n\t\t\t// each of these can by async\n\t\t\tsynchronize(function() {\n\t\t\t\ttest.setup();\n\t\t\t});\n\t\t\tsynchronize(function() {\n\t\t\t\ttest.run();\n\t\t\t});\n\t\t\tsynchronize(function() {\n\t\t\t\ttest.teardown();\n\t\t\t});\n\t\t\tsynchronize(function() {\n\t\t\t\ttest.finish();\n\t\t\t});\n\t\t}\n\n\t\t// `bad` initialized at top of scope\n\t\t// defer when previous test run passed, if storage is available\n\t\tbad = QUnit.config.reorder && defined.sessionStorage &&\n\t\t\t\t\t\t+sessionStorage.getItem( \"qunit-test-\" + this.module + \"-\" + this.testName );\n\n\t\tif ( bad ) {\n\t\t\trun();\n\t\t} else {\n\t\t\tsynchronize( run, true );\n\t\t}\n\t}\n};\n\n// Root QUnit object.\n// `QUnit` initialized at top of scope\nQUnit = {\n\n\t// call on start of module test to prepend name to all tests\n\tmodule: function( name, testEnvironment ) {\n\t\tconfig.currentModule = name;\n\t\tconfig.currentModuleTestEnvironment = testEnvironment;\n\t\tconfig.modules[name] = true;\n\t},\n\n\tasyncTest: function( testName, expected, callback ) {\n\t\tif ( arguments.length === 2 ) {\n\t\t\tcallback = expected;\n\t\t\texpected = null;\n\t\t}\n\n\t\tQUnit.test( testName, expected, callback, true );\n\t},\n\n\ttest: function( testName, expected, callback, async ) {\n\t\tvar test,\n\t\t\tnameHtml = \"<span class='test-name'>\" + escapeText( testName ) + \"</span>\";\n\n\t\tif ( arguments.length === 2 ) {\n\t\t\tcallback = expected;\n\t\t\texpected = null;\n\t\t}\n\n\t\tif ( config.currentModule ) {\n\t\t\tnameHtml = \"<span class='module-name'>\" + escapeText( config.currentModule ) + \"</span>: \" + nameHtml;\n\t\t}\n\n\t\ttest = new Test({\n\t\t\tnameHtml: nameHtml,\n\t\t\ttestName: testName,\n\t\t\texpected: expected,\n\t\t\tasync: async,\n\t\t\tcallback: callback,\n\t\t\tmodule: config.currentModule,\n\t\t\tmoduleTestEnvironment: config.currentModuleTestEnvironment,\n\t\t\tstack: sourceFromStacktrace( 2 )\n\t\t});\n\n\t\tif ( !validTest( test ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\ttest.queue();\n\t},\n\n\t// Specify the number of expected assertions to guarantee that failed test (no assertions are run at all) don't slip through.\n\texpect: function( asserts ) {\n\t\tif (arguments.length === 1) {\n\t\t\tconfig.current.expected = asserts;\n\t\t} else {\n\t\t\treturn config.current.expected;\n\t\t}\n\t},\n\n\tstart: function( count ) {\n\t\t// QUnit hasn't been initialized yet.\n\t\t// Note: RequireJS (et al) may delay onLoad\n\t\tif ( config.semaphore === undefined ) {\n\t\t\tQUnit.begin(function() {\n\t\t\t\t// This is triggered at the top of QUnit.load, push start() to the event loop, to allow QUnit.load to finish first\n\t\t\t\tsetTimeout(function() {\n\t\t\t\t\tQUnit.start( count );\n\t\t\t\t});\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\n\t\tconfig.semaphore -= count || 1;\n\t\t// don't start until equal number of stop-calls\n\t\tif ( config.semaphore > 0 ) {\n\t\t\treturn;\n\t\t}\n\t\t// ignore if start is called more often then stop\n\t\tif ( config.semaphore < 0 ) {\n\t\t\tconfig.semaphore = 0;\n\t\t\tQUnit.pushFailure( \"Called start() while already started (QUnit.config.semaphore was 0 already)\", null, sourceFromStacktrace(2) );\n\t\t\treturn;\n\t\t}\n\t\t// A slight delay, to avoid any current callbacks\n\t\tif ( defined.setTimeout ) {\n\t\t\tsetTimeout(function() {\n\t\t\t\tif ( config.semaphore > 0 ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tif ( config.timeout ) {\n\t\t\t\t\tclearTimeout( config.timeout );\n\t\t\t\t}\n\n\t\t\t\tconfig.blocking = false;\n\t\t\t\tprocess( true );\n\t\t\t}, 13);\n\t\t} else {\n\t\t\tconfig.blocking = false;\n\t\t\tprocess( true );\n\t\t}\n\t},\n\n\tstop: function( count ) {\n\t\tconfig.semaphore += count || 1;\n\t\tconfig.blocking = true;\n\n\t\tif ( config.testTimeout && defined.setTimeout ) {\n\t\t\tclearTimeout( config.timeout );\n\t\t\tconfig.timeout = setTimeout(function() {\n\t\t\t\tQUnit.ok( false, \"Test timed out\" );\n\t\t\t\tconfig.semaphore = 1;\n\t\t\t\tQUnit.start();\n\t\t\t}, config.testTimeout );\n\t\t}\n\t}\n};\n\n// `assert` initialized at top of scope\n// Assert helpers\n// All of these must either call QUnit.push() or manually do:\n// - runLoggingCallbacks( \"log\", .. );\n// - config.current.assertions.push({ .. });\n// We attach it to the QUnit object *after* we expose the public API,\n// otherwise `assert` will become a global variable in browsers (#341).\nassert = {\n\t/**\n\t * Asserts rough true-ish result.\n\t * @name ok\n\t * @function\n\t * @example ok( \"asdfasdf\".length > 5, \"There must be at least 5 chars\" );\n\t */\n\tok: function( result, msg ) {\n\t\tif ( !config.current ) {\n\t\t\tthrow new Error( \"ok() assertion outside test context, was \" + sourceFromStacktrace(2) );\n\t\t}\n\t\tresult = !!result;\n\t\tmsg = msg || (result ? \"okay\" : \"failed\" );\n\n\t\tvar source,\n\t\t\tdetails = {\n\t\t\t\tmodule: config.current.module,\n\t\t\t\tname: config.current.testName,\n\t\t\t\tresult: result,\n\t\t\t\tmessage: msg\n\t\t\t};\n\n\t\tmsg = \"<span class='test-message'>\" + escapeText( msg ) + \"</span>\";\n\n\t\tif ( !result ) {\n\t\t\tsource = sourceFromStacktrace( 2 );\n\t\t\tif ( source ) {\n\t\t\t\tdetails.source = source;\n\t\t\t\tmsg += \"<table><tr class='test-source'><th>Source: </th><td><pre>\" + escapeText( source ) + \"</pre></td></tr></table>\";\n\t\t\t}\n\t\t}\n\t\trunLoggingCallbacks( \"log\", QUnit, details );\n\t\tconfig.current.assertions.push({\n\t\t\tresult: result,\n\t\t\tmessage: msg\n\t\t});\n\t},\n\n\t/**\n\t * Assert that the first two arguments are equal, with an optional message.\n\t * Prints out both actual and expected values.\n\t * @name equal\n\t * @function\n\t * @example equal( format( \"Received {0} bytes.\", 2), \"Received 2 bytes.\", \"format() replaces {0} with next argument\" );\n\t */\n\tequal: function( actual, expected, message ) {\n\t\t/*jshint eqeqeq:false */\n\t\tQUnit.push( expected == actual, actual, expected, message );\n\t},\n\n\t/**\n\t * @name notEqual\n\t * @function\n\t */\n\tnotEqual: function( actual, expected, message ) {\n\t\t/*jshint eqeqeq:false */\n\t\tQUnit.push( expected != actual, actual, expected, message );\n\t},\n\n\t/**\n\t * @name propEqual\n\t * @function\n\t */\n\tpropEqual: function( actual, expected, message ) {\n\t\tactual = objectValues(actual);\n\t\texpected = objectValues(expected);\n\t\tQUnit.push( QUnit.equiv(actual, expected), actual, expected, message );\n\t},\n\n\t/**\n\t * @name notPropEqual\n\t * @function\n\t */\n\tnotPropEqual: function( actual, expected, message ) {\n\t\tactual = objectValues(actual);\n\t\texpected = objectValues(expected);\n\t\tQUnit.push( !QUnit.equiv(actual, expected), actual, expected, message );\n\t},\n\n\t/**\n\t * @name deepEqual\n\t * @function\n\t */\n\tdeepEqual: function( actual, expected, message ) {\n\t\tQUnit.push( QUnit.equiv(actual, expected), actual, expected, message );\n\t},\n\n\t/**\n\t * @name notDeepEqual\n\t * @function\n\t */\n\tnotDeepEqual: function( actual, expected, message ) {\n\t\tQUnit.push( !QUnit.equiv(actual, expected), actual, expected, message );\n\t},\n\n\t/**\n\t * @name strictEqual\n\t * @function\n\t */\n\tstrictEqual: function( actual, expected, message ) {\n\t\tQUnit.push( expected === actual, actual, expected, message );\n\t},\n\n\t/**\n\t * @name notStrictEqual\n\t * @function\n\t */\n\tnotStrictEqual: function( actual, expected, message ) {\n\t\tQUnit.push( expected !== actual, actual, expected, message );\n\t},\n\n\t\"throws\": function( block, expected, message ) {\n\t\tvar actual,\n\t\t\texpectedOutput = expected,\n\t\t\tok = false;\n\n\t\t// 'expected' is optional\n\t\tif ( typeof expected === \"string\" ) {\n\t\t\tmessage = expected;\n\t\t\texpected = null;\n\t\t}\n\n\t\tconfig.current.ignoreGlobalErrors = true;\n\t\ttry {\n\t\t\tblock.call( config.current.testEnvironment );\n\t\t} catch (e) {\n\t\t\tactual = e;\n\t\t}\n\t\tconfig.current.ignoreGlobalErrors = false;\n\n\t\tif ( actual ) {\n\t\t\t// we don't want to validate thrown error\n\t\t\tif ( !expected ) {\n\t\t\t\tok = true;\n\t\t\t\texpectedOutput = null;\n\t\t\t// expected is a regexp\n\t\t\t} else if ( QUnit.objectType( expected ) === \"regexp\" ) {\n\t\t\t\tok = expected.test( errorString( actual ) );\n\t\t\t// expected is a constructor\n\t\t\t} else if ( actual instanceof expected ) {\n\t\t\t\tok = true;\n\t\t\t// expected is a validation function which returns true is validation passed\n\t\t\t} else if ( expected.call( {}, actual ) === true ) {\n\t\t\t\texpectedOutput = null;\n\t\t\t\tok = true;\n\t\t\t}\n\n\t\t\tQUnit.push( ok, actual, expectedOutput, message );\n\t\t} else {\n\t\t\tQUnit.pushFailure( message, null, \"No exception was thrown.\" );\n\t\t}\n\t}\n};\n\n/**\n * @deprecated since 1.8.0\n * Kept assertion helpers in root for backwards compatibility.\n */\nextend( QUnit, assert );\n\n/**\n * @deprecated since 1.9.0\n * Kept root \"raises()\" for backwards compatibility.\n * (Note that we don't introduce assert.raises).\n */\nQUnit.raises = assert[ \"throws\" ];\n\n/**\n * @deprecated since 1.0.0, replaced with error pushes since 1.3.0\n * Kept to avoid TypeErrors for undefined methods.\n */\nQUnit.equals = function() {\n\tQUnit.push( false, false, false, \"QUnit.equals has been deprecated since 2009 (e88049a0), use QUnit.equal instead\" );\n};\nQUnit.same = function() {\n\tQUnit.push( false, false, false, \"QUnit.same has been deprecated since 2009 (e88049a0), use QUnit.deepEqual instead\" );\n};\n\n// We want access to the constructor's prototype\n(function() {\n\tfunction F() {}\n\tF.prototype = QUnit;\n\tQUnit = new F();\n\t// Make F QUnit's constructor so that we can add to the prototype later\n\tQUnit.constructor = F;\n}());\n\n/**\n * Config object: Maintain internal state\n * Later exposed as QUnit.config\n * `config` initialized at top of scope\n */\nconfig = {\n\t// The queue of tests to run\n\tqueue: [],\n\n\t// block until document ready\n\tblocking: true,\n\n\t// when enabled, show only failing tests\n\t// gets persisted through sessionStorage and can be changed in UI via checkbox\n\thidepassed: false,\n\n\t// by default, run previously failed tests first\n\t// very useful in combination with \"Hide passed tests\" checked\n\treorder: true,\n\n\t// by default, modify document.title when suite is done\n\taltertitle: true,\n\n\t// when enabled, all tests must call expect()\n\trequireExpects: false,\n\n\t// add checkboxes that are persisted in the query-string\n\t// when enabled, the id is set to `true` as a `QUnit.config` property\n\turlConfig: [\n\t\t{\n\t\t\tid: \"noglobals\",\n\t\t\tlabel: \"Check for Globals\",\n\t\t\ttooltip: \"Enabling this will test if any test introduces new properties on the `window` object. Stored as query-strings.\"\n\t\t},\n\t\t{\n\t\t\tid: \"notrycatch\",\n\t\t\tlabel: \"No try-catch\",\n\t\t\ttooltip: \"Enabling this will run tests outside of a try-catch block. Makes debugging exceptions in IE reasonable. Stored as query-strings.\"\n\t\t}\n\t],\n\n\t// Set of all modules.\n\tmodules: {},\n\n\t// logging callback queues\n\tbegin: [],\n\tdone: [],\n\tlog: [],\n\ttestStart: [],\n\ttestDone: [],\n\tmoduleStart: [],\n\tmoduleDone: []\n};\n\n// Export global variables, unless an 'exports' object exists,\n// in that case we assume we're in CommonJS (dealt with on the bottom of the script)\nif ( typeof exports === \"undefined\" ) {\n\textend( window, QUnit.constructor.prototype );\n\n\t// Expose QUnit object\n\twindow.QUnit = QUnit;\n}\n\n// Initialize more QUnit.config and QUnit.urlParams\n(function() {\n\tvar i,\n\t\tlocation = window.location || { search: \"\", protocol: \"file:\" },\n\t\tparams = location.search.slice( 1 ).split( \"&\" ),\n\t\tlength = params.length,\n\t\turlParams = {},\n\t\tcurrent;\n\n\tif ( params[ 0 ] ) {\n\t\tfor ( i = 0; i < length; i++ ) {\n\t\t\tcurrent = params[ i ].split( \"=\" );\n\t\t\tcurrent[ 0 ] = decodeURIComponent( current[ 0 ] );\n\t\t\t// allow just a key to turn on a flag, e.g., test.html?noglobals\n\t\t\tcurrent[ 1 ] = current[ 1 ] ? decodeURIComponent( current[ 1 ] ) : true;\n\t\t\turlParams[ current[ 0 ] ] = current[ 1 ];\n\t\t}\n\t}\n\n\tQUnit.urlParams = urlParams;\n\n\t// String search anywhere in moduleName+testName\n\tconfig.filter = urlParams.filter;\n\n\t// Exact match of the module name\n\tconfig.module = urlParams.module;\n\n\tconfig.testNumber = parseInt( urlParams.testNumber, 10 ) || null;\n\n\t// Figure out if we're running the tests from a server or not\n\tQUnit.isLocal = location.protocol === \"file:\";\n}());\n\n// Extend QUnit object,\n// these after set here because they should not be exposed as global functions\nextend( QUnit, {\n\tassert: assert,\n\n\tconfig: config,\n\n\t// Initialize the configuration options\n\tinit: function() {\n\t\textend( config, {\n\t\t\tstats: { all: 0, bad: 0 },\n\t\t\tmoduleStats: { all: 0, bad: 0 },\n\t\t\tstarted: +new Date(),\n\t\t\tupdateRate: 1000,\n\t\t\tblocking: false,\n\t\t\tautostart: true,\n\t\t\tautorun: false,\n\t\t\tfilter: \"\",\n\t\t\tqueue: [],\n\t\t\tsemaphore: 1\n\t\t});\n\n\t\tvar tests, banner, result,\n\t\t\tqunit = id( \"qunit\" );\n\n\t\tif ( qunit ) {\n\t\t\tqunit.innerHTML =\n\t\t\t\t\"<h1 id='qunit-header'>\" + escapeText( document.title ) + \"</h1>\" +\n\t\t\t\t\"<h2 id='qunit-banner'></h2>\" +\n\t\t\t\t\"<div id='qunit-testrunner-toolbar'></div>\" +\n\t\t\t\t\"<h2 id='qunit-userAgent'></h2>\" +\n\t\t\t\t\"<ol id='qunit-tests'></ol>\";\n\t\t}\n\n\t\ttests = id( \"qunit-tests\" );\n\t\tbanner = id( \"qunit-banner\" );\n\t\tresult = id( \"qunit-testresult\" );\n\n\t\tif ( tests ) {\n\t\t\ttests.innerHTML = \"\";\n\t\t}\n\n\t\tif ( banner ) {\n\t\t\tbanner.className = \"\";\n\t\t}\n\n\t\tif ( result ) {\n\t\t\tresult.parentNode.removeChild( result );\n\t\t}\n\n\t\tif ( tests ) {\n\t\t\tresult = document.createElement( \"p\" );\n\t\t\tresult.id = \"qunit-testresult\";\n\t\t\tresult.className = \"result\";\n\t\t\ttests.parentNode.insertBefore( result, tests );\n\t\t\tresult.innerHTML = \"Running...<br/>&nbsp;\";\n\t\t}\n\t},\n\n\t// Resets the test setup. Useful for tests that modify the DOM.\n\t/*\n\tDEPRECATED: Use multiple tests instead of resetting inside a test.\n\tUse testStart or testDone for custom cleanup.\n\tThis method will throw an error in 2.0, and will be removed in 2.1\n\t*/\n\treset: function() {\n\t\tvar fixture = id( \"qunit-fixture\" );\n\t\tif ( fixture ) {\n\t\t\tfixture.innerHTML = config.fixture;\n\t\t}\n\t},\n\n\t// Trigger an event on an element.\n\t// @example triggerEvent( document.body, \"click\" );\n\ttriggerEvent: function( elem, type, event ) {\n\t\tif ( document.createEvent ) {\n\t\t\tevent = document.createEvent( \"MouseEvents\" );\n\t\t\tevent.initMouseEvent(type, true, true, elem.ownerDocument.defaultView,\n\t\t\t\t0, 0, 0, 0, 0, false, false, false, false, 0, null);\n\n\t\t\telem.dispatchEvent( event );\n\t\t} else if ( elem.fireEvent ) {\n\t\t\telem.fireEvent( \"on\" + type );\n\t\t}\n\t},\n\n\t// Safe object type checking\n\tis: function( type, obj ) {\n\t\treturn QUnit.objectType( obj ) === type;\n\t},\n\n\tobjectType: function( obj ) {\n\t\tif ( typeof obj === \"undefined\" ) {\n\t\t\t\treturn \"undefined\";\n\t\t// consider: typeof null === object\n\t\t}\n\t\tif ( obj === null ) {\n\t\t\t\treturn \"null\";\n\t\t}\n\n\t\tvar match = toString.call( obj ).match(/^\\[object\\s(.*)\\]$/),\n\t\t\ttype = match && match[1] || \"\";\n\n\t\tswitch ( type ) {\n\t\t\tcase \"Number\":\n\t\t\t\tif ( isNaN(obj) ) {\n\t\t\t\t\treturn \"nan\";\n\t\t\t\t}\n\t\t\t\treturn \"number\";\n\t\t\tcase \"String\":\n\t\t\tcase \"Boolean\":\n\t\t\tcase \"Array\":\n\t\t\tcase \"Date\":\n\t\t\tcase \"RegExp\":\n\t\t\tcase \"Function\":\n\t\t\t\treturn type.toLowerCase();\n\t\t}\n\t\tif ( typeof obj === \"object\" ) {\n\t\t\treturn \"object\";\n\t\t}\n\t\treturn undefined;\n\t},\n\n\tpush: function( result, actual, expected, message ) {\n\t\tif ( !config.current ) {\n\t\t\tthrow new Error( \"assertion outside test context, was \" + sourceFromStacktrace() );\n\t\t}\n\n\t\tvar output, source,\n\t\t\tdetails = {\n\t\t\t\tmodule: config.current.module,\n\t\t\t\tname: config.current.testName,\n\t\t\t\tresult: result,\n\t\t\t\tmessage: message,\n\t\t\t\tactual: actual,\n\t\t\t\texpected: expected\n\t\t\t};\n\n\t\tmessage = escapeText( message ) || ( result ? \"okay\" : \"failed\" );\n\t\tmessage = \"<span class='test-message'>\" + message + \"</span>\";\n\t\toutput = message;\n\n\t\tif ( !result ) {\n\t\t\texpected = escapeText( QUnit.jsDump.parse(expected) );\n\t\t\tactual = escapeText( QUnit.jsDump.parse(actual) );\n\t\t\toutput += \"<table><tr class='test-expected'><th>Expected: </th><td><pre>\" + expected + \"</pre></td></tr>\";\n\n\t\t\tif ( actual !== expected ) {\n\t\t\t\toutput += \"<tr class='test-actual'><th>Result: </th><td><pre>\" + actual + \"</pre></td></tr>\";\n\t\t\t\toutput += \"<tr class='test-diff'><th>Diff: </th><td><pre>\" + QUnit.diff( expected, actual ) + \"</pre></td></tr>\";\n\t\t\t}\n\n\t\t\tsource = sourceFromStacktrace();\n\n\t\t\tif ( source ) {\n\t\t\t\tdetails.source = source;\n\t\t\t\toutput += \"<tr class='test-source'><th>Source: </th><td><pre>\" + escapeText( source ) + \"</pre></td></tr>\";\n\t\t\t}\n\n\t\t\toutput += \"</table>\";\n\t\t}\n\n\t\trunLoggingCallbacks( \"log\", QUnit, details );\n\n\t\tconfig.current.assertions.push({\n\t\t\tresult: !!result,\n\t\t\tmessage: output\n\t\t});\n\t},\n\n\tpushFailure: function( message, source, actual ) {\n\t\tif ( !config.current ) {\n\t\t\tthrow new Error( \"pushFailure() assertion outside test context, was \" + sourceFromStacktrace(2) );\n\t\t}\n\n\t\tvar output,\n\t\t\tdetails = {\n\t\t\t\tmodule: config.current.module,\n\t\t\t\tname: config.current.testName,\n\t\t\t\tresult: false,\n\t\t\t\tmessage: message\n\t\t\t};\n\n\t\tmessage = escapeText( message ) || \"error\";\n\t\tmessage = \"<span class='test-message'>\" + message + \"</span>\";\n\t\toutput = message;\n\n\t\toutput += \"<table>\";\n\n\t\tif ( actual ) {\n\t\t\toutput += \"<tr class='test-actual'><th>Result: </th><td><pre>\" + escapeText( actual ) + \"</pre></td></tr>\";\n\t\t}\n\n\t\tif ( source ) {\n\t\t\tdetails.source = source;\n\t\t\toutput += \"<tr class='test-source'><th>Source: </th><td><pre>\" + escapeText( source ) + \"</pre></td></tr>\";\n\t\t}\n\n\t\toutput += \"</table>\";\n\n\t\trunLoggingCallbacks( \"log\", QUnit, details );\n\n\t\tconfig.current.assertions.push({\n\t\t\tresult: false,\n\t\t\tmessage: output\n\t\t});\n\t},\n\n\turl: function( params ) {\n\t\tparams = extend( extend( {}, QUnit.urlParams ), params );\n\t\tvar key,\n\t\t\tquerystring = \"?\";\n\n\t\tfor ( key in params ) {\n\t\t\tif ( hasOwn.call( params, key ) ) {\n\t\t\t\tquerystring += encodeURIComponent( key ) + \"=\" +\n\t\t\t\t\tencodeURIComponent( params[ key ] ) + \"&\";\n\t\t\t}\n\t\t}\n\t\treturn window.location.protocol + \"//\" + window.location.host +\n\t\t\twindow.location.pathname + querystring.slice( 0, -1 );\n\t},\n\n\textend: extend,\n\tid: id,\n\taddEvent: addEvent,\n\taddClass: addClass,\n\thasClass: hasClass,\n\tremoveClass: removeClass\n\t// load, equiv, jsDump, diff: Attached later\n});\n\n/**\n * @deprecated: Created for backwards compatibility with test runner that set the hook function\n * into QUnit.{hook}, instead of invoking it and passing the hook function.\n * QUnit.constructor is set to the empty F() above so that we can add to it's prototype here.\n * Doing this allows us to tell if the following methods have been overwritten on the actual\n * QUnit object.\n */\nextend( QUnit.constructor.prototype, {\n\n\t// Logging callbacks; all receive a single argument with the listed properties\n\t// run test/logs.html for any related changes\n\tbegin: registerLoggingCallback( \"begin\" ),\n\n\t// done: { failed, passed, total, runtime }\n\tdone: registerLoggingCallback( \"done\" ),\n\n\t// log: { result, actual, expected, message }\n\tlog: registerLoggingCallback( \"log\" ),\n\n\t// testStart: { name }\n\ttestStart: registerLoggingCallback( \"testStart\" ),\n\n\t// testDone: { name, failed, passed, total, duration }\n\ttestDone: registerLoggingCallback( \"testDone\" ),\n\n\t// moduleStart: { name }\n\tmoduleStart: registerLoggingCallback( \"moduleStart\" ),\n\n\t// moduleDone: { name, failed, passed, total }\n\tmoduleDone: registerLoggingCallback( \"moduleDone\" )\n});\n\nif ( typeof document === \"undefined\" || document.readyState === \"complete\" ) {\n\tconfig.autorun = true;\n}\n\nQUnit.load = function() {\n\trunLoggingCallbacks( \"begin\", QUnit, {} );\n\n\t// Initialize the config, saving the execution queue\n\tvar banner, filter, i, label, len, main, ol, toolbar, userAgent, val,\n\t\turlConfigCheckboxesContainer, urlConfigCheckboxes, moduleFilter,\n\t\tnumModules = 0,\n\t\tmoduleNames = [],\n\t\tmoduleFilterHtml = \"\",\n\t\turlConfigHtml = \"\",\n\t\toldconfig = extend( {}, config );\n\n\tQUnit.init();\n\textend(config, oldconfig);\n\n\tconfig.blocking = false;\n\n\tlen = config.urlConfig.length;\n\n\tfor ( i = 0; i < len; i++ ) {\n\t\tval = config.urlConfig[i];\n\t\tif ( typeof val === \"string\" ) {\n\t\t\tval = {\n\t\t\t\tid: val,\n\t\t\t\tlabel: val,\n\t\t\t\ttooltip: \"[no tooltip available]\"\n\t\t\t};\n\t\t}\n\t\tconfig[ val.id ] = QUnit.urlParams[ val.id ];\n\t\turlConfigHtml += \"<input id='qunit-urlconfig-\" + escapeText( val.id ) +\n\t\t\t\"' name='\" + escapeText( val.id ) +\n\t\t\t\"' type='checkbox'\" + ( config[ val.id ] ? \" checked='checked'\" : \"\" ) +\n\t\t\t\" title='\" + escapeText( val.tooltip ) +\n\t\t\t\"'><label for='qunit-urlconfig-\" + escapeText( val.id ) +\n\t\t\t\"' title='\" + escapeText( val.tooltip ) + \"'>\" + val.label + \"</label>\";\n\t}\n\tfor ( i in config.modules ) {\n\t\tif ( config.modules.hasOwnProperty( i ) ) {\n\t\t\tmoduleNames.push(i);\n\t\t}\n\t}\n\tnumModules = moduleNames.length;\n\tmoduleNames.sort( function( a, b ) {\n\t\treturn a.localeCompare( b );\n\t});\n\tmoduleFilterHtml += \"<label for='qunit-modulefilter'>Module: </label><select id='qunit-modulefilter' name='modulefilter'><option value='' \" +\n\t\t( config.module === undefined  ? \"selected='selected'\" : \"\" ) +\n\t\t\">< All Modules ></option>\";\n\n\n\tfor ( i = 0; i < numModules; i++) {\n\t\t\tmoduleFilterHtml += \"<option value='\" + escapeText( encodeURIComponent(moduleNames[i]) ) + \"' \" +\n\t\t\t\t( config.module === moduleNames[i] ? \"selected='selected'\" : \"\" ) +\n\t\t\t\t\">\" + escapeText(moduleNames[i]) + \"</option>\";\n\t}\n\tmoduleFilterHtml += \"</select>\";\n\n\t// `userAgent` initialized at top of scope\n\tuserAgent = id( \"qunit-userAgent\" );\n\tif ( userAgent ) {\n\t\tuserAgent.innerHTML = navigator.userAgent;\n\t}\n\n\t// `banner` initialized at top of scope\n\tbanner = id( \"qunit-header\" );\n\tif ( banner ) {\n\t\tbanner.innerHTML = \"<a href='\" + QUnit.url({ filter: undefined, module: undefined, testNumber: undefined }) + \"'>\" + banner.innerHTML + \"</a> \";\n\t}\n\n\t// `toolbar` initialized at top of scope\n\ttoolbar = id( \"qunit-testrunner-toolbar\" );\n\tif ( toolbar ) {\n\t\t// `filter` initialized at top of scope\n\t\tfilter = document.createElement( \"input\" );\n\t\tfilter.type = \"checkbox\";\n\t\tfilter.id = \"qunit-filter-pass\";\n\n\t\taddEvent( filter, \"click\", function() {\n\t\t\tvar tmp,\n\t\t\t\tol = document.getElementById( \"qunit-tests\" );\n\n\t\t\tif ( filter.checked ) {\n\t\t\t\tol.className = ol.className + \" hidepass\";\n\t\t\t} else {\n\t\t\t\ttmp = \" \" + ol.className.replace( /[\\n\\t\\r]/g, \" \" ) + \" \";\n\t\t\t\tol.className = tmp.replace( / hidepass /, \" \" );\n\t\t\t}\n\t\t\tif ( defined.sessionStorage ) {\n\t\t\t\tif (filter.checked) {\n\t\t\t\t\tsessionStorage.setItem( \"qunit-filter-passed-tests\", \"true\" );\n\t\t\t\t} else {\n\t\t\t\t\tsessionStorage.removeItem( \"qunit-filter-passed-tests\" );\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\tif ( config.hidepassed || defined.sessionStorage && sessionStorage.getItem( \"qunit-filter-passed-tests\" ) ) {\n\t\t\tfilter.checked = true;\n\t\t\t// `ol` initialized at top of scope\n\t\t\tol = document.getElementById( \"qunit-tests\" );\n\t\t\tol.className = ol.className + \" hidepass\";\n\t\t}\n\t\ttoolbar.appendChild( filter );\n\n\t\t// `label` initialized at top of scope\n\t\tlabel = document.createElement( \"label\" );\n\t\tlabel.setAttribute( \"for\", \"qunit-filter-pass\" );\n\t\tlabel.setAttribute( \"title\", \"Only show tests and assertions that fail. Stored in sessionStorage.\" );\n\t\tlabel.innerHTML = \"Hide passed tests\";\n\t\ttoolbar.appendChild( label );\n\n\t\turlConfigCheckboxesContainer = document.createElement(\"span\");\n\t\turlConfigCheckboxesContainer.innerHTML = urlConfigHtml;\n\t\turlConfigCheckboxes = urlConfigCheckboxesContainer.getElementsByTagName(\"input\");\n\t\t// For oldIE support:\n\t\t// * Add handlers to the individual elements instead of the container\n\t\t// * Use \"click\" instead of \"change\"\n\t\t// * Fallback from event.target to event.srcElement\n\t\taddEvents( urlConfigCheckboxes, \"click\", function( event ) {\n\t\t\tvar params = {},\n\t\t\t\ttarget = event.target || event.srcElement;\n\t\t\tparams[ target.name ] = target.checked ? true : undefined;\n\t\t\twindow.location = QUnit.url( params );\n\t\t});\n\t\ttoolbar.appendChild( urlConfigCheckboxesContainer );\n\n\t\tif (numModules > 1) {\n\t\t\tmoduleFilter = document.createElement( \"span\" );\n\t\t\tmoduleFilter.setAttribute( \"id\", \"qunit-modulefilter-container\" );\n\t\t\tmoduleFilter.innerHTML = moduleFilterHtml;\n\t\t\taddEvent( moduleFilter.lastChild, \"change\", function() {\n\t\t\t\tvar selectBox = moduleFilter.getElementsByTagName(\"select\")[0],\n\t\t\t\t\tselectedModule = decodeURIComponent(selectBox.options[selectBox.selectedIndex].value);\n\n\t\t\t\twindow.location = QUnit.url({\n\t\t\t\t\tmodule: ( selectedModule === \"\" ) ? undefined : selectedModule,\n\t\t\t\t\t// Remove any existing filters\n\t\t\t\t\tfilter: undefined,\n\t\t\t\t\ttestNumber: undefined\n\t\t\t\t});\n\t\t\t});\n\t\t\ttoolbar.appendChild(moduleFilter);\n\t\t}\n\t}\n\n\t// `main` initialized at top of scope\n\tmain = id( \"qunit-fixture\" );\n\tif ( main ) {\n\t\tconfig.fixture = main.innerHTML;\n\t}\n\n\tif ( config.autostart ) {\n\t\tQUnit.start();\n\t}\n};\n\naddEvent( window, \"load\", QUnit.load );\n\n// `onErrorFnPrev` initialized at top of scope\n// Preserve other handlers\nonErrorFnPrev = window.onerror;\n\n// Cover uncaught exceptions\n// Returning true will suppress the default browser handler,\n// returning false will let it run.\nwindow.onerror = function ( error, filePath, linerNr ) {\n\tvar ret = false;\n\tif ( onErrorFnPrev ) {\n\t\tret = onErrorFnPrev( error, filePath, linerNr );\n\t}\n\n\t// Treat return value as window.onerror itself does,\n\t// Only do our handling if not suppressed.\n\tif ( ret !== true ) {\n\t\tif ( QUnit.config.current ) {\n\t\t\tif ( QUnit.config.current.ignoreGlobalErrors ) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\tQUnit.pushFailure( error, filePath + \":\" + linerNr );\n\t\t} else {\n\t\t\tQUnit.test( \"global failure\", extend( function() {\n\t\t\t\tQUnit.pushFailure( error, filePath + \":\" + linerNr );\n\t\t\t}, { validTest: validTest } ) );\n\t\t}\n\t\treturn false;\n\t}\n\n\treturn ret;\n};\n\nfunction done() {\n\tconfig.autorun = true;\n\n\t// Log the last module results\n\tif ( config.currentModule ) {\n\t\trunLoggingCallbacks( \"moduleDone\", QUnit, {\n\t\t\tname: config.currentModule,\n\t\t\tfailed: config.moduleStats.bad,\n\t\t\tpassed: config.moduleStats.all - config.moduleStats.bad,\n\t\t\ttotal: config.moduleStats.all\n\t\t});\n\t}\n\tdelete config.previousModule;\n\n\tvar i, key,\n\t\tbanner = id( \"qunit-banner\" ),\n\t\ttests = id( \"qunit-tests\" ),\n\t\truntime = +new Date() - config.started,\n\t\tpassed = config.stats.all - config.stats.bad,\n\t\thtml = [\n\t\t\t\"Tests completed in \",\n\t\t\truntime,\n\t\t\t\" milliseconds.<br/>\",\n\t\t\t\"<span class='passed'>\",\n\t\t\tpassed,\n\t\t\t\"</span> assertions of <span class='total'>\",\n\t\t\tconfig.stats.all,\n\t\t\t\"</span> passed, <span class='failed'>\",\n\t\t\tconfig.stats.bad,\n\t\t\t\"</span> failed.\"\n\t\t].join( \"\" );\n\n\tif ( banner ) {\n\t\tbanner.className = ( config.stats.bad ? \"qunit-fail\" : \"qunit-pass\" );\n\t}\n\n\tif ( tests ) {\n\t\tid( \"qunit-testresult\" ).innerHTML = html;\n\t}\n\n\tif ( config.altertitle && typeof document !== \"undefined\" && document.title ) {\n\t\t// show ✖ for good, ✔ for bad suite result in title\n\t\t// use escape sequences in case file gets loaded with non-utf-8-charset\n\t\tdocument.title = [\n\t\t\t( config.stats.bad ? \"\\u2716\" : \"\\u2714\" ),\n\t\t\tdocument.title.replace( /^[\\u2714\\u2716] /i, \"\" )\n\t\t].join( \" \" );\n\t}\n\n\t// clear own sessionStorage items if all tests passed\n\tif ( config.reorder && defined.sessionStorage && config.stats.bad === 0 ) {\n\t\t// `key` & `i` initialized at top of scope\n\t\tfor ( i = 0; i < sessionStorage.length; i++ ) {\n\t\t\tkey = sessionStorage.key( i++ );\n\t\t\tif ( key.indexOf( \"qunit-test-\" ) === 0 ) {\n\t\t\t\tsessionStorage.removeItem( key );\n\t\t\t}\n\t\t}\n\t}\n\n\t// scroll back to top to show results\n\tif ( window.scrollTo ) {\n\t\twindow.scrollTo(0, 0);\n\t}\n\n\trunLoggingCallbacks( \"done\", QUnit, {\n\t\tfailed: config.stats.bad,\n\t\tpassed: passed,\n\t\ttotal: config.stats.all,\n\t\truntime: runtime\n\t});\n}\n\n/** @return Boolean: true if this test should be ran */\nfunction validTest( test ) {\n\tvar include,\n\t\tfilter = config.filter && config.filter.toLowerCase(),\n\t\tmodule = config.module && config.module.toLowerCase(),\n\t\tfullName = (test.module + \": \" + test.testName).toLowerCase();\n\n\t// Internally-generated tests are always valid\n\tif ( test.callback && test.callback.validTest === validTest ) {\n\t\tdelete test.callback.validTest;\n\t\treturn true;\n\t}\n\n\tif ( config.testNumber ) {\n\t\treturn test.testNumber === config.testNumber;\n\t}\n\n\tif ( module && ( !test.module || test.module.toLowerCase() !== module ) ) {\n\t\treturn false;\n\t}\n\n\tif ( !filter ) {\n\t\treturn true;\n\t}\n\n\tinclude = filter.charAt( 0 ) !== \"!\";\n\tif ( !include ) {\n\t\tfilter = filter.slice( 1 );\n\t}\n\n\t// If the filter matches, we need to honour include\n\tif ( fullName.indexOf( filter ) !== -1 ) {\n\t\treturn include;\n\t}\n\n\t// Otherwise, do the opposite\n\treturn !include;\n}\n\n// so far supports only Firefox, Chrome and Opera (buggy), Safari (for real exceptions)\n// Later Safari and IE10 are supposed to support error.stack as well\n// See also https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error/Stack\nfunction extractStacktrace( e, offset ) {\n\toffset = offset === undefined ? 3 : offset;\n\n\tvar stack, include, i;\n\n\tif ( e.stacktrace ) {\n\t\t// Opera\n\t\treturn e.stacktrace.split( \"\\n\" )[ offset + 3 ];\n\t} else if ( e.stack ) {\n\t\t// Firefox, Chrome\n\t\tstack = e.stack.split( \"\\n\" );\n\t\tif (/^error$/i.test( stack[0] ) ) {\n\t\t\tstack.shift();\n\t\t}\n\t\tif ( fileName ) {\n\t\t\tinclude = [];\n\t\t\tfor ( i = offset; i < stack.length; i++ ) {\n\t\t\t\tif ( stack[ i ].indexOf( fileName ) !== -1 ) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tinclude.push( stack[ i ] );\n\t\t\t}\n\t\t\tif ( include.length ) {\n\t\t\t\treturn include.join( \"\\n\" );\n\t\t\t}\n\t\t}\n\t\treturn stack[ offset ];\n\t} else if ( e.sourceURL ) {\n\t\t// Safari, PhantomJS\n\t\t// hopefully one day Safari provides actual stacktraces\n\t\t// exclude useless self-reference for generated Error objects\n\t\tif ( /qunit.js$/.test( e.sourceURL ) ) {\n\t\t\treturn;\n\t\t}\n\t\t// for actual exceptions, this is useful\n\t\treturn e.sourceURL + \":\" + e.line;\n\t}\n}\nfunction sourceFromStacktrace( offset ) {\n\ttry {\n\t\tthrow new Error();\n\t} catch ( e ) {\n\t\treturn extractStacktrace( e, offset );\n\t}\n}\n\n/**\n * Escape text for attribute or text content.\n */\nfunction escapeText( s ) {\n\tif ( !s ) {\n\t\treturn \"\";\n\t}\n\ts = s + \"\";\n\t// Both single quotes and double quotes (for attributes)\n\treturn s.replace( /['\"<>&]/g, function( s ) {\n\t\tswitch( s ) {\n\t\t\tcase \"'\":\n\t\t\t\treturn \"&#039;\";\n\t\t\tcase \"\\\"\":\n\t\t\t\treturn \"&quot;\";\n\t\t\tcase \"<\":\n\t\t\t\treturn \"&lt;\";\n\t\t\tcase \">\":\n\t\t\t\treturn \"&gt;\";\n\t\t\tcase \"&\":\n\t\t\t\treturn \"&amp;\";\n\t\t}\n\t});\n}\n\nfunction synchronize( callback, last ) {\n\tconfig.queue.push( callback );\n\n\tif ( config.autorun && !config.blocking ) {\n\t\tprocess( last );\n\t}\n}\n\nfunction process( last ) {\n\tfunction next() {\n\t\tprocess( last );\n\t}\n\tvar start = new Date().getTime();\n\tconfig.depth = config.depth ? config.depth + 1 : 1;\n\n\twhile ( config.queue.length && !config.blocking ) {\n\t\tif ( !defined.setTimeout || config.updateRate <= 0 || ( ( new Date().getTime() - start ) < config.updateRate ) ) {\n\t\t\tconfig.queue.shift()();\n\t\t} else {\n\t\t\tsetTimeout( next, 13 );\n\t\t\tbreak;\n\t\t}\n\t}\n\tconfig.depth--;\n\tif ( last && !config.blocking && !config.queue.length && config.depth === 0 ) {\n\t\tdone();\n\t}\n}\n\nfunction saveGlobal() {\n\tconfig.pollution = [];\n\n\tif ( config.noglobals ) {\n\t\tfor ( var key in window ) {\n\t\t\tif ( hasOwn.call( window, key ) ) {\n\t\t\t\t// in Opera sometimes DOM element ids show up here, ignore them\n\t\t\t\tif ( /^qunit-test-output/.test( key ) ) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tconfig.pollution.push( key );\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunction checkPollution() {\n\tvar newGlobals,\n\t\tdeletedGlobals,\n\t\told = config.pollution;\n\n\tsaveGlobal();\n\n\tnewGlobals = diff( config.pollution, old );\n\tif ( newGlobals.length > 0 ) {\n\t\tQUnit.pushFailure( \"Introduced global variable(s): \" + newGlobals.join(\", \") );\n\t}\n\n\tdeletedGlobals = diff( old, config.pollution );\n\tif ( deletedGlobals.length > 0 ) {\n\t\tQUnit.pushFailure( \"Deleted global variable(s): \" + deletedGlobals.join(\", \") );\n\t}\n}\n\n// returns a new Array with the elements that are in a but not in b\nfunction diff( a, b ) {\n\tvar i, j,\n\t\tresult = a.slice();\n\n\tfor ( i = 0; i < result.length; i++ ) {\n\t\tfor ( j = 0; j < b.length; j++ ) {\n\t\t\tif ( result[i] === b[j] ) {\n\t\t\t\tresult.splice( i, 1 );\n\t\t\t\ti--;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\treturn result;\n}\n\nfunction extend( a, b ) {\n\tfor ( var prop in b ) {\n\t\tif ( hasOwn.call( b, prop ) ) {\n\t\t\t// Avoid \"Member not found\" error in IE8 caused by messing with window.constructor\n\t\t\tif ( !( prop === \"constructor\" && a === window ) ) {\n\t\t\t\tif ( b[ prop ] === undefined ) {\n\t\t\t\t\tdelete a[ prop ];\n\t\t\t\t} else {\n\t\t\t\t\ta[ prop ] = b[ prop ];\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn a;\n}\n\n/**\n * @param {HTMLElement} elem\n * @param {string} type\n * @param {Function} fn\n */\nfunction addEvent( elem, type, fn ) {\n\t// Standards-based browsers\n\tif ( elem.addEventListener ) {\n\t\telem.addEventListener( type, fn, false );\n\t// IE\n\t} else {\n\t\telem.attachEvent( \"on\" + type, fn );\n\t}\n}\n\n/**\n * @param {Array|NodeList} elems\n * @param {string} type\n * @param {Function} fn\n */\nfunction addEvents( elems, type, fn ) {\n\tvar i = elems.length;\n\twhile ( i-- ) {\n\t\taddEvent( elems[i], type, fn );\n\t}\n}\n\nfunction hasClass( elem, name ) {\n\treturn (\" \" + elem.className + \" \").indexOf(\" \" + name + \" \") > -1;\n}\n\nfunction addClass( elem, name ) {\n\tif ( !hasClass( elem, name ) ) {\n\t\telem.className += (elem.className ? \" \" : \"\") + name;\n\t}\n}\n\nfunction removeClass( elem, name ) {\n\tvar set = \" \" + elem.className + \" \";\n\t// Class name may appear multiple times\n\twhile ( set.indexOf(\" \" + name + \" \") > -1 ) {\n\t\tset = set.replace(\" \" + name + \" \" , \" \");\n\t}\n\t// If possible, trim it for prettiness, but not necessarily\n\telem.className = typeof set.trim === \"function\" ? set.trim() : set.replace(/^\\s+|\\s+$/g, \"\");\n}\n\nfunction id( name ) {\n\treturn !!( typeof document !== \"undefined\" && document && document.getElementById ) &&\n\t\tdocument.getElementById( name );\n}\n\nfunction registerLoggingCallback( key ) {\n\treturn function( callback ) {\n\t\tconfig[key].push( callback );\n\t};\n}\n\n// Supports deprecated method of completely overwriting logging callbacks\nfunction runLoggingCallbacks( key, scope, args ) {\n\tvar i, callbacks;\n\tif ( QUnit.hasOwnProperty( key ) ) {\n\t\tQUnit[ key ].call(scope, args );\n\t} else {\n\t\tcallbacks = config[ key ];\n\t\tfor ( i = 0; i < callbacks.length; i++ ) {\n\t\t\tcallbacks[ i ].call( scope, args );\n\t\t}\n\t}\n}\n\n// Test for equality any JavaScript type.\n// Author: Philippe Rathé <prathe@gmail.com>\nQUnit.equiv = (function() {\n\n\t// Call the o related callback with the given arguments.\n\tfunction bindCallbacks( o, callbacks, args ) {\n\t\tvar prop = QUnit.objectType( o );\n\t\tif ( prop ) {\n\t\t\tif ( QUnit.objectType( callbacks[ prop ] ) === \"function\" ) {\n\t\t\t\treturn callbacks[ prop ].apply( callbacks, args );\n\t\t\t} else {\n\t\t\t\treturn callbacks[ prop ]; // or undefined\n\t\t\t}\n\t\t}\n\t}\n\n\t// the real equiv function\n\tvar innerEquiv,\n\t\t// stack to decide between skip/abort functions\n\t\tcallers = [],\n\t\t// stack to avoiding loops from circular referencing\n\t\tparents = [],\n\t\tparentsB = [],\n\n\t\tgetProto = Object.getPrototypeOf || function ( obj ) {\n\t\t\t/*jshint camelcase:false */\n\t\t\treturn obj.__proto__;\n\t\t},\n\t\tcallbacks = (function () {\n\n\t\t\t// for string, boolean, number and null\n\t\t\tfunction useStrictEquality( b, a ) {\n\t\t\t\t/*jshint eqeqeq:false */\n\t\t\t\tif ( b instanceof a.constructor || a instanceof b.constructor ) {\n\t\t\t\t\t// to catch short annotation VS 'new' annotation of a\n\t\t\t\t\t// declaration\n\t\t\t\t\t// e.g. var i = 1;\n\t\t\t\t\t// var j = new Number(1);\n\t\t\t\t\treturn a == b;\n\t\t\t\t} else {\n\t\t\t\t\treturn a === b;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\t\"string\": useStrictEquality,\n\t\t\t\t\"boolean\": useStrictEquality,\n\t\t\t\t\"number\": useStrictEquality,\n\t\t\t\t\"null\": useStrictEquality,\n\t\t\t\t\"undefined\": useStrictEquality,\n\n\t\t\t\t\"nan\": function( b ) {\n\t\t\t\t\treturn isNaN( b );\n\t\t\t\t},\n\n\t\t\t\t\"date\": function( b, a ) {\n\t\t\t\t\treturn QUnit.objectType( b ) === \"date\" && a.valueOf() === b.valueOf();\n\t\t\t\t},\n\n\t\t\t\t\"regexp\": function( b, a ) {\n\t\t\t\t\treturn QUnit.objectType( b ) === \"regexp\" &&\n\t\t\t\t\t\t// the regex itself\n\t\t\t\t\t\ta.source === b.source &&\n\t\t\t\t\t\t// and its modifiers\n\t\t\t\t\t\ta.global === b.global &&\n\t\t\t\t\t\t// (gmi) ...\n\t\t\t\t\t\ta.ignoreCase === b.ignoreCase &&\n\t\t\t\t\t\ta.multiline === b.multiline &&\n\t\t\t\t\t\ta.sticky === b.sticky;\n\t\t\t\t},\n\n\t\t\t\t// - skip when the property is a method of an instance (OOP)\n\t\t\t\t// - abort otherwise,\n\t\t\t\t// initial === would have catch identical references anyway\n\t\t\t\t\"function\": function() {\n\t\t\t\t\tvar caller = callers[callers.length - 1];\n\t\t\t\t\treturn caller !== Object && typeof caller !== \"undefined\";\n\t\t\t\t},\n\n\t\t\t\t\"array\": function( b, a ) {\n\t\t\t\t\tvar i, j, len, loop, aCircular, bCircular;\n\n\t\t\t\t\t// b could be an object literal here\n\t\t\t\t\tif ( QUnit.objectType( b ) !== \"array\" ) {\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\n\t\t\t\t\tlen = a.length;\n\t\t\t\t\tif ( len !== b.length ) {\n\t\t\t\t\t\t// safe and faster\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\n\t\t\t\t\t// track reference to avoid circular references\n\t\t\t\t\tparents.push( a );\n\t\t\t\t\tparentsB.push( b );\n\t\t\t\t\tfor ( i = 0; i < len; i++ ) {\n\t\t\t\t\t\tloop = false;\n\t\t\t\t\t\tfor ( j = 0; j < parents.length; j++ ) {\n\t\t\t\t\t\t\taCircular = parents[j] === a[i];\n\t\t\t\t\t\t\tbCircular = parentsB[j] === b[i];\n\t\t\t\t\t\t\tif ( aCircular || bCircular ) {\n\t\t\t\t\t\t\t\tif ( a[i] === b[i] || aCircular && bCircular ) {\n\t\t\t\t\t\t\t\t\tloop = true;\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tparents.pop();\n\t\t\t\t\t\t\t\t\tparentsB.pop();\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}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif ( !loop && !innerEquiv(a[i], b[i]) ) {\n\t\t\t\t\t\t\tparents.pop();\n\t\t\t\t\t\t\tparentsB.pop();\n\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tparents.pop();\n\t\t\t\t\tparentsB.pop();\n\t\t\t\t\treturn true;\n\t\t\t\t},\n\n\t\t\t\t\"object\": function( b, a ) {\n\t\t\t\t\t/*jshint forin:false */\n\t\t\t\t\tvar i, j, loop, aCircular, bCircular,\n\t\t\t\t\t\t// Default to true\n\t\t\t\t\t\teq = true,\n\t\t\t\t\t\taProperties = [],\n\t\t\t\t\t\tbProperties = [];\n\n\t\t\t\t\t// comparing constructors is more strict than using\n\t\t\t\t\t// instanceof\n\t\t\t\t\tif ( a.constructor !== b.constructor ) {\n\t\t\t\t\t\t// Allow objects with no prototype to be equivalent to\n\t\t\t\t\t\t// objects with Object as their constructor.\n\t\t\t\t\t\tif ( !(( getProto(a) === null && getProto(b) === Object.prototype ) ||\n\t\t\t\t\t\t\t( getProto(b) === null && getProto(a) === Object.prototype ) ) ) {\n\t\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// stack constructor before traversing properties\n\t\t\t\t\tcallers.push( a.constructor );\n\n\t\t\t\t\t// track reference to avoid circular references\n\t\t\t\t\tparents.push( a );\n\t\t\t\t\tparentsB.push( b );\n\n\t\t\t\t\t// be strict: don't ensure hasOwnProperty and go deep\n\t\t\t\t\tfor ( i in a ) {\n\t\t\t\t\t\tloop = false;\n\t\t\t\t\t\tfor ( j = 0; j < parents.length; j++ ) {\n\t\t\t\t\t\t\taCircular = parents[j] === a[i];\n\t\t\t\t\t\t\tbCircular = parentsB[j] === b[i];\n\t\t\t\t\t\t\tif ( aCircular || bCircular ) {\n\t\t\t\t\t\t\t\tif ( a[i] === b[i] || aCircular && bCircular ) {\n\t\t\t\t\t\t\t\t\tloop = true;\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\teq = false;\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\taProperties.push(i);\n\t\t\t\t\t\tif ( !loop && !innerEquiv(a[i], b[i]) ) {\n\t\t\t\t\t\t\teq = false;\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\tparents.pop();\n\t\t\t\t\tparentsB.pop();\n\t\t\t\t\tcallers.pop(); // unstack, we are done\n\n\t\t\t\t\tfor ( i in b ) {\n\t\t\t\t\t\tbProperties.push( i ); // collect b's properties\n\t\t\t\t\t}\n\n\t\t\t\t\t// Ensures identical properties name\n\t\t\t\t\treturn eq && innerEquiv( aProperties.sort(), bProperties.sort() );\n\t\t\t\t}\n\t\t\t};\n\t\t}());\n\n\tinnerEquiv = function() { // can take multiple arguments\n\t\tvar args = [].slice.apply( arguments );\n\t\tif ( args.length < 2 ) {\n\t\t\treturn true; // end transition\n\t\t}\n\n\t\treturn (function( a, b ) {\n\t\t\tif ( a === b ) {\n\t\t\t\treturn true; // catch the most you can\n\t\t\t} else if ( a === null || b === null || typeof a === \"undefined\" ||\n\t\t\t\t\ttypeof b === \"undefined\" ||\n\t\t\t\t\tQUnit.objectType(a) !== QUnit.objectType(b) ) {\n\t\t\t\treturn false; // don't lose time with error prone cases\n\t\t\t} else {\n\t\t\t\treturn bindCallbacks(a, callbacks, [ b, a ]);\n\t\t\t}\n\n\t\t\t// apply transition with (1..n) arguments\n\t\t}( args[0], args[1] ) && innerEquiv.apply( this, args.splice(1, args.length - 1 )) );\n\t};\n\n\treturn innerEquiv;\n}());\n\n/**\n * jsDump Copyright (c) 2008 Ariel Flesler - aflesler(at)gmail(dot)com |\n * http://flesler.blogspot.com Licensed under BSD\n * (http://www.opensource.org/licenses/bsd-license.php) Date: 5/15/2008\n *\n * @projectDescription Advanced and extensible data dumping for Javascript.\n * @version 1.0.0\n * @author Ariel Flesler\n * @link {http://flesler.blogspot.com/2008/05/jsdump-pretty-dump-of-any-javascript.html}\n */\nQUnit.jsDump = (function() {\n\tfunction quote( str ) {\n\t\treturn \"\\\"\" + str.toString().replace( /\"/g, \"\\\\\\\"\" ) + \"\\\"\";\n\t}\n\tfunction literal( o ) {\n\t\treturn o + \"\";\n\t}\n\tfunction join( pre, arr, post ) {\n\t\tvar s = jsDump.separator(),\n\t\t\tbase = jsDump.indent(),\n\t\t\tinner = jsDump.indent(1);\n\t\tif ( arr.join ) {\n\t\t\tarr = arr.join( \",\" + s + inner );\n\t\t}\n\t\tif ( !arr ) {\n\t\t\treturn pre + post;\n\t\t}\n\t\treturn [ pre, inner + arr, base + post ].join(s);\n\t}\n\tfunction array( arr, stack ) {\n\t\tvar i = arr.length, ret = new Array(i);\n\t\tthis.up();\n\t\twhile ( i-- ) {\n\t\t\tret[i] = this.parse( arr[i] , undefined , stack);\n\t\t}\n\t\tthis.down();\n\t\treturn join( \"[\", ret, \"]\" );\n\t}\n\n\tvar reName = /^function (\\w+)/,\n\t\tjsDump = {\n\t\t\t// type is used mostly internally, you can fix a (custom)type in advance\n\t\t\tparse: function( obj, type, stack ) {\n\t\t\t\tstack = stack || [ ];\n\t\t\t\tvar inStack, res,\n\t\t\t\t\tparser = this.parsers[ type || this.typeOf(obj) ];\n\n\t\t\t\ttype = typeof parser;\n\t\t\t\tinStack = inArray( obj, stack );\n\n\t\t\t\tif ( inStack !== -1 ) {\n\t\t\t\t\treturn \"recursion(\" + (inStack - stack.length) + \")\";\n\t\t\t\t}\n\t\t\t\tif ( type === \"function\" )  {\n\t\t\t\t\tstack.push( obj );\n\t\t\t\t\tres = parser.call( this, obj, stack );\n\t\t\t\t\tstack.pop();\n\t\t\t\t\treturn res;\n\t\t\t\t}\n\t\t\t\treturn ( type === \"string\" ) ? parser : this.parsers.error;\n\t\t\t},\n\t\t\ttypeOf: function( obj ) {\n\t\t\t\tvar type;\n\t\t\t\tif ( obj === null ) {\n\t\t\t\t\ttype = \"null\";\n\t\t\t\t} else if ( typeof obj === \"undefined\" ) {\n\t\t\t\t\ttype = \"undefined\";\n\t\t\t\t} else if ( QUnit.is( \"regexp\", obj) ) {\n\t\t\t\t\ttype = \"regexp\";\n\t\t\t\t} else if ( QUnit.is( \"date\", obj) ) {\n\t\t\t\t\ttype = \"date\";\n\t\t\t\t} else if ( QUnit.is( \"function\", obj) ) {\n\t\t\t\t\ttype = \"function\";\n\t\t\t\t} else if ( typeof obj.setInterval !== undefined && typeof obj.document !== \"undefined\" && typeof obj.nodeType === \"undefined\" ) {\n\t\t\t\t\ttype = \"window\";\n\t\t\t\t} else if ( obj.nodeType === 9 ) {\n\t\t\t\t\ttype = \"document\";\n\t\t\t\t} else if ( obj.nodeType ) {\n\t\t\t\t\ttype = \"node\";\n\t\t\t\t} else if (\n\t\t\t\t\t// native arrays\n\t\t\t\t\ttoString.call( obj ) === \"[object Array]\" ||\n\t\t\t\t\t// NodeList objects\n\t\t\t\t\t( typeof obj.length === \"number\" && typeof obj.item !== \"undefined\" && ( obj.length ? obj.item(0) === obj[0] : ( obj.item( 0 ) === null && typeof obj[0] === \"undefined\" ) ) )\n\t\t\t\t) {\n\t\t\t\t\ttype = \"array\";\n\t\t\t\t} else if ( obj.constructor === Error.prototype.constructor ) {\n\t\t\t\t\ttype = \"error\";\n\t\t\t\t} else {\n\t\t\t\t\ttype = typeof obj;\n\t\t\t\t}\n\t\t\t\treturn type;\n\t\t\t},\n\t\t\tseparator: function() {\n\t\t\t\treturn this.multiline ?\tthis.HTML ? \"<br />\" : \"\\n\" : this.HTML ? \"&nbsp;\" : \" \";\n\t\t\t},\n\t\t\t// extra can be a number, shortcut for increasing-calling-decreasing\n\t\t\tindent: function( extra ) {\n\t\t\t\tif ( !this.multiline ) {\n\t\t\t\t\treturn \"\";\n\t\t\t\t}\n\t\t\t\tvar chr = this.indentChar;\n\t\t\t\tif ( this.HTML ) {\n\t\t\t\t\tchr = chr.replace( /\\t/g, \"   \" ).replace( / /g, \"&nbsp;\" );\n\t\t\t\t}\n\t\t\t\treturn new Array( this.depth + ( extra || 0 ) ).join(chr);\n\t\t\t},\n\t\t\tup: function( a ) {\n\t\t\t\tthis.depth += a || 1;\n\t\t\t},\n\t\t\tdown: function( a ) {\n\t\t\t\tthis.depth -= a || 1;\n\t\t\t},\n\t\t\tsetParser: function( name, parser ) {\n\t\t\t\tthis.parsers[name] = parser;\n\t\t\t},\n\t\t\t// The next 3 are exposed so you can use them\n\t\t\tquote: quote,\n\t\t\tliteral: literal,\n\t\t\tjoin: join,\n\t\t\t//\n\t\t\tdepth: 1,\n\t\t\t// This is the list of parsers, to modify them, use jsDump.setParser\n\t\t\tparsers: {\n\t\t\t\twindow: \"[Window]\",\n\t\t\t\tdocument: \"[Document]\",\n\t\t\t\terror: function(error) {\n\t\t\t\t\treturn \"Error(\\\"\" + error.message + \"\\\")\";\n\t\t\t\t},\n\t\t\t\tunknown: \"[Unknown]\",\n\t\t\t\t\"null\": \"null\",\n\t\t\t\t\"undefined\": \"undefined\",\n\t\t\t\t\"function\": function( fn ) {\n\t\t\t\t\tvar ret = \"function\",\n\t\t\t\t\t\t// functions never have name in IE\n\t\t\t\t\t\tname = \"name\" in fn ? fn.name : (reName.exec(fn) || [])[1];\n\n\t\t\t\t\tif ( name ) {\n\t\t\t\t\t\tret += \" \" + name;\n\t\t\t\t\t}\n\t\t\t\t\tret += \"( \";\n\n\t\t\t\t\tret = [ ret, QUnit.jsDump.parse( fn, \"functionArgs\" ), \"){\" ].join( \"\" );\n\t\t\t\t\treturn join( ret, QUnit.jsDump.parse(fn,\"functionCode\" ), \"}\" );\n\t\t\t\t},\n\t\t\t\tarray: array,\n\t\t\t\tnodelist: array,\n\t\t\t\t\"arguments\": array,\n\t\t\t\tobject: function( map, stack ) {\n\t\t\t\t\t/*jshint forin:false */\n\t\t\t\t\tvar ret = [ ], keys, key, val, i;\n\t\t\t\t\tQUnit.jsDump.up();\n\t\t\t\t\tkeys = [];\n\t\t\t\t\tfor ( key in map ) {\n\t\t\t\t\t\tkeys.push( key );\n\t\t\t\t\t}\n\t\t\t\t\tkeys.sort();\n\t\t\t\t\tfor ( i = 0; i < keys.length; i++ ) {\n\t\t\t\t\t\tkey = keys[ i ];\n\t\t\t\t\t\tval = map[ key ];\n\t\t\t\t\t\tret.push( QUnit.jsDump.parse( key, \"key\" ) + \": \" + QUnit.jsDump.parse( val, undefined, stack ) );\n\t\t\t\t\t}\n\t\t\t\t\tQUnit.jsDump.down();\n\t\t\t\t\treturn join( \"{\", ret, \"}\" );\n\t\t\t\t},\n\t\t\t\tnode: function( node ) {\n\t\t\t\t\tvar len, i, val,\n\t\t\t\t\t\topen = QUnit.jsDump.HTML ? \"&lt;\" : \"<\",\n\t\t\t\t\t\tclose = QUnit.jsDump.HTML ? \"&gt;\" : \">\",\n\t\t\t\t\t\ttag = node.nodeName.toLowerCase(),\n\t\t\t\t\t\tret = open + tag,\n\t\t\t\t\t\tattrs = node.attributes;\n\n\t\t\t\t\tif ( attrs ) {\n\t\t\t\t\t\tfor ( i = 0, len = attrs.length; i < len; i++ ) {\n\t\t\t\t\t\t\tval = attrs[i].nodeValue;\n\t\t\t\t\t\t\t// IE6 includes all attributes in .attributes, even ones not explicitly set.\n\t\t\t\t\t\t\t// Those have values like undefined, null, 0, false, \"\" or \"inherit\".\n\t\t\t\t\t\t\tif ( val && val !== \"inherit\" ) {\n\t\t\t\t\t\t\t\tret += \" \" + attrs[i].nodeName + \"=\" + QUnit.jsDump.parse( val, \"attribute\" );\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\tret += close;\n\n\t\t\t\t\t// Show content of TextNode or CDATASection\n\t\t\t\t\tif ( node.nodeType === 3 || node.nodeType === 4 ) {\n\t\t\t\t\t\tret += node.nodeValue;\n\t\t\t\t\t}\n\n\t\t\t\t\treturn ret + open + \"/\" + tag + close;\n\t\t\t\t},\n\t\t\t\t// function calls it internally, it's the arguments part of the function\n\t\t\t\tfunctionArgs: function( fn ) {\n\t\t\t\t\tvar args,\n\t\t\t\t\t\tl = fn.length;\n\n\t\t\t\t\tif ( !l ) {\n\t\t\t\t\t\treturn \"\";\n\t\t\t\t\t}\n\n\t\t\t\t\targs = new Array(l);\n\t\t\t\t\twhile ( l-- ) {\n\t\t\t\t\t\t// 97 is 'a'\n\t\t\t\t\t\targs[l] = String.fromCharCode(97+l);\n\t\t\t\t\t}\n\t\t\t\t\treturn \" \" + args.join( \", \" ) + \" \";\n\t\t\t\t},\n\t\t\t\t// object calls it internally, the key part of an item in a map\n\t\t\t\tkey: quote,\n\t\t\t\t// function calls it internally, it's the content of the function\n\t\t\t\tfunctionCode: \"[code]\",\n\t\t\t\t// node calls it internally, it's an html attribute value\n\t\t\t\tattribute: quote,\n\t\t\t\tstring: quote,\n\t\t\t\tdate: quote,\n\t\t\t\tregexp: literal,\n\t\t\t\tnumber: literal,\n\t\t\t\t\"boolean\": literal\n\t\t\t},\n\t\t\t// if true, entities are escaped ( <, >, \\t, space and \\n )\n\t\t\tHTML: false,\n\t\t\t// indentation unit\n\t\t\tindentChar: \"  \",\n\t\t\t// if true, items in a collection, are separated by a \\n, else just a space.\n\t\t\tmultiline: true\n\t\t};\n\n\treturn jsDump;\n}());\n\n// from jquery.js\nfunction inArray( elem, array ) {\n\tif ( array.indexOf ) {\n\t\treturn array.indexOf( elem );\n\t}\n\n\tfor ( var i = 0, length = array.length; i < length; i++ ) {\n\t\tif ( array[ i ] === elem ) {\n\t\t\treturn i;\n\t\t}\n\t}\n\n\treturn -1;\n}\n\n/*\n * Javascript Diff Algorithm\n *  By John Resig (http://ejohn.org/)\n *  Modified by Chu Alan \"sprite\"\n *\n * Released under the MIT license.\n *\n * More Info:\n *  http://ejohn.org/projects/javascript-diff-algorithm/\n *\n * Usage: QUnit.diff(expected, actual)\n *\n * QUnit.diff( \"the quick brown fox jumped over\", \"the quick fox jumps over\" ) == \"the  quick <del>brown </del> fox <del>jumped </del><ins>jumps </ins> over\"\n */\nQUnit.diff = (function() {\n\t/*jshint eqeqeq:false, eqnull:true */\n\tfunction diff( o, n ) {\n\t\tvar i,\n\t\t\tns = {},\n\t\t\tos = {};\n\n\t\tfor ( i = 0; i < n.length; i++ ) {\n\t\t\tif ( !hasOwn.call( ns, n[i] ) ) {\n\t\t\t\tns[ n[i] ] = {\n\t\t\t\t\trows: [],\n\t\t\t\t\to: null\n\t\t\t\t};\n\t\t\t}\n\t\t\tns[ n[i] ].rows.push( i );\n\t\t}\n\n\t\tfor ( i = 0; i < o.length; i++ ) {\n\t\t\tif ( !hasOwn.call( os, o[i] ) ) {\n\t\t\t\tos[ o[i] ] = {\n\t\t\t\t\trows: [],\n\t\t\t\t\tn: null\n\t\t\t\t};\n\t\t\t}\n\t\t\tos[ o[i] ].rows.push( i );\n\t\t}\n\n\t\tfor ( i in ns ) {\n\t\t\tif ( hasOwn.call( ns, i ) ) {\n\t\t\t\tif ( ns[i].rows.length === 1 && hasOwn.call( os, i ) && os[i].rows.length === 1 ) {\n\t\t\t\t\tn[ ns[i].rows[0] ] = {\n\t\t\t\t\t\ttext: n[ ns[i].rows[0] ],\n\t\t\t\t\t\trow: os[i].rows[0]\n\t\t\t\t\t};\n\t\t\t\t\to[ os[i].rows[0] ] = {\n\t\t\t\t\t\ttext: o[ os[i].rows[0] ],\n\t\t\t\t\t\trow: ns[i].rows[0]\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 < n.length - 1; i++ ) {\n\t\t\tif ( n[i].text != null && n[ i + 1 ].text == null && n[i].row + 1 < o.length && o[ n[i].row + 1 ].text == null &&\n\t\t\t\t\t\tn[ i + 1 ] == o[ n[i].row + 1 ] ) {\n\n\t\t\t\tn[ i + 1 ] = {\n\t\t\t\t\ttext: n[ i + 1 ],\n\t\t\t\t\trow: n[i].row + 1\n\t\t\t\t};\n\t\t\t\to[ n[i].row + 1 ] = {\n\t\t\t\t\ttext: o[ n[i].row + 1 ],\n\t\t\t\t\trow: i + 1\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\n\t\tfor ( i = n.length - 1; i > 0; i-- ) {\n\t\t\tif ( n[i].text != null && n[ i - 1 ].text == null && n[i].row > 0 && o[ n[i].row - 1 ].text == null &&\n\t\t\t\t\t\tn[ i - 1 ] == o[ n[i].row - 1 ]) {\n\n\t\t\t\tn[ i - 1 ] = {\n\t\t\t\t\ttext: n[ i - 1 ],\n\t\t\t\t\trow: n[i].row - 1\n\t\t\t\t};\n\t\t\t\to[ n[i].row - 1 ] = {\n\t\t\t\t\ttext: o[ n[i].row - 1 ],\n\t\t\t\t\trow: i - 1\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\n\t\treturn {\n\t\t\to: o,\n\t\t\tn: n\n\t\t};\n\t}\n\n\treturn function( o, n ) {\n\t\to = o.replace( /\\s+$/, \"\" );\n\t\tn = n.replace( /\\s+$/, \"\" );\n\n\t\tvar i, pre,\n\t\t\tstr = \"\",\n\t\t\tout = diff( o === \"\" ? [] : o.split(/\\s+/), n === \"\" ? [] : n.split(/\\s+/) ),\n\t\t\toSpace = o.match(/\\s+/g),\n\t\t\tnSpace = n.match(/\\s+/g);\n\n\t\tif ( oSpace == null ) {\n\t\t\toSpace = [ \" \" ];\n\t\t}\n\t\telse {\n\t\t\toSpace.push( \" \" );\n\t\t}\n\n\t\tif ( nSpace == null ) {\n\t\t\tnSpace = [ \" \" ];\n\t\t}\n\t\telse {\n\t\t\tnSpace.push( \" \" );\n\t\t}\n\n\t\tif ( out.n.length === 0 ) {\n\t\t\tfor ( i = 0; i < out.o.length; i++ ) {\n\t\t\t\tstr += \"<del>\" + out.o[i] + oSpace[i] + \"</del>\";\n\t\t\t}\n\t\t}\n\t\telse {\n\t\t\tif ( out.n[0].text == null ) {\n\t\t\t\tfor ( n = 0; n < out.o.length && out.o[n].text == null; n++ ) {\n\t\t\t\t\tstr += \"<del>\" + out.o[n] + oSpace[n] + \"</del>\";\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfor ( i = 0; i < out.n.length; i++ ) {\n\t\t\t\tif (out.n[i].text == null) {\n\t\t\t\t\tstr += \"<ins>\" + out.n[i] + nSpace[i] + \"</ins>\";\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\t// `pre` initialized at top of scope\n\t\t\t\t\tpre = \"\";\n\n\t\t\t\t\tfor ( n = out.n[i].row + 1; n < out.o.length && out.o[n].text == null; n++ ) {\n\t\t\t\t\t\tpre += \"<del>\" + out.o[n] + oSpace[n] + \"</del>\";\n\t\t\t\t\t}\n\t\t\t\t\tstr += \" \" + out.n[i].text + nSpace[i] + pre;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn str;\n\t};\n}());\n\n// for CommonJS environments, export everything\nif ( typeof exports !== \"undefined\" ) {\n\textend( exports, QUnit.constructor.prototype );\n}\n\n// get at whatever the global object is, like window in browsers\n}( (function() {return this;}.call()) ));\n"
  },
  {
    "path": "flowable-ui-web/task/libs/sizzle_1.10.16/test/unit/extending.js",
    "content": "module(\"extending\", { teardown: moduleTeardown });\n\ntest(\"custom pseudos\", function() {\n\texpect( 6 );\n\n\tSizzle.selectors.filters.foundation = Sizzle.selectors.filters.root;\n\tdeepEqual( Sizzle(\":foundation\"), [ document.documentElement ], \"Copy element filter with new name\" );\n\tdelete Sizzle.selectors.filters.foundation;\n\n\tSizzle.selectors.setFilters.primary = Sizzle.selectors.setFilters.first;\n\tt( \"Copy set filter with new name\", \"div:primary\", [\"qunit\"] );\n\tdelete Sizzle.selectors.setFilters.primary;\n\n\tSizzle.selectors.filters.aristotlean = Sizzle.selectors.createPseudo(function() {\n\t\treturn function( elem ) {\n\t\t\treturn !!elem.id;\n\t\t};\n\t});\n\tt( \"Custom element filter\", \"#foo :aristotlean\", [ \"sndp\", \"en\", \"yahoo\", \"sap\", \"anchor2\", \"simon\" ] );\n\tdelete Sizzle.selectors.filters.aristotlean;\n\n\tSizzle.selectors.filters.endswith = Sizzle.selectors.createPseudo(function( text ) {\n\t\treturn function( elem ) {\n\t\t\treturn Sizzle.getText( elem ).slice( -text.length ) === text;\n\t\t};\n\t});\n\tt( \"Custom element filter with argument\", \"a:endswith(ogle)\", [\"google\"] );\n\tdelete Sizzle.selectors.filters.endswith;\n\n\tSizzle.selectors.setFilters.second = Sizzle.selectors.createPseudo(function() {\n\t\treturn Sizzle.selectors.createPseudo(function( seed, matches ) {\n\t\t\tif ( seed[1] ) {\n\t\t\t\tmatches[1] = seed[1];\n\t\t\t\tseed[1] = false;\n\t\t\t}\n\t\t});\n\t});\n\tt( \"Custom set filter\", \"#qunit-fixture p:second\", [\"ap\"] );\n\tdelete Sizzle.selectors.filters.second;\n\n\tSizzle.selectors.setFilters.slice = Sizzle.selectors.createPseudo(function( argument ) {\n\t\tvar bounds = argument.split(\":\");\n\t\treturn Sizzle.selectors.createPseudo(function( seed, matches ) {\n\t\t\tvar i = bounds[1];\n\n\t\t\t// Match elements found at the specified indexes\n\t\t\twhile ( --i >= bounds[0] ) {\n\t\t\t\tif ( seed[i] ) {\n\t\t\t\t\tmatches[i] = seed[i];\n\t\t\t\t\tseed[i] = false;\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t});\n\tt( \"Custom set filter with argument\", \"#qunit-fixture p:slice(1:3)\", [ \"ap\", \"sndp\" ] );\n\tdelete Sizzle.selectors.filters.slice;\n});\n\ntest(\"backwards-compatible custom pseudos\", function() {\n\texpect( 3 );\n\n\tSizzle.selectors.filters.icontains = function( elem, i, match ) {\n\t\treturn Sizzle.getText( elem ).toLowerCase().indexOf( (match[3] || \"\").toLowerCase() ) > -1;\n\t};\n\tt( \"Custom element filter with argument\", \"a:icontains(THIS BLOG ENTRY)\", [\"simon1\"] );\n\tdelete Sizzle.selectors.filters.icontains;\n\n\tSizzle.selectors.setFilters.podium = function( elements, argument ) {\n\t\tvar count = argument == null || argument === \"\" ? 3 : +argument;\n\t\treturn elements.slice( 0, count );\n\t};\n\t// Using TAG as the first token here forces this setMatcher into a fail state\n\t// Where the descendent combinator was lost\n\tt( \"Custom setFilter\", \"form#form :PODIUM\", [\"label-for\", \"text1\", \"text2\"] );\n\tt( \"Custom setFilter with argument\", \"#form input:Podium(1)\", [\"text1\"] );\n\tdelete Sizzle.selectors.setFilters.podium;\n});\n\ntest(\"custom attribute getters\", function() {\n\texpect( 2 );\n\n\tvar original = Sizzle.selectors.attrHandle.hreflang,\n\t\tselector = \"a:contains('mark')[hreflang='http://diveintomark.org/en']\";\n\n\tSizzle.selectors.attrHandle.hreflang = function( elem, name ) {\n\t\tvar href = elem.getAttribute(\"href\"),\n\t\t\tlang = elem.getAttribute( name );\n\t\treturn lang && ( href + lang );\n\t};\n\n\tdeepEqual( Sizzle(selector, createWithFriesXML()), [], \"Custom attrHandle (preferred document)\" );\n\tt( \"Custom attrHandle (preferred document)\", selector, [\"mark\"] );\n\n\tSizzle.selectors.attrHandle.hreflang = original;\n});\n"
  },
  {
    "path": "flowable-ui-web/task/libs/sizzle_1.10.16/test/unit/selector.js",
    "content": "module(\"selector\", { teardown: moduleTeardown });\n\n// #### NOTE: ####\n// jQuery should not be used in this module\n// except for DOM manipulation\n// If jQuery is mandatory for the selection, move the test to jquery/test/unit/selector.js\n// Use t() or Sizzle()\n// ###############\n\n/*\n\t======== QUnit Reference ========\n\thttp://docs.jquery.com/QUnit\n\n\tTest methods:\n\t\texpect(numAssertions)\n\t\tstop()\n\t\tstart()\n\t\t\tnote: QUnit's eventual addition of an argument to stop/start is ignored in this test suite\n\t\t\tso that start and stop can be passed as callbacks without worrying about\n\t\t\t\ttheir parameters\n\tTest assertions:\n\t\tok(value, [message])\n\t\tequal(actual, expected, [message])\n\t\tnotEqual(actual, expected, [message])\n\t\tdeepEqual(actual, expected, [message])\n\t\tnotDeepEqual(actual, expected, [message])\n\t\tstrictEqual(actual, expected, [message])\n\t\tnotStrictEqual(actual, expected, [message])\n\t\traises(block, [expected], [message])\n\n\t======== testinit.js reference ========\n\tSee data/testinit.js\n\n\tq(...);\n\t\tReturns an array of elements with the given IDs\n\t\t@example q(\"main\", \"foo\", \"bar\") => [<div id=\"main\">, <span id=\"foo\">, <input id=\"bar\">]\n\n\tt( testName, selector, [ \"array\", \"of\", \"ids\" ] );\n\t\tAsserts that a select matches the given IDs\n\t\t@example t(\"Check for something\", \"//[a]\", [\"foo\", \"baar\"]);\n\n\turl( \"some/url.php\" );\n\t\tAdd random number to url to stop caching\n\t\t@example url(\"data/test.html\") => \"data/test.html?10538358428943\"\n\t\t@example url(\"data/test.php?foo=bar\") => \"data/test.php?foo=bar&10538358345554\"\n*/\n\ntest(\"element\", function() {\n\texpect( 39 );\n\n\tvar form, all, good, i, obj1, lengthtest,\n\t\tsiblingTest, siblingNext, iframe, iframeDoc, html;\n\n\tequal( Sizzle(\"\").length, 0, \"Empty selector returns an empty array\" );\n\tdeepEqual( Sizzle(\"div\", document.createTextNode(\"\")), [], \"Text element as context fails silently\" );\n\tform = document.getElementById(\"form\");\n\tok( !Sizzle.matchesSelector( form, \"\" ), \"Empty string passed to matchesSelector does not match\" );\n\tequal( Sizzle(\" \").length, 0, \"Empty selector returns an empty array\" );\n\tequal( Sizzle(\"\\t\").length, 0, \"Empty selector returns an empty array\" );\n\n\tok( Sizzle(\"*\").length >= 30, \"Select all\" );\n\tall = Sizzle(\"*\");\n\tgood = true;\n\tfor ( i = 0; i < all.length; i++ ) {\n\t\tif ( all[i].nodeType === 8 ) {\n\t\t\tgood = false;\n\t\t}\n\t}\n\tok( good, \"Select all elements, no comment nodes\" );\n\tt( \"Element Selector\", \"html\", [\"html\"] );\n\tt( \"Element Selector\", \"body\", [\"body\"] );\n\tt( \"Element Selector\", \"#qunit-fixture p\", [\"firstp\",\"ap\",\"sndp\",\"en\",\"sap\",\"first\"] );\n\n\tt( \"Leading space\", \" #qunit-fixture p\", [\"firstp\",\"ap\",\"sndp\",\"en\",\"sap\",\"first\"] );\n\tt( \"Leading tab\", \"\\t#qunit-fixture p\", [\"firstp\",\"ap\",\"sndp\",\"en\",\"sap\",\"first\"] );\n\tt( \"Leading carriage return\", \"\\r#qunit-fixture p\", [\"firstp\",\"ap\",\"sndp\",\"en\",\"sap\",\"first\"] );\n\tt( \"Leading line feed\", \"\\n#qunit-fixture p\", [\"firstp\",\"ap\",\"sndp\",\"en\",\"sap\",\"first\"] );\n\tt( \"Leading form feed\", \"\\f#qunit-fixture p\", [\"firstp\",\"ap\",\"sndp\",\"en\",\"sap\",\"first\"] );\n\tt( \"Trailing space\", \"#qunit-fixture p \", [\"firstp\",\"ap\",\"sndp\",\"en\",\"sap\",\"first\"] );\n\tt( \"Trailing tab\", \"#qunit-fixture p\\t\", [\"firstp\",\"ap\",\"sndp\",\"en\",\"sap\",\"first\"] );\n\tt( \"Trailing carriage return\", \"#qunit-fixture p\\r\", [\"firstp\",\"ap\",\"sndp\",\"en\",\"sap\",\"first\"] );\n\tt( \"Trailing line feed\", \"#qunit-fixture p\\n\", [\"firstp\",\"ap\",\"sndp\",\"en\",\"sap\",\"first\"] );\n\tt( \"Trailing form feed\", \"#qunit-fixture p\\f\", [\"firstp\",\"ap\",\"sndp\",\"en\",\"sap\",\"first\"] );\n\n\tt( \"Parent Element\", \"dl ol\", [\"empty\", \"listWithTabIndex\"] );\n\tt( \"Parent Element (non-space descendant combinator)\", \"dl\\tol\", [\"empty\", \"listWithTabIndex\"] );\n\tobj1 = document.getElementById(\"object1\");\n\tequal( Sizzle(\"param\", obj1).length, 2, \"Object/param as context\" );\n\n\tdeepEqual( Sizzle(\"select\", form), q(\"select1\",\"select2\",\"select3\",\"select4\",\"select5\"), \"Finding selects with a context.\" );\n\n\t// Check for unique-ness and sort order\n\tdeepEqual( Sizzle(\"p, div p\"), Sizzle(\"p\"), \"Check for duplicates: p, div p\" );\n\n\tt( \"Checking sort order\", \"h2, h1\", [\"qunit-header\", \"qunit-banner\", \"qunit-userAgent\"] );\n\tt( \"Checking sort order\", \"h2:first, h1:first\", [\"qunit-header\", \"qunit-banner\"] );\n\tt( \"Checking sort order\", \"#qunit-fixture p, #qunit-fixture p a\", [\"firstp\", \"simon1\", \"ap\", \"google\", \"groups\", \"anchor1\", \"mark\", \"sndp\", \"en\", \"yahoo\", \"sap\", \"anchor2\", \"simon\", \"first\"] );\n\n\t// Test Conflict ID\n\tlengthtest = document.getElementById(\"lengthtest\");\n\tdeepEqual( Sizzle(\"#idTest\", lengthtest), q(\"idTest\"), \"Finding element with id of ID.\" );\n\tdeepEqual( Sizzle(\"[name='id']\", lengthtest), q(\"idTest\"), \"Finding element with id of ID.\" );\n\tdeepEqual( Sizzle(\"input[id='idTest']\", lengthtest), q(\"idTest\"), \"Finding elements with id of ID.\" );\n\n\tsiblingTest = document.getElementById(\"siblingTest\");\n\tdeepEqual( Sizzle(\"div em\", siblingTest), [], \"Element-rooted QSA does not select based on document context\" );\n\tdeepEqual( Sizzle(\"div em, div em, div em:not(div em)\", siblingTest), [], \"Element-rooted QSA does not select based on document context\" );\n\tdeepEqual( Sizzle(\"div em, em\\\\,\", siblingTest), [], \"Escaped commas do not get treated with an id in element-rooted QSA\" );\n\n\tsiblingNext = document.getElementById(\"siblingnext\");\n\tdocument.createDocumentFragment().appendChild( siblingTest );\n\tdeepEqual( Sizzle( \"em + :not(:has(*)):not(:empty), foo\", siblingTest ), [ siblingNext ],\n\t\t\"Non-qSA path correctly sets detached context for sibling selectors (jQuery #14351)\" );\n\n\tiframe = document.getElementById(\"iframe\"),\n\t\tiframeDoc = iframe.contentDocument || iframe.contentWindow.document;\n\tiframeDoc.open();\n\tiframeDoc.write(\"<body><p id='foo'>bar</p></body>\");\n\tiframeDoc.close();\n\tdeepEqual(\n\t\tSizzle( \"p:contains(bar)\", iframeDoc ),\n\t\t[ iframeDoc.getElementById(\"foo\") ],\n\t\t\"Other document as context\"\n\t);\n\n\thtml = \"\";\n\tfor ( i = 0; i < 100; i++ ) {\n\t\thtml = \"<div>\" + html + \"</div>\";\n\t}\n\thtml = jQuery( html ).appendTo( document.body );\n\tok( !!Sizzle(\"body div div div\").length, \"No stack or performance problems with large amounts of descendents\" );\n\tok( !!Sizzle(\"body>div div div\").length, \"No stack or performance problems with large amounts of descendents\" );\n\thtml.remove();\n\n\t// Real use case would be using .watch in browsers with window.watch (see Issue #157)\n\tq(\"qunit-fixture\")[0].appendChild( document.createElement(\"toString\") ).id = \"toString\";\n\tt( \"Element name matches Object.prototype property\", \"toString#toString\", [\"toString\"] );\n});\n\ntest(\"XML Document Selectors\", function() {\n\tvar xml = createWithFriesXML();\n\texpect( 11 );\n\n\tequal( Sizzle(\"foo_bar\", xml).length, 1, \"Element Selector with underscore\" );\n\tequal( Sizzle(\".component\", xml).length, 1, \"Class selector\" );\n\tequal( Sizzle(\"[class*=component]\", xml).length, 1, \"Attribute selector for class\" );\n\tequal( Sizzle(\"property[name=prop2]\", xml).length, 1, \"Attribute selector with name\" );\n\tequal( Sizzle(\"[name=prop2]\", xml).length, 1, \"Attribute selector with name\" );\n\tequal( Sizzle(\"#seite1\", xml).length, 1, \"Attribute selector with ID\" );\n\tequal( Sizzle(\"component#seite1\", xml).length, 1, \"Attribute selector with ID\" );\n\tequal( Sizzle.matches( \"#seite1\", Sizzle(\"component\", xml) ).length, 1, \"Attribute selector filter with ID\" );\n\tequal( Sizzle(\"meta property thing\", xml).length, 2, \"Descendent selector and dir caching\" );\n\tok( Sizzle.matchesSelector( xml.lastChild, \"soap\\\\:Envelope\" ), \"Check for namespaced element\" );\n\n\txml = jQuery.parseXML(\"<?xml version='1.0' encoding='UTF-8'?><root><elem id='1'/></root>\");\n\tequal( Sizzle( \"elem:not(:has(*))\", xml ).length, 1,\n\t\t\"Non-qSA path correctly handles numeric ids (jQuery #14142)\" );\n});\n\ntest(\"broken\", function() {\n\texpect( 26 );\n\n\tvar attrbad,\n\t\tbroken = function( name, selector ) {\n\t\t\traises(function() {\n\t\t\t\t// Setting context to null here somehow avoids QUnit's window.error handling\n\t\t\t\t// making the e & e.message correct\n\t\t\t\t// For whatever reason, without this,\n\t\t\t\t// Sizzle.error will be called but no error will be seen in oldIE\n\t\t\t\tSizzle.call( null, selector );\n\t\t\t}, function( e ) {\n\t\t\t\treturn e.message.indexOf(\"Syntax error\") >= 0;\n\t\t\t}, name + \": \" + selector );\n\t\t};\n\n\tbroken( \"Broken Selector\", \"[\" );\n\tbroken( \"Broken Selector\", \"(\" );\n\tbroken( \"Broken Selector\", \"{\" );\n\tbroken( \"Broken Selector\", \"<\" );\n\tbroken( \"Broken Selector\", \"()\" );\n\tbroken( \"Broken Selector\", \"<>\" );\n\tbroken( \"Broken Selector\", \"{}\" );\n\tbroken( \"Broken Selector\", \",\" );\n\tbroken( \"Broken Selector\", \",a\" );\n\tbroken( \"Broken Selector\", \"a,\" );\n\t// Hangs on IE 9 if regular expression is inefficient\n\tbroken( \"Broken Selector\", \"[id=012345678901234567890123456789\");\n\tbroken( \"Doesn't exist\", \":visble\" );\n\tbroken( \"Nth-child\", \":nth-child\" );\n\t// Sigh again. IE 9 thinks this is also a real selector\n\t// not super critical that we fix this case\n\t//broken( \"Nth-child\", \":nth-child(-)\" );\n\t// Sigh. WebKit thinks this is a real selector in qSA\n\t// They've already fixed this and it'll be coming into\n\t// current browsers soon. Currently, Safari 5.0 still has this problem\n\t// broken( \"Nth-child\", \":nth-child(asdf)\", [] );\n\tbroken( \"Nth-child\", \":nth-child(2n+-0)\" );\n\tbroken( \"Nth-child\", \":nth-child(2+0)\" );\n\tbroken( \"Nth-child\", \":nth-child(- 1n)\" );\n\tbroken( \"Nth-child\", \":nth-child(-1 n)\" );\n\tbroken( \"First-child\", \":first-child(n)\" );\n\tbroken( \"Last-child\", \":last-child(n)\" );\n\tbroken( \"Only-child\", \":only-child(n)\" );\n\tbroken( \"Nth-last-last-child\", \":nth-last-last-child(1)\" );\n\tbroken( \"First-last-child\", \":first-last-child\" );\n\tbroken( \"Last-last-child\", \":last-last-child\" );\n\tbroken( \"Only-last-child\", \":only-last-child\" );\n\n\t// Make sure attribute value quoting works correctly. See: #6093\n\tattrbad = jQuery(\"<input type='hidden' value='2' name='foo.baz' id='attrbad1'/><input type='hidden' value='2' name='foo[baz]' id='attrbad2'/>\").appendTo(\"#qunit-fixture\");\n\n\tbroken( \"Attribute not escaped\", \"input[name=foo.baz]\", [] );\n\t// Shouldn't be matching those inner brackets\n\tbroken( \"Attribute not escaped\", \"input[name=foo[baz]]\", [] );\n});\n\ntest(\"id\", function() {\n\texpect( 34 );\n\n\tvar fiddle, a;\n\n\tt( \"ID Selector\", \"#body\", [\"body\"] );\n\tt( \"ID Selector w/ Element\", \"body#body\", [\"body\"] );\n\tt( \"ID Selector w/ Element\", \"ul#first\", [] );\n\tt( \"ID selector with existing ID descendant\", \"#firstp #simon1\", [\"simon1\"] );\n\tt( \"ID selector with non-existant descendant\", \"#firstp #foobar\", [] );\n\tt( \"ID selector using UTF8\", \"#台北Táiběi\", [\"台北Táiběi\"] );\n\tt( \"Multiple ID selectors using UTF8\", \"#台北Táiběi, #台北\", [\"台北Táiběi\",\"台北\"] );\n\tt( \"Descendant ID selector using UTF8\", \"div #台北\", [\"台北\"] );\n\tt( \"Child ID selector using UTF8\", \"form > #台北\", [\"台北\"] );\n\n\tt( \"Escaped ID\", \"#foo\\\\:bar\", [\"foo:bar\"] );\n\tt( \"Escaped ID with descendent\", \"#foo\\\\:bar span:not(:input)\", [\"foo_descendent\"] );\n\tt( \"Escaped ID\", \"#test\\\\.foo\\\\[5\\\\]bar\", [\"test.foo[5]bar\"] );\n\tt( \"Descendant escaped ID\", \"div #foo\\\\:bar\", [\"foo:bar\"] );\n\tt( \"Descendant escaped ID\", \"div #test\\\\.foo\\\\[5\\\\]bar\", [\"test.foo[5]bar\"] );\n\tt( \"Child escaped ID\", \"form > #foo\\\\:bar\", [\"foo:bar\"] );\n\tt( \"Child escaped ID\", \"form > #test\\\\.foo\\\\[5\\\\]bar\", [\"test.foo[5]bar\"] );\n\n\tfiddle = jQuery(\"<div id='fiddle\\\\Foo'><span id='fiddleSpan'></span></div>\").appendTo(\"#qunit-fixture\");\n\tdeepEqual( Sizzle( \"> span\", Sizzle(\"#fiddle\\\\\\\\Foo\")[0] ), q([ \"fiddleSpan\" ]), \"Escaped ID as context\" );\n\tfiddle.remove();\n\n\tt( \"ID Selector, child ID present\", \"#form > #radio1\", [\"radio1\"] ); // bug #267\n\tt( \"ID Selector, not an ancestor ID\", \"#form #first\", [] );\n\tt( \"ID Selector, not a child ID\", \"#form > #option1a\", [] );\n\n\tt( \"All Children of ID\", \"#foo > *\", [\"sndp\", \"en\", \"sap\"] );\n\tt( \"All Children of ID with no children\", \"#firstUL > *\", [] );\n\n\tequal( Sizzle(\"#tName1\")[0].id, \"tName1\", \"ID selector with same value for a name attribute\" );\n\tt( \"ID selector non-existing but name attribute on an A tag\",         \"#tName2\",      [] );\n\tt( \"Leading ID selector non-existing but name attribute on an A tag\", \"#tName2 span\", [] );\n\tt( \"Leading ID selector existing, retrieving the child\",              \"#tName1 span\", [\"tName1-span\"] );\n\tequal( Sizzle(\"div > div #tName1\")[0].id, Sizzle(\"#tName1-span\")[0].parentNode.id, \"Ending with ID\" );\n\n\ta = jQuery(\"<a id='backslash\\\\foo'></a>\").appendTo(\"#qunit-fixture\");\n\tt( \"ID Selector contains backslash\", \"#backslash\\\\\\\\foo\", [\"backslash\\\\foo\"] );\n\n\tt( \"ID Selector on Form with an input that has a name of 'id'\", \"#lengthtest\", [\"lengthtest\"] );\n\n\tt( \"ID selector with non-existant ancestor\", \"#asdfasdf #foobar\", [] ); // bug #986\n\n\tdeepEqual( Sizzle(\"div#form\", document.body), [], \"ID selector within the context of another element\" );\n\n\tt( \"Underscore ID\", \"#types_all\", [\"types_all\"] );\n\tt( \"Dash ID\", \"#qunit-fixture\", [\"qunit-fixture\"] );\n\n\tt( \"ID with weird characters in it\", \"#name\\\\+value\", [\"name+value\"] );\n});\n\ntest(\"class\", function() {\n\texpect( 26 );\n\n\tt( \"Class Selector\", \".blog\", [\"mark\",\"simon\"] );\n\tt( \"Class Selector\", \".GROUPS\", [\"groups\"] );\n\tt( \"Class Selector\", \".blog.link\", [\"simon\"] );\n\tt( \"Class Selector w/ Element\", \"a.blog\", [\"mark\",\"simon\"] );\n\tt( \"Parent Class Selector\", \"p .blog\", [\"mark\",\"simon\"] );\n\n\tt( \"Class selector using UTF8\", \".台北Táiběi\", [\"utf8class1\"] );\n\t//t( \"Class selector using UTF8\", \".台北\", [\"utf8class1\",\"utf8class2\"] );\n\tt( \"Class selector using UTF8\", \".台北Táiběi.台北\", [\"utf8class1\"] );\n\tt( \"Class selector using UTF8\", \".台北Táiběi, .台北\", [\"utf8class1\",\"utf8class2\"] );\n\tt( \"Descendant class selector using UTF8\", \"div .台北Táiběi\", [\"utf8class1\"] );\n\tt( \"Child class selector using UTF8\", \"form > .台北Táiběi\", [\"utf8class1\"] );\n\n\tt( \"Escaped Class\", \".foo\\\\:bar\", [\"foo:bar\"] );\n\tt( \"Escaped Class\", \".test\\\\.foo\\\\[5\\\\]bar\", [\"test.foo[5]bar\"] );\n\tt( \"Descendant escaped Class\", \"div .foo\\\\:bar\", [\"foo:bar\"] );\n\tt( \"Descendant escaped Class\", \"div .test\\\\.foo\\\\[5\\\\]bar\", [\"test.foo[5]bar\"] );\n\tt( \"Child escaped Class\", \"form > .foo\\\\:bar\", [\"foo:bar\"] );\n\tt( \"Child escaped Class\", \"form > .test\\\\.foo\\\\[5\\\\]bar\", [\"test.foo[5]bar\"] );\n\n\tvar div = document.createElement(\"div\");\n\tdiv.innerHTML = \"<div class='test e'></div><div class='test'></div>\";\n\tdeepEqual( Sizzle(\".e\", div), [ div.firstChild ], \"Finding a second class.\" );\n\n\tdiv.lastChild.className = \"e\";\n\n\tdeepEqual( Sizzle(\".e\", div), [ div.firstChild, div.lastChild ], \"Finding a modified class.\" );\n\n\tok( !Sizzle.matchesSelector( div, \".null\"), \".null does not match an element with no class\" );\n\tok( !Sizzle.matchesSelector( div.firstChild, \".null div\"), \".null does not match an element with no class\" );\n\tdiv.className = \"null\";\n\tok( Sizzle.matchesSelector( div, \".null\"), \".null matches element with class 'null'\" );\n\tok( Sizzle.matchesSelector( div.firstChild, \".null div\"), \"caching system respects DOM changes\" );\n\tok( !Sizzle.matchesSelector( document, \".foo\" ), \"testing class on document doesn't error\" );\n\tok( !Sizzle.matchesSelector( window, \".foo\" ), \"testing class on window doesn't error\" );\n\n\tdiv.lastChild.className += \" hasOwnProperty toString\";\n\tdeepEqual( Sizzle(\".e.hasOwnProperty.toString\", div), [ div.lastChild ], \"Classes match Object.prototype properties\" );\n\n\tdiv = jQuery(\"<div><svg width='200' height='250' version='1.1' xmlns='http://www.w3.org/2000/svg'><rect x='10' y='10' width='30' height='30' class='foo'></rect></svg></div>\")[0];\n\tequal( Sizzle(\".foo\", div).length, 1, \"Class selector against SVG\" );\n});\n\ntest(\"name\", function() {\n\texpect( 14 );\n\n\tvar form;\n\n\tt( \"Name selector\", \"input[name=action]\", [\"text1\"] );\n\tt( \"Name selector with single quotes\", \"input[name='action']\", [\"text1\"] );\n\tt( \"Name selector with double quotes\", \"input[name=\\\"action\\\"]\", [\"text1\"] );\n\n\tt( \"Name selector non-input\", \"[name=example]\", [\"name-is-example\"] );\n\tt( \"Name selector non-input\", \"[name=div]\", [\"name-is-div\"] );\n\tt( \"Name selector non-input\", \"*[name=iframe]\", [\"iframe\"] );\n\n\tt( \"Name selector for grouped input\", \"input[name='types[]']\", [\"types_all\", \"types_anime\", \"types_movie\"] );\n\n\tform = document.getElementById(\"form\");\n\tdeepEqual( Sizzle(\"input[name=action]\", form), q(\"text1\"), \"Name selector within the context of another element\" );\n\tdeepEqual( Sizzle(\"input[name='foo[bar]']\", form), q(\"hidden2\"), \"Name selector for grouped form element within the context of another element\" );\n\n\tform = jQuery(\"<form><input name='id'/></form>\").appendTo(\"body\");\n\tequal( Sizzle(\"input\", form[0]).length, 1, \"Make sure that rooted queries on forms (with possible expandos) work.\" );\n\n\tform.remove();\n\n\tt( \"Find elements that have similar IDs\", \"[name=tName1]\", [\"tName1ID\"] );\n\tt( \"Find elements that have similar IDs\", \"[name=tName2]\", [\"tName2ID\"] );\n\tt( \"Find elements that have similar IDs\", \"#tName2ID\", [\"tName2ID\"] );\n\n\tt( \"Case-sensitivity\", \"[name=tname1]\", [] );\n});\n\ntest(\"multiple\", function() {\n\texpect(6);\n\n\tt( \"Comma Support\", \"h2, #qunit-fixture p\", [\"qunit-banner\",\"qunit-userAgent\",\"firstp\",\"ap\",\"sndp\",\"en\",\"sap\",\"first\"] );\n\tt( \"Comma Support\", \"h2 , #qunit-fixture p\", [\"qunit-banner\",\"qunit-userAgent\",\"firstp\",\"ap\",\"sndp\",\"en\",\"sap\",\"first\"] );\n\tt( \"Comma Support\", \"h2 , #qunit-fixture p\", [\"qunit-banner\",\"qunit-userAgent\",\"firstp\",\"ap\",\"sndp\",\"en\",\"sap\",\"first\"] );\n\tt( \"Comma Support\", \"h2,#qunit-fixture p\", [\"qunit-banner\",\"qunit-userAgent\",\"firstp\",\"ap\",\"sndp\",\"en\",\"sap\",\"first\"] );\n\tt( \"Comma Support\", \"h2,#qunit-fixture p \", [\"qunit-banner\",\"qunit-userAgent\",\"firstp\",\"ap\",\"sndp\",\"en\",\"sap\",\"first\"] );\n\tt( \"Comma Support\", \"h2\\t,\\r#qunit-fixture p\\n\", [\"qunit-banner\",\"qunit-userAgent\",\"firstp\",\"ap\",\"sndp\",\"en\",\"sap\",\"first\"] );\n});\n\ntest(\"child and adjacent\", function() {\n\texpect( 42 );\n\n\tvar siblingFirst, en, nothiddendiv;\n\n\tt( \"Child\", \"p > a\", [\"simon1\",\"google\",\"groups\",\"mark\",\"yahoo\",\"simon\"] );\n\tt( \"Child\", \"p> a\", [\"simon1\",\"google\",\"groups\",\"mark\",\"yahoo\",\"simon\"] );\n\tt( \"Child\", \"p >a\", [\"simon1\",\"google\",\"groups\",\"mark\",\"yahoo\",\"simon\"] );\n\tt( \"Child\", \"p>a\", [\"simon1\",\"google\",\"groups\",\"mark\",\"yahoo\",\"simon\"] );\n\tt( \"Child w/ Class\", \"p > a.blog\", [\"mark\",\"simon\"] );\n\tt( \"All Children\", \"code > *\", [\"anchor1\",\"anchor2\"] );\n\tt( \"All Grandchildren\", \"p > * > *\", [\"anchor1\",\"anchor2\"] );\n\tt( \"Adjacent\", \"#qunit-fixture a + a\", [\"groups\", \"tName2ID\"] );\n\tt( \"Adjacent\", \"#qunit-fixture a +a\", [\"groups\", \"tName2ID\"] );\n\tt( \"Adjacent\", \"#qunit-fixture a+ a\", [\"groups\", \"tName2ID\"] );\n\tt( \"Adjacent\", \"#qunit-fixture a+a\", [\"groups\", \"tName2ID\"] );\n\tt( \"Adjacent\", \"p + p\", [\"ap\",\"en\",\"sap\"] );\n\tt( \"Adjacent\", \"p#firstp + p\", [\"ap\"] );\n\tt( \"Adjacent\", \"p[lang=en] + p\", [\"sap\"] );\n\tt( \"Adjacent\", \"a.GROUPS + code + a\", [\"mark\"] );\n\tt( \"Comma, Child, and Adjacent\", \"#qunit-fixture a + a, code > a\", [\"groups\",\"anchor1\",\"anchor2\",\"tName2ID\"] );\n\tt( \"Element Preceded By\", \"#qunit-fixture p ~ div\", [\"foo\", \"nothiddendiv\", \"moretests\",\"tabindex-tests\", \"liveHandlerOrder\", \"siblingTest\"] );\n\tt( \"Element Preceded By\", \"#first ~ div\", [\"moretests\",\"tabindex-tests\", \"liveHandlerOrder\", \"siblingTest\"] );\n\tt( \"Element Preceded By\", \"#groups ~ a\", [\"mark\"] );\n\tt( \"Element Preceded By\", \"#length ~ input\", [\"idTest\"] );\n\tt( \"Element Preceded By\", \"#siblingfirst ~ em\", [\"siblingnext\", \"siblingthird\"] );\n\tt( \"Element Preceded By (multiple)\", \"#siblingTest em ~ em ~ em ~ span\", [\"siblingspan\"] );\n\tt( \"Element Preceded By, Containing\", \"#liveHandlerOrder ~ div em:contains('1')\", [\"siblingfirst\"] );\n\n\tsiblingFirst = document.getElementById(\"siblingfirst\");\n\n\tdeepEqual( Sizzle(\"~ em\", siblingFirst), q(\"siblingnext\", \"siblingthird\"), \"Element Preceded By with a context.\" );\n\tdeepEqual( Sizzle(\"+ em\", siblingFirst), q(\"siblingnext\"), \"Element Directly Preceded By with a context.\" );\n\tdeepEqual( Sizzle(\"~ em:first\", siblingFirst), q(\"siblingnext\"), \"Element Preceded By positional with a context.\" );\n\n\ten = document.getElementById(\"en\");\n\tdeepEqual( Sizzle(\"+ p, a\", en), q(\"yahoo\", \"sap\"), \"Compound selector with context, beginning with sibling test.\" );\n\tdeepEqual( Sizzle(\"a, + p\", en), q(\"yahoo\", \"sap\"), \"Compound selector with context, containing sibling test.\" );\n\n\tt( \"Multiple combinators selects all levels\", \"#siblingTest em *\", [\"siblingchild\", \"siblinggrandchild\", \"siblinggreatgrandchild\"] );\n\tt( \"Multiple combinators selects all levels\", \"#siblingTest > em *\", [\"siblingchild\", \"siblinggrandchild\", \"siblinggreatgrandchild\"] );\n\tt( \"Multiple sibling combinators doesn't miss general siblings\", \"#siblingTest > em:first-child + em ~ span\", [\"siblingspan\"] );\n\tt( \"Combinators are not skipped when mixing general and specific\", \"#siblingTest > em:contains('x') + em ~ span\", [] );\n\n\tequal( Sizzle(\"#listWithTabIndex\").length, 1, \"Parent div for next test is found via ID (#8310)\" );\n\tequal( Sizzle(\"#listWithTabIndex li:eq(2) ~ li\").length, 1, \"Find by general sibling combinator (#8310)\" );\n\tequal( Sizzle(\"#__sizzle__\").length, 0, \"Make sure the temporary id assigned by sizzle is cleared out (#8310)\" );\n\tequal( Sizzle(\"#listWithTabIndex\").length, 1, \"Parent div for previous test is still found via ID (#8310)\" );\n\n\tt( \"Verify deep class selector\", \"div.blah > p > a\", [] );\n\n\tt( \"No element deep selector\", \"div.foo > span > a\", [] );\n\n\tnothiddendiv = document.getElementById(\"nothiddendiv\");\n\tdeepEqual( Sizzle(\"> :first\", nothiddendiv), q(\"nothiddendivchild\"), \"Verify child context positional selector\" );\n\tdeepEqual( Sizzle(\"> :eq(0)\", nothiddendiv), q(\"nothiddendivchild\"), \"Verify child context positional selector\" );\n\tdeepEqual( Sizzle(\"> *:first\", nothiddendiv), q(\"nothiddendivchild\"), \"Verify child context positional selector\" );\n\n\tt( \"Non-existant ancestors\", \".fototab > .thumbnails > a\", [] );\n});\n\ntest(\"attributes\", function() {\n\texpect( 76 );\n\n\tvar opt, input, attrbad, div;\n\n\tt( \"Attribute Exists\", \"#qunit-fixture a[title]\", [\"google\"] );\n\tt( \"Attribute Exists (case-insensitive)\", \"#qunit-fixture a[TITLE]\", [\"google\"] );\n\tt( \"Attribute Exists\", \"#qunit-fixture *[title]\", [\"google\"] );\n\tt( \"Attribute Exists\", \"#qunit-fixture [title]\", [\"google\"] );\n\tt( \"Attribute Exists\", \"#qunit-fixture a[ title ]\", [\"google\"] );\n\n\tt( \"Boolean attribute exists\", \"#select2 option[selected]\", [\"option2d\"]);\n\tt( \"Boolean attribute equals\", \"#select2 option[selected='selected']\", [\"option2d\"]);\n\n\tt( \"Attribute Equals\", \"#qunit-fixture a[rel='bookmark']\", [\"simon1\"] );\n\tt( \"Attribute Equals\", \"#qunit-fixture a[rel='bookmark']\", [\"simon1\"] );\n\tt( \"Attribute Equals\", \"#qunit-fixture a[rel=bookmark]\", [\"simon1\"] );\n\tt( \"Attribute Equals\", \"#qunit-fixture a[href='http://www.google.com/']\", [\"google\"] );\n\tt( \"Attribute Equals\", \"#qunit-fixture a[ rel = 'bookmark' ]\", [\"simon1\"] );\n\tt( \"Attribute Equals Number\", \"#qunit-fixture option[value=1]\", [\"option1b\",\"option2b\",\"option3b\",\"option4b\",\"option5c\"] );\n\tt( \"Attribute Equals Number\", \"#qunit-fixture li[tabIndex=-1]\", [\"foodWithNegativeTabIndex\"] );\n\n\tdocument.getElementById(\"anchor2\").href = \"#2\";\n\tt( \"href Attribute\", \"p a[href^=#]\", [\"anchor2\"] );\n\tt( \"href Attribute\", \"p a[href*=#]\", [\"simon1\", \"anchor2\"] );\n\n\tt( \"for Attribute\", \"form label[for]\", [\"label-for\"] );\n\tt( \"for Attribute in form\", \"#form [for=action]\", [\"label-for\"] );\n\n\tt( \"Attribute containing []\", \"input[name^='foo[']\", [\"hidden2\"] );\n\tt( \"Attribute containing []\", \"input[name^='foo[bar]']\", [\"hidden2\"] );\n\tt( \"Attribute containing []\", \"input[name*='[bar]']\", [\"hidden2\"] );\n\tt( \"Attribute containing []\", \"input[name$='bar]']\", [\"hidden2\"] );\n\tt( \"Attribute containing []\", \"input[name$='[bar]']\", [\"hidden2\"] );\n\tt( \"Attribute containing []\", \"input[name$='foo[bar]']\", [\"hidden2\"] );\n\tt( \"Attribute containing []\", \"input[name*='foo[bar]']\", [\"hidden2\"] );\n\n\tdeepEqual( Sizzle( \"input[data-comma='0,1']\" ), [ document.getElementById(\"el12087\") ], \"Without context, single-quoted attribute containing ','\" );\n\tdeepEqual( Sizzle( \"input[data-comma=\\\"0,1\\\"]\" ), [ document.getElementById(\"el12087\") ], \"Without context, double-quoted attribute containing ','\" );\n\tdeepEqual( Sizzle( \"input[data-comma='0,1']\", document.getElementById(\"t12087\") ), [ document.getElementById(\"el12087\") ], \"With context, single-quoted attribute containing ','\" );\n\tdeepEqual( Sizzle( \"input[data-comma=\\\"0,1\\\"]\", document.getElementById(\"t12087\") ), [ document.getElementById(\"el12087\") ], \"With context, double-quoted attribute containing ','\" );\n\n\tt( \"Multiple Attribute Equals\", \"#form input[type='radio'], #form input[type='hidden']\", [\"radio1\", \"radio2\", \"hidden1\"] );\n\tt( \"Multiple Attribute Equals\", \"#form input[type='radio'], #form input[type=\\\"hidden\\\"]\", [\"radio1\", \"radio2\", \"hidden1\"] );\n\tt( \"Multiple Attribute Equals\", \"#form input[type='radio'], #form input[type=hidden]\", [\"radio1\", \"radio2\", \"hidden1\"] );\n\n\tt( \"Attribute selector using UTF8\", \"span[lang=中文]\", [\"台北\"] );\n\n\tt( \"Attribute Begins With\", \"a[href ^= 'http://www']\", [\"google\",\"yahoo\"] );\n\tt( \"Attribute Ends With\", \"a[href $= 'org/']\", [\"mark\"] );\n\tt( \"Attribute Contains\", \"a[href *= 'google']\", [\"google\",\"groups\"] );\n\tt( \"Attribute Is Not Equal\", \"#ap a[hreflang!='en']\", [\"google\",\"groups\",\"anchor1\"] );\n\n\topt = document.getElementById(\"option1a\");\n\topt.setAttribute( \"test\", \"\" );\n\n\tok( Sizzle.matchesSelector( opt, \"[id*=option1][type!=checkbox]\" ), \"Attribute Is Not Equal Matches\" );\n\tok( Sizzle.matchesSelector( opt, \"[id*=option1]\" ), \"Attribute With No Quotes Contains Matches\" );\n\tok( Sizzle.matchesSelector( opt, \"[test=]\" ), \"Attribute With No Quotes No Content Matches\" );\n\tok( !Sizzle.matchesSelector( opt, \"[test^='']\" ), \"Attribute with empty string value does not match startsWith selector (^=)\" );\n\tok( Sizzle.matchesSelector( opt, \"[id=option1a]\" ), \"Attribute With No Quotes Equals Matches\" );\n\tok( Sizzle.matchesSelector( document.getElementById(\"simon1\"), \"a[href*=#]\" ), \"Attribute With No Quotes Href Contains Matches\" );\n\n\tt( \"Empty values\", \"#select1 option[value='']\", [\"option1a\"] );\n\tt( \"Empty values\", \"#select1 option[value!='']\", [\"option1b\",\"option1c\",\"option1d\"] );\n\n\tt( \"Select options via :selected\", \"#select1 option:selected\", [\"option1a\"] );\n\tt( \"Select options via :selected\", \"#select2 option:selected\", [\"option2d\"] );\n\tt( \"Select options via :selected\", \"#select3 option:selected\", [\"option3b\", \"option3c\"] );\n\tt( \"Select options via :selected\", \"select[name='select2'] option:selected\", [\"option2d\"] );\n\n\tt( \"Grouped Form Elements\", \"input[name='foo[bar]']\", [\"hidden2\"] );\n\n\tinput = document.getElementById(\"text1\");\n\tinput.title = \"Don't click me\";\n\n\tok( Sizzle.matchesSelector( input, \"input[title=\\\"Don't click me\\\"]\" ), \"Quote within attribute value does not mess up tokenizer\" );\n\n\t// Uncomment if the boolHook is removed\n\t// var check2 = document.getElementById(\"check2\");\n\t// check2.checked = true;\n\t// ok( !Sizzle.matches(\"[checked]\", [ check2 ] ), \"Dynamic boolean attributes match when they should with Sizzle.matches (#11115)\" );\n\n\t// jQuery #12303\n\tinput.setAttribute( \"data-pos\", \":first\" );\n\tok( Sizzle.matchesSelector( input, \"input[data-pos=\\\\:first]\"), \"POS within attribute value is treated as an attribute value\" );\n\tok( Sizzle.matchesSelector( input, \"input[data-pos=':first']\"), \"POS within attribute value is treated as an attribute value\" );\n\tok( Sizzle.matchesSelector( input, \":input[data-pos=':first']\"), \"POS within attribute value after pseudo is treated as an attribute value\" );\n\tinput.removeAttribute(\"data-pos\");\n\n\t// Make sure attribute value quoting works correctly. See jQuery #6093; #6428; #13894\n\t// Use seeded results to bypass querySelectorAll optimizations\n\tattrbad = jQuery(\n\t\t\"<input type='hidden' id='attrbad_space' name='foo bar'/>\" +\n\t\t\"<input type='hidden' id='attrbad_dot' value='2' name='foo.baz'/>\" +\n\t\t\"<input type='hidden' id='attrbad_brackets' value='2' name='foo[baz]'/>\" +\n\t\t\"<input type='hidden' id='attrbad_injection' data-attr='foo_baz&#39;]'/>\" +\n\t\t\"<input type='hidden' id='attrbad_quote' data-attr='&#39;'/>\" +\n\t\t\"<input type='hidden' id='attrbad_backslash' data-attr='&#92;'/>\" +\n\t\t\"<input type='hidden' id='attrbad_backslash_quote' data-attr='&#92;&#39;'/>\" +\n\t\t\"<input type='hidden' id='attrbad_backslash_backslash' data-attr='&#92;&#92;'/>\" +\n\t\t\"<input type='hidden' id='attrbad_unicode' data-attr='&#x4e00;'/>\"\n\t).appendTo(\"#qunit-fixture\").get();\n\n\tt( \"Underscores don't need escaping\", \"input[id=types_all]\", [\"types_all\"] );\n\n\tdeepEqual( Sizzle( \"input[name=foo\\\\ bar]\", null, null, attrbad ), q(\"attrbad_space\"),\n\t\t\"Escaped space\" );\n\tdeepEqual( Sizzle( \"input[name=foo\\\\.baz]\", null, null, attrbad ), q(\"attrbad_dot\"),\n\t\t\"Escaped dot\" );\n\tdeepEqual( Sizzle( \"input[name=foo\\\\[baz\\\\]]\", null, null, attrbad ), q(\"attrbad_brackets\"),\n\t\t\"Escaped brackets\" );\n\tdeepEqual( Sizzle( \"input[data-attr='foo_baz\\\\']']\", null, null, attrbad ), q(\"attrbad_injection\"),\n\t\t\"Escaped quote + right bracket\" );\n\n\tdeepEqual( Sizzle( \"input[data-attr='\\\\'']\", null, null, attrbad ), q(\"attrbad_quote\"),\n\t\t\"Quoted quote\" );\n\tdeepEqual( Sizzle( \"input[data-attr='\\\\\\\\']\", null, null, attrbad ), q(\"attrbad_backslash\"),\n\t\t\"Quoted backslash\" );\n\tdeepEqual( Sizzle( \"input[data-attr='\\\\\\\\\\\\'']\", null, null, attrbad ), q(\"attrbad_backslash_quote\"),\n\t\t\"Quoted backslash quote\" );\n\tdeepEqual( Sizzle( \"input[data-attr='\\\\\\\\\\\\\\\\']\", null, null, attrbad ), q(\"attrbad_backslash_backslash\"),\n\t\t\"Quoted backslash backslash\" );\n\n\tdeepEqual( Sizzle( \"input[data-attr='\\\\5C\\\\\\\\']\", null, null, attrbad ), q(\"attrbad_backslash_backslash\"),\n\t\t\"Quoted backslash backslash (numeric escape)\" );\n\tdeepEqual( Sizzle( \"input[data-attr='\\\\5C \\\\\\\\']\", null, null, attrbad ), q(\"attrbad_backslash_backslash\"),\n\t\t\"Quoted backslash backslash (numeric escape with trailing space)\" );\n\tdeepEqual( Sizzle( \"input[data-attr='\\\\5C\\t\\\\\\\\']\", null, null, attrbad ), q(\"attrbad_backslash_backslash\"),\n\t\t\"Quoted backslash backslash (numeric escape with trailing tab)\" );\n\tdeepEqual( Sizzle( \"input[data-attr='\\\\04e00']\", null, null, attrbad ), q(\"attrbad_unicode\"),\n\t\t\"Long numeric escape (BMP)\" );\n\tdocument.getElementById(\"attrbad_unicode\").setAttribute( \"data-attr\", \"\\uD834\\uDF06A\" );\n\t// It was too much code to fix Safari 5.x Supplemental Plane crashes (see ba5f09fa404379a87370ec905ffa47f8ac40aaa3)\n\t// deepEqual( Sizzle( \"input[data-attr='\\\\01D306A']\", null, null, attrbad ), q(\"attrbad_unicode\"),\n\t// \t\"Long numeric escape (non-BMP)\" );\n\n\tt( \"input[type=text]\", \"#form input[type=text]\", [\"text1\", \"text2\", \"hidden2\", \"name\"] );\n\tt( \"input[type=search]\", \"#form input[type=search]\", [\"search\"] );\n\tt( \"script[src] (jQuery #13777)\", \"#moretests script[src]\", [\"script-src\"] );\n\n\t// #3279\n\tdiv = document.createElement(\"div\");\n\tdiv.innerHTML = \"<div id='foo' xml:test='something'></div>\";\n\n\tdeepEqual( Sizzle( \"[xml\\\\:test]\", div ), [ div.firstChild ], \"Finding by attribute with escaped characters.\" );\n\n\tdiv = document.getElementById(\"foo\");\n\tt( \"Object.prototype property \\\"constructor\\\" (negative)\", \"[constructor]\", [] );\n\tt( \"Gecko Object.prototype property \\\"watch\\\" (negative)\", \"[watch]\", [] );\n\tdiv.setAttribute( \"constructor\", \"foo\" );\n\tdiv.setAttribute( \"watch\", \"bar\" );\n\tt( \"Object.prototype property \\\"constructor\\\"\", \"[constructor='foo']\", [\"foo\"] );\n\tt( \"Gecko Object.prototype property \\\"watch\\\"\", \"[watch='bar']\", [\"foo\"] );\n\n\tt( \"Value attribute is retrieved correctly\", \"input[value=Test]\", [\"text1\", \"text2\"] );\n});\n\ntest(\"pseudo - (parent|empty)\", function() {\n\texpect( 3 );\n\tt( \"Empty\", \"ul:empty\", [\"firstUL\"] );\n\tt( \"Empty with comment node\", \"ol:empty\", [\"empty\"] );\n\tt( \"Is A Parent\", \"#qunit-fixture p:parent\", [\"firstp\",\"ap\",\"sndp\",\"en\",\"sap\",\"first\"] );\n});\n\ntest(\"pseudo - (first|last|only)-(child|of-type)\", function() {\n\texpect( 12 );\n\n\tt( \"First Child\", \"p:first-child\", [\"firstp\",\"sndp\"] );\n\tt( \"First Child (leading id)\", \"#qunit-fixture p:first-child\", [\"firstp\",\"sndp\"] );\n\tt( \"First Child (leading class)\", \".nothiddendiv div:first-child\", [\"nothiddendivchild\"] );\n\tt( \"First Child (case-insensitive)\", \"#qunit-fixture p:FIRST-CHILD\", [\"firstp\",\"sndp\"] );\n\n\tt( \"Last Child\", \"p:last-child\", [\"sap\"] );\n\tt( \"Last Child (leading id)\", \"#qunit-fixture a:last-child\", [\"simon1\",\"anchor1\",\"mark\",\"yahoo\",\"anchor2\",\"simon\",\"liveLink1\",\"liveLink2\"] );\n\n\tt( \"Only Child\", \"#qunit-fixture a:only-child\", [\"simon1\",\"anchor1\",\"yahoo\",\"anchor2\",\"liveLink1\",\"liveLink2\"] );\n\n\tt( \"First-of-type\", \"#qunit-fixture > p:first-of-type\", [\"firstp\"] );\n\tt( \"Last-of-type\", \"#qunit-fixture > p:last-of-type\", [\"first\"] );\n\tt( \"Only-of-type\", \"#qunit-fixture > :only-of-type\", [\"name+value\", \"firstUL\", \"empty\", \"floatTest\", \"iframe\", \"table\"] );\n\n\t// Verify that the child position isn't being cached improperly\n\tvar secondChildren = jQuery(\"p:nth-child(2)\").before(\"<div></div>\");\n\n\tt( \"No longer second child\", \"p:nth-child(2)\", [] );\n\tsecondChildren.prev().remove();\n\tt( \"Restored second child\", \"p:nth-child(2)\", [\"ap\",\"en\"] );\n});\n\ntest(\"pseudo - nth-child\", function() {\n\texpect( 30 );\n\n\tt( \"Nth-child\", \"p:nth-child(1)\", [\"firstp\",\"sndp\"] );\n\tt( \"Nth-child (with whitespace)\", \"p:nth-child( 1 )\", [\"firstp\",\"sndp\"] );\n\tt( \"Nth-child (case-insensitive)\", \"#form select:first option:NTH-child(3)\", [\"option1c\"] );\n\tt( \"Not nth-child\", \"#qunit-fixture p:not(:nth-child(1))\", [\"ap\",\"en\",\"sap\",\"first\"] );\n\n\tt( \"Nth-child(2)\", \"#qunit-fixture form#form > *:nth-child(2)\", [\"text1\"] );\n\tt( \"Nth-child(2)\", \"#qunit-fixture form#form > :nth-child(2)\", [\"text1\"] );\n\n\tt( \"Nth-child(-1)\", \"#form select:first option:nth-child(-1)\", [] );\n\tt( \"Nth-child(3)\", \"#form select:first option:nth-child(3)\", [\"option1c\"] );\n\tt( \"Nth-child(0n+3)\", \"#form select:first option:nth-child(0n+3)\", [\"option1c\"] );\n\tt( \"Nth-child(1n+0)\", \"#form select:first option:nth-child(1n+0)\", [\"option1a\", \"option1b\", \"option1c\", \"option1d\"] );\n\tt( \"Nth-child(1n)\", \"#form select:first option:nth-child(1n)\", [\"option1a\", \"option1b\", \"option1c\", \"option1d\"] );\n\tt( \"Nth-child(n)\", \"#form select:first option:nth-child(n)\", [\"option1a\", \"option1b\", \"option1c\", \"option1d\"] );\n\tt( \"Nth-child(even)\", \"#form select:first option:nth-child(even)\", [\"option1b\", \"option1d\"] );\n\tt( \"Nth-child(odd)\", \"#form select:first option:nth-child(odd)\", [\"option1a\", \"option1c\"] );\n\tt( \"Nth-child(2n)\", \"#form select:first option:nth-child(2n)\", [\"option1b\", \"option1d\"] );\n\tt( \"Nth-child(2n+1)\", \"#form select:first option:nth-child(2n+1)\", [\"option1a\", \"option1c\"] );\n\tt( \"Nth-child(2n + 1)\", \"#form select:first option:nth-child(2n + 1)\", [\"option1a\", \"option1c\"] );\n\tt( \"Nth-child(+2n + 1)\", \"#form select:first option:nth-child(+2n + 1)\", [\"option1a\", \"option1c\"] );\n\tt( \"Nth-child(3n)\", \"#form select:first option:nth-child(3n)\", [\"option1c\"] );\n\tt( \"Nth-child(3n+1)\", \"#form select:first option:nth-child(3n+1)\", [\"option1a\", \"option1d\"] );\n\tt( \"Nth-child(3n+2)\", \"#form select:first option:nth-child(3n+2)\", [\"option1b\"] );\n\tt( \"Nth-child(3n+3)\", \"#form select:first option:nth-child(3n+3)\", [\"option1c\"] );\n\tt( \"Nth-child(3n-1)\", \"#form select:first option:nth-child(3n-1)\", [\"option1b\"] );\n\tt( \"Nth-child(3n-2)\", \"#form select:first option:nth-child(3n-2)\", [\"option1a\", \"option1d\"] );\n\tt( \"Nth-child(3n-3)\", \"#form select:first option:nth-child(3n-3)\", [\"option1c\"] );\n\tt( \"Nth-child(3n+0)\", \"#form select:first option:nth-child(3n+0)\", [\"option1c\"] );\n\tt( \"Nth-child(-1n+3)\", \"#form select:first option:nth-child(-1n+3)\", [\"option1a\", \"option1b\", \"option1c\"] );\n\tt( \"Nth-child(-n+3)\", \"#form select:first option:nth-child(-n+3)\", [\"option1a\", \"option1b\", \"option1c\"] );\n\tt( \"Nth-child(-1n + 3)\", \"#form select:first option:nth-child(-1n + 3)\", [\"option1a\", \"option1b\", \"option1c\"] );\n\n\tdeepEqual( Sizzle( \":nth-child(n)\", null, null, [ document.createElement(\"a\") ].concat( q(\"ap\") ) ), q(\"ap\"), \"Seeded nth-child\" );\n});\n\ntest(\"pseudo - nth-last-child\", function() {\n\texpect( 30 );\n\n\tt( \"Nth-last-child\", \"form:nth-last-child(5)\", [\"testForm\"] );\n\tt( \"Nth-last-child (with whitespace)\", \"form:nth-last-child( 5 )\", [\"testForm\"] );\n\tt( \"Nth-last-child (case-insensitive)\", \"#form select:first option:NTH-last-child(3)\", [\"option1b\"] );\n\tt( \"Not nth-last-child\", \"#qunit-fixture p:not(:nth-last-child(1))\", [\"firstp\", \"ap\", \"sndp\", \"en\", \"first\"] );\n\n\tt( \"Nth-last-child(-1)\", \"#form select:first option:nth-last-child(-1)\", [] );\n\tt( \"Nth-last-child(3)\", \"#form select:first :nth-last-child(3)\", [\"option1b\"] );\n\tt( \"Nth-last-child(3)\", \"#form select:first *:nth-last-child(3)\", [\"option1b\"] );\n\tt( \"Nth-last-child(3)\", \"#form select:first option:nth-last-child(3)\", [\"option1b\"] );\n\tt( \"Nth-last-child(0n+3)\", \"#form select:first option:nth-last-child(0n+3)\", [\"option1b\"] );\n\tt( \"Nth-last-child(1n+0)\", \"#form select:first option:nth-last-child(1n+0)\", [\"option1a\", \"option1b\", \"option1c\", \"option1d\"] );\n\tt( \"Nth-last-child(1n)\", \"#form select:first option:nth-last-child(1n)\", [\"option1a\", \"option1b\", \"option1c\", \"option1d\"] );\n\tt( \"Nth-last-child(n)\", \"#form select:first option:nth-last-child(n)\", [\"option1a\", \"option1b\", \"option1c\", \"option1d\"] );\n\tt( \"Nth-last-child(even)\", \"#form select:first option:nth-last-child(even)\", [\"option1a\", \"option1c\"] );\n\tt( \"Nth-last-child(odd)\", \"#form select:first option:nth-last-child(odd)\", [\"option1b\", \"option1d\"] );\n\tt( \"Nth-last-child(2n)\", \"#form select:first option:nth-last-child(2n)\", [\"option1a\", \"option1c\"] );\n\tt( \"Nth-last-child(2n+1)\", \"#form select:first option:nth-last-child(2n+1)\", [\"option1b\", \"option1d\"] );\n\tt( \"Nth-last-child(2n + 1)\", \"#form select:first option:nth-last-child(2n + 1)\", [\"option1b\", \"option1d\"] );\n\tt( \"Nth-last-child(+2n + 1)\", \"#form select:first option:nth-last-child(+2n + 1)\", [\"option1b\", \"option1d\"] );\n\tt( \"Nth-last-child(3n)\", \"#form select:first option:nth-last-child(3n)\", [\"option1b\"] );\n\tt( \"Nth-last-child(3n+1)\", \"#form select:first option:nth-last-child(3n+1)\", [\"option1a\", \"option1d\"] );\n\tt( \"Nth-last-child(3n+2)\", \"#form select:first option:nth-last-child(3n+2)\", [\"option1c\"] );\n\tt( \"Nth-last-child(3n+3)\", \"#form select:first option:nth-last-child(3n+3)\", [\"option1b\"] );\n\tt( \"Nth-last-child(3n-1)\", \"#form select:first option:nth-last-child(3n-1)\", [\"option1c\"] );\n\tt( \"Nth-last-child(3n-2)\", \"#form select:first option:nth-last-child(3n-2)\", [\"option1a\", \"option1d\"] );\n\tt( \"Nth-last-child(3n-3)\", \"#form select:first option:nth-last-child(3n-3)\", [\"option1b\"] );\n\tt( \"Nth-last-child(3n+0)\", \"#form select:first option:nth-last-child(3n+0)\", [\"option1b\"] );\n\tt( \"Nth-last-child(-1n+3)\", \"#form select:first option:nth-last-child(-1n+3)\", [\"option1b\", \"option1c\", \"option1d\"] );\n\tt( \"Nth-last-child(-n+3)\", \"#form select:first option:nth-last-child(-n+3)\", [\"option1b\", \"option1c\", \"option1d\"] );\n\tt( \"Nth-last-child(-1n + 3)\", \"#form select:first option:nth-last-child(-1n + 3)\", [\"option1b\", \"option1c\", \"option1d\"] );\n\n\tdeepEqual( Sizzle( \":nth-last-child(n)\", null, null, [ document.createElement(\"a\") ].concat( q(\"ap\") ) ), q(\"ap\"), \"Seeded nth-last-child\" );\n});\n\ntest(\"pseudo - nth-of-type\", function() {\n\texpect( 9 );\n\tt( \"Nth-of-type(-1)\", \":nth-of-type(-1)\", [] );\n\tt( \"Nth-of-type(3)\", \"#ap :nth-of-type(3)\", [\"mark\"] );\n\tt( \"Nth-of-type(n)\", \"#ap :nth-of-type(n)\", [\"google\", \"groups\", \"code1\", \"anchor1\", \"mark\"] );\n\tt( \"Nth-of-type(0n+3)\", \"#ap :nth-of-type(0n+3)\", [\"mark\"] );\n\tt( \"Nth-of-type(2n)\", \"#ap :nth-of-type(2n)\", [\"groups\"] );\n\tt( \"Nth-of-type(even)\", \"#ap :nth-of-type(even)\", [\"groups\"] );\n\tt( \"Nth-of-type(2n+1)\", \"#ap :nth-of-type(2n+1)\", [\"google\", \"code1\", \"anchor1\", \"mark\"] );\n\tt( \"Nth-of-type(odd)\", \"#ap :nth-of-type(odd)\", [\"google\", \"code1\", \"anchor1\", \"mark\"] );\n\tt( \"Nth-of-type(-n+2)\", \"#qunit-fixture > :nth-of-type(-n+2)\", [\"firstp\", \"ap\", \"foo\", \"nothiddendiv\", \"name+value\", \"firstUL\", \"empty\", \"form\", \"floatTest\", \"iframe\", \"lengthtest\", \"table\"] );\n});\n\ntest(\"pseudo - nth-last-of-type\", function() {\n\texpect( 9 );\n\tt( \"Nth-last-of-type(-1)\", \":nth-last-of-type(-1)\", [] );\n\tt( \"Nth-last-of-type(3)\", \"#ap :nth-last-of-type(3)\", [\"google\"] );\n\tt( \"Nth-last-of-type(n)\", \"#ap :nth-last-of-type(n)\", [\"google\", \"groups\", \"code1\", \"anchor1\", \"mark\"] );\n\tt( \"Nth-last-of-type(0n+3)\", \"#ap :nth-last-of-type(0n+3)\", [\"google\"] );\n\tt( \"Nth-last-of-type(2n)\", \"#ap :nth-last-of-type(2n)\", [\"groups\"] );\n\tt( \"Nth-last-of-type(even)\", \"#ap :nth-last-of-type(even)\", [\"groups\"] );\n\tt( \"Nth-last-of-type(2n+1)\", \"#ap :nth-last-of-type(2n+1)\", [\"google\", \"code1\", \"anchor1\", \"mark\"] );\n\tt( \"Nth-last-of-type(odd)\", \"#ap :nth-last-of-type(odd)\", [\"google\", \"code1\", \"anchor1\", \"mark\"] );\n\tt( \"Nth-last-of-type(-n+2)\", \"#qunit-fixture > :nth-last-of-type(-n+2)\", [\"ap\", \"name+value\", \"first\", \"firstUL\", \"empty\", \"floatTest\", \"iframe\", \"table\", \"name-tests\", \"testForm\", \"liveHandlerOrder\", \"siblingTest\"] );\n});\n\ntest(\"pseudo - has\", function() {\n\texpect( 3 );\n\n\tt( \"Basic test\", \"p:has(a)\", [\"firstp\",\"ap\",\"en\",\"sap\"] );\n\tt( \"Basic test (irrelevant whitespace)\", \"p:has( a )\", [\"firstp\",\"ap\",\"en\",\"sap\"] );\n\tt( \"Nested with overlapping candidates\", \"#qunit-fixture div:has(div:has(div:not([id])))\", [ \"moretests\", \"t2037\" ] );\n});\n\ntest(\"pseudo - misc\", function() {\n\texpect( 39 );\n\n\tvar select, tmp, input;\n\n\tt( \"Headers\", \":header\", [\"qunit-header\", \"qunit-banner\", \"qunit-userAgent\"] );\n\tt( \"Headers(case-insensitive)\", \":Header\", [\"qunit-header\", \"qunit-banner\", \"qunit-userAgent\"] );\n\tt( \"Multiple matches with the same context (cache check)\", \"#form select:has(option:first-child:contains('o'))\", [\"select1\", \"select2\", \"select3\", \"select4\"] );\n\n\tok( Sizzle(\"#qunit-fixture :not(:has(:has(*)))\").length, \"All not grandparents\" );\n\n\tselect = document.getElementById(\"select1\");\n\tok( Sizzle.matchesSelector( select, \":has(option)\" ), \"Has Option Matches\" );\n\n\tok( Sizzle(\"a:contains('')\").length, \"Empty string contains\" );\n\tt( \"Text Contains\", \"a:contains(Google)\", [\"google\",\"groups\"] );\n\tt( \"Text Contains\", \"a:contains(Google Groups)\", [\"groups\"] );\n\n\tt( \"Text Contains\", \"a:contains('Google Groups (Link)')\", [\"groups\"] );\n\tt( \"Text Contains\", \"a:contains(\\\"(Link)\\\")\", [\"groups\"] );\n\tt( \"Text Contains\", \"a:contains(Google Groups (Link))\", [\"groups\"] );\n\tt( \"Text Contains\", \"a:contains((Link))\", [\"groups\"] );\n\n\n\ttmp = document.createElement(\"div\");\n\ttmp.id = \"tmp_input\";\n\tdocument.body.appendChild( tmp );\n\n\tjQuery.each( [ \"button\", \"submit\", \"reset\" ], function( i, type ) {\n\t\tvar els = jQuery(\n\t\t\t\"<input id='input_%' type='%'/><button id='button_%' type='%'>test</button>\"\n\t\t\t.replace( /%/g, type )\n\t\t).appendTo( tmp );\n\n\t\tt( \"Input Buttons :\" + type, \"#tmp_input :\" + type, [ \"input_\" + type, \"button_\" + type ] );\n\n\t\tok( Sizzle.matchesSelector( els[0], \":\" + type ), \"Input Matches :\" + type );\n\t\tok( Sizzle.matchesSelector( els[1], \":\" + type ), \"Button Matches :\" + type );\n\t});\n\n\tdocument.body.removeChild( tmp );\n\n\t// Recreate tmp\n\ttmp = document.createElement(\"div\");\n\ttmp.id = \"tmp_input\";\n\ttmp.innerHTML = \"<span>Hello I am focusable.</span>\";\n\t// Setting tabIndex should make the element focusable\n\t// http://dev.w3.org/html5/spec/single-page.html#focus-management\n\tdocument.body.appendChild( tmp );\n\ttmp.tabIndex = 0;\n\ttmp.focus();\n\tif ( document.activeElement !== tmp || (document.hasFocus && !document.hasFocus()) ||\n\t\t(document.querySelectorAll && !document.querySelectorAll(\"div:focus\").length) ) {\n\t\tok( true, \"The div was not focused. Skip checking the :focus match.\" );\n\t\tok( true, \"The div was not focused. Skip checking the :focus match.\" );\n\t} else {\n\t\tt( \"tabIndex element focused\", \":focus\", [ \"tmp_input\" ] );\n\t\tok( Sizzle.matchesSelector( tmp, \":focus\" ), \":focus matches tabIndex div\" );\n\t}\n\n\t// Blur tmp\n\ttmp.blur();\n\tdocument.body.focus();\n\tok( !Sizzle.matchesSelector( tmp, \":focus\" ), \":focus doesn't match tabIndex div\" );\n\tdocument.body.removeChild( tmp );\n\n\t// Input focus/active\n\tinput = document.createElement(\"input\");\n\tinput.type = \"text\";\n\tinput.id = \"focus-input\";\n\n\tdocument.body.appendChild( input );\n\tinput.focus();\n\n\t// Inputs can't be focused unless the document has focus\n\tif ( document.activeElement !== input || (document.hasFocus && !document.hasFocus()) ||\n\t\t(document.querySelectorAll && !document.querySelectorAll(\"input:focus\").length) ) {\n\t\tok( true, \"The input was not focused. Skip checking the :focus match.\" );\n\t\tok( true, \"The input was not focused. Skip checking the :focus match.\" );\n\t} else {\n\t\tt( \"Element focused\", \"input:focus\", [ \"focus-input\" ] );\n\t\tok( Sizzle.matchesSelector( input, \":focus\" ), \":focus matches\" );\n\t}\n\n\tinput.blur();\n\n\t// When IE is out of focus, blur does not work. Force it here.\n\tif ( document.activeElement === input ) {\n\t\tdocument.body.focus();\n\t}\n\n\tok( !Sizzle.matchesSelector( input, \":focus\" ), \":focus doesn't match\" );\n\tdocument.body.removeChild( input );\n\n\n\n\tdeepEqual(\n\t\tSizzle( \"[id='select1'] *:not(:last-child), [id='select2'] *:not(:last-child)\", q(\"qunit-fixture\")[0] ),\n\t\tq( \"option1a\", \"option1b\", \"option1c\", \"option2a\", \"option2b\", \"option2c\" ),\n\t\t\"caching system tolerates recursive selection\"\n\t);\n\n\t// Tokenization edge cases\n\tt( \"Sequential pseudos\", \"#qunit-fixture p:has(:contains(mark)):has(code)\", [\"ap\"] );\n\tt( \"Sequential pseudos\", \"#qunit-fixture p:has(:contains(mark)):has(code):contains(This link)\", [\"ap\"] );\n\n\tt( \"Pseudo argument containing ')'\", \"p:has(>a.GROUPS[src!=')'])\", [\"ap\"] );\n\tt( \"Pseudo argument containing ')'\", \"p:has(>a.GROUPS[src!=')'])\", [\"ap\"] );\n\tt( \"Pseudo followed by token containing ')'\", \"p:contains(id=\\\"foo\\\")[id!=\\\\)]\", [\"sndp\"] );\n\tt( \"Pseudo followed by token containing ')'\", \"p:contains(id=\\\"foo\\\")[id!=')']\", [\"sndp\"] );\n\n\tt( \"Multi-pseudo\", \"#ap:has(*), #ap:has(*)\", [\"ap\"] );\n\tt( \"Multi-positional\", \"#ap:gt(0), #ap:lt(1)\", [\"ap\"] );\n\tt( \"Multi-pseudo with leading nonexistent id\", \"#nonexistent:has(*), #ap:has(*)\", [\"ap\"] );\n\tt( \"Multi-positional with leading nonexistent id\", \"#nonexistent:gt(0), #ap:lt(1)\", [\"ap\"] );\n\n\tt( \"Tokenization stressor\", \"a[class*=blog]:not(:has(*, :contains(!)), :contains(!)), br:contains(]), p:contains(]), :not(:empty):not(:parent)\", [\"ap\", \"mark\",\"yahoo\",\"simon\"] );\n});\n\n\ntest(\"pseudo - :not\", function() {\n\texpect( 43 );\n\n\tt( \"Not\", \"a.blog:not(.link)\", [\"mark\"] );\n\tt( \":not() with :first\", \"#foo p:not(:first) .link\", [\"simon\"] );\n\n\tt( \"Not - multiple\", \"#form option:not(:contains(Nothing),#option1b,:selected)\", [\"option1c\", \"option1d\", \"option2b\", \"option2c\", \"option3d\", \"option3e\", \"option4e\", \"option5b\", \"option5c\"] );\n\tt( \"Not - recursive\", \"#form option:not(:not(:selected))[id^='option3']\", [ \"option3b\", \"option3c\"] );\n\n\tt( \":not() failing interior\", \"#qunit-fixture p:not(.foo)\", [\"firstp\",\"ap\",\"sndp\",\"en\",\"sap\",\"first\"] );\n\tt( \":not() failing interior\", \"#qunit-fixture p:not(div.foo)\", [\"firstp\",\"ap\",\"sndp\",\"en\",\"sap\",\"first\"] );\n\tt( \":not() failing interior\", \"#qunit-fixture p:not(p.foo)\", [\"firstp\",\"ap\",\"sndp\",\"en\",\"sap\",\"first\"] );\n\tt( \":not() failing interior\", \"#qunit-fixture p:not(#blargh)\", [\"firstp\",\"ap\",\"sndp\",\"en\",\"sap\",\"first\"] );\n\tt( \":not() failing interior\", \"#qunit-fixture p:not(div#blargh)\", [\"firstp\",\"ap\",\"sndp\",\"en\",\"sap\",\"first\"] );\n\tt( \":not() failing interior\", \"#qunit-fixture p:not(p#blargh)\", [\"firstp\",\"ap\",\"sndp\",\"en\",\"sap\",\"first\"] );\n\n\tt( \":not Multiple\", \"#qunit-fixture p:not(a)\", [\"firstp\",\"ap\",\"sndp\",\"en\",\"sap\",\"first\"] );\n\tt( \":not Multiple\", \"#qunit-fixture p:not( a )\", [\"firstp\",\"ap\",\"sndp\",\"en\",\"sap\",\"first\"] );\n\tt( \":not Multiple\", \"#qunit-fixture p:not( p )\", [] );\n\tt( \":not Multiple\", \"#qunit-fixture p:not(a, b)\", [\"firstp\",\"ap\",\"sndp\",\"en\",\"sap\",\"first\"] );\n\tt( \":not Multiple\", \"#qunit-fixture p:not(a, b, div)\", [\"firstp\",\"ap\",\"sndp\",\"en\",\"sap\",\"first\"] );\n\tt( \":not Multiple\", \"p:not(p)\", [] );\n\tt( \":not Multiple\", \"p:not(a,p)\", [] );\n\tt( \":not Multiple\", \"p:not(p,a)\", [] );\n\tt( \":not Multiple\", \"p:not(a,p,b)\", [] );\n\tt( \":not Multiple\", \":input:not(:image,:input,:submit)\", [] );\n\tt( \":not Multiple\", \"#qunit-fixture p:not(:has(a), :nth-child(1))\", [\"first\"] );\n\n\tt( \"No element not selector\", \".container div:not(.excluded) div\", [] );\n\n\tt( \":not() Existing attribute\", \"#form select:not([multiple])\", [\"select1\", \"select2\", \"select5\"]);\n\tt( \":not() Equals attribute\", \"#form select:not([name=select1])\", [\"select2\", \"select3\", \"select4\",\"select5\"]);\n\tt( \":not() Equals quoted attribute\", \"#form select:not([name='select1'])\", [\"select2\", \"select3\", \"select4\", \"select5\"]);\n\n\tt( \":not() Multiple Class\", \"#foo a:not(.blog)\", [\"yahoo\", \"anchor2\"] );\n\tt( \":not() Multiple Class\", \"#foo a:not(.link)\", [\"yahoo\", \"anchor2\"] );\n\tt( \":not() Multiple Class\", \"#foo a:not(.blog.link)\", [\"yahoo\", \"anchor2\"] );\n\n\tt( \":not chaining (compound)\", \"#qunit-fixture div[id]:not(:has(div, span)):not(:has(*))\", [\"nothiddendivchild\", \"divWithNoTabIndex\"] );\n\tt( \":not chaining (with attribute)\", \"#qunit-fixture form[id]:not([action$='formaction']):not(:button)\", [\"lengthtest\", \"name-tests\", \"testForm\"] );\n\tt( \":not chaining (colon in attribute)\", \"#qunit-fixture form[id]:not([action='form:action']):not(:button)\", [\"form\", \"lengthtest\", \"name-tests\", \"testForm\"] );\n\tt( \":not chaining (colon in attribute and nested chaining)\", \"#qunit-fixture form[id]:not([action='form:action']:button):not(:input)\", [\"form\", \"lengthtest\", \"name-tests\", \"testForm\"] );\n\tt( \":not chaining\", \"#form select:not(.select1):contains(Nothing) > option:not(option)\", [] );\n\n\tt( \"positional :not()\", \"#foo p:not(:last)\", [\"sndp\", \"en\"] );\n\tt( \"positional :not() prefix\", \"#foo p:not(:last) a\", [\"yahoo\"] );\n\tt( \"compound positional :not()\", \"#foo p:not(:first, :last)\", [\"en\"] );\n\tt( \"compound positional :not()\", \"#foo p:not(:first, :even)\", [\"en\"] );\n\tt( \"compound positional :not()\", \"#foo p:not(:first, :odd)\", [\"sap\"] );\n\tt( \"reordered compound positional :not()\", \"#foo p:not(:odd, :first)\", [\"sap\"] );\n\n\tt( \"positional :not() with pre-filter\", \"#foo p:not([id]:first)\", [\"en\", \"sap\"] );\n\tt( \"positional :not() with post-filter\", \"#foo p:not(:first[id])\", [\"en\", \"sap\"] );\n\tt( \"positional :not() with pre-filter\", \"#foo p:not([lang]:first)\", [\"sndp\", \"sap\"] );\n\tt( \"positional :not() with post-filter\", \"#foo p:not(:first[lang])\", [\"sndp\", \"en\", \"sap\"] );\n});\n\ntest(\"pseudo - position\", function() {\n\texpect( 33 );\n\n\tt( \"First element\", \"div:first\", [\"qunit\"] );\n\tt( \"First element(case-insensitive)\", \"div:fiRst\", [\"qunit\"] );\n\tt( \"nth Element\", \"#qunit-fixture p:nth(1)\", [\"ap\"] );\n\tt( \"First Element\", \"#qunit-fixture p:first\", [\"firstp\"] );\n\tt( \"Last Element\", \"p:last\", [\"first\"] );\n\tt( \"Even Elements\", \"#qunit-fixture p:even\", [\"firstp\",\"sndp\",\"sap\"] );\n\tt( \"Odd Elements\", \"#qunit-fixture p:odd\", [\"ap\",\"en\",\"first\"] );\n\tt( \"Position Equals\", \"#qunit-fixture p:eq(1)\", [\"ap\"] );\n\tt( \"Position Equals (negative)\", \"#qunit-fixture p:eq(-1)\", [\"first\"] );\n\tt( \"Position Greater Than\", \"#qunit-fixture p:gt(0)\", [\"ap\",\"sndp\",\"en\",\"sap\",\"first\"] );\n\tt( \"Position Less Than\", \"#qunit-fixture p:lt(3)\", [\"firstp\",\"ap\",\"sndp\"] );\n\n\tt( \"Check position filtering\", \"div#nothiddendiv:eq(0)\", [\"nothiddendiv\"] );\n\tt( \"Check position filtering\", \"div#nothiddendiv:last\", [\"nothiddendiv\"] );\n\tt( \"Check position filtering\", \"div#nothiddendiv:not(:gt(0))\", [\"nothiddendiv\"] );\n\tt( \"Check position filtering\", \"#foo > :not(:first)\", [\"en\", \"sap\"] );\n\tt( \"Check position filtering\", \"#qunit-fixture select > :not(:gt(2))\", [\"option1a\", \"option1b\", \"option1c\"] );\n\tt( \"Check position filtering\", \"#qunit-fixture select:lt(2) :not(:first)\", [\"option1b\", \"option1c\", \"option1d\", \"option2a\", \"option2b\", \"option2c\", \"option2d\"] );\n\tt( \"Check position filtering\", \"div.nothiddendiv:eq(0)\", [\"nothiddendiv\"] );\n\tt( \"Check position filtering\", \"div.nothiddendiv:last\", [\"nothiddendiv\"] );\n\tt( \"Check position filtering\", \"div.nothiddendiv:not(:lt(0))\", [\"nothiddendiv\"] );\n\n\tt( \"Check element position\", \"#qunit-fixture div div:eq(0)\", [\"nothiddendivchild\"] );\n\tt( \"Check element position\", \"#select1 option:eq(3)\", [\"option1d\"] );\n\tt( \"Check element position\", \"#qunit-fixture div div:eq(10)\", [\"names-group\"] );\n\tt( \"Check element position\", \"#qunit-fixture div div:first\", [\"nothiddendivchild\"] );\n\tt( \"Check element position\", \"#qunit-fixture div > div:first\", [\"nothiddendivchild\"] );\n\tt( \"Check element position\", \"#dl div:first div:first\", [\"foo\"] );\n\tt( \"Check element position\", \"#dl div:first > div:first\", [\"foo\"] );\n\tt( \"Check element position\", \"div#nothiddendiv:first > div:first\", [\"nothiddendivchild\"] );\n\tt( \"Chained pseudo after a pos pseudo\", \"#listWithTabIndex li:eq(0):contains(Rice)\", [\"foodWithNegativeTabIndex\"] );\n\n\tt( \"Check sort order with POS and comma\", \"#qunit-fixture em>em>em>em:first-child,div>em:first\", [\"siblingfirst\", \"siblinggreatgrandchild\"] );\n\n\tt( \"Isolated position\", \":last\", [\"last\"] );\n\n\tdeepEqual( Sizzle( \"*:lt(2) + *\", null, [], Sizzle(\"#qunit-fixture > p\") ), q(\"ap\"), \"Seeded pos with trailing relative\" );\n\n\t// jQuery #12526\n\tvar context = jQuery(\"#qunit-fixture\").append(\"<div id='jquery12526'></div>\")[0];\n\tdeepEqual( Sizzle( \":last\", context ), q(\"jquery12526\"), \"Post-manipulation positional\" );\n});\n\ntest(\"pseudo - form\", function() {\n\texpect( 10 );\n\n\tvar extraTexts = jQuery(\"<input id=\\\"impliedText\\\"/><input id=\\\"capitalText\\\" type=\\\"TEXT\\\">\").appendTo(\"#form\");\n\n\tt( \"Form element :input\", \"#form :input\", [\"text1\", \"text2\", \"radio1\", \"radio2\", \"check1\", \"check2\", \"hidden1\", \"hidden2\", \"name\", \"search\", \"button\", \"area1\", \"select1\", \"select2\", \"select3\", \"select4\", \"select5\", \"impliedText\", \"capitalText\"] );\n\tt( \"Form element :radio\", \"#form :radio\", [\"radio1\", \"radio2\"] );\n\tt( \"Form element :checkbox\", \"#form :checkbox\", [\"check1\", \"check2\"] );\n\tt( \"Form element :text\", \"#form :text\", [\"text1\", \"text2\", \"hidden2\", \"name\", \"impliedText\", \"capitalText\"] );\n\tt( \"Form element :radio:checked\", \"#form :radio:checked\", [\"radio2\"] );\n\tt( \"Form element :checkbox:checked\", \"#form :checkbox:checked\", [\"check1\"] );\n\tt( \"Form element :radio:checked, :checkbox:checked\", \"#form :radio:checked, #form :checkbox:checked\", [\"radio2\", \"check1\"] );\n\n\tt( \"Selected Option Element\", \"#form option:selected\", [\"option1a\",\"option2d\",\"option3b\",\"option3c\",\"option4b\",\"option4c\",\"option4d\",\"option5a\"] );\n\tt( \"Selected Option Element are also :checked\", \"#form option:checked\", [\"option1a\",\"option2d\",\"option3b\",\"option3c\",\"option4b\",\"option4c\",\"option4d\",\"option5a\"] );\n\tt( \"Hidden inputs should be treated as enabled. See QSA test.\", \"#hidden1:enabled\", [\"hidden1\"] );\n\n\textraTexts.remove();\n});\n\ntest(\"pseudo - :target and :root\", function() {\n\texpect( 2 );\n\n\t// Target\n\tvar oldHash,\n\t$link = jQuery(\"<a/>\").attr({\n\t\thref: \"#\",\n\t\tid: \"new-link\"\n\t}).appendTo(\"#qunit-fixture\");\n\n\toldHash = window.location.hash;\n\twindow.location.hash = \"new-link\";\n\n\tt( \":target\", \":target\", [\"new-link\"] );\n\n\t$link.remove();\n\twindow.location.hash = oldHash;\n\n\t// Root\n\tequal( Sizzle(\":root\")[0], document.documentElement, \":root selector\" );\n});\n\ntest(\"pseudo - :lang\", function() {\n\texpect( 105 );\n\n\tvar docElem = document.documentElement,\n\t\tdocXmlLang = docElem.getAttribute(\"xml:lang\"),\n\t\tdocLang = docElem.lang,\n\t\tfoo = document.getElementById(\"foo\"),\n\t\tanchor = document.getElementById(\"anchor2\"),\n\t\txml = createWithFriesXML(),\n\t\ttestLang = function( text, elem, container, lang, extra ) {\n\t\t\tvar message,\n\t\t\t\tfull = lang + \"-\" + extra;\n\n\t\t\tmessage = \"lang=\" + lang + \" \" + text;\n\t\t\tcontainer.setAttribute( container.ownerDocument.documentElement.nodeName === \"HTML\" ? \"lang\" : \"xml:lang\", lang );\n\t\t\tassertMatch( message, elem, \":lang(\" + lang + \")\" );\n\t\t\tassertMatch( message, elem, \":lang(\" + mixCase(lang) + \")\" );\n\t\t\tassertNoMatch( message, elem, \":lang(\" + full + \")\" );\n\t\t\tassertNoMatch( message, elem, \":lang(\" + mixCase(full) + \")\" );\n\t\t\tassertNoMatch( message, elem, \":lang(\" + lang + \"-)\" );\n\t\t\tassertNoMatch( message, elem, \":lang(\" + full + \"-)\" );\n\t\t\tassertNoMatch( message, elem, \":lang(\" + lang + \"glish)\" );\n\t\t\tassertNoMatch( message, elem, \":lang(\" + full + \"glish)\" );\n\n\t\t\tmessage = \"lang=\" + full + \" \" + text;\n\t\t\tcontainer.setAttribute( container.ownerDocument.documentElement.nodeName === \"HTML\" ? \"lang\" : \"xml:lang\", full );\n\t\t\tassertMatch( message, elem, \":lang(\" + lang + \")\" );\n\t\t\tassertMatch( message, elem, \":lang(\" + mixCase(lang) + \")\" );\n\t\t\tassertMatch( message, elem, \":lang(\" + full + \")\" );\n\t\t\tassertMatch( message, elem, \":lang(\" + mixCase(full) + \")\" );\n\t\t\tassertNoMatch( message, elem, \":lang(\" + lang + \"-)\" );\n\t\t\tassertNoMatch( message, elem, \":lang(\" + full + \"-)\" );\n\t\t\tassertNoMatch( message, elem, \":lang(\" + lang + \"glish)\" );\n\t\t\tassertNoMatch( message, elem, \":lang(\" + full + \"glish)\" );\n\t\t},\n\t\tmixCase = function( str ) {\n\t\t\tvar ret = str.split(\"\"),\n\t\t\t\ti = ret.length;\n\t\t\twhile ( i-- ) {\n\t\t\t\tif ( i & 1 ) {\n\t\t\t\t\tret[i] = ret[i].toUpperCase();\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn ret.join(\"\");\n\t\t},\n\t\tassertMatch = function( text, elem, selector ) {\n\t\t\tok( Sizzle.matchesSelector( elem, selector ), text + \" match \" + selector );\n\t\t},\n\t\tassertNoMatch = function( text, elem, selector ) {\n\t\t\tok( !Sizzle.matchesSelector( elem, selector ), text + \" fail \" + selector );\n\t\t};\n\n\t// Prefixing and inheritance\n\tok( Sizzle.matchesSelector( docElem, \":lang(\" + docElem.lang + \")\" ), \"starting :lang\" );\n\ttestLang( \"document\", anchor, docElem, \"en\", \"us\" );\n\ttestLang( \"grandparent\", anchor, anchor.parentNode.parentNode, \"yue\", \"hk\" );\n\tok( !Sizzle.matchesSelector( anchor, \":lang(en), :lang(en-us)\" ),\n\t\t\":lang does not look above an ancestor with specified lang\" );\n\ttestLang( \"self\", anchor, anchor, \"es\", \"419\" );\n\tok( !Sizzle.matchesSelector( anchor, \":lang(en), :lang(en-us), :lang(yue), :lang(yue-hk)\" ),\n\t\t\":lang does not look above self with specified lang\" );\n\n\t// Searching by language tag\n\tanchor.parentNode.parentNode.lang = \"arab\";\n\tanchor.parentNode.lang = anchor.parentNode.id = \"ara-sa\";\n\tanchor.lang = \"ara\";\n\tdeepEqual( Sizzle( \":lang(ara)\", foo ), [ anchor.parentNode, anchor ], \"Find by :lang\" );\n\n\t// Selector validity\n\tanchor.parentNode.lang = \"ara\";\n\tanchor.lang = \"ara\\\\b\";\n\tdeepEqual( Sizzle( \":lang(ara\\\\b)\", foo ), [], \":lang respects backslashes\" );\n\tdeepEqual( Sizzle( \":lang(ara\\\\\\\\b)\", foo ), [ anchor ], \":lang respects escaped backslashes\" );\n\traises(function() {\n\t\tSizzle.call( null, \"dl:lang(c++)\" );\n\t}, function( e ) {\n\t\treturn e.message.indexOf(\"Syntax error\") >= 0;\n\t}, \":lang value must be a valid identifier\" );\n\n\t// XML\n\tfoo = jQuery( \"response\", xml )[0];\n\tanchor = jQuery( \"#seite1\", xml )[0];\n\ttestLang( \"XML document\", anchor, xml.documentElement, \"en\", \"us\" );\n\ttestLang( \"XML grandparent\", anchor, foo, \"yue\", \"hk\" );\n\tok( !Sizzle.matchesSelector( anchor, \":lang(en), :lang(en-us)\" ),\n\t\t\"XML :lang does not look above an ancestor with specified lang\" );\n\ttestLang( \"XML self\", anchor, anchor, \"es\", \"419\" );\n\tok( !Sizzle.matchesSelector( anchor, \":lang(en), :lang(en-us), :lang(yue), :lang(yue-hk)\" ),\n\t\t\"XML :lang does not look above self with specified lang\" );\n\n\t// Cleanup\n\tif ( docXmlLang == null ) {\n\t\tdocElem.removeAttribute(\"xml:lang\");\n\t} else {\n\t\tdocElem.setAttribute( \"xml:lang\", docXmlLang );\n\t}\n\tdocElem.lang = docLang;\n});\n\ntest(\"caching\", function() {\n\texpect( 2 );\n\tSizzle( \":not(code)\", document.getElementById(\"ap\") );\n\tdeepEqual( Sizzle( \":not(code)\", document.getElementById(\"foo\") ), q(\"sndp\", \"en\", \"yahoo\", \"sap\", \"anchor2\", \"simon\"), \"Reusing selector with new context\" );\n\n\tt( \"Deep ancestry caching in post-positional element matcher (jQuery #14657)\",\n\t\t\"#qunit-fixture a:lt(3):parent\",\n\t\t[ \"simon1\", \"google\", \"groups\" ] );\n});\n\nasyncTest( \"Iframe dispatch should not affect Sizzle, see jQuery #13936\", 1, function() {\n\tvar loaded = false,\n\t\tthrown = false,\n\t\tiframe = document.getElementById(\"iframe\"),\n\t\tiframeDoc = iframe.contentDocument || iframe.contentWindow.document;\n\n\tjQuery( iframe ).on( \"load\", function() {\n\t\tvar form;\n\n\t\ttry {\n\t\t\tiframeDoc = this.contentDocument || this.contentWindow.document;\n\t\t\tform = Sizzle( \"#navigate\", iframeDoc )[ 0 ];\n\t\t} catch ( e ) {\n\t\t\tthrown = e;\n\t\t}\n\n\t\tif ( loaded ) {\n\t\t\tstrictEqual( thrown, false, \"No error thrown from post-reload Sizzle call\" );\n\t\t\tstart();\n\t\t} else {\n\t\t\tloaded = true;\n\t\t\tform.submit();\n\t\t}\n\t});\n\n\tiframeDoc.open();\n\tiframeDoc.write(\"<body><form id='navigate'></form></body>\");\n\tiframeDoc.close();\n});\n\ntest(\"matchesSelector\", function() {\n\texpect( 6 );\n\n\tvar el = document.getElementById(\"simon1\"),\n\t\tdisconnected = document.createElement(\"div\");\n\n\tok( Sizzle.matchesSelector( el, \"[rel='bookmark']\" ), \"quoted attribute\" );\n\tok( Sizzle.matchesSelector( el, \"[rel=bookmark]\" ), \"unquoted attribute\" );\n\tok( Sizzle.matchesSelector( el, \"[\\nrel = bookmark\\t]\" ), \"unquoted attribute with non-semantic whitespace\" );\n\n\tok( Sizzle.matchesSelector( disconnected, \"div\" ), \"disconnected element\" );\n\n\tok( Sizzle.matchesSelector( el, \"* > *\" ), \"child combinator (matching)\" );\n\tok( !Sizzle.matchesSelector( disconnected, \"* > *\" ), \"child combinator (not matching)\" );\n});\n"
  },
  {
    "path": "flowable-ui-web/task/libs/sizzle_1.10.16/test/unit/utilities.js",
    "content": "module(\"utilities\", { teardown: moduleTeardown });\n\nfunction testAttr( doc ) {\n\texpect( 9 );\n\n\tvar el;\n\tif ( doc ) {\n\t\t// XML\n\t\tel = doc.createElement( \"input\" );\n\t\tel.setAttribute( \"type\", \"checkbox\" );\n\t} else {\n\t\t// Set checked on creation by creating with a fragment\n\t\t// See http://jsfiddle.net/8sVgA/1/show/light in oldIE\n\t\tel = jQuery( \"<input type='checkbox' checked='checked' />\" )[0];\n\t}\n\n\t// Set it again for good measure\n\tel.setAttribute( \"checked\", \"checked\" );\n\tel.setAttribute( \"id\", \"id\" );\n\tel.setAttribute( \"value\", \"on\" );\n\n\tstrictEqual( Sizzle.attr( el, \"nonexistent\" ), null, \"nonexistent\" );\n\tstrictEqual( Sizzle.attr( el, \"id\" ), \"id\", \"existent\" );\n\tstrictEqual( Sizzle.attr( el, \"value\" ), \"on\", \"value\" );\n\tstrictEqual( Sizzle.attr( el, \"checked\" ), \"checked\", \"boolean\" );\n\tstrictEqual( Sizzle.attr( el, \"href\" ), null, \"interpolation risk\" );\n\tstrictEqual( Sizzle.attr( el, \"constructor\" ), null,\n\t\t\"Object.prototype property \\\"constructor\\\" (negative)\" );\n\tstrictEqual( Sizzle.attr( el, \"watch\" ), null,\n\t\t\"Gecko Object.prototype property \\\"watch\\\" (negative)\" );\n\tel.setAttribute( \"constructor\", \"foo\" );\n\tel.setAttribute( \"watch\", \"bar\" );\n\tstrictEqual( Sizzle.attr( el, \"constructor\" ), \"foo\",\n\t\t\"Object.prototype property \\\"constructor\\\"\" );\n\tstrictEqual( Sizzle.attr( el, \"watch\" ), \"bar\",\n\t\t\"Gecko Object.prototype property \\\"watch\\\"\" );\n}\n\ntest(\"Sizzle.attr (HTML)\", function() {\n\ttestAttr();\n});\n\ntest(\"Sizzle.attr (XML)\", function() {\n\ttestAttr( jQuery.parseXML(\"<root/>\") );\n});\n\ntest(\"Sizzle.contains\", function() {\n\texpect( 16 );\n\n\tvar container = document.getElementById(\"nonnodes\"),\n\t\telement = container.firstChild,\n\t\ttext = element.nextSibling,\n\t\tnonContained = container.nextSibling,\n\t\tdetached = document.createElement(\"a\");\n\tok( element && element.nodeType === 1, \"preliminary: found element\" );\n\tok( text && text.nodeType === 3, \"preliminary: found text\" );\n\tok( nonContained, \"preliminary: found non-descendant\" );\n\tok( Sizzle.contains(container, element), \"child\" );\n\tok( Sizzle.contains(container.parentNode, element), \"grandchild\" );\n\tok( Sizzle.contains(container, text), \"text child\" );\n\tok( Sizzle.contains(container.parentNode, text), \"text grandchild\" );\n\tok( !Sizzle.contains(container, container), \"self\" );\n\tok( !Sizzle.contains(element, container), \"parent\" );\n\tok( !Sizzle.contains(container, nonContained), \"non-descendant\" );\n\tok( !Sizzle.contains(container, document), \"document\" );\n\tok( !Sizzle.contains(container, document.documentElement), \"documentElement (negative)\" );\n\tok( !Sizzle.contains(container, null), \"Passing null does not throw an error\" );\n\tok( Sizzle.contains(document, document.documentElement), \"documentElement (positive)\" );\n\tok( Sizzle.contains(document, element), \"document container (positive)\" );\n\tok( !Sizzle.contains(document, detached), \"document container (negative)\" );\n});\n\nif ( jQuery(\"<svg xmlns='http://www.w3.org/2000/svg' version='1.1' height='1' width='1'><g/></svg>\")[0].firstChild ) {\n\ttest(\"Sizzle.contains in SVG (jQuery #10832)\", function() {\n\t\texpect( 4 );\n\n\t\tvar svg = jQuery(\n\t\t\t\"<svg xmlns='http://www.w3.org/2000/svg' version='1.1' height='1' width='1'>\" +\n\t\t\t\t\"<g><circle cx='1' cy='1' r='1' /></g>\" +\n\t\t\t\"</svg>\"\n\t\t).appendTo(\"#qunit-fixture\")[0];\n\n\t\tok( Sizzle.contains( svg, svg.firstChild ), \"root child\" );\n\t\tok( Sizzle.contains( svg.firstChild, svg.firstChild.firstChild ), \"element child\" );\n\t\tok( Sizzle.contains( svg, svg.firstChild.firstChild ), \"root granchild\" );\n\t\tok( !Sizzle.contains( svg.firstChild.firstChild, svg.firstChild ), \"parent (negative)\" );\n\t});\n}\n\ntest(\"Sizzle.uniqueSort\", function() {\n\texpect( 14 );\n\n\tfunction Arrayish( arr ) {\n\t\tvar i = this.length = arr.length;\n\t\twhile ( i-- ) {\n\t\t\tthis[ i ] = arr[ i ];\n\t\t}\n\t}\n\tArrayish.prototype = {\n\t\tslice: [].slice,\n\t\tsort: [].sort,\n\t\tsplice: [].splice\n\t};\n\n\tvar i, tests,\n\t\tdetached = [],\n\t\tbody = document.body,\n\t\tfixture = document.getElementById(\"qunit-fixture\"),\n\t\tdetached1 = document.createElement(\"p\"),\n\t\tdetached2 = document.createElement(\"ul\"),\n\t\tdetachedChild = detached1.appendChild( document.createElement(\"a\") ),\n\t\tdetachedGrandchild = detachedChild.appendChild( document.createElement(\"b\") );\n\n\tfor ( i = 0; i < 12; i++ ) {\n\t\tdetached.push( document.createElement(\"li\") );\n\t\tdetached[i].id = \"detached\" + i;\n\t\tdetached2.appendChild( document.createElement(\"li\") ).id = \"detachedChild\" + i;\n\t}\n\n\ttests = {\n\t\t\"Empty\": {\n\t\t\tinput: [],\n\t\t\texpected: []\n\t\t},\n\t\t\"Single-element\": {\n\t\t\tinput: [ fixture ],\n\t\t\texpected: [ fixture ]\n\t\t},\n\t\t\"No duplicates\": {\n\t\t\tinput: [ fixture, body ],\n\t\t\texpected: [ body, fixture ]\n\t\t},\n\t\t\"Duplicates\": {\n\t\t\tinput: [ body, fixture, fixture, body ],\n\t\t\texpected: [ body, fixture ]\n\t\t},\n\t\t\"Detached\": {\n\t\t\tinput: detached.slice( 0 ),\n\t\t\texpected: detached.slice( 0 )\n\t\t},\n\t\t\"Detached children\": {\n\t\t\tinput: [\n\t\t\t\tdetached2.childNodes[0],\n\t\t\t\tdetached2.childNodes[1],\n\t\t\t\tdetached2.childNodes[2],\n\t\t\t\tdetached2.childNodes[3]\n\t\t\t],\n\t\t\texpected: [\n\t\t\t\tdetached2.childNodes[0],\n\t\t\t\tdetached2.childNodes[1],\n\t\t\t\tdetached2.childNodes[2],\n\t\t\t\tdetached2.childNodes[3]\n\t\t\t]\n\t\t},\n\t\t\"Attached/detached mixture\": {\n\t\t\tinput: [ detached1, fixture, detached2, document, detachedChild, body, detachedGrandchild ],\n\t\t\texpected: [ document, body, fixture ],\n\t\t\tlength: 3\n\t\t}\n\t};\n\n\tjQuery.each( tests, function( label, test ) {\n\t\tvar length = test.length || test.input.length;\n\t\tdeepEqual( Sizzle.uniqueSort( test.input ).slice( 0, length ), test.expected, label + \" (array)\" );\n\t\tdeepEqual( Sizzle.uniqueSort( new Arrayish(test.input) ).slice( 0, length ), test.expected, label + \" (quasi-array)\" );\n\t});\n});\n\ntestIframeWithCallback( \"Sizzle.uniqueSort works cross-window (jQuery #14381)\", \"mixed_sort.html\", deepEqual );\n"
  },
  {
    "path": "flowable-ui-web/task/libs/ui-grid_3.0.0/ui-grid.css",
    "content": "/*!\n * ui-grid - v3.0.0-rc.19 - 2015-02-11\n * Copyright (c) 2015 ; License: MIT \n */\n.ui-grid {\n  border: 1px solid #d4d4d4;\n  box-sizing: content-box;\n  -webkit-border-radius: 0px;\n  -moz-border-radius: 0px;\n  border-radius: 0px;\n  -webkit-transform: translateZ(0);\n  -moz-transform: translateZ(0);\n  -o-transform: translateZ(0);\n  -ms-transform: translateZ(0);\n  transform: translateZ(0);\n}\n.ui-grid-vertical-bar {\n  position: absolute;\n  right: 0;\n  width: 0;\n}\n.ui-grid-header-cell:not(:last-child) .ui-grid-vertical-bar,\n.ui-grid-cell:not(:last-child) .ui-grid-vertical-bar {\n  width: 1px;\n}\n.ui-grid-header-cell:not(:last-child) .ui-grid-vertical-bar {\n  background-color: #d4d4d4;\n}\n.ui-grid-cell:not(:last-child) .ui-grid-vertical-bar {\n  background-color: #d4d4d4;\n}\n.ui-grid-header-cell:last-child .ui-grid-vertical-bar {\n  right: -1px;\n  width: 1px;\n  background-color: #d4d4d4;\n}\n.ui-grid-clearfix:before,\n.ui-grid-clearfix:after {\n  content: \"\";\n  display: table;\n}\n.ui-grid-clearfix:after {\n  clear: both;\n}\n.ui-grid-invisible {\n  visibility: hidden;\n}\n.ui-grid-top-panel-background {\n  background: #f3f3f3;\n  background: -webkit-gradient(linear, left bottom, left top, color-stop(0, #eeeeee), color-stop(1, #ffffff));\n  background: -ms-linear-gradient(bottom, #eeeeee, #ffffff);\n  background: -moz-linear-gradient(center bottom, #eeeeee 0%, #ffffff 100%);\n  background: -o-linear-gradient(#ffffff, #eeeeee);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#eeeeee', GradientType=0);\n}\n.ui-grid-header {\n  border-bottom: 1px solid #d4d4d4;\n  box-sizing: content-box;\n}\n.ui-grid-top-panel {\n  position: relative;\n  overflow: hidden;\n  font-weight: bold;\n  background: #f3f3f3;\n  background: -webkit-gradient(linear, left bottom, left top, color-stop(0, #eeeeee), color-stop(1, #ffffff));\n  background: -ms-linear-gradient(bottom, #eeeeee, #ffffff);\n  background: -moz-linear-gradient(center bottom, #eeeeee 0%, #ffffff 100%);\n  background: -o-linear-gradient(#ffffff, #eeeeee);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#eeeeee', GradientType=0);\n  -webkit-border-top-right-radius: -1px;\n  -webkit-border-bottom-right-radius: 0;\n  -webkit-border-bottom-left-radius: 0;\n  -webkit-border-top-left-radius: -1px;\n  -moz-border-radius-topright: -1px;\n  -moz-border-radius-bottomright: 0;\n  -moz-border-radius-bottomleft: 0;\n  -moz-border-radius-topleft: -1px;\n  border-top-right-radius: -1px;\n  border-bottom-right-radius: 0;\n  border-bottom-left-radius: 0;\n  border-top-left-radius: -1px;\n  -moz-background-clip: padding-box;\n  -webkit-background-clip: padding-box;\n  background-clip: padding-box;\n}\n.ui-grid-header-viewport {\n  overflow: hidden;\n}\n.ui-grid-header-canvas {\n  position: relative;\n}\n.ui-grid-header-canvas:before,\n.ui-grid-header-canvas:after {\n  content: \"\";\n  display: table;\n  line-height: 0;\n}\n.ui-grid-header-canvas:after {\n  clear: both;\n}\n.ui-grid-header-cell {\n  position: relative;\n  box-sizing: border-box;\n  float: left;\n  top: 0;\n  bottom: 0;\n  background-color: inherit;\n  border-right: 1px solid;\n  border-color: #d4d4d4;\n  -webkit-user-select: none;\n  -moz-user-select: none;\n  -ms-user-select: none;\n  user-select: none;\n  width: 0;\n}\n.ui-grid-header-cell .sortable {\n  cursor: pointer;\n}\n.ui-grid-header .ui-grid-vertical-bar {\n  top: 0;\n  bottom: 0;\n}\n.ui-grid-column-menu-button {\n  position: absolute;\n  right: 1px;\n  top: 0;\n}\n.ui-grid-column-menu-button .ui-grid-icon-angle-down {\n  vertical-align: sub;\n}\n.ui-grid-column-menu-button-last-col {\n  margin-right: 25px;\n}\n.ui-grid-column-menu {\n  position: absolute;\n}\n/* Slide up/down animations */\n.ui-grid-column-menu .ui-grid-menu .ui-grid-menu-mid.ng-hide-add,\n.ui-grid-column-menu .ui-grid-menu .ui-grid-menu-mid.ng-hide-remove {\n  -webkit-transition: all 0.05s linear;\n  -moz-transition: all 0.05s linear;\n  -o-transition: all 0.05s linear;\n  transition: all 0.05s linear;\n  display: block !important;\n}\n.ui-grid-column-menu .ui-grid-menu .ui-grid-menu-mid.ng-hide-add.ng-hide-add-active,\n.ui-grid-column-menu .ui-grid-menu .ui-grid-menu-mid.ng-hide-remove {\n  -webkit-transform: translateY(-100%);\n  -moz-transform: translateY(-100%);\n  -o-transform: translateY(-100%);\n  -ms-transform: translateY(-100%);\n  transform: translateY(-100%);\n}\n.ui-grid-column-menu .ui-grid-menu .ui-grid-menu-mid.ng-hide-add,\n.ui-grid-column-menu .ui-grid-menu .ui-grid-menu-mid.ng-hide-remove.ng-hide-remove-active {\n  -webkit-transform: translateY(0);\n  -moz-transform: translateY(0);\n  -o-transform: translateY(0);\n  -ms-transform: translateY(0);\n  transform: translateY(0);\n}\n/* Slide up/down animations */\n.ui-grid-menu-button .ui-grid-menu .ui-grid-menu-mid.ng-hide-add,\n.ui-grid-menu-button .ui-grid-menu .ui-grid-menu-mid.ng-hide-remove {\n  -webkit-transition: all 0.05s linear;\n  -moz-transition: all 0.05s linear;\n  -o-transition: all 0.05s linear;\n  transition: all 0.05s linear;\n  display: block !important;\n}\n.ui-grid-menu-button .ui-grid-menu .ui-grid-menu-mid.ng-hide-add.ng-hide-add-active,\n.ui-grid-menu-button .ui-grid-menu .ui-grid-menu-mid.ng-hide-remove {\n  -webkit-transform: translateY(-100%);\n  -moz-transform: translateY(-100%);\n  -o-transform: translateY(-100%);\n  -ms-transform: translateY(-100%);\n  transform: translateY(-100%);\n}\n.ui-grid-menu-button .ui-grid-menu .ui-grid-menu-mid.ng-hide-add,\n.ui-grid-menu-button .ui-grid-menu .ui-grid-menu-mid.ng-hide-remove.ng-hide-remove-active {\n  -webkit-transform: translateY(0);\n  -moz-transform: translateY(0);\n  -o-transform: translateY(0);\n  -ms-transform: translateY(0);\n  transform: translateY(0);\n}\n.ui-grid-filter-container {\n  padding: 4px 10px;\n  position: relative;\n}\n.ui-grid-filter-container .ui-grid-filter-button {\n  position: absolute;\n  top: 0;\n  bottom: 0;\n  right: 0;\n}\n.ui-grid-filter-container .ui-grid-filter-button [class^=\"ui-grid-icon\"] {\n  position: absolute;\n  top: 50%;\n  line-height: 32px;\n  margin-top: -16px;\n  right: 10px;\n  opacity: 0.66;\n}\n.ui-grid-filter-container .ui-grid-filter-button [class^=\"ui-grid-icon\"]:hover {\n  opacity: 1;\n}\ninput[type=\"text\"].ui-grid-filter-input {\n  padding: 0;\n  margin: 0;\n  border: 0;\n  width: 100%;\n  border: 1px solid #d4d4d4;\n  -webkit-border-top-right-radius: 0px;\n  -webkit-border-bottom-right-radius: 0;\n  -webkit-border-bottom-left-radius: 0;\n  -webkit-border-top-left-radius: 0;\n  -moz-border-radius-topright: 0px;\n  -moz-border-radius-bottomright: 0;\n  -moz-border-radius-bottomleft: 0;\n  -moz-border-radius-topleft: 0;\n  border-top-right-radius: 0px;\n  border-bottom-right-radius: 0;\n  border-bottom-left-radius: 0;\n  border-top-left-radius: 0;\n  -moz-background-clip: padding-box;\n  -webkit-background-clip: padding-box;\n  background-clip: padding-box;\n}\ninput[type=\"text\"].ui-grid-filter-input:hover {\n  border: 1px solid #d4d4d4;\n}\n.ui-grid-render-container {\n  position: inherit;\n  -webkit-border-top-right-radius: 0;\n  -webkit-border-bottom-right-radius: 0px;\n  -webkit-border-bottom-left-radius: 0px;\n  -webkit-border-top-left-radius: 0;\n  -moz-border-radius-topright: 0;\n  -moz-border-radius-bottomright: 0px;\n  -moz-border-radius-bottomleft: 0px;\n  -moz-border-radius-topleft: 0;\n  border-top-right-radius: 0;\n  border-bottom-right-radius: 0px;\n  border-bottom-left-radius: 0px;\n  border-top-left-radius: 0;\n  -moz-background-clip: padding-box;\n  -webkit-background-clip: padding-box;\n  background-clip: padding-box;\n}\n.ui-grid-render-container:focus {\n  outline: none;\n}\n.ui-grid-viewport {\n  min-height: 20px;\n  position: relative;\n  overflow-y: scroll;\n  -webkit-overflow-scrolling: touch;\n}\n.ui-grid-viewport :focus {\n  outline: none;\n}\n.ui-grid-canvas {\n  position: relative;\n  padding-top: 1px;\n}\n.ui-grid-row:nth-child(odd) .ui-grid-cell {\n  background-color: #fdfdfd;\n}\n.ui-grid-row:nth-child(even) .ui-grid-cell {\n  background-color: #f3f3f3;\n}\n.ui-grid-row:last-child .ui-grid-cell {\n  border-bottom-color: #d4d4d4;\n  border-bottom-style: solid;\n}\n.ui-grid-no-row-overlay {\n  position: absolute;\n  top: 0;\n  bottom: 0;\n  left: 0;\n  right: 0;\n  margin: 10%;\n  background: #f3f3f3;\n  background: -webkit-gradient(linear, left bottom, left top, color-stop(0, #eeeeee), color-stop(1, #ffffff));\n  background: -ms-linear-gradient(bottom, #eeeeee, #ffffff);\n  background: -moz-linear-gradient(center bottom, #eeeeee 0%, #ffffff 100%);\n  background: -o-linear-gradient(#ffffff, #eeeeee);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#eeeeee', GradientType=0);\n  -webkit-border-top-right-radius: 0px;\n  -webkit-border-bottom-right-radius: 0;\n  -webkit-border-bottom-left-radius: 0;\n  -webkit-border-top-left-radius: 0;\n  -moz-border-radius-topright: 0px;\n  -moz-border-radius-bottomright: 0;\n  -moz-border-radius-bottomleft: 0;\n  -moz-border-radius-topleft: 0;\n  border-top-right-radius: 0px;\n  border-bottom-right-radius: 0;\n  border-bottom-left-radius: 0;\n  border-top-left-radius: 0;\n  -moz-background-clip: padding-box;\n  -webkit-background-clip: padding-box;\n  background-clip: padding-box;\n  border: 1px solid #d4d4d4;\n  font-size: 2em;\n  text-align: center;\n}\n.ui-grid-no-row-overlay > * {\n  position: absolute;\n  display: table;\n  margin: auto 0;\n  width: 100%;\n  top: 0;\n  bottom: 0;\n  left: 0;\n  right: 0;\n  opacity: 0.66;\n}\n.ui-grid-cell {\n  overflow: hidden;\n  float: left;\n  background-color: inherit;\n  border-right: 1px solid;\n  border-color: #d4d4d4;\n  box-sizing: border-box;\n}\n.ui-grid-cell-contents {\n  padding: 5px;\n  -moz-box-sizing: border-box;\n  -webkit-box-sizing: border-box;\n  box-sizing: border-box;\n  white-space: nowrap;\n  -ms-text-overflow: ellipsis;\n  -o-text-overflow: ellipsis;\n  text-overflow: ellipsis;\n  overflow: hidden;\n  height: 100%;\n}\n.ui-grid-cell-contents-hidden {\n  visibility: hidden;\n  width: 0;\n  height: 0;\n  display: none;\n}\n.ui-grid-row-header-cell {\n  background-color: #F0F0EE !important;\n  border-bottom: solid 1px #d4d4d4;\n}\n.ui-grid-footer-panel-background {\n  background: #f3f3f3;\n  background: -webkit-gradient(linear, left bottom, left top, color-stop(0, #eeeeee), color-stop(1, #ffffff));\n  background: -ms-linear-gradient(bottom, #eeeeee, #ffffff);\n  background: -moz-linear-gradient(center bottom, #eeeeee 0%, #ffffff 100%);\n  background: -o-linear-gradient(#ffffff, #eeeeee);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#eeeeee', GradientType=0);\n}\n.ui-grid-footer-panel {\n  position: relative;\n  border-bottom: 1px solid #d4d4d4;\n  border-top: 1px solid #d4d4d4;\n  overflow: hidden;\n  font-weight: bold;\n  background: #f3f3f3;\n  background: -webkit-gradient(linear, left bottom, left top, color-stop(0, #eeeeee), color-stop(1, #ffffff));\n  background: -ms-linear-gradient(bottom, #eeeeee, #ffffff);\n  background: -moz-linear-gradient(center bottom, #eeeeee 0%, #ffffff 100%);\n  background: -o-linear-gradient(#ffffff, #eeeeee);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#eeeeee', GradientType=0);\n  -webkit-border-top-right-radius: -1px;\n  -webkit-border-bottom-right-radius: 0;\n  -webkit-border-bottom-left-radius: 0;\n  -webkit-border-top-left-radius: -1px;\n  -moz-border-radius-topright: -1px;\n  -moz-border-radius-bottomright: 0;\n  -moz-border-radius-bottomleft: 0;\n  -moz-border-radius-topleft: -1px;\n  border-top-right-radius: -1px;\n  border-bottom-right-radius: 0;\n  border-bottom-left-radius: 0;\n  border-top-left-radius: -1px;\n  -moz-background-clip: padding-box;\n  -webkit-background-clip: padding-box;\n  background-clip: padding-box;\n}\n.ui-grid-grid-footer {\n  float: left;\n  width: 100%;\n}\n.ui-grid-footer-viewport {\n  overflow: hidden;\n}\n.ui-grid-footer-canvas {\n  position: relative;\n}\n.ui-grid-footer-canvas:before,\n.ui-grid-footer-canvas:after {\n  content: \"\";\n  display: table;\n  line-height: 0;\n}\n.ui-grid-footer-canvas:after {\n  clear: both;\n}\n.ui-grid-footer-cell {\n  overflow: hidden;\n  float: left;\n  background-color: inherit;\n  border-right: 1px solid;\n  border-color: #d4d4d4;\n  box-sizing: border-box;\n}\n.ui-grid-footer-cell:last-child {\n  border-right: 0;\n}\ninput[type=\"text\"].ui-grid-filter-input {\n  padding: 0;\n  margin: 0;\n  border: 0;\n  width: 100%;\n  border: 1px solid #d4d4d4;\n  -webkit-border-top-right-radius: 0px;\n  -webkit-border-bottom-right-radius: 0;\n  -webkit-border-bottom-left-radius: 0;\n  -webkit-border-top-left-radius: 0;\n  -moz-border-radius-topright: 0px;\n  -moz-border-radius-bottomright: 0;\n  -moz-border-radius-bottomleft: 0;\n  -moz-border-radius-topleft: 0;\n  border-top-right-radius: 0px;\n  border-bottom-right-radius: 0;\n  border-bottom-left-radius: 0;\n  border-top-left-radius: 0;\n  -moz-background-clip: padding-box;\n  -webkit-background-clip: padding-box;\n  background-clip: padding-box;\n}\ninput[type=\"text\"].ui-grid-filter-input:hover {\n  border: 1px solid #d4d4d4;\n}\n.ui-grid-menu-button {\n  z-index: 2;\n  position: absolute;\n  right: 0;\n  background: #f3f3f3;\n  border: 1px solid #d4d4d4;\n  cursor: pointer;\n  min-height: 27px;\n  font-weight: normal;\n}\n.ui-grid-menu-button .ui-grid-icon-container {\n  margin-top: 3px;\n}\n.ui-grid-menu-button .ui-grid-menu {\n  right: 0;\n}\n.ui-grid-menu-button .ui-grid-menu .ui-grid-menu-mid {\n  overflow-y: scroll;\n  max-height: 300px;\n  border: 1px solid #d4d4d4;\n}\n.ui-grid-menu {\n  z-index: 2;\n  position: absolute;\n  overflow: hidden;\n  padding: 0 10px 20px 10px;\n  cursor: pointer;\n  box-sizing: content-box;\n}\n.ui-grid-menu .ui-grid-menu-inner {\n  background: #f3f3f3;\n  border: 1px solid #d4d4d4;\n  position: relative;\n  white-space: nowrap;\n  -webkit-border-radius: 0px;\n  -moz-border-radius: 0px;\n  border-radius: 0px;\n  -webkit-box-shadow: 0 10px 20px rgba(0, 0, 0, 0.2), inset 0 12px 12px -14px rgba(0, 0, 0, 0.2);\n  -moz-box-shadow: 0 10px 20px rgba(0, 0, 0, 0.2), inset 0 12px 12px -14px rgba(0, 0, 0, 0.2);\n  box-shadow: 0 10px 20px rgba(0, 0, 0, 0.2), inset 0 12px 12px -14px rgba(0, 0, 0, 0.2);\n}\n.ui-grid-menu .ui-grid-menu-inner ul {\n  margin: 0;\n  padding: 0;\n  list-style-type: none;\n}\n.ui-grid-menu .ui-grid-menu-inner ul li {\n  padding: 8px;\n  cursor: pointer;\n}\n.ui-grid-menu .ui-grid-menu-inner ul li:hover {\n  -webkit-box-shadow: inset 0 0 14px rgba(0, 0, 0, 0.2);\n  -moz-box-shadow: inset 0 0 14px rgba(0, 0, 0, 0.2);\n  box-shadow: inset 0 0 14px rgba(0, 0, 0, 0.2);\n}\n.ui-grid-menu .ui-grid-menu-inner ul li.ui-grid-menu-item-active {\n  -webkit-box-shadow: inset 0 0 14px rgba(0, 0, 0, 0.2);\n  -moz-box-shadow: inset 0 0 14px rgba(0, 0, 0, 0.2);\n  box-shadow: inset 0 0 14px rgba(0, 0, 0, 0.2);\n  background-color: #cecece;\n}\n.ui-grid-menu .ui-grid-menu-inner ul li:not(:last-child) {\n  border-bottom: 1px solid #d4d4d4;\n}\n.ui-grid-sortarrow {\n  right: 5px;\n  position: absolute;\n  width: 20px;\n  top: 0;\n  bottom: 0;\n  background-position: center;\n}\n.ui-grid-sortarrow.down {\n  -webkit-transform: rotate(180deg);\n  -moz-transform: rotate(180deg);\n  -o-transform: rotate(180deg);\n  -ms-transform: rotate(180deg);\n  transform: rotate(180deg);\n}\n@font-face {\n  font-family: 'ui-grid';\n  src: url('ui-grid.eot');\n  src: url('ui-grid.eot#iefix') format('embedded-opentype'), url('ui-grid.woff') format('woff'), url('ui-grid.ttf?') format('truetype'), url('ui-grid.svg?#ui-grid') format('svg');\n  font-weight: normal;\n  font-style: normal;\n}\n/* Chrome hack: SVG is rendered more smooth in Windozze. 100% magic, uncomment if you need it. */\n/* Note, that will break hinting! In other OS-es font will be not as sharp as it could be */\n/*\n@media screen and (-webkit-min-device-pixel-ratio:0) {\n  @font-face {\n    font-family: 'ui-grid';\n    src: url('../font/ui-grid.svg?12312827#ui-grid') format('svg');\n  }\n}\n*/\n[class^=\"ui-grid-icon\"]:before,\n[class*=\" ui-grid-icon\"]:before {\n  font-family: \"ui-grid\";\n  font-style: normal;\n  font-weight: normal;\n  speak: none;\n  display: inline-block;\n  text-decoration: inherit;\n  width: 1em;\n  margin-right: .2em;\n  text-align: center;\n  /* opacity: .8; */\n  /* For safety - reset parent styles, that can break glyph codes*/\n  font-variant: normal;\n  text-transform: none;\n  /* fix buttons height, for twitter bootstrap */\n  line-height: 1em;\n  /* Animation center compensation - margins should be symmetric */\n  /* remove if not needed */\n  margin-left: .2em;\n  /* you can be more comfortable with increased icons size */\n  /* font-size: 120%; */\n  /* Uncomment for 3D effect */\n  /* text-shadow: 1px 1px 1px rgba(127, 127, 127, 0.3); */\n}\n.ui-grid-icon-blank::before {\n  width: 1em;\n  content: ' ';\n}\n/*\n* RTL Styles\n*/\n.ui-grid[dir=rtl] .ui-grid-header-cell,\n.ui-grid[dir=rtl] .ui-grid-footer-cell,\n.ui-grid[dir=rtl] .ui-grid-cell {\n  float: right !important;\n}\n.ui-grid[dir=rtl] .ui-grid-column-menu-button {\n  position: absolute;\n  left: 1px;\n  top: 0;\n  right: inherit;\n}\n.ui-grid[dir=rtl] .ui-grid-cell:first-child,\n.ui-grid[dir=rtl] .ui-grid-header-cell:first-child,\n.ui-grid[dir=rtl] .ui-grid-footer-cell:first-child {\n  border-right: 0;\n}\n.ui-grid[dir=rtl] .ui-grid-cell:last-child,\n.ui-grid[dir=rtl] .ui-grid-header-cell:last-child {\n  border-left: 1px solid;\n  border-color: #d4d4d4;\n}\n.ui-grid[dir=rtl] .ui-grid-header-cell:first-child .ui-grid-vertical-bar,\n.ui-grid[dir=rtl] .ui-grid-footer-cell:first-child .ui-grid-vertical-bar,\n.ui-grid[dir=rtl] .ui-grid-cell:first-child .ui-grid-vertical-bar {\n  width: 0;\n}\n.ui-grid[dir=rtl] .ui-grid-menu-button {\n  z-index: 2;\n  position: absolute;\n  left: 0;\n  right: auto;\n  background: #f3f3f3;\n  border: 1px solid #d4d4d4;\n  cursor: pointer;\n  min-height: 27px;\n  font-weight: normal;\n}\n.ui-grid[dir=rtl] .ui-grid-menu-button .ui-grid-menu {\n  left: 0;\n  right: auto;\n}\n.ui-grid[dir=rtl] .ui-grid-filter-container .ui-grid-filter-button {\n  right: initial;\n  left: 0;\n}\n.ui-grid[dir=rtl] .ui-grid-filter-container .ui-grid-filter-button [class^=\"ui-grid-icon\"] {\n  right: initial;\n  left: 10px;\n}\n/*\n   Animation example, for spinners\n*/\n.ui-grid-animate-spin {\n  -moz-animation: ui-grid-spin 2s infinite linear;\n  -o-animation: ui-grid-spin 2s infinite linear;\n  -webkit-animation: ui-grid-spin 2s infinite linear;\n  animation: ui-grid-spin 2s infinite linear;\n  display: inline-block;\n}\n@-moz-keyframes ui-grid-spin {\n  0% {\n    -moz-transform: rotate(0deg);\n    -o-transform: rotate(0deg);\n    -webkit-transform: rotate(0deg);\n    transform: rotate(0deg);\n  }\n  100% {\n    -moz-transform: rotate(359deg);\n    -o-transform: rotate(359deg);\n    -webkit-transform: rotate(359deg);\n    transform: rotate(359deg);\n  }\n}\n@-webkit-keyframes ui-grid-spin {\n  0% {\n    -moz-transform: rotate(0deg);\n    -o-transform: rotate(0deg);\n    -webkit-transform: rotate(0deg);\n    transform: rotate(0deg);\n  }\n  100% {\n    -moz-transform: rotate(359deg);\n    -o-transform: rotate(359deg);\n    -webkit-transform: rotate(359deg);\n    transform: rotate(359deg);\n  }\n}\n@-o-keyframes ui-grid-spin {\n  0% {\n    -moz-transform: rotate(0deg);\n    -o-transform: rotate(0deg);\n    -webkit-transform: rotate(0deg);\n    transform: rotate(0deg);\n  }\n  100% {\n    -moz-transform: rotate(359deg);\n    -o-transform: rotate(359deg);\n    -webkit-transform: rotate(359deg);\n    transform: rotate(359deg);\n  }\n}\n@-ms-keyframes ui-grid-spin {\n  0% {\n    -moz-transform: rotate(0deg);\n    -o-transform: rotate(0deg);\n    -webkit-transform: rotate(0deg);\n    transform: rotate(0deg);\n  }\n  100% {\n    -moz-transform: rotate(359deg);\n    -o-transform: rotate(359deg);\n    -webkit-transform: rotate(359deg);\n    transform: rotate(359deg);\n  }\n}\n@keyframes ui-grid-spin {\n  0% {\n    -moz-transform: rotate(0deg);\n    -o-transform: rotate(0deg);\n    -webkit-transform: rotate(0deg);\n    transform: rotate(0deg);\n  }\n  100% {\n    -moz-transform: rotate(359deg);\n    -o-transform: rotate(359deg);\n    -webkit-transform: rotate(359deg);\n    transform: rotate(359deg);\n  }\n}\n/*---------------------------------------------------\n    LESS Elements 0.9\n  ---------------------------------------------------\n    A set of useful LESS mixins\n    More info at: http://lesselements.com\n  ---------------------------------------------------*/\n/* This file contains variable declarations (do not remove this line) */\n/*-- VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/\n/**\n* @section Grid styles\n*/\n/**\n* @section Header styles\n*/\n/** @description Colors for header gradient */\n/**\n* @section Grid body styles\n*/\n/** @description Colors used for row alternation */\n/**\n* @section Sort arrow colors\n*/\n/**\n* @section Scrollbar styles\n*/\n/**\n* @section font library path\n*/\n/*-- END VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/\n\n/* This file contains variable declarations (do not remove this line) */\n/*-- VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/\n/**\n* @section Grid styles\n*/\n/**\n* @section Header styles\n*/\n/** @description Colors for header gradient */\n/**\n* @section Grid body styles\n*/\n/** @description Colors used for row alternation */\n/**\n* @section Sort arrow colors\n*/\n/**\n* @section Scrollbar styles\n*/\n/**\n* @section font library path\n*/\n/*-- END VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/\n.ui-grid-cell-focus {\n  outline: 0;\n  background-color: #b3c4c7;\n}\n\n/* This file contains variable declarations (do not remove this line) */\n/*-- VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/\n/**\n* @section Grid styles\n*/\n/**\n* @section Header styles\n*/\n/** @description Colors for header gradient */\n/**\n* @section Grid body styles\n*/\n/** @description Colors used for row alternation */\n/**\n* @section Sort arrow colors\n*/\n/**\n* @section Scrollbar styles\n*/\n/**\n* @section font library path\n*/\n/*-- END VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/\ndiv.ui-grid-cell input {\n  border-radius: inherit;\n  padding: 0;\n  width: 100%;\n  color: inherit;\n  height: auto;\n  font: inherit;\n  outline: none;\n}\ndiv.ui-grid-cell input:focus {\n  color: inherit;\n  outline: none;\n}\ndiv.ui-grid-cell input[type=\"checkbox\"] {\n  margin: 9px 0 0 6px;\n  width: auto;\n}\ndiv.ui-grid-cell input.ng-invalid {\n  border: 1px solid #fc8f8f;\n}\ndiv.ui-grid-cell input.ng-valid {\n  border: 1px solid #d4d4d4;\n}\n\n/* This file contains variable declarations (do not remove this line) */\n/*-- VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/\n/**\n* @section Grid styles\n*/\n/**\n* @section Header styles\n*/\n/** @description Colors for header gradient */\n/**\n* @section Grid body styles\n*/\n/** @description Colors used for row alternation */\n/**\n* @section Sort arrow colors\n*/\n/**\n* @section Scrollbar styles\n*/\n/**\n* @section font library path\n*/\n/*-- END VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/\n.expandableRow .ui-grid-row:nth-child(odd) .ui-grid-cell {\n  background-color: #fdfdfd;\n}\n.expandableRow .ui-grid-row:nth-child(even) .ui-grid-cell {\n  background-color: #f3f3f3;\n}\n\n/* This file contains variable declarations (do not remove this line) */\n/*-- VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/\n/**\n* @section Grid styles\n*/\n/**\n* @section Header styles\n*/\n/** @description Colors for header gradient */\n/**\n* @section Grid body styles\n*/\n/** @description Colors used for row alternation */\n/**\n* @section Sort arrow colors\n*/\n/**\n* @section Scrollbar styles\n*/\n/**\n* @section font library path\n*/\n/*-- END VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/\n\n/* This file contains variable declarations (do not remove this line) */\n/*-- VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/\n/**\n* @section Grid styles\n*/\n/**\n* @section Header styles\n*/\n/** @description Colors for header gradient */\n/**\n* @section Grid body styles\n*/\n/** @description Colors used for row alternation */\n/**\n* @section Sort arrow colors\n*/\n/**\n* @section Scrollbar styles\n*/\n/**\n* @section font library path\n*/\n/*-- END VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/\n\n/* This file contains variable declarations (do not remove this line) */\n/*-- VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/\n/**\n* @section Grid styles\n*/\n/**\n* @section Header styles\n*/\n/** @description Colors for header gradient */\n/**\n* @section Grid body styles\n*/\n/** @description Colors used for row alternation */\n/**\n* @section Sort arrow colors\n*/\n/**\n* @section Scrollbar styles\n*/\n/**\n* @section font library path\n*/\n/*-- END VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/\n.movingColumn {\n  position: fixed;\n  border: 1px solid #d4d4d4;\n  box-shadow: inset 0 0 14px rgba(0, 0, 0, 0.2);\n}\n.movingColumn .ui-grid-icon-angle-down {\n  display: none;\n}\n\n.ui-grid-pager-panel {\n  position: absolute;\n  left: 0;\n  bottom: 0;\n  width: 100%;\n  padding-top: 3px;\n  padding-bottom: 3px;\n}\n.ui-grid-pager-container {\n  float: left;\n}\n.ui-grid-pager-control {\n  margin-right: 10px;\n  margin-left: 10px;\n  min-width: 135px;\n  float: left;\n}\n.ui-grid-pager-control button {\n  height: 25px;\n  min-width: 26px;\n}\n.ui-grid-pager-control input {\n  height: 26px;\n  width: 50px;\n  vertical-align: top;\n}\n.ui-grid-pager-control .first-bar {\n  width: 10px;\n  border-left: 2px solid #4d4d4d;\n  margin-top: -6px;\n  height: 12px;\n  margin-left: -3px;\n}\n.ui-grid-pager-control .first-triangle {\n  width: 0;\n  height: 0;\n  border-style: solid;\n  border-width: 5px 8.7px 5px 0;\n  border-color: transparent #4d4d4d transparent transparent;\n  margin-left: 2px;\n}\n.ui-grid-pager-control .next-triangle {\n  margin-left: 1px;\n}\n.ui-grid-pager-control .prev-triangle {\n  margin-left: 0;\n}\n.ui-grid-pager-control .last-triangle {\n  width: 0;\n  height: 0;\n  border-style: solid;\n  border-width: 5px 0 5px 8.7px;\n  border-color: transparent transparent transparent #4d4d4d;\n  margin-left: -1px;\n}\n.ui-grid-pager-control .last-bar {\n  width: 10px;\n  border-left: 2px solid #4d4d4d;\n  margin-top: -6px;\n  height: 12px;\n  margin-left: 1px;\n}\n.ui-grid-pager-row-count-picker {\n  float: left;\n}\n.ui-grid-pager-row-count-picker select {\n  height: 26px;\n  width: 60px;\n}\n.ui-grid-pager-row-count-picker .ui-grid-pager-row-count-label {\n  margin-top: 3px;\n}\n.ui-grid-pager-count-container {\n  float: right;\n  margin-top: 4px;\n  min-width: 50px;\n}\n.ui-grid-pager-count-container .ui-grid-pager-count {\n  margin-right: 10px;\n  margin-left: 10px;\n  float: right;\n}\n\n/* This file contains variable declarations (do not remove this line) */\n/*-- VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/\n/**\n* @section Grid styles\n*/\n/**\n* @section Header styles\n*/\n/** @description Colors for header gradient */\n/**\n* @section Grid body styles\n*/\n/** @description Colors used for row alternation */\n/**\n* @section Sort arrow colors\n*/\n/**\n* @section Scrollbar styles\n*/\n/**\n* @section font library path\n*/\n/*-- END VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/\n.ui-grid-pinned-container {\n  float: left;\n}\n.ui-grid-pinned-container.ui-grid-pinned-container-left .ui-grid-header-cell:last-child {\n  box-sizing: border-box;\n  border-right: 1px solid;\n  border-width: 1px;\n  border-color: #aeaeae;\n}\n.ui-grid-pinned-container.ui-grid-pinned-container-left .ui-grid-cell:last-child {\n  box-sizing: border-box;\n  border-right: 1px solid;\n  border-width: 1px;\n  border-color: #aeaeae;\n}\n.ui-grid-pinned-container.ui-grid-pinned-container-left .ui-grid-header-cell:not(:last-child) .ui-grid-vertical-bar,\n.ui-grid-pinned-container .ui-grid-cell:not(:last-child) .ui-grid-vertical-bar {\n  width: 1px;\n}\n.ui-grid-pinned-container.ui-grid-pinned-container-left .ui-grid-header-cell:not(:last-child) .ui-grid-vertical-bar {\n  background-color: #d4d4d4;\n}\n.ui-grid-pinned-container.ui-grid-pinned-container-left .ui-grid-cell:not(:last-child) .ui-grid-vertical-bar {\n  background-color: #aeaeae;\n}\n.ui-grid-pinned-container.ui-grid-pinned-container-left .ui-grid-header-cell:last-child .ui-grid-vertical-bar {\n  right: -1px;\n  width: 1px;\n  background-color: #aeaeae;\n}\n.ui-grid-pinned-container.ui-grid-pinned-container-right .ui-grid-header-cell:first-child {\n  box-sizing: border-box;\n  border-left: 1px solid;\n  border-width: 1px;\n  border-color: #aeaeae;\n}\n.ui-grid-pinned-container.ui-grid-pinned-container-right .ui-grid-cell:first-child {\n  box-sizing: border-box;\n  border-left: 1px solid;\n  border-width: 1px;\n  border-color: #aeaeae;\n}\n.ui-grid-pinned-container.ui-grid-pinned-container-right .ui-grid-header-cell:not(:first-child) .ui-grid-vertical-bar,\n.ui-grid-pinned-container .ui-grid-cell:not(:first-child) .ui-grid-vertical-bar {\n  width: 1px;\n}\n.ui-grid-pinned-container.ui-grid-pinned-container-right .ui-grid-header-cell:not(:first-child) .ui-grid-vertical-bar {\n  background-color: #d4d4d4;\n}\n.ui-grid-pinned-container.ui-grid-pinned-container-right .ui-grid-cell:not(:last-child) .ui-grid-vertical-bar {\n  background-color: #aeaeae;\n}\n.ui-grid-pinned-container.ui-grid-pinned-container-first .ui-grid-header-cell:first-child .ui-grid-vertical-bar {\n  left: -1px;\n  width: 1px;\n  background-color: #aeaeae;\n}\n.ui-grid-render-container-body {\n  float: left;\n}\n\n/* This file contains variable declarations (do not remove this line) */\n/*-- VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/\n/**\n* @section Grid styles\n*/\n/**\n* @section Header styles\n*/\n/** @description Colors for header gradient */\n/**\n* @section Grid body styles\n*/\n/** @description Colors used for row alternation */\n/**\n* @section Sort arrow colors\n*/\n/**\n* @section Scrollbar styles\n*/\n/**\n* @section font library path\n*/\n/*-- END VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/\n.ui-grid-column-resizer {\n  top: 0;\n  bottom: 0;\n  width: 5px;\n  position: absolute;\n  cursor: col-resize;\n}\n.ui-grid-column-resizer.left {\n  left: 0;\n}\n.ui-grid-column-resizer.right {\n  right: 0;\n}\n.ui-grid.column-resizing {\n  cursor: col-resize;\n}\n.ui-grid.column-resizing .ui-grid-resize-overlay {\n  position: absolute;\n  top: 0;\n  height: 100%;\n  width: 1px;\n  background-color: #aeaeae;\n}\n\n/* This file contains variable declarations (do not remove this line) */\n/*-- VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/\n/**\n* @section Grid styles\n*/\n/**\n* @section Header styles\n*/\n/** @description Colors for header gradient */\n/**\n* @section Grid body styles\n*/\n/** @description Colors used for row alternation */\n/**\n* @section Sort arrow colors\n*/\n/**\n* @section Scrollbar styles\n*/\n/**\n* @section font library path\n*/\n/*-- END VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/\n.ui-grid-row-saving .ui-grid-cell {\n  color: #848484 !important;\n}\n.ui-grid-row-dirty .ui-grid-cell {\n  color: #610b38;\n}\n.ui-grid-row-error .ui-grid-cell {\n  color: #ff0000 !important;\n}\n\n/* This file contains variable declarations (do not remove this line) */\n/*-- VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/\n/**\n* @section Grid styles\n*/\n/**\n* @section Header styles\n*/\n/** @description Colors for header gradient */\n/**\n* @section Grid body styles\n*/\n/** @description Colors used for row alternation */\n/**\n* @section Sort arrow colors\n*/\n/**\n* @section Scrollbar styles\n*/\n/**\n* @section font library path\n*/\n/*-- END VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/\n.ui-grid-row-selected > [ui-grid-row] > .ui-grid-cell {\n  background-color: #c9dde1 !important;\n}\n.ui-grid-disable-selection {\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  cursor: default;\n}\n.ui-grid-selection-row-header-buttons {\n  cursor: pointer;\n  opacity: 0.1;\n}\n.ui-grid-selection-row-header-buttons.ui-grid-row-selected {\n  opacity: 1;\n}\n.ui-grid-selection-row-header-buttons.ui-grid-all-selected {\n  opacity: 1;\n}\n\n.ui-grid-icon-plus-squared:before {\n  content: '\\c350';\n}\n/* '썐' */\n.ui-grid-icon-minus-squared:before {\n  content: '\\c351';\n}\n/* '썑' */\n.ui-grid-icon-search:before {\n  content: '\\c352';\n}\n/* '썒' */\n.ui-grid-icon-cancel:before {\n  content: '\\c353';\n}\n/* '썓' */\n.ui-grid-icon-info-circled:before {\n  content: '\\c354';\n}\n/* '썔' */\n.ui-grid-icon-lock:before {\n  content: '\\c355';\n}\n/* '썕' */\n.ui-grid-icon-lock-open:before {\n  content: '\\c356';\n}\n/* '썖' */\n.ui-grid-icon-pencil:before {\n  content: '\\c357';\n}\n/* '썗' */\n.ui-grid-icon-down-dir:before {\n  content: '\\c358';\n}\n/* '썘' */\n.ui-grid-icon-up-dir:before {\n  content: '\\c359';\n}\n/* '썙' */\n.ui-grid-icon-left-dir:before {\n  content: '\\c35a';\n}\n/* '썚' */\n.ui-grid-icon-right-dir:before {\n  content: '\\c35b';\n}\n/* '썛' */\n.ui-grid-icon-left-open:before {\n  content: '\\c35c';\n}\n/* '썜' */\n.ui-grid-icon-right-open:before {\n  content: '\\c35d';\n}\n/* '썝' */\n.ui-grid-icon-angle-down:before {\n  content: '\\c35e';\n}\n/* '썞' */\n.ui-grid-icon-filter:before {\n  content: '\\c35f';\n}\n/* '썟' */\n.ui-grid-icon-sort-alt-up:before {\n  content: '\\c360';\n}\n/* '썠' */\n.ui-grid-icon-sort-alt-down:before {\n  content: '\\c361';\n}\n/* '썡' */\n.ui-grid-icon-ok:before {\n  content: '\\c362';\n}\n/* '썢' */\n.ui-grid-icon-menu:before {\n  content: '\\c363';\n}\n/* '썣' */\n.ui-grid-icon-spin5:before {\n  content: '\\ea61';\n}\n/* '' */\n"
  },
  {
    "path": "flowable-ui-web/task/libs/ui-grid_3.0.0/ui-grid.js",
    "content": "/*!\n * ui-grid - v3.0.0-rc.19 - 2015-02-11\n * Copyright (c) 2015 ; License: MIT \n */\n\n(function () {\n  'use strict';\n  angular.module('ui.grid.i18n', []);\n  angular.module('ui.grid', ['ui.grid.i18n']);\n})();\n(function () {\n  'use strict';\n  angular.module('ui.grid').constant('uiGridConstants', {\n    LOG_DEBUG_MESSAGES: true,\n    LOG_WARN_MESSAGES: true,\n    LOG_ERROR_MESSAGES: true,\n    CUSTOM_FILTERS: /CUSTOM_FILTERS/g,\n    COL_FIELD: /COL_FIELD/g,\n    MODEL_COL_FIELD: /MODEL_COL_FIELD/g,\n    DISPLAY_CELL_TEMPLATE: /DISPLAY_CELL_TEMPLATE/g,\n    TEMPLATE_REGEXP: /<.+>/,\n    FUNC_REGEXP: /(\\([^)]*\\))?$/,\n    DOT_REGEXP: /\\./g,\n    APOS_REGEXP: /'/g,\n    BRACKET_REGEXP: /^(.*)((?:\\s*\\[\\s*\\d+\\s*\\]\\s*)|(?:\\s*\\[\\s*\"(?:[^\"\\\\]|\\\\.)*\"\\s*\\]\\s*)|(?:\\s*\\[\\s*'(?:[^'\\\\]|\\\\.)*'\\s*\\]\\s*))(.*)$/,\n    COL_CLASS_PREFIX: 'ui-grid-col',\n    events: {\n      GRID_SCROLL: 'uiGridScroll',\n      COLUMN_MENU_SHOWN: 'uiGridColMenuShown',\n      ITEM_DRAGGING: 'uiGridItemDragStart', // For any item being dragged\n      COLUMN_HEADER_CLICK: 'uiGridColumnHeaderClick'\n    },\n    // copied from http://www.lsauer.com/2011/08/javascript-keymap-keycodes-in-json.html\n    keymap: {\n      TAB: 9,\n      STRG: 17,\n      CTRL: 17,\n      CTRLRIGHT: 18,\n      CTRLR: 18,\n      SHIFT: 16,\n      RETURN: 13,\n      ENTER: 13,\n      BACKSPACE: 8,\n      BCKSP: 8,\n      ALT: 18,\n      ALTR: 17,\n      ALTRIGHT: 17,\n      SPACE: 32,\n      WIN: 91,\n      MAC: 91,\n      FN: null,\n      PG_UP: 33,\n      PG_DOWN: 34,\n      UP: 38,\n      DOWN: 40,\n      LEFT: 37,\n      RIGHT: 39,\n      ESC: 27,\n      DEL: 46,\n      F1: 112,\n      F2: 113,\n      F3: 114,\n      F4: 115,\n      F5: 116,\n      F6: 117,\n      F7: 118,\n      F8: 119,\n      F9: 120,\n      F10: 121,\n      F11: 122,\n      F12: 123\n    },\n    ASC: 'asc',\n    DESC: 'desc',\n    filter: {\n      STARTS_WITH: 2,\n      ENDS_WITH: 4,\n      EXACT: 8,\n      CONTAINS: 16,\n      GREATER_THAN: 32,\n      GREATER_THAN_OR_EQUAL: 64,\n      LESS_THAN: 128,\n      LESS_THAN_OR_EQUAL: 256,\n      NOT_EQUAL: 512\n    },\n\n    aggregationTypes: {\n      sum: 2,\n      count: 4,\n      avg: 8,\n      min: 16,\n      max: 32\n    },\n\n    // TODO(c0bra): Create full list of these somehow. NOTE: do any allow a space before or after them?\n    CURRENCY_SYMBOLS: ['ƒ', '$', '£', '$', '¤', '¥', '៛', '₩', '₱', '฿', '₫'],\n\n    scrollDirection: {\n      UP: 'up',\n      DOWN: 'down',\n      LEFT: 'left',\n      RIGHT: 'right',\n      NONE: 'none'\n\n    },\n\n    dataChange: {\n      ALL: 'all',\n      EDIT: 'edit',\n      ROW: 'row',\n      COLUMN: 'column',\n      OPTIONS: 'options'\n    },\n    scrollbars: {\n      NEVER: 0,\n      ALWAYS: 1\n      //WHEN_NEEDED: 2\n    }\n  });\n\n})();\nangular.module('ui.grid').directive('uiGridCell', ['$compile', '$parse', 'gridUtil', 'uiGridConstants', function ($compile, $parse, gridUtil, uiGridConstants) {\n  var uiGridCell = {\n    priority: 0,\n    scope: false,\n    require: '?^uiGrid',\n    compile: function() {\n      return {\n        pre: function($scope, $elm, $attrs, uiGridCtrl) {\n          function compileTemplate() {\n            var compiledElementFn = $scope.col.compiledElementFn;\n\n            compiledElementFn($scope, function(clonedElement, scope) {\n              $elm.append(clonedElement);\n            });\n          }\n\n          // If the grid controller is present, use it to get the compiled cell template function\n          if (uiGridCtrl && $scope.col.compiledElementFn) {\n             compileTemplate();\n          }\n          // No controller, compile the element manually (for unit tests)\n          else {\n            if ( uiGridCtrl && !$scope.col.compiledElementFn ){\n              // gridUtil.logError('Render has been called before precompile.  Please log a ui-grid issue');  \n\n              $scope.col.getCompiledElementFn()\n                .then(function (compiledElementFn) {\n                  compiledElementFn($scope, function(clonedElement, scope) {\n                    $elm.append(clonedElement);\n                  });\n                });\n            }\n            else {\n              var html = $scope.col.cellTemplate\n                .replace(uiGridConstants.MODEL_COL_FIELD, 'row.entity.' + gridUtil.preEval($scope.col.field))\n                .replace(uiGridConstants.COL_FIELD, 'grid.getCellValue(row, col)');\n\n              var cellElement = $compile(html)($scope);\n              $elm.append(cellElement);\n            }\n          }\n        },\n        post: function($scope, $elm, $attrs, uiGridCtrl) {\n          var initColClass = $scope.col.getColClass(false);\n          $elm.addClass(initColClass);\n\n          var classAdded;\n          var updateClass = function( grid ){\n            var contents = $elm;\n            if ( classAdded ){\n              contents.removeClass( classAdded );\n              classAdded = null;\n            }\n\n            if (angular.isFunction($scope.col.cellClass)) {\n              classAdded = $scope.col.cellClass($scope.grid, $scope.row, $scope.col, $scope.rowRenderIndex, $scope.colRenderIndex);\n            }\n            else {\n              classAdded = $scope.col.cellClass;\n            }\n            contents.addClass(classAdded);\n          };\n\n          if ($scope.col.cellClass) {\n            updateClass();\n          }\n          \n          // Register a data change watch that would get triggered whenever someone edits a cell or modifies column defs\n          var dataChangeDereg = $scope.grid.registerDataChangeCallback( updateClass, [uiGridConstants.dataChange.COLUMN, uiGridConstants.dataChange.EDIT]);\n          \n          // watch the col and row to see if they change - which would indicate that we've scrolled or sorted or otherwise\n          // changed the row/col that this cell relates to, and we need to re-evaluate cell classes and maybe other things\n          var cellChangeFunction = function( n, o ){\n            if ( n !== o ) {\n              if ( classAdded || $scope.col.cellClass ){\n                updateClass();\n              }\n\n              // See if the column's internal class has changed\n              var newColClass = $scope.col.getColClass(false);\n              if (newColClass !== initColClass) {\n                $elm.removeClass(initColClass);\n                $elm.addClass(newColClass);\n                initColClass = newColClass;\n              }\n            }\n          };\n\n          // TODO(c0bra): Turn this into a deep array watch\n          var colWatchDereg = $scope.$watch( 'col', cellChangeFunction );\n          var rowWatchDereg = $scope.$watch( 'row', cellChangeFunction );\n          \n          \n          var deregisterFunction = function() {\n            dataChangeDereg();\n            colWatchDereg();\n            rowWatchDereg(); \n          };\n          \n          $scope.$on( '$destroy', deregisterFunction );\n          $elm.on( '$destroy', deregisterFunction );\n        }\n      };\n    }\n  };\n\n  return uiGridCell;\n}]);\n\n\n(function(){\n\nangular.module('ui.grid')\n.service('uiGridColumnMenuService', [ 'i18nService', 'uiGridConstants', 'gridUtil', \nfunction ( i18nService, uiGridConstants, gridUtil ) {\n/**\n *  @ngdoc service\n *  @name ui.grid.service:uiGridColumnMenuService\n *\n *  @description Services for working with column menus, factored out\n *  to make the code easier to understand\n */\n\n  var service = {\n    /**\n     * @ngdoc method\n     * @methodOf ui.grid.service:uiGridColumnMenuService\n     * @name initialize\n     * @description  Sets defaults, puts a reference to the $scope on \n     * the uiGridController\n     * @param {$scope} $scope the $scope from the uiGridColumnMenu\n     * @param {controller} uiGridCtrl the uiGridController for the grid\n     * we're on\n     * \n     */\n    initialize: function( $scope, uiGridCtrl ){\n      $scope.grid = uiGridCtrl.grid;\n\n      // Store a reference to this link/controller in the main uiGrid controller\n      // to allow showMenu later\n      uiGridCtrl.columnMenuScope = $scope;\n      \n      // Save whether we're shown or not so the columns can check\n      $scope.menuShown = false;\n    },\n    \n    \n    /**\n     * @ngdoc method\n     * @methodOf ui.grid.service:uiGridColumnMenuService\n     * @name setColMenuItemWatch\n     * @description  Setup a watch on $scope.col.menuItems, and update\n     * menuItems based on this.  $scope.col needs to be set by the column\n     * before calling the menu.\n     * @param {$scope} $scope the $scope from the uiGridColumnMenu\n     * @param {controller} uiGridCtrl the uiGridController for the grid\n     * we're on\n     * \n     */    \n    setColMenuItemWatch: function ( $scope ){\n      var deregFunction = $scope.$watch('col.menuItems', function (n, o) {\n        if (typeof(n) !== 'undefined' && n && angular.isArray(n)) {\n          n.forEach(function (item) {\n            if (typeof(item.context) === 'undefined' || !item.context) {\n              item.context = {};\n            }\n            item.context.col = $scope.col;\n          });\n\n          $scope.menuItems = $scope.defaultMenuItems.concat(n);\n        }\n        else {\n          $scope.menuItems = $scope.defaultMenuItems;\n        }\n      }); \n      \n      $scope.$on( '$destroy', deregFunction );     \n    },\n\n\n    /**\n     * @ngdoc boolean\n     * @name enableSorting\n     * @propertyOf ui.grid.class:GridOptions.columnDef\n     * @description (optional) True by default. When enabled, this setting adds sort\n     * widgets to the column header, allowing sorting of the data in the individual column.\n     */\n    /**\n     * @ngdoc method\n     * @methodOf ui.grid.service:uiGridColumnMenuService\n     * @name sortable\n     * @description  determines whether this column is sortable\n     * @param {$scope} $scope the $scope from the uiGridColumnMenu\n     * \n     */    \n    sortable: function( $scope ) {\n      if ( $scope.grid.options.enableSorting && typeof($scope.col) !== 'undefined' && $scope.col && $scope.col.enableSorting) {\n        return true;\n      }\n      else {\n        return false;\n      }\n    },\n    \n    /**\n     * @ngdoc method\n     * @methodOf ui.grid.service:uiGridColumnMenuService\n     * @name isActiveSort\n     * @description  determines whether the requested sort direction is current active, to \n     * allow highlighting in the menu\n     * @param {$scope} $scope the $scope from the uiGridColumnMenu\n     * @param {string} direction the direction that we'd have selected for us to be active\n     * \n     */  \n    isActiveSort: function( $scope, direction ){\n      return (typeof($scope.col) !== 'undefined' && typeof($scope.col.sort) !== 'undefined' && \n              typeof($scope.col.sort.direction) !== 'undefined' && $scope.col.sort.direction === direction);\n      \n    },\n    \n    /**\n     * @ngdoc boolean\n     * @name suppressRemoveSort\n     * @propertyOf ui.grid.class:GridOptions.columnDef\n     * @description (optional) False by default. When enabled, this setting hides the removeSort option\n     * in the menu.\n     */\n    /**\n     * @ngdoc method\n     * @methodOf ui.grid.service:uiGridColumnMenuService\n     * @name suppressRemoveSort\n     * @description  determines whether we should suppress the removeSort option\n     * @param {$scope} $scope the $scope from the uiGridColumnMenu\n     * \n     */  \n    suppressRemoveSort: function( $scope ) {\n      if ($scope.col && $scope.col.colDef && $scope.col.colDef.suppressRemoveSort) {\n        return true;\n      }\n      else {\n        return false;\n      }\n    },       \n\n\n    /**\n     * @ngdoc boolean\n     * @name enableHiding\n     * @propertyOf ui.grid.class:GridOptions.columnDef\n     * @description (optional) True by default. When set to false, this setting prevents a user from hiding the column\n     * using the column menu or the grid menu.\n     */\n    /**\n     * @ngdoc method\n     * @methodOf ui.grid.service:uiGridColumnMenuService\n     * @name hideable\n     * @description  determines whether a column can be hidden, by checking the enableHiding columnDef option\n     * @param {$scope} $scope the $scope from the uiGridColumnMenu\n     * \n     */  \n    hideable: function( $scope ) {\n      if (typeof($scope.col) !== 'undefined' && $scope.col && $scope.col.colDef && $scope.col.colDef.enableHiding === false ) {\n        return false;\n      }\n      else {\n        return true;\n      }\n    },     \n\n\n    /**\n     * @ngdoc method\n     * @methodOf ui.grid.service:uiGridColumnMenuService\n     * @name getDefaultMenuItems\n     * @description  returns the default menu items for a column menu\n     * @param {$scope} $scope the $scope from the uiGridColumnMenu\n     * \n     */     \n    getDefaultMenuItems: function( $scope ){\n      return [\n        {\n          title: i18nService.getSafeText('sort.ascending'),\n          icon: 'ui-grid-icon-sort-alt-up',\n          action: function($event) {\n            $event.stopPropagation();\n            $scope.sortColumn($event, uiGridConstants.ASC);\n          },\n          shown: function () {\n            return service.sortable( $scope );\n          },\n          active: function() {\n            return service.isActiveSort( $scope, uiGridConstants.ASC);\n          }\n        },\n        {\n          title: i18nService.getSafeText('sort.descending'),\n          icon: 'ui-grid-icon-sort-alt-down',\n          action: function($event) {\n            $event.stopPropagation();\n            $scope.sortColumn($event, uiGridConstants.DESC);\n          },\n          shown: function() {\n            return service.sortable( $scope );\n          },\n          active: function() {\n            return service.isActiveSort( $scope, uiGridConstants.DESC);\n          }\n        },\n        {\n          title: i18nService.getSafeText('sort.remove'),\n          icon: 'ui-grid-icon-cancel',\n          action: function ($event) {\n            $event.stopPropagation();\n            $scope.unsortColumn();\n          },\n          shown: function() {\n            return service.sortable( $scope ) && \n                   typeof($scope.col) !== 'undefined' && (typeof($scope.col.sort) !== 'undefined' && \n                   typeof($scope.col.sort.direction) !== 'undefined') && $scope.col.sort.direction !== null &&\n                  !service.suppressRemoveSort( $scope );\n          }\n        },\n        {\n          title: i18nService.getSafeText('column.hide'),\n          icon: 'ui-grid-icon-cancel',\n          shown: function() {\n            return service.hideable( $scope );\n          },\n          action: function ($event) {\n            $event.stopPropagation();\n            $scope.hideColumn();\n          }\n        }\n      ];\n    },\n    \n\n    /**\n     * @ngdoc method\n     * @methodOf ui.grid.service:uiGridColumnMenuService\n     * @name getColumnElementPosition\n     * @description  gets the position information needed to place the column\n     * menu below the column header\n     * @param {$scope} $scope the $scope from the uiGridColumnMenu\n     * @param {GridCol} column the column we want to position below\n     * @param {element} $columnElement the column element we want to position below\n     * @returns {hash} containing left, top, offset, height, width\n     * \n     */  \n    getColumnElementPosition: function( $scope, column, $columnElement ){\n      var positionData = {};\n      positionData.left = $columnElement[0].offsetLeft;\n      positionData.top = $columnElement[0].offsetTop;\n\n      // Get the grid scrollLeft\n      positionData.offset = 0;\n      if (column.grid.options.offsetLeft) {\n        positionData.offset = column.grid.options.offsetLeft;\n      }\n\n      positionData.height = gridUtil.elementHeight($columnElement, true);\n      positionData.width = gridUtil.elementWidth($columnElement, true);\n      \n      return positionData;\n    },\n    \n\n    /**\n     * @ngdoc method\n     * @methodOf ui.grid.service:uiGridColumnMenuService\n     * @name repositionMenu\n     * @description  Reposition the menu below the new column.  If the menu has no child nodes \n     * (i.e. it's not currently visible) then we guess it's width at 100, we'll be called again\n     * later to fix it\n     * @param {$scope} $scope the $scope from the uiGridColumnMenu\n     * @param {GridCol} column the column we want to position below\n     * @param {hash} positionData a hash containing left, top, offset, height, width\n     * @param {element} $elm the column menu element that we want to reposition\n     * @param {element} $columnElement the column element that we want to reposition underneath\n     * \n     */  \n    repositionMenu: function( $scope, column, positionData, $elm, $columnElement ) {\n      var menu = $elm[0].querySelectorAll('.ui-grid-menu');\n      var containerId = column.renderContainer ? column.renderContainer : 'body';\n      var renderContainer = column.grid.renderContainers[containerId];\n\n      // It's possible that the render container of the column we're attaching to is \n      // offset from the grid (i.e. pinned containers), we need to get the difference in the offsetLeft \n      // between the render container and the grid\n      var renderContainerElm = gridUtil.closestElm($columnElement, '.ui-grid-render-container');\n      var renderContainerOffset = renderContainerElm.getBoundingClientRect().left - $scope.grid.element[0].getBoundingClientRect().left;\n\n      var containerScrollLeft = renderContainerElm.querySelectorAll('.ui-grid-viewport')[0].scrollLeft;\n\n      // default value the last width for _this_ column, otherwise last width for _any_ column, otherwise default to 170\n      var myWidth = column.lastMenuWidth ? column.lastMenuWidth : ( $scope.lastMenuWidth ? $scope.lastMenuWidth : 170);\n      var paddingRight = column.lastMenuPaddingRight ? column.lastMenuPaddingRight : ( $scope.lastMenuPaddingRight ? $scope.lastMenuPaddingRight : 10);\n      \n      if ( menu.length !== 0 ){\n        var mid = menu[0].querySelectorAll('.ui-grid-menu-mid'); \n        if ( mid.length !== 0 && !angular.element(mid).hasClass('ng-hide') ) {\n          myWidth = gridUtil.elementWidth(menu, true);\n          $scope.lastMenuWidth = myWidth;\n          column.lastMenuWidth = myWidth;\n  \n          // TODO(c0bra): use padding-left/padding-right based on document direction (ltr/rtl), place menu on proper side\n          // Get the column menu right padding\n          paddingRight = parseInt(gridUtil.getStyles(angular.element(menu)[0])['paddingRight'], 10);\n          $scope.lastMenuPaddingRight = paddingRight;\n          column.lastMenuPaddingRight = paddingRight;\n        }\n      }\n      \n      var left = positionData.left + renderContainerOffset - containerScrollLeft + positionData.width - myWidth + paddingRight;\n      if (left < positionData.offset){\n        left = positionData.offset;\n      }\n\n      $elm.css('left', left + 'px');\n      $elm.css('top', (positionData.top + positionData.height) + 'px');\n    }    \n\n  };\n  \n  return service;\n}])\n\n\n.directive('uiGridColumnMenu', ['$timeout', 'gridUtil', 'uiGridConstants', 'uiGridColumnMenuService', \nfunction ($timeout, gridUtil, uiGridConstants, uiGridColumnMenuService) {\n/**\n * @ngdoc directive\n * @name ui.grid.directive:uiGridColumnMenu\n * @description  Provides the column menu framework, leverages uiGridMenu underneath\n * \n */\n\n  var uiGridColumnMenu = {\n    priority: 0,\n    scope: true,\n    require: '?^uiGrid',\n    templateUrl: 'ui-grid/uiGridColumnMenu',\n    replace: true,\n    link: function ($scope, $elm, $attrs, uiGridCtrl) {\n      var self = this;\n      \n      uiGridColumnMenuService.initialize( $scope, uiGridCtrl );\n\n      $scope.defaultMenuItems = uiGridColumnMenuService.getDefaultMenuItems( $scope );\n\n      // Set the menu items for use with the column menu. The user can later add additional items via the watch\n      $scope.menuItems = $scope.defaultMenuItems;\n      uiGridColumnMenuService.setColMenuItemWatch( $scope );\n\n  \n      /**\n       * @ngdoc method\n       * @methodOf ui.grid.directive:uiGridColumnMenu\n       * @name showMenu\n       * @description Shows the column menu.  If the menu is already displayed it\n       * calls the menu to ask it to hide (it will animate), then it repositions the menu\n       * to the right place whilst hidden (it will make an assumption on menu width), \n       * then it asks the menu to show (it will animate), then it repositions the menu again \n       * once we can calculate it's size.\n       * @param {GridCol} column the column we want to position below\n       * @param {element} $columnElement the column element we want to position below\n       */\n      $scope.showMenu = function(column, $columnElement, event) {\n        // Swap to this column\n        $scope.col = column;\n\n        // Get the position information for the column element\n        var colElementPosition = uiGridColumnMenuService.getColumnElementPosition( $scope, column, $columnElement );\n\n        if ($scope.menuShown) {\n          // we want to hide, then reposition, then show, but we want to wait for animations\n          // we set a variable, and then rely on the menu-hidden event to call the reposition and show\n          $scope.colElement = $columnElement;\n          $scope.colElementPosition = colElementPosition;\n          $scope.hideThenShow = true;\n\n          $scope.$broadcast('hide-menu', { originalEvent: event });\n        } else {\n          self.shown = $scope.menuShown = true;\n          uiGridColumnMenuService.repositionMenu( $scope, column, colElementPosition, $elm, $columnElement );\n\n          $scope.colElement = $columnElement;\n          $scope.colElementPosition = colElementPosition;\n          $scope.$broadcast('show-menu', { originalEvent: event });\n        } \n\n      };\n\n\n      /**\n       * @ngdoc method\n       * @methodOf ui.grid.directive:uiGridColumnMenu\n       * @name hideMenu\n       * @description Hides the column menu.\n       * @param {boolean} broadcastTrigger true if we were triggered by a broadcast\n       * from the menu itself - in which case don't broadcast again as we'll get\n       * an infinite loop\n       */\n      $scope.hideMenu = function( broadcastTrigger ) {\n        // delete $scope.col;\n        $scope.menuShown = false;\n        \n        if ( !broadcastTrigger ){\n          $scope.$broadcast('hide-menu');\n        }\n      };\n\n      \n      $scope.$on('menu-hidden', function() {\n        if ( $scope.hideThenShow ){\n          delete $scope.hideThenShow;\n\n          uiGridColumnMenuService.repositionMenu( $scope, $scope.col, $scope.colElementPosition, $elm, $scope.colElement );\n          $scope.$broadcast('show-menu');\n\n          $scope.menuShown = true;\n        } else {\n          $scope.hideMenu( true );\n        }\n      });\n      \n      $scope.$on('menu-shown', function() {\n        $timeout( function() {\n          uiGridColumnMenuService.repositionMenu( $scope, $scope.col, $scope.colElementPosition, $elm, $scope.colElement );\n          delete $scope.colElementPosition;\n          delete $scope.columnElement;\n        }, 200);\n      });\n\n \n      /* Column methods */\n      $scope.sortColumn = function (event, dir) {\n        event.stopPropagation();\n\n        $scope.grid.sortColumn($scope.col, dir, true)\n          .then(function () {\n            $scope.grid.refresh();\n            $scope.hideMenu();\n          });\n      };\n\n      $scope.unsortColumn = function () {\n        $scope.col.unsort();\n\n        $scope.grid.refresh();\n        $scope.hideMenu();\n      };\n\n      $scope.hideColumn = function () {\n        $scope.col.colDef.visible = false;\n\n        $scope.grid.refresh();\n        $scope.hideMenu();\n        $scope.grid.api.core.notifyDataChange( uiGridConstants.dataChange.COLUMN );\n        $scope.grid.api.core.raise.columnVisibilityChanged( $scope.col );        \n      };\n    },\n    \n    \n    \n    controller: ['$scope', function ($scope) {\n      var self = this;\n      \n      $scope.$watch('menuItems', function (n, o) {\n        self.menuItems = n;\n      });\n    }]\n  };\n\n  return uiGridColumnMenu;\n\n}]);\n\n})();\n(function () {\n  'use strict';\n\n  angular.module('ui.grid').directive('uiGridFooterCell', ['$timeout', 'gridUtil', 'uiGridConstants', '$compile',\n  function ($timeout, gridUtil, uiGridConstants, $compile) {\n    var uiGridFooterCell = {\n      priority: 0,\n      scope: {\n        col: '=',\n        row: '=',\n        renderIndex: '='\n      },\n      replace: true,\n      require: '^uiGrid',\n      compile: function compile(tElement, tAttrs, transclude) {\n        return {\n          pre: function ($scope, $elm, $attrs, uiGridCtrl) {\n            var cellFooter = $compile($scope.col.footerCellTemplate)($scope);\n            $elm.append(cellFooter);\n          },\n          post: function ($scope, $elm, $attrs, uiGridCtrl) {\n            //$elm.addClass($scope.col.getColClass(false));\n            $scope.grid = uiGridCtrl.grid;\n\n            $elm.addClass($scope.col.getColClass(false));\n\n            // apply any footerCellClass\n            var classAdded;\n            var updateClass = function( grid ){\n              var contents = $elm;\n              if ( classAdded ){\n                contents.removeClass( classAdded );\n                classAdded = null;\n              }\n  \n              if (angular.isFunction($scope.col.footerCellClass)) {\n                classAdded = $scope.col.footerCellClass($scope.grid, $scope.row, $scope.col, $scope.rowRenderIndex, $scope.colRenderIndex);\n              }\n              else {\n                classAdded = $scope.col.footerCellClass;\n              }\n              contents.addClass(classAdded);\n            };\n  \n            if ($scope.col.footerCellClass) {\n              updateClass();\n            }\n\n            // Register a data change watch that would get triggered whenever someone edits a cell or modifies column defs\n            var dataChangeDereg = $scope.grid.registerDataChangeCallback( updateClass, [uiGridConstants.dataChange.COLUMN]);\n\n            $scope.$on( '$destroy', dataChangeDereg );\n          }\n        };\n      }\n    };\n\n    return uiGridFooterCell;\n  }]);\n\n})();\n\n(function () {\n  'use strict';\n\n  angular.module('ui.grid').directive('uiGridFooter', ['$templateCache', '$compile', 'uiGridConstants', 'gridUtil', '$timeout', function ($templateCache, $compile, uiGridConstants, gridUtil, $timeout) {\n    var defaultTemplate = 'ui-grid/ui-grid-footer';\n\n    return {\n      restrict: 'EA',\n      replace: true,\n      // priority: 1000,\n      require: ['^uiGrid', '^uiGridRenderContainer'],\n      scope: true,\n      compile: function ($elm, $attrs) {\n        return {\n          pre: function ($scope, $elm, $attrs, controllers) {\n            var uiGridCtrl = controllers[0];\n            var containerCtrl = controllers[1];\n\n            $scope.grid = uiGridCtrl.grid;\n            $scope.colContainer = containerCtrl.colContainer;\n\n            containerCtrl.footer = $elm;\n\n            var footerTemplate = ($scope.grid.options.footerTemplate) ? $scope.grid.options.footerTemplate : defaultTemplate;\n            gridUtil.getTemplate(footerTemplate)\n              .then(function (contents) {\n                var template = angular.element(contents);\n\n                var newElm = $compile(template)($scope);\n                $elm.append(newElm);\n\n                if (containerCtrl) {\n                  // Inject a reference to the footer viewport (if it exists) into the grid controller for use in the horizontal scroll handler below\n                  var footerViewport = $elm[0].getElementsByClassName('ui-grid-footer-viewport')[0];\n\n                  if (footerViewport) {\n                    containerCtrl.footerViewport = footerViewport;\n                  }\n                }\n              });\n          },\n\n          post: function ($scope, $elm, $attrs, controllers) {\n            var uiGridCtrl = controllers[0];\n            var containerCtrl = controllers[1];\n\n            // gridUtil.logDebug('ui-grid-footer link');\n\n            var grid = uiGridCtrl.grid;\n\n            // Don't animate footer cells\n            gridUtil.disableAnimations($elm);\n\n            containerCtrl.footer = $elm;\n\n            var footerViewport = $elm[0].getElementsByClassName('ui-grid-footer-viewport')[0];\n            if (footerViewport) {\n              containerCtrl.footerViewport = footerViewport;\n            }\n          }\n        };\n      }\n    };\n  }]);\n\n})();\n(function () {\n  'use strict';\n\n  angular.module('ui.grid').directive('uiGridGridFooter', ['$templateCache', '$compile', 'uiGridConstants', 'gridUtil', '$timeout', function ($templateCache, $compile, uiGridConstants, gridUtil, $timeout) {\n    var defaultTemplate = 'ui-grid/ui-grid-grid-footer';\n\n    return {\n      restrict: 'EA',\n      replace: true,\n      // priority: 1000,\n      require: '^uiGrid',\n      scope: true,\n      compile: function ($elm, $attrs) {\n        return {\n          pre: function ($scope, $elm, $attrs, uiGridCtrl) {\n\n            $scope.grid = uiGridCtrl.grid;\n\n            var footerTemplate = ($scope.grid.options.gridFooterTemplate) ? $scope.grid.options.gridFooterTemplate : defaultTemplate;\n            gridUtil.getTemplate(footerTemplate)\n              .then(function (contents) {\n                var template = angular.element(contents);\n\n                var newElm = $compile(template)($scope);\n                $elm.append(newElm);\n              });\n          },\n\n          post: function ($scope, $elm, $attrs, controllers) {\n\n          }\n        };\n      }\n    };\n  }]);\n\n})();\n(function(){\n  'use strict';\n\n  angular.module('ui.grid').directive('uiGridGroupPanel', [\"$compile\", \"uiGridConstants\", \"gridUtil\", function($compile, uiGridConstants, gridUtil) {\n    var defaultTemplate = 'ui-grid/ui-grid-group-panel';\n\n    return {\n      restrict: 'EA',\n      replace: true,\n      require: '?^uiGrid',\n      scope: false,\n      compile: function($elm, $attrs) {\n        return {\n          pre: function ($scope, $elm, $attrs, uiGridCtrl) {\n            var groupPanelTemplate = $scope.grid.options.groupPanelTemplate  || defaultTemplate;\n\n             gridUtil.getTemplate(groupPanelTemplate)\n              .then(function (contents) {\n                var template = angular.element(contents);\n                \n                var newElm = $compile(template)($scope);\n                $elm.append(newElm);\n              });\n          },\n\n          post: function ($scope, $elm, $attrs, uiGridCtrl) {\n            $elm.bind('$destroy', function() {\n              // scrollUnbinder();\n            });\n          }\n        };\n      }\n    };\n  }]);\n\n})();\n(function(){\n  'use strict';\n\n  angular.module('ui.grid').directive('uiGridHeaderCell', ['$compile', '$timeout', '$window', '$document', 'gridUtil', 'uiGridConstants', 'ScrollEvent',\n  function ($compile, $timeout, $window, $document, gridUtil, uiGridConstants, ScrollEvent) {\n    // Do stuff after mouse has been down this many ms on the header cell\n    var mousedownTimeout = 500;\n\n    var uiGridHeaderCell = {\n      priority: 0,\n      scope: {\n        col: '=',\n        row: '=',\n        renderIndex: '='\n      },\n      require: ['?^uiGrid', '^uiGridRenderContainer'],\n      replace: true,\n      compile: function() {\n        return {\n          pre: function ($scope, $elm, $attrs) {\n            var cellHeader = $compile($scope.col.headerCellTemplate)($scope);\n            $elm.append(cellHeader);\n          },\n          \n          post: function ($scope, $elm, $attrs, controllers) {\n            var uiGridCtrl = controllers[0];\n            var renderContainerCtrl = controllers[1];\n\n            $scope.grid = uiGridCtrl.grid;\n\n            $scope.renderContainer = uiGridCtrl.grid.renderContainers[renderContainerCtrl.containerId];\n            \n            var initColClass = $scope.col.getColClass(false);\n            $elm.addClass(initColClass);\n    \n            // Hide the menu by default\n            $scope.menuShown = false;\n    \n            // Put asc and desc sort directions in scope\n            $scope.asc = uiGridConstants.ASC;\n            $scope.desc = uiGridConstants.DESC;\n    \n            // Store a reference to menu element\n            var $colMenu = angular.element( $elm[0].querySelectorAll('.ui-grid-header-cell-menu') );\n    \n            var $contentsElm = angular.element( $elm[0].querySelectorAll('.ui-grid-cell-contents') );\n    \n\n            // apply any headerCellClass\n            var classAdded;\n            var updateClass = function( grid ){\n              var contents = $elm;\n              if ( classAdded ){\n                contents.removeClass( classAdded );\n                classAdded = null;\n              }\n  \n              if (angular.isFunction($scope.col.headerCellClass)) {\n                classAdded = $scope.col.headerCellClass($scope.grid, $scope.row, $scope.col, $scope.rowRenderIndex, $scope.colRenderIndex);\n              }\n              else {\n                classAdded = $scope.col.headerCellClass;\n              }\n              contents.addClass(classAdded);\n              \n              var rightMostContainer = $scope.grid.renderContainers['right'] ? $scope.grid.renderContainers['right'] : $scope.grid.renderContainers['body'];\n              $scope.isLastCol = ( $scope.col === rightMostContainer.visibleColumnCache[ rightMostContainer.visibleColumnCache.length - 1 ] );\n            };\n\n            $scope.$watch('col', function (n, o) {\n              if (n !== o) {\n                // See if the column's internal class has changed\n                var newColClass = $scope.col.getColClass(false);\n                if (newColClass !== initColClass) {\n                  $elm.removeClass(initColClass);\n                  $elm.addClass(newColClass);\n                  initColClass = newColClass;\n                }\n              }\n            });\n  \n            updateClass();\n            \n            // Register a data change watch that would get triggered whenever someone edits a cell or modifies column defs\n            var dataChangeDereg = $scope.grid.registerDataChangeCallback( updateClass, [uiGridConstants.dataChange.COLUMN]);\n\n            $scope.$on( '$destroy', dataChangeDereg );            \n\n\n            // Figure out whether this column is sortable or not\n            if (uiGridCtrl.grid.options.enableSorting && $scope.col.enableSorting) {\n              $scope.sortable = true;\n            }\n            else {\n              $scope.sortable = false;\n            }\n    \n            // Figure out whether this column is filterable or not\n            if (uiGridCtrl.grid.options.enableFiltering && $scope.col.enableFiltering) {\n              $scope.filterable = true;\n            }\n            else {\n              $scope.filterable = false;\n            }\n            \n            // figure out whether we support column menus\n            if ($scope.col.grid.options && $scope.col.grid.options.enableColumnMenus !== false && \n                    $scope.col.colDef && $scope.col.colDef.enableColumnMenu !== false){\n              $scope.colMenu = true;\n            } else {\n              $scope.colMenu = false;\n            }\n    \n            function handleClick(event) {\n              // If the shift key is being held down, add this column to the sort\n              var add = false;\n              if (event.shiftKey) {\n                add = true;\n              }\n    \n              // Sort this column then rebuild the grid's rows\n              uiGridCtrl.grid.sortColumn($scope.col, add)\n                .then(function () {\n                  if (uiGridCtrl.columnMenuScope) { uiGridCtrl.columnMenuScope.hideMenu(); }\n                  uiGridCtrl.grid.refresh();\n                });\n            }\n    \n            /**\n            * @ngdoc property\n            * @name enableColumnMenu\n            * @propertyOf ui.grid.class:GridOptions.columnDef\n            * @description if column menus are enabled, controls the column menus for this specific\n            * column (i.e. if gridOptions.enableColumnMenus, then you can control column menus\n            * using this option. If gridOptions.enableColumnMenus === false then you get no column\n            * menus irrespective of the value of this option ).  Defaults to true.\n            *\n            */\n            /**\n            * @ngdoc property\n            * @name enableColumnMenus\n            * @propertyOf ui.grid.class:GridOptions.columnDef\n            * @description Override for column menus everywhere - if set to false then you get no\n            * column menus.  Defaults to true.\n            *\n            */\n\n            if ($scope.sortable || $scope.colMenu) {\n              // Long-click (for mobile)\n              var cancelMousedownTimeout;\n              var mousedownStartTime = 0;\n\n              var downEvent = gridUtil.isTouchEnabled() ? 'touchstart' : 'mousedown';\n              $contentsElm.on(downEvent, function(event) {\n                event.stopPropagation();\n\n                if (typeof(event.originalEvent) !== 'undefined' && event.originalEvent !== undefined) {\n                  event = event.originalEvent;\n                }\n      \n                // Don't show the menu if it's not the left button\n                if (event.button && event.button !== 0) {\n                  return;\n                }\n      \n                mousedownStartTime = (new Date()).getTime();\n      \n                cancelMousedownTimeout = $timeout(function() { }, mousedownTimeout);\n      \n                cancelMousedownTimeout.then(function () {\n                  if ( $scope.colMenu ) {\n                    uiGridCtrl.columnMenuScope.showMenu($scope.col, $elm, event);\n                  }\n                });\n\n                uiGridCtrl.fireEvent(uiGridConstants.events.COLUMN_HEADER_CLICK, {event: event, columnName: $scope.col.colDef.name});\n              });\n        \n              var upEvent = gridUtil.isTouchEnabled() ? 'touchend' : 'mouseup';\n              $contentsElm.on(upEvent, function () {\n                $timeout.cancel(cancelMousedownTimeout);\n              });\n  \n              $scope.$on('$destroy', function () {\n                $contentsElm.off('mousedown touchstart');\n              });\n            }\n\n\n            $scope.toggleMenu = function(event) {\n              event.stopPropagation();\n    \n              // If the menu is already showing...\n              if (uiGridCtrl.columnMenuScope.menuShown) {\n                // ... and we're the column the menu is on...\n                if (uiGridCtrl.columnMenuScope.col === $scope.col) {\n                  // ... hide it\n                  uiGridCtrl.columnMenuScope.hideMenu();\n                }\n                // ... and we're NOT the column the menu is on\n                else {\n                  // ... move the menu to our column\n                  uiGridCtrl.columnMenuScope.showMenu($scope.col, $elm);\n                }\n              }\n              // If the menu is NOT showing\n              else {\n                // ... show it on our column\n                uiGridCtrl.columnMenuScope.showMenu($scope.col, $elm);\n              }\n            };\n    \n            // If this column is sortable, add a click event handler\n            if ($scope.sortable) {\n              var clickEvent = gridUtil.isTouchEnabled() ? 'touchend' : 'click';\n              $contentsElm.on(clickEvent, function(event) {\n                event.stopPropagation();\n    \n                $timeout.cancel(cancelMousedownTimeout);\n    \n                var mousedownEndTime = (new Date()).getTime();\n                var mousedownTime = mousedownEndTime - mousedownStartTime;\n    \n                if (mousedownTime > mousedownTimeout) {\n                  // long click, handled above with mousedown\n                }\n                else {\n                  // short click\n                  handleClick(event);\n                }\n              });\n    \n              $scope.$on('$destroy', function () {\n                // Cancel any pending long-click timeout\n                $timeout.cancel(cancelMousedownTimeout);\n              });\n            }\n    \n            if ($scope.filterable) {\n              var filterDeregisters = [];\n              angular.forEach($scope.col.filters, function(filter, i) {\n                filterDeregisters.push($scope.$watch('col.filters[' + i + '].term', function(n, o) {\n                  if (n !== o) {\n                    uiGridCtrl.grid.api.core.raise.filterChanged();\n                    uiGridCtrl.grid.refresh()\n                      .then(function () {\n                        if (uiGridCtrl.prevScrollArgs && uiGridCtrl.prevScrollArgs.y && uiGridCtrl.prevScrollArgs.y.percentage) {\n                          var scrollEvent = new ScrollEvent(uiGridCtrl.grid,null,null,'uiGridHeaderCell.toggleMenu');\n                          scrollEvent.y.percentage = uiGridCtrl.prevScrollArgs.y.percentage;\n                          scrollEvent.fireScrollingEvent();\n                        }\n                      });\n                  }\n                }));  \n              });\n              $scope.$on('$destroy', function() {\n                angular.forEach(filterDeregisters, function(filterDeregister) {\n                  filterDeregister();\n                });\n              });\n            }\n          }\n        };\n      }\n    };\n\n    return uiGridHeaderCell;\n  }]);\n\n})();\n\n(function(){\n  'use strict';\n\n  angular.module('ui.grid').directive('uiGridHeader', ['$templateCache', '$compile', 'uiGridConstants', 'gridUtil', '$timeout', function($templateCache, $compile, uiGridConstants, gridUtil, $timeout) {\n    var defaultTemplate = 'ui-grid/ui-grid-header';\n    var emptyTemplate = 'ui-grid/ui-grid-no-header';\n\n    return {\n      restrict: 'EA',\n      // templateUrl: 'ui-grid/ui-grid-header',\n      replace: true,\n      // priority: 1000,\n      require: ['^uiGrid', '^uiGridRenderContainer'],\n      scope: true,\n      compile: function($elm, $attrs) {\n        return {\n          pre: function ($scope, $elm, $attrs, controllers) {\n            var uiGridCtrl = controllers[0];\n            var containerCtrl = controllers[1];\n\n            $scope.grid = uiGridCtrl.grid;\n            $scope.colContainer = containerCtrl.colContainer;\n\n\n\n            containerCtrl.header = $elm;\n            containerCtrl.colContainer.header = $elm;\n            \n            var headerTemplate;\n            if (!$scope.grid.options.showHeader) {\n              headerTemplate = emptyTemplate;\n            }\n            else {\n              headerTemplate = ($scope.grid.options.headerTemplate) ? $scope.grid.options.headerTemplate : defaultTemplate;            \n            }\n\n             gridUtil.getTemplate(headerTemplate)\n              .then(function (contents) {\n                var template = angular.element(contents);\n                \n                var newElm = $compile(template)($scope);\n                $elm.replaceWith(newElm);\n\n                // Replace the reference to the container's header element with this new element\n                containerCtrl.header = newElm;\n                containerCtrl.colContainer.header = newElm;\n\n                // And update $elm to be the new element\n                $elm = newElm;\n\n                if (containerCtrl) {\n                  // Inject a reference to the header viewport (if it exists) into the grid controller for use in the horizontal scroll handler below\n                  var headerViewport = $elm[0].getElementsByClassName('ui-grid-header-viewport')[0];\n\n                  if (headerViewport) {\n                    containerCtrl.headerViewport = headerViewport;\n                  }\n                }\n              });\n          },\n\n          post: function ($scope, $elm, $attrs, controllers) {\n            var uiGridCtrl = controllers[0];\n            var containerCtrl = controllers[1];\n\n            // gridUtil.logDebug('ui-grid-header link');\n\n            var grid = uiGridCtrl.grid;\n\n            // Don't animate header cells\n            gridUtil.disableAnimations($elm);\n\n            function updateColumnWidths() {\n              // Get the width of the viewport\n              var availableWidth = containerCtrl.colContainer.getViewportWidth();\n\n              //if (typeof(uiGridCtrl.grid.verticalScrollbarWidth) !== 'undefined' && uiGridCtrl.grid.verticalScrollbarWidth !== undefined && uiGridCtrl.grid.verticalScrollbarWidth > 0) {\n              //  availableWidth = availableWidth + uiGridCtrl.grid.verticalScrollbarWidth;\n              //}\n\n              // The total number of columns\n              // var equalWidthColumnCount = columnCount = uiGridCtrl.grid.options.columnDefs.length;\n              // var equalWidth = availableWidth / equalWidthColumnCount;\n\n              var columnCache = containerCtrl.colContainer.visibleColumnCache,\n                  canvasWidth = 0,\n                  asteriskNum = 0,\n                  oneAsterisk = 0,\n                  leftoverWidth = availableWidth,\n                  hasVariableWidth = false;\n              \n              var getColWidth = function(column){\n                if (column.widthType === \"manual\"){ \n                  return +column.width; \n                }\n                else if (column.widthType === \"percent\"){ \n                  return parseInt(column.width.replace(/%/g, ''), 10) * availableWidth / 100;\n                }\n                else if (column.widthType === \"auto\"){\n                  // leftOverWidth is subtracted from after each call to this\n                  // function so we need to calculate oneAsterisk size only once\n                  if (oneAsterisk === 0) {\n                    oneAsterisk = parseInt(leftoverWidth / asteriskNum, 10);\n                  }\n                  return column.width.length * oneAsterisk; \n                }\n              };\n              \n              // Populate / determine column width types:\n              columnCache.forEach(function(column){\n                column.widthType = null;\n                if (isFinite(+column.width)){\n                  column.widthType = \"manual\";\n                }\n                else if (gridUtil.endsWith(column.width, \"%\")){\n                  column.widthType = \"percent\";\n                  hasVariableWidth = true;\n                }\n                else if (angular.isString(column.width) && column.width.indexOf('*') !== -1){\n                  column.widthType = \"auto\";\n                  asteriskNum += column.width.length;\n                  hasVariableWidth = true;\n                }\n              });\n              \n              // For sorting, calculate width from first to last:\n              var colWidthPriority = [\"manual\", \"percent\", \"auto\"];\n              columnCache.filter(function(column){\n                // Only draw visible items with a widthType\n                return (column.visible && column.widthType); \n              }).sort(function(a,b){\n                // Calculate widths in order, so that manual comes first, etc.\n                return colWidthPriority.indexOf(a.widthType) - colWidthPriority.indexOf(b.widthType);\n              }).forEach(function(column){\n                // Calculate widths:\n                var colWidth = getColWidth(column);\n                if (column.minWidth){\n                  colWidth = Math.max(colWidth, column.minWidth);\n                }\n                if (column.maxWidth){\n                  colWidth = Math.min(colWidth, column.maxWidth);\n                }\n                column.drawnWidth = Math.floor(colWidth);\n                canvasWidth += column.drawnWidth;\n                leftoverWidth -= column.drawnWidth;\n              });\n\n              // If the grid width didn't divide evenly into the column widths and we have pixels left over, dole them out to the columns one by one to make everything fit\n              if (hasVariableWidth && leftoverWidth > 0 && canvasWidth > 0 && canvasWidth < availableWidth) {\n                var remFn = function (column) {\n                  if (leftoverWidth > 0 && (column.widthType === \"auto\" || column.widthType === \"percent\")) {\n                    column.drawnWidth = column.drawnWidth + 1;\n                    canvasWidth = canvasWidth + 1;\n                    leftoverWidth--;\n                  }\n                };\n                var prevLeftover = 0;\n                do {\n                  prevLeftover = leftoverWidth;\n                  columnCache.forEach(remFn);\n                } while (leftoverWidth > 0 && leftoverWidth !== prevLeftover );\n              }\n              canvasWidth = Math.max(canvasWidth, availableWidth);\n\n              // Build the CSS\n              // uiGridCtrl.grid.columns.forEach(function (column) {\n              var ret = '';\n              columnCache.forEach(function (column) {\n                ret = ret + column.getColClassDefinition();\n              });\n\n              // Add the vertical scrollbar width back in to the canvas width, it's taken out in getViewportWidth\n              //if (grid.verticalScrollbarWidth) {\n              //  canvasWidth = canvasWidth + grid.verticalScrollbarWidth;\n              //}\n              // canvasWidth = canvasWidth + 1;\n\n              // if we have a grid menu, then we prune the width of the last column header\n              // to allow room for the button whilst still getting to the column menu\n              if (columnCache.length > 0) { // && grid.options.enableGridMenu) {\n                columnCache[columnCache.length - 1].headerWidth = columnCache[columnCache.length - 1].drawnWidth - 30;\n              }\n\n              containerCtrl.colContainer.canvasWidth = parseInt(canvasWidth, 10);\n\n              // Return the styles back to buildStyles which pops them into the `customStyles` scope variable\n              return ret;\n            }\n            \n            containerCtrl.header = $elm;\n            \n            var headerViewport = $elm[0].getElementsByClassName('ui-grid-header-viewport')[0];\n            if (headerViewport) {\n              containerCtrl.headerViewport = headerViewport;\n            }\n\n            //todo: remove this if by injecting gridCtrl into unit tests\n            if (uiGridCtrl) {\n              uiGridCtrl.grid.registerStyleComputation({\n                priority: 5,\n                func: updateColumnWidths\n              });\n            }\n          }\n        };\n      }\n    };\n  }]);\n\n})();\n\n(function(){\n\nangular.module('ui.grid')\n.service('uiGridGridMenuService', [ 'gridUtil', 'i18nService', 'uiGridConstants', function( gridUtil, i18nService, uiGridConstants ) {\n  /**\n   *  @ngdoc service\n   *  @name ui.grid.gridMenuService\n   *\n   *  @description Methods for working with the grid menu\n   */\n\n  var service = {\n    /**\n     * @ngdoc method\n     * @methodOf ui.grid.gridMenuService\n     * @name initialize\n     * @description Sets up the gridMenu. Most importantly, sets our\n     * scope onto the grid object as grid.gridMenuScope, allowing us\n     * to operate when passed only the grid.  Second most importantly, \n     * we register the 'addToGridMenu' and 'removeFromGridMenu' methods\n     * on the core api.\n     * @param {$scope} $scope the scope of this gridMenu\n     * @param {Grid} grid the grid to which this gridMenu is associated\n     */\n    initialize: function( $scope, grid ){\n      grid.gridMenuScope = $scope;\n      $scope.grid = grid;\n      $scope.registeredMenuItems = [];\n      \n      // not certain this is needed, but would be bad to create a memory leak\n      $scope.$on('$destroy', function() {\n        if ( $scope.grid && $scope.grid.gridMenuScope ){\n          $scope.grid.gridMenuScope = null;\n        }\n        if ( $scope.grid ){\n          $scope.grid = null;\n        }\n        if ( $scope.registeredMenuItems ){\n          $scope.registeredMenuItems = null;\n        }\n      });\n      \n      $scope.registeredMenuItems = [];\n\n      /**\n       * @ngdoc function\n       * @name addToGridMenu\n       * @methodOf ui.grid.core.api:PublicApi\n       * @description add items to the grid menu.  Used by features\n       * to add their menu items if they are enabled, can also be used by\n       * end users to add menu items.  This method has the advantage of allowing\n       * remove again, which can simplify management of which items are included\n       * in the menu when.  (Noting that in most cases the shown and active functions\n       * provide a better way to handle visibility of menu items)\n       * @param {Grid} grid the grid on which we are acting\n       * @param {array} items menu items in the format as described in the tutorial, with \n       * the added note that if you want to use remove you must also specify an `id` field,\n       * which is provided when you want to remove an item.  The id should be unique.\n       * \n       */\n      grid.api.registerMethod( 'core', 'addToGridMenu', service.addToGridMenu );\n  \n      /**\n       * @ngdoc function\n       * @name removeFromGridMenu\n       * @methodOf ui.grid.core.api:PublicApi\n       * @description Remove an item from the grid menu based on a provided id. Assumes\n       * that the id is unique, removes only the last instance of that id. Does nothing if\n       * the specified id is not found\n       * @param {Grid} grid the grid on which we are acting\n       * @param {string} id the id we'd like to remove from the menu\n       * \n       */\n      grid.api.registerMethod( 'core', 'removeFromGridMenu', service.removeFromGridMenu );\n    },\n \n    \n    /**\n     * @ngdoc function\n     * @name addToGridMenu\n     * @propertyOf ui.grid.class:GridOptions\n     * @description add items to the grid menu.  Used by features\n     * to add their menu items if they are enabled, can also be used by\n     * end users to add menu items.  This method has the advantage of allowing\n     * remove again, which can simplify management of which items are included\n     * in the menu when.  (Noting that in most cases the shown and active functions\n     * provide a better way to handle visibility of menu items)\n     * @param {Grid} grid the grid on which we are acting\n     * @param {array} items menu items in the format as described in the tutorial, with \n     * the added note that if you want to use remove you must also specify an `id` field,\n     * which is provided when you want to remove an item.  The id should be unique.\n     * \n     */\n    addToGridMenu: function( grid, menuItems ) {\n      if ( !angular.isArray( menuItems ) ) {\n        gridUtil.logError( 'addToGridMenu: menuItems must be an array, and is not, not adding any items');\n      } else {\n        if ( grid.gridMenuScope ){\n          grid.gridMenuScope.registeredMenuItems = grid.gridMenuScope.registeredMenuItems ? grid.gridMenuScope.registeredMenuItems : [];\n          grid.gridMenuScope.registeredMenuItems = grid.gridMenuScope.registeredMenuItems.concat( menuItems );\n        } else {\n          gridUtil.logError( 'Asked to addToGridMenu, but gridMenuScope not present.  Timing issue?  Please log issue with ui-grid');\n        }\n      }  \n    },\n    \n\n    /**\n     * @ngdoc function\n     * @name removeFromGridMenu\n     * @methodOf ui.grid.core.api:PublicApi\n     * @description Remove an item from the grid menu based on a provided id.  Assumes\n     * that the id is unique, removes only the last instance of that id.  Does nothing if\n     * the specified id is not found.  If there is no gridMenuScope or registeredMenuItems\n     * then do nothing silently - the desired result is those menu items not be present and they\n     * aren't.\n     * @param {Grid} grid the grid on which we are acting\n     * @param {string} id the id we'd like to remove from the menu\n     * \n     */    \n    removeFromGridMenu: function( grid, id ){\n      var foundIndex = -1;\n      \n      if ( grid && grid.gridMenuScope ){\n        grid.gridMenuScope.registeredMenuItems.forEach( function( value, index ) {\n          if ( value.id === id ){\n            if (foundIndex > -1) {\n              gridUtil.logError( 'removeFromGridMenu: found multiple items with the same id, removing only the last' );\n            } else {\n              \n              foundIndex = index;\n            }\n          }\n        });\n      }\n\n      if ( foundIndex > -1 ){\n        grid.gridMenuScope.registeredMenuItems.splice( foundIndex, 1 );\n      }\n    },\n    \n        \n    /**\n     * @ngdoc array\n     * @name gridMenuCustomItems\n     * @propertyOf ui.grid.class:GridOptions\n     * @description (optional) An array of menu items that should be added to\n     * the gridMenu.  Follow the format documented in the tutorial for column\n     * menu customisation.  The context provided to the action function will \n     * include context.grid.  An alternative if working with dynamic menus is to use the \n     * provided api - core.addToGridMenu and core.removeFromGridMenu, which handles\n     * some of the management of items for you.\n     * \n     */\n    /**\n     * @ngdoc boolean\n     * @name gridMenuShowHideColumns\n     * @propertyOf ui.grid.class:GridOptions\n     * @description true by default, whether the grid menu should allow hide/show\n     * of columns\n     * \n     */\n    /**\n     * @ngdoc method\n     * @methodOf ui.grid.gridMenuService\n     * @name getMenuItems\n     * @description Decides the menu items to show in the menu.  This is a\n     * combination of:\n     * \n     * - the default menu items that are always included, \n     * - any menu items that have been provided through the addMenuItem api. These\n     *   are typically added by features within the grid\n     * - any menu items included in grid.options.gridMenuCustomItems.  These can be\n     *   changed dynamically, as they're always recalculated whenever we show the\n     *   menu\n     * @param {$scope} $scope the scope of this gridMenu, from which we can find all \n     * the information that we need\n     * @returns {array} an array of menu items that can be shown \n     */\n    getMenuItems: function( $scope ) {\n      var menuItems = [\n        // this is where we add any menu items we want to always include\n      ];\n      \n      if ( $scope.grid.options.gridMenuCustomItems ){\n        if ( !angular.isArray( $scope.grid.options.gridMenuCustomItems ) ){ \n          gridUtil.logError( 'gridOptions.gridMenuCustomItems must be an array, and is not'); \n        } else {\n          menuItems = menuItems.concat( $scope.grid.options.gridMenuCustomItems );\n        }\n      }\n  \n      menuItems = menuItems.concat( $scope.registeredMenuItems );\n      \n      if ( $scope.grid.options.gridMenuShowHideColumns !== false ){\n        menuItems = menuItems.concat( service.showHideColumns( $scope ) );\n      }\n      \n      return menuItems;\n    },\n    \n    \n    /**\n     * @ngdoc array\n     * @name gridMenuTitleFilter\n     * @propertyOf ui.grid.class:GridOptions\n     * @description (optional) A function that takes a title string \n     * (usually the col.displayName), and converts it into a display value.  The function\n     * must return either a string or a promise.\n     * \n     * Used for internationalization of the grid menu column names - for angular-translate\n     * you can pass $translate as the function, for i18nService you can pass getSafeText as the \n     * function\n     * @example\n     * <pre>\n     *   gridOptions = {\n     *     gridMenuTitleFilter: $translate\n     *   }\n     * </pre>\n     */\n    /**\n     * @ngdoc method\n     * @methodOf ui.grid.gridMenuService\n     * @name showHideColumns\n     * @description Adds two menu items for each of the columns in columnDefs.  One\n     * menu item for hide, one menu item for show.  Each is visible when appropriate\n     * (show when column is not visible, hide when column is visible).  Each toggles\n     * the visible property on the columnDef using toggleColumnVisibility\n     * @param {$scope} $scope of a gridMenu, which contains a reference to the grid\n     */\n    showHideColumns: function( $scope ){\n      var showHideColumns = [];\n      if ( !$scope.grid.options.columnDefs || $scope.grid.options.columnDefs.length === 0 || $scope.grid.columns.length === 0 ) {\n        return showHideColumns;\n      }\n      \n      // add header for columns\n      showHideColumns.push({\n        title: i18nService.getSafeText('gridMenu.columns')\n      });\n      \n      $scope.grid.options.gridMenuTitleFilter = $scope.grid.options.gridMenuTitleFilter ? $scope.grid.options.gridMenuTitleFilter : function( title ) { return title; };  \n      \n      $scope.grid.options.columnDefs.forEach( function( colDef, index ){\n        if ( colDef.enableHiding !== false ){\n          // add hide menu item - shows an OK icon as we only show when column is already visible\n          var menuItem = {\n            icon: 'ui-grid-icon-ok',\n            action: function($event) {\n              $event.stopPropagation();\n              service.toggleColumnVisibility( this.context.gridCol );\n            },\n            shown: function() {\n              return this.context.gridCol.colDef.visible === true || this.context.gridCol.colDef.visible === undefined;\n            },\n            context: { gridCol: $scope.grid.getColumn(colDef.name || colDef.field) }\n          };\n          service.setMenuItemTitle( menuItem, colDef, $scope.grid );\n          showHideColumns.push( menuItem );\n\n          // add show menu item - shows no icon as we only show when column is invisible\n          menuItem = {\n            icon: 'ui-grid-icon-cancel',\n            action: function($event) {\n              $event.stopPropagation();\n              service.toggleColumnVisibility( this.context.gridCol );\n            },\n            shown: function() {\n              return !(this.context.gridCol.colDef.visible === true || this.context.gridCol.colDef.visible === undefined);\n            },\n            context: { gridCol: $scope.grid.getColumn(colDef.name || colDef.field) }\n          };\n          service.setMenuItemTitle( menuItem, colDef, $scope.grid );\n          showHideColumns.push( menuItem );\n        }\n      });\n      return showHideColumns;\n    },\n    \n    \n    /**\n     * @ngdoc method\n     * @methodOf ui.grid.gridMenuService\n     * @name setMenuItemTitle\n     * @description Handles the response from gridMenuTitleFilter, adding it directly to the menu\n     * item if it returns a string, otherwise waiting for the promise to resolve or reject then\n     * putting the result into the title \n     * @param {object} menuItem the menuItem we want to put the title on\n     * @param {object} colDef the colDef from which we can get displayName, name or field\n     * @param {Grid} grid the grid, from which we can get the options.gridMenuTitleFilter\n     * \n     */\n    setMenuItemTitle: function( menuItem, colDef, grid ){\n      var title = grid.options.gridMenuTitleFilter( colDef.displayName || colDef.name || colDef.field );\n      \n      if ( typeof(title) === 'string' ){\n        menuItem.title = title;\n      } else if ( title.then ){\n        // must be a promise\n        menuItem.title = \"\";\n        title.then( function( successValue ) {\n          menuItem.title = successValue;\n        }, function( errorValue ) {\n          menuItem.title = errorValue;\n        });\n      } else {\n        gridUtil.logError('Expected gridMenuTitleFilter to return a string or a promise, it has returned neither, bad config');\n        menuItem.title = 'badconfig';\n      }\n    },\n\n    /**\n     * @ngdoc method\n     * @methodOf ui.grid.gridMenuService\n     * @name toggleColumnVisibility\n     * @description Toggles the visibility of an individual column.  Expects to be\n     * provided a context that has on it a gridColumn, which is the column that\n     * we'll operate upon.  We change the visibility, and refresh the grid as appropriate\n     * @param {GridCol} gridCol the column that we want to toggle\n     * \n     */\n    toggleColumnVisibility: function( gridCol ) {\n      gridCol.colDef.visible = !( gridCol.colDef.visible === true || gridCol.colDef.visible === undefined ); \n      \n      gridCol.grid.refresh();\n      gridCol.grid.api.core.notifyDataChange( uiGridConstants.dataChange.COLUMN );\n      gridCol.grid.api.core.raise.columnVisibilityChanged( gridCol );\n    }\n  };\n  \n  return service;\n}])\n\n\n\n.directive('uiGridMenuButton', ['gridUtil', 'uiGridConstants', 'uiGridGridMenuService', \nfunction (gridUtil, uiGridConstants, uiGridGridMenuService) {\n\n  return {\n    priority: 0,\n    scope: true,\n    require: ['?^uiGrid'],\n    templateUrl: 'ui-grid/ui-grid-menu-button',\n    replace: true,\n\n\n    link: function ($scope, $elm, $attrs, controllers) {\n      var uiGridCtrl = controllers[0];\n\n      uiGridGridMenuService.initialize($scope, uiGridCtrl.grid);\n      \n      $scope.shown = false;\n\n      $scope.toggleMenu = function () {\n        if ( $scope.shown ){\n          $scope.$broadcast('hide-menu');\n          $scope.shown = false;\n        } else {\n          $scope.menuItems = uiGridGridMenuService.getMenuItems( $scope );\n          $scope.$broadcast('show-menu');\n          $scope.shown = true;\n        }\n      };\n      \n      $scope.$on('menu-hidden', function() {\n        $scope.shown = false;\n      });\n    }\n  };\n\n}]);\n\n})();\n(function(){\n\n/**\n * @ngdoc directive\n * @name ui.grid.directive:uiGridColumnMenu\n * @element style\n * @restrict A\n *\n * @description\n * Allows us to interpolate expressions in `<style>` elements. Angular doesn't do this by default as it can/will/might? break in IE8.\n *\n * @example\n <doc:example module=\"app\">\n <doc:source>\n <script>\n var app = angular.module('app', ['ui.grid']);\n\n app.controller('MainCtrl', ['$scope', function ($scope) {\n   \n }]);\n </script>\n\n <div ng-controller=\"MainCtrl\">\n   <div ui-grid-menu shown=\"true\"  ></div>\n </div>\n </doc:source>\n <doc:scenario>\n </doc:scenario>\n </doc:example>\n */\nangular.module('ui.grid')\n\n.directive('uiGridMenu', ['$compile', '$timeout', '$window', '$document', 'gridUtil', 'uiGridConstants', \nfunction ($compile, $timeout, $window, $document, gridUtil, uiGridConstants) {\n  var uiGridMenu = {\n    priority: 0,\n    scope: {\n      // shown: '&',\n      menuItems: '=',\n      autoHide: '=?'\n    },\n    require: '?^uiGrid',\n    templateUrl: 'ui-grid/uiGridMenu',\n    replace: false,\n    link: function ($scope, $elm, $attrs, uiGridCtrl) {\n      var self = this;\n      var menuMid;\n      var $animate;\n     \n    // *** Show/Hide functions ******\n      self.showMenu = $scope.showMenu = function(event, args) {\n        if ( !$scope.shown ){\n\n          /*\n           * In order to animate cleanly we remove the ng-if, wait a digest cycle, then\n           * animate the removal of the ng-hide.  We can't successfully (so far as I can tell)\n           * animate removal of the ng-if, as the menu items aren't there yet.  And we don't want\n           * to rely on ng-show only, as that leaves elements in the DOM that are needlessly evaluated\n           * on scroll events.\n           * \n           * Note when testing animation that animations don't run on the tutorials.  When debugging it looks\n           * like they do, but angular has a default $animate provider that is just a stub, and that's what's\n           * being called.  ALso don't be fooled by the fact that your browser has actually loaded the \n           * angular-translate.js, it's not using it.  You need to test animations in an external application. \n           */\n          $scope.shown = true;\n\n          $timeout( function() {\n            $scope.shownMid = true;\n            $scope.$emit('menu-shown');\n          });\n        } else if ( !$scope.shownMid ) {\n          // we're probably doing a hide then show, so we don't need to wait for ng-if\n          $scope.shownMid = true;\n          $scope.$emit('menu-shown');\n        }\n\n        var docEventType = 'click';\n        if (args && args.originalEvent && args.originalEvent.type && args.originalEvent.type === 'touchstart') {\n          docEventType = args.originalEvent.type;\n        }\n\n        // Turn off an existing document click handler\n        angular.element(document).off('click touchstart', applyHideMenu);\n\n        // Turn on the document click handler, but in a timeout so it doesn't apply to THIS click if there is one\n        $timeout(function() {\n          angular.element(document).on(docEventType, applyHideMenu);\n        });\n      };\n\n\n      self.hideMenu = $scope.hideMenu = function(event, args) {\n        if ( $scope.shown ){\n          /*\n           * In order to animate cleanly we animate the addition of ng-hide, then use a $timeout to\n           * set the ng-if (shown = false) after the animation runs.  In theory we can cascade off the\n           * callback on the addClass method, but it is very unreliable with unit tests for no discernable reason.\n           *   \n           * The user may have clicked on the menu again whilst\n           * we're waiting, so we check that the mid isn't shown before applying the ng-if.\n           */\n          $scope.shownMid = false;\n          $timeout( function() {\n            if ( !$scope.shownMid ){\n              $scope.shown = false;\n              $scope.$emit('menu-hidden');\n            }\n          }, 200);\n        }\n\n        angular.element(document).off('click touchstart', applyHideMenu);\n      };\n\n      $scope.$on('hide-menu', function (event, args) {\n        $scope.hideMenu(event, args);\n      });\n\n      $scope.$on('show-menu', function (event, args) {\n        $scope.showMenu(event, args);\n      });\n\n      \n    // *** Auto hide when click elsewhere ******\n      var applyHideMenu = function(){\n        if ($scope.shown) {\n          $scope.$apply(function () {\n            $scope.hideMenu();\n          });\n        }\n      };\n    \n      if (typeof($scope.autoHide) === 'undefined' || $scope.autoHide === undefined) {\n        $scope.autoHide = true;\n      }\n\n      if ($scope.autoHide) {\n        angular.element($window).on('resize', applyHideMenu);\n      }\n\n      $scope.$on('$destroy', function () {\n        angular.element(document).off('click touchstart', applyHideMenu);\n      });\n      \n\n      $scope.$on('$destroy', function() {\n        angular.element($window).off('resize', applyHideMenu);\n      });\n\n      if (uiGridCtrl) {\n       $scope.$on('$destroy', uiGridCtrl.grid.api.core.on.scrollEvent($scope, applyHideMenu ));\n      }\n\n      $scope.$on('$destroy', $scope.$on(uiGridConstants.events.ITEM_DRAGGING, applyHideMenu ));\n    },\n    \n    \n    controller: ['$scope', '$element', '$attrs', function ($scope, $element, $attrs) {\n      var self = this;\n    }]\n  };\n\n  return uiGridMenu;\n}])\n\n.directive('uiGridMenuItem', ['gridUtil', '$compile', 'i18nService', function (gridUtil, $compile, i18nService) {\n  var uiGridMenuItem = {\n    priority: 0,\n    scope: {\n      name: '=',\n      active: '=',\n      action: '=',\n      icon: '=',\n      shown: '=',\n      context: '=',\n      templateUrl: '='\n    },\n    require: ['?^uiGrid', '^uiGridMenu'],\n    templateUrl: 'ui-grid/uiGridMenuItem',\n    replace: true,\n    compile: function($elm, $attrs) {\n      return {\n        pre: function ($scope, $elm, $attrs, controllers) {\n          var uiGridCtrl = controllers[0],\n              uiGridMenuCtrl = controllers[1];\n          \n          if ($scope.templateUrl) {\n            gridUtil.getTemplate($scope.templateUrl)\n                .then(function (contents) {\n                  var template = angular.element(contents);\n                    \n                  var newElm = $compile(template)($scope);\n                  $elm.replaceWith(newElm);\n                });\n          }\n        },\n        post: function ($scope, $elm, $attrs, controllers) {\n          var uiGridCtrl = controllers[0],\n              uiGridMenuCtrl = controllers[1];\n\n          // TODO(c0bra): validate that shown and active are functions if they're defined. An exception is already thrown above this though\n          // if (typeof($scope.shown) !== 'undefined' && $scope.shown && typeof($scope.shown) !== 'function') {\n          //   throw new TypeError(\"$scope.shown is defined but not a function\");\n          // }\n          if (typeof($scope.shown) === 'undefined' || $scope.shown === null) {\n            $scope.shown = function() { return true; };\n          }\n\n          $scope.itemShown = function () {\n            var context = {};\n            if ($scope.context) {\n              context.context = $scope.context;\n            }\n\n            if (typeof(uiGridCtrl) !== 'undefined' && uiGridCtrl) {\n              context.grid = uiGridCtrl.grid;\n            }\n\n            return $scope.shown.call(context);\n          };\n\n          $scope.itemAction = function($event,title) {\n            // gridUtil.logDebug('itemAction');\n            $event.stopPropagation();\n\n            if (typeof($scope.action) === 'function') {\n              var context = {};\n\n              if ($scope.context) {\n                context.context = $scope.context;\n              }\n\n              // Add the grid to the function call context if the uiGrid controller is present\n              if (typeof(uiGridCtrl) !== 'undefined' && uiGridCtrl) {\n                context.grid = uiGridCtrl.grid;\n              }\n\n              $scope.action.call(context, $event, title);\n\n              $scope.$emit('hide-menu');\n            }\n          };\n\n          $scope.i18n = i18nService.get();\n        }\n      };\n    }\n  };\n\n  return uiGridMenuItem;\n}]);\n\n})();\n(function () {\n  'use strict';\n\n  var module = angular.module('ui.grid');\n  \n  module.directive('uiGridRenderContainer', ['$timeout', '$document', 'uiGridConstants', 'gridUtil', 'ScrollEvent',\n    function($timeout, $document, uiGridConstants, gridUtil, ScrollEvent) {\n    return {\n      replace: true,\n      transclude: true,\n      templateUrl: 'ui-grid/uiGridRenderContainer',\n      require: ['^uiGrid', 'uiGridRenderContainer'],\n      scope: {\n        containerId: '=',\n        rowContainerName: '=',\n        colContainerName: '=',\n        bindScrollHorizontal: '=',\n        bindScrollVertical: '=',\n        enableVerticalScrollbar: '=',\n        enableHorizontalScrollbar: '='\n      },\n      controller: 'uiGridRenderContainer as RenderContainer',\n      compile: function () {\n        return {\n          pre: function prelink($scope, $elm, $attrs, controllers) {\n            // gridUtil.logDebug('render container ' + $scope.containerId + ' pre-link');\n\n            var uiGridCtrl = controllers[0];\n            var containerCtrl = controllers[1];\n\n            var grid = $scope.grid = uiGridCtrl.grid;\n\n            // Verify that the render container for this element exists\n            if (!$scope.rowContainerName) {\n              throw \"No row render container name specified\";\n            }\n            if (!$scope.colContainerName) {\n              throw \"No column render container name specified\";\n            }\n\n            if (!grid.renderContainers[$scope.rowContainerName]) {\n              throw \"Row render container '\" + $scope.rowContainerName + \"' is not registered.\";\n            }\n            if (!grid.renderContainers[$scope.colContainerName]) {\n              throw \"Column render container '\" + $scope.colContainerName + \"' is not registered.\";\n            }\n\n            var rowContainer = $scope.rowContainer = grid.renderContainers[$scope.rowContainerName];\n            var colContainer = $scope.colContainer = grid.renderContainers[$scope.colContainerName];\n            \n            containerCtrl.containerId = $scope.containerId;\n            containerCtrl.rowContainer = rowContainer;\n            containerCtrl.colContainer = colContainer;\n          },\n          post: function postlink($scope, $elm, $attrs, controllers) {\n            // gridUtil.logDebug('render container ' + $scope.containerId + ' post-link');\n\n            var uiGridCtrl = controllers[0];\n            var containerCtrl = controllers[1];\n\n            var grid = uiGridCtrl.grid;\n            var rowContainer = containerCtrl.rowContainer;\n            var colContainer = containerCtrl.colContainer;\n\n            var renderContainer = grid.renderContainers[$scope.containerId];\n\n            // Put the container name on this element as a class\n            $elm.addClass('ui-grid-render-container-' + $scope.containerId);\n\n            // Bind to left/right-scroll events\n            if ($scope.bindScrollHorizontal || $scope.bindScrollVertical) {\n              grid.api.core.on.scrollEvent($scope,scrollHandler);\n            }\n\n            function scrollHandler (args) {\n              // exit if not for this grid\n              if (args.grid && args.grid.id !== grid.id){\n                return;\n              }\n\n              \n              // Vertical scroll\n              if (args.y && $scope.bindScrollVertical) {\n                containerCtrl.prevScrollArgs = args;\n\n                var newScrollTop = args.getNewScrollTop(rowContainer,containerCtrl.viewport);\n\n                //only set scrollTop if we coming from something other than viewPort scrollBar or\n                //another column container\n                if (args.source !== ScrollEvent.Sources.ViewPortScroll ||\n                    args.sourceColContainer !== colContainer) {\n                  containerCtrl.viewport[0].scrollTop = newScrollTop;\n                }\n\n              }\n\n              // Horizontal scroll\n              if (args.x && $scope.bindScrollHorizontal) {\n                containerCtrl.prevScrollArgs = args;\n                var newScrollLeft = args.getNewScrollLeft(colContainer,containerCtrl.viewport);\n\n                // Make the current horizontal scroll position available in the $scope\n                $scope.newScrollLeft = newScrollLeft;                \n\n                if (containerCtrl.headerViewport) {\n                  containerCtrl.headerViewport.scrollLeft = gridUtil.denormalizeScrollLeft(containerCtrl.headerViewport, newScrollLeft);\n                }\n\n                if (containerCtrl.footerViewport) {\n                  containerCtrl.footerViewport.scrollLeft = gridUtil.denormalizeScrollLeft(containerCtrl.footerViewport, newScrollLeft);\n                }\n\n                //scroll came from somewhere else, so the viewport must be positioned\n                if (args.source !== ScrollEvent.Sources.ViewPortScroll) {\n                  containerCtrl.viewport[0].scrollLeft = newScrollLeft;\n                }\n\n                containerCtrl.prevScrollLeft = newScrollLeft;\n              }\n            }\n\n            // Scroll the render container viewport when the mousewheel is used\n            $elm.bind('wheel mousewheel DomMouseScroll MozMousePixelScroll', function(evt) {\n              // use wheelDeltaY\n\n              var newEvent = gridUtil.normalizeWheelEvent(evt);\n\n              var scrollEvent = new ScrollEvent(grid, rowContainer, colContainer, ScrollEvent.Sources.RenderContainerMouseWheel);\n              if (newEvent.deltaY !== 0) {\n                var scrollYAmount = newEvent.deltaY * -120;\n\n                // Get the scroll percentage\n                var scrollYPercentage = (containerCtrl.viewport[0].scrollTop + scrollYAmount) / rowContainer.getVerticalScrollLength();\n\n                // Keep scrollPercentage within the range 0-1.\n                if (scrollYPercentage < 0) { scrollYPercentage = 0; }\n                else if (scrollYPercentage > 1) { scrollYPercentage = 1; }\n\n                scrollEvent.y = { percentage: scrollYPercentage, pixels: scrollYAmount };\n              }\n              if (newEvent.deltaX !== 0) {\n                var scrollXAmount = newEvent.deltaX * -120;\n\n                // Get the scroll percentage\n                var scrollLeft = gridUtil.normalizeScrollLeft(containerCtrl.viewport);\n                var scrollXPercentage = (scrollLeft + scrollXAmount) / (colContainer.getCanvasWidth() - colContainer.getViewportWidth());\n\n                // Keep scrollPercentage within the range 0-1.\n                if (scrollXPercentage < 0) { scrollXPercentage = 0; }\n                else if (scrollXPercentage > 1) { scrollXPercentage = 1; }\n\n                scrollEvent.x = { percentage: scrollXPercentage, pixels: scrollXAmount };\n              }\n\n              // todo: this isn't working when scrolling down.  it works fine for up.  tested on Chrome\n              // Let the parent container scroll if the grid is already at the top/bottom\n                if ((scrollEvent.y && scrollEvent.y.percentage !== 0 && scrollEvent.y.percentage !== 1 && containerCtrl.viewport[0].scrollTop !== 0 ) ||\n                    (scrollEvent.x && scrollEvent.x.percentage !== 0 && scrollEvent.x.percentage !== 1)) {\n                  evt.preventDefault();\n              }\n\n              scrollEvent.fireThrottledScrollingEvent();\n            });\n\n            var startY = 0,\n            startX = 0,\n            scrollTopStart = 0,\n            scrollLeftStart = 0,\n            directionY = 1,\n            directionX = 1,\n            moveStart;\n\n            function touchmove(event) {\n              if (event.originalEvent) {\n                event = event.originalEvent;\n              }\n\n              var deltaX, deltaY, newX, newY;\n              newX = event.targetTouches[0].screenX;\n              newY = event.targetTouches[0].screenY;\n              deltaX = -(newX - startX);\n              deltaY = -(newY - startY);\n\n              directionY = (deltaY < 1) ? -1 : 1;\n              directionX = (deltaX < 1) ? -1 : 1;\n\n              deltaY *= 2;\n              deltaX *= 2;\n\n              var scrollEvent = new ScrollEvent(grid, rowContainer, colContainer, ScrollEvent.Sources.RenderContainerTouchMove);\n\n              if (deltaY !== 0) {\n                var scrollYPercentage = (scrollTopStart + deltaY) / rowContainer.getVerticalScrollLength();\n\n                if (scrollYPercentage > 1) { scrollYPercentage = 1; }\n                else if (scrollYPercentage < 0) { scrollYPercentage = 0; }\n\n                scrollEvent.y = { percentage: scrollYPercentage, pixels: deltaY };\n              }\n              if (deltaX !== 0) {\n                var scrollXPercentage = (scrollLeftStart + deltaX) / (colContainer.getCanvasWidth() - colContainer.getViewportWidth());\n\n                if (scrollXPercentage > 1) { scrollXPercentage = 1; }\n                else if (scrollXPercentage < 0) { scrollXPercentage = 0; }\n\n                scrollEvent.x = { percentage: scrollXPercentage, pixels: deltaX };\n              }\n\n              // Let the parent container scroll if the grid is already at the top/bottom\n              if ((scrollEvent.y && scrollEvent.y.percentage !== 0 && scrollEvent.y.percentage !== 1) ||\n                  (scrollEvent.x && scrollEvent.x.percentage !== 0 && scrollEvent.x.percentage !== 1)) {\n                event.preventDefault();\n              }\n              scrollEvent.fireScrollingEvent();\n            }\n            \n            function touchend(event) {\n              if (event.originalEvent) {\n                event = event.originalEvent;\n              }\n\n              $document.unbind('touchmove', touchmove);\n              $document.unbind('touchend', touchend);\n              $document.unbind('touchcancel', touchend);\n\n              // Get the distance we moved on the Y axis\n              var scrollTopEnd = containerCtrl.viewport[0].scrollTop;\n              var scrollLeftEnd = containerCtrl.viewport[0].scrollTop;\n              var deltaY = Math.abs(scrollTopEnd - scrollTopStart);\n              var deltaX = Math.abs(scrollLeftEnd - scrollLeftStart);\n\n              // Get the duration it took to move this far\n              var moveDuration = (new Date()) - moveStart;\n\n              // Scale the amount moved by the time it took to move it (i.e. quicker, longer moves == more scrolling after the move is over)\n              var moveYScale = deltaY / moveDuration;\n              var moveXScale = deltaX / moveDuration;\n\n              var decelerateInterval = 63; // 1/16th second\n              var decelerateCount = 8; // == 1/2 second\n              var scrollYLength = 120 * directionY * moveYScale;\n              var scrollXLength = 120 * directionX * moveXScale;\n\n              //function decelerate() {\n              //  $timeout(function() {\n              //    var args = new ScrollEvent(grid, rowContainer, colContainer, ScrollEvent.Sources.RenderContainerTouchMove);\n              //\n              //    if (scrollYLength !== 0) {\n              //      var scrollYPercentage = (containerCtrl.viewport[0].scrollTop + scrollYLength) / rowContainer.getVerticalScrollLength();\n              //\n              //      args.y = { percentage: scrollYPercentage, pixels: scrollYLength };\n              //    }\n              //\n              //    if (scrollXLength !== 0) {\n              //      var scrollXPercentage = (containerCtrl.viewport[0].scrollLeft + scrollXLength) / (colContainer.getCanvasWidth() - colContainer.getViewportWidth());\n              //      args.x = { percentage: scrollXPercentage, pixels: scrollXLength };\n              //    }\n              //\n              //    uiGridCtrl.fireScrollingEvent(args);\n              //\n              //    decelerateCount = decelerateCount -1;\n              //    scrollYLength = scrollYLength / 2;\n              //    scrollXLength = scrollXLength / 2;\n              //\n              //    if (decelerateCount > 0) {\n              //      decelerate();\n              //    }\n              //    else {\n              //      uiGridCtrl.scrollbars.forEach(function (sbar) {\n              //        sbar.removeClass('ui-grid-scrollbar-visible');\n              //        sbar.removeClass('ui-grid-scrolling');\n              //      });\n              //    }\n              //  }, decelerateInterval);\n              //}\n\n              // decelerate();\n            }\n\n            if (gridUtil.isTouchEnabled()) {\n              $elm.bind('touchstart', function (event) {\n                if (event.originalEvent) {\n                  event = event.originalEvent;\n                }\n\n                //uiGridCtrl.scrollbars.forEach(function (sbar) {\n                //  sbar.addClass('ui-grid-scrollbar-visible');\n                //  sbar.addClass('ui-grid-scrolling');\n                //});\n\n                moveStart = new Date();\n                startY = event.targetTouches[0].screenY;\n                startX = event.targetTouches[0].screenX;\n                scrollTopStart = containerCtrl.viewport[0].scrollTop;\n                scrollLeftStart = containerCtrl.viewport[0].scrollLeft;\n                \n                $document.on('touchmove', touchmove);\n                $document.on('touchend touchcancel', touchend);\n              });\n            }\n\n            $elm.bind('$destroy', function() {\n              $elm.unbind('keydown');\n\n              ['touchstart', 'touchmove', 'touchend','keydown', 'wheel', 'mousewheel', 'DomMouseScroll', 'MozMousePixelScroll'].forEach(function (eventName) {\n                $elm.unbind(eventName);\n              });\n            });\n            \n            // TODO(c0bra): Handle resizing the inner canvas based on the number of elements\n            function update() {\n              var ret = '';\n\n              var canvasWidth = colContainer.getCanvasWidth();\n              var viewportWidth = colContainer.getViewportWidth();\n\n              var canvasHeight = rowContainer.getCanvasHeight();\n\n              //add additional height for scrollbar on left and right container\n              if ($scope.containerId !== 'body') {\n                canvasHeight += grid.scrollbarHeight;\n              }\n\n              var viewportHeight = rowContainer.getViewportHeight();\n\n              var headerViewportWidth = colContainer.getHeaderViewportWidth();\n              var footerViewportWidth = colContainer.getHeaderViewportWidth();\n              \n              // Set canvas dimensions\n              ret += '\\n .grid' + uiGridCtrl.grid.id + ' .ui-grid-render-container-' + $scope.containerId + ' .ui-grid-canvas { width: ' + canvasWidth + 'px; height: ' + canvasHeight + 'px; }';\n\n              ret += '\\n .grid' + uiGridCtrl.grid.id + ' .ui-grid-render-container-' + $scope.containerId + ' .ui-grid-header-canvas { width: ' + (canvasWidth + grid.scrollbarWidth) + 'px; }';\n              \n              ret += '\\n .grid' + uiGridCtrl.grid.id + ' .ui-grid-render-container-' + $scope.containerId + ' .ui-grid-viewport { width: ' + viewportWidth + 'px; height: ' + viewportHeight + 'px; }';\n              ret += '\\n .grid' + uiGridCtrl.grid.id + ' .ui-grid-render-container-' + $scope.containerId + ' .ui-grid-header-viewport { width: ' + headerViewportWidth + 'px; }';\n\n              ret += '\\n .grid' + uiGridCtrl.grid.id + ' .ui-grid-render-container-' + $scope.containerId + ' .ui-grid-footer-canvas { width: ' + canvasWidth + grid.scrollbarWidth + 'px; }';\n              ret += '\\n .grid' + uiGridCtrl.grid.id + ' .ui-grid-render-container-' + $scope.containerId + ' .ui-grid-footer-viewport { width: ' + footerViewportWidth + 'px; }';\n\n              // If the render container has an \"explicit\" header height (such as in the case that its header is smaller than the other headers and needs to be explicitly set to be the same, ue thae)\n              if (renderContainer.explicitHeaderHeight !== undefined && renderContainer.explicitHeaderHeight !== null && renderContainer.explicitHeaderHeight > 0) {\n                ret += '\\n .grid' + uiGridCtrl.grid.id + ' .ui-grid-render-container-' + $scope.containerId + ' .ui-grid-header-cell { height: ' + renderContainer.explicitHeaderHeight + 'px; }';\n              }\n              // Otherwise if the render container has an INNER header height, use that on the header cells (so that all the header cells are the same height and those that have less elements don't have undersized borders)\n              else if (renderContainer.innerHeaderHeight !== undefined && renderContainer.innerHeaderHeight !== null && renderContainer.innerHeaderHeight > 0) {\n                ret += '\\n .grid' + uiGridCtrl.grid.id + ' .ui-grid-render-container-' + $scope.containerId + ' .ui-grid-header-cell { height: ' + renderContainer.innerHeaderHeight + 'px; }';\n              }\n\n              return ret;\n            }\n            \n            uiGridCtrl.grid.registerStyleComputation({\n              priority: 6,\n              func: update\n            });\n          }\n        };\n      }\n    };\n\n  }]);\n\n  module.controller('uiGridRenderContainer', ['$scope', 'gridUtil', function ($scope, gridUtil) {\n    var self = this;\n\n    self.rowStyle = function (index) {\n      var renderContainer = $scope.grid.renderContainers[$scope.containerId];\n\n      var styles = {};\n      \n      if (!renderContainer.disableRowOffset) {\n        if (index === 0 && self.currentTopRow !== 0) {\n          // The row offset-top is just the height of the rows above the current top-most row, which are no longer rendered\n          var hiddenRowWidth = ($scope.rowContainer.currentTopRow) *\n            $scope.rowContainer.visibleRowCache[$scope.rowContainer.currentTopRow].height;\n\n          // return { 'margin-top': hiddenRowWidth + 'px' };\n          //gridUtil.logDebug('margin-top ' + hiddenRowWidth );\n          styles['margin-top'] = hiddenRowWidth + 'px';\n        }\n      }\n      \n      if (!renderContainer.disableColumnOffset && $scope.colContainer.currentFirstColumn !== 0) {\n        if ($scope.grid.isRTL()) {\n          styles['margin-right'] = $scope.colContainer.columnOffset + 'px';\n        }\n        else {\n          styles['margin-left'] = $scope.colContainer.columnOffset + 'px';\n        }\n      }\n\n      return styles;\n    };\n\n    self.columnStyle = function (index) {\n      var renderContainer = $scope.grid.renderContainers[$scope.containerId];\n\n      var self = this;\n\n      if (!renderContainer.disableColumnOffset) {\n        if (index === 0 && $scope.colContainer.currentFirstColumn !== 0) {\n          var offset = $scope.colContainer.columnOffset;\n\n          if ($scope.grid.isRTL()) {\n            return { 'margin-right': offset + 'px' };\n          }\n          else {\n            return { 'margin-left': offset + 'px' }; \n          }\n        }\n      }\n\n      return null;\n    };\n  }]);\n\n})();\n\n(function(){\n  'use strict';\n\n  angular.module('ui.grid').directive('uiGridRow', ['gridUtil', function(gridUtil) {\n    return {\n      replace: true,\n      // priority: 2001,\n      // templateUrl: 'ui-grid/ui-grid-row',\n      require: ['^uiGrid', '^uiGridRenderContainer'],\n      scope: {\n         row: '=uiGridRow',\n         //rowRenderIndex is added to scope to give the true visual index of the row to any directives that need it\n         rowRenderIndex: '='\n      },\n      compile: function() {\n        return {\n          pre: function($scope, $elm, $attrs, controllers) {\n            var uiGridCtrl = controllers[0];\n            var containerCtrl = controllers[1];\n\n            var grid = uiGridCtrl.grid;\n\n            $scope.grid = uiGridCtrl.grid;\n            $scope.colContainer = containerCtrl.colContainer;\n\n            // Function for attaching the template to this scope\n            var clonedElement, cloneScope;\n            function compileTemplate() {\n              $scope.row.getRowTemplateFn.then(function (compiledElementFn) {\n                // var compiledElementFn = $scope.row.compiledElementFn;\n\n                // Create a new scope for the contents of this row, so we can destroy it later if need be\n                var newScope = $scope.$new();\n\n                compiledElementFn(newScope, function (newElm, scope) {\n                  // If we already have a cloned element, we need to remove it and destroy its scope\n                  if (clonedElement) {\n                    clonedElement.remove();\n                    cloneScope.$destroy();\n                  }\n\n                  // Empty the row and append the new element\n                  $elm.empty().append(newElm);\n\n                  // Save the new cloned element and scope\n                  clonedElement = newElm;\n                  cloneScope = newScope;\n                });\n              });\n            }\n\n            // Initially attach the compiled template to this scope\n            compileTemplate();\n\n            // If the row's compiled element function changes, we need to replace this element's contents with the new compiled template\n            $scope.$watch('row.getRowTemplateFn', function (newFunc, oldFunc) {\n              if (newFunc !== oldFunc) {\n                compileTemplate();\n              }\n            });\n          },\n          post: function($scope, $elm, $attrs, controllers) {\n\n          }\n        };\n      }\n    };\n  }]);\n\n})();\n(function(){\n// 'use strict';\n\n  /**\n   * @ngdoc directive\n   * @name ui.grid.directive:uiGridStyle\n   * @element style\n   * @restrict A\n   *\n   * @description\n   * Allows us to interpolate expressions in `<style>` elements. Angular doesn't do this by default as it can/will/might? break in IE8.\n   *\n   * @example\n   <doc:example module=\"app\">\n   <doc:source>\n   <script>\n   var app = angular.module('app', ['ui.grid']);\n\n   app.controller('MainCtrl', ['$scope', function ($scope) {\n          $scope.myStyle = '.blah { border: 1px solid }';\n        }]);\n   </script>\n\n   <div ng-controller=\"MainCtrl\">\n   <style ui-grid-style>{{ myStyle }}</style>\n   <span class=\"blah\">I am in a box.</span>\n   </div>\n   </doc:source>\n   <doc:scenario>\n   it('should apply the right class to the element', function () {\n        element(by.css('.blah')).getCssValue('border')\n          .then(function(c) {\n            expect(c).toContain('1px solid');\n          });\n      });\n   </doc:scenario>\n   </doc:example>\n   */\n\n\n  angular.module('ui.grid').directive('uiGridStyle', ['gridUtil', '$interpolate', function(gridUtil, $interpolate) {\n    return {\n      // restrict: 'A',\n      // priority: 1000,\n      // require: '?^uiGrid',\n      link: function($scope, $elm, $attrs, uiGridCtrl) {\n        // gridUtil.logDebug('ui-grid-style link');\n        // if (uiGridCtrl === undefined) {\n        //    gridUtil.logWarn('[ui-grid-style link] uiGridCtrl is undefined!');\n        // }\n\n        var interpolateFn = $interpolate($elm.text(), true);\n\n        if (interpolateFn) {\n          $scope.$watch(interpolateFn, function(value) {\n            $elm.text(value);\n          });\n        }\n\n          // uiGridCtrl.recalcRowStyles = function() {\n          //   var offset = (scope.options.offsetTop || 0) - (scope.options.excessRows * scope.options.rowHeight);\n          //   var rowHeight = scope.options.rowHeight;\n\n          //   var ret = '';\n          //   var rowStyleCount = uiGridCtrl.minRowsToRender() + (scope.options.excessRows * 2);\n          //   for (var i = 1; i <= rowStyleCount; i++) {\n          //     ret = ret + ' .grid' + scope.gridId + ' .ui-grid-row:nth-child(' + i + ') { top: ' + offset + 'px; }';\n          //     offset = offset + rowHeight;\n          //   }\n\n          //   scope.rowStyles = ret;\n          // };\n\n          // uiGridCtrl.styleComputions.push(uiGridCtrl.recalcRowStyles);\n\n      }\n    };\n  }]);\n\n})();\n(function(){\n  'use strict';\n\n  angular.module('ui.grid').directive('uiGridViewport', ['gridUtil','ScrollEvent','uiGridConstants',\n    function(gridUtil, ScrollEvent, uiGridConstants) {\n      return {\n        replace: true,\n        scope: {},\n        templateUrl: 'ui-grid/uiGridViewport',\n        require: ['^uiGrid', '^uiGridRenderContainer'],\n        link: function($scope, $elm, $attrs, controllers) {\n          // gridUtil.logDebug('viewport post-link');\n\n          var uiGridCtrl = controllers[0];\n          var containerCtrl = controllers[1];\n\n          $scope.containerCtrl = containerCtrl;\n\n          var rowContainer = containerCtrl.rowContainer;\n          var colContainer = containerCtrl.colContainer;\n\n          var grid = uiGridCtrl.grid;\n\n          $scope.grid = uiGridCtrl.grid;\n\n          // Put the containers in scope so we can get rows and columns from them\n          $scope.rowContainer = containerCtrl.rowContainer;\n          $scope.colContainer = containerCtrl.colContainer;\n\n          // Register this viewport with its container \n          containerCtrl.viewport = $elm;\n\n          $elm.on('scroll', function (evt) {\n            var newScrollTop = $elm[0].scrollTop;\n            // var newScrollLeft = $elm[0].scrollLeft;\n            var newScrollLeft = gridUtil.normalizeScrollLeft($elm);\n            var horizScrollPercentage = -1;\n            var vertScrollPercentage = -1;\n\n            // Handle RTL here\n\n            if (newScrollLeft !== colContainer.prevScrollLeft) {\n              grid.flagScrollingHorizontally();\n              var xDiff = newScrollLeft - colContainer.prevScrollLeft;\n\n              if (xDiff > 0) { grid.scrollDirection = uiGridConstants.scrollDirection.RIGHT; }\n              if (xDiff < 0) { grid.scrollDirection = uiGridConstants.scrollDirection.LEFT; }\n\n              var horizScrollLength = (colContainer.getCanvasWidth() - colContainer.getViewportWidth());\n              if (horizScrollLength !== 0) {\n                horizScrollPercentage = newScrollLeft / horizScrollLength;\n              }\n              else {\n                horizScrollPercentage = 0;\n              }\n\n              colContainer.adjustScrollHorizontal(newScrollLeft, horizScrollPercentage);\n            }\n\n            if (newScrollTop !== rowContainer.prevScrollTop) {\n              grid.flagScrollingVertically();\n              var yDiff = newScrollTop - rowContainer.prevScrollTop;\n\n              if (yDiff > 0 ) { grid.scrollDirection = uiGridConstants.scrollDirection.DOWN; }\n              if (yDiff < 0 ) { grid.scrollDirection = uiGridConstants.scrollDirection.UP; }\n\n              var vertScrollLength = rowContainer.getVerticalScrollLength();\n\n              vertScrollPercentage = newScrollTop / vertScrollLength;\n\n              if (vertScrollPercentage > 1) { vertScrollPercentage = 1; }\n              if (vertScrollPercentage < 0) { vertScrollPercentage = 0; }\n              \n              rowContainer.adjustScrollVertical(newScrollTop, vertScrollPercentage);\n            }\n\n              var scrollEvent = new ScrollEvent(grid, rowContainer, colContainer, ScrollEvent.Sources.ViewPortScroll);\n              scrollEvent.newScrollLeft = newScrollLeft;\n              scrollEvent.newScrollTop = newScrollTop;\n              if ( horizScrollPercentage > -1 ){\n                scrollEvent.x = { percentage: horizScrollPercentage };\n              }\n\n              if ( vertScrollPercentage > -1 ){\n                scrollEvent.y = { percentage: vertScrollPercentage };\n              }\n              scrollEvent.fireScrollingEvent();\n          });\n        }\n      };\n    }\n  ]);\n\n})();\n(function() {\n\nangular.module('ui.grid')\n.directive('uiGridVisible', function uiGridVisibleAction() {\n  return function ($scope, $elm, $attr) {\n    $scope.$watch($attr.uiGridVisible, function (visible) {\n        // $elm.css('visibility', visible ? 'visible' : 'hidden');\n        $elm[visible ? 'removeClass' : 'addClass']('ui-grid-invisible');\n    });\n  };\n});\n\n})();\n(function () {\n  'use strict';\n\n  angular.module('ui.grid').controller('uiGridController', ['$scope', '$element', '$attrs', 'gridUtil', '$q', 'uiGridConstants',\n                    '$templateCache', 'gridClassFactory', '$timeout', '$parse', '$compile', 'ScrollEvent',\n    function ($scope, $elm, $attrs, gridUtil, $q, uiGridConstants,\n              $templateCache, gridClassFactory, $timeout, $parse, $compile, ScrollEvent) {\n      // gridUtil.logDebug('ui-grid controller');\n\n      var self = this;\n\n      self.grid = gridClassFactory.createGrid($scope.uiGrid);\n\n      //assign $scope.$parent if appScope not already assigned\n      self.grid.appScope = self.grid.appScope || $scope.$parent;\n\n      $elm.addClass('grid' + self.grid.id);\n      self.grid.rtl = gridUtil.getStyles($elm[0])['direction'] === 'rtl';\n\n\n      // angular.extend(self.grid.options, );\n\n      //all properties of grid are available on scope\n      $scope.grid = self.grid;\n\n      if ($attrs.uiGridColumns) {\n        $attrs.$observe('uiGridColumns', function(value) {\n          self.grid.options.columnDefs = value;\n          self.grid.buildColumns()\n            .then(function(){\n              self.grid.preCompileCellTemplates();\n\n              self.grid.refreshCanvas(true);\n            });\n        });\n      }\n\n\n      var dataWatchCollectionDereg;\n      if (angular.isString($scope.uiGrid.data)) {\n        dataWatchCollectionDereg = $scope.$parent.$watchCollection($scope.uiGrid.data, dataWatchFunction);\n      }\n      else {\n        dataWatchCollectionDereg = $scope.$parent.$watchCollection(function() { return $scope.uiGrid.data; }, dataWatchFunction);\n      }\n\n      var columnDefWatchCollectionDereg = $scope.$parent.$watchCollection(function() { return $scope.uiGrid.columnDefs; }, columnDefsWatchFunction);\n\n      function columnDefsWatchFunction(n, o) {\n        if (n && n !== o) {\n          self.grid.options.columnDefs = n;\n          self.grid.buildColumns({ orderByColumnDefs: true })\n            .then(function(){\n\n              self.grid.preCompileCellTemplates();\n\n              self.grid.callDataChangeCallbacks(uiGridConstants.dataChange.COLUMN);\n            });\n        }\n      }\n\n      function adjustInfiniteScrollPosition (scrollToRow) {\n\n        var scrollEvent = new ScrollEvent(self.grid, null, null, 'ui.grid.adjustInfiniteScrollPosition');\n        var totalRows = self.grid.renderContainers.body.visibleRowCache.length;\n        var percentage = ( scrollToRow + ( scrollToRow / ( totalRows - 1 ) ) ) / totalRows;\n\n        //for infinite scroll, never allow it to be at the zero position so the up button can be active\n        if ( percentage === 0 ) {\n          scrollEvent.y = {pixels: 1};\n        }\n        else {\n          scrollEvent.y = {percentage: percentage};\n        }\n        scrollEvent.fireScrollingEvent();\n\n      }\n\n      function dataWatchFunction(newData) {\n        // gridUtil.logDebug('dataWatch fired');\n        var promises = [];\n        \n        if (newData) {\n          if (\n            // If we have no columns (i.e. columns length is either 0 or equal to the number of row header columns, which don't count because they're created automatically)\n            self.grid.columns.length === (self.grid.rowHeaderColumns ? self.grid.rowHeaderColumns.length : 0) &&\n            // ... and we don't have a ui-grid-columns attribute, which would define columns for us\n            !$attrs.uiGridColumns &&\n            // ... and we have no pre-defined columns\n            self.grid.options.columnDefs.length === 0 &&\n            // ... but we DO have data\n            newData.length > 0\n          ) {\n            // ... then build the column definitions from the data that we have\n            self.grid.buildColumnDefsFromData(newData);\n          }\n\n          // If we either have some columns defined, or some data defined\n          if (self.grid.options.columnDefs.length > 0 || newData.length > 0) {\n            // Build the column set, then pre-compile the column cell templates\n            promises.push(self.grid.buildColumns()\n              .then(function() {\n                self.grid.preCompileCellTemplates();\n              }));\n          }\n\n          $q.all(promises).then(function() {\n            self.grid.modifyRows(newData)\n              .then(function () {\n                // if (self.viewport) {\n                  self.grid.redrawInPlace();\n                // }\n\n                $scope.$evalAsync(function() {\n                  self.grid.refreshCanvas(true);\n                  self.grid.callDataChangeCallbacks(uiGridConstants.dataChange.ROW);\n\n                  $timeout(function () {\n                    //Process post load scroll events if using infinite scroll\n                    if ( self.grid.options.enableInfiniteScroll ) {\n                      //If first load, seed the scrollbar down a little to activate the button\n                      if ( self.grid.renderContainers.body.prevRowScrollIndex === 0 ) {\n                        adjustInfiniteScrollPosition(0);\n                      }\n                      //If we are scrolling up, we need to reseed the grid.\n                      if (self.grid.scrollDirection === uiGridConstants.scrollDirection.UP) {\n                        adjustInfiniteScrollPosition(self.grid.renderContainers.body.prevRowScrollIndex + 1 + self.grid.options.excessRows);\n                      }\n                    }\n                    }, 0);\n                });\n              });\n          });\n        }\n      }\n\n      $scope.$on('$destroy', function() {\n        dataWatchCollectionDereg();\n        columnDefWatchCollectionDereg();\n      });\n\n      $scope.$watch(function () { return self.grid.styleComputations; }, function() {\n        self.grid.refreshCanvas(true);\n      });\n\n\n      self.fireEvent = function(eventName, args) {\n        // Add the grid to the event arguments if it's not there\n        if (typeof(args) === 'undefined' || args === undefined) {\n          args = {};\n        }\n\n        if (typeof(args.grid) === 'undefined' || args.grid === undefined) {\n          args.grid = self.grid;\n        }\n\n        $scope.$broadcast(eventName, args);\n      };\n\n      self.innerCompile = function innerCompile(elm) {\n        $compile(elm)($scope);\n      };\n\n    }]);\n\n/**\n *  @ngdoc directive\n *  @name ui.grid.directive:uiGrid\n *  @element div\n *  @restrict EA\n *  @param {Object} uiGrid Options for the grid to use\n *\n *  @description Create a very basic grid.\n *\n *  @example\n    <example module=\"app\">\n      <file name=\"app.js\">\n        var app = angular.module('app', ['ui.grid']);\n\n        app.controller('MainCtrl', ['$scope', function ($scope) {\n          $scope.data = [\n            { name: 'Bob', title: 'CEO' },\n            { name: 'Frank', title: 'Lowly Developer' }\n          ];\n        }]);\n      </file>\n      <file name=\"index.html\">\n        <div ng-controller=\"MainCtrl\">\n          <div ui-grid=\"{ data: data }\"></div>\n        </div>\n      </file>\n    </example>\n */\nangular.module('ui.grid').directive('uiGrid',\n  [\n    '$compile',\n    '$templateCache',\n    'gridUtil',\n    '$window',\n    'uiGridConstants',\n    function(\n      $compile,\n      $templateCache,\n      gridUtil,\n      $window,\n      uiGridConstants\n      ) {\n      return {\n        templateUrl: 'ui-grid/ui-grid',\n        scope: {\n          uiGrid: '='\n        },\n        replace: true,\n        transclude: true,\n        controller: 'uiGridController',\n        compile: function () {\n          return {\n            post: function ($scope, $elm, $attrs, uiGridCtrl) {\n              // gridUtil.logDebug('ui-grid postlink');\n\n              var grid = uiGridCtrl.grid;\n\n              // Initialize scrollbars (TODO: move to controller??)\n              uiGridCtrl.scrollbars = [];\n\n              //todo: assume it is ok to communicate that rendering is complete??\n              grid.renderingComplete();\n\n              grid.element = $elm;\n\n              grid.gridWidth = $scope.gridWidth = gridUtil.elementWidth($elm);\n\n              // Default canvasWidth to the grid width, in case we don't get any column definitions to calculate it from\n              grid.canvasWidth = uiGridCtrl.grid.gridWidth;\n\n              grid.gridHeight = $scope.gridHeight = gridUtil.elementHeight($elm);\n\n              // If the grid isn't tall enough to fit a single row, it's kind of useless. Resize it to fit a minimum number of rows\n              if (grid.gridHeight < grid.options.rowHeight) {\n                // Figure out the new height\n                var contentHeight = grid.options.minRowsToShow * grid.options.rowHeight;\n                var headerHeight = grid.options.showHeader ? grid.options.headerRowHeight : 0;\n                var footerHeight = grid.calcFooterHeight();\n                \n                var scrollbarHeight = 0;\n                if (grid.options.enableHorizontalScrollbar === uiGridConstants.scrollbars.ALWAYS) {\n                  scrollbarHeight = gridUtil.getScrollbarWidth();\n                }\n\n                var maxNumberOfFilters = 0;\n                // Calculates the maximum number of filters in the columns\n                angular.forEach(grid.options.columnDefs, function(col) {\n                  if (col.hasOwnProperty('filter')) {\n                    if (maxNumberOfFilters < 1) {\n                        maxNumberOfFilters = 1;\n                    }\n                  }\n                  else if (col.hasOwnProperty('filters')) {\n                    if (maxNumberOfFilters < col.filters.length) {\n                        maxNumberOfFilters = col.filters.length;\n                    }\n                  }\n                });\n                var filterHeight = maxNumberOfFilters * headerHeight;\n\n                var newHeight = headerHeight + contentHeight + footerHeight + scrollbarHeight + filterHeight;\n\n                $elm.css('height', newHeight + 'px');\n\n                grid.gridHeight = $scope.gridHeight = gridUtil.elementHeight($elm);\n              }\n\n              // Run initial canvas refresh\n              grid.refreshCanvas();\n\n              //if we add a left container after render, we need to watch and react\n              $scope.$watch(function () { return grid.hasLeftContainer();}, function (newValue, oldValue) {\n                if (newValue === oldValue) {\n                  return;\n                }\n                grid.refreshCanvas(true);\n              });\n\n              //if we add a right container after render, we need to watch and react\n              $scope.$watch(function () { return grid.hasRightContainer();}, function (newValue, oldValue) {\n                if (newValue === oldValue) {\n                  return;\n                }\n                grid.refreshCanvas(true);\n              });\n\n\n              // Resize the grid on window resize events\n              function gridResize($event) {\n                grid.gridWidth = $scope.gridWidth = gridUtil.elementWidth($elm);\n                grid.gridHeight = $scope.gridHeight = gridUtil.elementHeight($elm);\n\n                grid.refreshCanvas(true);\n              }\n\n              angular.element($window).on('resize', gridResize);\n\n              // Unbind from window resize events when the grid is destroyed\n              $elm.on('$destroy', function () {\n                angular.element($window).off('resize', gridResize);\n              });\n            }\n          };\n        }\n      };\n    }\n  ]);\n\n})();\n\n(function(){\n  'use strict';\n\n  angular.module('ui.grid').directive('uiGridPinnedContainer', ['gridUtil', function (gridUtil) {\n    return {\n      restrict: 'EA',\n      replace: true,\n      template: '<div class=\"ui-grid-pinned-container\"><div ui-grid-render-container container-id=\"side\" row-container-name=\"\\'body\\'\" col-container-name=\"side\" bind-scroll-vertical=\"true\" class=\"{{ side }} ui-grid-render-container-{{ side }}\"></div></div>',\n      scope: {\n        side: '=uiGridPinnedContainer'\n      },\n      require: '^uiGrid',\n      compile: function compile() {\n        return {\n          post: function ($scope, $elm, $attrs, uiGridCtrl) {\n            // gridUtil.logDebug('ui-grid-pinned-container ' + $scope.side + ' link');\n\n            var grid = uiGridCtrl.grid;\n\n            var myWidth = 0;\n\n            $elm.addClass('ui-grid-pinned-container-' + $scope.side);\n\n            function updateContainerWidth() {\n              if ($scope.side === 'left' || $scope.side === 'right') {\n                var cols = grid.renderContainers[$scope.side].visibleColumnCache;\n                var width = 0;\n                for (var i = 0; i < cols.length; i++) {\n                  var col = cols[i];\n                  width += col.drawnWidth || col.width || 0;\n                }\n\n                myWidth = width;\n              }              \n            }\n            \n            function updateContainerDimensions() {\n              // gridUtil.logDebug('update ' + $scope.side + ' dimensions');\n\n              var ret = '';\n              \n              // Column containers\n              if ($scope.side === 'left' || $scope.side === 'right') {\n                updateContainerWidth();\n\n                // gridUtil.logDebug('myWidth', myWidth);\n\n                // TODO(c0bra): Subtract sum of col widths from grid viewport width and update it\n                $elm.attr('style', null);\n\n                var myHeight = grid.renderContainers.body.getViewportHeight(); // + grid.horizontalScrollbarHeight;\n\n                ret += '.grid' + grid.id + ' .ui-grid-pinned-container-' + $scope.side + ', .grid' + grid.id + ' .ui-grid-pinned-container-' + $scope.side + ' .ui-grid-render-container-' + $scope.side + ' .ui-grid-viewport { width: ' + myWidth + 'px; height: ' + myHeight + 'px; } ';\n              }\n\n              return ret;\n            }\n\n            grid.renderContainers.body.registerViewportAdjuster(function (adjustment) {\n              if ( myWidth === 0 || !myWidth ){\n                updateContainerWidth();\n              }\n              // Subtract our own width\n              adjustment.width -= myWidth;\n\n              return adjustment;\n            });\n\n            // Register style computation to adjust for columns in `side`'s render container\n            grid.registerStyleComputation({\n              priority: 15,\n              func: updateContainerDimensions\n            });\n          }\n        };\n      }\n    };\n  }]);\n})();\n(function(){\n\nangular.module('ui.grid')\n.factory('Grid', ['$q', '$compile', '$parse', 'gridUtil', 'uiGridConstants', 'GridOptions', 'GridColumn', 'GridRow', 'GridApi', 'rowSorter', 'rowSearcher', 'GridRenderContainer', '$timeout',\n    function($q, $compile, $parse, gridUtil, uiGridConstants, GridOptions, GridColumn, GridRow, GridApi, rowSorter, rowSearcher, GridRenderContainer, $timeout) {\n\n  /**\n   * @ngdoc object\n   * @name ui.grid.core.api:PublicApi\n   * @description Public Api for the core grid features\n   *\n   */\n  \n  /**\n   * @ngdoc function\n   * @name ui.grid.class:Grid\n   * @description Grid is the main viewModel.  Any properties or methods needed to maintain state are defined in\n   * this prototype.  One instance of Grid is created per Grid directive instance.\n   * @param {object} options Object map of options to pass into the grid. An 'id' property is expected.\n   */\n  var Grid = function Grid(options) {\n    var self = this;\n    // Get the id out of the options, then remove it\n    if (options !== undefined && typeof(options.id) !== 'undefined' && options.id) {\n      if (!/^[_a-zA-Z0-9-]+$/.test(options.id)) {\n        throw new Error(\"Grid id '\" + options.id + '\" is invalid. It must follow CSS selector syntax rules.');\n      }\n    }\n    else {\n      throw new Error('No ID provided. An ID must be given when creating a grid.');\n    }\n  \n    self.id = options.id;\n    delete options.id;\n  \n    // Get default options\n    self.options = GridOptions.initialize( options );\n\n    /**\n     * @ngdoc object\n     * @name appScope\n     * @propertyOf ui.grid.class:Grid\n     * @description reference to the application scope (the parent scope of the ui-grid element).  Assigned in ui-grid controller\n     * <br/>\n     * use gridOptions.appScopeProvider to override the default assignment of $scope.$parent with any reference\n     */\n    self.appScope = self.options.appScopeProvider;\n  \n    self.headerHeight = self.options.headerRowHeight;\n\n\n    self.footerHeight = self.calcFooterHeight();\n\n    self.rtl = false;\n    self.gridHeight = 0;\n    self.gridWidth = 0;\n    self.columnBuilders = [];\n    self.rowBuilders = [];\n    self.rowsProcessors = [];\n    self.columnsProcessors = [];\n    self.styleComputations = [];\n    self.viewportAdjusters = [];\n    self.rowHeaderColumns = [];\n    self.dataChangeCallbacks = {};\n  \n    // self.visibleRowCache = [];\n  \n    // Set of 'render' containers for self grid, which can render sets of rows\n    self.renderContainers = {};\n  \n    // Create a\n    self.renderContainers.body = new GridRenderContainer('body', self);\n  \n    self.cellValueGetterCache = {};\n  \n    // Cached function to use with custom row templates\n    self.getRowTemplateFn = null;\n  \n  \n    //representation of the rows on the grid.\n    //these are wrapped references to the actual data rows (options.data)\n    self.rows = [];\n  \n    //represents the columns on the grid\n    self.columns = [];\n  \n    /**\n     * @ngdoc boolean\n     * @name isScrollingVertically\n     * @propertyOf ui.grid.class:Grid\n     * @description set to true when Grid is scrolling vertically. Set to false via debounced method\n     */\n    self.isScrollingVertically = false;\n  \n    /**\n     * @ngdoc boolean\n     * @name isScrollingHorizontally\n     * @propertyOf ui.grid.class:Grid\n     * @description set to true when Grid is scrolling horizontally. Set to false via debounced method\n     */\n    self.isScrollingHorizontally = false;\n\n    /**\n     * @ngdoc property\n     * @name scrollDirection\n     * @propertyOf ui.grid.class:Grid\n     * @description set one of the uiGridConstants.scrollDirection values (UP, DOWN, LEFT, RIGHT, NONE), which tells\n     * us which direction we are scrolling. Set to NONE via debounced method\n     */\n    self.scrollDirection = uiGridConstants.scrollDirection.NONE;\n\n    var debouncedVertical = gridUtil.debounce(function () {\n      self.isScrollingVertically = false;\n      self.scrollDirection = uiGridConstants.scrollDirection.NONE;\n    }, 1000);\n  \n    var debouncedHorizontal = gridUtil.debounce(function () {\n      self.isScrollingHorizontally = false;\n      self.scrollDirection = uiGridConstants.scrollDirection.NONE;\n    }, 1000);\n  \n  \n    /**\n     * @ngdoc function\n     * @name flagScrollingVertically\n     * @methodOf ui.grid.class:Grid\n     * @description sets isScrollingVertically to true and sets it to false in a debounced function\n     */\n    self.flagScrollingVertically = function() {\n      self.isScrollingVertically = true;\n      debouncedVertical();\n    };\n  \n    /**\n     * @ngdoc function\n     * @name flagScrollingHorizontally\n     * @methodOf ui.grid.class:Grid\n     * @description sets isScrollingHorizontally to true and sets it to false in a debounced function\n     */\n    self.flagScrollingHorizontally = function() {\n      self.isScrollingHorizontally = true;\n      debouncedHorizontal();\n    };\n\n    self.scrollbarHeight = 0;\n    self.scrollbarWidth = 0;\n    if (self.options.enableHorizontalScrollbar === uiGridConstants.scrollbars.ALWAYS) {\n      self.scrollbarHeight = gridUtil.getScrollbarWidth();\n    }\n\n    if (self.options.enableVerticalScrollbar === uiGridConstants.scrollbars.ALWAYS) {\n      self.scrollbarWidth = gridUtil.getScrollbarWidth();\n    }\n  \n  \n  \n    self.api = new GridApi(self);\n  \n    /**\n     * @ngdoc function\n     * @name refresh\n     * @methodOf ui.grid.core.api:PublicApi\n     * @description Refresh the rendered grid on screen.\n     * \n     */\n    self.api.registerMethod( 'core', 'refresh', this.refresh );\n  \n    /**\n     * @ngdoc function\n     * @name refreshRows\n     * @methodOf ui.grid.core.api:PublicApi\n     * @description Refresh the rendered grid on screen?  Note: not functional at present\n     * @returns {promise} promise that is resolved when render completes?\n     * \n     */\n    self.api.registerMethod( 'core', 'refreshRows', this.refreshRows );\n  \n    /**\n     * @ngdoc function\n     * @name handleWindowResize\n     * @methodOf ui.grid.core.api:PublicApi\n     * @description Trigger a grid resize, normally this would be picked\n     * up by a watch on window size, but in some circumstances it is necessary\n     * to call this manually\n     * @returns {promise} promise that is resolved when render completes?\n     * \n     */\n    self.api.registerMethod( 'core', 'handleWindowResize', this.handleWindowResize );\n  \n  \n    /**\n     * @ngdoc function\n     * @name addRowHeaderColumn\n     * @methodOf ui.grid.core.api:PublicApi\n     * @description adds a row header column to the grid\n     * @param {object} column def\n     * \n     */\n    self.api.registerMethod( 'core', 'addRowHeaderColumn', this.addRowHeaderColumn );\n  \n  \n    /**\n     * @ngdoc function\n     * @name sortHandleNulls\n     * @methodOf ui.grid.core.api:PublicApi\n     * @description A null handling method that can be used when building custom sort\n     * functions\n     * @example\n     * <pre>\n     *   mySortFn = function(a, b) {\n     *   var nulls = $scope.gridApi.core.sortHandleNulls(a, b);\n     *   if ( nulls !== null ){\n     *     return nulls;\n     *   } else {\n     *     // your code for sorting here\n     *   };\n     * </pre>\n     * @param {object} a sort value a\n     * @param {object} b sort value b\n     * @returns {number} null if there were no nulls/undefineds, otherwise returns\n     * a sort value that should be passed back from the sort function\n     * \n     */\n    self.api.registerMethod( 'core', 'sortHandleNulls', rowSorter.handleNulls );\n  \n  \n    /**\n     * @ngdoc function\n     * @name sortChanged\n     * @methodOf  ui.grid.core.api:PublicApi\n     * @description The sort criteria on one or more columns has\n     * changed.  Provides as parameters the grid and the output of\n     * getColumnSorting, which is an array of gridColumns\n     * that have sorting on them, sorted in priority order. \n     * \n     * @param {Grid} grid the grid\n     * @param {array} sortColumns an array of columns with \n     * sorts on them, in priority order\n     * \n     * @example\n     * <pre>\n     *      gridApi.core.on.sortChanged( grid, sortColumns );\n     * </pre>\n     */\n    self.api.registerEvent( 'core', 'sortChanged' );\n  \n      /**\n     * @ngdoc function\n     * @name columnVisibilityChanged\n     * @methodOf  ui.grid.core.api:PublicApi\n     * @description The visibility of a column has changed,\n     * the column itself is passed out as a parameter of the event. \n     * \n     * @param {GridCol} column the column that changed\n     * \n     * @example\n     * <pre>\n     *      gridApi.core.on.columnVisibilityChanged( $scope, function (column) {\n     *        // do something\n     *      } );\n     * </pre>\n     */\n    self.api.registerEvent( 'core', 'columnVisibilityChanged' );\n  \n    /**\n     * @ngdoc method\n     * @name notifyDataChange\n     * @methodOf ui.grid.core.api:PublicApi\n     * @description Notify the grid that a data or config change has occurred,\n     * where that change isn't something the grid was otherwise noticing.  This \n     * might be particularly relevant where you've changed values within the data\n     * and you'd like cell classes to be re-evaluated, or changed config within \n     * the columnDef and you'd like headerCellClasses to be re-evaluated.\n     * @param {string} type one of the \n     * uiGridConstants.dataChange values (ALL, ROW, EDIT, COLUMN), which tells\n     * us which refreshes to fire.\n     * \n     */\n    self.api.registerMethod( 'core', 'notifyDataChange', this.notifyDataChange );\n    \n    self.registerDataChangeCallback( self.columnRefreshCallback, [uiGridConstants.dataChange.COLUMN]);\n    self.registerDataChangeCallback( self.processRowsCallback, [uiGridConstants.dataChange.EDIT]);\n\n    self.registerStyleComputation({\n      priority: 10,\n      func: self.getFooterStyles\n    });\n  };\n\n   Grid.prototype.calcFooterHeight = function () {\n     if (!this.hasFooter()) {\n       return 0;\n     }\n\n     var height = 0;\n     if (this.options.showGridFooter) {\n       height += this.options.gridFooterHeight;\n     }\n\n     if (this.options.showColumnFooter) {\n       height += this.options.columnFooterHeight;\n     }\n\n     return height;\n   };\n\n   Grid.prototype.getFooterStyles = function () {\n     var style = '.grid' + this.id + ' .ui-grid-footer-aggregates-row { height: ' + this.options.columnFooterHeight + 'px; }';\n     style += ' .grid' + this.id + ' .ui-grid-footer-info { height: ' + this.options.gridFooterHeight + 'px; }';\n     return style;\n   };\n\n  Grid.prototype.hasFooter = function () {\n   return this.options.showGridFooter || this.options.showColumnFooter;\n  };\n\n  /**\n   * @ngdoc function\n   * @name isRTL\n   * @methodOf ui.grid.class:Grid\n   * @description Returns true if grid is RightToLeft\n   */\n  Grid.prototype.isRTL = function () {\n    return this.rtl;\n  };\n\n\n  /**\n   * @ngdoc function\n   * @name registerColumnBuilder\n   * @methodOf ui.grid.class:Grid\n   * @description When the build creates columns from column definitions, the columnbuilders will be called to add\n   * additional properties to the column.\n   * @param {function(colDef, col, gridOptions)} columnsProcessor function to be called\n   */\n  Grid.prototype.registerColumnBuilder = function registerColumnBuilder(columnBuilder) {\n    this.columnBuilders.push(columnBuilder);\n  };\n\n  /**\n   * @ngdoc function\n   * @name buildColumnDefsFromData\n   * @methodOf ui.grid.class:Grid\n   * @description Populates columnDefs from the provided data\n   * @param {function(colDef, col, gridOptions)} rowBuilder function to be called\n   */\n  Grid.prototype.buildColumnDefsFromData = function (dataRows){\n    this.options.columnDefs =  gridUtil.getColumnsFromData(dataRows, this.options.excludeProperties);\n  };\n\n  /**\n   * @ngdoc function\n   * @name registerRowBuilder\n   * @methodOf ui.grid.class:Grid\n   * @description When the build creates rows from gridOptions.data, the rowBuilders will be called to add\n   * additional properties to the row.\n   * @param {function(row, gridOptions)} rowBuilder function to be called\n   */\n  Grid.prototype.registerRowBuilder = function registerRowBuilder(rowBuilder) {\n    this.rowBuilders.push(rowBuilder);\n  };\n\n\n  /**\n   * @ngdoc function\n   * @name registerDataChangeCallback\n   * @methodOf ui.grid.class:Grid\n   * @description When a data change occurs, the data change callbacks of the specified type\n   * will be called.  The rules are:\n   * \n   * - when the data watch fires, that is considered a ROW change (the data watch only notices\n   *   added or removed rows)\n   * - when the api is called to inform us of a change, the declared type of that change is used\n   * - when a cell edit completes, the EDIT callbacks are triggered\n   * - when the columnDef watch fires, the COLUMN callbacks are triggered\n   * - when the options watch fires, the OPTIONS callbacks are triggered\n   * \n   * For a given event:\n   * - ALL calls ROW, EDIT, COLUMN, OPTIONS and ALL callbacks\n   * - ROW calls ROW and ALL callbacks\n   * - EDIT calls EDIT and ALL callbacks\n   * - COLUMN calls COLUMN and ALL callbacks\n   * - OPTIONS calls OPTIONS and ALL callbacks\n   * \n   * @param {function(grid)} callback function to be called\n   * @param {array} types the types of data change you want to be informed of.  Values from \n   * the uiGridConstants.dataChange values ( ALL, EDIT, ROW, COLUMN, OPTIONS ).  Optional and defaults to\n   * ALL \n   * @returns {function} deregister function - a function that can be called to deregister this callback\n   */\n  Grid.prototype.registerDataChangeCallback = function registerDataChangeCallback(callback, types, _this) {\n    var uid = gridUtil.nextUid();\n    if ( !types ){\n      types = [uiGridConstants.dataChange.ALL];\n    }\n    if ( !Array.isArray(types)){\n      gridUtil.logError(\"Expected types to be an array or null in registerDataChangeCallback, value passed was: \" + types );\n    }\n    this.dataChangeCallbacks[uid] = { callback: callback, types: types, _this:_this };\n    \n    var self = this;\n    var deregisterFunction = function() {\n      delete self.dataChangeCallbacks[uid];\n    };\n    return deregisterFunction;\n  };\n\n  /**\n   * @ngdoc function\n   * @name callDataChangeCallbacks\n   * @methodOf ui.grid.class:Grid\n   * @description Calls the callbacks based on the type of data change that\n   * has occurred. Always calls the ALL callbacks, calls the ROW, EDIT, COLUMN and OPTIONS callbacks if the \n   * event type is matching, or if the type is ALL.\n   * @param {number} type the type of event that occurred - one of the \n   * uiGridConstants.dataChange values (ALL, ROW, EDIT, COLUMN, OPTIONS)\n   */\n  Grid.prototype.callDataChangeCallbacks = function callDataChangeCallbacks(type, options) {\n    angular.forEach( this.dataChangeCallbacks, function( callback, uid ){\n      if ( callback.types.indexOf( uiGridConstants.dataChange.ALL ) !== -1 ||\n           callback.types.indexOf( type ) !== -1 ||\n           type === uiGridConstants.dataChange.ALL ) {\n        if (callback._this) {\n           callback.callback.apply(callback._this,this);\n        }\n        else {\n          callback.callback( this );\n        }\n      }\n    }, this);\n  };\n  \n  /**\n   * @ngdoc function\n   * @name notifyDataChange\n   * @methodOf ui.grid.class:Grid\n   * @description Notifies us that a data change has occurred, used in the public\n   * api for users to tell us when they've changed data or some other event that \n   * our watches cannot pick up\n   * @param {string} type the type of event that occurred - one of the \n   * uiGridConstants.dataChange values (ALL, ROW, EDIT, COLUMN)\n   */\n  Grid.prototype.notifyDataChange = function notifyDataChange(type) {\n    var constants = uiGridConstants.dataChange;\n    if ( type === constants.ALL || \n         type === constants.COLUMN ||\n         type === constants.EDIT ||\n         type === constants.ROW ||\n         type === constants.OPTIONS ){\n      this.callDataChangeCallbacks( type );\n    } else {\n      gridUtil.logError(\"Notified of a data change, but the type was not recognised, so no action taken, type was: \" + type);\n    }\n  };\n  \n  \n  /**\n   * @ngdoc function\n   * @name columnRefreshCallback\n   * @methodOf ui.grid.class:Grid\n   * @description refreshes the grid when a column refresh\n   * is notified, which triggers handling of the visible flag. \n   * This is called on uiGridConstants.dataChange.COLUMN, and is \n   * registered as a dataChangeCallback in grid.js\n   * @param {string} name column name\n   */\n  Grid.prototype.columnRefreshCallback = function columnRefreshCallback( grid ){\n    grid.buildColumns();\n    grid.refresh();\n  };\n\n\n  /**\n   * @ngdoc function\n   * @name processRowsCallback\n   * @methodOf ui.grid.class:Grid\n   * @description calls the row processors, specifically\n   * intended to reset the sorting when an edit is called,\n   * registered as a dataChangeCallback on uiGridConstants.dataChange.EDIT\n   * @param {string} name column name\n   */\n  Grid.prototype.processRowsCallback = function processRowsCallback( grid ){\n    grid.refreshRows();\n  };\n    \n\n  /**\n   * @ngdoc function\n   * @name getColumn\n   * @methodOf ui.grid.class:Grid\n   * @description returns a grid column for the column name\n   * @param {string} name column name\n   */\n  Grid.prototype.getColumn = function getColumn(name) {\n    var columns = this.columns.filter(function (column) {\n      return column.colDef.name === name;\n    });\n    return columns.length > 0 ? columns[0] : null;\n  };\n\n  /**\n   * @ngdoc function\n   * @name getColDef\n   * @methodOf ui.grid.class:Grid\n   * @description returns a grid colDef for the column name\n   * @param {string} name column.field\n   */\n  Grid.prototype.getColDef = function getColDef(name) {\n    var colDefs = this.options.columnDefs.filter(function (colDef) {\n      return colDef.name === name;\n    });\n    return colDefs.length > 0 ? colDefs[0] : null;\n  };\n\n  /**\n   * @ngdoc function\n   * @name assignTypes\n   * @methodOf ui.grid.class:Grid\n   * @description uses the first row of data to assign colDef.type for any types not defined.\n   */\n  /**\n   * @ngdoc property\n   * @name type\n   * @propertyOf ui.grid.class:GridOptions.columnDef\n   * @description the type of the column, used in sorting.  If not provided then the \n   * grid will guess the type.  Add this only if the grid guessing is not to your\n   * satisfaction.  Refer to {@link ui.grid.service:GridUtil.guessType gridUtil.guessType} for\n   * a list of values the grid knows about.\n   *\n   */\n  Grid.prototype.assignTypes = function(){\n    var self = this;\n    self.options.columnDefs.forEach(function (colDef, index) {\n\n      //Assign colDef type if not specified\n      if (!colDef.type) {\n        var col = new GridColumn(colDef, index, self);\n        var firstRow = self.rows.length > 0 ? self.rows[0] : null;\n        if (firstRow) {\n          colDef.type = gridUtil.guessType(self.getCellValue(firstRow, col));\n        }\n        else {\n          gridUtil.logWarn('Unable to assign type from data, so defaulting to string');\n          colDef.type = 'string';\n        }\n      }\n    });\n  };\n\n  /**\n  * @ngdoc function\n  * @name addRowHeaderColumn\n  * @methodOf ui.grid.class:Grid\n  * @description adds a row header column to the grid\n  * @param {object} column def\n  */\n  Grid.prototype.addRowHeaderColumn = function addRowHeaderColumn(colDef) {\n    var self = this;\n    //self.createLeftContainer();\n    var rowHeaderCol = new GridColumn(colDef, self.rowHeaderColumns.length, self);\n    rowHeaderCol.isRowHeader = true;\n    if (self.isRTL()) {\n      self.createRightContainer();\n      rowHeaderCol.renderContainer = 'right';\n    }\n    else {\n      self.createLeftContainer();\n      rowHeaderCol.renderContainer = 'left';\n    }\n\n    // relies on the default column builder being first in array, as it is instantiated\n    // as part of grid creation\n    self.columnBuilders[0](colDef,rowHeaderCol,self.options)\n      .then(function(){\n        rowHeaderCol.enableFiltering = false;\n        rowHeaderCol.enableSorting = false;\n        rowHeaderCol.enableHiding = false;\n        self.rowHeaderColumns.push(rowHeaderCol);\n        self.buildColumns()\n          .then( function() {\n            self.preCompileCellTemplates();\n            self.refresh();\n          });\n      });\n  };\n\n  /**\n   * @ngdoc function\n   * @name buildColumns\n   * @methodOf ui.grid.class:Grid\n   * @description creates GridColumn objects from the columnDefinition.  Calls each registered\n   * columnBuilder to further process the column\n   * @param {object} options  An object contains options to use when building columns\n   *\n   * * **orderByColumnDefs**: defaults to **false**. When true, `buildColumns` will reorder existing columns according to the order within the column definitions.\n   *\n   * @returns {Promise} a promise to load any needed column resources\n   */\n  Grid.prototype.buildColumns = function buildColumns(opts) {\n    var options = {\n      orderByColumnDefs: false\n    };\n\n    angular.extend(options, opts);\n\n    // gridUtil.logDebug('buildColumns');\n    var self = this;\n    var builderPromises = [];\n    var headerOffset = self.rowHeaderColumns.length;\n    var i;\n\n    // Remove any columns for which a columnDef cannot be found\n    // Deliberately don't use forEach, as it doesn't like splice being called in the middle\n    // Also don't cache columns.length, as it will change during this operation\n    for (i = 0; i < self.columns.length; i++){\n      if (!self.getColDef(self.columns[i].name)) {\n        self.columns.splice(i, 1);\n        i--;\n      }\n    }\n\n    //add row header columns to the grid columns array _after_ columns without columnDefs have been removed\n    self.rowHeaderColumns.forEach(function (rowHeaderColumn) {\n      self.columns.unshift(rowHeaderColumn);\n    });\n\n\n    // look at each column def, and update column properties to match.  If the column def\n    // doesn't have a column, then splice in a new gridCol\n    self.options.columnDefs.forEach(function (colDef, index) {\n      self.preprocessColDef(colDef);\n      var col = self.getColumn(colDef.name);\n\n      if (!col) {\n        col = new GridColumn(colDef, gridUtil.nextUid(), self);\n        self.columns.splice(index + headerOffset, 0, col);\n      }\n      else {\n        // tell updateColumnDef that the column was pre-existing\n        col.updateColumnDef(colDef, false);\n      }\n\n      self.columnBuilders.forEach(function (builder) {\n        builderPromises.push(builder.call(self, colDef, col, self.options));\n      });\n    });\n\n    /*** Reorder columns if necessary ***/\n    if (!!options.orderByColumnDefs) {\n      // Create a shallow copy of the columns as a cache\n      var columnCache = self.columns.slice(0);\n\n      // We need to allow for the \"row headers\" when mapping from the column defs array to the columns array\n      //   If we have a row header in columns[0] and don't account for it   we'll overwrite it with the column in columnDefs[0]\n\n      // Go through all the column defs\n      for (i = 0; i < self.options.columnDefs.length; i++) {\n        // If the column at this index has a different name than the column at the same index in the column defs...\n        if (self.columns[i + headerOffset].name !== self.options.columnDefs[i].name) {\n          // Replace the one in the cache with the appropriate column\n          columnCache[i + headerOffset] = self.getColumn(self.options.columnDefs[i].name);\n        }\n        else {\n          // Otherwise just copy over the one from the initial columns\n          columnCache[i + headerOffset] = self.columns[i + headerOffset];\n        }\n      }\n\n      // Empty out the columns array, non-destructively\n      self.columns.length = 0;\n\n      // And splice in the updated, ordered columns from the cache\n      Array.prototype.splice.apply(self.columns, [0, 0].concat(columnCache));\n    }\n\n    return $q.all(builderPromises).then(function(){\n      if (self.rows.length > 0){\n        self.assignTypes();\n      }\n    });\n  };\n\n/**\n * @ngdoc function\n * @name preCompileCellTemplates\n * @methodOf ui.grid.class:Grid\n * @description precompiles all cell templates\n */\n  Grid.prototype.preCompileCellTemplates = function() {\n    var self = this;\n    this.columns.forEach(function (col) {\n      var html = col.cellTemplate.replace(uiGridConstants.MODEL_COL_FIELD, self.getQualifiedColField(col));\n      html = html.replace(uiGridConstants.COL_FIELD, 'grid.getCellValue(row, col)');\n\n\n      var compiledElementFn = $compile(html);\n      col.compiledElementFn = compiledElementFn;\n\n      if (col.compiledElementFnDefer) {\n        col.compiledElementFnDefer.resolve(col.compiledElementFn);\n      }\n    });\n  };\n\n  /**\n   * @ngdoc function\n   * @name getGridQualifiedColField\n   * @methodOf ui.grid.class:Grid\n   * @description Returns the $parse-able accessor for a column within its $scope\n   * @param {GridColumn} col col object\n   */\n  Grid.prototype.getQualifiedColField = function (col) {\n    return 'row.entity.' + gridUtil.preEval(col.field);\n  };\n\n  /**\n   * @ngdoc function\n   * @name createLeftContainer\n   * @methodOf ui.grid.class:Grid\n   * @description creates the left render container if it doesn't already exist\n   */\n  Grid.prototype.createLeftContainer = function() {\n    if (!this.hasLeftContainer()) {\n      this.renderContainers.left = new GridRenderContainer('left', this, { disableColumnOffset: true });\n    }\n  };\n\n  /**\n   * @ngdoc function\n   * @name createRightContainer\n   * @methodOf ui.grid.class:Grid\n   * @description creates the right render container if it doesn't already exist\n   */\n  Grid.prototype.createRightContainer = function() {\n    if (!this.hasRightContainer()) {\n      this.renderContainers.right = new GridRenderContainer('right', this, { disableColumnOffset: true });\n    }\n  };\n\n  /**\n   * @ngdoc function\n   * @name hasLeftContainer\n   * @methodOf ui.grid.class:Grid\n   * @description returns true if leftContainer exists\n   */\n  Grid.prototype.hasLeftContainer = function() {\n    return this.renderContainers.left !== undefined;\n  };\n\n  /**\n   * @ngdoc function\n   * @name hasLeftContainer\n   * @methodOf ui.grid.class:Grid\n   * @description returns true if rightContainer exists\n   */\n  Grid.prototype.hasRightContainer = function() {\n    return this.renderContainers.right !== undefined;\n  };\n\n\n      /**\n   * undocumented function\n   * @name preprocessColDef\n   * @methodOf ui.grid.class:Grid\n   * @description defaults the name property from field to maintain backwards compatibility with 2.x\n   * validates that name or field is present\n   */\n  Grid.prototype.preprocessColDef = function preprocessColDef(colDef) {\n    var self = this;\n\n    if (!colDef.field && !colDef.name) {\n      throw new Error('colDef.name or colDef.field property is required');\n    }\n\n    //maintain backwards compatibility with 2.x\n    //field was required in 2.x.  now name is required\n    if (colDef.name === undefined && colDef.field !== undefined) {\n      // See if the column name already exists:\n      var foundName = self.getColumn(colDef.field);\n\n      // If a column with this name already  exists, we will add an incrementing number to the end of the new column name\n      if (foundName) {\n        // Search through the columns for names in the format: <name><1, 2 ... N>, i.e. 'Age1, Age2, Age3',\n        var nameRE = new RegExp('^' + colDef.field + '(\\\\d+)$', 'i');\n\n        var foundColumns = self.columns.filter(function (column) {\n          // Test against the displayName, as that's what'll have the incremented number\n          return nameRE.test(column.displayName);\n        })\n        // Sort the found columns by the end-number\n        .sort(function (a, b) {\n          if (a === b) {\n            return 0;\n          }\n          else {\n            var numA = a.match(nameRE)[1];\n            var numB = b.match(nameRE)[1];\n\n            return parseInt(numA, 10) > parseInt(numB, 10) ? 1 : -1;\n          }\n        });\n\n        // Not columns found, so start with number \"2\"\n        if (foundColumns.length === 0) {\n          colDef.name = colDef.field + '2';\n        }\n        else {\n          // Get the number from the final column\n          var lastNum = foundColumns[foundColumns.length-1].displayName.match(nameRE)[1];\n\n          // Make sure to parse to an int\n          lastNum = parseInt(lastNum, 10);\n\n          // Add 1 to the number from the last column and tack it on to the field to be the name for this new column \n          colDef.name = colDef.field + (lastNum + 1);\n        }\n      }\n      // ... otherwise just use the field as the column name\n      else {\n        colDef.name = colDef.field;\n      }\n    }\n\n  };\n\n  // Return a list of items that exist in the `n` array but not the `o` array. Uses optional property accessors passed as third & fourth parameters\n  Grid.prototype.newInN = function newInN(o, n, oAccessor, nAccessor) {\n    var self = this;\n\n    var t = [];\n    for (var i = 0; i < n.length; i++) {\n      var nV = nAccessor ? n[i][nAccessor] : n[i];\n      \n      var found = false;\n      for (var j = 0; j < o.length; j++) {\n        var oV = oAccessor ? o[j][oAccessor] : o[j];\n        if (self.options.rowEquality(nV, oV)) {\n          found = true;\n          break;\n        }\n      }\n      if (!found) {\n        t.push(nV);\n      }\n    }\n    \n    return t;\n  };\n\n    /**\n     * @ngdoc function\n     * @name getRow\n     * @methodOf ui.grid.class:Grid\n     * @description returns the GridRow that contains the rowEntity\n     * @param {object} rowEntity the gridOptions.data array element instance\n     */\n    Grid.prototype.getRow = function getRow(rowEntity) {\n      var self = this;\n      var rows = this.rows.filter(function (row) {\n        return self.options.rowEquality(row.entity, rowEntity);\n      });\n      return rows.length > 0 ? rows[0] : null;\n    };\n\n\n      /**\n   * @ngdoc function\n   * @name modifyRows\n   * @methodOf ui.grid.class:Grid\n   * @description creates or removes GridRow objects from the newRawData array.  Calls each registered\n   * rowBuilder to further process the row\n   *\n   * Rows are identified using the gridOptions.rowEquality function\n   */\n  Grid.prototype.modifyRows = function modifyRows(newRawData) {\n    var self = this,\n        i,\n        rowhash,\n        found,\n        newRow;\n    if ((self.options.useExternalSorting || self.getColumnSorting().length === 0) && newRawData.length > 0) {\n        var oldRowHash = self.rowHashMap;\n        if (!oldRowHash) {\n           oldRowHash = {get: function(){return null;}};\n        }\n        self.createRowHashMap();\n        rowhash = self.rowHashMap;\n        var wasEmpty = self.rows.length === 0;\n        self.rows.length = 0;\n        for (i = 0; i < newRawData.length; i++) {\n            var newRawRow = newRawData[i];\n            found = oldRowHash.get(newRawRow);\n            if (found) {\n              newRow = found.row; \n            }\n            else {\n              newRow = self.processRowBuilders(new GridRow(newRawRow, i, self));\n            }\n            self.rows.push(newRow);\n            rowhash.put(newRawRow, {\n                i: i,\n                entity: newRawRow,\n                row:newRow\n            });\n        }\n        //now that we have data, it is save to assign types to colDefs\n//        if (wasEmpty) {\n           self.assignTypes();\n//        }\n    } else {\n    if (self.rows.length === 0 && newRawData.length > 0) {\n      if (self.options.enableRowHashing) {\n        if (!self.rowHashMap) {\n          self.createRowHashMap();\n        }\n\n        for (i = 0; i < newRawData.length; i++) {\n          newRow = newRawData[i];\n\n          self.rowHashMap.put(newRow, {\n            i: i,\n            entity: newRow\n          });\n        }\n      }\n\n      self.addRows(newRawData);\n      //now that we have data, it is save to assign types to colDefs\n      self.assignTypes();\n    }\n    else if (newRawData.length > 0) {\n      var unfoundNewRows, unfoundOldRows, unfoundNewRowsToFind;\n\n      // If row hashing is turned on\n      if (self.options.enableRowHashing) {\n        // Array of new rows that haven't been found in the old rowset\n        unfoundNewRows = [];\n        // Array of new rows that we explicitly HAVE to search for manually in the old row set. They cannot be looked up by their identity (because it doesn't exist).\n        unfoundNewRowsToFind = [];\n        // Map of rows that have been found in the new rowset\n        var foundOldRows = {};\n        // Array of old rows that have NOT been found in the new rowset\n        unfoundOldRows = [];\n\n        // Create the row HashMap if it doesn't exist already\n        if (!self.rowHashMap) {\n          self.createRowHashMap();\n        }\n        rowhash = self.rowHashMap;\n        \n        // Make sure every new row has a hash\n        for (i = 0; i < newRawData.length; i++) {\n          newRow = newRawData[i];\n\n          // Flag this row as needing to be manually found if it didn't come in with a $$hashKey\n          var mustFind = false;\n          if (!self.options.getRowIdentity(newRow)) {\n            mustFind = true;\n          }\n\n          // See if the new row is already in the rowhash\n          found = rowhash.get(newRow);\n          // If so...\n          if (found) {\n            // See if it's already being used by as GridRow\n            if (found.row) {\n              // If so, mark this new row as being found\n              foundOldRows[self.options.rowIdentity(newRow)] = true;\n            }\n          }\n          else {\n            // Put the row in the hashmap with the index it corresponds to\n            rowhash.put(newRow, {\n              i: i,\n              entity: newRow\n            });\n            \n            // This row has to be searched for manually in the old row set\n            if (mustFind) {\n              unfoundNewRowsToFind.push(newRow);\n            }\n            else {\n              unfoundNewRows.push(newRow);\n            }\n          }\n        }\n\n        // Build the list of unfound old rows\n        for (i = 0; i < self.rows.length; i++) {\n          var row = self.rows[i];\n          var hash = self.options.rowIdentity(row.entity);\n          if (!foundOldRows[hash]) {\n            unfoundOldRows.push(row);\n          }\n        }\n      }\n\n      // Look for new rows\n      var newRows = unfoundNewRows || [];\n\n      // The unfound new rows is either `unfoundNewRowsToFind`, if row hashing is turned on, or straight `newRawData` if it isn't\n      var unfoundNew = (unfoundNewRowsToFind || newRawData);\n\n      // Search for real new rows in `unfoundNew` and concat them onto `newRows`\n      newRows = newRows.concat(self.newInN(self.rows, unfoundNew, 'entity'));\n      \n      self.addRows(newRows); \n      \n      var deletedRows = self.getDeletedRows((unfoundOldRows || self.rows), newRawData);\n\n      for (i = 0; i < deletedRows.length; i++) {\n        if (self.options.enableRowHashing) {\n          self.rowHashMap.remove(deletedRows[i].entity);\n        }\n\n        self.rows.splice( self.rows.indexOf(deletedRows[i]), 1 );\n      }\n    }\n    // Empty data set\n    else {\n      // Reset the row HashMap\n      self.createRowHashMap();\n\n      // Reset the rows length!\n      self.rows.length = 0;\n    }\n    }\n    \n    var p1 = $q.when(self.processRowsProcessors(self.rows))\n      .then(function (renderableRows) {\n        return self.setVisibleRows(renderableRows);\n      });\n\n    var p2 = $q.when(self.processColumnsProcessors(self.columns))\n      .then(function (renderableColumns) {\n        return self.setVisibleColumns(renderableColumns);\n      });\n\n    return $q.all([p1, p2]);\n  };\n\n  Grid.prototype.getDeletedRows = function(oldRows, newRows) {\n    var self = this;\n\n    var olds = oldRows.filter(function (oldRow) {\n      return !newRows.some(function (newItem) {\n        return self.options.rowEquality(newItem, oldRow.entity);\n      });\n    });\n    // var olds = self.newInN(newRows, oldRows, null, 'entity');\n    // dump('olds', olds);\n    return olds;\n  };\n\n  /**\n   * Private Undocumented Method\n   * @name addRows\n   * @methodOf ui.grid.class:Grid\n   * @description adds the newRawData array of rows to the grid and calls all registered\n   * rowBuilders. this keyword will reference the grid\n   */\n  Grid.prototype.addRows = function addRows(newRawData) {\n    var self = this;\n\n    var existingRowCount = self.rows.length;\n    for (var i = 0; i < newRawData.length; i++) {\n      var newRow = self.processRowBuilders(new GridRow(newRawData[i], i + existingRowCount, self));\n\n      if (self.options.enableRowHashing) {\n        var found = self.rowHashMap.get(newRow.entity);\n        if (found) {\n          found.row = newRow;\n        }\n      }\n\n      self.rows.push(newRow);\n    }\n  };\n\n  /**\n   * @ngdoc function\n   * @name processRowBuilders\n   * @methodOf ui.grid.class:Grid\n   * @description processes all RowBuilders for the gridRow\n   * @param {GridRow} gridRow reference to gridRow\n   * @returns {GridRow} the gridRow with all additional behavior added\n   */\n  Grid.prototype.processRowBuilders = function processRowBuilders(gridRow) {\n    var self = this;\n\n    self.rowBuilders.forEach(function (builder) {\n      builder.call(self, gridRow, self.options);\n    });\n\n    return gridRow;\n  };\n\n  /**\n   * @ngdoc function\n   * @name registerStyleComputation\n   * @methodOf ui.grid.class:Grid\n   * @description registered a styleComputation function\n   * \n   * If the function returns a value it will be appended into the grid's `<style>` block\n   * @param {function($scope)} styleComputation function\n   */\n  Grid.prototype.registerStyleComputation = function registerStyleComputation(styleComputationInfo) {\n    this.styleComputations.push(styleComputationInfo);\n  };\n\n\n  // NOTE (c0bra): We already have rowBuilders. I think these do exactly the same thing...\n  // Grid.prototype.registerRowFilter = function(filter) {\n  //   // TODO(c0bra): validate filter?\n\n  //   this.rowFilters.push(filter);\n  // };\n\n  // Grid.prototype.removeRowFilter = function(filter) {\n  //   var idx = this.rowFilters.indexOf(filter);\n\n  //   if (typeof(idx) !== 'undefined' && idx !== undefined) {\n  //     this.rowFilters.slice(idx, 1);\n  //   }\n  // };\n  \n  // Grid.prototype.processRowFilters = function(rows) {\n  //   var self = this;\n  //   self.rowFilters.forEach(function (filter) {\n  //     filter.call(self, rows);\n  //   });\n  // };\n\n\n  /**\n   * @ngdoc function\n   * @name registerRowsProcessor\n   * @methodOf ui.grid.class:Grid\n   * @param {function(renderableRows)} rows processor function\n   * @returns {Array[GridRow]} Updated renderable rows\n   * @description\n\n     Register a \"rows processor\" function. When the rows are updated,\n     the grid calls each registered \"rows processor\", which has a chance\n     to alter the set of rows (sorting, etc) as long as the count is not\n     modified.\n   */\n  Grid.prototype.registerRowsProcessor = function registerRowsProcessor(processor) {\n    if (!angular.isFunction(processor)) {\n      throw 'Attempt to register non-function rows processor: ' + processor;\n    }\n\n    this.rowsProcessors.push(processor);\n  };\n\n  /**\n   * @ngdoc function\n   * @name removeRowsProcessor\n   * @methodOf ui.grid.class:Grid\n   * @param {function(renderableRows)} rows processor function\n   * @description Remove a registered rows processor\n   */\n  Grid.prototype.removeRowsProcessor = function removeRowsProcessor(processor) {\n    var idx = this.rowsProcessors.indexOf(processor);\n\n    if (typeof(idx) !== 'undefined' && idx !== undefined) {\n      this.rowsProcessors.splice(idx, 1);\n    }\n  };\n  \n  /**\n   * Private Undocumented Method\n   * @name processRowsProcessors\n   * @methodOf ui.grid.class:Grid\n   * @param {Array[GridRow]} The array of \"renderable\" rows\n   * @param {Array[GridColumn]} The array of columns\n   * @description Run all the registered rows processors on the array of renderable rows\n   */\n  Grid.prototype.processRowsProcessors = function processRowsProcessors(renderableRows) {\n    var self = this;\n\n    // Create a shallow copy of the rows so that we can safely sort them without altering the original grid.rows sort order\n    var myRenderableRows = renderableRows.slice(0);\n    \n    // self.rowsProcessors.forEach(function (processor) {\n    //   myRenderableRows = processor.call(self, myRenderableRows, self.columns);\n\n    //   if (!renderableRows) {\n    //     throw \"Processor at index \" + i + \" did not return a set of renderable rows\";\n    //   }\n\n    //   if (!angular.isArray(renderableRows)) {\n    //     throw \"Processor at index \" + i + \" did not return an array\";\n    //   }\n\n    //   i++;\n    // });\n\n    // Return myRenderableRows with no processing if we have no rows processors \n    if (self.rowsProcessors.length === 0) {\n      return $q.when(myRenderableRows);\n    }\n  \n    // Counter for iterating through rows processors\n    var i = 0;\n    \n    // Promise for when we're done with all the processors\n    var finished = $q.defer();\n\n    // This function will call the processor in self.rowsProcessors at index 'i', and then\n    //   when done will call the next processor in the list, using the output from the processor\n    //   at i as the argument for 'renderedRowsToProcess' on the next iteration.\n    //  \n    //   If we're at the end of the list of processors, we resolve our 'finished' callback with\n    //   the result.\n    function startProcessor(i, renderedRowsToProcess) {\n      // Get the processor at 'i'\n      var processor = self.rowsProcessors[i];\n\n      // Call the processor, passing in the rows to process and the current columns\n      //   (note: it's wrapped in $q.when() in case the processor does not return a promise)\n      return $q.when( processor.call(self, renderedRowsToProcess, self.columns) )\n        .then(function handleProcessedRows(processedRows) {\n          // Check for errors\n          if (!processedRows) {\n            throw \"Processor at index \" + i + \" did not return a set of renderable rows\";\n          }\n\n          if (!angular.isArray(processedRows)) {\n            throw \"Processor at index \" + i + \" did not return an array\";\n          }\n\n          // Processor is done, increment the counter\n          i++;\n\n          // If we're not done with the processors, call the next one\n          if (i <= self.rowsProcessors.length - 1) {\n            return startProcessor(i, processedRows);\n          }\n          // We're done! Resolve the 'finished' promise\n          else {\n            finished.resolve(processedRows);\n          }\n        });\n    }\n\n    // Start on the first processor\n    startProcessor(0, myRenderableRows);\n    \n    return finished.promise;\n  };\n\n  Grid.prototype.setVisibleRows = function setVisibleRows(rows) {\n    // gridUtil.logDebug('setVisibleRows');\n\n    var self = this;\n\n    //var newVisibleRowCache = [];\n\n    // Reset all the render container row caches\n    for (var i in self.renderContainers) {\n      var container = self.renderContainers[i];\n\n      container.canvasHeightShouldUpdate = true;\n      \n      if ( typeof(container.visibleRowCache) === 'undefined' ){\n        container.visibleRowCache = [];  \n      } else {\n        container.visibleRowCache.length = 0;  \n      }\n    }\n    \n    // rows.forEach(function (row) {\n    for (var ri = 0; ri < rows.length; ri++) {\n      var row = rows[ri];\n\n      // If the row is visible\n      if (row.visible) {\n        // newVisibleRowCache.push(row);\n\n        // If the row has a container specified\n        if (typeof(row.renderContainer) !== 'undefined' && row.renderContainer) {\n          self.renderContainers[row.renderContainer].visibleRowCache.push(row);\n        }\n        // If not, put it into the body container\n        else {\n          self.renderContainers.body.visibleRowCache.push(row);\n        }\n      }\n    }\n    self.api.core.raise.rowsRendered(this.api);\n  };\n\n  /**\n   * @ngdoc function\n   * @name registerColumnsProcessor\n   * @methodOf ui.grid.class:Grid\n   * @param {function(renderableColumns)} rows processor function\n   * @returns {Array[GridColumn]} Updated renderable columns\n   * @description\n\n     Register a \"columns processor\" function. When the columns are updated,\n     the grid calls each registered \"columns processor\", which has a chance\n     to alter the set of columns, as long as the count is not modified.\n   */\n  Grid.prototype.registerColumnsProcessor = function registerColumnsProcessor(processor) {\n    if (!angular.isFunction(processor)) {\n      throw 'Attempt to register non-function rows processor: ' + processor;\n    }\n\n    this.columnsProcessors.push(processor);\n  };\n\n  Grid.prototype.removeColumnsProcessor = function removeColumnsProcessor(processor) {\n    var idx = this.columnsProcessors.indexOf(processor);\n\n    if (typeof(idx) !== 'undefined' && idx !== undefined) {\n      this.columnsProcessors.splice(idx, 1);\n    }\n  };\n\n  Grid.prototype.processColumnsProcessors = function processColumnsProcessors(renderableColumns) {\n    var self = this;\n\n    // Create a shallow copy of the rows so that we can safely sort them without altering the original grid.rows sort order\n    var myRenderableColumns = renderableColumns.slice(0);\n\n    // Return myRenderableRows with no processing if we have no rows processors \n    if (self.columnsProcessors.length === 0) {\n      return $q.when(myRenderableColumns);\n    }\n  \n    // Counter for iterating through rows processors\n    var i = 0;\n    \n    // Promise for when we're done with all the processors\n    var finished = $q.defer();\n\n    // This function will call the processor in self.rowsProcessors at index 'i', and then\n    //   when done will call the next processor in the list, using the output from the processor\n    //   at i as the argument for 'renderedRowsToProcess' on the next iteration.\n    //  \n    //   If we're at the end of the list of processors, we resolve our 'finished' callback with\n    //   the result.\n    function startProcessor(i, renderedColumnsToProcess) {\n      // Get the processor at 'i'\n      var processor = self.columnsProcessors[i];\n\n      // Call the processor, passing in the rows to process and the current columns\n      //   (note: it's wrapped in $q.when() in case the processor does not return a promise)\n      return $q.when( processor.call(self, renderedColumnsToProcess, self.rows) )\n        .then(function handleProcessedRows(processedColumns) {\n          // Check for errors\n          if (!processedColumns) {\n            throw \"Processor at index \" + i + \" did not return a set of renderable rows\";\n          }\n\n          if (!angular.isArray(processedColumns)) {\n            throw \"Processor at index \" + i + \" did not return an array\";\n          }\n\n          // Processor is done, increment the counter\n          i++;\n\n          // If we're not done with the processors, call the next one\n          if (i <= self.columnsProcessors.length - 1) {\n            return startProcessor(i, myRenderableColumns);\n          }\n          // We're done! Resolve the 'finished' promise\n          else {\n            finished.resolve(myRenderableColumns);\n          }\n        });\n    }\n\n    // Start on the first processor\n    startProcessor(0, myRenderableColumns);\n    \n    return finished.promise;\n  };\n\n  Grid.prototype.setVisibleColumns = function setVisibleColumns(columns) {\n    // gridUtil.logDebug('setVisibleColumns');\n\n    var self = this;\n\n    // Reset all the render container row caches\n    for (var i in self.renderContainers) {\n      var container = self.renderContainers[i];\n\n      container.visibleColumnCache.length = 0;\n    }\n\n    for (var ci = 0; ci < columns.length; ci++) {\n      var column = columns[ci];\n\n      // If the column is visible\n      if (column.visible) {\n        // If the column has a container specified\n        if (typeof(column.renderContainer) !== 'undefined' && column.renderContainer) {\n          self.renderContainers[column.renderContainer].visibleColumnCache.push(column);\n        }\n        // If not, put it into the body container\n        else {\n          self.renderContainers.body.visibleColumnCache.push(column);\n        }\n      }\n    }\n  };\n\n  /**\n   * @ngdoc function\n   * @name handleWindowResize\n   * @methodOf ui.grid.class:Grid\n   * @description Triggered when the browser window resizes; automatically resizes the grid\n   */\n  Grid.prototype.handleWindowResize = function handleWindowResize($event) {\n    var self = this;\n\n    self.gridWidth = gridUtil.elementWidth(self.element);\n    self.gridHeight = gridUtil.elementHeight(self.element);\n\n    self.queueRefresh();\n  };\n\n  /**\n   * @ngdoc function\n   * @name queueRefresh\n   * @methodOf ui.grid.class:Grid\n   * @description todo: @c0bra can you document this method?\n   */\n  Grid.prototype.queueRefresh = function queueRefresh() {\n    var self = this;\n\n    if (self.refreshCanceller) {\n      $timeout.cancel(self.refreshCanceller);\n    }\n\n    self.refreshCanceller = $timeout(function () {\n      self.refreshCanvas(true);\n    });\n\n    self.refreshCanceller.then(function () {\n      self.refreshCanceller = null;\n    });\n\n    return self.refreshCanceller;\n  };\n\n  /**\n   * @ngdoc function\n   * @name updateCanvasHeight\n   * @methodOf ui.grid.class:Grid\n   * @description flags all render containers to update their canvas height\n   */\n  Grid.prototype.updateCanvasHeight = function updateCanvasHeight() {\n    var self = this;\n\n    for (var containerId in self.renderContainers) {\n      if (self.renderContainers.hasOwnProperty(containerId)) {\n        var container = self.renderContainers[containerId];\n        container.canvasHeightShouldUpdate = true;\n      }\n    }\n  };\n\n  /**\n   * @ngdoc function\n   * @name buildStyles\n   * @methodOf ui.grid.class:Grid\n   * @description calls each styleComputation function\n   */\n  // TODO: this used to take $scope, but couldn't see that it was used\n  Grid.prototype.buildStyles = function buildStyles() {\n    // gridUtil.logDebug('buildStyles');\n\n    var self = this;\n    \n    self.customStyles = '';\n\n    self.styleComputations\n      .sort(function(a, b) {\n        if (a.priority === null) { return 1; }\n        if (b.priority === null) { return -1; }\n        if (a.priority === null && b.priority === null) { return 0; }\n        return a.priority - b.priority;\n      })\n      .forEach(function (compInfo) {\n        // this used to provide $scope as a second parameter, but I couldn't find any \n        // style builders that used it, so removed it as part of moving to grid from controller\n        var ret = compInfo.func.call(self);\n\n        if (angular.isString(ret)) {\n          self.customStyles += '\\n' + ret;\n        }\n      });\n  };\n\n\n  Grid.prototype.minColumnsToRender = function minColumnsToRender() {\n    var self = this;\n    var viewport = this.getViewportWidth();\n\n    var min = 0;\n    var totalWidth = 0;\n    self.columns.forEach(function(col, i) {\n      if (totalWidth < viewport) {\n        totalWidth += col.drawnWidth;\n        min++;\n      }\n      else {\n        var currWidth = 0;\n        for (var j = i; j >= i - min; j--) {\n          currWidth += self.columns[j].drawnWidth;\n        }\n        if (currWidth < viewport) {\n          min++;\n        }\n      }\n    });\n\n    return min;\n  };\n\n  Grid.prototype.getBodyHeight = function getBodyHeight() {\n    // Start with the viewportHeight\n    var bodyHeight = this.getViewportHeight();\n\n    // Add the horizontal scrollbar height if there is one\n    //if (typeof(this.horizontalScrollbarHeight) !== 'undefined' && this.horizontalScrollbarHeight !== undefined && this.horizontalScrollbarHeight > 0) {\n    //  bodyHeight = bodyHeight + this.horizontalScrollbarHeight;\n    //}\n\n    return bodyHeight;\n  };\n\n  // NOTE: viewport drawable height is the height of the grid minus the header row height (including any border)\n  // TODO(c0bra): account for footer height\n  Grid.prototype.getViewportHeight = function getViewportHeight() {\n    var self = this;\n\n    var viewPortHeight = this.gridHeight - this.headerHeight - this.footerHeight;\n\n    // Account for native horizontal scrollbar, if present\n    //if (typeof(this.horizontalScrollbarHeight) !== 'undefined' && this.horizontalScrollbarHeight !== undefined && this.horizontalScrollbarHeight > 0) {\n    //  viewPortHeight = viewPortHeight - this.horizontalScrollbarHeight;\n    //}\n\n    var adjustment = self.getViewportAdjustment();\n    \n    viewPortHeight = viewPortHeight + adjustment.height;\n\n    //gridUtil.logDebug('viewPortHeight', viewPortHeight);\n\n    return viewPortHeight;\n  };\n\n  Grid.prototype.getViewportWidth = function getViewportWidth() {\n    var self = this;\n\n    var viewPortWidth = this.gridWidth;\n\n    //if (typeof(this.verticalScrollbarWidth) !== 'undefined' && this.verticalScrollbarWidth !== undefined && this.verticalScrollbarWidth > 0) {\n    //  viewPortWidth = viewPortWidth - this.verticalScrollbarWidth;\n    //}\n\n    var adjustment = self.getViewportAdjustment();\n    \n    viewPortWidth = viewPortWidth + adjustment.width;\n\n    //gridUtil.logDebug('getviewPortWidth', viewPortWidth);\n\n    return viewPortWidth;\n  };\n\n  Grid.prototype.getHeaderViewportWidth = function getHeaderViewportWidth() {\n    var viewPortWidth = this.getViewportWidth();\n\n    //if (typeof(this.verticalScrollbarWidth) !== 'undefined' && this.verticalScrollbarWidth !== undefined && this.verticalScrollbarWidth > 0) {\n    //  viewPortWidth = viewPortWidth + this.verticalScrollbarWidth;\n    //}\n\n    return viewPortWidth;\n  };\n\n  Grid.prototype.registerViewportAdjuster = function registerViewportAdjuster(func) {\n    this.viewportAdjusters.push(func);\n  };\n\n  Grid.prototype.removeViewportAdjuster = function registerViewportAdjuster(func) {\n    var idx = this.viewportAdjusters.indexOf(func);\n\n    if (typeof(idx) !== 'undefined' && idx !== undefined) {\n      this.viewportAdjusters.splice(idx, 1);\n    }\n  };\n\n  Grid.prototype.getViewportAdjustment = function getViewportAdjustment() {\n    var self = this;\n\n    var adjustment = { height: 0, width: 0 };\n\n    self.viewportAdjusters.forEach(function (func) {\n      adjustment = func.call(this, adjustment);\n    });\n\n    return adjustment;\n  };\n\n  Grid.prototype.getVisibleRowCount = function getVisibleRowCount() {\n    // var count = 0;\n\n    // this.rows.forEach(function (row) {\n    //   if (row.visible) {\n    //     count++;\n    //   }\n    // });\n\n    // return this.visibleRowCache.length;\n    return this.renderContainers.body.visibleRowCache.length;\n  };\n\n   Grid.prototype.getVisibleRows = function getVisibleRows() {\n    return this.renderContainers.body.visibleRowCache;\n   };\n\n  Grid.prototype.getVisibleColumnCount = function getVisibleColumnCount() {\n    // var count = 0;\n\n    // this.rows.forEach(function (row) {\n    //   if (row.visible) {\n    //     count++;\n    //   }\n    // });\n\n    // return this.visibleRowCache.length;\n    return this.renderContainers.body.visibleColumnCache.length;\n  };\n\n\n  Grid.prototype.searchRows = function searchRows(renderableRows) {\n    return rowSearcher.search(this, renderableRows, this.columns);\n  };\n\n  Grid.prototype.sortByColumn = function sortByColumn(renderableRows) {\n    return rowSorter.sort(this, renderableRows, this.columns);\n  };\n\n  /**\n   * @ngdoc function\n   * @name getCellValue\n   * @methodOf ui.grid.class:Grid\n   * @description Gets the value of a cell for a particular row and column\n   * @param {GridRow} row Row to access\n   * @param {GridColumn} col Column to access\n   */\n  Grid.prototype.getCellValue = function getCellValue(row, col){\n    var self = this;\n\n    if (!self.cellValueGetterCache[col.colDef.name]) {\n      self.cellValueGetterCache[col.colDef.name] = $parse(row.getEntityQualifiedColField(col));\n    }\n\n    return self.cellValueGetterCache[col.colDef.name](row);\n  };\n\n  \n  Grid.prototype.getNextColumnSortPriority = function getNextColumnSortPriority() {\n    var self = this,\n        p = 0;\n\n    self.columns.forEach(function (col) {\n      if (col.sort && col.sort.priority && col.sort.priority > p) {\n        p = col.sort.priority;\n      }\n    });\n\n    return p + 1;\n  };\n\n  /**\n   * @ngdoc function\n   * @name resetColumnSorting\n   * @methodOf ui.grid.class:Grid\n   * @description Return the columns that the grid is currently being sorted by\n   * @param {GridColumn} [excludedColumn] Optional GridColumn to exclude from having its sorting reset\n   */\n  Grid.prototype.resetColumnSorting = function resetColumnSorting(excludeCol) {\n    var self = this;\n\n    self.columns.forEach(function (col) {\n      if (col !== excludeCol && !col.colDef.suppressRemoveSort) {\n        col.sort = {};\n      }\n    });\n  };\n\n  /**\n   * @ngdoc function\n   * @name getColumnSorting\n   * @methodOf ui.grid.class:Grid\n   * @description Return the columns that the grid is currently being sorted by\n   * @returns {Array[GridColumn]} An array of GridColumn objects\n   */\n  Grid.prototype.getColumnSorting = function getColumnSorting() {\n    var self = this;\n\n    var sortedCols = [], myCols;\n\n    // Iterate through all the columns, sorted by priority\n    // Make local copy of column list, because sorting is in-place and we do not want to\n    // change the original sequence of columns\n    myCols = self.columns.slice(0);\n    myCols.sort(rowSorter.prioritySort).forEach(function (col) {\n      if (col.sort && typeof(col.sort.direction) !== 'undefined' && col.sort.direction && (col.sort.direction === uiGridConstants.ASC || col.sort.direction === uiGridConstants.DESC)) {\n        sortedCols.push(col);\n      }\n    });\n\n    return sortedCols;\n  };\n\n  /**\n   * @ngdoc function\n   * @name sortColumn\n   * @methodOf ui.grid.class:Grid\n   * @description Set the sorting on a given column, optionally resetting any existing sorting on the Grid.\n   * Emits the sortChanged event whenever the sort criteria are changed.\n   * @param {GridColumn} column Column to set the sorting on\n   * @param {uiGridConstants.ASC|uiGridConstants.DESC} [direction] Direction to sort by, either descending or ascending.\n   *   If not provided, the column will iterate through the sort directions: ascending, descending, unsorted.\n   * @param {boolean} [add] Add this column to the sorting. If not provided or set to `false`, the Grid will reset any existing sorting and sort\n   *   by this column only\n   * @returns {Promise} A resolved promise that supplies the column.\n   */\n  \n  Grid.prototype.sortColumn = function sortColumn(column, directionOrAdd, add) {\n    var self = this,\n        direction = null;\n\n    if (typeof(column) === 'undefined' || !column) {\n      throw new Error('No column parameter provided');\n    }\n\n    // Second argument can either be a direction or whether to add this column to the existing sort.\n    //   If it's a boolean, it's an add, otherwise, it's a direction\n    if (typeof(directionOrAdd) === 'boolean') {\n      add = directionOrAdd;\n    }\n    else {\n      direction = directionOrAdd;\n    }\n    \n    if (!add) {\n      self.resetColumnSorting(column);\n      column.sort.priority = 0;\n    }\n    else {\n      column.sort.priority = self.getNextColumnSortPriority();\n    }\n\n    if (!direction) {\n      // Figure out the sort direction\n      if (column.sort.direction && column.sort.direction === uiGridConstants.ASC) {\n        column.sort.direction = uiGridConstants.DESC;\n      }\n      else if (column.sort.direction && column.sort.direction === uiGridConstants.DESC) {\n        if ( column.colDef && column.colDef.suppressRemoveSort ){\n          column.sort.direction = uiGridConstants.ASC;\n        } else {\n          column.sort.direction = null;\n        }\n      }\n      else {\n        column.sort.direction = uiGridConstants.ASC;\n      }\n    }\n    else {\n      column.sort.direction = direction;\n    }\n    \n    self.api.core.raise.sortChanged( self, self.getColumnSorting() );\n\n    return $q.when(column);\n  };\n  \n  /**\n   * communicate to outside world that we are done with initial rendering\n   */\n  Grid.prototype.renderingComplete = function(){\n    if (angular.isFunction(this.options.onRegisterApi)) {\n      this.options.onRegisterApi(this.api);\n    }\n    this.api.core.raise.renderingComplete( this.api );\n  };\n\n  Grid.prototype.createRowHashMap = function createRowHashMap() {\n    var self = this;\n\n    var hashMap = new RowHashMap();\n    hashMap.grid = self;\n\n    self.rowHashMap = hashMap;\n  };\n  \n  \n  /**\n   * @ngdoc function\n   * @name refresh\n   * @methodOf ui.grid.class:Grid\n   * @description Refresh the rendered grid on screen.\n   * \n   */\n  Grid.prototype.refresh = function refresh() {\n    // gridUtil.logDebug('grid refresh');\n    \n    var self = this;\n    \n    var p1 = self.processRowsProcessors(self.rows).then(function (renderableRows) {\n      self.setVisibleRows(renderableRows);\n    });\n\n    var p2 = self.processColumnsProcessors(self.columns).then(function (renderableColumns) {\n      self.setVisibleColumns(renderableColumns);\n    });\n\n    return $q.all([p1, p2]).then(function () {\n      self.redrawInPlace();\n\n      self.refreshCanvas(true);\n    });\n  };  \n  \n  /**\n   * @ngdoc function\n   * @name refreshRows\n   * @methodOf ui.grid.class:Grid\n   * @description Refresh the rendered rows on screen?  Note: not functional at present \n   * @returns {promise} promise that is resolved when render completes?\n   * \n   */\n  Grid.prototype.refreshRows = function refreshRows() {\n    var self = this;\n    \n    return self.processRowsProcessors(self.rows)\n      .then(function (renderableRows) {\n        self.setVisibleRows(renderableRows);\n\n        self.redrawInPlace();\n\n        self.refreshCanvas( true );\n      });\n  };\n\n  /**\n   * @ngdoc function\n   * @name redrawCanvas\n   * @methodOf ui.grid.class:Grid\n   * @description TBD\n   * @params {object} buildStyles optional parameter.  Use TBD\n   * @returns {promise} promise that is resolved when the canvas\n   * has been refreshed\n   * \n   */\n  Grid.prototype.refreshCanvas = function(buildStyles) {\n    var self = this;\n\n    if (buildStyles) {\n      self.buildStyles();\n    }\n\n    var p = $q.defer();\n\n    // Get all the header heights\n    var containerHeadersToRecalc = [];\n    for (var containerId in self.renderContainers) {\n      if (self.renderContainers.hasOwnProperty(containerId)) {\n        var container = self.renderContainers[containerId];\n\n        // Skip containers that have no canvasWidth set yet\n        if (container.canvasWidth === null || isNaN(container.canvasWidth)) {\n          continue;\n        }\n\n        if (container.header) {\n          containerHeadersToRecalc.push(container);\n        }\n      }\n    }\n\n    if (containerHeadersToRecalc.length > 0) {\n      // Putting in a timeout as it's not calculating after the grid element is rendered and filled out\n      $timeout(function() {\n        // var oldHeaderHeight = self.grid.headerHeight;\n        // self.grid.headerHeight = gridUtil.outerElementHeight(self.header);\n\n        var rebuildStyles = false;\n\n        // Get all the header heights\n        var maxHeight = 0;\n        var i, container;\n        for (i = 0; i < containerHeadersToRecalc.length; i++) {\n          container = containerHeadersToRecalc[i];\n\n          // Skip containers that have no canvasWidth set yet\n          if (container.canvasWidth === null || isNaN(container.canvasWidth)) {\n            continue;\n          }\n\n          if (container.header) {\n            var oldHeaderHeight = container.headerHeight;\n            var headerHeight = gridUtil.outerElementHeight(container.header);\n\n            container.headerHeight = parseInt(headerHeight, 10);\n\n            if (oldHeaderHeight !== headerHeight) {\n              rebuildStyles = true;\n            }\n\n            // Get the \"inner\" header height, that is the height minus the top and bottom borders, if present. We'll use it to make sure all the headers have a consistent height\n            var topBorder = gridUtil.getBorderSize(container.header, 'top');\n            var bottomBorder = gridUtil.getBorderSize(container.header, 'bottom');\n            var innerHeaderHeight = parseInt(headerHeight - topBorder - bottomBorder, 10);\n\n            innerHeaderHeight  = innerHeaderHeight < 0 ? 0 : innerHeaderHeight;\n\n            container.innerHeaderHeight = innerHeaderHeight;\n\n            // Save the largest header height for use later\n            if (innerHeaderHeight > maxHeight) {\n              maxHeight = innerHeaderHeight;\n            }\n          }\n        }\n\n        // Go through all the headers\n        for (i = 0; i < containerHeadersToRecalc.length; i++) {\n          container = containerHeadersToRecalc[i];\n\n          // If this header's height is less than another header's height, then explicitly set it so they're the same and one isn't all offset and weird looking\n          if (container.headerHeight < maxHeight) {\n            container.explicitHeaderHeight = maxHeight;\n          }\n        }\n\n        // Rebuild styles if the header height has changed\n        //   The header height is used in body/viewport calculations and those are then used in other styles so we need it to be available\n        if (buildStyles && rebuildStyles) {\n          self.buildStyles();\n        }\n\n        p.resolve();\n      });\n    }\n    else {\n      // Timeout still needs to be here to trigger digest after styles have been rebuilt\n      $timeout(function() {\n        p.resolve();\n      });\n    }\n\n    return p.promise;\n  };\n\n\n  /**\n   * @ngdoc function\n   * @name redrawCanvas\n   * @methodOf ui.grid.class:Grid\n   * @description Redraw the rows and columns based on our current scroll position\n   * \n   */\n  Grid.prototype.redrawInPlace = function redrawInPlace() {\n    // gridUtil.logDebug('redrawInPlace');\n    \n    var self = this;\n\n    for (var i in self.renderContainers) {\n      var container = self.renderContainers[i];\n\n      // gridUtil.logDebug('redrawing container', i);\n\n      container.adjustRows(null, container.prevScrolltopPercentage, true);\n      container.adjustColumns(null, container.prevScrollleftPercentage);\n    }\n  };\n\n    /**\n     * @ngdoc function\n     * @name hasLeftContainerColumns\n     * @methodOf ui.grid.class:Grid\n     * @description returns true if leftContainer has columns\n     */\n    Grid.prototype.hasLeftContainerColumns = function () {\n      return this.hasLeftContainer() && this.renderContainers.left.renderedColumns.length > 0;\n    };\n\n    /**\n     * @ngdoc function\n     * @name hasRightContainerColumns\n     * @methodOf ui.grid.class:Grid\n     * @description returns true if rightContainer has columns\n     */\n    Grid.prototype.hasRightContainerColumns = function () {\n      return this.hasRightContainer() && this.renderContainers.right.renderedColumns.length > 0;\n    };\n\n\n\n\n  // Blatantly stolen from Angular as it isn't exposed (yet? 2.0?)\n  function RowHashMap() {}\n\n  RowHashMap.prototype = {\n    /**\n     * Store key value pair\n     * @param key key to store can be any type\n     * @param value value to store can be any type\n     */\n    put: function(key, value) {\n      this[this.grid.options.rowIdentity(key)] = value;\n    },\n\n    /**\n     * @param key\n     * @returns {Object} the value for the key\n     */\n    get: function(key) {\n      return this[this.grid.options.rowIdentity(key)];\n    },\n\n    /**\n     * Remove the key/value pair\n     * @param key\n     */\n    remove: function(key) {\n      var value = this[key = this.grid.options.rowIdentity(key)];\n      delete this[key];\n      return value;\n    }\n  };\n\n\n\n  return Grid;\n\n}]);\n\n})();\n\n(function () {\n\n  angular.module('ui.grid')\n    .factory('GridApi', ['$q', '$rootScope', 'gridUtil', 'uiGridConstants', 'GridRow', 'uiGridGridMenuService',\n      function ($q, $rootScope, gridUtil, uiGridConstants, GridRow, uiGridGridMenuService) {\n        /**\n         * @ngdoc function\n         * @name ui.grid.class:GridApi\n         * @description GridApi provides the ability to register public methods events inside the grid and allow\n         * for other components to use the api via featureName.raise.methodName and featureName.on.eventName(function(args){}.\n         * <br/>\n         * To listen to events, you must add a callback to gridOptions.onRegisterApi\n         * <pre>\n         *   $scope.gridOptions.onRegisterApi = function(gridApi){\n         *      gridApi.cellNav.on.navigate($scope,function(newRowCol, oldRowCol){\n         *          $log.log('navigation event');\n         *      });\n         *   };\n         * </pre>\n         * @param {object} grid grid that owns api\n         */\n        var GridApi = function GridApi(grid) {\n          this.grid = grid;\n          this.listeners = [];\n          \n          /**\n           * @ngdoc function\n           * @name renderingComplete\n           * @methodOf  ui.grid.core.api:PublicApi\n           * @description Rendering is complete, called at the same\n           * time as `onRegisterApi`, but provides a way to obtain\n           * that same event within features without stopping end\n           * users from getting at the onRegisterApi method.\n           * \n           * Included in gridApi so that it's always there - otherwise\n           * there is still a timing problem with when a feature can\n           * call this. \n           * \n           * @param {GridApi} gridApi the grid api, as normally \n           * returned in the onRegisterApi method\n           * \n           * @example\n           * <pre>\n           *      gridApi.core.on.renderingComplete( grid );\n           * </pre>\n           */\n          this.registerEvent( 'core', 'renderingComplete' );\n\n          /**\n           * @ngdoc event\n           * @name filterChanged\n           * @eventOf  ui.grid.core.api:PublicApi\n           * @description  is raised after the filter is changed.  The nature\n           * of the watch expression doesn't allow notification of what changed,\n           * so the receiver of this event will need to re-extract the filter \n           * conditions from the columns.\n           * \n           */\n          this.registerEvent( 'core', 'filterChanged' );\n\n          /**\n           * @ngdoc function\n           * @name setRowInvisible\n           * @methodOf  ui.grid.core.api:PublicApi\n           * @description Sets an override on the row to make it always invisible,\n           * which will override any filtering or other visibility calculations.  \n           * If the row is currently visible then sets it to invisible and calls\n           * both grid refresh and emits the rowsVisibleChanged event\n           * @param {object} rowEntity gridOptions.data[] array instance\n           */\n          this.registerMethod( 'core', 'setRowInvisible', GridRow.prototype.setRowInvisible );\n      \n          /**\n           * @ngdoc function\n           * @name clearRowInvisible\n           * @methodOf  ui.grid.core.api:PublicApi\n           * @description Clears any override on visibility for the row so that it returns to \n           * using normal filtering and other visibility calculations.  \n           * If the row is currently invisible then sets it to visible and calls\n           * both grid refresh and emits the rowsVisibleChanged event\n           * TODO: if a filter is active then we can't just set it to visible?\n           * @param {object} rowEntity gridOptions.data[] array instance\n           */\n          this.registerMethod( 'core', 'clearRowInvisible', GridRow.prototype.clearRowInvisible );\n      \n          /**\n           * @ngdoc function\n           * @name getVisibleRows\n           * @methodOf  ui.grid.core.api:PublicApi\n           * @description Returns all visible rows\n           * @param {Grid} grid the grid you want to get visible rows from\n           * @returns {array} an array of gridRow\n           */\n          this.registerMethod( 'core', 'getVisibleRows', this.grid.getVisibleRows );\n          \n          /**\n           * @ngdoc event\n           * @name rowsVisibleChanged\n           * @eventOf  ui.grid.core.api:PublicApi\n           * @description  is raised after the rows that are visible\n           * change.  The filtering is zero-based, so it isn't possible\n           * to say which rows changed (unlike in the selection feature).\n           * We can plausibly know which row was changed when setRowInvisible\n           * is called, but in that situation the user already knows which row\n           * they changed.  When a filter runs we don't know what changed,\n           * and that is the one that would have been useful.\n           *\n           */\n          this.registerEvent( 'core', 'rowsVisibleChanged' );\n\n          /**\n           * @ngdoc event\n           * @name rowsRendered\n           * @eventOf  ui.grid.core.api:PublicApi\n           * @description  is raised after the cache of visible rows is changed.\n           */\n          this.registerEvent( 'core', 'rowsRendered' );\n\n\n          /**\n           * @ngdoc event\n           * @name scrollEvent\n           * @eventOf  ui.grid.core.api:PublicApi\n           * @description  is raised on a scroll Event.  Called frequently so be careful what you do with it\n           */\n          this.registerEvent( 'core', 'scrollEvent' );\n\n          /**\n           * @ngdoc event\n           * @name canvasHeightChanged\n           * @eventOf  ui.grid.core.api:PublicApi\n           * @description  is raised when the canvas height has changed\n           * <br/>\n           * arguments: oldHeight, newHeight\n           */\n          this.registerEvent( 'core', 'canvasHeightChanged');\n        };\n\n        /**\n         * @ngdoc function\n         * @name ui.grid.class:suppressEvents\n         * @methodOf ui.grid.class:GridApi\n         * @description Used to execute a function while disabling the specified event listeners.\n         * Disables the listenerFunctions, executes the callbackFn, and then enables\n         * the listenerFunctions again\n         * @param {object} listenerFuncs listenerFunc or array of listenerFuncs to suppress. These must be the same\n         * functions that were used in the .on.eventName method\n         * @param {object} callBackFn function to execute\n         * @example\n         * <pre>\n         *    var navigate = function (newRowCol, oldRowCol){\n         *       //do something on navigate\n         *    }\n         *\n         *    gridApi.cellNav.on.navigate(scope,navigate);\n         *\n         *\n         *    //call the scrollTo event and suppress our navigate listener\n         *    //scrollTo will still raise the event for other listeners\n         *    gridApi.suppressEvents(navigate, function(){\n         *       gridApi.cellNav.scrollTo(aRow, aCol);\n         *    });\n         *\n         * </pre>\n         */\n        GridApi.prototype.suppressEvents = function (listenerFuncs, callBackFn) {\n          var self = this;\n          var listeners = angular.isArray(listenerFuncs) ? listenerFuncs : [listenerFuncs];\n\n          //find all registered listeners\n          var foundListeners = [];\n          listeners.forEach(function (l) {\n            foundListeners = self.listeners.filter(function (lstnr) {\n              return l === lstnr.handler;\n            });\n          });\n\n          //deregister all the listeners\n          foundListeners.forEach(function(l){\n            l.dereg();\n          });\n\n          callBackFn();\n\n          //reregister all the listeners\n          foundListeners.forEach(function(l){\n              l.dereg = registerEventWithAngular(l.eventId, l.handler, self.grid, l._this);\n          });\n\n        };\n\n        /**\n         * @ngdoc function\n         * @name registerEvent\n         * @methodOf ui.grid.class:GridApi\n         * @description Registers a new event for the given feature.  The event will get a\n         * .raise and .on prepended to it\n         * <br>\n         * .raise.eventName() - takes no arguments\n         * <br/>\n         * <br/>\n         * .on.eventName(scope, callBackFn, _this)\n         * <br/>\n         * scope - a scope reference to add a deregister call to the scopes .$on('destroy')\n         * <br/>\n         * callBackFn - The function to call\n         * <br/>\n         * _this - optional this context variable for callbackFn. If omitted, grid.api will be used for the context\n         * <br/>\n         * .on.eventName returns a dereg funtion that will remove the listener.  It's not necessary to use it as the listener\n         * will be removed when the scope is destroyed.\n         * @param {string} featureName name of the feature that raises the event\n         * @param {string} eventName  name of the event\n         */\n        GridApi.prototype.registerEvent = function (featureName, eventName) {\n          var self = this;\n          if (!self[featureName]) {\n            self[featureName] = {};\n          }\n\n          var feature = self[featureName];\n          if (!feature.on) {\n            feature.on = {};\n            feature.raise = {};\n          }\n\n          var eventId = self.grid.id + featureName + eventName;\n\n          // gridUtil.logDebug('Creating raise event method ' + featureName + '.raise.' + eventName);\n          feature.raise[eventName] = function () {\n            $rootScope.$emit.apply($rootScope, [eventId].concat(Array.prototype.slice.call(arguments)));\n          };\n\n          // gridUtil.logDebug('Creating on event method ' + featureName + '.on.' + eventName);\n          feature.on[eventName] = function (scope, handler, _this) {\n            var deregAngularOn = registerEventWithAngular(eventId, handler, self.grid, _this);\n\n            //track our listener so we can turn off and on\n            var listener = {handler: handler, dereg: deregAngularOn, eventId: eventId, scope: scope, _this:_this};\n            self.listeners.push(listener);\n\n            var removeListener = function(){\n              listener.dereg();\n              var index = self.listeners.indexOf(listener);\n              self.listeners.splice(index,1);\n            };\n\n            //destroy tracking when scope is destroyed\n            scope.$on('$destroy', function() {\n              removeListener();\n            });\n\n            return removeListener;\n          };\n        };\n\n        function registerEventWithAngular(eventId, handler, grid, _this) {\n          return $rootScope.$on(eventId, function (event) {\n            var args = Array.prototype.slice.call(arguments);\n            args.splice(0, 1); //remove evt argument\n            handler.apply(_this ? _this : grid.api, args);\n          });\n        }\n\n        /**\n         * @ngdoc function\n         * @name registerEventsFromObject\n         * @methodOf ui.grid.class:GridApi\n         * @description Registers features and events from a simple objectMap.\n         * eventObjectMap must be in this format (multiple features allowed)\n         * <pre>\n         * {featureName:\n         *        {\n         *          eventNameOne:function(args){},\n         *          eventNameTwo:function(args){}\n         *        }\n         *  }\n         * </pre>\n         * @param {object} eventObjectMap map of feature/event names\n         */\n        GridApi.prototype.registerEventsFromObject = function (eventObjectMap) {\n          var self = this;\n          var features = [];\n          angular.forEach(eventObjectMap, function (featProp, featPropName) {\n            var feature = {name: featPropName, events: []};\n            angular.forEach(featProp, function (prop, propName) {\n              feature.events.push(propName);\n            });\n            features.push(feature);\n          });\n\n          features.forEach(function (feature) {\n            feature.events.forEach(function (event) {\n              self.registerEvent(feature.name, event);\n            });\n          });\n\n        };\n\n        /**\n         * @ngdoc function\n         * @name registerMethod\n         * @methodOf ui.grid.class:GridApi\n         * @description Registers a new event for the given feature\n         * @param {string} featureName name of the feature\n         * @param {string} methodName  name of the method\n         * @param {object} callBackFn function to execute\n         * @param {object} _this binds callBackFn 'this' to _this.  Defaults to gridApi.grid\n         */\n        GridApi.prototype.registerMethod = function (featureName, methodName, callBackFn, _this) {\n          if (!this[featureName]) {\n            this[featureName] = {};\n          }\n\n          var feature = this[featureName];\n\n          feature[methodName] = gridUtil.createBoundedWrapper(_this || this.grid, callBackFn);\n        };\n\n        /**\n         * @ngdoc function\n         * @name registerMethodsFromObject\n         * @methodOf ui.grid.class:GridApi\n         * @description Registers features and methods from a simple objectMap.\n         * eventObjectMap must be in this format (multiple features allowed)\n         * <br>\n         * {featureName:\n         *        {\n         *          methodNameOne:function(args){},\n         *          methodNameTwo:function(args){}\n         *        }\n         * @param {object} eventObjectMap map of feature/event names\n         * @param {object} _this binds this to _this for all functions.  Defaults to gridApi.grid\n         */\n        GridApi.prototype.registerMethodsFromObject = function (methodMap, _this) {\n          var self = this;\n          var features = [];\n          angular.forEach(methodMap, function (featProp, featPropName) {\n            var feature = {name: featPropName, methods: []};\n            angular.forEach(featProp, function (prop, propName) {\n              feature.methods.push({name: propName, fn: prop});\n            });\n            features.push(feature);\n          });\n\n          features.forEach(function (feature) {\n            feature.methods.forEach(function (method) {\n              self.registerMethod(feature.name, method.name, method.fn, _this);\n            });\n          });\n\n        };\n        \n        return GridApi;\n\n      }]);\n\n})();\n\n(function(){\n\nangular.module('ui.grid')\n.factory('GridColumn', ['gridUtil', 'uiGridConstants', 'i18nService', function(gridUtil, uiGridConstants, i18nService) {\n\n  /**\n   * @ngdoc function\n   * @name ui.grid.class:GridColumn\n   * @description Represents the viewModel for each column.  Any state or methods needed for a Grid Column\n   * are defined on this prototype\n   * @param {ColDef} colDef Column definition.\n   * @param {number} index the current position of the column in the array\n   * @param {Grid} grid reference to the grid\n   */\n   \n  /**\n   * ******************************************************************************************\n   * PaulL1: Ugly hack here in documentation.  These properties are clearly properties of GridColumn, \n   * and need to be noted as such for those extending and building ui-grid itself.\n   * However, from an end-developer perspective, they interact with all these through columnDefs,\n   * and they really need to be documented there.  I feel like they're relatively static, and\n   * I can't find an elegant way for ngDoc to reference to both....so I've duplicated each\n   * comment block.  Ugh.\n   * \n   */\n\n  /** \n   * @ngdoc property\n   * @name name\n   * @propertyOf ui.grid.class:GridColumn\n   * @description (mandatory) each column should have a name, although for backward\n   * compatibility with 2.x name can be omitted if field is present\n   *\n   */\n\n  /** \n   * @ngdoc property\n   * @name name\n   * @propertyOf ui.grid.class:GridOptions.columnDef\n   * @description (mandatory) each column should have a name, although for backward\n   * compatibility with 2.x name can be omitted if field is present\n   *\n   */\n    \n  /** \n   * @ngdoc property\n   * @name displayName\n   * @propertyOf ui.grid.class:GridColumn\n   * @description Column name that will be shown in the header.  If displayName is not\n   * provided then one is generated using the name.\n   *\n   */\n\n  /** \n   * @ngdoc property\n   * @name displayName\n   * @propertyOf ui.grid.class:GridOptions.columnDef\n   * @description Column name that will be shown in the header.  If displayName is not\n   * provided then one is generated using the name.\n   *\n   */\n       \n  /** \n   * @ngdoc property\n   * @name field\n   * @propertyOf ui.grid.class:GridColumn\n   * @description field must be provided if you wish to bind to a \n   * property in the data source.  Should be an angular expression that evaluates against grid.options.data \n   * array element.  Can be a complex expression: <code>employee.address.city</code>, or can be a function: <code>employee.getFullAddress()</code>.\n   * See the angular docs on binding expressions.\n   *\n   */\n    \n  /** \n   * @ngdoc property\n   * @name field\n   * @propertyOf ui.grid.class:GridOptions.columnDef\n   * @description field must be provided if you wish to bind to a \n   * property in the data source.  Should be an angular expression that evaluates against grid.options.data \n   * array element.  Can be a complex expression: <code>employee.address.city</code>, or can be a function: <code>employee.getFullAddress()</code>.    * See the angular docs on binding expressions.    *\n   */\n    \n  /** \n   * @ngdoc property\n   * @name filter\n   * @propertyOf ui.grid.class:GridColumn\n   * @description Filter on this column.  \n   * @example\n   * <pre>{ term: 'text', condition: uiGridConstants.filter.STARTS_WITH, placeholder: 'type to filter...', flags: { caseSensitive: false } }</pre>\n   *\n   */\n    \n  /**\n   * @ngdoc method\n   * @methodOf ui.grid.class:GridColumn\n   * @name GridColumn\n   * @description Initializes a gridColumn\n   * @param {ColumnDef} colDef the column def to associate with this column\n   * @param {number} uid the unique and immutable uid we'd like to allocate to this column\n   * @param {Grid} grid the grid we'd like to create this column in\n   */ \n  function GridColumn(colDef, uid, grid) {\n    var self = this;\n\n    self.grid = grid;\n    self.uid = uid;\n\n    self.updateColumnDef(colDef, true);\n  }\n\n\n  /**\n   * @ngdoc method\n   * @methodOf ui.grid.class:GridColumn\n   * @name setPropertyOrDefault\n   * @description Sets a property on the column using the passed in columnDef, and\n   * setting the defaultValue if the value cannot be found on the colDef\n   * @param {ColumnDef} colDef the column def to look in for the property value\n   * @param {string} propName the property name we'd like to set\n   * @param {object} defaultValue the value to use if the colDef doesn't provide the setting\n   */ \n  GridColumn.prototype.setPropertyOrDefault = function (colDef, propName, defaultValue) {\n    var self = this;\n\n    // Use the column definition filter if we were passed it\n    if (typeof(colDef[propName]) !== 'undefined' && colDef[propName]) {\n      self[propName] = colDef[propName];\n    }\n    // Otherwise use our own if it's set\n    else if (typeof(self[propName]) !== 'undefined') {\n      self[propName] = self[propName];\n    }\n    // Default to empty object for the filter\n    else {\n      self[propName] = defaultValue ? defaultValue : {};\n    }\n  };\n\n  \n  \n  /** \n   * @ngdoc property\n   * @name width\n   * @propertyOf ui.grid.class:GridOptions.columnDef\n   * @description sets the column width.  Can be either \n   * a number or a percentage, or an * for auto.\n   * @example\n   * <pre>  $scope.gridOptions.columnDefs = [ { field: 'field1', width: 100},\n   *                                          { field: 'field2', width: '20%'},\n   *                                          { field: 'field3', width: '*' }]; </pre>\n   *\n   */\n\n  /** \n   * @ngdoc property\n   * @name minWidth\n   * @propertyOf ui.grid.class:GridOptions.columnDef\n   * @description sets the minimum column width.  Should be a number.\n   * @example\n   * <pre>  $scope.gridOptions.columnDefs = [ { field: 'field1', minWidth: 100}]; </pre>\n   *\n   */\n\n  /** \n   * @ngdoc property\n   * @name maxWidth\n   * @propertyOf ui.grid.class:GridOptions.columnDef\n   * @description sets the maximum column width.  Should be a number.\n   * @example\n   * <pre>  $scope.gridOptions.columnDefs = [ { field: 'field1', maxWidth: 100}]; </pre>\n   *\n   */\n\n  /** \n   * @ngdoc property\n   * @name visible\n   * @propertyOf ui.grid.class:GridOptions.columnDef\n   * @description sets whether or not the column is visible\n   * </br>Default is true\n   * @example\n   * <pre>  $scope.gridOptions.columnDefs = [ \n   *     { field: 'field1', visible: true},\n   *     { field: 'field2', visible: false }\n   *   ]; </pre>\n   *\n   */\n   \n  /**\n   * @ngdoc property\n   * @name sort\n   * @propertyOf ui.grid.class:GridOptions.columnDef\n   * @description Can be used to set the sort direction for the column, values are\n   * uiGridConstants.ASC or uiGridConstants.DESC\n   * @example\n   * <pre>  $scope.gridOptions.columnDefs = [ { field: 'field1', sort: { direction: uiGridConstants.ASC }}] </pre>\n   */\n  \n\n  /** \n   * @ngdoc property\n   * @name sortingAlgorithm\n   * @propertyOf ui.grid.class:GridColumn\n   * @description Algorithm to use for sorting this column. Takes 'a' and 'b' parameters \n   * like any normal sorting function.\n   *\n   */\n\n  /** \n   * @ngdoc property\n   * @name sortingAlgorithm\n   * @propertyOf ui.grid.class:GridOptions.columnDef\n   * @description Algorithm to use for sorting this column. Takes 'a' and 'b' parameters \n   * like any normal sorting function.\n   *\n   */\n      \n  /** \n   * @ngdoc array\n   * @name filters\n   * @propertyOf ui.grid.class:GridOptions.columnDef\n   * @description Specify multiple filter fields.\n   * @example\n   * <pre>$scope.gridOptions.columnDefs = [ \n   *   {\n   *     field: 'field1', filters: [\n   *       {\n   *         term: 'aa',\n   *         condition: uiGridConstants.filter.STARTS_WITH,\n   *         placeholder: 'starts with...',\n   *         flags: { caseSensitive: false }\n   *       },\n   *       {\n   *         condition: uiGridConstants.filter.ENDS_WITH,\n   *         placeholder: 'ends with...'\n   *       }\n   *     ]\n   *   }\n   * ]; </pre>\n   *\n   * \n   */ \n   \n  /** \n   * @ngdoc array\n   * @name filters\n   * @propertyOf ui.grid.class:GridColumn\n   * @description Filters for this column. Includes 'term' property bound to filter input elements.\n   * @example\n   * <pre>[\n   *   {\n   *     term: 'foo', // ngModel for <input>\n   *     condition: uiGridConstants.filter.STARTS_WITH,\n   *     placeholder: 'starts with...',\n   *     flags: { caseSensitive: false }\n   *   },\n   *   {\n   *     term: 'baz',\n   *     condition: uiGridConstants.filter.ENDS_WITH,\n   *     placeholder: 'ends with...'\n   *   }\n   * ] </pre>\n   *\n   * \n   */   \n\n  /** \n   * @ngdoc array\n   * @name menuItems\n   * @propertyOf ui.grid.class:GridOptions.columnDef\n   * @description used to add menu items to a column.  Refer to the tutorial on this \n   * functionality.  A number of settings are supported:\n   * \n   * - title: controls the title that is displayed in the menu\n   * - icon: the icon shown alongside that title\n   * - action: the method to call when the menu is clicked\n   * - shown: a function to evaluate to determine whether or not to show the item\n   * - active: a function to evaluate to determine whether or not the item is currently selected\n   * - context: context to pass to the action function??\n   * @example\n   * <pre>  $scope.gridOptions.columnDefs = [ \n   *   { field: 'field1', menuItems: [\n   *     {\n   *       title: 'Outer Scope Alert',\n   *       icon: 'ui-grid-icon-info-circled',\n   *       action: function($event) {\n   *         this.context.blargh(); // $scope.blargh() would work too, this is just an example\n   *       },\n   *       shown: function() { return true; },\n   *       active: function() { return true; },\n   *       context: $scope\n   *     },\n   *     {\n   *       title: 'Grid ID',\n   *       action: function() {\n   *         alert('Grid ID: ' + this.grid.id);\n   *       }\n   *     }\n   *   ] }]; </pre>\n   *\n   */   \n\n  /**\n   * @ngdoc method\n   * @methodOf ui.grid.class:GridColumn\n   * @name updateColumnDef\n   * @description Moves settings from the columnDef down onto the column,\n   * and sets properties as appropriate\n   * @param {ColumnDef} colDef the column def to look in for the property value\n   * @param {boolean} isNew whether the column is being newly created, if not\n   * we're updating an existing column, and some items such as the sort shouldn't\n   * be copied down\n   */ \n  GridColumn.prototype.updateColumnDef = function(colDef, isNew) {\n    var self = this;\n\n    self.colDef = colDef;\n\n    if (colDef.name === undefined) {\n      throw new Error('colDef.name is required for column at index ' + self.grid.options.columnDefs.indexOf(colDef));\n    }\n\n    self.displayName = (colDef.displayName === undefined) ? gridUtil.readableColumnName(colDef.name) : colDef.displayName;\n    \n    var parseErrorMsg = \"Cannot parse column width '\" + colDef.width + \"' for column named '\" + colDef.name + \"'\";\n\n    // If width is not defined, set it to a single star\n    if (gridUtil.isNullOrUndefined(self.width) || !angular.isNumber(self.width)) {\n      if (gridUtil.isNullOrUndefined(colDef.width)) {\n        self.width = '*';\n      }\n      else {\n        // If the width is not a number\n        if (!angular.isNumber(colDef.width)) {\n          // See if it ends with a percent\n          if (gridUtil.endsWith(colDef.width, '%')) {\n            // If so we should be able to parse the non-percent-sign part to a number\n            var percentStr = colDef.width.replace(/%/g, '');\n            var percent = parseInt(percentStr, 10);\n            if (isNaN(percent)) {\n              throw new Error(parseErrorMsg);\n            }\n            self.width = colDef.width;\n          }\n          // And see if it's a number string\n          else if (colDef.width.match(/^(\\d+)$/)) {\n            self.width = parseInt(colDef.width.match(/^(\\d+)$/)[1], 10);\n          }\n          // Otherwise it should be a string of asterisks\n          else if (colDef.width.match(/^\\*+$/)) {\n            self.width = colDef.width;\n          }\n          // No idea, throw an Error\n          else {\n            throw new Error(parseErrorMsg);\n          }\n        }\n        // Is a number, use it as the width\n        else {\n          self.width = colDef.width;\n        }\n      }\n    }\n\n    self.minWidth = !colDef.minWidth ? 30 : colDef.minWidth;\n    self.maxWidth = !colDef.maxWidth ? 9000 : colDef.maxWidth;\n\n    //use field if it is defined; name if it is not\n    self.field = (colDef.field === undefined) ? colDef.name : colDef.field;\n    \n    if ( typeof( self.field ) !== 'string' ){\n      gridUtil.logError( 'Field is not a string, this is likely to break the code, Field is: ' + self.field );\n    }\n    \n    self.name = colDef.name;\n\n    // Use colDef.displayName as long as it's not undefined, otherwise default to the field name\n    self.displayName = (colDef.displayName === undefined) ? gridUtil.readableColumnName(colDef.name) : colDef.displayName;\n\n    //self.originalIndex = index;\n\n    self.aggregationType = angular.isDefined(colDef.aggregationType) ? colDef.aggregationType : null;\n    self.footerCellTemplate = angular.isDefined(colDef.footerCellTemplate) ? colDef.footerCellTemplate : null;\n\n    /**\n     * @ngdoc property\n     * @name footerCellClass\n     * @propertyOf ui.grid.class:GridOptions.columnDef\n     * @description footerCellClass can be a string specifying the class to append to a cell\n     * or it can be a function(row,rowRenderIndex, col, colRenderIndex) that returns a class name\n     *\n     */\n    self.footerCellClass = colDef.footerCellClass;\n\n    /**\n     * @ngdoc property\n     * @name cellClass\n     * @propertyOf ui.grid.class:GridOptions.columnDef\n     * @description cellClass can be a string specifying the class to append to a cell\n     * or it can be a function(row,rowRenderIndex, col, colRenderIndex) that returns a class name\n     *\n     */\n    self.cellClass = colDef.cellClass;\n\n    /**\n     * @ngdoc property\n     * @name headerCellClass\n     * @propertyOf ui.grid.class:GridOptions.columnDef\n     * @description headerCellClass can be a string specifying the class to append to a cell\n     * or it can be a function(row,rowRenderIndex, col, colRenderIndex) that returns a class name\n     *\n     */\n    self.headerCellClass = colDef.headerCellClass;\n\n    /**\n     * @ngdoc property\n     * @name cellFilter\n     * @propertyOf ui.grid.class:GridOptions.columnDef\n     * @description cellFilter is a filter to apply to the content of each cell\n     * @example\n     * <pre>\n     *   gridOptions.columnDefs[0].cellFilter = 'date'\n     *\n     */\n    self.cellFilter = colDef.cellFilter ? colDef.cellFilter : \"\";\n\n    /**\n     * @ngdoc property\n     * @name headerCellFilter\n     * @propertyOf ui.grid.class:GridOptions.columnDef\n     * @description headerCellFilter is a filter to apply to the content of the column header\n     * @example\n     * <pre>\n     *   gridOptions.columnDefs[0].headerCellFilter = 'translate'\n     *\n     */\n    self.headerCellFilter = colDef.headerCellFilter ? colDef.headerCellFilter : \"\";\n\n    /**\n     * @ngdoc property\n     * @name footerCellFilter\n     * @propertyOf ui.grid.class:GridOptions.columnDef\n     * @description footerCellFilter is a filter to apply to the content of the column footer\n     * @example\n     * <pre>\n     *   gridOptions.columnDefs[0].footerCellFilter = 'date'\n     *\n     */\n    self.footerCellFilter = colDef.footerCellFilter ? colDef.footerCellFilter : \"\";\n\n    self.visible = gridUtil.isNullOrUndefined(colDef.visible) || colDef.visible;\n\n    self.headerClass = colDef.headerClass;\n    //self.cursor = self.sortable ? 'pointer' : 'default';\n\n    // Turn on sorting by default\n    self.enableSorting = typeof(colDef.enableSorting) !== 'undefined' ? colDef.enableSorting : true;\n    self.sortingAlgorithm = colDef.sortingAlgorithm;\n\n    /**\n     * @ngdoc property\n     * @name enableFiltering\n     * @propertyOf ui.grid.class:GridOptions.columnDef\n     * @description turn off filtering for an individual column, where\n     * you've turned on filtering for the overall grid\n     * @example\n     * <pre>\n     *   gridOptions.columnDefs[0].enableFiltering = false;\n     *\n     */\n    // Turn on filtering by default (it's disabled by default at the Grid level)\n    self.enableFiltering = typeof(colDef.enableFiltering) !== 'undefined' ? colDef.enableFiltering : true;\n\n    // self.menuItems = colDef.menuItems;\n    self.setPropertyOrDefault(colDef, 'menuItems', []);\n\n    // Use the column definition sort if we were passed it, but only if this is a newly added column\n    if ( isNew ){\n      self.setPropertyOrDefault(colDef, 'sort');\n    }\n\n    // Set up default filters array for when one is not provided.\n    //   In other words, this (in column def):\n    //   \n    //       filter: { term: 'something', flags: {}, condition: [CONDITION] }\n    //       \n    //   is just shorthand for this:\n    //   \n    //       filters: [{ term: 'something', flags: {}, condition: [CONDITION] }]\n    //       \n    var defaultFilters = [];\n    if (colDef.filter) {\n      defaultFilters.push(colDef.filter);\n    }\n    else if (self.enableFiltering && self.grid.options.enableFiltering) {\n      // Add an empty filter definition object, which will\n      // translate to a guessed condition and no pre-populated\n      // value for the filter <input>.\n      defaultFilters.push({});\n    }\n\n    /** \n     * @ngdoc property\n     * @name filter\n     * @propertyOf ui.grid.class:GridOptions.columnDef\n     * @description Specify a single filter field on this column.\n     * \n     * A filter consists of a condition, a term, and a placeholder:\n     * \n     * - condition defines how rows are chosen as matching the filter term. This can be set to\n     * one of the constants in uiGridConstants.filter, or you can supply a custom filter function\n     * that gets passed the following arguments: [searchTerm, cellValue, row, column].\n     * - term: If set, the filter field will be pre-populated\n     * with this value.\n     * - placeholder: String that will be set to the `<input>.placeholder` attribute.\n     * - noTerm: set this to true if you have defined a custom function in condition, and\n     * your custom function doesn't require a term (so it can run even when the term is null)\n     * - flags: only flag currently available is `caseSensitive`, set to false if you don't want\n     * case sensitive matching\n     * @example\n     * <pre>$scope.gridOptions.columnDefs = [ \n     *   {\n     *     field: 'field1',\n     *     filter: {\n     *       term: 'xx',\n     *       condition: uiGridConstants.filter.STARTS_WITH,\n     *       placeholder: 'starts with...',\n     *       flags: { caseSensitive: false }\n     *     }\n     *   }\n     * ]; </pre>\n     *\n     */\n  \n    /*\n\n      self.filters = [\n        {\n          term: 'search term'\n          condition: uiGridConstants.filter.CONTAINS,\n          placeholder: 'my placeholder',\n          flags: {\n            caseSensitive: true\n          }\n        }\n      ]\n\n    */\n\n    // Only set filter if this is a newly added column, if we're updating an existing\n    // column then we don't want to put the default filter back if the user may have already\n    // removed it.\n    if ( isNew ) {\n      self.setPropertyOrDefault(colDef, 'filter');\n      self.setPropertyOrDefault(colDef, 'filters', defaultFilters);\n    }\n\n    // Remove this column from the grid sorting, include inside build columns so has\n    // access to self - all seems a bit dodgy but doesn't work otherwise so have left\n    // as is\n    GridColumn.prototype.unsort = function () {\n      this.sort = {};\n      self.grid.api.core.raise.sortChanged( self, self.grid.getColumnSorting() );\n    };\n  \n  };\n\n\n  /**\n   * @ngdoc function\n   * @name getColClass\n   * @methodOf ui.grid.class:GridColumn\n   * @description Returns the class name for the column\n   * @param {bool} prefixDot  if true, will return .className instead of className\n   */\n  GridColumn.prototype.getColClass = function (prefixDot) {\n    var cls = uiGridConstants.COL_CLASS_PREFIX + this.uid;\n\n    return prefixDot ? '.' + cls : cls;\n  };\n\n  /**\n   * @ngdoc function\n   * @name getColClassDefinition\n   * @methodOf ui.grid.class:GridColumn\n   * @description Returns the class definition for th column\n   */\n  GridColumn.prototype.getColClassDefinition = function () {\n    return ' .grid' + this.grid.id + ' ' + this.getColClass(true) + ' { width: ' + this.drawnWidth + 'px; }';\n  };\n\n  /**\n   * @ngdoc function\n   * @name getRenderContainer\n   * @methodOf ui.grid.class:GridColumn\n   * @description Returns the render container object that this column belongs to.\n   *\n   * Columns will be default be in the `body` render container if they aren't allocated to one specifically.\n   */\n  GridColumn.prototype.getRenderContainer = function getRenderContainer() {\n    var self = this;\n\n    var containerId = self.renderContainer;\n\n    if (containerId === null || containerId === '' || containerId === undefined) {\n      containerId = 'body';\n    }\n\n    return self.grid.renderContainers[containerId];\n  };\n\n  /**\n   * @ngdoc function\n   * @name showColumn\n   * @methodOf ui.grid.class:GridColumn\n   * @description Makes the column visible by setting colDef.visible = true\n   */\n  GridColumn.prototype.showColumn = function() {\n      this.colDef.visible = true;\n  };\n\n  /**\n   * @ngdoc function\n   * @name hideColumn\n   * @methodOf ui.grid.class:GridColumn\n   * @description Hides the column by setting colDef.visible = false\n   */\n  GridColumn.prototype.hideColumn = function() {\n      this.colDef.visible = false;\n  };\n\n  /**\n   * @ngdoc function\n   * @name getAggregationValue\n   * @methodOf ui.grid.class:GridColumn\n   * @description gets the aggregation value based on the aggregation type for this column\n   */\n  GridColumn.prototype.getAggregationValue = function () {\n    var self = this;\n    var result = 0;\n    var visibleRows = self.grid.getVisibleRows();\n\n    var cellValues = function(){\n      var values = [];\n      angular.forEach(visibleRows, function (row) {\n        var cellValue = self.grid.getCellValue(row, self);\n        if (angular.isNumber(cellValue)) {\n          values.push(cellValue);\n        }\n      });\n      return values;\n    };\n\n    if (angular.isFunction(self.aggregationType)) {\n      return self.aggregationType(visibleRows, self);\n    }\n    else if (self.aggregationType === uiGridConstants.aggregationTypes.count) {\n      return self.grid.getVisibleRowCount();\n    }\n    else if (self.aggregationType === uiGridConstants.aggregationTypes.sum) {\n      angular.forEach(cellValues(), function (value) {\n        result += value;\n      });\n      return result;\n    }\n    else if (self.aggregationType === uiGridConstants.aggregationTypes.avg) {\n      angular.forEach(cellValues(), function (value) {\n        result += value;\n      });\n      result = result / cellValues().length;\n      return result;\n    }\n    else if (self.aggregationType === uiGridConstants.aggregationTypes.min) {\n      return Math.min.apply(null, cellValues());\n    }\n    else if (self.aggregationType === uiGridConstants.aggregationTypes.max) {\n      return Math.max.apply(null, cellValues());\n    }\n    else {\n      return '\\u00A0';\n    }\n  };\n    \n  /** \n   * @ngdoc property\n   * @name aggregationHideLabel\n   * @propertyOf ui.grid.class:GridOptions.columnDef\n   * @description defaults to false, if set to true hides the label text\n   * in the aggregation footer, so only the value is displayed.\n   *\n   */\n  /**\n   * @ngdoc function\n   * @name getAggregationText\n   * @methodOf ui.grid.class:GridColumn\n   * @description Gets the aggregation label from colDef.aggregationLabel if\n   * specified or by using i18n, including deciding whether or not to display\n   * based on colDef.aggregationHideLabel.\n   *\n   * @param {string} label the i18n lookup value to use for the column label\n   * \n   */\n  GridColumn.prototype.getAggregationText = function () {\n    var self = this;\n    if ( self.colDef.aggregationHideLabel ){\n      return '';\n    }\n    else if ( self.colDef.aggregationLabel ) {\n      return self.colDef.aggregationLabel;\n    }\n    else {\n      switch ( self.colDef.aggregationType ){\n        case uiGridConstants.aggregationTypes.count:\n          return i18nService.getSafeText('aggregation.count');\n        case uiGridConstants.aggregationTypes.sum:\n          return i18nService.getSafeText('aggregation.sum');\n        case uiGridConstants.aggregationTypes.avg:\n          return i18nService.getSafeText('aggregation.avg');\n        case uiGridConstants.aggregationTypes.min:\n          return i18nService.getSafeText('aggregation.min');\n        case uiGridConstants.aggregationTypes.max:\n          return i18nService.getSafeText('aggregation.max');\n        default:\n          return '';\n      }\n    }\n  };\n\n  GridColumn.prototype.getCellTemplate = function () {\n    var self = this;\n\n    return self.cellTemplatePromise;\n  };\n\n  GridColumn.prototype.getCompiledElementFn = function () {\n    var self = this;\n\n    return self.compiledElementFnDefer.promise;\n  };\n\n  return GridColumn;\n}]);\n\n})();\n\n  (function(){\n\nangular.module('ui.grid')\n.factory('GridOptions', ['gridUtil','uiGridConstants', function(gridUtil,uiGridConstants) {\n\n  /**\n   * @ngdoc function\n   * @name ui.grid.class:GridOptions\n   * @description Default GridOptions class.  GridOptions are defined by the application developer and overlaid\n   * over this object.  Setting gridOptions within your controller is the most common method for an application \n   * developer to configure the behaviour of their ui-grid\n   * \n   * @example To define your gridOptions within your controller:\n   * <pre>$scope.gridOptions = {\n   *   data: $scope.myData,\n   *   columnDefs: [ \n   *     { name: 'field1', displayName: 'pretty display name' },\n   *     { name: 'field2', visible: false }\n   *  ]\n   * };</pre>\n   * \n   * You can then use this within your html template, when you define your grid:\n   * <pre>&lt;div ui-grid=\"gridOptions\"&gt;&lt;/div&gt;</pre>\n   *\n   * To provide default options for all of the grids within your application, use an angular\n   * decorator to modify the GridOptions factory.\n   * <pre>\n   * app.config(function($provide){\n   *   $provide.decorator('GridOptions',function($delegate){\n   *     var gridOptions;\n   *     gridOptions = angular.copy($delegate);\n   *     gridOptions.initialize = function(options) {\n   *       var initOptions;\n   *       initOptions = $delegate.initialize(options);\n   *       initOptions.enableColumnMenus = false;\n   *       return initOptions;\n   *     };\n   *     return gridOptions;\n   *   });\n   * });\n   * </pre>\n   */\n  return {\n    initialize: function( baseOptions ){\n      /**\n       * @ngdoc function\n       * @name onRegisterApi\n       * @propertyOf ui.grid.class:GridOptions\n       * @description A callback that returns the gridApi once the grid is instantiated, which is \n       * then used to interact with the grid programatically.\n       * \n       * Note that the gridApi.core.renderingComplete event is identical to this \n       * callback, but has the advantage that it can be called from multiple places\n       * if needed\n       * \n       * @example\n       * <pre>\n       *   $scope.gridOptions.onRegisterApi = function ( gridApi ) {\n       *     $scope.gridApi = gridApi;\n       *     $scope.gridApi.selection.selectAllRows( $scope.gridApi.grid );\n       *   };\n       * </pre>\n       * \n       */\n      baseOptions.onRegisterApi = baseOptions.onRegisterApi || angular.noop();\n  \n      /**\n       * @ngdoc object\n       * @name data\n       * @propertyOf ui.grid.class:GridOptions\n       * @description (mandatory) Array of data to be rendered into the grid, providing the data source or data binding for \n       * the grid.  The most common case is an array of objects, where each object has a number of attributes.\n       * Each attribute automatically becomes a column in your grid.  This array could, for example, be sourced from\n       * an angularJS $resource query request.  The array can also contain complex objects.\n       * \n       */\n      baseOptions.data = baseOptions.data || [];\n  \n      /**\n       * @ngdoc array\n       * @name columnDefs\n       * @propertyOf  ui.grid.class:GridOptions\n       * @description Array of columnDef objects.  Only required property is name.\n       * The individual options available in columnDefs are documented in the\n       * {@link ui.grid.class:GridOptions.columnDef columnDef} section\n       * </br>_field property can be used in place of name for backwards compatibility with 2.x_\n       *  @example\n       *\n       * <pre>var columnDefs = [{name:'field1'}, {name:'field2'}];</pre>\n       *\n       */\n      baseOptions.columnDefs = baseOptions.columnDefs || [];\n  \n      /**\n       * @ngdoc object\n       * @name ui.grid.class:GridOptions.columnDef\n       * @description Definition / configuration of an individual column, which would typically be\n       * one of many column definitions within the gridOptions.columnDefs array\n       * @example\n       * <pre>{name:'field1', field: 'field1', filter: { term: 'xxx' }}</pre>\n       *\n       */\n  \n          \n      /**\n       * @ngdoc array\n       * @name excludeProperties\n       * @propertyOf  ui.grid.class:GridOptions\n       * @description Array of property names in data to ignore when auto-generating column names.  Provides the\n       * inverse of columnDefs - columnDefs is a list of columns to include, excludeProperties is a list of columns\n       * to exclude. \n       * \n       * If columnDefs is defined, this will be ignored.\n       * \n       * Defaults to ['$$hashKey']\n       */\n      \n      baseOptions.excludeProperties = baseOptions.excludeProperties || ['$$hashKey'];\n  \n      /**\n       * @ngdoc boolean\n       * @name enableRowHashing\n       * @propertyOf ui.grid.class:GridOptions\n       * @description True by default. When enabled, this setting allows uiGrid to add\n       * `$$hashKey`-type properties (similar to Angular) to elements in the `data` array. This allows\n       * the grid to maintain state while vastly speeding up the process of altering `data` by adding/moving/removing rows.\n       * \n       * Note that this DOES add properties to your data that you may not want, but they are stripped out when using `angular.toJson()`. IF\n       * you do not want this at all you can disable this setting but you will take a performance hit if you are using large numbers of rows\n       * and are altering the data set often.\n       */\n      baseOptions.enableRowHashing = baseOptions.enableRowHashing !== false;\n  \n      /**\n       * @ngdoc function\n       * @name rowIdentity\n       * @methodOf ui.grid.class:GridOptions\n       * @description This function is used to get and, if necessary, set the value uniquely identifying this row (i.e. if an identity is not present it will set one).\n       * \n       * By default it returns the `$$hashKey` property if it exists. If it doesn't it uses gridUtil.nextUid() to generate one\n       */\n      baseOptions.rowIdentity = baseOptions.rowIdentity || function rowIdentity(row) {\n        return gridUtil.hashKey(row);\n      };\n  \n      /**\n       * @ngdoc function\n       * @name getRowIdentity\n       * @methodOf ui.grid.class:GridOptions\n       * @description This function returns the identity value uniquely identifying this row, if one is not present it does not set it.\n       * \n       * By default it returns the `$$hashKey` property but can be overridden to use any property or set of properties you want.\n       */\n      baseOptions.getRowIdentity = baseOptions.getRowIdentity || function getRowIdentity(row) {\n        return row.$$hashKey;\n      };\n\n      /**\n       * @ngdoc property\n       * @name showHeader\n       * @propertyOf ui.grid.class:GridOptions\n       * @description True by default. When set to false, this setting will replace the\n       * standard header template with '<div></div>', resulting in no header being shown.\n       *\n       * It will also set the `headerRowHeight` option to 0.\n       */\n      baseOptions.showHeader = typeof(baseOptions.showHeader) !== \"undefined\" ? baseOptions.showHeader : true;\n\n      /**\n       * @ngdoc property\n       * @name headerRowHeight\n       * @propertyOf ui.grid.class:GridOptions\n       * @description The height of the header in pixels, defaults to 30\n       *\n       */\n      if (!baseOptions.showHeader) {\n        baseOptions.headerRowHeight = 0;\n      }\n      else {\n        baseOptions.headerRowHeight = typeof(baseOptions.headerRowHeight) !== \"undefined\" ? baseOptions.headerRowHeight : 30;\n      }\n\n      /**\n       * @ngdoc property\n       * @name rowHeight\n       * @propertyOf ui.grid.class:GridOptions\n       * @description The height of the row in pixels, defaults to 30\n       *\n       */\n      baseOptions.rowHeight = baseOptions.rowHeight || 30;\n  \n      /**\n       * @ngdoc integer\n       * @name minRowsToShow\n       * @propertyOf ui.grid.class:GridOptions\n       * @description Minimum number of rows to show when the grid doesn't have a defined height. Defaults to \"10\".\n       */\n      baseOptions.minRowsToShow = typeof(baseOptions.minRowsToShow) !== \"undefined\" ? baseOptions.minRowsToShow : 10;\n  \n      /**\n       * @ngdoc property\n       * @name showGridFooter\n       * @propertyOf ui.grid.class:GridOptions\n       * @description Whether or not to show the footer, defaults to false\n       * The footer display Total Rows and Visible Rows (filtered rows)\n       */\n      baseOptions.showGridFooter = baseOptions.showGridFooter === true;\n\n      /**\n       * @ngdoc property\n       * @name showColumnFooter\n       * @propertyOf ui.grid.class:GridOptions\n       * @description Whether or not to show the column footer, defaults to false\n       * The column footer displays column aggregates\n       */\n      baseOptions.showColumnFooter = baseOptions.showColumnFooter === true;\n\n      /**\n       * @ngdoc property\n       * @name columnFooterHeight\n       * @propertyOf ui.grid.class:GridOptions\n       * @description The height of the footer rows (column footer and grid footer) in pixels\n       *\n       */\n      baseOptions.columnFooterHeight = typeof(baseOptions.columnFooterHeight) !== \"undefined\" ? baseOptions.columnFooterHeight : 30;\n      baseOptions.gridFooterHeight = typeof(baseOptions.gridFooterHeight) !== \"undefined\" ? baseOptions.gridFooterHeight : 30;\n\n      baseOptions.columnWidth = typeof(baseOptions.columnWidth) !== \"undefined\" ? baseOptions.columnWidth : 50;\n\n      /**\n       * @ngdoc property\n       * @name maxVisibleColumnCount\n       * @propertyOf ui.grid.class:GridOptions\n       * @description Defaults to 200\n       *\n       */\n      baseOptions.maxVisibleColumnCount = typeof(baseOptions.maxVisibleColumnCount) !== \"undefined\" ? baseOptions.maxVisibleColumnCount : 200;\n  \n      /**\n       * @ngdoc property\n       * @name virtualizationThreshold\n       * @propertyOf ui.grid.class:GridOptions\n       * @description Turn virtualization on when number of data elements goes over this number, defaults to 20\n       */\n      baseOptions.virtualizationThreshold = typeof(baseOptions.virtualizationThreshold) !== \"undefined\" ? baseOptions.virtualizationThreshold : 20;\n  \n      /**\n       * @ngdoc property\n       * @name columnVirtualizationThreshold\n       * @propertyOf ui.grid.class:GridOptions\n       * @description Turn virtualization on when number of columns goes over this number, defaults to 10\n       */\n      baseOptions.columnVirtualizationThreshold = typeof(baseOptions.columnVirtualizationThreshold) !== \"undefined\" ? baseOptions.columnVirtualizationThreshold : 10;\n  \n      /**\n       * @ngdoc property\n       * @name excessRows\n       * @propertyOf ui.grid.class:GridOptions\n       * @description Extra rows to to render outside of the viewport, which helps with smoothness of scrolling.\n       * Defaults to 4\n       */\n      baseOptions.excessRows = typeof(baseOptions.excessRows) !== \"undefined\" ? baseOptions.excessRows : 4;\n      /**\n       * @ngdoc property\n       * @name scrollThreshold\n       * @propertyOf ui.grid.class:GridOptions\n       * @description Defaults to 4\n       */\n      baseOptions.scrollThreshold = typeof(baseOptions.scrollThreshold) !== \"undefined\" ? baseOptions.scrollThreshold : 4;\n  \n      /**\n       * @ngdoc property\n       * @name excessColumns\n       * @propertyOf ui.grid.class:GridOptions\n       * @description Extra columns to to render outside of the viewport, which helps with smoothness of scrolling.\n       * Defaults to 4\n       */\n      baseOptions.excessColumns = typeof(baseOptions.excessColumns) !== \"undefined\" ? baseOptions.excessColumns : 4;\n      /**\n       * @ngdoc property\n       * @name horizontalScrollThreshold\n       * @propertyOf ui.grid.class:GridOptions\n       * @description Defaults to 4\n       */\n      baseOptions.horizontalScrollThreshold = typeof(baseOptions.horizontalScrollThreshold) !== \"undefined\" ? baseOptions.horizontalScrollThreshold : 2;\n  \n      /**\n       * @ngdoc property\n       * @name scrollThrottle\n       * @propertyOf ui.grid.class:GridOptions\n       * @description Default time to throttle scroll events to, defaults to 70ms\n       */\n      baseOptions.scrollThrottle = typeof(baseOptions.scrollThrottle) !== \"undefined\" ? baseOptions.scrollThrottle : 70;\n  \n      /**\n       * @ngdoc boolean\n       * @name enableSorting\n       * @propertyOf ui.grid.class:GridOptions\n       * @description True by default. When enabled, this setting adds sort\n       * widgets to the column headers, allowing sorting of the data for the entire grid.\n       * Sorting can then be disabled on individual columns using the columnDefs.\n       */\n      baseOptions.enableSorting = baseOptions.enableSorting !== false;\n  \n      /**\n       * @ngdoc boolean\n       * @name enableFiltering\n       * @propertyOf ui.grid.class:GridOptions\n       * @description False by default. When enabled, this setting adds filter \n       * boxes to each column header, allowing filtering within the column for the entire grid.\n       * Filtering can then be disabled on individual columns using the columnDefs. \n       */\n      baseOptions.enableFiltering = baseOptions.enableFiltering === true;\n  \n      /**\n       * @ngdoc boolean\n       * @name enableColumnMenus\n       * @propertyOf ui.grid.class:GridOptions\n       * @description True by default. When enabled, this setting displays a column\n       * menu within each column.\n       */\n      baseOptions.enableColumnMenus = baseOptions.enableColumnMenus !== false;\n  \n      /**\n       * @ngdoc boolean\n       * @name enableVerticalScrollbar\n       * @propertyOf ui.grid.class:GridOptions\n       * @description uiGridConstants.scrollbars.ALWAYS by default. This settings controls the vertical scrollbar for the grid.\n       * Supported values: uiGridConstants.scrollbars.ALWAYS, uiGridConstants.scrollbars.NEVER\n       */\n      baseOptions.enableVerticalScrollbar = typeof(baseOptions.enableVerticalScrollbar) !== \"undefined\" ? baseOptions.enableVerticalScrollbar : uiGridConstants.scrollbars.ALWAYS;\n      \n      /**\n       * @ngdoc boolean\n       * @name enableHorizontalScrollbar\n       * @propertyOf ui.grid.class:GridOptions\n       * @description uiGridConstants.scrollbars.ALWAYS by default. This settings controls the horizontal scrollbar for the grid.\n       * Supported values: uiGridConstants.scrollbars.ALWAYS, uiGridConstants.scrollbars.NEVER\n       */\n      baseOptions.enableHorizontalScrollbar = typeof(baseOptions.enableHorizontalScrollbar) !== \"undefined\" ? baseOptions.enableHorizontalScrollbar : uiGridConstants.scrollbars.ALWAYS;\n  \n      /**\n       * @ngdoc boolean\n       * @name minimumColumnSize\n       * @propertyOf ui.grid.class:GridOptions\n       * @description Columns can't be smaller than this, defaults to 10 pixels\n       */\n      baseOptions.minimumColumnSize = typeof(baseOptions.minimumColumnSize) !== \"undefined\" ? baseOptions.minimumColumnSize : 10;\n  \n      /**\n       * @ngdoc function\n       * @name rowEquality\n       * @methodOf ui.grid.class:GridOptions\n       * @description By default, rows are compared using object equality.  This option can be overridden\n       * to compare on any data item property or function\n       * @param {object} entityA First Data Item to compare\n       * @param {object} entityB Second Data Item to compare\n       */\n      baseOptions.rowEquality = baseOptions.rowEquality || function(entityA, entityB) {\n        return entityA === entityB;\n      };\n  \n      /**\n       * @ngdoc string\n       * @name headerTemplate\n       * @propertyOf ui.grid.class:GridOptions\n       * @description Null by default. When provided, this setting uses a custom header\n       * template, rather than the default template. Can be set to either the name of a template file:\n       * <pre>  $scope.gridOptions.headerTemplate = 'header_template.html';</pre>\n       * inline html \n       * <pre>  $scope.gridOptions.headerTemplate = '<div class=\"ui-grid-top-panel\" style=\"text-align: center\">I am a Custom Grid Header</div>'</pre>\n       * or the id of a precompiled template (TBD how to use this).  \n       * </br>Refer to the custom header tutorial for more information.\n       * If you want no header at all, you can set to an empty div:\n       * <pre>  $scope.gridOptions.headerTemplate = '<div></div>';</pre>\n       * \n       * If you want to only have a static header, then you can set to static content.  If\n       * you want to tailor the existing column headers, then you should look at the\n       * current 'ui-grid-header.html' template in github as your starting point.\n       * \n       */\n      baseOptions.headerTemplate = baseOptions.headerTemplate || null;\n  \n      /**\n       * @ngdoc string\n       * @name footerTemplate\n       * @propertyOf ui.grid.class:GridOptions\n       * @description (optional) Null by default. When provided, this setting uses a custom footer\n       * template. Can be set to either the name of a template file 'footer_template.html', inline html\n       * <pre>'<div class=\"ui-grid-bottom-panel\" style=\"text-align: center\">I am a Custom Grid Footer</div>'</pre>, or the id\n       * of a precompiled template (TBD how to use this).  Refer to the custom footer tutorial for more information.\n       */\n      baseOptions.footerTemplate = baseOptions.footerTemplate || null;\n  \n      /**\n       * @ngdoc string\n       * @name rowTemplate\n       * @propertyOf ui.grid.class:GridOptions\n       * @description 'ui-grid/ui-grid-row' by default. When provided, this setting uses a \n       * custom row template.  Can be set to either the name of a template file:\n       * <pre> $scope.gridOptions.rowTemplate = 'row_template.html';</pre>\n       * inline html \n       * <pre>  $scope.gridOptions.rowTemplate = '<div style=\"background-color: aquamarine\" ng-click=\"grid.appScope.fnOne(row)\" ng-repeat=\"col in colContainer.renderedColumns track by col.colDef.name\" class=\"ui-grid-cell\" ui-grid-cell></div>';</pre>\n       * or the id of a precompiled template (TBD how to use this) can be provided.  \n       * </br>Refer to the custom row template tutorial for more information.\n       */\n      baseOptions.rowTemplate = baseOptions.rowTemplate || 'ui-grid/ui-grid-row';\n\n      /**\n       * @ngdoc object\n       * @name appScopeProvider\n       * @propertyOf ui.grid.class:GridOptions\n       * @description by default, the parent scope of the ui-grid element will be assigned to grid.appScope\n       * this property allows you to assign any reference you want to grid.appScope\n       */\n      baseOptions.appScopeProvider = baseOptions.appScopeProvider || null;\n      \n      return baseOptions;\n    }     \n  };\n\n\n}]);\n\n})();\n\n(function(){\n\nangular.module('ui.grid')\n  \n  /**\n   * @ngdoc function\n   * @name ui.grid.class:GridRenderContainer\n   * @description The grid has render containers, allowing the ability to have pinned columns.  If the grid\n   * is right-to-left then there may be a right render container, if left-to-right then there may \n   * be a left render container.  There is always a body render container.\n   * @param {string} name The name of the render container ('body', 'left', or 'right')\n   * @param {Grid} grid the grid the render container is in\n   * @param {object} options the render container options\n   */\n.factory('GridRenderContainer', ['gridUtil', 'uiGridConstants', function(gridUtil, uiGridConstants) {\n  function GridRenderContainer(name, grid, options) {\n    var self = this;\n\n    // if (gridUtil.type(grid) !== 'Grid') {\n    //   throw new Error('Grid argument is not a Grid object');\n    // }\n\n    self.name = name;\n\n    self.grid = grid;\n    \n    // self.rowCache = [];\n    // self.columnCache = [];\n\n    self.visibleRowCache = [];\n    self.visibleColumnCache = [];\n\n    self.renderedRows = [];\n    self.renderedColumns = [];\n\n    self.prevScrollTop = 0;\n    self.prevScrolltopPercentage = 0;\n    self.prevRowScrollIndex = 0;\n\n    self.prevScrollLeft = 0;\n    self.prevScrollleftPercentage = 0;\n    self.prevColumnScrollIndex = 0;\n\n    self.columnStyles = \"\";\n\n    self.viewportAdjusters = [];\n\n    /**\n     *  @ngdoc boolean\n     *  @name canvasHeightShouldUpdate\n     *  @propertyOf  ui.grid.class:GridRenderContainer\n     *  @description flag to signal that container should recalculate the canvas size\n     */\n    self.canvasHeightShouldUpdate = true;\n\n    /**\n     *  @ngdoc boolean\n     *  @name canvasHeight\n     *  @propertyOf  ui.grid.class:GridRenderContainer\n     *  @description last calculated canvas height value\n     */\n    self.$$canvasHeight = 0;\n\n    if (options && angular.isObject(options)) {\n      angular.extend(self, options);\n    }\n\n    grid.registerStyleComputation({\n      priority: 5,\n      func: function () {\n        return self.columnStyles;\n      }\n    });\n  }\n\n  // GridRenderContainer.prototype.addRenderable = function addRenderable(renderable) {\n  //   this.renderables.push(renderable);\n  // };\n\n  GridRenderContainer.prototype.reset = function reset() {\n    // this.rowCache.length = 0;\n    // this.columnCache.length = 0;\n\n    this.visibleColumnCache.length = 0;\n    this.visibleRowCache.length = 0;\n\n    this.renderedRows.length = 0;\n    this.renderedColumns.length = 0;\n  };\n\n  // TODO(c0bra): calculate size?? Should this be in a stackable directive?\n\n  GridRenderContainer.prototype.minRowsToRender = function minRowsToRender() {\n    var self = this;\n    var minRows = 0;\n    var rowAddedHeight = 0;\n    var viewPortHeight = self.getViewportHeight();\n    for (var i = self.visibleRowCache.length - 1; rowAddedHeight < viewPortHeight && i >= 0; i--) {\n      rowAddedHeight += self.visibleRowCache[i].height;\n      minRows++;\n    }\n    return minRows;\n  };\n\n  GridRenderContainer.prototype.minColumnsToRender = function minColumnsToRender() {\n    var self = this;\n    var viewportWidth = this.getViewportWidth();\n\n    var min = 0;\n    var totalWidth = 0;\n    // self.columns.forEach(function(col, i) {\n    for (var i = 0; i < self.visibleColumnCache.length; i++) {\n      var col = self.visibleColumnCache[i];\n\n      if (totalWidth < viewportWidth) {\n        totalWidth += col.drawnWidth ? col.drawnWidth : 0;\n        min++;\n      }\n      else {\n        var currWidth = 0;\n        for (var j = i; j >= i - min; j--) {\n          currWidth += self.visibleColumnCache[j].drawnWidth ? self.visibleColumnCache[j].drawnWidth : 0;\n        }\n        if (currWidth < viewportWidth) {\n          min++;\n        }\n      }\n    }\n\n    return min;\n  };\n\n  GridRenderContainer.prototype.getVisibleRowCount = function getVisibleRowCount() {\n    return this.visibleRowCache.length;\n  };\n\n  /**\n   * @ngdoc function\n   * @name registerViewportAdjuster\n   * @methodOf ui.grid.class:GridRenderContainer\n   * @description Registers an adjuster to the render container's available width or height.  Adjusters are used\n   * to tell the render container that there is something else consuming space, and to adjust it's size\n   * appropriately.  \n   * @param {function} func the adjuster function we want to register\n   */\n\n  GridRenderContainer.prototype.registerViewportAdjuster = function registerViewportAdjuster(func) {\n    this.viewportAdjusters.push(func);\n  };\n\n  /**\n   * @ngdoc function\n   * @name removeViewportAdjuster\n   * @methodOf ui.grid.class:GridRenderContainer\n   * @description Removes an adjuster, should be used when your element is destroyed\n   * @param {function} func the adjuster function we want to remove\n   */\n  GridRenderContainer.prototype.removeViewportAdjuster = function registerViewportAdjuster(func) {\n    var idx = this.viewportAdjusters.indexOf(func);\n\n    if (typeof(idx) !== 'undefined' && idx !== undefined) {\n      this.viewportAdjusters.splice(idx, 1);\n    }\n  };\n\n  /**\n   * @ngdoc function\n   * @name getViewportAdjustment\n   * @methodOf ui.grid.class:GridRenderContainer\n   * @description Gets the adjustment based on the viewportAdjusters.  \n   * @returns {object} a hash of { height: x, width: y }.  Usually the values will be negative\n   */\n  GridRenderContainer.prototype.getViewportAdjustment = function getViewportAdjustment() {\n    var self = this;\n\n    var adjustment = { height: 0, width: 0 };\n\n    self.viewportAdjusters.forEach(function (func) {\n      adjustment = func.call(this, adjustment);\n    });\n\n    return adjustment;\n  };\n\n  GridRenderContainer.prototype.getViewportHeight = function getViewportHeight() {\n    var self = this;\n\n    var headerHeight = (self.headerHeight) ? self.headerHeight : self.grid.headerHeight;\n\n    var viewPortHeight = self.grid.gridHeight - headerHeight - self.grid.footerHeight;\n\n\n    var adjustment = self.getViewportAdjustment();\n    \n    viewPortHeight = viewPortHeight + adjustment.height;\n\n    return viewPortHeight;\n  };\n\n  GridRenderContainer.prototype.getViewportWidth = function getViewportWidth() {\n    var self = this;\n\n    var viewPortWidth = self.grid.gridWidth;\n\n    //if (typeof(self.grid.verticalScrollbarWidth) !== 'undefined' && self.grid.verticalScrollbarWidth !== undefined && self.grid.verticalScrollbarWidth > 0) {\n    //  viewPortWidth = viewPortWidth - self.grid.verticalScrollbarWidth;\n    //}\n\n    var adjustment = self.getViewportAdjustment();\n    \n    viewPortWidth = viewPortWidth + adjustment.width;\n\n    return viewPortWidth;\n  };\n\n  GridRenderContainer.prototype.getHeaderViewportWidth = function getHeaderViewportWidth() {\n    var self = this;\n\n    var viewPortWidth = this.getViewportWidth();\n\n    //if (typeof(self.grid.verticalScrollbarWidth) !== 'undefined' && self.grid.verticalScrollbarWidth !== undefined && self.grid.verticalScrollbarWidth > 0) {\n    //  viewPortWidth = viewPortWidth + self.grid.verticalScrollbarWidth;\n    //}\n\n    // var adjustment = self.getViewportAdjustment();\n    // viewPortWidth = viewPortWidth + adjustment.width;\n\n    return viewPortWidth;\n  };\n\n\n  /**\n   * @ngdoc function\n   * @name getCanvasHeight\n   * @methodOf ui.grid.class:GridRenderContainer\n   * @description Returns the total canvas height.   Only recalculates if canvasHeightShouldUpdate = false\n   * @returns {number} total height of all the visible rows in the container\n   */\n  GridRenderContainer.prototype.getCanvasHeight = function getCanvasHeight() {\n    var self = this;\n\n    if (!self.canvasHeightShouldUpdate) {\n      return self.$$canvasHeight;\n    }\n\n    var oldCanvasHeight = self.$$canvasHeight;\n\n    self.$$canvasHeight =  0;\n\n    self.visibleRowCache.forEach(function(row){\n      self.$$canvasHeight += row.height;\n    });\n\n\n    self.canvasHeightShouldUpdate = false;\n\n    self.grid.api.core.raise.canvasHeightChanged(oldCanvasHeight, self.$$canvasHeight);\n\n    return self.$$canvasHeight;\n  };\n\n  GridRenderContainer.prototype.getVerticalScrollLength = function getVerticalScrollLength() {\n    return this.getCanvasHeight() - this.getViewportHeight();\n  };\n\n  GridRenderContainer.prototype.getCanvasWidth = function getCanvasWidth() {\n    var self = this;\n\n    var ret = self.canvasWidth;\n\n    //if (typeof(self.verticalScrollbarWidth) !== 'undefined' && self.verticalScrollbarWidth !== undefined && self.verticalScrollbarWidth > 0) {\n    //  ret = ret - self.verticalScrollbarWidth;\n    //}\n\n    return ret;\n  };\n\n  GridRenderContainer.prototype.setRenderedRows = function setRenderedRows(newRows) {\n    this.renderedRows.length = newRows.length;\n    for (var i = 0; i < newRows.length; i++) {\n      this.renderedRows[i] = newRows[i];\n    }\n  };\n\n  GridRenderContainer.prototype.setRenderedColumns = function setRenderedColumns(newColumns) {\n    var self = this;\n\n    // OLD:\n    this.renderedColumns.length = newColumns.length;\n    for (var i = 0; i < newColumns.length; i++) {\n      this.renderedColumns[i] = newColumns[i];\n    }\n    \n    this.updateColumnOffset();\n  };\n\n  GridRenderContainer.prototype.updateColumnOffset = function updateColumnOffset() {\n    // Calculate the width of the columns on the left side that are no longer rendered.\n    //  That will be the offset for the columns as we scroll horizontally.\n    var hiddenColumnsWidth = 0;\n    for (var i = 0; i < this.currentFirstColumn; i++) {\n      hiddenColumnsWidth += this.visibleColumnCache[i].drawnWidth;\n    }\n\n    this.columnOffset = hiddenColumnsWidth;\n  };\n\n  GridRenderContainer.prototype.adjustScrollVertical = function adjustScrollVertical(scrollTop, scrollPercentage, force) {\n    if (this.prevScrollTop === scrollTop && !force) {\n      return;\n    }\n\n    if (typeof(scrollTop) === 'undefined' || scrollTop === undefined || scrollTop === null) {\n      scrollTop = (this.getCanvasHeight() - this.getCanvasWidth()) * scrollPercentage;\n    }\n\n    this.adjustRows(scrollTop, scrollPercentage, false);\n\n    this.prevScrollTop = scrollTop;\n    this.prevScrolltopPercentage = scrollPercentage;\n\n    this.grid.queueRefresh();\n  };\n\n  GridRenderContainer.prototype.adjustScrollHorizontal = function adjustScrollHorizontal(scrollLeft, scrollPercentage, force) {\n    if (this.prevScrollLeft === scrollLeft && !force) {\n      return;\n    }\n\n    if (typeof(scrollLeft) === 'undefined' || scrollLeft === undefined || scrollLeft === null) {\n      scrollLeft = (this.getCanvasWidth() - this.getViewportWidth()) * scrollPercentage;\n    }\n\n    this.adjustColumns(scrollLeft, scrollPercentage);\n\n    this.prevScrollLeft = scrollLeft;\n    this.prevScrollleftPercentage = scrollPercentage;\n\n    this.grid.queueRefresh();\n  };\n\n  GridRenderContainer.prototype.adjustRows = function adjustRows(scrollTop, scrollPercentage, postDataLoaded) {\n    var self = this;\n\n    var minRows = self.minRowsToRender();\n\n    var rowCache = self.visibleRowCache;\n\n    var maxRowIndex = rowCache.length - minRows;\n\n    // Calculate the scroll percentage according to the scrollTop location, if no percentage was provided\n    if ((typeof(scrollPercentage) === 'undefined' || scrollPercentage === null) && scrollTop) {\n      scrollPercentage = scrollTop / self.getVerticalScrollLength();\n    }\n    \n    var rowIndex = Math.ceil(Math.min(maxRowIndex, maxRowIndex * scrollPercentage));\n\n    // Define a max row index that we can't scroll past\n    if (rowIndex > maxRowIndex) {\n      rowIndex = maxRowIndex;\n    }\n\n    var newRange = [];\n    if (rowCache.length > self.grid.options.virtualizationThreshold) {\n      if (!(typeof(scrollTop) === 'undefined' || scrollTop === null)) {\n        // Have we hit the threshold going down?\n        if (!self.grid.options.enableInfiniteScroll && self.prevScrollTop < scrollTop && rowIndex < self.prevRowScrollIndex + self.grid.options.scrollThreshold && rowIndex < maxRowIndex) {\n          return;\n        }\n        //Have we hit the threshold going up?\n        if (!self.grid.options.enableInfiniteScroll && self.prevScrollTop > scrollTop && rowIndex > self.prevRowScrollIndex - self.grid.options.scrollThreshold && rowIndex < maxRowIndex) {\n          return;\n        }\n      }\n      var rangeStart = {};\n      var rangeEnd = {};\n\n      //If infinite scroll is enabled, and we loaded more data coming from redrawInPlace, then recalculate the range and set rowIndex to proper place to scroll to\n      if ( self.grid.options.enableInfiniteScroll && self.grid.scrollDirection !== uiGridConstants.scrollDirection.NONE && postDataLoaded ) {\n        var findIndex = null;\n        var i = null;\n        if ( self.grid.scrollDirection === uiGridConstants.scrollDirection.UP ) {\n          findIndex = rowIndex > 0 ? self.grid.options.excessRows : 0;\n          for ( i = 0; i < rowCache.length; i++) {\n            if (rowCache[i].entity.$$hashKey === self.renderedRows[findIndex].entity.$$hashKey) {\n              rowIndex = i;\n              break;\n            }\n          }\n          rangeStart = Math.max(0, rowIndex);\n          rangeEnd = Math.min(rowCache.length, rangeStart + self.grid.options.excessRows + minRows);\n        }\n        else if ( self.grid.scrollDirection === uiGridConstants.scrollDirection.DOWN ) {\n          findIndex = minRows;\n          for ( i = 0; i < rowCache.length; i++) {\n            if (rowCache[i].entity.$$hashKey === self.renderedRows[findIndex].entity.$$hashKey) {\n              rowIndex = i;\n              break;\n            }\n          }\n          rangeStart = Math.max(0, rowIndex - self.grid.options.excessRows - minRows);\n          rangeEnd = Math.min(rowCache.length, rowIndex + minRows + self.grid.options.excessRows);\n        }\n      }\n      else {\n        rangeStart = Math.max(0, rowIndex - self.grid.options.excessRows);\n        rangeEnd = Math.min(rowCache.length, rowIndex + minRows + self.grid.options.excessRows);\n      }\n\n      newRange = [rangeStart, rangeEnd];\n    }\n    else {\n      var maxLen = self.visibleRowCache.length;\n      newRange = [0, Math.max(maxLen, minRows + self.grid.options.excessRows)];\n    }\n\n    self.updateViewableRowRange(newRange);\n\n    self.prevRowScrollIndex = rowIndex;\n  };\n\n  GridRenderContainer.prototype.adjustColumns = function adjustColumns(scrollLeft, scrollPercentage) {\n    var self = this;\n\n    var minCols = self.minColumnsToRender();\n\n    var columnCache = self.visibleColumnCache;\n    var maxColumnIndex = columnCache.length - minCols;\n\n    // Calculate the scroll percentage according to the scrollTop location, if no percentage was provided\n    if ((typeof(scrollPercentage) === 'undefined' || scrollPercentage === null) && scrollLeft) {\n      scrollPercentage = scrollLeft / self.getCanvasWidth();\n    }\n\n    var colIndex = Math.ceil(Math.min(maxColumnIndex, maxColumnIndex * scrollPercentage));\n\n    // Define a max row index that we can't scroll past\n    if (colIndex > maxColumnIndex) {\n      colIndex = maxColumnIndex;\n    }\n    \n    var newRange = [];\n    if (columnCache.length > self.grid.options.columnVirtualizationThreshold && self.getCanvasWidth() > self.getViewportWidth()) {\n      /* Commented the following lines because otherwise the moved column wasn't visible immediately on the new position\n       * in the case of many columns with horizontal scroll, one had to scroll left or right and then return in order to see it\n      // Have we hit the threshold going down?\n      if (self.prevScrollLeft < scrollLeft && colIndex < self.prevColumnScrollIndex + self.grid.options.horizontalScrollThreshold && colIndex < maxColumnIndex) {\n        return;\n      }\n      //Have we hit the threshold going up?\n      if (self.prevScrollLeft > scrollLeft && colIndex > self.prevColumnScrollIndex - self.grid.options.horizontalScrollThreshold && colIndex < maxColumnIndex) {\n        return;\n      }*/\n\n      var rangeStart = Math.max(0, colIndex - self.grid.options.excessColumns);\n      var rangeEnd = Math.min(columnCache.length, colIndex + minCols + self.grid.options.excessColumns);\n\n      newRange = [rangeStart, rangeEnd];\n    }\n    else {\n      var maxLen = self.visibleColumnCache.length;\n\n      newRange = [0, Math.max(maxLen, minCols + self.grid.options.excessColumns)];\n    }\n    \n    self.updateViewableColumnRange(newRange);\n\n    self.prevColumnScrollIndex = colIndex;\n  };\n\n  // Method for updating the visible rows\n  GridRenderContainer.prototype.updateViewableRowRange = function updateViewableRowRange(renderedRange) {\n    // Slice out the range of rows from the data\n    // var rowArr = uiGridCtrl.grid.rows.slice(renderedRange[0], renderedRange[1]);\n    var rowArr = this.visibleRowCache.slice(renderedRange[0], renderedRange[1]);\n\n    // Define the top-most rendered row\n    this.currentTopRow = renderedRange[0];\n\n    // TODO(c0bra): make this method!\n    this.setRenderedRows(rowArr);\n  };\n\n  // Method for updating the visible columns\n  GridRenderContainer.prototype.updateViewableColumnRange = function updateViewableColumnRange(renderedRange) {\n    // Slice out the range of rows from the data\n    // var columnArr = uiGridCtrl.grid.columns.slice(renderedRange[0], renderedRange[1]);\n    var columnArr = this.visibleColumnCache.slice(renderedRange[0], renderedRange[1]);\n\n    // Define the left-most rendered columns\n    this.currentFirstColumn = renderedRange[0];\n\n    this.setRenderedColumns(columnArr);\n  };\n\n  GridRenderContainer.prototype.rowStyle = function (index) {\n    var self = this;\n\n    var styles = {};\n    \n    if (index === 0 && self.currentTopRow !== 0) {\n      // The row offset-top is just the height of the rows above the current top-most row, which are no longer rendered\n      var hiddenRowWidth = (self.currentTopRow) * self.grid.options.rowHeight;\n\n      // return { 'margin-top': hiddenRowWidth + 'px' };\n      styles['margin-top'] = hiddenRowWidth + 'px';\n    }\n\n    if (self.currentFirstColumn !== 0) {\n      if (self.grid.isRTL()) {\n        styles['margin-right'] = self.columnOffset + 'px';\n      }\n      else {\n        styles['margin-left'] = self.columnOffset + 'px';\n      }\n    }\n\n    return styles;\n  };\n\n  GridRenderContainer.prototype.columnStyle = function (index) {\n    var self = this;\n    \n    if (index === 0 && self.currentFirstColumn !== 0) {\n      var offset = self.columnOffset;\n\n      if (self.grid.isRTL()) {\n        return { 'margin-right': offset + 'px' };\n      }\n      else {\n        return { 'margin-left': offset + 'px' };\n      }\n    }\n\n    return null;\n  };\n\n  GridRenderContainer.prototype.updateColumnWidths = function () {\n    var self = this;\n\n    var asterisksArray = [],\n        percentArray = [],\n        manualArray = [],\n        asteriskNum = 0,\n        totalWidth = 0;\n\n    // Get the width of the viewport\n    var availableWidth = self.getViewportWidth();\n\n    //if (typeof(self.grid.verticalScrollbarWidth) !== 'undefined' && self.grid.verticalScrollbarWidth !== undefined && self.grid.verticalScrollbarWidth > 0) {\n    //  availableWidth = availableWidth + self.grid.verticalScrollbarWidth;\n    //}\n\n    // The total number of columns\n    // var equalWidthColumnCount = columnCount = uiGridCtrl.grid.options.columnDefs.length;\n    // var equalWidth = availableWidth / equalWidthColumnCount;\n\n    // The last column we processed\n    var lastColumn;\n\n    var manualWidthSum = 0;\n\n    var canvasWidth = 0;\n\n    var ret = '';\n\n\n    // uiGridCtrl.grid.columns.forEach(function(column, i) {\n\n    var columnCache = self.visibleColumnCache;\n\n    columnCache.forEach(function(column, i) {\n      // ret = ret + ' .grid' + uiGridCtrl.grid.id + ' .col' + i + ' { width: ' + equalWidth + 'px; left: ' + left + 'px; }';\n      //var colWidth = (typeof(c.width) !== 'undefined' && c.width !== undefined) ? c.width : equalWidth;\n\n      // Skip hidden columns\n      if (!column.visible) { return; }\n\n      var colWidth,\n          isPercent = false;\n\n      if (!angular.isNumber(column.width)) {\n        isPercent = isNaN(column.width) && gridUtil.endsWith(column.width, \"%\");\n      }\n\n      if (angular.isString(column.width) && column.width.indexOf('*') !== -1) { //  we need to save it until the end to do the calulations on the remaining width.\n        asteriskNum = parseInt(asteriskNum + column.width.length, 10);\n        \n        asterisksArray.push(column);\n      }\n      else if (isPercent) { // If the width is a percentage, save it until the very last.\n        percentArray.push(column);\n      }\n      else if (angular.isNumber(column.width)) {\n        manualWidthSum = parseInt(manualWidthSum + column.width, 10);\n        \n        canvasWidth = parseInt(canvasWidth, 10) + parseInt(column.width, 10);\n\n        column.drawnWidth = column.width;\n      }\n    });\n\n    // Get the remaining width (available width subtracted by the manual widths sum)\n    var remainingWidth = availableWidth - manualWidthSum;\n\n    var i, column, colWidth;\n\n    if (percentArray.length > 0) {\n      // Pre-process to make sure they're all within any min/max values\n      for (i = 0; i < percentArray.length; i++) {\n        column = percentArray[i];\n\n        var percent = parseInt(column.width.replace(/%/g, ''), 10) / 100;\n\n        colWidth = parseInt(percent * remainingWidth, 10);\n\n        if (column.colDef.minWidth && colWidth < column.colDef.minWidth) {\n          colWidth = column.colDef.minWidth;\n\n          remainingWidth = remainingWidth - colWidth;\n\n          canvasWidth += colWidth;\n          column.drawnWidth = colWidth;\n\n          // Remove this element from the percent array so it's not processed below\n          percentArray.splice(i, 1);\n        }\n        else if (column.colDef.maxWidth && colWidth > column.colDef.maxWidth) {\n          colWidth = column.colDef.maxWidth;\n\n          remainingWidth = remainingWidth - colWidth;\n\n          canvasWidth += colWidth;\n          column.drawnWidth = colWidth;\n\n          // Remove this element from the percent array so it's not processed below\n          percentArray.splice(i, 1);\n        }\n      }\n\n      percentArray.forEach(function(column) {\n        var percent = parseInt(column.width.replace(/%/g, ''), 10) / 100;\n        var colWidth = parseInt(percent * remainingWidth, 10);\n\n        canvasWidth += colWidth;\n\n        column.drawnWidth = colWidth;\n      });\n    }\n\n    if (asterisksArray.length > 0) {\n      var asteriskVal = parseInt(remainingWidth / asteriskNum, 10);\n\n       // Pre-process to make sure they're all within any min/max values\n      for (i = 0; i < asterisksArray.length; i++) {\n        column = asterisksArray[i];\n\n        colWidth = parseInt(asteriskVal * column.width.length, 10);\n\n        if (column.colDef.minWidth && colWidth < column.colDef.minWidth) {\n          colWidth = column.colDef.minWidth;\n\n          remainingWidth = remainingWidth - colWidth;\n          asteriskNum--;\n\n          canvasWidth += colWidth;\n          column.drawnWidth = colWidth;\n\n          lastColumn = column;\n\n          // Remove this element from the percent array so it's not processed below\n          asterisksArray.splice(i, 1);\n        }\n        else if (column.colDef.maxWidth && colWidth > column.colDef.maxWidth) {\n          colWidth = column.colDef.maxWidth;\n\n          remainingWidth = remainingWidth - colWidth;\n          asteriskNum--;\n\n          canvasWidth += colWidth;\n          column.drawnWidth = colWidth;\n\n          // Remove this element from the percent array so it's not processed below\n          asterisksArray.splice(i, 1);\n        }\n      }\n\n      // Redo the asterisk value, as we may have removed columns due to width constraints\n      asteriskVal = parseInt(remainingWidth / asteriskNum, 10);\n\n      asterisksArray.forEach(function(column) {\n        var colWidth = parseInt(asteriskVal * column.width.length, 10);\n\n        canvasWidth += colWidth;\n\n        column.drawnWidth = colWidth;\n      });\n    }\n\n    // If the grid width didn't divide evenly into the column widths and we have pixels left over, dole them out to the columns one by one to make everything fit\n    var leftoverWidth = availableWidth - parseInt(canvasWidth, 10);\n\n    if (leftoverWidth > 0 && canvasWidth > 0 && canvasWidth < availableWidth) {\n      var variableColumn = false;\n      // uiGridCtrl.grid.columns.forEach(function(col) {\n      columnCache.forEach(function(col) {\n        if (col.width && !angular.isNumber(col.width)) {\n          variableColumn = true;\n        }\n      });\n\n      if (variableColumn) {\n        var remFn = function (column) {\n          if (leftoverWidth > 0) {\n            column.drawnWidth = column.drawnWidth + 1;\n            canvasWidth = canvasWidth + 1;\n            leftoverWidth--;\n          }\n        };\n        while (leftoverWidth > 0) {\n          columnCache.forEach(remFn);\n        }\n      }\n    }\n\n    if (canvasWidth < availableWidth) {\n      canvasWidth = availableWidth;\n    }\n\n    // Build the CSS\n    columnCache.forEach(function (column) {\n      ret = ret + column.getColClassDefinition();\n    });\n\n    // Add the vertical scrollbar width back in to the canvas width, it's taken out in getCanvasWidth\n    //if (self.grid.verticalScrollbarWidth) {\n    //  canvasWidth = canvasWidth + self.grid.verticalScrollbarWidth;\n    //}\n    // canvasWidth = canvasWidth + 1;\n\n    self.canvasWidth = parseInt(canvasWidth, 10);\n\n    // Return the styles back to buildStyles which pops them into the `customStyles` scope variable\n    // return ret;\n\n    // Set this render container's column styles so they can be used in style computation\n    this.columnStyles = ret;\n  };\n\n  GridRenderContainer.prototype.getViewPortStyle = function () {\n    var self = this;\n    var styles = {};\n\n    if (self.name === 'body') {\n      styles['overflow-x'] = self.grid.options.enableHorizontalScrollbar === uiGridConstants.scrollbars.NEVER ? 'hidden' : 'scroll';\n      if (!self.grid.isRTL()) {\n        if (self.grid.hasRightContainerColumns()) {\n          styles['overflow-y'] = 'hidden';\n        }\n        else {\n          styles['overflow-y'] = self.grid.options.enableVerticalScrollbar === uiGridConstants.scrollbars.NEVER ? 'hidden' : 'scroll';\n        }\n      }\n      else {\n        if (self.grid.hasLeftContainerColumns()) {\n          styles['overflow-y'] = 'hidden';\n        }\n        else {\n          styles['overflow-y'] = self.grid.options.enableVerticalScrollbar === uiGridConstants.scrollbars.NEVER ? 'hidden' : 'scroll';\n        }\n      }\n    }\n    else if (self.name === 'left') {\n      styles['overflow-x'] = 'hidden';\n      styles['overflow-y'] = self.grid.isRTL() ? (self.grid.options.enableVerticalScrollbar === uiGridConstants.scrollbars.NEVER ? 'hidden' : 'scroll') : 'hidden';\n    }\n    else {\n      styles['overflow-x'] = 'hidden';\n      styles['overflow-y'] = !self.grid.isRTL() ? (self.grid.options.enableVerticalScrollbar === uiGridConstants.scrollbars.NEVER ? 'hidden' : 'scroll') : 'hidden';\n    }\n\n    return styles;\n\n\n  };\n\n  return GridRenderContainer;\n}]);\n\n})();\n\n(function(){\n\nangular.module('ui.grid')\n.factory('GridRow', ['gridUtil', function(gridUtil) {\n\n   /**\n   * @ngdoc function\n   * @name ui.grid.class:GridRow\n   * @description GridRow is the viewModel for one logical row on the grid.  A grid Row is not necessarily a one-to-one\n   * relation to gridOptions.data.\n   * @param {object} entity the array item from GridOptions.data\n   * @param {number} index the current position of the row in the array\n   * @param {Grid} reference to the parent grid\n   */\n  function GridRow(entity, index, grid) {\n\n     /**\n      *  @ngdoc object\n      *  @name grid\n      *  @propertyOf  ui.grid.class:GridRow\n      *  @description A reference back to the grid\n      */\n     this.grid = grid;\n\n     /**\n      *  @ngdoc object\n      *  @name entity\n      *  @propertyOf  ui.grid.class:GridRow\n      *  @description A reference to an item in gridOptions.data[]\n      */\n    this.entity = entity;\n\n     /**\n      *  @ngdoc object\n      *  @name uid\n      *  @propertyOf  ui.grid.class:GridRow\n      *  @description  UniqueId of row\n      */\n     this.uid = gridUtil.nextUid();\n\n     /**\n      *  @ngdoc object\n      *  @name visible\n      *  @propertyOf  ui.grid.class:GridRow\n      *  @description If true, the row will be rendered\n      */\n    // Default to true\n    this.visible = true;\n\n\n    this.$$height = grid.options.rowHeight;\n\n  }\n\n    /**\n     *  @ngdoc object\n     *  @name height\n     *  @propertyOf  ui.grid.class:GridRow\n     *  @description height of each individual row. changing the height will flag all\n     *  row renderContainers to recalculate their canvas height\n     */\n    Object.defineProperty(GridRow.prototype, 'height', {\n      get: function() {\n        return this.$$height;\n      },\n      set: function(height) {\n        if (height !== this.$$height) {\n          this.grid.updateCanvasHeight();\n          this.$$height = height;\n        }\n      }\n    });\n\n  /**\n   * @ngdoc function\n   * @name getQualifiedColField\n   * @methodOf ui.grid.class:GridRow\n   * @description returns the qualified field name as it exists on scope\n   * ie: row.entity.fieldA\n   * @param {GridCol} col column instance\n   * @returns {string} resulting name that can be evaluated on scope\n   */\n    GridRow.prototype.getQualifiedColField = function(col) {\n      return 'row.' + this.getEntityQualifiedColField(col);\n    };\n\n    /**\n     * @ngdoc function\n     * @name getEntityQualifiedColField\n     * @methodOf ui.grid.class:GridRow\n     * @description returns the qualified field name minus the row path\n     * ie: entity.fieldA\n     * @param {GridCol} col column instance\n     * @returns {string} resulting name that can be evaluated against a row\n     */\n  GridRow.prototype.getEntityQualifiedColField = function(col) {\n    return gridUtil.preEval('entity.' + col.field);\n  };\n  \n  \n  /**\n   * @ngdoc function\n   * @name setRowInvisible\n   * @methodOf  ui.grid.class:GridRow\n   * @description Sets an override on the row that forces it to always\n   * be invisible, and if the row is currently visible then marks it\n   * as invisible and refreshes the grid.  Emits the rowsVisibleChanged\n   * event if it changed the row visibility\n   * @param {GridRow} row row to force invisible, needs to be a GridRow,\n   * which can be found from your data entity using grid.findRow\n   */\n  GridRow.prototype.setRowInvisible = function (row) {\n    if (row !== null) {\n      row.forceInvisible = true;\n      \n      if ( row.visible ){\n        row.visible = false;\n        row.grid.refresh();\n        row.grid.api.core.raise.rowsVisibleChanged();\n      }\n    }        \n  };\n\n  /**\n   * @ngdoc function\n   * @name clearRowInvisible\n   * @methodOf ui.grid.class:GridRow\n   * @description Clears any override on the row visibility, returning it \n   * to normal visibility calculations.  If the row is currently invisible\n   * then sets it to visible and calls refresh and emits the rowsVisibleChanged\n   * event\n   * TODO: if filter in action, then is this right?\n   * @param {GridRow} row row clear force invisible, needs to be a GridRow,\n   * which can be found from your data entity using grid.findRow\n   */\n  GridRow.prototype.clearRowInvisible = function (row) {\n    if (row !== null) {\n      row.forceInvisible = false;\n      \n      if ( !row.visible ){\n        row.visible = true;\n        row.grid.refresh();\n        row.grid.api.core.raise.rowsVisibleChanged();\n      }\n    }        \n  };\n\n  return GridRow;\n}]);\n\n})();\n(function () {\n  angular.module('ui.grid')\n    .factory('ScrollEvent', ['gridUtil', function (gridUtil) {\n\n      /**\n       * @ngdoc function\n       * @name ui.grid.class:ScrollEvent\n       * @description Model for all scrollEvents\n       * @param {Grid} grid that owns the scroll event\n       * @param {GridRenderContainer} sourceRowContainer that owns the scroll event. Can be null\n       * @param {GridRenderContainer} sourceColContainer that owns the scroll event. Can be null\n       * @param {string} source the source of the event - from uiGridConstants.scrollEventSources or a string value of directive/service/factory.functionName\n       */\n      function ScrollEvent(grid, sourceRowContainer, sourceColContainer, source) {\n        var self = this;\n        if (!grid) {\n          throw new Error(\"grid argument is required\");\n        }\n\n        /**\n         *  @ngdoc object\n         *  @name grid\n         *  @propertyOf  ui.grid.class:ScrollEvent\n         *  @description A reference back to the grid\n         */\n         self.grid = grid;\n\n\n\n        /**\n         *  @ngdoc object\n         *  @name entity\n         *  @propertyOf  ui.grid.class:ScrollEvent\n         *  @description the source of the scroll event. limited to values from uiGridConstants.scrollEventSources\n         */\n        self.source = source;\n\n        self.sourceRowContainer = sourceRowContainer;\n        self.sourceColContainer = sourceColContainer;\n\n        self.newScrollLeft = null;\n        self.newScrollTop = null;\n        self.x = null;\n        self.y = null;\n\n\n        /**\n         *  @ngdoc function\n         *  @name fireThrottledScrollingEvent\n         *  @methodOf  ui.grid.class:ScrollEvent\n         *  @description fires a throttled event using grid.api.core.raise.scrollEvent\n         */\n        self.fireThrottledScrollingEvent = gridUtil.throttle(function() {\n          self.grid.api.core.raise.scrollEvent(self);\n        }, self.grid.options.scrollThrottle, {trailing: true});\n\n      }\n\n      /**\n       *  @ngdoc function\n       *  @name fireScrollingEvent\n       *  @methodOf  ui.grid.class:ScrollEvent\n       *  @description fires an event using grid.api.core.raise.scrollEvent\n       */\n      ScrollEvent.prototype.fireScrollingEvent = function() {\n        this.grid.api.core.raise.scrollEvent(this);\n      };\n\n\n      /**\n       *  @ngdoc function\n       *  @name getNewScrollLeft\n       *  @methodOf  ui.grid.class:ScrollEvent\n       *  @description returns newScrollLeft property if available; calculates a new value if it isn't\n       */\n      ScrollEvent.prototype.getNewScrollLeft = function(colContainer, viewport){\n        var self = this;\n\n        if (!self.newScrollLeft){\n          var scrollWidth = (colContainer.getCanvasWidth() - colContainer.getViewportWidth());\n\n          var oldScrollLeft = gridUtil.normalizeScrollLeft(viewport);\n\n          var scrollXPercentage;\n          if (typeof(self.x.percentage) !== 'undefined' && self.x.percentage !== undefined) {\n            scrollXPercentage = self.x.percentage;\n          }\n          else if (typeof(self.x.pixels) !== 'undefined' && self.x.pixels !== undefined) {\n            scrollXPercentage = self.x.percentage = (oldScrollLeft + self.x.pixels) / scrollWidth;\n          }\n          else {\n            throw new Error(\"No percentage or pixel value provided for scroll event X axis\");\n          }\n\n          return Math.max(0, scrollXPercentage * scrollWidth);\n        }\n\n        return self.newScrollLeft;\n      };\n\n\n      /**\n       *  @ngdoc function\n       *  @name getNewScrollTop\n       *  @methodOf  ui.grid.class:ScrollEvent\n       *  @description returns newScrollTop property if available; calculates a new value if it isn't\n       */\n      ScrollEvent.prototype.getNewScrollTop = function(rowContainer, viewport){\n        var self = this;\n\n\n        if (!self.newScrollTop){\n          var scrollLength = rowContainer.getVerticalScrollLength();\n\n          var oldScrollTop = viewport[0].scrollTop;\n\n          var scrollYPercentage;\n          if (typeof(self.y.percentage) !== 'undefined' && self.y.percentage !== undefined) {\n            scrollYPercentage = self.y.percentage;\n          }\n          else if (typeof(self.y.pixels) !== 'undefined' && self.y.pixels !== undefined) {\n            scrollYPercentage = self.y.percentage = (oldScrollTop + self.y.pixels) / scrollLength;\n          }\n          else {\n            throw new Error(\"No percentage or pixel value provided for scroll event Y axis\");\n          }\n\n          return Math.max(0, scrollYPercentage * scrollLength);\n        }\n\n        return self.newScrollTop;\n      };\n\n\n      ScrollEvent.Sources = {\n        ViewPortScroll: 'ViewPortScroll',\n        RenderContainerMouseWheel: 'RenderContainerMouseWheel',\n        RenderContainerTouchMove: 'RenderContainerTouchMove',\n        Other: 99\n      };\n\n      return ScrollEvent;\n    }]);\n\n\n\n})();\n(function () {\n  'use strict';\n  /**\n   *  @ngdoc object\n   *  @name ui.grid.service:gridClassFactory\n   *\n   *  @description factory to return dom specific instances of a grid\n   *\n   */\n  angular.module('ui.grid').service('gridClassFactory', ['gridUtil', '$q', '$compile', '$templateCache', 'uiGridConstants', 'Grid', 'GridColumn', 'GridRow',\n    function (gridUtil, $q, $compile, $templateCache, uiGridConstants, Grid, GridColumn, GridRow) {\n\n      var service = {\n        /**\n         * @ngdoc method\n         * @name createGrid\n         * @methodOf ui.grid.service:gridClassFactory\n         * @description Creates a new grid instance. Each instance will have a unique id\n         * @param {object} options An object map of options to pass into the created grid instance.\n         * @returns {Grid} grid\n         */\n        createGrid : function(options) {\n          options = (typeof(options) !== 'undefined') ? options : {};\n          options.id = gridUtil.newId();\n          var grid = new Grid(options);\n\n          // NOTE/TODO: rowTemplate should always be defined...\n          if (grid.options.rowTemplate) {\n            var rowTemplateFnPromise = $q.defer();\n            grid.getRowTemplateFn = rowTemplateFnPromise.promise;\n            \n            gridUtil.getTemplate(grid.options.rowTemplate)\n              .then(\n                function (template) {\n                  var rowTemplateFn = $compile(template);\n                  rowTemplateFnPromise.resolve(rowTemplateFn);\n                },\n                function (res) {\n                  // Todo handle response error here?\n                  throw new Error(\"Couldn't fetch/use row template '\" + grid.options.rowTemplate + \"'\");\n                });\n          }\n\n          grid.registerColumnBuilder(service.defaultColumnBuilder);\n\n          // Row builder for custom row templates\n          grid.registerRowBuilder(service.rowTemplateAssigner);\n\n          // Reset all rows to visible initially\n          grid.registerRowsProcessor(function allRowsVisible(rows) {\n            rows.forEach(function (row) {\n              row.visible = !row.forceInvisible;\n            });\n\n            return rows;\n          });\n\n          grid.registerColumnsProcessor(function allColumnsVisible(columns) {\n            columns.forEach(function (column) {\n              column.visible = true;\n            });\n\n            return columns;\n          });\n\n          grid.registerColumnsProcessor(function(renderableColumns) {\n              renderableColumns.forEach(function (column) {\n                  if (column.colDef.visible === false) {\n                      column.visible = false;\n                  }\n              });\n\n              return renderableColumns;\n          });\n\n\n\n          if (grid.options.enableFiltering) {\n            grid.registerRowsProcessor(grid.searchRows);\n          }\n\n          // Register the default row processor, it sorts rows by selected columns\n          if (grid.options.externalSort && angular.isFunction(grid.options.externalSort)) {\n            grid.registerRowsProcessor(grid.options.externalSort);\n          }\n          else {\n            grid.registerRowsProcessor(grid.sortByColumn);\n          }\n\n          return grid;\n        },\n\n        /**\n         * @ngdoc function\n         * @name defaultColumnBuilder\n         * @methodOf ui.grid.service:gridClassFactory\n         * @description Processes designTime column definitions and applies them to col for the\n         *              core grid features\n         * @param {object} colDef reference to column definition\n         * @param {GridColumn} col reference to gridCol\n         * @param {object} gridOptions reference to grid options\n         */\n        defaultColumnBuilder: function (colDef, col, gridOptions) {\n\n          var templateGetPromises = [];\n\n          /**\n           * @ngdoc property\n           * @name headerCellTemplate\n           * @propertyOf ui.grid.class:GridOptions.columnDef\n           * @description a custom template for the header for this column.  The default\n           * is ui-grid/uiGridHeaderCell\n           *\n           */\n          if (!colDef.headerCellTemplate) {\n            col.providedHeaderCellTemplate = 'ui-grid/uiGridHeaderCell';\n          } else {\n            col.providedHeaderCellTemplate = colDef.headerCellTemplate;\n          }\n\n          /**\n           * @ngdoc property\n           * @name cellTemplate\n           * @propertyOf ui.grid.class:GridOptions.columnDef\n           * @description a custom template for each cell in this column.  The default\n           * is ui-grid/uiGridCell.  If you are using the cellNav feature, this template\n           * must contain a div that can receive focus.\n           *\n           */\n          if (!colDef.cellTemplate) {\n            col.providedCellTemplate = 'ui-grid/uiGridCell';\n          } else {\n            col.providedCellTemplate = colDef.cellTemplate;\n          }\n\n          /**\n           * @ngdoc property\n           * @name footerCellTemplate\n           * @propertyOf ui.grid.class:GridOptions.columnDef\n           * @description a custom template for the footer for this column.  The default\n           * is ui-grid/uiGridFooterCell\n           *\n           */\n          if (!colDef.footerCellTemplate) {\n            col.providedFooterCellTemplate = 'ui-grid/uiGridFooterCell';\n          } else {\n            col.providedFooterCellTemplate = colDef.footerCellTemplate;\n          }\n\n          col.cellTemplatePromise = gridUtil.getTemplate(col.providedCellTemplate);\n          templateGetPromises.push(col.cellTemplatePromise\n            .then(\n              function (template) {\n                col.cellTemplate = template.replace(uiGridConstants.CUSTOM_FILTERS, col.cellFilter ? \"|\" + col.cellFilter : \"\");\n              },\n              function (res) {\n                throw new Error(\"Couldn't fetch/use colDef.cellTemplate '\" + colDef.cellTemplate + \"'\");\n              })\n          );\n\n          templateGetPromises.push(gridUtil.getTemplate(col.providedHeaderCellTemplate)\n              .then(\n              function (template) {\n                col.headerCellTemplate = template.replace(uiGridConstants.CUSTOM_FILTERS, col.headerCellFilter ? \"|\" + col.headerCellFilter : \"\");\n              },\n              function (res) {\n                throw new Error(\"Couldn't fetch/use colDef.headerCellTemplate '\" + colDef.headerCellTemplate + \"'\");\n              })\n          );\n\n          templateGetPromises.push(gridUtil.getTemplate(col.providedFooterCellTemplate)\n              .then(\n              function (template) {\n                col.footerCellTemplate = template.replace(uiGridConstants.CUSTOM_FILTERS, col.footerCellFilter ? \"|\" + col.footerCellFilter : \"\");\n              },\n              function (res) {\n                throw new Error(\"Couldn't fetch/use colDef.footerCellTemplate '\" + colDef.footerCellTemplate + \"'\");\n              })\n          );\n\n          // Create a promise for the compiled element function\n          col.compiledElementFnDefer = $q.defer();\n\n          return $q.all(templateGetPromises);\n        },\n\n        rowTemplateAssigner: function rowTemplateAssigner(row) {\n          var grid = this;\n\n          // Row has no template assigned to it\n          if (!row.rowTemplate) {\n            // Use the default row template from the grid\n            row.rowTemplate = grid.options.rowTemplate;\n\n            // Use the grid's function for fetching the compiled row template function\n            row.getRowTemplateFn = grid.getRowTemplateFn;\n          }\n          // Row has its own template assigned\n          else {\n            // Create a promise for the compiled row template function\n            var perRowTemplateFnPromise = $q.defer();\n            row.getRowTemplateFn = perRowTemplateFnPromise.promise;\n\n            // Get the row template\n            gridUtil.getTemplate(row.rowTemplate)\n              .then(function (template) {\n                // Compile the template\n                var rowTemplateFn = $compile(template);\n                \n                // Resolve the compiled template function promise\n                perRowTemplateFnPromise.resolve(rowTemplateFn);\n              },\n              function (res) {\n                // Todo handle response error here?\n                throw new Error(\"Couldn't fetch/use row template '\" + row.rowTemplate + \"'\");\n              });\n          }\n\n          return row.getRowTemplateFn;\n        }\n      };\n\n      //class definitions (moved to separate factories)\n\n      return service;\n    }]);\n\n})();\n(function() {\n\nvar module = angular.module('ui.grid');\n\nfunction escapeRegExp(str) {\n  return str.replace(/[\\-\\[\\]\\/\\{\\}\\(\\)\\*\\+\\?\\.\\\\\\^\\$\\|]/g, \"\\\\$&\");\n}\n\n\n/**\n *  @ngdoc service\n *  @name ui.grid.service:rowSearcher\n *\n *  @description Service for searching/filtering rows based on column value conditions.\n */\nmodule.service('rowSearcher', ['gridUtil', 'uiGridConstants', function (gridUtil, uiGridConstants) {\n  var defaultCondition = uiGridConstants.filter.STARTS_WITH;\n\n  var rowSearcher = {};\n\n  /**\n   * @ngdoc function\n   * @name getTerm\n   * @methodOf ui.grid.service:rowSearcher\n   * @description Get the term from a filter\n   * Trims leading and trailing whitespace\n   * @param {object} filter object to use\n   * @returns {object} Parsed term\n   */\n  rowSearcher.getTerm = function getTerm(filter) {\n    if (typeof(filter.term) === 'undefined') { return filter.term; }\n    \n    var term = filter.term;\n\n    // Strip leading and trailing whitespace if the term is a string\n    if (typeof(term) === 'string') {\n      term = term.trim();\n    }\n\n    return term;\n  };\n\n  /**\n   * @ngdoc function\n   * @name stripTerm\n   * @methodOf ui.grid.service:rowSearcher\n   * @description Remove leading and trailing asterisk (*) from the filter's term\n   * @param {object} filter object to use\n   * @returns {uiGridConstants.filter<int>} Value representing the condition constant value\n   */\n  rowSearcher.stripTerm = function stripTerm(filter) {\n    var term = rowSearcher.getTerm(filter);\n\n    if (typeof(term) === 'string') {\n      return escapeRegExp(term.replace(/(^\\*|\\*$)/g, ''));\n    }\n    else {\n      return term;\n    }\n  };\n  \n\n  /**\n   * @ngdoc function\n   * @name guessCondition\n   * @methodOf ui.grid.service:rowSearcher\n   * @description Guess the condition for a filter based on its term\n   * <br>\n   * Defaults to STARTS_WITH. Uses CONTAINS for strings beginning and ending with *s (*bob*).\n   * Uses STARTS_WITH for strings ending with * (bo*). Uses ENDS_WITH for strings starting with * (*ob).\n   * @param {object} filter object to use\n   * @returns {uiGridConstants.filter<int>} Value representing the condition constant value\n   */\n  rowSearcher.guessCondition = function guessCondition(filter) {\n    if (typeof(filter.term) === 'undefined' || !filter.term) {\n      return defaultCondition;\n    }\n\n    var term = rowSearcher.getTerm(filter);\n    \n    if (/\\*/.test(term)) {\n      var regexpFlags = '';\n      if (!filter.flags || !filter.flags.caseSensitive) {\n        regexpFlags += 'i';\n      }\n\n      var reText = term.replace(/(\\\\)?\\*/g, function ($0, $1) { return $1 ? $0 : '[\\\\s\\\\S]*?'; });\n      return new RegExp('^' + reText + '$', regexpFlags);\n    }\n    // Otherwise default to default condition\n    else {\n      return defaultCondition;\n    }\n  };\n  \n  \n  /**\n   * @ngdoc function\n   * @name setupFilters\n   * @methodOf ui.grid.service:rowSearcher\n   * @description For a given columns filters (either col.filters, or [col.filter] can be passed in),\n   * do all the parsing and pre-processing and store that data into a new filters object.  The object\n   * has the condition, the flags, the stripped term, and a parsed reg exp if there was one.\n   * \n   * We could use a forEach in here, since it's much less performance sensitive, but since we're using \n   * for loops everywhere else in this module...\n   * \n   * @param {array} filters the filters from the column (col.filters or [col.filter])\n   * @returns {array} An array of parsed/preprocessed filters\n   */\n  rowSearcher.setupFilters = function setupFilters( filters ){\n    var newFilters = [];\n    \n    var filtersLength = filters.length;\n    for ( var i = 0; i < filtersLength; i++ ){\n      var filter = filters[i];\n      if ( filter.noTerm || filter.term ){\n        var newFilter = {};\n        \n        var regexpFlags = '';\n        if (!filter.flags || !filter.flags.caseSensitive) {\n          regexpFlags += 'i';\n        }\n    \n        if ( filter.term ){\n          // it is possible to have noTerm.  We don't need to copy that across, it was just a flag to avoid\n          // getting the filter ignored if the filter was a function that didn't use a term\n          newFilter.term = rowSearcher.stripTerm(filter);\n        }\n        \n        if ( filter.condition ){\n          newFilter.condition = filter.condition;\n        } else {\n          newFilter.condition = rowSearcher.guessCondition(filter);\n        }\n\n        newFilter.flags = angular.extend( { caseSensitive: false }, filter.flags );\n\n        if (newFilter.condition === uiGridConstants.filter.STARTS_WITH) {\n          newFilter.startswithRE = new RegExp('^' + newFilter.term, regexpFlags);\n        }\n        \n         if (newFilter.condition === uiGridConstants.filter.ENDS_WITH) {\n          newFilter.endswithRE = new RegExp(newFilter.term + '$', regexpFlags);\n        }\n\n        if (newFilter.condition === uiGridConstants.filter.CONTAINS) {\n          newFilter.containsRE = new RegExp(newFilter.term, regexpFlags);\n        }\n\n        if (newFilter.condition === uiGridConstants.filter.EXACT) {\n          newFilter.exactRE = new RegExp('^' + newFilter.term + '$', regexpFlags);\n        }\n        \n        newFilters.push(newFilter);\n      }\n    }\n    return newFilters;\n  };\n  \n\n  /**\n   * @ngdoc function\n   * @name runColumnFilter\n   * @methodOf ui.grid.service:rowSearcher\n   * @description Runs a single pre-parsed filter against a cell, returning true\n   * if the cell matches that one filter.\n   * \n   * @param {Grid} grid the grid we're working against\n   * @param {GridRow} row the row we're matching against\n   * @param {GridCol} column the column that we're working against\n   * @param {object} filter the specific, preparsed, filter that we want to test\n   * @returns {boolean} true if we match (row stays visible)\n   */\n  rowSearcher.runColumnFilter = function runColumnFilter(grid, row, column, filter) {\n    // Cache typeof condition\n    var conditionType = typeof(filter.condition);\n\n    // Term to search for.\n    var term = filter.term;\n\n    // Get the column value for this row\n    var value = grid.getCellValue(row, column);\n    \n    // If the filter's condition is a RegExp, then use it\n    if (filter.condition instanceof RegExp) {\n      return filter.condition.test(value);\n    }\n\n    // If the filter's condition is a function, run it\n    if (conditionType === 'function') {\n      return filter.condition(term, value, row, column);\n    }\n    \n    if (filter.startswithRE) {\n      return filter.startswithRE.test(value);\n    }\n    \n    if (filter.endswithRE) {\n      return filter.endswithRE.test(value);\n    }\n    \n    if (filter.containsRE) {\n      return filter.containsRE.test(value);\n    }\n    \n    if (filter.exactRE) {\n      return filter.exactRE.test(value);\n    }\n\n    if (filter.condition === uiGridConstants.filter.NOT_EQUAL) {\n      var regex = new RegExp('^' + term + '$');\n      return !regex.exec(value);\n    }\n\n    if (typeof(value) === 'number'){\n      // if the term has a decimal in it, it comes through as '9\\.4', we need to take out the \\\n      var tempFloat = parseFloat(term.replace(/\\\\./,'.'));\n      if (!isNaN(tempFloat)) {\n        term = tempFloat;\n      }\n    }\n\n    if (filter.condition === uiGridConstants.filter.GREATER_THAN) {\n      return (value > term);\n    }\n\n    if (filter.condition === uiGridConstants.filter.GREATER_THAN_OR_EQUAL) {\n      return (value >= term);\n    }\n\n    if (filter.condition === uiGridConstants.filter.LESS_THAN) {\n      return (value < term);\n    }\n    \n    if (filter.condition === uiGridConstants.filter.LESS_THAN_OR_EQUAL) {\n      return (value <= term);\n    }\n    \n    return true;\n  };\n\n\n  /**\n   * @ngdoc boolean\n   * @name useExternalFiltering\n   * @propertyOf ui.grid.class:GridOptions\n   * @description False by default. When enabled, this setting suppresses the internal filtering.\n   * All UI logic will still operate, allowing filter conditions to be set and modified.\n   * \n   * The external filter logic can listen for the `filterChange` event, which fires whenever\n   * a filter has been adjusted.\n   */\n  /**\n   * @ngdoc function\n   * @name searchColumn\n   * @methodOf ui.grid.service:rowSearcher\n   * @description Process provided filters on provided column against a given row. If the row meets \n   * the conditions on all the filters, return true.\n   * @param {Grid} grid Grid to search in\n   * @param {GridRow} row Row to search on\n   * @param {GridCol} column Column with the filters to use\n   * @param {array} filters array of pre-parsed/preprocessed filters to apply\n   * @returns {boolean} Whether the column matches or not.\n   */\n  rowSearcher.searchColumn = function searchColumn(grid, row, column, filters) {\n    if (grid.options.useExternalFiltering) {\n      return true;\n    }\n    \n    var filtersLength = filters.length;\n    for (var i = 0; i < filtersLength; i++) {\n      var filter = filters[i];\n      \n      var ret = rowSearcher.runColumnFilter(grid, row, column, filter);\n      if (!ret) {\n        return false;\n      }\n    }\n\n    return true;\n  };\n\n\n  /**\n   * @ngdoc function\n   * @name search\n   * @methodOf ui.grid.service:rowSearcher\n   * @description Run a search across the given rows and columns, marking any rows that don't \n   * match the stored col.filters or col.filter as invisible.\n   * @param {Grid} grid Grid instance to search inside\n   * @param {Array[GridRow]} rows GridRows to filter\n   * @param {Array[GridColumn]} columns GridColumns with filters to process\n   */\n  rowSearcher.search = function search(grid, rows, columns) {\n    /*\n     * Added performance optimisations into this code base, as this logic creates deeply nested\n     * loops and is therefore very performance sensitive.  In particular, avoiding forEach as\n     * this impacts some browser optimisers (particularly Chrome), using iterators instead\n     */\n    \n    // Don't do anything if we weren't passed any rows\n    if (!rows) {\n      return;\n    }\n\n    // Build list of filters to apply\n    var filterData = [];\n\n    var colsLength = columns.length;\n    for (var i = 0; i < colsLength; i++) {\n      var col = columns[i];\n      \n      if (typeof(col.filters) !== 'undefined' && ( col.filters.length > 1 || col.filters.length === 1 && ( typeof(col.filters[0].term) !== 'undefined' && col.filters[0].term || col.filters[0].noTerm ) ) ) {\n        filterData.push( { col: col, filters: rowSearcher.setupFilters(col.filters) } );\n      }\n      else if (typeof(col.filter) !== 'undefined' && col.filter && ( typeof(col.filter.term) !== 'undefined' && col.filter.term || col.filter.noTerm ) ) {\n        filterData.push( { col: col, filters: rowSearcher.setupFilters([col.filter]) } );\n      }\n    }\n    \n    if (filterData.length > 0) {\n      // define functions outside the loop, performance optimisation\n      var foreachRow = function(grid, row, col, filters){\n        if (row.forceInvisible || !rowSearcher.searchColumn(grid, row, col, filters)) {\n          row.visible = false;\n        }\n      };\n      \n      var foreachFilterCol = function(grid, filterData){\n        var rowsLength = rows.length;\n        for ( var i = 0; i < rowsLength; i++){\n          foreachRow(grid, rows[i], filterData.col, filterData.filters);  \n        }\n      };\n\n      // nested loop itself - foreachFilterCol, which in turn calls foreachRow\n      var filterDataLength = filterData.length;\n      for ( var j = 0; j < filterDataLength; j++){\n        foreachFilterCol( grid, filterData[j] );  \n      }\n\n      if (grid.api.core.raise.rowsVisibleChanged) {\n        grid.api.core.raise.rowsVisibleChanged();\n      }\n    }\n\n    return rows;\n  };\n\n  return rowSearcher;\n}]);\n\n})();\n(function() {\n\nvar module = angular.module('ui.grid');\n\n/**\n * @ngdoc object\n * @name ui.grid.class:RowSorter\n * @description RowSorter provides the default sorting mechanisms, \n * including guessing column types and applying appropriate sort \n * algorithms\n * \n */ \n\nmodule.service('rowSorter', ['$parse', 'uiGridConstants', function ($parse, uiGridConstants) {\n  var currencyRegexStr = \n    '(' +\n    uiGridConstants.CURRENCY_SYMBOLS\n      .map(function (a) { return '\\\\' + a; }) // Escape all the currency symbols ($ at least will jack up this regex)\n      .join('|') + // Join all the symbols together with |s\n    ')?';\n\n  // /^[-+]?[£$¤¥]?[\\d,.]+%?$/\n  var numberStrRegex = new RegExp('^[-+]?' + currencyRegexStr + '[\\\\d,.]+' + currencyRegexStr + '%?$');\n\n  var rowSorter = {\n    // Cache of sorting functions. Once we create them, we don't want to keep re-doing it\n    //   this takes a piece of data from the cell and tries to determine its type and what sorting\n    //   function to use for it\n    colSortFnCache: []\n  };\n\n\n  /**\n   * @ngdoc method\n   * @methodOf ui.grid.class:RowSorter\n   * @name guessSortFn\n   * @description Assigns a sort function to use based on the itemType in the column\n   * @param {string} itemType one of 'number', 'boolean', 'string', 'date', 'object'.  And\n   * error will be thrown for any other type.\n   * @returns {function} a sort function that will sort that type\n   */\n  rowSorter.guessSortFn = function guessSortFn(itemType) {\n    switch (itemType) {\n      case \"number\":\n        return rowSorter.sortNumber;\n      case \"boolean\":\n        return rowSorter.sortBool;\n      case \"string\":\n        return rowSorter.sortAlpha;\n      case \"date\":\n        return rowSorter.sortDate;\n      case \"object\":\n        return rowSorter.basicSort;\n      default:\n        throw new Error('No sorting function found for type:' + itemType);\n    }\n  };\n\n\n  /**\n   * @ngdoc method\n   * @methodOf ui.grid.class:RowSorter\n   * @name handleNulls\n   * @description Sorts nulls and undefined to the bottom (top when\n   * descending).  Called by each of the internal sorters before\n   * attempting to sort.  Note that this method is available on the core api\n   * via gridApi.core.sortHandleNulls\n   * @param {object} a sort value a\n   * @param {object} b sort value b\n   * @returns {number} null if there were no nulls/undefineds, otherwise returns\n   * a sort value that should be passed back from the sort function\n   */\n  rowSorter.handleNulls = function handleNulls(a, b) {\n    // We want to allow zero values and false values to be evaluated in the sort function\n    if ((!a && a !== 0 && a !== false) || (!b && b !== 0 && b !== false)) {\n      // We want to force nulls and such to the bottom when we sort... which effectively is \"greater than\"\n      if ((!a && a !== 0 && a !== false) && (!b && b !== 0 && b !== false)) {\n        return 0;\n      }\n      else if (!a && a !== 0 && a !== false) {\n        return 1;\n      }\n      else if (!b && b !== 0 && b !== false) {\n        return -1;\n      }\n    }\n    return null;\n  };\n\n\n  /**\n   * @ngdoc method\n   * @methodOf ui.grid.class:RowSorter\n   * @name basicSort\n   * @description Sorts any values that provide the < method, including strings\n   * or numbers.  Handles nulls and undefined through calling handleNulls \n   * @param {object} a sort value a\n   * @param {object} b sort value b\n   * @returns {number} normal sort function, returns -ve, 0, +ve\n   */\n  rowSorter.basicSort = function basicSort(a, b) {\n    var nulls = rowSorter.handleNulls(a, b);\n    if ( nulls !== null ){\n      return nulls;\n    } else {\n      if (a === b) {\n        return 0;\n      }\n      if (a < b) {\n        return -1;\n      }\n      return 1;\n    }\n  };\n\n\n  /**\n   * @ngdoc method\n   * @methodOf ui.grid.class:RowSorter\n   * @name sortNumber\n   * @description Sorts numerical values.  Handles nulls and undefined through calling handleNulls \n   * @param {object} a sort value a\n   * @param {object} b sort value b\n   * @returns {number} normal sort function, returns -ve, 0, +ve\n   */\n  rowSorter.sortNumber = function sortNumber(a, b) {\n    var nulls = rowSorter.handleNulls(a, b);\n    if ( nulls !== null ){\n      return nulls;\n    } else {\n      return a - b;\n    }\n  };\n\n\n  /**\n   * @ngdoc method\n   * @methodOf ui.grid.class:RowSorter\n   * @name sortNumberStr\n   * @description Sorts numerical values that are stored in a string (i.e. parses them to numbers first).  \n   * Handles nulls and undefined through calling handleNulls \n   * @param {object} a sort value a\n   * @param {object} b sort value b\n   * @returns {number} normal sort function, returns -ve, 0, +ve\n   */\n  rowSorter.sortNumberStr = function sortNumberStr(a, b) {\n    var nulls = rowSorter.handleNulls(a, b);\n    if ( nulls !== null ){\n      return nulls;\n    } else {\n      var numA, // The parsed number form of 'a'\n          numB, // The parsed number form of 'b'\n          badA = false,\n          badB = false;\n  \n      // Try to parse 'a' to a float\n      numA = parseFloat(a.replace(/[^0-9.-]/g, ''));\n  \n      // If 'a' couldn't be parsed to float, flag it as bad\n      if (isNaN(numA)) {\n          badA = true;\n      }\n  \n      // Try to parse 'b' to a float\n      numB = parseFloat(b.replace(/[^0-9.-]/g, ''));\n  \n      // If 'b' couldn't be parsed to float, flag it as bad\n      if (isNaN(numB)) {\n          badB = true;\n      }\n  \n      // We want bad ones to get pushed to the bottom... which effectively is \"greater than\"\n      if (badA && badB) {\n          return 0;\n      }\n  \n      if (badA) {\n          return 1;\n      }\n  \n      if (badB) {\n          return -1;\n      }\n  \n      return numA - numB;\n    }\n  };\n\n\n  /**\n   * @ngdoc method\n   * @methodOf ui.grid.class:RowSorter\n   * @name sortAlpha\n   * @description Sorts string values. Handles nulls and undefined through calling handleNulls \n   * @param {object} a sort value a\n   * @param {object} b sort value b\n   * @returns {number} normal sort function, returns -ve, 0, +ve\n   */\n  rowSorter.sortAlpha = function sortAlpha(a, b) {\n    var nulls = rowSorter.handleNulls(a, b);\n    if ( nulls !== null ){\n      return nulls;\n    } else {\n      var strA = a.toString().toLowerCase(),\n          strB = b.toString().toLowerCase();\n  \n      return strA === strB ? 0 : (strA < strB ? -1 : 1);\n    }\n  };\n\n\n  /**\n   * @ngdoc method\n   * @methodOf ui.grid.class:RowSorter\n   * @name sortDate\n   * @description Sorts date values. Handles nulls and undefined through calling handleNulls \n   * @param {object} a sort value a\n   * @param {object} b sort value b\n   * @returns {number} normal sort function, returns -ve, 0, +ve\n   */\n  rowSorter.sortDate = function sortDate(a, b) {\n    var nulls = rowSorter.handleNulls(a, b);\n    if ( nulls !== null ){\n      return nulls;\n    } else {\n      var timeA = a.getTime(),\n          timeB = b.getTime();\n  \n      return timeA === timeB ? 0 : (timeA < timeB ? -1 : 1);\n    }\n  };\n\n\n  /**\n   * @ngdoc method\n   * @methodOf ui.grid.class:RowSorter\n   * @name sortBool\n   * @description Sorts boolean values, true is considered larger than false. \n   * Handles nulls and undefined through calling handleNulls \n   * @param {object} a sort value a\n   * @param {object} b sort value b\n   * @returns {number} normal sort function, returns -ve, 0, +ve\n   */\n  rowSorter.sortBool = function sortBool(a, b) {\n    var nulls = rowSorter.handleNulls(a, b);\n    if ( nulls !== null ){\n      return nulls;\n    } else {\n      if (a && b) {\n        return 0;\n      }\n  \n      if (!a && !b) {\n        return 0;\n      }\n      else {\n        return a ? 1 : -1;\n      }\n    }\n  };\n\n\n  /**\n   * @ngdoc method\n   * @methodOf ui.grid.class:RowSorter\n   * @name getSortFn\n   * @description Get the sort function for the column.  Looks first in \n   * rowSorter.colSortFnCache using the column name, failing that it\n   * looks at col.sortingAlgorithm (and puts it in the cache), failing that\n   * it guesses the sort algorithm based on the data type.\n   * \n   * The cache currently seems a bit pointless, as none of the work we do is\n   * processor intensive enough to need caching.  Presumably in future we might\n   * inspect the row data itself to guess the sort function, and in that case\n   * it would make sense to have a cache, the infrastructure is in place to allow\n   * that.\n   * \n   * @param {Grid} grid the grid to consider\n   * @param {GridCol} col the column to find a function for\n   * @param {array} rows an array of grid rows.  Currently unused, but presumably in future\n   * we might inspect the rows themselves to decide what sort of data might be there\n   * @returns {function} the sort function chosen for the column\n   */\n  rowSorter.getSortFn = function getSortFn(grid, col, rows) {\n    var sortFn, item;\n\n    // See if we already figured out what to use to sort the column and have it in the cache\n    if (rowSorter.colSortFnCache[col.colDef.name]) {\n      sortFn = rowSorter.colSortFnCache[col.colDef.name];\n    }\n    // If the column has its OWN sorting algorithm, use that\n    else if (col.sortingAlgorithm !== undefined) {\n      sortFn = col.sortingAlgorithm;\n      rowSorter.colSortFnCache[col.colDef.name] = col.sortingAlgorithm;\n    }\n    // Try and guess what sort function to use\n    else {\n      // Guess the sort function\n      sortFn = rowSorter.guessSortFn(col.colDef.type);\n\n      // If we found a sort function, cache it\n      if (sortFn) {\n        rowSorter.colSortFnCache[col.colDef.name] = sortFn;\n      }\n      else {\n        // We assign the alpha sort because anything that is null/undefined will never get passed to\n        // the actual sorting function. It will get caught in our null check and returned to be sorted\n        // down to the bottom\n        sortFn = rowSorter.sortAlpha;\n      }\n    }\n\n    return sortFn;\n  };\n\n\n\n  /**\n   * @ngdoc method\n   * @methodOf ui.grid.class:RowSorter\n   * @name prioritySort\n   * @description Used where multiple columns are present in the sort criteria,\n   * we determine which column should take precedence in the sort by sorting\n   * the columns based on their sort.priority\n   * \n   * @param {gridColumn} a column a\n   * @param {gridColumn} b column b\n   * @returns {number} normal sort function, returns -ve, 0, +ve\n   */\n  rowSorter.prioritySort = function (a, b) {\n    // Both columns have a sort priority\n    if (a.sort.priority !== undefined && b.sort.priority !== undefined) {\n      // A is higher priority\n      if (a.sort.priority < b.sort.priority) {\n        return -1;\n      }\n      // Equal\n      else if (a.sort.priority === b.sort.priority) {\n        return 0;\n      }\n      // B is higher\n      else {\n        return 1;\n      }\n    }\n    // Only A has a priority\n    else if (a.sort.priority || a.sort.priority === 0) {\n      return -1;\n    }\n    // Only B has a priority\n    else if (b.sort.priority || b.sort.priority === 0) {\n      return 1;\n    }\n    // Neither has a priority\n    else {\n      return 0;\n    }\n  };\n\n\n  /**\n   * @ngdoc object\n   * @name useExternalSorting\n   * @propertyOf ui.grid.class:GridOptions\n   * @description Prevents the internal sorting from executing.  Events will\n   * still be fired when the sort changes, and the sort information on\n   * the columns will be updated, allowing an external sorter (for example,\n   * server sorting) to be implemented.  Defaults to false. \n   * \n   */\n  /**\n   * @ngdoc method\n   * @methodOf ui.grid.class:RowSorter\n   * @name sort\n   * @description sorts the grid \n   * @param {Object} grid the grid itself\n   * @param {Object} rows the rows to be sorted\n   * @param {Object} columns the columns in which to look\n   * for sort criteria\n   */\n  rowSorter.sort = function rowSorterSort(grid, rows, columns) {\n    // first make sure we are even supposed to do work\n    if (!rows) {\n      return;\n    }\n    \n    if (grid.options.useExternalSorting){\n      return rows;\n    }\n\n    // Build the list of columns to sort by\n    var sortCols = [];\n    columns.forEach(function (col) {\n      if (col.sort && col.sort.direction && (col.sort.direction === uiGridConstants.ASC || col.sort.direction === uiGridConstants.DESC)) {\n        sortCols.push(col);\n      }\n    });\n\n    // Sort the \"sort columns\" by their sort priority\n    sortCols = sortCols.sort(rowSorter.prioritySort);\n\n    // Now rows to sort by, maintain original order\n    if (sortCols.length === 0) {\n      return rows;\n    }\n    \n    // Re-usable variables\n    var col, direction;\n\n    // IE9-11 HACK.... the 'rows' variable would be empty where we call rowSorter.getSortFn(...) below. We have to use a separate reference\n    // var d = data.slice(0);\n    var r = rows.slice(0);\n    \n    // put a custom index field on each row, used to make a stable sort out of unstable sorts (e.g. Chrome)\n    angular.forEach( rows, function ( row, idx ) {\n      row.entity.$uiGridIndex = idx;\n    });\n\n    // Now actually sort the data\n    var newRows = rows.sort(function rowSortFn(rowA, rowB) {\n      var tem = 0,\n          idx = 0,\n          sortFn;\n\n      while (tem === 0 && idx < sortCols.length) {\n        // grab the metadata for the rest of the logic\n        col = sortCols[idx];\n        direction = sortCols[idx].sort.direction;\n\n        sortFn = rowSorter.getSortFn(grid, col, r);\n        \n        var propA = grid.getCellValue(rowA, col);\n        var propB = grid.getCellValue(rowB, col);\n\n        tem = sortFn(propA, propB);\n\n        idx++;\n      }\n\n      // Chrome doesn't implement a stable sort function.  If our sort returns 0 \n      // (i.e. the items are equal), then return the previous order using our custom\n      // index variable\n      if (tem === 0 ) {\n        return rowA.entity.$uiGridIndex - rowB.entity.$uiGridIndex;\n      }\n      \n      // Made it this far, we don't have to worry about null & undefined\n      if (direction === uiGridConstants.ASC) {\n        return tem;\n      } else {\n        return 0 - tem;\n      }\n    });\n    \n    // remove the custom index field on each row, used to make a stable sort out of unstable sorts (e.g. Chrome)\n    angular.forEach( newRows, function ( row, idx ) {\n      delete row.entity.$uiGridIndex;\n    });\n    \n    return newRows;\n  };\n\n  return rowSorter;\n}]);\n\n})();\n(function() {\n\nvar module = angular.module('ui.grid');\n\nfunction getStyles (elem) {\n  var e = elem;\n  if (typeof(e.length) !== 'undefined' && e.length) {\n    e = elem[0];\n  }\n\n  return e.ownerDocument.defaultView.getComputedStyle(e, null);\n}\n\nvar rnumnonpx = new RegExp( \"^(\" + (/[+-]?(?:\\d*\\.|)\\d+(?:[eE][+-]?\\d+|)/).source + \")(?!px)[a-z%]+$\", \"i\" ),\n    // swappable if display is none or starts with table except \"table\", \"table-cell\", or \"table-caption\"\n    // see here for display values: https://developer.mozilla.org/en-US/docs/CSS/display\n    rdisplayswap = /^(block|none|table(?!-c[ea]).+)/,\n    cssShow = { position: \"absolute\", visibility: \"hidden\", display: \"block\" };\n\nfunction augmentWidthOrHeight( elem, name, extra, isBorderBox, styles ) {\n  var i = extra === ( isBorderBox ? 'border' : 'content' ) ?\n          // If we already have the right measurement, avoid augmentation\n          4 :\n          // Otherwise initialize for horizontal or vertical properties\n          name === 'width' ? 1 : 0,\n\n          val = 0;\n\n  var sides = ['Top', 'Right', 'Bottom', 'Left'];\n  \n  for ( ; i < 4; i += 2 ) {\n    var side = sides[i];\n    // dump('side', side);\n\n    // both box models exclude margin, so add it if we want it\n    if ( extra === 'margin' ) {\n      var marg = parseFloat(styles[extra + side]);\n      if (!isNaN(marg)) {\n        val += marg;\n      }\n    }\n    // dump('val1', val);\n\n    if ( isBorderBox ) {\n      // border-box includes padding, so remove it if we want content\n      if ( extra === 'content' ) {\n        var padd = parseFloat(styles['padding' + side]);\n        if (!isNaN(padd)) {\n          val -= padd;\n          // dump('val2', val);\n        }\n      }\n\n      // at this point, extra isn't border nor margin, so remove border\n      if ( extra !== 'margin' ) {\n        var bordermarg = parseFloat(styles['border' + side + 'Width']);\n        if (!isNaN(bordermarg)) {\n          val -= bordermarg;\n          // dump('val3', val);\n        }\n      }\n    }\n    else {\n      // at this point, extra isn't content, so add padding\n      var nocontentPad = parseFloat(styles['padding' + side]);\n      if (!isNaN(nocontentPad)) {\n        val += nocontentPad;\n        // dump('val4', val);\n      }\n\n      // at this point, extra isn't content nor padding, so add border\n      if ( extra !== 'padding') {\n        var nocontentnopad = parseFloat(styles['border' + side + 'Width']);\n        if (!isNaN(nocontentnopad)) {\n          val += nocontentnopad;\n          // dump('val5', val);\n        }\n      }\n    }\n  }\n\n  // dump('augVal', val);\n\n  return val;\n}\n\nfunction getWidthOrHeight( elem, name, extra ) {\n  // Start with offset property, which is equivalent to the border-box value\n  var valueIsBorderBox = true,\n          val,\n          styles = getStyles(elem),\n          isBorderBox = styles['boxSizing'] === 'border-box';\n\n  // some non-html elements return undefined for offsetWidth, so check for null/undefined\n  // svg - https://bugzilla.mozilla.org/show_bug.cgi?id=649285\n  // MathML - https://bugzilla.mozilla.org/show_bug.cgi?id=491668\n  if ( val <= 0 || val == null ) {\n    // Fall back to computed then uncomputed css if necessary\n    val = styles[name];\n    if ( val < 0 || val == null ) {\n      val = elem.style[ name ];\n    }\n\n    // Computed unit is not pixels. Stop here and return.\n    if ( rnumnonpx.test(val) ) {\n      return val;\n    }\n\n    // we need the check for style in case a browser which returns unreliable values\n    // for getComputedStyle silently falls back to the reliable elem.style\n    valueIsBorderBox = isBorderBox &&\n            ( true || val === elem.style[ name ] ); // use 'true' instead of 'support.boxSizingReliable()'\n\n    // Normalize \"\", auto, and prepare for extra\n    val = parseFloat( val ) || 0;\n  }\n\n  // use the active box-sizing model to add/subtract irrelevant styles\n  var ret = ( val +\n    augmentWidthOrHeight(\n      elem,\n      name,\n      extra || ( isBorderBox ? \"border\" : \"content\" ),\n      valueIsBorderBox,\n      styles\n    )\n  );\n\n  // dump('ret', ret, val);\n  return ret;\n}\n\nvar uid = ['0', '0', '0'];\nvar uidPrefix = 'uiGrid-';\n\n/**\n *  @ngdoc service\n *  @name ui.grid.service:GridUtil\n *  \n *  @description Grid utility functions\n */\nmodule.service('gridUtil', ['$log', '$window', '$document', '$http', '$templateCache', '$timeout', '$injector', '$q', '$interpolate', 'uiGridConstants',\n  function ($log, $window, $document, $http, $templateCache, $timeout, $injector, $q, $interpolate, uiGridConstants) {\n  var s = {\n\n    getStyles: getStyles,\n\n    /**\n     * @ngdoc method\n     * @name createBoundedWrapper\n     * @methodOf ui.grid.service:GridUtil\n     *\n     * @param {object} Object to bind 'this' to\n     * @param {method} Method to bind\n     * @returns {Function} The wrapper that performs the binding\n     *\n     * @description\n     * Binds given method to given object.\n     *\n     * By means of a wrapper, ensures that ``method`` is always bound to\n     * ``object`` regardless of its calling environment.\n     * Iow, inside ``method``, ``this`` always points to ``object``.\n     *\n     * See http://alistapart.com/article/getoutbindingsituations\n     *\n     */\n    createBoundedWrapper: function(object, method) {\n        return function() {\n            return method.apply(object, arguments);\n        };\n    },\n\n\n    /**\n     * @ngdoc method\n     * @name readableColumnName\n     * @methodOf ui.grid.service:GridUtil\n     *\n     * @param {string} columnName Column name as a string\n     * @returns {string} Column name appropriately capitalized and split apart\n     *\n       @example\n       <example module=\"app\">\n        <file name=\"app.js\">\n          var app = angular.module('app', ['ui.grid']);\n\n          app.controller('MainCtrl', ['$scope', 'gridUtil', function ($scope, gridUtil) {\n            $scope.name = 'firstName';\n            $scope.columnName = function(name) {\n              return gridUtil.readableColumnName(name);\n            };\n          }]);\n        </file>\n        <file name=\"index.html\">\n          <div ng-controller=\"MainCtrl\">\n            <strong>Column name:</strong> <input ng-model=\"name\" />\n            <br>\n            <strong>Output:</strong> <span ng-bind=\"columnName(name)\"></span>\n          </div>\n        </file>\n      </example>\n     */\n    readableColumnName: function (columnName) {\n      // Convert underscores to spaces\n      if (typeof(columnName) === 'undefined' || columnName === undefined || columnName === null) { return columnName; }\n\n      if (typeof(columnName) !== 'string') {\n        columnName = String(columnName);\n      }\n\n      return columnName.replace(/_+/g, ' ')\n        // Replace a completely all-capsed word with a first-letter-capitalized version\n        .replace(/^[A-Z]+$/, function (match) {\n          return angular.lowercase(angular.uppercase(match.charAt(0)) + match.slice(1));\n        })\n        // Capitalize the first letter of words\n        .replace(/(\\w+)/g, function (match) {\n          return angular.uppercase(match.charAt(0)) + match.slice(1);\n        })\n        // Put a space in between words that have partial capilizations (i.e. 'firstName' becomes 'First Name')\n        // .replace(/([A-Z]|[A-Z]\\w+)([A-Z])/g, \"$1 $2\");\n        // .replace(/(\\w+?|\\w)([A-Z])/g, \"$1 $2\");\n        .replace(/(\\w+?(?=[A-Z]))/g, '$1 ');\n    },\n\n    /**\n     * @ngdoc method\n     * @name getColumnsFromData\n     * @methodOf ui.grid.service:GridUtil\n     * @description Return a list of column names, given a data set\n     *\n     * @param {string} data Data array for grid\n     * @returns {Object} Column definitions with field accessor and column name\n     *\n     * @example\n       <pre>\n         var data = [\n           { firstName: 'Bob', lastName: 'Jones' },\n           { firstName: 'Frank', lastName: 'Smith' }\n         ];\n\n         var columnDefs = GridUtil.getColumnsFromData(data, excludeProperties);\n\n         columnDefs == [\n          {\n            field: 'firstName',\n            name: 'First Name'\n          },\n          {\n            field: 'lastName',\n            name: 'Last Name'\n          }\n         ];\n       </pre>\n     */\n    getColumnsFromData: function (data, excludeProperties) {\n      var columnDefs = [];\n\n      if (!data || typeof(data[0]) === 'undefined' || data[0] === undefined) { return []; }\n      if (angular.isUndefined(excludeProperties)) { excludeProperties = []; }\n\n      var item = data[0];\n      \n      angular.forEach(item,function (prop, propName) {\n        if ( excludeProperties.indexOf(propName) === -1){\n          columnDefs.push({\n            name: propName\n          });\n        }\n      });\n\n      return columnDefs;\n    },\n\n    /**\n     * @ngdoc method\n     * @name newId\n     * @methodOf ui.grid.service:GridUtil\n     * @description Return a unique ID string\n     *\n     * @returns {string} Unique string\n     *\n     * @example\n       <pre>\n        var id = GridUtil.newId();\n\n        # 1387305700482;\n       </pre>\n     */\n    newId: (function() {\n      var seedId = new Date().getTime();\n      return function() {\n          return seedId += 1;\n      };\n    })(),\n\n\n    /**\n     * @ngdoc method\n     * @name getTemplate\n     * @methodOf ui.grid.service:GridUtil\n     * @description Get's template from cache / element / url\n     *\n     * @param {string|element|promise} Either a string representing the template id, a string representing the template url,\n     *   an jQuery/Angualr element, or a promise that returns the template contents to use.\n     * @returns {object} a promise resolving to template contents\n     *\n     * @example\n     <pre>\n     GridUtil.getTemplate(url).then(function (contents) {\n          alert(contents);\n        })\n     </pre>\n     */\n    getTemplate: function (template) {\n      // Try to fetch the template out of the templateCache\n      if ($templateCache.get(template)) {\n        return s.postProcessTemplate($templateCache.get(template));\n      }\n\n      // See if the template is itself a promise\n      if (template.hasOwnProperty('then')) {\n        return template.then(s.postProcessTemplate);\n      }\n\n      // If the template is an element, return the element\n      try {\n        if (angular.element(template).length > 0) {\n          return $q.when(template).then(s.postProcessTemplate);\n        }\n      }\n      catch (err){\n        //do nothing; not valid html\n      }\n\n      s.logDebug('fetching url', template);\n\n      // Default to trying to fetch the template as a url with $http\n      return $http({ method: 'GET', url: template})\n        .then(\n          function (result) {\n            var templateHtml = result.data.trim();\n            //put in templateCache for next call\n            $templateCache.put(template, templateHtml);\n            return templateHtml;\n          },\n          function (err) {\n            throw new Error(\"Could not get template \" + template + \": \" + err);\n          }\n        )\n        .then(s.postProcessTemplate);\n    },\n\n    // \n    postProcessTemplate: function (template) {\n      var startSym = $interpolate.startSymbol(),\n          endSym = $interpolate.endSymbol();\n\n      // If either of the interpolation symbols have been changed, we need to alter this template\n      if (startSym !== '{{' || endSym !== '}}') {\n        template = template.replace(/\\{\\{/g, startSym);\n        template = template.replace(/\\}\\}/g, endSym);\n      }\n\n      return $q.when(template);\n    },\n\n    /**\n     * @ngdoc method\n     * @name guessType\n     * @methodOf ui.grid.service:GridUtil\n     * @description guesses the type of an argument\n     *\n     * @param {string/number/bool/object} item variable to examine\n     * @returns {string} one of the following\n     * 'string'\n     * 'boolean'\n     * 'number'\n     * 'date'\n     * 'object'\n     */\n    guessType : function (item) {\n      var itemType = typeof(item);\n\n      // Check for numbers and booleans\n      switch (itemType) {\n        case \"number\":\n        case \"boolean\":\n        case \"string\":\n          return itemType;\n        default:\n          if (angular.isDate(item)) {\n            return \"date\";\n          }\n          return \"object\";\n      }\n    },\n\n\n  /**\n    * @ngdoc method\n    * @name elementWidth\n    * @methodOf ui.grid.service:GridUtil\n    *\n    * @param {element} element DOM element\n    * @param {string} [extra] Optional modifier for calculation. Use 'margin' to account for margins on element\n    *\n    * @returns {number} Element width in pixels, accounting for any borders, etc.\n    */\n    elementWidth: function (elem) {\n      \n    },\n\n    /**\n    * @ngdoc method\n    * @name elementHeight\n    * @methodOf ui.grid.service:GridUtil\n    *\n    * @param {element} element DOM element\n    * @param {string} [extra] Optional modifier for calculation. Use 'margin' to account for margins on element\n    *\n    * @returns {number} Element height in pixels, accounting for any borders, etc.\n    */\n    elementHeight: function (elem) {\n      \n    },\n\n    // Thanks to http://stackoverflow.com/a/13382873/888165\n    getScrollbarWidth: function() {\n        var outer = document.createElement(\"div\");\n        outer.style.visibility = \"hidden\";\n        outer.style.width = \"100px\";\n        outer.style.msOverflowStyle = \"scrollbar\"; // needed for WinJS apps\n\n        document.body.appendChild(outer);\n\n        var widthNoScroll = outer.offsetWidth;\n        // force scrollbars\n        outer.style.overflow = \"scroll\";\n\n        // add innerdiv\n        var inner = document.createElement(\"div\");\n        inner.style.width = \"100%\";\n        outer.appendChild(inner);        \n\n        var widthWithScroll = inner.offsetWidth;\n\n        // remove divs\n        outer.parentNode.removeChild(outer);\n\n        return widthNoScroll - widthWithScroll;\n    },\n\n    swap: function( elem, options, callback, args ) {\n      var ret, name,\n              old = {};\n\n      // Remember the old values, and insert the new ones\n      for ( name in options ) {\n        old[ name ] = elem.style[ name ];\n        elem.style[ name ] = options[ name ];\n      }\n\n      ret = callback.apply( elem, args || [] );\n\n      // Revert the old values\n      for ( name in options ) {\n        elem.style[ name ] = old[ name ];\n      }\n\n      return ret;\n    },\n\n    fakeElement: function( elem, options, callback, args ) {\n      var ret, name,\n          newElement = angular.element(elem).clone()[0];\n\n      for ( name in options ) {\n        newElement.style[ name ] = options[ name ];\n      }\n\n      angular.element(document.body).append(newElement);\n\n      ret = callback.call( newElement, newElement );\n\n      angular.element(newElement).remove();\n\n      return ret;\n    },\n\n    /**\n    * @ngdoc method\n    * @name normalizeWheelEvent\n    * @methodOf ui.grid.service:GridUtil\n    *\n    * @param {event} event A mouse wheel event\n    *\n    * @returns {event} A normalized event\n    *\n    * @description\n    * Given an event from this list:\n    *\n    * `wheel, mousewheel, DomMouseScroll, MozMousePixelScroll`\n    *\n    * \"normalize\" it\n    * so that it stays consistent no matter what browser it comes from (i.e. scale it correctly and make sure the direction is right.)\n    */\n    normalizeWheelEvent: function (event) {\n      // var toFix = ['wheel', 'mousewheel', 'DOMMouseScroll', 'MozMousePixelScroll'];\n      // var toBind = 'onwheel' in document || document.documentMode >= 9 ? ['wheel'] : ['mousewheel', 'DomMouseScroll', 'MozMousePixelScroll'];\n      var lowestDelta, lowestDeltaXY;\n      \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          absDeltaXY = 0,\n          fn;\n\n      // event = $.event.fix(orgEvent);\n      // event.type = 'mousewheel';\n\n      // NOTE: jQuery masks the event and stores it in the event as originalEvent\n      if (orgEvent.originalEvent) {\n        orgEvent = orgEvent.originalEvent;\n      }\n\n      // Old school scrollwheel delta\n      if ( orgEvent.wheelDelta ) { delta = orgEvent.wheelDelta; }\n      if ( orgEvent.detail )     { delta = orgEvent.detail * -1; }\n\n      // At a minimum, setup the deltaY to be delta\n      deltaY = delta;\n\n      // Firefox < 17 related to DOMMouseScroll event\n      if ( orgEvent.axis !== undefined && orgEvent.axis === orgEvent.HORIZONTAL_AXIS ) {\n          deltaY = 0;\n          deltaX = delta * -1;\n      }\n\n      // New school wheel delta (wheel event)\n      if ( orgEvent.deltaY ) {\n          deltaY = orgEvent.deltaY * -1;\n          delta  = deltaY;\n      }\n      if ( orgEvent.deltaX ) {\n          deltaX = orgEvent.deltaX;\n          delta  = deltaX * -1;\n      }\n\n      // Webkit\n      if ( orgEvent.wheelDeltaY !== undefined ) { deltaY = orgEvent.wheelDeltaY; }\n      if ( orgEvent.wheelDeltaX !== undefined ) { deltaX = orgEvent.wheelDeltaX; }\n\n      // Look for lowest delta to normalize the delta values\n      absDelta = Math.abs(delta);\n      if ( !lowestDelta || absDelta < lowestDelta ) { lowestDelta = absDelta; }\n      absDeltaXY = Math.max(Math.abs(deltaY), Math.abs(deltaX));\n      if ( !lowestDeltaXY || absDeltaXY < lowestDeltaXY ) { lowestDeltaXY = absDeltaXY; }\n\n      // Get a whole value for the deltas\n      fn     = delta > 0 ? 'floor' : 'ceil';\n      delta  = Math[fn](delta  / lowestDelta);\n      deltaX = Math[fn](deltaX / lowestDeltaXY);\n      deltaY = Math[fn](deltaY / lowestDeltaXY);\n\n      return {\n        delta: delta,\n        deltaX: deltaX,\n        deltaY: deltaY\n      };\n    },\n\n    // Stolen from Modernizr\n    // TODO: make this, and everythign that flows from it, robust\n    //http://www.stucox.com/blog/you-cant-detect-a-touchscreen/\n    isTouchEnabled: function() {\n      var bool;\n\n      if (('ontouchstart' in $window) || $window.DocumentTouch && $document instanceof DocumentTouch) {\n        bool = true;\n      }\n\n      return bool;\n    },\n\n    isNullOrUndefined: function(obj) {\n      if (obj === undefined || obj === null) {\n        return true;\n      }\n      return false;\n    },\n\n    endsWith: function(str, suffix) {\n      if (!str || !suffix || typeof str !== \"string\") {\n        return false;\n      }\n      return str.indexOf(suffix, str.length - suffix.length) !== -1;\n    },\n\n    arrayContainsObjectWithProperty: function(array, propertyName, propertyValue) {\n        var found = false;\n        angular.forEach(array, function (object) {\n            if (object[propertyName] === propertyValue) {\n                found = true;\n            }\n        });\n        return found;\n    },\n\n    // Shim requestAnimationFrame\n    requestAnimationFrame: $window.requestAnimationFrame && $window.requestAnimationFrame.bind($window) ||\n                           $window.webkitRequestAnimationFrame && $window.webkitRequestAnimationFrame.bind($window) ||\n                           function(fn) {\n                             return $timeout(fn, 10, false);\n                           },\n\n    numericAndNullSort: function (a, b) {\n      if (a === null) { return 1; }\n      if (b === null) { return -1; }\n      if (a === null && b === null) { return 0; }\n      return a - b;\n    },\n\n    // Disable ngAnimate animations on an element\n    disableAnimations: function (element) {\n      var $animate;\n      try {\n        $animate = $injector.get('$animate');\n        $animate.enabled(false, element);\n      }\n      catch (e) {}\n    },\n\n    enableAnimations: function (element) {\n      var $animate;\n      try {\n        $animate = $injector.get('$animate');\n        $animate.enabled(true, element);\n        return $animate;\n      }\n      catch (e) {}\n    },\n\n    // Blatantly stolen from Angular as it isn't exposed (yet. 2.0 maybe?)\n    nextUid: function nextUid() {\n      var index = uid.length;\n      var digit;\n\n      while (index) {\n        index--;\n        digit = uid[index].charCodeAt(0);\n        if (digit === 57 /*'9'*/) {\n          uid[index] = 'A';\n          return uidPrefix + uid.join('');\n        }\n        if (digit === 90  /*'Z'*/) {\n          uid[index] = '0';\n        } else {\n          uid[index] = String.fromCharCode(digit + 1);\n          return uidPrefix + uid.join('');\n        }\n      }\n      uid.unshift('0');\n\n      return uidPrefix + uid.join('');\n    },\n\n    // Blatantly stolen from Angular as it isn't exposed (yet. 2.0 maybe?)\n    hashKey: function hashKey(obj) {\n      var objType = typeof obj,\n          key;\n\n      if (objType === 'object' && obj !== null) {\n        if (typeof (key = obj.$$hashKey) === 'function') {\n          // must invoke on object to keep the right this\n          key = obj.$$hashKey();\n        }\n        else if (typeof(obj.$$hashKey) !== 'undefined' && obj.$$hashKey) {\n          key = obj.$$hashKey;\n        }\n        else if (key === undefined) {\n          key = obj.$$hashKey = s.nextUid();\n        }\n      }\n      else {\n        key = obj;\n      }\n\n      return objType + ':' + key;\n    },\n\n    resetUids: function () {\n      uid = ['0', '0', '0'];\n    },\n    \n    /**\n     * @ngdoc method\n     * @methodOf ui.grid.service:GridUtil\n     * @name logError\n     * @description wraps the $log method, allowing us to choose different\n     * treatment within ui-grid if we so desired.  At present we only log\n     * error messages if uiGridConstants.LOG_ERROR_MESSAGES is set to true\n     * @param {string} logMessage message to be logged to the console\n     * \n     */\n    logError: function( logMessage ){\n      if ( uiGridConstants.LOG_ERROR_MESSAGES ){\n        $log.error( logMessage );\n      }\n    },\n\n    /**\n     * @ngdoc method\n     * @methodOf ui.grid.service:GridUtil\n     * @name logWarn\n     * @description wraps the $log method, allowing us to choose different\n     * treatment within ui-grid if we so desired.  At present we only log\n     * warning messages if uiGridConstants.LOG_WARN_MESSAGES is set to true\n     * @param {string} logMessage message to be logged to the console\n     * \n     */\n    logWarn: function( logMessage ){\n      if ( uiGridConstants.LOG_WARN_MESSAGES ){\n        $log.warn( logMessage );\n      }\n    },\n\n    /**\n     * @ngdoc method\n     * @methodOf ui.grid.service:GridUtil\n     * @name logDebug\n     * @description wraps the $log method, allowing us to choose different\n     * treatment within ui-grid if we so desired.  At present we only log\n     * debug messages if uiGridConstants.LOG_DEBUG_MESSAGES is set to true\n     * \n     */\n    logDebug: function() {\n      if ( uiGridConstants.LOG_DEBUG_MESSAGES ){\n        $log.debug.apply($log, arguments);\n      }\n    }\n\n  };\n\n  ['width', 'height'].forEach(function (name) {\n    var capsName = angular.uppercase(name.charAt(0)) + name.substr(1);\n    s['element' + capsName] = function (elem, extra) {\n      var e = elem;\n      if (e && typeof(e.length) !== 'undefined' && e.length) {\n        e = elem[0];\n      }\n\n      if (e) {\n        var styles = getStyles(e);\n        return e.offsetWidth === 0 && rdisplayswap.test(styles.display) ?\n                  s.fakeElement(e, cssShow, function(newElm) {\n                    return getWidthOrHeight( newElm, name, extra );\n                  }) :\n                  getWidthOrHeight( e, name, extra );\n      }\n      else {\n        return null;\n      }\n    };\n\n    s['outerElement' + capsName] = function (elem, margin) {\n      return elem ? s['element' + capsName].call(this, elem, margin ? 'margin' : 'border') : null;\n    };\n  });\n\n  // http://stackoverflow.com/a/24107550/888165\n  s.closestElm = function closestElm(el, selector) {\n    if (typeof(el.length) !== 'undefined' && el.length) {\n      el = el[0];\n    }\n\n    var matchesFn;\n\n    // find vendor prefix\n    ['matches','webkitMatchesSelector','mozMatchesSelector','msMatchesSelector','oMatchesSelector'].some(function(fn) {\n        if (typeof document.body[fn] === 'function') {\n            matchesFn = fn;\n            return true;\n        }\n        return false;\n    });\n\n    // traverse parents\n    var parent;\n    while (el !== null) {\n      parent = el.parentElement;\n      if (parent !== null && parent[matchesFn](selector)) {\n          return parent;\n      }\n      el = parent;\n    }\n\n    return null;\n  };\n\n  s.type = function (obj) {\n    var text = Function.prototype.toString.call(obj.constructor);\n    return text.match(/function (.*?)\\(/)[1];\n  };\n\n  s.getBorderSize = function getBorderSize(elem, borderType) {\n    if (typeof(elem.length) !== 'undefined' && elem.length) {\n      elem = elem[0];\n    }\n\n    var styles = getStyles(elem);\n\n    // If a specific border is supplied, like 'top', read the 'borderTop' style property\n    if (borderType) {\n      borderType = 'border' + borderType.charAt(0).toUpperCase() + borderType.slice(1);\n    }\n    else {\n      borderType = 'border';\n    }\n\n    borderType += 'Width';\n\n    var val = parseInt(styles[borderType], 10);\n\n    if (isNaN(val)) {\n      return 0;\n    }\n    else {\n      return val;\n    }\n  };\n\n  // http://stackoverflow.com/a/22948274/888165\n  // TODO: Opera? Mobile?\n  s.detectBrowser = function detectBrowser() {\n    var userAgent = $window.navigator.userAgent;\n\n    var browsers = {chrome: /chrome/i, safari: /safari/i, firefox: /firefox/i, ie: /internet explorer|trident\\//i};\n\n    for (var key in browsers) {\n      if (browsers[key].test(userAgent)) {\n        return key;\n      }\n    }\n\n    return 'unknown';\n  };\n\n  /**\n    * @ngdoc method\n    * @name normalizeScrollLeft\n    * @methodOf ui.grid.service:GridUtil\n    *\n    * @param {element} element The element to get the `scrollLeft` from.\n    *\n    * @returns {int} A normalized scrollLeft value for the current browser.\n    *\n    * @description\n    * Browsers currently handle RTL in different ways, resulting in inconsistent scrollLeft values. This method normalizes them\n    */\n  s.normalizeScrollLeft = function normalizeScrollLeft(element) {\n    if (typeof(element.length) !== 'undefined' && element.length) {\n      element = element[0];\n    }\n\n    var browser = s.detectBrowser();\n\n    var scrollLeft = element.scrollLeft;\n    \n    var dir = s.getStyles(element)['direction'];\n\n    // IE stays normal in RTL\n    if (browser === 'ie') {\n      return scrollLeft;\n    }\n    // Chrome doesn't alter the scrollLeft value. So with RTL on a 400px-wide grid, the right-most position will still be 400 and the left-most will still be 0;\n    else if (browser === 'chrome') {\n      if (dir === 'rtl') {\n        // Get the max scroll for the element\n        var maxScrollLeft = element.scrollWidth - element.clientWidth;\n\n        // Subtract the current scroll amount from the max scroll\n        return maxScrollLeft - scrollLeft;\n      }\n      else {\n        return scrollLeft;\n      }\n    }\n    // Firefox goes negative!\n    else if (browser === 'firefox') {\n      return Math.abs(scrollLeft);\n    }\n    else {\n      // TODO(c0bra): Handle other browsers? Android? iOS? Opera?\n      return scrollLeft;\n    }\n  };\n\n  /**\n  * @ngdoc method\n  * @name normalizeScrollLeft\n  * @methodOf ui.grid.service:GridUtil\n  *\n  * @param {element} element The element to normalize the `scrollLeft` value for\n  * @param {int} scrollLeft The `scrollLeft` value to denormalize.\n  *\n  * @returns {int} A normalized scrollLeft value for the current browser.\n  *\n  * @description\n  * Browsers currently handle RTL in different ways, resulting in inconsistent scrollLeft values. This method denormalizes a value for the current browser.\n  */\n  s.denormalizeScrollLeft = function denormalizeScrollLeft(element, scrollLeft) {\n    if (typeof(element.length) !== 'undefined' && element.length) {\n      element = element[0];\n    }\n\n    var browser = s.detectBrowser();\n\n    var dir = s.getStyles(element)['direction'];\n\n    // IE stays normal in RTL\n    if (browser === 'ie') {\n      return scrollLeft;\n    }\n    // Chrome doesn't alter the scrollLeft value. So with RTL on a 400px-wide grid, the right-most position will still be 400 and the left-most will still be 0;\n    else if (browser === 'chrome') {\n      if (dir === 'rtl') {\n        // Get the max scroll for the element\n        var maxScrollLeft = element.scrollWidth - element.clientWidth;\n\n        // Subtract the current scroll amount from the max scroll\n        return maxScrollLeft - scrollLeft;\n      }\n      else {\n        return scrollLeft;\n      }\n    }\n    // Firefox goes negative!\n    else if (browser === 'firefox') {\n      if (dir === 'rtl') {\n        return scrollLeft * -1;\n      }\n      else {\n        return scrollLeft;\n      }\n    }\n    else {\n      // TODO(c0bra): Handle other browsers? Android? iOS? Opera?\n      return scrollLeft;\n    }\n  };\n\n    /**\n     * @ngdoc method\n     * @name preEval\n     * @methodOf ui.grid.service:GridUtil\n     *\n     * @param {string} path Path to evaluate\n     *\n     * @returns {string} A path that is normalized.\n     *\n     * @description\n     * Takes a field path and converts it to bracket notation to allow for special characters in path\n     * @example\n     * <pre>\n     * gridUtil.preEval('property') == 'property'\n     * gridUtil.preEval('nested.deep.prop-erty') = \"nested['deep']['prop-erty']\"\n     * </pre>\n     */\n  s.preEval = function (path) {\n    var m = uiGridConstants.BRACKET_REGEXP.exec(path);\n    if (m) {\n      return (m[1] ? s.preEval(m[1]) : m[1]) + m[2] + (m[3] ? s.preEval(m[3]) : m[3]);\n    } else {\n      path = path.replace(uiGridConstants.APOS_REGEXP, '\\\\\\'');\n      var parts = path.split(uiGridConstants.DOT_REGEXP);\n      var preparsed = [parts.shift()];    // first item must be var notation, thus skip\n      angular.forEach(parts, function (part) {\n        preparsed.push(part.replace(uiGridConstants.FUNC_REGEXP, '\\']$1'));\n      });\n      return preparsed.join('[\\'');\n    }\n  };\n\n  /**\n   * @ngdoc method\n   * @name debounce\n   * @methodOf ui.grid.service:GridUtil\n   *\n   * @param {function} func function to debounce\n   * @param {number} wait milliseconds to delay\n   * @param {bool} immediate execute before delay\n   *\n   * @returns {function} A function that can be executed as debounced function\n   *\n   * @description\n   * Copied from https://github.com/shahata/angular-debounce\n   * Takes a function, decorates it to execute only 1 time after multiple calls, and returns the decorated function\n   * @example\n   * <pre>\n   * var debouncedFunc =  gridUtil.debounce(function(){alert('debounced');}, 500);\n   * debouncedFunc();\n   * debouncedFunc();\n   * debouncedFunc();\n   * </pre>\n   */\n  s.debounce =  function (func, wait, immediate) {\n    var timeout, args, context, result;\n    function debounce() {\n      /* jshint validthis:true */\n      context = this;\n      args = arguments;\n      var later = function () {\n        timeout = null;\n        if (!immediate) {\n          result = func.apply(context, args);\n        }\n      };\n      var callNow = immediate && !timeout;\n      if (timeout) {\n        $timeout.cancel(timeout);\n      }\n      timeout = $timeout(later, wait);\n      if (callNow) {\n        result = func.apply(context, args);\n      }\n      return result;\n    }\n    debounce.cancel = function () {\n      $timeout.cancel(timeout);\n      timeout = null;\n    };\n    return debounce;\n  };\n\n  /**\n   * @ngdoc method\n   * @name throttle\n   * @methodOf ui.grid.service:GridUtil\n   *\n   * @param {function} func function to throttle\n   * @param {number} wait milliseconds to delay after first trigger\n   * @param {Object} params to use in throttle.\n   *\n   * @returns {function} A function that can be executed as throttled function\n   *\n   * @description\n   * Adapted from debounce function (above)\n   * Potential keys for Params Object are:\n   *    trailing (bool) - whether to trigger after throttle time ends if called multiple times\n   * @example\n   * <pre>\n   * var throttledFunc =  gridUtil.throttle(function(){console.log('throttled');}, 500, {trailing: true});\n   * throttledFunc(); //=> logs throttled\n   * throttledFunc(); //=> queues attempt to log throttled for ~500ms (since trailing param is truthy)\n   * throttledFunc(); //=> updates arguments to keep most-recent request, but does not do anything else.\n   * </pre>\n   */\n  s.throttle = function(func, wait, options){\n    options = options || {};\n    var lastCall = 0, queued = null, context, args;\n\n    function runFunc(endDate){\n      lastCall = +new Date();\n      func.apply(context, args);\n      $timeout(function(){ queued = null; }, 0);\n    }\n\n    return function(){\n      /* jshint validthis:true */\n      context = this;\n      args = arguments;\n      if (queued === null){\n        var sinceLast = +new Date() - lastCall;\n        if (sinceLast > wait){\n          runFunc();\n        }\n        else if (options.trailing){\n          queued = $timeout(runFunc, wait - sinceLast);\n        }\n      }\n    };\n  };\n\n  return s;\n}]);\n\n// Add 'px' to the end of a number string if it doesn't have it already\nmodule.filter('px', function() {\n  return function(str) {\n    if (str.match(/^[\\d\\.]+$/)) {\n      return str + 'px';\n    }\n    else {\n      return str;\n    }\n  };\n});\n\n})();\n\n(function(){\n  angular.module('ui.grid').config(['$provide', function($provide) {\n    $provide.decorator('i18nService', ['$delegate', function($delegate) {\n      $delegate.add('da', {\n        aggregate:{\n          label: 'artikler'\n        },\n        groupPanel:{\n          description: 'Grupér rækker udfra en kolonne ved at trække dens overskift hertil.'\n        },\n        search:{\n          placeholder: 'Søg...',\n          showingItems: 'Viste rækker:',\n          selectedItems: 'Valgte rækker:',\n          totalItems: 'Rækker totalt:',\n          size: 'Side størrelse:',\n          first: 'Første side',\n          next: 'Næste side',\n          previous: 'Forrige side',\n          last: 'Sidste side'\n        },\n        menu:{\n          text: 'Vælg kolonner:'\n        },\n        column: {\n          hide: 'Skjul kolonne'\n        },\n        aggregation: {\n          count: 'samlede rækker: ',\n          sum: 'smalede: ',\n          avg: 'gns: ',\n          min: 'min: ',\n          max: 'max: '\n        },\n        gridMenu: {\n          columns: 'Columns:',\n          importerTitle: 'Import file',\n          exporterAllAsCsv: 'Export all data as csv',\n          exporterVisibleAsCsv: 'Export visible data as csv',\n          exporterSelectedAsCsv: 'Export selected data as csv',\n          exporterAllAsPdf: 'Export all data as pdf',\n          exporterVisibleAsPdf: 'Export visible data as pdf',\n          exporterSelectedAsPdf: 'Export selected data as pdf'\n        },\n        importer: {\n          noHeaders: 'Column names were unable to be derived, does the file have a header?',\n          noObjects: 'Objects were not able to be derived, was there data in the file other than headers?',\n          invalidCsv: 'File was unable to be processed, is it valid CSV?',\n          invalidJson: 'File was unable to be processed, is it valid Json?',\n          jsonNotArray: 'Imported json file must contain an array, aborting.'\n        }\n      });\n      return $delegate;\n    }]);\n  }]);\n})();\n(function () {\n  angular.module('ui.grid').config(['$provide', function ($provide) {\n    $provide.decorator('i18nService', ['$delegate', function ($delegate) {\n      $delegate.add('de', {\n        aggregate: {\n          label: 'eintrag'\n        },\n        groupPanel: {\n          description: 'Ziehen Sie eine Spaltenüberschrift hierhin, um nach dieser Spalte zu gruppieren.'\n        },\n        search: {\n          placeholder: 'Suche...',\n          showingItems: 'Zeige Einträge:',\n          selectedItems: 'Ausgewählte Einträge:',\n          totalItems: 'Einträge gesamt:',\n          size: 'Einträge pro Seite:',\n          first: 'Erste Seite',\n          next: 'Nächste Seite',\n          previous: 'Vorherige Seite',\n          last: 'Letzte Seite'\n        },\n        menu: {\n          text: 'Spalten auswählen:'\n        },\n        sort: {\n          ascending: 'aufsteigend sortieren',\n          descending: 'absteigend sortieren',\n          remove: 'Sortierung zurücksetzen'\n        },\n        column: {\n          hide: 'Spalte ausblenden'\n        },\n        aggregation: {\n          count: 'Zeilen insgesamt: ',\n          sum: 'gesamt: ',\n          avg: 'Durchschnitt: ',\n          min: 'min: ',\n          max: 'max: '\n        },\n        gridMenu: {\n          columns: 'Spalten:',\n          importerTitle: 'Datei importieren',\n          exporterAllAsCsv: 'Alle Daten als CSV exportieren',\n          exporterVisibleAsCsv: 'sichtbare Daten als CSV exportieren',\n          exporterSelectedAsCsv: 'markierte Daten als CSV exportieren',\n          exporterAllAsPdf: 'Alle Daten als PDF exportieren',\n          exporterVisibleAsPdf: 'sichtbare Daten als PDF exportieren',\n          exporterSelectedAsPdf: 'markierte Daten als CSV exportieren'\n        },\n        importer: {\n          noHeaders: 'Es konnten keine Spaltennamen ermittelt werden. Sind in der Datei Spaltendefinitionen enthalten?',\n          noObjects: 'Es konnten keine Zeileninformationen gelesen werden, Sind in der Datei außer den Spaltendefinitionen auch Daten enthalten?',\n          invalidCsv: 'Die Datei konnte nicht eingelesen werden, ist es eine gültige CSV-Datei?',\n          invalidJson: 'Die Datei konnte nicht eingelesen werden. Enthält sie gültiges JSON?',\n          jsonNotArray: 'Die importierte JSON-Datei muß ein Array enthalten. Breche Import ab.'\n        }\n      });\n      return $delegate;\n    }]);\n  }]);\n})();\n\n(function () {\n  angular.module('ui.grid').config(['$provide', function($provide) {\n    $provide.decorator('i18nService', ['$delegate', function($delegate) {\n      $delegate.add('en', {\n        aggregate: {\n          label: 'items'\n        },\n        groupPanel: {\n          description: 'Drag a column header here and drop it to group by that column.'\n        },\n        search: {\n          placeholder: 'Search...',\n          showingItems: 'Showing Items:',\n          selectedItems: 'Selected Items:',\n          totalItems: 'Total Items:',\n          size: 'Page Size:',\n          first: 'First Page',\n          next: 'Next Page',\n          previous: 'Previous Page',\n          last: 'Last Page'\n        },\n        menu: {\n          text: 'Choose Columns:'\n        },\n        sort: {\n          ascending: 'Sort Ascending',\n          descending: 'Sort Descending',\n          remove: 'Remove Sort'\n        },\n        column: {\n          hide: 'Hide Column'\n        },\n        aggregation: {\n          count: 'total rows: ',\n          sum: 'total: ',\n          avg: 'avg: ',\n          min: 'min: ',\n          max: 'max: '\n        },\n        pinning: {\n         pinLeft: 'Pin Left',\n          pinRight: 'Pin Right',\n          unpin: 'Unpin'\n        },\n        gridMenu: {\n          columns: 'Columns:',\n          importerTitle: 'Import file',\n          exporterAllAsCsv: 'Export all data as csv',\n          exporterVisibleAsCsv: 'Export visible data as csv',\n          exporterSelectedAsCsv: 'Export selected data as csv',\n          exporterAllAsPdf: 'Export all data as pdf',\n          exporterVisibleAsPdf: 'Export visible data as pdf',\n          exporterSelectedAsPdf: 'Export selected data as pdf'\n        },\n        importer: {\n          noHeaders: 'Column names were unable to be derived, does the file have a header?',\n          noObjects: 'Objects were not able to be derived, was there data in the file other than headers?',\n          invalidCsv: 'File was unable to be processed, is it valid CSV?',\n          invalidJson: 'File was unable to be processed, is it valid Json?',\n          jsonNotArray: 'Imported json file must contain an array, aborting.'\n        },\n        pagination: {\n          sizes: 'items per page',\n          totalItems: 'items'\n        }\n      });\n      return $delegate;\n    }]);\n  }]);\n})();\n\n(function () {\n  angular.module('ui.grid').config(['$provide', function($provide) {\n    $provide.decorator('i18nService', ['$delegate', function($delegate) {\n      $delegate.add('es', {\n        aggregate: {\n          label: 'Artículos'\n        },\n        groupPanel: {\n          description: 'Arrastre un encabezado de columna aquí y suéltelo para agrupar por esa columna.'\n        },\n        search: {\n          placeholder: 'Buscar...',\n          showingItems: 'Artículos Mostrados:',\n          selectedItems: 'Artículos Seleccionados:',\n          totalItems: 'Artículos Totales:',\n          size: 'Tamaño de Página:',\n          first: 'Primera Página',\n          next: 'Página Siguiente',\n          previous: 'Página Anterior',\n          last: 'Última Página'\n        },\n        menu: {\n          text: 'Elegir columnas:'\n        },\n        sort: {\n          ascending: 'Orden Ascendente',\n          descending: 'Orden Descendente',\n          remove: 'Sin Ordenar'\n        },\n        column: {\n          hide: 'Ocultar la columna'\n        },\n        aggregation: {\n          count: 'filas totales: ',\n          sum: 'total: ',\n          avg: 'media: ',\n          min: 'min: ',\n          max: 'max: '\n        },\n        pinning: {\n          pinLeft: 'Fijar a la Izquierda',\n          pinRight: 'Fijar a la Derecha',\n          unpin: 'Quitar Fijación'\n        },\n        gridMenu: {\n          columns: 'Columnas:',\n          importerTitle: 'Importar archivo',\n          exporterAllAsCsv: 'Exportar todo como csv',\n          exporterVisibleAsCsv: 'Exportar vista como csv',\n          exporterSelectedAsCsv: 'Exportar selección como csv',\n          exporterAllAsPdf: 'Exportar todo como pdf',\n          exporterVisibleAsPdf: 'Exportar vista como pdf',\n          exporterSelectedAsPdf: 'Exportar selección como pdf'\n        },\n        importer: {\n          noHeaders: 'No fue posible derivar los nombres de las columnas, ¿tiene encabezados el archivo?',\n          noObjects: 'No fue posible obtener registros, ¿contiene datos el archivo, aparte de los encabezados?',\n          invalidCsv: 'No fue posible procesar el archivo, ¿es un CSV válido?',\n          invalidJson: 'No fue posible procesar el archivo, ¿es un Json válido?',\n          jsonNotArray: 'El archivo json importado debe contener un array, abortando.'\n        }\n      });\n      return $delegate;\n    }]);\n}]);\n})();\n\n(function () {\n  angular.module('ui.grid').config(['$provide', function($provide) {\n    $provide.decorator('i18nService', ['$delegate', function($delegate) {\n      $delegate.add('fa', {\n        aggregate: {\n          label: 'موردها'\n        },\n        groupPanel: {\n          description: 'یک عنوان ستون اینجا را بردار و به گروهی از آن ستون بیانداز.'\n        },\n        search: {\n          placeholder: 'جستجو...',\n          showingItems: 'نمایش موردها:',\n          selectedItems: 'موردهای انتخاب\\u200cشده:',\n          totalItems: 'همهٔ موردها:',\n          size: 'اندازهٔ صفحه:',\n          first: 'صفحهٔ اول',\n          next: 'صفحهٔ بعد',\n          previous: 'صفحهٔ قبل',\n          last: 'آخرین صفحه'\n        },\n        menu: {\n          text: 'انتخاب ستون\\u200cها:'\n        },\n        column: {\n          hide: 'ستون پنهان کن'\n        },\n        aggregation: {\n          count: 'total rows: ',\n          sum: 'total: ',\n          avg: 'avg: ',\n          min: 'min: ',\n          max: 'max: '\n        },\n        gridMenu: {\n          columns: 'Columns:',\n          importerTitle: 'Import file',\n          exporterAllAsCsv: 'Export all data as csv',\n          exporterVisibleAsCsv: 'Export visible data as csv',\n          exporterSelectedAsCsv: 'Export selected data as csv',\n          exporterAllAsPdf: 'Export all data as pdf',\n          exporterVisibleAsPdf: 'Export visible data as pdf',\n          exporterSelectedAsPdf: 'Export selected data as pdf'\n        },\n        importer: {\n          noHeaders: 'Column names were unable to be derived, does the file have a header?',\n          noObjects: 'Objects were not able to be derived, was there data in the file other than headers?',\n          invalidCsv: 'File was unable to be processed, is it valid CSV?',\n          invalidJson: 'File was unable to be processed, is it valid Json?',\n          jsonNotArray: 'Imported json file must contain an array, aborting.'\n        }\n      });\n      return $delegate;\n    }]);\n}]);\n})();\n(function () {\n  angular.module('ui.grid').config(['$provide', function($provide) {\n    $provide.decorator('i18nService', ['$delegate', function($delegate) {\n      $delegate.add('fi', {\n        aggregate: {\n          label: 'rivit'\n        },\n        groupPanel: {\n          description: 'Raahaa ja pudota otsikko tähän ryhmittääksesi sarakkeen mukaan.'\n        },\n        search: {\n          placeholder: 'Hae...',\n          showingItems: 'Näytetään rivejä:',\n          selectedItems: 'Valitut rivit:',\n          totalItems: 'Rivejä yht.:',\n          size: 'Näytä:',\n          first: 'Ensimmäinen sivu',\n          next: 'Seuraava sivu',\n          previous: 'Edellinen sivu',\n          last: 'Viimeinen sivu'\n        },\n        menu: {\n          text: 'Valitse sarakkeet:'\n        },\n        sort: {\n          ascending: 'Järjestä nouseva',\n          descending: 'Järjestä laskeva',\n          remove: 'Poista järjestys'\n        },\n        column: {\n          hide: 'Piilota sarake'\n        },\n        aggregation: {\n          count: 'Rivejä yht.: ',\n          sum: 'Summa: ',\n          avg: 'K.a.: ',\n          min: 'Min: ',\n          max: 'Max: '\n        },\n        pinning: {\n         pinLeft: 'Lukitse vasemmalle',\n          pinRight: 'Lukitse oikealle',\n          unpin: 'Poista lukitus'\n        },\n        gridMenu: {\n          columns: 'Sarakkeet:',\n          importerTitle: 'Tuo tiedosto',\n          exporterAllAsCsv: 'Vie tiedot csv-muodossa',\n          exporterVisibleAsCsv: 'Vie näkyvä tieto csv-muodossa',\n          exporterSelectedAsCsv: 'Vie valittu tieto csv-muodossa',\n          exporterAllAsPdf: 'Vie tiedot pdf-muodossa',\n          exporterVisibleAsPdf: 'Vie näkyvä tieto pdf-muodossa',\n          exporterSelectedAsPdf: 'Vie valittu tieto pdf-muodossa'\n        },\n        importer: {\n          noHeaders: 'Sarakkeen nimiä ei voitu päätellä, onko tiedostossa otsikkoriviä?',\n          noObjects: 'Tietoja ei voitu lukea, onko tiedostossa muuta kuin otsikkot?',\n          invalidCsv: 'Tiedostoa ei voitu käsitellä, oliko se CSV-muodossa?',\n          invalidJson: 'Tiedostoa ei voitu käsitellä, oliko se JSON-muodossa?',\n          jsonNotArray: 'Tiedosto ei sisältänyt taulukkoa, lopetetaan.'\n        }\n      });\n      return $delegate;\n    }]);\n  }]);\n})();\n\n(function () {\n  angular.module('ui.grid').config(['$provide', function($provide) {\n    $provide.decorator('i18nService', ['$delegate', function($delegate) {\n      $delegate.add('fr', {\n        aggregate: {\n          label: 'articles'\n        },\n        groupPanel: {\n          description: 'Faites glisser un en-tête de colonne ici et déposez-le vers un groupe par cette colonne.'\n        },\n        search: {\n          placeholder: 'Recherche...',\n          showingItems: 'Articles Affichage des:',\n          selectedItems: 'Éléments Articles:',\n          totalItems: 'Nombre total d\\'articles:',\n          size: 'Taille de page:',\n          first: 'Première page',\n          next: 'Page Suivante',\n          previous: 'Page précédente',\n          last: 'Dernière page'\n        },\n        menu: {\n          text: 'Choisir des colonnes:'\n        },\n        sort: {\n          ascending: 'Trier par ordre croissant',\n          descending: 'Trier par ordre décroissant',\n          remove: 'Enlever le tri'\n        },\n        column: {\n          hide: 'Cacher la colonne'\n        },\n        aggregation: {\n          count: 'total lignes: ',\n          sum: 'total: ',\n          avg: 'moy: ',\n          min: 'min: ',\n          max: 'max: '\n        },\n        pinning: {\n          pinLeft: 'Épingler à gauche',\n          pinRight: 'Épingler à droite',\n          unpin: 'Détacher'\n        },\n        gridMenu: {\n          columns: 'Colonnes:',\n          importerTitle: 'Importer un fichier',\n          exporterAllAsCsv: 'Exporter toutes les données en CSV',\n          exporterVisibleAsCsv: 'Exporter les données visibles en CSV',\n          exporterSelectedAsCsv: 'Exporter les données sélectionnées en CSV',\n          exporterAllAsPdf: 'Exporter toutes les données en PDF',\n          exporterVisibleAsPdf: 'Exporter les données visibles en PDF',\n          exporterSelectedAsPdf: 'Exporter les données sélectionnées en PDF'\n        },\n        importer: {\n          noHeaders: 'Impossible de déterminer le nom des colonnes, le fichier possède-t-il un en-tête ?',\n          noObjects: 'Aucun objet trouvé, le fichier possède-t-il des données autres que l\\'en-tête ?',\n          invalidCsv: 'Le fichier n\\'a pas pu être traité, le CSV est-il valide ?',\n          invalidJson: 'Le fichier n\\'a pas pu être traité, le JSON est-il valide ?',\n          jsonNotArray: 'Le fichier JSON importé doit contenir un tableau. Abandon.'\n        },\n        pagination: {\n          sizes: 'articles par page',\n          totalItems: 'articles'\n        }\n      });\n      return $delegate;\n    }]);\n}]);\n})();\n(function () {\n  angular.module('ui.grid').config(['$provide', function ($provide) {\n    $provide.decorator('i18nService', ['$delegate', function ($delegate) {\n      $delegate.add('he', {\n        aggregate: {\n          label: 'items'\n        },\n        groupPanel: {\n          description: 'גרור עמודה לכאן ושחרר בכדי לקבץ עמודה זו.'\n        },\n        search: {\n          placeholder: 'חפש...',\n          showingItems: 'מציג:',\n          selectedItems: 'סה\"כ נבחרו:',\n          totalItems: 'סה\"כ רשומות:',\n          size: 'תוצאות בדף:',\n          first: 'דף ראשון',\n          next: 'דף הבא',\n          previous: 'דף קודם',\n          last: 'דף אחרון'\n        },\n        menu: {\n          text: 'בחר עמודות:'\n        },\n        sort: {\n          ascending: 'סדר עולה',\n          descending: 'סדר יורד',\n          remove: 'בטל'\n        },\n        column: {\n          hide: 'טור הסתר'\n        },\n        aggregation: {\n          count: 'total rows: ',\n          sum: 'total: ',\n          avg: 'avg: ',\n          min: 'min: ',\n          max: 'max: '\n        },\n        gridMenu: {\n          columns: 'Columns:',\n          importerTitle: 'Import file',\n          exporterAllAsCsv: 'Export all data as csv',\n          exporterVisibleAsCsv: 'Export visible data as csv',\n          exporterSelectedAsCsv: 'Export selected data as csv',\n          exporterAllAsPdf: 'Export all data as pdf',\n          exporterVisibleAsPdf: 'Export visible data as pdf',\n          exporterSelectedAsPdf: 'Export selected data as pdf'\n        },\n        importer: {\n          noHeaders: 'Column names were unable to be derived, does the file have a header?',\n          noObjects: 'Objects were not able to be derived, was there data in the file other than headers?',\n          invalidCsv: 'File was unable to be processed, is it valid CSV?',\n          invalidJson: 'File was unable to be processed, is it valid Json?',\n          jsonNotArray: 'Imported json file must contain an array, aborting.'\n        }\n      });\n      return $delegate;\n    }]);\n  }]);\n})();\n(function () {\n  angular.module('ui.grid').config(['$provide', function($provide) {\n    $provide.decorator('i18nService', ['$delegate', function($delegate) {\n      $delegate.add('it', {\n        aggregate: {\n          label: 'elementi'\n        },\n        groupPanel: {\n          description: 'Trascina un\\'intestazione all\\'interno del gruppo della colonna.'\n        },\n        search: {\n          placeholder: 'Ricerca...',\n          showingItems: 'Mostra:',\n          selectedItems: 'Selezionati:',\n          totalItems: 'Totali:',\n          size: 'Tot Pagine:',\n          first: 'Prima',\n          next: 'Prossima',\n          previous: 'Precedente',\n          last: 'Ultima'\n        },\n        menu: {\n          text: 'Scegli le colonne:'\n        },\n        sort: {\n          ascending: 'Asc.',\n          descending: 'Desc.',\n          remove: 'Annulla ordinamento'\n        },\n        column: {\n          hide: 'Nascondi'\n        },\n        aggregation: {\n          count: 'righe totali: ',\n          sum: 'tot: ',\n          avg: 'media: ',\n          min: 'minimo: ',\n          max: 'massimo: '\n        },\n        pinning: {\n         pinLeft: 'Blocca a sx',\n          pinRight: 'Blocca a dx',\n          unpin: 'Blocca in alto'\n        },\n        gridMenu: {\n          columns: 'Colonne:',\n          importerTitle: 'Importa',\n          exporterAllAsCsv: 'Esporta tutti i dati in CSV',\n          exporterVisibleAsCsv: 'Esporta i dati visibili in CSV',\n          exporterSelectedAsCsv: 'Esporta i dati selezionati in CSV',\n          exporterAllAsPdf: 'Esporta tutti i dati in PDF',\n          exporterVisibleAsPdf: 'Esporta i dati visibili in PDF',\n          exporterSelectedAsPdf: 'Esporta i dati selezionati in PDF'\n        },\n        importer: {\n          noHeaders: 'Impossibile reperire i nomi delle colonne, sicuro che siano indicati all\\'interno del file?',\n          noObjects: 'Impossibile reperire gli oggetti, sicuro che siano indicati all\\'interno del file?',\n          invalidCsv: 'Impossibile elaborare il file, sicuro che sia un CSV?',\n          invalidJson: 'Impossibile elaborare il file, sicuro che sia un JSON valido?',\n          jsonNotArray: 'Errore! Il file JSON da importare deve contenere un array.'\n        }\n      });\n      return $delegate;\n    }]);\n  }]);\n})();\n(function() {\n  angular.module('ui.grid').config(['$provide', function($provide) {\n    $provide.decorator('i18nService', ['$delegate', function($delegate) {\n      $delegate.add('ja', {\n        aggregate: {\n          label: '件'\n        },\n        groupPanel: {\n          description: '列名部分をここにドラッグアンドドロップすることで列ごとにグループ分けを行うことができます。'\n        },\n        search: {\n          placeholder: '検索...',\n          showingItems: '絞込み件数:',\n          selectedItems: '選択件数:',\n          totalItems: '全件数:',\n          size: 'ページサイズ: ',\n          first: '最初のページ',\n          next: '次のページ',\n          previous: '前のページ',\n          last: '最後のページ'\n        },\n        menu: {\n          text: '列選択:'\n        },\n        sort: {\n          ascending: '昇順ソート',\n          descending: '降順ソート',\n          remove: 'ソート取消'\n        },\n        column: {\n          hide: '列を隠す'\n        },\n        aggregation: {\n          count: '合計件数: ',\n          sum: '合計: ',\n          avg: '平均: ',\n          min: '最小値: ',\n          max: '最大値: '\n        },\n        pinning: {\n          pinLeft: '左にピン留め',\n          pinRight: '右にピン留め',\n          unpin: 'ピン留め取消'\n        },\n        gridMenu: {\n          columns: '列:',\n          importerTitle: 'インポートファイル',\n          exporterAllAsCsv: '全てのデータをCSV形式でエクスポート',\n          exporterVisibleAsCsv: '絞込み済みデータをCSV形式でエクスポート',\n          exporterSelectedAsCsv: '選択しているデータをCSV形式でエクスポート',\n          exporterAllAsPdf: '全てのデータをPDFでエクスポート',\n          exporterVisibleAsPdf: '絞込み済みデータをPDFでエクスポート',\n          exporterSelectedAsPdf: '選択しているデータをPDFでエクスポート'\n        },\n        importer: {\n          noHeaders: '列名が抽出できません。ヘッダーは設定されていますか？',\n          noObjects: 'データが抽出できません。ファイルにデータは含まれていますか？',\n          invalidCsv: '処理を行うことができません。ファイルは有効なCSVファイルですか？',\n          invalidJson: '処理を行うことができません。ファイルは有効なJSONファイルですか？',\n          jsonNotArray: 'JSONファイルは配列を含んでいる必要があります。処理を中断します。'\n        },\n        pagination: {\n          sizes: '件 / ページ',\n          totalItems: '件'\n        }\n      });\n      return $delegate;\n    }]);\n  }]);\n})();\n\n(function () {\n  angular.module('ui.grid').config(['$provide', function($provide) {\n    $provide.decorator('i18nService', ['$delegate', function($delegate) {\n      $delegate.add('nl', {\n        aggregate: {\n          label: 'items'\n        },\n        groupPanel: {\n          description: 'Sleep hier een kolomnaam heen om op te groeperen.'\n        },\n        search: {\n          placeholder: 'Zoeken...',\n          showingItems: 'Getoonde items:',\n          selectedItems: 'Geselecteerde items:',\n          totalItems: 'Totaal aantal items:',\n          size: 'Items per pagina:',\n          first: 'Eerste pagina',\n          next: 'Volgende pagina',\n          previous: 'Vorige pagina',\n          last: 'Laatste pagina'\n        },\n        menu: {\n          text: 'Kies kolommen:'\n        },\n        sort: {\n          ascending: 'Sorteer oplopend',\n          descending: 'Sorteer aflopend',\n          remove: 'Verwijder sortering'\n        },\n        column: {\n          hide: 'Verberg kolom'\n        },\n        aggregation: {\n          count: 'Aantal rijen: ',\n          sum: 'Som: ',\n          avg: 'Gemiddelde: ',\n          min: 'Min: ',\n          max: 'Max: '\n        },\n        pinning: {\n          pinLeft: 'Zet links vast',\n          pinRight: 'Zet rechts vast',\n          unpin: 'Maak los'\n        },\n        gridMenu: {\n          columns: 'Kolommen:',\n          importerTitle: 'Importeer bestand',\n          exporterAllAsCsv: 'Exporteer alle data als csv',\n          exporterVisibleAsCsv: 'Exporteer zichtbare data als csv',\n          exporterSelectedAsCsv: 'Exporteer geselecteerde data als csv',\n          exporterAllAsPdf: 'Exporteer alle data als pdf',\n          exporterVisibleAsPdf: 'Exporteer zichtbare data als pdf',\n          exporterSelectedAsPdf: 'Exporteer geselecteerde data als pdf'\n        },\n        importer: {\n          noHeaders: 'Kolomnamen kunnen niet worden afgeleid. Heeft het bestand een header?',\n          noObjects: 'Objecten kunnen niet worden afgeleid. Bevat het bestand data naast de headers?',\n          invalidCsv: 'Het bestand kan niet verwerkt worden. Is het een valide csv bestand?',\n          invalidJson: 'Het bestand kan niet verwerkt worden. Is het valide json?',\n          jsonNotArray: 'Het json bestand moet een array bevatten. De actie wordt geannuleerd.'\n        }\n      });\n      return $delegate;\n    }]);\n  }]);\n})();\n(function () {\n  angular.module('ui.grid').config(['$provide', function($provide) {\n    $provide.decorator('i18nService', ['$delegate', function($delegate) {\n      $delegate.add('pt-br', {\n        aggregate: {\n          label: 'itens'\n        },\n        groupPanel: {\n          description: 'Arraste e solte uma coluna aqui para agrupar por essa coluna'\n        },\n        search: {\n          placeholder: 'Procurar...',\n          showingItems: 'Mostrando os Itens:',\n          selectedItems: 'Items Selecionados:',\n          totalItems: 'Total de Itens:',\n          size: 'Tamanho da Página:',\n          first: 'Primeira Página',\n          next: 'Próxima Página',\n          previous: 'Página Anterior',\n          last: 'Última Página'\n        },\n        menu: {\n          text: 'Selecione as colunas:'\n        },\n        sort: {\n          ascending: 'Ordenar Ascendente',\n          descending: 'Ordenar Descendente',\n          remove: 'Remover Ordenação'\n        },\n        column: {\n          hide: 'Esconder coluna'\n        },\n        aggregation: {\n          count: 'total de linhas: ',\n          sum: 'total: ',\n          avg: 'med: ',\n          min: 'min: ',\n          max: 'max: '\n        },\n        pinning: {\n          pinLeft: 'Fixar Esquerda',\n          pinRight: 'Fixar Direita',\n          unpin: 'Desprender'\n        },\n        gridMenu: {\n          columns: 'Colunas:',\n          exporterAllAsCsv: 'Exportar todos os dados como csv',\n          exporterVisibleAsCsv: 'Exportar dados visíveis como csv',\n          exporterSelectedAsCsv: 'Exportar dados selecionados como csv',\n          exporterAllAsPdf: 'Exportar todos os dados como pdf',\n          exporterVisibleAsPdf: 'Exportar dados visíveis como pdf',\n          exporterSelectedAsPdf: 'Exportar dados selecionados como pdf'\n        },\n        importer: {\n          noHeaders: 'Nomes de colunas não puderam ser derivados. O arquivo tem um cabeçalho?',\n          noObjects: 'Objetos não puderam ser derivados. Havia dados no arquivo, além dos cabeçalhos?',\n          invalidCsv: 'Arquivo não pode ser processado. É um CSV válido?',\n          invalidJson: 'Arquivo não pode ser processado. É um Json válido?',\n          jsonNotArray: 'Arquivo json importado tem que conter um array. Abortando.'\n        }\n      });\n      return $delegate;\n    }]);\n}]);\n})();\n(function () {\n  angular.module('ui.grid').config(['$provide', function($provide) {\n    $provide.decorator('i18nService', ['$delegate', function($delegate) {\n      $delegate.add('ru', {\n        aggregate: {\n          label: 'элементы'\n        },\n        groupPanel: {\n          description: 'Для группировки по столбцу перетащите сюда его название.'\n        },\n        search: {\n          placeholder: 'Поиск...',\n          showingItems: 'Показать элементы:',\n          selectedItems: 'Выбранные элементы:',\n          totalItems: 'Всего элементов:',\n          size: 'Размер страницы:',\n          first: 'Первая страница',\n          next: 'Следующая страница',\n          previous: 'Предыдущая страница',\n          last: 'Последняя страница'\n        },\n        menu: {\n          text: 'Выбрать столбцы:'\n        },\n        sort: {\n          ascending: 'По возрастанию',\n          descending: 'По убыванию',\n          remove: 'Убрать сортировку'\n        },\n        column: {\n          hide: 'спрятать столбец'\n        },\n        aggregation: {\n          count: 'всего строк: ',\n          sum: 'итого: ',\n          avg: 'среднее: ',\n          min: 'мин: ',\n          max: 'макс: '\n        },\n        gridMenu: {\n          columns: 'Столбцы:',\n          importerTitle: 'Import file',\n          exporterAllAsCsv: 'Экспортировать всё в CSV',\n          exporterVisibleAsCsv: 'Экспортировать видимые данные в CSV',\n          exporterSelectedAsCsv: 'Экспортировать выбранные данные в CSV',\n          exporterAllAsPdf: 'Экспортировать всё в PDF',\n          exporterVisibleAsPdf: 'Экспортировать видимые данные в PDF',\n          exporterSelectedAsPdf: 'Экспортировать выбранные данные в PDF'\n        },\n        importer: {\n          noHeaders: 'Column names were unable to be derived, does the file have a header?',\n          noObjects: 'Objects were not able to be derived, was there data in the file other than headers?',\n          invalidCsv: 'File was unable to be processed, is it valid CSV?',\n          invalidJson: 'File was unable to be processed, is it valid Json?',\n          jsonNotArray: 'Imported json file must contain an array, aborting.'\n        }\n      });\n      return $delegate;\n    }]);\n  }]);\n})();\n\n(function () {\n  angular.module('ui.grid').config(['$provide', function($provide) {\n    $provide.decorator('i18nService', ['$delegate', function($delegate) {\n      $delegate.add('sk', {\n        aggregate: {\n          label: 'items'\n        },\n        groupPanel: {\n          description: 'Pretiahni sem názov stĺpca pre zoskupenie podľa toho stĺpca.'\n        },\n        search: {\n          placeholder: 'Hľadaj...',\n          showingItems: 'Zobrazujem položky:',\n          selectedItems: 'Vybraté položky:',\n          totalItems: 'Počet položiek:',\n          size: 'Počet:',\n          first: 'Prvá strana',\n          next: 'Ďalšia strana',\n          previous: 'Predchádzajúca strana',\n          last: 'Posledná strana'\n        },\n        menu: {\n          text: 'Vyberte stĺpce:'\n        },\n        sort: {\n          ascending: 'Zotriediť vzostupne',\n          descending: 'Zotriediť zostupne',\n          remove: 'Vymazať triedenie'\n        },\n        aggregation: {\n          count: 'total rows: ',\n          sum: 'total: ',\n          avg: 'avg: ',\n          min: 'min: ',\n          max: 'max: '\n        },\n        gridMenu: {\n          columns: 'Columns:',\n          importerTitle: 'Import file',\n          exporterAllAsCsv: 'Export all data as csv',\n          exporterVisibleAsCsv: 'Export visible data as csv',\n          exporterSelectedAsCsv: 'Export selected data as csv',\n          exporterAllAsPdf: 'Export all data as pdf',\n          exporterVisibleAsPdf: 'Export visible data as pdf',\n          exporterSelectedAsPdf: 'Export selected data as pdf'\n        },\n        importer: {\n          noHeaders: 'Column names were unable to be derived, does the file have a header?',\n          noObjects: 'Objects were not able to be derived, was there data in the file other than headers?',\n          invalidCsv: 'File was unable to be processed, is it valid CSV?',\n          invalidJson: 'File was unable to be processed, is it valid Json?',\n          jsonNotArray: 'Imported json file must contain an array, aborting.'\n        }\n      });\n      return $delegate;\n    }]);\n  }]);\n})();\n\n(function () {\n  angular.module('ui.grid').config(['$provide', function($provide) {\n    $provide.decorator('i18nService', ['$delegate', function($delegate) {\n      $delegate.add('sv', {\n        aggregate: {\n          label: 'Artiklar'\n        },\n        groupPanel: {\n          description: 'Dra en kolumnrubrik hit och släpp den för att gruppera efter den kolumnen.'\n        },\n        search: {\n          placeholder: 'Sök...',\n          showingItems: 'Visar artiklar:',\n          selectedItems: 'Valda artiklar:',\n          totalItems: 'Antal artiklar:',\n          size: 'Sidstorlek:',\n          first: 'Första sidan',\n          next: 'Nästa sida',\n          previous: 'Föregående sida',\n          last: 'Sista sidan'\n        },\n        menu: {\n          text: 'Välj kolumner:'\n        },\n        sort: {\n          ascending: 'Sortera stigande',\n          descending: 'Sortera fallande',\n          remove: 'Inaktivera sortering'\n        },\n        column: {\n          hide: 'Göm kolumn'\n        },\n        aggregation: {\n          count: 'Antal rader: ',\n          sum: 'Summa: ',\n          avg: 'Genomsnitt: ',\n          min: 'Min: ',\n          max: 'Max: '\n        },\n        pinning: {\n          pinLeft: 'Fäst vänster',\n          pinRight: 'Fäst höger',\n          unpin: 'Lösgör'\n        },\n        gridMenu: {\n          columns: 'Kolumner:',\n          importerTitle: 'Importera fil',\n          exporterAllAsCsv: 'Exportera all data som CSV',\n          exporterVisibleAsCsv: 'Exportera synlig data som CSV',\n          exporterSelectedAsCsv: 'Exportera markerad data som CSV',\n          exporterAllAsPdf: 'Exportera all data som PDF',\n          exporterVisibleAsPdf: 'Exportera synlig data som PDF',\n          exporterSelectedAsPdf: 'Exportera markerad data som PDF'\n        },\n        importer: {\n          noHeaders: 'Kolumnnamn kunde inte härledas. Har filen ett sidhuvud?',\n          noObjects: 'Objekt kunde inte härledas. Har filen data undantaget sidhuvud?',\n          invalidCsv: 'Filen kunde inte behandlas, är den en giltig CSV?',\n          invalidJson: 'Filen kunde inte behandlas, är den en giltig JSON?',\n          jsonNotArray: 'Importerad JSON-fil måste innehålla ett fält. Import avbruten.'\n        },\n        pagination: {\n          sizes: 'Artiklar per sida',\n          totalItems: 'Artiklar'\n        }\n      });\n      return $delegate;\n    }]);\n  }]);\n})();\n\n/**\n * @ngdoc overview\n * @name ui.grid.i18n\n * @description\n *\n *  # ui.grid.i18n\n * This module provides i18n functions to ui.grid and any application that wants to use it\n\n *\n * <div doc-module-components=\"ui.grid.i18n\"></div>\n */\n\n(function () {\n  var DIRECTIVE_ALIASES = ['uiT', 'uiTranslate'];\n  var FILTER_ALIASES = ['t', 'uiTranslate'];\n\n  var module = angular.module('ui.grid.i18n');\n\n\n  /**\n   *  @ngdoc object\n   *  @name ui.grid.i18n.constant:i18nConstants\n   *\n   *  @description constants available in i18n module\n   */\n  module.constant('i18nConstants', {\n    MISSING: '[MISSING]',\n    UPDATE_EVENT: '$uiI18n',\n\n    LOCALE_DIRECTIVE_ALIAS: 'uiI18n',\n    // default to english\n    DEFAULT_LANG: 'en'\n  });\n\n//    module.config(['$provide', function($provide) {\n//        $provide.decorator('i18nService', ['$delegate', function($delegate) {}])}]);\n\n  /**\n   *  @ngdoc service\n   *  @name ui.grid.i18n.service:i18nService\n   *\n   *  @description Services for i18n\n   */\n  module.service('i18nService', ['$log', 'i18nConstants', '$rootScope',\n    function ($log, i18nConstants, $rootScope) {\n\n      var langCache = {\n        _langs: {},\n        current: null,\n        get: function (lang) {\n          return this._langs[lang.toLowerCase()];\n        },\n        add: function (lang, strings) {\n          var lower = lang.toLowerCase();\n          if (!this._langs[lower]) {\n            this._langs[lower] = {};\n          }\n          angular.extend(this._langs[lower], strings);\n        },\n        getAllLangs: function () {\n          var langs = [];\n          if (!this._langs) {\n            return langs;\n          }\n\n          for (var key in this._langs) {\n            langs.push(key);\n          }\n\n          return langs;\n        },\n        setCurrent: function (lang) {\n          this.current = lang.toLowerCase();\n        },\n        getCurrentLang: function () {\n          return this.current;\n        }\n      };\n\n      var service = {\n\n        /**\n         * @ngdoc service\n         * @name add\n         * @methodOf ui.grid.i18n.service:i18nService\n         * @description  Adds the languages and strings to the cache. Decorate this service to\n         * add more translation strings\n         * @param {string} lang language to add\n         * @param {object} stringMaps of strings to add grouped by property names\n         * @example\n         * <pre>\n         *      i18nService.add('en', {\n         *         aggregate: {\n         *                 label1: 'items',\n         *                 label2: 'some more items'\n         *                 }\n         *         },\n         *         groupPanel: {\n         *              description: 'Drag a column header here and drop it to group by that column.'\n         *           }\n         *      }\n         * </pre>\n         */\n        add: function (langs, stringMaps) {\n          if (typeof(langs) === 'object') {\n            angular.forEach(langs, function (lang) {\n              if (lang) {\n                langCache.add(lang, stringMaps);\n              }\n            });\n          } else {\n            langCache.add(langs, stringMaps);\n          }\n        },\n\n        /**\n         * @ngdoc service\n         * @name getAllLangs\n         * @methodOf ui.grid.i18n.service:i18nService\n         * @description  return all currently loaded languages\n         * @returns {array} string\n         */\n        getAllLangs: function () {\n          return langCache.getAllLangs();\n        },\n\n        /**\n         * @ngdoc service\n         * @name get\n         * @methodOf ui.grid.i18n.service:i18nService\n         * @description  return all currently loaded languages\n         * @param {string} lang to return.  If not specified, returns current language\n         * @returns {object} the translation string maps for the language\n         */\n        get: function (lang) {\n          var language = lang ? lang : service.getCurrentLang();\n          return langCache.get(language);\n        },\n\n        /**\n         * @ngdoc service\n         * @name getSafeText\n         * @methodOf ui.grid.i18n.service:i18nService\n         * @description  returns the text specified in the path or a Missing text if text is not found\n         * @param {string} path property path to use for retrieving text from string map\n         * @param {string} lang to return.  If not specified, returns current language\n         * @returns {object} the translation for the path\n         * @example\n         * <pre>\n         * i18nService.getSafeText('sort.ascending')\n         * </pre>\n         */\n        getSafeText: function (path, lang) {\n          var language = lang ? lang : service.getCurrentLang();\n          var trans = langCache.get(language);\n\n          if (!trans) {\n            return i18nConstants.MISSING;\n          }\n\n          var paths = path.split('.');\n          var current = trans;\n\n          for (var i = 0; i < paths.length; ++i) {\n            if (current[paths[i]] === undefined || current[paths[i]] === null) {\n              return i18nConstants.MISSING;\n            } else {\n              current = current[paths[i]];\n            }\n          }\n\n          return current;\n\n        },\n\n        /**\n         * @ngdoc service\n         * @name setCurrentLang\n         * @methodOf ui.grid.i18n.service:i18nService\n         * @description sets the current language to use in the application\n         * $broadcasts the Update_Event on the $rootScope\n         * @param {string} lang to set\n         * @example\n         * <pre>\n         * i18nService.setCurrentLang('fr');\n         * </pre>\n         */\n\n        setCurrentLang: function (lang) {\n          if (lang) {\n            langCache.setCurrent(lang);\n            $rootScope.$broadcast(i18nConstants.UPDATE_EVENT);\n          }\n        },\n\n        /**\n         * @ngdoc service\n         * @name getCurrentLang\n         * @methodOf ui.grid.i18n.service:i18nService\n         * @description returns the current language used in the application\n         */\n        getCurrentLang: function () {\n          var lang = langCache.getCurrentLang();\n          if (!lang) {\n            lang = i18nConstants.DEFAULT_LANG;\n            langCache.setCurrent(lang);\n          }\n          return lang;\n        }\n\n      };\n\n      return service;\n\n    }]);\n\n  var localeDirective = function (i18nService, i18nConstants) {\n    return {\n      compile: function () {\n        return {\n          pre: function ($scope, $elm, $attrs) {\n            var alias = i18nConstants.LOCALE_DIRECTIVE_ALIAS;\n            // check for watchable property\n            var lang = $scope.$eval($attrs[alias]);\n            if (lang) {\n              $scope.$watch($attrs[alias], function () {\n                i18nService.setCurrentLang(lang);\n              });\n            } else if ($attrs.$$observers) {\n              $attrs.$observe(alias, function () {\n                i18nService.setCurrentLang($attrs[alias] || i18nConstants.DEFAULT_LANG);\n              });\n            }\n          }\n        };\n      }\n    };\n  };\n\n  module.directive('uiI18n', ['i18nService', 'i18nConstants', localeDirective]);\n\n  // directive syntax\n  var uitDirective = function ($parse, i18nService, i18nConstants) {\n    return {\n      restrict: 'EA',\n      compile: function () {\n        return {\n          pre: function ($scope, $elm, $attrs) {\n            var alias1 = DIRECTIVE_ALIASES[0],\n              alias2 = DIRECTIVE_ALIASES[1];\n            var token = $attrs[alias1] || $attrs[alias2] || $elm.html();\n            var missing = i18nConstants.MISSING + token;\n            var observer;\n            if ($attrs.$$observers) {\n              var prop = $attrs[alias1] ? alias1 : alias2;\n              observer = $attrs.$observe(prop, function (result) {\n                if (result) {\n                  $elm.html($parse(result)(i18nService.getCurrentLang()) || missing);\n                }\n              });\n            }\n            var getter = $parse(token);\n            var listener = $scope.$on(i18nConstants.UPDATE_EVENT, function (evt) {\n              if (observer) {\n                observer($attrs[alias1] || $attrs[alias2]);\n              } else {\n                // set text based on i18n current language\n                $elm.html(getter(i18nService.get()) || missing);\n              }\n            });\n            $scope.$on('$destroy', listener);\n\n            $elm.html(getter(i18nService.get()) || missing);\n          }\n        };\n      }\n    };\n  };\n\n  angular.forEach( DIRECTIVE_ALIASES, function ( alias ) {\n    module.directive( alias, ['$parse', 'i18nService', 'i18nConstants', uitDirective] );\n  } );\n\n  // optional filter syntax\n  var uitFilter = function ($parse, i18nService, i18nConstants) {\n    return function (data) {\n      var getter = $parse(data);\n      // set text based on i18n current language\n      return getter(i18nService.get()) || i18nConstants.MISSING + data;\n    };\n  };\n\n  angular.forEach( FILTER_ALIASES, function ( alias ) {\n    module.filter( alias, ['$parse', 'i18nService', 'i18nConstants', uitFilter] );\n  } );\n\n\n})();\n(function() {\n  angular.module('ui.grid').config(['$provide', function($provide) {\n    $provide.decorator('i18nService', ['$delegate', function($delegate) {\n      $delegate.add('zh-cn', {\n        aggregate: {\n          label: '行'\n        },\n        groupPanel: {\n          description: '拖曳表头到此处进行分组'\n        },\n        search: {\n          placeholder: '查找',\n          showingItems: '已显示行数：',\n          selectedItems: '已选择行数：',\n          totalItems: '总行数：',\n          size: '每页显示行数：',\n          first: '首页',\n          next: '下一页',\n          previous: '上一页',\n          last: '末页'\n        },\n        menu: {\n          text: '选择列：'\n        },\n        sort: {\n          ascending: '升序',\n          descending: '降序',\n          remove: '取消排序'\n        },\n        column: {\n          hide: '隐藏列'\n        },\n        aggregation: {\n          count: '计数：',\n          sum: '求和：',\n          avg: '均值：',\n          min: '最小值：',\n          max: '最大值：'\n        },\n        pinning: {\n          pinLeft: '左侧固定',\n          pinRight: '右侧固定',\n          unpin: '取消固定'\n        },\n        gridMenu: {\n          columns: '列：',\n          importerTitle: '导入文件',\n          exporterAllAsCsv: '导出全部数据到CSV',\n          exporterVisibleAsCsv: '导出可见数据到CSV',\n          exporterSelectedAsCsv: '导出已选数据到CSV',\n          exporterAllAsPdf: '导出全部数据到PDF',\n          exporterVisibleAsPdf: '导出可见数据到PDF',\n          exporterSelectedAsPdf: '导出已选数据到PDF'\n        },\n        importer: {\n          noHeaders: '无法获取列名，确定文件包含表头？',\n          noObjects: '无法获取数据，确定文件包含数据？',\n          invalidCsv: '无法处理文件，确定是合法的CSV文件？',\n          invalidJson: '无法处理文件，确定是合法的JSON文件？',\n          jsonNotArray: '导入的文件不是JSON数组！'\n        },\n        pagination: {\n          sizes: '行每页',\n          totalItems: '行'\n        }\n      });\n      return $delegate;\n    }]);\n  }]);\n})();\n\n(function() {\n  angular.module('ui.grid').config(['$provide', function($provide) {\n    $provide.decorator('i18nService', ['$delegate', function($delegate) {\n      $delegate.add('zh-tw', {\n        aggregate: {\n          label: '行'\n        },\n        groupPanel: {\n          description: '拖曳表頭到此處進行分組'\n        },\n        search: {\n          placeholder: '查找',\n          showingItems: '已顯示行數：',\n          selectedItems: '已選擇行數：',\n          totalItems: '總行數：',\n          size: '每頁顯示行數：',\n          first: '首頁',\n          next: '下壹頁',\n          previous: '上壹頁',\n          last: '末頁'\n        },\n        menu: {\n          text: '選擇列：'\n        },\n        sort: {\n          ascending: '升序',\n          descending: '降序',\n          remove: '取消排序'\n        },\n        column: {\n          hide: '隱藏列'\n        },\n        aggregation: {\n          count: '計數：',\n          sum: '求和：',\n          avg: '均值：',\n          min: '最小值：',\n          max: '最大值：'\n        },\n        pinning: {\n          pinLeft: '左側固定',\n          pinRight: '右側固定',\n          unpin: '取消固定'\n        },\n        gridMenu: {\n          columns: '列：',\n          importerTitle: '導入文件',\n          exporterAllAsCsv: '導出全部數據到CSV',\n          exporterVisibleAsCsv: '導出可見數據到CSV',\n          exporterSelectedAsCsv: '導出已選數據到CSV',\n          exporterAllAsPdf: '導出全部數據到PDF',\n          exporterVisibleAsPdf: '導出可見數據到PDF',\n          exporterSelectedAsPdf: '導出已選數據到PDF'\n        },\n        importer: {\n          noHeaders: '無法獲取列名，確定文件包含表頭？',\n          noObjects: '無法獲取數據，確定文件包含數據？',\n          invalidCsv: '無法處理文件，確定是合法的CSV文件？',\n          invalidJson: '無法處理文件，確定是合法的JSON文件？',\n          jsonNotArray: '導入的文件不是JSON數組！'\n        },\n        pagination: {\n          sizes: '行每頁',\n          totalItems: '行'\n        }\n      });\n      return $delegate;\n    }]);\n  }]);\n})();\n\n(function() {\n  'use strict';\n  /**\n   *  @ngdoc overview\n   *  @name ui.grid.autoResize\n   *\n   *  @description \n   *\n   *  #ui.grid.autoResize\n   *  This module provides auto-resizing functionality to ui-grid\n   *\n   */\n  var module = angular.module('ui.grid.autoResize', ['ui.grid']);\n  \n\n  module.directive('uiGridAutoResize', ['$timeout', 'gridUtil', function ($timeout, gridUtil) {\n    return {\n      require: 'uiGrid',\n      scope: false,\n      link: function ($scope, $elm, $attrs, uiGridCtrl) {\n        var prevGridWidth, prevGridHeight;\n\n        function getDimensions() {\n          prevGridHeight = gridUtil.elementHeight($elm);\n          prevGridWidth = gridUtil.elementWidth($elm);\n        }\n\n        // Initialize the dimensions\n        getDimensions();\n\n        var resizeTimeoutId;\n        function startTimeout() {\n          clearTimeout(resizeTimeoutId);\n\n          resizeTimeoutId = setTimeout(function () {\n            var newGridHeight = gridUtil.elementHeight($elm);\n            var newGridWidth = gridUtil.elementWidth($elm);\n\n            if (newGridHeight !== prevGridHeight || newGridWidth !== prevGridWidth) {\n              uiGridCtrl.grid.gridHeight = newGridHeight;\n              uiGridCtrl.grid.gridWidth = newGridWidth;\n\n              $scope.$apply(function () {\n                uiGridCtrl.grid.refresh()\n                  .then(function () {\n                    getDimensions();\n\n                    startTimeout();\n                  });\n              });\n            }\n            else {\n              startTimeout();\n            }\n          }, 250);\n        }\n\n        startTimeout();\n\n        $scope.$on('$destroy', function() {\n          clearTimeout(resizeTimeoutId);\n        });\n      }\n    };\n  }]);\n})();\n(function () {\n  'use strict';\n  var module = angular.module('ui.grid.cellNav', ['ui.grid']);\n\n  function RowCol(row, col) {\n    this.row = row;\n    this.col = col;\n  }\n\n  /**\n   *  @ngdoc object\n   *  @name ui.grid.cellNav.constant:uiGridCellNavConstants\n   *\n   *  @description constants available in cellNav\n   */\n  module.constant('uiGridCellNavConstants', {\n    FEATURE_NAME: 'gridCellNav',\n    CELL_NAV_EVENT: 'cellNav',\n    direction: {LEFT: 0, RIGHT: 1, UP: 2, DOWN: 3, PG_UP: 4, PG_DOWN: 5},\n    EVENT_TYPE: {\n      KEYDOWN: 0,\n      CLICK: 1\n    }\n  });\n\n\n  module.factory('uiGridCellNavFactory', ['gridUtil', 'uiGridConstants', 'uiGridCellNavConstants', '$q',\n    function (gridUtil, uiGridConstants, uiGridCellNavConstants, $q) {\n      /**\n       *  @ngdoc object\n       *  @name ui.grid.cellNav.object:CellNav\n       *  @description returns a CellNav prototype function\n       *  @param {object} rowContainer container for rows\n       *  @param {object} colContainer parent column container\n       *  @param {object} leftColContainer column container to the left of parent\n       *  @param {object} rightColContainer column container to the right of parent\n       */\n      var UiGridCellNav = function UiGridCellNav(rowContainer, colContainer, leftColContainer, rightColContainer) {\n        this.rows = rowContainer.visibleRowCache;\n        this.columns = colContainer.visibleColumnCache;\n        this.leftColumns = leftColContainer ? leftColContainer.visibleColumnCache : [];\n        this.rightColumns = rightColContainer ? rightColContainer.visibleColumnCache : [];\n        this.bodyContainer = rowContainer;\n      };\n\n      /** returns focusable columns of all containers */\n      UiGridCellNav.prototype.getFocusableCols = function () {\n        var allColumns = this.leftColumns.concat(this.columns, this.rightColumns);\n\n        return allColumns.filter(function (col) {\n          return col.colDef.allowCellFocus;\n        });\n      };\n\n      /**\n       *  @ngdoc object\n       *  @name ui.grid.cellNav.api:GridRow\n       *\n       *  @description GridRow settings for cellNav feature, these are available to be\n       *  set only internally (for example, by other features)\n       */\n\n      /**\n       *  @ngdoc object\n       *  @name allowCellFocus\n       *  @propertyOf  ui.grid.cellNav.api:GridRow\n       *  @description Enable focus on a cell within this row.  If set to false then no cells\n       *  in this row can be focused - group header rows as an example would set this to false.\n       *  <br/>Defaults to true\n       */\n      /** returns focusable rows */\n      UiGridCellNav.prototype.getFocusableRows = function () {\n        return this.rows.filter(function(row) {\n          return row.allowCellFocus !== false;\n        });\n      };\n\n      UiGridCellNav.prototype.getNextRowCol = function (direction, curRow, curCol) {\n        switch (direction) {\n          case uiGridCellNavConstants.direction.LEFT:\n            return this.getRowColLeft(curRow, curCol);\n          case uiGridCellNavConstants.direction.RIGHT:\n            return this.getRowColRight(curRow, curCol);\n          case uiGridCellNavConstants.direction.UP:\n            return this.getRowColUp(curRow, curCol);\n          case uiGridCellNavConstants.direction.DOWN:\n            return this.getRowColDown(curRow, curCol);\n          case uiGridCellNavConstants.direction.PG_UP:\n            return this.getRowColPageUp(curRow, curCol);\n          case uiGridCellNavConstants.direction.PG_DOWN:\n            return this.getRowColPageDown(curRow, curCol);\n        }\n\n      };\n\n      UiGridCellNav.prototype.getRowColLeft = function (curRow, curCol) {\n        var focusableCols = this.getFocusableCols();\n        var focusableRows = this.getFocusableRows();\n        var curColIndex = focusableCols.indexOf(curCol);\n        var curRowIndex = focusableRows.indexOf(curRow);\n\n        //could not find column in focusable Columns so set it to 1\n        if (curColIndex === -1) {\n          curColIndex = 1;\n        }\n\n        var nextColIndex = curColIndex === 0 ? focusableCols.length - 1 : curColIndex - 1;\n\n        //get column to left\n        if (nextColIndex > curColIndex) {\n          if (curRowIndex === 0) {\n            return new RowCol(curRow, focusableCols[nextColIndex]); //return same row\n          }\n          else {\n            //up one row and far right column\n            return new RowCol(focusableRows[curRowIndex - 1], focusableCols[nextColIndex]);\n          }\n        }\n        else {\n          return new RowCol(curRow, focusableCols[nextColIndex]);\n        }\n      };\n\n      UiGridCellNav.prototype.getRowColRight = function (curRow, curCol) {\n        var focusableCols = this.getFocusableCols();\n        var focusableRows = this.getFocusableRows();\n        var curColIndex = focusableCols.indexOf(curCol);\n        var curRowIndex = focusableRows.indexOf(curRow);\n\n        //could not find column in focusable Columns so set it to 0\n        if (curColIndex === -1) {\n          curColIndex = 0;\n        }\n        var nextColIndex = curColIndex === focusableCols.length - 1 ? 0 : curColIndex + 1;\n\n        if (nextColIndex < curColIndex) {\n          if (curRowIndex === focusableRows.length - 1) {\n            return new RowCol(curRow, focusableCols[nextColIndex]); //return same row\n          }\n          else {\n            //down one row and far left column\n            return new RowCol(focusableRows[curRowIndex + 1], focusableCols[nextColIndex]);\n          }\n        }\n        else {\n          return new RowCol(curRow, focusableCols[nextColIndex]);\n        }\n      };\n\n      UiGridCellNav.prototype.getRowColDown = function (curRow, curCol) {\n        var focusableCols = this.getFocusableCols();\n        var focusableRows = this.getFocusableRows();\n        var curColIndex = focusableCols.indexOf(curCol);\n        var curRowIndex = focusableRows.indexOf(curRow);\n\n        //could not find column in focusable Columns so set it to 0\n        if (curColIndex === -1) {\n          curColIndex = 0;\n        }\n\n        if (curRowIndex === focusableRows.length - 1) {\n          return new RowCol(curRow, focusableCols[curColIndex]); //return same row\n        }\n        else {\n          //down one row\n          return new RowCol(focusableRows[curRowIndex + 1], focusableCols[curColIndex]);\n        }\n      };\n\n      UiGridCellNav.prototype.getRowColPageDown = function (curRow, curCol) {\n        var focusableCols = this.getFocusableCols();\n        var focusableRows = this.getFocusableRows();\n        var curColIndex = focusableCols.indexOf(curCol);\n        var curRowIndex = focusableRows.indexOf(curRow);\n\n        //could not find column in focusable Columns so set it to 0\n        if (curColIndex === -1) {\n          curColIndex = 0;\n        }\n\n        var pageSize = this.bodyContainer.minRowsToRender();\n        if (curRowIndex >= focusableRows.length - pageSize) {\n          return new RowCol(focusableRows[focusableRows.length - 1], focusableCols[curColIndex]); //return last row\n        }\n        else {\n          //down one page\n          return new RowCol(focusableRows[curRowIndex + pageSize], focusableCols[curColIndex]);\n        }\n      };\n\n      UiGridCellNav.prototype.getRowColUp = function (curRow, curCol) {\n        var focusableCols = this.getFocusableCols();\n        var focusableRows = this.getFocusableRows();\n        var curColIndex = focusableCols.indexOf(curCol);\n        var curRowIndex = focusableRows.indexOf(curRow);\n\n        //could not find column in focusable Columns so set it to 0\n        if (curColIndex === -1) {\n          curColIndex = 0;\n        }\n\n        if (curRowIndex === 0) {\n          return new RowCol(curRow, focusableCols[curColIndex]); //return same row\n        }\n        else {\n          //up one row\n          return new RowCol(focusableRows[curRowIndex - 1], focusableCols[curColIndex]);\n        }\n      };\n\n      UiGridCellNav.prototype.getRowColPageUp = function (curRow, curCol) {\n        var focusableCols = this.getFocusableCols();\n        var focusableRows = this.getFocusableRows();\n        var curColIndex = focusableCols.indexOf(curCol);\n        var curRowIndex = focusableRows.indexOf(curRow);\n\n        //could not find column in focusable Columns so set it to 0\n        if (curColIndex === -1) {\n          curColIndex = 0;\n        }\n\n        var pageSize = this.bodyContainer.minRowsToRender();\n        if (curRowIndex - pageSize < 0) {\n          return new RowCol(focusableRows[0], focusableCols[curColIndex]); //return first row\n        }\n        else {\n          //up one page\n          return new RowCol(focusableRows[curRowIndex - pageSize], focusableCols[curColIndex]);\n        }\n      };\n      return UiGridCellNav;\n    }]);\n\n  /**\n   *  @ngdoc service\n   *  @name ui.grid.cellNav.service:uiGridCellNavService\n   *\n   *  @description Services for cell navigation features. If you don't like the key maps we use,\n   *  or the direction cells navigation, override with a service decorator (see angular docs)\n   */\n  module.service('uiGridCellNavService', ['gridUtil', 'uiGridConstants', 'uiGridCellNavConstants', '$q', 'uiGridCellNavFactory', 'ScrollEvent',\n    function (gridUtil, uiGridConstants, uiGridCellNavConstants, $q, UiGridCellNav, ScrollEvent) {\n\n      var service = {\n\n        initializeGrid: function (grid) {\n          grid.registerColumnBuilder(service.cellNavColumnBuilder);\n\n          //create variables for state\n          grid.cellNav = {};\n          grid.cellNav.lastRowCol = null;\n          grid.cellNav.focusedCells = [];\n\n          service.defaultGridOptions(grid.options);\n\n          /**\n           *  @ngdoc object\n           *  @name ui.grid.cellNav.api:PublicApi\n           *\n           *  @description Public Api for cellNav feature\n           */\n          var publicApi = {\n            events: {\n              cellNav: {\n                /**\n                 * @ngdoc event\n                 * @name navigate\n                 * @eventOf  ui.grid.cellNav.api:PublicApi\n                 * @description raised when the active cell is changed\n                 * <pre>\n                 *      gridApi.cellNav.on.navigate(scope,function(newRowcol, oldRowCol){})\n                 * </pre>\n                 * @param {object} newRowCol new position\n                 * @param {object} oldRowCol old position\n                 */\n                navigate: function (newRowCol, oldRowCol) {\n                }\n              }\n            },\n            methods: {\n              cellNav: {\n                /**\n                 * @ngdoc function\n                 * @name scrollTo\n                 * @methodOf  ui.grid.cellNav.api:PublicApi\n                 * @description brings the specified row and column into view\n                 * @param {object} rowEntity gridOptions.data[] array instance to make visible\n                 * @param {object} colDef to make visible\n                 */\n                scrollTo: function (rowEntity, colDef) {\n                  service.scrollTo(grid, rowEntity, colDef);\n                },\n\n                /**\n                 * @ngdoc function\n                 * @name scrollToFocus\n                 * @methodOf  ui.grid.cellNav.api:PublicApi\n                 * @description brings the specified row and column into view, and sets focus\n                 * to that cell\n                 * @param {object} rowEntity gridOptions.data[] array instance to make visible and set focus\n                 * @param {object} colDef to make visible and set focus\n                 */\n                scrollToFocus: function (rowEntity, colDef) {\n                  service.scrollToFocus(grid, rowEntity, colDef);\n                },\n\n                /**\n                 * @ngdoc function\n                 * @name scrollToFocus\n                 * @methodOf  ui.grid.cellNav.api:PublicApi\n                 * @description brings the specified row and column fully into view if it isn't already\n                 * @param {GridRow} row grid row that we should make fully visible\n                 * @param {GridCol} col grid col to make fully visible\n                 */\n                scrollToIfNecessary: function (row, col) {\n                  service.scrollToIfNecessary(grid, row, col);\n                },\n\n                /**\n                 * @ngdoc function\n                 * @name getFocusedCell\n                 * @methodOf  ui.grid.cellNav.api:PublicApi\n                 * @description returns the current (or last if Grid does not have focus) focused row and column\n                 * <br> value is null if no selection has occurred\n                 */\n                getFocusedCell: function () {\n                  return grid.cellNav.lastRowCol;\n                },\n\n                /**\n                 * @ngdoc function\n                 * @name getCurrentSelection\n                 * @methodOf  ui.grid.cellNav.api:PublicApi\n                 * @description returns an array containing the current selection\n                 * <br> array is empty if no selection has occurred\n                 */\n                getCurrentSelection: function () {\n                  return grid.cellNav.focusedCells;\n                },\n\n                /**\n                 * @ngdoc function\n                 * @name rowColSelectIndex\n                 * @methodOf  ui.grid.cellNav.api:PublicApi\n                 * @description returns the index in the order in which the RowCol was selected, returns -1 if the RowCol\n                 * isn't selected\n                 * @param {object} rowCol the rowCol to evaluate\n                 */\n                rowColSelectIndex: function (rowCol) {\n                  //return gridUtil.arrayContainsObjectWithProperty(grid.cellNav.focusedCells, 'col.uid', rowCol.col.uid) &&\n                  var index = -1;\n                  for (var i = 0; i < grid.cellNav.focusedCells.length; i++) {\n                    if (grid.cellNav.focusedCells[i].col.uid === rowCol.col.uid &&\n                      grid.cellNav.focusedCells[i].row.uid === rowCol.row.uid) {\n                      index = i;\n                      break;\n                    }\n                  }\n                  return index;\n                }\n              }\n            }\n          };\n\n          grid.api.registerEventsFromObject(publicApi.events);\n\n          grid.api.registerMethodsFromObject(publicApi.methods);\n\n        },\n\n        defaultGridOptions: function (gridOptions) {\n          /**\n           *  @ngdoc object\n           *  @name ui.grid.cellNav.api:GridOptions\n           *\n           *  @description GridOptions for cellNav feature, these are available to be\n           *  set using the ui-grid {@link ui.grid.class:GridOptions gridOptions}\n           */\n\n          /**\n           *  @ngdoc object\n           *  @name modifierKeysToMultiSelectCells\n           *  @propertyOf  ui.grid.cellNav.api:GridOptions\n           *  @description Enable multiple cell selection only when using the ctrlKey or shiftKey.\n           *  <br/>Defaults to false\n           */\n          gridOptions.modifierKeysToMultiSelectCells = gridOptions.modifierKeysToMultiSelectCells === true;\n\n        },\n\n        /**\n         * @ngdoc service\n         * @name decorateRenderContainers\n         * @methodOf ui.grid.cellNav.service:uiGridCellNavService\n         * @description  decorates grid renderContainers with cellNav functions\n         */\n        decorateRenderContainers: function (grid) {\n\n          var rightContainer = grid.hasRightContainer() ? grid.renderContainers.right : null;\n          var leftContainer = grid.hasLeftContainer() ? grid.renderContainers.left : null;\n\n          if (leftContainer !== null) {\n            grid.renderContainers.left.cellNav = new UiGridCellNav(grid.renderContainers.body, leftContainer, rightContainer, grid.renderContainers.body);\n          }\n          if (rightContainer !== null) {\n            grid.renderContainers.right.cellNav = new UiGridCellNav(grid.renderContainers.body, rightContainer, grid.renderContainers.body, leftContainer);\n          }\n\n          grid.renderContainers.body.cellNav = new UiGridCellNav(grid.renderContainers.body, grid.renderContainers.body, leftContainer, rightContainer);\n        },\n\n        /**\n         * @ngdoc service\n         * @name getDirection\n         * @methodOf ui.grid.cellNav.service:uiGridCellNavService\n         * @description  determines which direction to for a given keyDown event\n         * @returns {uiGridCellNavConstants.direction} direction\n         */\n        getDirection: function (evt) {\n          if (evt.keyCode === uiGridConstants.keymap.LEFT ||\n            (evt.keyCode === uiGridConstants.keymap.TAB && evt.shiftKey)) {\n            return uiGridCellNavConstants.direction.LEFT;\n          }\n          if (evt.keyCode === uiGridConstants.keymap.RIGHT ||\n            evt.keyCode === uiGridConstants.keymap.TAB) {\n            return uiGridCellNavConstants.direction.RIGHT;\n          }\n\n          if (evt.keyCode === uiGridConstants.keymap.UP ||\n            (evt.keyCode === uiGridConstants.keymap.ENTER && evt.shiftKey) ) {\n            return uiGridCellNavConstants.direction.UP;\n          }\n\n          if (evt.keyCode === uiGridConstants.keymap.PG_UP){\n            return uiGridCellNavConstants.direction.PG_UP;\n          }\n\n          if (evt.keyCode === uiGridConstants.keymap.DOWN ||\n            evt.keyCode === uiGridConstants.keymap.ENTER) {\n            return uiGridCellNavConstants.direction.DOWN;\n          }\n\n          if (evt.keyCode === uiGridConstants.keymap.PG_DOWN){\n            return uiGridCellNavConstants.direction.PG_DOWN;\n          }\n\n          return null;\n        },\n\n        /**\n         * @ngdoc service\n         * @name cellNavColumnBuilder\n         * @methodOf ui.grid.cellNav.service:uiGridCellNavService\n         * @description columnBuilder function that adds cell navigation properties to grid column\n         * @returns {promise} promise that will load any needed templates when resolved\n         */\n        cellNavColumnBuilder: function (colDef, col, gridOptions) {\n          var promises = [];\n\n          /**\n           *  @ngdoc object\n           *  @name ui.grid.cellNav.api:ColumnDef\n           *\n           *  @description Column Definitions for cellNav feature, these are available to be\n           *  set using the ui-grid {@link ui.grid.class:GridOptions.columnDef gridOptions.columnDefs}\n           */\n\n          /**\n           *  @ngdoc object\n           *  @name allowCellFocus\n           *  @propertyOf  ui.grid.cellNav.api:ColumnDef\n           *  @description Enable focus on a cell within this column.\n           *  <br/>Defaults to true\n           */\n          colDef.allowCellFocus = colDef.allowCellFocus === undefined ? true : colDef.allowCellFocus;\n\n          return $q.all(promises);\n        },\n\n        /**\n         * @ngdoc method\n         * @methodOf ui.grid.cellNav.service:uiGridCellNavService\n         * @name scrollTo\n         * @description Scroll the grid such that the specified\n         * row and column is in view\n         * @param {Grid} grid the grid you'd like to act upon, usually available\n         * from gridApi.grid\n         * @param {object} rowEntity gridOptions.data[] array instance to make visible\n         * @param {object} colDef to make visible\n         */\n        scrollTo: function (grid, rowEntity, colDef) {\n          var gridRow = null, gridCol = null;\n\n          if (rowEntity !== null && typeof(rowEntity) !== 'undefined' ) {\n            gridRow = grid.getRow(rowEntity);\n          }\n\n          if (colDef !== null && typeof(colDef) !== 'undefined' ) {\n            gridCol = grid.getColumn(colDef.name ? colDef.name : colDef.field);\n          }\n          this.scrollToInternal(grid, gridRow, gridCol);\n        },\n\n        /**\n         * @ngdoc method\n         * @methodOf ui.grid.cellNav.service:uiGridCellNavService\n         * @name scrollToFocus\n         * @description Scroll the grid such that the specified\n         * row and column is in view, and set focus to the cell in that row and column\n         * @param {Grid} grid the grid you'd like to act upon, usually available\n         * from gridApi.grid\n         * @param {object} rowEntity gridOptions.data[] array instance to make visible and set focus to\n         * @param {object} colDef to make visible and set focus to\n         */\n        scrollToFocus: function (grid, rowEntity, colDef) {\n          var gridRow = null, gridCol = null;\n\n          if (rowEntity !== null) {\n            gridRow = grid.getRow(rowEntity);\n          }\n\n          if (colDef !== null) {\n            gridCol = grid.getColumn(colDef.name ? colDef.name : colDef.field);\n          }\n          this.scrollToInternal(grid, gridRow, gridCol);\n\n          var rowCol = { row: gridRow, col: gridCol };\n\n          // Broadcast the navigation\n          grid.cellNav.broadcastCellNav(rowCol);\n\n        },\n\n        /**\n         * @ngdoc method\n         * @methodOf ui.grid.cellNav.service:uiGridCellNavService\n         * @name scrollToInternal\n         * @description Like scrollTo, but takes gridRow and gridCol.\n         * In calculating the scroll height we have to deal with wanting\n         * 0% for the first row, and 100% for the last row.  Normal maths\n         * for a 10 row list would return 1/10 = 10% for the first row, so\n         * we need to tweak the numbers to add an extra 10% somewhere.  The\n         * formula if we're trying to get to row 0 in a 10 row list (assuming our\n         * index is zero based, so the last row is row 9) is:\n         * <pre>\n         *   0 + 0 / 10 = 0%\n         * </pre>\n         *\n         * To get to row 9 (i.e. the last row) in the same list, we want to\n         * go to:\n         * <pre>\n         *  ( 9 + 1 ) / 10 = 100%\n         * </pre>\n         * So we need to apportion one whole row within the overall grid scroll,\n         * the formula is:\n         * <pre>\n         *   ( index + ( index / (total rows - 1) ) / total rows\n         * </pre>\n         * @param {Grid} grid the grid you'd like to act upon, usually available\n         * from gridApi.grid\n         * @param {GridRow} gridRow row to make visible\n         * @param {GridCol} gridCol column to make visible\n         */\n        scrollToInternal: function (grid, gridRow, gridCol) {\n          var scrollEvent = new ScrollEvent(grid,null,null,'uiGridCellNavService.scrollToInternal');\n\n          if (gridRow !== null) {\n            var seekRowIndex = grid.renderContainers.body.visibleRowCache.indexOf(gridRow);\n            var totalRows = grid.renderContainers.body.visibleRowCache.length;\n            var percentage = ( seekRowIndex + ( seekRowIndex / ( totalRows - 1 ) ) ) / totalRows;\n            scrollEvent.y = { percentage:  percentage  };\n          }\n\n          if (gridCol !== null) {\n            scrollEvent.x = { percentage: this.getLeftWidth(grid, gridCol) / this.getLeftWidth(grid, grid.renderContainers.body.visibleColumnCache[grid.renderContainers.body.visibleColumnCache.length - 1] ) };\n          }\n\n          if (scrollEvent.y || scrollEvent.x) {\n            scrollEvent.fireScrollingEvent();\n          }\n        },\n\n        /**\n         * @ngdoc method\n         * @methodOf ui.grid.cellNav.service:uiGridCellNavService\n         * @name scrollToIfNecessary\n         * @description Scrolls the grid to make a certain row and column combo visible,\n         *   in the case that it is not completely visible on the screen already.\n         * @param {Grid} grid the grid you'd like to act upon, usually available\n         * from gridApi.grid\n         * @param {GridRow} gridRow row to make visible\n         * @param {GridCol} gridCol column to make visible\n         */\n        scrollToIfNecessary: function (grid, gridRow, gridCol) {\n          var scrollEvent = new ScrollEvent(grid, 'uiGridCellNavService.scrollToIfNecessary');\n\n          // Alias the visible row and column caches\n          var visRowCache = grid.renderContainers.body.visibleRowCache;\n          var visColCache = grid.renderContainers.body.visibleColumnCache;\n\n          /*-- Get the top, left, right, and bottom \"scrolled\" edges of the grid --*/\n\n          // The top boundary is the current Y scroll position PLUS the header height, because the header can obscure rows when the grid is scrolled downwards\n          var topBound = grid.renderContainers.body.prevScrollTop + grid.headerHeight;\n\n          // Don't the let top boundary be less than 0\n          topBound = (topBound < 0) ? 0 : topBound;\n\n          // The left boundary is the current X scroll position\n          var leftBound = grid.renderContainers.body.prevScrollLeft;\n\n          // The bottom boundary is the current Y scroll position, plus the height of the grid, but minus the header height.\n          //   Basically this is the viewport height added on to the scroll position\n          var bottomBound = grid.renderContainers.body.prevScrollTop + grid.gridHeight - grid.headerHeight;\n\n          // If there's a horizontal scrollbar, remove its height from the bottom boundary, otherwise we'll be letting it obscure rows\n          //if (grid.horizontalScrollbarHeight) {\n          //  bottomBound = bottomBound - grid.horizontalScrollbarHeight;\n          //}\n\n          // The right position is the current X scroll position minus the grid width\n          var rightBound = grid.renderContainers.body.prevScrollLeft + Math.ceil(grid.gridWidth);\n\n          // If there's a vertical scrollbar, subtract it from the right boundary or we'll allow it to obscure cells\n          //if (grid.verticalScrollbarWidth) {\n          //  rightBound = rightBound - grid.verticalScrollbarWidth;\n          //}\n\n          // We were given a row to scroll to\n          if (gridRow !== null) {\n            // This is the index of the row we want to scroll to, within the list of rows that can be visible\n            var seekRowIndex = visRowCache.indexOf(gridRow);\n\n            // Total vertical scroll length of the grid\n            var scrollLength = (grid.renderContainers.body.getCanvasHeight() - grid.renderContainers.body.getViewportHeight());\n\n            // Add the height of the native horizontal scrollbar to the scroll length, if it's there. Otherwise it will mask over the final row\n            //if (grid.horizontalScrollbarHeight && grid.horizontalScrollbarHeight > 0) {\n            //  scrollLength = scrollLength + grid.horizontalScrollbarHeight;\n            //}\n\n            // This is the minimum amount of pixels we need to scroll vertical in order to see this row.\n            var pixelsToSeeRow = ((seekRowIndex + 1) * grid.options.rowHeight);\n\n            // Don't let the pixels required to see the row be less than zero\n            pixelsToSeeRow = (pixelsToSeeRow < 0) ? 0 : pixelsToSeeRow;\n\n            var scrollPixels, percentage;\n\n            // If the scroll position we need to see the row is LESS than the top boundary, i.e. obscured above the top of the grid...\n            if (pixelsToSeeRow < topBound) {\n              // Get the different between the top boundary and the required scroll position and subtract it from the current scroll position\\\n              //   to get the full position we need\n              scrollPixels = grid.renderContainers.body.prevScrollTop - (topBound - pixelsToSeeRow);\n\n              // Turn the scroll position into a percentage and make it an argument for a scroll event\n              percentage = scrollPixels / scrollLength;\n              scrollEvent.y = { percentage: percentage  };\n            }\n            // Otherwise if the scroll position we need to see the row is MORE than the bottom boundary, i.e. obscured below the bottom of the grid...\n            else if (pixelsToSeeRow > bottomBound) {\n              // Get the different between the bottom boundary and the required scroll position and add it to the current scroll position\n              //   to get the full position we need\n              scrollPixels = pixelsToSeeRow - bottomBound + grid.renderContainers.body.prevScrollTop;\n\n              // Turn the scroll position into a percentage and make it an argument for a scroll event\n              percentage = scrollPixels / scrollLength;\n              scrollEvent.y = { percentage: percentage  };\n            }\n          }\n\n          // We were given a column to scroll to\n          if (gridCol !== null) {\n            // This is the index of the row we want to scroll to, within the list of rows that can be visible\n            var seekColumnIndex = visColCache.indexOf(gridCol);\n\n            // Total vertical scroll length of the grid\n            var horizScrollLength = (grid.renderContainers.body.getCanvasWidth() - grid.renderContainers.body.getViewportWidth());\n\n            // Add the height of the native horizontal scrollbar to the scroll length, if it's there. Otherwise it will mask over the final row\n            // if (grid.verticalScrollbarWidth && grid.verticalScrollbarWidth > 0) {\n            //   horizScrollLength = horizScrollLength + grid.verticalScrollbarWidth;\n            // }\n\n            // This is the minimum amount of pixels we need to scroll vertical in order to see this column\n            var columnLeftEdge = 0;\n            for (var i = 0; i < seekColumnIndex; i++) {\n              var col = visColCache[i];\n              columnLeftEdge += col.drawnWidth;\n            }\n            columnLeftEdge = (columnLeftEdge < 0) ? 0 : columnLeftEdge;\n\n            var columnRightEdge = columnLeftEdge + gridCol.drawnWidth;\n\n            // Don't let the pixels required to see the column be less than zero\n            columnRightEdge = (columnRightEdge < 0) ? 0 : columnRightEdge;\n\n            var horizScrollPixels, horizPercentage;\n\n            // If the scroll position we need to see the row is LESS than the top boundary, i.e. obscured above the top of the grid...\n            if (columnLeftEdge < leftBound) {\n              // Get the different between the top boundary and the required scroll position and subtract it from the current scroll position\\\n              //   to get the full position we need\n              horizScrollPixels = grid.renderContainers.body.prevScrollLeft - (leftBound - columnLeftEdge);\n\n              // Turn the scroll position into a percentage and make it an argument for a scroll event\n              horizPercentage = horizScrollPixels / horizScrollLength;\n              horizPercentage = (horizPercentage > 1) ? 1 : horizPercentage;\n              scrollEvent.x = { percentage: horizPercentage  };\n            }\n            // Otherwise if the scroll position we need to see the row is MORE than the bottom boundary, i.e. obscured below the bottom of the grid...\n            else if (columnRightEdge > rightBound) {\n              // Get the different between the bottom boundary and the required scroll position and add it to the current scroll position\n              //   to get the full position we need\n              horizScrollPixels = columnRightEdge - rightBound + grid.renderContainers.body.prevScrollLeft;\n\n              // Turn the scroll position into a percentage and make it an argument for a scroll event\n              horizPercentage = horizScrollPixels / horizScrollLength;\n              horizPercentage = (horizPercentage > 1) ? 1 : horizPercentage;\n              scrollEvent.x = { percentage: horizPercentage  };\n            }\n          }\n\n          // If we need to scroll on either the x or y axes, fire a scroll event\n          if (scrollEvent.y || scrollEvent.x) {\n            scrollEvent.fireScrollingEvent();\n          }\n        },\n\n        /**\n         * @ngdoc method\n         * @methodOf ui.grid.cellNav.service:uiGridCellNavService\n         * @name getLeftWidth\n         * @description Get the current drawn width of the columns in the\n         * grid up to the numbered column, and add an apportionment for the\n         * column that we're on.  So if we are on column 0, we want to scroll\n         * 0% (i.e. exclude this column from calc).  If we're on the last column\n         * we want to scroll to 100% (i.e. include this column in the calc). So\n         * we include (thisColIndex / totalNumberCols) % of this column width\n         * @param {Grid} grid the grid you'd like to act upon, usually available\n         * from gridApi.grid\n         * @param {gridCol} upToCol the column to total up to and including\n         */\n        getLeftWidth: function (grid, upToCol) {\n          var width = 0;\n\n          if (!upToCol) {\n            return width;\n          }\n\n          var lastIndex = grid.renderContainers.body.visibleColumnCache.indexOf( upToCol );\n\n          // total column widths up-to but not including the passed in column\n          grid.renderContainers.body.visibleColumnCache.forEach( function( col, index ) {\n            if ( index < lastIndex ){\n              width += col.drawnWidth;\n            }\n          });\n\n          // pro-rata the final column based on % of total columns.\n          var percentage = lastIndex === 0 ? 0 : (lastIndex + 1) / grid.renderContainers.body.visibleColumnCache.length;\n          width += upToCol.drawnWidth * percentage;\n\n          return width;\n        }\n      };\n\n      return service;\n    }]);\n\n  /**\n   *  @ngdoc directive\n   *  @name ui.grid.cellNav.directive:uiCellNav\n   *  @element div\n   *  @restrict EA\n   *\n   *  @description Adds cell navigation features to the grid columns\n   *\n   *  @example\n   <example module=\"app\">\n   <file name=\"app.js\">\n   var app = angular.module('app', ['ui.grid', 'ui.grid.cellNav']);\n\n   app.controller('MainCtrl', ['$scope', function ($scope) {\n      $scope.data = [\n        { name: 'Bob', title: 'CEO' },\n            { name: 'Frank', title: 'Lowly Developer' }\n      ];\n\n      $scope.columnDefs = [\n        {name: 'name'},\n        {name: 'title'}\n      ];\n    }]);\n   </file>\n   <file name=\"index.html\">\n   <div ng-controller=\"MainCtrl\">\n   <div ui-grid=\"{ data: data, columnDefs: columnDefs }\" ui-grid-cellnav></div>\n   </div>\n   </file>\n   </example>\n   */\n  module.directive('uiGridCellnav', ['gridUtil', 'uiGridCellNavService', 'uiGridCellNavConstants',\n    function (gridUtil, uiGridCellNavService, uiGridCellNavConstants) {\n      return {\n        replace: true,\n        priority: -150,\n        require: '^uiGrid',\n        scope: false,\n        controller: function () {},\n        compile: function () {\n          return {\n            pre: function ($scope, $elm, $attrs, uiGridCtrl) {\n              var _scope = $scope;\n\n              var grid = uiGridCtrl.grid;\n              uiGridCellNavService.initializeGrid(grid);\n\n              uiGridCtrl.cellNav = {};\n\n              uiGridCtrl.cellNav.focusCell = function (row, col) {\n                uiGridCtrl.cellNav.broadcastCellNav({ row: row, col: col });\n              };\n\n              //  gridUtil.logDebug('uiGridEdit preLink');\n              uiGridCtrl.cellNav.broadcastCellNav = grid.cellNav.broadcastCellNav = function (newRowCol, modifierDown) {\n                modifierDown = !(modifierDown === undefined || !modifierDown);\n                uiGridCtrl.cellNav.broadcastFocus(newRowCol, modifierDown);\n                _scope.$broadcast(uiGridCellNavConstants.CELL_NAV_EVENT, newRowCol, modifierDown);\n              };\n\n              uiGridCtrl.cellNav.broadcastFocus = function (rowCol, modifierDown) {\n                modifierDown = !(modifierDown === undefined || !modifierDown);\n\n                var row = rowCol.row,\n                  col = rowCol.col;\n\n                var rowColSelectIndex = uiGridCtrl.grid.api.cellNav.rowColSelectIndex(rowCol);\n\n                if (grid.cellNav.lastRowCol === null || rowColSelectIndex === -1) {\n                  var newRowCol = new RowCol(row, col);\n                  grid.api.cellNav.raise.navigate(newRowCol, grid.cellNav.lastRowCol);\n                  grid.cellNav.lastRowCol = newRowCol;\n                  if (uiGridCtrl.grid.options.modifierKeysToMultiSelectCells && modifierDown) {\n                    grid.cellNav.focusedCells.push(rowCol);\n                  } else {\n                    grid.cellNav.focusedCells = [rowCol];\n                  }\n                } else if (grid.options.modifierKeysToMultiSelectCells && modifierDown &&\n                  rowColSelectIndex >= 0) {\n\n                  grid.cellNav.focusedCells.splice(rowColSelectIndex, 1);\n                }\n              };\n\n              uiGridCtrl.cellNav.handleKeyDown = function (evt) {\n                var direction = uiGridCellNavService.getDirection(evt);\n                if (direction === null) {\n                  return true;\n                }\n\n                var containerId = 'body';\n                if (evt.uiGridTargetRenderContainerId) {\n                  containerId = evt.uiGridTargetRenderContainerId;\n                }\n\n                // Get the last-focused row+col combo\n                var lastRowCol = uiGridCtrl.grid.api.cellNav.getFocusedCell();\n                if (lastRowCol) {\n                  // Figure out which new row+combo we're navigating to\n                  var rowCol = uiGridCtrl.grid.renderContainers[containerId].cellNav.getNextRowCol(direction, lastRowCol.row, lastRowCol.col);\n\n                  rowCol.eventType = uiGridCellNavConstants.EVENT_TYPE.KEYDOWN;\n\n                  // Broadcast the navigation\n                  uiGridCtrl.cellNav.broadcastCellNav(rowCol);\n\n                  // Scroll to the new cell, if it's not completely visible within the render container's viewport\n                  uiGridCellNavService.scrollToIfNecessary(grid, rowCol.row, rowCol.col);\n\n                  evt.stopPropagation();\n                  evt.preventDefault();\n\n                  return false;\n                }\n              };\n            },\n            post: function ($scope, $elm, $attrs, uiGridCtrl) {\n            }\n          };\n        }\n      };\n    }]);\n\n  module.directive('uiGridRenderContainer', ['$timeout', '$document', 'gridUtil', 'uiGridConstants', 'uiGridCellNavService', 'uiGridCellNavConstants',\n    function ($timeout, $document, gridUtil, uiGridConstants, uiGridCellNavService, uiGridCellNavConstants) {\n      return {\n        replace: true,\n        priority: -99999, //this needs to run very last\n        require: ['^uiGrid', 'uiGridRenderContainer', '?^uiGridCellnav'],\n        scope: false,\n        compile: function () {\n          return {\n            post: function ($scope, $elm, $attrs, controllers) {\n              var uiGridCtrl = controllers[0],\n                 renderContainerCtrl = controllers[1];\n\n              // Skip attaching cell-nav specific logic if the directive is not attached above us\n              if (!uiGridCtrl.grid.api.cellNav) { return; }\n\n              var containerId = renderContainerCtrl.containerId;\n\n              var grid = uiGridCtrl.grid;\n\n              // Needs to run last after all renderContainers are built\n              uiGridCellNavService.decorateRenderContainers(grid);\n\n              // Let the render container be focus-able\n              $elm.attr(\"tabindex\", -1);\n\n              // Bind to keydown events in the render container\n              $elm.on('keydown', function (evt) {\n                evt.uiGridTargetRenderContainerId = containerId;\n                return uiGridCtrl.cellNav.handleKeyDown(evt);\n              });\n\n              var needFocus = false;\n              \n              // When there's a scroll event we need to make sure to re-focus the right row, because the cell contents may have changed\n              grid.api.core.on.scrollEvent($scope, function (args) {\n                // Skip if not this grid that the event was broadcast for\n                if (args.grid && args.grid.id !== uiGridCtrl.grid.id) {\n                  return;\n                }\n\n                // Skip if there's no currently-focused cell\n                if (uiGridCtrl.grid.api.cellNav.getFocusedCell() == null) {\n                  return;\n                }\n                \n                /*\n                 * If we have scrolled due to cellNav, we want to set the focus to the new cell after the \n                 * virtualisation has run, and after scroll.  If we scrolled through the browser scroll\n                 * bar or other user action, we're going to discard the focus, because it will no longer \n                 * be valid (and, noting #2423, trying to keep it causes problems)\n                 * \n                 * If cellNav triggers the scroll, we get a scrollToIfNecessary, then a viewport scroll. We\n                 * want to wait for the viewport scroll to finish, then do a refocus.  \n                 * \n                 * If someone manually scrolls we get just the viewport scroll, no scrollToIfNecessary.  We\n                 * want to just clear the focus\n                 * \n                 * Logic is:\n                 *  - if cellNav scroll, set a flag that will be resolved in the native scroll\n                 *  - if native scroll, look for the cellNav promise and resolve it\n                 *    - if not present, then use a timeout to clear focus\n                 *    - if it is present, then instead use a timeout to set focus\n                 */ \n                \n                // We have to wrap in TWO timeouts so that we run AFTER the scroll event is resolved.\n                if ( args.source === 'uiGridCellNavService.scrollToIfNecessary'){\n                  needFocus = true;\n/*\n                  focusTimeout = $timeout(function () {\n                    if ( clearFocusTimeout ){\n                      $timeout.cancel(clearFocusTimeout);\n                    }\n                    focusTimeout = $timeout(function () {\n                      if ( clearFocusTimeout ){\n                        $timeout.cancel(clearFocusTimeout);\n                      }\n                      // Get the last row+col combo\n                      var lastRowCol = uiGridCtrl.grid.api.cellNav.getFocusedCell();\n  \n                      // If the body element becomes active, re-focus on the render container so we can capture cellNav events again.\n                      //   NOTE: this happens when we navigate LET from the left-most cell (RIGHT from the right-most) and have to re-render a new\n                      //   set of cells. The cell element we are navigating to doesn't exist and focus gets lost. This will re-capture it, imperfectly...\n                      if ($document.activeElement === $document.body) {\n                        $elm[0].focus();\n                      }\n  \n                      // broadcast a cellNav event so we clear the focus on all cells\n                      uiGridCtrl.cellNav.broadcastCellNav(lastRowCol);\n                    });\n                  });\n                  */\n                } else {\n                  if ( needFocus ){\n                    $timeout(function () {\n                      $timeout(function () {\n                        // Get the last row+col combo\n                        var lastRowCol = uiGridCtrl.grid.api.cellNav.getFocusedCell();\n    \n                        // If the body element becomes active, re-focus on the render container so we can capture cellNav events again.\n                        //   NOTE: this happens when we navigate LET from the left-most cell (RIGHT from the right-most) and have to re-render a new\n                        //   set of cells. The cell element we are navigating to doesn't exist and focus gets lost. This will re-capture it, imperfectly...\n                        if ($document.activeElement === $document.body) {\n                          $elm[0].focus();\n                        }\n    \n                        // broadcast a cellNav event so we clear the focus on all cells\n                        uiGridCtrl.cellNav.broadcastCellNav(lastRowCol);\n                        \n                        needFocus = false;\n                      });\n                    });\n                  }\n                }\n              });  \n             \n            }\n          };\n        }\n      };\n    }]);\n\n  /**\n   *  @ngdoc directive\n   *  @name ui.grid.cellNav.directive:uiGridCell\n   *  @element div\n   *  @restrict A\n   *  @description Stacks on top of ui.grid.uiGridCell to provide cell navigation\n   */\n  module.directive('uiGridCell', ['$timeout', '$document', 'uiGridCellNavService', 'gridUtil', 'uiGridCellNavConstants', 'uiGridConstants',\n    function ($timeout, $document, uiGridCellNavService, gridUtil, uiGridCellNavConstants, uiGridConstants) {\n      return {\n        priority: -150, // run after default uiGridCell directive and ui.grid.edit uiGridCell\n        restrict: 'A',\n        require: '^uiGrid',\n        scope: false,\n        link: function ($scope, $elm, $attrs, uiGridCtrl) {\n          // Skip attaching cell-nav specific logic if the directive is not attached above us\n          if (!uiGridCtrl.grid.api.cellNav) { return; }\n\n          if (!$scope.col.colDef.allowCellFocus) {\n            return;\n          }\n\n          setTabEnabled();\n\n          // When a cell is clicked, broadcast a cellNav event saying that this row+col combo is now focused\n          $elm.find('div').on('click', function (evt) {\n            uiGridCtrl.cellNav.broadcastCellNav(new RowCol($scope.row, $scope.col), evt.ctrlKey || evt.metaKey);\n\n            evt.stopPropagation();\n          });\n\n          // This event is fired for all cells.  If the cell matches, then focus is set\n          $scope.$on(uiGridCellNavConstants.CELL_NAV_EVENT, function (evt, rowCol, modifierDown) {\n            if (rowCol.row === $scope.row &&\n              rowCol.col === $scope.col) {\n              if (uiGridCtrl.grid.options.modifierKeysToMultiSelectCells && modifierDown &&\n                uiGridCtrl.grid.api.cellNav.rowColSelectIndex(rowCol) === -1) {\n                clearFocus();\n              } else {\n                setFocused();\n              }\n\n              // This cellNav event came from a keydown event so we can safely refocus\n              if (rowCol.hasOwnProperty('eventType') && rowCol.eventType === uiGridCellNavConstants.EVENT_TYPE.KEYDOWN) {\n                $elm.find('div')[0].focus();\n              }\n            }\n            else if (!(uiGridCtrl.grid.options.modifierKeysToMultiSelectCells && modifierDown)) {\n              clearFocus();\n            }\n          });\n\n          function setTabEnabled() {\n            $elm.find('div').attr(\"tabindex\", -1);\n          }\n\n          function setFocused() {\n            var div = $elm.find('div');\n            div.addClass('ui-grid-cell-focus');\n          }\n\n          function clearFocus() {\n            var div = $elm.find('div');\n            div.removeClass('ui-grid-cell-focus');\n          }\n\n          $scope.$on('$destroy', function () {\n            $elm.find('div').off('click');\n          });\n        }\n      };\n    }]);\n\n})();\n\n(function () {\n  'use strict';\n\n  /**\n   * @ngdoc overview\n   * @name ui.grid.edit\n   * @description\n   *\n   *  # ui.grid.edit\n   * This module provides cell editing capability to ui.grid. The goal was to emulate keying data in a spreadsheet via\n   * a keyboard.\n   * <br/>\n   * <br/>\n   * To really get the full spreadsheet-like data entry, the ui.grid.cellNav module should be used. This will allow the\n   * user to key data and then tab, arrow, or enter to the cells beside or below.\n   *\n   * <div doc-module-components=\"ui.grid.edit\"></div>\n   */\n\n  var module = angular.module('ui.grid.edit', ['ui.grid']);\n\n  /**\n   *  @ngdoc object\n   *  @name ui.grid.edit.constant:uiGridEditConstants\n   *\n   *  @description constants available in edit module\n   */\n  module.constant('uiGridEditConstants', {\n    EDITABLE_CELL_TEMPLATE: /EDITABLE_CELL_TEMPLATE/g,\n    //must be lowercase because template bulder converts to lower\n    EDITABLE_CELL_DIRECTIVE: /editable_cell_directive/g,\n    events: {\n      BEGIN_CELL_EDIT: 'uiGridEventBeginCellEdit',\n      END_CELL_EDIT: 'uiGridEventEndCellEdit',\n      CANCEL_CELL_EDIT: 'uiGridEventCancelCellEdit'\n    }\n  });\n\n  /**\n   *  @ngdoc service\n   *  @name ui.grid.edit.service:uiGridEditService\n   *\n   *  @description Services for editing features\n   */\n  module.service('uiGridEditService', ['$q', '$templateCache', 'uiGridConstants', 'gridUtil',\n    function ($q, $templateCache, uiGridConstants, gridUtil) {\n\n      var service = {\n\n        initializeGrid: function (grid) {\n\n          service.defaultGridOptions(grid.options);\n\n          grid.registerColumnBuilder(service.editColumnBuilder);\n\n          /**\n           *  @ngdoc object\n           *  @name ui.grid.edit.api:PublicApi\n           *\n           *  @description Public Api for edit feature\n           */\n          var publicApi = {\n            events: {\n              edit: {\n                /**\n                 * @ngdoc event\n                 * @name afterCellEdit\n                 * @eventOf  ui.grid.edit.api:PublicApi\n                 * @description raised when cell editing is complete\n                 * <pre>\n                 *      gridApi.edit.on.afterCellEdit(scope,function(rowEntity, colDef){})\n                 * </pre>\n                 * @param {object} rowEntity the options.data element that was edited\n                 * @param {object} colDef the column that was edited\n                 * @param {object} newValue new value\n                 * @param {object} oldValue old value\n                 */\n                afterCellEdit: function (rowEntity, colDef, newValue, oldValue) {\n                },\n                /**\n                 * @ngdoc event\n                 * @name beginCellEdit\n                 * @eventOf  ui.grid.edit.api:PublicApi\n                 * @description raised when cell editing starts on a cell\n                 * <pre>\n                 *      gridApi.edit.on.beginCellEdit(scope,function(rowEntity, colDef){})\n                 * </pre>\n                 * @param {object} rowEntity the options.data element that was edited\n                 * @param {object} colDef the column that was edited\n                 */\n                beginCellEdit: function (rowEntity, colDef) {\n                },\n                /**\n                 * @ngdoc event\n                 * @name cancelCellEdit\n                 * @eventOf  ui.grid.edit.api:PublicApi\n                 * @description raised when cell editing is cancelled on a cell\n                 * <pre>\n                 *      gridApi.edit.on.cancelCellEdit(scope,function(rowEntity, colDef){})\n                 * </pre>\n                 * @param {object} rowEntity the options.data element that was edited\n                 * @param {object} colDef the column that was edited\n                 */\n                cancelCellEdit: function (rowEntity, colDef) {\n                }\n              }\n            },\n            methods: {\n              edit: { }\n            }\n          };\n\n          grid.api.registerEventsFromObject(publicApi.events);\n          //grid.api.registerMethodsFromObject(publicApi.methods);\n\n        },\n\n        defaultGridOptions: function (gridOptions) {\n\n          /**\n           *  @ngdoc object\n           *  @name ui.grid.edit.api:GridOptions\n           *\n           *  @description Options for configuring the edit feature, these are available to be\n           *  set using the ui-grid {@link ui.grid.class:GridOptions gridOptions}\n           */\n\n          /**\n           *  @ngdoc object\n           *  @name enableCellEdit\n           *  @propertyOf  ui.grid.edit.api:GridOptions\n           *  @description If defined, sets the default value for the editable flag on each individual colDefs\n           *  if their individual enableCellEdit configuration is not defined. Defaults to undefined.\n           */\n\n          /**\n           *  @ngdoc object\n           *  @name cellEditableCondition\n           *  @propertyOf  ui.grid.edit.api:GridOptions\n           *  @description If specified, either a value or function to be used by all columns before editing.\n           *  If falsy, then editing of cell is not allowed.\n           *  @example\n           *  <pre>\n           *  function($scope){\n           *    //use $scope.row.entity and $scope.col.colDef to determine if editing is allowed\n           *    return true;\n           *  }\n           *  </pre>\n           */\n          gridOptions.cellEditableCondition = gridOptions.cellEditableCondition === undefined ? true : gridOptions.cellEditableCondition;\n\n          /**\n           *  @ngdoc object\n           *  @name editableCellTemplate\n           *  @propertyOf  ui.grid.edit.api:GridOptions\n           *  @description If specified, cellTemplate to use as the editor for all columns.\n           *  <br/> defaults to 'ui-grid/cellTextEditor'\n           */\n\n          /**\n           *  @ngdoc object\n           *  @name enableCellEditOnFocus\n           *  @propertyOf  ui.grid.edit.api:GridOptions\n           *  @description If true, then editor is invoked as soon as cell receives focus. Default false.\n           *  <br/>_requires cellNav feature and the edit feature to be enabled_\n           */\n            //enableCellEditOnFocus can only be used if cellnav module is used\n          gridOptions.enableCellEditOnFocus = gridOptions.enableCellEditOnFocus === undefined ? false : gridOptions.enableCellEditOnFocus;\n        },\n\n        /**\n         * @ngdoc service\n         * @name editColumnBuilder\n         * @methodOf ui.grid.edit.service:uiGridEditService\n         * @description columnBuilder function that adds edit properties to grid column\n         * @returns {promise} promise that will load any needed templates when resolved\n         */\n        editColumnBuilder: function (colDef, col, gridOptions) {\n\n          var promises = [];\n\n          /**\n           *  @ngdoc object\n           *  @name ui.grid.edit.api:ColumnDef\n           *\n           *  @description Column Definition for edit feature, these are available to be\n           *  set using the ui-grid {@link ui.grid.class:GridOptions.columnDef gridOptions.columnDefs}\n           */\n\n          /**\n           *  @ngdoc object\n           *  @name enableCellEdit\n           *  @propertyOf  ui.grid.edit.api:ColumnDef\n           *  @description enable editing on column\n           */\n          colDef.enableCellEdit = colDef.enableCellEdit === undefined ? (gridOptions.enableCellEdit === undefined ?\n            (colDef.type !== 'object') : gridOptions.enableCellEdit) : colDef.enableCellEdit;\n\n          /**\n           *  @ngdoc object\n           *  @name cellEditableCondition\n           *  @propertyOf  ui.grid.edit.api:ColumnDef\n           *  @description If specified, either a value or function evaluated before editing cell.  If falsy, then editing of cell is not allowed.\n           *  @example\n           *  <pre>\n           *  function($scope){\n           *    //use $scope.row.entity and $scope.col.colDef to determine if editing is allowed\n           *    return true;\n           *  }\n           *  </pre>\n           */\n          colDef.cellEditableCondition = colDef.cellEditableCondition === undefined ? gridOptions.cellEditableCondition :  colDef.cellEditableCondition;\n\n          /**\n           *  @ngdoc object\n           *  @name editableCellTemplate\n           *  @propertyOf  ui.grid.edit.api:ColumnDef\n           *  @description cell template to be used when editing this column. Can be Url or text template\n           *  <br/>Defaults to gridOptions.editableCellTemplate\n           */\n          if (colDef.enableCellEdit) {\n            colDef.editableCellTemplate = colDef.editableCellTemplate || gridOptions.editableCellTemplate || 'ui-grid/cellEditor';\n\n            promises.push(gridUtil.getTemplate(colDef.editableCellTemplate)\n              .then(\n              function (template) {\n                col.editableCellTemplate = template;\n              },\n              function (res) {\n                // Todo handle response error here?\n                throw new Error(\"Couldn't fetch/use colDef.editableCellTemplate '\" + colDef.editableCellTemplate + \"'\");\n              }));\n          }\n\n          /**\n           *  @ngdoc object\n           *  @name enableCellEditOnFocus\n           *  @propertyOf  ui.grid.edit.api:ColumnDef\n           *  @requires ui.grid.cellNav\n           *  @description If true, then editor is invoked as soon as cell receives focus. Default false.\n           *  <br>_requires both the cellNav feature and the edit feature to be enabled_\n           */\n            //enableCellEditOnFocus can only be used if cellnav module is used\n          colDef.enableCellEditOnFocus = colDef.enableCellEditOnFocus === undefined ? gridOptions.enableCellEditOnFocus : colDef.enableCellEditOnFocus;\n\n          return $q.all(promises);\n        },\n\n        /**\n         * @ngdoc service\n         * @name isStartEditKey\n         * @methodOf ui.grid.edit.service:uiGridEditService\n         * @description  Determines if a keypress should start editing.  Decorate this service to override with your\n         * own key events.  See service decorator in angular docs.\n         * @param {Event} evt keydown event\n         * @returns {boolean} true if an edit should start\n         */\n        isStartEditKey: function (evt) {\n          if (evt.keyCode === uiGridConstants.keymap.LEFT ||\n            (evt.keyCode === uiGridConstants.keymap.TAB && evt.shiftKey) ||\n\n            evt.keyCode === uiGridConstants.keymap.RIGHT ||\n            evt.keyCode === uiGridConstants.keymap.TAB ||\n\n            evt.keyCode === uiGridConstants.keymap.UP ||\n            (evt.keyCode === uiGridConstants.keymap.ENTER && evt.shiftKey) ||\n\n            evt.keyCode === uiGridConstants.keymap.DOWN ||\n            evt.keyCode === uiGridConstants.keymap.ENTER) {\n            return false;\n\n          }\n          return true;\n        }\n\n\n      };\n\n      return service;\n\n    }]);\n\n  /**\n   *  @ngdoc directive\n   *  @name ui.grid.edit.directive:uiGridEdit\n   *  @element div\n   *  @restrict A\n   *\n   *  @description Adds editing features to the ui-grid directive.\n   *\n   *  @example\n   <example module=\"app\">\n   <file name=\"app.js\">\n   var app = angular.module('app', ['ui.grid', 'ui.grid.edit']);\n\n   app.controller('MainCtrl', ['$scope', function ($scope) {\n      $scope.data = [\n        { name: 'Bob', title: 'CEO' },\n            { name: 'Frank', title: 'Lowly Developer' }\n      ];\n\n      $scope.columnDefs = [\n        {name: 'name', enableCellEdit: true},\n        {name: 'title', enableCellEdit: true}\n      ];\n    }]);\n   </file>\n   <file name=\"index.html\">\n   <div ng-controller=\"MainCtrl\">\n   <div ui-grid=\"{ data: data, columnDefs: columnDefs }\" ui-grid-edit></div>\n   </div>\n   </file>\n   </example>\n   */\n  module.directive('uiGridEdit', ['gridUtil', 'uiGridEditService', function (gridUtil, uiGridEditService) {\n    return {\n      replace: true,\n      priority: 0,\n      require: '^uiGrid',\n      scope: false,\n      compile: function () {\n        return {\n          pre: function ($scope, $elm, $attrs, uiGridCtrl) {\n            uiGridEditService.initializeGrid(uiGridCtrl.grid);\n          },\n          post: function ($scope, $elm, $attrs, uiGridCtrl) {\n          }\n        };\n      }\n    };\n  }]);\n\n  /**\n   *  @ngdoc directive\n   *  @name ui.grid.edit.directive:uiGridCell\n   *  @element div\n   *  @restrict A\n   *\n   *  @description Stacks on top of ui.grid.uiGridCell to provide in-line editing capabilities to the cell\n   *  Editing Actions.\n   *\n   *  Binds edit start events to the uiGridCell element.  When the events fire, the gridCell element is appended\n   *  with the columnDef.editableCellTemplate element ('cellEditor.html' by default).\n   *\n   *  The editableCellTemplate should respond to uiGridEditConstants.events.BEGIN\\_CELL\\_EDIT angular event\n   *  and do the initial steps needed to edit the cell (setfocus on input element, etc).\n   *\n   *  When the editableCellTemplate recognizes that the editing is ended (blur event, Enter key, etc.)\n   *  it should emit the uiGridEditConstants.events.END\\_CELL\\_EDIT event.\n   *\n   *  If editableCellTemplate recognizes that the editing has been cancelled (esc key)\n   *  it should emit the uiGridEditConstants.events.CANCEL\\_CELL\\_EDIT event.  The original value\n   *  will be set back on the model by the uiGridCell directive.\n   *\n   *  Events that invoke editing:\n   *    - dblclick\n   *    - F2 keydown (when using cell selection)\n   *\n   *  Events that end editing:\n   *    - Dependent on the specific editableCellTemplate\n   *    - Standards should be blur and enter keydown\n   *\n   *  Events that cancel editing:\n   *    - Dependent on the specific editableCellTemplate\n   *    - Standards should be Esc keydown\n   *\n   *  Grid Events that end editing:\n   *    - uiGridConstants.events.GRID_SCROLL\n   *\n   */\n\n  /**\n   *  @ngdoc object\n   *  @name ui.grid.edit.api:GridRow\n   *\n   *  @description GridRow options for edit feature, these are available to be\n   *  set internally only, by other features\n   */\n\n  /**\n   *  @ngdoc object\n   *  @name enableCellEdit\n   *  @propertyOf  ui.grid.edit.api:GridRow\n   *  @description enable editing on row, grouping for example might disable editing on group header rows\n   */\n\n  module.directive('uiGridCell',\n    ['$compile', '$injector', '$timeout', 'uiGridConstants', 'uiGridEditConstants', 'gridUtil', '$parse', 'uiGridEditService',\n      function ($compile, $injector, $timeout, uiGridConstants, uiGridEditConstants, gridUtil, $parse, uiGridEditService) {\n        var touchstartTimeout = 500;\n\n        return {\n          priority: -100, // run after default uiGridCell directive\n          restrict: 'A',\n          scope: false,\n          require: '?^uiGrid',\n          link: function ($scope, $elm, $attrs, uiGridCtrl) {\n            if (!$scope.col.colDef.enableCellEdit || $scope.row.enableCellEdit === false) {\n              return;\n            }\n\n            var html;\n            var origCellValue;\n            var inEdit = false;\n            var isFocusedBeforeEdit = false;\n            var cellModel;\n            var cancelTouchstartTimeout;\n\n            var editCellScope;\n\n            registerBeginEditEvents();\n\n            function registerBeginEditEvents() {\n              $elm.on('dblclick', beginEdit);\n              $elm.on('keydown', beginEditKeyDown);\n              if ($scope.col.colDef.enableCellEditOnFocus) {\n                $elm.find('div').on('focus', beginEditFocus);\n              }\n\n              // Add touchstart handling. If the users starts a touch and it doesn't end after X milliseconds, then start the edit\n              $elm.on('touchstart', touchStart);\n            }\n\n            function touchStart(event) {\n              // jQuery masks events\n              if (typeof(event.originalEvent) !== 'undefined' && event.originalEvent !== undefined) {\n                event = event.originalEvent;\n              }\n\n              // Bind touchend handler\n              $elm.on('touchend', touchEnd);\n\n              // Start a timeout\n              cancelTouchstartTimeout = $timeout(function() { }, touchstartTimeout);\n\n              // Timeout's done! Start the edit\n              cancelTouchstartTimeout.then(function () {\n                // Use setTimeout to start the edit because beginEdit expects to be outside of $digest\n                setTimeout(beginEdit, 0);\n\n                // Undbind the touchend handler, we don't need it anymore\n                $elm.off('touchend', touchEnd);\n              });\n            }\n\n            // Cancel any touchstart timeout\n            function touchEnd(event) {\n              $timeout.cancel(cancelTouchstartTimeout);\n              $elm.off('touchend', touchEnd);\n            }\n\n            function cancelBeginEditEvents() {\n              $elm.off('dblclick', beginEdit);\n              $elm.off('keydown', beginEditKeyDown);\n              if ($scope.col.colDef.enableCellEditOnFocus) {\n                $elm.find('div').off('focus', beginEditFocus);\n              }\n              $elm.off('touchstart', touchStart);\n            }\n\n            function beginEditFocus(evt) {\n              // gridUtil.logDebug('begin edit');\n              if (uiGridCtrl && uiGridCtrl.cellNav) {\n                // NOTE(c0bra): This is causing a loop where focusCell causes beginEditFocus to be called....\n                uiGridCtrl.cellNav.focusCell($scope.row, $scope.col);\n              }\n\n              evt.stopPropagation();\n              beginEdit();\n            }\n\n            // If the cellNagv module is installed and we can get the uiGridCellNavConstants value injected,\n            //   then if the column has enableCellEditOnFocus set to true, we need to listen for cellNav events\n            //   to this cell and start editing when the \"focus\" reaches us\n            try {\n              var uiGridCellNavConstants = $injector.get('uiGridCellNavConstants');\n\n              if ($scope.col.colDef.enableCellEditOnFocus) {\n                $scope.$on(uiGridCellNavConstants.CELL_NAV_EVENT, function (evt, rowCol) {\n                  if (rowCol.row === $scope.row && rowCol.col === $scope.col) {\n                    beginEdit();\n                  }\n                  else {\n                    endEdit();\n                  }\n                });\n              }\n            }\n            catch (e) {}\n\n            function beginEditKeyDown(evt) {\n              if (uiGridEditService.isStartEditKey(evt)) {\n                beginEdit();\n              }\n            }\n\n            function shouldEdit(col, row) {\n              return !row.isSaving &&\n                ( angular.isFunction(col.colDef.cellEditableCondition) ?\n                    col.colDef.cellEditableCondition($scope) :\n                    col.colDef.cellEditableCondition );\n            }\n\n\n            /**\n             *  @ngdoc property\n             *  @name editDropdownOptionsArray\n             *  @propertyOf ui.grid.edit.api:ColumnDef\n             *  @description an array of values in the format\n             *  [ {id: xxx, value: xxx} ], which is populated\n             *  into the edit dropdown\n             *\n             */\n            /**\n             *  @ngdoc property\n             *  @name editDropdownIdLabel\n             *  @propertyOf ui.grid.edit.api:ColumnDef\n             *  @description the label for the \"id\" field\n             *  in the editDropdownOptionsArray.  Defaults\n             *  to 'id'\n             *  @example\n             *  <pre>\n             *    $scope.gridOptions = {\n             *      columnDefs: [\n             *        {name: 'status', editableCellTemplate: 'ui-grid/dropdownEditor',\n             *          editDropdownOptionsArray: [{code: 1, status: 'active'}, {code: 2, status: 'inactive'}],\n             *          editDropdownIdLabel: 'code', editDropdownValueLabel: 'status' }\n             *      ],\n             *  </pre>\n             *\n             */\n            /**\n             *  @ngdoc property\n             *  @name editDropdownRowEntityOptionsArrayPath\n             *  @propertyOf ui.grid.edit.api:ColumnDef\n             *  @description a path to a property on row.entity containing an\n             *  array of values in the format\n             *  [ {id: xxx, value: xxx} ], which will be used to populate\n             *  the edit dropdown.  This can be used when the dropdown values are dependent on\n             *  the backing row entity.\n             *  If this property is set then editDropdownOptionsArray will be ignored.\n             *  @example\n             *  <pre>\n             *    $scope.gridOptions = {\n             *      columnDefs: [\n             *        {name: 'status', editableCellTemplate: 'ui-grid/dropdownEditor',\n             *          editDropdownRowEntityOptionsArrayPath: 'foo.bars[0].baz',\n             *          editDropdownIdLabel: 'code', editDropdownValueLabel: 'status' }\n             *      ],\n             *  </pre>\n             *\n             */\n            /**\n             *  @ngdoc property\n             *  @name editDropdownValueLabel\n             *  @propertyOf ui.grid.edit.api:ColumnDef\n             *  @description the label for the \"value\" field\n             *  in the editDropdownOptionsArray.  Defaults\n             *  to 'value'\n             *  @example\n             *  <pre>\n             *    $scope.gridOptions = {\n             *      columnDefs: [\n             *        {name: 'status', editableCellTemplate: 'ui-grid/dropdownEditor',\n             *          editDropdownOptionsArray: [{code: 1, status: 'active'}, {code: 2, status: 'inactive'}],\n             *          editDropdownIdLabel: 'code', editDropdownValueLabel: 'status' }\n             *      ],\n             *  </pre>\n             *\n             */\n            /**\n             *  @ngdoc property\n             *  @name editDropdownFilter\n             *  @propertyOf ui.grid.edit.api:ColumnDef\n             *  @description A filter that you would like to apply to the values in the options list\n             *  of the dropdown.  For example if you were using angular-translate you might set this\n             *  to `'translate'`\n             *  @example\n             *  <pre>\n             *    $scope.gridOptions = {\n             *      columnDefs: [\n             *        {name: 'status', editableCellTemplate: 'ui-grid/dropdownEditor',\n             *          editDropdownOptionsArray: [{code: 1, status: 'active'}, {code: 2, status: 'inactive'}],\n             *          editDropdownIdLabel: 'code', editDropdownValueLabel: 'status', editDropdownFilter: 'translate' }\n             *      ],\n             *  </pre>\n             *\n             */\n            function beginEdit() {\n              // If we are already editing, then just skip this so we don't try editing twice...\n              if (inEdit) {\n                return;\n              }\n\n              if (!shouldEdit($scope.col, $scope.row)) {\n                return;\n              }\n\n              // if the cell isn't fully visible, and cellNav is present, scroll it to be fully visible before we start\n              if ( $scope.grid.api.cellNav ){\n                $scope.grid.api.cellNav.scrollToIfNecessary( $scope, $scope.row, $scope.col );\n              }\n              \n              cellModel = $parse($scope.row.getQualifiedColField($scope.col));\n              //get original value from the cell\n              origCellValue = cellModel($scope);\n\n              html = $scope.col.editableCellTemplate;\n              html = html.replace(uiGridConstants.MODEL_COL_FIELD, $scope.row.getQualifiedColField($scope.col));\n\n              var optionFilter = $scope.col.colDef.editDropdownFilter ? '|' + $scope.col.colDef.editDropdownFilter : '';\n              html = html.replace(uiGridConstants.CUSTOM_FILTERS, optionFilter);\n\n              var inputType = 'text';\n              switch ($scope.col.colDef.type){\n                case 'boolean':\n                  inputType = 'checkbox';\n                  break;\n                case 'number':\n                  inputType = 'number';\n                  break;\n                case 'date':\n                  inputType = 'date';\n                  break;\n              }\n              html = html.replace('INPUT_TYPE', inputType);\n\n              var editDropdownRowEntityOptionsArrayPath = $scope.col.colDef.editDropdownRowEntityOptionsArrayPath;\n              if (editDropdownRowEntityOptionsArrayPath) {\n                $scope.editDropdownOptionsArray =  resolveObjectFromPath($scope.row.entity, editDropdownRowEntityOptionsArrayPath);\n              }\n              else {\n                $scope.editDropdownOptionsArray = $scope.col.colDef.editDropdownOptionsArray;\n              }\n              $scope.editDropdownIdLabel = $scope.col.colDef.editDropdownIdLabel ? $scope.col.colDef.editDropdownIdLabel : 'id';\n              $scope.editDropdownValueLabel = $scope.col.colDef.editDropdownValueLabel ? $scope.col.colDef.editDropdownValueLabel : 'value';\n\n              var cellElement;\n              $scope.$apply(function () {\n                inEdit = true;\n                cancelBeginEditEvents();\n                var cellElement = angular.element(html);\n                $elm.append(cellElement);\n                editCellScope = $scope.$new();\n                $compile(cellElement)(editCellScope);\n                var gridCellContentsEl = angular.element($elm.children()[0]);\n                isFocusedBeforeEdit = gridCellContentsEl.hasClass('ui-grid-cell-focus');\n                gridCellContentsEl.addClass('ui-grid-cell-contents-hidden');\n              });\n\n              //stop editing when grid is scrolled\n              var deregOnGridScroll = $scope.col.grid.api.core.on.scrollEvent($scope, function () {\n                endEdit(true);\n                $scope.grid.api.edit.raise.afterCellEdit($scope.row.entity, $scope.col.colDef, cellModel($scope), origCellValue);\n                deregOnGridScroll();\n                deregOnEndCellEdit();\n                deregOnCancelCellEdit();\n              });\n\n              //end editing\n              var deregOnEndCellEdit = $scope.$on(uiGridEditConstants.events.END_CELL_EDIT, function (evt, retainFocus) {\n                endEdit(retainFocus);\n                $scope.grid.api.edit.raise.afterCellEdit($scope.row.entity, $scope.col.colDef, cellModel($scope), origCellValue);\n                deregOnEndCellEdit();\n                deregOnGridScroll();\n                deregOnCancelCellEdit();\n              });\n\n              //cancel editing\n              var deregOnCancelCellEdit = $scope.$on(uiGridEditConstants.events.CANCEL_CELL_EDIT, function () {\n                cancelEdit();\n                deregOnCancelCellEdit();\n                deregOnGridScroll();\n                deregOnEndCellEdit();\n              });\n\n              $scope.$broadcast(uiGridEditConstants.events.BEGIN_CELL_EDIT);\n              $scope.grid.api.edit.raise.beginCellEdit($scope.row.entity, $scope.col.colDef);\n            }\n\n            function endEdit(retainFocus) {\n              if (!inEdit) {\n                return;\n              }\n              var gridCellContentsEl = angular.element($elm.children()[0]);\n              //remove edit element\n              editCellScope.$destroy();\n              angular.element($elm.children()[1]).remove();\n              gridCellContentsEl.removeClass('ui-grid-cell-contents-hidden');\n              if (retainFocus && isFocusedBeforeEdit) {\n                gridCellContentsEl[0].focus();\n              }\n              isFocusedBeforeEdit = false;\n              inEdit = false;\n              registerBeginEditEvents();\n              $scope.grid.api.core.notifyDataChange( uiGridConstants.dataChange.EDIT );\n            }\n\n            function cancelEdit() {\n              if (!inEdit) {\n                return;\n              }\n              cellModel.assign($scope, origCellValue);\n              $scope.$apply();\n\n              $scope.grid.api.edit.raise.cancelCellEdit($scope.row.entity, $scope.col.colDef);\n              endEdit(true);\n            }\n\n            // resolves a string path against the given object\n            // shamelessly borrowed from\n            // http://stackoverflow.com/questions/6491463/accessing-nested-javascript-objects-with-string-key\n            function resolveObjectFromPath(object, path) {\n              path = path.replace(/\\[(\\w+)\\]/g, '.$1'); // convert indexes to properties\n              path = path.replace(/^\\./, '');           // strip a leading dot\n              var a = path.split('.');\n              while (a.length) {\n                  var n = a.shift();\n                  if (n in object) {\n                      object = object[n];\n                  } else {\n                      return;\n                  }\n              }\n              return object;\n            }\n\n          }\n        };\n      }]);\n\n  /**\n   *  @ngdoc directive\n   *  @name ui.grid.edit.directive:uiGridEditor\n   *  @element div\n   *  @restrict A\n   *\n   *  @description input editor directive for editable fields.\n   *  Provides EndEdit and CancelEdit events\n   *\n   *  Events that end editing:\n   *     blur and enter keydown\n   *\n   *  Events that cancel editing:\n   *    - Esc keydown\n   *\n   */\n  module.directive('uiGridEditor',\n    ['gridUtil', 'uiGridConstants', 'uiGridEditConstants',\n      function (gridUtil, uiGridConstants, uiGridEditConstants) {\n        return {\n          scope: true,\n          require: ['?^uiGrid', '?^uiGridRenderContainer'],\n          compile: function () {\n            return {\n              pre: function ($scope, $elm, $attrs) {\n\n              },\n              post: function ($scope, $elm, $attrs, controllers) {\n                var uiGridCtrl, renderContainerCtrl;\n                if (controllers[0]) { uiGridCtrl = controllers[0]; }\n                if (controllers[1]) { renderContainerCtrl = controllers[1]; }\n\n                //set focus at start of edit\n                $scope.$on(uiGridEditConstants.events.BEGIN_CELL_EDIT, function () {\n                  $elm[0].focus();\n                  $elm[0].select();\n                  $elm.on('blur', function (evt) {\n                    $scope.stopEdit(evt);\n                  });\n                });\n\n\n               $scope.deepEdit = false;\n\n               $scope.stopEdit = function (evt) {\n                  if ($scope.inputForm && !$scope.inputForm.$valid) {\n                    evt.stopPropagation();\n                    $scope.$emit(uiGridEditConstants.events.CANCEL_CELL_EDIT);\n                  }\n                  else {\n                    $scope.$emit(uiGridEditConstants.events.END_CELL_EDIT);\n                  }\n                  $scope.deepEdit = false;\n                };\n\n                $elm.on('click', function (evt) {\n                  $scope.deepEdit = true;\n                });\n\n                $elm.on('keydown', function (evt) {\n                  switch (evt.keyCode) {\n                    case uiGridConstants.keymap.ESC:\n                      evt.stopPropagation();\n                      $scope.$emit(uiGridEditConstants.events.CANCEL_CELL_EDIT);\n                      break;\n                    case uiGridConstants.keymap.ENTER: // Enter (Leave Field)\n                      $scope.stopEdit(evt);\n                      break;\n                    case uiGridConstants.keymap.TAB:\n                      $scope.stopEdit(evt);\n                      break;\n                  }\n\n                  if ($scope.deepEdit) {\n                    switch (evt.keyCode) {\n                      case uiGridConstants.keymap.LEFT:\n                        evt.stopPropagation();\n                        break;\n                      case uiGridConstants.keymap.RIGHT:\n                        evt.stopPropagation();\n                        break;\n                      case uiGridConstants.keymap.UP:\n                        evt.stopPropagation();\n                        break;\n                      case uiGridConstants.keymap.DOWN:\n                        evt.stopPropagation();\n                        break;\n                    }\n                  }\n                  // Pass the keydown event off to the cellNav service, if it exists\n                  else if (uiGridCtrl && uiGridCtrl.hasOwnProperty('cellNav') && renderContainerCtrl) {\n                    evt.uiGridTargetRenderContainerId = renderContainerCtrl.containerId;\n                    uiGridCtrl.cellNav.handleKeyDown(evt);\n                  }\n\n                  return true;\n                });\n              }\n            };\n          }\n        };\n      }]);\n\n  /**\n   *  @ngdoc directive\n   *  @name ui.grid.edit.directive:input\n   *  @element input\n   *  @restrict E\n   *\n   *  @description directive to provide binding between input[date] value and ng-model for angular 1.2\n   *  It is similar to input[date] directive of angular 1.3\n   *\n   *  Supported date format for input is 'yyyy-MM-dd'\n   *  The directive will set the $valid property of input element and the enclosing form to false if\n   *  model is invalid date or value of input is entered wrong.\n   *\n   */\n    module.directive('uiGridEditor', ['$filter', function ($filter) {\n      function parseDateString(dateString) {\n        if (typeof(dateString) === 'undefined' || dateString === '') {\n          return null;\n        }\n        var parts = dateString.split('-');\n        if (parts.length !== 3) {\n          return null;\n        }\n        var year = parseInt(parts[0], 10);\n        var month = parseInt(parts[1], 10);\n        var day = parseInt(parts[2], 10);\n\n        if (month < 1 || year < 1 || day < 1) {\n          return null;\n        }\n        return new Date(year, (month - 1), day);\n      }\n      return {\n        priority: -100, // run after default uiGridEditor directive\n        require: '?ngModel',\n        link: function (scope, element, attrs, ngModel) {\n\n          if (angular.version.minor === 2 && attrs.type && attrs.type === 'date' && ngModel) {\n\n            ngModel.$formatters.push(function (modelValue) {\n              ngModel.$setValidity(null,(!modelValue || !isNaN(modelValue.getTime())));\n              return $filter('date')(modelValue, 'yyyy-MM-dd');\n            });\n\n            ngModel.$parsers.push(function (viewValue) {\n              if (viewValue && viewValue.length > 0) {\n                var dateValue = parseDateString(viewValue);\n                ngModel.$setValidity(null, (dateValue && !isNaN(dateValue.getTime())));\n                return dateValue;\n              }\n              else {\n                ngModel.$setValidity(null, true);\n                return null;\n              }\n            });\n          }\n        }\n      };\n    }]);\n\n\n  /**\n   *  @ngdoc directive\n   *  @name ui.grid.edit.directive:uiGridEditDropdown\n   *  @element div\n   *  @restrict A\n   *\n   *  @description dropdown editor for editable fields.\n   *  Provides EndEdit and CancelEdit events\n   *\n   *  Events that end editing:\n   *     blur and enter keydown, and any left/right nav\n   *\n   *  Events that cancel editing:\n   *    - Esc keydown\n   *\n   */\n  module.directive('uiGridEditDropdown',\n    ['uiGridConstants', 'uiGridEditConstants',\n      function (uiGridConstants, uiGridEditConstants) {\n        return {\n          scope: true,\n          compile: function () {\n            return {\n              pre: function ($scope, $elm, $attrs) {\n\n              },\n              post: function ($scope, $elm, $attrs) {\n\n                //set focus at start of edit\n                $scope.$on(uiGridEditConstants.events.BEGIN_CELL_EDIT, function () {\n                  $elm[0].focus();\n                  $elm[0].style.width = ($elm[0].parentElement.offsetWidth - 1) + 'px';\n                  $elm.on('blur', function (evt) {\n                    $scope.stopEdit(evt);\n                  });\n                });\n\n\n                $scope.stopEdit = function (evt) {\n                  // no need to validate a dropdown - invalid values shouldn't be\n                  // available in the list\n                  $scope.$emit(uiGridEditConstants.events.END_CELL_EDIT);\n                };\n\n                $elm.on('keydown', function (evt) {\n                  switch (evt.keyCode) {\n                    case uiGridConstants.keymap.ESC:\n                      evt.stopPropagation();\n                      $scope.$emit(uiGridEditConstants.events.CANCEL_CELL_EDIT);\n                      break;\n                    case uiGridConstants.keymap.ENTER: // Enter (Leave Field)\n                      $scope.stopEdit(evt);\n                      break;\n                    case uiGridConstants.keymap.LEFT:\n                      $scope.stopEdit(evt);\n                      break;\n                    case uiGridConstants.keymap.RIGHT:\n                      $scope.stopEdit(evt);\n                      break;\n                    case uiGridConstants.keymap.UP:\n                      evt.stopPropagation();\n                      break;\n                    case uiGridConstants.keymap.DOWN:\n                      evt.stopPropagation();\n                      break;\n                    case uiGridConstants.keymap.TAB:\n                      $scope.stopEdit(evt);\n                      break;\n                  }\n                  return true;\n                });\n              }\n            };\n          }\n        };\n      }]);\n\n})();\n\n(function () {\n  'use strict';\n\n  /**\n   * @ngdoc overview\n   * @name ui.grid.expandable\n   * @description\n   *\n   *  # ui.grid.expandable\n   * This module provides the ability to create subgrids with the ability to expand a row\n   * to show the subgrid.\n   *\n   * <div doc-module-components=\"ui.grid.expandable\"></div>\n   */\n  var module = angular.module('ui.grid.expandable', ['ui.grid']);\n\n  /**\n   *  @ngdoc service\n   *  @name ui.grid.expandable.service:uiGridExpandableService\n   *\n   *  @description Services for the expandable grid\n   */\n  module.service('uiGridExpandableService', ['gridUtil', '$compile', function (gridUtil, $compile) {\n    var service = {\n      initializeGrid: function (grid) {\n        \n        grid.expandable = {};\n        grid.expandable.expandedAll = false;\n\n        /**\n         *  @ngdoc object\n         *  @name enableExpandable\n         *  @propertyOf  ui.grid.expandable.api:GridOptions\n         *  @description Whether or not to use expandable feature, allows you to turn off expandable on specific grids\n         *  within your application, or in specific modes on _this_ grid. Defaults to true.  \n         *  @example\n         *  <pre>\n         *    $scope.gridOptions = {\n         *      enableExpandable: false\n         *    }\n         *  </pre>  \n         */\n        grid.options.enableExpandable = grid.options.enableExpandable !== false;\n        \n        /**\n         *  @ngdoc object\n         *  @name expandableRowHeight\n         *  @propertyOf  ui.grid.expandable.api:GridOptions\n         *  @description Height in pixels of the expanded subgrid.  Defaults to\n         *  150\n         *  @example\n         *  <pre>\n         *    $scope.gridOptions = {\n         *      expandableRowHeight: 150\n         *    }\n         *  </pre>  \n         */\n        grid.options.expandableRowHeight = grid.options.expandableRowHeight || 150;\n\n        /**\n         *  @ngdoc object\n         *  @name \n         *  @propertyOf  ui.grid.expandable.api:GridOptions\n         *  @description Width in pixels of the expandable column. Defaults to 40\n         *  @example\n         *  <pre>\n         *    $scope.gridOptions = {\n         *      expandableRowHeaderWidth: 40\n         *    }\n         *  </pre>  \n         */\n        grid.options.expandableRowHeaderWidth = grid.options.expandableRowHeaderWidth || 40;\n\n        /**\n         *  @ngdoc object\n         *  @name expandableRowTemplate\n         *  @propertyOf  ui.grid.expandable.api:GridOptions\n         *  @description Mandatory. The template for your expanded row\n         *  @example\n         *  <pre>\n         *    $scope.gridOptions = {\n         *      expandableRowTemplate: 'expandableRowTemplate.html'\n         *    }\n         *  </pre>  \n         */\n        if ( grid.options.enableExpandable && !grid.options.expandableRowTemplate ){\n          gridUtil.logError( 'You have not set the expandableRowTemplate, disabling expandable module' );\n          grid.options.enableExpandable = false;\n        }\n\n        /**\n         *  @ngdoc object\n         *  @name ui.grid.expandable.api:PublicApi\n         *\n         *  @description Public Api for expandable feature\n         */\n        /**\n         *  @ngdoc object\n         *  @name ui.grid.expandable.api:GridOptions\n         *\n         *  @description Options for configuring the expandable feature, these are available to be  \n         *  set using the ui-grid {@link ui.grid.class:GridOptions gridOptions}\n         */\n        var publicApi = {\n          events: {\n            expandable: {\n              /**\n               * @ngdoc event\n               * @name rowExpandedStateChanged\n               * @eventOf  ui.grid.expandable.api:PublicApi\n               * @description raised when cell editing is complete\n               * <pre>\n               *      gridApi.expandable.on.rowExpandedStateChanged(scope,function(row){})\n               * </pre>\n               * @param {GridRow} row the row that was expanded\n               */\n              rowExpandedStateChanged: function (scope, row) {\n              }\n            }\n          },\n          \n          methods: {\n            expandable: {\n              /**\n               * @ngdoc method\n               * @name toggleRowExpansion\n               * @methodOf  ui.grid.expandable.api:PublicApi\n               * @description Toggle a specific row\n               * <pre>\n               *      gridApi.expandable.toggleRowExpansion(rowEntity);\n               * </pre>\n               * @param {object} rowEntity the data entity for the row you want to expand\n               */              \n              toggleRowExpansion: function (rowEntity) {\n                var row = grid.getRow(rowEntity);\n                if (row !== null) {\n                  service.toggleRowExpansion(grid, row);\n                }\n              },\n\n              /**\n               * @ngdoc method\n               * @name expandAllRows\n               * @methodOf  ui.grid.expandable.api:PublicApi\n               * @description Expand all subgrids.\n               * <pre>\n               *      gridApi.expandable.expandAllRows();\n               * </pre>\n               */              \n              expandAllRows: function() {\n                service.expandAllRows(grid);\n              },\n\n              /**\n               * @ngdoc method\n               * @name collapseAllRows\n               * @methodOf  ui.grid.expandable.api:PublicApi\n               * @description Collapse all subgrids.\n               * <pre>\n               *      gridApi.expandable.collapseAllRows();\n               * </pre>\n               */              \n              collapseAllRows: function() {\n                service.collapseAllRows(grid);\n              },\n\n              /**\n               * @ngdoc method\n               * @name toggleAllRows\n               * @methodOf  ui.grid.expandable.api:PublicApi\n               * @description Toggle all subgrids.\n               * <pre>\n               *      gridApi.expandable.toggleAllRows();\n               * </pre>\n               */              \n              toggleAllRows: function() {\n                service.toggleAllRows(grid);\n              }\n            }\n          }\n        };\n        grid.api.registerEventsFromObject(publicApi.events);\n        grid.api.registerMethodsFromObject(publicApi.methods);\n      },\n      \n      toggleRowExpansion: function (grid, row) {\n        row.isExpanded = !row.isExpanded;\n        if (row.isExpanded) {\n          row.height = row.grid.options.rowHeight + grid.options.expandableRowHeight;\n        }\n        else {\n          row.height = row.grid.options.rowHeight;\n          grid.expandable.expandedAll = false;\n        }\n        grid.api.expandable.raise.rowExpandedStateChanged(row);\n      },\n      \n      expandAllRows: function(grid, $scope) {\n        angular.forEach(grid.renderContainers.body.visibleRowCache, function(row) {\n          if (!row.isExpanded) {\n            service.toggleRowExpansion(grid, row);\n          }\n        });\n        grid.expandable.expandedAll = true;\n        grid.refresh();\n      },\n      \n      collapseAllRows: function(grid) {\n        angular.forEach(grid.renderContainers.body.visibleRowCache, function(row) {\n          if (row.isExpanded) {\n            service.toggleRowExpansion(grid, row);\n          }\n        });\n        grid.expandable.expandedAll = false;\n        grid.refresh();\n      },\n\n      toggleAllRows: function(grid) {\n        if (grid.expandable.expandedAll) {\n          service.collapseAllRows(grid);\n        }\n        else {\n          service.expandAllRows(grid);\n        }\n      }\n    };\n    return service;\n  }]);\n\n  /**\n   *  @ngdoc object\n   *  @name enableExpandableRowHeader\n   *  @propertyOf  ui.grid.expandable.api:GridOptions\n   *  @description Show a rowHeader to provide the expandable buttons.  If set to false then implies\n   *  you're going to use a custom method for expanding and collapsing the subgrids. Defaults to true.\n   *  @example\n   *  <pre>\n   *    $scope.gridOptions = {\n   *      enableExpandableRowHeader: false\n   *    }\n   *  </pre>  \n   */\n  module.directive('uiGridExpandable', ['uiGridExpandableService', '$templateCache',\n    function (uiGridExpandableService, $templateCache) {\n      return {\n        replace: true,\n        priority: 0,\n        require: '^uiGrid',\n        scope: false,\n        compile: function () {\n          return {\n            pre: function ($scope, $elm, $attrs, uiGridCtrl) {\n              if ( uiGridCtrl.grid.options.enableExpandableRowHeader !== false ) {\n                var expandableRowHeaderColDef = {\n                  name: 'expandableButtons', \n                  displayName: '', \n                  exporterSuppressExport: true, \n                  enableColumnResizing: false, \n                  enableColumnMenu: false,\n                  width: uiGridCtrl.grid.options.expandableRowHeaderWidth || 40\n                };\n                expandableRowHeaderColDef.cellTemplate = $templateCache.get('ui-grid/expandableRowHeader');\n                expandableRowHeaderColDef.headerCellTemplate = $templateCache.get('ui-grid/expandableTopRowHeader');\n                uiGridCtrl.grid.addRowHeaderColumn(expandableRowHeaderColDef);\n              }\n              uiGridExpandableService.initializeGrid(uiGridCtrl.grid);\n            },\n            post: function ($scope, $elm, $attrs, uiGridCtrl) {\n            }\n          };\n        }\n      };\n    }]);\n\n  /**\n   *  @ngdoc directive\n   *  @name ui.grid.expandable.directive:uiGrid\n   *  @description stacks on the uiGrid directive to register child grid with parent row when child is created\n   */\n  module.directive('uiGrid', ['uiGridExpandableService', '$templateCache',\n    function (uiGridExpandableService, $templateCache) {\n      return {\n        replace: true,\n        priority: 1000,\n        require: '^uiGrid',\n        scope: false,\n        compile: function () {\n          return {\n            pre: function ($scope, $elm, $attrs, uiGridCtrl) {\n\n              uiGridCtrl.grid.api.core.on.renderingComplete($scope, function() {\n                //if a parent grid row is on the scope, then add the parentRow property to this childGrid\n                if ($scope.row && $scope.row.grid && $scope.row.grid.options && $scope.row.grid.options.enableExpandable) {\n\n                  /**\n                   *  @ngdoc directive\n                   *  @name ui.grid.expandable.class:Grid\n                   *  @description Additional Grid properties added by expandable module\n                   */\n\n                  /**\n                   *  @ngdoc object\n                   *  @name parentRow\n                   *  @propertyOf ui.grid.expandable.class:Grid\n                   *  @description reference to the expanded parent row that owns this grid\n                   */\n                  uiGridCtrl.grid.parentRow = $scope.row;\n\n                  //todo: adjust height on parent row when child grid height changes. we need some sort of gridHeightChanged event\n                 // uiGridCtrl.grid.core.on.canvasHeightChanged($scope, function(oldHeight, newHeight) {\n                 //   uiGridCtrl.grid.parentRow = newHeight;\n                 // });\n                }\n\n              });\n            },\n            post: function ($scope, $elm, $attrs, uiGridCtrl) {\n\n            }\n          };\n        }\n      };\n    }]);\n\n  /**\n   *  @ngdoc directive\n   *  @name ui.grid.expandable.directive:uiGridExpandableRow\n   *  @description directive to render the expandable row template\n   */\n  module.directive('uiGridExpandableRow',\n  ['uiGridExpandableService', '$timeout', '$compile', 'uiGridConstants','gridUtil','$interval', '$log',\n    function (uiGridExpandableService, $timeout, $compile, uiGridConstants, gridUtil, $interval, $log) {\n\n      return {\n        replace: false,\n        priority: 0,\n        scope: false,\n\n        compile: function () {\n          return {\n            pre: function ($scope, $elm, $attrs, uiGridCtrl) {\n              gridUtil.getTemplate($scope.grid.options.expandableRowTemplate).then(\n                function (template) {\n                  if ($scope.grid.options.expandableRowScope) {\n                    var expandableRowScope = $scope.grid.options.expandableRowScope;\n                    for (var property in expandableRowScope) {\n                      if (expandableRowScope.hasOwnProperty(property)) {\n                        $scope[property] = expandableRowScope[property];\n                      }\n                    }\n                  }\n                  var expandedRowElement = $compile(template)($scope);\n                  $elm.append(expandedRowElement);\n                  $scope.row.expandedRendered = true;\n              });\n            },\n\n            post: function ($scope, $elm, $attrs, uiGridCtrl) {\n              $scope.$on('$destroy', function() {\n                $scope.row.expandedRendered = false;\n              });\n            }\n          };\n        }\n      };\n    }]);\n\n  /**\n   *  @ngdoc directive\n   *  @name ui.grid.expandable.directive:uiGridRow\n   *  @description stacks on the uiGridRow directive to add support for expandable rows\n   */\n  module.directive('uiGridRow',\n    ['$compile', 'gridUtil', '$templateCache',\n      function ($compile, gridUtil, $templateCache) {\n        return {\n          priority: -200,\n          scope: false,\n          compile: function ($elm, $attrs) {\n            return {\n              pre: function ($scope, $elm, $attrs, controllers) {\n\n                $scope.expandableRow = {};\n\n                $scope.expandableRow.shouldRenderExpand = function () {\n                  var ret = $scope.colContainer.name === 'body' &&  $scope.grid.options.enableExpandable !== false && $scope.row.isExpanded && (!$scope.grid.isScrollingVertically || $scope.row.expandedRendered);\n                  return ret;\n                };\n\n                $scope.expandableRow.shouldRenderFiller = function () {\n                  var ret = $scope.row.isExpanded && ( $scope.colContainer.name !== 'body' || ($scope.grid.isScrollingVertically && !$scope.row.expandedRendered));\n                  return ret;\n                };\n\n                  function updateRowContainerWidth() {\n                      var grid = $scope.grid;\n                      var colWidth = 0;\n                      angular.forEach(grid.columns, function (column) {\n                          if (column.renderContainer === 'left') {\n                            colWidth += column.width;\n                          }\n                      });\n                      colWidth = Math.floor(colWidth);\n                      return '.grid' + grid.id + ' .ui-grid-pinned-container-' + $scope.colContainer.name + ', .grid' + grid.id +\n                          ' .ui-grid-pinned-container-' + $scope.colContainer.name + ' .ui-grid-render-container-' + $scope.colContainer.name +\n                          ' .ui-grid-viewport .ui-grid-canvas .ui-grid-row { width: ' + colWidth + 'px; }';\n                  }\n\n                  if ($scope.colContainer.name === 'left') {\n                      $scope.grid.registerStyleComputation({\n                          priority: 15,\n                          func: updateRowContainerWidth\n                      });\n                  }\n\n              },\n              post: function ($scope, $elm, $attrs, controllers) {\n              }\n            };\n          }\n        };\n      }]);\n\n  /**\n   *  @ngdoc directive\n   *  @name ui.grid.expandable.directive:uiGridViewport\n   *  @description stacks on the uiGridViewport directive to append the expandable row html elements to the\n   *  default gridRow template\n   */\n  module.directive('uiGridViewport',\n    ['$compile', 'gridUtil', '$templateCache',\n      function ($compile, gridUtil, $templateCache) {\n        return {\n          priority: -200,\n          scope: false,\n          compile: function ($elm, $attrs) {\n            var rowRepeatDiv = angular.element($elm.children().children()[0]);\n            var expandedRowFillerElement = $templateCache.get('ui-grid/expandableScrollFiller');\n            var expandedRowElement = $templateCache.get('ui-grid/expandableRow');\n            rowRepeatDiv.append(expandedRowElement);\n            rowRepeatDiv.append(expandedRowFillerElement);\n            return {\n              pre: function ($scope, $elm, $attrs, controllers) {\n              },\n              post: function ($scope, $elm, $attrs, controllers) {\n              }\n            };\n          }\n        };\n      }]);\n\n})();\n\n/* global console */\n\n(function () {\n  'use strict';\n\n  /**\n   * @ngdoc overview\n   * @name ui.grid.exporter\n   * @description\n   *\n   *  # ui.grid.exporter\n   * This module provides the ability to exporter data from the grid.  \n   * \n   * Data can be exported in a range of formats, and all data, visible \n   * data, or selected rows can be exported, with all columns or visible\n   * columns.\n   * \n   * No UI is provided, the caller should provide their own UI/buttons \n   * as appropriate, or enable the gridMenu\n   * \n   * <br/>\n   * <br/>\n   *\n   * <div doc-module-components=\"ui.grid.exporter\"></div>\n   */\n\n  var module = angular.module('ui.grid.exporter', ['ui.grid']);\n\n  /**\n   *  @ngdoc object\n   *  @name ui.grid.exporter.constant:uiGridExporterConstants\n   *\n   *  @description constants available in exporter module\n   */\n  /**\n   * @ngdoc property\n   * @propertyOf ui.grid.exporter.constant:uiGridExporterConstants\n   * @name ALL\n   * @description export all data, including data not visible.  Can\n   * be set for either rowTypes or colTypes\n   */\n  /**\n   * @ngdoc property\n   * @propertyOf ui.grid.exporter.constant:uiGridExporterConstants\n   * @name VISIBLE\n   * @description export only visible data, including data not visible.  Can\n   * be set for either rowTypes or colTypes\n   */\n  /**\n   * @ngdoc property\n   * @propertyOf ui.grid.exporter.constant:uiGridExporterConstants\n   * @name SELECTED\n   * @description export all data, including data not visible.  Can\n   * be set only for rowTypes, selection of only some columns is \n   * not supported\n   */\n  module.constant('uiGridExporterConstants', {\n    featureName: 'exporter',\n    ALL: 'all',\n    VISIBLE: 'visible',\n    SELECTED: 'selected',\n    CSV_CONTENT: 'CSV_CONTENT',\n    BUTTON_LABEL: 'BUTTON_LABEL',\n    FILE_NAME: 'FILE_NAME'\n  });\n\n  /**\n   *  @ngdoc service\n   *  @name ui.grid.exporter.service:uiGridExporterService\n   *\n   *  @description Services for exporter feature\n   */\n  module.service('uiGridExporterService', ['$q', 'uiGridExporterConstants', 'uiGridSelectionConstants', 'gridUtil', '$compile', '$interval', 'i18nService',\n    function ($q, uiGridExporterConstants, uiGridSelectionConstants, gridUtil, $compile, $interval, i18nService) {\n\n      var service = {\n\n        initializeGrid: function (grid) {\n\n          //add feature namespace and any properties to grid for needed state\n          grid.exporter = {};\n          this.defaultGridOptions(grid.options);\n\n          /**\n           *  @ngdoc object\n           *  @name ui.grid.exporter.api:PublicApi\n           *\n           *  @description Public Api for exporter feature\n           */\n          var publicApi = {\n            events: {\n              exporter: {\n              }\n            },\n            methods: {\n              exporter: {\n                /**\n                 * @ngdoc function\n                 * @name csvExport\n                 * @methodOf  ui.grid.exporter.api:PublicApi\n                 * @description Exports rows from the grid in csv format, \n                 * the data exported is selected based on the provided options\n                 * @param {string} rowTypes which rows to export, valid values are\n                 * uiGridExporterConstants.ALL, uiGridExporterConstants.VISIBLE,\n                 * uiGridExporterConstants.SELECTED\n                 * @param {string} colTypes which columns to export, valid values are\n                 * uiGridExporterConstants.ALL, uiGridExporterConstants.VISIBLE\n                 */\n                csvExport: function (rowTypes, colTypes) {\n                  service.csvExport(grid, rowTypes, colTypes);\n                },\n                /**\n                 * @ngdoc function\n                 * @name pdfExport\n                 * @methodOf  ui.grid.exporter.api:PublicApi\n                 * @description Exports rows from the grid in pdf format, \n                 * the data exported is selected based on the provided options\n                 * Note that this function has a dependency on pdfMake, all\n                 * going well this has been installed for you.\n                 * The resulting pdf opens in a new browser window.\n                 * @param {string} rowTypes which rows to export, valid values are\n                 * uiGridExporterConstants.ALL, uiGridExporterConstants.VISIBLE,\n                 * uiGridExporterConstants.SELECTED\n                 * @param {string} colTypes which columns to export, valid values are\n                 * uiGridExporterConstants.ALL, uiGridExporterConstants.VISIBLE\n                 */\n                pdfExport: function (rowTypes, colTypes) {\n                  service.pdfExport(grid, rowTypes, colTypes);\n                }\n              }\n            }\n          };\n\n          grid.api.registerEventsFromObject(publicApi.events);\n\n          grid.api.registerMethodsFromObject(publicApi.methods);\n          \n          if (grid.api.core.addToGridMenu){\n            service.addToMenu( grid );\n          } else {\n            // order of registration is not guaranteed, register in a little while\n            $interval( function() {\n              if (grid.api.core.addToGridMenu){\n                service.addToMenu( grid );\n              }              \n            }, 100, 1);\n          }\n\n        },\n\n        defaultGridOptions: function (gridOptions) {\n          //default option to true unless it was explicitly set to false\n          /**\n           * @ngdoc object\n           * @name ui.grid.exporter.api:GridOptions\n           *\n           * @description GridOptions for exporter feature, these are available to be  \n           * set using the ui-grid {@link ui.grid.class:GridOptions gridOptions}\n           */\n          /**\n           * @ngdoc object\n           * @name ui.grid.exporter.api:ColumnDef\n           * @description ColumnDef settings for exporter\n           */\n          /**\n           * @ngdoc object\n           * @name exporterSuppressMenu\n           * @propertyOf  ui.grid.exporter.api:GridOptions\n           * @description Don't show the export menu button, implying the user\n           * will roll their own UI for calling the exporter\n           * <br/>Defaults to false\n           */\n          gridOptions.exporterSuppressMenu = gridOptions.exporterSuppressMenu === true;\n          /**\n           * @ngdoc object\n           * @name exporterMenuLabel\n           * @propertyOf  ui.grid.exporter.api:GridOptions\n           * @description The text to show on the exporter menu button\n           * link\n           * <br/>Defaults to 'Export'\n           */\n          gridOptions.exporterMenuLabel = gridOptions.exporterMenuLabel ? gridOptions.exporterMenuLabel : 'Export';\n          /**\n           * @ngdoc object\n           * @name exporterSuppressColumns\n           * @propertyOf  ui.grid.exporter.api:GridOptions\n           * @description Columns that should not be exported.  The selectionRowHeader is already automatically\n           * suppressed, but if you had a button column or some other \"system\" column that shouldn't be shown in the\n           * output then add it in this list.  You should provide an array of column names.\n           * <br/>Defaults to: []\n           * <pre>\n           *   gridOptions.exporterSuppressColumns = [ 'buttons' ];\n           * </pre>\n           */\n          gridOptions.exporterSuppressColumns = gridOptions.exporterSuppressColumns ? gridOptions.exporterSuppressColumns : [];\n          /**\n           * @ngdoc object\n           * @name exporterCsvColumnSeparator\n           * @propertyOf  ui.grid.exporter.api:GridOptions\n           * @description The character to use as column separator\n           * link\n           * <br/>Defaults to ','\n           */\n          gridOptions.exporterCsvColumnSeparator = gridOptions.exporterCsvColumnSeparator ? gridOptions.exporterCsvColumnSeparator : ',';\n          /**\n           * @ngdoc object\n           * @name exporterCsvFilename\n           * @propertyOf  ui.grid.exporter.api:GridOptions\n           * @description The default filename to use when saving the downloaded csv.  \n           * This will only work in some browsers.\n           * <br/>Defaults to 'download.csv'\n           */\n          gridOptions.exporterCsvFilename = gridOptions.exporterCsvFilename ? gridOptions.exporterCsvFilename : 'download.csv';\n          /**\n           * @ngdoc object\n           * @name exporterPdfDefaultStyle\n           * @propertyOf  ui.grid.exporter.api:GridOptions\n           * @description The default style in pdfMake format\n           * <br/>Defaults to:\n           * <pre>\n           *   {\n           *     fontSize: 11\n           *   }\n           * </pre>\n           */\n          gridOptions.exporterPdfDefaultStyle = gridOptions.exporterPdfDefaultStyle ? gridOptions.exporterPdfDefaultStyle : { fontSize: 11 };\n          /**\n           * @ngdoc object\n           * @name exporterPdfTableStyle\n           * @propertyOf  ui.grid.exporter.api:GridOptions\n           * @description The table style in pdfMake format\n           * <br/>Defaults to:\n           * <pre>\n           *   {\n           *     margin: [0, 5, 0, 15]\n           *   }\n           * </pre>\n           */\n          gridOptions.exporterPdfTableStyle = gridOptions.exporterPdfTableStyle ? gridOptions.exporterPdfTableStyle : { margin: [0, 5, 0, 15] };\n          /**\n           * @ngdoc object\n           * @name exporterPdfTableHeaderStyle\n           * @propertyOf  ui.grid.exporter.api:GridOptions\n           * @description The tableHeader style in pdfMake format\n           * <br/>Defaults to:\n           * <pre>\n           *   {\n           *     bold: true,\n           *     fontSize: 12,\n           *     color: 'black'\n           *   }\n           * </pre>\n           */\n          gridOptions.exporterPdfTableHeaderStyle = gridOptions.exporterPdfTableHeaderStyle ? gridOptions.exporterPdfTableHeaderStyle : { bold: true, fontSize: 12, color: 'black' };\n          /**\n           * @ngdoc object\n           * @name exporterPdfHeader\n           * @propertyOf  ui.grid.exporter.api:GridOptions\n           * @description The header section for pdf exports.  Can be\n           * simple text:\n           * <pre>\n           *   gridOptions.exporterPdfHeader = 'My Header';\n           * </pre>\n           * Can be a more complex object in pdfMake format:\n           * <pre>\n           *   gridOptions.exporterPdfHeader = {\n           *     columns: [\n           *       'Left part',\n           *       { text: 'Right part', alignment: 'right' }\n           *     ]\n           *   };\n           * </pre>\n           * Or can be a function, allowing page numbers and the like\n           * <pre>\n           *   gridOptions.exporterPdfHeader: function(currentPage, pageCount) { return currentPage.toString() + ' of ' + pageCount; };\n           * </pre>\n           */\n          gridOptions.exporterPdfHeader = gridOptions.exporterPdfHeader ? gridOptions.exporterPdfHeader : null;\n          /**\n           * @ngdoc object\n           * @name exporterPdfFooter\n           * @propertyOf  ui.grid.exporter.api:GridOptions\n           * @description The header section for pdf exports.  Can be\n           * simple text:\n           * <pre>\n           *   gridOptions.exporterPdfFooter = 'My Footer';\n           * </pre>\n           * Can be a more complex object in pdfMake format:\n           * <pre>\n           *   gridOptions.exporterPdfFooter = {\n           *     columns: [\n           *       'Left part',\n           *       { text: 'Right part', alignment: 'right' }\n           *     ]\n           *   };\n           * </pre>\n           * Or can be a function, allowing page numbers and the like\n           * <pre>\n           *   gridOptions.exporterPdfFooter: function(currentPage, pageCount) { return currentPage.toString() + ' of ' + pageCount; };\n           * </pre>\n           */\n          gridOptions.exporterPdfFooter = gridOptions.exporterPdfFooter ? gridOptions.exporterPdfFooter : null;\n          /**\n           * @ngdoc object\n           * @name exporterPdfOrientation\n           * @propertyOf  ui.grid.exporter.api:GridOptions\n           * @description The orientation, should be a valid pdfMake value,\n           * 'landscape' or 'portrait'\n           * <br/>Defaults to landscape\n           */\n          gridOptions.exporterPdfOrientation = gridOptions.exporterPdfOrientation ? gridOptions.exporterPdfOrientation : 'landscape';\n          /**\n           * @ngdoc object\n           * @name exporterPdfPageSize\n           * @propertyOf  ui.grid.exporter.api:GridOptions\n           * @description The orientation, should be a valid pdfMake\n           * paper size, usually 'A4' or 'LETTER'\n           * {@link https://github.com/bpampuch/pdfmake/blob/master/src/standardPageSizes.js pdfMake page sizes}\n           * <br/>Defaults to A4\n           */\n          gridOptions.exporterPdfPageSize = gridOptions.exporterPdfPageSize ? gridOptions.exporterPdfPageSize : 'A4';\n          /**\n           * @ngdoc object\n           * @name exporterPdfMaxGridWidth\n           * @propertyOf  ui.grid.exporter.api:GridOptions\n           * @description The maxium grid width - the current grid width \n           * will be scaled to match this, with any fixed width columns\n           * being adjusted accordingly.\n           * <br/>Defaults to 720 (for A4 landscape), use 670 for LETTER \n           */\n          gridOptions.exporterPdfMaxGridWidth = gridOptions.exporterPdfMaxGridWidth ? gridOptions.exporterPdfMaxGridWidth : 720;\n          /**\n           * @ngdoc object\n           * @name exporterPdfTableLayout\n           * @propertyOf  ui.grid.exporter.api:GridOptions\n           * @description A tableLayout in pdfMake format, \n           * controls gridlines and the like.  We use the default\n           * layout usually.\n           * <br/>Defaults to null, which means no layout \n           */\n\n          /**\n           * @ngdoc object\n           * @name exporterMenuCsv\n           * @propertyOf  ui.grid.exporter.api:GridOptions\n           * @description Add csv export menu items to the ui-grid grid menu, if it's present.  Defaults to true.\n           */\n          gridOptions.exporterMenuCsv = gridOptions.exporterMenuCsv !== undefined ? gridOptions.exporterMenuCsv : true;\n\n          /**\n           * @ngdoc object\n           * @name exporterMenuPdf\n           * @propertyOf  ui.grid.exporter.api:GridOptions\n           * @description Add pdf export menu items to the ui-grid grid menu, if it's present.  Defaults to true.\n           */\n          gridOptions.exporterMenuPdf = gridOptions.exporterMenuPdf !== undefined ? gridOptions.exporterMenuPdf : true;\n          \n          /**\n           * @ngdoc object\n           * @name exporterPdfCustomFormatter\n           * @propertyOf  ui.grid.exporter.api:GridOptions\n           * @description A custom callback routine that changes the pdf document, adding any\n           * custom styling or content that is supported by pdfMake.  Takes in the complete docDefinition, and\n           * must return an updated docDefinition ready for pdfMake.\n           * @example\n           * In this example we add a style to the style array, so that we can use it in our\n           * footer definition.\n           * <pre>\n           *   gridOptions.exporterPdfCustomFormatter = function ( docDefinition ) {\n           *     docDefinition.styles.footerStyle = { bold: true, fontSize: 10 };\n           *     return docDefinition;\n           *   }\n           * \n           *   gridOptions.exporterPdfFooter = { text: 'My footer', style: 'footerStyle' }\n           * </pre>\n           */\n          gridOptions.exporterPdfCustomFormatter = ( gridOptions.exporterPdfCustomFormatter && typeof( gridOptions.exporterPdfCustomFormatter ) === 'function' ) ? gridOptions.exporterPdfCustomFormatter : function ( docDef ) { return docDef; };\n          \n          /**\n           * @ngdoc object\n           * @name exporterHeaderFilterUseName\n           * @propertyOf  ui.grid.exporter.api:GridOptions\n           * @description Defaults to false, which leads to `displayName` being passed into the headerFilter.\n           * If set to true, then will pass `name` instead.\n           * \n           * \n           * @example\n           * <pre>\n           *   gridOptions.exporterHeaderFilterUseName = true;\n           * </pre>\n           */\n          gridOptions.exporterHeaderFilterUseName = gridOptions.exporterHeaderFilterUseName === true;          \n\n          /**\n           * @ngdoc object\n           * @name exporterHeaderFilter\n           * @propertyOf  ui.grid.exporter.api:GridOptions\n           * @description A function to apply to the header displayNames before exporting.  Useful for internationalisation,\n           * for example if you were using angular-translate you'd set this to `$translate.instant`.  Note that this\n           * call must be synchronous, it cannot be a call that returns a promise.\n           * \n           * Behaviour can be changed to pass in `name` instead of `displayName` through use of `exporterHeaderFilterUseName: true`.\n           * \n           * @example\n           * <pre>\n           *   gridOptions.exporterHeaderFilter = function( displayName ){ return 'col: ' + name; };\n           * </pre>\n           * OR\n           * <pre>\n           *   gridOptions.exporterHeaderFilter = $translate.instant;\n           * </pre>\n           */\n          \n          /**\n           * @ngdoc function\n           * @name exporterFieldCallback\n           * @propertyOf  ui.grid.exporter.api:GridOptions\n           * @description A function to call for each field before exporting it.  Allows \n           * massaging of raw data into a display format, for example if you have applied \n           * filters to convert codes into decodes, or you require\n           * a specific date format in the exported content.\n           * \n           * The method is called once for each field exported, and provides the grid, the\n           * gridCol and the GridRow for you to use as context in massaging the data.\n           * \n           * @param {Grid} grid provides the grid in case you have need of it\n           * @param {GridRow} row the row from which the data comes\n           * @param {GridCol} col the column from which the data comes\n           * @param {object} value the value for your massaging\n           * @returns {object} you must return the massaged value ready for exporting\n           * \n           * @example\n           * <pre>\n           *   gridOptions.exporterFieldCallback = function ( grid, row, col, value ){\n           *     if ( col.name === 'status' ){\n           *       value = decodeStatus( value );\n           *     }\n           *     return value;\n           *   }\n           * </pre>\n           */\n          gridOptions.exporterFieldCallback = gridOptions.exporterFieldCallback ? gridOptions.exporterFieldCallback : function( grid, row, col, value ) { return value; };\n        },\n\n\n        /**\n         * @ngdoc function\n         * @name addToMenu\n         * @methodOf  ui.grid.exporter.service:uiGridExporterService\n         * @description Adds export items to the grid menu,\n         * allowing the user to select export options \n         * @param {Grid} grid the grid from which data should be exported\n         */\n        addToMenu: function ( grid ) {\n          grid.api.core.addToGridMenu( grid, [\n            {\n              title: i18nService.getSafeText('gridMenu.exporterAllAsCsv'),\n              action: function ($event) {\n                this.grid.api.exporter.csvExport( uiGridExporterConstants.ALL, uiGridExporterConstants.ALL );\n              },\n              shown: function() {\n                return this.grid.options.exporterMenuCsv; \n              }\n            },\n            {\n              title: i18nService.getSafeText('gridMenu.exporterVisibleAsCsv'),\n              action: function ($event) {\n                this.grid.api.exporter.csvExport( uiGridExporterConstants.VISIBLE, uiGridExporterConstants.VISIBLE );\n              },\n              shown: function() {\n                return this.grid.options.exporterMenuCsv; \n              }\n            },\n            {\n              title: i18nService.getSafeText('gridMenu.exporterSelectedAsCsv'),\n              action: function ($event) {\n                this.grid.api.exporter.csvExport( uiGridExporterConstants.SELECTED, uiGridExporterConstants.VISIBLE );\n              },\n              shown: function() {\n                return this.grid.options.exporterMenuCsv &&\n                       ( this.grid.api.selection && this.grid.api.selection.getSelectedRows().length > 0 ); \n              }\n            },\n            {\n              title: i18nService.getSafeText('gridMenu.exporterAllAsPdf'),\n              action: function ($event) {\n                this.grid.api.exporter.pdfExport( uiGridExporterConstants.ALL, uiGridExporterConstants.ALL );\n              },\n              shown: function() {\n                return this.grid.options.exporterMenuPdf; \n              }\n            },\n            {\n              title: i18nService.getSafeText('gridMenu.exporterVisibleAsPdf'),\n              action: function ($event) {\n                this.grid.api.exporter.pdfExport( uiGridExporterConstants.VISIBLE, uiGridExporterConstants.VISIBLE );\n              },\n              shown: function() {\n                return this.grid.options.exporterMenuPdf; \n              }\n            },\n            {\n              title: i18nService.getSafeText('gridMenu.exporterSelectedAsPdf'),\n              action: function ($event) {\n                this.grid.api.exporter.pdfExport( uiGridExporterConstants.SELECTED, uiGridExporterConstants.VISIBLE );\n              },\n              shown: function() {\n                return this.grid.options.exporterMenuPdf &&\n                       ( this.grid.api.selection && this.grid.api.selection.getSelectedRows().length > 0 ); \n              }\n            }\n          ]);\n        },\n        \n\n        /**\n         * @ngdoc function\n         * @name csvExport\n         * @methodOf  ui.grid.exporter.service:uiGridExporterService\n         * @description Exports rows from the grid in csv format, \n         * the data exported is selected based on the provided options\n         * @param {Grid} grid the grid from which data should be exported\n         * @param {string} rowTypes which rows to export, valid values are\n         * uiGridExporterConstants.ALL, uiGridExporterConstants.VISIBLE,\n         * uiGridExporterConstants.SELECTED\n         * @param {string} colTypes which columns to export, valid values are\n         * uiGridExporterConstants.ALL, uiGridExporterConstants.VISIBLE,\n         * uiGridExporterConstants.SELECTED\n         */\n        csvExport: function (grid, rowTypes, colTypes) {\n          var exportColumnHeaders = this.getColumnHeaders(grid, colTypes);\n          var exportData = this.getData(grid, rowTypes, colTypes);\n          var csvContent = this.formatAsCsv(exportColumnHeaders, exportData, grid.options.exporterCsvColumnSeparator);\n          \n          this.downloadFile (grid.options.exporterCsvFilename, csvContent);\n        },\n        \n        \n        /** \n         * @ngdoc property\n         * @propertyOf ui.grid.exporter.api:ColumnDef\n         * @name exporterSuppressExport\n         * @description Suppresses export for this column.  Used by selection and expandable.\n         */\n\n        /**\n         * @ngdoc function\n         * @name getColumnHeaders\n         * @methodOf  ui.grid.exporter.service:uiGridExporterService\n         * @description Gets the column headers from the grid to use\n         * as a title row for the exported file, all headers have \n         * headerCellFilters applied as appropriate.\n         * \n         * Column headers are an array of objects, each object has\n         * name, displayName, width and align attributes.  Only name is\n         * used for csv, all attributes are used for pdf.\n         * \n         * @param {Grid} grid the grid from which data should be exported\n         * @param {string} colTypes which columns to export, valid values are\n         * uiGridExporterConstants.ALL, uiGridExporterConstants.VISIBLE,\n         * uiGridExporterConstants.SELECTED\n         */\n        getColumnHeaders: function (grid, colTypes) {\n          var headers = [];\n          angular.forEach(grid.columns, function( gridCol, index ) {\n            if ( (gridCol.visible || colTypes === uiGridExporterConstants.ALL ) && \n                 gridCol.colDef.exporterSuppressExport !== true &&\n                 grid.options.exporterSuppressColumns.indexOf( gridCol.name ) === -1 ){\n              headers.push({\n                name: gridCol.field,\n                displayName: grid.options.exporterHeaderFilter ? ( grid.options.exporterHeaderFilterUseName ? grid.options.exporterHeaderFilter(gridCol.name) : grid.options.exporterHeaderFilter(gridCol.displayName) ) : gridCol.displayName,\n                width: gridCol.drawnWidth ? gridCol.drawnWidth : gridCol.width,\n                align: gridCol.colDef.type === 'number' ? 'right' : 'left'\n              });\n            }\n          });\n          \n          return headers;\n        },\n        \n        \n        /** \n         * @ngdoc property\n         * @propertyOf ui.grid.exporter.api:ColumnDef\n         * @name exporterPdfAlign\n         * @description the alignment you'd like for this specific column when\n         * exported into a pdf.  Can be 'left', 'right', 'center' or any other\n         * valid pdfMake alignment option.\n         */\n\n\n        /**\n         * @ngdoc object\n         * @name ui.grid.exporter.api:GridRow\n         * @description GridRow settings for exporter\n         */\n        /**\n         * @ngdoc object\n         * @name exporterEnableExporting\n         * @propertyOf  ui.grid.exporter.api:GridRow\n         * @description If set to false, then don't export this row, notwithstanding visible or \n         * other settings\n         * <br/>Defaults to true\n         */\n\n        /**\n         * @ngdoc function\n         * @name getData\n         * @methodOf  ui.grid.exporter.service:uiGridExporterService\n         * @description Gets data from the grid based on the provided options,\n         * all cells have cellFilters applied as appropriate.  Any rows marked\n         * `exporterEnableExporting: false` will not be exported\n         * @param {Grid} grid the grid from which data should be exported\n         * @param {string} rowTypes which rows to export, valid values are\n         * uiGridExporterConstants.ALL, uiGridExporterConstants.VISIBLE,\n         * uiGridExporterConstants.SELECTED\n         * @param {string} colTypes which columns to export, valid values are\n         * uiGridExporterConstants.ALL, uiGridExporterConstants.VISIBLE,\n         * uiGridExporterConstants.SELECTED\n         */\n        getData: function (grid, rowTypes, colTypes) {\n          var data = [];\n          \n          var rows;\n          \n          switch ( rowTypes ) {\n            case uiGridExporterConstants.ALL:\n              rows = grid.rows; \n              break;\n            case uiGridExporterConstants.VISIBLE:\n              rows = grid.getVisibleRows();\n              break;\n            case uiGridExporterConstants.SELECTED:\n              if ( grid.api.selection ){\n                rows = grid.api.selection.getSelectedGridRows();\n              } else {\n                gridUtil.logError('selection feature must be enabled to allow selected rows to be exported');\n              }\n              break;\n          }\n          \n          angular.forEach(rows, function( row, index ) {\n\n            if (row.exporterEnableExporting !== false) {\n              var extractedRow = [];\n              angular.forEach(grid.columns, function( gridCol, index ) {\n              if ( (gridCol.visible || colTypes === uiGridExporterConstants.ALL ) && \n                   gridCol.colDef.exporterSuppressExport !== true &&\n                   grid.options.exporterSuppressColumns.indexOf( gridCol.name ) === -1 ){\n                  var extractedField = { value: grid.options.exporterFieldCallback( grid, row, gridCol, grid.getCellValue( row, gridCol ) ) };\n                  if ( gridCol.colDef.exporterPdfAlign ) {\n                    extractedField.alignment = gridCol.colDef.exporterPdfAlign;                 \n                  }\n                  extractedRow.push(extractedField);\n                }\n              });\n              \n              data.push(extractedRow);\n            }\n          });\n          \n          return data;\n        },\n\n\n        /**\n         * @ngdoc function\n         * @name formatAsCSV\n         * @methodOf  ui.grid.exporter.service:uiGridExporterService\n         * @description Formats the column headers and data as a CSV, \n         * and sends that data to the user\n         * @param {array} exportColumnHeaders an array of column headers, \n         * where each header is an object with name, width and maybe alignment\n         * @param {array} exportData an array of rows, where each row is\n         * an array of column data\n         * @returns {string} csv the formatted csv as a string\n         */\n        formatAsCsv: function (exportColumnHeaders, exportData, separator) {\n          var self = this;\n          \n          var bareHeaders = exportColumnHeaders.map(function(header){return { value: header.displayName };});\n          \n          var csv = self.formatRowAsCsv(this, separator)(bareHeaders) + '\\n';\n          \n          csv += exportData.map(this.formatRowAsCsv(this, separator)).join('\\n');\n          \n          return csv;\n        },\n\n        /**\n         * @ngdoc function\n         * @name formatRowAsCsv\n         * @methodOf  ui.grid.exporter.service:uiGridExporterService\n         * @description Renders a single field as a csv field, including\n         * quotes around the value\n         * @param {exporterService} exporter pass in exporter \n         * @param {array} row the row to be turned into a csv string\n         * @returns {string} a csv-ified version of the row\n         */\n        formatRowAsCsv: function (exporter, separator) {\n          return function (row) {\n            return row.map(exporter.formatFieldAsCsv).join(separator);\n          };\n        },\n        \n        /**\n         * @ngdoc function\n         * @name formatFieldAsCsv\n         * @methodOf  ui.grid.exporter.service:uiGridExporterService\n         * @description Renders a single field as a csv field, including\n         * quotes around the value\n         * @param {field} field the field to be turned into a csv string,\n         * may be of any type\n         * @returns {string} a csv-ified version of the field\n         */\n        formatFieldAsCsv: function (field) {\n          if (field.value == null) { // we want to catch anything null-ish, hence just == not ===\n            return '';\n          }\n          if (typeof(field.value) === 'number') {\n            return field.value;\n          }\n          if (typeof(field.value) === 'boolean') {\n            return (field.value ? 'TRUE' : 'FALSE') ;\n          }\n          if (typeof(field.value) === 'string') {\n            return '\"' + field.value.replace(/\"/g,'\"\"') + '\"';\n          }\n\n          return JSON.stringify(field.value);        \n        },\n\n\n        /**\n         * @ngdoc function\n         * @name downloadFile\n         * @methodOf  ui.grid.exporter.service:uiGridExporterService\n         * @description Triggers download of a csv file.  Logic provided\n         * by @cssensei (from his colleagues at https://github.com/ifeelgoods) in issue #2391\n         * @param {string} fileName the filename we'd like our file to be\n         * given\n         * @param {string} csvContent the csv content that we'd like to \n         * download as a file\n         */\n        downloadFile: function (fileName, csvContent) {\n          var D = document;\n          var a = D.createElement('a');\n          var strMimeType = 'application/octet-stream;charset=utf-8';\n          var rawFile;\n      \n          // IE10+\n          if (navigator.msSaveBlob) {\n            return navigator.msSaveBlob(new Blob([\"\\ufeff\", csvContent], {\n              type: strMimeType\n            }), fileName);\n          }\n      \n          //html5 A[download]\n          if ('download' in a) {\n            var blob = new Blob([csvContent], {\n              type: strMimeType\n            });\n            rawFile = URL.createObjectURL(blob);\n            a.setAttribute('download', fileName);\n          } else {\n            rawFile = 'data:' + strMimeType + ',' + encodeURIComponent(csvContent);\n            a.setAttribute('target', '_blank');\n          }\n      \n          a.href = rawFile;\n          a.setAttribute('style', 'display:none;');\n          D.body.appendChild(a);\n          setTimeout(function() {\n            if (a.click) {\n              a.click();\n              // Workaround for Safari 5\n            } else if (document.createEvent) {\n              var eventObj = document.createEvent('MouseEvents');\n              eventObj.initEvent('click', true, true);\n              a.dispatchEvent(eventObj);\n            }\n            D.body.removeChild(a);\n    \n          }, 100);\n        },\n\n        /**\n         * @ngdoc function\n         * @name pdfExport\n         * @methodOf  ui.grid.exporter.service:uiGridExporterService\n         * @description Exports rows from the grid in pdf format, \n         * the data exported is selected based on the provided options.\n         * Note that this function has a dependency on pdfMake, which must\n         * be installed.  The resulting pdf opens in a new\n         * browser window.\n         * @param {Grid} grid the grid from which data should be exported\n         * @param {string} rowTypes which rows to export, valid values are\n         * uiGridExporterConstants.ALL, uiGridExporterConstants.VISIBLE,\n         * uiGridExporterConstants.SELECTED\n         * @param {string} colTypes which columns to export, valid values are\n         * uiGridExporterConstants.ALL, uiGridExporterConstants.VISIBLE,\n         * uiGridExporterConstants.SELECTED\n         */\n        pdfExport: function (grid, rowTypes, colTypes) {\n          var exportColumnHeaders = this.getColumnHeaders(grid, colTypes);\n          var exportData = this.getData(grid, rowTypes, colTypes);\n          var docDefinition = this.prepareAsPdf(grid, exportColumnHeaders, exportData);\n          \n          pdfMake.createPdf(docDefinition).open();\n        },\n        \n        \n        /**\n         * @ngdoc function\n         * @name renderAsPdf\n         * @methodOf  ui.grid.exporter.service:uiGridExporterService\n         * @description Renders the data into a pdf, and opens that pdf.\n         * \n         * @param {Grid} grid the grid from which data should be exported\n         * @param {array} exportColumnHeaders an array of column headers, \n         * where each header is an object with name, width and maybe alignment\n         * @param {array} exportData an array of rows, where each row is\n         * an array of column data\n         * @returns {object} a pdfMake format document definition, ready \n         * for generation\n         */        \n        prepareAsPdf: function(grid, exportColumnHeaders, exportData) {\n          var headerWidths = this.calculatePdfHeaderWidths( grid, exportColumnHeaders );\n          \n          var headerColumns = exportColumnHeaders.map( function( header ) {\n            return { text: header.displayName, style: 'tableHeader' }; \n          });\n          \n          var stringData = exportData.map(this.formatRowAsPdf(this));\n          \n          var allData = [headerColumns].concat(stringData);\n          \n          var docDefinition = {\n            pageOrientation: grid.options.exporterPdfOrientation,\n            pageSize: grid.options.exporterPdfPageSize,\n            content: [{\n              style: 'tableStyle',\n              table: {\n                headerRows: 1,\n                widths: headerWidths,\n                body: allData \n              }\n            }],\n            styles: {\n              tableStyle: grid.options.exporterPdfTableStyle,\n              tableHeader: grid.options.exporterPdfTableHeaderStyle\n            },\n            defaultStyle: grid.options.exporterPdfDefaultStyle\n          };\n          \n          if ( grid.options.exporterPdfLayout ){\n            docDefinition.layout = grid.options.exporterPdfLayout;\n          }\n          \n          if ( grid.options.exporterPdfHeader ){\n            docDefinition.header = grid.options.exporterPdfHeader;\n          }\n          \n          if ( grid.options.exporterPdfFooter ){\n            docDefinition.footer = grid.options.exporterPdfFooter;\n          }\n          \n          if ( grid.options.exporterPdfCustomFormatter ){\n            docDefinition = grid.options.exporterPdfCustomFormatter( docDefinition );\n          }\n          return docDefinition;\n          \n        },\n        \n                \n        /**\n         * @ngdoc function\n         * @name calculatePdfHeaderWidths\n         * @methodOf  ui.grid.exporter.service:uiGridExporterService\n         * @description Determines the column widths base on the \n         * widths we got from the grid.  If the column is drawn\n         * then we have a drawnWidth.  If the column is not visible\n         * then we have '*', 'x%' or a width.  When columns are\n         * not visible they don't contribute to the overall gridWidth,\n         * so we need to adjust to allow for extra columns\n         * \n         * Our basic heuristic is to take the current gridWidth, plus \n         * numeric columns and call this the base gridwidth.\n         * \n         * To that we add 100 for any '*' column, and x% of the base gridWidth\n         * for any column that is a %\n         *  \n         * @param {Grid} grid the grid from which data should be exported\n         * @param {object} exportHeaders array of header information \n         * @returns {object} an array of header widths\n         */\n        calculatePdfHeaderWidths: function ( grid, exportHeaders ) {\n          var baseGridWidth = 0;\n          angular.forEach(exportHeaders, function(value){\n            if (typeof(value.width) === 'number'){\n              baseGridWidth += value.width;\n            }\n          });\n          \n          var extraColumns = 0;\n          angular.forEach(exportHeaders, function(value){\n            if (value.width === '*'){\n              extraColumns += 100;\n            }\n            if (typeof(value.width) === 'string' && value.width.match(/(\\d)*%/)) {\n              var percent = parseInt(value.width.match(/(\\d)*%/)[0]);\n              \n              value.width = baseGridWidth * percent / 100;\n              extraColumns += value.width;\n            }\n          });\n          \n          var gridWidth = baseGridWidth + extraColumns;\n          \n          return exportHeaders.map(function( header ) {\n            return header.width === '*' ? header.width : header.width * grid.options.exporterPdfMaxGridWidth / gridWidth;\n          });\n          \n        },\n        \n        /**\n         * @ngdoc function\n         * @name formatRowAsPdf\n         * @methodOf  ui.grid.exporter.service:uiGridExporterService\n         * @description Renders a row in a format consumable by PDF,\n         * mainly meaning casting everything to a string\n         * @param {exporterService} exporter pass in exporter \n         * @param {array} row the row to be turned into a csv string\n         * @returns {string} a csv-ified version of the row\n         */\n        formatRowAsPdf: function ( exporter ) {\n          return function( row ) {\n            return row.map(exporter.formatFieldAsPdfString);\n          };\n        },\n        \n        \n        /**\n         * @ngdoc function\n         * @name formatFieldAsCsv\n         * @methodOf  ui.grid.exporter.service:uiGridExporterService\n         * @description Renders a single field as a pdf-able field, which\n         * is different from a csv field only in that strings don't have quotes\n         * around them\n         * @param {field} field the field to be turned into a pdf string,\n         * may be of any type\n         * @returns {string} a string-ified version of the field\n         */\n        formatFieldAsPdfString: function (field) {\n          var returnVal;\n          if (field.value == null) { // we want to catch anything null-ish, hence just == not ===\n            returnVal = '';\n          } else if (typeof(field.value) === 'number') {\n            returnVal = field.value.toString();\n          } else if (typeof(field.value) === 'boolean') {\n            returnVal = (field.value ? 'TRUE' : 'FALSE') ;\n          } else if (typeof(field.value) === 'string') {\n            returnVal = field.value.replace(/\"/g,'\"\"');\n          } else {\n            returnVal = JSON.stringify(field.value).replace(/^\"/,'').replace(/\"$/,'');        \n          }\n          \n          if (field.alignment && typeof(field.alignment) === 'string' ){\n            returnVal = { text: returnVal, alignment: field.alignment };\n          }\n          \n          return returnVal;\n        }\n      };\n\n      return service;\n\n    }\n  ]);\n\n  /**\n   *  @ngdoc directive\n   *  @name ui.grid.exporter.directive:uiGridExporter\n   *  @element div\n   *  @restrict A\n   *\n   *  @description Adds exporter features to grid\n   *\n   *  @example\n   <example module=\"app\">\n   <file name=\"app.js\">\n   var app = angular.module('app', ['ui.grid', 'ui.grid.exporter']);\n\n   app.controller('MainCtrl', ['$scope', function ($scope) {\n      $scope.data = [\n        { name: 'Bob', title: 'CEO' },\n            { name: 'Frank', title: 'Lowly Developer' }\n      ];\n\n      $scope.gridOptions = {\n        enableGridMenu: true,\n        exporterMenuCsv: false,\n        columnDefs: [\n          {name: 'name', enableCellEdit: true},\n          {name: 'title', enableCellEdit: true}\n        ],\n        data: $scope.data\n      };\n    }]);\n   </file>\n   <file name=\"index.html\">\n   <div ng-controller=\"MainCtrl\">\n   <div ui-grid=\"gridOptions\" ui-grid-exporter></div>\n   </div>\n   </file>\n   </example>\n   */\n  module.directive('uiGridExporter', ['uiGridExporterConstants', 'uiGridExporterService', 'gridUtil', '$compile',\n    function (uiGridExporterConstants, uiGridExporterService, gridUtil, $compile) {\n      return {\n        replace: true,\n        priority: 0,\n        require: '^uiGrid',\n        scope: false,\n        link: function ($scope, $elm, $attrs, uiGridCtrl) {\n          uiGridExporterService.initializeGrid(uiGridCtrl.grid);\n          uiGridCtrl.grid.exporter.$scope = $scope;\n        }\n      };\n    }\n  ]);\n})();\n\n(function () {\n  'use strict';\n\n  /**\n   * @ngdoc overview\n   * @name ui.grid.importer\n   * @description\n   *\n   *  # ui.grid.importer\n   * This module provides the ability to import data into the grid. It\n   * uses the column defs to work out which data belongs in which column, \n   * and creates entities from a configured class (typically a $resource).\n   * \n   * If the rowEdit feature is enabled, it also calls save on those newly \n   * created objects, and then displays any errors in the imported data.  \n   * \n   * Currently the importer imports only CSV and json files, although provision has been\n   * made to process other file formats, and these can be added over time.  \n   * \n   * For json files, the properties within each object in the json must match the column names\n   * (to put it another way, the importer doesn't process the json, it just copies the objects\n   * within the json into a new instance of the specified object type)\n   * \n   * For CSV import, the default column identification relies on each column in the\n   * header row matching a column.name or column.displayName. Optionally, a column identification \n   * callback can be used.  This allows matching using other attributes, which is particularly\n   * useful if your application has internationalised column headings (i.e. the headings that \n   * the user sees don't match the column names).\n   * \n   * The importer makes use of the grid menu as the UI for requesting an\n   * import. \n   *\n   * <div ui-grid-importer></div>\n   */\n\n  var module = angular.module('ui.grid.importer', ['ui.grid']);\n\n  /**\n   *  @ngdoc object\n   *  @name ui.grid.importer.constant:uiGridImporterConstants\n   *\n   *  @description constants available in importer module\n   */\n\n  module.constant('uiGridImporterConstants', {\n    featureName: 'importer'\n  });\n\n  /**\n   *  @ngdoc service\n   *  @name ui.grid.importer.service:uiGridImporterService\n   *\n   *  @description Services for importer feature\n   */\n  module.service('uiGridImporterService', ['$q', 'uiGridConstants', 'uiGridImporterConstants', 'gridUtil', '$compile', '$interval', 'i18nService', '$window',\n    function ($q, uiGridConstants, uiGridImporterConstants, gridUtil, $compile, $interval, i18nService, $window) {\n\n      var service = {\n\n        initializeGrid: function ($scope, grid) {\n\n          //add feature namespace and any properties to grid for needed state\n          grid.importer = {\n            $scope: $scope \n          };\n          \n          this.defaultGridOptions(grid.options);\n\n          /**\n           *  @ngdoc object\n           *  @name ui.grid.importer.api:PublicApi\n           *\n           *  @description Public Api for importer feature\n           */\n          var publicApi = {\n            events: {\n              importer: {\n              }\n            },\n            methods: {\n              importer: {\n                /**\n                 * @ngdoc function\n                 * @name importFile\n                 * @methodOf  ui.grid.importer.api:PublicApi\n                 * @description Imports a file into the grid using the file object \n                 * provided.  Bypasses the grid menu\n                 * @param {File} fileObject the file we want to import, as a javascript\n                 * File object\n                 */\n                importFile: function ( fileObject ) {\n                  service.importThisFile( grid, fileObject );\n                }\n              }\n            }\n          };\n\n          grid.api.registerEventsFromObject(publicApi.events);\n\n          grid.api.registerMethodsFromObject(publicApi.methods);\n\n          if ( grid.options.enableImporter && grid.options.importerShowMenu ){\n            if ( grid.api.core.addToGridMenu ){\n              service.addToMenu( grid );\n            } else {\n              // order of registration is not guaranteed, register in a little while\n              $interval( function() {\n                if (grid.api.core.addToGridMenu){\n                  service.addToMenu( grid );\n                }             \n              }, 100, 1);\n            }\n          }\n        },\n        \n\n        defaultGridOptions: function (gridOptions) {\n          //default option to true unless it was explicitly set to false\n          /**\n           * @ngdoc object\n           * @name ui.grid.importer.api:GridOptions\n           *\n           * @description GridOptions for importer feature, these are available to be  \n           * set using the ui-grid {@link ui.grid.class:GridOptions gridOptions}\n           */\n\n          /**\n           * @ngdoc property\n           * @propertyOf ui.grid.importer.api:GridOptions\n           * @name enableImporter\n           * @description Whether or not importer is enabled.  Automatically set\n           * to false if the user's browser does not support the required fileApi.\n           * Otherwise defaults to true.\n           * \n           */\n          if (gridOptions.enableImporter  || gridOptions.enableImporter === undefined) {\n            if ( !($window.hasOwnProperty('File') && $window.hasOwnProperty('FileReader') && $window.hasOwnProperty('FileList') && $window.hasOwnProperty('Blob')) ) {\n              gridUtil.logError('The File APIs are not fully supported in this browser, grid importer cannot be used.');\n              gridOptions.enableImporter = false;\n            } else {\n              gridOptions.enableImporter = true;\n            }\n          } else {\n            gridOptions.enableImporter = false;\n          }\n          \n          /**\n           * @ngdoc method\n           * @name importerProcessHeaders\n           * @methodOf ui.grid.importer.api:GridOptions\n           * @description A callback function that will process headers using custom\n           * logic.  Set this callback function if the headers that your user will provide in their \n           * import file don't necessarily match the grid header or field names.  This might commonly\n           * occur where your application is internationalised, and therefore the field names\n           * that the user recognises are in a different language than the field names that\n           * ui-grid knows about.\n           * \n           * Defaults to the internal `processHeaders` method, which seeks to match using both\n           * displayName and column.name.  Any non-matching columns are discarded.\n           * \n           * Your callback routine should respond by processing the header array, and returning an array\n           * of matching column names.  A null value in any given position means \"don't import this column\"\n           * \n           * <pre>\n           *      gridOptions.importerProcessHeaders: function( headerArray ) {\n           *        var myHeaderColumns = [];\n           *        var thisCol;\n           *        headerArray.forEach( function( value, index ) {\n           *          thisCol = mySpecialLookupFunction( value );\n           *          myHeaderColumns.push( thisCol.name ); \n           *        });\n           *        \n           *        return myHeaderCols;\n           *      })\n           * </pre>\n           * @param {Grid} grid the grid we're importing into\n           * @param {array} headerArray an array of the text from the first row of the csv file,\n           * which you need to match to column.names\n           * @returns {array} array of matching column names, in the same order as the headerArray\n           * \n           */\n          gridOptions.importerProcessHeaders = gridOptions.importerProcessHeaders || service.processHeaders;\n\n          /**\n           * @ngdoc method\n           * @name importerHeaderFilter\n           * @methodOf ui.grid.importer.api:GridOptions\n           * @description A callback function that will filter (usually translate) a single\n           * header.  Used when you want to match the passed in column names to the column\n           * displayName after the header filter.\n           * \n           * Your callback routine needs to return the filtered header value. \n           * <pre>\n           *      gridOptions.importerHeaderFilter: function( displayName ) {\n           *        return $translate.instant( displayName );\n           *      })\n           * </pre>\n           * \n           * or:\n           * <pre>\n           *      gridOptions.importerHeaderFilter: $translate.instant\n           * </pre>\n           * @param {string} displayName the displayName that we'd like to translate\n           * @returns {string} the translated name\n           * \n           */\n          gridOptions.importerHeaderFilter = gridOptions.importerHeaderFilter || function( displayName ) { return displayName; };\n\n          /**\n           * @ngdoc method\n           * @name importerErrorCallback\n           * @methodOf ui.grid.importer.api:GridOptions\n           * @description A callback function that provides custom error handling, rather\n           * than the standard grid behaviour of an alert box and a console message.  You \n           * might use this to internationalise the console log messages, or to write to a \n           * custom logging routine that returned errors to the server.\n           * \n           * <pre>\n           *      gridOptions.importerErrorCallback: function( grid, errorKey, consoleMessage, context ) {\n           *        myUserDisplayRoutine( errorKey );\n           *        myLoggingRoutine( consoleMessage, context );\n           *      })\n           * </pre>\n           * @param {Grid} grid the grid we're importing into, may be useful if you're positioning messages\n           * in some way\n           * @param {string} errorKey one of the i18n keys the importer can return - importer.noHeaders, \n           * importer.noObjects, importer.invalidCsv, importer.invalidJson, importer.jsonNotArray\n           * @param {string} consoleMessage the English console message that importer would have written\n           * @param {object} context the context data that importer would have appended to that console message,\n           * often the file content itself or the element that is in error\n           * \n           */\n          if ( !gridOptions.importerErrorCallback ||  typeof(gridOptions.importerErrorCallback) !== 'function' ){\n            delete gridOptions.importerErrorCallback;  \n          }\n\n          /**\n           * @ngdoc method\n           * @name importerDataAddCallback\n           * @methodOf ui.grid.importer.api:GridOptions\n           * @description A mandatory callback function that adds data to the source data array.  The grid\n           * generally doesn't add rows to the source data array, it is tidier to handle this through a user\n           * callback.\n           * \n           * <pre>\n           *      gridOptions.importerDataAddCallback: function( grid, newObjects ) {\n           *        $scope.myData = $scope.myData.concat( newObjects );\n           *      })\n           * </pre>\n           * @param {Grid} grid the grid we're importing into, may be useful in some way\n           * @param {array} newObjects an array of new objects that you should add to your data\n           * \n           */\n          if ( gridOptions.enableImporter === true && !gridOptions.importerDataAddCallback ) {\n            gridUtil.logError(\"You have not set an importerDataAddCallback, importer is disabled\");\n            gridOptions.enableImporter = false;\n          }\n                    \n          /**\n           * @ngdoc object\n           * @name importerNewObject\n           * @propertyOf  ui.grid.importer.api:GridOptions\n           * @description An object on which we call `new` to create each new row before inserting it into\n           * the data array.  Typically this would be a $resource entity, which means that if you're using \n           * the rowEdit feature, you can directly call save on this entity when the save event is triggered.\n           * \n           * Defaults to a vanilla javascript object\n           * \n           * @example\n           * <pre>\n           *   gridOptions.importerNewObject = MyRes;\n           * </pre>\n           * \n           */\n\n          /**\n           * @ngdoc property\n           * @propertyOf ui.grid.importer.api:GridOptions\n           * @name importerShowMenu\n           * @description Whether or not to show an item in the grid menu.  Defaults to true.\n           * \n           */\n          gridOptions.importerShowMenu = gridOptions.importerShowMenu !== false;\n          \n          /**\n           * @ngdoc method\n           * @methodOf ui.grid.importer.api:GridOptions\n           * @name importerObjectCallback\n           * @description A callback that massages the data for each object.  For example,\n           * you might have data stored as a code value, but display the decode.  This callback\n           * can be used to change the decoded value back into a code.  Defaults to doing nothing.\n           * @param {Grid} grid in case you need it\n           * @param {object} newObject the new object as importer has created it, modify it\n           * then return the modified version\n           * @returns {object} the modified object\n           * @example\n           * <pre>\n           *   gridOptions.importerObjectCallback = function ( grid, newObject ) {\n           *     switch newObject.status {\n           *       case 'Active':\n           *         newObject.status = 1;\n           *         break;\n           *       case 'Inactive':\n           *         newObject.status = 2;\n           *         break;\n           *     }\n           *     return newObject;\n           *   };\n           * </pre>\n           */\n          gridOptions.importerObjectCallback = gridOptions.importerObjectCallback || function( grid, newObject ) { return newObject; };\n        },\n\n\n        /**\n         * @ngdoc function\n         * @name addToMenu\n         * @methodOf  ui.grid.importer.service:uiGridImporterService\n         * @description Adds import menu item to the grid menu,\n         * allowing the user to request import of a file \n         * @param {Grid} grid the grid into which data should be imported\n         */\n        addToMenu: function ( grid ) {\n          grid.api.core.addToGridMenu( grid, [\n            {\n              title: i18nService.getSafeText('gridMenu.importerTitle')\n            },\n            {\n              templateUrl: 'ui-grid/importerMenuItemContainer',\n              action: function ($event) {\n                this.grid.api.importer.importAFile( grid );\n              }\n            }\n          ]);\n        },\n        \n        \n        /**\n         * @ngdoc function\n         * @name importThisFile\n         * @methodOf ui.grid.importer.service:uiGridImporterService\n         * @description Imports the provided file into the grid using the file object \n         * provided.  Bypasses the grid menu\n         * @param {Grid} grid the grid we're importing into\n         * @param {File} fileObject the file we want to import, as returned from the File\n         * javascript object\n         */\n        importThisFile: function ( grid, fileObject ) {\n          if (!fileObject){\n            gridUtil.logError( 'No file object provided to importThisFile, should be impossible, aborting');\n            return;\n          }\n          \n          var reader = new FileReader();\n          \n          switch ( fileObject.type ){\n            case 'application/json':\n              reader.onload = service.importJsonClosure( grid );\n              break;\n            default:\n              reader.onload = service.importCsvClosure( grid );\n              break;\n          }\n          \n          reader.readAsText( fileObject );\n        },\n        \n        \n        /**\n         * @ngdoc function\n         * @name importJson\n         * @methodOf ui.grid.importer.service:uiGridImporterService\n         * @description Creates a function that imports a json file into the grid.\n         * The json data is imported into new objects of type `gridOptions.importerNewObject`,\n         * and if the rowEdit feature is enabled the rows are marked as dirty\n         * @param {Grid} grid the grid we want to import into\n         * @param {FileObject} importFile the file that we want to import, as \n         * a FileObject\n         */\n        importJsonClosure: function( grid ) {\n          return function( importFile ){\n            var newObjects = [];\n            var newObject;\n            \n            angular.forEach( service.parseJson( grid, importFile ), function( value, index ) {\n              newObject = service.newObject( grid );\n              angular.extend( newObject, value );\n              newObject = grid.options.importerObjectCallback( grid, newObject );\n              newObjects.push( newObject );\n            });\n            \n            service.addObjects( grid, newObjects );\n            \n          };\n        },\n\n\n        /**\n         * @ngdoc function\n         * @name parseJson\n         * @methodOf ui.grid.importer.service:uiGridImporterService\n         * @description Parses a json file, returns the parsed data.\n         * Displays an error if file doesn't parse\n         * @param {Grid} grid the grid that we want to import into \n         * @param {FileObject} importFile the file that we want to import, as \n         * a FileObject\n         * @returns {array} array of objects from the imported json\n         */\n        parseJson: function( grid, importFile ){\n          var loadedObjects;\n          try {\n            loadedObjects = JSON.parse( importFile.target.result );\n          } catch (e) {\n            service.alertError( grid, 'importer.invalidJson', 'File could not be processed, is it valid json? Content was: ', importFile.target.result );\n            return;\n          }\n          \n          if ( !Array.isArray( loadedObjects ) ){\n            service.alertError( grid, 'importer.jsonNotarray', 'Import failed, file is not an array, file was: ', importFile.target.result );\n            return [];\n          } else {\n            return loadedObjects;\n          }\n        },\n        \n        \n        \n        /**\n         * @ngdoc function\n         * @name importCsvClosure\n         * @methodOf ui.grid.importer.service:uiGridImporterService\n         * @description Creates a function that imports a csv file into the grid\n         * (allowing it to be used in the reader.onload event)\n         * @param {Grid} grid the grid that we want to import into \n         * @param {FileObject} importFile the file that we want to import, as \n         * a file object\n         */\n        importCsvClosure: function( grid ) {\n          return function( importFile ){\n            var importArray = service.parseCsv( importFile );\n            if ( !importArray || importArray.length < 1 ){ \n              service.alertError( grid, 'importer.invalidCsv', 'File could not be processed, is it valid csv? Content was: ', importFile.target.result );\n              return; \n            }\n            \n            var newObjects = service.createCsvObjects( grid, importArray );\n            if ( !newObjects || newObjects.length === 0 ){\n              service.alertError( grid, 'importer.noObjects', 'Objects were not able to be derived, content was: ', importFile.target.result );\n              return;\n            }\n            \n            service.addObjects( grid, newObjects );\n          };\n        },\n        \n        \n        /**\n         * @ngdoc function\n         * @name parseCsv\n         * @methodOf ui.grid.importer.service:uiGridImporterService\n         * @description Parses a csv file into an array of arrays, with the first\n         * array being the headers, and the remaining arrays being the data.\n         * The logic for this comes from https://github.com/thetalecrafter/excel.js/blob/master/src/csv.js, \n         * which is noted as being under the MIT license.  The code is modified to pass the jscs yoda condition\n         * checker\n         * @param {FileObject} importFile the file that we want to import, as a \n         * file object\n         */\n        parseCsv: function( importFile ) {\n          var csv = importFile.target.result;\n          \n          // use the CSV-JS library to parse\n          return CSV.parse(csv);\n        },\n        \n\n        /**\n         * @ngdoc function\n         * @name createCsvObjects\n         * @methodOf ui.grid.importer.service:uiGridImporterService\n         * @description Converts an array of arrays (representing the csv file)\n         * into a set of objects.  Uses the provided `gridOptions.importerNewObject`\n         * to create the objects, and maps the header row into the individual columns \n         * using either `gridOptions.importerProcessHeaders`, or by using a native method\n         * of matching to either the displayName, column name or column field of\n         * the columns in the column defs.  The resulting objects will have attributes\n         * that are named based on the column.field or column.name, in that order.\n         * @param {Grid} grid the grid that we want to import into \n         * @param {FileObject} importFile the file that we want to import, as a \n         * file object\n         */\n        createCsvObjects: function( grid, importArray ){\n          // pull off header row and turn into headers\n          var headerMapping = grid.options.importerProcessHeaders( grid, importArray.shift() );\n          if ( !headerMapping || headerMapping.length === 0 ){\n            service.alertError( grid, 'importer.noHeaders', 'Column names could not be derived, content was: ', importArray );\n            return [];\n          }\n          \n          var newObjects = [];\n          var newObject;\n          angular.forEach( importArray, function( row, index ) {\n            newObject = service.newObject( grid );\n            angular.forEach( row, function( field, index ){\n              if ( headerMapping[index] !== null ){\n                newObject[ headerMapping[index] ] = field;\n              }\n            });\n            newObject = grid.options.importerObjectCallback( grid, newObject );\n            newObjects.push( newObject );\n          });\n          \n          return newObjects;\n        },\n        \n        \n        /**\n         * @ngdoc function\n         * @name processHeaders\n         * @methodOf ui.grid.importer.service:uiGridImporterService\n         * @description Determines the columns that the header row from\n         * a csv (or other) file represents.\n         * @param {Grid} grid the grid we're importing into\n         * @param {array} headerRow the header row that we wish to match against\n         * the column definitions\n         * @returns {array} an array of the attribute names that should be used\n         * for that column, based on matching the headers or creating the headers\n         * \n         */\n        processHeaders: function( grid, headerRow ) {\n          var headers = [];\n          if ( !grid.options.columnDefs || grid.options.columnDefs.length === 0 ){\n            // we are going to create new columnDefs for all these columns, so just remove\n            // spaces from the names to create fields\n            angular.forEach( headerRow, function( value, index ) {\n              headers.push( value.replace( /[^0-9a-zA-Z\\-_]/g, '_' ) );\n            });\n            return headers;\n          } else {\n            var lookupHash = service.flattenColumnDefs( grid, grid.options.columnDefs );\n            angular.forEach( headerRow, function( value, index ) {\n              if ( lookupHash[value] ) {\n                headers.push( lookupHash[value] );\n              } else if ( lookupHash[ value.toLowerCase() ] ) {\n                headers.push( lookupHash[ value.toLowerCase() ] );\n              } else {\n                headers.push( null );\n              }\n            });\n            return headers;\n          }\n        },\n        \n        \n        /**\n         * @name flattenColumnDefs\n         * @methodOf ui.grid.importer.service:uiGridImporterService\n         * @description Runs through the column defs and creates a hash of\n         * the displayName, name and field, and of each of those values forced to lower case,\n         * with each pointing to the field or name\n         * (whichever is present).  Used to lookup column headers and decide what \n         * attribute name to give to the resulting field. \n         * @param {Grid} grid the grid we're importing into\n         * @param {array} columnDefs the columnDefs that we should flatten\n         * @returns {hash} the flattened version of the column def information, allowing\n         * us to look up a value by `flattenedHash[ headerValue ]`\n         */\n        flattenColumnDefs: function( grid, columnDefs ){\n          var flattenedHash = {};\n          angular.forEach( columnDefs, function( columnDef, index) {\n            if ( columnDef.name ){\n              flattenedHash[ columnDef.name ] = columnDef.field || columnDef.name;\n              flattenedHash[ columnDef.name.toLowerCase() ] = columnDef.field || columnDef.name;\n            }\n            \n            if ( columnDef.field ){\n              flattenedHash[ columnDef.field ] = columnDef.field || columnDef.name;\n              flattenedHash[ columnDef.field.toLowerCase() ] = columnDef.field || columnDef.name;\n            }\n            \n            if ( columnDef.displayName ){\n              flattenedHash[ columnDef.displayName ] = columnDef.field || columnDef.name;\n              flattenedHash[ columnDef.displayName.toLowerCase() ] = columnDef.field || columnDef.name;\n            }\n            \n            if ( columnDef.displayName && grid.options.importerHeaderFilter ){\n              flattenedHash[ grid.options.importerHeaderFilter(columnDef.displayName) ] = columnDef.field || columnDef.name;\n              flattenedHash[ grid.options.importerHeaderFilter(columnDef.displayName).toLowerCase() ] = columnDef.field || columnDef.name;\n            }\n          });\n          \n          return flattenedHash;\n        },\n        \n        \n        /**\n         * @ngdoc function\n         * @name addObjects\n         * @methodOf ui.grid.importer.service:uiGridImporterService\n         * @description Inserts our new objects into the grid data, and\n         * sets the rows to dirty if the rowEdit feature is being used\n         * \n         * Does this by registering a watch on dataChanges, which essentially\n         * is waiting on the result of the grid data watch, and downstream processing.\n         * \n         * When the callback is called, it deregisters itself - we don't want to run\n         * again next time data is added.\n         * \n         * If we never get called, we deregister on destroy.\n         * \n         * @param {Grid} grid the grid we're importing into\n         * @param {array} newObjects the objects we want to insert into the grid data\n         * @returns {object} the new object\n         */\n        addObjects: function( grid, newObjects, $scope ){\n          if ( grid.api.rowEdit ){\n            var dataChangeDereg = grid.registerDataChangeCallback( function() {\n              grid.api.rowEdit.setRowsDirty( newObjects );\n              dataChangeDereg();\n            }, [uiGridConstants.dataChange.ROW] );\n            \n            grid.importer.$scope.$on( '$destroy', dataChangeDereg );\n          }\n\n          grid.importer.$scope.$apply( grid.options.importerDataAddCallback( grid, newObjects ) );\n          \n        },\n        \n        \n        /**\n         * @ngdoc function\n         * @name newObject\n         * @methodOf ui.grid.importer.service:uiGridImporterService\n         * @description Makes a new object based on `gridOptions.importerNewObject`,\n         * or based on an empty object if not present\n         * @param {Grid} grid the grid we're importing into\n         * @returns {object} the new object\n         */\n        newObject: function( grid ){\n          if ( typeof(grid.options) !== \"undefined\" && typeof(grid.options.importerNewObject) !== \"undefined\" ){\n            return new grid.options.importerNewObject();\n          } else {\n            return {};\n          }\n        },\n        \n        \n        /**\n         * @ngdoc function\n         * @name alertError\n         * @methodOf ui.grid.importer.service:uiGridImporterService\n         * @description Provides an internationalised user alert for the failure,\n         * and logs a console message including diagnostic content.\n         * Optionally, if the the `gridOptions.importerErrorCallback` routine\n         * is defined, then calls that instead, allowing user specified error routines\n         * @param {Grid} grid the grid we're importing into\n         * @param {array} headerRow the header row that we wish to match against\n         * the column definitions\n         */\n        alertError: function( grid, alertI18nToken, consoleMessage, context ){\n          if ( grid.options.importerErrorCallback ){\n            grid.options.importerErrorCallback( grid, alertI18nToken, consoleMessage, context );\n          } else {\n            $window.alert(i18nService.getSafeText( alertI18nToken )); \n            gridUtil.logError(consoleMessage + context ); \n          }\n        }\n      };\n\n      return service;\n\n    }\n  ]);\n\n  /**\n   *  @ngdoc directive\n   *  @name ui.grid.importer.directive:uiGridImporter\n   *  @element div\n   *  @restrict A\n   *\n   *  @description Adds importer features to grid\n   *\n   */\n  module.directive('uiGridImporter', ['uiGridImporterConstants', 'uiGridImporterService', 'gridUtil', '$compile',\n    function (uiGridImporterConstants, uiGridImporterService, gridUtil, $compile) {\n      return {\n        replace: true,\n        priority: 0,\n        require: '^uiGrid',\n        scope: false,\n        link: function ($scope, $elm, $attrs, uiGridCtrl) {\n          uiGridImporterService.initializeGrid($scope, uiGridCtrl.grid);\n        }\n      };\n    }\n  ]);\n  \n  /**\n   *  @ngdoc directive\n   *  @name ui.grid.importer.directive:uiGridImporterMenuItem\n   *  @element div\n   *  @restrict A\n   *\n   *  @description Handles the processing from the importer menu item - once a file is\n   *  selected\n   *\n   */\n  module.directive('uiGridImporterMenuItem', ['uiGridImporterConstants', 'uiGridImporterService', 'gridUtil', '$compile',\n    function (uiGridImporterConstants, uiGridImporterService, gridUtil, $compile) {\n      return {\n        replace: true,\n        priority: 0,\n        require: '^uiGrid',\n        scope: false,\n        templateUrl: 'ui-grid/importerMenuItem',\n        link: function ($scope, $elm, $attrs, uiGridCtrl) {\n          var handleFileSelect = function( event ){\n            var target = event.srcElement || event.target;\n            \n            if (target && target.files && target.files.length === 1) {\n              var fileObject = target.files[0];\n              uiGridImporterService.importThisFile( grid, fileObject );\n              target.form.reset();\n            }\n          };\n\n          var fileChooser = $elm[0].querySelectorAll('.ui-grid-importer-file-chooser');\n          var grid = uiGridCtrl.grid;\n          \n          if ( fileChooser.length !== 1 ){\n            gridUtil.logError('Found > 1 or < 1 file choosers within the menu item, error, cannot continue');\n          } else {\n            fileChooser[0].addEventListener('change', handleFileSelect, false);  // TODO: why the false on the end?  Google  \n          }\n        }\n      };\n    }\n  ]);  \n})();\n(function() {\n  'use strict';\n  /**\n   *  @ngdoc overview\n   *  @name ui.grid.infiniteScroll\n   *\n   *  @description\n   *\n   *   #ui.grid.infiniteScroll\n   * This module provides infinite scroll functionality to ui-grid\n   *\n   */\n  var module = angular.module('ui.grid.infiniteScroll', ['ui.grid']);\n  /**\n   *  @ngdoc service\n   *  @name ui.grid.infiniteScroll.service:uiGridInfiniteScrollService\n   *\n   *  @description Service for infinite scroll features\n   */\n  module.service('uiGridInfiniteScrollService', ['gridUtil', '$compile', '$timeout', 'uiGridConstants', function (gridUtil, $compile, $timeout, uiGridConstants) {\n\n    var service = {\n\n      /**\n       * @ngdoc function\n       * @name initializeGrid\n       * @methodOf ui.grid.infiniteScroll.service:uiGridInfiniteScrollService\n       * @description This method register events and methods into grid public API\n       */\n\n      initializeGrid: function(grid) {\n        service.defaultGridOptions(grid.options);\n\n        /**\n         *  @ngdoc object\n         *  @name ui.grid.infiniteScroll.api:PublicAPI\n         *\n         *  @description Public API for infinite scroll feature\n         */\n        var publicApi = {\n          events: {\n            infiniteScroll: {\n\n              /**\n               * @ngdoc event\n               * @name needLoadMoreData\n               * @eventOf ui.grid.infiniteScroll.api:PublicAPI\n               * @description This event fires when scroll reached bottom percentage of grid\n               * and needs to load data\n               */\n\n              needLoadMoreData: function ($scope, fn) {\n              },\n\n              /**\n               * @ngdoc event\n               * @name needLoadMoreDataTop\n               * @eventOf ui.grid.infiniteScroll.api:PublicAPI\n               * @description This event fires when scroll reached top percentage of grid\n               * and needs to load data\n               */\n\n              needLoadMoreDataTop: function ($scope, fn) {\n              }\n            }\n          },\n          methods: {\n            infiniteScroll: {\n\n              /**\n               * @ngdoc function\n               * @name dataLoaded\n               * @methodOf ui.grid.infiniteScroll.api:PublicAPI\n               * @description This function is used as a promise when data finished loading.\n               * See infinite_scroll ngdoc for example of usage\n               */\n\n              dataLoaded: function() {\n                grid.options.loadTimout = false;\n              }\n            }\n          }\n        };\n        grid.options.loadTimout = false;\n        grid.api.registerEventsFromObject(publicApi.events);\n        grid.api.registerMethodsFromObject(publicApi.methods);\n      },\n      defaultGridOptions: function (gridOptions) {\n        //default option to true unless it was explicitly set to false\n        /**\n         *  @ngdoc object\n         *  @name ui.grid.infiniteScroll.api:GridOptions\n         *\n         *  @description GridOptions for infinite scroll feature, these are available to be\n         *  set using the ui-grid {@link ui.grid.class:GridOptions gridOptions}\n         */\n\n        /**\n         *  @ngdoc object\n         *  @name enableInfiniteScroll\n         *  @propertyOf  ui.grid.infiniteScroll.api:GridOptions\n         *  @description Enable infinite scrolling for this grid\n         *  <br/>Defaults to true\n         */\n        gridOptions.enableInfiniteScroll = gridOptions.enableInfiniteScroll !== false;\n      },\n\n\n      /**\n       * @ngdoc function\n       * @name loadData\n       * @methodOf ui.grid.infiniteScroll.service:uiGridInfiniteScrollService\n       * @description This function fires 'needLoadMoreData' or 'needLoadMoreDataTop' event based on scrollDirection\n       */\n\n      loadData: function (grid) {\n        grid.options.loadTimout = true;\n        if (grid.scrollDirection === uiGridConstants.scrollDirection.UP) {\n          grid.api.infiniteScroll.raise.needLoadMoreDataTop();\n          return;\n        }\n        grid.api.infiniteScroll.raise.needLoadMoreData();\n      },\n\n      /**\n       * @ngdoc function\n       * @name checkScroll\n       * @methodOf ui.grid.infiniteScroll.service:uiGridInfiniteScrollService\n       * @description This function checks scroll position inside grid and\n       * calls 'loadData' function when scroll reaches 'infiniteScrollPercentage'\n       */\n\n      checkScroll: function(grid, scrollTop) {\n\n        /* Take infiniteScrollPercentage value or use 20% as default */\n        var infiniteScrollPercentage = grid.options.infiniteScrollPercentage ? grid.options.infiniteScrollPercentage : 20;\n\n        if (!grid.options.loadTimout && scrollTop <= infiniteScrollPercentage) {\n          this.loadData(grid);\n          return true;\n        }\n        return false;\n      }\n      /**\n       * @ngdoc property\n       * @name infiniteScrollPercentage\n       * @propertyOf ui.grid.class:GridOptions\n       * @description This setting controls at what percentage of the scroll more data\n       * is requested by the infinite scroll\n       */\n    };\n    return service;\n  }]);\n  /**\n   *  @ngdoc directive\n   *  @name ui.grid.infiniteScroll.directive:uiGridInfiniteScroll\n   *  @element div\n   *  @restrict A\n   *\n   *  @description Adds infinite scroll features to grid\n   *\n   *  @example\n   <example module=\"app\">\n   <file name=\"app.js\">\n   var app = angular.module('app', ['ui.grid', 'ui.grid.infiniteScroll']);\n\n   app.controller('MainCtrl', ['$scope', function ($scope) {\n      $scope.data = [\n        { name: 'Alex', car: 'Toyota' },\n            { name: 'Sam', car: 'Lexus' }\n      ];\n\n      $scope.columnDefs = [\n        {name: 'name'},\n        {name: 'car'}\n      ];\n    }]);\n   </file>\n   <file name=\"index.html\">\n   <div ng-controller=\"MainCtrl\">\n   <div ui-grid=\"{ data: data, columnDefs: columnDefs }\" ui-grid-infinite-scroll=\"20\"></div>\n   </div>\n   </file>\n   </example>\n   */\n\n  module.directive('uiGridInfiniteScroll', ['uiGridInfiniteScrollService',\n    function (uiGridInfiniteScrollService) {\n      return {\n        priority: -200,\n        scope: false,\n        require: '^uiGrid',\n        compile: function($scope, $elm, $attr){\n          return {\n            pre: function($scope, $elm, $attr, uiGridCtrl) {\n              uiGridInfiniteScrollService.initializeGrid(uiGridCtrl.grid);\n            },\n            post: function($scope, $elm, $attr) {\n            }\n          };\n        }\n      };\n    }]);\n\n  module.directive('uiGridViewport',\n    ['$compile', 'gridUtil', 'uiGridInfiniteScrollService', 'uiGridConstants',\n      function ($compile, gridUtil, uiGridInfiniteScrollService, uiGridConstants) {\n        return {\n          priority: -200,\n          scope: false,\n          link: function ($scope, $elm, $attr){\n            if ($scope.grid.options.enableInfiniteScroll) {\n              $scope.grid.api.core.on.scrollEvent($scope, function (args) {\n                  //Prevent circular scroll references, if source is coming from ui.grid.adjustInfiniteScrollPosition() function\n                  if (args.y && (args.source !== 'ui.grid.adjustInfiniteScrollPosition')) {\n                    var percentage = 100 - (args.y.percentage * 100);\n                    if ($scope.grid.scrollDirection === uiGridConstants.scrollDirection.UP) {\n                      percentage = (args.y.percentage * 100);\n                    }\n                    uiGridInfiniteScrollService.checkScroll($scope.grid, percentage);\n                  }\n              });\n            }\n          }\n        };\n      }]);\n})();\n(function () {\n  'use strict';\n\n  /**\n   * @ngdoc overview\n   * @name ui.grid.moveColumns\n   * @description\n   * # ui.grid.moveColumns\n   * This module provides column moving capability to ui.grid. It enables to change the position of columns.\n   * <div doc-module-components=\"ui.grid.moveColumns\"></div>\n   */\n  var module = angular.module('ui.grid.moveColumns', ['ui.grid']);\n\n  /**\n   *  @ngdoc service\n   *  @name ui.grid.moveColumns.service:uiGridMoveColumnService\n   *  @description Service for column moving feature.\n   */\n  module.service('uiGridMoveColumnService', ['$q', '$timeout', '$log', 'ScrollEvent', 'uiGridConstants', function ($q, $timeout, $log, ScrollEvent, uiGridConstants) {\n\n    var service = {\n      initializeGrid: function (grid) {\n        var self = this;\n        this.registerPublicApi(grid);\n        this.defaultGridOptions(grid.options);\n        grid.registerColumnBuilder(self.movableColumnBuilder);\n      },\n      registerPublicApi: function (grid) {\n        var self = this;\n        /**\n         *  @ngdoc object\n         *  @name ui.grid.moveColumns.api:PublicApi\n         *  @description Public Api for column moving feature.\n         */\n        var publicApi = {\n          events: {\n            /**\n             * @ngdoc event\n             * @name columnPositionChanged\n             * @eventOf  ui.grid.moveColumns.api:PublicApi\n             * @description raised when column is moved\n             * <pre>\n             *      gridApi.colMovable.on.columnPositionChanged(scope,function(colDef, originalPosition, newPosition){})\n             * </pre>\n             * @param {object} colDef the column that was moved\n             * @param {integer} originalPosition of the column\n             * @param {integer} finalPosition of the column\n             */\n            colMovable: {\n              columnPositionChanged: function (colDef, originalPosition, newPosition) {\n              }\n            }\n          },\n          methods: {\n            /**\n             * @ngdoc method\n             * @name moveColumn\n             * @methodOf  ui.grid.moveColumns.api:PublicApi\n             * @description Method can be used to change column position.\n             * <pre>\n             *      gridApi.colMovable.moveColumn(oldPosition, newPosition)\n             * </pre>\n             * @param {integer} originalPosition of the column\n             * @param {integer} finalPosition of the column\n             */\n            colMovable: {\n              moveColumn: function (originalPosition, finalPosition) {\n                var columns = grid.columns;\n                if (!angular.isNumber(originalPosition) || !angular.isNumber(finalPosition)) {\n                  console.log('Please provide valid values for originalPosition and finalPosition');\n                  return;\n                }\n                var nonMovableColumns = 0;\n                for (var i = 0; i < columns.length; i++) {\n                  if ((angular.isDefined(columns[i].colDef.visible) && columns[i].colDef.visible === false) || columns[i].isRowHeader === true) {\n                    nonMovableColumns++;\n                  }\n                }\n                if (originalPosition >= (columns.length - nonMovableColumns) || finalPosition >= (columns.length - nonMovableColumns)) {\n                  console.log('Invalid values for originalPosition, finalPosition');\n                  return;\n                }\n                var findPositionForRenderIndex = function (index) {\n                  var position = index;\n                  for (var i = 0; i <= position; i++) {\n                    if (angular.isDefined(columns[i]) && ((angular.isDefined(columns[i].colDef.visible) && columns[i].colDef.visible === false) || columns[i].isRowHeader === true)) {\n                      position++;\n                    }\n                  }\n                  return position;\n                };\n                self.redrawColumnAtPosition(grid, findPositionForRenderIndex(originalPosition), findPositionForRenderIndex(finalPosition));\n              }\n            }\n          }\n        };\n        grid.api.registerEventsFromObject(publicApi.events);\n        grid.api.registerMethodsFromObject(publicApi.methods);\n      },\n      defaultGridOptions: function (gridOptions) {\n        /**\n         *  @ngdoc object\n         *  @name ui.grid.moveColumns.api:GridOptions\n         *\n         *  @description Options for configuring the move column feature, these are available to be\n         *  set using the ui-grid {@link ui.grid.class:GridOptions gridOptions}\n         */\n        /**\n         *  @ngdoc object\n         *  @name enableColumnMoving\n         *  @propertyOf  ui.grid.moveColumns.api:GridOptions\n         *  @description If defined, sets the default value for the colMovable flag on each individual colDefs\n         *  if their individual enableColumnMoving configuration is not defined. Defaults to true.\n         */\n        gridOptions.enableColumnMoving = gridOptions.enableColumnMoving !== false;\n      },\n      movableColumnBuilder: function (colDef, col, gridOptions) {\n        var promises = [];\n        /**\n         *  @ngdoc object\n         *  @name ui.grid.moveColumns.api:ColumnDef\n         *\n         *  @description Column Definition for move column feature, these are available to be\n         *  set using the ui-grid {@link ui.grid.class:GridOptions.columnDef gridOptions.columnDefs}\n         */\n        /**\n         *  @ngdoc object\n         *  @name enableColumnMoving\n         *  @propertyOf  ui.grid.moveColumns.api:ColumnDef\n         *  @description Enable column moving for the column.\n         */\n        colDef.enableColumnMoving = colDef.enableColumnMoving === undefined ? gridOptions.enableColumnMoving\n          : colDef.enableColumnMoving;\n        return $q.all(promises);\n      },\n      redrawColumnAtPosition: function (grid, originalPosition, newPosition) {\n\n        var columns = grid.columns;\n\n        var originalColumn = columns[originalPosition];\n        if (originalColumn.colDef.enableColumnMoving) {\n          if (originalPosition > newPosition) {\n            for (var i1 = originalPosition; i1 > newPosition; i1--) {\n              columns[i1] = columns[i1 - 1];\n            }\n          }\n          else if (newPosition > originalPosition) {\n            for (var i2 = originalPosition; i2 < newPosition; i2++) {\n              columns[i2] = columns[i2 + 1];\n            }\n          }\n          columns[newPosition] = originalColumn;\n          $timeout(function () {\n            grid.refresh();\n            grid.api.colMovable.raise.columnPositionChanged(originalColumn.colDef, originalPosition, newPosition);\n            grid.api.core.notifyDataChange( uiGridConstants.dataChange.COLUMN );\n          });\n        }\n      }\n    };\n    return service;\n  }]);\n\n  /**\n   *  @ngdoc directive\n   *  @name ui.grid.moveColumns.directive:uiGridMoveColumns\n   *  @element div\n   *  @restrict A\n   *  @description Adds column moving features to the ui-grid directive.\n   *  @example\n   <example module=\"app\">\n   <file name=\"app.js\">\n   var app = angular.module('app', ['ui.grid', 'ui.grid.moveColumns']);\n   app.controller('MainCtrl', ['$scope', function ($scope) {\n        $scope.data = [\n          { name: 'Bob', title: 'CEO', age: 45 },\n          { name: 'Frank', title: 'Lowly Developer', age: 25 },\n          { name: 'Jenny', title: 'Highly Developer', age: 35 }\n        ];\n        $scope.columnDefs = [\n          {name: 'name'},\n          {name: 'title'},\n          {name: 'age'}\n        ];\n      }]);\n   </file>\n   <file name=\"main.css\">\n   .grid {\n      width: 100%;\n      height: 150px;\n    }\n   </file>\n   <file name=\"index.html\">\n   <div ng-controller=\"MainCtrl\">\n   <div class=\"grid\" ui-grid=\"{ data: data, columnDefs: columnDefs }\" ui-grid-move-columns></div>\n   </div>\n   </file>\n   </example>\n   */\n  module.directive('uiGridMoveColumns', ['uiGridMoveColumnService', function (uiGridMoveColumnService) {\n    return {\n      replace: true,\n      priority: 0,\n      require: '^uiGrid',\n      scope: false,\n      compile: function () {\n        return {\n          pre: function ($scope, $elm, $attrs, uiGridCtrl) {\n            uiGridMoveColumnService.initializeGrid(uiGridCtrl.grid);\n          },\n          post: function ($scope, $elm, $attrs, uiGridCtrl) {\n          }\n        };\n      }\n    };\n  }]);\n\n  /**\n   *  @ngdoc directive\n   *  @name ui.grid.moveColumns.directive:uiGridHeaderCell\n   *  @element div\n   *  @restrict A\n   *\n   *  @description Stacks on top of ui.grid.uiGridHeaderCell to provide capability to be able to move it to reposition column.\n   *\n   *  On receiving mouseDown event headerCell is cloned, now as the mouse moves the cloned header cell also moved in the grid.\n   *  In case the moving cloned header cell reaches the left or right extreme of grid, grid scrolling is triggered (if horizontal scroll exists).\n   *  On mouseUp event column is repositioned at position where mouse is released and cloned header cell is removed.\n   *\n   *  Events that invoke cloning of header cell:\n   *    - mousedown\n   *\n   *  Events that invoke movement of cloned header cell:\n   *    - mousemove\n   *\n   *  Events that invoke repositioning of column:\n   *    - mouseup\n   */\n  module.directive('uiGridHeaderCell', ['$q', 'gridUtil', 'uiGridMoveColumnService', '$document', '$log', 'uiGridConstants', 'ScrollEvent',\n    function ($q, gridUtil, uiGridMoveColumnService, $document, $log, uiGridConstants, ScrollEvent) {\n      return {\n        priority: -10,\n        require: '^uiGrid',\n        compile: function () {\n          return {\n            post: function ($scope, $elm, $attrs, uiGridCtrl) {\n\n              if ($scope.col.colDef.enableColumnMoving) {\n\n                $scope.$on(uiGridConstants.events.COLUMN_HEADER_CLICK, function (event, args) {\n\n                  if (args.columnName === $scope.col.colDef.name && !$scope.col.renderContainer) {\n\n                    var evt = args.event;\n                    if (evt.target.className !== 'ui-grid-icon-angle-down' && evt.target.tagName !== 'I' &&\n                      evt.target.className.indexOf('ui-grid-filter-input') < 0) {\n\n                      //Setting some variables required for calculations.\n                      var gridLeft = $scope.grid.element[0].getBoundingClientRect().left;\n                      var previousMouseX = evt.pageX;\n                      var totalMouseMovement = 0;\n                      var rightMoveLimit = gridLeft + $scope.grid.getViewportWidth();// - $scope.grid.verticalScrollbarWidth;\n\n                      //Clone element should move horizontally with mouse.\n                      var elmCloned = false;\n                      var movingElm;\n                      var reducedWidth;\n\n                      var cloneElement = function () {\n                        elmCloned = true;\n\n                        //Cloning header cell and appending to current header cell.\n                        movingElm = $elm.clone();\n                        $elm.parent().append(movingElm);\n\n                        //Left of cloned element should be aligned to original header cell.\n                        movingElm.addClass('movingColumn');\n                        var movingElementStyles = {};\n                        var elmLeft = $elm[0].getBoundingClientRect().left;\n                        movingElementStyles.left = (elmLeft - gridLeft) + 'px';\n                        var gridRight = $scope.grid.element[0].getBoundingClientRect().right;\n                        var elmRight = $elm[0].getBoundingClientRect().right;\n                        if (elmRight > gridRight) {\n                          reducedWidth = $scope.col.drawnWidth + (gridRight - elmRight);\n                          movingElementStyles.width = reducedWidth + 'px';\n                        }\n                        movingElm.css(movingElementStyles);\n                      };\n\n                      var moveElement = function (changeValue) {\n                        //Hide column menu\n                        uiGridCtrl.fireEvent('hide-menu');\n\n                        //Calculate total column width\n                        var columns = $scope.grid.columns;\n                        var totalColumnWidth = 0;\n                        for (var i = 0; i < columns.length; i++) {\n                          if (angular.isUndefined(columns[i].colDef.visible) || columns[i].colDef.visible === true) {\n                            totalColumnWidth += columns[i].drawnWidth || columns[i].width || columns[i].colDef.width;\n                          }\n                        }\n\n                        //Calculate new position of left of column\n                        var currentElmLeft = movingElm[0].getBoundingClientRect().left - 1;\n                        var currentElmRight = movingElm[0].getBoundingClientRect().right;\n                        var newElementLeft;\n                        if (gridUtil.detectBrowser() === 'ie') {\n                          newElementLeft = currentElmLeft + changeValue;\n                        }\n                        else {\n                          newElementLeft = currentElmLeft - gridLeft + changeValue;\n                        }\n                        newElementLeft = newElementLeft < rightMoveLimit ? newElementLeft : rightMoveLimit;\n\n                        //Update css of moving column to adjust to new left value or fire scroll in case column has reached edge of grid\n                        if ((currentElmLeft >= gridLeft || changeValue > 0) && (currentElmRight <= rightMoveLimit || changeValue < 0)) {\n                          movingElm.css({visibility: 'visible', 'left': newElementLeft + 'px'});\n                        }\n                        else if (totalColumnWidth > Math.ceil(uiGridCtrl.grid.gridWidth)) {\n                          changeValue *= 8;\n                          var scrollEvent = new ScrollEvent($scope.col.grid, null, null, 'uiGridHeaderCell.moveElement');\n                          scrollEvent.x = {pixels: changeValue};\n                          scrollEvent.fireScrollingEvent();\n                        }\n\n                        //Calculate total width of columns on the left of the moving column and the mouse movement\n                        var totalColumnsLeftWidth = 0;\n                        for (var il = 0; il < columns.length; il++) {\n                          if (angular.isUndefined(columns[il].colDef.visible) || columns[il].colDef.visible === true) {\n                            if (columns[il].colDef.name !== $scope.col.colDef.name) {\n                              totalColumnsLeftWidth += columns[il].drawnWidth || columns[il].width || columns[il].colDef.width;\n                            }\n                            else {\n                              break;\n                            }\n                          }\n                        }\n                        if ($scope.newScrollLeft === undefined) {\n                          totalMouseMovement += changeValue;\n                        }\n                        else {\n                          totalMouseMovement = $scope.newScrollLeft + newElementLeft - totalColumnsLeftWidth;\n                        }\n\n                        //Increase width of moving column, in case the rightmost column was moved and its width was\n                        //decreased because of overflow\n                        if (reducedWidth < $scope.col.drawnWidth) {\n                          reducedWidth += Math.abs(changeValue);\n                          movingElm.css({'width': reducedWidth + 'px'});\n                        }\n                      };\n\n                      var mouseMoveHandler = function (evt) {\n                        //Disable text selection in Chrome during column move\n                        document.onselectstart = function() { return false; };\n\n                        var changeValue = evt.pageX - previousMouseX;\n                        if (!elmCloned && Math.abs(changeValue) > 50) {\n                          cloneElement();\n                        }\n                        else if (elmCloned) {\n                          moveElement(changeValue);\n                          previousMouseX = evt.pageX;\n                        }\n                      };\n\n                      /*\n                       //Commenting these lines as they are creating trouble with column moving when grid has huge scroll\n                       // On scope destroy, remove the mouse event handlers from the document body\n                       $scope.$on('$destroy', function () {\n                       $document.off('mousemove', mouseMoveHandler);\n                       $document.off('mouseup', mouseUpHandler);\n                       });\n                       */\n                      $document.on('mousemove', mouseMoveHandler);\n\n                      var mouseUpHandler = function (evt) {\n                        //Re-enable text selection after column move\n                        document.onselectstart = null;\n\n                        //Remove the cloned element on mouse up.\n                        if (movingElm) {\n                          movingElm.remove();\n                        }\n\n                        var columns = $scope.grid.columns;\n                        var columnIndex = 0;\n                        for (var i = 0; i < columns.length; i++) {\n                          if (columns[i].colDef.name !== $scope.col.colDef.name) {\n                            columnIndex++;\n                          }\n                          else {\n                            break;\n                          }\n                        }\n\n                        //Case where column should be moved to a position on its left\n                        if (totalMouseMovement < 0) {\n                          var totalColumnsLeftWidth = 0;\n                          for (var il = columnIndex - 1; il >= 0; il--) {\n                            if (angular.isUndefined(columns[il].colDef.visible) || columns[il].colDef.visible === true) {\n                              totalColumnsLeftWidth += columns[il].drawnWidth || columns[il].width || columns[il].colDef.width;\n                              if (totalColumnsLeftWidth > Math.abs(totalMouseMovement)) {\n                                uiGridMoveColumnService.redrawColumnAtPosition\n                                ($scope.grid, columnIndex, il + 1);\n                                break;\n                              }\n                            }\n                          }\n                          //Case where column should be moved to beginning of the grid.\n                          if (totalColumnsLeftWidth < Math.abs(totalMouseMovement)) {\n                            uiGridMoveColumnService.redrawColumnAtPosition\n                            ($scope.grid, columnIndex, 0);\n                          }\n                        }\n\n                        //Case where column should be moved to a position on its right\n                        else if (totalMouseMovement > 0) {\n                          var totalColumnsRightWidth = 0;\n                          for (var ir = columnIndex + 1; ir < columns.length; ir++) {\n                            if (angular.isUndefined(columns[ir].colDef.visible) || columns[ir].colDef.visible === true) {\n                              totalColumnsRightWidth += columns[ir].drawnWidth || columns[ir].width || columns[ir].colDef.width;\n                              if (totalColumnsRightWidth > totalMouseMovement) {\n                                uiGridMoveColumnService.redrawColumnAtPosition\n                                ($scope.grid, columnIndex, ir - 1);\n                                break;\n                              }\n                            }\n                          }\n                          //Case where column should be moved to end of the grid.\n                          if (totalColumnsRightWidth < totalMouseMovement) {\n                            uiGridMoveColumnService.redrawColumnAtPosition\n                            ($scope.grid, columnIndex, columns.length - 1);\n                          }\n                        }\n/*\n                        else if (totalMouseMovement === 0) {\n                          if (uiGridCtrl.grid.options.enableSorting && $scope.col.enableSorting) {\n                            //sort the current column\n                            var add = false;\n                            if (evt.shiftKey) {\n                              add = true;\n                            }\n                            // Sort this column then rebuild the grid's rows\n                            uiGridCtrl.grid.sortColumn($scope.col, add)\n                              .then(function () {\n                                if (uiGridCtrl.columnMenuScope) {\n                                  uiGridCtrl.columnMenuScope.hideMenu();\n                                }\n                                uiGridCtrl.grid.refresh();\n                              });\n                          }\n                        }\n*/\n                        $document.off('mousemove', mouseMoveHandler);\n                        $document.off('mouseup', mouseUpHandler);\n                      };\n\n                      //Binding the mouseup event handler\n                      $document.on('mouseup', mouseUpHandler);\n                    }\n                  }\n                });\n              }\n            }\n          };\n        }\n      };\n    }]);\n})();\n\n(function() {\n  'use strict';\n\n  /**\n   * @ngdoc overview\n   * @name ui.grid.pagination\n   *\n   * @description\n   *\n   * #ui.grid.pagination\n   * This module provides pagination support to ui-grid\n   */\n  var module = angular.module('ui.grid.pagination', ['ng', 'ui.grid']);\n\n  /**\n   * @ngdoc service\n   * @name ui.grid.pagination.service:uiGridPaginationService\n   *\n   * @description Service for the pagination feature\n   */\n  module.service('uiGridPaginationService', ['gridUtil',\n    function (gridUtil) {\n      var service = {\n        /**\n         * @ngdoc method\n         * @name initializeGrid\n         * @methodOf ui.grid.pagination.service:uiGridPaginationService\n         * @description Attaches the service to a certain grid\n         * @param {Grid} grid The grid we want to work with\n         */\n        initializeGrid: function (grid) {\n          service.defaultGridOptions(grid.options);\n\n          /**\n          * @ngdoc object\n          * @name ui.grid.pagination.api:PublicAPI\n          *\n          * @description Public API for the pagination feature\n          */\n          var publicApi = {\n            events: {\n              pagination: {\n              /**\n               * @ngdoc event\n               * @name paginationChanged\n               * @eventOf ui.grid.pagination.api:PublicAPI\n               * @description This event fires when the pageSize or currentPage changes\n               * @param {int} currentPage requested page number\n               * @param {int} pageSize requested page size\n               */\n                paginationChanged: function (currentPage, pageSize) { }\n              }\n            },\n            methods: {\n              pagination: {\n                /**\n                 * @ngdoc method\n                 * @name getPage\n                 * @methodOf ui.grid.pagination.api:PublicAPI\n                 * @description Returns the number of the current page\n                 */\n                getPage: function () {\n                  return grid.options.enablePagination ? grid.options.paginationCurrentPage : null;\n                },\n                /**\n                 * @ngdoc method\n                 * @name getTotalPages\n                 * @methodOf ui.grid.pagination.api:PublicAPI\n                 * @description Returns the total number of pages\n                 */\n                getTotalPages: function () {\n                  if (!grid.options.enablePagination) {\n                    return null;\n                  }\n\n                  return (grid.options.totalItems === 0) ? 1 : Math.ceil(grid.options.totalItems / grid.options.paginationPageSize);\n                },\n                /**\n                 * @ngdoc method\n                 * @name nextPage\n                 * @methodOf ui.grid.pagination.api:PublicAPI\n                 * @description Moves to the next page, if possible\n                 */\n                nextPage: function () {\n                  if (!grid.options.enablePagination) {\n                    return;\n                  }\n\n                  if (grid.options.totalItems > 0) {\n                    grid.options.paginationCurrentPage = Math.min(\n                      grid.options.paginationCurrentPage + 1,\n                      publicApi.methods.pagination.getTotalPages()\n                    );\n                  } else {\n                    grid.options.paginationCurrentPage++;\n                  }\n                },\n                /**\n                 * @ngdoc method\n                 * @name previousPage\n                 * @methodOf ui.grid.pagination.api:PublicAPI\n                 * @description Moves to the previous page, if we're not on the first page\n                 */\n                previousPage: function () {\n                  if (!grid.options.enablePagination) {\n                    return;\n                  }\n\n                  grid.options.paginationCurrentPage = Math.max(grid.options.paginationCurrentPage - 1, 1);\n                },\n                /**\n                 * @ngdoc method\n                 * @name seek\n                 * @methodOf ui.grid.pagination.api:PublicAPI\n                 * @description Moves to the requested page\n                 * @param {int} page The number of the page that should be displayed\n                 */\n                seek: function (page) {\n                  if (!grid.options.enablePagination) {\n                    return;\n                  }\n                  if (!angular.isNumber(page) || page < 1) {\n                    throw 'Invalid page number: ' + page;\n                  }\n\n                  grid.options.paginationCurrentPage = Math.min(page, publicApi.methods.pagination.getTotalPages());\n                }\n              }\n            }\n          };\n\n          grid.api.registerEventsFromObject(publicApi.events);\n          grid.api.registerMethodsFromObject(publicApi.methods);\n          grid.registerRowsProcessor(function (renderableRows) {\n            if (grid.options.useExternalPagination || !grid.options.enablePagination) {\n              return renderableRows;\n            }\n            //client side pagination\n            var pageSize = parseInt(grid.options.paginationPageSize, 10);\n            var currentPage = parseInt(grid.options.paginationCurrentPage, 10);\n            \n            var visibleRows = renderableRows.filter(function (row) { return row.visible; });\n            grid.options.totalItems = visibleRows.length;\n\n            var firstRow = (currentPage - 1) * pageSize;\n            if (firstRow > visibleRows.length) {\n              currentPage = grid.options.paginationCurrentPage = 1;\n              firstRow = (currentPage - 1) * pageSize;\n            }\n            return visibleRows.slice(firstRow, firstRow + pageSize);\n          });\n\n        },\n        defaultGridOptions: function (gridOptions) {\n          /**\n           * @ngdoc object\n           * @name ui.grid.pagination.api:GridOptions\n           *\n           * @description GridOptions for the pagination feature, these are available to be\n           * set using the ui-grid {@link ui.grid.class:GridOptions gridOptions}\n           */\n\n          /**\n           * @ngdoc property\n           * @name enablePagination\n           * @propertyOf ui.grid.pagination.api:GridOptions\n           * @description Enables pagination, defaults to true\n           */\n          gridOptions.enablePagination = gridOptions.enablePagination !== false;\n          /**\n           * @ngdoc property\n           * @name enablePaginationControls\n           * @propertyOf ui.grid.pagination.api:GridOptions\n           * @description Enables the paginator at the bottom of the grid. Turn this off, if you want to implement your\n           *              own controls outside the grid.\n           */\n          gridOptions.enablePaginationControls = gridOptions.enablePaginationControls !== false;\n          /**\n           * @ngdoc property\n           * @name useExternalPagination\n           * @propertyOf ui.grid.pagination.api:GridOptions\n           * @description Disables client side pagination. When true, handle the paginationChanged event and set data\n           *              and totalItems, defaults to `false`\n           */\n          gridOptions.useExternalPagination = gridOptions.useExternalPagination === true;\n          /**\n           * @ngdoc property\n           * @name totalItems\n           * @propertyOf ui.grid.pagination.api:GridOptions\n           * @description Total number of items, set automatically when client side pagination, needs set by user\n           *              for server side pagination\n           */\n          if (gridUtil.isNullOrUndefined(gridOptions.totalItems)) {\n            gridOptions.totalItems = 0;\n          }\n          /**\n           * @ngdoc property\n           * @name paginationPageSizes\n           * @propertyOf ui.grid.pagination.api:GridOptions\n           * @description Array of page sizes, defaults to `[250, 500, 1000]`\n           */\n          if (gridUtil.isNullOrUndefined(gridOptions.paginationPageSizes)) {\n            gridOptions.paginationPageSizes = [250, 500, 1000];\n          }\n          /**\n           * @ngdoc property\n           * @name paginationPageSize\n           * @propertyOf ui.grid.pagination.api:GridOptions\n           * @description Page size, defaults to the first item in paginationPageSizes, or 0 if paginationPageSizes is empty\n           */\n          if (gridUtil.isNullOrUndefined(gridOptions.paginationPageSize)) {\n            if (gridOptions.paginationPageSizes.length > 0) {\n              gridOptions.paginationPageSize = gridOptions.paginationPageSizes[0];\n            } else {              \n              gridOptions.paginationPageSize = 0;\n            }\n          }\n          /**\n           * @ngdoc property\n           * @name paginationCurrentPage\n           * @propertyOf ui.grid.pagination.api:GridOptions\n           * @description Current page number, defaults to 1\n           */\n          if (gridUtil.isNullOrUndefined(gridOptions.paginationCurrentPage)) {\n            gridOptions.paginationCurrentPage = 1;\n          }\n\n          /**\n           * @ngdoc property\n           * @name paginationTemplate\n           * @propertyOf ui.grid.pagination.api:GridOptions\n           * @description A custom template for the pager, defaults to `ui-grid/pagination`\n           */\n          if (gridUtil.isNullOrUndefined(gridOptions.paginationTemplate)) {\n            gridOptions.paginationTemplate = 'ui-grid/pagination';\n          }\n        },\n        /**\n         * @ngdoc method\n         * @methodOf ui.grid.pagination.service:uiGridPaginationService\n         * @name uiGridPaginationService\n         * @description  Raises paginationChanged and calls refresh for client side pagination\n         * @param {Grid} grid the grid for which the pagination changed\n         * @param {int} currentPage requested page number\n         * @param {int} pageSize requested page size\n         */\n        onPaginationChanged: function (grid, currentPage, pageSize) {\n            grid.api.pagination.raise.paginationChanged(currentPage, pageSize);\n            if (!grid.options.useExternalPagination) {\n              grid.refresh(); //client side pagination\n            }\n        }\n      };\n      \n      return service;\n    }\n  ]);\n  /**\n   *  @ngdoc directive\n   *  @name ui.grid.pagination.directive:uiGridPagination\n   *  @element div\n   *  @restrict A\n   *\n   *  @description Adds pagination features to grid\n   *  @example\n   <example module=\"app\">\n   <file name=\"app.js\">\n   var app = angular.module('app', ['ui.grid', 'ui.grid.pagination']);\n\n   app.controller('MainCtrl', ['$scope', function ($scope) {\n      $scope.data = [\n        { name: 'Alex', car: 'Toyota' },\n        { name: 'Sam', car: 'Lexus' },\n        { name: 'Joe', car: 'Dodge' },\n        { name: 'Bob', car: 'Buick' },\n        { name: 'Cindy', car: 'Ford' },\n        { name: 'Brian', car: 'Audi' },\n        { name: 'Malcom', car: 'Mercedes Benz' },\n        { name: 'Dave', car: 'Ford' },\n        { name: 'Stacey', car: 'Audi' },\n        { name: 'Amy', car: 'Acura' },\n        { name: 'Scott', car: 'Toyota' },\n        { name: 'Ryan', car: 'BMW' },\n      ];\n\n      $scope.gridOptions = {\n        data: 'data',\n        paginationPageSizes: [5, 10, 25],\n        paginationPageSize: 5,\n        columnDefs: [\n          {name: 'name'},\n          {name: 'car'}\n        ];\n       }\n    }]);\n   </file>\n   <file name=\"index.html\">\n   <div ng-controller=\"MainCtrl\">\n   <div ui-grid=\"gridOptions\" ui-grid-pagination></div>\n   </div>\n   </file>\n   </example>\n   */\n  module.directive('uiGridPagination', ['gridUtil', 'uiGridPaginationService',\n    function (gridUtil, uiGridPaginationService) {\n      return {\n        priority: -200,\n        scope: false,\n        require: 'uiGrid',\n        link: {\n          pre: function ($scope, $elm, $attr, uiGridCtrl) {\n            uiGridPaginationService.initializeGrid(uiGridCtrl.grid);\n\n            gridUtil.getTemplate(uiGridCtrl.grid.options.paginationTemplate)\n              .then(function (contents) {\n                var template = angular.element(contents);\n                $elm.append(template);\n                uiGridCtrl.innerCompile(template);\n              });\n          }\n        }\n      };\n    }\n  ]);\n\n  /**\n   *  @ngdoc directive\n   *  @name ui.grid.pagination.directive:uiGridPager\n   *  @element div\n   *\n   *  @description Panel for handling pagination\n   */\n  module.directive('uiGridPager', ['uiGridPaginationService', 'uiGridConstants', 'gridUtil', 'i18nService',\n    function (uiGridPaginationService, uiGridConstants, gridUtil, i18nService) {\n      return {\n        priority: -200,\n        scope: true,\n        require: '^uiGrid',\n        link: function ($scope, $elm, $attr, uiGridCtrl) {\n          $scope.paginationApi = uiGridCtrl.grid.api.pagination;\n          $scope.sizesLabel = i18nService.getSafeText('pagination.sizes');\n          $scope.totalItemsLabel = i18nService.getSafeText('pagination.totalItems');\n          \n          var options = uiGridCtrl.grid.options;\n          \n          uiGridCtrl.grid.renderContainers.body.registerViewportAdjuster(function (adjustment) {\n            adjustment.height = adjustment.height - gridUtil.elementHeight($elm);\n            return adjustment;\n          });\n          \n          var dataChangeDereg = uiGridCtrl.grid.registerDataChangeCallback(function (grid) {\n            if (!grid.options.useExternalPagination) {\n              grid.options.totalItems = grid.rows.length;\n            }\n          }, [uiGridConstants.dataChange.ROW]);\n          \n          $scope.$on('$destroy', dataChangeDereg);\n\n          var setShowing = function () {\n            $scope.showingLow = ((options.paginationCurrentPage - 1) * options.paginationPageSize) + 1;\n            $scope.showingHigh = Math.min(options.paginationCurrentPage * options.paginationPageSize, options.totalItems);\n          };\n\n          var deregT = $scope.$watch('grid.options.totalItems + grid.options.paginationPageSize', setShowing);\n\n          var deregP = $scope.$watch('grid.options.paginationCurrentPage + grid.options.paginationPageSize', function (newValues, oldValues) {\n              if (newValues === oldValues) { \n                return; \n              }\n\n              if (!angular.isNumber(options.paginationCurrentPage) || options.paginationCurrentPage < 1) {\n                options.paginationCurrentPage = 1;\n                return;\n              }\n\n              if (options.totalItems > 0 && options.paginationCurrentPage > $scope.paginationApi.getTotalPages()) {\n                options.paginationCurrentPage = $scope.paginationApi.getTotalPages();\n                return;\n              }\n\n              setShowing();\n              uiGridPaginationService.onPaginationChanged($scope.grid, options.paginationCurrentPage, options.paginationPageSize);\n            }\n          );\n\n          $scope.$on('$destroy', function() {\n            deregT();\n            deregP();\n          });\n\n          $scope.cantPageForward = function () {\n            if (options.totalItems > 0) {\n              return options.paginationCurrentPage >= $scope.paginationApi.getTotalPages();\n            } else {\n              return options.data.length < 1;\n            }\n          };\n          \n          $scope.cantPageToLast = function () {\n            if (options.totalItems > 0) {\n              return $scope.cantPageForward();\n            } else {\n              return true;\n            }\n          };\n          \n          $scope.cantPageBackward = function () {\n            return options.paginationCurrentPage <= 1;\n          };\n        }\n      };\n    }\n  ]);\n})();\n\n(function () {\n  'use strict';\n\n  /**\n   * @ngdoc overview\n   * @name ui.grid.pinning\n   * @description\n   *\n   *  # ui.grid.pinning\n   * This module provides column pinning to the end user via menu options in the column header\n   * <br/>\n   * <br/>\n   *\n   * <div doc-module-components=\"ui.grid.pinning\"></div>\n   */\n\n  var module = angular.module('ui.grid.pinning', ['ui.grid']);\n\n  module.service('uiGridPinningService', ['gridUtil', 'GridRenderContainer', 'i18nService', function (gridUtil, GridRenderContainer, i18nService) {\n    var service = {\n\n      initializeGrid: function (grid) {\n        service.defaultGridOptions(grid.options);\n\n        // Register a column builder to add new menu items for pinning left and right\n        grid.registerColumnBuilder(service.pinningColumnBuilder);\n      },\n\n      defaultGridOptions: function (gridOptions) {\n        //default option to true unless it was explicitly set to false\n        /**\n         *  @ngdoc object\n         *  @name ui.grid.pinning.api:GridOptions\n         *\n         *  @description GridOptions for pinning feature, these are available to be  \n           *  set using the ui-grid {@link ui.grid.class:GridOptions gridOptions}\n         */\n\n        /**\n         *  @ngdoc object\n         *  @name enablePinning\n         *  @propertyOf  ui.grid.pinning.api:GridOptions\n         *  @description Enable pinning for the entire grid.  \n         *  <br/>Defaults to true\n         */\n        gridOptions.enablePinning = gridOptions.enablePinning !== false;\n\n      },\n\n      pinningColumnBuilder: function (colDef, col, gridOptions) {\n        //default to true unless gridOptions or colDef is explicitly false\n\n        /**\n         *  @ngdoc object\n         *  @name ui.grid.pinning.api:ColumnDef\n         *\n         *  @description ColumnDef for pinning feature, these are available to be \n         *  set using the ui-grid {@link ui.grid.class:GridOptions.columnDef gridOptions.columnDefs}\n         */\n\n        /**\n         *  @ngdoc object\n         *  @name enablePinning\n         *  @propertyOf  ui.grid.pinning.api:ColumnDef\n         *  @description Enable pinning for the individual column.  \n         *  <br/>Defaults to true\n         */\n        colDef.enablePinning = colDef.enablePinning === undefined ? gridOptions.enablePinning : colDef.enablePinning;\n\n\n        /**\n         *  @ngdoc object\n         *  @name pinnedLeft\n         *  @propertyOf  ui.grid.pinning.api:ColumnDef\n         *  @description Column is pinned left when grid is rendered\n         *  <br/>Defaults to false\n         */\n\n        /**\n         *  @ngdoc object\n         *  @name pinnedRight\n         *  @propertyOf  ui.grid.pinning.api:ColumnDef\n         *  @description Column is pinned right when grid is rendered\n         *  <br/>Defaults to false\n         */\n        if (colDef.pinnedLeft) {\n          if (col.width === '*') {\n            // Need to refresh so the width can be calculated.\n            col.grid.refresh()\n                .then(function () {\n                    col.renderContainer = 'left';\n                    // Need to calculate the width. If col.drawnWidth is used instead then the width\n                    // will be 100% if it's the first column, 50% if it's the second etc.\n                    col.width = col.grid.canvasWidth / col.grid.columns.length;\n                    col.grid.createLeftContainer();\n            });\n          }\n          else {\n            col.renderContainer = 'left';\n            col.grid.createLeftContainer();\n          }\n        }\n        else if (colDef.pinnedRight) {\n            if (col.width === '*') {\n                // Need to refresh so the width can be calculated.\n                col.grid.refresh()\n                    .then(function () {\n                        col.renderContainer = 'right';\n                        // Need to calculate the width. If col.drawnWidth is used instead then the width\n                        // will be 100% if it's the first column, 50% if it's the second etc.\n                        col.width = col.grid.canvasWidth / col.grid.columns.length;\n                        col.grid.createRightContainer();\n                    });\n            }\n            else {\n                col.renderContainer = 'right';\n                col.grid.createRightContainer();\n            }\n        }\n\n        if (!colDef.enablePinning) {\n          return;\n        }\n\n        var pinColumnLeftAction = {\n          name: 'ui.grid.pinning.pinLeft',\n          title: i18nService.get().pinning.pinLeft,\n          icon: 'ui-grid-icon-left-open',\n          shown: function () {\n            return typeof(this.context.col.renderContainer) === 'undefined' || !this.context.col.renderContainer || this.context.col.renderContainer !== 'left';\n          },\n          action: function () {\n            this.context.col.renderContainer = 'left';\n            this.context.col.width = this.context.col.drawnWidth;\n            this.context.col.grid.createLeftContainer();\n\n            // Need to call refresh twice; once to move our column over to the new render container and then\n            //   a second time to update the grid viewport dimensions with our adjustments\n            col.grid.refresh()\n              .then(function () {\n                col.grid.refresh();\n              });\n          }\n        };\n\n        var pinColumnRightAction = {\n          name: 'ui.grid.pinning.pinRight',\n          title: i18nService.get().pinning.pinRight,\n          icon: 'ui-grid-icon-right-open',\n          shown: function () {\n            return typeof(this.context.col.renderContainer) === 'undefined' || !this.context.col.renderContainer || this.context.col.renderContainer !== 'right';\n          },\n          action: function () {\n            this.context.col.renderContainer = 'right';\n            this.context.col.width = this.context.col.drawnWidth;\n            this.context.col.grid.createRightContainer();\n\n\n            // Need to call refresh twice; once to move our column over to the new render container and then\n            //   a second time to update the grid viewport dimensions with our adjustments\n            col.grid.refresh()\n              .then(function () {\n                col.grid.refresh();\n              });\n          }\n        };\n\n        var removePinAction = {\n          name: 'ui.grid.pinning.unpin',\n          title: i18nService.get().pinning.unpin,\n          icon: 'ui-grid-icon-cancel',\n          shown: function () {\n            return typeof(this.context.col.renderContainer) !== 'undefined' && this.context.col.renderContainer !== null && this.context.col.renderContainer !== 'body';\n          },\n          action: function () {\n            this.context.col.renderContainer = null;\n\n            // Need to call refresh twice; once to move our column over to the new render container and then\n            //   a second time to update the grid viewport dimensions with our adjustments\n            col.grid.refresh()\n              .then(function () {\n                col.grid.refresh();\n              });\n          }\n        };\n\n        if (!gridUtil.arrayContainsObjectWithProperty(col.menuItems, 'name', 'ui.grid.pinning.pinLeft')) {\n          col.menuItems.push(pinColumnLeftAction);\n        }\n        if (!gridUtil.arrayContainsObjectWithProperty(col.menuItems, 'name', 'ui.grid.pinning.pinRight')) {\n          col.menuItems.push(pinColumnRightAction);\n        }\n        if (!gridUtil.arrayContainsObjectWithProperty(col.menuItems, 'name', 'ui.grid.pinning.unpin')) {\n          col.menuItems.push(removePinAction);\n        }\n      }\n    };\n\n    return service;\n  }]);\n\n  module.directive('uiGridPinning', ['gridUtil', 'uiGridPinningService',\n    function (gridUtil, uiGridPinningService) {\n      return {\n        require: 'uiGrid',\n        scope: false,\n        compile: function () {\n          return {\n            pre: function ($scope, $elm, $attrs, uiGridCtrl) {\n              uiGridPinningService.initializeGrid(uiGridCtrl.grid);\n            },\n            post: function ($scope, $elm, $attrs, uiGridCtrl) {\n            }\n          };\n        }\n      };\n    }]);\n\n\n})();\n\n(function(){\n  'use strict';\n\n  var module = angular.module('ui.grid.resizeColumns', ['ui.grid']);\n\n  module.service('uiGridResizeColumnsService', ['gridUtil', '$q', '$timeout',\n    function (gridUtil, $q, $timeout) {\n\n      var service = {\n        defaultGridOptions: function(gridOptions){\n          //default option to true unless it was explicitly set to false\n          /**\n           *  @ngdoc object\n           *  @name ui.grid.resizeColumns.api:GridOptions\n           *\n           *  @description GridOptions for resizeColumns feature, these are available to be  \n           *  set using the ui-grid {@link ui.grid.class:GridOptions gridOptions}\n           */\n\n          /**\n           *  @ngdoc object\n           *  @name enableColumnResizing\n           *  @propertyOf  ui.grid.resizeColumns.api:GridOptions\n           *  @description Enable column resizing on the entire grid \n           *  <br/>Defaults to true\n           */\n          gridOptions.enableColumnResizing = gridOptions.enableColumnResizing !== false;\n\n          //legacy support\n          //use old name if it is explicitly false\n          if (gridOptions.enableColumnResize === false){\n            gridOptions.enableColumnResizing = false;\n          }\n        },\n\n        colResizerColumnBuilder: function (colDef, col, gridOptions) {\n\n          var promises = [];\n          /**\n           *  @ngdoc object\n           *  @name ui.grid.resizeColumns.api:ColumnDef\n           *\n           *  @description ColumnDef for resizeColumns feature, these are available to be \n           *  set using the ui-grid {@link ui.grid.class:GridOptions.columnDef gridOptions.columnDefs}\n           */\n\n          /**\n           *  @ngdoc object\n           *  @name enableColumnResizing\n           *  @propertyOf  ui.grid.resizeColumns.api:ColumnDef\n           *  @description Enable column resizing on an individual column\n           *  <br/>Defaults to GridOptions.enableColumnResizing\n           */\n          //default to true unless gridOptions or colDef is explicitly false\n          colDef.enableColumnResizing = colDef.enableColumnResizing === undefined ? gridOptions.enableColumnResizing : colDef.enableColumnResizing;\n\n\n          //legacy support of old option name\n          if (colDef.enableColumnResize === false){\n            colDef.enableColumnResizing = false;\n          }\n\n          return $q.all(promises);\n        },\n        \n        registerPublicApi: function (grid) {\n            /**\n             *  @ngdoc object\n             *  @name ui.grid.resizeColumns.api:PublicApi\n             *  @description Public Api for column resize feature.\n             */\n            var publicApi = {\n              events: {\n                /**\n                 * @ngdoc event\n                 * @name columnSizeChanged\n                 * @eventOf  ui.grid.resizeColumns.api:PublicApi\n                 * @description raised when column is resized\n                 * <pre>\n                 *      gridApi.colResizable.on.columnSizeChanged(scope,function(colDef, deltaChange){})\n                 * </pre>\n                 * @param {object} colDef the column that was resized\n                 * @param {integer} delta of the column size change\n                 */\n                colResizable: {\n                  columnSizeChanged: function (colDef, deltaChange) {\n                  }\n                }\n              }\n            };\n            grid.api.registerEventsFromObject(publicApi.events);\n        },\n        \n        fireColumnSizeChanged: function (grid, colDef, deltaChange) {\n          $timeout(function () {\n            grid.api.colResizable.raise.columnSizeChanged(colDef, deltaChange);\n          });\n        },\n        \n        // get either this column, or the column next to this column, to resize,\n        // returns the column we're going to resize\n        findTargetCol: function(col, position, rtlMultiplier){\n          var renderContainer = col.getRenderContainer();\n\n          if (position === 'left') {\n            // Get the column to the left of this one\n            var colIndex = renderContainer.visibleColumnCache.indexOf(col);          \n            return renderContainer.visibleColumnCache[colIndex - 1 * rtlMultiplier];\n          } else {\n            return col;\n          }\n        }\n        \n      };\n\n      return service;\n\n    }]);\n\n\n  /**\n   * @ngdoc directive\n   * @name ui.grid.resizeColumns.directive:uiGridResizeColumns\n   * @element div\n   * @restrict A\n   * @description\n   * Enables resizing for all columns on the grid. If, for some reason, you want to use the ui-grid-resize-columns directive, but not allow column resizing, you can explicitly set the\n   * option to false. This prevents resizing for the entire grid, regardless of individual columnDef options.\n   *\n   * @example\n   <doc:example module=\"app\">\n   <doc:source>\n   <script>\n   var app = angular.module('app', ['ui.grid', 'ui.grid.resizeColumns']);\n\n   app.controller('MainCtrl', ['$scope', function ($scope) {\n          $scope.gridOpts = {\n            data: [\n              { \"name\": \"Ethel Price\", \"gender\": \"female\", \"company\": \"Enersol\" },\n              { \"name\": \"Claudine Neal\", \"gender\": \"female\", \"company\": \"Sealoud\" },\n              { \"name\": \"Beryl Rice\", \"gender\": \"female\", \"company\": \"Velity\" },\n              { \"name\": \"Wilder Gonzales\", \"gender\": \"male\", \"company\": \"Geekko\" }\n            ]\n          };\n        }]);\n   </script>\n\n   <div ng-controller=\"MainCtrl\">\n   <div class=\"testGrid\" ui-grid=\"gridOpts\" ui-grid-resize-columns ></div>\n   </div>\n   </doc:source>\n   <doc:scenario>\n\n   </doc:scenario>\n   </doc:example>\n   */\n  module.directive('uiGridResizeColumns', ['gridUtil', 'uiGridResizeColumnsService', function (gridUtil, uiGridResizeColumnsService) {\n    return {\n      replace: true,\n      priority: 0,\n      require: '^uiGrid',\n      scope: false,\n      compile: function () {\n        return {\n          pre: function ($scope, $elm, $attrs, uiGridCtrl) {            \n            uiGridResizeColumnsService.defaultGridOptions(uiGridCtrl.grid.options);\n            uiGridCtrl.grid.registerColumnBuilder( uiGridResizeColumnsService.colResizerColumnBuilder);\n            uiGridResizeColumnsService.registerPublicApi(uiGridCtrl.grid);\n          },\n          post: function ($scope, $elm, $attrs, uiGridCtrl) {\n          }\n        };\n      }\n    };\n  }]);\n\n  // Extend the uiGridHeaderCell directive\n  module.directive('uiGridHeaderCell', ['gridUtil', '$templateCache', '$compile', '$q', 'uiGridResizeColumnsService', 'uiGridConstants', '$timeout', function (gridUtil, $templateCache, $compile, $q, uiGridResizeColumnsService, uiGridConstants, $timeout) {\n    return {\n      // Run after the original uiGridHeaderCell\n      priority: -10,\n      require: '^uiGrid',\n      // scope: false,\n      compile: function() {\n        return {\n          post: function ($scope, $elm, $attrs, uiGridCtrl) {\n            var grid = uiGridCtrl.grid;\n\n            if (grid.options.enableColumnResizing) {\n              var columnResizerElm = $templateCache.get('ui-grid/columnResizer');\n    \n              var rtlMultiplier = 1;\n              //when in RTL mode reverse the direction using the rtlMultiplier and change the position to left\n              if (grid.isRTL()) {\n                $scope.position = 'left';\n                rtlMultiplier = -1;\n              }\n\n              var displayResizers = function(){\n                \n                // remove any existing resizers.  \n                var resizers = $elm[0].getElementsByClassName('ui-grid-column-resizer');\n                for ( var i = 0; i < resizers.length; i++ ){\n                  angular.element(resizers[i]).remove();\n                } \n                \n                // get the target column for the left resizer\n                var otherCol = uiGridResizeColumnsService.findTargetCol($scope.col, 'left', rtlMultiplier);\n                var renderContainer = $scope.col.getRenderContainer();\n              \n                // Don't append the left resizer if this is the first column or the column to the left of this one has resizing disabled\n                if (otherCol && renderContainer.visibleColumnCache.indexOf($scope.col) !== 0 && otherCol.colDef.enableColumnResizing !== false) {\n                  var resizerLeft = angular.element(columnResizerElm).clone();\n                  resizerLeft.attr('position', 'left');\n\n                  $elm.prepend(resizerLeft);\n                  $compile(resizerLeft)($scope);\n                }\n                \n                // Don't append the right resizer if this column has resizing disabled\n                if ($scope.col.colDef.enableColumnResizing !== false) {\n                  var resizerRight = angular.element(columnResizerElm).clone();\n                  resizerRight.attr('position', 'right');\n\n                  $elm.append(resizerRight);\n                  $compile(resizerRight)($scope);\n                }\n              };\n\n              displayResizers();\n              \n              var waitDisplay = function(){\n                $timeout(displayResizers);\n              };\n              \n              var dataChangeDereg = grid.registerDataChangeCallback( waitDisplay, [uiGridConstants.dataChange.COLUMN] );\n              \n              $scope.$on( '$destroy', dataChangeDereg );\n            }\n          }\n        };\n      }\n    };\n  }]);\n\n\n  \n  /**\n   * @ngdoc directive\n   * @name ui.grid.resizeColumns.directive:uiGridColumnResizer\n   * @element div\n   * @restrict A\n   *\n   * @description\n   * Draggable handle that controls column resizing.\n   * \n   * @example\n   <doc:example module=\"app\">\n     <doc:source>\n       <script>\n        var app = angular.module('app', ['ui.grid', 'ui.grid.resizeColumns']);\n\n        app.controller('MainCtrl', ['$scope', function ($scope) {\n          $scope.gridOpts = {\n            enableColumnResizing: true,\n            data: [\n              { \"name\": \"Ethel Price\", \"gender\": \"female\", \"company\": \"Enersol\" },\n              { \"name\": \"Claudine Neal\", \"gender\": \"female\", \"company\": \"Sealoud\" },\n              { \"name\": \"Beryl Rice\", \"gender\": \"female\", \"company\": \"Velity\" },\n              { \"name\": \"Wilder Gonzales\", \"gender\": \"male\", \"company\": \"Geekko\" }\n            ]\n          };\n        }]);\n       </script>\n\n       <div ng-controller=\"MainCtrl\">\n        <div class=\"testGrid\" ui-grid=\"gridOpts\"></div>\n       </div>\n     </doc:source>\n     <doc:scenario>\n      // TODO: e2e specs?\n        // TODO: Obey minWidth and maxWIdth;\n\n      // TODO: post-resize a horizontal scroll event should be fired\n     </doc:scenario>\n   </doc:example>\n   */  \n  module.directive('uiGridColumnResizer', ['$document', 'gridUtil', 'uiGridConstants', 'uiGridResizeColumnsService', function ($document, gridUtil, uiGridConstants, uiGridResizeColumnsService) {\n    var resizeOverlay = angular.element('<div class=\"ui-grid-resize-overlay\"></div>');\n\n    var downEvent, upEvent, moveEvent;\n\n    if (gridUtil.isTouchEnabled()) {\n      downEvent = 'touchstart';\n      upEvent = 'touchend';\n      moveEvent = 'touchmove';\n    }\n    else {\n      downEvent = 'mousedown';\n      upEvent = 'mouseup';\n      moveEvent = 'mousemove';\n    }\n\n    var resizer = {\n      priority: 0,\n      scope: {\n        col: '=',\n        position: '@',\n        renderIndex: '='\n      },\n      require: '?^uiGrid',\n      link: function ($scope, $elm, $attrs, uiGridCtrl) {\n        var startX = 0,\n            x = 0,\n            gridLeft = 0,\n            rtlMultiplier = 1;\n\n        //when in RTL mode reverse the direction using the rtlMultiplier and change the position to left\n        if (uiGridCtrl.grid.isRTL()) {\n          $scope.position = 'left';\n          rtlMultiplier = -1;\n        }\n\n        if ($scope.position === 'left') {\n          $elm.addClass('left');\n        }\n        else if ($scope.position === 'right') {\n          $elm.addClass('right');\n        }\n\n        // Resize all the other columns around col\n        function resizeAroundColumn(col) {\n          // Get this column's render container\n          var renderContainer = col.getRenderContainer();\n\n          renderContainer.visibleColumnCache.forEach(function (column) {\n            // Skip the column we just resized\n            if (column === col) { return; }\n            \n            var colDef = column.colDef;\n            if (!colDef.width || (angular.isString(colDef.width) && (colDef.width.indexOf('*') !== -1 || colDef.width.indexOf('%') !== -1))) {\n              column.width = column.drawnWidth;\n            }\n          });\n        }\n\n        // Build the columns then refresh the grid canvas\n        //   takes an argument representing the diff along the X-axis that the resize had\n        function buildColumnsAndRefresh(xDiff) {\n          // Build the columns\n          uiGridCtrl.grid.buildColumns()\n            .then(function() {\n              // Then refresh the grid canvas, rebuilding the styles so that the scrollbar updates its size\n              uiGridCtrl.grid.refreshCanvas(true).then( function() {\n                uiGridCtrl.grid.refresh();\n              });\n            });\n        }\n\n        // Check that the requested width isn't wider than the maxWidth, or narrower than the minWidth\n        // Returns the new recommended with, after constraints applied\n        function constrainWidth(col, width){\n          var newWidth = width;\n\n          // If the new width would be less than the column's allowably minimum width, don't allow it\n          if (col.colDef.minWidth && newWidth < col.colDef.minWidth) {\n            newWidth = col.colDef.minWidth;\n          }\n          else if (col.colDef.maxWidth && newWidth > col.colDef.maxWidth) {\n            newWidth = col.colDef.maxWidth;\n          }\n          \n          return newWidth;\n        }\n        \n        \n        function mousemove(event, args) {\n          if (event.originalEvent) { event = event.originalEvent; }\n          event.preventDefault();\n\n          x = (event.targetTouches ? event.targetTouches[0] : event).clientX - gridLeft;\n\n          if (x < 0) { x = 0; }\n          else if (x > uiGridCtrl.grid.gridWidth) { x = uiGridCtrl.grid.gridWidth; }\n\n          var col = uiGridResizeColumnsService.findTargetCol($scope.col, $scope.position, rtlMultiplier);\n\n          // Don't resize if it's disabled on this column\n          if (col.colDef.enableColumnResizing === false) {\n            return;\n          }\n\n          if (!uiGridCtrl.grid.element.hasClass('column-resizing')) {\n            uiGridCtrl.grid.element.addClass('column-resizing');\n          }\n\n          // Get the diff along the X axis\n          var xDiff = x - startX;\n\n          // Get the width that this mouse would give the column\n          var newWidth = parseInt(col.drawnWidth + xDiff * rtlMultiplier, 10);\n\n          // check we're not outside the allowable bounds for this column\n          x = x + ( constrainWidth(col, newWidth) - newWidth ) * rtlMultiplier;\n          \n          resizeOverlay.css({ left: x + 'px' });\n\n          uiGridCtrl.fireEvent(uiGridConstants.events.ITEM_DRAGGING);\n        }\n        \n\n        function mouseup(event, args) {\n          if (event.originalEvent) { event = event.originalEvent; }\n          event.preventDefault();\n\n          uiGridCtrl.grid.element.removeClass('column-resizing');\n\n          resizeOverlay.remove();\n\n          // Resize the column\n          x = (event.changedTouches ? event.changedTouches[0] : event).clientX - gridLeft;\n          var xDiff = x - startX;\n\n          if (xDiff === 0) {\n            $document.off(upEvent, mouseup);\n            $document.off(moveEvent, mousemove);\n            return;\n          }\n\n          var col = uiGridResizeColumnsService.findTargetCol($scope.col, $scope.position, rtlMultiplier);\n\n          // Don't resize if it's disabled on this column\n          if (col.colDef.enableColumnResizing === false) {\n            return;\n          }\n\n          // Get the new width\n          var newWidth = parseInt(col.drawnWidth + xDiff * rtlMultiplier, 10);\n\n          // check we're not outside the allowable bounds for this column\n          col.width = constrainWidth(col, newWidth);\n\n          // All other columns because fixed to their drawn width, if they aren't already\n          resizeAroundColumn(col);\n\n          buildColumnsAndRefresh(xDiff);\n\n          uiGridResizeColumnsService.fireColumnSizeChanged(uiGridCtrl.grid, col.colDef, xDiff);\n\n          $document.off(upEvent, mouseup);\n          $document.off(moveEvent, mousemove);\n        }\n\n\n        $elm.on(downEvent, function(event, args) {\n          if (event.originalEvent) { event = event.originalEvent; }\n          event.stopPropagation();\n\n          // Get the left offset of the grid\n          // gridLeft = uiGridCtrl.grid.element[0].offsetLeft;\n          gridLeft = uiGridCtrl.grid.element[0].getBoundingClientRect().left;\n\n          // Get the starting X position, which is the X coordinate of the click minus the grid's offset\n          startX = (event.targetTouches ? event.targetTouches[0] : event).clientX - gridLeft;\n\n          // Append the resizer overlay\n          uiGridCtrl.grid.element.append(resizeOverlay);\n\n          // Place the resizer overlay at the start position\n          resizeOverlay.css({ left: startX });\n\n          // Add handlers for mouse move and up events\n          $document.on(upEvent, mouseup);\n          $document.on(moveEvent, mousemove);\n        });\n\n\n        // On doubleclick, resize to fit all rendered cells\n        $elm.on('dblclick', function(event, args) {\n          event.stopPropagation();\n\n          var col = uiGridResizeColumnsService.findTargetCol($scope.col, $scope.position, rtlMultiplier);\n\n          // Don't resize if it's disabled on this column\n          if (col.colDef.enableColumnResizing === false) {\n            return;\n          }\n\n          // Go through the rendered rows and find out the max size for the data in this column\n          var maxWidth = 0;\n          var xDiff = 0;\n\n          // Get the parent render container element\n          var renderContainerElm = gridUtil.closestElm($elm, '.ui-grid-render-container');\n\n          // Get the cell contents so we measure correctly. For the header cell we have to account for the sort icon and the menu buttons, if present\n          var cells = renderContainerElm.querySelectorAll('.' + uiGridConstants.COL_CLASS_PREFIX + col.uid + ' .ui-grid-cell-contents');\n          Array.prototype.forEach.call(cells, function (cell) {\n              // Get the cell width\n              // gridUtil.logDebug('width', gridUtil.elementWidth(cell));\n\n              // Account for the menu button if it exists\n              var menuButton;\n              if (angular.element(cell).parent().hasClass('ui-grid-header-cell')) {\n                menuButton = angular.element(cell).parent()[0].querySelectorAll('.ui-grid-column-menu-button');\n              }\n\n              gridUtil.fakeElement(cell, {}, function(newElm) {\n                // Make the element float since it's a div and can expand to fill its container\n                var e = angular.element(newElm);\n                e.attr('style', 'float: left');\n\n                var width = gridUtil.elementWidth(e);\n\n                if (menuButton) {\n                  var menuButtonWidth = gridUtil.elementWidth(menuButton);\n                  width = width + menuButtonWidth;\n                }\n\n                if (width > maxWidth) {\n                  maxWidth = width;\n                  xDiff = maxWidth - width;\n                }\n              });\n            });\n\n          // check we're not outside the allowable bounds for this column\n          col.width = constrainWidth(col, maxWidth);\n          \n          // All other columns because fixed to their drawn width, if they aren't already\n          resizeAroundColumn(col);\n\n          buildColumnsAndRefresh(xDiff);\n          \n          uiGridResizeColumnsService.fireColumnSizeChanged(uiGridCtrl.grid, col.colDef, xDiff);\n        });\n\n        $elm.on('$destroy', function() {\n          $elm.off(downEvent);\n          $elm.off('dblclick');\n          $document.off(moveEvent, mousemove);\n          $document.off(upEvent, mouseup);\n        });\n      }\n    };\n\n    return resizer;\n  }]);\n\n})();\n(function () {\n  'use strict';\n\n  /**\n   * @ngdoc overview\n   * @name ui.grid.rowEdit\n   * @description\n   *\n   *  # ui.grid.rowEdit\n   * This module extends the edit feature to provide tracking and saving of rows\n   * of data.  The tutorial provides more information on how this feature is best\n   * used {@link tutorial/205_row_editable here}.\n   * <br/>\n   * This feature depends on usage of the ui-grid-edit feature, and also benefits\n   * from use of ui-grid-cellNav to provide the full spreadsheet-like editing \n   * experience\n   * \n   */\n\n  var module = angular.module('ui.grid.rowEdit', ['ui.grid', 'ui.grid.edit', 'ui.grid.cellNav']);\n\n  /**\n   *  @ngdoc object\n   *  @name ui.grid.rowEdit.constant:uiGridRowEditConstants\n   *\n   *  @description constants available in row edit module\n   */\n  module.constant('uiGridRowEditConstants', {\n  });\n\n  /**\n   *  @ngdoc service\n   *  @name ui.grid.rowEdit.service:uiGridRowEditService\n   *\n   *  @description Services for row editing features\n   */\n  module.service('uiGridRowEditService', ['$interval', '$q', 'uiGridConstants', 'uiGridRowEditConstants', 'gridUtil', \n    function ($interval, $q, uiGridConstants, uiGridRowEditConstants, gridUtil) {\n\n      var service = {\n\n        initializeGrid: function (scope, grid) {\n          /**\n           *  @ngdoc object\n           *  @name ui.grid.rowEdit.api:PublicApi\n           *\n           *  @description Public Api for rowEdit feature\n           */\n          \n          grid.rowEdit = {};\n          \n          var publicApi = {\n            events: {\n              rowEdit: {\n                /**\n                 * @ngdoc event\n                 * @eventOf ui.grid.rowEdit.api:PublicApi\n                 * @name saveRow\n                 * @description raised when a row is ready for saving.  Once your\n                 * row has saved you may need to use angular.extend to update the\n                 * data entity with any changed data from your save (for example, \n                 * lock version information if you're using optimistic locking,\n                 * or last update time/user information).\n                 * \n                 * Your method should call setSavePromise somewhere in the body before\n                 * returning control.  The feature will then wait, with the gridRow greyed out \n                 * whilst this promise is being resolved.\n                 * \n                 * <pre>\n                 *      gridApi.rowEdit.on.saveRow(scope,function(rowEntity){})\n                 * </pre>\n                 * and somewhere within the event handler:\n                 * <pre>\n                 *      gridApi.rowEdit.setSavePromise( grid, rowEntity, savePromise)\n                 * </pre>\n                 * @param {object} rowEntity the options.data element that was edited\n                 * @returns {promise} Your saveRow method should return a promise, the\n                 * promise should either be resolved (implying successful save), or \n                 * rejected (implying an error).\n                 */\n                saveRow: function (rowEntity) {\n                }\n              }\n            },\n            methods: {\n              rowEdit: {\n                /**\n                 * @ngdoc method\n                 * @methodOf ui.grid.rowEdit.api:PublicApi\n                 * @name setSavePromise\n                 * @description Sets the promise associated with the row save, mandatory that\n                 * the saveRow event handler calls this method somewhere before returning.\n                 * <pre>\n                 *      gridApi.rowEdit.setSavePromise(grid, rowEntity)\n                 * </pre>\n                 * @param {object} rowEntity a data row from the grid for which a save has\n                 * been initiated\n                 * @param {promise} savePromise the promise that will be resolved when the\n                 * save is successful, or rejected if the save fails\n                 * \n                 */\n                setSavePromise: function ( rowEntity, savePromise) {\n                  service.setSavePromise(grid, rowEntity, savePromise);\n                },\n                /**\n                 * @ngdoc method\n                 * @methodOf ui.grid.rowEdit.api:PublicApi\n                 * @name getDirtyRows\n                 * @description Returns all currently dirty rows\n                 * <pre>\n                 *      gridApi.rowEdit.getDirtyRows(grid)\n                 * </pre>\n                 * @returns {array} An array of gridRows that are currently dirty\n                 * \n                 */\n                getDirtyRows: function () {\n                  return grid.rowEdit.dirtyRows ? grid.rowEdit.dirtyRows : [];\n                },\n                /**\n                 * @ngdoc method\n                 * @methodOf ui.grid.rowEdit.api:PublicApi\n                 * @name getErrorRows\n                 * @description Returns all currently errored rows\n                 * <pre>\n                 *      gridApi.rowEdit.getErrorRows(grid)\n                 * </pre>\n                 * @returns {array} An array of gridRows that are currently in error\n                 * \n                 */\n                getErrorRows: function () {\n                  return grid.rowEdit.errorRows ? grid.rowEdit.errorRows : [];\n                },\n                /**\n                 * @ngdoc method\n                 * @methodOf ui.grid.rowEdit.api:PublicApi\n                 * @name flushDirtyRows\n                 * @description Triggers a save event for all currently dirty rows, could\n                 * be used where user presses a save button or navigates away from the page\n                 * <pre>\n                 *      gridApi.rowEdit.flushDirtyRows(grid)\n                 * </pre>\n                 * @returns {promise} a promise that represents the aggregate of all\n                 * of the individual save promises - i.e. it will be resolved when all\n                 * the individual save promises have been resolved.\n                 * \n                 */\n                flushDirtyRows: function () {\n                  return service.flushDirtyRows(grid);\n                },\n                \n                /**\n                 * @ngdoc method\n                 * @methodOf ui.grid.rowEdit.api:PublicApi\n                 * @name setRowsDirty\n                 * @description Sets each of the rows passed in dataRows\n                 * to be dirty.  note that if you have only just inserted the\n                 * rows into your data you will need to wait for a $digest cycle\n                 * before the gridRows are present - so often you would wrap this\n                 * call in a $interval or $timeout\n                 * <pre>\n                 *      $interval( function() {\n                 *        gridApi.rowEdit.setRowsDirty(grid, myDataRows);\n                 *      }, 0, 1);\n                 * </pre>\n                 * @param {array} dataRows the data entities for which the gridRows\n                 * should be set dirty.  \n                 * \n                 */\n                setRowsDirty: function ( dataRows) {\n                  service.setRowsDirty(grid, dataRows);\n                }\n              }\n            }\n          };\n\n          grid.api.registerEventsFromObject(publicApi.events);\n          grid.api.registerMethodsFromObject(publicApi.methods);\n          \n          grid.api.core.on.renderingComplete( scope, function ( gridApi ) {\n            grid.api.edit.on.afterCellEdit( scope, service.endEditCell );\n            grid.api.edit.on.beginCellEdit( scope, service.beginEditCell );\n            grid.api.edit.on.cancelCellEdit( scope, service.cancelEditCell );\n            \n            if ( grid.api.cellNav ) {\n              grid.api.cellNav.on.navigate( scope, service.navigate );\n            }              \n          });\n\n        },\n\n        defaultGridOptions: function (gridOptions) {\n\n          /**\n           *  @ngdoc object\n           *  @name ui.grid.rowEdit.api:GridOptions\n           *\n           *  @description Options for configuring the rowEdit feature, these are available to be  \n           *  set using the ui-grid {@link ui.grid.class:GridOptions gridOptions}\n           */\n\n        },\n\n\n        /**\n         * @ngdoc method\n         * @methodOf ui.grid.rowEdit.service:uiGridRowEditService\n         * @name saveRow\n         * @description  Returns a function that saves the specified row from the grid,\n         * and returns a promise\n         * @param {object} grid the grid for which dirty rows should be flushed\n         * @param {GridRow} gridRow the row that should be saved\n         * @returns {function} the saveRow function returns a function.  That function\n         * in turn, when called, returns a promise relating to the save callback\n         */\n        saveRow: function ( grid, gridRow ) {\n          var self = this;\n\n          return function() {\n            gridRow.isSaving = true;\n\n            var promise = grid.api.rowEdit.raise.saveRow( gridRow.entity );\n            \n            if ( gridRow.rowEditSavePromise ){\n              gridRow.rowEditSavePromise.then( self.processSuccessPromise( grid, gridRow ), self.processErrorPromise( grid, gridRow ));\n            } else {\n              gridUtil.logError( 'A promise was not returned when saveRow event was raised, either nobody is listening to event, or event handler did not return a promise' );\n            }\n            return promise;\n          };\n        },\n        \n\n        /**\n         * @ngdoc method\n         * @methodOf  ui.grid.rowEdit.service:uiGridRowEditService\n         * @name setSavePromise\n         * @description Sets the promise associated with the row save, mandatory that\n         * the saveRow event handler calls this method somewhere before returning.\n         * <pre>\n         *      gridApi.rowEdit.setSavePromise(grid, rowEntity)\n         * </pre>\n         * @param {object} grid the grid for which dirty rows should be returned\n         * @param {object} rowEntity a data row from the grid for which a save has\n         * been initiated\n         * @param {promise} savePromise the promise that will be resolved when the\n         * save is successful, or rejected if the save fails\n         * \n         */\n        setSavePromise: function (grid, rowEntity, savePromise) {\n          var gridRow = grid.getRow( rowEntity );\n          gridRow.rowEditSavePromise = savePromise;\n        },\n\n\n        /**\n         * @ngdoc method\n         * @methodOf ui.grid.rowEdit.service:uiGridRowEditService\n         * @name processSuccessPromise\n         * @description  Returns a function that processes the successful\n         * resolution of a save promise  \n         * @param {object} grid the grid for which the promise should be processed\n         * @param {GridRow} gridRow the row that has been saved\n         * @returns {function} the success handling function\n         */\n        processSuccessPromise: function ( grid, gridRow ) {\n          var self = this;\n          \n          return function() {\n            delete gridRow.isSaving;\n            delete gridRow.isDirty;\n            delete gridRow.isError;\n            delete gridRow.rowEditSaveTimer;\n            self.removeRow( grid.rowEdit.errorRows, gridRow );\n            self.removeRow( grid.rowEdit.dirtyRows, gridRow );\n          };\n        },\n        \n\n        /**\n         * @ngdoc method\n         * @methodOf ui.grid.rowEdit.service:uiGridRowEditService\n         * @name processErrorPromise\n         * @description  Returns a function that processes the failed\n         * resolution of a save promise  \n         * @param {object} grid the grid for which the promise should be processed\n         * @param {GridRow} gridRow the row that is now in error\n         * @returns {function} the error handling function\n         */\n        processErrorPromise: function ( grid, gridRow ) {\n          return function() {\n            delete gridRow.isSaving;\n            delete gridRow.rowEditSaveTimer;\n\n            gridRow.isError = true;\n            \n            if (!grid.rowEdit.errorRows){\n              grid.rowEdit.errorRows = [];\n            }\n            if (!service.isRowPresent( grid.rowEdit.errorRows, gridRow ) ){\n              grid.rowEdit.errorRows.push( gridRow );\n            }\n          };\n        },\n        \n        \n        /**\n         * @ngdoc method\n         * @methodOf ui.grid.rowEdit.service:uiGridRowEditService\n         * @name removeRow\n         * @description  Removes a row from a cache of rows - either\n         * grid.rowEdit.errorRows or grid.rowEdit.dirtyRows.  If the row\n         * is not present silently does nothing. \n         * @param {array} rowArray the array from which to remove the row\n         * @param {GridRow} gridRow the row that should be removed\n         */\n        removeRow: function( rowArray, removeGridRow ){\n          angular.forEach( rowArray, function( gridRow, index ){\n            if ( gridRow.uid === removeGridRow.uid ){\n              rowArray.splice( index, 1);\n            }\n          });\n        },\n        \n        \n        /**\n         * @ngdoc method\n         * @methodOf ui.grid.rowEdit.service:uiGridRowEditService\n         * @name isRowPresent\n         * @description  Checks whether a row is already present\n         * in the given array \n         * @param {array} rowArray the array in which to look for the row\n         * @param {GridRow} gridRow the row that should be looked for\n         */\n        isRowPresent: function( rowArray, removeGridRow ){\n          var present = false;\n          angular.forEach( rowArray, function( gridRow, index ){\n            if ( gridRow.uid === removeGridRow.uid ){\n              present = true;\n            }\n          });\n          return present;\n        },\n\n        \n        /**\n         * @ngdoc method\n         * @methodOf ui.grid.rowEdit.service:uiGridRowEditService\n         * @name flushDirtyRows\n         * @description Triggers a save event for all currently dirty rows, could\n         * be used where user presses a save button or navigates away from the page\n         * <pre>\n         *      gridApi.rowEdit.flushDirtyRows(grid)\n         * </pre>\n         * @param {object} grid the grid for which dirty rows should be flushed\n         * @returns {promise} a promise that represents the aggregate of all\n         * of the individual save promises - i.e. it will be resolved when all\n         * the individual save promises have been resolved.\n         * \n         */\n        flushDirtyRows: function(grid){\n          var promises = [];\n          angular.forEach(grid.rowEdit.dirtyRows, function( gridRow ){\n            service.saveRow( grid, gridRow )();\n            promises.push( gridRow.rowEditSavePromise );\n          });\n          \n          return $q.all( promises );\n        },\n        \n        \n        /**\n         * @ngdoc method\n         * @methodOf ui.grid.rowEdit.service:uiGridRowEditService\n         * @name endEditCell\n         * @description Receives an afterCellEdit event from the edit function,\n         * and sets flags as appropriate.  Only the rowEntity parameter\n         * is processed, although other params are available.  Grid\n         * is automatically provided by the gridApi. \n         * @param {object} rowEntity the data entity for which the cell\n         * was edited\n         */        \n        endEditCell: function( rowEntity, colDef, newValue, previousValue ){\n          var grid = this.grid;\n          var gridRow = grid.getRow( rowEntity );\n          if ( !gridRow ){ gridUtil.logError( 'Unable to find rowEntity in grid data, dirty flag cannot be set' ); return; }\n\n          if ( newValue !== previousValue || gridRow.isDirty ){\n            if ( !grid.rowEdit.dirtyRows ){\n              grid.rowEdit.dirtyRows = [];\n            }\n            \n            if ( !gridRow.isDirty ){\n              gridRow.isDirty = true;\n              grid.rowEdit.dirtyRows.push( gridRow );\n            }\n            \n            delete gridRow.isError;\n            \n            service.considerSetTimer( grid, gridRow );\n          }\n        },\n        \n        \n        /**\n         * @ngdoc method\n         * @methodOf ui.grid.rowEdit.service:uiGridRowEditService\n         * @name beginEditCell\n         * @description Receives a beginCellEdit event from the edit function,\n         * and cancels any rowEditSaveTimers if present, as the user is still editing\n         * this row.  Only the rowEntity parameter\n         * is processed, although other params are available.  Grid\n         * is automatically provided by the gridApi. \n         * @param {object} rowEntity the data entity for which the cell\n         * editing has commenced\n         */\n        beginEditCell: function( rowEntity, colDef ){\n          var grid = this.grid;\n          var gridRow = grid.getRow( rowEntity );\n          if ( !gridRow ){ gridUtil.logError( 'Unable to find rowEntity in grid data, timer cannot be cancelled' ); return; }\n          \n          service.cancelTimer( grid, gridRow );\n        },\n\n\n        /**\n         * @ngdoc method\n         * @methodOf ui.grid.rowEdit.service:uiGridRowEditService\n         * @name cancelEditCell\n         * @description Receives a cancelCellEdit event from the edit function,\n         * and if the row was already dirty, restarts the save timer.  If the row\n         * was not already dirty, then it's not dirty now either and does nothing.\n         * \n         * Only the rowEntity parameter\n         * is processed, although other params are available.  Grid\n         * is automatically provided by the gridApi.\n         *  \n         * @param {object} rowEntity the data entity for which the cell\n         * editing was cancelled\n         */        \n        cancelEditCell: function( rowEntity, colDef ){\n          var grid = this.grid;\n          var gridRow = grid.getRow( rowEntity );\n          if ( !gridRow ){ gridUtil.logError( 'Unable to find rowEntity in grid data, timer cannot be set' ); return; }\n          \n          service.considerSetTimer( grid, gridRow );\n        },\n        \n        \n        /**\n         * @ngdoc method\n         * @methodOf ui.grid.rowEdit.service:uiGridRowEditService\n         * @name navigate\n         * @description cellNav tells us that the selected cell has changed.  If\n         * the new row had a timer running, then stop it similar to in a beginCellEdit\n         * call.  If the old row is dirty and not the same as the new row, then \n         * start a timer on it.\n         * @param {object} newRowCol the row and column that were selected\n         * @param {object} oldRowCol the row and column that was left\n         * \n         */\n        navigate: function( newRowCol, oldRowCol ){\n          var grid = this.grid;\n          if ( newRowCol.row.rowEditSaveTimer ){\n            service.cancelTimer( grid, newRowCol.row );\n          }\n\n          if ( oldRowCol && oldRowCol.row && oldRowCol.row !== newRowCol.row ){\n            service.considerSetTimer( grid, oldRowCol.row );\n          }\n        },\n        \n        \n        /**\n         * @ngdoc property\n         * @propertyOf ui.grid.rowEdit.api:GridOptions\n         * @name rowEditWaitInterval\n         * @description How long the grid should wait for another change on this row\n         * before triggering a save (in milliseconds).  If set to -1, then saves are \n         * never triggered by timer (implying that the user will call flushDirtyRows() \n         * manually)\n         * \n         * @example\n         * Setting the wait interval to 4 seconds\n         * <pre>\n         *   $scope.gridOptions = { rowEditWaitInterval: 4000 }\n         * </pre>\n         * \n         */\n        /**\n         * @ngdoc method\n         * @methodOf ui.grid.rowEdit.service:uiGridRowEditService\n         * @name considerSetTimer\n         * @description Consider setting a timer on this row (if it is dirty).  if there is a timer running \n         * on the row and the row isn't currently saving, cancel it, using cancelTimer, then if the row is \n         * dirty and not currently saving then set a new timer\n         * @param {object} grid the grid for which we are processing\n         * @param {GridRow} gridRow the row for which the timer should be adjusted\n         * \n         */\n        considerSetTimer: function( grid, gridRow ){\n          service.cancelTimer( grid, gridRow );\n          \n          if ( gridRow.isDirty && !gridRow.isSaving ){\n            if ( grid.options.rowEditWaitInterval !== -1 ){\n              var waitTime = grid.options.rowEditWaitInterval ? grid.options.rowEditWaitInterval : 2000;\n              gridRow.rowEditSaveTimer = $interval( service.saveRow( grid, gridRow ), waitTime, 1);\n            }\n          }\n        },\n        \n\n        /**\n         * @ngdoc method\n         * @methodOf ui.grid.rowEdit.service:uiGridRowEditService\n         * @name cancelTimer\n         * @description cancel the $interval for any timer running on this row\n         * then delete the timer itself\n         * @param {object} grid the grid for which we are processing\n         * @param {GridRow} gridRow the row for which the timer should be adjusted\n         * \n         */\n        cancelTimer: function( grid, gridRow ){\n          if ( gridRow.rowEditSaveTimer && !gridRow.isSaving ){\n            $interval.cancel(gridRow.rowEditSaveTimer);\n            delete gridRow.rowEditSaveTimer;\n          }\n        },\n\n\n        /**\n         * @ngdoc method\n         * @methodOf ui.grid.rowEdit.service:uiGridRowEditService\n         * @name setRowsDirty\n         * @description Sets each of the rows passed in dataRows\n         * to be dirty.  note that if you have only just inserted the\n         * rows into your data you will need to wait for a $digest cycle\n         * before the gridRows are present - so often you would wrap this\n         * call in a $interval or $timeout\n         * <pre>\n         *      $interval( function() {\n         *        gridApi.rowEdit.setRowsDirty( myDataRows);\n         *      }, 0, 1);\n         * </pre>\n         * @param {object} grid the grid for which rows should be set dirty\n         * @param {array} dataRows the data entities for which the gridRows\n         * should be set dirty.  \n         * \n         */\n        setRowsDirty: function( grid, myDataRows ) {\n          var gridRow;\n          myDataRows.forEach( function( value, index ){\n            gridRow = grid.getRow( value );\n            if ( gridRow ){\n              if ( !grid.rowEdit.dirtyRows ){\n                grid.rowEdit.dirtyRows = [];\n              }\n              \n              if ( !gridRow.isDirty ){\n                gridRow.isDirty = true;\n                grid.rowEdit.dirtyRows.push( gridRow );\n              }\n              \n              delete gridRow.isError;\n              \n              service.considerSetTimer( grid, gridRow );\n            } else {\n              gridUtil.logError( \"requested row not found in rowEdit.setRowsDirty, row was: \" + value );\n            }\n          });\n        }\n        \n        \n      };\n\n      return service;\n\n    }]);\n\n  /**\n   *  @ngdoc directive\n   *  @name ui.grid.rowEdit.directive:uiGridEdit\n   *  @element div\n   *  @restrict A\n   *\n   *  @description Adds row editing features to the ui-grid-edit directive.\n   *\n   */\n  module.directive('uiGridRowEdit', ['gridUtil', 'uiGridRowEditService', 'uiGridEditConstants', \n  function (gridUtil, uiGridRowEditService, uiGridEditConstants) {\n    return {\n      replace: true,\n      priority: 0,\n      require: '^uiGrid',\n      scope: false,\n      compile: function () {\n        return {\n          pre: function ($scope, $elm, $attrs, uiGridCtrl) {\n            uiGridRowEditService.initializeGrid($scope, uiGridCtrl.grid);\n          },\n          post: function ($scope, $elm, $attrs, uiGridCtrl) {            \n          }\n        };\n      }\n    };\n  }]);\n\n\n  /**\n   *  @ngdoc directive\n   *  @name ui.grid.rowEdit.directive:uiGridViewport\n   *  @element div\n   *\n   *  @description Stacks on top of ui.grid.uiGridViewport to alter the attributes used\n   *  for the grid row to allow coloring of saving and error rows\n   */\n  module.directive('uiGridViewport',\n    ['$compile', 'uiGridConstants', 'gridUtil', '$parse',\n      function ($compile, uiGridConstants, gridUtil, $parse) {\n        return {\n          priority: -200, // run after default  directive\n          scope: false,\n          compile: function ($elm, $attrs) {\n            var rowRepeatDiv = angular.element($elm.children().children()[0]);\n            \n            var existingNgClass = rowRepeatDiv.attr(\"ng-class\");\n            var newNgClass = '';\n            if ( existingNgClass ) {\n              newNgClass = existingNgClass.slice(0, -1) + \", 'ui-grid-row-dirty': row.isDirty, 'ui-grid-row-saving': row.isSaving, 'ui-grid-row-error': row.isError}\";\n            } else {\n              newNgClass = \"{'ui-grid-row-dirty': row.isDirty, 'ui-grid-row-saving': row.isSaving, 'ui-grid-row-error': row.isError}\";\n            }\n            rowRepeatDiv.attr(\"ng-class\", newNgClass);\n\n            return {\n              pre: function ($scope, $elm, $attrs, controllers) {\n\n              },\n              post: function ($scope, $elm, $attrs, controllers) {\n              }\n            };\n          }\n        };\n      }]);\n\n})();\n\n(function () {\n  'use strict';\n\n  /**\n   * @ngdoc overview\n   * @name ui.grid.saveState\n   * @description\n   *\n   *  # ui.grid.saveState\n   * This module provides the ability to save the grid state, and restore\n   * it when the user returns to the page.  \n   * \n   * No UI is provided, the caller should provide their own UI/buttons \n   * as appropriate. Usually the navigate events would be used to save\n   * the grid state and restore it.\n   * \n   * <br/>\n   * <br/>\n   *\n   * <div doc-module-components=\"ui.grid.save-state\"></div>\n   */\n\n  var module = angular.module('ui.grid.saveState', ['ui.grid', 'ui.grid.selection', 'ui.grid.cellNav']);\n\n  /**\n   *  @ngdoc object\n   *  @name ui.grid.saveState.constant:uiGridSaveStateConstants\n   *\n   *  @description constants available in save state module\n   */\n\n  module.constant('uiGridSaveStateConstants', {\n    featureName: 'saveState'\n  });\n\n  /**\n   *  @ngdoc service\n   *  @name ui.grid.saveState.service:uiGridSaveStateService\n   *\n   *  @description Services for saveState feature\n   */\n  module.service('uiGridSaveStateService', ['$q', 'uiGridSaveStateConstants', 'gridUtil', '$compile', '$interval', 'uiGridConstants',\n    function ($q, uiGridSaveStateConstants, gridUtil, $compile, $interval, uiGridConstants ) {\n\n      var service = {\n\n        initializeGrid: function (grid) {\n\n          //add feature namespace and any properties to grid for needed state\n          grid.saveState = {};\n          this.defaultGridOptions(grid.options);\n\n          /**\n           *  @ngdoc object\n           *  @name ui.grid.saveState.api:PublicApi\n           *\n           *  @description Public Api for saveState feature\n           */\n          var publicApi = {\n            events: {\n              saveState: {\n              }\n            },\n            methods: {\n              saveState: {\n                /**\n                 * @ngdoc function\n                 * @name save\n                 * @methodOf  ui.grid.saveState.api:PublicApi\n                 * @description Packages the current state of the grid into \n                 * an object, and provides it to the user for saving\n                 * @returns {object} the state as a javascript object that can be saved\n                 */\n                save: function () {\n                  return service.save(grid);\n                },\n                /**\n                 * @ngdoc function\n                 * @name restore\n                 * @methodOf  ui.grid.saveState.api:PublicApi\n                 * @description Restores the provided state into the grid\n                 * @param {scope} $scope a scope that we can broadcast on\n                 * @param {object} state the state that should be restored into the grid\n                 */\n                restore: function ( $scope, state) {\n                  service.restore(grid, $scope, state);\n                }\n              }\n            }\n          };\n\n          grid.api.registerEventsFromObject(publicApi.events);\n\n          grid.api.registerMethodsFromObject(publicApi.methods);\n          \n        },\n\n        defaultGridOptions: function (gridOptions) {\n          //default option to true unless it was explicitly set to false\n          /**\n           * @ngdoc object\n           * @name ui.grid.saveState.api:GridOptions\n           *\n           * @description GridOptions for saveState feature, these are available to be  \n           * set using the ui-grid {@link ui.grid.class:GridOptions gridOptions}\n           */\n          /**\n           * @ngdoc object\n           * @name saveWidths\n           * @propertyOf  ui.grid.saveState.api:GridOptions\n           * @description Save the current column widths.  Note that unless\n           * you've provided the user with some way to resize their columns (say\n           * the resize columns feature), then this makes little sense.\n           * <br/>Defaults to true\n           */\n          gridOptions.saveWidths = gridOptions.saveWidths !== false;\n          /**\n           * @ngdoc object\n           * @name saveOrder\n           * @propertyOf  ui.grid.saveState.api:GridOptions\n           * @description Save the current column order.  Note that unless\n           * you've provided the user with some way to reorder their columns (for\n           * example the move columns feature), this makes little sense.\n           * <br/>Defaults to true\n           */\n          gridOptions.saveOrder = gridOptions.saveOrder !== false;\n          /**\n           * @ngdoc object\n           * @name saveScroll\n           * @propertyOf  ui.grid.saveState.api:GridOptions\n           * @description Save the current scroll position.  Note that this\n           * is saved as the percentage of the grid scrolled - so if your\n           * user returns to a grid with a significantly different number of \n           * rows (perhaps some data has been deleted) then the scroll won't \n           * actually show the same rows as before.  If you want to scroll to\n           * a specific row then you should instead use the saveFocus option, which\n           * is the default.\n           * \n           * Note that this element will only be saved if the cellNav feature is\n           * enabled\n           * <br/>Defaults to false\n           */\n          gridOptions.saveScroll = gridOptions.saveScroll === true;\n          /**\n           * @ngdoc object\n           * @name saveFocus\n           * @propertyOf  ui.grid.saveState.api:GridOptions\n           * @description Save the current focused cell.  On returning\n           * to this focused cell we'll also scroll.  This option is\n           * preferred to the saveScroll option, so is set to true by\n           * default.  If saveScroll is set to true then this option will \n           * be disabled.  \n           * \n           * By default this option saves the current row number and column \n           * number, and returns to that row and column.  However, if you define\n           * a saveRowIdentity function, then it will return you to the currently \n           * selected column within that row (in a business sense - so if some\n           * rows have been deleted, it will still find the same data, presuming it \n           * still exists in the list.  If it isn't in the list then it will instead\n           * return to the same row number - i.e. scroll percentage)\n           * \n           * Note that this option will do nothing if the cellNav\n           * feature is not enabled.\n           * \n           * <br/>Defaults to true (unless saveScroll is true)\n           */\n          gridOptions.saveFocus = gridOptions.saveScroll !== true && gridOptions.saveFocus !== false;\n          /**\n           * @ngdoc object\n           * @name saveRowIdentity\n           * @propertyOf  ui.grid.saveState.api:GridOptions\n           * @description A function that can be called, passing in a rowEntity, \n           * and that will return a unique id for that row.  This might simply \n           * return the `id` field from that row (if you have one), or it might\n           * concatenate some fields within the row to make a unique value.\n           * \n           * This value will be used to find the same row again and set the focus \n           * to it, if it exists when we return.\n           * \n           * <br/>Defaults to undefined\n           */\n          /**\n           * @ngdoc object\n           * @name saveVisible\n           * @propertyOf  ui.grid.saveState.api:GridOptions\n           * @description Save whether or not columns are visible.\n           * \n           * <br/>Defaults to true\n           */\n          gridOptions.saveVisible = gridOptions.saveVisible !== false;          \n          /**\n           * @ngdoc object\n           * @name saveSort\n           * @propertyOf  ui.grid.saveState.api:GridOptions\n           * @description Save the current sort state for each column\n           * \n           * <br/>Defaults to true\n           */\n          gridOptions.saveSort = gridOptions.saveSort !== false;         \n          /**\n           * @ngdoc object\n           * @name saveFilter\n           * @propertyOf  ui.grid.saveState.api:GridOptions\n           * @description Save the current filter state for each column\n           * \n           * <br/>Defaults to true\n           */\n          gridOptions.saveFilter = gridOptions.saveFilter !== false;\n          /**\n           * @ngdoc object\n           * @name saveSelection\n           * @propertyOf  ui.grid.saveState.api:GridOptions\n           * @description Save the currently selected rows.  If the `saveRowIdentity` callback\n           * is defined, then it will save the id of the row and select that.  If not, then\n           * it will attempt to select the rows by row number, which will give the wrong results\n           * if the data set has changed in the mean-time.\n           * \n           * Note that this option only does anything\n           * if the selection feature is enabled.  \n           * \n           * <br/>Defaults to true\n           */\n          gridOptions.saveSelection = gridOptions.saveSelection !== false;          \n        },\n\n\n\n        /**\n         * @ngdoc function\n         * @name save\n         * @methodOf  ui.grid.saveState.service:uiGridSaveStateService\n         * @description Saves the current grid state into an object, and\n         * passes that object back to the caller\n         * @param {Grid} grid the grid whose state we'd like to save\n         * @returns {object} the state ready to be saved\n         */\n        save: function (grid) {\n          var savedState = {};\n          \n          savedState.columns = service.saveColumns( grid );\n          savedState.scrollFocus = service.saveScrollFocus( grid );\n          savedState.selection = service.saveSelection( grid );\n          \n          return savedState;\n        },\n        \n        \n        /**\n         * @ngdoc function\n         * @name restore\n         * @methodOf  ui.grid.saveState.service:uiGridSaveStateService\n         * @description Applies the provided state to the grid\n         * \n         * @param {Grid} grid the grid whose state we'd like to restore\n         * @param {scope} $scope a scope that we can broadcast on\n         * @param {object} state the state we'd like to restore\n         */\n        restore: function( grid, $scope, state ){\n          if ( state.columns ) {\n            service.restoreColumns( grid, state.columns );\n          }\n          \n          if ( state.scrollFocus ){\n            service.restoreScrollFocus( grid, $scope, state.scrollFocus );\n          }\n          \n          if ( state.selection ){\n            service.restoreSelection( grid, state.selection );\n          }\n          \n          grid.refresh();\n        },\n        \n        \n        /**\n         * @ngdoc function\n         * @name saveColumns\n         * @methodOf  ui.grid.saveState.service:uiGridSaveStateService\n         * @description Saves the column setup, including sort, filters, ordering\n         * and column widths.\n         * \n         * Works through the current columns, storing them in order.  Stores the\n         * column name, then the visible flag, width, sort and filters for each column.\n         *\n         * @param {Grid} grid the grid whose state we'd like to save\n         * @returns {array} the columns state ready to be saved\n         */\n        saveColumns: function( grid ) {\n          var columns = [];\n          angular.forEach( grid.columns, function( column ) {\n            var savedColumn = {};\n            savedColumn.name = column.name;\n            savedColumn.visible = column.visible;\n            savedColumn.width = column.width;\n            \n            // these two must be copied, not just pointed too - otherwise our saved state is pointing to the same object as current state\n            savedColumn.sort = angular.copy( column.sort );\n            savedColumn.filters = angular.copy ( column.filters );\n            columns.push( savedColumn );\n          });\n          \n          return columns;\n        },\n        \n\n        /**\n         * @ngdoc function\n         * @name saveScrollFocus\n         * @methodOf  ui.grid.saveState.service:uiGridSaveStateService\n         * @description Saves the currently scroll or focus.\n         * \n         * If cellNav isn't present then does nothing - we can't return\n         * to the scroll position without cellNav anyway.\n         * \n         * If the cellNav module is present, and saveFocus is true, then\n         * it saves the currently focused cell.  If rowIdentity is present\n         * then saves using rowIdentity, otherwise saves visibleRowNum.\n         * \n         * If the cellNav module is not present, and saveScroll is true, then\n         * it approximates the current scroll row and column, and saves that.\n         * \n         * @param {Grid} grid the grid whose state we'd like to save\n         * @returns {object} the selection state ready to be saved\n         */\n        saveScrollFocus: function( grid ){\n          if ( !grid.api.cellNav ){\n            return {};\n          }\n          \n          var scrollFocus = {};\n          if ( grid.options.saveFocus ){\n            scrollFocus.focus = true;\n            var rowCol = grid.api.cellNav.getFocusedCell();\n            if ( rowCol !== null ) {\n              scrollFocus.colName = rowCol.col.colDef.name;\n              scrollFocus.rowVal = service.getRowVal( grid, rowCol.row );\n            }\n          } else if ( grid.options.saveScroll ) {\n            scrollFocus.focus = false;\n            if ( grid.renderContainers.body.prevRowScrollIndex ){\n              scrollFocus.rowVal = service.getRowVal( grid, grid.renderContainers.body.visibleRowCache[ grid.renderContainers.body.prevRowScrollIndex ]);\n            }\n            \n            if ( grid.renderContainers.body.prevColScrollIndex ){\n              scrollFocus.colName = grid.renderContainers.body.visibleColumnCache[ grid.renderContainers.body.prevColScrollIndex ].name;\n            }\n          }        \n          \n          return scrollFocus;\n        },\n        \n\n        /**\n         * @ngdoc function\n         * @name saveSelection\n         * @methodOf  ui.grid.saveState.service:uiGridSaveStateService\n         * @description Saves the currently selected rows, if the selection feature is enabled\n         * @param {Grid} grid the grid whose state we'd like to save\n         * @returns {object} the selection state ready to be saved\n         */\n        saveSelection: function( grid ){\n          if ( !grid.api.selection ){\n            return {};\n          }\n          \n          var selection = grid.api.selection.getSelectedGridRows().map( function( gridRow ) {\n            return service.getRowVal( grid, gridRow );\n          });\n          \n          return selection;\n        },\n        \n        \n        /**\n         * @ngdoc function\n         * @name getRowVal\n         * @methodOf  ui.grid.saveState.service:uiGridSaveStateService\n         * @description Helper function that gets either the rowNum or\n         * the saveRowIdentity, given a gridRow \n         * @param {Grid} grid the grid the row is in\n         * @param {GridRow} gridRow the row we want the rowNum for\n         * @returns {object} an object containing { identity: true/false, row: rowNumber/rowIdentity }\n         * \n         */\n        getRowVal: function( grid, gridRow ){\n          if ( !gridRow ) {\n            return null;\n          }\n          \n          var rowVal = {};\n          if ( grid.options.saveRowIdentity ){\n            rowVal.identity = true;\n            rowVal.row = grid.options.saveRowIdentity( gridRow.entity );\n          } else {\n            rowVal.identity = false;\n            rowVal.row = grid.renderContainers.body.visibleRowCache.indexOf( gridRow );\n          }\n          return rowVal;\n        },\n        \n        \n        /**\n         * @ngdoc function\n         * @name restoreColumns\n         * @methodOf  ui.grid.saveState.service:uiGridSaveStateService\n         * @description Restores the columns, including order, visible, width\n         * sort and filters.\n         * \n         * @param {Grid} grid the grid whose state we'd like to restore\n         * @param {object} columnsState the list of columns we had before, with their state\n         */\n        restoreColumns: function( grid, columnsState ){\n          angular.forEach( columnsState, function( columnState, index ) {\n            var currentCol = grid.columns.filter( function( column ) {\n              return column.name === columnState.name;\n            });\n            \n            if ( currentCol.length > 0 ){\n              var currentIndex = grid.columns.indexOf( currentCol[0] );\n              \n              if ( grid.columns[currentIndex].visible !== columnState.visible ||\n                   grid.columns[currentIndex].colDef.visible !== columnState.visible ){\n                grid.columns[currentIndex].visible = columnState.visible;\n                grid.columns[currentIndex].colDef.visible = columnState.visible;\n                grid.api.core.raise.columnVisibilityChanged( grid.columns[currentIndex]);\n              }\n              \n              grid.columns[currentIndex].width = columnState.width;\n\n              if ( !angular.equals(grid.columns[currentIndex].sort, columnState.sort && \n                   !( grid.columns[currentIndex].sort === undefined && angular.isEmpty(columnState.sort) ) ) ){\n                grid.columns[currentIndex].sort = angular.copy( columnState.sort );\n                grid.api.core.raise.sortChanged();\n              }\n\n              if ( !angular.equals(grid.columns[currentIndex].filters, columnState.filters ) ){\n                grid.columns[currentIndex].filters = angular.copy( columnState.filters );\n                grid.api.core.raise.filterChanged();\n              }\n              \n              if ( currentIndex !== index ){\n                var column = grid.columns.splice( currentIndex, 1 )[0];\n                grid.columns.splice( index, 0, column );\n              }\n            }\n          });\n        },\n        \n\n        /**\n         * @ngdoc function\n         * @name restoreScrollFocus\n         * @methodOf  ui.grid.saveState.service:uiGridSaveStateService\n         * @description Scrolls to the position that was saved.  If focus is true, then\n         * sets focus to the specified row/col.  If focus is false, then scrolls to the \n         * specified row/col.\n         * \n         * @param {Grid} grid the grid whose state we'd like to restore\n         * @param {scope} $scope a scope that we can broadcast on\n         * @param {object} scrollFocusState the scroll/focus state ready to be restored\n         */\n        restoreScrollFocus: function( grid, $scope, scrollFocusState ){\n          if ( !grid.api.cellNav ){\n            return;\n          }\n          \n          var colDef, row;\n          if ( scrollFocusState.colName ){\n            var colDefs = grid.options.columnDefs.filter( function( colDef ) { return colDef.name === scrollFocusState.colName; });\n            if ( colDefs.length > 0 ){\n              colDef = colDefs[0];\n            }\n          }\n          \n          if ( scrollFocusState.rowVal && scrollFocusState.rowVal.row ){\n            if ( scrollFocusState.rowVal.identity ){\n              row = service.findRowByIdentity( grid, scrollFocusState.rowVal );\n            } else {\n              row = grid.renderContainers.body.visibleRowCache[ scrollFocusState.rowVal.row ];\n            }\n          }\n          \n          var entity = row && row.entity ? row.entity : null ;\n\n          if ( colDef || entity ) {          \n            if (scrollFocusState.focus ){\n              grid.api.cellNav.scrollToFocus( $scope, entity, colDef );\n            } else {\n              grid.api.cellNav.scrollTo( $scope, entity, colDef );\n            }\n          }\n        },\n        \n\n        /**\n         * @ngdoc function\n         * @name restoreSelection\n         * @methodOf  ui.grid.saveState.service:uiGridSaveStateService\n         * @description Selects the rows that are provided in the selection\n         * state.  If you are using `saveRowIdentity` and more than one row matches the identity\n         * function then only the first is selected.\n         * @param {Grid} grid the grid whose state we'd like to restore\n         * @param {object} selectionState the selection state ready to be restored\n         */\n        restoreSelection: function( grid, selectionState ){\n          if ( !grid.api.selection ){\n            return;\n          }\n          \n          grid.api.selection.clearSelectedRows();\n\n          angular.forEach( selectionState, function( rowVal ) {\n            if ( rowVal.identity ){\n              var foundRow = service.findRowByIdentity( grid, rowVal );\n              \n              if ( foundRow ){\n                grid.api.selection.selectRow( foundRow.entity );\n              }\n              \n            } else {\n              grid.api.selection.selectRowByVisibleIndex( rowVal.row );\n            }\n          });\n        },\n        \n        \n        /**\n         * @ngdoc function\n         * @name findRowByIdentity\n         * @methodOf  ui.grid.saveState.service:uiGridSaveStateService\n         * @description Finds a row given it's identity value, returns the first found row\n         * if any are found, otherwise returns null if no rows are found.\n         * @param {Grid} grid the grid whose state we'd like to restore\n         * @param {object} rowVal the row we'd like to find\n         * @returns {gridRow} the found row, or null if none found\n         */\n        findRowByIdentity: function( grid, rowVal ){\n          if ( !grid.options.saveRowIdentity ){\n            return null;\n          }\n          \n          var filteredRows = grid.rows.filter( function( gridRow ) {\n            if ( grid.options.saveRowIdentity( gridRow.entity ) === rowVal.row ){\n              return true;\n            } else {\n              return false;\n            }\n          });\n          \n          if ( filteredRows.length > 0 ){\n            return filteredRows[0];\n          } else {\n            return null;\n          }\n        }\n      };\n\n      return service;\n\n    }\n  ]);\n\n  /**\n   *  @ngdoc directive\n   *  @name ui.grid.saveState.directive:uiGridSaveState\n   *  @element div\n   *  @restrict A\n   *\n   *  @description Adds saveState features to grid\n   *\n   *  @example\n   <example module=\"app\">\n   <file name=\"app.js\">\n   var app = angular.module('app', ['ui.grid', 'ui.grid.saveState']);\n\n   app.controller('MainCtrl', ['$scope', function ($scope) {\n      $scope.data = [\n        { name: 'Bob', title: 'CEO' },\n        { name: 'Frank', title: 'Lowly Developer' }\n      ];\n\n      $scope.gridOptions = {\n        columnDefs: [\n          {name: 'name'},\n          {name: 'title', enableCellEdit: true}\n        ],\n        data: $scope.data\n      };\n    }]);\n   </file>\n   <file name=\"index.html\">\n   <div ng-controller=\"MainCtrl\">\n   <div ui-grid=\"gridOptions\" ui-grid-save-state></div>\n   </div>\n   </file>\n   </example>\n   */\n  module.directive('uiGridSaveState', ['uiGridSaveStateConstants', 'uiGridSaveStateService', 'gridUtil', '$compile',\n    function (uiGridSaveStateConstants, uiGridSaveStateService, gridUtil, $compile) {\n      return {\n        replace: true,\n        priority: 0,\n        require: '^uiGrid',\n        scope: false,\n        link: function ($scope, $elm, $attrs, uiGridCtrl) {\n          uiGridSaveStateService.initializeGrid(uiGridCtrl.grid);\n        }\n      };\n    }\n  ]);\n})();\n\n(function () {\n  'use strict';\n\n  /**\n   * @ngdoc overview\n   * @name ui.grid.selection\n   * @description\n   *\n   *  # ui.grid.selection\n   * This module provides row selection\n   * <br/>\n   * <br/>\n   *\n   * <div doc-module-components=\"ui.grid.selection\"></div>\n   */\n\n  var module = angular.module('ui.grid.selection', ['ui.grid']);\n\n  /**\n   *  @ngdoc object\n   *  @name ui.grid.selection.constant:uiGridSelectionConstants\n   *\n   *  @description constants available in selection module\n   */\n  module.constant('uiGridSelectionConstants', {\n    featureName: \"selection\",\n    selectionRowHeaderColName: 'selectionRowHeaderCol'\n  });\n\n  //add methods to GridRow\n  angular.module('ui.grid').config(['$provide', function($provide) {\n    $provide.decorator('GridRow', ['$delegate', function($delegate) {\n\n      /**\n       *  @ngdoc object\n       *  @name ui.grid.selection.api:GridRow\n       *\n       *  @description GridRow prototype functions added for selection\n       */\n\n      /**\n       *  @ngdoc object\n       *  @name enableSelection\n       *  @propertyOf  ui.grid.selection.api:GridRow\n       *  @description Enable row selection for this row, only settable by internal code.\n       *\n       *  The grouping feature, for example, might set group header rows to not be selectable.\n       *  <br/>Defaults to true\n       */\n\n      /**\n       *  @ngdoc object\n       *  @name isSelected\n       *  @propertyOf  ui.grid.selection.api:GridRow\n       *  @description Selected state of row.  Should be readonly. Make any changes to selected state using setSelected().\n       *  <br/>Defaults to false\n       */\n\n\n        /**\n         * @ngdoc function\n         * @name setSelected\n         * @methodOf ui.grid.selection.api:GridRow\n         * @description Sets the isSelected property and updates the selectedCount\n         * Changes to isSelected state should only be made via this function\n         * @param {bool} selelected value to set\n         */\n        $delegate.prototype.setSelected = function(selected) {\n          this.isSelected = selected;\n          if (selected) {\n            this.grid.selection.selectedCount++;\n          }\n          else {\n            this.grid.selection.selectedCount--;\n          }\n        };\n\n      return $delegate;\n    }]);\n  }]);\n\n  /**\n   *  @ngdoc service\n   *  @name ui.grid.selection.service:uiGridSelectionService\n   *\n   *  @description Services for selection features\n   */\n  module.service('uiGridSelectionService', ['$q', '$templateCache', 'uiGridSelectionConstants', 'gridUtil',\n    function ($q, $templateCache, uiGridSelectionConstants, gridUtil) {\n\n      var service = {\n\n        initializeGrid: function (grid) {\n\n          //add feature namespace and any properties to grid for needed\n          /**\n           *  @ngdoc object\n           *  @name ui.grid.selection.grid:selection\n           *\n           *  @description Grid properties and functions added for selection\n           */\n          grid.selection = {};\n          grid.selection.lastSelectedRow = null;\n          grid.selection.selectAll = false;\n\n\n          /**\n           *  @ngdoc object\n           *  @name selectedCount\n           *  @propertyOf  ui.grid.selection.grid:selection\n           *  @description Current count of selected rows\n           *  @example\n           *  var count = grid.selection.selectedCount\n           */\n          grid.selection.selectedCount = 0;\n\n          service.defaultGridOptions(grid.options);\n\n          /**\n           *  @ngdoc object\n           *  @name ui.grid.selection.api:PublicApi\n           *\n           *  @description Public Api for selection feature\n           */\n          var publicApi = {\n            events: {\n              selection: {\n                /**\n                 * @ngdoc event\n                 * @name rowSelectionChanged\n                 * @eventOf  ui.grid.selection.api:PublicApi\n                 * @description  is raised after the row.isSelected state is changed\n                 * @param {GridRow} row the row that was selected/deselected\n                 * @param {Event} event object if raised from an event\n                 */\n                rowSelectionChanged: function (scope, row, evt) {\n                },\n                /**\n                 * @ngdoc event\n                 * @name rowSelectionChangedBatch\n                 * @eventOf  ui.grid.selection.api:PublicApi\n                 * @description  is raised after the row.isSelected state is changed\n                 * in bulk, if the `enableSelectionBatchEvent` option is set to true\n                 * (which it is by default).  This allows more efficient processing\n                 * of bulk events.\n                 * @param {array} rows the rows that were selected/deselected\n                 * @param {Event} event object if raised from an event\n                 */\n                rowSelectionChangedBatch: function (scope, rows, evt) {\n                }\n              }\n            },\n            methods: {\n              selection: {\n                /**\n                 * @ngdoc function\n                 * @name toggleRowSelection\n                 * @methodOf  ui.grid.selection.api:PublicApi\n                 * @description Toggles data row as selected or unselected\n                 * @param {object} rowEntity gridOptions.data[] array instance\n                 * @param {Event} event object if raised from an event\n                 */\n                toggleRowSelection: function (rowEntity, evt) {\n                  var row = grid.getRow(rowEntity);\n                  if (row !== null && row.enableSelection !== false) {\n                    service.toggleRowSelection(grid, row, evt, grid.options.multiSelect, grid.options.noUnselect);\n                  }\n                },\n                /**\n                 * @ngdoc function\n                 * @name selectRow\n                 * @methodOf  ui.grid.selection.api:PublicApi\n                 * @description Select the data row\n                 * @param {object} rowEntity gridOptions.data[] array instance\n                 * @param {Event} event object if raised from an event\n                 */\n                selectRow: function (rowEntity, evt) {\n                  var row = grid.getRow(rowEntity);\n                  if (row !== null && !row.isSelected && row.enableSelection !== false) {\n                    service.toggleRowSelection(grid, row, evt, grid.options.multiSelect, grid.options.noUnselect);\n                  }\n                },\n                /**\n                 * @ngdoc function\n                 * @name selectRowByVisibleIndex\n                 * @methodOf  ui.grid.selection.api:PublicApi\n                 * @description Select the specified row by visible index (i.e. if you\n                 * specify row 0 you'll get the first visible row selected).  In this context\n                 * visible means of those rows that are theoretically visible (i.e. not filtered),\n                 * rather than rows currently rendered on the screen.\n                 * @param {number} index index within the rowsVisible array\n                 * @param {Event} event object if raised from an event\n                 */\n                selectRowByVisibleIndex: function ( rowNum, evt ) {\n                  var row = grid.renderContainers.body.visibleRowCache[rowNum];\n                  if (row !== null && typeof(row) !== 'undefined' && !row.isSelected && row.enableSelection !== false) {\n                    service.toggleRowSelection(grid, row, evt, grid.options.multiSelect, grid.options.noUnselect);\n                  }\n                },\n                /**\n                 * @ngdoc function\n                 * @name unSelectRow\n                 * @methodOf  ui.grid.selection.api:PublicApi\n                 * @description UnSelect the data row\n                 * @param {object} rowEntity gridOptions.data[] array instance\n                 * @param {Event} event object if raised from an event\n                 */\n                unSelectRow: function (rowEntity, evt) {\n                  var row = grid.getRow(rowEntity);\n                  if (row !== null && row.isSelected) {\n                    service.toggleRowSelection(grid, row, evt, grid.options.multiSelect, grid.options.noUnselect);\n                  }\n                },\n                /**\n                 * @ngdoc function\n                 * @name selectAllRows\n                 * @methodOf  ui.grid.selection.api:PublicApi\n                 * @description Selects all rows.  Does nothing if multiSelect = false\n                 * @param {Event} event object if raised from an event\n                 */\n                selectAllRows: function (evt) {\n                  if (grid.options.multiSelect === false) {\n                    return;\n                  }\n\n                  var changedRows = [];\n                  grid.rows.forEach(function (row) {\n                    if ( !row.isSelected && row.enableSelection !== false ){\n                      row.setSelected(true);\n                      service.decideRaiseSelectionEvent( grid, row, changedRows, evt );\n                    }\n                  });\n                  service.decideRaiseSelectionBatchEvent( grid, changedRows, evt );\n                  grid.selection.selectAll = true;\n                },\n                /**\n                 * @ngdoc function\n                 * @name selectAllVisibleRows\n                 * @methodOf  ui.grid.selection.api:PublicApi\n                 * @description Selects all visible rows.  Does nothing if multiSelect = false\n                 * @param {Event} event object if raised from an event\n                 */\n                selectAllVisibleRows: function (evt) {\n                  if (grid.options.multiSelect === false) {\n                    return;\n                  }\n\n                  var changedRows = [];\n                  grid.rows.forEach(function (row) {\n                    if (row.visible) {\n                      if (!row.isSelected && row.enableSelection !== false){\n                        row.setSelected(true);\n                        service.decideRaiseSelectionEvent( grid, row, changedRows, evt );\n                      }\n                    } else {\n                      if (row.isSelected){\n                        row.setSelected(false);\n                        service.decideRaiseSelectionEvent( grid, row, changedRows, evt );\n                      }\n                    }\n                  });\n                  service.decideRaiseSelectionBatchEvent( grid, changedRows, evt );\n                  grid.selection.selectAll = true;\n                },\n                /**\n                 * @ngdoc function\n                 * @name clearSelectedRows\n                 * @methodOf  ui.grid.selection.api:PublicApi\n                 * @description Unselects all rows\n                 * @param {Event} event object if raised from an event\n                 */\n                clearSelectedRows: function (evt) {\n                  service.clearSelectedRows(grid, evt);\n                },\n                /**\n                 * @ngdoc function\n                 * @name getSelectedRows\n                 * @methodOf  ui.grid.selection.api:PublicApi\n                 * @description returns all selectedRow's entity references\n                 */\n                getSelectedRows: function () {\n                  return service.getSelectedRows(grid).map(function (gridRow) {\n                    return gridRow.entity;\n                  });\n                },\n                /**\n                 * @ngdoc function\n                 * @name getSelectedGridRows\n                 * @methodOf  ui.grid.selection.api:PublicApi\n                 * @description returns all selectedRow's as gridRows\n                 */\n                getSelectedGridRows: function () {\n                  return service.getSelectedRows(grid);\n                },\n                /**\n                 * @ngdoc function\n                 * @name setMultiSelect\n                 * @methodOf  ui.grid.selection.api:PublicApi\n                 * @description Sets the current gridOption.multiSelect to true or false\n                 * @param {bool} multiSelect true to allow multiple rows\n                 */\n                setMultiSelect: function (multiSelect) {\n                  grid.options.multiSelect = multiSelect;\n                },\n                /**\n                 * @ngdoc function\n                 * @name setModifierKeysToMultiSelect\n                 * @methodOf  ui.grid.selection.api:PublicApi\n                 * @description Sets the current gridOption.modifierKeysToMultiSelect to true or false\n                 * @param {bool} modifierKeysToMultiSelect true to only allow multiple rows when using ctrlKey or shiftKey is used\n                 */\n                setModifierKeysToMultiSelect: function (modifierKeysToMultiSelect) {\n                  grid.options.modifierKeysToMultiSelect = modifierKeysToMultiSelect;\n                },\n                /**\n                 * @ngdoc function\n                 * @name getSelectAllState\n                 * @methodOf  ui.grid.selection.api:PublicApi\n                 * @description Returns whether or not the selectAll checkbox is currently ticked.  The\n                 * grid doesn't automatically select rows when you add extra data - so when you add data\n                 * you need to explicitly check whether the selectAll is set, and then call setVisible rows\n                 * if it is\n                 */\n                getSelectAllState: function () {\n                  return grid.selection.selectAll;\n                }\n\n              }\n            }\n          };\n\n          grid.api.registerEventsFromObject(publicApi.events);\n\n          grid.api.registerMethodsFromObject(publicApi.methods);\n\n        },\n\n        defaultGridOptions: function (gridOptions) {\n          //default option to true unless it was explicitly set to false\n          /**\n           *  @ngdoc object\n           *  @name ui.grid.selection.api:GridOptions\n           *\n           *  @description GridOptions for selection feature, these are available to be\n           *  set using the ui-grid {@link ui.grid.class:GridOptions gridOptions}\n           */\n\n          /**\n           *  @ngdoc object\n           *  @name enableRowSelection\n           *  @propertyOf  ui.grid.selection.api:GridOptions\n           *  @description Enable row selection for entire grid.\n           *  <br/>Defaults to true\n           */\n          gridOptions.enableRowSelection = gridOptions.enableRowSelection !== false;\n          /**\n           *  @ngdoc object\n           *  @name multiSelect\n           *  @propertyOf  ui.grid.selection.api:GridOptions\n           *  @description Enable multiple row selection for entire grid\n           *  <br/>Defaults to true\n           */\n          gridOptions.multiSelect = gridOptions.multiSelect !== false;\n          /**\n           *  @ngdoc object\n           *  @name noUnselect\n           *  @propertyOf  ui.grid.selection.api:GridOptions\n           *  @description Prevent a row from being unselected.  Works in conjunction\n           *  with `multiselect = false` and `gridApi.selection.selectRow()` to allow\n           *  you to create a single selection only grid - a row is always selected, you\n           *  can only select different rows, you can't unselect the row.\n           *  <br/>Defaults to false\n           */\n          gridOptions.noUnselect = gridOptions.noUnselect === true;\n          /**\n           *  @ngdoc object\n           *  @name modifierKeysToMultiSelect\n           *  @propertyOf  ui.grid.selection.api:GridOptions\n           *  @description Enable multiple row selection only when using the ctrlKey or shiftKey. Requires multiSelect to be true.\n           *  <br/>Defaults to false\n           */\n          gridOptions.modifierKeysToMultiSelect = gridOptions.modifierKeysToMultiSelect === true;\n          /**\n           *  @ngdoc object\n           *  @name enableRowHeaderSelection\n           *  @propertyOf  ui.grid.selection.api:GridOptions\n           *  @description Enable a row header to be used for selection\n           *  <br/>Defaults to true\n           */\n          gridOptions.enableRowHeaderSelection = gridOptions.enableRowHeaderSelection !== false;\n          /**\n           *  @ngdoc object\n           *  @name enableSelectAll\n           *  @propertyOf  ui.grid.selection.api:GridOptions\n           *  @description Enable the select all checkbox at the top of the selectionRowHeader\n           *  <br/>Defaults to true\n           */\n          gridOptions.enableSelectAll = gridOptions.enableSelectAll !== false;\n          /**\n           *  @ngdoc object\n           *  @name enableSelectionBatchEvent\n           *  @propertyOf  ui.grid.selection.api:GridOptions\n           *  @description If selected rows are changed in bulk, either via the API or\n           *  via the selectAll checkbox, then a separate event is fired.  Setting this\n           *  option to false will cause the rowSelectionChanged event to be called multiple times\n           *  instead\n           *  <br/>Defaults to true\n           */\n          gridOptions.enableSelectionBatchEvent = gridOptions.enableSelectionBatchEvent !== false;\n          /**\n           *  @ngdoc object\n           *  @name selectionRowHeaderWidth\n           *  @propertyOf  ui.grid.selection.api:GridOptions\n           *  @description can be used to set a custom width for the row header selection column\n           *  <br/>Defaults to 30px\n           */\n          gridOptions.selectionRowHeaderWidth = angular.isDefined(gridOptions.selectionRowHeaderWidth) ? gridOptions.selectionRowHeaderWidth : 30;\n\n          /**\n           *  @ngdoc object\n           *  @name enableFooterTotalSelected\n           *  @propertyOf  ui.grid.selection.api:GridOptions\n           *  @description Shows the total number of selected items in footer if true.\n           *  <br/>Defaults to true.\n           *  <br/>GridOptions.showFooter must also be set to true.\n           */\n          gridOptions.enableFooterTotalSelected = gridOptions.enableFooterTotalSelected !== false;\n\n          /**\n           *  @ngdoc object\n           *  @name isRowSelectable\n           *  @propertyOf  ui.grid.selection.api:GridOptions\n           *  @description Makes it possible to specify a method that evaluates for each and sets its \"enableSelection\" property.\n           */\n\n          gridOptions.isRowSelectable = angular.isDefined(gridOptions.isRowSelectable) ? gridOptions.isRowSelectable : angular.noop;\n        },\n\n        /**\n         * @ngdoc function\n         * @name toggleRowSelection\n         * @methodOf  ui.grid.selection.service:uiGridSelectionService\n         * @description Toggles row as selected or unselected\n         * @param {Grid} grid grid object\n         * @param {GridRow} row row to select or deselect\n         * @param {Event} event object if resulting from event\n         * @param {bool} multiSelect if false, only one row at time can be selected\n         * @param {bool} noUnselect if true then rows cannot be unselected\n         */\n        toggleRowSelection: function (grid, row, evt, multiSelect, noUnselect) {\n          var selected = row.isSelected;\n\n          if (!multiSelect && !selected) {\n            service.clearSelectedRows(grid, evt);\n          } else if (!multiSelect && selected) {\n            var selectedRows = service.getSelectedRows(grid);\n            if (selectedRows.length > 1) {\n              selected = false; // Enable reselect of the row\n              service.clearSelectedRows(grid, evt);\n            }\n          }\n\n          if (selected && noUnselect){\n            // don't deselect the row \n          } else if (row.enableSelection !== false) {\n            row.setSelected(!selected);\n            if (row.isSelected === true) {\n              grid.selection.lastSelectedRow = row;\n            } else {\n              grid.selection.selectAll = false;\n            }\n            grid.api.selection.raise.rowSelectionChanged(row, evt);\n          }\n        },\n        /**\n         * @ngdoc function\n         * @name shiftSelect\n         * @methodOf  ui.grid.selection.service:uiGridSelectionService\n         * @description selects a group of rows from the last selected row using the shift key\n         * @param {Grid} grid grid object\n         * @param {GridRow} clicked row\n         * @param {Event} event object if raised from an event\n         * @param {bool} multiSelect if false, does nothing this is for multiSelect only\n         */\n        shiftSelect: function (grid, row, evt, multiSelect) {\n          if (!multiSelect) {\n            return;\n          }\n          var selectedRows = service.getSelectedRows(grid);\n          var fromRow = selectedRows.length > 0 ? grid.renderContainers.body.visibleRowCache.indexOf(grid.selection.lastSelectedRow) : 0;\n          var toRow = grid.renderContainers.body.visibleRowCache.indexOf(row);\n          //reverse select direction\n          if (fromRow > toRow) {\n            var tmp = fromRow;\n            fromRow = toRow;\n            toRow = tmp;\n          }\n\n          var changedRows = [];\n          for (var i = fromRow; i <= toRow; i++) {\n            var rowToSelect = grid.renderContainers.body.visibleRowCache[i];\n            if (rowToSelect) {\n              if ( !rowToSelect.isSelected && rowToSelect.enableSelection !== false ){\n                rowToSelect.setSelected(true);\n                grid.selection.lastSelectedRow = rowToSelect;\n                service.decideRaiseSelectionEvent( grid, rowToSelect, changedRows, evt );\n              }\n            }\n          }\n          service.decideRaiseSelectionBatchEvent( grid, changedRows, evt );\n        },\n        /**\n         * @ngdoc function\n         * @name getSelectedRows\n         * @methodOf  ui.grid.selection.service:uiGridSelectionService\n         * @description Returns all the selected rows\n         * @param {Grid} grid grid object\n         */\n        getSelectedRows: function (grid) {\n          return grid.rows.filter(function (row) {\n            return row.isSelected;\n          });\n        },\n\n        /**\n         * @ngdoc function\n         * @name clearSelectedRows\n         * @methodOf  ui.grid.selection.service:uiGridSelectionService\n         * @description Clears all selected rows\n         * @param {Grid} grid grid object\n         * @param {Event} event object if raised from an event\n         */\n        clearSelectedRows: function (grid, evt) {\n          var changedRows = [];\n          service.getSelectedRows(grid).forEach(function (row) {\n            if ( row.isSelected ){\n              row.setSelected(false);\n              service.decideRaiseSelectionEvent( grid, row, changedRows, evt );\n            }\n          });\n          service.decideRaiseSelectionBatchEvent( grid, changedRows, evt );\n          grid.selection.selectAll = false;\n        },\n\n        /**\n         * @ngdoc function\n         * @name decideRaiseSelectionEvent\n         * @methodOf  ui.grid.selection.service:uiGridSelectionService\n         * @description Decides whether to raise a single event or a batch event\n         * @param {Grid} grid grid object\n         * @param {GridRow} row row that has changed\n         * @param {array} changedRows an array to which we can append the changed\n         * @param {Event} event object if raised from an event\n         * row if we're doing batch events\n         */\n        decideRaiseSelectionEvent: function( grid, row, changedRows, evt ){\n          if ( !grid.options.enableSelectionBatchEvent ){\n            grid.api.selection.raise.rowSelectionChanged(row, evt);\n          } else {\n            changedRows.push(row);\n          }\n        },\n\n        /**\n         * @ngdoc function\n         * @name raiseSelectionEvent\n         * @methodOf  ui.grid.selection.service:uiGridSelectionService\n         * @description Decides whether we need to raise a batch event, and\n         * raises it if we do.\n         * @param {Grid} grid grid object\n         * @param {array} changedRows an array of changed rows, only populated\n         * @param {Event} event object if raised from an event\n         * if we're doing batch events\n         */\n        decideRaiseSelectionBatchEvent: function( grid, changedRows, evt ){\n          if ( changedRows.length > 0 ){\n            grid.api.selection.raise.rowSelectionChangedBatch(changedRows, evt);\n          }\n        }\n      };\n\n      return service;\n\n    }]);\n\n  /**\n   *  @ngdoc directive\n   *  @name ui.grid.selection.directive:uiGridSelection\n   *  @element div\n   *  @restrict A\n   *\n   *  @description Adds selection features to grid\n   *\n   *  @example\n   <example module=\"app\">\n   <file name=\"app.js\">\n   var app = angular.module('app', ['ui.grid', 'ui.grid.selection']);\n\n   app.controller('MainCtrl', ['$scope', function ($scope) {\n      $scope.data = [\n        { name: 'Bob', title: 'CEO' },\n            { name: 'Frank', title: 'Lowly Developer' }\n      ];\n\n      $scope.columnDefs = [\n        {name: 'name', enableCellEdit: true},\n        {name: 'title', enableCellEdit: true}\n      ];\n    }]);\n   </file>\n   <file name=\"index.html\">\n   <div ng-controller=\"MainCtrl\">\n   <div ui-grid=\"{ data: data, columnDefs: columnDefs }\" ui-grid-selection></div>\n   </div>\n   </file>\n   </example>\n   */\n  module.directive('uiGridSelection', ['uiGridSelectionConstants', 'uiGridSelectionService', '$templateCache',\n    function (uiGridSelectionConstants, uiGridSelectionService, $templateCache) {\n      return {\n        replace: true,\n        priority: 0,\n        require: '^uiGrid',\n        scope: false,\n        compile: function () {\n          return {\n            pre: function ($scope, $elm, $attrs, uiGridCtrl) {\n              uiGridSelectionService.initializeGrid(uiGridCtrl.grid);\n              if (uiGridCtrl.grid.options.enableRowHeaderSelection) {\n                var selectionRowHeaderDef = {\n                  name: uiGridSelectionConstants.selectionRowHeaderColName,\n                  displayName: '',\n                  width:  uiGridCtrl.grid.options.selectionRowHeaderWidth,\n                  minWidth: 10,\n                  cellTemplate: 'ui-grid/selectionRowHeader',\n                  headerCellTemplate: 'ui-grid/selectionHeaderCell',\n                  enableColumnResizing: false,\n                  enableColumnMenu: false,\n                  exporterSuppressExport: true \n                };\n\n                uiGridCtrl.grid.addRowHeaderColumn(selectionRowHeaderDef);\n              }\n              \n              if (uiGridCtrl.grid.options.isRowSelectable !== angular.noop) {\n                uiGridCtrl.grid.registerRowBuilder(function(row, options) {\n                  row.enableSelection = uiGridCtrl.grid.options.isRowSelectable(row);\n                });\n              }\n            },\n            post: function ($scope, $elm, $attrs, uiGridCtrl) {\n\n            }\n          };\n        }\n      };\n    }]);\n\n  module.directive('uiGridSelectionRowHeaderButtons', ['$templateCache', 'uiGridSelectionService',\n    function ($templateCache, uiGridSelectionService) {\n      return {\n        replace: true,\n        restrict: 'E',\n        template: $templateCache.get('ui-grid/selectionRowHeaderButtons'),\n        scope: true,\n        require: '^uiGrid',\n        link: function($scope, $elm, $attrs, uiGridCtrl) {\n          var self = uiGridCtrl.grid;\n          $scope.selectButtonClick = function(row, evt) {\n            if (evt.shiftKey) {\n              uiGridSelectionService.shiftSelect(self, row, evt, self.options.multiSelect);\n            }\n            else if (evt.ctrlKey || evt.metaKey) {\n              uiGridSelectionService.toggleRowSelection(self, row, evt, self.options.multiSelect, self.options.noUnselect);\n            }\n            else {\n              uiGridSelectionService.toggleRowSelection(self, row, evt, (self.options.multiSelect && !self.options.modifierKeysToMultiSelect), self.options.noUnselect);\n            }\n          };\n        }\n      };\n    }]);\n\n  module.directive('uiGridSelectionSelectAllButtons', ['$templateCache', 'uiGridSelectionService',\n    function ($templateCache, uiGridSelectionService) {\n      return {\n        replace: true,\n        restrict: 'E',\n        template: $templateCache.get('ui-grid/selectionSelectAllButtons'),\n        scope: false,\n        link: function($scope, $elm, $attrs, uiGridCtrl) {\n          var self = $scope.col.grid;\n\n          $scope.headerButtonClick = function(row, evt) {\n            if ( self.selection.selectAll ){\n              uiGridSelectionService.clearSelectedRows(self, evt);\n              if ( self.options.noUnselect ){\n                self.api.selection.selectRowByVisibleIndex(0, evt);\n              }\n              self.selection.selectAll = false;\n            } else {\n              if ( self.options.multiSelect ){\n                self.api.selection.selectAllVisibleRows(evt);\n                self.selection.selectAll = true;\n              }\n            }\n          };\n        }\n      };\n    }]);\n\n  /**\n   *  @ngdoc directive\n   *  @name ui.grid.selection.directive:uiGridViewport\n   *  @element div\n   *\n   *  @description Stacks on top of ui.grid.uiGridViewport to alter the attributes used\n   *  for the grid row\n   */\n  module.directive('uiGridViewport',\n    ['$compile', 'uiGridConstants', 'uiGridSelectionConstants', 'gridUtil', '$parse', 'uiGridSelectionService',\n      function ($compile, uiGridConstants, uiGridSelectionConstants, gridUtil, $parse, uiGridSelectionService) {\n        return {\n          priority: -200, // run after default  directive\n          scope: false,\n          compile: function ($elm, $attrs) {\n            var rowRepeatDiv = angular.element($elm.children().children()[0]);\n\n            var existingNgClass = rowRepeatDiv.attr(\"ng-class\");\n            var newNgClass = '';\n            if ( existingNgClass ) {\n              newNgClass = existingNgClass.slice(0, -1) + \",'ui-grid-row-selected': row.isSelected}\";\n            } else {\n              newNgClass = \"{'ui-grid-row-selected': row.isSelected}\";\n            }\n            rowRepeatDiv.attr(\"ng-class\", newNgClass);\n\n            return {\n              pre: function ($scope, $elm, $attrs, controllers) {\n\n              },\n              post: function ($scope, $elm, $attrs, controllers) {\n              }\n            };\n          }\n        };\n      }]);\n\n  /**\n   *  @ngdoc directive\n   *  @name ui.grid.selection.directive:uiGridCell\n   *  @element div\n   *  @restrict A\n   *\n   *  @description Stacks on top of ui.grid.uiGridCell to provide selection feature\n   */\n  module.directive('uiGridCell',\n    ['$compile', 'uiGridConstants', 'uiGridSelectionConstants', 'gridUtil', '$parse', 'uiGridSelectionService',\n      function ($compile, uiGridConstants, uiGridSelectionConstants, gridUtil, $parse, uiGridSelectionService) {\n        return {\n          priority: -200, // run after default uiGridCell directive\n          restrict: 'A',\n          scope: false,\n          link: function ($scope, $elm, $attrs) {\n\n            var touchStartTime = 0;\n            var touchTimeout = 300;\n            var selectCells = function(evt){\n              if (evt.shiftKey) {\n                uiGridSelectionService.shiftSelect($scope.grid, $scope.row, evt, $scope.grid.options.multiSelect);\n              }\n              else if (evt.ctrlKey || evt.metaKey) {\n                uiGridSelectionService.toggleRowSelection($scope.grid, $scope.row, evt, $scope.grid.options.multiSelect, $scope.grid.options.noUnselect);\n              }\n              else {\n                uiGridSelectionService.toggleRowSelection($scope.grid, $scope.row, evt, ($scope.grid.options.multiSelect && !$scope.grid.options.modifierKeysToMultiSelect), $scope.grid.options.noUnselect);\n              }\n              $scope.$apply();\n            };\n\n            var touchStart = function(evt){\n              touchStartTime = (new Date()).getTime();\n            };\n\n            var touchEnd = function(evt) {\n              var touchEndTime = (new Date()).getTime();\n              var touchTime = touchEndTime - touchStartTime;\n\n              if (touchTime < touchTimeout ) {\n                // short touch\n                selectCells(evt);\n              }\n            };\n\n            function registerRowSelectionEvents() {\n              if ($scope.grid.options.enableRowSelection && !$scope.grid.options.enableRowHeaderSelection) {\n                $elm.addClass('ui-grid-disable-selection');\n                $elm.on('touchstart', touchStart);\n                $elm.on('touchend', touchEnd);\n                $elm.on('click', selectCells);\n\n                $scope.registered = true;\n              }\n            }\n\n            function deregisterRowSelectionEvents() {\n              if ($scope.registered){\n                $elm.removeClass('ui-grid-disable-selection');\n\n                $elm.off('touchstart', touchStart);\n                $elm.off('touchend', touchEnd);\n                $elm.off('click', selectCells);\n\n                $scope.registered = false;\n              }\n            }\n\n            registerRowSelectionEvents();\n            // register a dataChange callback so that we can change the selection configuration dynamically\n            // if the user changes the options\n            var dataChangeDereg = $scope.grid.registerDataChangeCallback( function() {\n              if ( $scope.grid.options.enableRowSelection && !$scope.grid.options.enableRowHeaderSelection &&\n                !$scope.registered ){\n                registerRowSelectionEvents();\n              } else if ( ( !$scope.grid.options.enableRowSelection || $scope.grid.options.enableRowHeaderSelection ) &&\n                $scope.registered ){\n                deregisterRowSelectionEvents();\n              }\n            }, [uiGridConstants.dataChange.OPTIONS] );\n\n            $elm.on( '$destroy', dataChangeDereg);\n          }\n        };\n      }]);\n\n  module.directive('uiGridGridFooter', ['$compile', 'uiGridConstants', 'gridUtil', function ($compile, uiGridConstants, gridUtil) {\n    return {\n      restrict: 'EA',\n      replace: true,\n      priority: -1000,\n      require: '^uiGrid',\n      scope: true,\n      compile: function ($elm, $attrs) {\n        return {\n          pre: function ($scope, $elm, $attrs, uiGridCtrl) {\n\n            if (!uiGridCtrl.grid.options.showGridFooter) {\n              return;\n            }\n\n\n            gridUtil.getTemplate('ui-grid/gridFooterSelectedItems')\n              .then(function (contents) {\n                var template = angular.element(contents);\n\n                var newElm = $compile(template)($scope);\n\n                angular.element($elm[0].getElementsByClassName('ui-grid-grid-footer')[0]).append(newElm);\n              });\n          },\n\n          post: function ($scope, $elm, $attrs, controllers) {\n\n          }\n        };\n      }\n    };\n  }]);\n\n})();\n\nangular.module('ui.grid').run(['$templateCache', function($templateCache) {\n  'use strict';\n\n  $templateCache.put('ui-grid/ui-grid-footer',\n    \"<div class=\\\"ui-grid-footer-panel ui-grid-footer-aggregates-row\\\"><div class=\\\"ui-grid-footer ui-grid-footer-viewport\\\"><div class=\\\"ui-grid-footer-canvas\\\"><div ng-repeat=\\\"col in colContainer.renderedColumns track by col.colDef.name\\\" ui-grid-footer-cell col=\\\"col\\\" render-index=\\\"$index\\\" class=\\\"ui-grid-footer-cell ui-grid-clearfix\\\" ng-style=\\\"$index === 0 && colContainer.columnStyle($index)\\\"></div></div></div></div>\"\n  );\n\n\n  $templateCache.put('ui-grid/ui-grid-grid-footer',\n    \"<div class=\\\"ui-grid-footer-info ui-grid-grid-footer\\\"><span>{{'search.totalItems' | t}} {{grid.rows.length}}</span> <span ng-if=\\\"grid.renderContainers.body.visibleRowCache.length !== grid.rows.length\\\" class=\\\"ngLabel\\\">({{\\\"search.showingItems\\\" | t}} {{grid.renderContainers.body.visibleRowCache.length}})</span></div>\"\n  );\n\n\n  $templateCache.put('ui-grid/ui-grid-group-panel',\n    \"<div class=\\\"ui-grid-group-panel\\\"><div ui-t=\\\"groupPanel.description\\\" class=\\\"description\\\" ng-show=\\\"groupings.length == 0\\\"></div><ul ng-show=\\\"groupings.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>\"\n  );\n\n\n  $templateCache.put('ui-grid/ui-grid-header',\n    \"<div class=\\\"ui-grid-header\\\"><div class=\\\"ui-grid-top-panel\\\"><div class=\\\"ui-grid-header-viewport\\\"><div class=\\\"ui-grid-header-canvas\\\"><div class=\\\"ui-grid-header-cell ui-grid-clearfix\\\" ng-repeat=\\\"col in colContainer.renderedColumns track by col.colDef.name\\\" ui-grid-header-cell col=\\\"col\\\" render-index=\\\"$index\\\" ng-style=\\\"$index === 0 && colContainer.columnStyle($index)\\\"></div></div></div><div ui-grid-menu></div></div></div>\"\n  );\n\n\n  $templateCache.put('ui-grid/ui-grid-menu-button',\n    \"<div class=\\\"ui-grid-menu-button\\\" ng-click=\\\"toggleMenu()\\\"><div class=\\\"ui-grid-icon-container\\\"><i class=\\\"ui-grid-icon-menu\\\">&nbsp;</i></div><div ui-grid-menu menu-items=\\\"menuItems\\\"></div></div>\"\n  );\n\n\n  $templateCache.put('ui-grid/ui-grid-no-header',\n    \"<div class=\\\"ui-grid-top-panel\\\"></div>\"\n  );\n\n\n  $templateCache.put('ui-grid/ui-grid-row',\n    \"<div ng-repeat=\\\"(colRenderIndex, col) in colContainer.renderedColumns track by col.colDef.name\\\" class=\\\"ui-grid-cell\\\" ng-class=\\\"{ 'ui-grid-row-header-cell': col.isRowHeader }\\\" ui-grid-cell></div>\"\n  );\n\n\n  $templateCache.put('ui-grid/ui-grid',\n    \"<div ui-i18n=\\\"en\\\" class=\\\"ui-grid\\\"><!-- TODO (c0bra): add \\\"scoped\\\" attr here, eventually? --><style ui-grid-style>.grid{{ grid.id }} {\\n\" +\n    \"      /* Styles for the grid */\\n\" +\n    \"    }\\n\" +\n    \"\\n\" +\n    \"    .grid{{ grid.id }} .ui-grid-row, .grid{{ grid.id }} .ui-grid-cell, .grid{{ grid.id }} .ui-grid-cell .ui-grid-vertical-bar {\\n\" +\n    \"      height: {{ grid.options.rowHeight }}px;\\n\" +\n    \"    }\\n\" +\n    \"\\n\" +\n    \"    .grid{{ grid.id }} .ui-grid-row:last-child .ui-grid-cell {\\n\" +\n    \"      border-bottom-width: {{ ((grid.getTotalRowHeight() < grid.getViewportHeight()) && '1') || '0' }}px;\\n\" +\n    \"    }\\n\" +\n    \"\\n\" +\n    \"    {{ grid.verticalScrollbarStyles }}\\n\" +\n    \"    {{ grid.horizontalScrollbarStyles }}\\n\" +\n    \"\\n\" +\n    \"    /*\\n\" +\n    \"    .ui-grid[dir=rtl] .ui-grid-viewport {\\n\" +\n    \"      padding-left: {{ grid.verticalScrollbarWidth }}px;\\n\" +\n    \"    }\\n\" +\n    \"    */\\n\" +\n    \"\\n\" +\n    \"    {{ grid.customStyles }}</style><div ui-grid-menu-button ng-if=\\\"grid.options.enableGridMenu\\\"></div><div ng-if=\\\"grid.hasLeftContainer()\\\" style=\\\"width: 0\\\" ui-grid-pinned-container=\\\"'left'\\\"></div><div ui-grid-render-container container-id=\\\"'body'\\\" col-container-name=\\\"'body'\\\" row-container-name=\\\"'body'\\\" bind-scroll-horizontal=\\\"true\\\" bind-scroll-vertical=\\\"true\\\" enable-horizontal-scrollbar=\\\"grid.options.enableHorizontalScrollbar\\\" enable-vertical-scrollbar=\\\"grid.options.enableVerticalScrollbar\\\"></div><div ng-if=\\\"grid.hasRightContainer()\\\" style=\\\"width: 0\\\" ui-grid-pinned-container=\\\"'right'\\\"></div><div ui-grid-grid-footer ng-if=\\\"grid.options.showGridFooter\\\"></div><div ui-grid-column-menu ng-if=\\\"grid.options.enableColumnMenus\\\"></div><div ng-transclude></div></div>\"\n  );\n\n\n  $templateCache.put('ui-grid/uiGridCell',\n    \"<div class=\\\"ui-grid-cell-contents\\\">{{COL_FIELD CUSTOM_FILTERS}}</div>\"\n  );\n\n\n  $templateCache.put('ui-grid/uiGridColumnFilter',\n    \"<li class=\\\"ui-grid-menu-item ui-grid-clearfix ui-grid-column-filter\\\" ng-show=\\\"itemShown()\\\" ng-click=\\\"$event.stopPropagation();\\\"><div class=\\\"input-container\\\"><input class=\\\"column-filter-input\\\" type=\\\"text\\\" ng-model=\\\"item.model\\\" placeholder=\\\"{{ i18n.search.placeholder }}\\\"><div class=\\\"column-filter-cancel-icon-container\\\"><i class=\\\"ui-grid-filter-cancel ui-grid-icon-cancel column-filter-cancel-icon\\\">&nbsp;</i></div></div><div style=\\\"button-container\\\" ng-click=\\\"item.action($event)\\\"><div class=\\\"ui-grid-button\\\"><i class=\\\"ui-grid-icon-search\\\">&nbsp;</i></div></div></li>\"\n  );\n\n\n  $templateCache.put('ui-grid/uiGridColumnMenu',\n    \"<div class=\\\"ui-grid-column-menu\\\"><div ui-grid-menu menu-items=\\\"menuItems\\\"><!-- <div class=\\\"ui-grid-column-menu\\\">\\n\" +\n    \"    <div class=\\\"inner\\\" ng-show=\\\"menuShown\\\">\\n\" +\n    \"      <ul>\\n\" +\n    \"        <div ng-show=\\\"grid.options.enableSorting\\\">\\n\" +\n    \"          <li ng-click=\\\"sortColumn($event, asc)\\\" ng-class=\\\"{ 'selected' : col.sort.direction == asc }\\\"><i class=\\\"ui-grid-icon-sort-alt-up\\\"></i> Sort Ascending</li>\\n\" +\n    \"          <li ng-click=\\\"sortColumn($event, desc)\\\" ng-class=\\\"{ 'selected' : col.sort.direction == desc }\\\"><i class=\\\"ui-grid-icon-sort-alt-down\\\"></i> Sort Descending</li>\\n\" +\n    \"          <li ng-show=\\\"col.sort.direction\\\" ng-click=\\\"unsortColumn()\\\"><i class=\\\"ui-grid-icon-cancel\\\"></i> Remove Sort</li>\\n\" +\n    \"        </div>\\n\" +\n    \"      </ul>\\n\" +\n    \"    </div>\\n\" +\n    \"  </div> --></div></div>\"\n  );\n\n\n  $templateCache.put('ui-grid/uiGridFooterCell',\n    \"<div class=\\\"ui-grid-cell-contents\\\" col-index=\\\"renderIndex\\\"><div>{{ col.getAggregationText() + ( col.getAggregationValue() CUSTOM_FILTERS ) }}</div></div>\"\n  );\n\n\n  $templateCache.put('ui-grid/uiGridHeaderCell',\n    \"<div ng-class=\\\"{ 'sortable': sortable }\\\"><!-- <div class=\\\"ui-grid-vertical-bar\\\">&nbsp;</div> --><div class=\\\"ui-grid-cell-contents\\\" col-index=\\\"renderIndex\\\"><span>{{ col.displayName CUSTOM_FILTERS }}</span> <span ui-grid-visible=\\\"col.sort.direction\\\" ng-class=\\\"{ 'ui-grid-icon-up-dir': col.sort.direction == asc, 'ui-grid-icon-down-dir': col.sort.direction == desc, 'ui-grid-icon-blank': !col.sort.direction }\\\">&nbsp;</span></div><div class=\\\"ui-grid-column-menu-button\\\" ng-if=\\\"grid.options.enableColumnMenus && !col.isRowHeader  && col.colDef.enableColumnMenu !== false\\\" ng-click=\\\"toggleMenu($event)\\\" ng-class=\\\"{'ui-grid-column-menu-button-last-col': isLastCol}\\\"><i class=\\\"ui-grid-icon-angle-down\\\">&nbsp;</i></div><div ng-if=\\\"filterable\\\" class=\\\"ui-grid-filter-container\\\" ng-repeat=\\\"colFilter in col.filters\\\"><input type=\\\"text\\\" class=\\\"ui-grid-filter-input\\\" ng-model=\\\"colFilter.term\\\" ng-attr-placeholder=\\\"{{colFilter.placeholder || ''}}\\\"><div class=\\\"ui-grid-filter-button\\\" ng-click=\\\"colFilter.term = null\\\"><i class=\\\"ui-grid-icon-cancel\\\" ng-show=\\\"!!colFilter.term\\\">&nbsp;</i><!-- use !! because angular interprets 'f' as false --></div></div></div>\"\n  );\n\n\n  $templateCache.put('ui-grid/uiGridMenu',\n    \"<div class=\\\"ui-grid-menu\\\" ng-if=\\\"shown\\\"><div class=\\\"ui-grid-menu-mid\\\" ng-show=\\\"shownMid\\\"><div class=\\\"ui-grid-menu-inner\\\"><ul class=\\\"ui-grid-menu-items\\\"><li ng-repeat=\\\"item in menuItems\\\" ui-grid-menu-item action=\\\"item.action\\\" name=\\\"item.title\\\" active=\\\"item.active\\\" icon=\\\"item.icon\\\" shown=\\\"item.shown\\\" context=\\\"item.context\\\" template-url=\\\"item.templateUrl\\\"></li></ul></div></div></div>\"\n  );\n\n\n  $templateCache.put('ui-grid/uiGridMenuItem',\n    \"<li class=\\\"ui-grid-menu-item\\\" ng-click=\\\"itemAction($event, title)\\\" ng-show=\\\"itemShown()\\\" ng-class=\\\"{ 'ui-grid-menu-item-active' : active() }\\\"><i ng-class=\\\"icon\\\"></i> {{ name }}</li>\"\n  );\n\n\n  $templateCache.put('ui-grid/uiGridRenderContainer',\n    \"<div class=\\\"ui-grid-render-container\\\"><div ui-grid-header></div><div ui-grid-viewport></div><div ui-grid-footer ng-if=\\\"grid.options.showColumnFooter\\\"></div></div>\"\n  );\n\n\n  $templateCache.put('ui-grid/uiGridViewport',\n    \"<div class=\\\"ui-grid-viewport\\\" ng-style=\\\"containerCtrl.colContainer.getViewPortStyle()\\\"><div class=\\\"ui-grid-canvas\\\"><div ng-repeat=\\\"(rowRenderIndex, row) in rowContainer.renderedRows track by $index\\\" class=\\\"ui-grid-row\\\" ng-style=\\\"containerCtrl.rowStyle(rowRenderIndex)\\\"><div ui-grid-row=\\\"row\\\" row-render-index=\\\"rowRenderIndex\\\"></div></div></div></div>\"\n  );\n\n\n  $templateCache.put('ui-grid/cellEditor',\n    \"<div><form name=\\\"inputForm\\\"><input type=\\\"INPUT_TYPE\\\" ng-class=\\\"'colt' + col.uid\\\" ui-grid-editor ng-model=\\\"MODEL_COL_FIELD\\\"></form></div>\"\n  );\n\n\n  $templateCache.put('ui-grid/dropdownEditor',\n    \"<div><form name=\\\"inputForm\\\"><select ng-class=\\\"'colt' + col.uid\\\" ui-grid-edit-dropdown ng-model=\\\"MODEL_COL_FIELD\\\" ng-options=\\\"field[editDropdownIdLabel] as field[editDropdownValueLabel] CUSTOM_FILTERS for field in editDropdownOptionsArray\\\"></select></form></div>\"\n  );\n\n\n  $templateCache.put('ui-grid/expandableRow',\n    \"<div ui-grid-expandable-row ng-if=\\\"expandableRow.shouldRenderExpand()\\\" class=\\\"expandableRow\\\" style=\\\"float:left; margin-top: 1px; margin-bottom: 1px\\\" ng-style=\\\"{width: (grid.renderContainers.body.getCanvasWidth()) + 'px'\\n\" +\n    \"     , height: grid.options.expandableRowHeight + 'px'}\\\"></div>\"\n  );\n\n\n  $templateCache.put('ui-grid/expandableRowHeader',\n    \"<div class=\\\"ui-grid-row-header-cell ui-grid-expandable-buttons-cell\\\"><div class=\\\"ui-grid-cell-contents\\\"><i ng-class=\\\"{ 'ui-grid-icon-plus-squared' : !row.isExpanded, 'ui-grid-icon-minus-squared' : row.isExpanded }\\\" ng-click=\\\"grid.api.expandable.toggleRowExpansion(row.entity)\\\"></i></div></div>\"\n  );\n\n\n  $templateCache.put('ui-grid/expandableScrollFiller',\n    \"<div ng-if=\\\"expandableRow.shouldRenderFiller()\\\" style=\\\"float:left; margin-top: 2px; margin-bottom: 2px\\\" ng-style=\\\"{ width: (grid.getViewportWidth()) + 'px',\\n\" +\n    \"              height: grid.options.expandableRowHeight + 'px', 'margin-left': grid.options.rowHeader.rowHeaderWidth + 'px' }\\\"><i class=\\\"ui-grid-icon-spin5 ui-grid-animate-spin\\\" ng-style=\\\"{ 'margin-top': ( grid.options.expandableRowHeight/2 - 5) + 'px',\\n\" +\n    \"            'margin-left' : ((grid.getViewportWidth() - grid.options.rowHeader.rowHeaderWidth)/2 - 5) + 'px' }\\\"></i></div>\"\n  );\n\n\n  $templateCache.put('ui-grid/expandableTopRowHeader',\n    \"<div class=\\\"ui-grid-row-header-cell ui-grid-expandable-buttons-cell\\\"><div class=\\\"ui-grid-cell-contents\\\"><i ng-class=\\\"{ 'ui-grid-icon-plus-squared' : !grid.expandable.expandedAll, 'ui-grid-icon-minus-squared' : grid.expandable.expandedAll }\\\" ng-click=\\\"grid.api.expandable.toggleAllRows()\\\"></i></div></div>\"\n  );\n\n\n  $templateCache.put('ui-grid/csvLink',\n    \"<span class=\\\"ui-grid-exporter-csv-link-span\\\"><a href=\\\"data:text/csv;charset=UTF-8,CSV_CONTENT\\\" download=\\\"FILE_NAME\\\">LINK_LABEL</a></span>\"\n  );\n\n\n  $templateCache.put('ui-grid/importerMenuItem',\n    \"<li class=\\\"ui-grid-menu-item\\\"><form><input class=\\\"ui-grid-importer-file-chooser\\\" type=\\\"file\\\" id=\\\"files\\\" name=\\\"files[]\\\"></form></li>\"\n  );\n\n\n  $templateCache.put('ui-grid/importerMenuItemContainer',\n    \"<div ui-grid-importer-menu-item></div>\"\n  );\n\n\n  $templateCache.put('ui-grid/pagination',\n    \"<div class=\\\"ui-grid-pager-panel\\\" ui-grid-pager ng-show=\\\"grid.options.enablePaginationControls\\\"><div class=\\\"ui-grid-pager-container\\\"><div class=\\\"ui-grid-pager-control\\\"><button type=\\\"button\\\" ng-click=\\\"paginationApi.seek(1)\\\" ng-disabled=\\\"cantPageBackward()\\\"><div class=\\\"first-triangle\\\"><div class=\\\"first-bar\\\"></div></div></button> <button type=\\\"button\\\" ng-click=\\\"paginationApi.previousPage()\\\" ng-disabled=\\\"cantPageBackward()\\\"><div class=\\\"first-triangle prev-triangle\\\"></div></button> <input type=\\\"number\\\" ng-model=\\\"grid.options.paginationCurrentPage\\\" min=\\\"1\\\" max=\\\"{{ paginationApi.getTotalPages() }}\\\" required> <span class=\\\"ui-grid-pager-max-pages-number\\\" ng-show=\\\"paginationApi.getTotalPages() > 0\\\">/ {{ paginationApi.getTotalPages() }}</span> <button type=\\\"button\\\" ng-click=\\\"paginationApi.nextPage()\\\" ng-disabled=\\\"cantPageForward()\\\"><div class=\\\"last-triangle next-triangle\\\"></div></button> <button type=\\\"button\\\" ng-click=\\\"paginationApi.seek(paginationApi.getTotalPages())\\\" ng-disabled=\\\"cantPageToLast()\\\"><div class=\\\"last-triangle\\\"><div class=\\\"last-bar\\\"></div></div></button></div><div class=\\\"ui-grid-pager-row-count-picker\\\"><select ng-model=\\\"grid.options.paginationPageSize\\\" ng-options=\\\"o as o for o in grid.options.paginationPageSizes\\\"></select><span class=\\\"ui-grid-pager-row-count-label\\\">&nbsp;{{sizesLabel}}</span></div></div><div class=\\\"ui-grid-pager-count-container\\\"><div class=\\\"ui-grid-pager-count\\\"><span ng-show=\\\"grid.options.totalItems > 0\\\">{{showingLow}} - {{showingHigh}} of {{grid.options.totalItems}} {{totalItemsLabel}}</span></div></div></div>\"\n  );\n\n\n  $templateCache.put('ui-grid/columnResizer',\n    \"<div ui-grid-column-resizer ng-if=\\\"grid.options.enableColumnResizing\\\" class=\\\"ui-grid-column-resizer\\\" col=\\\"col\\\" position=\\\"right\\\" render-index=\\\"renderIndex\\\"></div>\"\n  );\n\n\n  $templateCache.put('ui-grid/gridFooterSelectedItems',\n    \"<span ng-if=\\\"grid.selection.selectedCount !== 0 && grid.options.enableFooterTotalSelected\\\">({{\\\"search.selectedItems\\\" | t}} {{grid.selection.selectedCount}})</span>\"\n  );\n\n\n  $templateCache.put('ui-grid/selectionHeaderCell',\n    \"<div><!-- <div class=\\\"ui-grid-vertical-bar\\\">&nbsp;</div> --><div class=\\\"ui-grid-cell-contents\\\" col-index=\\\"renderIndex\\\"><ui-grid-selection-select-all-buttons ng-if=\\\"grid.options.enableSelectAll\\\"></ui-grid-selection-select-all-buttons></div></div>\"\n  );\n\n\n  $templateCache.put('ui-grid/selectionRowHeader',\n    \"<div class=\\\"ui-grid-disable-selection\\\"><div class=\\\"ui-grid-cell-contents\\\"><ui-grid-selection-row-header-buttons></ui-grid-selection-row-header-buttons></div></div>\"\n  );\n\n\n  $templateCache.put('ui-grid/selectionRowHeaderButtons',\n    \"<div class=\\\"ui-grid-selection-row-header-buttons ui-grid-icon-ok\\\" ng-class=\\\"{'ui-grid-row-selected': row.isSelected}\\\" ng-click=\\\"selectButtonClick(row, $event)\\\">&nbsp;</div>\"\n  );\n\n\n  $templateCache.put('ui-grid/selectionSelectAllButtons',\n    \"<div class=\\\"ui-grid-selection-row-header-buttons ui-grid-icon-ok\\\" ng-class=\\\"{'ui-grid-all-selected': grid.selection.selectAll}\\\" ng-click=\\\"headerButtonClick($event)\\\"></div>\"\n  );\n\n}]);\n"
  },
  {
    "path": "flowable-ui-web/task/manifest.json",
    "content": "{\n\t\"name\": \"\",\n\t\"icons\": [\n\t\t{\n\t\t\t\"src\": \"images\\/android-chrome-192x192.png?v=Om5N75Y123\",\n\t\t\t\"sizes\": \"192x192\",\n\t\t\t\"type\": \"image\\/png\"\n\t\t},\n\t\t{\n\t\t\t\"src\": \"images\\/android-chrome-384x384.png?v=Om5N75Y123\",\n\t\t\t\"sizes\": \"384x384\",\n\t\t\t\"type\": \"image\\/png\"\n\t\t}\n\t],\n\t\"theme_color\": \"#ffffff\",\n\t\"display\": \"standalone\"\n}\n"
  },
  {
    "path": "flowable-ui-web/task/scripts/app-cfg.js",
    "content": "/* Copyright 2005-2015 Alfresco Software, Ltd.\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'use strict';\n\nvar FLOWABLE = FLOWABLE || {};\n\nvar pathname = window.location.pathname.replace(/^(\\/[^\\/]*)(\\/.*)?$/, '$1').replace(/\\/$/, '');\n\nFLOWABLE.CONFIG = {\n\t'onPremise' : true,\n\t'contextRoot' : '/flowable_task',\n\t'webContextRoot' : pathname,\n    'datesLocalization' : false\n};\n\n//\n// DEV ENV OVERRIDES\n//\n\n"
  },
  {
    "path": "flowable-ui-web/task/scripts/common/controllers/about.js",
    "content": "/* 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'use strict';\n\nflowableApp.controller('AboutFlowablePopupCtrl', ['$rootScope', '$scope', '$http', '$translate', '$interval', '$dateFormatter', function($rootScope, $scope, $http, $translate, $interval, $dateFormatter) {\n    $scope.popup = {\n        loading: true,\n        activitiVersion: {},\n        licenseHolder: ''\n    };\n\n    $http({method: 'GET', url: FLOWABLE.CONFIG.contextRoot + '/app/rest/about-info'}).\n        success(function(response, status, headers, config) {\n            $scope.popup.licenseHolder = response.holder;\n            $scope.popup.activitiVersion = response.versionInfo.edition + ' v' + response.versionInfo.majorVersion + '.' + response.versionInfo.minorVersion + '.' + response.versionInfo.revisionVersion;\n            $scope.popup.activitiVersionType = response.versionInfo.type;\n            if (response.goodBeforeDate) {\n                $scope.popup.goodBeforeDate = $dateFormatter.formatDate(new Date(response.goodBeforeDate));\n            }\n            $scope.popup.loading = false;\n        }).\n        error(function(response, status, headers, config) {\n            $scope.popup.loading = false;\n        });\n\n\n    $scope.cancel = function() {\n        $scope.close();\n    };\n\n\n    $scope.close = function() {\n        $scope.$hide();\n    }\n\n}]);"
  },
  {
    "path": "flowable-ui-web/task/scripts/common/directives.js",
    "content": "/* 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 */\nflowableModule\n  .directive('restrictInput', [\"$parse\", function ($parse) {\n    return {\n      restrict: 'A',\n      require: 'ngModel',\n      priority: 1002,\n\n      link: function postLink(scope, elm, attrs, ctrl) {\n\n        var acceptedFormat = attrs[\"restrictInput\"];\n        if (acceptedFormat == undefined || acceptedFormat == null || acceptedFormat == \"\") {\n           acceptedFormat = attrs[\"dateFormat\"];\n        }\n\n        scope.field.acceptedFormat=acceptedFormat;\n\n        function calculateAcceptedFormats(format) {\n          var format1 = format.toUpperCase(); //d-m-yyyy\n          var format2 = format1.replace(/-D-/,\"-DD-\").replace(/^D-/,\"DD-\").replace(/-D$/,\"-DD\"); //dd-m-yyyy\n          var format3 = format1.replace(/-M-/,\"-MM-\").replace(/^M-/,\"MM-\").replace(/-M$/,\"-MM\");  //d-mm-yyyy\n          var format4 = format2.replace(/-M-/,\"-MM-\").replace(/^M-/,\"MM-\").replace(/-M$/,\"-MM\");  //dd-mm-yyyy\n          return [format1,format2,format3,format4];\n        }\n\n        var acceptedFormats = calculateAcceptedFormats(acceptedFormat);\n        var skipValidation = false;\n\n        if (acceptedFormat == undefined || acceptedFormat == null || acceptedFormat == \"\") {\n          skipValidation = true;\n        }\n        var oldRenderer = ctrl.$render;\n\n        ctrl.$render = function () {\n          elm.val(ctrl.$viewValue);\n          if (ctrl.$dateValue && !isNaN(ctrl.$dateValue.getTime())) {\n            if (oldRenderer) {\n              oldRenderer();\n            }\n          }\n        };\n\n        function isValidText(viewValue, format) {\n          if (viewValue === undefined || viewValue == null || viewValue ==='') return true;\n          if (viewValue.length > format.length) return false;\n\n           for (var i = 0; i < Math.min(format.length, viewValue.length); i++) {\n             var charType = format[i];\n             if (charType.toUpperCase().match(/D|M|Y/)) {\n               if (viewValue[i].match(/\\d/) == null) return false;\n             }else {\n               if (viewValue[i] != charType) return false;\n             }\n           }\n           return true;\n         }\n\n        ctrl.$parsers.unshift(function (viewValue) {\n\n          if (skipValidation) return viewValue; //just skip this parser\n\n          var isValid = false;\n          for(var i =0 ; i < acceptedFormats.length && !isValid; i++){\n            isValid |= isValidText(viewValue,acceptedFormats[i]);\n          }\n\n          if (!isValid) {\n            //should restore to the latest known well formated date.\n            ctrl.$dateValue = null;\n          } else {\n            ctrl.$lastValidText = viewValue;\n\n              //by default the date picker in angular strap does not reset the dateValue if the viewValue is null or empty.\n              if (viewValue === undefined || viewValue == null || viewValue === '') {\n                  ctrl.$dateValue = null;\n              }\n\n            return viewValue;\n          }\n\n          ctrl.$setViewValue(ctrl.$lastValidText);\n          ctrl.$render();\n          return ctrl.$lastValidText;\n        });\n\n      }\n    }\n  }\n  ]);\n\n\nflowableModule\n    .directive('autoHeight', ['$rootScope', '$timeout', function($rootScope, $timeout) {\n        return {\n            restrict: 'AC',\n            scope: {\n              'toWatch': '=autoHeight'\n            },\n            compile: function (element, attr) {\n                return function ($scope, $element, $attrs) {\n                    var offset = 0;\n                    if($attrs['offset']) {\n                        offset = parseInt($attrs['offset']);\n                        if(isNaN(offset) || offset == undefined) {\n                            offset = 0;\n                        }\n                    }\n\n                    var update = function($element) {\n                        // Get hold of parent and iterate all the children to get available height\n\n                        $timeout(function() {\n                            var total = $element.parent().outerHeight() - offset;\n                            var found = false;\n                            $element.parent().children().each(function() {\n                                if(!found) {\n                                    if($element[0] == this) {\n                                        found = true;\n                                    } else {\n                                        // Substract preceding child's height\n                                        total -= angular.element(this).outerHeight();\n                                    }\n                                }\n                            });\n\n                            if(found) {\n                                $element.height(total);\n                            }\n                        }, 0);\n                    };\n\n                    if($scope.unregisterWatcher) {\n                        $scope.unregisterWatcher();\n                    }\n                    $scope.unregisterWatcher = $rootScope.$watch('window.height', function(windowHeight) {\n                        update($element);\n                    });\n\n                    if($scope.unregisterForceWatcher) {\n                        $scope.unregisterForceWatcher();\n                    }\n                    $scope.unregisterForceWatcher = $rootScope.$watch('window.forceRefresh', function(forceValue) {\n                        update($element);\n                    });\n\n\n                    $scope.$on('$destroy', function() {\n                        // Cleanup watcher for window-height\n                        if($scope.unregisterWatcher) {\n                            $scope.unregisterWatcher();\n                        }\n                        if($scope.unregisterForceWatcher) {\n                            $scope.unregisterForceWatcher();\n                        }\n                    });\n                }\n            }\n        };\n    }]);\n\n/**\n * Directive that ensures the child-element with class .active is visible and scrolls if needed. Watches the value\n * of the directive and will re-apply if this value is changes.\n */\nflowableModule\n    .directive('scrollToActive', ['$timeout', function($timeout) {\n        return {\n            restrict: 'AC',\n            scope: {\n                toWatch: \"=scrollToActiveModel\"\n            },\n            compile: function (element, attr) {\n                return function ($scope, $element, $attrs) {\n                    $scope.$watch('toWatch', function() {\n                        $timeout(function() {\n                            var useParent = $attrs['useParent'];\n                            var offsetTop = $attrs['offsetTop'];\n                            if(offsetTop) {\n                                offsetTop = parseInt(offsetTop);\n                                if(isNaN(offsetTop)) {\n                                    offsetTop = 0;\n                                }\n                            }\n                            if (!offsetTop) {\n                                offsetTop = 0;\n                            }\n\n                            var selectedArr = $element.children('.active');\n                            if(selectedArr && selectedArr.length > 0) {\n                                var selected = angular.element(selectedArr[0]);\n\n                                if(useParent) {\n                                    $element = angular.element($element.parent());\n                                }\n                                var selectedTop = selected.position().top - $element.position().top + $element.scrollTop();\n                                var selectedBottom = selectedTop + selected.outerHeight();\n                                var elementBottom = $element.scrollTop() + $element.innerHeight();\n                                var elementTop = elementBottom - $element.innerHeight();\n\n                                if(selectedTop <= elementTop) {\n                                    // scroll up\n                                    $element.scrollTop(selectedTop - selected.outerHeight() - offsetTop);\n                                } else if(selectedBottom > elementBottom) {\n                                    // scroll down\n                                    $element.scrollTop(elementTop + selected.outerHeight() - offsetTop);\n                                }\n                            }\n                        }, 0);\n                    });\n                }\n            }\n        };\n    }]);\n\n/**\n * Directive that ensures the popup is scrolled into view, using the first parent as scroll-pane that has\n * a class 'scroll-container' set on it. Is applied when the popup is shown.\n */\nflowableModule\n    .directive('autoScroll', ['$timeout', function($timeout) {\n        return {\n            restrict: 'AC',\n            compile: function (element, attr) {\n                return function ($scope, $element, $attrs) {\n                    $scope.$on('tooltip.show', function() {\n                        $timeout(function() {\n                            // Find appropriate parent\n                            var parent = $element[0];\n                            while(parent) {\n                                if(parent.className && parent.className.indexOf('scroll-container') >= 0) {\n                                    break;\n                                }\n                                parent = parent.parentNode;\n                            }\n\n                            if(parent) {\n                                parent = angular.element(parent);\n                                var selectedTop = $element.offset().top  - parent.offset().top + $element.scrollTop();\n                                var selectedBottom = selectedTop + $element.outerHeight();\n\n                                if(selectedBottom + 30 >= parent.outerHeight()) {\n                                    parent.scrollTop(selectedTop);\n                                }\n                            }\n                        }, 50);\n                    });\n                }\n            }\n        };\n    }]);\n\nflowableModule\n    .directive('userName', function() {\n        var directive = {};\n        directive.template = '{{user.firstName && user.firstName != \"null\" ? user.firstName : \"\"}} {{user.lastName && user.lastName != \"null\" ? user.lastName : \"\"}} {{ (user.email && !user.firstName && !user.lastName) && user.email || \"\"}}';\n        directive.scope = {\n            user: \"=userName\"\n        };\n        return directive;\n    });\n\n\n/**\n * Executes the method that is set on the directive attribute value when ANY OTHER element is clicked, which is not the element the\n * directive is on, or any of it's children.\n *\n */\nflowableModule\n    .directive('clickAnywhere', [\"$document\", \"$parse\", function ($document, $parse) {\n\n        var linkFunction = function ($scope, $element, $attributes) {\n\n            var scopeExpression = $attributes.clickAnywhere;\n            var invoker = $parse(scopeExpression);\n\n            var ignoreId = $attributes.ignore;\n            var ignoreClass = $attributes.ignoreClass;\n            var ignorePopupEvents = $attributes.ignorePopupEvents == 'true';\n\n            var handler = function (event) {\n                // Check source of event\n                var parent = event.target;\n                while(parent) {\n                    if(parent == $element[0] ||\n                        (ignoreId && parent.id == ignoreId) ||\n                        (ignoreClass && parent.className && parent.className.indexOf(ignoreClass) >= 0)) {\n\n                        event.stopPropagation();\n                        event.preventDefault();\n                        return;\n                    }\n                    parent = parent.parentNode;\n                }\n\n                $scope.$apply(\n                    function () {\n                        invoker($scope, {$event: event});\n                    }\n                );\n            };\n\n            $document.on(\"click\", handler);\n\n            $scope.$on('$destroy', function () {\n                $document.off(\"click\", handler);\n            });\n\n            // Special handling for tooltips which don't destroy the scope\n            var hideReg = $scope.$on('tooltip.hide', function () {\n                if(!ignorePopupEvents) {\n                    $document.off(\"click\", handler);\n                    hideReg();\n                }\n            });\n\n        };\n\n        // Return the linking function.\n        return( linkFunction );\n    }\n    ]);\n\n\n\n\nflowableModule\n    .directive('autoFocus', ['$timeout', '$parse', function($timeout, $parse) {\n        return {\n            restrict: 'AC',\n            compile: function($element, attr) {\n                var selectText;\n\n                if(attr[\"selectText\"]) {\n                    selectText = $parse(attr[\"selectText\"]);\n                }\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                                if(selectText && selectText(_scope.$parent)) {\n                                    input[0].setSelectionRange(0,input[0].value.length);\n                                }\n                            }\n                        } else {\n                            // Focus element where the directive is put on\n                            _element[0].focus();\n                            if(selectText && selectText(_scope.$parent)) {\n                                _element[0].setSelectionRange(0,_element[0].value.length);\n                            }\n                        }\n                    }, 100);\n                }\n            }\n        };\n    }]);\n\nflowableModule\n    .directive('focusWhen', ['$timeout', function ($timeout) {\n        return {\n            link: function (scope, element, attrs) {\n                scope.$watch(attrs.ngFocus, function (val) {\n                    if (angular.isDefined(val) && val) {\n                        $timeout(function () {\n                            element[0].focus();\n                        });\n                    }\n                }, true);\n\n                element.bind('blur', function () {\n                    if (angular.isDefined(attrs.ngFocusLost)) {\n                        scope.safeApply(attrs.ngFocusLost);\n                    }\n                });\n            }\n        };\n    }]);\n\n\nflowableModule\n    .directive('loading', [function() {\n        var directive = {};\n        directive.restrict = 'A';\n        directive.template = '<div class=\"loading\" ng-show=\"loading\"><div class=\"l1\"></div><div class=\"l2\"></div><div class=\"l3\"></div></div>';\n        directive.scope = {\n            loading : \"=loading\",\n            loadingText: \"=loadingText\"\n        };\n        return directive;\n    }]);\n\n// Workaround for https://github.com/twbs/bootstrap/issues/8379 :\n// prototype.js interferes with regular dropdown behavior\nflowableModule\n    .directive('activitiFixDropdownBug', function() {\n        return {\n            restrict: 'AEC',\n            link: function(scope, element, attrs) {\n                element.on('hidden.bs.dropdown\t', function () {\n                    element.show(); // evil prototype.js has added display:none to it ...\n                })\n            }\n        };\n    });\n\n/**\n * Directive for rendering user link.\n */\nflowableModule\n  .directive('userLink', function() {\n    var directive = {};\n    directive.template = '{{user.firstName && user.firstName || \"\"}} {{user.lastName && user.lastName || \"\"}} {{ (user.email && !user.firstName && !user.lastName) && user.email || \"\"}}';\n    directive.scope = {\n        user: \"=userLink\"\n    };\n\n    directive.compile = function(element, attributes) {\n        element.addClass('people-link');\n    };\n\n    return directive;\n});\n\n/**\n * Directive for rendering a form field.\n */\nflowableModule\n    .directive('formField', function () {\n        var directive = {};\n\n        directive.template = ' {{field.name || \"\"}} - {{field.id}}';\n        directive.scope = {\n            field: \"=formField\"\n        };\n\n        directive.compile = function (element, attributes) {\n            element.addClass('form-field');\n        };\n        return directive;\n    });\n/**\n * Directive to capture mouse up, down, enter and escape on input fields (eg. list navigation)\n */\nflowableModule\n    .directive('customKeys', [\"$parse\", function ($parse) {\n        var directive = {};\n        directive.compile = function($element, attr) {\n            var up, down, enter, escape;\n\n            if(attr[\"upPressed\"]) {\n                up = $parse(attr[\"upPressed\"]);\n            }\n            if(attr[\"downPressed\"]) {\n                down = $parse(attr[\"downPressed\"]);\n            }\n            if(attr[\"enterPressed\"]) {\n                enter = $parse(attr[\"enterPressed\"]);\n            }\n\n            if(attr[\"escapePressed\"]) {\n                escape = $parse(attr[\"escapePressed\"]);\n            }\n\n            return function(scope, element, attr) {\n                element.on('keyup', function(e) {\n                    if(e.keyCode === 38) {\n                        scope.$apply(function() {\n                            if(up) {\n                                up(scope, {$event:e});\n                            }\n                        });\n                    } else if(e.keyCode === 40) {\n                        scope.$apply(function() {\n                            if(down) {\n                                down(scope, {$event:e});\n                            }\n                        });\n                    } else if(e.keyCode === 13) {\n                        scope.$apply(function() {\n                            if(enter) {\n                                enter(scope, {$event:e});\n                            }\n                        });\n                    } else if(e.keyCode === 27) {\n                    scope.$apply(function() {\n                        if(escape) {\n                            escape(scope, {$event:e});\n                        }\n                    });\n                }\n                });\n\n                element.on('keydown', element, function (e) {\n                    if (e.keyCode === 38 || e.keyCode === 40 || e.keyCode === 13 || e.keyCode === 27)\n                        e.preventDefault();\n                });\n            };\n    };\n    return directive;\n}]);\n\n// Delayed setting of model value in scope, based on input value unchanged after a number of millis\n// See below: ngDebounce is preferred (as it hooks into ngModel, meaning that ng-change will keep working - but not with delayedModel)\nflowableModule\n    .directive('delayedModel', ['$timeout', function($timeout) {\n    return {\n        scope: {\n            targetModel: '=delayedModel'\n        },\n        link: function(scope, element, attrs) {\n\n            element.val(scope.targetModel);\n\n            // Also watch model for any changes not triggered by timer\n            scope.$watch('targetModel', function(newVal, oldVal) {\n                if(scheduled) {\n                    $timeout.cancel(scheduled);\n                }\n                if (newVal !== oldVal) {\n                    element.val(scope.targetModel);\n                }\n            });\n\n            var scheduled;\n            element.on('keyup paste search', function() {\n                if(element.val() !== scope.targetModel) {\n                    if(scheduled) {\n                        $timeout.cancel(scheduled);\n                    }\n                    scheduled = $timeout(function() {\n                        scope.targetModel = element[0].value;\n                        element.val(scope.targetModel);\n                        scope.$apply();\n                    }, attrs.delay || 200);\n                }\n            });\n        }\n    };\n}]);\n\n\n// From https://gist.github.com/benbrandt22/bb44184a2eddcd4b0b8a\nflowableModule.directive('ngDebounce', ['$timeout', function($timeout) {\n    return {\n        restrict: 'A',\n        require: 'ngModel',\n        priority: 99,\n        link: function(scope, elm, attr, ngModelCtrl) {\n            if (attr.type === 'radio' || attr.type === 'checkbox') return;\n\n            elm.unbind('input');\n\n            var debounce;\n            elm.bind('input', function() {\n                $timeout.cancel(debounce);\n                debounce = $timeout( function() {\n                    scope.$apply(function() {\n                        ngModelCtrl.$setViewValue(elm.val());\n                    });\n                }, attr.ngDebounce || 1000);\n            });\n            elm.bind('blur', function() {\n                scope.$apply(function() {\n                    ngModelCtrl.$setViewValue(elm.val());\n                });\n            });\n        }\n\n    }\n}]);\n\nflowableModule.directive('externalContent', ['$parse', '$timeout', 'appResourceRoot', function ($parse, $timeout, appResourceRoot) {\n    var directive = {};\n    directive.restrict = 'A';\n    directive.templateUrl = appResourceRoot + '../views/common/templates/external-content-template.html';\n\n    directive.scope = {\n        taskId : '=taskId',\n        processInstanceId: '=formDefinition',\n        caseInstanceId: '=caseId',\n        folderSelect: '=folderSelect',\n        linkOnly: '=linkOnly',\n        preSelectedAlfrescoAccount: '=account',\n        uploadInProgress: '=uploadInProgress'\n    };\n    directive.link = function ($scope, $element, $attributes) {\n\n        if($attributes[\"onContentUpload\"]) {\n            $scope.uploadedCallback = $parse($attributes['onContentUpload']);\n        }\n\n        if($attributes[\"onFolderSelect\"]) {\n            $scope.folderSelectCallback = $parse($attributes['onFolderSelect']);\n        }\n\n        if($attributes[\"onUploadInProgress\"]) {\n            $scope.uploadInProgressCallback = $parse($attributes['onUploadInProgress']);\n        }\n\n        // Schedule hooking in of click-listener. we cannot use angular ng-click since this\n        // will force a new $apply/$digest to happen when the click() is called on the button\n        $timeout(function() {\n            $element.find('div.select-file').click(function() {\n                $element.find('input[type=\"file\"]').click();\n            });\n        }, 200);\n    };\n    directive.controller = ['$scope', '$element', 'RelatedContentService', '$modal', '$window', '$translate', '$rootScope',  function($scope, $element, RelatedContentService, $modal, $window, $translate, $rootScope) {\n        $scope.uploadModel = {uploading: false};\n\n        $scope.clearPopupError = function() {\n        };\n\n        $scope.openFileSelect = function(element) {\n            $scope.errorMessage = undefined;\n            var parent = angular.element(element).parent();\n            parent.children('input').click();\n        };\n\n        $scope.onFileSelect = function ($files, isIE) {\n            $scope.errorMessage = undefined;\n            if(!$scope.linkOnly) {\n                $scope.errorMessage = undefined;\n                if(!$scope.folderSelect && !$scope.uploadModel.uploading && $files.length > 0) {\n                    if ($scope.uploadInProgressCallback) {\n                        $scope.uploadInProgressCallback($scope.$parent, {status: true});\n                    }\n\n                    $scope.uploadModel.uploading = true;\n                    var file = $files[0];\n\n                    $scope.clearPopupError();\n                    RelatedContentService.addRelatedContent($scope.taskId, $scope.processInstanceId, $scope.caseInstanceId, file, isIE).progress(function (evt) {\n                        $scope.uploadModel.uploadProgress = parseInt(100.0 * evt.loaded / evt.total);\n                    }).then(function (data) {\n                        if ($scope.uploadInProgressCallback) {\n                            $scope.uploadInProgressCallback($scope.$parent, {status: false});\n\n                        }\n\n                        $scope.uploadModel.uploading = false;\n                        if($scope.uploadedCallback) {\n                            $scope.uploadedCallback($scope.$parent, {'content': data});\n                        }\n                    }, function (error) {\n                        // Error callback\n                        if ($scope.uploadInProgressCallback) {\n                            $scope.uploadInProgressCallback($scope.$parent, {status: false});\n                        }\n\n                        if(error && error.messageKey) {\n                            var formattedData = {};\n                            if(error.customData) {\n                                formattedData.quota =  $scope.formatFileSize(error.customData.quota)\n                            };\n\n                            $translate(error.messageKey, formattedData).then(function(message) {\n                                $scope.errorMessage = message;\n                            });\n                        }\n                        $scope.uploadModel.uploading = false;\n                    });\n                }\n            }\n        };\n\n    }];\n\n    return directive;\n}]);\n\n\nflowableModule.\n    directive('selectPeoplePopover', ['$rootScope', '$http', '$popover', 'appResourceRoot', 'UserService', '$parse', function($rootScope, $http, $popover, appResourceRoot, UserService, $parse) {\n        var directive = {};\n        directive.restrict = 'A';\n\n        directive.scope = {\n            excludeTaskId: '=excludeTaskId',\n            excludeProcessId: '=excludeProcessId',\n            excludeUserId: '=excludeUserId',\n            excludeUserIds: '=excludeUserIds',\n            tenantId: '=tenantId',\n            type: '=type',\n            restrictWithGroup: '=restrictWithGroup',\n            selectPeopleFormFields: '=selectPeopleFormFields',\n            ignoreContainer: '=ignoreContainer'\n        };\n\n        directive.link = function($scope, $element, attrs) {\n            // Set defaults\n            var placement = \"bottom\";\n\n            $element.addClass(\"toggle-people-select\");\n\n            if(attrs.placement) {\n                placement = attrs.placement;\n            }\n\n            var closeOnSelect = true;\n            if(attrs.closeOnSelect !== undefined) {\n                closeOnSelect = attrs.closeOnSelect;\n            }\n\n            if ($scope.ignoreContainer) {\n                $scope.popover = $popover($element, {template: appResourceRoot + '../views/common/popover/select-people-popover.html?'  +\n                    Date.now(), placement: placement});\n\n            } else {\n                $scope.popover = $popover($element, {template: appResourceRoot + '../views/common/popover/select-people-popover.html?'  +\n                    Date.now(), placement: placement, container: 'body'});\n            }\n\n            // Parse callbacks\n            var selectedCallback, cancelledCallback;\n            if (attrs['onPeopleSelected']) {\n                selectedCallback = $parse(attrs['onPeopleSelected']);\n            }\n            if (attrs['onCancel']) {\n                cancelledCallback = $parse(attrs['onCancel']);\n            }\n\n            // Parse type\n            // Can be 'workflow' or 'idm'. In 'workflow', the users are retrieved for filling task assignments etc. This is the default if this param is omitted. 'idm' is more strict.\n            var backendType = 'workflow';\n            if ($scope.type !== null && $scope.type !== undefined) {\n                backendType = $scope.type;\n            }\n\n            var popoverScope = $scope.popover.$scope;\n            popoverScope.title = attrs['popoverTitle'];\n\n            popoverScope.popupModel = {\n                userResults: [],\n                userField: {},\n                userFieldFilter: ['people']\n            };\n\n            if ($scope.selectPeopleFormFields) {\n                popoverScope.popupModel.formFields = $scope.selectPeopleFormFields;\n            }\n\n            popoverScope.setSearchType = function() {\n                popoverScope.popupModel.userSourceType = 'search';\n            };\n\n            popoverScope.setFormFieldType = function() {\n                popoverScope.popupModel.userSourceType = 'field';\n            };\n\n            popoverScope.$watch('popupModel.userField', function() {\n                if (popoverScope.popupModel.userField && popoverScope.popupModel.userField.id) {\n                    if (selectedCallback) {\n                        // Run callback in parent scope of directive\n                        var simpleUserField = {\n                                id: popoverScope.popupModel.userField.id,\n                                name: popoverScope.popupModel.userField.name,\n                                type: popoverScope.popupModel.userField.type\n                        }\n\n                        selectedCallback($scope.$parent, {'userField': simpleUserField});\n                        popoverScope.popupModel.userField = {};\n                    }\n\n                    if (closeOnSelect || closeOnSelect === 'true') {\n                        popoverScope.$hide();\n                    }\n                }\n            });\n\n            popoverScope.$watch('popupModel.filter', function() {\n                if (popoverScope.popupModel.filter && popoverScope.popupModel.filter.length > 0) {\n\n                    var userGetPromise;\n                    if (backendType === 'idm') {\n                        userGetPromise = UserService.getFilteredUsersStrict(popoverScope.popupModel.filter, $scope.tenantId, $scope.restrictWithGroup);\n                    } else {\n                        // Default: go to workflow users backend\n                        userGetPromise = UserService.getFilteredUsers(popoverScope.popupModel.filter, $scope.excludeTaskId,\n                                $scope.excludeProcessId, $scope.tenantId, $scope.restrictWithGroup);\n                    }\n\n                    userGetPromise.then(function(result) {\n                        popoverScope.popupModel.showRecentResults =  false;\n\n                        var users = [];\n                        var excludeUserIdSet = $scope.excludeUserId !== null && $scope.excludeUserId !== undefined;\n                        var excludeUserIdsSet = $scope.excludeUserIds !== null && $scope.excludeUserIds !== undefined;\n                        if (excludeUserIdSet === true || excludeUserIdsSet === true) {\n                            for (var userIndex=0; userIndex < result.data.length; userIndex++) {\n\n                                var userExcluded = false;\n                                if (excludeUserIdSet === true && result.data[userIndex].id === $scope.excludeUserId) {\n                                    userExcluded = true;\n                                }\n                                if (excludeUserIdsSet === true && $scope.excludeUserIds.indexOf(result.data[userIndex].id) >= 0) {\n                                    userExcluded = true;\n                                }\n\n                                if (!userExcluded) {\n                                    users.push(result.data[userIndex]);\n                                }\n\n                            }\n                        } else {\n                            users = result.data;\n                        }\n                        popoverScope.popupModel.userResults = users;\n                        popoverScope.resetSelection();\n                    });\n                } else {\n                    popoverScope.resetSelection();\n                    popoverScope.popupModel.userResults = [];\n                }\n            });\n\n            popoverScope.resetSelection = function() {\n                popoverScope.popupModel.selectedUser = undefined;\n                popoverScope.popupModel.selectedIndex = -1;\n            };\n\n            popoverScope.nextUser = function() {\n                var users = popoverScope.popupModel.userResults;\n                if(users && users.length > 0 && popoverScope.popupModel.selectedIndex < users.length -1) {\n                    popoverScope.popupModel.selectedIndex+=1;\n                    popoverScope.popupModel.selectedUser = users[popoverScope.popupModel.selectedIndex];\n                }\n            };\n\n            popoverScope.previousUser = function() {\n                var users = popoverScope.popupModel.userResults;\n                if(users && users.length > 0 && popoverScope.popupModel.selectedIndex > 0) {\n                    popoverScope.popupModel.selectedIndex-=1;\n                    popoverScope.popupModel.selectedUser = users[popoverScope.popupModel.selectedIndex];\n                }\n            };\n\n            popoverScope.confirmUser = function(user) {\n                if (!user) {\n                    // Selection is done with keyboard, use selection index\n                    var users = popoverScope.popupModel.userResults;\n                    if (popoverScope.popupModel.selectedIndex >= 0 && popoverScope.popupModel.selectedIndex <users.length) {\n                        user = users[popoverScope.popupModel.selectedIndex];\n                    }\n                }\n\n                if (user) {\n                    if (selectedCallback) {\n                        // Run callback in parent scope of directive\n                        selectedCallback($scope.$parent, {'user': user});\n                    }\n\n                    if (closeOnSelect === 'true') {\n                        popoverScope.$hide();\n                    } else {\n                        var users = popoverScope.popupModel.userResults;\n                        users.splice(jQuery.inArray(user, users),1);\n                        popoverScope.popupModel.selectedIndex=0;\n                        popoverScope.popupModel.selectedUser = users[popoverScope.popupModel.selectedIndex];\n                    }\n                }\n            };\n\n            popoverScope.$on('tooltip.hide', function() {\n                // Invalidate recent results\n                if(popoverScope.popupModel.showRecentResults && popoverScope.popupModel.added) {\n                    popoverScope.popupModel.recentUsers = [];\n                }\n                popoverScope.popupModel.userResults = [];\n                popoverScope.popupModel.filter = '';\n\n                if(popoverScope.popupModel.added) {\n                    popoverScope.popupModel.added = false;\n                } else {\n                    if(cancelledCallback) {\n                        // Run callback in parent scope of directive\n                        cancelledCallback($scope.$parent);\n                    }\n                }\n            });\n\n        };\n        return directive;\n    }]);\n\nflowableModule.\ndirective('selectFunctionalGroupPopover', ['$rootScope', '$http', '$popover','appResourceRoot', 'FunctionalGroupService', '$parse',\n    function($rootScope, $http, $popover, appResourceRoot, FunctionalGroupService, $parse) {\n\n    var directive = {};\n    directive.restrict = 'A';\n\n    directive.scope = {\n        type: '=type',\n        ignoreContainer: '=ignoreContainer',\n        restrictWithGroup: '=restrictWithGroup',\n        excludeGroupIds: '=excludeGroupIds'\n    };\n\n    directive.link = function($scope, $element, attrs) {\n        // Set defaults\n        var placement = \"bottom\";\n\n        $element.addClass(\"toggle-functional-group-select\");\n\n        if (attrs.placement) {\n            placement = attrs.placement;\n        }\n\n        var closeOnSelect = true;\n        if (attrs.closeOnSelect !== undefined) {\n            closeOnSelect = attrs.closeOnSelect;\n        }\n\n        if ($scope.ignoreContainer) {\n            $scope.popover = $popover($element, {template: appResourceRoot + '../views/common/popover/select-functional-group-popover.html?' +\n                Date.now(), placement: placement});\n\n        } else {\n            $scope.popover = $popover($element, {template: appResourceRoot + '../views/common/popover/select-functional-group-popover.html?' +\n                Date.now(), placement: placement, container: 'body'});\n        }\n\n        // Parse callbacks\n        var selectedCallback, cancelledCallback;\n        if (attrs['onGroupSelected']) {\n            selectedCallback = $parse(attrs['onGroupSelected']);\n        }\n        if (attrs['onCancel']) {\n            cancelledCallback = $parse(attrs['onCancel']);\n        }\n\n        var popoverScope = $scope.popover.$scope;\n        popoverScope.title = attrs['popoverTitle'];\n\n        popoverScope.popupModel = {\n            groupResults: []\n        };\n\n        popoverScope.$watch('popupModel.filter', function() {\n            if (popoverScope.popupModel.filter && popoverScope.popupModel.filter.length > 0) {\n\n                var tenantId;\n                if ($rootScope.common !== null && $rootScope.common !== undefined && $rootScope.common.selectedTenantId !== null && $rootScope.common.selectedTenantId !== undefined) {\n                    tenantId = $rootScope.common.selectedTenantId > 0 ? $rootScope.common.selectedTenantId : undefined;\n                }\n\n               FunctionalGroupService.getFilteredGroups(popoverScope.popupModel.filter, $scope.restrictWithGroup, tenantId).then(function(result) {\n                    var groups = [];\n                    if ($scope.excludeGroupId != null && $scope.excludeGroupId) {\n                        for (var groupIndex=0; groupIndex < result.data.length; groupIndex++) {\n                            if (result.data[groupIndex].id !== $scope.excludeGroupId) {\n                                groups.push(result.data[groupIndex]);\n                            }\n                        }\n                    } else if ($scope.excludeGroupIds != null && $scope.excludeGroupIds !== undefined) {\n                        for (var groupIndex=0; groupIndex < result.data.length; groupIndex++) {\n                            if ($scope.excludeGroupIds.indexOf(result.data[groupIndex].id) < 0) {\n                                groups.push(result.data[groupIndex]);\n                            }\n                        }\n                    } else {\n                        groups = result.data;\n                    }\n                    popoverScope.popupModel.groupResults = groups;\n                    popoverScope.resetSelection();\n                });\n            } else {\n                popoverScope.resetSelection();\n                popoverScope.popupModel.groupResults = [];\n            }\n        });\n\n        popoverScope.resetSelection = function() {\n            popoverScope.popupModel.selectedGroup = undefined;\n            popoverScope.popupModel.selectedIndex = -1;\n        };\n\n        popoverScope.nextGroup = function() {\n            var groups = popoverScope.popupModel.groupResults;\n            if (groups && groups.length > 0 && popoverScope.popupModel.selectedIndex < groups.length -1) {\n                popoverScope.popupModel.selectedIndex+=1;\n                popoverScope.popupModel.groupUser = groups[popoverScope.popupModel.selectedIndex];\n            }\n        };\n\n        popoverScope.previousGroup = function() {\n            var groups = popoverScope.popupModel.groupResults;\n            if (groups && groups.length > 0 && popoverScope.popupModel.selectedIndex > 0) {\n                popoverScope.popupModel.selectedIndex-=1;\n                popoverScope.popupModel.selectedGroup = groups[popoverScope.popupModel.selectedIndex];\n            }\n        };\n\n        popoverScope.confirmGroup = function(group) {\n            if (!group) {\n                // Selection is done with keyboard, use selection index\n                var groups = popoverScope.popupModel.groupResults;\n                if (popoverScope.popupModel.selectedIndex >= 0 && popoverScope.popupModel.selectedIndex < groups.length) {\n                    group = groups[popoverScope.popupModel.selectedIndex];\n                }\n            }\n\n            if (group) {\n                if(selectedCallback) {\n                    // Run callback in parent scope of directive\n                    selectedCallback($scope.$parent, {'group': group});\n                }\n\n                if (closeOnSelect === 'true') {\n                    popoverScope.$hide();\n                } else {\n                    var groups = popoverScope.popupModel.groupResults;\n                    groups.splice(jQuery.inArray(group, groups), 1);\n                    popoverScope.popupModel.selectedIndex = 0;\n                    popoverScope.popupModel.selectedGroup = groups[popoverScope.popupModel.selectedIndex];\n                }\n            }\n        };\n\n        popoverScope.$on('tooltip.hide', function() {\n            popoverScope.popupModel.groupResults = [];\n            popoverScope.popupModel.filter = '';\n\n            if (popoverScope.popupModel.added) {\n                popoverScope.popupModel.added = false;\n            } else {\n                if (cancelledCallback) {\n                    // Run callback in parent scope of directive\n                    cancelledCallback($scope.$parent);\n                }\n            }\n        });\n\n    };\n    return directive;\n}]);\n\nflowableModule.directive('tabControl', ['$compile', '$http', '$templateCache', function($compile, $http, $templateCache) {\n\n        var updateTemplate = function($scope, element, attributes) {\n            if(!$scope.activeTemplate || $scope.activeTemplate != $scope.activeTab.id) {\n                // Check if current loaded template is still the right one\n                var contentDiv = $(element.children()[1]);\n\n                var childScope = angular.element(element.children()[1]).scope();\n                if($scope.activeTemplate && childScope != $scope) {\n                    // Child-scope created by the included element, should be destroyed\n                    childScope.$destroy();\n                }\n\n                if($scope.activeTab && $scope.activeTab.templateUrl) {\n                    // Load the HTML-fragment or get from cache\n                    var loader = $http.get($scope.activeTab.templateUrl, {cache: $templateCache});\n                    var promise = loader.success(function(html) {\n                        contentDiv.html(html);\n                    }).then(function (response) {\n                        $scope.activeTemplate = $scope.activeTab.id;\n                        contentDiv.replaceWith($compile(contentDiv.html())($scope));\n                    });\n                } else {\n                    // No templates are being used, no need to use the contentDiv for this tab, clear it\n                    contentDiv.empty();\n                }\n            }\n        };\n\n        var directive = {};\n        directive.restrict = 'A';\n        directive.replace = true;\n        directive.transclude = true;\n        directive.template = '<div><div class=\"clearfix\"><ul class=\"tabs clearfix\">' +\n            '<li ng-repeat=\"tab in tabs\" ng-class=\"{\\'active\\': tab.id == activeTab.id}\"><a ng-click=\"tabClicked(tab)\">{{tab.title && (tab.title | translate) || (tab.name | translate)}}</a></li>' +\n            '</ul></div>' +\n            '<div></div>' +\n            '</div>';\n\n        directive.scope = {\n            possibleTabs : \"=tabControl\",\n            model: \"=model\",\n            activeTabReference: \"=activeTab\"\n        };\n\n\n        directive.controller = ['$scope', '$element', function($scope, $element) {\n\n            $scope.refreshTabs = function() {\n                var tabs = [];\n                for(var i=0; i < $scope.possibleTabs.length; i++) {\n                    var tab = $scope.possibleTabs[i];\n                    if(!tab.hide) {\n                        tabs.push(tab);\n                    }\n                }\n                $scope.tabs = tabs;\n            };\n\n            $scope.$watch('possibleTabs', function() {\n                $scope.refreshTabs();\n            }, true);\n\n            $scope.$watch('activeTabReference', function(newValue, oldValue) {\n                if(!$scope.activeTab || $scope.activeTab.id != newValue) {\n                    // Active tab ID changed from outside of the directive controller, need to switch to the\n                    // right tab within this scope\n                    var newTab = $scope.findTab(newValue);\n                    if(newTab) {\n                        $scope.tabClicked(newTab);\n                    }\n                }\n            });\n\n            $scope.findTab = function(tabId) {\n                if($scope.possibleTabs) {\n                    for(var i=0; i< $scope.possibleTabs.length; i++) {\n                        if($scope.possibleTabs[i].id == tabId) {\n                            return $scope.possibleTabs[i];\n                        }\n                    }\n                }\n                return undefined;\n            };\n\n            $scope.tabClicked = function(tab) {\n                if (tab.hide) {\n                    tab.hide = false;\n                    $scope.refreshTabs();\n                }\n                $scope.activeTab = tab;\n                if (tab) {\n                    $scope.activeTabReference = tab.id;\n                } else {\n                    $scope.activeTabReference = undefined;\n                }\n                updateTemplate($scope, $element);\n            };\n\n            $scope.refreshTabs();\n\n            if($scope.tabs && $scope.tabs.length > 0) {\n                if($scope.activeTabReference) {\n                    $scope.activeTab = $scope.findTab($scope.activeTabReference);\n                }\n\n                if(!$scope.activeTab) {\n                    // Revert to the first tab, if no tab is forced to be shown first\n                    $scope.activeTab = $scope.tabs[0];\n                }\n                $scope.tabClicked($scope.activeTab);\n            }\n        }];\n\n        directive.link = updateTemplate;\n\n        return directive;\n    }]);\n\n/**\n * Directive that calls the function present in the toggle-dragover attribute with a single parameter (over) when\n * dragging over the element has started (over = true) or ended (over = false)\n */\nflowableModule\n    .directive('toggleDragover', [\"$document\", \"$parse\", function ($document, $parse) {\n        var linkFunction = function ($scope, $element, $attributes) {\n\n\n            var toggleFunction = $attributes.toggleDragover;\n            var callback = $parse(toggleFunction);\n\n            var el = $element[0];\n\n            el.addEventListener('dragenter',function(e) {\n                    $scope.$apply(function() {\n                        callback($scope, {'over': true});\n                    });\n                    return false;\n                },\n                false\n            );\n\n            el.addEventListener('dragleave', function(e) {\n                    $scope.$apply(function() {\n                        callback($scope, {'over': false});\n                    });\n                    return false;\n                },\n                false\n            );\n        };\n\n        return( linkFunction );\n    }]);\n\nflowableModule.directive('editInPlace', function () {\n    return {\n        restrict: 'E',\n        scope: {\n            value: '='\n        },\n        template: '<span ng-click=\"edit()\" ng-bind=\"value\"></span><span class=\"glyphicon glyphicon-pencil edit-in-place-icon\"></span><input ng-model=\"value\" class=\"inline-edit-value form-control\" ng-blur=\"stopEdit()\" custom-keys enter-pressed=\"stopEdit()\">',\n        link: function ($scope, element, attrs) {\n\n            var iconElement = angular.element(element.children()[1]);\n            var inputElement = angular.element(element.children()[2]);\n\n            // This directive should have a set class so we can style it.\n            element.addClass('edit-in-place');\n\n            // Initially, we're not editing.\n            $scope.editing = false;\n\n            // ng-click handler to activate edit-in-place\n            $scope.edit = function () {\n                $scope.editing = true;\n\n                // We control display through a class on the directive itself. See the CSS.\n                element.addClass('active');\n\n                // And we must focus the element.\n                // `angular.element()` provides a chainable array, like jQuery so to access a native DOM function,\n                // we have to reference the first element in the array.\n                inputElement[0].focus();\n            };\n\n            $scope.stopEdit = function() {\n                $scope.editing = false;\n                element.removeClass('active');\n            };\n\n//            // When we leave the input, we're done editing.\n//            inputElement.prop('onblur', function () {\n//                console.log('ONBLUR');\n//                $scope.editing = false;\n//                element.removeClass('active');\n//            });\n        }\n    };\n});\n\n\n/* UTILITY METHODS */\n\n/**\n * This creates a modal window that auto closes on route change.\n * By default, this is NOT the case, and leads to some funny behaviour.\n *\n * Use this method vs the default $modal({myJson}) approach\n */\nvar _internalCreateModal = function(modalConfig, $modal, $scope) {\n\n    if ($scope !== null && $scope !== undefined) {\n        $scope.modal = $modal(modalConfig);\n\n        $scope.$on('$routeChangeStart', function () {\n            if ($scope.modal) {\n                $scope.modal.hide();\n            }\n        });\n\n        return $scope.modal;\n    } else {\n        return $modal(modalConfig);\n    }\n\n};\n\nflowableModule.\n    directive('numberInputCheck', function() {\n\n        return {\n            require: 'ngModel',\n            link: function(scope, element, attrs, modelCtrl) {\n\n                modelCtrl.$parsers.push(function (inputValue) {\n\n                    var transformedInput;\n                    if (inputValue && inputValue.indexOf('-') == 0) {\n                        transformedInput = inputValue.substr(1).replace(/([^0-9])/g, '');\n                        transformedInput = '-' + transformedInput;\n                    } else {\n                        transformedInput = inputValue.replace(/([^0-9])/g, '');\n                    }\n\n                    if (transformedInput != inputValue) {\n                        modelCtrl.$setViewValue(transformedInput);\n                        modelCtrl.$render();\n                    }\n\n                    return transformedInput;\n                });\n            }\n        };\n    });\n\n\nflowableModule.\ndirective('decimalNumberInputCheck', function() {\n\n    return {\n        require: 'ngModel',\n        link: function(scope, element, attrs, modelCtrl) {\n\n            modelCtrl.$parsers.push(function (inputValue) {\n\n            \tvar transformedInput = inputValue;\n                var negativeSign = '';\n\n                if (transformedInput && transformedInput.indexOf('-') == 0) {\n                    negativeSign = '-';\n                    transformedInput = inputValue.substr(1);\n                }\n\n                if(transformedInput && transformedInput.indexOf('.') == 0 ){\n                    transformedInput = \"0\" + transformedInput;\n                }\n\n                if(transformedInput && transformedInput.indexOf('.') > -1){\n                    var dotIndex = transformedInput.indexOf('.');\n                    var left = transformedInput.substr(0, dotIndex);\n                    var right = transformedInput.substr(dotIndex+1);\n\n                    left = left.replace(/([^0-9])/g, '');\n                    right = right.replace(/([^0-9])/g, '');\n                    transformedInput = negativeSign + left + '.' + right;\n                }\n                else{\n                    transformedInput = negativeSign + transformedInput.replace(/([^0-9])/g, '');\n                }\n\n\n                if (transformedInput != inputValue) {\n                    modelCtrl.$setViewValue(transformedInput);\n                    modelCtrl.$render();\n                }\n\n                return transformedInput;\n            });\n        }\n    };\n});\n"
  },
  {
    "path": "flowable-ui-web/task/scripts/common/providers-config.js",
    "content": "/* 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 * Configure the HTTP provider such that no caching happens when fetching\n * a resource using $http.\n */\nflowableModule.factory('NotPermittedInterceptor', [ '$q', '$window', function($q, $window) {\n    return {\n        responseError: function ( response ) {\n\n            if (response.status === 403) {\n                $window.location.href = FLOWABLE.CONFIG.contextRoot;\n                $window.location.reload();\n                return $q.reject(response);\n            }\n            else{\n                return $q.reject(response);\n            }\n        }\n    }\n}]);\n\nflowableModule.config(['$httpProvider', function($httpProvider) {\n\n    if (!$httpProvider.defaults.headers.get) {\n        $httpProvider.defaults.headers.get = {};\n    }\n\n    $httpProvider.defaults.headers.get['Cache-Control'] = 'no-cache, no-store, must-revalidate';\n    $httpProvider.defaults.headers.get['Pragma'] = 'no-cache';\n    $httpProvider.defaults.headers.get['Expires'] = '0';\n\n    $httpProvider.interceptors.push('NotPermittedInterceptor');\n\n}]);"
  },
  {
    "path": "flowable-ui-web/task/scripts/common/services/functional-group-service.js",
    "content": "/* 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'use strict';\n\n// User service\nflowableModule.service('FunctionalGroupService', ['$http', '$q',\n    function ($http, $q) {\n\n        var httpAsPromise = function(options) {\n            var deferred = $q.defer();\n            $http(options).\n                success(function (response, status, headers, config) {\n                    deferred.resolve(response);\n                })\n                .error(function (response, status, headers, config) {\n                    deferred.reject(response);\n                });\n            return deferred.promise;\n        };\n        \n        var groupInfoHttpAsPromise = function(options, index) {\n            var deferred = $q.defer();\n            $http(options).\n                success(function (response, status, headers, config) {\n                    var groupInfoFormObject = {\n                        groupData: response,\n                        index: index\n                    };\n                    deferred.resolve(groupInfoFormObject);\n                })\n                .error(function (response, status, headers, config) {\n                    deferred.reject(response);\n                });\n                \n            return deferred.promise;\n        };\n        \n        /*\n         * Get group info by id\n         */\n        this.getGroupInfo = function (groupId) {\n            \n            return httpAsPromise({\n                method: 'GET',\n                url: FLOWABLE.CONFIG.contextRoot + '/app/rest/workflow-groups/' + groupId\n            });\n        };\n        \n        this.getGroupInfoForForm = function (groupId, index) {\n            \n            return groupInfoHttpAsPromise({\n                method: 'GET',\n                url: FLOWABLE.CONFIG.contextRoot + '/app/rest/workflow-groups/' + groupId\n            }, index);\n        };\n\n        this.getFilteredGroups = function(filterText, group, tenantId) {\n\n            var params = {};\n\n            if (filterText !== null && filterText !== undefined) {\n                params.filter = filterText;\n            }\n            \n            if (group && group.id) {\n                params.groupId = group.id;\n            }\n\n            return httpAsPromise(\n                {\n                    method: 'GET',\n                    url: FLOWABLE.CONFIG.contextRoot + '/app/rest/workflow-groups',\n                    params: params\n                }\n            )\n        };\n    }]);\n"
  },
  {
    "path": "flowable-ui-web/task/scripts/common/services/recursion-helper.js",
    "content": "/* 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'use strict';\n\n// Recursion Helper service, makes it possible to use nested directives of the same type\nflowableModule.factory('RecursionHelper', ['$compile', function($compile){\n    return {\n        /**\n         * Manually compiles the element, fixing the recursion loop.\n         * @param element\n         * @param [link] A post-link function, or an object with function(s) registered via pre and post properties.\n         * @returns An object containing the linking functions.\n         */\n        compile: function(element, link){\n            // Normalize the link parameter\n            if(angular.isFunction(link)){\n                link = { post: link };\n            }\n\n            // Break the recursion loop by removing the contents\n            var contents = element.contents().remove();\n            var compiledContents;\n            return {\n                pre: (link && link.pre) ? link.pre : null,\n                /**\n                 * Compiles and re-adds the contents\n                 */\n                post: function(scope, element){\n                    // Compile the contents\n                    if(!compiledContents){\n                        compiledContents = $compile(contents);\n                    }\n                    // Re-add the compiled contents to the element\n                    compiledContents(scope, function(clone){\n                        element.append(clone);\n                    });\n\n                    // Call the post-linking function, if any\n                    if(link && link.post){\n                        link.post.apply(null, arguments);\n                    }\n                }\n            };\n        }\n    };\n}]);"
  },
  {
    "path": "flowable-ui-web/task/scripts/common/services/related-content-service.js",
    "content": "/* 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'use strict';\n\nflowableModule.service('RelatedContentService', ['$http', '$q', '$rootScope', '$translate', '$location', 'Upload', '$timeout',\n    function ($http, $q, $rootScope, $translate, $location, Upload, $timeout) {\n\n        var httpAsPromise = function(options) {\n            var deferred = $q.defer();\n            $http(options).\n                success(function (response, status, headers, config) {\n                    deferred.resolve(response);\n                })\n                .error(function (response, status, headers, config) {\n                    deferred.reject(response);\n                });\n            return deferred.promise;\n        };\n\n        this.deleteContent = function(contentId, taskId) {\n            var promise = httpAsPromise(\n                {\n                    method: 'DELETE',\n                    url: FLOWABLE.CONFIG.contextRoot + '/app/rest/content/' + contentId\n                }\n            );\n\n            return promise;\n        };\n\n        this.addRelatedContent = function(taskId, processInstanceId, caseInstanceId, file, isIE) {\n            var deferred = $q.defer();\n            var uploadPromise;\n            var url;\n\n            if(taskId) {\n                if (isIE) {\n                    url = FLOWABLE.CONFIG.contextRoot + '/app/rest/tasks/' + taskId + '/raw-content/text';\n                } else {\n                    url = FLOWABLE.CONFIG.contextRoot + '/app/rest/tasks/' + taskId + '/raw-content';\n                }\n                uploadPromise = Upload.upload({\n                    url: url,\n                    method: 'POST',\n                    file: file\n                });\n\n            } else if (processInstanceId) {\n                if (isIE) {\n                    url = FLOWABLE.CONFIG.contextRoot + '/app/rest/process-instances/' + processInstanceId + '/raw-content/text';\n                } else {\n                    url = FLOWABLE.CONFIG.contextRoot + '/app/rest/process-instances/' + processInstanceId + '/raw-content';\n                }\n                uploadPromise = Upload.upload({\n                    url: url,\n                    method: 'POST',\n                    file: file\n                });\n            } else if (caseInstanceId) {\n                if (isIE) {\n                    url = FLOWABLE.CONFIG.contextRoot + '/app/rest/case-instances/' + caseInstanceId + '/raw-content/text';\n                } else {\n                    url = FLOWABLE.CONFIG.contextRoot + '/app/rest/case-instances/' + caseInstanceId + '/raw-content';\n                }\n                uploadPromise = Upload.upload({\n                    url: url,\n                    method: 'POST',\n                    file: file\n                });\n            } else {\n                if (isIE) {\n                    url = FLOWABLE.CONFIG.contextRoot + '/app/rest/content/raw/text';\n                } else {\n                    url = FLOWABLE.CONFIG.contextRoot + '/app/rest/content/raw';\n                }\n                // Generic piece of content, initially marked as temporary\n                uploadPromise = Upload.upload({\n                    url: url,\n                    method: 'POST',\n                    file: file\n                });\n            }\n\n            var service = this;\n            uploadPromise.success(function (response, status, headers, config) {\n                if(response && response.id) {\n                    service.addUrlToContent(response);\n                }\n                deferred.resolve(response);\n            }).error(function (data, status, headers, config) {\n                deferred.reject(data);\n            });\n\n            // Add progress to the promise as well, to keep caller\n            // notified of progress but still have control over the success-call\n            // in order to add the raw URL before resolving promise\n            var promise = deferred.promise;\n            promise.progress = function(callback) {\n                uploadPromise.progress(callback);\n                return promise;\n            };\n\n            return promise\n\n        };\n\n        this.addRelatedContentFromSource = function(taskId, processInstanceId, source, sourceId, name, link) {\n            var url;\n            if(taskId) {\n                url = FLOWABLE.CONFIG.contextRoot + '/app/rest/tasks/' + taskId + '/content';\n            } else {\n                url = FLOWABLE.CONFIG.contextRoot + '/app/rest/content';\n            }\n\n            // Force a boolean value to be sent in the response body\n            link = (link == true);\n\n            var data = {\n                source: source,\n                sourceId: sourceId,\n                name: name,\n                link: link\n            };\n\n            var service = this;\n            var deferred = $q.defer();\n            $http(\n                {\n                    method: 'POST',\n                    url: url,\n                    data: data\n                }\n               ).success(function (response, status, headers, config) {\n                    if(response && response.id) {\n                        service.addUrlToContent(response);\n                    }\n                    deferred.resolve(response);\n                })\n                .error(function (response, status, headers, config) {\n                        deferred.reject(response);\n                });\n\n\n            var promise = deferred.promise;\n\n            return promise;\n        };\n\n        this.getRelatedContent = function(id) {\n            var url = FLOWABLE.CONFIG.contextRoot + '/app/rest/content/' + id;\n\n            var service = this;\n            var deferred = $q.defer();\n            $http(\n                {\n                    method: 'GET',\n                    url: url\n                }\n            ).success(function (response, status, headers, config) {\n                if(response && response.id) {\n                    service.addUrlToContent(response);\n                }\n                deferred.resolve(response);\n            })\n            .error(function (response, status, headers, config) {\n                deferred.reject(response);\n            });\n\n            var promise = deferred.promise;\n            return promise;\n        };\n\n        this.addUrlToContent = function(content) {\n            if(content && content.id) {\n                content.rawUrl = FLOWABLE.CONFIG.contextRoot + '/app/rest/content/' + content.id + \"/raw\";\n\n                var fileExtenstion = content.name.split('.').pop();\n\n                if(!content.link && (content.simpleType == 'word' || content.simpleType == 'excel' || content.simpleType == 'powerpoint')) {\n                    content.officeUrl = FLOWABLE.CONFIG.contextRoot + '/aos/' + content.id + \"/\" + content.name;\n                }\n\n                if(content.thumbnailStatus == 'created') {\n                    content.thumbnailUrl  =  FLOWABLE.CONFIG.contextRoot + '/app/rest/content/' + content.id + \"/rendition/thumbnail?noCache=\" + new Date().getTime();\n                }\n\n                if(content.previewStatus == 'created') {\n                    content.pdfUrl =  FLOWABLE.CONFIG.contextRoot + '/app/rest/content/' + content.id + \"/rendition/preview?noCache=\" + new Date().getTime();\n                } else if (content.simpleType === 'image' || fileExtenstion === 'jpg' || fileExtenstion === 'jpeg' || fileExtenstion === 'png') {\n                    content.imageUrl = content.rawUrl;\n                    content.thumbnailUrl = content.rawUrl;\n                } else if(content.simpleType == 'pdf') {\n                    content.pdfUrl = content.rawUrl;\n                }\n\n            }\n        };\n    }\n]);\n"
  },
  {
    "path": "flowable-ui-web/task/scripts/common/services/resource-service.js",
    "content": "/* 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'use strict';\n\n// User service\nflowableModule.service('ResourceService', ['$http', '$q', 'appResourceRoot',\n    function ($http, $q, appResourceRoot) {\n\n        var loadedResources = {};\n\n        function loadStylesheet(relativeUrl, cache)\n        {\n            var url = appResourceRoot + relativeUrl;\n            if (!cache || !loadedResources[url])\n            {\n                if (cache) {\n                    loadedResources[url] = true;\n                }\n                if (document.createStyleSheet)\n                {\n                    try\n                    {\n                        document.createStyleSheet();\n                    } catch (e) { }\n                }\n                else {\n                    var link = document.createElement(\"link\");\n                    link.rel = \"stylesheet\";\n                    link.type = \"text/css\";\n                    link.media = \"all\";\n                    link.href = url;\n                    document.getElementsByTagName(\"head\")[0].appendChild(link);\n                }\n            }\n        }\n\n        function loadScript(relativeUrl, callback, cache)\n        {\n            var url = appResourceRoot + relativeUrl;\n            if (cache && loadedResources[url] && callback)\n            {\n                callback();\n            }\n            else\n            {\n                if (cache) {\n                    loadedResources[url] = true;\n                }\n\n                // Insert the node so it gets loaded\n                var script = document.createElement(\"script\");\n                script.type=\"text/javascript\";\n                script.src = url;\n\n                if (callback) {\n                    var done = false;\n\n                    // Attach handlers for all browsers\n                    script.onload = script.onreadystatechange = function()\n                    {\n                        if (!done && (!this.readyState || this.readyState == \"loaded\" || this.readyState == \"complete\"))\n                        {\n                            done = true;\n                            callback();\n                        }\n                    };\n                }\n                var el = document.getElementsByTagName(\"head\")[0];\n                el.appendChild(script);\n            }\n        }\n\n        function loadScripts(relativeUrls, callback, cache)\n        {\n            function loadNext()\n            {\n                var relativeUrl = relativeUrls.shift();\n                if (relativeUrl)\n                {\n                    loadScript.call(this, relativeUrl, loadNext.bind(this), cache);\n                }\n                else\n                {\n                    if (callback)\n                    {\n                        callback();\n                    }\n                }\n            }\n            loadNext.call(this);\n        }\n\n        function loadFromHtml(url, callback, cache)\n        {\n            $http.get(url).success(function(responseText)\n            {\n                var xmlDoc;\n                if (window.DOMParser)\n                {\n                    var parser = new DOMParser();\n                    xmlDoc = parser.parseFromString(responseText, \"text/xml\");\n                }\n                else // Internet Explorer\n                {\n                    xmlDoc = new ActiveXObject(\"Microsoft.XMLDOM\");\n                    xmlDoc.async = false;\n                    xmlDoc.loadXML(responseText);\n                }\n                var resources = xmlDoc.getElementsByTagName(\"link\");\n                var resourceUrl;\n                var resourceUrls = [];\n                for (var i = 0, il = resources.length; i < il; i++)\n                {\n                    resourceUrl = resources[i].getAttribute(\"href\");\n                    if (resourceUrl)\n                    {\n                        loadStylesheet(resourceUrl, cache);\n                    }\n                }\n                resources = xmlDoc.getElementsByTagName(\"script\");\n                for (i = 0, il = resources.length; i < il; i++)\n                {\n                    resourceUrl = resources[i].getAttribute(\"src\");\n                    if (resourceUrl)\n                    {\n                        resourceUrls.push(resourceUrl);\n                    }\n                }\n                loadScripts(resourceUrls, callback, cache);\n            });\n        }\n\n        this.loadFromHtml = loadFromHtml;\n        this.loadScript = loadScript;\n        this.loadStylesheet = loadStylesheet;\n    }]);\n"
  },
  {
    "path": "flowable-ui-web/task/scripts/common/services/runtime-app-definition-service.js",
    "content": "/* 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'use strict';\n\n// User service\nflowableApp.service('RuntimeAppDefinitionService', ['$http', '$q', '$location', 'appName',\n    function ($http, $q, $location, appName) {\n\n        var httpAsPromise = function(options) {\n            var deferred = $q.defer();\n            $http(options).\n                success(function (response, status, headers, config) {\n                    deferred.resolve(response);\n                })\n                .error(function (response, status, headers, config) {\n                    deferred.reject(response);\n                });\n            return deferred.promise;\n        };\n\n        this.getApplications = function () {\n\n            var defaultApps = [];\n\n            // Determine the full url with a context root (if any)\n            var baseUrl = $location.absUrl();\n            var index = baseUrl.indexOf('/#');\n            if (index >= 0) {\n                baseUrl = baseUrl.substring(0, index);\n            }\n            index = baseUrl.indexOf('?');\n            if (index >= 0) {\n                baseUrl = baseUrl.substring(0, index);\n            }\n            if (baseUrl[baseUrl.length - 1] == '/') {\n                baseUrl = baseUrl.substring(0, baseUrl.length - 1);\n            }\n            if (appName.length > 0 && baseUrl.substring(baseUrl.length - appName.length) == appName) {\n                baseUrl = baseUrl.substring(0, baseUrl.length - appName.length - 1);\n            }\n\n            var transformAppsResponse = function(value, headersGetter, status) {\n                if (status !== 200) {\n                    return;\n                }\n                \n                var response = JSON.parse(value);\n                var customApps = [];\n                for (var i = 0; i < response.data.length; i++) {\n\n                    var app = response.data[i];\n                    if (app.defaultAppId !== undefined && app.defaultAppId !== null) {\n\n                        if (app.defaultAppId === 'tasks') {\n\n                            defaultApps.push(\n                                {\n                                    id: 'tasks',\n                                    titleKey: 'APP.TASKS.TITLE',\n                                    descriptionKey: 'APP.TASKS.DESCRIPTION',\n                                    defaultAppId : app.defaultAppId,\n                                    theme: 'theme-2',\n                                    icon: 'icon icon-clock',\n                                    fixedBaseUrl: baseUrl + '/workflow/' + '/#/',\n                                    fixedUrl: baseUrl + '/workflow/',\n                                    pages: ['tasks', 'processes']\n                                });\n                        }\n\n                    } else {\n\n                        // Custom app\n                        app.icon = 'glyphicon ' + app.icon;\n                        app.fixedBaseUrl = baseUrl + '/workflow/#/apps/' + app.appDefinitionKey + '/';\n                        app.fixedUrl = app.fixedBaseUrl + 'tasks';\n                        app.pages = [ 'tasks', 'processes' ];\n                        app.deletable = true;\n                        customApps.push(app);\n                    }\n\n                }\n\n                return {\n                    defaultApps: defaultApps,\n                    customApps: customApps\n                };\n            };\n\n            return httpAsPromise({\n                method: 'GET',\n                url: FLOWABLE.CONFIG.contextRoot + '/app/rest/runtime/app-definitions',\n                transformResponse: transformAppsResponse\n            });\n        };\n\n        this.deleteAppDefinition = function (appDefinitionKey) {\n            var promise = httpAsPromise({\n                method: 'DELETE',\n                url: FLOWABLE.CONFIG.contextRoot + '/app/rest/runtime/app-definitions/' + appDefinitionKey\n            });\n\n            return promise;\n        };\n    }]);"
  },
  {
    "path": "flowable-ui-web/task/scripts/common/services/user-service.js",
    "content": "/* 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'use strict';\n\n// User service\nflowableModule.service('UserService', ['$http', '$q',\n    function ($http, $q) {\n\n        var httpAsPromise = function(options) {\n            var deferred = $q.defer();\n            $http(options).\n                success(function (response, status, headers, config) {\n                    deferred.resolve(response);\n                })\n                .error(function (response, status, headers, config) {\n                    deferred.reject(response);\n                });\n            return deferred.promise;\n        };\n        \n        var userInfoHttpAsPromise = function(options, index) {\n            var deferred = $q.defer();\n            $http(options).\n                success(function (response, status, headers, config) {\n                    var userInfoFormObject = {\n                        userData: response,\n                        index: index\n                    };\n                    deferred.resolve(userInfoFormObject);\n                })\n                .error(function (response, status, headers, config) {\n                    deferred.reject(response);\n                });\n                \n            return deferred.promise;\n        };\n        \n        /*\n         * Get user info by id\n         */\n        this.getUserInfo = function (userId) {\n            \n            return httpAsPromise({\n                method: 'GET',\n                url: FLOWABLE.CONFIG.contextRoot + '/app/rest/users/' + userId\n            });\n        };\n        \n        /*\n         * Get user info by id\n         */\n        this.getUserInfoForForm = function (userId, index) {\n        \n            return userInfoHttpAsPromise({\n                method: 'GET',\n                url: FLOWABLE.CONFIG.contextRoot + '/app/rest/users/' + userId\n            }, index);\n        };\n\n        /*\n         * Filter users based on a filter text, in the context of workflow: for tasks, processes, etc.\n         */\n        this.getFilteredUsers = function (filterText, taskId, processInstanceId, tenantId, group) {\n            var params = {};\n            if (typeof filterText === 'string') {\n               params.filter = filterText;\n            }\n            else {\n               // Could be i.e. { email: 'user@domain.com' } or { externalId: 'externalUserId' }\n               params = filterText;\n            }\n            if(taskId) {\n                params.excludeTaskId = taskId;\n            }\n            if (processInstanceId) {\n                params.excludeProcessId = processInstanceId;\n            }\n\n            if (group && group.id) {\n                params.groupId = group.id;\n            }\n\n            return httpAsPromise({\n                method: 'GET',\n                url: FLOWABLE.CONFIG.contextRoot + '/app/rest/workflow-users',\n                params: params\n            });\n        };\n\n        /*\n         * Filter users based on a filter text, in the context of IDM: use no context (contrary to the getFilteredUsers method).\n         */\n        this.getFilteredUsersStrict = function(filterText, tenantId, group) {\n\n            var params = {};\n\n            params.status = 'active';\n\n            if (filterText !== null && filterText !== undefined) {\n                params.filter = filterText;\n            }\n\n            if (group && group.id) {\n                params.groupId = group.id;\n            }\n\n            return httpAsPromise(\n                {\n                    method: 'GET',\n                    url: FLOWABLE.CONFIG.contextRoot + '/app/rest/admin/users',\n                    params: params\n                }\n            )\n        };\n\n    }]);\n"
  },
  {
    "path": "flowable-ui-web/task/scripts/landing-app.js",
    "content": "/* 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'use strict';\n\nvar flowableApp = angular.module('flowableLanding', [\n  'ngCookies',\n  'ngResource',\n  'ngSanitize',\n  'ngRoute',\n  'mgcrea.ngStrap',\n  'ngAnimate',\n  'pascalprecht.translate'\n]);\n\nvar flowableModule = flowableApp;\nflowableApp\n  // Initialize routes\n  .config(['$provide', '$routeProvider', '$selectProvider', '$datepickerProvider', '$translateProvider', function ($provide, $routeProvider, $selectProvider, $datepickerProvider, $translateProvider) {\n\n    var appName = '';\n    $provide.value('appName', appName);\n\n    var ctx = FLOWABLE.CONFIG.webContextRoot;\n    var appResourceRoot = ctx + (ctx && ctx.charAt(ctx.length - 1) !== '/' ? '/' : '');\n    $provide.value('appResourceRoot', appResourceRoot);\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    // Override carets for bs-datepicker directive\n    angular.extend($datepickerProvider.defaults, {\n        iconLeft: 'icon icon-caret-left',\n        iconRight: 'icon icon-caret-right'\n    });\n\n    $routeProvider\n        .when('/', {\n            templateUrl: 'views/landing.html',\n            controller: 'LandingController'\n        })\n        .otherwise({\n            redirectTo: FLOWABLE.CONFIG.appDefaultRoute || '/'\n        });\n\n        // Initialize angular-translate\n        $translateProvider.useStaticFilesLoader({\n          prefix: './i18n/',\n          suffix: '.json'\n        })\n        /*\n        This can be used to map multiple browser language keys to a\n        angular translate language key.\n        */\n        // .registerAvailableLanguageKeys(['en'], {\n        //     'en-*': 'en'\n        // })\n        .useSanitizeValueStrategy('escapeParameters')\n        .uniformLanguageTag('bcp47')\n        .determinePreferredLanguage();\n    }])\n    .run(['$rootScope', '$timeout', '$translate', '$location', '$http', '$window', '$popover', 'appResourceRoot', 'RuntimeAppDefinitionService',\n        function($rootScope, $timeout, $translate, $location, $http, $window, $popover, appResourceRoot, RuntimeAppDefinitionService) {\n\n        // set angular translate fallback language\n        $translate.fallbackLanguage(['en']);\n\n        $rootScope.appResourceRoot = appResourceRoot;\n\n        // Alerts\n        $rootScope.alerts = {\n            queue: []\n        };\n        \n        $rootScope.webRootUrl = function() {\n            return FLOWABLE.CONFIG.webContextRoot;\n        };\n        \n        $rootScope.restRootUrl = function() {\n            return FLOWABLE.CONFIG.contextRoot;\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        $rootScope.logout = function () {\n            $rootScope.authenticated = false;\n            $rootScope.authenticationError = false;\n            $http.get(FLOWABLE.CONFIG.contextRoot + '/app/logout')\n                .success(function (data, status, headers, config) {\n                    $rootScope.login = null;\n                    $rootScope.authenticated = false;\n                    $window.location.href = '/';\n                    $window.location.reload();\n                });\n        };\n\n        $http.get(FLOWABLE.CONFIG.contextRoot + '/app/rest/account')\n        \t.success(function (data, status, headers, config) {\n              \t$rootScope.account = data;\n               \t$rootScope.invalidCredentials = false;\n \t\t\t\t$rootScope.authenticated = true;\n          \t});\n\n     }])\n     .run(['$rootScope', '$location', '$window', '$translate', '$modal',\n        function($rootScope, $location, $window, $translate, $modal) {\n         \n        /* Auto-height */\n\n        $rootScope.window = {};\n        var updateWindowSize = function() {\n            $rootScope.window.width = $window.innerWidth;\n            $rootScope.window.height  = $window.innerHeight;\n        };\n\n        // Window resize hook\n        angular.element($window).bind('resize', function() {\n            $rootScope.$apply(updateWindowSize());\n        });\n\n        $rootScope.$watch('window.forceRefresh', function(newValue) {\n            if(newValue) {\n                $timeout(function() {\n                    updateWindowSize();\n                    $rootScope.window.forceRefresh = false;\n                });\n            }\n        });\n\n        updateWindowSize();\n\n        /* Capabilities */\n\n        $rootScope.backToLanding = function() {\n            var baseUrl = $location.absUrl();\n            var index = baseUrl.indexOf('/#');\n            if (index >= 0) {\n                baseUrl = baseUrl.substring(0, index);\n                baseUrl += '/';\n            }\n            $window.location.href = baseUrl;\n        };\n}]);\n"
  },
  {
    "path": "flowable-ui-web/task/scripts/landing-controller.js",
    "content": "/* 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 */\nflowableApp.controller('LandingController', ['$scope','$window', '$location', '$http', '$translate', '$modal', 'RuntimeAppDefinitionService', '$rootScope',\n    function ($scope, $window, $location, $http, $translate, $modal, RuntimeAppDefinitionService, $rootScope) {\n\n        $scope.model = {\n          loading: true\n        };\n\n        $translate('APP.ACTION.DELETE').then(function(message) {\n            $scope.appActions = [\n                {\n                    text: message,\n                    click: 'deleteApp(app); '\n                }\n            ];\n        });\n\n        $scope.loadApps = function() {\n            $scope.model.customAppsFetched = false;\n            RuntimeAppDefinitionService.getApplications().then(function(result){\n                $scope.model.apps = result.defaultApps.concat(result.customApps);\n                $scope.model.customAppsFetched = true;\n                $scope.model.customApps = result.customApps.length > 0;\n\n                // Determine the full url with a context root (if any)\n                var baseUrl = $location.absUrl();\n                var index = baseUrl.indexOf('/#');\n                if (index >= 0) {\n                    baseUrl = baseUrl.substring(0, index);\n                }\n                index = baseUrl.indexOf('?');\n                if (index >= 0) {\n                    baseUrl = baseUrl.substring(0, index);\n                }\n                if (baseUrl[baseUrl.length - 1] == '/') {\n                    baseUrl = baseUrl.substring(0, baseUrl.length - 1);\n                }\n\n                $scope.urls = {\n                    workflow: baseUrl + '/workflow/'\n                };\n\n\n            })\n        };\n\n        $scope.appSelected = function(app) {\n            if(app.fixedUrl) {\n                $window.location.href = app.fixedUrl;\n            }\n        };\n\n        $scope.addAppDefinition = function() {\n\n            _internalCreateModal({\n                template: 'views/modal/add-app-definition-modal.html',\n                scope: $scope\n            }, $modal, $scope);\n        };\n\n\n        $scope.deleteApp = function(app) {\n            if(app && app.id) {\n                RuntimeAppDefinitionService.deleteAppDefinition(app.id).then(function() {\n                    $rootScope.addAlertPromise($translate('APP.MESSAGE.DELETED'), 'info')\n\n                    // Remove app from list\n                    var index = -1;\n                    for(var i=0; i< $scope.model.apps.length; i++) {\n                        if($scope.model.apps[i].id == app.id) {\n                            index = i;\n                            break;\n                        }\n                    }\n\n                    if(index >= 0) {\n                        $scope.model.apps.splice(index, 1);\n                    }\n                });\n            }\n        };\n\n        $scope.loadApps();\n    }]\n);\n"
  },
  {
    "path": "flowable-ui-web/task/scripts/resource-loader.js",
    "content": "/* Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n(function(resources){\n\n    if (resources) {\n\n        // Pause angular bootstrap so we have time to register and override angular services/directives etc\n        window.name = 'NG_DEFER_BOOTSTRAP!';\n\n        function load(res, node, callback, scope) {\n            var resource;\n            if (res.tag === 'script') {\n                resource = document.createElement('script');\n                resource.type = res.type || 'text/javascript';\n                resource.src = res.src;\n\n                if (callback) {\n                    var done = false;\n\n                    // Attach handlers for all browsers\n                    resource.onload = resource.onreadystatechange = function()\n                    {\n                        if (!done && (!this.readyState || this.readyState == \"loaded\" || this.readyState == \"complete\"))\n                        {\n                            done = true;\n                            callback.call(scope ? scope : this, res);\n                        }\n                    };\n                }\n            }\n            else if (res.tag === 'link') {\n                resource = document.createElement('link');\n                resource.rel = res.rel || 'stylesheet';\n                resource.href = res.href;\n            }\n\n            if (node.nextSibling) {\n                node.parentNode.insertBefore(resource, node.nextSibling);\n            }\n            else {\n                node.parentNode.appendChild(resource);\n            }\n\n            if (res.tag === 'link' && callback) {\n                callback.call(scope ? scope : this, res);\n            }\n        }\n\n        function getResourceLoaderElement() {\n            var scripts = document.getElementsByTagName('script');\n            for (var i = 0, il = scripts.length; i < il; i++) {\n                if (scripts[i].src.indexOf('scripts/resource-loader.js') != -1) {\n                    return scripts[i];\n                }\n            }\n            return null;\n        }\n\n        var res = resources['*'];\n        var resourceLoaderElement = getResourceLoaderElement();\n        var appName = resourceLoaderElement.getAttribute('app');\n        if (resources.hasOwnProperty(appName)) {\n            res = resources[appName];\n        }\n\n        var loadedResources = 0;\n        for (var i = 0, il = res.length; i < il; i++) {\n            load(res[i], resourceLoaderElement, function(){\n                loadedResources++;\n                if (loadedResources == res.length) {\n                    // Let angular resume bootstrap\n                    var interval = window.setInterval(function(){\n                        if (angular && typeof angular.resumeBootstrap == 'function') {\n                            angular.resumeBootstrap();\n                            window.clearInterval(interval);\n                        }\n                    }, 20);\n\n                }\n            });\n        }\n    }\n\n})(FLOWABLE.CONFIG.resources);"
  },
  {
    "path": "flowable-ui-web/task/styles/common/style-retina.css",
    "content": "/* Retina tweaks */\n@media \tonly screen and (-webkit-min-device-pixel-ratio: 1.5),\nonly screen and (   min--moz-device-pixel-ratio: 1.5),\nonly screen and (     -o-min-device-pixel-ratio: 3/2),\nonly screen and (        min-device-pixel-ratio: 1.5),\nonly screen and (min-resolution: 192dpi) {\n\n    .navbar-header .navbar-brand {\n        background-size: 148px 25px;\n    }\n\n    .account .google-drive {\n        background: transparent url('../../images/google-drive-2x.png') 50% 50% no-repeat;\n        background-size: 34px 34px;\n    }\n\n    .account .alfresco {\n        background: transparent url('../../images/alfresco-2x.png') 50% 50% no-repeat;\n        background-size: 34px 34px;\n    }\n\n    .account .alfresco-cloud {\n        background: transparent url('../../images/alfresco-cloud-2x.png') 50% 50% no-repeat;\n        background-size: 34px 34px;\n    }\n}"
  },
  {
    "path": "flowable-ui-web/task/styles/common/style.css",
    "content": "/**\n Colors:\n\n  - Header: #1f3245\n  - Subheader: #e8edf1\n  - Subheader border: #a4acb9\n  - Highlight buttons/text: #2980b9\n  - Text color: #1a1a1a\n  - Filter color: #373e48\n  - Dark highlight: #606b7d\n*/\n\n@font-face {\n    font-family: 'cherokeeregular';\n    src: url('../../fonts/cherokee-webfont.eot');\n    src: url('../../fonts/cherokee-webfont.eot?#iefix') format('embedded-opentype'),\n    url('../../fonts/cherokee-webfont.woff') format('woff'),\n    url('../../fonts/cherokee-webfont.ttf') format('truetype'),\n    url('../../fonts/cherokee-webfont.svg#cherokeeregular') format('svg');\n    font-weight: normal;\n    font-style: normal;\n}\n\n@font-face {\n    font-family: 'Titillium Web';\n    font-style: normal;\n    font-weight: normal;\n    url('../../fonts/TitilliumWeb-Regular.ttf') format('truetype');\n}\n\n@font-face {\n    font-family: 'Titillium Web';\n    font-style: normal;\n    font-weight: bold;\n    url('../../fonts/TitilliumWeb-Bold.ttf') format('truetype');\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,\nbody pre {\n    font-family: 'Titillium Web', sans-serif;\n}\n\nbody pre {\n    border: none;\n    padding: 0;\n    background: transparent;\n}\n\nhr {\n\tborder-top: 1px solid #606b7d; \n}\n\n.form-wrapper textarea {\n    width: 100%;\n    max-width: 100%;\n    min-width: 100%;\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:hover {\n    font-weight: bolder;\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: #2980b9;\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\nbutton.btn.glyphicon{\n\ttop: 0;\n\tpadding: 8.5px 12px;\n\tborder-color: transparent;\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.btn[disabled]:hover, .btn[disabled].active, .btn[disabled]:focus {\n    background-color: #3990c9;\n    border-color: #ffffff;\n    color: #ffffff;\n}\n\n.btn[disabled]:active, .btn[disabled].active {\n    outline: 0;\n    background-image: none;\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\n.btn.disabled, .btn[disabled], .btn[disabled]:active, .btn[disabled]:hover {\n    background-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: #2980b9;\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: #2980b9;\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: 350px;\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: #1f3245;\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    width: 180px;\n}\n\n\n.navbar-nav {\n    height: 40px;\n    margin-left: 50px;\n}\n\n.navbar-inverse .navbar-nav > li > a {\n\tcolor: #a8bac1;\n}\n\n.navbar-inverse .navbar-nav > .active > a {\n\tbackground-color: #1f3245;\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    content: \" \";\n    height: 0;\n    width: 0;\n    position: absolute;\n    pointer-events: none;\n    border: 6px solid rgba(0, 0, 0, 0);\n    border-top-color: #1f3245;\n    margin-left: -6px;\n}\n\n.navbar-nav > li.active:hover:after {\n    border-top-color: #000000;\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: #2980b9;\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: 'Titillium Web', 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: #2980b9;\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    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: 1;\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    background-color: #ffffff;\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: #2980b9;\n}\n\n.main-list .list-subheader {\n    margin-top: 40px;\n    position: relative;\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: #2980b9;\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: #2980b9;\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: #2980b9;\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: #2980b9;\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\nh3+div > .dropzone {\n    margin-top: 5px;\n}\n\n.dropzone {\n    position: relative;\n    margin: 0px;\n    padding: 10px 10px;\n    text-align: center;\n}\n\n.dropzone .error, .error-message {\n    background-color: #e9af9f;\n    border: 1px solid #e4593d;\n    background-color: rgba(228, 89, 61, .7);\n    padding: 5px;\n    margin-bottom: 5px;\n    font-size: 14px;\n    color:white;\n}\n\n.dropzone.selection {\n    text-align: left;\n    padding-left: 5px;\n}\n\n.dropzone .select-file {\n    line-height: 40px;\n}\n\n.dropzone.dragover {\n    border: 1px dotted #2980b9;\n}\n\n.dropzone .message {\n    color: #999999;\n    line-height: 22px;\n    visibility: hidden;\n    position: absolute;\n    top: 20px;\n    left: 10px;\n    right: 10px;\n    text-align: center;\n}\n\n.dropzone.dragover .message {\n    color: #2980b9;\n    font-size: 20px;\n    visibility: inherit;\n}\n\n\n.dropzone.uploading .message {\n    visibility: hidden;\n}\n\n.dropzone input[type=file] {\n    width: 100%;\n    display: none;\n    visibility: hidden;\n}\n\n.dropzone.dragover input, .dropzone.dragover .account, .dropzone.dragover .select-file {\n    visibility: hidden;\n}\n\n.dropzone .account {\n    float: left;\n    text-align: center;\n    width: 50px;\n\n    padding: 0px 0px 0px 3px;\n    border-left: 1px solid #eeeeee;\n}\n\n.dropzone .no-upload .account {\n    border-left: none;\n    border-right: 1px solid #eeeeee;\n}\n.dropzone .account:first-child {\n    padding-left: 0;\n}\n\n.dropzone .account > div {\n    height: 40px;\n    cursor: pointer;\n}\n\n.dropzone.uploading .account > div {\n    cursor: not-allowed;\n}\n\n.account .google-drive {\n    background: transparent url('../../images/google-drive.png') 50% 50% no-repeat;\n}\n\n.account .alfresco {\n    background: transparent url('../../images/alfresco.png') 50% 50% no-repeat;\n}\n\n.account .alfresco-cloud {\n    background: transparent url('../../images/alfresco-cloud.png') 50% 50% no-repeat;\n}\n\n.dropzone .loading {\n    position: absolute;\n    left: 50%;\n    margin-left: -15px;\n    line-height: 30px;\n    top: 0px;\n}\n\n.dropzoneIE9.selectionIE9 {\n    text-align: left;\n    padding-left: 5px;\n}\n.dropzoneIE9 {\n    position: relative;\n    margin: 0px;\n    padding: 10px 10px;\n    text-align: center;\n}\n.selectionIE9 {\n    position: relative;\n    margin: 0;\n    padding: 6px 8px;\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    font-size: 14px;\n    cursor: pointer;\n}\n\n.selectionIE9 .actions {\n    float: right;\n}\n\n.dropzoneIE9 .account:first-child {\n    padding-left: 0;\n}\n\n.dropzoneIE9 .account {\n    float: left;\n    text-align: center;\n    width: 50px;\n    padding: 0px 0px 0px 3px;\n    border-left: 1px solid #eeeeee;\n}\n\n.dropzoneIE9 .account > div {\n    height: 40px;\n    cursor: pointer;\n}\n\n.dropzoneIE9 .select-file {\n    line-height: 40px;\n}\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}\n\n\n.read-only-select {\n    overflow: auto;\n}\n.read-only-select .selection {\n    overflow: hidden;\n    width:100%;\n    text-align: left;\n}\n\n/** people select */\n\n.people-select {\n    overflow: auto;\n    max-width: 100%;\n}\n\n.popover .people-select {\n    font-size: 13px;\n}\n\n.popover .people-select .simple-list {\n    height: 180px;\n    overflow: auto;\n    border-bottom: 1px solid #eeeeee;\n}\n\n.people-select-link {\n    color: #428bca;\n    cursor: pointer;\n}\n\n/** date select */\n\n.form-field {\n    overflow: auto;\n    max-width: 100%;\n}\n\n.popover .form-field {\n    font-size: 13px;\n}\n\n.popover .form-field .simple-list {\n    height: 180px;\n    overflow: auto;\n    border-bottom: 1px solid #eeeeee;\n}\n\n.form-field-link {\n    color: #428bca;\n    cursor: pointer;\n}\n\n.dropdown-menu.datepicker .calendar-grid .btn {\n    background-color: #ffffff;\n    color: #1a1a1a;\n    border: none;\n\n    -webkit-border-radius: 0;\n    -moz-border-radius: 0;\n    border-radius: 0;\n}\n\n.dropdown-menu.datepicker th {\n    background-color: #e8edf1;\n}\n.dropdown-menu.datepicker th .btn {\n    background-color: #e8edf1;\n    color: #1a1a1a;\n    border-color: #e8edf1;\n}\n\n.dropdown-menu.datepicker th .btn:hover, .dropdown-menu.datepicker th .btn:focus {\n    color: #2980b9;\n}\n\n.dropdown-menu.datepicker .calendar-grid .btn:hover, .dropdown-menu.datepicker .calendar-grid .btn:focus {\n    background-color: #f8f8f9;\n    border: none;\n    color: #1a1a1a;\n}\n\n.dropdown-menu.datepicker .calendar-grid .btn-today, .dropdown-menu.datepicker .calendar-grid .btn-today:focus, .dropdown-menu.datepicker .calendar-grid .btn-today:hover {\n    background-color: #b8dde7;\n}\n\n.dropdown-menu.datepicker .calendar-grid .btn-primary, .dropdown-menu.datepicker .calendar-grid .btn-primary:hover, .dropdown-menu.datepicker .calendar-grid .btn-primary:focus {\n    background-color: #2980b9;\n    color: #ffffff;\n}\n\n.dropdown-menu.datepicker .custom-buttons .btn {\n    border-color: #ffffff;\n}\n\n.comments > li {\n    padding: 8px 6px;\n}\n\n.comments > li > .title {\n\n    color: #888888;\n    font-size: 13px;\n    margin: 0 0 3px 0;\n}\n\n.comments > li > .message {\n    text-align: left;\n    color: #3a3a3a;\n    padding-left: 3px;\n    word-wrap: break-word;\n}\n\n.comments > li > .message:before, .comments > li > .message:after {\n    font-style: italic;\n}\n\n.comments > li > .message:before {\n    content: open-quote;\n    padding-right: 2px;\n}\n\n.comments > li > .message:after {\n    content: close-quote;\n    padding-left: 2px;\n}\n\n\n.form-wrapper {\n    margin: 10px 0 20px 0;\n}\n\n.form-wrapper .well-sm {\n    padding: 6px 9px;\n}\n\n.checklist.simple-list .user-picture {\n    margin-top: 2px;\n    width: 32px;\n    height: 32px;\n    background-size: 32px 32px;\n    line-height: 32px;\n    font-size: 15px;\n}\n\n.checklist.simple-list > li {\n    cursor: pointer;\n}\n\n.diagram-popup-wrapper {\n    min-width: 1000px;\n    max-width: 1400px;\n    min-height: 300px;\n    z-index: 1005;\n}\n\n.model-preview-wrapper {\n    width: 100%;\n    height:100%;\n    padding: 10px;\n    overflow: auto;\n}\n\n.upload-image-form {\n    margin: 0 20% 0 20%;\n    text-align: center;\n}\n\n.upload-image-dropbox {\n    background: #F8F8F8;\n    border: 5px dashed #DDD;\n    color: #8e8e8e;\n    text-align: center;\n    padding: 35px 0 35px 0;\n    margin: 20px 0 20px 0;\n}\n\n.upload-image-dropbox.dragover {\n    border: 5px dashed #55ae4d;\n    color: #55ae4d;\n}\n\n\n.google-drive-browse .simple-list, .alfresco-cloud-browse .simple-list {\n    position: relative;\n    max-height: 350px;\n    min-height: 350px;\n    height: 350px;\n    overflow: auto;\n}\n\n.alfresco-cloud-browse .col-xs-6 {\n    padding: 0 0 0 10px;\n}\n\n.alfresco-cloud-browse .col-xs-6:first-child {\n    padding-left: 0;\n}\n\n.crumbs {\n    margin: 5px 0px;\n    color: #666666;\n}\n\n.crumb {\n    color: #666666;\n    cursor: pointer;\n}\n\n.crumb i {\n    font-size: 80%;\n}\n\n.crumb:hover {\n    color: #2980b9;\n    text-decoration: underline;\n}\n.crumb:hover i {\n    color: #666666;\n}\n\n/** Apps */\n.apps-wrapper {\n    padding-top: 55px;\n    width: 1200px;\n    margin: 0 auto;\n}\n\n.app-wrapper {\n    float: left;\n    width: 300px;\n}\n\n.app {\n    margin: 10px 10px;\n    height: 200px;\n    border-left: 8px solid transparent;\n    overflow: hidden;\n    position: relative;\n    cursor: pointer;\n}\n\n.app .backdrop, .app .logo {\n    position: absolute;\n    text-shadow: none;\n\n    -webkit-transition: all 1s ease;\n    -moz-transition: all 1s ease;\n    -o-transition: all 1s ease;\n    transition: all 1s ease;\n\n    z-index: 4;\n}\n\n.app .backdrop {\n    font-size: 300px;\n    right: 50px;\n    top: -100px;\n}\n\n.app .logo {\n    font-size: 150px;\n    right: 20px;\n    top: 20px;\n}\n\n.app:hover .backdrop {\n    top: -55px;\n}\n\n.app:hover .logo {\n    right: -10px\n}\n\n.app h3 {\n    margin: 15px 10px 0px 10px;\n    position: relative;\n}\n\n.app-content {\n    color: #ffffff;\n    position: relative;\n    z-index: 5;\n}\n\n\n.app-content p {\n    display: none;\n    margin: 10px 0px 10px 10px;\n    padding: 10px 10px 0 0;\n    border-top: 1px solid #ffffff;\n    border-color: rgba(255,255,255, .1);\n}\n\n.app:hover .app-content p {\n    display: inherit;\n}\n\n.app .actions {\n    position: absolute;\n    top: 0px;\n    right: 0;\n    width: 40px;\n    height: 49px;\n    background-color: transparent;\n    line-height: 50px;\n    text-align: center;\n    z-index: 6;\n    visibility: hidden;\n    font-size: 16px;\n    color: #ffffff;\n    border-right: 2px solid transparent;\n    border-top: 2px solid transparent;\n}\n\n.app .selection-marker {\n    position: absolute;\n    top: 0px;\n    right: 5px;\n    width: 50px;\n    height: 48px;\n    font-size: 45px;\n    color: #ffffff;\n    z-index: 6;\n}\n\n.app:hover .actions {\n    visibility: visible;\n}\n.app .actions:hover {\n    background-color: #ffffff;\n    background-color: rgba(255,255,255, .7);\n    text-shadow: none;\n}\n\n.app .actions+.dropdown-menu {\n    background-color: #ffffff;\n    background-color: rgba(255,255,255, .8);\n    text-shadow: none;\n}\n.app-indicator {\n    position: relative;\n    padding-left: 20px;\n    color: #ffffff;\n}\n\n.app-indicator > span {\n    margin-right: 10px;\n    margin-left: 25px;\n    font-size: 16px;\n    padding-right: 15px;\n    white-space: nowrap;\n    text-overflow: ellipsis;\n}\n\n.app-indicator > .btn-group {\n    border-left: 1px solid #999999;\n}\n\n.app-indicator > i {\n    position: absolute;\n    left: 5px;\n    top:6px;\n    font-size: 28px;\n    color: #ffffff;\n    color: rgba(255, 255, 255, .5);\n}\n\n.popover.app-links-popover {\n    margin-top: 0;\n    padding: 5px;\n    width: 446px;\n    max-width: 446px;\n    overflow: auto;\n    max-height: calc(100vh - 40px);\n}\n.app-link-wrapper {\n    float: left;\n    display: inline-block;\n    min-height: 80px;\n    width: 90px;\n    margin: 5px;\n    text-align: center;\n    padding: 5px;\n    padding-top: 10px;\n    -webkit-transition: background-color 0.5s ease-out;\n    -moz-transition: background-color 0.5s ease-out;\n    -o-transition: background-color 0.5s ease-out;\n    transition: background-color 0.5s ease-out;\n    cursor: pointer;\n}\n.app-link-wrapper:hover,\n.app-link-wrapper:active {\n    background-color: #eee;\n}\n.app-link-name  {\n    word-wrap: break-word;\n    color: black;\n    opacity: 0.9;\n    margin-top: 5px;\n}\n.app-link-icon {\n    border-radius: 50%;\n    height: 50px;\n    width: 50px;\n    display: inline-block;\n}\n.app-link-icon > i {\n    color: white;\n    opacity: 0.5;\n    border-radius: 50%;\n    margin-bottom: 5px;\n    padding: 10px;\n    font-size: 30px;\n}\n.app-link-icon > span {\n    color: black;\n}\n\n.app-link-icon.theme-1,\n.app.theme-1 {\n    background-color: #269abc;\n}\n.app.theme-1 {\n    border-color: #269abc;\n    text-shadow: 1px 1px #168aac;\n}\n\n.app-indicator.theme-1 {\n    background: #269abc;\n    background: -moz-linear-gradient(left,  rgba(38,154,188,0) 0%, rgba(38,154,188,0.02) 1%, rgba(38,154,188,1) 30%, rgba(38,154,188,1) 100%); /* FF3.6+ */\n    background: -webkit-linear-gradient(left,  rgba(38,154,188,0) 0%,rgba(38,154,188,0.02) 1%,rgba(38,154,188,1) 30%,rgba(38,154,188,1) 100%); /* Chrome10+,Safari5.1+ */\n    background: -ms-linear-gradient(left,  rgba(38,154,188,0) 0%,rgba(38,154,188,0.02) 1%,rgba(38,154,188,1) 30%,rgba(38,154,188,1) 100%); /* IE10+ */\n    background: linear-gradient(to right,  rgba(38,154,188,0) 0%,rgba(38,154,188,0.02) 1%,rgba(38,154,188,1) 30%,rgba(38,154,188,1) 100%); /* W3C */\n    filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#00269abc', endColorstr='#269abc',GradientType=1 ); /* IE6-9 */\n}\n\n.app-indicator.theme-1 > .btn-group {\n    border-color: #168aac;\n}\n\n.app-indicator.theme-1 > .btn-group .btn-default:hover, .app-indicator.theme-1 > .btn-group .btn-default:focus {\n    background-color: #168aac;\n}\n\n.app.theme-1  .actions+.dropdown-menu li:hover a {\n    background-color: #168aac;\n}\n\n.app.theme-1 .backdrop i {\n    color: #2a9ec0;\n}\n\n.app.theme-1 .logo i {\n    color: #168aac;\n}\n\n.active > .app.preview.theme-1, .app.theme-1:hover {\n    border-color: #168aac;\n}\n\n.app.theme-1 .actions:hover {\n    border-color: #269abc;\n    color: #269abc;\n}\n\n.app-link-icon.theme-2,\n.app.theme-2 {\n    background-color: #7da9b0;\n}\n.app.theme-2 {\n    border-color: #7da9b0;\n    text-shadow: 1px 1px #6d99a0;\n}\n\n.app-indicator.theme-2 {\n    background: #7da9b0;\n    background: -moz-linear-gradient(left,  rgba(125,169,176,0) 0%, rgba(125,169,176,0.02) 1%, rgba(125,169,176,1) 30%, rgba(125,169,176,1) 100%); /* FF3.6+ */\n    background: -webkit-linear-gradient(left,  rgba(125,169,176,0) 0%,rgba(125,169,176,0.02) 1%,rgba(125,169,176,1) 30%,rgba(125,169,176,1) 100%); /* Chrome10+,Safari5.1+ */\n    background: -ms-linear-gradient(left,  rgba(125,169,176,0) 0%,rgba(125,169,176,0.02) 1%,rgba(125,169,176,1) 30%,rgba(125,169,176,1) 100%); /* IE10+ */\n    background: linear-gradient(to right,  rgba(125,169,176,0) 0%,rgba(125,169,176,0.02) 1%,rgba(125,169,176,1) 30%,rgba(125,169,176,1) 100%); /* W3C */\n    filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#00269abc', endColorstr='#269abc',GradientType=1 ); /* IE6-9 */\n}\n\n.app-indicator.theme-2 > .btn-group {\n    border-color: #6d99a0;\n}\n\n.app-indicator.theme-2 > .btn-group .btn-default:hover, .app-indicator.theme-2 > .btn-group .btn-default:focus {\n    background-color: #6d99a0;\n}\n\n.app.theme-2 .actions+.dropdown-menu li:hover a {\n    background-color: #6d99a0;\n}\n\n.app.theme-2 .backdrop i {\n    color: #81adb4;\n}\n\n.app.theme-2 .logo i {\n    color: #6d99a0;\n}\n\n.active > .app.preview.theme-2, .app.theme-2:hover {\n    border-color: #6d99a0;\n}\n\n.app.theme-2 .actions:hover {\n    border-color: #7da9b0;\n    color: #7da9b0;\n}\n\n.app-link-icon.theme-3,\n.app.theme-3 {\n    background-color: #7689ab;\n}\n.app.theme-3 {\n    border-color: #7689ab;\n    text-shadow: 1px 1px #66799b;\n}\n\n.app-indicator.theme-3 {\n    background: #7689ab;\n    background: -moz-linear-gradient(left,  rgba(118,137,171,0) 0%, rgba(118,137,171,0.02) 1%, rgba(118,137,171,1) 30%, rgba(118,137,171,1) 100%); /* FF3.6+ */\n    background: -webkit-linear-gradient(left,  rgba(118,137,171,0) 0%,rgba(118,137,171,0.02) 1%,rgba(118,137,171,1) 30%,rgba(118,137,171,1) 100%); /* Chrome10+,Safari5.1+ */\n    background: -ms-linear-gradient(left,  rgba(118,137,171,0) 0%,rgba(118,137,171,0.02) 1%,rgba(118,137,171,1) 30%,rgba(118,137,171,1) 100%); /* IE10+ */\n    background: linear-gradient(to right,  rgba(118,137,171,0) 0%,rgba(118,137,171,0.02) 1%,rgba(118,137,171,1) 30%,rgba(118,137,171,1) 100%); /* W3C */\n    filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#00269abc', endColorstr='#269abc',GradientType=1 ); /* IE6-9 */\n}\n\n.app-indicator.theme-3 > .btn-group {\n    border-color: #66799b;\n}\n\n.app-indicator.theme-3 > .btn-group .btn-default:hover, .app-indicator.theme-3 > .btn-group .btn-default:focus {\n    background-color: #66799b;\n}\n\n.app.theme-3 .actions+.dropdown-menu li:hover a {\n    background-color: #66799b;\n}\n\n.app.theme-3 .backdrop i {\n    color: #7a8daf;\n}\n\n.app.theme-3 .logo i {\n    color: #66799b;\n}\n\n.active > .app.preview.theme-3, .app.theme-3:hover {\n    border-color: #66799b;\n}\n\n.app.theme-3 .actions:hover {\n    border-color: #7689ab;\n    color: #7689ab;\n}\n\n.app-link-icon.theme-4,\n.app.theme-4 {\n    background-color: #c74e3e;\n}\n.app.theme-4 {\n    border-color: #c74e3e;\n    text-shadow: 1px 1px #b73e2e;\n}\n\n.app-indicator.theme-4 {\n    background: #c74e3e;\n    background: -moz-linear-gradient(left,  rgba(199,78,62,0) 0%, rgba(199,78,62,0.02) 1%, rgba(199,78,62,1) 30%, rgba(199,78,62,1) 100%); /* FF3.6+ */\n    background: -webkit-linear-gradient(left,  rgba(199,78,62,0) 0%,rgba(199,78,62,0.02) 1%,rgba(199,78,62,1) 30%,rgba(199,78,62,1) 100%); /* Chrome10+,Safari5.1+ */\n    background: -ms-linear-gradient(left,  rgba(199,78,62,0) 0%,rgba(199,78,62,0.02) 1%,rgba(199,78,62,1) 30%,rgba(199,78,62,1) 100%); /* IE10+ */\n    background: linear-gradient(to right,  rgba(199,78,62,0) 0%,rgba(199,78,62,0.02) 1%,rgba(199,78,62,1) 30%,rgba(199,78,62,1) 100%); /* W3C */\n    filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#00269abc', endColorstr='#269abc',GradientType=1 ); /* IE6-9 */\n}\n\n.app-indicator.theme-4 > .btn-group {\n    border-color: #b73e2e;\n}\n\n.app-indicator.theme-4 > .btn-group .btn-default:hover, .app-indicator.theme-4 > .btn-group .btn-default:focus {\n    background-color: #b73e2e;\n}\n\n.app.theme-4 .actions+.dropdown-menu li:hover a {\n    background-color: #b73e2e;\n}\n\n\n.app.theme-4 .backdrop i {\n    color: #cb5245;\n}\n\n.app.theme-4 .logo i {\n    color: #b73e2e;\n}\n\n.active > .app.preview.theme-4, .app.theme-4:hover {\n    border-color: #b73e2e;\n}\n\n.app.theme-4 .actions:hover {\n    border-color: #c74e3e;\n    color: #c74e3e;\n}\n\n.app-link-icon.theme-5,\n.app.theme-5 {\n    background-color: #fab96c;\n}\n.app.theme-5 {\n    border-color: #fab96c;\n    text-shadow: 1px 1px #eaa95c;\n}\n\n.app-indicator.theme-5 {\n    background: #fab96c;\n    background: -moz-linear-gradient(left,  rgba(250,185,108,0) 0%, rgba(250,185,108,0.02) 1%, rgba(250,185,108,1) 30%, rgba(250,185,108,1) 100%); /* FF3.6+ */\n    background: -webkit-linear-gradient(left,  rgba(250,185,108,0) 0%,rgba(250,185,108,0.02) 1%,rgba(250,185,108,1) 30%,rgba(250,185,108,1) 100%); /* Chrome10+,Safari5.1+ */\n    background: -ms-linear-gradient(left,  rgba(250,185,108,0) 0%,rgba(250,185,108,0.02) 1%,rgba(250,185,108,1) 30%,rgba(250,185,108,1) 100%); /* IE10+ */\n    background: linear-gradient(to right,  rgba(250,185,108,0) 0%,rgba(250,185,108,0.02) 1%,rgba(250,185,108,1) 30%,rgba(250,185,108,1) 100%); /* W3C */\n    filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#00269abc', endColorstr='#269abc',GradientType=1 ); /* IE6-9 */\n}\n\n.app-indicator.theme-5 > .btn-group {\n    border-color: #eaa95c;\n}\n\n.app-indicator.theme-5 > .btn-group .btn-default:hover, .app-indicator.theme-5 > .btn-group .btn-default:focus {\n    background-color: #eaa95c;\n}\n\n.app.theme-5 .actions+.dropdown-menu li:hover a {\n    background-color: #eaa95c;\n}\n\n.app.theme-5 .backdrop i {\n    color: #febd70;\n}\n\n.app.theme-5 .logo i {\n    color: #eaa95c;\n}\n\n.active > .app.preview.theme-5, .app.theme-5:hover {\n    border-color: #eaa95c;\n}\n\n.app.theme-5 .actions:hover {\n    border-color: #fab96c;\n    color: #fab96c;\n}\n\n.app-link-icon.theme-6,\n.app.theme-6 {\n    background-color: #759d4c;\n}\n.app.theme-6 {\n    border-color: #759d4c;\n    text-shadow: 1px 1px #658d3c;\n}\n\n.app-indicator.theme-6 {\n    background: #759d4c;\n    background: -moz-linear-gradient(left,  rgba(117,157,76,0) 0%, rgba(117,157,76,0.02) 1%, rgba(117,157,76,1) 30%, rgba(117,157,76,1) 100%); /* FF3.6+ */\n    background: -webkit-linear-gradient(left,  rgba(117,157,76,0) 0%,rgba(117,157,76,0.02) 1%,rgba(117,157,76,1) 30%,rgba(117,157,76,1) 100%); /* Chrome10+,Safari5.1+ */\n    background: -ms-linear-gradient(left,  rgba(117,157,76,0) 0%,rgba(117,157,76,0.02) 1%,rgba(117,157,76,1) 30%,rgba(117,157,76,1) 100%); /* IE10+ */\n    background: linear-gradient(to right,  rgba(117,157,76,0) 0%,rgba(117,157,76,0.02) 1%,rgba(117,157,76,1) 30%,rgba(117,157,76,1) 100%); /* W3C */\n    filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#00269abc', endColorstr='#269abc',GradientType=1 ); /* IE6-9 */\n}\n\n.app-indicator.theme-6 > .btn-group {\n    border-color: #658d3c;\n}\n\n.app-indicator.theme-6 > .btn-group .btn-default:hover, .app-indicator.theme-6 > .btn-group .btn-default:focus {\n    background-color: #658d3c;\n}\n\n.app.theme-6 .actions+.dropdown-menu li:hover a {\n    background-color: #658d3c;\n}\n\n.app.theme-6 .backdrop i {\n    color: #79a150;\n}\n\n.app.theme-6 .logo i {\n    color: #658d3c;\n}\n\n.active > .app.preview.theme-6, .app.theme-6:hover {\n    border-color: #658d3c;\n}\n\n.app.theme-6 .actions:hover {\n    border-color: #759d4c;\n    color: #759d4c;\n}\n\n.app-link-icon.theme-7,\n.app.theme-7 {\n    background-color: #b1b489;\n}\n.app.theme-7 {\n    border-color: #b1b489;\n    text-shadow: 1px 1px #a1a479;\n}\n\n.app-indicator.theme-7 {\n    background: #b1b489;\n    background: -moz-linear-gradient(left,  rgba(177,180,137,0) 0%, rgba(177,180,137,0.02) 1%, rgba(177,180,137,1) 30%, rgba(177,180,137,1) 100%); /* FF3.6+ */\n    background: -webkit-linear-gradient(left,  rgba(177,180,137,0) 0%,rgba(177,180,137,0.02) 1%,rgba(177,180,137,1) 30%,rgba(177,180,137,1) 100%); /* Chrome10+,Safari5.1+ */\n    background: -ms-linear-gradient(left,  rgba(177,180,137,0) 0%,rgba(177,180,137,0.02) 1%,rgba(177,180,137,1) 30%,rgba(177,180,137,1) 100%); /* IE10+ */\n    background: linear-gradient(to right,  rgba(177,180,137,0) 0%,rgba(177,180,137,0.02) 1%,rgba(177,180,137,1) 30%,rgba(177,180,137,1) 100%); /* W3C */\n    filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#00269abc', endColorstr='#269abc',GradientType=1 ); /* IE6-9 */\n}\n\n.app-indicator.theme-7 > .btn-group {\n    border-color: #a1a479;\n}\n\n.app-indicator.theme-7 > .btn-group .btn-default:hover, .app-indicator.theme-7 > .btn-group .btn-default:focus {\n    background-color: #a1a479;\n}\n\n.app.theme-7 .actions+.dropdown-menu li:hover a {\n    background-color: #a1a479;\n}\n\n.app.theme-7 .backdrop i {\n    color: #b5b98d;\n}\n\n.app.theme-7 .logo i {\n    color: #a1a479;\n}\n\n.active > .app.preview.theme-7, .app.theme-7:hover {\n    border-color: #a1a479;\n}\n\n.app.theme-7 .actions:hover {\n    border-color: #b1b489;\n    color: #b1b489;\n}\n\n.app-link-icon.theme-8,\n.app.theme-8 {\n    background-color: #a17299;\n}\n.app.theme-8 {\n    border-color: #a17299;\n    text-shadow: 1px 1px #916289;\n}\n\n.app-indicator.theme-8 {\n    background: #a17299;\n    background: -moz-linear-gradient(left,  rgba(161,114,153,0) 0%, rgba(161,114,153,0.02) 1%, rgba(161,114,153,1) 30%, rgba(161,114,153,1) 100%); /* FF3.6+ */\n    background: -webkit-linear-gradient(left,  rgba(161,114,153,0) 0%,rgba(161,114,153,0.02) 1%,rgba(161,114,153,1) 30%,rgba(161,114,153,1) 100%); /* Chrome10+,Safari5.1+ */\n    background: -ms-linear-gradient(left,  rgba(161,114,153,0) 0%,rgba(161,114,153,0.02) 1%,rgba(161,114,153,1) 30%,rgba(161,114,153,1) 100%); /* IE10+ */\n    background: linear-gradient(to right,  rgba(161,114,153,0) 0%,rgba(161,114,153,0.02) 1%,rgba(161,114,153,1) 30%,rgba(161,114,153,1) 100%); /* W3C */\n    filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#00269abc', endColorstr='#269abc',GradientType=1 ); /* IE6-9 */\n}\n\n.app-indicator.theme-8 > .btn-group {\n    border-color: #916289;\n}\n\n.app-indicator.theme-8 > .btn-group .btn-default:hover, .app-indicator.theme-8 > .btn-group .btn-default:focus {\n    background-color: #916289;\n}\n\n.app.theme-8 .actions+.dropdown-menu li:hover a {\n    background-color: #916289;\n}\n\n.app.theme-8 .backdrop i {\n    color: #a5769d;\n}\n\n.app.theme-8 .logo i {\n    color: #916289;\n}\n\n.active > .app.preview.theme-8, .app.theme-8:hover {\n    border-color: #916289;\n}\n\n.app.theme-8 .actions:hover {\n    border-color: #a17299;\n    color: #a17299;\n}\n\n.app-link-icon.theme-9,\n.app.theme-9 {\n    background-color: #696c67;\n}\n.app.theme-9 {\n    border-color: #696c67;\n    text-shadow: 1px 1px #595c57;\n}\n\n.app-indicator.theme-9 {\n    background: #696c67;\n    background: -moz-linear-gradient(left,  rgba(105,108,103,0) 0%, rgba(105,108,103,0.02) 1%, rgba(105,108,103,1) 30%, rgba(105,108,103,1) 100%); /* FF3.6+ */\n    background: -webkit-linear-gradient(left,  rgba(105,108,103,0) 0%,rgba(105,108,103,0.02) 1%,rgba(105,108,103,1) 30%,rgba(105,108,103,1) 100%); /* Chrome10+,Safari5.1+ */\n    background: -ms-linear-gradient(left,  rgba(105,108,103,0) 0%,rgba(105,108,103,0.02) 1%,rgba(105,108,103,1) 30%,rgba(105,108,103,1) 100%); /* IE10+ */\n    background: linear-gradient(to right,  rgba(105,108,103,0) 0%,rgba(105,108,103,0.02) 1%,rgba(105,108,103,1) 30%,rgba(105,108,103,1) 100%); /* W3C */\n    filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#00269abc', endColorstr='#269abc',GradientType=1 ); /* IE6-9 */\n}\n\n.app-indicator.theme-9 > .btn-group {\n    border-color: #595c57;\n}\n\n.app-indicator.theme-9 > .btn-group .btn-default:hover, .app-indicator.theme-9 > .btn-group .btn-default:focus {\n    background-color: #595c57;\n}\n\n.app.theme-9 .actions+.dropdown-menu li:hover a {\n    background-color: #595c57;\n}\n\n.app.theme-9 .backdrop i {\n    color: #6d706b;\n}\n\n.app.theme-9 .logo i {\n    color: #595c57;\n}\n\n.active > .app.preview.theme-9, .app.theme-9:hover {\n    border-color: #595c57;\n}\n\n.app.theme-9 .actions:hover {\n    border-color: #696c67;\n    color: #696c67;\n}\n\n.app-link-icon.theme-10,\n.app.theme-10 {\n    background-color: #cabb33;\n}\n.app.theme-10 {\n    border-color: #cabb33;\n    text-shadow: 1px 1px #baab23;\n}\n\n.app-indicator.theme-10 {\n    background: #cabb33;\n    background: -moz-linear-gradient(left,  rgba(202,187,51,0) 0%, rgba(202,187,51,0.02) 1%, rgba(202,187,51,1) 30%, rgba(202,187,51,1) 100%); /* FF3.6+ */\n    background: -webkit-linear-gradient(left,  rgba(202,187,51,0) 0%,rgba(202,187,51,0.02) 1%,rgba(202,187,51,1) 30%,rgba(202,187,51,1) 100%); /* Chrome10+,Safari5.1+ */\n    background: -ms-linear-gradient(left,  rgba(202,187,51,0) 0%,rgba(202,187,51,0.02) 1%,rgba(202,187,51,1) 30%,rgba(202,187,51,1) 100%); /* IE10+ */\n    background: linear-gradient(to right,  rgba(202,187,51,0) 0%,rgba(202,187,51,0.02) 1%,rgba(202,187,51,1) 30%,rgba(202,187,51,1) 100%); /* W3C */\n    filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#00269abc', endColorstr='#269abc',GradientType=1 ); /* IE6-9 */\n}\n\n.app-indicator.theme-10 > .btn-group {\n    border-color: #baab23;\n}\n\n.app-indicator.theme-10 > .btn-group .btn-default:hover, .app-indicator.theme-10 > .btn-group .btn-default:focus {\n    background-color: #baab23;\n}\n\n.app.theme-10 .actions+.dropdown-menu li:hover a {\n    background-color: #baab23;\n}\n\n.app.theme-10 .backdrop i {\n    color: #cebf37;\n}\n\n.app.theme-10 .logo i {\n    color: #baab23;\n}\n\n.active > .app.preview.theme-10, .app.theme-10:hover {\n    border-color: #baab23;\n}\n\n.app.theme-10 .actions:hover {\n    border-color: #cabb33;\n    color: #cabb33;\n}\n\n.create-app {\n    margin: 10px;\n    height: 200px;\n    padding: 5px;\n    background-color: #f8f8f7;\n}\n\n.create-app h3 {\n    font-size: 24px;\n    color: #666666;\n    line-height: 180px;\n    text-align: center;\n\n    -webkit-transition: font-size .2s ease;\n    -moz-transition: font-size .2s ease;\n    -o-transition: font-size .2s ease;\n    transition: font-size .2s ease;\n}\n\n.app.create-app:hover {\n    border-color: #eeeeee;\n}\n\n.app.create-app:hover h3{\n    font-size: 110px;\n}\n\n.app.create-app .fixed {\n    position: absolute;\n    top: 40px;\n    left: 0;\n    right: 0;\n    color: #666666;\n    visibility: hidden;\n    text-align: center;\n    font-size: 24px;\n}\n\n.app.create-app:hover .fixed {\n    visibility: visible;\n}\n\n.app.create-app .backdrop  {\n    color: #eeeeee;\n    top: -100px;\n}\n\n.app.create-app:hover .backdrop  {\n    top: -85px;\n}\n\n/** Landing logo (shared between apps) */\n\n.landing-logo {\n    line-height: 40px;\n    height: 40px;\n    width: 180px;\n    float: left;\n    cursor: pointer;\n}\n\n.landing-logo img {\n    max-height: 35px;\n    margin-top: -3px;\n    margin-left: 10px;\n}\n\n/** Password strength indicator */\n\n\nul#strength {\n    display:inline;\n    list-style:none;\n    margin:0;\n    margin-left:15px;\n    padding:0;\n    vertical-align:2px;\n}\n\nul#strength li {\n    background-color:#DDD;\n    border-radius:2px;\n    display:inline-block;\n    height:5px;\n    margin-right:1px;\n    width:20px;\n}\n\nul#strength li.pwd-very-weak {\n    background-color: #a02c2c;\n}\n\nul#strength li.pwd-weak {\n    background-color: #d45500;\n}\n\nul#strength li.pwd-good {\n    background-color: #ffcc00;\n}\n\nul#strength li.pwd-strong {\n    background-color: #aad400;\n}\n\nul#strength li.pwd-very-strong {\n    background-color: #71c837;\n}\n\nul#strength span {\n    font-weight: bold;\n    padding-left: 5px;\n}\n\nul#strength span.pwd-very-weak {\n    color: #a02c2c;\n}\n\nul#strength span.pwd-weak {\n    color: #d45500;\n}\n\nul#strength span.pwd-good {\n    color: #ffcc00;\n}\n\nul#strength span.pwd-strong {\n    color: #aad400;\n}\n\nul#strength span.pwd-very-strong {\n    color: #71c837;\n}\n\n\nul#strength > li:last-child {\n    margin:0;\n}\n\n.modal-body.content-preview-wrapper {\n    background-color: #404040;\n    padding: 0;\n}\n.modal-body.content-preview-wrapper .nothing-to-see {\n    background-color: #ffffff;\n    padding: 20px 0 0 0;\n    height: 480px;\n    text-align: center;\n    font-size: 15px;\n    color: #666666;\n}\n\n/**\n * Some modal windows need to have a scrollbar inside the modal window.\n * Use the following classes to do so.\n */\n\n.modal-body-with-overflow {\n    max-height: 500px;\n    overflow: auto;\n}\n\n.preview-image {\n    max-width: 100%;\n    max-height: 100%;\n    display: block;\n    margin-left: auto;\n    margin-right: auto;\n}\n\n@media (min-width: 1400px) {\n    .apps-wrapper {\n        width: 1400px;\n    }\n\n    .app-wrapper {\n        float: left;\n        width: 350px;\n    }\n}\n\n@media (max-width: 1200px) {\n    .apps-wrapper {\n        width: 900px;\n    }\n}\n\n\n/** Task details **/\n.summary-header {\n    margin-top: 10px;\n}\n.summary-header > div{\n    float: left;\n    margin-right: 15px;\n    border-left: 1px solid #cccccc;\n    padding-left: 15px;\n    min-height: 32px;\n}\n\n.summary-header.pack > div {\n    min-height: 32px;\n}\n\n.summary-header.pack  .title.title-lg {\n}\n\n.summary-header > div:first-child {\n    border-left: none;\n    padding-left: 0;\n}\n\n.summary-header .btn.btn-xs {\n    background-color: transparent;\n    border: 1px solid #bbbbbb;\n    color: #666666;\n    margin-top: 3px;\n}\n\n.summary-header .btn.btn-xs:hover, .summary-header .btn.btn-xs:active, .summary-header .btn.btn-xs:focus{\n    border: 1px solid #bbbbbb;\n    color: #666666;\n}\n\n.user-picture {\n    text-align: center;\n    font-size: 15px;\n    height: 32px;\n    width: 32px;\n    line-height: 32px;\n    padding: 0;\n    margin: 0 2px 0 0;\n    overflow: hidden;\n    color: #ffffff;\n    background: #2980b9 no-repeat center center;\n    background-size: 32px 32px;\n    cursor: pointer;\n    border: 1px solid transparent;\n}\n\n.summary-header .user-picture {\n    float: left;\n}\n\n.user-picture.no-picture {\n    border-color: #2980b9;\n}\n\n.user-picture span {\n    visibility: hidden;\n}\n\n.user-picture.more {\n    background-color: #6fc2d7;\n    color: #f6f6f6;\n}\n\n.user-picture.add {\n    background-color: #6fc2d7;\n    color: #f6f6f6;\n    font-size: 20px;\n    margin-left: 5px;\n}\n\n.user-picture:hover span, .user-picture.no-picture span, .user-picture.more span, .user-picture.add span {\n    visibility: visible;\n}\n\n.user-picture.no-picture:hover {\n    border-color: #32a3c0;\n}\n\n.summary-header .title {\n    margin-bottom: 2px;\n    font-size: 12px;\n    color: #666666;\n    cursor: pointer;\n}\n\n.summary-header .title.title-lg {\n    margin-top: 5px;\n    font-size: 14px;\n}\n\n.summary-header .title.title-lg > span {\n    font-size: 15px;\n}\n\n.summary-header .title > span {\n    font-size: 13px;\n    color: #555555;\n}\n\n.related-content {\n    float: left;\n    text-align: center;\n    height: 32px;\n    width: 32px;\n    line-height: 32px;\n    padding: 0;\n    margin: 0;\n    overflow: hidden;\n    cursor: pointer;\n}\n\n.related-content i.icon {\n    line-height: 32px;\n    font-size: 26px;\n}\n\n.related-content.more {\n    font-size: 15px;\n    color: #999999;\n    text-align: left;\n    padding: 0 5px;\n    width: auto;\n}\n\n.summary-header .title+.related-content {\n    margin-left: -4px;\n}\n\n.tabs-wrapper {\n    margin-bottom: 20px;\n}\n\n.tabs-wrapper .badge {\n    background-color: #bfbfbf;\n    font-size: 10px;\n}\n\n.component .tabs-wrapper .title {\n    background: rgb(238, 241, 241);\n}\n\n.tabs {\n    padding: 0px;\n    margin-bottom: -1px;\n    margin-left: -1px;\n    margin-top: -1px;\n    z-index: 2000;\n}\n\n.tabs .tab {\n    float: left;\n    border-right: 1px solid #eef1f1;\n    border-bottom: 1px solid #eef1f1;\n    background-color: #f5f7f7;\n    margin-top: 0;\n}\n\n.tabs .tab a {\n    font-size: 15px;\n    font-weight: bold;\n    text-decoration: none;\n    margin: 0;\n    padding: 8px 15px;\n    line-height: 39px;\n    color: #7b8a8a;\n    background-color: #f5f7f7;\n    cursor: pointer;\n}\n\n.tabs .tab.active {\n    border-bottom-color: #ffffff;\n    background-color: #ffffff;\n}\n\n.tabs .label {\n    margin-left: 5px;\n}\n\n.tabs .tab a:hover {\n    color: #384042;\n}\n\n.tabs .tab.active a, .tabs .tab.active a:hover {\n    background-color: #ffffff;\n    color: #000000;\n    cursor: pointer;\n}\n\n.tabs {\n    list-style: none inside;\n    padding:0;\n    margin: 0;\n    border-bottom: 1px solid #bbbbbb;\n}\n\n.tabs > li {\n    display: block;\n    float: left;\n    margin-bottom: -1px;\n    border: 1px solid transparent;\n    border-bottom-color: #bbbbbb;\n}\n\n.tabs > li a {\n    display: block;\n    padding: 8px 40px;\n    text-decoration: none;\n    color: #888a85;\n    font-size: 16px;\n}\n.tabs > li a .badge {\n    min-width: 10px;\n    font-size: 12px;\n    margin-left: 4px;\n    padding: 2px 4px;\n    background-color: #5f8dd3;\n}\n\n.tabs > li a:hover {\n    text-decoration: none;\n    color: #5f8dd3;\n}\n\n.tabs > li.active {\n    border-color: #bbbbbb;\n    border-bottom-color: #ffffff;\n\n    -moz-border-radius-topleft: 5px;\n    -webkit-border-top-left-radius: 5px;\n    border-top-left-radius: 5px;\n    -moz-border-radius-topright: 5px;\n    -webkit-border-top-right-radius: 5px;\n    border-top-right-radius: 5px;\n\n}\n\n.tabs > li.active a {\n    color: #000000;\n    cursor: default;\n}\n\n.main-content .tabs {\n    padding: 0 0 0 10px;\n    margin-bottom: 5px;\n    margin-top: 8px;\n}\n\n.people-list.simple-list li {\n    line-height: 24px;\n    padding: 4px;\n}\n\n.people-list li .actions {\n    margin-top: 4px;\n}\n.simple-list .user-picture {\n    float: left;\n    font-size: 12px;\n    width: 24px;\n    height: 24px;\n    line-height: 24px;\n    background-size: 24px 24px;\n    margin-right: 6px;\n    border: none;\n}\n\n.content-group {\n    border-bottom: 1px dotted #eeeeee;\n    margin: 5px 0;\n}\n\n.content-group:last-child {\n    border: none;\n}\n\n/* Help */\n\n.help-container {\n    display: table;\n    height: 100%;\n    padding: 0 30px;\n    margin: 0px auto;\n}\n\n.help-container.fixed {\n    padding-top: 40px;\n}\n\n.help-container > div {\n    display: table-cell;\n    vertical-align: middle;\n    position: relative;\n}\n\n.help-text {\n    margin-top: 10px;\n    color: #636363;\n    background: #eee;\n    padding: 20px;\n    -webkit-border-radius: 10px;\n    -moz-border-radius: 10px;\n    border-radius: 10px;\n    max-width: 450px;\n    font-size: 14px;\n    position: relative;\n}\n\n.help-text.wide {\n    max-width: 550px;\n}\n\n.help-text .description {\n    margin-bottom: 25px;\n}\n\n.help-text .description:last-child {\n    margin-bottom: 0px;\n}\n\n.help-entry {\n    margin: 5px 0 5px 10px;\n    cursor: pointer;\n    padding: 5px;\n}\n\n.help-entry:hover, .help-entry.active {\n    background-color: #f6f6f7;\n}\n\n.help-entry.active {\n    padding: 10px;\n}\n\n.help-entry:hover > span {\n    color: #2980b9;\n}\n\n.help-entry.active:hover > span {\n    color: #636363;\n}\n\n.help-entry .pull-right > .btn {\n    border: none;\n}\n\n.help-entry .note, .action-note {\n    font-size: 12px;\n    color: #999999;\n    padding-left: 38px;\n}\n\n.help-entry:hover .note {\n    color: #999999;\n    text-decoration: none;\n}\n\n.action-note:hover {\n    text-decoration: underline;\n    cursor: pointer;\n}\n\n.help-entry > .glyphicon {\n    margin-right: 5px;\n}\n\n.help-entry > .icon {\n    margin-right: 5px;\n    font-size: 110%;\n}\n\n.help-text > a {\n    color: #636363;\n}\n\n.help-entry:hover > .glyphicon {\n    text-decoration: none;\n}\n\n.no-custom-apps .help-container {\n    float: left;\n    padding-left: 50px;\n}\n\n.content-list.simple-list li {\n    width: 50%;\n    float: left;\n    padding: 5px 10px;\n    margin-bottom: 10px;\n\n    white-space: nowrap;\n    overflow: hidden;\n    text-overflow: ellipsis;\n}\n\n.content-list.simple-list li .subtle {\n    white-space: nowrap;\n    overflow: hidden;\n    text-overflow: ellipsis;\n}\n\n.content-list.simple-list li:hover {\n    background-color: #ffffff;\n}\n\n.content-list.simple-list li .actions {\n    background-color: #ffffff;\n    border: 1px solid #eeeeee;\n    padding: 5px 4px 0 4px;\n    display: inline-block;\n    right: 0px;\n}\n\n.content-list.simple-list .subtle {\n    font-size: 12px;\n}\n.content-list.simple-list .nothing-to-see {\n    border: 1px solid #999999;\n    box-shadow: 1px 1px 2px #dddddd;\n    background-color: #ffffff;\n    width: 130px;\n    height: 155px;\n    padding: 50px 0 0 0;\n    text-align: center;\n}\n\n.content-list.simple-list .nothing-to-see .loading {\n    display: inline-block;\n    position: relative;\n    margin: 3px;\n    left: 0;\n}\n\n.frame {\n    white-space: nowrap;\n    text-align: left;\n    margin-bottom: 5px;\n    width: 100%;\n}\n\n.helper {\n    display: inline-block;\n}\n\n.frame img {\n    max-height: 155px;\n    padding: 5px;\n\n    border: 1px solid #999999;\n    box-shadow: 1px 1px 2px #dddddd;\n    background-color: #ffffff;\n}\n\n.content-list.simple-list li .frame .thumb-wrapper {\n    padding: 10px;\n    background-color: transparent;\n    display: inline-block;\n}\n.content-list.simple-list li:hover .frame .thumb-wrapper {\n    background-color: #eeeeee;\n}\n\n.form-wrapper .col-md-12 .content-list.simple-list li {\n    width: 25%;\n}\n\n.dynamicTableContainer {\n    /*min-height: 165px;*/\n}\n\n.dynamicTable {\n  border: 1px solid rgb(212,212,212) !important;\n  border-radius: 4px;\n  border-spacing: 2px;\n  display: block;\n  width: 100%;\n  height: 180px;\n  border-collapse: collapse;\n  margin-bottom: 5px;\n}\n\n.dynamicTable td, .dynamicTable tr {\n  border: 1px solid rgb(212,212,212) !important;\n  padding: 6px;\n}\n\n.dynamicTableContainer .control-buttons {\n  margin-bottom: 10px;\n}\n\n.edit-in-place-icon {\n    font-size: 20px;\n    color: darkgrey;\n    display: none;\n    margin-left: 5px;\n}\n.edit-in-place span {\n    cursor: pointer;\n}\n.edit-in-place:hover span {\n    display: inline-block;\n}\n.edit-in-place input {\n    display: none;\n}\n.edit-in-place.active span {\n    display: none;\n}\n.edit-in-place.active input {\n    display: inline-block;\n}\n\n.has-error .dynamicTable {\n  border: 1px solid #a94442 !important;\n}\n\n.noHeight {\n  height:auto;\n}\n\n.form-control.ng-invalid {\n    border-color: #a94442 !important;\n    box-shadow: 0 1px 1px rgba(0,0,0,0.075) inset, 0 0 8px rgba(255,0,0,0.5);\n}\n\n.control-label.ng-invalid {\n    color: #a94442 !important;\n    font-weight: bold;\n\n}\n"
  },
  {
    "path": "flowable-ui-web/task/styles/style-landing.css",
    "content": "/* Login */\n\n.login-container {\n    width: 100%;\n    height: 100%;\n}\n\n.login-left-column {\n    width: 66%;\n    background-image: url(../images/login-banner.png);\n    background-repeat: no-repeat;\n    background-color: #8FBE6F;\n    background-position: left bottom;\n    height: 100%;\n    display: inline-block;\n    vertical-align: top;\n    position: relative;\n}\n\n.login-right-column {\n    width: 30%;\n    height: 100%;\n    display: inline-block;\n    vertical-align: top;\n    position: relative;\n}\n\n.login-form {\n    position: absolute;\n    width: 100%;\n    padding: 40px 10px 40px 40px;\n    top: 25%;\n    left: 0;\n}\n\n.login-error {\n    color: #e4593d\n}\n\n/* App selection popup */\n\n.item-wrapper {\n    padding-left: 0;\n    margin-top: 5px;\n}\n\n.item-wrapper .message {\n    text-align: left;\n    margin-left: 5px;\n    line-height: 40px;\n    color: #606b7d;\n}\n.item-wrapper .message span {\n    font-size: 14px;    \n}\n\n.item-wrapper .item {\n    width: 25%;\n    padding: 0;\n    margin: 0;\n    float: left;\n}\n\n.modal-footer {\n    position: relative;\n}\n.modal-footer .loading {\n    position: absolute;\n    top: 5px;\n    left: 50%;\n    margin-left: -20px;\n}\n"
  },
  {
    "path": "flowable-ui-web/task/views/common/popover/select-functional-group-popover.html",
    "content": "<div class=\"popover\" click-anywhere=\"$hide()\" ignore-class=\"toggle-functional-group-select\">\n    <div class=\"arrow\"></div>\n    <div class=\"popover-header\">\n        <span class=\"title\">{{title && (title | translate) || ('GENERAL.TITLE.SELECT-GROUP' | translate)}}</span>\n\n        <div class=\"actions\">\n            <a ng-click=\"$hide()\">{{'GENERAL.ACTION.CLOSE' | translate}}</a>\n        </div>\n    </div>\n\n    <div class=\"popover-wrapper\">\n    \n        <div class=\"form-group\">\n            <input class=\"form-control\" type=\"text\" id=\"people-select-input\" placeholder=\"{{ 'GENERAL.MESSAGE.SELECT-GROUP-SEARCH-PLACEHOLDER' | translate }}\" auto-focus\n                   custom-keys up-pressed=\"previousGroup()\" down-pressed=\"nextGroup()\" enter-pressed=\"confirmGroup()\"\n                   delayed-model=\"popupModel.filter\" delay=\"200\"/>\n        </div>\n        <h4>\n            <span translate=\"GENERAL.TITLE.MATCHING-GROUPS\"></span>\n        </h4>\n        <div class=\"people-select\">\n            <div class=\"no-results\" ng-show=\"popupModel.groupResults.length == 0\">\n                <span>{{'GENERAL.MESSAGE.SELECT-GROUP-NO-MATCHING-RESULTS' | translate}}</span>\n            </div>\n            <ul class=\"simple-list selectable pack\" ng-show=\"popupModel.groupResults.length > 0\" scroll-to-active scroll-to-active-model=\"popupModel.selectedGroup.id\">\n                <li ng-click=\"confirmGroup(group);\" ng-repeat=\"group in popupModel.groupResults\"\n                    ng-class=\"{'active': group.id === popupModel.selectedGroup.id}\">\n                    <span>{{group.name}}</span>\n                </li>\n            </ul>\n        </div>\n        \n    </div>\n</div>"
  },
  {
    "path": "flowable-ui-web/task/views/common/popover/select-people-popover.html",
    "content": "<div class=\"popover\" click-anywhere=\"$hide()\" ignore-class=\"toggle-people-select\">\n    <div class=\"arrow\"></div>\n    <div class=\"popover-header\">\n        <span class=\"title\">{{title && (title | translate) || ('GENERAL.TITLE.INVOLVE-PEOPLE' | translate)}}</span>\n\n        <div class=\"actions\">\n            <a ng-click=\"$hide()\" ng-show=\"!newTask.loading\">\n                {{'GENERAL.ACTION.CLOSE' | translate}}</a>\n        </div>\n    </div>\n\n    <div class=\"popover-wrapper\">\n\n        <div class=\"form-group\" ng-if=\"popupModel.formFields\">\n            <div class=\"col-xs-4\">\n                <label>{{'INVOLVE-PEOPLE.SOURCE.TYPE' | translate}}</label>\n            </div>\n            <div class=\"col-xs-8\">\n                <div class=\"btn-group btn-group-justified\">\n                  <div class=\"btn-group\">\n                    <button type=\"button\" class=\"btn btn-default\" ng-click=\"setSearchType()\" ng-model=\"popupModel.userSourceType\" ng-class=\"{'active' : (!popupModel.userSourceType || popupModel.userSourceType == 'search')}\">{{'INVOLVE-PEOPLE.SOURCE.SEARCH-OPTION' | translate}}</button>\n                  </div>\n                  <div class=\"btn-group\">\n                    <button type=\"button\" class=\"btn btn-default\" ng-click=\"setFormFieldType()\" ng-model=\"popupModel.userSourceType\" ng-class=\"{'active' : popupModel.userSourceType == 'field'}\">{{'INVOLVE-PEOPLE.SOURCE.FIELD-OPTION' | translate}}</button>\n                  </div>\n                </div>\n            </div>\n        </div>\n        \n        <div ng-if=\"popupModel.formFields\" class=\"col-xs-12\" style=\"margin-bottom:10px\" />\n\n        <div ng-show=\"(!popupModel.userSourceType || popupModel.userSourceType == 'search')\">\n            <div class=\"form-group\">\n                <input class=\"form-control\" type=\"text\" id=\"people-select-input\" placeholder=\"{{ 'INVOLVE-PEOPLE.SEARCH-PLACEHOLDER' | translate }}\" auto-focus\n                       custom-keys up-pressed=\"previousUser()\" down-pressed=\"nextUser()\" enter-pressed=\"confirmUser()\"\n                       delayed-model=\"popupModel.filter\" delay=\"200\"/>\n                <div class=\"subtle\" translate=\"GENERAL.MESSAGE.SELECT-PEOPLE-HELP\" style=\"padding: 5px 0 0 1px;\"></div>\n            </div>\n            <h4>\n                <!--<span translate=\"GENERAL.TITLE.RECENT-PEOPLE\" ng-show=\"popupModel.showRecentResults\"></span>-->\n                <span translate=\"GENERAL.TITLE.MATCHING-PEOPLE\" ng-if=\"!popupModel.showRecentResults\"></span>\n            </h4>\n            <div class=\"people-select\">\n                <div class=\"no-results\" ng-show=\"popupModel.userResults.length == 0\">\n                    <span>{{'INVOLVE-PEOPLE.NO-MATCHING-RESULTS' | translate}}</span>\n                </div>\n                <ul class=\"simple-list selectable pack\" ng-show=\"popupModel.userResults.length > 0\" scroll-to-active scroll-to-active-model=\"popupModel.selectedUser.id\">\n                    <li ng-click=\"confirmUser(user);\" ng-repeat=\"user in popupModel.userResults\"\n                        ng-class=\"{'active': user.id === popupModel.selectedUser.id}\">\n                        <i class=\"icon icon-user\"></i><span user-name=\"user\"></span>\n                    </li>\n                </ul>\n            </div>\n        </div>\n        \n        <div ng-show=\"popupModel.userSourceType == 'field'\" class=\"form-group clearfix\">\n            <div class=\"col-xs-4\">\n                <label>{{'PROCESS-BUILDER.PUBLISH-STEP.SOURCE.FORM-FIELD' | translate}}:</label>\n            </div>\n            <div class=\"col-xs-8\">\n                <div id=\"userFormField\" variables-select include-type=\"false\" expand-relative=\"true\" field-type-filter=\"popupModel.userFieldFilter\"\n                       select-title=\"'FORM-BUILDER.MESSAGE.READONLY-TEXT-INSERT-FIELD'\" fields=\"popupModel.formFields\" selected-field=\"popupModel.userField\" ignore-selection=\"true\"></div>\n            </div>\n        </div>\n        \n    </div>\n\n</div>"
  },
  {
    "path": "flowable-ui-web/task/views/common/templates/external-content-template.html",
    "content": "<!--[if IE 9]>\n<div class=\"dropzoneIE9 selectionIE9\" ng-if=\"!folderSelect\">\n\n    <div loading=\"model.uploading\"></div>\n    <div class=\"error\" ng-if=\"errorMessage\">\n        {{errorMessage}}\n    </div>\n\n    <div class=\"clearfix\">\n        <div ng-if=\"!linkOnly\" class=\"select-file\">\n            <button class=\"btn btn-xs\" ngf-select=\"\" ngf-change=\"onFileSelect($files, true)\">{{'CONTENT.MESSAGE.SELECT' | translate}}</button>\n        </div>\n    </div>\n</div>\n<![endif]-->\n<!--[if gt IE 9]> <!-- -->\n<div class=\"dropzone selection\" ngf-drop ngf-change=\"onFileSelect($files, false)\"\n     ngf-drop-available=\"dropSupported=true\"\n     ngf-drag-over-class=\"dragover\" ng-class=\"{'uploading': model.uploading}\" ng-if=\"!folderSelect\">\n\n    <div loading=\"model.uploading\"></div>\n    <div class=\"error\" ng-if=\"errorMessage\">\n        {{errorMessage}}\n    </div>\n\n    <input type=\"file\" ngf-select=\"\" ngf-change=\"onFileSelect($files)\" ng-disabled=\"model.uploading\" ng-if=\"!linkOnly\">\n\n    <div class=\"clearfix\">\n        <div class=\"message\" ng-if=\"!linkOnly\">\n            {{'CONTENT.MESSAGE.DRAGOVER' | translate}}\n        </div>\n        <div class=\"select-file\" ng-if=\"!linkOnly\">{{'CONTENT.MESSAGE.DROP' | translate}}\n            <button class=\"btn btn-xs\">{{'CONTENT.MESSAGE.SELECT' | translate}}</button>\n        </div>\n    </div>\n</div>\n<div ng-if=\"folderSelect\">\n    <button class=\"btn btn-xs\" ng-click=\"selectFolder($event)\">\n        {{'COMMON.SELECT-FOLDER' | translate}}\n    </button>\n</div>\n<!-- <![endif]-->\n"
  },
  {
    "path": "flowable-ui-web/task/views/landing.html",
    "content": "\n<div id={{app.id}} class=\"app-wrapper\" ng-repeat=\"app in model.apps\">\n    <div class=\"app {{app.theme}}\">\n        <a href=\"{{app.fixedUrl}}\">\n            <div class=\"app-content\">\n                <h3>{{app.titleKey && (app.titleKey | translate) || app.name}}</h3>\n\n                <p>{{app.descriptionKey && (app.descriptionKey | translate) || app.description}}</p>\n            </div>\n            <div class=\"backdrop\">\n                <i class=\"{{app.icon}}\"></i>\n            </div>\n            <div class=\"logo\">\n                <i class=\"{{app.icon}}\"></i>\n            </div>\n        </a>\n    </div>\n</div>\n"
  },
  {
    "path": "flowable-ui-web/task/views/modal/add-app-definition-modal.html",
    "content": "\n<div class=\"modal\" ng-controller=\"AddAppDefinitionPopupCtrl\">\n    <div class=\"modal-dialog wide\">\n        <div class=\"modal-content\">\n            <div class=\"modal-header\">\n                <button type=\"button\" class=\"close\" ng-click=\"$hide()\">&times;</button>\n                <h3 class=\"modal-title\" translate=\"APP.POPUP.ADD-APP-TITLE\"></h3>\n                <div class=\"summary\">\n                    {{'APP.POPUP.ADD-APP-SUMMARY' | translate}}\n                </div>\n            </div>\n            <div class=\"modal-body modal-body-with-overflow\">\n                <div class=\"error-message\" ng-if=\"errorMessage\">\n                    <span>{{errorMessage}}</span>\n                </div>\n                <div class=\"row\">\n                    <div class=\"col-xs-10 item-wrapper\">\n                        <div class=\"item fadein\" ng-repeat=\"app in popup.apps.data\">\n                            <div class=\"app {{app.theme ? app.theme : 'theme-1'}}\" ng-click=\"selectApp(app); $event.stopPropagation();\">\n                                <div class=\"selection-marker\" ng-show=\"isAppSelected(app)\">\n                                    <i class=\"glyphicon glyphicon-ok\"></i>\n                                </div>\n                                <div class=\"app-content\">\n                                    <h3>{{app.name}}</h3>\n                        \n                                    <p>{{app.description}}</p>\n                                </div>\n                                <div class=\"backdrop\">\n                                    <i ng-show=\"!app.icon\" class=\"icon icon-choice\"></i>\n                                    <i ng-show=\"app.icon\" class=\"glyphicon {{app.icon}}\"></i>\n                                </div>\n                                <div class=\"logo\">\n                                    <i ng-show=\"!app.icon\" class=\"icon icon-choice\"></i>\n                                    <i ng-show=\"app.icon\" class=\"glyphicon {{app.icon}}\"></i>\n                                </div>\n                            </div>\n                        </div>\n                    </div>\n                </div>\n            </div>\n            <div class=\"modal-footer\">\n                <div loading=\"popup.loading\"></div>\n                <button ng-click=\"cancel()\" class=\"btn btn-primary\" translate ng-disabled=\"popup.loading\">GENERAL.ACTION.CANCEL</button>\n                <button ng-disabled=\"popup.selectedApps.length == 0 || popup.loading\" ng-click=\"deploy()\" class=\"btn btn-primary\" translate>GENERAL.ACTION.DEPLOY</button>\n            </div>\n        </div>\n    </div>\n</div>"
  },
  {
    "path": "flowable-ui-web/task/workflow/i18n/en.json",
    "content": "{\n    \"COMMON\" : {\n        \"SELECT-FOLDER\": \"Select folder...\"\n    },\n    \"GENERAL\": {\n        \"MAIN-TITLE\": \"Flowable - My Tasks\",\n        \"ERROR\": {\n            \"GENERIC\": \"Sorry, an error occured...\",\n            \"UNKNOWN\": \"Sorry, an error occured while performing the requested operation.\",\n            \"BAD_REQUEST\": \"An error occured while performing the requested operation\",\n            \"NOT_FOUND\": \"The resource you are trying to access does not exist\",\n            \"UNAUTHORIZED\": \"You should sign in in order to perform the requested operation.\",\n            \"FORBIDDEN\": \"You are not allowed to perform the requested operation\",\n            \"INTERNAL_SERVER_ERROR\": \"Sorry, an unexpected error occured while performing the requested operation.\"\n        },\n        \"NAVIGATION\": {\n            \"TASKS\": \"Tasks\",\n            \"PROCESSES\": \"Processes\",\n            \"CASES\": \"Cases\",\n            \"DESIGN\": \"Design\",\n            \"CREATE\": \"+ Create\",\n            \"LOGIN\": \"Sign in\"\n        },\n        \"TITLE\": {\n            \"ADD-COMMENT\": \"Create comment\",\n            \"INVOLVE-PEOPLE\": \"Select person\",\n            \"RECENT-PEOPLE\": \"Recent people\",\n            \"MATCHING-PEOPLE\": \"Matching people\",\n            \"SELECT-GROUP\": \"Select group\",\n            \"MATCHING-GROUPS\": \"Matching groups\",\n            \"FILTER\": \"Filter\",\n            \"SELECT-DATE\": \"Select a date\"\n        },\n        \"ACTION\": {\n            \"LOGOUT\": \"Sign out\",\n            \"ADD-COMMENT\": \"Add comment\",\n            \"SAVE\": \"Save\",\n            \"CANCEL\": \"Cancel\",\n            \"CLOSE\": \"Close\",\n            \"CONFIRM\": \"Confirm\",\n            \"SHOW-MORE\": \"Show more...\"\n        },\n        \"MESSAGE\": {\n            \"SELECT-PEOPLE-HELP\": \"Use &uparrow; and &downarrow; to select and press Enter to confirm\",\n            \"SELECT-GROUP-HELP\": \"Use &uparrow; and &downarrow; to select and press Enter to confirm\",\n            \"SELECT-GROUP-SEARCH-PLACEHOLDER\": \"Search group\",\n            \"SELECT-GROUP-NO-MATCHING-RESULTS\": \"Use the search box above to find groups.\",\n            \"UPLOAD-CONTENT\": \"Select or drop a file\",\n            \"UPLOAD-CONTENT-NO-DROP\": \"Select a file to upload\",\n            \"DROPZONE\": \"Drop the file to upload\",\n            \"YES\": \"Yes\",\n            \"NO\": \"No\"\n        },\n        \"TIME\": {\n            \"HOURS\": \"hours\",\n            \"MINUTES\": \"minutes\",\n            \"SECONDS\": \"seconds\"\n        },\n        \"ABOUT\": {\n            \"TYPE\": \"Type\",\n            \"LICENSED-TO\": \"Licensed To\",\n            \"EXPIRES\": \"Expires\",\n            \"COPYRIGHT\": \"© 2005-2015 Alfresco Software Inc. All rights reserved.\",\n            \"LEGAL\": \"Legal and License\"\n        }\n    },\n    \"LOGIN\": {\n        \"TITLE\": \"Sign in\",\n        \"USERNAME\": \"Username\",\n        \"USERNAME-PLACEHOLDER\": \"Enter your username\",\n        \"PASSWORD\": \"Password\",\n        \"PASSWORD-PLACEHOLDER\": \"Enter your password\",\n        \"ACTION\": {\n            \"CONFIRM\": \"Sign in\"\n        }\n    },\n    \"TASK\": {\n        \"SECTION\": {\n            \"PEOPLE\": \"People\",\n            \"CONTENT\": \"Content\",\n            \"COMMENTS\": \"Comments\",\n            \"NOTES\": \"Notes\"\n        },\n        \"FILTER\": {\n            \"CREATED-DESC\": \"Newest first\",\n            \"CREATED-ASC\": \"Oldest first\",\n            \"DUE-DESC\": \"Due last\",\n            \"DUE-ASC\": \"Due first\",\n            \"TEXT\": \"Filter\",\n            \"TEXT-PLACEHOLDER\": \"Search by task name\",\n            \"TEXT-SUMMARY\": \"Filtered by: {{text}}\",\n            \"PROCESS-DEFINITION\": \"Process Definition\",\n            \"PROCESS-DEFINITION-PLACEHOLDER\": \"Select process definition ...\",\n            \"STATE\": \"State\",\n            \"STATE-OPEN\": \"open\",\n            \"STATE-COMPLETED\": \"completed\",\n            \"ASSIGNMENT\": \"Assignment\",\n            \"ASSIGNMENT-INVOLVED\": \"Tasks where I am involved\",\n            \"ASSIGNMENT-ASSIGNEE\": \"Tasks where I am the assignee\",\n            \"ASSIGNMENT-CANDIDATE\": \"Tasks where I am one of the candidates\",\n            \"ASSIGNMENT-GROUP\": \"Tasks assigned to the group \\\"{{name}}\\\"\",\n            \"RESET\": \"Reset filters\"\n        },\n        \"ALERT\": {\n            \"COMMENT-ADDED\": \"Comment was added to \\\"{{name}}\\\"\",\n            \"PERSON-INVOLVED\": \"{{firstName}} {{lastName}} is now involved in \\\"{{taskName}}\\\"\",\n            \"PERSON-NO-LONGER-INVOLVED\": \"{{firstName}} {{lastName}} is no longer involved in \\\"{{taskName}}\\\"\",\n            \"CREATED\": \"Task \\\"{{name}}\\\" was created\",\n            \"COMPLETED\": \"Task completed\",\n            \"SAVED\": \"Task form is saved\",\n            \"ASSIGNED\": \"Task \\\"{{taskName}}\\\" is now asigned to {{firstName}} {{lastName}}\",\n            \"RELATED-CONTENT-ADDED\": \"\\\"{{name}}\\\" has been added to the task\",\n            \"RELATED-CONTENT-ADDED-LOADING\": \"\\\"{{name}}\\\" has been added to the task. The content will be available once retrieved from the external source.\"\n        },\n        \"ACTION\": {\n            \"COMPLETE-TASK-WITH-FORM\": \"Complete form\",\n            \"COMPLETE\": \"Complete\",\n            \"CLAIM\": \"Claim\",\n            \"ASSIGN\": \"Assign\",\n            \"REASSIGN\": \"Reassign\",\n            \"CREATE\": \"+ Create Task\",\n            \"CREATE-SUB-TASK\": \"Create sub task\",\n            \"CREATE-CONFIRM\": \"Create\",\n            \"INVOLVE\": \"+ Involve people\",\n            \"ADD-COMMENT\": \"+ Add comment\",\n            \"ADD-COMMENT-CONFIRM\": \"Add comment\",\n            \"ADD-CONTENT\": \"+ Add content\",\n            \"CLEAR-DUEDATE\": \"Clear due date\",\n            \"DUE-TODAY\": \"Due today\",\n            \"CLEAR-DATE\": \"Clear date\",\n            \"DATE-TODAY\": \"Date today\",\n            \"AUDIT-LOG\": \"Audit Log\"\n        },\n        \"TITLE\": {\n            \"ASSIGN\": \"Select assignee\",\n            \"ASSIGNEE\": \"Assignee\",\n            \"CONTENT\": \"Related content\",\n            \"SUBTASK\": \"Sub tasks\",\n            \"CREATE-NEW\": \"New Task\",\n            \"FORM\": \"Form\",\n            \"DETAILS\": \"Details\",\n            \"ADD-RELATED-CONTENT\": \"Add related content\",\n            \"SELECT-DUEDATE\": \"Select due date\",\n            \"SELECT-DATE\": \"Select date\",\n            \"NO-CONTENT-ITEMS\": \"No content items\",\n            \"NO-PEOPLE-INVOLVED\": \"No people involved\",\n            \"NO-COMMENTS\": \"No comments\",\n            \"COMMENT-COUNT\": \"comment\",\n            \"COMMENTS-COUNT\": \"comments\",\n            \"NO-SUBTASKS\": \"No sub tasks\",\n            \"SUBTASK-COUNT\": \"sub task \",\n            \"SUBTASKS-COUNT\": \"sub tasks\",\n            \"SHOW-DETAILS\": \"Show details\",\n            \"SHOW-FORM\": \"Show form\"\n        },\n        \"FIELD\": {\n            \"NAME\": \"Name\",\n            \"DESCRIPTION\": \"Description\",\n            \"ASSIGNEE\": \"Assignee\",\n\n            \"DUE\": \"Due\",\n            \"PROCESS-INSTANCE\": \"Part of process\",\n            \"CASE-INSTANCE\": \"Part of case\",\n            \"PARENT-TASK\": \"Part of task\",\n            \"ENDED\": \"Ended\",\n            \"DURATION\": \"Duration\"\n        },\n        \"MESSAGE\": {\n            \"NO-NAME\": \"Nameless task\",\n            \"NO-ASSIGNEE\": \"Assigned to nobody\",\n            \"NO-DUEDATE\": \"No due date\",\n            \"DUE-ON\": \"Due\",\n            \"CREATED-ON\": \"Created\",\n            \"ENDED-ON\": \"Completed\",\n            \"REACHED-ON\": \"Reached\",\n            \"COMPLETED-BY\": \"Completed by\",\n            \"NO-DESCRIPTION\": \"This task has no description\",\n            \"NO-RELATED-CONTENT\": \"This task has no related content yet...\",\n            \"NO-PEOPLE-INVOLVED\": \"This task has no people involved yet...\",\n            \"NO-COMMENTS\": \"This task has no comments yet...\",\n            \"INVOLVE-PEOPLE-PLACEHOLDER\": \"+ Add person\",\n            \"CONTENT-UPLOADED-BY\": \"Added by \",\n            \"ASSIGNEE\": \"Assigned to\",\n            \"NEW-COMMENT-PLACEHOLDER\": \"Enter a comment to add to this task\",\n            \"COMMENT-HEADER\": \"Added by {{createdBy | username}}, {{created | dateformat:\\\"fromNow\\\"}}\",\n            \"NO-FILTER\": \"Showing your tasks, no filter applied\",\n            \"FILTERED\": \"Showing your tasks, filtered\",\n            \"NO-TASKS\": \"No matching tasks found...\",\n            \"DURATION\": \"Took {{duration}}\",\n            \"CLAIM-TASK-FIRST\": \"To see and fill in the form for this task, you need to claim this task first. You can do that by pressing the blue button in the top right of the page.\",\n            \"NO-TASKS-HELP\": \"Well, it looks like there are no tasks for you! To get something started, you can:\",\n            \"NO-SUCH-TASK-HELP\": \"The task you are looking for cannot be found! If you want to, you can instead:\",\n            \"NO-SUCH-TASK-RETURN-TO-LIST\": \"Return to your list of tasks\",\n            \"NO-TASKS-CREATE-TASK\": \"Create a task for yourself or assign it to someone else\",\n            \"NO-TASKS-CREATE-PROCESS\": \"Start a new process and then track its progress\"\n        },\n        \"HELP\" : {\n            \"DESCRIPTION\": \"This task has no details yet. You can change that by choosing one of these actions:\",\n            \"COMPLETED-DESCRIPTION\": \"This completed task has no details.\",\n            \"DESCRIPTION-WITH-CLAIM\": \"This task has no details yet. You can change that by choosing one of the following actions. In addition, to complete this task you need to claim it first by pressing the blue button in the top right of the page.\",\n            \"ADD-PEOPLE\": \"Involve someone else and start collaborating\",\n            \"ADD-COMMENT\": \"Enlighten others by adding a comment\",\n            \"ADD-CONTENT\": \"Add a document and share the knowledge\",\n            \"ADD-SUBTASK\": \"Create a sub task\"\n        }\n    },\n    \"PROCESS\": {\n        \"ALERT\": {\n            \"COMMENT-ADDED\": \"Comment was added\",\n            \"STARTED\": \"A new  \\\"{{processDefinitionName}}\\\" process was started\",\n            \"START-PROCESS-CONTENT-ADD-FAILED\": \"Failed to add {{noOfFiles}} file(s) to the process\"\n        },\n        \"TITLE\": {\n            \"DIAGRAM\": \"Process diagram\",\n            \"EXECUTION\": \"Execution\",\n            \"EXECUTIONS\": \"Executions\",\n            \"EXPRESSION\": \"Expression\",\n            \"SCRIPT\": \"Script\",\n            \"RESULT\": \"Result\",\n            \"VARIABLES\": \"Variables\",\n            \"LOG\": \"Log\"\n        },\n        \"FILTER\": {\n            \"CREATED-DESC\": \"Newest first\",\n            \"CREATED-ASC\": \"Oldest first\",\n            \"ENDED-DESC\": \"Completed most recently\",\n            \"ENDED-ASC\": \"Completed least recently\",\n            \"STATE-SUMMARY\": \"Showing {{state.title | translate}} processes\",\n            \"STATE\": \"Process State\",\n            \"STATE-RUNNING\": \"running\",\n            \"STATE-COMPLETED\": \"completed\",\n            \"STATE-ALL\": \"all\"\n        },\n        \"MESSAGE\": {\n            \"NO-DESCRIPTION\": \"This process instance has no description\",\n            \"NO-FILTER\": \"Showing all process instances, not filtered\",\n            \"NO-INSTANCES\": \"No matching process instances found...\",\n            \"NO-INSTANCES-HELP\": \"There are no processes that are running now. If your processes have completed, you can find them using the filter for the process list. To get going with something new you can:\",\n            \"NO-INSTANCES-HELP-START\": \"Start a new process and track its progress\",\n            \"NO-TASKS\": \"No tasks are currently active ...\",\n            \"NO-COMPLETED-TASKS\": \"No tasks have been completed yet...\",\n            \"NO-BUSINESS-KEY\": \"No business key set\",\n            \"NO-ACTIVE-MILESTONES\": \"No active milestones\",\n            \"CATEGORY\": \"Category: {{processDefinitionCategory}}\",\n            \"NEW-COMMENT-PLACEHOLDER\": \"Enter a comment to add to this process\",\n            \"COMMENT-HEADER\": \"Added by {{createdBy | username}}, {{created | dateformat:\\\"fromNow\\\"}}\",\n            \"SELECT-DEFINITION\": \"Select a process to start from the list below\",\n            \"NO-PROCESS-DEFINITIONS\": \"You cannot start a process since there are no process definitions available\",\n            \"START-PROCESS\": \"Start Process\",\n            \"STARTED-BY\": \"Started by\",\n            \"NO-PROCESS-DEFINITION-SELECTED-HELP\": \"Please select a process definition\"\n        },\n        \"ACTION\" : {\n            \"CREATE\": \"+ Start a process\",\n            \"BACK-TO-LIST\": \"Back to process instances\",\n            \"SHOW-DIAGRAM\": \"Show diagram\",\n            \"CANCEL\": \"Cancel process\",\n            \"EXECUTE\": \"Execute\",\n            \"DELETE\": \"Delete process\",\n            \"ADD-COMMENT\": \"+ Add comment\",\n            \"ADD-COMMENT-CONFIRM\": \"Add comment\",\n            \"AUDIT-LOG\": \"Audit Log\"\n        },\n        \"FIELD\": {\n            \"BUSINESS-KEY\": \"Business key\",\n            \"CATEGORY\": \"Category\",\n            \"PROCESS-DEFINITION\": \"Process definition\",\n            \"STARTED\": \"Started\",\n            \"STARTED-BY\": \"Started by\",\n            \"ENDED\": \"Ended\",\n            \"NAME\": \"Process instance name\",\n            \"NAME-PLACEHOLDER\" : \"Enter an optional name for the process being started\"\n        },\n        \"SECTION\": {\n            \"ACTIVE-TASKS\": \"Active tasks\",\n            \"START-FORM\": \"Start form\",\n            \"COMPLETED-TASKS\": \"Completed tasks\",\n            \"COMMENTS\": \"Comments\",\n            \"CONTENT\" : \"Content\"\n        },\n        \"POPUP\": {\n            \"CANCEL-TITLE\": \"Cancel the process?\",\n            \"CANCEL-DESCRIPTION\": \"Are you sure you want to cancel process {{name}}?\",\n            \"DELETE-TITLE\": \"Delete the process?\",\n            \"DELETE-DESCRIPTION\": \"Are you sure you want to delete process {{name}}? All tasks, content and comments related to this process will be deleted permanently.\"\n        }\n    },\n    \"CASE\": {\n        \"ALERT\": {\n            \"STARTED\": \"A new  \\\"{{caseDefinitionName}}\\\" case was started\",\n            \"START-CASE-CONTENT-ADD-FAILED\": \"Failed to add {{noOfFiles}} file(s) to the case\"\n        },\n        \"TITLE\": {\n            \"DIAGRAM\": \"Case diagram\"\n        },\n        \"FILTER\": {\n            \"CREATED-DESC\": \"Newest first\",\n            \"CREATED-ASC\": \"Oldest first\",\n            \"ENDED-DESC\": \"Completed most recently\",\n            \"ENDED-ASC\": \"Completed least recently\",\n            \"STATE-SUMMARY\": \"Showing {{state.title | translate}} cases\",\n            \"STATE\": \"Case State\",\n            \"STATE-RUNNING\": \"running\",\n            \"STATE-COMPLETED\": \"completed\",\n            \"STATE-ALL\": \"all\"\n        },\n        \"MESSAGE\": {\n            \"NO-DESCRIPTION\": \"This case instance has no description\",\n            \"NO-FILTER\": \"Showing all case instances, not filtered\",\n            \"NO-INSTANCES\": \"No matching case instances found...\",\n            \"NO-INSTANCES-HELP\": \"There are no cases that are running now. If your cases have completed, you can find them using the filter for the case list. To get going with something new you can:\",\n            \"NO-INSTANCES-HELP-START\": \"Start a new case and track its progress\",\n            \"NO-TASKS\": \"No tasks are currently active ...\",\n            \"NO-COMPLETED-TASKS\": \"No tasks have been completed yet...\",\n            \"NO-BUSINESS-KEY\": \"No business key set\",\n            \"CATEGORY\": \"Category: {{processDefinitionCategory}}\",\n            \"SELECT-DEFINITION\": \"Select a case to start from the list below\",\n            \"NO-CASE-DEFINITIONS\": \"You cannot start a case since there are no case definitions available\",\n            \"START-CASE\": \"Start Case\",\n            \"STARTED-BY\": \"Started by\",\n            \"STAGE-STARTED\": \"Started\",\n            \"STAGE-ENDED\": \"Ended\",\n            \"STAGE-NOT-STARTED\": \"Not started yet\",\n            \"STATE\": \"State\",\n            \"STAGE-NO-NAME\": \"Nameless stage\",\n            \"MILESTONE-REACHED-ON\": \"Reached\",\n            \"MILESTONE-TERMINATED-ON\": \"Terminated\",\n            \"NO-CASE-DEFINITION-SELECTED-HELP\": \"Please select a case definition\",\n            \"NO-ACTIVE-STAGES\": \"No active stages\",\n            \"NO-ENDED-STAGES\": \"No ended stages\",\n            \"NO-AVAILABLE-MILESTONES\": \"No active milestones\",\n            \"NO-REACHED-MILESTONES\": \"No reached milestones\",\n            \"NO-AVAILABLE-USER-EVENT-LISTENERS\":\"No User Event Listeners available\",\n            \"NO-COMPLETED-USER-EVENT-LISTENERS\":\"No User Event Listeners completed\",\n            \"USER-EVENT-LISTENER-NO-NAME\": \"Nameless User Event Listener\",\n            \"USER-EVENT-LISTENER-COMPLETED\": \"Completed\",\n            \"ENABLED-PLAN-ITEM_INSTANCE-NO-NAME\": \"No name\",\n            \"START-PLAN-ITEM-INSTANCE\": \"Start\"\n        },\n        \"ACTION\" : {\n            \"CREATE\": \"+ Start a case\",\n            \"BACK-TO-LIST\": \"Back to case instances\",\n            \"SHOW-DIAGRAM\": \"Show diagram\",\n            \"CANCEL\": \"Cancel case\",\n            \"DELETE\": \"Delete case\",\n            \"TRIGGER-USER-EVENT-LISTENER\": \"Trigger\",\n            \"AUDIT-LOG\": \"Audit Log\"\n        },\n        \"FIELD\": {\n            \"BUSINESS-KEY\": \"Business key\",\n            \"CATEGORY\": \"Category\",\n            \"CASE-DEFINITION\": \"Case definition\",\n            \"STARTED\": \"Started\",\n            \"STARTED-BY\": \"Started by\",\n            \"ENDED\": \"Ended\",\n            \"NAME\": \"Case instance name\",\n            \"NAME-PLACEHOLDER\" : \"Enter an optional name for the case being started\"\n        },\n        \"SECTION\": {\n            \"ACTIVE-TASKS\": \"Active tasks\",\n            \"COMPLETED-TASKS\": \"Completed tasks\",\n            \"ACTIVE-STAGES\": \"Available/Active stages\",\n            \"ENDED-STAGES\": \"Ended stages\",\n            \"AVAILABLE-MILESTONES\": \"Available milestones\",\n            \"REACHED-MILESTONES\": \"Reached milestones\",\n            \"AVAILABLE-USER-EVENT-LISTENERS\": \"Available User Event Listeners\",\n            \"COMPLETED-USER-EVENT-LISTENERS\": \"Completed User Event Listeners\",\n            \"CONTENT\" : \"Content\",\n            \"ENABLED-PLAN-ITEM-INSTANCES\": \"Enabled plan item instances\"\n        },\n        \"POPUP\": {\n            \"CANCEL-TITLE\": \"Cancel the case?\",\n            \"CANCEL-DESCRIPTION\": \"Are you sure you want to cancel case {{name}}?\",\n            \"DELETE-TITLE\": \"Delete the case?\",\n            \"DELETE-DESCRIPTION\": \"Are you sure you want to delete case {{name}}? All tasks and content related to this case will be deleted permanently.\"\n        }\n    },\n    \"INVOLVE-PEOPLE\": {\n        \"NO-MATCHING-RESULTS\": \"Use the search box above to find users\",\n        \"SEARCH-PLACEHOLDER\": \"Search user\",\n        \"BACK-TO-SEARCH\": \"Back to search\",\n        \"ACTION-SELECT\": \"Select\"\n    },\n    \"INTEGRATION\": {\n        \"ALERT\": {\n        }\n    },\n    \"CONTENT\": {\n        \"SIMPLE-TYPE\": {\n            \"WORD\": \"Document\",\n            \"EXCEL\": \"Spreadsheet\",\n            \"PDF\": \"PDF Document\",\n            \"IMAGE\": \"Image\",\n            \"FOLDER\": \"Folder\",\n            \"CONTENT\": \"Content\"\n        },\n        \"MESSAGE\": {\n            \"NO-PREVIEW-AVAILABLE\": \"No preview available\",\n            \"PREVIEW-PENDING\": \"Creating preview...\",\n            \"CONTENT-PENDING\": \"Getting content...\",\n            \"NOT-FOUND\": \"The content can not be found\",\n            \"DELETE-CONFIRMATION\": \"Are you sure you want to delete {{name}}?\",\n            \"DROP\": \"Drop or \",\n            \"SELECT\": \"Select a file\",\n            \"DRAGOVER\": \"Drop file to upload\",\n            \"EXTERNAL-ONLY\": \"Select source of content\"\n        },\n        \"TITLE\": {\n            \"DELETE\": \"Delete content\",\n            \"NOT-FOUND\": \"File Not Found\"\n        },\n        \"ACTION\":  {\n        }\n    },\n    \"FORM\" : {\n        \"ACTION\": {\n            \"SAVE\": \"Save\"\n        },\n        \"DEFAULT-OUTCOME\": {\n            \"COMPLETE\": \"Complete\",\n            \"START-PROCESS\": \"Start process\",\n            \"START-CASE\": \"Start case\"\n        },\n        \"MESSAGE\" : {\n            \"SELECT-PERSON\": \"No person selected...\",\n            \"SELECT-GROUP\": \"No group selected...\",\n            \"EMPTY\": \"(empty)\"\n        }\n    },\n    \"APP-DEFINITION\" : {\n        \"MESSAGE\" : {\n            \"NOT-FOUND\": \"No app definition found with the given id\",\n            \"MISSING\": \"Flowable is running in integration mode, but the required app definition is missing\"\n        }\n    }\n}\n"
  },
  {
    "path": "flowable-ui-web/task/workflow/i18n/es.json",
    "content": "{\n    \"COMMON\" : {\n        \"SELECT-FOLDER\": \"Selecciona folder...\"\n    },\n    \"GENERAL\": {\n        \"MAIN-TITLE\": \"Flowable - Mis Tareas\",\n        \"ERROR\": {\n            \"GENERIC\": \"Lo sentimos, un error ocurrio...\",\n            \"UNKNOWN\": \"Lo sentimos, un error ocurrio meintras se ejecutaba la operacion seleccionada.\",\n            \"BAD_REQUEST\": \"Lo sentimos, un error ocurrio meintras se ejecutaba la operacion seleccionada\",\n            \"NOT_FOUND\": \"El recurso que intentas accesar no existe\",\n            \"UNAUTHORIZED\": \"Debes iniciar sesion para realizar la operacion seleccionada.\",\n            \"FORBIDDEN\": \"No tienes permitido realizar la operacion seleccionada\",\n            \"INTERNAL_SERVER_ERROR\": \"Lo sentimos, ocurrio un error inesperado mientras se realizaba la operacion seleccionada.\"\n        },\n        \"NAVIGATION\": {\n            \"TASKS\": \"Tareas\",\n            \"PROCESSES\": \"Procesos\",\n            \"DESIGN\": \"Diseno\",\n            \"CREATE\": \"+ Crear\",\n            \"LOGIN\": \"Iniciar sesion\"\n        },\n        \"TITLE\": {\n            \"ADD-COMMENT\": \"Crear comentario\",\n            \"INVOLVE-PEOPLE\": \"Seleccionar persona\",\n            \"RECENT-PEOPLE\": \"Personas recientes\",\n            \"MATCHING-PEOPLE\": \"Personas similares\",\n            \"SELECT-GROUP\": \"Seleccionar grupo\",\n            \"MATCHING-GROUPS\": \"Grupos similares\",\n            \"FILTER\": \"Filtro\",\n            \"SELECT-DATE\": \"Selecciona una fecha\"\n        },\n        \"ACTION\": {\n            \"LOGOUT\": \"Salir\",\n            \"ADD-COMMENT\": \"Agregar comentario\",\n            \"SAVE\": \"Guardar\",\n            \"CANCEL\": \"Cancelar\",\n            \"CLOSE\": \"Cerrar\",\n            \"CONFIRM\": \"Confirmar\",\n            \"SHOW-MORE\": \"Mostrar mas...\"\n        },\n        \"MESSAGE\": {\n            \"SELECT-PEOPLE-HELP\": \"Usa &uparrow; y &downarrow; para seleccionar y presiona Enter para confirmar\",\n            \"SELECT-GROUP-HELP\": \"Usa &uparrow; y &downarrow; para seleccionar y presiona Enter para confirmar\",\n            \"SELECT-GROUP-SEARCH-PLACEHOLDER\": \"Buscar grupo\",\n            \"SELECT-GROUP-NO-MATCHING-RESULTS\": \"Usa el campo buscar de arriba para encontrar grupos.\",\n            \"UPLOAD-CONTENT\": \"Selecciona o arrastra archivo\",\n            \"UPLOAD-CONTENT-NO-DROP\": \"Seleciona un archivo para subir\",\n            \"DROPZONE\": \"arrastra el archivo para subir\",\n            \"YES\": \"Si\",\n            \"NO\": \"No\"\n        },\n        \"TIME\": {\n            \"HOURS\": \"horas\",\n            \"MINUTES\": \"minutos\",\n            \"SECONDS\": \"segundos\"\n        },\n        \"ABOUT\": {\n            \"TYPE\": \"Tipe\",\n            \"LICENSED-TO\": \"Licenciado A\",\n            \"EXPIRES\": \"Expira\",\n            \"COPYRIGHT\": \"© 2005-2017 Flowable All rights reserved.\",\n            \"LEGAL\": \"Legal and License\"\n        }\n    },\n    \"LOGIN\": {\n        \"TITLE\": \"Iniciar sesion\",\n        \"USERNAME\": \"Usuario\",\n        \"USERNAME-PLACEHOLDER\": \"Introduce tu usuario\",\n        \"PASSWORD\": \"Password\",\n        \"PASSWORD-PLACEHOLDER\": \"Introduce tu password\",\n        \"ACTION\": {\n            \"CONFIRM\": \"Iniciar sesion\"\n        }\n    },\n    \"TASK\": {\n        \"SECTION\": {\n            \"PEOPLE\": \"Prsonas\",\n            \"CONTENT\": \"Contenido\",\n            \"COMMENTS\": \"Comentarios\",\n            \"NOTES\": \"Notas\"\n        },\n        \"FILTER\": {\n            \"CREATED-DESC\": \"El mas reciente primero\",\n            \"CREATED-ASC\": \"El mas antiguo primero\",\n            \"DUE-DESC\": \"El ultimo que vencio\",\n            \"DUE-ASC\": \"El primero que vencio\",\n            \"TEXT\": \"Filtro\",\n            \"TEXT-PLACEHOLDER\": \"Buscar por nombre de tarea\",\n            \"TEXT-SUMMARY\": \"Filtrado por: {{text}}\",\n            \"PROCESS-DEFINITION\": \"Definicion de proceso\",\n            \"PROCESS-DEFINITION-PLACEHOLDER\": \"Seleccionar definicion de proceso ...\",\n            \"STATE\": \"Estado\",\n            \"STATE-OPEN\": \"abierto\",\n            \"STATE-COMPLETED\": \"completado\",\n            \"ASSIGNMENT\": \"Asignacion\",\n            \"ASSIGNMENT-INVOLVED\": \"Tareas donde participo\",\n            \"ASSIGNMENT-ASSIGNEE\": \"Tareas que me asignaron\",\n            \"ASSIGNMENT-CANDIDATE\": \"Tareas que puedo realizar\",\n            \"ASSIGNMENT-GROUP\": \"Tareas asignadas al grupo \\\"{{name}}\\\"\",\n            \"RESET\": \"Resetear filtros\"\n        },\n        \"ALERT\": {\n            \"COMMENT-ADDED\": \"Se agrego un comentario a \\\"{{name}}\\\"\",\n            \"PERSON-INVOLVED\": \"{{firstName}} {{lastName}} esta ahora participando en \\\"{{taskName}}\\\"\",\n            \"PERSON-NO-LONGER-INVOLVED\": \"{{firstName}} {{lastName}} no esta participando mas en \\\"{{taskName}}\\\"\",\n            \"CREATED\": \"Tarea \\\"{{name}}\\\" fue creada\",\n            \"COMPLETED\": \"Tarea completada\",\n            \"SAVED\": \"Formulario de la tarea guardado\",\n            \"ASSIGNED\": \"Tarea \\\"{{taskName}}\\\" se asigno a {{firstName}} {{lastName}}\",\n            \"RELATED-CONTENT-ADDED\": \"\\\"{{name}}\\\" fue agregado a la tarea\",\n            \"RELATED-CONTENT-ADDED-LOADING\": \"\\\"{{name}}\\\" fue agregado a la tarea. El contenido estara disponible cuando se term,ine de cargar desde la fuente externa.\"\n        },\n        \"ACTION\": {\n            \"COMPLETE-TASK-WITH-FORM\": \"Formulario de completar\",\n            \"COMPLETE\": \"Completar\",\n            \"CLAIM\": \"Reclamar\",\n            \"ASSIGN\": \"Asignar\",\n            \"REASSIGN\": \"Reasignar\",\n            \"CREATE\": \"+ Crear Tarea\",\n            \"CREATE-CONFIRM\": \"Crear\",\n            \"INVOLVE\": \"+ Involucrar personas\",\n            \"ADD-COMMENT\": \"+ Agregar comentario\",\n            \"ADD-COMMENT-CONFIRM\": \"Agregar comentario\",\n            \"ADD-CONTENT\": \"+ Agregar contenido\",\n            \"CLEAR-DUEDATE\": \"Borrar fecha de vencimiento\",\n            \"DUE-TODAY\": \"Vencimiento el dia de hoy\",\n            \"CLEAR-DATE\": \"Limpiar fecha\",\n            \"DATE-TODAY\": \"Fecha de hoy\",\n            \"AUDIT-LOG\": \"Audit Log\"\n        },\n        \"TITLE\": {\n            \"ASSIGN\": \"Seleccionar participante\",\n            \"ASSIGNEE\": \"Asignado\",\n            \"CONTENT\": \"Contenido relacionado\",\n            \"CREATE-NEW\": \"Nueva tarea\",\n            \"FORM\": \"Formulario\",\n            \"DETAILS\": \"Detalles\",\n            \"ADD-RELATED-CONTENT\": \"Agregar contenido relacionado\",\n            \"SELECT-DUEDATE\": \"Seleccionar fecha de vencimiento\",\n            \"SELECT-DATE\": \"Seleccionar fecha\",\n            \"NO-CONTENT-ITEMS\": \"No hay contenido relacionado\",\n            \"NO-PEOPLE-INVOLVED\": \"No hay personas involucradas\",\n            \"NO-COMMENTS\": \"No hay comentarios\",\n            \"COMMENT-COUNT\": \"comentarios\",\n            \"COMMENTS-COUNT\": \"comentarios\",\n            \"SHOW-DETAILS\": \"Mostrar detalles\",\n            \"SHOW-FORM\": \"Mostrar formularios\"\n        },\n        \"FIELD\": {\n            \"NAME\": \"Nombre\",\n            \"DESCRIPTION\": \"Descripcion\",\n            \"ASSIGNEE\": \"Asignado\",\n            \"DUE\": \"Vencimiento\",\n            \"PROCESS-INSTANCE\": \"Parte del proceso\",\n            \"ENDED\": \"Finalizado\",\n            \"DURATION\": \"Duracion\"\n        },\n        \"MESSAGE\": {\n            \"NO-NAME\": \"Tarea sin nombre\",\n            \"NO-ASSIGNEE\": \"Asignada a nadie\",\n            \"NO-DUEDATE\": \"Sin fecha de vencimiento\",\n            \"DUE-ON\": \"Vencimiento\",\n            \"CREATED-ON\": \"Creada\",\n            \"ENDED-ON\": \"Completada\",\n            \"REACHED-ON\": \"Alcanzado\",\n            \"COMPLETED-BY\": \"Completada por\",\n            \"NO-DESCRIPTION\": \"Esta tarea no tiene descripcion\",\n            \"NO-RELATED-CONTENT\": \"Esta tarea aun no tiene contenido relacionado...\",\n            \"NO-PEOPLE-INVOLVED\": \"Esta tarea aun no tiene personas involucradas...\",\n            \"NO-COMMENTS\": \"Esta tarea aun no tiene comentarios...\",\n            \"INVOLVE-PEOPLE-PLACEHOLDER\": \"+ Agregar persona\",\n            \"CONTENT-UPLOADED-BY\": \"Agregado por \",\n            \"ASSIGNEE\": \"Asignado a\",\n            \"NEW-COMMENT-PLACEHOLDER\": \"Introduce un comentario a agregar a esta tarea\",\n            \"COMMENT-HEADER\": \"Agregado por {{createdBy | username}}, {{created | dateformat:\\\"fromNow\\\"}}\",\n            \"NO-FILTER\": \"Mostrando tus tareas, ningun filtro aplicado\",\n            \"FILTERED\": \"Mostrando tus tareas, filtradas\",\n            \"NO-TASKS\": \"No se encontraron tareas similares...\",\n            \"DURATION\": \"Tomo {{duration}}\",\n            \"CLAIM-TASK-FIRST\": \"Para ver y llenar el formulario de esta tarea, necesitas reclamar esta tarea primero. puedes hacer eso presionando el boton azul en la esquina superior derecha de la pagina.\",\n            \"NO-TASKS-HELP\": \"Parece que no hay tareas para ti! Para iniciar algo tu puedes:\",\n            \"NO-SUCH-TASK-HELP\": \"La tarea que estas buscando no puede ser encontrada!  Si gustas puedes en lugar de:\",\n            \"NO-SUCH-TASK-RETURN-TO-LIST\": \"Regresar a tu lista de tareas\",\n            \"NO-TASKS-CREATE-TASK\": \"Crear una tarea para ti mismo o asignarsela a alguien mas\",\n            \"NO-TASKS-CREATE-PROCESS\": \"Inicia un nuevo proceso y despues rastrea su progreso\"\n\n        },\n        \"HELP\" : {\n            \"DESCRIPTION\": \"Esta tarea no tiene detalles aun. Puedes cambiar esto eligiendo una de las siguientes acciones:\",\n            \"COMPLETED-DESCRIPTION\": \"Esta tarea completada no tiene detalles.\",\n            \"DESCRIPTION-WITH-CLAIM\": \"Esta tarea no tiene detalles aun. Puedes cambiar esto eligiendo una de las siguientes acciones. para completar esta tarea necesitas reclamarla primero. puedes hacer eso presionando el boton azul en la esquina superior derecha de la pagina.\",\n            \"ADD-PEOPLE\": \"Involucra a alguien mas y comienza a colaborar\",\n            \"ADD-COMMENT\": \"Ilumina a otros agregando un comentario\",\n            \"ADD-CONTENT\": \"Agrega un documento y comparte el conocimiento\"\n        }\n    },\n    \"PROCESS\": {\n        \"ALERT\": {\n            \"COMMENT-ADDED\": \"Se agrego un comentario\",\n            \"STARTED\": \"Se inicio un nuevo proceso  \\\"{{processDefinitionName}}\\\"\",\n            \"START-PROCESS-CONTENT-ADD-FAILED\": \"Falla al agregar {{noOfFiles}} archivos al proceso\"\n        },\n        \"TITLE\": {\n            \"DIAGRAM\": \"Diagrama de proceso\"\n        },\n        \"FILTER\": {\n            \"CREATED-DESC\": \"El mas reciente primero\",\n            \"CREATED-ASC\": \"El mas antiguo primero\",\n            \"ENDED-DESC\": \"Completado recientemente\",\n            \"ENDED-ASC\": \"Completed mas antiguo\",\n            \"STATE-SUMMARY\": \"Mostrando {{state.title | translate}} procesos\",\n            \"STATE\": \"Estado del Proceso \",\n            \"STATE-RUNNING\": \"corriendo\",\n            \"STATE-COMPLETED\": \"completado\",\n            \"STATE-ALL\": \"todo\"\n        },\n        \"MESSAGE\": {\n            \"NO-DESCRIPTION\": \"Esta instancia de proceos no tiene descripcion\",\n            \"NO-FILTER\": \"Mostrando todas las instancias de proceso, no filtradas\",\n            \"NO-INSTANCES\": \"No se encontraron instancias de proceso similares...\",\n            \"NO-INSTANCES-HELP\": \"No hay proceso que esten corriendo ahora. Si tus proceso se han completado, puedes encontrarlos utilizando el  filtro para la lista de procesos. Para iniciar algo nuevo tu puedes:\",\n            \"NO-INSTANCES-HELP-START\": \"Iniciar un nuevo proceso y rastrear su progreso\",\n            \"NO-TASKS\": \"No hay tareas activas actualmente ...\",\n            \"NO-COMPLETED-TASKS\": \"Aun no hay tareas completadas...\",\n            \"NO-BUSINESS-KEY\": \"No se fijo la Business key\",\n            \"NO-ACTIVE-MILESTONES\": \"No hay hitos por alcanzar\",\n            \"CATEGORY\": \"Categoria: {{processDefinitionCategory}}\",\n            \"NEW-COMMENT-PLACEHOLDER\": \"Introduce un comentario para agregarlo a este proceso\",\n            \"COMMENT-HEADER\": \"Agregado por {{createdBy | username}}, {{created | dateformat:\\\"fromNow\\\"}}\",\n            \"SELECT-DEFINITION\": \"Selecciona un proceso a iniciar de la lista debajo\",\n            \"NO-PROCESS-DEFINITIONS\": \"No puedes iniciar un proceso ya que no tienes proceso disponibles\",\n            \"START-PROCESS\": \"Iniciar proceso\",\n            \"STARTED-BY\": \"Iniciado por\",\n            \"NO-PROCESS-DEFINITION-SELECTED-HELP\": \"Por favor selecciona una definicion de proceso\"\n        },\n        \"ACTION\" : {\n            \"CREATE\": \"+ Iniciar proceso\",\n            \"BACK-TO-LIST\": \"Regresar a instancias de proceso\",\n            \"SHOW-DIAGRAM\": \"Mostrar diagrama\",\n            \"CANCEL\": \"Cancelar proceso\",\n            \"DELETE\": \"Borrar proceso\",\n            \"ADD-COMMENT\": \"+ Agregar comentario\",\n            \"ADD-COMMENT-CONFIRM\": \"Agregar comentario\",\n            \"AUDIT-LOG\": \"Audit Log\"\n        },\n        \"FIELD\": {\n            \"BUSINESS-KEY\": \"Business key\",\n            \"CATEGORY\": \"Categoria\",\n            \"PROCESS-DEFINITION\": \"Definicion de proceso\",\n            \"STARTED\": \"Iniciado\",\n            \"STARTED-BY\": \"Iniciado por\",\n            \"ENDED\": \"Finalizado\",\n            \"NAME\": \"Nombre de la instancia de proceso\",\n            \"NAME-PLACEHOLDER\" : \"Introduce un nombre opcional para el proceso que esta siendo iniciado\"\n        },\n        \"SECTION\": {\n            \"ACTIVE-TASKS\": \"Tareas activas\",\n            \"START-FORM\": \"Formulario de inicio\",\n            \"COMPLETED-TASKS\": \"Tareas completadas\",\n            \"COMMENTS\": \"Comentarios\",\n            \"CONTENT\" : \"Contenido\"\n        },\n        \"POPUP\": {\n            \"CANCEL-TITLE\": \"Cancelar el proceso?\",\n            \"CANCEL-DESCRIPTION\": \"Estas seguro que deseas cancelar el proceso {{name}}?\",\n            \"DELETE-TITLE\": \"Eliminar el proceso?\",\n            \"DELETE-DESCRIPTION\": \"Estas seguro que deseas borrar el proceso {{name}}? Todas las tareas, comentarios y contenido relacionado a este proceso se borrara permanentemente.\"\n        }\n    },\n    \"CASE\": {\n        \"ALERT\": {\n            \"STARTED\": \"Un nuevo caso  \\\"{{caseDefinitionName}}\\\" ha comenzado\",\n            \"START-CASE-CONTENT-ADD-FAILED\": \"Fallo al agregar {{noOfFiles}} fichero(s) al caso\"\n        },\n        \"TITLE\": {\n            \"DIAGRAM\": \"Diagrama de Caso\"\n        },\n        \"FILTER\": {\n            \"CREATED-DESC\": \"Nuevo primero\",\n            \"CREATED-ASC\": \"Antiguo primero\",\n            \"ENDED-DESC\": \"Completado más reciente\",\n            \"ENDED-ASC\": \"Completado más antiguo\",\n            \"STATE-SUMMARY\": \"Mostrando {{state.title | translate}} casos\",\n            \"STATE\": \"Estado del Caso\",\n            \"STATE-RUNNING\": \"en ejecución\",\n            \"STATE-COMPLETED\": \"completado\",\n            \"STATE-ALL\": \"todos\"\n        },\n        \"MESSAGE\": {\n            \"NO-DESCRIPTION\": \"Esta instancia de caso no tiene descripción\",\n            \"NO-FILTER\": \"Mostrando todos los casos, sin filtro\",\n            \"NO-INSTANCES\": \"No se han encontrado instancias de caso que coincidan...\",\n            \"NO-INSTANCES-HELP\": \"No hay casos en ejecución. Los casos completados pueden encotrarse usando el filtro. Para comenzar con algo nuevo, podría:\",\n            \"NO-INSTANCES-HELP-START\": \"Comenzar un nuevo caso y seguir su progreso\",\n            \"NO-TASKS\": \"No hay tareas activas actualmente ...\",\n            \"NO-COMPLETED-TASKS\": \"No se han completado tareas aún ...\",\n            \"NO-BUSINESS-KEY\": \"No se ha especificado la clave de negocio\",\n            \"CATEGORY\": \"Categoria: {{processDefinitionCategory}}\",\n            \"SELECT-DEFINITION\": \"Seleccione un caso para comenzar de la lista\",\n            \"NO-CASE-DEFINITIONS\": \"No puede comenzar un case ya que no hay definiciones disponibles\",\n            \"START-CASE\": \"Comenzar un Caso\",\n            \"STARTED-BY\": \"Comenzado por\",\n            \"STAGE-STARTED\": \"Comenzada\",\n            \"STAGE-ENDED\": \"Terminada\",\n            \"STAGE-NOT-STARTED\": \"No comenzada aún\",\n            \"STATE\": \"Estado\",\n            \"STAGE-NO-NAME\": \"Etapa sin nombre\",\n            \"MILESTONE-REACHED-ON\": \"Alcanzado\",\n            \"MILESTONE-TERMINATED-ON\": \"Terminado\",\n            \"NO-CASE-DEFINITION-SELECTED-HELP\": \"Por favor escoja una definición de caso\",\n            \"NO-ACTIVE-STAGES\": \"No hay etapas activas\",\n            \"NO-ENDED-STAGES\": \"No hay etapas finalizadas\",\n            \"NO-AVAILABLE-MILESTONES\": \"No hay hitos disponibles\",\n            \"NO-REACHED-MILESTONES\": \"No se han alcanzado hitos\",\n            \"NO-AVAILABLE-USER-EVENT-LISTENERS\":\"No hay eventos de usuario disponibles\",\n            \"NO-COMPLETED-USER-EVENT-LISTENERS\":\"No hay eventos de usuario completados\",\n            \"USER-EVENT-LISTENER-NO-NAME\": \"Evento de usuario sin nombre\",\n            \"USER-EVENT-LISTENER-COMPLETED\": \"Completado\",\n            \"ENABLED-PLAN-ITEM_INSTANCE-NO-NAME\": \"Sin nombre\",\n            \"START-PLAN-ITEM-INSTANCE\": \"Empezar\"\n        },\n        \"ACTION\" : {\n            \"CREATE\": \"+ Comenzar un caso\",\n            \"BACK-TO-LIST\": \"Regresar a las instancias de caso\",\n            \"SHOW-DIAGRAM\": \"Mostrar digrama\",\n            \"CANCEL\": \"Cancelar caso\",\n            \"DELETE\": \"Borrar caso\",\n            \"TRIGGER-USER-EVENT-LISTENER\": \"Disparar\",\n            \"AUDIT-LOG\": \"Bitácora de Auditoría\"\n        },\n        \"FIELD\": {\n            \"BUSINESS-KEY\": \"Business key\",\n            \"CATEGORY\": \"Categoria\",\n            \"CASE-DEFINITION\": \"Definición de caso\",\n            \"STARTED\": \"Comenzado\",\n            \"STARTED-BY\": \"Comenzado por\",\n            \"ENDED\": \"Finalizado\",\n            \"NAME\": \"Nombre de la instancia de caso\",\n            \"NAME-PLACEHOLDER\" : \"Introduzca un nombre opcional para el caso a comenzar\"\n        },\n        \"SECTION\": {\n            \"ACTIVE-TASKS\": \"Tareas activas\",\n            \"COMPLETED-TASKS\": \"Tareas completadas\",\n            \"ACTIVE-STAGES\": \"Etapas disponibles/activas\",\n            \"ENDED-STAGES\": \"Etapas finalizadas\",\n            \"AVAILABLE-MILESTONES\": \"Hitos disponibles\",\n            \"REACHED-MILESTONES\": \"Hitos alcanzados\",\n            \"AVAILABLE-USER-EVENT-LISTENERS\": \"Eventos de usuario disponibles\",\n            \"COMPLETED-USER-EVENT-LISTENERS\": \"Eventos de usuario completados\",\n            \"CONTENT\" : \"Contenido\",\n            \"ENABLED-PLAN-ITEM-INSTANCES\": \"Instancia de plan item habilitado\"\n        },\n        \"POPUP\": {\n            \"CANCEL-TITLE\": \"Cancelar el caso?\",\n            \"CANCEL-DESCRIPTION\": \"Esta seguro que desea cancelar el caso {{name}}?\",\n            \"DELETE-TITLE\": \"Borrar el caso?\",\n            \"DELETE-DESCRIPTION\": \"Esta seguro que desea borrar el caso {{name}}? Todas las tareas y contenido relacionado al caso se borrarán de manera permanente.\"\n        }\n    },\n    \"INVOLVE-PEOPLE\": {\n        \"NO-MATCHING-RESULTS\": \"Usa el campo buscar usuario de arriba para encontrar usuarios\",\n        \"SEARCH-PLACEHOLDER\": \"Buscar usuario\",\n        \"BACK-TO-SEARCH\": \"Regresar a la busqueda\",\n        \"ACTION-SELECT\": \"Seleccionar\"\n    },\n    \"INTEGRATION\": {\n        \"ALERT\": {\n        }\n    },\n    \"CONTENT\": {\n        \"SIMPLE-TYPE\": {\n            \"WORD\": \"Documento\",\n            \"EXCEL\": \"Hoja de calculo\",\n            \"PDF\": \"PDF\",\n            \"IMAGE\": \"Imagen\",\n            \"FOLDER\": \"Carpeta\",\n            \"CONTENT\": \"Contenido\"\n        },\n        \"MESSAGE\": {\n            \"NO-PREVIEW-AVAILABLE\": \"No hay vista previa disponible\",\n            \"PREVIEW-PENDING\": \"Creando vista previa...\",\n            \"CONTENT-PENDING\": \"Obteniendo contenido...\",\n            \"NOT-FOUND\": \"El contenido no puede ser encontrado\",\n            \"DELETE-CONFIRMATION\": \"Estas seguro que deseas borrar {{name}}?\",\n            \"DROP\": \"Arrastrar o \",\n            \"SELECT\": \"Selecciona un archivo\",\n            \"DRAGOVER\": \"Arrastra un archivo para subirlo\",\n            \"EXTERNAL-ONLY\": \"Selecciona la fuente del contenido\"\n        },\n        \"TITLE\": {\n            \"DELETE\": \"Borrar contenido\",\n            \"NOT-FOUND\": \"Archivo no encontrado\"\n        },\n        \"ACTION\":  {\n        }\n    },\n    \"FORM\" : {\n        \"ACTION\": {\n            \"SAVE\": \"Guardar\"\n        },\n        \"DEFAULT-OUTCOME\": {\n            \"COMPLETE\": \"Completar\",\n            \"START-PROCESS\": \"Iniciar proceso\"\n        },\n        \"MESSAGE\" : {\n            \"SELECT-PERSON\": \"No hay persona seleccionada...\",\n            \"SELECT-GROUP\": \"No hay grupo seleccionado...\",\n            \"EMPTY\": \"(vacio)\"\n        }\n    },\n    \"APP-DEFINITION\" : {\n        \"MESSAGE\" : {\n            \"NOT-FOUND\": \"No se encontro una App con el identificador proporcionado\",\n            \"MISSING\": \"Activiti is running in integration mode, but the required app definition is missing\"\n        }\n    }\n}\n"
  },
  {
    "path": "flowable-ui-web/task/workflow/i18n/fr.json",
    "content": "{\n    \"COMMON\" : {\n        \"SELECT-FOLDER\": \"Choisir un répertoire...\"\n    },\n    \"GENERAL\": {\n        \"MAIN-TITLE\": \"Flowable - Mes Tâches\",\n        \"ERROR\": {\n            \"GENERIC\": \"Désolé, une erreur s'est produite...\",\n            \"UNKNOWN\": \"Désolé, une erreur s'est produite lors de l'exécution de l'opération.\",\n            \"BAD_REQUEST\": \"Une erreur s'est produite lors de l'exécution de l'opération demandée.\",\n            \"NOT_FOUND\": \"La resource demandée n'existe pas\",\n            \"UNAUTHORIZED\": \"Veuillez d'abord vous connecter pour effectuer cette opération.\",\n            \"FORBIDDEN\": \"Vous n'êtes pas autorisé à effectuer cette opération.\",\n            \"INTERNAL_SERVER_ERROR\": \"Désolé, une erreur inattendue s'est produite lors de l'exécution de l'opération.\"\n        },\n        \"NAVIGATION\": {\n            \"TASKS\": \"Tâches\",\n            \"PROCESSES\": \"Processus\",\n            \"CASES\": \"Cas\",\n            \"DESIGN\": \"Conception\",\n            \"CREATE\": \"+ Création\",\n            \"LOGIN\": \"Se connecter\"\n        },\n        \"TITLE\": {\n            \"ADD-COMMENT\": \"Ajouter un commentaire\",\n            \"INVOLVE-PEOPLE\": \"Sélectionner une personne\",\n            \"RECENT-PEOPLE\": \"Personnes récentes\",\n            \"MATCHING-PEOPLE\": \"Personnes correspondantes\",\n            \"SELECT-GROUP\": \"Sélectionner un groupe\",\n            \"MATCHING-GROUPS\": \"Groupes correspondants\",\n            \"FILTER\": \"Filtres\",\n            \"SELECT-DATE\": \"Sélectionner a date\"\n        },\n        \"ACTION\": {\n            \"LOGOUT\": \"Se déconnecter\",\n            \"ADD-COMMENT\": \"Ajouter un commentaire\",\n            \"SAVE\": \"Enregistrer\",\n            \"CANCEL\": \"Annuler\",\n            \"CLOSE\": \"Fermer\",\n            \"CONFIRM\": \"Confirmer\",\n            \"SHOW-MORE\": \"Voir plus...\"\n        },\n        \"MESSAGE\": {\n            \"SELECT-PEOPLE-HELP\": \"Utiliser &uparrow; et &downarrow; pour sélectionner et appuyez sur Entrée pour confirmer\",\n            \"SELECT-GROUP-HELP\": \"Utiliser &uparrow; et &downarrow; pour sélectionner et appuyez sur Entrée pour confirmer\",\n            \"SELECT-GROUP-SEARCH-PLACEHOLDER\": \"Rechercher un groupe\",\n            \"SELECT-GROUP-NO-MATCHING-RESULTS\": \"Utilisez le champ de recherche ci-dessus pour trouver des groupes.\",\n            \"UPLOAD-CONTENT\": \"Sélectionner ou déposer un fichier\",\n            \"UPLOAD-CONTENT-NO-DROP\": \"Sélectionner un fichier à télécharger\",\n            \"DROPZONE\": \"Déposer un fichier à télécharger\",\n            \"YES\": \"Oui\",\n            \"NO\": \"Non\"\n        },\n        \"TIME\": {\n            \"HOURS\": \"heures\",\n            \"MINUTES\": \"minutes\",\n            \"SECONDS\": \"secondes\"\n        },\n        \"ABOUT\": {\n            \"TYPE\": \"Type\",\n            \"LICENSED-TO\": \"Licensed To\",\n            \"EXPIRES\": \"Expires\",\n            \"COPYRIGHT\": \"© 2005-2015 Alfresco Software Inc. All rights reserved.\",\n            \"LEGAL\": \"Legal and License\"\n        }\n    },\n    \"LOGIN\": {\n        \"TITLE\": \"Se connecter\",\n        \"USERNAME\": \"Nom d'utilisateur\",\n        \"USERNAME-PLACEHOLDER\": \"Veuillez saisir votre nom d'utilisateur\",\n        \"PASSWORD\": \"Mot de passe\",\n        \"PASSWORD-PLACEHOLDER\": \"Veuillez saisir votre mot de passe\",\n        \"ACTION\": {\n            \"CONFIRM\": \"Connexion\"\n        }\n    },\n    \"TASK\": {\n        \"SECTION\": {\n            \"PEOPLE\": \"Personnes\",\n            \"CONTENT\": \"Contenu\",\n            \"COMMENTS\": \"Commentaires\",\n            \"NOTES\": \"Notes\"\n        },\n        \"FILTER\": {\n            \"CREATED-DESC\": \"Plus récent\",\n            \"CREATED-ASC\": \"Plus ancien\",\n            \"DUE-DESC\": \"Dû en dernier\",\n            \"DUE-ASC\": \"Dû en premier\",\n            \"TEXT\": \"Filtres\",\n            \"TEXT-PLACEHOLDER\": \"Recherche par nom d'utilisateur\",\n            \"TEXT-SUMMARY\": \"Filtré par: {{text}}\",\n            \"PROCESS-DEFINITION\": \"Définition du Processus\",\n            \"PROCESS-DEFINITION-PLACEHOLDER\": \"Sélectionner une définition de processus...\",\n            \"STATE\": \"État\",\n            \"STATE-OPEN\": \"ouvert\",\n            \"STATE-COMPLETED\": \"terminé\",\n            \"ASSIGNMENT\": \"Assignment\",\n            \"ASSIGNMENT-INVOLVED\": \"Tâches auxquelles je suis impliqué\",\n            \"ASSIGNMENT-ASSIGNEE\": \"Tâches où je suis la personne assignée\",\n            \"ASSIGNMENT-CANDIDATE\": \"Tâches où je suis l'un des candidats\",\n            \"ASSIGNMENT-GROUP\": \"Tâches assignées au groupe \\\"{{name}}\\\"\",\n            \"RESET\": \"Réinitialiser les filtres\"\n        },\n        \"ALERT\": {\n            \"COMMENT-ADDED\": \"Des commentaires ont été ajoutés par \\\"{{name}}\\\"\",\n            \"PERSON-INVOLVED\": \"{{firstName}} {{lastName}} est maintenant impliqué dans \\\"{{taskName}}\\\"\",\n            \"PERSON-NO-LONGER-INVOLVED\": \"{{firstName}} {{lastName}} n'est plus impliqué dans \\\"{{taskName}}\\\"\",\n            \"CREATED\": \"La tâche \\\"{{name}}\\\" a été créée\",\n            \"COMPLETED\": \"Tâche terminée\",\n            \"SAVED\": \"Le fomulaire de la tâche a été sauvé\",\n            \"ASSIGNED\": \"La tâche \\\"{{taskName}}\\\" est maintenant assignée à  {{firstName}} {{lastName}}\",\n            \"RELATED-CONTENT-ADDED\": \"\\\"{{name}}\\\" a été ajoutée à la tâche\",\n            \"RELATED-CONTENT-ADDED-LOADING\": \"\\\"{{name}}\\\" a été ajoutée à la tâche. Le contenu sera disponible une fois récupéré de la source externe.\"\n        },\n        \"ACTION\": {\n            \"COMPLETE-TASK-WITH-FORM\": \"Fomulaire\",\n            \"COMPLETE\": \"Terminer\",\n            \"CLAIM\": \"Revendiquer\",\n            \"ASSIGN\": \"Assigner\",\n            \"REASSIGN\": \"Réassigner\",\n            \"CREATE\": \"+ Créer La tâche\",\n            \"CREATE-SUB-TASK\": \"Créer une sous-tâche\",\n            \"CREATE-CONFIRM\": \"Créer\",\n            \"INVOLVE\": \"+ Impliquer des personnes\",\n            \"ADD-COMMENT\": \"+ Ajouter un commentaire\",\n            \"ADD-COMMENT-CONFIRM\": \"Ajouter un commentaire\",\n            \"ADD-CONTENT\": \"+ Ajouter un contenu\",\n            \"CLEAR-DUEDATE\": \"Vider la date d'échéance\",\n            \"DUE-TODAY\": \"Dû aujourd'hui\",\n            \"CLEAR-DATE\": \"Vider la date\",\n            \"DATE-TODAY\": \"Date d'aujourd'hui\",\n            \"AUDIT-LOG\": \"Audit Log\"\n        },\n        \"TITLE\": {\n            \"ASSIGN\": \"Sélectionner une personne assignée\",\n            \"ASSIGNEE\": \"Personne assignée\",\n            \"CONTENT\": \"Contenu connexe\",\n            \"SUBTASK\": \"Sous-tâches\",\n            \"CREATE-NEW\": \"Nouvelle tâche\",\n            \"FORM\": \"Formulaire\",\n            \"DETAILS\": \"Détails\",\n            \"ADD-RELATED-CONTENT\": \"Ajouter un contenu connexe\",\n            \"SELECT-DUEDATE\": \"Sélectionner une date d'échéance\",\n            \"SELECT-DATE\": \"Sélectionner une date\",\n            \"NO-CONTENT-ITEMS\": \"Aucun contenu\",\n            \"NO-PEOPLE-INVOLVED\": \"Aucune personne impliqué\",\n            \"NO-COMMENTS\": \"Aucun commentaires\",\n            \"COMMENT-COUNT\": \"commentaire\",\n            \"COMMENTS-COUNT\": \"commentaires\",\n            \"NO-SUBTASKS\": \"Aucune sous tâche\",\n            \"SUBTASK-COUNT\": \"sous-tâche \",\n            \"SUBTASKS-COUNT\": \"sous-tâches\",\n            \"SHOW-DETAILS\": \"Afficher les détails\",\n            \"SHOW-FORM\": \"Afficher le formulaire\"\n        },\n        \"FIELD\": {\n            \"NAME\": \"Nom\",\n            \"DESCRIPTION\": \"Description\",\n            \"ASSIGNEE\": \"Personne assignée\",\n\n            \"DUE\": \"Dû\",\n            \"PROCESS-INSTANCE\": \"Partie du processus\",\n            \"CASE-INSTANCE\": \"Partie du cas\",\n            \"PARENT-TASK\": \"Partie de la tâche\",\n            \"ENDED\": \"Terminé\",\n            \"DURATION\": \"Durée\"\n        },\n        \"MESSAGE\": {\n            \"NO-NAME\": \"Tâche sans nom\",\n            \"NO-ASSIGNEE\": \"Assigné à personne\",\n            \"NO-DUEDATE\": \"Aucune date d'échéance\",\n            \"DUE-ON\": \"Dû\",\n            \"CREATED-ON\": \"Créée le\",\n            \"ENDED-ON\": \"Terminée le\",\n            \"REACHED-ON\": \"Atteint\",\n            \"COMPLETED-BY\": \"Terminée par\",\n            \"NO-DESCRIPTION\": \"Cette tâche n'a pas de description\",\n            \"NO-RELATED-CONTENT\": \"Cette tâche n'a pas encore de contenu connexe...\",\n            \"NO-PEOPLE-INVOLVED\": \"Cette tâche n'a pas encore de personnes impliquées...\",\n            \"NO-COMMENTS\": \"Cette tâche n'a pas encore de commentaires...\",\n            \"INVOLVE-PEOPLE-PLACEHOLDER\": \"+ Ajouter des personnes\",\n            \"CONTENT-UPLOADED-BY\": \"Ajouté par \",\n            \"ASSIGNEE\": \"Assigné à\",\n            \"NEW-COMMENT-PLACEHOLDER\": \"Entrer un commenataire à ajouter à cette tâche\",\n            \"COMMENT-HEADER\": \"Ajouté par {{createdBy | username}}, {{created | dateformat:\\\"fromNow\\\"}}\",\n            \"NO-FILTER\": \"Montrer vos tâches, pas de filtre appliqué\",\n            \"FILTERED\": \"Montrer vos tâches, filtré\",\n            \"NO-TASKS\": \"Aucune tâche correspondante n'a été trouvée ...\",\n            \"DURATION\": \"A pris {{duration}}\",\n            \"CLAIM-TASK-FIRST\": \"Pour voir et remplir le formulaire de cette tâche, vous devez d'abord réclamer cette tâche. Vous pouvez le faire en appuyant sur le bouton bleu en haut à droite de la page.\",\n            \"NO-TASKS-HELP\": \"Bien, il semble qu'il n'y ait aucune tâche pour vous! Pour commencer quelque chose, vous pouvez:\",\n            \"NO-SUCH-TASK-HELP\": \"La tâche que vous recherchez ne peut être trouvée! Si vous le souhaitez, vous pouvez plutôt:\",\n            \"NO-SUCH-TASK-RETURN-TO-LIST\": \"Retournez à votre liste de tâches\",\n            \"NO-TASKS-CREATE-TASK\": \"Créez une tâche pour vous-même ou attribuez-la à quelqu'un d'autre\",\n            \"NO-TASKS-CREATE-PROCESS\": \"Démarrez un nouveau processus et suivez son avancement\"\n\n        },\n        \"HELP\" : {\n            \"DESCRIPTION\": \"Cette tâche n'a pas encore de détails. Vous pouvez changer cela en choisissant l'une de ces actions:\",\n            \"COMPLETED-DESCRIPTION\": \"Cette tâche terminée n'a pas de détails.\",\n            \"DESCRIPTION-WITH-CLAIM\": \"Cette tâche n'a pas encore de détails. Vous pouvez modifier cela en choisissant l'une des actions suivantes. De plus, pour compléter cette tâche, vous devez d'abord la revendiquer en appuyant sur le bouton bleu en haut à droite de la page.\",\n            \"ADD-PEOPLE\": \"Invitez quelqu'un d'autre et commencez à collaborer\",\n            \"ADD-COMMENT\": \"Eclairer les autres en ajoutant un commentaire\",\n            \"ADD-CONTENT\": \"Ajouter un document et partager les connaissances\",\n            \"ADD-SUBTASK\": \"Créer une sous-tâche\"\n        }\n    },\n    \"PROCESS\": {\n        \"ALERT\": {\n            \"COMMENT-ADDED\": \"Le commentaire a été ajouté\",\n            \"STARTED\": \"Un nouveau processus  \\\"{{processDefinitionName}}\\\" a été démarré\",\n            \"START-PROCESS-CONTENT-ADD-FAILED\": \"Impossible d'ajouter {{noOfFiles}} fichier(s) au processus\"\n        },\n        \"TITLE\": {\n            \"DIAGRAM\": \"Diagramme de processus\",\n            \"EXECUTION\": \"Exécution\",\n            \"EXECUTIONS\": \"Exécutions\",\n            \"EXPRESSION\": \"Expression\",\n            \"SCRIPT\": \"Script\",\n            \"RESULT\": \"Resultat\",\n            \"VARIABLES\": \"Variables\",\n            \"LOG\": \"Log\"\n        },\n        \"FILTER\": {\n            \"CREATED-DESC\": \"Le plus récent en premier\",\n            \"CREATED-ASC\": \"Le plus ancient en premier\",\n            \"ENDED-DESC\": \"Terminé récemment\",\n            \"ENDED-ASC\": \"Terminé le moins récemment\",\n            \"STATE-SUMMARY\": \"Afficher {{state.title | translate}} processus\",\n            \"STATE\": \"Etat de processus\",\n            \"STATE-RUNNING\": \"en cours\",\n            \"STATE-COMPLETED\": \"terminé\",\n            \"STATE-ALL\": \"tous\"\n        },\n        \"MESSAGE\": {\n            \"NO-DESCRIPTION\": \"Cette instance de processus n'a pas de description\",\n            \"NO-FILTER\": \"Afficher toutes les instances de processus, non filtré\",\n            \"NO-INSTANCES\": \"Aucune instance de processus correspondante n'a été trouvée ...\",\n            \"NO-INSTANCES-HELP\": \"Il n'y a pas de processus en cours d'exécution. Si vos processus sont terminés, vous pouvez les trouver en utilisant le filtre dans la liste des processus. Pour aller de l'avant avec quelque chose de nouveau, vous pouvez:\",\n            \"NO-INSTANCES-HELP-START\": \"Démarrer un nouveau processus et suivre son avancement\",\n            \"NO-TASKS\": \"Aucune tâche n'est active actuellement...\",\n            \"NO-COMPLETED-TASKS\": \"Aucune tâche n'a été terminée...\",\n            \"NO-BUSINESS-KEY\": \"Aucune clé métier definie\",\n            \"NO-ACTIVE-MILESTONES\": \"No active milestones\",\n            \"CATEGORY\": \"Categorie: {{processDefinitionCategory}}\",\n            \"NEW-COMMENT-PLACEHOLDER\": \"Entrez un commentaire à ajouter à ce processus\",\n            \"COMMENT-HEADER\": \"Ajouter par {{createdBy | username}}, {{created | dateformat:\\\"fromNow\\\"}}\",\n            \"SELECT-DEFINITION\": \"Sélectionner dans la liste ci-dessous un processus à démarrer\",\n            \"NO-PROCESS-DEFINITIONS\": \"Vous ne pouvez pas démarrer un processus car il n'y a pas de définitions de processus disponibles\",\n            \"START-PROCESS\": \"Commencer le processus\",\n            \"STARTED-BY\": \"Démarré par\",\n            \"NO-PROCESS-DEFINITION-SELECTED-HELP\": \"Sélectionnez une définition de processus\"\n        },\n        \"ACTION\" : {\n            \"CREATE\": \"+ Démarrer un processus\",\n            \"BACK-TO-LIST\": \"Retour aux instances de processus\",\n            \"SHOW-DIAGRAM\": \"Afficher le diagramme\",\n            \"CANCEL\": \"Annuler le processus\",\n            \"EXECUTE\": \"Exécuter\",\n            \"DELETE\": \"Supprimer le processus\",\n            \"ADD-COMMENT\": \"+ Ajouter un commentaire\",\n            \"ADD-COMMENT-CONFIRM\": \"Ajouter un commentaire\",\n            \"AUDIT-LOG\": \"Audit Log\"\n        },\n        \"FIELD\": {\n            \"BUSINESS-KEY\": \"Clé métier\",\n            \"CATEGORY\": \"Categorie\",\n            \"PROCESS-DEFINITION\": \"Définition de Processus\",\n            \"STARTED\": \"Démarré\",\n            \"STARTED-BY\": \"Démarré par\",\n            \"ENDED\": \"Terminé\",\n            \"NAME\": \"Nom de l'instance de processus\",\n            \"NAME-PLACEHOLDER\" : \"Entrez un nom facultatif pour la procédure en cours de démarrage\"\n        },\n        \"SECTION\": {\n            \"ACTIVE-TASKS\": \"Tâches actives\",\n            \"START-FORM\": \"Formulaire de départ\",\n            \"COMPLETED-TASKS\": \"Tâches terminées \",\n            \"COMMENTS\": \"Commentaires\",\n            \"CONTENT\" : \"Contenus\"\n        },\n        \"POPUP\": {\n            \"CANCEL-TITLE\": \"Annuler le processus?\",\n            \"CANCEL-DESCRIPTION\": \"Êtes-vous sûr de vouloir annuler le processus {{name}}?\",\n            \"DELETE-TITLE\": \"Supprimer le processus?\",\n            \"DELETE-DESCRIPTION\": \"Êtes-vous sûr de vouloir supprimer le processus {{name}}? Toutes les tâches, le contenu et les commentaires liés à ce processus seront supprimés définitivement.\"\n        }\n    },\n    \"CASE\": {\n        \"ALERT\": {\n            \"STARTED\": \"Un nouveau case  \\\"{{caseDefinitionName}}\\\"  a été démarré\",\n            \"START-CASE-CONTENT-ADD-FAILED\": \"Impossible d'ajouter {{noOfFiles}} fichier(s) au cas\"\n        },\n        \"TITLE\": {\n            \"DIAGRAM\": \"Diagramme de case\"\n        },\n        \"FILTER\": {\n            \"CREATED-DESC\": \"Le plus récent en premier\",\n            \"CREATED-ASC\": \"Le plus ancient en premier\",\n            \"ENDED-DESC\": \"Terminé récemment\",\n            \"ENDED-ASC\": \"Terminé le moins récemment\",\n            \"STATE-SUMMARY\": \"Afficher {{state.title | translate}} cas\",\n            \"STATE\": \"Etat du cas\",\n            \"STATE-RUNNING\": \"en cours\",\n            \"STATE-COMPLETED\": \"terminé\",\n            \"STATE-ALL\": \"tous\"\n        },\n        \"MESSAGE\": {\n            \"NO-DESCRIPTION\": \"Cette instance de cas n'a pas de description\",\n            \"NO-FILTER\": \"Montrer tous les cas, non filtré\",\n            \"NO-INSTANCES\": \"Aucune instance de cas correspondante n'a été trouvée...\",\n            \"NO-INSTANCES-HELP\": \"Il n'y a pas de cas en cours d'exécution. Si vos cas sont terminés, vous pouvez les trouver en utilisant le filtre dans la liste des cas. Pour aller de l'avant avec quelque chose de nouveau, vous pouvez:\",\n            \"NO-INSTANCES-HELP-START\": \"Démarrer un nouveau cas et suivre son avancement\",\n            \"NO-TASKS\": \"Aucune tâche n'est active actuellement...\",\n            \"NO-COMPLETED-TASKS\": \"Aucune tâche n'a été terminée...\",\n            \"NO-BUSINESS-KEY\": \"Aucune clé métier definie\",\n            \"CATEGORY\": \"Catégorie: {{processDefinitionCategory}}\",\n            \"SELECT-DEFINITION\": \"Sélectionner dans la liste ci-dessous un cas à démarrer\",\n            \"NO-CASE-DEFINITIONS\": \"Vous ne pouvez pas démarrer un cas car il n'y a pas de définitions de cas disponibles\",\n            \"START-CASE\": \"Commencer le cas\",\n            \"STARTED-BY\": \"Démarré par\",\n            \"STAGE-STARTED\": \"Commencé\",\n            \"STAGE-ENDED\": \"Terminé\",\n            \"STAGE-NOT-STARTED\": \"Pas encore commencé\",\n            \"STATE\": \"Etat\",\n            \"STAGE-NO-NAME\": \"Étape sans nom\",\n            \"MILESTONE-REACHED-ON\": \"Atteint\",\n            \"MILESTONE-TERMINATED-ON\": \"Terminé\",\n            \"NO-CASE-DEFINITION-SELECTED-HELP\": \"Sélectionnez une définition de processus\",\n            \"NO-ACTIVE-STAGES\": \"Pas d'étapes actives\",\n            \"NO-ENDED-STAGES\": \"Étapes non terminées\",\n            \"NO-AVAILABLE-MILESTONES\": \"Pas de Jalons disponible\",\n            \"NO-REACHED-MILESTONES\": \"Pas de Jalons atteints\",\n            \"NO-AVAILABLE-USER-EVENT-LISTENERS\":\"Aucun événement utilisateur disponible\",\n            \"NO-COMPLETED-USER-EVENT-LISTENERS\":\"Aucun événement utilisateur terminé\",\n            \"USER-EVENT-LISTENER-NO-NAME\": \"Evénement utilisateur sans nom\",\n            \"USER-EVENT-LISTENER-COMPLETED\": \"Terminé\",\n            \"ENABLED-PLAN-ITEM_INSTANCE-NO-NAME\": \"Sans nom\",\n            \"START-PLAN-ITEM-INSTANCE\": \"Démarrer\"\n        },\n        \"ACTION\" : {\n            \"CREATE\": \"+ Démarrer un cas\",\n            \"BACK-TO-LIST\": \"Retour aux instances de cas\",\n            \"SHOW-DIAGRAM\": \"Afficher le diagramme\",\n            \"CANCEL\": \"Annuler le cas\",\n            \"DELETE\": \"Supprimer le cas\",\n            \"TRIGGER-USER-EVENT-LISTENER\": \"Déclencheur\",\n            \"AUDIT-LOG\": \"Audit Log\"\n        },\n        \"FIELD\": {\n            \"BUSINESS-KEY\": \"Clé métier\",\n            \"CATEGORY\": \"Categorie\",\n            \"CASE-DEFINITION\": \"Définition de Cas\",\n            \"STARTED\": \"Démarré\",\n            \"STARTED-BY\": \"Démarré par\",\n            \"ENDED\": \"Terminé\",\n            \"NAME\": \"Nom de l'instance de cas\",\n            \"NAME-PLACEHOLDER\" : \"Entrez un nom facultatif pour le cas en cours de démarrage\"\n        },\n        \"SECTION\": {\n            \"ACTIVE-TASKS\": \"Tâches actives\",\n            \"COMPLETED-TASKS\": \"Tâches terminées\",\n            \"ACTIVE-STAGES\": \"Étapes disponible/actives\",\n            \"ENDED-STAGES\": \"Étapes terminées\",\n            \"AVAILABLE-MILESTONES\": \"Jalons disponible\",\n            \"REACHED-MILESTONES\": \"Atteint des Jalons\",\n            \"AVAILABLE-USER-EVENT-LISTENERS\": \"Evénement utilisateur disponible\",\n            \"COMPLETED-USER-EVENT-LISTENERS\": \"Événement utilisateur terminé\",\n            \"CONTENT\" : \"Contenus\",\n            \"ENABLED-PLAN-ITEM-INSTANCES\": \"Plan item instances activées\"\n        },\n        \"POPUP\": {\n            \"CANCEL-TITLE\": \"Annuler le cas?\",\n            \"CANCEL-DESCRIPTION\": \"Êtes-vous sûr de vouloir annuler le cas {{name}}?\",\n            \"DELETE-TITLE\": \"Supprimer le cas?\",\n            \"DELETE-DESCRIPTION\": \"Êtes-vous sûr de vouloir supprimer le cas {{name}}? Toutes les tâches, le contenu et les commentaires liés à ce cas seront supprimés définitivement.\"\n        }\n    },\n    \"INVOLVE-PEOPLE\": {\n        \"NO-MATCHING-RESULTS\": \"Utilisez le champ de recherche ci-dessus pour trouver des utilisateurs\",\n        \"SEARCH-PLACEHOLDER\": \"Rerchercher les utilisateurs\",\n        \"BACK-TO-SEARCH\": \"Retour vers la recherche\",\n        \"ACTION-SELECT\": \"Sélectionner\"\n    },\n    \"INTEGRATION\": {\n        \"ALERT\": {\n        }\n    },\n    \"CONTENT\": {\n        \"SIMPLE-TYPE\": {\n            \"WORD\": \"Document\",\n            \"EXCEL\": \"Feuille de calcul\",\n            \"PDF\": \"Document PDF \",\n            \"IMAGE\": \"Image\",\n            \"FOLDER\": \"Répertoire\",\n            \"CONTENT\": \"Contenu\"\n        },\n        \"MESSAGE\": {\n            \"NO-PREVIEW-AVAILABLE\": \"Aucun aperçu disponible\",\n            \"PREVIEW-PENDING\": \"Creation de l'aperçu...\",\n            \"CONTENT-PENDING\": \"Téléchargement du contenu...\",\n            \"NOT-FOUND\": \"TLe contenu ne peut être trouvé\",\n            \"DELETE-CONFIRMATION\": \"Etes-vous sûr de vouloir supprimer {{name}}?\",\n            \"DROP\": \"Déposer ou \",\n            \"SELECT\": \"Sélectionner un fichier\",\n            \"DRAGOVER\": \"Déposer un fichier à télécharger \",\n            \"EXTERNAL-ONLY\": \"Sélectionner la source du contenu\"\n        },\n        \"TITLE\": {\n            \"DELETE\": \"Supprimer le contenu\",\n            \"NOT-FOUND\": \"Fichier non trouvé\"\n        },\n        \"ACTION\":  {\n        }\n    },\n    \"FORM\" : {\n        \"ACTION\": {\n            \"SAVE\": \"Enregistrer\"\n        },\n        \"DEFAULT-OUTCOME\": {\n            \"COMPLETE\": \"Terminer\",\n            \"START-PROCESS\": \"Démarrer le processus\",\n            \"START-CASE\": \"Démarrer le cas\"\n        },\n        \"MESSAGE\" : {\n            \"SELECT-PERSON\": \"Aucune personne choisie...\",\n            \"SELECT-GROUP\": \"Aucun groupe choisi...\",\n            \"EMPTY\": \"(vide)\"\n        }\n    },\n    \"APP-DEFINITION\" : {\n        \"MESSAGE\" : {\n            \"NOT-FOUND\": \"Aucune définition d'app definition n'a été trouvé avec cet identifiant\",\n            \"MISSING\": \"Flowable s'exécute en mode d'intégration, mais la définition de l'application requise est manquante\"\n        }\n    }\n}\n"
  },
  {
    "path": "flowable-ui-web/task/workflow/i18n/pt-BR.json",
    "content": "{\n  \"COMMON\":{\n    \"SELECT-FOLDER\":\"Selecione uma pasta...\"\n  },\n  \"GENERAL\":{\n    \"MAIN-TITLE\":\"Flowable - Minhas Tarefas\",\n    \"ERROR\":{\n      \"GENERIC\":\"Desculpe, ocorreu um erro...\",\n      \"UNKNOWN\":\"Desculpe, um erro ocorreu durante a execução da operação solicitada.\",\n      \"BAD_REQUEST\":\"Um erro ocorreu durante a execução da operação solicitada\",\n      \"NOT_FOUND\":\"O recurso que você está tentando acessar não existe\",\n      \"UNAUTHORIZED\":\"Você deve fazer login para executar a operação solicitada.\",\n      \"FORBIDDEN\":\"Você não está autorizado a executar a operação solicitada\",\n      \"INTERNAL_SERVER_ERROR\":\"Desculpe, um erro inesperado ocorreu durante a execução da operação solicitada.\"\n    },\n    \"NAVIGATION\":{\n      \"TASKS\":\"Tarefas\",\n      \"PROCESSES\":\"Processos\",\n      \"DESIGN\":\"Desenho\",\n      \"CREATE\":\"+ Criar\",\n      \"LOGIN\":\"Entrar\"\n    },\n    \"TITLE\":{\n      \"ADD-COMMENT\":\"Criar comentário\",\n      \"INVOLVE-PEOPLE\":\"Selecione uma pessoa\",\n      \"RECENT-PEOPLE\":\"Pessoas recentes\",\n      \"MATCHING-PEOPLE\":\"Pessoas correspondentes\",\n      \"SELECT-GROUP\":\"Selecionar grupo\",\n      \"MATCHING-GROUPS\":\"Grupos correspondentes\",\n      \"FILTER\":\"Filtro\",\n      \"SELECT-DATE\":\"Selecione uma data\"\n    },\n    \"ACTION\":{\n      \"LOGOUT\":\"Sair\",\n      \"ADD-COMMENT\":\"Adicionar comentário\",\n      \"SAVE\":\"Salvar\",\n      \"CANCEL\":\"Cancelar\",\n      \"CLOSE\":\"Fechar\",\n      \"CONFIRM\":\"Confirmar\",\n      \"SHOW-MORE\":\"Mostrar mais...\"\n    },\n    \"MESSAGE\":{\n      \"SELECT-PEOPLE-HELP\":\"Use &uparrow; e &downarrow; para selecionar e pressione Enter para confirmar\",\n      \"SELECT-GROUP-HELP\":\"Use &uparrow; e &downarrow; para selecionar e pressione Enter para confirmar\",\n      \"SELECT-GROUP-SEARCH-PLACEHOLDER\":\"Buscar grupos\",\n      \"SELECT-GROUP-NO-MATCHING-RESULTS\":\"Use a caixa de pesquisa acima para encontrar grupos.\",\n      \"UPLOAD-CONTENT\":\"Selecione ou arraste e solte o arquivo\",\n      \"UPLOAD-CONTENT-NO-DROP\":\"Selecione o arquivo para carregar\",\n      \"DROPZONE\":\"Arraste e Solte o arquivo para enviá-lo\",\n      \"YES\":\"Sim\",\n      \"NO\":\"Não\"\n    },\n    \"TIME\":{\n      \"HOURS\":\"horas\",\n      \"MINUTES\":\"minutos\",\n      \"SECONDS\":\"segundos\"\n    },\n    \"ABOUT\":{\n      \"TYPE\":\"Tipo\",\n      \"LICENSED-TO\":\"Licenciado para\",\n      \"EXPIRES\":\"Expira em\",\n      \"COPYRIGHT\":\"&copyleft; Flowable. Todos os direitos reservados.\",\n      \"LEGAL\":\"Jurídica e licença\"\n    }\n  },\n  \"LOGIN\":{\n    \"TITLE\":\"Entrar\",\n    \"USERNAME\":\"Nome de Usuário\",\n    \"USERNAME-PLACEHOLDER\":\"Digite seu nome de usuário\",\n    \"PASSWORD\":\"Senha\",\n    \"PASSWORD-PLACEHOLDER\":\"Digite sua senha\",\n    \"ACTION\":{\n      \"CONFIRM\":\"Entrar\"\n    }\n  },\n  \"TASK\":{\n    \"SECTION\":{\n      \"PEOPLE\":\"Pessoas\",\n      \"CONTENT\":\"Conteúdo\",\n      \"COMMENTS\":\"Comentários\",\n      \"NOTES\":\"Anotações\"\n    },\n    \"FILTER\":{\n      \"CREATED-DESC\":\"Mais Recentes Primeiro\",\n      \"CREATED-ASC\":\"Mais antigos primeiro\",\n      \"DUE-DESC\":\"Vencimento até\",\n      \"DUE-ASC\":\"Que vence primeiro\",\n      \"TEXT\":\"Filtro\",\n      \"TEXT-PLACEHOLDER\":\"Pesquisar por nome de tarefa\",\n      \"TEXT-SUMMARY\":\"Filtrado por: {{text}}\",\n      \"PROCESS-DEFINITION\":\"Definição de processo\",\n      \"PROCESS-DEFINITION-PLACEHOLDER\":\"Seleccione a definição de processo...\",\n      \"STATE\":\"Status\",\n      \"STATE-OPEN\":\"Aberto\",\n      \"STATE-COMPLETED\":\"Concluído\",\n      \"ASSIGNMENT\":\"Atribuído\",\n      \"ASSIGNMENT-INVOLVED\":\"Tarefas em que estou envolvido\",\n      \"ASSIGNMENT-ASSIGNEE\":\"Tarefas em que estou atribuído\",\n      \"ASSIGNMENT-CANDIDATE\":\"Tarefas em que sou um dos candidatos\",\n      \"ASSIGNMENT-GROUP\":\"Tarefas atribuídas para o grupo \\\"{{name}}\\\"\",\n      \"RESET\":\"Redefinir filtros\"\n    },\n    \"ALERT\":{\n      \"COMMENT-ADDED\":\"Um comentário foi adicionado ao \\\"{{name}}\\\"\",\n      \"PERSON-INVOLVED\":\"{{firstName}} {{lastName}} agora está envolvido em \\\"{{taskName}}\\\"\",\n      \"PERSON-NO-LONGER-INVOLVED\":\"{{firstName}} {{lastName}} não está mais envolvido em \\\"{{taskName}}\\\"\",\n      \"CREATED\":\"A tarefa \\\"{{name}}\\\" foi criada\",\n      \"COMPLETED\":\"Tarefa concluída\",\n      \"SAVED\":\"Formulário de tarefa foi salvo\",\n      \"ASSIGNED\":\"Tarefa \\\"{{taskName}}\\\" foi atribuído para {{firstName}} {{lastName}}\",\n      \"RELATED-CONTENT-ADDED\":\"\\\"{{name}}\\\" foi adicionada à tarefa\",\n      \"RELATED-CONTENT-ADDED-LOADING\":\"\\\"{{name}}\\\" foi adicionado à tarefa. O conteúdo estará disponível uma vez que for obtida de fonte externa.\"\n    },\n    \"ACTION\":{\n      \"COMPLETE-TASK-WITH-FORM\":\"Formulário completo\",\n      \"COMPLETE\":\"Completar\",\n      \"CLAIM\":\"Reivindicar\",\n      \"ASSIGN\":\"Atribuir\",\n      \"REASSIGN\":\"Reatribuir\",\n      \"CREATE\":\"+ Criar tarefa\",\n      \"CREATE-CONFIRM\":\"Criar\",\n      \"INVOLVE\":\"+ Envolver pessoas\",\n      \"ADD-COMMENT\":\"+ Adicionar comentário\",\n      \"ADD-COMMENT-CONFIRM\":\"Adicionar Comentário\",\n      \"ADD-CONTENT\":\"+ Adicionar conteúdo\",\n      \"CLEAR-DUEDATE\":\"Limpar data de vencimento\",\n      \"DUE-TODAY\":\"Vence hoje\",\n      \"CLEAR-DATE\":\"Limpar data\",\n      \"DATE-TODAY\":\"Data de hoje\",\n      \"AUDIT-LOG\":\"Log de auditoria\"\n    },\n    \"TITLE\":{\n      \"ASSIGN\":\"Selecione o responsável\",\n      \"ASSIGNEE\":\"Responsável\",\n      \"CONTENT\":\"Conteúdo relacionado\",\n      \"CREATE-NEW\":\"Nova tarefa\",\n      \"FORM\":\"Formulário\",\n      \"DETAILS\":\"Detalhes\",\n      \"ADD-RELATED-CONTENT\":\"Adicionar conteúdo relacionado\",\n      \"SELECT-DUEDATE\":\"Selecione a data de vencimento\",\n      \"SELECT-DATE\":\"Selecione a data\",\n      \"NO-CONTENT-ITEMS\":\"Não há itens de conteúdo\",\n      \"NO-PEOPLE-INVOLVED\":\"Não há pessoas envolvidas\",\n      \"NO-COMMENTS\":\"Nenhum comentário\",\n      \"COMMENT-COUNT\":\"comentário\",\n      \"COMMENTS-COUNT\":\"comentários\",\n      \"SHOW-DETAILS\":\"Mostrar detalhes\",\n      \"SHOW-FORM\":\"Mostrar formulário\"\n    },\n    \"FIELD\":{\n      \"NAME\":\"Nome\",\n      \"DESCRIPTION\":\"Descrição\",\n      \"ASSIGNEE\":\"Responsável\",\n      \"DUE\":\"Vencimento\",\n      \"PROCESS-INSTANCE\":\"Processo\",\n      \"ENDED\":\"Finalizado em\",\n      \"DURATION\":\"Duração\"\n    },\n    \"MESSAGE\":{\n      \"NO-NAME\":\"Tarefa sem nome\",\n      \"NO-ASSIGNEE\":\"Atribuído a ninguém\",\n      \"NO-DUEDATE\":\"Sem data de vencimento\",\n      \"DUE-ON\":\"Vencimento\",\n      \"CREATED-ON\":\"Criado em\",\n      \"ENDED-ON\":\"Concluído\",\n      \"REACHED-ON\":\"Alcançado\",\n      \"COMPLETED-BY\":\"Concluído por\",\n      \"NO-DESCRIPTION\":\"Esta tarefa não tem descrição\",\n      \"NO-RELATED-CONTENT\":\"Esta tarefa não tem nenhum conteúdo relacionado ainda...\",\n      \"NO-PEOPLE-INVOLVED\":\"Esta tarefa não tem pessoas envolvidas ainda...\",\n      \"NO-COMMENTS\":\"Esta tarefa não tem comentários ainda...\",\n      \"INVOLVE-PEOPLE-PLACEHOLDER\":\"+ Adicionar pessoa\",\n      \"CONTENT-UPLOADED-BY\":\"Adicionado por \",\n      \"ASSIGNEE\":\"Atribuído a\",\n      \"NEW-COMMENT-PLACEHOLDER\":\"Entre com um comentário para adicionar a esta tarefa\",\n      \"COMMENT-HEADER\":\"Adicionado por {{createdBy | username}}, {{created | dateformat: \\\"fromNow\\\"}}\",\n      \"NO-FILTER\":\"Mostrando as suas tarefas, nenhum filtro aplicado\",\n      \"FILTERED\":\"Mostrando as suas tarefas, nenhum filtro aplicado\",\n      \"NO-TASKS\":\"Não há tarefas correspondentes encontradas...\",\n      \"DURATION\":\"Demorou {{duration}}\",\n      \"CLAIM-TASK-FIRST\":\"Para ver e preencher o formulário para esta tarefa, você precisa reivindicar esta tarefa primeiro. Você pode fazer isso pressionando o botão azul no canto superior direito da página.\",\n      \"NO-TASKS-HELP\":\"Bem, parece que não há tarefas para você! Para obter alguma iniciada, você pode:\",\n      \"NO-SUCH-TASK-HELP\":\"A tarefa que você está procurando não foi encontrada! Se você quiser, você pode em vez disso:\",\n      \"NO-SUCH-TASK-RETURN-TO-LIST\":\"Retornar à sua lista de tarefas\",\n      \"NO-TASKS-CREATE-TASK\":\"Criar uma tarefa para si mesmo ou atribuí-la a outra pessoa\",\n      \"NO-TASKS-CREATE-PROCESS\":\"Iniciar um novo processo e em seguida acompanhar o seu progresso\"\n    },\n    \"HELP\":{\n      \"DESCRIPTION\":\"Esta tarefa ainda não tem detalhada ainda. Você pode mudar isso, escolhendo uma destas ações:\",\n      \"COMPLETED-DESCRIPTION\":\"Esta tarefa concluída não tem nenhum detalhe.\",\n      \"DESCRIPTION-WITH-CLAIM\":\"Esta tarefa ainda não tem detalhe. Você pode mudar isso, escolhendo uma das seguintes ações. Além disso, para concluir esta tarefa você precisa primeiro reclamá-la pressionando o botão azul no canto superior direito da página.\",\n      \"ADD-PEOPLE\":\"Envolva outra pessoa e comece a colaborar\",\n      \"ADD-COMMENT\":\"Destaque os outros adicionando um comentário\",\n      \"ADD-CONTENT\":\"Adicione um documento e compartilhe o conhecimento\"\n    }\n  },\n  \"PROCESS\":{\n    \"ALERT\":{\n      \"COMMENT-ADDED\":\"O comentário foi adicionado\",\n      \"STARTED\":\"Um novo processo \\\"{{processDefinitionName}}\\\" foi iniciado\",\n      \"START-PROCESS-CONTENT-ADD-FAILED\":\"Falha ao adicionar {{noOfFiles}} arquivo(s) ao processo\"\n    },\n    \"TITLE\":{\n      \"DIAGRAM\":\"Diagrama de processo\"\n    },\n    \"FILTER\":{\n      \"CREATED-DESC\":\"Mais Recentes Primeiro\",\n      \"CREATED-ASC\":\"Mais antigos primeiro\",\n      \"ENDED-DESC\":\"Completados recentemente\",\n      \"ENDED-ASC\":\"Completados menos recentemente\",\n      \"STATE-SUMMARY\":\"Mostrando o processo {{state.title | translate}}\",\n      \"STATE\":\"Estado do processo\",\n      \"STATE-RUNNING\":\"em execução\",\n      \"STATE-COMPLETED\":\"concluído\",\n      \"STATE-ALL\":\"Todos\"\n    },\n    \"MESSAGE\":{\n      \"NO-DESCRIPTION\":\"Esta instância de processo não tem descrição\",\n      \"NO-FILTER\":\"Mostrando todas as instâncias do processo, nenhum filtro aplicado\",\n      \"NO-INSTANCES\":\"Não há instâncias de processo correspondente encontradas...\",\n      \"NO-INSTANCES-HELP\":\"Não há nenhum processo executando agora. Se seus processos foram concluídos, você pode encontrá-los usando o filtro para a lista de processos. Para iniciar algum novo você pode:\",\n      \"NO-INSTANCES-HELP-START\":\"Iniciar um novo processo e acompanhar o seu progresso\",\n      \"NO-TASKS\":\"Não há tarefas ativas no momento...\",\n      \"NO-COMPLETED-TASKS\":\"Não há tarefas concluídas ainda...\",\n      \"NO-BUSINESS-KEY\":\"Nenhum conjunto de chave de negócios\",\n      \"NO-ACTIVE-MILESTONES\": \"No active milestones\",\n      \"CATEGORY\":\"Categoria: {{processDefinitionCategory}}\",\n      \"NEW-COMMENT-PLACEHOLDER\":\"Entre com o comentário a adicionar a este processo\",\n      \"COMMENT-HEADER\":\"Adicionado por {{createdBy | username}}, {{created | dateformat: \\\"fromNow\\\"}}\",\n      \"SELECT-DEFINITION\":\"Selecione um processo para iniciar a partir da lista abaixo\",\n      \"NO-PROCESS-DEFINITIONS\":\"Você não pode iniciar um processo, pois não há definições de processos disponíveis\",\n      \"START-PROCESS\":\"Iniciar Processo\",\n      \"STARTED-BY\":\"Iniciado por\",\n      \"NO-PROCESS-DEFINITION-SELECTED-HELP\":\"Por favor, selecione uma definição do processo\"\n    },\n    \"ACTION\":{\n      \"CREATE\":\"+ Iniciar um processo\",\n      \"BACK-TO-LIST\":\"Voltar para instâncias de processo\",\n      \"SHOW-DIAGRAM\":\"Mostrar o diagrama\",\n      \"CANCEL\":\"Cancelar o processo\",\n      \"DELETE\":\"Excluir o processo\",\n      \"ADD-COMMENT\":\"+ Adicionar comentário\",\n      \"ADD-COMMENT-CONFIRM\":\"Adicionar comentário\",\n      \"AUDIT-LOG\":\"Log de auditoria\"\n    },\n    \"FIELD\":{\n      \"BUSINESS-KEY\":\"Chave de negócios\",\n      \"CATEGORY\":\"Categoria\",\n      \"PROCESS-DEFINITION\":\"Definição de processo\",\n      \"STARTED\":\"Iniciado\",\n      \"STARTED-BY\":\"Iniciado por\",\n      \"ENDED\":\"Finalizado em\",\n      \"NAME\":\"Nome de instância do processo\",\n      \"NAME-PLACEHOLDER\":\"Digite um nome opcional para o processo que esta sendo iniciado\"\n    },\n    \"SECTION\":{\n      \"ACTIVE-TASKS\":\"Tarefas ativas\",\n      \"START-FORM\":\"Formulário de início\",\n      \"COMPLETED-TASKS\":\"Tarefas concluídas\",\n      \"COMMENTS\":\"Comentários\",\n      \"CONTENT\":\"Conteúdo\"\n    },\n    \"POPUP\":{\n      \"CANCEL-TITLE\":\"Cancelar o processo?\",\n      \"CANCEL-DESCRIPTION\":\"Você tem certeza que deseja cancelar o processo {{name}}?\",\n      \"DELETE-TITLE\":\"Excluir o processo?\",\n      \"DELETE-DESCRIPTION\":\"Você tem certeza que deseja excluir o processo {{name}}? Todas as tarefas, conteúdo e comentários relacionados com este processo serão excluídos permanentemente.\"\n    }\n  },\n  \"INVOLVE-PEOPLE\":{\n    \"NO-MATCHING-RESULTS\":\"Use a caixa de pesquisa acima para encontrar usuários\",\n    \"SEARCH-PLACEHOLDER\":\"Procurar usuário\",\n    \"BACK-TO-SEARCH\":\"Volta para pesquisa\",\n    \"ACTION-SELECT\":\"Selecionar\"\n  },\n  \"INTEGRATION\":{\n    \"ALERT\":{\n      \n    }\n  },\n  \"CONTENT\":{\n    \"SIMPLE-TYPE\":{\n      \"WORD\":\"Documento\",\n      \"EXCEL\":\"Planilha\",\n      \"PDF\":\"Documento PDF\",\n      \"IMAGE\":\"Imagem\",\n      \"FOLDER\":\"Pasta\",\n      \"CONTENT\":\"Conteúdo\"\n    },\n    \"MESSAGE\":{\n      \"NO-PREVIEW-AVAILABLE\":\"Sem visualização disponível\",\n      \"PREVIEW-PENDING\":\"Criar visualização...\",\n      \"CONTENT-PENDING\":\"Recebendo o conteúdo...\",\n      \"NOT-FOUND\":\"O conteúdo não pode ser encontrado\",\n      \"DELETE-CONFIRMATION\":\"Tem certeza que deseja excluir o {{name}}?\",\n      \"DROP\":\"Arrastar e Soltar ou \",\n      \"SELECT\":\"Escolha um aquivo\",\n      \"DRAGOVER\":\"Arraste e Solte o arquivo para carrega-lo\",\n      \"EXTERNAL-ONLY\":\"Selecione a fonte de conteúdo\"\n    },\n    \"TITLE\":{\n      \"DELETE\":\"Excluir conteúdo\",\n      \"NOT-FOUND\":\"Arquivo não encontrado\"\n    },\n    \"ACTION\":{\n      \n    }\n  },\n  \"FORM\":{\n    \"ACTION\":{\n      \"SAVE\":\"Salvar\"\n    },\n    \"DEFAULT-OUTCOME\":{\n      \"COMPLETE\":\"Completar\",\n      \"START-PROCESS\":\"Iniciar processo\"\n    },\n    \"MESSAGE\":{\n      \"SELECT-PERSON\":\"Nenhuma pessoa selecionada...\",\n      \"SELECT-GROUP\":\"Nenhum grupo selecionado...\",\n      \"EMPTY\":\"(vazio)\"\n    }\n  },\n  \"APP-DEFINITION\":{\n    \"MESSAGE\":{\n      \"NOT-FOUND\":\"Nenhuma definição de aplicativo encontrado com a identificação requisitada\",\n      \"MISSING\":\"Flowable eatá executado no modo de integração, mas a definição de aplicativo necessário está faltando\"\n    }\n  }\n}\n"
  },
  {
    "path": "flowable-ui-web/task/workflow/i18n/zh-CN.json",
    "content": "{\n    \"COMMON\" : {\n        \"SELECT-FOLDER\": \"选择文件夹...\"\n    },\n    \"GENERAL\": {\n        \"MAIN-TITLE\": \"Flowable -我的任务\",\n        \"ERROR\": {\n            \"GENERIC\": \"对不起, 发生了错误...\",\n            \"UNKNOWN\": \"对不起, 执行请求的操作时出错。\",\n            \"BAD_REQUEST\": \"执行请求的操作时发生错误\",\n            \"NOT_FOUND\": \"您试图访问的资源不存在\",\n            \"UNAUTHORIZED\": \"您应该登录才能执行请求的操作。\",\n            \"FORBIDDEN\": \"您不允许执行请求的操作\",\n            \"INTERNAL_SERVER_ERROR\": \"对不起, 执行请求的操作时出现意外错误。\"\n        },\n        \"NAVIGATION\": {\n            \"TASKS\": \"任务\",\n            \"PROCESSES\": \"流程\",\n            \"CASES\": \"Cases\",\n            \"DESIGN\": \"设计\",\n            \"CREATE\": \"+ 创建\",\n            \"LOGIN\": \"登录\"\n        },\n        \"TITLE\": {\n            \"ADD-COMMENT\": \"创建评论\", \n            \"INVOLVE-PEOPLE\": \"选择人\", \n            \"RECENT-PEOPLE\": \"最近的人\", \n            \"MATCHING-PEOPLE\": \"匹配的人\", \n            \"SELECT-GROUP\": \"选择组\", \n            \"MATCHING-GROUPS\": \"匹配组\", \n            \"FILTER\": \"筛选条件\", \n            \"SELECT-DATE\": \"选择日期\"\n        },\n        \"ACTION\": {\n            \"LOGOUT\": \"退出\", \n            \"ADD-COMMENT\": \"添加评论\", \n            \"SAVE\": \"保存\", \n            \"CANCEL\": \"取消\", \n            \"CLOSE\": \"关闭\", \n            \"CONFIRM\": \"确认\", \n            \"SHOW-MORE\": \"显示更多...\"\n        },\n        \"MESSAGE\": {\n            \"SELECT-PEOPLE-HELP\": \"使用 &uparrow; 和 &downarrow; 选择并按回车键确认\", \n            \"SELECT-GROUP-HELP\": \"使用 &uparrow; 和 &downarrow; 选择并按回车键确认\", \n            \"SELECT-GROUP-SEARCH-PLACEHOLDER\": \"搜索组\", \n            \"SELECT-GROUP-NO-MATCHING-RESULTS\": \"使用上面的搜索框查找组。\",\n            \"UPLOAD-CONTENT\": \"选择或删除文件\", \n            \"UPLOAD-CONTENT-NO-DROP\": \"选择要上载的文件\", \n            \"DROPZONE\": \"删除文件上传\", \n            \"YES\": \"是的\", \n            \"NO\": \"不\"\n        },\n        \"TIME\": {\n            \"HOURS\": \"小时\", \n            \"MINUTES\": \"分钟\", \n            \"SECONDS\": \"秒\"\n        },\n        \"ABOUT\": {\n            \"TYPE\": \"类型\", \n            \"LICENSED-TO\": \"许可的\", \n            \"EXPIRES\": \"期满\", \n            \"COPYRIGHT\": \"©2005-2015 Alfresco 软件 Inc。版权所有\", \n            \"LEGAL\": \"法律和许可证\"\n        }\n    },\n    \"LOGIN\": {\n        \"TITLE\": \"登录\", \n        \"USERNAME\": \"用户名\", \n        \"USERNAME-PLACEHOLDER\": \"输入您的用户名\", \n        \"PASSWORD\": \"密码\", \n        \"PASSWORD-PLACEHOLDER\": \"输入您的密码\", \n        \"ACTION\": {\n            \"CONFIRM\": \"登录\"\n        }\n    },\n    \"TASK\": {\n        \"SECTION\": {\n            \"PEOPLE\": \"人\", \n            \"CONTENT\": \"内容\", \n            \"COMMENTS\": \"评论\", \n            \"NOTES\": \"注意\"\n        },\n        \"FILTER\": {\n            \"CREATED-DESC\": \"最近的\", \n            \"CREATED-ASC\": \"最早的\", \n            \"DUE-DESC\": \"最晚到期\", \n            \"DUE-ASC\": \"最早到期\", \n            \"TEXT\": \"筛选条件\", \n            \"TEXT-PLACEHOLDER\": \"按任务名称搜索\", \n            \"TEXT-SUMMARY\": \"已筛选: {{text}}\", \n            \"PROCESS-DEFINITION\": \"流程定义\", \n            \"PROCESS-DEFINITION-PLACEHOLDER\": \"选择流程定义...\", \n            \"STATE\": \"国家\",\n            \"STATE-OPEN\": \"开放\", \n            \"STATE-COMPLETED\": \"已完成\", \n            \"ASSIGNMENT\": \"分配\", \n            \"ASSIGNMENT-INVOLVED\": \"我参与的任务\", \n            \"ASSIGNMENT-ASSIGNEE\": \"我是被分配人的任务\", \n            \"ASSIGNMENT-CANDIDATE\": \"我是其中一个候选人的任务\", \n            \"ASSIGNMENT-GROUP\": \"分配给组 \\\"{{name}} \\\" 的任务\", \n            \"RESET\": \"重置筛选条件\"\n        },\n        \"ALERT\": {\n        \t\"COMMENT-ADDED\": \"已将注释添加到\\\"{{name}}\\\"\", \n            \"PERSON-INVOLVED\": \"{{lastName}}{{firstName}}现在参与\\\"{{taskName}} \\\"\", \n            \"PERSON-NO-LONGER-INVOLVED\": \"{{lastName}}{{firstName}}不再参与\\\"{{taskName}} \\\"\", \n            \"CREATED\": \"已创建任务 \\\"{{name}} \\\"\", \n            \"COMPLETED\": \"任务完成\", \n            \"SAVED\": \"任务表已保存\", \n            \"ASSIGNED\": \"任务 \\\"{{taskName}} \\\" 现在分配到 {{lastName}}{{firstName}}\", \n            \"RELATED-CONTENT-ADDED\": \"\\\"{{name}} \\\" 已添加到任务中\", \n            \"RELATED-CONTENT-ADDED-LOADING\": \"\\\"{{name}}\\\"已添加到任务中。一旦从外部源检索到这些内容, 就可以使用。\"\n        },\n        \"ACTION\": {\n            \"COMPLETE-TASK-WITH-FORM\": \"完成表单\",\n            \"COMPLETE\": \"完成\",\n            \"CLAIM\": \"认领\",\n            \"ASSIGN\": \"分配\", \n            \"REASSIGN\": \"重新分配\", \n            \"CREATE\": \"+ 创建任务\", \n             \"CREATE-SUB-TASK\": \"创建子任务\",\n            \"CREATE-CONFIRM\": \"创建\", \n            \"INVOLVE\": \"+ 参与人\", \n            \"ADD-COMMENT\": \"+ 添加评论\", \n            \"ADD-COMMENT-CONFIRM\": \"添加评论\", \n            \"ADD-CONTENT\": \"+ 添加内容\", \n            \"CLEAR-DUEDATE\": \"Clear due date\", \n            \"DUE-TODAY\": \"今天到期\", \n            \"CLEAR-DATE\": \"Clear date\", \n            \"DATE-TODAY\": \"今日日期\", \n            \"AUDIT-LOG\": \"审核日志\"\n        },\n        \"TITLE\": {\n            \"ASSIGN\": \"选择被分配人\",\n            \"ASSIGNEE\": \"被分配人\",\n            \"CONTENT\": \"相关内容\",\n            \"SUBTASK\": \"子任务\",\n            \"CREATE-NEW\": \"新任务\",\n            \"FORM\": \"表单\",\n            \"DETAILS\": \"详细信息\",\n            \"ADD-RELATED-CONTENT\": \"添加相关内容\",\n            \"SELECT-DUEDATE\": \"选择到期日期\",\n            \"SELECT-DATE\": \"选择日期\",\n            \"NO-CONTENT-ITEMS\": \"无内容项目\",\n            \"NO-PEOPLE-INVOLVED\": \"没有人参与\",\n            \"NO-COMMENTS\": \"无评论\",\n            \"COMMENT-COUNT\": \"评论\",\n            \"COMMENTS-COUNT\": \"评论\",\n            \"NO-SUBTASKS\": \"没有子任务\",\n            \"SUBTASK-COUNT\": \"子任务 \",\n            \"SUBTASKS-COUNT\": \"子任务\",\n            \"SHOW-DETAILS\": \"显示详细信息\",\n            \"SHOW-FORM\": \"显示表单\"\n        },\n        \"FIELD\": {\n            \"NAME\": \"名称\",\n            \"DESCRIPTION\": \"描述\",\n            \"ASSIGNEE\": \"被分配人\",\n\n            \"DUE\": \"到期\",\n            \"PROCESS-INSTANCE\": \"部分流程\",\n            \"CASE-INSTANCE\": \"部分case\",\n            \"PARENT-TASK\": \"部分任务\",\n            \"ENDED\": \"结束\",\n            \"DURATION\": \"Duration\"\n        },\n        \"MESSAGE\": {\n            \"NO-NAME\": \"没有名称的任务\",\n            \"NO-ASSIGNEE\": \"Assigned to nobody\",\n            \"NO-DUEDATE\": \"没有截止日期\",\n            \"DUE-ON\": \"到期\",\n            \"CREATED-ON\": \"创建\",\n            \"ENDED-ON\": \"完成\",\n            \"REACHED-ON\": \"Reached\",\n            \"COMPLETED-BY\": \"Completed by\",\n            \"NO-DESCRIPTION\": \"这项任务没有说明\",\n            \"NO-RELATED-CONTENT\": \"此任务还没有相关内容...\",\n            \"NO-PEOPLE-INVOLVED\": \"这项任务还没有人参与...\",\n            \"NO-COMMENTS\": \"此任务尚未发表评论...\",\n            \"INVOLVE-PEOPLE-PLACEHOLDER\": \"+ 添加人\",\n            \"CONTENT-UPLOADED-BY\": \"添加的 \",\n            \"ASSIGNEE\": \"Assigned to\",\n            \"NEW-COMMENT-PLACEHOLDER\": \"输入要添加到此任务的注释\",\n            \"COMMENT-HEADER\": \" {{createdBy | username}}, {{created | dateformat:\\\"fromNow\\\"}} 添加\",\n            \"NO-FILTER\": \"显示您的全部任务\",\n            \"FILTERED\": \"显筛选之后您的任务\",\n            \"NO-TASKS\": \"没有找到匹配的任务...\",\n            \"DURATION\": \"采取了 {{duration}}\",\n            \"CLAIM-TASK-FIRST\": \"要查看并填写此任务的表单, 您需要首先声明此任务。您可以通过按页面右上的蓝色按钮来完成此项。\",\n            \"NO-TASKS-HELP\": \"嗯，看起来好像没有任务给你！为了开始某事，你可以:\",\n            \"NO-SUCH-TASK-HELP\": \"看起来您没什么任务! 如果你想，你可以代替:\",\n            \"NO-SUCH-TASK-RETURN-TO-LIST\": \"返回到您的任务列表\",\n            \"NO-TASKS-CREATE-TASK\": \"为自己创建任务或将其分派给其他人\",\n            \"NO-TASKS-CREATE-PROCESS\": \"启动一个新流程, 然后跟踪其进度\"\n        },\n        \"HELP\" : {\n            \"DESCRIPTION\": \"此任务尚未详细说明。您可以通过选择下列操作之一来更改它:\",\n            \"COMPLETED-DESCRIPTION\": \"此已完成的任务没有详细信息。\",\n            \"DESCRIPTION-WITH-CLAIM\": \"此任务尚未详细说明。您可以通过选择下列操作之一来更改它。此外, 要完成此任务, 您需要首先通过按页面右上的蓝色按钮来声明它。\",\n            \"ADD-PEOPLE\": \"参与其他人并开始合作\",\n            \"ADD-COMMENT\": \"通过添加评论启发他人\",\n            \"ADD-CONTENT\": \"添加文档并共享知识\",\n            \"ADD-SUBTASK\": \"创建一个子任务\"\n        }\n    },\n    \"PROCESS\": {\n        \"ALERT\": {\n            \"COMMENT-ADDED\": \"评论被添加\",\n            \"STARTED\": \"已启动一个新的\\\"{{processDefinitionName}}}\\\" 流程\",\n            \"START-PROCESS-CONTENT-ADD-FAILED\": \"将 {{noOfFiles}} 文件添加到流程操作失败\"\n        },\n        \"TITLE\": {\n            \"DIAGRAM\": \"流程图\",\n            \"EXECUTION\": \"Execution\",\n            \"EXECUTIONS\": \"Executions\",\n            \"EXPRESSION\": \"Expression\",\n            \"SCRIPT\": \"Script\",\n            \"RESULT\": \"Result\",\n            \"VARIABLES\": \"Variables\",\n            \"LOG\": \"Log\"\n        },\n        \"FILTER\": {\n            \"CREATED-DESC\": \"最近的\",\n            \"CREATED-ASC\": \"最早的\",\n            \"ENDED-DESC\": \"最近完成的\",\n            \"ENDED-ASC\": \"最早完成的\",\n            \"STATE-SUMMARY\": \"显示 {{state.title | translate}} 流程\",\n            \"STATE\": \"流程状态\",\n            \"STATE-RUNNING\": \"运行\",\n            \"STATE-COMPLETED\": \"已完成\",\n            \"STATE-ALL\": \"所有\"\n        },\n        \"MESSAGE\": {\n            \"NO-DESCRIPTION\": \"此流程实例没有说明\",\n            \"NO-FILTER\": \"显示所有流程实例\",\n            \"NO-INSTANCES\": \"找到匹配的流程实例...\",\n            \"NO-INSTANCES-HELP\": \"现在没有正在运行的流程。如果流程已完成, 则可以使用 \\\"流程\\\" 列表的筛选器找到它们。为了得到新的东西, 你可以:\",\n            \"NO-INSTANCES-HELP-START\": \"启动新流程并跟踪其进度\",\n            \"NO-TASKS\": \"当前没有任务处于活动状态 ...\",\n            \"NO-COMPLETED-TASKS\": \"尚未完成任务...\",\n            \"NO-BUSINESS-KEY\": \"没有设置business key \",\n            \"NO-ACTIVE-MILESTONES\": \"没有活动里程碑\",\n            \"CATEGORY\": \"类别: {{processDefinitionCategory}}\",\n            \"NEW-COMMENT-PLACEHOLDER\": \"Enter a comment to add to this process\",\n            \"COMMENT-HEADER\": \" {{createdBy | username}}, {{created | dateformat:\\\"fromNow\\\"}} 添加\",\n            \"SELECT-DEFINITION\": \"从下面的列表中选择一个流程\",\n            \"NO-PROCESS-DEFINITIONS\": \"您无法启动流程, 因为没有可用的流程定义\",\n            \"START-PROCESS\": \"启动流程\",\n            \"STARTED-BY\": \"Started by\",\n            \"NO-PROCESS-DEFINITION-SELECTED-HELP\": \"请选择流程定义\"\n        },\n        \"ACTION\" : {\n            \"CREATE\": \"+ 启动流程\",\n            \"BACK-TO-LIST\": \"返回到流程实例\",\n            \"SHOW-DIAGRAM\": \"显示图\",\n            \"CANCEL\": \"取消流程\",\n            \"EXECUTE\": \"Execute\",\n            \"DELETE\": \"删除流程\",\n            \"ADD-COMMENT\": \"+  添加评论\",\n            \"ADD-COMMENT-CONFIRM\": \" 添加评论\",\n            \"AUDIT-LOG\": \"审核日志\"\n        },\n        \"FIELD\": {\n            \"BUSINESS-KEY\": \"Business key\",\n            \"CATEGORY\": \"分类\",\n            \"PROCESS-DEFINITION\": \"流程定义\",\n            \"STARTED\": \"开始\",\n            \"STARTED-BY\": \"Started by\",\n            \"ENDED\": \"结束\",\n            \"NAME\": \"流程实例名称\",\n            \"NAME-PLACEHOLDER\" : \"为正在启动的流程输入一个可选名称\"\n        },\n        \"SECTION\": {\n            \"ACTIVE-TASKS\": \"活动任务\",\n            \"START-FORM\": \"Start form\",\n            \"COMPLETED-TASKS\": \"完成的任务\",\n            \"COMMENTS\": \"评论\",\n            \"CONTENT\" : \"内容\"\n        },\n        \"POPUP\": {\n            \"CANCEL-TITLE\": \"取消流程?\",\n            \"CANCEL-DESCRIPTION\": \"是否确实要取消流程  {{name}}?\",\n            \"DELETE-TITLE\": \"是否删除该流程?\",\n            \"DELETE-DESCRIPTION\": \"确实要删除流程 {{name}} 吗？所有与此流程相关的任务、内容和评论将被永久删除。\"\n        }\n    },\n    \"CASE\": {\n        \"ALERT\": {\n            \"STARTED\": \"A new  \\\"{{caseDefinitionName}}\\\" case was started\",\n            \"START-CASE-CONTENT-ADD-FAILED\": \"Failed to add {{noOfFiles}} file(s) to the case\"\n        },\n        \"TITLE\": {\n            \"DIAGRAM\": \"Case图像\"\n        },\n        \"FILTER\": {\n            \"CREATED-DESC\": \"最近的\",\n            \"CREATED-ASC\": \"最早的\",\n            \"ENDED-DESC\": \"最近完成\",\n            \"ENDED-ASC\": \"最早完成的\",\n            \"STATE-SUMMARY\": \"显示 {{state.title | translate}} cases\",\n            \"STATE\": \"Case 状态\",\n            \"STATE-RUNNING\": \"运行的\",\n            \"STATE-COMPLETED\": \"已经完成的\",\n            \"STATE-ALL\": \"所有\"\n        },\n        \"MESSAGE\": {\n            \"NO-DESCRIPTION\": \"这个case实例没有说明\",\n            \"NO-FILTER\": \"显示所有case实例\",\n            \"NO-INSTANCES\": \"未找到匹配的case实例...\",\n            \"NO-INSTANCES-HELP\": \"现在没有正在运行的cases。如果流程已完成, 则可以使用case列表的筛选器找到它们。为了得到新的东西, 你可以:\",\n            \"NO-INSTANCES-HELP-START\": \"启动新case并跟踪其进度\",\n            \"NO-TASKS\": \"当前没有任务处于活动状态 ...\",\n            \"NO-COMPLETED-TASKS\": \"尚未完成任务...\",\n            \"NO-BUSINESS-KEY\": \"没有设置 business key\",\n            \"CATEGORY\": \"分类: {{processDefinitionCategory}}\",\n            \"SELECT-DEFINITION\": \"从下面的列表中选择一个case并启动\",\n            \"NO-CASE-DEFINITIONS\": \" 您无法启动case, 因为没有可用的case定义\",\n            \"START-CASE\": \"启动Case\",\n            \"STARTED-BY\": \"Started by\",\n            \"STAGE-STARTED\": \"启动\",\n            \"STAGE-ENDED\": \"结束\",\n            \"STAGE-NOT-STARTED\": \"还没有开始\",\n            \"STATE\": \"状态\",\n            \"STAGE-NO-NAME\": \"Nameless stage\",\n            \"MILESTONE-REACHED-ON\": \"Reached\",\n            \"MILESTONE-TERMINATED-ON\": \"Terminated\",\n            \"NO-CASE-DEFINITION-SELECTED-HELP\": \"请选择一个case定义\",\n            \"NO-ACTIVE-STAGES\": \"没有活动stages\",\n            \"NO-ENDED-STAGES\": \"没有结束的stages\",\n            \"NO-AVAILABLE-MILESTONES\": \"没有活动里程碑\",\n            \"NO-REACHED-MILESTONES\": \"没有到达里程碑\",\n            \"NO-AVAILABLE-USER-EVENT-LISTENERS\":\"没有可用的事件监听器\",\n            \"NO-COMPLETED-USER-EVENT-LISTENERS\":\"没有完成的事件监听器\",\n            \"USER-EVENT-LISTENER-NO-NAME\": \"没有名称的事件监听器 Event Listener\",\n            \"USER-EVENT-LISTENER-COMPLETED\": \"完成\",\n            \"ENABLED-PLAN-ITEM_INSTANCE-NO-NAME\": \"没有名称\",\n            \"START-PLAN-ITEM-INSTANCE\": \"启动\"\n        },\n        \"ACTION\" : {\n            \"CREATE\": \"+ 启动一个case\",\n            \"BACK-TO-LIST\": \"返回到case实例列表\",\n            \"SHOW-DIAGRAM\": \"显示图\",\n            \"CANCEL\": \"取消case\",\n            \"DELETE\": \"删除case\",\n            \"TRIGGER-USER-EVENT-LISTENER\": \"触发\",\n            \"AUDIT-LOG\": \"审核日志\"\n        },\n        \"FIELD\": {\n            \"BUSINESS-KEY\": \"Business key\",\n            \"CATEGORY\": \"分类\",\n            \"CASE-DEFINITION\": \"Case定义\",\n            \"STARTED\": \"Started\",\n            \"STARTED-BY\": \"Started by\",\n            \"ENDED\": \"结束\",\n            \"NAME\": \"Case实例名称\",\n            \"NAME-PLACEHOLDER\" : \"为正在启动的case输入一个可选的名称\"\n        },\n        \"SECTION\": {\n            \"ACTIVE-TASKS\": \"活动任务\",\n            \"COMPLETED-TASKS\": \"完成的任务\",\n            \"ACTIVE-STAGES\": \"可用/活动 stages\",\n            \"ENDED-STAGES\": \"结束的 stages\",\n            \"AVAILABLE-MILESTONES\": \"可用的里程碑（milestones）\",\n            \"REACHED-MILESTONES\": \"可达到的里程碑（milestones）\",\n            \"AVAILABLE-USER-EVENT-LISTENERS\": \"可以用的用户事件监听器\",\n            \"COMPLETED-USER-EVENT-LISTENERS\": \"已经完成的用户事件监听器\",\n            \"CONTENT\" : \"内容\",\n            \"ENABLED-PLAN-ITEM-INSTANCES\": \"启用计划项目实例\"\n        },\n        \"POPUP\": {\n            \"CANCEL-TITLE\": \"取消case?\",\n            \"CANCEL-DESCRIPTION\": \"是否确实要取消case {{name}}?\",\n            \"DELETE-TITLE\": \"删除该case?\",\n            \"DELETE-DESCRIPTION\": \"确实要删除 case {{name}}?所有与这个case相关的任务、内容和评论将被永久删除 \"\n        }\n    },\n    \"INVOLVE-PEOPLE\": {\n        \"NO-MATCHING-RESULTS\": \"使用上面的搜索框查找用户\",\n        \"SEARCH-PLACEHOLDER\": \"搜索用户\",\n        \"BACK-TO-SEARCH\": \"回到搜索\",\n        \"ACTION-SELECT\": \"选择\"\n    },\n    \"INTEGRATION\": {\n        \"ALERT\": {\n        }\n    },\n    \"CONTENT\": {\n        \"SIMPLE-TYPE\": {\n            \"WORD\": \"文件\",\n            \"EXCEL\": \"电子表格\",\n            \"PDF\": \"PDF 文档\",\n            \"IMAGE\": \"图像\",\n            \"FOLDER\": \"文件夹\",\n            \"CONTENT\": \"Content\"\n        },\n        \"MESSAGE\": {\n            \"NO-PREVIEW-AVAILABLE\": \"没有可用的预览\",\n            \"PREVIEW-PENDING\": \"正在创建预览...\",\n            \"CONTENT-PENDING\": \"获取content...\",\n            \"NOT-FOUND\": \"无法找到content\",\n            \"DELETE-CONFIRMATION\": \"是否确实要删除 {{name}}?\",\n            \"DROP\": \"Drop 或 \",\n            \"SELECT\": \"选择一个文件\",\n            \"DRAGOVER\": \"Drop文件去上传\",\n            \"EXTERNAL-ONLY\": \"选择content源\"\n        },\n        \"TITLE\": {\n            \"DELETE\": \"删除content\",\n            \"NOT-FOUND\": \"找不到文件\"\n        },\n        \"ACTION\":  {\n        }\n    },\n    \"FORM\" : {\n        \"ACTION\": {\n            \"SAVE\": \"保存\"\n        },\n        \"DEFAULT-OUTCOME\": {\n            \"COMPLETE\": \"完成\",\n            \"START-PROCESS\": \"启动流程\",\n            \"START-CASE\": \"启动case\"\n        },\n        \"MESSAGE\" : {\n            \"SELECT-PERSON\": \"没有人选择...\",\n            \"SELECT-GROUP\": \"没有选定的组...\",\n            \"EMPTY\": \"(空)\"\n        }\n    },\n    \"APP-DEFINITION\" : {\n        \"MESSAGE\" : {\n            \"NOT-FOUND\": \"没有使用给定id找到 app 定义\",\n            \"MISSING\": \" Flowable运行在集成模式下,但是所需的app定义丢失了\"\n        }\n    }\n}\n"
  },
  {
    "path": "flowable-ui-web/task/workflow/index.html",
    "content": "<!doctype html>\n<!--[if lt IE 7]>      <html class=\"no-js lt-ie9 lt-ie8 lt-ie7\"> <![endif]-->\n<!--[if IE 7]>         <html class=\"no-js lt-ie9 lt-ie8\"> <![endif]-->\n<!--[if IE 8]>         <html class=\"no-js lt-ie9\"> <![endif]-->\n<!--[if gt IE 8]><!--> <html class=\"no-js\"> <!--<![endif]-->\n<head>\n    <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    <title>Flowable Workflow</title>\n    <link rel=\"icon\" type=\"image/ico\" href=\"../favicon.ico\">\n\n    <!-- build:css styles/3thparty.css -->\n    <link href=\"../styles/common/bootstrap.min.css\" rel=\"stylesheet\">\n    <!-- endbuild -->\n\n    <!-- build:css styles/style.css -->\n    <link href=\"../styles/common/style.css\" rel=\"stylesheet\">\n    <link href=\"../styles/common/style-retina.css\" rel=\"stylesheet\">\n    <link href=\"styles/style-workflow.css\" rel=\"stylesheet\">\n    <link rel=\"stylesheet\" href=\"../libs/angular-loading-bar-0.7.0/loading-bar.min.css\" />\n    <!-- endbuild -->\n\n    <link rel=\"Stylesheet\" href=\"../libs/ui-grid_3.0.0/ui-grid.css\" type=\"text/css\"/>\n</head>\n<body ng-app=\"flowableApp\" ng-cloak>\n    <div class=\"navbar navbar-fixed-top navbar-inverse\" ng-show=\"!root.headless\" role=\"navigation\" id=\"main-nav\">\n        <div class=\"fixed-container\">\n            <div class=\"navbar-header\">\n                <a ng-click=\"backToLanding()\" class=\"landing-logo\" ng-if=\"account != null && account != undefined\" title=\"{{'GENERAL.MAIN-TITLE' | translate}}\">\n                    <img ng-src=\"{{appResourceRoot}}../images/flowable-logo.png\" ng-srcset=\"{{appResourceRoot}}../images/flowable-logo.png 1x, {{appResourceRoot}}../images/flowable-logo@2x.png 2x\">\n                </a>\n                <ul class=\"nav navbar-nav\" ng-show=\"authenticated\">\n                    <li ng-repeat=\"item in mainNavigation\" ng-class=\"{'active': item.id == mainPage.id}\">\n                        <a ng-click=\"setMainPage(item)\">{{item.title | translate}}</a>\n                    </li>\n                </ul>\n            </div>\n            <div class=\"pull-right {{activeAppDefinition.theme}}\" ng-class=\"{'app-indicator': activeAppDefinition.theme}\" ng-show=\"authenticated\" ng-cloack>\n                <span ng-if=\"activeAppDefinition.theme\">\n                    {{activeAppDefinition.name}}\n                </span>\n                <i class=\"glyphicon {{activeAppDefinition.icon}}\"></i>\n                <div class=\"dropdown btn-group btn-group-sm\">\n                    <button type=\"button\" class=\"btn btn-default dropdown-toggle\"\n                            data-toggle=\"dropdown\">{{account.firstName && account.firstName != 'null' ? account.firstName : ''}} {{account.lastName && account.lastName != 'null' ? account.lastName : ''}}\n                        <span class=\"glyphicon glyphicon-chevron-down\" style=\"font-size: 10px\" aria-hidden=\"true\"></span>\n                    </button>\n                    <ul class=\"dropdown-menu pull-right\">\n                        <li><a ng-click=\"logout()\" translate=\"GENERAL.ACTION.LOGOUT\"></a></li>\n                    </ul>\n                </div>\n            </div>\n        </div>\n    </div>\n\n    <!--[if lt IE 9]>\n    <div class=\"unsupported-browser\">\n        <p class=\"alert error\">You are using an unsupported browser. Please upgrade your browser in order to use the\n            editor.</p>\n    </div>\n    <![endif]-->\n    <!--[if IE 9]>\n    <div id=\"no-flash-message\" class=\"unsupported-browser\" style=\"display: none\">\n        <p class=\"alert error\">No Adobe Flash installed. Please install Adobe Flash in order to use the file upload capabilities on this version of Internet Explorer.</p>\n    </div>\n    <script>\n        var hasFlash = false;\n        try {\n            hasFlash = Boolean(new ActiveXObject('ShockwaveFlash.ShockwaveFlash'));\n        } catch(exception) {\n            hasFlash = ('undefined' != typeof navigator.mimeTypes['application/x-shockwave-flash']);\n        }\n        if (!hasFlash) {\n            var showNoFlashMessage = function () {\n                var element = document.getElementById('no-flash-message');\n                element.style.display=\"block\";\n            };\n            showNoFlashMessage();\n        }\n    </script>\n    <![endif]-->\n    <div class=\"alert-wrapper\" ng-cloak ng-class=\"{'no-header' : root.headless}\">\n        <div class=\"alert {{alerts.current.type}}\" ng-show=\"alerts.current\" ng-click=\"dismissAlert()\">\n            <span>{{alerts.current.message}}</span>\n            <span class=\"badge\" ng-show=\"alerts.queue.length\">{{alerts.queue.length + 1}}</span>\n        </div>\n    </div>\n\n    <div class=\"wrapper clearfix\" ng-class=\"{'no-header' : root.headless}\" ng-view=\"\" ng-cloak ng-style=\"{height: window.height + 'px'}\">\n    </div>\n\n    <!--[if lt IE 9]>\n    <script src=\"../libs/es5-shim-15.3.4.5/es5-shim.js\"></script>\n    <script src=\"../libs/json3_3.2.6/lib/json3.min.js\"></script>\n    <![endif]-->\n\n    <!-- 3rd party libs -->\n    <script src=\"../libs/jquery_1.11.0/jquery.min.js\"></script>\n    <script src=\"../libs/jquery-ui-1.10.3.custom.min.js\"></script>\n\n    <script src=\"../libs/angular_1.3.13/angular.min.js\"></script>\n    <script src=\"../libs/angular-animate_1.3.13/angular-animate.min.js\"></script>\n    <script src=\"../libs/bootstrap_3.1.1/js/bootstrap.min.js\"></script>\n    <script src=\"../libs/angular-resource_1.3.13/angular-resource.min.js\"></script>\n    <script src=\"../libs/angular-cookies_1.3.13/angular-cookies.min.js\"></script>\n    <script src=\"../libs/angular-sanitize_1.3.13/angular-sanitize.min.js\"></script>\n    <script src=\"../libs/angular-route_1.3.13/angular-route.min.js\"></script>\n    <script src=\"../libs/angular-translate_2.15.1/angular-translate.min.js\"></script>\n    <script src=\"../libs/angular-translate-storage-cookie/angular-translate-storage-cookie.js\"></script>\n    <script src=\"../libs/angular-translate-loader-static-files/angular-translate-loader-static-files.js\"></script>\n    <script src=\"../libs/angular-strap_2.1.6/angular-strap.min.js\"></script>\n    <script src=\"../libs/angular-strap_2.1.6/angular-strap.tpl.min.js\"></script>\n    <script src=\"../libs/angular-dragdrop_1.0.11/angular-dragdrop.min.js\"></script>\n    <script src=\"../libs/ng-file-upload/ng-file-upload-shim.min.js\"></script>\n    <script src=\"../libs/ng-file-upload/ng-file-upload.min.js\"></script>\n    <script src=\"../libs/momentjs_2.18.1/momentjs.min.js\"></script>\n    <script src=\"../libs/ui-grid_3.0.0/ui-grid.js\" type=\"text/javascript\"></script>\n    <script src=\"../libs/angular-loading-bar-0.7.0/loading-bar.min.js\"></script>\n    <script src=\"../libs/angular-hotkeys_1.4.5/hotkeys--activiti-patch.js\"></script>\n    <script src=\"../libs/angular-ui-mask/mask.min.js\"></script>\n\n    <!-- Configuration -->\n    <script src=\"../scripts/app-cfg.js?v=2\"></script>\n\n    <!-- build:js scripts/scripts.js -->\n    <script src=\"scripts/workflow-app.js\"></script>\n    <script src=\"scripts/services/cmmn-stage-service.js\"></script>\n    <script src=\"scripts/services/cmmn-milestone-service.js\"></script>\n    <script src=\"scripts/services/cmmn-user-event-listener-service.js\"></script>\n    <script src=\"scripts/services/cmmn-plan-item-instance-service.js\"></script>\n    <script src=\"scripts/services/comment-service.js\"></script>\n    <script src=\"scripts/services/process-service.js\"></script>\n    <script src=\"scripts/services/case-service.js\"></script>\n    <script src=\"scripts/services/task-service.js\"></script>\n    <script src=\"scripts/services/form-service.js\"></script>\n    <script src=\"scripts/services/app-definition-service.js\"></script>\n    <script src=\"scripts/controllers.js\"></script>\n    <script src=\"scripts/controllers/document-preview.js\"></script>\n    <script src=\"scripts/controllers/tasks.js\"></script>\n    <script src=\"scripts/controllers/task.js\"></script>\n    <script src=\"scripts/controllers/processes.js\"></script>\n    <script src=\"scripts/controllers/process.js\"></script>\n    <script src=\"scripts/controllers/render-form.js\"></script>\n    <script src=\"scripts/controllers/start-form.js\"></script>\n    <script src=\"scripts/controllers/start-process.js\"></script>\n    <script src=\"scripts/controllers/cases.js\"></script>\n    <script src=\"scripts/controllers/case.js\"></script>\n    <script src=\"scripts/controllers/case-start-form.js\"></script>\n    <script src=\"scripts/workflow-directives.js\"></script>\n\n    <script src=\"../scripts/common/services/user-service.js\"></script>\n\t<script src=\"../scripts/common/services/functional-group-service.js\"></script>\n\t<script src=\"../scripts/common/services/related-content-service.js\"></script>\n    <script src=\"../scripts/common/services/runtime-app-definition-service.js\"></script>\n    <script src=\"../scripts/common/directives.js\"></script>\n    <script src=\"../scripts/common/providers-config.js\"></script>\n    <script src=\"../scripts/common/services/resource-service.js\"></script>\n    <script src=\"../scripts/common/services/recursion-helper.js\"></script>\n\n    <script src=\"../scripts/common/controllers/about.js\"></script>\n    <!-- endbuild -->\n\n    <!-- Integration extensions -->\n    <script src=\"../scripts/resource-loader.js?v=2\" app=\"workflow\"></script>\n\n</body>\n</html>\n"
  },
  {
    "path": "flowable-ui-web/task/workflow/scripts/controllers/case-start-form.js",
    "content": "/* 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'use strict';\n\nangular.module('flowableApp')\n    .controller('CaseStartFormController', ['$rootScope', '$scope', '$translate', '$http', '$timeout','$location', '$route', '$modal', '$routeParams', '$popover',\n        function ($rootScope, $scope, $translate, $http, $timeout, $location, $route, $modal, $routeParams, $popover) {\n   \n    $scope.model.initializing = true;    \n        \n    $scope.$watch('selectedCaseInstance', function(newValue) {\n       \n        if (newValue && newValue.id && (newValue.id != $rootScope.root.selectedCaseId || !$scope.model.initializing)) {\n            $scope.model.caseInstance = newValue;\n\n            $scope.getCaseInstance(newValue.id);\n            $rootScope.root.showStartForm = false;\n            $scope.model.formData = undefined;\n            $scope.model.initializing = false;\n        }\n    });\n        \n    $scope.getCaseInstance = function(caseInstanceId) {\n        $http({method: 'GET', url: FLOWABLE.CONFIG.contextRoot + '/app/rest/case-instances/' + caseInstanceId}).\n            success(function(response, status, headers, config) {\n                $scope.model.caseInstance = response;\n                $scope.loadStartForm(caseInstanceId);\n            }).\n            error(function(response, status, headers, config) {\n                console.log('Something went wrong: ' + response);\n            });\n    };\n\n    $scope.loadStartForm = function(caseInstanceId) {\n        $http({method: 'GET', url: FLOWABLE.CONFIG.contextRoot + '/app/rest/case-instances/' + caseInstanceId + '/start-form'}).\n            success(function(response, status, headers, config) {\n                $scope.model.formData = response;\n            }).\n            error(function(response, status, headers, config) {\n                console.log('Something went wrong: ' + response);\n            });\n    };\n    \n    $scope.openCaseInstance = function() {\n        $rootScope.root.showStartForm = false;\n        $scope.model.formData = undefined;\n    };\n    \n    $scope.getCaseInstance($rootScope.root.selectedCaseId);\n}]);\n"
  },
  {
    "path": "flowable-ui-web/task/workflow/scripts/controllers/case.js",
    "content": "/* 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'use strict';\n\nangular.module('flowableApp')\n    .controller('CaseController', ['$rootScope', '$scope', '$translate', '$http', '$timeout', '$location', '$modal', '$routeParams', 'AppDefinitionService',\n        function ($rootScope, $scope, $translate, $http, $timeout, $location, $modal, $routeParams, AppDefinitionService) {\n\n            // Ensure correct main page is set\n            $rootScope.setMainPageById('cases');\n\n            $scope.selectedCaseInstance = {id: $routeParams.caseId};\n\n            $scope.appDefinitionKey = $routeParams.appDefinitionKey;\n\n            $scope.$on('caseinstance-deleted', function (event, data) {\n                $scope.openCases();\n            });\n\n            $scope.openCases = function (task) {\n                var path = '';\n                if ($rootScope.activeAppDefinition && !FLOWABLE.CONFIG.integrationProfile) {\n                    path = \"/apps/\" + $rootScope.activeAppDefinition.id;\n                }\n                $location.path(path + \"/cases\");\n            };\n        }]);\n\nangular.module('flowableApp')\n    .controller('CaseDetailController', ['$rootScope', '$scope', '$translate', '$http', '$timeout', '$location', '$route', '$modal', '$routeParams', '$popover', 'appResourceRoot', 'TaskService', 'CaseService', 'CommentService', 'RelatedContentService', 'MilestoneService', 'StageService', 'UserEventListenerService', 'PlanItemInstanceService',\n        function ($rootScope, $scope, $translate, $http, $timeout, $location, $route, $modal, $routeParams, $popover, appResourceRoot, TaskService, CaseService, CommentService, RelatedContentService, MilestoneService, StageService, UserEventListenerService, PlanItemInstanceService) {\n\n            $rootScope.root.showStartForm = false;\n\n            $scope.model = {\n                // Indirect binding between selected task in parent scope to have control over display\n                // before actual selected task is switched\n                caseInstance: $scope.selectedCaseInstance\n            };\n\n\n            $scope.model.contentSummary = {\n                loading: false\n            };\n\n            $scope.$watch('selectedCaseInstance', function (newValue) {\n                if (newValue && newValue.id) {\n                    $scope.model.caseUpdating = true;\n                    $scope.model.caseInstance = newValue;\n\n                    $scope.getCaseInstance(newValue.id);\n                }\n            });\n\n            $scope.getCaseInstance = function (caseInstanceId) {\n                $http({method: 'GET', url: FLOWABLE.CONFIG.contextRoot + '/app/rest/case-instances/' + caseInstanceId}).success(function (response, status, headers, config) {\n                    $scope.model.caseInstance = response;\n                    $scope.loadCaseTasks();\n                    $scope.loadRelatedContent();\n                    $scope.loadCaseInstanceStages();\n                    $scope.loadUserEventListeners();\n                    $scope.loadCaseInstanceMilestones();\n                    $scope.loadEnabledPlanItemInstances();\n                }).error(function (response, status, headers, config) {\n                    console.log('Something went wrong: ' + response);\n                });\n            };\n\n            $scope.loadCaseTasks = function () {\n\n                // Runtime tasks\n                TaskService.getCaseInstanceTasks($scope.model.caseInstance.id, false).then(function (response) {\n                    $scope.model.caseTasks = response.data;\n                });\n\n                TaskService.getCaseInstanceTasks($scope.model.caseInstance.id, true).then(function (response) {\n                    if (response.data && response.data.length > 0) {\n                        $scope.model.completedCaseTasks = response.data;\n                    } else {\n                        $scope.model.completedCaseTasks = [];\n                    }\n\n                    // Calculate duration\n                    for (var i = 0; i < response.data.length; i++) {\n                        var task = response.data[i];\n                        if (task.duration) {\n                            task.duration = moment.duration(task.duration).humanize();\n                        }\n                    }\n                });\n            };\n\n            $scope.loadCaseInstanceStages = function () {\n\n                $scope.model.caseHasStages = false;\n\n                StageService.getCaseInstanceActiveStages($scope.model.caseInstance.id).then(function (response) {\n                    if (response.data && response.data.length > 0) {\n                        $scope.model.caseActiveStages = response.data;\n                        $scope.model.caseHasStages = true;\n                    } else {\n                        $scope.model.caseActiveStages = [];\n                    }\n                });\n\n                StageService.getCaseInstanceEndedStages($scope.model.caseInstance.id).then(function (response) {\n                    if (response.data && response.data.length > 0) {\n                        $scope.model.caseEndedStages = response.data;\n                        $scope.model.caseHasStages = true;\n                    } else {\n                        $scope.model.caseEndedStages = [];\n                    }\n                });\n            };\n\n            $scope.loadCaseInstanceMilestones = function () {\n\n                $scope.model.caseHasMilestones = false;\n\n                MilestoneService.getCaseInstanceAvailableMilestones($scope.model.caseInstance.id).then(function (response) {\n                    if (response.data && response.data.length > 0) {\n                        $scope.model.caseAvailableMilestones = response.data;\n                        $scope.model.caseHasMilestones = true;\n                    } else {\n                        $scope.model.caseAvailableMilestones = [];\n                    }\n                });\n\n                MilestoneService.getCaseInstanceEndedMilestones($scope.model.caseInstance.id).then(function (response) {\n                    if (response.data && response.data.length > 0) {\n                        $scope.model.caseEndedMilestones = response.data;\n                        $scope.model.caseHasMilestones = true;\n                    } else {\n                        $scope.model.caseEndedMilestones = [];\n                    }\n                });\n            };\n\n            $scope.loadUserEventListeners = function () {\n\n                $scope.model.hasUserEventListeners = false;\n\n                UserEventListenerService.getCaseInstanceAvailableUserEventListeners($scope.model.caseInstance.id).then(function (response) {\n                    if (response.data && response.data.length > 0) {\n                        $scope.model.caseAvailableUserEventListeners = response.data;\n                        $scope.model.hasUserEventListeners = true;\n                    } else {\n                        $scope.model.caseAvailableUserEventListeners = [];\n                    }\n                });\n\n                UserEventListenerService.getCaseInstanceCompletedUserEventListeners($scope.model.caseInstance.id).then(function (response) {\n                    if (response.data && response.data.length > 0) {\n                        $scope.model.caseCompletedUserEventListeners = response.data;\n                        $scope.model.hasUserEventListeners = true;\n                    } else {\n                        $scope.model.caseCompletedUserEventListeners = [];\n                    }\n                });\n            };\n\n            $scope.loadEnabledPlanItemInstances = function() {\n\n                $scope.model.hasEnabledPlanItemInstance = false;\n\n                PlanItemInstanceService.getCaseInstanceEnabledPlanItemInstances($scope.model.caseInstance.id).then(function (response) {\n                    if (response.data && response.data.length > 0) {\n                        $scope.model.caseEnabledPlanItemInstances = response.data;\n                        $scope.model.hasEnabledPlanItemInstance = true;\n                    } else {\n                        $scope.model.caseEnabledPlanItemInstances = [];\n                    }\n                });\n\n            };\n\n            $scope.toggleCreateContent = function () {\n                $scope.model.contentSummary.addContent = !$scope.model.contentSummary.addContent;\n            };\n\n            $scope.onContentUploaded = function (content) {\n                if ($scope.model.content && $scope.model.content.data) {\n                    $scope.model.content.data.push(content);\n                    RelatedContentService.addUrlToContent(content);\n                    $scope.model.selectedContent = content;\n                }\n                $rootScope.addAlertPromise($translate('TASK.ALERT.RELATED-CONTENT-ADDED', content), 'info');\n                $scope.toggleCreateContent();\n            };\n\n            $scope.onContentDeleted = function (content) {\n                if ($scope.model.content && $scope.model.content.data) {\n                    $scope.model.content.data.forEach(function (value, i, arr) {\n                        if (content === value) {\n                            arr.splice(i, 1);\n                        }\n                    })\n                }\n            };\n\n            $scope.selectContent = function (content) {\n                if ($scope.model.selectedContent == content) {\n                    $scope.model.selectedContent = undefined;\n                } else {\n                    $scope.model.selectedContent = content;\n                }\n            };\n\n            $scope.loadRelatedContent = function () {\n                $scope.model.content = undefined;\n                CaseService.getRelatedContent($scope.model.caseInstance.id).then(function (data) {\n                    $scope.model.content = data;\n                });\n            };\n\n            $scope.$watch(\"model.content\", function (newValue) {\n                if (newValue && newValue.data && newValue.data.length > 0) {\n                    var needsRefresh = false;\n                    for (var i = 0; i < newValue.data.length; i++) {\n                        var entry = newValue.data[i];\n                        if (!entry.contentAvailable) {\n                            needsRefresh = true;\n                            break;\n                        }\n                    }\n                }\n            }, true);\n\n            $scope.cancelCase = function (final) {\n                if ($scope.model.caseInstance) {\n                    var modalInstance = _internalCreateModal({\n                        template: appResourceRoot + 'views/modal/case-cancel.html',\n                        scope: $scope,\n                        show: true\n                    }, $modal, $scope);\n\n                    if (final) {\n                        modalInstance.$scope.finalDelete = true;\n                    }\n                }\n            };\n\n            $scope.deleteCase = function () {\n                $scope.cancelCase(true);\n            };\n\n            $scope.$on('caseinstance-deleted', function (event, data) {\n                $route.reload();\n            });\n\n            $scope.$on('user-event-listener-triggered', function (event, data) {\n                $route.reload();\n            });\n\n            $scope.openTask = function (task) {\n                $rootScope.root.selectedTaskId = task.id;\n                var path = '';\n                if ($rootScope.activeAppDefinition && !FLOWABLE.CONFIG.integrationProfile) {\n                    path = \"/apps/\" + $rootScope.activeAppDefinition.id;\n                }\n                $location.path(path + \"/tasks\");\n            };\n\n            $scope.triggerUserEventListener = function (userEventListener) {\n                UserEventListenerService.triggerCaseInstanceUserEventListener($scope.model.caseInstance.id, userEventListener.id);\n            };\n\n            $scope.startPlanItemInstance = function (planItemInstance) {\n                PlanItemInstanceService.startPlanItemInstance(planItemInstance.caseInstanceId, planItemInstance.id);\n                $route.reload();\n            };\n\n            $scope.openStartForm = function () {\n                $rootScope.root.showStartForm = true;\n                $rootScope.root.selectedCaseId = $scope.model.caseInstance.id;\n            };\n\n            $scope.popupShown = function () {\n\n            };\n\n            $scope.closeDiagramPopup = function () {\n                jQuery('.qtip').qtip('destroy', true);\n            };\n            \n            $scope.showDiagram = function() {\n                var modalInstance = _internalCreateModal({\n                    template: appResourceRoot + 'views/modal/case-instance-graphical.html',\n                    scope: $scope,\n                    show: true\n                }, $modal, $scope);\n            };\n    }]);\n\nangular.module('flowableApp')\n    .controller('ShowCaseDiagramCtrl', ['$scope', '$timeout', '$q', 'ResourceService', 'appResourceRoot',\n        function ($scope, $timeout, $q, ResourceService, appResourceRoot) {\n\n            $timeout(function () {\n                jQuery(\"#cmmnModel\").attr('data-model-id', $scope.model.caseInstance.id);\n                jQuery(\"#cmmnModel\").attr('data-model-type', 'runtime');\n\n                // in case we want to show a historic model, include additional attribute on the div\n                if ($scope.model.caseInstance.ended) {\n                    jQuery(\"#cmmnModel\").attr('data-history-id', $scope.model.caseInstance.id);\n                }\n\n                var viewerUrl = appResourceRoot + \"../display-cmmn/displaymodel.html?version=\" + Date.now();\n\n                // If Flowable has been deployed inside an AMD environment Raphael will fail to register\n                // itself globally until displaymodel.js (which depends ona global Raphale variable) is running,\n                // therefore remove AMD's define method until we have loaded in Raphael and displaymodel.js\n                // and assume/hope its not used during.\n                var amdDefine = window.define;\n                window.define = undefined;\n                ResourceService.loadFromHtml(viewerUrl, function () {\n                    // Restore AMD's define method again\n                    window.define = amdDefine;\n                });\n            }, 100);\n        }\n        ]\n    );\n\nangular.module('flowableApp')\n    .controller('CancelCaseCtrl', ['$scope', '$http', '$route', 'CaseService', function ($scope, $http, $route, CaseService) {\n\n        $scope.popup = {loading: false};\n\n        $scope.ok = function () {\n            $scope.popup.loading = true;\n\n            CaseService.deleteCase($scope.model.caseInstance.id).then(function (response, status, headers, config) {\n                $scope.$hide();\n            }).finally(function (response, status, headers, config) {\n                $scope.popup.loading = false;\n            })\n        };\n\n        $scope.cancel = function () {\n            $scope.$hide();\n        }\n    }\n    ]);\n"
  },
  {
    "path": "flowable-ui-web/task/workflow/scripts/controllers/cases.js",
    "content": "/* 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'use strict';\n\nangular.module('flowableApp')\n    .controller('CasesController', ['$rootScope', '$scope', '$translate', '$http', '$timeout', '$location', '$modal', '$routeParams', '$popover', 'appResourceRoot', 'AppDefinitionService', 'CaseService',\n        function ($rootScope, $scope, $translate, $http, $timeout, $location, $modal, $routeParams, $popover, appResourceRoot, AppDefinitionService, CaseService) {\n\n        var caseId = $routeParams.caseId;\n\n        // Ensure correct main page is set\n        $rootScope.setMainPageById('cases');\n\n        // Initialize model\n        $scope.model = {\n            page: 0,\n            initialLoad: false,\n            mode: 'case-list'\n        };\n\n        $scope.model.contentSummary = {\n            loading: false\n        };\n\n         $scope.model.runtimeSorts = [\n            { 'id': 'created-desc', 'title': 'CASE.FILTER.CREATED-DESC'},\n            { 'id': 'created-asc', 'title': 'CASE.FILTER.CREATED-ASC' }\n        ];\n\n        $scope.model.completedSorts = [];\n        $scope.model.completedSorts.push($scope.model.runtimeSorts[0]); // needs to be same reference!\n        $scope.model.completedSorts.push($scope.model.runtimeSorts[1]); // needs to be same reference!\n        $scope.model.completedSorts.push({ 'id': 'ended-asc', 'title': 'CASE.FILTER.ENDED-DESC' });\n        $scope.model.completedSorts.push({ 'id': 'ended-desc', 'title': 'CASE.FILTER.ENDED-ASC' });\n\n        $scope.model.sorts = $scope.model.runtimeSorts;\n\n        $scope.model.stateFilterOptions = [\n            { 'id': 'running', 'title': 'CASE.FILTER.STATE-RUNNING' },\n            { 'id': 'completed', 'title': 'CASE.FILTER.STATE-COMPLETED' },\n            { 'id': 'all', 'title': 'CASE.FILTER.STATE-ALL' }\n        ];\n\n        $scope.model.filter = {\n            loading: false,\n            expanded: false,\n            param: {\n                state: $scope.model.stateFilterOptions[0],\n                sort: $scope.model.sorts[0].id\n            }\n        };\n\n        $scope.appDefinitionKey = $routeParams.appDefinitionKey;\n        $scope.missingAppdefinition = $scope.appDefinitionKey === false;\n\n        // In case of viewing case instances in an app-context, need to make filter aware of this\n        $scope.model.filter.param.appDefinitionKey = $scope.appDefinitionKey;\n\n        // The filter is stored on the rootScope, which allows the user to switch back and forth without losing the filter.\n        if ($rootScope.caseFilter !== null && $rootScope.caseFilter !== undefined) {\n            $scope.model.filter.param = $rootScope.caseFilter.param;\n        } else {\n            $rootScope.caseFilter = { param: $scope.model.filter.param }\n        }\n\n        // Update app on rootScope. If app id present, it will fetch definition if not already fetched to update view and navigation accordingly\n        AppDefinitionService.setActiveAppDefinitionKey($scope.appDefinitionKey);\n\n        $scope.selectCaseInstance = function (caseInstance) {\n            $scope.selectedCaseInstance = caseInstance;\n            $scope.state = {noCases:false};\n        };\n\n        $scope.expandFilter = function () {\n            $scope.model.filter.expanded = true;\n        };\n\n        $scope.collapseFilter = function () {\n            $scope.model.filter.expanded = false;\n        };\n\n        $scope.$watch(\"model.filter.param\", function (newValue) {\n            if (newValue) {\n                if ($scope.model.initialLoad) {\n                    $scope.loadCaseInstances();\n                }\n\n                if (newValue.state.id === 'completed' || newValue.state.id === 'all') {\n                    $scope.model.sorts = $scope.model.completedSorts;\n                } else {\n                    $scope.model.sorts = $scope.model.runtimeSorts;\n                    if (newValue.sort === 'ended-asc' || newValue.sort === 'ended-desc') {\n                        $scope.model.filter.param.sort = $scope.model.sorts[0].id;\n                    }\n                }\n            }\n        }, true);\n\n        $scope.nextPage = function () {\n            $scope.loadCaseInstances(true);\n        };\n\n        // TODO: move to service\n        $scope.loadCaseInstances = function (nextPage) {\n\n            $scope.model.filter.loading = true;\n\n            var params = $scope.model.filter.param;\n\n            if (nextPage) {\n                $scope.model.page += 1;\n            } else {\n                $scope.model.page = 0;\n            }\n\n            var instanceQueryData = {\n                sort: params.sort,\n                page: $scope.model.page\n            };\n\n            if (params.appDefinitionKey) {\n                instanceQueryData.appDefinitionKey = params.appDefinitionKey;\n            }\n\n            if (params.state) {\n                instanceQueryData.state = params.state.id;\n            }\n\n\n            $http({method: 'POST', url: FLOWABLE.CONFIG.contextRoot + '/app/rest/query/case-instances', data: instanceQueryData}).\n                success(function (response, status, headers, config) {\n                    $scope.model.initialLoad = true;\n                    var instances = response.data;\n\n                    if (response.start > 0) {\n                        // Add results instead of removing existing ones\n                        for (var i = 0; i < instances.length; i++) {\n                            $scope.model.caseInstances.push(instances[i]);\n                        }\n\n                        $scope.state = {noCases: false};\n                    } else {\n                        $scope.model.caseInstances = instances;\n                        $scope.state = {noCases: (!response.data || response.data.length == 0)};\n                    }\n\n                    if (response.start + response.size < response.total) {\n                        // More pages available\n                        $scope.model.hasNextPage = true;\n                    } else {\n                        $scope.model.hasNextPage = false;\n                    }\n\n                    var isSelected = false;\n\n                    if ($rootScope.root.selectedCaseId) {\n                        for (var i = 0; i < instances.length; i++) {\n                            if (instances[i].id == $rootScope.root.selectedCaseId) {\n                                isSelected = true;\n                                $scope.selectedCaseInstance = instances[i];\n                                break;\n                            }\n                        }\n                        $rootScope.root.selectedCaseId = undefined;\n                    }\n                    if (!isSelected && instances.length > 0) {\n                        if (!$scope.selectedCaseInstance) {\n                            $scope.selectedCaseInstance = instances[0];\n                        }\n                    }\n\n                    // If there is a new case instance, we want it to be selected\n                    if ($scope.newCaseInstance !== null && $scope.newCaseInstance !== undefined) {\n                        if ($scope.newCaseInstance.id !== null && $scope.newCaseInstance.id !== undefined) {\n                            for (var instanceIndex = 0; instanceIndex < $scope.model.caseInstances.length; instanceIndex++) {\n                                if ($scope.model.caseInstances[instanceIndex].id === $scope.newCaseInstance.id) {\n                                    $scope.selectedCaseInstance = $scope.model.caseInstances[instanceIndex];\n                                    break;\n                                }\n                            }\n                        }\n                       // Always reset when loading case instance\n                        $scope.newCaseInstance = undefined;\n                    }\n\n                    $scope.model.filter.loading = false;\n                    $rootScope.window.forceRefresh = true;\n                }).\n                error(function (response, status, headers, config) {\n                    console.log('Something went wrong: ' + response);\n                });\n        };\n\n            $scope.selectCaseDefinition = function (definition) {\n            $scope.newCaseInstance.caseDefinitionId = definition.id;\n            $scope.newCaseInstance.name = definition.name + ' - ' + new moment().format('MMMM Do YYYY');\n            $scope.newCaseInstance.caseDefinition = definition;\n\n            $timeout(function () {\n                angular.element('#start-case-name').focus();\n            }, 20);\n        };\n\n            $scope.dragOverContent = function (over) {\n                if (over && !$scope.model.contentSummary.addContent) {\n                    $scope.model.contentSummary.addContent = true;\n                }\n            };\n\n            $scope.toggleCreateContent = function () {\n                $scope.model.contentSummary.addContent = !$scope.model.contentSummary.addContent;\n            };\n\n            $scope.onContentUploaded = function (content) {\n                if ($scope.model.content && $scope.model.content.data) {\n                    $scope.model.content.data.push(content);\n                    RelatedContentService.addUrlToContent(content);\n                    $scope.model.selectedContent = content;\n                }\n                $rootScope.addAlertPromise($translate('TASK.ALERT.RELATED-CONTENT-ADDED', content), 'info');\n                $scope.toggleCreateContent();\n            };\n\n            $scope.onContentDeleted = function (content) {\n                if ($scope.model.content && $scope.model.content.data) {\n                    $scope.model.content.data.forEach(function (value, i, arr) {\n                        if (content === value) {\n                            arr.splice(i, 1);\n                        }\n                    })\n                }\n            };\n\n            $scope.selectContent = function (content) {\n                if ($scope.model.selectedContent == content) {\n                    $scope.model.selectedContent = undefined;\n                } else {\n                    $scope.model.selectedContent = content;\n                }\n            };\n\n            $scope.selectStateFilter = function (state) {\n            if (state != $scope.model.filter.param.state) {\n                $scope.model.filter.param.state = state;\n                $scope.collapseFilter();\n                $scope.selectedCaseInstance = undefined;\n            }\n        };\n\n        $scope.sortChanged = function() {\n            $scope.selectedCaseInstance = undefined;\n        };\n\n        $scope.selectDefaultDefinition = function() {\n            // Select first non-default definition, if any\n            CaseService.getCaseDefinitions($scope.appDefinitionKey).then(function(response) {\n            \t$rootScope.root.caseDefinitions = response.data;\n\t            if ($scope.root.caseDefinitions && $scope.root.caseDefinitions.length > 0) {\n\t                for (var i=0; i< $scope.root.caseDefinitions.length; i++) {\n\t                    var def = $scope.root.caseDefinitions[i];\n\t                    if (def.id != 'default') {\n\t                        $scope.selectCaseDefinition(def);\n\t                        break;\n\t                    }\n\t                }\n\t            }\n\t        });\n\n        };\n\n        $scope.backToList = function(reloadCaseInstances) {\n\n            $scope.newCaseInstance = undefined;\n\n            $scope.model.mode = 'case-list';\n            $scope.startFormError = undefined;\n\n            // If param is true: reload, no questions asked\n            if (reloadCaseInstances) {\n\n                // Reset selection\n                $scope.selectedCaseInstance = undefined;\n\n                // Reset filters\n                $scope.model.filter.param.state = $scope.model.stateFilterOptions[0];\n                $scope.model.filter.param.sort = $scope.model.sorts[0].id;\n\n                $scope.loadCaseInstances();\n            }\n\n            // In case we're coming from the task page, no case instances have been loaded\n            if ($scope.model.caseInstances === null || $scope.model.caseInstances === undefined) {\n                $scope.loadCaseInstances();\n            }\n\n        };\n\n        $scope.createCaseInstance = function () {\n\n            // Reset state\n            $rootScope.root.showStartForm = false;\n\n            $scope.model.mode = 'case-create';\n            $scope.newCaseInstance = {};\n            $scope.selectDefaultDefinition();\n        };\n\n\n        // Called after form is submitted\n        $scope.$on('case-started', function (event, data) {\n            $scope.newCaseInstance.id = data.id;\n            $scope.backToList(true);\n        });\n\n        $scope.startCaseInstanceWithoutForm = function() {\n            $scope.newCaseInstance.loading = true;\n            var createInstanceData = {caseDefinitionId: $scope.newCaseInstance.caseDefinition.id, name: $scope.newCaseInstance.name};\n            $http({method: 'POST', url: FLOWABLE.CONFIG.contextRoot + '/app/rest/case-instances', data: createInstanceData}).\n                success(function (response, status, headers, config) {\n                    $scope.newCaseInstance.id = response.id;\n                    $scope.newCaseInstance.loading = false;\n                    $scope.backToList(true);\n\n                }).\n                error(function (response, status, headers, config) {\n                    $scope.newCaseInstance.loading = false;\n\n                    if(response && response.messageKey) {\n                        $translate(response.messageKey, response.customData).then(function(message) {\n                            $scope.errorMessage = message;\n                            console.log(message);\n                        });\n                    }\n                });\n        };\n\n        $rootScope.loadCaseDefinitions($scope.appDefinitionKey);\n\n        // If 'createCaseInstance' is set (eg from the task page)\n        if ($rootScope.createCaseInstance) {\n            $rootScope.createCaseInstance = false;\n            $scope.createCaseInstance();\n        } else {\n            $scope.loadCaseInstances();\n        }\n\n    }]);\n"
  },
  {
    "path": "flowable-ui-web/task/workflow/scripts/controllers/document-preview.js",
    "content": "/* 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'use strict';\n\nangular.module('flowableApp')\n    .controller('DocumentPreviewController', ['$rootScope', '$scope', '$modal', 'appResourceRoot', 'RelatedContentService',\n        function ($rootScope, $scope, $modal, appResourceRoot, RelatedContentService) {\n\n            RelatedContentService.addUrlToContent($scope.content);\n\n            $scope.deleteContent = function(content, task) {\n                var modalInstance = _internalCreateModal({\n                    template: appResourceRoot + 'views/modal/delete-content.html',\n                    show: true\n                }, $modal, $scope);\n\n                modalInstance.$scope.popup = {\n                    content: content,\n                    loading: false\n                };\n\n                modalInstance.$scope.ok = function() {\n                    RelatedContentService.deleteContent(content.id, task && task.id).then(function() {\n                        $scope.deleted({ content: content });\n                        $scope.content = null;\n                    });\n                };\n            };\n\n        }\n    ]\n);\n"
  },
  {
    "path": "flowable-ui-web/task/workflow/scripts/controllers/process.js",
    "content": "/* 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'use strict';\n\nangular.module('flowableApp')\n  .controller('ProcessController', ['$rootScope', '$scope', '$translate', '$http', '$timeout', '$location', '$modal', '$routeParams', 'AppDefinitionService',\n    function ($rootScope, $scope, $translate, $http, $timeout, $location, $modal, $routeParams, AppDefinitionService) {\n\n      // Ensure correct main page is set\n      $rootScope.setMainPageById('processes');\n\n      $scope.selectedProcessInstance = { id: $routeParams.processId };\n\n        $scope.appDefinitionKey = $routeParams.appDefinitionKey;\n\n        $scope.$on('processinstance-deleted', function (event, data) {\n            $scope.openProcesses();\n        });\n\n        $scope.openProcesses = function(task) {\n            var path='';\n            if($rootScope.activeAppDefinition && !FLOWABLE.CONFIG.integrationProfile) {\n                path = \"/apps/\" + $rootScope.activeAppDefinition.id;\n            }\n            $location.path(path + \"/processes\");\n        };\n}]);\n\nangular.module('flowableApp')\n    .controller('ProcessDetailController', ['$rootScope', '$scope', '$translate', '$http', '$timeout','$location', '$route', '$modal', '$routeParams', '$popover', 'appResourceRoot', 'TaskService', 'CommentService', 'RelatedContentService',\n        function ($rootScope, $scope, $translate, $http, $timeout, $location, $route, $modal, $routeParams, $popover, appResourceRoot, TaskService, CommentService, RelatedContentService) {\n\n    $rootScope.root.showStartForm = false;\n\n    $scope.model = {\n        // Indirect binding between selected task in parent scope to have control over display\n        // before actual selected task is switched\n        processInstance: $scope.selectedProcessInstance\n    };\n\n    $scope.$watch('selectedProcessInstance', function(newValue) {\n        if (newValue && newValue.id) {\n            $scope.model.processUpdating = true;\n            $scope.model.processInstance = newValue;\n\n            $scope.getProcessInstance(newValue.id);\n        }\n    });\n\n    $scope.getProcessInstance = function(processInstanceId) {\n        $http({method: 'GET', url: FLOWABLE.CONFIG.contextRoot + '/app/rest/process-instances/' + processInstanceId}).\n            success(function(response, status, headers, config) {\n                $scope.model.processInstance = response;\n                $scope.loadProcessTasks();\n                $scope.loadComments();\n            }).\n            error(function(response, status, headers, config) {\n                console.log('Something went wrong: ' + response);\n            });\n    };\n\n    $rootScope.loadProcessTasks = function() {\n\n        // Runtime tasks\n        TaskService.getProcessInstanceTasks($scope.model.processInstance.id, false).then(function(response) {\n            $scope.model.processTasks = response.data;\n        });\n\n        TaskService.getProcessInstanceTasks($scope.model.processInstance.id, true).then(function(response) {\n            if(response.data && response.data.length > 0) {\n                $scope.model.completedProcessTasks = response.data;\n            } else {\n                $scope.model.completedProcessTasks = [];\n            }\n\n            // Calculate duration\n            for(var i=0; i<response.data.length; i++) {\n                var task = response.data[i];\n                if(task.duration) {\n                    task.duration = moment.duration(task.duration).humanize();\n                }\n            }\n        });\n    };\n\n    $scope.toggleCreateComment = function() {\n\n        $scope.model.addComment = !$scope.model.addComment;\n\n        if($scope.model.addComment) {\n            $timeout(function() {\n                angular.element('.focusable').focus();\n            }, 100);\n        }\n    };\n\n    $scope.cancelProcess = function(final) {\n        if ($scope.model.processInstance) {\n            var modalInstance = _internalCreateModal({\n                template: appResourceRoot + 'views/modal/process-cancel.html',\n                scope: $scope,\n                show: true\n            }, $modal, $scope);\n\n            if(final) {\n                modalInstance.$scope.finalDelete = true;\n            }\n        }\n    };\n\n    $scope.deleteProcess = function() {\n        $scope.cancelProcess(true);\n    };\n\n    $scope.$on('processinstance-deleted', function (event, data) {\n        $route.reload();\n    });\n\n    $scope.openTask = function(task) {\n        // TODO: use URL instead\n        $rootScope.root.selectedTaskId = task.id;\n        var path='';\n        if($rootScope.activeAppDefinition && !FLOWABLE.CONFIG.integrationProfile) {\n            path = \"/apps/\" + $rootScope.activeAppDefinition.id;\n        }\n        $location.path(path + \"/tasks\");\n    };\n\n    $scope.openStartForm = function() {\n        $rootScope.root.showStartForm = true;\n        $rootScope.root.selectedProcessId = $scope.model.processInstance.id;\n    };\n\n    $scope.popupShown = function() {\n\n    };\n\n    $scope.closeDiagramPopup = function() {\n        jQuery('.qtip').qtip('destroy', true);\n    };\n\n    $scope.loadComments = function() {\n        CommentService.getProcessInstanceComments($scope.model.processInstance.id).then(function (data) {\n            $scope.model.comments = data;\n        });\n    };\n\n    $scope.confirmNewComment = function() {\n        $scope.model.commentLoading = true;\n\n        CommentService.createProcessInstanceComment($scope.model.processInstance.id, $scope.model.newComment.trim())\n            .then(function(comment) {\n                $scope.model.newComment = undefined;\n                $scope.model.commentLoading = false;\n                $rootScope.addAlertPromise($translate('PROCESS.ALERT.COMMENT-ADDED'));\n\n                $scope.toggleCreateComment();\n\n\n                $scope.loadComments();\n            });\n    };\n\n    $scope.showDiagram = function() {\n        var modalInstance = _internalCreateModal({\n            template: appResourceRoot + 'views/modal/process-instance-graphical.html',\n            scope: $scope,\n            show: true\n        }, $modal, $scope);\n\n    };\n}]);\n\nangular.module('flowableApp')\n    .controller('ShowProcessDiagramCtrl', ['$scope', '$http', '$interval', '$timeout', '$translate', '$q', 'ResourceService', 'appResourceRoot', '$rootScope',\n        function ($scope, $http, $interval, $timeout, $translate, $q, ResourceService, appResourceRoot, $rootScope) {\n\n            $scope.model.isDebuggerEnabled = false;\n            $scope.model.scriptLanguage = 'groovy';\n\n            $http({\n                method: 'GET',\n                url: '../app/rest/debugger/',\n                async: false\n            }).success(function (data) {\n                $scope.model.isDebuggerEnabled = data;\n                $scope.getExecutions();\n                $scope.getEventLog();\n                $scope.getProcessVariables();\n            });\n\n            $scope.model.variables = [];\n            $scope.model.executions = undefined;\n            $scope.model.selectedExecution = $scope.model.processInstance.id;\n            $scope.model.displayVariables = true;\n\n            $scope.model.errorMessage = '';\n\n            // config for executions grid\n            $scope.gridExecutions = {\n                data: $scope.model.executions,\n                columnDefs: [\n                    {field: 'id', displayName: \"Id\", name: 'id', maxWidth: 10},\n                    {field: 'parentId', displayName: \"Parent id\", name: 'parentId', maxWidth: 10},\n                    {\n                        field: 'processInstanceId',\n                        displayName: \"Process id\",\n                        name: 'processInstanceId',\n                        maxWidth: 90\n                    },\n                    {\n                        field: 'superExecutionId',\n                        displayName: \"Super execution id\",\n                        name: 'superExecutionId',\n                        maxWidth: 90\n                    },\n                    {field: 'activityId', displayName: \"Activity\", name: 'activityId', maxWidth: 90},\n                    {field: 'suspended', displayName: \"Suspended\", name: 'suspended', maxWidth: 90},\n                    {field: 'tenantId', displayName: \"Tenant id\", name: 'tenantId', maxWidth: 90}\n                ],\n                enableRowSelection: true,\n                multiSelect: false,\n                noUnselect: true,\n                enableRowHeaderSelection: false,\n                onRegisterApi: function (gridApi) {\n                    $scope.gridExecutionsApi = gridApi;\n                    $scope.gridExecutionsApi.grid.modifyRows($scope.gridExecutions.data);\n                    if ($scope.gridExecutions.data) {\n                        for (var i = 0; i < $scope.gridExecutions.data.length; i++) {\n                            if ($scope.model.selectedExecution == $scope.gridExecutions.data[i].id) {\n                                $scope.gridExecutionsApi.selection.selectRow($scope.gridExecutions.data[i]);\n                                i = $scope.gridExecutions.data.length;\n                            }\n                        }\n                    }\n                    $scope.gridExecutionsApi.selection.on.rowSelectionChanged($scope, function (row) {\n                        var activityToUnselect = modelDiv.attr(\"selected-activity\");\n                        if (activityToUnselect) {\n                            var rectangleToUnselect = paper.getById(activityToUnselect);\n                            if (rectangleToUnselect) {\n                                rectangleToUnselect.attr({\"stroke\": \"green\"});\n                            }\n                        }\n                        modelDiv.attr(\"selected-execution\", row.entity.id);\n                        $scope.model.selectedExecution = row.entity.id;\n                        modelDiv.attr(\"selected-activity\", row.entity.activityId);\n                        if (row.entity.activityId) {\n                            var paperActivity = paper.getById(row.entity.activityId);\n                            if (paperActivity) {\n                                paperActivity.attr({\"stroke\": \"red\"});\n                            }\n                        }\n\n                        $scope.loadVariables();\n                    });\n                }\n            };\n\n            $scope.getExecutions = function () {\n                if ($scope.model.isDebuggerEnabled) {\n                    $http({\n                        method: 'GET',\n                        url: '../app/rest/debugger/executions/' + $scope.model.processInstance.id\n                    }).success(function (data) {\n                        $scope.model.executions = data;\n                        $scope.gridExecutions.data = data;\n                        if ($scope.gridExecutionsApi) {\n                            $scope.gridExecutionsApi.grid.modifyRows($scope.gridExecutions.data);\n                            for (var i = 0; i < $scope.gridExecutions.data.length; i++) {\n                                if ($scope.model.selectedExecution == $scope.gridExecutions.data[i].id) {\n                                    $scope.gridExecutionsApi.selection.selectRow($scope.gridExecutions.data[i]);\n                                    i = $scope.gridExecutions.data.length;\n                                }\n                            }\n                        }\n                        jQuery(\"#bpmnModel\").data($scope.model.executions);\n                    }).error(function (data, status, headers, config) {\n                        $scope.model.errorMessage = data;\n                    });\n                }\n            }\n\n            $scope.getProcessVariables = function () {\n                if ($scope.model.isDebuggerEnabled) {\n                    $http({\n                        method: 'GET',\n                        url: '../app/rest/debugger/variables/' + $scope.model.processInstance.id\n                    }).success(function (data) {\n                        $scope.gridVariables.data = data;\n                        if ($scope.gridVariablesApi) {\n                            $scope.gridVariablesApi.core.refresh();\n                        }\n                    });\n                }\n            }\n\n            $scope.getEventLog = function () {\n                if ($scope.model.isDebuggerEnabled) {\n                    $http({\n                        method: 'GET',\n                        url: '../app/rest/debugger/eventlog/' + $scope.model.processInstance.id\n                    }).success(function (data) {\n                        $scope.gridLog.data = data;\n                        if ($scope.gridLogApi) {\n                            $scope.gridLogApi.core.refresh();\n                        }\n                    });\n                }\n            }\n\n            $scope.tabData = {\n                tabs: [\n                    {id: 'variables', name: 'PROCESS.TITLE.VARIABLES'},\n                    {id: 'executions', name: 'PROCESS.TITLE.EXECUTIONS'},\n                    {id: 'log', name: 'PROCESS.TITLE.LOG'}\n                ],\n                activeTab: 'variables'\n            };\n\n            if (!$scope.model.processInstance.ended) {\n                $scope.tabData.tabs.push(\n                    {id: 'expression', name: 'PROCESS.TITLE.EXPRESSION'}\n                    );\n                $scope.tabData.tabs.push(\n                    {id: 'script', name: 'PROCESS.TITLE.SCRIPT'}\n                    );\n            }\n\n            $scope.loadVariables = function () {\n                if ($scope.model.isDebuggerEnabled) {\n                    $http({\n                        method: 'GET',\n                        url: '../app/rest/debugger/variables/' + jQuery(\"#bpmnModel\").attr(\"selected-execution\")\n                    }).success(function (data, status, headers, config) {\n                        $scope.model.variables = data;\n                        $scope.gridVariables.data = data;\n                        if ($scope.gridVariablesApi) {\n                            $scope.gridVariablesApi.core.refresh();\n                        }\n                    });\n                }\n            };\n\n            $scope.executionSelected = function () {\n                jQuery(\"#bpmnModel\").attr(\"selectedElement\", $scope.model.selectedExecution.activityId);\n                $scope.loadVariables();\n            }\n\n            // Config for variable grid\n            $scope.gridVariables = {\n                data: $scope.model.variables,\n                columnDefs: [\n                    {field: 'processId', displayName: \"Process\", maxWidth: 10},\n                    {field: 'executionId', displayName: \"Execution\", maxWidth: 10},\n                    {field: 'taskId', displayName: \"Task\", maxWidth: 10},\n                    {field: 'type', displayName: \"Type\", maxWidth: 10},\n                    {field: 'name', displayName: \"Name\", maxWidth: 10},\n                    {\n                        field: 'value', displayName: \"Value\",\n                        cellTemplate: '<div><div style=\"text-align: left\" class=\"ngCellText\">{{grid.getCellValue(row, col)}}</div></div>'\n                    }\n                ],\n                onRegisterApi: function (gridApi) {\n                    $scope.gridVariablesApi = gridApi;\n                }\n            };\n\n            // Config for variable grid\n            $scope.gridLog = {\n                columnDefs: [\n                    {field: 'id', displayName: \"Id\", maxWidth: 10},\n                    {field: 'type', displayName: \"Type\", maxWidth: 10},\n                    {field: 'timeStamp', displayName: \"Time Stamp\", maxWidth: 90},\n                    {field: 'executionId', displayName: \"Execution\", maxWidth: 90},\n                    {field: 'taskId', displayName: \"Task id\", maxWidth: 90}\n                ],\n                enableRowSelection: true,\n                multiSelect: false,\n                noUnselect: true,\n                enableRowHeaderSelection: false,\n                onRegisterApi: function (gridApi) {\n                    $scope.gridLogApi = gridApi;\n                }\n            };\n\n            $scope.evaluateExpression = function () {\n                if ($scope.model.isDebuggerEnabled) {\n                    $scope.model.errorMessage = '';\n                    $scope.model.result = '';\n\n                    var selExecution = jQuery(\"#bpmnModel\").attr(\"selected-execution\");\n                    if (!selExecution) {\n                        selExecution = $scope.model.processInstance.id;\n                    }\n                    $http({\n                        method: 'POST',\n                        url: '../app/rest/debugger/evaluate/expression/' + selExecution,\n                        data: $scope.model.expression\n                    }).success(function (data) {\n                        $scope.model.result = data;\n                    }).error(function (data, status, headers, config) {\n                        $rootScope.addAlert(\"Execution evaluation failed :\" + data, 'error');\n                    });\n                }\n            }\n\n            $scope.evaluateScript = function () {\n                if ($scope.model.isDebuggerEnabled) {\n                    $scope.model.errorMessage = '';\n\n                    var selExecution = jQuery(\"#bpmnModel\").attr(\"selected-execution\");\n                    if (!selExecution) {\n                        selExecution = $scope.model.processInstance.id;\n                    }\n                    $http({\n                        method: 'POST',\n                        url: '../app/rest/debugger/evaluate/' + $scope.model.scriptLanguage + '/' + selExecution,\n                        data: $scope.model.scriptText\n                    }).success(function (data) {\n                        $rootScope.addAlert(\"script executed\", 'info')\n                    }).error(function (data, status, headers, config) {\n                        $rootScope.addAlert(data, 'error');\n                    });\n                }\n            }\n\n            $timeout(function () {\n                jQuery(\"#bpmnModel\").attr('data-model-id', $scope.model.processInstance.id);\n                jQuery(\"#bpmnModel\").attr('data-model-type', 'runtime');\n\n                // in case we want to show a historic model, include additional attribute on the div\n                if ($scope.model.processInstance.ended) {\n                    jQuery(\"#bpmnModel\").attr('data-history-id', $scope.model.processInstance.id);\n                }\n\n                var viewerUrl = appResourceRoot + \"../display/displaymodel.html?version=\" + Date.now();\n\n                // If Flowable has been deployed inside an AMD environment Raphael will fail to register\n                // itself globally until displaymodel.js (which depends ona global Raphale variable) is running,\n                // therefore remove AMD's define method until we have loaded in Raphael and displaymodel.js\n                // and assume/hope its not used during.\n                var amdDefine = window.define;\n                window.define = undefined;\n                ResourceService.loadFromHtml(viewerUrl, function () {\n                    // Restore AMD's define method again\n                    window.define = amdDefine;\n                });\n            }, 100);\n        }\n        ]\n    );\n\nangular.module('flowableApp')\n.controller('CancelProcessCtrl', ['$scope', '$http', '$route', 'ProcessService', function ($scope, $http, $route, ProcessService) {\n\n        $scope.popup = {loading: false};\n\n        $scope.ok = function() {\n            $scope.popup.loading = true;\n\n            ProcessService.deleteProcess($scope.model.processInstance.id).\n                then(function(response, status, headers, config) {\n                    $scope.$hide();\n                }).\n                finally(function(response, status, headers, config) {\n                    $scope.popup.loading = false;\n                })\n        };\n\n        $scope.cancel = function() {\n            $scope.$hide();\n        }\n    }\n]);\n"
  },
  {
    "path": "flowable-ui-web/task/workflow/scripts/controllers/processes.js",
    "content": "/* 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'use strict';\n\nangular.module('flowableApp')\n    .controller('ProcessesController', ['$rootScope', '$scope', '$translate', '$http', '$timeout', '$location', '$modal', '$routeParams', '$popover', 'appResourceRoot', 'AppDefinitionService', 'ProcessService',\n        function ($rootScope, $scope, $translate, $http, $timeout, $location, $modal, $routeParams, $popover, appResourceRoot, AppDefinitionService, ProcessService) {\n\n        var processId = $routeParams.processId;\n\n        // Ensure correct main page is set\n        $rootScope.setMainPageById('processes');\n\n        // Initialize model\n        $scope.model = {\n            page: 0,\n            initialLoad: false,\n            mode: 'process-list'\n        };\n\n        $scope.model.runtimeSorts = [\n            { 'id': 'created-desc', 'title': 'PROCESS.FILTER.CREATED-DESC'},\n            { 'id': 'created-asc', 'title': 'PROCESS.FILTER.CREATED-ASC' }\n        ];\n\n        $scope.model.completedSorts = [];\n        $scope.model.completedSorts.push($scope.model.runtimeSorts[0]); // needs to be same reference!\n        $scope.model.completedSorts.push($scope.model.runtimeSorts[1]); // needs to be same reference!\n        $scope.model.completedSorts.push({ 'id': 'ended-asc', 'title': 'PROCESS.FILTER.ENDED-DESC' });\n        $scope.model.completedSorts.push({ 'id': 'ended-desc', 'title': 'PROCESS.FILTER.ENDED-ASC' });\n\n        $scope.model.sorts = $scope.model.runtimeSorts;\n\n        $scope.model.stateFilterOptions = [\n            { 'id': 'running', 'title': 'PROCESS.FILTER.STATE-RUNNING' },\n            { 'id': 'completed', 'title': 'PROCESS.FILTER.STATE-COMPLETED' },\n            { 'id': 'all', 'title': 'PROCESS.FILTER.STATE-ALL' }\n        ];\n\n        $scope.model.filter = {\n            loading: false,\n            expanded: false,\n            param: {\n                state: $scope.model.stateFilterOptions[0],\n                sort: $scope.model.sorts[0].id\n            }\n        };\n\n        $scope.appDefinitionKey = $routeParams.appDefinitionKey;\n        $scope.missingAppdefinition = $scope.appDefinitionKey === false;\n\n        // In case of viewing process instances in an app-context, need to make filter aware of this\n        $scope.model.filter.param.appDefinitionKey = $scope.appDefinitionKey;\n\n        // The filter is stored on the rootScope, which allows the user to switch back and forth without losing the filter.\n        if ($rootScope.processFilter !== null && $rootScope.processFilter !== undefined) {\n            $scope.model.filter.param = $rootScope.processFilter.param;\n        } else {\n            $rootScope.processFilter = { param: $scope.model.filter.param }\n        }\n\n        // Update app on rootScope. If app id present, it will fetch definition if not already fetched to update view and navigation accordingly\n        AppDefinitionService.setActiveAppDefinitionKey($scope.appDefinitionKey);\n\n        $scope.selectProcessInstance = function (processInstance) {\n            $scope.selectedProcessInstance = processInstance;\n            $scope.state = {noProcesses:false};\n        };\n\n        $scope.expandFilter = function () {\n            $scope.model.filter.expanded = true;\n        };\n\n        $scope.collapseFilter = function () {\n            $scope.model.filter.expanded = false;\n        };\n\n        $scope.$watch(\"model.filter.param\", function (newValue) {\n            if (newValue) {\n                if ($scope.model.initialLoad) {\n                    $scope.loadProcessInstances();\n                }\n\n                if (newValue.state.id === 'completed' || newValue.state.id === 'all') {\n                    $scope.model.sorts = $scope.model.completedSorts;\n                } else {\n                    $scope.model.sorts = $scope.model.runtimeSorts;\n                    if (newValue.sort === 'ended-asc' || newValue.sort === 'ended-desc') {\n                        $scope.model.filter.param.sort = $scope.model.sorts[0].id;\n                    }\n                }\n            }\n        }, true);\n\n        $scope.nextPage = function () {\n            $scope.loadProcessInstances(true);\n        };\n\n        // TODO: move to service\n        $scope.loadProcessInstances = function (nextPage) {\n\n            $scope.model.filter.loading = true;\n\n            var params = $scope.model.filter.param;\n\n            if (nextPage) {\n                $scope.model.page += 1;\n            } else {\n                $scope.model.page = 0;\n            }\n\n            var instanceQueryData = {\n                sort: params.sort,\n                page: $scope.model.page\n            };\n\n            if (params.appDefinitionKey) {\n                instanceQueryData.appDefinitionKey = params.appDefinitionKey;\n            }\n\n            if (params.state) {\n                instanceQueryData.state = params.state.id;\n            }\n\n\n            $http({method: 'POST', url: FLOWABLE.CONFIG.contextRoot + '/app/rest/query/process-instances', data: instanceQueryData}).\n                success(function (response, status, headers, config) {\n                    $scope.model.initialLoad = true;\n                    var instances = response.data;\n\n                    if (response.start > 0) {\n                        // Add results instead of removing existing ones\n                        for (var i = 0; i < instances.length; i++) {\n                            $scope.model.processInstances.push(instances[i]);\n                        }\n\n                        $scope.state = {noProcesses: false};\n                    } else {\n                        $scope.model.processInstances = instances;\n                        $scope.state = {noProcesses: (!response.data || response.data.length == 0)};\n                    }\n\n                    if (response.start + response.size < response.total) {\n                        // More pages available\n                        $scope.model.hasNextPage = true;\n                    } else {\n                        $scope.model.hasNextPage = false;\n                    }\n\n                    var isSelected = false;\n\n                    if ($rootScope.root.selectedProcessId) {\n                        for (var i = 0; i < instances.length; i++) {\n                            if (instances[i].id == $rootScope.root.selectedProcessId) {\n                                isSelected = true;\n                                $scope.selectedProcessInstance = instances[i];\n                                break;\n                            }\n                        }\n                        $rootScope.root.selectedProcessId = undefined;\n                    }\n                    if (!isSelected && instances.length > 0) {\n                        if (!$scope.selectedProcessInstance) {\n                            $scope.selectedProcessInstance = instances[0];\n                        }\n                    }\n\n                    // If there is a new process instance, we want it to be selected\n                    if ($scope.newProcessInstance !== null && $scope.newProcessInstance !== undefined) {\n                        if ($scope.newProcessInstance.id !== null && $scope.newProcessInstance.id !== undefined) {\n                            for (var instanceIndex = 0; instanceIndex < $scope.model.processInstances.length; instanceIndex++) {\n                                if ($scope.model.processInstances[instanceIndex].id === $scope.newProcessInstance.id) {\n                                    $scope.selectedProcessInstance = $scope.model.processInstances[instanceIndex];\n                                    break;\n                                }\n                            }\n                        }\n                       // Always reset when loading process instance\n                        $scope.newProcessInstance = undefined;\n                    }\n\n                    $scope.model.filter.loading = false;\n                    $rootScope.window.forceRefresh = true;\n                }).\n                error(function (response, status, headers, config) {\n                    console.log('Something went wrong: ' + response);\n                });\n        };\n\n        $scope.selectProcessDefinition = function (definition) {\n            $scope.newProcessInstance.processDefinitionId = definition.id;\n            $scope.newProcessInstance.name = definition.name + ' - ' + new moment().format('MMMM Do YYYY');\n            $scope.newProcessInstance.processDefinition = definition;\n\n            $timeout(function () {\n                angular.element('#start-process-name').focus();\n            }, 20);\n        };\n\n        $scope.selectStateFilter = function (state) {\n            if (state != $scope.model.filter.param.state) {\n                $scope.model.filter.param.state = state;\n                $scope.collapseFilter();\n                $scope.selectedProcessInstance = undefined;\n            }\n        };\n\n        $scope.sortChanged = function() {\n            $scope.selectedProcessInstance = undefined;\n        };\n\n        $scope.selectDefaultDefinition = function() {\n            // Select first non-default definition, if any\n            ProcessService.getProcessDefinitions($scope.appDefinitionKey).then(function(response) {\n            \t$rootScope.root.processDefinitions = response.data;\n\t            if ($scope.root.processDefinitions && $scope.root.processDefinitions.length > 0) {\n\t                for (var i=0; i< $scope.root.processDefinitions.length; i++) {\n\t                    var def = $scope.root.processDefinitions[i];\n\t                    if (def.id != 'default') {\n\t                        $scope.selectProcessDefinition(def);\n\t                        break;\n\t                    }\n\t                }\n\t            }\n\t        });\n\n        };\n\n        $scope.backToList = function(reloadProcessInstances) {\n\n            $scope.newProcessInstance = undefined;\n\n            $scope.model.mode = 'process-list';\n            $scope.startFormError = undefined;\n\n            // If param is true: reload, no questions asked\n            if (reloadProcessInstances) {\n\n                // Reset selection\n                $scope.selectedProcessInstance = undefined;\n\n                // Reset filters\n                $scope.model.filter.param.state = $scope.model.stateFilterOptions[0];\n                $scope.model.filter.param.sort = $scope.model.sorts[0].id;\n\n                $scope.loadProcessInstances();\n            }\n\n            // In case we're coming from the task page, no process instances have been loaded\n            if ($scope.model.processInstances === null || $scope.model.processInstances === undefined) {\n                $scope.loadProcessInstances();\n            }\n\n        };\n\n        $scope.createProcessInstance = function () {\n\n            // Reset state\n            $rootScope.root.showStartForm = false;\n\n            $scope.model.mode = 'process-create';\n            $scope.newProcessInstance = {};\n            $scope.selectDefaultDefinition();\n        };\n\n        $scope.$on('process-started-error', function (event, data) {\n            $rootScope.addAlert(data.error.message, 'error');\n        });\n\n        // Called after form is submitted\n        $scope.$on('process-started', function (event, data) {\n            $scope.newProcessInstance.id = data.id;\n            $scope.backToList(true);\n        });\n\n        $scope.startProcessInstanceWithoutForm = function() {\n            $scope.newProcessInstance.loading = true;\n            var createInstanceData = {processDefinitionId: $scope.newProcessInstance.processDefinition.id, name: $scope.newProcessInstance.name};\n            $http({method: 'POST', url: FLOWABLE.CONFIG.contextRoot + '/app/rest/process-instances', data: createInstanceData}).\n                success(function (response, status, headers, config) {\n                    $scope.newProcessInstance.id = response.id;\n                    $scope.newProcessInstance.loading = false;\n                    $scope.backToList(true);\n\n                }).\n                error(function (response, status, headers, config) {\n                    $scope.newProcessInstance.loading = false;\n\n                    if(response && response.messageKey) {\n                        $translate(response.messageKey, response.customData).then(function(message) {\n                            $scope.errorMessage = message;\n                            console.log(message);\n                        });\n                    }\n                });\n        };\n\n        $rootScope.loadProcessDefinitions($scope.appDefinitionKey);\n\n        // If 'createProcessInstance' is set (eg from the task page)\n        if ($rootScope.createProcessInstance) {\n            $rootScope.createProcessInstance = false;\n            $scope.createProcessInstance();\n        } else {\n            $scope.loadProcessInstances();\n        }\n\n    }]);\n"
  },
  {
    "path": "flowable-ui-web/task/workflow/scripts/controllers/render-form.js",
    "content": "/* 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 */\nangular.module('flowableApp')\n    .controller('RenderFormController', ['$rootScope', '$scope', '$http', '$translate', '$modal', 'appResourceRoot', 'FormService', 'UserService', 'FunctionalGroupService', 'RelatedContentService', '$sce', '$timeout', 'TaskService', 'hotkeys', 'uiGridConstants',\n        function ($rootScope, $scope, $http, $translate, $modal, appResourceRoot, FormService, UserService, FunctionalGroupService, RelatedContentService, $sce, $timeout, TaskService, hotkeys, uiGridConstants) {\n\n            // when you bind it to the controller's scope, it will automatically unbind\n            // the hotkey when the scope is destroyed (due to ng-if or something that changes the DOM)\n            hotkeys.bindTo($scope)\n                .add({\n                    combo: 'tab',\n                    description: 'forward tab navigation',\n                    allowIn: ['INPUT', 'SELECT', 'TEXTAREA'],\n                    callback: function (event) {\n                        var currentFormElement = $scope.detectCurrentFormElement(event.target);\n                        var nextElement = $scope.getNextTabFormElement(currentFormElement);\n                        focusFormElement(nextElement, event);\n                    }\n                }).add({\n                    combo: 'shift+tab',\n                    description: 'Backward tab navigation',\n                    allowIn: ['INPUT', 'SELECT', 'TEXTAREA'],\n                    callback: function (event) {\n                        var currentFormElement = $scope.detectCurrentFormElement(event.target);\n                        var prevElement = $scope.getPrevTabFormElement(currentFormElement);\n                        focusFormElement(prevElement, event);\n                    }\n                });\n\n            function focusFormElement(formElement, event) {\n                if (formElement && formElement != null) {\n                    if (formElement.type == \"radio-buttons\") {\n                        formElement = angular.element(\"#activiti-\" + formElement.id + \">div>label>input:nth-child(1)\");\n                    }  else {\n                        formElement = angular.element(\"#activiti-\" + formElement.id);\n                    }\n                    if (formElement[0]) {\n                        if (typeOf('HTMLLIElement', formElement[0]))            {\n                            event.preventDefault();\n                        } else {\n                            formElement[0].focus();\n                            event.preventDefault();\n                        }\n                    }\n                }\n            }\n\n            function typeOf(name, obj) {\n                return Object.prototype.toString.call(obj) === '[object ' + name + ']';\n            }\n\n            function initModel () {\n                $scope.model = {\n                    loading: false,\n                    valid: false,\n                    uploads: {},\n                    completeButtonDisabled: false,\n                    saveButtonDisabled: false,\n                    uploadInProgress: false,\n                    isTaskForm: false\n                };\n            }\n\n            initModel();\n\n\n            $scope.detectCurrentFormElement = function (currentHtmlElement) {\n                var currentHtmlElementId = currentHtmlElement.id;\n                if (typeOf('HTMLInputElement', currentHtmlElement) && currentHtmlElement.type == \"radio\") {\n                    //the current input is a radio option\n                    //then the parent id #activiti-<name>\n                    currentHtmlElementId = \"activiti-\" + currentHtmlElement.name;\n                }\n\n                var fields = $scope.model.allFormFields;\n\n                //calculate the index of the current element in the fields array.\n                var indexInSorted = 0;\n                var elementToBeSelected = null;\n                for (indexInSorted = 0; indexInSorted < fields.length && elementToBeSelected==null; indexInSorted++) {\n                    if (elementToBeSelected == null && \"activiti-\" + fields[indexInSorted].id == currentHtmlElementId) {\n                        //find the element in the form elements for the next element to be selected\n                        elementToBeSelected = fields[indexInSorted];\n                    }\n                }\n                return elementToBeSelected;\n            };\n\n            $scope.getNextTabFormElement = function (currentElement) {\n                var elementToBeSelected = null;\n                if (currentElement && currentElement != null) {\n                    var fields = $scope.model.allFormFields;\n\n                    var sortedElements = filterAndSortElements(fields);\n\n                    //calculate the index of the next element in the sorted array.\n                    var indexInSorted = 0;\n                    var foundElementIndex = -1;\n                    for (indexInSorted = 0; indexInSorted < sortedElements.length && foundElementIndex == -1; indexInSorted++) {\n                        if (sortedElements[indexInSorted].id == currentElement.id) {\n                            foundElementIndex = indexInSorted;\n                        }\n                    }\n\n                    if (foundElementIndex >= 0 && foundElementIndex < sortedElements.length) {\n                        while (foundElementIndex < sortedElements.length-1 && elementToBeSelected == null) {\n                            //find the element in the form elements for the next element to be selected\n                            elementToBeSelected = sortedElements[++foundElementIndex];\n                        }\n                    }\n                }\n                return elementToBeSelected;\n            };\n\n            $scope.getPrevTabFormElement = function (currentElement) {\n                var elementToBeSelected = null;\n                if (currentElement && currentElement != null) {\n\n                    var fields = $scope.model.allFormFields;\n                    var sortedElements = filterAndSortElements(fields);\n\n                    //calculate the index of the next element in the sorted array.\n                    var indexInSorted = 0;\n                    var foundElementIndex = -1;\n                    for (indexInSorted = 0; indexInSorted < sortedElements.length && foundElementIndex == -1; indexInSorted++) {\n                         if (sortedElements[indexInSorted].id == currentElement.id) {\n                            foundElementIndex = indexInSorted;\n                        }\n                    }\n\n                    if (foundElementIndex > 0) {\n                        while (foundElementIndex > 0 && elementToBeSelected == null) {\n                            //find the element in the form elements for the prev element to be selected\n                            elementToBeSelected = sortedElements[--foundElementIndex];\n                        }\n                    }\n                }\n                return elementToBeSelected;\n            };\n\n            function filterAndSortElements(fields) {\n                var sortedElements = [];\n                for (var i = 0; i < fields.length; i++) {\n                    sortedElements.push(fields[i]);\n                }\n\n                sortedElements = sortedElements.filter(function (field) {\n                    return !(\n                       field.isVisible == false\n                        || field.type === 'people'\n                        || field.type === 'functional-group'\n                        || field.type === 'expression'\n                        || field.type === 'upload');\n                });\n\n                sortedElements = sortedElements.sort(function (field1, field2) {\n                    var htmlElement1 = angular.element(\"#activiti-\" + field1.id);\n                    var htmlElement2 = angular.element(\"#activiti-\" + field2.id);\n                    var xPosition1 = 999999;\n                    var yPosition1 = 999999;\n\n                    var xPosition2 = 999999;\n                    var yPosition2 = 999999;\n\n                    if (htmlElement1) {\n                        var testedElementRect1 = htmlElement1[0].getBoundingClientRect();\n                        xPosition1 = testedElementRect1.left;\n                        yPosition1 = testedElementRect1.top;\n                    }\n\n                    if (htmlElement2) {\n                        var testedElementRect2 = htmlElement2[0].getBoundingClientRect();\n                        xPosition2 = testedElementRect2.left;\n                        yPosition2 = testedElementRect2.top;\n                    }\n\n                    if (yPosition1 == yPosition2) {\n                        if (xPosition1 == xPosition2) return 0;\n                        return (xPosition1 - xPosition2) / Math.abs(xPosition1 - xPosition2);\n                    }\n\n                    return (yPosition1 - yPosition2) / Math.abs(yPosition1 - yPosition2);\n\n                });\n\n                return sortedElements;\n            }\n\n            $scope.isEmpty = function (field) {\n                return (field.value === undefined || field.value == null || field.value.length == 0);\n            };\n\n            $scope.isEmptyDropdown = function(field) {\n\n                // Manual\n                if (field.hasEmptyValue !== null && field.hasEmptyValue !== undefined && field.hasEmptyValue === true) {\n                    if (field.options !== null && field.options !== undefined && field.options.length > 0) {\n                        var emptyValue = field.options[0];\n                        if (emptyValue === field.value) {\n                            return true;\n                        }\n                    }\n                } else if (field.value === '') {\n                    return true\n                }\n                return false;\n            };\n\n            $scope.appResourceRoot = appResourceRoot;\n\n            $scope.model.outcomesOnly = $scope.outcomesOnly !== null && $scope.outcomesOnly !== undefined\n                && ($scope.outcomesOnly === true || $scope.outcomesOnly === 'true');\n\n            // needed for selecting today in date popover\n\n            $scope.clearDate = function(field, callback) {\n                field.value = '';\n                if (callback) {\n                    callback(field.value);\n                }\n                jQuery(\"#\" + $rootScope.activitiFieldIdPrefix + field.id).blur();\n            };\n\n            $scope.selectToday = function(field, callback) {\n                var today = new Date();\n                today = new Date(today.getFullYear(), today.getMonth(), today.getDate(), 0, 0, 0, 0);\n                field.value = today;\n                if (callback) {\n                    callback(field.value);\n                }\n                jQuery(\"#\" + $rootScope.activitiFieldIdPrefix + field.id).blur();\n            };\n\n            $scope.closeDatePopup = function (field) {\n                jQuery(\"#\" + $rootScope.activitiFieldIdPrefix + field.id).blur();\n            };\n\n            $scope.combineFormVariables = function () {\n\n                var fields = $scope.model.allFormFields;\n                var localVariables = [];\n\n                for (var fieldArrayIndex = 0; fieldArrayIndex < fields.length; fieldArrayIndex++) {\n                    // Only adding value fields for form elements currently supported in condition evaluation\n                    if (fields[fieldArrayIndex].type !== 'expression') {\n                        localVariables.push(fields[fieldArrayIndex]);\n                    }\n                }\n\n                $scope.currentAndHistoricFormFields = localVariables;\n            };\n\n            /**\n             * Helper method: find a form field with a given id in a collection of fields\n             */\n            $scope.findFormFieldWithId = function (fields, id) {\n                if (fields && fields.length > 0) {\n\n                    // First check the current form fields\n                    for (var i = 0; i < fields.length; i++) {\n                        if (fields[i].id === id && fields[i].hasOwnProperty('isVisible')) {\n                            return fields[i];\n                        }\n                    }\n\n                    // Then check the historical ones\n                    for (var i = 0; i < fields.length; i++) {\n                        if (fields[i].id === id) {\n                            return fields[i];\n                        }\n                    }\n\n                }\n                return undefined;\n            };\n\n            // Pre-process any previous values, if needed\n            $scope.preProcessFields = function (fields) {\n                for (var i = 0; i < fields.length; i++) {\n                    var field = fields[i];\n\n                    // set visibility bool if no condition is present\n                    if (!field.visibilityCondition) {\n                        field.isVisible = true;\n                    }\n\n                    if (field.type == 'dropdown' && field.value && field.options && !field.readOnly) {\n                        for (var j = 0; j < field.options.length; j++) {\n                            if (field.options[j].name == field.value) {\n                                field.value = field.options[j];\n                                break;\n                            }\n                        }\n\n                    } else if (field.type == 'date' && field.value && !field.readOnly) {\n                        var dateArray = field.value.split('-');\n                        if (dateArray && dateArray.length == 3) {\n                            field.value = new Date(dateArray[0],dateArray[1]-1,dateArray[2]);\n                        }\n\n                    } else if (field.type == 'people' && field.value) {\n                        UserService.getUserInfoForForm(field.value, i).then(function (userInfoFormObject) {\n                            fields[userInfoFormObject.index].value = userInfoFormObject.userData;\n                        });\n\n                    } else if (field.type == 'functional-group' && field.value) {\n                        FunctionalGroupService.getGroupInfoForForm(field.value, i).then(function (groupInfoFormObject) {\n                            fields[groupInfoFormObject.index].value = groupInfoFormObject.groupData;\n                        });\n\n                    } else if (field.type == 'upload' && field.value) {\n                        $scope.model.uploads[field.id] = [];\n                        var newUploadValue = '';\n                        for (var j = 0; j < field.value.length; j++) {\n                            $scope.model.uploads[field.id].push(field.value[j]);\n                            if (newUploadValue.length > 0) {\n                                newUploadValue += ',';\n                            }\n                            newUploadValue += field.value[j].id;\n                        }\n                        field.value = newUploadValue;\n\t\t\t\t\t}\n                }\n            };\n\n            /**\n             * Helper method: prepares the form fields for usage in the form template\n             */\n            var prepareFormFields = function (formData) {\n\n                $scope.model.allFormFields = formData.fields;\n\n                $scope.model.restValues = {};\n\n                // populate only REST values in case of outcomesOnly\n                if (!$scope.outcomesOnly) {\n                    $scope.preProcessFields($scope.model.allFormFields);\n                }\n            };\n\n            $scope.validateField = function () {\n\n                function arrayContains(selectOptions, key, value) {\n                    var found = false;\n                    selectOptions.every(function (element, index, array) {\n                        if (element[key] == value) {\n                            found = true;\n                            return false;\n                        }\n                        return true;\n                    });\n                    return found;\n                }\n\n                function findMatchingItem(items, key, value) {\n                    var foundItem = undefined;\n                    if (items && items.length > 0) {\n                        items.every(function (item, index, array) {\n                            if (item[key] == value) {\n                                foundItem = item;\n                                return false;\n                            }\n                            return true;\n                        });\n                    }\n                    return foundItem;\n                }\n\n                if ($scope.model.allFormFields) {\n                    var formValid = true;\n                    for (var fieldIndex = 0; fieldIndex < $scope.model.allFormFields.length; fieldIndex++) {\n                        var field = $scope.model.allFormFields[fieldIndex];\n\n                        if (field) {\n                            // Required field check\n                            if (field && field.required) {\n                                switch (field.type) {\n\n                                    case 'boolean':\n                                        if ((field.value === undefined || field.value == false || field.value == null)) {\n                                            formValid = false;\n                                        }\n                                        break;\n\n                                    case 'radio-buttons':\n                                        var selectOptions = field.options;\n\n                                        if (field.value === undefined || field.value == '' || field.value == null) {\n                                            formValid = false;\n                                        } else {\n                                            formValid = arrayContains(selectOptions, \"name\", field.value);\n                                            if (!formValid) {\n                                                field.value = undefined;\n                                            }\n                                        }\n                                        break;\n\n                                    case 'dropdown':\n\n                                        var emptyValue;\n                                        if (field.hasEmptyValue !== null && field.hasEmptyValue !== undefined && field.hasEmptyValue === true) {\n                                            if (field.options !== null && field.options !== null && field.options.length > 0) {\n                                                emptyValue = field.options[0];\n                                            }\n                                        }\n\n                                        if (emptyValue !== undefined && emptyValue !== null) {\n                                            if (field.value.name === emptyValue.name) {\n                                                formValid = false;\n                                            }\n                                        }\n\n                                        break;\n\n                                    default: //any other type\n                                        if (field.value === undefined || field.value === '' || field.value === null) {\n                                            formValid = false;\n                                        }\n                                        break;\n                                }\n\n                                if (!formValid) {\n                                    break;\n                                }\n                            } else {\n\n                            }\n                        }\n                    }\n\n                    $scope.model.valid = formValid;\n                }\n            };\n\n\n            // Deep watch form data fields to call validation\n            $scope.$watch('formData', function () {\n                $scope.validateField();\n            }, true);\n\n            /*\n             * Fetching the task form if task id was provided, a start form if process definition id was\n             * provided and otherwise the model should be on the scope\n             */\n\n            var fetchAndRenderForm = function () {\n\n                $scope.model.loading = true;\n\n                if ($scope.formDefinition) {\n\n                    $scope.formData = $scope.formDefinition;\n                    prepareFormFields($scope.formData);\n\n                    if ($scope.model.outcomesOnly !== true) {\n\n                        $scope.combineFormVariables();\n                        $scope.model.loading = false;\n                    }\n\n                    $scope.model.loading = false;\n\n                } else if ($scope.taskId) {\n\n                    FormService.getTaskForm($scope.taskId).then(function (formData) {\n\n                        $scope.formData = formData;\n                        prepareFormFields($scope.formData); // Prepare the form fields to allow for layouting\n\n                        if ($scope.model.outcomesOnly !== true) {\n                            $scope.combineFormVariables();\n                            $scope.model.loading = false;\n\n                        }\n\n                        $scope.model.loading = false;\n\n                    });\n\n                } else if ($scope.processDefinitionId) {\n\n                    FormService.getStartForm($scope.processDefinitionId).then(function (formData) {\n                        $scope.formData = formData;\n                        prepareFormFields($scope.formData); // Prepare the form fields to allow for layouting\n                        $scope.model.loading = false;\n\n                        $scope.combineFormVariables();\n                    });\n                } else if ($scope.caseDefinitionId) {\n\n                    FormService.getCaseStartForm($scope.caseDefinitionId).then(function (formData) {\n                        $scope.formData = formData;\n                        prepareFormFields($scope.formData); // Prepare the form fields to allow for layouting\n                        $scope.model.loading = false;\n\n                        $scope.combineFormVariables();\n                    });\n                }\n            };\n\n            // Fetch and show on first usage\n            fetchAndRenderForm();\n\n            // Re-render when process definition || caseDefinitionId changes\n            $scope.$watch('processDefinitionId', function (newValue, oldValue) {\n                if (newValue !== oldValue) {\n                    // Check if actually changed\n                    initModel();\n                    fetchAndRenderForm();\n                }\n            }, true);\n            $scope.$watch('caseDefinitionId', function (newValue, oldValue) {\n                if (newValue !== oldValue) {\n                    // Check if actually changed\n                    initModel();\n                    fetchAndRenderForm();\n                }\n            }, true);\n\n            /**\n             * Generates a default button text based on what is passed as config\n             */\n            $scope.getDefaultCompleteButtonText = function () {\n                if ($scope.processDefinitionId) {\n                    return $translate.instant('FORM.DEFAULT-OUTCOME.START-PROCESS');\n                } else if ($scope.caseDefinitionId) {\n                    return $translate.instant('FORM.DEFAULT-OUTCOME.START-CASE');\n                } else {\n                    return $translate.instant('FORM.DEFAULT-OUTCOME.COMPLETE');\n                }\n            };\n\n            $scope.saveForm = function () {\n\n                $scope.model.loading = true;\n                $scope.model.completeButtonDisabled = true;\n\n                // Prep data\n                var postData = $scope.createPostData();\n                postData.formId = $scope.formData.id;\n\n                 FormService.saveTaskForm($scope.taskId, postData).then(\n                     function (data) {\n                         $rootScope.addAlertPromise($translate('TASK.ALERT.SAVED'));\n                         $scope.model.completeButtonDisabled = false;\n                         $scope.model.loading = false;\n                     },\n                     function (errorResponse) {\n                         $scope.model.completeButtonDisabled = false;\n                         $scope.model.loading = false;\n                         $scope.$emit('task-save-error', {\n                             taskId: $scope.taskId,\n                             error: errorResponse\n                         });\n                     });\n            };\n\n            $scope.completeForm = function (outcome) {\n\n                $scope.model.loading = true;\n                $scope.model.completeButtonDisabled = true;\n\n                // Prep data\n                var postData = $scope.createPostData();\n                postData.formId = $scope.formData.id;\n\n                if (outcome) {\n                    postData.outcome = outcome.name;\n                }\n\n                if ($scope.processDefinitionId) {\n\n                    // Add right process-definition for this form\n                    postData.processDefinitionId = $scope.processDefinitionId;\n\n                    if ($scope.processName) {\n                        postData.name = $scope.processName;\n                    }\n\n                    FormService.completeStartForm(postData).then(\n                        function (data) {\n                            $scope.$emit('process-started', data);\n                            $scope.model.completeButtonDisabled = false;\n                            $scope.model.loading = false;\n                        },\n                        function (errorResponse) {\n                            $scope.model.completeButtonDisabled = false;\n                            $scope.model.loading = false;\n                            $scope.$emit('process-started-error', {\n                            \tprocessDefinitionId: $scope.processDefinitionId,\n                            \terror: errorResponse\n                           \t});\n                        });\n\n\n                } else if ($scope.caseDefinitionId) {\n\n                    // Add right process-definition for this form\n                    postData.caseDefinitionId = $scope.caseDefinitionId;\n\n                    if ($scope.caseName) {\n                        postData.name = $scope.caseName;\n                    }\n\n                    FormService.completeCaseStartForm(postData).then(\n                        function (data) {\n                            $scope.$emit('case-started', data);\n                            $scope.model.completeButtonDisabled = false;\n                            $scope.model.loading = false;\n                        },\n                        function (errorResponse) {\n                            $scope.model.completeButtonDisabled = false;\n                            $scope.model.loading = false;\n                            $scope.$emit('case-started-error', {\n                                caseDefinitionId: $scope.caseDefinitionId,\n                                error: errorResponse\n                            });\n                        });\n\n\n                } else {\n\n                    FormService.completeTaskForm($scope.taskId, postData).then(\n                        function (data) {\n                            $scope.$emit('task-completed', {taskId: $scope.taskId});\n                            $scope.model.completeButtonDisabled = false;\n                            $scope.model.loading = false;\n                        },\n                        function (errorResponse) {\n                            $scope.model.completeButtonDisabled = false;\n                            $scope.model.loading = false;\n                            $scope.$emit('task-completed-error', {\n                            \ttaskId: $scope.taskId,\n                            \terror: errorResponse\n                            });\n                        });\n\n                }\n            };\n\n            $scope.fieldPersonSelected = function (user, field) {\n                field.value = user;\n            };\n\n            $scope.fieldPersonRemoved = function (user, field) {\n                field.value = undefined;\n            };\n\n            $scope.fieldGroupSelected = function (group, field) {\n                field.value = group;\n            };\n\n            $scope.fieldGroupRemoved = function (group, field) {\n                field.value = undefined;\n            };\n\n            $scope.contentUploaded = function (content, field) {\n                if (!$scope.model.uploads[field.id]) {\n                    $scope.model.uploads[field.id] = [];\n                }\n                $scope.model.uploads[field.id].push(content);\n                $scope.updateContentValue(field);\n            };\n\n            $scope.removeContent = function (content, field) {\n                if ($scope.model.uploads[field.id]) {\n\n                    $scope.model.uploads[field.id] = jQuery.grep($scope.model.uploads[field.id], function (elem, index) {\n                        return elem !== content;\n                    });\n                    $scope.updateContentValue(field);\n                }\n            };\n\n            $scope.updateContentValue = function (field) {\n                if (!$scope.model.uploads[field.id]) {\n                    field.value = undefined;\n                } else {\n                    var newValue = '';\n                    for (var i = 0; i < $scope.model.uploads[field.id].length; i++) {\n                        if (i > 0) {\n                            newValue += ',';\n                        }\n                        newValue += $scope.model.uploads[field.id][i].id;\n                    }\n\n                    field.value = newValue;\n                }\n            };\n\n            $scope.onFieldValueChange = function (field) {\n            };\n\n            $scope.uploadInProgress = function (state) {\n                if (state !== 'undefined') {\n                    $scope.model.uploadInProgress = state;\n                }\n            };\n\n            $scope.createPostData = function() {\n                var postData = {values: {}};\n                if (!$scope.model.allFormFields) return postData;\n\n                for (var fieldArrayIndex = 0; fieldArrayIndex < $scope.model.allFormFields.length; fieldArrayIndex++) {\n                    var field = $scope.model.allFormFields[fieldArrayIndex];\n                    if (!field || !field.isVisible) continue;\n\n                    if (field.type === 'boolean' && field.value == null) {\n                        field.value = false;\n                    }\n\n                    if (field && field.type !== 'expression' && !field.readOnly) {\n\n                        if (field.type === 'dropdown' && field.hasEmptyValue !== null && field.hasEmptyValue !== undefined && field.hasEmptyValue === true) {\n\n                            // Manually filled dropdown\n                            if (field.options !== null && field.options !== undefined && field.options.length > 0) {\n\n                                var emptyValue = field.options[0];\n                                if (field.value != null && field.value != undefined && emptyValue.name !== field.value.name) {\n                                    postData.values[field.id] = field.value;\n                                }\n                            }\n\n                        } else if (field.type === 'date' && field.value) {\n                            postData.values[field.id] = field.value.getFullYear() + '-' + (field.value.getMonth() + 1) + '-' + field.value.getDate();\n\n                        } else {\n                            postData.values[field.id] = field.value;\n                        }\n                    }\n                }\n\n                return postData;\n            };\n\n            $scope.togglePasswordFieldType = function(field){\n        \t\t\tif(field.params.type === undefined || !field.params.type)\n        \t\t\t\tfield.params.type = true;\t\n        \t\t\telse\n        \t\t\t\tfield.params.type = false;\t\n            };\n\n            // Place methods that are used by controls into an object which is pushed won the container hierarchy\n            // Note that these callbacks must be mapped inside the formElement directive as well (workflow-directives.js)\n            $scope.controlCallbacks = {\n                onFieldValueChange: $scope.onFieldValueChange,\n                isEmpty: $scope.isEmpty,\n                isEmptyDropdown: $scope.isEmptyDropdown,\n                fieldPersonSelected: $scope.fieldPersonSelected,\n                fieldPersonRemoved: $scope.fieldPersonRemoved,\n                fieldGroupSelected: $scope.fieldGroupSelected,\n                fieldGroupRemoved: $scope.fieldGroupRemoved,\n                removeContent: $scope.removeContent,\n                contentUploaded: $scope.contentUploaded,\n                uploadInProgress: $scope.uploadInProgress,\n                handleReadonlyClick: $scope.handleReadonlyClick,\n                clearDate: $scope.clearDate,\n                selectToday: $scope.selectToday,\n                closeDatePopup: $scope.closeDatePopup,\n                togglePasswordFieldType: $scope.togglePasswordFieldType\n            };\n\n            if ($scope.taskId) {\n                $scope.model.isTaskForm = true;\n            }\n\n        }]);\n"
  },
  {
    "path": "flowable-ui-web/task/workflow/scripts/controllers/start-form.js",
    "content": "/* 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'use strict';\n\nangular.module('flowableApp')\n    .controller('StartFormController', ['$rootScope', '$scope', '$translate', '$http', '$timeout','$location', '$route', '$modal', '$routeParams', '$popover',\n        function ($rootScope, $scope, $translate, $http, $timeout, $location, $route, $modal, $routeParams, $popover) {\n   \n    $scope.model.initializing = true;    \n        \n    $scope.$watch('selectedProcessInstance', function(newValue) {\n       \n        if (newValue && newValue.id && (newValue.id != $rootScope.root.selectedProcessId || !$scope.model.initializing)) {\n            $scope.model.processInstance = newValue;\n\n            $scope.getProcessInstance(newValue.id);\n            $rootScope.root.showStartForm = false;\n            $scope.model.formData = undefined;\n            $scope.model.initializing = false;\n        }\n    });\n        \n    $scope.getProcessInstance = function(processInstanceId) {\n        if (processInstanceId === undefined || processInstanceId === '') {\n            return;\n        }\n        $http({method: 'GET', url: FLOWABLE.CONFIG.contextRoot + '/app/rest/process-instances/' + processInstanceId}).\n            success(function(response, status, headers, config) {\n                $scope.model.processInstance = response;\n                $scope.loadStartForm(processInstanceId);\n            }).\n            error(function(response, status, headers, config) {\n                console.log('Something went wrong: ' + response);\n            });\n    };\n\n    $scope.loadStartForm = function(processInstanceId) {\n        $http({method: 'GET', url: FLOWABLE.CONFIG.contextRoot + '/app/rest/process-instances/' + processInstanceId + '/start-form'}).\n            success(function(response, status, headers, config) {\n                $scope.model.formData = response;\n            }).\n            error(function(response, status, headers, config) {\n                console.log('Something went wrong: ' + response);\n            });\n    };\n    \n    $scope.openProcessInstance = function() {\n        $rootScope.root.showStartForm = false;\n        $scope.model.formData = undefined;\n    };\n    \n    $scope.getProcessInstance($rootScope.root.selectedProcessId);\n}]);\n"
  },
  {
    "path": "flowable-ui-web/task/workflow/scripts/controllers/start-process.js",
    "content": "/* 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'use strict';\n\nangular.module('flowableApp')\n      .controller('StartProcessController', ['$rootScope', '$scope', '$translate', '$http', '$timeout','$location', '$route', '$modal', '$routeParams', '$q', 'AppDefinitionService', 'ProcessService', 'FormService', 'RelatedContentService',\n   function ($rootScope, $scope, $translate, $http, $timeout, $location, $route, $modal, $routeParams, $q, AppDefinitionService, ProcessService, FormService, RelatedContentService) {\n\n       $scope.appDefinitionKey = $routeParams.appDefinitionKey;\n       $scope.missingAppdefinition = $scope.appDefinitionKey === false;\n\n       AppDefinitionService.setActiveAppDefinitionKey($scope.appDefinitionKey);\n\n       ProcessService.getProcessDefinitions($scope.appDefinitionKey).then(function(response){\n           $scope.processDefinitions = response.data;\n       });\n\n      $scope.processName = '';\n      $scope.processDefinition = null;\n      $scope.processDefinitionWithStartFormId = null;\n      $scope.startFormDefinition = null;\n\n      // Support for prepopulating upload fields\n      if (FLOWABLE.CONFIG.workflow && FLOWABLE.CONFIG.workflow.addStartProcessContent) {\n         $scope.startProcessContent = FLOWABLE.CONFIG.workflow.addStartProcessContent;\n         $scope.startProcessContentQueued = false;\n      }\n      $scope.addedStartProcessContent = null;\n\n      $scope.selectProcessDefinition = function(definition){\n         if ($scope.processDefinition == definition)\n         {\n            // deselect workflow\n            $scope.processDefinition = null;\n            $scope.processDefinitionWithStartFormId = null;\n            $scope.startFormDefinition = null;\n         }\n         else {\n            $scope.processDefinition = definition;\n            if (definition.hasStartForm) {\n               $scope.loadStartForm(definition);\n            }\n            else {\n               $scope.processName = definition.name + ' - ' + new moment().format('MMMM Do YYYY');\n               $scope.processDefinitionWithStartFormId = null;\n               $scope.startFormDefinition = null;\n            }\n         }\n      };\n\n      $scope.loadStartForm = function(){\n         // First lets see if there is any content that shall be added to the start form\n         if (!$scope.startProcessContent) {\n            // No content shall be added, just show the form\n            $scope.setStartForm();\n         }\n         else if ($scope.startProcessContent) {\n            // Start form shall be pre-populated with files\n            if ($scope.addedStartProcessContent) {\n              // Content has already been added, lets show the start form\n               $scope.setStartForm();\n            }\n            else\n            {\n               // All content has not been added yet but is it being queued?\n               if ($scope.startProcessContentQueued) {\n                  // The content is being queued and added right now, don't do anything.\n                  // When the queue is finished and setForm is called, it will use the last selected\n                  // process definition\n               }\n               else {\n                  // Lets queue the content to be added\n                  $scope.startProcessContentQueued = true;\n                  if (typeof $scope.startProcessContent == 'function') {\n                     // Instead of the actual content that hsall be added a function was provided,\n                     // let it load the content so we can add it afterwards\n                     $scope.startProcessContent(function(content){\n                        // Replace the loader function with data\n                        $scope.startProcessContent = content;\n\n                        // Add the data\n                        $scope.queueStartProcessContent().then(function(){\n                           $scope.setStartForm();\n                        });\n                     }, function(code, msg){\n                        $rootScope.addAlert(msg, 'error');\n                     });\n                  }\n                  else {\n                     // the data to be added is there, then add id\n                     $scope.queueStartProcessContent().then(function(){\n                        $scope.setStartForm();\n                     });\n                  }\n               }\n            }\n         }\n         else {\n            // Content is already being added to the start form, lets make\n         }\n      };\n\n      $scope.queueStartProcessContent = function(){\n         var addedContent = [];\n         var deferred = $q.defer();\n         var contentToAdd = $scope.startProcessContent;\n         var content;\n         for (var i = 0; i < contentToAdd.length; i++) {\n            content = contentToAdd[i];\n            RelatedContentService.addRelatedContentFromSource(null, null, content.source, content.sourceId , content.name, content.link).then(function(result) {\n               addedContent.push(result);\n               if (addedContent.length == contentToAdd.length) {\n                  $scope.addedStartProcessContent = addedContent;\n                  deferred.resolve();\n               }\n            }, function(error) {\n               $rootScope.addAlert($translate('PROCESS.ALERT.START-PROCESS-CONTENT-ADD-FAILED', { noOfFiles: contentToAdd.length }), 'error');\n               deferred.reject();\n            });\n         }\n         return deferred.promise;\n      };\n\n      $scope.setStartForm = function(){\n         var definition = $scope.processDefinition;\n         if (definition.hasStartForm) {\n            // Load start form\n            FormService.getStartForm(definition.id).then(function(formData) {\n               // Merge in the content to become pre-populated upload fields\n               if ($scope.addedStartProcessContent) {\n                  var field;\n                  var allFormFields = formData.fields;\n                  for (var index in allFormFields) {\n                     field = allFormFields[index];\n                     if (field.type == 'upload') {\n                        field.value = $scope.addedStartProcessContent;\n                        break;\n                     }\n                  }\n               }\n\n               $scope.processName = definition.name + ' - ' + new moment().format('MMMM Do YYYY');\n               $scope.processDefinition = definition;\n               $scope.processDefinitionWithStartFormId = definition.id;\n               $scope.startFormDefinition = formData;\n            });\n         }\n      };\n\n      $scope.navigateToView = function (view) {\n          if ($scope.appDefinitionKey && !FLOWABLE.CONFIG.integrationProfile) {\n              $location.path(\"/apps/\" + encodeURIComponent($scope.appDefinitionKey)+ view);\n          }\n          else {\n              $location.path(view);\n          }\n      };\n\n      $scope.createProcessInstance = function(){\n         ProcessService.createProcess({\n            processDefinitionId: $scope.processDefinition.id,\n            name: $scope.processName\n         }).then(function(){\n             $scope.navigateToView('/processes');\n         })\n\n      };\n\n      var unregisterProcessStartedCallback = $scope.$on('process-started', function (event, data) {\n         unregisterProcessStartedCallback();\n          $scope.navigateToView('/processes');\n      });\n\n\n   }]);\n"
  },
  {
    "path": "flowable-ui-web/task/workflow/scripts/controllers/task.js",
    "content": "/* 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'use strict';\n\n\nangular.module('flowableApp')\n    .controller('TaskController', ['$rootScope', '$scope', '$translate', '$timeout','$location', '$modal', '$popover', 'appResourceRoot', 'CommentService', 'TaskService', '$routeParams', 'AppDefinitionService',\n        function ($rootScope, $scope, $translate, $timeout, $location, $modal, $popover, appResourceRoot, CommentService, TaskService, $routeParams, AppDefinitionService) {\n\n            // Ensure correct main page is set\n            $rootScope.setMainPageById('tasks');\n\n            $scope.selectedTask = { id: $routeParams.taskId };\n\n            $scope.appDefinitionKey = $routeParams.appDefinitionKey;\n\n            $scope.$on('task-completed', function (event, data) {\n                $rootScope.addAlertPromise($translate('TASK.ALERT.COMPLETED', data));\n                $scope.openTasks();\n            });\n\n            $scope.openTasks = function(task) {\n                var path='';\n                if($rootScope.activeAppDefinition && !FLOWABLE.CONFIG.integrationProfile) {\n                    path = \"/apps/\" + $rootScope.activeAppDefinition.id;\n                }\n                $location.path(path + \"/tasks\");\n            };\n        }]\n);\n\nangular.module('flowableApp')\n  .controller('TaskDetailController', ['$rootScope', '$scope', '$translate', '$http','$location', '$routeParams', 'appResourceRoot', 'CommentService', 'TaskService', 'FormService', 'RelatedContentService', '$timeout', '$modal', '$popover',\n        function ($rootScope, $scope, $translate, $http, $location, $routeParams, appResourceRoot, CommentService, TaskService, FormService, RelatedContentService, $timeout, $modal, $popover) {\n\n    $scope.model = {\n        // Indirect binding between selected task in parent scope to have control over display\n        // before actual selected task is switched\n\t    task: $scope.selectedTask,\n\t    completeButtonDisabled: false,\n\t    claimButtonDisabled: false,\n        uploadInProgress: false\n\t};\n\n    $scope.activeTab = 'form';\n\n    $scope.model.involvementSummary = {\n        loading: false\n    };\n\n    $scope.model.contentSummary = {\n        loading: false\n    };\n\n    $scope.model.commentSummary = {\n        loading: false\n    };\n\n    $scope.model.subTaskSummary = {\n        loading: false\n    };\n\n    $scope.resetModel = function() {\n        // Reset tabs\n        $scope.taskTabs = [];\n        if ($scope.model.task.formKey != null) {\n            $scope.taskTabs.push(\n                {\n                    'id': 'form',\n                    'title': 'TASK.TITLE.FORM'\n                }\n            );\n            $scope.activeTab = 'form';\n        } else {\n            $scope.activeTab = 'details';\n        }\n\n        $scope.taskTabs.push( {\n            'id': 'details',\n            'title': 'TASK.TITLE.DETAILS'\n        });\n\n        // Reset summary model\n        $scope.model.involvementSummary = {\n            loading: true\n        };\n\n        $scope.model.contentSummary = {\n            loading: true\n        };\n\n        $scope.model.commentSummary = {\n            loading: true\n        };\n\n        $scope.model.subTaskSummary = {\n            loading: true\n        };\n\n        $scope.model.content = undefined;\n        $scope.model.comments = undefined;\n\n        $timeout(function() {\n            // Force refresh of all auto-height components as the tabs can be hidden or shown\n            $rootScope.window.forceRefresh = true;\n        }, 100);\n\n        var today = new Date();\n        $scope.today = new Date(today.getFullYear(), today.getMonth(), today.getDate() , 0, 0, 0, 0);\n    };\n\n    $scope.showPeople = function() {\n        $scope.activeTab = 'details';\n    };\n    $scope.showContent = function() {\n        $scope.activeTab = 'details';\n    };\n    $scope.showComments= function() {\n        $scope.activeTab = 'details';\n    };\n    $scope.showSubTasks= function() {\n        $scope.activeTab = 'details';\n    };\n    $scope.toggleForm= function() {\n        if($scope.activeTab == 'form') {\n            $scope.activeTab = 'details';\n        } else {\n            $scope.activeTab = 'form';\n        }\n    };\n\n    // The selected task is set by the parent, eg in tasks.js\n    $scope.$watch('selectedTask', function(newValue) {\n        if(newValue && newValue.id) {\n            $scope.model.taskUpdating = true;\n            $scope.model.task = newValue;\n            $scope.model.claimButtonDisabled = false;\n            if ($scope.model.task.formKey) {\n                $scope.resetModel();\n            }\n            $scope.getTask(newValue.id);\n        } else {\n            // Reset whole model to make sure nothing is left behind in case a new task will\n            // be selected in the future\n            $scope.model = {};\n        }\n    });\n\n\t// Ensure correct main page is set\n    $rootScope.setMainPageById('tasks');\n\n\n    $scope.setTaskAssigneeValue = function(user) {\n        var alertData = {\n            firstName: user.firstName,\n            lastName: user.lastName,\n            taskName: $scope.model.task.name\n        };\n\n        TaskService.assignTask($scope.model.task.id, user.id).then(function(data) {\n            $rootScope.addAlertPromise($translate('TASK.ALERT.ASSIGNED', alertData));\n            $scope.model.task = data;\n        });\n    };\n\n    $scope.setTaskAssigneeValueByEmail = function(email) {\n        TaskService.assignTaskByEmail($scope.model.task.id, email).then(function() {\n            $scope.model.task.assignee = {email: email}; // Faking a user (since it will only be an email address)\n        });\n    };\n\n    $scope.involvePerson = function (user) {\n        var alertData = {\n            firstName: user.firstName,\n            lastName: user.lastName,\n            taskName: $scope.model.task.name\n        };\n\n        TaskService.involveUserInTask(user.id, $scope.model.task.id).then(function() {\n            $rootScope.addAlertPromise($translate('TASK.ALERT.PERSON-INVOLVED',\n                alertData));\n\n            if(!$scope.model.task.involvedPeople) {\n                $scope.model.task.involvedPeople = [user];\n            } else {\n                $scope.model.task.involvedPeople.push(user);\n            }\n        });\n    };\n\n    $scope.involvePersonByEmail = function(email) {\n        TaskService.involveUserInTaskByEmail(email, $scope.model.task.id).then(function() {\n            if(!$scope.model.task.involvedPeople) {\n                $scope.model.task.involvedPeople = {email: email};\n            } else {\n                $scope.model.task.involvedPeople.push({email: email});\n            }\n        });\n    };\n\n    $scope.removeInvolvedUser = function (user) {\n        var alertData = {\n            firstName: user.firstName,\n            lastName: user.lastName,\n            taskName: $scope.model.task.name\n        };\n\n        TaskService.removeInvolvedUserInTask(user, $scope.model.task.id).then(function() {\n            $rootScope.addAlertPromise($translate('TASK.ALERT.PERSON-NO-LONGER-INVOLVED',\n                alertData));\n\n            $scope.model.task.involvedPeople.splice($.inArray(user, $scope.model.task.involvedPeople),1);\n        });\n    };\n\n    $scope.getTask = function(taskId) {\n        $scope.model.loading = true;\n        $scope.model.formData = undefined;\n        $scope.model.hasFormKey = false;\n        if ($scope.model.task.formKey) {\n            $scope.model.hasFormKey = true;\n        }\n\n        $http({method: 'GET', url: FLOWABLE.CONFIG.contextRoot + '/app/rest/tasks/' + taskId}).\n            success(function(response, status, headers, config) {\n\n                // Do not replace the model, as it's still used in the task-list\n                angular.extend($scope.model.task, response);\n\n                $scope.model.loading = false;\n                $scope.noSuchTask = false;\n\n                if (!$scope.model.hasFormKey) {\n                    $scope.resetModel();\n                }\n\n                $scope.loadComments();\n                $scope.loadRelatedContent();\n                $scope.loadSubTasks();\n\n                if ($scope.model.task.processInstanceId) {\n                    $scope.loadProcessInstance();\n                } else {\n                    $scope.model.processInstance = undefined;\n                }\n\n                if ($scope.model.task.scopeId) {\n                    $scope.loadCaseInstance();\n                } else {\n                    $scope.model.caseInstance = undefined;\n                }\n\n                $scope.refreshInvolvmentSummary();\n\n                // Loading form already\n                if ($scope.model.task.formKey !== null && $scope.model.task.formKey !== undefined) {\n                    FormService.getTaskForm($scope.model.task.id).then(function(formData) {\n                        $scope.model.formData = formData;\n                    });\n                } else {\n                    $scope.model.formData = undefined;\n                }\n\n                $scope.model.taskUpdating = false;\n            }).\n            error(function(response, status, headers, config) {\n                $scope.noSuchTask = true;\n            });\n    };\n\n    $scope.$watch('model.task.involvedPeople', function(newValue) {\n        $scope.refreshInvolvmentSummary();\n    }, true);\n\n    $scope.refreshInvolvmentSummary = function() {\n        if($scope.model.task) {\n            var newValue = $scope.model.task.involvedPeople;\n            $scope.model.involvementSummary.loading = false;\n            if(newValue && newValue.length > 0) {\n                $scope.model.involvementSummary.count = newValue.length;\n\n                if(newValue.length > 8) {\n                    $scope.model.involvementSummary.overflow = true;\n                    $scope.model.involvementSummary.items = [];\n\n                    for(var i=0; i< 8; i++) {\n                        $scope.model.involvementSummary.items.push(newValue[i]);\n                    }\n                } else {\n                    $scope.model.involvementSummary.overflow = false;\n                    $scope.model.involvementSummary.items = newValue;\n                }\n\n            } else {\n                $scope.model.involvementSummary.count = 0;\n            }\n        }\n    };\n\n    $scope.$watch('model.content.data', function(newValue) {\n        if($scope.model.task) {\n            $scope.model.contentSummary.loading = false;\n            if(newValue && newValue.length > 0) {\n                $scope.model.contentSummary.count = newValue.length;\n\n                if(newValue.length > 8) {\n                    $scope.model.contentSummary.overflow = true;\n                    $scope.model.contentSummary.items = [];\n\n                    for(var i=0; i< 8; i++) {\n                        $scope.model.contentSummary.items.push(newValue[i]);\n                    }\n                } else {\n                    $scope.model.contentSummary.overflow = false;\n                    $scope.model.contentSummary.items = newValue;\n                }\n\n            } else {\n                $scope.model.contentSummary.count = 0;\n            }\n        }\n    }, true);\n\n    $scope.$watch('model.comments.data', function(newValue) {\n       $scope.refreshCommentSummary();\n    }, true);\n\n    $scope.$watch('model.subTasks.data', function(newValue) {\n       $scope.refreshSubTaskSummary();\n    }, true);\n\n    $scope.refreshCommentSummary = function() {\n        if ($scope.model.task) {\n            var newValue = $scope.model.comments ? $scope.model.comments.data : undefined;\n            $scope.model.commentSummary.loading = false;\n\n            if(newValue) {\n                $scope.model.commentSummary.count = newValue.length;\n            } else {\n                $scope.model.commentSummary.loading = true;\n                $scope.model.commentSummary.count = undefined;\n            }\n        }\n    };\n\n    $scope.refreshSubTaskSummary = function() {\n        if ($scope.model.task) {\n            var newValue = $scope.model.subTasks ? $scope.model.subTasks : undefined;\n            $scope.model.subTaskSummary.loading = false;\n\n            if(newValue) {\n                $scope.model.subTaskSummary.count = newValue.length;\n            } else {\n                $scope.model.subTaskSummary.loading = true;\n                $scope.model.subTaskSummary.count = undefined;\n            }\n        }\n    };\n\n    $scope.dragOverContent = function(over) {\n        if(over && ! $scope.model.contentSummary.addContent) {\n            $scope.model.contentSummary.addContent = true;\n        }\n    };\n\n    $scope.$watch('model.content.data', function(newValue) {\n        if($scope.model.task) {\n        }\n    }, true);\n\n    $scope.loadComments = function() {\n        CommentService.getTaskComments($scope.model.task.id).then(function (data) {\n            $scope.model.comments = data;\n\n            $scope.refreshCommentSummary();\n        });\n    };\n\n    $scope.loadSubTasks = function() {\n        TaskService.getSubTasks($scope.model.task.id).then(function (data) {\n            $scope.model.subTasks = data;\n\n            $scope.refreshSubTaskSummary();\n        });\n    };\n\n    $scope.toggleCreateComment = function() {\n        if($scope.model.commentSummary.addComment) {\n            $scope.model.commentSummary.newComment = undefined;\n        }\n\n        $scope.model.commentSummary.addComment = ! $scope.model.commentSummary.addComment;\n\n        if($scope.model.commentSummary.addComment) {\n            $timeout(function() {\n                angular.element('.focusable').focus();\n            }, 100);\n\n        }\n    };\n\n    $scope.toggleCreateContent = function() {\n        $scope.model.contentSummary.addContent = ! $scope.model.contentSummary.addContent;\n    };\n\n    $scope.onContentUploaded = function(content) {\n        if ($scope.model.content && $scope.model.content.data) {\n            $scope.model.content.data.push(content);\n            RelatedContentService.addUrlToContent(content);\n            $scope.model.selectedContent = content;\n        }\n        $rootScope.addAlertPromise($translate('TASK.ALERT.RELATED-CONTENT-ADDED', content), 'info');\n        $scope.toggleCreateContent();\n    };\n\n    $scope.onContentDeleted = function(content) {\n        if ($scope.model.content && $scope.model.content.data) {\n            $scope.model.content.data.forEach(function(value, i, arr){\n                if (content === value) {\n                    arr.splice(i, 1);\n                }\n            })\n        }\n    };\n\n    $scope.selectContent = function (content) {\n        if ($scope.model.selectedContent == content) {\n            $scope.model.selectedContent = undefined;\n        } else {\n            $scope.model.selectedContent = content;\n        }\n    };\n\n    $scope.confirmNewComment = function() {\n        $scope.model.commentSummary.loading = true;\n        CommentService.createTaskComment($scope.model.task.id, $scope.model.commentSummary.newComment.trim())\n            .then(function(comment) {\n                $scope.model.commentSummary.newComment = undefined;\n                $scope.model.commentSummary.addComment = false;\n                $scope.model.commentSummary.loading = false;\n                $rootScope.addAlertPromise($translate('TASK.ALERT.COMMENT-ADDED', $scope.model.task));\n                $scope.loadComments();\n            });\n    };\n\n    $scope.$watch('model.task.dueDate', function(newValue, oldValue) {\n        if (!$scope.model.taskUpdating && $scope.model.task) {\n            // Update task due-date\n\n            if (oldValue === null && newValue === null\n                || oldValue === null && newValue === undefined\n                || oldValue === undefined && newValue === undefined\n                || oldValue === undefined && newValue === null) {\n                return;\n            }\n\n            // Normalize the date to midnight\n            if(newValue && newValue !== undefined && newValue.getHours && newValue.getHours() != 23) {\n                newValue.setHours(23);\n                newValue.setMinutes(59);\n                newValue.setSeconds(59);\n                $scope.model.task.dueDate = newValue;\n            }\n\n            if (new Date(oldValue).getTime() != new Date(newValue).getTime() || oldValue != null && newValue != null) {\n                $scope.model.taskUpdating = true;\n                // Explicitly force NULL value when undefined to make sure the null\n                // is sent to the service\n                var data = {\n                    dueDate: newValue ? newValue : null\n                };\n                TaskService.updateTask($scope.model.task.id, data).then(function(response) {\n                    $scope.model.taskUpdating = false;\n                });\n            }\n        }\n    });\n\n    $scope.createTaskInline = function() {\n        if(!$scope.newTask) {\n            $scope.newTask = {\n                name: 'New task',\n                inline: true\n            };\n        }\n    };\n\n    $scope.createProcess = function() {\n        $rootScope.createProcessInstance = true;\n        $scope.openProcessInstance();\n    };\n\n    $scope.selectProcessDefinition = function (definition) {\n        $scope.newProcessInstance.processDefinitionId = definition.id;\n        $scope.newProcessInstance.name = definition.name + ' - ' + new moment().format('MMMM Do YYYY');\n\n        $timeout(function () {\n            angular.element('#start-process-name').focus();\n        }, 20);\n    };\n\n    $scope.closeInlineTaskCreation = function($event) {\n        $scope.newTask = undefined;\n        $event.stopPropagation();\n    };\n\n            $scope.setTaskAssignee = function (user) {\n                $scope.newTask.assignee = user;\n            };\n\n            $scope.createSubTask = function (element) {\n                // Create popover\n                if (!$scope.createTaskPopover) {\n                    $scope.newTask = {\n                        name: 'New task'\n                    };\n\n                    $scope.createTaskPopover = $popover(angular.element(element), {\n                        template: appResourceRoot + 'views/popover/create-task-popover.html',\n                        placement: 'bottom-right',\n                        show: true,\n                        scope: $scope\n                    });\n\n                    $scope.createTaskPopover.$scope.$on('tooltip.hide', function () {\n                        $scope.createTaskPopover.$scope.$destroy();\n                        $scope.createTaskPopover.destroy();\n                        $scope.createTaskPopover = undefined;\n\n                        $scope.newTask = undefined;\n                    });\n                }\n            };\n\n\n            $scope.confirmTaskCreation = function (newTask) {\n                if (!newTask) {\n                    newTask = $scope.newTask;\n                }\n                if (newTask && newTask.name) {\n                    var taskData = {\n                        name: newTask.name,\n                        description: newTask.description,\n                        assignee: newTask.assignee ? newTask.assignee.id : null\n                    };\n\n                    taskData.parentTaskId = '' + $scope.model.task.id\n\n                    if ($rootScope.activeAppDefinition) {\n                        taskData.category = '' + $rootScope.activeAppDefinition.id;\n                    }\n\n                    newTask.loading = true;\n                    TaskService.createTask(taskData).then(function (task) {\n                        newTask.loading = false;\n\n                        if ($scope.createTaskPopover) {\n                            $scope.createTaskPopover.$scope.$destroy();\n                            $scope.createTaskPopover.destroy();\n                            $scope.createTaskPopover = undefined;\n                        }\n\n                        $rootScope.addAlertPromise($translate('TASK.ALERT.CREATED', task));\n                    });\n                }\n            };\n\n\n            $scope.completeTask = function() {\n        $scope.model.completeButtonDisabled = true;\n        TaskService.completeTask($scope.model.task.id);\n    };\n\n    $scope.claimTask = function() {\n        $scope.model.loading = true;\n        $scope.model.claimButtonDisabled = true;\n        TaskService.claimTask($scope.model.task.id).then(function(data) {\n            // Refetch data on claim success\n            $scope.getTask($scope.model.task.id);\n        });\n    };\n\n    $scope.loadProcessInstance = function() {\n        $http({method: 'GET', url: FLOWABLE.CONFIG.contextRoot + '/app/rest/process-instances/' + $scope.model.task.processInstanceId}).\n            success(function(response, status, headers, config) {\n                $scope.model.processInstance = response;\n            }).\n            error(function(response, status, headers, config) {\n                // Do nothing. User is not allowed to see the process instance\n            });\n    };\n\n    $scope.openProcessInstance = function(id) {\n        $rootScope.root.selectedProcessId = id;\n        var path='';\n        if($rootScope.activeAppDefinition && !FLOWABLE.CONFIG.integrationProfile) {\n            path = \"/apps/\" + $rootScope.activeAppDefinition.id;\n        }\n        $location.path(path + \"/processes\");\n    };\n\n    $scope.loadCaseInstance = function() {\n        $http({method: 'GET', url: FLOWABLE.CONFIG.contextRoot + '/app/rest/case-instances/' + $scope.model.task.scopeId}).\n            success(function(response, status, headers, config) {\n                $scope.model.caseInstance = response;\n            }).\n            error(function(response, status, headers, config) {\n                // Do nothing. User is not allowed to see the process instance\n            });\n    };\n\n    $scope.openCaseInstance = function(id) {\n        $rootScope.root.selectedCaseId = id;\n        var path='';\n        if($rootScope.activeAppDefinition && !FLOWABLE.CONFIG.integrationProfile) {\n            path = \"/apps/\" + $rootScope.activeAppDefinition.id;\n        }\n        $location.path(path + \"/cases\");\n    };\n\n    $scope.openTaskInstance = function(taskId) {\n        $rootScope.root.selectedTaskId = taskId;\n        $scope.refreshFilter();\n    };\n\n    $scope.returnToTaskList = function() {\n        var path='';\n        if($rootScope.activeAppDefinition && !FLOWABLE.CONFIG.integrationProfile) {\n            path = \"/apps/\" + $rootScope.activeAppDefinition.id;\n        }\n        $location.path(path + \"/tasks\");\n    };\n\n    // OLD STUFF\n\n\n    $scope.returnToList = function() {\n        $location.path(\"/tasks\");\n    };\n\n    $scope.loadRelatedContent = function() {\n        $scope.model.content = undefined;\n        TaskService.getRelatedContent($scope.model.task.id).then(function (data) {\n            $scope.model.content = data;\n        });\n    };\n\n    $scope.$watch(\"model.content\", function(newValue) {\n       if(newValue && newValue.data && newValue.data.length > 0) {\n           var needsRefresh = false;\n           for(var i=0; i<newValue.data.length; i++) {\n               var entry =  newValue.data[i];\n               if(!entry.contentAvailable) {\n                   needsRefresh = true;\n                   break;\n               }\n           }\n       }\n    }, true);\n\n    $scope.editComment = function() {\n        $scope.model.editingComment = true;\n    };\n\n    $scope.stopEditComment = function() {\n        $scope.model.editingComment = false;\n    };\n\n\n    $scope.userInvolved = function (user) {\n        var alertData = {\n            firstName: user.firstName,\n            lastName: user.lastName,\n            taskName: $scope.model.task.name\n        };\n\n        TaskService.involveUserInTask(user.id, $scope.model.task.id).then(function() {\n            $rootScope.addAlertPromise($translate('TASK.ALERT.PERSON-INVOLVED',\n                alertData));\n\n            if(!$scope.model.task.involvedPeople) {\n                $scope.model.task.involvedPeople = [user];\n            } else {\n                $scope.model.task.involvedPeople.push(user);\n            }\n\n        });\n    };\n\n    $scope.assigneeSelected = function(user) {\n        var alertData = {\n            firstName: user.firstName,\n            lastName: user.lastName,\n            taskName: $scope.model.task.name\n        };\n\n        TaskService.assignTask($scope.model.task.id, user.id).then(function() {\n            $rootScope.addAlertPromise($translate('TASK.ALERT.ASSIGNED',\n                alertData));\n\n        $scope.model.task.assignee = user;\n        });\n    };\n\n\n    $scope.revealContent = function(content) {\n        $scope.model.activeTab = \"content\";\n        $scope.model.selectedContent = content;\n    };\n\n    $scope.hasDetails = function() {\n\n        if ($scope.model.loading == true\n            || ($scope.model.involvementSummary === null || $scope.model.involvementSummary === undefined || $scope.model.involvementSummary.loading === true)\n            || ($scope.model.contentSummary === null || $scope.model.contentSummary === undefined || $scope.model.contentSummary.loading === true)\n            || ($scope.model.commentSummary === null || $scope.model.commentSummary === undefined || $scope.model.commentSummary.loading === true)\n            || ($scope.model.subTaskSummary === null || $scope.model.subTaskSummary === undefined || $scope.model.subTaskSummary.loading === true) ) {\n            return false;\n        }\n\n        if ($scope.model.task !== null && $scope.model.task !== undefined) {\n\n            // Returning true by default, or the screen will flicker until all the data (people/comments/content) have been fetched\n            var hasPeople = false;\n            var hasContent = false;\n            var hasComments = false;\n            var hasSubTasks = false;\n\n            // Involved people\n            if ($scope.model.task.involvedPeople !== null\n                && $scope.model.task.involvedPeople !== undefined\n                && $scope.model.task.involvedPeople.length > 0) {\n                hasPeople = true;\n            }\n\n            // Content\n            if ($scope.model.content !== null\n                && $scope.model.content !== undefined\n                && $scope.model.content.data.length > 0) {\n                hasContent = true;\n            }\n\n            // Comments\n            if ($scope.model.comments !== null\n                && $scope.model.comments !==undefined\n                && $scope.model.comments.data.length > 0) {\n                hasComments = true;\n            }\n\n            // SubTasks\n            if ($scope.model.subTasks !== null\n                && $scope.model.subTasks !==undefined\n                && $scope.model.subTasks.length > 0) {\n                hasSubTasks = true;\n            }\n\n            return hasPeople || hasContent || hasComments || hasSubTasks;\n\n        }\n        return false;\n    };\n\n        $scope.uploadInProgress = function(state) {\n            if (state !== 'undefined') {\n                $scope.model.uploadInProgress = state;\n            }\n        };\n }]);\n\n\nangular.module('flowableApp')\n    .controller('CreateTaskController', ['$rootScope', '$scope', '$translate', '$http', '$location', 'TaskService',\n        function ($rootScope, $scope, $translate, $http, $location, TaskService) {\n\n            $scope.createTask = function() {\n                TaskService.createTask($scope.newTask).then(function(createdTask) {\n                    $scope.resetModel();\n                    $rootScope.addAlertPromise($translate('TASK.ALERT.CREATED', createdTask));\n                });\n            };\n\n            $scope.resetModel = function() {\n                $scope.newTask = {\n                    name: '',\n                    description: ''\n                };\n            };\n\n            $scope.resetModel();\n\n        }\n]);\n\nangular.module('flowableApp')\n    .controller('ContentDetailsController', ['$rootScope', '$scope', '$translate', '$modal', 'appResourceRoot', 'RelatedContentService',\n        function ($rootScope, $scope, $translate, $modal, appResourceRoot, RelatedContentService) {\n\n            $scope.model = {\n                selectedContent: $scope.content,\n                selectedTask : $scope.task\n            };\n\n            // Map simple-type to readable content type name\n            var translateKey;\n            if($scope.content) {\n                translateKey = \"CONTENT.SIMPLE-TYPE.\" + $scope.content.simpleType.toUpperCase();\n            } else {\n                translateKey = \"CONTENT.SIMPLE-TYPE.CONTENT\";\n            }\n\n            $translate(translateKey).then(function(message) {\n                $scope.model.contentType = message;\n            });\n\n            $scope.getPdfViewerUrl = function(content) {\n                var urlEncoded = encodeURIComponent(content.pdfUrl);\n\n                return appResourceRoot + 'views/templates/viewer.html?file=' + urlEncoded;\n            };\n\n            $scope.deleteContent = function(content, task) {\n                var modalInstance = _internalCreateModal({\n                    template: appResourceRoot + 'views/modal/delete-content.html',\n                    show: true\n                }, $modal, $scope);\n\n                modalInstance.$scope.popup = {\n                    content: content,\n                    loading: false\n                };\n\n                modalInstance.$scope.ok = function() {\n                    RelatedContentService.deleteContent(content.id, task && task.id).then(function() {\n                        $scope.$emit('content-deleted', {content: content});\n                        $scope.model.selectedContent = null;\n                        $scope.model.selectedTask = null;\n                    });\n                };\n            };\n        }\n]);\n"
  },
  {
    "path": "flowable-ui-web/task/workflow/scripts/controllers/tasks.js",
    "content": "/* 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'use strict';\n\nangular.module('flowableApp')\n  .controller('TasksController', ['$rootScope', '$scope', '$translate', '$http', '$timeout','$location', '$modal', '$popover', 'appResourceRoot', 'CommentService', 'TaskService', '$routeParams', 'AppDefinitionService',\n        function ($rootScope, $scope, $translate, $http, $timeout, $location, $modal, $popover, appResourceRoot, CommentService, TaskService, $routeParams, AppDefinitionService) {\n\n            // Ensure correct main page is set\n            $rootScope.setMainPageById('tasks');\n\n            $scope.model = {\n                page: 0,\n                initialLoad: false\n            };\n\n            // Init sort options\n            $scope.model.sorts = [\n                { id: 'created-desc', title: 'TASK.FILTER.CREATED-DESC' },\n                { id: 'created-asc', title: 'TASK.FILTER.CREATED-ASC' },\n                { id: 'due-desc', title: 'TASK.FILTER.DUE-DESC' },\n                { id: 'due-asc', title: 'TASK.FILTER.DUE-ASC' }\n            ];\n\n            // Init state options\n            $scope.model.stateFilterOptions = [\n                { id: 'open', title: 'TASK.FILTER.STATE-OPEN' },\n                { id: 'completed', title: 'TASK.FILTER.STATE-COMPLETED' }\n            ];\n\n            // Init assignment options\n            $scope.model.assignmentOptions = [\n                { id: 'involved', title: $translate.instant('TASK.FILTER.ASSIGNMENT-INVOLVED') },\n                { id: 'assignee', title: $translate.instant('TASK.FILTER.ASSIGNMENT-ASSIGNEE') },\n                { id: 'candidate', title: $translate.instant('TASK.FILTER.ASSIGNMENT-CANDIDATE') }\n            ];\n\n            if ($scope.account && $scope.account.groups && $scope.account.groups.length > 0) {\n                for (var i=0; i < $scope.account.groups.length; i++) {\n                    if ($scope.account.groups[i].type == 1) {\n                        $scope.model.assignmentOptions.push({ id: 'group_' + $scope.account.groups[i].id, title: $translate.instant('TASK.FILTER.ASSIGNMENT-GROUP', $scope.account.groups[i]) });\n                    }\n                }\n            }\n\n            // Sets defaults for all filters\n            $scope.resetFilters = function(forcePropagateToRootScope) {\n\n                $scope.model.page = 0;\n\n                // Init empty filter model\n                $scope.model.filter = {\n                    loading: false,\n                    expanded: false,\n                    param: {\n                        state: $scope.model.stateFilterOptions[0],\n                        nonDefaultFilter: false\n                    }\n                };\n\n                // Defaults\n                $scope.model.filter.param.sort = $scope.model.sorts[0].id;\n                $scope.model.filter.param.assignment = $scope.model.assignmentOptions[0].id;\n                $scope.model.filter.param.processDefinitionId = 'default';\n\n                $scope.appDefinitionKey = $routeParams.appDefinitionKey;\n                $scope.missingAppdefinition = $scope.appDefinitionKey === false;\n\n                // In case of viewing tasks in an app-context, need to make filter aware of this\n                $scope.model.filter.param.appDefinitionKey = $scope.appDefinitionKey;\n\n                // Propagate to root filter\n                if (forcePropagateToRootScope === true || ($rootScope.taskFilter === null && $rootScope.taskFilter === undefined)) {\n                    $rootScope.taskFilter = { param: $scope.model.filter.param };\n                }\n            };\n\n            $scope.resetFilters(); // First time: init defaults\n\n\n            // The filter is stored on the rootScope, which allows the user to switch back and forth without losing the filter.\n            if ($rootScope.taskFilter !== null && $rootScope.taskFilter !== undefined) {\n                $scope.model.filter.param = $rootScope.taskFilter.param;\n            } else {\n                $rootScope.taskFilter = { param: $scope.model.filter.param };\n            }\n\n            // Update app on rootScope. If app id present, it will fetch definition if not already fetched to update view and navigation accordingly\n            AppDefinitionService.setActiveAppDefinitionKey($scope.appDefinitionKey);\n\n            // Callback for state selection widget\n            $scope.selectStateFilter = function (state) {\n                if(state !== $scope.model.filter.param.state) {\n                    $scope.model.filter.param.state = state;\n                    $scope.collapseFilter();\n                    $scope.resetPaging();\n                    $scope.refreshFilter();\n                }\n            };\n\n            $scope.sortChanged = function() {\n                $scope.resetPaging();\n                $scope.refreshFilter();\n            };\n\n            $scope.nextPage = function() {\n                $scope.model.page = $scope.model.page +1;\n                $scope.refreshFilter();\n            };\n\n            $scope.resetPaging = function() {\n                $scope.model.page = 0;\n            };\n\n            $scope.refreshFilter = function () {\n                $scope.model.filter.loading = true;\n\n                var params = $scope.model.filter.param;\n                params.nonDefaultFilter = false;\n\n                // Assignee\n                var data = {\n                    assignee: $rootScope.account.id,\n                    page: $scope.model.page\n                };\n\n                // Text filter\n                if (params.text) {\n                    data.text = params.text;\n                    params.nonDefaultFilter = true;\n                }\n\n                // State folder\n                if (params.state) {\n                    data.state = params.state.id;\n\n                    if (params.state.id !== 'open') {\n                        params.nonDefaultFilter = true;\n                    }\n                }\n\n                // Assignment\n                if (params.assignment) {\n                    data.assignment = params.assignment;\n\n                    if (params.assignment !== 'involved') {\n                        params.nonDefaultFilter = true;\n                    }\n                }\n\n                // Process definition\n                if (params.processDefinitionId && params.processDefinitionId !== 'default') { // default = empty choice\n                    data.processDefinitionId = params.processDefinitionId;\n                    params.nonDefaultFilter = true;\n                }\n\n                // App definition\n                if (params.appDefinitionKey) {\n                    data.appDefinitionKey = params.appDefinitionKey;\n                }\n\n                // Sort order\n                data.sort = params.sort;\n\n\n                TaskService.queryTasks(data).then(function (response) {\n                    $scope.model.filter.loading = false;\n\n                    if (response.start === 0) {\n                        $scope.model.tasks = response.data;\n\n                        if((!response.data || response.data.length == 0) && !params.nonDefaultFilter) {\n                            $scope.state= {noOwnTasks: true};\n                        } else {\n                            $scope.state= {noOwnTasks: false};\n                        }\n\n                        $scope.selectedTask = $scope.model.tasks[0];\n\n                    } else {\n                        for (var taskIndex=0; taskIndex<response.data.length; taskIndex++) {\n                            $scope.model.tasks.push(response.data[taskIndex]);\n                        }\n                        $scope.state= {noOwnTasks: false};\n\n                        if (!$scope.selectedTask) {\n                            $scope.selectedTask = response.data[0];\n                        }\n                    }\n                    $scope.model.hasNextPage = (response.start + response.size < response.total);\n\n\n                    // If coming from the process page the root.selectedTaskId will be set\n                    var taskIsPartOfCurrentList = false;\n                    if ($rootScope.root.selectedTaskId) {\n                        for (var i = 0; i < response.data.length; i++) {\n                            if (response.data[i].id == $rootScope.root.selectedTaskId) {\n                                taskIsPartOfCurrentList = true;\n                                $scope.selectedTask = response.data[i];\n                                break;\n                            }\n                        }\n\n                        // if the task isn't part of the currently showed list,\n                        // the details are still shown\n                        if (!taskIsPartOfCurrentList) {\n                            // This is kinda cheating, but this way no additional fetch is needed\n                            $scope.selectedTask = { id:  $rootScope.root.selectedTaskId};\n                        }\n\n                        // Always remove the root task id when it was used (otherwise will screw up next calls)\n                        $rootScope.root.selectedTaskId = undefined;\n\n                    } else {\n                        if (!$scope.selectedTask) {\n                            $scope.selectedTask = $scope.model.tasks[0];\n                        }\n                    }\n\n                });\n            };\n\n            $scope.selectTask = function (task) {\n                $scope.selectedTask = task;\n            };\n\n            $scope.createTask = function () {\n                // Create popover\n                if (!$scope.createTaskPopover) {\n                    $scope.newTask = {\n                        name: 'New task'\n                    };\n\n                    $scope.createTaskPopover = $popover(angular.element('#toggle-create-task'), {\n                        template: appResourceRoot+ 'views/popover/create-task-popover.html',\n                        placement: 'bottom-left',\n                        show: true,\n                        scope: $scope\n                    });\n\n                    $scope.createTaskPopover.$scope.$on('tooltip.hide', function () {\n                        $scope.createTaskPopover.$scope.$destroy();\n                        $scope.createTaskPopover.destroy();\n                        $scope.createTaskPopover = undefined;\n\n                        $scope.newTask = undefined;\n                    });\n                }\n            };\n\n            $scope.setTaskAssignee = function (user) {\n                $scope.newTask.assignee = user;\n            };\n\n            $scope.confirmTaskCreation = function (newTask) {\n\n                if(!newTask) {\n                    newTask = $scope.newTask;\n                }\n                if (newTask && newTask.name) {\n                    var taskData = {\n                        name: newTask.name,\n                        description: newTask.description\n                    };\n\n                    if (newTask.assignee && newTask.assignee.id) {\n                        taskData.assignee= newTask.assignee.id;\n                    }\n\n                    if ($rootScope.activeAppDefinition) {\n                        taskData.category = '' + $rootScope.activeAppDefinition.id;\n                    }\n\n                    newTask.loading = true;\n                    TaskService.createTask(taskData).then(function (task) {\n                        newTask.loading = false;\n\n                        if($scope.createTaskPopover) {\n                            $scope.createTaskPopover.$scope.$destroy();\n                            $scope.createTaskPopover.destroy();\n                            $scope.createTaskPopover = undefined;\n                        }\n\n                        $rootScope.addAlertPromise($translate('TASK.ALERT.CREATED', task));\n                    });\n                }\n            };\n\n            $scope.expandFilter = function () {\n                $scope.model.filter.expanded = true;\n            };\n\n            $scope.collapseFilter = function () {\n                $scope.model.filter.expanded = false;\n            };\n\n\n            $scope.$on('task-completed', function (event, data) {\n                $rootScope.addAlertPromise($translate('TASK.ALERT.COMPLETED', data));\n                if (data && data.taskId == $scope.selectedTask.id) {\n                    // Current task has been completed. Refresh the filter\n                    $scope.selectedTask = undefined;\n                    $scope.resetPaging();\n                    $scope.refreshFilter();\n                }\n            });\n\n            $scope.$on('task-saved', function (event, data) {\n                $rootScope.addAlertPromise($translate('TASK.ALERT.SAVED', data));\n            });\n\n            $scope.$on('task-completed-error', function (event, data) {\n                $rootScope.addAlert(data.error.message, 'error');\n            });\n\n            $scope.$on('task-save-error', function (event, data) {\n                $rootScope.addAlert(data.error.message, 'error');\n            });\n\n            // Refreshing list when new task is created\n            $scope.$on(\"new-task-created\", function (event, task) {\n                // New tasks should always be on top, hence the sorting is set to last created\n                $scope.resetFilters(true);\n                $scope.resetPaging();\n                $scope.refreshFilter();\n            });\n\n            // Load process definitions for the filter dropdown\n            $rootScope.loadProcessDefinitions($scope.appDefinitionKey);\n\n            // Add a watch, so we can\n            var unregisterWatch = $scope.$watch('root.processDefinitions', function(data) {\n                if (data !== null && data != undefined && data.length > 0) {\n                    var processDefinitions = data;\n                    processDefinitions.splice(0, 0, {id:'default', name: ''});\n                    $scope.model.processDefinitions = processDefinitions;\n                    unregisterWatch();\n                }\n            });\n\n            // Initial load\n            if (!$rootScope.account) {\n           \t\t$http.get(FLOWABLE.CONFIG.contextRoot + '/app/rest/account')\n                \t.success(function (data, status, headers, config) {\n                      \t$rootScope.account = data;\n                       \t$rootScope.invalidCredentials = false;\n         \t\t\t\t$scope.refreshFilter();\n\n                  \t});\n\n            } else {\n            \t$scope.refreshFilter();\n            }\n\n  }]);\n"
  },
  {
    "path": "flowable-ui-web/task/workflow/scripts/controllers.js",
    "content": "/* 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 */\nflowableApp.controller('AddCommentController', ['$scope', '$location', 'AuthenticationSharedService', '$timeout',\n    function ($scope, $location, AuthenticationSharedService, $timeout) {\n\n      $scope.popupModel = {\n          newComment: '',\n          added: false\n      };\n\n      $scope.createComment = function() {\n          $scope.popupModel.added = true;\n          $scope.$emit(\"new-comment-confirm\", $scope.popupModel.newComment);\n\n          // Popover directive doesn't expose hiding from parent scopes, no other way\n          if($scope.$$childHead) {\n              $scope.$$childHead.$hide();\n          }\n      };\n\n      $scope.$on('tooltip.hide', function() {\n        if($scope.popupModel.added) {\n            $scope.popupModel.added = false;\n        } else {\n            $scope.$emit(\"new-comment-cancelled\", $scope.popupModel.newComment);\n        }\n      });\n    }]\n);"
  },
  {
    "path": "flowable-ui-web/task/workflow/scripts/services/app-definition-service.js",
    "content": "/* 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'use strict';\n\n// Comment service\nangular.module('flowableApp').service('AppDefinitionService', ['$http', '$q', '$rootScope', '$location', '$translate',\n    function ($http, $q, $rootScope, $location, $translate) {\n\n        var httpAsPromise = function(options) {\n            var deferred = $q.defer();\n            $http(options).\n                success(function (response, status, headers, config) {\n                    deferred.resolve(response);\n                })\n                .error(function (response, status, headers, config) {\n                    deferred.reject(response);\n                });\n            return deferred.promise;\n        };\n\n\n        /**\n         * Set the deployment key of the app that should be used. In case the app definition\n         * is not yet cached, it will be fetched.\n         *\n         * Updating this value will be reflected in the header, to make user aware of a change of context.\n         */\n        this.setActiveAppDefinitionKey = function(appDefinitionKey) {\n            if (appDefinitionKey) {\n                if ($rootScope.appDefinitions[appDefinitionKey]) {\n                    $rootScope.activeAppDefinition = $rootScope.appDefinitions[appDefinitionKey];\n                } else {\n                    // Add placeholder with ID only, and fetch the actual object\n                    $rootScope.activeAppDefinition = {id: appDefinitionKey};\n                    $rootScope.appDefinitions[appDefinitionKey] = $rootScope.activeAppDefinition\n                    this.getAppDefinition(appDefinitionKey).then(function(result) {\n                        $rootScope.appDefinitions[result.id] = result;\n\n                        // Also update the active definition, if the fetched definition id matches the active one\n                        if($rootScope.activeAppDefinition && $rootScope.activeAppDefinition.id == result.id) {\n                            $rootScope.activeAppDefinition = result;\n                        }\n                    }, function() {\n                        // When app definition cannot be found, show error and redirect to start page\n                        $rootScope.addAlertPromise($translate('APP-DEFINITION.MESSAGE.NOT-FOUND'), 'error');\n                        $location.path(\"/\");\n\n                    });\n                }\n            } else {\n                // Clear active app-definition\n                $rootScope.activeAppDefinition = undefined;\n            }\n        };\n\n        this.getAppDefinition = function (appDefinitionKey) {\n            return httpAsPromise({\n                method: 'GET',\n                url: FLOWABLE.CONFIG.contextRoot + '/app/rest/runtime/app-definitions/' + appDefinitionKey\n            });\n        };\n\n    }]);\n"
  },
  {
    "path": "flowable-ui-web/task/workflow/scripts/services/case-service.js",
    "content": "/* 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'use strict';\n\n// Task service\nangular.module('flowableApp').service('CaseService', ['$http', '$q', '$rootScope', 'RelatedContentService',\n    function ($http, $q, $rootScope, RelatedContentService) {\n\n        var httpAsPromise = function(options) {\n            var deferred = $q.defer();\n            $http(options).\n                success(function (response, status, headers, config) {\n                    deferred.resolve(response);\n                })\n                .error(function (response, status, headers, config) {\n                    deferred.reject(response);\n                });\n            return deferred.promise;\n        };\n\n        this.getCaseDefinitions = function(appDefinitionKey) {\n            var url = FLOWABLE.CONFIG.contextRoot + '/app/rest/case-definitions?latest=true';\n            if (appDefinitionKey) {\n                url += '&appDefinitionKey=' + appDefinitionKey;\n            }\n            return httpAsPromise(\n                {\n                    method: 'GET',\n                    url: url\n                }\n            );\n        };\n\n    this.getRelatedContent = function (caseId) {\n        var deferred = $q.defer();\n        $http({\n            method: 'GET',\n            url: FLOWABLE.CONFIG.contextRoot + '/app/rest/case-instances/' + caseId + '/content'\n        }).success(function (response, status, headers, config) {\n            // Add raw URL property to all content\n            if (response && response.data) {\n                for (var i = 0; i < response.data.length; i++) {\n                    RelatedContentService.addUrlToContent(response.data[i]);\n                }\n            }\n            deferred.resolve(response);\n        })\n            .error(function (response, status, headers, config) {\n                deferred.reject(response);\n            });\n        return deferred.promise;\n    };\n\n\n    this.createCase = function(caseData) {\n            var deferred = $q.defer();\n            $http({\n                method: 'POST',\n                url: FLOWABLE.CONFIG.contextRoot + '/app/rest/case-instances',\n                data: caseData\n            }).success(function (response, status, headers, config) {\n                $rootScope.$broadcast('new-case-created', response);\n                deferred.resolve(response);\n            }).error(function (response, status, headers, config) {\n                $rootScope.addAlert(response.message, 'error');\n                deferred.reject(response);\n            });\n\n            var promise = deferred.promise;\n            return promise;\n        };\n\n        this.deleteCase = function(caseInstanceId) {\n            var deferred = $q.defer();\n            $http({\n                method: 'DELETE',\n                url: FLOWABLE.CONFIG.contextRoot + '/app/rest/case-instances/' + caseInstanceId\n            }).success(function (response, status, headers, config) {\n                $rootScope.$broadcast('caseinstance-deleted', response);\n                deferred.resolve(response);\n            }).error(function (response, status, headers, config) {\n                $rootScope.addAlert(response.message, 'error');\n                deferred.reject(response);\n            });\n\n            var promise = deferred.promise;\n            return promise;\n        }\n    }]\n);\n"
  },
  {
    "path": "flowable-ui-web/task/workflow/scripts/services/cmmn-milestone-service.js",
    "content": "/* 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'use strict';\n\n// Milestone service\nangular.module('flowableApp').service('MilestoneService', ['$http', '$q', '$rootScope',\n    function ($http, $q, $rootScope) {\n        var httpAsPromise = function (options) {\n            var deferred = $q.defer();\n            $http(options).success(function (response, status, headers, config) {\n                deferred.resolve(response);\n            })\n                .error(function (response, status, headers, config) {\n                    deferred.reject(response);\n                });\n            return deferred.promise;\n        };\n\n        this.getCaseInstanceAvailableMilestones = function (caseInstanceId) {\n\n            var data = {\n                caseInstanceId: caseInstanceId\n            };\n\n            return httpAsPromise(\n                {\n                    method: 'GET',\n                    url: FLOWABLE.CONFIG.contextRoot + '/app/rest/case-instances/' + caseInstanceId + '/available-milestones',\n                    data: data\n                }\n            );\n        };\n\n        this.getCaseInstanceEndedMilestones = function (caseInstanceId) {\n\n            var data = {\n                caseInstanceId: caseInstanceId\n            };\n\n            return httpAsPromise(\n                {\n                    method: 'GET',\n                    url: FLOWABLE.CONFIG.contextRoot + '/app/rest/case-instances/' + caseInstanceId + '/ended-milestones',\n                    data: data\n                }\n            );\n        };\n\n    }]);\n\n"
  },
  {
    "path": "flowable-ui-web/task/workflow/scripts/services/cmmn-plan-item-instance-service.js",
    "content": "/* 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'use strict';\n\n// Plan item instance service\nangular.module('flowableApp').service('PlanItemInstanceService', ['$http', '$q', '$rootScope',\n    function ($http, $q, $rootScope) {\n        var httpAsPromise = function (options) {\n            var deferred = $q.defer();\n            $http(options)\n                .success(function (response, status, headers, config) {\n                    deferred.resolve(response);\n                })\n                .error(function (response, status, headers, config) {\n                    deferred.reject(response);\n                });\n            return deferred.promise;\n        };\n\n        this.getCaseInstanceEnabledPlanItemInstances = function (caseInstanceId) {\n            return httpAsPromise(\n                {\n                    method: 'GET',\n                    url: FLOWABLE.CONFIG.contextRoot + '/app/rest/case-instances/' + caseInstanceId + '/enabled-planitem-instances'\n                }\n            );\n        };\n\n        this.startPlanItemInstance = function (caseInstanceId, planItemInstanceId) {\n            var deferred = $q.defer();\n            $http({\n                method: 'POST',\n                url: FLOWABLE.CONFIG.contextRoot + '/app/rest/case-instances/' + caseInstanceId + '/enabled-planitem-instances/' + planItemInstanceId\n            }).success(function (response, status, headers, config) {\n                $rootScope.$broadcast('user-event-listener-triggered', response);\n                deferred.resolve(response);\n            }).error(function (response, status, headers, config) {\n                $rootScope.addAlert(response.message, 'error');\n                deferred.reject(response);\n            });\n\n            return deferred.promise;\n        };\n    }]);\n\n"
  },
  {
    "path": "flowable-ui-web/task/workflow/scripts/services/cmmn-stage-service.js",
    "content": "/* 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'use strict';\n\n// Milestone service\nangular.module('flowableApp').service('StageService', ['$http', '$q', '$rootScope',\n    function ($http, $q, $rootScope) {\n        var httpAsPromise = function (options) {\n            var deferred = $q.defer();\n            $http(options).success(function (response, status, headers, config) {\n                deferred.resolve(response);\n            })\n                .error(function (response, status, headers, config) {\n                    deferred.reject(response);\n                });\n            return deferred.promise;\n        };\n\n        this.getCaseInstanceActiveStages = function (caseInstanceId) {\n\n            var data = {\n                caseInstanceId: caseInstanceId\n            };\n\n            return httpAsPromise(\n                {\n                    method: 'GET',\n                    url: FLOWABLE.CONFIG.contextRoot + '/app/rest/case-instances/' + caseInstanceId + '/active-stages',\n                    data: data\n                }\n            );\n        };\n\n        this.getCaseInstanceEndedStages = function (caseInstanceId) {\n\n            var data = {\n                caseInstanceId: caseInstanceId\n            };\n\n            return httpAsPromise(\n                {\n                    method: 'GET',\n                    url: FLOWABLE.CONFIG.contextRoot + '/app/rest/case-instances/' + caseInstanceId + '/ended-stages',\n                    data: data\n                }\n            );\n        };\n\n    }]);\n\n"
  },
  {
    "path": "flowable-ui-web/task/workflow/scripts/services/cmmn-user-event-listener-service.js",
    "content": "/* 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'use strict';\n\n// Milestone service\nangular.module('flowableApp').service('UserEventListenerService', ['$http', '$q', '$rootScope',\n    function ($http, $q, $rootScope) {\n        var httpAsPromise = function (options) {\n            var deferred = $q.defer();\n            $http(options).success(function (response, status, headers, config) {\n                deferred.resolve(response);\n            })\n                .error(function (response, status, headers, config) {\n                    deferred.reject(response);\n                });\n            return deferred.promise;\n        };\n\n        this.getCaseInstanceAvailableUserEventListeners = function (caseInstanceId) {\n\n            var data = {\n                caseInstanceId: caseInstanceId\n            };\n\n            return httpAsPromise(\n                {\n                    method: 'GET',\n                    url: FLOWABLE.CONFIG.contextRoot + '/app/rest/case-instances/' + caseInstanceId + '/available-user-event-listeners',\n                    data: data\n                }\n            );\n        };\n\n        this.getCaseInstanceCompletedUserEventListeners = function (caseInstanceId) {\n\n            var data = {\n                caseInstanceId: caseInstanceId\n            };\n\n            return httpAsPromise(\n                {\n                    method: 'GET',\n                    url: FLOWABLE.CONFIG.contextRoot + '/app/rest/case-instances/' + caseInstanceId + '/completed-user-event-listeners',\n                    data: data\n                }\n            );\n        };\n\n        this.triggerCaseInstanceUserEventListener = function (caseInstanceId, userEventListenerId) {\n\n            var deferred = $q.defer();\n            var data = {\n                caseInstanceId: caseInstanceId,\n                userEventListener: userEventListenerId\n            };\n\n            $http({\n                method: 'POST',\n                url: FLOWABLE.CONFIG.contextRoot + '/app/rest/case-instances/' + caseInstanceId + '/trigger-user-event-listener/' + userEventListenerId,\n                data: data\n            }).success(function (response, status, headers, config) {\n                $rootScope.$broadcast('user-event-listener-triggered', response);\n                deferred.resolve(response);\n            }).error(function (response, status, headers, config) {\n                $rootScope.addAlert(response.message, 'error');\n                deferred.reject(response);\n            });\n\n            var promise = deferred.promise;\n            return promise;\n        };\n    }]);\n\n"
  },
  {
    "path": "flowable-ui-web/task/workflow/scripts/services/comment-service.js",
    "content": "/* 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'use strict';\n\n// Comment service\nangular.module('flowableApp').service('CommentService', ['$http', '$q',\n    function ($http, $q) {\n\n        /*\n         * Get all comments on a task\n         */\n        this.getTaskComments = function (taskId) {\n\n            var deferred = $q.defer();\n\n            $http({method: 'GET', url: FLOWABLE.CONFIG.contextRoot + '/app/rest/tasks/' + taskId + '/comments', params: {latestFirst: true}}).\n                success(function (response, status, headers, config) {\n                    deferred.resolve(response);\n                })\n                .error(function (response, status, headers, config) {\n                    deferred.reject(response);\n                });\n\n            return deferred.promise;\n        };\n\n        /*\n         * Create a new comment on a task\n         */\n        this.createTaskComment = function (taskId, message) {\n            var deferred = $q.defer();\n\n            var data = {message: message};\n            $http({method: 'POST', url: FLOWABLE.CONFIG.contextRoot + '/app/rest/tasks/' + taskId + '/comments', data: data}).\n                success(function (response, status, headers, config) {\n                    deferred.resolve(response);\n                })\n                .error(function (response, status, headers, config) {\n                    deferred.reject(response);\n                });\n\n            var promise = deferred.promise;\n            return promise;\n        };\n        \n        /*\n         * Get all comments on a process instance\n         */\n        this.getProcessInstanceComments = function (processInstanceId) {\n\n            var deferred = $q.defer();\n\n            $http({method: 'GET', url: FLOWABLE.CONFIG.contextRoot + '/app/rest/process-instances/' + processInstanceId + '/comments', params: {latestFirst: true}}).\n                success(function (response, status, headers, config) {\n                    deferred.resolve(response);\n                })\n                .error(function (response, status, headers, config) {\n                    deferred.reject(response);\n                });\n\n            return deferred.promise;\n        };\n\n        /*\n         * Create a new comment on a process instance\n         */\n        this.createProcessInstanceComment = function (processInstanceId, message) {\n            var deferred = $q.defer();\n\n            var data = {message: message};\n            $http({method: 'POST', url: FLOWABLE.CONFIG.contextRoot + '/app/rest/process-instances/' + processInstanceId + '/comments', data: data}).\n                success(function (response, status, headers, config) {\n                    deferred.resolve(response);\n                })\n                .error(function (response, status, headers, config) {\n                    deferred.reject(response);\n                });\n\n            var promise = deferred.promise;\n            return promise;\n        };\n\n    }]);\n"
  },
  {
    "path": "flowable-ui-web/task/workflow/scripts/services/form-service.js",
    "content": "/* 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'use strict';\n\n// Task service\nangular.module('flowableApp').service('FormService', ['$http', '$q',\n    function ($http, $q) {\n\n        var httpAsPromise = function(options) {\n            var deferred = $q.defer();\n            $http(options).\n                success(function (response, status, headers, config) {\n                    deferred.resolve(response);\n                })\n                .error(function (response, status, headers, config) {\n                    deferred.reject(response);\n                });\n            return deferred.promise;\n        };\n\n        this.getTaskForm = function(taskId) {\n\n            return httpAsPromise(\n                {\n                    method: 'GET',\n                    url: FLOWABLE.CONFIG.contextRoot + '/app/rest/task-forms/' + taskId\n                }\n            );\n        };\n\n        this.completeTaskForm = function(taskId, data) {\n\n            var promise = httpAsPromise(\n                {\n                    method: 'POST',\n                    url: FLOWABLE.CONFIG.contextRoot + '/app/rest/task-forms/' + taskId,\n                    data: data\n                }\n            );\n\n            return promise;\n        };\n\n        this.saveTaskForm = function(taskId, data) {\n\n            var promise = httpAsPromise(\n                {\n                    method: 'POST',\n                    url: FLOWABLE.CONFIG.contextRoot + '/app/rest/task-forms/' + taskId + '/save-form',\n                    data: data\n                }\n            );\n\n            return promise;\n        };\n\n        this.getStartForm = function(processDefinitionId) {\n\n            return httpAsPromise(\n                {\n                    method: 'GET',\n                    url: FLOWABLE.CONFIG.contextRoot + '/app/rest/process-definitions/' + processDefinitionId + \"/start-form\"\n                }\n            );\n        };\n\n        this.completeStartForm = function(data) {\n\n            var promise = httpAsPromise(\n                {\n                    method: 'POST',\n                    url: FLOWABLE.CONFIG.contextRoot + '/app/rest/process-instances/',\n                    data: data\n                }\n            );\n\n            return promise;\n        };\n\n        this.getCaseStartForm = function(caseDefinitionId) {\n\n            return httpAsPromise(\n                {\n                    method: 'GET',\n                    url: FLOWABLE.CONFIG.contextRoot + '/app/rest/case-definitions/' + caseDefinitionId + \"/start-form\"\n                }\n            );\n        };\n\n        this.completeCaseStartForm = function(data) {\n\n            var promise = httpAsPromise(\n                {\n                    method: 'POST',\n                    url: FLOWABLE.CONFIG.contextRoot + '/app/rest/case-instances/',\n                    data: data\n                }\n            );\n\n            return promise;\n        };\n\n\n\n    }]);\n"
  },
  {
    "path": "flowable-ui-web/task/workflow/scripts/services/process-service.js",
    "content": "/* 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'use strict';\n\n// Task service\nangular.module('flowableApp').service('ProcessService', ['$http', '$q', '$rootScope', 'RelatedContentService',\n    function ($http, $q, $rootScope, RelatedContentService) {\n\n        var httpAsPromise = function(options) {\n            var deferred = $q.defer();\n            $http(options).\n                success(function (response, status, headers, config) {\n                    deferred.resolve(response);\n                })\n                .error(function (response, status, headers, config) {\n                    deferred.reject(response);\n                });\n            return deferred.promise;\n        };\n\n        this.getProcessDefinitions = function(appDefinitionKey) {\n            var url = FLOWABLE.CONFIG.contextRoot + '/app/rest/process-definitions?latest=true';\n            if (appDefinitionKey) {\n                url += '&appDefinitionKey=' + appDefinitionKey;\n            }\n            return httpAsPromise(\n                {\n                    method: 'GET',\n                    url: url\n                }\n            );\n        };\n\n        this.createProcess = function(processData) {\n            var deferred = $q.defer();\n            $http({\n                method: 'POST',\n                url: FLOWABLE.CONFIG.contextRoot + '/app/rest/process-instances',\n                data: processData\n            }).success(function (response, status, headers, config) {\n                $rootScope.$broadcast('new-process-created', response);\n                deferred.resolve(response);\n            }).error(function (response, status, headers, config) {\n                $rootScope.addAlert(response.message, 'error');\n                deferred.reject(response);\n            });\n\n            var promise = deferred.promise;\n            return promise;\n        };\n\n        this.deleteProcess = function(processInstanceId) {\n            var deferred = $q.defer();\n            $http({\n                method: 'DELETE',\n                url: FLOWABLE.CONFIG.contextRoot + '/app/rest/process-instances/' + processInstanceId\n            }).success(function (response, status, headers, config) {\n                $rootScope.$broadcast('processinstance-deleted', response);\n                deferred.resolve(response);\n            }).error(function (response, status, headers, config) {\n                $rootScope.addAlert(response.message, 'error');\n                deferred.reject(response);\n            });\n\n            var promise = deferred.promise;\n            return promise;\n        }\n    }]\n);\n"
  },
  {
    "path": "flowable-ui-web/task/workflow/scripts/services/task-service.js",
    "content": "/* 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'use strict';\n\n// Task service\nangular.module('flowableApp').service('TaskService', ['$http', '$q', '$rootScope', 'RelatedContentService',\n    function ($http, $q, $rootScope, RelatedContentService) {\n\n        var httpAsPromise = function(options) {\n            var deferred = $q.defer();\n            $http(options).\n                success(function (response, status, headers, config) {\n                    deferred.resolve(response);\n                })\n                .error(function (response, status, headers, config) {\n                    deferred.reject(response);\n                });\n            return deferred.promise;\n        };\n\n        this.getProcessInstanceTasks = function(processInstanceId, isCompleted) {\n\n            var data = {\n                processInstanceId: processInstanceId\n            };\n\n            if (isCompleted) {\n                data.state = 'completed'\n            }\n\n            return httpAsPromise(\n                {\n                    method: 'POST',\n                    url: FLOWABLE.CONFIG.contextRoot + '/app/rest/query/tasks',\n                    data: data\n                }\n            );\n        };\n\n        this.getCaseInstanceTasks = function(caseInstanceId, isCompleted) {\n\n            var data = {\n                caseInstanceId: caseInstanceId\n            };\n\n            if (isCompleted) {\n                data.state = 'completed'\n            }\n\n            return httpAsPromise(\n                {\n                    method: 'POST',\n                    url: FLOWABLE.CONFIG.contextRoot + '/app/rest/query/tasks',\n                    data: data\n                }\n            );\n        };\n\n        this.involveUserInTask = function(userId, taskId) {\n\n            var involveData = {\n                userId: userId\n            };\n\n            var promise = httpAsPromise(\n                {\n                    method: 'PUT',\n                    url: FLOWABLE.CONFIG.contextRoot + '/app/rest/tasks/' + taskId + '/action/involve',\n                    data: involveData\n                }\n            );\n\n            return promise;\n        };\n\n        this.involveUserInTaskByEmail = function(email, taskId) {\n\n            var involveData = {\n                email: email\n            };\n\n            var promise = httpAsPromise(\n                {\n                    method: 'PUT',\n                    url: FLOWABLE.CONFIG.contextRoot + '/app/rest/tasks/' + taskId + '/action/involve',\n                    data: involveData\n                }\n            );\n\n            return promise;\n        };\n\n        this.removeInvolvedUserInTask = function(user, taskId) {\n\n            var removeInvolvedData = {};\n            if (user.id !== null && user.id !== undefined) {\n                removeInvolvedData.userId = user.id;\n            } else {\n                removeInvolvedData.email = user.email;\n            }\n\n            var promise = httpAsPromise(\n                {\n                    method: 'PUT',\n                    url: FLOWABLE.CONFIG.contextRoot + '/app/rest/tasks/' + taskId + '/action/remove-involved',\n                    data: removeInvolvedData\n                }\n            );\n\n            return promise;\n        };\n\n        this.queryTasks = function(data) {\n            return httpAsPromise(\n                {\n                    method: 'POST',\n                    url: FLOWABLE.CONFIG.contextRoot + '/app/rest/query/tasks',\n                    data: data\n                }\n            );\n        };\n\n        /**\n         * Simple completion of a task without submitting form-data.\n         */\n        this.completeTask = function(taskId) {\n            var deferred = $q.defer();\n            $http( {\n                method: 'PUT',\n                url: FLOWABLE.CONFIG.contextRoot + '/app/rest/tasks/' + taskId + '/action/complete'\n            }).\n            success(function (response, status, headers, config) {\n                $rootScope.$broadcast('task-completed', {taskId: taskId});\n                deferred.resolve(response);\n            })\n            .error(function (response, status, headers, config) {\n                $rootScope.addAlert(response.message, 'error');\n                deferred.reject(response);\n            });\n\n            var promise = deferred.promise;\n            return promise;\n        };\n\n        this.claimTask = function(taskId) {\n            var promise = httpAsPromise(\n                {\n                    method: 'PUT',\n                    url: FLOWABLE.CONFIG.contextRoot + '/app/rest/tasks/' + taskId + '/action/claim'\n                }\n            );\n\n            return promise;\n        };\n\n        this.getRelatedContent = function(taskId) {\n            var deferred = $q.defer();\n            $http({\n                method: 'GET',\n                url: FLOWABLE.CONFIG.contextRoot + '/app/rest/tasks/' + taskId + '/content'\n            }).\n            success(function (response, status, headers, config) {\n                // Add raw URL property to all content\n                if(response && response.data) {\n                    for(var i=0; i< response.data.length; i++) {\n                        RelatedContentService.addUrlToContent(response.data[i]);\n                    }\n                }\n                deferred.resolve(response);\n            })\n            .error(function (response, status, headers, config) {\n                deferred.reject(response);\n            });\n            return deferred.promise;\n        };\n\n        /*\n         * Get all subTasks for a task\n         */\n        this.getSubTasks = function (taskId) {\n\n            var deferred = $q.defer();\n\n            $http({\n                method: 'GET',\n                url: FLOWABLE.CONFIG.contextRoot + '/app/rest/tasks/' + taskId + '/subtasks',\n                params: {latestFirst: true}\n            }).success(function (response, status, headers, config) {\n                deferred.resolve(response);\n            })\n                .error(function (response, status, headers, config) {\n                    deferred.reject(response);\n                });\n\n            return deferred.promise;\n        };\n\n        this.assignTask = function(taskId, userId) {\n            var assignData = {\n                assignee: userId\n            };\n\n            var promise = httpAsPromise(\n                {\n                    method: 'PUT',\n                    url: FLOWABLE.CONFIG.contextRoot + '/app/rest/tasks/' + taskId + '/action/assign',\n                    data: assignData\n                }\n            );\n\n            return promise;\n        };\n\n        this.assignTaskByEmail = function(taskId, email) {\n            var promise = httpAsPromise(\n                {\n                    method: 'PUT',\n                    url: FLOWABLE.CONFIG.contextRoot + '/app/rest/tasks/' + taskId + '/action/assign',\n                    data: {email: email}\n                }\n            );\n\n            return promise;\n        };\n\n        this.updateTask = function(taskId, data) {\n            return httpAsPromise(\n                {\n                    method: 'PUT',\n                    url: FLOWABLE.CONFIG.contextRoot + '/app/rest/tasks/' + taskId,\n                    data: data\n                }\n            );\n        };\n\n        this.createTask = function(taskData) {\n            var deferred = $q.defer();\n            $http({\n                method: 'POST',\n                url: FLOWABLE.CONFIG.contextRoot + '/app/rest/tasks',\n                data: taskData\n            }).\n            success(function (response, status, headers, config) {\n                $rootScope.$broadcast('new-task-created', response);\n                deferred.resolve(response);\n            })\n            .error(function (response, status, headers, config) {\n                $rootScope.addAlert(response.message, 'error');\n                deferred.reject(response);\n            });\n\n            var promise = deferred.promise;\n            return promise;\n        };\n\n    }]);\n"
  },
  {
    "path": "flowable-ui-web/task/workflow/scripts/workflow-app.js",
    "content": "/* 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'use strict';\n\nvar flowableApp = angular.module('flowableApp', [\n    'ngCookies',\n    'ngResource',\n    'ngSanitize',\n    'ngRoute',\n    'ngDragDrop',\n    'mgcrea.ngStrap',\n    'ngFileUpload',\n    'ngAnimate',\n    'pascalprecht.translate',\n    'ui.grid',\n    'ui.grid.edit',\n    'ui.grid.selection',\n    'ui.grid.autoResize',\n    'angular-loading-bar',\n    'cfp.hotkeys',\n    'ui.mask'\t \n]);\n\nvar flowableModule = flowableApp;\n\nflowableApp\n\n  // Initialize routes\n   .config(['$provide', '$routeProvider', '$selectProvider', '$datepickerProvider', '$translateProvider', 'cfpLoadingBarProvider',\n   function ($provide, $routeProvider, $selectProvider, $datepickerProvider, $translateProvider, cfpLoadingBarProvider) {\n\n   var appName = 'workflow';\n   $provide.value('appName', appName);\n   var appResourceRoot = FLOWABLE.CONFIG.webContextRoot + (FLOWABLE.CONFIG.webContextRoot ? '/' + appName + '/' : '');\n   $provide.value('appResourceRoot', appResourceRoot);\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    // Override carets for bs-datepicker directive\n    angular.extend($datepickerProvider.defaults, {\n        iconLeft: 'icon icon-caret-left',\n        iconRight: 'icon icon-caret-right'\n    });\n\n    $routeProvider\n        .when('/start-process', {\n            templateUrl: appResourceRoot + 'views/start-process.html',\n            controller: 'StartProcessController'\n        })\n        .when('/apps/:appDefinitionKey/start-process', {\n            templateUrl: appResourceRoot + 'views/start-process.html',\n            controller: 'StartProcessController'\n        })\n        .when('/tasks', {\n            templateUrl: appResourceRoot + 'views/tasks.html',\n            controller: 'TasksController'\n        })\n        .when('/apps/:appDefinitionKey/tasks', {\n            templateUrl: appResourceRoot + 'views/tasks.html',\n            controller: 'TasksController'\n        })\n        .when('/task/:taskId', {\n            templateUrl: appResourceRoot + 'views/task.html',\n            controller: 'TaskController'\n        })\n        .when('/apps/:appDefinitionKey/task/:taskId', {\n            templateUrl: appResourceRoot + 'views/task.html',\n            controller: 'TaskController'\n        })\n        .when('/processes', {\n            templateUrl: appResourceRoot + 'views/processes.html',\n            controller: 'ProcessesController'\n        })\n        .when('/apps/:appDefinitionKey/processes', {\n            templateUrl: appResourceRoot + 'views/processes.html',\n            controller: 'ProcessesController'\n        })\n        .when('/process/:processId', {\n            templateUrl: appResourceRoot + 'views/process.html',\n            controller: 'ProcessController'\n        })\n        .when('/apps/:appDefinitionKey/process/:processId', {\n            templateUrl: appResourceRoot + 'views/process.html',\n            controller: 'ProcessController'\n        })\n        .when('/cases', {\n            templateUrl: appResourceRoot + 'views/cases.html',\n            controller: 'CasesController'\n        })\n        .when('/apps/:appDefinitionKey/cases', {\n            templateUrl: appResourceRoot + 'views/cases.html',\n            controller: 'CasesController'\n        })\n        .when('/apps/:appDefinitionKey/case/:caseId', {\n            templateUrl: appResourceRoot + 'views/case.html',\n            controller: 'CaseController'\n        })\n        .otherwise({\n            redirectTo: FLOWABLE.CONFIG.appDefaultRoute || '/tasks'\n        });\n\n        // Initialize angular-translate\n        $translateProvider.useStaticFilesLoader({\n           prefix: './i18n/',\n           suffix: '.json'\n        })\n        /*\n        This can be used to map multiple browser language keys to a\n        angular translate language key.\n        */\n        // .registerAvailableLanguageKeys(['en'], {\n        //     'en-*': 'en'\n        // })\n        .useSanitizeValueStrategy('escapeParameters')\n        .uniformLanguageTag('bcp47')\n        .determinePreferredLanguage();\n\n       // turn loading bar spinner off (angular-loading-bar lib)\n       cfpLoadingBarProvider.includeSpinner = false;\n    }])\n    .run(['$rootScope', '$routeParams', '$timeout', '$translate', '$location', '$http', '$window', 'appResourceRoot', 'AppDefinitionService', 'ProcessService', 'CaseService',\n        function($rootScope, $routeParams, $timeout, $translate, $location, $http, $window, appResourceRoot, AppDefinitionService, ProcessService, CaseService) {\n\n        // set angular translate fallback language\n        $translate.fallbackLanguage(['en']);\n\n        // setting Moment-JS (global) locale\n        if (FLOWABLE.CONFIG.datesLocalization) {\n            moment.locale($translate.proposedLanguage());\n        }\n\n        $rootScope.restRootUrl = function() {\n            return FLOWABLE.CONFIG.contextRoot;\n        };\n\n        $rootScope.config = FLOWABLE.CONFIG;\n        $rootScope.appResourceRoot = appResourceRoot;\n        $rootScope.activitiFieldIdPrefix = 'activiti-';\n\n        $rootScope.window = {};\n        var updateWindowSize = function() {\n            $rootScope.window.width = $window.innerWidth;\n            $rootScope.window.height  = $window.innerHeight;\n        };\n\n        // Window resize hook\n        angular.element($window).bind('resize', function() {\n            $rootScope.$apply(updateWindowSize());\n        });\n\n        $rootScope.$watch('window.forceRefresh', function(newValue) {\n            if(newValue) {\n                $timeout(function() {\n                    updateWindowSize();\n                    $rootScope.window.forceRefresh = false;\n                });\n            }\n        });\n\n        updateWindowSize();\n\n        // Main navigation\n        $rootScope.mainNavigation = [\n            {\n                'id': 'tasks',\n                'title': 'GENERAL.NAVIGATION.TASKS',\n                'path': '/tasks'\n            },\n            {\n                'id': 'processes',\n                'title': 'GENERAL.NAVIGATION.PROCESSES',\n                'path': '/processes'\n            },\n            {\n                'id': 'cases',\n                'title': 'GENERAL.NAVIGATION.CASES',\n                'path': '/cases'\n            }\n        ];\n\n        $rootScope.mainPage = $rootScope.mainNavigation[0];\n\n        // Empty object to hold cached app-definitions\n        $rootScope.appDefinitions = {\n\n        };\n\n        /*\n         * Set the current main page, using the page object. If the page is already active,\n         * this is a no-op.\n         */\n        $rootScope.setMainPage = function(mainPage) {\n            $rootScope.mainPage = mainPage;\n\n            var path;\n            if($rootScope.activeAppDefinition) {\n                path = \"/apps/\" + $rootScope.activeAppDefinition.id + mainPage.path;\n            } else {\n                path = $rootScope.mainPage.path;\n            }\n            $location.path(path);\n        };\n\n        /*\n         * Set the current main page, using the page ID. If the page is already active,\n         * this is a no-op.\n         */\n        $rootScope.setMainPageById = function(mainPageId) {\n            for (var i=0; i<$rootScope.mainNavigation.length; i++) {\n                if (mainPageId == $rootScope.mainNavigation[i].id) {\n                    $rootScope.mainPage = $rootScope.mainNavigation[i];\n                    break;\n                }\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        $http.get(FLOWABLE.CONFIG.contextRoot + '/app/rest/account')\n        \t.success(function (data, status, headers, config) {\n              \t$rootScope.account = data;\n               \t$rootScope.invalidCredentials = false;\n \t\t\t\t$rootScope.authenticated = true;\n          \t});\n\n        $rootScope.model = {};\n        // TODO: remove proc-def from rootscope or make smarter\n        $rootScope.root = {};\n\n        $rootScope.loadProcessDefinitions = function(appDefinitionKey) {\n        \tProcessService.getProcessDefinitions(appDefinitionKey).then(function(response) {\n        \t\t$rootScope.root.processDefinitions = response.data;\n        \t});\n        };\n        \n        $rootScope.loadCaseDefinitions = function(appDefinitionKey) {\n            CaseService.getCaseDefinitions(appDefinitionKey).then(function(response) {\n                $rootScope.root.caseDefinitions = response.data;\n            });\n        };\n\n        $rootScope.$on(\"$locationChangeStart\",\n            function (event, newUrl, oldUrl) {\n                if(newUrl.indexOf(\"headless\") >= 0) {\n                    $rootScope.root.headless = true;\n                } else {\n                    $rootScope.root.headless = false;\n                }\n            }\n        );\n\n        /**\n         * A 'safer' apply that avoids concurrent updates (which $apply allows).\n         */\n        $rootScope.safeApply = function(fn) {\n            var phase = this.$root.$$phase;\n            if(phase == '$apply' || phase == '$digest') {\n                if(fn && (typeof(fn) === 'function')) {\n                    fn();\n                }\n            } else {\n                this.$apply(fn);\n            }\n        };\n\n        $rootScope.logout = function () {\n            $rootScope.authenticated = false;\n            $rootScope.authenticationError = false;\n            $http.get(FLOWABLE.CONFIG.contextRoot + '/app/logout')\n                .success(function (data, status, headers, config) {\n                    $rootScope.login = null;\n                    $rootScope.authenticated = false;\n                    $window.location.href = '/';\n                    $window.location.reload();\n                });\n        };\n\n    }\n  ])\n  .run(['$rootScope', '$location', '$window', '$translate', 'appName', '$modal',\n        function($rootScope, $location, $window, $translate, appName , $modal) {\n\n        var fixedUrlPart = '/' + appName + '/';\n\n        $rootScope.backToLanding = function() {\n            var baseUrl = $location.absUrl();\n            var index = baseUrl.indexOf(fixedUrlPart);\n            if (index >= 0) {\n                baseUrl = baseUrl.substring(0, index) + '/';\n            }\n            $window.location.href = baseUrl;\n        };\n    }])\n\n    // Moment-JS date-formatting filter\n    .filter('dateformat', function() {\n        return function(date, format) {\n            if (date) {\n                if(format == 'fromNow') {\n                    return moment(date).fromNow();\n                } else if(format == 'fromNowFull') {\n                    return moment(date).fromNow() + ' (' + moment(date).format('MMMM Do YYYY') + ')';\n                } else if (format) {\n                    return moment(date).format(format);\n                } else {\n                    return moment(date).calendar();\n                }\n            }\n            return '';\n        };\n    })\n    .filter('duration', ['$translate', function($translate) {\n        return function(millis) {\n            if (millis) {\n                var duration = moment.duration(millis);\n                var result = '';\n                var hours = duration.hours();\n                if (hours > 0) {\n                    result = result + hours + ' ' + $translate.instant('GENERAL.TIME.HOURS') + ' ';\n                }\n                var mins = duration.minutes();\n                if (mins > 0) {\n                    result = result + mins + ' ' + $translate.instant('GENERAL.TIME.MINUTES');\n                }\n\n                if (hours == 0 && mins == 0) {\n                    result = duration.seconds() + ' ' + $translate.instant('GENERAL.TIME.SECONDS');\n\n                }\n\n                return result;\n            }\n            return millis;\n        };\n    }])\n    .filter('username', function() {\n        return function(user) {\n            if (user) {\n               if(user.firstName) {\n                   return user.firstName + \" \" + user.lastName;\n               } else if(user.lastName) {\n                   return user.lastName;\n               } else {\n\t\t\t       if (user != undefined && user != null){\n\t\t\t\t       var _user = user.split(\".\");\n\t\t\t\t\t   if (_user.length > 1){\n\t\t\t\t\t       user = _user[0].charAt(0).toUpperCase() + _user[0].slice(1) +\" \"+ _user[1].charAt(0).toUpperCase() + _user[1].slice(1);\n\t\t\t\t\t   } else {\n\t\t\t\t\t\t   user = _user[0].charAt(0).toUpperCase() + _user[0].slice(1);\n\t\t\t\t\t   }\n\t\t\t\t\t   return user;\n\t\t\t\t\t   \n\t\t\t\t   } else {\n\t\t\t\t\t   return \"??\";\n\t\t\t       }\n\t\t\t   }\n            }\n            return '';\n        };\n    });\n"
  },
  {
    "path": "flowable-ui-web/task/workflow/scripts/workflow-directives.js",
    "content": "/* 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 */\nangular.module('flowableApp').directive('documentPreview', ['$parse', 'appResourceRoot', function ($parse, appResourceRoot) {\n    return {\n        restrict: 'E',\n        templateUrl: appResourceRoot + 'views/templates/document-preview.html',\n        scope: {\n            content: '=',\n            task: '=',\n            deleted: '&onDelete',\n            editable: '=',\n            readOnly: '='\n        },\n        controller: 'DocumentPreviewController'\n    };\n}]);\n\nangular.module('flowableApp').directive('activitiForm', ['$rootScope', 'appResourceRoot', function ($rootScope, appResourceRoot) {\n    return {\n        restrict: 'E',\n        templateUrl: appResourceRoot + 'views/templates/form-template.html',\n        scope: {\n            taskId : '=taskId',\n            formDefinition: '=formDefinition',\n            processName: '=processName',\n            processDefinitionId: '=processDefinitionId',\n            caseName: '=caseName',\n            caseDefinitionId: '=caseDefinitionId',\n            outcomesOnly: '=outcomesOnly',\n            disableForm: '=disableForm',\n            disableFormText: '=disableFormText',\n            hideButtons: '=hideButtons'\n        },\n        link: function ($scope, element, attributes) {\n            $rootScope.window.forceRefresh = true;\n        }\n    };\n}]);\n\nangular.module('flowableApp').\n    directive('optimalGrid', ['$compile', '$http', function($compile, $http) {\n        var directive = {};\n        directive.restrict = 'A';\n        directive.replace = true;\n        directive.scope = {\n            toWatch : \"=optimalGrid\"\n        };\n\n        directive.controller = ['$scope', '$element', '$timeout', function($scope, $element, $timeout) {\n            // Deep watch of object\n            $scope.$watch('toWatch', function(newValue) {\n                var previous;\n                var seperatorNeeded = false;\n                var i=0;\n                $element.children().each(function() {\n                    var current = angular.element(this);\n                    if(current.hasClass('col-xs-6')) {\n                        if(!current.hasClass('ng-hide')) {\n                            i++;\n                        }\n                    } else if(current.hasClass('col-xs-12')) {\n                        if(current.hasClass('seperator')) {\n                            // Seperator\n                            if(i == 2) {\n                                i = 0;\n                                current.removeClass('hidden');\n                            } else {\n                                current.addClass('hidden');\n                            }\n                        } else {\n                            // Double column\n                            if(previous && i > 0) {\n                                previous.removeClass('hidden');\n                            }\n                            i = 0;\n                        }\n                    }\n                    previous = current;\n                });\n\n\n                if(i > 0 && previous) {\n                    previous.removeClass('hidden');\n                }\n            }, true);\n        }];\n        return directive;\n    }]);\n\nangular.module('flowableApp').\n    directive('jumpers', ['$compile', '$http', function($compile, $http) {\n        var directive = {};\n        directive.restrict = 'A';\n        directive.replace = true;\n        directive.transclude = true;\n        directive.template = '<div><ul class=\"jumpers\">' +\n            '<li ng-repeat=\"jumper in jumpers\" ng-show=\"jumper.show || !jumper.static\" ng-click=\"jumperClicked(jumper)\" ng-class=\"{\\'pending\\': !jumper.show}\">{{jumper.title | translate}} <span ng-show=\"jumper.badge != undefined\">{{jumper.badge}}</span></li>' +\n            '</ul></div>';\n\n        directive.scope = {\n            jumpers : \"=jumpers\",\n            activeJumperReference: \"=activeJumper\"\n        };\n\n        directive.controller = ['$scope', '$element', '$timeout', function($scope, $element, $timeout) {\n\n            $scope.state = {};\n            $scope.$watch('activeJumperReference', function(newValue, oldValue) {\n                if(!$scope.activeJumper || $scope.activeJumper.id != newValue) {\n                    var newJumper = $scope.findJumper(newValue);\n                    if(newJumper) {\n                        $scope.jumperClicked(newJumper);\n                    }\n                }\n            });\n\n            $scope.findJumper = function(tabId) {\n                if($scope.jumpers) {\n                    for(var i=0; i< $scope.jumpers.length; i++) {\n                        if($scope.jumpers[i].id == tabId) {\n                            return $scope.jumpers[i];\n                        }\n                    }\n                }\n                return undefined;\n            };\n\n            $scope.jumperClicked = function(jumper) {\n                if(!jumper.show) {\n                    jumper.show = true;\n                }\n\n                if(jumper) {\n                    $scope.activeJumperReference = jumper.id;\n                    $scope.activeJumper = jumper;\n                    if(jumper.anchor) {\n                        $timeout(function() {\n                            var selected = angular.element(\"#\" + jumper.anchor);\n                            if(selected.length) {\n                                var parentElement = selected.parent();\n\n                                var selectedTop = selected.position().top - parentElement.position().top + parentElement.scrollTop();\n                                var selectedBottom = selectedTop + selected.outerHeight();\n                                var elementBottom = parentElement.scrollTop() + parentElement.innerHeight();\n                                var elementTop = elementBottom - parentElement.innerHeight();\n\n                                if(selectedTop <= elementTop) {\n                                    // scroll up\n                                    parentElement.scrollTop(selectedTop);\n                                } else if(selectedBottom > elementBottom) {\n                                    // scroll down\n                                    parentElement.scrollTop(selectedTop);\n                                }\n                            }\n\n                        }, 100)\n                    }\n\n                } else {\n                    $scope.activeJumperReference = undefined;\n                    $scope.activeJumper = undefined;\n                }\n            };\n        }];\n        return directive;\n    }]);\n\n\n/**\n * Directive for using the bootstrap-daterangepicker widget.\n *\n * Taken/inspired from https://github.com/luisfarzati/ng-bs-daterangepicker\n */\nangular.module('flowableApp')\n    .directive('input', ['$compile', '$http', function($compile, $http) {\n        return {\n            restrict: 'E',\n            require: '?ngModel',\n            link: function ($scope, $element, $attributes, ngModel) {\n                if ($attributes.type !== 'daterange' || ngModel === null ) return;\n\n                var options = {};\n                options.format = $attributes.format || 'YYYY-MM-DD';\n                options.separator = $attributes.separator || ' - ';\n                options.minDate = $attributes.minDate && moment($attributes.minDate);\n                options.maxDate = $attributes.maxDate && moment($attributes.maxDate);\n                options.dateLimit = $attributes.limit && moment.duration.apply(this, $attributes.limit.split(' ').map(function (elem, index) { return index === 0 && parseInt(elem, 10) || elem; }) );\n                options.ranges = $attributes.ranges && $parse($attributes.ranges)($scope);\n                options.locale = $attributes.locale && $parse($attributes.locale)($scope);\n                options.opens = $attributes.opens && $parse($attributes.opens)($scope);\n\n                function format(date) {\n                    return date.format(options.format);\n                }\n\n                function formatted(dates) {\n                    return [format(dates.startDate), format(dates.endDate)].join(options.separator);\n                }\n\n                ngModel.$formatters.unshift(function (modelValue) {\n                    if (!modelValue) return '';\n                    return modelValue;\n                });\n\n                ngModel.$parsers.unshift(function (viewValue) {\n                    return viewValue;\n                });\n\n                ngModel.$render = function () {\n                    if (!ngModel.$viewValue || !ngModel.$viewValue.startDate) return;\n                    $element.val(formatted(ngModel.$viewValue));\n                };\n\n                $scope.$watch($attributes.ngModel, function (modelValue) {\n                    if (!modelValue || (!modelValue.startDate)) {\n                        ngModel.$setViewValue({ startDate: moment().startOf('day'), endDate: moment().startOf('day') });\n                        return;\n                    }\n                    $element.data('daterangepicker').startDate = modelValue.startDate;\n                    $element.data('daterangepicker').endDate = modelValue.endDate;\n                    $element.data('daterangepicker').updateView();\n                    $element.data('daterangepicker').updateCalendars();\n                    $element.data('daterangepicker').updateInputText();\n                });\n\n                $element.daterangepicker(options, function(start, end, rangeName) {\n                    $scope.$apply(function () {\n                        ngModel.$setViewValue({ startDate: start, endDate: end ,rangeName: rangeName});\n                        ngModel.$render();\n                    });\n                });\n            }\n        };\n    }]);\n\nangular.module('flowableApp').\n    directive('userPicture', ['$compile', '$http', function($compile, $http) {\n        var directive = {};\n        directive.restrict = 'A';\n        directive.replace = true;\n        directive.transclude = false;\n        directive.template =\n            '<div class=\"{{userPic.class}}\" ng-style=\"{\\'background-image\\': userPic.style}\" title=\"{{userPic.userName | username}}\">' +\n                '<span>{{userPic.text}}</span>'+\n            '</div>';\n\n        directive.scope = {\n            user : \"=userPicture\"\n        };\n\n        directive.controller = ['$scope', '$element', '$timeout', function($scope, $element, $timeout) {\n            $scope.$watch('user', function(newValue, oldValue) {\n                $scope.refreshUser(newValue);\n            });\n            $element.bind('error', function() {\n                console.log('No picture');\n            });\n\n\n            $scope.refreshUser = function(user) {\n                if(user) {\n                    var newUserPic = {text: ''};\n                    if(user.pictureId) {\n                        newUserPic.class = \"user-picture\";\n                        newUserPic.style='url(\"' + FLOWABLE.CONFIG.contextRoot + '/app/rest/users/' + user.id  +'/picture\")';\n                    } else {\n                        newUserPic.class=\"user-picture no-picture\";\n                    }\n\n                    if(user.firstName && user.lastName) {\n                        newUserPic.text = user.firstName.substring(0,1).toUpperCase() + user.lastName.substring(0,1).toUpperCase();\n                        newUserPic.userName = user.firstName + ' ' + user.lastName;\n                    } else if(user.lastName != undefined && user.lastName != null) {\n                        if (user.lastName.length > 1) {\n                            newUserPic.text = user.lastName.substring(0, 2).toUpperCase();\n                        } else if (user.lastName.length == 1) {\n                            newUserPic.text = user.lastName.substring(0, 1).toUpperCase();\n                        }\n                        newUserPic.userName = user.lastName;\n                    } else if(user.firstName != undefined && user.firstName != null) {\n                        if (user.firstName.length > 1) {\n                            newUserPic.text = user.firstName.substring(0, 2).toUpperCase();\n                        } else if (user.firstName.length == 1) {\n                            newUserPic.text = user.firstName.substring(0, 1).toUpperCase();\n                        }\n                        newUserPic.userName = user.firstName;\n                    } else {\n                        if (user != undefined && user != null){\n\t\t\t\t\t\t\tif (user.length > 1) {\n\t\t\t\t\t\t\t\tnewUserPic.text = user.substring(0, 2).toUpperCase();\n\t\t\t\t\t\t\t} else if (user.length == 1) {\n\t\t\t\t\t\t\t\tnewUserPic.text = user.substring(0, 1).toUpperCase();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tnewUserPic.userName = user;\n\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tnewUserPic.text ='??';\n\t\t\t\t\t\t\tnewUserPic.userName = '';\n\t\t\t\t\t\t}\n                    }\n                }\n\n                $scope.userPic = newUserPic;\n            };\n\n\n\n            $scope.refreshUser($scope.user);\n        }];\n        return directive;\n    }]);\n\n//form builder element renderer\nangular.module('flowableApp')\n    .directive('formElement', ['$rootScope', '$timeout', '$modal', '$http', '$templateCache', '$translate', 'appResourceRoot', 'RecursionHelper', function ($rootScope, $timeout, $modal, $http, $templateCache, $translate, appResourceRoot, RecursionHelper) {\n        return {\n            restrict: 'E',\n            templateUrl: appResourceRoot + 'views/templates/form-element-template.html',\n            transclude: false,\n            scope: {\n                field: '=',\n                taskForm: '=',\n                controlCallbacks: '=',\n                model: '='\n            },\n            compile: function (element) {\n                return RecursionHelper.compile(element, this.link);\n            },\n            link: function ($scope, $element, attributes) {\n\n                $scope.appResourceRoot = appResourceRoot;\n                $scope.activitiFieldIdPrefix = $rootScope.activitiFieldIdPrefix;\n\n                $scope.onFieldValueChange = function(field){\n                    return $scope.controlCallbacks.onFieldValueChange(field);\n                };\n\n                $scope.isEmpty = function(field){\n                    return $scope.controlCallbacks.isEmpty(field);\n                };\n\n                $scope.isEmptyDropdown = function(field) {\n                    return $scope.controlCallbacks.isEmptyDropdown(field);\n                };\n\n                $scope.fieldPersonSelected = function(user, field){\n                    return $scope.controlCallbacks.fieldPersonSelected(user, field);\n                };\n\n                $scope.fieldPersonRemoved = function(user, field){\n                    return $scope.controlCallbacks.fieldPersonRemoved(user, field);\n                };\n\n                $scope.fieldGroupSelected = function(group, field){\n                    return $scope.controlCallbacks.fieldGroupSelected(group, field);\n                };\n\n                $scope.fieldGroupRemoved = function(group, field){\n                    return $scope.controlCallbacks.fieldGroupRemoved(group, field);\n                };\n\n                $scope.removeContent = function(content, field){\n                    return $scope.controlCallbacks.removeContent(content, field);\n                };\n\n                $scope.contentUploaded = function(content, field){\n                    return $scope.controlCallbacks.contentUploaded(content, field);\n                };\n\n                $scope.uploadInProgress = function(status){\n                    return $scope.controlCallbacks.uploadInProgress(status);\n                };\n\n                $scope.handleReadonlyClick = function($event, field){\n                    return $scope.controlCallbacks.handleReadonlyClick($event, field);\n                };\n\n                $scope.clearDate = function(field, callback){\n                    return $scope.controlCallbacks.clearDate(field, callback);\n                };\n\n                $scope.selectToday = function(field, callback){\n                    return $scope.controlCallbacks.selectToday(field, callback);\n                };\n\n                $scope.closeDatePopup = function(field){\n                    return $scope.controlCallbacks.closeDatePopup(field);\n                };\n\n                $scope.togglePasswordFieldType = function(field){\n                \t\treturn $scope.controlCallbacks.togglePasswordFieldType(field);\n                };\n            }\n        }\n    }]);\n"
  },
  {
    "path": "flowable-ui-web/task/workflow/styles/style-workflow.css",
    "content": "/** Copyright 2005-2015 Alfresco Software, Ltd.\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/* Process instance / Process definition list */\n\n.slide-animation-proc-def-list.ng-enter\n{\n    -webkit-transition: 200ms cubic-bezier(0.250, 0.250, 0.750, 0.750) all;\n    -moz-transition: 200ms cubic-bezier(0.250, 0.250, 0.750, 0.750) all;\n    -ms-transition: 200ms cubic-bezier(0.250, 0.250, 0.750, 0.750) all;\n    -o-transition: 200ms cubic-bezier(0.250, 0.250, 0.750, 0.750) all;\n    transition: 200ms cubic-bezier(0.250, 0.250, 0.750, 0.750) all;\n}\n\n.slide-animation-proc-def-list.ng-enter {\n    left: -100%;\n}\n\n.slide-animation-proc-def-list.ng-enter.slide-animation-proc-def-list.ng-enter-active  {\n    left: 0;\n}\n\n.proc-def-list{\n    height: 100%;\n    width: 100%;\n    overflow: hidden;\n    z-index: 2;\n}\n.proc-def-list {\n    background-color: #ffffff;\n    position: relative;\n    float: left;\n    width: 400px;\n    margin-right: 20px;\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.proc-inst-list > .list-header {\n    height: 4rem;\n}\n\n.proc-inst-list > .list-subheader {\n    height: 5rem;\n}\n\n/* Using the calc() stuff comes from Erik. Talk with him if you disagree. */\n.proc-inst-list > .list-wrapper {\n    height: calc(100% - 9rem);\n}\n\n/* Process instance details */\n\n.process-instance-name {\n    padding: 10px 3px 0 25px;\n    width: 50%;\n}"
  },
  {
    "path": "flowable-ui-web/task/workflow/views/case-detail.html",
    "content": "<div class=\"main-content\" ng-controller=\"CaseDetailController\">\n\n    <div class=\"help-container\" ng-if=\"!model.caseInstance && !model.loading && state.noCases && (newCaseInstance == null || newCaseInstance == undefined)\" auto-height ng-cloak>\n        <div>\n            <div class=\"help-text wide\">\n                <div class=\"description\">\n                    {{'CASE.MESSAGE.NO-INSTANCES-HELP' | translate}}\n                </div>\n                <div class=\"help-entry toggle-create-task\" ng-class=\"{'active': newCaseInstance.inline }\" ng-click=\"createCaseInstance()\">\n                    <span class=\"glyphicon glyphicon-plus-sign\"></span>\n                    <span translate=\"CASE.MESSAGE.NO-INSTANCES-HELP-START\"></span>\n                </div>\n            </div>\n        </div>\n    </div>\n\n\n    <div class=\"header\" ng-if=\"newCaseInstance != null && newCaseInstance != undefined && newCaseInstance.caseDefinition\">\n        <h2>\n            <edit-in-place value=\"newCaseInstance.name\"></edit-in-place>\n        </h2>\n    </div>\n\n    <div class=\"content clearfix\" auto-height offset=\"6\"\n         ng-if=\"newCaseInstance != null && newCaseInstance != undefined && newCaseInstance.caseDefinition && newCaseInstance.caseDefinition.hasStartForm\">\n        <div class=\"alert error\" ng-show=\"startFormError\">\n            {{startFormError}}\n        </div>\n        <div>\n            <activiti-form case-name=\"newCaseInstance.name\" case-definition-id=\"newCaseInstance.caseDefinition.id\"></activiti-form>\n        </div>\n    </div>\n\n    <div class=\"content clearfix\" auto-height offset=\"6\"\n         ng-if=\"newCaseInstance != null && newCaseInstance != undefined && newCaseInstance.caseDefinition && !newCaseInstance.caseDefinition.hasStartForm\">\n        <div class=\"pull-right\">\n            <button class=\"btn btn-default\" style=\"margin: 10px 15px 0 0\"\n                    ng-disabled=\"newCaseInstance.loading\"\n                    ng-click=\"startCaseInstanceWithoutForm()\">{{'FORM.DEFAULT-OUTCOME.START-CASE' | translate}}\n            </button>\n        </div>\n    </div>\n\n\n    <div class=\"header\" ng-if=\"!newCaseInstance && model.caseInstance\">\n        <div class=\"btn-group pull-right\" ng-show=\"model.caseInstance.startedBy.id == ('' + account.id)\">\n            <button ng-if=\"!model.caseInstance.ended\" class=\"btn\" ng-click=\"cancelCase()\" translate=\"CASE.ACTION.CANCEL\"></button>\n            <button ng-if=\"model.caseInstance.ended\" class=\"btn\" ng-click=\"deleteCase()\" translate=\"CASE.ACTION.DELETE\"></button>\n        </div>\n        <div class=\"btn-group pull-right\" ng-show=\"model.caseInstance.graphicalNotationDefined\">\n            <button class=\"btn\" id=\"caseDiagramTrigger\" translate=\"PROCESS.ACTION.SHOW-DIAGRAM\" ng-click=\"showDiagram()\"></button>\n        </div>\n        <h2> {{model.caseInstance.name && model.caseInstance.name || model.caseInstance.caseDefinitionName}}</h2>\n\n        <div class=\"detail\">\n            <span class=\"label\" ng-if=\"model.caseInstance.startedBy\">{{'PROCESS.FIELD.STARTED-BY' | translate}}: </span>\n            <span user-name=\"model.caseInstance.startedBy\" ng-if=\"model.caseInstance.startedBy\"></span>\n            <span class=\"label\">{{'PROCESS.FIELD.STARTED' | translate}}: </span>\n            <span title=\"{{model.caseInstance.started | dateformat}}\">{{model.caseInstance.started | dateformat:'fromNow'}}</span>\n            <span class=\"label\" ng-show=\"model.caseInstance.ended\">{{'PROCESS.FIELD.ENDED' | translate}}: </span>\n            <span ng-show=\"model.caseInstance.ended\" title=\"{{model.caseInstance.ended | dateformat}}\">{{model.caseInstance.ended | dateformat:'fromNow'}}</span>\n        </div>\n    </div>\n\n    <div class=\"content clearfix split\" auto-height offset=\"6\" ng-if=\"!newCaseInstance && model.caseInstance\">\n        <div class=\"split-right\">\n            <div class=\"section pack\" toggle-dragover=\"dragOverContent(over)\" ng-if=\"!$scope.model.contentSummary.loading\">\n                <h3 class=\"toggle-content-select\" ng-click=\"toggleCreateContent()\"\n                    title=\"{{'TASK.ACTION.ADD-CONTENT' | translate}}\">{{'TASK.TITLE.CONTENT' | translate}}\n                    <span class=\"action\" ng-if=\"!model.caseInstance.endDate\"><a>+</a></span>\n                </h3>\n                <div external-content on-content-upload=\"onContentUploaded(content)\" on-upload-in-progress=\"uploadInProgress(status)\" case-id=\"model.caseInstance.id\"\n                     ng-if=\"model.contentSummary.addContent\"/>\n                <div class=\"form-group\">\n                    <ul id=\"related-content-list\" class=\"clearfix simple-list selectable content-list\">\n                        <li ng-repeat=\"content in model.content.data\" title=\"{{content.name}}\">\n                            <document-preview content=\"content\" editable=\"true\" read-only=\"false\"\n                                              on-delete=\"onContentDeleted(content)\"></document-preview>\n                        </li>\n                    </ul>\n                </div>\n            </div>\n            <div class=\"section pack\" ng-if=\"model.hasUserEventListeners\">\n                <h3 translate=\"CASE.SECTION.AVAILABLE-USER-EVENT-LISTENERS\"></h3>\n\n                <ul class=\"simple-list checklist\">\n                    <li ng-repeat=\"userEventListener in model.caseAvailableUserEventListeners\">\n                        <div class=\"clearfix\">\n                            <div>\n                                <button ng-if=\"userEventListener.state == 'available'\" class=\"btn\" ng-click=\"triggerUserEventListener(userEventListener)\" translate=\"{{userEventListener.name || ('CASE.MESSAGE.USER-EVENT-LISTENER-NO-NAME' | translate)}}\"></button>\n                                <span ng-if=\"userEventListener.state != 'available'\">{{userEventListener.name || ('CASE.MESSAGE.STAGE-NO-NAME' | translate)}}</span>\n                            </div>\n                        </div>\n                    </li>\n                </ul>\n                <div class=\"nothing-to-see\" ng-show=\"!model.caseAvailableUserEventListeners || model.caseAvailableUserEventListeners.length == 0\">\n                    <span translate=\"CASE.MESSAGE.NO-AVAILABLE-USER-EVENT-LISTENERS\"></span>\n                </div>\n            </div>\n            <div class=\"section pack\" ng-if=\"model.hasUserEventListeners\">\n                <h3 translate=\"CASE.SECTION.COMPLETED-USER-EVENT-LISTENERS\"></h3>\n                <ul class=\"simple-list checklist\">\n                    <li ng-repeat=\"userEventListener in model.caseCompletedUserEventListeners\">\n                        <div class=\"clearfix\">\n                            <div class=\"pull-right\">\n                                <span class=\"badge\">{{'CASE.MESSAGE.USER-EVENT-LISTENER-COMPLETED' | translate}} {{(userEventListener.stateDate | dateformat:'fromNow')}}</span>\n                            </div>\n                            <div>\n                                <span>{{userEventListener.name || ('CASE.MESSAGE.USER-EVENT-LISTENER-NO-NAME' | translate)}}</span>\n                            </div>\n                            <div class=\"subtle\">\n                                <span>{{'CASE.MESSAGE.STATE' | translate}}: {{userEventListener.state}}</span>\n                            </div>\n                        </div>\n                    </li>\n                </ul>\n                <div class=\"nothing-to-see\" ng-show=\"!model.caseCompletedUserEventListeners || model.caseCompletedUserEventListeners.length == 0\">\n                    <span translate=\"CASE.MESSAGE.NO-COMPLETED-USER-EVENT-LISTENERS\"></span>\n                </div>\n            </div>\n            <div class=\"section pack\" ng-if=\"model.hasEnabledPlanItemInstance\">\n                <h3 translate=\"CASE.SECTION.ENABLED-PLAN-ITEM-INSTANCES\"></h3>\n                <ul class=\"simple-list checklist\">\n                    <li ng-repeat=\"planItemInstance in model.caseEnabledPlanItemInstances\">\n                        <div class=\"clearfix\">\n                            <div>\n                                <button class=\"btn\" ng-click=\"startPlanItemInstance(planItemInstance)\">\n                                    {{'CASE.MESSAGE.START-PLAN-ITEM-INSTANCE' | translate}} {{planItemInstance.name || ('CASE.MESSAGE.ENABLED-PLAN-ITEM_INSTANCE-NO-NAME' | translate)}}\n                                </button>\n                            </div>\n                        </div>\n                    </li>\n                </ul>\n            </div>\n        </div>\n        <div class=\"split-left\">\n            <div class=\"section pack\" ng-show=\"model.caseHasStages\">\n                <h3 translate=\"CASE.SECTION.ACTIVE-STAGES\"></h3>\n                <ul class=\"simple-list checklist\">\n                    <li ng-repeat=\"stage in model.caseActiveStages\">\n                        <div class=\"clearfix\">\n                            <div class=\"pull-right\">\n                                <span class=\"badge\" ng-if=\"stage.state == 'active'\">\n                                    {{'CASE.MESSAGE.STAGE-STARTED' | translate}} {{(stage.startedDate | dateformat:'fromNow')}}\n                                </span>\n                                <span class=\"badge\" ng-if=\"stage.state == 'available'\">\n                                    {{'CASE.MESSAGE.STAGE-NOT-STARTED' | translate}}\n                                </span>\n                            </div>\n                            <div>\n                                <div user-picture=\"stage.name\"></div>\n                                {{stage.name || ('CASE.MESSAGE.STAGE-NO-NAME' | translate)}}\n                            </div>\n                            <div class=\"subtle\">\n                                <span>\n                                    {{'CASE.MESSAGE.STATE' | translate}}: {{stage.state}}\n                                </span>\n                            </div>\n                        </div>\n                    </li>\n                </ul>\n                <div class=\"nothing-to-see\" ng-show=\"!model.caseActiveStages || model.caseActiveStages.length == 0\">\n                    <span translate=\"CASE.MESSAGE.NO-ACTIVE-STAGES\"></span>\n                </div>\n            </div>\n            <div class=\"section pack\" ng-show=\"model.caseHasStages\">\n                <h3 translate=\"CASE.SECTION.ENDED-STAGES\"></h3>\n                <ul class=\"simple-list checklist\">\n                    <li ng-repeat=\"stage in model.caseEndedStages\">\n                        <div class=\"clearfix\">\n                            <div class=\"pull-right\">\n                                <span class=\"badge\">\n                                    {{'CASE.MESSAGE.STAGE-ENDED' | translate}} {{(stage.endedDate | dateformat:'fromNow')}}\n                                </span>\n                            </div>\n                            <div>\n                                <div user-picture=\"stage.name\"></div>\n                                {{stage.name || ('CASE.MESSAGE.STAGE-NO-NAME' | translate)}}\n                            </div>\n                            <div class=\"subtle\">\n                                <span>\n                                    {{'CASE.MESSAGE.STATE' | translate}}: {{stage.state}}\n                                </span>\n                            </div>\n                        </div>\n                    </li>\n                </ul>\n                <div class=\"nothing-to-see\" ng-show=\"!model.caseEndedStages || model.caseEndedStages.length == 0\">\n                    <span translate=\"CASE.MESSAGE.NO-ENDED-STAGES\"></span>\n                </div>\n            </div>\n            <div class=\"section pack\">\n                <h3 translate=\"PROCESS.SECTION.ACTIVE-TASKS\"></h3>\n                <ul class=\"simple-list checklist\">\n                    <li ng-repeat=\"task in model.caseTasks\" ng-click=\"openTask(task)\">\n                        <div class=\"clearfix\">\n                            <div class=\"pull-right\">\n                                <span class=\"badge\" ng-if=\"task.dueDate\">\n                                    {{'TASK.MESSAGE.DUE-ON' | translate}} {{(task.dueDate | dateformat:'fromNow')}}\n                                </span>\n                                <span class=\"badge\" ng-if=\"!task.dueDate\">\n                                    {{'TASK.MESSAGE.CREATED-ON' | translate}} {{(task.created | dateformat:'fromNow')}}\n                                </span>\n                            </div>\n                            <div>\n                                <div user-picture=\"task.assignee\"></div>\n                                {{task.name && task.name || ('TASK.MESSAGE.NO-NAME' | translate)}}\n                            </div>\n                            <div class=\"subtle\">\n                                <span ng-if=\"task.assignee.id\">\n                                    {{'TASK.MESSAGE.ASSIGNEE' | translate}} {{task.assignee.firstName && task.assignee.firstName != 'null' ? task.assignee.firstName : ''}} {{task.assignee.lastName && task.assignee.lastName != 'null' ? task.assignee.lastName : ''}}\n                                </span>\n                                <span ng-if=\"!task.assignee.id\" translate=\"TASK.MESSAGE.NO-ASSIGNEE\">\n                                </span>\n                            </div>\n                        </div>\n                    </li>\n                </ul>\n                <div class=\"nothing-to-see\" ng-show=\"!model.caseTasks || model.caseTasks.length == 0\">\n                    <span translate=\"PROCESS.MESSAGE.NO-TASKS\"></span>\n                </div>\n            </div>\n            <div class=\"section pack\" ng-show=\"model.caseInstance.startFormDefined\">\n                <h3 translate=\"PROCESS.SECTION.START-FORM\" id=\"startForm\"></h3>\n                <ul class=\"simple-list checklist\">\n                    <li ng-click=\"openStartForm()\" class=\"complete\">\n                        <div class=\"clearfix\">\n                            <div>\n                                <div user-picture=\"model.caseInstance.startedBy\"></div>\n                                <span translate=\"PROCESS.SECTION.START-FORM\"></span>\n                            </div>\n                            <div class=\"subtle\">\n                                <span ng-if=\"model.caseInstance.startedBy.id\">\n                                \t{{'TASK.MESSAGE.COMPLETED-BY' | translate}} {{model.caseInstance.startedBy.firstName && model.caseInstance.startedBy.firstName != 'null' ? model.caseInstance.startedBy.firstName : ''}} {{model.caseInstance.startedBy.lastName && model.caseInstance.startedBy.lastName != 'null' ? model.caseInstance.startedBy.lastName : ''}}\n                                    {{model.caseInstance.started | dateformat:'fromNow'}}\n                                </span>\n                            </div>\n                        </div>\n                    </li>\n                </ul>\n            </div>\n            <div class=\"section pack\">\n                <h3 translate=\"PROCESS.SECTION.COMPLETED-TASKS\" id=\"completedTasks\"></h3>\n                <ul class=\"simple-list checklist\">\n                    <li ng-repeat=\"task in model.completedCaseTasks\" ng-click=\"openTask(task)\" class=\"complete\">\n                        <div class=\"clearfix\">\n                            <div class=\"pull-right\">\n                                <span class=\"badge\">\n                                    {{'TASK.MESSAGE.DURATION' | translate:task}}\n                                </span>\n                            </div>\n                            <div>\n                                <div user-picture=\"task.assignee\"></div>\n                                {{task.name && task.name || ('TASK.MESSAGE.NO-NAME' | translate)}}\n                            </div>\n                            <div class=\"subtle\">\n                                <span ng-if=\"task.assignee.id\">\n                                \t{{'TASK.MESSAGE.COMPLETED-BY' | translate}} {{task.assignee.firstName && task.assignee.firstName != 'null' ? task.assignee.firstName : ''}} {{task.assignee.lastName && task.assignee.lastName != 'null' ? task.assignee.lastName : ''}}\n                                    {{task.endDate | dateformat:'fromNow'}}\n                                </span>\n                                <span ng-if=\"!task.assignee.id\" translate=\"TASK.MESSAGE.NO-ASSIGNEE\">\n                                </span>\n                            </div>\n                        </div>\n                    </li>\n                </ul>\n                <div class=\"nothing-to-see\" ng-show=\"model.completedCaseTasks.length == 0\">\n                    <span translate=\"PROCESS.MESSAGE.NO-COMPLETED-TASKS\"></span>\n                </div>\n            </div>\n            <div class=\"section pack\" ng-show=\"model.caseHasMilestones\">\n                <h3 translate=\"CASE.SECTION.AVAILABLE-MILESTONES\" id=\"activeMilestones\"></h3>\n                <ul class=\"simple-list checklist\">\n                    <li ng-repeat=\"milestone in model.caseAvailableMilestones\" class=\"complete\">\n                        <div class=\"clearfix\">\n                            <div class=\"pull-right\">\n                                <div class=\"pull-right\">\n                                <span class=\"badge\" ng-if=\"milestone.timestamp\">\n                                    {{'TASK.MESSAGE.CREATED-ON' | translate}} {{(milestone.timestamp | dateformat:'fromNow')}}\n                                </span>\n                                </div>\n                            </div>\n                            <div>\n                                <div user-picture=\"milestone.name\"></div>\n                                {{milestone.name && milestone.name || ('TASK.MESSAGE.NO-NAME' | translate)}}\n                            </div>\n                            <div class=\"subtle\">\n                                <span/>\n                            </div>\n                        </div>\n                    </li>\n                </ul>\n                <div class=\"nothing-to-see\" ng-show=\"model.caseAvailableMilestones.length == 0\">\n                    <span translate=\"CASE.MESSAGE.NO-AVAILABLE-MILESTONES\"></span>\n                </div>\n            </div>\n            <div class=\"section pack\" ng-show=\"model.caseHasMilestones\">\n                <h3 translate=\"CASE.SECTION.REACHED-MILESTONES\" id=\"reachedMilestones\"></h3>\n                <ul class=\"simple-list checklist\">\n                    <li ng-repeat=\"milestone in model.caseEndedMilestones\" class=\"complete\">\n                        <div class=\"clearfix\">\n                            <div class=\"pull-right\">\n                                <span class=\"badge\" ng-if=\"milestone.state=='completed'\">\n                                    {{'CASE.MESSAGE.MILESTONE-REACHED-ON' | translate}} {{(milestone.timestamp | dateformat:'fromNow')}}\n                                </span>\n                                <span class=\"badge\" ng-if=\"milestone.state!='completed'\">\n                                    {{'CASE.MESSAGE.MILESTONE-TERMINATED-ON' | translate}} {{(milestone.timestamp | dateformat:'fromNow')}}\n                                </span>\n                            </div>\n                            <div>\n                                <div user-picture=\"milestone.name\"></div>\n                                {{milestone.name && milestone.name || ('TASK.MESSAGE.NO-NAME' | translate)}}\n                            </div>\n                            <div class=\"subtle\">\n                                <span>\n                                    {{'CASE.MESSAGE.STATE' | translate}}: {{milestone.state}}\n                                </span>\n                            </div>\n                        </div>\n                    </li>\n                </ul>\n                <div class=\"nothing-to-see\" ng-show=\"model.caseEndedMilestones.length == 0\">\n                    <span translate=\"CASE.MESSAGE.NO-REACHED-MILESTONES\"></span>\n                </div>\n            </div>\n        </div>\n\n    </div>\n</div>\n"
  },
  {
    "path": "flowable-ui-web/task/workflow/views/case-start-form.html",
    "content": "<div class=\"main-content\" ng-controller=\"CaseStartFormController\">\n\n    <div class=\"header\" ng-show=\"model.caseInstance\">\n        \n        <h2> {{model.caseInstance.name && model.caseInstance.name ||\n            model.caseInstance.caseDefinitionName}}</h2>\n\n        <div class=\"detail\">\n            <span class=\"label\" ng-show=\"model.caseInstance.startedBy\">{{'PROCESS.FIELD.STARTED-BY' | translate}}: </span>\n            <span user-name=\"model.caseInstance.startedBy\" ng-show=\"model.caseInstance.startedBy\"></span>\n            <span class=\"label\">{{'PROCESS.FIELD.STARTED' | translate}}: </span>\n            <span title=\"{{model.caseInstance.started | dateformat}}\">{{model.caseInstance.started | dateformat:'fromNow'}}</span>\n            <span class=\"label\" ng-show=\"model.caseInstance.ended\">{{'PROCESS.FIELD.ENDED' | translate}}: </span>\n            <span ng-show=\"model.caseInstance.ended\" title=\"{{model.caseInstance.ended | dateformat}}\">{{model.caseInstance.ended | dateformat:'fromNow'}}</span>\n            <span ng-if=\"model.caseInstance.id\" class=\"label\">{{'TASK.FIELD.PROCESS-INSTANCE' | translate}}: </span>\n            <span ng-if=\"model.caseInstance.id\">\n                <a ng-click=\"openCaseInstance()\">{{model.caseInstance.name && model.caseInstance.name || model.caseInstance.caseDefinitionName}}</a>\n            </span>\n        </div>\n    </div>\n\n    <div class=\"content clearfix\" auto-height offset=\"6\" ng-if=\"model.caseInstance && model.formData\">\n        <!-- FORM -->\n        <div class=\"section\">\n            <activiti-form form-definition=\"model.formData\"\n                           hide-buttons=\"true\">\n            </activiti-form>\n        </div>\n\n    </div>\n</div>"
  },
  {
    "path": "flowable-ui-web/task/workflow/views/case.html",
    "content": "<div class=\"main-content-wrapper\" ng-include=\"appResourceRoot + 'views/case-detail.html'\" ></div>\n"
  },
  {
    "path": "flowable-ui-web/task/workflow/views/cases.html",
    "content": "\n<div class=\"main-list\" id=\"main-list\" ng-if=\"!missingAppdefinition\">\n\n    <div class=\"proc-inst-list\" ng-show=\"model.mode == 'case-list'\" style=\"height:100%\">\n\n        <div class=\"list-header\" id=\"list-header\" click-anywhere=\"collapseFilter()\" ignore-popup-events=\"true\">\n\n            <div class=\"summary\" ng-show=\"!model.filter.expanded\" ng-click=\"expandFilter()\">\n                <span ng-if=\"model.filter.param.state\">{{'CASE.FILTER.STATE-SUMMARY' | translate:model.filter.param}}</span>\n                <span ng-if=\"!model.filter.param.state\">{{'CASE.MESSAGE.NO-FILTER' | translate}}</span>\n                <span class=\"pull-right\"><span class=\"glyphicon glyphicon-filter\"></span></span>\n            </div>\n\n            <div class=\"summary\" ng-show=\"model.filter.expanded\">\n                <div class=\"form-group\" >\n                    <label translate=\"CASE.FILTER.STATE\"></label>\n                    <div class=\"selection toggle\">\n                        <div class=\"toggle-3\" ng-repeat=\"option in model.stateFilterOptions\" ng-class=\"{'active' : model.filter.param.state.id == option.id}\">\n                            <button class=\"btn btn-xs\" ng-click=\"selectStateFilter(option)\">{{option.title | translate}}</button>\n                        </div>\n                    </div>\n                </div>\n            </div>\n        </div>\n        <div class=\"list-subheader clearfix\">\n            <div class=\"btn-group pull-left\">\n                <button id=\"toggle-create-process\" class=\"btn btn-xs dropdown-toggle\" translate=\"CASE.ACTION.CREATE\" ng-click=\"createCaseInstance()\">&nbsp;</button>\n            </div>\n            <div class=\"sort\">\n                <div class=\"dropdown btn-group btn-group-sm\">\n                    <a class=\"dropdown-toggle\" trigger=\"click\" placement=\"bottom-right\" ng-model=\"model.filter.param.sort\" ng-change=\"sortChanged()\"\n                       ng-options=\"sort.id as (sort.title | translate) for sort in model.sorts\" bs-select></a>\n                </div>\n            </div>\n        </div>\n\n        <div loading=\"model.filter.loading\"></div>\n        <div class=\"list-wrapper\" ng-show=\"!model.filter.loading\">\n            <ul class=\"full-list\">\n                <li ng-repeat=\"caseInstance in model.caseInstances\" ng-class=\"{'active': selectedCaseInstance.id == caseInstance.id}\" ng-click=\"selectCaseInstance(caseInstance)\">\n                    <div>\n                        <div class=\"pull-right\">\n                            <span class=\"badge\" ng-if=\"!processInstance.ended\">\n                                {{'CASE.FIELD.STARTED' | translate}} {{(caseInstance.started | dateformat:'fromNow')}}\n                            </span>\n                            <span class=\"badge\" ng-if=\"processInstance.ended\">\n                                {{'CASE.FIELD.ENDED' | translate}} {{(caseInstance.ended | dateformat:'fromNow')}}\n                            </span>\n                        </div>\n                        <div class=\"title\">\n                            {{caseInstance.name && caseInstance.name || caseInstance.processDefinitionName}}\n                        </div>\n                        <div class=\"summary\">\n                             <span ng-if=\"caseInstance.startedBy\">\n                             \t{{'CASE.MESSAGE.STARTED-BY' | translate}} {{caseInstance.startedBy.firstName && caseInstance.startedBy.firstName != 'null' ? caseInstance.startedBy.firstName : ''}} {{caseInstance.startedBy.lastName && caseInstance.startedBy.lastName != 'null' ? caseInstance.startedBy.lastName : ''}}\n                            </span>\n                        </div>\n                        <div class=\"detail\">\n                            {{caseInstance.description && caseInstance.description || caseInstance.processDefinitionName}}\n                        </div>\n                    </div>\n                </li>\n                <li class=\"more\" ng-if=\"model.hasNextPage && !model.filter.loading\" ng-click=\"nextPage()\">\n                    <i class=\"icon icon-caret-right\"></i> {{'GENERAL.ACTION.SHOW-MORE' | translate}}\n                </li>\n            </ul>\n            <div class=\"nothing-to-see\" ng-show=\"model.processInstances.length == 0\">\n                <span  translate=\"CASE.MESSAGE.NO-INSTANCES\"></span>\n            </div>\n        </div>\n\n    </div>\n\n\n\n    <div class=\"proc-def-list\" ng-if=\"model.mode == 'case-create'\" style=\"height: 100%\">\n\n        <div class=\"list-header\">\n            <div class=\"summary\" translate=\"CASE.MESSAGE.SELECT-DEFINITION\" style=\"cursor: auto\"></div>\n        </div>\n\n        <div class=\"list-subheader clearfix\">\n            <div class=\"btn-group pull-left\">\n                <button class=\"btn btn-xs\" ng-click=\"backToList()\">\n                    &lt; {{'CASE.ACTION.BACK-TO-LIST' | translate}}</button>\n            </div>\n        </div>\n\n        <div>\n\n            <div class=\"nothing-to-see\" ng-if=\"root.caseDefinitions.length == 0\">\n                <span>{{'CASE.MESSAGE.NO-CASE-DEFINITIONS' | translate}}</span>\n            </div>\n\n            <div class=\"list-wrapper\">\n                <ul class=\"full-list\">\n                    <li ng-repeat=\"definition in root.caseDefinitions\"\n                        ng-class=\"{'active' : newCaseInstance.caseDefinitionId == definition.id}\"\n                        ng-click=\"selectCaseDefinition(definition)\">\n                        <div>\n                            <div class=\"title\">\n                                {{definition.name}}\n                            </div>\n                            <div class=\"summary\">\n                                {{definition.description}}\n                            </div>\n                        </div>\n                    </li>\n                </ul>\n            </div>\n\n        </div>\n\n    </div>\n\n</div>\n\n\n\n<div class=\"main-content-wrapper\" ng-if=\"!root.showStartForm && !missingAppdefinition\" ng-include=\"appResourceRoot + 'views/case-detail.html'\" ></div>\n\n<div class=\"main-content-wrapper\" ng-if=\"root.showStartForm && !missingAppdefinition\" ng-include=\"appResourceRoot + 'views/case-start-form.html'\"></div>\n\n<div ng-if=\"missingAppdefinition\" ng-include=\"appResourceRoot + 'views/integration-mode-error.html'\"></div>"
  },
  {
    "path": "flowable-ui-web/task/workflow/views/integration-mode-error.html",
    "content": "<div>\n\n    <div class=\"help-container\" auto-height ng-cloak>\n        <div>\n            <div class=\"help-text wide\">\n                <div class=\"description\">\n                    {{'APP-DEFINITION.MESSAGE.MISSING' | translate}}\n                </div>\n            </div>\n        </div>\n    </div>\n\n</div>"
  },
  {
    "path": "flowable-ui-web/task/workflow/views/modal/case-cancel.html",
    "content": "\n<div class=\"modal\" ng-controller=\"CancelCaseCtrl\">\n\t<div class=\"modal-dialog\">\n\t\t<div class=\"modal-content\">\n\t\t\t<div class=\"modal-header\">\n\t\t\t\t<h2 ng-if=\"!finalDelete\">{{'PROCESS.POPUP.CANCEL-TITLE' | translate}}</h2>\n\t\t\t\t<h2 ng-if=\"finalDelete\">{{'PROCESS.POPUP.DELETE-TITLE' | translate}}</h2>\n\t\t\t</div>\n\t\t\t<div class=\"modal-body\">\n\t\t\t\t<p ng-if=\"!finalDelete\">{{'PROCESS.POPUP.CANCEL-DESCRIPTION' | translate:model.caseInstance}}</p>\n\t\t\t\t<p ng-if=\"finalDelete\">{{'PROCESS.POPUP.DELETE-DESCRIPTION' | translate:model.caseInstance}}</p>\n\t\t\t</div>\n\t\t\t<div class=\"modal-footer\">\n\t\t\t\t<div class=\"pull-right\">\n\t\t\t\t\t<button type=\"button\" class=\"btn btn-sm btn-default\" ng-click=\"cancel()\" ng-disabled=\"popup.loading\">\n\t\t\t\t\t\t{{'GENERAL.ACTION.CANCEL' | translate}}\n\t\t\t\t\t</button>\n\t\t\t\t\t<button type=\"button\" class=\"btn btn-sm btn-danger\" ng-click=\"ok()\" ng-disabled=\"popup.loading\">\n\t\t\t\t\t\t<span>{{'GENERAL.ACTION.CONFIRM' | translate}}</span>\n\t\t\t\t\t</button>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"loading pull-right\" ng-show=\"popup.loading\">\n\t\t\t\t\t<div class=\"l1\"></div><div class=\"l2\"></div><div class=\"l2\"></div>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</div>\n\t</div>\n</div>"
  },
  {
    "path": "flowable-ui-web/task/workflow/views/modal/case-instance-graphical.html",
    "content": "\n<div class=\"modal\" ng-controller=\"ShowCaseDiagramCtrl\">\n    <div class=\"modal-dialog wide\">\n        <div class=\"modal-content\">\n            <div class=\"modal-header\">\n                <div class=\"pull-right\">\n                    <button type=\"button\" class=\"close\" ng-click=\"$hide()\">&times;</button>\n                </div>\n            </div>\n            <div class=\"modal-body\">\n                <div class=\"error-message\" ng-if=\"model.errorMessage\">\n                    <span>{{model.errorMessage}}</span>\n                </div>\n                <div class=\"alert-wrapper\" ng-cloak>\n                    <div class=\"alert {{alerts.current.type}}\" ng-show=\"alerts.current\" ng-click=\"dismissAlert()\">\n                        <span>{{alerts.current.message}}</span>\n                        <span class=\"badge\" ng-show=\"alerts.queue.length\">{{alerts.queue.length + 1}}</span>\n                    </div>\n                </div>\n\n                <div class=\"popup-wrapper clearfix\">\n                    <div class=\"model-preview-wrapper\">\n                        <div id=\"cmmnModel\"/>\n                    </div>\n                </div>\n            </div>\n            <div class=\"modal-footer\">\n                <div class=\"row\">\n\n                    <div class=\"pull-right\">\n                        <button type=\"button\" class=\"btn btn-sm btn-default\" ng-click=\"$hide()\">\n                            {{'GENERAL.ACTION.CLOSE' | translate}}\n                        </button>\n                    </div>\n                </div>\n            </div>\n        </div>\n    </div>\n</div>\n"
  },
  {
    "path": "flowable-ui-web/task/workflow/views/modal/delete-content.html",
    "content": "\n<div class=\"modal\">\n\t<div class=\"modal-dialog\">\n\t\t<div class=\"modal-content\">\n\t\t\t<div class=\"modal-header\">\n\t\t\t\t<h2>{{'CONTENT.TITLE.DELETE' | translate}}</h2>\n\t\t\t</div>\n\t\t\t<div class=\"modal-body\">\n\t\t\t\t<p>{{'CONTENT.MESSAGE.DELETE-CONFIRMATION' | translate:popup.content}}</p>\n\t\t\t</div>\n\t\t\t<div class=\"modal-footer\">\n\t\t\t\t<div class=\"pull-right\">\n\t\t\t\t\t<button type=\"button\" class=\"btn btn-sm btn-default\" ng-click=\"$hide();\" ng-disabled=\"popup.loading\">\n\t\t\t\t\t\t{{'GENERAL.ACTION.CANCEL' | translate}}\n\t\t\t\t\t</button>\n\t\t\t\t\t<button type=\"button\" class=\"btn btn-sm btn-danger\" ng-click=\"ok(); $hide();\" ng-disabled=\"popup.loading\">\n\t\t\t\t\t\t<span>{{'GENERAL.ACTION.CONFIRM' | translate}}</span>\n\t\t\t\t\t</button>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"loading pull-right\" ng-show=\"popup.loading\">\n\t\t\t\t\t<div class=\"l1\"></div><div class=\"l2\"></div><div class=\"l2\"></div>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</div>\n\t</div>\n</div>"
  },
  {
    "path": "flowable-ui-web/task/workflow/views/modal/process-cancel.html",
    "content": "\n<div class=\"modal\" ng-controller=\"CancelProcessCtrl\">\n\t<div class=\"modal-dialog\">\n\t\t<div class=\"modal-content\">\n\t\t\t<div class=\"modal-header\">\n\t\t\t\t<h2 ng-if=\"!finalDelete\">{{'PROCESS.POPUP.CANCEL-TITLE' | translate}}</h2>\n\t\t\t\t<h2 ng-if=\"finalDelete\">{{'PROCESS.POPUP.DELETE-TITLE' | translate}}</h2>\n\t\t\t</div>\n\t\t\t<div class=\"modal-body\">\n\t\t\t\t<p ng-if=\"!finalDelete\">{{'PROCESS.POPUP.CANCEL-DESCRIPTION' | translate:model.processInstance}}</p>\n\t\t\t\t<p ng-if=\"finalDelete\">{{'PROCESS.POPUP.DELETE-DESCRIPTION' | translate:model.processInstance}}</p>\n\t\t\t</div>\n\t\t\t<div class=\"modal-footer\">\n\t\t\t\t<div class=\"pull-right\">\n\t\t\t\t\t<button type=\"button\" class=\"btn btn-sm btn-default\" ng-click=\"cancel()\" ng-disabled=\"popup.loading\">\n\t\t\t\t\t\t{{'GENERAL.ACTION.CANCEL' | translate}}\n\t\t\t\t\t</button>\n\t\t\t\t\t<button type=\"button\" class=\"btn btn-sm btn-danger\" ng-click=\"ok()\" ng-disabled=\"popup.loading\">\n\t\t\t\t\t\t<span>{{'GENERAL.ACTION.CONFIRM' | translate}}</span>\n\t\t\t\t\t</button>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"loading pull-right\" ng-show=\"popup.loading\">\n\t\t\t\t\t<div class=\"l1\"></div><div class=\"l2\"></div><div class=\"l2\"></div>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</div>\n\t</div>\n</div>"
  },
  {
    "path": "flowable-ui-web/task/workflow/views/modal/process-instance-graphical.html",
    "content": "\n<div class=\"modal\" ng-controller=\"ShowProcessDiagramCtrl\">\n    <div class=\"modal-dialog wide\">\n        <div class=\"modal-content\">\n            <div class=\"modal-header\">\n                <div class=\"pull-right\">\n                    <button type=\"button\" class=\"close\" ng-click=\"$hide()\">&times;</button>\n                </div>\n                <h3 class=\"modal-title\">{{'PROCESS.TITLE.DIAGRAM' | translate}}\n                    <span id=\"navigationTree\">| <a href=\"javascript:_navigateTo('FLOWABLE_ROOT_PROCESS')\">Root</a></span>\n                </h3>\n            </div>\n            <div class=\"modal-body\">\n                <div class=\"error-message\" ng-if=\"model.errorMessage\">\n                    <span>{{model.errorMessage}}</span>\n                </div>\n                <div class=\"alert-wrapper\" ng-cloak>\n                    <div class=\"alert {{alerts.current.type}}\" ng-show=\"alerts.current\" ng-click=\"dismissAlert()\">\n                        <span>{{alerts.current.message}}</span>\n                        <span class=\"badge\" ng-show=\"alerts.queue.length\">{{alerts.queue.length + 1}}</span>\n                    </div>\n                </div>\n\n                <div class=\"popup-wrapper clearfix\">\n                    <div class=\"model-preview-wrapper\">\n                        <div id=\"bpmnModel\"/>\n                    </div>\n                </div>\n            </div>\n            <div class=\"modal-footer\">\n                <div class=\"row\">\n\n                    <div class=\"component\" ng-if=\"model.isDebuggerEnabled\">\n                        <div class=\"tabs-wrapper\">\n                            <div class=\"tabs clearfix\">\n                                <div class=\"tab\" ng-repeat=\"tab in tabData.tabs\"\n                                     ng-class=\"{'active': tabData.activeTab == tab.id}\">\n                                    <a ng-click=\"tabData.activeTab = tab.id\">\n                                        {{tab.name | translate:node}}&nbsp;\n                                        <span class=\"badge\" ng-if=\"tab.info != undefined\">{{tab.info}}</span>\n                                    </a>\n                                </div>\n                            </div>\n                            <div class=\"title\"></div>\n\n                            <div class=\"grid-wrapper grid-wrapper-compact\"\n                                 ng-if=\"gridVariables && tabData.activeTab == tabData.tabs[0].id\">\n                                <div class=\"pull-left\">\n                                    <label for=\"executionId\">{{'PROCESS.TITLE.EXECUTION' | translate}}</label>\n                                    <span id=\"executionId\"\n                                          ng-bind=\"model.selectedExecution\">{{model.selectedExecution}}</span>\n                                </div>\n                                <div class=\"ui-grid-contents-wrapper\" ng-show=\"model.displayVariables\">\n                                    <label for=\"variablesUi\">{{'PROCESS.TITLE.VARIABLES' | translate}}</label>\n                                    <div id=\"variablesUi\" ui-grid=\"gridVariables\" style=\"height: 200px; width: 100%\"\n                                         ui-grid-auto-resize></div>\n                                </div>\n                            </div>\n\n                            <div class=\"grid-wrapper grid-wrapper-compact\"\n                                 ng-if=\"gridExecutions && tabData.activeTab == tabData.tabs[1].id\">\n                                <div class=\"ui-grid-contents-wrapper\" ng-show=\"model.executions\">\n                                    <div id=\"executionsUi\" ui-grid=\"gridExecutions\" style=\"height: 200px; width: 100%\"\n                                         ui-grid-selection\n                                         ui-grid-auto-resize></div>\n                                </div>\n                            </div>\n\n                            <div class=\"grid-wrapper grid-wrapper-compact\"\n                                 ng-if=\"gridLog && tabData.activeTab == tabData.tabs[2].id\">\n                                <div class=\"ui-grid-contents-wrapper\">\n                                    <div id=\"logUi\" ui-grid=\"gridLog\" style=\"height: 200px; width: 100%\"\n                                         ui-grid-selection\n                                         ui-grid-auto-resize></div>\n                                </div>\n\n                            </div>\n                            <div class=\"grid-wrapper grid-wrapper-compact\"\n                                 ng-if=\"!model.processInstance.ended && tabData.activeTab == tabData.tabs[3].id\">\n                                <div class=\"col-xs-12\">\n                                    <label for=\"expressionText\" class=\"col-xs-1\">{{'PROCESS.TITLE.EXPRESSION' | translate}}</label>\n                                    <div id=\"expressionText\" class=\"col-xs-7\">\n                                        <textarea class=\"form-control\" ng-model=\"model.expression\" editor-input-check\n                                                  style=\"width:100%; height:100%; max-width: 100%; max-height: 100%; min-height: 50px\"\n                                        />\n                                    </div>\n                                    <div class=\"col-xs-1\">\n                                        <label for=\"expressionResult\">{{'PROCESS.TITLE.RESULT' | translate}}</label>\n                                    </div>\n                                    <div class=\"col-xs-1\">\n                                        <div id=\"expressionResult\" ng-if=\"model.result\">\n                                            <span>{{model.result}}</span>\n                                        </div>\n                                    </div>\n                                </div>\n                            </div>\n                            <div class=\"grid-wrapper grid-wrapper-compact\"\n                                 ng-if=\"!model.processInstance.ended && tabData.activeTab == tabData.tabs[4].id\">\n                                <div class=\"col-xs-12\">\n                                    <label for=\"scriptText\" class=\"col-xs-1\">{{'PROCESS.TITLE.SCRIPT' | translate}}</label>\n                                    <div id=\"scriptText\" class=\"col-xs-7\">\n                                        <textarea class=\"form-control\" ng-model=\"model.scriptText\" editor-input-check\n                                                  style=\"width:100%; height:100%; max-width: 100%; max-height: 100%; min-height: 150px\"\n                                        />\n                                    </div>\n                                    <div id=\"scriptLanguage\" class=\"col-xs-1\" align=\"left\">\n                                        <input type=\"radio\" ng-model=\"model.scriptLanguage\" name=\"scriptLanguage\" value=\"groovy\"> groovy\n                                        <input type=\"radio\" ng-model=\"model.scriptLanguage\" name=\"scriptLanguage\" value=\"javascript\"> js\n                                    </div>\n                                </div>\n                            </div>\n                        </div>\n                    </div>\n                </div>\n\n                <div class=\"pull-left\" ng-if=\"!model.processInstance.ended && tabData.activeTab == tabData.tabs[3].id\">\n                    <button type=\"button\" class=\"btn btn-sm btn-default\" ng-click=\"evaluateExpression()\">\n                        {{'PROCESS.ACTION.EXECUTE' | translate}}\n                    </button>\n                </div>\n                <div class=\"pull-left\" ng-if=\"!model.processInstance.ended && tabData.activeTab == tabData.tabs[4].id\">\n                    <button type=\"button\" class=\"btn btn-sm btn-default\" ng-click=\"evaluateScript()\">\n                        {{'PROCESS.ACTION.EXECUTE' | translate}}\n                    </button>\n                </div>\n                <div class=\"pull-right\">\n                    <button type=\"button\" class=\"btn btn-sm btn-default\" ng-click=\"$hide()\">\n                        {{'GENERAL.ACTION.CLOSE' | translate}}\n                    </button>\n                </div>\n            </div>\n        </div>\n    </div>\n</div>\n"
  },
  {
    "path": "flowable-ui-web/task/workflow/views/popover/add-related-content-popover.html",
    "content": "<div class=\"popover\" click-anywhere=\"$hide()\" ignore-class=\"toggle-content-select\" auto-scroll>\n    <div class=\"arrow\"></div>\n    <div class=\"popover-header\">\n        <span class=\"title\">{{'TASK.TITLE.ADD-RELATED-CONTENT' | translate}}</span>\n\n        <div class=\"actions\">\n            <a ng-click=\"$hide()\" ng-show=\"!newTask.loading\">\n                {{'GENERAL.ACTION.CLOSE' | translate}}</a>\n        </div>\n    </div>\n\n    <div class=\"popover-wrapper\">\n    </div>\n</div>"
  },
  {
    "path": "flowable-ui-web/task/workflow/views/popover/create-task-popover.html",
    "content": "<div class=\"popover\" ignore-class=\"toggle-create-task\">\n    <div class=\"arrow\"></div>\n    <div class=\"popover-header\">\n        <span translate=\"TASK.TITLE.CREATE-NEW\"></span>\n        <div class=\"actions\">\n            <a ng-click=\"$hide()\" ng-show=\"!newTask.loading\">{{'GENERAL.ACTION.CLOSE' | translate}}</a>\n        </div>\n    </div>\n    <div class=\"popover-wrapper clearfix\">\n        <div class=\"form-group\">\n            <label translate=\"TASK.FIELD.NAME\"></label>\n            <input type=\"text\" class=\"form-control\" ng-model=\"newTask.name\" ng-placeholder=\"Name\" auto-focus\n                   select-text=\"newTask.name\" ng-disabled=\"newTask.loading\"\n                   custom-keys enter-pressed=\"confirmTaskCreation()\">\n        </div>\n        <div class=\"form-group\">\n            <label translate=\"TASK.FIELD.DESCRIPTION\"></label>\n            <textarea class=\"form-control\" rows=\"3\" id=\"add-comment-input\" ng-model=\"newTask.description\" ng-disabled=\"newTask.loading\"></textarea>\n        </div>\n        <div class=\"form-group\">\n            <span class=\"glyphicon glyphicon-user\"></span>\n            <span ng-model=\"newTask.assignee\"\n                    select-people-popover\n                  close-on-select=\"true\"\n                  on-people-selected=\"setTaskAssignee(user)\"\n                  on-email-selected=\"setTaskAssigneeByEmail(email)\"\n                  placement=\"bottom\"\n                  exclude-user-id=\"newTask.assignee.id\"\n                  title=\"{{'TASK.FIELD.ASSIGNEE' | translate}}\">{{'TASK.FIELD.ASSIGNEE' | translate}}\n            </span>\n            <span ng-if=\"newTask.assignee\" user-name=\"newTask.assignee\"></span>\n        </div>\n    </div>\n    <div class=\"popover-footer\">\n        <div class=\"btn-group pull-right\">\n        <button class=\"btn btn-default\" ng-click=\"$hide();\" ng-disabled=\"newTask.loading\" translate=\"GENERAL.ACTION.CANCEL\" ></button>\n        <button class=\"btn btn-default\" ng-click=\"confirmTaskCreation();\" ng-disabled=\"!newTask.name || newTask.name.length == 0 || newTask.loading\" translate=\"TASK.ACTION.CREATE-CONFIRM\" ></button>\n    </div>\n        <div loading=\"newTask.loading\"></div>\n    </div>\n</div>\n"
  },
  {
    "path": "flowable-ui-web/task/workflow/views/process-detail.html",
    "content": "<div class=\"main-content\" ng-controller=\"ProcessDetailController\">\n\n    <div class=\"help-container\" ng-if=\"!model.processInstance && !model.loading && state.noProcesses && (newProcessInstance == null || newProcessInstance == undefined)\" auto-height ng-cloak>\n        <div>\n            <div class=\"help-text wide\">\n                <div class=\"description\">\n                    {{'PROCESS.MESSAGE.NO-INSTANCES-HELP' | translate}}\n                </div>\n                <div class=\"help-entry toggle-create-task\" ng-class=\"{'active': newProcessInstance.inline }\" ng-click=\"createProcessInstance()\">\n                    <span class=\"glyphicon glyphicon-plus-sign\"></span>\n                    <span translate=\"PROCESS.MESSAGE.NO-INSTANCES-HELP-START\"></span>\n                </div>\n            </div>\n        </div>\n    </div>\n\n\n    <div class=\"header\" ng-if=\"newProcessInstance != null && newProcessInstance != undefined && newProcessInstance.processDefinition\">\n          <h2>\n              <edit-in-place value=\"newProcessInstance.name\"></edit-in-place>\n          </h2>\n    </div>\n\n    <div class=\"content clearfix\" auto-height offset=\"6\" ng-if=\"newProcessInstance != null && newProcessInstance != undefined && newProcessInstance.processDefinition && newProcessInstance.processDefinition.hasStartForm\">\n        <div class=\"alert error\" ng-show=\"startFormError\">\n            {{startFormError}}\n        </div>\n        <div>\n            <activiti-form process-name=\"newProcessInstance.name\" process-definition-id=\"newProcessInstance.processDefinition.id\"></activiti-form>\n        </div>\n    </div>\n\n    <div class=\"content clearfix\" auto-height offset=\"6\" ng-if=\"newProcessInstance != null && newProcessInstance != undefined && newProcessInstance.processDefinition && !newProcessInstance.processDefinition.hasStartForm\">\n        <div class=\"pull-right\">\n            <button class=\"btn btn-default\" style=\"margin: 10px 15px 0 0\"\n                    ng-disabled=\"newProcessInstance.loading\"\n                    ng-click=\"startProcessInstanceWithoutForm()\">{{'FORM.DEFAULT-OUTCOME.START-PROCESS' | translate}}\n            </button>\n        </div>\n    </div>\n\n\n    <div class=\"header\" ng-if=\"!newProcessInstance && model.processInstance\">\n        <div class=\"btn-group pull-right\" ng-show=\"model.processInstance.startedBy.id == ('' + account.id)\">\n            <button ng-if=\"!model.processInstance.ended\" class=\"btn\" ng-click=\"cancelProcess()\" translate=\"PROCESS.ACTION.CANCEL\"></button>\n            <button ng-if=\"model.processInstance.ended\" class=\"btn\" ng-click=\"deleteProcess()\" translate=\"PROCESS.ACTION.DELETE\"></button>\n        </div>\n        <div class=\"btn-group pull-right\" ng-show=\"model.processInstance.graphicalNotationDefined\">\n            <button class=\"btn\" id=\"processDiagramTrigger\" translate=\"PROCESS.ACTION.SHOW-DIAGRAM\" ng-click=\"showDiagram()\"></button>\n        </div>\n        <h2> {{model.processInstance.name && model.processInstance.name ||\n            model.processInstance.processDefinitionName}}</h2>\n\n        <div class=\"detail\">\n            <span class=\"label\" ng-if=\"model.processInstance.startedBy\">{{'PROCESS.FIELD.STARTED-BY' | translate}}: </span>\n            <span user-name=\"model.processInstance.startedBy\" ng-if=\"model.processInstance.startedBy\"></span>\n            <span class=\"label\">{{'PROCESS.FIELD.STARTED' | translate}}: </span>\n            <span title=\"{{model.processInstance.started | dateformat}}\">{{model.processInstance.started | dateformat:'fromNow'}}</span>\n            <span class=\"label\" ng-show=\"model.processInstance.ended\">{{'PROCESS.FIELD.ENDED' | translate}}: </span>\n            <span ng-show=\"model.processInstance.ended\" title=\"{{model.processInstance.ended | dateformat}}\">{{model.processInstance.ended | dateformat:'fromNow'}}</span>\n        </div>\n    </div>\n\n    <div class=\"content clearfix split\" auto-height offset=\"6\" ng-if=\"!newProcessInstance && model.processInstance\">\n        <div class=\"split-right\">\n\n            <div class=\"section\">\n                <h3 close-on-select=\"false\" ng-click=\"toggleCreateComment()\" title=\"{{'PROCESS.ACTION.ADD-COMMENT' | translate}}\">{{'PROCESS.SECTION.COMMENTS' | translate}}\n                    <span class=\"action\">\n                        <a>+</a>\n                    </span>\n                </h3>\n\n                <div class=\"form-group clearfix box\"\n                     ng-show=\"model.addComment\"\n                     auto-focus=\"model.addComment\">\n                    <textarea class=\"form-control focusable\" rows=\"2\" ng-disabled=\"model.commentLoading\"\n                              ng-model=\"model.newComment\" id=\"add-comment-inline\"\n                              placeholder=\"{{'PROCESS.MESSAGE.NEW-COMMENT-PLACEHOLDER' | translate}}\">\n                    </textarea>\n\n                    <div class=\"pull-right\">\n                        <button tabindex=\"-1\" class=\"btn btn-xs\" translate=\"GENERAL.ACTION.CANCEL\"\n                                ng-click=\"toggleCreateComment()\" ng-disabled=\"model.commentLoading\"></button>\n                        <button class=\"btn btn-xs\" translate=\"PROCESS.ACTION.ADD-COMMENT-CONFIRM\"\n                                ng-disabled=\"!model.newComment || model.commentLoading || model.newComment.length > 4000\"\n                                ng-click=\"confirmNewComment()\"></button>\n                    </div>\n                </div>\n                <ul class=\"simple-list comments selectable\" ng-show=\"model.comments.data.length\">\n                    <li ng-repeat=\"comment in model.comments.data\">\n                        <div class=\"title\">\n                            <div user-picture=\"comment.createdBy\"></div>\n                            {{'PROCESS.MESSAGE.COMMENT-HEADER' | translate:comment}}\n                        </div>\n                        <div class=\"message\">{{comment.message}}</div>\n                    </li>\n                </ul>\n            </div>\n\n        </div>\n        <div class=\"split-left\">\n            <div class=\"section pack\">\n                <h3 translate=\"PROCESS.SECTION.ACTIVE-TASKS\"></h3>\n                <ul class=\"simple-list checklist\">\n                    <li ng-repeat=\"task in model.processTasks\" ng-click=\"openTask(task)\">\n                        <div class=\"clearfix\">\n                            <div class=\"pull-right\">\n                                <span class=\"badge\" ng-if=\"task.dueDate\">\n                                    {{'TASK.MESSAGE.DUE-ON' | translate}} {{(task.dueDate | dateformat:'fromNow')}}\n                                </span>\n                                <span class=\"badge\" ng-if=\"!task.dueDate\">\n                                    {{'TASK.MESSAGE.CREATED-ON' | translate}} {{(task.created | dateformat:'fromNow')}}\n                                </span>\n                            </div>\n                            <div>\n                                <div user-picture=\"task.assignee\"></div>\n                                {{task.name && task.name || ('TASK.MESSAGE.NO-NAME' | translate)}}\n                            </div>\n                            <div class=\"subtle\">\n                                <span ng-if=\"task.assignee.id\">\n                                    {{'TASK.MESSAGE.ASSIGNEE' | translate}} {{task.assignee.firstName && task.assignee.firstName != 'null' ? task.assignee.firstName : ''}} {{task.assignee.lastName && task.assignee.lastName != 'null' ? task.assignee.lastName : ''}}\n                                </span>\n                                <span ng-if=\"!task.assignee.id\" translate=\"TASK.MESSAGE.NO-ASSIGNEE\">\n                                </span>\n                            </div>\n                        </div>\n                    </li>\n                </ul>\n                <div class=\"nothing-to-see\" ng-show=\"!model.processTasks || model.processTasks.length == 0\">\n                    <span translate=\"PROCESS.MESSAGE.NO-TASKS\"></span>\n                </div>\n             </div>\n             <div class=\"section pack\" ng-show=\"model.processInstance.startFormDefined\">\n                <h3 translate=\"PROCESS.SECTION.START-FORM\" id=\"startForm\"></h3>\n                <ul class=\"simple-list checklist\">\n                    <li ng-click=\"openStartForm()\" class=\"complete\">\n                        <div class=\"clearfix\">\n                            <div>\n                                <div user-picture=\"model.processInstance.startedBy\"></div>\n                                <span translate=\"PROCESS.SECTION.START-FORM\"></span>\n                            </div>\n                            <div class=\"subtle\">\n                                <span ng-if=\"model.processInstance.startedBy.id\">\n                                \t{{'TASK.MESSAGE.COMPLETED-BY' | translate}} {{model.processInstance.startedBy.firstName && model.processInstance.startedBy.firstName != 'null' ? model.processInstance.startedBy.firstName : ''}} {{model.processInstance.startedBy.lastName && model.processInstance.startedBy.lastName != 'null' ? model.processInstance.startedBy.lastName : ''}}\n                                    {{model.processInstance.started | dateformat:'fromNow'}}\n                                </span>\n                            </div>\n                        </div>\n                    </li>\n                </ul>\n             </div>\n            <div class=\"section pack\">\n                <h3 translate=\"PROCESS.SECTION.COMPLETED-TASKS\" id=\"completedTasks\"></h3>\n                <ul class=\"simple-list checklist\">\n                    <li ng-repeat=\"task in model.completedProcessTasks\" ng-click=\"openTask(task)\" class=\"complete\">\n                        <div class=\"clearfix\">\n                            <div class=\"pull-right\">\n                                <span class=\"badge\">\n                                    {{'TASK.MESSAGE.DURATION' | translate:task}}\n                                </span>\n                            </div>\n                            <div>\n                                <div user-picture=\"task.assignee\"></div>\n                                {{task.name && task.name || ('TASK.MESSAGE.NO-NAME' | translate)}}\n                            </div>\n                            <div class=\"subtle\">\n                                <span ng-if=\"task.assignee.id\">\n                                \t{{'TASK.MESSAGE.COMPLETED-BY' | translate}} {{task.assignee.firstName && task.assignee.firstName != 'null' ? task.assignee.firstName : ''}} {{task.assignee.lastName && task.assignee.lastName != 'null' ? task.assignee.lastName : ''}}\n                                    {{task.endDate | dateformat:'fromNow'}}\n                                </span>\n                                <span ng-if=\"!task.assignee.id\" translate=\"TASK.MESSAGE.NO-ASSIGNEE\">\n                                </span>\n                            </div>\n                        </div>\n                    </li>\n                </ul>\n                <div class=\"nothing-to-see\" ng-show=\"model.completedProcessTasks.length == 0\">\n                    <span translate=\"PROCESS.MESSAGE.NO-COMPLETED-TASKS\"></span>\n                </div>\n\n            </div>\n        </div>\n\n    </div>\n</div>\n"
  },
  {
    "path": "flowable-ui-web/task/workflow/views/process.html",
    "content": "<div class=\"main-content-wrapper\" ng-include=\"appResourceRoot + 'views/process-detail.html'\" ></div>\n"
  },
  {
    "path": "flowable-ui-web/task/workflow/views/processes.html",
    "content": "\n<div class=\"main-list\" id=\"main-list\" ng-if=\"!missingAppdefinition\">\n\n    <div class=\"proc-inst-list\" ng-show=\"model.mode == 'process-list'\" style=\"height:100%\">\n\n        <div class=\"list-header\" id=\"list-header\" click-anywhere=\"collapseFilter()\" ignore-popup-events=\"true\">\n\n            <div class=\"summary\" ng-show=\"!model.filter.expanded\" ng-click=\"expandFilter()\">\n                <span ng-if=\"model.filter.param.state\">{{'PROCESS.FILTER.STATE-SUMMARY' | translate:model.filter.param}}</span>\n                <span ng-if=\"!model.filter.param.state\">{{'PROCESS.MESSAGE.NO-FILTER' | translate}}</span>\n                <span class=\"pull-right\"><span class=\"glyphicon glyphicon-filter\"></span></span>\n            </div>\n\n            <div class=\"summary\" ng-show=\"model.filter.expanded\">\n                <div class=\"form-group\" >\n                    <label translate=\"PROCESS.FILTER.STATE\"></label>\n                    <div class=\"selection toggle\">\n                        <div class=\"toggle-3\" ng-repeat=\"option in model.stateFilterOptions\" ng-class=\"{'active' : model.filter.param.state.id == option.id}\">\n                            <button class=\"btn btn-xs\" ng-click=\"selectStateFilter(option)\">{{option.title | translate}}</button>\n                        </div>\n                    </div>\n                </div>\n            </div>\n        </div>\n        <div class=\"list-subheader clearfix\">\n            <div class=\"btn-group pull-left\">\n                <button id=\"toggle-create-process\" class=\"btn btn-xs dropdown-toggle\" translate=\"PROCESS.ACTION.CREATE\" ng-click=\"createProcessInstance()\">&nbsp;</button>\n            </div>\n            <div class=\"sort\">\n                <div class=\"dropdown btn-group btn-group-sm\">\n                    <a class=\"dropdown-toggle\" trigger=\"click\" placement=\"bottom-right\" ng-model=\"model.filter.param.sort\" ng-change=\"sortChanged()\"\n                       ng-options=\"sort.id as (sort.title | translate) for sort in model.sorts\" bs-select></a>\n                </div>\n            </div>\n        </div>\n\n        <div loading=\"model.filter.loading\"></div>\n        <div class=\"list-wrapper\" ng-show=\"!model.filter.loading\">\n            <ul class=\"full-list\">\n                <li ng-repeat=\"processInstance in model.processInstances\" ng-class=\"{'active': selectedProcessInstance.id == processInstance.id}\" ng-click=\"selectProcessInstance(processInstance)\">\n                    <div>\n                        <div class=\"pull-right\">\n                            <span class=\"badge\" ng-if=\"!processInstance.ended\">\n                                {{'PROCESS.FIELD.STARTED' | translate}} {{(processInstance.started | dateformat:'fromNow')}}\n                            </span>\n                            <span class=\"badge\" ng-if=\"processInstance.ended\">\n                                {{'PROCESS.FIELD.ENDED' | translate}} {{(processInstance.ended | dateformat:'fromNow')}}\n                            </span>\n                        </div>\n                        <div class=\"title\">\n                            {{processInstance.name && processInstance.name || processInstance.processDefinitionName}}\n                        </div>\n                        <div class=\"summary\">\n                             <span ng-if=\"processInstance.startedBy\">\n                             \t{{'PROCESS.MESSAGE.STARTED-BY' | translate}} {{processInstance.startedBy.firstName && processInstance.startedBy.firstName != 'null' ? processInstance.startedBy.firstName : ''}} {{processInstance.startedBy.lastName && processInstance.startedBy.lastName != 'null' ? processInstance.startedBy.lastName : ''}}\n                            </span>\n                        </div>\n                        <div class=\"detail\">\n                            {{processInstance.description && processInstance.description || processInstance.processDefinitionName}}\n                        </div>\n                    </div>\n                </li>\n                <li class=\"more\" ng-if=\"model.hasNextPage && !model.filter.loading\" ng-click=\"nextPage()\">\n                    <i class=\"icon icon-caret-right\"></i> {{'GENERAL.ACTION.SHOW-MORE' | translate}}\n                </li>\n            </ul>\n            <div class=\"nothing-to-see\" ng-show=\"model.processInstances.length == 0\">\n                <span  translate=\"PROCESS.MESSAGE.NO-INSTANCES\"></span>\n            </div>\n        </div>\n\n    </div>\n\n\n\n    <div class=\"proc-def-list\" ng-if=\"model.mode == 'process-create'\" style=\"height: 100%\">\n\n        <div class=\"list-header\">\n            <div class=\"summary\" translate=\"PROCESS.MESSAGE.SELECT-DEFINITION\" style=\"cursor: auto\"></div>\n        </div>\n\n        <div class=\"list-subheader clearfix\">\n            <div class=\"btn-group pull-left\">\n                <button class=\"btn btn-xs\" ng-click=\"backToList()\">\n                    &lt; {{'PROCESS.ACTION.BACK-TO-LIST' | translate}}</button>\n            </div>\n        </div>\n\n        <div>\n\n            <div class=\"nothing-to-see\" ng-if=\"root.processDefinitions.length == 0\">\n                <span>{{'PROCESS.MESSAGE.NO-PROCESS-DEFINITIONS' | translate}}</span>\n            </div>\n\n            <div class=\"list-wrapper\">\n                <ul class=\"full-list\">\n                    <li ng-repeat=\"definition in root.processDefinitions\"\n                        ng-class=\"{'active' : newProcessInstance.processDefinitionId == definition.id}\"\n                        ng-click=\"selectProcessDefinition(definition)\">\n                        <div>\n                            <div class=\"title\">\n                                {{definition.name}}\n                            </div>\n                            <div class=\"summary\">\n                                {{definition.description}}\n                            </div>\n                        </div>\n                    </li>\n                </ul>\n            </div>\n\n        </div>\n\n    </div>\n\n</div>\n\n\n\n<div class=\"main-content-wrapper\" ng-if=\"!root.showStartForm && !missingAppdefinition\" ng-include=\"appResourceRoot + 'views/process-detail.html'\" ></div>\n\n<div class=\"main-content-wrapper\" ng-if=\"root.showStartForm && !missingAppdefinition\" ng-include=\"appResourceRoot + 'views/start-form.html'\"></div>\n\n<div ng-if=\"missingAppdefinition\" ng-include=\"appResourceRoot + 'views/integration-mode-error.html'\"></div>"
  },
  {
    "path": "flowable-ui-web/task/workflow/views/start-form.html",
    "content": "<div class=\"main-content\" ng-controller=\"StartFormController\">\n\n    <div class=\"header\" ng-show=\"model.processInstance\">\n        \n        <h2> {{model.processInstance.name && model.processInstance.name ||\n            model.processInstance.processDefinitionName}}</h2>\n\n        <div class=\"detail\">\n            <span class=\"label\" ng-show=\"model.processInstance.startedBy\">{{'PROCESS.FIELD.STARTED-BY' | translate}}: </span>\n            <span user-name=\"model.processInstance.startedBy\" ng-show=\"model.processInstance.startedBy\"></span>\n            <span class=\"label\">{{'PROCESS.FIELD.STARTED' | translate}}: </span>\n            <span title=\"{{model.processInstance.started | dateformat}}\">{{model.processInstance.started | dateformat:'fromNow'}}</span>\n            <span class=\"label\" ng-show=\"model.processInstance.ended\">{{'PROCESS.FIELD.ENDED' | translate}}: </span>\n            <span ng-show=\"model.processInstance.ended\" title=\"{{model.processInstance.ended | dateformat}}\">{{model.processInstance.ended | dateformat:'fromNow'}}</span>\n            <span ng-if=\"model.processInstance.id\" class=\"label\">{{'TASK.FIELD.PROCESS-INSTANCE' | translate}}: </span>\n            <span ng-if=\"model.processInstance.id\">\n                <a ng-click=\"openProcessInstance()\">{{model.processInstance.name && model.processInstance.name || model.processInstance.processDefinitionName}}</a>\n            </span>\n        </div>\n    </div>\n\n    <div class=\"content clearfix\" auto-height offset=\"6\" ng-if=\"model.processInstance && model.formData\">\n        <!-- FORM -->\n        <div class=\"section\">\n            <activiti-form form-definition=\"model.formData\"\n                           hide-buttons=\"true\">\n            </activiti-form>\n        </div>\n\n    </div>\n</div>"
  },
  {
    "path": "flowable-ui-web/task/workflow/views/start-process.html",
    "content": "<div class=\"main-list\" id=\"main-list\" ng-if=\"!missingAppdefinition\">\n\n   <div class=\"form-group\">\n      <div class=\"container-fluid\">\n         <h1>Start Workflow</h1>\n         <div class=\"subtle\" translate=\"PROCESS.MESSAGE.SELECT-DEFINITION\"></div>\n         <div>\n            <div class=\"form-group\">\n               <div class=\"no-results\" ng-show=\"popupModel.userResults.length == 0\">\n                  <span>{{'PROCESS.MESSAGE.NO-PROCESS-DEFINITIONS' | translate}}</span>\n               </div>\n\n               <ul class=\"simple-list selection\">\n                  <li ng-if=\"definition.name != 'Hire' && definition.name != 'Todo'\" ng-class=\"{'active' : processDefinition.id == definition.id}\" ng-repeat=\"definition in processDefinitions\" ng-click=\"selectProcessDefinition(definition)\">\n                     {{definition.name}}\n                  </li>\n               </ul>\n            </div>\n         </div>\n\n      </div>\n   </div>\n</div>\n\n<div class=\"main-content-wrapper\" ng-show=\"!processDefinition.id && !missingAppdefinition\">\n   <div class=\"help-container\" auto-height ng-cloak>\n      <div>\n         <div class=\"help-text wide\">\n            <div class=\"description\" ng-show=\"processDefinitions.length == 0\">\n               {{'PROCESS.MESSAGE.NO-PROCESS-DEFINITIONS' | translate}}\n            </div>\n            <div class=\"description\" ng-show=\"processDefinitions.length > 0\">\n               {{'PROCESS.MESSAGE.NO-PROCESS-DEFINITION-SELECTED-HELP' | translate}}\n            </div>\n         </div>\n      </div>\n   </div>\n</div>\n\n<div class=\"main-content-wrapper\" ng-show=\"processDefinition.id && !missingAppdefinition\">\n   <div class=\"main-content\">\n      <div class=\"header\">\n         <div class=\"form-group\">\n            <h2>\n                <edit-in-place value=\"processName\"></edit-in-place>\n            </h2>\n         </div>\n         <span>{{processDefinition.description}}</span>\n      </div>\n\n      <activiti-form process-name=\"processName\" process-definition-id=\"processDefinitionWithStartFormId\" form-definition=\"startFormDefinition\" ng-show=\"processDefinitionWithStartFormId\"></activiti-form>\n\n      <div class=\"form-wrapper container-fluid\">\n         <div class=\"pull-right\" ng-show=\"processDefinitions.length && !processDefinitionWithStartFormId\">\n            <button class=\"btn btn-default\" ng-disabled=\"processName.length == 0\"\n                    ng-click=\"createProcessInstance()\">{{'FORM.DEFAULT-OUTCOME.START-PROCESS' | translate}}</button>\n         </div>\n      </div>\n\n   </div>\n</div>\n\n<div ng-if=\"missingAppdefinition\" ng-include=\"appResourceRoot + 'views/integration-mode-error.html'\"></div>"
  },
  {
    "path": "flowable-ui-web/task/workflow/views/task-detail.html",
    "content": "<div class=\"main-content\" ng-controller=\"TaskDetailController\">\n\n    <div class=\"help-container\" ng-if=\"noSuchTask\" auto-height ng-cloak>\n        <div>\n            <div class=\"help-text wide\">\n                <div ng-if=\"noSuchTask\" class=\"description\">\n                    {{'TASK.MESSAGE.NO-SUCH-TASK-HELP' | translate}}\n                </div>\n                <div class=\"help-entry\" ng-click=\"returnToTaskList(); $event.stopPropagation();\">\n                    <span class=\"glyphicon glyphicon-arrow-left\"></span>\n                    <span translate=\"TASK.MESSAGE.NO-SUCH-TASK-RETURN-TO-LIST\"></span>\n                </div>\n            </div>\n        </div>\n    </div>\n\n    <div class=\"help-container\" ng-if=\"!model.task && !model.loading && state.noOwnTasks && !noSuchTask\" auto-height ng-cloak>\n        <div>\n            <div class=\"help-text wide\">\n                <div ng-if=\"state.noOwnTasks\" class=\"description\">\n                    {{'TASK.MESSAGE.NO-TASKS-HELP' | translate}}\n                </div>\n                <div class=\"help-entry toggle-create-task\" ng-class=\"{'active': newTask.inline }\" ng-click=\"createTaskInline()\" ng-show=\"!newProcessInstance.inline\">\n                    <span class=\"glyphicon glyphicon-plus-sign\"></span>\n                    <span translate=\"TASK.MESSAGE.NO-TASKS-CREATE-TASK\"></span>\n                    <div ng-if=\"newTask.inline\" class=\"clearfix\" style=\"padding: 5px;\">\n                        <div class=\"form-group\">\n                            <label translate=\"TASK.FIELD.NAME\"></label>\n                            <input type=\"text\" class=\"form-control\" ng-model=\"newTask.name\" ng-placeholder=\"Name\" auto-focus=\"newTask.inline\"\n                                   select-text=\"newTask.name\" ng-disabled=\"newTask.loading\"\n                                   custom-keys enter-pressed=\"confirmTaskCreation(newTask)\">\n                        </div>\n                        <div class=\"form-group\">\n                            <label translate=\"TASK.FIELD.DESCRIPTION\"></label>\n                            <textarea class=\"form-control\" rows=\"2\" id=\"add-comment-input\" ng-model=\"newTask.description\" ng-disabled=\"newTask.loading\"></textarea>\n                        </div>\n                        <div class=\"pull-right\">\n                            <button class=\"btn btn-xs\" ng-click=\"cancelTaskCreation(); closeInlineTaskCreation($event);\" ng-disabled=\"newTask.loading\" translate=\"GENERAL.ACTION.CANCEL\" tabindex=\"-1\"></button>\n                            <button class=\"btn btn-xs\" ng-click=\"confirmTaskCreation(newTask); closeInlineTaskCreation($event);\" ng-disabled=\"!newTask.name || newTask.name.length == 0 || newTask.loading\" translate=\"TASK.ACTION.CREATE-CONFIRM\" ></button>\n                        </div>\n                    </div>\n                </div>\n                <div class=\"help-entry\" ng-click=\"createProcess(); $event.stopPropagation();\" ng-show=\"!newTask.inline\" ng-class=\"{'active': newProcessInstance.inline }\">\n                    <span class=\"glyphicon glyphicon-plus-sign\"></span>\n                    <span translate=\"TASK.MESSAGE.NO-TASKS-CREATE-PROCESS\"></span>\n                </div>\n            </div>\n        </div>\n    </div>\n    <div class=\"header\" ng-show=\"model.task && !noSuchTask\">\n        <div class=\" pull-right\">\n            <button class=\"btn\" ng-if=\"!model.task.formKey && !model.task.endDate && (model.task.assignee.id == account.id || (model.task.initiatorCanCompleteTask && model.task.processInstanceStartUserId == ('' + account.id)))\"\n                    translate=\"TASK.ACTION.COMPLETE\"\n                    ng-disabled=\"model.completeButtonDisabled || model.uploadInProgress\"\n                    ng-click=\"completeTask()\"></button>\n\n            <button class=\"btn\" ng-if=\"(model.task.assignee == null || model.task.assignee == undefined) &&\n                (model.task.memberOfCandidateGroup || model.task.memberOfCandidateUsers ||\n                (model.task.initiatorCanCompleteTask && model.task.processInstanceStartUserId == ('' + account.id)))\"\n                    translate=\"TASK.ACTION.CLAIM\"\n                    ng-disabled=\"model.claimButtonDisabled || model.uploadInProgress\"\n                    ng-click=\"claimTask()\"></button>\n\n            <activiti-form form-definition=\"model.formData\"\n                   task-id=\"model.task.id\"\n                   ng-if=\"model.task.assignee && model.formData\"\n                   outcomes-only=\"true\"\n                   disable-form=\"(model.task.assignee.id != account.id && (!model.task.initiatorCanCompleteTask || model.task.processInstanceStartUserId != ('' + account.id)))\"\n                   hide-buttons=\"model.task.endDate\">\n            </activiti-form>\n\n        </div>\n        <h2>{{model.task.name && model.task.name || ('TASK.MESSAGE.NO-NAME' | translate)}}</h2>\n\n        <div class=\"detail\">\n            <span class=\"label\">{{'TASK.FIELD.ASSIGNEE' | translate}}: </span>\n            <a ng-if=\"!model.task.endDate && model.task.assignee && (model.task.assignee.id == account.id || (model.task.initiatorCanCompleteTask && model.task.processInstanceStartUserId == ('' + account.id)))\" class=\"subtle-select\"\n                    select-people-popover\n                    exclude-user-id=\"model.task.assignee.id\"\n                    on-people-selected=\"setTaskAssigneeValue(user)\"\n                    on-email-selected=\"setTaskAssigneeValueByEmail(email)\"\n                    close-on-select=\"true\"\n                    placement=\"bottom-left\">\n                <span ng-if=\"model.task.assignee\" user-name=\"model.task.assignee\"></span>\n            </a>\n            <span ng-if=\"model.task.assignee && (model.task.endDate || (model.task.assignee.id != account.id && (!model.task.initiatorCanCompleteTask || model.task.processInstanceStartUserId != ('' + account.id))))\" user-name=\"model.task.assignee\"></span>\n            <span ng-if=\"(model.task.endDate && !model.task.assignee) || !model.task.assignee\" translate=\"TASK.MESSAGE.NO-ASSIGNEE\"></span>\n            <span class=\"label\">{{'TASK.FIELD.DUE' | translate}}: </span>\n            <a ng-if=\"!model.task.endDate && !model.taskUpdating\" id=\"due-date-select\" placement=\"bottom-left\" class=\"subtle-select\" bs-datepicker template=\"{{appResourceRoot}}views/templates/due-date-picker-template.html\" ng-model=\"model.task.dueDate\" trigger=\"click\" autoclose=\"true\" placement=\"bottom-center\" title=\"{{model.task.dueDate | dateformat}}\">\n                {{model.task.dueDate && (model.task.dueDate | dateformat:'fromNow') || ('TASK.MESSAGE.NO-DUEDATE' | translate)}}\n            </a>\n            <span ng-if=\"model.task.endDate\">{{model.task.dueDate && (model.task.dueDate | dateformat:'fromNow') || ('TASK.MESSAGE.NO-DUEDATE' | translate)}}</span>\n            <span ng-if=\"model.task.processInstanceId && model.processInstance\" class=\"label\">{{'TASK.FIELD.PROCESS-INSTANCE' | translate}}: </span>\n            <span ng-if=\"model.processInstance\">\n                <a ng-click=\"openProcessInstance(model.processInstance.id)\">{{model.processInstance.name && model.processInstance.name || model.processInstance.processDefinitionName}}</a>\n            </span>\n            <span ng-if=\"model.task.scopeId && model.caseInstance\" class=\"label\">{{'TASK.FIELD.CASE-INSTANCE' | translate}}: </span>\n            <span ng-if=\"model.caseInstance\">\n                <a ng-click=\"openCaseInstance(model.caseInstance.id)\">{{model.caseInstance.name && model.caseInstance.name || model.caseInstance.caseDefinitionName}}</a>\n            </span>\n            <span ng-if=\"model.task.parentTaskId\" class=\"label\">{{'TASK.FIELD.PARENT-TASK' | translate}}: </span>\n            <span ng-if=\"model.task.parentTaskId\">\n                <a ng-click=\"openTaskInstance(model.task.parentTaskId)\">{{model.task.parentTaskName}}</a>\n            </span>\n\n            <span class=\"label\" ng-if=\"model.task.endDate != null && model.task.endDate != undefined\">{{'TASK.FIELD.ENDED' | translate}}: </span>\n            <span ng-if=\"model.task.endDate != null && model.task.endDate != undefined\">{{model.task.endDate | dateformat:'fromNow'}}</span>\n\n            <span class=\"label\" ng-if=\"model.task.endDate != null && model.task.endDate != undefined\">{{'TASK.FIELD.DURATION' | translate}}: </span>\n            <span ng-if=\"model.task.endDate != null && model.task.endDate != undefined\">{{model.task.duration | duration}}</span>\n        </div>\n\n        <div class=\"summary-header clearfix\" ng-class=\"{'pack': model.involvementSummary.count == 0 &amp;&amp; model.contentSummary.count == 0}\">\n            <div class=\"clearfix\" ng-click=\"showPeople()\">\n                <div class=\"title title-lg\" ng-show=\"model.involvementSummary.count == 0\">\n                    {{'TASK.TITLE.NO-PEOPLE-INVOLVED' | translate}}\n                </div>\n\n                <div user-picture=\"user\" ng-repeat=\"user in model.involvementSummary.items\"></div>\n\n                <div class=\"user-picture more\" ng-show=\"model.involvementSummary.overflow\">\n                    <span>...</span>\n                </div>\n            </div>\n            <div class=\"clearfix\" ng-click=\"showContent()\">\n                <div class=\"title title-lg\" ng-show=\"model.contentSummary.count == 0\">\n                    {{'TASK.TITLE.NO-CONTENT-ITEMS' | translate}}\n                </div>\n\n                <div class=\"related-content\" ng-repeat=\"content in model.contentSummary.items\" title=\"{{content.name}}\">\n                    <i class=\"icon icon-{{content.simpleType}}\"></i>\n                </div>\n\n                <div class=\"related-content more\" ng-show=\"model.contentSummary.overflow\">\n                    <span>...</span>\n                </div>\n            </div>\n            <div class=\"clearfix\" ng-click=\"showComments()\">\n                <div class=\"title title-lg\" ng-show=\"model.commentSummary.count == 1\">\n                   1 {{'TASK.TITLE.COMMENT-COUNT' | translate}}\n                </div>\n                <div class=\"title title-lg\" ng-show=\"model.commentSummary.count > 1\">\n                    <span>{{model.commentSummary.count}}</span> {{'TASK.TITLE.COMMENTS-COUNT' | translate}}\n                </div>\n                <div class=\"title title-lg\" ng-show=\"model.commentSummary.count == 0\">\n                    {{'TASK.TITLE.NO-COMMENTS' | translate}}\n                </div>\n            </div>\n            <div class=\"clearfix\" ng-click=\"showSubTasks()\">\n                <div class=\"title title-lg\" ng-show=\"model.subTaskSummary.count == 1\">\n                   1 {{'TASK.TITLE.SUBTASK-COUNT' | translate}}\n                </div>\n                <div class=\"title title-lg\" ng-show=\"model.subTaskSummary.count > 1\">\n                    <span>{{model.subTaskSummary.count}}</span> {{'TASK.TITLE.SUBTASKS-COUNT' | translate}}\n                </div>\n                <div class=\"title title-lg\" ng-show=\"model.subTaskSummary.count == 0\">\n                    {{'TASK.TITLE.NO-SUBTASKS' | translate}}\n                </div>\n            </div>\n            <div ng-show=\"model.task.formKey\" ng-click=\"toggleForm()\">\n                <button class=\"btn btn-xs\">\n                    <span ng-show=\"activeTab == 'form'\">\n                        {{'TASK.TITLE.SHOW-DETAILS' | translate}}\n                    </span>\n                    <span ng-show=\"activeTab == 'details'\">\n                        {{'TASK.TITLE.SHOW-FORM' | translate}}\n                    </span>\n\n                </button>\n            </div>\n        </div>\n    </div>\n\n    <div class=\"content clearfix scroll-container\" auto-height offset=\"6\" ng-if=\"model.task && !noSuchTask\" ng-class=\"{'split': activeTab == 'details' && hasDetails() == true}\">\n\n        <!-- FORM -->\n        <div class=\"section\" ng-show=\"activeTab == 'form' && model.formData != null && model.formData != undefined\">\n\n            <!-- unclaimed task-->\n            <div ng-if=\"model.task.assignee == null || model.task.assignee == undefined\">\n                <activiti-form form-definition=\"model.formData\" task-id=\"model.task.id\"\n                               ng-if=\"model.formData\"\n                               disable-form=\"model.task.assignee == null || model.task.assignee == undefined\"\n                               hide-buttons=\"model.task.endDate\"\n                               disable-form-text=\"'TASK.MESSAGE.CLAIM-TASK-FIRST'\">\n                </activiti-form>\n            </div>\n\n            <!-- task with assignee -->\n            <div ng-if=\"model.task.assignee && model.task.assignee.id != undefined && model.task.assignee.id != null && model.task.assignee.id != undefined\">\n                <activiti-form form-definition=\"model.formData\" task-id=\"model.task.id\"\n                               ng-if=\"model.formData\"\n                               hide-buttons=\"model.task.endDate || (model.task.assignee.id != account.id && (!model.task.initiatorCanCompleteTask || model.task.processInstanceStartUserId != ('' + account.id)))\">\n                </activiti-form>\n            </div>\n        </div>\n\n        <!-- COMMENTS -->\n        <div class=\"split-right\" ng-show=\"activeTab == 'details' && hasDetails() == true && !model.commentSummary.loading\">\n            <div class=\"section\">\n                <h3 close-on-select=\"false\" ng-click=\"toggleCreateComment()\" title=\"{{'TASK.ACTION.ADD-COMMENT' | translate}}\">{{'TASK.SECTION.COMMENTS' | translate}}\n                    <span class=\"action\" ng-if=\"!model.task.endDate\">\n                        <a>+</a>\n                    </span>\n                </h3>\n\n                <div class=\"form-group clearfix box\"\n                     ng-show=\"model.commentSummary.addComment\"\n                     auto-focus=\"model.commentSummary\">\n                    <textarea class=\"form-control focusable\" rows=\"2\" ng-disabled=\"model.commentSummary.loading\"\n                              ng-model=\"model.commentSummary.newComment\" id=\"add-comment-inline\"\n                              placeholder=\"{{'TASK.MESSAGE.NEW-COMMENT-PLACEHOLDER' | translate}}\">\n                    </textarea>\n\n                    <div class=\"pull-right\">\n                        <button tabindex=\"-1\" class=\"btn btn-xs\" translate=\"GENERAL.ACTION.CANCEL\"\n                                ng-click=\"toggleCreateComment()\" ng-disabled=\"model.commentSummary.loading\"></button>\n                        <button class=\"btn btn-xs\" translate=\"TASK.ACTION.ADD-COMMENT-CONFIRM\"\n                                ng-disabled=\"!model.commentSummary.newComment || model.commentSummary.loading || model.commentSummary.newComment.length > 4000\"\n                                ng-click=\"confirmNewComment()\"></button>\n                    </div>\n                </div>\n                <ul class=\"simple-list comments selectable\" ng-show=\"model.comments.data.length\">\n                    <li ng-repeat=\"comment in model.comments.data\">\n                        <div class=\"title\">\n                            <div user-picture=\"comment.createdBy\"></div>\n                            {{'TASK.MESSAGE.COMMENT-HEADER' | translate:comment}}\n                        </div>\n                        <div class=\"message\">{{comment.message}}</div>\n                    </li>\n                </ul>\n            </div>\n        </div>\n\n        <!-- INVOLVED PEOPLE AND CONTENT-->\n        <div class=\"split-left\" ng-show=\"activeTab == 'details' && hasDetails() == true\">\n            <div class=\"section pack\" ng-if=\"!$scope.model.commentSummary.loading\">\n                <h3 close-on-select=\"false\" select-people-popover on-people-selected=\"involvePerson(user)\" on-email-selected=\"involvePersonByEmail(email)\"\n                    placement=\"bottom-left\" exclude-task-id=\"model.task.id\" title=\"{{'TASK.ACTION.INVOLVE' | translate}}\">\n\n                    {{'TASK.SECTION.PEOPLE' | translate}}\n                        <span class=\"action\" ng-if=\"!model.task.endDate\">\n                            <a>+</a>\n                        </span>\n                </h3>\n\n                <ul class=\"simple-list selectable\">\n                    <li ng-repeat=\"person in model.task.involvedPeople\" class=\"clearfix\">\n\n                        <div user-picture=\"person\"></div> <span\n                            user-name=\"person\"></span>\n\n                        <div class=\"actions\" ng-if=\"!model.task.endDate\"><a><i class=\"icon icon-remove\"\n                                                   ng-click=\"removeInvolvedUser(person)\"></i></a></div>\n                    </li>\n                </ul>\n\n            </div>\n            <div class=\"section pack\" toggle-dragover=\"dragOverContent(over)\" ng-if=\"!$scope.model.contentSummary.loading\">\n                <h3 class=\"toggle-content-select\" ng-click=\"toggleCreateContent()\" title=\"{{'TASK.ACTION.ADD-CONTENT' | translate}}\">{{'TASK.TITLE.CONTENT' | translate}}\n                    <span class=\"action\" ng-if=\"!model.task.endDate\"><a>+</a></span>\n                </h3>\n\n                <div external-content on-content-upload=\"onContentUploaded(content)\" on-upload-in-progress=\"uploadInProgress(status)\" task-id=\"model.task.id\" ng-if=\"model.contentSummary.addContent\"></div>\n\n                <div class=\"form-group\">\n                    <ul id=\"related-content-list\" class=\"clearfix simple-list selectable content-list\">\n                        <li ng-repeat=\"content in model.content.data\" title=\"{{content.name}}\">\n                            <document-preview content=\"content\" editable=\"true\" read-only=\"false\" on-delete=\"onContentDeleted(content)\"></document-preview>\n                        </li>\n                    </ul>\n                </div>\n            </div>\n            <div class=\"section pack\" ng-if=\"!$scope.model.subTaskSummary.loading\">\n                <h3 id=\"toggle-add-subtask\" class=\"toggle-content-select\" ng-click=\"createSubTask('#toggle-add-subtask')\"> \n                    {{'TASK.TITLE.SUBTASK' | translate}}\n                    <span class=\"action\" ng-if=\"!model.task.endDate\">\n                            <a>+</a>\n                        </span>\n                </h3>\n\n                <div class=\"form-group\">\n                    <ul id=\"related-subtask-list\" class=\"full-list\">\n                        <li ng-repeat=\"task in model.subTasks\" title=\"{{task.name}}\" ng-click=\"openTaskInstance(task.id)\">\n                            <div>\n                                <div class=\"pull-right\">\n                        <span class=\"badge\" ng-if=\"task.dueDate\">\n                            {{'TASK.MESSAGE.DUE-ON' | translate}} {{(task.dueDate | dateformat:'fromNow')}}\n                        </span>\n                                    <span class=\"badge\" ng-if=\"!task.dueDate\">\n                            {{'TASK.MESSAGE.CREATED-ON' | translate}} {{(task.created | dateformat:'fromNow')}}\n                        </span>\n                                </div>\n                                <div class=\"title\">\n                                    {{task.name && task.name || ('TASK.MESSAGE.NO-NAME' | translate)}}\n                                </div>\n                                <div class=\"summary\">\n                                    {{task.description && task.description || ('TASK.MESSAGE.NO-DESCRIPTION' |\n                                    translate)}}\n                                </div>\n                                <div class=\"detail\">\n                        <span ng-if=\"task.assignee.id\">\n                            {{'TASK.MESSAGE.ASSIGNEE' | translate}} {{task.assignee.firstName && task.assignee.firstName != 'null' ? task.assignee.firstName : ''}} {{task.assignee.lastName && task.assignee.lastName != 'null' ? task.assignee.lastName : ''}}\n                        </span>\n                                    <span ng-if=\"!task.assignee.id\" translate=\"TASK.MESSAGE.NO-ASSIGNEE\">\n                        </span>\n                                </div>\n                            </div>\n                        </li>\n                    </ul>\n                </div>\n            </div>\n         </div>\n\n        <div class=\"help-container\" ng-if=\"activeTab == 'details' && model.task != null && model.task != undefined && hasDetails() == false && !model.involvementSummary.loading && !model.contentSummary.loading && !model.commentSummary.loading && !model.subTaskSummary.loading\">\n            <div>\n                <div class=\"help-text\">\n\n                    <div class=\"description\" ng-if=\"!model.task.endDate && model.task.assignee != null && model.task.assignee != undefined\">\n                        {{'TASK.HELP.DESCRIPTION' | translate}}\n                    </div>\n\n                    <div class=\"description\" ng-if=\"model.task.endDate\">\n                        {{'TASK.HELP.COMPLETED-DESCRIPTION' | translate}}\n                    </div>\n\n                    <div class=\"description\" ng-if=\"!model.task.endDate && (model.task.assignee == null || model.task.assignee == undefined)\">\n                        {{'TASK.HELP.DESCRIPTION-WITH-CLAIM' | translate}}\n                    </div>\n\n\n                    <div class=\"help-entry\" ng-if=\"!model.task.endDate\">\n                        <span class=\"glyphicon glyphicon-user\"></span>\n                        <span select-people-popover\n                              close-on-select=\"true\"\n                              on-people-selected=\"involvePerson(user)\"\n                              on-email-selected=\"involvePersonByEmail(email)\"\n                              placement=\"bottom\"\n                              exclude-task-id=\"model.task.id\"\n                              title=\"{{'TASK.ACTION.INVOLVE' | translate}}\">{{'TASK.HELP.ADD-PEOPLE' | translate}}</span>\n                    </div>\n                    <div ng-if=\"!model.task.endDate\">\n                        <div class=\"help-entry\"\n                             ng-click=\"toggleCreateContent()\"\n                             ng-if=\"model.contentSummary.addContent == null || model.contentSummary.addContent == undefined || model.contentSummary.addContent == false\">\n                            <span class=\"glyphicon glyphicon-list-alt\"></span>\n                            <span>{{'TASK.HELP.ADD-CONTENT' | translate}}</span>\n                        </div>\n\n                        <div external-content on-content-upload=\"onContentUploaded(content)\" on-upload-in-progress=\"uploadInProgress(status)\" task-id=\"model.task.id\" ng-if=\"model.contentSummary.addContent\"></div>\n                    </div>\n\n                    <div ng-if=\"!model.task.endDate\">\n                        <div ng-click=\"toggleCreateComment()\" class=\"help-entry\"\n                             ng-if=\"model.commentSummary.addComment == null || model.commentSummary.addComment == undefined || model.commentSummary.addComment == false\">\n                            <span class=\"glyphicon glyphicon-pencil\"></span>\n                            <span>{{'TASK.HELP.ADD-COMMENT' | translate}}</span>\n                        </div>\n\n                        <div class=\"form-group clearfix box\"\n                             ng-if=\"model.commentSummary.addComment\">\n                            <textarea class=\"form-control focusable\" rows=\"2\" ng-disabled=\"model.commentSummary.loading\"\n                                      ng-model=\"model.commentSummary.newComment\" id=\"add-comment-popup\"\n                                      placeholder=\"{{'TASK.MESSAGE.NEW-COMMENT-PLACEHOLDER' | translate}}\"\n                                    auto-focus>\n                            </textarea>\n\n                            <div class=\"pull-right\">\n                                <button tabindex=\"-1\" class=\"btn btn-xs\" translate=\"GENERAL.ACTION.CANCEL\"\n                                        ng-click=\"toggleCreateComment()\" ng-disabled=\"model.commentSummary.loading\"></button>\n                                <button class=\"btn btn-xs\" translate=\"TASK.ACTION.ADD-COMMENT-CONFIRM\"\n                                        ng-disabled=\"!model.commentSummary.newComment || model.commentSummary.loading || model.commentSummary.newComment.length > 4000\"\n                                        ng-click=\"confirmNewComment()\"></button>\n                            </div>\n                        </div>\n                    </div>\n\n                    <div ng-if=\"!model.task.endDate\">\n                        <div class=\"help-entry\"\n                             id=\"toggle-create-subtask\"\n                             ng-click=\"createSubTask('#toggle-create-subtask')\"\n                             ng-if=\"model.contentSummary.addContent == null || model.contentSummary.addContent == undefined || model.contentSummary.addContent == false\">\n                            <span class=\"glyphicon glyphicon-check\"></span>\n                            <span>{{'TASK.HELP.ADD-SUBTASK' | translate}}</span>\n                        </div>\n                    </div>\n\n                </div>\n            </div>\n        </div>\n\n    </div>\n</div>\n"
  },
  {
    "path": "flowable-ui-web/task/workflow/views/task-form-test.html",
    "content": "\n<div>\n    This is just for testing :\n    <div>\n        {{model.form}}\n    </div>\n</div>\n<br/><br/>\n\n<div>Rendered by Angular</div>\n<div style=\"padding: 20px;\">\n    <activiti-form form-data=\"model.form\"></activiti-form>\n</div>\n\n<br/><br/>\n\n<div>The Jquery directly rendered one:</div>\n<div id=\"someId\"></div>\n\n<br/><br/>\n\n<div>Rendered by the Angular wrapper of the jquery code</div>\n<activiti-form2 task-id=\"model.taskId\" form-model=\"model.form2\"></activiti-form2>\n\n<br/>\n<div>The model managed by jquery/angular:</div>\n<div>{{model.form2}}</div>\n\n"
  },
  {
    "path": "flowable-ui-web/task/workflow/views/task.html",
    "content": "<div class=\"main-content-wrapper\" ng-include=\"appResourceRoot + 'views/task-detail.html'\"></div>\n"
  },
  {
    "path": "flowable-ui-web/task/workflow/views/tasks.html",
    "content": "\n<div class=\"main-list\" id=\"main-list\" ng-if=\"!missingAppdefinition\">\n    <div class=\"list-header\" id=\"list-header\" click-anywhere=\"collapseFilter()\">\n\n        <div class=\"summary\" ng-show=\"!model.filter.expanded\" ng-click=\"expandFilter()\">\n            <span ng-if=\"model.filter.param.nonDefaultFilter\">{{'TASK.MESSAGE.FILTERED' | translate}}</span>\n            <span ng-if=\"!model.filter.param.nonDefaultFilter\">{{'TASK.MESSAGE.NO-FILTER' | translate}}</span>\n            <span class=\"pull-right\"><span class=\"glyphicon glyphicon-filter\"></span></span>\n        </div>\n\n        <div class=\"summary\" ng-show=\"model.filter.expanded\" custom-keys escape-pressed=\"collapseFilter()\">\n            <div class=\"form-group\" >\n                <label translate=\"TASK.FILTER.TEXT\"></label>\n                <input class=\"form-control\" type=\"text\" placeholder=\"{{'TASK.FILTER.TEXT-PLACEHOLDER' | translate}}\"\n                       auto-focus=\"model.filter.expanded\"\n                       ng-model=\"model.filter.param.text\" ng-change=\"refreshFilter()\" ng-debounce=\"400\">\n            </div>\n\n            <div class=\"form-group\">\n                <label translate=\"TASK.FILTER.STATE\"></label>\n                <div class=\"selection toggle\">\n                    <div class=\"toggle-2\" ng-repeat=\"option in model.stateFilterOptions\" ng-class=\"{'active' : model.filter.param.state.id == option.id}\">\n                        <button class=\"btn btn-xs\" ng-click=\"selectStateFilter(option)\">{{option.title | translate}}</button>\n                    </div>\n                </div>\n            </div>\n\n            <div class=\"form-group\">\n                <label translate=\"TASK.FILTER.PROCESS-DEFINITION\"></label>\n                <select class=\"form-control\"\n                        ng-options=\"option.id as option.name for option in model.processDefinitions\"\n                        ng-model=\"model.filter.param.processDefinitionId\"\n                        ng-change=\"collapseFilter();refreshFilter()\"\n                        ng-disabled=\"model.loading\">\n                </select>\n            </div>\n\n            <div class=\"form-group\">\n                <label translate=\"TASK.FILTER.ASSIGNMENT\"></label>\n                <select class=\"form-control\"\n                        ng-options=\"option.id as option.title for option in model.assignmentOptions\"\n                        ng-model=\"model.filter.param.assignment\"\n                        ng-change=\"collapseFilter();refreshFilter()\"\n                        ng-disabled=\"model.loading\">\n                </select>\n            </div>\n\n            <div class=\"text-center\">\n                <button class=\"btn btn-sm\" ng-click=\"resetFilters(true); refreshFilter();\">{{'TASK.FILTER.RESET' | translate}}</button>\n            </div>\n\n        </div>\n    </div>\n    <div class=\"list-subheader clearfix\">\n        <div class=\"btn-group pull-left\">\n            <button id=\"toggle-create-task\" class=\"btn btn-xs dropdown-toggle toggle-create-task\" translate=\"TASK.ACTION.CREATE\" ng-click=\"createTask()\">&nbsp;</button>\n        </div>\n        <div class=\"sort\">\n            <div class=\"dropdown btn-group btn-group-sm\">\n                <a class=\"dropdown-toggle\" trigger=\"click\" placement=\"bottom-right\" ng-model=\"model.filter.param.sort\" ng-change=\"sortChanged()\"\n                   ng-options=\"sort.id as (sort.title | translate) for sort in model.sorts\" bs-select></a>\n                </ul>\n            </div>\n        </div>\n    </div>\n\n    <div loading=\"model.filter.loading\"></div>\n    <div class=\"list-wrapper\" ng-show=\"!model.filter.loading\" auto-height>\n\n        <ul class=\"full-list\" scroll-to-active=\"selectedTask\" use-parent=\"true\" offset-top=\"100\">\n            <li ng-repeat=\"task in model.tasks\" ng-class=\"{'active': selectedTask.id == task.id}\" ng-click=\"selectTask(task)\">\n                <div>\n                    <div class=\"pull-right\">\n                        <span class=\"badge\" ng-if=\"task.dueDate\">\n                            {{'TASK.MESSAGE.DUE-ON' | translate}} {{(task.dueDate | dateformat:'fromNow')}}\n                        </span>\n                        <span class=\"badge\" ng-if=\"!task.dueDate\">\n                            {{'TASK.MESSAGE.CREATED-ON' | translate}} {{(task.created | dateformat:'fromNow')}}\n                        </span>\n                    </div>\n                    <div class=\"title\">\n                        {{task.name && task.name || ('TASK.MESSAGE.NO-NAME' | translate)}}\n                    </div>\n                    <div class=\"summary\">\n                        {{task.description && task.description || ('TASK.MESSAGE.NO-DESCRIPTION' | translate)}}\n                    </div>\n                    <div class=\"detail\">\n                        <span ng-if=\"task.assignee.id\">\n                            {{'TASK.MESSAGE.ASSIGNEE' | translate}} {{task.assignee.firstName && task.assignee.firstName != 'null' ? task.assignee.firstName : ''}} {{task.assignee.lastName && task.assignee.lastName != 'null' ? task.assignee.lastName : ''}}\n                        </span>\n                        <span ng-if=\"!task.assignee.id\" translate=\"TASK.MESSAGE.NO-ASSIGNEE\">\n                        </span>\n                    </div>\n                </div>\n            </li>\n            <li class=\"more\" ng-if=\"model.hasNextPage && !model.filter.loading\" ng-click=\"nextPage()\">\n                <i class=\"icon icon-caret-right\"></i> {{'GENERAL.ACTION.SHOW-MORE' | translate}}\n            </li>\n        </ul>\n        <div class=\"nothing-to-see\" ng-show=\"model.tasks.length == 0\">\n            <span  translate=\"TASK.MESSAGE.NO-TASKS\"></span>\n        </div>\n    </div>\n</div>\n\n<div class=\"main-content-wrapper\" ng-include=\"appResourceRoot + 'views/task-detail.html'\" ng-if=\"!missingAppdefinition\"></div>\n\n<div ng-if=\"missingAppdefinition\" ng-include=\"appResourceRoot + 'views/integration-mode-error.html'\"></div>"
  },
  {
    "path": "flowable-ui-web/task/workflow/views/templates/date-picker-row-edit-template.html",
    "content": "<div class=\"popover dropdown-menu datepicker\" ng-class=\"'datepicker-mode-' + $mode\" style=\"max-width: 320px;\">\n    <div class=\"arrow\"></div>\n    <div class=\"popover-header\">\n        <span translate=\"TASK.TITLE.SELECT-DATE\"></span>\n        <div class=\"actions\">\n            <a ng-click=\"closeDatePopupEditRow(columnDefinition); $hide()\">{{'GENERAL.ACTION.CLOSE' | translate}}</a>\n        </div>\n    </div>\n    <div class=\"popover-content\">\n        <div class=\"center\">\n            <div class=\"btn-group span\">\n                <button class=\"btn btn-xs\" ng-click=\"clearDateEditRow(columnDefinition, $select); $hide()\" translate=\"TASK.ACTION.CLEAR-DATE\"></button>\n                <button class=\"btn btn-xs\" ng-click=\"selectTodayEditRow(columnDefinition, $select); $hide()\" translate=\"TASK.ACTION.DATE-TODAY\"></button>\n            </div>\n        </div>\n        <div class=\"section\">\n            <table style=\"table-layout: fixed; height: 100%; width: 100%;\">\n                <thead>\n                <tr class=\"text-center\">\n                    <th>\n                        <button tabindex=\"-1\" type=\"button\" class=\"btn btn-default pull-left\" ng-click=\"$selectPane(-1)\">\n                            <i class=\"{{$iconLeft}}\"></i>\n                        </button>\n                    </th>\n                    <th colspan=\"{{ rows[0].length - 2 }}\">\n                        <button tabindex=\"-1\" type=\"button\" class=\"btn btn-default btn-block text-strong\"  ng-click=\"$toggleMode()\">\n                            <strong style=\"text-transform: capitalize;\" ng-bind=\"title\"></strong>\n                        </button>\n                    </th>\n                    <th>\n                        <button tabindex=\"-1\" type=\"button\" class=\"btn btn-default pull-right\" ng-click=\"$selectPane(+1)\">\n                            <i class=\"{{$iconRight}}\"></i>\n                        </button>\n                    </th>\n                </tr>\n                <tr ng-show=\"showLabels\" ng-bind-html=\"labels\"></tr>\n                </thead>\n                <tbody class=\"calendar-grid\">\n                <tr ng-repeat=\"(i, row) in rows\" height=\"{{ 100 / rows.length }}%\">\n                    <td class=\"text-center\" ng-repeat=\"(j, el) in row\">\n                        <button tabindex=\"-1\" type=\"button\" class=\"btn btn-default\" style=\"width: 100%\" ng-class=\"{'btn-primary': el.selected, 'btn-info btn-today': el.isToday && !el.selected}\" ng-click=\"$select(el.date)\" ng-disabled=\"el.disabled\">\n                            <span ng-class=\"{'text-muted': el.muted}\" ng-bind=\"el.label\"></span>\n                        </button>\n                    </td>\n                </tr>\n                </tbody>\n            </table>\n        </div>\n    </div>\n</div>"
  },
  {
    "path": "flowable-ui-web/task/workflow/views/templates/date-picker-template.html",
    "content": "<div class=\"popover dropdown-menu datepicker\" ng-class=\"'datepicker-mode-' + $mode\" style=\"max-width: 320px;\">\n    <div class=\"arrow\"></div>\n    <div class=\"popover-header\">\n        <span translate=\"TASK.TITLE.SELECT-DATE\"></span>\n        <div class=\"actions\">\n            <a ng-click=\"closeDatePopup(field); $hide()\">{{'GENERAL.ACTION.CLOSE' | translate}}</a>\n        </div>\n    </div>\n    <div class=\"popover-content\">\n        <div class=\"center\">\n            <div class=\"btn-group span\">\n                <button class=\"btn btn-xs\" ng-click=\"clearDate(field, $select); $hide()\" translate=\"TASK.ACTION.CLEAR-DATE\"></button>\n                <button class=\"btn btn-xs\" ng-click=\"selectToday(field, $select); $hide()\" translate=\"TASK.ACTION.DATE-TODAY\"></button>\n            </div>\n        </div>\n        <div class=\"section\">\n            <table style=\"table-layout: fixed; height: 100%; width: 100%;\">\n                <thead>\n                <tr class=\"text-center\">\n                    <th>\n                        <button tabindex=\"-1\" type=\"button\" class=\"btn btn-default pull-left\" ng-click=\"$selectPane(-1)\">\n                            <i class=\"{{$iconLeft}}\"></i>\n                        </button>\n                    </th>\n                    <th colspan=\"{{ rows[0].length - 2 }}\">\n                        <button tabindex=\"-1\" type=\"button\" class=\"btn btn-default btn-block text-strong\"  ng-click=\"$toggleMode()\">\n                            <strong style=\"text-transform: capitalize;\" ng-bind=\"title\"></strong>\n                        </button>\n                    </th>\n                    <th>\n                        <button tabindex=\"-1\" type=\"button\" class=\"btn btn-default pull-right\" ng-click=\"$selectPane(+1)\">\n                            <i class=\"{{$iconRight}}\"></i>\n                        </button>\n                    </th>\n                </tr>\n                <tr ng-show=\"showLabels\" ng-bind-html=\"labels\"></tr>\n                </thead>\n                <tbody class=\"calendar-grid\">\n                <tr ng-repeat=\"(i, row) in rows\" height=\"{{ 100 / rows.length }}%\">\n                    <td class=\"text-center\" ng-repeat=\"(j, el) in row\">\n                        <button tabindex=\"-1\" type=\"button\" class=\"btn btn-default\" style=\"width: 100%\" ng-class=\"{'btn-primary': el.selected, 'btn-info btn-today': el.isToday && !el.selected}\" ng-click=\"$select(el.date)\" ng-disabled=\"el.disabled\">\n                            <span ng-class=\"{'text-muted': el.muted}\" ng-bind=\"el.label\"></span>\n                        </button>\n                    </td>\n                </tr>\n                </tbody>\n            </table>\n        </div>\n    </div>\n</div>"
  },
  {
    "path": "flowable-ui-web/task/workflow/views/templates/document-preview.html",
    "content": "<div title=\"{{content.name}}\">\n\n  <i ng-show=\"content.contentAvailable\" class=\"icon icon-{{content.simpleType}}\"\n     ng-if=\"content.simpleType\"></i>\n  {{content.name}}\n\n  <div class=\"actions\">\n    <a ng-show=\"content.contentAvailable && (!content.source)\" target=\"_blank\" download=\"{{content.name}}\"\n       href=\"{{content.rawUrl}}\" ng-click=\"$event.stopPropagation();\"> <i\n            class=\"icon icon-download\"></i></a>\n    <a ng-show=\"!readOnly\" ng-click=\"deleteContent(content); $event.preventDefault(); $event.stopPropagation();\"><i\n              class=\"icon icon-remove\"></i></a>\n  </div>\n  <div class=\"subtle\">{{'TASK.MESSAGE.CONTENT-UPLOADED-BY' | translate}} <span\n          user-name=\"content.createdBy\"></span> , {{content.created | dateformat}}\n  </div>\n</div>\n"
  },
  {
    "path": "flowable-ui-web/task/workflow/views/templates/due-date-picker-template.html",
    "content": "<div class=\"popover dropdown-menu datepicker\" ng-class=\"'datepicker-mode-' + $mode\" style=\"max-width: 320px;\" click-anywhere=\"$hide()\" ignore=\"due-date-select\">\n    <div class=\"arrow\"></div>\n    <div class=\"popover-header\">\n        <span translate=\"TASK.TITLE.SELECT-DUEDATE\"></span>\n        <div class=\"actions\">\n            <a ng-click=\"$hide()\">{{'GENERAL.ACTION.CLOSE' | translate}}</a>\n        </div>\n    </div>\n    <div class=\"popover-content\">\n        <div class=\"center\">\n            <div class=\"btn-group span\">\n                <button class=\"btn btn-xs\" ng-click=\"$select()\" translate=\"TASK.ACTION.CLEAR-DUEDATE\"></button>\n                <button class=\"btn btn-xs\" ng-click=\"$select(today)\" translate=\"TASK.ACTION.DUE-TODAY\"></button>\n            </div>\n        </div>\n        <div class=\"section\">\n            <table style=\"table-layout: fixed; height: 100%; width: 100%;\">\n                <thead>\n                <tr class=\"text-center\">\n                    <th>\n                        <button tabindex=\"-1\" type=\"button\" class=\"btn btn-default pull-left\" ng-click=\"$selectPane(-1)\">\n                            <i class=\"{{$iconLeft}}\"></i>\n                        </button>\n                    </th>\n                    <th colspan=\"{{ rows[0].length - 2 }}\">\n                        <button tabindex=\"-1\" type=\"button\" class=\"btn btn-default btn-block text-strong\"  ng-click=\"$toggleMode()\">\n                            <strong style=\"text-transform: capitalize;\" ng-bind=\"title\"></strong>\n                        </button>\n                    </th>\n                    <th>\n                        <button tabindex=\"-1\" type=\"button\" class=\"btn btn-default pull-right\" ng-click=\"$selectPane(+1)\">\n                            <i class=\"{{$iconRight}}\"></i>\n                        </button>\n                    </th>\n                </tr>\n                <tr ng-show=\"showLabels\" ng-bind-html=\"labels\"></tr>\n                </thead>\n                <tbody class=\"calendar-grid\">\n                <tr ng-repeat=\"(i, row) in rows\" height=\"{{ 100 / rows.length }}%\">\n                    <td class=\"text-center\" ng-repeat=\"(j, el) in row\">\n                        <button tabindex=\"-1\" type=\"button\" class=\"btn btn-default\" style=\"width: 100%\" ng-class=\"{'btn-primary': el.selected, 'btn-info btn-today': el.isToday && !el.selected}\" ng-click=\"$select(el.date)\" ng-disabled=\"el.disabled\">\n                            <span ng-class=\"{'text-muted': el.muted}\" ng-bind=\"el.label\"></span>\n                        </button>\n                    </td>\n                </tr>\n                </tbody>\n            </table>\n        </div>\n    </div>\n</div>"
  },
  {
    "path": "flowable-ui-web/task/workflow/views/templates/form-element-template.html",
    "content": "<div ng-if=\"field != null && field != undefined && !field.readOnly\" ng-switch=\"field.type\">\n\n    <div ng-switch-when=\"text\" class=\"form-group\" ng-show=\"field.isVisible\" ng-class=\"{'has-error': field.required && isEmpty(field)}\">\n        <label class=\"control-label\">{{field.name}}</label>\n        <span class=\"marker\" ng-if=\"field.required\">*</span>\n        <input id=\"{{activitiFieldIdPrefix + field.id}}\" type=\"text\" name=\"{{field.id}}\" class=\"form-control\" placeholder=\"{{field.placeholder}}\" ng-model=\"field.value\" ng-change=\"onFieldValueChange(field)\" ng-blur=\"onFieldBlur(field)\" ng-focus=\"onFieldFocus(field)\" ng-required=\"field.required\" ng-minlength=\"{{field.params.minLength || ''}}\" maxlength=\"{{field.params.maxLength || ''}}\" ng-pattern=\"field.params.regexPattern || ''\" ui-mask=\"{{field.params.mask || ''}}\">\n    </div>\n    \n   <div ng-switch-when=\"password\" class=\"form-group\" ng-show=\"field.isVisible\" ng-class=\"{'has-error': field.required && isEmpty(field)}\">\n        <label class=\"control-label\">{{field.name}}</label>\n        <span class=\"marker\" ng-if=\"field.required\">*</span>\n        <div class=\"input-group\" ng-if=\"field.params.passwordunmask\">\n        <input id=\"{{activitiFieldIdPrefix + field.id}}\" type=\"{{field.params.type? 'text' : 'password' }}\" name=\"{{field.id}}\" class=\"form-control\" placeholder=\"{{field.placeholder}}\" ng-model=\"field.value\" ng-change=\"onFieldValueChange(field)\" ng-blur=\"onFieldBlur(field)\" ng-focus=\"onFieldFocus(field)\" ng-required=\"field.required\" ng-minlength=\"{{field.params.minLength || ''}}\" maxlength=\"{{field.params.maxLength || ''}}\">\n        <span ng-if=\"field.params.passwordunmask\" class=\"input-group-btn\">\n        \t\t<button class=\"btn glyphicon\" ng-class=\"{'glyphicon-eye-open': !field.params.type, 'glyphicon-eye-close': field.params.type }\" type=\"button\" ng-click=\"togglePasswordFieldType(field)\"></button>\n      \t</span>\n      \t</div>\n      \t<input id=\"{{activitiFieldIdPrefix + field.id}}\" type=\"password\" name=\"{{field.id}}\" class=\"form-control\" placeholder=\"{{field.placeholder}}\" ng-model=\"field.value\" ng-change=\"onFieldValueChange(field)\" ng-blur=\"onFieldBlur(field)\" ng-focus=\"onFieldFocus(field)\" ng-required=\"field.required\" ng-minlength=\"{{field.params.minLength || ''}}\" maxlength=\"{{field.params.maxLength || ''}}\" ng-if=\"!field.params.passwordunmask\">\n    </div>\n\n    <div ng-switch-when=\"multi-line-text\" class=\"form-group\" ng-show=\"field.isVisible\" ng-class=\"{'has-error': field.required && isEmpty(field)}\">\n        <label class=\"control-label\">{{field.name}}</label>\n        <span class=\"marker\" ng-if=\"field.required\">*</span>\n        <textarea id=\"{{activitiFieldIdPrefix + field.id}}\" name=\"{{field.id}}\" class=\"form-control\" placeholder=\"{{field.placeholder}}\" ng-model=\"field.value\" ng-change=\"onFieldValueChange(field)\" ng-blur=\"onFieldBlur(field)\" ng-focus=\"onFieldFocus(field)\" ng-required=\"field.required\" ng-minlength=\"{{field.params.minLength || ''}}\" maxlength=\"{{field.params.maxLength || ''}}\" ng-pattern=\"field.params.regexPattern || ''\" ui-mask=\"{{field.params.mask || ''}}\"></textarea>\n    </div>\n\n    <div ng-switch-when=\"integer\" class=\"form-group\" ng-show=\"field.isVisible\" ng-class=\"{'has-error': field.required && isEmpty(field)}\">\n        <label class=\"control-label\">{{field.name}}</label>\n        <span class=\"marker\" ng-if=\"field.required\">*</span>\n        <input id=\"{{activitiFieldIdPrefix + field.id}}\" type=\"text\" name=\"{{field.id}}\" class=\"form-control\" placeholder=\"{{field.placeholder}}\" ng-model=\"field.value\" ng-change=\"onFieldValueChange(field)\" ng-blur=\"onFieldBlur(field)\" ng-focus=\"onFieldFocus(field)\" number-input-check ng-required=\"field.required\" ng-minlength=\"{{field.params.minLength || ''}}\" maxlength=\"{{field.params.maxLength || ''}}\" ng-pattern=\"field.params.regexPattern || ''\" ui-mask=\"{{field.params.mask || ''}}\">\n    </div>\n    \n    <div ng-switch-when=\"decimal\" class=\"form-group\" ng-show=\"field.isVisible\" ng-class=\"{'has-error': field.required && isEmpty(field)}\">\n        <label class=\"control-label\">{{field.name}}</label>\n        <span class=\"marker\" ng-if=\"field.required\">*</span>\n        <input id=\"{{activitiFieldIdPrefix + field.id}}\" type=\"text\" name=\"{{field.id}}\" class=\"form-control\" placeholder=\"{{field.placeholder}}\" ng-model=\"field.value\" ng-change=\"onFieldValueChange(field)\" ng-blur=\"onFieldBlur(field)\" ng-focus=\"onFieldFocus(field)\" decimal-number-input-check ng-required=\"field.required\" ng-minlength=\"{{field.params.minLength || ''}}\" maxlength=\"{{field.params.maxLength || ''}}\" ng-pattern=\"field.params.regexPattern || ''\" ui-mask=\"{{field.params.mask || ''}}\">\n    </div>\n\n    <div ng-switch-when=\"date\" class=\"form-group\" ng-show=\"field.isVisible\" ng-class=\"{'has-error': field.required && isEmpty(field)}\">\n        <label class=\"control-label\"><i class=\"glyphicon glyphicon-calendar\"></i> {{field.name}}</label>\n        <span class=\"marker\" ng-if=\"field.required\">*</span>\n        <span class=\"control-label\" ng-if=\"field.acceptedFormat\">({{field.acceptedFormat}})</span>\n        <input id=\"{{activitiFieldIdPrefix + field.id}}\" name=\"{{field.id}}\" type=\"text\" class=\"form-control \" placeholder=\"{{field.placeholder}}\" ng-model=\"field.value\" ng-change=\"onFieldValueChange(field)\" bs-datepicker restrict-input template=\"{{appResourceRoot}}views/templates/date-picker-template.html\" data-container=\"body\" data-date-format=\"d-M-yyyy\" trigger=\"focus\" autoclose=\"true\" ng-required=\"field.required\">\n    </div>\n\n    <div ng-switch-when=\"boolean\" class=\"form-group\" ng-show=\"field.isVisible\" ng-class=\"{'has-error': field.required && isEmpty(field)}\">\n        <label class=\"control-label\" style=\"cursor: pointer;\">\n            <input id=\"{{activitiFieldIdPrefix + field.id}}\" type=\"checkbox\" name=\"{{field.id}}\" ng-model=\"field.value\" ng-change=\"onFieldValueChange(field)\" ng-blur=\"onFieldBlur(field)\" ng-focus=\"onFieldFocus(field)\" ng-required=\"field.required\"> <span>{{field.name}}</span>\n            <span class=\"marker\" ng-if=\"field.required\">*</span>\n        </label>\n    </div>\n\n    <div ng-switch-when=\"dropdown\" class=\"form-group\" ng-show=\"field.isVisible\" ng-class=\"{'has-error': field.required && isEmptyDropdown(field)}\">\n        <label class=\"control-label\">{{field.name}}</label>\n        <span class=\"marker\" ng-if=\"field.required\">*</span>\n        <select id=\"{{activitiFieldIdPrefix + field.id}}\" class=\"form-control\" name=\"{{field.id}}\"\n                ng-options=\"option.name for option in field.options\" ng-model=\"field.value\" ng-change=\"onFieldValueChange(field)\" ng-blur=\"onFieldBlur(field)\" ng-focus=\"onFieldFocus(field)\" ng-required=\"field.required\">\n            <option style=\"display:none\" value=\"\">{{field.placeholder}}</option>\n        </select>\n    </div>\n\n    <div ng-switch-when=\"radio-buttons\" class=\"form-group\" ng-if=\"field.isVisible\" ng-class=\"{'has-error': field.required && isEmpty(field)}\">\n        <div>\n            <label class=\"control-label\">{{field.name}}</label>\n            <span class=\"marker\" ng-if=\"field.required\">*</span>\n        </div>\n        <div id=\"{{activitiFieldIdPrefix + field.id}}\">\n            <div ng-repeat=\"option in field.options\" class=\"radio\">\n                <label class=\"control-label\">\n                    <input id=\"{{activitiFieldIdPrefix + field.id}}_{{$index}}\" type=\"radio\"\n                           value=\"{{option.id ? option.id : option.name}}\"\n                           name=\"{{field.id}}\"\n                           ng-required=\"field.required\"\n                           ng-model=\"field.value\"\n                           ng-change=\"onFieldValueChange(field)\">\n                    {{option.name}}\n                    </input>\n                </label>\n            </div>\n        </div>\n    </div>\n\n    <div ng-switch-when=\"people\" class=\"form-group\" ng-show=\"field.isVisible\" ng-class=\"{'has-error': field.required && isEmpty(field)}\">\n        <label class=\"control-label\">{{field.name}}</label>\n        <span class=\"marker\" ng-if=\"field.required\">*</span>\n        <div id=\"{{activitiFieldIdPrefix + field.id}}\" class=\"people-select\">\n            <ul class=\"simple-list\">\n                <li class=\"action\" select-people-popover popover-title=\"{{field.name}}\" placement=\"bottom-left\" on-people-selected=\"fieldPersonSelected(user, field)\"\n                    restrict-with-group=\"field.params.restrictWithGroup\" ng-required=\"field.required\">\n                    <div ng-if=\"field.value && field.value.id\" user-picture=\"field.value\"></div>\n                    <span ng-if=\"!field.value && !field.placeholder\" translate=\"FORM.MESSAGE.SELECT-PERSON\"></span>\n                    <span ng-if=\"!field.value && field.placeholder\" translate=\"{{field.placeholder}}\"></span>\n                    <div ng-if=\"field.value && field.value.id\" user-link=\"field.value\"></div>\n                    <span ng-if=\"field.value && !field.value.id\">{{field.value}}</span>\n                    <div class=\"actions\" ng-if=\"field.value\">\n                        <a ng-click=\"fieldPersonRemoved(field.value, field)\"><i class=\"icon icon-remove\"></i></a>\n                    </div>\n                </li>\n            </ul>\n        </div>\n    </div>\n\n    <div ng-switch-when=\"functional-group\" class=\"form-group\" ng-show=\"field.isVisible\" ng-class=\"{'has-error': field.required && isEmpty(field)}\">\n        <label class=\"control-label\">{{field.name}}</label>\n        <span class=\"marker\" ng-if=\"field.required\">*</span>\n        <div id=\"{{activitiFieldIdPrefix + field.id}}\" class=\"people-select\">\n            <ul class=\"simple-list\">\n                <li class=\"action\" select-functional-group-popover popover-title=\"{{field.name}}\" placement=\"bottom-left\"\n                    on-group-selected=\"fieldGroupSelected(group, field)\" restrict-with-group=\"field.params.restrictWithGroup\">\n                    <span ng-if=\"!field.value && !field.placeholder\" translate=\"FORM.MESSAGE.SELECT-GROUP\"></span>\n                    <span ng-if=\"!field.value && field.placeholder\" translate=\"{{field.placeholder}}\"></span>\n                    <div ng-if=\"field.value && field.value.id && field.value.name\">{{field.value.name}}</div>\n                    <div class=\"actions\" ng-if=\"field.value && field.value.id && field.value.name\">\n                        <a ng-click=\"fieldGroupRemoved(field.value, field)\"><i class=\"icon icon-remove\"></i></a>\n                    </div>\n                </li>\n            </ul>\n        </div>\n    </div>\n\n    <div ng-switch-when=\"upload\" class=\"form-group\" ng-class=\"{'has-error' : field.required && isEmpty(field)}\" ng-show=\"field.isVisible\">\n        <label class=\"control-label\">{{field.name}}</label>\n        <span class=\"marker\" ng-if=\"field.required\">*</span>\n        <ul class=\"simple-list\" ng-show=\"model.uploads[field.id].length > 0\">\n            <li ng-repeat=\"content in model.uploads[field.id]\">\n                <i class=\"icon icon-{{content.simpleType}}\"></i>\n                {{content.name}}\n                <div class=\"actions\">\n                    <a ng-click=\"removeContent(content, field)\"><i class=\"icon icon-remove\"></i></a>\n                </div>\n            </li>\n        </ul>\n        <div id=\"{{activitiFieldIdPrefix + field.id}}\" external-content link-only=\"field.params.link\"\n             on-content-upload=\"contentUploaded(content, field)\"\n             on-upload-in-progress=\"uploadInProgress(status)\"\n             ng-show=\"field.params.multiple || (!field.params.multiple && model.uploads[field.id].length != 1)\"></div>\n    </div>\n    \n    <div ng-switch-when=\"hyperlink\" class=\"form-group {{field.className}}\" ng-show=\"field.isVisible\">\n        <label class=\"control-label\">{{field.name}}</label>\n        <div>\n             <a id=\"{{activitiFieldIdPrefix + field.id}}\" ng-href=\"{{field.value}}\" target=\"_blank\">{{field.value}}</a>\n        </div>\n    </div>\n\n\t<div ng-switch-when=\"spacer\" class=\"form-group\" ng-show=\"field.isVisible\" >\n        <br id=\"{{activitiFieldIdPrefix + field.id}}\" name=\"{{field.id}}\" />\n    </div>\n\t\n\t<div ng-switch-when=\"horizontal-line\" class=\"row,form-group\" ng-show=\"field.isVisible\" >\n\t\t<hr id=\"{{activitiFieldIdPrefix + field.id}}\" name=\"{{field.id}}\" >\n    </div>\n    \n     <div ng-switch-when=\"headline\" class=\"form-group\" ng-show=\"field.isVisible\">\n\t\t<h4 id=\"{{activitiFieldIdPrefix + field.id}}\" name=\"{{field.id}}\"><strong>{{field.name}}</strong></h4>\n  \t</div>\n\n\t <div ng-switch-when=\"headline-with-line\" class=\"form-group\" ng-show=\"field.isVisible\">\n\t\t<h4 id=\"{{activitiFieldIdPrefix + field.id}}\" name=\"{{field.id}}\"><strong>{{field.name}}</strong></h4>\n\t\t<hr>\n\t </div>\n\n    <div ng-switch-when=\"expression\" class=\"form-group\" ng-show=\"field.isVisible\">\n    \t<div class=\"well well-sm\" ng-style=\"{'font-size': field.params.size + 'em'}\">\n    \t\t<div ng-show=\"!field.value && !field.expression\">\n    \t\t\t{{'FORM.MESSAGE.EMPTY' | translate}}\n    \t\t</div>\n    \t\t<div ng-show=\"!field.value\">\n    \t\t\t{{field.expression}}\n    \t\t</div>\n    \t\t<div ng-show=\"field.value\">\n    \t\t\t{{field.value}}\n    \t\t</div>        \t\n        </div>\n    </div>\n</div>\n\n<div ng-if=\"field != null && field != undefined && field.readOnly\" ng-switch=\"field.type\">\n    <div ng-switch-when=\"boolean\" ng-show=\"field.isVisible\">\n        <label class=\"checkbox\">\n            <input type=\"checkbox\" class=\"checkbox\" ng-checked=\"{{field.value}}\" disabled />\n            {{field.name}}\n        </label>\n    </div>\n\n\t<div ng-switch-when=\"people\" ng-show=\"field.isVisible\">\n        <label class=\"control-label\">{{field.name}}</label>\n        <span ng-if=\"!field.value\" translate=\"FORM.MESSAGE.EMPTY\"></span>\n        <ul class=\"simple-list\" ng-if=\"field.value\">\n            <li>\n                <div user-picture=\"field.value\"></div>\n                <div user-link=\"field.value\"></div>\n            </li>\n        </ul>\n    </div>\n    <div ng-switch-when=\"functional-group\" ng-show=\"field.isVisible\">\n        <label class=\"control-label\">{{field.name}}</label>\n        <span ng-if=\"!field.value\" translate=\"FORM.MESSAGE.EMPTY\"></span>\n        <ul class=\"simple-list\" ng-if=\"field.value && field.value.name\">\n            <li>\n                <div>{{field.value.name}}</div>\n            </li>\n        </ul>\n    </div>\n    <div ng-switch-when=\"upload\" ng-show=\"field.isVisible\">\n        <label class=\"control-label\">{{field.name}}</label>\n        <span ng-if=\"!field.value || field.value.length == 0\" translate=\"FORM.MESSAGE.EMPTY\"></span>\n        <ul class=\"simple-list selectable content-list\">\n            <li ng-repeat=\"content in model.uploads[field.id]\" title=\"{{content.name}}\">\n                <document-preview content=\"content\" editable=\"field.params.documentsEditable\" read-only=\"true\"></document-preview>\n            </li>\n        </ul>\n        <div class=\"clearfix\"></div>\n    </div>\n\n   <div ng-switch-when=\"hyperlink\" class=\"form-group {{field.className}} readonly\" ng-show=\"field.isVisible\">\n         <label class=\"control-label\">{{field.name}}</label>\n         <div>\n             <a ng-href=\"{{field.params.hyperlinkUrl}}\" target=\"_blank\">{{field.params.hyperlinkUrl}}</a>\n         </div>\n    </div>\t\n\t\n    <div ng-switch-when=\"radio-buttons\" class=\"form-group\" ng-show=\"field.isVisible\">\n        <label class=\"control-label\">{{field.name}}</label>\n        <div class=\"well well-sm\">\n            {{field.value && field.value || ('FORM.MESSAGE.EMPTY' | translate)}}\n        </div>\n    </div>\n\n    <div ng-switch-when=\"multi-line-text\" class=\"form-group\" ng-show=\"field.isVisible\">\n        <label class=\"control-label\">{{field.name}}</label>\n        <textarea class=\"form-control\" readonly>{{field.value && field.value || ('FORM.MESSAGE.EMPTY' | translate)}}</textarea>\n    </div>\n    \n   \t<div ng-switch-when=\"spacer\" class=\"form-group\" ng-show=\"field.isVisible\" >\n        <br id=\"{{activitiFieldIdPrefix + field.id}}\" name=\"{{field.id}}\" />\n    </div>\n\t\n\t<div ng-switch-when=\"horizontal-line\" class=\"row,form-group\" ng-show=\"field.isVisible\" >\n\t\t<hr id=\"{{activitiFieldIdPrefix + field.id}}\" name=\"{{field.id}}\" >\n    </div>\n    \n     <div ng-switch-when=\"headline\" class=\"form-group\" ng-show=\"field.isVisible\">\n\t\t<h4 id=\"{{activitiFieldIdPrefix + field.id}}\" name=\"{{field.id}}\"><strong>{{field.name}}</strong></h4>\n  \t</div>\n\n\t <div ng-switch-when=\"headline-with-line\" class=\"form-group\" ng-show=\"field.isVisible\">\n\t\t<h4 id=\"{{activitiFieldIdPrefix + field.id}}\" name=\"{{field.id}}\"><strong>{{field.name}}</strong></h4>\n\t\t<hr>\n\t </div>    \n    \n    <div ng-switch-when=\"expression\" ng-show=\"field.isVisible\">\n        <div class=\"well well-sm\" ng-style=\"{'font-size': field.params.size + 'em'}\">\n    \t\t<div ng-show=\"!field.value && !field.expression\">\n    \t\t\t{{'FORM.MESSAGE.EMPTY' | translate}}\n    \t\t</div>\n    \t\t<div ng-show=\"!field.value\">\n    \t\t\t{{field.expression}}\n    \t\t</div>\n    \t\t<div ng-show=\"field.value\">\n    \t\t\t{{field.value}}\n    \t\t</div>        \t\n        </div>\n    </div>\n\n    <div ng-switch-default ng-show=\"field.isVisible\">\n        <label class=\"control-label\">{{field.name}}</label>\n        <div class=\"well well-sm\">\n            {{field.value && field.value || ('FORM.MESSAGE.EMPTY' | translate)}}\n        </div>\n    </div>\n</div>\n"
  },
  {
    "path": "flowable-ui-web/task/workflow/views/templates/form-template.html",
    "content": "<div ng-controller=\"RenderFormController\" id=\"formsection\">\n\n    <div loading=\"model.loading\"></div>\n\n    <div ng-if=\"!model.loading && formData != null && formData != undefined && (disableForm == null || disableForm == undefined || disableForm == false)\"\n         class=\"form-wrapper container-fluid\">\n\n        <div ng-if=\"!outcomesOnly\" >\n            <div ng-form=\"taskForm\">\n                <div ng-repeat=\"field in formData.fields\" id=\"fieldContainer_{{field.id}}\">\n                    <form-element field=\"field\" task-form=\"taskForm\" control-callbacks=\"controlCallbacks\" model=\"model\"></form-element>\n                </div>\n            </div>\n        </div>\n\n        <div ng-if=\"!formData.outcomes || formData.outcomes.length === 0\" class=\"clearfix form-actions\">\n            <div class=\"pull-right\" ng-if=\"(hideButtons == undefined || hideButtons == null || hideButtons == false) && (disableForm == undefined || disableForm == null || disableForm == false)\">\n                <button id=\"form_save_button\" class=\"btn btn-default\" ng-disabled=\"model.completeButtonDisabled || !model.valid || (disableOutcomes != undefined && disableOutcomes != null && disableOutcomes) || model.uploadInProgress\"\n                        ng-click=\"saveForm()\" ng-show=\"!processDefinitionId && !caseDefinitionId\" translate=\"FORM.ACTION.SAVE\"></button>\n                <button id=\"form_complete_button\" class=\"btn btn-default\" ng-disabled=\"model.completeButtonDisabled || !model.valid || (disableOutcomes != undefined && disableOutcomes != null && disableOutcomes) || model.uploadInProgress\"\n                        ng-click=\"completeForm('complete')\">{{getDefaultCompleteButtonText()}}</button>\n            </div>\n        </div>\n\n        <div ng-if=\"formData.outcomes && formData.outcomes.length > 0\" class=\"clearfix form-actions\">\n            <div class=\"pull-right\" ng-if=\"(hideButtons == undefined || hideButtons == null || hideButtons == false) && (disableForm == undefined || disableForm == null || disableForm == false)\">\n                <button id=\"form_save_button\" class=\"btn btn-default\"\n                        ng-disabled=\"!model.valid || model.completeButtonDisabled || model.uploadInProgress\"\n                        ng-click=\"saveForm()\" ng-show=\"!processDefinitionId && !caseDefinitionId\" translate=\"FORM.ACTION.SAVE\"></button>\n                <button id=\"form_complete_button\" class=\"btn btn-default\"\n                        ng-disabled=\"!model.valid || model.completeButtonDisabled || model.uploadInProgress\"\n                        ng-repeat=\"outcome in formData.outcomes\"\n                        ng-click=\"completeForm(outcome)\">{{outcome.name}}</button>\n            </div>\n        </div>\n\n        <div ng-if=\"formData.selectedOutcome && formData.selectedOutcome.length > 0\" class=\"clearfix form-actions\">\n        \t<div class=\"pull-right\">\n                <button id=\"form_complete_button\" class=\"btn btn-default\" ng-disabled=\"true\">{{formData.selectedOutcome}}</button>\n            </div>\n        </div>\n\n    </div>\n\n\n    <div ng-if=\"disableForm != null && disableForm != undefined && disableForm == true\">\n        <div ng-if=\"disableFormText\" class=\"text-center\">\n            <div class=\"help-container fixed\">\n                <div>\n                    <div class=\"help-text\">\n                        <div class=\"description\">\n                            {{disableFormText | translate}}\n                        </div>\n                    </div>\n                </div>\n            </div>\n        </div>\n    </div>\n\n</div>\n"
  }
]